diff --git a/arm-trusted-firmware/.checkpatch.conf b/arm-trusted-firmware/.checkpatch.conf new file mode 100644 index 0000000..baa983d --- /dev/null +++ b/arm-trusted-firmware/.checkpatch.conf @@ -0,0 +1,91 @@ +# +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# Configure how the Linux checkpatch script should be invoked in the context of +# the Trusted Firmware source tree. +# + +# This is not Linux so don't expect a Linux tree! +--no-tree + +# The Linux kernel expects the SPDX license tag in the first line of each file. +# We don't follow this in the Trusted Firmware. +--ignore SPDX_LICENSE_TAG + +# This clarifes the lines indications in the report. +# +# E.g.: +# Without this option, we have the following output: +# #333: FILE: drivers/arm/gic/arm_gic.c:160: +# So we have 2 lines indications (333 and 160), which is confusing. +# We only care about the position in the source file. +# +# With this option, it becomes: +# drivers/arm/gic/arm_gic.c:160: +--showfile + +# Don't show some messages like the list of ignored types or the suggestion to +# use "--fix" or report changes to the maintainers. +--quiet + +# +# Ignore the following message types, as they don't necessarily make sense in +# the context of the Trusted Firmware. +# + +# COMPLEX_MACRO generates false positives. +--ignore COMPLEX_MACRO + +# Commit messages might contain a Gerrit Change-Id. +--ignore GERRIT_CHANGE_ID + +# Do not check the format of commit messages, as Gerrit's merge commits do not +# preserve it. +--ignore GIT_COMMIT_ID + +# FILE_PATH_CHANGES reports this kind of message: +# "added, moved or deleted file(s), does MAINTAINERS need updating?" +# We do not use this MAINTAINERS file process in TF. +--ignore FILE_PATH_CHANGES + +# AVOID_EXTERNS reports this kind of messages: +# "externs should be avoided in .c files" +# We don't follow this convention in TF. +--ignore AVOID_EXTERNS + +# NEW_TYPEDEFS reports this kind of messages: +# "do not add new typedefs" +# We allow adding new typedefs in TF. +--ignore NEW_TYPEDEFS + +# Avoid "Does not appear to be a unified-diff format patch" message +--ignore NOT_UNIFIED_DIFF + +# VOLATILE reports this kind of messages: +# "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt" +# We allow the usage of the volatile keyword in TF. +--ignore VOLATILE + +# BRACES reports this kind of messages: +# braces {} are not necessary for any arm of this statement +--ignore BRACES + +# PREFER_KERNEL_TYPES reports this kind of messages (when using --strict): +# "Prefer kernel type 'u32' over 'uint32_t'" +--ignore PREFER_KERNEL_TYPES + +# USLEEP_RANGE reports this kind of messages (when using --strict): +# "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt" +--ignore USLEEP_RANGE + +# COMPARISON_TO_NULL reports this kind of messages (when using --strict): +# Comparison to NULL could be written "" +--ignore COMPARISON_TO_NULL + +# UNNECESSARY_PARENTHESES reports this kind of messages (when using --strict): +# Unnecessary parentheses around "" +--ignore UNNECESSARY_PARENTHESES diff --git a/arm-trusted-firmware/.commitlintrc.js b/arm-trusted-firmware/.commitlintrc.js new file mode 100644 index 0000000..ed971a3 --- /dev/null +++ b/arm-trusted-firmware/.commitlintrc.js @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* eslint-env es6 */ + +"use strict"; + +const fs = require("fs"); +const yaml = require("js-yaml"); + +const { "trailer-exists": trailerExists } = require("@commitlint/rules").default; + +/* + * The types and scopes accepted by both Commitlint and Commitizen are defined by the changelog + * configuration file - `changelog.yaml` - as they decide which section of the changelog commits + * with a given type and scope are placed in. + */ + +let changelog; + +try { + const contents = fs.readFileSync("changelog.yaml", "utf8"); + + changelog = yaml.load(contents); +} catch (err) { + console.log(err); + + throw err; +} + +function getTypes(sections) { + return sections.map(section => section.type) +} + +function getScopes(subsections) { + return subsections.flatMap(subsection => { + const scope = subsection.scope ? [ subsection.scope ] : []; + const subscopes = getScopes(subsection.subsections || []); + + return scope.concat(subscopes); + }) +}; + +const types = getTypes(changelog.sections).sort(); /* Sort alphabetically */ +const scopes = getScopes(changelog.subsections).sort(); /* Sort alphabetically */ + +module.exports = { + extends: ["@commitlint/config-conventional"], + plugins: [ + { + rules: { + "signed-off-by-exists": trailerExists, + "change-id-exists": trailerExists, + }, + }, + ], + rules: { + "header-max-length": [1, "always", 50], /* Warning */ + "body-max-line-length": [1, "always", 72], /* Warning */ + + "change-id-exists": [1, "always", "Change-Id:"], /* Warning */ + "signed-off-by-exists": [1, "always", "Signed-off-by:"], /* Warning */ + + "type-case": [2, "always", "lower-case" ], /* Error */ + "type-enum": [2, "always", types], /* Error */ + + "scope-case": [2, "always", "lower-case"], /* Error */ + "scope-empty": [2, "never"], /* Error */ + "scope-enum": [1, "always", scopes] /* Warning */ + }, +}; diff --git a/arm-trusted-firmware/.cz.json b/arm-trusted-firmware/.cz.json new file mode 100644 index 0000000..556c39f --- /dev/null +++ b/arm-trusted-firmware/.cz.json @@ -0,0 +1,3 @@ +{ + "path": "@commitlint/cz-commitlint" +} diff --git a/arm-trusted-firmware/.editorconfig b/arm-trusted-firmware/.editorconfig new file mode 100644 index 0000000..12f786d --- /dev/null +++ b/arm-trusted-firmware/.editorconfig @@ -0,0 +1,72 @@ +# +# Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Trusted Firmware-A Coding style spec for editors. + +# References: +# [EC] http://editorconfig.org/ +# [CONT] contributing.rst +# [LCS] Linux Coding Style +# (https://www.kernel.org/doc/html/v4.10/process/coding-style.html) +# [PEP8] Style Guide for Python Code +# (https://www.python.org/dev/peps/pep-0008) + + +root = true + +# set default to match [LCS] .c/.h settings. +# This will also apply to .S, .mk, .sh, Makefile, .dts, etc. +[*] +# Not specified, but fits current ARM-TF sources. +charset = utf-8 + +# Not specified, but implicit for "LINUX coding style". +end_of_line = lf + +# [LCS] Chapter 1: Indentation +# "and thus indentations are also 8 characters" +indent_size = 8 + +# [LCS] Chapter 1: Indentation +# "Outside of comments,...spaces are never used for indentation" +indent_style = tab + +# Not specified by [LCS], but sensible +insert_final_newline = true + +# [LCS] Chapter 2: Breaking long lines and strings +# "The limit on the length of lines is 100 columns" +# This is a "soft" requirement for Arm-TF, and should not be the sole +# reason for changes. +max_line_length = 100 + +# [LCS] Chapter 1: Indentation +# "Tabs are 8 characters" +tab_width = 8 + +# [LCS] Chapter 1: Indentation +# "Get a decent editor and don't leave whitespace at the end of lines." +# [LCS] Chapter 3.1: Spaces +# "Do not leave trailing whitespace at the ends of lines." +trim_trailing_whitespace = true + + +# Adjustment for ReStructuredText (RST) documentation +[*.{rst}] +indent_size = 4 +indent_style = space + + +# Adjustment for python which prefers a different style +[*.py] +# [PEP8] Indentation +# "Use 4 spaces per indentation level." +indent_size = 4 +indent_style = space + +# [PEP8] Maximum Line Length +# "Limit all lines to a maximum of 79 characters." +max_line_length = 79 diff --git a/arm-trusted-firmware/.gitreview b/arm-trusted-firmware/.gitreview new file mode 100644 index 0000000..afdb74d --- /dev/null +++ b/arm-trusted-firmware/.gitreview @@ -0,0 +1,5 @@ +[gerrit] +host=review.trustedfirmware.org +port=29418 +project=TF-A/trusted-firmware-a +defaultbranch=integration diff --git a/arm-trusted-firmware/.husky/commit-msg b/arm-trusted-firmware/.husky/commit-msg new file mode 100755 index 0000000..c1c9600 --- /dev/null +++ b/arm-trusted-firmware/.husky/commit-msg @@ -0,0 +1,7 @@ +#!/bin/sh + +# shellcheck source=./_/husky.sh +. "$(dirname "$0")/_/husky.sh" + +"$(dirname "$0")/commit-msg.gerrit" "$@" +"$(dirname "$0")/commit-msg.commitlint" "$@" diff --git a/arm-trusted-firmware/.husky/commit-msg.commitlint b/arm-trusted-firmware/.husky/commit-msg.commitlint new file mode 100755 index 0000000..ca25ce1 --- /dev/null +++ b/arm-trusted-firmware/.husky/commit-msg.commitlint @@ -0,0 +1,3 @@ +#!/bin/sh + +npx --no-install commitlint --edit "$1" diff --git a/arm-trusted-firmware/.husky/commit-msg.gerrit b/arm-trusted-firmware/.husky/commit-msg.gerrit new file mode 100755 index 0000000..b8ce477 --- /dev/null +++ b/arm-trusted-firmware/.husky/commit-msg.gerrit @@ -0,0 +1,194 @@ +#!/bin/sh +# From Gerrit Code Review 2.14.20 +# +# Part of Gerrit Code Review (https://www.gerritcodereview.com/) +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +unset GREP_OPTIONS + +CHANGE_ID_AFTER="Bug|Depends-On|Issue|Test|Feature|Fixes|Fixed" +MSG="$1" + +# Check for, and add if missing, a unique Change-Id +# +add_ChangeId() { + clean_message=`sed -e ' + /^diff --git .*/{ + s/// + q + } + /^Signed-off-by:/d + /^#/d + ' "$MSG" | git stripspace` + if test -z "$clean_message" + then + return + fi + + # Do not add Change-Id to temp commits + if echo "$clean_message" | head -1 | grep -q '^\(fixup\|squash\)!' + then + return + fi + + if test "false" = "`git config --bool --get gerrit.createChangeId`" + then + return + fi + + # Does Change-Id: already exist? if so, exit (no change). + if grep -i '^Change-Id:' "$MSG" >/dev/null + then + return + fi + + id=`_gen_ChangeId` + T="$MSG.tmp.$$" + AWK=awk + if [ -x /usr/xpg4/bin/awk ]; then + # Solaris AWK is just too broken + AWK=/usr/xpg4/bin/awk + fi + + # Get core.commentChar from git config or use default symbol + commentChar=`git config --get core.commentChar` + commentChar=${commentChar:-#} + + # How this works: + # - parse the commit message as (textLine+ blankLine*)* + # - assume textLine+ to be a footer until proven otherwise + # - exception: the first block is not footer (as it is the title) + # - read textLine+ into a variable + # - then count blankLines + # - once the next textLine appears, print textLine+ blankLine* as these + # aren't footer + # - in END, the last textLine+ block is available for footer parsing + $AWK ' + BEGIN { + if (match(ENVIRON["OS"], "Windows")) { + RS="\r?\n" # Required on recent Cygwin + } + # while we start with the assumption that textLine+ + # is a footer, the first block is not. + isFooter = 0 + footerComment = 0 + blankLines = 0 + } + + # Skip lines starting with commentChar without any spaces before it. + /^'"$commentChar"'/ { next } + + # Skip the line starting with the diff command and everything after it, + # up to the end of the file, assuming it is only patch data. + # If more than one line before the diff was empty, strip all but one. + /^diff --git / { + blankLines = 0 + while (getline) { } + next + } + + # Count blank lines outside footer comments + /^$/ && (footerComment == 0) { + blankLines++ + next + } + + # Catch footer comment + /^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) { + footerComment = 1 + } + + /]$/ && (footerComment == 1) { + footerComment = 2 + } + + # We have a non-blank line after blank lines. Handle this. + (blankLines > 0) { + print lines + for (i = 0; i < blankLines; i++) { + print "" + } + + lines = "" + blankLines = 0 + isFooter = 1 + footerComment = 0 + } + + # Detect that the current block is not the footer + (footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) { + isFooter = 0 + } + + { + # We need this information about the current last comment line + if (footerComment == 2) { + footerComment = 0 + } + if (lines != "") { + lines = lines "\n"; + } + lines = lines $0 + } + + # Footer handling: + # If the last block is considered a footer, splice in the Change-Id at the + # right place. + # Look for the right place to inject Change-Id by considering + # CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first, + # then Change-Id, then everything else (eg. Signed-off-by:). + # + # Otherwise just print the last block, a new line and the Change-Id as a + # block of its own. + END { + unprinted = 1 + if (isFooter == 0) { + print lines "\n" + lines = "" + } + changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):" + numlines = split(lines, footer, "\n") + for (line = 1; line <= numlines; line++) { + if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) { + unprinted = 0 + print "Change-Id: I'"$id"'" + } + print footer[line] + } + if (unprinted) { + print "Change-Id: I'"$id"'" + } + }' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T" +} +_gen_ChangeIdInput() { + echo "tree `git write-tree`" + if parent=`git rev-parse "HEAD^0" 2>/dev/null` + then + echo "parent $parent" + fi + echo "author `git var GIT_AUTHOR_IDENT`" + echo "committer `git var GIT_COMMITTER_IDENT`" + echo + printf '%s' "$clean_message" +} +_gen_ChangeId() { + _gen_ChangeIdInput | + git hash-object -t commit --stdin +} + + +add_ChangeId diff --git a/arm-trusted-firmware/.husky/prepare-commit-msg b/arm-trusted-firmware/.husky/prepare-commit-msg new file mode 100755 index 0000000..593dfa8 --- /dev/null +++ b/arm-trusted-firmware/.husky/prepare-commit-msg @@ -0,0 +1,6 @@ +#!/bin/sh + +# shellcheck source=./_/husky.sh +. "$(dirname "$0")/_/husky.sh" + +"$(dirname "$0")/prepare-commit-msg.cz" "$@" diff --git a/arm-trusted-firmware/.husky/prepare-commit-msg.cz b/arm-trusted-firmware/.husky/prepare-commit-msg.cz new file mode 100755 index 0000000..724527d --- /dev/null +++ b/arm-trusted-firmware/.husky/prepare-commit-msg.cz @@ -0,0 +1,28 @@ +#!/bin/bash + +file="$1" +type="$2" + +if [ -z "$type" ]; then # only run on new commits + # + # Save any commit message trailers generated by Git. + # + + trailers=$(git interpret-trailers --parse "$file") + + # + # Execute the Commitizen hook. + # + + (exec < "/dev/tty" && npx --no-install git-cz --hook) || true + + # + # Restore any trailers that Commitizen might have overwritten. + # + + printf "\n" >> "$file" + + while IFS= read -r trailer; do + git interpret-trailers --in-place --trailer "$trailer" "$file" + done <<< "$trailers" +fi diff --git a/arm-trusted-firmware/.versionrc.js b/arm-trusted-firmware/.versionrc.js new file mode 100644 index 0000000..f699a07 --- /dev/null +++ b/arm-trusted-firmware/.versionrc.js @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* eslint-env es6 */ + +"use strict"; + +const fs = require("fs"); +const yaml = require("js-yaml"); + +/* + * The types and scopes accepted by both Commitlint and Commitizen are defined by the changelog + * configuration file - `changelog.yaml` - as they decide which section of the changelog commits + * with a given type and scope are placed in. + */ + +let changelog; + +try { + const contents = fs.readFileSync("changelog.yaml", "utf8"); + + changelog = yaml.load(contents); +} catch (err) { + console.log(err); + + throw err; +} + +/* + * The next couple of functions are just used to transform the changelog YAML configuration + * structure into one accepted by the Conventional Changelog adapter (conventional-changelog-tf-a). + */ + +function getTypes(sections) { + return sections.map(section => { + return { + "type": section.type, + "section": section.hidden ? undefined : section.title, + "hidden": section.hidden || false, + }; + }) +} + +function getSections(subsections) { + return subsections.flatMap(subsection => { + const scope = subsection.scope ? [ subsection.scope ] : []; + + return { + "title": subsection.title, + "sections": getSections(subsection.subsections || []), + "scopes": scope.concat(subsection.deprecated || []), + }; + }) +}; + +const types = getTypes(changelog.sections); +const sections = getSections(changelog.subsections); + +module.exports = { + "header": "# Change Log & Release Notes\n\nThis document contains a summary of the new features, changes, fixes and known\nissues in each release of Trusted Firmware-A.\n", + "preset": { + "name": "tf-a", + "commitUrlFormat": "https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/{{hash}}", + "compareUrlFormat": "https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/{{previousTag}}..refs/tags/{{currentTag}}", + "userUrlFormat": "https://github.com/{{user}}", + + "types": types, + "sections": sections, + }, + "infile": "docs/change-log.md", + "skip": { + "commit": true, + "tag": true + }, + "bumpFiles": [ + { + "filename": "package.json", + "type": "json" + }, + { + "filename": "package-lock.json", + "type": "json" + }, + { + "filename": "tools/conventional-changelog-tf-a/package.json", + "type": "json" + }, + { + "filename": "Makefile", + "updater": { + "readVersion": function (contents) { + const major = contents.match(/^VERSION_MAJOR\s*:=\s*(\d+?)$/m)[1]; + const minor = contents.match(/^VERSION_MINOR\s*:=\s*(\d+?)$/m)[1]; + + return `${major}.${minor}.0`; + }, + + "writeVersion": function (contents, version) { + const major = version.split(".")[0]; + const minor = version.split(".")[1]; + + contents = contents.replace(/^(VERSION_MAJOR\s*:=\s*)(\d+?)$/m, `$1${major}`); + contents = contents.replace(/^(VERSION_MINOR\s*:=\s*)(\d+?)$/m, `$1${minor}`); + + return contents; + } + } + } + ] +}; diff --git a/arm-trusted-firmware/Makefile b/arm-trusted-firmware/Makefile new file mode 100644 index 0000000..95c9075 --- /dev/null +++ b/arm-trusted-firmware/Makefile @@ -0,0 +1,1536 @@ +# +# Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# Trusted Firmware Version +# +VERSION_MAJOR := 2 +VERSION_MINOR := 6 + +# 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 + +# FEAT_RME +ifeq (${ENABLE_RME},1) +# RME doesn't support PIE +ifneq (${ENABLE_PIE},0) + $(error ENABLE_RME does not support PIE) +endif +# RME requires AARCH64 +ifneq (${ARCH},aarch64) + $(error ENABLE_RME requires AArch64) +endif +# RME requires el2 context to be saved for now. +CTX_INCLUDE_EL2_REGS := 1 +CTX_INCLUDE_AARCH32_REGS := 0 +ARM_ARCH_MAJOR := 8 +ARM_ARCH_MINOR := 6 +endif + +# USE_SPINLOCK_CAS requires AArch64 build +ifeq (${USE_SPINLOCK_CAS},1) +ifneq (${ARCH},aarch64) + $(error USE_SPINLOCK_CAS requires AArch64) +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 + +# Determine and enable FEAT_FGT to access HDFGRTR_EL2 register for v8.6 and higher versions. +ifeq "8.6" "$(word 1, $(sort 8.6 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +ENABLE_FEAT_FGT = 1 +endif + +# Determine and enable FEAT_ECV to access CNTPOFF_EL2 register for v8.6 and higher versions. +ifeq "8.6" "$(word 1, $(sort 8.6 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +ENABLE_FEAT_ECV = 1 +endif + +ifeq "8.4" "$(word 1, $(sort 8.4 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +ENABLE_FEAT_DIT = 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) + # 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 + + ifeq ($(TS_SP_FW_CONFIG),1) + DTC_CPPFLAGS += -DTS_SP_FW_CONFIG + endif + + ifneq ($(ARM_BL2_SP_LIST_DTS),) + DTC_CPPFLAGS += -DARM_BL2_SP_LIST_DTS=$(ARM_BL2_SP_LIST_DTS) + endif + + ifneq ($(SP_LAYOUT_FILE),) + BL2_ENABLE_SP_LOAD := 1 + 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 rmmd Makefile if RME is enabled +################################################################################ + +ifneq (${ENABLE_RME},0) +ifneq (${ARCH},aarch64) + $(error ENABLE_RME requires AArch64) +endif +include services/std_svc/rmmd/rmmd.mk +$(warning "RME is an experimental feature") +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 + +ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT}),) + CRYPTO_SUPPORT := 1 +else + CRYPTO_SUPPORT := 0 +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 only supported when SDEI_SUPPORT is enabled") +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) + endif +endif + +ifeq ($(CTX_INCLUDE_MTE_REGS),1) + ifneq (${ARCH},aarch64) + $(error CTX_INCLUDE_MTE_REGS requires AArch64) + endif +endif + +ifeq ($(PSA_FWU_SUPPORT),1) + $(info PSA_FWU_SUPPORT is an experimental feature) +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) + endif +endif + +# SME/SVE only supported on AArch64 +ifeq (${ARCH},aarch32) + ifeq (${ENABLE_SME_FOR_NS},1) + $(error "ENABLE_SME_FOR_NS cannot be used with ARCH=aarch32") + endif + ifeq (${ENABLE_SVE_FOR_NS},1) + # Warning instead of error due to CI dependency on this + $(error "ENABLE_SVE_FOR_NS cannot be used with ARCH=aarch32") + endif +endif + +# Ensure ENABLE_RME is not used with SME +ifeq (${ENABLE_RME},1) + ifeq (${ENABLE_SME_FOR_NS},1) + $(error "ENABLE_SME_FOR_NS cannot be used with ENABLE_RME") + endif +endif + +# Secure SME/SVE requires the non-secure component as well +ifeq (${ENABLE_SME_FOR_SWD},1) + ifeq (${ENABLE_SME_FOR_NS},0) + $(error "ENABLE_SME_FOR_SWD requires ENABLE_SME_FOR_NS") + endif +endif +ifeq (${ENABLE_SVE_FOR_SWD},1) + ifeq (${ENABLE_SVE_FOR_NS},0) + $(error "ENABLE_SVE_FOR_SWD requires ENABLE_SVE_FOR_NS") + endif +endif + +# SVE and SME cannot be used with CTX_INCLUDE_FPREGS since secure manager does +# its own context management including FPU registers. +ifeq (${CTX_INCLUDE_FPREGS},1) + ifeq (${ENABLE_SME_FOR_NS},1) + $(error "ENABLE_SME_FOR_NS cannot be used with CTX_INCLUDE_FPREGS") + endif + ifeq (${ENABLE_SVE_FOR_NS},1) + # Warning instead of error due to CI dependency on this + $(warning "ENABLE_SVE_FOR_NS cannot be used with CTX_INCLUDE_FPREGS") + $(warning "Forced ENABLE_SVE_FOR_NS=0") + override ENABLE_SVE_FOR_NS := 0 + endif +endif + +################################################################################ +# Process platform overrideable behaviour +################################################################################ + +ifdef BL1_SOURCES +NEED_BL1 := yes +endif + +ifdef BL2_SOURCES + NEED_BL2 := yes + + # 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 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 + +ifdef BL2U_SOURCES +NEED_BL2U := yes +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 + +ifdef FDT_SOURCES +NEED_FDT := yes +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 + +# Defination of SIMICS flag +SIMICS_BUILD ?= 0 + +################################################################################ +# Include BL specific makefiles +################################################################################ + +ifeq (${NEED_BL1},yes) +include bl1/bl1.mk +endif + +ifeq (${NEED_BL2},yes) +include bl2/bl2.mk +endif + +ifeq (${NEED_BL2U},yes) +include bl2u/bl2u.mk +endif + +ifeq (${NEED_BL31},yes) +include bl31/bl31.mk +endif + +################################################################################ +# Build options checks +################################################################################ + +$(eval $(call assert_booleans,\ + $(sort \ + ALLOW_RO_XLAT_TABLES \ + BL2_ENABLE_SP_LOAD \ + 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 \ + ENABLE_AMU_AUXILIARY_COUNTERS \ + ENABLE_AMU_FCONF \ + AMU_RESTRICT_COUNTERS \ + ENABLE_ASSERTIONS \ + ENABLE_MPAM_FOR_LOWER_ELS \ + ENABLE_PIE \ + ENABLE_PMF \ + ENABLE_PSCI_STAT \ + ENABLE_RME \ + ENABLE_RUNTIME_INSTRUMENTATION \ + ENABLE_SME_FOR_NS \ + ENABLE_SME_FOR_SWD \ + ENABLE_SPE_FOR_LOWER_ELS \ + ENABLE_SVE_FOR_NS \ + ENABLE_SVE_FOR_SWD \ + 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_BL2_NOLOAD_REGION \ + SEPARATE_NOBITS_REGION \ + SPIN_ON_BL1_EXIT \ + SPM_MM \ + SPMD_SPM_AT_SEL2 \ + TRUSTED_BOARD_BOOT \ + CRYPTO_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 \ + 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 \ + ENABLE_FEAT_DIT \ + PSA_FWU_SUPPORT \ + ENABLE_TRBE_FOR_NS \ + ENABLE_SYS_REG_TRACE_FOR_NS \ + ENABLE_TRF_FOR_NS \ + ENABLE_FEAT_HCX \ + ENABLE_MPMM \ + ENABLE_MPMM_FCONF \ + ENABLE_FEAT_FGT \ + ENABLE_FEAT_AMUv1 \ + ENABLE_FEAT_ECV \ + SIMICS_BUILD \ +))) + +$(eval $(call assert_numerics,\ + $(sort \ + ARM_ARCH_MAJOR \ + ARM_ARCH_MINOR \ + BRANCH_PROTECTION \ + FW_ENC_STATUS \ + NR_OF_FW_BANKS \ + NR_OF_IMAGES_IN_FW_BANK \ +))) + +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 \ + BL2_ENABLE_SP_LOAD \ + 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 \ + ENABLE_AMU_AUXILIARY_COUNTERS \ + ENABLE_AMU_FCONF \ + AMU_RESTRICT_COUNTERS \ + ENABLE_ASSERTIONS \ + ENABLE_BTI \ + ENABLE_MPAM_FOR_LOWER_ELS \ + ENABLE_PAUTH \ + ENABLE_PIE \ + ENABLE_PMF \ + ENABLE_PSCI_STAT \ + ENABLE_RME \ + ENABLE_RUNTIME_INSTRUMENTATION \ + ENABLE_SME_FOR_NS \ + ENABLE_SME_FOR_SWD \ + ENABLE_SPE_FOR_LOWER_ELS \ + ENABLE_SVE_FOR_NS \ + ENABLE_SVE_FOR_SWD \ + 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_BL2_NOLOAD_REGION \ + SEPARATE_NOBITS_REGION \ + RECLAIM_INIT_CODE \ + SPD_${SPD} \ + SPIN_ON_BL1_EXIT \ + SPM_MM \ + SPMD_SPM_AT_SEL2 \ + TRUSTED_BOARD_BOOT \ + CRYPTO_SUPPORT \ + 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 \ + ENABLE_FEAT_DIT \ + NR_OF_FW_BANKS \ + NR_OF_IMAGES_IN_FW_BANK \ + PSA_FWU_SUPPORT \ + ENABLE_TRBE_FOR_NS \ + ENABLE_SYS_REG_TRACE_FOR_NS \ + ENABLE_TRF_FOR_NS \ + ENABLE_FEAT_HCX \ + ENABLE_MPMM \ + ENABLE_MPMM_FCONF \ + ENABLE_FEAT_FGT \ + ENABLE_FEAT_AMUv1 \ + ENABLE_FEAT_ECV \ + SIMICS_BUILD \ +))) + +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 + -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) +BL1_SOURCES := $(sort ${BL1_SOURCES}) + +$(eval $(call MAKE_BL,bl1)) +endif + +ifeq (${NEED_BL2},yes) +ifeq (${BL2_AT_EL3}, 0) +FIP_BL2_ARGS := tb-fw +endif + +BL2_SOURCES := $(sort ${BL2_SOURCES}) + +$(if ${BL2}, $(eval $(call TOOL_ADD_IMG,bl2,--${FIP_BL2_ARGS})),\ + $(eval $(call MAKE_BL,bl2,${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,bl31,soc-fw,,$(ENCRYPT_BL31)))) +else +$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw)),\ + $(eval $(call MAKE_BL,bl31,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,bl32,tos-fw,,$(ENCRYPT_BL32))),\ + $(eval $(call TOOL_ADD_IMG,bl32,--tos-fw,,$(ENCRYPT_BL32)))) +else +$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,bl32,tos-fw)),\ + $(eval $(call TOOL_ADD_IMG,bl32,--tos-fw))) +endif +endif + +# If RMM image is needed but RMM is not defined, Test Realm Payload (TRP) +# needs to be built from RMM_SOURCES. +ifeq (${NEED_RMM},yes) +# Sort RMM source files to remove duplicates +RMM_SOURCES := $(sort ${RMM_SOURCES}) +BUILD_RMM := $(if $(RMM),,$(if $(RMM_SOURCES),1)) + +$(if ${BUILD_RMM}, $(eval $(call MAKE_BL,rmm,rmm-fw)),\ + $(eval $(call TOOL_ADD_IMG,rmm,--rmm-fw))) +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,bl2u,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} realclean + ${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 --no-merges $$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} OPENSSL_DIR=${OPENSSL_DIR} --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/arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c b/arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c new file mode 100644 index 0000000..ce04aaa --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../bl1_private.h" + +/******************************************************************************* + * TODO: Function that does the first bit of architectural setup. + ******************************************************************************/ +void bl1_arch_setup(void) +{ + +} diff --git a/arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c b/arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c new file mode 100644 index 0000000..85d35a7 --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c @@ -0,0 +1,172 @@ +/* + * 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 "../bl1_private.h" + +/* + * Following arrays will be used for context management. + * There are 2 instances, for the Secure and Non-Secure contexts. + */ +static cpu_context_t bl1_cpu_context[2]; +static smc_ctx_t bl1_smc_context[2]; + +/* Following contains the next cpu context pointer. */ +static void *bl1_next_cpu_context_ptr; + +/* Following contains the next smc context pointer. */ +static void *bl1_next_smc_context_ptr; + +/* Following functions are used for SMC context handling */ +void *smc_get_ctx(unsigned int security_state) +{ + assert(sec_state_is_valid(security_state)); + return &bl1_smc_context[security_state]; +} + +void smc_set_next_ctx(unsigned int security_state) +{ + assert(sec_state_is_valid(security_state)); + bl1_next_smc_context_ptr = &bl1_smc_context[security_state]; +} + +void *smc_get_next_ctx(void) +{ + return bl1_next_smc_context_ptr; +} + +/* Following functions are used for CPU context handling */ +void *cm_get_context(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + return &bl1_cpu_context[security_state]; +} + +void cm_set_next_context(void *context) +{ + assert(context != NULL); + bl1_next_cpu_context_ptr = context; +} + +void *cm_get_next_context(void) +{ + return bl1_next_cpu_context_ptr; +} + +/******************************************************************************* + * Following function copies GP regs r0-r4, lr and spsr, + * from the CPU context to the SMC context structures. + ******************************************************************************/ +static void copy_cpu_ctx_to_smc_ctx(const regs_t *cpu_reg_ctx, + smc_ctx_t *next_smc_ctx) +{ + next_smc_ctx->r0 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R0); + next_smc_ctx->r1 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R1); + next_smc_ctx->r2 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R2); + next_smc_ctx->r3 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R3); + next_smc_ctx->lr_mon = read_ctx_reg(cpu_reg_ctx, CTX_LR); + next_smc_ctx->spsr_mon = read_ctx_reg(cpu_reg_ctx, CTX_SPSR); + next_smc_ctx->scr = read_ctx_reg(cpu_reg_ctx, CTX_SCR); +} + +/******************************************************************************* + * Following function flushes the SMC & CPU context pointer and its data. + ******************************************************************************/ +static void flush_smc_and_cpu_ctx(void) +{ + flush_dcache_range((uintptr_t)&bl1_next_smc_context_ptr, + sizeof(bl1_next_smc_context_ptr)); + flush_dcache_range((uintptr_t)bl1_next_smc_context_ptr, + sizeof(smc_ctx_t)); + + flush_dcache_range((uintptr_t)&bl1_next_cpu_context_ptr, + sizeof(bl1_next_cpu_context_ptr)); + flush_dcache_range((uintptr_t)bl1_next_cpu_context_ptr, + sizeof(cpu_context_t)); +} + +/******************************************************************************* + * This function prepares the context for Secure/Normal world images. + * Normal world images are transitioned to HYP(if supported) else SVC. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + unsigned int security_state, mode = MODE32_svc; + image_desc_t *desc; + entry_point_info_t *next_bl_ep; + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + assert(desc != NULL); + + /* Get the entry point info. */ + next_bl_ep = &desc->ep_info; + + /* Get the image security state. */ + security_state = GET_SECURITY_STATE(next_bl_ep->h.attr); + + /* Prepare the SPSR for the next BL image. */ + if ((security_state != SECURE) && (GET_VIRT_EXT(read_id_pfr1()) != 0U)) { + mode = MODE32_hyp; + } + + next_bl_ep->spsr = SPSR_MODE32(mode, SPSR_T_ARM, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + + /* Allow platform to make change */ + bl1_plat_set_ep_info(image_id, next_bl_ep); + + /* Prepare the cpu context for the next BL image. */ + cm_init_my_context(next_bl_ep); + cm_prepare_el3_exit(security_state); + cm_set_next_context(cm_get_context(security_state)); + + /* Prepare the smc context for the next BL image. */ + smc_set_next_ctx(security_state); + copy_cpu_ctx_to_smc_ctx(get_regs_ctx(cm_get_next_context()), + smc_get_next_ctx()); + + /* + * If the next image is non-secure, then we need to program the banked + * non secure sctlr. This is not required when the next image is secure + * because in AArch32, we expect the secure world to have the same + * SCTLR settings. + */ + if (security_state == NON_SECURE) { + cpu_context_t *ctx = cm_get_context(security_state); + u_register_t ns_sctlr; + + /* Temporarily set the NS bit to access NS SCTLR */ + write_scr(read_scr() | SCR_NS_BIT); + isb(); + + ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR); + write_sctlr(ns_sctlr); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); + } + + /* + * Flush the SMC & CPU context and the (next)pointers, + * to access them after caches are disabled. + */ + flush_smc_and_cpu_ctx(); + + /* Indicate that image is in execution state. */ + desc->state = IMAGE_STATE_EXECUTED; + + print_entry_point_info(next_bl_ep); +} diff --git a/arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S b/arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S new file mode 100644 index 0000000..94dfd37 --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + + .globl bl1_vector_table + .globl bl1_entrypoint + + /* ----------------------------------------------------- + * Setup the vector table to support SVC & MON mode. + * ----------------------------------------------------- + */ +vector_base bl1_vector_table + b bl1_entrypoint + b report_exception /* Undef */ + b bl1_aarch32_smc_handler /* SMC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ + + /* ----------------------------------------------------- + * bl1_entrypoint() is the entry point into the trusted + * firmware code when a cpu is released from warm or + * cold reset. + * ----------------------------------------------------- + */ + +func bl1_entrypoint +/* --------------------------------------------------------------------- +* If the reset address is programmable then bl1_entrypoint() is +* executed only on the cold boot path. Therefore, we can skip the warm +* boot mailbox mechanism. +* --------------------------------------------------------------------- +*/ + 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=bl1_vector_table \ + _pie_fixup_size=0 + + /* ----------------------------------------------------- + * Perform BL1 setup + * ----------------------------------------------------- + */ + bl bl1_setup + + /* ----------------------------------------------------- + * Jump to main function. + * ----------------------------------------------------- + */ + bl bl1_main + + /* ----------------------------------------------------- + * Jump to next image. + * ----------------------------------------------------- + */ + + /* + * Get the smc_context for next BL image, + * program the gp/system registers and save it in `r4`. + */ + bl smc_get_next_ctx + mov r4, r0 + + /* Only turn-off MMU if going to secure world */ + ldr r5, [r4, #SMC_CTX_SCR] + tst r5, #SCR_NS_BIT + bne skip_mmu_off + + /* + * MMU needs to be disabled because both BL1 and BL2/BL2U execute + * in PL1, and therefore share the same address space. + * BL2/BL2U will initialize the address space according to its + * own requirement. + */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + +skip_mmu_off: + /* Restore smc_context from `r4` and exit secure monitor mode. */ + mov r0, r4 + monitor_exit +endfunc bl1_entrypoint diff --git a/arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S b/arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S new file mode 100644 index 0000000..493d2ca --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + .globl bl1_aarch32_smc_handler + + +func bl1_aarch32_smc_handler + /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ + str lr, [sp, #SMC_CTX_LR_MON] + + /* ------------------------------------------------ + * SMC in BL1 is handled assuming that the MMU is + * turned off by BL2. + * ------------------------------------------------ + */ + + /* ---------------------------------------------- + * Detect if this is a RUN_IMAGE or other SMC. + * ---------------------------------------------- + */ + mov lr, #BL1_SMC_RUN_IMAGE + cmp lr, r0 + bne smc_handler + + /* ------------------------------------------------ + * Make sure only Secure world reaches here. + * ------------------------------------------------ + */ + ldcopr r8, SCR + tst r8, #SCR_NS_BIT + blne report_exception + + /* --------------------------------------------------------------------- + * Pass control to next secure image. + * Here it expects r1 to contain the address of a entry_point_info_t + * structure describing the BL entrypoint. + * --------------------------------------------------------------------- + */ + mov r8, r1 + mov r0, r1 + bl bl1_print_next_bl_ep_info + +#if SPIN_ON_BL1_EXIT + bl print_debug_loop_message +debug_loop: + b debug_loop +#endif + + mov r0, r8 + bl bl1_plat_prepare_exit + + stcopr r0, TLBIALL + dsb sy + isb + + /* + * Extract PC and SPSR based on struct `entry_point_info_t` + * and load it in LR and SPSR registers respectively. + */ + ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET] + ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] + msr spsr_xc, r1 + + /* Some BL32 stages expect lr_svc to provide the BL33 entry address */ + cps #MODE32_svc + ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET] + cps #MODE32_mon + + add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET + ldm r8, {r0, r1, r2, r3} + exception_return +endfunc bl1_aarch32_smc_handler + + /* ----------------------------------------------------- + * Save Secure/Normal world context and jump to + * BL1 SMC handler. + * ----------------------------------------------------- + */ +func smc_handler + /* ----------------------------------------------------- + * Save the GP registers. + * ----------------------------------------------------- + */ + smccc_save_gp_mode_regs + + /* + * `sp` still points to `smc_ctx_t`. Save it to a register + * and restore the C runtime stack pointer to `sp`. + */ + mov r6, sp + ldr sp, [r6, #SMC_CTX_SP_MON] + + ldr r0, [r6, #SMC_CTX_SCR] + and r7, r0, #SCR_NS_BIT /* flags */ + + /* Switch to Secure Mode */ + bic r0, #SCR_NS_BIT + stcopr r0, SCR + isb + + /* If caller is from Secure world then turn on the MMU */ + tst r7, #SCR_NS_BIT + bne skip_mmu_on + + /* Turn on the MMU */ + mov r0, #DISABLE_DCACHE + bl enable_mmu_svc_mon + + /* Enable the data cache. */ + ldcopr r9, SCTLR + orr r9, r9, #SCTLR_C_BIT + stcopr r9, SCTLR + isb + +skip_mmu_on: + /* Prepare arguments for BL1 SMC wrapper. */ + ldr r0, [r6, #SMC_CTX_GPREG_R0] /* smc_fid */ + mov r1, #0 /* cookie */ + mov r2, r6 /* handle */ + mov r3, r7 /* flags */ + bl bl1_smc_wrapper + + /* Get the smc_context for next BL image */ + bl smc_get_next_ctx + mov r4, r0 + + /* Only turn-off MMU if going to secure world */ + ldr r5, [r4, #SMC_CTX_SCR] + tst r5, #SCR_NS_BIT + bne skip_mmu_off + + /* Disable the MMU */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + +skip_mmu_off: + /* ----------------------------------------------------- + * Do the transition to next BL image. + * ----------------------------------------------------- + */ + mov r0, r4 + monitor_exit +endfunc smc_handler diff --git a/arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c b/arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c new file mode 100644 index 0000000..0a1cb30 --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "../bl1_private.h" + +/******************************************************************************* + * Function that does the first bit of architectural setup that affects + * execution in the non-secure address space. + ******************************************************************************/ +void bl1_arch_setup(void) +{ + /* Set the next EL to be AArch64 */ + write_scr_el3(read_scr_el3() | SCR_RW_BIT); +} + +/******************************************************************************* + * Set the Secure EL1 required architectural state + ******************************************************************************/ +void bl1_arch_next_el_setup(void) +{ + u_register_t next_sctlr; + + /* Use the same endianness than the current BL */ + next_sctlr = (read_sctlr_el3() & SCTLR_EE_BIT); + + /* Set SCTLR Secure EL1 */ + next_sctlr |= SCTLR_EL1_RES1; + + write_sctlr_el1(next_sctlr); +} diff --git a/arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c b/arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c new file mode 100644 index 0000000..b9a7e5b --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "../bl1_private.h" + +/* Following contains the cpu context pointers. */ +static void *bl1_cpu_context_ptr[2]; +entry_point_info_t *bl2_ep_info; + + +void *cm_get_context(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + return bl1_cpu_context_ptr[security_state]; +} + +void cm_set_context(void *context, uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + bl1_cpu_context_ptr[security_state] = context; +} + +#if ENABLE_RME +/******************************************************************************* + * This function prepares the entry point information to run BL2 in Root world, + * i.e. EL3, for the case when FEAT_RME is enabled. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + image_desc_t *bl2_desc; + + assert(image_id == BL2_IMAGE_ID); + + /* Get the image descriptor. */ + bl2_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(bl2_desc != NULL); + + /* Get the entry point info. */ + bl2_ep_info = &bl2_desc->ep_info; + + bl2_ep_info->spsr = (uint32_t)SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + + /* + * Flush cache since bl2_ep_info is accessed after MMU is disabled + * before jumping to BL2. + */ + flush_dcache_range((uintptr_t)bl2_ep_info, sizeof(entry_point_info_t)); + + /* Indicate that image is in execution state. */ + bl2_desc->state = IMAGE_STATE_EXECUTED; + + /* Print debug info and flush the console before running BL2. */ + print_entry_point_info(bl2_ep_info); +} +#else +/******************************************************************************* + * This function prepares the context for Secure/Normal world images. + * Normal world images are transitioned to EL2(if supported) else EL1. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + + /* + * Following array will be used for context management. + * There are 2 instances, for the Secure and Non-Secure contexts. + */ + static cpu_context_t bl1_cpu_context[2]; + + unsigned int security_state, mode = MODE_EL1; + image_desc_t *desc; + entry_point_info_t *next_bl_ep; + +#if CTX_INCLUDE_AARCH32_REGS + /* + * Ensure that the build flag to save AArch32 system registers in CPU + * context is not set for AArch64-only platforms. + */ + if (el_implemented(1) == EL_IMPL_A64ONLY) { + ERROR("EL1 supports AArch64-only. Please set build flag " + "CTX_INCLUDE_AARCH32_REGS = 0\n"); + panic(); + } +#endif + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + assert(desc != NULL); + + /* Get the entry point info. */ + next_bl_ep = &desc->ep_info; + + /* Get the image security state. */ + security_state = GET_SECURITY_STATE(next_bl_ep->h.attr); + + /* Setup the Secure/Non-Secure context if not done already. */ + if (cm_get_context(security_state) == NULL) + cm_set_context(&bl1_cpu_context[security_state], security_state); + + /* Prepare the SPSR for the next BL image. */ + if ((security_state != SECURE) && (el_implemented(2) != EL_IMPL_NONE)) { + mode = MODE_EL2; + } + + next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode, + (uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + + /* Allow platform to make change */ + bl1_plat_set_ep_info(image_id, next_bl_ep); + + /* Prepare the context for the next BL image. */ + cm_init_my_context(next_bl_ep); + cm_prepare_el3_exit(security_state); + + /* Indicate that image is in execution state. */ + desc->state = IMAGE_STATE_EXECUTED; + + print_entry_point_info(next_bl_ep); +} +#endif /* ENABLE_RME */ diff --git a/arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S b/arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S new file mode 100644 index 0000000..f61c060 --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl1_entrypoint + .globl bl1_run_bl2_in_root + + + /* ----------------------------------------------------- + * bl1_entrypoint() is the entry point into the trusted + * firmware code when a cpu is released from warm or + * cold reset. + * ----------------------------------------------------- + */ + +func bl1_entrypoint + /* --------------------------------------------------------------------- + * If the reset address is programmable then bl1_entrypoint() is + * executed only on the cold boot path. Therefore, we can skip the warm + * boot mailbox mechanism. + * --------------------------------------------------------------------- + */ + 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=bl1_exceptions \ + _pie_fixup_size=0 + + /* -------------------------------------------------------------------- + * Perform BL1 setup + * -------------------------------------------------------------------- + */ + bl bl1_setup + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication. + * -------------------------------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------------------------- + * Initialize platform and jump to our c-entry point + * for this type of reset. + * -------------------------------------------------------------------- + */ + bl bl1_main + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Disable pointer authentication before jumping to next boot image. + * -------------------------------------------------------------------- + */ + bl pauth_disable_el3 +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------- + * Do the transition to next boot image. + * -------------------------------------------------- + */ +#if ENABLE_RME + b bl1_run_bl2_in_root +#else + b el3_exit +#endif +endfunc bl1_entrypoint + + /* ----------------------------------------------------- + * void bl1_run_bl2_in_root(); + * This function runs BL2 in root/EL3 when RME is enabled. + * ----------------------------------------------------- + */ + +func bl1_run_bl2_in_root + /* read bl2_ep_info */ + adrp x20, bl2_ep_info + add x20, x20, :lo12:bl2_ep_info + ldr x20, [x20] + + /* --------------------------------------------- + * MMU needs to be disabled because BL2 executes + * in EL3. It will initialize the address space + * according to its own requirements. + * --------------------------------------------- + */ + bl disable_mmu_icache_el3 + tlbi alle3 + + 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 bl1_run_bl2_in_root diff --git a/arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S b/arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S new file mode 100644 index 0000000..c54219f --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2013-2022, 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 BL1. + * ----------------------------------------------------------------------------- + */ + .globl bl1_exceptions + +vector_base bl1_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 + /* Enable the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* Expect only SMC exceptions */ + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + cmp x30, #EC_AARCH64_SMC + b.ne unexpected_sync_exception + + b smc_handler64 +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 + + +func smc_handler64 + + /* ---------------------------------------------- + * Detect if this is a RUN_IMAGE or other SMC. + * ---------------------------------------------- + */ + mov x30, #BL1_SMC_RUN_IMAGE + cmp x30, x0 + b.ne smc_handler + + /* ------------------------------------------------ + * Make sure only Secure world reaches here. + * ------------------------------------------------ + */ + mrs x30, scr_el3 + tst x30, #SCR_NS_BIT + b.ne unexpected_sync_exception + + /* ---------------------------------------------- + * Handling RUN_IMAGE SMC. First switch back to + * SP_EL0 for the C runtime stack. + * ---------------------------------------------- + */ + ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + msr spsel, #MODE_SP_EL0 + mov sp, x30 + + /* --------------------------------------------------------------------- + * Pass EL3 control to next BL image. + * Here it expects X1 with the address of a entry_point_info_t + * structure describing the next BL image entrypoint. + * --------------------------------------------------------------------- + */ + mov x20, x1 + + mov x0, x20 + bl bl1_print_next_bl_ep_info + + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, x1 + ubfx x0, x1, #MODE_EL_SHIFT, #2 + cmp x0, #MODE_EL3 + b.ne unexpected_sync_exception + + bl disable_mmu_icache_el3 + tlbi alle3 + dsb ish /* ERET implies ISB, so it is not needed here */ + +#if SPIN_ON_BL1_EXIT + bl print_debug_loop_message +debug_loop: + b debug_loop +#endif + + mov x0, x20 + bl bl1_plat_prepare_exit + + 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 smc_handler64 + +unexpected_sync_exception: + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + + /* ----------------------------------------------------- + * Save Secure/Normal world context and jump to + * BL1 SMC handler. + * ----------------------------------------------------- + */ +smc_handler: + /* ----------------------------------------------------- + * Save x0-x29 and ARMv8.3-PAuth (if enabled) registers. + * If Secure Cycle Counter is not disabled in MDCR_EL3 + * when ARMv8.5-PMU is implemented, save PMCR_EL0 and + * disable Cycle Counter. + * TODO: Revisit to store only SMCCC specified registers. + * ----------------------------------------------------- + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* ----------------------------------------------------- + * Load and program stored APIAKey firmware key. + * Re-enable pointer authentication in EL3, as it was + * disabled before jumping to the next boot image. + * ----------------------------------------------------- + */ + bl pauth_load_bl1_apiakey_enable +#endif + /* ----------------------------------------------------- + * Populate the parameters for the SMC handler. We + * already have x0-x4 in place. x5 will point to a + * cookie (not used now). x6 will point to the context + * structure (SP_EL3) and x7 will contain flags we need + * to pass to the handler. + * ----------------------------------------------------- + */ + mov x5, xzr + mov x6, sp + + /* ----------------------------------------------------- + * Restore the saved C runtime stack value which will + * become the new SP_EL0 i.e. EL3 runtime stack. It was + * saved in the 'cpu_context' structure prior to the last + * ERET from EL3. + * ----------------------------------------------------- + */ + ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + + /* --------------------------------------------- + * Switch back to SP_EL0 for the C runtime stack. + * --------------------------------------------- + */ + msr spsel, #MODE_SP_EL0 + mov sp, x12 + + /* ----------------------------------------------------- + * Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there + * is a world switch during SMC handling. + * ----------------------------------------------------- + */ + mrs x16, spsr_el3 + mrs x17, elr_el3 + mrs x18, scr_el3 + stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + + /* Copy SCR_EL3.NS bit to the flag to indicate caller's security */ + bfi x7, x18, #0, #1 + + /* ----------------------------------------------------- + * Go to BL1 SMC handler. + * ----------------------------------------------------- + */ + bl bl1_smc_handler + + /* ----------------------------------------------------- + * Do the transition to next BL image. + * ----------------------------------------------------- + */ + b el3_exit diff --git a/arm-trusted-firmware/bl1/bl1.ld.S b/arm-trusted-firmware/bl1/bl1.ld.S new file mode 100644 index 0000000..bc23828 --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1.ld.S @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * The .data section gets copied from ROM to RAM at runtime. + * Its LMA should be 16-byte aligned to allow efficient copying of 16-bytes + * aligned regions in it. + * Its VMA must be page-aligned as it marks the first read/write page. + */ +#define DATA_ALIGN 16 + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl1_entrypoint) + +MEMORY { + ROM (rx): ORIGIN = BL1_RO_BASE, LENGTH = BL1_RO_LIMIT - BL1_RO_BASE + RAM (rwx): ORIGIN = BL1_RW_BASE, LENGTH = BL1_RW_LIMIT - BL1_RW_BASE +} + +SECTIONS +{ + . = BL1_RO_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL1_RO_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl1_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >ROM + + /* .ARM.extab and .ARM.exidx are only added because Clang need them */ + .ARM.extab . : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >ROM + + .ARM.exidx . : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } >ROM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* + * No need to pad out the .rodata section to a page boundary. Next is + * the .data section, which can mapped in ROM with the same memory + * attributes as the .rodata section. + * + * Pad out to 16 bytes though as .data section needs to be 16 byte + * aligned and lld does not align the LMA to the aligment specified + * on the .data section. + */ + __RODATA_END__ = .; + . = ALIGN(16); + } >ROM +#else + ro . : { + __RO_START__ = .; + *bl1_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + *(.vectors) + __RO_END__ = .; + + /* + * Pad out to 16 bytes as .data section needs to be 16 byte aligned and + * lld does not align the LMA to the aligment specified on the .data + * section. + */ + . = ALIGN(16); + } >ROM +#endif + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + + . = BL1_RW_BASE; + ASSERT(BL1_RW_BASE == ALIGN(PAGE_SIZE), + "BL1_RW_BASE address is not aligned on a page boundary.") + + DATA_SECTION >RAM AT>ROM + __DATA_RAM_START__ = __DATA_START__; + __DATA_RAM_END__ = __DATA_END__; + + 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 + + __BL1_RAM_START__ = ADDR(.data); + __BL1_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 BL1's actual content in Trusted ROM. + */ + __BL1_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__; + ASSERT(__BL1_ROM_END__ <= BL1_RO_LIMIT, + "BL1's ROM content has exceeded its limit.") + + __BSS_SIZE__ = SIZEOF(.bss); + +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= BL1_RW_LIMIT, "BL1's RW section has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl1/bl1.mk b/arm-trusted-firmware/bl1/bl1.mk new file mode 100644 index 0000000..9f63fd5 --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1.mk @@ -0,0 +1,32 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL1_SOURCES += bl1/${ARCH}/bl1_arch_setup.c \ + bl1/${ARCH}/bl1_context_mgmt.c \ + bl1/${ARCH}/bl1_entrypoint.S \ + bl1/${ARCH}/bl1_exceptions.S \ + bl1/bl1_main.c \ + lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c \ + lib/el3_runtime/${ARCH}/context_mgmt.c \ + plat/common/plat_bl1_common.c \ + plat/common/${ARCH}/platform_up_stack.S \ + ${MBEDTLS_SOURCES} + +ifeq (${DISABLE_MTPMU},1) +BL1_SOURCES += lib/extensions/mtpmu/${ARCH}/mtpmu.S +endif + +ifeq (${ARCH},aarch64) +BL1_SOURCES += lib/cpus/aarch64/dsu_helpers.S \ + lib/el3_runtime/aarch64/context.S +endif + +ifeq (${TRUSTED_BOARD_BOOT},1) +BL1_SOURCES += bl1/bl1_fwu.c +endif + +BL1_LINKERFILE := bl1/bl1.ld.S diff --git a/arm-trusted-firmware/bl1/bl1_fwu.c b/arm-trusted-firmware/bl1/bl1_fwu.c new file mode 100644 index 0000000..b70bffd --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1_fwu.c @@ -0,0 +1,745 @@ +/* + * Copyright (c) 2015-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 + +#include "bl1_private.h" + +/* + * Function declarations. + */ +static int bl1_fwu_image_copy(unsigned int image_id, + uintptr_t image_src, + unsigned int block_size, + unsigned int image_size, + unsigned int flags); +static int bl1_fwu_image_auth(unsigned int image_id, + uintptr_t image_src, + unsigned int image_size, + unsigned int flags); +static int bl1_fwu_image_execute(unsigned int image_id, + void **handle, + unsigned int flags); +static register_t bl1_fwu_image_resume(register_t image_param, + void **handle, + unsigned int flags); +static int bl1_fwu_sec_image_done(void **handle, + unsigned int flags); +static int bl1_fwu_image_reset(unsigned int image_id, + unsigned int flags); +__dead2 static void bl1_fwu_done(void *client_cookie, void *reserved); + +/* + * This keeps track of last executed secure image id. + */ +static unsigned int sec_exec_image_id = INVALID_IMAGE_ID; + +/******************************************************************************* + * Top level handler for servicing FWU SMCs. + ******************************************************************************/ +u_register_t bl1_fwu_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) +{ + + switch (smc_fid) { + case FWU_SMC_IMAGE_COPY: + SMC_RET1(handle, bl1_fwu_image_copy((uint32_t)x1, x2, + (uint32_t)x3, (uint32_t)x4, flags)); + + case FWU_SMC_IMAGE_AUTH: + SMC_RET1(handle, bl1_fwu_image_auth((uint32_t)x1, x2, + (uint32_t)x3, flags)); + + case FWU_SMC_IMAGE_EXECUTE: + SMC_RET1(handle, bl1_fwu_image_execute((uint32_t)x1, &handle, + flags)); + + case FWU_SMC_IMAGE_RESUME: + SMC_RET1(handle, bl1_fwu_image_resume((register_t)x1, &handle, + flags)); + + case FWU_SMC_SEC_IMAGE_DONE: + SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags)); + + case FWU_SMC_IMAGE_RESET: + SMC_RET1(handle, bl1_fwu_image_reset((uint32_t)x1, flags)); + + case FWU_SMC_UPDATE_DONE: + bl1_fwu_done((void *)x1, NULL); + + default: + assert(false); /* Unreachable */ + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +/******************************************************************************* + * Utility functions to keep track of the images that are loaded at any time. + ******************************************************************************/ + +#ifdef PLAT_FWU_MAX_SIMULTANEOUS_IMAGES +#define FWU_MAX_SIMULTANEOUS_IMAGES PLAT_FWU_MAX_SIMULTANEOUS_IMAGES +#else +#define FWU_MAX_SIMULTANEOUS_IMAGES 10 +#endif + +static unsigned int bl1_fwu_loaded_ids[FWU_MAX_SIMULTANEOUS_IMAGES] = { + [0 ... FWU_MAX_SIMULTANEOUS_IMAGES-1] = INVALID_IMAGE_ID +}; + +/* + * Adds an image_id to the bl1_fwu_loaded_ids array. + * Returns 0 on success, 1 on error. + */ +static int bl1_fwu_add_loaded_id(unsigned int image_id) +{ + int i; + + /* Check if the ID is already in the list */ + for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { + if (bl1_fwu_loaded_ids[i] == image_id) + return 0; + } + + /* Find an empty slot */ + for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { + if (bl1_fwu_loaded_ids[i] == INVALID_IMAGE_ID) { + bl1_fwu_loaded_ids[i] = image_id; + return 0; + } + } + + return 1; +} + +/* + * Removes an image_id from the bl1_fwu_loaded_ids array. + * Returns 0 on success, 1 on error. + */ +static int bl1_fwu_remove_loaded_id(unsigned int image_id) +{ + int i; + + /* Find the ID */ + for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { + if (bl1_fwu_loaded_ids[i] == image_id) { + bl1_fwu_loaded_ids[i] = INVALID_IMAGE_ID; + return 0; + } + } + + return 1; +} + +/******************************************************************************* + * This function checks if the specified image overlaps another image already + * loaded. It returns 0 if there is no overlap, a negative error code otherwise. + ******************************************************************************/ +static int bl1_fwu_image_check_overlaps(unsigned int image_id) +{ + const image_desc_t *desc, *checked_desc; + const image_info_t *info, *checked_info; + + uintptr_t image_base, image_end; + uintptr_t checked_image_base, checked_image_end; + + checked_desc = bl1_plat_get_image_desc(image_id); + checked_info = &checked_desc->image_info; + + /* Image being checked mustn't be empty. */ + assert(checked_info->image_size != 0); + + checked_image_base = checked_info->image_base; + checked_image_end = checked_image_base + checked_info->image_size - 1; + /* No need to check for overflows, it's done in bl1_fwu_image_copy(). */ + + for (int i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { + + /* Skip INVALID_IMAGE_IDs and don't check image against itself */ + if ((bl1_fwu_loaded_ids[i] == INVALID_IMAGE_ID) || + (bl1_fwu_loaded_ids[i] == image_id)) + continue; + + desc = bl1_plat_get_image_desc(bl1_fwu_loaded_ids[i]); + + /* Only check images that are loaded or being loaded. */ + assert ((desc != NULL) && (desc->state != IMAGE_STATE_RESET)); + + info = &desc->image_info; + + /* There cannot be overlaps with an empty image. */ + if (info->image_size == 0) + continue; + + image_base = info->image_base; + image_end = image_base + info->image_size - 1; + /* + * Overflows cannot happen. It is checked in + * bl1_fwu_image_copy() when the image goes from RESET to + * COPYING or COPIED. + */ + assert (image_end > image_base); + + /* Check if there are overlaps. */ + if (!((image_end < checked_image_base) || + (checked_image_end < image_base))) { + VERBOSE("Image with ID %d overlaps existing image with ID %d", + checked_desc->image_id, desc->image_id); + return -EPERM; + } + } + + return 0; +} + +/******************************************************************************* + * This function is responsible for copying secure images in AP Secure RAM. + ******************************************************************************/ +static int bl1_fwu_image_copy(unsigned int image_id, + uintptr_t image_src, + unsigned int block_size, + unsigned int image_size, + unsigned int flags) +{ + uintptr_t dest_addr; + unsigned int remaining; + image_desc_t *desc; + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + if (desc == NULL) { + WARN("BL1-FWU: Invalid image ID %u\n", image_id); + return -EPERM; + } + + /* + * The request must originate from a non-secure caller and target a + * secure image. Any other scenario is invalid. + */ + if (GET_SECURITY_STATE(flags) == SECURE) { + WARN("BL1-FWU: Copy not allowed from secure world.\n"); + return -EPERM; + } + if (GET_SECURITY_STATE(desc->ep_info.h.attr) == NON_SECURE) { + WARN("BL1-FWU: Copy not allowed for non-secure images.\n"); + return -EPERM; + } + + /* Check whether the FWU state machine is in the correct state. */ + if ((desc->state != IMAGE_STATE_RESET) && + (desc->state != IMAGE_STATE_COPYING)) { + WARN("BL1-FWU: Copy not allowed at this point of the FWU" + " process.\n"); + return -EPERM; + } + + if ((image_src == 0U) || (block_size == 0U) || + check_uptr_overflow(image_src, block_size - 1)) { + WARN("BL1-FWU: Copy not allowed due to invalid image source" + " or block size\n"); + return -ENOMEM; + } + + if (desc->state == IMAGE_STATE_COPYING) { + /* + * There must have been at least 1 copy operation for this image + * previously. + */ + assert(desc->copied_size != 0U); + /* + * The image size must have been recorded in the 1st copy + * operation. + */ + image_size = desc->image_info.image_size; + assert(image_size != 0); + assert(desc->copied_size < image_size); + + INFO("BL1-FWU: Continuing image copy in blocks\n"); + } else { /* desc->state == IMAGE_STATE_RESET */ + INFO("BL1-FWU: Initial call to copy an image\n"); + + /* + * image_size is relevant only for the 1st copy request, it is + * then ignored for subsequent calls for this image. + */ + if (image_size == 0) { + WARN("BL1-FWU: Copy not allowed due to invalid image" + " size\n"); + return -ENOMEM; + } + + /* Check that the image size to load is within limit */ + if (image_size > desc->image_info.image_max_size) { + WARN("BL1-FWU: Image size out of bounds\n"); + return -ENOMEM; + } + + /* Save the given image size. */ + desc->image_info.image_size = image_size; + + /* Make sure the image doesn't overlap other images. */ + if (bl1_fwu_image_check_overlaps(image_id) != 0) { + desc->image_info.image_size = 0; + WARN("BL1-FWU: This image overlaps another one\n"); + return -EPERM; + } + + /* + * copied_size must be explicitly initialized here because the + * FWU code doesn't necessarily do it when it resets the state + * machine. + */ + desc->copied_size = 0; + } + + /* + * If the given block size is more than the total image size + * then clip the former to the latter. + */ + remaining = image_size - desc->copied_size; + if (block_size > remaining) { + WARN("BL1-FWU: Block size is too big, clipping it.\n"); + block_size = remaining; + } + + /* Make sure the source image is mapped in memory. */ + if (bl1_plat_mem_check(image_src, block_size, flags) != 0) { + WARN("BL1-FWU: Source image is not mapped.\n"); + return -ENOMEM; + } + + if (bl1_fwu_add_loaded_id(image_id) != 0) { + WARN("BL1-FWU: Too many images loaded at the same time.\n"); + return -ENOMEM; + } + + /* Allow the platform to handle pre-image load before copying */ + if (desc->state == IMAGE_STATE_RESET) { + if (bl1_plat_handle_pre_image_load(image_id) != 0) { + ERROR("BL1-FWU: Failure in pre-image load of image id %d\n", + image_id); + return -EPERM; + } + } + + /* Everything looks sane. Go ahead and copy the block of data. */ + dest_addr = desc->image_info.image_base + desc->copied_size; + (void)memcpy((void *) dest_addr, (const void *) image_src, block_size); + flush_dcache_range(dest_addr, block_size); + + desc->copied_size += block_size; + desc->state = (block_size == remaining) ? + IMAGE_STATE_COPIED : IMAGE_STATE_COPYING; + + INFO("BL1-FWU: Copy operation successful.\n"); + return 0; +} + +/******************************************************************************* + * This function is responsible for authenticating Normal/Secure images. + ******************************************************************************/ +static int bl1_fwu_image_auth(unsigned int image_id, + uintptr_t image_src, + unsigned int image_size, + unsigned int flags) +{ + int result; + uintptr_t base_addr; + unsigned int total_size; + image_desc_t *desc; + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + if (desc == NULL) + return -EPERM; + + if (GET_SECURITY_STATE(flags) == SECURE) { + if (desc->state != IMAGE_STATE_RESET) { + WARN("BL1-FWU: Authentication from secure world " + "while in invalid state\n"); + return -EPERM; + } + } else { + if (GET_SECURITY_STATE(desc->ep_info.h.attr) == SECURE) { + if (desc->state != IMAGE_STATE_COPIED) { + WARN("BL1-FWU: Authentication of secure image " + "from non-secure world while not in copied state\n"); + return -EPERM; + } + } else { + if (desc->state != IMAGE_STATE_RESET) { + WARN("BL1-FWU: Authentication of non-secure image " + "from non-secure world while in invalid state\n"); + return -EPERM; + } + } + } + + if (desc->state == IMAGE_STATE_COPIED) { + /* + * Image is in COPIED state. + * Use the stored address and size. + */ + base_addr = desc->image_info.image_base; + total_size = desc->image_info.image_size; + } else { + if ((image_src == 0U) || (image_size == 0U) || + check_uptr_overflow(image_src, image_size - 1)) { + WARN("BL1-FWU: Auth not allowed due to invalid" + " image source/size\n"); + return -ENOMEM; + } + + /* + * Image is in RESET state. + * Check the parameters and authenticate the source image in place. + */ + if (bl1_plat_mem_check(image_src, image_size, \ + desc->ep_info.h.attr) != 0) { + WARN("BL1-FWU: Authentication arguments source/size not mapped\n"); + return -ENOMEM; + } + + if (bl1_fwu_add_loaded_id(image_id) != 0) { + WARN("BL1-FWU: Too many images loaded at the same time.\n"); + return -ENOMEM; + } + + base_addr = image_src; + total_size = image_size; + + /* Update the image size in the descriptor. */ + desc->image_info.image_size = total_size; + } + + /* + * Authenticate the image. + */ + INFO("BL1-FWU: Authenticating image_id:%d\n", image_id); + result = auth_mod_verify_img(image_id, (void *)base_addr, total_size); + if (result != 0) { + WARN("BL1-FWU: Authentication Failed err=%d\n", result); + + /* + * Authentication has failed. + * Clear the memory if the image was copied. + * This is to prevent an attack where this contains + * some malicious code that can somehow be executed later. + */ + if (desc->state == IMAGE_STATE_COPIED) { + /* Clear the memory.*/ + zero_normalmem((void *)base_addr, total_size); + flush_dcache_range(base_addr, total_size); + + /* Indicate that image can be copied again*/ + desc->state = IMAGE_STATE_RESET; + } + + /* + * Even if this fails it's ok because the ID isn't in the array. + * The image cannot be in RESET state here, it is checked at the + * beginning of the function. + */ + (void)bl1_fwu_remove_loaded_id(image_id); + return -EAUTH; + } + + /* Indicate that image is in authenticated state. */ + desc->state = IMAGE_STATE_AUTHENTICATED; + + /* Allow the platform to handle post-image load */ + result = bl1_plat_handle_post_image_load(image_id); + if (result != 0) { + ERROR("BL1-FWU: Failure %d in post-image load of image id %d\n", + result, image_id); + /* + * Panic here as the platform handling of post-image load is + * not correct. + */ + plat_error_handler(result); + } + + /* + * Flush image_info to memory so that other + * secure world images can see changes. + */ + flush_dcache_range((uintptr_t)&desc->image_info, + sizeof(image_info_t)); + + INFO("BL1-FWU: Authentication was successful\n"); + + return 0; +} + +/******************************************************************************* + * This function is responsible for executing Secure images. + ******************************************************************************/ +static int bl1_fwu_image_execute(unsigned int image_id, + void **handle, + unsigned int flags) +{ + /* Get the image descriptor. */ + image_desc_t *desc = bl1_plat_get_image_desc(image_id); + + /* + * Execution is NOT allowed if: + * image_id is invalid OR + * Caller is from Secure world OR + * Image is Non-Secure OR + * Image is Non-Executable OR + * Image is NOT in AUTHENTICATED state. + */ + if ((desc == NULL) || + (GET_SECURITY_STATE(flags) == SECURE) || + (GET_SECURITY_STATE(desc->ep_info.h.attr) == NON_SECURE) || + (EP_GET_EXE(desc->ep_info.h.attr) == NON_EXECUTABLE) || + (desc->state != IMAGE_STATE_AUTHENTICATED)) { + WARN("BL1-FWU: Execution not allowed due to invalid state/args\n"); + return -EPERM; + } + + INFO("BL1-FWU: Executing Secure image\n"); + +#ifdef __aarch64__ + /* Save NS-EL1 system registers. */ + cm_el1_sysregs_context_save(NON_SECURE); +#endif + + /* Prepare the image for execution. */ + bl1_prepare_next_image(image_id); + + /* Update the secure image id. */ + sec_exec_image_id = image_id; + +#ifdef __aarch64__ + *handle = cm_get_context(SECURE); +#else + *handle = smc_get_ctx(SECURE); +#endif + return 0; +} + +/******************************************************************************* + * This function is responsible for resuming execution in the other security + * world + ******************************************************************************/ +static register_t bl1_fwu_image_resume(register_t image_param, + void **handle, + unsigned int flags) +{ + image_desc_t *desc; + unsigned int resume_sec_state; + unsigned int caller_sec_state = GET_SECURITY_STATE(flags); + + /* Get the image descriptor for last executed secure image id. */ + desc = bl1_plat_get_image_desc(sec_exec_image_id); + if (caller_sec_state == NON_SECURE) { + if (desc == NULL) { + WARN("BL1-FWU: Resume not allowed due to no available" + "secure image\n"); + return -EPERM; + } + } else { + /* desc must be valid for secure world callers */ + assert(desc != NULL); + } + + assert(GET_SECURITY_STATE(desc->ep_info.h.attr) == SECURE); + assert(EP_GET_EXE(desc->ep_info.h.attr) == EXECUTABLE); + + if (caller_sec_state == SECURE) { + assert(desc->state == IMAGE_STATE_EXECUTED); + + /* Update the flags. */ + desc->state = IMAGE_STATE_INTERRUPTED; + resume_sec_state = NON_SECURE; + } else { + assert(desc->state == IMAGE_STATE_INTERRUPTED); + + /* Update the flags. */ + desc->state = IMAGE_STATE_EXECUTED; + resume_sec_state = SECURE; + } + + INFO("BL1-FWU: Resuming %s world context\n", + (resume_sec_state == SECURE) ? "secure" : "normal"); + +#ifdef __aarch64__ + /* Save the EL1 system registers of calling world. */ + cm_el1_sysregs_context_save(caller_sec_state); + + /* Restore the EL1 system registers of resuming world. */ + cm_el1_sysregs_context_restore(resume_sec_state); + + /* Update the next context. */ + cm_set_next_eret_context(resume_sec_state); + + *handle = cm_get_context(resume_sec_state); +#else + /* Update the next context. */ + cm_set_next_context(cm_get_context(resume_sec_state)); + + /* Prepare the smc context for the next BL image. */ + smc_set_next_ctx(resume_sec_state); + + *handle = smc_get_ctx(resume_sec_state); +#endif + return image_param; +} + +/******************************************************************************* + * This function is responsible for resuming normal world context. + ******************************************************************************/ +static int bl1_fwu_sec_image_done(void **handle, unsigned int flags) +{ + image_desc_t *desc; + + /* Make sure caller is from the secure world */ + if (GET_SECURITY_STATE(flags) == NON_SECURE) { + WARN("BL1-FWU: Image done not allowed from normal world\n"); + return -EPERM; + } + + /* Get the image descriptor for last executed secure image id */ + desc = bl1_plat_get_image_desc(sec_exec_image_id); + + /* desc must correspond to a valid secure executing image */ + assert(desc != NULL); + assert(GET_SECURITY_STATE(desc->ep_info.h.attr) == SECURE); + assert(EP_GET_EXE(desc->ep_info.h.attr) == EXECUTABLE); + assert(desc->state == IMAGE_STATE_EXECUTED); + +#if ENABLE_ASSERTIONS + int rc = bl1_fwu_remove_loaded_id(sec_exec_image_id); + assert(rc == 0); +#else + bl1_fwu_remove_loaded_id(sec_exec_image_id); +#endif + + /* Update the flags. */ + desc->state = IMAGE_STATE_RESET; + sec_exec_image_id = INVALID_IMAGE_ID; + + INFO("BL1-FWU: Resuming Normal world context\n"); +#ifdef __aarch64__ + /* + * Secure world is done so no need to save the context. + * Just restore the Non-Secure context. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + + /* Update the next context. */ + cm_set_next_eret_context(NON_SECURE); + + *handle = cm_get_context(NON_SECURE); +#else + /* Update the next context. */ + cm_set_next_context(cm_get_context(NON_SECURE)); + + /* Prepare the smc context for the next BL image. */ + smc_set_next_ctx(NON_SECURE); + + *handle = smc_get_ctx(NON_SECURE); +#endif + return 0; +} + +/******************************************************************************* + * This function provides the opportunity for users to perform any + * platform specific handling after the Firmware update is done. + ******************************************************************************/ +__dead2 static void bl1_fwu_done(void *client_cookie, void *reserved) +{ + NOTICE("BL1-FWU: *******FWU Process Completed*******\n"); + + /* + * Call platform done function. + */ + bl1_plat_fwu_done(client_cookie, reserved); + assert(false); +} + +/******************************************************************************* + * This function resets an image to IMAGE_STATE_RESET. It fails if the image is + * being executed. + ******************************************************************************/ +static int bl1_fwu_image_reset(unsigned int image_id, unsigned int flags) +{ + image_desc_t *desc = bl1_plat_get_image_desc(image_id); + + if ((desc == NULL) || (GET_SECURITY_STATE(flags) == SECURE)) { + WARN("BL1-FWU: Reset not allowed due to invalid args\n"); + return -EPERM; + } + + switch (desc->state) { + + case IMAGE_STATE_RESET: + /* Nothing to do. */ + break; + + case IMAGE_STATE_INTERRUPTED: + case IMAGE_STATE_AUTHENTICATED: + case IMAGE_STATE_COPIED: + case IMAGE_STATE_COPYING: + + if (bl1_fwu_remove_loaded_id(image_id) != 0) { + WARN("BL1-FWU: Image reset couldn't find the image ID\n"); + return -EPERM; + } + + if (desc->copied_size != 0U) { + /* Clear the memory if the image is copied */ + assert(GET_SECURITY_STATE(desc->ep_info.h.attr) + == SECURE); + + zero_normalmem((void *)desc->image_info.image_base, + desc->copied_size); + flush_dcache_range(desc->image_info.image_base, + desc->copied_size); + } + + /* Reset status variables */ + desc->copied_size = 0; + desc->image_info.image_size = 0; + desc->state = IMAGE_STATE_RESET; + + /* Clear authentication state */ + auth_img_flags[image_id] = 0; + + break; + + case IMAGE_STATE_EXECUTED: + default: + assert(false); /* Unreachable */ + break; + } + + return 0; +} diff --git a/arm-trusted-firmware/bl1/bl1_main.c b/arm-trusted-firmware/bl1/bl1_main.c new file mode 100644 index 0000000..7399bc8 --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1_main.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2013-2022, 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 +#include +#include + +#include "bl1_private.h" + +static void bl1_load_bl2(void); + +#if ENABLE_PAUTH +uint64_t bl1_apiakey[2]; +#endif + +/******************************************************************************* + * Helper utility to calculate the BL2 memory layout taking into consideration + * the BL1 RW data assuming that it is at the top of the memory layout. + ******************************************************************************/ +void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout, + meminfo_t *bl2_mem_layout) +{ + assert(bl1_mem_layout != NULL); + assert(bl2_mem_layout != NULL); + + /* + * Remove BL1 RW data from the scope of memory visible to BL2. + * This is assuming BL1 RW data is at the top of bl1_mem_layout. + */ + assert(BL1_RW_BASE > bl1_mem_layout->total_base); + bl2_mem_layout->total_base = bl1_mem_layout->total_base; + bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base; + + flush_dcache_range((uintptr_t)bl2_mem_layout, sizeof(meminfo_t)); +} + +/******************************************************************************* + * Setup function for BL1. + ******************************************************************************/ +void bl1_setup(void) +{ + /* Perform early platform-specific setup */ + bl1_early_platform_setup(); + + /* Perform late platform-specific setup */ + bl1_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 */ +} + +/******************************************************************************* + * Function to perform late architectural and platform specific initialization. + * It also queries the platform to load and run next BL image. Only called + * by the primary cpu after a cold boot. + ******************************************************************************/ +void bl1_main(void) +{ + unsigned int image_id; + + /* Announce our arrival */ + NOTICE(FIRMWARE_WELCOME_STR); + NOTICE("BL1: %s\n", version_string); + NOTICE("BL1: %s\n", build_message); + + INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE, (void *)BL1_RAM_LIMIT); + + print_errata_status(); + +#if ENABLE_ASSERTIONS + u_register_t val; + /* + * Ensure that MMU/Caches and coherency are turned on + */ +#ifdef __aarch64__ + val = read_sctlr_el3(); +#else + val = read_sctlr(); +#endif + assert((val & SCTLR_M_BIT) != 0); + assert((val & SCTLR_C_BIT) != 0); + assert((val & SCTLR_I_BIT) != 0); + /* + * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the + * provided platform value + */ + val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK; + /* + * If CWG is zero, then no CWG information is available but we can + * at least check the platform value is less than the architectural + * maximum. + */ + if (val != 0) + assert(CACHE_WRITEBACK_GRANULE == SIZE_FROM_LOG2_WORDS(val)); + else + assert(CACHE_WRITEBACK_GRANULE <= MAX_CACHE_LINE_SIZE); +#endif /* ENABLE_ASSERTIONS */ + + /* Perform remaining generic architectural setup from EL3 */ + bl1_arch_setup(); + + crypto_mod_init(); + + /* Initialize authentication module */ + auth_mod_init(); + + /* Initialize the measured boot */ + bl1_plat_mboot_init(); + + /* Perform platform setup in BL1. */ + bl1_platform_setup(); + +#if ENABLE_PAUTH + /* Store APIAKey_EL1 key */ + bl1_apiakey[0] = read_apiakeylo_el1(); + bl1_apiakey[1] = read_apiakeyhi_el1(); +#endif /* ENABLE_PAUTH */ + + /* Get the image id of next image to load and run. */ + image_id = bl1_plat_get_next_image_id(); + + /* + * We currently interpret any image id other than + * BL2_IMAGE_ID as the start of firmware update. + */ + if (image_id == BL2_IMAGE_ID) + bl1_load_bl2(); + else + NOTICE("BL1-FWU: *******FWU Process Started*******\n"); + + /* Teardown the measured boot driver */ + bl1_plat_mboot_finish(); + + bl1_prepare_next_image(image_id); + + console_flush(); +} + +/******************************************************************************* + * This function locates and loads the BL2 raw binary image in the trusted SRAM. + * Called by the primary cpu after a cold boot. + * TODO: Add support for alternative image load mechanism e.g using virtio/elf + * loader etc. + ******************************************************************************/ +static void bl1_load_bl2(void) +{ + image_desc_t *desc; + image_info_t *info; + int err; + + /* Get the image descriptor */ + desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(desc != NULL); + + /* Get the image info */ + info = &desc->image_info; + INFO("BL1: Loading BL2\n"); + + err = bl1_plat_handle_pre_image_load(BL2_IMAGE_ID); + if (err != 0) { + ERROR("Failure in pre image load handling of BL2 (%d)\n", err); + plat_error_handler(err); + } + + err = load_auth_image(BL2_IMAGE_ID, info); + if (err != 0) { + ERROR("Failed to load BL2 firmware.\n"); + plat_error_handler(err); + } + + /* Allow platform to handle image information. */ + err = bl1_plat_handle_post_image_load(BL2_IMAGE_ID); + if (err != 0) { + ERROR("Failure in post image load handling of BL2 (%d)\n", err); + plat_error_handler(err); + } + + NOTICE("BL1: Booting BL2\n"); +} + +/******************************************************************************* + * Function called just before handing over to the next BL to inform the user + * about the boot progress. In debug mode, also print details about the BL + * image's execution context. + ******************************************************************************/ +void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info) +{ +#ifdef __aarch64__ + NOTICE("BL1: Booting BL31\n"); +#else + NOTICE("BL1: Booting BL32\n"); +#endif /* __aarch64__ */ + print_entry_point_info(bl_ep_info); +} + +#if SPIN_ON_BL1_EXIT +void print_debug_loop_message(void) +{ + NOTICE("BL1: Debug loop, spinning forever\n"); + NOTICE("BL1: Please connect the debugger to continue\n"); +} +#endif + +/******************************************************************************* + * Top level handler for servicing BL1 SMCs. + ******************************************************************************/ +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) +{ + /* BL1 Service UUID */ + DEFINE_SVC_UUID2(bl1_svc_uid, + U(0xd46739fd), 0xcb72, 0x9a4d, 0xb5, 0x75, + 0x67, 0x15, 0xd6, 0xf4, 0xbb, 0x4a); + + +#if TRUSTED_BOARD_BOOT + /* + * Dispatch FWU calls to FWU SMC handler and return its return + * value + */ + if (is_fwu_fid(smc_fid)) { + return bl1_fwu_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif + + switch (smc_fid) { + case BL1_SMC_CALL_COUNT: + SMC_RET1(handle, BL1_NUM_SMC_CALLS); + + case BL1_SMC_UID: + SMC_UUID_RET(handle, bl1_svc_uid); + + case BL1_SMC_VERSION: + SMC_RET1(handle, BL1_SMC_MAJOR_VER | BL1_SMC_MINOR_VER); + + default: + WARN("Unimplemented BL1 SMC Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/******************************************************************************* + * BL1 SMC wrapper. This function is only used in AArch32 mode to ensure ABI + * compliance when invoking bl1_smc_handler. + ******************************************************************************/ +u_register_t bl1_smc_wrapper(uint32_t smc_fid, + void *cookie, + void *handle, + unsigned int flags) +{ + u_register_t x1, x2, x3, x4; + + assert(handle != NULL); + + get_smc_params_from_ctx(handle, x1, x2, x3, x4); + return bl1_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); +} diff --git a/arm-trusted-firmware/bl1/bl1_private.h b/arm-trusted-firmware/bl1/bl1_private.h new file mode 100644 index 0000000..e119ba7 --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL1_PRIVATE_H +#define BL1_PRIVATE_H + +#include + +#include + +extern entry_point_info_t *bl2_ep_info; + +/****************************************** + * Function prototypes + *****************************************/ +void bl1_arch_setup(void); +void bl1_arch_next_el_setup(void); + +void bl1_prepare_next_image(unsigned int image_id); +void bl1_run_bl2_in_root(void); + +u_register_t bl1_fwu_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); + +#endif /* BL1_PRIVATE_H */ diff --git a/arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c b/arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c new file mode 100644 index 0000000..4836712 --- /dev/null +++ b/arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +image_desc_t bl1_tbbr_image_descs[] = { + { + .image_id = FWU_CERT_ID, + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_1, 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_IMAGE_BINARY, + VERSION_1, entry_point_info_t, SECURE), + }, +#if NS_BL1U_BASE + { + .image_id = NS_BL1U_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_1, entry_point_info_t, NON_SECURE | EXECUTABLE), + .ep_info.pc = NS_BL1U_BASE, + }, +#endif +#if SCP_BL2U_BASE + { + .image_id = SCP_BL2U_IMAGE_ID, + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_1, image_info_t, 0), + .image_info.image_base = SCP_BL2U_BASE, + .image_info.image_max_size = SCP_BL2U_LIMIT - SCP_BL2U_BASE, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_1, entry_point_info_t, SECURE), + }, +#endif +#if BL2U_BASE + { + .image_id = BL2U_IMAGE_ID, + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_1, image_info_t, 0), + .image_info.image_base = BL2U_BASE, + .image_info.image_max_size = BL2U_LIMIT - BL2U_BASE, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_1, entry_point_info_t, SECURE | EXECUTABLE), + .ep_info.pc = BL2U_BASE, + }, +#endif +#if NS_BL2U_BASE + { + .image_id = NS_BL2U_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_1, entry_point_info_t, NON_SECURE), + }, +#endif + BL2_IMAGE_DESC, + + { + .image_id = INVALID_IMAGE_ID, + } +}; diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c b/arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c new file mode 100644 index 0000000..4fd8d07 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../bl2_private.h" + +/******************************************************************************* + * Place holder function to perform any Secure SVC specific architectural + * setup. At the moment there is nothing to do. + ******************************************************************************/ +void bl2_arch_setup(void) +{ + +} diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S b/arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S new file mode 100644 index 0000000..40154aa --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl bl2_entrypoint + + +func bl2_entrypoint + /* Save arguments x0-x3 from previous Boot loader */ + mov r9, r0 + mov r10, r1 + mov r11, r2 + mov r12, r3 + + 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_vector_table \ + _pie_fixup_size=0 + + /* + * Restore parameters of boot rom + */ + mov r0, r9 + mov r1, r10 + mov r2, r11 + mov r3, r12 + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + bl bl2_el3_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2_entrypoint diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S b/arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S new file mode 100644 index 0000000..087b665 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_vector_table + +vector_base bl2_vector_table + b bl2_entrypoint + b report_exception /* Undef */ + b report_exception /* SVC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S b/arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S new file mode 100644 index 0000000..6e8e2c1 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_vector_table + .globl bl2_entrypoint + + +vector_base bl2_vector_table + b bl2_entrypoint + b report_exception /* Undef */ + b report_exception /* SVC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ + + +func bl2_entrypoint + /*--------------------------------------------- + * Save arguments x0 - x3 from BL1 for future + * use. + * --------------------------------------------- + */ + mov r9, r0 + mov r10, r1 + mov r11, r2 + mov r12, r3 + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + ldr r0, =bl2_vector_table + stcopr r0, VBAR + isb + + /* -------------------------------------------------------- + * Enable the instruction cache - disable speculative loads + * -------------------------------------------------------- + */ + ldcopr r0, SCTLR + orr r0, r0, #SCTLR_I_BIT + bic r0, r0, #SCTLR_DSSBS_BIT + stcopr r0, SCTLR + isb + + /* --------------------------------------------- + * Since BL2 executes after BL1, it is assumed + * here that BL1 has already has done the + * necessary register initializations. + * --------------------------------------------- + */ + + /* --------------------------------------------- + * 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. + * --------------------------------------------- + */ + ldr r0, =__RW_START__ + ldr r1, =__RW_END__ + sub r1, r1, r0 + bl inv_dcache_range + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + ldr r0, =__BSS_START__ + ldr r1, =__BSS_END__ + sub r1, r1, r0 + bl zeromem + +#if USE_COHERENT_MEM + ldr r0, =__COHERENT_RAM_START__ + ldr r1, =__COHERENT_RAM_END_UNALIGNED__ + sub r1, r1, r0 + 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 r0, r9 + mov r1, r10 + mov r2, r11 + mov r3, r12 + + bl bl2_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2_entrypoint diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S b/arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S new file mode 100644 index 0000000..0b3554e --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_run_next_image + + +func bl2_run_next_image + mov r8,r0 + + /* + * MMU needs to be disabled because both BL2 and BL32 execute + * in PL1, and therefore share the same address space. + * BL32 will initialize the address space according to its + * own requirement. + */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + mov r0, r8 + bl bl2_el3_plat_prepare_exit + + /* + * Extract PC and SPSR based on struct `entry_point_info_t` + * and load it in LR and SPSR registers respectively. + */ + ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET] + ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] + msr spsr_xc, r1 + + /* Some BL32 stages expect lr_svc to provide the BL33 entry address */ + cps #MODE32_svc + ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET] + cps #MODE32_mon + + add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET + ldm r8, {r0, r1, r2, r3} + exception_return +endfunc bl2_run_next_image diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c b/arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c new file mode 100644 index 0000000..54052f7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S b/arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S new file mode 100644 index 0000000..45bac7d --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + + .globl bl2_entrypoint + +#if BL2_IN_XIP_MEM +#define FIXUP_SIZE 0 +#else +#define FIXUP_SIZE ((BL2_LIMIT) - (BL2_BASE)) +#endif + +func bl2_entrypoint + /* 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 diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S b/arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S new file mode 100644 index 0000000..3d58051 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S b/arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S new file mode 100644 index 0000000..a021e42 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S b/arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S new file mode 100644 index 0000000..076e326 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + + .globl bl2_entrypoint + + +func bl2_entrypoint + /* 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=0 \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=1 \ + _exception_vectors=bl2_el3_exceptions \ + _pie_fixup_size=0 + + /* --------------------------------------------- + * Restore parameters of boot rom + * --------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + bl bl2_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 diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S b/arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S new file mode 100644 index 0000000..f0a8be8 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_run_next_image + + +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/arm-trusted-firmware/bl2/bl2.ld.S b/arm-trusted-firmware/bl2/bl2.ld.S new file mode 100644 index 0000000..d332ec0 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2.ld.S @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2013-2021, 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__ = .; +#if ENABLE_RME + *bl2_rme_entrypoint.o(.text*) +#else /* ENABLE_RME */ + *bl2_entrypoint.o(.text*) +#endif /* ENABLE_RME */ + *(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/arm-trusted-firmware/bl2/bl2.mk b/arm-trusted-firmware/bl2/bl2.mk new file mode 100644 index 0000000..7a973e5 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2.mk @@ -0,0 +1,50 @@ +# +# Copyright (c) 2013-2021, 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 (${ENABLE_RME},1) +# Using RME, run BL2 at EL3 +include lib/gpt_rme/gpt_rme.mk + +BL2_SOURCES += bl2/${ARCH}/bl2_rme_entrypoint.S \ + bl2/${ARCH}/bl2_el3_exceptions.S \ + bl2/${ARCH}/bl2_run_next_image.S \ + ${GPT_LIB_SRCS} +BL2_LINKERFILE := bl2/bl2.ld.S + +else ifeq (${BL2_AT_EL3},0) +# Normal operation, no RME, no BL2 at EL3 +BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S +BL2_LINKERFILE := bl2/bl2.ld.S + +else +# BL2 at EL3, no RME +BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \ + bl2/${ARCH}/bl2_el3_exceptions.S \ + bl2/${ARCH}/bl2_run_next_image.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/arm-trusted-firmware/bl2/bl2_el3.ld.S b/arm-trusted-firmware/bl2/bl2_el3.ld.S new file mode 100644 index 0000000..6aa7afd --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2_el3.ld.S @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2017-2022, 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 +#if SEPARATE_BL2_NOLOAD_REGION + RAM_NOLOAD (rw!a): ORIGIN = BL2_NOLOAD_START, LENGTH = BL2_NOLOAD_LIMIT - BL2_NOLOAD_START +#else +#define RAM_NOLOAD RAM +#endif +#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 +#if SEPARATE_BL2_NOLOAD_REGION + SAVED_ADDR = .; + . = BL2_NOLOAD_START; + __BL2_NOLOAD_START__ = .; +#endif + STACK_SECTION >RAM_NOLOAD + BSS_SECTION >RAM_NOLOAD + XLAT_TABLE_SECTION >RAM_NOLOAD +#if SEPARATE_BL2_NOLOAD_REGION + __BL2_NOLOAD_END__ = .; + . = SAVED_ADDR; +#endif + +#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/arm-trusted-firmware/bl2/bl2_image_load_v2.c b/arm-trusted-firmware/bl2/bl2_image_load_v2.c new file mode 100644 index 0000000..dee3fc2 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2_image_load_v2.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include "bl2_private.h" +#include +#include +#include +#include +#include + +#include + +/******************************************************************************* + * 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 %u\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 %u (%i)\n", + bl2_node_info->image_id, err); + plat_error_handler(err); + } + } else { + INFO("BL2: Skip loading image id %u\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/arm-trusted-firmware/bl2/bl2_main.c b/arm-trusted-firmware/bl2/bl2_main.c new file mode 100644 index 0000000..5da8037 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2_main.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013-2022, 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 "bl2_private.h" + +#ifdef __aarch64__ +#define NEXT_IMAGE "BL31" +#else +#define NEXT_IMAGE "BL32" +#endif + +#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 */ +} +#else /* BL2_AT_EL3 */ +/******************************************************************************* + * Setup function for BL2 when BL2_AT_EL3=0 + ******************************************************************************/ +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 */ +} +#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 PSA_FWU_SUPPORT + fwu_init(); +#endif /* PSA_FWU_SUPPORT */ + + crypto_mod_init(); + + /* Initialize authentication module */ + auth_mod_init(); + + /* Initialize the Measured Boot backend */ + bl2_plat_mboot_init(); + + /* Initialize boot source */ + bl2_plat_preload_setup(); + + /* Load the subsequent bootloader images. */ + next_bl_ep_info = bl2_load_images(); + + /* Teardown the Measured Boot backend */ + bl2_plat_mboot_finish(); + +#if !BL2_AT_EL3 && !ENABLE_RME +#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 || ENABLE_RME */ + 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 && ENABLE_RME */ +} diff --git a/arm-trusted-firmware/bl2/bl2_private.h b/arm-trusted-firmware/bl2/bl2_private.h new file mode 100644 index 0000000..b1704d2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S b/arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S new file mode 100644 index 0000000..e4dd03d --- /dev/null +++ b/arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2u_vector_table + .globl bl2u_entrypoint + + +vector_base bl2u_vector_table + b bl2u_entrypoint + b report_exception /* Undef */ + b report_exception /* SVC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ + + +func bl2u_entrypoint + /*--------------------------------------------- + * Save from r1 the extents of the trusted ram + * available to BL2U for future use. + * r0 is not currently used. + * --------------------------------------------- + */ + mov r11, r1 + mov r10, r2 + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + ldr r0, =bl2u_vector_table + stcopr r0, VBAR + isb + + /* -------------------------------------------------------- + * Enable the instruction cache - disable speculative loads + * -------------------------------------------------------- + */ + ldcopr r0, SCTLR + orr r0, r0, #SCTLR_I_BIT + bic r0, r0, #SCTLR_DSSBS_BIT + stcopr r0, SCTLR + isb + + /* --------------------------------------------- + * Since BL2U executes after BL1, it is assumed + * here that BL1 has already has done the + * necessary register initializations. + * --------------------------------------------- + */ + + /* --------------------------------------------- + * Invalidate the RW memory used by the BL2U + * 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. + * --------------------------------------------- + */ + ldr r0, =__RW_START__ + ldr r1, =__RW_END__ + sub r1, r1, r0 + bl inv_dcache_range + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + ldr r0, =__BSS_START__ + ldr r1, =__BSS_END__ + sub r1, r1, r0 + bl zeromem + + /* -------------------------------------------- + * 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 early platform setup & platform + * specific early arch. setup e.g. mmu setup + * --------------------------------------------- + */ + mov r0, r11 + mov r1, r10 + bl bl2u_early_platform_setup + bl bl2u_plat_arch_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2u_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2u_entrypoint diff --git a/arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S b/arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S new file mode 100644 index 0000000..15978b6 --- /dev/null +++ b/arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2u_entrypoint + + +func bl2u_entrypoint + /*--------------------------------------------- + * Store the extents of the tzram available to + * BL2U and other platform specific information + * for future use. x0 is currently not used. + * --------------------------------------------- + */ + mov x20, x1 + mov x21, x2 + + /* --------------------------------------------- + * 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 BL2U + * 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 + + /* -------------------------------------------- + * 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 early platform setup & platform + * specific early arch. setup e.g. mmu setup + * --------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + bl bl2u_early_platform_setup + bl bl2u_plat_arch_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication. + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif + + /* --------------------------------------------- + * Jump to bl2u_main function. + * --------------------------------------------- + */ + bl bl2u_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2u_entrypoint diff --git a/arm-trusted-firmware/bl2u/bl2u.ld.S b/arm-trusted-firmware/bl2u/bl2u.ld.S new file mode 100644 index 0000000..a7752a4 --- /dev/null +++ b/arm-trusted-firmware/bl2u/bl2u.ld.S @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl2u_entrypoint) + +MEMORY { + RAM (rwx): ORIGIN = BL2U_BASE, LENGTH = BL2U_LIMIT - BL2U_BASE +} + + +SECTIONS +{ + . = BL2U_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2U_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl2u_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__ = .; + *bl2u_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__ = .; + __BL2U_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); + + ASSERT(. <= BL2U_LIMIT, "BL2U image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl2u/bl2u.mk b/arm-trusted-firmware/bl2u/bl2u.mk new file mode 100644 index 0000000..b4d7634 --- /dev/null +++ b/arm-trusted-firmware/bl2u/bl2u.mk @@ -0,0 +1,15 @@ +# +# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL2U_SOURCES += bl2u/bl2u_main.c \ + bl2u/${ARCH}/bl2u_entrypoint.S \ + plat/common/${ARCH}/platform_up_stack.S + +ifeq (${ARCH},aarch64) +BL2U_SOURCES += common/aarch64/early_exceptions.S +endif + +BL2U_LINKERFILE := bl2u/bl2u.ld.S diff --git a/arm-trusted-firmware/bl2u/bl2u_main.c b/arm-trusted-firmware/bl2u/bl2u_main.c new file mode 100644 index 0000000..fcb73b9 --- /dev/null +++ b/arm-trusted-firmware/bl2u/bl2u_main.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015-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 + +/******************************************************************************* + * This function is responsible to: + * Load SCP_BL2U if platform has defined SCP_BL2U_BASE + * Perform platform setup. + * Go back to EL3. + ******************************************************************************/ +void bl2u_main(void) +{ + NOTICE("BL2U: %s\n", version_string); + NOTICE("BL2U: %s\n", build_message); + +#if SCP_BL2U_BASE + int rc; + /* Load the subsequent bootloader images */ + rc = bl2u_plat_handle_scp_bl2u(); + if (rc != 0) { + ERROR("Failed to load SCP_BL2U (%i)\n", rc); + panic(); + } +#endif + + /* Perform platform setup in BL2U after loading SCP_BL2U */ + bl2u_platform_setup(); + + console_flush(); + +#ifndef __aarch64__ + /* + * For AArch32 state BL1 and BL2U share the MMU setup. + * Given that BL2U does not map BL1 regions, MMU needs + * to be disabled in order to go back to BL1. + */ + disable_mmu_icache_secure(); +#endif /* !__aarch64__ */ + + /* + * Indicate that BL2U is done and resume back to + * normal world via an SMC to BL1. + * x1 could be passed to Normal world, + * so DO NOT pass any secret information. + */ + smc(FWU_SMC_SEC_IMAGE_DONE, 0, 0, 0, 0, 0, 0, 0); + wfi(); +} diff --git a/arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S b/arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S new file mode 100644 index 0000000..ed05864 --- /dev/null +++ b/arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + + .globl bl31_entrypoint + .globl bl31_warm_entrypoint + + /* ----------------------------------------------------- + * bl31_entrypoint() is the cold boot entrypoint, + * executed only by the primary cpu. + * ----------------------------------------------------- + */ + +func bl31_entrypoint + /* --------------------------------------------------------------- + * Stash the previous bootloader arguments x0 - x3 for later use. + * --------------------------------------------------------------- + */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + +#if !RESET_TO_BL31 + /* --------------------------------------------------------------------- + * For !RESET_TO_BL31 systems, only the primary CPU ever reaches + * bl31_entrypoint() during the cold boot flow, so the cold/warm boot + * and primary/secondary CPU logic should not be executed in this case. + * + * Also, assume that the previous bootloader has already initialised the + * SCTLR_EL3, including the endianness, and has initialised the memory. + * --------------------------------------------------------------------- + */ + el3_entrypoint_common \ + _init_sctlr=0 \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=1 \ + _exception_vectors=runtime_exceptions \ + _pie_fixup_size=BL31_LIMIT - BL31_BASE +#else + + /* --------------------------------------------------------------------- + * For RESET_TO_BL31 systems which have a programmable reset address, + * bl31_entrypoint() is executed only on the cold boot path so we can + * skip the warm boot mailbox mechanism. + * --------------------------------------------------------------------- + */ + 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=runtime_exceptions \ + _pie_fixup_size=BL31_LIMIT - BL31_BASE + + /* --------------------------------------------------------------------- + * For RESET_TO_BL31 systems, BL31 is the first bootloader to run so + * there's no argument to relay from a previous bootloader. Zero the + * arguments passed to the platform layer to reflect that. + * --------------------------------------------------------------------- + */ + mov x20, 0 + mov x21, 0 + mov x22, 0 + mov x23, 0 +#endif /* RESET_TO_BL31 */ + + /* -------------------------------------------------------------------- + * Perform BL31 setup + * -------------------------------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + bl bl31_setup + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication + * -------------------------------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------------------------- + * Jump to main function + * -------------------------------------------------------------------- + */ + bl bl31_main + + /* -------------------------------------------------------------------- + * Clean the .data & .bss sections to main memory. This ensures + * that any global data which was initialised by the primary CPU + * is visible to secondary CPUs before they enable their data + * caches and participate in coherency. + * -------------------------------------------------------------------- + */ + adrp x0, __DATA_START__ + add x0, x0, :lo12:__DATA_START__ + adrp x1, __DATA_END__ + add x1, x1, :lo12:__DATA_END__ + sub x1, x1, x0 + bl clean_dcache_range + + 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 clean_dcache_range + + b el3_exit +endfunc bl31_entrypoint + + /* -------------------------------------------------------------------- + * This CPU has been physically powered up. It is either resuming from + * suspend or has simply been turned on. In both cases, call the BL31 + * warmboot entrypoint + * -------------------------------------------------------------------- + */ +func bl31_warm_entrypoint +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * This timestamp update happens with cache off. The next + * timestamp collection will need to do cache maintenance prior + * to timestamp update. + */ + pmf_calc_timestamp_addr rt_instr_svc, RT_INSTR_EXIT_HW_LOW_PWR + mrs x1, cntpct_el0 + str x1, [x0] +#endif + + /* + * On the warm boot path, most of the EL3 initialisations performed by + * 'el3_entrypoint_common' must be skipped: + * + * - Only when the platform bypasses the BL1/BL31 entrypoint by + * programming the reset address do we need to initialise SCTLR_EL3. + * In other cases, we assume this has been taken care by the + * entrypoint code. + * + * - No need to determine the type of boot, we know it is a warm boot. + * + * - Do not try to distinguish between primary and secondary CPUs, this + * notion only exists for a cold boot. + * + * - No need to initialise the memory or the C runtime environment, + * it has been done once and for all on the cold boot path. + */ + el3_entrypoint_common \ + _init_sctlr=PROGRAMMABLE_RESET_ADDRESS \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=0 \ + _exception_vectors=runtime_exceptions \ + _pie_fixup_size=0 + + /* + * We're about to enable MMU and participate in PSCI state coordination. + * + * The PSCI implementation invokes platform routines that enable CPUs to + * participate in coherency. On a system where CPUs are not + * cache-coherent without appropriate platform specific programming, + * having caches enabled until such time might lead to coherency issues + * (resulting from stale data getting speculatively fetched, among + * others). Therefore we keep data caches disabled even after enabling + * the MMU for such platforms. + * + * On systems with hardware-assisted coherency, or on single cluster + * platforms, such platform specific programming is not required to + * enter coherency (as CPUs already are); and there's no reason to have + * caches disabled either. + */ +#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY + mov x0, xzr +#else + mov x0, #DISABLE_DCACHE +#endif + bl bl31_plat_enable_mmu + +#if ENABLE_RME + /* + * At warm boot GPT data structures have already been initialized in RAM + * but the sysregs for this CPU need to be initialized. Note that the GPT + * accesses are controlled attributes in GPCCR and do not depend on the + * SCR_EL3.C bit. + */ + bl gpt_enable + cbz x0, 1f + no_ret plat_panic_handler +1: +#endif + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication + * -------------------------------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + bl psci_warmboot_entrypoint + +#if ENABLE_RUNTIME_INSTRUMENTATION + pmf_calc_timestamp_addr rt_instr_svc, RT_INSTR_EXIT_PSCI + mov x19, x0 + + /* + * Invalidate before updating timestamp to ensure previous timestamp + * updates on the same cache line with caches disabled are properly + * seen by the same core. Without the cache invalidate, the core might + * write into a stale cache line. + */ + mov x1, #PMF_TS_SIZE + mov x20, x30 + bl inv_dcache_range + mov x30, x20 + + mrs x0, cntpct_el0 + str x0, [x19] +#endif + b el3_exit +endfunc bl31_warm_entrypoint diff --git a/arm-trusted-firmware/bl31/aarch64/crash_reporting.S b/arm-trusted-firmware/bl31/aarch64/crash_reporting.S new file mode 100644 index 0000000..d56b513 --- /dev/null +++ b/arm-trusted-firmware/bl31/aarch64/crash_reporting.S @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + + .globl report_unhandled_exception + .globl report_unhandled_interrupt + .globl el3_panic + .globl elx_panic + +#if CRASH_REPORTING + + /* ------------------------------------------------------ + * The below section deals with dumping the system state + * when an unhandled exception is taken in EL3. + * The layout and the names of the registers which will + * be dumped during a unhandled exception is given below. + * ------------------------------------------------------ + */ +.section .rodata.crash_prints, "aS" +print_spacer: + .asciz " = 0x" + +gp_regs: + .asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\ + "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\ + "x16", "x17", "x18", "x19", "x20", "x21", "x22",\ + "x23", "x24", "x25", "x26", "x27", "x28", "x29", "" +el3_sys_regs: + .asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\ + "daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\ + "esr_el3", "far_el3", "" + +non_el3_sys_regs: + .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\ + "spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\ + "csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\ + "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\ + "tpidrro_el0", "par_el1", "mpidr_el1", "afsr0_el1", "afsr1_el1",\ + "contextidr_el1", "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0",\ + "cntv_ctl_el0", "cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", "" + +#if CTX_INCLUDE_AARCH32_REGS +aarch32_regs: + .asciz "dacr32_el2", "ifsr32_el2", "" +#endif /* CTX_INCLUDE_AARCH32_REGS */ + +panic_msg: + .asciz "PANIC in EL3.\nx30" +excpt_msg: + .asciz "Unhandled Exception in EL3.\nx30" +intr_excpt_msg: + .ascii "Unhandled Interrupt Exception in EL3.\n" +x30_msg: + .asciz "x30" +excpt_msg_el: + .asciz "Unhandled Exception from EL" + + /* + * Helper function to print from crash buf. + * The print loop is controlled by the buf size and + * ascii reg name list which is passed in x6. The + * function returns the crash buf address in x0. + * Clobbers : x0 - x7, sp + */ +func size_controlled_print + /* Save the lr */ + mov sp, x30 + /* load the crash buf address */ + mrs x7, tpidr_el3 +test_size_list: + /* Calculate x5 always as it will be clobbered by asm_print_hex */ + mrs x5, tpidr_el3 + add x5, x5, #CPU_DATA_CRASH_BUF_SIZE + /* Test whether we have reached end of crash buf */ + cmp x7, x5 + b.eq exit_size_print + ldrb w4, [x6] + /* Test whether we are at end of list */ + cbz w4, exit_size_print + mov x4, x6 + /* asm_print_str updates x4 to point to next entry in list */ + bl asm_print_str + /* x0 = number of symbols printed + 1 */ + sub x0, x4, x6 + /* update x6 with the updated list pointer */ + mov x6, x4 + bl print_alignment + ldr x4, [x7], #REGSZ + bl asm_print_hex + bl asm_print_newline + b test_size_list +exit_size_print: + mov x30, sp + ret +endfunc size_controlled_print + + /* ----------------------------------------------------- + * This function calculates and prints required number + * of space characters followed by "= 0x", based on the + * length of ascii register name. + * x0: length of ascii register name + 1 + * ------------------------------------------------------ + */ +func print_alignment + /* The minimum ascii length is 3, e.g. for "x0" */ + adr x4, print_spacer - 3 + add x4, x4, x0 + b asm_print_str +endfunc print_alignment + + /* + * Helper function to store x8 - x15 registers to + * the crash buf. The system registers values are + * copied to x8 to x15 by the caller which are then + * copied to the crash buf by this function. + * x0 points to the crash buf. It then calls + * size_controlled_print to print to console. + * Clobbers : x0 - x7, sp + */ +func str_in_crash_buf_print + /* restore the crash buf address in x0 */ + mrs x0, tpidr_el3 + stp x8, x9, [x0] + stp x10, x11, [x0, #REGSZ * 2] + stp x12, x13, [x0, #REGSZ * 4] + stp x14, x15, [x0, #REGSZ * 6] + b size_controlled_print +endfunc str_in_crash_buf_print + + /* ------------------------------------------------------ + * This macro calculates the offset to crash buf from + * cpu_data and stores it in tpidr_el3. It also saves x0 + * and x1 in the crash buf by using sp as a temporary + * register. + * ------------------------------------------------------ + */ + .macro prepare_crash_buf_save_x0_x1 + /* we can corrupt this reg to free up x0 */ + mov sp, x0 + /* tpidr_el3 contains the address to cpu_data structure */ + mrs x0, tpidr_el3 + /* Calculate the Crash buffer offset in cpu_data */ + add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET + /* Store crash buffer address in tpidr_el3 */ + msr tpidr_el3, x0 + str x1, [x0, #REGSZ] + mov x1, sp + str x1, [x0] + .endm + + /* ----------------------------------------------------- + * This function allows to report a crash (if crash + * reporting is enabled) when an unhandled exception + * occurs. It prints the CPU state via the crash console + * making use of the crash buf. This function will + * not return. + * ----------------------------------------------------- + */ +func report_unhandled_exception + prepare_crash_buf_save_x0_x1 + adr x0, excpt_msg + mov sp, x0 + /* This call will not return */ + b do_crash_reporting +endfunc report_unhandled_exception + + /* ----------------------------------------------------- + * This function allows to report a crash (if crash + * reporting is enabled) when an unhandled interrupt + * occurs. It prints the CPU state via the crash console + * making use of the crash buf. This function will + * not return. + * ----------------------------------------------------- + */ +func report_unhandled_interrupt + prepare_crash_buf_save_x0_x1 + adr x0, intr_excpt_msg + mov sp, x0 + /* This call will not return */ + b do_crash_reporting +endfunc report_unhandled_interrupt + + /* ----------------------------------------------------- + * This function allows to report a crash from the lower + * exception level (if crash reporting is enabled) when + * panic() is invoked from C Runtime. + * It prints the CPU state via the crash console making + * use of 'cpu_context' structure where general purpose + * registers are saved and the crash buf. + * This function will not return. + * + * x0: Exception level + * ----------------------------------------------------- + */ +func elx_panic + msr spsel, #MODE_SP_ELX + mov x8, x0 + + /* Print the crash message */ + adr x4, excpt_msg_el + bl asm_print_str + + /* Print exception level */ + add x0, x8, #'0' + bl plat_crash_console_putc + bl asm_print_newline + + /* Report x0 - x29 values stored in 'gpregs_ctx' structure */ + /* Store the ascii list pointer in x6 */ + adr x6, gp_regs + add x7, sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0 + +print_next: + ldrb w4, [x6] + /* Test whether we are at end of list */ + cbz w4, print_x30 + mov x4, x6 + /* asm_print_str updates x4 to point to next entry in list */ + bl asm_print_str + /* x0 = number of symbols printed + 1 */ + sub x0, x4, x6 + /* Update x6 with the updated list pointer */ + mov x6, x4 + bl print_alignment + ldr x4, [x7], #REGSZ + bl asm_print_hex + bl asm_print_newline + b print_next + +print_x30: + adr x4, x30_msg + bl asm_print_str + + /* Print spaces to align "x30" string */ + mov x0, #4 + bl print_alignment + + /* Report x30 */ + ldr x4, [x7] + + /* ---------------------------------------------------------------- + * Different virtual address space size can be defined for each EL. + * Ensure that we use the proper one by reading the corresponding + * TCR_ELx register. + * ---------------------------------------------------------------- + */ + cmp x8, #MODE_EL2 + b.lt from_el1 /* EL1 */ + mrs x2, sctlr_el2 + mrs x1, tcr_el2 + + /* ---------------------------------------------------------------- + * Check if pointer authentication is enabled at the specified EL. + * If it isn't, we can then skip stripping a PAC code. + * ---------------------------------------------------------------- + */ +test_pauth: + tst x2, #(SCTLR_EnIA_BIT | SCTLR_EnIB_BIT) + b.eq no_pauth + + /* Demangle address */ + and x1, x1, #0x3F /* T0SZ = TCR_ELx[5:0] */ + sub x1, x1, #64 + neg x1, x1 /* bottom_pac_bit = 64 - T0SZ */ + mov x2, #-1 + lsl x2, x2, x1 + bic x4, x4, x2 + +no_pauth: + bl asm_print_hex + bl asm_print_newline + + /* tpidr_el3 contains the address to cpu_data structure */ + mrs x0, tpidr_el3 + /* Calculate the Crash buffer offset in cpu_data */ + add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET + /* Store crash buffer address in tpidr_el3 */ + msr tpidr_el3, x0 + + /* Print the rest of crash dump */ + b print_el3_sys_regs + +from_el1: + mrs x2, sctlr_el1 + mrs x1, tcr_el1 + b test_pauth +endfunc elx_panic + + /* ----------------------------------------------------- + * This function allows to report a crash (if crash + * reporting is enabled) when panic() is invoked from + * C Runtime. It prints the CPU state via the crash + * console making use of the crash buf. This function + * will not return. + * ----------------------------------------------------- + */ +func el3_panic + msr spsel, #MODE_SP_ELX + prepare_crash_buf_save_x0_x1 + adr x0, panic_msg + mov sp, x0 + /* Fall through to 'do_crash_reporting' */ + + /* ------------------------------------------------------------ + * The common crash reporting functionality. It requires x0 + * and x1 has already been stored in crash buf, sp points to + * crash message and tpidr_el3 contains the crash buf address. + * The function does the following: + * - Retrieve the crash buffer from tpidr_el3 + * - Store x2 to x6 in the crash buffer + * - Initialise the crash console. + * - Print the crash message by using the address in sp. + * - Print x30 value to the crash console. + * - Print x0 - x7 from the crash buf to the crash console. + * - Print x8 - x29 (in groups of 8 registers) using the + * crash buf to the crash console. + * - Print el3 sys regs (in groups of 8 registers) using the + * crash buf to the crash console. + * - Print non el3 sys regs (in groups of 8 registers) using + * the crash buf to the crash console. + * ------------------------------------------------------------ + */ +do_crash_reporting: + /* Retrieve the crash buf from tpidr_el3 */ + mrs x0, tpidr_el3 + /* Store x2 - x6, x30 in the crash buffer */ + stp x2, x3, [x0, #REGSZ * 2] + stp x4, x5, [x0, #REGSZ * 4] + stp x6, x30, [x0, #REGSZ * 6] + /* Initialize the crash console */ + bl plat_crash_console_init + /* Verify the console is initialized */ + cbz x0, crash_panic + /* Print the crash message. sp points to the crash message */ + mov x4, sp + bl asm_print_str + /* Print spaces to align "x30" string */ + mov x0, #4 + bl print_alignment + /* Load the crash buf address */ + mrs x0, tpidr_el3 + /* Report x30 first from the crash buf */ + ldr x4, [x0, #REGSZ * 7] + +#if ENABLE_PAUTH + /* Demangle address */ + xpaci x4 +#endif + bl asm_print_hex + bl asm_print_newline + /* Load the crash buf address */ + mrs x0, tpidr_el3 + /* Now mov x7 into crash buf */ + str x7, [x0, #REGSZ * 7] + + /* Report x0 - x29 values stored in crash buf */ + /* Store the ascii list pointer in x6 */ + adr x6, gp_regs + /* Print x0 to x7 from the crash buf */ + bl size_controlled_print + /* Store x8 - x15 in crash buf and print */ + bl str_in_crash_buf_print + /* Load the crash buf address */ + mrs x0, tpidr_el3 + /* Store the rest of gp regs and print */ + stp x16, x17, [x0] + stp x18, x19, [x0, #REGSZ * 2] + stp x20, x21, [x0, #REGSZ * 4] + stp x22, x23, [x0, #REGSZ * 6] + bl size_controlled_print + /* Load the crash buf address */ + mrs x0, tpidr_el3 + stp x24, x25, [x0] + stp x26, x27, [x0, #REGSZ * 2] + stp x28, x29, [x0, #REGSZ * 4] + bl size_controlled_print + + /* Print the el3 sys registers */ +print_el3_sys_regs: + adr x6, el3_sys_regs + mrs x8, scr_el3 + mrs x9, sctlr_el3 + mrs x10, cptr_el3 + mrs x11, tcr_el3 + mrs x12, daif + mrs x13, mair_el3 + mrs x14, spsr_el3 + mrs x15, elr_el3 + bl str_in_crash_buf_print + mrs x8, ttbr0_el3 + mrs x9, esr_el3 + mrs x10, far_el3 + bl str_in_crash_buf_print + + /* Print the non el3 sys registers */ + adr x6, non_el3_sys_regs + mrs x8, spsr_el1 + mrs x9, elr_el1 + mrs x10, spsr_abt + mrs x11, spsr_und + mrs x12, spsr_irq + mrs x13, spsr_fiq + mrs x14, sctlr_el1 + mrs x15, actlr_el1 + bl str_in_crash_buf_print + mrs x8, cpacr_el1 + mrs x9, csselr_el1 + mrs x10, sp_el1 + mrs x11, esr_el1 + mrs x12, ttbr0_el1 + mrs x13, ttbr1_el1 + mrs x14, mair_el1 + mrs x15, amair_el1 + bl str_in_crash_buf_print + mrs x8, tcr_el1 + mrs x9, tpidr_el1 + mrs x10, tpidr_el0 + mrs x11, tpidrro_el0 + mrs x12, par_el1 + mrs x13, mpidr_el1 + mrs x14, afsr0_el1 + mrs x15, afsr1_el1 + bl str_in_crash_buf_print + mrs x8, contextidr_el1 + mrs x9, vbar_el1 + mrs x10, cntp_ctl_el0 + mrs x11, cntp_cval_el0 + mrs x12, cntv_ctl_el0 + mrs x13, cntv_cval_el0 + mrs x14, cntkctl_el1 + mrs x15, sp_el0 + bl str_in_crash_buf_print + mrs x8, isr_el1 + bl str_in_crash_buf_print + +#if CTX_INCLUDE_AARCH32_REGS + /* Print the AArch32 registers */ + adr x6, aarch32_regs + mrs x8, dacr32_el2 + mrs x9, ifsr32_el2 + bl str_in_crash_buf_print +#endif /* CTX_INCLUDE_AARCH32_REGS */ + + /* Get the cpu specific registers to report */ + bl do_cpu_reg_dump + bl str_in_crash_buf_print + + /* Print some platform registers */ + plat_crash_print_regs + + bl plat_crash_console_flush + + /* Done reporting */ + no_ret plat_panic_handler +endfunc el3_panic + +#else /* CRASH_REPORTING */ +func report_unhandled_exception +report_unhandled_interrupt: + no_ret plat_panic_handler +endfunc report_unhandled_exception +#endif /* CRASH_REPORTING */ + +func crash_panic + no_ret plat_panic_handler +endfunc crash_panic diff --git a/arm-trusted-firmware/bl31/aarch64/ea_delegate.S b/arm-trusted-firmware/bl31/aarch64/ea_delegate.S new file mode 100644 index 0000000..fa6ede8 --- /dev/null +++ b/arm-trusted-firmware/bl31/aarch64/ea_delegate.S @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + .globl handle_lower_el_ea_esb + .globl handle_lower_el_async_ea + .globl enter_lower_el_sync_ea + .globl enter_lower_el_async_ea + + +/* + * Function to delegate External Aborts synchronized by ESB instruction at EL3 + * vector entry. This function assumes GP registers x0-x29 have been saved, and + * are available for use. It delegates the handling of the EA to platform + * handler, and returns only upon successfully handling the EA; otherwise + * panics. On return from this function, the original exception handler is + * expected to resume. + */ +func handle_lower_el_ea_esb + mov x0, #ERROR_EA_ESB + mrs x1, DISR_EL1 + b ea_proceed +endfunc handle_lower_el_ea_esb + + +/* + * This function forms the tail end of Synchronous Exception entry from lower + * EL, and expects to handle Synchronous External Aborts from lower EL and CPU + * Implementation Defined Exceptions. If any other kind of exception is detected, + * then this function reports unhandled exception. + * + * Since it's part of exception vector, this function doesn't expect any GP + * registers to have been saved. It delegates the handling of the EA to platform + * handler, and upon successfully handling the EA, exits EL3; otherwise panics. + */ +func enter_lower_el_sync_ea + /* + * Explicitly save x30 so as to free up a register and to enable + * branching. + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + + /* Check for I/D aborts from lower EL */ + cmp x30, #EC_IABORT_LOWER_EL + b.eq 1f + + cmp x30, #EC_DABORT_LOWER_EL + b.eq 1f + + /* Save GP registers */ + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + + /* Get the cpu_ops pointer */ + bl get_cpu_ops_ptr + + /* Get the cpu_ops exception handler */ + ldr x0, [x0, #CPU_E_HANDLER_FUNC] + + /* + * If the reserved function pointer is NULL, this CPU does not have an + * implementation defined exception handler function + */ + cbz x0, 2f + mrs x1, esr_el3 + ubfx x1, x1, #ESR_EC_SHIFT, #ESR_EC_LENGTH + blr x0 + b 2f + +1: + /* Test for EA bit in the instruction syndrome */ + mrs x30, esr_el3 + tbz x30, #ESR_ISS_EABORT_EA_BIT, 3f + + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey +#endif + + /* Setup exception class and syndrome arguments for platform handler */ + mov x0, #ERROR_EA_SYNC + mrs x1, esr_el3 + bl delegate_sync_ea + + /* el3_exit assumes SP_EL0 on entry */ + msr spsel, #MODE_SP_EL0 + b el3_exit +2: + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + +3: + /* Synchronous exceptions other than the above are assumed to be EA */ + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + no_ret report_unhandled_exception +endfunc enter_lower_el_sync_ea + + +/* + * This function handles SErrors from lower ELs. + * + * Since it's part of exception vector, this function doesn't expect any GP + * registers to have been saved. It delegates the handling of the EA to platform + * handler, and upon successfully handling the EA, exits EL3; otherwise panics. + */ +func enter_lower_el_async_ea + /* + * Explicitly save x30 so as to free up a register and to enable + * branching + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +handle_lower_el_async_ea: + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey +#endif + + /* Setup exception class and syndrome arguments for platform handler */ + mov x0, #ERROR_EA_ASYNC + mrs x1, esr_el3 + bl delegate_async_ea + + /* el3_exit assumes SP_EL0 on entry */ + msr spsel, #MODE_SP_EL0 + b el3_exit +endfunc enter_lower_el_async_ea + + +/* + * Prelude for Synchronous External Abort handling. This function assumes that + * all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func delegate_sync_ea +#if RAS_EXTENSION + /* + * Check for Uncontainable error type. If so, route to the platform + * fatal error handler rather than the generic EA one. + */ + ubfx x2, x1, #EABORT_SET_SHIFT, #EABORT_SET_WIDTH + cmp x2, #ERROR_STATUS_SET_UC + b.ne 1f + + /* Check fault status code */ + ubfx x3, x1, #EABORT_DFSC_SHIFT, #EABORT_DFSC_WIDTH + cmp x3, #SYNC_EA_FSC + b.ne 1f + + no_ret plat_handle_uncontainable_ea +1: +#endif + + b ea_proceed +endfunc delegate_sync_ea + + +/* + * Prelude for Asynchronous External Abort handling. This function assumes that + * all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func delegate_async_ea +#if RAS_EXTENSION + /* + * Check for Implementation Defined Syndrome. If so, skip checking + * Uncontainable error type from the syndrome as the format is unknown. + */ + tbnz x1, #SERROR_IDS_BIT, 1f + + /* + * Check for Uncontainable error type. If so, route to the platform + * fatal error handler rather than the generic EA one. + */ + ubfx x2, x1, #EABORT_AET_SHIFT, #EABORT_AET_WIDTH + cmp x2, #ERROR_STATUS_UET_UC + b.ne 1f + + /* Check DFSC for SError type */ + ubfx x3, x1, #EABORT_DFSC_SHIFT, #EABORT_DFSC_WIDTH + cmp x3, #DFSC_SERROR + b.ne 1f + + no_ret plat_handle_uncontainable_ea +1: +#endif + + b ea_proceed +endfunc delegate_async_ea + + +/* + * Delegate External Abort handling to platform's EA handler. This function + * assumes that all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func ea_proceed + /* + * If the ESR loaded earlier is not zero, we were processing an EA + * already, and this is a double fault. + */ + ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3] + cbz x5, 1f + no_ret plat_handle_double_fault + +1: + /* Save EL3 state */ + mrs x2, spsr_el3 + mrs x3, elr_el3 + stp x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + + /* + * Save ESR as handling might involve lower ELs, and returning back to + * EL3 from there would trample the original ESR. + */ + mrs x4, scr_el3 + mrs x5, esr_el3 + stp x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + + /* + * Setup rest of arguments, and call platform External Abort handler. + * + * x0: EA reason (already in place) + * x1: Exception syndrome (already in place). + * x2: Cookie (unused for now). + * x3: Context pointer. + * x4: Flags (security state from SCR for now). + */ + mov x2, xzr + mov x3, sp + ubfx x4, x4, #0, #1 + + /* Switch to runtime stack */ + ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + msr spsel, #MODE_SP_EL0 + mov sp, x5 + + mov x29, x30 +#if ENABLE_ASSERTIONS + /* Stash the stack pointer */ + mov x28, sp +#endif + bl plat_ea_handler + +#if ENABLE_ASSERTIONS + /* + * Error handling flows might involve long jumps; so upon returning from + * the platform error handler, validate that the we've completely + * unwound the stack. + */ + mov x27, sp + cmp x28, x27 + ASM_ASSERT(eq) +#endif + + /* Make SP point to context */ + msr spsel, #MODE_SP_ELX + + /* Restore EL3 state and ESR */ + ldp x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + msr spsr_el3, x1 + msr elr_el3, x2 + + /* Restore ESR_EL3 and SCR_EL3 */ + ldp x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + msr scr_el3, x3 + msr esr_el3, x4 + +#if ENABLE_ASSERTIONS + cmp x4, xzr + ASM_ASSERT(ne) +#endif + + /* Clear ESR storage */ + str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3] + + ret x29 +endfunc ea_proceed diff --git a/arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S b/arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S new file mode 100644 index 0000000..bf5bd8d --- /dev/null +++ b/arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .globl runtime_exceptions + + .globl sync_exception_sp_el0 + .globl irq_sp_el0 + .globl fiq_sp_el0 + .globl serror_sp_el0 + + .globl sync_exception_sp_elx + .globl irq_sp_elx + .globl fiq_sp_elx + .globl serror_sp_elx + + .globl sync_exception_aarch64 + .globl irq_aarch64 + .globl fiq_aarch64 + .globl serror_aarch64 + + .globl sync_exception_aarch32 + .globl irq_aarch32 + .globl fiq_aarch32 + .globl serror_aarch32 + + /* + * Macro that prepares entry to EL3 upon taking an exception. + * + * With RAS_EXTENSION, this macro synchronizes pending errors with an ESB + * instruction. When an error is thus synchronized, the handling is + * delegated to platform EA handler. + * + * Without RAS_EXTENSION, this macro synchronizes pending errors using + * a DSB, unmasks Asynchronous External Aborts and saves X30 before + * setting the flag CTX_IS_IN_EL3. + */ + .macro check_and_unmask_ea +#if RAS_EXTENSION + /* Synchronize pending External Aborts */ + esb + + /* Unmask the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* + * Explicitly save x30 so as to free up a register and to enable + * branching + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* Check for SErrors synchronized by the ESB instruction */ + mrs x30, DISR_EL1 + tbz x30, #DISR_A_BIT, 1f + + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + + bl handle_lower_el_ea_esb + + /* Restore general purpose, PMCR_EL0 and ARMv8.3-PAuth registers */ + bl restore_gp_pmcr_pauth_regs +1: +#else + /* + * For SoCs which do not implement RAS, use DSB as a barrier to + * synchronize pending external aborts. + */ + dsb sy + + /* Unmask the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* Use ISB for the above unmask operation to take effect immediately */ + isb + + /* + * Refer Note 1. No need to restore X30 as both handle_sync_exception + * and handle_interrupt_exception macro which follow this macro modify + * X30 anyway. + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + mov x30, #1 + str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3] + dmb sy +#endif + .endm + +#if !RAS_EXTENSION + /* + * Note 1: The explicit DSB at the entry of various exception vectors + * for handling exceptions from lower ELs can inadvertently trigger an + * SError exception in EL3 due to pending asynchronous aborts in lower + * ELs. This will end up being handled by serror_sp_elx which will + * ultimately panic and die. + * The way to workaround is to update a flag to indicate if the exception + * truly came from EL3. This flag is allocated in the cpu_context + * structure and located at offset "CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3" + * This is not a bullet proof solution to the problem at hand because + * we assume the instructions following "isb" that help to update the + * flag execute without causing further exceptions. + */ + + /* --------------------------------------------------------------------- + * This macro handles Asynchronous External Aborts. + * --------------------------------------------------------------------- + */ + .macro handle_async_ea + /* + * Use a barrier to synchronize pending external aborts. + */ + dsb sy + + /* Unmask the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* Use ISB for the above unmask operation to take effect immediately */ + isb + + /* Refer Note 1 */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + mov x30, #1 + str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3] + dmb sy + + b handle_lower_el_async_ea + .endm + + /* + * This macro checks if the exception was taken due to SError in EL3 or + * because of pending asynchronous external aborts from lower EL that got + * triggered due to explicit synchronization in EL3. Refer Note 1. + */ + .macro check_if_serror_from_EL3 + /* Assumes SP_EL3 on entry */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3] + cbnz x30, exp_from_EL3 + + /* Handle asynchronous external abort from lower EL */ + b handle_lower_el_async_ea + +exp_from_EL3: + /* Jump to plat_handle_el3_ea which does not return */ + .endm +#endif + + /* --------------------------------------------------------------------- + * This macro handles Synchronous exceptions. + * Only SMC exceptions are supported. + * --------------------------------------------------------------------- + */ + .macro handle_sync_exception +#if ENABLE_RUNTIME_INSTRUMENTATION + /* + * Read the timestamp value and store it in per-cpu data. The value + * will be extracted from per-cpu data by the C level SMC handler and + * saved to the PMF timestamp region. + */ + mrs x30, cntpct_el0 + str x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + mrs x29, tpidr_el3 + str x30, [x29, #CPU_DATA_PMF_TS0_OFFSET] + ldr x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] +#endif + + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + + /* Handle SMC exceptions separately from other synchronous exceptions */ + cmp x30, #EC_AARCH32_SMC + b.eq smc_handler32 + + cmp x30, #EC_AARCH64_SMC + b.eq smc_handler64 + + /* Synchronous exceptions other than the above are assumed to be EA */ + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + b enter_lower_el_sync_ea + .endm + + + /* --------------------------------------------------------------------- + * This macro handles FIQ or IRQ interrupts i.e. EL3, S-EL1 and NS + * interrupts. + * --------------------------------------------------------------------- + */ + .macro handle_interrupt_exception label + + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey +#endif + + /* Save the EL3 system registers needed to return from this exception */ + mrs x0, spsr_el3 + mrs x1, elr_el3 + stp x0, x1, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + + /* Switch to the runtime stack i.e. SP_EL0 */ + ldr x2, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + mov x20, sp + msr spsel, #MODE_SP_EL0 + mov sp, x2 + + /* + * Find out whether this is a valid interrupt type. + * If the interrupt controller reports a spurious interrupt then return + * to where we came from. + */ + bl plat_ic_get_pending_interrupt_type + cmp x0, #INTR_TYPE_INVAL + b.eq interrupt_exit_\label + + /* + * Get the registered handler for this interrupt type. + * A NULL return value could be 'cause of the following conditions: + * + * a. An interrupt of a type was routed correctly but a handler for its + * type was not registered. + * + * b. An interrupt of a type was not routed correctly so a handler for + * its type was not registered. + * + * c. An interrupt of a type was routed correctly to EL3, but was + * deasserted before its pending state could be read. Another + * interrupt of a different type pended at the same time and its + * type was reported as pending instead. However, a handler for this + * type was not registered. + * + * a. and b. can only happen due to a programming error. The + * occurrence of c. could be beyond the control of Trusted Firmware. + * It makes sense to return from this exception instead of reporting an + * error. + */ + bl get_interrupt_type_handler + cbz x0, interrupt_exit_\label + mov x21, x0 + + mov x0, #INTR_ID_UNAVAILABLE + + /* Set the current security state in the 'flags' parameter */ + mrs x2, scr_el3 + ubfx x1, x2, #0, #1 + + /* Restore the reference to the 'handle' i.e. SP_EL3 */ + mov x2, x20 + + /* x3 will point to a cookie (not used now) */ + mov x3, xzr + + /* Call the interrupt type handler */ + blr x21 + +interrupt_exit_\label: + /* Return from exception, possibly in a different security state */ + b el3_exit + + .endm + + +vector_base runtime_exceptions + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry sync_exception_sp_el0 +#ifdef MONITOR_TRAPS + stp x29, x30, [sp, #-16]! + + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + + /* Check for BRK */ + cmp x30, #EC_BRK + b.eq brk_handler + + ldp x29, x30, [sp], #16 +#endif /* MONITOR_TRAPS */ + + /* We don't expect any synchronous exceptions from EL3 */ + b report_unhandled_exception +end_vector_entry sync_exception_sp_el0 + +vector_entry irq_sp_el0 + /* + * EL3 code is non-reentrant. Any asynchronous exception is a serious + * error. Loop infinitely. + */ + b report_unhandled_interrupt +end_vector_entry irq_sp_el0 + + +vector_entry fiq_sp_el0 + b report_unhandled_interrupt +end_vector_entry fiq_sp_el0 + + +vector_entry serror_sp_el0 + no_ret plat_handle_el3_ea +end_vector_entry serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry sync_exception_sp_elx + /* + * This exception will trigger if anything went wrong during a previous + * exception entry or exit or while handling an earlier unexpected + * synchronous exception. There is a high probability that SP_EL3 is + * corrupted. + */ + b report_unhandled_exception +end_vector_entry sync_exception_sp_elx + +vector_entry irq_sp_elx + b report_unhandled_interrupt +end_vector_entry irq_sp_elx + +vector_entry fiq_sp_elx + b report_unhandled_interrupt +end_vector_entry fiq_sp_elx + +vector_entry serror_sp_elx +#if !RAS_EXTENSION + check_if_serror_from_EL3 +#endif + no_ret plat_handle_el3_ea +end_vector_entry serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry sync_exception_aarch64 + /* + * This exception vector will be the entry point for SMCs and traps + * that are unhandled at lower ELs most commonly. SP_EL3 should point + * to a valid cpu context where the general purpose and system register + * state can be saved. + */ + apply_at_speculative_wa + check_and_unmask_ea + handle_sync_exception +end_vector_entry sync_exception_aarch64 + +vector_entry irq_aarch64 + apply_at_speculative_wa + check_and_unmask_ea + handle_interrupt_exception irq_aarch64 +end_vector_entry irq_aarch64 + +vector_entry fiq_aarch64 + apply_at_speculative_wa + check_and_unmask_ea + handle_interrupt_exception fiq_aarch64 +end_vector_entry fiq_aarch64 + +vector_entry serror_aarch64 + apply_at_speculative_wa +#if RAS_EXTENSION + msr daifclr, #DAIF_ABT_BIT + b enter_lower_el_async_ea +#else + handle_async_ea +#endif +end_vector_entry serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry sync_exception_aarch32 + /* + * This exception vector will be the entry point for SMCs and traps + * that are unhandled at lower ELs most commonly. SP_EL3 should point + * to a valid cpu context where the general purpose and system register + * state can be saved. + */ + apply_at_speculative_wa + check_and_unmask_ea + handle_sync_exception +end_vector_entry sync_exception_aarch32 + +vector_entry irq_aarch32 + apply_at_speculative_wa + check_and_unmask_ea + handle_interrupt_exception irq_aarch32 +end_vector_entry irq_aarch32 + +vector_entry fiq_aarch32 + apply_at_speculative_wa + check_and_unmask_ea + handle_interrupt_exception fiq_aarch32 +end_vector_entry fiq_aarch32 + +vector_entry serror_aarch32 + apply_at_speculative_wa +#if RAS_EXTENSION + msr daifclr, #DAIF_ABT_BIT + b enter_lower_el_async_ea +#else + handle_async_ea +#endif +end_vector_entry serror_aarch32 + +#ifdef MONITOR_TRAPS + .section .rodata.brk_string, "aS" +brk_location: + .asciz "Error at instruction 0x" +brk_message: + .asciz "Unexpected BRK instruction with value 0x" +#endif /* MONITOR_TRAPS */ + + /* --------------------------------------------------------------------- + * The following code handles secure monitor calls. + * Depending upon the execution state from where the SMC has been + * invoked, it frees some general purpose registers to perform the + * remaining tasks. They involve finding the runtime service handler + * that is the target of the SMC & switching to runtime stacks (SP_EL0) + * before calling the handler. + * + * Note that x30 has been explicitly saved and can be used here + * --------------------------------------------------------------------- + */ +func smc_handler +smc_handler32: + /* Check whether aarch32 issued an SMC64 */ + tbnz x0, #FUNCID_CC_SHIFT, smc_prohibited + +smc_handler64: + /* NOTE: The code below must preserve x0-x4 */ + + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey +#endif + + /* + * Populate the parameters for the SMC handler. + * We already have x0-x4 in place. x5 will point to a cookie (not used + * now). x6 will point to the context structure (SP_EL3) and x7 will + * contain flags we need to pass to the handler. + */ + mov x5, xzr + mov x6, sp + + /* + * Restore the saved C runtime stack value which will become the new + * SP_EL0 i.e. EL3 runtime stack. It was saved in the 'cpu_context' + * structure prior to the last ERET from EL3. + */ + ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + + /* Switch to SP_EL0 */ + msr spsel, #MODE_SP_EL0 + + /* + * Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there is a world + * switch during SMC handling. + * TODO: Revisit if all system registers can be saved later. + */ + mrs x16, spsr_el3 + mrs x17, elr_el3 + mrs x18, scr_el3 + stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + + /* Clear flag register */ + mov x7, xzr + +#if ENABLE_RME + /* Copy SCR_EL3.NSE bit to the flag to indicate caller's security */ + ubfx x7, x18, #SCR_NSE_SHIFT, 1 + + /* + * Shift copied SCR_EL3.NSE bit by 5 to create space for + * SCR_EL3.NS bit. Bit 5 of the flag correspondes to + * the SCR_EL3.NSE bit. + */ + lsl x7, x7, #5 +#endif /* ENABLE_RME */ + + /* Copy SCR_EL3.NS bit to the flag to indicate caller's security */ + bfi x7, x18, #0, #1 + + mov sp, x12 + + /* Get the unique owning entity number */ + ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTH + ubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH + orr x16, x16, x15, lsl #FUNCID_OEN_WIDTH + + /* Load descriptor index from array of indices */ + adrp x14, rt_svc_descs_indices + add x14, x14, :lo12:rt_svc_descs_indices + ldrb w15, [x14, x16] + + /* Any index greater than 127 is invalid. Check bit 7. */ + tbnz w15, 7, smc_unknown + + /* + * Get the descriptor using the index + * x11 = (base + off), w15 = index + * + * handler = (base + off) + (index << log2(size)) + */ + adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE) + lsl w10, w15, #RT_SVC_SIZE_LOG2 + ldr x15, [x11, w10, uxtw] + + /* + * Call the Secure Monitor Call handler and then drop directly into + * el3_exit() which will program any remaining architectural state + * prior to issuing the ERET to the desired lower EL. + */ +#if DEBUG + cbz x15, rt_svc_fw_critical_error +#endif + blr x15 + + b el3_exit + +smc_unknown: + /* + * Unknown SMC call. Populate return value with SMC_UNK and call + * el3_exit() which will restore the remaining architectural state + * i.e., SYS, GP and PAuth registers(if any) prior to issuing the ERET + * to the desired lower EL. + */ + mov x0, #SMC_UNK + str x0, [x6, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + b el3_exit + +smc_prohibited: + restore_ptw_el1_sys_regs + ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + mov x0, #SMC_UNK + exception_return + +#if DEBUG +rt_svc_fw_critical_error: + /* Switch to SP_ELx */ + msr spsel, #MODE_SP_ELX + no_ret report_unhandled_exception +#endif +endfunc smc_handler + + /* --------------------------------------------------------------------- + * The following code handles exceptions caused by BRK instructions. + * Following a BRK instruction, the only real valid cause of action is + * to print some information and panic, as the code that caused it is + * likely in an inconsistent internal state. + * + * This is initially intended to be used in conjunction with + * __builtin_trap. + * --------------------------------------------------------------------- + */ +#ifdef MONITOR_TRAPS +func brk_handler + /* Extract the ISS */ + mrs x10, esr_el3 + ubfx x10, x10, #ESR_ISS_SHIFT, #ESR_ISS_LENGTH + + /* Ensure the console is initialized */ + bl plat_crash_console_init + + adr x4, brk_location + bl asm_print_str + mrs x4, elr_el3 + bl asm_print_hex + bl asm_print_newline + + adr x4, brk_message + bl asm_print_str + mov x4, x10 + mov x5, #28 + bl asm_print_hex_bits + bl asm_print_newline + + no_ret plat_panic_handler +endfunc brk_handler +#endif /* MONITOR_TRAPS */ diff --git a/arm-trusted-firmware/bl31/bl31.ld.S b/arm-trusted-firmware/bl31/bl31.ld.S new file mode 100644 index 0000000..8a1573a --- /dev/null +++ b/arm-trusted-firmware/bl31/bl31.ld.S @@ -0,0 +1,195 @@ +/* + * 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(bl31_entrypoint) + + +MEMORY { + RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE +#if SEPARATE_NOBITS_REGION + NOBITS (rw!a): ORIGIN = BL31_NOBITS_BASE, LENGTH = BL31_NOBITS_LIMIT - BL31_NOBITS_BASE +#else +#define NOBITS RAM +#endif +} + +#ifdef PLAT_EXTRA_LD_SCRIPT +#include +#endif + +SECTIONS +{ + . = BL31_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL31_BASE address is not aligned on a page boundary.") + + __BL31_START__ = .; + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl31_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(SORT(.text*))) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* Place pubsub sections for events */ + . = ALIGN(8); +#include + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *bl31_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* Place pubsub sections for events */ + . = ALIGN(8); +#include + + *(.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 + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + +#if SPM_MM +#ifndef SPM_SHIM_EXCEPTIONS_VMA +#define SPM_SHIM_EXCEPTIONS_VMA RAM +#endif + + /* + * Exception vectors of the SPM shim layer. They must be aligned to a 2K + * address, but we need to place them in a separate page so that we can set + * individual permissions to them, so the actual alignment needed is 4K. + * + * There's no need to include this into the RO section of BL31 because it + * doesn't need to be accessed by BL31. + */ + spm_shim_exceptions : ALIGN(PAGE_SIZE) { + __SPM_SHIM_EXCEPTIONS_START__ = .; + *(.spm_shim_exceptions) + . = ALIGN(PAGE_SIZE); + __SPM_SHIM_EXCEPTIONS_END__ = .; + } >SPM_SHIM_EXCEPTIONS_VMA AT>RAM + + PROVIDE(__SPM_SHIM_EXCEPTIONS_LMA__ = LOADADDR(spm_shim_exceptions)); + . = LOADADDR(spm_shim_exceptions) + SIZEOF(spm_shim_exceptions); +#endif + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + RELA_SECTION >RAM + +#ifdef BL31_PROGBITS_LIMIT + ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.") +#endif + +#if SEPARATE_NOBITS_REGION + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + . = ALIGN(PAGE_SIZE); + __RW_END__ = .; + __BL31_END__ = .; + + ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") + + . = BL31_NOBITS_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL31 NOBITS base address is not aligned on a page boundary.") + + __NOBITS_START__ = .; +#endif + + STACK_SECTION >NOBITS + BSS_SECTION >NOBITS + XLAT_TABLE_SECTION >NOBITS + +#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__ = .; + /* + * Bakery locks are stored in coherent memory + * + * Each lock's data is contiguous and fully allocated by the compiler + */ + *(bakery_lock) + *(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__ = .; + } >NOBITS +#endif + +#if SEPARATE_NOBITS_REGION + /* + * Define a linker symbol to mark end of the NOBITS memory area for this + * image. + */ + __NOBITS_END__ = .; + + ASSERT(. <= BL31_NOBITS_LIMIT, "BL31 NOBITS region has exceeded its limit.") +#else + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL31_END__ = .; + + /DISCARD/ : { + *(.dynsym .dynstr .hash .gnu.hash) + } + + ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") +#endif +} diff --git a/arm-trusted-firmware/bl31/bl31.mk b/arm-trusted-firmware/bl31/bl31.mk new file mode 100644 index 0000000..e751824 --- /dev/null +++ b/arm-trusted-firmware/bl31/bl31.mk @@ -0,0 +1,151 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +################################################################################ +# Include Makefile for the SPM-MM implementation +################################################################################ +ifeq (${SUPPORT_UNKNOWN_MPID},1) + ifeq (${DEBUG},0) + $(warning WARNING: SUPPORT_UNKNOWN_MPID enabled) + endif +endif + +ifeq (${SPM_MM},1) + ifeq (${EL3_EXCEPTION_HANDLING},0) + $(error EL3_EXCEPTION_HANDLING must be 1 for SPM-MM support) + else + $(info Including SPM Management Mode (MM) makefile) + include services/std_svc/spm_mm/spm_mm.mk + endif +endif + +include lib/extensions/amu/amu.mk +include lib/mpmm/mpmm.mk +include lib/psci/psci_lib.mk + +BL31_SOURCES += bl31/bl31_main.c \ + bl31/interrupt_mgmt.c \ + bl31/aarch64/bl31_entrypoint.S \ + bl31/aarch64/crash_reporting.S \ + bl31/aarch64/ea_delegate.S \ + bl31/aarch64/runtime_exceptions.S \ + bl31/bl31_context_mgmt.c \ + common/runtime_svc.c \ + lib/cpus/aarch64/dsu_helpers.S \ + plat/common/aarch64/platform_mp_stack.S \ + services/arm_arch_svc/arm_arch_svc_setup.c \ + services/std_svc/std_svc_setup.c \ + ${PSCI_LIB_SOURCES} \ + ${SPMD_SOURCES} \ + ${SPM_SOURCES} + +ifeq (${DISABLE_MTPMU},1) +BL31_SOURCES += lib/extensions/mtpmu/aarch64/mtpmu.S +endif + +ifeq (${ENABLE_PMF}, 1) +BL31_SOURCES += lib/pmf/pmf_main.c +endif + +include lib/debugfs/debugfs.mk +ifeq (${USE_DEBUGFS},1) + BL31_SOURCES += $(DEBUGFS_SRCS) +endif + +ifeq (${EL3_EXCEPTION_HANDLING},1) +BL31_SOURCES += bl31/ehf.c +endif + +ifeq (${SDEI_SUPPORT},1) +ifeq (${EL3_EXCEPTION_HANDLING},0) + $(error EL3_EXCEPTION_HANDLING must be 1 for SDEI support) +endif +BL31_SOURCES += services/std_svc/sdei/sdei_dispatch.S \ + services/std_svc/sdei/sdei_event.c \ + services/std_svc/sdei/sdei_intr_mgmt.c \ + services/std_svc/sdei/sdei_main.c \ + services/std_svc/sdei/sdei_state.c +endif + +ifeq (${TRNG_SUPPORT},1) +BL31_SOURCES += services/std_svc/trng/trng_main.c \ + services/std_svc/trng/trng_entropy_pool.c +endif + +ifeq (${ENABLE_SPE_FOR_LOWER_ELS},1) +BL31_SOURCES += lib/extensions/spe/spe.c +endif + +ifeq (${ENABLE_AMU},1) +BL31_SOURCES += ${AMU_SOURCES} +endif + +ifeq (${ENABLE_MPMM},1) +BL31_SOURCES += ${MPMM_SOURCES} +endif + +ifeq (${ENABLE_SME_FOR_NS},1) +BL31_SOURCES += lib/extensions/sme/sme.c +BL31_SOURCES += lib/extensions/sve/sve.c +else +ifeq (${ENABLE_SVE_FOR_NS},1) +BL31_SOURCES += lib/extensions/sve/sve.c +endif +endif + +ifeq (${ENABLE_MPAM_FOR_LOWER_ELS},1) +BL31_SOURCES += lib/extensions/mpam/mpam.c +endif + +ifeq (${ENABLE_TRBE_FOR_NS},1) +BL31_SOURCES += lib/extensions/trbe/trbe.c +endif + +ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1) +BL31_SOURCES += lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c +endif + +ifeq (${ENABLE_TRF_FOR_NS},1) +BL31_SOURCES += lib/extensions/trf/aarch64/trf.c +endif + +ifeq (${WORKAROUND_CVE_2017_5715},1) +BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \ + lib/cpus/aarch64/wa_cve_2017_5715_mmu.S +endif + +ifeq ($(SMC_PCI_SUPPORT),1) +BL31_SOURCES += services/std_svc/pci_svc.c +endif + +ifeq (${ENABLE_RME},1) +include lib/gpt_rme/gpt_rme.mk + +BL31_SOURCES += ${GPT_LIB_SRCS} \ + ${RMMD_SOURCES} +endif + +BL31_LINKERFILE := bl31/bl31.ld.S + +# Flag used to indicate if Crash reporting via console should be included +# in BL31. This defaults to being present in DEBUG builds only +ifndef CRASH_REPORTING +CRASH_REPORTING := $(DEBUG) +endif + +$(eval $(call assert_booleans,\ + $(sort \ + CRASH_REPORTING \ + EL3_EXCEPTION_HANDLING \ + SDEI_SUPPORT \ +))) + +$(eval $(call add_defines,\ + $(sort \ + CRASH_REPORTING \ + EL3_EXCEPTION_HANDLING \ + SDEI_SUPPORT \ +))) diff --git a/arm-trusted-firmware/bl31/bl31_context_mgmt.c b/arm-trusted-firmware/bl31/bl31_context_mgmt.c new file mode 100644 index 0000000..34f69ad --- /dev/null +++ b/arm-trusted-firmware/bl31/bl31_context_mgmt.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * for the calling CPU that was set as the context for the specified security + * state. NULL is returned if no such structure has been specified. + ******************************************************************************/ +void *cm_get_context(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + + return get_cpu_data(cpu_context[get_cpu_context_index(security_state)]); +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state for the calling CPU + ******************************************************************************/ +void cm_set_context(void *context, uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + + set_cpu_data(cpu_context[get_cpu_context_index(security_state)], + context); +} + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * for the CPU identified by `cpu_idx` that was set as the context for the + * specified security state. NULL is returned if no such structure has been + * specified. + ******************************************************************************/ +void *cm_get_context_by_index(unsigned int cpu_idx, + unsigned int security_state) +{ + assert(sec_state_is_valid(security_state)); + + return get_cpu_data_by_index(cpu_idx, + cpu_context[get_cpu_context_index(security_state)]); +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state for the CPU identified by CPU index. + ******************************************************************************/ +void cm_set_context_by_index(unsigned int cpu_idx, void *context, + unsigned int security_state) +{ + assert(sec_state_is_valid(security_state)); + + set_cpu_data_by_index(cpu_idx, + cpu_context[get_cpu_context_index(security_state)], + context); +} diff --git a/arm-trusted-firmware/bl31/bl31_main.c b/arm-trusted-firmware/bl31/bl31_main.c new file mode 100644 index 0000000..9ac10e2 --- /dev/null +++ b/arm-trusted-firmware/bl31/bl31_main.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2013-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 +#include +#include + +#if ENABLE_RUNTIME_INSTRUMENTATION +PMF_REGISTER_SERVICE_SMC(rt_instr_svc, PMF_RT_INSTR_SVC_ID, + RT_INSTR_TOTAL_IDS, PMF_STORE_ENABLE) +#endif + +/******************************************************************************* + * This function pointer is used to initialise the BL32 image. It's initialized + * by SPD calling bl31_register_bl32_init after setting up all things necessary + * for SP execution. In cases where both SPD and SP are absent, or when SPD + * finds it impossible to execute SP, this pointer is left as NULL + ******************************************************************************/ +static int32_t (*bl32_init)(void); + +/***************************************************************************** + * Function used to initialise RMM if RME is enabled + *****************************************************************************/ +#if ENABLE_RME +static int32_t (*rmm_init)(void); +#endif + +/******************************************************************************* + * Variable to indicate whether next image to execute after BL31 is BL33 + * (non-secure & default) or BL32 (secure). + ******************************************************************************/ +static uint32_t next_image_type = NON_SECURE; + +#ifdef SUPPORT_UNKNOWN_MPID +/* + * Flag to know whether an unsupported MPID has been detected. To avoid having it + * landing on the .bss section, it is initialized to a non-zero value, this way + * we avoid potential WAW hazards during system bring up. + * */ +volatile uint32_t unsupported_mpid_flag = 1; +#endif + +/* + * Implement the ARM Standard Service function to get arguments for a + * particular service. + */ +uintptr_t get_arm_std_svc_args(unsigned int svc_mask) +{ + /* Setup the arguments for PSCI Library */ + DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, bl31_warm_entrypoint); + + /* PSCI is the only ARM Standard Service implemented */ + assert(svc_mask == PSCI_FID_MASK); + + return (uintptr_t)&psci_args; +} + +/******************************************************************************* + * Simple function to initialise all BL31 helper libraries. + ******************************************************************************/ +void __init bl31_lib_init(void) +{ + cm_init(); +} + +/******************************************************************************* + * Setup function for BL31. + ******************************************************************************/ +void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl31_early_platform_setup2(arg0, arg1, arg2, arg3); + + /* Perform late platform-specific setup */ + bl31_plat_arch_setup(); + +#if ENABLE_FEAT_HCX + /* + * Assert that FEAT_HCX is supported on this system, without this check + * an exception would occur during context save/restore if enabled but + * not supported. + */ + assert(is_feat_hcx_present()); +#endif /* ENABLE_FEAT_HCX */ + +#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 */ +} + +/******************************************************************************* + * BL31 is responsible for setting up the runtime services for the primary cpu + * before passing control to the bootloader or an Operating System. This + * function calls runtime_svc_init() which initializes all registered runtime + * services. The run time services would setup enough context for the core to + * switch to the next exception level. When this function returns, the core will + * switch to the programmed exception level via an ERET. + ******************************************************************************/ +void bl31_main(void) +{ + NOTICE("BL31: %s\n", version_string); + NOTICE("BL31: %s\n", build_message); + +#ifdef SUPPORT_UNKNOWN_MPID + if (unsupported_mpid_flag == 0) { + NOTICE("Unsupported MPID detected!\n"); + } +#endif + + /* Perform platform setup in BL31 */ + bl31_platform_setup(); + + /* Initialise helper libraries */ + bl31_lib_init(); + +#if EL3_EXCEPTION_HANDLING + INFO("BL31: Initialising Exception Handling Framework\n"); + ehf_init(); +#endif + + /* Initialize the runtime services e.g. psci. */ + INFO("BL31: Initializing runtime services\n"); + runtime_svc_init(); + + /* + * All the cold boot actions on the primary cpu are done. We now need to + * decide which is the next image and how to execute it. + * If the SPD runtime service is present, it would want to pass control + * to BL32 first in S-EL1. In that case, SPD would have registered a + * function to initialize bl32 where it takes responsibility of entering + * S-EL1 and returning control back to bl31_main. Similarly, if RME is + * enabled and a function is registered to initialize RMM, control is + * transferred to RMM in R-EL2. After RMM initialization, control is + * returned back to bl31_main. Once this is done we can prepare entry + * into BL33 as normal. + */ + + /* + * If SPD had registered an init hook, invoke it. + */ + if (bl32_init != NULL) { + INFO("BL31: Initializing BL32\n"); + + int32_t rc = (*bl32_init)(); + + if (rc == 0) { + WARN("BL31: BL32 initialization failed\n"); + } + } + + /* + * If RME is enabled and init hook is registered, initialize RMM + * in R-EL2. + */ +#if ENABLE_RME + if (rmm_init != NULL) { + INFO("BL31: Initializing RMM\n"); + + int32_t rc = (*rmm_init)(); + + if (rc == 0) { + WARN("BL31: RMM initialization failed\n"); + } + } +#endif + + /* + * We are ready to enter the next EL. Prepare entry into the image + * corresponding to the desired security state after the next ERET. + */ + bl31_prepare_next_image_entry(); + + console_flush(); + + /* + * Perform any platform specific runtime setup prior to cold boot exit + * from BL31 + */ + bl31_plat_runtime_setup(); +} + +/******************************************************************************* + * Accessor functions to help runtime services decide which image should be + * executed after BL31. This is BL33 or the non-secure bootloader image by + * default but the Secure payload dispatcher could override this by requesting + * an entry into BL32 (Secure payload) first. If it does so then it should use + * the same API to program an entry into BL33 once BL32 initialisation is + * complete. + ******************************************************************************/ +void bl31_set_next_image_type(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + next_image_type = security_state; +} + +uint32_t bl31_get_next_image_type(void) +{ + return next_image_type; +} + +/******************************************************************************* + * This function programs EL3 registers and performs other setup to enable entry + * into the next image after BL31 at the next ERET. + ******************************************************************************/ +void __init bl31_prepare_next_image_entry(void) +{ + entry_point_info_t *next_image_info; + uint32_t image_type; + +#if CTX_INCLUDE_AARCH32_REGS + /* + * Ensure that the build flag to save AArch32 system registers in CPU + * context is not set for AArch64-only platforms. + */ + if (el_implemented(1) == EL_IMPL_A64ONLY) { + ERROR("EL1 supports AArch64-only. Please set build flag " + "CTX_INCLUDE_AARCH32_REGS = 0\n"); + panic(); + } +#endif + + /* Determine which image to execute next */ + image_type = bl31_get_next_image_type(); + + /* Program EL3 registers to enable entry into the next EL */ + next_image_info = bl31_plat_get_next_image_ep_info(image_type); + assert(next_image_info != NULL); + assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr)); + + INFO("BL31: Preparing for EL3 exit to %s world\n", + (image_type == SECURE) ? "secure" : "normal"); + print_entry_point_info(next_image_info); + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(image_type); +} + +/******************************************************************************* + * This function initializes the pointer to BL32 init function. This is expected + * to be called by the SPD after it finishes all its initialization + ******************************************************************************/ +void bl31_register_bl32_init(int32_t (*func)(void)) +{ + bl32_init = func; +} + +#if ENABLE_RME +/******************************************************************************* + * This function initializes the pointer to RMM init function. This is expected + * to be called by the RMMD after it finishes all its initialization + ******************************************************************************/ +void bl31_register_rmm_init(int32_t (*func)(void)) +{ + rmm_init = func; +} +#endif diff --git a/arm-trusted-firmware/bl31/ehf.c b/arm-trusted-firmware/bl31/ehf.c new file mode 100644 index 0000000..745f165 --- /dev/null +++ b/arm-trusted-firmware/bl31/ehf.c @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Exception handlers at EL3, their priority levels, and management. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Output EHF logs as verbose */ +#define EHF_LOG(...) VERBOSE("EHF: " __VA_ARGS__) + +#define EHF_INVALID_IDX (-1) + +/* For a valid handler, return the actual function pointer; otherwise, 0. */ +#define RAW_HANDLER(h) \ + ((ehf_handler_t) ((((h) & EHF_PRI_VALID_) != 0U) ? \ + ((h) & ~EHF_PRI_VALID_) : 0U)) + +#define PRI_BIT(idx) (((ehf_pri_bits_t) 1u) << (idx)) + +/* + * Convert index into secure priority using the platform-defined priority bits + * field. + */ +#define IDX_TO_PRI(idx) \ + ((((unsigned) idx) << (7u - exception_data.pri_bits)) & 0x7fU) + +/* Check whether a given index is valid */ +#define IS_IDX_VALID(idx) \ + ((exception_data.ehf_priorities[idx].ehf_handler & EHF_PRI_VALID_) != 0U) + +/* Returns whether given priority is in secure priority range */ +#define IS_PRI_SECURE(pri) (((pri) & 0x80U) == 0U) + +/* To be defined by the platform */ +extern const ehf_priorities_t exception_data; + +/* Translate priority to the index in the priority array */ +static unsigned int pri_to_idx(unsigned int priority) +{ + unsigned int idx; + + idx = EHF_PRI_TO_IDX(priority, exception_data.pri_bits); + assert(idx < exception_data.num_priorities); + assert(IS_IDX_VALID(idx)); + + return idx; +} + +/* Return whether there are outstanding priority activation */ +static bool has_valid_pri_activations(pe_exc_data_t *pe_data) +{ + return pe_data->active_pri_bits != 0U; +} + +static pe_exc_data_t *this_cpu_data(void) +{ + return &get_cpu_data(ehf_data); +} + +/* + * Return the current priority index of this CPU. If no priority is active, + * return EHF_INVALID_IDX. + */ +static int get_pe_highest_active_idx(pe_exc_data_t *pe_data) +{ + if (!has_valid_pri_activations(pe_data)) + return EHF_INVALID_IDX; + + /* Current priority is the right-most bit */ + return (int) __builtin_ctz(pe_data->active_pri_bits); +} + +/* + * Mark priority active by setting the corresponding bit in active_pri_bits and + * programming the priority mask. + * + * This API is to be used as part of delegating to lower ELs other than for + * interrupts; e.g. while handling synchronous exceptions. + * + * This API is expected to be invoked before restoring context (Secure or + * Non-secure) in preparation for the respective dispatch. + */ +void ehf_activate_priority(unsigned int priority) +{ + int cur_pri_idx; + unsigned int old_mask, run_pri, idx; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* + * Query interrupt controller for the running priority, or idle priority + * if no interrupts are being handled. The requested priority must be + * less (higher priority) than the active running priority. + */ + run_pri = plat_ic_get_running_priority(); + if (priority >= run_pri) { + ERROR("Running priority higher (0x%x) than requested (0x%x)\n", + run_pri, priority); + panic(); + } + + /* + * If there were priority activations already, the requested priority + * must be less (higher priority) than the current highest priority + * activation so far. + */ + cur_pri_idx = get_pe_highest_active_idx(pe_data); + idx = pri_to_idx(priority); + if ((cur_pri_idx != EHF_INVALID_IDX) && + (idx >= ((unsigned int) cur_pri_idx))) { + ERROR("Activation priority mismatch: req=0x%x current=0x%x\n", + priority, IDX_TO_PRI(cur_pri_idx)); + panic(); + } + + /* Set the bit corresponding to the requested priority */ + pe_data->active_pri_bits |= PRI_BIT(idx); + + /* + * Program priority mask for the activated level. Check that the new + * priority mask is setting a higher priority level than the existing + * mask. + */ + old_mask = plat_ic_set_priority_mask(priority); + if (priority >= old_mask) { + ERROR("Requested priority (0x%x) lower than Priority Mask (0x%x)\n", + priority, old_mask); + panic(); + } + + /* + * If this is the first activation, save the priority mask. This will be + * restored after the last deactivation. + */ + if (cur_pri_idx == EHF_INVALID_IDX) + pe_data->init_pri_mask = (uint8_t) old_mask; + + EHF_LOG("activate prio=%d\n", get_pe_highest_active_idx(pe_data)); +} + +/* + * Mark priority inactive by clearing the corresponding bit in active_pri_bits, + * and programming the priority mask. + * + * This API is expected to be used as part of delegating to to lower ELs other + * than for interrupts; e.g. while handling synchronous exceptions. + * + * This API is expected to be invoked after saving context (Secure or + * Non-secure), having concluded the respective dispatch. + */ +void ehf_deactivate_priority(unsigned int priority) +{ + int cur_pri_idx; + pe_exc_data_t *pe_data = this_cpu_data(); + unsigned int old_mask, run_pri, idx; + + /* + * Query interrupt controller for the running priority, or idle priority + * if no interrupts are being handled. The requested priority must be + * less (higher priority) than the active running priority. + */ + run_pri = plat_ic_get_running_priority(); + if (priority >= run_pri) { + ERROR("Running priority higher (0x%x) than requested (0x%x)\n", + run_pri, priority); + panic(); + } + + /* + * Deactivation is allowed only when there are priority activations, and + * the deactivation priority level must match the current activated + * priority. + */ + cur_pri_idx = get_pe_highest_active_idx(pe_data); + idx = pri_to_idx(priority); + if ((cur_pri_idx == EHF_INVALID_IDX) || + (idx != ((unsigned int) cur_pri_idx))) { + ERROR("Deactivation priority mismatch: req=0x%x current=0x%x\n", + priority, IDX_TO_PRI(cur_pri_idx)); + panic(); + } + + /* Clear bit corresponding to highest priority */ + pe_data->active_pri_bits &= (pe_data->active_pri_bits - 1u); + + /* + * Restore priority mask corresponding to the next priority, or the + * one stashed earlier if there are no more to deactivate. + */ + cur_pri_idx = get_pe_highest_active_idx(pe_data); + if (cur_pri_idx == EHF_INVALID_IDX) + old_mask = plat_ic_set_priority_mask(pe_data->init_pri_mask); + else + old_mask = plat_ic_set_priority_mask(priority); + + if (old_mask > priority) { + ERROR("Deactivation priority (0x%x) lower than Priority Mask (0x%x)\n", + priority, old_mask); + panic(); + } + + EHF_LOG("deactivate prio=%d\n", get_pe_highest_active_idx(pe_data)); +} + +/* + * After leaving Non-secure world, stash current Non-secure Priority Mask, and + * set Priority Mask to the highest Non-secure priority so that Non-secure + * interrupts cannot preempt Secure execution. + * + * If the current running priority is in the secure range, or if there are + * outstanding priority activations, this function does nothing. + * + * This function subscribes to the 'cm_exited_normal_world' event published by + * the Context Management Library. + */ +static void *ehf_exited_normal_world(const void *arg) +{ + unsigned int run_pri; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* If the running priority is in the secure range, do nothing */ + run_pri = plat_ic_get_running_priority(); + if (IS_PRI_SECURE(run_pri)) + return NULL; + + /* Do nothing if there are explicit activations */ + if (has_valid_pri_activations(pe_data)) + return NULL; + + assert(pe_data->ns_pri_mask == 0u); + + pe_data->ns_pri_mask = + (uint8_t) plat_ic_set_priority_mask(GIC_HIGHEST_NS_PRIORITY); + + /* The previous Priority Mask is not expected to be in secure range */ + if (IS_PRI_SECURE(pe_data->ns_pri_mask)) { + ERROR("Priority Mask (0x%x) already in secure range\n", + pe_data->ns_pri_mask); + panic(); + } + + EHF_LOG("Priority Mask: 0x%x => 0x%x\n", pe_data->ns_pri_mask, + GIC_HIGHEST_NS_PRIORITY); + + return NULL; +} + +/* + * Conclude Secure execution and prepare for return to Non-secure world. Restore + * the Non-secure Priority Mask previously stashed upon leaving Non-secure + * world. + * + * If there the current running priority is in the secure range, or if there are + * outstanding priority activations, this function does nothing. + * + * This function subscribes to the 'cm_entering_normal_world' event published by + * the Context Management Library. + */ +static void *ehf_entering_normal_world(const void *arg) +{ + unsigned int old_pmr, run_pri; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* If the running priority is in the secure range, do nothing */ + run_pri = plat_ic_get_running_priority(); + if (IS_PRI_SECURE(run_pri)) + return NULL; + + /* + * If there are explicit activations, do nothing. The Priority Mask will + * be restored upon the last deactivation. + */ + if (has_valid_pri_activations(pe_data)) + return NULL; + + /* Do nothing if we don't have a valid Priority Mask to restore */ + if (pe_data->ns_pri_mask == 0U) + return NULL; + + old_pmr = plat_ic_set_priority_mask(pe_data->ns_pri_mask); + + /* + * When exiting secure world, the current Priority Mask must be + * GIC_HIGHEST_NS_PRIORITY (as set during entry), or the Non-secure + * priority mask set upon calling ehf_allow_ns_preemption() + */ + if ((old_pmr != GIC_HIGHEST_NS_PRIORITY) && + (old_pmr != pe_data->ns_pri_mask)) { + ERROR("Invalid Priority Mask (0x%x) restored\n", old_pmr); + panic(); + } + + EHF_LOG("Priority Mask: 0x%x => 0x%x\n", old_pmr, pe_data->ns_pri_mask); + + pe_data->ns_pri_mask = 0; + + return NULL; +} + +/* + * Program Priority Mask to the original Non-secure priority such that + * Non-secure interrupts may preempt Secure execution (for example, during + * Yielding SMC calls). The 'preempt_ret_code' parameter indicates the Yielding + * SMC's return value in case the call was preempted. + * + * This API is expected to be invoked before delegating a yielding SMC to Secure + * EL1. I.e. within the window of secure execution after Non-secure context is + * saved (after entry into EL3) and Secure context is restored (before entering + * Secure EL1). + */ +void ehf_allow_ns_preemption(uint64_t preempt_ret_code) +{ + cpu_context_t *ns_ctx; + unsigned int old_pmr __unused; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* + * We should have been notified earlier of entering secure world, and + * therefore have stashed the Non-secure priority mask. + */ + assert(pe_data->ns_pri_mask != 0U); + + /* Make sure no priority levels are active when requesting this */ + if (has_valid_pri_activations(pe_data)) { + ERROR("PE %lx has priority activations: 0x%x\n", + read_mpidr_el1(), pe_data->active_pri_bits); + panic(); + } + + /* + * Program preempted return code to x0 right away so that, if the + * Yielding SMC was indeed preempted before a dispatcher gets a chance + * to populate it, the caller would find the correct return value. + */ + ns_ctx = cm_get_context(NON_SECURE); + assert(ns_ctx != NULL); + write_ctx_reg(get_gpregs_ctx(ns_ctx), CTX_GPREG_X0, preempt_ret_code); + + old_pmr = plat_ic_set_priority_mask(pe_data->ns_pri_mask); + + EHF_LOG("Priority Mask: 0x%x => 0x%x\n", old_pmr, pe_data->ns_pri_mask); + + pe_data->ns_pri_mask = 0; +} + +/* + * Return whether Secure execution has explicitly allowed Non-secure interrupts + * to preempt itself (for example, during Yielding SMC calls). + */ +unsigned int ehf_is_ns_preemption_allowed(void) +{ + unsigned int run_pri; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* If running priority is in secure range, return false */ + run_pri = plat_ic_get_running_priority(); + if (IS_PRI_SECURE(run_pri)) + return 0; + + /* + * If Non-secure preemption was permitted by calling + * ehf_allow_ns_preemption() earlier: + * + * - There wouldn't have been priority activations; + * - We would have cleared the stashed the Non-secure Priority Mask. + */ + if (has_valid_pri_activations(pe_data)) + return 0; + if (pe_data->ns_pri_mask != 0U) + return 0; + + return 1; +} + +/* + * Top-level EL3 interrupt handler. + */ +static uint64_t ehf_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + int ret = 0; + uint32_t intr_raw; + unsigned int intr, pri, idx; + ehf_handler_t handler; + + /* + * Top-level interrupt type handler from Interrupt Management Framework + * doesn't acknowledge the interrupt; so the interrupt ID must be + * invalid. + */ + assert(id == INTR_ID_UNAVAILABLE); + + /* + * Acknowledge interrupt. Proceed with handling only for valid interrupt + * IDs. This situation may arise because of Interrupt Management + * Framework identifying an EL3 interrupt, but before it's been + * acknowledged here, the interrupt was either deasserted, or there was + * a higher-priority interrupt of another type. + */ + intr_raw = plat_ic_acknowledge_interrupt(); + intr = plat_ic_get_interrupt_id(intr_raw); + if (intr == INTR_ID_UNAVAILABLE) + return 0; + + /* Having acknowledged the interrupt, get the running priority */ + pri = plat_ic_get_running_priority(); + + /* Check EL3 interrupt priority is in secure range */ + assert(IS_PRI_SECURE(pri)); + + /* + * Translate the priority to a descriptor index. We do this by masking + * and shifting the running priority value (platform-supplied). + */ + idx = pri_to_idx(pri); + + /* Validate priority */ + assert(pri == IDX_TO_PRI(idx)); + + handler = (ehf_handler_t) RAW_HANDLER( + exception_data.ehf_priorities[idx].ehf_handler); + if (handler == NULL) { + ERROR("No EL3 exception handler for priority 0x%x\n", + IDX_TO_PRI(idx)); + panic(); + } + + /* + * Call registered handler. Pass the raw interrupt value to registered + * handlers. + */ + ret = handler(intr_raw, flags, handle, cookie); + + return (uint64_t) ret; +} + +/* + * Initialize the EL3 exception handling. + */ +void __init ehf_init(void) +{ + unsigned int flags = 0; + int ret __unused; + + /* Ensure EL3 interrupts are supported */ + assert(plat_ic_has_interrupt_type(INTR_TYPE_EL3) != 0); + + /* + * Make sure that priority water mark has enough bits to represent the + * whole priority array. + */ + assert(exception_data.num_priorities <= (sizeof(ehf_pri_bits_t) * 8U)); + + assert(exception_data.ehf_priorities != NULL); + + /* + * Bit 7 of GIC priority must be 0 for secure interrupts. This means + * platforms must use at least 1 of the remaining 7 bits. + */ + assert((exception_data.pri_bits >= 1U) || + (exception_data.pri_bits < 8U)); + + /* Route EL3 interrupts when in Secure and Non-secure. */ + set_interrupt_rm_flag(flags, NON_SECURE); + set_interrupt_rm_flag(flags, SECURE); + + /* Register handler for EL3 interrupts */ + ret = register_interrupt_type_handler(INTR_TYPE_EL3, + ehf_el3_interrupt_handler, flags); + assert(ret == 0); +} + +/* + * Register a handler at the supplied priority. Registration is allowed only if + * a handler hasn't been registered before, or one wasn't provided at build + * time. The priority for which the handler is being registered must also accord + * with the platform-supplied data. + */ +void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler) +{ + unsigned int idx; + + /* Sanity check for handler */ + assert(handler != NULL); + + /* Handler ought to be 4-byte aligned */ + assert((((uintptr_t) handler) & 3U) == 0U); + + /* Ensure we register for valid priority */ + idx = pri_to_idx(pri); + assert(idx < exception_data.num_priorities); + assert(IDX_TO_PRI(idx) == pri); + + /* Return failure if a handler was already registered */ + if (exception_data.ehf_priorities[idx].ehf_handler != EHF_NO_HANDLER_) { + ERROR("Handler already registered for priority 0x%x\n", pri); + panic(); + } + + /* + * Install handler, and retain the valid bit. We assume that the handler + * is 4-byte aligned, which is usually the case. + */ + exception_data.ehf_priorities[idx].ehf_handler = + (((uintptr_t) handler) | EHF_PRI_VALID_); + + EHF_LOG("register pri=0x%x handler=%p\n", pri, handler); +} + +SUBSCRIBE_TO_EVENT(cm_entering_normal_world, ehf_entering_normal_world); +SUBSCRIBE_TO_EVENT(cm_exited_normal_world, ehf_exited_normal_world); diff --git a/arm-trusted-firmware/bl31/interrupt_mgmt.c b/arm-trusted-firmware/bl31/interrupt_mgmt.c new file mode 100644 index 0000000..b8cc3de --- /dev/null +++ b/arm-trusted-firmware/bl31/interrupt_mgmt.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +/******************************************************************************* + * Local structure and corresponding array to keep track of the state of the + * registered interrupt handlers for each interrupt type. + * The field descriptions are: + * + * 'scr_el3[2]' : Mapping of the routing model in the 'flags' field to the + * value of the SCR_EL3.IRQ or FIQ bit for each security state. + * There are two instances of this field corresponding to the + * two security states. + * + * 'flags' : Bit[0], Routing model for this interrupt type when execution is + * not in EL3 in the secure state. '1' implies that this + * interrupt will be routed to EL3. '0' implies that this + * interrupt will be routed to the current exception level. + * + * Bit[1], Routing model for this interrupt type when execution is + * not in EL3 in the non-secure state. '1' implies that this + * interrupt will be routed to EL3. '0' implies that this + * interrupt will be routed to the current exception level. + * + * All other bits are reserved and SBZ. + ******************************************************************************/ +typedef struct intr_type_desc { + interrupt_type_handler_t handler; + u_register_t scr_el3[2]; + uint32_t flags; +} intr_type_desc_t; + +static intr_type_desc_t intr_type_descs[MAX_INTR_TYPES]; + +/******************************************************************************* + * This function validates the interrupt type. + ******************************************************************************/ +static int32_t validate_interrupt_type(uint32_t type) +{ + if ((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_NS) || + (type == INTR_TYPE_EL3)) + return 0; + + return -EINVAL; +} + +/******************************************************************************* +* This function validates the routing model for this type of interrupt + ******************************************************************************/ +static int32_t validate_routing_model(uint32_t type, uint32_t flags) +{ + uint32_t rm_flags = (flags >> INTR_RM_FLAGS_SHIFT) & INTR_RM_FLAGS_MASK; + + if (type == INTR_TYPE_S_EL1) + return validate_sel1_interrupt_rm(rm_flags); + + if (type == INTR_TYPE_NS) + return validate_ns_interrupt_rm(rm_flags); + + if (type == INTR_TYPE_EL3) + return validate_el3_interrupt_rm(rm_flags); + + return -EINVAL; +} + +/******************************************************************************* + * This function returns the cached copy of the SCR_EL3 which contains the + * routing model (expressed through the IRQ and FIQ bits) for a security state + * which was stored through a call to 'set_routing_model()' earlier. + ******************************************************************************/ +u_register_t get_scr_el3_from_routing_model(uint32_t security_state) +{ + u_register_t scr_el3; + + assert(sec_state_is_valid(security_state)); + scr_el3 = intr_type_descs[INTR_TYPE_NS].scr_el3[security_state]; + scr_el3 |= intr_type_descs[INTR_TYPE_S_EL1].scr_el3[security_state]; + scr_el3 |= intr_type_descs[INTR_TYPE_EL3].scr_el3[security_state]; + return scr_el3; +} + +/******************************************************************************* + * This function uses the 'interrupt_type_flags' parameter to obtain the value + * of the trap bit (IRQ/FIQ) in the SCR_EL3 for a security state for this + * interrupt type. It uses it to update the SCR_EL3 in the cpu context and the + * 'intr_type_desc' for that security state. + ******************************************************************************/ +static void set_scr_el3_from_rm(uint32_t type, + uint32_t interrupt_type_flags, + uint32_t security_state) +{ + uint32_t flag, bit_pos; + + flag = get_interrupt_rm_flag(interrupt_type_flags, security_state); + bit_pos = plat_interrupt_type_to_line(type, security_state); + intr_type_descs[type].scr_el3[security_state] = (u_register_t)flag << bit_pos; + + /* + * Update scr_el3 only if there is a context available. If not, it + * will be updated later during context initialization which will obtain + * the scr_el3 value to be used via get_scr_el3_from_routing_model() + */ + if (cm_get_context(security_state) != NULL) + cm_write_scr_el3_bit(security_state, bit_pos, flag); +} + +/******************************************************************************* + * This function validates the routing model specified in the 'flags' and + * updates internal data structures to reflect the new routing model. It also + * updates the copy of SCR_EL3 for each security state with the new routing + * model in the 'cpu_context' structure for this cpu. + ******************************************************************************/ +int32_t set_routing_model(uint32_t type, uint32_t flags) +{ + int32_t rc; + + rc = validate_interrupt_type(type); + if (rc != 0) + return rc; + + rc = validate_routing_model(type, flags); + if (rc != 0) + return rc; + + /* Update the routing model in internal data structures */ + intr_type_descs[type].flags = flags; + set_scr_el3_from_rm(type, flags, SECURE); + set_scr_el3_from_rm(type, flags, NON_SECURE); + + return 0; +} + +/****************************************************************************** + * This function disables the routing model of interrupt 'type' from the + * specified 'security_state' on the local core. The disable is in effect + * till the core powers down or till the next enable for that interrupt + * type. + *****************************************************************************/ +int disable_intr_rm_local(uint32_t type, uint32_t security_state) +{ + uint32_t bit_pos, flag; + + assert(intr_type_descs[type].handler != NULL); + + flag = get_interrupt_rm_flag(INTR_DEFAULT_RM, security_state); + + bit_pos = plat_interrupt_type_to_line(type, security_state); + cm_write_scr_el3_bit(security_state, bit_pos, flag); + + return 0; +} + +/****************************************************************************** + * This function enables the routing model of interrupt 'type' from the + * specified 'security_state' on the local core. + *****************************************************************************/ +int enable_intr_rm_local(uint32_t type, uint32_t security_state) +{ + uint32_t bit_pos, flag; + + assert(intr_type_descs[type].handler != NULL); + + flag = get_interrupt_rm_flag(intr_type_descs[type].flags, + security_state); + + bit_pos = plat_interrupt_type_to_line(type, security_state); + cm_write_scr_el3_bit(security_state, bit_pos, flag); + + return 0; +} + +/******************************************************************************* + * This function registers a handler for the 'type' of interrupt specified. It + * also validates the routing model specified in the 'flags' for this type of + * interrupt. + ******************************************************************************/ +int32_t register_interrupt_type_handler(uint32_t type, + interrupt_type_handler_t handler, + uint32_t flags) +{ + int32_t rc; + + /* Validate the 'handler' parameter */ + if (handler == NULL) + return -EINVAL; + + /* Validate the 'flags' parameter */ + if ((flags & INTR_TYPE_FLAGS_MASK) != 0U) + return -EINVAL; + + /* Check if a handler has already been registered */ + if (intr_type_descs[type].handler != NULL) + return -EALREADY; + + rc = set_routing_model(type, flags); + if (rc != 0) + return rc; + + /* Save the handler */ + intr_type_descs[type].handler = handler; + + return 0; +} + +/******************************************************************************* + * This function is called when an interrupt is generated and returns the + * handler for the interrupt type (if registered). It returns NULL if the + * interrupt type is not supported or its handler has not been registered. + ******************************************************************************/ +interrupt_type_handler_t get_interrupt_type_handler(uint32_t type) +{ + if (validate_interrupt_type(type) != 0) + return NULL; + + return intr_type_descs[type].handler; +} + diff --git a/arm-trusted-firmware/bl32/optee/optee.mk b/arm-trusted-firmware/bl32/optee/optee.mk new file mode 100644 index 0000000..c8aa7ce --- /dev/null +++ b/arm-trusted-firmware/bl32/optee/optee.mk @@ -0,0 +1,15 @@ +# +# Copyright (c) 2016-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# This makefile only aims at complying with Trusted Firmware-A build process so +# that "optee" is a valid TF-A AArch32 Secure Playload identifier. + +ifneq ($(ARCH),aarch32) +$(error This directory targets AArch32 support) +endif + +$(eval $(call add_define,AARCH32_SP_OPTEE)) + +$(info Trusted Firmware-A built for OP-TEE payload support) diff --git a/arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S b/arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S new file mode 100644 index 0000000..39f1065 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2016-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 + + .globl sp_min_vector_table + .globl sp_min_entrypoint + .globl sp_min_warm_entrypoint + .globl sp_min_handle_smc + .globl sp_min_handle_fiq + +#define FIXUP_SIZE ((BL32_LIMIT) - (BL32_BASE)) + + .macro route_fiq_to_sp_min reg + /* ----------------------------------------------------- + * FIQs are secure interrupts trapped by Monitor and non + * secure is not allowed to mask the FIQs. + * ----------------------------------------------------- + */ + ldcopr \reg, SCR + orr \reg, \reg, #SCR_FIQ_BIT + bic \reg, \reg, #SCR_FW_BIT + stcopr \reg, SCR + .endm + + .macro clrex_on_monitor_entry +#if (ARM_ARCH_MAJOR == 7) + /* + * ARMv7 architectures need to clear the exclusive access when + * entering Monitor mode. + */ + clrex +#endif + .endm + +vector_base sp_min_vector_table + b sp_min_entrypoint + b plat_panic_handler /* Undef */ + b sp_min_handle_smc /* Syscall */ + b plat_panic_handler /* Prefetch abort */ + b plat_panic_handler /* Data abort */ + b plat_panic_handler /* Reserved */ + b plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ + + +/* + * The Cold boot/Reset entrypoint for SP_MIN + */ +func sp_min_entrypoint +#if !RESET_TO_SP_MIN + /* --------------------------------------------------------------- + * Preceding bootloader has populated r0 with a pointer to a + * 'bl_params_t' structure & r1 with a pointer to platform + * specific structure + * --------------------------------------------------------------- + */ + mov r9, r0 + mov r10, r1 + mov r11, r2 + mov r12, r3 + + /* --------------------------------------------------------------------- + * For !RESET_TO_SP_MIN systems, only the primary CPU ever reaches + * sp_min_entrypoint() during the cold boot flow, so the cold/warm boot + * and primary/secondary CPU logic should not be executed in this case. + * + * Also, assume that the previous bootloader has already initialised the + * SCTLR, including the CPU endianness, and has initialised the memory. + * --------------------------------------------------------------------- + */ + el3_entrypoint_common \ + _init_sctlr=0 \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=1 \ + _exception_vectors=sp_min_vector_table \ + _pie_fixup_size=FIXUP_SIZE + + /* --------------------------------------------------------------------- + * Relay the previous bootloader's arguments to the platform layer + * --------------------------------------------------------------------- + */ +#else + /* --------------------------------------------------------------------- + * For RESET_TO_SP_MIN systems which have a programmable reset address, + * sp_min_entrypoint() is executed only on the cold boot path so we can + * skip the warm boot mailbox mechanism. + * --------------------------------------------------------------------- + */ + 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=sp_min_vector_table \ + _pie_fixup_size=FIXUP_SIZE + + /* --------------------------------------------------------------------- + * For RESET_TO_SP_MIN systems, BL32 (SP_MIN) is the first bootloader + * to run so there's no argument to relay from a previous bootloader. + * Zero the arguments passed to the platform layer to reflect that. + * --------------------------------------------------------------------- + */ + mov r9, #0 + mov r10, #0 + mov r11, #0 + mov r12, #0 + +#endif /* RESET_TO_SP_MIN */ + +#if SP_MIN_WITH_SECURE_FIQ + route_fiq_to_sp_min r4 +#endif + + mov r0, r9 + mov r1, r10 + mov r2, r11 + mov r3, r12 + bl sp_min_early_platform_setup2 + bl sp_min_plat_arch_setup + + /* Jump to the main function */ + bl sp_min_main + + /* ------------------------------------------------------------- + * Clean the .data & .bss sections to main memory. This ensures + * that any global data which was initialised by the primary CPU + * is visible to secondary CPUs before they enable their data + * caches and participate in coherency. + * ------------------------------------------------------------- + */ + ldr r0, =__DATA_START__ + ldr r1, =__DATA_END__ + sub r1, r1, r0 + bl clean_dcache_range + + ldr r0, =__BSS_START__ + ldr r1, =__BSS_END__ + sub r1, r1, r0 + bl clean_dcache_range + + bl smc_get_next_ctx + + /* r0 points to `smc_ctx_t` */ + /* The PSCI cpu_context registers have been copied to `smc_ctx_t` */ + b sp_min_exit +endfunc sp_min_entrypoint + + +/* + * SMC handling function for SP_MIN. + */ +func sp_min_handle_smc + /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ + str lr, [sp, #SMC_CTX_LR_MON] + +#if ENABLE_RUNTIME_INSTRUMENTATION + /* + * Read the timestamp value and store it on top of the C runtime stack. + * The value will be saved to the per-cpu data once the C stack is + * available, as a valid stack is needed to call _cpu_data() + */ + strd r0, r1, [sp, #SMC_CTX_GPREG_R0] + ldcopr16 r0, r1, CNTPCT_64 + ldr lr, [sp, #SMC_CTX_SP_MON] + strd r0, r1, [lr, #-8]! + str lr, [sp, #SMC_CTX_SP_MON] + ldrd r0, r1, [sp, #SMC_CTX_GPREG_R0] +#endif + + smccc_save_gp_mode_regs + + clrex_on_monitor_entry + + /* + * `sp` still points to `smc_ctx_t`. Save it to a register + * and restore the C runtime stack pointer to `sp`. + */ + mov r2, sp /* handle */ + ldr sp, [r2, #SMC_CTX_SP_MON] + +#if ENABLE_RUNTIME_INSTRUMENTATION + /* Save handle to a callee saved register */ + mov r6, r2 + + /* + * Restore the timestamp value and store it in per-cpu data. The value + * will be extracted from per-cpu data by the C level SMC handler and + * saved to the PMF timestamp region. + */ + ldrd r4, r5, [sp], #8 + bl _cpu_data + strd r4, r5, [r0, #CPU_DATA_PMF_TS0_OFFSET] + + /* Restore handle */ + mov r2, r6 +#endif + + ldr r0, [r2, #SMC_CTX_SCR] + and r3, r0, #SCR_NS_BIT /* flags */ + + /* Switch to Secure Mode*/ + bic r0, #SCR_NS_BIT + stcopr r0, SCR + isb + + ldr r0, [r2, #SMC_CTX_GPREG_R0] /* smc_fid */ + /* Check whether an SMC64 is issued */ + tst r0, #(FUNCID_CC_MASK << FUNCID_CC_SHIFT) + beq 1f + /* SMC32 is not detected. Return error back to caller */ + mov r0, #SMC_UNK + str r0, [r2, #SMC_CTX_GPREG_R0] + mov r0, r2 + b sp_min_exit +1: + /* SMC32 is detected */ + mov r1, #0 /* cookie */ + bl handle_runtime_svc + + /* `r0` points to `smc_ctx_t` */ + b sp_min_exit +endfunc sp_min_handle_smc + +/* + * Secure Interrupts handling function for SP_MIN. + */ +func sp_min_handle_fiq +#if !SP_MIN_WITH_SECURE_FIQ + b plat_panic_handler +#else + /* FIQ has a +4 offset for lr compared to preferred return address */ + sub lr, lr, #4 + /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ + str lr, [sp, #SMC_CTX_LR_MON] + + smccc_save_gp_mode_regs + + clrex_on_monitor_entry + + /* load run-time stack */ + mov r2, sp + ldr sp, [r2, #SMC_CTX_SP_MON] + + /* Switch to Secure Mode */ + ldr r0, [r2, #SMC_CTX_SCR] + bic r0, #SCR_NS_BIT + stcopr r0, SCR + isb + + push {r2, r3} + bl sp_min_fiq + pop {r0, r3} + + b sp_min_exit +#endif +endfunc sp_min_handle_fiq + +/* + * The Warm boot entrypoint for SP_MIN. + */ +func sp_min_warm_entrypoint +#if ENABLE_RUNTIME_INSTRUMENTATION + /* + * This timestamp update happens with cache off. The next + * timestamp collection will need to do cache maintenance prior + * to timestamp update. + */ + pmf_calc_timestamp_addr rt_instr_svc, RT_INSTR_EXIT_HW_LOW_PWR + ldcopr16 r2, r3, CNTPCT_64 + strd r2, r3, [r0] +#endif + /* + * On the warm boot path, most of the EL3 initialisations performed by + * 'el3_entrypoint_common' must be skipped: + * + * - Only when the platform bypasses the BL1/BL32 (SP_MIN) entrypoint by + * programming the reset address do we need to initialied the SCTLR. + * In other cases, we assume this has been taken care by the + * entrypoint code. + * + * - No need to determine the type of boot, we know it is a warm boot. + * + * - Do not try to distinguish between primary and secondary CPUs, this + * notion only exists for a cold boot. + * + * - No need to initialise the memory or the C runtime environment, + * it has been done once and for all on the cold boot path. + */ + el3_entrypoint_common \ + _init_sctlr=PROGRAMMABLE_RESET_ADDRESS \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=0 \ + _exception_vectors=sp_min_vector_table \ + _pie_fixup_size=0 + + /* + * We're about to enable MMU and participate in PSCI state coordination. + * + * The PSCI implementation invokes platform routines that enable CPUs to + * participate in coherency. On a system where CPUs are not + * cache-coherent without appropriate platform specific programming, + * having caches enabled until such time might lead to coherency issues + * (resulting from stale data getting speculatively fetched, among + * others). Therefore we keep data caches disabled even after enabling + * the MMU for such platforms. + * + * On systems with hardware-assisted coherency, or on single cluster + * platforms, such platform specific programming is not required to + * enter coherency (as CPUs already are); and there's no reason to have + * caches disabled either. + */ +#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY + mov r0, #0 +#else + mov r0, #DISABLE_DCACHE +#endif + bl bl32_plat_enable_mmu + +#if SP_MIN_WITH_SECURE_FIQ + route_fiq_to_sp_min r0 +#endif + + bl sp_min_warm_boot + bl smc_get_next_ctx + /* r0 points to `smc_ctx_t` */ + /* The PSCI cpu_context registers have been copied to `smc_ctx_t` */ + +#if ENABLE_RUNTIME_INSTRUMENTATION + /* Save smc_ctx_t */ + mov r5, r0 + + pmf_calc_timestamp_addr rt_instr_svc, RT_INSTR_EXIT_PSCI + mov r4, r0 + + /* + * Invalidate before updating timestamp to ensure previous timestamp + * updates on the same cache line with caches disabled are properly + * seen by the same core. Without the cache invalidate, the core might + * write into a stale cache line. + */ + mov r1, #PMF_TS_SIZE + bl inv_dcache_range + + ldcopr16 r0, r1, CNTPCT_64 + strd r0, r1, [r4] + + /* Restore smc_ctx_t */ + mov r0, r5 +#endif + + b sp_min_exit +endfunc sp_min_warm_entrypoint + +/* + * The function to restore the registers from SMC context and return + * to the mode restored to SPSR. + * + * Arguments : r0 must point to the SMC context to restore from. + */ +func sp_min_exit + monitor_exit +endfunc sp_min_exit diff --git a/arm-trusted-firmware/bl32/sp_min/sp_min.ld.S b/arm-trusted-firmware/bl32/sp_min/sp_min.ld.S new file mode 100644 index 0000000..475affa --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/sp_min.ld.S @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(elf32-littlearm) +OUTPUT_ARCH(arm) +ENTRY(sp_min_vector_table) + +MEMORY { + RAM (rwx): ORIGIN = BL32_BASE, LENGTH = BL32_LIMIT - BL32_BASE +} + +#ifdef PLAT_SP_MIN_EXTRA_LD_SCRIPT +#include +#endif + +SECTIONS +{ + . = BL32_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL32_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *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 + + /* Place pubsub sections for events */ + . = ALIGN(8); +#include + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* Place pubsub sections for events */ + . = ALIGN(8); +#include + + *(.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 + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + RELA_SECTION >RAM + +#ifdef BL32_PROGBITS_LIMIT + ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.") +#endif + + STACK_SECTION >RAM + BSS_SECTION >RAM + XLAT_TABLE_SECTION >RAM + + __BSS_SIZE__ = SIZEOF(.bss); + +#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__ = .; + /* + * Bakery locks are stored in coherent memory + * + * Each lock's data is contiguous and fully allocated by the compiler + */ + *(bakery_lock) + *(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 + + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + /* + * Define a linker symbol to mark the end of the RW memory area for this + * image. + */ + __RW_END__ = .; + + __BL32_END__ = .; + + /DISCARD/ : { + *(.dynsym .dynstr .hash .gnu.hash) + } + + ASSERT(. <= BL32_LIMIT, "BL32 image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl32/sp_min/sp_min.mk b/arm-trusted-firmware/bl32/sp_min/sp_min.mk new file mode 100644 index 0000000..590b032 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/sp_min.mk @@ -0,0 +1,73 @@ +# +# Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH}, aarch32) + $(error SP_MIN is only supported on AArch32 platforms) +endif + +include lib/extensions/amu/amu.mk +include lib/psci/psci_lib.mk + +INCLUDES += -Iinclude/bl32/sp_min + +BL32_SOURCES += bl32/sp_min/sp_min_main.c \ + bl32/sp_min/aarch32/entrypoint.S \ + common/runtime_svc.c \ + plat/common/aarch32/plat_sp_min_common.c\ + services/std_svc/std_svc_setup.c \ + ${PSCI_LIB_SOURCES} + +ifeq (${DISABLE_MTPMU},1) +BL32_SOURCES += lib/extensions/mtpmu/aarch32/mtpmu.S +endif + +ifeq (${ENABLE_PMF}, 1) +BL32_SOURCES += lib/pmf/pmf_main.c +endif + +ifeq (${ENABLE_AMU},1) +BL32_SOURCES += ${AMU_SOURCES} +endif + +ifeq (${WORKAROUND_CVE_2017_5715},1) +BL32_SOURCES += bl32/sp_min/wa_cve_2017_5715_bpiall.S \ + bl32/sp_min/wa_cve_2017_5715_icache_inv.S +endif + +ifeq (${TRNG_SUPPORT},1) +BL32_SOURCES += services/std_svc/trng/trng_main.c \ + services/std_svc/trng/trng_entropy_pool.c +endif + +ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1) +BL32_SOURCES += lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c +endif + +ifeq (${ENABLE_TRF_FOR_NS},1) +BL32_SOURCES += lib/extensions/trf/aarch32/trf.c +endif + +BL32_LINKERFILE := bl32/sp_min/sp_min.ld.S + +# Include the platform-specific SP_MIN Makefile +# If no platform-specific SP_MIN Makefile exists, it means SP_MIN is not supported +# on this platform. +SP_MIN_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/sp_min/sp_min-${PLAT}.mk) +ifeq (,${SP_MIN_PLAT_MAKEFILE}) + $(error SP_MIN is not supported on platform ${PLAT}) +else + include ${SP_MIN_PLAT_MAKEFILE} +endif + +RESET_TO_SP_MIN := 0 +$(eval $(call add_define,RESET_TO_SP_MIN)) +$(eval $(call assert_boolean,RESET_TO_SP_MIN)) + +# Flag to allow SP_MIN to handle FIQ interrupts in monitor mode. The platform +# port is free to override this value. It is default disabled. +SP_MIN_WITH_SECURE_FIQ ?= 0 +$(eval $(call add_define,SP_MIN_WITH_SECURE_FIQ)) +$(eval $(call assert_boolean,SP_MIN_WITH_SECURE_FIQ)) diff --git a/arm-trusted-firmware/bl32/sp_min/sp_min_main.c b/arm-trusted-firmware/bl32/sp_min/sp_min_main.c new file mode 100644 index 0000000..f050160 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/sp_min_main.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2016-2019, 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 +#include +#include +#include +#include +#include +#include +#include + +#include "sp_min_private.h" + +#if ENABLE_RUNTIME_INSTRUMENTATION +PMF_REGISTER_SERVICE_SMC(rt_instr_svc, PMF_RT_INSTR_SVC_ID, + RT_INSTR_TOTAL_IDS, PMF_STORE_ENABLE) +#endif + +/* Pointers to per-core cpu contexts */ +static void *sp_min_cpu_ctx_ptr[PLATFORM_CORE_COUNT]; + +/* SP_MIN only stores the non secure smc context */ +static smc_ctx_t sp_min_smc_context[PLATFORM_CORE_COUNT]; + +/****************************************************************************** + * Define the smccc helper library APIs + *****************************************************************************/ +void *smc_get_ctx(unsigned int security_state) +{ + assert(security_state == NON_SECURE); + return &sp_min_smc_context[plat_my_core_pos()]; +} + +void smc_set_next_ctx(unsigned int security_state) +{ + assert(security_state == NON_SECURE); + /* SP_MIN stores only non secure smc context. Nothing to do here */ +} + +void *smc_get_next_ctx(void) +{ + return &sp_min_smc_context[plat_my_core_pos()]; +} + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * for the calling CPU that was set as the context for the specified security + * state. NULL is returned if no such structure has been specified. + ******************************************************************************/ +void *cm_get_context(uint32_t security_state) +{ + assert(security_state == NON_SECURE); + return sp_min_cpu_ctx_ptr[plat_my_core_pos()]; +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state for the calling CPU + ******************************************************************************/ +void cm_set_context(void *context, uint32_t security_state) +{ + assert(security_state == NON_SECURE); + sp_min_cpu_ctx_ptr[plat_my_core_pos()] = context; +} + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * for the CPU identified by `cpu_idx` that was set as the context for the + * specified security state. NULL is returned if no such structure has been + * specified. + ******************************************************************************/ +void *cm_get_context_by_index(unsigned int cpu_idx, + unsigned int security_state) +{ + assert(security_state == NON_SECURE); + return sp_min_cpu_ctx_ptr[cpu_idx]; +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state for the CPU identified by CPU index. + ******************************************************************************/ +void cm_set_context_by_index(unsigned int cpu_idx, void *context, + unsigned int security_state) +{ + assert(security_state == NON_SECURE); + sp_min_cpu_ctx_ptr[cpu_idx] = context; +} + +static void copy_cpu_ctx_to_smc_stx(const regs_t *cpu_reg_ctx, + smc_ctx_t *next_smc_ctx) +{ + next_smc_ctx->r0 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R0); + next_smc_ctx->r1 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R1); + next_smc_ctx->r2 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R2); + next_smc_ctx->lr_mon = read_ctx_reg(cpu_reg_ctx, CTX_LR); + next_smc_ctx->spsr_mon = read_ctx_reg(cpu_reg_ctx, CTX_SPSR); + next_smc_ctx->scr = read_ctx_reg(cpu_reg_ctx, CTX_SCR); +} + +/******************************************************************************* + * This function invokes the PSCI library interface to initialize the + * non secure cpu context and copies the relevant cpu context register values + * to smc context. These registers will get programmed during `smc_exit`. + ******************************************************************************/ +static void sp_min_prepare_next_image_entry(void) +{ + entry_point_info_t *next_image_info; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + u_register_t ns_sctlr; + + /* Program system registers to proceed to non-secure */ + next_image_info = sp_min_plat_get_bl33_ep_info(); + assert(next_image_info); + assert(NON_SECURE == GET_SECURITY_STATE(next_image_info->h.attr)); + + INFO("SP_MIN: Preparing exit to normal world\n"); + + psci_prepare_next_non_secure_ctx(next_image_info); + smc_set_next_ctx(NON_SECURE); + + /* Copy r0, lr and spsr from cpu context to SMC context */ + copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)), + smc_get_next_ctx()); + + /* Temporarily set the NS bit to access NS SCTLR */ + write_scr(read_scr() | SCR_NS_BIT); + isb(); + ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR); + write_sctlr(ns_sctlr); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); +} + +/****************************************************************************** + * Implement the ARM Standard Service function to get arguments for a + * particular service. + *****************************************************************************/ +uintptr_t get_arm_std_svc_args(unsigned int svc_mask) +{ + /* Setup the arguments for PSCI Library */ + DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, sp_min_warm_entrypoint); + + /* PSCI is the only ARM Standard Service implemented */ + assert(svc_mask == PSCI_FID_MASK); + + return (uintptr_t)&psci_args; +} + +/****************************************************************************** + * The SP_MIN main function. Do the platform and PSCI Library setup. Also + * initialize the runtime service framework. + *****************************************************************************/ +void sp_min_main(void) +{ + NOTICE("SP_MIN: %s\n", version_string); + NOTICE("SP_MIN: %s\n", build_message); + + /* Perform the SP_MIN platform setup */ + sp_min_platform_setup(); + + /* Initialize the runtime services e.g. psci */ + INFO("SP_MIN: Initializing runtime services\n"); + runtime_svc_init(); + + /* + * We are ready to enter the next EL. Prepare entry into the image + * corresponding to the desired security state after the next ERET. + */ + sp_min_prepare_next_image_entry(); + + /* + * Perform any platform specific runtime setup prior to cold boot exit + * from SP_MIN. + */ + sp_min_plat_runtime_setup(); + + console_flush(); +} + +/****************************************************************************** + * This function is invoked during warm boot. Invoke the PSCI library + * warm boot entry point which takes care of Architectural and platform setup/ + * restore. Copy the relevant cpu_context register values to smc context which + * will get programmed during `smc_exit`. + *****************************************************************************/ +void sp_min_warm_boot(void) +{ + smc_ctx_t *next_smc_ctx; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + u_register_t ns_sctlr; + + psci_warmboot_entrypoint(); + + smc_set_next_ctx(NON_SECURE); + + next_smc_ctx = smc_get_next_ctx(); + zeromem(next_smc_ctx, sizeof(smc_ctx_t)); + + copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)), + next_smc_ctx); + + /* Temporarily set the NS bit to access NS SCTLR */ + write_scr(read_scr() | SCR_NS_BIT); + isb(); + ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR); + write_sctlr(ns_sctlr); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); +} + +#if SP_MIN_WITH_SECURE_FIQ +/****************************************************************************** + * This function is invoked on secure interrupts. By construction of the + * SP_MIN, secure interrupts can only be handled when core executes in non + * secure state. + *****************************************************************************/ +void sp_min_fiq(void) +{ + uint32_t id; + + id = plat_ic_acknowledge_interrupt(); + sp_min_plat_fiq_handler(id); + plat_ic_end_of_interrupt(id); +} +#endif /* SP_MIN_WITH_SECURE_FIQ */ diff --git a/arm-trusted-firmware/bl32/sp_min/sp_min_private.h b/arm-trusted-firmware/bl32/sp_min/sp_min_private.h new file mode 100644 index 0000000..628581a --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/sp_min_private.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SP_MIN_PRIVATE_H +#define SP_MIN_PRIVATE_H + +void sp_min_main(void); +void sp_min_warm_boot(void); +void sp_min_fiq(void); + +#endif /* SP_MIN_PRIVATE_H */ diff --git a/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S b/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S new file mode 100644 index 0000000..385f3d4 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl wa_cve_2017_5715_bpiall_vbar + +vector_base wa_cve_2017_5715_bpiall_vbar + /* We encode the exception entry in the bottom 3 bits of SP */ + add sp, sp, #1 /* Reset: 0b111 */ + add sp, sp, #1 /* Undef: 0b110 */ + add sp, sp, #1 /* Syscall: 0b101 */ + add sp, sp, #1 /* Prefetch abort: 0b100 */ + add sp, sp, #1 /* Data abort: 0b011 */ + add sp, sp, #1 /* Reserved: 0b010 */ + add sp, sp, #1 /* IRQ: 0b001 */ + nop /* FIQ: 0b000 */ + + /* + * Invalidate the branch predictor, `r0` is a dummy register + * and is unused. + */ + stcopr r0, BPIALL + isb + + /* + * As we cannot use any temporary registers and cannot + * clobber SP, we can decode the exception entry using + * an unrolled binary search. + * + * Note, if this code is re-used by other secure payloads, + * the below exception entry vectors must be changed to + * the vectors specific to that secure payload. + */ + + tst sp, #4 + bne 1f + + tst sp, #2 + bne 3f + + /* Expected encoding: 0x1 and 0x0 */ + tst sp, #1 + /* Restore original value of SP by clearing the bottom 3 bits */ + bic sp, sp, #0x7 + bne plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ + +1: + tst sp, #2 + bne 2f + + /* Expected encoding: 0x4 and 0x5 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_handle_smc /* Syscall */ + b plat_panic_handler /* Prefetch abort */ + +2: + /* Expected encoding: 0x7 and 0x6 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_entrypoint /* Reset */ + b plat_panic_handler /* Undef */ + +3: + /* Expected encoding: 0x2 and 0x3 */ + tst sp, #1 + bic sp, sp, #0x7 + bne plat_panic_handler /* Data abort */ + b plat_panic_handler /* Reserved */ diff --git a/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S b/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S new file mode 100644 index 0000000..d0a4625 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl wa_cve_2017_5715_icache_inv_vbar + +vector_base wa_cve_2017_5715_icache_inv_vbar + /* We encode the exception entry in the bottom 3 bits of SP */ + add sp, sp, #1 /* Reset: 0b111 */ + add sp, sp, #1 /* Undef: 0b110 */ + add sp, sp, #1 /* Syscall: 0b101 */ + add sp, sp, #1 /* Prefetch abort: 0b100 */ + add sp, sp, #1 /* Data abort: 0b011 */ + add sp, sp, #1 /* Reserved: 0b010 */ + add sp, sp, #1 /* IRQ: 0b001 */ + nop /* FIQ: 0b000 */ + + /* + * Invalidate the instruction cache, which we assume also + * invalidates the branch predictor. This may depend on + * other CPU specific changes (e.g. an ACTLR setting). + */ + stcopr r0, ICIALLU + isb + + /* + * As we cannot use any temporary registers and cannot + * clobber SP, we can decode the exception entry using + * an unrolled binary search. + * + * Note, if this code is re-used by other secure payloads, + * the below exception entry vectors must be changed to + * the vectors specific to that secure payload. + */ + + tst sp, #4 + bne 1f + + tst sp, #2 + bne 3f + + /* Expected encoding: 0x1 and 0x0 */ + tst sp, #1 + /* Restore original value of SP by clearing the bottom 3 bits */ + bic sp, sp, #0x7 + bne plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ + +1: + /* Expected encoding: 0x4 and 0x5 */ + tst sp, #2 + bne 2f + + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_handle_smc /* Syscall */ + b plat_panic_handler /* Prefetch abort */ + +2: + /* Expected encoding: 0x7 and 0x6 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_entrypoint /* Reset */ + b plat_panic_handler /* Undef */ + +3: + /* Expected encoding: 0x2 and 0x3 */ + tst sp, #1 + bic sp, sp, #0x7 + bne plat_panic_handler /* Data abort */ + b plat_panic_handler /* Reserved */ diff --git a/arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S new file mode 100644 index 0000000..7d77f47 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include "../tsp_private.h" + + + .globl tsp_entrypoint + .globl tsp_vector_table + + + + /* --------------------------------------------- + * Populate the params in x0-x7 from the pointer + * to the smc args structure in x0. + * --------------------------------------------- + */ + .macro restore_args_call_smc + ldp x6, x7, [x0, #TSP_ARG6] + ldp x4, x5, [x0, #TSP_ARG4] + ldp x2, x3, [x0, #TSP_ARG2] + ldp x0, x1, [x0, #TSP_ARG0] + smc #0 + .endm + + .macro save_eret_context reg1 reg2 + mrs \reg1, elr_el1 + mrs \reg2, spsr_el1 + stp \reg1, \reg2, [sp, #-0x10]! + stp x30, x18, [sp, #-0x10]! + .endm + + .macro restore_eret_context reg1 reg2 + ldp x30, x18, [sp], #0x10 + ldp \reg1, \reg2, [sp], #0x10 + msr elr_el1, \reg1 + msr spsr_el1, \reg2 + .endm + +func tsp_entrypoint _align=3 + +#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, (BL32_LIMIT - BL32_BASE) + add x1, x1, x0 + bl fixup_gdt_reloc +#endif /* ENABLE_PIE */ + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, tsp_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 BL32 + * 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. If PIE + * is enabled however, RO sections including the + * GOT may be modified during pie fixup. + * Therefore, to be on the safe side, invalidate + * the entire image region if PIE is enabled. + * --------------------------------------------- + */ +#if ENABLE_PIE +#if SEPARATE_CODE_AND_RODATA + adrp x0, __TEXT_START__ + add x0, x0, :lo12:__TEXT_START__ +#else + adrp x0, __RO_START__ + add x0, x0, :lo12:__RO_START__ +#endif /* SEPARATE_CODE_AND_RODATA */ +#else + adrp x0, __RW_START__ + add x0, x0, :lo12:__RW_START__ +#endif /* ENABLE_PIE */ + adrp x1, __RW_END__ + add x1, x1, :lo12:__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 TSP setup + * --------------------------------------------- + */ + bl tsp_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl tsp_main + + /* --------------------------------------------- + * Tell TSPD that we are done initialising + * --------------------------------------------- + */ + mov x1, x0 + mov x0, #TSP_ENTRY_DONE + smc #0 + +tsp_entrypoint_panic: + b tsp_entrypoint_panic +endfunc tsp_entrypoint + + + /* ------------------------------------------- + * Table of entrypoint vectors provided to the + * TSPD for the various entrypoints + * ------------------------------------------- + */ +vector_base tsp_vector_table + b tsp_yield_smc_entry + b tsp_fast_smc_entry + b tsp_cpu_on_entry + b tsp_cpu_off_entry + b tsp_cpu_resume_entry + b tsp_cpu_suspend_entry + b tsp_sel1_intr_entry + b tsp_system_off_entry + b tsp_system_reset_entry + b tsp_abort_yield_smc_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is to be turned off through a CPU_OFF + * psci call to ask the TSP to perform any + * bookeeping necessary. In the current + * implementation, the TSPD expects the TSP to + * re-initialise its state so nothing is done + * here except for acknowledging the request. + * --------------------------------------------- + */ +func tsp_cpu_off_entry + bl tsp_cpu_off_main + restore_args_call_smc +endfunc tsp_cpu_off_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when the + * system is about to be switched off (through + * a SYSTEM_OFF psci call) to ask the TSP to + * perform any necessary bookkeeping. + * --------------------------------------------- + */ +func tsp_system_off_entry + bl tsp_system_off_main + restore_args_call_smc +endfunc tsp_system_off_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when the + * system is about to be reset (through a + * SYSTEM_RESET psci call) to ask the TSP to + * perform any necessary bookkeeping. + * --------------------------------------------- + */ +func tsp_system_reset_entry + bl tsp_system_reset_main + restore_args_call_smc +endfunc tsp_system_reset_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is turned on using a CPU_ON psci call to + * ask the TSP to initialise itself i.e. setup + * the mmu, stacks etc. Minimal architectural + * state will be initialised by the TSPD when + * this function is entered i.e. Caches and MMU + * will be turned off, the execution state + * will be aarch64 and exceptions masked. + * --------------------------------------------- + */ +func tsp_cpu_on_entry + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, tsp_exceptions + msr vbar_el1, x0 + isb + + /* Enable the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------- + * Enable the instruction cache, stack pointer + * and data access alignment checks + * --------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el1 + orr x0, x0, x1 + msr sctlr_el1, x0 + isb + + /* -------------------------------------------- + * Give ourselves a stack whose memory will be + * marked as Normal-IS-WBWA when the MMU is + * enabled. + * -------------------------------------------- + */ + bl plat_set_my_stack + + /* -------------------------------------------- + * Enable MMU and D-caches together. + * -------------------------------------------- + */ + mov x0, #0 + bl bl32_plat_enable_mmu + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Enter C runtime to perform any remaining + * book keeping + * --------------------------------------------- + */ + bl tsp_cpu_on_main + restore_args_call_smc + + /* Should never reach here */ +tsp_cpu_on_entry_panic: + b tsp_cpu_on_entry_panic +endfunc tsp_cpu_on_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is to be suspended through a CPU_SUSPEND + * psci call to ask the TSP to perform any + * bookeeping necessary. In the current + * implementation, the TSPD saves and restores + * the EL1 state. + * --------------------------------------------- + */ +func tsp_cpu_suspend_entry + bl tsp_cpu_suspend_main + restore_args_call_smc +endfunc tsp_cpu_suspend_entry + + /*------------------------------------------------- + * This entrypoint is used by the TSPD to pass + * control for `synchronously` handling a S-EL1 + * Interrupt which was triggered while executing + * in normal world. 'x0' contains a magic number + * which indicates this. TSPD expects control to + * be handed back at the end of interrupt + * processing. This is done through an SMC. + * The handover agreement is: + * + * 1. PSTATE.DAIF are set upon entry. 'x1' has + * the ELR_EL3 from the non-secure state. + * 2. TSP has to preserve the callee saved + * general purpose registers, SP_EL1/EL0 and + * LR. + * 3. TSP has to preserve the system and vfp + * registers (if applicable). + * 4. TSP can use 'x0-x18' to enable its C + * runtime. + * 5. TSP returns to TSPD using an SMC with + * 'x0' = TSP_HANDLED_S_EL1_INTR + * ------------------------------------------------ + */ +func tsp_sel1_intr_entry +#if DEBUG + mov_imm x2, TSP_HANDLE_SEL1_INTR_AND_RETURN + cmp x0, x2 + b.ne tsp_sel1_int_entry_panic +#endif + /*------------------------------------------------- + * Save any previous context needed to perform + * an exception return from S-EL1 e.g. context + * from a previous Non secure Interrupt. + * Update statistics and handle the S-EL1 + * interrupt before returning to the TSPD. + * IRQ/FIQs are not enabled since that will + * complicate the implementation. Execution + * will be transferred back to the normal world + * in any case. The handler can return 0 + * if the interrupt was handled or TSP_PREEMPTED + * if the expected interrupt was preempted + * by an interrupt that should be handled in EL3 + * e.g. Group 0 interrupt in GICv3. In both + * the cases switch to EL3 using SMC with id + * TSP_HANDLED_S_EL1_INTR. Any other return value + * from the handler will result in panic. + * ------------------------------------------------ + */ + save_eret_context x2 x3 + bl tsp_update_sync_sel1_intr_stats + bl tsp_common_int_handler + /* Check if the S-EL1 interrupt has been handled */ + cbnz x0, tsp_sel1_intr_check_preemption + b tsp_sel1_intr_return +tsp_sel1_intr_check_preemption: + /* Check if the S-EL1 interrupt has been preempted */ + mov_imm x1, TSP_PREEMPTED + cmp x0, x1 + b.ne tsp_sel1_int_entry_panic +tsp_sel1_intr_return: + mov_imm x0, TSP_HANDLED_S_EL1_INTR + restore_eret_context x2 x3 + smc #0 + + /* Should never reach here */ +tsp_sel1_int_entry_panic: + no_ret plat_panic_handler +endfunc tsp_sel1_intr_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu resumes execution after an earlier + * CPU_SUSPEND psci call to ask the TSP to + * restore its saved context. In the current + * implementation, the TSPD saves and restores + * EL1 state so nothing is done here apart from + * acknowledging the request. + * --------------------------------------------- + */ +func tsp_cpu_resume_entry + bl tsp_cpu_resume_main + restore_args_call_smc + + /* Should never reach here */ + no_ret plat_panic_handler +endfunc tsp_cpu_resume_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD to ask + * the TSP to service a fast smc request. + * --------------------------------------------- + */ +func tsp_fast_smc_entry + bl tsp_smc_handler + restore_args_call_smc + + /* Should never reach here */ + no_ret plat_panic_handler +endfunc tsp_fast_smc_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD to ask + * the TSP to service a Yielding SMC request. + * We will enable preemption during execution + * of tsp_smc_handler. + * --------------------------------------------- + */ +func tsp_yield_smc_entry + msr daifclr, #DAIF_FIQ_BIT | DAIF_IRQ_BIT + bl tsp_smc_handler + msr daifset, #DAIF_FIQ_BIT | DAIF_IRQ_BIT + restore_args_call_smc + + /* Should never reach here */ + no_ret plat_panic_handler +endfunc tsp_yield_smc_entry + + /*--------------------------------------------------------------------- + * This entrypoint is used by the TSPD to abort a pre-empted Yielding + * SMC. It could be on behalf of non-secure world or because a CPU + * suspend/CPU off request needs to abort the preempted SMC. + * -------------------------------------------------------------------- + */ +func tsp_abort_yield_smc_entry + + /* + * Exceptions masking is already done by the TSPD when entering this + * hook so there is no need to do it here. + */ + + /* Reset the stack used by the pre-empted SMC */ + bl plat_set_my_stack + + /* + * Allow some cleanup such as releasing locks. + */ + bl tsp_abort_smc_handler + + restore_args_call_smc + + /* Should never reach here */ + bl plat_panic_handler +endfunc tsp_abort_yield_smc_entry diff --git a/arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S new file mode 100644 index 0000000..4c6a56a --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + /* ---------------------------------------------------- + * The caller-saved registers x0-x18 and LR are saved + * here. + * ---------------------------------------------------- + */ + +#define SCRATCH_REG_SIZE #(20 * 8) + + .macro save_caller_regs_and_lr + sub sp, sp, SCRATCH_REG_SIZE + stp x0, x1, [sp] + stp x2, x3, [sp, #0x10] + stp x4, x5, [sp, #0x20] + stp x6, x7, [sp, #0x30] + stp x8, x9, [sp, #0x40] + stp x10, x11, [sp, #0x50] + stp x12, x13, [sp, #0x60] + stp x14, x15, [sp, #0x70] + stp x16, x17, [sp, #0x80] + stp x18, x30, [sp, #0x90] + .endm + + .macro restore_caller_regs_and_lr + ldp x0, x1, [sp] + ldp x2, x3, [sp, #0x10] + ldp x4, x5, [sp, #0x20] + ldp x6, x7, [sp, #0x30] + ldp x8, x9, [sp, #0x40] + ldp x10, x11, [sp, #0x50] + ldp x12, x13, [sp, #0x60] + ldp x14, x15, [sp, #0x70] + ldp x16, x17, [sp, #0x80] + ldp x18, x30, [sp, #0x90] + add sp, sp, SCRATCH_REG_SIZE + .endm + + /* ---------------------------------------------------- + * Common TSP interrupt handling routine + * ---------------------------------------------------- + */ + .macro handle_tsp_interrupt label + /* Enable the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + save_caller_regs_and_lr + bl tsp_common_int_handler + cbz x0, interrupt_exit_\label + + /* + * This interrupt was not targetted to S-EL1 so send it to + * the monitor and wait for execution to resume. + */ + smc #0 +interrupt_exit_\label: + restore_caller_regs_and_lr + exception_return + .endm + + .globl tsp_exceptions + + /* ----------------------------------------------------- + * TSP exception handlers. + * ----------------------------------------------------- + */ +vector_base tsp_exceptions + /* ----------------------------------------------------- + * Current EL with _sp_el0 : 0x0 - 0x200. No exceptions + * are expected and treated as irrecoverable errors. + * ----------------------------------------------------- + */ +vector_entry sync_exception_sp_el0 + b plat_panic_handler +end_vector_entry sync_exception_sp_el0 + +vector_entry irq_sp_el0 + b plat_panic_handler +end_vector_entry irq_sp_el0 + +vector_entry fiq_sp_el0 + b plat_panic_handler +end_vector_entry fiq_sp_el0 + +vector_entry serror_sp_el0 + b plat_panic_handler +end_vector_entry serror_sp_el0 + + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400. Only IRQs/FIQs + * are expected and handled + * ----------------------------------------------------- + */ +vector_entry sync_exception_sp_elx + b plat_panic_handler +end_vector_entry sync_exception_sp_elx + +vector_entry irq_sp_elx + handle_tsp_interrupt irq_sp_elx +end_vector_entry irq_sp_elx + +vector_entry fiq_sp_elx + handle_tsp_interrupt fiq_sp_elx +end_vector_entry fiq_sp_elx + +vector_entry serror_sp_elx + b plat_panic_handler +end_vector_entry serror_sp_elx + + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600. No exceptions + * are handled since TSP does not implement a lower EL + * ----------------------------------------------------- + */ +vector_entry sync_exception_aarch64 + b plat_panic_handler +end_vector_entry sync_exception_aarch64 + +vector_entry irq_aarch64 + b plat_panic_handler +end_vector_entry irq_aarch64 + +vector_entry fiq_aarch64 + b plat_panic_handler +end_vector_entry fiq_aarch64 + +vector_entry serror_aarch64 + b plat_panic_handler +end_vector_entry serror_aarch64 + + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800. No exceptions + * handled since the TSP does not implement a lower EL. + * ----------------------------------------------------- + */ +vector_entry sync_exception_aarch32 + b plat_panic_handler +end_vector_entry sync_exception_aarch32 + +vector_entry irq_aarch32 + b plat_panic_handler +end_vector_entry irq_aarch32 + +vector_entry fiq_aarch32 + b plat_panic_handler +end_vector_entry fiq_aarch32 + +vector_entry serror_aarch32 + b plat_panic_handler +end_vector_entry serror_aarch32 diff --git a/arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S new file mode 100644 index 0000000..6e238ea --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl tsp_get_magic + +/* + * This function raises an SMC to retrieve arguments from secure + * monitor/dispatcher, saves the returned arguments the array received in x0, + * and then returns to the caller + */ +func tsp_get_magic + /* Load arguments */ + ldr w0, _tsp_fid_get_magic + + /* Raise SMC */ + smc #0 + + /* Return arguments in x1:x0 */ + ret +endfunc tsp_get_magic + + .align 2 +_tsp_fid_get_magic: + .word TSP_GET_ARGS diff --git a/arm-trusted-firmware/bl32/tsp/tsp.ld.S b/arm-trusted-firmware/bl32/tsp/tsp.ld.S new file mode 100644 index 0000000..d86ae55 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp.ld.S @@ -0,0 +1,123 @@ +/* + * 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(tsp_entrypoint) + + +MEMORY { + RAM (rwx): ORIGIN = TSP_SEC_MEM_BASE, LENGTH = TSP_SEC_MEM_SIZE +} + + +SECTIONS +{ + . = BL32_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL32_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *tsp_entrypoint.o(.text*) + *(.text*) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + + RODATA_COMMON + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *tsp_entrypoint.o(.text*) + *(.text*) + *(.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 + RELA_SECTION >RAM + +#ifdef TSP_PROGBITS_LIMIT + ASSERT(. <= TSP_PROGBITS_LIMIT, "TSP progbits has exceeded its limit.") +#endif + + 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 the end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL32_END__ = .; + + /DISCARD/ : { + *(.dynsym .dynstr .hash .gnu.hash) + } + + __BSS_SIZE__ = SIZEOF(.bss); +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= BL32_LIMIT, "BL32 image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl32/tsp/tsp.mk b/arm-trusted-firmware/bl32/tsp/tsp.mk new file mode 100644 index 0000000..3fd6d99 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp.mk @@ -0,0 +1,36 @@ +# +# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +INCLUDES += -Iinclude/bl32/tsp + +BL32_SOURCES += bl32/tsp/tsp_main.c \ + bl32/tsp/aarch64/tsp_entrypoint.S \ + bl32/tsp/aarch64/tsp_exceptions.S \ + bl32/tsp/aarch64/tsp_request.S \ + bl32/tsp/tsp_interrupt.c \ + bl32/tsp/tsp_timer.c \ + common/aarch64/early_exceptions.S \ + lib/locks/exclusive/aarch64/spinlock.S + +BL32_LINKERFILE := bl32/tsp/tsp.ld.S + +# This flag determines if the TSPD initializes BL32 in tspd_init() (synchronous +# method) or configures BL31 to pass control to BL32 instead of BL33 +# (asynchronous method). +TSP_INIT_ASYNC := 0 + +$(eval $(call assert_boolean,TSP_INIT_ASYNC)) +$(eval $(call add_define,TSP_INIT_ASYNC)) + +# Include the platform-specific TSP Makefile +# If no platform-specific TSP Makefile exists, it means TSP is not supported +# on this platform. +TSP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/tsp/tsp-${PLAT}.mk) +ifeq (,${TSP_PLAT_MAKEFILE}) + $(error TSP is not supported on platform ${PLAT}) +else + include ${TSP_PLAT_MAKEFILE} +endif diff --git a/arm-trusted-firmware/bl32/tsp/tsp_interrupt.c b/arm-trusted-firmware/bl32/tsp/tsp_interrupt.c new file mode 100644 index 0000000..430b5dd --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp_interrupt.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include + +#include "tsp_private.h" + +/******************************************************************************* + * This function updates the TSP statistics for S-EL1 interrupts handled + * synchronously i.e the ones that have been handed over by the TSPD. It also + * keeps count of the number of times control was passed back to the TSPD + * after handling the interrupt. In the future it will be possible that the + * TSPD hands over an S-EL1 interrupt to the TSP but does not expect it to + * return execution. This statistic will be useful to distinguish between these + * two models of synchronous S-EL1 interrupt handling. The 'elr_el3' parameter + * contains the address of the instruction in normal world where this S-EL1 + * interrupt was generated. + ******************************************************************************/ +void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3) +{ + uint32_t linear_id = plat_my_core_pos(); + + tsp_stats[linear_id].sync_sel1_intr_count++; + if (type == TSP_HANDLE_SEL1_INTR_AND_RETURN) + tsp_stats[linear_id].sync_sel1_intr_ret_count++; + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + spin_lock(&console_lock); + VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%" PRIx64 "\n", + read_mpidr(), elr_el3); + VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests," + " %d sync s-el1 interrupt returns\n", + read_mpidr(), + tsp_stats[linear_id].sync_sel1_intr_count, + tsp_stats[linear_id].sync_sel1_intr_ret_count); + spin_unlock(&console_lock); +#endif +} + +/****************************************************************************** + * This function is invoked when a non S-EL1 interrupt is received and causes + * the preemption of TSP. This function returns TSP_PREEMPTED and results + * in the control being handed over to EL3 for handling the interrupt. + *****************************************************************************/ +int32_t tsp_handle_preemption(void) +{ + uint32_t linear_id = plat_my_core_pos(); + + tsp_stats[linear_id].preempt_intr_count++; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + spin_lock(&console_lock); + VERBOSE("TSP: cpu 0x%lx: %d preempt interrupt requests\n", + read_mpidr(), tsp_stats[linear_id].preempt_intr_count); + spin_unlock(&console_lock); +#endif + return TSP_PREEMPTED; +} + +/******************************************************************************* + * TSP interrupt handler is called as a part of both synchronous and + * asynchronous handling of TSP interrupts. Currently the physical timer + * interrupt is the only S-EL1 interrupt that this handler expects. It returns + * 0 upon successfully handling the expected interrupt and all other + * interrupts are treated as normal world or EL3 interrupts. + ******************************************************************************/ +int32_t tsp_common_int_handler(void) +{ + uint32_t linear_id = plat_my_core_pos(), id; + + /* + * Get the highest priority pending interrupt id and see if it is the + * secure physical generic timer interrupt in which case, handle it. + * Otherwise throw this interrupt at the EL3 firmware. + * + * There is a small time window between reading the highest priority + * pending interrupt and acknowledging it during which another + * interrupt of higher priority could become the highest pending + * interrupt. This is not expected to happen currently for TSP. + */ + id = plat_ic_get_pending_interrupt_id(); + + /* TSP can only handle the secure physical timer interrupt */ + if (id != TSP_IRQ_SEC_PHY_TIMER) + return tsp_handle_preemption(); + + /* + * Acknowledge and handle the secure timer interrupt. Also sanity check + * if it has been preempted by another interrupt through an assertion. + */ + id = plat_ic_acknowledge_interrupt(); + assert(id == TSP_IRQ_SEC_PHY_TIMER); + tsp_generic_timer_handler(); + plat_ic_end_of_interrupt(id); + + /* Update the statistics and print some messages */ + tsp_stats[linear_id].sel1_intr_count++; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + spin_lock(&console_lock); + VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %d\n", + read_mpidr(), id); + VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n", + read_mpidr(), tsp_stats[linear_id].sel1_intr_count); + spin_unlock(&console_lock); +#endif + return 0; +} diff --git a/arm-trusted-firmware/bl32/tsp/tsp_main.c b/arm-trusted-firmware/bl32/tsp/tsp_main.c new file mode 100644 index 0000000..522c1b4 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp_main.c @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2013-2022, 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 "tsp_private.h" + + +/******************************************************************************* + * Lock to control access to the console + ******************************************************************************/ +spinlock_t console_lock; + +/******************************************************************************* + * Per cpu data structure to populate parameters for an SMC in C code and use + * a pointer to this structure in assembler code to populate x0-x7 + ******************************************************************************/ +static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Per cpu data structure to keep track of TSP activity + ******************************************************************************/ +work_statistics_t tsp_stats[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * The TSP memory footprint starts at address BL32_BASE and ends with the + * linker symbol __BL32_END__. Use these addresses to compute the TSP image + * size. + ******************************************************************************/ +#define BL32_TOTAL_LIMIT BL32_END +#define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE) + +static tsp_args_t *set_smc_args(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id; + tsp_args_t *pcpu_smc_args; + + /* + * Return to Secure Monitor by raising an SMC. The results of the + * service are passed as an arguments to the SMC + */ + linear_id = plat_my_core_pos(); + pcpu_smc_args = &tsp_smc_args[linear_id]; + write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0); + write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1); + write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2); + write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3); + write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4); + write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5); + write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6); + write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7); + + return pcpu_smc_args; +} + +/******************************************************************************* + * Setup function for TSP. + ******************************************************************************/ +void tsp_setup(void) +{ + /* Perform early platform-specific setup */ + tsp_early_platform_setup(); + + /* Perform late platform-specific setup */ + tsp_plat_arch_setup(); + +#if ENABLE_PAUTH + /* + * 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 /* ENABLE_PAUTH */ +} + +/******************************************************************************* + * TSP main entry point where it gets the opportunity to initialize its secure + * state/applications. Once the state is initialized, it must return to the + * SPD with a pointer to the 'tsp_vector_table' jump table. + ******************************************************************************/ +uint64_t tsp_main(void) +{ + NOTICE("TSP: %s\n", version_string); + NOTICE("TSP: %s\n", build_message); + INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE); + INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE); + + uint32_t linear_id = plat_my_core_pos(); + + /* Initialize the platform */ + tsp_platform_setup(); + + /* Initialize secure/applications state here */ + tsp_generic_timer_start(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_on_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_on_count); + spin_unlock(&console_lock); +#endif + return (uint64_t) &tsp_vector_table; +} + +/******************************************************************************* + * This function performs any remaining book keeping in the test secure payload + * after this cpu's architectural state has been setup in response to an earlier + * psci cpu_on request. + ******************************************************************************/ +tsp_args_t *tsp_cpu_on_main(void) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* Initialize secure/applications state here */ + tsp_generic_timer_start(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_on_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx turned on\n", read_mpidr()); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_on_count); + spin_unlock(&console_lock); +#endif + /* Indicate to the SPD that we have completed turned ourselves on */ + return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any remaining book keeping in the test secure payload + * before this cpu is turned off in response to a psci cpu_off request. + ******************************************************************************/ +tsp_args_t *tsp_cpu_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* + * This cpu is being turned off, so disable the timer to prevent the + * secure timer interrupt from interfering with power down. A pending + * interrupt will be lost but we do not care as we are turning off. + */ + tsp_generic_timer_stop(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_off_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx off request\n", read_mpidr()); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_off_count); + spin_unlock(&console_lock); +#endif + + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any book keeping in the test secure payload before + * this cpu's architectural state is saved in response to an earlier psci + * cpu_suspend request. + ******************************************************************************/ +tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* + * Save the time context and disable it to prevent the secure timer + * interrupt from interfering with wakeup from the suspend state. + */ + tsp_generic_timer_save(); + tsp_generic_timer_stop(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_suspend_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_suspend_count); + spin_unlock(&console_lock); +#endif + + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any book keeping in the test secure payload after this + * cpu's architectural state has been restored after wakeup from an earlier psci + * cpu_suspend request. + ******************************************************************************/ +tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* Restore the generic timer context */ + tsp_generic_timer_restore(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_resume_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n", + read_mpidr(), max_off_pwrlvl); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_resume_count); + spin_unlock(&console_lock); +#endif + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any remaining bookkeeping in the test secure payload + * before the system is switched off (in response to a psci SYSTEM_OFF request) + ******************************************************************************/ +tsp_args_t *tsp_system_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr()); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count); + spin_unlock(&console_lock); +#endif + + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_SYSTEM_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any remaining bookkeeping in the test secure payload + * before the system is reset (in response to a psci SYSTEM_RESET request) + ******************************************************************************/ +tsp_args_t *tsp_system_reset_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr()); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count); + spin_unlock(&console_lock); +#endif + + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * TSP fast smc handler. The secure monitor jumps to this function by + * doing the ERET after populating X0-X7 registers. The arguments are received + * in the function arguments in order. Once the service is rendered, this + * function returns to Secure Monitor by raising SMC. + ******************************************************************************/ +tsp_args_t *tsp_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint128_t service_args; + uint64_t service_arg0; + uint64_t service_arg1; + uint64_t results[2]; + uint32_t linear_id = plat_my_core_pos(); + u_register_t dit; + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx received %s smc 0x%" PRIx64 "\n", read_mpidr(), + ((func >> 31) & 1) == 1 ? "fast" : "yielding", + func); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count); + spin_unlock(&console_lock); +#endif + + /* Render secure services and obtain results here */ + results[0] = arg1; + results[1] = arg2; + + /* + * Request a service back from dispatcher/secure monitor. + * This call returns and thereafter resumes execution. + */ + service_args = tsp_get_magic(); + service_arg0 = (uint64_t)service_args; + service_arg1 = (uint64_t)(service_args >> 64U); + +#if CTX_INCLUDE_MTE_REGS + /* + * Write a dummy value to an MTE register, to simulate usage in the + * secure world + */ + write_gcr_el1(0x99); +#endif + + /* Determine the function to perform based on the function ID */ + switch (TSP_BARE_FID(func)) { + case TSP_ADD: + results[0] += service_arg0; + results[1] += service_arg1; + break; + case TSP_SUB: + results[0] -= service_arg0; + results[1] -= service_arg1; + break; + case TSP_MUL: + results[0] *= service_arg0; + results[1] *= service_arg1; + break; + case TSP_DIV: + results[0] /= service_arg0 ? service_arg0 : 1; + results[1] /= service_arg1 ? service_arg1 : 1; + break; + case TSP_CHECK_DIT: + if (!is_armv8_4_dit_present()) { +#if LOG_LEVEL >= LOG_LEVEL_ERROR + spin_lock(&console_lock); + ERROR("DIT not supported\n"); + spin_unlock(&console_lock); +#endif + results[0] = 0; + results[1] = 0xffff; + break; + } + dit = read_dit(); + results[0] = dit == service_arg0; + results[1] = dit; + /* Toggle the dit bit */ + write_dit(service_arg0 != 0U ? 0 : DIT_BIT); + break; + default: + break; + } + + return set_smc_args(func, 0, + results[0], + results[1], + 0, 0, 0, 0); +} + +/******************************************************************************* + * TSP smc abort handler. This function is called when aborting a preempted + * yielding SMC request. It should cleanup all resources owned by the SMC + * handler such as locks or dynamically allocated memory so following SMC + * request are executed in a clean environment. + ******************************************************************************/ +tsp_args_t *tsp_abort_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0); +} diff --git a/arm-trusted-firmware/bl32/tsp/tsp_private.h b/arm-trusted-firmware/bl32/tsp/tsp_private.h new file mode 100644 index 0000000..38d9732 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp_private.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TSP_PRIVATE_H +#define TSP_PRIVATE_H + +/* Definitions to help the assembler access the SMC/ERET args structure */ +#define TSP_ARGS_SIZE 0x40 +#define TSP_ARG0 0x0 +#define TSP_ARG1 0x8 +#define TSP_ARG2 0x10 +#define TSP_ARG3 0x18 +#define TSP_ARG4 0x20 +#define TSP_ARG5 0x28 +#define TSP_ARG6 0x30 +#define TSP_ARG7 0x38 +#define TSP_ARGS_END 0x40 + + +#ifndef __ASSEMBLER__ + +#include + +#include /* For CACHE_WRITEBACK_GRANULE */ + +#include +#include +#include + +typedef struct work_statistics { + /* Number of s-el1 interrupts on this cpu */ + uint32_t sel1_intr_count; + /* Number of non s-el1 interrupts on this cpu which preempted TSP */ + uint32_t preempt_intr_count; + /* Number of sync s-el1 interrupts on this cpu */ + uint32_t sync_sel1_intr_count; + /* Number of s-el1 interrupts returns on this cpu */ + uint32_t sync_sel1_intr_ret_count; + uint32_t smc_count; /* Number of returns on this cpu */ + uint32_t eret_count; /* Number of entries on this cpu */ + uint32_t cpu_on_count; /* Number of cpu on requests */ + uint32_t cpu_off_count; /* Number of cpu off requests */ + uint32_t cpu_suspend_count; /* Number of cpu suspend requests */ + uint32_t cpu_resume_count; /* Number of cpu resume requests */ +} __aligned(CACHE_WRITEBACK_GRANULE) work_statistics_t; + +typedef struct tsp_args { + uint64_t _regs[TSP_ARGS_END >> 3]; +} __aligned(CACHE_WRITEBACK_GRANULE) tsp_args_t; + +/* Macros to access members of the above structure using their offsets */ +#define read_sp_arg(args, offset) ((args)->_regs[offset >> 3]) +#define write_sp_arg(args, offset, val) (((args)->_regs[offset >> 3]) \ + = val) +/* + * Ensure that the assembler's view of the size of the tsp_args is the + * same as the compilers + */ +CASSERT(TSP_ARGS_SIZE == sizeof(tsp_args_t), assert_sp_args_size_mismatch); + +uint128_t tsp_get_magic(void); + +tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); +tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); +tsp_args_t *tsp_cpu_on_main(void); +tsp_args_t *tsp_cpu_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +/* Generic Timer functions */ +void tsp_generic_timer_start(void); +void tsp_generic_timer_handler(void); +void tsp_generic_timer_stop(void); +void tsp_generic_timer_save(void); +void tsp_generic_timer_restore(void); + +/* S-EL1 interrupt management functions */ +void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3); + + +/* Data structure to keep track of TSP statistics */ +extern spinlock_t console_lock; +extern work_statistics_t tsp_stats[PLATFORM_CORE_COUNT]; + +/* Vector table of jumps */ +extern tsp_vectors_t tsp_vector_table; + +/* functions */ +int32_t tsp_common_int_handler(void); +int32_t tsp_handle_preemption(void); + +tsp_args_t *tsp_abort_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +tsp_args_t *tsp_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +tsp_args_t *tsp_system_reset_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +tsp_args_t *tsp_system_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +uint64_t tsp_main(void); +#endif /* __ASSEMBLER__ */ + +#endif /* TSP_PRIVATE_H */ diff --git a/arm-trusted-firmware/bl32/tsp/tsp_timer.c b/arm-trusted-firmware/bl32/tsp/tsp_timer.c new file mode 100644 index 0000000..d1ff2b0 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp_timer.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "tsp_private.h" + +/******************************************************************************* + * Data structure to keep track of per-cpu secure generic timer context across + * power management operations. + ******************************************************************************/ +typedef struct timer_context { + uint64_t cval; + uint32_t ctl; +} timer_context_t; + +static timer_context_t pcpu_timer_context[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * This function initializes the generic timer to fire every 0.5 second + ******************************************************************************/ +void tsp_generic_timer_start(void) +{ + uint64_t cval; + uint32_t ctl = 0; + + /* The timer will fire every 0.5 second */ + cval = read_cntpct_el0() + (read_cntfrq_el0() >> 1); + write_cntps_cval_el1(cval); + + /* Enable the secure physical timer */ + set_cntp_ctl_enable(ctl); + write_cntps_ctl_el1(ctl); +} + +/******************************************************************************* + * This function deasserts the timer interrupt and sets it up again + ******************************************************************************/ +void tsp_generic_timer_handler(void) +{ + /* Ensure that the timer did assert the interrupt */ + assert(get_cntp_ctl_istatus(read_cntps_ctl_el1())); + + /* + * Disable the timer and reprogram it. The barriers ensure that there is + * no reordering of instructions around the reprogramming code. + */ + isb(); + write_cntps_ctl_el1(0); + tsp_generic_timer_start(); + isb(); +} + +/******************************************************************************* + * This function deasserts the timer interrupt prior to cpu power down + ******************************************************************************/ +void tsp_generic_timer_stop(void) +{ + /* Disable the timer */ + write_cntps_ctl_el1(0); +} + +/******************************************************************************* + * This function saves the timer context prior to cpu suspension + ******************************************************************************/ +void tsp_generic_timer_save(void) +{ + uint32_t linear_id = plat_my_core_pos(); + + pcpu_timer_context[linear_id].cval = read_cntps_cval_el1(); + pcpu_timer_context[linear_id].ctl = read_cntps_ctl_el1(); + flush_dcache_range((uint64_t) &pcpu_timer_context[linear_id], + sizeof(pcpu_timer_context[linear_id])); +} + +/******************************************************************************* + * This function restores the timer context post cpu resumption + ******************************************************************************/ +void tsp_generic_timer_restore(void) +{ + uint32_t linear_id = plat_my_core_pos(); + + write_cntps_cval_el1(pcpu_timer_context[linear_id].cval); + write_cntps_ctl_el1(pcpu_timer_context[linear_id].ctl); +} diff --git a/arm-trusted-firmware/changelog.yaml b/arm-trusted-firmware/changelog.yaml new file mode 100644 index 0000000..939fb65 --- /dev/null +++ b/arm-trusted-firmware/changelog.yaml @@ -0,0 +1,1017 @@ +# +# Copyright (c) 2021-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# The following block describes the top-level sections of the changelog. Commits are categorized +# into these top-level sections based on the commit message "type": +# +# feat(xyz): add the xyz feature +# ^^^^ +# + +sections: + - title: New Features + description: A new feature + type: feat + + - title: Resolved Issues + description: A bug fix + type: fix + + - title: Build System + description: Changes that affect the build system or external dependencies + type: build + hidden: true + + - title: Continuous Integration + description: Changes to our CI configuration files and scripts + type: ci + hidden: true + + - title: Build System + description: Documentation-only changes + type: docs + hidden: true + + - title: Performance Improvements + description: A code change that improves performance + type: perf + hidden: true + + - title: Code Refactoring + description: A code change that neither fixes a bug nor adds a feature + type: refactor + hidden: true + + - title: Reverted Changes + description: Changes that revert a previous change + type: revert + hidden: true + + - title: Style + description: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.) + type: style + hidden: true + + - title: Tests + description: Adding missing tests or correcting existing tests + type: test + hidden: true + + - title: Miscellaneous + description: Any other change + type: chore + hidden: true + +# +# The following block describes the sub-sections of the changelog. These sub-sections may appear in +# any of the top-level sections, and describe the individual components that a change may relate to. +# +# Sub-sections have an optional associated commit message "scope": +# +# feat(xyz): add the xyz feature +# ^^^ +# +# This file also describes deprecated scopes, which are scopes that were used before we introduced +# scope enforcement. These will not pass CI checks when used, but they will be used to generate the +# changelog. +# +# Please note that new scopes should be kebab-case: https://en.wiktionary.org/wiki/kebab_case +# + +subsections: + - title: Architecture + + subsections: + - title: Activity Monitors Extension (FEAT_AMU) + scope: amu + + - title: Support for the `HCRX_EL2` register (FEAT_HCX) + scope: hcx + + - title: Memory Partitioning and Monitoring (MPAM) Extension (FEAT_MPAM) + scope: mpam + + - title: Scalable Matrix Extension (FEAT_SME) + scope: sme + + - title: Scalable Vector Extension (FEAT_SVE) + scope: sve + + - title: System Register Trace Extensions (FEAT_ETMv4, FEAT_ETE and FEAT_ETEv1.1) + scope: sys-reg-trace + + deprecated: + - sys_reg_trace + + - title: Trace Buffer Extension (FEAT_TRBE) + scope: trbe + + - title: Self-hosted Trace Extensions (FEAT_TRF) + scope: trf + + - title: Statistical profiling Extension (FEAT_SPE) + scope: spe + + - title: Platforms + + subsections: + - title: Allwinner + scope: allwinner + + deprecated: + - plat/allwinner + + - title: Arm + scope: arm + + deprecated: + - plat/arm + + subsections: + - title: FPGA + scope: fpga + + deprecated: + - arm_fgpa + - arm_fpga + - plat/arm_fpga + + - title: FVP + scope: fvp + + deprecated: + - plat/fvp + + - title: FVP-R + scope: fvp-r + + deprecated: + - fvp_r + + - title: Juno + scope: juno + + - title: Morello + scope: morello + + - title: RD + scope: rd + + subsections: + - title: RD-N2 + scope: rdn2 + + deprecated: + - board/rdn2 + + - title: SGI + scope: sgi + + deprecated: + - plat/sgi + - plat/arm/sgi + + - title: TC + scope: tc + + subsections: + - title: TC0 + scope: tc0 + + deprecated: + - plat/tc0 + + - title: Intel + scope: intel + + subsections: + - title: SoC + scope: soc + + - title: Marvell + scope: marvell + + deprecated: + - plat/marvell + + subsections: + - title: Armada + scope: armada + + deprecated: + - plat/marvell/armada + + subsections: + - title: A3K + scope: a3k + + deprecated: + - plat/marvell/a3k + + - title: A8K + scope: a8k + + deprecated: + - plat/marvell/a8k + + - title: MediaTek + scope: mediatek + + deprecated: + - plat/mediatek/common + - plat/mediatek + + subsections: + - title: MT8183 + scope: mt8183 + + deprecated: + - plat/mediatek/mt8183 + + - title: MT8192 + scope: mt8192 + + deprecated: + - plat/mdeiatek/mt8192 + + - title: MT8195 + scope: mt8195 + + deprecated: + - plat/mediatek/me8195 + - plat/mediatek/mt8195 + - plat/mdeiatek/mt8195 + + - title: NVIDIA + scope: nvidia + + subsections: + - title: Tegra + scope: tegra + + deprecated: + - plat/tegra + + subsections: + - title: Tegra 132 + scope: tegra132 + + - title: NXP + scope: nxp + + deprecated: + - plat/nxp + - plat/nxp/common + + subsections: + - title: i.MX + scope: imx + + deprecated: + - plat/imx + - plat/imx/imx + + subsections: + - title: i.MX 8M + scope: imx8m + + deprecated: + - plat/imx8m + - plat/imx/imx8m + + subsections: + - title: i.MX 8M Mini + scope: imx8mm + + deprecated: + - plat/imx/imx8m/imx8mm + + - title: i.MX 8M Plus + scope: imx8mp + + deprecated: + - plat/imx/imx8m/imx8mp + + - title: Layerscape + scope: layerscape + + deprecated: + - docs/nxp/layerscape + + subsections: + - title: LS1028A + scope: ls1028a + + deprecated: + - plat/nxp/ls1028a + + subsections: + - title: LS1028ARDB + scope: ls1028ardb + + deprecated: + - plat/nxp/ls1028ardb + + - title: LX2 + scope: lx2 + + deprecated: + - plat/nxp/lx2 + + subsections: + - title: LX216 + scope: lx216 + + deprecated: + - plat/nxp/lx216x + + subsections: + - title: LX2160 + scope: lx2160 + + deprecated: + - plat/soc-lx2160 + + - title: LS1046A + scope: ls1046a + + subsections: + - title: LS1046ARDB + scope: ls1046ardb + + - title: LS1046AFRWY + scope: ls1046afrwy + + - title: LS1046AQDS + scope: ls1046aqds + + - title: LS1088A + scope: ls1088a + + subsections: + - title: LS1088ARDB + scope: ls1088ardb + + - title: LS1088AQDS + scope: ls1088aqds + + - title: QEMU + scope: qemu + + deprecated: + - plat/qemu + + - title: QTI + scope: qti + + subsections: + - title: SC1780 + scope: sc7180 + + deprecated: + - plat/qti/sc7180 + + - title: SC7280 + scope: sc7280 + + deprecated: + - plat/qti/sc7280 + + - title: MSM8916 + scope: msm8916 + + - title: Raspberry Pi + scope: rpi + + subsections: + - title: Raspberry Pi 4 + scope: rpi4 + + - title: Renesas + scope: renesas + + subsections: + - title: R-Car + scope: rcar + + deprecated: + - plat/rcar + + subsections: + - title: R-Car 3 + scope: rcar3 + + deprecated: + - plat/rcar3 + + - title: Rockchip + scope: rockchip + + subsections: + - title: RK3399 + scope: rk3399 + + deprecated: + - rockchip/rk3399 + - rk3399/suspend + + - title: Socionext + scope: socionext + + subsections: + - title: Synquacer + scope: synquacer + + deprecated: + - plat/synquacer + + - title: ST + scope: st + + deprecated: + - plat/st + + subsections: + - title: ST32MP1 + scope: stm32mp1 + + deprecated: + - plat/st/stm32mp1 + + - title: Xilinx + scope: xilinx + + deprecated: + - plat/xilinx + + subsections: + - title: Versal + scope: versal + + deprecated: + - plat/xilinx/versal/include + - plat/xilinx/versal + - plat/versal + + - title: ZynqMP + scope: zynqmp + + deprecated: + - plat/zynqmp + - plat/xilinx/zynqmp + + - title: Bootloader Images + scope: bl + + deprecated: + - bl_common + + subsections: + - title: BL1 + scope: bl1 + + - title: BL2 + scope: bl2 + + - title: Services + scope: services + + subsections: + - title: FF-A + scope: ff-a + + deprecated: + - ffa + + - title: RME + scope: rme + + - title: SPM + scope: spm + + deprecated: + - spmc + - spmd + - SPMD + + - title: SPM MM + scope: spm-mm + + - title: Libraries + + subsections: + - title: CPU Support + scope: cpus + + deprecated: + - cpu + - errata + - errata_report + + - title: EL3 Runtime + scope: el3-runtime + + deprecated: + - el3_runtime + + - title: FCONF + scope: fconf + + - title: MPMM + scope: mpmm + + - title: OP-TEE + scope: optee + + deprecated: + - lib/optee + + - title: PSCI + scope: psci + + - title: GPT + scope: gpt + + deprecated: + - gpt_rme + + - title: SMCCC + scope: smccc + + - title: Translation Tables + scope: xlat + + - title: Drivers + + subsections: + - title: Authentication + scope: auth + + deprecated: + - driver/auth + + subsections: + - title: CryptoCell-713 + scope: cc-713 + + - title: FWU + scope: fwu + + deprecated: + - fwu_metadata + + - title: I/O + scope: io + + subsections: + - title: MTD + scope: mtd + + deprecated: + - io_mtd + + - title: Measured Boot + scope: measured-boot + + deprecated: + - measured boot + - measured_boot + + - title: MMC + scope: mmc + + deprecated: + - drivers/mmc + + - title: MTD + scope: mtd + + deprecated: + - drivers/mtd + + subsections: + - title: NAND + scope: nand + + subsections: + - title: SPI NAND + scope: spi-nand + + deprecated: + - spi_nand + + - title: Partition + scope: partition + + - title: SCMI + scope: scmi + + deprecated: + - scmi_common + - drivers/scmi-msg + + - title: UFS + scope: ufs + + - title: Arm + scope: arm-drivers + + subsections: + - title: Ethos-N + scope: ethos-n + + deprecated: + - drivers/arm/ethosn + + - title: GIC + scope: gic + + subsections: + - title: GICv3 + scope: gicv3 + + subsections: + - title: GIC-600AE + scope: gic600ae + + - title: TZC + scope: tzc + + subsections: + - title: TZC-400 + scope: tzc400 + + deprecated: + - drivers/tzc400 + + - title: Marvell + scope: marvell-drivers + + subsections: + - title: COMPHY + scope: marvell-comphy + + deprecated: + - drivers/marvell/comphy + + subsections: + - title: Armada 3700 + scope: marvell-comphy-3700 + + deprecated: + - drivers/marvell/comphy-3700 + + - title: CP110 + scope: marvell-comphy-cp110 + + deprecated: + - drivers/marvell/comphy-cp110 + + - title: UART + scope: marvell-uart + + deprecated: + - plat/marvell/uart + + - title: Armada + scope: armada-drivers + + subsections: + - title: A3K + scope: a3k-drivers + + subsections: + - title: A3720 + scope: a3720-uart + + deprecated: + - plat/marvell/a3720/uart + + - title: MediaTek + scope: mediatek-drivers + + subsections: + - title: APU + scope: mediatek-apu + + deprecated: + - plat/mediatek/apu + + - title: EMI MPU + scope: mediatek-emi-mpu + + deprecated: + - plat/mediatek/mpu + + - title: PMIC Wrapper + scope: mediatek-pmic-wrapper + + deprecated: + - plat/mediatek/pmic_wrap + + - title: MT8192 + scope: mt8192-drivers + + subsections: + - title: SPM + scope: mt8192-spm + + deprecated: + - mediatek/mt8192/spm + + - title: NXP + scope: nxp-drivers + + subsections: + - title: DCFG + scope: nxp-dcfg + + deprecated: + - driver/nxp/dcfg + + - title: FLEXSPI + scope: flexspi + + deprecated: + - include/drivers/flexspi + - driver/nxp/xspi + + - title: SCFG + scope: nxp-scfg + + deprecated: + - nxp/scfg + + - title: SFP + scope: nxp-sfp + + deprecated: + - drivers/nxp/sfp + + - title: QSPI + scope: nxp-qspi + + - title: NXP Crypto + scope: nxp-crypto + + - title: DDR + scope: nxp-ddr + + - title: GIC + scope: nxp-gic + + - title: Renesas + scope: renesas-drivers + + subsections: + - title: R-Car3 + scope: rcar3-drivers + + deprecated: + - drivers/rcar3 + + - title: ST + scope: st-drivers + + deprecated: + - drivers/st + + subsections: + - title: BSEC + scope: st-bsec + + - title: Clock + scope: st-clock + + deprecated: + - stm32mp_clk + - drivers/st/clk + - stm32mp1_clk + + - title: Crypto + scope: st-crypto + + - title: DDR + scope: st-ddr + + - title: I/O + scope: st-io-drivers + + subsections: + - title: STM32 Image + scope: st-io-stm32image + + deprecated: + - io-stm32image + - io_stm32image + + - title: fiptool + scope: fiptool + + - title: I2C + scope: st-i2c + + - title: FMC + scope: st-fmc + + - title: GPIO + scope: st-gpio + + - title: SDMMC2 + scope: st-sdmmc2 + + deprecated: + - stm32_sdmmc2 + + - title: ST PMIC + scope: st-pmic + + deprecated: + - drivers/st/pmic + + - title: STPMIC1 + scope: stpmic1 + + - title: Regulator + scope: st-regulator + + - title: Reset + scope: st-reset + + - title: SPI + scope: st-spi + + - title: UART + scope: st-uart + + subsections: + - title: STM32 Console + scope: stm32-console + + deprecated: + - stm32_console + + - title: USB + scope: st-usb + + deprecated: + - drivers/st/usb + + - title: Watchdog + scope: st-iwdg + + - title: USB + scope: usb + + deprecated: + - drivers/usb + + - title: Miscellaneous + + subsections: + - title: AArch64 + scope: aarch64 + + - title: Debug + scope: debug + + deprecated: + - common/debug + + - title: CRC32 + scope: crc32 + + subsections: + - title: Hardware CRC32 + scope: hw-crc32 + + deprecated: + - hw_crc + - hw_crc32 + + - title: Software CRC32 + scope: sw-crc32 + + deprecated: + - sw_crc32 + + - title: DT Bindings + scope: dt-bindings + + - title: FDT Wrappers + scope: fdt-wrappers + + - title: FDTs + scope: fdts + + deprecated: + - fdt + + subsections: + - title: Morello + scope: morello-fdts + + deprecated: + - fdts/morello + + - title: STM32MP1 + scope: stm32mp1-fdts + + deprecated: + - fdts stm32mp1 + + - title: PIE + scope: pie + + - title: Security + scope: security + + - title: SDEI + scope: sdei + + - title: TBBR + scope: tbbr + + - title: NXP + + subsections: + - title: OCRAM + scope: nxp-ocram + + deprecated: + - nxp/common/ocram + + - title: PSCI + scope: nxp-psci + + deprecated: + - plat/nxp/common/psci + + - title: Documentation + scope: docs + + deprecated: + - doc + + subsections: + - title: Changelog + scope: changelog + + - title: Commit Style + scope: commit-style + + - title: Contribution Guidelines + scope: contributing + + deprecated: + - contribution-guidelines + - docs-contributing.rst + + - title: Maintainers + scope: maintainers + + - title: Prerequisites + scope: prerequisites + + - title: Build System + scope: build + + deprecated: + - makefile + - Makefile + + subsections: + - title: Git Hooks + scope: hooks + + - title: Tools + + subsections: + - title: STM32 Image + scope: stm32image + + deprecated: + - tools/stm32image + + - title: NXP Tools + scope: nxp-tools + + - title: Dependencies + scope: deps + + subsections: + - title: checkpatch + scope: checkpatch + + - title: commitlint + scope: commitlint + + - title: libfdt + scope: libfdt + + - title: Node Package Manager (NPM) + scope: npm diff --git a/arm-trusted-firmware/common/aarch32/debug.S b/arm-trusted-firmware/common/aarch32/debug.S new file mode 100644 index 0000000..9d410df --- /dev/null +++ b/arm-trusted-firmware/common/aarch32/debug.S @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2016-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_assert + .globl do_panic + .globl report_exception + +/* 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 '0' + +#if ENABLE_ASSERTIONS +.section .rodata.assert_str, "aS" +assert_msg1: + .asciz "ASSERT: File " +assert_msg2: +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /****************************************************************** + * Virtualization comes with the UDIV/SDIV instructions. If missing + * write file line number in hexadecimal format. + ******************************************************************/ + .asciz " Line 0x" +#else + .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: r4 = the decimal to print. + * Clobber: lr, r0, r1, r2, r5, r6 + */ + .macro asm_print_line_dec + mov r6, #10 /* Divide by 10 after every loop iteration */ + ldr r5, =MAX_DEC_DIVISOR +dec_print_loop: + udiv r0, r4, r5 /* Get the quotient */ + mls r4, r0, r5, r4 /* Find the remainder */ + add r0, r0, #ASCII_OFFSET_NUM /* Convert to ascii */ + bl plat_crash_console_putc + udiv r5, r5, r6 /* Reduce divisor */ + cmp r5, #0 + bne dec_print_loop + .endm +#endif + +/* --------------------------------------------------------------------------- + * 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 : + * r0 - File name + * r1 - Line no + * Clobber list : lr, r0 - r6 + * --------------------------------------------------------------------------- + */ +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. + */ + /* Stash the parameters already in r0 and r1 */ + mov r5, r0 + mov r6, r1 + + /* Ensure the console is initialized */ + bl plat_crash_console_init + + /* Check if the console is initialized */ + cmp r0, #0 + beq _assert_loop + + /* The console is initialized */ + ldr r4, =assert_msg1 + bl asm_print_str + mov r4, r5 + bl asm_print_str + ldr r4, =assert_msg2 + bl asm_print_str + + /* Check if line number higher than max permitted */ + ldr r4, =~0xffff + tst r6, r4 + bne _assert_loop + mov r4, r6 + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /****************************************************************** + * Virtualization comes with the UDIV/SDIV instructions. If missing + * write file line number in hexadecimal format. + ******************************************************************/ + bl asm_print_hex +#else + asm_print_line_dec +#endif + 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 r4 + * Clobber: lr, r0 - r4 + */ +func asm_print_str + mov r3, lr +1: + ldrb r0, [r4], #0x1 + cmp r0, #0 + beq 2f + bl plat_crash_console_putc + b 1b +2: + bx r3 +endfunc asm_print_str + +/* + * This function prints a hexadecimal number in r4. + * In: r4 = the hexadecimal to print. + * Clobber: lr, r0 - r3, r5 + */ +func asm_print_hex + mov r5, #32 /* No of bits to convert to ascii */ + + /* Convert to ascii number of bits in r5 */ +asm_print_hex_bits: + mov r3, lr +1: + sub r5, r5, #4 + lsr r0, r4, r5 + and r0, r0, #0xf + cmp r0, #0xa + blo 2f + /* Add by 0x27 in addition to ASCII_OFFSET_NUM + * to get ascii for characters 'a - f'. + */ + add r0, r0, #0x27 +2: + add r0, r0, #ASCII_OFFSET_NUM + bl plat_crash_console_putc + cmp r5, #0 + bne 1b + bx r3 +endfunc asm_print_hex + + /*********************************************************** + * The common implementation of do_panic for all BL stages + ***********************************************************/ + +.section .rodata.panic_str, "aS" + panic_msg: .asciz "PANIC at PC : 0x" + panic_end: .asciz "\r\n" + +func do_panic + /* Have LR copy point to PC at the time of panic */ + sub r6, lr, #4 + + /* Initialize crash console and verify success */ + bl plat_crash_console_init + + /* Check if the console is initialized */ + cmp r0, #0 + beq _panic_handler + + /* The console is initialized */ + ldr r4, =panic_msg + bl asm_print_str + + /* Print LR in hex */ + mov r4, r6 + bl asm_print_hex + + /* Print new line */ + ldr r4, =panic_end + bl asm_print_str + + bl plat_crash_console_flush + +_panic_handler: + mov lr, r6 + b plat_panic_handler +endfunc do_panic + + /*********************************************************** + * This function is called from the vector table for + * unhandled exceptions. It reads the current mode and + * passes it to platform. + ***********************************************************/ +func report_exception + mrs r0, cpsr + and r0, #MODE32_MASK + bl plat_report_exception + no_ret plat_panic_handler +endfunc report_exception diff --git a/arm-trusted-firmware/common/aarch64/debug.S b/arm-trusted-firmware/common/aarch64/debug.S new file mode 100644 index 0000000..d105d08 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/common/aarch64/early_exceptions.S b/arm-trusted-firmware/common/aarch64/early_exceptions.S new file mode 100644 index 0000000..36a8724 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/common/backtrace/backtrace.c b/arm-trusted-firmware/common/backtrace/backtrace.c new file mode 100644 index 0000000..25e2c70 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/common/backtrace/backtrace.mk b/arm-trusted-firmware/common/backtrace/backtrace.mk new file mode 100644 index 0000000..e669331 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/common/bl_common.c b/arm-trusted-firmware/common/bl_common.c new file mode 100644 index 0000000..9bfaafd --- /dev/null +++ b/arm-trusted-firmware/common/bl_common.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2013-2022, 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; +} + +#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; + } + + 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(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; + +/* + * All firmware banks should be part of the same non-volatile storage as per + * PSA FWU specification, hence don't check for any alternate boot source + * when PSA FWU is enabled. + */ +#if PSA_FWU_SUPPORT + err = load_auth_image_internal(image_id, image_data); +#else + do { + err = load_auth_image_internal(image_id, image_data); + } while ((err != 0) && (plat_try_next_boot_source() != 0)); +#endif /* PSA_FWU_SUPPORT */ + + if (err == 0) { + /* + * If loading of the image gets passed (along with its + * authentication in case of Trusted-Boot flow) then measure + * it (if MEASURED_BOOT flag is enabled). + */ + err = plat_mboot_measure_image(image_id, image_data); + if (err != 0) { + return err; + } + + /* + * Flush the image to main memory so that it can be executed + * later by any CPU, regardless of cache and MMU state. + */ + flush_dcache_range(image_data->image_base, + image_data->image_size); + } + + 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/arm-trusted-firmware/common/desc_image_load.c b/arm-trusted-firmware/common/desc_image_load.c new file mode 100644 index 0000000..30b97e0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/common/fdt_fixup.c b/arm-trusted-firmware/common/fdt_fixup.c new file mode 100644 index 0000000..de02b46 --- /dev/null +++ b/arm-trusted-firmware/common/fdt_fixup.c @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Contains generic routines to fix up the device tree blob passed on to + * payloads like BL32 and BL33 (and further down the boot chain). + * This allows to easily add PSCI nodes, when the original DT does not have + * it or advertises another method. + * Also it supports to add reserved memory nodes to describe memory that + * is used by the secure world, so that non-secure software avoids using + * that. + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + + +static int append_psci_compatible(void *fdt, int offs, const char *str) +{ + return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1); +} + +/* + * Those defines are for PSCI v0.1 legacy clients, which we expect to use + * the same execution state (AArch32/AArch64) as TF-A. + * Kernels running in AArch32 on an AArch64 TF-A should use PSCI v0.2. + */ +#ifdef __aarch64__ +#define PSCI_CPU_SUSPEND_FNID PSCI_CPU_SUSPEND_AARCH64 +#define PSCI_CPU_ON_FNID PSCI_CPU_ON_AARCH64 +#else +#define PSCI_CPU_SUSPEND_FNID PSCI_CPU_SUSPEND_AARCH32 +#define PSCI_CPU_ON_FNID PSCI_CPU_ON_AARCH32 +#endif + +/******************************************************************************* + * dt_add_psci_node() - Add a PSCI node into an existing device tree + * @fdt: pointer to the device tree blob in memory + * + * Add a device tree node describing PSCI into the root level of an existing + * device tree blob in memory. + * This will add v0.1, v0.2 and v1.0 compatible strings and the standard + * function IDs for v0.1 compatibility. + * An existing PSCI node will not be touched, the function will return success + * in this case. This function will not touch the /cpus enable methods, use + * dt_add_psci_cpu_enable_methods() for that. + * + * Return: 0 on success, -1 otherwise. + ******************************************************************************/ +int dt_add_psci_node(void *fdt) +{ + int offs; + + if (fdt_path_offset(fdt, "/psci") >= 0) { + WARN("PSCI Device Tree node already exists!\n"); + return 0; + } + + offs = fdt_path_offset(fdt, "/"); + if (offs < 0) + return -1; + offs = fdt_add_subnode(fdt, offs, "psci"); + if (offs < 0) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci-1.0")) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci-0.2")) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci")) + return -1; + if (fdt_setprop_string(fdt, offs, "method", "smc")) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_FNID)) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF)) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_FNID)) + return -1; + return 0; +} + +/* + * Find the first subnode that has a "device_type" property with the value + * "cpu" and which's enable-method is not "psci" (yet). + * Returns 0 if no such subnode is found, so all have already been patched + * or none have to be patched in the first place. + * Returns 1 if *one* such subnode has been found and successfully changed + * to "psci". + * Returns negative values on error. + * + * Call in a loop until it returns 0. Recalculate the node offset after + * it has returned 1. + */ +static int dt_update_one_cpu_node(void *fdt, int offset) +{ + int offs; + + /* Iterate over all subnodes to find those with device_type = "cpu". */ + for (offs = fdt_first_subnode(fdt, offset); offs >= 0; + offs = fdt_next_subnode(fdt, offs)) { + const char *prop; + int len; + int ret; + + prop = fdt_getprop(fdt, offs, "device_type", &len); + if (prop == NULL) + continue; + if ((strcmp(prop, "cpu") != 0) || (len != 4)) + continue; + + /* Ignore any nodes which already use "psci". */ + prop = fdt_getprop(fdt, offs, "enable-method", &len); + if ((prop != NULL) && + (strcmp(prop, "psci") == 0) && (len == 5)) + continue; + + ret = fdt_setprop_string(fdt, offs, "enable-method", "psci"); + if (ret < 0) + return ret; + /* + * Subnode found and patched. + * Restart to accommodate potentially changed offsets. + */ + return 1; + } + + if (offs == -FDT_ERR_NOTFOUND) + return 0; + + return offs; +} + +/******************************************************************************* + * dt_add_psci_cpu_enable_methods() - switch CPU nodes in DT to use PSCI + * @fdt: pointer to the device tree blob in memory + * + * Iterate over all CPU device tree nodes (/cpus/cpu@x) in memory to change + * the enable-method to PSCI. This will add the enable-method properties, if + * required, or will change existing properties to read "psci". + * + * Return: 0 on success, or a negative error value otherwise. + ******************************************************************************/ + +int dt_add_psci_cpu_enable_methods(void *fdt) +{ + int offs, ret; + + do { + offs = fdt_path_offset(fdt, "/cpus"); + if (offs < 0) + return offs; + + ret = dt_update_one_cpu_node(fdt, offs); + } while (ret > 0); + + return ret; +} + +#define HIGH_BITS(x) ((sizeof(x) > 4) ? ((x) >> 32) : (typeof(x))0) + +/******************************************************************************* + * fdt_add_reserved_memory() - reserve (secure) memory regions in DT + * @dtb: pointer to the device tree blob in memory + * @node_name: name of the subnode to be used + * @base: physical base address of the reserved region + * @size: size of the reserved region + * + * Add a region of memory to the /reserved-memory node in a device tree in + * memory, creating that node if required. Each region goes into a subnode + * of that node and has a @node_name, a @base address and a @size. + * This will prevent any device tree consumer from using that memory. It + * can be used to announce secure memory regions, as it adds the "no-map" + * property to prevent mapping and speculative operations on that region. + * + * See reserved-memory/reserved-memory.txt in the (Linux kernel) DT binding + * documentation for details. + * According to this binding, the address-cells and size-cells must match + * those of the root node. + * + * Return: 0 on success, a negative error value otherwise. + ******************************************************************************/ +int fdt_add_reserved_memory(void *dtb, const char *node_name, + uintptr_t base, size_t size) +{ + int offs = fdt_path_offset(dtb, "/reserved-memory"); + uint32_t addresses[4]; + int ac, sc; + unsigned int idx = 0; + + ac = fdt_address_cells(dtb, 0); + sc = fdt_size_cells(dtb, 0); + if (offs < 0) { /* create if not existing yet */ + offs = fdt_add_subnode(dtb, 0, "reserved-memory"); + if (offs < 0) { + return offs; + } + fdt_setprop_u32(dtb, offs, "#address-cells", ac); + fdt_setprop_u32(dtb, offs, "#size-cells", sc); + fdt_setprop(dtb, offs, "ranges", NULL, 0); + } + + if (ac > 1) { + addresses[idx] = cpu_to_fdt32(HIGH_BITS(base)); + idx++; + } + addresses[idx] = cpu_to_fdt32(base & 0xffffffff); + idx++; + if (sc > 1) { + addresses[idx] = cpu_to_fdt32(HIGH_BITS(size)); + idx++; + } + addresses[idx] = cpu_to_fdt32(size & 0xffffffff); + idx++; + offs = fdt_add_subnode(dtb, offs, node_name); + fdt_setprop(dtb, offs, "no-map", NULL, 0); + fdt_setprop(dtb, offs, "reg", addresses, idx * sizeof(uint32_t)); + + return 0; +} + +/******************************************************************************* + * fdt_add_cpu() Add a new CPU node to the DT + * @dtb: Pointer to the device tree blob in memory + * @parent: Offset of the parent node + * @mpidr: MPIDR for the current CPU + * + * Create and add a new cpu node to a DTB. + * + * Return the offset of the new node or a negative value in case of error + ******************************************************************************/ + +static int fdt_add_cpu(void *dtb, int parent, u_register_t mpidr) +{ + int cpu_offs; + int err; + char snode_name[15]; + uint64_t reg_prop; + + reg_prop = mpidr & MPID_MASK & ~MPIDR_MT_MASK; + + snprintf(snode_name, sizeof(snode_name), "cpu@%x", + (unsigned int)reg_prop); + + cpu_offs = fdt_add_subnode(dtb, parent, snode_name); + if (cpu_offs < 0) { + ERROR ("FDT: add subnode \"%s\" failed: %i\n", + snode_name, cpu_offs); + return cpu_offs; + } + + err = fdt_setprop_string(dtb, cpu_offs, "compatible", "arm,armv8"); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "compatible", cpu_offs); + return err; + } + + err = fdt_setprop_u64(dtb, cpu_offs, "reg", reg_prop); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "reg", cpu_offs); + return err; + } + + err = fdt_setprop_string(dtb, cpu_offs, "device_type", "cpu"); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "device_type", cpu_offs); + return err; + } + + err = fdt_setprop_string(dtb, cpu_offs, "enable-method", "psci"); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "enable-method", cpu_offs); + return err; + } + + return cpu_offs; +} + +/****************************************************************************** + * fdt_add_cpus_node() - Add the cpus node to the DTB + * @dtb: pointer to the device tree blob in memory + * @afflv0: Maximum number of threads per core (affinity level 0). + * @afflv1: Maximum number of CPUs per cluster (affinity level 1). + * @afflv2: Maximum number of clusters (affinity level 2). + * + * Iterate over all the possible MPIDs given the maximum affinity levels and + * add a cpus node to the DTB with all the valid CPUs on the system. + * If there is already a /cpus node, exit gracefully + * + * A system with two CPUs would generate a node equivalent or similar to: + * + * cpus { + * #address-cells = <2>; + * #size-cells = <0>; + * + * cpu0: cpu@0 { + * compatible = "arm,armv8"; + * reg = <0x0 0x0>; + * device_type = "cpu"; + * enable-method = "psci"; + * }; + * cpu1: cpu@10000 { + * compatible = "arm,armv8"; + * reg = <0x0 0x100>; + * device_type = "cpu"; + * enable-method = "psci"; + * }; + * }; + * + * Full documentation about the CPU bindings can be found at: + * https://www.kernel.org/doc/Documentation/devicetree/bindings/arm/cpus.txt + * + * Return the offset of the node or a negative value on error. + ******************************************************************************/ + +int fdt_add_cpus_node(void *dtb, unsigned int afflv0, + unsigned int afflv1, unsigned int afflv2) +{ + int offs; + int err; + unsigned int i, j, k; + u_register_t mpidr; + int cpuid; + + if (fdt_path_offset(dtb, "/cpus") >= 0) { + return -EEXIST; + } + + offs = fdt_add_subnode(dtb, 0, "cpus"); + if (offs < 0) { + ERROR ("FDT: add subnode \"cpus\" node to parent node failed"); + return offs; + } + + err = fdt_setprop_u32(dtb, offs, "#address-cells", 2); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "#address-cells", offs); + return err; + } + + err = fdt_setprop_u32(dtb, offs, "#size-cells", 0); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "#size-cells", offs); + return err; + } + + /* + * Populate the node with the CPUs. + * As libfdt prepends subnodes within a node, reverse the index count + * so the CPU nodes would be better ordered. + */ + for (i = afflv2; i > 0U; i--) { + for (j = afflv1; j > 0U; j--) { + for (k = afflv0; k > 0U; k--) { + mpidr = ((i - 1) << MPIDR_AFF2_SHIFT) | + ((j - 1) << MPIDR_AFF1_SHIFT) | + ((k - 1) << MPIDR_AFF0_SHIFT) | + (read_mpidr_el1() & MPIDR_MT_MASK); + + cpuid = plat_core_pos_by_mpidr(mpidr); + if (cpuid >= 0) { + /* Valid MPID found */ + err = fdt_add_cpu(dtb, offs, mpidr); + if (err < 0) { + ERROR ("FDT: %s 0x%08x\n", + "error adding CPU", + (uint32_t)mpidr); + return err; + } + } + } + } + } + + return offs; +} + +/** + * fdt_adjust_gic_redist() - Adjust GICv3 redistributor size + * @dtb: Pointer to the DT blob in memory + * @nr_cores: Number of CPU cores on this system. + * @gicr_base: Base address of the first GICR frame, or ~0 if unchanged + * @gicr_frame_size: Size of the GICR frame per core + * + * On a GICv3 compatible interrupt controller, the redistributor provides + * a number of 64k pages per each supported core. So with a dynamic topology, + * this size cannot be known upfront and thus can't be hardcoded into the DTB. + * + * Find the DT node describing the GICv3 interrupt controller, and adjust + * the size of the redistributor to match the number of actual cores on + * this system. + * A GICv4 compatible redistributor uses four 64K pages per core, whereas GICs + * without support for direct injection of virtual interrupts use two 64K pages. + * The @gicr_frame_size parameter should be 262144 and 131072, respectively. + * Also optionally allow adjusting the GICR frame base address, when this is + * different due to ITS frames between distributor and redistributor. + * + * Return: 0 on success, negative error value otherwise. + */ +int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, + uintptr_t gicr_base, unsigned int gicr_frame_size) +{ + int offset = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-v3"); + uint64_t reg_64; + uint32_t reg_32; + void *val; + int parent, ret; + int ac, sc; + + if (offset < 0) { + return offset; + } + + parent = fdt_parent_offset(dtb, offset); + if (parent < 0) { + return parent; + } + ac = fdt_address_cells(dtb, parent); + sc = fdt_size_cells(dtb, parent); + if (ac < 0 || sc < 0) { + return -EINVAL; + } + + if (gicr_base != INVALID_BASE_ADDR) { + if (ac == 1) { + reg_32 = cpu_to_fdt32(gicr_base); + val = ®_32; + } else { + reg_64 = cpu_to_fdt64(gicr_base); + val = ®_64; + } + /* + * The redistributor base address is the second address in + * the "reg" entry, so we have to skip one address and one + * size cell. + */ + ret = fdt_setprop_inplace_namelen_partial(dtb, offset, + "reg", 3, + (ac + sc) * 4, + val, ac * 4); + if (ret < 0) { + return ret; + } + } + + if (sc == 1) { + reg_32 = cpu_to_fdt32(nr_cores * gicr_frame_size); + val = ®_32; + } else { + reg_64 = cpu_to_fdt64(nr_cores * (uint64_t)gicr_frame_size); + val = ®_64; + } + + /* + * The redistributor is described in the second "reg" entry. + * So we have to skip one address and one size cell, then another + * address cell to get to the second size cell. + */ + return fdt_setprop_inplace_namelen_partial(dtb, offset, "reg", 3, + (ac + sc + ac) * 4, + val, sc * 4); +} diff --git a/arm-trusted-firmware/common/fdt_wrappers.c b/arm-trusted-firmware/common/fdt_wrappers.c new file mode 100644 index 0000000..2a9673f --- /dev/null +++ b/arm-trusted-firmware/common/fdt_wrappers.c @@ -0,0 +1,620 @@ +/* + * 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 */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* + * Read cells from a given property of the given node. Any number of 32-bit + * cells of the property can be read. Returns 0 on success, or a negative + * FDT error value otherwise. + */ +int fdt_read_uint32_array(const void *dtb, int node, const char *prop_name, + unsigned int cells, uint32_t *value) +{ + const fdt32_t *prop; + int value_len; + + assert(dtb != NULL); + assert(prop_name != NULL); + assert(value != NULL); + assert(node >= 0); + + /* Access property and obtain its length (in bytes) */ + prop = fdt_getprop(dtb, node, prop_name, &value_len); + if (prop == NULL) { + VERBOSE("Couldn't find property %s in dtb\n", prop_name); + return -FDT_ERR_NOTFOUND; + } + + /* Verify that property length can fill the entire array. */ + if (NCELLS((unsigned int)value_len) < cells) { + WARN("Property length mismatch\n"); + return -FDT_ERR_BADVALUE; + } + + for (unsigned int i = 0U; i < cells; i++) { + value[i] = fdt32_to_cpu(prop[i]); + } + + return 0; +} + +int fdt_read_uint32(const void *dtb, int node, const char *prop_name, + uint32_t *value) +{ + return fdt_read_uint32_array(dtb, node, prop_name, 1, value); +} + +uint32_t fdt_read_uint32_default(const void *dtb, int node, + const char *prop_name, uint32_t dflt_value) +{ + uint32_t ret = dflt_value; + int err = fdt_read_uint32(dtb, node, prop_name, &ret); + + if (err < 0) { + return dflt_value; + } + + return ret; +} + +int fdt_read_uint64(const void *dtb, int node, const char *prop_name, + uint64_t *value) +{ + uint32_t array[2] = {0, 0}; + int ret; + + ret = fdt_read_uint32_array(dtb, node, prop_name, 2, array); + if (ret < 0) { + return ret; + } + + *value = ((uint64_t)array[0] << 32) | array[1]; + return 0; +} + +/* + * Read bytes from a given property of the given node. Any number of + * bytes of the property can be read. The fdt pointer is updated. + * Returns 0 on success, and -1 on error. + */ +int fdtw_read_bytes(const void *dtb, int node, const char *prop, + unsigned int length, void *value) +{ + const void *ptr; + int value_len; + + assert(dtb != NULL); + assert(prop != NULL); + assert(value != NULL); + assert(node >= 0); + + /* Access property and obtain its length (in bytes) */ + ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), + &value_len); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + /* Verify that property length is not less than number of bytes */ + if ((unsigned int)value_len < length) { + WARN("Property length mismatch\n"); + return -1; + } + + (void)memcpy(value, ptr, length); + + return 0; +} + +/* + * Read string from a given property of the given node. Up to 'size - 1' + * characters are read, and a NUL terminator is added. Returns 0 on success, + * and -1 upon error. + */ +int fdtw_read_string(const void *dtb, int node, const char *prop, + char *str, size_t size) +{ + const char *ptr; + size_t len; + + assert(dtb != NULL); + assert(node >= 0); + assert(prop != NULL); + assert(str != NULL); + assert(size > 0U); + + ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), NULL); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + len = strlcpy(str, ptr, size); + if (len >= size) { + WARN("String of property %s in dtb has been truncated\n", prop); + return -1; + } + + return 0; +} + +/* + * Read UUID from a given property of the given node. Returns 0 on success, + * and a negative value upon error. + */ +int fdtw_read_uuid(const void *dtb, int node, const char *prop, + unsigned int length, uint8_t *uuid) +{ + /* Buffer for UUID string (plus NUL terminator) */ + char uuid_string[UUID_STRING_LENGTH + 1U]; + int err; + + assert(dtb != NULL); + assert(prop != NULL); + assert(uuid != NULL); + assert(node >= 0); + + if (length < UUID_BYTES_LENGTH) { + return -EINVAL; + } + + err = fdtw_read_string(dtb, node, prop, uuid_string, + UUID_STRING_LENGTH + 1U); + if (err != 0) { + return err; + } + + if (read_uuid(uuid, uuid_string) != 0) { + return -FDT_ERR_BADVALUE; + } + + return 0; +} + +/* + * Write cells in place to a given property of the given node. At most 2 cells + * of the property are written. Returns 0 on success, and -1 upon error. + */ +int fdtw_write_inplace_cells(void *dtb, int node, const char *prop, + unsigned int cells, void *value) +{ + int err, len; + + assert(dtb != NULL); + assert(prop != NULL); + assert(value != NULL); + assert(node >= 0); + + /* We expect either 1 or 2 cell property */ + assert(cells <= 2U); + + if (cells == 2U) + *(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value); + else + *(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value); + + len = (int)cells * 4; + + /* Set property value in place */ + err = fdt_setprop_inplace(dtb, node, prop, value, len); + if (err != 0) { + WARN("Modify property %s failed with error %d\n", prop, err); + return -1; + } + + return 0; +} + +/* + * Write bytes in place to a given property of the given node. + * Any number of bytes of the property can be written. + * Returns 0 on success, and < 0 on error. + */ +int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop, + unsigned int length, const void *data) +{ + const void *ptr; + int namelen, value_len, err; + + assert(dtb != NULL); + assert(prop != NULL); + assert(data != NULL); + assert(node >= 0); + + namelen = (int)strlen(prop); + + /* Access property and obtain its length in bytes */ + ptr = fdt_getprop_namelen(dtb, node, prop, namelen, &value_len); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + /* Verify that property length is not less than number of bytes */ + if ((unsigned int)value_len < length) { + WARN("Property length mismatch\n"); + return -1; + } + + /* Set property value in place */ + err = fdt_setprop_inplace_namelen_partial(dtb, node, prop, + namelen, 0, + data, (int)length); + if (err != 0) { + WARN("Set property %s failed with error %d\n", prop, err); + } + + return err; +} + +static uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells) +{ + uint64_t reg = fdt32_to_cpu(prop[0]); + + if (nr_cells > 1) { + reg = (reg << 32) | fdt32_to_cpu(prop[1]); + } + + return reg; +} + +int fdt_get_reg_props_by_index(const void *dtb, int node, int index, + uintptr_t *base, size_t *size) +{ + const fdt32_t *prop; + int parent, len; + int ac, sc; + int cell; + + parent = fdt_parent_offset(dtb, node); + if (parent < 0) { + return -FDT_ERR_BADOFFSET; + } + + ac = fdt_address_cells(dtb, parent); + sc = fdt_size_cells(dtb, parent); + + cell = index * (ac + sc); + + prop = fdt_getprop(dtb, node, "reg", &len); + if (prop == NULL) { + WARN("Couldn't find \"reg\" property in dtb\n"); + return -FDT_ERR_NOTFOUND; + } + + if (((cell + ac + sc) * (int)sizeof(uint32_t)) > len) { + return -FDT_ERR_BADVALUE; + } + + if (base != NULL) { + *base = (uintptr_t)fdt_read_prop_cells(&prop[cell], ac); + } + + if (size != NULL) { + *size = (size_t)fdt_read_prop_cells(&prop[cell + ac], sc); + } + + return 0; +} + +/******************************************************************************* + * This function fills reg node info (base & size) with an index found by + * checking the reg-names node. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +int fdt_get_reg_props_by_name(const void *dtb, int node, const char *name, + uintptr_t *base, size_t *size) +{ + int index; + + index = fdt_stringlist_search(dtb, node, "reg-names", name); + if (index < 0) { + return index; + } + + return fdt_get_reg_props_by_index(dtb, node, index, base, size); +} + +/******************************************************************************* + * This function gets the stdout path node. + * It reads the value indicated inside the device tree. + * Returns node offset on success and a negative FDT error code on failure. + ******************************************************************************/ +int fdt_get_stdout_node_offset(const void *dtb) +{ + int node; + const char *prop, *path; + int len; + + /* The /secure-chosen node takes precedence over the standard one. */ + node = fdt_path_offset(dtb, "/secure-chosen"); + if (node < 0) { + node = fdt_path_offset(dtb, "/chosen"); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + } + + prop = fdt_getprop(dtb, node, "stdout-path", NULL); + if (prop == NULL) { + return -FDT_ERR_NOTFOUND; + } + + /* Determine the actual path length, as a colon terminates the path. */ + path = strchr(prop, ':'); + if (path == NULL) { + len = strlen(prop); + } else { + len = path - prop; + } + + /* Aliases cannot start with a '/', so it must be the actual path. */ + if (prop[0] == '/') { + return fdt_path_offset_namelen(dtb, prop, len); + } + + /* Lookup the alias, as this contains the actual path. */ + path = fdt_get_alias_namelen(dtb, prop, len); + if (path == NULL) { + return -FDT_ERR_NOTFOUND; + } + + return fdt_path_offset(dtb, path); +} + + +/******************************************************************************* + * Only devices which are direct children of root node use CPU address domain. + * All other devices use addresses that are local to the device node and cannot + * directly used by CPU. Device tree provides an address translation mechanism + * through "ranges" property which provides mappings from local address space to + * parent address space. Since a device could be a child of a child node to the + * root node, there can be more than one level of address translation needed to + * map the device local address space to CPU address space. + * fdtw_translate_address() API performs address translation of a local address + * to a global address with help of various helper functions. + ******************************************************************************/ + +static bool fdtw_xlat_hit(const uint32_t *value, int child_addr_size, + int parent_addr_size, int range_size, uint64_t base_address, + uint64_t *translated_addr) +{ + uint64_t local_address, parent_address, addr_range; + + local_address = fdt_read_prop_cells(value, child_addr_size); + parent_address = fdt_read_prop_cells(value + child_addr_size, + parent_addr_size); + addr_range = fdt_read_prop_cells(value + child_addr_size + + parent_addr_size, + range_size); + VERBOSE("DT: Address %" PRIx64 " mapped to %" PRIx64 " with range %" PRIx64 "\n", + local_address, parent_address, addr_range); + + /* Perform range check */ + if ((base_address < local_address) || + (base_address >= local_address + addr_range)) { + return false; + } + + /* Found hit for the addr range that needs to be translated */ + *translated_addr = parent_address + (base_address - local_address); + VERBOSE("DT: child address %" PRIx64 "mapped to %" PRIx64 " in parent bus\n", + local_address, parent_address); + return true; +} + +#define ILLEGAL_ADDR ULL(~0) + +static uint64_t fdtw_search_all_xlat_entries(const void *dtb, + const struct fdt_property *ranges_prop, + int local_bus, uint64_t base_address) +{ + uint64_t translated_addr; + const uint32_t *next_entry; + int parent_bus_node, nxlat_entries, length; + int self_addr_cells, parent_addr_cells, self_size_cells, ncells_xlat; + + /* + * The number of cells in one translation entry in ranges is the sum of + * the following values: + * self#address-cells + parent#address-cells + self#size-cells + * Ex: the iofpga ranges property has one translation entry with 4 cells + * They represent iofpga#addr-cells + motherboard#addr-cells + iofpga#size-cells + * = 1 + 2 + 1 + */ + + parent_bus_node = fdt_parent_offset(dtb, local_bus); + self_addr_cells = fdt_address_cells(dtb, local_bus); + self_size_cells = fdt_size_cells(dtb, local_bus); + parent_addr_cells = fdt_address_cells(dtb, parent_bus_node); + + /* Number of cells per translation entry i.e., mapping */ + ncells_xlat = self_addr_cells + parent_addr_cells + self_size_cells; + + assert(ncells_xlat > 0); + + /* + * Find the number of translations(mappings) specified in the current + * `ranges` property. Note that length represents number of bytes and + * is stored in big endian mode. + */ + length = fdt32_to_cpu(ranges_prop->len); + nxlat_entries = (length/sizeof(uint32_t))/ncells_xlat; + + assert(nxlat_entries > 0); + + next_entry = (const uint32_t *)ranges_prop->data; + + /* Iterate over the entries in the "ranges" */ + for (int i = 0; i < nxlat_entries; i++) { + if (fdtw_xlat_hit(next_entry, self_addr_cells, + parent_addr_cells, self_size_cells, base_address, + &translated_addr)){ + return translated_addr; + } + next_entry = next_entry + ncells_xlat; + } + + INFO("DT: No translation found for address %" PRIx64 " in node %s\n", + base_address, fdt_get_name(dtb, local_bus, NULL)); + return ILLEGAL_ADDR; +} + + +/******************************************************************************* + * address mapping needs to be done recursively starting from current node to + * root node through all intermediate parent nodes. + * Sample device tree is shown here: + +smb@0,0 { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + v2m_serial1: uart@a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <0 6 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + }; +}; + + * As seen above, there are 3 levels of address translations needed. An empty + * `ranges` property denotes identity mapping (as seen in `motherboard` node). + * Each ranges property can map a set of child addresses to parent bus. Hence + * there can be more than 1 (translation) entry in the ranges property as seen + * in the `smb` node which has 6 translation entries. + ******************************************************************************/ + +/* Recursive implementation */ +uint64_t fdtw_translate_address(const void *dtb, int node, + uint64_t base_address) +{ + int length, local_bus_node; + const char *node_name; + uint64_t global_address; + + local_bus_node = fdt_parent_offset(dtb, node); + node_name = fdt_get_name(dtb, local_bus_node, NULL); + + /* + * In the example given above, starting from the leaf node: + * uart@a000 represents the current node + * iofpga@3,00000000 represents the local bus + * motherboard represents the parent bus + */ + + /* Read the ranges property */ + const struct fdt_property *property = fdt_get_property(dtb, + local_bus_node, "ranges", &length); + + if (property == NULL) { + if (local_bus_node == 0) { + /* + * root node doesn't have range property as addresses + * are in CPU address space. + */ + return base_address; + } + INFO("DT: Couldn't find ranges property in node %s\n", + node_name); + return ILLEGAL_ADDR; + } else if (length == 0) { + /* empty ranges indicates identity map to parent bus */ + return fdtw_translate_address(dtb, local_bus_node, base_address); + } + + VERBOSE("DT: Translation lookup in node %s at offset %d\n", node_name, + local_bus_node); + global_address = fdtw_search_all_xlat_entries(dtb, property, + local_bus_node, base_address); + + if (global_address == ILLEGAL_ADDR) { + return ILLEGAL_ADDR; + } + + /* Translate the local device address recursively */ + return fdtw_translate_address(dtb, local_bus_node, global_address); +} + +/* + * For every CPU node (`/cpus/cpu@n`) in an FDT, execute a callback passing a + * pointer to the FDT and the offset of the CPU node. If the return value of the + * callback is negative, it is treated as an error and the loop is aborted. In + * this situation, the value of the callback is returned from the function. + * + * Returns `0` on success, or a negative integer representing an error code. + */ +int fdtw_for_each_cpu(const void *dtb, + int (*callback)(const void *dtb, int node, uintptr_t mpidr)) +{ + int ret = 0; + int parent, node = 0; + + parent = fdt_path_offset(dtb, "/cpus"); + if (parent < 0) { + return parent; + } + + fdt_for_each_subnode(node, dtb, parent) { + const char *name; + int len; + + uintptr_t mpidr = 0U; + + name = fdt_get_name(dtb, node, &len); + if (strncmp(name, "cpu@", 4) != 0) { + continue; + } + + ret = fdt_get_reg_props_by_index(dtb, node, 0, &mpidr, NULL); + if (ret < 0) { + break; + } + + ret = callback(dtb, node, mpidr); + if (ret < 0) { + break; + } + } + + return ret; +} diff --git a/arm-trusted-firmware/common/fdt_wrappers.mk b/arm-trusted-firmware/common/fdt_wrappers.mk new file mode 100644 index 0000000..62b8c6e --- /dev/null +++ b/arm-trusted-firmware/common/fdt_wrappers.mk @@ -0,0 +1,7 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +FDT_WRAPPERS_SOURCES := common/fdt_wrappers.c diff --git a/arm-trusted-firmware/common/image_decompress.c b/arm-trusted-firmware/common/image_decompress.c new file mode 100644 index 0000000..a4586ae --- /dev/null +++ b/arm-trusted-firmware/common/image_decompress.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +static uintptr_t decompressor_buf_base; +static uint32_t decompressor_buf_size; +static decompressor_t *decompressor; +static struct image_info saved_image_info; + +void image_decompress_init(uintptr_t buf_base, uint32_t buf_size, + decompressor_t *_decompressor) +{ + decompressor_buf_base = buf_base; + decompressor_buf_size = buf_size; + decompressor = _decompressor; +} + +void image_decompress_prepare(struct image_info *info) +{ + /* + * If the image is compressed, it should be loaded into the temporary + * buffer instead of its final destination. We save image_info, then + * override ->image_base and ->image_max_size so that load_image() will + * transfer the compressed data to the temporary buffer. + */ + saved_image_info = *info; + info->image_base = decompressor_buf_base; + info->image_max_size = decompressor_buf_size; +} + +int image_decompress(struct image_info *info) +{ + uintptr_t compressed_image_base, image_base, work_base; + uint32_t compressed_image_size, work_size; + int ret; + + /* + * The size of compressed data has been filled by load_image(). + * Read it out before restoring image_info. + */ + compressed_image_size = info->image_size; + compressed_image_base = info->image_base; + *info = saved_image_info; + + assert(compressed_image_size <= decompressor_buf_size); + + image_base = info->image_base; + + /* + * Use the rest of the temporary buffer as workspace of the + * decompressor since the decompressor may need additional memory. + */ + work_base = compressed_image_base + compressed_image_size; + work_size = decompressor_buf_size - compressed_image_size; + + ret = decompressor(&compressed_image_base, compressed_image_size, + &image_base, info->image_max_size, + work_base, work_size); + if (ret) { + ERROR("Failed to decompress image (err=%d)\n", ret); + return ret; + } + + /* image_base is updated to the final pos when decompressor() exits. */ + info->image_size = image_base - info->image_base; + + flush_dcache_range(info->image_base, info->image_size); + + return 0; +} diff --git a/arm-trusted-firmware/common/runtime_svc.c b/arm-trusted-firmware/common/runtime_svc.c new file mode 100644 index 0000000..a2c0c09 --- /dev/null +++ b/arm-trusted-firmware/common/runtime_svc.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/******************************************************************************* + * The 'rt_svc_descs' array holds the runtime service descriptors exported by + * services by placing them in the 'rt_svc_descs' linker section. + * The 'rt_svc_descs_indices' array holds the index of a descriptor in the + * 'rt_svc_descs' array. When an SMC arrives, the OEN[29:24] bits and the call + * type[31] bit in the function id are combined to get an index into the + * 'rt_svc_descs_indices' array. This gives the index of the descriptor in the + * 'rt_svc_descs' array which contains the SMC handler. + ******************************************************************************/ +uint8_t rt_svc_descs_indices[MAX_RT_SVCS]; + +#define RT_SVC_DECS_NUM ((RT_SVC_DESCS_END - RT_SVC_DESCS_START)\ + / sizeof(rt_svc_desc_t)) + +/******************************************************************************* + * Function to invoke the registered `handle` corresponding to the smc_fid in + * AArch32 mode. + ******************************************************************************/ +uintptr_t handle_runtime_svc(uint32_t smc_fid, + void *cookie, + void *handle, + unsigned int flags) +{ + u_register_t x1, x2, x3, x4; + unsigned int index; + unsigned int idx; + const rt_svc_desc_t *rt_svc_descs; + + assert(handle != NULL); + idx = get_unique_oen_from_smc_fid(smc_fid); + assert(idx < MAX_RT_SVCS); + + index = rt_svc_descs_indices[idx]; + if (index >= RT_SVC_DECS_NUM) + SMC_RET1(handle, SMC_UNK); + + rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START; + + get_smc_params_from_ctx(handle, x1, x2, x3, x4); + + return rt_svc_descs[index].handle(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); +} + +/******************************************************************************* + * Simple routine to sanity check a runtime service descriptor before using it + ******************************************************************************/ +static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc) +{ + if (desc == NULL) + return -EINVAL; + + if (desc->start_oen > desc->end_oen) + return -EINVAL; + + if (desc->end_oen >= OEN_LIMIT) + return -EINVAL; + + if ((desc->call_type != SMC_TYPE_FAST) && + (desc->call_type != SMC_TYPE_YIELD)) + return -EINVAL; + + /* A runtime service having no init or handle function doesn't make sense */ + if ((desc->init == NULL) && (desc->handle == NULL)) + return -EINVAL; + + return 0; +} + +/******************************************************************************* + * This function calls the initialisation routine in the descriptor exported by + * a runtime service. Once a descriptor has been validated, its start & end + * owning entity numbers and the call type are combined to form a unique oen. + * The unique oen is used as an index into the 'rt_svc_descs_indices' array. + * The index of the runtime service descriptor is stored at this index. + ******************************************************************************/ +void __init runtime_svc_init(void) +{ + int rc = 0; + uint8_t index, start_idx, end_idx; + rt_svc_desc_t *rt_svc_descs; + + /* Assert the number of descriptors detected are less than maximum indices */ + assert((RT_SVC_DESCS_END >= RT_SVC_DESCS_START) && + (RT_SVC_DECS_NUM < MAX_RT_SVCS)); + + /* If no runtime services are implemented then simply bail out */ + if (RT_SVC_DECS_NUM == 0U) + return; + + /* Initialise internal variables to invalid state */ + (void)memset(rt_svc_descs_indices, -1, sizeof(rt_svc_descs_indices)); + + rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START; + for (index = 0U; index < RT_SVC_DECS_NUM; index++) { + rt_svc_desc_t *service = &rt_svc_descs[index]; + + /* + * An invalid descriptor is an error condition since it is + * difficult to predict the system behaviour in the absence + * of this service. + */ + rc = validate_rt_svc_desc(service); + if (rc != 0) { + ERROR("Invalid runtime service descriptor %p\n", + (void *) service); + panic(); + } + + /* + * The runtime service may have separate rt_svc_desc_t + * for its fast smc and yielding smc. Since the service itself + * need to be initialized only once, only one of them will have + * an initialisation routine defined. Call the initialisation + * routine for this runtime service, if it is defined. + */ + if (service->init != NULL) { + rc = service->init(); + if (rc != 0) { + ERROR("Error initializing runtime service %s\n", + service->name); + continue; + } + } + + /* + * Fill the indices corresponding to the start and end + * owning entity numbers with the index of the + * descriptor which will handle the SMCs for this owning + * entity range. + */ + start_idx = (uint8_t)get_unique_oen(service->start_oen, + service->call_type); + end_idx = (uint8_t)get_unique_oen(service->end_oen, + service->call_type); + assert(start_idx <= end_idx); + assert(end_idx < MAX_RT_SVCS); + for (; start_idx <= end_idx; start_idx++) + rt_svc_descs_indices[start_idx] = index; + } +} diff --git a/arm-trusted-firmware/common/tf_crc32.c b/arm-trusted-firmware/common/tf_crc32.c new file mode 100644 index 0000000..b33d36e --- /dev/null +++ b/arm-trusted-firmware/common/tf_crc32.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +/* compute CRC using Arm intrinsic function + * + * This function is useful for the platforms with the CPU ARMv8.0 + * (with CRC instructions supported), and onwards. + * Platforms with CPU ARMv8.0 should make sure to add a compile switch + * '-march=armv8-a+crc" for successful compilation of this file. + * + * @crc: previous accumulated CRC + * @buf: buffer base address + * @size: the size of the buffer + * + * Return calculated CRC value + */ +uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size) +{ + assert(buf != NULL); + + uint32_t calc_crc = ~crc; + const unsigned char *local_buf = buf; + size_t local_size = size; + + /* + * calculate CRC over byte data + */ + while (local_size != 0UL) { + calc_crc = __crc32b(calc_crc, *local_buf); + local_buf++; + local_size--; + } + + return ~calc_crc; +} diff --git a/arm-trusted-firmware/common/tf_log.c b/arm-trusted-firmware/common/tf_log.c new file mode 100644 index 0000000..68f1be4 --- /dev/null +++ b/arm-trusted-firmware/common/tf_log.c @@ -0,0 +1,79 @@ +/* + * 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); +} + +void tf_log_newline(const char log_fmt[2]) +{ + unsigned int log_level = log_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; + + putchar('\n'); +} + +/* + * 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/arm-trusted-firmware/common/uuid.c b/arm-trusted-firmware/common/uuid.c new file mode 100644 index 0000000..ac6db50 --- /dev/null +++ b/arm-trusted-firmware/common/uuid.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include + +/* Return the hex nibble value of a char */ +static int8_t hex_val(char hex) +{ + int8_t val = 0; + + if ((hex >= '0') && (hex <= '9')) { + val = (int8_t)(hex - '0'); + } else if ((hex >= 'a') && (hex <= 'f')) { + val = (int8_t)(hex - 'a' + 0xa); + } else if ((hex >= 'A') && (hex <= 'F')) { + val = (int8_t)(hex - 'A' + 0xa); + } else { + val = -1; + } + + return val; +} + +/* + * Read hex_src_len hex characters from hex_src, convert to bytes and + * store in buffer pointed to by dest + */ +static int read_hex(uint8_t *dest, char *hex_src, unsigned int hex_src_len) +{ + int8_t nibble; + uint8_t byte; + + /* + * The string length must be a multiple of 2 to represent an + * exact number of bytes. + */ + assert((hex_src_len % 2U) == 0U); + + for (unsigned int i = 0U; i < (hex_src_len / 2U); i++) { + nibble = 0; + byte = 0U; + + nibble = hex_val(hex_src[2U * i]); + if (nibble < 0) { + return -1; + } + byte = (uint8_t)nibble; + byte <<= 4U; + + nibble = hex_val(hex_src[(2U * i) + 1U]); + if (nibble < 0) { + return -1; + } + byte |= (uint8_t)nibble; + + *dest = byte; + dest++; + } + + return 0; +} + +/* Parse UUIDs of the form aabbccdd-eeff-4099-8877-665544332211 */ +int read_uuid(uint8_t *dest, char *uuid) +{ + int err; + uint8_t *dest_start = dest; + + /* Check that we have enough characters */ + if (strnlen(uuid, UUID_STRING_LENGTH) != UUID_STRING_LENGTH) { + WARN("UUID string is too short\n"); + return -EINVAL; + } + + /* aabbccdd */ + err = read_hex(dest, uuid, 8); + uuid += 8; + dest += 4; + + /* Check for '-' */ + err |= ((*uuid == '-') ? 0 : -1); + uuid++; + + /* eeff */ + err |= read_hex(dest, uuid, 4); + uuid += 4; + dest += 2; + + /* Check for '-' */ + err |= ((*uuid == '-') ? 0 : -1); + uuid++; + + /* 4099 */ + err |= read_hex(dest, uuid, 4); + uuid += 4; + dest += 2; + + /* Check for '-' */ + err |= ((*uuid == '-') ? 0 : -1); + uuid++; + + /* 8877 */ + err |= read_hex(dest, uuid, 4); + uuid += 4; + dest += 2; + + /* Check for '-' */ + err |= ((*uuid == '-') ? 0 : -1); + uuid++; + + /* 665544332211 */ + err |= read_hex(dest, uuid, 12); + uuid += 12; + dest += 6; + + if (err < 0) { + WARN("Error parsing UUID\n"); + /* Clear the buffer on error */ + memset((void *)dest_start, '\0', UUID_BYTES_LENGTH * sizeof(uint8_t)); + return -EINVAL; + } + + return 0; +} + diff --git a/arm-trusted-firmware/dco.txt b/arm-trusted-firmware/dco.txt new file mode 100644 index 0000000..8201f99 --- /dev/null +++ b/arm-trusted-firmware/dco.txt @@ -0,0 +1,37 @@ +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/arm-trusted-firmware/docs/Makefile b/arm-trusted-firmware/docs/Makefile new file mode 100644 index 0000000..3dd7ebc --- /dev/null +++ b/arm-trusted-firmware/docs/Makefile @@ -0,0 +1,25 @@ +# +# Copyright (c) 2019-2020, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -W +SPHINXBUILD = sphinx-build +SPHINXPROJ = TrustedFirmware-A +SOURCEDIR = . +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/arm-trusted-firmware/docs/_static/css/custom.css b/arm-trusted-firmware/docs/_static/css/custom.css new file mode 100644 index 0000000..f6f5fa0 --- /dev/null +++ b/arm-trusted-firmware/docs/_static/css/custom.css @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Set the white-space property of tables to normal. + * With this setting sequences of whitespace inside + * a table will collapse into a single whitespace, + * and text will wrap when necessary. + */ +.wy-table-responsive table td { +white-space: normal; +} diff --git a/arm-trusted-firmware/docs/about/acknowledgements.rst b/arm-trusted-firmware/docs/about/acknowledgements.rst new file mode 100644 index 0000000..dfc66c8 --- /dev/null +++ b/arm-trusted-firmware/docs/about/acknowledgements.rst @@ -0,0 +1,22 @@ +Contributor Acknowledgements +============================ + +.. note:: + This file is only relevant for legacy contributions, to acknowledge the + specific contributors referred to in "Arm Limited and Contributors" copyright + notices. As contributors are now encouraged to put their name or company name + directly into the copyright notices, this file is not relevant for new + contributions. See the :ref:`License` document for the correct template to + use for new contributions. + +- Linaro Limited +- Marvell International Ltd. +- NVIDIA Corporation +- NXP Semiconductors +- Socionext Inc. +- STMicroelectronics +- Xilinx, Inc. + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/about/contact.rst b/arm-trusted-firmware/docs/about/contact.rst new file mode 100644 index 0000000..4440a37 --- /dev/null +++ b/arm-trusted-firmware/docs/about/contact.rst @@ -0,0 +1,56 @@ +Support & Contact +----------------- + +We welcome any feedback on |TF-A| and there are several methods for providing +it or for obtaining support. + +.. warning:: + If you think you have found a security vulnerability, please report this using + the process defined in the :ref:`Security Handling` document. + +Mailing Lists +^^^^^^^^^^^^^ + +Public mailing lists for TF-A and the wider Trusted Firmware project are +hosted on TrustedFirmware.org. The mailing lists can be used for general +enquiries, enhancement requests and issue reports, or to follow and participate +in technical or organizational discussions around the project. These discussions +include design proposals, advance notice of changes and upcoming events. + +The relevant lists for the TF-A project are: + +- `TF-A development`_ +- `TF-A-Tests development`_ + +You can see a `summary of all the lists`_ on the TrustedFirmware.org website. + +Open Tech Forum Call +^^^^^^^^^^^^^^^^^^^^ + +Every other week, we organize a call with all interested TF-A contributors. +Anyone is welcome to join. This is an opportunity to discuss any technical +topic within the community. More details can be found `here`_. + +.. _here: https://www.trustedfirmware.org/meetings/tf-a-technical-forum/ + +Issue Tracker +^^^^^^^^^^^^^ + +Bug reports may be filed on the `issue tracker`_ on the TrustedFirmware.org +website. Using this tracker gives everyone visibility of the known issues in +TF-A. + +Arm Licensees +^^^^^^^^^^^^^ + +Arm licensees have an additional support conduit - they may contact Arm directly +via their partner managers. + +.. _`issue tracker`: https://developer.trustedfirmware.org +.. _`TF-A development`: https://lists.trustedfirmware.org/pipermail/tf-a/ +.. _`TF-A-Tests development`: https://lists.trustedfirmware.org/pipermail/tf-a-tests/ +.. _`summary of all the lists`: https://lists.trustedfirmware.org + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/about/features.rst b/arm-trusted-firmware/docs/about/features.rst new file mode 100644 index 0000000..4b7fbe5 --- /dev/null +++ b/arm-trusted-firmware/docs/about/features.rst @@ -0,0 +1,127 @@ +Feature Overview +================ + +This page provides an overview of the current |TF-A| feature set. For a full +description of these features and their implementation details, please see +the documents that are part of the *Components* and *System Design* chapters. + +The :ref:`Change Log & Release Notes` provides details of changes made since the +last release. + +Current features +---------------- + +- Initialization of the secure world, for example exception vectors, control + registers and interrupts for the platform. + +- Library support for CPU specific reset and power down sequences. This + includes support for errata workarounds and the latest Arm DynamIQ CPUs. + +- Drivers to enable standard initialization of Arm System IP, for example + Generic Interrupt Controller (GIC), Cache Coherent Interconnect (CCI), + Cache Coherent Network (CCN), Network Interconnect (NIC) and TrustZone + Controller (TZC). + +- A generic |SCMI| driver to interface with conforming power controllers, for + example the Arm System Control Processor (SCP). + +- SMC (Secure Monitor Call) handling, conforming to the `SMC Calling + Convention`_ using an EL3 runtime services framework. + +- |PSCI| library support for CPU, cluster and system power management + use-cases. + This library is pre-integrated with the AArch64 EL3 Runtime Software, and + is also suitable for integration with other AArch32 EL3 Runtime Software, + for example an AArch32 Secure OS. + +- A minimal AArch32 Secure Payload (*SP_MIN*) to demonstrate |PSCI| library + integration with AArch32 EL3 Runtime Software. + +- Secure Monitor library code such as world switching, EL1 context management + and interrupt routing. + When a Secure-EL1 Payload (SP) is present, for example a Secure OS, the + AArch64 EL3 Runtime Software must be integrated with a Secure Payload + Dispatcher (SPD) component to customize the interaction with the SP. + +- A Test SP and SPD to demonstrate AArch64 Secure Monitor functionality and SP + interaction with PSCI. + +- SPDs for the `OP-TEE Secure OS`_, `NVIDIA Trusted Little Kernel`_ + and `Trusty Secure OS`_. + +- A Trusted Board Boot implementation, conforming to all mandatory TBBR + requirements. This includes image authentication, Firmware Update (or + recovery mode), and packaging of the various firmware images into a + Firmware Image Package (FIP). + +- Pre-integration of TBB with the Arm CryptoCell product, to take advantage of + its hardware Root of Trust and crypto acceleration services. + +- Reliability, Availability, and Serviceability (RAS) functionality, including + + - A Secure Partition Manager (SPM) to manage Secure Partitions in + Secure-EL0, which can be used to implement simple management and + security services. + + - An |SDEI| dispatcher to route interrupt-based |SDEI| events. + + - An Exception Handling Framework (EHF) that allows dispatching of EL3 + interrupts to their registered handlers, to facilitate firmware-first + error handling. + +- A dynamic configuration framework that enables each of the firmware images + to be configured at runtime if required by the platform. It also enables + loading of a hardware configuration (for example, a kernel device tree) + as part of the FIP, to be passed through the firmware stages. + This feature is now incorporated inside the firmware configuration framework + (fconf). + +- Support for alternative boot flows, for example to support platforms where + the EL3 Runtime Software is loaded using other firmware or a separate + secure system processor, or where a non-TF-A ROM expects BL2 to be loaded + at EL3. + +- Support for the GCC, LLVM and Arm Compiler 6 toolchains. + +- Support for combining several libraries into a "romlib" image that may be + shared across images to reduce memory footprint. The romlib image is stored + in ROM but is accessed through a jump-table that may be stored + in read-write memory, allowing for the library code to be patched. + +- Support for the Secure Partition Manager Dispatcher (SPMD) component as a + new standard service. + +- Support for ARMv8.3 pointer authentication in the normal and secure worlds. + The use of pointer authentication in the normal world is enabled whenever + architectural support is available, without the need for additional build + flags. + +- Position-Independent Executable (PIE) support. Currently for BL2, BL31, and + TSP, with further support to be added in a future release. + +Still to come +------------- + +- Support for additional platforms. + +- Refinements to Position Independent Executable (PIE) support. + +- Continued support for the FF-A v1.0 (formally known as SPCI) specification, to enable the + use of secure partition management in the secure world. + +- Documentation enhancements. + +- Ongoing support for new architectural features, CPUs and System IP. + +- Ongoing support for new Arm system architecture specifications. + +- Ongoing security hardening, optimization and quality improvements. + +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _OP-TEE Secure OS: https://github.com/OP-TEE/optee_os +.. _NVIDIA Trusted Little Kernel: http://nv-tegra.nvidia.com/gitweb/?p=3rdparty/ote_partner/tlk.git;a=summary +.. _Trusty Secure OS: https://source.android.com/security/trusty + +-------------- + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/about/index.rst b/arm-trusted-firmware/docs/about/index.rst new file mode 100644 index 0000000..3a10266 --- /dev/null +++ b/arm-trusted-firmware/docs/about/index.rst @@ -0,0 +1,13 @@ +About +===== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + features + release-information + maintainers + contact + acknowledgements diff --git a/arm-trusted-firmware/docs/about/maintainers.rst b/arm-trusted-firmware/docs/about/maintainers.rst new file mode 100644 index 0000000..b58ea71 --- /dev/null +++ b/arm-trusted-firmware/docs/about/maintainers.rst @@ -0,0 +1,865 @@ +Project Maintenance +=================== + +Trusted Firmware-A (TF-A) is an open governance community project. All +contributions are ultimately merged by the maintainers listed below. Technical +ownership of most parts of the codebase falls on the code owners listed +below. An acknowledgement from these code owners is required before the +maintainers merge a contribution. + +More details may be found in the `Project Maintenance Process`_ document. + +.. |M| replace:: **Mail** +.. |G| replace:: **GitHub ID** +.. |F| replace:: **Files** + +.. _maintainers: + +Maintainers +----------- + +:|M|: Dan Handley +:|G|: `danh-arm`_ +:|M|: Soby Mathew +:|G|: `soby-mathew`_ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Mark Dykes +:|G|: `mardyk01`_ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|M|: Bipin Ravi +:|G|: `bipinravi-arm`_ +:|M|: Joanna Farley +:|G|: `joannafarley-arm`_ +:|M|: Julius Werner +:|G|: `jwerner-chromium`_ +:|M|: Varun Wadekar +:|G|: `vwadekar`_ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|M|: Lauren Wehrmeister +:|G|: `laurenw-arm`_ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Raghu Krishnamurthy +:|G|: `raghuncstate`_ + + +.. _code owners: + +Code owners +----------- + +Common Code +~~~~~~~~~~~ + +Armv7-A architecture port +^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Etienne Carriere +:|G|: `etienne-lms`_ + +Build Definitions for CMake Build System +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: / + +Software Delegated Exception Interface (SDEI) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Mark Dykes +:|G|: `mardyk01`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: services/std_svc/sdei/ + +Trusted Boot +^^^^^^^^^^^^ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|F|: drivers/auth/ + +Secure Partition Manager (SPM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Maksims Svecovs +:|G|: `max-shvetsov`_ +:|M|: Joao Alves +:|G|: `J-Alves`_ +:|F|: services/std_svc/spm\* + +Exception Handling Framework (EHF) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: bl31/ehf.c + +Realm Management Extension (RME) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Bipin Ravi +:|G|: `bipinravi-arm`_ +:|M|: Mark Dykes +:|G|: `mardyk01`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ + +Drivers, Libraries and Framework Code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Console API framework +^^^^^^^^^^^^^^^^^^^^^ +:|M|: Julius Werner +:|G|: `jwerner-chromium`_ +:|F|: drivers/console/ +:|F|: include/drivers/console.h +:|F|: plat/common/aarch64/crash_console_helpers.S + +coreboot support libraries +^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Julius Werner +:|G|: `jwerner-chromium`_ +:|F|: drivers/coreboot/ +:|F|: include/drivers/coreboot/ +:|F|: include/lib/coreboot.h +:|F|: lib/coreboot/ + +eMMC/UFS drivers +^^^^^^^^^^^^^^^^ +:|M|: Haojian Zhuang +:|G|: `hzhuang1`_ +:|F|: drivers/partition/ +:|F|: drivers/synopsys/emmc/ +:|F|: drivers/synopsys/ufs/ +:|F|: drivers/ufs/ +:|F|: include/drivers/dw_ufs.h +:|F|: include/drivers/ufs.h +:|F|: include/drivers/synopsys/dw_mmc.h + +JTAG DCC console driver +^^^^^^^^^^^^^^^^^^^^^^^ +:M: Michal Simek +:G: `michalsimek`_ +:M: Venkatesh Yadav Abbarapu +:G: `venkatesh`_ +:F: drivers/arm/dcc/ +:F: include/drivers/arm/dcc.h + +Power State Coordination Interface (PSCI) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Lauren Wehrmeister +:|G|: `laurenw-arm`_ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|F|: lib/psci/ + +DebugFS +^^^^^^^ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|F|: lib/debugfs/ + +Firmware Configuration Framework (FCONF) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|M|: Lauren Wehrmeister +:|G|: `laurenw-arm`_ +:|F|: lib/fconf/ + +Performance Measurement Framework (PMF) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Joao Alves +:|G|: `J-Alves`_ +:|M|: Jimmy Brisson +:|G|: `theotherjimmy`_ +:|F|: lib/pmf/ + +Arm CPU libraries +^^^^^^^^^^^^^^^^^ +:|M|: Lauren Wehrmeister +:|G|: `laurenw-arm`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: lib/cpus/ + +Reliability Availability Serviceabilty (RAS) framework +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|F|: lib/extensions/ras/ + +Activity Monitors Unit (AMU) extensions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: lib/extensions/amu/ + +Memory Partitioning And Monitoring (MPAM) extensions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|M|: Jimmy Brisson +:|G|: `theotherjimmy`_ +:|F|: lib/extensions/mpam/ + +Pointer Authentication (PAuth) and Branch Target Identification (BTI) extensions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|F|: lib/extensions/pauth/ + +Statistical Profiling Extension (SPE) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|M|: Jimmy Brisson +:|G|: `theotherjimmy`_ +:|F|: lib/extensions/spe/ + +Scalable Vector Extension (SVE) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jimmy Brisson +:|G|: `theotherjimmy`_ +:|F|: lib/extensions/sve/ + +Standard C library +^^^^^^^^^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: lib/libc/ + +Library At ROM (ROMlib) +^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|F|: lib/romlib/ + +Translation tables (``xlat_tables``) library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|M|: Joao Alves +:|G|: `J-Alves`_ +:|F|: lib/xlat\_tables_\*/ + +IO abstraction layer +^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|F|: drivers/io/ + +GIC driver +^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|F|: drivers/arm/gic/ + +Libfdt wrappers +^^^^^^^^^^^^^^^ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|F|: common/fdt_wrappers.c + +Firmware Encryption Framework +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Sumit Garg +:|G|: `b49020`_ +:|F|: drivers/io/io_encrypted.c +:|F|: include/drivers/io/io_encrypted.h +:|F|: include/tools_share/firmware_encrypted.h + +Measured Boot +^^^^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|F|: drivers/measured_boot +:|F|: include/drivers/measured_boot +:|F|: plat/arm/board/fvp/fvp_measured_boot.c + +System Control and Management Interface (SCMI) Server +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Etienne Carriere +:|G|: `etienne-lms`_ +:|M|: Peng Fan +:|G|: `MrVan`_ +:|F|: drivers/scmi-msg +:|F|: include/drivers/scmi\* + +Max Power Mitigation Mechanism (MPMM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: include/lib/mpmm/ +:|F|: lib/mpmm/ + +Granule Protection Tables Library (GPT-RME) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Mark Dykes +:|G|: `mardyk01`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: lib/gpt_rme +:|F|: include/lib/gpt_rme + +Platform Ports +~~~~~~~~~~~~~~ + +Allwinner ARMv8 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|M|: Samuel Holland +:|G|: `smaeul`_ +:|F|: docs/plat/allwinner.rst +:|F|: plat/allwinner/ +:|F|: drivers/allwinner/ + +Amlogic Meson S905 (GXBB) platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|F|: docs/plat/meson-gxbb.rst +:|F|: drivers/amlogic/ +:|F|: plat/amlogic/gxbb/ + +Amlogic Meson S905x (GXL) platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Remi Pommarel +:|G|: `remi-triplefault`_ +:|F|: docs/plat/meson-gxl.rst +:|F|: plat/amlogic/gxl/ + +Amlogic Meson S905X2 (G12A) platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Carlo Caione +:|G|: `carlocaione`_ +:|F|: docs/plat/meson-g12a.rst +:|F|: plat/amlogic/g12a/ + +Amlogic Meson A113D (AXG) platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Carlo Caione +:|G|: `carlocaione`_ +:|F|: docs/plat/meson-axg.rst +:|F|: plat/amlogic/axg/ + +Arm FPGA platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|F|: plat/arm/board/arm_fpga + +Arm FVP Platform port +^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|F|: plat/arm/board/fvp + +Arm Juno Platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: plat/arm/board/juno + +Arm Morello and N1SDP Platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manoj Kumar +:|G|: `manojkumar-arm`_ +:|M|: Chandni Cherukuri +:|G|: `chandnich`_ +:|F|: plat/arm/board/morello +:|F|: plat/arm/board/n1sdp + +Arm Rich IoT Platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Abdellatif El Khlifi +:|G|: `abdellatif-elkhlifi`_ +:|M|: Vishnu Banavath +:|G|: `vishnu-banavath`_ +:|F|: plat/arm/board/corstone700 +:|F|: plat/arm/board/a5ds +:|F|: plat/arm/board/corstone1000 + +Arm Reference Design platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Thomas Abraham +:|G|: `thomas-arm`_ +:|M|: Vijayenthiran Subramaniam +:|G|: `vijayenthiran-arm`_ +:|F|: plat/arm/css/sgi/ +:|F|: plat/arm/board/rde1edge/ +:|F|: plat/arm/board/rdn1edge/ +:|F|: plat/arm/board/rdn2/ +:|F|: plat/arm/board/rdv1/ +:|F|: plat/arm/board/rdv1mc/ +:|F|: plat/arm/board/sgi575/ + +Arm Total Compute platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Arunachalam Ganapathy +:|G|: `arugan02`_ +:|M|: Usama Arif +:|G|: `uarif1`_ +:|F|: plat/arm/board/tc + +HiSilicon HiKey and HiKey960 platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Haojian Zhuang +:|G|: `hzhuang1`_ +:|F|: docs/plat/hikey.rst +:|F|: docs/plat/hikey960.rst +:|F|: plat/hisilicon/hikey/ +:|F|: plat/hisilicon/hikey960/ + +HiSilicon Poplar platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Shawn Guo +:|G|: `shawnguo2`_ +:|F|: docs/plat/poplar.rst +:|F|: plat/hisilicon/poplar/ + +Intel SocFPGA platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Tien Hock Loh +:|G|: `thloh85-intel`_ +:|M|: Hadi Asyrafi +:|G|: mabdulha +:|F|: plat/intel/soc +:|F|: drivers/intel/soc/ + +MediaTek platform ports +^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Rex-BC Chen +:|G|: `mtk-rex-bc-chen`_ +:|M|: Leon Chen +:|G|: `leon-chen-mtk`_ +:|F|: docs/plat/mt\*.rst +:|F|: plat/mediatek/ + +Marvell platform ports and SoC drivers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Konstantin Porotchkin +:|G|: `kostapr`_ +:|F|: docs/plat/marvell/ +:|F|: plat/marvell/ +:|F|: drivers/marvell/ +:|F|: tools/marvell/ + +NVidia platform ports +^^^^^^^^^^^^^^^^^^^^^ +:|M|: Varun Wadekar +:|G|: `vwadekar`_ +:|F|: docs/plat/nvidia-tegra.rst +:|F|: include/lib/cpus/aarch64/denver.h +:|F|: lib/cpus/aarch64/denver.S +:|F|: plat/nvidia/ + +NXP i.MX 7 WaRP7 platform port and SoC drivers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Bryan O'Donoghue +:|G|: `bryanodonoghue`_ +:|M|: Jun Nie +:|G|: `niej`_ +:|F|: docs/plat/warp7.rst +:|F|: plat/imx/common/ +:|F|: plat/imx/imx7/ +:|F|: drivers/imx/timer/ +:|F|: drivers/imx/uart/ +:|F|: drivers/imx/usdhc/ + +NXP i.MX 8 platform port +^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Peng Fan +:|G|: `MrVan`_ +:|F|: docs/plat/imx8.rst +:|F|: plat/imx/ + +NXP i.MX8M platform port +^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jacky Bai +:|G|: `JackyBai`_ +:|F|: docs/plat/imx8m.rst +:|F|: plat/imx/imx8m/ + +NXP QorIQ Layerscape common code for platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Pankaj Gupta +:|G|: `pangupta`_ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: docs/plat/nxp/ +:|F|: plat/nxp/ +:|F|: drivers/nxp/ +:|F|: tools/nxp/ + +NXP SoC Part LX2160A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Pankaj Gupta +:|G|: `pangupta`_ +:|F|: plat/nxp/soc-lx2160a +:|F|: plat/nxp/soc-lx2160a/lx2162aqds +:|F|: plat/nxp/soc-lx2160a/lx2160aqds +:|F|: plat/nxp/soc-lx2160a/lx2160ardb + +NXP SoC Part LS1028A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: plat/nxp/soc-ls1028a +:|F|: plat/nxp/soc-ls1028a/ls1028ardb + +NXP SoC Part LS1043A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: plat/nxp/soc-ls1043a +:|F|: plat/nxp/soc-ls1043a/ls1043ardb + +NXP SoC Part LS1046A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: plat/nxp/soc-ls1046a +:|F|: plat/nxp/soc-ls1046a/ls1046ardb +:|F|: plat/nxp/soc-ls1046a/ls1046afrwy +:|F|: plat/nxp/soc-ls1046a/ls1046aqds + +NXP SoC Part LS1088A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: plat/nxp/soc-ls1088a +:|F|: plat/nxp/soc-ls1088a/ls1088ardb +:|F|: plat/nxp/soc-ls1088a/ls1088aqds + +QEMU platform port +^^^^^^^^^^^^^^^^^^ +:|M|: Jens Wiklander +:|G|: `jenswi-linaro`_ +:|F|: docs/plat/qemu.rst +:|F|: plat/qemu/ + +QTI platform port +^^^^^^^^^^^^^^^^^ +:|M|: Saurabh Gorecha +:|G|: `sgorecha`_ +:|M|: Lachit Patel +:|G|: `lachitp`_ +:|M|: Sreevyshanavi Kare +:|G|: `sreekare`_ +:|M|: QTI TF Maintainers +:|F|: docs/plat/qti.rst +:|F|: plat/qti/ + +QTI MSM8916 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Stephan Gerhold +:|G|: `stephan-gh`_ +:|M|: Nikita Travkin +:|G|: `TravMurav`_ +:|F|: docs/plat/qti-msm8916.rst +:|F|: plat/qti/msm8916/ + +Raspberry Pi 3 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Ying-Chun Liu (PaulLiu) +:|G|: `grandpaul`_ +:|F|: docs/plat/rpi3.rst +:|F|: plat/rpi/rpi3/ +:|F|: plat/rpi/common/ +:|F|: drivers/rpi3/ +:|F|: include/drivers/rpi3/ + +Raspberry Pi 4 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|F|: docs/plat/rpi4.rst +:|F|: plat/rpi/rpi4/ +:|F|: plat/rpi/common/ +:|F|: drivers/rpi3/ +:|F|: include/drivers/rpi3/ + +Renesas rcar-gen3 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jorge Ramirez-Ortiz +:|G|: `ldts`_ +:|M|: Marek Vasut +:|G|: `marex`_ +:|F|: docs/plat/rcar-gen3.rst +:|F|: plat/renesas/common +:|F|: plat/renesas/rcar +:|F|: drivers/renesas/common +:|F|: drivers/renesas/rcar +:|F|: tools/renesas/rcar_layout_create + +Renesas RZ/G2 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Biju Das +:|G|: `bijucdas`_ +:|M|: Marek Vasut +:|G|: `marex`_ +:|M|: Lad Prabhakar +:|G|: `prabhakarlad`_ +:|F|: docs/plat/rz-g2.rst +:|F|: plat/renesas/common +:|F|: plat/renesas/rzg +:|F|: drivers/renesas/common +:|F|: drivers/renesas/rzg +:|F|: tools/renesas/rzg_layout_create + +RockChip platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Tony Xie +:|G|: `TonyXie06`_ +:|G|: `rockchip-linux`_ +:|M|: Heiko Stuebner +:|G|: `mmind`_ +:|M|: Julius Werner +:|G|: `jwerner-chromium`_ +:|F|: plat/rockchip/ + +STM32MP1 platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Yann Gautier +:|G|: `Yann-lms`_ +:|F|: docs/plat/stm32mp1.rst +:|F|: drivers/st/ +:|F|: fdts/stm32\* +:|F|: include/drivers/st/ +:|F|: include/dt-bindings/\*/stm32\* +:|F|: plat/st/ +:|F|: tools/stm32image/ + +Synquacer platform port +^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Sumit Garg +:|G|: `b49020`_ +:|F|: docs/plat/synquacer.rst +:|F|: plat/socionext/synquacer/ + +Texas Instruments platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Nishanth Menon +:|G|: `nmenon`_ +:|F|: docs/plat/ti-k3.rst +:|F|: plat/ti/ + +UniPhier platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Orphan +:|F|: docs/plat/socionext-uniphier.rst +:|F|: plat/socionext/uniphier/ + +Xilinx platform port +^^^^^^^^^^^^^^^^^^^^ +:|M|: Michal Simek +:|G|: `michalsimek`_ +:|M|: Venkatesh Yadav Abbarapu +:|G|: `venkatesh`_ +:|F|: docs/plat/xilinx-zynqmp.rst +:|F|: plat/xilinx/ + + +Secure Payloads and Dispatchers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +OP-TEE dispatcher +^^^^^^^^^^^^^^^^^ +:|M|: Jens Wiklander +:|G|: `jenswi-linaro`_ +:|F|: docs/components/spd/optee-dispatcher.rst +:|F|: services/spd/opteed/ + +TLK/Trusty secure payloads +^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Varun Wadekar +:|G|: `vwadekar`_ +:|F|: docs/components/spd/tlk-dispatcher.rst +:|F|: docs/components/spd/trusty-dispatcher.rst +:|F|: include/bl32/payloads/tlk.h +:|F|: services/spd/tlkd/ +:|F|: services/spd/trusty/ + +Test Secure Payload (TSP) +^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|F|: bl32/tsp/ +:|F|: services/spd/tspd/ + +Tools +~~~~~ + +Fiptool +^^^^^^^ +:|M|: Joao Alves +:|G|: `J-Alves`_ +:|F|: tools/fiptool/ + +Cert_create tool +^^^^^^^^^^^^^^^^ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|F|: tools/cert_create/ + +Encrypt_fw tool +^^^^^^^^^^^^^^^ +:|M|: Sumit Garg +:|G|: `b49020`_ +:|F|: tools/encrypt_fw/ + +Sptool +^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|F|: tools/sptool/ + +Build system +^^^^^^^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|F|: Makefile +:|F|: make_helpers/ + +Threat Model +~~~~~~~~~~~~~ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|M|: Joanna Farley +:|G|: `joannafarley-arm`_ +:|M|: Raghu Krishnamurthy +:|G|: `raghuncstate`_ +:|M|: Varun Wadekar +:|G|: `vwadekar`_ +:|F|: docs/threat_model/ + +Conventional Changelog Extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: tools/conventional-changelog-tf-a + +.. _AlexeiFedorov: https://github.com/AlexeiFedorov +.. _Andre-ARM: https://github.com/Andre-ARM +.. _Anson-Huang: https://github.com/Anson-Huang +.. _bijucdas: https://github.com/bijucdas +.. _bryanodonoghue: https://github.com/bryanodonoghue +.. _b49020: https://github.com/b49020 +.. _carlocaione: https://github.com/carlocaione +.. _danh-arm: https://github.com/danh-arm +.. _etienne-lms: https://github.com/etienne-lms +.. _glneo: https://github.com/glneo +.. _grandpaul: https://github.com/grandpaul +.. _hzhuang1: https://github.com/hzhuang1 +.. _JackyBai: https://github.com/JackyBai +.. _jenswi-linaro: https://github.com/jenswi-linaro +.. _jwerner-chromium: https://github.com/jwerner-chromium +.. _kostapr: https://github.com/kostapr +.. _lachitp: https://github.com/lachitp +.. _ldts: https://github.com/ldts +.. _marex: https://github.com/marex +.. _masahir0y: https://github.com/masahir0y +.. _michalsimek: https://github.com/michalsimek +.. _mmind: https://github.com/mmind +.. _MrVan: https://github.com/MrVan +.. _mtk-rex-bc-chen: https://github.com/mtk-rex-bc-chen +.. _leon-chen-mtk: https://github.com/leon-chen-mtk +.. _niej: https://github.com/niej +.. _npoushin: https://github.com/npoushin +.. _prabhakarlad: https://github.com/prabhakarlad +.. _remi-triplefault: https://github.com/repk +.. _rockchip-linux: https://github.com/rockchip-linux +.. _sandrine-bailleux-arm: https://github.com/sandrine-bailleux-arm +.. _sgorecha: https://github.com/sgorecha +.. _shawnguo2: https://github.com/shawnguo2 +.. _smaeul: https://github.com/smaeul +.. _soby-mathew: https://github.com/soby-mathew +.. _sreekare: https://github.com/sreekare +.. _stephan-gh: https://github.com/stephan-gh +.. _thloh85-intel: https://github.com/thloh85-intel +.. _thomas-arm: https://github.com/thomas-arm +.. _TonyXie06: https://github.com/TonyXie06 +.. _TravMurav: https://github.com/TravMurav +.. _vwadekar: https://github.com/vwadekar +.. _venkatesh: https://github.com/vabbarap +.. _Yann-lms: https://github.com/Yann-lms +.. _manish-pandey-arm: https://github.com/manish-pandey-arm +.. _mardyk01: https://github.com/mardyk01 +.. _odeprez: https://github.com/odeprez +.. _bipinravi-arm: https://github.com/bipinravi-arm +.. _joannafarley-arm: https://github.com/joannafarley-arm +.. _ManishVB-Arm: https://github.com/ManishVB-Arm +.. _max-shvetsov: https://github.com/max-shvetsov +.. _javieralso-arm: https://github.com/javieralso-arm +.. _laurenw-arm: https://github.com/laurenw-arm +.. _zelalem-aweke: https://github.com/zelalem-aweke +.. _theotherjimmy: https://github.com/theotherjimmy +.. _J-Alves: https://github.com/J-Alves +.. _madhukar-Arm: https://github.com/madhukar-Arm +.. _john-powell-arm: https://github.com/john-powell-arm +.. _raghuncstate: https://github.com/raghuncstate +.. _CJKay: https://github.com/cjkay +.. _nmenon: https://github.com/nmenon +.. _manojkumar-arm: https://github.com/manojkumar-arm +.. _chandnich: https://github.com/chandnich +.. _abdellatif-elkhlifi: https://github.com/abdellatif-elkhlifi +.. _vishnu-banavath: https://github.com/vishnu-banavath +.. _vijayenthiran-arm: https://github.com/vijayenthiran-arm +.. _arugan02: https://github.com/arugan02 +.. _uarif1: https://github.com/uarif1 +.. _pangupta: https://github.com/pangupta +.. _JiafeiPan: https://github.com/JiafeiPan + +.. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/ diff --git a/arm-trusted-firmware/docs/about/release-information.rst b/arm-trusted-firmware/docs/about/release-information.rst new file mode 100644 index 0000000..b3553ae --- /dev/null +++ b/arm-trusted-firmware/docs/about/release-information.rst @@ -0,0 +1,71 @@ +Release Processes +================= + +Project Release Cadence +----------------------- + +The project currently aims to do a release once every 6 months which will be +tagged on the master branch. There will be a code freeze (stop merging +non-essential changes) up to 4 weeks prior to the target release date. The release +candidates will start appearing after this and only bug fixes or updates +required for the release will be merged. The maintainers are free to use their +judgement on what changes are essential for the release. A release branch may be +created after code freeze if there are significant changes that need merging onto +the integration branch during the merge window. + +The release testing will be performed on release candidates and depending on +issues found, additional release candidates may be created to fix the issues. + +:: + + |<----------6 months---------->| + |<---4 weeks--->| |<---4 weeks--->| + +-----------------------------------------------------------> time + | | | | + code freeze ver w.x code freeze ver y.z + + +Upcoming Releases +~~~~~~~~~~~~~~~~~ + +These are the estimated dates for the upcoming release. These may change +depending on project requirement and partner feedback. + ++-----------------+---------------------------+------------------------------+ +| Release Version | Target Date | Expected Code Freeze | ++=================+===========================+==============================+ +| v2.0 | 1st week of Oct '18 | 1st week of Sep '18 | ++-----------------+---------------------------+------------------------------+ +| v2.1 | 5th week of Mar '19 | 1st week of Mar '19 | ++-----------------+---------------------------+------------------------------+ +| v2.2 | 4th week of Oct '19 | 1st week of Oct '19 | ++-----------------+---------------------------+------------------------------+ +| v2.3 | 4th week of Apr '20 | 1st week of Apr '20 | ++-----------------+---------------------------+------------------------------+ +| v2.4 | 2nd week of Nov '20 | 4th week of Oct '20 | ++-----------------+---------------------------+------------------------------+ +| v2.5 | 3rd week of May '21 | 5th week of Apr '21 | ++-----------------+---------------------------+------------------------------+ +| v2.6 | 4th week of Nov '21 | 2nd week of Nov '21 | ++-----------------+---------------------------+------------------------------+ +| v2.7 | 2nd week of May '22 | 4th week of Apr '22 | ++-----------------+---------------------------+------------------------------+ + +Removal of Deprecated Interfaces +-------------------------------- + +As mentioned in the :ref:`Platform Compatibility Policy`, this is a live +document cataloging all the deprecated interfaces in TF-A project and the +Release version after which it will be removed. + ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| Interface | Deprecation | Removed | Comments | +| | Date | after | | +| | | Release | | ++================================+=============+=========+=========================================================+ +| STM32MP_USE_STM32IMAGE macro | Dec '21 | 2.7 | FIP is the recommended boot method for STM32MP | ++--------------------------------+-------------+---------+---------------------------------------------------------+ + +-------------- + +*Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/change-log.md b/arm-trusted-firmware/docs/change-log.md new file mode 100644 index 0000000..ab50968 --- /dev/null +++ b/arm-trusted-firmware/docs/change-log.md @@ -0,0 +1,4746 @@ +# Change Log & Release Notes + +This document contains a summary of the new features, changes, fixes and known +issues in each release of Trusted Firmware-A. + +## [2.6.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.5..refs/tags/v2.6) (2021-11-22) + +### âš  BREAKING CHANGES + +- **Architecture** + + - **Activity Monitors Extension (FEAT_AMU)** + + - The public AMU API has been reduced to enablement only + to facilitate refactoring work. These APIs were not previously used. + + **See:** privatize unused AMU APIs ([b4b726e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b4b726ea868359cf683c07337b69fe91a2a6929a)) + + - The `PLAT_AMU_GROUP1_COUNTERS_MASK` platform definition + has been removed. Platforms should specify per-core AMU counter masks + via FCONF or a platform-specific mechanism going forward. + + **See:** remove `PLAT_AMU_GROUP1_COUNTERS_MASK` ([6c8dda1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6c8dda19e5f484f8544365fd71d965f0afc39244)) + +- **Libraries** + + - **FCONF** + + - FCONF is no longer added to BL1 and BL2 automatically + when the FCONF Makefile (`fconf.mk`) is included. When including this + Makefile, consider whether you need to add `${FCONF_SOURCES}` and + `${FCONF_DYN_SOURCES}` to `BL1_SOURCES` and `BL2_SOURCES`. + + **See:** clean up source collection ([e04da4c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e04da4c8e132f43218f18ad3b41479ca54bb9263)) + +- **Drivers** + + - **Arm** + + - **Ethos-N** + + - multi-device support + + **See:** multi-device support ([1c65989](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1c65989e70c9734defc666e824628620b2060b92)) + +### New Features + +- **Architecture** + + - **Activity Monitors Extension (FEAT_AMU)** + + - enable per-core AMU auxiliary counters ([742ca23](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/742ca2307f4e9f82cb2c21518819425e5bcc0f90)) + + - **Support for the `HCRX_EL2` register (FEAT_HCX)** + + - add build option to enable FEAT_HCX ([cb4ec47](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cb4ec47b5c73e04472984acf821e6be41b98064f)) + + - **Scalable Matrix Extension (FEAT_SME)** + + - enable SME functionality ([dc78e62](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/dc78e62d80e64bf4fe5d5bf4844a7bd1696b7c92)) + + - **Scalable Vector Extension (FEAT_SVE)** + + - enable SVE for the secure world ([0c5e7d1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0c5e7d1ce376cabcebebc43dbf238fe4482ab2dc)) + + - **System Register Trace Extensions (FEAT_ETMv4, FEAT_ETE and FEAT_ETEv1.1)** + + - enable trace system registers access from lower NS ELs ([d4582d3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d4582d30885673987240cf01fd4f5d2e6780e84c)) + - initialize trap settings of trace system registers access ([2031d61](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2031d6166a58623ae59034bc2353fcd2fabe9c30)) + + - **Trace Buffer Extension (FEAT_TRBE)** + + - enable access to trace buffer control registers from lower NS EL ([813524e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/813524ea9d2e4138246b8f77a772299e52fb33bc)) + - initialize trap settings of trace buffer control registers access ([40ff907](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/40ff90747098ed9d2a09894d1a886c10ca76cee6)) + + - **Self-hosted Trace Extension (FEAT_TRF)** + + - enable trace filter control register access from lower NS EL ([8fcd3d9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8fcd3d9600bb2cb6809c6fc68f945ce3ad89633d)) + - initialize trap settings of trace filter control registers access ([5de20ec](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5de20ece38f782c8459f546a08c6a97b9e0f5bc5)) + + - **RME** + + - add context management changes for FEAT_RME ([c5ea4f8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c5ea4f8a6679131010636eb524d2a15b709d0196)) + - add ENABLE_RME build option and support for RMM image ([5b18de0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5b18de09e80f87963df9a2e451c47e2321b8643a)) + - add GPT Library ([1839012](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1839012d5b5d431f7ec307230eae9890a5fe7477)) + - add Realm security state definition ([4693ff7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4693ff7225faadc5ad1bcd1c2fb3fbbb8fe1aed0)) + - add register definitions and helper functions for FEAT_RME ([81c272b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/81c272b3b71af38bc5cfb10bbe5722e328a1578e)) + - add RMM dispatcher (RMMD) ([77c2775](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77c2775323a5ff8b77230f05c0cc57f830e9f153)) + - add Test Realm Payload (TRP) ([50a3056](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/50a3056a3cd33d395e8712e1d1e67a8840bf3db1)) + - add xlat table library changes for FEAT_RME ([3621823](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/362182386bafbda9e6671be921fa30cc20610d30)) + - disable Watchdog for Arm platforms if FEAT_RME enabled ([07e96d1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/07e96d1d2958b6f121476fd391ac67bf8c2c4735)) + - run BL2 in root world when FEAT_RME is enabled ([6c09af9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6c09af9f8b36cdfa1dc4d5052f7e4792f63fa88a)) + +- **Platforms** + + - **Allwinner** + + - add R329 support ([13bacd3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/13bacd3bc3e6b76009adf9183e5396b6457eb12c)) + + - **Arm** + + - add FWU support in Arm platforms ([2f1177b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2f1177b2b9ebec3b2fe92607cd771bda1dc9cbfc)) + - add GPT initialization code for Arm platforms ([deb4b3a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/deb4b3a63e3a52f2e9823865a1932f6289ccb7ac)) + - add GPT parser support ([ef1daa4](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ef1daa420f7b2920b2ee35379de2aefed6ab2605)) + - enable PIE when RESET_TO_SP_MIN=1 ([7285fd5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7285fd5f9aa6d9cc0e0f1dc9c71785b46a88d999)) + + - **FPGA** + + - add ITS autodetection ([d7e39c4](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d7e39c43f2f58aabb085ed7b8f461f9ece6002d0)) + - add kernel trampoline ([de9fdb9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/de9fdb9b5925ae08137d4212a85e9a1d319509c9)) + - determine GICR base by probing ([93b785f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/93b785f5ae66a6418581c304c83a346e8baa5aa3)) + - query PL011 to learn system frequency ([d850169](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d850169c9c233c4bc413d8319196557b54683688)) + - support GICv4 images ([c69f815](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c69f815b09ab85d3ace8fd2979ffafb1184ec76c)) + - write UART baud base clock frequency into DTB ([422b44f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/422b44fb56db7ca8b1a2f9f706733d7d4c2fdeb1)) + + - **FVP** + + - enable external SP images in BL2 config ([33993a3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/33993a3737737a03ee5a9d386d0a027bdc947c9c)) + - add memory map for FVP platform for FEAT_RME ([c872072](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c8720729726faffc39ec64f3a02440a48c8c305a)) + - add RMM image support for FVP platform ([9d870b7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9d870b79c16ef09b0c4a9db18e071c2fa235d1ad)) + - enable trace extension features by default ([cd3f0ae](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cd3f0ae6f855b2998bc09e5c3a458528c92acb90)) + - pass Event Log addr and size from BL1 to BL2 ([0500f44](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0500f4479eb1d0d5ab9e83dac42b633a5ff677dd)) + + - **FVP-R** + + - support for TB-R has been added + - configure system registers to boot rich OS ([28bbbf3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/28bbbf3bf583e0c85004727e694455dfcabd50a4)) + + - **RD** + + - **RD-N2** + + - add support for variant 1 of rd-n2 platform ([fe5d5bb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fe5d5bbfe6bd0f386f92bdc419a7e04d885d5b43)) + - add tzc master source ids for soc dma ([3139270](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3139270693ab0fc6d66fed4fe11e183829b47e2e)) + + - **SGI** + + - add CPU specific handler for Neoverse N2 ([d932a58](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d932a5831e26620d61d171d0fd8bc2f14938e6f1)) + - add CPU specific handler for Neoverse V1 ([cbee43e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cbee43ebd69377bce1c4fa8d40c6fd67f2be2ee4)) + - increase max BL2 size ([7186a29](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7186a29bbfe3044d5e8001ddfe1d9238578e0944)) + - enable AMU for RD-V1-MC ([e8b119e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e8b119e03ad9de5fc440e5929287c94c22fc3946)) + - enable use of PSCI extended state ID format ([7bd64c7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7bd64c70e91f73a236b84fb51d5045e308479b5a)) + - introduce platform variant build option ([cfe1506](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cfe1506ee8303d9e0714b3a5b2cd165f76ad5d11)) + + - **TC** + + - enable MPMM ([c19a82b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c19a82bef08df58350f1b6668e0604ff8a5bd46d)) + - Enable SVE for both secure and non-secure world ([10198ea](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/10198eab3aa7b0eeba10d9667197816b052ba3e4)) + - populate HW_CONFIG in BL31 ([34a87d7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/34a87d74d9fbbe8037431ea5101110a9f1cf30e1)) + - introduce TC1 platform ([6ec0c65](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6ec0c65b09745fd0f4cee44ee3aa99870303f448)) + - add DRAM2 to TZC non-secure region ([76b4a6b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/76b4a6bb208c22b1c5971964a209ff7d54982348)) + + - add bootargs node ([4a840f2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4a840f27cd7a05d8e3687aa325adcd019c0d22ee)) + - add cpu capacity to provide scheduling information ([309f593](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/309f5938e610c73cb51b3ba175fed971f49d0888)) + - add Ivy partition ([a19bd32](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a19bd32ed14c33571f3715198d47bac9d0f2808e)) + - add support for trusted services ([ca93248](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ca9324819ee308f9b3a4bb004f02a512c8f301f6)) + - update Matterhorn ELP DVFS clock index ([a2f6294](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a2f6294c98935895d4592ef7e30058ca6e995f4b)) + - update mhuv2 dts node to align with upstream driver ([63067ce](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/63067ce87e4afa193b2c7f6a4917d1e54b61b000)) + + - **Diphda** + + - adding the diphda platform ([bf3ce99](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bf3ce9937182e5d8d91e058baabb8213acedacdb)) + - disabling non volatile counters in diphda ([7f70cd2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7f70cd29235cc5e96ff6b5f509c7e4260bec5610)) + - enabling stack protector for diphda ([c7e4f1c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c7e4f1cfb84136a7521f26e403a6635ffdce4a2b)) + + - **Marvell** + + - introduce t9130_cex7_eval ([d01139f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d01139f3b59a1bc6542e74f52ff3fb26eea23c69)) + + - **Armada** + + - **A8K** + + - allow overriding default paths ([0b702af](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0b702afc3aabc349a513a5b00397b58a62fea634)) + + - **MediaTek** + + - enable software reset for CIRQ ([b3b162f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b3b162f3b48e087f6656513862a6f9e1fa0757b1)) + + - **MT8192** + + - add DFD control in SiP service ([5183e63](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5183e637a0496ad8dfbd8c892bc874ac6a1531bf)) + + - **MT8195** + + - add DFD control in SiP service ([3b994a7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3b994a75306cc487144dd8e2e15433799e62e6f2)) + - add display port control in SiP service ([7eb4223](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7eb42237575eb3f241c9b22efc5fe91368470aa6)) + - remove adsp event from wakeup source ([c260b32](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c260b3246b6be27c7463d36ce7f76368c94a8540)) + - add DCM driver ([49d3bd8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49d3bd8c4c80ecd19ecfd74812ff1eaa01478cdd)) + - add EMI MPU basic drivers ([75edd34](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/75edd34ade8efaa8a76c5fd59103454023632989)) + - add SPM suspend driver ([859e346](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/859e346b89461f31df17b76ef25ce9e8d2a7279d)) + - add support for PTP3 ([0481896](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/048189637ead887787bd5bc47b1dfab98f321705)) + - add vcore-dvfs support ([d562130](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d562130ea9637b885135a5efe41cb98f2365754f)) + - support MCUSYS off when system suspend ([d336e09](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d336e093dd9ec917ce69484eae8914d98efa328d)) + + - **NXP** + + - add build macro for BOOT_MODE validation checking ([cd1280e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cd1280ea2e5c8be6f28485a2d5054d06e54e74c1)) + - add CCI and EPU address definition ([6cad59c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6cad59c429b4382ad62aee3a67fa1b3fd4ad38b7)) + - add EESR register definition ([8bfb168](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8bfb16813aff9b3dcbeaa2f77027d44b97f04b6d)) + - add SecMon register definition for ch_3_2 ([66f7884](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/66f7884b5229b1d2977d73d105af1c34cb55f95d)) + - define common macro for ARM registers ([35efe7a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/35efe7a4cea4b3c55b661aac49ef1a85ca8feaa9)) + - define default PSCI features if not defined ([a204785](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a2047853224083328ef67cacbc17a2001ba14701)) + - define default SD buffer ([4225ce8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4225ce8b87635287ecf5cd3baaf31ea703a2640b)) + + - **i.MX** + + - **i.MX 8M** + + - add sdei support for i.MX8MN ([ce2be32](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ce2be321e8a5865871810b36c580181ea95a1a64)) + - add sdei support for i.MX8MP ([6b63125](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6b63125c415491417e1c389e4015be5ebdee2841)) + - add SiP call for secondary boot ([9ce232f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9ce232fe985a0bb308af459ede8a22629255d4e7)) + - add system_reset2 implementation ([60a0dde](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/60a0dde91bd03f4011c1d52d4d3aea8166e939a0)) + + - **i.MX 8M Mini** + + - enlarge BL33 (U-boot) size in FIP ([d53c9db](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d53c9dbf9ff9c435552b62f47fb95bfe86d025e3)) + + - **i.MX 8M Plus** + + - add imx8mp_private.h to the build ([91566d6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/91566d663b26434813fa674412bb695be1965557)) + - add in BL2 with FIP ([75fbf55](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/75fbf5546b7beca93e4782bc35906f9536392e04)) + - add initial definition to facilitate FIP layout ([f696843](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f696843eab5cf0547b6c6307eaccea25678654c4)) + - enable Trusted Boot ([a16ecd2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a16ecd2cff36b3a8a76d223f4e272e165c941b31)) + + - **Layerscape** + + - add ls1028a soc and board support ([52a1e9f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/52a1e9ff37251987b71b743951038cd8d1fa0ba4)) + + - **LX2** + + - add SUPPORTED_BOOT_MODE definition ([28b3221](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/28b3221aebdd48577e2288a75cd2f7547da514e9)) + + - **LS1028A** + + - add ls1028a soc support ([9d250f0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9d250f03d7a38cac86655495879b2151b877db0d)) + + - **LS1028ARDB** + + - add ls1028ardb board support ([34e2112](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/34e2112d1a3a8e4ea33a24bdc6505518266333a9)) + + - **QTI** + + - **SC7280** + + - add support for pmk7325 ([b8a0511](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b8a05116ed2a87a9689c4f9be6218a4bce88034a)) + - support for qti sc7280 plat ([46ee50e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/46ee50e0b34e19d383a28bc3b3dadbfb4c07b270)) + + - **Renesas** + + - **R-Car** + + - change process for Suspend To RAM ([731aa26](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/731aa26f38d76645b6d50077c28dffb9b02dd08a)) + + - **R-Car 3** + + - add a DRAM size setting for M3N ([f95d551](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f95d551217a287bd909aa3c82f4ade4986ad7244)) + - add new board revision for Salvator-XS/H3ULCB ([4379a3e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4379a3e9744cf3b0844446335aca40357a889b9a)) + - add optional support for gzip-compressed BL33 ([ddf2ca0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ddf2ca03979ea9fad305b1bc59beb6e27f0e1c02)) + - add process of SSCG setting for R-Car D3 ([14f0a08](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/14f0a0817297905c03ddf2c4c6040482ef71d744)) + - add process to back up X6 and X7 register's value ([7d58aed](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7d58aed3b05fa8c677a7c823c1ca5017a462a3d3)) + - add SYSCEXTMASK bit set/clear in scu_power_up ([63a7a34](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/63a7a34706eedba4d13ce6fc661a634801cf8909)) + - apply ERRATA_A53_1530924 and ERRATA_A57_1319537 ([2892fed](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2892fedaf27d8bbc68780a4a2c506c768e81b9f1)) + - change the memory map for OP-TEE ([a4d821a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a4d821a5a625d941f95ec39fb51ac4fc07c46c5c)) + - emit RPC status to DT fragment if RPC unlocked ([12c75c8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/12c75c8886a0ee69d7e279a48cbeb8d1602826b3)) + - keep RWDT enabled ([8991086](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/899108601a0c3b08ead5e686d92ea0794700ff35)) + - modify LifeC register setting for R-Car D3 ([5460f82](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5460f82806752e419fdd6862e8ca9c5fefbee3f2)) + - modify operation register from SYSCISR to SYSCISCR ([d10f876](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d10f87674ecee54cffe1ab554cc05733fd16c7f0)) + - modify SWDT counter setting for R-Car D3 ([053c134](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/053c134683cf74fbf4efad311815b806821f1436)) + - remove access to RMSTPCRn registers in R-Car D3 ([71f2239](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/71f2239f53cd3137ad6abdaf0334dc53f2f21cb1)) + - update DDR setting for R-Car D3 ([042d710](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/042d710d1d917357c5142b340c79978264d3afb1)) + - update IPL and Secure Monitor Rev.3.0.0 ([c5f5bb1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c5f5bb17abfcf6c0eeb3e6c3d70499de0bd6abc0)) + - use PRR cut to determine DRAM size on M3 ([42ffd27](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/42ffd279dd1a686b19e2f1b69d2e35413d5efeba)) + + - **ST** + + - add a new DDR firewall management ([4584e01](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4584e01dc643665038004f6c8a4f8bd64e14dacb)) + - add a USB DFU stack ([efbd65f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/efbd65fa7b5cf70f20d6b18152741ccdf8a65bb6)) + - add helper to save boot interface ([7e87ba2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7e87ba2598a07facdeb73237dcb350a261ac17b6)) + - add STM32CubeProgrammer support on USB ([afad521](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/afad5214a79259f56bc2003b00859abfe8a18d4d)) + - add STM32MP_EMMC_BOOT option ([214c8a8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/214c8a8d08b2b3c24f12cbc69f497f44851ca524)) + - create new helper for DT access ([ea97bbf](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ea97bbf6a001b270fd0a25b4b0d0c382e277f3f8)) + - implement platform functions for SMCCC_ARCH_SOC_ID ([3d20178](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3d201787e8246022b1f193283c12e7cb4bfc83ff)) + - improve FIP image loading from MMC ([18b415b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/18b415be9d631b3e0c3a3caacc5f02edb9413f6b)) + - manage io_policies with FCONF ([d5a84ee](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d5a84eeaac2c8ce14d3f2662dc9523b4abf41516)) + - use FCONF to configure platform ([29332bc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/29332bcd680ce7e5f864813d9a900360f5e35d41)) + - use FIP to load images ([1d204ee](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1d204ee4ab12893fceb12097bd4f0a074be253b2)) + + - **ST32MP1** + + - add STM32MP_USB_PROGRAMMER target ([fa92fef](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fa92fef0a024cdb537fe56c84a0156cc48c1ac2d)) + - add USB DFU support for STM32MP1 ([942f6be](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/942f6be211d4816ad2568d30d807b8fd53d7f981)) + + - **Xilinx** + + - **Versal** + + - add support for SLS mitigation ([302b4df](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/302b4dfb8fb0041959b8593a098ccae6c61e3238)) + + - **ZynqMP** + + - add support for runtime feature config ([578f468](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/578f468ac058bbb60b08f78e2aa2c20cdc601620)) + - sync IOCTL IDs ([38c0b25](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/38c0b2521a0ea0951f4e1ee678ccdbce5fc07a98)) + - add SDEI support ([4143268](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4143268a5ca8f91f1014e0d83edf766946ffff76)) + - add support for XCK26 silicon ([7a30e08](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7a30e08b70e7fbb745554d500182bb6e258c5ab8)) + - extend DT description by TF-A ([0a8143d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0a8143dd636d4234dd2e79d32cb49dc80675c68f)) + +- **Bootloader Images** + + - import BL_NOBITS_{BASE,END} when defined ([9aedca0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9aedca021d917c7435aa2a0405972aa9d44493a2)) + +- **Services** + + - **FF-A** + + - adding notifications SMC IDs ([fc3f480](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fc3f480023e3a52460add25f18dd550dde44d9ff)) + - change manifest messaging method ([bb320db](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bb320dbc4751f7ea0c37ffba07d14628e58081d0)) + - feature retrieval through FFA_FEATURES call ([96b71eb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/96b71eb9597efbf4857216cac1caeefc9e8bbf3e)) + - update FF-A version to v1.1 ([e1c732d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e1c732d46fa91231b39209621ead1e5a5fb2c497)) + - add Ivy partition to tb fw config ([1bc02c2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1bc02c2e0f63b6a7863e10cf6189292d42e693db)) + - add support for FFA_SPM_ID_GET ([70c121a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/70c121a258e43dc2462ed528b44d92594ffb27b3)) + - route secure interrupts to SPMC ([8cb99c3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8cb99c3fc3539bb9926e73a1c33fd72f424fc453)) + +- **Libraries** + + - **CPU Support** + + - add support for Hayes CPU ([7bd8dfb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7bd8dfb85a8bf5c22d6a39f4538b89cc748090d1)) + - add support for Hunter CPU ([fb9e5f7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fb9e5f7bb76e9764b3ecd7973668c851015fa1b4)) + - add support for Demeter CPU ([f4616ef](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f4616efafbc1004f1330f515b898e7617e338875)) + - workaround for Cortex A78 AE erratum 1941500 ([47d6f5f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/47d6f5ff16d1f2ad009d630a381054b10fa0a06f)) + - workaround for Cortex A78 AE erratum 1951502 ([8913047](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8913047a52e646877812617a2d98cff99494487b)) + + - **MPMM** + + - add support for MPMM ([6812078](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/68120783d6d6f99c605e9f746ee0e91e2908feb1)) + + - **OP-TEE** + + - introduce optee_header_is_valid() ([b84a850](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b84a850864c05fef587fcbb301f955428966de64)) + + - **PSCI** + + - require validate_power_state to expose CPU_SUSPEND ([a1d5ac6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a1d5ac6a5aa5d9d18a481de20d272f64a71391f7)) + + - **SMCCC** + + - add bit definition for SMCCC_ARCH_SOC_ID ([96b0596](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/96b0596ea25e1f03b862a5bfaa92add6c3e51a33)) + +- **Drivers** + + - **FWU** + + - add FWU metadata header and build options ([5357f83](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5357f83d4ee89fb831d7e4f6149ae2f652e1b9af)) + - add FWU driver ([0ec3ac6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0ec3ac60d86b75d132e7a63fc09ea47e67f90bbd)) + - avoid booting with an alternate boot source ([4b48f7b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4b48f7b56577a78cdc9a2b47280cb62cbae0f7c3)) + - avoid NV counter upgrade in trial run state ([c0bfc88](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c0bfc88f8e8e03974834cbcacbbfbd5f202a2857)) + - initialize FWU driver in BL2 ([396b339](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/396b339dc20b97ddd75146e03467a255e28f31b9)) + - introduce FWU platform-specific functions declarations ([efb2ced](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/efb2ced256dacbab71ca11cbc87f70f413ca6729)) + + - **I/O** + + - **MTD** + + - offset management for FIP usage ([9a9ea82](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9a9ea82948fd2f1459b6351cb0641f3f77b4e6de)) + + - **Measured Boot** + + - add documentation to build and run PoC ([a125c55](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a125c556230501ee0f5ec9f8b0b721625d484a41)) + - move init and teardown functions to platform layer ([47bf3ac](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/47bf3ac31ec84d4b221fdef760c04b5f4416cba4)) + - image hash measurement and recording in BL1 ([48ba034](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/48ba0345f7b42880ec4442d7e90e3e1af95feadd)) + - update tb_fw_config with event log properties ([e742bcd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e742bcdae0d28dc14a2aa0b4ca30f50420bb5ebe)) + + - **MMC** + + - boot partition read support ([5014b52](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5014b52dec0c2527ca85c0fbe9c9281a24cc7b10)) + + - **MTD** + + - **NAND** + + - count bad blocks before a given offset ([bc3eebb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bc3eebb25d5ee340e56047d0e46b81d5af85ff17)) + + - **SCMI** + + - add power domain protocol ([7e4833c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7e4833cdde8235d228f1f1c40f52b989ad5aa98a)) + + - **Arm** + + - **Ethos-N** + + - multi-device support ([1c65989](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1c65989e70c9734defc666e824628620b2060b92)) + + - **GIC** + + - **GICv3** + + - detect GICv4 feature at runtime ([858f40e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/858f40e379684fefc8b52c7b9e60576bc3794a69)) + - introduce GIC component identification ([73a643e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/73a643eed9d88910a09ca666bc7ab7f5e532324e)) + - multichip: detect GIC-700 at runtime ([feb7081](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/feb7081863f454b9e465efc074ca669f7a4c783d)) + + - **GIC-600AE** + + - introduce support for Fault Management Unit ([2c248ad](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2c248ade2e958eed33127b4ea767fbb7499f31a7)) + + - **TZC** + + - **TZC-400** + + - update filters by region ([ce7ef9d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ce7ef9d146ce5ca6b9be5ef049377b3817d53d10)) + + - **MediaTek** + + - **APU** + + - add mt8192 APU device apc driver ([f46e1f1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f46e1f18539d6d992c82ae605c2cd2a1d0757fa4)) + - add mt8192 APU iommap regions ([2671f31](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2671f3187249d641c55929c812d6691aeeff502a)) + - add mt8192 APU SiP call support ([ca4c0c2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ca4c0c2e78eb19d442de4608d9096a755b540a37)) + - setup mt8192 APU_S_S_4 and APU_S_S_5 permission ([77b6801](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77b6801966d203e09ca118fad42543e934d73e6f)) + + - **EMI MPU** + + - add MPU support for DSP ([6c4973b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6c4973b0a9a75aa83233b696c97d573426eebd98)) + + - **NXP** + + - **DCFG** + + - define RSTCR_RESET_REQ ([6c5d140](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6c5d140ed99cfec47b239acc242c0f3db1e3bf7c)) + + - **FLEXSPI** + + - add MT35XU02G flash info ([a4f5015](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a4f5015a0080134251e9272719f5dad1ce2aa842)) + + - **Renesas** + + - **R-Car3** + + - add extra offset if booting B-side ([993d809](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/993d809cc115ce23dd2df1df19dc8bb548cc19cd)) + - add function to judge a DDR rank ([726050b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/726050b8e2d2ee2234e103e2df55f9c7f262c851)) + + - **ST** + + - manage boot part in io_mmc ([f3d2750](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f3d2750aa2293c0279bc447a85771827ca8b74c1)) + + - **USB** + + - add device driver for STM32MP1 ([9a138eb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9a138eb5f29f6747e181a1b3b4199ad57721a3e0)) + + - **USB** + + - add a USB device stack ([859bfd8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/859bfd8d42341c6dea2b193db79dc4828e074ad7)) + +- **Miscellaneous** + + - **Debug** + + - add new macro ERROR_NL() to print just a newline ([fd1360a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fd1360a339e84ccd49f8a2d8a42e4c131a681b3c)) + + - **CRC32** + + - **Hardware CRC32** + + - add support for HW computed CRC ([a1cedad](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a1cedadf73863ff103fecd64fa188334e1541337)) + + - **Software CRC32** + + - add software CRC32 support ([f216937](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f21693704a7bac275e12b44ae30fd210bc317175)) + + - **DT Bindings** + + - add STM32MP1 TZC400 bindings ([43de546](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/43de546b909947ab44f104aaee02b98fba70f44c)) + + - **FDT Wrappers** + + - add CPU enumeration utility function ([2d9ea36](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2d9ea360350303e37a8dd39f3599ac88aaef0ff9)) + + - **FDTs** + + - add for_each_compatible_node macro ([ff76614](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ff766148b52bfecf09728a83fc3becc7941d943c)) + - introduce wrapper function to read DT UUIDs ([d13dbb6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d13dbb6f1d5e28737a3319af035a6cb991bc6f8f)) + - add firewall regions into STM32MP1 DT ([86b43c5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/86b43c58a4105c8cef13d860dd73fa9bd560526a)) + - add IO policies for STM32MP1 ([21e002f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/21e002fb777fad9d02a94dc961f077fb444517fa)) + - add STM32MP1 fw-config DT files ([d9e0586](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d9e0586b619b331eb2db75911ca82f927e20bd1c)) + + - **STM32MP1** + + - align DT with latest kernel ([e8a953a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e8a953a9b85806f7324c8c7245435d5b9226c279)) + - delete nodes for non-used boot devices ([4357db5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4357db5b17ce6ba7357dd99276f34ab497ce60ef)) + + - **NXP** + + - **OCRAM** + + - add driver for OCRAM initialization ([10b1e13](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/10b1e13bd200849ff134dd8d2fde341a8526f563)) + + - **PSCI** + + - define CPUECTLR_TIMER_2TICKS ([3a2cc2e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3a2cc2e262890cffee1fc46835e85be6055189e8)) + +- **Dependencies** + + - **libfdt** + + - also allow changing base address ([4d585fe](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4d585fe52feb231d5e73ec50a505122d5e9bf450)) + +### Resolved Issues + +- **Architecture** + +- **Platforms** + + - print newline before fatal abort error message ([a5fea81](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a5fea8105887d0dd15edf94aebd591b1b6b5ef05)) + + - **Allwinner** + + - delay after enabling CPU power ([86a7429](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/86a7429e477786dad6fab002538aef825f4ca35a)) + + - **Arm** + + - correct UUID strings in FVP DT ([748bdd1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/748bdd19aa27c15438d829bdba42fe4062a265a1)) + - fix a VERBOSE trace ([5869ebd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5869ebd0e87f1de987e51994103440fa8c77b26f)) + - remove unused memory node ([be42c4b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/be42c4b4bf3c44f2970b7a1658c46b8d5863cad1)) + + - **FPGA** + + - allow build after MAKE_* changes ([9d38a3e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9d38a3e698331e3c8192cc3e0cc8584e6ed987d9)) + - avoid re-linking from executable ELF file ([a67ac76](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a67ac7648cd814ed8f8d4ece1b265c6d48c6dc81)) + - Change PL011 UART IRQ ([195381a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/195381a91313bc0bce2cfa087f3c55136a9e8496)) + - limit BL31 memory usage ([d457230](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d4572303ed45faceffed859955b0e71724fddfd2)) + - reserve BL31 memory ([13e16fe](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/13e16fee86451e2f871c2aac757b32299fe5ead6)) + - streamline generated axf file ([9177e4f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9177e4fd9356b0f249be8b6fe14f222e10f1e6cd)) + - enable AMU extension ([d810e30](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d810e30dd6b47e0725dccbcb42ca0a0c5215ee34)) + - increase initrd size ([c3ce73b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c3ce73be0bfe31fa28805fe92b3e727232ffd37a)) + + - **FVP** + + - fix fvp_cpu_standby() function ([3202ce8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3202ce8bbb4af8580736d2a1634ad45c3f89d931)) + - spmc optee manifest remove SMC allowlist ([183725b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/183725b39d75e362a32b3c5d0be110c255c56bdd)) + - allow changing the kernel DTB load address ([672d669](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/672d669d6c72f92c6b81464d1d421e392bc1aa3e)) + - bump BL2 stack size ([d22f1d3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d22f1d358731f0f55f2f392fa587f0fa8d315aa5)) + - provide boot files via semihosting ([749d0fa](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/749d0fa80d1c7ca30b4092a381a06deeeaf1747f)) + - OP-TEE SP manifest per latest SPMC changes ([b7bc51a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b7bc51a7a747bf40d219b2041e5b3ce56737a71b)) + + - **FVP-R** + + - fix compilation error in release mode ([7d96e79](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7d96e79a1a2efdf85f1ed46cdd5c577b58054f53)) + + - **Morello** + + - initialise CNTFRQ in Non Secure CNTBaseN ([7f2d23d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7f2d23d9d790df90021de6c5165ef10fe5cc5590)) + + - **TC** + + - enable AMU extension ([b5863ca](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b5863cab9adb3fed0c1e4dfb92cf906794e7bdb4)) + - change UUID to string format ([1c19536](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1c1953653c20b4a8c61a7deb3fc493d496d8c478)) + - remove "arm,psci" from psci node ([814646b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/814646b4cb792ab14df04e28360fefd168399b3c)) + - remove ffa and optee device tree node ([f1b44a9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f1b44a9050fbc12e8c260107bfff2930476df062)) + - set cactus-tertiary vcpu count to 1 ([05f667f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/05f667f0c670ba9682050714561309f00210c282)) + + - **SGI** + + - avoid redefinition of 'efi_guid' structure ([f34322c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f34322c1cea1e355aeb4133df6aa601d719be5a3)) + + - **Marvell** + + - Check the required libraries before building doimage ([dd47809](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/dd47809e9ea75188060bf8b294efa8578d255c63)) + + - **Armada** + + - select correct pcie reference clock source ([371648e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/371648e1c76b5230bf8e153629064c02086365c9)) + - fix MSS loader for A8K family ([dceac43](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/dceac436f620e60cd0149194377871b225216079)) + + - **A3K** + + - disable HANDLE_EA_EL3_FIRST by default ([3017e93](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3017e932768c7357a1a41493c58323419e9a1ec9)) + - enable workaround for erratum 1530924 ([975563d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/975563dbfc012b6e8a7765dd8e48220e1bc53dec)) + - Fix building uart-images.tgz.bin archive ([d3f8db0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d3f8db07b618e79c05805a1598e5e834e42fea98)) + - Fix check for external dependences ([2baf503](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2baf50385ba2b460afef4a7919b13b3a350fd03a)) + - fix printing info messages on output ([9f6d154](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9f6d15408340af07ed3c2500202b147189eaa7ef)) + - update information about PCIe abort hack ([068fe91](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/068fe919613197bf221c00fb84a1d94c66a7a8ca)) + - Remove encryption password ([076374c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/076374c9b97d47b10ba5c6034817866c08d66ed4)) + + - **A8K** + + - Add missing build dependency for BLE target ([04738e6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/04738e69917f8e8790bf4cf83ceb05f85e1f45bb)) + - Correctly set include directories for individual targets ([559ab2d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/559ab2df4a35cd82b2a67a0bebeb3028544a6766)) + - Require that MV_DDR_PATH is correctly set ([528dafc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/528dafc367c4f49d4904c4335422502dacf469bf)) + - fix number of CPU power switches. ([5cf6faf](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5cf6fafe223da89c60e2323c242ea188b17e98c3)) + + - **MediaTek** + + - **MT8183** + + - fix out-of-bound access ([420c26b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/420c26b33a29c8328a1806ccb2f5a5885041fdfc)) + + - **MT8195** + + - use correct print format for uint64_t ([964ee4e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/964ee4e6be70ef638d6c875a761ab5ca359d84fe)) + - fix error setting for SPM ([1f81ccc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1f81cccedd40cb397813b0fa826ea1d793b02089)) + - extend MMU region size ([9ff8b8c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9ff8b8ca9393e31e790eb2c8e7ea5c5f41f45198)) + - fix coverity fail ([85e4d14](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/85e4d14df157b5641421ea2b844c146ddc230152)) + + - **NXP** + + - **i.MX** + + - do not keep mmc_device_info in stack ([99d37c8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/99d37c8cb8196a7296311fb4f97f80f086021c74)) + + - **i.MX 8M** + + - **i.MX 8M Mini** + + - fix FTBFS on SPD=opteed ([10bfc77](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/10bfc77e7b3afce17185114ac66361a0914f7784)) + + - **Layerscape** + + - **LX2** + + - **LS1028A** + + - define endianness of scfg and gpio ([2475f63](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2475f63bdec6c24c13f7d6ec7f70275b1bde5c15)) + - fix compile error when enable fuse provision ([a0da9c4](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a0da9c4bd296ec1a47683a1ee05f5d1ed71828c7)) + + - **QEMU** + + - (NS_DRAM0_BASE + NS_DRAM0_SIZE) ADDR overflow 32bit ([325716c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/325716c97b7835b8d249f12c1461556bab8c53a0)) + - reboot/shutdown with low to high gpio ([bd2ad12](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bd2ad12ef10f558a5b15f5768b66e7b2606c6498)) + + - **QTI** + + - **SC1780** + + - qti smc addition ([cc35a37](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cc35a3771d28a96906f8d0f393ff664924a2d4dc)) + + - **Raspberry Pi** + + - **Raspberry Pi 4** + + - drop /memreserve/ region ([5d2793a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5d2793a61aded9602af86e90a571f64ff07f93b3)) + + - **Renesas** + + - **R-Car** + + - change process that copy code to system ram ([49593cc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49593cc1ce0d0471aeef7ca24a5415da2dd55bea)) + - fix cache maintenance process of reading cert header ([c77ab18](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c77ab18ec7c8e0f3d953177b835e004a9b53515f)) + - fix to load image when option BL2_DCACHE_ENABLE is enabled ([d2ece8d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d2ece8dba2f31091b1fa6c302d4255495bb15705)) + + - **R-Car 3** + + - fix disabling MFIS write protection for R-Car D3 ([a8c0c3e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a8c0c3e9d0df2215ed3b9ef66f4596787d957566)) + - fix eMMC boot support for R-Car D3 ([77ab366](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77ab3661e55c39694c7ee81de2d1615775711b64)) + - fix source file to make about GICv2 ([fb3406b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fb3406b6b573cb0b35138ca3c89c5641d3d7b790)) + - fix version judgment for R-Car D3 ([c3d192b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c3d192b8e52823dcbc32e21e47c30693d38bb49f)) + - generate two memory nodes for larger than 2 GiB channel 0 ([21924f2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/21924f2466b9b5e1243c142932e6f498da5633e9)) + + - **Rockchip** + + - **RK3399** + + - correct LPDDR4 resume sequence ([2c4b0c0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2c4b0c05c6546e24eb7209ffb3bb465d4feed164)) + - fix dram section placement ([f943b7c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f943b7c8e292e3aad2fcbdd0a37505f62b3b4c87)) + + - **Socionext** + + - **Synquacer** + + - update scmi power domain off handling ([f7f5d2c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f7f5d2c4cd209c2d21244da4fa442050eb4531ab)) + + - **ST** + + - add STM32IMAGE_SRC ([f223505](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f22350583c2e26ea291eae3dc54db867fdf0d9af)) + - add UART reset in crash console init ([b38e2ed](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b38e2ed29ef791dad0cb61fed81b74d612f58b01)) + - apply security at the end of BL2 ([99080bd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/99080bd1273331007f0b2d6f64fed51ac6861bcd)) + - correct BSEC error code management ([72c7884](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/72c7884092684af4cc3c49e08f913b3ffed783ba)) + - correct IO compensation disabling ([c2d18ca](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c2d18ca80f4bd32f58ba07f53d9bb2586df18fc0)) + - correct signedness comparison issue ([5657dec](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5657decc7ffa1376c0a97b6d14ea1428877f5af4)) + - improve DDR get size function ([91ffc1d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/91ffc1deffa2c1c64efe4dfaf27b78f2621a8b0b)) + - only check header major when booting ([8ce8918](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8ce89187459ec77dd9ffdffba3a2b77838d51b6d)) + - panic if boot interface is wrong ([71693a6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/71693a66341e7d9d683ef32981243cb4c4439351)) + - remove double space ([306dcd6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/306dcd6b0d1981b75e103c560a4034bdaa6862d5)) + + - **ST32MP1** + + - add bl prefix for internal linker script ([7684ddd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7684dddcfb14c45bad33b091410a0bf14a3a9830)) + + - **Xilinx** + + - **Versal** + + - correct IPI buffer offset ([e1e5b13](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e1e5b1339b9f73f7f1893d8a6d4dfe4b19ba0ad1)) + - use sync method for blocking calls ([fa58171](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fa58171534976f94b93a44184afd050d8225e404)) + + - **ZynqMP** + + - use sync method for blocking calls ([c063c5a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c063c5a4f92d5787536e595ca4906b458b0f26cb)) + +- **Services** + + - drop warning on unimplemented calls ([67fad51](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/67fad514ee974dcf0252fa0e9219eb3c580eb714)) + + - **RME** + + - fixes a shift by 64 bits bug in the RME GPT library ([322b344](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/322b344e30cb87b9293060d5946b3c17fe3b9133)) + + - **SPM** + + - do not compile if SVE/SME is enabled ([4333f95](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4333f95bedb5f2b53dcb62e0e9c563794ec33c07)) + - error macro to use correct print format ([0c23e6f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0c23e6f44d41593b6e7f97594c12b5791bd75189)) + - revert workaround hafnium as hypervisor ([3221fce](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3221fce842c0b5aea984bb8dbc1393082bd88a58)) + - fixing coverity issue for SPM Core. ([f7fb0bf](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f7fb0bf77f3434bfb67411cad65e704fdef27f76)) + +- **Libraries** + + - **LIBC** + + - use long for 64-bit types on aarch64 ([4ce3e99](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4ce3e99a336b74611349595ea7fd5ed0277c3eeb)) + + - **CPU Support** + + - correct Demeter CPU name ([4cb576a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4cb576a0c5bd2e7669606996a9f79602596df07c)) + - workaround for Cortex A78 erratum 2242635 ([1ea9190](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1ea9190c6a4d2299c6dc19adc0bbe93d4f051eff)) + - workaround for Cortex-A710 erratum 2058056 ([744bdbf](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/744bdbf732ffd2abf84b2431624051e93bc29f7b)) + - workaround for Neoverse V1 erratum 2216392 ([4c8fe6b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4c8fe6b17fa994a630b2a30f8666df103f2e370d)) + - workaround for Neoverse-N2 erratum 2138953 ([ef8f0c5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ef8f0c52ddf83e815a029319971682d7a26b6a6f)) + - workaround for Neoverse-N2 erratum 2138958 ([c948185](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c948185c973c13df36c62c4bcb50e22b14d6e06a)) + - workaround for Neoverse-N2 erratum 2242400 ([603806d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/603806d1376c4b18211fb1d4cc338153de026c32)) + - workaround for Neoverse-N2 erratum 2242415 ([5819e23](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5819e23bc47c860872141caf42bddddb1b8679a5)) + - workaround for Neoverse-N2 erratum 2280757 ([0d2d999](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0d2d99924e1be548e75c46cfd536f7503cf863e0)) + - rename Matterhorn, Matterhorn ELP, and Klein CPUs ([c6ac4df](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c6ac4df622befb5bb42ac136745094e1498c91d8)) + + - **EL3 Runtime** + + - correct CASSERT for pauth ([b4f8d44](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b4f8d44597faf641177134ee08db7c3fcef5aa14)) + - fix SVE and AMU extension enablement flags ([68ac5ed](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/68ac5ed0493b24e6a0a178171a47db75a31cc423)) + - random typos in tf-a code base ([2e61d68](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2e61d6871cc310e9404fe5cfa10b9828f1c869a7)) + - Remove save/restore of EL2 timer registers ([a7cf274](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a7cf2743f3eb487912302aafc748c81bbd1fc603)) + + - **OP-TEE** + + - correct signedness comparison ([21d2be8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/21d2be83a2eabb328071e857e538ced3c8351874)) + + - **GPT** + + - add necessary barriers and remove cache clean ([77612b9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77612b90acaffc82cea712f4a431c727bbb968ec)) + - use correct print format for uint64_t ([2461bd3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2461bd3a89f7f2cdf4a7302536746733970cfe53)) + + - **Translation Tables** + + - remove always true check in assert ([74d720a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/74d720a026735263d2f290fd05370dad0d4c7219)) + +- **Drivers** + + - **Authentication** + + - avoid NV counter upgrade without certificate validation ([a2a5a94](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a2a5a9456969266dc68d5845f31e05be0c3ff2e3)) + + - **CryptoCell-713** + + - fix a build failure with CC-713 library ([e5fbee5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e5fbee5085c682ac3438e6f66c8bdaffb6076fa2)) + + - **MTD** + + - fix MISRA issues and logic improvement ([5130ad1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5130ad14d52a0196422fed8a7d08e25659890b15)) + - macronix quad enable bit issue ([c332740](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c3327408eb4b5852c0ed9d8933c35aaa6de34c21)) + + - **NAND** + + - **SPI NAND** + + - check correct manufacturer id ([4490b79](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4490b7963303fbe59b07a66c8498a803eb5c239c)) + - check that parameters have been set ([bc453ab](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bc453ab1b2fd4267d34f2b9587f73b8940ee1538)) + + - **SCMI** + + - entry: add weak functions ([b3c8fd5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b3c8fd5d778144340d289ad4825123106aac4a96)) + - smt: fix build for aarch64 ([0e223c6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0e223c6a9e5a2d92cae00fdd16a02a3f8971b114)) + - mention "SCMI" in driver initialisation message ([e0baae7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e0baae7316bfdf3e49e5e158f79eb80cd51fc700)) + - relax requirement for exact protocol version ([125868c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/125868c94150f52ff85cdb59aee623ab1f9f259d)) + + - **UFS** + + - add reset before DME_LINKSTARTUP ([905635d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/905635d5e74e3c7b7b2412a673009c8aaabb73e1)) + + - **Arm** + + - **GIC** + + - **GICv3** + + - add dsb in both disable and enable function of gicv3_cpuif ([5a5e0aa](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5a5e0aac398989536dc4be790820af89da3d093a)) + + - **GIC-600AE** + + - fix timeout calculation ([7f322f2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7f322f228e76caa5480f827af0aa6751f00fc1c4)) + + - **TZC** + + - **TZC-400** + + - never disable filter 0 ([ef378d3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ef378d3ec1ef9d7c28baef32ed409688e962542b)) + + - **Marvell** + + - **COMPHY** + + - fix name of 3.125G SerDes mode ([a669983](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a669983c78828e3f4a4f14b9e5a6ee79dcfde20f)) + + - **Armada 3700** + + - configure phy selector also for PCIe ([0f3a122](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0f3a1221093256999af5f2a80e9b3d7231b9f5fb)) + - fix address overflow ([c074f70](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c074f70ce5d85e1735b589b323fac99d7eb988b5)) + - handle failures in power functions ([49b664e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49b664e75f43fda08dddef4f0510d346bdd25565)) + + - **CP110** + + - fix error code in pcie power on ([c0a909c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c0a909cdcce2d9a2ceefe672ad2fc1cae7e39ec4)) + + - **Armada** + + - **A3K** + + - **A3720** + + - fix configuring UART clock ([b9185c7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b9185c75f7ec2b600ebe0d49281e216a2456b764)) + - fix UART clock rate value and divisor calculation ([66a7752](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/66a7752834382595d26214783ae4698fd1f00bd6)) + - fix UART parent clock rate determination ([5a91c43](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5a91c439cbeb1f64b8b9830de91efad5113d3c89)) + + - **MediaTek** + + - **PMIC Wrapper** + + - update idle flow ([9ed4e6f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9ed4e6fb669b8fcafc4e8acfa6a36db305d27ac8)) + + - **MT8192** + + - **SPM** + + - add missing bit define for debug purpose ([310c3a2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/310c3a26e17d99aafc73b3504d0b6dfbdb97fd4c)) + + - **NXP** + + - **FLEXSPI** + + - fix warm boot wait time for MT35XU512A ([1ff7e46](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1ff7e46b092b74891bc2dc7263e4dfae947b2223)) + + - **SCFG** + + - fix endianness checking ([fb90cfd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fb90cfd4eee504f1d16aa143728af427dc6e0ed8)) + + - **SFP** + + - fix compile warning ([3239a17](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3239a17561c124df7095391c0d64e86910660cdc)) + + - **Renesas** + + - **R-Car3** + + - console: fix a return value of console_rcar_init ([bb273e3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bb273e3be1c4f1cddeac9ceaac95fb56e41e6b98)) + - ddr: update DDR setting for H3, M3, M3N ([ec767c1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ec767c1b99675fbb50ef1b2fdb2d38e881e4789d)) + - emmc: remove CPG_CPGWPR redefinition ([36d5645](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/36d5645aec947ab00b925b21141e59e58e1efd8c)) + - fix CPG registers redefinition ([0dae56b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0dae56bb2f0aa1f89ec98ebe3931fb19751a5c72)) + - i2c_dvfs: fix I2C operation ([b757d3a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b757d3a1d901bee9b7ad430702575adba04889ba)) + + - **ST** + + - **Clock** + + - use correct return value ([8f97c4f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8f97c4fab1769b3f7f37a2a7a01ade36e5c94eaa)) + - correctly manage RTC clock source ([1550909](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/15509093f0ba9a10f97c6f92bc3bb9fcf79a48ce)) + - fix MCU/AXI parent clock ([b8fe48b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b8fe48b6f2b07fce49363cb3c0f8dac9e286439b)) + - fix MPU clock rate ([602ae2f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/602ae2f23c2bc9d79a9ab2b7c5dde1932fffc984)) + - fix RTC clock rating ([cbd2e8a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cbd2e8a6afdd05c4b404d7998134a3f60cc15518)) + - keep RTC clock always on ([5b111c7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5b111c74795ea5e9c8a12d0e6b18d77e431311ed)) + - keep RTCAPB clock always on ([373f06b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/373f06be4ee1114369b96763481b58885623aea4)) + - set other clocks as always on ([bf39318](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bf39318d93c270ff72bda4b46e4771aba7aea313)) + + - **I/O** + + - **STM32 Image** + + - invalidate cache on local buf ([a5bcf82](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a5bcf82402ff415326b4dba42aae95c499821e94)) + - uninitialized variable warning ([c1d732d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c1d732d0db2463998036c678619007da79a25b3f)) + + - **ST PMIC** + + - initialize i2c_state ([4282284](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/42822844bfed2e9ffaeae850cc60f5c3d4d9d654)) + - missing error check ([a4bcfe9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a4bcfe94e73db89ce2ebbb23c8e33e51eea5026a)) + + - **STPMIC1** + + - fix power switches activation ([0161991](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0161991184e5feacacc679bdb9c92681b85235eb)) + - update error cases return ([ed6a852](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ed6a85234653c5ee2520389b769ff47e321df8a4)) + + - **UART** + + - **STM32 Console** + + - do not skip init for crash console ([49c7f0c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49c7f0cef4cc864185828750f1f61f3f33f284f7)) + + - **USB** + + - add a optional ops get_other_speed_config_desc ([216c122](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/216c1223c2c65bd1c119a28b9406f70a9ee7b063)) + - fix Null pointer dereferences in usb_core_set_config ([0cb9870](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0cb9870ddfa1b2fec50debe6d6333cbcb3df1e7e)) + - remove deadcode when USBD_EP_NB = 1 ([7ca4928](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7ca49284be083b03ae11aa348b40358876ee5d4b)) + - remove unnecessary cast ([025f5ef](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/025f5ef201a39ba7285f368139e690bbd7a44653)) + +- **Miscellaneous** + + - use correct printf format for uint64_t ([4ef449c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4ef449c15a4055d92632cb7e72267f525a7e2fca)) + + - **DT Bindings** + + - fix static checks ([0861fcd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0861fcdd3e3f2625e133de3dae9c548de7c1ee48)) + + - **FDTs** + + - avoid output on missing DT property ([49e789e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49e789e353efaf97f84eca016c6a1b8a2b3e3d98)) + - fix OOB write in uuid parsing function ([d0d6424](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d0d642450f1f3a0f43e0e156ef57a0c460dd48cf)) + + - **Morello** + + - fix scmi clock specifier to cluster mappings ([387a906](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/387a9065a271ecde0e47dc5a9f9d037637502beb)) + + - **STM32MP1** + + - correct copyright dates ([8d26029](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8d26029168fe70a86de524ed68c56e8666823714)) + - set ETH clock on PLL4P on ST boards ([3e881a8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3e881a8834a955f1e552300bdbf1dafd02ea8f1c)) + - update PLL nodes for ED1/EV1 boards ([cdbbb9f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cdbbb9f7ecd4687fa52e1c655b631377c24862b9)) + - use 'kHz' as kilohertz abbreviation ([4955d08](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4955d08de7aa664387d2e5f690e78b85ac23a402)) + + - **PIE** + + - invalidate data cache in the entire image range if PIE is enabled ([596d20d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/596d20d9e4d50c02b5a0cce8cad2a1c205cd687a)) + + - **Security** + + - Set MDCR_EL3.MCCD bit ([12f6c06](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/12f6c0649732a35a7ed45ba350a963f09a5710ca)) + + - **SDEI** + + - fix assert while kdump issue ([d39db26](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d39db2695ba626b9c0ee38652fe160b4e84b15d9)) + - print event number in hex format ([6b94356](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6b94356b577744d425476a029c47bd35eb13c148)) + - set SPSR for SDEI based on TakeException ([37596fc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/37596fcb43e34ed4bcf1bd3e86d8dec1011edab8)) + +- **Documentation** + + - fix TF-A v2.6 release date in the release information page ([c90fa47](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c90fa47202b762fe8f54e9c0561e94d37907b6ad)) + - fix `FF-A` substitution ([a61940c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a61940ca739eb89be7c1bb2408a9178c2da5cb70)) + - fix typos in v2.5 release documentation ([481c7b6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/481c7b6b9107a3f71ee750f89cacdd8f9c729838)) + - remove "experimental" tag for stable features ([700e768](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/700e7685dd4682a929645a79de39f503c9140b2d)) + + - **Contribution Guidelines** + + - fix formatting for code snippet ([d0bbe81](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d0bbe8150eb35fe2bac1567751bf84a8f073dd39)) + +- **Build System** + + - use space in WARNINGS list ([34b508b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/34b508be9f021831423a8a14f56dff547e24c743)) + + - **Git Hooks** + + - downgrade `package-lock.json` version ([7434b65](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7434b65208175bdf3f44e0e62aaaeabc9c494ee3)) + +- **Tools** + + - **STM32 Image** + + - improve the tool ([8d0036d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8d0036d3d8c8ac1524539ea90382acafb1e524c0)) + + - **SPTOOL** + + - SP UUID little to big endian in TF-A build ([dcdbcdd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/dcdbcddebdee8d4d2c6c8316f615b428758b22ac)) + + - **DOIMAGE** + + - Fix doimage syntax breaking secure mode build ([6d55ef1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6d55ef1a24dc92a3b737aaa02141f550caaace06)) + +- **Dependencies** + + - **checkpatch** + + - do not check merge commits ([77a0a7f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77a0a7f1d96b188849d1d8d8884b3c93857d3f69)) + +## [2.5.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.4..refs/tags/v2.5) (2021-05-17) + +### New Features + +- Architecture support + + - Added support for speculation barrier(`FEAT_SB`) for non-Armv8.5 platforms + starting from Armv8.0 + - Added support for Activity Monitors Extension version 1.1(`FEAT_AMUv1p1`) + - Added helper functions for Random number generator(`FEAT_RNG`) registers + - Added support for Armv8.6 Multi-threaded PMU extensions (`FEAT_MTPMU`) + - Added support for MTE Asymmetric Fault Handling extensions(`FEAT_MTE3`) + - Added support for Privileged Access Never extensions(`FEAT_PANx`) + +- Bootloader images + + - Added PIE support for AArch32 builds + - Enable Trusted Random Number Generator service for BL32(sp_min) + +- Build System + + - Added build option for Arm Feature Modifiers + +- Drivers + + - Added support for interrupts in TZC-400 driver + - Broadcom + - Added support for I2C, MDIO and USB drivers + - Marvell + - Added support for secure read/write of dfc register-set + - Added support for thermal sensor driver + - Implement a3700_core_getc API in console driver + - Added rx training on 10G port + - Marvell Mochi + - Added support for cn913x in PCIe mode + - Marvell Armada A8K + - Added support for TRNG-IP-76 driver and accessing RNG register + - Mediatek MT8192 + - Added support for following drivers + - MPU configuration for SCP/PCIe + - SPM suspend + - Vcore DVFS + - LPM + - PTP3 + - UART save and restore + - Power-off + - PMIC + - CPU hotplug and MCDI support + - SPMC + - MPU + - Mediatek MT8195 + - Added support for following drivers + - GPIO, NCDI, SPMC drivers + - Power-off + - CPU hotplug, reboot and MCDI + - Delay timer and sys timer + - GIC + - NXP + - Added support for + - non-volatile storage API + - chain of trust and trusted board boot using two modes: MBEDTLS and CSF + - fip-handler necessary for DDR initialization + - SMMU and console drivers + - crypto hardware accelerator driver + - following drivers: SD, EMMC, QSPI, FLEXSPI, GPIO, GIC, CSU, PMU, DDR + - NXP Security Monitor and SFP driver + - interconnect config APIs using ARM CCN-CCI driver + - TZC APIs to configure DDR region + - generic timer driver + - Device configuration driver + - IMX + - Added support for image loading and io-storage driver for TBBR fip booting + - Renesas + - Added support for PFC and EMMC driver + - RZ Family: + - G2N, G2E and G2H SoCs + - Added support for watchdog, QoS, PFC and DRAM initialization + - RZG Family: + - G2M + - Added support for QoS and DRAM initialization + - Xilinx + - Added JTAG DCC support for Versal and ZynqMP SoC family. + +- Libraries + + - C standard library + - Added support to print `%` in `snprintf()` and `printf()` APIs + - Added support for strtoull, strtoll, strtoul, strtol APIs from FreeBSD + project + - CPU support + - Added support for + - Cortex_A78C CPU + - Makalu ELP CPU + - Makalu CPU + - Matterhorn ELP CPU + - Neoverse-N2 CPU + - CPU Errata + - Arm Cortex-A76: Added workaround for erratum 1946160 + - Arm Cortex-A77: Added workaround for erratum 1946167 + - Arm Cortex-A78: Added workaround for erratum 1941498 and 1951500 + - Arm Neoverse-N1: Added workaround for erratum 1946160 + - Flattened device tree(libfdt) + - Added support for wrapper function to read UUIDs in string format from dtb + +- Platforms + + - Added support for MediaTek MT8195 + - Added support for Arm RD-N2 board + - Allwinner + - Added support for H616 SoC + - Arm + - Added support for GPT parser + - Protect GICR frames for fused/unused cores + - Arm Morello + - Added VirtIO network device to Morello FVP fdts + - Arm RD-N2 + - Added support for variant 1 of RD-N2 platform + - Enable AMU support + - Arm RD-V1 + - Enable AMU support + - Arm SGI + - Added support for platform variant build option + - Arm TC0 + - Added Matterhorn ELP CPU support + - Added support for opteed + - Arm Juno + - Added support to use hw_config in BL31 + - Use TRNG entropy source for SMCCC TRNG interface + - Condition Juno entropy source with CRC instructions + - Marvell Mochi + - Added support for detection of secure mode + - Marvell ARMADA + - Added support for new compile option A3720_DB_PM_WAKEUP_SRC + - Added support doing system reset via CM3 secure coprocessor + - Made several makefile enhancements required to build WTMI_MULTI_IMG and + TIMDDRTOOL + - Added support for building DOIMAGETOOL tool + - Added new target mrvl_bootimage + - Mediatek MT8192 + - Added support for rtc power off sequence + - Mediatek MT8195 + - Added support for SiP service + - STM32MP1 + - Added support for + - Seeed ODYSSEY SoM and board + - SDMMC2 and I2C2 pins in pinctrl + - I2C2 peripheral in DTS + - PIE for BL32 + - TZC-400 interrupt managament + - Linux Automation MC-1 board + - Renesas RZG + - Added support for identifying EK874 RZ/G2E board + - Added support for identifying HopeRun HiHope RZ/G2H and RZ/G2H boards + - Rockchip + - Added support for stack protector + - QEMU + - Added support for `max` CPU + - Added Cortex-A72 support to `virt` platform + - Enabled trigger reboot from secure pl061 + - QEMU SBSA + - Added support for sbsa-ref Embedded Controller + - NXP + - Added support for warm reset to retain ddr content + - Added support for image loader necessary for loading fip image + - lx2160a SoC Family + - Added support for + - new platform lx2160a-aqds + - new platform lx2160a-rdb + - new platform lx2162a-aqds + - errata handling + - IMX imx8mm + - Added support for trusted board boot + - TI K3 + - Added support for lite device board + - Enabled Cortex-A72 erratum 1319367 + - Enabled Cortex-A53 erratum 1530924 + - Xilinx ZynqMP + - Added support for PS and system reset on WDT restart + - Added support for error management + - Enable support for log messages necessary for debug + - Added support for PM API SMC call for efuse and register access + +- Processes + + - Introduced process for platform deprecation + - Added documentation for TF-A threat model + - Provided a copy of the MIT license to comply with the license requirements + of the arm-gic.h source file (originating from the Linux kernel project and + re-distributed in TF-A). + +- Services + + - Added support for TRNG firmware interface service + - Arm + - Added SiP service to configure Ethos-N NPU + - SPMC + - Added documentation for SPM(Hafnium) SMMUv3 driver + - SPMD + - Added support for + - FFA_INTERRUPT forwading ABI + - FFA_SECONDARY_EP_REGISTER ABI + - FF-A v1.0 boot time power management, SPMC secondary core boot and early + run-time power management + +- Tools + + - FIPTool + - Added mechanism to allow platform specific image UUID + - git hooks + - Added support for conventional commits through commitlint hook, commitizen + hook and husky configuration files. + - NXP tool + - Added support for a tool that creates pbl file from BL2 + - Renesas RZ/G2 + - Added tool support for creating bootparam and cert_header images + - CertCreate + - Added support for platform-defined certificates, keys, and extensions + using the platform's makefile + - shared tools + - Added EFI_GUID representation to uuid helper data structure + +### Changed + +- Common components + + - Print newline after hex address in aarch64 el3_panic function + - Use proper `#address-cells` and `#size-cells` for reserved-memory in dtbs + +- Drivers + + - Move SCMI driver from ST platform directory and make it common to all + platforms + - Arm GICv3 + - Shift eSPI register offset in GICD_OFFSET_64() + - Use mpidr to probe GICR for current CPU + - Arm TZC-400 + - Adjust filter tag if it set to FILTER_BIT_ALL + - Cadence + - Enhance UART driver APIs to put characters to fifo + - Mediatek MT8192 + - Move timer driver to common folder + - Enhanced sys_cirq driver to add more IC services + - Renesas + - Move ddr and delay driver to common directory + - Renesas rcar + - Treat log as device memory in console driver + - Renesas RZ Family: + - G2N and G2H SoCs + - Select MMC_CH1 for eMMC channel + - Marvell + - Added support for checking if TRNG unit is present + - Marvell A3K + - Set TXDCLK_2X_SEL bit during PCIe initialization + - Set mask parameter for every reg_set call + - Marvell Mochi + - Added missing stream IDs configurations + - MbedTLS + - Migrated to Mbed TLS v2.26.0 + - IMX imx8mp + - Change the bl31 physical load address + - QEMU SBSA + - Enable secure variable storage + - SCMI + - Update power domain protocol version to 2.0 + - STM32 + - Remove dead code from nand FMC driver + +- Libraries + + - C Standard Library + - Use macros to reduce duplicated code between snprintf and printf + - CPU support + - Sanity check pointers before use in AArch32 builds + - Arm Cortex-A78 + - Remove rainier cpu workaround for errata 1542319 + - Arm Makalu ELP + - Added "\_arm" suffix to Makalu ELP CPU lib + +- Miscellaneous + + - Editorconfig + - set max line length to 100 + +- Platforms + + - Allwinner + - Added reserved-memory node to DT + - Express memmap more dynamically + - Move SEPARATE_NOBITS_REGION to platforms + - Limit FDT checks to reduce code size + - Use CPUIDLE hardware when available + - Allow conditional compilation of SCPI and native PSCI ops + - Always use a 3MHz RSB bus clock + - Enable workaround for Cortex-A53 erratum 1530924 + - Fixed non-default PRELOADED_BL33_BASE + - Leave CPU power alone during BL31 setup + - Added several psci hooks enhancements to improve system shutdown/reset + sequence + - Return the PMIC to I2C mode after use + - Separate code to power off self and other CPUs + - Split native and SCPI-based PSCI implementations + - Allwinner H6 + - Added R_PRCM security setup for H6 board + - Added SPC security setup for H6 board + - Use RSB for the PMIC connection on H6 + - Arm + - Store UUID as a string, rather than ints + - Replace FIP base and size macro with a generic name + - Move compile time switch from source to dt file + - Don't provide NT_FW_CONFIG when booting hafnium + - Do not setup 'disabled' regulator + - Increase SP max size + - Remove false dependency of ARM_LINUX_KERNEL_AS_BL33 on RESET_TO_BL31 and + allow it to be enabled independently + - Arm FVP + - Do not map GIC region in BL1 and BL2 + - Arm Juno + - Refactor juno_getentropy() to return 64 bits on each call + - Arm Morello + - Remove "virtio-rng" from Morello FVP + - Enable virtIO P9 device for Morello fvp + - Arm RDV1 + - Allow all PSCI callbacks on RD-V1 + - Rename rddaniel to rdv1 + - Arm RDV1MC + - Rename rddanielxlr to rdv1mc + - Initialize TZC-400 controllers + - Arm TC0 + - Updated GICR base address + - Use scmi_dvfs clock index 1 for cores 4-7 through fdt + - Added reserved-memory node for OP-TEE fdts + - Enabled Theodul DSU in TC platform + - OP-TEE as S-EL1 SP with SPMC at S-EL2 + - Update Matterhorm ELP DVFS clock index + - Arm SGI + - Allow access to TZC controller on all chips + - Define memory regions for multi-chip platforms + - Allow access to nor2 flash and system registers from S-EL0 + - Define default list of memory regions for DMC-620 TZC + - Improve macros defining cper buffer memory region + - Refactor DMC-620 error handling SMC function id + - Refactor SDEI specific macros + - Added platform id value for RDN2 platform + - Refactored header file inclusions and inclusion of memory mapping + - Arm RDN2 + - Allow usage of secure partitions on RDN2 platform + - Update GIC redistributor and TZC base address + - Arm SGM775 + - Deprecate Arm sgm775 FVP platform + - Marvell + - Increase TX FIFO EMPTY timeout from 2ms to 3ms + - Update delay code to be compatible with 1200 MHz CPU + - Marvell ARMADA + - Postpone MSS CPU startup to BL31 stage + - Allow builds without MSS support + - Use MSS SRAM in secure mode + - Added missing FORCE, .PHONY and clean targets + - Cleanup MSS SRAM if used for copy + - Move definition of mrvl_flash target to common marvell_common.mk file + - Show informative build messages and blank lines + - Marvell ARMADA A3K + - Added a new target mrvl_uart which builds UART image + - Added checks that WTP, MV_DDR_PATH and CRYPTOPP_PATH are correctly defined + - Allow use of the system Crypto++ library + - Build \$(WTMI_ENC_IMG) in \$(BUILD_PLAT) directory + - Build intermediate files in \$(BUILD_PLAT) directory + - Build UART image files directly in \$(BUILD_UART) subdirectory + - Correctly set DDR_TOPOLOGY and CLOCKSPRESET for WTMI + - Do not use 'echo -e' in Makefile + - Improve 4GB DRAM usage from 3.375 GB to 3.75 GB + - Remove unused variable WTMI_SYSINIT_IMG from Makefile + - Simplify check if WTP variable is defined + - Split building \$(WTMI_MULTI_IMG) and \$(TIMDDRTOOL) + - Marvell ARMADA A8K + - Allow CP1/CP2 mapping at BLE stage + - Mediatek MT8183 + - Added timer V20 compensation + - Nvidia Tegra + - Rename SMC API + - TI K3 + - Make plat_get_syscnt_freq2 helper check CNT_FID0 register + - Fill non-message data fields in sec_proxy with 0x0 + - Update ti_sci_msg_req_reboot ABI to include domain + - Enable USE_COHERENT_MEM only for the generic board + - Explicitly map SEC_SRAM_BASE to 0x0 + - Use BL31_SIZE instead of computing + - Define the correct number of max table entries and increase SRAM size to + account for additional table + - Raspberry Pi4 + - Switch to gicv2.mk and GICV2_SOURCES + - Renesas + - Move headers and assembly files to common folder + - Renesas rzg + - Added device tree memory node enhancements + - Rockchip + - Switch to using common gicv3.mk + - STM32MP1 + - Set BL sizes regardless of flags + - QEMU + - Include gicv2.mk for compiling GICv2 source files + - Change DEVICE2 definition for MMU + - Added helper to calculate the position shift from MPIDR + - QEMU SBSA + - Include libraries for Cortex-A72 + - Increase SHARED_RAM_SIZE + - Addes support in spm_mm for upto 512 cores + - Added support for topology handling + - QTI + - Mandate SMC implementation + - Xilinx + - Rename the IPI CRC checksum macro + - Use fno-jump-tables flag in CPPFLAGS + - Xilinx versal + - Added the IPI CRC checksum macro support + - Mark IPI calls secure/non-secure + - Enable sgi to communicate with linux using IPI + - Remove Cortex-A53 compilation + - Xilinx ZynqMP + - Configure counter frequency during initialization + - Filter errors related to clock gate permissions + - Implement pinctrl request/release EEMI API + - Reimplement pinctrl get/set config parameter EEMI API calls + - Reimplement pinctrl set/get function EEMI API + - Update error codes to match Linux and PMU Firmware + - Update PM version and support PM version check + - Update return type in query functions + - Added missing ids for 43/46/47dr devices + - Checked for DLL status before doing reset + - Disable ITAPDLYENA bit for zero ITAP delay + - Include GICv2 makefile + - Remove the custom crash implementation + +- Services + + - SPMD + - Lock the g_spmd_pm structure + - Declare third cactus instance as UP SP + - Provide number of vCPUs and VM size for first SP + - Remove `chosen` node from SPMC manifests + - Move OP-TEE SP manifest DTS to FVP platform + - Update OP-TEE SP manifest with device-regions node + - Remove device-memory node from SPMC manifests + - SPM_MM + - Use sp_boot_info to set SP context + - SDEI + - Updata the affinity of shared event + +- Tools + + - FIPtool + - Do not print duplicate verbose lines about building fiptool + - CertCreate + - Updated tool for platform defined certs, keys & extensions + - Create only requested certificates + - Avoid duplicates in extension stack + +### Resolved Issues + +- Several fixes for typos and mis-spellings in documentation + +- Build system + + - Fixed \$\{FIP_NAME} to be rebuilt only when needed in Makefile + - Do not mark file targets as .PHONY target in Makefile + +- Drivers + + - Authorization + - Avoid NV counter upgrade without certificate validation + - Arm GICv3 + - Fixed logical issue for num_eints + - Limit SPI ID to avoid misjudgement in GICD_OFFSET() + - Fixed potential GICD context override with ESPI enabled + - Marvell A3700 + - Fixed configuring polarity invert bits + - Arm TZC-400 + - Correct FAIL_CONTROL Privileged bit + - Fixed logical error in FILTER_BIT definitions + - Renesas rcar + - Fixed several coding style violations reported by checkpatch + +- Libraries + + - Arch helpers + - Fixed assertions in processing dynamic relocations for AArch64 builds + - C standard library + - Fixed MISRA issues in memset() ABI + - RAS + - Fixed bug of binary search in RAS interrupt handler + +- Platforms + + - Arm + - Fixed missing copyrights in arm-gic.h file + - Fixed the order of header files in several dts files + - Fixed error message printing in board makefile + - Fixed bug of overriding the last node in image load helper API + - Fixed stdout-path in fdts files of TC0 and N1SDP platforms + - Turn ON/OFF redistributor in sync with GIC CPU interface ON/OFF for css + platforms + - Arm FVP + - Fixed Generic Timer interrupt types in platform dts files + - Arm Juno + - Fixed parallel build issue for romlib config + - Arm SGI + - Fixed bug in SDEI receive event of RAS handler + - Intel Agilex + - Fixed PLAT_MAX_PWR_LVL value + - Marvell + - Fixed SPD handling in dram port + - Marvell ARMADA + - Fixed TRNG return SMC handling + - Fixed the logic used for LD selector mask + - Fixed MSS firmware loader for A8K family + - ST + - Fixed few violations reported by coverity static checks + - STM32MP1 + - Fixed SELFREF_TO_X32 mask in ddr driver + - Do not keep mmc_device_info in stack + - Correct plat_crash_console_flush() + - QEMU SBSA + - Fixed memory type of secure NOR flash + - QTI + - Fixed NUM_APID and REG_APID_MAP() argument in SPMI driver + - Intel + - Do not keep mmc_device_info in stack + - Hisilicon + - Do not keep mmc_device_info in stack + +- Services + + - EL3 runtime + - Fixed the EL2 context save/restore routine by removing EL2 generic timer + system registers + - Added fix for exception handler in BL31 by synchronizing pending EA using + DSB barrier + - SPMD + - Fixed error codes to use int32_t type + - TSPD + - Added bug fix in tspd interrupt handling when TSP_NS_INTR_ASYNC_PREEMPT is + enabled + - TRNG + - Fixed compilation errors with -O0 compile option + - DebugFS + - Checked channel index before calling clone function + - PSCI + - Fixed limit of 256 CPUs caused by cast to unsigned char + - TSP + - Fixed compilation erros when built with GCC 11.0.0 toolchain + +- Tools + + - FIPtool + - Do not call `make clean` for `all` target + - CertCreate + - Fixed bug to avoid cleaning when building the binary + - Used preallocated parts of the HASH struct to avoid leaking HASH struct + fields + - Free arguments copied with strdup + - Free keys after use + - Free X509_EXTENSION structures on stack to avoid leaking them + - Optimized the code to avoid unnecessary attempts to create non-requested + certificates + +## [2.4.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.3..refs/tags/v2.4) (2020-11-17) + +### New Features + +- Architecture support + - Armv8.6-A + - Added support for Armv8.6 Enhanced Counter Virtualization (ECV) + - Added support for Armv8.6 Fine Grained Traps (FGT) + - Added support for Armv8.6 WFE trap delays +- Bootloader images + - Added support for Measured Boot +- Build System + - Added build option `COT_DESC_IN_DTB` to create Chain of Trust at runtime + - Added build option `OPENSSL_DIR` to direct tools to OpenSSL libraries + - Added build option `RAS_TRAP_LOWER_EL_ERR_ACCESS` to enable trapping RAS + register accesses from EL1/EL2 to EL3 + - Extended build option `BRANCH_PROTECTION` to support branch target + identification +- Common components + - Added support for exporting CPU nodes to the device tree + - Added support for single and dual-root Chains of Trust in secure partitions +- Drivers + - Added Broadcom RNG driver + - Added Marvell `mg_conf_cm3` driver + - Added System Control and Management Interface (SCMI) driver + - Added STMicroelectronics ETZPC driver + - Arm GICv3 + - Added support for detecting topology at runtime + - Dual Root + - Added support for platform certificates + - Marvell Cache LLC + - Added support for mapping the entire LLC into SRAM + - Marvell CCU + - Added workaround for erratum 3033912 + - Marvell CP110 COMPHY + - Added support for SATA COMPHY polarity inversion + - Added support for USB COMPHY polarity inversion + - Added workaround for erratum IPCE_COMPHY-1353 + - STM32MP1 Clocks + - Added `RTC` as a gateable clock + - Added support for shifted clock selector bit masks + - Added support for using additional clocks as parents +- Libraries + - C standard library + - Added support for hexadecimal and pointer format specifiers in `snprint()` + - Added assembly alternatives for various library functions + - CPU support + - Arm Cortex-A53 + - Added workaround for erratum 1530924 + - Arm Cortex-A55 + - Added workaround for erratum 1530923 + - Arm Cortex-A57 + - Added workaround for erratum 1319537 + - Arm Cortex-A76 + - Added workaround for erratum 1165522 + - Added workaround for erratum 1791580 + - Added workaround for erratum 1868343 + - Arm Cortex-A72 + - Added workaround for erratum 1319367 + - Arm Cortex-A77 + - Added workaround for erratum 1508412 + - Added workaround for erratum 1800714 + - Added workaround for erratum 1925769 + - Arm Neoverse-N1 + - Added workaround for erratum 1868343 + - EL3 Runtime + - Added support for saving/restoring registers related to nested + virtualization in EL2 context switches if the architecture supports it + - FCONF + - Added support for Measured Boot + - Added support for populating Chain of Trust properties + - Added support for loading the `fw_config` image + - Measured Boot + - Added support for event logging +- Platforms + - Added support for Arm Morello + - Added support for Arm TC0 + - Added support for iEi PUZZLE-M801 + - Added support for Marvell OCTEON TX2 T9130 + - Added support for MediaTek MT8192 + - Added support for NXP i.MX 8M Nano + - Added support for NXP i.MX 8M Plus + - Added support for QTI CHIP SC7180 + - Added support for STM32MP151F + - Added support for STM32MP153F + - Added support for STM32MP157F + - Added support for STM32MP151D + - Added support for STM32MP153D + - Added support for STM32MP157D + - Arm + - Added support for platform-owned SPs + - Added support for resetting to BL31 + - Arm FPGA + - Added support for Klein + - Added support for Matterhorn + - Added support for additional CPU clusters + - Arm FVP + - Added support for performing SDEI platform setup at runtime + - Added support for SMCCC's `SMCCC_ARCH_SOC_ID` command + - Added an `id` field under the NV-counter node in the device tree to + differentiate between trusted and non-trusted NV-counters + - Added support for extracting the clock frequency from the timer node in + the device tree + - Arm Juno + - Added support for SMCCC's `SMCCC_ARCH_SOC_ID` command + - Arm N1SDP + - Added support for cross-chip PCI-e + - Marvell + - Added support for AVS reduction + - Marvell ARMADA + - Added support for twin-die combined memory device + - Marvell ARMADA A8K + - Added support for DDR with 32-bit bus width (both ECC and non-ECC) + - Marvell AP806 + - Added workaround for erratum FE-4265711 + - Marvell AP807 + - Added workaround for erratum 3033912 + - Nvidia Tegra + - Added debug printouts indicating SC7 entry sequence completion + - Added support for SDEI + - Added support for stack protection + - Added support for GICv3 + - Added support for SMCCC's `SMCCC_ARCH_SOC_ID` command + - Nvidia Tegra194 + - Added support for RAS exception handling + - Added support for SPM + - NXP i.MX + - Added support for SDEI + - QEMU SBSA + - Added support for the Secure Partition Manager + - QTI + - Added RNG driver + - Added SPMI PMIC arbitrator driver + - Added support for SMCCC's `SMCCC_ARCH_SOC_ID` command + - STM32MP1 + - Added support for exposing peripheral interfaces to the non-secure world + at runtime + - Added support for SCMI clock and reset services + - Added support for STM32MP15x CPU revision Z + - Added support for SMCCC services in `SP_MIN` +- Services + - Secure Payload Dispatcher + - Added a provision to allow clients to retrieve the service UUID + - SPMC + - Added secondary core endpoint information to the SPMC context structure + - SPMD + - Added support for booting OP-TEE as a guest S-EL1 Secure Partition on top + of Hafnium in S-EL2 + - Added a provision for handling SPMC messages to register secondary core + entry points + - Added support for power management operations +- Tools + - CertCreate + - Added support for secure partitions + - CertTool + - Added support for the `fw_config` image + - FIPTool + - Added support for the `fw_config` image + +### Changed + +- Architecture support +- Bootloader images +- Build System + - The top-level Makefile now supports building FipTool on Windows + - The default value of `KEY_SIZE` has been changed to to 2048 when RSA is in + use + - The previously-deprecated macro `__ASSEMBLY__` has now been removed +- Common components + - Certain functions that flush the console will no longer return error + information +- Drivers + - Arm GIC + - Usage of `drivers/arm/gic/common/gic_common.c` has now been deprecated in + favour of `drivers/arm/gic/vX/gicvX.mk` + - Added support for detecting the presence of a GIC600-AE + - Added support for detecting the presence of a GIC-Clayton + - Marvell MCI + - Now performs link tuning for all MCI interfaces to improve performance + - Marvell MoChi + - PIDI masters are no longer forced into a non-secure access level when + `LLC_SRAM` is enabled + - The SD/MMC controllers are now accessible from guest virtual machines + - Mbed TLS + - Migrated to Mbed TLS v2.24.0 + - STM32 FMC2 NAND + - Adjusted FMC node bindings to include an EBI controller node + - STM32 Reset + - Added an optional timeout argument to assertion functions + - STM32MP1 Clocks + - Enabled several additional system clocks during initialization +- Libraries + - C Standard Library + - Improved `memset` performance by avoiding single-byte writes + - Added optimized assembly variants of `memset` + - CPU support + - Renamed Cortex-Hercules to Cortex-A78 + - Renamed Cortex-Hercules AE to Cortex-A78 AE + - Renamed Neoverse Zeus to Neoverse V1 + - Coreboot + - Updated ‘coreboot_get_memory_type’ API to take an extra argument as a + ’memory size’ that used to return a valid memory type. + - libfdt + - Updated to latest upstream version +- Platforms + - Allwinner + - Disabled non-secure access to PRCM power control registers + - Arm + - `BL32_BASE` is now platform-dependent when `SPD_spmd` is enabled + - Added support for loading the Chain of Trust from the device tree + - The firmware update check is now executed only once + - NV-counter base addresses are now loaded from the device tree when + `COT_DESC_IN_DTB` is enabled + - Now loads and populates `fw_config` and `tb_fw_config` + - FCONF population now occurs after caches have been enabled in order to + reduce boot times + - Arm Corstone-700 + - Platform support has been split into both an FVP and an FPGA variant + - Arm FPGA + - DTB and BL33 load addresses have been given sensible default values + - Now reads generic timer counter frequency, GICD and GICR base addresses, + and UART address from DT + - Now treats the primary PL011 UART as an SBSA Generic UART + - Arm FVP + - Secure interrupt descriptions, UART parameters, clock frequencies and + GICv3 parameters are now queried through FCONF + - UART parameters are now queried through the device tree + - Added an owner field to Cactus secure partitions + - Increased the maximum size of BL2 when the Chain of Trust is loaded from + the device tree + - Reduces the maximum size of BL31 + - The `FVP_USE_SP804_TIMER` and `FVP_VE_USE_SP804_TIMER` build options have + been removed in favour of a common `USE_SP804_TIMER` option + - Added a third Cactus partition to manifests + - Device tree nodes now store UUIDs in big-endian + - Arm Juno + - Increased the maximum size of BL2 when optimizations have not been applied + - Reduced the maximum size of BL31 and BL32 + - Marvell AP807 + - Enabled snoop filters + - Marvell ARMADA A3K + - UART recovery images are now suffixed with `.bin` + - Marvell ARMADA A8K + - Option `BL31_CACHE_DISABLE` is now disabled (`0`) by default + - Nvidia Tegra + - Added VPR resize supported check when processing video memory resize + requests + - Added SMMU verification to prevent potential issues caused by undetected + corruption of the SMMU configuration during boot + - The GIC CPU interface is now properly disabled after CPU off + - The GICv2 sources list and the `BL31_SIZE` definition have been made + platform-specific + - The SPE driver will no longer flush the console when writing individual + characters + - Nvidia Tegra194 + - TZDRAM setup has been moved to platform-specific early boot handlers + - Increased verbosity of debug prints for RAS SErrors + - Support for powering down CPUs during CPU suspend has been removed + - Now verifies firewall settings before using resources + - TI K3 + - The UART number has been made configurable through `K3_USART` + - Rockchip RK3368 + - The maximum number of memory map regions has been increased to 20 + - Socionext Uniphier + - The maximum size of BL33 has been increased to support larger bootloaders + - STM32 + - Removed platform-specific DT functions in favour of using existing generic + alternatives + - STM32MP1 + - Increased verbosity of exception reports in debug builds + - Device trees have been updated to align with the Linux kernel + - Now uses the ETZPC driver to configure secure-aware interfaces for + assignment to the non-secure world + - Finished good variants have been added to the board identifier + enumerations + - Non-secure access to clocks and reset domains now depends on their state + of registration + - NEON is now disabled in `SP_MIN` + - The last page of `SYSRAM` is now used as SCMI shared memory + - Checks to verify platform compatibility have been added to verify that an + image is compatible with the chip ID of the running platform + - QEMU SBSA + - Removed support for Arm's Cortex-A53 +- Services + - Renamed SPCI to FF-A + - SPMD + - No longer forwards requests to the non-secure world when retrieving + partition information + - SPMC manifest size is now retrieved directly from SPMD instead of the + device tree + - The FF-A version handler now returns SPMD's version when the origin of the + call is secure, and SPMC's version when the origin of the call is + non-secure + - SPMC + - Updated the manifest to declare CPU nodes in descending order as per the + SPM (Hafnium) multicore requirement + - Updated the device tree to mark 2GB as device memory for the first + partition excluding trusted DRAM region (which is reserved for SPMC) + - Increased the number of EC contexts to the maximum number of PEs as per + the FF-A specification +- Tools + - FIPTool + - Now returns `0` on `help` and `help ` + - Marvell DoImage + - Updated Mbed TLS support to v2.8 + - SPTool + - Now appends CertTool arguments + +### Resolved Issues + +- Bootloader images + - Fixed compilation errors for dual-root Chains of Trust caused by symbol + collision + - BL31 + - Fixed compilation errors on platforms with fewer than 4 cores caused by + initialization code exceeding the end of the stacks + - Fixed compilation errors when building a position-independent image +- Build System + - Fixed invalid empty version strings + - Fixed compilation errors on Windows caused by a non-portable architecture + revision comparison +- Drivers + - Arm GIC + - Fixed spurious interrupts caused by a missing barrier + - STM32 Flexible Memory Controller 2 (FMC2) NAND driver + - Fixed runtime instability caused by incorrect error detection logic + - STM32MP1 Clock driver + - Fixed incorrectly-formatted log messages + - Fixed runtime instability caused by improper clock gating procedures + - STMicroelectronics Raw NAND driver + - Fixed runtime instability caused by incorrect unit conversion when waiting + for NAND readiness +- Libraries + - AMU + - Fixed timeout errors caused by excess error logging + - EL3 Runtime + - Fixed runtime instability caused by improper register save/restore routine + in EL2 + - FCONF + - Fixed failure to initialize GICv3 caused by overly-strict device tree + requirements + - Measured Boot + - Fixed driver errors caused by a missing default value for the `HASH_ALG` + build option + - SPE + - Fixed feature detection check that prevented CPUs supporting SVE from + detecting support for SPE in the non-secure world + - Translation Tables + - Fixed various MISRA-C 2012 static analysis violations +- Platforms + - Allwinner A64 + - Fixed USB issues on certain battery-powered device caused by improperly + activated USB power rail + - Arm + - Fixed compilation errors caused by increase in BL2 size + - Fixed compilation errors caused by missing Makefile dependencies to + generated files when building the FIP + - Fixed MISRA-C 2012 static analysis violations caused by unused structures + in include directives intended to be feature-gated + - Arm FPGA + - Fixed initialization issues caused by incorrect MPIDR topology mapping + logic + - Arm RD-N1-edge + - Fixed compilation errors caused by mismatched parentheses in Makefile + - Arm SGI + - Fixed crashes due to the flash memory used for cold reboot attack + protection not being mapped + - Intel Agilex + - Fixed initialization issues caused by several compounding bugs + - Marvell + - Fixed compilation warnings caused by multiple Makefile inclusions + - Marvell ARMADA A3K + - Fixed boot issue in debug builds caused by checks on the BL33 load address + that are not appropriate for this platform + - Nvidia Tegra + - Fixed incorrect delay timer reads + - Fixed spurious interrupts in the non-secure world during cold boot caused + by the arbitration bit in the memory controller not being cleared + - Fixed faulty video memory resize sequence + - Nvidia Tegra194 + - Fixed incorrect alignment of TZDRAM base address + - NXP iMX8M + - Fixed CPU hot-plug issues caused by race condition + - STM32MP1 + - Fixed compilation errors in highly-parallel builds caused by incorrect + Makefile dependencies + - STM32MP157C-ED1 + - Fixed initialization issues caused by missing device tree hash node + - Raspberry Pi 3 + - Fixed compilation errors caused by incorrect dependency ordering in + Makefile + - Rockchip + - Fixed initialization issues caused by non-critical errors when parsing FDT + being treated as critical + - Rockchip RK3368 + - Fixed runtime instability caused by incorrect CPUID shift value + - QEMU + - Fixed compilation errors caused by incorrect dependency ordering in + Makefile + - QEMU SBSA + - Fixed initialization issues caused by FDT exceeding reserved memory size + - QTI + - Fixed compilation errors caused by inclusion of a non-existent file +- Services + - FF-A (previously SPCI) + - Fixed SPMD aborts caused by incorrect behaviour when the manifest is + page-aligned +- Tools + - Fixed compilation issues when compiling tools from within their respective + directories + - FIPTool + - Fixed command line parsing issues on Windows when using arguments whose + names also happen to be a subset of another's + - Marvell DoImage + - Fixed PKCS signature verification errors at boot on some platforms caused + by generation of misaligned images + +### Known Issues + +- Platforms + - NVIDIA Tegra + - Signed comparison compiler warnings occurring in libfdt are currently + being worked around by disabling the warning for the platform until the + underlying issue is resolved in libfdt + +## [2.3.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.2..refs/tags/v2.3) (2020-04-20) + +### New Features + +- Arm Architecture + - Add support for Armv8.4-SecEL2 extension through the SPCI defined SPMD/SPMC + components. + - Build option to support EL2 context save and restore in the secure world + (CTX_INCLUDE_EL2_REGS). + - Add support for SMCCC v1.2 (introducing the new SMCCC_ARCH_SOC_ID SMC). Note + that the support is compliant, but the SVE registers save/restore will be + done as part of future S-EL2/SPM development. +- BL-specific + - Enhanced BL2 bootloader flow to load secure partitions based on firmware + configuration data (fconf). + - Changes necessary to support SEPARATE_NOBITS_REGION feature + - TSP and BL2_AT_EL3: Add Position Independent Execution `PIE` support +- Build System + - Add support for documentation build as a target in Makefile + - Add `COT` build option to select the Chain of Trust to use when the Trusted + Boot feature is enabled (default: `tbbr`). + - Added creation and injection of secure partition packages into the FIP. + - Build option to support SPMC component loading and run at S-EL1 or S-EL2 + (SPMD_SPM_AT_SEL2). + - Enable MTE support + - Enable Link Time Optimization in GCC + - Enable -Wredundant-decls warning check + - Makefile: Add support to optionally encrypt BL31 and BL32 + - Add support to pass the nt_fw_config DTB to OP-TEE. + - Introduce per-BL `CPPFLAGS`, `ASFLAGS`, and `LDFLAGS` + - build_macros: Add CREATE_SEQ function to generate sequence of numbers +- CPU Support + - cortex-a57: Enable higher performance non-cacheable load forwarding + - Hercules: Workaround for Errata 1688305 + - Klein: Support added for Klein CPU + - Matterhorn: Support added for Matterhorn CPU +- Drivers + - auth: Add `calc_hash` function for hash calculation. Used for authentication + of images when measured boot is enabled. + - cryptocell: Add authenticated decryption framework, and support for + CryptoCell-713 and CryptoCell-712 RSA 3K + - gic600: Add support for multichip configuration and Clayton + - gicv3: Introduce makefile, Add extended PPI and SPI range, Add support for + probing multiple GIC Redistributor frames + - gicv4: Add GICv4 extension for GIC driver + - io: Add an IO abstraction layer to load encrypted firmwares + - mhu: Derive doorbell base address + - mtd: Add SPI-NOR, SPI-NAND, SPI-MEM, and raw NAND framework + - scmi: Allow use of multiple SCMI channels + - scu: Add a driver for snoop control unit +- Libraries + - coreboot: Add memory range parsing and use generic base address + - compiler_rt: Import popcountdi2.c and popcountsi2.c files, aeabi_ldivmode.S + file and dependencies + - debugFS: Add DebugFS functionality + - el3_runtime: Add support for enabling S-EL2 + - fconf: Add Firmware Configuration Framework (fconf) (experimental). + - libc: Add memrchr function + - locks: bakery: Use is_dcache_enabled() helper and add a DMB to the + 'read_cache_op' macro + - psci: Add support to enable different personality of the same soc. + - xlat_tables_v2: Add support to pass shareability attribute for normal memory + region, use get_current_el_maybe_constant() in is_dcache_enabled(), + read-only xlat tables for BL31 memory, and add enable_mmu() +- New Platforms Support + - arm/arm_fpga: New platform support added for FPGA + - arm/rddaniel: New platform support added for rd-daniel platform + - brcm/stingray: New platform support added for Broadcom stingray platform + - nvidia/tegra194: New platform support for Nvidia Tegra194 platform +- Platforms + - allwinner: Implement PSCI system suspend using SCPI, add a msgbox driver for + use with SCPI, and reserve and map space for the SCP firmware + - allwinner: axp: Add AXP805 support + - allwinner: power: Add DLDO4 power rail + - amlogic: axg: Add a build flag when using ATOS as BL32 and support for the + A113D (AXG) platform + - arm/a5ds: Add ethernet node and L2 cache node in devicetree + - arm/common: Add support for the new `dualroot` chain of trust + - arm/common: Add support for SEPARATE_NOBITS_REGION + - arm/common: Re-enable PIE when RESET_TO_BL31=1 + - arm/common: Allow boards to specify second DRAM Base address and to define + PLAT_ARM_TZC_FILTERS + - arm/corstone700: Add support for mhuv2 and stack protector + - arm/fvp: Add support for fconf in BL31 and SP_MIN. Populate power domain + descriptor dynamically by leveraging fconf APIs. + - arm/fvp: Add Cactus/Ivy Secure Partition information and use two instances + of Cactus at S-EL1 + - arm/fvp: Add support to run BL32 in TDRAM and BL31 in secure DRAM + - arm/fvp: Add support for GICv4 extension and BL2 hash calculation in BL1 + - arm/n1sdp: Setup multichip gic routing table, update platform macros for + dual-chip setup, introduce platform information SDS region, add support to + update presence of External LLC, and enable the NEOVERSE_N1_EXTERNAL_LLC + flag + - arm/rdn1edge: Add support for dual-chip configuration and use CREATE_SEQ + helper macro to compare chip count + - arm/sgm: Always use SCMI for SGM platforms + - arm/sgm775: Add support for dynamic config using fconf + - arm/sgi: Add multi-chip mode parameter in HW_CONFIG dts, macros for remote + chip device region, chip_id and multi_chip_mode to platform variant info, + and introduce number of chips macro + - brcm: Add BL2 and BL31 support common across Broadcom platforms + - brcm: Add iproc SPI Nor flash support, spi driver, emmc driver, and support + to retrieve plat_toc_flags + - hisilicon: hikey960: Enable system power off callback + - intel: Enable bridge access, SiP SMC secure register access, and uboot + entrypoint support + - intel: Implement platform specific system reset 2 + - intel: Introduce mailbox response length handling + - imx: console: Use CONSOLE_T_BASE for UART base address and generic console_t + data structure + - imx8mm: Provide uart base as build option and add the support for opteed spd + on imx8mq/imx8mm + - imx8qx: Provide debug uart num as build + - imx8qm: Apply clk/pinmux configuration for DEBUG_CONSOLE and provide debug + uart num as build param + - marvell: a8k: Implement platform specific power off and add support for + loading MG CM3 images + - mediatek: mt8183: Add Vmodem/Vcore DVS init level + - qemu: Support optional encryption of BL31 and BL32 images and + ARM_LINUX_KERNEL_AS_BL33 to pass FDT address + - qemu: Define ARMV7_SUPPORTS_VFP + - qemu: Implement PSCI_CPU_OFF and qemu_system_off via semihosting + - renesas: rcar_gen3: Add new board revision for M3ULCB + - rockchip: Enable workaround for erratum 855873, claim a macro to enable hdcp + feature for DP, enable power domains of rk3399 before reset, add support for + UART3 as serial output, and initialize reset and poweroff GPIOs with known + invalid value + - rpi: Implement PSCI CPU_OFF, use MMIO accessor, autodetect Mini-UART vs. + PL011 configuration, and allow using PL011 UART for RPi3/RPi4 + - rpi3: Include GPIO driver in all BL stages and use same "clock-less" setup + scheme as RPi4 + - rpi3/4: Add support for offlining CPUs + - st: stm32mp1: platform.mk: Support generating multiple images in one build, + migrate to implicit rules, derive map file name from target name, generate + linker script with fixed name, and use PHONY for the appropriate targets + - st: stm32mp1: Add support for SPI-NOR, raw NAND, and SPI-NAND boot device, + QSPI, FMC2 driver + - st: stm32mp1: Use stm32mp_get_ddr_ns_size() function, set XN attribute for + some areas in BL2, dynamically map DDR later and non-cacheable during its + test, add a function to get non-secure DDR size, add DT helper for reg by + name, and add compilation flags for boot devices + - socionext: uniphier: Turn on ENABLE_PIE + - ti: k3: Add PIE support + - xilinx: versal: Add set wakeup source, client wakeup, query data, request + wakeup, PM_INIT_FINALIZE, PM_GET_TRUSTZONE_VERSION, PM IOCTL, support for + suspend related, and Get_ChipID APIs + - xilinx: versal: Implement power down/restart related EEMI, SMC handler for + EEMI, PLL related PM, clock related PM, pin control related PM, reset + related PM, device related PM , APIs + - xilinx: versal: Enable ipi mailbox service + - xilinx: versal: Add get_api_version support and support to send PM API to + PMC using IPI + - xilinx: zynqmp: Add checksum support for IPI data, GET_CALLBACK_DATA + function, support to query max divisor, CLK_SET_RATE_PARENT in gem clock + node, support for custom type flags, LPD WDT clock to the pm_clock + structure, idcodes for new RFSoC silicons ZU48DR and ZU49DR, and id for new + RFSoC device ZU39DR +- Security + - Use Speculation Barrier instruction for v8.5+ cores + - Add support for optional firmware encryption feature (experimental). + - Introduce a new `dualroot` chain of trust. + - aarch64: Prevent speculative execution past ERET + - aarch32: Stop speculative execution past exception returns. +- SPCI + - Introduced the Secure Partition Manager Dispatcher (SPMD) component as a new + standard service. +- Tools + - cert_create: Introduce CoT build option and TBBR CoT makefile, and define + the dualroot CoT + - encrypt_fw: Add firmware authenticated encryption tool + - memory: Add show_memory script that prints a representation of the memory + layout for the latest build + +### Changed + +- Arm Architecture + - PIE: Make call to GDT relocation fixup generalized +- BL-Specific + - Increase maximum size of BL2 image + - BL31: Discard .dynsym .dynstr .hash sections to make ENABLE_PIE work + - BL31: Split into two separate memory regions + - Unify BL linker scripts and reduce code duplication. +- Build System + - Changes to drive cert_create for dualroot CoT + - Enable -Wlogical-op always + - Enable -Wshadow always + - Refactor the warning flags + - PIE: Pass PIE options only to BL31 + - Reduce space lost to object alignment + - Set lld as the default linker for Clang builds + - Remove -Wunused-const-variable and -Wpadded warning + - Remove -Wmissing-declarations warning from WARNING1 level +- Drivers + - authentication: Necessary fix in drivers to upgrade to mbedtls-2.18.0 + - console: Integrate UART base address in generic console_t + - gicv3: Change API for GICR_IPRIORITYR accessors and separate GICD and GICR + accessor functions + - io: Change seek offset to signed long long and panic in case of io setup + failure + - smmu: SMMUv3: Changed retry loop to delay timer + - tbbr: Reduce size of hash and ECDSA key buffers when possible +- Library Code + - libc: Consolidate the size_t, unified, and NULL definitions, and unify + intmax_t and uintmax_t on AArch32/64 + - ROMLIB: Optimize memory layout when ROMLIB is used + - xlat_tables_v2: Use ARRAY_SIZE in REGISTER_XLAT_CONTEXT_FULL_SPEC, merge + REGISTER_XLAT_CONTEXT\_{FULL_SPEC,RO_BASE_TABLE}, and simplify end address + checks in mmap_add_region_check() +- Platforms + - allwinner: Adjust SRAM A2 base to include the ARISC vectors, clean up MMU + setup, reenable USE_COHERENT_MEM, remove unused include path, move the + NOBITS region to SRAM A1, convert AXP803 regulator setup code into a driver, + enable clock before resetting I2C/RSB + - allwinner: h6: power: Switch to using the AXP driver + - allwinner: a64: power: Use fdt_for_each_subnode, remove obsolete register + check, remove duplicate DT check, and make sunxi_turn_off_soc static + - allwinner: Build PMIC bus drivers only in BL31, clean up PMIC-related error + handling, and synchronize PMIC enumerations + - arm/a5ds: Change boot address to point to DDR address + - arm/common: Check for out-of-bound accesses in the platform io policies + - arm/corstone700: Updating the kernel arguments to support initramfs, use + fdts DDR memory and XIP rootfs, and set UART clocks to 32MHz + - arm/fvp: Modify multithreaded dts file of DynamIQ FVPs, slightly bump the + stack size for bl1 and bl2, remove re-definition of topology related build + options, stop reclaiming init code with Clang builds, and map only the + needed DRAM region statically in BL31/SP_MIN + - arm/juno: Maximize space allocated to SCP_BL2 + - arm/sgi: Bump bl1 RW limit, mark remote chip shared ram as non-cacheable, + move GIC related constants to board files, include AFF3 affinity in core + position calculation, move bl31_platform_setup to board file, and move + topology information to board folder + - common: Refactor load_auth_image_internal(). + - hisilicon: Remove uefi-tools in hikey and hikey960 documentation + - intel: Modify non secure access function, BL31 address mapping, mailbox's + get_config_status, and stratix10 BL31 parameter handling + - intel: Remove un-needed checks for qspi driver r/w and s10 unused source + code + - intel: Change all global sip function to static + - intel: Refactor common platform code + - intel: Create SiP service header file + - marvell: armada: scp_bl2: Allow loading up to 8 images + - marvell: comphy-a3700: Support SGMII COMPHY power off and fix USB3 powering + on when on lane 2 + - marvell: Consolidate console register calls + - mediatek: mt8183: Protect 4GB~8GB dram memory, refine GIC driver for low + power scenarios, and switch PLL/CLKSQ/ck_off/axi_26m control to SPM + - qemu: Update flash address map to keep FIP in secure FLASH0 + - renesas: rcar_gen3: Update IPL and Secure Monitor Rev.2.0.6, update DDR + setting for H3, M3, M3N, change fixed destination address of BL31 and BL32, + add missing #{address,size}-cells into generated DT, pass DT to OpTee OS, + and move DDR drivers out of staging + - rockchip: Make miniloader ddr_parameter handling optional, cleanup securing + of ddr regions, move secure init to separate file, use base+size for secure + ddr regions, bring TZRAM_SIZE values in lined, and prevent macro expansion + in paths + - rpi: Move plat_helpers.S to common + - rpi3: gpio: Simplify GPIO setup + - rpi4: Skip UART initialisation + - st: stm32m1: Use generic console_t data structure, remove second QSPI flash + instance, update for FMC2 pin muxing, and reduce MAX_XLAT_TABLES to 4 + - socionext: uniphier: Make on-chip SRAM and I/O register regions configurable + - socionext: uniphier: Make PSCI related, counter control, UART, pinmon, NAND + controller, and eMMC controller base addresses configurable + - socionext: uniphier: Change block_addressing flag and the return value type + of .is_usb_boot() to bool + - socionext: uniphier: Run BL33 at EL2, call uniphier_scp_is_running() only + when on-chip STM is supported, define PLAT_XLAT_TABLES_DYNAMIC only for BL2, + support read-only xlat tables, use enable_mmu() in common function, shrink + UNIPHIER_ROM_REGION_SIZE, prepare uniphier_soc_info() for next SoC, extend + boot device detection for future SoCs, make all BL images completely + position-independent, make uniphier_mmap_setup() work with PIE, pass SCP + base address as a function parameter, set buffer offset and length for + io_block dynamically, and use more mmap_add_dynamic_region() for loading + images + - spd/trusty: Disable error messages seen during boot, allow gic base to be + specified with GICD_BASE, and allow getting trusty memsize from + BL32_MEM_SIZE instead of TSP_SEC_MEM_SIZE + - ti: k3: common: Enable ARM cluster power down and rename device IDs to be + more consistent + - ti: k3: drivers: ti_sci: Put sequence number in coherent memory and remove + indirect structure of const data + - xilinx: Move ipi mailbox svc to xilinx common + - xilinx: zynqmp: Use GIC framework for warm restart + - xilinx: zynqmp: pm: Move custom clock flags to typeflags, remove + CLK_TOPSW_LSBUS from invalid clock list and rename FPD WDT clock ID + - xilinx: versal: Increase OCM memory size for DEBUG builds and adjust cpu + clock, Move versal_def.h and versal_private to include directory +- Tools + - sptool: Updated sptool to accommodate building secure partition packages. + +### Resolved Issues + +- Arm Architecture + - Fix crash dump for lower EL +- BL-Specific + - Bug fix: Protect TSP prints with lock + - Fix boot failures on some builds linked with ld.lld. +- Build System + - Fix clang build if CC is not in the path. + - Fix 'BL stage' comment for build macros +- Code Quality + - coverity: Fix various MISRA violations including null pointer violations, C + issues in BL1/BL2/BL31 and FDT helper functions, using boolean essential, + type, and removing unnecessary header file and comparisons to LONG_MAX in + debugfs devfip + - Based on coding guidelines, replace all `unsigned long` depending on if + fixed based on AArch32 or AArch64. + - Unify type of "cpu_idx" and Platform specific defines across PSCI module. +- Drivers + - auth: Necessary fix in drivers to upgrade to mbedtls-2.18.0 + - delay_timer: Fix non-standard frequency issue in udelay + - gicv3: Fix compiler dependent behavior + - gic600: Fix include ordering according to the coding style and power up + sequence +- Library Code + - el3_runtime: Fix stack pointer maintenance on EA handling path, fixup + 'cm_setup_context' prototype, and adds TPIDR_EL2 register to the context + save restore routines + - libc: Fix SIZE_MAX on AArch32 + - locks: T589: Fix insufficient ordering guarantees in bakery lock + - pmf: Fix 'tautological-constant-compare' error, Make the runtime + instrumentation work on AArch32, and Simplify PMF helper macro definitions + across header files + - xlat_tables_v2: Fix assembler warning of PLAT_RO_XLAT_TABLES +- Platforms + - allwinner: Fix H6 GPIO and CCU memory map addresses and incorrect ARISC code + patch offset check + - arm/a5ds: Correct system freq and Cache Writeback Granule, and cleanup + enable-method in devicetree + - arm/fvp: Fix incorrect GIC mapping, BL31 load address and image size for + RESET_TO_BL31=1, topology description of cpus for DynamIQ based FVP, and + multithreaded FVP power domain tree + - arm/fvp: spm-mm: Correcting instructions to build SPM for FVP + - arm/common: Fix ROTPK hash generation for ECDSA encryption, BL2 bug in + dynamic configuration initialisation, and current RECLAIM_INIT_CODE behavior + - arm/rde1edge: Fix incorrect topology tree description + - arm/sgi: Fix the incorrect check for SCMI channel ID + - common: Flush dcache when storing timestamp + - intel: Fix UEFI decompression issue, memory calibration, SMC SIP service, + mailbox config return status, mailbox driver logic, FPGA manager on + reconfiguration, and mailbox send_cmd issue + - imx: Fix shift-overflow errors, the rdc memory region slot's offset, + multiple definition of ipc_handle, missing inclusion of cdefs.h, and correct + the SGIs that used for secure interrupt + - mediatek: mt8183: Fix AARCH64 init fail on CPU0 + - rockchip: Fix definition of struct param_ddr_usage + - rpi4: Fix documentation of armstub config entry + - st: Correct io possible NULL pointer dereference and device_size type, nand + xor_ecc.val assigned value, static analysis tool issues, and fix incorrect + return value and correctly check pwr-regulators node + - xilinx: zynqmp: Correct syscnt freq for QEMU and fix clock models and IDs of + GEM-related clocks + +### Known Issues + +- Build System + - dtb: DTB creation not supported when building on a Windows host. + + This step in the build process is skipped when running on a Windows host. A + known issue from the 1.6 release. + + - Intermittent assertion firing `ASSERT: services/spd/tspd/tspd_main.c:105` +- Coverity + - Intermittent Race condition in Coverity Jenkins Build Job +- Platforms + - arm/juno: System suspend from Linux does not function as documented in the + user guide + + Following the instructions provided in the user guide document does not + result in the platform entering system suspend state as expected. A message + relating to the hdlcd driver failing to suspend will be emitted on the Linux + terminal. + + - mediatek/mt6795: This platform does not build in this release + +## [2.2.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.1..refs/tags/v2.2) (2019-10-22) + +### New Features + +- Architecture + - Enable Pointer Authentication (PAuth) support for Secure World + + - Adds support for ARMv8.3-PAuth in BL1 SMC calls and BL2U image for + firmware updates. + + - Enable Memory Tagging Extension (MTE) support in both secure and non-secure + worlds + + - Adds support for the new Memory Tagging Extension arriving in ARMv8.5. MTE + support is now enabled by default on systems that support it at EL0. + - To enable it at ELx for both the non-secure and the secure world, the + compiler flag `CTX_INCLUDE_MTE_REGS` includes register saving and + restoring when necessary in order to prevent information leakage between + the worlds. + + - Add support for Branch Target Identification (BTI) +- Build System + - Modify FVP makefile for CPUs that support both AArch64/32 + - AArch32: Allow compiling with soft-float toolchain + - Makefile: Add default warning flags + - Add Makefile check for PAuth and AArch64 + - Add compile-time errors for HW_ASSISTED_COHERENCY flag + - Apply compile-time check for AArch64-only CPUs + - build_macros: Add mechanism to prevent bin generation. + - Add support for default stack-protector flag + - spd: opteed: Enable NS_TIMER_SWITCH + - plat/arm: Skip BL2U if RESET_TO_SP_MIN flag is set + - Add new build option to let each platform select which implementation of + spinlocks it wants to use +- CPU Support + - DSU: Workaround for erratum 798953 and 936184 + - Neoverse N1: Force cacheable atomic to near atomic + - Neoverse N1: Workaround for erratum 1073348, 1130799, 1165347, 1207823, + 1220197, 1257314, 1262606, 1262888, 1275112, 1315703, 1542419 + - Neoverse Zeus: Apply the MSR SSBS instruction + - cortex-Hercules/HerculesAE: Support added for Cortex-Hercules and + Cortex-HerculesAE CPUs + - cortex-Hercules/HerculesAE: Enable AMU for Cortex-Hercules and + Cortex-HerculesAE + - cortex-a76AE: Support added for Cortex-A76AE CPU + - cortex-a76: Workaround for erratum 1257314, 1262606, 1262888, 1275112, + 1286807 + - cortex-a65/a65AE: Support added for Cortex-A65 and Cortex-A65AE CPUs + - cortex-a65: Enable AMU for Cortex-A65 + - cortex-a55: Workaround for erratum 1221012 + - cortex-a35: Workaround for erratum 855472 + - cortex-a9: Workaround for erratum 794073 +- Drivers + - console: Allow the console to register multiple times + + - delay: Timeout detection support + + - gicv3: Enabled multi-socket GIC redistributor frame discovery and migrated + ARM platforms to the new API + + - Adds `gicv3_rdistif_probe` function that delegates the responsibility of + discovering the corresponding redistributor base frame to each CPU itself. + + - sbsa: Add SBSA watchdog driver + + - st/stm32_hash: Add HASH driver + + - ti/uart: Add an AArch32 variant +- Library at ROM (romlib) + - Introduce BTI support in Library at ROM (romlib) +- New Platforms Support + - amlogic: g12a: New platform support added for the S905X2 (G12A) platform + - amlogic: meson/gxl: New platform support added for Amlogic Meson S905x (GXL) + - arm/a5ds: New platform support added for A5 DesignStart + - arm/corstone: New platform support added for Corstone-700 + - intel: New platform support added for Agilex + - mediatek: New platform support added for MediaTek mt8183 + - qemu/qemu_sbsa: New platform support added for QEMU SBSA platform + - renesas/rcar_gen3: plat: New platform support added for D3 + - rockchip: New platform support added for px30 + - rockchip: New platform support added for rk3288 + - rpi: New platform support added for Raspberry Pi 4 +- Platforms + - arm/common: Introduce wrapper functions to setup secure watchdog + - arm/fvp: Add Delay Timer driver to BL1 and BL31 and option for defining + platform DRAM2 base + - arm/fvp: Add Linux DTS files for 32 bit threaded FVPs + - arm/n1sdp: Add code for DDR ECC enablement and BL33 copy to DDR, Initialise + CNTFRQ in Non Secure CNTBaseN + - arm/juno: Use shared mbedtls heap between BL1 and BL2 and add basic support + for dynamic config + - imx: Basic support for PicoPi iMX7D, rdc module init, caam module init, + aipstz init, IMX_SIP_GET_SOC_INFO, IMX_SIP_BUILDINFO added + - intel: Add ncore ccu driver + - mediatek/mt81\*: Use new bl31_params_parse() helper + - nvidia: tegra: Add support for multi console interface + - qemu/qemu_sbsa: Adding memory mapping for both FLASH0/FLASH1 + - qemu: Added gicv3 support, new console interface in AArch32, and + sub-platforms + - renesas/rcar_gen3: plat: Add R-Car V3M support, new board revision for + H3ULCB, DBSC4 setting before self-refresh mode + - socionext/uniphier: Support console based on multi-console + - st: stm32mp1: Add OP-TEE, Avenger96, watchdog, LpDDR3, authentication + support and general SYSCFG management + - ti/k3: common: Add support for J721E, Use coherent memory for shared data, + Trap all asynchronous bus errors to EL3 + - xilinx/zynqmp: Add support for multi console interface, Initialize IPI table + from zynqmp_config_setup() +- PSCI + - Adding new optional PSCI hook `pwr_domain_on_finish_late` + - This PSCI hook `pwr_domain_on_finish_late` is similar to + `pwr_domain_on_finish` but is guaranteed to be invoked when the respective + core and cluster are participating in coherency. +- Security + - Speculative Store Bypass Safe (SSBS): Further enhance protection against + Spectre variant 4 by disabling speculative loads/stores (SPSR.SSBS bit) by + default. + - UBSAN support and handlers + - Adds support for the Undefined Behaviour sanitizer. There are two types of + support offered - minimalistic trapping support which essentially + immediately crashes on undefined behaviour and full support with full + debug messages. +- Tools + - cert_create: Add support for bigger RSA key sizes (3KB and 4KB), previously + the maximum size was 2KB. + - fiptool: Add support to build fiptool on Windows. + +### Changed + +- Architecture + - Refactor ARMv8.3 Pointer Authentication support code + - backtrace: Strip PAC field when PAUTH is enabled + - Prettify crash reporting output on AArch64. + - Rework smc_unknown return code path in smc_handler + - Leverage the existing `el3_exit()` return routine for smc_unknown return + path rather than a custom set of instructions. +- BL-Specific + - Invalidate dcache build option for BL2 entry at EL3 + - Add missing support for BL2_AT_EL3 in XIP memory +- Boot Flow + - Add helper to parse BL31 parameters (both versions) + - Factor out cross-BL API into export headers suitable for 3rd party code + - Introduce lightweight BL platform parameter library +- Drivers + - auth: Memory optimization for Chain of Trust (CoT) description + - bsec: Move bsec_mode_is_closed_device() service to platform + - cryptocell: Move Cryptocell specific API into driver + - gicv3: Prevent pending G1S interrupt from becoming G0 interrupt + - mbedtls: Remove weak heap implementation + - mmc: Increase delay between ACMD41 retries + - mmc: stm32_sdmmc2: Correctly manage block size + - mmc: stm32_sdmmc2: Manage max-frequency property from DT + - synopsys/emmc: Do not change FIFO TH as this breaks some platforms + - synopsys: Update synopsys drivers to not rely on undefined overflow + behaviour + - ufs: Extend the delay after reset to wait for some slower chips +- Platforms + - amlogic/meson/gxl: Remove BL2 dependency from BL31 + - arm/common: Shorten the Firmware Update (FWU) process + - arm/fvp: Remove GIC initialisation from secondary core cold boot + - arm/sgm: Temporarily disable shared Mbed TLS heap for SGM + - hisilicon: Update hisilicon drivers to not rely on undefined overflow + behaviour + - imx: imx8: Replace PLAT_IMX8\* with PLAT_imx8\*, remove duplicated linker + symbols and deprecated code include, keep only IRQ 32 unmasked, enable all + power domain by default + - marvell: Prevent SError accessing PCIe link, Switch to xlat_tables_v2, do + not rely on argument passed via smc, make sure that comphy init will use + correct address + - mediatek: mt8173: Refactor RTC and PMIC drivers + - mediatek: mt8173: Apply MULTI_CONSOLE framework + - nvidia: Tegra: memctrl_v2: fix "overflow before widen" coverity issue + - qemu: Simplify the image size calculation, Move and generalise FDT PSCI + fixup, move gicv2 codes to separate file + - renesas/rcar_gen3: Convert to multi-console API, update QoS setting, Update + IPL and Secure Monitor Rev2.0.4, Change to restore timer counter value at + resume, Update DDR setting rev.0.35, qos: change subslot cycle, Change + periodic write DQ training option. + - rockchip: Allow SOCs with undefined wfe check bits, Streamline and complete + UARTn_BASE macros, drop rockchip-specific imported linker symbols for bl31, + Disable binary generation for all SOCs, Allow console device to be set by + DTB, Use new bl31_params_parse functions + - rpi/rpi3: Move shared rpi3 files into common directory + - socionext/uniphier: Set CONSOLE_FLAG_TRANSLATE_CRLF and clean up console + driver + - socionext/uniphier: Replace DIV_ROUND_UP() with div_round_up() from + utils_def.h + - st/stm32mp: Split stm32mp_io_setup function, move + stm32_get_gpio_bank_clock() to private file, correctly handle Clock + Spreading Generator, move oscillator functions to generic file, realign + device tree files with internal devs, enable RTCAPB clock for dual-core + chips, use a common function to check spinlock is available, move + check_header() to common code + - ti/k3: Enable SEPARATE_CODE_AND_RODATA by default, Remove shared RAM space, + Drop \_ADDRESS from K3_USART_BASE to match other defines, Remove MSMC port + definitions, Allow USE_COHERENT_MEM for K3, Set L2 latency on A72 cores +- PSCI + - PSCI: Lookup list of parent nodes to lock only once +- Secure Partition Manager (SPM): SPCI Prototype + - Fix service UUID lookup + - Adjust size of virtual address space per partition + - Refactor xlat context creation + - Move shim layer to TTBR1_EL1 + - Ignore empty regions in resource description +- Security + - Refactor SPSR initialisation code + - SMMUv3: Abort DMA transactions + - For security DMA should be blocked at the SMMU by default unless + explicitly enabled for a device. SMMU is disabled after reset with all + streams bypassing the SMMU, and abortion of all incoming transactions + implements a default deny policy on reset. + - Moves `bl1_platform_setup()` function from arm_bl1_setup.c to FVP + platforms' fvp_bl1_setup.c and fvp_ve_bl1_setup.c files. +- Tools + - cert_create: Remove RSA PKCS#1 v1.5 support + +### Resolved Issues + +- Architecture + - Fix the CAS spinlock implementation by adding a missing DSB in + `spin_unlock()` + - AArch64: Fix SCTLR bit definitions + - Removes incorrect `SCTLR_V_BIT` definition and adds definitions for + ARMv8.3-Pauth `EnIB`, `EnDA` and `EnDB` bits. + - Fix restoration of PAuth context + - Replace call to `pauth_context_save()` with `pauth_context_restore()` in + case of unknown SMC call. +- BL-Specific Issues + - Fix BL31 crash reporting on AArch64 only platforms +- Build System + - Remove several warnings reported with W=2 and W=1 +- Code Quality Issues + - SCTLR and ACTLR are 32-bit for AArch32 and 64-bit for AArch64 + - Unify type of "cpu_idx" across PSCI module. + - Assert if power level value greater then PSCI_INVALID_PWR_LVL + - Unsigned long should not be used as per coding guidelines + - Reduce the number of memory leaks in cert_create + - Fix type of cot_desc_ptr + - Use explicit-width data types in AAPCS parameter structs + - Add python configuration for editorconfig + - BL1: Fix type consistency + - Enable -Wshift-overflow=2 to check for undefined shift behavior + - Updated upstream platforms to not rely on undefined overflow behaviour +- Coverity Quality Issues + - Remove GGC ignore -Warray-bounds + - Fix Coverity #261967, Infinite loop + - Fix Coverity #343017, Missing unlock + - Fix Coverity #343008, Side affect in assertion + - Fix Coverity #342970, Uninitialized scalar variable +- CPU Support + - cortex-a12: Fix MIDR mask +- Drivers + - console: Remove Arm console unregister on suspend + - gicv3: Fix support for full SPI range + - scmi: Fix wrong payload length +- Library Code + - libc: Fix sparse warning for \_\_assert() + - libc: Fix memchr implementation +- Platforms + - rpi: rpi3: Fix compilation error when stack protector is enabled + - socionext/uniphier: Fix compilation fail for SPM support build config + - st/stm32mp1: Fix TZC400 configuration against non-secure DDR + - ti/k3: common: Fix RO data area size calculation +- Security + - AArch32: Disable Secure Cycle Counter + - Changes the implementation for disabling Secure Cycle Counter. For ARMv8.5 + the counter gets disabled by setting `SDCR.SCCD` bit on CPU cold/warm + boot. For the earlier architectures PMCR register is saved/restored on + secure world entry/exit from/to Non-secure state, and cycle counting gets + disabled by setting PMCR.DP bit. + - AArch64: Disable Secure Cycle Counter + - For ARMv8.5 the counter gets disabled by setting `MDCR_El3.SCCD` bit on + CPU cold/warm boot. For the earlier architectures PMCR_EL0 register is + saved/restored on secure world entry/exit from/to Non-secure state, and + cycle counting gets disabled by setting PMCR_EL0.DP bit. + +### Deprecations + +- Common Code + - Remove MULTI_CONSOLE_API flag and references to it + - Remove deprecated `plat_crash_console_*` + - Remove deprecated interfaces `get_afflvl_shift`, `mpidr_mask_lower_afflvls`, + `eret` + - AARCH32/AARCH64 macros are now deprecated in favor of `__aarch64__` + - `__ASSEMBLY__` macro is now deprecated in favor of `__ASSEMBLER__` +- Drivers + - console: Removed legacy console API + - console: Remove deprecated finish_console_register + - tzc: Remove deprecated types `tzc_action_t` and `tzc_region_attributes_t` +- Secure Partition Manager (SPM): + - Prototype SPCI-based SPM (services/std_svc/spm) will be replaced with + alternative methods of secure partitioning support. + +### Known Issues + +- Build System Issues + - dtb: DTB creation not supported when building on a Windows host. + + This step in the build process is skipped when running on a Windows host. A + known issue from the 1.6 release. +- Platform Issues + - arm/juno: System suspend from Linux does not function as documented in the + user guide + + Following the instructions provided in the user guide document does not + result in the platform entering system suspend state as expected. A message + relating to the hdlcd driver failing to suspend will be emitted on the Linux + terminal. + + - mediatek/mt6795: This platform does not build in this release + +## [2.1.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.0..refs/tags/v2.1) (2019-03-29) + +### New Features + +- Architecture + + - Support for ARMv8.3 pointer authentication in the normal and secure worlds + + The use of pointer authentication in the normal world is enabled whenever + architectural support is available, without the need for additional build + flags. + + Use of pointer authentication in the secure world remains an experimental + configuration at this time. Using both the `ENABLE_PAUTH` and + `CTX_INCLUDE_PAUTH_REGS` build flags, pointer authentication can be enabled + in EL3 and S-EL1/0. + + See the {ref}`Firmware Design` document for additional details on the use of + pointer authentication. + + - Enable Data Independent Timing (DIT) in EL3, where supported + +- Build System + + - Support for BL-specific build flags + + - Support setting compiler target architecture based on `ARM_ARCH_MINOR` build + option. + + - New `RECLAIM_INIT_CODE` build flag: + + A significant amount of the code used for the initialization of BL31 is not + needed again after boot time. In order to reduce the runtime memory + footprint, the memory used for this code can be reclaimed after + initialization. + + Certain boot-time functions were marked with the `__init` attribute to + enable this reclamation. + +- CPU Support + + - cortex-a76: Workaround for erratum 1073348 + - cortex-a76: Workaround for erratum 1220197 + - cortex-a76: Workaround for erratum 1130799 + - cortex-a75: Workaround for erratum 790748 + - cortex-a75: Workaround for erratum 764081 + - cortex-a73: Workaround for erratum 852427 + - cortex-a73: Workaround for erratum 855423 + - cortex-a57: Workaround for erratum 817169 + - cortex-a57: Workaround for erratum 814670 + - cortex-a55: Workaround for erratum 903758 + - cortex-a55: Workaround for erratum 846532 + - cortex-a55: Workaround for erratum 798797 + - cortex-a55: Workaround for erratum 778703 + - cortex-a55: Workaround for erratum 768277 + - cortex-a53: Workaround for erratum 819472 + - cortex-a53: Workaround for erratum 824069 + - cortex-a53: Workaround for erratum 827319 + - cortex-a17: Workaround for erratum 852423 + - cortex-a17: Workaround for erratum 852421 + - cortex-a15: Workaround for erratum 816470 + - cortex-a15: Workaround for erratum 827671 + +- Documentation + + - Exception Handling Framework documentation + - Library at ROM (romlib) documentation + - RAS framework documentation + - Coding Guidelines document + +- Drivers + + - ccn: Add API for setting and reading node registers + + - Adds `ccn_read_node_reg` function + - Adds `ccn_write_node_reg` function + + - partition: Support MBR partition entries + + - scmi: Add `plat_css_get_scmi_info` function + + Adds a new API `plat_css_get_scmi_info` which lets the platform register a + platform-specific instance of `scmi_channel_plat_info_t` and remove the + default values + + - tzc380: Add TZC-380 TrustZone Controller driver + + - tzc-dmc620: Add driver to manage the TrustZone Controller within the DMC-620 + Dynamic Memory Controller + +- Library at ROM (romlib) + + - Add platform-specific jump table list + + - Allow patching of romlib functions + + This change allows patching of functions in the romlib. This can be done by + adding "patch" at the end of the jump table entry for the function that + needs to be patched in the file jmptbl.i. + +- Library Code + + - Support non-LPAE-enabled MMU tables in AArch32 + - mmio: Add `mmio_clrsetbits_16` function + - 16-bit variant of `mmio_clrsetbits` + - object_pool: Add Object Pool Allocator + - Manages object allocation using a fixed-size static array + - Adds `pool_alloc` and `pool_alloc_n` functions + - Does not provide any functions to free allocated objects (by design) + - libc: Added `strlcpy` function + - libc: Import `strrchr` function from FreeBSD + - xlat_tables: Add support for ARMv8.4-TTST + - xlat_tables: Support mapping regions without an explicitly specified VA + +- Math + + - Added softudiv macro to support software division + +- Memory Partitioning And Monitoring (MPAM) + + - Enabled MPAM EL2 traps (`MPAMHCR_EL2` and `MPAM_EL2`) + +- Platforms + + - amlogic: Add support for Meson S905 (GXBB) + + - arm/fvp_ve: Add support for FVP Versatile Express platform + + - arm/n1sdp: Add support for Neoverse N1 System Development platform + + - arm/rde1edge: Add support for Neoverse E1 platform + + - arm/rdn1edge: Add support for Neoverse N1 platform + + - arm: Add support for booting directly to Linux without an intermediate + loader (AArch32) + + - arm/juno: Enable new CPU errata workarounds for A53 and A57 + + - arm/juno: Add romlib support + + Building a combined BL1 and ROMLIB binary file with the correct page + alignment is now supported on the Juno platform. When `USE_ROMLIB` is set + for Juno, it generates the combined file `bl1_romlib.bin` which needs to be + used instead of bl1.bin. + + - intel/stratix: Add support for Intel Stratix 10 SoC FPGA platform + + - marvell: Add support for Armada-37xx SoC platform + + - nxp: Add support for i.MX8M and i.MX7 Warp7 platforms + + - renesas: Add support for R-Car Gen3 platform + + - xilinx: Add support for Versal ACAP platforms + +- Position-Independent Executable (PIE) + + PIE support has initially been added to BL31. The `ENABLE_PIE` build flag is + used to enable or disable this functionality as required. + +- Secure Partition Manager + + - New SPM implementation based on SPCI Alpha 1 draft specification + + A new version of SPM has been implemented, based on the SPCI (Secure + Partition Client Interface) and SPRT (Secure Partition Runtime) draft + specifications. + + The new implementation is a prototype that is expected to undergo intensive + rework as the specifications change. It has basic support for multiple + Secure Partitions and Resource Descriptions. + + The older version of SPM, based on MM (ARM Management Mode Interface + Specification), is still present in the codebase. A new build flag, `SPM_MM` + has been added to allow selection of the desired implementation. This flag + defaults to 1, selecting the MM-based implementation. + +- Security + + - Spectre Variant-1 mitigations (`CVE-2017-5753`) + + - Use Speculation Store Bypass Safe (SSBS) functionality where available + + Provides mitigation against `CVE-2018-19440` (Not saving x0 to x3 registers + can leak information from one Normal World SMC client to another) + +### Changed + +- Build System + + - Warning levels are now selectable with `W=<1,2,3>` + - Removed unneeded include paths in PLAT_INCLUDES + - "Warnings as errors" (Werror) can be disabled using `E=0` + - Support totally quiet output with `-s` flag + - Support passing options to checkpatch using `CHECKPATCH_OPTS=` + - Invoke host compiler with `HOSTCC / HOSTCCFLAGS` instead of `CC / CFLAGS` + - Make device tree pre-processing similar to U-boot/Linux by: + - Creating separate `CPPFLAGS` for DT preprocessing so that compiler options + specific to it can be accommodated. + - Replacing `CPP` with `PP` for DT pre-processing + +- CPU Support + + - Errata report function definition is now mandatory for CPU support files + + CPU operation files must now define a `_errata_report` function to + print errata status. This is no longer a weak reference. + +- Documentation + + - Migrated some content from GitHub wiki to `docs/` directory + - Security advisories now have CVE links + - Updated copyright guidelines + +- Drivers + + - console: The `MULTI_CONSOLE_API` framework has been rewritten in C + + - console: Ported multi-console driver to AArch32 + + - gic: Remove 'lowest priority' constants + + Removed `GIC_LOWEST_SEC_PRIORITY` and `GIC_LOWEST_NS_PRIORITY`. Platforms + should define these if required, or instead determine the correct priority + values at runtime. + + - delay_timer: Check that the Generic Timer extension is present + + - mmc: Increase command reply timeout to 10 milliseconds + + - mmc: Poll eMMC device status to ensure `EXT_CSD` command completion + + - mmc: Correctly check return code from `mmc_fill_device_info` + +- External Libraries + + - libfdt: Upgraded from 1.4.2 to 1.4.6-9 + + > + + - mbed TLS: Upgraded from 2.12 to 2.16 + + > + + This change incorporates fixes for security issues that should be reviewed to + determine if they are relevant for software implementations using Trusted + Firmware-A. See the [mbed TLS releases] page for details on changes from the + 2.12 to the 2.16 release. + +- Library Code + + - compiler-rt: Updated `lshrdi3.c` and `int_lib.h` with changes from LLVM + master branch (r345645) + - cpu: Updated macro that checks need for `CVE-2017-5715` mitigation + - libc: Made setjmp and longjmp C standard compliant + - libc: Allowed overriding the default libc (use `OVERRIDE_LIBC`) + - libc: Moved setjmp and longjmp to the `libc/` directory + +- Platforms + + - Removed Mbed TLS dependency from plat_bl_common.c + + - arm: Removed unused `ARM_MAP_BL_ROMLIB` macro + + - arm: Removed `ARM_BOARD_OPTIMISE_MEM` feature and build flag + + - arm: Moved several components into `drivers/` directory + + This affects the SDS, SCP, SCPI, MHU and SCMI components + + - arm/juno: Increased maximum BL2 image size to `0xF000` + + This change was required to accommodate a larger `libfdt` library + +- SCMI + + - Optimized bakery locks when hardware-assisted coherency is enabled using the + `HW_ASSISTED_COHERENCY` build flag + +- SDEI + + - Added support for unconditionally resuming secure world execution after {{ + SDEI }} event processing completes + + {{ SDEI }} interrupts, although targeting EL3, occur on behalf of the + non-secure world, and may have higher priority than secure world interrupts. + Therefore they might preempt secure execution and yield execution to the + non-secure {{ SDEI }} handler. Upon completion of {{ SDEI }} event handling, + resume secure execution if it was preempted. + +- Translation Tables (XLAT) + + - Dynamically detect need for `Common not Private (TTBRn_ELx.CnP)` bit + + Properly handle the case where `ARMv8.2-TTCNP` is implemented in a CPU that + does not implement all mandatory v8.2 features (and so must claim to + implement a lower architecture version). + +### Resolved Issues + +- Architecture + - Incorrect check for SSBS feature detection + - Unintentional register clobber in AArch32 reset_handler function +- Build System + - Dependency issue during DTB image build + - Incorrect variable expansion in Arm platform makefiles + - Building on Windows with verbose mode (`V=1`) enabled is broken + - AArch32 compilation flags is missing `$(march32-directive)` +- BL-Specific Issues + - bl2: `uintptr_t is not defined` error when `BL2_IN_XIP_MEM` is defined + - bl2: Missing prototype warning in `bl2_arch_setup` + - bl31: Omission of Global Offset Table (GOT) section +- Code Quality Issues + - Multiple MISRA compliance issues + - Potential NULL pointer dereference (Coverity-detected) +- Drivers + - mmc: Local declaration of `scr` variable causes a cache issue when + invalidating after the read DMA transfer completes + - mmc: `ACMD41` does not send voltage information during initialization, + resulting in the command being treated as a query. This prevents the command + from initializing the controller. + - mmc: When checking device state using `mmc_device_state()` there are no + retries attempted in the event of an error + - ccn: Incorrect Region ID calculation for RN-I nodes + - console: `Fix MULTI_CONSOLE_API` when used as a crash console + - partition: Improper NULL checking in gpt.c + - partition: Compilation failure in `VERBOSE` mode (`V=1`) +- Library Code + - common: Incorrect check for Address Authentication support + + - xlat: Fix XLAT_V1 / XLAT_V2 incompatibility + + The file `arm_xlat_tables.h` has been renamed to `xlat_tables_compat.h` and + has been moved to a common folder. This header can be used to guarantee + compatibility, as it includes the correct header based on + `XLAT_TABLES_LIB_V2`. + + - xlat: armclang unused-function warning on `xlat_clean_dcache_range` + + - xlat: Invalid `mm_cursor` checks in `mmap_add` and `mmap_add_ctx` + + - sdei: Missing `context.h` header +- Platforms + - common: Missing prototype warning for `plat_log_get_prefix` + + - arm: Insufficient maximum BL33 image size + + - arm: Potential memory corruption during BL2-BL31 transition + + On Arm platforms, the BL2 memory can be overlaid by BL31/BL32. The memory + descriptors describing the list of executable images are created in BL2 R/W + memory, which could be possibly corrupted later on by BL31/BL32 due to + overlay. This patch creates a reserved location in SRAM for these + descriptors and are copied over by BL2 before handing over to next BL image. + + - juno: Invalid behaviour when `CSS_USE_SCMI_SDS_DRIVER` is not set + + In `juno_pm.c` the `css_scmi_override_pm_ops` function was used regardless + of whether the build flag was set. The original behaviour has been restored + in the case where the build flag is not set. +- Tools + - fiptool: Incorrect UUID parsing of blob parameters + - doimage: Incorrect object rules in Makefile + +### Deprecations + +- Common Code + - `plat_crash_console_init` function + - `plat_crash_console_putc` function + - `plat_crash_console_flush` function + - `finish_console_register` macro +- AArch64-specific Code + - helpers: `get_afflvl_shift` + - helpers: `mpidr_mask_lower_afflvls` + - helpers: `eret` +- Secure Partition Manager (SPM) + - Boot-info structure + +### Known Issues + +- Build System Issues + - dtb: DTB creation not supported when building on a Windows host. + + This step in the build process is skipped when running on a Windows host. A + known issue from the 1.6 release. +- Platform Issues + - arm/juno: System suspend from Linux does not function as documented in the + user guide + + Following the instructions provided in the user guide document does not + result in the platform entering system suspend state as expected. A message + relating to the hdlcd driver failing to suspend will be emitted on the Linux + terminal. + + - arm/juno: The firmware update use-cases do not work with motherboard + firmware version \< v1.5.0 (the reset reason is not preserved). The Linaro + 18.04 release has MB v1.4.9. The MB v1.5.0 is available in Linaro 18.10 + release. + + - mediatek/mt6795: This platform does not build in this release + +## [2.0.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.6..refs/tags/v2.0) (2018-10-02) + +### New Features + +- Removal of a number of deprecated APIs + + - A new Platform Compatibility Policy document has been created which + references a wiki page that maintains a listing of deprecated interfaces and + the release after which they will be removed. + - All deprecated interfaces except the MULTI_CONSOLE_API have been removed + from the code base. + - Various Arm and partner platforms have been updated to remove the use of + removed APIs in this release. + - This release is otherwise unchanged from 1.6 release + +### Issues resolved since last release + +- No issues known at 1.6 release resolved in 2.0 release + +### Known Issues + +- DTB creation not supported when building on a Windows host. This step in the + build process is skipped when running on a Windows host. Known issue from 1.6 + version. +- As a result of removal of deprecated interfaces the Nvidia Tegra, Marvell + Armada 8K and MediaTek MT6795 platforms do not build in this release. Also + MediaTek MT8173, NXP QorIQ LS1043A, NXP i.MX8QX, NXP i.MX8QMa, Rockchip + RK3328, Rockchip RK3368 and Rockchip RK3399 platforms have not been confirmed + to be working after the removal of the deprecated interfaces although they do + build. + +## [1.6.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.5..refs/tags/v1.6) (2018-09-21) + +### New Features + +- Addressing Speculation Security Vulnerabilities + + - Implement static workaround for CVE-2018-3639 for AArch32 and AArch64 + - Add support for dynamic mitigation for CVE-2018-3639 + - Implement dynamic mitigation for CVE-2018-3639 on Cortex-A76 + - Ensure {{ SDEI }} handler executes with CVE-2018-3639 mitigation enabled + +- Introduce RAS handling on AArch64 + + - Some RAS extensions are mandatory for Armv8.2 CPUs, with others mandatory + for Armv8.4 CPUs however, all extensions are also optional extensions to the + base Armv8.0 architecture. + - The Armv8 RAS Extensions introduced Standard Error Records which are a set + of standard registers to configure RAS node policy and allow RAS Nodes to + record and expose error information for error handling agents. + - Capabilities are provided to support RAS Node enumeration and iteration + along with individual interrupt registrations and fault injections support. + - Introduce handlers for Uncontainable errors, Double Faults and EL3 External + Aborts + +- Enable Memory Partitioning And Monitoring (MPAM) for lower EL's + + - Memory Partitioning And Monitoring is an Armv8.4 feature that enables + various memory system components and resources to define partitions. + Software running at various ELs can then assign themselves to the desired + partition to control their performance aspects. + - When ENABLE_MPAM_FOR_LOWER_ELS is set to 1, EL3 allows lower ELs to access + their own MPAM registers without trapping to EL3. This patch however, + doesn't make use of partitioning in EL3; platform initialisation code should + configure and use partitions in EL3 if required. + +- Introduce ROM Lib Feature + + - Support combining several libraries into a self-called "romlib" image, that + may be shared across images to reduce memory footprint. The romlib image is + stored in ROM but is accessed through a jump-table that may be stored in + read-write memory, allowing for the library code to be patched. + +- Introduce Backtrace Feature + + - This function displays the backtrace, the current EL and security state to + allow a post-processing tool to choose the right binary to interpret the + dump. + - Print backtrace in assert() and panic() to the console. + +- Code hygiene changes and alignment with MISRA C-2012 guideline with fixes + addressing issues complying to the following rules: + + - MISRA rules 4.9, 5.1, 5.3, 5.7, 8.2-8.5, 8.8, 8.13, 9.3, 10.1, 10.3-10.4, + 10.8, 11.3, 11.6, 12.1, 14.4, 15.7, 16.1-16.7, 17.7-17.8, 20.7, 20.10, + 20.12, 21.1, 21.15, 22.7 + - Clean up the usage of void pointers to access symbols + - Increase usage of static qualifier to locally used functions and data + - Migrated to use of u_register_t for register read/write to better match + AArch32 and AArch64 type sizes + - Use int-ll64 for both AArch32 and AArch64 to assist in consistent format + strings between architectures + - Clean up TF-A libc by removing non arm copyrighted implementations and + replacing them with modified FreeBSD and SCC implementations + +- Various changes to support Clang linker and assembler + + - The clang assembler/preprocessor is used when Clang is selected. However, + the clang linker is not used because it is unable to link TF-A objects due + to immaturity of clang linker functionality at this time. + +- Refactor support APIs into Libraries + + - Evolve libfdt, mbed TLS library and standard C library sources as proper + libraries that TF-A may be linked against. + +- CPU Enhancements + + - Add CPU support for Cortex-Ares and Cortex-A76 + - Add AMU support for Cortex-Ares + - Add initial CPU support for Cortex-Deimos + - Add initial CPU support for Cortex-Helios + - Implement dynamic mitigation for CVE-2018-3639 on Cortex-A76 + - Implement Cortex-Ares erratum 1043202 workaround + - Implement DSU erratum 936184 workaround + - Check presence of fix for errata 843419 in Cortex-A53 + - Check presence of fix for errata 835769 in Cortex-A53 + +- Translation Tables Enhancements + + - The xlat v2 library has been refactored in order to be reused by different + TF components at different EL's including the addition of EL2. Some + refactoring to make the code more generic and less specific to TF, in order + to reuse the library outside of this project. + +- SPM Enhancements + + - General cleanups and refactoring to pave the way to multiple partitions + support + +- SDEI Enhancements + + - Allow platforms to define explicit events + - Determine client EL from NS context's SCR_EL3 + - Make dispatches synchronous + - Introduce jump primitives for BL31 + - Mask events after CPU wakeup in {{ SDEI }} dispatcher to conform to the + specification + +- Misc TF-A Core Common Code Enhancements + + - Add support for eXecute In Place (XIP) memory in BL2 + - Add support for the SMC Calling Convention 2.0 + - Introduce External Abort handling on AArch64 External Abort routed to EL3 + was reported as an unhandled exception and caused a panic. This change + enables Trusted Firmware-A to handle External Aborts routed to EL3. + - Save value of ACTLR_EL1 implementation-defined register in the CPU context + structure rather than forcing it to 0. + - Introduce ARM_LINUX_KERNEL_AS_BL33 build option, which allows BL31 to + directly jump to a Linux kernel. This makes for a quicker and simpler boot + flow, which might be useful in some test environments. + - Add dynamic configurations for BL31, BL32 and BL33 enabling support for + Chain of Trust (COT). + - Make TF UUID RFC 4122 compliant + +- New Platform Support + + - Arm SGI-575 + - Arm SGM-775 + - Allwinner sun50i_64 + - Allwinner sun50i_h6 + - NXP QorIQ LS1043A + - NXP i.MX8QX + - NXP i.MX8QM + - NXP i.MX7Solo WaRP7 + - TI K3 + - Socionext Synquacer SC2A11 + - Marvell Armada 8K + - STMicroelectronics STM32MP1 + +- Misc Generic Platform Common Code Enhancements + + - Add MMC framework that supports both eMMC and SD card devices + +- Misc Arm Platform Common Code Enhancements + + - Demonstrate PSCI MEM_PROTECT from el3_runtime + - Provide RAS support + - Migrate AArch64 port to the multi console driver. The old API is deprecated + and will eventually be removed. + - Move BL31 below BL2 to enable BL2 overlay resulting in changes in the layout + of BL images in memory to enable more efficient use of available space. + - Add cpp build processing for dtb that allows processing device tree with + external includes. + - Extend FIP io driver to support multiple FIP devices + - Add support for SCMI AP core configuration protocol v1.0 + - Use SCMI AP core protocol to set the warm boot entrypoint + - Add support to Mbed TLS drivers for shared heap among different BL images to + help optimise memory usage + - Enable non-secure access to UART1 through a build option to support a serial + debug port for debugger connection + +- Enhancements for Arm Juno Platform + + - Add support for TrustZone Media Protection 1 (TZMP1) + +- Enhancements for Arm FVP Platform + + - Dynamic_config: remove the FVP dtb files + - Set DYNAMIC_WORKAROUND_CVE_2018_3639=1 on FVP by default + - Set the ability to dynamically disable Trusted Boot Board authentication to + be off by default with DYN_DISABLE_AUTH + - Add librom enhancement support in FVP + - Support shared Mbed TLS heap between BL1 and BL2 that allow a reduction in + BL2 size for FVP + +- Enhancements for Arm SGI/SGM Platform + + - Enable ARM_PLAT_MT flag for SGI-575 + - Add dts files to enable support for dynamic config + - Add RAS support + - Support shared Mbed TLS heap for SGI and SGM between BL1 and BL2 + +- Enhancements for Non Arm Platforms + + - Raspberry Pi Platform + - Hikey Platforms + - Xilinx Platforms + - QEMU Platform + - Rockchip rk3399 Platform + - TI Platforms + - Socionext Platforms + - Allwinner Platforms + - NXP Platforms + - NVIDIA Tegra Platform + - Marvell Platforms + - STMicroelectronics STM32MP1 Platform + +### Issues resolved since last release + +- No issues known at 1.5 release resolved in 1.6 release + +### Known Issues + +- DTB creation not supported when building on a Windows host. This step in the + build process is skipped when running on a Windows host. Known issue from 1.5 + version. + +## [1.5.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.4..refs/tags/v1.5) (2018-03-20) + +### New features + +- Added new firmware support to enable RAS (Reliability, Availability, and + Serviceability) functionality. + + - Secure Partition Manager (SPM): A Secure Partition is a software execution + environment instantiated in S-EL0 that can be used to implement simple + management and security services. The SPM is the firmware component that is + responsible for managing a Secure Partition. + + - SDEI dispatcher: Support for interrupt-based {{ SDEI }} events and all + interfaces as defined by the {{ SDEI }} specification v1.0, see + [SDEI Specification] + + - Exception Handling Framework (EHF): Framework that allows dispatching of EL3 + interrupts to their registered handlers which are registered based on their + priorities. Facilitates firmware-first error handling policy where + asynchronous exceptions may be routed to EL3. + + Integrated the TSPD with EHF. + +- Updated PSCI support: + + - Implemented PSCI v1.1 optional features `MEM_PROTECT` and `SYSTEM_RESET2`. + The supported PSCI version was updated to v1.1. + + - Improved PSCI STAT timestamp collection, including moving accounting for + retention states to be inside the locks and fixing handling of wrap-around + when calculating residency in AArch32 execution state. + + - Added optional handler for early suspend that executes when suspending to a + power-down state and with data caches enabled. + + This may provide a performance improvement on platforms where it is safe to + perform some or all of the platform actions from `pwr_domain_suspend` with + the data caches enabled. + +- Enabled build option, BL2_AT_EL3, for BL2 to allow execution at EL3 without + any dependency on TF BL1. + + This allows platforms which already have a non-TF Boot ROM to directly load + and execute BL2 and subsequent BL stages without need for BL1. This was not + previously possible because BL2 executes at S-EL1 and cannot jump straight to + EL3. + +- Implemented support for SMCCC v1.1, including `SMCCC_VERSION` and + `SMCCC_ARCH_FEATURES`. + + Additionally, added support for `SMCCC_VERSION` in PSCI features to enable + discovery of the SMCCC version via PSCI feature call. + +- Added Dynamic Configuration framework which enables each of the boot loader + stages to be dynamically configured at runtime if required by the platform. + The boot loader stage may optionally specify a firmware configuration file + and/or hardware configuration file that can then be shared with the next boot + loader stage. + + Introduced a new BL handover interface that essentially allows passing of 4 + arguments between the different BL stages. + + Updated cert_create and fip_tool to support the dynamic configuration files. + The COT also updated to support these new files. + +- Code hygiene changes and alignment with MISRA guideline: + + - Fix use of undefined macros. + - Achieved compliance with Mandatory MISRA coding rules. + - Achieved compliance for following Required MISRA rules for the default build + configurations on FVP and Juno platforms : 7.3, 8.3, 8.4, 8.5 and 8.8. + +- Added support for Armv8.2-A architectural features: + + - Updated translation table set-up to set the CnP (Common not Private) bit for + secure page tables so that multiple PEs in the same Inner Shareable domain + can use the same translation table entries for a given stage of translation + in a particular translation regime. + - Extended the supported values of ID_AA64MMFR0_EL1.PARange to include the + 52-bit Physical Address range. + - Added support for the Scalable Vector Extension to allow Normal world + software to access SVE functionality but disable access to SVE, SIMD and + floating point functionality from the Secure world in order to prevent + corruption of the Z-registers. + +- Added support for Armv8.4-A architectural feature Activity Monitor Unit (AMU) + + extensions. + + In addition to the v8.4 architectural extension, AMU support on Cortex-A75 was + implemented. + +- Enhanced OP-TEE support to enable use of pageable OP-TEE image. The Arm + standard platforms are updated to load up to 3 images for OP-TEE; header, + pager image and paged image. + + The chain of trust is extended to support the additional images. + +- Enhancements to the translation table library: + + - Introduced APIs to get and set the memory attributes of a region. + - Added support to manage both privilege levels in translation regimes that + describe translations for 2 Exception levels, specifically the EL1&0 + translation regime, and extended the memory map region attributes to include + specifying Non-privileged access. + - Added support to specify the granularity of the mappings of each region, for + instance a 2MB region can be specified to be mapped with 4KB page tables + instead of a 2MB block. + - Disabled the higher VA range to avoid unpredictable behaviour if there is an + attempt to access addresses in the higher VA range. + - Added helpers for Device and Normal memory MAIR encodings that align with + the Arm Architecture Reference Manual for Armv8-A (Arm DDI0487B.b). + - Code hygiene including fixing type length and signedness of constants, + refactoring of function to enable the MMU, removing all instances where the + virtual address space is hardcoded and added comments that document + alignment needed between memory attributes and attributes specified in + TCR_ELx. + +- Updated GIC support: + + - Introduce new APIs for GICv2 and GICv3 that provide the capability to + specify interrupt properties rather than list of interrupt numbers alone. + The Arm platforms and other upstream platforms are migrated to use interrupt + properties. + + - Added helpers to save / restore the GICv3 context, specifically the + Distributor and Redistributor contexts and architectural parts of the ITS + power management. The Distributor and Redistributor helpers also support the + implementation-defined part of GIC-500 and GIC-600. + + Updated the Arm FVP platform to save / restore the GICv3 context on system + suspend / resume as an example of how to use the helpers. + + Introduced a new TZC secured DDR carve-out for use by Arm platforms for + storing EL3 runtime data such as the GICv3 register context. + +- Added support for Armv7-A architecture via build option ARM_ARCH_MAJOR=7. This + includes following features: + + - Updates GICv2 driver to manage GICv1 with security extensions. + - Software implementation for 32bit division. + - Enabled use of generic timer for platforms that do not set + ARM_CORTEX_Ax=yes. + - Support for Armv7-A Virtualization extensions \[DDI0406C_C\]. + - Support for both Armv7-A platforms that only have 32-bit addressing and + Armv7-A platforms that support large page addressing. + - Included support for following Armv7 CPUs: Cortex-A12, Cortex-A17, + Cortex-A7, Cortex-A5, Cortex-A9, Cortex-A15. + - Added support in QEMU for Armv7-A/Cortex-A15. + +- Enhancements to Firmware Update feature: + + - Updated the FWU documentation to describe the additional images needed for + Firmware update, and how they are used for both the Juno platform and the + Arm FVP platforms. + +- Enhancements to Trusted Board Boot feature: + + - Added support to cert_create tool for RSA PKCS1# v1.5 and SHA384, SHA512 and + SHA256. + - For Arm platforms added support to use ECDSA keys. + - Enhanced the mbed TLS wrapper layer to include support for both RSA and + ECDSA to enable runtime selection between RSA and ECDSA keys. + +- Added support for secure interrupt handling in AArch32 sp_min, hardcoded to + only handle FIQs. + +- Added support to allow a platform to load images from multiple boot sources, + for example from a second flash drive. + +- Added a logging framework that allows platforms to reduce the logging level at + runtime and additionally the prefix string can be defined by the platform. + +- Further improvements to register initialisation: + + - Control register PMCR_EL0 / PMCR is set to prohibit cycle counting in the + secure world. This register is added to the list of registers that are saved + and restored during world switch. + - When EL3 is running in AArch32 execution state, the Non-secure version of + SCTLR is explicitly initialised during the warmboot flow rather than relying + on the hardware to set the correct reset values. + +- Enhanced support for Arm platforms: + + - Introduced driver for Shared-Data-Structure (SDS) framework which is used + for communication between SCP and the AP CPU, replacing Boot-Over_MHU (BOM) + protocol. + + The Juno platform is migrated to use SDS with the SCMI support added in v1.3 + and is set as default. + + The driver can be found in the plat/arm/css/drivers folder. + + - Improved memory usage by only mapping TSP memory region when the TSPD has + been included in the build. This reduces the memory footprint and avoids + unnecessary memory being mapped. + + - Updated support for multi-threading CPUs for FVP platforms - always check + the MT field in MPDIR and access the bit fields accordingly. + + - Support building for platforms that model DynamIQ configuration by + implementing all CPUs in a single cluster. + + - Improved nor flash driver, for instance clearing status registers before + sending commands. Driver can be found plat/arm/board/common folder. + +- Enhancements to QEMU platform: + + - Added support for TBB. + - Added support for using OP-TEE pageable image. + - Added support for LOAD_IMAGE_V2. + - Migrated to use translation table library v2 by default. + - Added support for SEPARATE_CODE_AND_RODATA. + +- Applied workarounds CVE-2017-5715 on Arm Cortex-A57, -A72, -A73 and -A75, and + for Armv7-A CPUs Cortex-A9, -A15 and -A17. + +- Applied errata workaround for Arm Cortex-A57: 859972. + +- Applied errata workaround for Arm Cortex-A72: 859971. + +- Added support for Poplar 96Board platform. + +- Added support for Raspberry Pi 3 platform. + +- Added Call Frame Information (CFI) assembler directives to the vector entries + which enables debuggers to display the backtrace of functions that triggered a + synchronous abort. + +- Added ability to build dtb. + +- Added support for pre-tool (cert_create and fiptool) image processing enabling + compression of the image files before processing by cert_create and fiptool. + + This can reduce fip size and may also speed up loading of images. The image + verification will also get faster because certificates are generated based on + compressed images. + + Imported zlib 1.2.11 to implement gunzip() for data compression. + +- Enhancements to fiptool: + + - Enabled the fiptool to be built using Visual Studio. + - Added padding bytes at the end of the last image in the fip to be facilitate + transfer by DMA. + +### Issues resolved since last release + +- TF-A can be built with optimisations disabled (-O0). +- Memory layout updated to enable Trusted Board Boot on Juno platform when + running TF-A in AArch32 execution mode (resolving [tf-issue#501]). + +### Known Issues + +- DTB creation not supported when building on a Windows host. This step in the + build process is skipped when running on a Windows host. + +## [1.4.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.3..refs/tags/v1.4) (2017-07-07) + +### New features + +- Enabled support for platforms with hardware assisted coherency. + + A new build option HW_ASSISTED_COHERENCY allows platforms to take advantage of + the following optimisations: + + - Skip performing cache maintenance during power-up and power-down. + - Use spin-locks instead of bakery locks. + - Enable data caches early on warm-booted CPUs. + +- Added support for Cortex-A75 and Cortex-A55 processors. + + Both Cortex-A75 and Cortex-A55 processors use the Arm DynamIQ Shared Unit + (DSU). The power-down and power-up sequences are therefore mostly managed in + hardware, reducing complexity of the software operations. + +- Introduced Arm GIC-600 driver. + + Arm GIC-600 IP complies with Arm GICv3 architecture. For FVP platforms, the + GIC-600 driver is chosen when FVP_USE_GIC_DRIVER is set to FVP_GIC600. + +- Updated GICv3 support: + + - Introduced power management APIs for GICv3 Redistributor. These APIs allow + platforms to power down the Redistributor during CPU power on/off. Requires + the GICv3 implementations to have power management operations. + + Implemented the power management APIs for FVP. + + - GIC driver data is flushed by the primary CPU so that secondary CPU do not + read stale GIC data. + +- Added support for Arm System Control and Management Interface v1.0 (SCMI). + + The SCMI driver implements the power domain management and system power + management protocol of the SCMI specification (Arm DEN 0056ASCMI) for + communicating with any compliant power controller. + + Support is added for the Juno platform. The driver can be found in the + plat/arm/css/drivers folder. + +- Added support to enable pre-integration of TBB with the Arm TrustZone + CryptoCell product, to take advantage of its hardware Root of Trust and crypto + acceleration services. + +- Enabled Statistical Profiling Extensions for lower ELs. + + The firmware support is limited to the use of SPE in the Non-secure state and + accesses to the SPE specific registers from S-EL1 will trap to EL3. + + The SPE are architecturally specified for AArch64 only. + +- Code hygiene changes aligned with MISRA guidelines: + + - Fixed signed / unsigned comparison warnings in the translation table + library. + - Added U(\_x) macro and together with the existing ULL(\_x) macro fixed some + of the signed-ness defects flagged by the MISRA scanner. + +- Enhancements to Firmware Update feature: + + - The FWU logic now checks for overlapping images to prevent execution of + unauthenticated arbitrary code. + - Introduced new FWU_SMC_IMAGE_RESET SMC that changes the image loading state + machine to go from COPYING, COPIED or AUTHENTICATED states to RESET state. + Previously, this was only possible when the authentication of an image + failed or when the execution of the image finished. + - Fixed integer overflow which addressed TFV-1: Malformed Firmware Update SMC + can result in copy of unexpectedly large data into secure memory. + +- Introduced support for Arm Compiler 6 and LLVM (clang). + + TF-A can now also be built with the Arm Compiler 6 or the clang compilers. The + assembler and linker must be provided by the GNU toolchain. + + Tested with Arm CC 6.7 and clang 3.9.x and 4.0.x. + +- Memory footprint improvements: + + - Introduced `tf_snprintf`, a reduced version of `snprintf` which has support + for a limited set of formats. + + The mbedtls driver is updated to optionally use `tf_snprintf` instead of + `snprintf`. + + - The `assert()` is updated to no longer print the function name, and + additional logging options are supported via an optional platform define + `PLAT_LOG_LEVEL_ASSERT`, which controls how verbose the assert output is. + +- Enhancements to TF-A support when running in AArch32 execution state: + + - Support booting SP_MIN and BL33 in AArch32 execution mode on Juno. Due to + hardware limitations, BL1 and BL2 boot in AArch64 state and there is + additional trampoline code to warm reset into SP_MIN in AArch32 execution + state. + - Added support for Arm Cortex-A53/57/72 MPCore processors including the + errata workarounds that are already implemented for AArch64 execution state. + - For FVP platforms, added AArch32 Trusted Board Boot support, including the + Firmware Update feature. + +- Introduced Arm SiP service for use by Arm standard platforms. + + - Added new Arm SiP Service SMCs to enable the Non-secure world to read PMF + timestamps. + + Added PMF instrumentation points in TF-A in order to quantify the overall + time spent in the PSCI software implementation. + + - Added new Arm SiP service SMC to switch execution state. + + This allows the lower exception level to change its execution state from + AArch64 to AArch32, or vice verse, via a request to EL3. + +- Migrated to use SPDX\[0\] license identifiers to make software license + auditing simpler. + + \:::\{note} Files that have been imported by FreeBSD have not been modified. + \::: + + \[0\]: + +- Enhancements to the translation table library: + + - Added version 2 of translation table library that allows different + translation tables to be modified by using different 'contexts'. Version 1 + of the translation table library only allows the current EL's translation + tables to be modified. + + Version 2 of the translation table also added support for dynamic regions; + regions that can be added and removed dynamically whilst the MMU is enabled. + Static regions can only be added or removed before the MMU is enabled. + + The dynamic mapping functionality is enabled or disabled when compiling by + setting the build option PLAT_XLAT_TABLES_DYNAMIC to 1 or 0. This can be + done per-image. + + - Added support for translation regimes with two virtual address spaces such + as the one shared by EL1 and EL0. + + The library does not support initializing translation tables for EL0 + software. + + - Added support to mark the translation tables as non-cacheable using an + additional build option `XLAT_TABLE_NC`. + +- Added support for GCC stack protection. A new build option + ENABLE_STACK_PROTECTOR was introduced that enables compilation of all BL + images with one of the GCC -fstack-protector-\* options. + + A new platform function plat_get_stack_protector_canary() was introduced that + returns a value used to initialize the canary for stack corruption detection. + For increased effectiveness of protection platforms must provide an + implementation that returns a random value. + +- Enhanced support for Arm platforms: + + - Added support for multi-threading CPUs, indicated by `MT` field in MPDIR. A + new build flag `ARM_PLAT_MT` is added, and when enabled, the functions + accessing MPIDR assume that the `MT` bit is set for the platform and access + the bit fields accordingly. + + Also, a new API `plat_arm_get_cpu_pe_count` is added when `ARM_PLAT_MT` is + enabled, returning the Processing Element count within the physical CPU + corresponding to `mpidr`. + + - The Arm platforms migrated to use version 2 of the translation tables. + + - Introduced a new Arm platform layer API `plat_arm_psci_override_pm_ops` + which allows Arm platforms to modify `plat_arm_psci_pm_ops` and therefore + dynamically define PSCI capability. + + - The Arm platforms migrated to use IMAGE_LOAD_V2 by default. + +- Enhanced reporting of errata workaround status with the following policy: + + - If an errata workaround is enabled: + + - If it applies (i.e. the CPU is affected by the errata), an INFO message is + printed, confirming that the errata workaround has been applied. + - If it does not apply, a VERBOSE message is printed, confirming that the + errata workaround has been skipped. + + - If an errata workaround is not enabled, but would have applied had it been, + a WARN message is printed, alerting that errata workaround is missing. + +- Added build options ARM_ARCH_MAJOR and ARM_ARM_MINOR to choose the + architecture version to target TF-A. + +- Updated the spin lock implementation to use the more efficient CAS (Compare + And Swap) instruction when available. This instruction was introduced in + Armv8.1-A. + +- Applied errata workaround for Arm Cortex-A53: 855873. + +- Applied errata workaround for Arm-Cortex-A57: 813419. + +- Enabled all A53 and A57 errata workarounds for Juno, both in AArch64 and + AArch32 execution states. + +- Added support for Socionext UniPhier SoC platform. + +- Added support for Hikey960 and Hikey platforms. + +- Added support for Rockchip RK3328 platform. + +- Added support for NVidia Tegra T186 platform. + +- Added support for Designware emmc driver. + +- Imported libfdt v1.4.2 that addresses buffer overflow in fdt_offset_ptr(). + +- Enhanced the CPU operations framework to allow power handlers to be registered + on per-level basis. This enables support for future CPUs that have multiple + threads which might need powering down individually. + +- Updated register initialisation to prevent unexpected behaviour: + + - Debug registers MDCR-EL3/SDCR and MDCR_EL2/HDCR are initialised to avoid + unexpected traps into the higher exception levels and disable secure + self-hosted debug. Additionally, secure privileged external debug on Juno is + disabled by programming the appropriate Juno SoC registers. + - EL2 and EL3 configurable controls are initialised to avoid unexpected traps + in the higher exception levels. + - Essential control registers are fully initialised on EL3 start-up, when + initialising the non-secure and secure context structures and when preparing + to leave EL3 for a lower EL. This gives better alignment with the Arm ARM + which states that software must initialise RES0 and RES1 fields with 0 / 1. + +- Enhanced PSCI support: + + - Introduced new platform interfaces that decouple PSCI stat residency + calculation from PMF, enabling platforms to use alternative methods of + capturing timestamps. + - PSCI stat accounting performed for retention/standby states when requested + at multiple power levels. + +- Simplified fiptool to have a single linked list of image descriptors. + +- For the TSP, resolved corruption of pre-empted secure context by aborting any + pre-empted SMC during PSCI power management requests. + +### Issues resolved since last release + +- TF-A can be built with the latest mbed TLS version (v2.4.2). The earlier + version 2.3.0 cannot be used due to build warnings that the TF-A build system + interprets as errors. +- TBBR, including the Firmware Update feature is now supported on FVP platforms + when running TF-A in AArch32 state. +- The version of the AEMv8 Base FVP used in this release has resolved the issue + of the model executing a reset instead of terminating in response to a + shutdown request using the PSCI SYSTEM_OFF API. + +### Known Issues + +- Building TF-A with compiler optimisations disabled (-O0) fails. +- Trusted Board Boot currently does not work on Juno when running Trusted + Firmware in AArch32 execution state due to error when loading the sp_min to + memory because of lack of free space available. See [tf-issue#501] for more + details. +- The errata workaround for A53 errata 843419 is only available from binutils + 2.26 and is not present in GCC4.9. If this errata is applicable to the + platform, please use GCC compiler version of at least 5.0. See [PR#1002] for + more details. + +## [1.3.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.2..refs/tags/v1.3) (2016-10-13) + +### New features + +- Added support for running TF-A in AArch32 execution state. + + The PSCI library has been refactored to allow integration with **EL3 Runtime + Software**. This is software that is executing at the highest secure privilege + which is EL3 in AArch64 or Secure SVC/Monitor mode in AArch32. See + \{ref}`PSCI Library Integration guide for Armv8-A AArch32 systems`. + + Included is a minimal AArch32 Secure Payload, **SP-MIN**, that illustrates the + usage and integration of the PSCI library with EL3 Runtime Software running in + AArch32 state. + + Booting to the BL1/BL2 images as well as booting straight to the Secure + Payload is supported. + +- Improvements to the initialization framework for the PSCI service and Arm + Standard Services in general. + + The PSCI service is now initialized as part of Arm Standard Service + initialization. This consolidates the initializations of any Arm Standard + Service that may be added in the future. + + A new function `get_arm_std_svc_args()` is introduced to get arguments + corresponding to each standard service and must be implemented by the EL3 + Runtime Software. + + For PSCI, a new versioned structure `psci_lib_args_t` is introduced to + initialize the PSCI Library. **Note** this is a compatibility break due to the + change in the prototype of `psci_setup()`. + +- To support AArch32 builds of BL1 and BL2, implemented a new, alternative + firmware image loading mechanism that adds flexibility. + + The current mechanism has a hard-coded set of images and execution order + (BL31, BL32, etc). The new mechanism is data-driven by a list of image + descriptors provided by the platform code. + + Arm platforms have been updated to support the new loading mechanism. + + The new mechanism is enabled by a build flag (`LOAD_IMAGE_V2`) which is + currently off by default for the AArch64 build. + + **Note** `TRUSTED_BOARD_BOOT` is currently not supported when `LOAD_IMAGE_V2` + is enabled. + +- Updated requirements for making contributions to TF-A. + + Commits now must have a 'Signed-off-by:' field to certify that the + contribution has been made under the terms of the + {download}`Developer Certificate of Origin <../dco.txt>`. + + A signed CLA is no longer required. + + The {ref}`Contributor's Guide` has been updated to reflect this change. + +- Introduced Performance Measurement Framework (PMF) which provides support for + capturing, storing, dumping and retrieving time-stamps to measure the + execution time of critical paths in the firmware. This relies on defining + fixed sample points at key places in the code. + +- To support the QEMU platform port, imported libfdt v1.4.1 from + + +- Updated PSCI support: + + - Added support for PSCI NODE_HW_STATE API for Arm platforms. + - New optional platform hook, `pwr_domain_pwr_down_wfi()`, in `plat_psci_ops` + to enable platforms to perform platform-specific actions needed to enter + powerdown, including the 'wfi' invocation. + - PSCI STAT residency and count functions have been added on Arm platforms by + using PMF. + +- Enhancements to the translation table library: + + - Limited memory mapping support for region overlaps to only allow regions to + overlap that are identity mapped or have the same virtual to physical + address offset, and overlap completely but must not cover the same area. + + This limitation will enable future enhancements without having to support + complex edge cases that may not be necessary. + + - The initial translation lookup level is now inferred from the virtual + address space size. Previously, it was hard-coded. + + - Added support for mapping Normal, Inner Non-cacheable, Outer Non-cacheable + memory in the translation table library. + + This can be useful to map a non-cacheable memory region, such as a DMA + buffer. + + - Introduced the MT_EXECUTE/MT_EXECUTE_NEVER memory mapping attributes to + specify the access permissions for instruction execution of a memory region. + +- Enabled support to isolate code and read-only data on separate memory pages, + allowing independent access control to be applied to each. + +- Enabled SCR_EL3.SIF (Secure Instruction Fetch) bit in BL1 and BL31 common + architectural setup code, preventing fetching instructions from non-secure + memory when in secure state. + +- Enhancements to FIP support: + + - Replaced `fip_create` with `fiptool` which provides a more consistent and + intuitive interface as well as additional support to remove an image from a + FIP file. + - Enabled printing the SHA256 digest with info command, allowing quick + verification of an image within a FIP without having to extract the image + and running sha256sum on it. + - Added support for unpacking the contents of an existing FIP file into the + working directory. + - Aligned command line options for specifying images to use same naming + convention as specified by TBBR and already used in cert_create tool. + +- Refactored the TZC-400 driver to also support memory controllers that + integrate TZC functionality, for example Arm CoreLink DMC-500. Also added + DMC-500 specific support. + +- Implemented generic delay timer based on the system generic counter and + migrated all platforms to use it. + +- Enhanced support for Arm platforms: + + - Updated image loading support to make SCP images (SCP_BL2 and SCP_BL2U) + optional. + - Enhanced topology description support to allow multi-cluster topology + definitions. + - Added interconnect abstraction layer to help platform ports select the right + interconnect driver, CCI or CCN, for the platform. + - Added support to allow loading BL31 in the TZC-secured DRAM instead of the + default secure SRAM. + - Added support to use a System Security Control (SSC) Registers Unit enabling + TF-A to be compiled to support multiple Arm platforms and then select one at + runtime. + - Restricted mapping of Trusted ROM in BL1 to what is actually needed by BL1 + rather than entire Trusted ROM region. + - Flash is now mapped as execute-never by default. This increases security by + restricting the executable region to what is strictly needed. + +- Applied following erratum workarounds for Cortex-A57: 833471, 826977, 829520, + 828024 and 826974. + +- Added support for Mediatek MT6795 platform. + +- Added support for QEMU virtualization Armv8-A target. + +- Added support for Rockchip RK3368 and RK3399 platforms. + +- Added support for Xilinx Zynq UltraScale+ MPSoC platform. + +- Added support for Arm Cortex-A73 MPCore Processor. + +- Added support for Arm Cortex-A72 processor. + +- Added support for Arm Cortex-A35 processor. + +- Added support for Arm Cortex-A32 MPCore Processor. + +- Enabled preloaded BL33 alternative boot flow, in which BL2 does not load BL33 + from non-volatile storage and BL31 hands execution over to a preloaded BL33. + The User Guide has been updated with an example of how to use this option with + a bootwrapped kernel. + +- Added support to build TF-A on a Windows-based host machine. + +- Updated Trusted Board Boot prototype implementation: + + - Enabled the ability for a production ROM with TBBR enabled to boot test + software before a real ROTPK is deployed (e.g. manufacturing mode). Added + support to use ROTPK in certificate without verifying against the platform + value when `ROTPK_NOT_DEPLOYED` bit is set. + - Added support for non-volatile counter authentication to the Authentication + Module to protect against roll-back. + +- Updated GICv3 support: + + - Enabled processor power-down and automatic power-on using GICv3. + - Enabled G1S or G0 interrupts to be configured independently. + - Changed FVP default interrupt driver to be the GICv3-only driver. **Note** + the default build of TF-A will not be able to boot Linux kernel with GICv2 + FDT blob. + - Enabled wake-up from CPU_SUSPEND to stand-by by temporarily re-routing + interrupts and then restoring after resume. + +### Issues resolved since last release + +### Known issues + +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI `SYSTEM_OFF` API. This issue will be fixed in a future version of the + model. +- Building TF-A with compiler optimisations disabled (`-O0`) fails. +- TF-A cannot be built with mbed TLS version v2.3.0 due to build warnings that + the TF-A build system interprets as errors. +- TBBR is not currently supported when running TF-A in AArch32 state. + +## [1.2.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.1..refs/tags/v1.2) (2015-12-22) + +### New features + +- The Trusted Board Boot implementation on Arm platforms now conforms to the + mandatory requirements of the TBBR specification. + + In particular, the boot process is now guarded by a Trusted Watchdog, which + will reset the system in case of an authentication or loading error. On Arm + platforms, a secure instance of Arm SP805 is used as the Trusted Watchdog. + + Also, a firmware update process has been implemented. It enables authenticated + firmware to update firmware images from external interfaces to SoC + Non-Volatile memories. This feature functions even when the current firmware + in the system is corrupt or missing; it therefore may be used as a recovery + mode. + +- Improvements have been made to the Certificate Generation Tool (`cert_create`) + as follows. + + - Added support for the Firmware Update process by extending the Chain of + Trust definition in the tool to include the Firmware Update certificate and + the required extensions. + - Introduced a new API that allows one to specify command line options in the + Chain of Trust description. This makes the declaration of the tool's + arguments more flexible and easier to extend. + - The tool has been reworked to follow a data driven approach, which makes it + easier to maintain and extend. + +- Extended the FIP tool (`fip_create`) to support the new set of images involved + in the Firmware Update process. + +- Various memory footprint improvements. In particular: + + - The bakery lock structure for coherent memory has been optimised. + - The mbed TLS SHA1 functions are not needed, as SHA256 is used to generate + the certificate signature. Therefore, they have been compiled out, reducing + the memory footprint of BL1 and BL2 by approximately 6 KB. + - On Arm development platforms, each BL stage now individually defines the + number of regions that it needs to map in the MMU. + +- Added the following new design documents: + + - {ref}`Authentication Framework & Chain of Trust` + - {ref}`Firmware Update (FWU)` + - {ref}`CPU Reset` + - {ref}`PSCI Power Domain Tree Structure` + +- Applied the new image terminology to the code base and documentation, as + described in the {ref}`Image Terminology` document. + +- The build system has been reworked to improve readability and facilitate + adding future extensions. + +- On Arm standard platforms, BL31 uses the boot console during cold boot but + switches to the runtime console for any later logs at runtime. The TSP uses + the runtime console for all output. + +- Implemented a basic NOR flash driver for Arm platforms. It programs the device + using CFI (Common Flash Interface) standard commands. + +- Implemented support for booting EL3 payloads on Arm platforms, which reduces + the complexity of developing EL3 baremetal code by doing essential baremetal + initialization. + +- Provided separate drivers for GICv3 and GICv2. These expect the entire + software stack to use either GICv2 or GICv3; hybrid GIC software systems are + no longer supported and the legacy Arm GIC driver has been deprecated. + +- Added support for Juno r1 and r2. A single set of Juno TF-A binaries can run + on Juno r0, r1 and r2 boards. Note that this TF-A version depends on a Linaro + release that does *not* contain Juno r2 support. + +- Added support for MediaTek mt8173 platform. + +- Implemented a generic driver for Arm CCN IP. + +- Major rework of the PSCI implementation. + + - Added framework to handle composite power states. + - Decoupled the notions of affinity instances (which describes the + hierarchical arrangement of cores) and of power domain topology, instead of + assuming a one-to-one mapping. + - Better alignment with version 1.0 of the PSCI specification. + +- Added support for the SYSTEM_SUSPEND PSCI API on Arm platforms. When invoked + on the last running core on a supported platform, this puts the system into a + low power mode with memory retention. + +- Unified the reset handling code as much as possible across BL stages. Also + introduced some build options to enable optimization of the reset path on + platforms that support it. + +- Added a simple delay timer API, as well as an SP804 timer driver, which is + enabled on FVP. + +- Added support for NVidia Tegra T210 and T132 SoCs. + +- Reorganised Arm platforms ports to greatly improve code shareability and + facilitate the reuse of some of this code by other platforms. + +- Added support for Arm Cortex-A72 processor in the CPU specific framework. + +- Provided better error handling. Platform ports can now define their own error + handling, for example to perform platform specific bookkeeping or post-error + actions. + +- Implemented a unified driver for Arm Cache Coherent Interconnects used for + both CCI-400 & CCI-500 IPs. Arm platforms ports have been migrated to this + common driver. The standalone CCI-400 driver has been deprecated. + +### Issues resolved since last release + +- The Trusted Board Boot implementation has been redesigned to provide greater + modularity and scalability. See the + \{ref}`Authentication Framework & Chain of Trust` document. All missing + mandatory features are now implemented. +- The FVP and Juno ports may now use the hash of the ROTPK stored in the Trusted + Key Storage registers to verify the ROTPK. Alternatively, a development public + key hash embedded in the BL1 and BL2 binaries might be used instead. The + location of the ROTPK is chosen at build-time using the `ARM_ROTPK_LOCATION` + build option. +- GICv3 is now fully supported and stable. + +### Known issues + +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI `SYSTEM_OFF` API. This issue will be fixed in a future version of the + model. +- While this version has low on-chip RAM requirements, there are further RAM + usage enhancements that could be made. +- The upstream documentation could be improved for structural consistency, + clarity and completeness. In particular, the design documentation is + incomplete for PSCI, the TSP(D) and the Juno platform. +- Building TF-A with compiler optimisations disabled (`-O0`) fails. + +## [1.1.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.0..refs/tags/v1.1) (2015-02-04) + +### New features + +- A prototype implementation of Trusted Board Boot has been added. Boot loader + images are verified by BL1 and BL2 during the cold boot path. BL1 and BL2 use + the PolarSSL SSL library to verify certificates and images. The OpenSSL + library is used to create the X.509 certificates. Support has been added to + `fip_create` tool to package the certificates in a FIP. + +- Support for calling CPU and platform specific reset handlers upon entry into + BL3-1 during the cold and warm boot paths has been added. This happens after + another Boot ROM `reset_handler()` has already run. This enables a developer + to perform additional actions or undo actions already performed during the + first call of the reset handlers e.g. apply additional errata workarounds. + +- Support has been added to demonstrate routing of IRQs to EL3 instead of S-EL1 + when execution is in secure world. + +- The PSCI implementation now conforms to version 1.0 of the PSCI specification. + All the mandatory APIs and selected optional APIs are supported. In + particular, support for the `PSCI_FEATURES` API has been added. A capability + variable is constructed during initialization by examining the `plat_pm_ops` + and `spd_pm_ops` exported by the platform and the Secure Payload Dispatcher. + This is used by the PSCI FEATURES function to determine which PSCI APIs are + supported by the platform. + +- Improvements have been made to the PSCI code as follows. + + - The code has been refactored to remove redundant parameters from internal + functions. + - Changes have been made to the code for PSCI `CPU_SUSPEND`, `CPU_ON` and + `CPU_OFF` calls to facilitate an early return to the caller in case a + failure condition is detected. For example, a PSCI `CPU_SUSPEND` call + returns `SUCCESS` to the caller if a pending interrupt is detected early in + the code path. + - Optional platform APIs have been added to validate the `power_state` and + `entrypoint` parameters early in PSCI `CPU_ON` and `CPU_SUSPEND` code paths. + - PSCI migrate APIs have been reworked to invoke the SPD hook to determine the + type of Trusted OS and the CPU it is resident on (if applicable). Also, + during a PSCI `MIGRATE` call, the SPD hook to migrate the Trusted OS is + invoked. + +- It is now possible to build TF-A without marking at least an extra page of + memory as coherent. The build flag `USE_COHERENT_MEM` can be used to choose + between the two implementations. This has been made possible through these + changes. + + - An implementation of Bakery locks, where the locks are not allocated in + coherent memory has been added. + - Memory which was previously marked as coherent is now kept coherent through + the use of software cache maintenance operations. + + Approximately, 4K worth of memory is saved for each boot loader stage when + `USE_COHERENT_MEM=0`. Enabling this option increases the latencies associated + with acquire and release of locks. It also requires changes to the platform + ports. + +- It is now possible to specify the name of the FIP at build time by defining + the `FIP_NAME` variable. + +- Issues with dependencies on the 'fiptool' makefile target have been rectified. + The `fip_create` tool is now rebuilt whenever its source files change. + +- The BL3-1 runtime console is now also used as the crash console. The crash + console is changed to SoC UART0 (UART2) from the previous FPGA UART0 (UART0) + on Juno. In FVP, it is changed from UART0 to UART1. + +- CPU errata workarounds are applied only when the revision and part number + match. This behaviour has been made consistent across the debug and release + builds. The debug build additionally prints a warning if a mismatch is + detected. + +- It is now possible to issue cache maintenance operations by set/way for a + particular level of data cache. Levels 1-3 are currently supported. + +- The following improvements have been made to the FVP port. + + - The build option `FVP_SHARED_DATA_LOCATION` which allowed relocation of + shared data into the Trusted DRAM has been deprecated. Shared data is now + always located at the base of Trusted SRAM. + - BL2 Translation tables have been updated to map only the region of DRAM + which is accessible to normal world. This is the region of the 2GB DDR-DRAM + memory at 0x80000000 excluding the top 16MB. The top 16MB is accessible to + only the secure world. + - BL3-2 can now reside in the top 16MB of DRAM which is accessible only to the + secure world. This can be done by setting the build flag + `FVP_TSP_RAM_LOCATION` to the value `dram`. + +- Separate translation tables are created for each boot loader image. The + `IMAGE_BLx` build options are used to do this. This allows each stage to + create mappings only for areas in the memory map that it needs. + +- A Secure Payload Dispatcher (OPTEED) for the OP-TEE Trusted OS has been added. + Details of using it with TF-A can be found in {ref}`OP-TEE Dispatcher` + +### Issues resolved since last release + +- The Juno port has been aligned with the FVP port as follows. + + - Support for reclaiming all BL1 RW memory and BL2 memory by overlaying the + BL3-1/BL3-2 NOBITS sections on top of them has been added to the Juno port. + - The top 16MB of the 2GB DDR-DRAM memory at 0x80000000 is configured using + the TZC-400 controller to be accessible only to the secure world. + - The Arm GIC driver is used to configure the GIC-400 instead of using a GIC + driver private to the Juno port. + - PSCI `CPU_SUSPEND` calls that target a standby state are now supported. + - The TZC-400 driver is used to configure the controller instead of direct + accesses to the registers. + +- The Linux kernel version referred to in the user guide has DVFS and HMP + support enabled. + +- DS-5 v5.19 did not detect Version 5.8 of the Cortex-A57-A53 Base FVPs in CADI + server mode. This issue is not seen with DS-5 v5.20 and Version 6.2 of the + Cortex-A57-A53 Base FVPs. + +### Known issues + +- The Trusted Board Boot implementation is a prototype. There are issues with + the modularity and scalability of the design. Support for a Trusted Watchdog, + firmware update mechanism, recovery images and Trusted debug is absent. These + issues will be addressed in future releases. +- The FVP and Juno ports do not use the hash of the ROTPK stored in the Trusted + Key Storage registers to verify the ROTPK in the `plat_match_rotpk()` + function. This prevents the correct establishment of the Chain of Trust at the + first step in the Trusted Board Boot process. +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI `SYSTEM_OFF` API. This issue will be fixed in a future version of the + model. +- GICv3 support is experimental. There are known issues with GICv3 + initialization in the TF-A. +- While this version greatly reduces the on-chip RAM requirements, there are + further RAM usage enhancements that could be made. +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. +- The Juno-specific firmware design documentation is incomplete. + +## [1.0.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v0.4..refs/tags/v1.0) (2014-08-28) + +### New features + +- It is now possible to map higher physical addresses using non-flat virtual to + physical address mappings in the MMU setup. + +- Wider use is now made of the per-CPU data cache in BL3-1 to store: + + - Pointers to the non-secure and secure security state contexts. + - A pointer to the CPU-specific operations. + - A pointer to PSCI specific information (for example the current power + state). + - A crash reporting buffer. + +- The following RAM usage improvements result in a BL3-1 RAM usage reduction + from 96KB to 56KB (for FVP with TSPD), and a total RAM usage reduction across + all images from 208KB to 88KB, compared to the previous release. + + - Removed the separate `early_exception` vectors from BL3-1 (2KB code size + saving). + - Removed NSRAM from the FVP memory map, allowing the removal of one (4KB) + translation table. + - Eliminated the internal `psci_suspend_context` array, saving 2KB. + - Correctly dimensioned the PSCI `aff_map_node` array, saving 1.5KB in the FVP + port. + - Removed calling CPU mpidr from the bakery lock API, saving 160 bytes. + - Removed current CPU mpidr from PSCI common code, saving 160 bytes. + - Inlined the mmio accessor functions, saving 360 bytes. + - Fully reclaimed all BL1 RW memory and BL2 memory on the FVP port by + overlaying the BL3-1/BL3-2 NOBITS sections on top of these at runtime. + - Made storing the FP register context optional, saving 0.5KB per context (8KB + on the FVP port, with TSPD enabled and running on 8 CPUs). + - Implemented a leaner `tf_printf()` function, allowing the stack to be + greatly reduced. + - Removed coherent stacks from the codebase. Stacks allocated in normal memory + are now used before and after the MMU is enabled. This saves 768 bytes per + CPU in BL3-1. + - Reworked the crash reporting in BL3-1 to use less stack. + - Optimized the EL3 register state stored in the `cpu_context` structure so + that registers that do not change during normal execution are re-initialized + each time during cold/warm boot, rather than restored from memory. This + saves about 1.2KB. + - As a result of some of the above, reduced the runtime stack size in all BL + images. For BL3-1, this saves 1KB per CPU. + +- PSCI SMC handler improvements to correctly handle calls from secure states and + from AArch32. + +- CPU contexts are now initialized from the `entry_point_info`. BL3-1 fully + determines the exception level to use for the non-trusted firmware (BL3-3) + based on the SPSR value provided by the BL2 platform code (or otherwise + provided to BL3-1). This allows platform code to directly run non-trusted + firmware payloads at either EL2 or EL1 without requiring an EL2 stub or OS + loader. + +- Code refactoring improvements: + + - Refactored `fvp_config` into a common platform header. + - Refactored the fvp gic code to be a generic driver that no longer has an + explicit dependency on platform code. + - Refactored the CCI-400 driver to not have dependency on platform code. + - Simplified the IO driver so it's no longer necessary to call `io_init()` and + moved all the IO storage framework code to one place. + - Simplified the interface the the TZC-400 driver. + - Clarified the platform porting interface to the TSP. + - Reworked the TSPD setup code to support the alternate BL3-2 initialization + flow where BL3-1 generic code hands control to BL3-2, rather than expecting + the TSPD to hand control directly to BL3-2. + - Considerable rework to PSCI generic code to support CPU specific operations. + +- Improved console log output, by: + + - Adding the concept of debug log levels. + - Rationalizing the existing debug messages and adding new ones. + - Printing out the version of each BL stage at runtime. + - Adding support for printing console output from assembler code, including + when a crash occurs before the C runtime is initialized. + +- Moved up to the latest versions of the FVPs, toolchain, EDK2, kernel, Linaro + file system and DS-5. + +- On the FVP port, made the use of the Trusted DRAM region optional at build + time (off by default). Normal platforms will not have such a "ready-to-use" + DRAM area so it is not a good example to use it. + +- Added support for PSCI `SYSTEM_OFF` and `SYSTEM_RESET` APIs. + +- Added support for CPU specific reset sequences, power down sequences and + register dumping during crash reporting. The CPU specific reset sequences + include support for errata workarounds. + +- Merged the Juno port into the master branch. Added support for CPU hotplug and + CPU idle. Updated the user guide to describe how to build and run on the Juno + platform. + +### Issues resolved since last release + +- Removed the concept of top/bottom image loading. The image loader now + automatically detects the position of the image inside the current memory + layout and updates the layout to minimize fragmentation. This resolves the + image loader limitations of previously releases. There are currently no plans + to support dynamic image loading. +- CPU idle now works on the publicized version of the Foundation FVP. +- All known issues relating to the compiler version used have now been resolved. + This TF-A version uses Linaro toolchain 14.07 (based on GCC 4.9). + +### Known issues + +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in the + TF-A. + +- While this version greatly reduces the on-chip RAM requirements, there are + further RAM usage enhancements that could be made. + +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +- The Juno-specific firmware design documentation is incomplete. + +- Some recent enhancements to the FVP port have not yet been translated into the + Juno port. These will be tracked via the tf-issues project. + +- The Linux kernel version referred to in the user guide has DVFS and HMP + support disabled due to some known instabilities at the time of this release. + A future kernel version will re-enable these features. + +- DS-5 v5.19 does not detect Version 5.8 of the Cortex-A57-A53 Base FVPs in CADI + server mode. This is because the `` reported by the FVP in this + version has changed. For example, for the Cortex-A57x4-A53x4 Base FVP, the + `` reported by the FVP is `FVP_Base_Cortex_A57x4_A53x4`, while DS-5 + expects it to be `FVP_Base_A57x4_A53x4`. + + The temporary fix to this problem is to change the name of the FVP in + `sw/debugger/configdb/Boards/ARM FVP/Base_A57x4_A53x4/cadi_config.xml`. Change + the following line: + + ``` + System Generator:FVP_Base_A57x4_A53x4 + ``` + + to System Generator:FVP_Base_Cortex-A57x4_A53x4 + + A similar change can be made to the other Cortex-A57-A53 Base FVP variants. + +## [0.4.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v0.3..refs/tags/v0.4) (2014-06-03) + +### New features + +- Makefile improvements: + + - Improved dependency checking when building. + - Removed `dump` target (build now always produces dump files). + - Enabled platform ports to optionally make use of parts of the Trusted + Firmware (e.g. BL3-1 only), rather than being forced to use all parts. Also + made the `fip` target optional. + - Specified the full path to source files and removed use of the `vpath` + keyword. + +- Provided translation table library code for potential re-use by platforms + other than the FVPs. + +- Moved architectural timer setup to platform-specific code. + +- Added standby state support to PSCI cpu_suspend implementation. + +- SRAM usage improvements: + + - Started using the `-ffunction-sections`, `-fdata-sections` and + `--gc-sections` compiler/linker options to remove unused code and data from + the images. Previously, all common functions were being built into all + binary images, whether or not they were actually used. + - Placed all assembler functions in their own section to allow more unused + functions to be removed from images. + - Updated BL1 and BL2 to use a single coherent stack each, rather than one per + CPU. + - Changed variables that were unnecessarily declared and initialized as + non-const (i.e. in the .data section) so they are either uninitialized (zero + init) or const. + +- Moved the Test Secure-EL1 Payload (BL3-2) to execute in Trusted SRAM by + default. The option for it to run in Trusted DRAM remains. + +- Implemented a TrustZone Address Space Controller (TZC-400) driver. A default + configuration is provided for the Base FVPs. This means the model parameter + `-C bp.secure_memory=1` is now supported. + +- Started saving the PSCI cpu_suspend 'power_state' parameter prior to + suspending a CPU. This allows platforms that implement multiple power-down + states at the same affinity level to identify a specific state. + +- Refactored the entire codebase to reduce the amount of nesting in header files + and to make the use of system/user includes more consistent. Also split + platform.h to separate out the platform porting declarations from the required + platform porting definitions and the definitions/declarations specific to the + platform port. + +- Optimized the data cache clean/invalidate operations. + +- Improved the BL3-1 unhandled exception handling and reporting. Unhandled + exceptions now result in a dump of registers to the console. + +- Major rework to the handover interface between BL stages, in particular the + interface to BL3-1. The interface now conforms to a specification and is more + future proof. + +- Added support for optionally making the BL3-1 entrypoint a reset handler + (instead of BL1). This allows platforms with an alternative image loading + architecture to re-use BL3-1 with fewer modifications to generic code. + +- Reserved some DDR DRAM for secure use on FVP platforms to avoid future + compatibility problems with non-secure software. + +- Added support for secure interrupts targeting the Secure-EL1 Payload (SP) + (using GICv2 routing only). Demonstrated this working by adding an interrupt + target and supporting test code to the TSP. Also demonstrated non-secure + interrupt handling during TSP processing. + +### Issues resolved since last release + +- Now support use of the model parameter `-C bp.secure_memory=1` in the Base + FVPs (see **New features**). +- Support for secure world interrupt handling now available (see **New + features**). +- Made enough SRAM savings (see **New features**) to enable the Test Secure-EL1 + Payload (BL3-2) to execute in Trusted SRAM by default. +- The tested filesystem used for this release (Linaro AArch64 OpenEmbedded + 14.04) now correctly reports progress in the console. +- Improved the Makefile structure to make it easier to separate out parts of the + TF-A for re-use in platform ports. Also, improved target dependency checking. + +### Known issues + +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in the + TF-A. +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead to + loading errors, even if the images should theoretically fit in memory. +- TF-A still uses too much on-chip Trusted SRAM. A number of RAM usage + enhancements have been identified to rectify this situation. +- CPU idle does not work on the advertised version of the Foundation FVP. Some + FVP fixes are required that are not available externally at the time of + writing. This can be worked around by disabling CPU idle in the Linux kernel. +- Various bugs in TF-A, UEFI and the Linux kernel have been observed when using + Linaro toolchain versions later than 13.11. Although most of these have been + fixed, some remain at the time of writing. These mainly seem to relate to a + subtle change in the way the compiler converts between 64-bit and 32-bit + values (e.g. during casting operations), which reveals previously hidden bugs + in client code. +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +## [0.3.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v0.2..refs/tags/v0.3) (2014-02-28) + +### New features + +- Support for Foundation FVP Version 2.0 added. The documented UEFI + configuration disables some devices that are unavailable in the Foundation + FVP, including MMC and CLCD. The resultant UEFI binary can be used on the + AEMv8 and Cortex-A57-A53 Base FVPs, as well as the Foundation FVP. + + \:::\{note} The software will not work on Version 1.0 of the Foundation FVP. + \::: + +- Enabled third party contributions. Added a new contributing.md containing + instructions for how to contribute and updated copyright text in all files to + acknowledge contributors. + +- The PSCI CPU_SUSPEND API has been stabilised to the extent where it can be + used for entry into power down states with the following restrictions: + + - Entry into standby states is not supported. + - The API is only supported on the AEMv8 and Cortex-A57-A53 Base FVPs. + +- The PSCI AFFINITY_INFO api has undergone limited testing on the Base FVPs to + allow experimental use. + +- Required C library and runtime header files are now included locally in TF-A + instead of depending on the toolchain standard include paths. The local + implementation has been cleaned up and reduced in scope. + +- Added I/O abstraction framework, primarily to allow generic code to load + images in a platform-independent way. The existing image loading code has been + reworked to use the new framework. Semi-hosting and NOR flash I/O drivers are + provided. + +- Introduced Firmware Image Package (FIP) handling code and tools. A FIP + combines multiple firmware images with a Table of Contents (ToC) into a single + binary image. The new FIP driver is another type of I/O driver. The Makefile + builds a FIP by default and the FVP platform code expect to load a FIP from + NOR flash, although some support for image loading using semi- hosting is + retained. + + \:::\{note} Building a FIP by default is a non-backwards-compatible change. ::: + + \:::\{note} Generic BL2 code now loads a BL3-3 (non-trusted firmware) image + into DRAM instead of expecting this to be pre-loaded at known location. This + is also a non-backwards-compatible change. ::: + + \:::\{note} Some non-trusted firmware (e.g. UEFI) will need to be rebuilt so + that it knows the new location to execute from and no longer needs to copy + particular code modules to DRAM itself. ::: + +- Reworked BL2 to BL3-1 handover interface. A new composite structure + (bl31_args) holds the superset of information that needs to be passed from BL2 + to BL3-1, including information on how handover execution control to BL3-2 (if + present) and BL3-3 (non-trusted firmware). + +- Added library support for CPU context management, allowing the saving and + restoring of + + - Shared system registers between Secure-EL1 and EL1. + - VFP registers. + - Essential EL3 system registers. + +- Added a framework for implementing EL3 runtime services. Reworked the PSCI + implementation to be one such runtime service. + +- Reworked the exception handling logic, making use of both SP_EL0 and SP_EL3 + stack pointers for determining the type of exception, managing general purpose + and system register context on exception entry/exit, and handling SMCs. SMCs + are directed to the correct EL3 runtime service. + +- Added support for a Test Secure-EL1 Payload (TSP) and a corresponding + Dispatcher (TSPD), which is loaded as an EL3 runtime service. The TSPD + implements Secure Monitor functionality such as world switching and EL1 + context management, and is responsible for communication with the TSP. + + \:::\{note} The TSPD does not yet contain support for secure world interrupts. + \::: + + \:::\{note} The TSP/TSPD is not built by default. ::: + +### Issues resolved since last release + +- Support has been added for switching context between secure and normal worlds + in EL3. +- PSCI API calls `AFFINITY_INFO` & `PSCI_VERSION` have now been tested (to a + limited extent). +- The TF-A build artifacts are now placed in the `./build` directory and + sub-directories instead of being placed in the root of the project. +- TF-A is now free from build warnings. Build warnings are now treated as + errors. +- TF-A now provides C library support locally within the project to maintain + compatibility between toolchains/systems. +- The PSCI locking code has been reworked so it no longer takes locks in an + incorrect sequence. +- The RAM-disk method of loading a Linux file-system has been confirmed to work + with the TF-A and Linux kernel version (based on version 3.13) used in this + release, for both Foundation and Base FVPs. + +### Known issues + +The following is a list of issues which are expected to be fixed in the future +releases of TF-A. + +- The TrustZone Address Space Controller (TZC-400) is not being programmed yet. + Use of model parameter `-C bp.secure_memory=1` is not supported. +- No support yet for secure world interrupt handling. +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in + TF-A. +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead to + loading errors, even if the images should theoretically fit in memory. +- TF-A uses too much on-chip Trusted SRAM. Currently the Test Secure-EL1 Payload + (BL3-2) executes in Trusted DRAM since there is not enough SRAM. A number of + RAM usage enhancements have been identified to rectify this situation. +- CPU idle does not work on the advertised version of the Foundation FVP. Some + FVP fixes are required that are not available externally at the time of + writing. +- Various bugs in TF-A, UEFI and the Linux kernel have been observed when using + Linaro toolchain versions later than 13.11. Although most of these have been + fixed, some remain at the time of writing. These mainly seem to relate to a + subtle change in the way the compiler converts between 64-bit and 32-bit + values (e.g. during casting operations), which reveals previously hidden bugs + in client code. +- The tested filesystem used for this release (Linaro AArch64 OpenEmbedded + 14.01) does not report progress correctly in the console. It only seems to + produce error output, not standard output. It otherwise appears to function + correctly. Other filesystem versions on the same software stack do not exhibit + the problem. +- The Makefile structure doesn't make it easy to separate out parts of the TF-A + for re-use in platform ports, for example if only BL3-1 is required in a + platform port. Also, dependency checking in the Makefile is flawed. +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +## [0.2.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4b825dc642cb6eb9a060e54bf8d69288fbee4904..refs/tags/v0.2) (2013-10-25) + +### New features + +- First source release. +- Code for the PSCI suspend feature is supplied, although this is not enabled by + default since there are known issues (see below). + +### Issues resolved since last release + +- The "psci" nodes in the FDTs provided in this release now fully comply with + the recommendations made in the PSCI specification. + +### Known issues + +The following is a list of issues which are expected to be fixed in the future +releases of TF-A. + +- The TrustZone Address Space Controller (TZC-400) is not being programmed yet. + Use of model parameter `-C bp.secure_memory=1` is not supported. +- No support yet for secure world interrupt handling or for switching context + between secure and normal worlds in EL3. +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in + TF-A. +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead to + loading errors, even if the images should theoretically fit in memory. +- Although support for PSCI `CPU_SUSPEND` is present, it is not yet stable and + ready for use. +- PSCI API calls `AFFINITY_INFO` & `PSCI_VERSION` are implemented but have not + been tested. +- The TF-A make files result in all build artifacts being placed in the root of + the project. These should be placed in appropriate sub-directories. +- The compilation of TF-A is not free from compilation warnings. Some of these + warnings have not been investigated yet so they could mask real bugs. +- TF-A currently uses toolchain/system include files like stdio.h. It should + provide versions of these within the project to maintain compatibility between + toolchains/systems. +- The PSCI code takes some locks in an incorrect sequence. This may cause + problems with suspend and hotplug in certain conditions. +- The Linux kernel used in this release is based on version 3.12-rc4. Using this + kernel with the TF-A fails to start the file-system as a RAM-disk. It fails to + execute user-space `init` from the RAM-disk. As an alternative, the + VirtioBlock mechanism can be used to provide a file-system to the kernel. + +______________________________________________________________________ + +*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.* + +[mbed tls releases]: https://tls.mbed.org/tech-updates/releases +[pr#1002]: https://github.com/ARM-software/arm-trusted-firmware/pull/1002#issuecomment-312650193 +[sdei specification]: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +[tf-issue#501]: https://github.com/ARM-software/tf-issues/issues/501 diff --git a/arm-trusted-firmware/docs/components/activity-monitors.rst b/arm-trusted-firmware/docs/components/activity-monitors.rst new file mode 100644 index 0000000..dd45c43 --- /dev/null +++ b/arm-trusted-firmware/docs/components/activity-monitors.rst @@ -0,0 +1,34 @@ +Activity Monitors +================= + +FEAT_AMUv1 of the Armv8-A architecture introduces the Activity Monitors +extension. This extension describes the architecture for the Activity Monitor +Unit (|AMU|), an optional non-invasive component for monitoring core events +through a set of 64-bit counters. + +When the ``ENABLE_AMU=1`` build option is provided, Trusted Firmware-A sets up +the |AMU| prior to its exit from EL3, and will save and restore architected +|AMU| counters as necessary upon suspend and resume. + +.. _Activity Monitor Auxiliary Counters: + +Auxiliary counters +------------------ + +FEAT_AMUv1 describes a set of implementation-defined auxiliary counters (also +known as group 1 counters), controlled by the ``ENABLE_AMU_AUXILIARY_COUNTERS`` +build option. + +As a security precaution, Trusted Firmware-A does not enable these by default. +Instead, platforms may configure their auxiliary counters through one of two +possible mechanisms: + +- |FCONF|, controlled by the ``ENABLE_AMU_FCONF`` build option. +- A platform implementation of the ``plat_amu_topology`` function (the default). + +See :ref:`Activity Monitor Unit (AMU) Bindings` for documentation on the |FCONF| +device tree bindings. + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/arm-sip-service.rst b/arm-trusted-firmware/docs/components/arm-sip-service.rst new file mode 100644 index 0000000..b51a94d --- /dev/null +++ b/arm-trusted-firmware/docs/components/arm-sip-service.rst @@ -0,0 +1,435 @@ +Arm SiP Services +================ + +This document enumerates and describes the Arm SiP (Silicon Provider) services. + +SiP services are non-standard, platform-specific services offered by the silicon +implementer or platform provider. They are accessed via ``SMC`` ("SMC calls") +instruction executed from Exception Levels below EL3. SMC calls for SiP +services: + +- Follow `SMC Calling Convention`_; +- Use SMC function IDs that fall in the SiP range, which are ``0xc2000000`` - + ``0xc200ffff`` for 64-bit calls, and ``0x82000000`` - ``0x8200ffff`` for 32-bit + calls. + +The Arm SiP implementation offers the following services: + +- Performance Measurement Framework (PMF) +- Execution State Switching service +- DebugFS interface + +Source definitions for Arm SiP service are located in the ``arm_sip_svc.h`` header +file. + +Performance Measurement Framework (PMF) +--------------------------------------- + +The :ref:`Performance Measurement Framework ` +allows callers to retrieve timestamps captured at various paths in TF-A +execution. + +Execution State Switching service +--------------------------------- + +Execution State Switching service provides a mechanism for a non-secure lower +Exception Level (either EL2, or NS EL1 if EL2 isn't implemented) to request to +switch its execution state (a.k.a. Register Width), either from AArch64 to +AArch32, or from AArch32 to AArch64, for the calling CPU. This service is only +available when Trusted Firmware-A (TF-A) is built for AArch64 (i.e. when build +option ``ARCH`` is set to ``aarch64``). + +``ARM_SIP_SVC_EXE_STATE_SWITCH`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t Function ID + uint32_t PC hi + uint32_t PC lo + uint32_t Cookie hi + uint32_t Cookie lo + + Return: + uint32_t + +The function ID parameter must be ``0x82000020``. It uniquely identifies the +Execution State Switching service being requested. + +The parameters *PC hi* and *PC lo* defines upper and lower words, respectively, +of the entry point (physical address) at which execution should start, after +Execution State has been switched. When calling from AArch64, *PC hi* must be 0. + +When execution starts at the supplied entry point after Execution State has been +switched, the parameters *Cookie hi* and *Cookie lo* are passed in CPU registers +0 and 1, respectively. When calling from AArch64, *Cookie hi* must be 0. + +This call can only be made on the primary CPU, before any secondaries were +brought up with ``CPU_ON`` PSCI call. Otherwise, the call will always fail. + +The effect of switching execution state is as if the Exception Level were +entered for the first time, following power on. This means CPU registers that +have a defined reset value by the Architecture will assume that value. Other +registers should not be expected to hold their values before the call was made. +CPU endianness, however, is preserved from the previous execution state. Note +that this switches the execution state of the calling CPU only. This is not a +substitute for PSCI ``SYSTEM_RESET``. + +The service may return the following error codes: + +- ``STATE_SW_E_PARAM``: If any of the parameters were deemed invalid for + a specific request. +- ``STATE_SW_E_DENIED``: If the call is not successful, or when TF-A is + built for AArch32. + +If the call is successful, the caller wouldn't observe the SMC returning. +Instead, execution starts at the supplied entry point, with the CPU registers 0 +and 1 populated with the supplied *Cookie hi* and *Cookie lo* values, +respectively. + +DebugFS interface +----------------- + +The optional DebugFS interface is accessed through an SMC SiP service. Refer +to the component documentation for details. + +String parameters are passed through a shared buffer using a specific union: + +.. code:: c + + union debugfs_parms { + struct { + char fname[MAX_PATH_LEN]; + } open; + + struct mount { + char srv[MAX_PATH_LEN]; + char where[MAX_PATH_LEN]; + char spec[MAX_PATH_LEN]; + } mount; + + struct { + char path[MAX_PATH_LEN]; + dir_t dir; + } stat; + + struct { + char oldpath[MAX_PATH_LEN]; + char newpath[MAX_PATH_LEN]; + } bind; + }; + +Format of the dir_t structure as such: + +.. code:: c + + typedef struct { + char name[NAMELEN]; + long length; + unsigned char mode; + unsigned char index; + unsigned char dev; + qid_t qid; + } dir_t; + + +* Identifiers + +======================== ============================================= +SMC_OK 0 +SMC_UNK -1 +DEBUGFS_E_INVALID_PARAMS -2 +======================== ============================================= + +======================== ============================================= +MOUNT 0 +CREATE 1 +OPEN 2 +CLOSE 3 +READ 4 +WRITE 5 +SEEK 6 +BIND 7 +STAT 8 +INIT 10 +VERSION 11 +======================== ============================================= + +MOUNT +~~~~~ + +Description +^^^^^^^^^^^ +This operation mounts a blob of data pointed to by path stored in `src`, at +filesystem location pointed to by path stored in `where`, using driver pointed +to by path in `spec`. + +Parameters +^^^^^^^^^^ +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``MOUNT`` +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if mount operation failed +=============== ========================================================== + +OPEN +~~~~ + +Description +^^^^^^^^^^^ +This operation opens the file path pointed to by `fname`. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``OPEN`` +uint32_t mode +======== ============================================================ + +mode can be one of: + +.. code:: c + + enum mode { + O_READ = 1 << 0, + O_WRITE = 1 << 1, + O_RDWR = 1 << 2, + O_BIND = 1 << 3, + O_DIR = 1 << 4, + O_STAT = 1 << 5 + }; + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if open operation failed + +uint32_t w1: file descriptor id on success. +=============== ========================================================== + +CLOSE +~~~~~ + +Description +^^^^^^^^^^^ + +This operation closes a file described by a file descriptor obtained by a +previous call to OPEN. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``CLOSE`` +uint32_t File descriptor id returned by OPEN +======== ============================================================ + +Return values +^^^^^^^^^^^^^ +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if close operation failed +=============== ========================================================== + +READ +~~~~ + +Description +^^^^^^^^^^^ + +This operation reads a number of bytes from a file descriptor obtained by +a previous call to OPEN. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``READ`` +uint32_t File descriptor id returned by OPEN +uint32_t Number of bytes to read +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +On success, the read data is retrieved from the shared buffer after the +operation. + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if read operation failed + +uint32_t w1: number of bytes read on success. +=============== ========================================================== + +SEEK +~~~~ + +Description +^^^^^^^^^^^ + +Move file pointer for file described by given `file descriptor` of given +`offset` related to `whence`. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``SEEK`` +uint32_t File descriptor id returned by OPEN +sint32_t offset in the file relative to whence +uint32_t whence +======== ============================================================ + +whence can be one of: + +========= ============================================================ +KSEEK_SET 0 +KSEEK_CUR 1 +KSEEK_END 2 +========= ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if seek operation failed +=============== ========================================================== + +BIND +~~~~ + +Description +^^^^^^^^^^^ + +Create a link from `oldpath` to `newpath`. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``BIND`` +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if bind operation failed +=============== ========================================================== + +STAT +~~~~ + +Description +^^^^^^^^^^^ + +Perform a stat operation on provided file `name` and returns the directory +entry statistics into `dir`. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``STAT`` +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if stat operation failed +=============== ========================================================== + +INIT +~~~~ + +Description +^^^^^^^^^^^ +Initial call to setup the shared exchange buffer. Notice if successful once, +subsequent calls fail after a first initialization. The caller maps the same +page frame in its virtual space and uses this buffer to exchange string +parameters with filesystem primitives. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``INIT`` +uint64_t Physical address of the shared buffer. +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ====================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if already initialized, + or internal error occurred. +=============== ====================================================== + +VERSION +~~~~~~~ + +Description +^^^^^^^^^^^ +Returns the debugfs interface version if implemented in TF-A. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``VERSION`` +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ====================================================== +int32_t w0 == SMC_OK on success + + w0 == SMC_UNK if interface is not implemented + +uint32_t w1: On success, debugfs interface version, 32 bits + value with major version number in upper 16 bits and + minor version in lower 16 bits. +=============== ====================================================== + +* CREATE(1) and WRITE (5) command identifiers are unimplemented and + return `SMC_UNK`. + +-------------- + +*Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.* + +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest diff --git a/arm-trusted-firmware/docs/components/cot-binding.rst b/arm-trusted-firmware/docs/components/cot-binding.rst new file mode 100644 index 0000000..4f8c8b7 --- /dev/null +++ b/arm-trusted-firmware/docs/components/cot-binding.rst @@ -0,0 +1,332 @@ +Chain of trust bindings +======================= + +The device tree allows to describe the chain of trust with the help of +'cot' node which contain 'manifests' and 'images' as sub-nodes. +'manifests' and 'images' nodes contains number of sub-nodes (i.e. 'certificate' +and 'image' nodes) mentioning properties of the certificate and image respectively. + +Also, device tree describes 'non-volatile-counters' node which contains number of +sub-nodes mentioning properties of all non-volatile-counters used in the chain of trust. + +cot +------------------------------------------------------------------ +This is root node which contains 'manifests' and 'images' as sub-nodes + + +Manifests and Certificate node bindings definition +---------------------------------------------------------------- + +- Manifests node + Description: Container of certificate nodes. + + PROPERTIES + + - compatible: + Usage: required + + Value type: + + Definition: must be "arm, cert-descs" + +- Certificate node + Description: + + Describes certificate properties which are used + during the authentication process. + + PROPERTIES + + - root-certificate + Usage: + + Required for the certificate with no parent. + In other words, certificates which are validated + using root of trust public key. + + Value type: + + - image-id + Usage: Required for every certificate with unique id. + + Value type: + + - parent + Usage: + + It refers to their parent image, which typically contains + information to authenticate the certificate. + This property is required for all non-root certificates. + + This property is not required for root-certificates + as root-certificates are validated using root of trust + public key provided by platform. + + Value type: + + - signing-key + Usage: + + This property is used to refer public key node present in + parent certificate node and it is required property for all + non-root certificates which are authenticated using public-key + present in parent certificate. + + This property is not required for root-certificates + as root-certificates are validated using root of trust + public key provided by platform. + + Value type: + + - antirollback-counter + Usage: + + This property is used by all certificates which are + protected against rollback attacks using a non-volatile + counter and it is an optional property. + + This property is used to refer one of the non-volatile + counter sub-node present in 'non-volatile counters' node. + + Value type: + + + SUBNODES + - Description: + + Hash and public key information present in the certificate + are shown by these nodes. + + - public key node + Description: Provide public key information in the certificate. + + PROPERTIES + + - oid + Usage: + + This property provides the Object ID of public key + provided in the certificate which the help of which + public key information can be extracted. + + Value type: + + - hash node + Description: Provide the hash information in the certificate. + + PROPERTIES + + - oid + Usage: + + This property provides the Object ID of hash provided in + the certificate which the help of which hash information + can be extracted. + + Value type: + +Example: + +.. code:: c + + cot { + manifests { + compatible = "arm, cert-descs†+ + trusted-key-cert: trusted-key-cert { + root-certificate; + image-id = ; + antirollback-counter = <&trusted_nv_counter>; + + trusted-world-pk: trusted-world-pk { + oid = TRUSTED_WORLD_PK_OID; + }; + non-trusted-world-pk: non-trusted-world-pk { + oid = NON_TRUSTED_WORLD_PK_OID; + }; + }; + + scp_fw_key_cert: scp_fw_key_cert { + image-id = ; + parent = <&trusted-key-cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + + scp_fw_content_pk: scp_fw_content_pk { + oid = SCP_FW_CONTENT_CERT_PK_OID; + }; + }; + . + . + . + + next-certificate { + + }; + }; + }; + +Images and Image node bindings definition +----------------------------------------- + +- Images node + Description: Container of image nodes + + PROPERTIES + + - compatible: + Usage: required + + Value type: + + Definition: must be "arm, img-descs" + +- Image node + Description: + + Describes image properties which will be used during + authentication process. + + PROPERTIES + + - image-id + Usage: Required for every image with unique id. + + Value type: + + - parent + Usage: + + Required for every image to provide a reference to + its parent image, which contains the necessary information + to authenticate it. + + Value type: + + - hash + Usage: + + Required for all images which are validated using + hash method. This property is used to refer hash + node present in parent certificate node. + + Value type: + + Note: + + Currently, all images are validated using 'hash' + method. In future, there may be multiple methods can + be used to validate the image. + +Example: + +.. code:: c + + cot { + images { + compatible = "arm, img-descs"; + + scp_bl2_image { + image-id = ; + parent = <&scp_fw_content_cert>; + hash = <&scp_fw_hash>; + }; + + . + . + . + + next-img { + + }; + }; + }; + +non-volatile counter node binding definition +-------------------------------------------- + +- non-volatile counters node + Description: Contains properties for non-volatile counters. + + PROPERTIES + + - compatible: + Usage: required + + Value type: + + Definition: must be "arm, non-volatile-counter" + + - #address-cells + Usage: required + + Value type: + + Definition: + + Must be set according to address size + of non-volatile counter register + + - #size-cells + Usage: required + + Value type: + + Definition: must be set to 0 + + SUBNODE + - counters node + Description: Contains various non-volatile counters present in the platform. + + PROPERTIES + - id + Usage: Required for every nv-counter with unique id. + + Value type: + + - reg + Usage: + + Register base address of non-volatile counter and it is required + property. + + Value type: + + - oid + Usage: + + This property provides the Object ID of non-volatile counter + provided in the certificate and it is required property. + + Value type: + +Example: +Below is non-volatile counters example for ARM platform + +.. code:: c + + non_volatile_counters: non_volatile_counters { + compatible = "arm, non-volatile-counter"; + #address-cells = <1>; + #size-cells = <0>; + + trusted-nv-counter: trusted_nv_counter { + id = ; + reg = ; + oid = TRUSTED_FW_NVCOUNTER_OID; + }; + + non_trusted_nv_counter: non_trusted_nv_counter { + id = ; + reg = ; + oid = NON_TRUSTED_FW_NVCOUNTER_OID; + }; + }; + +Future update to chain of trust binding +--------------------------------------- + +This binding document needs to be revisited to generalise some terminologies +which are currently specific to X.509 certificates for e.g. Object IDs. + +*Copyright (c) 2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/debugfs-design.rst b/arm-trusted-firmware/docs/components/debugfs-design.rst new file mode 100644 index 0000000..2536515 --- /dev/null +++ b/arm-trusted-firmware/docs/components/debugfs-design.rst @@ -0,0 +1,125 @@ +======== +Debug FS +======== + +.. contents:: + +Overview +-------- + +The *DebugFS* feature is primarily aimed at exposing firmware debug data to +higher SW layers such as a non-secure component. Such component can be the +TFTF test payload or a Linux kernel module. + +Virtual filesystem +------------------ + +The core functionality lies in a virtual file system based on a 9p file server +interface (`Notes on the Plan 9 Kernel Source`_ and +`Linux 9p remote filesystem protocol`_). +The implementation permits exposing virtual files, firmware drivers, and file blobs. + +Namespace +~~~~~~~~~ + +Two namespaces are exposed: + + - # is used as root for drivers (e.g. #t0 is the first uart) + - / is used as root for virtual "files" (e.g. /fip, or /dev/uart) + +9p interface +~~~~~~~~~~~~ + +The associated primitives are: + +- Unix-like: + + - open(): create a file descriptor that acts as a handle to the file passed as + an argument. + - close(): close the file descriptor created by open(). + - read(): read from a file to a buffer. + - write(): write from a buffer to a file. + - seek(): set the file position indicator of a file descriptor either to a + relative or an absolute offset. + - stat(): get information about a file (type, mode, size, ...). + +.. code:: c + + 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 stat(char *path, dir_t *dir); + +- Specific primitives : + + - mount(): create a link between a driver and spec. + - create(): create a file in a specific location. + - bind(): expose the content of a directory to another directory. + +.. code:: c + + int mount(char *srv, char *mnt, char *spec); + int create(const char *name, int flags); + int bind(char *path, char *where); + +This interface is embedded into the BL31 run-time payload when selected by build +options. The interface multiplexes drivers or emulated "files": + +- Debug data can be partitioned into different virtual files e.g. expose PMF + measurements through a file, and internal firmware state counters through + another file. +- This permits direct access to a firmware driver, mainly for test purposes + (e.g. a hardware device that may not be accessible to non-privileged/ + non-secure layers, or for which no support exists in the NS side). + +SMC interface +------------- + +The communication with the 9p layer in BL31 is made through an SMC conduit +(`SMC Calling Convention`_), using a specific SiP Function Id. An NS +shared buffer is used to pass path string parameters, or e.g. to exchange +data on a read operation. Refer to :ref:`ARM SiP Services ` +for a description of the SMC interface. + +Security considerations +----------------------- + +- Due to the nature of the exposed data, the feature is considered experimental + and importantly **shall only be used in debug builds**. +- Several primitive imply string manipulations and usage of string formats. +- Special care is taken with the shared buffer to avoid TOCTOU attacks. + +Limitations +----------- + +- In order to setup the shared buffer, the component consuming the interface + needs to allocate a physical page frame and transmit its address. +- In order to map the shared buffer, BL31 requires enabling the dynamic xlat + table option. +- Data exchange is limited by the shared buffer length. A large read operation + might be split into multiple read operations of smaller chunks. +- On concurrent access, a spinlock is implemented in the BL31 service to protect + the internal work buffer, and re-entrancy into the filesystem layers. +- Notice, a physical device driver if exposed by the firmware may conflict with + the higher level OS if the latter implements its own driver for the same + physical device. + +Applications +------------ + +The SMC interface is accessible from an NS environment, that is: + +- a test payload, bootloader or hypervisor running at NS-EL2 +- a Linux kernel driver running at NS-EL1 +- a Linux userspace application through the kernel driver + +-------------- + +*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.* + +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _Notes on the Plan 9 Kernel Source: http://lsub.org/who/nemo/9.pdf +.. _Linux 9p remote filesystem protocol: https://www.kernel.org/doc/Documentation/filesystems/9p.txt +.. _ARM SiP Services: arm-sip-service.rst diff --git a/arm-trusted-firmware/docs/components/exception-handling.rst b/arm-trusted-firmware/docs/components/exception-handling.rst new file mode 100644 index 0000000..6f223c6 --- /dev/null +++ b/arm-trusted-firmware/docs/components/exception-handling.rst @@ -0,0 +1,619 @@ +Exception Handling Framework +============================ + +This document describes various aspects of handling exceptions by Runtime +Firmware (BL31) that are targeted at EL3, other than SMCs. The |EHF| takes care +of the following exceptions when targeted at EL3: + +- Interrupts +- Synchronous External Aborts +- Asynchronous External Aborts + +|TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is +described in the :ref:`Firmware Design document `. However, the +|EHF| changes the semantics of `Interrupt handling`_ and :ref:`synchronous +exceptions ` other than SMCs. + +The |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to +``1``, and is only available for AArch64 systems. + +Introduction +------------ + +Through various control bits in the ``SCR_EL3`` register, the Arm architecture +allows for asynchronous exceptions to be routed to EL3. As described in the +:ref:`Interrupt Management Framework` document, depending on the chosen +interrupt routing model, TF-A appropriately sets the ``FIQ`` and ``IRQ`` bits of +``SCR_EL3`` register to effect this routing. For most use cases, other than for +the purpose of facilitating context switch between Normal and Secure worlds, +FIQs and IRQs routed to EL3 are not required to be handled in EL3. + +However, the evolving system and standards landscape demands that various +exceptions are targeted at and handled in EL3. For instance: + +- Starting with ARMv8.2 architecture extension, many RAS features have been + introduced to the Arm architecture. With RAS features implemented, various + components of the system may use one of the asynchronous exceptions to signal + error conditions to PEs. These error conditions are of critical nature, and + it's imperative that corrective or remedial actions are taken at the earliest + opportunity. Therefore, a *Firmware-first Handling* approach is generally + followed in response to RAS events in the system. + +- The Arm `SDEI specification`_ defines interfaces through which Normal world + interacts with the Runtime Firmware in order to request notification of + system events. The |SDEI| specification requires that these events are + notified even when the Normal world executes with the exceptions masked. This + too implies that firmware-first handling is required, where the events are + first received by the EL3 firmware, and then dispatched to Normal world + through purely software mechanism. + +For |TF-A|, firmware-first handling means that asynchronous exceptions are +suitably routed to EL3, and the Runtime Firmware (BL31) is extended to include +software components that are capable of handling those exceptions that target +EL3. These components—referred to as *dispatchers* [#spd]_ in general—may +choose to: + +.. _delegation-use-cases: + +- Receive and handle exceptions entirely in EL3, meaning the exceptions + handling terminates in EL3. + +- Receive exceptions, but handle part of the exception in EL3, and delegate the + rest of the handling to a dedicated software stack running at lower Secure + ELs. In this scheme, the handling spans various secure ELs. + +- Receive exceptions, but handle part of the exception in EL3, and delegate + processing of the error to dedicated software stack running at lower secure + ELs (as above); additionally, the Normal world may also be required to + participate in the handling, or be notified of such events (for example, as + an |SDEI| event). In this scheme, exception handling potentially and + maximally spans all ELs in both Secure and Normal worlds. + +On any given system, all of the above handling models may be employed +independently depending on platform choice and the nature of the exception +received. + +.. [#spd] Not to be confused with :ref:`Secure Payload Dispatcher + `, which is an EL3 component that operates in EL3 + on behalf of Secure OS. + +The role of Exception Handling Framework +---------------------------------------- + +Corollary to the use cases cited above, the primary role of the |EHF| is to +facilitate firmware-first handling of exceptions on Arm systems. The |EHF| thus +enables multiple exception dispatchers in runtime firmware to co-exist, register +for, and handle exceptions targeted at EL3. This section outlines the basics, +and the rest of this document expands the various aspects of the |EHF|. + +In order to arbitrate exception handling among dispatchers, the |EHF| operation +is based on a priority scheme. This priority scheme is closely tied to how the +Arm GIC architecture defines it, although it's applied to non-interrupt +exceptions too (SErrors, for example). + +The platform is required to `partition`__ the Secure priority space into +priority levels as applicable for the Secure software stack. It then assigns the +dispatchers to one or more priority levels. The dispatchers then register +handlers for the priority levels at runtime. A dispatcher can register handlers +for more than one priority level. + +.. __: `Partitioning priority levels`_ + + +.. _ehf-figure: + +.. image:: ../resources/diagrams/draw.io/ehf.svg + +A priority level is *active* when a handler at that priority level is currently +executing in EL3, or has delegated the execution to a lower EL. For interrupts, +this is implicit when an interrupt is targeted and acknowledged at EL3, and the +priority of the acknowledged interrupt is used to match its registered handler. +The priority level is likewise implicitly deactivated when the interrupt +handling concludes by EOIing the interrupt. + +Non-interrupt exceptions (SErrors, for example) don't have a notion of priority. +In order for the priority arbitration to work, the |EHF| provides APIs in order +for these non-interrupt exceptions to assume a priority, and to interwork with +interrupts. Dispatchers handling such exceptions must therefore explicitly +activate and deactivate the respective priority level as and when they're +handled or delegated. + +Because priority activation and deactivation for interrupt handling is implicit +and involves GIC priority masking, it's impossible for a lower priority +interrupt to preempt a higher priority one. By extension, this means that a +lower priority dispatcher cannot preempt a higher-priority one. Priority +activation and deactivation for non-interrupt exceptions, however, has to be +explicit. The |EHF| therefore disallows for lower priority level to be activated +whilst a higher priority level is active, and would result in a panic. +Likewise, a panic would result if it's attempted to deactivate a lower priority +level when a higher priority level is active. + +In essence, priority level activation and deactivation conceptually works like a +stack—priority levels stack up in strictly increasing fashion, and need to be +unstacked in strictly the reverse order. For interrupts, the GIC ensures this is +the case; for non-interrupts, the |EHF| monitors and asserts this. See +`Transition of priority levels`_. + +.. _interrupt-handling: + +Interrupt handling +------------------ + +The |EHF| is a client of *Interrupt Management Framework*, and registers the +top-level handler for interrupts that target EL3, as described in the +:ref:`Interrupt Management Framework` document. This has the following +implications: + +- On GICv3 systems, when executing in S-EL1, pending Non-secure interrupts of + sufficient priority are signalled as FIQs, and therefore will be routed to + EL3. As a result, S-EL1 software cannot expect to handle Non-secure + interrupts at S-EL1. Essentially, this deprecates the routing mode described + as :ref:`CSS=0, TEL3=0 `. + + In order for S-EL1 software to handle Non-secure interrupts while having + |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts + are received at EL3, but are then :ref:`synchronously ` + handled over to S-EL1. + +- On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is + set to ``1`` so that *Group 0* interrupts target EL3. + +- While executing in Secure world, |EHF| sets GIC Priority Mask Register to the + lowest Secure priority. This means that no Non-secure interrupts can preempt + Secure execution. See `Effect on SMC calls`_ for more details. + +As mentioned above, with |EHF|, the platform is required to partition *Group 0* +interrupts into distinct priority levels. A dispatcher that chooses to receive +interrupts can then *own* one or more priority levels, and register interrupt +handlers for them. A given priority level can be assigned to only one handler. A +dispatcher may register more than one priority level. + +Dispatchers are assigned interrupt priority levels in two steps: + +.. _Partitioning priority levels: + +Partitioning priority levels +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interrupts are associated to dispatchers by way of grouping and assigning +interrupts to a priority level. In other words, all interrupts that are to +target a particular dispatcher should fall in a particular priority level. For +priority assignment: + +- Of the 8 bits of priority that Arm GIC architecture permits, bit 7 must be 0 + (secure space). + +- Depending on the number of dispatchers to support, the platform must choose + to use the top *n* of the 7 remaining bits to identify and assign interrupts + to individual dispatchers. Choosing *n* bits supports up to 2\ :sup:`n` + distinct dispatchers. For example, by choosing 2 additional bits (i.e., bits + 6 and 5), the platform can partition into 4 secure priority ranges: ``0x0``, + ``0x20``, ``0x40``, and ``0x60``. See `Interrupt handling example`_. + +.. note:: + + The Arm GIC architecture requires that a GIC implementation that supports two + security states must implement at least 32 priority levels; i.e., at least 5 + upper bits of the 8 bits are writeable. In the scheme described above, when + choosing *n* bits for priority range assignment, the platform must ensure + that at least ``n+1`` top bits of GIC priority are writeable. + +The priority thus assigned to an interrupt is also used to determine the +priority of delegated execution in lower ELs. Delegated execution in lower EL is +associated with a priority level chosen with ``ehf_activate_priority()`` API +(described `later`__). The chosen priority level also determines the interrupts +masked while executing in a lower EL, therefore controls preemption of delegated +execution. + +.. __: `ehf-apis`_ + +The platform expresses the chosen priority levels by declaring an array of +priority level descriptors. Each entry in the array is of type +``ehf_pri_desc_t``, and declares a priority level, and shall be populated by the +``EHF_PRI_DESC()`` macro. + +.. warning:: + + The macro ``EHF_PRI_DESC()`` installs the descriptors in the array at a + computed index, and not necessarily where the macro is placed in the array. + The size of the array might therefore be larger than what it appears to be. + The ``ARRAY_SIZE()`` macro therefore should be used to determine the size of + array. + +Finally, this array of descriptors is exposed to |EHF| via the +``EHF_REGISTER_PRIORITIES()`` macro. + +Refer to the `Interrupt handling example`_ for usage. See also: `Interrupt +Prioritisation Considerations`_. + +Programming priority +~~~~~~~~~~~~~~~~~~~~ + +The text in `Partitioning priority levels`_ only describes how the platform +expresses the required levels of priority. It however doesn't choose interrupts +nor program the required priority in GIC. + +The :ref:`Firmware Design guide` explains methods +for configuring secure interrupts. |EHF| requires the platform to enumerate +interrupt properties (as opposed to just numbers) of Secure interrupts. The +priority of secure interrupts must match that as determined in the +`Partitioning priority levels`_ section above. + +See `Limitations`_, and also refer to `Interrupt handling example`_ for +illustration. + +Registering handler +------------------- + +Dispatchers register handlers for their priority levels through the following +API: + +.. code:: c + + int ehf_register_priority_handler(int pri, ehf_handler_t handler) + +The API takes two arguments: + +- The priority level for which the handler is being registered; + +- The handler to be registered. The handler must be aligned to 4 bytes. + +If a dispatcher owns more than one priority levels, it has to call the API for +each of them. + +The API will succeed, and return ``0``, only if: + +- There exists a descriptor with the priority level requested. + +- There are no handlers already registered by a previous call to the API. + +Otherwise, the API returns ``-1``. + +The interrupt handler should have the following signature: + +.. code:: c + + typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie); + +The parameters are as obtained from the top-level :ref:`EL3 interrupt handler +`. + +The :ref:`SDEI dispatcher`, for +example, expects the platform to allocate two different priority levels— +``PLAT_SDEI_CRITICAL_PRI``, and ``PLAT_SDEI_NORMAL_PRI`` —and registers the +same handler to handle both levels. + +Interrupt handling example +-------------------------- + +The following annotated snippet demonstrates how a platform might choose to +assign interrupts to fictitious dispatchers: + +.. code:: c + + #include + #include + #include + + ... + + /* + * This platform uses 2 bits for interrupt association. In total, 3 upper + * bits are in use. + * + * 7 6 5 3 0 + * .-.-.-.----------. + * |0|b|b| ..0.. | + * '-'-'-'----------' + */ + #define PLAT_PRI_BITS 2 + + /* Priorities for individual dispatchers */ + #define DISP0_PRIO 0x00 /* Not used */ + #define DISP1_PRIO 0x20 + #define DISP2_PRIO 0x40 + #define DISP3_PRIO 0x60 + + /* Install priority level descriptors for each dispatcher */ + ehf_pri_desc_t plat_exceptions[] = { + EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO), + EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO), + EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO), + }; + + /* Expose priority descriptors to Exception Handling Framework */ + EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), + PLAT_PRI_BITS); + + ... + + /* List interrupt properties for GIC driver. All interrupts target EL3 */ + const interrupt_prop_t plat_interrupts[] = { + /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */ + INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + + /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */ + INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + + /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */ + INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + }; + + ... + + /* Dispatcher 1 registers its handler */ + ehf_register_priority_handler(DISP1_PRIO, disp1_handler); + + /* Dispatcher 2 registers its handler */ + ehf_register_priority_handler(DISP2_PRIO, disp2_handler); + + /* Dispatcher 3 registers its handler */ + ehf_register_priority_handler(DISP3_PRIO, disp3_handler); + + ... + +See also the `Build-time flow`_ and the `Run-time flow`_. + +.. _Activating and Deactivating priorities: + +Activating and Deactivating priorities +-------------------------------------- + +A priority level is said to be *active* when an exception of that priority is +being handled: for interrupts, this is implied when the interrupt is +acknowledged; for non-interrupt exceptions, such as SErrors or :ref:`SDEI +explicit dispatches `, this has to be done via +calling ``ehf_activate_priority()``. See `Run-time flow`_. + +Conversely, when the dispatcher has reached a logical resolution for the cause +of the exception, the corresponding priority level ought to be deactivated. As +above, for interrupts, this is implied when the interrupt is EOId in the GIC; +for other exceptions, this has to be done via calling +``ehf_deactivate_priority()``. + +Thanks to `different provisions`__ for exception delegation, there are +potentially more than one work flow for deactivation: + +.. __: `delegation-use-cases`_ + +.. _deactivation workflows: + +- The dispatcher has addressed the cause of the exception, and decided to take + no further action. In this case, the dispatcher's handler deactivates the + priority level before returning to the |EHF|. Runtime firmware, upon exit + through an ``ERET``, resumes execution before the interrupt occurred. + +- The dispatcher has to delegate the execution to lower ELs, and the cause of + the exception can be considered resolved only when the lower EL returns + signals complete (via an ``SMC``) at a future point in time. The following + sequence ensues: + + #. The dispatcher calls ``setjmp()`` to setup a jump point, and arranges to + enter a lower EL upon the next ``ERET``. + + #. Through the ensuing ``ERET`` from runtime firmware, execution is delegated + to a lower EL. + + #. The lower EL completes its execution, and signals completion via an + ``SMC``. + + #. The ``SMC`` is handled by the same dispatcher that handled the exception + previously. Noticing the conclusion of exception handling, the dispatcher + does ``longjmp()`` to resume beyond the previous jump point. + +As mentioned above, the |EHF| provides the following APIs for activating and +deactivating interrupt: + +.. _ehf-apis: + +- ``ehf_activate_priority()`` activates the supplied priority level, but only + if the current active priority is higher than the given one; otherwise + panics. Also, to prevent interruption by physical interrupts of lower + priority, the |EHF| programs the *Priority Mask Register* corresponding to + the PE to the priority being activated. Dispatchers typically only need to + call this when handling exceptions other than interrupts, and it needs to + delegate execution to a lower EL at a desired priority level. + +- ``ehf_deactivate_priority()`` deactivates a given priority, but only if the + current active priority is equal to the given one; otherwise panics. |EHF| + also restores the *Priority Mask Register* corresponding to the PE to the + priority before the call to ``ehf_activate_priority()``. Dispatchers + typically only need to call this after handling exceptions other than + interrupts. + +The calling of APIs are subject to allowed `transitions`__. See also the +`Run-time flow`_. + +.. __: `Transition of priority levels`_ + +Transition of priority levels +----------------------------- + +The |EHF| APIs ``ehf_activate_priority()`` and ``ehf_deactivate_priority()`` can +be called to transition the current priority level on a PE. A given sequence of +calls to these APIs are subject to the following conditions: + +- For activation, the |EHF| only allows for the priority to increase (i.e. + numeric value decreases); + +- For deactivation, the |EHF| only allows for the priority to decrease (i.e. + numeric value increases). Additionally, the priority being deactivated is + required to be the current priority. + +If these are violated, a panic will result. + +.. _Effect on SMC calls: + +Effect on SMC calls +------------------- + +In general, Secure execution is regarded as more important than Non-secure +execution. As discussed elsewhere in this document, EL3 execution, and any +delegated execution thereafter, has the effect of raising GIC's priority +mask—either implicitly by acknowledging Secure interrupts, or when dispatchers +call ``ehf_activate_priority()``. As a result, Non-secure interrupts cannot +preempt any Secure execution. + +SMCs from Non-secure world are synchronous exceptions, and are mechanisms for +Non-secure world to request Secure services. They're broadly classified as +*Fast* or *Yielding* (see `SMCCC`__). + +.. __: https://developer.arm.com/docs/den0028/latest + +- *Fast* SMCs are atomic from the caller's point of view. I.e., they return + to the caller only when the Secure world has finished serving the request. + Any Non-secure interrupts that become pending meanwhile cannot preempt Secure + execution. + +- *Yielding* SMCs carry the semantics of a preemptible, lower-priority request. + A pending Non-secure interrupt can preempt Secure execution handling a + Yielding SMC. I.e., the caller might observe a Yielding SMC returning when + either: + + #. Secure world completes the request, and the caller would find ``SMC_OK`` + as the return code. + + #. A Non-secure interrupt preempts Secure execution. Non-secure interrupt is + handled, and Non-secure execution resumes after ``SMC`` instruction. + + The dispatcher handling a Yielding SMC must provide a different return code + to the Non-secure caller to distinguish the latter case. This return code, + however, is not standardised (unlike ``SMC_UNKNOWN`` or ``SMC_OK``, for + example), so will vary across dispatchers that handle the request. + +For the latter case above, dispatchers before |EHF| expect Non-secure interrupts +to be taken to S-EL1 [#irq]_, so would get a chance to populate the designated +preempted error code before yielding to Non-secure world. + +The introduction of |EHF| changes the behaviour as described in `Interrupt +handling`_. + +When |EHF| is enabled, in order to allow Non-secure interrupts to preempt +Yielding SMC handling, the dispatcher must call ``ehf_allow_ns_preemption()`` +API. The API takes one argument, the error code to be returned to the Non-secure +world upon getting preempted. + +.. [#irq] In case of GICv2, Non-secure interrupts while in S-EL1 were signalled + as IRQs, and in case of GICv3, FIQs. + +Build-time flow +--------------- + +Please refer to the `figure`__ above. + +.. __: `ehf-figure`_ + +The build-time flow involves the following steps: + +#. Platform assigns priorities by installing priority level descriptors for + individual dispatchers, as described in `Partitioning priority levels`_. + +#. Platform provides interrupt properties to GIC driver, as described in + `Programming priority`_. + +#. Dispatcher calling ``ehf_register_priority_handler()`` to register an + interrupt handler. + +Also refer to the `Interrupt handling example`_. + +Run-time flow +------------- + +.. _interrupt-flow: + +The following is an example flow for interrupts: + +#. The GIC driver, during initialization, iterates through the platform-supplied + interrupt properties (see `Programming priority`_), and configures the + interrupts. This programs the appropriate priority and group (Group 0) on + interrupts belonging to different dispatchers. + +#. The |EHF|, during its initialisation, registers a top-level interrupt handler + with the :ref:`Interrupt Management Framework` for EL3 + interrupts. This also results in setting the routing bits in ``SCR_EL3``. + +#. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0 + interrupt, and is taken to EL3. + +#. The top-level EL3 interrupt handler executes. The handler acknowledges the + interrupt, reads its *Running Priority*, and from that, determines the + dispatcher handler. + +#. The |EHF| programs the *Priority Mask Register* of the PE to the priority of + the interrupt received. + +#. The |EHF| marks that priority level *active*, and jumps to the dispatcher + handler. + +#. Once the dispatcher handler finishes its job, it has to immediately + *deactivate* the priority level before returning to the |EHF|. See + `deactivation workflows`_. + +.. _non-interrupt-flow: + +The following is an example flow for exceptions that targets EL3 other than +interrupt: + +#. The platform provides handlers for the specific kind of exception. + +#. The exception arrives, and the corresponding handler is executed. + +#. The handler calls ``ehf_activate_priority()`` to activate the required + priority level. This also has the effect of raising GIC priority mask, thus + preventing interrupts of lower priority from preempting the handling. The + handler may choose to do the handling entirely in EL3 or delegate to a lower + EL. + +#. Once exception handling concludes, the handler calls + ``ehf_deactivate_priority()`` to deactivate the priority level activated + earlier. This also has the effect of lowering GIC priority mask to what it + was before. + +Interrupt Prioritisation Considerations +--------------------------------------- + +The GIC priority scheme, by design, prioritises Secure interrupts over Normal +world ones. The platform further assigns relative priorities amongst Secure +dispatchers through |EHF|. + +As mentioned in `Partitioning priority levels`_, interrupts targeting distinct +dispatchers fall in distinct priority levels. Because they're routed via the +GIC, interrupt delivery to the PE is subject to GIC prioritisation rules. In +particular, when an interrupt is being handled by the PE (i.e., the interrupt is +in *Active* state), only interrupts of higher priority are signalled to the PE, +even if interrupts of same or lower priority are pending. This has the side +effect of one dispatcher being starved of interrupts by virtue of another +dispatcher handling its (higher priority) interrupts. + +The |EHF| doesn't enforce a particular prioritisation policy, but the platform +should carefully consider the assignment of priorities to dispatchers integrated +into runtime firmware. The platform should sensibly delineate priority to +various dispatchers according to their nature. In particular, dispatchers of +critical nature (RAS, for example) should be assigned higher priority than +others (|SDEI|, for example); and within |SDEI|, Critical priority +|SDEI| should be assigned higher priority than Normal ones. + +Limitations +----------- + +The |EHF| has the following limitations: + +- Although there could be up to 128 Secure dispatchers supported by the GIC + priority scheme, the size of descriptor array exposed with + ``EHF_REGISTER_PRIORITIES()`` macro is currently limited to 32. This serves most + expected use cases. This may be expanded in the future, should use cases + demand so. + +- The platform must ensure that the priority assigned to the dispatcher in the + exception descriptor and the programmed priority of interrupts handled by the + dispatcher match. The |EHF| cannot verify that this has been followed. + +-------------- + +*Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.* + +.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf diff --git a/arm-trusted-firmware/docs/components/fconf/amu-bindings.rst b/arm-trusted-firmware/docs/components/fconf/amu-bindings.rst new file mode 100644 index 0000000..047f75e --- /dev/null +++ b/arm-trusted-firmware/docs/components/fconf/amu-bindings.rst @@ -0,0 +1,142 @@ +Activity Monitor Unit (AMU) Bindings +==================================== + +To support platform-defined Activity Monitor Unit (|AMU|) auxiliary counters +through FCONF, the ``HW_CONFIG`` device tree accepts several |AMU|-specific +nodes and properties. + +Bindings +^^^^^^^^ + +.. contents:: + :local: + +``/cpus/cpus/cpu*`` node properties +""""""""""""""""""""""""""""""""""" + +The ``cpu`` node has been augmented to support a handle to an associated |AMU| +view, which should describe the counters offered by the core. + ++---------------+-------+---------------+-------------------------------------+ +| Property name | Usage | Value type | Description | ++===============+=======+===============+=====================================+ +| ``amu`` | O | ```` | If present, indicates that an |AMU| | +| | | | is available and its counters are | +| | | | described by the node provided. | ++---------------+-------+---------------+-------------------------------------+ + +``/cpus/amus`` node properties +"""""""""""""""""""""""""""""" + +The ``amus`` node describes the |AMUs| implemented by the cores in the system. +This node does not have any properties. + +``/cpus/amus/amu*`` node properties +""""""""""""""""""""""""""""""""""" + +An ``amu`` node describes the layout and meaning of the auxiliary counter +registers of one or more |AMUs|, and may be shared by multiple cores. + ++--------------------+-------+------------+------------------------------------+ +| Property name | Usage | Value type | Description | ++====================+=======+============+====================================+ +| ``#address-cells`` | R | ```` | Value shall be 1. Specifies that | +| | | | the ``reg`` property array of | +| | | | children of this node uses a | +| | | | single cell. | ++--------------------+-------+------------+------------------------------------+ +| ``#size-cells`` | R | ```` | Value shall be 0. Specifies that | +| | | | no size is required in the ``reg`` | +| | | | property in children of this node. | ++--------------------+-------+------------+------------------------------------+ + +``/cpus/amus/amu*/counter*`` node properties +"""""""""""""""""""""""""""""""""""""""""""" + +A ``counter`` node describes an auxiliary counter belonging to the parent |AMU| +view. + ++-------------------+-------+-------------+------------------------------------+ +| Property name | Usage | Value type | Description | ++===================+=======+=============+====================================+ +| ``reg`` | R | array | Represents the counter register | +| | | | index, and must be a single cell. | ++-------------------+-------+-------------+------------------------------------+ +| ``enable-at-el3`` | O | ```` | The presence of this property | +| | | | indicates that this counter should | +| | | | be enabled prior to EL3 exit. | ++-------------------+-------+-------------+------------------------------------+ + +Example +^^^^^^^ + +An example system offering four cores made up of two clusters, where the cores +of each cluster share different |AMUs|, may use something like the following: + +.. code-block:: + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + amus { + amu0: amu-0 { + #address-cells = <1>; + #size-cells = <0>; + + counterX: counter@0 { + reg = <0>; + + enable-at-el3; + }; + + counterY: counter@1 { + reg = <1>; + + enable-at-el3; + }; + }; + + amu1: amu-1 { + #address-cells = <1>; + #size-cells = <0>; + + counterZ: counter@0 { + reg = <0>; + + enable-at-el3; + }; + }; + }; + + cpu0@00000 { + ... + + amu = <&amu0>; + }; + + cpu1@00100 { + ... + + amu = <&amu0>; + }; + + cpu2@10000 { + ... + + amu = <&amu1>; + }; + + cpu3@10100 { + ... + + amu = <&amu1>; + }; + } + +In this situation, ``cpu0`` and ``cpu1`` (the two cores in the first cluster), +share the view of their AMUs defined by ``amu0``. Likewise, ``cpu2`` and +``cpu3`` (the two cores in the second cluster), share the view of their |AMUs| +defined by ``amu1``. This will cause ``counterX`` and ``counterY`` to be enabled +for both ``cpu0`` and ``cpu1``, and ``counterZ`` to be enabled for both ``cpu2`` +and ``cpu3``. diff --git a/arm-trusted-firmware/docs/components/fconf/fconf_properties.rst b/arm-trusted-firmware/docs/components/fconf/fconf_properties.rst new file mode 100644 index 0000000..5c28a7a --- /dev/null +++ b/arm-trusted-firmware/docs/components/fconf/fconf_properties.rst @@ -0,0 +1,32 @@ +DTB binding for FCONF properties +================================ + +This document describes the device tree format of |FCONF| properties. These +properties are not related to a specific platform and can be queried from +common code. + +Dynamic configuration +~~~~~~~~~~~~~~~~~~~~~ + +The |FCONF| framework expects a *dtb-registry* node with the following field: + +- compatible [mandatory] + - value type: + - Must be the string "fconf,dyn_cfg-dtb_registry". + +Then a list of subnodes representing a configuration |DTB|, which can be used +by |FCONF|. Each subnode should be named according to the information it +contains, and must be formed with the following fields: + +- load-address [mandatory] + - value type: + - Physical loading base address of the configuration. + +- max-size [mandatory] + - value type: + - Maximum size of the configuration. + +- id [mandatory] + - value type: + - Image ID of the configuration. + diff --git a/arm-trusted-firmware/docs/components/fconf/index.rst b/arm-trusted-firmware/docs/components/fconf/index.rst new file mode 100644 index 0000000..029f324 --- /dev/null +++ b/arm-trusted-firmware/docs/components/fconf/index.rst @@ -0,0 +1,149 @@ +Firmware Configuration Framework +================================ + +This document provides an overview of the |FCONF| framework. + +Introduction +~~~~~~~~~~~~ + +The Firmware CONfiguration Framework (|FCONF|) is an abstraction layer for +platform specific data, allowing a "property" to be queried and a value +retrieved without the requesting entity knowing what backing store is being used +to hold the data. + +It is used to bridge new and old ways of providing platform-specific data. +Today, information like the Chain of Trust is held within several, nested +platform-defined tables. In the future, it may be provided as part of a device +blob, along with the rest of the information about images to load. +Introducing this abstraction layer will make migration easier and will preserve +functionality for platforms that cannot / don't want to use device tree. + +Accessing properties +~~~~~~~~~~~~~~~~~~~~ + +Properties defined in the |FCONF| are grouped around namespaces and +sub-namespaces: a.b.property. +Examples namespace can be: + +- (|TBBR|) Chain of Trust data: tbbr.cot.trusted_boot_fw_cert +- (|TBBR|) dynamic configuration info: tbbr.dyn_config.disable_auth +- Arm io policies: arm.io_policies.bl2_image +- GICv3 properties: hw_config.gicv3_config.gicr_base + +Properties can be accessed with the ``FCONF_GET_PROPERTY(a,b,property)`` macro. + +Defining properties +~~~~~~~~~~~~~~~~~~~ + +Properties composing the |FCONF| have to be stored in C structures. If +properties originate from a different backend source such as a device tree, +then the platform has to provide a ``populate()`` function which essentially +captures the property and stores them into a corresponding |FCONF| based C +structure. + +Such a ``populate()`` function is usually platform specific and is associated +with a specific backend source. For example, a populator function which +captures the hardware topology of the platform from the HW_CONFIG device tree. +Hence each ``populate()`` function must be registered with a specific +``config_type`` identifier. It broadly represents a logical grouping of +configuration properties which is usually a device tree file. + +Example: + - FW_CONFIG: properties related to base address, maximum size and image id + of other DTBs etc. + - TB_FW: properties related to trusted firmware such as IO policies, + mbedtls heap info etc. + - HW_CONFIG: properties related to hardware configuration of the SoC + such as topology, GIC controller, PSCI hooks, CPU ID etc. + +Hence the ``populate()`` callback must be registered to the (|FCONF|) framework +with the ``FCONF_REGISTER_POPULATOR()`` macro. This ensures that the function +would be called inside the generic ``fconf_populate()`` function during +initialization. + +:: + + int fconf_populate_topology(uintptr_t config) + { + /* read hw config dtb and fill soc_topology struct */ + } + + FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology); + +Then, a wrapper has to be provided to match the ``FCONF_GET_PROPERTY()`` macro: + +:: + + /* generic getter */ + #define FCONF_GET_PROPERTY(a,b,property) a##__##b##_getter(property) + + /* my specific getter */ + #define hw_config__topology_getter(prop) soc_topology.prop + +This second level wrapper can be used to remap the ``FCONF_GET_PROPERTY()`` to +anything appropriate: structure, array, function, etc.. + +To ensure a good interpretation of the properties, this documentation must +explain how the properties are described for a specific backend. Refer to the +:ref:`binding-document` section for more information and example. + +Loading the property device tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``fconf_load_config(image_id)`` must be called to load fw_config and +tb_fw_config devices tree containing the properties' values. This must be done +after the io layer is initialized, as the |DTB| is stored on an external +device (FIP). + +.. uml:: ../../resources/diagrams/plantuml/fconf_bl1_load_config.puml + +Populating the properties +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once a valid device tree is available, the ``fconf_populate(config)`` function +can be used to fill the C data structure with the data from the config |DTB|. +This function will call all the ``populate()`` callbacks which have been +registered with ``FCONF_REGISTER_POPULATOR()`` as described above. + +.. uml:: ../../resources/diagrams/plantuml/fconf_bl2_populate.puml + +Namespace guidance +~~~~~~~~~~~~~~~~~~ + +As mentioned above, properties are logically grouped around namespaces and +sub-namespaces. The following concepts should be considered when adding new +properties/namespaces. +The framework differentiates two types of properties: + + - Properties used inside common code. + - Properties used inside platform specific code. + +The first category applies to properties being part of the firmware and shared +across multiple platforms. They should be globally accessible and defined +inside the ``lib/fconf`` directory. The namespace must be chosen to reflect the +feature/data abstracted. + +Example: + - |TBBR| related properties: tbbr.cot.bl2_id + - Dynamic configuration information: dyn_cfg.dtb_info.hw_config_id + +The second category should represent the majority of the properties defined +within the framework: Platform specific properties. They must be accessed only +within the platform API and are defined only inside the platform scope. The +namespace must contain the platform name under which the properties defined +belong. + +Example: + - Arm io framework: arm.io_policies.bl31_id + +.. _binding-document: + +Properties binding information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + fconf_properties + amu-bindings + mpmm-bindings diff --git a/arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst b/arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst new file mode 100644 index 0000000..d3cc857 --- /dev/null +++ b/arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst @@ -0,0 +1,48 @@ +Maximum Power Mitigation Mechanism (MPMM) Bindings +================================================== + +|MPMM| support cannot be determined at runtime by the firmware. Instead, these +DTB bindings allow the platform to communicate per-core support for |MPMM| via +the ``HW_CONFIG`` device tree blob. + +Bindings +^^^^^^^^ + +.. contents:: + :local: + +``/cpus/cpus/cpu*`` node properties +""""""""""""""""""""""""""""""""""" + +The ``cpu`` node has been augmented to allow the platform to indicate support +for |MPMM| on a given core. + ++-------------------+-------+-------------+------------------------------------+ +| Property name | Usage | Value type | Description | ++===================+=======+=============+====================================+ +| ``supports-mpmm`` | O | ```` | If present, indicates that |MPMM| | +| | | | is available on this core. | ++-------------------+-------+-------------+------------------------------------+ + +Example +^^^^^^^ + +An example system offering two cores, one with support for |MPMM| and one +without, can be described as follows: + +.. code-block:: + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0@00000 { + ... + + supports-mpmm; + }; + + cpu1@00100 { + ... + }; + } diff --git a/arm-trusted-firmware/docs/components/ffa-manifest-binding.rst b/arm-trusted-firmware/docs/components/ffa-manifest-binding.rst new file mode 100644 index 0000000..df2985c --- /dev/null +++ b/arm-trusted-firmware/docs/components/ffa-manifest-binding.rst @@ -0,0 +1,252 @@ +FF-A manifest binding to device tree +======================================== + +This document defines the nodes and properties used to define a partition, +according to the FF-A specification. + +Version 1.0 +----------- + +Partition Properties +^^^^^^^^^^^^^^^^^^^^ + +- compatible [mandatory] + - value type: + - Must be the string "arm,ffa-manifest-X.Y" which specifies the major and + minor versions of the device tree binding for the FFA manifest represented + by this node. The minor number is incremented if the binding changes in a + backwards compatible manner. + + - X is an integer representing the major version number of this document. + - Y is an integer representing the minor version number of this document. + +- ffa-version [mandatory] + - value type: + - Must be two 16 bits values (X, Y), concatenated as 31:16 -> X, + 15:0 -> Y, where: + + - X is the major version of FF-A expected by the partition at the FFA + instance it will execute. + - Y is the minor version of FF-A expected by the partition at the FFA + instance it will execute. + +- uuid [mandatory] + - value type: + - An array consisting of 4 values, identifying the UUID of the service + implemented by this partition. The UUID format is described in RFC 4122. + +- id + - value type: + - Pre-allocated partition ID. + +- auxiliary-id + - value type: + - Pre-allocated ID that could be used in memory management transactions. + +- description + - value type: + - Name of the partition e.g. for debugging purposes. + +- execution-ctx-count [mandatory] + - value type: + - Number of vCPUs that a VM or SP wants to instantiate. + + - In the absence of virtualization, this is the number of execution + contexts that a partition implements. + - If value of this field = 1 and number of PEs > 1 then the partition is + treated as UP & migrate capable. + - If the value of this field > 1 then the partition is treated as a MP + capable partition irrespective of the number of PEs. + +- exception-level [mandatory] + - value type: + - The target exception level for the partition: + + - 0x0: EL1 + - 0x1: S_EL0 + - 0x2: S_EL1 + +- execution-state [mandatory] + - value type: + - The target execution state of the partition: + + - 0: AArch64 + - 1: AArch32 + +- load-address + - value type: + - Physical base address of the partition in memory. Absence of this field + indicates that the partition is position independent and can be loaded at + any address chosen at boot time. + +- entrypoint-offset + - value type: + - Offset from the base of the partition's binary image to the entry point of + the partition. Absence of this field indicates that the entry point is at + offset 0x0 from the base of the partition's binary. + +- xlat-granule [mandatory] + - value type: + - Translation granule used with the partition: + + - 0x0: 4k + - 0x1: 16k + - 0x2: 64k + +- boot-order + - value type: + - A unique number amongst all partitions that specifies if this partition + must be booted before others. The partition with the smaller number will be + booted first. + +- rx-tx-buffer + - value type: "memory-regions" node + - Specific "memory-regions" nodes that describe the RX/TX buffers expected + by the partition. + The "compatible" must be the string "arm,ffa-manifest-rx_tx-buffer". + +- messaging-method [mandatory] + - value type: + - Specifies which messaging methods are supported by the partition, set bit + means the feature is supported, clear bit - not supported: + + - Bit[0]: partition can receive direct requests if set + - Bit[1]: partition can send direct requests if set + - Bit[2]: partition can send and receive indirect messages + +- managed-exit + - value type: + - Specifies if managed exit is supported. + +- has-primary-scheduler + - value type: + - Presence of this field indicates that the partition implements the primary + scheduler. If so, run-time EL must be EL1. + +- run-time-model + - value type: + - Run time model that the SPM must enforce for this SP: + + - 0x0: Run to completion + - 0x1: Preemptible + +- time-slice-mem + - value type: + - Presence of this field indicates that the partition doesn't expect the + partition manager to time slice long running memory management functions. + +- gp-register-num + - value type: + - Presence of this field indicates that the partition expects the + ffa_init_info structure to be passed in via the specified general purpose + register. + The field specifies the general purpose register number but not its width. + The width is derived from the partition's execution state, as specified in + the partition properties. For example, if the number value is 1 then the + general-purpose register used will be x1 in AArch64 state and w1 in AArch32 + state. + +- stream-endpoint-ids + - value type: + - List of tuples, identifying the IDs this partition is acting as + proxy for. + +Memory Regions +-------------- + +- compatible [mandatory] + - value type: + - Must be the string "arm,ffa-manifest-memory-regions". + +- description + - value type: + - Name of the memory region e.g. for debugging purposes. + +- pages-count [mandatory] + - value type: + - Count of pages of memory region as a multiple of the translation granule + size + +- attributes [mandatory] + - value type: + - Mapping modes: ORed to get required permission + + - 0x1: Read + - 0x2: Write + - 0x4: Execute + +- base-address + - value type: + - Base address of the region. The address must be aligned to the translation + granule size. + The address given may be a Physical Address (PA), Virtual Address (VA), or + Intermediate Physical Address (IPA). Refer to the FFA specification for + more information on the restrictions around the address type. + If the base address is omitted then the partition manager must map a memory + region of the specified size into the partition's translation regime and + then communicate the region properties (including the base address chosen + by the partition manager) to the partition. + +Device Regions +-------------- + +- compatible [mandatory] + - value type: + - Must be the string "arm,ffa-manifest-device-regions". + +- description + - value type: + - Name of the device region e.g. for debugging purposes. + +- reg [mandatory] + - value type: + - A (address, num-pages) pair describing the device, where: + + - address: The physical base address value of the device MMIO + region. + - num-pages: The number of pages of the region. The total size of + the region is this value multiplied by the translation granule size. + +- attributes [mandatory] + - value type: + - Mapping modes: ORed to get required permission + + - 0x1: Read + - 0x2: Write + - 0x4: Execute + +- smmu-id + - value type: + - On systems with multiple System Memory Management Units (SMMUs) this + identifier is used to inform the partition manager which SMMU the device is + upstream of. If the field is omitted then it is assumed that the device is + not upstream of any SMMU. + +- stream-ids + - value type: + - A list of (id, mem-manage) pair, where: + + - id: A unique value amongst all devices assigned to the partition. + +- interrupts [mandatory] + - value type: + - A list of (id, attributes) pair describing the device interrupts, where: + + - id: The interrupt IDs. + - attributes: A value, + containing the attributes for each interrupt ID: + + - Interrupt type: SPI, PPI, SGI + - Interrupt configuration: Edge triggered, Level triggered + - Interrupt security state: Secure, Non-secure + - Interrupt priority value + - Target execution context/vCPU for each SPI + +- exclusive-access + - value type: + - Presence of this field implies that this endpoint must be granted exclusive + access and ownership of this device's MMIO region. + +-------------- + +*Copyright (c) 2019-2021, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/firmware-update.rst b/arm-trusted-firmware/docs/components/firmware-update.rst new file mode 100644 index 0000000..a591565 --- /dev/null +++ b/arm-trusted-firmware/docs/components/firmware-update.rst @@ -0,0 +1,400 @@ +Firmware Update (FWU) +===================== + +Introduction +------------ + +This document describes the design of the Firmware Update (FWU) feature, which +enables authenticated firmware to update firmware images from external +interfaces such as USB, UART, SD-eMMC, NAND, NOR or Ethernet to SoC Non-Volatile +memories such as NAND Flash, LPDDR2-NVM or any memory determined by the +platform. This feature functions even when the current firmware in the system +is corrupt or missing; it therefore may be used as a recovery mode. It may also +be complemented by other, higher level firmware update software. + +FWU implements a specific part of the Trusted Board Boot Requirements (TBBR) +specification, Arm DEN0006C-1. It should be used in conjunction with the +:ref:`Trusted Board Boot` design document, which describes the image +authentication parts of the Trusted Firmware-A (TF-A) TBBR implementation. + +Scope +~~~~~ + +This document describes the secure world FWU design. It is beyond its scope to +describe how normal world FWU images should operate. To implement normal world +FWU images, please refer to the "Non-Trusted Firmware Updater" requirements in +the TBBR. + +FWU Overview +------------ + +The FWU boot flow is primarily mediated by BL1. Since BL1 executes in ROM, and +it is usually desirable to minimize the amount of ROM code, the design allows +some parts of FWU to be implemented in other secure and normal world images. +Platform code may choose which parts are implemented in which images but the +general expectation is: + +- BL1 handles: + + - Detection and initiation of the FWU boot flow. + - Copying images from non-secure to secure memory + - FWU image authentication + - Context switching between the normal and secure world during the FWU + process. + +- Other secure world FWU images handle platform initialization required by + the FWU process. +- Normal world FWU images handle loading of firmware images from external + interfaces to non-secure memory. + +The primary requirements of the FWU feature are: + +#. Export a BL1 SMC interface to interoperate with other FWU images executing + at other Exception Levels. +#. Export a platform interface to provide FWU common code with the information + it needs, and to enable platform specific FWU functionality. See the + :ref:`Porting Guide` for details of this interface. + +TF-A uses abbreviated image terminology for FWU images like for other TF-A +images. See the :ref:`Image Terminology` document for an explanation of these +terms. + +The following diagram shows the FWU boot flow for Arm development platforms. +Arm CSS platforms like Juno have a System Control Processor (SCP), and these +use all defined FWU images. Other platforms may use a subset of these. + +|Flow Diagram| + +Image Identification +-------------------- + +Each FWU image and certificate is identified by a unique ID, defined by the +platform, which BL1 uses to fetch an image descriptor (``image_desc_t``) via a +call to ``bl1_plat_get_image_desc()``. The same ID is also used to prepare the +Chain of Trust (Refer to the :ref:`Authentication Framework & Chain of Trust` +document for more information). + +The image descriptor includes the following information: + +- Executable or non-executable image. This indicates whether the normal world + is permitted to request execution of a secure world FWU image (after + authentication). Secure world certificates and non-AP images are examples + of non-executable images. +- Secure or non-secure image. This indicates whether the image is + authenticated/executed in secure or non-secure memory. +- Image base address and size. +- Image entry point configuration (an ``entry_point_info_t``). +- FWU image state. + +BL1 uses the FWU image descriptors to: + +- Validate the arguments of FWU SMCs +- Manage the state of the FWU process +- Initialize the execution state of the next FWU image. + +FWU State Machine +----------------- + +BL1 maintains state for each FWU image during FWU execution. FWU images at lower +Exception Levels raise SMCs to invoke FWU functionality in BL1, which causes +BL1 to update its FWU image state. The BL1 image states and valid state +transitions are shown in the diagram below. Note that secure images have a more +complex state machine than non-secure images. + +|FWU state machine| + +The following is a brief description of the supported states: + +- RESET: This is the initial state of every image at the start of FWU. + Authentication failure also leads to this state. A secure + image may yield to this state if it has completed execution. + It can also be reached by using ``FWU_SMC_IMAGE_RESET``. + +- COPYING: This is the state of a secure image while BL1 is copying it + in blocks from non-secure to secure memory. + +- COPIED: This is the state of a secure image when BL1 has completed + copying it to secure memory. + +- AUTHENTICATED: This is the state of an image when BL1 has successfully + authenticated it. + +- EXECUTED: This is the state of a secure, executable image when BL1 has + passed execution control to it. + +- INTERRUPTED: This is the state of a secure, executable image after it has + requested BL1 to resume normal world execution. + +BL1 SMC Interface +----------------- + +BL1_SMC_CALL_COUNT +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x0 + + Return: + uint32_t + +This SMC returns the number of SMCs supported by BL1. + +BL1_SMC_UID +~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x1 + + Return: + UUID : 32 bits in each of w0-w3 (or r0-r3 for AArch32 callers) + +This SMC returns the 128-bit `Universally Unique Identifier`_ for the +BL1 SMC service. + +BL1_SMC_VERSION +~~~~~~~~~~~~~~~ + +:: + + Argument: + uint32_t function ID : 0x3 + + Return: + uint32_t : Bits [31:16] Major Version + Bits [15:0] Minor Version + +This SMC returns the current version of the BL1 SMC service. + +BL1_SMC_RUN_IMAGE +~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x4 + entry_point_info_t *ep_info + + Return: + void + + Pre-conditions: + if (normal world caller) synchronous exception + if (ep_info not EL3) synchronous exception + +This SMC passes execution control to an EL3 image described by the provided +``entry_point_info_t`` structure. In the normal TF-A boot flow, BL2 invokes +this SMC for BL1 to pass execution control to BL31. + +FWU_SMC_IMAGE_COPY +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x10 + unsigned int image_id + uintptr_t image_addr + unsigned int block_size + unsigned int image_size + + Return: + int : 0 (Success) + : -ENOMEM + : -EPERM + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (image_id is non-secure image) return -EPERM + if (image_id state is not (RESET or COPYING)) return -EPERM + if (secure world caller) return -EPERM + if (image_addr + block_size overflows) return -ENOMEM + if (image destination address + image_size overflows) return -ENOMEM + if (source block is in secure memory) return -ENOMEM + if (source block is not mapped into BL1) return -ENOMEM + if (image_size > free secure memory) return -ENOMEM + if (image overlaps another image) return -EPERM + +This SMC copies the secure image indicated by ``image_id`` from non-secure memory +to secure memory for later authentication. The image may be copied in a single +block or multiple blocks. In either case, the total size of the image must be +provided in ``image_size`` when invoking this SMC for the first time for each +image; it is ignored in subsequent calls (if any) for the same image. + +The ``image_addr`` and ``block_size`` specify the source memory block to copy from. +The destination address is provided by the platform code. + +If ``block_size`` is greater than the amount of remaining bytes to copy for this +image then the former is truncated to the latter. The copy operation is then +considered as complete and the FWU state machine transitions to the "COPIED" +state. If there is still more to copy, the FWU state machine stays in or +transitions to the COPYING state (depending on the previous state). + +When using multiple blocks, the source blocks do not necessarily need to be in +contiguous memory. + +Once the SMC is handled, BL1 returns from exception to the normal world caller. + +FWU_SMC_IMAGE_AUTH +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x11 + unsigned int image_id + uintptr_t image_addr + unsigned int image_size + + Return: + int : 0 (Success) + : -ENOMEM + : -EPERM + : -EAUTH + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (secure world caller) + if (image_id state is not RESET) return -EPERM + if (image_addr/image_size is not mapped into BL1) return -ENOMEM + else // normal world caller + if (image_id is secure image) + if (image_id state is not COPIED) return -EPERM + else // image_id is non-secure image + if (image_id state is not RESET) return -EPERM + if (image_addr/image_size is in secure memory) return -ENOMEM + if (image_addr/image_size not mapped into BL1) return -ENOMEM + +This SMC authenticates the image specified by ``image_id``. If the image is in the +RESET state, BL1 authenticates the image in place using the provided +``image_addr`` and ``image_size``. If the image is a secure image in the COPIED +state, BL1 authenticates the image from the secure memory that BL1 previously +copied the image into. + +BL1 returns from exception to the caller. If authentication succeeds then BL1 +sets the image state to AUTHENTICATED. If authentication fails then BL1 returns +the -EAUTH error and sets the image state back to RESET. + +FWU_SMC_IMAGE_EXECUTE +~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x12 + unsigned int image_id + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (secure world caller) return -EPERM + if (image_id is non-secure image) return -EPERM + if (image_id is non-executable image) return -EPERM + if (image_id state is not AUTHENTICATED) return -EPERM + +This SMC initiates execution of a previously authenticated image specified by +``image_id``, in the other security world to the caller. The current +implementation only supports normal world callers initiating execution of a +secure world image. + +BL1 saves the normal world caller's context, sets the secure image state to +EXECUTED, and returns from exception to the secure image. + +FWU_SMC_IMAGE_RESUME +~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x13 + register_t image_param + + Return: + register_t : image_param (Success) + : -EPERM + + Pre-conditions: + if (normal world caller and no INTERRUPTED secure image) return -EPERM + +This SMC resumes execution in the other security world while there is a secure +image in the EXECUTED/INTERRUPTED state. + +For normal world callers, BL1 sets the previously interrupted secure image state +to EXECUTED. For secure world callers, BL1 sets the previously executing secure +image state to INTERRUPTED. In either case, BL1 saves the calling world's +context, restores the resuming world's context and returns from exception into +the resuming world. If the call is successful then the caller provided +``image_param`` is returned to the resumed world, otherwise an error code is +returned to the caller. + +FWU_SMC_SEC_IMAGE_DONE +~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x14 + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (normal world caller) return -EPERM + +This SMC indicates completion of a previously executing secure image. + +BL1 sets the previously executing secure image state to the RESET state, +restores the normal world context and returns from exception into the normal +world. + +FWU_SMC_UPDATE_DONE +~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x15 + register_t client_cookie + + Return: + N/A + +This SMC completes the firmware update process. BL1 calls the platform specific +function ``bl1_plat_fwu_done``, passing the optional argument ``client_cookie`` as +a ``void *``. The SMC does not return. + +FWU_SMC_IMAGE_RESET +~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x16 + unsigned int image_id + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (secure world caller) return -EPERM + if (image in EXECUTED) return -EPERM + +This SMC sets the state of an image to RESET and zeroes the memory used by it. + +This is only allowed if the image is not being executed. + +-------------- + +*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Universally Unique Identifier: https://tools.ietf.org/rfc/rfc4122.txt +.. |Flow Diagram| image:: ../resources/diagrams/fwu_flow.png +.. |FWU state machine| image:: ../resources/diagrams/fwu_states.png diff --git a/arm-trusted-firmware/docs/components/granule-protection-tables-design.rst b/arm-trusted-firmware/docs/components/granule-protection-tables-design.rst new file mode 100644 index 0000000..07637dd --- /dev/null +++ b/arm-trusted-firmware/docs/components/granule-protection-tables-design.rst @@ -0,0 +1,235 @@ +Granule Protection Tables Library +================================= + +This document describes the design of the granule protection tables (GPT) +library used by Trusted Firmware-A (TF-A). This library provides the APIs needed +to initialize the GPTs based on a data structure containing information about +the systems memory layout, configure the system registers to enable granule +protection checks based on these tables, and transition granules between +different PAS (physical address spaces) at runtime. + +Arm CCA adds two new security states for a total of four: root, realm, secure, and +non-secure. In addition to new security states, corresponding physical address +spaces have been added to control memory access for each state. The PAS access +allowed to each security state can be seen in the table below. + +.. list-table:: Security states and PAS access rights + :widths: 25 25 25 25 25 + :header-rows: 1 + + * - + - Root state + - Realm state + - Secure state + - Non-secure state + * - Root PAS + - yes + - no + - no + - no + * - Realm PAS + - yes + - yes + - no + - no + * - Secure PAS + - yes + - no + - yes + - no + * - Non-secure PAS + - yes + - yes + - yes + - yes + +The GPT can function as either a 1 level or 2 level lookup depending on how a +PAS region is configured. The first step is the level 0 table, each entry in the +level 0 table controls access to a relatively large region in memory (block +descriptor), and the entire region can belong to a single PAS when a one step +mapping is used, or a level 0 entry can link to a level 1 table where relatively +small regions (granules) of memory can be assigned to different PAS with a 2 +step mapping. The type of mapping used for each PAS is determined by the user +when setting up the configuration structure. + +Design Concepts and Interfaces +------------------------------ + +This section covers some important concepts and data structures used in the GPT +library. + +There are three main parameters that determine how the tables are organized and +function: the PPS (protected physical space) which is the total amount of +protected physical address space in the system, PGS (physical granule size) +which is how large each level 1 granule is, and L0GPTSZ (level 0 GPT size) which +determines how much physical memory is governed by each level 0 entry. A granule +is the smallest unit of memory that can be independently assigned to a PAS. + +L0GPTSZ is determined by the hardware and is read from the GPCCR_EL3 register. +PPS and PGS are passed into the APIs at runtime and can be determined in +whatever way is best for a given platform, either through some algorithm or hard +coded in the firmware. + +GPT setup is split into two parts: table creation and runtime initialization. In +the table creation step, a data structure containing information about the +desired PAS regions is passed into the library which validates the mappings, +creates the tables in memory, and enables granule protection checks. In the +runtime initialization step, the runtime firmware locates the existing tables in +memory using the GPT register configuration and saves important data to a +structure used by the granule transition service which will be covered more +below. + +In the reference implementation for FVP models, you can find an example of PAS +region definitions in the file ``include/plat/arm/common/arm_pas_def.h``. Table +creation API calls can be found in ``plat/arm/common/arm_bl2_setup.c`` and +runtime initialization API calls can be seen in +``plat/arm/common/arm_bl31_setup.c``. + +Defining PAS regions +~~~~~~~~~~~~~~~~~~~~ + +A ``pas_region_t`` structure is a way to represent a physical address space and +its attributes that can be used by the GPT library to initialize the tables. + +This structure is composed of the following: + +#. The base physical address +#. The region size +#. The desired attributes of this memory region (mapping type, PAS type) + +See the ``pas_region_t`` type in ``include/lib/gpt_rme/gpt_rme.h``. + +The programmer should provide the API with an array containing ``pas_region_t`` +structures, then the library will check the desired memory access layout for +validity and create tables to implement it. + +``pas_region_t`` is a public type, however it is recommended that the macros +``GPT_MAP_REGION_BLOCK`` and ``GPT_MAP_REGION_GRANULE`` be used to populate +these structures instead of doing it manually to reduce the risk of future +compatibility issues. These macros take the base physical address, region size, +and PAS type as arguments to generate the pas_region_t structure. As the names +imply, ``GPT_MAP_REGION_BLOCK`` creates a region using only L0 mapping while +``GPT_MAP_REGION_GRANULE`` creates a region using L0 and L1 mappings. + +Level 0 and Level 1 Tables +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The GPT initialization APIs require memory to be passed in for the tables to be +constructed, ``gpt_init_l0_tables`` takes a memory address and size for building +the level 0 tables and ``gpt_init_pas_l1_tables`` takes an address and size for +building the level 1 tables which are linked from level 0 descriptors. The +tables should have PAS type ``GPT_GPI_ROOT`` and a typical system might place +its level 0 table in SRAM and its level 1 table(s) in DRAM. + +Granule Transition Service +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Granule Transition Service allows memory mapped with GPT_MAP_REGION_GRANULE +ownership to be changed using SMC calls. Non-secure granules can be transitioned +to either realm or secure space, and realm and secure granules can be +transitioned back to non-secure. This library only allows memory mapped as +granules to be transitioned, memory mapped as blocks have their GPIs fixed after +table creation. + +Library APIs +------------ + +The public APIs and types can be found in ``include/lib/gpt_rme/gpt_rme.h`` and this +section is intended to provide additional details and clarifications. + +To create the GPTs and enable granule protection checks the APIs need to be +called in the correct order and at the correct time during the system boot +process. + +#. Firmware must enable the MMU. +#. Firmware must call ``gpt_init_l0_tables`` to initialize the level 0 tables to + a default state, that is, initializing all of the L0 descriptors to allow all + accesses to all memory. The PPS is provided to this function as an argument. +#. DDR discovery and initialization by the system, the discovered DDR region(s) + are then added to the L1 PAS regions to be initialized in the next step and + used by the GTSI at runtime. +#. Firmware must call ``gpt_init_pas_l1_tables`` with a pointer to an array of + ``pas_region_t`` structures containing the desired memory access layout. The + PGS is provided to this function as an argument. +#. Firmware must call ``gpt_enable`` to enable granule protection checks by + setting the correct register values. +#. In systems that make use of the granule transition service, runtime + firmware must call ``gpt_runtime_init`` to set up the data structures needed + by the GTSI to find the tables and transition granules between PAS types. + +API Constraints +~~~~~~~~~~~~~~~ + +The values allowed by the API for PPS and PGS are enumerated types +defined in the file ``include/lib/gpt_rme/gpt_rme.h``. + +Allowable values for PPS along with their corresponding size. + +* ``GPCCR_PPS_4GB`` (4GB protected space, 0x100000000 bytes) +* ``GPCCR_PPS_64GB`` (64GB protected space, 0x1000000000 bytes) +* ``GPCCR_PPS_1TB`` (1TB protected space, 0x10000000000 bytes) +* ``GPCCR_PPS_4TB`` (4TB protected space, 0x40000000000 bytes) +* ``GPCCR_PPS_16TB`` (16TB protected space, 0x100000000000 bytes) +* ``GPCCR_PPS_256TB`` (256TB protected space, 0x1000000000000 bytes) +* ``GPCCR_PPS_4PB`` (4PB protected space, 0x10000000000000 bytes) + +Allowable values for PGS along with their corresponding size. + +* ``GPCCR_PGS_4K`` (4KB granules, 0x1000 bytes) +* ``GPCCR_PGS_16K`` (16KB granules, 0x4000 bytes) +* ``GPCCR_PGS_64K`` (64KB granules, 0x10000 bytes) + +Allowable values for L0GPTSZ along with the corresponding size. + +* ``GPCCR_L0GPTSZ_30BITS`` (1GB regions, 0x40000000 bytes) +* ``GPCCR_L0GPTSZ_34BITS`` (16GB regions, 0x400000000 bytes) +* ``GPCCR_L0GPTSZ_36BITS`` (64GB regions, 0x1000000000 bytes) +* ``GPCCR_L0GPTSZ_39BITS`` (512GB regions, 0x8000000000 bytes) + +Note that the value of the PPS, PGS, and L0GPTSZ definitions is an encoded value +corresponding to the size, not the size itself. The decoded hex representations +of the sizes have been provided for convenience. + +The L0 table memory has some constraints that must be taken into account. + +* The L0 table must be aligned to either the table size or 4096 bytes, whichever + is greater. L0 table size is the total protected space (PPS) divided by the + size of each L0 region (L0GPTSZ) multiplied by the size of each L0 descriptor + (8 bytes). ((PPS / L0GPTSZ) * 8) +* The L0 memory size must be greater than or equal to the table size. +* The L0 memory must fall within a PAS of type GPT_GPI_ROOT. + +The L1 memory also has some constraints. + +* The L1 tables must be aligned to their size. The size of each L1 table is the + size of each L0 region (L0GPTSZ) divided by the granule size (PGS) divided by + the granules controlled in each byte (2). ((L0GPTSZ / PGS) / 2) +* There must be enough L1 memory supplied to build all requested L1 tables. +* The L1 memory must fall within a PAS of type GPT_GPI_ROOT. + +If an invalid combination of parameters is supplied, the APIs will print an +error message and return a negative value. The return values of APIs should be +checked to ensure successful configuration. + +Sample Calculation for L0 memory size and alignment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Let PPS=GPCCR_PPS_4GB and L0GPTSZ=GPCCR_L0GPTSZ_30BITS + +We can find the total L0 table size with ((PPS / L0GPTSZ) * 8) + +Substitute values to get this: ((0x100000000 / 0x40000000) * 8) + +And solve to get 32 bytes. In this case, 4096 is greater than 32, so the L0 +tables must be aligned to 4096 bytes. + +Sample calculation for L1 table size and alignment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Let PGS=GPCCR_PGS_4K and L0GPTSZ=GPCCR_L0GPTSZ_30BITS + +We can find the size of each L1 table with ((L0GPTSZ / PGS) / 2). + +Substitute values: ((0x40000000 / 0x1000) / 2) + +And solve to get 0x20000 bytes per L1 table. diff --git a/arm-trusted-firmware/docs/components/index.rst b/arm-trusted-firmware/docs/components/index.rst new file mode 100644 index 0000000..95fe42c --- /dev/null +++ b/arm-trusted-firmware/docs/components/index.rst @@ -0,0 +1,28 @@ +Components +========== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + spd/index + activity-monitors + arm-sip-service + debugfs-design + exception-handling + fconf/index + firmware-update + measured_boot/index + mpmm + platform-interrupt-controller-API + ras + romlib-design + sdei + secure-partition-manager + secure-partition-manager-mm + ffa-manifest-binding + xlat-tables-lib-v2-design + cot-binding + realm-management-extension + granule-protection-tables-design diff --git a/arm-trusted-firmware/docs/components/measured_boot/event_log.rst b/arm-trusted-firmware/docs/components/measured_boot/event_log.rst new file mode 100644 index 0000000..0881248 --- /dev/null +++ b/arm-trusted-firmware/docs/components/measured_boot/event_log.rst @@ -0,0 +1,35 @@ +DTB binding for Event Log properties +==================================== + +This document describes the device tree format of Event Log properties. +These properties are not related to a specific platform and can be queried +from common code. + +Dynamic configuration for Event Log +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Measured Boot driver expects a *tpm_event_log* node with the following field +in 'tb_fw_config', 'nt_fw_config' and 'tsp_fw_config' DTS files: + +- compatible [mandatory] + - value type: + - Must be the string "arm,tpm_event_log". + +Then a list of properties representing Event Log configuration, which +can be used by Measured Boot driver. Each property is named according +to the information it contains: + +- tpm_event_log_sm_addr [fvp_nt_fw_config.dts with OP-TEE] + - value type: + - Event Log base address in secure memory. + +Note. Currently OP-TEE does not support reading DTBs from Secure memory +and this property should be removed when this feature is supported. + +- tpm_event_log_addr [mandatory] + - value type: + - Event Log base address in non-secure memory. + +- tpm_event_log_size [mandatory] + - value type: + - Event Log size. diff --git a/arm-trusted-firmware/docs/components/measured_boot/index.rst b/arm-trusted-firmware/docs/components/measured_boot/index.rst new file mode 100644 index 0000000..e7f2634 --- /dev/null +++ b/arm-trusted-firmware/docs/components/measured_boot/index.rst @@ -0,0 +1,12 @@ +Measured Boot Driver (MBD) +========================== + +.. _measured-boot-document: + +Properties binding information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + event_log diff --git a/arm-trusted-firmware/docs/components/mpmm.rst b/arm-trusted-firmware/docs/components/mpmm.rst new file mode 100644 index 0000000..1b1c6d8 --- /dev/null +++ b/arm-trusted-firmware/docs/components/mpmm.rst @@ -0,0 +1,30 @@ +Maximum Power Mitigation Mechanism (MPMM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +|MPMM| is an optional microarchitectural power management mechanism supported by +some Arm Armv9-A cores, beginning with the Cortex-X2, Cortex-A710 and +Cortex-A510 cores. This mechanism detects and limits high-activity events to +assist in |SoC| processor power domain dynamic power budgeting and limit the +triggering of whole-rail (i.e. clock chopping) responses to overcurrent +conditions. + +|MPMM| is enabled on a per-core basis by the EL3 runtime firmware. The presence +of |MPMM| cannot be determined at runtime by the firmware, and therefore the +platform must expose this information through one of two possible mechanisms: + +- |FCONF|, controlled by the ``ENABLE_MPMM_FCONF`` build option. +- A platform implementation of the ``plat_mpmm_topology`` function (the + default). + +See :ref:`Maximum Power Mitigation Mechanism (MPMM) Bindings` for documentation +on the |FCONF| device tree bindings. + +.. warning:: + + |MPMM| exposes gear metrics through the auxiliary |AMU| counters. An + external power controller can use these metrics to budget SoC power by + limiting the number of cores that can execute higher-activity workloads or + switching to a different DVFS operating point. When this is the case, the + |AMU| counters that make up the |MPMM| gears must be enabled by the EL3 + runtime firmware - please see :ref:`Activity Monitor Auxiliary Counters` for + documentation on enabling auxiliary |AMU| counters. diff --git a/arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst b/arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst new file mode 100644 index 0000000..069c87b --- /dev/null +++ b/arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst @@ -0,0 +1,309 @@ +Platform Interrupt Controller API +================================= + +This document lists the optional platform interrupt controller API that +abstracts the runtime configuration and control of interrupt controller from the +generic code. The mandatory APIs are described in the +:ref:`Porting Guide `. + +Function: unsigned int plat_ic_get_running_priority(void); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This API should return the priority of the interrupt the PE is currently +servicing. This must be be called only after an interrupt has already been +acknowledged via ``plat_ic_acknowledge_interrupt``. + +In the case of Arm standard platforms using GIC, the *Running Priority Register* +is read to determine the priority of the interrupt. + +Function: int plat_ic_is_spi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Shared Peripheral Interrupt. Shared Peripheral Interrupts are typically +associated to system-wide peripherals, and these interrupts can target any PE in +the system. + +Function: int plat_ic_is_ppi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Private Peripheral Interrupt. Private Peripheral Interrupts are typically +associated with peripherals that are private to each PE. Interrupts from private +peripherals target to that PE only. + +Function: int plat_ic_is_sgi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Software Generated Interrupt. Software Generated Interrupts are raised by +explicit programming by software, and are typically used in inter-PE +communication. Secure SGIs are reserved for use by Secure world software. + +Function: unsigned int plat_ic_get_interrupt_active(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should return the *active* status of the interrupt ID specified by the +first parameter, ``id``. + +In case of Arm standard platforms using GIC, the implementation of the API reads +the GIC *Set Active Register* to read and return the active status of the +interrupt. + +Function: void plat_ic_enable_interrupt(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should enable the interrupt ID specified by the first parameter, +``id``. PEs in the system are expected to receive only enabled interrupts. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before enabling interrupt, and +then writes to GIC *Set Enable Register* to enable the interrupt. + +Function: void plat_ic_disable_interrupt(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should disable the interrupt ID specified by the first parameter, +``id``. PEs in the system are not expected to receive disabled interrupts. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to GIC *Clear Enable Register* to disable the interrupt, and inserts +barrier to make memory updates visible afterwards. + +Function: void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Return : void + +This API should set the priority of the interrupt specified by first parameter +``id`` to the value set by the second parameter ``priority``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to GIC *Priority Register* set interrupt priority. + +Function: int plat_ic_has_interrupt_type(unsigned int type); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should return whether the platform supports a given interrupt type. The +parameter ``type`` shall be one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1``, or +``INTR_TYPE_NS``. + +In case of Arm standard platforms using GICv3, the implementation of the API +returns ``1`` for all interrupt types. + +In case of Arm standard platforms using GICv2, the API always return ``1`` for +``INTR_TYPE_NS``. Return value for other types depends on the value of build +option ``GICV2_G0_FOR_EL3``: + +- For interrupt type ``INTR_TYPE_EL3``: + + - When ``GICV2_G0_FOR_EL3`` is ``0``, it returns ``0``, indicating no support + for EL3 interrupts. + + - When ``GICV2_G0_FOR_EL3`` is ``1``, it returns ``1``, indicating support for + EL3 interrupts. + +- For interrupt type ``INTR_TYPE_S_EL1``: + + - When ``GICV2_G0_FOR_EL3`` is ``0``, it returns ``1``, indicating support for + Secure EL1 interrupts. + + - When ``GICV2_G0_FOR_EL3`` is ``1``, it returns ``0``, indicating no support + for Secure EL1 interrupts. + +Function: void plat_ic_set_interrupt_type(unsigned int id, unsigned int type); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Return : void + +This API should set the interrupt specified by first parameter ``id`` to the +type specified by second parameter ``type``. The ``type`` parameter can be +one of: + +- ``INTR_TYPE_NS``: interrupt is meant to be consumed by the Non-secure world. + +- ``INTR_TYPE_S_EL1``: interrupt is meant to be consumed by Secure EL1. + +- ``INTR_TYPE_EL3``: interrupt is meant to be consumed by EL3. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Group Register* and *Group Modifier Register* (only GICv3) to +assign the interrupt to the right group. + +For GICv3: + +- ``INTR_TYPE_NS`` maps to Group 1 interrupt. + +- ``INTR_TYPE_S_EL1`` maps to Secure Group 1 interrupt. + +- ``INTR_TYPE_EL3`` maps to Secure Group 0 interrupt. + +For GICv2: + +- ``INTR_TYPE_NS`` maps to Group 1 interrupt. + +- When the build option ``GICV2_G0_FOR_EL3`` is set to ``0`` (the default), + ``INTR_TYPE_S_EL1`` maps to Group 0. Otherwise, ``INTR_TYPE_EL3`` maps to + Group 0 interrupt. + +Function: void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : u_register_t + Return : void + +This API should raise an EL3 SGI. The first parameter, ``sgi_num``, specifies +the ID of the SGI. The second parameter, ``target``, must be the MPIDR of the +target PE. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before raising SGI, then writes +to appropriate *SGI Register* in order to raise the EL3 SGI. + +Function: void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, u_register_t mpidr); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Argument : u_register_t + Return : void + +This API should set the routing mode of Share Peripheral Interrupt (SPI) +specified by first parameter ``id`` to that specified by the second parameter +``routing_mode``. + +The ``routing_mode`` parameter can be one of: + +- ``INTR_ROUTING_MODE_ANY`` means the interrupt can be routed to any PE in the + system. The ``mpidr`` parameter is ignored in this case. + +- ``INTR_ROUTING_MODE_PE`` means the interrupt is routed to the PE whose MPIDR + value is specified by the parameter ``mpidr``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Target Register* (GICv2) or *Route Register* (GICv3) to set +the routing. + +Function: void plat_ic_set_interrupt_pending(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should set the interrupt specified by first parameter ``id`` to +*Pending*. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before setting interrupt pending, +and writes to the GIC *Set Pending Register* to set the interrupt pending +status. + +Function: void plat_ic_clear_interrupt_pending(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should clear the *Pending* status of the interrupt specified by first +parameter ``id``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Clear Pending Register* to clear the interrupt pending +status, and inserts barrier to make memory updates visible afterwards. + +Function: unsigned int plat_ic_set_priority_mask(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should set the priority mask (first parameter) in the interrupt +controller such that only interrupts of higher priority than the supplied one +may be signalled to the PE. The API should return the current priority value +that it's overwriting. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts to order memory updates before updating mask, then writes to the GIC +*Priority Mask Register*, and make sure memory updates are visible before +potential trigger due to mask update. + +.. _plat_ic_get_interrupt_id: + +Function: unsigned int plat_ic_get_interrupt_id(unsigned int raw); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : unsigned int + +This API should extract and return the interrupt number from the raw value +obtained by the acknowledging the interrupt (read using +``plat_ic_acknowledge_interrupt()``). If the interrupt ID is invalid, this API +should return ``INTR_ID_UNAVAILABLE``. + +In case of Arm standard platforms using GIC, the implementation of the API +masks out the interrupt ID field from the acknowledged value from GIC. + +-------------- + +*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/ras.rst b/arm-trusted-firmware/docs/components/ras.rst new file mode 100644 index 0000000..02207d8 --- /dev/null +++ b/arm-trusted-firmware/docs/components/ras.rst @@ -0,0 +1,241 @@ +Reliability, Availability, and Serviceability (RAS) Extensions +============================================================== + +This document describes |TF-A| support for Arm Reliability, Availability, and +Serviceability (RAS) extensions. RAS is a mandatory extension for Armv8.2 and +later CPUs, and also an optional extension to the base Armv8.0 architecture. + +In conjunction with the |EHF|, support for RAS extension enables firmware-first +paradigm for handling platform errors: exceptions resulting from errors are +routed to and handled in EL3. Said errors are Synchronous External Abort (SEA), +Asynchronous External Abort (signalled as SErrors), Fault Handling and Error +Recovery interrupts. The |EHF| document mentions various :ref:`error handling +use-cases ` . + +For the description of Arm RAS extensions, Standard Error Records, and the +precise definition of RAS terminology, please refer to the Arm Architecture +Reference Manual. The rest of this document assumes familiarity with +architecture and terminology. + +Overview +-------- + +As mentioned above, the RAS support in |TF-A| enables routing to and handling of +exceptions resulting from platform errors in EL3. It allows the platform to +define an External Abort handler, and to register RAS nodes and interrupts. RAS +framework also provides `helpers`__ for accessing Standard Error Records as +introduced by the RAS extensions. + +.. __: `Standard Error Record helpers`_ + +The build option ``RAS_EXTENSION`` when set to ``1`` includes the RAS in run +time firmware; ``EL3_EXCEPTION_HANDLING`` and ``HANDLE_EA_EL3_FIRST`` must also +be set ``1``. ``RAS_TRAP_LOWER_EL_ERR_ACCESS`` controls the access to the RAS +error record registers from lower ELs. + +.. _ras-figure: + +.. image:: ../resources/diagrams/draw.io/ras.svg + +See more on `Engaging the RAS framework`_. + +Platform APIs +------------- + +The RAS framework allows the platform to define handlers for External Abort, +Uncontainable Errors, Double Fault, and errors rising from EL3 execution. Please +refer to :ref:`RAS Porting Guide `. + +Registering RAS error records +----------------------------- + +RAS nodes are components in the system capable of signalling errors to PEs +through one one of the notification mechanisms—SEAs, SErrors, or interrupts. RAS +nodes contain one or more error records, which are registers through which the +nodes advertise various properties of the signalled error. Arm recommends that +error records are implemented in the Standard Error Record format. The RAS +architecture allows for error records to be accessible via system or +memory-mapped registers. + +The platform should enumerate the error records providing for each of them: + +- A handler to probe error records for errors; +- When the probing identifies an error, a handler to handle it; +- For memory-mapped error record, its base address and size in KB; for a system + register-accessed record, the start index of the record and number of + continuous records from that index; +- Any node-specific auxiliary data. + +With this information supplied, when the run time firmware receives one of the +notification mechanisms, the RAS framework can iterate through and probe error +records for error, and invoke the appropriate handler to handle it. + +The RAS framework provides the macros to populate error record information. The +macros are versioned, and the latest version as of this writing is 1. These +macros create a structure of type ``struct err_record_info`` from its arguments, +which are later passed to probe and error handlers. + +For memory-mapped error records: + +.. code:: c + + ERR_RECORD_MEMMAP_V1(base_addr, size_num_k, probe, handler, aux) + +And, for system register ones: + +.. code:: c + + ERR_RECORD_SYSREG_V1(idx_start, num_idx, probe, handler, aux) + +The probe handler must have the following prototype: + +.. code:: c + + typedef int (*err_record_probe_t)(const struct err_record_info *info, + int *probe_data); + +The probe handler must return a non-zero value if an error was detected, or 0 +otherwise. The ``probe_data`` output parameter can be used to pass any useful +information resulting from probe to the error handler (see `below`__). For +example, it could return the index of the record. + +.. __: `Standard Error Record helpers`_ + +The error handler must have the following prototype: + +.. code:: c + + typedef int (*err_record_handler_t)(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data); + +The ``data`` constant parameter describes the various properties of the error, +including the reason for the error, exception syndrome, and also ``flags``, +``cookie``, and ``handle`` parameters from the :ref:`top-level exception handler +`. + +The platform is expected populate an array using the macros above, and register +the it with the RAS framework using the macro ``REGISTER_ERR_RECORD_INFO()``, +passing it the name of the array describing the records. Note that the macro +must be used in the same file where the array is defined. + +Standard Error Record helpers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The |TF-A| RAS framework provides probe handlers for Standard Error Records, for +both memory-mapped and System Register accesses: + +.. code:: c + + int ras_err_ser_probe_memmap(const struct err_record_info *info, + int *probe_data); + + int ras_err_ser_probe_sysreg(const struct err_record_info *info, + int *probe_data); + +When the platform enumerates error records, for those records in the Standard +Error Record format, these helpers maybe used instead of rolling out their own. +Both helpers above: + +- Return non-zero value when an error is detected in a Standard Error Record; +- Set ``probe_data`` to the index of the error record upon detecting an error. + +Registering RAS interrupts +-------------------------- + +RAS nodes can signal errors to the PE by raising Fault Handling and/or Error +Recovery interrupts. For the firmware-first handling paradigm for interrupts to +work, the platform must setup and register with |EHF|. See `Interaction with +Exception Handling Framework`_. + +For each RAS interrupt, the platform has to provide structure of type ``struct +ras_interrupt``: + +- Interrupt number; +- The associated error record information (pointer to the corresponding + ``struct err_record_info``); +- Optionally, a cookie. + +The platform is expected to define an array of ``struct ras_interrupt``, and +register it with the RAS framework using the macro +``REGISTER_RAS_INTERRUPTS()``, passing it the name of the array. Note that the +macro must be used in the same file where the array is defined. + +The array of ``struct ras_interrupt`` must be sorted in the increasing order of +interrupt number. This allows for fast look of handlers in order to service RAS +interrupts. + +Double-fault handling +--------------------- + +A Double Fault condition arises when an error is signalled to the PE while +handling of a previously signalled error is still underway. When a Double Fault +condition arises, the Arm RAS extensions only require for handler to perform +orderly shutdown of the system, as recovery may be impossible. + +The RAS extensions part of Armv8.4 introduced new architectural features to deal +with Double Fault conditions, specifically, the introduction of ``NMEA`` and +``EASE`` bits to ``SCR_EL3`` register. These were introduced to assist EL3 +software which runs part of its entry/exit routines with exceptions momentarily +masked—meaning, in such systems, External Aborts/SErrors are not immediately +handled when they occur, but only after the exceptions are unmasked again. + +|TF-A|, for legacy reasons, executes entire EL3 with all exceptions unmasked. +This means that all exceptions routed to EL3 are handled immediately. |TF-A| +thus is able to detect a Double Fault conditions in software, without needing +the intended advantages of Armv8.4 Double Fault architecture extensions. + +Double faults are fatal, and terminate at the platform double fault handler, and +doesn't return. + +Engaging the RAS framework +-------------------------- + +Enabling RAS support is a platform choice constructed from three distinct, but +related, build options: + +- ``RAS_EXTENSION=1`` includes the RAS framework in the run time firmware; + +- ``EL3_EXCEPTION_HANDLING=1`` enables handling of exceptions at EL3. See + `Interaction with Exception Handling Framework`_; + +- ``HANDLE_EA_EL3_FIRST=1`` enables routing of External Aborts and SErrors to + EL3. + +The RAS support in |TF-A| introduces a default implementation of +``plat_ea_handler``, the External Abort handler in EL3. When ``RAS_EXTENSION`` +is set to ``1``, it'll first call ``ras_ea_handler()`` function, which is the +top-level RAS exception handler. ``ras_ea_handler`` is responsible for iterating +to through platform-supplied error records, probe them, and when an error is +identified, look up and invoke the corresponding error handler. + +Note that, if the platform chooses to override the ``plat_ea_handler`` function +and intend to use the RAS framework, it must explicitly call +``ras_ea_handler()`` from within. + +Similarly, for RAS interrupts, the framework defines +``ras_interrupt_handler()``. The RAS framework arranges for it to be invoked +when a RAS interrupt taken at EL3. The function bisects the platform-supplied +sorted array of interrupts to look up the error record information associated +with the interrupt number. That error handler for that record is then invoked to +handle the error. + +Interaction with Exception Handling Framework +--------------------------------------------- + +As mentioned in earlier sections, RAS framework interacts with the |EHF| to +arbitrate handling of RAS exceptions with others that are routed to EL3. This +means that the platform must partition a :ref:`priority level ` for handling RAS exceptions. The platform must then define +the macro ``PLAT_RAS_PRI`` to the priority level used for RAS exceptions. +Platforms would typically want to allocate the highest secure priority for +RAS handling. + +Handling of both :ref:`interrupt ` and :ref:`non-interrupt +` exceptions follow the sequences outlined in the |EHF| +documentation. I.e., for interrupts, the priority management is implicit; but +for non-interrupt exceptions, they're explicit using :ref:`EHF APIs +`. + +-------------- + +*Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/realm-management-extension.rst b/arm-trusted-firmware/docs/components/realm-management-extension.rst new file mode 100644 index 0000000..5fa5140 --- /dev/null +++ b/arm-trusted-firmware/docs/components/realm-management-extension.rst @@ -0,0 +1,267 @@ + +Realm Management Extension (RME) +==================================== + +FEAT_RME (or RME for short) is an Armv9-A extension and is one component of the +`Arm Confidential Compute Architecture (Arm CCA)`_. TF-A supports RME starting +from version 2.6. This chapter discusses the changes to TF-A to support RME and +provides instructions on how to build and run TF-A with RME. + +RME support in TF-A +--------------------- + +The following diagram shows an Arm CCA software architecture with TF-A as the +EL3 firmware. In the Arm CCA architecture there are two additional security +states and address spaces: ``Root`` and ``Realm``. TF-A firmware runs in the +Root world. In the realm world, a Realm Management Monitor firmware (RMM) +manages the execution of Realm VMs and their interaction with the hypervisor. + +.. image:: ../resources/diagrams/arm-cca-software-arch.png + +RME is the hardware extension to support Arm CCA. To support RME, various +changes have been introduced to TF-A. We discuss those changes below. + +Changes to translation tables library +*************************************** +RME adds Root and Realm Physical address spaces. To support this, two new +memory type macros, ``MT_ROOT`` and ``MT_REALM``, have been added to the +:ref:`Translation (XLAT) Tables Library`. These macros are used to configure +memory regions as Root or Realm respectively. + +.. note:: + + Only version 2 of the translation tables library supports the new memory + types. + +Changes to context management +******************************* +A new CPU context for the Realm world has been added. The existing +:ref:`CPU context management API` can be used to manage Realm context. + +Boot flow changes +******************* +In a typical TF-A boot flow, BL2 runs at Secure-EL1. However when RME is +enabled, TF-A runs in the Root world at EL3. Therefore, the boot flow is +modified to run BL2 at EL3 when RME is enabled. In addition to this, a +Realm-world firmware (RMM) is loaded by BL2 in the Realm physical address +space. + +The boot flow when RME is enabled looks like the following: + +1. BL1 loads and executes BL2 at EL3 +2. BL2 loads images including RMM +3. BL2 transfers control to BL31 +4. BL31 initializes SPM (if SPM is enabled) +5. BL31 initializes RMM +6. BL31 transfers control to Normal-world software + +Granule Protection Tables (GPT) library +***************************************** +Isolation between the four physical address spaces is enforced by a process +called Granule Protection Check (GPC) performed by the MMU downstream any +address translation. GPC makes use of Granule Protection Table (GPT) in the +Root world that describes the physical address space assignment of every +page (granule). A GPT library that provides APIs to initialize GPTs and to +transition granules between different physical address spaces has been added. +More information about the GPT library can be found in the +:ref:`Granule Protection Tables Library` chapter. + +RMM Dispatcher (RMMD) +************************ +RMMD is a new standard runtime service that handles the switch to the Realm +world. It initializes the RMM and handles Realm Management Interface (RMI) +SMC calls from Non-secure and Realm worlds. + +Test Realm Payload (TRP) +************************* +TRP is a small test payload that runs at R-EL2 and implements a subset of +the Realm Management Interface (RMI) commands to primarily test EL3 firmware +and the interface between R-EL2 and EL3. When building TF-A with RME enabled, +if a path to an RMM image is not provided, TF-A builds the TRP by default +and uses it as RMM image. + +Building and running TF-A with RME +------------------------------------ + +This section describes how you can build and run TF-A with RME enabled. +We assume you have all the :ref:`Prerequisites` to build TF-A. + +To enable RME, you need to set the ENABLE_RME build flag when building +TF-A. Currently, this feature is only supported for the FVP platform. + +The following instructions show you how to build and run TF-A with RME +for two scenarios: TF-A with TF-A Tests, and four-world execution with +Hafnium and TF-A Tests. The instructions assume you have already obtained +TF-A. You can use the following command to clone TF-A. + +.. code:: shell + + git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git + +To run the tests, you need an FVP model. Please use the :ref:`latest version +` of *FVP_Base_RevC-2xAEMvA* model. + +.. note:: + + ENABLE_RME build option is currently experimental. + +Building TF-A with TF-A Tests +******************************************** +Use the following instructions to build TF-A with `TF-A Tests`_ as the +non-secure payload (BL33). + +**1. Obtain and build TF-A Tests** + +.. code:: shell + + git clone https://git.trustedfirmware.org/TF-A/tf-a-tests.git + cd tf-a-tests + make CROSS_COMPILE=aarch64-none-elf- PLAT=fvp DEBUG=1 + +This produces a TF-A Tests binary (*tftf.bin*) in the *build/fvp/debug* directory. + +**2. Build TF-A** + +.. code:: shell + + cd trusted-firmware-a + make CROSS_COMPILE=aarch64-none-elf- \ + PLAT=fvp \ + ENABLE_RME=1 \ + FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \ + DEBUG=1 \ + BL33= \ + all fip + +This produces *bl1.bin* and *fip.bin* binaries in the *build/fvp/debug* directory. +The above command also builds TRP. The TRP binary is packaged in *fip.bin*. + +Four-world execution with Hafnium and TF-A Tests +**************************************************** +Four-world execution involves software components at each security state: root, +secure, realm and non-secure. This section describes how to build TF-A +with four-world support. We use TF-A as the root firmware, `Hafnium`_ as the +secure component, TRP as the realm-world firmware and TF-A Tests as the +non-secure payload. + +Before building TF-A, you first need to build the other software components. +You can find instructions on how to get and build TF-A Tests above. + +**1. Obtain and build Hafnium** + +.. code:: shell + + git clone --recurse-submodules https://git.trustedfirmware.org/hafnium/hafnium.git + cd hafnium + # Use the default prebuilt LLVM/clang toolchain + PATH=$PWD/prebuilts/linux-x64/clang/bin:$PWD/prebuilts/linux-x64/dtc:$PATH + make PROJECT=reference + +The Hafnium binary should be located at +*out/reference/secure_aem_v8a_fvp_clang/hafnium.bin* + +**2. Build TF-A** + +Build TF-A with RME as well as SPM enabled. + +.. code:: shell + + make CROSS_COMPILE=aarch64-none-elf- \ + PLAT=fvp \ + ENABLE_RME=1 \ + FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \ + SPD=spmd \ + SPMD_SPM_AT_SEL2=1 \ + BRANCH_PROTECTION=1 \ + CTX_INCLUDE_PAUTH_REGS=1 \ + DEBUG=1 \ + SP_LAYOUT_FILE=/build/fvp/debug/sp_layout.json> \ + BL32= \ + BL33= \ + all fip + +Running the tests +********************* +Use the following command to run the tests on FVP. TF-A Tests should boot +and run the default tests including RME tests. + +.. code:: shell + + FVP_Base_RevC-2xAEMvA \ + -C bp.flashloader0.fname= \ + -C bp.secureflashloader.fname= \ + -C bp.refcounter.non_arch_start_at_default=1 \ + -C bp.refcounter.use_real_time=0 \ + -C bp.ve_sysregs.exit_on_shutdown=1 \ + -C cache_state_modelled=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster0.PA_SIZE=48 \ + -C cluster0.ecv_support_level=2 \ + -C cluster0.gicv3.cpuintf-mmap-access-level=2 \ + -C cluster0.gicv3.without-DS-support=1 \ + -C cluster0.gicv4.mask-virtual-interrupt=1 \ + -C cluster0.has_arm_v8-6=1 \ + -C cluster0.has_branch_target_exception=1 \ + -C cluster0.has_rme=1 \ + -C cluster0.has_rndr=1 \ + -C cluster0.has_amu=1 \ + -C cluster0.has_v8_7_pmu_extension=2 \ + -C cluster0.max_32bit_el=-1 \ + -C cluster0.restriction_on_speculative_execution=2 \ + -C cluster0.restriction_on_speculative_execution_aarch32=2 \ + -C cluster1.NUM_CORES=4 \ + -C cluster1.PA_SIZE=48 \ + -C cluster1.ecv_support_level=2 \ + -C cluster1.gicv3.cpuintf-mmap-access-level=2 \ + -C cluster1.gicv3.without-DS-support=1 \ + -C cluster1.gicv4.mask-virtual-interrupt=1 \ + -C cluster1.has_arm_v8-6=1 \ + -C cluster1.has_branch_target_exception=1 \ + -C cluster1.has_rme=1 \ + -C cluster1.has_rndr=1 \ + -C cluster1.has_amu=1 \ + -C cluster1.has_v8_7_pmu_extension=2 \ + -C cluster1.max_32bit_el=-1 \ + -C cluster1.restriction_on_speculative_execution=2 \ + -C cluster1.restriction_on_speculative_execution_aarch32=2 \ + -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B \ + -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0475 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 \ + -C bp.pl011_uart0.out_file=uart0.log \ + -C bp.pl011_uart1.out_file=uart1.log \ + -C bp.pl011_uart2.out_file=uart2.log \ + -C pctl.startup=0.0.0.0 \ + -Q 1000 \ + "$@" + +The bottom of the output from *uart0* should look something like the following. + +.. code-block:: shell + + ... + + > Test suite 'FF-A Interrupt' + Passed + > Test suite 'SMMUv3 tests' + Passed + > Test suite 'PMU Leakage' + Passed + > Test suite 'DebugFS' + Passed + > Test suite 'Realm payload tests' + Passed + > Test suite 'Invalid memory access' + Passed + ... + + +.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture +.. _Arm Architecture Models website: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models +.. _TF-A Tests: https://trustedfirmware-a-tests.readthedocs.io/en/latest +.. _Hafnium: https://www.trustedfirmware.org/projects/hafnium diff --git a/arm-trusted-firmware/docs/components/romlib-design.rst b/arm-trusted-firmware/docs/components/romlib-design.rst new file mode 100644 index 0000000..d34b3cc --- /dev/null +++ b/arm-trusted-firmware/docs/components/romlib-design.rst @@ -0,0 +1,155 @@ +Library at ROM +============== + +This document provides an overview of the "library at ROM" implementation in +Trusted Firmware-A (TF-A). + +Introduction +~~~~~~~~~~~~ + +The "library at ROM" feature allows platforms to build a library of functions to +be placed in ROM. This reduces SRAM usage by utilising the available space in +ROM. The "library at ROM" contains a jump table with the list of functions that +are placed in ROM. The capabilities of the "library at ROM" are: + +1. Functions can be from one or several libraries. + +2. Functions can be patched after they have been programmed into ROM. + +3. Platform-specific libraries can be placed in ROM. + +4. Functions can be accessed by one or more BL images. + +Index file +~~~~~~~~~~ + +.. image:: ../resources/diagrams/romlib_design.png + :width: 600 + +Library at ROM is described by an index file with the list of functions to be +placed in ROM. The index file is platform specific and its format is: + +:: + + lib function [patch] + + lib -- Name of the library the function belongs to + function -- Name of the function to be placed in library at ROM + [patch] -- Option to patch the function + +It is also possible to insert reserved spaces in the list by using the keyword +"reserved" rather than the "lib" and "function" names as shown below: + +:: + + reserved + +The reserved spaces can be used to add more functions in the future without +affecting the order and location of functions already existing in the jump +table. Also, for additional flexibility and modularity, the index file can +include other index files. + +For an index file example, refer to ``lib/romlib/jmptbl.i``. + +Wrapper functions +~~~~~~~~~~~~~~~~~ + +.. image:: ../resources/diagrams/romlib_wrapper.png + :width: 600 + +When invoking a function of the "library at ROM", the calling sequence is as +follows: + +BL image --> wrapper function --> jump table entry --> library at ROM + +The index file is used to create a jump table which is placed in ROM. Then, the +wrappers refer to the jump table to call the "library at ROM" functions. The +wrappers essentially contain a branch instruction to the jump table entry +corresponding to the original function. Finally, the original function in the BL +image(s) is replaced with the wrapper function. + +The "library at ROM" contains a necessary init function that initialises the +global variables defined by the functions inside "library at ROM". + +Script +~~~~~~ + +There is a ``romlib_generate.py`` Python script that generates the necessary +files for the "library at ROM" to work. It implements multiple functions: + +1. ``romlib_generate.py gentbl [args]`` - Generates the jump table by parsing + the index file. + +2. ``romlib_generator.py genvar [args]`` - Generates the jump table global + variable (**not** the jump table itself) with the absolute address in ROM. + This global variable is, basically, a pointer to the jump table. + +3. ``romlib_generator.py genwrappers [args]`` - 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``. + +4. ``romlib_generator.py pre [args]`` - Preprocesses the index file which means + it resolves all the include commands in the file recursively. It can also + generate a dependency file of the included index files which can be directly + used in makefiles. + +Each ``romlib_generate.py`` function has its own manual which is accessible by +runing ``romlib_generator.py [function] --help``. + +``romlib_generate.py`` requires Python 3 environment. + + +Patching of functions in library at ROM +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``romlib_generator.py genwrappers`` does not generate wrappers for the +entries in the index file that contain the keyword ``patch``. Thus, it allows +calling the function from the actual library by breaking the link to the +"library at ROM" version of this function. + +The calling sequence for a patched function is as follows: + +BL image --> function + +Memory impact +~~~~~~~~~~~~~ + +Using library at ROM will modify the memory layout of the BL images: + +- The ROM library needs a page aligned RAM section to hold the RW data. This + section is defined by the ROMLIB_RW_BASE and ROMLIB_RW_END macros. + On Arm platforms a section of 1 page (0x1000) is allocated at the top of SRAM. + This will have for effect to shift down all the BL images by 1 page. + +- Depending on the functions moved to the ROM library, the size of the BL images + will be reduced. + For example: moving MbedTLS function into the ROM library reduces BL1 and + BL2, but not BL31. + +- This change in BL images size can be taken into consideration to optimize the + memory layout when defining the BLx_BASE macros. + +Build library at ROM +~~~~~~~~~~~~~~~~~~~~~ + +The environment variable ``CROSS_COMPILE`` must be set appropriately. Refer to +:ref:`Performing an Initial Build` for more information about setting this +variable. + +In the below example the usage of ROMLIB together with mbed TLS is demonstrated +to showcase the benefits of library at ROM - it's not mandatory. + +.. code:: shell + + make PLAT=fvp \ + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33= \ + USE_ROMLIB=1 \ + all fip + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/sdei.rst b/arm-trusted-firmware/docs/components/sdei.rst new file mode 100644 index 0000000..60259c8 --- /dev/null +++ b/arm-trusted-firmware/docs/components/sdei.rst @@ -0,0 +1,369 @@ +SDEI: Software Delegated Exception Interface +============================================ + +This document provides an overview of the SDEI dispatcher implementation in +Trusted Firmware-A (TF-A). + +Introduction +------------ + +Software Delegated Exception Interface (|SDEI|) is an Arm specification for +Non-secure world to register handlers with firmware to receive notifications +about system events. Firmware will first receive the system events by way of +asynchronous exceptions and, in response, arranges for the registered handler to +execute in the Non-secure EL. + +Normal world software that interacts with the SDEI dispatcher (makes SDEI +requests and receives notifications) is referred to as the *SDEI Client*. A +client receives the event notification at the registered handler even when it +was executing with exceptions masked. The list of SDEI events available to the +client are specific to the platform [#std-event]_. See also `Determining client +EL`_. + +.. _general SDEI dispatch: + +The following figure depicts a general sequence involving SDEI client executing +at EL2 and an event dispatch resulting from the triggering of a bound interrupt. +A commentary is provided below: + +.. uml:: ../resources/diagrams/plantuml/sdei_general.puml + +As part of initialisation, the SDEI client binds a Non-secure interrupt [1], and +the SDEI dispatcher returns a platform dynamic event number [2]. The client then +registers a handler for that event [3], enables the event [5], and unmasks all +events on the current PE [7]. This sequence is typical of an SDEI client, but it +may involve additional SDEI calls. + +At a later point in time, when the bound interrupt triggers [9], it's trapped to +EL3. The interrupt is handed over to the SDEI dispatcher, which then arranges to +execute the registered handler [10]. The client terminates its execution with +``SDEI_EVENT_COMPLETE`` [11], following which the dispatcher resumes the +original EL2 execution [13]. Note that the SDEI interrupt remains active until +the client handler completes, at which point EL3 does EOI [12]. + +Other than events bound to interrupts, as depicted in the sequence above, SDEI +events can be explicitly dispatched in response to other exceptions, for +example, upon receiving an *SError* or *Synchronous External Abort*. See +`Explicit dispatch of events`_. + +The remainder of this document only discusses the design and implementation of +SDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI +specification, the interfaces, and their requirements. + +Defining events +--------------- + +A platform choosing to include the SDEI dispatcher must also define the events +available on the platform, along with their attributes. + +The platform is expected to provide two arrays of event descriptors: one for +private events, and another for shared events. The SDEI dispatcher provides +``SDEI_PRIVATE_EVENT()`` and ``SDEI_SHARED_EVENT()`` macros to populate the +event descriptors. Both macros take 3 arguments: + +- The event number: this must be a positive 32-bit integer. + +- For an event that has a backing interrupt, the interrupt number the event is + bound to: + + - If it's not applicable to an event, this shall be left as ``0``. + + - If the event is dynamic, this should be specified as ``SDEI_DYN_IRQ``. + +- A bit map of `Event flags`_. + +To define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This +macro takes only one parameter: an SGI number to signal other PEs. + +To define an event that's meant to be explicitly dispatched (i.e., not as a +result of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()`` +should be used. It accepts two parameters: + +- The event number (as above); + +- Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described + below. + +Once the event descriptor arrays are defined, they should be exported to the +SDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers +to the private and shared event descriptor arrays, respectively. Note that the +``REGISTER_SDEI_MAP()`` macro must be used in the same file where the arrays are +defined. + +Regarding event descriptors: + +- For Event 0: + + - There must be exactly one descriptor in the private array, and none in the + shared array. + + - The event should be defined using ``SDEI_DEFINE_EVENT_0()``. + + - Must be bound to a Secure SGI on the platform. + +- Explicit events should only be used in the private array. + +- Statically bound shared and private interrupts must be bound to shared and + private interrupts on the platform, respectively. See the section on + `Configuration within Exception Handling Framework`_. + +- Both arrays should be one-dimensional. The ``REGISTER_SDEI_MAP()`` macro + takes care of replicating private events for each PE on the platform. + +- Both arrays must be sorted in the increasing order of event number. + +The SDEI specification doesn't have provisions for discovery of available events +on the platform. The list of events made available to the client, along with +their semantics, have to be communicated out of band; for example, through +Device Trees or firmware configuration tables. + +See also `Event definition example`_. + +Event flags +~~~~~~~~~~~ + +Event flags describe the properties of the event. They are bit maps that can be +``OR``\ ed to form parameters to macros that define events (see +`Defining events`_). + +- ``SDEI_MAPF_DYNAMIC``: Marks the event as dynamic. Dynamic events can be + bound to (or released from) any Non-secure interrupt at runtime via the + ``SDEI_INTERRUPT_BIND`` and ``SDEI_INTERRUPT_RELEASE`` calls. + +- ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt. + These events cannot be re-bound at runtime. + +- ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is + the default priority. + +- ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority. + +Event definition example +------------------------ + +.. code:: c + + static sdei_ev_map_t plat_private_sdei[] = { + /* Event 0 definition */ + SDEI_DEFINE_EVENT_0(8), + + /* PPI */ + SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND), + + /* Dynamic private events */ + SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + + /* Events for explicit dispatch */ + SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL); + SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL); + }; + + /* Shared event mappings */ + static sdei_ev_map_t plat_shared_sdei[] = { + SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC), + + /* Dynamic shared events */ + SDEI_SHARED_EVENT(3000, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_SHARED_EVENT(3001, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + }; + + /* Export SDEI events */ + REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei); + +Configuration within Exception Handling Framework +------------------------------------------------- + +The SDEI dispatcher functions alongside the Exception Handling Framework. This +means that the platform must assign priorities to both Normal and Critical SDEI +interrupts for the platform: + +- Install priority descriptors for Normal and Critical SDEI interrupts. + +- For those interrupts that are statically bound (i.e. events defined as having + the ``SDEI_MAPF_BOUND`` property), enumerate their properties for the GIC + driver to configure interrupts accordingly. + + The interrupts must be configured to target EL3. This means that they should + be configured as *Group 0*. Additionally, on GICv2 systems, the build option + ``GICV2_G0_FOR_EL3`` must be set to ``1``. + +See also :ref:`porting_guide_sdei_requirements`. + +Determining client EL +--------------------- + +The SDEI specification requires that the *physical* SDEI client executes in the +highest Non-secure EL implemented on the system. This means that the dispatcher +will only allow SDEI calls to be made from: + +- EL2, if EL2 is implemented. The Hypervisor is expected to implement a + *virtual* SDEI dispatcher to support SDEI clients in Guest Operating Systems + executing in Non-secure EL1. + +- Non-secure EL1, if EL2 is not implemented or disabled. + +See the function ``sdei_client_el()`` in ``sdei_private.h``. + +.. _explicit-dispatch-of-events: + +Explicit dispatch of events +--------------------------- + +Typically, an SDEI event dispatch is caused by the PE receiving interrupts that +are bound to an SDEI event. However, there are cases where the Secure world +requires dispatch of an SDEI event as a direct or indirect result of a past +activity, such as receiving a Secure interrupt or an exception. + +The SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for +this purpose. The API has the following signature: + +.. code:: c + + int sdei_dispatch_event(int ev_num); + +The parameter ``ev_num`` is the event number to dispatch. The API returns ``0`` +on success, or ``-1`` on failure. + +The following figure depicts a scenario involving explicit dispatch of SDEI +event. A commentary is provided below: + +.. uml:: ../resources/diagrams/plantuml/sdei_explicit_dispatch.puml + +As part of initialisation, the SDEI client registers a handler for a platform +event [1], enables the event [3], and unmasks the current PE [5]. Note that, +unlike in `general SDEI dispatch`_, this doesn't involve interrupt binding, as +bound or dynamic events can't be explicitly dispatched (see the section below). + +At a later point in time, a critical event [#critical-event]_ is trapped into +EL3 [7]. EL3 performs a first-level triage of the event, and a RAS component +assumes further handling [8]. The dispatch completes, but intends to involve +Non-secure world in further handling, and therefore decides to explicitly +dispatch an event [10] (which the client had already registered for [1]). The +rest of the sequence is similar to that in the `general SDEI dispatch`_: the +requested event is dispatched to the client (assuming all the conditions are +met), and when the handler completes, the preempted execution resumes. + +Conditions for event dispatch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All of the following requirements must be met for the API to return ``0`` and +event to be dispatched: + +- SDEI events must be unmasked on the PE. I.e. the client must have called + ``PE_UNMASK`` beforehand. + +- Event 0 can't be dispatched. + +- The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro + described above. + +- The event must be private to the PE. + +- The event must have been registered for and enabled. + +- A dispatch for the same event must not be outstanding. I.e. it hasn't already + been dispatched and is yet to be completed. + +- The priority of the event (either Critical or Normal, as configured by the + platform at build-time) shouldn't cause priority inversion. This means: + + - If it's of Normal priority, neither Normal nor Critical priority dispatch + must be outstanding on the PE. + + - If it's of a Critical priority, no Critical priority dispatch must be + outstanding on the PE. + +Further, the caller should be aware of the following assumptions made by the +dispatcher: + +- The caller of the API is a component running in EL3; for example, a RAS + driver. + +- The requested dispatch will be permitted by the Exception Handling Framework. + I.e. the caller must make sure that the requested dispatch has sufficient + priority so as not to cause priority level inversion within Exception + Handling Framework. + +- The caller must be prepared for the SDEI dispatcher to restore the Non-secure + context, and mark that the active context. + +- The call will block until the SDEI client completes the event (i.e. when the + client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``). + +- The caller must be prepared for this API to return failure and handle + accordingly. + +Porting requirements +-------------------- + +The porting requirements of the SDEI dispatcher are outlined in the +:ref:`Porting Guide `. + +Note on writing SDEI event handlers +----------------------------------- + +*This section pertains to SDEI event handlers in general, not just when using +the TF-A SDEI dispatcher.* + +The SDEI specification requires that event handlers preserve the contents of all +registers except ``x0`` to ``x17``. This has significance if event handler is +written in C: compilers typically adjust the stack frame at the beginning and +end of C functions. For example, AArch64 GCC typically produces the following +function prologue and epilogue: + +:: + + c_event_handler: + stp x29, x30, [sp,#-32]! + mov x29, sp + + ... + + bl ... + + ... + + ldp x29, x30, [sp],#32 + ret + +The register ``x29`` is used as frame pointer in the prologue. Because neither a +valid ``SDEI_EVENT_COMPLETE`` nor ``SDEI_EVENT_COMPLETE_AND_RESUME`` calls +return to the handler, the epilogue never gets executed, and registers ``x29`` +and ``x30`` (in the case above) are inadvertently corrupted. This violates the +SDEI specification, and the normal execution thereafter will result in +unexpected behaviour. + +To work this around, it's advised that the top-level event handlers are +implemented in assembly, following a similar pattern as below: + +:: + + asm_event_handler: + /* Save link register whilst maintaining stack alignment */ + stp xzr, x30, [sp, #-16]! + bl c_event_handler + + /* Restore link register */ + ldp xzr, x30, [sp], #16 + + /* Complete call */ + ldr x0, =SDEI_EVENT_COMPLETE + smc #0 + b . + +-------------- + +*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.* + +.. rubric:: Footnotes + +.. [#std-event] Except event 0, which is defined by the SDEI specification as a + standard event. + +.. [#critical-event] Examples of critical events are *SError*, *Synchronous + External Abort*, *Fault Handling interrupt* or *Error + Recovery interrupt* from one of RAS nodes in the system. + +.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _Software Delegated Exception Interface: `SDEI specification`_ diff --git a/arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst b/arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst new file mode 100644 index 0000000..4cdb96c --- /dev/null +++ b/arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst @@ -0,0 +1,834 @@ +Secure Partition Manager (MM) +***************************** + +Foreword +======== + +Two implementations of a Secure Partition Manager co-exist in the TF-A codebase: + +- SPM based on the FF-A specification (:ref:`Secure Partition Manager`). +- SPM based on the MM interface. + +Both implementations differ in their architectures and only one can be selected +at build time. + +This document describes the latter implementation where the Secure Partition Manager +resides at EL3 and management services run from isolated Secure Partitions at S-EL0. +The communication protocol is established through the Management Mode (MM) interface. + +Background +========== + +In some market segments that primarily deal with client-side devices like mobile +phones, tablets, STBs and embedded devices, a Trusted OS instantiates trusted +applications to provide security services like DRM, secure payment and +authentication. The Global Platform TEE Client API specification defines the API +used by Non-secure world applications to access these services. A Trusted OS +fulfils the requirements of a security service as described above. + +Management services are typically implemented at the highest level of privilege +in the system, i.e. EL3 in Trusted Firmware-A (TF-A). The service requirements are +fulfilled by the execution environment provided by TF-A. + +The following diagram illustrates the corresponding software stack: + +|Image 1| + +In other market segments that primarily deal with server-side devices (e.g. data +centres and enterprise servers) the secure software stack typically does not +include a Global Platform Trusted OS. Security functions are accessed through +other interfaces (e.g. ACPI TCG TPM interface, UEFI runtime variable service). + +Placement of management and security functions with diverse requirements in a +privileged Exception Level (i.e. EL3 or S-EL1) makes security auditing of +firmware more difficult and does not allow isolation of unrelated services from +each other either. + +Introduction +============ + +A **Secure Partition** is a software execution environment instantiated in +S-EL0 that can be used to implement simple management and security services. +Since S-EL0 is an unprivileged Exception Level, a Secure Partition relies on +privileged firmware (i.e. TF-A) to be granted access to system and processor +resources. Essentially, it is a software sandbox in the Secure world that runs +under the control of privileged software, provides one or more services and +accesses the following system resources: + +- Memory and device regions in the system address map. + +- PE system registers. + +- A range of synchronous exceptions (e.g. SMC function identifiers). + +Note that currently TF-A only supports handling one Secure Partition. + +A Secure Partition enables TF-A to implement only the essential secure +services in EL3 and instantiate the rest in a partition in S-EL0. +Furthermore, multiple Secure Partitions can be used to isolate unrelated +services from each other. + +The following diagram illustrates the place of a Secure Partition in a typical +Armv8-A software stack. A single or multiple Secure Partitions provide secure +services to software components in the Non-secure world and other Secure +Partitions. + +|Image 2| + +The TF-A build system is responsible for including the Secure Partition image +in the FIP. During boot, BL2 includes support to authenticate and load the +Secure Partition image. A BL31 component called **Secure Partition Manager +(SPM)** is responsible for managing the partition. This is semantically +similar to a hypervisor managing a virtual machine. + +The SPM is responsible for the following actions during boot: + +- Allocate resources requested by the Secure Partition. + +- Perform architectural and system setup required by the Secure Partition to + fulfil a service request. + +- Implement a standard interface that is used for initialising a Secure + Partition. + +The SPM is responsible for the following actions during runtime: + +- Implement a standard interface that is used by a Secure Partition to fulfil + service requests. + +- Implement a standard interface that is used by the Non-secure world for + accessing the services exported by a Secure Partition. A service can be + invoked through a SMC. + +Alternatively, a partition can be viewed as a thread of execution running under +the control of the SPM. Hence common programming concepts described below are +applicable to a partition. + +Description +=========== + +The previous section introduced some general aspects of the software +architecture of a Secure Partition. This section describes the specific choices +made in the current implementation of this software architecture. Subsequent +revisions of the implementation will include a richer set of features that +enable a more flexible architecture. + +Building TF-A with Secure Partition support +------------------------------------------- + +SPM is supported on the Arm FVP exclusively at the moment. The current +implementation supports inclusion of only a single Secure Partition in which a +service always runs to completion (e.g. the requested services cannot be +preempted to give control back to the Normal world). + +It is not currently possible for BL31 to integrate SPM support and a Secure +Payload Dispatcher (SPD) at the same time; they are mutually exclusive. In the +SPM bootflow, a Secure Partition image executing at S-EL0 replaces the Secure +Payload image executing at S-EL1 (e.g. a Trusted OS). Both are referred to as +BL32. + +A working prototype of a SP has been implemented by re-purposing the EDK2 code +and tools, leveraging the concept of the *Standalone Management Mode (MM)* in +the UEFI specification (see the PI v1.6 Volume 4: Management Mode Core +Interface). This will be referred to as the *Standalone MM Secure Partition* in +the rest of this document. + +To enable SPM support in TF-A, the source code must be compiled with the build +flag ``SPM_MM=1``, along with ``EL3_EXCEPTION_HANDLING=1`` and ``ENABLE_SVE_FOR_NS=0``. +On Arm platforms the build option ``ARM_BL31_IN_DRAM`` must be set to 1. Also, the +location of the binary that contains the BL32 image +(``BL32=path/to/image.bin``) must be specified. + +First, build the Standalone MM Secure Partition. To build it, refer to the +`instructions in the EDK2 repository`_. + +Then build TF-A with SPM support and include the Standalone MM Secure Partition +image in the FIP: + +.. code:: shell + + BL32=path/to/standalone/mm/sp BL33=path/to/bl33.bin \ + make PLAT=fvp SPM_MM=1 EL3_EXCEPTION_HANDLING=1 ENABLE_SVE_FOR_NS=0 ARM_BL31_IN_DRAM=1 all fip + +Describing Secure Partition resources +------------------------------------- + +TF-A exports a porting interface that enables a platform to specify the system +resources required by the Secure Partition. Some instructions are given below. +However, this interface is under development and it may change as new features +are implemented. + +- A Secure Partition is considered a BL32 image, so the same defines that apply + to BL32 images apply to a Secure Partition: ``BL32_BASE`` and ``BL32_LIMIT``. + +- The following defines are needed to allocate space for the translation tables + used by the Secure Partition: ``PLAT_SP_IMAGE_MMAP_REGIONS`` and + ``PLAT_SP_IMAGE_MAX_XLAT_TABLES``. + +- The functions ``plat_get_secure_partition_mmap()`` and + ``plat_get_secure_partition_boot_info()`` have to be implemented. The file + ``plat/arm/board/fvp/fvp_common.c`` can be used as an example. It uses the + defines in ``include/plat/arm/common/arm_spm_def.h``. + + - ``plat_get_secure_partition_mmap()`` returns an array of mmap regions that + describe the memory regions that the SPM needs to allocate for a Secure + Partition. + + - ``plat_get_secure_partition_boot_info()`` returns a + ``spm_mm_boot_info_t`` struct that is populated by the platform + with information about the memory map of the Secure Partition. + +For an example of all the changes in context, you may refer to commit +``e29efeb1b4``, in which the port for FVP was introduced. + +Accessing Secure Partition services +----------------------------------- + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) describes SMCs as a conduit for +accessing services implemented in the Secure world. The ``MM_COMMUNICATE`` +interface defined in the `Management Mode Interface Specification`_ (*Arm DEN +0060A*) is used to invoke a Secure Partition service as a Fast Call. + +The mechanism used to identify a service within the partition depends on the +service implementation. It is assumed that the caller of the service will be +able to discover this mechanism through standard platform discovery mechanisms +like ACPI and Device Trees. For example, *Volume 4: Platform Initialisation +Specification v1.6. Management Mode Core Interface* specifies that a GUID is +used to identify a management mode service. A client populates the GUID in the +``EFI_MM_COMMUNICATE_HEADER``. The header is populated in the communication +buffer shared with the Secure Partition. + +A Fast Call appears to be atomic from the perspective of the caller and returns +when the requested operation has completed. A service invoked through the +``MM_COMMUNICATE`` SMC will run to completion in the partition on a given CPU. +The SPM is responsible for guaranteeing this behaviour. This means that there +can only be a single outstanding Fast Call in a partition on a given CPU. + +Exchanging data with the Secure Partition +----------------------------------------- + +The exchange of data between the Non-secure world and the partition takes place +through a shared memory region. The location of data in the shared memory area +is passed as a parameter to the ``MM_COMMUNICATE`` SMC. The shared memory area +is statically allocated by the SPM and is expected to be either implicitly known +to the Non-secure world or discovered through a platform discovery mechanism +e.g. ACPI table or device tree. It is possible for the Non-secure world to +exchange data with a partition only if it has been populated in this shared +memory area. The shared memory area is implemented as per the guidelines +specified in Section 3.2.3 of the `Management Mode Interface Specification`_ +(*Arm DEN 0060A*). + +The format of data structures used to encapsulate data in the shared memory is +agreed between the Non-secure world and the Secure Partition. For example, in +the `Management Mode Interface specification`_ (*Arm DEN 0060A*), Section 4 +describes that the communication buffer shared between the Non-secure world and +the Management Mode (MM) in the Secure world must be of the type +``EFI_MM_COMMUNICATE_HEADER``. This data structure is defined in *Volume 4: +Platform Initialisation Specification v1.6. Management Mode Core Interface*. +Any caller of a MM service will have to use the ``EFI_MM_COMMUNICATE_HEADER`` +data structure. + +Runtime model of the Secure Partition +===================================== + +This section describes how the Secure Partition interfaces with the SPM. + +Interface with SPM +------------------ + +In order to instantiate one or more secure services in the Secure Partition in +S-EL0, the SPM should define the following types of interfaces: + +- Interfaces that enable access to privileged operations from S-EL0. These + operations typically require access to system resources that are either shared + amongst multiple software components in the Secure world or cannot be directly + accessed from an unprivileged Exception Level. + +- Interfaces that establish the control path between the SPM and the Secure + Partition. + +This section describes the APIs currently exported by the SPM that enable a +Secure Partition to initialise itself and export its services in S-EL0. These +interfaces are not accessible from the Non-secure world. + +Conduit +^^^^^^^ + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) specification describes the SMC +and HVC conduits for accessing firmware services and their availability +depending on the implemented Exception levels. In S-EL0, the Supervisor Call +exception (SVC) is the only architectural mechanism available for unprivileged +software to make a request for an operation implemented in privileged software. +Hence, the SVC conduit must be used by the Secure Partition to access interfaces +implemented by the SPM. + +A SVC causes an exception to be taken to S-EL1. TF-A assumes ownership of S-EL1 +and installs a simple exception vector table in S-EL1 that relays a SVC request +from a Secure Partition as a SMC request to the SPM in EL3. Upon servicing the +SMC request, Trusted Firmware-A returns control directly to S-EL0 through an +ERET instruction. + +Calling conventions +^^^^^^^^^^^^^^^^^^^ + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) specification describes the +32-bit and 64-bit calling conventions for the SMC and HVC conduits. The SVC +conduit introduces the concept of SVC32 and SVC64 calling conventions. The SVC32 +and SVC64 calling conventions are equivalent to the 32-bit (SMC32) and the +64-bit (SMC64) calling conventions respectively. + +Communication initiated by SPM +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A service request is initiated from the SPM through an exception return +instruction (ERET) to S-EL0. Later, the Secure Partition issues an SVC +instruction to signal completion of the request. Some example use cases are +given below: + +- A request to initialise the Secure Partition during system boot. + +- A request to handle a runtime service request. + +Communication initiated by Secure Partition +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A request is initiated from the Secure Partition by executing a SVC instruction. +An ERET instruction is used by TF-A to return to S-EL0 with the result of the +request. + +For instance, a request to perform privileged operations on behalf of a +partition (e.g. management of memory attributes in the translation tables for +the Secure EL1&0 translation regime). + +Interfaces +^^^^^^^^^^ + +The current implementation reserves function IDs for Fast Calls in the Standard +Secure Service calls range (see `SMC Calling Convention`_ (*Arm DEN 0028B*) +specification) for each API exported by the SPM. This section defines the +function prototypes for each function ID. The function IDs specify whether one +or both of the SVC32 and SVC64 calling conventions can be used to invoke the +corresponding interface. + +Secure Partition Event Management +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Secure Partition provides an Event Management interface that is used by the +SPM to delegate service requests to the Secure Partition. The interface also +allows the Secure Partition to: + +- Register with the SPM a service that it provides. +- Indicate completion of a service request delegated by the SPM + +Miscellaneous interfaces +------------------------ + +``SPM_MM_VERSION_AARCH32`` +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Returns the version of the interface exported by SPM. + +- Parameters + + - **uint32** - Function ID + + - SVC32 Version: **0x84000060** + +- Return parameters + + - **int32** - Status + + On success, the format of the value is as follows: + + - Bit [31]: Must be 0 + - Bits [30:16]: Major Version. Must be 0 for this revision of the SPM + interface. + - Bits [15:0]: Minor Version. Must be 1 for this revision of the SPM + interface. + + On error, the format of the value is as follows: + + - ``NOT_SUPPORTED``: SPM interface is not supported or not available for the + client. + +- Usage + + This function returns the version of the Secure Partition Manager + implementation. The major version is 0 and the minor version is 1. The version + number is a 31-bit unsigned integer, with the upper 15 bits denoting the major + revision, and the lower 16 bits denoting the minor revision. The following + rules apply to the version numbering: + + - Different major revision values indicate possibly incompatible functions. + + - For two revisions, A and B, for which the major revision values are + identical, if the minor revision value of revision B is greater than the + minor revision value of revision A, then every function in revision A must + work in a compatible way with revision B. However, it is possible for + revision B to have a higher function count than revision A. + +- Implementation responsibilities + + If this function returns a valid version number, all the functions that are + described subsequently must be implemented, unless it is explicitly stated + that a function is optional. + +See `Error Codes`_ for integer values that are associated with each return +code. + +Secure Partition Initialisation +------------------------------- + +The SPM is responsible for initialising the architectural execution context to +enable initialisation of a service in S-EL0. The responsibilities of the SPM are +listed below. At the end of initialisation, the partition issues a +``MM_SP_EVENT_COMPLETE_AARCH64`` call (described later) to signal readiness for +handling requests for services implemented by the Secure Partition. The +initialisation event is executed as a Fast Call. + +Entry point invocation +^^^^^^^^^^^^^^^^^^^^^^ + +The entry point for service requests that should be handled as Fast Calls is +used as the target of the ERET instruction to start initialisation of the Secure +Partition. + +Architectural Setup +^^^^^^^^^^^^^^^^^^^ + +At cold boot, system registers accessible from S-EL0 will be in their reset +state unless otherwise specified. The SPM will perform the following +architectural setup to enable execution in S-EL0 + +MMU setup +^^^^^^^^^ + +The platform port of a Secure Partition specifies to the SPM a list of regions +that it needs access to and their attributes. The SPM validates this resource +description and initialises the Secure EL1&0 translation regime as follows. + +1. Device regions are mapped with nGnRE attributes and Execute Never + instruction access permissions. + +2. Code memory regions are mapped with RO data and Executable instruction access + permissions. + +3. Read Only data memory regions are mapped with RO data and Execute Never + instruction access permissions. + +4. Read Write data memory regions are mapped with RW data and Execute Never + instruction access permissions. + +5. If the resource description does not explicitly describe the type of memory + regions then all memory regions will be marked with Code memory region + attributes. + +6. The ``UXN`` and ``PXN`` bits are set for regions that are not executable by + S-EL0 or S-EL1. + +System Register Setup +^^^^^^^^^^^^^^^^^^^^^ + +System registers that influence software execution in S-EL0 are setup by the SPM +as follows: + +1. ``SCTLR_EL1`` + + - ``UCI=1`` + - ``EOE=0`` + - ``WXN=1`` + - ``nTWE=1`` + - ``nTWI=1`` + - ``UCT=1`` + - ``DZE=1`` + - ``I=1`` + - ``UMA=0`` + - ``SA0=1`` + - ``C=1`` + - ``A=1`` + - ``M=1`` + +2. ``CPACR_EL1`` + + - ``FPEN=b'11`` + +3. ``PSTATE`` + + - ``D,A,I,F=1`` + - ``CurrentEL=0`` (EL0) + - ``SpSel=0`` (Thread mode) + - ``NRW=0`` (AArch64) + +General Purpose Register Setup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +SPM will invoke the entry point of a service by executing an ERET instruction. +This transition into S-EL0 is special since it is not in response to a previous +request through a SVC instruction. This is the first entry into S-EL0. The +general purpose register usage at the time of entry will be as specified in the +"Return State" column of Table 3-1 in Section 3.1 "Register use in AArch64 SMC +calls" of the `SMC Calling Convention`_ (*Arm DEN 0028B*) specification. In +addition, certain other restrictions will be applied as described below. + +1. ``SP_EL0`` + + A non-zero value will indicate that the SPM has initialised the stack pointer + for the current CPU. + + The value will be 0 otherwise. + +2. ``X4-X30`` + + The values of these registers will be 0. + +3. ``X0-X3`` + + Parameters passed by the SPM. + + - ``X0``: Virtual address of a buffer shared between EL3 and S-EL0. The + buffer will be mapped in the Secure EL1&0 translation regime with read-only + memory attributes described earlier. + + - ``X1``: Size of the buffer in bytes. + + - ``X2``: Cookie value (*IMPLEMENTATION DEFINED*). + + - ``X3``: Cookie value (*IMPLEMENTATION DEFINED*). + +Runtime Event Delegation +------------------------ + +The SPM receives requests for Secure Partition services through a synchronous +invocation (i.e. a SMC from the Non-secure world). These requests are delegated +to the partition by programming a return from the last +``MM_SP_EVENT_COMPLETE_AARCH64`` call received from the partition. The last call +was made to signal either completion of Secure Partition initialisation or +completion of a partition service request. + +``MM_SP_EVENT_COMPLETE_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Signal completion of the last SP service request. + +- Parameters + + - **uint32** - Function ID + + - SVC64 Version: **0xC4000061** + + - **int32** - Event Status Code + + Zero or a positive value indicates that the event was handled successfully. + The values depend upon the original event that was delegated to the Secure + partition. They are described as follows. + + - ``SUCCESS`` : Used to indicate that the Secure Partition was initialised + or a runtime request was handled successfully. + + - Any other value greater than 0 is used to pass a specific Event Status + code in response to a runtime event. + + A negative value indicates an error. The values of Event Status code depend + on the original event. + +- Return parameters + + - **int32** - Event ID/Return Code + + Zero or a positive value specifies the unique ID of the event being + delegated to the partition by the SPM. + + In the current implementation, this parameter contains the function ID of + the ``MM_COMMUNICATE`` SMC. This value indicates to the partition that an + event has been delegated to it in response to an ``MM_COMMUNICATE`` request + from the Non-secure world. + + A negative value indicates an error. The format of the value is as follows: + + - ``NOT_SUPPORTED``: Function was called from the Non-secure world. + + See `Error Codes`_ for integer values that are associated with each return + code. + + - **uint32** - Event Context Address + + Address of a buffer shared between the SPM and Secure Partition to pass + event specific information. The format of the data populated in the buffer + is implementation defined. + + The buffer is mapped in the Secure EL1&0 translation regime with read-only + memory attributes described earlier. + + For the SVC64 version, this parameter is a 64-bit Virtual Address (VA). + + For the SVC32 version, this parameter is a 32-bit Virtual Address (VA). + + - **uint32** - Event context size + + Size of the memory starting at Event Address. + + - **uint32/uint64** - Event Cookie + + This is an optional parameter. If unused its value is SBZ. + +- Usage + + This function signals to the SPM that the handling of the last event delegated + to a partition has completed. The partition is ready to handle its next event. + A return from this function is in response to the next event that will be + delegated to the partition. The return parameters describe the next event. + +- Caller responsibilities + + A Secure Partition must only call ``MM_SP_EVENT_COMPLETE_AARCH64`` to signal + completion of a request that was delegated to it by the SPM. + +- Callee responsibilities + + When the SPM receives this call from a Secure Partition, the corresponding + syndrome information can be used to return control through an ERET + instruction, to the instruction immediately after the call in the Secure + Partition context. This syndrome information comprises of general purpose and + system register values when the call was made. + + The SPM must save this syndrome information and use it to delegate the next + event to the Secure Partition. The return parameters of this interface must + specify the properties of the event and be populated in ``X0-X3/W0-W3`` + registers. + +Secure Partition Memory Management +---------------------------------- + +A Secure Partition executes at S-EL0, which is an unprivileged Exception Level. +The SPM is responsible for enabling access to regions of memory in the system +address map from a Secure Partition. This is done by mapping these regions in +the Secure EL1&0 Translation regime with appropriate memory attributes. +Attributes refer to memory type, permission, cacheability and shareability +attributes used in the Translation tables. The definitions of these attributes +and their usage can be found in the `Armv8-A ARM`_ (*Arm DDI 0487*). + +All memory required by the Secure Partition is allocated upfront in the SPM, +even before handing over to the Secure Partition for the first time. The initial +access permissions of the memory regions are statically provided by the platform +port and should allow the Secure Partition to run its initialisation code. + +However, they might not suit the final needs of the Secure Partition because its +final memory layout might not be known until the Secure Partition initialises +itself. As the Secure Partition initialises its runtime environment it might, +for example, load dynamically some modules. For instance, a Secure Partition +could implement a loader for a standard executable file format (e.g. an PE-COFF +loader for loading executable files at runtime). These executable files will be +a part of the Secure Partition image. The location of various sections in an +executable file and their permission attributes (e.g. read-write data, read-only +data and code) will be known only when the file is loaded into memory. + +In this case, the Secure Partition needs a way to change the access permissions +of its memory regions. The SPM provides this feature through the +``MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64`` SVC interface. This interface is +available to the Secure Partition during a specific time window: from the first +entry into the Secure Partition up to the first ``SP_EVENT_COMPLETE`` call that +signals the Secure Partition has finished its initialisation. Once the +initialisation is complete, the SPM does not allow changes to the memory +attributes. + +This section describes the standard SVC interface that is implemented by the SPM +to determine and change permission attributes of memory regions that belong to a +Secure Partition. + +``MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Request the permission attributes of a memory region from S-EL0. + +- Parameters + + - **uint32** Function ID + + - SVC64 Version: **0xC4000064** + + - **uint64** Base Address + + This parameter is a 64-bit Virtual Address (VA). + + There are no alignment restrictions on the Base Address. The permission + attributes of the translation granule it lies in are returned. + +- Return parameters + + - **int32** - Memory Attributes/Return Code + + On success the format of the Return Code is as follows: + + - Bits[1:0] : Data access permission + + - b'00 : No access + - b'01 : Read-Write access + - b'10 : Reserved + - b'11 : Read-only access + + - Bit[2]: Instruction access permission + + - b'0 : Executable + - b'1 : Non-executable + + - Bit[30:3] : Reserved. SBZ. + + - Bit[31] : Must be 0 + + On failure the following error codes are returned: + + - ``INVALID_PARAMETERS``: The Secure Partition is not allowed to access the + memory region the Base Address lies in. + + - ``NOT_SUPPORTED`` : The SPM does not support retrieval of attributes of + any memory page that is accessible by the Secure Partition, or the + function was called from the Non-secure world. Also returned if it is + used after ``MM_SP_EVENT_COMPLETE_AARCH64``. + + See `Error Codes`_ for integer values that are associated with each return + code. + +- Usage + + This function is used to request the permission attributes for S-EL0 on a + memory region accessible from a Secure Partition. The size of the memory + region is equal to the Translation Granule size used in the Secure EL1&0 + translation regime. Requests to retrieve other memory region attributes are + not currently supported. + +- Caller responsibilities + + The caller must obtain the Translation Granule Size of the Secure EL1&0 + translation regime from the SPM through an implementation defined method. + +- Callee responsibilities + + The SPM must not return the memory access controls for a page of memory that + is not accessible from a Secure Partition. + +``MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Set the permission attributes of a memory region from S-EL0. + +- Parameters + + - **uint32** - Function ID + + - SVC64 Version: **0xC4000065** + + - **uint64** - Base Address + + This parameter is a 64-bit Virtual Address (VA). + + The alignment of the Base Address must be greater than or equal to the size + of the Translation Granule Size used in the Secure EL1&0 translation + regime. + + - **uint32** - Page count + + Number of pages starting from the Base Address whose memory attributes + should be changed. The page size is equal to the Translation Granule Size. + + - **uint32** - Memory Access Controls + + - Bits[1:0] : Data access permission + + - b'00 : No access + - b'01 : Read-Write access + - b'10 : Reserved + - b'11 : Read-only access + + - Bit[2] : Instruction access permission + + - b'0 : Executable + - b'1 : Non-executable + + - Bits[31:3] : Reserved. SBZ. + + A combination of attributes that mark the region with RW and Executable + permissions is prohibited. A request to mark a device memory region with + Executable permissions is prohibited. + +- Return parameters + + - **int32** - Return Code + + - ``SUCCESS``: The Memory Access Controls were changed successfully. + + - ``DENIED``: The SPM is servicing a request to change the attributes of a + memory region that overlaps with the region specified in this request. + + - ``INVALID_PARAMETER``: An invalid combination of Memory Access Controls + has been specified. The Base Address is not correctly aligned. The Secure + Partition is not allowed to access part or all of the memory region + specified in the call. + + - ``NO_MEMORY``: The SPM does not have memory resources to change the + attributes of the memory region in the translation tables. + + - ``NOT_SUPPORTED``: The SPM does not permit change of attributes of any + memory region that is accessible by the Secure Partition. Function was + called from the Non-secure world. Also returned if it is used after + ``MM_SP_EVENT_COMPLETE_AARCH64``. + + See `Error Codes`_ for integer values that are associated with each return + code. + +- Usage + + This function is used to change the permission attributes for S-EL0 on a + memory region accessible from a Secure Partition. The size of the memory + region is equal to the Translation Granule size used in the Secure EL1&0 + translation regime. Requests to change other memory region attributes are not + currently supported. + + This function is only available at boot time. This interface is revoked after + the Secure Partition sends the first ``MM_SP_EVENT_COMPLETE_AARCH64`` to + signal that it is initialised and ready to receive run-time requests. + +- Caller responsibilities + + The caller must obtain the Translation Granule Size of the Secure EL1&0 + translation regime from the SPM through an implementation defined method. + +- Callee responsibilities + + The SPM must preserve the original memory access controls of the region of + memory in case of an unsuccessful call.  The SPM must preserve the consistency + of the S-EL1 translation regime if this function is called on different PEs + concurrently and the memory regions specified overlap. + +Error Codes +----------- + +.. csv-table:: + :header: "Name", "Value" + + ``SUCCESS``,0 + ``NOT_SUPPORTED``,-1 + ``INVALID_PARAMETER``,-2 + ``DENIED``,-3 + ``NO_MEMORY``,-5 + ``NOT_PRESENT``,-7 + +-------------- + +*Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.* + +.. _Armv8-A ARM: https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile +.. _instructions in the EDK2 repository: https://github.com/tianocore/edk2-staging/blob/AArch64StandaloneMm/HowtoBuild.MD +.. _Management Mode Interface Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0060a/DEN0060A_ARM_MM_Interface_Specification.pdf +.. _SDEI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest + +.. |Image 1| image:: ../resources/diagrams/secure_sw_stack_tos.png +.. |Image 2| image:: ../resources/diagrams/secure_sw_stack_sp.png diff --git a/arm-trusted-firmware/docs/components/secure-partition-manager.rst b/arm-trusted-firmware/docs/components/secure-partition-manager.rst new file mode 100644 index 0000000..af298e3 --- /dev/null +++ b/arm-trusted-firmware/docs/components/secure-partition-manager.rst @@ -0,0 +1,1291 @@ +Secure Partition Manager +************************ + +.. contents:: + +Acronyms +======== + ++--------+--------------------------------------+ +| CoT | Chain of Trust | ++--------+--------------------------------------+ +| DMA | Direct Memory Access | ++--------+--------------------------------------+ +| DTB | Device Tree Blob | ++--------+--------------------------------------+ +| DTS | Device Tree Source | ++--------+--------------------------------------+ +| EC | Execution Context | ++--------+--------------------------------------+ +| FIP | Firmware Image Package | ++--------+--------------------------------------+ +| FF-A | Firmware Framework for Arm A-profile | ++--------+--------------------------------------+ +| IPA | Intermediate Physical Address | ++--------+--------------------------------------+ +| NWd | Normal World | ++--------+--------------------------------------+ +| ODM | Original Design Manufacturer | ++--------+--------------------------------------+ +| OEM | Original Equipment Manufacturer | ++--------+--------------------------------------+ +| PA | Physical Address | ++--------+--------------------------------------+ +| PE | Processing Element | ++--------+--------------------------------------+ +| PM | Power Management | ++--------+--------------------------------------+ +| PVM | Primary VM | ++--------+--------------------------------------+ +| SMMU | System Memory Management Unit | ++--------+--------------------------------------+ +| SP | Secure Partition | ++--------+--------------------------------------+ +| SPD | Secure Payload Dispatcher | ++--------+--------------------------------------+ +| SPM | Secure Partition Manager | ++--------+--------------------------------------+ +| SPMC | SPM Core | ++--------+--------------------------------------+ +| SPMD | SPM Dispatcher | ++--------+--------------------------------------+ +| SiP | Silicon Provider | ++--------+--------------------------------------+ +| SWd | Secure World | ++--------+--------------------------------------+ +| TLV | Tag-Length-Value | ++--------+--------------------------------------+ +| TOS | Trusted Operating System | ++--------+--------------------------------------+ +| VM | Virtual Machine | ++--------+--------------------------------------+ + +Foreword +======== + +Two implementations of a Secure Partition Manager co-exist in the TF-A codebase: + +- SPM based on the FF-A specification `[1]`_. +- SPM based on the MM interface to communicate with an S-EL0 partition `[2]`_. + +Both implementations differ in their architectures and only one can be selected +at build time. + +This document: + +- describes the FF-A implementation where the Secure Partition Manager + resides at EL3 and S-EL2 (or EL3 and S-EL1). +- is not an architecture specification and it might provide assumptions + on sections mandated as implementation-defined in the specification. +- covers the implications to TF-A used as a bootloader, and Hafnium + used as a reference code base for an S-EL2 secure firmware on + platforms implementing the FEAT_SEL2 (formerly Armv8.4 Secure EL2) + architecture extension. + +Terminology +----------- + +- The term Hypervisor refers to the NS-EL2 component managing Virtual Machines + (or partitions) in the normal world. +- The term SPMC refers to the S-EL2 component managing secure partitions in + the secure world when the FEAT_SEL2 architecture extension is implemented. +- Alternatively, SPMC can refer to an S-EL1 component, itself being a secure + partition and implementing the FF-A ABI on platforms not implementing the + FEAT_SEL2 architecture extension. +- The term VM refers to a normal world Virtual Machine managed by an Hypervisor. +- The term SP refers to a secure world "Virtual Machine" managed by an SPMC. + +Support for legacy platforms +---------------------------- + +In the implementation, the SPM is split into SPMD and SPMC components. +The SPMD is located at EL3 and mainly relays FF-A messages from +NWd (Hypervisor or OS kernel) to SPMC located either at S-EL1 or S-EL2. + +Hence TF-A supports both cases where the SPMC is located either at: + +- S-EL1 supporting platforms not implementing the FEAT_SEL2 architecture + extension. The SPMD relays the FF-A protocol from EL3 to S-EL1. +- or S-EL2 supporting platforms implementing the FEAT_SEL2 architecture + extension. The SPMD relays the FF-A protocol from EL3 to S-EL2. + +The same TF-A SPMD component is used to support both configurations. +The SPMC exception level is a build time choice. + +Sample reference stack +====================== + +The following diagram illustrates a possible configuration when the +FEAT_SEL2 architecture extension is implemented, showing the SPMD +and SPMC, one or multiple secure partitions, with an optional +Hypervisor: + +.. image:: ../resources/diagrams/ff-a-spm-sel2.png + +TF-A build options +================== + +This section explains the TF-A build options involved in building with +support for an FF-A based SPM where the SPMD is located at EL3 and the +SPMC located at S-EL1 or S-EL2: + +- **SPD=spmd**: this option selects the SPMD component to relay the FF-A + protocol from NWd to SWd back and forth. It is not possible to + enable another Secure Payload Dispatcher when this option is chosen. +- **SPMD_SPM_AT_SEL2**: this option adjusts the SPMC exception + level to being S-EL1 or S-EL2. It defaults to enabled (value 1) when + SPD=spmd is chosen. +- **CTX_INCLUDE_EL2_REGS**: this option permits saving (resp. + restoring) the EL2 system register context before entering (resp. + after leaving) the SPMC. It is mandatorily enabled when + ``SPMD_SPM_AT_SEL2`` is enabled. The context save/restore routine + and exhaustive list of registers is visible at `[4]`_. +- **SP_LAYOUT_FILE**: this option specifies a text description file + providing paths to SP binary images and manifests in DTS format + (see `Describing secure partitions`_). It + is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple + secure partitions are to be loaded on behalf of the SPMC. + ++---------------+----------------------+------------------+ +| | CTX_INCLUDE_EL2_REGS | SPMD_SPM_AT_SEL2 | ++---------------+----------------------+------------------+ +| SPMC at S-EL1 | 0 | 0 | ++---------------+----------------------+------------------+ +| SPMC at S-EL2 | 1 | 1 (default when | +| | | SPD=spmd) | ++---------------+----------------------+------------------+ + +Other combinations of such build options either break the build or are not +supported. + +Notes: + +- Only Arm's FVP platform is supported to use with the TF-A reference software + stack. +- The reference software stack uses FEAT_PAuth (formerly Armv8.3-PAuth) and + FEAT_BTI (formerly Armv8.5-BTI) architecture extensions by default at EL3 + and S-EL2. +- The ``CTX_INCLUDE_EL2_REGS`` option provides the generic support for + barely saving/restoring EL2 registers from an Arm arch perspective. As such + it is decoupled from the ``SPD=spmd`` option. +- BL32 option is re-purposed to specify the SPMC image. It can specify either + the Hafnium binary path (built for the secure world) or the path to a TEE + binary implementing FF-A interfaces. +- BL33 option can specify the TFTF binary or a normal world loader + such as U-Boot or the UEFI framework. + +Sample TF-A build command line when SPMC is located at S-EL1 +(e.g. when the FEAT_EL2 architecture extension is not implemented): + +.. code:: shell + + make \ + CROSS_COMPILE=aarch64-none-elf- \ + SPD=spmd \ + SPMD_SPM_AT_SEL2=0 \ + BL32= \ + BL33= \ + PLAT=fvp \ + all fip + +Sample TF-A build command line for a FEAT_SEL2 enabled system where the SPMC is +located at S-EL2: + +.. code:: shell + + make \ + CROSS_COMPILE=aarch64-none-elf- \ + PLAT=fvp \ + SPD=spmd \ + CTX_INCLUDE_EL2_REGS=1 \ + ARM_ARCH_MINOR=5 \ + BRANCH_PROTECTION=1 \ + CTX_INCLUDE_PAUTH_REGS=1 \ + BL32= \ + BL33= \ + SP_LAYOUT_FILE=sp_layout.json \ + all fip + +Same as above with enabling secure boot in addition: + +.. code:: shell + + make \ + CROSS_COMPILE=aarch64-none-elf- \ + PLAT=fvp \ + SPD=spmd \ + CTX_INCLUDE_EL2_REGS=1 \ + ARM_ARCH_MINOR=5 \ + BRANCH_PROTECTION=1 \ + CTX_INCLUDE_PAUTH_REGS=1 \ + BL32= \ + BL33= \ + SP_LAYOUT_FILE=sp_layout.json \ + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 \ + COT=dualroot \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + GENERATE_COT=1 \ + all fip + +FVP model invocation +==================== + +The FVP command line needs the following options to exercise the S-EL2 SPMC: + ++---------------------------------------------------+------------------------------------+ +| - cluster0.has_arm_v8-5=1 | Implements FEAT_SEL2, FEAT_PAuth, | +| - cluster1.has_arm_v8-5=1 | and FEAT_BTI. | ++---------------------------------------------------+------------------------------------+ +| - pci.pci_smmuv3.mmu.SMMU_AIDR=2 | Parameters required for the | +| - pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B | SMMUv3.2 modeling. | +| - pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 | | +| - pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 | | +| - pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 | | +| - pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 | | +| - pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 | | +| - pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 | | ++---------------------------------------------------+------------------------------------+ +| - cluster0.has_branch_target_exception=1 | Implements FEAT_BTI. | +| - cluster1.has_branch_target_exception=1 | | ++---------------------------------------------------+------------------------------------+ +| - cluster0.restriction_on_speculative_execution=2 | Required by the EL2 context | +| - cluster1.restriction_on_speculative_execution=2 | save/restore routine. | ++---------------------------------------------------+------------------------------------+ + +Sample FVP command line invocation: + +.. code:: shell + + /FVP_Base_RevC-2xAEMv8A -C pctl.startup=0.0.0.0 + -C cluster0.NUM_CORES=4 -C cluster1.NUM_CORES=4 -C bp.secure_memory=1 \ + -C bp.secureflashloader.fname=trusted-firmware-a/build/fvp/debug/bl1.bin \ + -C bp.flashloader0.fname=trusted-firmware-a/build/fvp/debug/fip.bin \ + -C bp.pl011_uart0.out_file=fvp-uart0.log -C bp.pl011_uart1.out_file=fvp-uart1.log \ + -C bp.pl011_uart2.out_file=fvp-uart2.log \ + -C cluster0.has_arm_v8-5=1 -C cluster1.has_arm_v8-5=1 -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 \ + -C cluster0.has_branch_target_exception=1 \ + -C cluster1.has_branch_target_exception=1 \ + -C cluster0.restriction_on_speculative_execution=2 \ + -C cluster1.restriction_on_speculative_execution=2 + +Boot process +============ + +Loading Hafnium and secure partitions in the secure world +--------------------------------------------------------- + +TF-A BL2 is the bootlader for the SPMC and SPs in the secure world. + +SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.). +Thus they are supplied as distinct signed entities within the FIP flash +image. The FIP image itself is not signed hence this provides the ability +to upgrade SPs in the field. + +Booting through TF-A +-------------------- + +SP manifests +~~~~~~~~~~~~ + +An SP manifest describes SP attributes as defined in `[1]`_ +(partition manifest at virtual FF-A instance) in DTS format. It is +represented as a single file associated with the SP. A sample is +provided by `[5]`_. A binding document is provided by `[6]`_. + +Secure Partition packages +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Secure partitions are bundled as independent package files consisting +of: + +- a header +- a DTB +- an image payload + +The header starts with a magic value and offset values to SP DTB and +image payload. Each SP package is loaded independently by BL2 loader +and verified for authenticity and integrity. + +The SP package identified by its UUID (matching FF-A uuid property) is +inserted as a single entry into the FIP at end of the TF-A build flow +as shown: + +.. code:: shell + + Trusted Boot Firmware BL2: offset=0x1F0, size=0x8AE1, cmdline="--tb-fw" + EL3 Runtime Firmware BL31: offset=0x8CD1, size=0x13000, cmdline="--soc-fw" + Secure Payload BL32 (Trusted OS): offset=0x1BCD1, size=0x15270, cmdline="--tos-fw" + Non-Trusted Firmware BL33: offset=0x30F41, size=0x92E0, cmdline="--nt-fw" + HW_CONFIG: offset=0x3A221, size=0x2348, cmdline="--hw-config" + TB_FW_CONFIG: offset=0x3C569, size=0x37A, cmdline="--tb-fw-config" + SOC_FW_CONFIG: offset=0x3C8E3, size=0x48, cmdline="--soc-fw-config" + TOS_FW_CONFIG: offset=0x3C92B, size=0x427, cmdline="--tos-fw-config" + NT_FW_CONFIG: offset=0x3CD52, size=0x48, cmdline="--nt-fw-config" + B4B5671E-4A90-4FE1-B81F-FB13DAE1DACB: offset=0x3CD9A, size=0xC168, cmdline="--blob" + D1582309-F023-47B9-827C-4464F5578FC8: offset=0x48F02, size=0xC168, cmdline="--blob" + +.. uml:: ../resources/diagrams/plantuml/fip-secure-partitions.puml + +Describing secure partitions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A json-formatted description file is passed to the build flow specifying paths +to the SP binary image and associated DTS partition manifest file. The latter +is processed by the dtc compiler to generate a DTB fed into the SP package. +This file also specifies the SP owner (as an optional field) identifying the +signing domain in case of dual root CoT. +The SP owner can either be the silicon or the platform provider. The +corresponding "owner" field value can either take the value of "SiP" or "Plat". +In absence of "owner" field, it defaults to "SiP" owner. +The UUID of the partition can be specified as a field in the description file or +if it does not exist there the UUID is extracted from the DTS partition +manifest. + +.. code:: shell + + { + "tee1" : { + "image": "tee1.bin", + "pm": "tee1.dts", + "owner": "SiP", + "uuid": "1b1820fe-48f7-4175-8999-d51da00b7c9f" + }, + + "tee2" : { + "image": "tee2.bin", + "pm": "tee2.dts", + "owner": "Plat" + } + } + +SPMC manifest +~~~~~~~~~~~~~ + +This manifest contains the SPMC *attribute* node consumed by the SPMD at boot +time. It implements `[1]`_ (SP manifest at physical FF-A instance) and serves +two different cases: + +- The SPMC resides at S-EL1: the SPMC manifest is used by the SPMD to setup a + SP that co-resides with the SPMC and executes at S-EL1 or Secure Supervisor + mode. +- The SPMC resides at S-EL2: the SPMC manifest is used by the SPMD to setup + the environment required by the SPMC to run at S-EL2. SPs run at S-EL1 or + S-EL0. + +.. code:: shell + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x0>; + exec_state = <0x0>; + load_address = <0x0 0x6000000>; + entrypoint = <0x0 0x6000000>; + binary_size = <0x60000>; + }; + +- *spmc_id* defines the endpoint ID value that SPMC can query through + ``FFA_ID_GET``. +- *maj_ver/min_ver*. SPMD checks provided version versus its internal + version and aborts if not matching. +- *exec_state* defines the SPMC execution state (AArch64 or AArch32). + Notice Hafnium used as a SPMC only supports AArch64. +- *load_address* and *binary_size* are mostly used to verify secondary + entry points fit into the loaded binary image. +- *entrypoint* defines the cold boot primary core entry point used by + SPMD (currently matches ``BL32_BASE``) to enter the SPMC. + +Other nodes in the manifest are consumed by Hafnium in the secure world. +A sample can be found at [7]: + +- The *hypervisor* node describes SPs. *is_ffa_partition* boolean attribute + indicates a FF-A compliant SP. The *load_address* field specifies the load + address at which TF-A loaded the SP package. +- *cpus* node provide the platform topology and allows MPIDR to VMPIDR mapping. + Note the primary core is declared first, then secondary core are declared + in reverse order. +- The *memory* node provides platform information on the ranges of memory + available to the SPMC. + +SPMC boot +~~~~~~~~~ + +The SPMC is loaded by BL2 as the BL32 image. + +The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[9]`_. + +BL2 passes the SPMC manifest address to BL31 through a register. + +At boot time, the SPMD in BL31 runs from the primary core, initializes the core +contexts and launches the SPMC (BL32) passing the following information through +registers: + +- X0 holds the ``TOS_FW_CONFIG`` physical address (or SPMC manifest blob). +- X1 holds the ``HW_CONFIG`` physical address. +- X4 holds the currently running core linear id. + +Loading of SPs +~~~~~~~~~~~~~~ + +At boot time, BL2 loads SPs sequentially in addition to the SPMC as depicted +below: + +.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml + +Note this boot flow is an implementation sample on Arm's FVP platform. +Platforms not using TF-A's *Firmware CONFiguration* framework would adjust to a +different implementation. + +Secure boot +~~~~~~~~~~~ + +The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC, +SPMC manifest, secure partitions and verifies them for authenticity and integrity. +Refer to TBBR specification `[3]`_. + +The multiple-signing domain feature (in current state dual signing domain `[8]`_) allows +the use of two root keys namely S-ROTPK and NS-ROTPK: + +- SPMC (BL32) and SPMC manifest are signed by the SiP using the S-ROTPK. +- BL33 may be signed by the OEM using NS-ROTPK. +- An SP may be signed either by SiP (using S-ROTPK) or by OEM (using NS-ROTPK). + +Also refer to `Describing secure partitions`_ and `TF-A build options`_ sections. + +Hafnium in the secure world +=========================== + +General considerations +---------------------- + +Build platform for the secure world +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In the Hafnium reference implementation specific code parts are only relevant to +the secure world. Such portions are isolated in architecture specific files +and/or enclosed by a ``SECURE_WORLD`` macro. + +Secure partitions CPU scheduling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FF-A v1.0 specification `[1]`_ provides two ways to relinquinsh CPU time to +secure partitions. For this a VM (Hypervisor or OS kernel), or SP invokes one of: + +- the FFA_MSG_SEND_DIRECT_REQ interface. +- the FFA_RUN interface. + +Platform topology +~~~~~~~~~~~~~~~~~ + +The *execution-ctx-count* SP manifest field can take the value of one or the +total number of PEs. The FF-A v1.0 specification `[1]`_ recommends the +following SP types: + +- Pinned MP SPs: an execution context matches a physical PE. MP SPs must + implement the same number of ECs as the number of PEs in the platform. +- Migratable UP SPs: a single execution context can run and be migrated on any + physical PE. Such SP declares a single EC in its SP manifest. An UP SP can + receive a direct message request originating from any physical core targeting + the single execution context. + +Parsing SP partition manifests +------------------------------ + +Hafnium consumes SP manifests as defined in `[1]`_ and `SP manifests`_. +Note the current implementation may not implement all optional fields. + +The SP manifest may contain memory and device regions nodes. In case of +an S-EL2 SPMC: + +- Memory regions are mapped in the SP EL1&0 Stage-2 translation regime at + load time (or EL1&0 Stage-1 for an S-EL1 SPMC). A memory region node can + specify RX/TX buffer regions in which case it is not necessary for an SP + to explicitly invoke the ``FFA_RXTX_MAP`` interface. +- Device regions are mapped in the SP EL1&0 Stage-2 translation regime (or + EL1&0 Stage-1 for an S-EL1 SPMC) as peripherals and possibly allocate + additional resources (e.g. interrupts). + +For the S-EL2 SPMC, base addresses for memory and device region nodes are IPAs +provided the SPMC identity maps IPAs to PAs within SP EL1&0 Stage-2 translation +regime. + +Note: in the current implementation both VTTBR_EL2 and VSTTBR_EL2 point to the +same set of page tables. It is still open whether two sets of page tables shall +be provided per SP. The memory region node as defined in the specification +provides a memory security attribute hinting to map either to the secure or +non-secure EL1&0 Stage-2 table if it exists. + +Passing boot data to the SP +--------------------------- + +In `[1]`_ , the "Protocol for passing data" section defines a method for passing +boot data to SPs (not currently implemented). + +Provided that the whole secure partition package image (see +`Secure Partition packages`_) is mapped to the SP secure EL1&0 Stage-2 +translation regime, an SP can access its own manifest DTB blob and extract its +partition manifest properties. + +SP Boot order +------------- + +SP manifests provide an optional boot order attribute meant to resolve +dependencies such as an SP providing a service required to properly boot +another SP. SPMC boots the SPs in accordance to the boot order attribute, +lowest to the highest value. If the boot order attribute is absent from the FF-A +manifest, the SP is treated as if it had the highest boot order value +(i.e. lowest booting priority). + +It is possible for an SP to call into another SP through a direct request +provided the latter SP has already been booted. + +Boot phases +----------- + +Primary core boot-up +~~~~~~~~~~~~~~~~~~~~ + +Upon boot-up, BL31 hands over to the SPMC (BL32) on the primary boot physical +core. The SPMC performs its platform initializations and registers the SPMC +secondary physical core entry point physical address by the use of the +`FFA_SECONDARY_EP_REGISTER`_ interface (SMC invocation from the SPMC to the SPMD +at secure physical FF-A instance). + +The SPMC then creates secure partitions based on SP packages and manifests. Each +secure partition is launched in sequence (`SP Boot order`_) on their "primary" +execution context. If the primary boot physical core linear id is N, an MP SP is +started using EC[N] on PE[N] (see `Platform topology`_). If the partition is a +UP SP, it is started using its unique EC0 on PE[N]. + +The SP primary EC (or the EC used when the partition is booted as described +above): + +- Performs the overall SP boot time initialization, and in case of a MP SP, + prepares the SP environment for other execution contexts. +- In the case of a MP SP, it invokes the FFA_SECONDARY_EP_REGISTER at secure + virtual FF-A instance (SMC invocation from SP to SPMC) to provide the IPA + entry point for other execution contexts. +- Exits through ``FFA_MSG_WAIT`` to indicate successful initialization or + ``FFA_ERROR`` in case of failure. + +Secondary cores boot-up +~~~~~~~~~~~~~~~~~~~~~~~ + +Once the system is started and NWd brought up, a secondary physical core is +woken up by the ``PSCI_CPU_ON`` service invocation. The TF-A SPD hook mechanism +calls into the SPMD on the newly woken up physical core. Then the SPMC is +entered at the secondary physical core entry point. + +In the current implementation, the first SP is resumed on the coresponding EC +(the virtual CPU which matches the physical core). The implication is that the +first SP must be a MP SP. + +In a linux based system, once secure and normal worlds are booted but prior to +a NWd FF-A driver has been loaded: + +- The first SP has initialized all its ECs in response to primary core boot up + (at system initialization) and secondary core boot up (as a result of linux + invoking PSCI_CPU_ON for all secondary cores). +- Other SPs have their first execution context initialized as a result of secure + world initialization on the primary boot core. Other ECs for those SPs have to + be run first through ffa_run to complete their initialization (which results + in the EC completing with FFA_MSG_WAIT). + +Refer to `Power management`_ for further details. + +Notifications +------------- + +The FF-A v1.1 specification `[1]`_ defines notifications as an asynchronous +communication mechanism with non-blocking semantics. It allows for one FF-A +endpoint to signal another for service provision, without hindering its current +progress. + +Hafnium currently supports 64 notifications. The IDs of each notification define +a position in a 64-bit bitmap. + +The signaling of notifications can interchangeably happen between NWd and SWd +FF-A endpoints. + +The SPMC is in charge of managing notifications from SPs to SPs, from SPs to +VMs, and from VMs to SPs. An hypervisor component would only manage +notifications from VMs to VMs. Given the SPMC has no visibility of the endpoints +deployed in NWd, the Hypervisor or OS kernel must invoke the interface +FFA_NOTIFICATION_BITMAP_CREATE to allocate the notifications bitmap per FF-A +endpoint in the NWd that supports it. + +A sender can signal notifications once the receiver has provided it with +permissions. Permissions are provided by invoking the interface +FFA_NOTIFICATION_BIND. + +Notifications are signaled by invoking FFA_NOTIFICATION_SET. Henceforth +they are considered to be in a pending sate. The receiver can retrieve its +pending notifications invoking FFA_NOTIFICATION_GET, which, from that moment, +are considered to be handled. + +Per the FF-A v1.1 spec, each FF-A endpoint must be associated with a scheduler +that is in charge of donating CPU cycles for notifications handling. The +FF-A driver calls FFA_NOTIFICATION_INFO_GET to retrieve the information about +which FF-A endpoints have pending notifications. The receiver scheduler is +called and informed by the FF-A driver, and it should allocate CPU cycles to the +receiver. + +There are two types of notifications supported: +- Global, which are targeted to a FF-A endpoint and can be handled within any of +its execution contexts, as determined by the scheduler of the system. +- Per-vCPU, which are targeted to a FF-A endpoint and to be handled within a +a specific execution context, as determined by the sender. + +The type of a notification is set when invoking FFA_NOTIFICATION_BIND to give +permissions to the sender. + +Notification signaling resorts to two interrupts: +- Schedule Receiver Interrupt: Non-secure physical interrupt to be handled by +the FF-A 'transport' driver within the receiver scheduler. At initialization +the SPMC (as suggested by the spec) configures a secure SGI, as non-secure, and +triggers it when there are pending notifications, and the respective receivers +need CPU cycles to handle them. +- Notifications Pending Interrupt: Virtual Interrupt to be handled by the +receiver of the notification. Set when there are pending notifications. For +per-vCPU the NPI is pended at the handling of FFA_NOTIFICATION_SET interface. + +The notifications receipt support is enabled in the partition FF-A manifest. + +The subsequent section provides more details about the each one of the +FF-A interfaces for notifications support. + +Mandatory interfaces +-------------------- + +The following interfaces are exposed to SPs: + +- ``FFA_VERSION`` +- ``FFA_FEATURES`` +- ``FFA_RX_RELEASE`` +- ``FFA_RXTX_MAP`` +- ``FFA_RXTX_UNMAP`` +- ``FFA_PARTITION_INFO_GET`` +- ``FFA_ID_GET`` +- ``FFA_MSG_WAIT`` +- ``FFA_MSG_SEND_DIRECT_REQ`` +- ``FFA_MSG_SEND_DIRECT_RESP`` +- ``FFA_MEM_DONATE`` +- ``FFA_MEM_LEND`` +- ``FFA_MEM_SHARE`` +- ``FFA_MEM_RETRIEVE_REQ`` +- ``FFA_MEM_RETRIEVE_RESP`` +- ``FFA_MEM_RELINQUISH`` +- ``FFA_MEM_RECLAIM`` + +As part of the support of FF-A v1.1, the following interfaces were added: + + - ``FFA_NOTIFICATION_BITMAP_CREATE`` + - ``FFA_NOTIFICATION_BITMAP_DESTROY`` + - ``FFA_NOTIFICATION_BIND`` + - ``FFA_NOTIFICATION_UNBIND`` + - ``FFA_NOTIFICATION_SET`` + - ``FFA_NOTIFICATION_GET`` + - ``FFA_NOTIFICATION_INFO_GET`` + - ``FFA_SPM_ID_GET`` + - ``FFA_SECONDARY_EP_REGISTER`` + +FFA_VERSION +~~~~~~~~~~~ + +``FFA_VERSION`` requires a *requested_version* parameter from the caller. +The returned value depends on the caller: + +- Hypervisor or OS kernel in NS-EL1/EL2: the SPMD returns the SPMC version + specified in the SPMC manifest. +- SP: the SPMC returns its own implemented version. +- SPMC at S-EL1/S-EL2: the SPMD returns its own implemented version. + +FFA_FEATURES +~~~~~~~~~~~~ + +FF-A features supported by the SPMC may be discovered by secure partitions at +boot (that is prior to NWd is booted) or run-time. + +The SPMC calling FFA_FEATURES at secure physical FF-A instance always get +FFA_SUCCESS from the SPMD. + +The request made by an Hypervisor or OS kernel is forwarded to the SPMC and +the response relayed back to the NWd. + +FFA_RXTX_MAP/FFA_RXTX_UNMAP +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When invoked from a secure partition FFA_RXTX_MAP maps the provided send and +receive buffers described by their IPAs to the SP EL1&0 Stage-2 translation +regime as secure buffers in the MMU descriptors. + +When invoked from the Hypervisor or OS kernel, the buffers are mapped into the +SPMC EL2 Stage-1 translation regime and marked as NS buffers in the MMU +descriptors. + +The FFA_RXTX_UNMAP unmaps the RX/TX pair from the translation regime of the +caller, either it being the Hypervisor or OS kernel, as well as a secure +partition. + +FFA_PARTITION_INFO_GET +~~~~~~~~~~~~~~~~~~~~~~ + +Partition info get call can originate: + +- from SP to SPMC +- from Hypervisor or OS kernel to SPMC. The request is relayed by the SPMD. + +FFA_ID_GET +~~~~~~~~~~ + +The FF-A id space is split into a non-secure space and secure space: + +- FF-A ID with bit 15 clear relates to VMs. +- FF-A ID with bit 15 set related to SPs. +- FF-A IDs 0, 0xffff, 0x8000 are assigned respectively to the Hypervisor, SPMD + and SPMC. + +The SPMD returns: + +- The default zero value on invocation from the Hypervisor. +- The ``spmc_id`` value specified in the SPMC manifest on invocation from + the SPMC (see `SPMC manifest`_) + +This convention helps the SPMC to determine the origin and destination worlds in +an FF-A ABI invocation. In particular the SPMC shall filter unauthorized +transactions in its world switch routine. It must not be permitted for a VM to +use a secure FF-A ID as origin world by spoofing: + +- A VM-to-SP direct request/response shall set the origin world to be non-secure + (FF-A ID bit 15 clear) and destination world to be secure (FF-A ID bit 15 + set). +- Similarly, an SP-to-SP direct request/response shall set the FF-A ID bit 15 + for both origin and destination IDs. + +An incoming direct message request arriving at SPMD from NWd is forwarded to +SPMC without a specific check. The SPMC is resumed through eret and "knows" the +message is coming from normal world in this specific code path. Thus the origin +endpoint ID must be checked by SPMC for being a normal world ID. + +An SP sending a direct message request must have bit 15 set in its origin +endpoint ID and this can be checked by the SPMC when the SP invokes the ABI. + +The SPMC shall reject the direct message if the claimed world in origin endpoint +ID is not consistent: + +- It is either forwarded by SPMD and thus origin endpoint ID must be a "normal + world ID", +- or initiated by an SP and thus origin endpoint ID must be a "secure world ID". + + +FFA_MSG_SEND_DIRECT_REQ/FFA_MSG_SEND_DIRECT_RESP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is a mandatory interface for secure partitions consisting in direct request +and responses with the following rules: + +- An SP can send a direct request to another SP. +- An SP can receive a direct request from another SP. +- An SP can send a direct response to another SP. +- An SP cannot send a direct request to an Hypervisor or OS kernel. +- An Hypervisor or OS kernel can send a direct request to an SP. +- An SP can send a direct response to an Hypervisor or OS kernel. + +FFA_NOTIFICATION_BITMAP_CREATE/FFA_NOTIFICATION_BITMAP_DESTROY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The secure partitions notifications bitmap are statically allocated by the SPMC. +Hence, this interface is not to be issued by secure partitions. + +At initialization, the SPMC is not aware of VMs/partitions deployed in the +normal world. Hence, the Hypervisor or OS kernel must use both ABIs for SPMC +to be prepared to handle notifications for the provided VM ID. + +FFA_NOTIFICATION_BIND/FFA_NOTIFICATION_UNBIND +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Pair of interfaces to manage permissions to signal notifications. Prior to +handling notifications, an FF-A endpoint must allow a given sender to signal a +bitmap of notifications. + +If the receiver doesn't have notification support enabled in its FF-A manifest, +it won't be able to bind notifications, hence forbidding it to receive any +notifications. + +FFA_NOTIFICATION_SET/FFA_NOTIFICATION_GET +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the notifications set are per-vCPU, the NPI interrupt is set as pending +for a given receiver partition. + +The FFA_NOTIFICATION_GET will retrieve all pending global notifications and all +pending per-vCPU notifications targeted to the current vCPU. + +Hafnium keeps the global counting of the pending notifications, which is +incremented and decremented at the handling of FFA_NOTIFICATION_SET and +FFA_NOTIFICATION_GET, respectively. If the counter reaches zero, prior to SPMC +triggering the SRI, it won't be triggered. + +FFA_NOTIFICATION_INFO_GET +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Hafnium keeps the global counting of pending notifications whose info has been +retrieved by this interface. The counting is incremented and decremented at the +handling of FFA_NOTIFICATION_INFO_GET and FFA_NOTIFICATION_GET, respectively. +It also tracks the notifications whose info has been retrieved individually, +such that it avoids duplicating returned information for subsequent calls to +FFA_NOTIFICATION_INFO_GET. For each notification, this state information is +reset when receiver called FFA_NOTIFICATION_GET to retrieve them. + +FFA_SPM_ID_GET +~~~~~~~~~~~~~~ + +Returns the FF-A ID allocated to the SPM component (which includes SPMC + SPMD). +At initialization, the SPMC queries the SPMD for the SPM ID, using this +same interface, and saves it. + +The call emitted at NS and secure physical FF-A instances returns the SPM ID +specified in the SPMC manifest. + +Secure partitions call this interface at the virtual instance, to which the SPMC +shall return the priorly retrieved SPM ID. + +The Hypervisor or OS kernel can issue an FFA_SPM_ID_GET call handled by the +SPMD, which returns the SPM ID. + +FFA_SECONDARY_EP_REGISTER +~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the SPMC boots, all secure partitions are initialized on their primary +Execution Context. + +The interface FFA_SECONDARY_EP_REGISTER is to be used by a secure partitions +from its first execution context, to provide the entry point address for +secondary execution contexts. + +A secondary EC is first resumed either upon invocation of PSCI_CPU_ON from +the NWd or by invocation of FFA_RUN. + +SPMC-SPMD direct requests/responses +----------------------------------- + +Implementation-defined FF-A IDs are allocated to the SPMC and SPMD. +Using those IDs in source/destination fields of a direct request/response +permits SPMD to SPMC communication and either way. + +- SPMC to SPMD direct request/response uses SMC conduit. +- SPMD to SPMC direct request/response uses ERET conduit. + +PE MMU configuration +-------------------- + +With secure virtualization enabled, two IPA spaces are output from the secure +EL1&0 Stage-1 translation (secure and non-secure). The EL1&0 Stage-2 translation +hardware is fed by: + +- A single secure IPA space when the SP EL1&0 Stage-1 MMU is disabled. +- Two IPA spaces (secure and non-secure) when the SP EL1&0 Stage-1 MMU is + enabled. + +``VTCR_EL2`` and ``VSTCR_EL2`` provide configuration bits for controlling the +NS/S IPA translations. +``VSTCR_EL2.SW`` = 0, ``VSTCR_EL2.SA`` = 0,``VTCR_EL2.NSW`` = 0, ``VTCR_EL2.NSA`` = 1: + +- Stage-2 translations for the NS IPA space access the NS PA space. +- Stage-2 translation table walks for the NS IPA space are to the secure PA space. + +Secure and non-secure IPA regions use the same set of Stage-2 page tables within +a SP. + +Interrupt management +-------------------- + +GIC ownership +~~~~~~~~~~~~~ + +The SPMC owns the GIC configuration. Secure and non-secure interrupts are +trapped at S-EL2. The SPMC manages interrupt resources and allocates interrupt +IDs based on SP manifests. The SPMC acknowledges physical interrupts and injects +virtual interrupts by setting the use of vIRQ/vFIQ bits before resuming a SP. + +Non-secure interrupt handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following illustrate the scenarios of non secure physical interrupts trapped +by the SPMC: + +- The SP handles a managed exit operation: + +.. image:: ../resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png + +- The SP is pre-empted without managed exit: + +.. image:: ../resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png + +Secure interrupt handling +------------------------- + +This section documents the support implemented for secure interrupt handling in +SPMC as per the guidance provided by FF-A v1.1 Beta0 specification. +The following assumptions are made about the system configuration: + + - In the current implementation, S-EL1 SPs are expected to use the para + virtualized ABIs for interrupt management rather than accessing virtual GIC + interface. + - Unless explicitly stated otherwise, this support is applicable only for + S-EL1 SPs managed by SPMC. + - Secure interrupts are configured as G1S or G0 interrupts. + - All physical interrupts are routed to SPMC when running a secure partition + execution context. + +A physical secure interrupt could preempt normal world execution. Moreover, when +the execution is in secure world, it is highly likely that the target of a +secure interrupt is not the currently running execution context of an SP. It +could be targeted to another FF-A component. Consequently, secure interrupt +management depends on the state of the target execution context of the SP that +is responsible for handling the interrupt. Hence, the spec provides guidance on +how to signal start and completion of secure interrupt handling as discussed in +further sections. + +Secure interrupt signaling mechanisms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Signaling refers to the mechanisms used by SPMC to indicate to the SP execution +context that it has a pending virtual interrupt and to further run the SP +execution context, such that it can handle the virtual interrupt. SPMC uses +either the FFA_INTERRUPT interface with ERET conduit or vIRQ signal for signaling +to S-EL1 SPs. When normal world execution is preempted by a secure interrupt, +the SPMD uses the FFA_INTERRUPT ABI with ERET conduit to signal interrupt to SPMC +running in S-EL2. + ++-----------+---------+---------------+---------------------------------------+ +| SP State | Conduit | Interface and | Description | +| | | parameters | | ++-----------+---------+---------------+---------------------------------------+ +| WAITING | ERET, | FFA_INTERRUPT,| SPMC signals to SP the ID of pending | +| | vIRQ | Interrupt ID | interrupt. It pends vIRQ signal and | +| | | | resumes execution context of SP | +| | | | through ERET. | ++-----------+---------+---------------+---------------------------------------+ +| BLOCKED | ERET, | FFA_INTERRUPT | SPMC signals to SP that an interrupt | +| | vIRQ | | is pending. It pends vIRQ signal and | +| | | | resumes execution context of SP | +| | | | through ERET. | ++-----------+---------+---------------+---------------------------------------+ +| PREEMPTED | vIRQ | NA | SPMC pends the vIRQ signal but does | +| | | | not resume execution context of SP. | ++-----------+---------+---------------+---------------------------------------+ +| RUNNING | ERET, | NA | SPMC pends the vIRQ signal and resumes| +| | vIRQ | | execution context of SP through ERET. | ++-----------+---------+---------------+---------------------------------------+ + +Secure interrupt completion mechanisms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A SP signals secure interrupt handling completion to the SPMC through the +following mechanisms: + + - ``FFA_MSG_WAIT`` ABI if it was in WAITING state. + - ``FFA_RUN`` ABI if its was in BLOCKED state. + +In the current implementation, S-EL1 SPs use para-virtualized HVC interface +implemented by SPMC to perform priority drop and interrupt deactivation (we +assume EOImode = 0, i.e. priority drop and deactivation are done together). + +If normal world execution was preempted by secure interrupt, SPMC uses +FFA_NORMAL_WORLD_RESUME ABI to indicate completion of secure interrupt handling +and further return execution to normal world. If the current SP execution +context was preempted by a secure interrupt to be handled by execution context +of target SP, SPMC resumes current SP after signal completion by target SP +execution context. + +An action is broadly a set of steps taken by the SPMC in response to a physical +interrupt. In order to simplify the design, the current version of secure +interrupt management support in SPMC (Hafnium) does not fully implement the +Scheduling models and Partition runtime models. However, the current +implementation loosely maps to the following actions that are legally allowed +by the specification. Please refer to the Table 8.4 in the spec for further +description of actions. The action specified for a type of interrupt when the +SP is in the message processing running state cannot be less permissive than the +action specified for the same type of interrupt when the SP is in the interrupt +handling running state. + ++--------------------+--------------------+------------+-------------+ +| Runtime Model | NS-Int | Self S-Int | Other S-Int | ++--------------------+--------------------+------------+-------------+ +| Message Processing | Signalable with ME | Signalable | Signalable | ++--------------------+--------------------+------------+-------------+ +| Interrupt Handling | Queued | Queued | Queued | ++--------------------+--------------------+------------+-------------+ + +Abbreviations: + + - NS-Int: A Non-secure physical interrupt. It requires a switch to the Normal + world to be handled. + - Other S-Int: A secure physical interrupt targeted to an SP different from + the one that is currently running. + - Self S-Int: A secure physical interrupt targeted to the SP that is currently + running. + +The following figure describes interrupt handling flow when secure interrupt +triggers while in normal world: + +.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-nwd.png + +A brief description of the events: + + - 1) Secure interrupt triggers while normal world is running. + - 2) FIQ gets trapped to EL3. + - 3) SPMD signals secure interrupt to SPMC at S-EL2 using FFA_INTERRUPT ABI. + - 4) SPMC identifies target vCPU of SP and injects virtual interrupt (pends + vIRQ). + - 5) Since SP1 vCPU is in WAITING state, SPMC signals using FFA_INTERRUPT with + interrupt id as argument and resume it using ERET. + - 6) Execution traps to vIRQ handler in SP1 provided that interrupt is not + masked i.e., PSTATE.I = 0 + - 7) SP1 services the interrupt and invokes the de-activation HVC call. + - 8) SPMC does internal state management and further de-activates the physical + interrupt and resumes SP vCPU. + - 9) SP performs secure interrupt completion through FFA_MSG_WAIT ABI. + - 10) SPMC returns control to EL3 using FFA_NORMAL_WORLD_RESUME. + - 11) EL3 resumes normal world execution. + +The following figure describes interrupt handling flow when secure interrupt +triggers while in secure world: + +.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-swd.png + +A brief description of the events: + + - 1) Secure interrupt triggers while SP2 is running and SP1 is blocked. + - 2) Gets trapped to SPMC as IRQ. + - 3) SPMC finds the target vCPU of secure partition responsible for handling + this secure interrupt. In this scenario, it is SP1. + - 4) SPMC pends vIRQ for SP1 and signals through FFA_INTERRUPT interface. + SPMC further resumes SP1 through ERET conduit. + - 5) Execution traps to vIRQ handler in SP1 provided that interrupt is not + masked i.e., PSTATE.I = 0 + - 6) SP1 services the secure interrupt and invokes the de-activation HVC call. + - 7) SPMC does internal state management, de-activates the physical interrupt + and resumes SP1 vCPU. + - 8) Assuming SP1 is in BLOCKED state, SP1 performs secure interrupt completion + through FFA_RUN ABI. + - 9) SPMC resumes the pre-empted vCPU of SP2. + + +Power management +---------------- + +In platforms with or without secure virtualization: + +- The NWd owns the platform PM policy. +- The Hypervisor or OS kernel is the component initiating PSCI service calls. +- The EL3 PSCI library is in charge of the PM coordination and control + (eventually writing to platform registers). +- While coordinating PM events, the PSCI library calls backs into the Secure + Payload Dispatcher for events the latter has statically registered to. + +When using the SPMD as a Secure Payload Dispatcher: + +- A power management event is relayed through the SPD hook to the SPMC. +- In the current implementation only cpu on (svc_on_finish) and cpu off + (svc_off) hooks are registered. +- The behavior for the cpu on event is described in `Secondary cores boot-up`_. + The SPMC is entered through its secondary physical core entry point. +- The cpu off event occurs when the NWd calls PSCI_CPU_OFF. The method by which + the PM event is conveyed to the SPMC is implementation-defined in context of + FF-A v1.0 (`SPMC-SPMD direct requests/responses`_). It consists in a SPMD-to-SPMC + direct request/response conveying the PM event details and SPMC response. + The SPMD performs a synchronous entry into the SPMC. The SPMC is entered and + updates its internal state to reflect the physical core is being turned off. + In the current implementation no SP is resumed as a consequence. This behavior + ensures a minimal support for CPU hotplug e.g. when initiated by the NWd linux + userspace. + +SMMUv3 support in Hafnium +========================= + +An SMMU is analogous to an MMU in a CPU. It performs address translations for +Direct Memory Access (DMA) requests from system I/O devices. +The responsibilities of an SMMU include: + +- Translation: Incoming DMA requests are translated from bus address space to + system physical address space using translation tables compliant to + Armv8/Armv7 VMSA descriptor format. +- Protection: An I/O device can be prohibited from read, write access to a + memory region or allowed. +- Isolation: Traffic from each individial device can be independently managed. + The devices are differentiated from each other using unique translation + tables. + +The following diagram illustrates a typical SMMU IP integrated in a SoC with +several I/O devices along with Interconnect and Memory system. + +.. image:: ../resources/diagrams/MMU-600.png + +SMMU has several versions including SMMUv1, SMMUv2 and SMMUv3. Hafnium provides +support for SMMUv3 driver in both normal and secure world. A brief introduction +of SMMUv3 functionality and the corresponding software support in Hafnium is +provided here. + +SMMUv3 features +--------------- + +- SMMUv3 provides Stage1, Stage2 translation as well as nested (Stage1 + Stage2) + translation support. It can either bypass or abort incoming translations as + well. +- Traffic (memory transactions) from each upstream I/O peripheral device, + referred to as Stream, can be independently managed using a combination of + several memory based configuration structures. This allows the SMMUv3 to + support a large number of streams with each stream assigned to a unique + translation context. +- Support for Armv8.1 VMSA where the SMMU shares the translation tables with + a Processing Element. AArch32(LPAE) and AArch64 translation table format + are supported by SMMUv3. +- SMMUv3 offers non-secure stream support with secure stream support being + optional. Logically, SMMUv3 behaves as if there is an indepdendent SMMU + instance for secure and non-secure stream support. +- It also supports sub-streams to differentiate traffic from a virtualized + peripheral associated with a VM/SP. +- Additionally, SMMUv3.2 provides support for PEs implementing Armv8.4-A + extensions. Consequently, SPM depends on Secure EL2 support in SMMUv3.2 + for providing Secure Stage2 translation support to upstream peripheral + devices. + +SMMUv3 Programming Interfaces +----------------------------- + +SMMUv3 has three software interfaces that are used by the Hafnium driver to +configure the behaviour of SMMUv3 and manage the streams. + +- Memory based data strutures that provide unique translation context for + each stream. +- Memory based circular buffers for command queue and event queue. +- A large number of SMMU configuration registers that are memory mapped during + boot time by Hafnium driver. Except a few registers, all configuration + registers have independent secure and non-secure versions to configure the + behaviour of SMMUv3 for translation of secure and non-secure streams + respectively. + +Peripheral device manifest +-------------------------- + +Currently, SMMUv3 driver in Hafnium only supports dependent peripheral devices. +These devices are dependent on PE endpoint to initiate and receive memory +management transactions on their behalf. The acccess to the MMIO regions of +any such device is assigned to the endpoint during boot. Moreover, SMMUv3 driver +uses the same stage 2 translations for the device as those used by partition +manager on behalf of the PE endpoint. This ensures that the peripheral device +has the same visibility of the physical address space as the endpoint. The +device node of the corresponding partition manifest (refer to `[1]`_ section 3.2 +) must specify these additional properties for each peripheral device in the +system : + +- smmu-id: This field helps to identify the SMMU instance that this device is + upstream of. +- stream-ids: List of stream IDs assigned to this device. + +.. code:: shell + + smmuv3-testengine { + base-address = <0x00000000 0x2bfe0000>; + pages-count = <32>; + attributes = <0x3>; + smmu-id = <0>; + stream-ids = <0x0 0x1>; + interrupts = <0x2 0x3>, <0x4 0x5>; + exclusive-access; + }; + +SMMUv3 driver limitations +------------------------- + +The primary design goal for the Hafnium SMMU driver is to support secure +streams. + +- Currently, the driver only supports Stage2 translations. No support for + Stage1 or nested translations. +- Supports only AArch64 translation format. +- No support for features such as PCI Express (PASIDs, ATS, PRI), MSI, RAS, + Fault handling, Performance Monitor Extensions, Event Handling, MPAM. +- No support for independent peripheral devices. + +S-EL0 Partition support +========================= +The SPMC (Hafnium) has limited capability to run S-EL0 FF-A partitions using +FEAT_VHE (mandatory with ARMv8.1 in non-secure state, and in secure world +with ARMv8.4 and FEAT_SEL2). + +S-EL0 partitions are useful for simple partitions that don't require full +Trusted OS functionality. It is also useful to reduce jitter and cycle +stealing from normal world since they are more lightweight than VMs. + +S-EL0 partitions are presented, loaded and initialized the same as S-EL1 VMs by +the SPMC. They are differentiated primarily by the 'exception-level' property +and the 'execution-ctx-count' property in the SP manifest. They are host apps +under the single EL2&0 Stage-1 translation regime controlled by the SPMC and +call into the SPMC through SVCs as opposed to HVCs and SMCs. These partitions +can use FF-A defined services (FFA_MEM_PERM_*) to update or change permissions +for memory regions. + +S-EL0 partitions are required by the FF-A specification to be UP endpoints, +capable of migrating, and the SPMC enforces this requirement. The SPMC allows +a S-EL0 partition to accept a direct message from secure world and normal world, +and generate direct responses to them. + +Memory sharing between and with S-EL0 partitions is supported. +Indirect messaging, Interrupt handling and Notifications are not supported with +S-EL0 partitions and is work in progress, planned for future releases. +All S-EL0 partitions must use AArch64. AArch32 S-EL0 partitions are not +supported. + + +References +========== + +.. _[1]: + +[1] `Arm Firmware Framework for Arm A-profile `__ + +.. _[2]: + +[2] :ref:`Secure Partition Manager using MM interface` + +.. _[3]: + +[3] `Trusted Boot Board Requirements +Client `__ + +.. _[4]: + +[4] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/lib/el3_runtime/aarch64/context.S#n45 + +.. _[5]: + +[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/plat/arm/fvp/fdts/cactus.dts + +.. _[6]: + +[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/ffa-manifest-binding.html + +.. _[7]: + +[7] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts + +.. _[8]: + +[8] https://lists.trustedfirmware.org/pipermail/tf-a/2020-February/000296.html + +.. _[9]: + +[9] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot + +-------------- + +*Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/spd/index.rst b/arm-trusted-firmware/docs/components/spd/index.rst new file mode 100644 index 0000000..25d0124 --- /dev/null +++ b/arm-trusted-firmware/docs/components/spd/index.rst @@ -0,0 +1,10 @@ +Secure Payload Dispatcher (SPD) +=============================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + optee-dispatcher + tlk-dispatcher + trusty-dispatcher diff --git a/arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst b/arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst new file mode 100644 index 0000000..63baccc --- /dev/null +++ b/arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst @@ -0,0 +1,14 @@ +OP-TEE Dispatcher +================= + +`OP-TEE OS`_ is a Trusted OS running as Secure EL1. + +To build and execute OP-TEE follow the instructions at +`OP-TEE build.git`_ + +-------------- + +*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.* + +.. _OP-TEE OS: https://github.com/OP-TEE/build +.. _OP-TEE build.git: https://github.com/OP-TEE/build diff --git a/arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst b/arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst new file mode 100644 index 0000000..a6c658c --- /dev/null +++ b/arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst @@ -0,0 +1,76 @@ +Trusted Little Kernel (TLK) Dispatcher +====================================== + +TLK dispatcher (TLK-D) adds support for NVIDIA's Trusted Little Kernel (TLK) +to work with Trusted Firmware-A (TF-A). TLK-D can be compiled by including it +in the platform's makefile. TLK is primarily meant to work with Tegra SoCs, +so while TF-A only supports TLK on Tegra, the dispatcher code can only be +compiled for other platforms. + +In order to compile TLK-D, we need a BL32 image to be present. Since, TLKD +just needs to compile, any BL32 image would do. To use TLK as the BL32, please +refer to the "Build TLK" section. + +Once a BL32 is ready, TLKD can be included in the image by adding "SPD=tlkd" +to the build command. + +Trusted Little Kernel (TLK) +--------------------------- + +TLK is a Trusted OS running as Secure EL1. It is a Free Open Source Software +(FOSS) release of the NVIDIA® Trusted Little Kernel (TLK) technology, which +extends technology made available with the development of the Little Kernel (LK). +You can download the LK modular embedded preemptive kernel for use on Arm, +x86, and AVR32 systems from https://github.com/travisg/lk + +NVIDIA implemented its Trusted Little Kernel (TLK) technology, designed as a +free and open-source trusted execution environment (OTE). + +TLK features include: + +• Small, pre-emptive kernel +• Supports multi-threading, IPCs, and thread scheduling +• Added TrustZone features +• Added Secure Storage +• Under MIT/FreeBSD license + +NVIDIA extensions to Little Kernel (LK) include: + +• User mode +• Address-space separation for TAs +• TLK Client Application (CA) library +• TLK TA library +• Crypto library (encrypt/decrypt, key handling) via OpenSSL +• Linux kernel driver +• Cortex A9/A15 support +• Power Management +• TrustZone memory carve-out (reconfigurable) +• Page table management +• Debugging support over UART (USB planned) + +TLK is hosted by NVIDIA on http://nv-tegra.nvidia.com under the +3rdparty/ote\_partner/tlk.git repository. Detailed information about +TLK and OTE can be found in the Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf +manual located under the "documentation" directory\_. + +Build TLK +--------- + +To build and execute TLK, follow the instructions from "Building a TLK Device" +section from Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf manual. + +Input parameters to TLK +----------------------- + +TLK expects the TZDRAM size and a structure containing the boot arguments. BL2 +passes this information to the EL3 software as members of the bl32\_ep\_info +struct, where bl32\_ep\_info is part of bl31\_params\_t (passed by BL2 in X0) + +Example +~~~~~~~ + +:: + + bl32_ep_info->args.arg0 = TZDRAM size available for BL32 + bl32_ep_info->args.arg1 = unused (used only on Armv7-A) + bl32_ep_info->args.arg2 = pointer to boot args diff --git a/arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst b/arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst new file mode 100644 index 0000000..a3cb829 --- /dev/null +++ b/arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst @@ -0,0 +1,32 @@ +Trusty Dispatcher +================= + +Trusty is a a set of software components, supporting a Trusted Execution +Environment (TEE) on mobile devices, published and maintained by Google. + +Detailed information and build instructions can be found on the Android +Open Source Project (AOSP) webpage for Trusty hosted at +https://source.android.com/security/trusty + +Boot parameters +--------------- + +Custom boot parameters can be passed to Trusty by providing a platform +specific function: + +.. code:: c + + void plat_trusty_set_boot_args(aapcs64_params_t *args) + +If this function is provided ``args->arg0`` must be set to the memory +size allocated to trusty. If the platform does not provide this +function, but defines ``TSP_SEC_MEM_SIZE``, a default implementation +will pass the memory size from ``TSP_SEC_MEM_SIZE``. ``args->arg1`` +can be set to a platform specific parameter block, and ``args->arg2`` +should then be set to the size of that block. + +Supported platforms +------------------- + +Out of all the platforms supported by Trusted Firmware-A, Trusty is only +verified and supported by NVIDIA's Tegra SoCs. diff --git a/arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst b/arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst new file mode 100644 index 0000000..cac32f5 --- /dev/null +++ b/arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst @@ -0,0 +1,442 @@ +Translation (XLAT) Tables Library +================================= + +This document describes the design of the translation tables library (version 2) +used by Trusted Firmware-A (TF-A). This library provides APIs to create page +tables based on a description of the memory layout, as well as setting up system +registers related to the Memory Management Unit (MMU) and performing the +required Translation Lookaside Buffer (TLB) maintenance operations. + +More specifically, some use cases that this library aims to support are: + +#. Statically allocate translation tables and populate them (at run-time) based + upon a description of the memory layout. The memory layout is typically + provided by the platform port as a list of memory regions; + +#. Support for generating translation tables pertaining to a different + translation regime than the exception level the library code is executing at; + +#. Support for dynamic mapping and unmapping of regions, even while the MMU is + on. This can be used to temporarily map some memory regions and unmap them + later on when no longer needed; + +#. Support for non-identity virtual to physical mappings to compress the virtual + address space; + +#. Support for changing memory attributes of memory regions at run-time. + + +About version 1, version 2 and MPU libraries +-------------------------------------------- + +This document focuses on version 2 of the library, whose sources are available +in the ``lib/xlat_tables_v2`` directory. Version 1 of the library can still be +found in ``lib/xlat_tables`` directory but it is less flexible and doesn't +support dynamic mapping. ``lib/xlat_mpu``, which configures Arm's MPU +equivalently, is also addressed here. The ``lib/xlat_mpu`` is experimental, +meaning that its API may change. It currently strives for consistency and +code-reuse with xlat_tables_v2. Future versions may be more MPU-specific (e.g., +removing all mentions of virtual addresses). Although potential bug fixes will +be applied to all versions of the xlat_* libs, future feature enhancements will +focus on version 2 and might not be back-ported to version 1 and MPU versions. +Therefore, it is recommended to use version 2, especially for new platform +ports (unless the platform uses an MPU). + +However, please note that version 2 and the MPU version are still in active +development and is not considered stable yet. Hence, compatibility breaks might +be introduced. + +From this point onwards, this document will implicitly refer to version 2 of the +library, unless stated otherwise. + + +Design concepts and interfaces +------------------------------ + +This section presents some of the key concepts and data structures used in the +translation tables library. + +`mmap` regions +~~~~~~~~~~~~~~ + +An ``mmap_region`` is an abstract, concise way to represent a memory region to +map. It is one of the key interfaces to the library. It is identified by: + +- its physical base address; +- its virtual base address; +- its size; +- its attributes; +- its mapping granularity (optional). + +See the ``struct mmap_region`` type in ``xlat_tables_v2.h``. + +The user usually provides a list of such mmap regions to map and lets the +library transpose that in a set of translation tables. As a result, the library +might create new translation tables, update or split existing ones. + +The region attributes specify the type of memory (for example device or cached +normal memory) as well as the memory access permissions (read-only or +read-write, executable or not, secure or non-secure, and so on). In the case of +the EL1&0 translation regime, the attributes also specify whether the region is +a User region (EL0) or Privileged region (EL1). See the ``MT_xxx`` definitions +in ``xlat_tables_v2.h``. Note that for the EL1&0 translation regime the Execute +Never attribute is set simultaneously for both EL1 and EL0. + +The granularity controls the translation table level to go down to when mapping +the region. For example, assuming the MMU has been configured to use a 4KB +granule size, the library might map a 2MB memory region using either of the two +following options: + +- using a single level-2 translation table entry; +- using a level-2 intermediate entry to a level-3 translation table (which + contains 512 entries, each mapping 4KB). + +The first solution potentially requires less translation tables, hence +potentially less memory. However, if part of this 2MB region is later remapped +with different memory attributes, the library might need to split the existing +page tables to refine the mappings. If a single level-2 entry has been used +here, a level-3 table will need to be allocated on the fly and the level-2 +modified to point to this new level-3 table. This has a performance cost at +run-time. + +If the user knows upfront that such a remapping operation is likely to happen +then they might enforce a 4KB mapping granularity for this 2MB region from the +beginning; remapping some of these 4KB pages on the fly then becomes a +lightweight operation. + +The region's granularity is an optional field; if it is not specified the +library will choose the mapping granularity for this region as it sees fit (more +details can be found in `The memory mapping algorithm`_ section below). + +The MPU library also uses ``struct mmap_region`` to specify translations, but +the MPU's translations are limited to specification of valid addresses and +access permissions. If the requested virtual and physical addresses mismatch +the system will panic. Being register-based for deterministic memory-reference +timing, the MPU hardware does not involve memory-resident translation tables. + +Currently, the MPU library is also limited to MPU translation at EL2 with no +MMU translation at other ELs. These limitations, however, are expected to be +overcome in future library versions. + +Translation Context +~~~~~~~~~~~~~~~~~~~ + +The library can create or modify translation tables pertaining to a different +translation regime than the exception level the library code is executing at. +For example, the library might be used by EL3 software (for instance BL31) to +create translation tables pertaining to the S-EL1&0 translation regime. + +This flexibility comes from the use of *translation contexts*. A *translation +context* constitutes the superset of information used by the library to track +the status of a set of translation tables for a given translation regime. + +The library internally allocates a default translation context, which pertains +to the translation regime of the current exception level. Additional contexts +may be explicitly allocated and initialized using the +``REGISTER_XLAT_CONTEXT()`` macro. Separate APIs are provided to act either on +the default translation context or on an alternative one. + +To register a translation context, the user must provide the library with the +following information: + +* A name. + + The resulting translation context variable will be called after this name, to + which ``_xlat_ctx`` is appended. For example, if the macro name parameter is + ``foo``, the context variable name will be ``foo_xlat_ctx``. + +* The maximum number of `mmap` regions to map. + + Should account for both static and dynamic regions, if applicable. + +* The number of sub-translation tables to allocate. + + Number of translation tables to statically allocate for this context, + excluding the initial lookup level translation table, which is always + allocated. For example, if the initial lookup level is 1, this parameter would + specify the number of level-2 and level-3 translation tables to pre-allocate + for this context. + +* The size of the virtual address space. + + Size in bytes of the virtual address space to map using this context. This + will incidentally determine the number of entries in the initial lookup level + translation table : the library will allocate as many entries as is required + to map the entire virtual address space. + +* The size of the physical address space. + + Size in bytes of the physical address space to map using this context. + +The default translation context is internally initialized using information +coming (for the most part) from platform-specific defines: + +- name: hard-coded to ``tf`` ; hence the name of the default context variable is + ``tf_xlat_ctx``; +- number of `mmap` regions: ``MAX_MMAP_REGIONS``; +- number of sub-translation tables: ``MAX_XLAT_TABLES``; +- size of the virtual address space: ``PLAT_VIRT_ADDR_SPACE_SIZE``; +- size of the physical address space: ``PLAT_PHY_ADDR_SPACE_SIZE``. + +Please refer to the :ref:`Porting Guide` for more details about these macros. + + +Static and dynamic memory regions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The library optionally supports dynamic memory mapping. This feature may be +enabled using the ``PLAT_XLAT_TABLES_DYNAMIC`` platform build flag. + +When dynamic memory mapping is enabled, the library categorises mmap regions as +*static* or *dynamic*. + +- *Static regions* are fixed for the lifetime of the system. They can only be + added early on, before the translation tables are created and populated. They + cannot be removed afterwards. + +- *Dynamic regions* can be added or removed any time. + +When the dynamic memory mapping feature is disabled, only static regions exist. + +The dynamic memory mapping feature may be used to map and unmap transient memory +areas. This is useful when the user needs to access some memory for a fixed +period of time, after which the memory may be discarded and reclaimed. For +example, a memory region that is only required at boot time while the system is +initializing, or to temporarily share a memory buffer between the normal world +and trusted world. Note that it is up to the caller to ensure that these regions +are not accessed concurrently while the regions are being added or removed. + +Although this feature provides some level of dynamic memory allocation, this +does not allow dynamically allocating an arbitrary amount of memory at an +arbitrary memory location. The user is still required to declare at compile-time +the limits of these allocations ; the library will deny any mapping request that +does not fit within this pre-allocated pool of memory. + + +Library APIs +------------ + +The external APIs exposed by this library are declared and documented in the +``xlat_tables_v2.h`` header file. This should be the reference point for +getting information about the usage of the different APIs this library +provides. This section just provides some extra details and clarifications. + +Although the ``mmap_region`` structure is a publicly visible type, it is not +recommended to populate these structures by hand. Instead, wherever APIs expect +function arguments of type ``mmap_region_t``, these should be constructed using +the ``MAP_REGION*()`` family of helper macros. This is to limit the risk of +compatibility breaks, should the ``mmap_region`` structure type evolve in the +future. + +The ``MAP_REGION()`` and ``MAP_REGION_FLAT()`` macros do not allow specifying a +mapping granularity, which leaves the library implementation free to choose +it. However, in cases where a specific granularity is required, the +``MAP_REGION2()`` macro might be used instead. Using ``MAP_REGION_FLAT()`` only +to define regions for the MPU library is strongly recommended. + +As explained earlier in this document, when the dynamic mapping feature is +disabled, there is no notion of dynamic regions. Conceptually, there are only +static regions. For this reason (and to retain backward compatibility with the +version 1 of the library), the APIs that map static regions do not embed the +word *static* in their functions names (for example ``mmap_add_region()``), in +contrast with the dynamic regions APIs (for example +``mmap_add_dynamic_region()``). + +Although the definition of static and dynamic regions is not based on the state +of the MMU, the two are still related in some way. Static regions can only be +added before ``init_xlat_tables()`` is called and ``init_xlat_tables()`` must be +called while the MMU is still off. As a result, static regions cannot be added +once the MMU has been enabled. Dynamic regions can be added with the MMU on or +off. In practice, the usual call flow would look like this: + +#. The MMU is initially off. + +#. Add some static regions, add some dynamic regions. + +#. Initialize translation tables based on the list of mmap regions (using one of + the ``init_xlat_tables*()`` APIs). + +#. At this point, it is no longer possible to add static regions. Dynamic + regions can still be added or removed. + +#. Enable the MMU. + +#. Dynamic regions can continue to be added or removed. + +Because static regions are added early on at boot time and are all in the +control of the platform initialization code, the ``mmap_add*()`` family of APIs +are not expected to fail. They do not return any error code. + +Nonetheless, these APIs will check upfront whether the region can be +successfully added before updating the translation context structure. If the +library detects that there is insufficient memory to meet the request, or that +the new region will overlap another one in an invalid way, or if any other +unexpected error is encountered, they will print an error message on the UART. +Additionally, when asserts are enabled (typically in debug builds), an assertion +will be triggered. Otherwise, the function call will just return straight away, +without adding the offending memory region. + + +Library limitations +------------------- + +Dynamic regions are not allowed to overlap each other. Static regions are +allowed to overlap as long as one of them is fully contained inside the other +one. This is allowed for backwards compatibility with the previous behaviour in +the version 1 of the library. + + +Implementation details +---------------------- + +Code structure +~~~~~~~~~~~~~~ + +The library is divided into 4 modules: + +- **Core module** + + Provides the main functionality of the library, such as the initialization of + translation tables contexts and mapping/unmapping memory regions. This module + provides functions such as ``mmap_add_region_ctx`` that let the caller specify + the translation tables context affected by them. + + See ``xlat_tables_core.c``. + +- **Active context module** + + Instantiates the context that is used by the current BL image and provides + helpers to manipulate it, abstracting it from the rest of the code. + This module provides functions such as ``mmap_add_region``, that directly + affect the BL image using them. + + See ``xlat_tables_context.c``. + +- **Utilities module** + + Provides additional functionality like debug print of the current state of the + translation tables and helpers to query memory attributes and to modify them. + + See ``xlat_tables_utils.c``. + +- **Architectural module** + + Provides functions that are dependent on the current execution state + (AArch32/AArch64), such as the functions used for TLB invalidation, setup the + MMU, or calculate the Physical Address Space size. They do not need a + translation context to work on. + + See ``aarch32/xlat_tables_arch.c`` and ``aarch64/xlat_tables_arch.c``. + +From mmap regions to translation tables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A translation context contains a list of ``mmap_region_t``, which holds the +information of all the regions that are mapped at any given time. Whenever there +is a request to map (resp. unmap) a memory region, it is added to (resp. removed +from) the ``mmap_region_t`` list. + +The mmap regions list is a conceptual way to represent the memory layout. At +some point, the library has to convert this information into actual translation +tables to program into the MMU. + +Before the ``init_xlat_tables()`` API is called, the library only acts on the +mmap regions list. Adding a static or dynamic region at this point through one +of the ``mmap_add*()`` APIs does not affect the translation tables in any way, +they only get registered in the internal mmap region list. It is only when the +user calls the ``init_xlat_tables()`` that the translation tables are populated +in memory based on the list of mmap regions registered so far. This is an +optimization that allows creation of the initial set of translation tables in +one go, rather than having to edit them every time while the MMU is disabled. + +After the ``init_xlat_tables()`` API has been called, only dynamic regions can +be added. Changes to the translation tables (as well as the mmap regions list) +will take effect immediately. + +The memory mapping algorithm +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The mapping function is implemented as a recursive algorithm. It is however +bound by the level of depth of the translation tables (the Armv8-A architecture +allows up to 4 lookup levels). + +By default [#granularity]_, the algorithm will attempt to minimize the +number of translation tables created to satisfy the user's request. It will +favour mapping a region using the biggest possible blocks, only creating a +sub-table if it is strictly necessary. This is to reduce the memory footprint of +the firmware. + +The most common reason for needing a sub-table is when a specific mapping +requires a finer granularity. Misaligned regions also require a finer +granularity than what the user may had originally expected, using a lot more +memory than expected. The reason is that all levels of translation are +restricted to address translations of the same granularity as the size of the +blocks of that level. For example, for a 4 KiB page size, a level 2 block entry +can only translate up to a granularity of 2 MiB. If the Physical Address is not +aligned to 2 MiB then additional level 3 tables are also needed. + +Note that not every translation level allows any type of descriptor. Depending +on the page size, levels 0 and 1 of translation may only allow table +descriptors. If a block entry could be able to describe a translation, but that +level does not allow block descriptors, a table descriptor will have to be used +instead, as well as additional tables at the next level. + +|Alignment Example| + +The mmap regions are sorted in a way that simplifies the code that maps +them. Even though this ordering is only strictly needed for overlapping static +regions, it must also be applied for dynamic regions to maintain a consistent +order of all regions at all times. As each new region is mapped, existing +entries in the translation tables are checked to ensure consistency. Please +refer to the comments in the source code of the core module for more details +about the sorting algorithm in use. + +This mapping algorithm does not apply to the MPU library, since the MPU hardware +directly maps regions by "base" and "limit" (bottom and top) addresses. + +TLB maintenance operations +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The library takes care of performing TLB maintenance operations when required. +For example, when the user requests removing a dynamic region, the library +invalidates all TLB entries associated to that region to ensure that these +changes are visible to subsequent execution, including speculative execution, +that uses the changed translation table entries. + +A counter-example is the initialization of translation tables. In this case, +explicit TLB maintenance is not required. The Armv8-A architecture guarantees +that all TLBs are disabled from reset and their contents have no effect on +address translation at reset [#tlb-reset-ref]_. Therefore, the TLBs invalidation +is deferred to the ``enable_mmu*()`` family of functions, just before the MMU is +turned on. + +Regarding enabling and disabling memory management, for the MPU library, to +reduce confusion, calls to enable or disable the MPU use ``mpu`` in their names +in place of ``mmu``. For example, the ``enable_mmu_el2()`` call is changed to +``enable_mpu_el2()``. + +TLB invalidation is not required when adding dynamic regions either. Dynamic +regions are not allowed to overlap existing memory region. Therefore, if the +dynamic mapping request is deemed legitimate, it automatically concerns memory +that was not mapped in this translation regime and the library will have +initialized its corresponding translation table entry to an invalid +descriptor. Given that the TLBs are not architecturally permitted to hold any +invalid translation table entry [#tlb-no-invalid-entry]_, this means that this +mapping cannot be cached in the TLBs. + +.. rubric:: Footnotes + +.. [#granularity] That is, when mmap regions do not enforce their mapping + granularity. + +.. [#tlb-reset-ref] See section D4.9 ``Translation Lookaside Buffers (TLBs)``, + subsection ``TLB behavior at reset`` in Armv8-A, rev C.a. + +.. [#tlb-no-invalid-entry] See section D4.10.1 ``General TLB maintenance + requirements`` in Armv8-A, rev C.a. + +-------------- + +*Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.* + +.. |Alignment Example| image:: ../resources/diagrams/xlat_align.png diff --git a/arm-trusted-firmware/docs/conf.py b/arm-trusted-firmware/docs/conf.py new file mode 100644 index 0000000..ef77f6b --- /dev/null +++ b/arm-trusted-firmware/docs/conf.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2019-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +# Configuration file for the Sphinx documentation builder. +# +# See the options documentation at http://www.sphinx-doc.org/en/master/config + +import os + +# -- Project information ----------------------------------------------------- + +project = 'Trusted Firmware-A' + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['myst_parser', 'sphinx.ext.autosectionlabel', 'sphinxcontrib.plantuml'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +source_suffix = ['.md', '.rst'] + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# Load the contents of the global substitutions file into the 'rst_prolog' +# variable. This ensures that the substitutions are all inserted into each page. +with open('global_substitutions.txt', 'r') as subs: + rst_prolog = subs.read() + +# Minimum version of sphinx required +needs_sphinx = '2.0' + +# -- Options for HTML output ------------------------------------------------- + +# Don't show the "Built with Sphinx" footer +html_show_sphinx = False + +# Don't show copyright info in the footer (we have this content in the page) +html_show_copyright = False + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = "sphinx_rtd_theme" + +# The logo to display in the sidebar +html_logo = 'resources/TrustedFirmware-Logo_standard-white.png' + +# Options for the "sphinx-rtd-theme" theme +html_theme_options = { + 'collapse_navigation': False, # Can expand and collapse sidebar entries + 'prev_next_buttons_location': 'both', # Top and bottom of the page + 'style_external_links': True # Display an icon next to external links +} + +# Path to _static directory +html_static_path = ['_static'] + +# Path to css file relative to html_static_path +html_css_files = [ + 'css/custom.css', +] + +# -- Options for autosectionlabel -------------------------------------------- + +# Only generate automatic section labels for document titles +autosectionlabel_maxdepth = 1 + +# -- Options for plantuml ---------------------------------------------------- + +plantuml_output_format = 'svg_img' diff --git a/arm-trusted-firmware/docs/design/alt-boot-flows.rst b/arm-trusted-firmware/docs/design/alt-boot-flows.rst new file mode 100644 index 0000000..b44c061 --- /dev/null +++ b/arm-trusted-firmware/docs/design/alt-boot-flows.rst @@ -0,0 +1,84 @@ +Alternative Boot Flows +====================== + +EL3 payloads alternative boot flow +---------------------------------- + +On a pre-production system, the ability to execute arbitrary, bare-metal code at +the highest exception level is required. It allows full, direct access to the +hardware, for example to run silicon soak tests. + +Although it is possible to implement some baremetal secure firmware from +scratch, this is a complex task on some platforms, depending on the level of +configuration required to put the system in the expected state. + +Rather than booting a baremetal application, a possible compromise is to boot +``EL3 payloads`` through TF-A instead. This is implemented as an alternative +boot flow, where a modified BL2 boots an EL3 payload, instead of loading the +other BL images and passing control to BL31. It reduces the complexity of +developing EL3 baremetal code by: + +- putting the system into a known architectural state; +- taking care of platform secure world initialization; +- loading the SCP_BL2 image if required by the platform. + +When booting an EL3 payload on Arm standard platforms, the configuration of the +TrustZone controller is simplified such that only region 0 is enabled and is +configured to permit secure access only. This gives full access to the whole +DRAM to the EL3 payload. + +The system is left in the same state as when entering BL31 in the default boot +flow. In particular: + +- Running in EL3; +- Current state is AArch64; +- Little-endian data access; +- All exceptions disabled; +- MMU disabled; +- Caches disabled. + +.. _alt_boot_flows_el3_payload: + +Booting an EL3 payload +~~~~~~~~~~~~~~~~~~~~~~ + +The EL3 payload image is a standalone image and is not part of the FIP. It is +not loaded by TF-A. Therefore, there are 2 possible scenarios: + +- The EL3 payload may reside in non-volatile memory (NVM) and execute in + place. In this case, booting it is just a matter of specifying the right + address in NVM through ``EL3_PAYLOAD_BASE`` when building TF-A. + +- The EL3 payload needs to be loaded in volatile memory (e.g. DRAM) at + run-time. + +To help in the latter scenario, the ``SPIN_ON_BL1_EXIT=1`` build option can be +used. The infinite loop that it introduces in BL1 stops execution at the right +moment for a debugger to take control of the target and load the payload (for +example, over JTAG). + +It is expected that this loading method will work in most cases, as a debugger +connection is usually available in a pre-production system. The user is free to +use any other platform-specific mechanism to load the EL3 payload, though. + + +Preloaded BL33 alternative boot flow +------------------------------------ + +Some platforms have the ability to preload BL33 into memory instead of relying +on TF-A to load it. This may simplify packaging of the normal world code and +improve performance in a development environment. When secure world cold boot +is complete, TF-A simply jumps to a BL33 base address provided at build time. + +For this option to be used, the ``PRELOADED_BL33_BASE`` build option has to be +used when compiling TF-A. For example, the following command will create a FIP +without a BL33 and prepare to jump to a BL33 image loaded at address +0x80000000: + +.. code:: shell + + make PRELOADED_BL33_BASE=0x80000000 PLAT=fvp all fip + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design/auth-framework.rst b/arm-trusted-firmware/docs/design/auth-framework.rst new file mode 100644 index 0000000..6913e66 --- /dev/null +++ b/arm-trusted-firmware/docs/design/auth-framework.rst @@ -0,0 +1,980 @@ +Authentication Framework & Chain of Trust +========================================= + +The aim of this document is to describe the authentication framework +implemented in Trusted Firmware-A (TF-A). This framework fulfills the +following requirements: + +#. It should be possible for a platform port to specify the Chain of Trust in + terms of certificate hierarchy and the mechanisms used to verify a + particular image/certificate. + +#. The framework should distinguish between: + + - The mechanism used to encode and transport information, e.g. DER encoded + X.509v3 certificates to ferry Subject Public Keys, hashes and non-volatile + counters. + + - The mechanism used to verify the transported information i.e. the + cryptographic libraries. + +The framework has been designed following a modular approach illustrated in the +next diagram: + +:: + + +---------------+---------------+------------+ + | Trusted | Trusted | Trusted | + | Firmware | Firmware | Firmware | + | Generic | IO Framework | Platform | + | Code i.e. | (IO) | Port | + | BL1/BL2 (GEN) | | (PP) | + +---------------+---------------+------------+ + ^ ^ ^ + | | | + v v v + +-----------+ +-----------+ +-----------+ + | | | | | Image | + | Crypto | | Auth | | Parser | + | Module |<->| Module |<->| Module | + | (CM) | | (AM) | | (IPM) | + | | | | | | + +-----------+ +-----------+ +-----------+ + ^ ^ + | | + v v + +----------------+ +-----------------+ + | Cryptographic | | Image Parser | + | Libraries (CL) | | Libraries (IPL) | + +----------------+ +-----------------+ + | | + | | + | | + v v + +-----------------+ + | Misc. Libs e.g. | + | ASN.1 decoder | + | | + +-----------------+ + + DIAGRAM 1. + +This document describes the inner details of the authentication framework and +the abstraction mechanisms available to specify a Chain of Trust. + +Framework design +---------------- + +This section describes some aspects of the framework design and the rationale +behind them. These aspects are key to verify a Chain of Trust. + +Chain of Trust +~~~~~~~~~~~~~~ + +A CoT is basically a sequence of authentication images which usually starts with +a root of trust and culminates in a single data image. The following diagram +illustrates how this maps to a CoT for the BL31 image described in the +`TBBR-Client specification`_. + +:: + + +------------------+ +-------------------+ + | ROTPK/ROTPK Hash |------>| Trusted Key | + +------------------+ | Certificate | + | (Auth Image) | + /+-------------------+ + / | + / | + / | + / | + L v + +------------------+ +-------------------+ + | Trusted World |------>| BL31 Key | + | Public Key | | Certificate | + +------------------+ | (Auth Image) | + +-------------------+ + / | + / | + / | + / | + / v + +------------------+ L +-------------------+ + | BL31 Content |------>| BL31 Content | + | Certificate PK | | Certificate | + +------------------+ | (Auth Image) | + +-------------------+ + / | + / | + / | + / | + / v + +------------------+ L +-------------------+ + | BL31 Hash |------>| BL31 Image | + | | | (Data Image) | + +------------------+ | | + +-------------------+ + + DIAGRAM 2. + +The root of trust is usually a public key (ROTPK) that has been burnt in the +platform and cannot be modified. + +Image types +~~~~~~~~~~~ + +Images in a CoT are categorised as authentication and data images. An +authentication image contains information to authenticate a data image or +another authentication image. A data image is usually a boot loader binary, but +it could be any other data that requires authentication. + +Component responsibilities +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For every image in a Chain of Trust, the following high level operations are +performed to verify it: + +#. Allocate memory for the image either statically or at runtime. + +#. Identify the image and load it in the allocated memory. + +#. Check the integrity of the image as per its type. + +#. Authenticate the image as per the cryptographic algorithms used. + +#. If the image is an authentication image, extract the information that will + be used to authenticate the next image in the CoT. + +In Diagram 1, each component is responsible for one or more of these operations. +The responsibilities are briefly described below. + +TF-A Generic code and IO framework (GEN/IO) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These components are responsible for initiating the authentication process for a +particular image in BL1 or BL2. For each BL image that requires authentication, +the Generic code asks recursively the Authentication module what is the parent +image until either an authenticated image or the ROT is reached. Then the +Generic code calls the IO framework to load the image and calls the +Authentication module to authenticate it, following the CoT from ROT to Image. + +TF-A Platform Port (PP) +^^^^^^^^^^^^^^^^^^^^^^^ + +The platform is responsible for: + +#. Specifying the CoT for each image that needs to be authenticated. Details of + how a CoT can be specified by the platform are explained later. The platform + also specifies the authentication methods and the parsing method used for + each image. + +#. Statically allocating memory for each parameter in each image which is + used for verifying the CoT, e.g. memory for public keys, hashes etc. + +#. Providing the ROTPK or a hash of it. + +#. Providing additional information to the IPM to enable it to identify and + extract authentication parameters contained in an image, e.g. if the + parameters are stored as X509v3 extensions, the corresponding OID must be + provided. + +#. Fulfill any other memory requirements of the IPM and the CM (not currently + described in this document). + +#. Export functions to verify an image which uses an authentication method that + cannot be interpreted by the CM, e.g. if an image has to be verified using a + NV counter, then the value of the counter to compare with can only be + provided by the platform. + +#. Export a custom IPM if a proprietary image format is being used (described + later). + +Authentication Module (AM) +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is responsible for: + +#. Providing the necessary abstraction mechanisms to describe a CoT. Amongst + other things, the authentication and image parsing methods must be specified + by the PP in the CoT. + +#. Verifying the CoT passed by GEN by utilising functionality exported by the + PP, IPM and CM. + +#. Tracking which images have been verified. In case an image is a part of + multiple CoTs then it should be verified only once e.g. the Trusted World + Key Certificate in the TBBR-Client spec. contains information to verify + SCP_BL2, BL31, BL32 each of which have a separate CoT. (This + responsibility has not been described in this document but should be + trivial to implement). + +#. Reusing memory meant for a data image to verify authentication images e.g. + in the CoT described in Diagram 2, each certificate can be loaded and + verified in the memory reserved by the platform for the BL31 image. By the + time BL31 (the data image) is loaded, all information to authenticate it + will have been extracted from the parent image i.e. BL31 content + certificate. It is assumed that the size of an authentication image will + never exceed the size of a data image. It should be possible to verify this + at build time using asserts. + +Cryptographic Module (CM) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The CM is responsible for providing an API to: + +#. Verify a digital signature. +#. Verify a hash. + +The CM does not include any cryptography related code, but it relies on an +external library to perform the cryptographic operations. A Crypto-Library (CL) +linking the CM and the external library must be implemented. The following +functions must be provided by the CL: + +.. code:: c + + void (*init)(void); + 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); + int (*verify_hash)(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + +These functions are registered in the CM using the macro: + +.. code:: c + + REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash); + +``_name`` must be a string containing the name of the CL. This name is used for +debugging purposes. + +Image Parser Module (IPM) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The IPM is responsible for: + +#. Checking the integrity of each image loaded by the IO framework. +#. Extracting parameters used for authenticating an image based upon a + description provided by the platform in the CoT descriptor. + +Images may have different formats (for example, authentication images could be +x509v3 certificates, signed ELF files or any other platform specific format). +The IPM allows to register an Image Parser Library (IPL) for every image format +used in the CoT. This library must implement the specific methods to parse the +image. The IPM obtains the image format from the CoT and calls the right IPL to +check the image integrity and extract the authentication parameters. + +See Section "Describing the image parsing methods" for more details about the +mechanism the IPM provides to define and register IPLs. + +Authentication methods +~~~~~~~~~~~~~~~~~~~~~~ + +The AM supports the following authentication methods: + +#. Hash +#. Digital signature + +The platform may specify these methods in the CoT in case it decides to define +a custom CoT instead of reusing a predefined one. + +If a data image uses multiple methods, then all the methods must be a part of +the same CoT. The number and type of parameters are method specific. These +parameters should be obtained from the parent image using the IPM. + +#. Hash + + Parameters: + + #. A pointer to data to hash + #. Length of the data + #. A pointer to the hash + #. Length of the hash + + The hash will be represented by the DER encoding of the following ASN.1 + type: + + :: + + DigestInfo ::= SEQUENCE { + digestAlgorithm DigestAlgorithmIdentifier, + digest Digest + } + + This ASN.1 structure makes it possible to remove any assumption about the + type of hash algorithm used as this information accompanies the hash. This + should allow the Cryptography Library (CL) to support multiple hash + algorithm implementations. + +#. Digital Signature + + Parameters: + + #. A pointer to data to sign + #. Length of the data + #. Public Key Algorithm + #. Public Key value + #. Digital Signature Algorithm + #. Digital Signature value + + The Public Key parameters will be represented by the DER encoding of the + following ASN.1 type: + + :: + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}}, + subjectPublicKey BIT STRING } + + The Digital Signature Algorithm will be represented by the DER encoding of + the following ASN.1 types. + + :: + + AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE { + algorithm ALGORITHM.&id({IOSet}), + parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL + } + + The digital signature will be represented by: + + :: + + signature ::= BIT STRING + +The authentication framework will use the image descriptor to extract all the +information related to authentication. + +Specifying a Chain of Trust +--------------------------- + +A CoT can be described as a set of image descriptors linked together in a +particular order. The order dictates the sequence in which they must be +verified. Each image has a set of properties which allow the AM to verify it. +These properties are described below. + +The PP is responsible for defining a single or multiple CoTs for a data image. +Unless otherwise specified, the data structures described in the following +sections are populated by the PP statically. + +Describing the image parsing methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The parsing method refers to the format of a particular image. For example, an +authentication image that represents a certificate could be in the X.509v3 +format. A data image that represents a boot loader stage could be in raw binary +or ELF format. The IPM supports three parsing methods. An image has to use one +of the three methods described below. An IPL is responsible for interpreting a +single parsing method. There has to be one IPL for every method used by the +platform. + +#. Raw format: This format is effectively a nop as an image using this method + is treated as being in raw binary format e.g. boot loader images used by + TF-A. This method should only be used by data images. + +#. X509V3 method: This method uses industry standards like X.509 to represent + PKI certificates (authentication images). It is expected that open source + libraries will be available which can be used to parse an image represented + by this method. Such libraries can be used to write the corresponding IPL + e.g. the X.509 parsing library code in mbed TLS. + +#. Platform defined method: This method caters for platform specific + proprietary standards to represent authentication or data images. For + example, The signature of a data image could be appended to the data image + raw binary. A header could be prepended to the combined blob to specify the + extents of each component. The platform will have to implement the + corresponding IPL to interpret such a format. + +The following enum can be used to define these three methods. + +.. code:: c + + typedef enum img_type_enum { + IMG_RAW, /* Binary image */ + IMG_PLAT, /* Platform specific format */ + IMG_CERT, /* X509v3 certificate */ + IMG_MAX_TYPES, + } img_type_t; + +An IPL must provide functions with the following prototypes: + +.. code:: c + + 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); + +An IPL for each type must be registered using the following macro: + +.. code:: c + + REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param) + +- ``_type``: one of the types described above. +- ``_name``: a string containing the IPL name for debugging purposes. +- ``_init``: initialization function pointer. +- ``_check_int``: check image integrity function pointer. +- ``_get_param``: extract authentication parameter function pointer. + +The ``init()`` function will be used to initialize the IPL. + +The ``check_integrity()`` function is passed a pointer to the memory where the +image has been loaded by the IO framework and the image length. It should ensure +that the image is in the format corresponding to the parsing method and has not +been tampered with. For example, RFC-2459 describes a validation sequence for an +X.509 certificate. + +The ``get_auth_param()`` function is passed a parameter descriptor containing +information about the parameter (``type_desc`` and ``cookie``) to identify and +extract the data corresponding to that parameter from an image. This data will +be used to verify either the current or the next image in the CoT sequence. + +Each image in the CoT will specify the parsing method it uses. This information +will be used by the IPM to find the right parser descriptor for the image. + +Describing the authentication method(s) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As part of the CoT, each image has to specify one or more authentication methods +which will be used to verify it. As described in the Section "Authentication +methods", there are three methods supported by the AM. + +.. code:: c + + typedef enum { + AUTH_METHOD_NONE, + AUTH_METHOD_HASH, + AUTH_METHOD_SIG, + AUTH_METHOD_NUM + } auth_method_type_t; + +The AM defines the type of each parameter used by an authentication method. It +uses this information to: + +#. Specify to the ``get_auth_param()`` function exported by the IPM, which + parameter should be extracted from an image. + +#. Correctly marshall the parameters while calling the verification function + exported by the CM and PP. + +#. Extract authentication parameters from a parent image in order to verify a + child image e.g. to verify the certificate image, the public key has to be + obtained from the parent image. + +.. code:: c + + typedef 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_type_t; + +The AM defines the following structure to identify an authentication parameter +required to verify an image. + +.. code:: c + + typedef struct auth_param_type_desc_s { + auth_param_type_t type; + void *cookie; + } auth_param_type_desc_t; + +``cookie`` is used by the platform to specify additional information to the IPM +which enables it to uniquely identify the parameter that should be extracted +from an image. For example, the hash of a BL3x image in its corresponding +content certificate is stored in an X509v3 custom extension field. An extension +field can only be identified using an OID. In this case, the ``cookie`` could +contain the pointer to the OID defined by the platform for the hash extension +field while the ``type`` field could be set to ``AUTH_PARAM_HASH``. A value of 0 for +the ``cookie`` field means that it is not used. + +For each method, the AM defines a structure with the parameters required to +verify the image. + +.. code:: c + + /* + * 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 *tbs; /* Data signed */ + } auth_method_param_sig_t; + +The AM defines the following structure to describe an authentication method for +verifying an image + +.. code:: c + + /* + * 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; + } param; + } auth_method_desc_t; + +Using the method type specified in the ``type`` field, the AM finds out what field +needs to access within the ``param`` union. + +Storing Authentication parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A parameter described by ``auth_param_type_desc_t`` to verify an image could be +obtained from either the image itself or its parent image. The memory allocated +for loading the parent image will be reused for loading the child image. Hence +parameters which are obtained from the parent for verifying a child image need +to have memory allocated for them separately where they can be stored. This +memory must be statically allocated by the platform port. + +The AM defines the following structure to store the data corresponding to an +authentication parameter. + +.. code:: c + + typedef struct auth_param_data_desc_s { + void *auth_param_ptr; + unsigned int auth_param_len; + } auth_param_data_desc_t; + +The ``auth_param_ptr`` field is initialized by the platform. The ``auth_param_len`` +field is used to specify the length of the data in the memory. + +For parameters that can be obtained from the child image itself, the IPM is +responsible for populating the ``auth_param_ptr`` and ``auth_param_len`` fields +while executing the ``img_get_auth_param()`` function. + +The AM defines the following structure to enable an image to describe the +parameters that should be extracted from it and used to verify the next image +(child) in a CoT. + +.. code:: c + + typedef struct auth_param_desc_s { + auth_param_type_desc_t type_desc; + auth_param_data_desc_t data; + } auth_param_desc_t; + +Describing an image in a CoT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An image in a CoT is a consolidation of the following aspects of a CoT described +above. + +#. A unique identifier specified by the platform which allows the IO framework + to locate the image in a FIP and load it in the memory reserved for the data + image in the CoT. + +#. A parsing method which is used by the AM to find the appropriate IPM. + +#. Authentication methods and their parameters as described in the previous + section. These are used to verify the current image. + +#. Parameters which are used to verify the next image in the current CoT. These + parameters are specified only by authentication images and can be extracted + from the current image once it has been verified. + +The following data structure describes an image in a CoT. + +.. code:: c + + typedef struct auth_img_desc_s { + unsigned int img_id; + const struct auth_img_desc_s *parent; + img_type_t img_type; + const auth_method_desc_t *const img_auth_methods; + const auth_param_desc_t *const authenticated_data; + } auth_img_desc_t; + +A CoT is defined as an array of pointers to ``auth_image_desc_t`` structures +linked together by the ``parent`` field. Those nodes with no parent must be +authenticated using the ROTPK stored in the platform. + +Implementation example +---------------------- + +This section is a detailed guide explaining a trusted boot implementation using +the authentication framework. This example corresponds to the Applicative +Functional Mode (AFM) as specified in the TBBR-Client document. It is +recommended to read this guide along with the source code. + +The TBBR CoT +~~~~~~~~~~~~ + +CoT specific to BL1 and BL2 can be found in ``drivers/auth/tbbr/tbbr_cot_bl1.c`` +and ``drivers/auth/tbbr/tbbr_cot_bl2.c`` respectively. The common CoT used across +BL1 and BL2 can be found in ``drivers/auth/tbbr/tbbr_cot_common.c``. +This CoT consists of an array of pointers to image descriptors and it is +registered in the framework using the macro ``REGISTER_COT(cot_desc)``, where +``cot_desc`` must be the name of the array (passing a pointer or any other +type of indirection will cause the registration process to fail). + +The number of images participating in the boot process depends on the CoT. +There is, however, a minimum set of images that are mandatory in TF-A and thus +all CoTs must present: + +- ``BL2`` +- ``SCP_BL2`` (platform specific) +- ``BL31`` +- ``BL32`` (optional) +- ``BL33`` + +The TBBR specifies the additional certificates that must accompany these images +for a proper authentication. Details about the TBBR CoT may be found in the +:ref:`Trusted Board Boot` document. + +Following the :ref:`Porting Guide`, a platform must provide unique +identifiers for all the images and certificates that will be loaded during the +boot process. If a platform is using the TBBR as a reference for trusted boot, +these identifiers can be obtained from ``include/common/tbbr/tbbr_img_def.h``. +Arm platforms include this file in ``include/plat/arm/common/arm_def.h``. Other +platforms may also include this file or provide their own identifiers. + +**Important**: the authentication module uses these identifiers to index the +CoT array, so the descriptors location in the array must match the identifiers. + +Each image descriptor must specify: + +- ``img_id``: the corresponding image unique identifier defined by the platform. +- ``img_type``: the image parser module uses the image type to call the proper + parsing library to check the image integrity and extract the required + authentication parameters. Three types of images are currently supported: + + - ``IMG_RAW``: image is a raw binary. No parsing functions are available, + other than reading the whole image. + - ``IMG_PLAT``: image format is platform specific. The platform may use this + type for custom images not directly supported by the authentication + framework. + - ``IMG_CERT``: image is an x509v3 certificate. + +- ``parent``: pointer to the parent image descriptor. The parent will contain + the information required to authenticate the current image. If the parent + is NULL, the authentication parameters will be obtained from the platform + (i.e. the BL2 and Trusted Key certificates are signed with the ROT private + key, whose public part is stored in the platform). +- ``img_auth_methods``: this points to an array which defines the + authentication methods that must be checked to consider an image + authenticated. Each method consists of a type and a list of parameter + descriptors. A parameter descriptor consists of a type and a cookie which + will point to specific information required to extract that parameter from + the image (i.e. if the parameter is stored in an x509v3 extension, the + cookie will point to the extension OID). Depending on the method type, a + different number of parameters must be specified. This pointer should not be + NULL. + Supported methods are: + + - ``AUTH_METHOD_HASH``: the hash of the image must match the hash extracted + from the parent image. The following parameter descriptors must be + specified: + + - ``data``: data to be hashed (obtained from current image) + - ``hash``: reference hash (obtained from parent image) + + - ``AUTH_METHOD_SIG``: the image (usually a certificate) must be signed with + the private key whose public part is extracted from the parent image (or + the platform if the parent is NULL). The following parameter descriptors + must be specified: + + - ``pk``: the public key (obtained from parent image) + - ``sig``: the digital signature (obtained from current image) + - ``alg``: the signature algorithm used (obtained from current image) + - ``data``: the data to be signed (obtained from current image) + +- ``authenticated_data``: this array pointer indicates what authentication + parameters must be extracted from an image once it has been authenticated. + Each parameter consists of a parameter descriptor and the buffer + address/size to store the parameter. The CoT is responsible for allocating + the required memory to store the parameters. This pointer may be NULL. + +In the ``tbbr_cot*.c`` file, a set of buffers are allocated to store the parameters +extracted from the certificates. In the case of the TBBR CoT, these parameters +are hashes and public keys. In DER format, an RSA-4096 public key requires 550 +bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication +process, some of the buffers may be reused at different stages during the boot. + +Next in that file, the parameter descriptors are defined. These descriptors will +be used to extract the parameter data from the corresponding image. + +Example: the BL31 Chain of Trust +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Four image descriptors form the BL31 Chain of Trust: + +.. code:: c + + static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } + }; + static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } + }; + static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }; + 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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } + }; + +The **Trusted Key certificate** is signed with the ROT private key and contains +the Trusted World public key and the Non-Trusted World public key as x509v3 +extensions. This must be specified in the image descriptor using the +``img_auth_methods`` and ``authenticated_data`` arrays, respectively. + +The Trusted Key certificate is authenticated by checking its digital signature +using the ROTPK. Four parameters are required to check a signature: the public +key, the algorithm, the signature and the data that has been signed. Therefore, +four parameter descriptors must be specified with the authentication method: + +- ``subject_pk``: parameter descriptor of type ``AUTH_PARAM_PUB_KEY``. This type + is used to extract a public key from the parent image. If the cookie is an + OID, the key is extracted from the corresponding x509v3 extension. If the + cookie is NULL, the subject public key is retrieved. In this case, because + the parent image is NULL, the public key is obtained from the platform + (this key will be the ROTPK). +- ``sig``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to extract + the signature from the certificate. +- ``sig_alg``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to + extract the signature algorithm from the certificate. +- ``raw_data``: parameter descriptor of type ``AUTH_PARAM_RAW_DATA``. It is used + to extract the data to be signed from the certificate. + +Once the signature has been checked and the certificate authenticated, the +Trusted World public key needs to be extracted from the certificate. A new entry +is created in the ``authenticated_data`` array for that purpose. In that entry, +the corresponding parameter descriptor must be specified along with the buffer +address to store the parameter value. In this case, the ``trusted_world_pk`` +descriptor is used to extract the public key from an x509v3 extension with OID +``TRUSTED_WORLD_PK_OID``. The BL31 key certificate will use this descriptor as +parameter in the signature authentication method. The key is stored in the +``trusted_world_pk_buf`` buffer. + +The **BL31 Key certificate** is authenticated by checking its digital signature +using the Trusted World public key obtained previously from the Trusted Key +certificate. In the image descriptor, we specify a single authentication method +by signature whose public key is the ``trusted_world_pk``. Once this certificate +has been authenticated, we have to extract the BL31 public key, stored in the +extension specified by ``soc_fw_content_pk``. This key will be copied to the +``content_pk_buf`` buffer. + +The **BL31 certificate** is authenticated by checking its digital signature +using the BL31 public key obtained previously from the BL31 Key certificate. +We specify the authentication method using ``soc_fw_content_pk`` as public key. +After authentication, we need to extract the BL31 hash, stored in the extension +specified by ``soc_fw_hash``. This hash will be copied to the +``soc_fw_hash_buf`` buffer. + +The **BL31 image** is authenticated by calculating its hash and matching it +with the hash obtained from the BL31 certificate. The image descriptor contains +a single authentication method by hash. The parameters to the hash method are +the reference hash, ``soc_fw_hash``, and the data to be hashed. In this case, +it is the whole image, so we specify ``raw_data``. + +The image parser library +~~~~~~~~~~~~~~~~~~~~~~~~ + +The image parser module relies on libraries to check the image integrity and +extract the authentication parameters. The number and type of parser libraries +depend on the images used in the CoT. Raw images do not need a library, so +only an x509v3 library is required for the TBBR CoT. + +Arm platforms will use an x509v3 library based on mbed TLS. This library may be +found in ``drivers/auth/mbedtls/mbedtls_x509_parser.c``. It exports three +functions: + +.. code:: c + + 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); + +The library is registered in the framework using the macro +``REGISTER_IMG_PARSER_LIB()``. Each time the image parser module needs to access +an image of type ``IMG_CERT``, it will call the corresponding function exported +in this file. + +The build system must be updated to include the corresponding library and +mbed TLS sources. Arm platforms use the ``arm_common.mk`` file to pull the +sources. + +The cryptographic library +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The cryptographic module relies on a library to perform the required operations, +i.e. verify a hash or a digital signature. Arm platforms will use a library +based on mbed TLS, which can be found in +``drivers/auth/mbedtls/mbedtls_crypto.c``. This library is registered in the +authentication framework using the macro ``REGISTER_CRYPTO_LIB()`` and exports +four functions: + +.. code:: c + + void init(void); + 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); + int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + 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) + +The mbedTLS library algorithm support is configured by both the +``TF_MBEDTLS_KEY_ALG`` and ``TF_MBEDTLS_KEY_SIZE`` variables. + +- ``TF_MBEDTLS_KEY_ALG`` can take in 3 values: `rsa`, `ecdsa` or `rsa+ecdsa`. + This variable allows the Makefile to include the corresponding sources in + the build for the various algorithms. Setting the variable to `rsa+ecdsa` + enables support for both rsa and ecdsa algorithms in the mbedTLS library. + +- ``TF_MBEDTLS_KEY_SIZE`` sets the supported RSA key size for TFA. Valid values + include 1024, 2048, 3072 and 4096. + +- ``TF_MBEDTLS_USE_AES_GCM`` enables the authenticated decryption support based + on AES-GCM algorithm. Valid values are 0 and 1. + +.. note:: + If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can + be defined in the platform Makefile. It will make mbed TLS use an + implementation of SHA-256 with smaller memory footprint (~1.5 KB less) but + slower (~30%). + +-------------- + +*Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.* + +.. _TBBR-Client specification: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a diff --git a/arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst b/arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst new file mode 100644 index 0000000..af0e769 --- /dev/null +++ b/arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst @@ -0,0 +1,605 @@ +Arm CPU Specific Build Macros +============================= + +This document describes the various build options present in the CPU specific +operations framework to enable errata workarounds and to enable optimizations +for a specific CPU on a platform. + +Security Vulnerability Workarounds +---------------------------------- + +TF-A exports a series of build flags which control which security +vulnerability workarounds should be applied at runtime. + +- ``WORKAROUND_CVE_2017_5715``: Enables the security workaround for + `CVE-2017-5715`_. This flag can be set to 0 by the platform if none + of the PEs in the system need the workaround. Setting this flag to 0 provides + no performance benefit for non-affected platforms, it just helps to comply + with the recommendation in the spec regarding workaround discovery. + Defaults to 1. + +- ``WORKAROUND_CVE_2018_3639``: Enables the security workaround for + `CVE-2018-3639`_. Defaults to 1. The TF-A project recommends to keep + the default value of 1 even on platforms that are unaffected by + CVE-2018-3639, in order to comply with the recommendation in the spec + regarding workaround discovery. + +- ``DYNAMIC_WORKAROUND_CVE_2018_3639``: Enables dynamic mitigation for + `CVE-2018-3639`_. This build option should be set to 1 if the target + platform contains at least 1 CPU that requires dynamic mitigation. + Defaults to 0. + +- ``WORKAROUND_CVE_2022_23960``: Enables mitigation for `CVE-2022-23960`_. + This build option should be set to 1 if the target platform contains at + least 1 CPU that requires this mitigation. Defaults to 1. + +.. _arm_cpu_macros_errata_workarounds: + +CPU Errata Workarounds +---------------------- + +TF-A exports a series of build flags which control the errata workarounds that +are applied to each CPU by the reset handler. The errata details can be found +in the CPU specific errata documents published by Arm: + +- `Cortex-A53 MPCore Software Developers Errata Notice`_ +- `Cortex-A57 MPCore Software Developers Errata Notice`_ +- `Cortex-A72 MPCore Software Developers Errata Notice`_ + +The errata workarounds are implemented for a particular revision or a set of +processor revisions. This is checked by the reset handler at runtime. Each +errata workaround is identified by its ``ID`` as specified in the processor's +errata notice document. The format of the define used to enable/disable the +errata workaround is ``ERRATA__``, where the ``Processor name`` +is for example ``A57`` for the ``Cortex_A57`` CPU. + +Refer to :ref:`firmware_design_cpu_errata_reporting` for information on how to +write errata workaround functions. + +All workarounds are disabled by default. The platform is responsible for +enabling these workarounds according to its requirement by defining the +errata workaround build flags in the platform specific makefile. In case +these workarounds are enabled for the wrong CPU revision then the errata +workaround is not applied. In the DEBUG build, this is indicated by +printing a warning to the crash console. + +In the current implementation, a platform which has more than 1 variant +with different revisions of a processor has no runtime mechanism available +for it to specify which errata workarounds should be enabled or not. + +The value of the build flags is 0 by default, that is, disabled. A value of 1 +will enable it. + +For Cortex-A9, the following errata build flags are defined : + +- ``ERRATA_A9_794073``: This applies errata 794073 workaround to Cortex-A9 + CPU. This needs to be enabled for all revisions of the CPU. + +For Cortex-A15, the following errata build flags are defined : + +- ``ERRATA_A15_816470``: This applies errata 816470 workaround to Cortex-A15 + CPU. This needs to be enabled only for revision >= r3p0 of the CPU. + +- ``ERRATA_A15_827671``: This applies errata 827671 workaround to Cortex-A15 + CPU. This needs to be enabled only for revision >= r3p0 of the CPU. + +For Cortex-A17, the following errata build flags are defined : + +- ``ERRATA_A17_852421``: This applies errata 852421 workaround to Cortex-A17 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A17_852423``: This applies errata 852423 workaround to Cortex-A17 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +For Cortex-A35, the following errata build flags are defined : + +- ``ERRATA_A35_855472``: This applies errata 855472 workaround to Cortex-A35 + CPUs. This needs to be enabled only for revision r0p0 of Cortex-A35. + +For Cortex-A53, the following errata build flags are defined : + +- ``ERRATA_A53_819472``: This applies errata 819472 workaround to all + CPUs. This needs to be enabled only for revision <= r0p1 of Cortex-A53. + +- ``ERRATA_A53_824069``: This applies errata 824069 workaround to all + CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53. + +- ``ERRATA_A53_826319``: This applies errata 826319 workaround to Cortex-A53 + CPU. This needs to be enabled only for revision <= r0p2 of the CPU. + +- ``ERRATA_A53_827319``: This applies errata 827319 workaround to all + CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53. + +- ``ERRATA_A53_835769``: This applies erratum 835769 workaround at compile and + link time to Cortex-A53 CPU. This needs to be enabled for some variants of + revision <= r0p4. This workaround can lead the linker to create ``*.stub`` + sections. + +- ``ERRATA_A53_836870``: This applies errata 836870 workaround to Cortex-A53 + CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From + r0p4 and onwards, this errata is enabled by default in hardware. + +- ``ERRATA_A53_843419``: This applies erratum 843419 workaround at link time + to Cortex-A53 CPU. This needs to be enabled for some variants of revision + <= r0p4. This workaround can lead the linker to emit ``*.stub`` sections + which are 4kB aligned. + +- ``ERRATA_A53_855873``: This applies errata 855873 workaround to Cortex-A53 + CPUs. Though the erratum is present in every revision of the CPU, + this workaround is only applied to CPUs from r0p3 onwards, which feature + a chicken bit in CPUACTLR_EL1 to enable a hardware workaround. + Earlier revisions of the CPU have other errata which require the same + workaround in software, so they should be covered anyway. + +- ``ERRATA_A53_1530924``: This applies errata 1530924 workaround to all + revisions of Cortex-A53 CPU. + +For Cortex-A55, the following errata build flags are defined : + +- ``ERRATA_A55_768277``: This applies errata 768277 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_778703``: This applies errata 778703 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_798797``: This applies errata 798797 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_846532``: This applies errata 846532 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +- ``ERRATA_A55_903758``: This applies errata 903758 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +- ``ERRATA_A55_1221012``: This applies errata 1221012 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision <= r1p0 of the CPU. + +- ``ERRATA_A55_1530923``: This applies errata 1530923 workaround to all + revisions of Cortex-A55 CPU. + +For Cortex-A57, the following errata build flags are defined : + +- ``ERRATA_A57_806969``: This applies errata 806969 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_813419``: This applies errata 813419 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_813420``: This applies errata 813420 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_814670``: This applies errata 814670 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_817169``: This applies errata 817169 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +- ``ERRATA_A57_826974``: This applies errata 826974 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_826977``: This applies errata 826977 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_828024``: This applies errata 828024 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_829520``: This applies errata 829520 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A57_833471``: This applies errata 833471 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p3 of the CPU. + +- ``ERRATA_A57_1319537``: This applies errata 1319537 workaround to all + revisions of Cortex-A57 CPU. + +For Cortex-A72, the following errata build flags are defined : + +- ``ERRATA_A72_859971``: This applies errata 859971 workaround to Cortex-A72 + CPU. This needs to be enabled only for revision <= r0p3 of the CPU. + +- ``ERRATA_A72_1319367``: This applies errata 1319367 workaround to all + revisions of Cortex-A72 CPU. + +For Cortex-A73, the following errata build flags are defined : + +- ``ERRATA_A73_852427``: This applies errata 852427 workaround to Cortex-A73 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A73_855423``: This applies errata 855423 workaround to Cortex-A73 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +For Cortex-A75, the following errata build flags are defined : + +- ``ERRATA_A75_764081``: This applies errata 764081 workaround to Cortex-A75 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A75_790748``: This applies errata 790748 workaround to Cortex-A75 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +For Cortex-A76, the following errata build flags are defined : + +- ``ERRATA_A76_1073348``: This applies errata 1073348 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r1p0 of the CPU. + +- ``ERRATA_A76_1130799``: This applies errata 1130799 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_A76_1220197``: This applies errata 1220197 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_A76_1257314``: This applies errata 1257314 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1262606``: This applies errata 1262606 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1262888``: This applies errata 1262888 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1791580``: This applies errata 1791580 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r4p0 of the CPU. + +- ``ERRATA_A76_1165522``: This applies errata 1165522 workaround to all + revisions of Cortex-A76 CPU. This errata is fixed in r3p0 but due to + limitation of errata framework this errata is applied to all revisions + of Cortex-A76 CPU. + +- ``ERRATA_A76_1868343``: This applies errata 1868343 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r4p0 of the CPU. + +- ``ERRATA_A76_1946160``: This applies errata 1946160 workaround to Cortex-A76 + CPU. This needs to be enabled only for revisions r3p0 - r4p1 of the CPU. + +For Cortex-A77, the following errata build flags are defined : + +- ``ERRATA_A77_1508412``: This applies errata 1508412 workaround to Cortex-A77 + CPU. This needs to be enabled only for revision <= r1p0 of the CPU. + +- ``ERRATA_A77_1925769``: This applies errata 1925769 workaround to Cortex-A77 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A77_1946167``: This applies errata 1946167 workaround to Cortex-A77 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A77_1791578``: This applies errata 1791578 workaround to Cortex-A77 + CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open. + +For Cortex-A78, the following errata build flags are defined : + +- ``ERRATA_A78_1688305``: This applies errata 1688305 workaround to Cortex-A78 + CPU. This needs to be enabled only for revision r0p0 - r1p0 of the CPU. + +- ``ERRATA_A78_1941498``: This applies errata 1941498 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU. + +- ``ERRATA_A78_1951500``: This applies errata 1951500 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r1p0 and r1p1, r0p0 has the same + issue but there is no workaround for that revision. + +- ``ERRATA_A78_1821534``: This applies errata 1821534 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r0p0 and r1p0. + +- ``ERRATA_A78_1952683``: This applies errata 1952683 workaround to Cortex-A78 + CPU. This needs to be enabled for revision r0p0, it is fixed in r1p0. + +- ``ERRATA_A78_2132060``: This applies errata 2132060 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2. It + is still open. + +- ``ERRATA_A78_2242635``: This applies errata 2242635 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r1p0, r1p1, and r1p2. The issue + is present in r0p0 but there is no workaround. It is still open. + +For Cortex-A78 AE, the following errata build flags are defined : + +- ``ERRATA_A78_AE_1941500`` : This applies errata 1941500 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. + This erratum is still open. + +- ``ERRATA_A78_AE_1951502`` : This applies errata 1951502 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This + erratum is still open. + +- ``ERRATA_A78_AE_2376748`` : This applies errata 2376748 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This + erratum is still open. + +- ``ERRATA_A78_AE_2395408`` : This applies errata 2395408 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This + erratum is still open. + +For Neoverse N1, the following errata build flags are defined : + +- ``ERRATA_N1_1073348``: This applies errata 1073348 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision r0p0 and r1p0 of the CPU. + +- ``ERRATA_N1_1130799``: This applies errata 1130799 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_N1_1165347``: This applies errata 1165347 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_N1_1207823``: This applies errata 1207823 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_N1_1220197``: This applies errata 1220197 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_N1_1257314``: This applies errata 1257314 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1262606``: This applies errata 1262606 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1262888``: This applies errata 1262888 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1275112``: This applies errata 1275112 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1315703``: This applies errata 1315703 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1542419``: This applies errata 1542419 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revisions r3p0 - r4p0 of the CPU. + +- ``ERRATA_N1_1868343``: This applies errata 1868343 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r4p0 of the CPU. + +- ``ERRATA_N1_1946160``: This applies errata 1946160 workaround to Neoverse-N1 + CPU. This needs to be enabled for revisions r3p0, r3p1, r4p0, and r4p1, for + revisions r0p0, r1p0, and r2p0 there is no workaround. + +For Neoverse V1, the following errata build flags are defined : + +- ``ERRATA_V1_1774420``: This applies errata 1774420 workaround to Neoverse-V1 + CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed + in r1p1. + +- ``ERRATA_V1_1791573``: This applies errata 1791573 workaround to Neoverse-V1 + CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed + in r1p1. + +- ``ERRATA_V1_1852267``: This applies errata 1852267 workaround to Neoverse-V1 + CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed + in r1p1. + +- ``ERRATA_V1_1925756``: This applies errata 1925756 workaround to Neoverse-V1 + CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open. + +- ``ERRATA_V1_1940577``: This applies errata 1940577 workaround to Neoverse-V1 + CPU. This needs to be enabled only for revision r1p0 and r1p1 of the + CPU. + +- ``ERRATA_V1_1966096``: This applies errata 1966096 workaround to Neoverse-V1 + CPU. This needs to be enabled for revisions r1p0 and r1p1 of the CPU, the + issue is present in r0p0 as well but there is no workaround for that + revision. It is still open. + +- ``ERRATA_V1_2139242``: This applies errata 2139242 workaround to Neoverse-V1 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the + CPU. It is still open. + +- ``ERRATA_V1_2108267``: This applies errata 2108267 workaround to Neoverse-V1 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU. + It is still open. + +- ``ERRATA_V1_2216392``: This applies errata 2216392 workaround to Neoverse-V1 + CPU. This needs to be enabled for revisions r1p0 and r1p1 of the CPU, the + issue is present in r0p0 as well but there is no workaround for that + revision. It is still open. + +For Cortex-A710, the following errata build flags are defined : + +- ``ERRATA_A710_1987031``: This applies errata 1987031 workaround to + Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU. It is still open. + +- ``ERRATA_A710_2081180``: This applies errata 2081180 workaround to + Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU. It is still open. + +- ``ERRATA_A710_2055002``: This applies errata 2055002 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r1p0, r2p0 of the CPU + and is still open. + +- ``ERRATA_A710_2017096``: This applies errata 2017096 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is still open. + +- ``ERRATA_A710_2083908``: This applies errata 2083908 workaround to + Cortex-A710 CPU. This needs to be enabled for revision r2p0 of the CPU and + is still open. + +- ``ERRATA_A710_2058056``: This applies errata 2058056 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is still open. + +- ``ERRATA_A710_2267065``: This applies errata 2267065 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is fixed in r2p1. + +- ``ERRATA_A710_2136059``: This applies errata 2136059 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is fixed in r2p1. + +- ``ERRATA_A710_2282622``: This applies errata 2282622 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is fixed in r2p1. + +For Neoverse N2, the following errata build flags are defined : + +- ``ERRATA_N2_2002655``: This applies errata 2002655 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU, it is still open. + +- ``ERRATA_N2_2067956``: This applies errata 2067956 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2025414``: This applies errata 2025414 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2189731``: This applies errata 2189731 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2138956``: This applies errata 2138956 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2138953``: This applies errata 2138953 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2242415``: This applies errata 2242415 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2138958``: This applies errata 2138958 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2242400``: This applies errata 2242400 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2280757``: This applies errata 2280757 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +For Cortex-X2, the following errata build flags are defined : + +- ``ERRATA_X2_2002765``: This applies errata 2002765 workaround to Cortex-X2 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r2p0 of the CPU, + it is still open. + +- ``ERRATA_X2_2058056``: This applies errata 2058056 workaround to Cortex-X2 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r2p0 of the CPU, + it is still open. + +- ``ERRATA_X2_2083908``: This applies errata 2083908 workaround to Cortex-X2 + CPU. This needs to be enabled for revision r2p0 of the CPU, it is still open. + +- ``ERRATA_X2_2017096``: This applies errata 2017096 workaround to + Cortex-X2 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU, it is fixed in r2p1. + +- ``ERRATA_X2_2081180``: This applies errata 2081180 workaround to + Cortex-X2 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU, it is fixed in r2p1. + +- ``ERRATA_X2_2216384``: This applies errata 2216384 workaround to + Cortex-X2 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU, it is fixed in r2p1. + +For Cortex-A510, the following errata build flags are defined : + +- ``ERRATA_A510_1922240``: This applies errata 1922240 workaround to + Cortex-A510 CPU. This needs to be enabled only for revision r0p0, it is + fixed in r0p1. + +- ``ERRATA_A510_2288014``: This applies errata 2288014 workaround to + Cortex-A510 CPU. This needs to be enabled only for revisions r0p0, r0p1, + r0p2, r0p3 and r1p0, it is fixed in r1p1. + +- ``ERRATA_A510_2042739``: This applies errata 2042739 workaround to + Cortex-A510 CPU. This needs to be enabled only for revisions r0p0, r0p1 and + r0p2, it is fixed in r0p3. + +- ``ERRATA_A510_2041909``: This applies errata 2041909 workaround to + Cortex-A510 CPU. This needs to be enabled only for revision r0p2 and is fixed + in r0p3. The issue is also present in r0p0 and r0p1 but there is no + workaround for those revisions. + +- ``ERRATA_A510_2250311``: This applies errata 2250311 workaround to + Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2, + r0p3 and r1p0, it is fixed in r1p1. This workaround disables MPMM even if + ENABLE_MPMM=1. + +- ``ERRATA_A510_2218950``: This applies errata 2218950 workaround to + Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2, + r0p3 and r1p0, it is fixed in r1p1. + +- ``ERRATA_A510_2172148``: This applies errata 2172148 workaround to + Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2, + r0p3 and r1p0, it is fixed in r1p1. + +DSU Errata Workarounds +---------------------- + +Similar to CPU errata, TF-A also implements workarounds for DSU (DynamIQ +Shared Unit) errata. The DSU errata details can be found in the respective Arm +documentation: + +- `Arm DSU Software Developers Errata Notice`_. + +Each erratum is identified by an ``ID``, as defined in the DSU errata notice +document. Thus, the build flags which enable/disable the errata workarounds +have the format ``ERRATA_DSU_``. The implementation and application logic +of DSU errata workarounds are similar to `CPU errata workarounds`_. + +For DSU errata, the following build flags are defined: + +- ``ERRATA_DSU_798953``: This applies errata 798953 workaround for the + affected DSU configurations. This errata applies only for those DSUs that + revision is r0p0 (on r0p1 it is fixed). However, please note that this + workaround results in increased DSU power consumption on idle. + +- ``ERRATA_DSU_936184``: This applies errata 936184 workaround for the + affected DSU configurations. This errata applies only for those DSUs that + contain the ACP interface **and** the DSU revision is older than r2p0 (on + r2p0 it is fixed). However, please note that this workaround results in + increased DSU power consumption on idle. + +CPU Specific optimizations +-------------------------- + +This section describes some of the optimizations allowed by the CPU micro +architecture that can be enabled by the platform as desired. + +- ``SKIP_A57_L1_FLUSH_PWR_DWN``: This flag enables an optimization in the + Cortex-A57 cluster power down sequence by not flushing the Level 1 data + cache. The L1 data cache and the L2 unified cache are inclusive. A flush + of the L2 by set/way flushes any dirty lines from the L1 as well. This + is a known safe deviation from the Cortex-A57 TRM defined power down + sequence. Each Cortex-A57 based platform must make its own decision on + whether to use the optimization. + +- ``A53_DISABLE_NON_TEMPORAL_HINT``: This flag disables the cache non-temporal + hint. The LDNP/STNP instructions as implemented on Cortex-A53 do not behave + in a way most programmers expect, and will most probably result in a + significant speed degradation to any code that employs them. The Armv8-A + architecture (see Arm DDI 0487A.h, section D3.4.3) allows cores to ignore + the non-temporal hint and treat LDNP/STNP as LDP/STP instead. Enabling this + flag enforces this behaviour. This needs to be enabled only for revisions + <= r0p3 of the CPU and is enabled by default. + +- ``A57_DISABLE_NON_TEMPORAL_HINT``: This flag has the same behaviour as + ``A53_DISABLE_NON_TEMPORAL_HINT`` but for Cortex-A57. This needs to be + enabled only for revisions <= r1p2 of the CPU and is enabled by default, + as recommended in section "4.7 Non-Temporal Loads/Stores" of the + `Cortex-A57 Software Optimization Guide`_. + +- ''A57_ENABLE_NON_CACHEABLE_LOAD_FWD'': This flag enables non-cacheable + streaming enhancement feature for Cortex-A57 CPUs. Platforms can set + this bit only if their memory system meets the requirement that cache + line fill requests from the Cortex-A57 processor are atomic. Each + Cortex-A57 based platform must make its own decision on whether to use + the optimization. This flag is disabled by default. + +- ``NEOVERSE_Nx_EXTERNAL_LLC``: This flag indicates that an external last + level cache(LLC) is present in the system, and that the DataSource field + on the master CHI interface indicates when data is returned from the LLC. + This is used to control how the LL_CACHE* PMU events count. + Default value is 0 (Disabled). + +-------------- + +*Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.* + +.. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715 +.. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639 +.. _CVE-2022-23960: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23960 +.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/index.html +.. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/index.html +.. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html +.. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf +.. _Arm DSU Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm138168/index.html diff --git a/arm-trusted-firmware/docs/design/firmware-design.rst b/arm-trusted-firmware/docs/design/firmware-design.rst new file mode 100644 index 0000000..0831dc0 --- /dev/null +++ b/arm-trusted-firmware/docs/design/firmware-design.rst @@ -0,0 +1,2743 @@ +Firmware Design +=============== + +Trusted Firmware-A (TF-A) implements a subset of the Trusted Board Boot +Requirements (TBBR) Platform Design Document (PDD) for Arm reference +platforms. + +The TBB sequence starts when the platform is powered on and runs up +to the stage where it hands-off control to firmware running in the normal +world in DRAM. This is the cold boot path. + +TF-A also implements the `Power State Coordination Interface PDD`_ as a +runtime service. PSCI is the interface from normal world software to firmware +implementing power management use-cases (for example, secondary CPU boot, +hotplug and idle). Normal world software can access TF-A runtime services via +the Arm SMC (Secure Monitor Call) instruction. The SMC instruction must be +used as mandated by the SMC Calling Convention (`SMCCC`_). + +TF-A implements a framework for configuring and managing interrupts generated +in either security state. The details of the interrupt management framework +and its design can be found in :ref:`Interrupt Management Framework`. + +TF-A also implements a library for setting up and managing the translation +tables. The details of this library can be found in +:ref:`Translation (XLAT) Tables Library`. + +TF-A can be built to support either AArch64 or AArch32 execution state. + +.. note:: + + The descriptions in this chapter are for the Arm TrustZone architecture. + For changes to the firmware design for the + `Arm Confidential Compute Architecture (Arm CCA)`_ please refer to the + chapter :ref:`Realm Management Extension (RME)`. + +Cold boot +--------- + +The cold boot path starts when the platform is physically turned on. If +``COLD_BOOT_SINGLE_CPU=0``, one of the CPUs released from reset is chosen as the +primary CPU, and the remaining CPUs are considered secondary CPUs. The primary +CPU is chosen through platform-specific means. The cold boot path is mainly +executed by the primary CPU, other than essential CPU initialization executed by +all CPUs. The secondary CPUs are kept in a safe platform-specific state until +the primary CPU has performed enough initialization to boot them. + +Refer to the :ref:`CPU Reset` for more information on the effect of the +``COLD_BOOT_SINGLE_CPU`` platform build option. + +The cold boot path in this implementation of TF-A depends on the execution +state. For AArch64, it is divided into five steps (in order of execution): + +- Boot Loader stage 1 (BL1) *AP Trusted ROM* +- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* +- Boot Loader stage 3-1 (BL31) *EL3 Runtime Software* +- Boot Loader stage 3-2 (BL32) *Secure-EL1 Payload* (optional) +- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* + +For AArch32, it is divided into four steps (in order of execution): + +- Boot Loader stage 1 (BL1) *AP Trusted ROM* +- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* +- Boot Loader stage 3-2 (BL32) *EL3 Runtime Software* +- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* + +Arm development platforms (Fixed Virtual Platforms (FVPs) and Juno) implement a +combination of the following types of memory regions. Each bootloader stage uses +one or more of these memory regions. + +- Regions accessible from both non-secure and secure states. For example, + non-trusted SRAM, ROM and DRAM. +- Regions accessible from only the secure state. For example, trusted SRAM and + ROM. The FVPs also implement the trusted DRAM which is statically + configured. Additionally, the Base FVPs and Juno development platform + configure the TrustZone Controller (TZC) to create a region in the DRAM + which is accessible only from the secure state. + +The sections below provide the following details: + +- dynamic configuration of Boot Loader stages +- initialization and execution of the first three stages during cold boot +- specification of the EL3 Runtime Software (BL31 for AArch64 and BL32 for + AArch32) entrypoint requirements for use by alternative Trusted Boot + Firmware in place of the provided BL1 and BL2 + +Dynamic Configuration during cold boot +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each of the Boot Loader stages may be dynamically configured if required by the +platform. The Boot Loader stage may optionally specify a firmware +configuration file and/or hardware configuration file as listed below: + +- FW_CONFIG - The firmware configuration file. Holds properties shared across + all BLx images. + An example is the "dtb-registry" node, which contains the information about + the other device tree configurations (load-address, size, image_id). +- HW_CONFIG - The hardware configuration file. Can be shared by all Boot Loader + stages and also by the Normal World Rich OS. +- TB_FW_CONFIG - Trusted Boot Firmware configuration file. Shared between BL1 + and BL2. +- SOC_FW_CONFIG - SoC Firmware configuration file. Used by BL31. +- TOS_FW_CONFIG - Trusted OS Firmware configuration file. Used by Trusted OS + (BL32). +- NT_FW_CONFIG - Non Trusted Firmware configuration file. Used by Non-trusted + firmware (BL33). + +The Arm development platforms use the Flattened Device Tree format for the +dynamic configuration files. + +Each Boot Loader stage can pass up to 4 arguments via registers to the next +stage. BL2 passes the list of the next images to execute to the *EL3 Runtime +Software* (BL31 for AArch64 and BL32 for AArch32) via `arg0`. All the other +arguments are platform defined. The Arm development platforms use the following +convention: + +- BL1 passes the address of a meminfo_t structure to BL2 via ``arg1``. This + structure contains the memory layout available to BL2. +- When dynamic configuration files are present, the firmware configuration for + the next Boot Loader stage is populated in the first available argument and + the generic hardware configuration is passed the next available argument. + For example, + + - FW_CONFIG is loaded by BL1, then its address is passed in ``arg0`` to BL2. + - TB_FW_CONFIG address is retrieved by BL2 from FW_CONFIG device tree. + - If HW_CONFIG is loaded by BL1, then its address is passed in ``arg2`` to + BL2. Note, ``arg1`` is already used for meminfo_t. + - If SOC_FW_CONFIG is loaded by BL2, then its address is passed in ``arg1`` + to BL31. Note, ``arg0`` is used to pass the list of executable images. + - Similarly, if HW_CONFIG is loaded by BL1 or BL2, then its address is + passed in ``arg2`` to BL31. + - For other BL3x images, if the firmware configuration file is loaded by + BL2, then its address is passed in ``arg0`` and if HW_CONFIG is loaded + then its address is passed in ``arg1``. + +BL1 +~~~ + +This stage begins execution from the platform's reset vector at EL3. The reset +address is platform dependent but it is usually located in a Trusted ROM area. +The BL1 data section is copied to trusted SRAM at runtime. + +On the Arm development platforms, BL1 code starts execution from the reset +vector defined by the constant ``BL1_RO_BASE``. The BL1 data section is copied +to the top of trusted SRAM as defined by the constant ``BL1_RW_BASE``. + +The functionality implemented by this stage is as follows. + +Determination of boot path +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Whenever a CPU is released from reset, BL1 needs to distinguish between a warm +boot and a cold boot. This is done using platform-specific mechanisms (see the +``plat_get_my_entrypoint()`` function in the :ref:`Porting Guide`). In the case +of a warm boot, a CPU is expected to continue execution from a separate +entrypoint. In the case of a cold boot, the secondary CPUs are placed in a safe +platform-specific state (see the ``plat_secondary_cold_boot_setup()`` function in +the :ref:`Porting Guide`) while the primary CPU executes the remaining cold boot +path as described in the following sections. + +This step only applies when ``PROGRAMMABLE_RESET_ADDRESS=0``. Refer to the +:ref:`CPU Reset` for more information on the effect of the +``PROGRAMMABLE_RESET_ADDRESS`` platform build option. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL1 performs minimal architectural initialization as follows. + +- Exception vectors + + BL1 sets up simple exception vectors for both synchronous and asynchronous + exceptions. The default behavior upon receiving an exception is to populate + a status code in the general purpose register ``X0/R0`` and call the + ``plat_report_exception()`` function (see the :ref:`Porting Guide`). The + status code is one of: + + For AArch64: + + :: + + 0x0 : Synchronous exception from Current EL with SP_EL0 + 0x1 : IRQ exception from Current EL with SP_EL0 + 0x2 : FIQ exception from Current EL with SP_EL0 + 0x3 : System Error exception from Current EL with SP_EL0 + 0x4 : Synchronous exception from Current EL with SP_ELx + 0x5 : IRQ exception from Current EL with SP_ELx + 0x6 : FIQ exception from Current EL with SP_ELx + 0x7 : System Error exception from Current EL with SP_ELx + 0x8 : Synchronous exception from Lower EL using aarch64 + 0x9 : IRQ exception from Lower EL using aarch64 + 0xa : FIQ exception from Lower EL using aarch64 + 0xb : System Error exception from Lower EL using aarch64 + 0xc : Synchronous exception from Lower EL using aarch32 + 0xd : IRQ exception from Lower EL using aarch32 + 0xe : FIQ exception from Lower EL using aarch32 + 0xf : System Error exception from Lower EL using aarch32 + + For AArch32: + + :: + + 0x10 : User mode + 0x11 : FIQ mode + 0x12 : IRQ mode + 0x13 : SVC mode + 0x16 : Monitor mode + 0x17 : Abort mode + 0x1a : Hypervisor mode + 0x1b : Undefined mode + 0x1f : System mode + + The ``plat_report_exception()`` implementation on the Arm FVP port programs + the Versatile Express System LED register in the following format to + indicate the occurrence of an unexpected exception: + + :: + + SYS_LED[0] - Security state (Secure=0/Non-Secure=1) + SYS_LED[2:1] - Exception Level (EL3=0x3, EL2=0x2, EL1=0x1, EL0=0x0) + For AArch32 it is always 0x0 + SYS_LED[7:3] - Exception Class (Sync/Async & origin). This is the value + of the status code + + A write to the LED register reflects in the System LEDs (S6LED0..7) in the + CLCD window of the FVP. + + BL1 does not expect to receive any exceptions other than the SMC exception. + For the latter, BL1 installs a simple stub. The stub expects to receive a + limited set of SMC types (determined by their function IDs in the general + purpose register ``X0/R0``): + + - ``BL1_SMC_RUN_IMAGE``: This SMC is raised by BL2 to make BL1 pass control + to EL3 Runtime Software. + - All SMCs listed in section "BL1 SMC Interface" in the :ref:`Firmware Update (FWU)` + Design Guide are supported for AArch64 only. These SMCs are currently + not supported when BL1 is built for AArch32. + + Any other SMC leads to an assertion failure. + +- CPU initialization + + BL1 calls the ``reset_handler()`` function which in turn calls the CPU + specific reset handler function (see the section: "CPU specific operations + framework"). + +- Control register setup (for AArch64) + + - ``SCTLR_EL3``. Instruction cache is enabled by setting the ``SCTLR_EL3.I`` + bit. Alignment and stack alignment checking is enabled by setting the + ``SCTLR_EL3.A`` and ``SCTLR_EL3.SA`` bits. Exception endianness is set to + little-endian by clearing the ``SCTLR_EL3.EE`` bit. + + - ``SCR_EL3``. The register width of the next lower exception level is set + to AArch64 by setting the ``SCR.RW`` bit. The ``SCR.EA`` bit is set to trap + both External Aborts and SError Interrupts in EL3. The ``SCR.SIF`` bit is + also set to disable instruction fetches from Non-secure memory when in + secure state. + + - ``CPTR_EL3``. Accesses to the ``CPACR_EL1`` register from EL1 or EL2, or the + ``CPTR_EL2`` register from EL2 are configured to not trap to EL3 by + clearing the ``CPTR_EL3.TCPAC`` bit. Access to the trace functionality is + configured not to trap to EL3 by clearing the ``CPTR_EL3.TTA`` bit. + Instructions that access the registers associated with Floating Point + and Advanced SIMD execution are configured to not trap to EL3 by + clearing the ``CPTR_EL3.TFP`` bit. + + - ``DAIF``. The SError interrupt is enabled by clearing the SError interrupt + mask bit. + + - ``MDCR_EL3``. The trap controls, ``MDCR_EL3.TDOSA``, ``MDCR_EL3.TDA`` and + ``MDCR_EL3.TPM``, are set so that accesses to the registers they control + do not trap to EL3. AArch64 Secure self-hosted debug is disabled by + setting the ``MDCR_EL3.SDD`` bit. Also ``MDCR_EL3.SPD32`` is set to + disable AArch32 Secure self-hosted privileged debug from S-EL1. + +- Control register setup (for AArch32) + + - ``SCTLR``. Instruction cache is enabled by setting the ``SCTLR.I`` bit. + Alignment checking is enabled by setting the ``SCTLR.A`` bit. + Exception endianness is set to little-endian by clearing the + ``SCTLR.EE`` bit. + + - ``SCR``. The ``SCR.SIF`` bit is set to disable instruction fetches from + Non-secure memory when in secure state. + + - ``CPACR``. Allow execution of Advanced SIMD instructions at PL0 and PL1, + by clearing the ``CPACR.ASEDIS`` bit. Access to the trace functionality + is configured not to trap to undefined mode by clearing the + ``CPACR.TRCDIS`` bit. + + - ``NSACR``. Enable non-secure access to Advanced SIMD functionality and + system register access to implemented trace registers. + + - ``FPEXC``. Enable access to the Advanced SIMD and floating-point + functionality from all Exception levels. + + - ``CPSR.A``. The Asynchronous data abort interrupt is enabled by clearing + the Asynchronous data abort interrupt mask bit. + + - ``SDCR``. The ``SDCR.SPD`` field is set to disable AArch32 Secure + self-hosted privileged debug. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +On Arm platforms, BL1 performs the following platform initializations: + +- Enable the Trusted Watchdog. +- Initialize the console. +- Configure the Interconnect to enable hardware coherency. +- Enable the MMU and map the memory it needs to access. +- Configure any required platform storage to load the next bootloader image + (BL2). +- If the BL1 dynamic configuration file, ``TB_FW_CONFIG``, is available, then + load it to the platform defined address and make it available to BL2 via + ``arg0``. +- Configure the system timer and program the `CNTFRQ_EL0` for use by NS-BL1U + and NS-BL2U firmware update images. + +Firmware Update detection and execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After performing platform setup, BL1 common code calls +``bl1_plat_get_next_image_id()`` to determine if :ref:`Firmware Update (FWU)` is +required or to proceed with the normal boot process. If the platform code +returns ``BL2_IMAGE_ID`` then the normal boot sequence is executed as described +in the next section, else BL1 assumes that :ref:`Firmware Update (FWU)` is +required and execution passes to the first image in the +:ref:`Firmware Update (FWU)` process. In either case, BL1 retrieves a descriptor +of the next image by calling ``bl1_plat_get_image_desc()``. The image descriptor +contains an ``entry_point_info_t`` structure, which BL1 uses to initialize the +execution state of the next image. + +BL2 image load and execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the normal boot flow, BL1 execution continues as follows: + +#. BL1 prints the following string from the primary CPU to indicate successful + execution of the BL1 stage: + + :: + + "Booting Trusted Firmware" + +#. BL1 loads a BL2 raw binary image from platform storage, at a + platform-specific base address. Prior to the load, BL1 invokes + ``bl1_plat_handle_pre_image_load()`` which allows the platform to update or + use the image information. If the BL2 image file is not present or if + there is not enough free trusted SRAM the following error message is + printed: + + :: + + "Failed to load BL2 firmware." + +#. BL1 invokes ``bl1_plat_handle_post_image_load()`` which again is intended + for platforms to take further action after image load. This function must + populate the necessary arguments for BL2, which may also include the memory + layout. Further description of the memory layout can be found later + in this document. + +#. BL1 passes control to the BL2 image at Secure EL1 (for AArch64) or at + Secure SVC mode (for AArch32), starting from its load address. + +BL2 +~~~ + +BL1 loads and passes control to BL2 at Secure-EL1 (for AArch64) or at Secure +SVC mode (for AArch32) . BL2 is linked against and loaded at a platform-specific +base address (more information can be found later in this document). +The functionality implemented by BL2 is as follows. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For AArch64, BL2 performs the minimal architectural initialization required +for subsequent stages of TF-A and normal world software. EL1 and EL0 are given +access to Floating Point and Advanced SIMD registers by setting the +``CPACR.FPEN`` bits. + +For AArch32, the minimal architectural initialization required for subsequent +stages of TF-A and normal world software is taken care of in BL1 as both BL1 +and BL2 execute at PL1. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +On Arm platforms, BL2 performs the following platform initializations: + +- Initialize the console. +- Configure any required platform storage to allow loading further bootloader + images. +- Enable the MMU and map the memory it needs to access. +- Perform platform security setup to allow access to controlled components. +- Reserve some memory for passing information to the next bootloader image + EL3 Runtime Software and populate it. +- Define the extents of memory available for loading each subsequent + bootloader image. +- If BL1 has passed TB_FW_CONFIG dynamic configuration file in ``arg0``, + then parse it. + +Image loading in BL2 +^^^^^^^^^^^^^^^^^^^^ + +BL2 generic code loads the images based on the list of loadable images +provided by the platform. BL2 passes the list of executable images +provided by the platform to the next handover BL image. + +The list of loadable images provided by the platform may also contain +dynamic configuration files. The files are loaded and can be parsed as +needed in the ``bl2_plat_handle_post_image_load()`` function. These +configuration files can be passed to next Boot Loader stages as arguments +by updating the corresponding entrypoint information in this function. + +SCP_BL2 (System Control Processor Firmware) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some systems have a separate System Control Processor (SCP) for power, clock, +reset and system control. BL2 loads the optional SCP_BL2 image from platform +storage into a platform-specific region of secure memory. The subsequent +handling of SCP_BL2 is platform specific. For example, on the Juno Arm +development platform port the image is transferred into SCP's internal memory +using the Boot Over MHU (BOM) protocol after being loaded in the trusted SRAM +memory. The SCP executes SCP_BL2 and signals to the Application Processor (AP) +for BL2 execution to continue. + +EL3 Runtime Software image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the EL3 Runtime Software image from platform storage into a platform- +specific address in trusted SRAM. If there is not enough memory to load the +image or image is missing it leads to an assertion failure. + +AArch64 BL32 (Secure-EL1 Payload) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the optional BL32 image from platform storage into a platform- +specific region of secure memory. The image executes in the secure world. BL2 +relies on BL31 to pass control to the BL32 image, if present. Hence, BL2 +populates a platform-specific area of memory with the entrypoint/load-address +of the BL32 image. The value of the Saved Processor Status Register (``SPSR``) +for entry into BL32 is not determined by BL2, it is initialized by the +Secure-EL1 Payload Dispatcher (see later) within BL31, which is responsible for +managing interaction with BL32. This information is passed to BL31. + +BL33 (Non-trusted Firmware) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the BL33 image (e.g. UEFI or other test or boot software) from +platform storage into non-secure memory as defined by the platform. + +BL2 relies on EL3 Runtime Software to pass control to BL33 once secure state +initialization is complete. Hence, BL2 populates a platform-specific area of +memory with the entrypoint and Saved Program Status Register (``SPSR``) of the +normal world software image. The entrypoint is the load address of the BL33 +image. The ``SPSR`` is determined as specified in Section 5.13 of the +`Power State Coordination Interface PDD`_. This information is passed to the +EL3 Runtime Software. + +AArch64 BL31 (EL3 Runtime Software) execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 execution continues as follows: + +#. BL2 passes control back to BL1 by raising an SMC, providing BL1 with the + BL31 entrypoint. The exception is handled by the SMC exception handler + installed by BL1. + +#. BL1 turns off the MMU and flushes the caches. It clears the + ``SCTLR_EL3.M/I/C`` bits, flushes the data cache to the point of coherency + and invalidates the TLBs. + +#. BL1 passes control to BL31 at the specified entrypoint at EL3. + +Running BL2 at EL3 execution level +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some platforms have a non-TF-A Boot ROM that expects the next boot stage +to execute at EL3. On these platforms, TF-A BL1 is a waste of memory +as its only purpose is to ensure TF-A BL2 is entered at S-EL1. To avoid +this waste, a special mode enables BL2 to execute at EL3, which allows +a non-TF-A Boot ROM to load and jump directly to BL2. This mode is selected +when the build flag BL2_AT_EL3 is enabled. The main differences in this +mode are: + +#. BL2 includes the reset code and the mailbox mechanism to differentiate + cold boot and warm boot. It runs at EL3 doing the arch + initialization required for EL3. + +#. BL2 does not receive the meminfo information from BL1 anymore. This + information can be passed by the Boot ROM or be internal to the + BL2 image. + +#. Since BL2 executes at EL3, BL2 jumps directly to the next image, + instead of invoking the RUN_IMAGE SMC call. + + +We assume 3 different types of BootROM support on the platform: + +#. The Boot ROM always jumps to the same address, for both cold + and warm boot. In this case, we will need to keep a resident part + of BL2 whose memory cannot be reclaimed by any other image. The + linker script defines the symbols __TEXT_RESIDENT_START__ and + __TEXT_RESIDENT_END__ that allows the platform to configure + correctly the memory map. +#. The platform has some mechanism to indicate the jump address to the + Boot ROM. Platform code can then program the jump address with + psci_warmboot_entrypoint during cold boot. +#. The platform has some mechanism to program the reset address using + the PROGRAMMABLE_RESET_ADDRESS feature. Platform code can then + program the reset address with psci_warmboot_entrypoint during + cold boot, bypassing the boot ROM for warm boot. + +In the last 2 cases, no part of BL2 needs to remain resident at +runtime. In the first 2 cases, we expect the Boot ROM to be able to +differentiate between warm and cold boot, to avoid loading BL2 again +during warm boot. + +This functionality can be tested with FVP loading the image directly +in memory and changing the address where the system jumps at reset. +For example: + + -C cluster0.cpu0.RVBAR=0x4022000 + --data cluster0.cpu0=bl2.bin@0x4022000 + +With this configuration, FVP is like a platform of the first case, +where the Boot ROM jumps always to the same address. For simplification, +BL32 is loaded in DRAM in this case, to avoid other images reclaiming +BL2 memory. + + +AArch64 BL31 +~~~~~~~~~~~~ + +The image for this stage is loaded by BL2 and BL1 passes control to BL31 at +EL3. BL31 executes solely in trusted SRAM. BL31 is linked against and +loaded at a platform-specific base address (more information can be found later +in this document). The functionality implemented by BL31 is as follows. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Currently, BL31 performs a similar architectural initialization to BL1 as +far as system register settings are concerned. Since BL1 code resides in ROM, +architectural initialization in BL31 allows override of any previous +initialization done by BL1. + +BL31 initializes the per-CPU data framework, which provides a cache of +frequently accessed per-CPU data optimised for fast, concurrent manipulation +on different CPUs. This buffer includes pointers to per-CPU contexts, crash +buffer, CPU reset and power down operations, PSCI data, platform data and so on. + +It then replaces the exception vectors populated by BL1 with its own. BL31 +exception vectors implement more elaborate support for handling SMCs since this +is the only mechanism to access the runtime services implemented by BL31 (PSCI +for example). BL31 checks each SMC for validity as specified by the +`SMC Calling Convention`_ before passing control to the required SMC +handler routine. + +BL31 programs the ``CNTFRQ_EL0`` register with the clock frequency of the system +counter, which is provided by the platform. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +BL31 performs detailed platform initialization, which enables normal world +software to function correctly. + +On Arm platforms, this consists of the following: + +- Initialize the console. +- Configure the Interconnect to enable hardware coherency. +- Enable the MMU and map the memory it needs to access. +- Initialize the generic interrupt controller. +- Initialize the power controller device. +- Detect the system topology. + +Runtime services initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL31 is responsible for initializing the runtime services. One of them is PSCI. + +As part of the PSCI initializations, BL31 detects the system topology. It also +initializes the data structures that implement the state machine used to track +the state of power domain nodes. The state can be one of ``OFF``, ``RUN`` or +``RETENTION``. All secondary CPUs are initially in the ``OFF`` state. The cluster +that the primary CPU belongs to is ``ON``; any other cluster is ``OFF``. It also +initializes the locks that protect them. BL31 accesses the state of a CPU or +cluster immediately after reset and before the data cache is enabled in the +warm boot path. It is not currently possible to use 'exclusive' based spinlocks, +therefore BL31 uses locks based on Lamport's Bakery algorithm instead. + +The runtime service framework and its initialization is described in more +detail in the "EL3 runtime services framework" section below. + +Details about the status of the PSCI implementation are provided in the +"Power State Coordination Interface" section below. + +AArch64 BL32 (Secure-EL1 Payload) image initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If a BL32 image is present then there must be a matching Secure-EL1 Payload +Dispatcher (SPD) service (see later for details). During initialization +that service must register a function to carry out initialization of BL32 +once the runtime services are fully initialized. BL31 invokes such a +registered function to initialize BL32 before running BL33. This initialization +is not necessary for AArch32 SPs. + +Details on BL32 initialization and the SPD's role are described in the +:ref:`firmware_design_sel1_spd` section below. + +BL33 (Non-trusted Firmware) execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +EL3 Runtime Software initializes the EL2 or EL1 processor context for normal- +world cold boot, ensuring that no secure state information finds its way into +the non-secure execution state. EL3 Runtime Software uses the entrypoint +information provided by BL2 to jump to the Non-trusted firmware image (BL33) +at the highest available Exception Level (EL2 if available, otherwise EL1). + +Using alternative Trusted Boot Firmware in place of BL1 & BL2 (AArch64 only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some platforms have existing implementations of Trusted Boot Firmware that +would like to use TF-A BL31 for the EL3 Runtime Software. To enable this +firmware architecture it is important to provide a fully documented and stable +interface between the Trusted Boot Firmware and BL31. + +Future changes to the BL31 interface will be done in a backwards compatible +way, and this enables these firmware components to be independently enhanced/ +updated to develop and exploit new functionality. + +Required CPU state when calling ``bl31_entrypoint()`` during cold boot +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function must only be called by the primary CPU. + +On entry to this function the calling primary CPU must be executing in AArch64 +EL3, little-endian data access, and all interrupt sources masked: + +:: + + PSTATE.EL = 3 + PSTATE.RW = 1 + PSTATE.DAIF = 0xf + SCTLR_EL3.EE = 0 + +X0 and X1 can be used to pass information from the Trusted Boot Firmware to the +platform code in BL31: + +:: + + X0 : Reserved for common TF-A information + X1 : Platform specific information + +BL31 zero-init sections (e.g. ``.bss``) should not contain valid data on entry, +these will be zero filled prior to invoking platform setup code. + +Use of the X0 and X1 parameters +''''''''''''''''''''''''''''''' + +The parameters are platform specific and passed from ``bl31_entrypoint()`` to +``bl31_early_platform_setup()``. The value of these parameters is never directly +used by the common BL31 code. + +The convention is that ``X0`` conveys information regarding the BL31, BL32 and +BL33 images from the Trusted Boot firmware and ``X1`` can be used for other +platform specific purpose. This convention allows platforms which use TF-A's +BL1 and BL2 images to transfer additional platform specific information from +Secure Boot without conflicting with future evolution of TF-A using ``X0`` to +pass a ``bl31_params`` structure. + +BL31 common and SPD initialization code depends on image and entrypoint +information about BL33 and BL32, which is provided via BL31 platform APIs. +This information is required until the start of execution of BL33. This +information can be provided in a platform defined manner, e.g. compiled into +the platform code in BL31, or provided in a platform defined memory location +by the Trusted Boot firmware, or passed from the Trusted Boot Firmware via the +Cold boot Initialization parameters. This data may need to be cleaned out of +the CPU caches if it is provided by an earlier boot stage and then accessed by +BL31 platform code before the caches are enabled. + +TF-A's BL2 implementation passes a ``bl31_params`` structure in +``X0`` and the Arm development platforms interpret this in the BL31 platform +code. + +MMU, Data caches & Coherency +'''''''''''''''''''''''''''' + +BL31 does not depend on the enabled state of the MMU, data caches or +interconnect coherency on entry to ``bl31_entrypoint()``. If these are disabled +on entry, these should be enabled during ``bl31_plat_arch_setup()``. + +Data structures used in the BL31 cold boot interface +'''''''''''''''''''''''''''''''''''''''''''''''''''' + +These structures are designed to support compatibility and independent +evolution of the structures and the firmware images. For example, a version of +BL31 that can interpret the BL3x image information from different versions of +BL2, a platform that uses an extended entry_point_info structure to convey +additional register information to BL31, or a ELF image loader that can convey +more details about the firmware images. + +To support these scenarios the structures are versioned and sized, which enables +BL31 to detect which information is present and respond appropriately. The +``param_header`` is defined to capture this information: + +.. code:: c + + 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; + +The structures using this format are ``entry_point_info``, ``image_info`` and +``bl31_params``. The code that allocates and populates these structures must set +the header fields appropriately, and the ``SET_PARAM_HEAD()`` a macro is defined +to simplify this action. + +Required CPU state for BL31 Warm boot initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When requesting a CPU power-on, or suspending a running CPU, TF-A provides +the platform power management code with a Warm boot initialization +entry-point, to be invoked by the CPU immediately after the reset handler. +On entry to the Warm boot initialization function the calling CPU must be in +AArch64 EL3, little-endian data access and all interrupt sources masked: + +:: + + PSTATE.EL = 3 + PSTATE.RW = 1 + PSTATE.DAIF = 0xf + SCTLR_EL3.EE = 0 + +The PSCI implementation will initialize the processor state and ensure that the +platform power management code is then invoked as required to initialize all +necessary system, cluster and CPU resources. + +AArch32 EL3 Runtime Software entrypoint interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable this firmware architecture it is important to provide a fully +documented and stable interface between the Trusted Boot Firmware and the +AArch32 EL3 Runtime Software. + +Future changes to the entrypoint interface will be done in a backwards +compatible way, and this enables these firmware components to be independently +enhanced/updated to develop and exploit new functionality. + +Required CPU state when entering during cold boot +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function must only be called by the primary CPU. + +On entry to this function the calling primary CPU must be executing in AArch32 +EL3, little-endian data access, and all interrupt sources masked: + +:: + + PSTATE.AIF = 0x7 + SCTLR.EE = 0 + +R0 and R1 are used to pass information from the Trusted Boot Firmware to the +platform code in AArch32 EL3 Runtime Software: + +:: + + R0 : Reserved for common TF-A information + R1 : Platform specific information + +Use of the R0 and R1 parameters +''''''''''''''''''''''''''''''' + +The parameters are platform specific and the convention is that ``R0`` conveys +information regarding the BL3x images from the Trusted Boot firmware and ``R1`` +can be used for other platform specific purpose. This convention allows +platforms which use TF-A's BL1 and BL2 images to transfer additional platform +specific information from Secure Boot without conflicting with future +evolution of TF-A using ``R0`` to pass a ``bl_params`` structure. + +The AArch32 EL3 Runtime Software is responsible for entry into BL33. This +information can be obtained in a platform defined manner, e.g. compiled into +the AArch32 EL3 Runtime Software, or provided in a platform defined memory +location by the Trusted Boot firmware, or passed from the Trusted Boot Firmware +via the Cold boot Initialization parameters. This data may need to be cleaned +out of the CPU caches if it is provided by an earlier boot stage and then +accessed by AArch32 EL3 Runtime Software before the caches are enabled. + +When using AArch32 EL3 Runtime Software, the Arm development platforms pass a +``bl_params`` structure in ``R0`` from BL2 to be interpreted by AArch32 EL3 Runtime +Software platform code. + +MMU, Data caches & Coherency +'''''''''''''''''''''''''''' + +AArch32 EL3 Runtime Software must not depend on the enabled state of the MMU, +data caches or interconnect coherency in its entrypoint. They must be explicitly +enabled if required. + +Data structures used in cold boot interface +''''''''''''''''''''''''''''''''''''''''''' + +The AArch32 EL3 Runtime Software cold boot interface uses ``bl_params`` instead +of ``bl31_params``. The ``bl_params`` structure is based on the convention +described in AArch64 BL31 cold boot interface section. + +Required CPU state for warm boot initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When requesting a CPU power-on, or suspending a running CPU, AArch32 EL3 +Runtime Software must ensure execution of a warm boot initialization entrypoint. +If TF-A BL1 is used and the PROGRAMMABLE_RESET_ADDRESS build flag is false, +then AArch32 EL3 Runtime Software must ensure that BL1 branches to the warm +boot entrypoint by arranging for the BL1 platform function, +plat_get_my_entrypoint(), to return a non-zero value. + +In this case, the warm boot entrypoint must be in AArch32 EL3, little-endian +data access and all interrupt sources masked: + +:: + + PSTATE.AIF = 0x7 + SCTLR.EE = 0 + +The warm boot entrypoint may be implemented by using TF-A +``psci_warmboot_entrypoint()`` function. In that case, the platform must fulfil +the pre-requisites mentioned in the +:ref:`PSCI Library Integration guide for Armv8-A AArch32 systems`. + +EL3 runtime services framework +------------------------------ + +Software executing in the non-secure state and in the secure state at exception +levels lower than EL3 will request runtime services using the Secure Monitor +Call (SMC) instruction. These requests will follow the convention described in +the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function +identifiers to each SMC request and describes how arguments are passed and +returned. + +The EL3 runtime services framework enables the development of services by +different providers that can be easily integrated into final product firmware. +The following sections describe the framework which facilitates the +registration, initialization and use of runtime services in EL3 Runtime +Software (BL31). + +The design of the runtime services depends heavily on the concepts and +definitions described in the `SMCCC`_, in particular SMC Function IDs, Owning +Entity Numbers (OEN), Fast and Yielding calls, and the SMC32 and SMC64 calling +conventions. Please refer to that document for more detailed explanation of +these terms. + +The following runtime services are expected to be implemented first. They have +not all been instantiated in the current implementation. + +#. Standard service calls + + This service is for management of the entire system. The Power State + Coordination Interface (`PSCI`_) is the first set of standard service calls + defined by Arm (see PSCI section later). + +#. Secure-EL1 Payload Dispatcher service + + If a system runs a Trusted OS or other Secure-EL1 Payload (SP) then + it also requires a *Secure Monitor* at EL3 to switch the EL1 processor + context between the normal world (EL1/EL2) and trusted world (Secure-EL1). + The Secure Monitor will make these world switches in response to SMCs. The + `SMCCC`_ provides for such SMCs with the Trusted OS Call and Trusted + Application Call OEN ranges. + + The interface between the EL3 Runtime Software and the Secure-EL1 Payload is + not defined by the `SMCCC`_ or any other standard. As a result, each + Secure-EL1 Payload requires a specific Secure Monitor that runs as a runtime + service - within TF-A this service is referred to as the Secure-EL1 Payload + Dispatcher (SPD). + + TF-A provides a Test Secure-EL1 Payload (TSP) and its associated Dispatcher + (TSPD). Details of SPD design and TSP/TSPD operation are described in the + :ref:`firmware_design_sel1_spd` section below. + +#. CPU implementation service + + This service will provide an interface to CPU implementation specific + services for a given platform e.g. access to processor errata workarounds. + This service is currently unimplemented. + +Additional services for Arm Architecture, SiP and OEM calls can be implemented. +Each implemented service handles a range of SMC function identifiers as +described in the `SMCCC`_. + +Registration +~~~~~~~~~~~~ + +A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying +the name of the service, the range of OENs covered, the type of service and +initialization and call handler functions. This macro instantiates a ``const struct rt_svc_desc`` for the service with these details (see ``runtime_svc.h``). +This structure is allocated in a special ELF section ``rt_svc_descs``, enabling +the framework to find all service descriptors included into BL31. + +The specific service for a SMC Function is selected based on the OEN and call +type of the Function ID, and the framework uses that information in the service +descriptor to identify the handler for the SMC Call. + +The service descriptors do not include information to identify the precise set +of SMC function identifiers supported by this service implementation, the +security state from which such calls are valid nor the capability to support +64-bit and/or 32-bit callers (using SMC32 or SMC64). Responding appropriately +to these aspects of a SMC call is the responsibility of the service +implementation, the framework is focused on integration of services from +different providers and minimizing the time taken by the framework before the +service handler is invoked. + +Details of the parameters, requirements and behavior of the initialization and +call handling functions are provided in the following sections. + +Initialization +~~~~~~~~~~~~~~ + +``runtime_svc_init()`` in ``runtime_svc.c`` initializes the runtime services +framework running on the primary CPU during cold boot as part of the BL31 +initialization. This happens prior to initializing a Trusted OS and running +Normal world boot firmware that might in turn use these services. +Initialization involves validating each of the declared runtime service +descriptors, calling the service initialization function and populating the +index used for runtime lookup of the service. + +The BL31 linker script collects all of the declared service descriptors into a +single array and defines symbols that allow the framework to locate and traverse +the array, and determine its size. + +The framework does basic validation of each descriptor to halt firmware +initialization if service declaration errors are detected. The framework does +not check descriptors for the following error conditions, and may behave in an +unpredictable manner under such scenarios: + +#. Overlapping OEN ranges +#. Multiple descriptors for the same range of OENs and ``call_type`` +#. Incorrect range of owning entity numbers for a given ``call_type`` + +Once validated, the service ``init()`` callback is invoked. This function carries +out any essential EL3 initialization before servicing requests. The ``init()`` +function is only invoked on the primary CPU during cold boot. If the service +uses per-CPU data this must either be initialized for all CPUs during this call, +or be done lazily when a CPU first issues an SMC call to that service. If +``init()`` returns anything other than ``0``, this is treated as an initialization +error and the service is ignored: this does not cause the firmware to halt. + +The OEN and call type fields present in the SMC Function ID cover a total of +128 distinct services, but in practice a single descriptor can cover a range of +OENs, e.g. SMCs to call a Trusted OS function. To optimize the lookup of a +service handler, the framework uses an array of 128 indices that map every +distinct OEN/call-type combination either to one of the declared services or to +indicate the service is not handled. This ``rt_svc_descs_indices[]`` array is +populated for all of the OENs covered by a service after the service ``init()`` +function has reported success. So a service that fails to initialize will never +have it's ``handle()`` function invoked. + +The following figure shows how the ``rt_svc_descs_indices[]`` index maps the SMC +Function ID call type and OEN onto a specific service handler in the +``rt_svc_descs[]`` array. + +|Image 1| + +.. _handling-an-smc: + +Handling an SMC +~~~~~~~~~~~~~~~ + +When the EL3 runtime services framework receives a Secure Monitor Call, the SMC +Function ID is passed in W0 from the lower exception level (as per the +`SMCCC`_). If the calling register width is AArch32, it is invalid to invoke an +SMC Function which indicates the SMC64 calling convention: such calls are +ignored and return the Unknown SMC Function Identifier result code ``0xFFFFFFFF`` +in R0/X0. + +Bit[31] (fast/yielding call) and bits[29:24] (owning entity number) of the SMC +Function ID are combined to index into the ``rt_svc_descs_indices[]`` array. The +resulting value might indicate a service that has no handler, in this case the +framework will also report an Unknown SMC Function ID. Otherwise, the value is +used as a further index into the ``rt_svc_descs[]`` array to locate the required +service and handler. + +The service's ``handle()`` callback is provided with five of the SMC parameters +directly, the others are saved into memory for retrieval (if needed) by the +handler. The handler is also provided with an opaque ``handle`` for use with the +supporting library for parameter retrieval, setting return values and context +manipulation; and with ``flags`` indicating the security state of the caller. The +framework finally sets up the execution stack for the handler, and invokes the +services ``handle()`` function. + +On return from the handler the result registers are populated in X0-X7 as needed +before restoring the stack and CPU state and returning from the original SMC. + +Exception Handling Framework +---------------------------- + +Please refer to the :ref:`Exception Handling Framework` document. + +Power State Coordination Interface +---------------------------------- + +TODO: Provide design walkthrough of PSCI implementation. + +The PSCI v1.1 specification categorizes APIs as optional and mandatory. All the +mandatory APIs in PSCI v1.1, PSCI v1.0 and in PSCI v0.2 draft specification +`Power State Coordination Interface PDD`_ are implemented. The table lists +the PSCI v1.1 APIs and their support in generic code. + +An API implementation might have a dependency on platform code e.g. CPU_SUSPEND +requires the platform to export a part of the implementation. Hence the level +of support of the mandatory APIs depends upon the support exported by the +platform port as well. The Juno and FVP (all variants) platforms export all the +required support. + ++-----------------------------+-------------+-------------------------------+ +| PSCI v1.1 API | Supported | Comments | ++=============================+=============+===============================+ +| ``PSCI_VERSION`` | Yes | The version returned is 1.1 | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_SUSPEND`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_OFF`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_ON`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``AFFINITY_INFO`` | Yes | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE_INFO_TYPE`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE_INFO_CPU`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_OFF`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_RESET`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_FEATURES`` | Yes | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_FREEZE`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_DEFAULT_SUSPEND`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``NODE_HW_STATE`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_SUSPEND`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_SET_SUSPEND_MODE`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_STAT_RESIDENCY`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_STAT_COUNT`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_RESET2`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MEM_PROTECT`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MEM_PROTECT_CHECK_RANGE`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ + +\*Note : These PSCI APIs require platform power management hooks to be +registered with the generic PSCI code to be supported. + +\*\*Note : These PSCI APIs require appropriate Secure Payload Dispatcher +hooks to be registered with the generic PSCI code to be supported. + +The PSCI implementation in TF-A is a library which can be integrated with +AArch64 or AArch32 EL3 Runtime Software for Armv8-A systems. A guide to +integrating PSCI library with AArch32 EL3 Runtime Software can be found +at :ref:`PSCI Library Integration guide for Armv8-A AArch32 systems`. + +.. _firmware_design_sel1_spd: + +Secure-EL1 Payloads and Dispatchers +----------------------------------- + +On a production system that includes a Trusted OS running in Secure-EL1/EL0, +the Trusted OS is coupled with a companion runtime service in the BL31 +firmware. This service is responsible for the initialisation of the Trusted +OS and all communications with it. The Trusted OS is the BL32 stage of the +boot flow in TF-A. The firmware will attempt to locate, load and execute a +BL32 image. + +TF-A uses a more general term for the BL32 software that runs at Secure-EL1 - +the *Secure-EL1 Payload* - as it is not always a Trusted OS. + +TF-A provides a Test Secure-EL1 Payload (TSP) and a Test Secure-EL1 Payload +Dispatcher (TSPD) service as an example of how a Trusted OS is supported on a +production system using the Runtime Services Framework. On such a system, the +Test BL32 image and service are replaced by the Trusted OS and its dispatcher +service. The TF-A build system expects that the dispatcher will define the +build flag ``NEED_BL32`` to enable it to include the BL32 in the build either +as a binary or to compile from source depending on whether the ``BL32`` build +option is specified or not. + +The TSP runs in Secure-EL1. It is designed to demonstrate synchronous +communication with the normal-world software running in EL1/EL2. Communication +is initiated by the normal-world software + +- either directly through a Fast SMC (as defined in the `SMCCC`_) + +- or indirectly through a `PSCI`_ SMC. The `PSCI`_ implementation in turn + informs the TSPD about the requested power management operation. This allows + the TSP to prepare for or respond to the power state change + +The TSPD service is responsible for. + +- Initializing the TSP + +- Routing requests and responses between the secure and the non-secure + states during the two types of communications just described + +Initializing a BL32 Image +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Secure-EL1 Payload Dispatcher (SPD) service is responsible for initializing +the BL32 image. It needs access to the information passed by BL2 to BL31 to do +so. This is provided by: + +.. code:: c + + entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t); + +which returns a reference to the ``entry_point_info`` structure corresponding to +the image which will be run in the specified security state. The SPD uses this +API to get entry point information for the SECURE image, BL32. + +In the absence of a BL32 image, BL31 passes control to the normal world +bootloader image (BL33). When the BL32 image is present, it is typical +that the SPD wants control to be passed to BL32 first and then later to BL33. + +To do this the SPD has to register a BL32 initialization function during +initialization of the SPD service. The BL32 initialization function has this +prototype: + +.. code:: c + + int32_t init(void); + +and is registered using the ``bl31_register_bl32_init()`` function. + +TF-A supports two approaches for the SPD to pass control to BL32 before +returning through EL3 and running the non-trusted firmware (BL33): + +#. In the BL32 setup function, use ``bl31_set_next_image_type()`` to + request that the exit from ``bl31_main()`` is to the BL32 entrypoint in + Secure-EL1. BL31 will exit to BL32 using the asynchronous method by + calling ``bl31_prepare_next_image_entry()`` and ``el3_exit()``. + + When the BL32 has completed initialization at Secure-EL1, it returns to + BL31 by issuing an SMC, using a Function ID allocated to the SPD. On + receipt of this SMC, the SPD service handler should switch the CPU context + from trusted to normal world and use the ``bl31_set_next_image_type()`` and + ``bl31_prepare_next_image_entry()`` functions to set up the initial return to + the normal world firmware BL33. On return from the handler the framework + will exit to EL2 and run BL33. + +#. The BL32 setup function registers an initialization function using + ``bl31_register_bl32_init()`` which provides a SPD-defined mechanism to + invoke a 'world-switch synchronous call' to Secure-EL1 to run the BL32 + entrypoint. + + .. note:: + The Test SPD service included with TF-A provides one implementation + of such a mechanism. + + On completion BL32 returns control to BL31 via a SMC, and on receipt the + SPD service handler invokes the synchronous call return mechanism to return + to the BL32 initialization function. On return from this function, + ``bl31_main()`` will set up the return to the normal world firmware BL33 and + continue the boot process in the normal world. + +Crash Reporting in BL31 +----------------------- + +BL31 implements a scheme for reporting the processor state when an unhandled +exception is encountered. The reporting mechanism attempts to preserve all the +register contents and report it via a dedicated UART (PL011 console). BL31 +reports the general purpose, EL3, Secure EL1 and some EL2 state registers. + +A dedicated per-CPU crash stack is maintained by BL31 and this is retrieved via +the per-CPU pointer cache. The implementation attempts to minimise the memory +required for this feature. The file ``crash_reporting.S`` contains the +implementation for crash reporting. + +The sample crash output is shown below. + +:: + + x0 = 0x000000002a4a0000 + x1 = 0x0000000000000001 + x2 = 0x0000000000000002 + x3 = 0x0000000000000003 + x4 = 0x0000000000000004 + x5 = 0x0000000000000005 + x6 = 0x0000000000000006 + x7 = 0x0000000000000007 + x8 = 0x0000000000000008 + x9 = 0x0000000000000009 + x10 = 0x0000000000000010 + x11 = 0x0000000000000011 + x12 = 0x0000000000000012 + x13 = 0x0000000000000013 + x14 = 0x0000000000000014 + x15 = 0x0000000000000015 + x16 = 0x0000000000000016 + x17 = 0x0000000000000017 + x18 = 0x0000000000000018 + x19 = 0x0000000000000019 + x20 = 0x0000000000000020 + x21 = 0x0000000000000021 + x22 = 0x0000000000000022 + x23 = 0x0000000000000023 + x24 = 0x0000000000000024 + x25 = 0x0000000000000025 + x26 = 0x0000000000000026 + x27 = 0x0000000000000027 + x28 = 0x0000000000000028 + x29 = 0x0000000000000029 + x30 = 0x0000000088000b78 + scr_el3 = 0x000000000003073d + sctlr_el3 = 0x00000000b0cd183f + cptr_el3 = 0x0000000000000000 + tcr_el3 = 0x000000008080351c + daif = 0x00000000000002c0 + mair_el3 = 0x00000000004404ff + spsr_el3 = 0x0000000060000349 + elr_el3 = 0x0000000088000114 + ttbr0_el3 = 0x0000000004018201 + esr_el3 = 0x00000000be000000 + far_el3 = 0x0000000000000000 + spsr_el1 = 0x0000000000000000 + elr_el1 = 0x0000000000000000 + spsr_abt = 0x0000000000000000 + spsr_und = 0x0000000000000000 + spsr_irq = 0x0000000000000000 + spsr_fiq = 0x0000000000000000 + sctlr_el1 = 0x0000000030d00800 + actlr_el1 = 0x0000000000000000 + cpacr_el1 = 0x0000000000000000 + csselr_el1 = 0x0000000000000000 + sp_el1 = 0x0000000000000000 + esr_el1 = 0x0000000000000000 + ttbr0_el1 = 0x0000000000000000 + ttbr1_el1 = 0x0000000000000000 + mair_el1 = 0x0000000000000000 + amair_el1 = 0x0000000000000000 + tcr_el1 = 0x0000000000000000 + tpidr_el1 = 0x0000000000000000 + tpidr_el0 = 0x0000000000000000 + tpidrro_el0 = 0x0000000000000000 + par_el1 = 0x0000000000000000 + mpidr_el1 = 0x0000000080000000 + afsr0_el1 = 0x0000000000000000 + afsr1_el1 = 0x0000000000000000 + contextidr_el1 = 0x0000000000000000 + vbar_el1 = 0x0000000000000000 + cntp_ctl_el0 = 0x0000000000000000 + cntp_cval_el0 = 0x0000000000000000 + cntv_ctl_el0 = 0x0000000000000000 + cntv_cval_el0 = 0x0000000000000000 + cntkctl_el1 = 0x0000000000000000 + sp_el0 = 0x0000000004014940 + isr_el1 = 0x0000000000000000 + dacr32_el2 = 0x0000000000000000 + ifsr32_el2 = 0x0000000000000000 + icc_hppir0_el1 = 0x00000000000003ff + icc_hppir1_el1 = 0x00000000000003ff + icc_ctlr_el3 = 0x0000000000080400 + gicd_ispendr regs (Offsets 0x200-0x278) + Offset Value + 0x200: 0x0000000000000000 + 0x208: 0x0000000000000000 + 0x210: 0x0000000000000000 + 0x218: 0x0000000000000000 + 0x220: 0x0000000000000000 + 0x228: 0x0000000000000000 + 0x230: 0x0000000000000000 + 0x238: 0x0000000000000000 + 0x240: 0x0000000000000000 + 0x248: 0x0000000000000000 + 0x250: 0x0000000000000000 + 0x258: 0x0000000000000000 + 0x260: 0x0000000000000000 + 0x268: 0x0000000000000000 + 0x270: 0x0000000000000000 + 0x278: 0x0000000000000000 + +Guidelines for Reset Handlers +----------------------------- + +TF-A implements a framework that allows CPU and platform ports to perform +actions very early after a CPU is released from reset in both the cold and warm +boot paths. This is done by calling the ``reset_handler()`` function in both +the BL1 and BL31 images. It in turn calls the platform and CPU specific reset +handling functions. + +Details for implementing a CPU specific reset handler can be found in +Section 8. Details for implementing a platform specific reset handler can be +found in the :ref:`Porting Guide` (see the ``plat_reset_handler()`` function). + +When adding functionality to a reset handler, keep in mind that if a different +reset handling behavior is required between the first and the subsequent +invocations of the reset handling code, this should be detected at runtime. +In other words, the reset handler should be able to detect whether an action has +already been performed and act as appropriate. Possible courses of actions are, +e.g. skip the action the second time, or undo/redo it. + +.. _configuring-secure-interrupts: + +Configuring secure interrupts +----------------------------- + +The GIC driver is responsible for performing initial configuration of secure +interrupts on the platform. To this end, the platform is expected to provide the +GIC driver (either GICv2 or GICv3, as selected by the platform) with the +interrupt configuration during the driver initialisation. + +Secure interrupt configuration are specified in an array of secure interrupt +properties. In this scheme, in both GICv2 and GICv3 driver data structures, the +``interrupt_props`` member points to an array of interrupt properties. Each +element of the array specifies the interrupt number and its attributes +(priority, group, configuration). Each element of the array shall be populated +by the macro ``INTR_PROP_DESC()``. The macro takes the following arguments: + +- 10-bit interrupt number, + +- 8-bit interrupt priority, + +- Interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1``, + ``INTR_TYPE_NS``), + +- Interrupt configuration (either ``GIC_INTR_CFG_LEVEL`` or + ``GIC_INTR_CFG_EDGE``). + +.. _firmware_design_cpu_ops_fwk: + +CPU specific operations framework +--------------------------------- + +Certain aspects of the Armv8-A architecture are implementation defined, +that is, certain behaviours are not architecturally defined, but must be +defined and documented by individual processor implementations. TF-A +implements a framework which categorises the common implementation defined +behaviours and allows a processor to export its implementation of that +behaviour. The categories are: + +#. Processor specific reset sequence. + +#. Processor specific power down sequences. + +#. Processor specific register dumping as a part of crash reporting. + +#. Errata status reporting. + +Each of the above categories fulfils a different requirement. + +#. allows any processor specific initialization before the caches and MMU + are turned on, like implementation of errata workarounds, entry into + the intra-cluster coherency domain etc. + +#. allows each processor to implement the power down sequence mandated in + its Technical Reference Manual (TRM). + +#. allows a processor to provide additional information to the developer + in the event of a crash, for example Cortex-A53 has registers which + can expose the data cache contents. + +#. allows a processor to define a function that inspects and reports the status + of all errata workarounds on that processor. + +Please note that only 2. is mandated by the TRM. + +The CPU specific operations framework scales to accommodate a large number of +different CPUs during power down and reset handling. The platform can specify +any CPU optimization it wants to enable for each CPU. It can also specify +the CPU errata workarounds to be applied for each CPU type during reset +handling by defining CPU errata compile time macros. Details on these macros +can be found in the :ref:`Arm CPU Specific Build Macros` document. + +The CPU specific operations framework depends on the ``cpu_ops`` structure which +needs to be exported for each type of CPU in the platform. It is defined in +``include/lib/cpus/aarch64/cpu_macros.S`` and has the following fields : ``midr``, +``reset_func()``, ``cpu_pwr_down_ops`` (array of power down functions) and +``cpu_reg_dump()``. + +The CPU specific files in ``lib/cpus`` export a ``cpu_ops`` data structure with +suitable handlers for that CPU. For example, ``lib/cpus/aarch64/cortex_a53.S`` +exports the ``cpu_ops`` for Cortex-A53 CPU. According to the platform +configuration, these CPU specific files must be included in the build by +the platform makefile. The generic CPU specific operations framework code exists +in ``lib/cpus/aarch64/cpu_helpers.S``. + +CPU specific Reset Handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After a reset, the state of the CPU when it calls generic reset handler is: +MMU turned off, both instruction and data caches turned off and not part +of any coherency domain. + +The BL entrypoint code first invokes the ``plat_reset_handler()`` to allow +the platform to perform any system initialization required and any system +errata workarounds that needs to be applied. The ``get_cpu_ops_ptr()`` reads +the current CPU midr, finds the matching ``cpu_ops`` entry in the ``cpu_ops`` +array and returns it. Note that only the part number and implementer fields +in midr are used to find the matching ``cpu_ops`` entry. The ``reset_func()`` in +the returned ``cpu_ops`` is then invoked which executes the required reset +handling for that CPU and also any errata workarounds enabled by the platform. +This function must preserve the values of general purpose registers x20 to x29. + +Refer to Section "Guidelines for Reset Handlers" for general guidelines +regarding placement of code in a reset handler. + +CPU specific power down sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +During the BL31 initialization sequence, the pointer to the matching ``cpu_ops`` +entry is stored in per-CPU data by ``init_cpu_ops()`` so that it can be quickly +retrieved during power down sequences. + +Various CPU drivers register handlers to perform power down at certain power +levels for that specific CPU. The PSCI service, upon receiving a power down +request, determines the highest power level at which to execute power down +sequence for a particular CPU. It uses the ``prepare_cpu_pwr_dwn()`` function to +pick the right power down handler for the requested level. The function +retrieves ``cpu_ops`` pointer member of per-CPU data, and from that, further +retrieves ``cpu_pwr_down_ops`` array, and indexes into the required level. If the +requested power level is higher than what a CPU driver supports, the handler +registered for highest level is invoked. + +At runtime the platform hooks for power down are invoked by the PSCI service to +perform platform specific operations during a power down sequence, for example +turning off CCI coherency during a cluster power down. + +CPU specific register reporting during crash +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the crash reporting is enabled in BL31, when a crash occurs, the crash +reporting framework calls ``do_cpu_reg_dump`` which retrieves the matching +``cpu_ops`` using ``get_cpu_ops_ptr()`` function. The ``cpu_reg_dump()`` in +``cpu_ops`` is invoked, which then returns the CPU specific register values to +be reported and a pointer to the ASCII list of register names in a format +expected by the crash reporting framework. + +.. _firmware_design_cpu_errata_reporting: + +CPU errata status reporting +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Errata workarounds for CPUs supported in TF-A are applied during both cold and +warm boots, shortly after reset. Individual Errata workarounds are enabled as +build options. Some errata workarounds have potential run-time implications; +therefore some are enabled by default, others not. Platform ports shall +override build options to enable or disable errata as appropriate. The CPU +drivers take care of applying errata workarounds that are enabled and applicable +to a given CPU. Refer to :ref:`arm_cpu_macros_errata_workarounds` for more +information. + +Functions in CPU drivers that apply errata workaround must follow the +conventions listed below. + +The errata workaround must be authored as two separate functions: + +- One that checks for errata. This function must determine whether that errata + applies to the current CPU. Typically this involves matching the current + CPUs revision and variant against a value that's known to be affected by the + errata. If the function determines that the errata applies to this CPU, it + must return ``ERRATA_APPLIES``; otherwise, it must return + ``ERRATA_NOT_APPLIES``. The utility functions ``cpu_get_rev_var`` and + ``cpu_rev_var_ls`` functions may come in handy for this purpose. + +For an errata identified as ``E``, the check function must be named +``check_errata_E``. + +This function will be invoked at different times, both from assembly and from +C run time. Therefore it must follow AAPCS, and must not use stack. + +- Another one that applies the errata workaround. This function would call the + check function described above, and applies errata workaround if required. + +CPU drivers that apply errata workaround can optionally implement an assembly +function that report the status of errata workarounds pertaining to that CPU. +For a driver that registers the CPU, for example, ``cpux`` via ``declare_cpu_ops`` +macro, the errata reporting function, if it exists, must be named +``cpux_errata_report``. This function will always be called with MMU enabled; it +must follow AAPCS and may use stack. + +In a debug build of TF-A, on a CPU that comes out of reset, both BL1 and the +runtime firmware (BL31 in AArch64, and BL32 in AArch32) will invoke errata +status reporting function, if one exists, for that type of CPU. + +To report the status of each errata workaround, the function shall use the +assembler macro ``report_errata``, passing it: + +- The build option that enables the errata; + +- The name of the CPU: this must be the same identifier that CPU driver + registered itself with, using ``declare_cpu_ops``; + +- And the errata identifier: the identifier must match what's used in the + errata's check function described above. + +The errata status reporting function will be called once per CPU type/errata +combination during the software's active life time. + +It's expected that whenever an errata workaround is submitted to TF-A, the +errata reporting function is appropriately extended to report its status as +well. + +Reporting the status of errata workaround is for informational purpose only; it +has no functional significance. + +Memory layout of BL images +-------------------------- + +Each bootloader image can be divided in 2 parts: + +- the static contents of the image. These are data actually stored in the + binary on the disk. In the ELF terminology, they are called ``PROGBITS`` + sections; + +- the run-time contents of the image. These are data that don't occupy any + space in the binary on the disk. The ELF binary just contains some + metadata indicating where these data will be stored at run-time and the + corresponding sections need to be allocated and initialized at run-time. + In the ELF terminology, they are called ``NOBITS`` sections. + +All PROGBITS sections are grouped together at the beginning of the image, +followed by all NOBITS sections. This is true for all TF-A images and it is +governed by the linker scripts. This ensures that the raw binary images are +as small as possible. If a NOBITS section was inserted in between PROGBITS +sections then the resulting binary file would contain zero bytes in place of +this NOBITS section, making the image unnecessarily bigger. Smaller images +allow faster loading from the FIP to the main memory. + +For BL31, a platform can specify an alternate location for NOBITS sections +(other than immediately following PROGBITS sections) by setting +``SEPARATE_NOBITS_REGION`` to 1 and defining ``BL31_NOBITS_BASE`` and +``BL31_NOBITS_LIMIT``. + +Linker scripts and symbols +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each bootloader stage image layout is described by its own linker script. The +linker scripts export some symbols into the program symbol table. Their values +correspond to particular addresses. TF-A code can refer to these symbols to +figure out the image memory layout. + +Linker symbols follow the following naming convention in TF-A. + +- ``__
_START__`` + + Start address of a given section named ``
``. + +- ``__
_END__`` + + End address of a given section named ``
``. If there is an alignment + constraint on the section's end address then ``__
_END__`` corresponds + to the end address of the section's actual contents, rounded up to the right + boundary. Refer to the value of ``__
_UNALIGNED_END__`` to know the + actual end address of the section's contents. + +- ``__
_UNALIGNED_END__`` + + End address of a given section named ``
`` without any padding or + rounding up due to some alignment constraint. + +- ``__
_SIZE__`` + + Size (in bytes) of a given section named ``
``. If there is an + alignment constraint on the section's end address then ``__
_SIZE__`` + corresponds to the size of the section's actual contents, rounded up to the + right boundary. In other words, ``__
_SIZE__ = __
_END__ - _
_START__``. Refer to the value of ``__
_UNALIGNED_SIZE__`` + to know the actual size of the section's contents. + +- ``__
_UNALIGNED_SIZE__`` + + Size (in bytes) of a given section named ``
`` without any padding or + rounding up due to some alignment constraint. In other words, + ``__
_UNALIGNED_SIZE__ = __
_UNALIGNED_END__ - __
_START__``. + +Some of the linker symbols are mandatory as TF-A code relies on them to be +defined. They are listed in the following subsections. Some of them must be +provided for each bootloader stage and some are specific to a given bootloader +stage. + +The linker scripts define some extra, optional symbols. They are not actually +used by any code but they help in understanding the bootloader images' memory +layout as they are easy to spot in the link map files. + +Common linker symbols +^^^^^^^^^^^^^^^^^^^^^ + +All BL images share the following requirements: + +- The BSS section must be zero-initialised before executing any C code. +- The coherent memory section (if enabled) must be zero-initialised as well. +- The MMU setup code needs to know the extents of the coherent and read-only + memory regions to set the right memory attributes. When + ``SEPARATE_CODE_AND_RODATA=1``, it needs to know more specifically how the + read-only memory region is divided between code and data. + +The following linker symbols are defined for this purpose: + +- ``__BSS_START__`` +- ``__BSS_SIZE__`` +- ``__COHERENT_RAM_START__`` Must be aligned on a page-size boundary. +- ``__COHERENT_RAM_END__`` Must be aligned on a page-size boundary. +- ``__COHERENT_RAM_UNALIGNED_SIZE__`` +- ``__RO_START__`` +- ``__RO_END__`` +- ``__TEXT_START__`` +- ``__TEXT_END__`` +- ``__RODATA_START__`` +- ``__RODATA_END__`` + +BL1's linker symbols +^^^^^^^^^^^^^^^^^^^^ + +BL1 being the ROM image, it has additional requirements. BL1 resides in ROM and +it is entirely executed in place but it needs some read-write memory for its +mutable data. Its ``.data`` section (i.e. its allocated read-write data) must be +relocated from ROM to RAM before executing any C code. + +The following additional linker symbols are defined for BL1: + +- ``__BL1_ROM_END__`` End address of BL1's ROM contents, covering its code + and ``.data`` section in ROM. +- ``__DATA_ROM_START__`` Start address of the ``.data`` section in ROM. Must be + aligned on a 16-byte boundary. +- ``__DATA_RAM_START__`` Address in RAM where the ``.data`` section should be + copied over. Must be aligned on a 16-byte boundary. +- ``__DATA_SIZE__`` Size of the ``.data`` section (in ROM or RAM). +- ``__BL1_RAM_START__`` Start address of BL1 read-write data. +- ``__BL1_RAM_END__`` End address of BL1 read-write data. + +How to choose the right base addresses for each bootloader stage image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There is currently no support for dynamic image loading in TF-A. This means +that all bootloader images need to be linked against their ultimate runtime +locations and the base addresses of each image must be chosen carefully such +that images don't overlap each other in an undesired way. As the code grows, +the base addresses might need adjustments to cope with the new memory layout. + +The memory layout is completely specific to the platform and so there is no +general recipe for choosing the right base addresses for each bootloader image. +However, there are tools to aid in understanding the memory layout. These are +the link map files: ``build///bl/bl.map``, with ```` +being the stage bootloader. They provide a detailed view of the memory usage of +each image. Among other useful information, they provide the end address of +each image. + +- ``bl1.map`` link map file provides ``__BL1_RAM_END__`` address. +- ``bl2.map`` link map file provides ``__BL2_END__`` address. +- ``bl31.map`` link map file provides ``__BL31_END__`` address. +- ``bl32.map`` link map file provides ``__BL32_END__`` address. + +For each bootloader image, the platform code must provide its start address +as well as a limit address that it must not overstep. The latter is used in the +linker scripts to check that the image doesn't grow past that address. If that +happens, the linker will issue a message similar to the following: + +:: + + aarch64-none-elf-ld: BLx has exceeded its limit. + +Additionally, if the platform memory layout implies some image overlaying like +on FVP, BL31 and TSP need to know the limit address that their PROGBITS +sections must not overstep. The platform code must provide those. + +TF-A does not provide any mechanism to verify at boot time that the memory +to load a new image is free to prevent overwriting a previously loaded image. +The platform must specify the memory available in the system for all the +relevant BL images to be loaded. + +For example, in the case of BL1 loading BL2, ``bl1_plat_sec_mem_layout()`` will +return the region defined by the platform where BL1 intends to load BL2. The +``load_image()`` function performs bounds check for the image size based on the +base and maximum image size provided by the platforms. Platforms must take +this behaviour into account when defining the base/size for each of the images. + +Memory layout on Arm development platforms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following list describes the memory layout on the Arm development platforms: + +- A 4KB page of shared memory is used for communication between Trusted + Firmware and the platform's power controller. This is located at the base of + Trusted SRAM. The amount of Trusted SRAM available to load the bootloader + images is reduced by the size of the shared memory. + + The shared memory is used to store the CPUs' entrypoint mailbox. On Juno, + this is also used for the MHU payload when passing messages to and from the + SCP. + +- Another 4 KB page is reserved for passing memory layout between BL1 and BL2 + and also the dynamic firmware configurations. + +- On FVP, BL1 is originally sitting in the Trusted ROM at address ``0x0``. On + Juno, BL1 resides in flash memory at address ``0x0BEC0000``. BL1 read-write + data are relocated to the top of Trusted SRAM at runtime. + +- BL2 is loaded below BL1 RW + +- EL3 Runtime Software, BL31 for AArch64 and BL32 for AArch32 (e.g. SP_MIN), + is loaded at the top of the Trusted SRAM, such that its NOBITS sections will + overwrite BL1 R/W data and BL2. This implies that BL1 global variables + remain valid only until execution reaches the EL3 Runtime Software entry + point during a cold boot. + +- On Juno, SCP_BL2 is loaded temporarily into the EL3 Runtime Software memory + region and transferred to the SCP before being overwritten by EL3 Runtime + Software. + +- BL32 (for AArch64) can be loaded in one of the following locations: + + - Trusted SRAM + - Trusted DRAM (FVP only) + - Secure region of DRAM (top 16MB of DRAM configured by the TrustZone + controller) + + When BL32 (for AArch64) is loaded into Trusted SRAM, it is loaded below + BL31. + +The location of the BL32 image will result in different memory maps. This is +illustrated for both FVP and Juno in the following diagrams, using the TSP as +an example. + +.. note:: + Loading the BL32 image in TZC secured DRAM doesn't change the memory + layout of the other images in Trusted SRAM. + +CONFIG section in memory layouts shown below contains: + +:: + + +--------------------+ + |bl2_mem_params_descs| + |--------------------| + | fw_configs | + +--------------------+ + +``bl2_mem_params_descs`` contains parameters passed from BL2 to next the +BL image during boot. + +``fw_configs`` includes soc_fw_config, tos_fw_config, tb_fw_config and fw_config. + +**FVP with TSP in Trusted SRAM with firmware configs :** +(These diagrams only cover the AArch64 case) + +:: + + DRAM + 0xffffffff +----------+ + : : + |----------| + |HW_CONFIG | + 0x83000000 |----------| (non-secure) + | | + 0x80000000 +----------+ + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL32 | + 0x04003000 +----------+ +----------------+ + | CONFIG | + 0x04001000 +----------+ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**FVP with TSP in Trusted DRAM with firmware configs (default option):** + +:: + + DRAM + 0xffffffff +--------------+ + : : + |--------------| + | HW_CONFIG | + 0x83000000 |--------------| (non-secure) + | | + 0x80000000 +--------------+ + + Trusted DRAM + 0x08000000 +--------------+ + | BL32 | + 0x06000000 +--------------+ + + Trusted SRAM + 0x04040000 +--------------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |--------------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |--------------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | +----------------+ + 0x04003000 +--------------+ + | CONFIG | + 0x04001000 +--------------+ + | Shared | + 0x04000000 +--------------+ + + Trusted ROM + 0x04000000 +--------------+ + | BL1 (ro) | + 0x00000000 +--------------+ + +**FVP with TSP in TZC-Secured DRAM with firmware configs :** + +:: + + DRAM + 0xffffffff +----------+ + | BL32 | (secure) + 0xff000000 +----------+ + | | + |----------| + |HW_CONFIG | + 0x83000000 |----------| (non-secure) + | | + 0x80000000 +----------+ + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | +----------------+ + 0x04003000 +----------+ + | CONFIG | + 0x04001000 +----------+ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**Juno with BL32 in Trusted SRAM :** + +:: + + Flash0 + 0x0C000000 +----------+ + : : + 0x0BED0000 |----------| + | BL1 (ro) | + 0x0BEC0000 |----------| + : : + 0x08000000 +----------+ BL31 is loaded + after SCP_BL2 has + Trusted SRAM been sent to SCP + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | + | | <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL32 | + | | +----------------+ + | | + 0x04001000 +----------+ + | MHU | + 0x04000000 +----------+ + +**Juno with BL32 in TZC-secured DRAM :** + +:: + + DRAM + 0xFFE00000 +----------+ + | BL32 | (secure) + 0xFF000000 |----------| + | | + : : (non-secure) + | | + 0x80000000 +----------+ + + Flash0 + 0x0C000000 +----------+ + : : + 0x0BED0000 |----------| + | BL1 (ro) | + 0x0BEC0000 |----------| + : : + 0x08000000 +----------+ BL31 is loaded + after SCP_BL2 has + Trusted SRAM been sent to SCP + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | + | | +----------------+ + 0x04001000 +----------+ + | MHU | + 0x04000000 +----------+ + +.. _firmware_design_fip: + +Firmware Image Package (FIP) +---------------------------- + +Using a Firmware Image Package (FIP) allows for packing bootloader images (and +potentially other payloads) into a single archive that can be loaded by TF-A +from non-volatile platform storage. A driver to load images from a FIP has +been added to the storage layer and allows a package to be read from supported +platform storage. A tool to create Firmware Image Packages is also provided +and described below. + +Firmware Image Package layout +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FIP layout consists of a table of contents (ToC) followed by payload data. +The ToC itself has a header followed by one or more table entries. The ToC is +terminated by an end marker entry, and since the size of the ToC is 0 bytes, +the offset equals the total size of the FIP file. All ToC entries describe some +payload data that has been appended to the end of the binary package. With the +information provided in the ToC entry the corresponding payload data can be +retrieved. + +:: + + ------------------ + | ToC Header | + |----------------| + | ToC Entry 0 | + |----------------| + | ToC Entry 1 | + |----------------| + | ToC End Marker | + |----------------| + | | + | Data 0 | + | | + |----------------| + | | + | Data 1 | + | | + ------------------ + +The ToC header and entry formats are described in the header file +``include/tools_share/firmware_image_package.h``. This file is used by both the +tool and TF-A. + +The ToC header has the following fields: + +:: + + `name`: The name of the ToC. This is currently used to validate the header. + `serial_number`: A non-zero number provided by the creation tool + `flags`: Flags associated with this data. + Bits 0-31: Reserved + Bits 32-47: Platform defined + Bits 48-63: Reserved + +A ToC entry has the following fields: + +:: + + `uuid`: All files are referred to by a pre-defined Universally Unique + IDentifier [UUID] . The UUIDs are defined in + `include/tools_share/firmware_image_package.h`. The platform translates + the requested image name into the corresponding UUID when accessing the + package. + `offset_address`: The offset address at which the corresponding payload data + can be found. The offset is calculated from the ToC base address. + `size`: The size of the corresponding payload data in bytes. + `flags`: Flags associated with this entry. None are yet defined. + +Firmware Image Package creation tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FIP creation tool can be used to pack specified images into a binary +package that can be loaded by TF-A from platform storage. The tool currently +only supports packing bootloader images. Additional image definitions can be +added to the tool as required. + +The tool can be found in ``tools/fiptool``. + +Loading from a Firmware Image Package (FIP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Firmware Image Package (FIP) driver can load images from a binary package on +non-volatile platform storage. For the Arm development platforms, this is +currently NOR FLASH. + +Bootloader images are loaded according to the platform policy as specified by +the function ``plat_get_image_source()``. For the Arm development platforms, this +means the platform will attempt to load images from a Firmware Image Package +located at the start of NOR FLASH0. + +The Arm development platforms' policy is to only allow loading of a known set of +images. The platform policy can be modified to allow additional images. + +Use of coherent memory in TF-A +------------------------------ + +There might be loss of coherency when physical memory with mismatched +shareability, cacheability and memory attributes is accessed by multiple CPUs +(refer to section B2.9 of `Arm ARM`_ for more details). This possibility occurs +in TF-A during power up/down sequences when coherency, MMU and caches are +turned on/off incrementally. + +TF-A defines coherent memory as a region of memory with Device nGnRE attributes +in the translation tables. The translation granule size in TF-A is 4KB. This +is the smallest possible size of the coherent memory region. + +By default, all data structures which are susceptible to accesses with +mismatched attributes from various CPUs are allocated in a coherent memory +region (refer to section 2.1 of :ref:`Porting Guide`). The coherent memory +region accesses are Outer Shareable, non-cacheable and they can be accessed with +the Device nGnRE attributes when the MMU is turned on. Hence, at the expense of +at least an extra page of memory, TF-A is able to work around coherency issues +due to mismatched memory attributes. + +The alternative to the above approach is to allocate the susceptible data +structures in Normal WriteBack WriteAllocate Inner shareable memory. This +approach requires the data structures to be designed so that it is possible to +work around the issue of mismatched memory attributes by performing software +cache maintenance on them. + +Disabling the use of coherent memory in TF-A +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It might be desirable to avoid the cost of allocating coherent memory on +platforms which are memory constrained. TF-A enables inclusion of coherent +memory in firmware images through the build flag ``USE_COHERENT_MEM``. +This flag is enabled by default. It can be disabled to choose the second +approach described above. + +The below sections analyze the data structures allocated in the coherent memory +region and the changes required to allocate them in normal memory. + +Coherent memory usage in PSCI implementation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``psci_non_cpu_pd_nodes`` data structure stores the platform's power domain +tree information for state management of power domains. By default, this data +structure is allocated in the coherent memory region in TF-A because it can be +accessed by multiple CPUs, either with caches enabled or disabled. + +.. code:: c + + typedef struct non_cpu_pwr_domain_node { + /* + * Index of the first CPU power domain node level 0 which has this node + * as its parent. + */ + unsigned int cpu_start_idx; + + /* + * Number of CPU power domains which are siblings of the domain indexed + * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx + * -> cpu_start_idx + ncpus' have this node as their parent. + */ + unsigned int ncpus; + + /* + * Index of the parent power domain node. + */ + unsigned int parent_node; + + plat_local_state_t local_state; + + unsigned char level; + + /* For indexing the psci_lock array*/ + unsigned char lock_index; + } non_cpu_pd_node_t; + +In order to move this data structure to normal memory, the use of each of its +fields must be analyzed. Fields like ``cpu_start_idx``, ``ncpus``, ``parent_node`` +``level`` and ``lock_index`` are only written once during cold boot. Hence removing +them from coherent memory involves only doing a clean and invalidate of the +cache lines after these fields are written. + +The field ``local_state`` can be concurrently accessed by multiple CPUs in +different cache states. A Lamport's Bakery lock ``psci_locks`` is used to ensure +mutual exclusion to this field and a clean and invalidate is needed after it +is written. + +Bakery lock data +~~~~~~~~~~~~~~~~ + +The bakery lock data structure ``bakery_lock_t`` is allocated in coherent memory +and is accessed by multiple CPUs with mismatched attributes. ``bakery_lock_t`` is +defined as follows: + +.. code:: c + + 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; + +It is a characteristic of Lamport's Bakery algorithm that the volatile per-CPU +fields can be read by all CPUs but only written to by the owning CPU. + +Depending upon the data cache line size, the per-CPU fields of the +``bakery_lock_t`` structure for multiple CPUs may exist on a single cache line. +These per-CPU fields can be read and written during lock contention by multiple +CPUs with mismatched memory attributes. Since these fields are a part of the +lock implementation, they do not have access to any other locking primitive to +safeguard against the resulting coherency issues. As a result, simple software +cache maintenance is not enough to allocate them in coherent memory. Consider +the following example. + +CPU0 updates its per-CPU field with data cache enabled. This write updates a +local cache line which contains a copy of the fields for other CPUs as well. Now +CPU1 updates its per-CPU field of the ``bakery_lock_t`` structure with data cache +disabled. CPU1 then issues a DCIVAC operation to invalidate any stale copies of +its field in any other cache line in the system. This operation will invalidate +the update made by CPU0 as well. + +To use bakery locks when ``USE_COHERENT_MEM`` is disabled, the lock data structure +has been redesigned. The changes utilise the characteristic of Lamport's Bakery +algorithm mentioned earlier. The bakery_lock structure only allocates the memory +for a single CPU. The macro ``DEFINE_BAKERY_LOCK`` allocates all the bakery locks +needed for a CPU into a section ``bakery_lock``. The linker allocates the memory +for other cores by using the total size allocated for the bakery_lock section +and multiplying it with (PLATFORM_CORE_COUNT - 1). This enables software to +perform software cache maintenance on the lock data structure without running +into coherency issues associated with mismatched attributes. + +The bakery lock data structure ``bakery_info_t`` is defined for use when +``USE_COHERENT_MEM`` is disabled as follows: + +.. code:: c + + 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; + +The ``bakery_info_t`` represents a single per-CPU field of one lock and +the combination of corresponding ``bakery_info_t`` structures for all CPUs in the +system represents the complete bakery lock. The view in memory for a system +with n bakery locks are: + +:: + + bakery_lock section start + |----------------| + | `bakery_info_t`| <-- Lock_0 per-CPU field + | Lock_0 | for CPU0 + |----------------| + | `bakery_info_t`| <-- Lock_1 per-CPU field + | Lock_1 | for CPU0 + |----------------| + | .... | + |----------------| + | `bakery_info_t`| <-- Lock_N per-CPU field + | Lock_N | for CPU0 + ------------------ + | XXXXX | + | Padding to | + | next Cache WB | <--- Calculate PERCPU_BAKERY_LOCK_SIZE, allocate + | Granule | continuous memory for remaining CPUs. + ------------------ + | `bakery_info_t`| <-- Lock_0 per-CPU field + | Lock_0 | for CPU1 + |----------------| + | `bakery_info_t`| <-- Lock_1 per-CPU field + | Lock_1 | for CPU1 + |----------------| + | .... | + |----------------| + | `bakery_info_t`| <-- Lock_N per-CPU field + | Lock_N | for CPU1 + ------------------ + | XXXXX | + | Padding to | + | next Cache WB | + | Granule | + ------------------ + +Consider a system of 2 CPUs with 'N' bakery locks as shown above. For an +operation on Lock_N, the corresponding ``bakery_info_t`` in both CPU0 and CPU1 +``bakery_lock`` section need to be fetched and appropriate cache operations need +to be performed for each access. + +On Arm Platforms, bakery locks are used in psci (``psci_locks``) and power controller +driver (``arm_lock``). + +Non Functional Impact of removing coherent memory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Removal of the coherent memory region leads to the additional software overhead +of performing cache maintenance for the affected data structures. However, since +the memory where the data structures are allocated is cacheable, the overhead is +mostly mitigated by an increase in performance. + +There is however a performance impact for bakery locks, due to: + +- Additional cache maintenance operations, and +- Multiple cache line reads for each lock operation, since the bakery locks + for each CPU are distributed across different cache lines. + +The implementation has been optimized to minimize this additional overhead. +Measurements indicate that when bakery locks are allocated in Normal memory, the +minimum latency of acquiring a lock is on an average 3-4 micro seconds whereas +in Device memory the same is 2 micro seconds. The measurements were done on the +Juno Arm development platform. + +As mentioned earlier, almost a page of memory can be saved by disabling +``USE_COHERENT_MEM``. Each platform needs to consider these trade-offs to decide +whether coherent memory should be used. If a platform disables +``USE_COHERENT_MEM`` and needs to use bakery locks in the porting layer, it can +optionally define macro ``PLAT_PERCPU_BAKERY_LOCK_SIZE`` (see the +:ref:`Porting Guide`). Refer to the reference platform code for examples. + +Isolating code and read-only data on separate memory pages +---------------------------------------------------------- + +In the Armv8-A VMSA, translation table entries include fields that define the +properties of the target memory region, such as its access permissions. The +smallest unit of memory that can be addressed by a translation table entry is +a memory page. Therefore, if software needs to set different permissions on two +memory regions then it needs to map them using different memory pages. + +The default memory layout for each BL image is as follows: + +:: + + | ... | + +-------------------+ + | Read-write data | + +-------------------+ Page boundary + | | + +-------------------+ + | Exception vectors | + +-------------------+ 2 KB boundary + | | + +-------------------+ + | Read-only data | + +-------------------+ + | Code | + +-------------------+ BLx_BASE + +.. note:: + The 2KB alignment for the exception vectors is an architectural + requirement. + +The read-write data start on a new memory page so that they can be mapped with +read-write permissions, whereas the code and read-only data below are configured +as read-only. + +However, the read-only data are not aligned on a page boundary. They are +contiguous to the code. Therefore, the end of the code section and the beginning +of the read-only data one might share a memory page. This forces both to be +mapped with the same memory attributes. As the code needs to be executable, this +means that the read-only data stored on the same memory page as the code are +executable as well. This could potentially be exploited as part of a security +attack. + +TF provides the build flag ``SEPARATE_CODE_AND_RODATA`` to isolate the code and +read-only data on separate memory pages. This in turn allows independent control +of the access permissions for the code and read-only data. In this case, +platform code gets a finer-grained view of the image layout and can +appropriately map the code region as executable and the read-only data as +execute-never. + +This has an impact on memory footprint, as padding bytes need to be introduced +between the code and read-only data to ensure the segregation of the two. To +limit the memory cost, this flag also changes the memory layout such that the +code and exception vectors are now contiguous, like so: + +:: + + | ... | + +-------------------+ + | Read-write data | + +-------------------+ Page boundary + | | + +-------------------+ + | Read-only data | + +-------------------+ Page boundary + | | + +-------------------+ + | Exception vectors | + +-------------------+ 2 KB boundary + | | + +-------------------+ + | Code | + +-------------------+ BLx_BASE + +With this more condensed memory layout, the separation of read-only data will +add zero or one page to the memory footprint of each BL image. Each platform +should consider the trade-off between memory footprint and security. + +This build flag is disabled by default, minimising memory footprint. On Arm +platforms, it is enabled. + +Publish and Subscribe Framework +------------------------------- + +The Publish and Subscribe Framework allows EL3 components to define and publish +events, to which other EL3 components can subscribe. + +The following macros are provided by the framework: + +- ``REGISTER_PUBSUB_EVENT(event)``: Defines an event, and takes one argument, + the event name, which must be a valid C identifier. All calls to + ``REGISTER_PUBSUB_EVENT`` macro must be placed in the file + ``pubsub_events.h``. + +- ``PUBLISH_EVENT_ARG(event, arg)``: Publishes a defined event, by iterating + subscribed handlers and calling them in turn. The handlers will be passed the + parameter ``arg``. The expected use-case is to broadcast an event. + +- ``PUBLISH_EVENT(event)``: Like ``PUBLISH_EVENT_ARG``, except that the value + ``NULL`` is passed to subscribed handlers. + +- ``SUBSCRIBE_TO_EVENT(event, handler)``: Registers the ``handler`` to + subscribe to ``event``. The handler will be executed whenever the ``event`` + is published. + +- ``for_each_subscriber(event, subscriber)``: Iterates through all handlers + subscribed for ``event``. ``subscriber`` must be a local variable of type + ``pubsub_cb_t *``, and will point to each subscribed handler in turn during + iteration. This macro can be used for those patterns that none of the + ``PUBLISH_EVENT_*()`` macros cover. + +Publishing an event that wasn't defined using ``REGISTER_PUBSUB_EVENT`` will +result in build error. Subscribing to an undefined event however won't. + +Subscribed handlers must be of type ``pubsub_cb_t``, with following function +signature: + +.. code:: c + + typedef void* (*pubsub_cb_t)(const void *arg); + +There may be arbitrary number of handlers registered to the same event. The +order in which subscribed handlers are notified when that event is published is +not defined. Subscribed handlers may be executed in any order; handlers should +not assume any relative ordering amongst them. + +Publishing an event on a PE will result in subscribed handlers executing on that +PE only; it won't cause handlers to execute on a different PE. + +Note that publishing an event on a PE blocks until all the subscribed handlers +finish executing on the PE. + +TF-A generic code publishes and subscribes to some events within. Platform +ports are discouraged from subscribing to them. These events may be withdrawn, +renamed, or have their semantics altered in the future. Platforms may however +register, publish, and subscribe to platform-specific events. + +Publish and Subscribe Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A publisher that wants to publish event ``foo`` would: + +- Define the event ``foo`` in the ``pubsub_events.h``. + + .. code:: c + + REGISTER_PUBSUB_EVENT(foo); + +- Depending on the nature of event, use one of ``PUBLISH_EVENT_*()`` macros to + publish the event at the appropriate path and time of execution. + +A subscriber that wants to subscribe to event ``foo`` published above would +implement: + +.. code:: c + + void *foo_handler(const void *arg) + { + void *result; + + /* Do handling ... */ + + return result; + } + + SUBSCRIBE_TO_EVENT(foo, foo_handler); + + +Reclaiming the BL31 initialization code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A significant amount of the code used for the initialization of BL31 is never +needed again after boot time. In order to reduce the runtime memory +footprint, the memory used for this code can be reclaimed after initialization +has finished and be used for runtime data. + +The build option ``RECLAIM_INIT_CODE`` can be set to mark this boot time code +with a ``.text.init.*`` attribute which can be filtered and placed suitably +within the BL image for later reclamation by the platform. The platform can +specify the filter and the memory region for this init section in BL31 via the +plat.ld.S linker script. For example, on the FVP, this section is placed +overlapping the secondary CPU stacks so that after the cold boot is done, this +memory can be reclaimed for the stacks. The init memory section is initially +mapped with ``RO``, ``EXECUTE`` attributes. After BL31 initialization has +completed, the FVP changes the attributes of this section to ``RW``, +``EXECUTE_NEVER`` allowing it to be used for runtime data. The memory attributes +are changed within the ``bl31_plat_runtime_setup`` platform hook. The init +section section can be reclaimed for any data which is accessed after cold +boot initialization and it is upto the platform to make the decision. + +.. _firmware_design_pmf: + +Performance Measurement Framework +--------------------------------- + +The Performance Measurement Framework (PMF) facilitates collection of +timestamps by registered services and provides interfaces to retrieve them +from within TF-A. A platform can choose to expose appropriate SMCs to +retrieve these collected timestamps. + +By default, the global physical counter is used for the timestamp +value and is read via ``CNTPCT_EL0``. The framework allows to retrieve +timestamps captured by other CPUs. + +Timestamp identifier format +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A PMF timestamp is uniquely identified across the system via the +timestamp ID or ``tid``. The ``tid`` is composed as follows: + +:: + + Bits 0-7: The local timestamp identifier. + Bits 8-9: Reserved. + Bits 10-15: The service identifier. + Bits 16-31: Reserved. + +#. The service identifier. Each PMF service is identified by a + service name and a service identifier. Both the service name and + identifier are unique within the system as a whole. + +#. The local timestamp identifier. This identifier is unique within a given + service. + +Registering a PMF service +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To register a PMF service, the ``PMF_REGISTER_SERVICE()`` macro from ``pmf.h`` +is used. The arguments required are the service name, the service ID, +the total number of local timestamps to be captured and a set of flags. + +The ``flags`` field can be specified as a bitwise-OR of the following values: + +:: + + PMF_STORE_ENABLE: The timestamp is stored in memory for later retrieval. + PMF_DUMP_ENABLE: The timestamp is dumped on the serial console. + +The ``PMF_REGISTER_SERVICE()`` reserves memory to store captured +timestamps in a PMF specific linker section at build time. +Additionally, it defines necessary functions to capture and +retrieve a particular timestamp for the given service at runtime. + +The macro ``PMF_REGISTER_SERVICE()`` only enables capturing PMF timestamps +from within TF-A. In order to retrieve timestamps from outside of TF-A, the +``PMF_REGISTER_SERVICE_SMC()`` macro must be used instead. This macro +accepts the same set of arguments as the ``PMF_REGISTER_SERVICE()`` +macro but additionally supports retrieving timestamps using SMCs. + +Capturing a timestamp +~~~~~~~~~~~~~~~~~~~~~ + +PMF timestamps are stored in a per-service timestamp region. On a +system with multiple CPUs, each timestamp is captured and stored +in a per-CPU cache line aligned memory region. + +Having registered the service, the ``PMF_CAPTURE_TIMESTAMP()`` macro can be +used to capture a timestamp at the location where it is used. The macro +takes the service name, a local timestamp identifier and a flag as arguments. + +The ``flags`` field argument can be zero, or ``PMF_CACHE_MAINT`` which +instructs PMF to do cache maintenance following the capture. Cache +maintenance is required if any of the service's timestamps are captured +with data cache disabled. + +To capture a timestamp in assembly code, the caller should use +``pmf_calc_timestamp_addr`` macro (defined in ``pmf_asm_macros.S``) to +calculate the address of where the timestamp would be stored. The +caller should then read ``CNTPCT_EL0`` register to obtain the timestamp +and store it at the determined address for later retrieval. + +Retrieving a timestamp +~~~~~~~~~~~~~~~~~~~~~~ + +From within TF-A, timestamps for individual CPUs can be retrieved using either +``PMF_GET_TIMESTAMP_BY_MPIDR()`` or ``PMF_GET_TIMESTAMP_BY_INDEX()`` macros. +These macros accept the CPU's MPIDR value, or its ordinal position +respectively. + +From outside TF-A, timestamps for individual CPUs can be retrieved by calling +into ``pmf_smc_handler()``. + +:: + + Interface : pmf_smc_handler() + Argument : 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 : uintptr_t + + smc_fid: Holds the SMC identifier which is either `PMF_SMC_GET_TIMESTAMP_32` + when the caller of the SMC is running in AArch32 mode + or `PMF_SMC_GET_TIMESTAMP_64` when the caller is running in AArch64 mode. + x1: Timestamp identifier. + x2: The `mpidr` of the CPU for which the timestamp has to be retrieved. + This can be the `mpidr` of a different core to the one initiating + the SMC. In that case, service specific cache maintenance may be + required to ensure the updated copy of the timestamp is returned. + x3: A flags value that is either 0 or `PMF_CACHE_MAINT`. If + `PMF_CACHE_MAINT` is passed, then the PMF code will perform a + cache invalidate before reading the timestamp. This ensures + an updated copy is returned. + +The remaining arguments, ``x4``, ``cookie``, ``handle`` and ``flags`` are unused +in this implementation. + +PMF code structure +~~~~~~~~~~~~~~~~~~ + +#. ``pmf_main.c`` consists of core functions that implement service registration, + initialization, storing, dumping and retrieving timestamps. + +#. ``pmf_smc.c`` contains the SMC handling for registered PMF services. + +#. ``pmf.h`` contains the public interface to Performance Measurement Framework. + +#. ``pmf_asm_macros.S`` consists of macros to facilitate capturing timestamps in + assembly code. + +#. ``pmf_helpers.h`` is an internal header used by ``pmf.h``. + +Armv8-A Architecture Extensions +------------------------------- + +TF-A makes use of Armv8-A Architecture Extensions where applicable. This +section lists the usage of Architecture Extensions, and build flags +controlling them. + +In general, and unless individually mentioned, the build options +``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` select the Architecture Extension to +target when building TF-A. Subsequent Arm Architecture Extensions are backward +compatible with previous versions. + +The build system only requires that ``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` have a +valid numeric value. These build options only control whether or not +Architecture Extension-specific code is included in the build. Otherwise, TF-A +targets the base Armv8.0-A architecture; i.e. as if ``ARM_ARCH_MAJOR`` == 8 +and ``ARM_ARCH_MINOR`` == 0, which are also their respective default values. + +.. seealso:: :ref:`Build Options` + +For details on the Architecture Extension and available features, please refer +to the respective Architecture Extension Supplement. + +Armv8.1-A +~~~~~~~~~ + +This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` >= 8, or when +``ARM_ARCH_MAJOR`` == 8 and ``ARM_ARCH_MINOR`` >= 1. + +- By default, a load-/store-exclusive instruction pair is used to implement + spinlocks. The ``USE_SPINLOCK_CAS`` build option when set to 1 selects the + spinlock implementation using the ARMv8.1-LSE Compare and Swap instruction. + Notice this instruction is only available in AArch64 execution state, so + the option is only available to AArch64 builds. + +Armv8.2-A +~~~~~~~~~ + +- The presence of ARMv8.2-TTCNP is detected at runtime. When it is present, the + Common not Private (TTBRn_ELx.CnP) bit is enabled to indicate that multiple + Processing Elements in the same Inner Shareable domain use the same + translation table entries for a given stage of translation for a particular + translation regime. + +Armv8.3-A +~~~~~~~~~ + +- Pointer authentication features of Armv8.3-A are unconditionally enabled in + the Non-secure world so that lower ELs are allowed to use them without + causing a trap to EL3. + + In order to enable the Secure world to use it, ``CTX_INCLUDE_PAUTH_REGS`` + must be set to 1. This will add all pointer authentication system registers + to the context that is saved when doing a world switch. + + The TF-A itself has support for pointer authentication at runtime + that can be enabled by setting ``BRANCH_PROTECTION`` option to non-zero and + ``CTX_INCLUDE_PAUTH_REGS`` to 1. This enables pointer authentication in BL1, + BL2, BL31, and the TSP if it is used. + + Note that Pointer Authentication is enabled for Non-secure world irrespective + of the value of these build flags if the CPU supports it. + + If ``ARM_ARCH_MAJOR == 8`` and ``ARM_ARCH_MINOR >= 3`` the code footprint of + enabling PAuth is lower because the compiler will use the optimized + PAuth instructions rather than the backwards-compatible ones. + +Armv8.5-A +~~~~~~~~~ + +- Branch Target Identification feature is selected by ``BRANCH_PROTECTION`` + option set to 1. This option defaults to 0. + +- Memory Tagging Extension feature is unconditionally enabled for both worlds + (at EL0 and S-EL0) if it is only supported at EL0. If instead it is + implemented at all ELs, it is unconditionally enabled for only the normal + world. To enable it for the secure world as well, the build option + ``CTX_INCLUDE_MTE_REGS`` is required. If the hardware does not implement + MTE support at all, it is always disabled, no matter what build options + are used. + +Armv7-A +~~~~~~~ + +This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 7. + +There are several Armv7-A extensions available. Obviously the TrustZone +extension is mandatory to support the TF-A bootloader and runtime services. + +Platform implementing an Armv7-A system can to define from its target +Cortex-A architecture through ``ARM_CORTEX_A = yes`` in their +``platform.mk`` script. For example ``ARM_CORTEX_A15=yes`` for a +Cortex-A15 target. + +Platform can also set ``ARM_WITH_NEON=yes`` to enable neon support. +Note that using neon at runtime has constraints on non secure world context. +TF-A does not yet provide VFP context management. + +Directive ``ARM_CORTEX_A`` and ``ARM_WITH_NEON`` are used to set +the toolchain target architecture directive. + +Platform may choose to not define straight the toolchain target architecture +directive by defining ``MARCH32_DIRECTIVE``. +I.e: + +.. code:: make + + MARCH32_DIRECTIVE := -mach=armv7-a + +Code Structure +-------------- + +TF-A code is logically divided between the three boot loader stages mentioned +in the previous sections. The code is also divided into the following +categories (present as directories in the source code): + +- **Platform specific.** Choice of architecture specific code depends upon + the platform. +- **Common code.** This is platform and architecture agnostic code. +- **Library code.** This code comprises of functionality commonly used by all + other code. The PSCI implementation and other EL3 runtime frameworks reside + as Library components. +- **Stage specific.** Code specific to a boot stage. +- **Drivers.** +- **Services.** EL3 runtime services (eg: SPD). Specific SPD services + reside in the ``services/spd`` directory (e.g. ``services/spd/tspd``). + +Each boot loader stage uses code from one or more of the above mentioned +categories. Based upon the above, the code layout looks like this: + +:: + + Directory Used by BL1? Used by BL2? Used by BL31? + bl1 Yes No No + bl2 No Yes No + bl31 No No Yes + plat Yes Yes Yes + drivers Yes No Yes + common Yes Yes Yes + lib Yes Yes Yes + services No No Yes + +The build system provides a non configurable build option IMAGE_BLx for each +boot loader stage (where x = BL stage). e.g. for BL1 , IMAGE_BL1 will be +defined by the build system. This enables TF-A to compile certain code only +for specific boot loader stages + +All assembler files have the ``.S`` extension. The linker source files for each +boot stage have the extension ``.ld.S``. These are processed by GCC to create the +linker scripts which have the extension ``.ld``. + +FDTs provide a description of the hardware platform and are used by the Linux +kernel at boot time. These can be found in the ``fdts`` directory. + +.. rubric:: References + +- `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D)`_ + +- `Power State Coordination Interface PDD`_ + +- `SMC Calling Convention`_ + +- :ref:`Interrupt Management Framework` + +-------------- + +*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.* + +.. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _SMCCC: https://developer.arm.com/docs/den0028/latest +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a +.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture + +.. |Image 1| image:: ../resources/diagrams/rt-svc-descs-layout.png diff --git a/arm-trusted-firmware/docs/design/index.rst b/arm-trusted-firmware/docs/design/index.rst new file mode 100644 index 0000000..e3b8f74 --- /dev/null +++ b/arm-trusted-firmware/docs/design/index.rst @@ -0,0 +1,21 @@ +System Design +============= + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + alt-boot-flows + auth-framework + cpu-specific-build-macros + firmware-design + interrupt-framework-design + psci-pd-tree + reset-design + trusted-board-boot + trusted-board-boot-build + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design/interrupt-framework-design.rst b/arm-trusted-firmware/docs/design/interrupt-framework-design.rst new file mode 100644 index 0000000..dfb2eac --- /dev/null +++ b/arm-trusted-firmware/docs/design/interrupt-framework-design.rst @@ -0,0 +1,1021 @@ +Interrupt Management Framework +============================== + +This framework is responsible for managing interrupts routed to EL3. It also +allows EL3 software to configure the interrupt routing behavior. Its main +objective is to implement the following two requirements. + +#. It should be possible to route interrupts meant to be handled by secure + software (Secure interrupts) to EL3, when execution is in non-secure state + (normal world). The framework should then take care of handing control of + the interrupt to either software in EL3 or Secure-EL1 depending upon the + software configuration and the GIC implementation. This requirement ensures + that secure interrupts are under the control of the secure software with + respect to their delivery and handling without the possibility of + intervention from non-secure software. + +#. It should be possible to route interrupts meant to be handled by + non-secure software (Non-secure interrupts) to the last executed exception + level in the normal world when the execution is in secure world at + exception levels lower than EL3. This could be done with or without the + knowledge of software executing in Secure-EL1/Secure-EL0. The choice of + approach should be governed by the secure software. This requirement + ensures that non-secure software is able to execute in tandem with the + secure software without overriding it. + +Concepts +-------- + +Interrupt types +~~~~~~~~~~~~~~~ + +The framework categorises an interrupt to be one of the following depending upon +the exception level(s) it is handled in. + +#. Secure EL1 interrupt. This type of interrupt can be routed to EL3 or + Secure-EL1 depending upon the security state of the current execution + context. It is always handled in Secure-EL1. + +#. Non-secure interrupt. This type of interrupt can be routed to EL3, + Secure-EL1, Non-secure EL1 or EL2 depending upon the security state of the + current execution context. It is always handled in either Non-secure EL1 + or EL2. + +#. EL3 interrupt. This type of interrupt can be routed to EL3 or Secure-EL1 + depending upon the security state of the current execution context. It is + always handled in EL3. + +The following constants define the various interrupt types in the framework +implementation. + +.. code:: c + + #define INTR_TYPE_S_EL1 0 + #define INTR_TYPE_EL3 1 + #define INTR_TYPE_NS 2 + +Routing model +~~~~~~~~~~~~~ + +A type of interrupt can be either generated as an FIQ or an IRQ. The target +exception level of an interrupt type is configured through the FIQ and IRQ bits +in the Secure Configuration Register at EL3 (``SCR_EL3.FIQ`` and ``SCR_EL3.IRQ`` +bits). When ``SCR_EL3.FIQ``\ =1, FIQs are routed to EL3. Otherwise they are routed +to the First Exception Level (FEL) capable of handling interrupts. When +``SCR_EL3.IRQ``\ =1, IRQs are routed to EL3. Otherwise they are routed to the +FEL. This register is configured independently by EL3 software for each security +state prior to entry into a lower exception level in that security state. + +A routing model for a type of interrupt (generated as FIQ or IRQ) is defined as +its target exception level for each security state. It is represented by a +single bit for each security state. A value of ``0`` means that the interrupt +should be routed to the FEL. A value of ``1`` means that the interrupt should be +routed to EL3. A routing model is applicable only when execution is not in EL3. + +The default routing model for an interrupt type is to route it to the FEL in +either security state. + +Valid routing models +~~~~~~~~~~~~~~~~~~~~ + +The framework considers certain routing models for each type of interrupt to be +incorrect as they conflict with the requirements mentioned in Section 1. The +following sub-sections describe all the possible routing models and specify +which ones are valid or invalid. EL3 interrupts are currently supported only +for GIC version 3.0 (Arm GICv3) and only the Secure-EL1 and Non-secure interrupt +types are supported for GIC version 2.0 (Arm GICv2) (see `Assumptions in +Interrupt Management Framework`_). The terminology used in the following +sub-sections is explained below. + +#. **CSS**. Current Security State. ``0`` when secure and ``1`` when non-secure + +#. **TEL3**. Target Exception Level 3. ``0`` when targeted to the FEL. ``1`` when + targeted to EL3. + +Secure-EL1 interrupts +^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + secure state. This is a valid routing model as secure software is in + control of handling secure interrupts. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure + state. This is a valid routing model as secure software in EL3 can + handover the interrupt to Secure-EL1 for handling. + +#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in + non-secure state. This is an invalid routing model as a secure interrupt + is not visible to the secure software which violates the motivation behind + the Arm Security Extensions. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is a valid routing model as secure software in EL3 + can handover the interrupt to Secure-EL1 for handling. + +Non-secure interrupts +^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + secure state. This allows the secure software to trap non-secure + interrupts, perform its book-keeping and hand the interrupt to the + non-secure software through EL3. This is a valid routing model as secure + software is in control of how its execution is preempted by non-secure + interrupts. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure + state. This is a valid routing model as secure software in EL3 can save + the state of software in Secure-EL1/Secure-EL0 before handing the + interrupt to non-secure software. This model requires additional + coordination between Secure-EL1 and EL3 software to ensure that the + former's state is correctly saved by the latter. + +#. **CSS=1, TEL3=0**. Interrupt is routed to FEL when execution is in + non-secure state. This is a valid routing model as a non-secure interrupt + is handled by non-secure software. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is an invalid routing model as there is no valid + reason to route the interrupt to EL3 software and then hand it back to + non-secure software for handling. + +.. _EL3 interrupts: + +EL3 interrupts +^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + Secure-EL1/Secure-EL0. This is a valid routing model as secure software + in Secure-EL1/Secure-EL0 is in control of how its execution is preempted + by EL3 interrupt and can handover the interrupt to EL3 for handling. + + However, when ``EL3_EXCEPTION_HANDLING`` is ``1``, this routing model is + invalid as EL3 interrupts are unconditionally routed to EL3, and EL3 + interrupts will always preempt Secure EL1/EL0 execution. See :ref:`exception + handling` documentation. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in + Secure-EL1/Secure-EL0. This is a valid routing model as secure software + in EL3 can handle the interrupt. + +#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in + non-secure state. This is an invalid routing model as a secure interrupt + is not visible to the secure software which violates the motivation behind + the Arm Security Extensions. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is a valid routing model as secure software in EL3 + can handle the interrupt. + +Mapping of interrupt type to signal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The framework is meant to work with any interrupt controller implemented by a +platform. A interrupt controller could generate a type of interrupt as either an +FIQ or IRQ signal to the CPU depending upon the current security state. The +mapping between the type and signal is known only to the platform. The framework +uses this information to determine whether the IRQ or the FIQ bit should be +programmed in ``SCR_EL3`` while applying the routing model for a type of +interrupt. The platform provides this information through the +``plat_interrupt_type_to_line()`` API (described in the +:ref:`Porting Guide`). For example, on the FVP port when the platform uses an +Arm GICv2 interrupt controller, Secure-EL1 interrupts are signaled through the +FIQ signal while Non-secure interrupts are signaled through the IRQ signal. +This applies when execution is in either security state. + +Effect of mapping of several interrupt types to one signal +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It should be noted that if more than one interrupt type maps to a single +interrupt signal, and if any one of the interrupt type sets **TEL3=1** for a +particular security state, then interrupt signal will be routed to EL3 when in +that security state. This means that all the other interrupt types using the +same interrupt signal will be forced to the same routing model. This should be +borne in mind when choosing the routing model for an interrupt type. + +For example, in Arm GICv3, when the execution context is Secure-EL1/ +Secure-EL0, both the EL3 and the non secure interrupt types map to the FIQ +signal. So if either one of the interrupt type sets the routing model so +that **TEL3=1** when **CSS=0**, the FIQ bit in ``SCR_EL3`` will be programmed to +route the FIQ signal to EL3 when executing in Secure-EL1/Secure-EL0, thereby +effectively routing the other interrupt type also to EL3. + +Assumptions in Interrupt Management Framework +--------------------------------------------- + +The framework makes the following assumptions to simplify its implementation. + +#. Although the framework has support for 2 types of secure interrupts (EL3 + and Secure-EL1 interrupt), only interrupt controller architectures + like Arm GICv3 has architectural support for EL3 interrupts in the form of + Group 0 interrupts. In Arm GICv2, all secure interrupts are assumed to be + handled in Secure-EL1. They can be delivered to Secure-EL1 via EL3 but they + cannot be handled in EL3. + +#. Interrupt exceptions (``PSTATE.I`` and ``F`` bits) are masked during execution + in EL3. + +#. Interrupt management: the following sections describe how interrupts are + managed by the interrupt handling framework. This entails: + + #. Providing an interface to allow registration of a handler and + specification of the routing model for a type of interrupt. + + #. Implementing support to hand control of an interrupt type to its + registered handler when the interrupt is generated. + +Both aspects of interrupt management involve various components in the secure +software stack spanning from EL3 to Secure-EL1. These components are described +in the section `Software components`_. The framework stores information +associated with each type of interrupt in the following data structure. + +.. code:: c + + typedef struct intr_type_desc { + interrupt_type_handler_t handler; + uint32_t flags; + uint32_t scr_el3[2]; + } intr_type_desc_t; + +The ``flags`` field stores the routing model for the interrupt type in +bits[1:0]. Bit[0] stores the routing model when execution is in the secure +state. Bit[1] stores the routing model when execution is in the non-secure +state. As mentioned in Section `Routing model`_, a value of ``0`` implies that +the interrupt should be targeted to the FEL. A value of ``1`` implies that it +should be targeted to EL3. The remaining bits are reserved and SBZ. The helper +macro ``set_interrupt_rm_flag()`` should be used to set the bits in the +``flags`` parameter. + +The ``scr_el3[2]`` field also stores the routing model but as a mapping of the +model in the ``flags`` field to the corresponding bit in the ``SCR_EL3`` for each +security state. + +The framework also depends upon the platform port to configure the interrupt +controller to distinguish between secure and non-secure interrupts. The platform +is expected to be aware of the secure devices present in the system and their +associated interrupt numbers. It should configure the interrupt controller to +enable the secure interrupts, ensure that their priority is always higher than +the non-secure interrupts and target them to the primary CPU. It should also +export the interface described in the :ref:`Porting Guide` to enable +handling of interrupts. + +In the remainder of this document, for the sake of simplicity a Arm GICv2 system +is considered and it is assumed that the FIQ signal is used to generate Secure-EL1 +interrupts and the IRQ signal is used to generate non-secure interrupts in either +security state. EL3 interrupts are not considered. + +Software components +------------------- + +Roles and responsibilities for interrupt management are sub-divided between the +following components of software running in EL3 and Secure-EL1. Each component is +briefly described below. + +#. EL3 Runtime Firmware. This component is common to all ports of TF-A. + +#. Secure Payload Dispatcher (SPD) service. This service interfaces with the + Secure Payload (SP) software which runs in Secure-EL1/Secure-EL0 and is + responsible for switching execution between secure and non-secure states. + A switch is triggered by a Secure Monitor Call and it uses the APIs + exported by the Context management library to implement this functionality. + Switching execution between the two security states is a requirement for + interrupt management as well. This results in a significant dependency on + the SPD service. TF-A implements an example Test Secure Payload Dispatcher + (TSPD) service. + + An SPD service plugs into the EL3 runtime firmware and could be common to + some ports of TF-A. + +#. Secure Payload (SP). On a production system, the Secure Payload corresponds + to a Secure OS which runs in Secure-EL1/Secure-EL0. It interfaces with the + SPD service to manage communication with non-secure software. TF-A + implements an example secure payload called Test Secure Payload (TSP) + which runs only in Secure-EL1. + + A Secure payload implementation could be common to some ports of TF-A, + just like the SPD service. + +Interrupt registration +---------------------- + +This section describes in detail the role of each software component (see +`Software components`_) during the registration of a handler for an interrupt +type. + +.. _el3-runtime-firmware: + +EL3 runtime firmware +~~~~~~~~~~~~~~~~~~~~ + +This component declares the following prototype for a handler of an interrupt type. + +.. code:: c + + typedef uint64_t (*interrupt_type_handler_t)(uint32_t id, + uint32_t flags, + void *handle, + void *cookie); + +The ``id`` is parameter is reserved and could be used in the future for passing +the interrupt id of the highest pending interrupt only if there is a foolproof +way of determining the id. Currently it contains ``INTR_ID_UNAVAILABLE``. + +The ``flags`` parameter contains miscellaneous information as follows. + +#. Security state, bit[0]. This bit indicates the security state of the lower + exception level when the interrupt was generated. A value of ``1`` means + that it was in the non-secure state. A value of ``0`` indicates that it was + in the secure state. This bit can be used by the handler to ensure that + interrupt was generated and routed as per the routing model specified + during registration. + +#. Reserved, bits[31:1]. The remaining bits are reserved for future use. + +The ``handle`` parameter points to the ``cpu_context`` structure of the current CPU +for the security state specified in the ``flags`` parameter. + +Once the handler routine completes, execution will return to either the secure +or non-secure state. The handler routine must return a pointer to +``cpu_context`` structure of the current CPU for the target security state. On +AArch64, this return value is currently ignored by the caller as the +appropriate ``cpu_context`` to be used is expected to be set by the handler +via the context management library APIs. +A portable interrupt handler implementation must set the target context both in +the structure pointed to by the returned pointer and via the context management +library APIs. The handler should treat all error conditions as critical errors +and take appropriate action within its implementation e.g. use assertion +failures. + +The runtime firmware provides the following API for registering a handler for a +particular type of interrupt. A Secure Payload Dispatcher service should use +this API to register a handler for Secure-EL1 and optionally for non-secure +interrupts. This API also requires the caller to specify the routing model for +the type of interrupt. + +.. code:: c + + int32_t register_interrupt_type_handler(uint32_t type, + interrupt_type_handler handler, + uint64_t flags); + +The ``type`` parameter can be one of the three interrupt types listed above i.e. +``INTR_TYPE_S_EL1``, ``INTR_TYPE_NS`` & ``INTR_TYPE_EL3``. The ``flags`` parameter +is as described in Section 2. + +The function will return ``0`` upon a successful registration. It will return +``-EALREADY`` in case a handler for the interrupt type has already been +registered. If the ``type`` is unrecognised or the ``flags`` or the ``handler`` are +invalid it will return ``-EINVAL``. + +Interrupt routing is governed by the configuration of the ``SCR_EL3.FIQ/IRQ`` bits +prior to entry into a lower exception level in either security state. The +context management library maintains a copy of the ``SCR_EL3`` system register for +each security state in the ``cpu_context`` structure of each CPU. It exports the +following APIs to let EL3 Runtime Firmware program and retrieve the routing +model for each security state for the current CPU. The value of ``SCR_EL3`` stored +in the ``cpu_context`` is used by the ``el3_exit()`` function to program the +``SCR_EL3`` register prior to returning from the EL3 exception level. + +.. code:: c + + uint32_t cm_get_scr_el3(uint32_t security_state); + void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value); + +``cm_get_scr_el3()`` returns the value of the ``SCR_EL3`` register for the specified +security state of the current CPU. ``cm_write_scr_el3_bit()`` writes a ``0`` or ``1`` +to the bit specified by ``bit_pos``. ``register_interrupt_type_handler()`` invokes +``set_routing_model()`` API which programs the ``SCR_EL3`` according to the routing +model using the ``cm_get_scr_el3()`` and ``cm_write_scr_el3_bit()`` APIs. + +It is worth noting that in the current implementation of the framework, the EL3 +runtime firmware is responsible for programming the routing model. The SPD is +responsible for ensuring that the routing model has been adhered to upon +receiving an interrupt. + +.. _spd-int-registration: + +Secure payload dispatcher +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A SPD service is responsible for determining and maintaining the interrupt +routing model supported by itself and the Secure Payload. It is also responsible +for ferrying interrupts between secure and non-secure software depending upon +the routing model. It could determine the routing model at build time or at +runtime. It must use this information to register a handler for each interrupt +type using the ``register_interrupt_type_handler()`` API in EL3 runtime firmware. + +If the routing model is not known to the SPD service at build time, then it must +be provided by the SP as the result of its initialisation. The SPD should +program the routing model only after SP initialisation has completed e.g. in the +SPD initialisation function pointed to by the ``bl32_init`` variable. + +The SPD should determine the mechanism to pass control to the Secure Payload +after receiving an interrupt from the EL3 runtime firmware. This information +could either be provided to the SPD service at build time or by the SP at +runtime. + +Test secure payload dispatcher behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + Where this document discusses ``TSP_NS_INTR_ASYNC_PREEMPT`` as being + ``1``, the same results also apply when ``EL3_EXCEPTION_HANDLING`` is ``1``. + +The TSPD only handles Secure-EL1 interrupts and is provided with the following +routing model at build time. + +- Secure-EL1 interrupts are routed to EL3 when execution is in non-secure + state and are routed to the FEL when execution is in the secure state + i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=1** for Secure-EL1 interrupts + +- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is zero, the default routing + model is used for non-secure interrupts. They are routed to the FEL in + either security state i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=0** for + Non-secure interrupts. + +- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, then the + non secure interrupts are routed to EL3 when execution is in secure state + i.e **CSS=0, TEL3=1** for non-secure interrupts. This effectively preempts + Secure-EL1. The default routing model is used for non secure interrupts in + non-secure state. i.e **CSS=1, TEL3=0**. + +It performs the following actions in the ``tspd_init()`` function to fulfill the +requirements mentioned earlier. + +#. It passes control to the Test Secure Payload to perform its + initialisation. The TSP provides the address of the vector table + ``tsp_vectors`` in the SP which also includes the handler for Secure-EL1 + interrupts in the ``sel1_intr_entry`` field. The TSPD passes control to the TSP at + this address when it receives a Secure-EL1 interrupt. + + The handover agreement between the TSP and the TSPD requires that the TSPD + masks all interrupts (``PSTATE.DAIF`` bits) when it calls + ``tsp_sel1_intr_entry()``. The TSP has to preserve the callee saved general + purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use + ``x0-x18`` to enable its C runtime. + +#. The TSPD implements a handler function for Secure-EL1 interrupts. This + function is registered with the EL3 runtime firmware using the + ``register_interrupt_type_handler()`` API as follows + + .. code:: c + + /* Forward declaration */ + interrupt_type_handler tspd_secure_el1_interrupt_handler; + int32_t rc, flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tspd_secure_el1_interrupt_handler, + flags); + if (rc) + panic(); + +#. When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, the TSPD + implements a handler function for non-secure interrupts. This function is + registered with the EL3 runtime firmware using the + ``register_interrupt_type_handler()`` API as follows + + .. code:: c + + /* Forward declaration */ + interrupt_type_handler tspd_ns_interrupt_handler; + int32_t rc, flags = 0; + set_interrupt_rm_flag(flags, SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_NS, + tspd_ns_interrupt_handler, + flags); + if (rc) + panic(); + +.. _sp-int-registration: + +Secure payload +~~~~~~~~~~~~~~ + +A Secure Payload must implement an interrupt handling framework at Secure-EL1 +(Secure-EL1 IHF) to support its chosen interrupt routing model. Secure payload +execution will alternate between the below cases. + +#. In the code where IRQ, FIQ or both interrupts are enabled, if an interrupt + type is targeted to the FEL, then it will be routed to the Secure-EL1 + exception vector table. This is defined as the **asynchronous mode** of + handling interrupts. This mode applies to both Secure-EL1 and non-secure + interrupts. + +#. In the code where both interrupts are disabled, if an interrupt type is + targeted to the FEL, then execution will eventually migrate to the + non-secure state. Any non-secure interrupts will be handled as described + in the routing model where **CSS=1 and TEL3=0**. Secure-EL1 interrupts + will be routed to EL3 (as per the routing model where **CSS=1 and + TEL3=1**) where the SPD service will hand them to the SP. This is defined + as the **synchronous mode** of handling interrupts. + +The interrupt handling framework implemented by the SP should support one or +both these interrupt handling models depending upon the chosen routing model. + +The following list briefly describes how the choice of a valid routing model +(see `Valid routing models`_) effects the implementation of the Secure-EL1 +IHF. If the choice of the interrupt routing model is not known to the SPD +service at compile time, then the SP should pass this information to the SPD +service at runtime during its initialisation phase. + +As mentioned earlier, an Arm GICv2 system is considered and it is assumed that +the FIQ signal is used to generate Secure-EL1 interrupts and the IRQ signal +is used to generate non-secure interrupts in either security state. + +Secure payload IHF design w.r.t secure-EL1 interrupts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. If ``PSTATE.F=0``, Secure-EL1 interrupts will be + triggered at one of the Secure-EL1 FIQ exception vectors. The Secure-EL1 + IHF should implement support for handling FIQ interrupts asynchronously. + + If ``PSTATE.F=1`` then Secure-EL1 interrupts will be handled as per the + synchronous interrupt handling model. The SP could implement this scenario + by exporting a separate entrypoint for Secure-EL1 interrupts to the SPD + service during the registration phase. The SPD service would also need to + know the state of the system, general purpose and the ``PSTATE`` registers + in which it should arrange to return execution to the SP. The SP should + provide this information in an implementation defined way during the + registration phase if it is not known to the SPD service at build time. + +#. **CSS=1, TEL3=1**. Interrupts are routed to EL3 when execution is in + non-secure state. They should be handled through the synchronous interrupt + handling model as described in 1. above. + +#. **CSS=0, TEL3=1**. Secure-EL1 interrupts are routed to EL3 when execution + is in secure state. They will not be visible to the SP. The ``PSTATE.F`` bit + in Secure-EL1/Secure-EL0 will not mask FIQs. The EL3 runtime firmware will + call the handler registered by the SPD service for Secure-EL1 interrupts. + Secure-EL1 IHF should then handle all Secure-EL1 interrupt through the + synchronous interrupt handling model described in 1. above. + +Secure payload IHF design w.r.t non-secure interrupts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. If ``PSTATE.I=0``, non-secure interrupts will be + triggered at one of the Secure-EL1 IRQ exception vectors . The Secure-EL1 + IHF should co-ordinate with the SPD service to transfer execution to the + non-secure state where the interrupt should be handled e.g the SP could + allocate a function identifier to issue a SMC64 or SMC32 to the SPD + service which indicates that the SP execution has been preempted by a + non-secure interrupt. If this function identifier is not known to the SPD + service at compile time then the SP could provide it during the + registration phase. + + If ``PSTATE.I=1`` then the non-secure interrupt will pend until execution + resumes in the non-secure state. + +#. **CSS=0, TEL3=1**. Non-secure interrupts are routed to EL3. They will not + be visible to the SP. The ``PSTATE.I`` bit in Secure-EL1/Secure-EL0 will + have not effect. The SPD service should register a non-secure interrupt + handler which should save the SP state correctly and resume execution in + the non-secure state where the interrupt will be handled. The Secure-EL1 + IHF does not need to take any action. + +#. **CSS=1, TEL3=0**. Non-secure interrupts are handled in the FEL in + non-secure state (EL1/EL2) and are not visible to the SP. This routing + model does not affect the SP behavior. + +A Secure Payload must also ensure that all Secure-EL1 interrupts are correctly +configured at the interrupt controller by the platform port of the EL3 runtime +firmware. It should configure any additional Secure-EL1 interrupts which the EL3 +runtime firmware is not aware of through its platform port. + +Test secure payload behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is +described in Section `Secure Payload Dispatcher`__. It is known to the TSPD +service at build time. + +.. __: #spd-int-registration + +The TSP implements an entrypoint (``tsp_sel1_intr_entry()``) for handling Secure-EL1 +interrupts taken in non-secure state and routed through the TSPD service +(synchronous handling model). It passes the reference to this entrypoint via +``tsp_vectors`` to the TSPD service. + +The TSP also replaces the default exception vector table referenced through the +``early_exceptions`` variable, with a vector table capable of handling FIQ and IRQ +exceptions taken at the same (Secure-EL1) exception level. This table is +referenced through the ``tsp_exceptions`` variable and programmed into the +VBAR_EL1. It caters for the asynchronous handling model. + +The TSP also programs the Secure Physical Timer in the Arm Generic Timer block +to raise a periodic interrupt (every half a second) for the purpose of testing +interrupt management across all the software components listed in `Software +components`_. + +Interrupt handling +------------------ + +This section describes in detail the role of each software component (see +Section `Software components`_) in handling an interrupt of a particular type. + +EL3 runtime firmware +~~~~~~~~~~~~~~~~~~~~ + +The EL3 runtime firmware populates the IRQ and FIQ exception vectors referenced +by the ``runtime_exceptions`` variable as follows. + +#. IRQ and FIQ exceptions taken from the current exception level with + ``SP_EL0`` or ``SP_EL3`` are reported as irrecoverable error conditions. As + mentioned earlier, EL3 runtime firmware always executes with the + ``PSTATE.I`` and ``PSTATE.F`` bits set. + +#. The following text describes how the IRQ and FIQ exceptions taken from a + lower exception level using AArch64 or AArch32 are handled. + +When an interrupt is generated, the vector for each interrupt type is +responsible for: + +#. Saving the entire general purpose register context (x0-x30) immediately + upon exception entry. The registers are saved in the per-cpu ``cpu_context`` + data structure referenced by the ``SP_EL3``\ register. + +#. Saving the ``ELR_EL3``, ``SP_EL0`` and ``SPSR_EL3`` system registers in the + per-cpu ``cpu_context`` data structure referenced by the ``SP_EL3`` register. + +#. Switching to the C runtime stack by restoring the ``CTX_RUNTIME_SP`` value + from the per-cpu ``cpu_context`` data structure in ``SP_EL0`` and + executing the ``msr spsel, #0`` instruction. + +#. Determining the type of interrupt. Secure-EL1 interrupts will be signaled + at the FIQ vector. Non-secure interrupts will be signaled at the IRQ + vector. The platform should implement the following API to determine the + type of the pending interrupt. + + .. code:: c + + uint32_t plat_ic_get_interrupt_type(void); + + It should return either ``INTR_TYPE_S_EL1`` or ``INTR_TYPE_NS``. + +#. Determining the handler for the type of interrupt that has been generated. + The following API has been added for this purpose. + + .. code:: c + + interrupt_type_handler get_interrupt_type_handler(uint32_t interrupt_type); + + It returns the reference to the registered handler for this interrupt + type. The ``handler`` is retrieved from the ``intr_type_desc_t`` structure as + described in Section 2. ``NULL`` is returned if no handler has been + registered for this type of interrupt. This scenario is reported as an + irrecoverable error condition. + +#. Calling the registered handler function for the interrupt type generated. + The ``id`` parameter is set to ``INTR_ID_UNAVAILABLE`` currently. The id along + with the current security state and a reference to the ``cpu_context_t`` + structure for the current security state are passed to the handler function + as its arguments. + + The handler function returns a reference to the per-cpu ``cpu_context_t`` + structure for the target security state. + +#. Calling ``el3_exit()`` to return from EL3 into a lower exception level in + the security state determined by the handler routine. The ``el3_exit()`` + function is responsible for restoring the register context from the + ``cpu_context_t`` data structure for the target security state. + +Secure payload dispatcher +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interrupt entry +^^^^^^^^^^^^^^^ + +The SPD service begins handling an interrupt when the EL3 runtime firmware calls +the handler function for that type of interrupt. The SPD service is responsible +for the following: + +#. Validating the interrupt. This involves ensuring that the interrupt was + generated according to the interrupt routing model specified by the SPD + service during registration. It should use the security state of the + exception level (passed in the ``flags`` parameter of the handler) where + the interrupt was taken from to determine this. If the interrupt is not + recognised then the handler should treat it as an irrecoverable error + condition. + + An SPD service can register a handler for Secure-EL1 and/or Non-secure + interrupts. A non-secure interrupt should never be routed to EL3 from + from non-secure state. Also if a routing model is chosen where Secure-EL1 + interrupts are routed to S-EL1 when execution is in Secure state, then a + S-EL1 interrupt should never be routed to EL3 from secure state. The handler + could use the security state flag to check this. + +#. Determining whether a context switch is required. This depends upon the + routing model and interrupt type. For non secure and S-EL1 interrupt, + if the security state of the execution context where the interrupt was + generated is not the same as the security state required for handling + the interrupt, a context switch is required. The following 2 cases + require a context switch from secure to non-secure or vice-versa: + + #. A Secure-EL1 interrupt taken from the non-secure state should be + routed to the Secure Payload. + + #. A non-secure interrupt taken from the secure state should be routed + to the last known non-secure exception level. + + The SPD service must save the system register context of the current + security state. It must then restore the system register context of the + target security state. It should use the ``cm_set_next_eret_context()`` API + to ensure that the next ``cpu_context`` to be restored is of the target + security state. + + If the target state is secure then execution should be handed to the SP as + per the synchronous interrupt handling model it implements. A Secure-EL1 + interrupt can be routed to EL3 while execution is in the SP. This implies + that SP execution can be preempted while handling an interrupt by a + another higher priority Secure-EL1 interrupt or a EL3 interrupt. The SPD + service should be able to handle this preemption or manage secure interrupt + priorities before handing control to the SP. + +#. Setting the return value of the handler to the per-cpu ``cpu_context`` if + the interrupt has been successfully validated and ready to be handled at a + lower exception level. + +The routing model allows non-secure interrupts to interrupt Secure-EL1 when in +secure state if it has been configured to do so. The SPD service and the SP +should implement a mechanism for routing these interrupts to the last known +exception level in the non-secure state. The former should save the SP context, +restore the non-secure context and arrange for entry into the non-secure state +so that the interrupt can be handled. + +Interrupt exit +^^^^^^^^^^^^^^ + +When the Secure Payload has finished handling a Secure-EL1 interrupt, it could +return control back to the SPD service through a SMC32 or SMC64. The SPD service +should handle this secure monitor call so that execution resumes in the +exception level and the security state from where the Secure-EL1 interrupt was +originally taken. + +Test secure payload dispatcher Secure-EL1 interrupt handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The example TSPD service registers a handler for Secure-EL1 interrupts taken +from the non-secure state. During execution in S-EL1, the TSPD expects that the +Secure-EL1 interrupts are handled in S-EL1 by TSP. Its handler +``tspd_secure_el1_interrupt_handler()`` expects only to be invoked for Secure-EL1 +originating from the non-secure state. It takes the following actions upon being +invoked. + +#. It uses the security state provided in the ``flags`` parameter to ensure + that the secure interrupt originated from the non-secure state. It asserts + if this is not the case. + +#. It saves the system register context for the non-secure state by calling + ``cm_el1_sysregs_context_save(NON_SECURE);``. + +#. It sets the ``ELR_EL3`` system register to ``tsp_sel1_intr_entry`` and sets the + ``SPSR_EL3.DAIF`` bits in the secure CPU context. It sets ``x0`` to + ``TSP_HANDLE_SEL1_INTR_AND_RETURN``. If the TSP was preempted earlier by a non + secure interrupt during ``yielding`` SMC processing, save the registers that + will be trashed, which is the ``ELR_EL3`` and ``SPSR_EL3``, in order to be able + to re-enter TSP for Secure-EL1 interrupt processing. It does not need to + save any other secure context since the TSP is expected to preserve it + (see section `Test secure payload dispatcher behavior`_). + +#. It restores the system register context for the secure state by calling + ``cm_el1_sysregs_context_restore(SECURE);``. + +#. It ensures that the secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(SECURE);``. + +#. It returns the per-cpu ``cpu_context`` to indicate that the interrupt can + now be handled by the SP. ``x1`` is written with the value of ``elr_el3`` + register for the non-secure state. This information is used by the SP for + debugging purposes. + +The figure below describes how the interrupt handling is implemented by the TSPD +when a Secure-EL1 interrupt is generated when execution is in the non-secure +state. + +|Image 1| + +The TSP issues an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier to +signal completion of interrupt handling. + +The TSPD service takes the following actions in ``tspd_smc_handler()`` function +upon receiving an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier: + +#. It ensures that the call originated from the secure state otherwise + execution returns to the non-secure state with ``SMC_UNK`` in ``x0``. + +#. It restores the saved ``ELR_EL3`` and ``SPSR_EL3`` system registers back to + the secure CPU context (see step 3 above) in case the TSP had been preempted + by a non secure interrupt earlier. + +#. It restores the system register context for the non-secure state by + calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. + +#. It ensures that the non-secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. + +#. ``tspd_smc_handler()`` returns a reference to the non-secure ``cpu_context`` + as the return value. + +Test secure payload dispatcher non-secure interrupt handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TSP in Secure-EL1 can be preempted by a non-secure interrupt during +``yielding`` SMC processing or by a higher priority EL3 interrupt during +Secure-EL1 interrupt processing. When ``EL3_EXCEPTION_HANDLING`` is ``0``, only +non-secure interrupts can cause preemption of TSP since there are no EL3 +interrupts in the system. With ``EL3_EXCEPTION_HANDLING=1`` however, any EL3 +interrupt may preempt Secure execution. + +It should be noted that while TSP is preempted, the TSPD only allows entry into +the TSP either for Secure-EL1 interrupt handling or for resuming the preempted +``yielding`` SMC in response to the ``TSP_FID_RESUME`` SMC from the normal world. +(See Section `Implication of preempted SMC on Non-Secure Software`_). + +The non-secure interrupt triggered in Secure-EL1 during ``yielding`` SMC +processing can be routed to either EL3 or Secure-EL1 and is controlled by build +option ``TSP_NS_INTR_ASYNC_PREEMPT`` (see Section `Test secure payload +dispatcher behavior`_). If the build option is set, the TSPD will set the +routing model for the non-secure interrupt to be routed to EL3 from secure state +i.e. **TEL3=1, CSS=0** and registers ``tspd_ns_interrupt_handler()`` as the +non-secure interrupt handler. The ``tspd_ns_interrupt_handler()`` on being +invoked ensures that the interrupt originated from the secure state and disables +routing of non-secure interrupts from secure state to EL3. This is to prevent +further preemption (by a non-secure interrupt) when TSP is reentered for +handling Secure-EL1 interrupts that triggered while execution was in the normal +world. The ``tspd_ns_interrupt_handler()`` then invokes +``tspd_handle_sp_preemption()`` for further handling. + +If the ``TSP_NS_INTR_ASYNC_PREEMPT`` build option is zero (default), the default +routing model for non-secure interrupt in secure state is in effect +i.e. **TEL3=0, CSS=0**. During ``yielding`` SMC processing, the IRQ +exceptions are unmasked i.e. ``PSTATE.I=0``, and a non-secure interrupt will +trigger at Secure-EL1 IRQ exception vector. The TSP saves the general purpose +register context and issues an SMC with ``TSP_PREEMPTED`` as the function +identifier to signal preemption of TSP. The TSPD SMC handler, +``tspd_smc_handler()``, ensures that the SMC call originated from the +secure state otherwise execution returns to the non-secure state with +``SMC_UNK`` in ``x0``. It then invokes ``tspd_handle_sp_preemption()`` for +further handling. + +The ``tspd_handle_sp_preemption()`` takes the following actions upon being +invoked: + +#. It saves the system register context for the secure state by calling + ``cm_el1_sysregs_context_save(SECURE)``. + +#. It restores the system register context for the non-secure state by + calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. + +#. It ensures that the non-secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. + +#. ``SMC_PREEMPTED`` is set in x0 and return to non secure state after + restoring non secure context. + +The Normal World is expected to resume the TSP after the ``yielding`` SMC +preemption by issuing an SMC with ``TSP_FID_RESUME`` as the function identifier +(see section `Implication of preempted SMC on Non-Secure Software`_). The TSPD +service takes the following actions in ``tspd_smc_handler()`` function upon +receiving this SMC: + +#. It ensures that the call originated from the non secure state. An + assertion is raised otherwise. + +#. Checks whether the TSP needs a resume i.e check if it was preempted. It + then saves the system register context for the non-secure state by calling + ``cm_el1_sysregs_context_save(NON_SECURE)``. + +#. Restores the secure context by calling + ``cm_el1_sysregs_context_restore(SECURE)`` + +#. It ensures that the secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(SECURE)``. + +#. ``tspd_smc_handler()`` returns a reference to the secure ``cpu_context`` as the + return value. + +The figure below describes how the TSP/TSPD handle a non-secure interrupt when +it is generated during execution in the TSP with ``PSTATE.I`` = 0 when the +``TSP_NS_INTR_ASYNC_PREEMPT`` build flag is 0. + +|Image 2| + +.. _sp-synchronous-int: + +Secure payload interrupt handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The SP should implement one or both of the synchronous and asynchronous +interrupt handling models depending upon the interrupt routing model it has +chosen (as described in section :ref:`Secure Payload `). + +In the synchronous model, it should begin handling a Secure-EL1 interrupt after +receiving control from the SPD service at an entrypoint agreed upon during build +time or during the registration phase. Before handling the interrupt, the SP +should save any Secure-EL1 system register context which is needed for resuming +normal execution in the SP later e.g. ``SPSR_EL1``, ``ELR_EL1``. After handling +the interrupt, the SP could return control back to the exception level and +security state where the interrupt was originally taken from. The SP should use +an SMC32 or SMC64 to ask the SPD service to do this. + +In the asynchronous model, the Secure Payload is responsible for handling +non-secure and Secure-EL1 interrupts at the IRQ and FIQ vectors in its exception +vector table when ``PSTATE.I`` and ``PSTATE.F`` bits are 0. As described earlier, +when a non-secure interrupt is generated, the SP should coordinate with the SPD +service to pass control back to the non-secure state in the last known exception +level. This will allow the non-secure interrupt to be handled in the non-secure +state. + +Test secure payload behavior +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TSPD hands control of a Secure-EL1 interrupt to the TSP at the +``tsp_sel1_intr_entry()``. The TSP handles the interrupt while ensuring that the +handover agreement described in Section `Test secure payload dispatcher +behavior`_ is maintained. It updates some statistics by calling +``tsp_update_sync_sel1_intr_stats()``. It then calls +``tsp_common_int_handler()`` which. + +#. Checks whether the interrupt is the secure physical timer interrupt. It + uses the platform API ``plat_ic_get_pending_interrupt_id()`` to get the + interrupt number. If it is not the secure physical timer interrupt, then + that means that a higher priority interrupt has preempted it. Invoke + ``tsp_handle_preemption()`` to handover control back to EL3 by issuing + an SMC with ``TSP_PREEMPTED`` as the function identifier. + +#. Handles the secure timer interrupt interrupt by acknowledging it using the + ``plat_ic_acknowledge_interrupt()`` platform API, calling + ``tsp_generic_timer_handler()`` to reprogram the secure physical generic + timer and calling the ``plat_ic_end_of_interrupt()`` platform API to signal + end of interrupt processing. + +The TSP passes control back to the TSPD by issuing an SMC64 with +``TSP_HANDLED_S_EL1_INTR`` as the function identifier. + +The TSP handles interrupts under the asynchronous model as follows. + +#. Secure-EL1 interrupts are handled by calling the ``tsp_common_int_handler()`` + function. The function has been described above. + +#. Non-secure interrupts are handled by calling the ``tsp_common_int_handler()`` + function which ends up invoking ``tsp_handle_preemption()`` and issuing an + SMC64 with ``TSP_PREEMPTED`` as the function identifier. Execution resumes at + the instruction that follows this SMC instruction when the TSPD hands control + to the TSP in response to an SMC with ``TSP_FID_RESUME`` as the function + identifier from the non-secure state (see section `Test secure payload + dispatcher non-secure interrupt handling`_). + +Other considerations +-------------------- + +Implication of preempted SMC on Non-Secure Software +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A ``yielding`` SMC call to Secure payload can be preempted by a non-secure +interrupt and the execution can return to the non-secure world for handling +the interrupt (For details on ``yielding`` SMC refer `SMC calling convention`_). +In this case, the SMC call has not completed its execution and the execution +must return back to the secure payload to resume the preempted SMC call. +This can be achieved by issuing an SMC call which instructs to resume the +preempted SMC. + +A ``fast`` SMC cannot be preempted and hence this case will not happen for +a fast SMC call. + +In the Test Secure Payload implementation, ``TSP_FID_RESUME`` is designated +as the resume SMC FID. It is important to note that ``TSP_FID_RESUME`` is a +``yielding`` SMC which means it too can be be preempted. The typical non +secure software sequence for issuing a ``yielding`` SMC would look like this, +assuming ``P.STATE.I=0`` in the non secure state : + +.. code:: c + + int rc; + rc = smc(TSP_YIELD_SMC_FID, ...); /* Issue a Yielding SMC call */ + /* The pending non-secure interrupt is handled by the interrupt handler + and returns back here. */ + while (rc == SMC_PREEMPTED) { /* Check if the SMC call is preempted */ + rc = smc(TSP_FID_RESUME); /* Issue resume SMC call */ + } + +The ``TSP_YIELD_SMC_FID`` is any ``yielding`` SMC function identifier and the smc() +function invokes a SMC call with the required arguments. The pending non-secure +interrupt causes an IRQ exception and the IRQ handler registered at the +exception vector handles the non-secure interrupt and returns. The return value +from the SMC call is tested for ``SMC_PREEMPTED`` to check whether it is +preempted. If it is, then the resume SMC call ``TSP_FID_RESUME`` is issued. The +return value of the SMC call is tested again to check if it is preempted. +This is done in a loop till the SMC call succeeds or fails. If a ``yielding`` +SMC is preempted, until it is resumed using ``TSP_FID_RESUME`` SMC and +completed, the current TSPD prevents any other SMC call from re-entering +TSP by returning ``SMC_UNK`` error. + +-------------- + +*Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.* + +.. _SMC calling convention: https://developer.arm.com/docs/den0028/latest + +.. |Image 1| image:: ../resources/diagrams/sec-int-handling.png +.. |Image 2| image:: ../resources/diagrams/non-sec-int-handling.png diff --git a/arm-trusted-firmware/docs/design/psci-pd-tree.rst b/arm-trusted-firmware/docs/design/psci-pd-tree.rst new file mode 100644 index 0000000..56a6d6f --- /dev/null +++ b/arm-trusted-firmware/docs/design/psci-pd-tree.rst @@ -0,0 +1,304 @@ +PSCI Power Domain Tree Structure +================================ + +Requirements +------------ + +#. A platform must export the ``plat_get_aff_count()`` and + ``plat_get_aff_state()`` APIs to enable the generic PSCI code to + populate a tree that describes the hierarchy of power domains in the + system. This approach is inflexible because a change to the topology + requires a change in the code. + + It would be much simpler for the platform to describe its power domain tree + in a data structure. + +#. The generic PSCI code generates MPIDRs in order to populate the power domain + tree. It also uses an MPIDR to find a node in the tree. The assumption that + a platform will use exactly the same MPIDRs as generated by the generic PSCI + code is not scalable. The use of an MPIDR also restricts the number of + levels in the power domain tree to four. + + Therefore, there is a need to decouple allocation of MPIDRs from the + mechanism used to populate the power domain topology tree. + +#. The current arrangement of the power domain tree requires a binary search + over the sibling nodes at a particular level to find a specified power + domain node. During a power management operation, the tree is traversed from + a 'start' to an 'end' power level. The binary search is required to find the + node at each level. The natural way to perform this traversal is to + start from a leaf node and follow the parent node pointer to reach the end + level. + + Therefore, there is a need to define data structures that implement the tree in + a way which facilitates such a traversal. + +#. The attributes of a core power domain differ from the attributes of power + domains at higher levels. For example, only a core power domain can be identified + using an MPIDR. There is no requirement to perform state coordination while + performing a power management operation on the core power domain. + + Therefore, there is a need to implement the tree in a way which facilitates this + distinction between a leaf and non-leaf node and any associated + optimizations. + +-------------- + +Design +------ + +Describing a power domain tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 1., the existing platform APIs +``plat_get_aff_count()`` and ``plat_get_aff_state()`` have been +removed. A platform must define an array of unsigned chars such that: + +#. The first entry in the array specifies the number of power domains at the + highest power level implemented in the platform. This caters for platforms + where the power domain tree does not have a single root node, for example, + the FVP has two cluster power domains at the highest level (1). + +#. Each subsequent entry corresponds to a power domain and contains the number + of power domains that are its direct children. + +#. The size of the array minus the first entry will be equal to the number of + non-leaf power domains. + +#. The value in each entry in the array is used to find the number of entries + to consider at the next level. The sum of the values (number of children) of + all the entries at a level specifies the number of entries in the array for + the next level. + +The following example power domain topology tree will be used to describe the +above text further. The leaf and non-leaf nodes in this tree have been numbered +separately. + +:: + + +-+ + |0| + +-+ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + +-+ +-+ + |1| |2| + +-+ +-+ + / \ / \ + / \ / \ + / \ / \ + / \ / \ + +-+ +-+ +-+ +-+ + |3| |4| |5| |6| + +-+ +-+ +-+ +-+ + +---+-----+ +----+----| +----+----+ +----+-----+-----+ + | | | | | | | | | | | | | + | | | | | | | | | | | | | + v v v v v v v v v v v v v + +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+ + |0| |1| |2| |3| |4| |5| |6| |7| |8| |9| |10| |11| |12| + +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+ + +This tree is defined by the platform as the array described above as follows: + +.. code:: c + + #define PLAT_NUM_POWER_DOMAINS 20 + #define PLATFORM_CORE_COUNT 13 + #define PSCI_NUM_NON_CPU_PWR_DOMAINS \ + (PLAT_NUM_POWER_DOMAINS - PLATFORM_CORE_COUNT) + + unsigned char plat_power_domain_tree_desc[] = { 1, 2, 2, 2, 3, 3, 3, 4}; + +Removing assumptions about MPIDRs used in a platform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 2., it is assumed that the platform assigns a +unique number (core index) between ``0`` and ``PLAT_CORE_COUNT - 1`` to each core +power domain. MPIDRs could be allocated in any manner and will not be used to +populate the tree. + +``plat_core_pos_by_mpidr(mpidr)`` will return the core index for the core +corresponding to the MPIDR. It will return an error (-1) if an MPIDR is passed +which is not allocated or corresponds to an absent core. The semantics of this +platform API have changed since it is required to validate the passed MPIDR. It +has been made a mandatory API as a result. + +Another mandatory API, ``plat_my_core_pos()`` has been added to return the core +index for the calling core. This API provides a more lightweight mechanism to get +the index since there is no need to validate the MPIDR of the calling core. + +The platform should assign the core indices (as illustrated in the diagram above) +such that, if the core nodes are numbered from left to right, then the index +for a core domain will be the same as the index returned by +``plat_core_pos_by_mpidr()`` or ``plat_my_core_pos()`` for that core. This +relationship allows the core nodes to be allocated in a separate array +(requirement 4.) during ``psci_setup()`` in such an order that the index of the +core in the array is the same as the return value from these APIs. + +Dealing with holes in MPIDR allocation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For platforms where the number of allocated MPIDRs is equal to the number of +core power domains, for example, Juno and FVPs, the logic to convert an MPIDR to +a core index should remain unchanged. Both Juno and FVP use a simple collision +proof hash function to do this. + +It is possible that on some platforms, the allocation of MPIDRs is not +contiguous or certain cores have been disabled. This essentially means that the +MPIDRs have been sparsely allocated, that is, the size of the range of MPIDRs +used by the platform is not equal to the number of core power domains. + +The platform could adopt one of the following approaches to deal with this +scenario: + +#. Implement more complex logic to convert a valid MPIDR to a core index while + maintaining the relationship described earlier. This means that the power + domain tree descriptor will not describe any core power domains which are + disabled or absent. Entries will not be allocated in the tree for these + domains. + +#. Treat unallocated MPIDRs and disabled cores as absent but still describe them + in the power domain descriptor, that is, the number of core nodes described + is equal to the size of the range of MPIDRs allocated. This approach will + lead to memory wastage since entries will be allocated in the tree but will + allow use of a simpler logic to convert an MPIDR to a core index. + +Traversing through and distinguishing between core and non-core power domains +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 3 and 4, separate data structures have been defined +to represent leaf and non-leaf power domain nodes in the tree. + +.. code:: c + + /******************************************************************************* + * The following two data structures implement the power domain tree. The tree + * is used to track the state of all the nodes i.e. power domain instances + * described by the platform. The tree consists of nodes that describe CPU power + * domains i.e. leaf nodes and all other power domains which are parents of a + * CPU power domain i.e. non-leaf nodes. + ******************************************************************************/ + typedef struct non_cpu_pwr_domain_node { + /* + * Index of the first CPU power domain node level 0 which has this node + * as its parent. + */ + unsigned int cpu_start_idx; + + /* + * Number of CPU power domains which are siblings of the domain indexed + * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx + * -> cpu_start_idx + ncpus' have this node as their parent. + */ + unsigned int ncpus; + + /* Index of the parent power domain node */ + unsigned int parent_node; + + ----- + } non_cpu_pd_node_t; + + typedef struct cpu_pwr_domain_node { + u_register_t mpidr; + + /* Index of the parent power domain node */ + unsigned int parent_node; + + ----- + } cpu_pd_node_t; + +The power domain tree is implemented as a combination of the following data +structures. + +.. code:: c + + non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS]; + cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT]; + +Populating the power domain tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``populate_power_domain_tree()`` function in ``psci_setup.c`` implements the +algorithm to parse the power domain descriptor exported by the platform to +populate the two arrays. It is essentially a breadth-first-search. The nodes for +each level starting from the root are laid out one after another in the +``psci_non_cpu_pd_nodes`` and ``psci_cpu_pd_nodes`` arrays as follows: + +:: + + psci_non_cpu_pd_nodes -> [[Level 3 nodes][Level 2 nodes][Level 1 nodes]] + psci_cpu_pd_nodes -> [Level 0 nodes] + +For the example power domain tree illustrated above, the ``psci_cpu_pd_nodes`` +will be populated as follows. The value in each entry is the index of the parent +node. Other fields have been ignored for simplicity. + +:: + + +-------------+ ^ + CPU0 | 3 | | + +-------------+ | + CPU1 | 3 | | + +-------------+ | + CPU2 | 3 | | + +-------------+ | + CPU3 | 4 | | + +-------------+ | + CPU4 | 4 | | + +-------------+ | + CPU5 | 4 | | PLATFORM_CORE_COUNT + +-------------+ | + CPU6 | 5 | | + +-------------+ | + CPU7 | 5 | | + +-------------+ | + CPU8 | 5 | | + +-------------+ | + CPU9 | 6 | | + +-------------+ | + CPU10 | 6 | | + +-------------+ | + CPU11 | 6 | | + +-------------+ | + CPU12 | 6 | v + +-------------+ + +The ``psci_non_cpu_pd_nodes`` array will be populated as follows. The value in +each entry is the index of the parent node. + +:: + + +-------------+ ^ + PD0 | -1 | | + +-------------+ | + PD1 | 0 | | + +-------------+ | + PD2 | 0 | | + +-------------+ | + PD3 | 1 | | PLAT_NUM_POWER_DOMAINS - + +-------------+ | PLATFORM_CORE_COUNT + PD4 | 1 | | + +-------------+ | + PD5 | 2 | | + +-------------+ | + PD6 | 2 | | + +-------------+ v + +Each core can find its node in the ``psci_cpu_pd_nodes`` array using the +``plat_my_core_pos()`` function. When a core is turned on, the normal world +provides an MPIDR. The ``plat_core_pos_by_mpidr()`` function is used to validate +the MPIDR before using it to find the corresponding core node. The non-core power +domain nodes do not need to be identified. + +-------------- + +*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design/reset-design.rst b/arm-trusted-firmware/docs/design/reset-design.rst new file mode 100644 index 0000000..7b10c95 --- /dev/null +++ b/arm-trusted-firmware/docs/design/reset-design.rst @@ -0,0 +1,161 @@ +CPU Reset +========= + +This document describes the high-level design of the framework to handle CPU +resets in Trusted Firmware-A (TF-A). It also describes how the platform +integrator can tailor this code to the system configuration to some extent, +resulting in a simplified and more optimised boot flow. + +This document should be used in conjunction with the :ref:`Firmware Design` +document which provides greater implementation details around the reset code, +specifically for the cold boot path. + +General reset code flow +----------------------- + +The TF-A reset code is implemented in BL1 by default. The following high-level +diagram illustrates this: + +|Default reset code flow| + +This diagram shows the default, unoptimised reset flow. Depending on the system +configuration, some of these steps might be unnecessary. The following sections +guide the platform integrator by indicating which build options exclude which +steps, depending on the capability of the platform. + +.. note:: + If BL31 is used as the TF-A entry point instead of BL1, the diagram + above is still relevant, as all these operations will occur in BL31 in + this case. Please refer to section 6 "Using BL31 entrypoint as the reset + address" for more information. + +Programmable CPU reset address +------------------------------ + +By default, TF-A assumes that the CPU reset address is not programmable. +Therefore, all CPUs start at the same address (typically address 0) whenever +they reset. Further logic is then required to identify whether it is a cold or +warm boot to direct CPUs to the right execution path. + +If the reset vector address (reflected in the reset vector base address register +``RVBAR_EL3``) is programmable then it is possible to make each CPU start directly +at the right address, both on a cold and warm reset. Therefore, the boot type +detection can be skipped, resulting in the following boot flow: + +|Reset code flow with programmable reset address| + +To enable this boot flow, compile TF-A with ``PROGRAMMABLE_RESET_ADDRESS=1``. +This option only affects the TF-A reset image, which is BL1 by default or BL31 if +``RESET_TO_BL31=1``. + +On both the FVP and Juno platforms, the reset vector address is not programmable +so both ports use ``PROGRAMMABLE_RESET_ADDRESS=0``. + +Cold boot on a single CPU +------------------------- + +By default, TF-A assumes that several CPUs may be released out of reset. +Therefore, the cold boot code has to arbitrate access to hardware resources +shared amongst CPUs. This is done by nominating one of the CPUs as the primary, +which is responsible for initialising shared hardware and coordinating the boot +flow with the other CPUs. + +If the platform guarantees that only a single CPU will ever be brought up then +no arbitration is required. The notion of primary/secondary CPU itself no longer +applies. This results in the following boot flow: + +|Reset code flow with single CPU released out of reset| + +To enable this boot flow, compile TF-A with ``COLD_BOOT_SINGLE_CPU=1``. This +option only affects the TF-A reset image, which is BL1 by default or BL31 if +``RESET_TO_BL31=1``. + +On both the FVP and Juno platforms, although only one core is powered up by +default, there are platform-specific ways to release any number of cores out of +reset. Therefore, both platform ports use ``COLD_BOOT_SINGLE_CPU=0``. + +Programmable CPU reset address, Cold boot on a single CPU +--------------------------------------------------------- + +It is obviously possible to combine both optimisations on platforms that have +a programmable CPU reset address and which release a single CPU out of reset. +This results in the following boot flow: + + +|Reset code flow with programmable reset address and single CPU released out of reset| + +To enable this boot flow, compile TF-A with both ``COLD_BOOT_SINGLE_CPU=1`` +and ``PROGRAMMABLE_RESET_ADDRESS=1``. These options only affect the TF-A reset +image, which is BL1 by default or BL31 if ``RESET_TO_BL31=1``. + +Using BL31 entrypoint as the reset address +------------------------------------------ + +On some platforms the runtime firmware (BL3x images) for the application +processors are loaded by some firmware running on a secure system processor +on the SoC, rather than by BL1 and BL2 running on the primary application +processor. For this type of SoC it is desirable for the application processor +to always reset to BL31 which eliminates the need for BL1 and BL2. + +TF-A provides a build-time option ``RESET_TO_BL31`` that includes some additional +logic in the BL31 entry point to support this use case. + +In this configuration, the platform's Trusted Boot Firmware must ensure that +BL31 is loaded to its runtime address, which must match the CPU's ``RVBAR_EL3`` +reset vector base address, before the application processor is powered on. +Additionally, platform software is responsible for loading the other BL3x images +required and providing entry point information for them to BL31. Loading these +images might be done by the Trusted Boot Firmware or by platform code in BL31. + +Although the Arm FVP platform does not support programming the reset base +address dynamically at run-time, it is possible to set the initial value of the +``RVBAR_EL3`` register at start-up. This feature is provided on the Base FVP +only. + +It allows the Arm FVP port to support the ``RESET_TO_BL31`` configuration, in +which case the ``bl31.bin`` image must be loaded to its run address in Trusted +SRAM and all CPU reset vectors be changed from the default ``0x0`` to this run +address. See the :ref:`Arm Fixed Virtual Platforms (FVP)` for details of running +the FVP models in this way. + +Although technically it would be possible to program the reset base address with +the right support in the SCP firmware, this is currently not implemented so the +Juno port doesn't support the ``RESET_TO_BL31`` configuration. + +The ``RESET_TO_BL31`` configuration requires some additions and changes in the +BL31 functionality: + +Determination of boot path +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In this configuration, BL31 uses the same reset framework and code as the one +described for BL1 above. Therefore, it is affected by the +``PROGRAMMABLE_RESET_ADDRESS`` and ``COLD_BOOT_SINGLE_CPU`` build options in the +same way. + +In the default, unoptimised BL31 reset flow, on a warm boot a CPU is directed +to the PSCI implementation via a platform defined mechanism. On a cold boot, +the platform must place any secondary CPUs into a safe state while the primary +CPU executes a modified BL31 initialization, as described below. + +Platform initialization +~~~~~~~~~~~~~~~~~~~~~~~ + +In this configuration, when the CPU resets to BL31 there are no parameters that +can be passed in registers by previous boot stages. Instead, the platform code +in BL31 needs to know, or be able to determine, the location of the BL32 (if +required) and BL33 images and provide this information in response to the +``bl31_plat_get_next_image_ep_info()`` function. + +Additionally, platform software is responsible for carrying out any security +initialisation, for example programming a TrustZone address space controller. +This might be done by the Trusted Boot Firmware or by platform code in BL31. + +-------------- + +*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.* + +.. |Default reset code flow| image:: ../resources/diagrams/default_reset_code.png +.. |Reset code flow with programmable reset address| image:: ../resources/diagrams/reset_code_no_boot_type_check.png +.. |Reset code flow with single CPU released out of reset| image:: ../resources/diagrams/reset_code_no_cpu_check.png +.. |Reset code flow with programmable reset address and single CPU released out of reset| image:: ../resources/diagrams/reset_code_no_checks.png diff --git a/arm-trusted-firmware/docs/design/trusted-board-boot-build.rst b/arm-trusted-firmware/docs/design/trusted-board-boot-build.rst new file mode 100644 index 0000000..dd61b61 --- /dev/null +++ b/arm-trusted-firmware/docs/design/trusted-board-boot-build.rst @@ -0,0 +1,115 @@ +Building FIP images with support for Trusted Board Boot +======================================================= + +Trusted Board Boot primarily consists of the following two features: + +- Image Authentication, described in :ref:`Trusted Board Boot`, and +- Firmware Update, described in :ref:`Firmware Update (FWU)` + +The following steps should be followed to build FIP and (optionally) FWU_FIP +images with support for these features: + +#. Fulfill the dependencies of the ``mbedtls`` cryptographic and image parser + modules by checking out a recent version of the `mbed TLS Repository`_. It + is important to use a version that is compatible with TF-A and fixes any + known security vulnerabilities. See `mbed TLS Security Center`_ for more + information. See the :ref:`Prerequisites` document for the appropriate + version of mbed TLS to use. + + The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS + source files the modules depend upon. + ``include/drivers/auth/mbedtls/mbedtls_config.h`` contains the configuration + options required to build the mbed TLS sources. + + Note that the mbed TLS library is licensed under the Apache version 2.0 + license. Using mbed TLS source code will affect the licensing of TF-A + binaries that are built using this library. + +#. To build the FIP image, ensure the following command line variables are set + while invoking ``make`` to build TF-A: + + - ``MBEDTLS_DIR=`` + - ``TRUSTED_BOARD_BOOT=1`` + - ``GENERATE_COT=1`` + + By default, this will use the Chain of Trust described in the TBBR-client + document. To select a different one, use the ``COT`` build option. + + In the case of Arm platforms, the location of the ROTPK hash must also be + specified at build time. The following locations are currently supported (see + ``ARM_ROTPK_LOCATION`` build option): + + - ``ARM_ROTPK_LOCATION=regs``: the ROTPK hash is obtained from the Trusted + root-key storage registers present in the platform. On Juno, these + registers are read-only. On FVP Base and Cortex models, the registers + are also read-only, but the value can be specified using the command line + option ``bp.trusted_key_storage.public_key`` when launching the model. + On Juno board, the default value corresponds to an ECDSA-SECP256R1 public + key hash, whose private part is not currently available. + + - ``ARM_ROTPK_LOCATION=devel_rsa``: use the default hash located in + ``plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin``. Enforce + generation of the new hash if ``ROT_KEY`` is specified. + + - ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the default hash located in + ``plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin``. Enforce + generation of the new hash if ``ROT_KEY`` is specified. + + Example of command line using RSA development keys: + + .. code:: shell + + MBEDTLS_DIR= \ + make PLAT= TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33=/ \ + all fip + + The result of this build will be the bl1.bin and the fip.bin binaries. This + FIP will include the certificates corresponding to the selected Chain of + Trust. These certificates can also be found in the output build directory. + +#. The optional FWU_FIP contains any additional images to be loaded from + Non-Volatile storage during the :ref:`Firmware Update (FWU)` process. To build the + FWU_FIP, any FWU images required by the platform must be specified on the + command line. On Arm development platforms like Juno, these are: + + - NS_BL2U. The AP non-secure Firmware Updater image. + - SCP_BL2U. The SCP Firmware Update Configuration image. + + Example of Juno command line for generating both ``fwu`` and ``fwu_fip`` + targets using RSA development: + + :: + + MBEDTLS_DIR= \ + make PLAT=juno TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33=/ \ + SCP_BL2=/ \ + SCP_BL2U=/ \ + NS_BL2U=/ \ + all fip fwu_fip + + .. note:: + The BL2U image will be built by default and added to the FWU_FIP. + The user may override this by adding ``BL2U=/`` + to the command line above. + + .. note:: + Building and installing the non-secure and SCP FWU images (NS_BL1U, + NS_BL2U and SCP_BL2U) is outside the scope of this document. + + The result of this build will be bl1.bin, fip.bin and fwu_fip.bin binaries. + Both the FIP and FWU_FIP will include the certificates corresponding to the + selected Chain of Trust. These certificates can also be found in the output + build directory. + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* + +.. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git +.. _mbed TLS Security Center: https://tls.mbed.org/security diff --git a/arm-trusted-firmware/docs/design/trusted-board-boot.rst b/arm-trusted-firmware/docs/design/trusted-board-boot.rst new file mode 100644 index 0000000..46177d7 --- /dev/null +++ b/arm-trusted-firmware/docs/design/trusted-board-boot.rst @@ -0,0 +1,263 @@ +Trusted Board Boot +================== + +The Trusted Board Boot (TBB) feature prevents malicious firmware from running on +the platform by authenticating all firmware images up to and including the +normal world bootloader. It does this by establishing a Chain of Trust using +Public-Key-Cryptography Standards (PKCS). + +This document describes the design of Trusted Firmware-A (TF-A) TBB, which is an +implementation of the `Trusted Board Boot Requirements (TBBR)`_ specification, +Arm DEN0006D. It should be used in conjunction with the +:ref:`Firmware Update (FWU)` design document, which implements a specific aspect +of the TBBR. + +Chain of Trust +-------------- + +A Chain of Trust (CoT) starts with a set of implicitly trusted components. On +the Arm development platforms, these components are: + +- A SHA-256 hash of the Root of Trust Public Key (ROTPK). It is stored in the + trusted root-key storage registers. Alternatively, a development ROTPK might + be used and its hash embedded into the BL1 and BL2 images (only for + development purposes). + +- The BL1 image, on the assumption that it resides in ROM so cannot be + tampered with. + +The remaining components in the CoT are either certificates or boot loader +images. The certificates follow the `X.509 v3`_ standard. This standard +enables adding custom extensions to the certificates, which are used to store +essential information to establish the CoT. + +In the TBB CoT all certificates are self-signed. There is no need for a +Certificate Authority (CA) because the CoT is not established by verifying the +validity of a certificate's issuer but by the content of the certificate +extensions. To sign the certificates, different signature schemes are available, +please refer to the :ref:`Build Options` for more details. + +The certificates are categorised as "Key" and "Content" certificates. Key +certificates are used to verify public keys which have been used to sign content +certificates. Content certificates are used to store the hash of a boot loader +image. An image can be authenticated by calculating its hash and matching it +with the hash extracted from the content certificate. Various hash algorithms +are supported to calculate all hashes, please refer to the :ref:`Build Options` +for more details.. The public keys and hashes are included as non-standard +extension fields in the `X.509 v3`_ certificates. + +The keys used to establish the CoT are: + +- **Root of trust key** + + The private part of this key is used to sign the BL2 content certificate and + the trusted key certificate. The public part is the ROTPK. + +- **Trusted world key** + + The private part is used to sign the key certificates corresponding to the + secure world images (SCP_BL2, BL31 and BL32). The public part is stored in + one of the extension fields in the trusted world certificate. + +- **Non-trusted world key** + + The private part is used to sign the key certificate corresponding to the + non secure world image (BL33). The public part is stored in one of the + extension fields in the trusted world certificate. + +- **BL3X keys** + + For each of SCP_BL2, BL31, BL32 and BL33, the private part is used to + sign the content certificate for the BL3X image. The public part is stored + in one of the extension fields in the corresponding key certificate. + +The following images are included in the CoT: + +- BL1 +- BL2 +- SCP_BL2 (optional) +- BL31 +- BL33 +- BL32 (optional) + +The following certificates are used to authenticate the images. + +- **BL2 content certificate** + + It is self-signed with the private part of the ROT key. It contains a hash + of the BL2 image. + +- **Trusted key certificate** + + It is self-signed with the private part of the ROT key. It contains the + public part of the trusted world key and the public part of the non-trusted + world key. + +- **SCP_BL2 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the SCP_BL2 key. + +- **SCP_BL2 content certificate** + + It is self-signed with the SCP_BL2 key. It contains a hash of the SCP_BL2 + image. + +- **BL31 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the BL31 key. + +- **BL31 content certificate** + + It is self-signed with the BL31 key. It contains a hash of the BL31 image. + +- **BL32 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the BL32 key. + +- **BL32 content certificate** + + It is self-signed with the BL32 key. It contains a hash of the BL32 image. + +- **BL33 key certificate** + + It is self-signed with the non-trusted world key. It contains the public + part of the BL33 key. + +- **BL33 content certificate** + + It is self-signed with the BL33 key. It contains a hash of the BL33 image. + +The SCP_BL2 and BL32 certificates are optional, but they must be present if the +corresponding SCP_BL2 or BL32 images are present. + +Trusted Board Boot Sequence +--------------------------- + +The CoT is verified through the following sequence of steps. The system panics +if any of the steps fail. + +- BL1 loads and verifies the BL2 content certificate. The issuer public key is + read from the verified certificate. A hash of that key is calculated and + compared with the hash of the ROTPK read from the trusted root-key storage + registers. If they match, the BL2 hash is read from the certificate. + + .. note:: + The matching operation is platform specific and is currently + unimplemented on the Arm development platforms. + +- BL1 loads the BL2 image. Its hash is calculated and compared with the hash + read from the certificate. Control is transferred to the BL2 image if all + the comparisons succeed. + +- BL2 loads and verifies the trusted key certificate. The issuer public key is + read from the verified certificate. A hash of that key is calculated and + compared with the hash of the ROTPK read from the trusted root-key storage + registers. If the comparison succeeds, BL2 reads and saves the trusted and + non-trusted world public keys from the verified certificate. + +The next two steps are executed for each of the SCP_BL2, BL31 & BL32 images. +The steps for the optional SCP_BL2 and BL32 images are skipped if these images +are not present. + +- BL2 loads and verifies the BL3x key certificate. The certificate signature + is verified using the trusted world public key. If the signature + verification succeeds, BL2 reads and saves the BL3x public key from the + certificate. + +- BL2 loads and verifies the BL3x content certificate. The signature is + verified using the BL3x public key. If the signature verification succeeds, + BL2 reads and saves the BL3x image hash from the certificate. + +The next two steps are executed only for the BL33 image. + +- BL2 loads and verifies the BL33 key certificate. If the signature + verification succeeds, BL2 reads and saves the BL33 public key from the + certificate. + +- BL2 loads and verifies the BL33 content certificate. If the signature + verification succeeds, BL2 reads and saves the BL33 image hash from the + certificate. + +The next step is executed for all the boot loader images. + +- BL2 calculates the hash of each image. It compares it with the hash obtained + from the corresponding content certificate. The image authentication succeeds + if the hashes match. + +The Trusted Board Boot implementation spans both generic and platform-specific +BL1 and BL2 code, and in tool code on the host build machine. The feature is +enabled through use of specific build flags as described in +:ref:`Build Options`. + +On the host machine, a tool generates the certificates, which are included in +the FIP along with the boot loader images. These certificates are loaded in +Trusted SRAM using the IO storage framework. They are then verified by an +Authentication module included in TF-A. + +The mechanism used for generating the FIP and the Authentication module are +described in the following sections. + +Authentication Framework +------------------------ + +The authentication framework included in TF-A provides support to implement +the desired trusted boot sequence. Arm platforms use this framework to +implement the boot requirements specified in the +`Trusted Board Boot Requirements (TBBR)`_ document. + +More information about the authentication framework can be found in the +:ref:`Authentication Framework & Chain of Trust` document. + +Certificate Generation Tool +--------------------------- + +The ``cert_create`` tool is built and runs on the host machine as part of the +TF-A build process when ``GENERATE_COT=1``. It takes the boot loader images +and keys as inputs (keys must be in PEM format) and generates the +certificates (in DER format) required to establish the CoT. New keys can be +generated by the tool in case they are not provided. The certificates are then +passed as inputs to the ``fiptool`` utility for creating the FIP. + +The certificates are also stored individually in the output build directory. + +The tool resides in the ``tools/cert_create`` directory. It uses the OpenSSL SSL +library version to generate the X.509 certificates. The specific version of the +library that is required is given in the :ref:`Prerequisites` document. + +Instructions for building and using the tool can be found at +:ref:`tools_build_cert_create`. + +Authenticated Encryption Framework +---------------------------------- + +The authenticated encryption framework included in TF-A provides support to +implement the optional firmware encryption feature. This feature can be +optionally enabled on platforms to implement the optional requirement: +R060_TBBR_FUNCTION as specified in the `Trusted Board Boot Requirements (TBBR)`_ +document. + +Firmware Encryption Tool +------------------------ + +The ``encrypt_fw`` tool is built and runs on the host machine as part of the +TF-A build process when ``DECRYPTION_SUPPORT != none``. It takes the plain +firmware image as input and generates the encrypted firmware image which can +then be passed as input to the ``fiptool`` utility for creating the FIP. + +The encrypted firmwares are also stored individually in the output build +directory. + +The tool resides in the ``tools/encrypt_fw`` directory. It uses OpenSSL SSL +library version 1.0.1 or later to do authenticated encryption operation. +Instructions for building and using the tool can be found in the +:ref:`tools_build_enctool`. + +-------------- + +*Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.* + +.. _X.509 v3: https://tools.ietf.org/rfc/rfc5280.txt +.. _Trusted Board Boot Requirements (TBBR): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a diff --git a/arm-trusted-firmware/docs/design_documents/cmake_framework.rst b/arm-trusted-firmware/docs/design_documents/cmake_framework.rst new file mode 100644 index 0000000..d88942e --- /dev/null +++ b/arm-trusted-firmware/docs/design_documents/cmake_framework.rst @@ -0,0 +1,165 @@ +TF-A CMake buildsystem +====================== + +:Author: Balint Dobszay +:Organization: Arm Limited +:Contact: Balint Dobszay +:Status: Accepted + +.. contents:: Table of Contents + +Abstract +-------- +This document presents a proposal for a new buildsystem for TF-A using CMake, +and as part of this a reusable CMake framework for embedded projects. For a +summary about the proposal, please see the `Phabricator wiki page +`_. As +mentioned there, the proposal consists of two phases. The subject of this +document is the first phase only. + +Introduction +------------ +The current Makefile based buildsystem of TF-A has become complicated and hard +to maintain, there is a need for a new, more flexible solution. The proposal is +to use CMake language for the new buildsystem. The main reasons of this decision +are the following: + +* It is a well-established, mature tool, widely accepted by open-source + projects. +* TF-M is already using CMake, reducing fragmentation for tf.org projects can be + beneficial. +* CMake has various advantages over Make, e.g.: + + * Host and target system agnostic project. + * CMake project is scalable, supports project modularization. + * Supports software integration. + * Out-of-the-box support for integration with several tools (e.g. project + generation for various IDEs, integration with cppcheck, etc). + +Of course there are drawbacks too: + +* Language is problematic (e.g. variable scope). +* Not embedded approach. + +To overcome these and other problems, we need to create workarounds for some +tasks, wrap CMake functions, etc. Since this functionality can be useful in +other embedded projects too, it is beneficial to collect the new code into a +reusable framework and store this in a separate repository. The following +diagram provides an overview of the framework structure: + +|Framework structure| + +Main features +------------- + +Structured configuration description +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In the current Makefile system the build configuration description, validation, +processing, and the target creation, source file description are mixed and +spread across several files. One of the goals of the framework is to organize +this. + +The framework provides a solution to describe the input build parameters, flags, +macros, etc. in a structured way. It contains two utilities for this purpose: + +* Map: simple key-value pair implementation. +* Group: collection of related maps. + +The related parameters shall be packed into a group (or "setting group"). The +setting groups shall be defined and filled with content in config files. +Currently the config files are created and edited manually, but later a +configuration management tool (e.g. Kconfig) shall be used to generate these +files. Therefore, the framework does not contain parameter validation and +conflict checking, these shall be handled by the configuration tool. + +Target description +^^^^^^^^^^^^^^^^^^ +The framework provides an API called STGT ('simple target') to describe the +targets, i.e. what is the build output, what source files are used, what +libraries are linked, etc. The API wraps the CMake target functions, and also +extends the built-in functionality, it can use the setting groups described in +the previous section. A group can be applied onto a target, i.e. a collection of +macros, flags, etc. can be applied onto the given output executable/library. +This provides a more granular way than the current Makefile system where most of +these are global and applied onto each target. + +Compiler abstraction +^^^^^^^^^^^^^^^^^^^^ +Apart from the built-in CMake usage of the compiler, there are some common tasks +that CMake does not solve (e.g. preprocessing a file). For these tasks the +framework uses wrapper functions instead of direct calls to the compiler. This +way it is not tied to one specific compiler. + +External tools +^^^^^^^^^^^^^^ +In the TF-A buildsystem some external tools are used, e.g. fiptool for image +generation or dtc for device tree compilation. These tools have to be found +and/or built by the framework. For this, the CMake find_package functionality is +used, any other necessary tools can be added later. + +Workflow +-------- +The following diagram demonstrates the development workflow using the framework: + +|Framework workflow| + +The process can be split into two main phases: + +In the provisioning phase, first we have to obtain the necessary resources, i.e. +clone the code repository and other dependencies. Next we have to do the +configuration, preferably using a config tool like KConfig. + +In the development phase first we run CMake, which will generate the buildsystem +using the selected generator backend (currently only the Makefile generator is +supported). After this we run the selected build tool which in turn calls the +compiler, linker, packaging tool, etc. Finally we can run and debug the output +executables. + +Usually during development only the steps in this second phase have to be +repeated, while the provisioning phase needs to be done only once (or rarely). + +Example +------- +This is a short example for the basic framework usage. + +First, we create a setting group called *mem_conf* and fill it with several +parameters. It is worth noting the difference between *CONFIG* and *DEFINE* +types: the former is only a CMake domain option, the latter is only a C language +macro. + +Next, we create a target called *fw1* and add the *mem_conf* setting group to +it. This means that all source and header files used by the target will have all +the parameters declared in the setting group. Then we set the target type to +executable, and add some source files. Since the target has the parameters from +the settings group, we can use it for conditionally adding source files. E.g. +*dram_controller.c* will only be added if MEM_TYPE equals dram. + +.. code-block:: cmake + + group_new(NAME mem_conf) + group_add(NAME mem_conf TYPE DEFINE KEY MEM_SIZE VAL 1024) + group_add(NAME mem_conf TYPE CONFIG DEFINE KEY MEM_TYPE VAL dram) + group_add(NAME mem_conf TYPE CFLAG KEY -Os) + + stgt_create(NAME fw1) + stgt_add_setting(NAME fw1 GROUPS mem_conf) + stgt_set_target(NAME fw1 TYPE exe) + + stgt_add_src(NAME fw1 SRC + ${CMAKE_SOURCE_DIR}/main.c + ) + + stgt_add_src_cond(NAME fw1 KEY MEM_TYPE VAL dram SRC + ${CMAKE_SOURCE_DIR}/dram_controller.c + ) + +.. |Framework structure| image:: + ../resources/diagrams/cmake_framework_structure.png + :width: 75 % + +.. |Framework workflow| image:: + ../resources/diagrams/cmake_framework_workflow.png + +-------------- + +*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst b/arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst new file mode 100644 index 0000000..59f9d4e --- /dev/null +++ b/arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst @@ -0,0 +1,197 @@ +Enhance Context Management library for EL3 firmware +=================================================== + +:Authors: Soby Mathew & Zelalem Aweke +:Organization: Arm Limited +:Contact: Soby Mathew & Zelalem Aweke +:Status: RFC + +.. contents:: Table of Contents + +Introduction +------------ +The context management library in TF-A provides the basic CPU context +initialization and management routines for use by different components +in EL3 firmware. The original design of the library was done keeping in +mind the 2 world switch and hence this design pattern has been extended to +keep up with growing requirements of EL3 firmware. With the introduction +of a new Realm world and a separate Root world for EL3 firmware, it is clear +that this library needs to be refactored to cater for future enhancements and +reduce chances of introducing error in code. This also aligns with the overall +goal of reducing EL3 firmware complexity and footprint. + +It is expected that the suggestions below could have legacy implications and +hence we are mainly targeting SPM/RMM based systems. It is expected that these +legacy issues will need to be sorted out as part of implementation on a case +by case basis. + +Design Principles +----------------- +The below section lays down the design principles for re-factoring the context +management library : + +(1) **Decentralized model for context mgmt** + + Both the Secure and Realm worlds have associated dispatcher component in + EL3 firmware to allow management of their respective worlds. Allowing the + dispatcher to own the context for their respective world and moving away + from a centralized policy management by context management library will + remove the world differentiation code in the library. This also means that + the library will not be responsible for CPU feature enablement for + Secure and Realm worlds. See point 3 and 4 for more details. + + The Non Secure world does not have a dispatcher component and hence EL3 + firmware (BL31)/context management library needs to have routines to help + initialize the Non Secure world context. + +(2) **EL3 should only initialize immediate used lower EL** + + Due to the way TF-A evolved, from EL3 interacting with an S-EL1 payload to + SPM in S-EL2, there is some code initializing S-EL1 registers which is + probably redundant when SPM is present in S-EL2. As a principle, EL3 + firmware should only initialize the next immediate lower EL in use. + If EL2 needs to be skipped and is not to be used at runtime, then + EL3 can do the bare minimal EL2 init and init EL1 to prepare for EL3 exit. + It is expected that this skip EL2 configuration is only needed for NS + world to support legacy Android deployments. It is worth removing this + `skip EL2 for Non Secure` config support if this is no longer used. + +(3) **Maintain EL3 sysregs which affect lower EL within CPU context** + + The CPU context contains some EL3 sysregs and gets applied on a per-world + basis (eg: cptr_el3, scr_el3, zcr_el3 is part of the context + because different settings need to be applied between each world). + But this design pattern is not enforced in TF-A. It is possible to directly + modify EL3 sysreg dynamically during the transition between NS and Secure + worlds. Having multiple ways of manipulating EL3 sysregs for different + values between the worlds is flaky and error prone. The proposal is to + enforce the rule that any EL3 sysreg which can be different between worlds + is maintained in the CPU Context. Once the context is initialized the + EL3 sysreg values corresponding to the world being entered will be restored. + +(4) **Allow more flexibility for Dispatchers to select feature set to save and restore** + + The current functions for EL2 CPU context save and restore is a single + function which takes care of saving and restoring all the registers for + EL2. This method is inflexible and it does not allow to dynamically detect + CPU features to select registers to save and restore. It also assumes that + both Realm and Secure world will have the same feature set enabled from + EL3 at runtime and makes it hard to enable different features for each + world. The framework should cater for selective save and restore of CPU + registers which can be controlled by the dispatcher. + + For the implementation, this could mean that there is a separate assembly + save and restore routine corresponding to Arch feature. The memory allocation + within the CPU Context for each set of registers will be controlled by a + FEAT_xxx build option. It is a valid configuration to have + context memory allocated but not used at runtime based on feature detection + at runtime or the platform owner has decided not to enable the feature + for the particular world. + +Context Allocation and Initialization +------------------------------------- + +|context_mgmt_abs| + +.. |context_mgmt_abs| image:: + ../resources/diagrams/context_management_abs.png + +The above figure shows how the CPU context is allocated within TF-A. The +allocation for Secure and Realm world is by the respective dispatcher. In the case +of NS world, the context is allocated by the PSCI lib. This scheme allows TF-A +to be built in various configurations (with or without Secure/Realm worlds) and +will result in optimal memory footprint. The Secure and Realm world contexts are +initialized by invoking context management library APIs which then initialize +each world based on conditional evaluation of the security state of the +context. The proposal here is to move the conditional initialization +of context for Secure and Realm worlds to their respective dispatchers and +have the library do only the common init needed. The library can export +helpers to initialize registers corresponding to certain features but +should not try to do different initialization between the worlds. The library +can also export helpers for initialization of NS CPU Context since there is no +dispatcher for that world. + +This implies that any world specific code in context mgmt lib should now be +migrated to the respective "owners". To maintain compatibility with legacy, the +current functions can be retained in the lib and perhaps define new ones for +use by SPMD and RMMD. The details of this can be worked out during +implementation. + +Introducing Root Context +------------------------ +Till now, we have been ignoring the fact that Root world (or EL3) itself could +have some settings which are distinct from NS/S/Realm worlds. In this case, +Root world itself would need to maintain some sysregs settings for its own +execution and would need to use sysregs of lower EL (eg: PAuth, pmcr) to enable +some functionalities in EL3. The current sequence for context save and restore +in TF-A is as given below: + +|context_mgmt_existing| + +.. |context_mgmt_existing| image:: + ../resources/diagrams/context_mgmt_existing.png + +Note1: The EL3 CPU context is not a homogenous collection of EL3 sysregs but +a collection of EL3 and some other lower EL registers. The save and restore +is also not done homogenously but based on the objective of using the +particular register. + +Note2: The EL1 context save and restore can possibly be removed when switching +to S-EL2 as SPM can take care of saving the incoming NS EL1 context. + +It can be seen that the EL3 sysreg values applied while the execution is in Root +world corresponds to the world it came from (eg: if entering EL3 from NS world, +the sysregs correspond to the values in NS context). There is a case that EL3 +itself may have some settings to apply for various reasons. A good example for +this is the cptr_el3 regsiter. Although FPU traps need to be disabled for +Non Secure, Secure and Realm worlds, the EL3 execution itself may keep the trap +enabled for the sake of robustness. Another example is, if the MTE feature +is enabled for a particular world, this feature will be enabled for Root world +as well when entering EL3 from that world. The firmware at EL3 may not +be expecting this feature to be enabled and may cause unwanted side-effects +which could be problematic. Thus it would be more robust if Root world is not +subject to EL3 sysreg values from other worlds but maintains its own values +which is stable and predictable throughout root world execution. + +There is also the case that when EL3 would like to make use of some +Architectural feature(s) or do some security hardening, it might need +programming of some lower EL sysregs. For example, if EL3 needs to make +use of Pointer Authentication (PAuth) feature, it needs to program +its own PAuth Keys during execution at EL3. Hence EL3 needs its +own copy of PAuth registers which needs to be restored on every +entry to EL3. A similar case can be made for DIT bit in PSTATE, +or use of SP_EL0 for C Runtime Stack at EL3. + +The proposal here is to maintain a separate root world CPU context +which gets applied for Root world execution. This is not the full +CPU_Context, but subset of EL3 sysregs (`el3_sysreg`) and lower EL +sysregs (`root_exc_context`) used by EL3. The save and restore +sequence for this Root context would need to be done in +an optimal way. The `el3_sysreg` does not need to be saved +on EL3 Exit and possibly only some registers in `root_exc_context` +of Root world context would need to be saved on EL3 exit (eg: SP_EL0). + +The new sequence for world switch including Root world context would +be as given below : + +|context_mgmt_proposed| + +.. |context_mgmt_proposed| image:: + ../resources/diagrams/context_mgmt_proposed.png + +Having this framework in place will allow Root world to make use of lower EL +registers easily for its own purposes and also have a fixed EL3 sysreg setting +which is not affected by the settings of other worlds. This will unify the +Root world register usage pattern for its own execution and remove some +of the adhoc usages in code. + +Conclusion +---------- +Of all the proposals, the introduction of Root world context would likely need +further prototyping to confirm the design and we will need to measure the +performance and memory impact of this change. Other changes are incremental +improvements which are thought to have negligible impact on EL3 performance. + +-------------- + +*Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design_documents/index.rst b/arm-trusted-firmware/docs/design_documents/index.rst new file mode 100644 index 0000000..257a510 --- /dev/null +++ b/arm-trusted-firmware/docs/design_documents/index.rst @@ -0,0 +1,15 @@ +Design Documents +================ + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + cmake_framework + context_mgmt_rework + measured_boot_poc + +-------------- + +*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst b/arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst new file mode 100644 index 0000000..3ae539b --- /dev/null +++ b/arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst @@ -0,0 +1,507 @@ +Interaction between Measured Boot and an fTPM (PoC) +=================================================== + +Measured Boot is the process of cryptographically measuring the code and +critical data used at boot time, for example using a TPM, so that the +security state can be attested later. + +The current implementation of the driver included in Trusted Firmware-A +(TF-A) stores the measurements into a `TGC event log`_ in secure +memory. No other means of recording measurements (such as a discrete TPM) is +supported right now. + +The driver also provides mechanisms to pass the Event Log to normal world if +needed. + +This manual provides instructions to build a proof of concept (PoC) with the +sole intention of showing how Measured Boot can be used in conjunction with +a firmware TPM (fTPM) service implemented on top of OP-TEE. + +.. note:: + The instructions given in this document are meant to be used to build + a PoC to show how Measured Boot on TF-A can interact with a third + party (f)TPM service and they try to be as general as possible. Different + platforms might have different needs and configurations (e.g. different + SHA algorithms) and they might also use different types of TPM services + (or even a different type of service to provide the attestation) + and therefore the instuctions given here might not apply in such scenarios. + +Components +~~~~~~~~~~ + +The PoC is built on top of the `OP-TEE Toolkit`_, which has support to build +TF-A with support for Measured Boot enabled (and run it on a Foundation Model) +since commit cf56848. + +The aforementioned toolkit builds a set of images that contain all the components +needed to test that the Event Log was properly created. One of these images will +contain a third party fTPM service which in turn will be used to process the +Event Log. + +The reason to choose OP-TEE Toolkit to build our PoC around it is mostly +for convenience. As the fTPM service used is an OP-TEE TA, it was easy to add +build support for it to the toolkit and then build the PoC around it. + +The most relevant components installed in the image that are closely related to +Measured Boot/fTPM functionality are: + + - **OP-TEE**: As stated earlier, the fTPM service used in this PoC is built as an + OP-TEE TA and therefore we need to include the OP-TEE OS image. + Support to interfacing with Measured Boot was added to version 3.9.0 of + OP-TEE by implementing the ``PTA_SYSTEM_GET_TPM_EVENT_LOG`` syscall, which + allows the former to pass a copy of the Event Log to any TA requesting it. + OP-TEE knows the location of the Event Log by reading the DTB bindings + received from TF-A. Visit :ref:`DTB binding for Event Log properties` + for more details on this. + + - **fTPM Service**: We use a third party fTPM service in order to validate + the Measured Boot functionality. The chosen fTPM service is a sample + implementation for Aarch32 architecture included on the `ms-tpm-20-ref`_ + reference implementation from Microsoft. The service was updated in order + to extend the Measured Boot Event Log at boot up and it uses the + aforementioned ``PTA_SYSTEM_GET_TPM_EVENT_LOG`` call to retrieve a copy + of the former. + + .. note:: + Arm does not provide an fTPM implementation. The fTPM service used here + is a third party one which has been updated to support Measured Boot + service as provided by TF-A. As such, it is beyond the scope of this + manual to test and verify the correctness of the output generated by the + fTPM service. + + - **TPM Kernel module**: In order to interact with the fTPM service, we need + a kernel module to forward the request from user space to the secure world. + + - `tpm2-tools`_: This is a set of tools that allow to interact with the + fTPM service. We use this in order to read the PCRs with the measurements. + +Building the PoC for the Arm FVP platform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As mentioned before, this PoC is based on the OP-TEE Toolkit with some +extensions to enable Measured Boot and an fTPM service. Therefore, we can rely +on the instructions to build the original OP-TEE Toolkit. As a general rule, +the following steps should suffice: + +(1) Start by following the `Get and build the solution`_ instructions to build + the OP-TEE toolkit. On step 3, you need to get the manifest for FVP + platform from the main branch: + + .. code:: shell + + $ repo init -u https://github.com/OP-TEE/manifest.git -m fvp.xml + + Then proceed synching the repos as stated in step 3. Continue following + the instructions and stop before step 5. + +(2) Next you should obtain the `Armv8-A Foundation Platform (For Linux Hosts Only)`_. + The binary should be untar'ed to the root of the repo tree, i.e., like + this: ``/Foundation_Platformpkg``. In the end, after cloning + all source code, getting the toolchains and "installing" + Foundation_Platformpkg, you should have a folder structure that looks like + this: + + .. code:: shell + + $ ls -la + total 80 + drwxrwxr-x 20 tf-a_user tf-a_user 4096 Jul 1 12:16 . + drwxr-xr-x 23 tf-a_user tf-a_user 4096 Jul 1 10:40 .. + drwxrwxr-x 12 tf-a_user tf-a_user 4096 Jul 1 10:45 build + drwxrwxr-x 16 tf-a_user tf-a_user 4096 Jul 1 12:16 buildroot + drwxrwxr-x 51 tf-a_user tf-a_user 4096 Jul 1 10:45 edk2 + drwxrwxr-x 6 tf-a_user tf-a_user 4096 Jul 1 12:14 edk2-platforms + drwxr-xr-x 7 tf-a_user tf-a_user 4096 Jul 1 10:52 Foundation_Platformpkg + drwxrwxr-x 17 tf-a_user tf-a_user 4096 Jul 2 10:40 grub + drwxrwxr-x 25 tf-a_user tf-a_user 4096 Jul 2 10:39 linux + drwxrwxr-x 15 tf-a_user tf-a_user 4096 Jul 1 10:45 mbedtls + drwxrwxr-x 6 tf-a_user tf-a_user 4096 Jul 1 10:45 ms-tpm-20-ref + drwxrwxr-x 8 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_client + drwxrwxr-x 10 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_examples + drwxrwxr-x 12 tf-a_user tf-a_user 4096 Jul 1 12:13 optee_os + drwxrwxr-x 8 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_test + drwxrwxr-x 7 tf-a_user tf-a_user 4096 Jul 1 10:45 .repo + drwxrwxr-x 4 tf-a_user tf-a_user 4096 Jul 1 12:12 toolchains + drwxrwxr-x 21 tf-a_user tf-a_user 4096 Jul 1 12:15 trusted-firmware-a + +(3) Now enter into ``ms-tpm-20-ref`` and get its dependencies: + + .. code:: shell + + $ cd ms-tpm-20-ref + $ git submodule init + $ git submodule update + Submodule path 'external/wolfssl': checked out '9c87f979a7f1d3a6d786b260653d566c1d31a1c4' + +(4) Now, you should be able to continue with step 5 in "`Get and build the solution`_" + instructions. In order to enable support for Measured Boot, you need to + set the ``MEASURED_BOOT`` build option: + + .. code:: shell + + $ MEASURED_BOOT=y make -j `nproc` + + .. note:: + The build process will likely take a long time. It is strongly recommended to + pass the ``-j`` option to make to run the process faster. + + After this step, you should be ready to run the image. + +Running and using the PoC on the Armv8-A Foundation AEM FVP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +With everything built, you can now run the image: + +.. code:: shell + + $ make run-only + +.. note:: + Using ``make run`` will build and run the image and it can be used instead + of simply ``make``. However, once the image is built, it is recommended to + use ``make run-only`` to avoid re-running all the building rules, which + would take time. + +When FVP is launched, two terminal windows will appear. ``FVP terminal_0`` +is the userspace terminal whereas ``FVP terminal_1`` is the counterpart for +the secure world (where TAs will print their logs, for instance). + +Log into the image shell with user ``root``, no password will be required. +Then we can issue the ``ftpm`` command, which is an alias that + +(1) loads the ftpm kernel module and + +(2) calls ``tpm2_pcrread``, which will access the fTPM service to read the + PCRs. + +When loading the ftpm kernel module, the fTPM TA is loaded into the secure +world. This TA then requests a copy of the Event Log generated during the +booting process so it can retrieve all the entries on the log and record them +first thing. + +.. note:: + For this PoC, nothing loaded after BL33 and NT_FW_CONFIG is recorded + in the Event Log. + +The secure world terminal should show the debug logs for the fTPM service, +including all the measurements available in the Event Log as they are being +processed: + +.. code:: shell + + M/TA: Preparing to extend the following TPM Event Log: + M/TA: TCG_EfiSpecIDEvent: + M/TA: PCRIndex : 0 + M/TA: EventType : 3 + M/TA: Digest : 00 + M/TA: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + M/TA: : 00 00 00 + M/TA: EventSize : 33 + M/TA: Signature : Spec ID Event03 + M/TA: PlatformClass : 0 + M/TA: SpecVersion : 2.0.2 + M/TA: UintnSize : 1 + M/TA: NumberOfAlgorithms : 1 + M/TA: DigestSizes : + M/TA: #0 AlgorithmId : SHA256 + M/TA: DigestSize : 32 + M/TA: VendorInfoSize : 0 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 3 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + M/TA: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + M/TA: EventSize : 17 + M/TA: Signature : StartupLocality + M/TA: StartupLocality : 0 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 58 26 32 6e 64 45 64 da 45 de 35 db 96 fd ed 63 + M/TA: : 2a 6a d4 0d aa 94 b0 b1 55 e4 72 e7 1f 0a e0 d5 + M/TA: EventSize : 5 + M/TA: Event : BL_2 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : cf f9 7d a3 5c 73 ac cb 7b a0 25 80 6a 6e 50 a5 + M/TA: : 6b 2e d2 8c c9 36 92 7d 46 c5 b9 c3 a4 6c 51 7c + M/TA: EventSize : 6 + M/TA: Event : BL_31 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 23 b0 a3 5d 54 d9 43 1a 5c b9 89 63 1c da 06 c2 + M/TA: : e5 de e7 7e 99 17 52 12 7d f7 45 ca 4f 4a 39 c0 + M/TA: EventSize : 10 + M/TA: Event : HW_CONFIG + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 4e e4 8e 5a e6 50 ed e0 b5 a3 54 8a 1f d6 0e 8a + M/TA: : ea 0e 71 75 0e a4 3f 82 76 ce af cd 7c b0 91 e0 + M/TA: EventSize : 14 + M/TA: Event : SOC_FW_CONFIG + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 01 b0 80 47 a1 ce 86 cd df 89 d2 1f 2e fc 6c 22 + M/TA: : f8 19 ec 6e 1e ec 73 ba 5a be d0 96 e3 5f 6d 75 + M/TA: EventSize : 6 + M/TA: Event : BL_32 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 5d c6 ef 35 5a 90 81 b4 37 e6 3b 52 da 92 ab 8e + M/TA: : d9 6e 93 98 2d 40 87 96 1b 5a a7 ee f1 f4 40 63 + M/TA: EventSize : 18 + M/TA: Event : BL32_EXTRA1_IMAGE + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 39 b7 13 b9 93 db 32 2f 1b 48 30 eb 2c f2 5c 25 + M/TA: : 00 0f 38 dc 8e c8 02 cd 79 f2 48 d2 2c 25 ab e2 + M/TA: EventSize : 6 + M/TA: Event : BL_33 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 25 10 60 5d d4 bc 9d 82 7a 16 9f 8a cc 47 95 a6 + M/TA: : fd ca a0 c1 2b c9 99 8f 51 20 ff c6 ed 74 68 5a + M/TA: EventSize : 13 + M/TA: Event : NT_FW_CONFIG + +These logs correspond to the measurements stored by TF-A during the measured +boot process and therefore, they should match the logs dumped by the former +during the boot up process. These can be seen on the terminal_0: + +.. code:: shell + + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v2.5(release):v2.5 + NOTICE: BL1: Built : 10:41:20, Jul 2 2021 + NOTICE: BL1: Booting BL2 + NOTICE: BL2: v2.5(release):v2.5 + NOTICE: BL2: Built : 10:41:20, Jul 2 2021 + NOTICE: TCG_EfiSpecIDEvent: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 3 + NOTICE: Digest : 00 + NOTICE: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + NOTICE: : 00 00 00 + NOTICE: EventSize : 33 + NOTICE: Signature : Spec ID Event03 + NOTICE: PlatformClass : 0 + NOTICE: SpecVersion : 2.0.2 + NOTICE: UintnSize : 1 + NOTICE: NumberOfAlgorithms : 1 + NOTICE: DigestSizes : + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: DigestSize : 32 + NOTICE: VendorInfoSize : 0 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 3 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + NOTICE: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + NOTICE: EventSize : 17 + NOTICE: Signature : StartupLocality + NOTICE: StartupLocality : 0 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 58 26 32 6e 64 45 64 da 45 de 35 db 96 fd ed 63 + NOTICE: : 2a 6a d4 0d aa 94 b0 b1 55 e4 72 e7 1f 0a e0 d5 + NOTICE: EventSize : 5 + NOTICE: Event : BL_2 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : cf f9 7d a3 5c 73 ac cb 7b a0 25 80 6a 6e 50 a5 + NOTICE: : 6b 2e d2 8c c9 36 92 7d 46 c5 b9 c3 a4 6c 51 7c + NOTICE: EventSize : 6 + NOTICE: Event : BL_31 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 23 b0 a3 5d 54 d9 43 1a 5c b9 89 63 1c da 06 c2 + NOTICE: : e5 de e7 7e 99 17 52 12 7d f7 45 ca 4f 4a 39 c0 + NOTICE: EventSize : 10 + NOTICE: Event : HW_CONFIG + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 4e e4 8e 5a e6 50 ed e0 b5 a3 54 8a 1f d6 0e 8a + NOTICE: : ea 0e 71 75 0e a4 3f 82 76 ce af cd 7c b0 91 e0 + NOTICE: EventSize : 14 + NOTICE: Event : SOC_FW_CONFIG + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 01 b0 80 47 a1 ce 86 cd df 89 d2 1f 2e fc 6c 22 + NOTICE: : f8 19 ec 6e 1e ec 73 ba 5a be d0 96 e3 5f 6d 75 + NOTICE: EventSize : 6 + NOTICE: Event : BL_32 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 5d c6 ef 35 5a 90 81 b4 37 e6 3b 52 da 92 ab 8e + NOTICE: : d9 6e 93 98 2d 40 87 96 1b 5a a7 ee f1 f4 40 63 + NOTICE: EventSize : 18 + NOTICE: Event : BL32_EXTRA1_IMAGE + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 39 b7 13 b9 93 db 32 2f 1b 48 30 eb 2c f2 5c 25 + NOTICE: : 00 0f 38 dc 8e c8 02 cd 79 f2 48 d2 2c 25 ab e2 + NOTICE: EventSize : 6 + NOTICE: Event : BL_33 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 25 10 60 5d d4 bc 9d 82 7a 16 9f 8a cc 47 95 a6 + NOTICE: : fd ca a0 c1 2b c9 99 8f 51 20 ff c6 ed 74 68 5a + NOTICE: EventSize : 13 + NOTICE: Event : NT_FW_CONFIG + NOTICE: BL1: Booting BL31 + NOTICE: BL31: v2.5(release):v2.5 + NOTICE: BL31: Built : 10:41:20, Jul 2 2021 + +Following up with the fTPM startup process, we can see that all the +measurements in the Event Log are extended and recorded in the appropriate PCR: + +.. code:: shell + + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: 9 Event logs processed + +After the fTPM TA is loaded, the call to ``insmod`` issued by the ``ftpm`` +alias to load the ftpm kernel module returns, and then the TPM PCRs are read +by means of ``tpm_pcrread`` command. Note that we are only interested in the +SHA256 logs here, as this is the algorithm we used on TF-A for the measurements +(see the field ``AlgorithmId`` on the logs above): + +.. code:: shell + + sha256: + 0 : 0xA6EB3A7417B8CFA9EBA2E7C22AD5A4C03CDB8F3FBDD7667F9C3EF2EA285A8C9F + 1 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 2 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 3 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 4 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 5 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 6 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 7 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 8 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 9 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 10: 0x0000000000000000000000000000000000000000000000000000000000000000 + 11: 0x0000000000000000000000000000000000000000000000000000000000000000 + 12: 0x0000000000000000000000000000000000000000000000000000000000000000 + 13: 0x0000000000000000000000000000000000000000000000000000000000000000 + 14: 0x0000000000000000000000000000000000000000000000000000000000000000 + 15: 0x0000000000000000000000000000000000000000000000000000000000000000 + 16: 0x0000000000000000000000000000000000000000000000000000000000000000 + 17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 23: 0x0000000000000000000000000000000000000000000000000000000000000000 + +In this PoC we are only interested in PCR0, which must be non-null. This is +because the boot process records all the images in this PCR (see field ``PCRIndex`` +on the Event Log above). The rest of the records must be 0 at this point. + +.. note:: + The fTPM service used has support only for 16 PCRs, therefore the content + of PCRs above 15 can be ignored. + +.. note:: + As stated earlier, Arm does not provide an fTPM implementation and therefore + we do not validate here if the content of PCR0 is correct or not. For this + PoC, we are only focused on the fact that the event log could be passed to a third + party fTPM and its records were properly extended. + +Fine-tuning the fTPM TA +~~~~~~~~~~~~~~~~~~~~~~~ + +As stated earlier, the OP-TEE Toolkit includes support to build a third party fTPM +service. The build options for this service are tailored for the PoC and defined in +the build environment variable ``FTPM_FLAGS`` (see ``/build/common.mk``) +but they can be modified if needed to better adapt it to a specific scenario. + +The most relevant options for Measured Boot support are: + + - **CFG_TA_DEBUG**: Enables debug logs in the Terminal_1 console. + - **CFG_TEE_TA_LOG_LEVEL**: Defines the log level used for the debug messages. + - **CFG_TA_MEASURED_BOOT**: Enables support for measured boot on the fTPM. + - **CFG_TA_EVENT_LOG_SIZE**: Defines the size, in bytes, of the larger event log that + the fTPM is able to store, as this buffer is allocated at build time. This must be at + least the same as the size of the event log generated by TF-A. If this build option + is not defined, the fTPM falls back to a default value of 1024 bytes, which is enough + for this PoC, so this variable is not defined in FTPM_FLAGS. + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* + +.. _OP-TEE Toolkit: https://github.com/OP-TEE/build +.. _ms-tpm-20-ref: https://github.com/microsoft/ms-tpm-20-ref +.. _Get and build the solution: https://optee.readthedocs.io/en/latest/building/gits/build.html#get-and-build-the-solution +.. _Armv8-A Foundation Platform (For Linux Hosts Only): https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models +.. _tpm2-tools: https://github.com/tpm2-software/tpm2-tools +.. _TGC event log: https://trustedcomputinggroup.org/resource/tcg-efi-platform-specification/ diff --git a/arm-trusted-firmware/docs/getting_started/build-options.rst b/arm-trusted-firmware/docs/getting_started/build-options.rst new file mode 100644 index 0000000..adc05e6 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/build-options.rst @@ -0,0 +1,974 @@ +Build Options +============= + +The TF-A build system supports the following build options. Unless mentioned +otherwise, these options are expected to be specified at the build command +line and are not to be modified in any component makefiles. Note that the +build system doesn't track dependency for build options. Therefore, if any of +the build options are changed from a previous build, a clean build must be +performed. + +.. _build_options_common: + +Common build options +-------------------- + +- ``AARCH32_INSTRUCTION_SET``: Choose the AArch32 instruction set that the + compiler should use. Valid values are T32 and A32. It defaults to T32 due to + code having a smaller resulting size. + +- ``AARCH32_SP`` : Choose the AArch32 Secure Payload component to be built as + as the BL32 image when ``ARCH=aarch32``. The value should be the path to the + directory containing the SP source, relative to the ``bl32/``; the directory + is expected to contain a makefile called ``.mk``. + +- ``AMU_RESTRICT_COUNTERS``: Register reads to the group 1 counters will return + zero at all but the highest implemented exception level. Reads from the + memory mapped view are unaffected by this control. + +- ``ARCH`` : Choose the target build architecture for TF-A. It can take either + ``aarch64`` or ``aarch32`` as values. By default, it is defined to + ``aarch64``. + +- ``ARM_ARCH_FEATURE``: Optional Arm Architecture build option which specifies + one or more feature modifiers. This option has the form ``[no]feature+...`` + and defaults to ``none``. It translates into compiler option + ``-march=armvX[.Y]-a+[no]feature+...``. See compiler's documentation for the + list of supported feature modifiers. + +- ``ARM_ARCH_MAJOR``: The major version of Arm Architecture to target when + compiling TF-A. Its value must be numeric, and defaults to 8 . See also, + *Armv8 Architecture Extensions* and *Armv7 Architecture Extensions* in + :ref:`Firmware Design`. + +- ``ARM_ARCH_MINOR``: The minor version of Arm Architecture to target when + compiling TF-A. Its value must be a numeric, and defaults to 0. See also, + *Armv8 Architecture Extensions* in :ref:`Firmware Design`. + +- ``BL2``: This is an optional build option which specifies the path to BL2 + image for the ``fip`` target. In this case, the BL2 in the TF-A will not be + built. + +- ``BL2U``: This is an optional build option which specifies the path to + BL2U image. In this case, the BL2U in TF-A will not be built. + +- ``BL2_AT_EL3``: This is an optional build option that enables the use of + BL2 at EL3 execution level. + +- ``BL2_ENABLE_SP_LOAD``: Boolean option to enable loading SP packages from the + FIP. Automatically enabled if ``SP_LAYOUT_FILE`` is provided. + +- ``BL2_IN_XIP_MEM``: In some use-cases BL2 will be stored in eXecute In Place + (XIP) memory, like BL1. In these use-cases, it is necessary to initialize + the RW sections in RAM, while leaving the RO sections in place. This option + enable this use-case. For now, this option is only supported when BL2_AT_EL3 + is set to '1'. + +- ``BL31``: This is an optional build option which specifies the path to + BL31 image for the ``fip`` target. In this case, the BL31 in TF-A will not + be built. + +- ``BL31_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL31 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BL32``: This is an optional build option which specifies the path to + BL32 image for the ``fip`` target. In this case, the BL32 in TF-A will not + be built. + +- ``BL32_EXTRA1``: This is an optional build option which specifies the path to + Trusted OS Extra1 image for the ``fip`` target. + +- ``BL32_EXTRA2``: This is an optional build option which specifies the path to + Trusted OS Extra2 image for the ``fip`` target. + +- ``BL32_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL32 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BL33``: Path to BL33 image in the host file system. This is mandatory for + ``fip`` target in case TF-A BL2 is used. + +- ``BL33_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL33 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BRANCH_PROTECTION``: Numeric value to enable ARMv8.3 Pointer Authentication + and ARMv8.5 Branch Target Identification support for TF-A BL images themselves. + If enabled, it is needed to use a compiler that supports the option + ``-mbranch-protection``. Selects the branch protection features to use: +- 0: Default value turns off all types of branch protection +- 1: Enables all types of branch protection features +- 2: Return address signing to its standard level +- 3: Extend the signing to include leaf functions +- 4: Turn on branch target identification mechanism + + The table below summarizes ``BRANCH_PROTECTION`` values, GCC compilation options + and resulting PAuth/BTI features. + + +-------+--------------+-------+-----+ + | Value | GCC option | PAuth | BTI | + +=======+==============+=======+=====+ + | 0 | none | N | N | + +-------+--------------+-------+-----+ + | 1 | standard | Y | Y | + +-------+--------------+-------+-----+ + | 2 | pac-ret | Y | N | + +-------+--------------+-------+-----+ + | 3 | pac-ret+leaf | Y | N | + +-------+--------------+-------+-----+ + | 4 | bti | N | Y | + +-------+--------------+-------+-----+ + + This option defaults to 0. + Note that Pointer Authentication is enabled for Non-secure world + irrespective of the value of this option if the CPU supports it. + +- ``BUILD_MESSAGE_TIMESTAMP``: String used to identify the time and date of the + compilation of each build. It must be set to a C string (including quotes + where applicable). Defaults to a string that contains the time and date of + the compilation. + +- ``BUILD_STRING``: Input string for VERSION_STRING, which allows the TF-A + build to be uniquely identified. Defaults to the current git commit id. + +- ``BUILD_BASE``: Output directory for the build. Defaults to ``./build`` + +- ``CFLAGS``: Extra user options appended on the compiler's command line in + addition to the options set by the build system. + +- ``COLD_BOOT_SINGLE_CPU``: This option indicates whether the platform may + release several CPUs out of reset. It can take either 0 (several CPUs may be + brought up) or 1 (only one CPU will ever be brought up during cold reset). + Default is 0. If the platform always brings up a single CPU, there is no + need to distinguish between primary and secondary CPUs and the boot path can + be optimised. The ``plat_is_my_cpu_primary()`` and + ``plat_secondary_cold_boot_setup()`` platform porting interfaces do not need + to be implemented in this case. + +- ``COT``: When Trusted Boot is enabled, selects the desired chain of trust. + Defaults to ``tbbr``. + +- ``CRASH_REPORTING``: A non-zero value enables a console dump of processor + register state when an unexpected exception occurs during execution of + BL31. This option defaults to the value of ``DEBUG`` - i.e. by default + this is only enabled for a debug build of the firmware. + +- ``CREATE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the + certificate generation tool to create new keys in case no valid keys are + present or specified. Allowed options are '0' or '1'. Default is '1'. + +- ``CTX_INCLUDE_AARCH32_REGS`` : Boolean option that, when set to 1, will cause + the AArch32 system registers to be included when saving and restoring the + CPU context. The option must be set to 0 for AArch64-only platforms (that + is on hardware that does not implement AArch32, or at least not at EL1 and + higher ELs). Default value is 1. + +- ``CTX_INCLUDE_EL2_REGS`` : This boolean option provides context save/restore + operations when entering/exiting an EL2 execution context. This is of primary + interest when Armv8.4-SecEL2 extension is implemented. Default is 0 (disabled). + This option must be equal to 1 (enabled) when ``SPD=spmd`` and + ``SPMD_SPM_AT_SEL2`` is set. + +- ``CTX_INCLUDE_FPREGS``: Boolean option that, when set to 1, will cause the FP + registers to be included when saving and restoring the CPU context. Default + is 0. + +- ``CTX_INCLUDE_NEVE_REGS``: Boolean option that, when set to 1, will cause the + Armv8.4-NV registers to be saved/restored when entering/exiting an EL2 + execution context. Default value is 0. + +- ``CTX_INCLUDE_PAUTH_REGS``: Boolean option that, when set to 1, enables + Pointer Authentication for Secure world. This will cause the ARMv8.3-PAuth + registers to be included when saving and restoring the CPU context as + part of world switch. Default value is 0. + Note that Pointer Authentication is enabled for Non-secure world irrespective + of the value of this flag if the CPU supports it. + +- ``DEBUG``: Chooses between a debug and release build. It can take either 0 + (release) or 1 (debug) as values. 0 is the default. + +- ``DECRYPTION_SUPPORT``: This build flag enables the user to select the + authenticated decryption algorithm to be used to decrypt firmware/s during + boot. It accepts 2 values: ``aes_gcm`` and ``none``. The default value of + this flag is ``none`` to disable firmware decryption which is an optional + feature as per TBBR. + +- ``DISABLE_BIN_GENERATION``: Boolean option to disable the generation + of the binary image. If set to 1, then only the ELF image is built. + 0 is the default. + +- ``DISABLE_MTPMU``: Boolean option to disable FEAT_MTPMU if implemented + (Armv8.6 onwards). Its default value is 0 to keep consistency with platforms + that do not implement FEAT_MTPMU. For more information on FEAT_MTPMU, + check the latest Arm ARM. + +- ``DYN_DISABLE_AUTH``: Provides the capability to dynamically disable Trusted + Board Boot authentication at runtime. This option is meant to be enabled only + for development platforms. ``TRUSTED_BOARD_BOOT`` flag must be set if this + flag has to be enabled. 0 is the default. + +- ``E``: Boolean option to make warnings into errors. Default is 1. + +- ``EL3_PAYLOAD_BASE``: This option enables booting an EL3 payload instead of + the normal boot flow. It must specify the entry point address of the EL3 + payload. Please refer to the "Booting an EL3 payload" section for more + details. + +- ``ENABLE_AMU``: Boolean option to enable Activity Monitor Unit extensions. + This is an optional architectural feature available on v8.4 onwards. Some + v8.2 implementations also implement an AMU and this option can be used to + enable this feature on those systems as well. Default is 0. + +- ``ENABLE_AMU_AUXILIARY_COUNTERS``: Enables support for AMU auxiliary counters + (also known as group 1 counters). These are implementation-defined counters, + and as such require additional platform configuration. Default is 0. + +- ``ENABLE_AMU_FCONF``: Enables configuration of the AMU through FCONF, which + allows platforms with auxiliary counters to describe them via the + ``HW_CONFIG`` device tree blob. Default is 0. + +- ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()`` + are compiled out. For debug builds, this option defaults to 1, and calls to + ``assert()`` are left in place. For release builds, this option defaults to 0 + and calls to ``assert()`` function are compiled out. This option can be set + independently of ``DEBUG``. It can also be used to hide any auxiliary code + that is only required for the assertion and does not fit in the assertion + itself. + +- ``ENABLE_BACKTRACE``: This option controls whether to enable backtrace + dumps or not. It is supported in both AArch64 and AArch32. However, in + AArch32 the format of the frame records are not defined in the AAPCS and they + are defined by the implementation. This implementation of backtrace only + supports the format used by GCC when T32 interworking is disabled. For this + reason enabling this option in AArch32 will force the compiler to only + generate A32 code. This option is enabled by default only in AArch64 debug + builds, but this behaviour can be overridden in each platform's Makefile or + in the build command line. + +- ``ENABLE_FEAT_AMUv1``: Boolean option to enable access to the HAFGRTR_EL2 + (Hypervisor Activity Monitors Fine-Grained Read Trap Register) during EL2 + to EL3 context save/restore operations. It is an optional feature available + on v8.4 and onwards and must be set to 1 alongside ``ENABLE_FEAT_FGT``, to + access the HAFGRTR_EL2 register. Defaults to ``0``. + +- ``ENABLE_FEAT_ECV``: Boolean option to enable support for the Enhanced Counter + Virtualization feature, allowing for access to the CNTPOFF_EL2 (Counter-timer + Physical Offset register) during EL2 to EL3 context save/restore operations. + Its a mandatory architectural feature in Armv8.6 and defaults to ``1`` for + v8.6 or later CPUs. + +- ``ENABLE_FEAT_FGT``: Boolean option to enable support for FGT (Fine Grain Traps) + feature allowing for access to the HDFGRTR_EL2 (Hypervisor Debug Fine-Grained + Read Trap Register) during EL2 to EL3 context save/restore operations. + Its a mandatory architectural feature in Armv8.6 and defaults to ``1`` for + v8.6 or later CPUs. + +- ``ENABLE_FEAT_HCX``: This option sets the bit SCR_EL3.HXEn in EL3 to allow + access to HCRX_EL2 (extended hypervisor control register) from EL2 as well as + adding HCRX_EL2 to the EL2 context save/restore operations. + +- ``ENABLE_LTO``: Boolean option to enable Link Time Optimization (LTO) + support in GCC for TF-A. This option is currently only supported for + AArch64. Default is 0. + +- ``ENABLE_MPAM_FOR_LOWER_ELS``: Boolean option to enable lower ELs to use MPAM + feature. MPAM is an optional Armv8.4 extension that enables various memory + system components and resources to define partitions; software running at + various ELs can assign themselves to desired partition to control their + performance aspects. + + When this option is set to ``1``, EL3 allows lower ELs to access their own + MPAM registers without trapping into EL3. This option doesn't make use of + partitioning in EL3, however. Platform initialisation code should configure + and use partitions in EL3 as required. This option defaults to ``0``. + +- ``ENABLE_MPMM``: Boolean option to enable support for the Maximum Power + Mitigation Mechanism supported by certain Arm cores, which allows the SoC + firmware to detect and limit high activity events to assist in SoC processor + power domain dynamic power budgeting and limit the triggering of whole-rail + (i.e. clock chopping) responses to overcurrent conditions. Defaults to ``0``. + +- ``ENABLE_MPMM_FCONF``: Enables configuration of MPMM through FCONF, which + allows platforms with cores supporting MPMM to describe them via the + ``HW_CONFIG`` device tree blob. Default is 0. + +- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE) + support within generic code in TF-A. This option is currently only supported + in BL2_AT_EL3, BL31, and BL32 (TSP) for AARCH64 binaries, and in BL32 + (SP_min) for AARCH32. Default is 0. + +- ``ENABLE_PMF``: Boolean option to enable support for optional Performance + Measurement Framework(PMF). Default is 0. + +- ``ENABLE_PSCI_STAT``: Boolean option to enable support for optional PSCI + functions ``PSCI_STAT_RESIDENCY`` and ``PSCI_STAT_COUNT``. Default is 0. + In the absence of an alternate stat collection backend, ``ENABLE_PMF`` must + be enabled. If ``ENABLE_PMF`` is set, the residency statistics are tracked in + software. + +- ``ENABLE_RME``: Boolean option to enable support for the ARMv9 Realm + Management Extension. Default value is 0. This is currently an experimental + feature. + +- ``ENABLE_RUNTIME_INSTRUMENTATION``: Boolean option to enable runtime + instrumentation which injects timestamp collection points into TF-A to + allow runtime performance to be measured. Currently, only PSCI is + instrumented. Enabling this option enables the ``ENABLE_PMF`` build option + as well. Default is 0. + +- ``ENABLE_SME_FOR_NS``: Boolean option to enable Scalable Matrix Extension + (SME), SVE, and FPU/SIMD for the non-secure world only. These features share + registers so are enabled together. Using this option without + ENABLE_SME_FOR_SWD=1 will cause SME, SVE, and FPU/SIMD instructions in secure + world to trap to EL3. SME is an optional architectural feature for AArch64 + and TF-A support is experimental. At this time, this build option cannot be + used on systems that have SPD=spmd/SPM_MM or ENABLE_RME, and attempting to + build with these options will fail. Default is 0. + +- ``ENABLE_SME_FOR_SWD``: Boolean option to enable the Scalable Matrix + Extension for secure world use along with SVE and FPU/SIMD, ENABLE_SME_FOR_NS + must also be set to use this. If enabling this, the secure world MUST + handle context switching for SME, SVE, and FPU/SIMD registers to ensure that + no data is leaked to non-secure world. This is experimental. Default is 0. + +- ``ENABLE_SPE_FOR_LOWER_ELS`` : Boolean option to enable Statistical Profiling + extensions. This is an optional architectural feature for AArch64. + The default is 1 but is automatically disabled when the target architecture + is AArch32. + +- ``ENABLE_SVE_FOR_NS``: Boolean option to enable Scalable Vector Extension + (SVE) for the Non-secure world only. SVE is an optional architectural feature + for AArch64. Note that when SVE is enabled for the Non-secure world, access + to SIMD and floating-point functionality from the Secure world is disabled by + default and controlled with ENABLE_SVE_FOR_SWD. + This is to avoid corruption of the Non-secure world data in the Z-registers + which are aliased by the SIMD and FP registers. The build option is not + compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an + assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` set to + 1. The default is 1 but is automatically disabled when ENABLE_SME_FOR_NS=1 + since SME encompasses SVE. At this time, this build option cannot be used on + systems that have SPM_MM enabled. + +- ``ENABLE_SVE_FOR_SWD``: Boolean option to enable SVE for the Secure world. + SVE is an optional architectural feature for AArch64. Note that this option + requires ENABLE_SVE_FOR_NS to be enabled. The default is 0 and it is + automatically disabled when the target architecture is AArch32. + +- ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection + checks in GCC. Allowed values are "all", "strong", "default" and "none". The + default value is set to "none". "strong" is the recommended stack protection + level if this feature is desired. "none" disables the stack protection. For + all values other than "none", the ``plat_get_stack_protector_canary()`` + platform hook needs to be implemented. The value is passed as the last + component of the option ``-fstack-protector-$ENABLE_STACK_PROTECTOR``. + +- ``ENCRYPT_BL31``: Binary flag to enable encryption of BL31 firmware. This + flag depends on ``DECRYPTION_SUPPORT`` build flag. + +- ``ENCRYPT_BL32``: Binary flag to enable encryption of Secure BL32 payload. + This flag depends on ``DECRYPTION_SUPPORT`` build flag. + +- ``ENC_KEY``: A 32-byte (256-bit) symmetric key in hex string format. It could + either be SSK or BSSK depending on ``FW_ENC_STATUS`` flag. This value depends + on ``DECRYPTION_SUPPORT`` build flag. + +- ``ENC_NONCE``: A 12-byte (96-bit) encryption nonce or Initialization Vector + (IV) in hex string format. This value depends on ``DECRYPTION_SUPPORT`` + build flag. + +- ``ERROR_DEPRECATED``: This option decides whether to treat the usage of + deprecated platform APIs, helper functions or drivers within Trusted + Firmware as error. It can take the value 1 (flag the use of deprecated + APIs as error) or 0. The default is 0. + +- ``EL3_EXCEPTION_HANDLING``: When set to ``1``, enable handling of exceptions + targeted at EL3. When set ``0`` (default), no exceptions are expected or + handled at EL3, and a panic will result. This is supported only for AArch64 + builds. + +- ``EVENT_LOG_LEVEL``: Chooses the log level to use for Measured Boot when + ``MEASURED_BOOT`` is enabled. For a list of valid values, see ``LOG_LEVEL``. + Default value is 40 (LOG_LEVEL_INFO). + +- ``FAULT_INJECTION_SUPPORT``: ARMv8.4 extensions introduced support for fault + injection from lower ELs, and this build option enables lower ELs to use + Error Records accessed via System Registers to inject faults. This is + applicable only to AArch64 builds. + + This feature is intended for testing purposes only, and is advisable to keep + disabled for production images. + +- ``FIP_NAME``: This is an optional build option which specifies the FIP + filename for the ``fip`` target. Default is ``fip.bin``. + +- ``FWU_FIP_NAME``: This is an optional build option which specifies the FWU + FIP filename for the ``fwu_fip`` target. Default is ``fwu_fip.bin``. + +- ``FW_ENC_STATUS``: Top level firmware's encryption numeric flag, values: + + :: + + 0: Encryption is done with Secret Symmetric Key (SSK) which is common + for a class of devices. + 1: Encryption is done with Binding Secret Symmetric Key (BSSK) which is + unique per device. + + This flag depends on ``DECRYPTION_SUPPORT`` build flag. + +- ``GENERATE_COT``: Boolean flag used to build and execute the ``cert_create`` + tool to create certificates as per the Chain of Trust described in + :ref:`Trusted Board Boot`. The build system then calls ``fiptool`` to + include the certificates in the FIP and FWU_FIP. Default value is '0'. + + Specify both ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=1`` to include support + for the Trusted Board Boot feature in the BL1 and BL2 images, to generate + the corresponding certificates, and to include those certificates in the + FIP and FWU_FIP. + + Note that if ``TRUSTED_BOARD_BOOT=0`` and ``GENERATE_COT=1``, the BL1 and BL2 + images will not include support for Trusted Board Boot. The FIP will still + include the corresponding certificates. This FIP can be used to verify the + Chain of Trust on the host machine through other mechanisms. + + Note that if ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=0``, the BL1 and BL2 + images will include support for Trusted Board Boot, but the FIP and FWU_FIP + will not include the corresponding certificates, causing a boot failure. + +- ``GICV2_G0_FOR_EL3``: Unlike GICv3, the GICv2 architecture doesn't have + inherent support for specific EL3 type interrupts. Setting this build option + to ``1`` assumes GICv2 *Group 0* interrupts are expected to target EL3, both + by :ref:`platform abstraction layer` and + :ref:`Interrupt Management Framework`. + This allows GICv2 platforms to enable features requiring EL3 interrupt type. + This also means that all GICv2 Group 0 interrupts are delivered to EL3, and + the Secure Payload interrupts needs to be synchronously handed over to Secure + EL1 for handling. The default value of this option is ``0``, which means the + Group 0 interrupts are assumed to be handled by Secure EL1. + +- ``HANDLE_EA_EL3_FIRST``: When set to ``1``, External Aborts and SError + Interrupts will be always trapped in EL3 i.e. in BL31 at runtime. When set to + ``0`` (default), these exceptions will be trapped in the current exception + level (or in EL1 if the current exception level is EL0). + +- ``HW_ASSISTED_COHERENCY``: On most Arm systems to-date, platform-specific + software operations are required for CPUs to enter and exit coherency. + However, newer systems exist where CPUs' entry to and exit from coherency + is managed in hardware. Such systems require software to only initiate these + operations, and the rest is managed in hardware, minimizing active software + management. In such systems, this boolean option enables TF-A to carry out + build and run-time optimizations during boot and power management operations. + This option defaults to 0 and if it is enabled, then it implies + ``WARMBOOT_ENABLE_DCACHE_EARLY`` is also enabled. + + If this flag is disabled while the platform which TF-A is compiled for + includes cores that manage coherency in hardware, then a compilation error is + generated. This is based on the fact that a system cannot have, at the same + time, cores that manage coherency in hardware and cores that don't. In other + words, a platform cannot have, at the same time, cores that require + ``HW_ASSISTED_COHERENCY=1`` and cores that require + ``HW_ASSISTED_COHERENCY=0``. + + Note that, when ``HW_ASSISTED_COHERENCY`` is enabled, version 2 of + translation library (xlat tables v2) must be used; version 1 of translation + library is not supported. + +- ``INVERTED_MEMMAP``: memmap tool print by default lower addresses at the + bottom, higher addresses at the top. This build flag can be set to '1' to + invert this behavior. Lower addresses will be printed at the top and higher + addresses at the bottom. + +- ``JUNO_AARCH32_EL3_RUNTIME``: This build flag enables you to execute EL3 + runtime software in AArch32 mode, which is required to run AArch32 on Juno. + By default this flag is set to '0'. Enabling this flag builds BL1 and BL2 in + AArch64 and facilitates the loading of ``SP_MIN`` and BL33 as AArch32 executable + images. + +- ``KEY_ALG``: This build flag enables the user to select the algorithm to be + used for generating the PKCS keys and subsequent signing of the certificate. + It accepts 3 values: ``rsa``, ``rsa_1_5`` and ``ecdsa``. The option + ``rsa_1_5`` is the legacy PKCS#1 RSA 1.5 algorithm which is not TBBR + compliant and is retained only for compatibility. The default value of this + flag is ``rsa`` which is the TBBR compliant PKCS#1 RSA 2.1 scheme. + +- ``KEY_SIZE``: This build flag enables the user to select the key size for + the algorithm specified by ``KEY_ALG``. The valid values for ``KEY_SIZE`` + depend on the chosen algorithm and the cryptographic module. + + +-----------+------------------------------------+ + | KEY_ALG | Possible key sizes | + +===========+====================================+ + | rsa | 1024 , 2048 (default), 3072, 4096* | + +-----------+------------------------------------+ + | ecdsa | unavailable | + +-----------+------------------------------------+ + + * Only 2048 bits size is available with CryptoCell 712 SBROM release 1. + Only 3072 bits size is available with CryptoCell 712 SBROM release 2. + +- ``HASH_ALG``: This build flag enables the user to select the secure hash + algorithm. It accepts 3 values: ``sha256``, ``sha384`` and ``sha512``. + The default value of this flag is ``sha256``. + +- ``LDFLAGS``: Extra user options appended to the linkers' command line in + addition to the one set by the build system. + +- ``LOG_LEVEL``: Chooses the log level, which controls the amount of console log + output compiled into the build. This should be one of the following: + + :: + + 0 (LOG_LEVEL_NONE) + 10 (LOG_LEVEL_ERROR) + 20 (LOG_LEVEL_NOTICE) + 30 (LOG_LEVEL_WARNING) + 40 (LOG_LEVEL_INFO) + 50 (LOG_LEVEL_VERBOSE) + + All log output up to and including the selected log level is compiled into + the build. The default value is 40 in debug builds and 20 in release builds. + +- ``MEASURED_BOOT``: Boolean flag to include support for the Measured Boot + feature. This flag can be enabled with ``TRUSTED_BOARD_BOOT`` in order to + provide trust that the code taking the measurements and recording them has + not been tampered with. + + This option defaults to 0. + +- ``NON_TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It + specifies the file that contains the Non-Trusted World private key in PEM + format. If ``SAVE_KEYS=1``, this file name will be used to save the key. + +- ``NS_BL2U``: Path to NS_BL2U image in the host file system. This image is + optional. It is only needed if the platform makefile specifies that it + is required in order to build the ``fwu_fip`` target. + +- ``NS_TIMER_SWITCH``: Enable save and restore for non-secure timer register + contents upon world switch. It can take either 0 (don't save and restore) or + 1 (do save and restore). 0 is the default. An SPD may set this to 1 if it + wants the timer registers to be saved and restored. + +- ``OVERRIDE_LIBC``: This option allows platforms to override the default libc + for the BL image. It can be either 0 (include) or 1 (remove). The default + value is 0. + +- ``PL011_GENERIC_UART``: Boolean option to indicate the PL011 driver that + the underlying hardware is not a full PL011 UART but a minimally compliant + generic UART, which is a subset of the PL011. The driver will not access + any register that is not part of the SBSA generic UART specification. + Default value is 0 (a full PL011 compliant UART is present). + +- ``PLAT``: Choose a platform to build TF-A for. The chosen platform name + must be subdirectory of any depth under ``plat/``, and must contain a + platform makefile named ``platform.mk``. For example, to build TF-A for the + Arm Juno board, select PLAT=juno. + +- ``PRELOADED_BL33_BASE``: This option enables booting a preloaded BL33 image + instead of the normal boot flow. When defined, it must specify the entry + point address for the preloaded BL33 image. This option is incompatible with + ``EL3_PAYLOAD_BASE``. If both are defined, ``EL3_PAYLOAD_BASE`` has priority + over ``PRELOADED_BL33_BASE``. + +- ``PROGRAMMABLE_RESET_ADDRESS``: This option indicates whether the reset + vector address can be programmed or is fixed on the platform. It can take + either 0 (fixed) or 1 (programmable). Default is 0. If the platform has a + programmable reset address, it is expected that a CPU will start executing + code directly at the right address, both on a cold and warm reset. In this + case, there is no need to identify the entrypoint on boot and the boot path + can be optimised. The ``plat_get_my_entrypoint()`` platform porting interface + does not need to be implemented in this case. + +- ``PSCI_EXTENDED_STATE_ID``: As per PSCI1.0 Specification, there are 2 formats + possible for the PSCI power-state parameter: original and extended State-ID + formats. This flag if set to 1, configures the generic PSCI layer to use the + extended format. The default value of this flag is 0, which means by default + the original power-state format is used by the PSCI implementation. This flag + should be specified by the platform makefile and it governs the return value + of PSCI_FEATURES API for CPU_SUSPEND smc function id. When this option is + enabled on Arm platforms, the option ``ARM_RECOM_STATE_ID_ENC`` needs to be + set to 1 as well. + +- ``RAS_EXTENSION``: When set to ``1``, enable Armv8.2 RAS features. RAS features + are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2 + or later CPUs. + + When ``RAS_EXTENSION`` is set to ``1``, ``HANDLE_EA_EL3_FIRST`` must also be + set to ``1``. + + This option is disabled by default. + +- ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead + of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 + entrypoint) or 1 (CPU reset to BL31 entrypoint). + The default value is 0. + +- ``RESET_TO_SP_MIN``: SP_MIN is the minimal AArch32 Secure Payload provided + in TF-A. This flag configures SP_MIN entrypoint as the CPU reset vector + instead of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 + entrypoint) or 1 (CPU reset to SP_MIN entrypoint). The default value is 0. + +- ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the ROT private key in PEM format and enforces public key + hash generation. If ``SAVE_KEYS=1``, this + file name will be used to save the key. + +- ``SAVE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the + certificate generation tool to save the keys used to establish the Chain of + Trust. Allowed options are '0' or '1'. Default is '0' (do not save). + +- ``SCP_BL2``: Path to SCP_BL2 image in the host file system. This image is optional. + If a SCP_BL2 image is present then this option must be passed for the ``fip`` + target. + +- ``SCP_BL2_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the SCP_BL2 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``SCP_BL2U``: Path to SCP_BL2U image in the host file system. This image is + optional. It is only needed if the platform makefile specifies that it + is required in order to build the ``fwu_fip`` target. + +- ``SDEI_SUPPORT``: Setting this to ``1`` enables support for Software + Delegated Exception Interface to BL31 image. This defaults to ``0``. + + When set to ``1``, the build option ``EL3_EXCEPTION_HANDLING`` must also be + set to ``1``. + +- ``SEPARATE_CODE_AND_RODATA``: Whether code and read-only data should be + isolated on separate memory pages. This is a trade-off between security and + memory usage. See "Isolating code and read-only data on separate memory + pages" section in :ref:`Firmware Design`. This flag is disabled by default + and affects all BL images. + +- ``SEPARATE_NOBITS_REGION``: Setting this option to ``1`` allows the NOBITS + sections of BL31 (.bss, stacks, page tables, and coherent memory) to be + allocated in RAM discontiguous from the loaded firmware image. When set, the + platform is expected to provide definitions for ``BL31_NOBITS_BASE`` and + ``BL31_NOBITS_LIMIT``. When the option is ``0`` (the default), NOBITS + sections are placed in RAM immediately following the loaded firmware image. + +- ``SEPARATE_BL2_NOLOAD_REGION``: Setting this option to ``1`` allows the + NOLOAD sections of BL2 (.bss, stacks, page tables) to be allocated in RAM + discontiguous from loaded firmware images. When set, the platform need to + provide definitions of ``BL2_NOLOAD_START`` and ``BL2_NOLOAD_LIMIT``. This + flag is disabled by default and NOLOAD sections are placed in RAM immediately + following the loaded firmware image. + +- ``SMC_PCI_SUPPORT``: This option allows platforms to handle PCI configuration + access requests via a standard SMCCC defined in `DEN0115`_. When combined with + UEFI+ACPI this can provide a certain amount of OS forward compatibility + with newer platforms that aren't ECAM compliant. + +- ``SPD``: Choose a Secure Payload Dispatcher component to be built into TF-A. + This build option is only valid if ``ARCH=aarch64``. The value should be + the path to the directory containing the SPD source, relative to + ``services/spd/``; the directory is expected to contain a makefile called + ``.mk``. The SPM Dispatcher standard service is located in + services/std_svc/spmd and enabled by ``SPD=spmd``. The SPM Dispatcher + cannot be enabled when the ``SPM_MM`` option is enabled. + +- ``SPIN_ON_BL1_EXIT``: This option introduces an infinite loop in BL1. It can + take either 0 (no loop) or 1 (add a loop). 0 is the default. This loop stops + execution in BL1 just before handing over to BL31. At this point, all + firmware images have been loaded in memory, and the MMU and caches are + turned off. Refer to the "Debugging options" section for more details. + +- ``SPMD_SPM_AT_SEL2`` : this boolean option is used jointly with the SPM + Dispatcher option (``SPD=spmd``). When enabled (1) it indicates the SPMC + component runs at the S-EL2 execution state provided by the Armv8.4-SecEL2 + extension. This is the default when enabling the SPM Dispatcher. When + disabled (0) it indicates the SPMC component runs at the S-EL1 execution + state. This latter configuration supports pre-Armv8.4 platforms (aka not + implementing the Armv8.4-SecEL2 extension). + +- ``SPM_MM`` : Boolean option to enable the Management Mode (MM)-based Secure + Partition Manager (SPM) implementation. The default value is ``0`` + (disabled). This option cannot be enabled (``1``) when SPM Dispatcher is + enabled (``SPD=spmd``). + +- ``SP_LAYOUT_FILE``: Platform provided path to JSON file containing the + description of secure partitions. The build system will parse this file and + package all secure partition blobs into the FIP. This file is not + necessarily part of TF-A tree. Only available when ``SPD=spmd``. + +- ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles + secure interrupts (caught through the FIQ line). Platforms can enable + this directive if they need to handle such interruption. When enabled, + the FIQ are handled in monitor mode and non secure world is not allowed + to mask these events. Platforms that enable FIQ handling in SP_MIN shall + implement the api ``sp_min_plat_fiq_handler()``. The default value is 0. + +- ``TRUSTED_BOARD_BOOT``: Boolean flag to include support for the Trusted Board + Boot feature. When set to '1', BL1 and BL2 images include support to load + and verify the certificates and images in a FIP, and BL1 includes support + for the Firmware Update. The default value is '0'. Generation and inclusion + of certificates in the FIP and FWU_FIP depends upon the value of the + ``GENERATE_COT`` option. + + .. warning:: + This option depends on ``CREATE_KEYS`` to be enabled. If the keys + already exist in disk, they will be overwritten without further notice. + +- ``TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It + specifies the file that contains the Trusted World private key in PEM + format. If ``SAVE_KEYS=1``, this file name will be used to save the key. + +- ``TSP_INIT_ASYNC``: Choose BL32 initialization method as asynchronous or + synchronous, (see "Initializing a BL32 Image" section in + :ref:`Firmware Design`). It can take the value 0 (BL32 is initialized using + synchronous method) or 1 (BL32 is initialized using asynchronous method). + Default is 0. + +- ``TSP_NS_INTR_ASYNC_PREEMPT``: A non zero value enables the interrupt + routing model which routes non-secure interrupts asynchronously from TSP + to EL3 causing immediate preemption of TSP. The EL3 is responsible + for saving and restoring the TSP context in this routing model. The + default routing model (when the value is 0) is to route non-secure + interrupts to TSP allowing it to save its context and hand over + synchronously to EL3 via an SMC. + + .. note:: + When ``EL3_EXCEPTION_HANDLING`` is ``1``, ``TSP_NS_INTR_ASYNC_PREEMPT`` + must also be set to ``1``. + +- ``USE_ARM_LINK``: This flag determines whether to enable support for ARM + linker. When the ``LINKER`` build variable points to the armlink linker, + this flag is enabled automatically. To enable support for armlink, platforms + will have to provide a scatter file for the BL image. Currently, Tegra + platforms use the armlink support to compile BL3-1 images. + +- ``USE_COHERENT_MEM``: This flag determines whether to include the coherent + memory region in the BL memory map or not (see "Use of Coherent memory in + TF-A" section in :ref:`Firmware Design`). It can take the value 1 + (Coherent memory region is included) or 0 (Coherent memory region is + excluded). Default is 1. + +- ``USE_DEBUGFS``: When set to 1 this option activates an EXPERIMENTAL feature + exposing a virtual filesystem interface through BL31 as a SiP SMC function. + Default is 0. + +- ``ARM_IO_IN_DTB``: This flag determines whether to use IO based on the + firmware configuration framework. This will move the io_policies into a + configuration device tree, instead of static structure in the code base. + +- ``COT_DESC_IN_DTB``: This flag determines whether to create COT descriptors + at runtime using fconf. If this flag is enabled, COT descriptors are + statically captured in tb_fw_config file in the form of device tree nodes + and properties. Currently, COT descriptors used by BL2 are moved to the + device tree and COT descriptors used by BL1 are retained in the code + base statically. + +- ``SDEI_IN_FCONF``: This flag determines whether to configure SDEI setup in + runtime using firmware configuration framework. The platform specific SDEI + shared and private events configuration is retrieved from device tree rather + than static C structures at compile time. This is only supported if + SDEI_SUPPORT build flag is enabled. + +- ``SEC_INT_DESC_IN_FCONF``: This flag determines whether to configure Group 0 + and Group1 secure interrupts using the firmware configuration framework. The + platform specific secure interrupt property descriptor is retrieved from + device tree in runtime rather than depending on static C structure at compile + time. + +- ``USE_ROMLIB``: This flag determines whether library at ROM will be used. + This feature creates a library of functions to be placed in ROM and thus + reduces SRAM usage. Refer to :ref:`Library at ROM` for further details. Default + is 0. + +- ``V``: Verbose build. If assigned anything other than 0, the build commands + are printed. Default is 0. + +- ``VERSION_STRING``: String used in the log output for each TF-A image. + Defaults to a string formed by concatenating the version number, build type + and build string. + +- ``W``: Warning level. Some compiler warning options of interest have been + regrouped and put in the root Makefile. This flag can take the values 0 to 3, + each level enabling more warning options. Default is 0. + +- ``WARMBOOT_ENABLE_DCACHE_EARLY`` : Boolean option to enable D-cache early on + the CPU after warm boot. This is applicable for platforms which do not + require interconnect programming to enable cache coherency (eg: single + cluster platforms). If this option is enabled, then warm boot path + enables D-caches immediately after enabling MMU. This option defaults to 0. + +- ``SUPPORT_STACK_MEMTAG``: This flag determines whether to enable memory + tagging for stack or not. It accepts 2 values: ``yes`` and ``no``. The + default value of this flag is ``no``. Note this option must be enabled only + for ARM architecture greater than Armv8.5-A. + +- ``ERRATA_SPECULATIVE_AT``: This flag determines whether to enable ``AT`` + speculative errata workaround or not. It accepts 2 values: ``1`` and ``0``. + The default value of this flag is ``0``. + + ``AT`` speculative errata workaround disables stage1 page table walk for + lower ELs (EL1 and EL0) in EL3 so that ``AT`` speculative fetch at any point + produces either the correct result or failure without TLB allocation. + + This boolean option enables errata for all below CPUs. + + +---------+--------------+-------------------------+ + | Errata | CPU | Workaround Define | + +=========+==============+=========================+ + | 1165522 | Cortex-A76 | ``ERRATA_A76_1165522`` | + +---------+--------------+-------------------------+ + | 1319367 | Cortex-A72 | ``ERRATA_A72_1319367`` | + +---------+--------------+-------------------------+ + | 1319537 | Cortex-A57 | ``ERRATA_A57_1319537`` | + +---------+--------------+-------------------------+ + | 1530923 | Cortex-A55 | ``ERRATA_A55_1530923`` | + +---------+--------------+-------------------------+ + | 1530924 | Cortex-A53 | ``ERRATA_A53_1530924`` | + +---------+--------------+-------------------------+ + + .. note:: + This option is enabled by build only if platform sets any of above defines + mentioned in ’Workaround Define' column in the table. + If this option is enabled for the EL3 software then EL2 software also must + implement this workaround due to the behaviour of the errata mentioned + in new SDEN document which will get published soon. + +- ``RAS_TRAP_LOWER_EL_ERR_ACCESS``: This flag enables/disables the SCR_EL3.TERR + bit, to trap access to the RAS ERR and RAS ERX registers from lower ELs. + This flag is disabled by default. + +- ``OPENSSL_DIR``: This flag is used to provide the installed openssl directory + path on the host machine which is used to build certificate generation and + firmware encryption tool. + +- ``USE_SP804_TIMER``: Use the SP804 timer instead of the Generic Timer for + functions that wait for an arbitrary time length (udelay and mdelay). The + default value is 0. + +- ``ENABLE_TRBE_FOR_NS``: This flag is used to enable access of trace buffer + control registers from NS ELs, NS-EL2 or NS-EL1(when NS-EL2 is implemented + but unused) when FEAT_TRBE is implemented. TRBE is an optional architectural + feature for AArch64. The default is 0 and it is automatically disabled when + the target architecture is AArch32. + +- ``ENABLE_SYS_REG_TRACE_FOR_NS``: Boolean option to enable trace system + registers access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented + but unused). This feature is available if trace unit such as ETMv4.x, and + ETE(extending ETM feature) is implemented. This flag is disabled by default. + +- ``ENABLE_TRF_FOR_NS``: Boolean option to enable trace filter control registers + access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented but unused), + if FEAT_TRF is implemented. This flag is disabled by default. + +GICv3 driver options +-------------------- + +GICv3 driver files are included using directive: + +``include drivers/arm/gic/v3/gicv3.mk`` + +The driver can be configured with the following options set in the platform +makefile: + +- ``GICV3_SUPPORT_GIC600``: Add support for the GIC-600 variants of GICv3. + Enabling this option will add runtime detection support for the + GIC-600, so is safe to select even for a GIC500 implementation. + This option defaults to 0. + +- ``GICV3_SUPPORT_GIC600AE_FMU``: Add support for the Fault Management Unit + for GIC-600 AE. Enabling this option will introduce support to initialize + the FMU. Platforms should call the init function during boot to enable the + FMU and its safety mechanisms. This option defaults to 0. + +- ``GICV3_IMPL_GIC600_MULTICHIP``: Selects GIC-600 variant with multichip + functionality. This option defaults to 0 + +- ``GICV3_OVERRIDE_DISTIF_PWR_OPS``: Allows override of default implementation + of ``arm_gicv3_distif_pre_save`` and ``arm_gicv3_distif_post_restore`` + functions. This is required for FVP platform which need to simulate GIC save + and restore during SYSTEM_SUSPEND without powering down GIC. Default is 0. + +- ``GIC_ENABLE_V4_EXTN`` : Enables GICv4 related changes in GICv3 driver. + This option defaults to 0. + +- ``GIC_EXT_INTID``: When set to ``1``, GICv3 driver will support extended + PPI (1056-1119) and SPI (4096-5119) range. This option defaults to 0. + +Debugging options +----------------- + +To compile a debug version and make the build more verbose use + +.. code:: shell + + make PLAT= DEBUG=1 V=1 all + +AArch64 GCC uses DWARF version 4 debugging symbols by default. Some tools (for +example DS-5) might not support this and may need an older version of DWARF +symbols to be emitted by GCC. This can be achieved by using the +``-gdwarf-`` flag, with the version being set to 2 or 3. Setting the +version to 2 is recommended for DS-5 versions older than 5.16. + +When debugging logic problems it might also be useful to disable all compiler +optimizations by using ``-O0``. + +.. warning:: + Using ``-O0`` could cause output images to be larger and base addresses + might need to be recalculated (see the **Memory layout on Arm development + platforms** section in the :ref:`Firmware Design`). + +Extra debug options can be passed to the build system by setting ``CFLAGS`` or +``LDFLAGS``: + +.. code:: shell + + CFLAGS='-O0 -gdwarf-2' \ + make PLAT= DEBUG=1 V=1 all + +Note that using ``-Wl,`` style compilation driver options in ``CFLAGS`` will be +ignored as the linker is called directly. + +It is also possible to introduce an infinite loop to help in debugging the +post-BL2 phase of TF-A. This can be done by rebuilding BL1 with the +``SPIN_ON_BL1_EXIT=1`` build flag. Refer to the :ref:`build_options_common` +section. In this case, the developer may take control of the target using a +debugger when indicated by the console output. When using DS-5, the following +commands can be used: + +:: + + # Stop target execution + interrupt + + # + # Prepare your debugging environment, e.g. set breakpoints + # + + # Jump over the debug loop + set var $AARCH64::$Core::$PC = $AARCH64::$Core::$PC + 4 + + # Resume execution + continue + +Firmware update options +----------------------- + +- ``NR_OF_FW_BANKS``: Define the number of firmware banks. This flag is used + in defining the firmware update metadata structure. This flag is by default + set to '2'. + +- ``NR_OF_IMAGES_IN_FW_BANK``: Define the number of firmware images in each + firmware bank. Each firmware bank must have the same number of images as per + the `PSA FW update specification`_. + This flag is used in defining the firmware update metadata structure. This + flag is by default set to '1'. + +- ``PSA_FWU_SUPPORT``: Enable the firmware update mechanism as per the + `PSA FW update specification`_. The default value is 0, and this is an + experimental feature. + PSA firmware update implementation has some limitations, such as BL2 is + not part of the protocol-updatable images, if BL2 needs to be updated, then + it should be done through another platform-defined mechanism, and it assumes + that the platform's hardware supports CRC32 instructions. + +-------------- + +*Copyright (c) 2019-2022, Arm Limited. All rights reserved.* + +.. _DEN0115: https://developer.arm.com/docs/den0115/latest +.. _PSA FW update specification: https://developer.arm.com/documentation/den0118/a/ diff --git a/arm-trusted-firmware/docs/getting_started/docs-build.rst b/arm-trusted-firmware/docs/getting_started/docs-build.rst new file mode 100644 index 0000000..87c677f --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/docs-build.rst @@ -0,0 +1,115 @@ +Building Documentation +====================== + +To create a rendered copy of this documentation locally you can use the +`Sphinx`_ tool to build and package the plain-text documents into HTML-formatted +pages. + +If you are building the documentation for the first time then you will need to +check that you have the required software packages, as described in the +*Prerequisites* section that follows. + +.. note:: + An online copy of the documentation is available at + https://www.trustedfirmware.org/docs/tf-a, if you want to view a rendered + copy without doing a local build. + +Prerequisites +------------- + +For building a local copy of the |TF-A| documentation you will need, at minimum: + +- Python 3 (3.5 or later) +- PlantUML (1.2017.15 or later) + +Optionally, the `Dia`_ application can be installed if you need to edit +existing ``.dia`` diagram files, or create new ones. + +You must also install the Python modules that are specified in the +``requirements.txt`` file in the root of the ``docs`` directory. These modules +can be installed using ``pip3`` (the Python Package Installer). Passing this +requirements file as an argument to ``pip3`` automatically installs the specific +module versions required by |TF-A|. + +An example set of installation commands for Ubuntu 18.04 LTS follows, assuming +that the working directory is ``docs``: + +.. code:: shell + + sudo apt install python3 python3-pip plantuml [dia] + pip3 install [--user] -r requirements.txt + +.. note:: + Several other modules will be installed as dependencies. Please review + the list to ensure that there will be no conflicts with other modules already + installed in your environment. + +Passing the optional ``--user`` argument to ``pip3`` will install the Python +packages only for the current user. Omitting this argument will attempt to +install the packages globally and this will likely require the command to be run +as root or using ``sudo``. + +.. note:: + More advanced usage instructions for *pip* are beyond the scope of this + document but you can refer to the `pip homepage`_ for detailed guides. + +Building rendered documentation +------------------------------- + +Documents can be built into HTML-formatted pages from project root directory by +running the following command. + +.. code:: shell + + make doc + +Output from the build process will be placed in: + +:: + + docs/build/html + +We also support building documentation in other formats. From the ``docs`` +directory of the project, run the following command to see the supported +formats. It is important to note that you will not get the correct result if +the command is run from the project root directory, as that would invoke the +top-level Makefile for |TF-A| itself. + +.. code:: shell + + make help + +Building rendered documentation from a container +------------------------------------------------ + +There may be cases where you can not either install or upgrade required +dependencies to generate the documents, so in this case, one way to +create the documentation is through a docker container. The first step is +to check if `docker`_ is installed in your host, otherwise check main docker +page for installation instructions. Once installed, run the following script +from project root directory + +.. code:: shell + + docker run --rm -v $PWD:/TF sphinxdoc/sphinx \ + bash -c 'cd /TF && \ + pip3 install plantuml -r ./docs/requirements.txt && make doc' + +The above command fetches the ``sphinxdoc/sphinx`` container from `docker +hub`_, launches the container, installs documentation requirements and finally +creates the documentation. Once done, exit the container and output from the +build process will be placed in: + +:: + + docs/build/html + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* + +.. _Sphinx: http://www.sphinx-doc.org/en/master/ +.. _pip homepage: https://pip.pypa.io/en/stable/ +.. _Dia: https://wiki.gnome.org/Apps/Dia +.. _docker: https://www.docker.com/ +.. _docker hub: https://hub.docker.com/repository/docker/sphinxdoc/sphinx diff --git a/arm-trusted-firmware/docs/getting_started/image-terminology.rst b/arm-trusted-firmware/docs/getting_started/image-terminology.rst new file mode 100644 index 0000000..a90ec0b --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/image-terminology.rst @@ -0,0 +1,183 @@ +Image Terminology +================= + +This page contains the current name, abbreviated name and purpose of the various +images referred to in the Trusted Firmware project. + +General Notes +------------- + +- Some of the names and abbreviated names have changed to accommodate new + requirements. The changed names are as backward compatible as possible to + minimize confusion. Where applicable, the previous names are indicated. Some + code, documentation and build artefacts may still refer to the previous names; + these will inevitably take time to catch up. + +- The main name change is to prefix each image with the processor it corresponds + to (for example ``AP_``, ``SCP_``, ...). In situations where there is no + ambiguity (for example, within AP specific code/documentation), it is + permitted to omit the processor prefix (for example, just BL1 instead of + ``AP_BL1``). + +- Previously, the format for 3rd level images had 2 forms; ``BL3`` was either + suffixed with a dash ("-") followed by a number (for example, ``BL3-1``) or a + subscript number, depending on whether rich text formatting was available. + This was confusing and often the dash gets omitted in practice. Therefore the + new form is to just omit the dash and not use subscript formatting. + +- The names no longer contain dash ("-") characters at all. In some places (for + example, function names) it's not possible to use this character. All dashes + are either removed or replaced by underscores ("_"). + +- The abbreviation BL stands for BootLoader. This is a historical anomaly. + Clearly, many of these images are not BootLoaders, they are simply firmware + images. However, the BL abbreviation is now widely used and is retained for + backwards compatibility. + +- The image names are not case sensitive. For example, ``bl1`` is + interchangeable with ``BL1``, although mixed case should be avoided. + +Trusted Firmware Images +----------------------- + +AP Boot ROM: ``AP_BL1`` +~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first code to execute on the AP and cannot be modified. +Its primary purpose is to perform the minimum initialization necessary to load +and authenticate an updateable AP firmware image into an executable RAM +location, then hand-off control to that image. + +AP RAM Firmware: ``AP_BL2`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage AP firmware. It is currently also known as the "Trusted +Boot Firmware". Its primary purpose is to perform any additional initialization +required to load and authenticate all 3rd level firmware images into their +executable RAM locations, then hand-off control to the EL3 Runtime Firmware. + +EL3 Runtime Firmware: ``AP_BL31`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Also known as "SoC AP firmware" or "EL3 monitor firmware". Its primary purpose +is to handle transitions between the normal and secure world. + +Secure-EL1 Payload (SP): ``AP_BL32`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically this is a TEE or Trusted OS, providing runtime secure services to the +normal world. However, it may refer to a more abstract Secure-EL1 Payload (SP). +Note that this abbreviation should only be used in systems where there is a +single or primary image executing at Secure-EL1. In systems where there are +potentially multiple SPs and there is no concept of a primary SP, this +abbreviation should be avoided; use the recommended **Other AP 3rd level +images** abbreviation instead. + +AP Normal World Firmware: ``AP_BL33`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For example, UEFI or uboot. Its primary purpose is to boot a normal world OS. + +Other AP 3rd level images: ``AP_BL3_XXX`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The abbreviated names of the existing 3rd level images imply a load/execution +ordering (for example, ``AP_BL31 -> AP_BL32 -> AP_BL33``). Some systems may +have additional images and/or a different load/execution ordering. The +abbreviated names of the existing images are retained for backward compatibility +but new 3rd level images should be suffixed with an underscore followed by text +identifier, not a number. + +In systems where 3rd level images are provided by different vendors, the +abbreviated name should identify the vendor as well as the image +function. For example, ``AP_BL3_ARM_RAS``. + +Realm Monitor Management Firmware: ``RMM`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the Realm-EL2 firmware. It is required if +:ref:`Realm Management Extension (RME)` feature is enabled. If a path to RMM +image is not provided, TF-A builds Test Realm Payload (TRP) image by default +and uses it as the RMM image. + +SCP Boot ROM: ``SCP_BL1`` (previously ``BL0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first code to execute on the SCP and cannot be modified. +Its primary purpose is to perform the minimum initialization necessary to load +and authenticate an updateable SCP firmware image into an executable RAM +location, then hand-off control to that image. This may be performed in +conjunction with other processor firmware (for example, ``AP_BL1`` and +``AP_BL2``). + +This image was previously abbreviated as ``BL0`` but in some systems, the SCP +may directly load/authenticate its own firmware. In these systems, it doesn't +make sense to interleave the image terminology for AP and SCP; both AP and SCP +Boot ROMs are ``BL1`` from their own point of view. + +SCP RAM Firmware: ``SCP_BL2`` (previously ``BL3-0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage SCP firmware. It is currently also known as the "SCP +runtime firmware" but it could potentially be an intermediate firmware if the +SCP needs to load/authenticate multiple 3rd level images in future. + +This image was previously abbreviated as BL3-0 but from the SCP's point of view, +this has always been the 2nd stage firmware. The previous name is too +AP-centric. + +Firmware Update (FWU) Images +---------------------------- + +The terminology for these images has not been widely adopted yet but they have +to be considered in a production Trusted Board Boot solution. + +AP Firmware Update Boot ROM: ``AP_NS_BL1U`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first normal world code to execute on the AP during a +firmware update operation, and cannot be modified. Its primary purpose is to +load subsequent firmware update images from an external interface and communicate +with ``AP_BL1`` to authenticate those images. + +During firmware update, there are (potentially) multiple transitions between the +secure and normal world. The "level" of the BL image is relative to the world +it's in so it makes sense to encode "NS" in the normal world images. The absence +of "NS" implies a secure world image. + +AP Firmware Update Config: ``AP_BL2U`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This image does the minimum necessary AP secure world configuration required to +complete the firmware update operation. It is potentially a subset of ``AP_BL2`` +functionality. + +SCP Firmware Update Config: ``SCP_BL2U`` (previously ``BL2-U0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This image does the minimum necessary SCP secure world configuration required to +complete the firmware update operation. It is potentially a subset of +``SCP_BL2`` functionality. + +AP Firmware Updater: ``AP_NS_BL2U`` (previously ``BL3-U``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage AP normal world firmware updater. Its primary purpose is +to load a new set of firmware images from an external interface and write them +into non-volatile storage. + +Other Processor Firmware Images +------------------------------- + +Some systems may have additional processors to the AP and SCP. For example, a +Management Control Processor (MCP). Images for these processors should follow +the same terminology, with the processor abbreviation prefix, followed by +underscore and the level of the firmware image. + +For example, + +MCP Boot ROM: ``MCP_BL1`` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +MCP RAM Firmware: ``MCP_BL2`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/arm-trusted-firmware/docs/getting_started/index.rst b/arm-trusted-firmware/docs/getting_started/index.rst new file mode 100644 index 0000000..817beaf --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/index.rst @@ -0,0 +1,21 @@ +Getting Started +=============== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + prerequisites + docs-build + tools-build + initial-build + build-options + image-terminology + porting-guide + psci-lib-integration-guide + rt-svc-writers-guide + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/getting_started/initial-build.rst b/arm-trusted-firmware/docs/getting_started/initial-build.rst new file mode 100644 index 0000000..d4a8f01 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/initial-build.rst @@ -0,0 +1,118 @@ +Performing an Initial Build +=========================== + +- Before building TF-A, the environment variable ``CROSS_COMPILE`` must point + to the Linaro cross compiler. + + For AArch64: + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + + For AArch32: + + .. code:: shell + + export CROSS_COMPILE=/bin/arm-none-eabi- + + It is possible to build TF-A using Clang or Arm Compiler 6. To do so + ``CC`` needs to point to the clang or armclang binary, which will + also select the clang or armclang assembler. Be aware that for Arm Compiler, + the GNU linker is used by default. However for Clang LLVM linker (LLD) + is used by default. In case of being needed the linker can be overridden + using the ``LD`` variable. LLVM linker (LLD) version 9 is + known to work with TF-A. + + In both cases ``CROSS_COMPILE`` should be set as described above. + + Arm Compiler 6 will be selected when the base name of the path assigned + to ``CC`` matches the string 'armclang'. + + For AArch64 using Arm Compiler 6: + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + make CC=/bin/armclang PLAT= all + + Clang will be selected when the base name of the path assigned to ``CC`` + contains the string 'clang'. This is to allow both clang and clang-X.Y + to work. + + For AArch64 using clang: + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + make CC=/bin/clang PLAT= all + +- Change to the root directory of the TF-A source tree and build. + + For AArch64: + + .. code:: shell + + make PLAT= all + + For AArch32: + + .. code:: shell + + make PLAT= ARCH=aarch32 AARCH32_SP=sp_min all + + Notes: + + - If ``PLAT`` is not specified, ``fvp`` is assumed by default. See the + :ref:`Build Options` document for more information on available build + options. + + - (AArch32 only) Currently only ``PLAT=fvp`` is supported. + + - (AArch32 only) ``AARCH32_SP`` is the AArch32 EL3 Runtime Software and it + corresponds to the BL32 image. A minimal ``AARCH32_SP``, sp_min, is + provided by TF-A to demonstrate how PSCI Library can be integrated with + an AArch32 EL3 Runtime Software. Some AArch32 EL3 Runtime Software may + include other runtime services, for example Trusted OS services. A guide + to integrate PSCI library with AArch32 EL3 Runtime Software can be found + at :ref:`PSCI Library Integration guide for Armv8-A AArch32 systems`. + + - (AArch64 only) The TSP (Test Secure Payload), corresponding to the BL32 + image, is not compiled in by default. Refer to the + :ref:`Test Secure Payload (TSP) and Dispatcher (TSPD)` document for + details on building the TSP. + + - By default this produces a release version of the build. To produce a + debug version instead, refer to the "Debugging options" section below. + + - The build process creates products in a ``build`` directory tree, building + the objects and binaries for each boot loader stage in separate + sub-directories. The following boot loader binary files are created + from the corresponding ELF files: + + - ``build///bl1.bin`` + - ``build///bl2.bin`` + - ``build///bl31.bin`` (AArch64 only) + - ``build///bl32.bin`` (mandatory for AArch32) + + where ```` is the name of the chosen platform and ```` + is either ``debug`` or ``release``. The actual number of images might differ + depending on the platform. + +- Build products for a specific build variant can be removed using: + + .. code:: shell + + make DEBUG= PLAT= clean + + ... where ```` is ``0`` or ``1``, as specified when building. + + The build tree can be removed completely using: + + .. code:: shell + + make realclean + +-------------- + +*Copyright (c) 2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/getting_started/porting-guide.rst b/arm-trusted-firmware/docs/getting_started/porting-guide.rst new file mode 100644 index 0000000..3d3b2e3 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/porting-guide.rst @@ -0,0 +1,3215 @@ +Porting Guide +============= + +Introduction +------------ + +Porting Trusted Firmware-A (TF-A) to a new platform involves making some +mandatory and optional modifications for both the cold and warm boot paths. +Modifications consist of: + +- Implementing a platform-specific function or variable, +- Setting up the execution context in a certain way, or +- Defining certain constants (for example #defines). + +The platform-specific functions and variables are declared in +``include/plat/common/platform.h``. The firmware provides a default +implementation of variables and functions to fulfill the optional requirements. +These implementations are all weakly defined; they are provided to ease the +porting effort. Each platform port can override them with its own implementation +if the default implementation is inadequate. + +Some modifications are common to all Boot Loader (BL) stages. Section 2 +discusses these in detail. The subsequent sections discuss the remaining +modifications for each BL stage in detail. + +Please refer to the :ref:`Platform Compatibility Policy` for the policy +regarding compatibility and deprecation of these porting interfaces. + +Only Arm development platforms (such as FVP and Juno) may use the +functions/definitions in ``include/plat/arm/common/`` and the corresponding +source files in ``plat/arm/common/``. This is done so that there are no +dependencies between platforms maintained by different people/companies. If you +want to use any of the functionality present in ``plat/arm`` files, please +create a pull request that moves the code to ``plat/common`` so that it can be +discussed. + +Common modifications +-------------------- + +This section covers the modifications that should be made by the platform for +each BL stage to correctly port the firmware stack. They are categorized as +either mandatory or optional. + +Common mandatory modifications +------------------------------ + +A platform port must enable the Memory Management Unit (MMU) as well as the +instruction and data caches for each BL stage. Setting up the translation +tables is the responsibility of the platform port because memory maps differ +across platforms. A memory translation library (see ``lib/xlat_tables/``) is +provided to help in this setup. + +Note that although this library supports non-identity mappings, this is intended +only for re-mapping peripheral physical addresses and allows platforms with high +I/O addresses to reduce their virtual address space. All other addresses +corresponding to code and data must currently use an identity mapping. + +Also, the only translation granule size supported in TF-A is 4KB, as various +parts of the code assume that is the case. It is not possible to switch to +16 KB or 64 KB granule sizes at the moment. + +In Arm standard platforms, each BL stage configures the MMU in the +platform-specific architecture setup function, ``blX_plat_arch_setup()``, and uses +an identity mapping for all addresses. + +If the build option ``USE_COHERENT_MEM`` is enabled, each platform can allocate a +block of identity mapped secure memory with Device-nGnRE attributes aligned to +page boundary (4K) for each BL stage. All sections which allocate coherent +memory are grouped under ``coherent_ram``. For ex: Bakery locks are placed in a +section identified by name ``bakery_lock`` inside ``coherent_ram`` so that its +possible for the firmware to place variables in it using the following C code +directive: + +:: + + __section("bakery_lock") + +Or alternatively the following assembler code directive: + +:: + + .section bakery_lock + +The ``coherent_ram`` section is a sum of all sections like ``bakery_lock`` which are +used to allocate any data structures that are accessed both when a CPU is +executing with its MMU and caches enabled, and when it's running with its MMU +and caches disabled. Examples are given below. + +The following variables, functions and constants must be defined by the platform +for the firmware to work correctly. + +File : platform_def.h [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each platform must ensure that a header file of this name is in the system +include path with the following constants defined. This will require updating +the list of ``PLAT_INCLUDES`` in the ``platform.mk`` file. + +Platform ports may optionally use the file ``include/plat/common/common_def.h``, +which provides typical values for some of the constants below. These values are +likely to be suitable for all platform ports. + +- **#define : PLATFORM_LINKER_FORMAT** + + Defines the linker format used by the platform, for example + ``elf64-littleaarch64``. + +- **#define : PLATFORM_LINKER_ARCH** + + Defines the processor architecture for the linker by the platform, for + example ``aarch64``. + +- **#define : PLATFORM_STACK_SIZE** + + Defines the normal stack memory available to each CPU. This constant is used + by ``plat/common/aarch64/platform_mp_stack.S`` and + ``plat/common/aarch64/platform_up_stack.S``. + +- **#define : CACHE_WRITEBACK_GRANULE** + + Defines the size in bits of the largest cache line across all the cache + levels in the platform. + +- **#define : FIRMWARE_WELCOME_STR** + + Defines the character string printed by BL1 upon entry into the ``bl1_main()`` + function. + +- **#define : PLATFORM_CORE_COUNT** + + Defines the total number of CPUs implemented by the platform across all + clusters in the system. + +- **#define : PLAT_NUM_PWR_DOMAINS** + + Defines the total number of nodes in the power domain topology + tree at all the power domain levels used by the platform. + This macro is used by the PSCI implementation to allocate + data structures to represent power domain topology. + +- **#define : PLAT_MAX_PWR_LVL** + + Defines the maximum power domain level that the power management operations + should apply to. More often, but not always, the power domain level + corresponds to affinity level. This macro allows the PSCI implementation + to know the highest power domain level that it should consider for power + management operations in the system that the platform implements. For + example, the Base AEM FVP implements two clusters with a configurable + number of CPUs and it reports the maximum power domain level as 1. + +- **#define : PLAT_MAX_OFF_STATE** + + Defines the local power state corresponding to the deepest power down + possible at every power domain level in the platform. The local power + states for each level may be sparsely allocated between 0 and this value + with 0 being reserved for the RUN state. The PSCI implementation uses this + value to initialize the local power states of the power domain nodes and + to specify the requested power state for a PSCI_CPU_OFF call. + +- **#define : PLAT_MAX_RET_STATE** + + Defines the local power state corresponding to the deepest retention state + possible at every power domain level in the platform. This macro should be + a value less than PLAT_MAX_OFF_STATE and greater than 0. It is used by the + PSCI implementation to distinguish between retention and power down local + power states within PSCI_CPU_SUSPEND call. + +- **#define : PLAT_MAX_PWR_LVL_STATES** + + Defines the maximum number of local power states per power domain level + that the platform supports. The default value of this macro is 2 since + most platforms just support a maximum of two local power states at each + power domain level (power-down and retention). If the platform needs to + account for more local power states, then it must redefine this macro. + + Currently, this macro is used by the Generic PSCI implementation to size + the array used for PSCI_STAT_COUNT/RESIDENCY accounting. + +- **#define : BL1_RO_BASE** + + Defines the base address in secure ROM where BL1 originally lives. Must be + aligned on a page-size boundary. + +- **#define : BL1_RO_LIMIT** + + Defines the maximum address in secure ROM that BL1's actual content (i.e. + excluding any data section allocated at runtime) can occupy. + +- **#define : BL1_RW_BASE** + + Defines the base address in secure RAM where BL1's read-write data will live + at runtime. Must be aligned on a page-size boundary. + +- **#define : BL1_RW_LIMIT** + + Defines the maximum address in secure RAM that BL1's read-write data can + occupy at runtime. + +- **#define : BL2_BASE** + + Defines the base address in secure RAM where BL1 loads the BL2 binary image. + Must be aligned on a page-size boundary. This constant is not applicable + when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_LIMIT** + + Defines the maximum address in secure RAM that the BL2 image can occupy. + This constant is not applicable when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RO_BASE** + + Defines the base address in secure XIP memory where BL2 RO section originally + lives. Must be aligned on a page-size boundary. This constant is only needed + when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RO_LIMIT** + + Defines the maximum address in secure XIP memory that BL2's actual content + (i.e. excluding any data section allocated at runtime) can occupy. This + constant is only needed when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RW_BASE** + + Defines the base address in secure RAM where BL2's read-write data will live + at runtime. Must be aligned on a page-size boundary. This constant is only + needed when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RW_LIMIT** + + Defines the maximum address in secure RAM that BL2's read-write data can + occupy at runtime. This constant is only needed when BL2_IN_XIP_MEM is set + to '1'. + +- **#define : BL31_BASE** + + Defines the base address in secure RAM where BL2 loads the BL31 binary + image. Must be aligned on a page-size boundary. + +- **#define : BL31_LIMIT** + + Defines the maximum address in secure RAM that the BL31 image can occupy. + +For every image, the platform must define individual identifiers that will be +used by BL1 or BL2 to load the corresponding image into memory from non-volatile +storage. For the sake of performance, integer numbers will be used as +identifiers. The platform will use those identifiers to return the relevant +information about the image to be loaded (file handler, load address, +authentication information, etc.). The following image identifiers are +mandatory: + +- **#define : BL2_IMAGE_ID** + + BL2 image identifier, used by BL1 to load BL2. + +- **#define : BL31_IMAGE_ID** + + BL31 image identifier, used by BL2 to load BL31. + +- **#define : BL33_IMAGE_ID** + + BL33 image identifier, used by BL2 to load BL33. + +If Trusted Board Boot is enabled, the following certificate identifiers must +also be defined: + +- **#define : TRUSTED_BOOT_FW_CERT_ID** + + BL2 content certificate identifier, used by BL1 to load the BL2 content + certificate. + +- **#define : TRUSTED_KEY_CERT_ID** + + Trusted key certificate identifier, used by BL2 to load the trusted key + certificate. + +- **#define : SOC_FW_KEY_CERT_ID** + + BL31 key certificate identifier, used by BL2 to load the BL31 key + certificate. + +- **#define : SOC_FW_CONTENT_CERT_ID** + + BL31 content certificate identifier, used by BL2 to load the BL31 content + certificate. + +- **#define : NON_TRUSTED_FW_KEY_CERT_ID** + + BL33 key certificate identifier, used by BL2 to load the BL33 key + certificate. + +- **#define : NON_TRUSTED_FW_CONTENT_CERT_ID** + + BL33 content certificate identifier, used by BL2 to load the BL33 content + certificate. + +- **#define : FWU_CERT_ID** + + Firmware Update (FWU) certificate identifier, used by NS_BL1U to load the + FWU content certificate. + +- **#define : PLAT_CRYPTOCELL_BASE** + + This defines the base address of Arm® TrustZone® CryptoCell and must be + defined if CryptoCell crypto driver is used for Trusted Board Boot. For + capable Arm platforms, this driver is used if ``ARM_CRYPTOCELL_INTEG`` is + set. + +If the AP Firmware Updater Configuration image, BL2U is used, the following +must also be defined: + +- **#define : BL2U_BASE** + + Defines the base address in secure memory where BL1 copies the BL2U binary + image. Must be aligned on a page-size boundary. + +- **#define : BL2U_LIMIT** + + Defines the maximum address in secure memory that the BL2U image can occupy. + +- **#define : BL2U_IMAGE_ID** + + BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to BL2U. + +If the SCP Firmware Update Configuration Image, SCP_BL2U is used, the following +must also be defined: + +- **#define : SCP_BL2U_IMAGE_ID** + + SCP_BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to SCP_BL2U. + + .. note:: + TF-A does not provide source code for this image. + +If the Non-Secure Firmware Updater ROM, NS_BL1U is used, the following must +also be defined: + +- **#define : NS_BL1U_BASE** + + Defines the base address in non-secure ROM where NS_BL1U executes. + Must be aligned on a page-size boundary. + + .. note:: + TF-A does not provide source code for this image. + +- **#define : NS_BL1U_IMAGE_ID** + + NS_BL1U image identifier, used by BL1 to fetch an image descriptor + corresponding to NS_BL1U. + +If the Non-Secure Firmware Updater, NS_BL2U is used, the following must also +be defined: + +- **#define : NS_BL2U_BASE** + + Defines the base address in non-secure memory where NS_BL2U executes. + Must be aligned on a page-size boundary. + + .. note:: + TF-A does not provide source code for this image. + +- **#define : NS_BL2U_IMAGE_ID** + + NS_BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to NS_BL2U. + +For the the Firmware update capability of TRUSTED BOARD BOOT, the following +macros may also be defined: + +- **#define : PLAT_FWU_MAX_SIMULTANEOUS_IMAGES** + + Total number of images that can be loaded simultaneously. If the platform + doesn't specify any value, it defaults to 10. + +If a SCP_BL2 image is supported by the platform, the following constants must +also be defined: + +- **#define : SCP_BL2_IMAGE_ID** + + SCP_BL2 image identifier, used by BL2 to load SCP_BL2 into secure memory + from platform storage before being transferred to the SCP. + +- **#define : SCP_FW_KEY_CERT_ID** + + SCP_BL2 key certificate identifier, used by BL2 to load the SCP_BL2 key + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : SCP_FW_CONTENT_CERT_ID** + + SCP_BL2 content certificate identifier, used by BL2 to load the SCP_BL2 + content certificate (mandatory when Trusted Board Boot is enabled). + +If a BL32 image is supported by the platform, the following constants must +also be defined: + +- **#define : BL32_IMAGE_ID** + + BL32 image identifier, used by BL2 to load BL32. + +- **#define : TRUSTED_OS_FW_KEY_CERT_ID** + + BL32 key certificate identifier, used by BL2 to load the BL32 key + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : TRUSTED_OS_FW_CONTENT_CERT_ID** + + BL32 content certificate identifier, used by BL2 to load the BL32 content + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : BL32_BASE** + + Defines the base address in secure memory where BL2 loads the BL32 binary + image. Must be aligned on a page-size boundary. + +- **#define : BL32_LIMIT** + + Defines the maximum address that the BL32 image can occupy. + +If the Test Secure-EL1 Payload (TSP) instantiation of BL32 is supported by the +platform, the following constants must also be defined: + +- **#define : TSP_SEC_MEM_BASE** + + Defines the base address of the secure memory used by the TSP image on the + platform. This must be at the same address or below ``BL32_BASE``. + +- **#define : TSP_SEC_MEM_SIZE** + + Defines the size of the secure memory used by the BL32 image on the + platform. ``TSP_SEC_MEM_BASE`` and ``TSP_SEC_MEM_SIZE`` must fully + accommodate the memory required by the BL32 image, defined by ``BL32_BASE`` + and ``BL32_LIMIT``. + +- **#define : TSP_IRQ_SEC_PHY_TIMER** + + Defines the ID of the secure physical generic timer interrupt used by the + TSP's interrupt handling code. + +If the platform port uses the translation table library code, the following +constants must also be defined: + +- **#define : PLAT_XLAT_TABLES_DYNAMIC** + + Optional flag that can be set per-image to enable the dynamic allocation of + regions even when the MMU is enabled. If not defined, only static + functionality will be available, if defined and set to 1 it will also + include the dynamic functionality. + +- **#define : MAX_XLAT_TABLES** + + Defines the maximum number of translation tables that are allocated by the + translation table library code. To minimize the amount of runtime memory + used, choose the smallest value needed to map the required virtual addresses + for each BL stage. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is enabled for a BL + image, ``MAX_XLAT_TABLES`` must be defined to accommodate the dynamic regions + as well. + +- **#define : MAX_MMAP_REGIONS** + + Defines the maximum number of regions that are allocated by the translation + table library code. A region consists of physical base address, virtual base + address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as + defined in the ``mmap_region_t`` structure. The platform defines the regions + that should be mapped. Then, the translation table library will create the + corresponding tables and descriptors at runtime. To minimize the amount of + runtime memory used, choose the smallest value needed to register the + required regions for each BL stage. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is + enabled for a BL image, ``MAX_MMAP_REGIONS`` must be defined to accommodate + the dynamic regions as well. + +- **#define : PLAT_VIRT_ADDR_SPACE_SIZE** + + Defines the total size of the virtual address space in bytes. For example, + for a 32 bit virtual address space, this value should be ``(1ULL << 32)``. + +- **#define : PLAT_PHY_ADDR_SPACE_SIZE** + + Defines the total size of the physical address space in bytes. For example, + for a 32 bit physical address space, this value should be ``(1ULL << 32)``. + +If the platform port uses the IO storage framework, the following constants +must also be defined: + +- **#define : MAX_IO_DEVICES** + + Defines the maximum number of registered IO devices. Attempting to register + more devices than this value using ``io_register_device()`` will fail with + -ENOMEM. + +- **#define : MAX_IO_HANDLES** + + Defines the maximum number of open IO handles. Attempting to open more IO + entities than this value using ``io_open()`` will fail with -ENOMEM. + +- **#define : MAX_IO_BLOCK_DEVICES** + + Defines the maximum number of registered IO block devices. Attempting to + register more devices this value using ``io_dev_open()`` will fail + with -ENOMEM. MAX_IO_BLOCK_DEVICES should be less than MAX_IO_DEVICES. + With this macro, multiple block devices could be supported at the same + time. + +If the platform needs to allocate data within the per-cpu data framework in +BL31, it should define the following macro. Currently this is only required if +the platform decides not to use the coherent memory section by undefining the +``USE_COHERENT_MEM`` build flag. In this case, the framework allocates the +required memory within the the per-cpu data to minimize wastage. + +- **#define : PLAT_PCPU_DATA_SIZE** + + Defines the memory (in bytes) to be reserved within the per-cpu data + structure for use by the platform layer. + +The following constants are optional. They should be defined when the platform +memory layout implies some image overlaying like in Arm standard platforms. + +- **#define : BL31_PROGBITS_LIMIT** + + Defines the maximum address in secure RAM that the BL31's progbits sections + can occupy. + +- **#define : TSP_PROGBITS_LIMIT** + + Defines the maximum address that the TSP's progbits sections can occupy. + +If the platform port uses the PL061 GPIO driver, the following constant may +optionally be defined: + +- **PLAT_PL061_MAX_GPIOS** + Maximum number of GPIOs required by the platform. This allows control how + much memory is allocated for PL061 GPIO controllers. The default value is + + #. $(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) + +If the platform port uses the partition driver, the following constant may +optionally be defined: + +- **PLAT_PARTITION_MAX_ENTRIES** + Maximum number of partition entries required by the platform. This allows + control how much memory is allocated for partition entries. The default + value is 128. + For example, define the build flag in ``platform.mk``: + PLAT_PARTITION_MAX_ENTRIES := 12 + $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) + +- **PLAT_PARTITION_BLOCK_SIZE** + The size of partition block. It could be either 512 bytes or 4096 bytes. + The default value is 512. + For example, define the build flag in ``platform.mk``: + PLAT_PARTITION_BLOCK_SIZE := 4096 + $(eval $(call add_define,PLAT_PARTITION_BLOCK_SIZE)) + +The following constant is optional. It should be defined to override the default +behaviour of the ``assert()`` function (for example, to save memory). + +- **PLAT_LOG_LEVEL_ASSERT** + If ``PLAT_LOG_LEVEL_ASSERT`` is higher or equal than ``LOG_LEVEL_VERBOSE``, + ``assert()`` prints the name of the file, the line number and the asserted + expression. Else if it is higher than ``LOG_LEVEL_INFO``, it prints the file + name and the line number. Else if it is lower than ``LOG_LEVEL_INFO``, it + doesn't print anything to the console. If ``PLAT_LOG_LEVEL_ASSERT`` isn't + defined, it defaults to ``LOG_LEVEL``. + +File : plat_macros.S [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each platform must ensure a file of this name is in the system include path with +the following macro defined. In the Arm development platforms, this file is +found in ``plat/arm/board//include/plat_macros.S``. + +- **Macro : plat_crash_print_regs** + + This macro allows the crash reporting routine to print relevant platform + registers in case of an unhandled exception in BL31. This aids in debugging + and this macro can be defined to be empty in case register reporting is not + desired. + + For instance, GIC or interconnect registers may be helpful for + troubleshooting. + +Handling Reset +-------------- + +BL1 by default implements the reset vector where execution starts from a cold +or warm boot. BL31 can be optionally set as a reset vector using the +``RESET_TO_BL31`` make variable. + +For each CPU, the reset vector code is responsible for the following tasks: + +#. Distinguishing between a cold boot and a warm boot. + +#. In the case of a cold boot and the CPU being a secondary CPU, ensuring that + the CPU is placed in a platform-specific state until the primary CPU + performs the necessary steps to remove it from this state. + +#. In the case of a warm boot, ensuring that the CPU jumps to a platform- + specific address in the BL31 image in the same processor mode as it was + when released from reset. + +The following functions need to be implemented by the platform port to enable +reset vector code to perform the above tasks. + +Function : plat_get_my_entrypoint() [mandatory when PROGRAMMABLE_RESET_ADDRESS == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +This function is called with the MMU and caches disabled +(``SCTLR_EL3.M`` = 0 and ``SCTLR_EL3.C`` = 0). The function is responsible for +distinguishing between a warm and cold reset for the current CPU using +platform-specific means. If it's a warm reset, then it returns the warm +reset entrypoint point provided to ``plat_setup_psci_ops()`` during +BL31 initialization. If it's a cold reset then this function must return zero. + +This function does not follow the Procedure Call Standard used by the +Application Binary Interface for the Arm 64-bit architecture. The caller should +not assume that callee saved registers are preserved across a call to this +function. + +This function fulfills requirement 1 and 3 listed above. + +Note that for platforms that support programming the reset address, it is +expected that a CPU will start executing code directly at the right address, +both on a cold and warm reset. In this case, there is no need to identify the +type of reset nor to query the warm reset entrypoint. Therefore, implementing +this function is not required on such platforms. + +Function : plat_secondary_cold_boot_setup() [mandatory when COLD_BOOT_SINGLE_CPU == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + +This function is called with the MMU and data caches disabled. It is responsible +for placing the executing secondary CPU in a platform-specific state until the +primary CPU performs the necessary actions to bring it out of that state and +allow entry into the OS. This function must not return. + +In the Arm FVP port, when using the normal boot flow, each secondary CPU powers +itself off. The primary CPU is responsible for powering up the secondary CPUs +when normal world software requires them. When booting an EL3 payload instead, +they stay powered on and are put in a holding pen until their mailbox gets +populated. + +This function fulfills requirement 2 above. + +Note that for platforms that can't release secondary CPUs out of reset, only the +primary CPU will execute the cold boot code. Therefore, implementing this +function is not required on such platforms. + +Function : plat_is_my_cpu_primary() [mandatory when COLD_BOOT_SINGLE_CPU == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function identifies whether the current CPU is the primary CPU or a +secondary CPU. A return value of zero indicates that the CPU is not the +primary CPU, while a non-zero return value indicates that the CPU is the +primary CPU. + +Note that for platforms that can't release secondary CPUs out of reset, only the +primary CPU will execute the cold boot code. Therefore, there is no need to +distinguish between primary and secondary CPUs and implementing this function is +not required. + +Function : platform_mem_init() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function is called before any access to data is made by the firmware, in +order to carry out any essential memory initialization. + +Function: plat_get_rotpk_info() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, void **, unsigned int *, unsigned int * + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It returns a +pointer to the ROTPK stored in the platform (or a hash of it) and its length. +The ROTPK must be encoded in DER format according to the following ASN.1 +structure: + +:: + + AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL + } + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING + } + +In case the function returns a hash of the key: + +:: + + DigestInfo ::= SEQUENCE { + digestAlgorithm AlgorithmIdentifier, + digest OCTET STRING + } + +The function returns 0 on success. Any other value is treated as error by the +Trusted Board Boot. The function also reports extra information related +to the ROTPK in the flags parameter: + +:: + + ROTPK_IS_HASH : Indicates that the ROTPK returned by the platform is a + hash. + ROTPK_NOT_DEPLOYED : This allows the platform to skip certificate ROTPK + verification while the platform ROTPK is not deployed. + When this flag is set, the function does not need to + return a platform ROTPK, and the authentication + framework uses the ROTPK in the certificate without + verifying it against the platform value. This flag + must not be used in a deployed production environment. + +Function: plat_get_nv_ctr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, unsigned int * + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It returns the +non-volatile counter value stored in the platform in the second argument. The +cookie in the first argument may be used to select the counter in case the +platform provides more than one (for example, on platforms that use the default +TBBR CoT, the cookie will correspond to the OID values defined in +TRUSTED_FW_NVCOUNTER_OID or NON_TRUSTED_FW_NVCOUNTER_OID). + +The function returns 0 on success. Any other value means the counter value could +not be retrieved from the platform. + +Function: plat_set_nv_ctr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, unsigned int + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It sets a new +counter value in the platform. The cookie in the first argument may be used to +select the counter (as explained in plat_get_nv_ctr()). The second argument is +the updated counter value to be written to the NV counter. + +The function returns 0 on success. Any other value means the counter value could +not be updated. + +Function: plat_set_nv_ctr2() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, const auth_img_desc_t *, unsigned int + Return : int + +This function is optional when Trusted Board Boot is enabled. If this +interface is defined, then ``plat_set_nv_ctr()`` need not be defined. The +first argument passed is a cookie and is typically used to +differentiate between a Non Trusted NV Counter and a Trusted NV +Counter. The second argument is a pointer to an authentication image +descriptor and may be used to decide if the counter is allowed to be +updated or not. The third argument is the updated counter value to +be written to the NV counter. + +The function returns 0 on success. Any other value means the counter value +either could not be updated or the authentication image descriptor indicates +that it is not allowed to be updated. + +Common mandatory function modifications +--------------------------------------- + +The following functions are mandatory functions which need to be implemented +by the platform port. + +Function : plat_my_core_pos() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function returns the index of the calling CPU which is used as a +CPU-specific linear index into blocks of memory (for example while allocating +per-CPU stacks). This function will be invoked very early in the +initialization sequence which mandates that this function should be +implemented in assembly and should not rely on the availability of a C +runtime environment. This function can clobber x0 - x8 and must preserve +x9 - x29. + +This function plays a crucial role in the power domain topology framework in +PSCI and details of this can be found in +:ref:`PSCI Power Domain Tree Structure`. + +Function : plat_core_pos_by_mpidr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t + Return : int + +This function validates the ``MPIDR`` of a CPU and converts it to an index, +which can be used as a CPU-specific linear index into blocks of memory. In +case the ``MPIDR`` is invalid, this function returns -1. This function will only +be invoked by BL31 after the power domain topology is initialized and can +utilize the C runtime environment. For further details about how TF-A +represents the power domain topology and how this relates to the linear CPU +index, please refer :ref:`PSCI Power Domain Tree Structure`. + +Function : plat_get_mbedtls_heap() [when TRUSTED_BOARD_BOOT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments : void **heap_addr, size_t *heap_size + Return : int + +This function is invoked during Mbed TLS library initialisation to get a heap, +by means of a starting address and a size. This heap will then be used +internally by the Mbed TLS library. Hence, each BL stage that utilises Mbed TLS +must be able to provide a heap to it. + +A helper function can be found in `drivers/auth/mbedtls/mbedtls_common.c` in +which a heap is statically reserved during compile time inside every image +(i.e. every BL stage) that utilises Mbed TLS. In this default implementation, +the function simply returns the address and size of this "pre-allocated" heap. +For a platform to use this default implementation, only a call to the helper +from inside plat_get_mbedtls_heap() body is enough and nothing else is needed. + +However, by writting their own implementation, platforms have the potential to +optimise memory usage. For example, on some Arm platforms, the Mbed TLS heap is +shared between BL1 and BL2 stages and, thus, the necessary space is not reserved +twice. + +On success the function should return 0 and a negative error code otherwise. + +Function : plat_get_enc_key_info() [when FW_ENC_STATUS == 0 or 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments : 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 + Return : int + +This function provides a symmetric key (either SSK or BSSK depending on +fw_enc_status) which is invoked during runtime decryption of encrypted +firmware images. `plat/common/plat_bl_common.c` provides a dummy weak +implementation for testing purposes which must be overridden by the platform +trying to implement a real world firmware encryption use-case. + +It also allows the platform to pass symmetric key identifier rather than +actual symmetric key which is useful in cases where the crypto backend provides +secure storage for the symmetric key. So in this case ``ENC_KEY_IS_IDENTIFIER`` +flag must be set in ``flags``. + +In addition to above a platform may also choose to provide an image specific +symmetric key/identifier using img_id. + +On success the function should return 0 and a negative error code otherwise. + +Note that this API depends on ``DECRYPTION_SUPPORT`` build flag. + +Function : plat_fwu_set_images_source() [when PSA_FWU_SUPPORT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const struct fwu_metadata *metadata + Return : void + +This function is mandatory when PSA_FWU_SUPPORT is enabled. +It provides a means to retrieve image specification (offset in +non-volatile storage and length) of active/updated images using the passed +FWU metadata, and update I/O policies of active/updated images using retrieved +image specification information. +Further I/O layer operations such as I/O open, I/O read, etc. on these +images rely on this function call. + +In Arm platforms, this function is used to set an I/O policy of the FIP image, +container of all active/updated secure and non-secure images. + +Function : plat_fwu_set_metadata_image_source() [when PSA_FWU_SUPPORT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec + Return : int + +This function is mandatory when PSA_FWU_SUPPORT is enabled. It is +responsible for setting up the platform I/O policy of the requested metadata +image (either FWU_METADATA_IMAGE_ID or BKUP_FWU_METADATA_IMAGE_ID) that will +be used to load this image from the platform's non-volatile storage. + +FWU metadata can not be always stored as a raw image in non-volatile storage +to define its image specification (offset in non-volatile storage and length) +statically in I/O policy. +For example, the FWU metadata image is stored as a partition inside the GUID +partition table image. Its specification is defined in the partition table +that needs to be parsed dynamically. +This function provides a means to retrieve such dynamic information to set +the I/O policy of the FWU metadata image. +Further I/O layer operations such as I/O open, I/O read, etc. on FWU metadata +image relies on this function call. + +It returns '0' on success, otherwise a negative error value on error. +Alongside, returns device handle and image specification from the I/O policy +of the requested FWU metadata image. + +Function : plat_fwu_get_boot_idx() [when PSA_FWU_SUPPORT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This function is mandatory when PSA_FWU_SUPPORT is enabled. It provides the +means to retrieve the boot index value from the platform. The boot index is the +bank from which the platform has booted the firmware images. + +By default, the platform will read the metadata structure and try to boot from +the active bank. If the platform fails to boot from the active bank due to +reasons like an Authentication failure, or on crossing a set number of watchdog +resets while booting from the active bank, the platform can then switch to boot +from a different bank. This function then returns the bank that the platform +should boot its images from. + +Common optional modifications +----------------------------- + +The following are helper functions implemented by the firmware that perform +common platform-specific tasks. A platform may choose to override these +definitions. + +Function : plat_set_my_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function sets the current stack pointer to the normal memory stack that +has been allocated for the current CPU. For BL images that only require a +stack for the primary CPU, the UP version of the function is used. The size +of the stack allocated to each CPU is specified by the platform defined +constant ``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in ``plat/common/aarch64/platform_up_stack.S`` and +``plat/common/aarch64/platform_mp_stack.S`` + +Function : plat_get_my_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +This function returns the base address of the normal memory stack that +has been allocated for the current CPU. For BL images that only require a +stack for the primary CPU, the UP version of the function is used. The size +of the stack allocated to each CPU is specified by the platform defined +constant ``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in ``plat/common/aarch64/platform_up_stack.S`` and +``plat/common/aarch64/platform_mp_stack.S`` + +Function : plat_report_exception() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +A platform may need to report various information about its status when an +exception is taken, for example the current exception level, the CPU security +state (secure/non-secure), the exception type, and so on. This function is +called in the following circumstances: + +- In BL1, whenever an exception is taken. +- In BL2, whenever an exception is taken. + +The default implementation doesn't do anything, to avoid making assumptions +about the way the platform displays its status information. + +For AArch64, this function receives the exception type as its argument. +Possible values for exceptions types are listed in the +``include/common/bl_common.h`` header file. Note that these constants are not +related to any architectural exception code; they are just a TF-A convention. + +For AArch32, this function receives the exception mode as its argument. +Possible values for exception modes are listed in the +``include/lib/aarch32/arch.h`` header file. + +Function : plat_reset_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +A platform may need to do additional initialization after reset. This function +allows the platform to do the platform specific initializations. Platform +specific errata workarounds could also be implemented here. The API should +preserve the values of callee saved registers x19 to x29. + +The default implementation doesn't do anything. If a platform needs to override +the default implementation, refer to the :ref:`Firmware Design` for general +guidelines. + +Function : plat_disable_acp() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API allows a platform to disable the Accelerator Coherency Port (if +present) during a cluster power down sequence. The default weak implementation +doesn't do anything. Since this API is called during the power down sequence, +it has restrictions for stack usage and it can use the registers x0 - x17 as +scratch registers. It should preserve the value in x18 register as it is used +by the caller to store the return address. + +Function : plat_error_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Return : void + +This API is called when the generic code encounters an error situation from +which it cannot continue. It allows the platform to perform error reporting or +recovery actions (for example, reset the system). This function must not return. + +The parameter indicates the type of error using standard codes from ``errno.h``. +Possible errors reported by the generic code are: + +- ``-EAUTH``: a certificate or image could not be authenticated (when Trusted + Board Boot is enabled) +- ``-ENOENT``: the requested image or certificate could not be found or an IO + error was detected +- ``-ENOMEM``: resources exhausted. TF-A does not use dynamic memory, so this + error is usually an indication of an incorrect array size + +The default implementation simply spins. + +Function : plat_panic_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API is called when the generic code encounters an unexpected error +situation from which it cannot recover. This function must not return, +and must be implemented in assembly because it may be called before the C +environment is initialized. + +.. note:: + The address from where it was called is stored in x30 (Link Register). + The default implementation simply spins. + +Function : plat_get_bl_image_load_info() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl_load_info_t * + +This function returns pointer to the list of images that the platform has +populated to load. This function is invoked in BL2 to load the +BL3xx images. + +Function : plat_get_next_bl_params() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl_params_t * + +This function returns a pointer to the shared memory that the platform has +kept aside to pass TF-A related information that next BL image needs. This +function is invoked in BL2 to pass this information to the next BL +image. + +Function : plat_get_stack_protector_canary() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : u_register_t + +This function returns a random value that is used to initialize the canary used +when the stack protector is enabled with ENABLE_STACK_PROTECTOR. A predictable +value will weaken the protection as the attacker could easily write the right +value as part of the attack most of the time. Therefore, it should return a +true random number. + +.. warning:: + For the protection to be effective, the global data need to be placed at + a lower address than the stack bases. Failure to do so would allow an + attacker to overwrite the canary as part of the stack buffer overflow attack. + +Function : plat_flush_next_bl_params() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function flushes to main memory all the image params that are passed to +next image. This function is invoked in BL2 to flush this information +to the next BL image. + +Function : plat_log_get_prefix() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : const char * + +This function defines the prefix string corresponding to the `log_level` to be +prepended to all the log output from TF-A. The `log_level` (argument) will +correspond to one of the standard log levels defined in debug.h. The platform +can override the common implementation to define a different prefix string for +the log output. The implementation should be robust to future changes that +increase the number of log levels. + +Function : plat_get_soc_version() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int32_t + +This function returns soc version which mainly consist of below fields + +:: + + soc_version[30:24] = JEP-106 continuation code for the SiP + soc_version[23:16] = JEP-106 identification code with parity bit for the SiP + soc_version[15:0] = Implementation defined SoC ID + +Function : plat_get_soc_revision() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int32_t + +This function returns soc revision in below format + +:: + + soc_revision[0:30] = SOC revision of specific SOC + +Function : plat_is_smccc_feature_available() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t + Return : int32_t + +This function returns SMC_ARCH_CALL_SUCCESS if the platform supports +the SMCCC function specified in the argument; otherwise returns +SMC_ARCH_CALL_NOT_SUPPORTED. + +Function : plat_mboot_measure_image() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, image_info_t * + Return : int + +When the MEASURED_BOOT flag is enabled: + +- This function measures the given image and records its measurement using + the measured boot backend driver. +- On the Arm FVP port, this function measures the given image using its + passed id and information and then records that measurement in the + Event Log buffer. +- This function must return 0 on success, a signed integer error code + otherwise. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Function : plat_mboot_measure_critical_data() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const void *, size_t + Return : int + +When the MEASURED_BOOT flag is enabled: + +- This function measures the given critical data structure and records its + measurement using the measured boot backend driver. +- This function must return 0 on success, a signed integer error code + otherwise. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Modifications specific to a Boot Loader stage +--------------------------------------------- + +Boot Loader Stage 1 (BL1) +------------------------- + +BL1 implements the reset vector where execution starts from after a cold or +warm boot. For each CPU, BL1 is responsible for the following tasks: + +#. Handling the reset as described in section 2.2 + +#. In the case of a cold boot and the CPU being the primary CPU, ensuring that + only this CPU executes the remaining BL1 code, including loading and passing + control to the BL2 stage. + +#. Identifying and starting the Firmware Update process (if required). + +#. Loading the BL2 image from non-volatile storage into secure memory at the + address specified by the platform defined constant ``BL2_BASE``. + +#. Populating a ``meminfo`` structure with the following information in memory, + accessible by BL2 immediately upon entry. + + :: + + meminfo.total_base = Base address of secure RAM visible to BL2 + meminfo.total_size = Size of secure RAM visible to BL2 + + By default, BL1 places this ``meminfo`` structure at the end of secure + memory visible to BL2. + + It is possible for the platform to decide where it wants to place the + ``meminfo`` structure for BL2 or restrict the amount of memory visible to + BL2 by overriding the weak default implementation of + ``bl1_plat_handle_post_image_load`` API. + +The following functions need to be implemented by the platform port to enable +BL1 to perform the above tasks. + +Function : bl1_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +On Arm standard platforms, this function: + +- Enables a secure instance of SP805 to act as the Trusted Watchdog. + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL1. + +- Enables issuing of snoop and DVM (Distributed Virtual Memory) requests to + the CCI slave interface corresponding to the cluster that includes the + primary CPU. + +Function : bl1_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function performs any platform-specific and architectural setup that the +platform requires. Platform-specific setup might include configuration of +memory controllers and the interconnect. + +In Arm standard platforms, this function enables the MMU. + +This function helps fulfill requirement 2 above. + +Function : bl1_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches enabled. It is responsible +for performing any remaining platform-specific setup that can occur after the +MMU and data cache have been enabled. + +if support for multiple boot sources is required, it initializes the boot +sequence used by plat_try_next_boot_source(). + +In Arm standard platforms, this function initializes the storage abstraction +layer used to load the next bootloader image. + +This function helps fulfill requirement 4 above. + +Function : bl1_plat_sec_mem_layout() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : meminfo * + +This function should only be called on the cold boot path. It executes with the +MMU and data caches enabled. The pointer returned by this function must point to +a ``meminfo`` structure containing the extents and availability of secure RAM for +the BL1 stage. + +:: + + meminfo.total_base = Base address of secure RAM visible to BL1 + meminfo.total_size = Size of secure RAM visible to BL1 + +This information is used by BL1 to load the BL2 image in secure RAM. BL1 also +populates a similar structure to tell BL2 the extents of memory available for +its own use. + +This function helps fulfill requirements 4 and 5 above. + +Function : bl1_plat_prepare_exit() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : entry_point_info_t * + Return : void + +This function is called prior to exiting BL1 in response to the +``BL1_SMC_RUN_IMAGE`` SMC request raised by BL2. It should be used to perform +platform specific clean up or bookkeeping operations before transferring +control to the next image. It receives the address of the ``entry_point_info_t`` +structure passed from BL2. This function runs with MMU disabled. + +Function : bl1_plat_set_ep_info() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, entry_point_info_t *ep_info + Return : void + +This function allows platforms to override ``ep_info`` for the given ``image_id``. + +The default implementation just returns. + +Function : bl1_plat_get_next_image_id() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This and the following function must be overridden to enable the FWU feature. + +BL1 calls this function after platform setup to identify the next image to be +loaded and executed. If the platform returns ``BL2_IMAGE_ID`` then BL1 proceeds +with the normal boot sequence, which loads and executes BL2. If the platform +returns a different image id, BL1 assumes that Firmware Update is required. + +The default implementation always returns ``BL2_IMAGE_ID``. The Arm development +platforms override this function to detect if firmware update is required, and +if so, return the first image in the firmware update process. + +Function : bl1_plat_get_image_desc() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : image_desc_t * + +BL1 calls this function to get the image descriptor information ``image_desc_t`` +for the provided ``image_id`` from the platform. + +The default implementation always returns a common BL2 image descriptor. Arm +standard platforms return an image descriptor corresponding to BL2 or one of +the firmware update images defined in the Trusted Board Boot Requirements +specification. + +Function : bl1_plat_handle_pre_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : int + +This function can be used by the platforms to update/use image information +corresponding to ``image_id``. This function is invoked in BL1, both in cold +boot and FWU code path, before loading the image. + +Function : bl1_plat_handle_post_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : int + +This function can be used by the platforms to update/use image information +corresponding to ``image_id``. This function is invoked in BL1, both in cold +boot and FWU code path, after loading and authenticating the image. + +The default weak implementation of this function calculates the amount of +Trusted SRAM that can be used by BL2 and allocates a ``meminfo_t`` +structure at the beginning of this free memory and populates it. The address +of ``meminfo_t`` structure is updated in ``arg1`` of the entrypoint +information to BL2. + +Function : bl1_plat_fwu_done() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, uintptr_t image_src, + unsigned int image_size + Return : void + +BL1 calls this function when the FWU process is complete. It must not return. +The platform may override this function to take platform specific action, for +example to initiate the normal boot flow. + +The default implementation spins forever. + +Function : bl1_plat_mem_check() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t mem_base, unsigned int mem_size, + unsigned int flags + Return : int + +BL1 calls this function while handling FWU related SMCs, more specifically when +copying or authenticating an image. Its responsibility is to ensure that the +region of memory identified by ``mem_base`` and ``mem_size`` is mapped in BL1, and +that this memory corresponds to either a secure or non-secure memory region as +indicated by the security state of the ``flags`` argument. + +This function can safely assume that the value resulting from the addition of +``mem_base`` and ``mem_size`` fits into a ``uintptr_t`` type variable and does not +overflow. + +This function must return 0 on success, a non-null error code otherwise. + +The default implementation of this function asserts therefore platforms must +override it when using the FWU feature. + +Function : bl1_plat_mboot_init() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +When the MEASURED_BOOT flag is enabled: + +- This function is used to initialize the backend driver(s) of measured boot. +- On the Arm FVP port, this function is used to initialize the Event Log + backend driver, and also to write header information in the Event Log buffer. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Function : bl1_plat_mboot_finish() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +When the MEASURED_BOOT flag is enabled: + +- This function is used to finalize the measured boot backend driver(s), + and also, set the information for the next bootloader component to + extend the measurement if needed. +- On the Arm FVP port, this function is used to pass the base address of + the Event Log buffer and its size to BL2 via tb_fw_config to extend the + Event Log buffer with the measurement of various images loaded by BL2. + It results in panic on error. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Boot Loader Stage 2 (BL2) +------------------------- + +The BL2 stage is executed only by the primary CPU, which is determined in BL1 +using the ``platform_is_primary_cpu()`` function. BL1 passed control to BL2 at +``BL2_BASE``. BL2 executes in Secure EL1 and and invokes +``plat_get_bl_image_load_info()`` to retrieve the list of images to load from +non-volatile storage to secure/non-secure RAM. After all the images are loaded +then BL2 invokes ``plat_get_next_bl_params()`` to get the list of executable +images to be passed to the next BL image. + +The following functions must be implemented by the platform port to enable BL2 +to perform the above tasks. + +Function : bl2_early_platform_setup2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. The 4 arguments are passed by BL1 to BL2 and these arguments +are platform specific. + +On Arm standard platforms, the arguments received are : + + arg0 - Points to load address of FW_CONFIG + + arg1 - ``meminfo`` structure populated by BL1. The platform copies + the contents of ``meminfo`` as it may be subsequently overwritten by BL2. + +On Arm standard platforms, this function also: + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL2. + +- Initializes the storage abstraction layer used to load further bootloader + images. It is necessary to do this early on platforms with a SCP_BL2 image, + since the later ``bl2_platform_setup`` must be done after SCP_BL2 is loaded. + +Function : bl2_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl2_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl2_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to perform any platform initialization +specific to BL2. + +In Arm standard platforms, this function performs security setup, including +configuration of the TrustZone controller to allow non-secure masters access +to most of DRAM. Part of DRAM is reserved for secure world use. + +Function : bl2_plat_handle_pre_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This function can be used by the platforms to update/use image information +for given ``image_id``. This function is currently invoked in BL2 before +loading each image. + +Function : bl2_plat_handle_post_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This function can be used by the platforms to update/use image information +for given ``image_id``. This function is currently invoked in BL2 after +loading each image. + +Function : bl2_plat_preload_setup [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This optional function performs any BL2 platform initialization +required before image loading, that is not done later in +bl2_platform_setup(). Specifically, if support for multiple +boot sources is required, it initializes the boot sequence used by +plat_try_next_boot_source(). + +Function : plat_try_next_boot_source() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This optional function passes to the next boot source in the redundancy +sequence. + +This function moves the current boot redundancy source to the next +element in the boot sequence. If there are no more boot sources then it +must return 0, otherwise it must return 1. The default implementation +of this always returns 0. + +Boot Loader Stage 2 (BL2) at EL3 +-------------------------------- + +When the platform has a non-TF-A Boot ROM it is desirable to jump +directly to BL2 instead of TF-A BL1. In this case BL2 is expected to +execute at EL3 instead of executing at EL1. Refer to the :ref:`Firmware Design` +document for more information. + +All mandatory functions of BL2 must be implemented, except the functions +bl2_early_platform_setup and bl2_el3_plat_arch_setup, because +their work is done now by bl2_el3_early_platform_setup and +bl2_el3_plat_arch_setup. These functions should generally implement +the bl1_plat_xxx() and bl2_plat_xxx() functionality combined. + + +Function : bl2_el3_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. This function receives four parameters which can be used +by the platform to pass any needed information from the Boot ROM to BL2. + +On Arm standard platforms, this function does the following: + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL2. + +- Initializes the storage abstraction layer used to load further bootloader + images. It is necessary to do this early on platforms with a SCP_BL2 image, + since the later ``bl2_platform_setup`` must be done after SCP_BL2 is loaded. + +- Initializes the private variables that define the memory layout used. + +Function : bl2_el3_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl2_el3_plat_prepare_exit() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function is called prior to exiting BL2 and run the next image. +It should be used to perform platform specific clean up or bookkeeping +operations before transferring control to the next image. This function +runs with MMU disabled. + +FWU Boot Loader Stage 2 (BL2U) +------------------------------ + +The AP Firmware Updater Configuration, BL2U, is an optional part of the FWU +process and is executed only by the primary CPU. BL1 passes control to BL2U at +``BL2U_BASE``. BL2U executes in Secure-EL1 and is responsible for: + +#. (Optional) Transferring the optional SCP_BL2U binary image from AP secure + memory to SCP RAM. BL2U uses the SCP_BL2U ``image_info`` passed by BL1. + ``SCP_BL2U_BASE`` defines the address in AP secure memory where SCP_BL2U + should be copied from. Subsequent handling of the SCP_BL2U image is + implemented by the platform specific ``bl2u_plat_handle_scp_bl2u()`` function. + If ``SCP_BL2U_BASE`` is not defined then this step is not performed. + +#. Any platform specific setup required to perform the FWU process. For + example, Arm standard platforms initialize the TZC controller so that the + normal world can access DDR memory. + +The following functions must be implemented by the platform port to enable +BL2U to perform the tasks mentioned above. + +Function : bl2u_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo *mem_info, void *plat_info + Return : void + +This function executes with the MMU and data caches disabled. It is only +called by the primary CPU. The arguments to this function is the address +of the ``meminfo`` structure and platform specific info provided by BL1. + +The platform may copy the contents of the ``mem_info`` and ``plat_info`` into +private storage as the original memory may be subsequently overwritten by BL2U. + +On Arm CSS platforms ``plat_info`` is interpreted as an ``image_info_t`` structure, +to extract SCP_BL2U image information, which is then copied into a private +variable. + +Function : bl2u_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only +called by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms, for example enabling the MMU (since the memory +map differs across platforms). + +Function : bl2u_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl2u_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to perform any platform initialization +specific to BL2U. + +In Arm standard platforms, this function performs security setup, including +configuration of the TrustZone controller to allow non-secure masters access +to most of DRAM. Part of DRAM is reserved for secure world use. + +Function : bl2u_plat_handle_scp_bl2u() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This function is used to perform any platform-specific actions required to +handle the SCP firmware. Typically it transfers the image into SCP memory using +a platform-specific protocol and waits until SCP executes it and signals to the +Application Processor (AP) for BL2U execution to continue. + +This function returns 0 on success, a negative error code otherwise. +This function is included if SCP_BL2U_BASE is defined. + +Function : bl2_plat_mboot_init() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +When the MEASURED_BOOT flag is enabled: + +- This function is used to initialize the backend driver(s) of measured boot. +- On the Arm FVP port, this function is used to initialize the Event Log + backend driver with the Event Log buffer information (base address and + size) received from BL1. It results in panic on error. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Function : bl2_plat_mboot_finish() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +When the MEASURED_BOOT flag is enabled: + +- This function is used to finalize the measured boot backend driver(s), + and also, set the information for the next bootloader component to extend + the measurement if needed. +- On the Arm FVP port, this function is used to pass the Event Log buffer + information (base address and size) to non-secure(BL33) and trusted OS(BL32) + via nt_fw and tos_fw config respectively. It results in panic on error. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Boot Loader Stage 3-1 (BL31) +---------------------------- + +During cold boot, the BL31 stage is executed only by the primary CPU. This is +determined in BL1 using the ``platform_is_primary_cpu()`` function. BL1 passes +control to BL31 at ``BL31_BASE``. During warm boot, BL31 is executed by all +CPUs. BL31 executes at EL3 and is responsible for: + +#. Re-initializing all architectural and platform state. Although BL1 performs + some of this initialization, BL31 remains resident in EL3 and must ensure + that EL3 architectural and platform state is completely initialized. It + should make no assumptions about the system state when it receives control. + +#. Passing control to a normal world BL image, pre-loaded at a platform- + specific address by BL2. On ARM platforms, BL31 uses the ``bl_params`` list + populated by BL2 in memory to do this. + +#. Providing runtime firmware services. Currently, BL31 only implements a + subset of the Power State Coordination Interface (PSCI) API as a runtime + service. See Section 3.3 below for details of porting the PSCI + implementation. + +#. Optionally passing control to the BL32 image, pre-loaded at a platform- + specific address by BL2. BL31 exports a set of APIs that allow runtime + services to specify the security state in which the next image should be + executed and run the corresponding image. On ARM platforms, BL31 uses the + ``bl_params`` list populated by BL2 in memory to do this. + +If BL31 is a reset vector, It also needs to handle the reset as specified in +section 2.2 before the tasks described above. + +The following functions must be implemented by the platform port to enable BL31 +to perform the above tasks. + +Function : bl31_early_platform_setup2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. BL2 can pass 4 arguments to BL31 and these arguments are +platform specific. + +In Arm standard platforms, the arguments received are : + + arg0 - The pointer to the head of `bl_params_t` list + which is list of executable images following BL31, + + arg1 - Points to load address of SOC_FW_CONFIG if present + except in case of Arm FVP and Juno platform. + + In case of Arm FVP and Juno platform, points to load address + of FW_CONFIG. + + arg2 - Points to load address of HW_CONFIG if present + + arg3 - A special value to verify platform parameters from BL2 to BL31. Not + used in release builds. + +The function runs through the `bl_param_t` list and extracts the entry point +information for BL32 and BL33. It also performs the following: + +- Initialize a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL31. + +- Enable issuing of snoop and DVM (Distributed Virtual Memory) requests to the + CCI slave interface corresponding to the cluster that includes the primary + CPU. + +Function : bl31_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl31_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl31_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to complete platform initialization so that both +BL31 runtime services and normal world software can function correctly. + +On Arm standard platforms, this function does the following: + +- Initialize the generic interrupt controller. + + Depending on the GIC driver selected by the platform, the appropriate GICv2 + or GICv3 initialization will be done, which mainly consists of: + + - Enable secure interrupts in the GIC CPU interface. + - Disable the legacy interrupt bypass mechanism. + - Configure the priority mask register to allow interrupts of all priorities + to be signaled to the CPU interface. + - Mark SGIs 8-15 and the other secure interrupts on the platform as secure. + - Target all secure SPIs to CPU0. + - Enable these secure interrupts in the GIC distributor. + - Configure all other interrupts as non-secure. + - Enable signaling of secure interrupts in the GIC distributor. + +- Enable system-level implementation of the generic timer counter through the + memory mapped interface. + +- Grant access to the system counter timer module + +- Initialize the power controller device. + + In particular, initialise the locks that prevent concurrent accesses to the + power controller device. + +Function : bl31_plat_runtime_setup() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +The purpose of this function is allow the platform to perform any BL31 runtime +setup just prior to BL31 exit during cold boot. The default weak +implementation of this function will invoke ``console_switch_state()`` to switch +console output to consoles marked for use in the ``runtime`` state. + +Function : bl31_plat_get_next_image_ep_info() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : entry_point_info * + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. + +This function is called by ``bl31_main()`` to retrieve information provided by +BL2 for the next image in the security state specified by the argument. BL31 +uses this information to pass control to that image in the specified security +state. This function must return a pointer to the ``entry_point_info`` structure +(that was copied during ``bl31_early_platform_setup()``) if the image exists. It +should return NULL otherwise. + +Function : plat_get_cca_attest_token() [mandatory when ENABLE_RME == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t, size_t *, uintptr_t, size_t + Return : int + +This function returns the Platform attestation token. + +The parameters of the function are: + + arg0 - A pointer to the buffer where the Platform token should be copied by + this function. The buffer must be big enough to hold the Platform + token. + + arg1 - Contains the size (in bytes) of the buffer passed in arg0. The + function returns the platform token length in this parameter. + + arg2 - A pointer to the buffer where the challenge object is stored. + + arg3 - The length of the challenge object in bytes. Possible values are 32, + 48 and 64. + +The function returns 0 on success, -EINVAL on failure. + +Function : plat_get_cca_realm_attest_key() [mandatory when ENABLE_RME == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t, size_t *, unsigned int + Return : int + +This function returns the delegated realm attestation key which will be used to +sign Realm attestation token. The API currently only supports P-384 ECC curve +key. + +The parameters of the function are: + + arg0 - A pointer to the buffer where the attestation key should be copied + by this function. The buffer must be big enough to hold the + attestation key. + + arg1 - Contains the size (in bytes) of the buffer passed in arg0. The + function returns the attestation key length in this parameter. + + arg2 - The type of the elliptic curve to which the requested attestation key + belongs. + +The function returns 0 on success, -EINVAL on failure. + +Function : bl31_plat_enable_mmu [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : void + +This function enables the MMU. The boot code calls this function with MMU and +caches disabled. This function should program necessary registers to enable +translation, and upon return, the MMU on the calling PE must be enabled. + +The function must honor flags passed in the first argument. These flags are +defined by the translation library, and can be found in the file +``include/lib/xlat_tables/xlat_mmu_helpers.h``. + +On DynamIQ systems, this function must not use stack while enabling MMU, which +is how the function in xlat table library version 2 is implemented. + +Function : plat_init_apkey [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint128_t + +This function returns the 128-bit value which can be used to program ARMv8.3 +pointer authentication keys. + +The value should be obtained from a reliable source of randomness. + +This function is only needed if ARMv8.3 pointer authentication is used in the +Trusted Firmware by building with ``BRANCH_PROTECTION`` option set to non-zero. + +Function : plat_get_syscnt_freq2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function is used by the architecture setup code to retrieve the counter +frequency for the CPU's generic timer. This value will be programmed into the +``CNTFRQ_EL0`` register. In Arm standard platforms, it returns the base frequency +of the system counter, which is retrieved from the first entry in the frequency +modes table. + +Function : plat_arm_set_twedel_scr_el3() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This function is used in v8.6+ systems to set the WFE trap delay value in +SCR_EL3. If this function returns TWED_DISABLED or is left unimplemented, this +feature is not enabled. The only hook provided is to set the TWED fields in +SCR_EL3, there are similar fields in HCR_EL2, SCTLR_EL2, and SCTLR_EL1 to adjust +the WFE trap delays in lower ELs and these fields should be set by the +appropriate EL2 or EL1 code depending on the platform configuration. + +#define : PLAT_PERCPU_BAKERY_LOCK_SIZE [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When ``USE_COHERENT_MEM = 0``, this constant defines the total memory (in +bytes) aligned to the cache line boundary that should be allocated per-cpu to +accommodate all the bakery locks. + +If this constant is not defined when ``USE_COHERENT_MEM = 0``, the linker +calculates the size of the ``bakery_lock`` input section, aligns it to the +nearest ``CACHE_WRITEBACK_GRANULE``, multiplies it with ``PLATFORM_CORE_COUNT`` +and stores the result in a linker symbol. This constant prevents a platform +from relying on the linker and provide a more efficient mechanism for +accessing per-cpu bakery lock information. + +If this constant is defined and its value is not equal to the value +calculated by the linker then a link time assertion is raised. A compile time +assertion is raised if the value of the constant is not aligned to the cache +line boundary. + +.. _porting_guide_sdei_requirements: + +SDEI porting requirements +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The |SDEI| dispatcher requires the platform to provide the following macros +and functions, of which some are optional, and some others mandatory. + +Macros +...... + +Macro: PLAT_SDEI_NORMAL_PRI [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This macro must be defined to the EL3 exception priority level associated with +Normal |SDEI| events on the platform. This must have a higher value +(therefore of lower priority) than ``PLAT_SDEI_CRITICAL_PRI``. + +Macro: PLAT_SDEI_CRITICAL_PRI [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This macro must be defined to the EL3 exception priority level associated with +Critical |SDEI| events on the platform. This must have a lower value +(therefore of higher priority) than ``PLAT_SDEI_NORMAL_PRI``. + +**Note**: |SDEI| exception priorities must be the lowest among Secure +priorities. Among the |SDEI| exceptions, Critical |SDEI| priority must +be higher than Normal |SDEI| priority. + +Functions +......... + +Function: int plat_sdei_validate_entry_point() [optional] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uintptr_t ep, unsigned int client_mode + Return: int + +This function validates the entry point address of the event handler provided by +the client for both event registration and *Complete and Resume* |SDEI| calls. +The function ensures that the address is valid in the client translation regime. + +The second argument is the exception level that the client is executing in. It +can be Non-Secure EL1 or Non-Secure EL2. + +The function must return ``0`` for successful validation, or ``-1`` upon failure. + +The default implementation always returns ``0``. On Arm platforms, this function +translates the entry point address within the client translation regime and +further ensures that the resulting physical address is located in Non-secure +DRAM. + +Function: void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr) [optional] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uint64_t + Argument: unsigned int + Return: void + +|SDEI| specification requires that a PE comes out of reset with the events +masked. The client therefore is expected to call ``PE_UNMASK`` to unmask +|SDEI| events on the PE. No |SDEI| events can be dispatched until such +time. + +Should a PE receive an interrupt that was bound to an |SDEI| event while the +events are masked on the PE, the dispatcher implementation invokes the function +``plat_sdei_handle_masked_trigger``. The MPIDR of the PE that received the +interrupt and the interrupt ID are passed as parameters. + +The default implementation only prints out a warning message. + +.. _porting_guide_trng_requirements: + +TRNG porting requirements +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The |TRNG| backend requires the platform to provide the following values +and mandatory functions. + +Values +...... + +value: uuid_t plat_trng_uuid [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This value must be defined to the UUID of the TRNG backend that is specific to +the hardware after ``plat_trng_setup`` function is called. This value must +conform to the SMCCC calling convention; The most significant 32 bits of the +UUID must not equal ``0xffffffff`` or the signed integer ``-1`` as this value in +w0 indicates failure to get a TRNG source. + +Functions +......... + +Function: void plat_entropy_setup(void) [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: none + Return: none + +This function is expected to do platform-specific initialization of any TRNG +hardware. This may include generating a UUID from a hardware-specific seed. + +Function: bool plat_get_entropy(uint64_t \*out) [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uint64_t * + Return: bool + Out : when the return value is true, the entropy has been written into the + storage pointed to + +This function writes entropy into storage provided by the caller. If no entropy +is available, it must return false and the storage must not be written. + +Power State Coordination Interface (in BL31) +-------------------------------------------- + +The TF-A implementation of the PSCI API is based around the concept of a +*power domain*. A *power domain* is a CPU or a logical group of CPUs which +share some state on which power management operations can be performed as +specified by `PSCI`_. Each CPU in the system is assigned a cpu index which is +a unique number between ``0`` and ``PLATFORM_CORE_COUNT - 1``. The +*power domains* are arranged in a hierarchical tree structure and each +*power domain* can be identified in a system by the cpu index of any CPU that +is part of that domain and a *power domain level*. A processing element (for +example, a CPU) is at level 0. If the *power domain* node above a CPU is a +logical grouping of CPUs that share some state, then level 1 is that group of +CPUs (for example, a cluster), and level 2 is a group of clusters (for +example, the system). More details on the power domain topology and its +organization can be found in :ref:`PSCI Power Domain Tree Structure`. + +BL31's platform initialization code exports a pointer to the platform-specific +power management operations required for the PSCI implementation to function +correctly. This information is populated in the ``plat_psci_ops`` structure. The +PSCI implementation calls members of the ``plat_psci_ops`` structure for performing +power management operations on the power domains. For example, the target +CPU is specified by its ``MPIDR`` in a PSCI ``CPU_ON`` call. The ``pwr_domain_on()`` +handler (if present) is called for the CPU power domain. + +The ``power-state`` parameter of a PSCI ``CPU_SUSPEND`` call can be used to +describe composite power states specific to a platform. The PSCI implementation +defines a generic representation of the power-state parameter, which is an +array of local power states where each index corresponds to a power domain +level. Each entry contains the local power state the power domain at that power +level could enter. It depends on the ``validate_power_state()`` handler to +convert the power-state parameter (possibly encoding a composite power state) +passed in a PSCI ``CPU_SUSPEND`` call to this representation. + +The following functions form part of platform port of PSCI functionality. + +Function : plat_psci_stat_accounting_start() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_power_state_t * + Return : void + +This is an optional hook that platforms can implement for residency statistics +accounting before entering a low power state. The ``pwr_domain_state`` field of +``state_info`` (first argument) can be inspected if stat accounting is done +differently at CPU level versus higher levels. As an example, if the element at +index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down +state, special hardware logic may be programmed in order to keep track of the +residency statistics. For higher levels (array indices > 0), the residency +statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the +default implementation will use PMF to capture timestamps. + +Function : plat_psci_stat_accounting_stop() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_power_state_t * + Return : void + +This is an optional hook that platforms can implement for residency statistics +accounting after exiting from a low power state. The ``pwr_domain_state`` field +of ``state_info`` (first argument) can be inspected if stat accounting is done +differently at CPU level versus higher levels. As an example, if the element at +index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down +state, special hardware logic may be programmed in order to keep track of the +residency statistics. For higher levels (array indices > 0), the residency +statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the +default implementation will use PMF to capture timestamps. + +Function : plat_psci_stat_get_residency() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const psci_power_state_t *, unsigned int + Return : u_register_t + +This is an optional interface that is is invoked after resuming from a low power +state and provides the time spent resident in that low power state by the power +domain at a particular power domain level. When a CPU wakes up from suspend, +all its parent power domain levels are also woken up. The generic PSCI code +invokes this function for each parent power domain that is resumed and it +identified by the ``lvl`` (first argument) parameter. The ``state_info`` (second +argument) describes the low power state that the power domain has resumed from. +The current CPU is the first CPU in the power domain to resume from the low +power state and the ``last_cpu_idx`` (third parameter) is the index of the last +CPU in the power domain to suspend and may be needed to calculate the residency +for that power domain. + +Function : plat_get_target_pwr_state() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const plat_local_state_t *, unsigned int + Return : plat_local_state_t + +The PSCI generic code uses this function to let the platform participate in +state coordination during a power management operation. The function is passed +a pointer to an array of platform specific local power state ``states`` (second +argument) which contains the requested power state for each CPU at a particular +power domain level ``lvl`` (first argument) within the power domain. The function +is expected to traverse this array of upto ``ncpus`` (third argument) and return +a coordinated target power state by the comparing all the requested power +states. The target power state should not be deeper than any of the requested +power states. + +A weak definition of this API is provided by default wherein it assumes +that the platform assigns a local state value in order of increasing depth +of the power state i.e. for two power states X & Y, if X < Y +then X represents a shallower power state than Y. As a result, the +coordinated target local power state for a power domain will be the minimum +of the requested local power state values. + +Function : plat_get_power_domain_tree_desc() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : const unsigned char * + +This function returns a pointer to the byte array containing the power domain +topology tree description. The format and method to construct this array are +described in :ref:`PSCI Power Domain Tree Structure`. The BL31 PSCI +initialization code requires this array to be described by the platform, either +statically or dynamically, to initialize the power domain topology tree. In case +the array is populated dynamically, then plat_core_pos_by_mpidr() and +plat_my_core_pos() should also be implemented suitably so that the topology tree +description matches the CPU indices returned by these APIs. These APIs together +form the platform interface for the PSCI topology framework. + +Function : plat_setup_psci_ops() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t, const plat_psci_ops ** + Return : int + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only +called by the primary CPU. + +This function is called by PSCI initialization code. Its purpose is to let +the platform layer know about the warm boot entrypoint through the +``sec_entrypoint`` (first argument) and to export handler routines for +platform-specific psci power management actions by populating the passed +pointer with a pointer to BL31's private ``plat_psci_ops`` structure. + +A description of each member of this structure is given below. Please refer to +the Arm FVP specific implementation of these handlers in +``plat/arm/board/fvp/fvp_pm.c`` as an example. For each PSCI function that the +platform wants to support, the associated operation or operations in this +structure must be provided and implemented (Refer section 4 of +:ref:`Firmware Design` for the PSCI API supported in TF-A). To disable a PSCI +function in a platform port, the operation should be removed from this +structure instead of providing an empty implementation. + +plat_psci_ops.cpu_standby() +........................... + +Perform the platform-specific actions to enter the standby state for a cpu +indicated by the passed argument. This provides a fast path for CPU standby +wherein overheads of PSCI state management and lock acquisition is avoided. +For this handler to be invoked by the PSCI ``CPU_SUSPEND`` API implementation, +the suspend state type specified in the ``power-state`` parameter should be +STANDBY and the target power domain level specified should be the CPU. The +handler should put the CPU into a low power retention state (usually by +issuing a wfi instruction) and ensure that it can be woken up from that +state by a normal interrupt. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_on() +............................. + +Perform the platform specific actions to power on a CPU, specified +by the ``MPIDR`` (first argument). The generic code expects the platform to +return PSCI_E_SUCCESS on success or PSCI_E_INTERN_FAIL for any failure. + +plat_psci_ops.pwr_domain_off() +.............................. + +Perform the platform specific actions to prepare to power off the calling CPU +and its higher parent power domain levels as indicated by the ``target_state`` +(first argument). It is called by the PSCI ``CPU_OFF`` API implementation. + +The ``target_state`` encodes the platform coordinated target local power states +for the CPU power domain and its parent power domain levels. The handler +needs to perform power management operation corresponding to the local state +at each power level. + +For this handler, the local power state for the CPU power domain will be a +power down state where as it could be either power down, retention or run state +for the higher power domain levels depending on the result of state +coordination. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_suspend_pwrdown_early() [optional] +........................................................... + +This optional function may be used as a performance optimization to replace +or complement pwr_domain_suspend() on some platforms. Its calling semantics +are identical to pwr_domain_suspend(), except the PSCI implementation only +calls this function when suspending to a power down state, and it guarantees +that data caches are enabled. + +When HW_ASSISTED_COHERENCY = 0, the PSCI implementation disables data caches +before calling pwr_domain_suspend(). If the target_state corresponds to a +power down state and it is safe to perform some or all of the platform +specific actions in that function with data caches enabled, it may be more +efficient to move those actions to this function. When HW_ASSISTED_COHERENCY += 1, data caches remain enabled throughout, and so there is no advantage to +moving platform specific actions to this function. + +plat_psci_ops.pwr_domain_suspend() +.................................. + +Perform the platform specific actions to prepare to suspend the calling +CPU and its higher parent power domain levels as indicated by the +``target_state`` (first argument). It is called by the PSCI ``CPU_SUSPEND`` +API implementation. + +The ``target_state`` has a similar meaning as described in +the ``pwr_domain_off()`` operation. It encodes the platform coordinated +target local power states for the CPU power domain and its parent +power domain levels. The handler needs to perform power management operation +corresponding to the local state at each power level. The generic code +expects the handler to succeed. + +The difference between turning a power domain off versus suspending it is that +in the former case, the power domain is expected to re-initialize its state +when it is next powered on (see ``pwr_domain_on_finish()``). In the latter +case, the power domain is expected to save enough state so that it can resume +execution by restoring this state when its powered on (see +``pwr_domain_suspend_finish()``). + +When suspending a core, the platform can also choose to power off the GICv3 +Redistributor and ITS through an implementation-defined sequence. To achieve +this safely, the ITS context must be saved first. The architectural part is +implemented by the ``gicv3_its_save_disable()`` helper, but most of the needed +sequence is implementation defined and it is therefore the responsibility of +the platform code to implement the necessary sequence. Then the GIC +Redistributor context can be saved using the ``gicv3_rdistif_save()`` helper. +Powering off the Redistributor requires the implementation to support it and it +is the responsibility of the platform code to execute the right implementation +defined sequence. + +When a system suspend is requested, the platform can also make use of the +``gicv3_distif_save()`` helper to save the context of the GIC Distributor after +it has saved the context of the Redistributors and ITS of all the cores in the +system. The context of the Distributor can be large and may require it to be +allocated in a special area if it cannot fit in the platform's global static +data, for example in DRAM. The Distributor can then be powered down using an +implementation-defined sequence. + +plat_psci_ops.pwr_domain_pwr_down_wfi() +....................................... + +This is an optional function and, if implemented, is expected to perform +platform specific actions including the ``wfi`` invocation which allows the +CPU to powerdown. Since this function is invoked outside the PSCI locks, +the actions performed in this hook must be local to the CPU or the platform +must ensure that races between multiple CPUs cannot occur. + +The ``target_state`` has a similar meaning as described in the ``pwr_domain_off()`` +operation and it encodes the platform coordinated target local power states for +the CPU power domain and its parent power domain levels. This function must +not return back to the caller. + +If this function is not implemented by the platform, PSCI generic +implementation invokes ``psci_power_down_wfi()`` for power down. + +plat_psci_ops.pwr_domain_on_finish() +.................................... + +This function is called by the PSCI implementation after the calling CPU is +powered on and released from reset in response to an earlier PSCI ``CPU_ON`` call. +It performs the platform-specific setup required to initialize enough state for +this CPU to enter the normal world and also provide secure runtime firmware +services. + +The ``target_state`` (first argument) is the prior state of the power domains +immediately before the CPU was turned on. It indicates which power domains +above the CPU might require initialization due to having previously been in +low power states. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_on_finish_late() [optional] +........................................................... + +This optional function is called by the PSCI implementation after the calling +CPU is fully powered on with respective data caches enabled. The calling CPU and +the associated cluster are guaranteed to be participating in coherency. This +function gives the flexibility to perform any platform-specific actions safely, +such as initialization or modification of shared data structures, without the +overhead of explicit cache maintainace operations. + +The ``target_state`` has a similar meaning as described in the ``pwr_domain_on_finish()`` +operation. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_suspend_finish() +......................................... + +This function is called by the PSCI implementation after the calling CPU is +powered on and released from reset in response to an asynchronous wakeup +event, for example a timer interrupt that was programmed by the CPU during the +``CPU_SUSPEND`` call or ``SYSTEM_SUSPEND`` call. It performs the platform-specific +setup required to restore the saved state for this CPU to resume execution +in the normal world and also provide secure runtime firmware services. + +The ``target_state`` (first argument) has a similar meaning as described in +the ``pwr_domain_on_finish()`` operation. The generic code expects the platform +to succeed. + +If the Distributor, Redistributors or ITS have been powered off as part of a +suspend, their context must be restored in this function in the reverse order +to how they were saved during suspend sequence. + +plat_psci_ops.system_off() +.......................... + +This function is called by PSCI implementation in response to a ``SYSTEM_OFF`` +call. It performs the platform-specific system poweroff sequence after +notifying the Secure Payload Dispatcher. + +plat_psci_ops.system_reset() +............................ + +This function is called by PSCI implementation in response to a ``SYSTEM_RESET`` +call. It performs the platform-specific system reset sequence after +notifying the Secure Payload Dispatcher. + +plat_psci_ops.validate_power_state() +.................................... + +This function is called by the PSCI implementation during the ``CPU_SUSPEND`` +call to validate the ``power_state`` parameter of the PSCI API and if valid, +populate it in ``req_state`` (second argument) array as power domain level +specific local states. If the ``power_state`` is invalid, the platform must +return PSCI_E_INVALID_PARAMS as error, which is propagated back to the +normal world PSCI client. + +plat_psci_ops.validate_ns_entrypoint() +...................................... + +This function is called by the PSCI implementation during the ``CPU_SUSPEND``, +``SYSTEM_SUSPEND`` and ``CPU_ON`` calls to validate the non-secure ``entry_point`` +parameter passed by the normal world. If the ``entry_point`` is invalid, +the platform must return PSCI_E_INVALID_ADDRESS as error, which is +propagated back to the normal world PSCI client. + +plat_psci_ops.get_sys_suspend_power_state() +........................................... + +This function is called by the PSCI implementation during the ``SYSTEM_SUSPEND`` +call to get the ``req_state`` parameter from platform which encodes the power +domain level specific local states to suspend to system affinity level. The +``req_state`` will be utilized to do the PSCI state coordination and +``pwr_domain_suspend()`` will be invoked with the coordinated target state to +enter system suspend. + +plat_psci_ops.get_pwr_lvl_state_idx() +..................................... + +This is an optional function and, if implemented, is invoked by the PSCI +implementation to convert the ``local_state`` (first argument) at a specified +``pwr_lvl`` (second argument) to an index between 0 and +``PLAT_MAX_PWR_LVL_STATES`` - 1. This function is only needed if the platform +supports more than two local power states at each power domain level, that is +``PLAT_MAX_PWR_LVL_STATES`` is greater than 2, and needs to account for these +local power states. + +plat_psci_ops.translate_power_state_by_mpidr() +.............................................. + +This is an optional function and, if implemented, verifies the ``power_state`` +(second argument) parameter of the PSCI API corresponding to a target power +domain. The target power domain is identified by using both ``MPIDR`` (first +argument) and the power domain level encoded in ``power_state``. The power domain +level specific local states are to be extracted from ``power_state`` and be +populated in the ``output_state`` (third argument) array. The functionality +is similar to the ``validate_power_state`` function described above and is +envisaged to be used in case the validity of ``power_state`` depend on the +targeted power domain. If the ``power_state`` is invalid for the targeted power +domain, the platform must return PSCI_E_INVALID_PARAMS as error. If this +function is not implemented, then the generic implementation relies on +``validate_power_state`` function to translate the ``power_state``. + +This function can also be used in case the platform wants to support local +power state encoding for ``power_state`` parameter of PSCI_STAT_COUNT/RESIDENCY +APIs as described in Section 5.18 of `PSCI`_. + +plat_psci_ops.get_node_hw_state() +................................. + +This is an optional function. If implemented this function is intended to return +the power state of a node (identified by the first parameter, the ``MPIDR``) in +the power domain topology (identified by the second parameter, ``power_level``), +as retrieved from a power controller or equivalent component on the platform. +Upon successful completion, the implementation must map and return the final +status among ``HW_ON``, ``HW_OFF`` or ``HW_STANDBY``. Upon encountering failures, it +must return either ``PSCI_E_INVALID_PARAMS`` or ``PSCI_E_NOT_SUPPORTED`` as +appropriate. + +Implementations are not expected to handle ``power_levels`` greater than +``PLAT_MAX_PWR_LVL``. + +plat_psci_ops.system_reset2() +............................. + +This is an optional function. If implemented this function is +called during the ``SYSTEM_RESET2`` call to perform a reset +based on the first parameter ``reset_type`` as specified in +`PSCI`_. The parameter ``cookie`` can be used to pass additional +reset information. If the ``reset_type`` is not supported, the +function must return ``PSCI_E_NOT_SUPPORTED``. For architectural +resets, all failures must return ``PSCI_E_INVALID_PARAMETERS`` +and vendor reset can return other PSCI error codes as defined +in `PSCI`_. On success this function will not return. + +plat_psci_ops.write_mem_protect() +................................. + +This is an optional function. If implemented it enables or disables the +``MEM_PROTECT`` functionality based on the value of ``val``. +A non-zero value enables ``MEM_PROTECT`` and a value of zero +disables it. Upon encountering failures it must return a negative value +and on success it must return 0. + +plat_psci_ops.read_mem_protect() +................................ + +This is an optional function. If implemented it returns the current +state of ``MEM_PROTECT`` via the ``val`` parameter. Upon encountering +failures it must return a negative value and on success it must +return 0. + +plat_psci_ops.mem_protect_chk() +............................... + +This is an optional function. If implemented it checks if a memory +region defined by a base address ``base`` and with a size of ``length`` +bytes is protected by ``MEM_PROTECT``. If the region is protected +then it must return 0, otherwise it must return a negative number. + +.. _porting_guide_imf_in_bl31: + +Interrupt Management framework (in BL31) +---------------------------------------- + +BL31 implements an Interrupt Management Framework (IMF) to manage interrupts +generated in either security state and targeted to EL1 or EL2 in the non-secure +state or EL3/S-EL1 in the secure state. The design of this framework is +described in the :ref:`Interrupt Management Framework` + +A platform should export the following APIs to support the IMF. The following +text briefly describes each API and its implementation in Arm standard +platforms. The API implementation depends upon the type of interrupt controller +present in the platform. Arm standard platform layer supports both +`Arm Generic Interrupt Controller version 2.0 (GICv2)`_ +and `3.0 (GICv3)`_. Juno builds the Arm platform layer to use GICv2 and the +FVP can be configured to use either GICv2 or GICv3 depending on the build flag +``FVP_USE_GIC_DRIVER`` (See :ref:`build_options_arm_fvp_platform` for more +details). + +See also: :ref:`Interrupt Controller Abstraction APIs`. + +Function : plat_interrupt_type_to_line() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t, uint32_t + Return : uint32_t + +The Arm processor signals an interrupt exception either through the IRQ or FIQ +interrupt line. The specific line that is signaled depends on how the interrupt +controller (IC) reports different interrupt types from an execution context in +either security state. The IMF uses this API to determine which interrupt line +the platform IC uses to signal each type of interrupt supported by the framework +from a given security state. This API must be invoked at EL3. + +The first parameter will be one of the ``INTR_TYPE_*`` values (see +:ref:`Interrupt Management Framework`) indicating the target type of the +interrupt, the second parameter is the security state of the originating +execution context. The return result is the bit position in the ``SCR_EL3`` +register of the respective interrupt trap: IRQ=1, FIQ=2. + +In the case of Arm standard platforms using GICv2, S-EL1 interrupts are +configured as FIQs and Non-secure interrupts as IRQs from either security +state. + +In the case of Arm standard platforms using GICv3, the interrupt line to be +configured depends on the security state of the execution context when the +interrupt is signalled and are as follows: + +- The S-EL1 interrupts are signaled as IRQ in S-EL0/1 context and as FIQ in + NS-EL0/1/2 context. +- The Non secure interrupts are signaled as FIQ in S-EL0/1 context and as IRQ + in the NS-EL0/1/2 context. +- The EL3 interrupts are signaled as FIQ in both S-EL0/1 and NS-EL0/1/2 + context. + +Function : plat_ic_get_pending_interrupt_type() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API returns the type of the highest priority pending interrupt at the +platform IC. The IMF uses the interrupt type to retrieve the corresponding +handler function. ``INTR_TYPE_INVAL`` is returned when there is no interrupt +pending. The valid interrupt types that can be returned are ``INTR_TYPE_EL3``, +``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``. This API must be invoked at EL3. + +In the case of Arm standard platforms using GICv2, the *Highest Priority +Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of +the pending interrupt. The type of interrupt depends upon the id value as +follows. + +#. id < 1022 is reported as a S-EL1 interrupt +#. id = 1022 is reported as a Non-secure interrupt. +#. id = 1023 is reported as an invalid interrupt type. + +In the case of Arm standard platforms using GICv3, the system register +``ICC_HPPIR0_EL1``, *Highest Priority Pending group 0 Interrupt Register*, +is read to determine the id of the pending interrupt. The type of interrupt +depends upon the id value as follows. + +#. id = ``PENDING_G1S_INTID`` (1020) is reported as a S-EL1 interrupt +#. id = ``PENDING_G1NS_INTID`` (1021) is reported as a Non-secure interrupt. +#. id = ``GIC_SPURIOUS_INTERRUPT`` (1023) is reported as an invalid interrupt type. +#. All other interrupt id's are reported as EL3 interrupt. + +Function : plat_ic_get_pending_interrupt_id() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API returns the id of the highest priority pending interrupt at the +platform IC. ``INTR_ID_UNAVAILABLE`` is returned when there is no interrupt +pending. + +In the case of Arm standard platforms using GICv2, the *Highest Priority +Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of the +pending interrupt. The id that is returned by API depends upon the value of +the id read from the interrupt controller as follows. + +#. id < 1022. id is returned as is. +#. id = 1022. The *Aliased Highest Priority Pending Interrupt Register* + (``GICC_AHPPIR``) is read to determine the id of the non-secure interrupt. + This id is returned by the API. +#. id = 1023. ``INTR_ID_UNAVAILABLE`` is returned. + +In the case of Arm standard platforms using GICv3, if the API is invoked from +EL3, the system register ``ICC_HPPIR0_EL1``, *Highest Priority Pending Interrupt +group 0 Register*, is read to determine the id of the pending interrupt. The id +that is returned by API depends upon the value of the id read from the +interrupt controller as follows. + +#. id < ``PENDING_G1S_INTID`` (1020). id is returned as is. +#. id = ``PENDING_G1S_INTID`` (1020) or ``PENDING_G1NS_INTID`` (1021). The system + register ``ICC_HPPIR1_EL1``, *Highest Priority Pending Interrupt group 1 + Register* is read to determine the id of the group 1 interrupt. This id + is returned by the API as long as it is a valid interrupt id +#. If the id is any of the special interrupt identifiers, + ``INTR_ID_UNAVAILABLE`` is returned. + +When the API invoked from S-EL1 for GICv3 systems, the id read from system +register ``ICC_HPPIR1_EL1``, *Highest Priority Pending group 1 Interrupt +Register*, is returned if is not equal to GIC_SPURIOUS_INTERRUPT (1023) else +``INTR_ID_UNAVAILABLE`` is returned. + +Function : plat_ic_acknowledge_interrupt() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API is used by the CPU to indicate to the platform IC that processing of +the highest pending interrupt has begun. It should return the raw, unmodified +value obtained from the interrupt controller when acknowledging an interrupt. +The actual interrupt number shall be extracted from this raw value using the API +`plat_ic_get_interrupt_id()`. + +This function in Arm standard platforms using GICv2, reads the *Interrupt +Acknowledge Register* (``GICC_IAR``). This changes the state of the highest +priority pending interrupt from pending to active in the interrupt controller. +It returns the value read from the ``GICC_IAR``, unmodified. + +In the case of Arm standard platforms using GICv3, if the API is invoked +from EL3, the function reads the system register ``ICC_IAR0_EL1``, *Interrupt +Acknowledge Register group 0*. If the API is invoked from S-EL1, the function +reads the system register ``ICC_IAR1_EL1``, *Interrupt Acknowledge Register +group 1*. The read changes the state of the highest pending interrupt from +pending to active in the interrupt controller. The value read is returned +unmodified. + +The TSP uses this API to start processing of the secure physical timer +interrupt. + +Function : plat_ic_end_of_interrupt() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : void + +This API is used by the CPU to indicate to the platform IC that processing of +the interrupt corresponding to the id (passed as the parameter) has +finished. The id should be the same as the id returned by the +``plat_ic_acknowledge_interrupt()`` API. + +Arm standard platforms write the id to the *End of Interrupt Register* +(``GICC_EOIR``) in case of GICv2, and to ``ICC_EOIR0_EL1`` or ``ICC_EOIR1_EL1`` +system register in case of GICv3 depending on where the API is invoked from, +EL3 or S-EL1. This deactivates the corresponding interrupt in the interrupt +controller. + +The TSP uses this API to finish processing of the secure physical timer +interrupt. + +Function : plat_ic_get_interrupt_type() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : uint32_t + +This API returns the type of the interrupt id passed as the parameter. +``INTR_TYPE_INVAL`` is returned if the id is invalid. If the id is valid, a valid +interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``) is +returned depending upon how the interrupt has been configured by the platform +IC. This API must be invoked at EL3. + +Arm standard platforms using GICv2 configures S-EL1 interrupts as Group0 interrupts +and Non-secure interrupts as Group1 interrupts. It reads the group value +corresponding to the interrupt id from the relevant *Interrupt Group Register* +(``GICD_IGROUPRn``). It uses the group value to determine the type of interrupt. + +In the case of Arm standard platforms using GICv3, both the *Interrupt Group +Register* (``GICD_IGROUPRn``) and *Interrupt Group Modifier Register* +(``GICD_IGRPMODRn``) is read to figure out whether the interrupt is configured +as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt. + +Crash Reporting mechanism (in BL31) +----------------------------------- + +BL31 implements a crash reporting mechanism which prints the various registers +of the CPU to enable quick crash analysis and debugging. This mechanism relies +on the platform implementing ``plat_crash_console_init``, +``plat_crash_console_putc`` and ``plat_crash_console_flush``. + +The file ``plat/common/aarch64/crash_console_helpers.S`` contains sample +implementation of all of them. Platforms may include this file to their +makefiles in order to benefit from them. By default, they will cause the crash +output to be routed over the normal console infrastructure and get printed on +consoles configured to output in crash state. ``console_set_scope()`` can be +used to control whether a console is used for crash output. + +.. note:: + Platforms are responsible for making sure that they only mark consoles for + use in the crash scope that are able to support this, i.e. that are written + in assembly and conform with the register clobber rules for putc() + (x0-x2, x16-x17) and flush() (x0-x3, x16-x17) crash callbacks. + +In some cases (such as debugging very early crashes that happen before the +normal boot console can be set up), platforms may want to control crash output +more explicitly. These platforms may instead provide custom implementations for +these. They are executed outside of a C environment and without a stack. Many +console drivers provide functions named ``console_xxx_core_init/putc/flush`` +that are designed to be used by these functions. See Arm platforms (like juno) +for an example of this. + +Function : plat_crash_console_init [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This API is used by the crash reporting mechanism to initialize the crash +console. It must only use the general purpose registers x0 through x7 to do the +initialization and returns 1 on success. + +Function : plat_crash_console_putc [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Return : int + +This API is used by the crash reporting mechanism to print a character on the +designated crash console. It must only use general purpose registers x1 and +x2 to do its work. The parameter and the return value are in general purpose +register x0. + +Function : plat_crash_console_flush [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API is used by the crash reporting mechanism to force write of all buffered +data on the designated crash console. It should only use general purpose +registers x0 through x5 to do its work. + +.. _External Abort handling and RAS Support: + +External Abort handling and RAS Support +--------------------------------------- + +Function : plat_ea_handler +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Argument : void * + Argument : void * + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework for the platform to handle an +External Abort received at EL3. The intention of the function is to attempt to +resolve the cause of External Abort and return; if that's not possible, to +initiate orderly shutdown of the system. + +The first parameter (``int ea_reason``) indicates the reason for External Abort. +Its value is one of ``ERROR_EA_*`` constants defined in ``ea_handle.h``. + +The second parameter (``uint64_t syndrome``) is the respective syndrome +presented to EL3 after having received the External Abort. Depending on the +nature of the abort (as can be inferred from the ``ea_reason`` parameter), this +can be the content of either ``ESR_EL3`` or ``DISR_EL1``. + +The third parameter (``void *cookie``) is unused for now. The fourth parameter +(``void *handle``) is a pointer to the preempted context. The fifth parameter +(``uint64_t flags``) indicates the preempted security state. These parameters +are received from the top-level exception handler. + +If ``RAS_EXTENSION`` is set to ``1``, the default implementation of this +function iterates through RAS handlers registered by the platform. If any of the +RAS handlers resolve the External Abort, no further action is taken. + +If ``RAS_EXTENSION`` is set to ``0``, or if none of the platform RAS handlers +could resolve the External Abort, the default implementation prints an error +message, and panics. + +Function : plat_handle_uncontainable_ea +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework when an External Abort of +Uncontainable type is received at EL3. Due to the critical nature of +Uncontainable errors, the intention of this function is to initiate orderly +shutdown of the system, and is not expected to return. + +This function must be implemented in assembly. + +The first and second parameters are the same as that of ``plat_ea_handler``. + +The default implementation of this function calls +``report_unhandled_exception``. + +Function : plat_handle_double_fault +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework when another External Abort is +received at EL3 while one is already being handled. I.e., a call to +``plat_ea_handler`` is outstanding. Due to its critical nature, the intention of +this function is to initiate orderly shutdown of the system, and is not expected +recover or return. + +This function must be implemented in assembly. + +The first and second parameters are the same as that of ``plat_ea_handler``. + +The default implementation of this function calls +``report_unhandled_exception``. + +Function : plat_handle_el3_ea +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Return : void + +This function is invoked when an External Abort is received while executing in +EL3. Due to its critical nature, the intention of this function is to initiate +orderly shutdown of the system, and is not expected recover or return. + +This function must be implemented in assembly. + +The default implementation of this function calls +``report_unhandled_exception``. + +Build flags +----------- + +There are some build flags which can be defined by the platform to control +inclusion or exclusion of certain BL stages from the FIP image. These flags +need to be defined in the platform makefile which will get included by the +build system. + +- **NEED_BL33** + By default, this flag is defined ``yes`` by the build system and ``BL33`` + build option should be supplied as a build option. The platform has the + option of excluding the BL33 image in the ``fip`` image by defining this flag + to ``no``. If any of the options ``EL3_PAYLOAD_BASE`` or ``PRELOADED_BL33_BASE`` + are used, this flag will be set to ``no`` automatically. + +Platform include paths +---------------------- + +Platforms are allowed to add more include paths to be passed to the compiler. +The ``PLAT_INCLUDES`` variable is used for this purpose. This is needed in +particular for the file ``platform_def.h``. + +Example: + +.. code:: c + + PLAT_INCLUDES += -Iinclude/plat/myplat/include + +C Library +--------- + +To avoid subtle toolchain behavioral dependencies, the header files provided +by the compiler are not used. The software is built with the ``-nostdinc`` flag +to ensure no headers are included from the toolchain inadvertently. Instead the +required headers are included in the TF-A source tree. The library only +contains those C library definitions required by the local implementation. If +more functionality is required, the needed library functions will need to be +added to the local implementation. + +Some C headers have been obtained from `FreeBSD`_ and `SCC`_, while others have +been written specifically for TF-A. Some implementation files have been obtained +from `FreeBSD`_, others have been written specifically for TF-A as well. The +files can be found in ``include/lib/libc`` and ``lib/libc``. + +SCC can be found in http://www.simple-cc.org/. A copy of the `FreeBSD`_ sources +can be obtained from http://github.com/freebsd/freebsd. + +Storage abstraction layer +------------------------- + +In order to improve platform independence and portability a storage abstraction +layer is used to load data from non-volatile platform storage. Currently +storage access is only required by BL1 and BL2 phases and performed inside the +``load_image()`` function in ``bl_common.c``. + +.. uml:: ../resources/diagrams/plantuml/io_framework_usage_overview.puml + +It is mandatory to implement at least one storage driver. For the Arm +development platforms the Firmware Image Package (FIP) driver is provided as +the default means to load data from storage (see :ref:`firmware_design_fip`). +The storage layer is described in the header file +``include/drivers/io/io_storage.h``. The implementation of the common library is +in ``drivers/io/io_storage.c`` and the driver files are located in +``drivers/io/``. + +.. uml:: ../resources/diagrams/plantuml/io_arm_class_diagram.puml + +Each IO driver must provide ``io_dev_*`` structures, as described in +``drivers/io/io_driver.h``. These are returned via a mandatory registration +function that is called on platform initialization. The semi-hosting driver +implementation in ``io_semihosting.c`` can be used as an example. + +Each platform should register devices and their drivers via the storage +abstraction layer. These drivers then need to be initialized by bootloader +phases as required in their respective ``blx_platform_setup()`` functions. + +.. uml:: ../resources/diagrams/plantuml/io_dev_registration.puml + +The storage abstraction layer provides mechanisms (``io_dev_init()``) to +initialize storage devices before IO operations are called. + +.. uml:: ../resources/diagrams/plantuml/io_dev_init_and_check.puml + +The basic operations supported by the layer +include ``open()``, ``close()``, ``read()``, ``write()``, ``size()`` and ``seek()``. +Drivers do not have to implement all operations, but each platform must +provide at least one driver for a device capable of supporting generic +operations such as loading a bootloader image. + +The current implementation only allows for known images to be loaded by the +firmware. These images are specified by using their identifiers, as defined in +``include/plat/common/common_def.h`` (or a separate header file included from +there). The platform layer (``plat_get_image_source()``) then returns a reference +to a device and a driver-specific ``spec`` which will be understood by the driver +to allow access to the image data. + +The layer is designed in such a way that is it possible to chain drivers with +other drivers. For example, file-system drivers may be implemented on top of +physical block devices, both represented by IO devices with corresponding +drivers. In such a case, the file-system "binding" with the block device may +be deferred until the file-system device is initialised. + +The abstraction currently depends on structures being statically allocated +by the drivers and callers, as the system does not yet provide a means of +dynamically allocating memory. This may also have the affect of limiting the +amount of open resources per driver. + +-------------- + +*Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.* + +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html +.. _3.0 (GICv3): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0069b/index.html +.. _FreeBSD: https://www.freebsd.org +.. _SCC: http://www.simple-cc.org/ diff --git a/arm-trusted-firmware/docs/getting_started/prerequisites.rst b/arm-trusted-firmware/docs/getting_started/prerequisites.rst new file mode 100644 index 0000000..ee30128 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/prerequisites.rst @@ -0,0 +1,169 @@ +Prerequisites +============= + +This document describes the software requirements for building |TF-A| for +AArch32 and AArch64 target platforms. + +It may possible to build |TF-A| with combinations of software packages that are +different from those listed below, however only the software described in this +document can be officially supported. + +Build Host +---------- + +|TF-A| can be built using either a Linux or a Windows machine as the build host. + +A relatively recent Linux distribution is recommended for building |TF-A|. We +have performed tests using Ubuntu 16.04 LTS (64-bit) but other distributions +should also work fine as a base, provided that the necessary tools and libraries +can be installed. + +.. _prerequisites_toolchain: + +Toolchain +--------- + +|TF-A| can be built with any of the following *cross-compiler* toolchains that +target the Armv7-A or Armv8-A architectures: + +- GCC >= 10.3-2021.07 (from the `Arm Developer website`_) +- Clang >= 4.0 +- Arm Compiler >= 6.0 + +In addition, a native compiler is required to build the supporting tools. + +.. note:: + The software has also been built on Windows 7 Enterprise SP1, using CMD.EXE, + Cygwin, and Msys (MinGW) shells, using version 5.3.1 of the GNU toolchain. + +.. note:: + For instructions on how to select the cross compiler refer to + :ref:`Performing an Initial Build`. + +.. _prerequisites_software_and_libraries: + +Software and Libraries +---------------------- + +The following tools are required to obtain and build |TF-A|: + +- An appropriate toolchain (see :ref:`prerequisites_toolchain`) +- GNU Make +- Git + +The following libraries must be available to build one or more components or +supporting tools: + +- OpenSSL >= 1.0.1 + + Required to build the cert_create tool. + +The following libraries are required for Trusted Board Boot support: + +- mbed TLS == 2.26.0 (tag: ``mbedtls-2.26.0``) + +These tools are optional: + +- Device Tree Compiler (DTC) >= 1.4.6 + + Needed if you want to rebuild the provided Flattened Device Tree (FDT) + source files (``.dts`` files). DTC is available for Linux through the package + repositories of most distributions. + +- Arm `Development Studio 5 (DS-5)`_ + + The standard software package used for debugging software on Arm development + platforms and |FVP| models. + +- Node.js >= 16 + + Highly recommended, and necessary in order to install and use the packaged + Git hooks and helper tools. Without these tools you will need to rely on the + CI for feedback on commit message conformance. + +Package Installation (Linux) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you are using the recommended Ubuntu distribution then you can install the +required packages with the following command: + +.. code:: shell + + sudo apt install build-essential git libssl-dev + +The optional packages can be installed using: + +.. code:: shell + + sudo apt install device-tree-compiler + +Additionally, to install an up-to-date version of Node.js, you can use the `Node +Version Manager`_ to install a version of your choosing (we recommend 16, but +later LTS versions might offer a more stable experience): + +.. code:: shell + + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | "$SHELL" + exec "$SHELL" -ic "nvm install 16; exec $SHELL" + +.. _Node Version Manager: https://github.com/nvm-sh/nvm#install--update-script + +Supporting Files +---------------- + +TF-A has been tested with pre-built binaries and file systems from `Linaro +Release 20.01`_. Alternatively, you can build the binaries from source using +instructions in :ref:`Performing an Initial Build`. + +.. _prerequisites_get_source: + +Getting the TF-A Source +----------------------- + +Source code for |TF-A| is maintained in a Git repository hosted on +TrustedFirmware.org. To clone this repository from the server, run the following +in your shell: + +.. code:: shell + + git clone "https://review.trustedfirmware.org/TF-A/trusted-firmware-a" + +Additional Steps for Contributors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you are planning on contributing back to TF-A, there are some things you'll +want to know. + +TF-A is hosted by a `Gerrit Code Review`_ server. Gerrit requires that all +commits include a ``Change-Id`` footer, and this footer is typically +automatically generated by a Git hook installed by you, the developer. + +If you have Node.js installed already, you can automatically install this hook, +along with any additional hooks and Javascript-based tooling that we use, by +running from within your newly-cloned repository: + +.. code:: shell + + npm install --no-save + +If you have opted **not** to install Node.js, you can install the Gerrit hook +manually by running: + +.. code:: shell + + curl -Lo $(git rev-parse --git-dir)/hooks/commit-msg https://review.trustedfirmware.org/tools/hooks/commit-msg + chmod +x $(git rev-parse --git-dir)/hooks/commit-msg + +You can read more about Git hooks in the *githooks* page of the Git +documentation, available `here `_. + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* + +.. _Arm Developer website: https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloads +.. _Gerrit Code Review: https://www.gerritcodereview.com/ +.. _Linaro Release Notes: https://community.arm.com/dev-platforms/w/docs/226/old-release-notes +.. _Linaro instructions: https://community.arm.com/dev-platforms/w/docs/304/arm-reference-platforms-deliverables +.. _Development Studio 5 (DS-5): https://developer.arm.com/products/software-development-tools/ds-5-development-studio +.. _Linaro Release 20.01: http://releases.linaro.org/members/arm/platforms/20.01 diff --git a/arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst b/arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst new file mode 100644 index 0000000..3735265 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst @@ -0,0 +1,546 @@ +PSCI Library Integration guide for Armv8-A AArch32 systems +========================================================== + +This document describes the PSCI library interface with a focus on how to +integrate with a suitable Trusted OS for an Armv8-A AArch32 system. The PSCI +Library implements the PSCI Standard as described in `PSCI spec`_ and is meant +to be integrated with EL3 Runtime Software which invokes the PSCI Library +interface appropriately. **EL3 Runtime Software** refers to software executing +at the highest secure privileged mode, which is EL3 in AArch64 or Secure SVC/ +Monitor mode in AArch32, and provides runtime services to the non-secure world. +The runtime service request is made via SMC (Secure Monitor Call) and the call +must adhere to `SMCCC`_. In AArch32, EL3 Runtime Software may additionally +include Trusted OS functionality. A minimal AArch32 Secure Payload, SP-MIN, is +provided in Trusted Firmware-A (TF-A) to illustrate the usage and integration +of the PSCI library. The description of PSCI library interface and its +integration with EL3 Runtime Software in this document is targeted towards +AArch32 systems. + +Generic call sequence for PSCI Library interface (AArch32) +---------------------------------------------------------- + +The generic call sequence of PSCI Library interfaces (see +`PSCI Library Interface`_) during cold boot in AArch32 +system is described below: + +#. After cold reset, the EL3 Runtime Software performs its cold boot + initialization including the PSCI library pre-requisites mentioned in + `PSCI Library Interface`_, and also the necessary platform + setup. + +#. Call ``psci_setup()`` in Monitor mode. + +#. Optionally call ``psci_register_spd_pm_hook()`` to register callbacks to + do bookkeeping for the EL3 Runtime Software during power management. + +#. Call ``psci_prepare_next_non_secure_ctx()`` to initialize the non-secure CPU + context. + +#. Get the non-secure ``cpu_context_t`` for the current CPU by calling + ``cm_get_context()`` , then programming the registers in the non-secure + context and exiting to non-secure world. If the EL3 Runtime Software needs + additional configuration to be set for non-secure context, like routing + FIQs to the secure world, the values of the registers can be modified prior + to programming. See `PSCI CPU context management`_ for more + details on CPU context management. + +The generic call sequence of PSCI library interfaces during warm boot in +AArch32 systems is described below: + +#. After warm reset, the EL3 Runtime Software performs the necessary warm + boot initialization including the PSCI library pre-requisites mentioned in + `PSCI Library Interface`_ (Note that the Data cache + **must not** be enabled). + +#. Call ``psci_warmboot_entrypoint()`` in Monitor mode. This interface + initializes/restores the non-secure CPU context as well. + +#. Do step 5 of the cold boot call sequence described above. + +The generic call sequence of PSCI library interfaces on receipt of a PSCI SMC +on an AArch32 system is described below: + +#. On receipt of an SMC, save the register context as per `SMCCC`_. + +#. If the SMC function identifier corresponds to a SMC32 PSCI API, construct + the appropriate arguments and call the ``psci_smc_handler()`` interface. + The invocation may or may not return back to the caller depending on + whether the PSCI API resulted in power down of the CPU. + +#. If ``psci_smc_handler()`` returns, populate the return value in R0 (AArch32)/ + X0 (AArch64) and restore other registers as per `SMCCC`_. + +PSCI CPU context management +--------------------------- + +PSCI library is in charge of initializing/restoring the non-secure CPU system +registers according to `PSCI specification`_ during cold/warm boot. +This is referred to as ``PSCI CPU Context Management``. Registers that need to +be preserved across CPU power down/power up cycles are maintained in +``cpu_context_t`` data structure. The initialization of other non-secure CPU +system registers which do not require coordination with the EL3 Runtime +Software is done directly by the PSCI library (see ``cm_prepare_el3_exit()``). + +The EL3 Runtime Software is responsible for managing register context +during switch between Normal and Secure worlds. The register context to be +saved and restored depends on the mechanism used to trigger the world switch. +For example, if the world switch was triggered by an SMC call, then the +registers need to be saved and restored according to `SMCCC`_. In AArch64, +due to the tight integration with BL31, both BL31 and PSCI library +use the same ``cpu_context_t`` data structure for PSCI CPU context management +and register context management during world switch. This cannot be assumed +for AArch32 EL3 Runtime Software since most AArch32 Trusted OSes already implement +a mechanism for register context management during world switch. Hence, when +the PSCI library is integrated with a AArch32 EL3 Runtime Software, the +``cpu_context_t`` is stripped down for just PSCI CPU context management. + +During cold/warm boot, after invoking appropriate PSCI library interfaces, it +is expected that the EL3 Runtime Software will query the ``cpu_context_t`` and +write appropriate values to the corresponding system registers. This mechanism +resolves 2 additional problems for AArch32 EL3 Runtime Software: + +#. Values for certain system registers like SCR and SCTLR cannot be + unilaterally determined by PSCI library and need inputs from the EL3 + Runtime Software. Using ``cpu_context_t`` as an intermediary data store + allows EL3 Runtime Software to modify the register values appropriately + before programming them. + +#. The PSCI library provides appropriate LR and SPSR values (entrypoint + information) for exit into non-secure world. Using ``cpu_context_t`` as an + intermediary data store allows the EL3 Runtime Software to store these + values safely until it is ready for exit to non-secure world. + +Currently the ``cpu_context_t`` data structure for AArch32 stores the following +registers: R0 - R3, LR (R14), SCR, SPSR, SCTLR. + +The EL3 Runtime Software must implement accessors to get/set pointers +to CPU context ``cpu_context_t`` data and these are described in +`CPU Context management API`_. + +PSCI Library Interface +---------------------- + +The PSCI library implements the `PSCI Specification`_. The interfaces +to this library are declared in ``psci_lib.h`` and are as listed below: + +.. code:: c + + 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); + 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); + +The CPU context data 'cpu_context_t' is programmed to the registers differently +when PSCI is integrated with an AArch32 EL3 Runtime Software compared to +when the PSCI is integrated with an AArch64 EL3 Runtime Software (BL31). For +example, in the case of AArch64, there is no need to retrieve ``cpu_context_t`` +data and program the registers as it will done implicitly as part of +``el3_exit``. The description below of the PSCI interfaces is targeted at +integration with an AArch32 EL3 Runtime Software. + +The PSCI library is responsible for initializing/restoring the non-secure world +to an appropriate state after boot and may choose to directly program the +non-secure system registers. The PSCI generic code takes care not to directly +modify any of the system registers affecting the secure world and instead +returns the values to be programmed to these registers via ``cpu_context_t``. +The EL3 Runtime Software is responsible for programming those registers and +can use the proposed values provided in the ``cpu_context_t``, modifying the +values if required. + +PSCI library needs the flexibility to access both secure and non-secure +copies of banked registers. Hence it needs to be invoked in Monitor mode +for AArch32 and in EL3 for AArch64. The NS bit in SCR (in AArch32) or SCR_EL3 +(in AArch64) must be set to 0. Additional requirements for the PSCI library +interfaces are: + +- Instruction cache must be enabled +- Both IRQ and FIQ must be masked for the current CPU +- The page tables must be setup and the MMU enabled +- The C runtime environment must be setup and stack initialized +- The Data cache must be enabled prior to invoking any of the PSCI library + interfaces except for ``psci_warmboot_entrypoint()``. For + ``psci_warmboot_entrypoint()``, if the build option ``HW_ASSISTED_COHERENCY`` + is enabled however, data caches are expected to be enabled. + +Further requirements for each interface can be found in the interface +description. + +Interface : psci_setup() +~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_lib_args_t *lib_args + Return : void + +This function is to be called by the primary CPU during cold boot before +any other interface to the PSCI library. It takes ``lib_args``, a const pointer +to ``psci_lib_args_t``, as the argument. The ``psci_lib_args_t`` is a versioned +structure and is declared in ``psci_lib.h`` header as follows: + +.. code:: c + + 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; + +The first field ``h``, of ``param_header_t`` type, provides the version +information. The second field ``mailbox_ep`` is the warm boot entrypoint address +and is used to configure the platform mailbox. Helper macros are provided in +``psci_lib.h`` to construct the ``lib_args`` argument statically or during +runtime. Prior to calling the ``psci_setup()`` interface, the platform setup for +cold boot must have completed. Major actions performed by this interface are: + +- Initializes architecture. +- Initializes PSCI power domain and state coordination data structures. +- Calls ``plat_setup_psci_ops()`` with warm boot entrypoint ``mailbox_ep`` as + argument. +- Calls ``cm_set_context_by_index()`` (see + `CPU Context management API`_) for all the CPUs in the + platform + +Interface : psci_prepare_next_non_secure_ctx() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : entry_point_info_t *next_image_info + Return : void + +After ``psci_setup()`` and prior to exit to the non-secure world, this function +must be called by the EL3 Runtime Software to initialize the non-secure world +context. The non-secure world entrypoint information ``next_image_info`` (first +argument) will be used to determine the non-secure context. After this function +returns, the EL3 Runtime Software must retrieve the ``cpu_context_t`` (using +cm_get_context()) for the current CPU and program the registers prior to exit +to the non-secure world. + +Interface : psci_register_spd_pm_hook() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const spd_pm_ops_t * + Return : void + +As explained in `Secure payload power management callback`_, +the EL3 Runtime Software may want to perform some bookkeeping during power +management operations. This function is used to register the ``spd_pm_ops_t`` +(first argument) callbacks with the PSCI library which will be called +appropriately during power management. Calling this function is optional and +need to be called by the primary CPU during the cold boot sequence after +``psci_setup()`` has completed. + +Interface : psci_smc_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : 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 + Return : u_register_t + +This function is the top level handler for SMCs which fall within the +PSCI service range specified in `SMCCC`_. The function ID ``smc_fid`` (first +argument) determines the PSCI API to be called. The ``x1`` to ``x4`` (2nd to 5th +arguments), are the values of the registers r1 - r4 (in AArch32) or x1 - x4 +(in AArch64) when the SMC is received. These are the arguments to PSCI API as +described in `PSCI spec`_. The 'flags' (8th argument) is a bit field parameter +and is detailed in 'smccc.h' header. It includes whether the call is from the +secure or non-secure world. The ``cookie`` (6th argument) and the ``handle`` +(7th argument) are not used and are reserved for future use. + +The return value from this interface is the return value from the underlying +PSCI API corresponding to ``smc_fid``. This function may not return back to the +caller if PSCI API causes power down of the CPU. In this case, when the CPU +wakes up, it will start execution from the warm reset address. + +Interface : psci_warmboot_entrypoint() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function performs the warm boot initialization/restoration as mandated by +`PSCI spec`_. For AArch32, on wakeup from power down the CPU resets to secure SVC +mode and the EL3 Runtime Software must perform the prerequisite initializations +mentioned at top of this section. This function must be called with Data cache +disabled (unless build option ``HW_ASSISTED_COHERENCY`` is enabled) but with MMU +initialized and enabled. The major actions performed by this function are: + +- Invalidates the stack and enables the data cache. +- Initializes architecture and PSCI state coordination. +- Restores/Initializes the peripheral drivers to the required state via + appropriate ``plat_psci_ops_t`` hooks +- Restores the EL3 Runtime Software context via appropriate ``spd_pm_ops_t`` + callbacks. +- Restores/Initializes the non-secure context and populates the + ``cpu_context_t`` for the current CPU. + +Upon the return of this function, the EL3 Runtime Software must retrieve the +non-secure ``cpu_context_t`` using ``cm_get_context()`` and program the registers +prior to exit to the non-secure world. + +EL3 Runtime Software dependencies +--------------------------------- + +The PSCI Library includes supporting frameworks like context management, +cpu operations (cpu_ops) and per-cpu data framework. Other helper library +functions like bakery locks and spin locks are also included in the library. +The dependencies which must be fulfilled by the EL3 Runtime Software +for integration with PSCI library are described below. + +General dependencies +~~~~~~~~~~~~~~~~~~~~ + +The PSCI library being a Multiprocessor (MP) implementation, EL3 Runtime +Software must provide an SMC handling framework capable of MP adhering to +`SMCCC`_ specification. + +The EL3 Runtime Software must also export cache maintenance primitives +and some helper utilities for assert, print and memory operations as listed +below. The TF-A source tree provides implementations for all +these functions but the EL3 Runtime Software may use its own implementation. + +**Functions : assert(), memcpy(), memset(), printf()** + +These must be implemented as described in ISO C Standard. + +**Function : flush_dcache_range()** + +:: + + Argument : uintptr_t addr, size_t size + Return : void + +This function cleans and invalidates (flushes) the data cache for memory +at address ``addr`` (first argument) address and of size ``size`` (second argument). + +**Function : inv_dcache_range()** + +:: + + Argument : uintptr_t addr, size_t size + Return : void + +This function invalidates (flushes) the data cache for memory at address +``addr`` (first argument) address and of size ``size`` (second argument). + +**Function : do_panic()** + +:: + + Argument : void + Return : void + +This function will be called by the PSCI library on encountering a critical +failure that cannot be recovered from. This function **must not** return. + +CPU Context management API +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The CPU context management data memory is statically allocated by PSCI library +in BSS section. The PSCI library requires the EL3 Runtime Software to implement +APIs to store and retrieve pointers to this CPU context data. SP-MIN +demonstrates how these APIs can be implemented but the EL3 Runtime Software can +choose a more optimal implementation (like dedicating the secure TPIDRPRW +system register (in AArch32) for storing these pointers). + +**Function : cm_set_context_by_index()** + +:: + + Argument : unsigned int cpu_idx, void *context, unsigned int security_state + Return : void + +This function is called during cold boot when the ``psci_setup()`` PSCI library +interface is called. + +This function must store the pointer to the CPU context data, ``context`` (2nd +argument), for the specified ``security_state`` (3rd argument) and CPU identified +by ``cpu_idx`` (first argument). The ``security_state`` will always be non-secure +when called by PSCI library and this argument is retained for compatibility +with BL31. The ``cpu_idx`` will correspond to the index returned by the +``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. + +The actual method of storing the ``context`` pointers is implementation specific. +For example, SP-MIN stores the pointers in the array ``sp_min_cpu_ctx_ptr`` +declared in ``sp_min_main.c``. + +**Function : cm_get_context()** + +:: + + Argument : uint32_t security_state + Return : void * + +This function must return the pointer to the ``cpu_context_t`` structure for +the specified ``security_state`` (first argument) for the current CPU. The caller +must ensure that ``cm_set_context_by_index`` is called first and the appropriate +context pointers are stored prior to invoking this API. The ``security_state`` +will always be non-secure when called by PSCI library and this argument +is retained for compatibility with BL31. + +**Function : cm_get_context_by_index()** + +:: + + Argument : unsigned int cpu_idx, unsigned int security_state + Return : void * + +This function must return the pointer to the ``cpu_context_t`` structure for +the specified ``security_state`` (second argument) for the CPU identified by +``cpu_idx`` (first argument). The caller must ensure that +``cm_set_context_by_index`` is called first and the appropriate context +pointers are stored prior to invoking this API. The ``security_state`` will +always be non-secure when called by PSCI library and this argument is +retained for compatibility with BL31. The ``cpu_idx`` will correspond to the +index returned by the ``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. + +Platform API +~~~~~~~~~~~~ + +The platform layer abstracts the platform-specific details from the generic +PSCI library. The following platform APIs/macros must be defined by the EL3 +Runtime Software for integration with the PSCI library. + +The mandatory platform APIs are: + +- plat_my_core_pos +- plat_core_pos_by_mpidr +- plat_get_syscnt_freq2 +- plat_get_power_domain_tree_desc +- plat_setup_psci_ops +- plat_reset_handler +- plat_panic_handler +- plat_get_my_stack + +The mandatory platform macros are: + +- PLATFORM_CORE_COUNT +- PLAT_MAX_PWR_LVL +- PLAT_NUM_PWR_DOMAINS +- CACHE_WRITEBACK_GRANULE +- PLAT_MAX_OFF_STATE +- PLAT_MAX_RET_STATE +- PLAT_MAX_PWR_LVL_STATES (optional) +- PLAT_PCPU_DATA_SIZE (optional) + +The details of these APIs/macros can be found in the :ref:`Porting Guide`. + +All platform specific operations for power management are done via +``plat_psci_ops_t`` callbacks registered by the platform when +``plat_setup_psci_ops()`` API is called. The description of each of +the callbacks in ``plat_psci_ops_t`` can be found in PSCI section of the +:ref:`Porting Guide`. If any these callbacks are not registered, then the +PSCI API associated with that callback will not be supported by PSCI +library. + +Secure payload power management callback +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +During PSCI power management operations, the EL3 Runtime Software may +need to perform some bookkeeping, and PSCI library provides +``spd_pm_ops_t`` callbacks for this purpose. These hooks must be +populated and registered by using ``psci_register_spd_pm_hook()`` PSCI +library interface. + +Typical bookkeeping during PSCI power management calls include save/restore +of the EL3 Runtime Software context. Also if the EL3 Runtime Software makes +use of secure interrupts, then these interrupts must also be managed +appropriately during CPU power down/power up. Any secure interrupt targeted +to the current CPU must be disabled or re-targeted to other running CPU prior +to power down of the current CPU. During power up, these interrupt can be +enabled/re-targeted back to the current CPU. + +.. code:: c + + typedef struct spd_pm_ops { + void (*svc_on)(u_register_t target_cpu); + int32_t (*svc_off)(u_register_t __unused); + void (*svc_suspend)(u_register_t max_off_pwrlvl); + void (*svc_on_finish)(u_register_t __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; + +A brief description of each callback is given below: + +- svc_on, svc_off, svc_on_finish + + The ``svc_on``, ``svc_off`` callbacks are called during PSCI_CPU_ON, + PSCI_CPU_OFF APIs respectively. The ``svc_on_finish`` is called when the + target CPU of PSCI_CPU_ON API powers up and executes the + ``psci_warmboot_entrypoint()`` PSCI library interface. + +- svc_suspend, svc_suspend_finish + + The ``svc_suspend`` callback is called during power down bu either + PSCI_SUSPEND or PSCI_SYSTEM_SUSPEND APIs. The ``svc_suspend_finish`` is + called when the CPU wakes up from suspend and executes the + ``psci_warmboot_entrypoint()`` PSCI library interface. The ``max_off_pwrlvl`` + (first parameter) denotes the highest power domain level being powered down + to or woken up from suspend. + +- svc_system_off, svc_system_reset + + These callbacks are called during PSCI_SYSTEM_OFF and PSCI_SYSTEM_RESET + PSCI APIs respectively. + +- svc_migrate_info + + This callback is called in response to PSCI_MIGRATE_INFO_TYPE or + PSCI_MIGRATE_INFO_UP_CPU APIs. The return value of this callback must + correspond to the return value of PSCI_MIGRATE_INFO_TYPE API as described + in `PSCI spec`_. If the secure payload is a Uniprocessor (UP) + implementation, then it must update the mpidr of the CPU it is resident in + via ``resident_cpu`` (first argument). The updates to ``resident_cpu`` is + ignored if the secure payload is a multiprocessor (MP) implementation. + +- svc_migrate + + This callback is only relevant if the secure payload in EL3 Runtime + Software is a Uniprocessor (UP) implementation and supports migration from + the current CPU ``from_cpu`` (first argument) to another CPU ``to_cpu`` + (second argument). This callback is called in response to PSCI_MIGRATE + API. This callback is never called if the secure payload is a + Multiprocessor (MP) implementation. + +CPU operations +~~~~~~~~~~~~~~ + +The CPU operations (cpu_ops) framework implement power down sequence specific +to the CPU and the details of which can be found at +:ref:`firmware_design_cpu_ops_fwk`. The TF-A tree implements the ``cpu_ops`` +for various supported CPUs and the EL3 Runtime Software needs to include the +required ``cpu_ops`` in its build. The start and end of the ``cpu_ops`` +descriptors must be exported by the EL3 Runtime Software via the +``__CPU_OPS_START__`` and ``__CPU_OPS_END__`` linker symbols. + +The ``cpu_ops`` descriptors also include reset sequences and may include errata +workarounds for the CPU. The EL3 Runtime Software can choose to call this +during cold/warm reset if it does not implement its own reset sequence/errata +workarounds. + +-------------- + +*Copyright (c) 2016-2020, Arm Limited and Contributors. All rights reserved.* + +.. _PSCI spec: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _SMCCC: https://developer.arm.com/docs/den0028/latest +.. _PSCI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _PSCI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf diff --git a/arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst b/arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst new file mode 100644 index 0000000..5a4be4d --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst @@ -0,0 +1,320 @@ +EL3 Runtime Service Writer's Guide +===================================================== + +Introduction +------------ + +This document describes how to add a runtime service to the EL3 Runtime +Firmware component of Trusted Firmware-A (TF-A), BL31. + +Software executing in the normal world and in the trusted world at exception +levels lower than EL3 will request runtime services using the Secure Monitor +Call (SMC) instruction. These requests will follow the convention described in +the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function +identifiers to each SMC request and describes how arguments are passed and +results are returned. + +SMC Functions are grouped together based on the implementor of the service, for +example a subset of the Function IDs are designated as "OEM Calls" (see `SMCCC`_ +for full details). The EL3 runtime services framework in BL31 enables the +independent implementation of services for each group, which are then compiled +into the BL31 image. This simplifies the integration of common software from +Arm to support `PSCI`_, Secure Monitor for a Trusted OS and SoC specific +software. The common runtime services framework ensures that SMC Functions are +dispatched to their respective service implementation - the +:ref:`Firmware Design` document provides details of how this is achieved. + +The interface and operation of the runtime services depends heavily on the +concepts and definitions described in the `SMCCC`_, in particular SMC Function +IDs, Owning Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and +SMC64 calling conventions. Please refer to that document for a full explanation +of these terms. + +Owning Entities, Call Types and Function IDs +-------------------------------------------- + +The SMC Function Identifier includes a OEN field. These values and their +meaning are described in `SMCCC`_ and summarized in table 1 below. Some entities +are allocated a range of of OENs. The OEN must be interpreted in conjunction +with the SMC call type, which is either *Fast* or *Yielding*. Fast calls are +uninterruptible whereas Yielding calls can be pre-empted. The majority of +Owning Entities only have allocated ranges for Fast calls: Yielding calls are +reserved exclusively for Trusted OS providers or for interoperability with +legacy 32-bit software that predates the `SMCCC`_. + +:: + + Type OEN Service + Fast 0 Arm Architecture calls + Fast 1 CPU Service calls + Fast 2 SiP Service calls + Fast 3 OEM Service calls + Fast 4 Standard Service calls + Fast 5-47 Reserved for future use + Fast 48-49 Trusted Application calls + Fast 50-63 Trusted OS calls + + Yielding 0- 1 Reserved for existing Armv7-A calls + Yielding 2-63 Trusted OS Standard Calls + +*Table 1: Service types and their corresponding Owning Entity Numbers* + +Each individual entity can allocate the valid identifiers within the entity +range as they need - it is not necessary to coordinate with other entities of +the same type. For example, two SoC providers can use the same Function ID +within the SiP Service calls OEN range to mean different things - as these +calls should be specific to the SoC. The Standard Runtime Calls OEN is used for +services defined by Arm standards, such as `PSCI`_. + +The SMC Function ID also indicates whether the call has followed the SMC32 +calling convention, where all parameters are 32-bit, or the SMC64 calling +convention, where the parameters are 64-bit. The framework identifies and +rejects invalid calls that use the SMC64 calling convention but that originate +from an AArch32 caller. + +The EL3 runtime services framework uses the call type and OEN to identify a +specific handler for each SMC call, but it is expected that an individual +handler will be responsible for all SMC Functions within a given service type. + +Getting started +--------------- + +TF-A has a ``services`` directory in the source tree under which +each owning entity can place the implementation of its runtime service. The +`PSCI`_ implementation is located here in the ``lib/psci`` directory. + +Runtime service sources will need to include the ``runtime_svc.h`` header file. + +Registering a runtime service +----------------------------- + +A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying +the name of the service, the range of OENs covered, the type of service and +initialization and call handler functions. + +.. code:: c + + #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) + +- ``_name`` is used to identify the data structure declared by this macro, and + is also used for diagnostic purposes + +- ``_start`` and ``_end`` values must be based on the ``OEN_*`` values defined in + ``smccc.h`` + +- ``_type`` must be one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` + +- ``_setup`` is the initialization function with the ``rt_svc_init`` signature: + + .. code:: c + + typedef int32_t (*rt_svc_init)(void); + +- ``_smch`` is the SMC handler function with the ``rt_svc_handle`` signature: + + .. code:: c + + 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); + +Details of the requirements and behavior of the two callbacks is provided in +the following sections. + +During initialization the services framework validates each declared service +to ensure that the following conditions are met: + +#. The ``_start`` OEN is not greater than the ``_end`` OEN +#. The ``_end`` OEN does not exceed the maximum OEN value (63) +#. The ``_type`` is one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` +#. ``_setup`` and ``_smch`` routines have been specified + +``std_svc_setup.c`` provides an example of registering a runtime service: + +.. code:: c + + /* Register Standard Service Calls as runtime service */ + DECLARE_RT_SVC( + std_svc, + OEN_STD_START, + OEN_STD_END, + SMC_TYPE_FAST, + std_svc_setup, + std_svc_smc_handler + ); + +Initializing a runtime service +------------------------------ + +Runtime services are initialized once, during cold boot, by the primary CPU +after platform and architectural initialization is complete. The framework +performs basic validation of the declared service before calling +the service initialization function (``_setup`` in the declaration). This +function must carry out any essential EL3 initialization prior to receiving a +SMC Function call via the handler function. + +On success, the initialization function must return ``0``. Any other return value +will cause the framework to issue a diagnostic: + +:: + + Error initializing runtime service + +and then ignore the service - the system will continue to boot but SMC calls +will not be passed to the service handler and instead return the *Unknown SMC +Function ID* result ``0xFFFFFFFF``. + +If the system must not be allowed to proceed without the service, the +initialization function must itself cause the firmware boot to be halted. + +If the service uses per-CPU data this must either be initialized for all CPUs +during this call, or be done lazily when a CPU first issues an SMC call to that +service. + +Handling runtime service requests +--------------------------------- + +SMC calls for a service are forwarded by the framework to the service's SMC +handler function (``_smch`` in the service declaration). This function must have +the following signature: + +.. code:: c + + 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); + +The handler is responsible for: + +#. Determining that ``smc_fid`` is a valid and supported SMC Function ID, + otherwise completing the request with the *Unknown SMC Function ID*: + + .. code:: c + + SMC_RET1(handle, SMC_UNK); + +#. Determining if the requested function is valid for the calling security + state. SMC Calls can be made from Non-secure, Secure or Realm worlds and + the framework will forward all calls to the service handler. + + The ``flags`` parameter to this function indicates the caller security state + in bits 0 and 5. The ``is_caller_secure(flags)``, ``is_caller_non_secure(flags)`` + and ``is_caller_realm(flags)`` helper functions can be used to determine whether + the caller's security state is Secure, Non-secure or Realm respectively. + + If invalid, the request should be completed with: + + .. code:: c + + SMC_RET1(handle, SMC_UNK); + +#. Truncating parameters for calls made using the SMC32 calling convention. + Such calls can be determined by checking the CC field in bit[30] of the + ``smc_fid`` parameter, for example by using: + + :: + + if (GET_SMC_CC(smc_fid) == SMC_32) ... + + For such calls, the upper bits of the parameters x1-x4 and the saved + parameters X5-X7 are UNDEFINED and must be explicitly ignored by the + handler. This can be done by truncating the values to a suitable 32-bit + integer type before use, for example by ensuring that functions defined + to handle individual SMC Functions use appropriate 32-bit parameters. + +#. Providing the service requested by the SMC Function, utilizing the + immediate parameters x1-x4 and/or the additional saved parameters X5-X7. + The latter can be retrieved using the ``SMC_GET_GP(handle, ref)`` function, + supplying the appropriate ``CTX_GPREG_Xn`` reference, e.g. + + .. code:: c + + uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6); + +#. Implementing the standard SMC32 Functions that provide information about + the implementation of the service. These are the Call Count, Implementor + UID and Revision Details for each service documented in section 6 of the + `SMCCC`_. + + TF-A expects owning entities to follow this recommendation. + +#. Returning the result to the caller. Based on `SMCCC`_ spec, results are + returned in W0-W7(X0-X7) registers for SMC32(SMC64) calls from AArch64 + state. Results are returned in R0-R7 registers for SMC32 calls from AArch32 + state. The framework provides a family of macros to set the multi-register + return value and complete the handler: + + .. code:: c + + AArch64 state: + + SMC_RET1(handle, x0); + SMC_RET2(handle, x0, x1); + SMC_RET3(handle, x0, x1, x2); + SMC_RET4(handle, x0, x1, x2, x3); + SMC_RET5(handle, x0, x1, x2, x3, x4); + SMC_RET6(handle, x0, x1, x2, x3, x4, x5); + SMC_RET7(handle, x0, x1, x2, x3, x4, x5, x6); + SMC_RET8(handle, x0, x1, x2, x3, x4, x5, x6, x7); + + AArch32 state: + + SMC_RET1(handle, r0); + SMC_RET2(handle, r0, r1); + SMC_RET3(handle, r0, r1, r2); + SMC_RET4(handle, r0, r1, r2, r3); + SMC_RET5(handle, r0, r1, r2, r3, r4); + SMC_RET6(handle, r0, r1, r2, r3, r4, r5); + SMC_RET7(handle, r0, r1, r2, r3, r4, r5, r6); + SMC_RET8(handle, r0, r1, r2, r3, r4, r5, r6, r7); + +The ``cookie`` parameter to the handler is reserved for future use and can be +ignored. The ``handle`` is returned by the SMC handler - completion of the +handler function must always be via one of the ``SMC_RETn()`` macros. + +.. note:: + The PSCI and Test Secure-EL1 Payload Dispatcher services do not follow + all of the above requirements yet. + +Services that contain multiple sub-services +------------------------------------------- + +It is possible that a single owning entity implements multiple sub-services. For +example, the Standard calls service handles ``0x84000000``-``0x8400FFFF`` and +``0xC4000000``-``0xC400FFFF`` functions. Within that range, the `PSCI`_ service +handles the ``0x84000000``-``0x8400001F`` and ``0xC4000000``-``0xC400001F`` functions. +In that respect, `PSCI`_ is a 'sub-service' of the Standard calls service. In +future, there could be additional such sub-services in the Standard calls +service which perform independent functions. + +In this situation it may be valuable to introduce a second level framework to +enable independent implementation of sub-services. Such a framework might look +very similar to the current runtime services framework, but using a different +part of the SMC Function ID to identify the sub-service. TF-A does not provide +such a framework at present. + +Secure-EL1 Payload Dispatcher service (SPD) +------------------------------------------- + +Services that handle SMC Functions targeting a Trusted OS, Trusted Application, +or other Secure-EL1 Payload are special. These services need to manage the +Secure-EL1 context, provide the *Secure Monitor* functionality of switching +between the normal and secure worlds, deliver SMC Calls through to Secure-EL1 +and generally manage the Secure-EL1 Payload through CPU power-state transitions. + +TODO: Provide details of the additional work required to implement a SPD and +the BL31 support for these services. Or a reference to the document that will +provide this information.... + +-------------- + +*Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.* + +.. _SMCCC: https://developer.arm.com/docs/den0028/latest +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf diff --git a/arm-trusted-firmware/docs/getting_started/tools-build.rst b/arm-trusted-firmware/docs/getting_started/tools-build.rst new file mode 100644 index 0000000..c050f58 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/tools-build.rst @@ -0,0 +1,167 @@ +Building Supporting Tools +========================= + +Building and using the FIP tool +------------------------------- + +Firmware Image Package (FIP) is a packaging format used by TF-A to package +firmware images in a single binary. The number and type of images that should +be packed in a FIP is platform specific and may include TF-A images and other +firmware images required by the platform. For example, most platforms require +a BL33 image which corresponds to the normal world bootloader (e.g. UEFI or +U-Boot). + +The TF-A build system provides the make target ``fip`` to create a FIP file +for the specified platform using the FIP creation tool included in the TF-A +project. Examples below show how to build a FIP file for FVP, packaging TF-A +and BL33 images. + +For AArch64: + +.. code:: shell + + make PLAT=fvp BL33=/bl33.bin fip + +For AArch32: + +.. code:: shell + + make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=/bl33.bin fip + +The resulting FIP may be found in: + +:: + + build/fvp//fip.bin + +For advanced operations on FIP files, it is also possible to independently build +the tool and create or modify FIPs using this tool. To do this, follow these +steps: + +It is recommended to remove old artifacts before building the tool: + +.. code:: shell + + make -C tools/fiptool clean + +Build the tool: + +.. code:: shell + + make [DEBUG=1] [V=1] fiptool + +The tool binary can be located in: + +:: + + ./tools/fiptool/fiptool + +Invoking the tool with ``help`` will print a help message with all available +options. + +Example 1: create a new Firmware package ``fip.bin`` that contains BL2 and BL31: + +.. code:: shell + + ./tools/fiptool/fiptool create \ + --tb-fw build///bl2.bin \ + --soc-fw build///bl31.bin \ + fip.bin + +Example 2: view the contents of an existing Firmware package: + +.. code:: shell + + ./tools/fiptool/fiptool info /fip.bin + +Example 3: update the entries of an existing Firmware package: + +.. code:: shell + + # Change the BL2 from Debug to Release version + ./tools/fiptool/fiptool update \ + --tb-fw build//release/bl2.bin \ + build//debug/fip.bin + +Example 4: unpack all entries from an existing Firmware package: + +.. code:: shell + + # Images will be unpacked to the working directory + ./tools/fiptool/fiptool unpack /fip.bin + +Example 5: remove an entry from an existing Firmware package: + +.. code:: shell + + ./tools/fiptool/fiptool remove \ + --tb-fw build//debug/fip.bin + +Note that if the destination FIP file exists, the create, update and +remove operations will automatically overwrite it. + +The unpack operation will fail if the images already exist at the +destination. In that case, use -f or --force to continue. + +More information about FIP can be found in the :ref:`Firmware Design` document. + +.. _tools_build_cert_create: + +Building the Certificate Generation Tool +---------------------------------------- + +The ``cert_create`` tool is built as part of the TF-A build process when the +``fip`` make target is specified and TBB is enabled (as described in the +previous section), but it can also be built separately with the following +command: + +.. code:: shell + + make PLAT= [DEBUG=1] [V=1] certtool + +For platforms that require their own IDs in certificate files, the generic +'cert_create' tool can be built with the following command. Note that the target +platform must define its IDs within a ``platform_oid.h`` header file for the +build to succeed. + +.. code:: shell + + make PLAT= USE_TBBR_DEFS=0 [DEBUG=1] [V=1] certtool + +``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more +verbose. The following command should be used to obtain help about the tool: + +.. code:: shell + + ./tools/cert_create/cert_create -h + +.. _tools_build_enctool: + +Building the Firmware Encryption Tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``encrypt_fw`` tool is built as part of the TF-A build process when the +``fip`` make target is specified, DECRYPTION_SUPPORT and TBB are enabled, but +it can also be built separately with the following command: + +.. code:: shell + + make PLAT= [DEBUG=1] [V=1] enctool + +``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more +verbose. The following command should be used to obtain help about the tool: + +.. code:: shell + + ./tools/encrypt_fw/encrypt_fw -h + +Note that the enctool in its current implementation only supports encryption +key to be provided in plain format. A typical implementation can very well +extend this tool to support custom techniques to protect encryption key. + +Also, a user may choose to provide encryption key or nonce as an input file +via using ``cat `` instead of a hex string. + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/global_substitutions.txt b/arm-trusted-firmware/docs/global_substitutions.txt new file mode 100644 index 0000000..0cf2946 --- /dev/null +++ b/arm-trusted-firmware/docs/global_substitutions.txt @@ -0,0 +1,68 @@ +.. |AArch32| replace:: :term:`AArch32` +.. |AArch64| replace:: :term:`AArch64` +.. |AMU| replace:: :term:`AMU` +.. |AMUs| replace:: :term:`AMUs ` +.. |API| replace:: :term:`API` +.. |BTI| replace:: :term:`BTI` +.. |CoT| replace:: :term:`CoT` +.. |COT| replace:: :term:`COT` +.. |CSS| replace:: :term:`CSS` +.. |CVE| replace:: :term:`CVE` +.. |DTB| replace:: :term:`DTB` +.. |DS-5| replace:: :term:`DS-5` +.. |DSU| replace:: :term:`DSU` +.. |DT| replace:: :term:`DT` +.. |EL| replace:: :term:`EL` +.. |EHF| replace:: :term:`EHF` +.. |FCONF| replace:: :term:`FCONF` +.. |FDT| replace:: :term:`FDT` +.. |FF-A| replace:: :term:`FF-A` +.. |FIP| replace:: :term:`FIP` +.. |FVP| replace:: :term:`FVP` +.. |FWU| replace:: :term:`FWU` +.. |GIC| replace:: :term:`GIC` +.. |ISA| replace:: :term:`ISA` +.. |Linaro| replace:: :term:`Linaro` +.. |MMU| replace:: :term:`MMU` +.. |MPAM| replace:: :term:`MPAM` +.. |MPMM| replace:: :term:`MPMM` +.. |MPIDR| replace:: :term:`MPIDR` +.. |MTE| replace:: :term:`MTE` +.. |OEN| replace:: :term:`OEN` +.. |OP-TEE| replace:: :term:`OP-TEE` +.. |OTE| replace:: :term:`OTE` +.. |PDD| replace:: :term:`PDD` +.. |PAUTH| replace:: :term:`PAUTH` +.. |PMF| replace:: :term:`PMF` +.. |PSCI| replace:: :term:`PSCI` +.. |RAS| replace:: :term:`RAS` +.. |ROT| replace:: :term:`ROT` +.. |SCMI| replace:: :term:`SCMI` +.. |SCP| replace:: :term:`SCP` +.. |SDEI| replace:: :term:`SDEI` +.. |SDS| replace:: :term:`SDS` +.. |SEA| replace:: :term:`SEA` +.. |SiP| replace:: :term:`SiP` +.. |SIP| replace:: :term:`SIP` +.. |SMC| replace:: :term:`SMC` +.. |SMCCC| replace:: :term:`SMCCC` +.. |SoC| replace:: :term:`SoC` +.. |SP| replace:: :term:`SP` +.. |SPD| replace:: :term:`SPD` +.. |SPM| replace:: :term:`SPM` +.. |SSBS| replace:: :term:`SSBS` +.. |SVE| replace:: :term:`SVE` +.. |TBB| replace:: :term:`TBB` +.. |TBBR| replace:: :term:`TBBR` +.. |TEE| replace:: :term:`TEE` +.. |TF-A| replace:: :term:`TF-A` +.. |TF-M| replace:: :term:`TF-M` +.. |TLB| replace:: :term:`TLB` +.. |TLK| replace:: :term:`TLK` +.. |TRNG| replace:: :term:`TRNG` +.. |TSP| replace:: :term:`TSP` +.. |TZC| replace:: :term:`TZC` +.. |UBSAN| replace:: :term:`UBSAN` +.. |UEFI| replace:: :term:`UEFI` +.. |WDOG| replace:: :term:`WDOG` +.. |XLAT| replace:: :term:`XLAT` diff --git a/arm-trusted-firmware/docs/glossary.rst b/arm-trusted-firmware/docs/glossary.rst new file mode 100644 index 0000000..aeeb133 --- /dev/null +++ b/arm-trusted-firmware/docs/glossary.rst @@ -0,0 +1,225 @@ +Glossary +======== + +This glossary provides definitions for terms and abbreviations used in the TF-A +documentation. + +You can find additional definitions in the `Arm Glossary`_. + +.. glossary:: + :sorted: + + AArch32 + 32-bit execution state of the ARMv8 ISA + + AArch64 + 64-bit execution state of the ARMv8 ISA + + AMU + Activity Monitor Unit, a hardware monitoring unit introduced by FEAT_AMUv1 + that exposes CPU core runtime metrics as a set of counter registers. + + API + Application Programming Interface + + AT + Address Translation + + BTI + Branch Target Identification. An Armv8.5 extension providing additional + control flow integrity around indirect branches and their targets. + + CoT + COT + Chain of Trust + + CSS + Compute Sub-System + + CVE + Common Vulnerabilities and Exposures. A CVE document is commonly used to + describe a publicly-known security vulnerability. + + DS-5 + Arm Development Studio 5 + + DSU + DynamIQ Shared Unit + + DT + Device Tree + + DTB + Device Tree Blob + + EL + Exception Level + + EHF + Exception Handling Framework + + FCONF + Firmware Configuration Framework + + FDT + Flattened Device Tree + + FF-A + Firmware Framework for Arm A-profile + + FIP + Firmware Image Package + + FVP + Fixed Virtual Platform + + FWU + FirmWare Update + + GIC + Generic Interrupt Controller + + ISA + Instruction Set Architecture + + Linaro + A collaborative engineering organization consolidating + and optimizing open source software and tools for the Arm architecture. + + MMU + Memory Management Unit + + MPAM + Memory Partitioning And Monitoring. An optional Armv8.4 extension. + + MPMM + Maximum Power Mitigation Mechanism, an optional power management mechanism + supported by some Arm Armv9-A cores. + + MPIDR + Multiprocessor Affinity Register + + MTE + Memory Tagging Extension. An optional Armv8.5 extension that enables + hardware-assisted memory tagging. + + OEN + Owning Entity Number + + OP-TEE + Open Portable Trusted Execution Environment. An example of a :term:`TEE` + + OTE + Open-source Trusted Execution Environment + + PDD + Platform Design Document + + PAUTH + Pointer Authentication. An optional extension introduced in Armv8.3. + + PMF + Performance Measurement Framework + + PSA + Platform Security Architecture + + PSCI + Power State Coordination Interface + + RAS + Reliability, Availability, and Serviceability extensions. A mandatory + extension for the Armv8.2 architecture and later. An optional extension to + the base Armv8 architecture. + + ROT + Root of Trust + + SCMI + System Control and Management Interface + + SCP + System Control Processor + + SDEI + Software Delegated Exception Interface + + SDS + Shared Data Storage + + SEA + Synchronous External Abort + + SiP + SIP + Silicon Provider + + SMC + Secure Monitor Call + + SMCCC + :term:`SMC` Calling Convention + + SoC + System on Chip + + SP + Secure Partition + + SPD + Secure Payload Dispatcher + + SPM + Secure Partition Manager + + SSBS + Speculative Store Bypass Safe. Introduced in Armv8.5, this configuration + bit can be set by software to allow or prevent the hardware from + performing speculative operations. + + SVE + Scalable Vector Extension + + TBB + Trusted Board Boot + + TBBR + Trusted Board Boot Requirements + + TEE + Trusted Execution Environment + + TF-A + Trusted Firmware-A + + TF-M + Trusted Firmware-M + + TLB + Translation Lookaside Buffer + + TLK + Trusted Little Kernel. A Trusted OS from NVIDIA. + + TRNG + True Randon Number Generator (hardware based) + + TSP + Test Secure Payload + + TZC + TrustZone Controller + + UBSAN + Undefined Behavior Sanitizer + + UEFI + Unified Extensible Firmware Interface + + WDOG + Watchdog + + XLAT + Translation (abbr.). For example, "XLAT table". + +.. _`Arm Glossary`: https://developer.arm.com/support/arm-glossary diff --git a/arm-trusted-firmware/docs/index.rst b/arm-trusted-firmware/docs/index.rst new file mode 100644 index 0000000..edc2535 --- /dev/null +++ b/arm-trusted-firmware/docs/index.rst @@ -0,0 +1,96 @@ +Trusted Firmware-A Documentation +================================ + +.. toctree:: + :maxdepth: 1 + :hidden: + + Home + about/index + getting_started/index + process/index + components/index + design/index + plat/index + perf/index + security_advisories/index + design_documents/index + threat_model/index + change-log + glossary + license + +Trusted Firmware-A (TF-A) provides a reference implementation of secure world +software for `Armv7-A and Armv8-A`_, including a `Secure Monitor`_ executing +at Exception Level 3 (EL3). It implements various Arm interface standards, +such as: + +- The `Power State Coordination Interface (PSCI)`_ +- `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)`_ +- `SMC Calling Convention`_ +- `System Control and Management Interface (SCMI)`_ +- `Software Delegated Exception Interface (SDEI)`_ +- `PSA FW update specification`_ + +Where possible, the code is designed for reuse or porting to other Armv7-A and +Armv8-A model and hardware platforms. + +This release provides a suitable starting point for productization of secure +world boot and runtime firmware, in either the AArch32 or AArch64 execution +states. + +Users are encouraged to do their own security validation, including penetration +testing, on any secure world code derived from TF-A. + +In collaboration with interested parties, we will continue to enhance |TF-A| +with reference implementations of Arm standards to benefit developers working +with Armv7-A and Armv8-A TrustZone technology. + +Getting Started +--------------- + +The |TF-A| documentation contains guidance for obtaining and building the +software for existing, supported platforms, as well as supporting information +for porting the software to a new platform. + +The **About** chapter gives a high-level overview of |TF-A| features as well as +some information on the project and how it is organized. + +Refer to the documents in the **Getting Started** chapter for information about +the prerequisites and requirements for building |TF-A|. + +The **Processes & Policies** chapter explains the project's release schedule +and process, how security disclosures are handled, and the guidelines for +contributing to the project (including the coding style). + +The **Components** chapter holds documents that explain specific components +that make up the |TF-A| software, the :ref:`Exception Handling Framework`, for +example. + +In the **System Design** chapter you will find documents that explain the +design of portions of the software that involve more than one component, such +as the :ref:`Trusted Board Boot` process. + +**Platform Ports** provides a list of the supported hardware and software-model +platforms that are supported upstream in |TF-A|. Most of these platforms also +have additional documentation that has been provided by the maintainers of the +platform. + +The results of any performance evaluations are added to the +**Performance & Testing** chapter. + +**Security Advisories** holds a list of documents relating to |CVE| entries that +have previously been raised against the software. + +-------------- + +*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.* + +.. _Armv7-A and Armv8-A: https://developer.arm.com/products/architecture/a-profile +.. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php +.. _Power State Coordination Interface (PSCI): http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a +.. _System Control and Management Interface (SCMI): http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/DEN0056A_System_Control_and_Management_Interface.pdf +.. _Software Delegated Exception Interface (SDEI): http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _PSA FW update specification: https://developer.arm.com/documentation/den0118/a/ diff --git a/arm-trusted-firmware/docs/license.rst b/arm-trusted-firmware/docs/license.rst new file mode 100644 index 0000000..80f1118 --- /dev/null +++ b/arm-trusted-firmware/docs/license.rst @@ -0,0 +1,90 @@ +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`` + - ``include/dt-bindings/interrupt-controller/irq.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/arm-trusted-firmware/docs/perf/index.rst b/arm-trusted-firmware/docs/perf/index.rst new file mode 100644 index 0000000..1482b80 --- /dev/null +++ b/arm-trusted-firmware/docs/perf/index.rst @@ -0,0 +1,15 @@ +Performance & Testing +===================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + psci-performance-juno + tsp + performance-monitoring-unit + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst b/arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst new file mode 100644 index 0000000..5dd1af5 --- /dev/null +++ b/arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst @@ -0,0 +1,158 @@ +Performance Monitoring Unit +=========================== + +The Performance Monitoring Unit (PMU) allows recording of architectural and +microarchitectural events for profiling purposes. + +This document gives an overview of the PMU counter configuration to assist with +implementation and to complement the PMU security guidelines given in the +:ref:`Secure Development Guidelines` document. + +.. note:: + This section applies to Armv8-A implementations which have version 3 + of the Performance Monitors Extension (PMUv3). + +PMU Counters +------------ + +The PMU makes 32 counters available at all privilege levels: + +- 31 programmable event counters: ``PMEVCNTR``, where ``n`` is ``0`` to + ``30``. +- A dedicated cycle counter: ``PMCCNTR``. + +Architectural mappings +~~~~~~~~~~~~~~~~~~~~~~ + ++--------------+---------+----------------------------+ +| Counters | State | System Register Name | ++==============+=========+============================+ +| | AArch64 | ``PMEVCNTR_EL0[63*:0]`` | +| Programmable +---------+----------------------------+ +| | AArch32 | ``PMEVCNTR[31:0]`` | ++--------------+---------+----------------------------+ +| | AArch64 | ``PMCCNTR_EL0[63:0]`` | +| Cycle +---------+----------------------------+ +| | AArch32 | ``PMCCNTR[63:0]`` | ++--------------+---------+----------------------------+ + +.. note:: + Bits [63:32] are only available if ARMv8.5-PMU is implemented. Refer to the + `Arm ARM`_ for a detailed description of ARMv8.5-PMU features. + +Configuring the PMU for counting events +--------------------------------------- + +Each programmable counter has an associated register, ``PMEVTYPER`` which +configures it. The cycle counter has the ``PMCCFILTR_EL0`` register, which has +an identical function and bit field layout as ``PMEVTYPER``. In addition, +the counters are enabled (permitted to increment) via the ``PMCNTENSET`` and +``PMCR`` registers. These can be accessed at all privilege levels. + +Architectural mappings +~~~~~~~~~~~~~~~~~~~~~~ + ++-----------------------------+------------------------+ +| AArch64 | AArch32 | ++=============================+========================+ +| ``PMEVTYPER_EL0[63*:0]`` | ``PMEVTYPER[31:0]`` | ++-----------------------------+------------------------+ +| ``PMCCFILTR_EL0[63*:0]`` | ``PMCCFILTR[31:0]`` | ++-----------------------------+------------------------+ +| ``PMCNTENSET_EL0[63*:0]`` | ``PMCNTENSET[31:0]`` | ++-----------------------------+------------------------+ +| ``PMCR_EL0[63*:0]`` | ``PMCR[31:0]`` | ++-----------------------------+------------------------+ + +.. note:: + Bits [63:32] are reserved. + +Relevant register fields +~~~~~~~~~~~~~~~~~~~~~~~~ + +For ``PMEVTYPER_EL0``/``PMEVTYPER`` and ``PMCCFILTR_EL0/PMCCFILTR``, the +most important fields are: + +- ``P``: + + - Bit 31. + - If set to ``0``, will increment the associated ``PMEVCNTR`` at EL1. + +- ``NSK``: + + - Bit 29. + - If equal to the ``P`` bit it enables the associated ``PMEVCNTR`` at + Non-secure EL1. + - Reserved if EL3 not implemented. + +- ``NSH``: + + - Bit 27. + - If set to ``1``, will increment the associated ``PMEVCNTR`` at EL2. + - Reserved if EL2 not implemented. + +- ``SH``: + + - Bit 24. + - If different to the ``NSH`` bit it enables the associated ``PMEVCNTR`` + at Secure EL2. + - Reserved if Secure EL2 not implemented. + +- ``M``: + + - Bit 26. + - If equal to the ``P`` bit it enables the associated ``PMEVCNTR`` at + EL3. + +- ``evtCount[15:10]``: + + - Extension to ``evtCount[9:0]``. Reserved unless ARMv8.1-PMU implemented. + +- ``evtCount[9:0]``: + + - The event number that the associated ``PMEVCNTR`` will count. + +For ``PMCNTENSET_EL0``/``PMCNTENSET``, the most important fields are: + +- ``P[30:0]``: + + - Setting bit ``P[n]`` to ``1`` enables counter ``PMEVCNTR``. + - The effects of ``PMEVTYPER`` are applied on top of this. + In other words, the counter will not increment at any privilege level or + security state unless it is enabled here. + +- ``C``: + + - Bit 31. + - If set to ``1`` enables the cycle counter ``PMCCNTR``. + +For ``PMCR``/``PMCR_EL0``, the most important fields are: + +- ``DP``: + + - Bit 5. + - If set to ``1`` it disables the cycle counter ``PMCCNTR`` where event + counting (by ``PMEVCNTR``) is prohibited (e.g. EL2 and the Secure + world). + - If set to ``0``, ``PMCCNTR`` will not be affected by this bit and + therefore will be able to count where the programmable counters are + prohibited. + +- ``E``: + + - Bit 0. + - Enables/disables counting altogether. + - The effects of ``PMCNTENSET`` and ``PMCR.DP`` are applied on top of this. + In other words, if this bit is ``0`` then no counters will increment + regardless of how the other PMU system registers or bit fields are + configured. + +.. rubric:: References + +- `Arm ARM`_ + +-------------- + +*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.* + +.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest diff --git a/arm-trusted-firmware/docs/perf/psci-performance-juno.rst b/arm-trusted-firmware/docs/perf/psci-performance-juno.rst new file mode 100644 index 0000000..eab3e4d --- /dev/null +++ b/arm-trusted-firmware/docs/perf/psci-performance-juno.rst @@ -0,0 +1,292 @@ +PSCI Performance Measurements on Arm Juno Development Platform +============================================================== + +This document summarises the findings of performance measurements of key +operations in the Trusted Firmware-A Power State Coordination Interface (PSCI) +implementation, using the in-built Performance Measurement Framework (PMF) and +runtime instrumentation timestamps. + +Method +------ + +We used the `Juno R1 platform`_ for these tests, which has 4 x Cortex-A53 and 2 +x Cortex-A57 clusters running at the following frequencies: + ++-----------------+--------------------+ +| Domain | Frequency (MHz) | ++=================+====================+ +| Cortex-A57 | 900 (nominal) | ++-----------------+--------------------+ +| Cortex-A53 | 650 (underdrive) | ++-----------------+--------------------+ +| AXI subsystem | 533 | ++-----------------+--------------------+ + +Juno supports CPU, cluster and system power down states, corresponding to power +levels 0, 1 and 2 respectively. It does not support any retention states. + +We used the upstream `TF master as of 31/01/2017`_, building the platform using +the ``ENABLE_RUNTIME_INSTRUMENTATION`` option: + +.. code:: shell + + make PLAT=juno ENABLE_RUNTIME_INSTRUMENTATION=1 \ + SCP_BL2= \ + BL33= \ + all fip + +When using the debug build of TF, there was no noticeable difference in the +results. + +The tests are based on an ARM-internal test framework. The release build of this +framework was used because the results in the debug build became skewed; the +console output prevented some of the tests from executing in parallel. + +The tests consist of both parallel and sequential tests, which are broadly +described as follows: + +- **Parallel Tests** This type of test powers on all the non-lead CPUs and + brings them and the lead CPU to a common synchronization point. The lead CPU + then initiates the test on all CPUs in parallel. + +- **Sequential Tests** This type of test powers on each non-lead CPU in + sequence. The lead CPU initiates the test on a non-lead CPU then waits for the + test to complete before proceeding to the next non-lead CPU. The lead CPU then + executes the test on itself. + +In the results below, CPUs 0-3 refer to CPUs in the little cluster (A53) and +CPUs 4-5 refer to CPUs in the big cluster (A57). In all cases CPU 4 is the lead +CPU. + +``PSCI_ENTRY`` refers to the time taken from entering the TF PSCI implementation +to the point the hardware enters the low power state (WFI). Referring to the TF +runtime instrumentation points, this corresponds to: +``(RT_INSTR_ENTER_HW_LOW_PWR - RT_INSTR_ENTER_PSCI)``. + +``PSCI_EXIT`` refers to the time taken from the point the hardware exits the low +power state to exiting the TF PSCI implementation. This corresponds to: +``(RT_INSTR_EXIT_PSCI - RT_INSTR_EXIT_HW_LOW_PWR)``. + +``CFLUSH_OVERHEAD`` refers to the part of ``PSCI_ENTRY`` taken to flush the +caches. This corresponds to: ``(RT_INSTR_EXIT_CFLUSH - RT_INSTR_ENTER_CFLUSH)``. + +Note there is very little variance observed in the values given (~1us), although +the values for each CPU are sometimes interchanged, depending on the order in +which locks are acquired. Also, there is very little variance observed between +executing the tests sequentially in a single boot or rebooting between tests. + +Given that runtime instrumentation using PMF is invasive, there is a small +(unquantified) overhead on the results. PMF uses the generic counter for +timestamps, which runs at 50MHz on Juno. + +Results and Commentary +---------------------- + +``CPU_SUSPEND`` to deepest power level on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 27 | 20 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 114 | 86 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 202 | 58 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 375 | 29 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 20 | 22 | 6 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 290 | 18 | 206 | ++-------+---------------------+--------------------+--------------------------+ + +A large variance in ``PSCI_ENTRY`` and ``PSCI_EXIT`` times across CPUs is +observed due to TF PSCI lock contention. In the worst case, CPU 3 has to wait +for the 3 other CPUs in the cluster (0-2) to complete ``PSCI_ENTRY`` and release +the lock before proceeding. + +The ``CFLUSH_OVERHEAD`` times for CPUs 3 and 5 are higher because they are the +last CPUs in their respective clusters to power down, therefore both the L1 and +L2 caches are flushed. + +The ``CFLUSH_OVERHEAD`` time for CPU 5 is a lot larger than that for CPU 3 +because the L2 cache size for the big cluster is lot larger (2MB) compared to +the little cluster (1MB). + +``CPU_SUSPEND`` to power level 0 on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 116 | 14 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 204 | 14 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 287 | 13 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 376 | 13 | 9 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 29 | 15 | 7 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 21 | 15 | 8 | ++-------+---------------------+--------------------+--------------------------+ + +There is no lock contention in TF generic code at power level 0 but the large +variance in ``PSCI_ENTRY`` times across CPUs is due to lock contention in Juno +platform code. The platform lock is used to mediate access to a single SCP +communication channel. This is compounded by the SCP firmware waiting for each +AP CPU to enter WFI before making the channel available to other CPUs, which +effectively serializes the SCP power down commands from all CPUs. + +On platforms with a more efficient CPU power down mechanism, it should be +possible to make the ``PSCI_ENTRY`` times smaller and consistent. + +The ``PSCI_EXIT`` times are consistent across all CPUs because TF does not +require locks at power level 0. + +The ``CFLUSH_OVERHEAD`` times for all CPUs are small and consistent since only +the cache associated with power level 0 is flushed (L1). + +``CPU_SUSPEND`` to deepest power level on all CPUs in sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 195 | 22 | 180 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 21 | 17 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +The ``CFLUSH_OVERHEAD`` times for lead CPU 4 and all CPUs in the non-lead cluster +are large because all other CPUs in the cluster are powered down during the +test. The ``CPU_SUSPEND`` call powers down to the cluster level, requiring a +flush of both L1 and L2 caches. + +The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little +CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared +to the little cluster (1MB). + +The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are low because lead +CPU 4 continues to run while CPU 5 is suspended. Hence CPU 5 only powers down to +level 0, which only requires L1 cache flush. + +``CPU_SUSPEND`` to power level 0 on all CPUs in sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 21 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 17 | 14 | 6 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 18 | 15 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +Here the times are small and consistent since there is no contention and it is +only necessary to flush the cache to power level 0 (L1). This is the best case +scenario. + +The ``PSCI_ENTRY`` times for CPUs in the big cluster are slightly smaller than +for the CPUs in little cluster due to greater CPU performance. + +The ``PSCI_EXIT`` times are generally lower than in the last test because the +cluster remains powered on throughout the test and there is less code to execute +on power on (for example, no need to enter CCI coherency) + +``CPU_OFF`` on all non-lead CPUs in sequence then ``CPU_SUSPEND`` on lead CPU to deepest power level +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The test sequence here is as follows: + +1. Call ``CPU_ON`` and ``CPU_OFF`` on each non-lead CPU in sequence. + +2. Program wake up timer and suspend the lead CPU to the deepest power level. + +3. Call ``CPU_ON`` on non-lead CPU to get the timestamps from each CPU. + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 111 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 195 | 22 | 181 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 20 | 23 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +The ``CFLUSH_OVERHEAD`` times for all little CPUs are large because all other +CPUs in that cluster are powerered down during the test. The ``CPU_OFF`` call +powers down to the cluster level, requiring a flush of both L1 and L2 caches. + +The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are small because +lead CPU 4 is running and CPU 5 only powers down to level 0, which only requires +an L1 cache flush. + +The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little +CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared +to the little cluster (1MB). + +The ``PSCI_EXIT`` times for CPUs in the big cluster are slightly smaller than +for CPUs in the little cluster due to greater CPU performance. These times +generally are greater than the ``PSCI_EXIT`` times in the ``CPU_SUSPEND`` tests +because there is more code to execute in the "on finisher" compared to the +"suspend finisher" (for example, GIC redistributor register programming). + +``PSCI_VERSION`` on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since very little code is associated with ``PSCI_VERSION``, this test +approximates the round trip latency for handling a fast SMC at EL3 in TF. + ++-------+-------------------+ +| CPU | TOTAL TIME (ns) | ++=======+===================+ +| 0 | 3020 | ++-------+-------------------+ +| 1 | 2940 | ++-------+-------------------+ +| 2 | 2980 | ++-------+-------------------+ +| 3 | 3060 | ++-------+-------------------+ +| 4 | 520 | ++-------+-------------------+ +| 5 | 720 | ++-------+-------------------+ + +The times for the big CPUs are less than the little CPUs due to greater CPU +performance. + +We suspect the time for lead CPU 4 is shorter than CPU 5 due to subtle cache +effects, given that these measurements are at the nano-second level. + +-------------- + +*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.* + +.. _Juno R1 platform: https://static.docs.arm.com/100122/0100/arm_versatile_express_juno_r1_development_platform_(v2m_juno_r1)_technical_reference_manual_100122_0100_05_en.pdf +.. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d diff --git a/arm-trusted-firmware/docs/perf/tsp.rst b/arm-trusted-firmware/docs/perf/tsp.rst new file mode 100644 index 0000000..f8b0048 --- /dev/null +++ b/arm-trusted-firmware/docs/perf/tsp.rst @@ -0,0 +1,27 @@ +Test Secure Payload (TSP) and Dispatcher (TSPD) +=============================================== + +Building the Test Secure Payload +-------------------------------- + +The TSP is coupled with a companion runtime service in the BL31 firmware, +called the TSPD. Therefore, if you intend to use the TSP, the BL31 image +must be recompiled as well. For more information on SPs and SPDs, see the +:ref:`firmware_design_sel1_spd` section in the :ref:`Firmware Design`. + +First clean the TF-A build directory to get rid of any previous BL31 binary. +Then to build the TSP image use: + +.. code:: shell + + make PLAT= SPD=tspd all + +An additional boot loader binary file is created in the ``build`` directory: + +:: + + build///bl32.bin + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/allwinner.rst b/arm-trusted-firmware/docs/plat/allwinner.rst new file mode 100644 index 0000000..3e9ce51 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/allwinner.rst @@ -0,0 +1,142 @@ +Allwinner ARMv8 SoCs +==================== + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Allwinner +SoCs with ARMv8 cores. Only BL31 is used to provide proper EL3 setup and +PSCI runtime services. + +Building TF-A +------------- + +There is one build target per supported SoC: + ++------+-------------------+ +| SoC | TF-A build target | ++======+===================+ +| A64 | sun50i_a64 | ++------+-------------------+ +| H5 | sun50i_a64 | ++------+-------------------+ +| H6 | sun50i_h6 | ++------+-------------------+ +| H616 | sun50i_h616 | ++------+-------------------+ +| H313 | sun50i_h616 | ++------+-------------------+ +| R329 | sun50i_r329 | ++------+-------------------+ + +To build with the default settings for a particular SoC: + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT= DEBUG=1 + +So for instance to build for a board with the Allwinner A64 SoC:: + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_a64 DEBUG=1 + +Platform-specific build options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The default build options should generate a working firmware image. There are +some build options that allow to fine-tune the firmware, or to disable support +for optional features. + +- ``SUNXI_PSCI_USE_NATIVE`` : Support direct control of the CPU cores powerdown + and powerup sequence by BL31. This requires either support for a code snippet + to be loaded into the ARISC SCP (A64, H5), or the power sequence control + registers to be programmed directly (H6, H616). This supports only basic + control, like core on/off and system off/reset. + This option defaults to 1. If an active SCP supporting the SCPI protocol + is detected at runtime, this control scheme will be ignored, and SCPI + will be used instead, unless support has been explicitly disabled. + +- ``SUNXI_PSCI_USE_SCPI`` : Support control of the CPU cores powerdown and + powerup sequence by talking to the SCP processor via the SCPI protocol. + This allows more advanced power saving techniques, like suspend to RAM. + This option defaults to 1 on SoCs that feature an SCP. If no SCP firmware + using the SCPI protocol is detected, the native sequence will be used + instead. If both native and SCPI methods are included, SCPI will be favoured + if SCP support is detected. + +- ``SUNXI_SETUP_REGULATORS`` : On SoCs that typically ship with a PMIC + power management controller, BL31 tries to set up all needed power rails, + programming them to their respective voltages. That allows bootloader + software like U-Boot to ignore power control via the PMIC. + This setting defaults to 1. In some situations that enables too many + regulators, or some regulators need to be enabled in a very specific + sequence. To avoid problems with those boards, ``SUNXI_SETUP_REGULATORS`` + can bet set to ``0`` on the build command line, to skip the PMIC setup + entirely. Any bootloader or OS would need to setup the PMIC on its own then. + +Installation +------------ + +U-Boot's SPL acts as a loader, loading both BL31 and BL33 (typically U-Boot). +Loading is done from SD card, eMMC or SPI flash, also via an USB debug +interface (FEL). + +After building bl31.bin, the binary must be fed to the U-Boot build system +to include it in the FIT image that the SPL loader will process. +bl31.bin can be either copied (or sym-linked) into U-Boot's root directory, +or the environment variable BL31 must contain the binary's path. +See the respective `U-Boot documentation`_ for more details. + +.. _U-Boot documentation: https://gitlab.denx.de/u-boot/u-boot/-/blob/master/board/sunxi/README.sunxi64 + +Memory layout +------------- + +A64, H5 and H6 SoCs +~~~~~~~~~~~~~~~~~~~ + +BL31 lives in SRAM A2, which is documented to be accessible from secure +world only. Since this SRAM region is very limited (48 KB), we take +several measures to reduce memory consumption. One of them is to confine +BL31 to only 28 bits of virtual address space, which reduces the number +of required page tables (each occupying 4KB of memory). +The mapping we use on those SoCs is as follows: + +:: + + 0 64K 16M 1GB 1G+160M physical address + +-+------+-+---+------+--...---+-------+----+------+---------- + |B| |S|///| |//...///| |////| | + |R| SRAM |C|///| dev |//...///| (sec) |////| BL33 | DRAM ... + |O| |P|///| MMIO |//...///| DRAM |////| | + |M| | |///| |//...///| (32M) |////| | + +-+------+-+---+------+--...---+-------+----+------+---------- + | | | | | | / / / / + | | | | | | / / / / + | | | | | | / / / / + | | | | | | / // / + | | | | | | / / / + +-+------+-+---+------+--+-------+------+ + |B| |S|///| |//| | | + |R| SRAM |C|///| dev |//| sec | BL33 | + |O| |P|///| MMIO |//| DRAM | | + |M| | |///| |//| | | + +-+------+-+---+------+--+-------+------+ + 0 64K 16M 160M 192M 256M virtual address + + +H616 SoC +~~~~~~~~ + +The H616 lacks the secure SRAM region present on the other SoCs, also +lacks the "ARISC" management processor (SCP) we use. BL31 thus needs to +run from DRAM, which prevents our compressed virtual memory map described +above. Since running in DRAM also lifts the restriction of the limited +SRAM size, we use the normal 1:1 mapping with 32 bits worth of virtual +address space. So the virtual addresses used in BL31 match the physical +addresses as presented above. + +Trusted OS dispatcher +--------------------- + +One can boot Trusted OS(OP-TEE OS, bl32 image) along side bl31 image on Allwinner A64. + +In order to include the 'opteed' dispatcher in the image, pass 'SPD=opteed' on the command line +while compiling the bl31 image and make sure the loader (SPL) loads the Trusted OS binary to +the beginning of DRAM (0x40000000). diff --git a/arm-trusted-firmware/docs/plat/arm/arm-build-options.rst b/arm-trusted-firmware/docs/plat/arm/arm-build-options.rst new file mode 100644 index 0000000..339ebbe --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/arm-build-options.rst @@ -0,0 +1,159 @@ +Arm Development Platform Build Options +====================================== + +Arm Platform Build Options +-------------------------- + +- ``ARM_BL31_IN_DRAM``: Boolean option to select loading of BL31 in TZC secured + DRAM. By default, BL31 is in the secure SRAM. Set this flag to 1 to load + BL31 in TZC secured DRAM. If TSP is present, then setting this option also + sets the TSP location to DRAM and ignores the ``ARM_TSP_RAM_LOCATION`` build + flag. + +- ``ARM_CONFIG_CNTACR``: boolean option to unlock access to the ``CNTBase`` + frame registers by setting the ``CNTCTLBase.CNTACR`` register bits. The + frame number ```` is defined by ``PLAT_ARM_NSTIMER_FRAME_ID``, which + should match the frame used by the Non-Secure image (normally the Linux + kernel). Default is true (access to the frame is allowed). + +- ``ARM_DISABLE_TRUSTED_WDOG``: boolean option to disable the Trusted Watchdog. + By default, Arm platforms use a watchdog to trigger a system reset in case + an error is encountered during the boot process (for example, when an image + could not be loaded or authenticated). The watchdog is enabled in the early + platform setup hook at BL1 and disabled in the BL1 prepare exit hook. The + Trusted Watchdog may be disabled at build time for testing or development + purposes. + +- ``ARM_LINUX_KERNEL_AS_BL33``: The Linux kernel expects registers x0-x3 to + have specific values at boot. This boolean option allows the Trusted Firmware + to have a Linux kernel image as BL33 by preparing the registers to these + values before jumping to BL33. This option defaults to 0 (disabled). For + AArch64 ``RESET_TO_BL31`` and for AArch32 ``RESET_TO_SP_MIN`` must be 1 when + using it. If this option is set to 1, ``ARM_PRELOADED_DTB_BASE`` must be set + to the location of a device tree blob (DTB) already loaded in memory. The + Linux Image address must be specified using the ``PRELOADED_BL33_BASE`` + option. + +- ``ARM_PLAT_MT``: This flag determines whether the Arm platform layer has to + cater for the multi-threading ``MT`` bit when accessing MPIDR. When this flag + is set, the functions which deal with MPIDR assume that the ``MT`` bit in + MPIDR is set and access the bit-fields in MPIDR accordingly. Default value of + this flag is 0. Note that this option is not used on FVP platforms. + +- ``ARM_RECOM_STATE_ID_ENC``: The PSCI1.0 specification recommends an encoding + for the construction of composite state-ID in the power-state parameter. + The existing PSCI clients currently do not support this encoding of + State-ID yet. Hence this flag is used to configure whether to use the + recommended State-ID encoding or not. The default value of this flag is 0, + in which case the platform is configured to expect NULL in the State-ID + field of power-state parameter. + +- ``ARM_ROTPK_LOCATION``: used when ``TRUSTED_BOARD_BOOT=1``. It specifies the + location of the ROTPK hash returned by the function ``plat_get_rotpk_info()`` + for Arm platforms. Depending on the selected option, the proper private key + must be specified using the ``ROT_KEY`` option when building the Trusted + Firmware. This private key will be used by the certificate generation tool + to sign the BL2 and Trusted Key certificates. Available options for + ``ARM_ROTPK_LOCATION`` are: + + - ``regs`` : return the ROTPK hash stored in the Trusted root-key storage + registers. + - ``devel_rsa`` : return a development public key hash embedded in the BL1 + and BL2 binaries. This hash has been obtained from the RSA public key + ``arm_rotpk_rsa.der``, located in ``plat/arm/board/common/rotpk``. To use + this option, ``arm_rotprivk_rsa.pem`` must be specified as ``ROT_KEY`` + when creating the certificates. + - ``devel_ecdsa`` : return a development public key hash embedded in the BL1 + and BL2 binaries. This hash has been obtained from the ECDSA public key + ``arm_rotpk_ecdsa.der``, located in ``plat/arm/board/common/rotpk``. To + use this option, ``arm_rotprivk_ecdsa.pem`` must be specified as + ``ROT_KEY`` when creating the certificates. + +- ``ARM_ROTPK_HASH``: used when ``ARM_ROTPK_LOCATION=devel_*``. Specifies the + location of the ROTPK hash. Not expected to be a build option. This defaults to + ``plat/arm/board/common/rotpk/*_sha256.bin`` depending on the specified algorithm. + Providing ``ROT_KEY`` enforces generation of the hash from the ``ROT_KEY`` and + overwrites the default hash file. + +- ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options: + + - ``tsram`` : Trusted SRAM (default option when TBB is not enabled) + - ``tdram`` : Trusted DRAM (if available) + - ``dram`` : Secure region in DRAM (default option when TBB is enabled, + configured by the TrustZone controller) + +- ``ARM_XLAT_TABLES_LIB_V1``: boolean option to compile TF-A with version 1 + of the translation tables library instead of version 2. It is set to 0 by + default, which selects version 2. + +- ``ARM_CRYPTOCELL_INTEG`` : bool option to enable TF-A to invoke Arm® + TrustZone® CryptoCell functionality for Trusted Board Boot on capable Arm + platforms. If this option is specified, then the path to the CryptoCell + SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag. + +- ``ARM_ETHOSN_NPU_DRIVER``: boolean option to enable a SiP service that can + configure an Arm Ethos-N NPU. To use this service the target platform's + ``HW_CONFIG`` must include the device tree nodes for the NPU. Currently, only + the Arm Juno platform has this included in its ``HW_CONFIG`` and the platform + only loads the ``HW_CONFIG`` in AArch64 builds. Default is 0. + +- ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the + SPMC Core manifest. Valid when ``SPD=spmd`` is selected. + +- ``ARM_BL2_SP_LIST_DTS``: Path to DTS file snippet to override the hardcoded + SP nodes in tb_fw_config. + +- ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in tb_fw_config + device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest + file name contains pattern optee_sp. + +- ``TS_SP_FW_CONFIG``: DTC build flag to include Trusted Services (Crypto and + internal-trusted-storage) as SP in tb_fw_config device tree. + +- ``ARM_GPT_SUPPORT``: Enable GPT parser to get the entry address and length of + the various partitions present in the GPT image. This support is available + only for the BL2 component, and it is disabled by default. + The following diagram shows the view of the FIP partition inside the GPT + image: + + |FIP in a GPT image| + +For a better understanding of these options, the Arm development platform memory +map is explained in the :ref:`Firmware Design`. + +.. _build_options_arm_css_platform: + +Arm CSS Platform-Specific Build Options +--------------------------------------- + +- ``CSS_DETECT_PRE_1_7_0_SCP``: Boolean flag to detect SCP version + incompatibility. Version 1.7.0 of the SCP firmware made a non-backwards + compatible change to the MTL protocol, used for AP/SCP communication. + TF-A no longer supports earlier SCP versions. If this option is set to 1 + then TF-A will detect if an earlier version is in use. Default is 1. + +- ``CSS_LOAD_SCP_IMAGES``: Boolean flag, which when set, adds SCP_BL2 and + SCP_BL2U to the FIP and FWU_FIP respectively, and enables them to be loaded + during boot. Default is 1. + +- ``CSS_USE_SCMI_SDS_DRIVER``: Boolean flag which selects SCMI/SDS drivers + instead of SCPI/BOM driver for communicating with the SCP during power + management operations and for SCP RAM Firmware transfer. If this option + is set to 1, then SCMI/SDS drivers will be used. Default is 0. + + - ``CSS_SGI_CHIP_COUNT``: Configures the number of chips on a SGI/RD platform + which supports multi-chip operation. If ``CSS_SGI_CHIP_COUNT`` is set to any + valid value greater than 1, the platform code performs required configuration + to support multi-chip operation. + +- ``CSS_SGI_PLATFORM_VARIANT``: Selects the variant of a SGI/RD platform. A + particular SGI/RD platform may have multiple variants which may differ in + core count, cluster count or other peripherals. This build option is used + to select the appropriate platform variant for the build. The range of + valid values is platform specific. + +-------------- + +.. |FIP in a GPT image| image:: ../../resources/diagrams/FIP_in_a_GPT_image.png + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst b/arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst new file mode 100644 index 0000000..5427c1d --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst @@ -0,0 +1,97 @@ +Arm FPGA Platform +================= + +This platform supports FPGA images used internally in Arm Ltd., for +testing and bringup of new cores. With that focus, peripheral support is +minimal: there is no mass storage or display output, for instance. Also +this port ignores any power management features of the platform. +Some interconnect setup is done internally by the platform, so the TF-A code +just needs to setup UART and GIC. + +The FPGA platform requires to pass on a DTB for the non-secure payload +(mostly Linux), so we let TF-A use information from the DTB for dynamic +configuration: the UART and GIC base addresses are read from there. + +As a result this port is a fairly generic BL31-only port, which can serve +as a template for a minimal new (and possibly DT-based) platform port. + +The aim of this port is to support as many FPGA images as possible with +a single build. Image specific data must be described in the DTB or should +be auto-detected at runtime. + +As the number and topology layout of the CPU cores differs significantly +across the various images, this is detected at runtime by BL31. +The /cpus node in the DT will be added and filled accordingly, as long as +it does not exist already. + +Platform-specific build options +------------------------------- + +- ``SUPPORT_UNKNOWN_MPID`` : Boolean option to allow unknown MPIDR registers. + Normally TF-A panics if it encounters a MPID value not matched to its + internal list, but for new or experimental cores this creates a lot of + churn. With this option, the code will fall back to some basic CPU support + code (only architectural system registers, and no errata). + Default value of this flag is 1. + +- ``PRELOADED_BL33_BASE`` : Physical address of the BL33 non-secure payload. + It must have been loaded into DRAM already, typically this is done by + the script that also loads BL31 and the DTB. + It defaults to 0x80080000, which is the traditional load address for an + arm64 Linux kernel. + +- ``FPGA_PRELOADED_DTB_BASE`` : Physical address of the flattened device + tree blob (DTB). This DT will be used by TF-A for dynamic configuration, + so it must describe at least the UART and a GICv3 interrupt controller. + The DT gets amended by the code, to potentially add a command line and + fill the CPU topology nodes. It will also be passed on to BL33, by + putting its address into the x0 register before jumping to the entry + point (following the Linux kernel boot protocol). + It defaults to 0x80070000, which is 64KB before the BL33 load address. + +- ``FPGA_PRELOADED_CMD_LINE`` : Physical address of the command line to + put into the devicetree blob. Due to the lack of a proper bootloader, + a command line can be put somewhere into memory, so that BL31 will + detect it and copy it into the DTB passed on to BL33. + To avoid random garbage, there needs to be a "CMD:" signature before the + actual command line. + Defaults to 0x1000, which is normally in the "ROM" space of the typical + FPGA image (which can be written by the FPGA payload uploader, but is + read-only to the CPU). The FPGA payload tool should be given a text file + containing the desired command line, prefixed by the "CMD:" signature. + +Building the TF-A image +----------------------- + + .. code:: shell + + make PLAT=arm_fgpa DEBUG=1 + + This will use the default load addresses as described above. When those + addresses need to differ for a certain setup, they can be passed on the + make command line: + + .. code:: shell + + make PLAT=arm_fgpa DEBUG=1 PRELOADED_BL33_BASE=0x80200000 FPGA_PRELOADED_DTB_BASE=0x80180000 bl31 + +Running the TF-A image +---------------------- + +After building TF-A, the actual TF-A code will be located in ``bl31.bin`` in +the build directory. +Additionally there is a ``bl31.axf`` ELF file, which contains BL31, as well +as some simple ROM trampoline code (required by the Arm FPGA boot flow) and +a generic DTB to support most of the FPGA images. This can be simply handed +over to the FPGA payload uploader, which will take care of loading the +components at their respective load addresses. In addition to this file +you need at least a BL33 payload (typically a Linux kernel image), optionally +a Linux initrd image file and possibly a command line: + + .. code:: shell + + fpga-run ... -m bl31.axf -l auto -m Image -l 0x80080000 -m initrd.gz -l 0x84000000 -m cmdline.txt -l 0x1000 + +-------------- + +*Copyright (c) 2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst b/arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst new file mode 100644 index 0000000..b889b7f --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst @@ -0,0 +1,61 @@ +Corstone1000 Platform +========================== + +Some of the features of the Corstone1000 platform referenced in TF-A include: + +- Cortex-A35 application processor (64-bit mode) +- Secure Enclave +- GIC-400 +- Trusted Board Boot + +Boot Sequence +------------- + +The board boot relies on CoT (chain of trust). The trusted-firmware-a +BL2 is extracted from the FIP and verified by the Secure Enclave +processor. BL2 verification relies on the signature area at the +beginning of the BL2 image. This area is needed by the SecureEnclave +bootloader. + +Then, the application processor is released from reset and starts by +executing BL2. + +BL2 performs the actions described in the trusted-firmware-a TBB design +document. + +Build Procedure (TF-A only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Obtain AArch64 ELF bare-metal target `toolchain `_. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Build TF-A: + + .. code:: shell + + make LD=aarch64-none-elf-ld \ + CC=aarch64-none-elf-gcc \ + V=1 \ + BUILD_BASE= \ + PLAT=corstone1000 \ + SPD=spmd \ + SPMD_SPM_AT_SEL2=0 \ + DEBUG=1 \ + MBEDTLS_DIR=mbedtls \ + OPENSSL_DIR= \ + RUNTIME_SYSROOT= \ + ARCH=aarch64 \ + TARGET_PLATFORM= \ + ENABLE_PIE=1 \ + BL2_AT_EL3=1 \ + CREATE_KEYS=1 \ + GENERATE_COT=1 \ + TRUSTED_BOARD_BOOT=1 \ + COT=tbbr \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL32= \ + BL33= \ + bl2 + +*Copyright (c) 2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst b/arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst new file mode 100644 index 0000000..8ac0741 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst @@ -0,0 +1,84 @@ +Arm Versatile Express +===================== + +Versatile Express (VE) family development platform provides an ultra fast +environment for prototyping Armv7 System-on-Chip designs. VE Fixed Virtual +Platforms (FVP) are simulations of Versatile Express boards. The platform in +Trusted Firmware-A has been verified with Arm Cortex-A5 and Cortex-A7 VE FVP's. +This platform is tested on and only expected to work with single core models. + +Boot Sequence +------------- + +BL1 --> BL2 --> BL32(sp_min) --> BL33(u-boot) --> Linux kernel + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ +- `U-boot `__ + +- `Trusted Firmware-A `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Obtain arm toolchain. The software stack has been verified with linaro 6.2 + `arm-linux-gnueabihf `__. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Fetch and build u-boot. + Make the .config file using the command: + + .. code:: shell + + make ARCH=arm vexpress_aemv8a_aarch32_config + + Make the u-boot binary for Cortex-A5 using the command: + + .. code:: shell + + make ARCH=arm SUPPORT_ARCH_TIMER=no + + Make the u-boot binary for Cortex-A7 using the command: + + .. code:: shell + + make ARCH=arm + + +- Build TF-A: + + The make command for Cortex-A5 is: + + .. code:: shell + + make PLAT=fvp_ve ARCH=aarch32 ARM_ARCH_MAJOR=7 ARM_CORTEX_A5=yes \ + AARCH32_SP=sp_min FVP_HW_CONFIG_DTS=fdts/fvp-ve-Cortex-A5x1.dts \ + ARM_XLAT_TABLES_LIB_V1=1 BL33= all fip + + The make command for Cortex-A7 is: + + .. code:: shell + + make PLAT=fvp_ve ARCH=aarch32 ARM_ARCH_MAJOR=7 ARM_CORTEX_A7=yes \ + AARCH32_SP=sp_min FVP_HW_CONFIG_DTS=fdts/fvp-ve-Cortex-A7x1.dts \ + BL33= all fip + +Run Procedure +~~~~~~~~~~~~~ + +The following model parameters should be used to boot Linux using the build of +Trusted Firmware-A made using the above make commands: + + .. code:: shell + + ./ \ + -C motherboard.flashloader1.fname= \ + --data cluster.cpu0=@0x80080000 \ + --data cluster.cpu0=@0x84000000 + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/fvp/index.rst b/arm-trusted-firmware/docs/plat/arm/fvp/index.rst new file mode 100644 index 0000000..2aaf195 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/fvp/index.rst @@ -0,0 +1,652 @@ +Arm Fixed Virtual Platforms (FVP) +================================= + +Fixed Virtual Platform (FVP) Support +------------------------------------ + +This section lists the supported Arm |FVP| platforms. Please refer to the FVP +documentation for a detailed description of the model parameter options. + +The latest version of the AArch64 build of TF-A has been tested on the following +Arm FVPs without shifted affinities, and that do not support threaded CPU cores +(64-bit host machine only). + +.. note:: + The FVP models used are Version 11.16 Build 16, unless otherwise stated. + +- ``Foundation_Platform`` +- ``FVP_Base_AEMv8A-AEMv8A-AEMv8A-AEMv8A-CCN502`` +- ``FVP_Base_AEMv8A-AEMv8A`` (For certain configurations also uses 11.14/21) +- ``FVP_Base_AEMv8A-GIC600AE`` +- ``FVP_Base_AEMvA`` (For certain configurations also uses 0.0/6684) +- ``FVP_Base_Cortex-A32x4`` (Version 11.12/38) +- ``FVP_Base_Cortex-A35x4`` +- ``FVP_Base_Cortex-A53x4`` +- ``FVP_Base_Cortex-A55x4`` +- ``FVP_Base_Cortex-A55x4+Cortex-A75x4`` +- ``FVP_Base_Cortex-A57x1-A53x1`` +- ``FVP_Base_Cortex-A57x2-A53x4`` +- ``FVP_Base_Cortex-A57x4-A53x4`` +- ``FVP_Base_Cortex-A57x4`` +- ``FVP_Base_Cortex-A65AEx8`` +- ``FVP_Base_Cortex-A65x4`` +- ``FVP_Base_Cortex-A710x4`` +- ``FVP_Base_Cortex-A72x4-A53x4`` +- ``FVP_Base_Cortex-A72x4`` +- ``FVP_Base_Cortex-A73x4-A53x4`` +- ``FVP_Base_Cortex-A73x4`` +- ``FVP_Base_Cortex-A75x4`` +- ``FVP_Base_Cortex-A76AEx4`` +- ``FVP_Base_Cortex-A76AEx8`` +- ``FVP_Base_Cortex-A76x4`` +- ``FVP_Base_Cortex-A77x4`` +- ``FVP_Base_Cortex-A78x4`` +- ``FVP_Base_Neoverse-E1x1`` +- ``FVP_Base_Neoverse-E1x2`` +- ``FVP_Base_Neoverse-E1x4`` +- ``FVP_Base_Neoverse-N1x4`` +- ``FVP_Base_Neoverse-N2x4`` (Version 11.12 build 38) +- ``FVP_Base_Neoverse-V1x4`` +- ``FVP_Base_RevC-2xAEMvA`` (For certain configurations also uses 0.0/6557) +- ``FVP_CSS_SGI-575`` (Version 11.15/26) +- ``FVP_Morello`` (Version 0.11/19) +- ``FVP_RD_E1_edge`` (Version 11.15/26) +- ``FVP_RD_N1_edge_dual`` (Version 11.15/26) +- ``FVP_RD_N1_edge`` (Version 11.15/26) +- ``FVP_RD_V1`` (Version 11.15/26) +- ``FVP_TC0`` +- ``FVP_TC1`` + +The latest version of the AArch32 build of TF-A has been tested on the +following Arm FVPs without shifted affinities, and that do not support threaded +CPU cores (64-bit host machine only). + +- ``FVP_Base_AEMvA`` +- ``FVP_Base_AEMv8A-AEMv8A`` +- ``FVP_Base_Cortex-A32x4`` + +.. note:: + The ``FVP_Base_RevC-2xAEMv8A`` FVP only supports shifted affinities, which + is not compatible with legacy GIC configurations. Therefore this FVP does not + support these legacy GIC configurations. + +The *Foundation* and *Base* FVPs can be downloaded free of charge. See the `Arm +FVP website`_. The Cortex-A models listed above are also available to download +from `Arm's website`_. + +.. note:: + The build numbers quoted above are those reported by launching the FVP + with the ``--version`` parameter. + +.. note:: + Linaro provides a ramdisk image in prebuilt FVP configurations and full + file systems that can be downloaded separately. To run an FVP with a virtio + file system image an additional FVP configuration option + ``-C bp.virtioblockdevice.image_path="/`` can be + used. + +.. note:: + The software will not work on Version 1.0 of the Foundation FVP. + The commands below would report an ``unhandled argument`` error in this case. + +.. note:: + FVPs can be launched with ``--cadi-server`` option such that a + CADI-compliant debugger (for example, Arm DS-5) can connect to and control + its execution. + +.. warning:: + Since FVP model Version 11.0 Build 11.0.34 and Version 8.5 Build 0.8.5202 + the internal synchronisation timings changed compared to older versions of + the models. The models can be launched with ``-Q 100`` option if they are + required to match the run time characteristics of the older versions. + +All the above platforms have been tested with `Linaro Release 20.01`_. + +.. _build_options_arm_fvp_platform: + +Arm FVP Platform Specific Build Options +--------------------------------------- + +- ``FVP_CLUSTER_COUNT`` : Configures the cluster count to be used to + build the topology tree within TF-A. By default TF-A is configured for dual + cluster topology and this option can be used to override the default value. + +- ``FVP_INTERCONNECT_DRIVER``: Selects the interconnect driver to be built. The + default interconnect driver depends on the value of ``FVP_CLUSTER_COUNT`` as + explained in the options below: + + - ``FVP_CCI`` : The CCI driver is selected. This is the default + if 0 < ``FVP_CLUSTER_COUNT`` <= 2. + - ``FVP_CCN`` : The CCN driver is selected. This is the default + if ``FVP_CLUSTER_COUNT`` > 2. + +- ``FVP_MAX_CPUS_PER_CLUSTER``: Sets the maximum number of CPUs implemented in + a single cluster. This option defaults to 4. + +- ``FVP_MAX_PE_PER_CPU``: Sets the maximum number of PEs implemented on any CPU + in the system. This option defaults to 1. Note that the build option + ``ARM_PLAT_MT`` doesn't have any effect on FVP platforms. + +- ``FVP_USE_GIC_DRIVER`` : Selects the GIC driver to be built. Options: + + - ``FVP_GICV2`` : The GICv2 only driver is selected + - ``FVP_GICV3`` : The GICv3 only driver is selected (default option) + +- ``FVP_HW_CONFIG_DTS`` : Specify the path to the DTS file to be compiled + to DTB and packaged in FIP as the HW_CONFIG. See :ref:`Firmware Design` for + details on HW_CONFIG. By default, this is initialized to a sensible DTS + file in ``fdts/`` folder depending on other build options. But some cases, + like shifted affinity format for MPIDR, cannot be detected at build time + and this option is needed to specify the appropriate DTS file. + +- ``FVP_HW_CONFIG`` : Specify the path to the HW_CONFIG blob to be packaged in + FIP. See :ref:`Firmware Design` for details on HW_CONFIG. This option is + similar to the ``FVP_HW_CONFIG_DTS`` option, but it directly specifies the + HW_CONFIG blob instead of the DTS file. This option is useful to override + the default HW_CONFIG selected by the build system. + +- ``FVP_GICR_REGION_PROTECTION``: Mark the redistributor pages of + inactive/fused CPU cores as read-only. The default value of this option + is ``0``, which means the redistributor pages of all CPU cores are marked + as read and write. + +Booting Firmware Update images +------------------------------ + +When Firmware Update (FWU) is enabled there are at least 2 new images +that have to be loaded, the Non-Secure FWU ROM (NS-BL1U), and the +FWU FIP. + +The additional fip images must be loaded with: + +:: + + --data cluster0.cpu0="/ns_bl1u.bin"@0x0beb8000 [ns_bl1u_base_address] + --data cluster0.cpu0="/fwu_fip.bin"@0x08400000 [ns_bl2u_base_address] + +The address ns_bl1u_base_address is the value of NS_BL1U_BASE. +In the same way, the address ns_bl2u_base_address is the value of +NS_BL2U_BASE. + +Booting an EL3 payload +---------------------- + +The EL3 payloads boot flow requires the CPU's mailbox to be cleared at reset for +the secondary CPUs holding pen to work properly. Unfortunately, its reset value +is undefined on the FVP platform and the FVP platform code doesn't clear it. +Therefore, one must modify the way the model is normally invoked in order to +clear the mailbox at start-up. + +One way to do that is to create an 8-byte file containing all zero bytes using +the following command: + +.. code:: shell + + dd if=/dev/zero of=mailbox.dat bs=1 count=8 + +and pre-load it into the FVP memory at the mailbox address (i.e. ``0x04000000``) +using the following model parameters: + +:: + + --data cluster0.cpu0=mailbox.dat@0x04000000 [Base FVPs] + --data=mailbox.dat@0x04000000 [Foundation FVP] + +To provide the model with the EL3 payload image, the following methods may be +used: + +#. If the EL3 payload is able to execute in place, it may be programmed into + flash memory. On Base Cortex and AEM FVPs, the following model parameter + loads it at the base address of the NOR FLASH1 (the NOR FLASH0 is already + used for the FIP): + + :: + + -C bp.flashloader1.fname="/" + + On Foundation FVP, there is no flash loader component and the EL3 payload + may be programmed anywhere in flash using method 3 below. + +#. When using the ``SPIN_ON_BL1_EXIT=1`` loading method, the following DS-5 + command may be used to load the EL3 payload ELF image over JTAG: + + :: + + load /el3-payload.elf + +#. The EL3 payload may be pre-loaded in volatile memory using the following + model parameters: + + :: + + --data cluster0.cpu0="/el3-payload>"@address [Base FVPs] + --data="/"@address [Foundation FVP] + + The address provided to the FVP must match the ``EL3_PAYLOAD_BASE`` address + used when building TF-A. + +Booting a preloaded kernel image (Base FVP) +------------------------------------------- + +The following example uses a simplified boot flow by directly jumping from the +TF-A to the Linux kernel, which will use a ramdisk as filesystem. This can be +useful if both the kernel and the device tree blob (DTB) are already present in +memory (like in FVP). + +For example, if the kernel is loaded at ``0x80080000`` and the DTB is loaded at +address ``0x82000000``, the firmware can be built like this: + +.. code:: shell + + CROSS_COMPILE=aarch64-none-elf- \ + make PLAT=fvp DEBUG=1 \ + RESET_TO_BL31=1 \ + ARM_LINUX_KERNEL_AS_BL33=1 \ + PRELOADED_BL33_BASE=0x80080000 \ + ARM_PRELOADED_DTB_BASE=0x82000000 \ + all fip + +Now, it is needed to modify the DTB so that the kernel knows the address of the +ramdisk. The following script generates a patched DTB from the provided one, +assuming that the ramdisk is loaded at address ``0x84000000``. Note that this +script assumes that the user is using a ramdisk image prepared for U-Boot, like +the ones provided by Linaro. If using a ramdisk without this header,the ``0x40`` +offset in ``INITRD_START`` has to be removed. + +.. code:: bash + + #!/bin/bash + + # Path to the input DTB + KERNEL_DTB=/ + # Path to the output DTB + PATCHED_KERNEL_DTB=/ + # Base address of the ramdisk + INITRD_BASE=0x84000000 + # Path to the ramdisk + INITRD=/ + + # Skip uboot header (64 bytes) + INITRD_START=$(printf "0x%x" $((${INITRD_BASE} + 0x40)) ) + INITRD_SIZE=$(stat -Lc %s ${INITRD}) + INITRD_END=$(printf "0x%x" $((${INITRD_BASE} + ${INITRD_SIZE})) ) + + CHOSEN_NODE=$(echo \ + "/ { \ + chosen { \ + linux,initrd-start = <${INITRD_START}>; \ + linux,initrd-end = <${INITRD_END}>; \ + }; \ + };") + + echo $(dtc -O dts -I dtb ${KERNEL_DTB}) ${CHOSEN_NODE} | \ + dtc -O dtb -o ${PATCHED_KERNEL_DTB} - + +And the FVP binary can be run with the following command: + +.. code:: shell + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBAR=0x04001000 \ + -C cluster0.cpu1.RVBAR=0x04001000 \ + -C cluster0.cpu2.RVBAR=0x04001000 \ + -C cluster0.cpu3.RVBAR=0x04001000 \ + -C cluster1.cpu0.RVBAR=0x04001000 \ + -C cluster1.cpu1.RVBAR=0x04001000 \ + -C cluster1.cpu2.RVBAR=0x04001000 \ + -C cluster1.cpu3.RVBAR=0x04001000 \ + --data cluster0.cpu0="/bl31.bin"@0x04001000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Obtaining the Flattened Device Trees +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Depending on the FVP configuration and Linux configuration used, different +FDT files are required. FDT source files for the Foundation and Base FVPs can +be found in the TF-A source directory under ``fdts/``. The Foundation FVP has +a subset of the Base FVP components. For example, the Foundation FVP lacks +CLCD and MMC support, and has only one CPU cluster. + +.. note:: + It is not recommended to use the FDTs built along the kernel because not + all FDTs are available from there. + +The dynamic configuration capability is enabled in the firmware for FVPs. +This means that the firmware can authenticate and load the FDT if present in +FIP. A default FDT is packaged into FIP during the build based on +the build configuration. This can be overridden by using the ``FVP_HW_CONFIG`` +or ``FVP_HW_CONFIG_DTS`` build options (refer to +:ref:`build_options_arm_fvp_platform` for details on the options). + +- ``fvp-base-gicv2-psci.dts`` + + For use with models such as the Cortex-A57-A53 Base FVPs without shifted + affinities and with Base memory map configuration. + +- ``fvp-base-gicv2-psci-aarch32.dts`` + + For use with models such as the Cortex-A32 Base FVPs without shifted + affinities and running Linux in AArch32 state with Base memory map + configuration. + +- ``fvp-base-gicv3-psci.dts`` + + For use with models such as the Cortex-A57-A53 Base FVPs without shifted + affinities and with Base memory map configuration and Linux GICv3 support. + +- ``fvp-base-gicv3-psci-1t.dts`` + + For use with models such as the AEMv8-RevC Base FVP with shifted affinities, + single threaded CPUs, Base memory map configuration and Linux GICv3 support. + +- ``fvp-base-gicv3-psci-dynamiq.dts`` + + For use with models as the Cortex-A55-A75 Base FVPs with shifted affinities, + single cluster, single threaded CPUs, Base memory map configuration and Linux + GICv3 support. + +- ``fvp-base-gicv3-psci-aarch32.dts`` + + For use with models such as the Cortex-A32 Base FVPs without shifted + affinities and running Linux in AArch32 state with Base memory map + configuration and Linux GICv3 support. + +- ``fvp-foundation-gicv2-psci.dts`` + + For use with Foundation FVP with Base memory map configuration. + +- ``fvp-foundation-gicv3-psci.dts`` + + (Default) For use with Foundation FVP with Base memory map configuration + and Linux GICv3 support. + + +Running on the Foundation FVP with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``Foundation_Platform`` parameters should be used to boot Linux with +4 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /Foundation_Platform \ + --cores=4 \ + --arm-v8.0 \ + --secure-memory \ + --visualization \ + --gicv3 \ + --data="/"@0x0 \ + --data="/"@0x08000000 \ + --data="/"@0x80080000 \ + --data="/"@0x84000000 + +Notes: + +- BL1 is loaded at the start of the Trusted ROM. +- The Firmware Image Package is loaded at the start of NOR FLASH0. +- The firmware loads the FDT packaged in FIP to the DRAM. The FDT load address + is specified via the ``hw_config_addr`` property in `TB_FW_CONFIG for FVP`_. +- The default use-case for the Foundation FVP is to use the ``--gicv3`` option + and enable the GICv3 device in the model. Note that without this option, + the Foundation FVP defaults to legacy (Versatile Express) memory map which + is not supported by TF-A. +- In order for TF-A to run correctly on the Foundation FVP, the architecture + versions must match. The Foundation FVP defaults to the highest v8.x + version it supports but the default build for TF-A is for v8.0. To avoid + issues either start the Foundation FVP to use v8.0 architecture using the + ``--arm-v8.0`` option, or build TF-A with an appropriate value for + ``ARM_ARCH_MINOR``. + +Running on the AEMv8 Base FVP with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_RevC-2xAEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /FVP_Base_RevC-2xAEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +.. note:: + The ``FVP_Base_RevC-2xAEMv8A`` has shifted affinities and requires + a specific DTS for all the CPUs to be loaded. + +Running on the AEMv8 Base FVP (AArch32) with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch32 build of TF-A. + +.. code:: shell + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.CONFIG64=0 \ + -C cluster0.cpu1.CONFIG64=0 \ + -C cluster0.cpu2.CONFIG64=0 \ + -C cluster0.cpu3.CONFIG64=0 \ + -C cluster1.cpu0.CONFIG64=0 \ + -C cluster1.cpu1.CONFIG64=0 \ + -C cluster1.cpu2.CONFIG64=0 \ + -C cluster1.cpu3.CONFIG64=0 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A57-A53 Base FVP with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to +boot Linux with 8 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /FVP_Base_Cortex-A57x4-A53x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A32 Base FVP (AArch32) with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to +boot Linux with 4 CPUs using the AArch32 build of TF-A. + +.. code:: shell + + /FVP_Base_Cortex-A32x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + + +Running on the AEMv8 Base FVP with reset to BL31 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_RevC-2xAEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /FVP_Base_RevC-2xAEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBAR=0x04010000 \ + -C cluster0.cpu1.RVBAR=0x04010000 \ + -C cluster0.cpu2.RVBAR=0x04010000 \ + -C cluster0.cpu3.RVBAR=0x04010000 \ + -C cluster1.cpu0.RVBAR=0x04010000 \ + -C cluster1.cpu1.RVBAR=0x04010000 \ + -C cluster1.cpu2.RVBAR=0x04010000 \ + -C cluster1.cpu3.RVBAR=0x04010000 \ + --data cluster0.cpu0="/"@0x04010000 \ + --data cluster0.cpu0="/"@0xff000000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Notes: + +- Position Independent Executable (PIE) support is enabled in this + config allowing BL31 to be loaded at any valid address for execution. + +- Since a FIP is not loaded when using BL31 as reset entrypoint, the + ``--data=""@`` + parameter is needed to load the individual bootloader images in memory. + BL32 image is only needed if BL31 has been built to expect a Secure-EL1 + Payload. For the same reason, the FDT needs to be compiled from the DT source + and loaded via the ``--data cluster0.cpu0="/"@0x82000000`` + parameter. + +- The ``FVP_Base_RevC-2xAEMv8A`` has shifted affinities and requires a + specific DTS for all the CPUs to be loaded. + +- The ``-C cluster.cpu.RVBAR=@`` parameter, where + X and Y are the cluster and CPU numbers respectively, is used to set the + reset vector for each core. + +- Changing the default value of ``ARM_TSP_RAM_LOCATION`` will also require + changing the value of + ``--data=""@`` to the new value of + ``BL32_BASE``. + + +Running on the AEMv8 Base FVP (AArch32) with reset to SP_MIN entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch32 build of TF-A. + +.. code:: shell + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.CONFIG64=0 \ + -C cluster0.cpu1.CONFIG64=0 \ + -C cluster0.cpu2.CONFIG64=0 \ + -C cluster0.cpu3.CONFIG64=0 \ + -C cluster1.cpu0.CONFIG64=0 \ + -C cluster1.cpu1.CONFIG64=0 \ + -C cluster1.cpu2.CONFIG64=0 \ + -C cluster1.cpu3.CONFIG64=0 \ + -C cluster0.cpu0.RVBAR=0x04002000 \ + -C cluster0.cpu1.RVBAR=0x04002000 \ + -C cluster0.cpu2.RVBAR=0x04002000 \ + -C cluster0.cpu3.RVBAR=0x04002000 \ + -C cluster1.cpu0.RVBAR=0x04002000 \ + -C cluster1.cpu1.RVBAR=0x04002000 \ + -C cluster1.cpu2.RVBAR=0x04002000 \ + -C cluster1.cpu3.RVBAR=0x04002000 \ + --data cluster0.cpu0="/"@0x04002000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +.. note:: + Position Independent Executable (PIE) support is enabled in this + config allowing SP_MIN to be loaded at any valid address for execution. + +Running on the Cortex-A57-A53 Base FVP with reset to BL31 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to +boot Linux with 8 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /FVP_Base_Cortex-A57x4-A53x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBARADDR=0x04010000 \ + -C cluster0.cpu1.RVBARADDR=0x04010000 \ + -C cluster0.cpu2.RVBARADDR=0x04010000 \ + -C cluster0.cpu3.RVBARADDR=0x04010000 \ + -C cluster1.cpu0.RVBARADDR=0x04010000 \ + -C cluster1.cpu1.RVBARADDR=0x04010000 \ + -C cluster1.cpu2.RVBARADDR=0x04010000 \ + -C cluster1.cpu3.RVBARADDR=0x04010000 \ + --data cluster0.cpu0="/"@0x04010000 \ + --data cluster0.cpu0="/"@0xff000000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A32 Base FVP (AArch32) with reset to SP_MIN entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to +boot Linux with 4 CPUs using the AArch32 build of TF-A. + +.. code:: shell + + /FVP_Base_Cortex-A32x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBARADDR=0x04002000 \ + -C cluster0.cpu1.RVBARADDR=0x04002000 \ + -C cluster0.cpu2.RVBARADDR=0x04002000 \ + -C cluster0.cpu3.RVBARADDR=0x04002000 \ + --data cluster0.cpu0="/"@0x04002000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +-------------- + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* + +.. _TB_FW_CONFIG for FVP: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts +.. _Arm's website: `FVP models`_ +.. _FVP models: https://developer.arm.com/products/system-design/fixed-virtual-platforms +.. _Linaro Release 20.01: http://releases.linaro.org/members/arm/platforms/20.01 +.. _Arm FVP website: https://developer.arm.com/products/system-design/fixed-virtual-platforms diff --git a/arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst b/arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst new file mode 100644 index 0000000..8af16ba --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst @@ -0,0 +1,46 @@ +ARM V8-R64 Fixed Virtual Platform (FVP) +======================================= + +Some of the features of Armv8-R AArch64 FVP platform referenced in Trusted +Boot R-class include: + +- Secure World Support Only +- EL2 as Maximum EL support (No EL3) +- MPU Support only at EL2 +- MPU or MMU Support at EL0/EL1 +- AArch64 Support Only +- Trusted Board Boot + +Further information on v8-R64 FVP is available at `info `_ + +Boot Sequence +------------- + +BL1 –> BL33 + +The execution begins from BL1 which loads the BL33 image, a boot-wrapped (bootloader + Operating System) +Operating System, from FIP to DRAM. + +Build Procedure +~~~~~~~~~~~~~~~ + +- Obtain arm `toolchain `_. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Build TF-A: + + .. code:: shell + + make PLAT=fvp_r BL33= all fip + + Enable TBBR by adding the following options to the make command: + + .. code:: shell + + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 \ + GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem + +*Copyright (c) 2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/index.rst b/arm-trusted-firmware/docs/plat/arm/index.rst new file mode 100644 index 0000000..2f68522 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/index.rst @@ -0,0 +1,24 @@ +Arm Development Platforms +========================= + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + juno/index + fvp/index + fvp_r/index + fvp-ve/index + tc/index + arm_fpga/index + arm-build-options + morello/index + corstone1000/index + +This chapter holds documentation related to Arm's development platforms, +including both software models (FVPs) and hardware development boards +such as Juno. + +-------------- + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/juno/index.rst b/arm-trusted-firmware/docs/plat/arm/juno/index.rst new file mode 100644 index 0000000..8b9d453 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/juno/index.rst @@ -0,0 +1,253 @@ +Arm Juno Development Platform +============================= + +Platform-specific build options +------------------------------- + +- ``JUNO_TZMP1`` : Boolean option to configure Juno to be used for TrustZone + Media Protection (TZ-MP1). Default value of this flag is 0. + +Running software on Juno +------------------------ + +This version of TF-A has been tested on variants r0, r1 and r2 of Juno. + +To run TF-A on Juno, you need to first prepare an SD card with Juno software +stack that includes TF-A. This version of TF-A is tested with pre-built +`Linaro release software stack`_ version 20.01. You can alternatively +build the software stack yourself by following the +`Juno platform software user guide`_. Once you prepare the software stack +on an SD card, you can replace the ``bl1.bin`` and ``fip.bin`` +binaries in the ``SOFTWARE/`` directory with custom built TF-A binaries. + +Preparing TF-A images +--------------------- + +This section provides Juno and FVP specific instructions to build Trusted +Firmware, obtain the additional required firmware, and pack it all together in +a single FIP binary. It assumes that a Linaro release software stack has been +installed. + +.. note:: + Pre-built binaries for AArch32 are available from Linaro Release 16.12 + onwards. Before that release, pre-built binaries are only available for + AArch64. + +.. warning:: + Follow the full instructions for one platform before switching to a + different one. Mixing instructions for different platforms may result in + corrupted binaries. + +.. warning:: + The uboot image downloaded by the Linaro workspace script does not always + match the uboot image packaged as BL33 in the corresponding fip file. It is + recommended to use the version that is packaged in the fip file using the + instructions below. + +.. note:: + For the FVP, the kernel FDT is packaged in FIP during build and loaded + by the firmware at runtime. + +#. Clean the working directory + + .. code:: shell + + make realclean + +#. Obtain SCP binaries (Juno) + + This version of TF-A is tested with SCP version 2.8.0 on Juno. You can + download pre-built SCP binaries (``scp_bl1.bin`` and ``scp_bl2.bin``) + from `TF-A downloads page`_. Alternatively, you can `build + the binaries from source`_. + +#. Obtain BL33 (all platforms) + + Use the fiptool to extract the BL33 image from the FIP + package included in the Linaro release: + + .. code:: shell + + # Build the fiptool + make [DEBUG=1] [V=1] fiptool + + # Unpack firmware images from Linaro FIP + ./tools/fiptool/fiptool unpack /[SOFTWARE]/fip.bin + + The unpack operation will result in a set of binary images extracted to the + current working directory. BL33 corresponds to ``nt-fw.bin``. + + .. note:: + The fiptool will complain if the images to be unpacked already + exist in the current directory. If that is the case, either delete those + files or use the ``--force`` option to overwrite. + + .. note:: + For AArch32, the instructions below assume that nt-fw.bin is a + normal world boot loader that supports AArch32. + +#. Build TF-A images and create a new FIP for FVP + + .. code:: shell + + # AArch64 + make PLAT=fvp BL33=nt-fw.bin all fip + + # AArch32 + make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=nt-fw.bin all fip + +#. Build TF-A images and create a new FIP for Juno + + For AArch64: + + Building for AArch64 on Juno simply requires the addition of ``SCP_BL2`` + as a build parameter. + + .. code:: shell + + make PLAT=juno BL33=nt-fw.bin SCP_BL2=scp_bl2.bin all fip + + For AArch32: + + Hardware restrictions on Juno prevent cold reset into AArch32 execution mode, + therefore BL1 and BL2 must be compiled for AArch64, and BL32 is compiled + separately for AArch32. + + - Before building BL32, the environment variable ``CROSS_COMPILE`` must point + to the AArch32 Linaro cross compiler. + + .. code:: shell + + export CROSS_COMPILE=/bin/arm-linux-gnueabihf- + + - Build BL32 in AArch32. + + .. code:: shell + + make ARCH=aarch32 PLAT=juno AARCH32_SP=sp_min \ + RESET_TO_SP_MIN=1 JUNO_AARCH32_EL3_RUNTIME=1 bl32 + + - Save ``bl32.bin`` to a temporary location and clean the build products. + + :: + + cp /bl32.bin + make realclean + + - Before building BL1 and BL2, the environment variable ``CROSS_COMPILE`` + must point to the AArch64 Linaro cross compiler. + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + + - The following parameters should be used to build BL1 and BL2 in AArch64 + and point to the BL32 file. + + .. code:: shell + + make ARCH=aarch64 PLAT=juno JUNO_AARCH32_EL3_RUNTIME=1 \ + BL33=nt-fw.bin SCP_BL2=scp_bl2.bin \ + BL32=/bl32.bin all fip + +The resulting BL1 and FIP images may be found in: + +:: + + # Juno + ./build/juno/release/bl1.bin + ./build/juno/release/fip.bin + + # FVP + ./build/fvp/release/bl1.bin + ./build/fvp/release/fip.bin + +After building TF-A, the files ``bl1.bin``, ``fip.bin`` and ``scp_bl1.bin`` +need to be copied to the ``SOFTWARE/`` directory on the Juno SD card. + +Booting Firmware Update images +------------------------------ + +The new images must be programmed in flash memory by adding +an entry in the ``SITE1/HBI0262x/images.txt`` configuration file +on the Juno SD card (where ``x`` depends on the revision of the Juno board). +Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory +programming" for more information. User should ensure these do not +overlap with any other entries in the file. + +:: + + NOR10UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE + NOR10ADDRESS: 0x00400000 ;Image Flash Address [ns_bl2u_base_address] + NOR10FILE: \SOFTWARE\fwu_fip.bin ;Image File Name + NOR10LOAD: 00000000 ;Image Load Address + NOR10ENTRY: 00000000 ;Image Entry Point + + NOR11UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE + NOR11ADDRESS: 0x03EB8000 ;Image Flash Address [ns_bl1u_base_address] + NOR11FILE: \SOFTWARE\ns_bl1u.bin ;Image File Name + NOR11LOAD: 00000000 ;Image Load Address + +The address ns_bl1u_base_address is the value of NS_BL1U_BASE - 0x8000000. +In the same way, the address ns_bl2u_base_address is the value of +NS_BL2U_BASE - 0x8000000. + +.. _plat_juno_booting_el3_payload: + +Booting an EL3 payload +---------------------- + +If the EL3 payload is able to execute in place, it may be programmed in flash +memory by adding an entry in the ``SITE1/HBI0262x/images.txt`` configuration file +on the Juno SD card (where ``x`` depends on the revision of the Juno board). +Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory +programming" for more information. + +Alternatively, the same DS-5 command mentioned in the FVP section above can +be used to load the EL3 payload's ELF file over JTAG on Juno. + +For more information on EL3 payloads in general, see +:ref:`alt_boot_flows_el3_payload`. + +Booting a preloaded kernel image +-------------------------------- + +The Trusted Firmware must be compiled in a similar way as for FVP explained +above. The process to load binaries to memory is the one explained in +`plat_juno_booting_el3_payload`_. + +Testing System Suspend +---------------------- + +The SYSTEM SUSPEND is a PSCI API which can be used to implement system suspend +to RAM. For more details refer to section 5.16 of `PSCI`_. To test system suspend +on Juno, at the linux shell prompt, issue the following command: + +.. code:: shell + + echo +10 > /sys/class/rtc/rtc0/wakealarm + echo -n mem > /sys/power/state + +The Juno board should suspend to RAM and then wakeup after 10 seconds due to +wakeup interrupt from RTC. + +Additional Resources +-------------------- + +Please visit the `Arm Platforms Portal`_ to get support and obtain any other Juno +software information. Please also refer to the `Juno Getting Started Guide`_ to +get more detailed information about the Juno Arm development platform and how to +configure it. + +-------------- + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* + +.. _Linaro release software stack: http://releases.linaro.org/members/arm/platforms/ +.. _Juno platform software user guide: https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/about/docs/juno/user-guide.rst +.. _TF-A downloads page: https://downloads.trustedfirmware.org/tf-a/css_scp_2.8.0/juno/ +.. _build the binaries from source: https://github.com/ARM-software/SCP-firmware/blob/master/user_guide.md#scp-firmware-user-guide +.. _Arm Platforms Portal: https://community.arm.com/dev-platforms/ +.. _Juno Getting Started Guide: http://infocenter.arm.com/help/topic/com.arm.doc.dui0928e/DUI0928E_juno_arm_development_platform_gsg.pdf +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Juno Arm Development Platform: http://www.arm.com/products/tools/development-boards/versatile-express/juno-arm-development-platform.php diff --git a/arm-trusted-firmware/docs/plat/arm/morello/index.rst b/arm-trusted-firmware/docs/plat/arm/morello/index.rst new file mode 100644 index 0000000..b18001c --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/morello/index.rst @@ -0,0 +1,33 @@ +Morello Platform +================ + +Morello is an ARMv8-A platform that implements the capability architecture extension. +The platform port present at `site `_ +provides ARMv8-A architecture enablement. + +Capability architecture specific changes will be added `here `_ + +Further information on Morello Platform is available at `info `_ + +Boot Sequence +------------- + +The execution begins from SCP_BL1 which loads the SCP_BL2 and starts its +execution. SCP_BL2 powers up the AP which starts execution at AP_BL31. The AP +then continues executing and hands off execution to Non-secure world (UEFI). + +Build Procedure (TF-A only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Obtain arm `toolchain `_. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Build TF-A: + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + + make PLAT=morello all + +*Copyright (c) 2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/tc/index.rst b/arm-trusted-firmware/docs/plat/arm/tc/index.rst new file mode 100644 index 0000000..20d3e56 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/tc/index.rst @@ -0,0 +1,56 @@ +TC Total Compute Platform +========================== + +Some of the features of TC platform referenced in TF-A include: + +- A `System Control Processor `_ + to abstract power and system management tasks away from application + processors. The RAM firmware for SCP is included in the TF-A FIP and is + loaded by AP BL2 from FIP in flash to SRAM for copying by SCP (SCP has access + to AP SRAM). +- GICv4 +- Trusted Board Boot +- SCMI +- MHUv2 + +Currently, the main difference between TC0 (TARGET_PLATFORM=0) and TC1 +(TARGET_PLATFORM=1) platforms w.r.t to TF-A is the CPUs supported. TC0 has +support for Cortex A510, Cortex A710 and Cortex X2, while TC1 has support for +Cortex A510, Cortex Makalu and Cortex Makalu ELP Arm CPUs. + + +Boot Sequence +------------- + +The execution begins from SCP_BL1. SCP_BL1 powers up the AP which starts +executing AP_BL1 and then executes AP_BL2 which loads the SCP_BL2 from +FIP to SRAM. The SCP has access to AP SRAM. The address and size of SCP_BL2 +is communicated to SCP using SDS. SCP copies SCP_BL2 from SRAM to its own +RAM and starts executing it. The AP then continues executing the rest of TF-A +stages including BL31 runtime stage and hands off executing to +Non-secure world (u-boot). + +Build Procedure (TF-A only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Obtain arm `toolchain `_. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Build TF-A: + + .. code:: shell + + make PLAT=tc BL33= \ + SCP_BL2= TARGET_PLATFORM={0,1} all fip + + Enable TBBR by adding the following options to the make command: + + .. code:: shell + + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 \ + GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem + +*Copyright (c) 2020-2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/brcm-stingray.rst b/arm-trusted-firmware/docs/plat/brcm-stingray.rst new file mode 100644 index 0000000..95029cc --- /dev/null +++ b/arm-trusted-firmware/docs/plat/brcm-stingray.rst @@ -0,0 +1,43 @@ +Broadcom Stingray +================= + +Description +----------- +Broadcom's Stingray(BCM958742t) is a multi-core processor with 8 Cortex-A72 cores. +Trusted Firmware-A (TF-A) is used to implement secure world firmware, supporting +BL2 and BL31 for Broadcom Stingray SoCs. + +On Poweron, Boot ROM will load bl2 image and Bl2 will initialize the hardware, +then loads bl31 and bl33 into DDR and boots to bl33. + +Boot Sequence +------------- + +Bootrom --> TF-A BL2 --> TF-A BL31 --> BL33(u-boot) + +Code Locations +~~~~~~~~~~~~~~ +- Trusted Firmware-A: + `link `__ + +How to build +------------ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Prepare AARCH64 toolchain. + +- Build u-boot first, and get the binary image: u-boot.bin, + +- Build TF-A + + Build fip: + + .. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=stingray BOARD_CFG=bcm958742t all fip BL33=u-boot.bin + +Deploy TF-A Images +~~~~~~~~~~~~~~~~~~ +The u-boot will be upstreamed soon, this doc will be updated once they are ready, and the link will be posted. diff --git a/arm-trusted-firmware/docs/plat/deprecated.rst b/arm-trusted-firmware/docs/plat/deprecated.rst new file mode 100644 index 0000000..7cc4258 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/deprecated.rst @@ -0,0 +1,20 @@ +Deprecated platforms +==================== + +Process of deprecating a platform +--------------------------------- + +Platform can be deprecated and its source can be kept in repository for a cooling +off period before deleting it or it can be deleted straight away. For later types +Deprecated/Deleted version would be same. + +List of deprecated platforms +---------------------------- + ++----------------+----------------+--------------------+--------------------+ +| Platform | Vendor | Deprecated version | Deleted version | ++================+================+====================+====================+ +| sgm775 | Arm | 2.5 | 2.7 | ++----------------+----------------+--------------------+--------------------+ +| mt6795 | MTK | 2.5 | 2.7 | ++----------------+----------------+--------------------+--------------------+ diff --git a/arm-trusted-firmware/docs/plat/hikey.rst b/arm-trusted-firmware/docs/plat/hikey.rst new file mode 100644 index 0000000..6c488b8 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/hikey.rst @@ -0,0 +1,155 @@ +HiKey +===== + +HiKey is one of 96boards. Hisilicon Kirin6220 processor is installed on HiKey. + +More information are listed in `link`_. + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- OP-TEE + `link `__ + +- edk2: + `link `__ + +- OpenPlatformPkg: + `link `__ + +- l-loader: + `link `__ + +- atf-fastboot: + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + + .. code:: shell + + git clone https://github.com/ARM-software/arm-trusted-firmware -b integration + git clone https://github.com/OP-TEE/optee_os + git clone https://github.com/96boards-hikey/edk2 -b testing/hikey960_v2.5 + git clone https://github.com/96boards-hikey/OpenPlatformPkg -b testing/hikey960_v1.3.4 + git clone https://github.com/96boards-hikey/l-loader -b testing/hikey960_v1.2 + git clone https://github.com/96boards-hikey/atf-fastboot + +- Create the symbol link to OpenPlatformPkg in edk2. + + .. code:: shell + + $cd ${BUILD_PATH}/edk2 + $ln -sf ../OpenPlatformPkg + +- Prepare AARCH64 && AARCH32 toolchain. Prepare python. + +- If your hikey hardware is built by CircuitCo, update *OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dsc* first. *(optional)* + console on hikey.** + + .. code:: shell + + DEFINE SERIAL_BASE=0xF8015000 + + If your hikey hardware is built by LeMaker, nothing to do. + +- Build it as debug mode. Create your own build script file or you could refer to **build\_uefi.sh** in l-loader git repository. + + .. code:: shell + + cd {BUILD_PATH}/arm-trusted-firmware + sh ../l-loader/build_uefi.sh hikey + +- Generate l-loader.bin and partition table for aosp. The eMMC capacity is either 8GB or 4GB. Just change "aosp-8g" to "linux-8g" for debian. + + .. code:: shell + + cd ${BUILD_PATH}/l-loader + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl2.bin + ln -sf ${BUILD_PATH}/atf-fastboot/build/hikey/${FASTBOOT_BUILD_OPTION}/bl1.bin fastboot.bin + make hikey PTABLE_LST=aosp-8g + +Setup Console +------------- + +- Install ser2net. Use telnet as the console since UEFI fails to display Boot Manager GUI in minicom. **If you don't need Boot Manager GUI, just ignore this section.** + + .. code:: shell + + $sudo apt-get install ser2net + +- Configure ser2net. + + .. code:: shell + + $sudo vi /etc/ser2net.conf + + Append one line for serial-over-USB in below. + *#ser2net.conf* + + .. code:: shell + + 2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner + +- Start ser2net + + .. code:: shell + + $sudo killall ser2net + $sudo ser2net -u + +- Open the console. + + .. code:: shell + + $telnet localhost 2004 + + And you could open the console remotely, too. + +Flash images in recovery mode +----------------------------- + +- Make sure Pin3-Pin4 on J15 are connected for recovery mode. Then power on HiKey. + +- Remove the modemmanager package. This package may cause the idt tool failure. + + .. code:: shell + + $sudo apt-get purge modemmanager + +- Run the command to download recovery.bin into HiKey. + + .. code:: shell + + $sudo python hisi-idt.py -d /dev/ttyUSB1 --img1 recovery.bin + +- Update images. All aosp or debian images could be fetched from `link `__. + + .. code:: shell + + $sudo fastboot flash ptable prm_ptable.img + $sudo fastboot flash loader l-loader.bin + $sudo fastboot flash fastboot fip.bin + $sudo fastboot flash boot boot.img + $sudo fastboot flash cache cache.img + $sudo fastboot flash system system.img + $sudo fastboot flash userdata userdata.img + +Boot UEFI in normal mode +------------------------ + +- Make sure Pin3-Pin4 on J15 are open for normal boot mode. Then power on HiKey. + +- Reference `link `__ + +.. _link: https://www.96boards.org/documentation/consumer/hikey/ diff --git a/arm-trusted-firmware/docs/plat/hikey960.rst b/arm-trusted-firmware/docs/plat/hikey960.rst new file mode 100644 index 0000000..982c2c8 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/hikey960.rst @@ -0,0 +1,180 @@ +HiKey960 +======== + +HiKey960 is one of 96boards. Hisilicon Hi3660 processor is installed on HiKey960. + +More information are listed in `link`_. + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- OP-TEE: + `link `__ + +- edk2: + `link `__ + +- OpenPlatformPkg: + `link `__ + +- l-loader: + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 5 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + + .. code:: shell + + git clone https://github.com/ARM-software/arm-trusted-firmware -b integration + git clone https://github.com/OP-TEE/optee_os + git clone https://github.com/96boards-hikey/edk2 -b testing/hikey960_v2.5 + git clone https://github.com/96boards-hikey/OpenPlatformPkg -b testing/hikey960_v1.3.4 + git clone https://github.com/96boards-hikey/l-loader -b testing/hikey960_v1.2 + +- Create the symbol link to OpenPlatformPkg in edk2. + + .. code:: shell + + $cd ${BUILD_PATH}/edk2 + $ln -sf ../OpenPlatformPkg + +- Prepare AARCH64 toolchain. + +- If your hikey960 hardware is v1, update *OpenPlatformPkg/Platforms/Hisilicon/HiKey960/HiKey960.dsc* first. *(optional)* + + .. code:: shell + + DEFINE SERIAL_BASE=0xFDF05000 + + If your hikey960 hardware is v2 or newer, nothing to do. + +- Build it as debug mode. Create script file for build. + + .. code:: shell + + cd {BUILD_PATH}/arm-trusted-firmware + sh ../l-loader/build_uefi.sh hikey960 + +- Generate l-loader.bin and partition table. + *Make sure that you're using the sgdisk in the l-loader directory.* + + .. code:: shell + + cd ${BUILD_PATH}/l-loader + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl2.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/BL33_AP_UEFI.fd + make hikey960 + +Setup Console +------------- + +- Install ser2net. Use telnet as the console since UEFI will output window + that fails to display in minicom. + + .. code:: shell + + $sudo apt-get install ser2net + +- Configure ser2net. + + .. code:: shell + + $sudo vi /etc/ser2net.conf + + Append one line for serial-over-USB in *#ser2net.conf* + + :: + + 2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner + +- Start ser2net + + .. code:: shell + + $sudo killall ser2net + $sudo ser2net -u + +- Open the console. + + .. code:: shell + + $telnet localhost 2004 + + And you could open the console remotely, too. + +Boot UEFI in recovery mode +-------------------------- + +- Fetch that are used in recovery mode. The code location is in below. + `link `__ + +- Prepare recovery binary. + + .. code:: shell + + $cd tools-images-hikey960 + $ln -sf ${BUILD_PATH}/l-loader/l-loader.bin + $ln -sf ${BUILD_PATH}/l-loader/fip.bin + $ln -sf ${BUILD_PATH}/l-loader/recovery.bin + +- Prepare config file. + + .. code:: shell + + $vi config + # The content of config file + ./sec_usb_xloader.img 0x00020000 + ./sec_uce_boot.img 0x6A908000 + ./recovery.bin 0x1AC00000 + +- Remove the modemmanager package. This package may causes hikey\_idt tool failure. + + .. code:: shell + + $sudo apt-get purge modemmanager + +- Run the command to download recovery.bin into HiKey960. + + .. code:: shell + + $sudo ./hikey_idt -c config -p /dev/ttyUSB1 + +- UEFI running in recovery mode. + When prompt '.' is displayed on console, press hotkey 'f' in keyboard. Then Android fastboot app is running. + The timeout of prompt '.' is 10 seconds. + +- Update images. + + .. code:: shell + + $sudo fastboot flash ptable prm_ptable.img + $sudo fastboot flash xloader sec_xloader.img + $sudo fastboot flash fastboot l-loader.bin + $sudo fastboot flash fip fip.bin + $sudo fastboot flash boot boot.img + $sudo fastboot flash cache cache.img + $sudo fastboot flash system system.img + $sudo fastboot flash userdata userdata.img + +- Notice: UEFI could also boot kernel in recovery mode, but BL31 isn't loaded in + recovery mode. + +Boot UEFI in normal mode +------------------------ + +- Make sure "Boot Mode" switch is OFF for normal boot mode. Then power on HiKey960. + +- Reference `link `__ + +.. _link: https://www.96boards.org/documentation/consumer/hikey/hikey960 diff --git a/arm-trusted-firmware/docs/plat/imx8.rst b/arm-trusted-firmware/docs/plat/imx8.rst new file mode 100644 index 0000000..49ba374 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/imx8.rst @@ -0,0 +1,58 @@ +NXP i.MX 8 Series +================= + +The i.MX 8 series of applications processors is a feature- and +performance-scalable multi-core platform that includes single-, +dual-, and quad-core families based on the Arm® Cortex® +architecture—including combined Cortex-A72 + Cortex-A53, +Cortex-A35, and Cortex-M4 based solutions for advanced graphics, +imaging, machine vision, audio, voice, video, and safety-critical +applications. + +The i.MX8QM is with 2 Cortex-A72 ARM core, 4 Cortex-A53 ARM core +and 1 Cortex-M4 system controller. + +The i.MX8QX is with 4 Cortex-A35 ARM core and 1 Cortex-M4 system +controller. + +The System Controller (SC) represents the evolution of centralized +control for system-level resources on i.MX8. The heart of the system +controller is a Cortex-M4 that executes system controller firmware. + +Boot Sequence +------------- + +Bootrom --> BL31 --> BL33(u-boot) --> Linux kernel + +How to build +------------ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Prepare AARCH64 toolchain. + +- Build System Controller Firmware and u-boot firstly, and get binary images: scfw_tcm.bin and u-boot.bin + +- Build TF-A + + Build bl31: + + .. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT= bl31 + + Target_SoC should be "imx8qm" for i.MX8QM SoC. + Target_SoC should be "imx8qx" for i.MX8QX SoC. + +Deploy TF-A Images +~~~~~~~~~~~~~~~~~~ + +TF-A binary(bl31.bin), scfw_tcm.bin and u-boot.bin are combined together +to generate a binary file called flash.bin, the imx-mkimage tool is used +to generate flash.bin, and flash.bin needs to be flashed into SD card +with certain offset for BOOT ROM. The system controller firmware, +u-boot and imx-mkimage will be upstreamed soon, this doc will be updated +once they are ready, and the link will be posted. + +.. _i.MX8: https://www.nxp.com/products/processors-and-microcontrollers/applications-processors/i.mx-applications-processors/i.mx-8-processors/i.mx-8-family-arm-cortex-a53-cortex-a72-virtualization-vision-3d-graphics-4k-video:i.MX8 diff --git a/arm-trusted-firmware/docs/plat/imx8m.rst b/arm-trusted-firmware/docs/plat/imx8m.rst new file mode 100644 index 0000000..101d52b --- /dev/null +++ b/arm-trusted-firmware/docs/plat/imx8m.rst @@ -0,0 +1,70 @@ +NXP i.MX 8M Series +================== + +The i.MX 8M family of applications processors based on Arm Corte-A53 and Cortex-M4 +cores provide high-performance computing, power efficiency, enhanced system +reliability and embedded security needed to drive the growth of fast-growing +edge node computing, streaming multimedia, and machine learning applications. + +imx8mq is dropped in TF-A CI build due to the small OCRAM size, but still actively +maintained in NXP official release. + +Boot Sequence +------------- + +Bootrom --> SPL --> BL31 --> BL33(u-boot) --> Linux kernel + +How to build +------------ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Prepare AARCH64 toolchain. + +- Build spl and u-boot firstly, and get binary images: u-boot-spl.bin, + u-boot-nodtb.bin and dtb for the target board. + +- Build TF-A + + Build bl31: + + .. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT= bl31 + + Target_SoC should be "imx8mq" for i.MX8MQ SoC. + Target_SoC should be "imx8mm" for i.MX8MM SoC. + Target_SoC should be "imx8mn" for i.MX8MN SoC. + Target_SoC should be "imx8mp" for i.MX8MP SoC. + +Deploy TF-A Images +~~~~~~~~~~~~~~~~~~ + +TF-A binary(bl31.bin), u-boot-spl.bin u-boot-nodtb.bin and dtb are combined +together to generate a binary file called flash.bin, the imx-mkimage tool is +used to generate flash.bin, and flash.bin needs to be flashed into SD card +with certain offset for BOOT ROM. the u-boot and imx-mkimage will be upstreamed +soon, this doc will be updated once they are ready, and the link will be posted. + +TBBR Boot Sequence +------------------ + +When setting NEED_BL2=1 on imx8mm. We support an alternative way of +boot sequence to support TBBR. + +Bootrom --> SPL --> BL2 --> BL31 --> BL33(u-boot with UEFI) --> grub + +This helps us to fulfill the SystemReady EBBR standard. +BL2 will be in the FIT image and SPL will verify it. +All of the BL3x will be put in the FIP image. BL2 will verify them. +In U-boot we turn on the UEFI secure boot features so it can verify +grub. And we use grub to verify linux kernel. + +Measured Boot +------------- + +When setting MEASURED_BOOT=1 on imx8mm we can let TF-A generate event logs +with a DTB overlay. The overlay will be put at PLAT_IMX8M_DTO_BASE with +maximum size PLAT_IMX8M_DTO_MAX_SIZE. Then in U-boot we can apply the DTB +overlay and let U-boot to parse the event log and update the PCRs. diff --git a/arm-trusted-firmware/docs/plat/index.rst b/arm-trusted-firmware/docs/plat/index.rst new file mode 100644 index 0000000..0cef16a --- /dev/null +++ b/arm-trusted-firmware/docs/plat/index.rst @@ -0,0 +1,66 @@ +Platform Ports +============== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + :hidden: + + allwinner + arm/index + deprecated + meson-axg + meson-gxbb + meson-gxl + meson-g12a + hikey + hikey960 + intel-agilex + intel-stratix10 + marvell/index + mt8183 + mt8186 + mt8192 + mt8195 + nvidia-tegra + warp7 + imx8 + imx8m + nxp/index + poplar + qemu + qemu-sbsa + qti + qti-msm8916 + rpi3 + rpi4 + rcar-gen3 + rz-g2 + rockchip + socionext-uniphier + synquacer + stm32mp1 + ti-k3 + xilinx-versal + xilinx-zynqmp + brcm-stingray + +This section provides a list of supported upstream *platform ports* and the +documentation associated with them. + +.. note:: + In addition to the platforms ports listed within the table of contents, there + are several additional platforms that are supported upstream but which do not + currently have associated documentation: + + - Arm Neoverse N1 System Development Platform (N1SDP) + - Arm Neoverse Reference Design N1 Edge (RD-N1-Edge) FVP + - Arm Neoverse Reference Design E1 Edge (RD-E1-Edge) FVP + - Arm SGI-575 and SGM-775 + - MediaTek MT6795 and MT8173 SoCs + - Arm Morello Platform + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/intel-agilex.rst b/arm-trusted-firmware/docs/plat/intel-agilex.rst new file mode 100644 index 0000000..ff27b6b --- /dev/null +++ b/arm-trusted-firmware/docs/plat/intel-agilex.rst @@ -0,0 +1,86 @@ +Intel Agilex SoCFPGA +======================== + +Agilex SoCFPGA is a FPGA with integrated quad-core 64-bit Arm Cortex A53 processor. + +Upon boot, Boot ROM loads bl2 into OCRAM. Bl2 subsequently initializes +the hardware, then loads bl31 and bl33 (UEFI) into DDR and boots to bl33. + +:: + + Boot ROM --> Trusted Firmware-A --> UEFI + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- UEFI (to be updated with new upstreamed UEFI): + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 2 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Prepare the AARCH64 toolchain. + +- Build UEFI using Agilex platform as configuration + This will be updated to use an updated UEFI using the latest EDK2 source + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- device=agx + +- Build atf providing the previously generated UEFI as the BL33 image + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- bl2 fip PLAT=agilex + BL33=PEI.ROM + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- dd fip.bin to a A2 partition on the MMC drive to be booted in Agilex + board. + +- Generate a SOF containing bl2 + +.. code:: bash + + aarch64-linux-gnu-objcopy -I binary -O ihex --change-addresses 0xffe00000 bl2.bin bl2.hex + quartus_cpf --bootloader bl2.hex + +- Configure SOF to board + +.. code:: bash + + nios2-configure-sof + +Boot trace +---------- + +:: + + INFO: DDR: DRAM calibration success. + INFO: ECC is disabled. + NOTICE: BL2: v2.1(debug) + NOTICE: BL2: Built + INFO: BL2: Doing platform setup + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0xffe1c000 + INFO: SPSR = 0x3cd + NOTICE: BL31: v2.1(debug) + NOTICE: BL31: Built + INFO: ARM GICv2 driver initialized + INFO: BL31: Initializing runtime services + WARNING: BL31: cortex_a53 + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x50000 + INFO: SPSR = 0x3c9 diff --git a/arm-trusted-firmware/docs/plat/intel-stratix10.rst b/arm-trusted-firmware/docs/plat/intel-stratix10.rst new file mode 100644 index 0000000..7f8d18e --- /dev/null +++ b/arm-trusted-firmware/docs/plat/intel-stratix10.rst @@ -0,0 +1,94 @@ +Intel Stratix 10 SoCFPGA +======================== + +Stratix 10 SoCFPGA is a FPGA with integrated quad-core 64-bit Arm Cortex A53 processor. + +Upon boot, Boot ROM loads bl2 into OCRAM. Bl2 subsequently initializes +the hardware, then loads bl31 and bl33 (UEFI) into DDR and boots to bl33. + +:: + + Boot ROM --> Trusted Firmware-A --> UEFI + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- UEFI (to be updated with new upstreamed UEFI): + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 2 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Prepare the AARCH64 toolchain. + +- Build UEFI using Stratix 10 platform as configuration + This will be updated to use an updated UEFI using the latest EDK2 source + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- device=s10 + +- Build atf providing the previously generated UEFI as the BL33 image + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- bl2 fip PLAT=stratix10 + BL33=PEI.ROM + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- dd fip.bin to a A2 partition on the MMC drive to be booted in Stratix 10 + board. + +- Generate a SOF containing bl2 + +.. code:: bash + + aarch64-linux-gnu-objcopy -I binary -O ihex --change-addresses 0xffe00000 bl2.bin bl2.hex + quartus_cpf --bootloader bl2.hex + +- Configure SOF to board + +.. code:: bash + + nios2-configure-sof + +Boot trace +---------- + +:: + + INFO: DDR: DRAM calibration success. + INFO: ECC is disabled. + INFO: Init HPS NOC's DDR Scheduler. + NOTICE: BL2: v2.0(debug):v2.0-809-g7f8474a-dirty + NOTICE: BL2: Built : 17:38:19, Feb 18 2019 + INFO: BL2: Doing platform setup + INFO: BL2: Loading image id 3 + INFO: Loading image id=3 at address 0xffe1c000 + INFO: Image id=3 loaded: 0xffe1c000 - 0xffe24034 + INFO: BL2: Loading image id 5 + INFO: Loading image id=5 at address 0x50000 + INFO: Image id=5 loaded: 0x50000 - 0x550000 + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0xffe1c000 + INFO: SPSR = 0x3cd + NOTICE: BL31: v2.0(debug):v2.0-810-g788c436-dirty + NOTICE: BL31: Built : 15:17:16, Feb 20 2019 + INFO: ARM GICv2 driver initialized + INFO: BL31: Initializing runtime services + WARNING: BL31: cortex_a53: CPU workaround for 855873 was missing! + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x50000 + INFO: SPSR = 0x3c9 + UEFI firmware (version 1.0 built at 11:26:18 on Nov 7 2018) diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/build.rst b/arm-trusted-firmware/docs/plat/marvell/armada/build.rst new file mode 100644 index 0000000..adb9603 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/build.rst @@ -0,0 +1,476 @@ +TF-A Build Instructions for Marvell Platforms +============================================= + +This section describes how to compile the Trusted Firmware-A (TF-A) project for Marvell's platforms. + +Build Instructions +------------------ +(1) Set the cross compiler + + .. code:: shell + + > export CROSS_COMPILE=/path/to/toolchain/aarch64-linux-gnu- + +(2) Set path for FIP images: + +Set U-Boot image path (relatively to TF-A root or absolute path) + + .. code:: shell + + > export BL33=path/to/u-boot.bin + +For example: if U-Boot project (and its images) is located at ``~/project/u-boot``, +BL33 should be ``~/project/u-boot/u-boot.bin`` + + .. note:: + + *u-boot.bin* should be used and not *u-boot-spl.bin* + +Set MSS/SCP image path (mandatory only for A7K/8K/CN913x when MSS_SUPPORT=1) + + .. code:: shell + + > export SCP_BL2=path/to/mrvl_scp_bl2*.img + +(3) Armada-37x0 build requires WTP tools installation. + +See below in the section "Tools and external components installation". +Install ARM 32-bit cross compiler, which is required for building WTMI image for CM3 + + .. code:: shell + + > sudo apt-get install gcc-arm-linux-gnueabi + +(4) Clean previous build residuals (if any) + + .. code:: shell + + > make distclean + +(5) Build TF-A + +There are several build options: + +- PLAT + + Supported Marvell platforms are: + + - a3700 - A3720 DB, EspressoBin and Turris MOX + - a70x0 + - a70x0_amc - AMC board + - a70x0_mochabin - Globalscale MOCHAbin + - a80x0 + - a80x0_mcbin - MacchiatoBin + - a80x0_puzzle - IEI Puzzle-M801 + - t9130 - CN913x + - t9130_cex7_eval - CN913x CEx7 Evaluation Board + +- DEBUG + + Default is without debug information (=0). in order to enable it use ``DEBUG=1``. + Can be enabled also when building UART recovery images, there is no issue with it. + + Production TF-A images should be built without this debug option! + +- LOG_LEVEL + + Defines the level of logging which will be purged to the default output port. + + - 0 - LOG_LEVEL_NONE + - 10 - LOG_LEVEL_ERROR + - 20 - LOG_LEVEL_NOTICE (default for DEBUG=0) + - 30 - LOG_LEVEL_WARNING + - 40 - LOG_LEVEL_INFO (default for DEBUG=1) + - 50 - LOG_LEVEL_VERBOSE + +- USE_COHERENT_MEM + + This flag determines whether to include the coherent memory region in the + BL memory map or not. Enabled by default. + +- LLC_ENABLE + + Flag defining the LLC (L3) cache state. The cache is enabled by default (``LLC_ENABLE=1``). + +- LLC_SRAM + + Flag enabling the LLC (L3) cache SRAM support. The LLC SRAM is activated and used + by Trusted OS (OP-TEE OS, BL32). The TF-A only prepares CCU address translation windows + for SRAM address range at BL31 execution stage with window target set to DRAM-0. + When Trusted OS activates LLC SRAM, the CCU window target is changed to SRAM. + There is no reason to enable this feature if OP-TEE OS built with CFG_WITH_PAGER=n. + Only set LLC_SRAM=1 if OP-TEE OS is built with CFG_WITH_PAGER=y. + +- MARVELL_SECURE_BOOT + + Build trusted(=1)/non trusted(=0) image, default is non trusted. + This parameter is used only for ``mrvl_flash`` and ``mrvl_uart`` targets. + +- MV_DDR_PATH + + This parameter is required for ``mrvl_flash`` and ``mrvl_uart`` targets. + For A7K/8K/CN913x it is used for BLE build and for Armada37x0 it used + for ddr_tool build. + + Specify path to the full checkout of Marvell mv-ddr-marvell git + repository. Checkout must contain also .git subdirectory because + mv-ddr build process calls git commands. + + Do not remove any parts of git checkout becuase build process and other + applications need them for correct building and version determination. + + +CN913x specific build options: + +- CP_NUM + + Total amount of CPs (South Bridge) connected to AP. When the parameter is omitted, + the build uses the default number of CPs, which is a number of embedded CPs inside the + package: 1 or 2 depending on the SoC used. The parameter is valid for OcteonTX2 CN913x SoC + family (PLAT=t9130), which can have external CPs connected to the MCI ports. Valid + values with CP_NUM are in a range of 1 to 3. + + +A7K/8K/CN913x specific build options: + +- BLE_PATH + + Points to BLE (Binary ROM extension) sources folder. + The parameter is optional, its default value is ``plat/marvell/armada/a8k/common/ble`` + which uses TF-A in-tree BLE implementation. + +- MSS_SUPPORT + + When ``MSS_SUPPORT=1``, then TF-A includes support for Management SubSystem (MSS). + When enabled it is required to specify path to the MSS firmware image via ``SCP_BL2`` + option. + + This option is by default enabled. + +- SCP_BL2 + + Specify path to the MSS fimware image binary which will run on Cortex-M3 coprocessor. + It is available in Marvell binaries-marvell git repository. Required when ``MSS_SUPPORT=1``. + +Globalscale MOCHAbin specific build options: + +- DDR_TOPOLOGY + + The DDR topology map index/name, default is 0. + + Supported Options: + - 0 - DDR4 1CS 2GB + - 1 - DDR4 1CS 4GB + - 2 - DDR4 2CS 8GB + +Armada37x0 specific build options: + +- HANDLE_EA_EL3_FIRST + + When ``HANDLE_EA_EL3_FIRST=1``, External Aborts and SError Interrupts will be always trapped + in TF-A. TF-A in this case enables dirty hack / workaround for a bug found in U-Boot and + Linux kernel PCIe controller driver pci-aardvark.c, traps and then masks SError interrupt + caused by AXI SLVERR on external access (syndrome 0xbf000002). + + Otherwise when ``HANDLE_EA_EL3_FIRST=0``, these exceptions will be trapped in the current + exception level (or in EL1 if the current exception level is EL0). So exceptions caused by + U-Boot will be trapped in U-Boot, exceptions caused by Linux kernel (or user applications) + will be trapped in Linux kernel. + + Mentioned bug in pci-aardvark.c driver is fixed in U-Boot version v2021.07 and Linux kernel + version v5.13 (workarounded since Linux kernel version 5.9) and also backported in Linux + kernel stable releases since versions v5.12.13, v5.10.46, v5.4.128, v4.19.198, v4.14.240. + + If target system has already patched version of U-Boot and Linux kernel then it is strongly + recommended to not enable this workaround as it disallows propagating of all External Aborts + to running Linux kernel and makes correctable errors as fatal aborts. + + This option is now disabled by default. In past this option was enabled by default in + TF-A versions v2.2, v2.3, v2.4 and v2.5. + +- CM3_SYSTEM_RESET + + When ``CM3_SYSTEM_RESET=1``, the Cortex-M3 secure coprocessor will be used for system reset. + + TF-A will send command 0x0009 with a magic value via the rWTM mailbox interface to the + Cortex-M3 secure coprocessor. + The firmware running in the coprocessor must either implement this functionality or + ignore the 0x0009 command (which is true for the firmware from A3700-utils-marvell + repository). If this option is enabled but the firmware does not support this command, + an error message will be printed prior trying to reboot via the usual way. + + This option is needed on Turris MOX as a workaround to a HW bug which causes reset to + sometime hang the board. + +- A3720_DB_PM_WAKEUP_SRC + + For Armada 3720 Development Board only, when ``A3720_DB_PM_WAKEUP_SRC=1``, + TF-A will setup PM wake up src configuration. This option is disabled by default. + + +Armada37x0 specific build options for ``mrvl_flash`` and ``mrvl_uart`` targets: + +- DDR_TOPOLOGY + + The DDR topology map index/name, default is 0. + + Supported Options: + - 0 - DDR3 1CS 512MB (DB-88F3720-DDR3-Modular, EspressoBin V3-V5) + - 1 - DDR4 1CS 512MB (DB-88F3720-DDR4-Modular) + - 2 - DDR3 2CS 1GB (EspressoBin V3-V5) + - 3 - DDR4 2CS 4GB (DB-88F3720-DDR4-Modular) + - 4 - DDR3 1CS 1GB (DB-88F3720-DDR3-Modular, EspressoBin V3-V5) + - 5 - DDR4 1CS 1GB (EspressoBin V7, EspressoBin-Ultra) + - 6 - DDR4 2CS 2GB (EspressoBin V7) + - 7 - DDR3 2CS 2GB (EspressoBin V3-V5) + - CUST - CUSTOMER BOARD (Customer board settings) + +- CLOCKSPRESET + + The clock tree configuration preset including CPU and DDR frequency, + default is CPU_800_DDR_800. + + - CPU_600_DDR_600 - CPU at 600 MHz, DDR at 600 MHz + - CPU_800_DDR_800 - CPU at 800 MHz, DDR at 800 MHz + - CPU_1000_DDR_800 - CPU at 1000 MHz, DDR at 800 MHz + - CPU_1200_DDR_750 - CPU at 1200 MHz, DDR at 750 MHz + + Look at Armada37x0 chip package marking on board to identify correct CPU frequency. + The last line on package marking (next line after the 88F37x0 line) should contain: + + - C080 or I080 - chip with 800 MHz CPU - use ``CLOCKSPRESET=CPU_800_DDR_800`` + - C100 or I100 - chip with 1000 MHz CPU - use ``CLOCKSPRESET=CPU_1000_DDR_800`` + - C120 - chip with 1200 MHz CPU - use ``CLOCKSPRESET=CPU_1200_DDR_750`` + +- BOOTDEV + + The flash boot device, default is ``SPINOR``. + + Currently, Armada37x0 only supports ``SPINOR``, ``SPINAND``, ``EMMCNORM`` and ``SATA``: + + - SPINOR - SPI NOR flash boot + - SPINAND - SPI NAND flash boot + - EMMCNORM - eMMC Download Mode + + Download boot loader or program code from eMMC flash into CM3 or CA53 + Requires full initialization and command sequence + + - SATA - SATA device boot + + Image needs to be stored at disk LBA 0 or at disk partition with + MBR type 0x4d (ASCII 'M' as in Marvell) or at disk partition with + GPT partition type GUID ``6828311A-BA55-42A4-BCDE-A89BB5EDECAE``. + +- PARTNUM + + The boot partition number, default is 0. + + To boot from eMMC, the value should be aligned with the parameter in + U-Boot with name of ``CONFIG_SYS_MMC_ENV_PART``, whose value by default is + 1. For details about CONFIG_SYS_MMC_ENV_PART, please refer to the U-Boot + build instructions. + +- WTMI_IMG + + The path of the binary can point to an image which + does nothing, an image which supports EFUSE or a customized CM3 firmware + binary. The default image is ``fuse.bin`` that built from sources in WTP + folder, which is the next option. If the default image is OK, then this + option should be skipped. + + Please note that this is not a full WTMI image, just a main loop without + hardware initialization code. Final WTMI image is built from this WTMI_IMG + binary and sys-init code from the WTP directory which sets DDR and CPU + clocks according to DDR_TOPOLOGY and CLOCKSPRESET options. + + CZ.NIC as part of Turris project released free and open source WTMI + application firmware ``wtmi_app.bin`` for all Armada 3720 devices. + This firmware includes additional features like access to Hardware + Random Number Generator of Armada 3720 SoC which original Marvell's + ``fuse.bin`` image does not have. + + CZ.NIC's Armada 3720 Secure Firmware is available at website: + + https://gitlab.nic.cz/turris/mox-boot-builder/ + +- WTP + + Specify path to the full checkout of Marvell A3700-utils-marvell git + repository. Checkout must contain also .git subdirectory because WTP + build process calls git commands. + + WTP build process uses also Marvell mv-ddr-marvell git repository + specified in MV_DDR_PATH option. + + Do not remove any parts of git checkout becuase build process and other + applications need them for correct building and version determination. + +- CRYPTOPP_PATH + + Use this parameter to point to Crypto++ source code + directory. If this option is specified then Crypto++ source code in + CRYPTOPP_PATH directory will be automatically compiled. Crypto++ library + is required for building WTP image tool. Either CRYPTOPP_PATH or + CRYPTOPP_LIBDIR with CRYPTOPP_INCDIR needs to be specified for Armada37x0. + +- CRYPTOPP_LIBDIR + + Use this parameter to point to the directory with + compiled Crypto++ library. By default it points to the CRYPTOPP_PATH. + + On Debian systems it is possible to install system-wide Crypto++ library + via command ``apt install libcrypto++-dev`` and specify CRYPTOPP_LIBDIR + to ``/usr/lib/``. + +- CRYPTOPP_INCDIR + + Use this parameter to point to the directory with + header files of Crypto++ library. By default it points to the CRYPTOPP_PATH. + + On Debian systems it is possible to install system-wide Crypto++ library + via command ``apt install libcrypto++-dev`` and specify CRYPTOPP_INCDIR + to ``/usr/include/crypto++/``. + + +For example, in order to build the image in debug mode with log level up to 'notice' level run + +.. code:: shell + + > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 PLAT= mrvl_flash + +And if we want to build a Armada37x0 image in debug mode with log level up to 'notice' level, +the image has the preset CPU at 1000 MHz, preset DDR3 at 800 MHz, the DDR topology of DDR4 2CS, +the image boot from SPI NOR flash partition 0, and the image is non trusted in WTP, the command +line is as following + +.. code:: shell + + > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 CLOCKSPRESET=CPU_1000_DDR_800 \ + MARVELL_SECURE_BOOT=0 DDR_TOPOLOGY=3 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 \ + MV_DDR_PATH=/path/to/mv-ddr-marvell/ WTP=/path/to/A3700-utils-marvell/ \ + CRYPTOPP_PATH=/path/to/cryptopp/ BL33=/path/to/u-boot.bin \ + all fip mrvl_bootimage mrvl_flash mrvl_uart + +To build just TF-A without WTMI image (useful for A3720 Turris MOX board), run following command: + +.. code:: shell + + > make USE_COHERENT_MEM=0 PLAT=a3700 CM3_SYSTEM_RESET=1 BL33=/path/to/u-boot.bin \ + CROSS_COMPILE=aarch64-linux-gnu- mrvl_bootimage + +Here is full example how to build production release of Marvell firmware image (concatenated +binary of Marvell's A3720 sys-init, CZ.NIC's Armada 3720 Secure Firmware, TF-A and U-Boot) for +EspressoBin board (PLAT=a3700) with 1GHz CPU (CLOCKSPRESET=CPU_1000_DDR_800) and +1GB DDR4 RAM (DDR_TOPOLOGY=5): + +.. code:: shell + + > git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git + > git clone https://source.denx.de/u-boot/u-boot.git + > git clone https://github.com/weidai11/cryptopp.git + > git clone https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git + > git clone https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git + > git clone https://gitlab.nic.cz/turris/mox-boot-builder.git + > make -C u-boot CROSS_COMPILE=aarch64-linux-gnu- mvebu_espressobin-88f3720_defconfig u-boot.bin + > make -C mox-boot-builder CROSS_CM3=arm-linux-gnueabi- wtmi_app.bin + > make -C trusted-firmware-a CROSS_COMPILE=aarch64-linux-gnu- CROSS_CM3=arm-linux-gnueabi- \ + USE_COHERENT_MEM=0 PLAT=a3700 CLOCKSPRESET=CPU_1000_DDR_800 DDR_TOPOLOGY=5 \ + MV_DDR_PATH=$PWD/mv-ddr-marvell/ WTP=$PWD/A3700-utils-marvell/ \ + CRYPTOPP_PATH=$PWD/cryptopp/ BL33=$PWD/u-boot/u-boot.bin \ + WTMI_IMG=$PWD/mox-boot-builder/wtmi_app.bin FIP_ALIGN=0x100 mrvl_flash + +Produced Marvell firmware flash image: ``trusted-firmware-a/build/a3700/release/flash-image.bin`` + +Special Build Flags +-------------------- + +- PLAT_RECOVERY_IMAGE_ENABLE + When set this option to enable secondary recovery function when build atf. + In order to build UART recovery image this operation should be disabled for + A7K/8K/CN913x because of hardware limitation (boot from secondary image + can interrupt UART recovery process). This MACRO definition is set in + ``plat/marvell/armada/a8k/common/include/platform_def.h`` file. + +- DDR32 + In order to work in 32bit DDR, instead of the default 64bit ECC DDR, + this flag should be set to 1. + +For more information about build options, please refer to the +:ref:`Build Options` document. + + +Build output +------------ +Marvell's TF-A compilation generates 8 files: + + - ble.bin - BLe image (not available for Armada37x0) + - bl1.bin - BL1 image + - bl2.bin - BL2 image + - bl31.bin - BL31 image + - fip.bin - FIP image (contains BL2, BL31 & BL33 (U-Boot) images) + - boot-image.bin - TF-A image (contains BL1 and FIP images) + - flash-image.bin - Flashable Marvell firmware image. For Armada37x0 it + contains TIM, WTMI and boot-image.bin images. For other platforms it contains + BLe and boot-image.bin images. Should be placed on the boot flash/device. + - uart-images.tgz.bin - GZIPed TAR archive which contains Armada37x0 images + for booting via UART. Could be loaded via Marvell's WtpDownload tool from + A3700-utils-marvell repository. + +Additional make target ``mrvl_bootimage`` produce ``boot-image.bin`` file. Target +``mrvl_flash`` produce final ``flash-image.bin`` file and target ``mrvl_uart`` +produce ``uart-images.tgz.bin`` file. + + +Tools and external components installation +------------------------------------------ + +Armada37x0 Builds require installation of additional components +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(1) ARM cross compiler capable of building images for the service CPU (CM3). + This component is usually included in the Linux host packages. + On Debian/Ubuntu hosts the default GNU ARM tool chain can be installed + using the following command + + .. code:: shell + + > sudo apt-get install gcc-arm-linux-gnueabi + + Only if required, the default tool chain prefix ``arm-linux-gnueabi-`` can be + overwritten using the environment variable ``CROSS_CM3``. + Example for BASH shell + + .. code:: shell + + > export CROSS_CM3=/opt/arm-cross/bin/arm-linux-gnueabi + +(2) DDR initialization library sources (mv_ddr) available at the following repository + (use the "master" branch): + + https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git + +(3) Armada3700 tools available at the following repository + (use the "master" branch): + + https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git + +(4) Crypto++ library available at the following repository: + + https://github.com/weidai11/cryptopp.git + +(5) Optional CZ.NIC's Armada 3720 Secure Firmware: + + https://gitlab.nic.cz/turris/mox-boot-builder.git + +Armada70x0, Armada80x0 and CN913x Builds require installation of additional components +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(1) DDR initialization library sources (mv_ddr) available at the following repository + (use the "master" branch): + + https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git + +(2) MSS Management SubSystem Firmware available at the following repository + (use the "binaries-marvell-armada-SDK10.0.1.0" branch): + + https://github.com/MarvellEmbeddedProcessors/binaries-marvell.git diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst new file mode 100644 index 0000000..e88a458 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst @@ -0,0 +1,49 @@ +Address decoding flow and address translation units of Marvell Armada 8K SoC family +=================================================================================== + +:: + + +--------------------------------------------------------------------------------------------------+ + | +-------------+ +--------------+ | + | | Memory +----- DRAM CS | | + |+------------+ +-----------+ +-----------+ | Controller | +--------------+ | + || AP DMA | | | | | +-------------+ | + || SD/eMMC | | CA72 CPUs | | AP MSS | +-------------+ | + || MCI-0/1 | | | | | | Memory | | + |+------+-----+ +--+--------+ +--------+--+ +------------+ | Controller | +-------------+ | + | | | | | +----- Translaton | |AP | | + | | | | | | +-------------+ |Configuration| | + | | | +-----+ +-------------------------Space | | + | | | +-------------+ | CCU | +-------------+ | + | | | | MMU +---------+ Windows | +-----------+ +-------------+ | + | | +-| translation | | Lookup +---- +--------- AP SPI | | + | | +-------------+ | | | | +-------------+ | + | | +-------------+ | | | IO | +-------------+ | + | +------------| SMMU +---------+ | | Windows +--------- AP MCI0/1 | | + | | translation | +------------+ | Lookup | +-------------+ | + | +---------+---+ | | +-------------+ | + | - | | +--------- AP STM | | + | +----------------- | | +-------------+ | + | AP | | +-+---------+ | + +---------------------------------------------------------------|----------------------------------+ + +-------------|-------------------------------------------------|----------------------------------+ + | CP | +-------------+ +------+-----+ +-------------------+ | + | | | | | +------- SB CFG Space | | + | | | DIOB | | | +-------------------+ | + | | | Windows ----------------- IOB | +-------------------+ | + | | | Control | | Windows +------| SB PCIe-0 - PCIe2 | | + | | | | | Lookup | +-------------------+ | + | | +------+------+ | | +-------------------+ | + | | | | +------+ SB NAND | | + | | | +------+-----+ +-------------------+ | + | | | | | + | | | | | + | +------------------+ +------------+ +------+-----+ +-------------------+ | + | | Network Engine | | | | +------- SB SPI-0/SPI-1 | | + | | Security Engine | | PCIe, MSS | | RUNIT | +-------------------+ | + | | SATA, USB | | DMA | | Windows | +-------------------+ | + | | SD/eMMC | | | | Lookup +------- SB Device Bus | | + | | TDM, I2C | | | | | +-------------------+ | + | +------------------+ +------------+ +------------+ | + | | + +--------------------------------------------------------------------------------------------------+ diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst new file mode 100644 index 0000000..d734003 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst @@ -0,0 +1,58 @@ +AMB - AXI MBUS address decoding +=============================== + +AXI to M-bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs. + +The Runit offers a second level of address windows lookup. It is used to map +transaction towards the CD BootROM, SPI0, SPI1 and Device bus (NOR). + +The Runit contains eight configurable windows. Each window defines a contiguous, +address space and the properties associated with that address space. + +:: + + Unit Bank ATTR + Device-Bus DEV_BOOT_CS 0x2F + DEV_CS0 0x3E + DEV_CS1 0x3D + DEV_CS2 0x3B + DEV_CS3 0x37 + SPI-0 SPI_A_CS0 0x1E + SPI_A_CS1 0x5E + SPI_A_CS2 0x9E + SPI_A_CS3 0xDE + SPI_A_CS4 0x1F + SPI_A_CS5 0x5F + SPI_A_CS6 0x9F + SPI_A_CS7 0xDF + SPI SPI_B_CS0 0x1A + SPI_B_CS1 0x5A + SPI_B_CS2 0x9A + SPI_B_CS3 0xDA + BOOT_ROM BOOT_ROM 0x1D + UART UART 0x01 + +Mandatory functions +------------------- + +- marvell_get_amb_memory_map + Returns the AMB windows configuration and the number of windows + +Mandatory structures +-------------------- + +- amb_memory_map + Array that include the configuration of the windows. Every window/entry is a + struct which has 2 parameters: + + - Base address of the window + - Attribute of the window + +Examples +-------- + +.. code:: c + + struct addr_map_win amb_memory_map[] = { + {0xf900, AMB_DEV_CS0_ID}, + }; diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst new file mode 100644 index 0000000..12118e9 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst @@ -0,0 +1,33 @@ +Marvell CCU address decoding bindings +===================================== + +CCU configuration driver (1st stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The CCU node includes a description of the address decoding configuration. + +Mandatory functions +------------------- + +- marvell_get_ccu_memory_map + Return the CCU windows configuration and the number of windows of the + specific AP. + +Mandatory structures +-------------------- + +- ccu_memory_map + Array that includes the configuration of the windows. Every window/entry is + a struct which has 3 parameters: + + - Base address of the window + - Size of the window + - Target-ID of the window + +Example +------- + +.. code:: c + + struct addr_map_win ccu_memory_map[] = { + {0x00000000f2000000, 0x00000000e000000, IO_0_TID}, /* IO window */ + }; diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst new file mode 100644 index 0000000..7498291 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst @@ -0,0 +1,46 @@ +Marvell IO WIN address decoding bindings +======================================== + +IO Window configuration driver (2nd stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The IO WIN includes a description of the address decoding configuration. + +Transactions that are decoded by CCU windows as IO peripheral, have an additional +layer of decoding. This additional address decoding layer defines one of the +following targets: + +- **0x0** = BootRom +- **0x1** = STM (Serial Trace Macro-cell, a programmer's port into trace stream) +- **0x2** = SPI direct access +- **0x3** = PCIe registers +- **0x4** = MCI Port +- **0x5** = PCIe port + +Mandatory functions +------------------- + +- marvell_get_io_win_memory_map + Returns the IO windows configuration and the number of windows of the + specific AP. + +Mandatory structures +-------------------- + +- io_win_memory_map + Array that include the configuration of the windows. Every window/entry is + a struct which has 3 parameters: + + - Base address of the window + - Size of the window + - Target-ID of the window + +Example +------- + +.. code:: c + + struct addr_map_win io_win_memory_map[] = { + {0x00000000fe000000, 0x000000001f00000, PCIE_PORT_TID}, /* PCIe window 31Mb for PCIe port*/ + {0x00000000ffe00000, 0x000000000100000, PCIE_REGS_TID}, /* PCI-REG window 64Kb for PCIe-reg*/ + {0x00000000f6000000, 0x000000000100000, MCIPHY_TID}, /* MCI window 1Mb for PHY-reg*/ + }; diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst new file mode 100644 index 0000000..aa41822 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst @@ -0,0 +1,52 @@ +Marvell IOB address decoding bindings +===================================== + +IO bridge configuration driver (3rd stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The IOB includes a description of the address decoding configuration. + +IOB supports up to n (in CP110 n=24) windows for external memory transaction. +When a transaction passes through the IOB, its address is compared to each of +the enabled windows. If there is a hit and it passes the security checks, it is +advanced to the target port. + +Mandatory functions +------------------- + +- marvell_get_iob_memory_map + Returns the IOB windows configuration and the number of windows + +Mandatory structures +-------------------- + +- iob_memory_map + Array that includes the configuration of the windows. Every window/entry is + a struct which has 3 parameters: + + - Base address of the window + - Size of the window + - Target-ID of the window + +Target ID options +----------------- + +- **0x0** = Internal configuration space +- **0x1** = MCI0 +- **0x2** = PEX1_X1 +- **0x3** = PEX2_X1 +- **0x4** = PEX0_X4 +- **0x5** = NAND flash +- **0x6** = RUNIT (NOR/SPI/BootRoom) +- **0x7** = MCI1 + +Example +------- + +.. code:: c + + struct addr_map_win iob_memory_map[] = { + {0x00000000f7000000, 0x0000000001000000, PEX1_TID}, /* PEX1_X1 window */ + {0x00000000f8000000, 0x0000000001000000, PEX2_TID}, /* PEX2_X1 window */ + {0x00000000f6000000, 0x0000000001000000, PEX0_TID}, /* PEX0_X4 window */ + {0x00000000f9000000, 0x0000000001000000, NAND_TID} /* NAND window */ + }; diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/porting.rst b/arm-trusted-firmware/docs/plat/marvell/armada/porting.rst new file mode 100644 index 0000000..ba8736d --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/porting.rst @@ -0,0 +1,158 @@ +TF-A Porting Guide for Marvell Platforms +======================================== + +This section describes how to port TF-A to a customer board, assuming that the +SoC being used is already supported in TF-A. + + +Source Code Structure +--------------------- + +- The customer platform specific code shall reside under ``plat/marvell/armada//_cust`` + (e.g. 'plat/marvell/armada/a8k/a7040_cust'). +- The platform name for build purposes is called ``_cust`` (e.g. ``a7040_cust``). +- The build system will reuse all files from within the soc directory, and take only the porting + files from the customer platform directory. + +Files that require porting are located at ``plat/marvell/armada//_cust`` directory. + + +Armada-70x0/Armada-80x0 Porting +------------------------------- + +SoC Physical Address Map (marvell_plat_config.c) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This file describes the SoC physical memory mapping to be used for the CCU, +IOWIN, AXI-MBUS and IOB address decode units (Refer to the functional spec for +more details). + +In most cases, using the default address decode windows should work OK. + +In cases where a special physical address map is needed (e.g. Special size for +PCIe MEM windows, large memory mapped SPI flash...), then porting of the SoC +memory map is required. + +.. note:: + For a detailed information on how CCU, IOWIN, AXI-MBUS & IOB work, please + refer to the SoC functional spec, and under + ``docs/plat/marvell/armada/misc/mvebu-[ccu/iob/amb/io-win].rst`` files. + +boot loader recovery (marvell_plat_config.c) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Background: + + Boot rom can skip the current image and choose to boot from next position if a + specific value (``0xDEADB002``) is returned by the ble main function. This + feature is used for boot loader recovery by booting from a valid flash-image + saved in next position on flash (e.g. address 2M in SPI flash). + + Supported options to implement the skip request are: + - GPIO + - I2C + - User defined + +- Porting: + + Under marvell_plat_config.c, implement struct skip_image that includes + specific board parameters. + + .. warning:: + To disable this feature make sure the struct skip_image is not implemented. + +- Example: + +In A7040-DB specific implementation +(``plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c``), the image skip is +implemented using GPIO: mpp 33 (SW5). + +Before resetting the board make sure there is a valid image on the next flash +address: + + -tftp [valid address] flash-image.bin + -sf update [valid address] 0x2000000 [size] + +Press reset and keep pressing the button connected to the chosen GPIO pin. A +skip image request message is printed on the screen and boot rom boots from the +saved image at the next position. + +DDR Porting (dram_port.c) +~~~~~~~~~~~~~~~~~~~~~~~~~ + +This file defines the dram topology and parameters of the target board. + +The DDR code is part of the BLE component, which is an extension of ARM Trusted +Firmware (TF-A). + +The DDR driver called mv_ddr is released separately apart from TF-A sources. + +The BLE and consequently, the DDR init code is executed at the early stage of +the boot process. + +Each supported platform of the TF-A has its own DDR porting file called +dram_port.c located at ``atf/plat/marvell/armada/a8k//board`` directory. + +Please refer to '/doc/porting_guide.txt' for detailed +porting description. + +The build target directory is "build//release/ble". + +Comphy Porting (phy-porting-layer.h or phy-default-porting-layer.h) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Background: + Some of the comphy's parameters value depend on the HW connection between + the SoC and the PHY. Every board type has specific HW characteristics like + wire length. Due to those differences some comphy parameters vary between + board types. Therefore each board type can have its own list of values for + all relevant comphy parameters. The PHY porting layer specifies which + parameters need to be suited and the board designer should provide relevant + values. + + The PHY porting layer simplifies updating static values per board type, + which are now grouped in one place. + + .. note:: + The parameters for the same type of comphy may vary even for the same + board type, it is because the lanes from comphy-x to some PHY may have + different HW characteristic than lanes from comphy-y to the same + (multiplexed) or other PHY. + +- Porting: + The porting layer for PHY was introduced in TF-A. There is one file + ``drivers/marvell/comphy/phy-default-porting-layer.h`` which contains the + defaults. Those default parameters are used only if there is no appropriate + phy-porting-layer.h file under: ``plat/marvell/armada///board/phy-porting-layer.h``. If the phy-porting-layer.h + exists, the phy-default-porting-layer.h is not going to be included. + + .. warning:: + Not all comphy types are already reworked to support the PHY porting + layer, currently the porting layer is supported for XFI/SFI and SATA + comphy types. + + The easiest way to prepare the PHY porting layer for custom board is to copy + existing example to a new platform: + + - cp ``plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h`` "plat/marvell/armada///board/phy-porting-layer.h" + - adjust relevant parameters or + - if different comphy index is used for specific feature, move it to proper table entry and then adjust. + + .. note:: + The final table size with comphy parameters can be different, depending + on the CP module count for given SoC type. + +- Example: + Example porting layer for armada-8040-db is under: + ``plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h`` + + .. note:: + If there is no PHY porting layer for new platform (missing + phy-porting-layer.h), the default values are used + (drivers/marvell/comphy/phy-default-porting-layer.h) and the user is + warned: + + .. warning:: + "Using default comphy parameters - it may be required to suit them for + your board". diff --git a/arm-trusted-firmware/docs/plat/marvell/index.rst b/arm-trusted-firmware/docs/plat/marvell/index.rst new file mode 100644 index 0000000..0d33432 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/index.rst @@ -0,0 +1,14 @@ +Marvell +======= + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + armada/build + armada/porting + armada/misc/mvebu-a8k-addr-map + armada/misc/mvebu-amb + armada/misc/mvebu-ccu + armada/misc/mvebu-io-win + armada/misc/mvebu-iob diff --git a/arm-trusted-firmware/docs/plat/meson-axg.rst b/arm-trusted-firmware/docs/plat/meson-axg.rst new file mode 100644 index 0000000..6f6732e --- /dev/null +++ b/arm-trusted-firmware/docs/plat/meson-axg.rst @@ -0,0 +1,27 @@ +Amlogic Meson A113D (AXG) +=========================== + +The Amlogic Meson A113D is a SoC with a quad core Arm Cortex-A53 running at +~1.2GHz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +.. code:: shell + + CROSS_COMPILE=aarch64-none-elf- make DEBUG=1 PLAT=axg [SPD=opteed] + [AML_USE_ATOS=1 when using ATOS as BL32] + +This port has been tested on a A113D board. After building it, follow the +instructions in the `U-Boot repository`_, replacing the mentioned **bl31.img** +by the one built from this port. + +.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/s400.rst diff --git a/arm-trusted-firmware/docs/plat/meson-g12a.rst b/arm-trusted-firmware/docs/plat/meson-g12a.rst new file mode 100644 index 0000000..9588ec4 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/meson-g12a.rst @@ -0,0 +1,27 @@ +Amlogic Meson S905X2 (G12A) +=========================== + +The Amlogic Meson S905X2 is a SoC with a quad core Arm Cortex-A53 running at +~1.8GHz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=g12a + +This port has been tested on a SEI510 board. After building it, follow the +instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the +mentioned **bl31.img** by the one built from this port. + +.. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README.g12a +.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/sei510.rst diff --git a/arm-trusted-firmware/docs/plat/meson-gxbb.rst b/arm-trusted-firmware/docs/plat/meson-gxbb.rst new file mode 100644 index 0000000..dbd83e0 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/meson-gxbb.rst @@ -0,0 +1,26 @@ +Amlogic Meson S905 (GXBB) +========================= + +The Amlogic Meson S905 is a SoC with a quad core Arm Cortex-A53 running at +1.5Ghz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxbb bl31 + +This port has been tested in a ODROID-C2. After building it, follow the +instructions in the `U-Boot repository`_, replacing the mentioned **bl31.bin** +by the one built from this port. + +.. _U-Boot repository: https://gitlab.denx.de/u-boot/u-boot/-/blob/master/board/amlogic/p200/README.odroid-c2 diff --git a/arm-trusted-firmware/docs/plat/meson-gxl.rst b/arm-trusted-firmware/docs/plat/meson-gxl.rst new file mode 100644 index 0000000..0751f1d --- /dev/null +++ b/arm-trusted-firmware/docs/plat/meson-gxl.rst @@ -0,0 +1,27 @@ +Amlogic Meson S905x (GXL) +========================= + +The Amlogic Meson S905x is a SoC with a quad core Arm Cortex-A53 running at +1.5Ghz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxl + +This port has been tested on a Lepotato. After building it, follow the +instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the +mentioned **bl31.img** by the one built from this port. + +.. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README +.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/p212.rst diff --git a/arm-trusted-firmware/docs/plat/mt8183.rst b/arm-trusted-firmware/docs/plat/mt8183.rst new file mode 100644 index 0000000..c639be1 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/mt8183.rst @@ -0,0 +1,20 @@ +MediaTek 8183 +============= + +MediaTek 8183 (MT8183) is a 64-bit ARM SoC introduced by MediaTek in early 2018. +The chip incorporates eight cores - four Cortex-A53 little cores and Cortex-A73. +Both clusters can operate at up to 2 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8183 DEBUG=1 diff --git a/arm-trusted-firmware/docs/plat/mt8186.rst b/arm-trusted-firmware/docs/plat/mt8186.rst new file mode 100644 index 0000000..16b833a --- /dev/null +++ b/arm-trusted-firmware/docs/plat/mt8186.rst @@ -0,0 +1,21 @@ +MediaTek 8186 +============= + +MediaTek 8186 (MT8186) is a 64-bit ARM SoC introduced by MediaTek in 2021. +The chip incorporates eight cores - six Cortex-A55 little cores and two Cortex-A76. +Cortex-A76 can operate at up to 2.05 GHz. +Cortex-A55 can operate at up to 2.0 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8186 DEBUG=1 COREBOOT=1 diff --git a/arm-trusted-firmware/docs/plat/mt8192.rst b/arm-trusted-firmware/docs/plat/mt8192.rst new file mode 100644 index 0000000..369afcf --- /dev/null +++ b/arm-trusted-firmware/docs/plat/mt8192.rst @@ -0,0 +1,21 @@ +MediaTek 8192 +============= + +MediaTek 8192 (MT8192) is a 64-bit ARM SoC introduced by MediaTek in 2020. +The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A76. +Cortex-A76 can operate at up to 2.2 GHz. +Cortex-A55 can operate at up to 2 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8192 DEBUG=1 COREBOOT=1 diff --git a/arm-trusted-firmware/docs/plat/mt8195.rst b/arm-trusted-firmware/docs/plat/mt8195.rst new file mode 100644 index 0000000..b2aeea2 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/mt8195.rst @@ -0,0 +1,21 @@ +MediaTek 8195 +============= + +MediaTek 8195 (MT8195) is a 64-bit ARM SoC introduced by MediaTek in 2021. +The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A76. +Cortex-A76 can operate at up to 2.2 GHz. +Cortex-A55 can operate at up to 2.0 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8195 DEBUG=1 COREBOOT=1 diff --git a/arm-trusted-firmware/docs/plat/nvidia-tegra.rst b/arm-trusted-firmware/docs/plat/nvidia-tegra.rst new file mode 100644 index 0000000..99e3bbc --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nvidia-tegra.rst @@ -0,0 +1,148 @@ +NVIDIA Tegra +============ + +- .. rubric:: T194 + :name: t194 + +T194 has eight NVIDIA Carmel CPU cores in a coherent multi-processor +configuration. The Carmel cores support the ARM Architecture version 8.2, +executing both 64-bit AArch64 code, and 32-bit AArch32 code. The Carmel +processors are organized as four dual-core clusters, where each cluster has +a dedicated 2 MiB Level-2 unified cache. A high speed coherency fabric connects +these processor complexes and allows heterogeneous multi-processing with all +eight cores if required. + +- .. rubric:: T186 + :name: t186 + +The NVIDIA® Parker (T186) series system-on-chip (SoC) delivers a heterogeneous +multi-processing (HMP) solution designed to optimize performance and +efficiency. + +T186 has Dual NVIDIA Denver2 ARM® CPU cores, plus Quad ARM Cortex®-A57 cores, +in a coherent multiprocessor configuration. The Denver 2 and Cortex-A57 cores +support ARMv8, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code +including legacy ARMv7 applications. The Denver 2 processors each have 128 KB +Instruction and 64 KB Data Level 1 caches; and have a 2MB shared Level 2 +unified cache. The Cortex-A57 processors each have 48 KB Instruction and 32 KB +Data Level 1 caches; and also have a 2 MB shared Level 2 unified cache. A +high speed coherency fabric connects these two processor complexes and allows +heterogeneous multi-processing with all six cores if required. + +Denver is NVIDIA's own custom-designed, 64-bit, dual-core CPU which is +fully Armv8-A architecture compatible. Each of the two Denver cores +implements a 7-way superscalar microarchitecture (up to 7 concurrent +micro-ops can be executed per clock), and includes a 128KB 4-way L1 +instruction cache, a 64KB 4-way L1 data cache, and a 2MB 16-way L2 +cache, which services both cores. + +Denver implements an innovative process called Dynamic Code Optimization, +which optimizes frequently used software routines at runtime into dense, +highly tuned microcode-equivalent routines. These are stored in a +dedicated, 128MB main-memory-based optimization cache. After being read +into the instruction cache, the optimized micro-ops are executed, +re-fetched and executed from the instruction cache as long as needed and +capacity allows. + +Effectively, this reduces the need to re-optimize the software routines. +Instead of using hardware to extract the instruction-level parallelism +(ILP) inherent in the code, Denver extracts the ILP once via software +techniques, and then executes those routines repeatedly, thus amortizing +the cost of ILP extraction over the many execution instances. + +Denver also features new low latency power-state transitions, in addition +to extensive power-gating and dynamic voltage and clock scaling based on +workloads. + +- .. rubric:: T210 + :name: t210 + +T210 has Quad Arm® Cortex®-A57 cores in a switched configuration with a +companion set of quad Arm Cortex-A53 cores. The Cortex-A57 and A53 cores +support Armv8-A, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code +including legacy Armv7-A applications. The Cortex-A57 processors each have +48 KB Instruction and 32 KB Data Level 1 caches; and have a 2 MB shared +Level 2 unified cache. The Cortex-A53 processors each have 32 KB Instruction +and 32 KB Data Level 1 caches; and have a 512 KB shared Level 2 unified cache. + +Directory structure +------------------- + +- plat/nvidia/tegra/common - Common code for all Tegra SoCs +- plat/nvidia/tegra/soc/txxx - Chip specific code + +Trusted OS dispatcher +--------------------- + +Tegra supports multiple Trusted OS'. + +- Trusted Little Kernel (TLK): In order to include the 'tlkd' dispatcher in + the image, pass 'SPD=tlkd' on the command line while preparing a bl31 image. +- Trusty: In order to include the 'trusty' dispatcher in the image, pass + 'SPD=trusty' on the command line while preparing a bl31 image. + +This allows other Trusted OS vendors to use the upstream code and include +their dispatchers in the image without changing any makefiles. + +These are the supported Trusted OS' by Tegra platforms. + +- Tegra210: TLK and Trusty +- Tegra186: Trusty +- Tegra194: Trusty + +Scatter files +------------- + +Tegra platforms currently support scatter files and ld.S scripts. The scatter +files help support ARMLINK linker to generate BL31 binaries. For now, there +exists a common scatter file, plat/nvidia/tegra/scat/bl31.scat, for all Tegra +SoCs. The `LINKER` build variable needs to point to the ARMLINK binary for +the scatter file to be used. Tegra platforms have verified BL31 image generation +with ARMCLANG (compilation) and ARMLINK (linking) for the Tegra186 platforms. + +Preparing the BL31 image to run on Tegra SoCs +--------------------------------------------- + +.. code:: shell + + CROSS_COMPILE=/bin/aarch64-none-elf- make PLAT=tegra \ + TARGET_SOC= SPD= + bl31 + +Platforms wanting to use different BL31\_BASE, can add ``PLAT_BL31_BASE=`` +to the build command line. + +The Tegra platform code expects a pointer to the following platform specific +structure via 'x1' register from the BL2 layer which is used by the +bl31\_early\_platform\_setup() handler to extract the TZDRAM carveout base and +size for loading the Trusted OS and the UART port ID to be used. The Tegra +memory controller driver programs this base/size in order to restrict NS +accesses. + +typedef struct plat\_params\_from\_bl2 { +/\* TZ memory size */ +uint64\_t tzdram\_size; +/* TZ memory base */ +uint64\_t tzdram\_base; +/* UART port ID \*/ +int uart\_id; +/* L2 ECC parity protection disable flag \*/ +int l2\_ecc\_parity\_prot\_dis; +/* SHMEM base address for storing the boot logs \*/ +uint64\_t boot\_profiler\_shmem\_base; +} plat\_params\_from\_bl2\_t; + +Power Management +---------------- + +The PSCI implementation expects each platform to expose the 'power state' +parameter to be used during the 'SYSTEM SUSPEND' call. The state-id field +is implementation defined on Tegra SoCs and is preferably defined by +tegra\_def.h. + +Tegra configs +------------- + +- 'tegra\_enable\_l2\_ecc\_parity\_prot': This flag enables the L2 ECC and Parity + Protection bit, for Arm Cortex-A57 CPUs, during CPU boot. This flag will + be enabled by Tegrs SoCs during 'Cluster power up' or 'System Suspend' exit. diff --git a/arm-trusted-firmware/docs/plat/nxp/index.rst b/arm-trusted-firmware/docs/plat/nxp/index.rst new file mode 100644 index 0000000..8546887 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nxp/index.rst @@ -0,0 +1,17 @@ +NXP Reference Development Platforms +=================================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + nxp-layerscape + nxp-ls-fuse-prov + nxp-ls-tbbr + +This chapter holds documentation related to NXP reference development platforms. +It includes details on image flashing, fuse provisioning and trusted board boot-up. + +-------------- + +*Copyright (c) 2021, NXP Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst b/arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst new file mode 100644 index 0000000..cd5874b --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst @@ -0,0 +1,473 @@ +NXP SoCs - Overview +===================== +.. section-numbering:: + :suffix: . + +The QorIQ family of ARM based SoCs that are supported on TF-A are: + +1. LX2160A + +- SoC Overview: + +The LX2160A multicore processor, the highest-performance member of the +Layerscape family, combines FinFET process technology's low power and +sixteen Arm® Cortex®-A72 cores with datapath acceleration optimized for +L2/3 packet processing, together with security offload, robust traffic +management and quality of service. + +Details about LX2160A can be found at `lx2160a`_. + +- LX2160ARDB Board: + +The LX2160A reference design board provides a comprehensive platform +that enables design and evaluation of the LX2160A or LX2162A processors. It +comes preloaded with a board support package (BSP) based on a standard Linux +kernel. + +Board details can be fetched from the link: `lx2160ardb`_. + +2. LS1028A + +- SoC Overview: + +The Layerscape LS1028A applications processor for industrial and +automotive includes a time-sensitive networking (TSN) -enabled Ethernet +switch and Ethernet controllers to support converged IT and OT networks. +Two powerful 64-bit Arm®v8 cores support real-time processing for +industrial control and virtual machines for edge computing in the IoT. +The integrated GPU and LCD controller enable Human-Machine Interface +(HMI) systems with next-generation interfaces. + +Details about LS1028A can be found at `ls1028a`_. + +- LS1028ARDB Board: + +The LS1028A reference design board (RDB) is a computing, evaluation, +and development platform that supports industrial IoT applications, human +machine interface solutions, and industrial networking. + +Details about LS1028A RDB board can be found at `ls1028ardb`_. + +3. LS1043A + +- SoC Overview: + +The Layerscape LS1043A processor is NXP's first quad-core, 64-bit Arm®-based +processor for embedded networking. The LS1023A (two core version) and the +LS1043A (four core version) deliver greater than 10 Gbps of performance +in a flexible I/O package supporting fanless designs. This SoC is a +purpose-built solution for small-form-factor networking and industrial +applications with BOM optimizations for economic low layer PCB, lower cost +power supply and single clock design. The new 0.9V versions of the LS1043A +and LS1023A deliver addition power savings for applications such as Wireless +LAN and to Power over Ethernet systems. + +Details about LS1043A can be found at `ls1043a`_. + +- LS1043ARDB Board: + +The LS1043A reference design board (RDB) is a computing, evaluation, and +development platform that supports the Layerscape LS1043A architecture +processor. The LS1043A-RDB can help shorten your time to market by providing +the following features: + +Memory subsystem: + * 2GByte DDR4 SDRAM (32bit bus) + * 128 Mbyte NOR flash single-chip memory + * 512 Mbyte NAND flash + * 16 Mbyte high-speed SPI flash + * SD connector to interface with the SD memory card + +Ethernet: + * XFI 10G port + * QSGMII with 4x 1G ports + * Two RGMII ports + +PCIe: + * PCIe2 (Lanes C) to mini-PCIe slot + * PCIe3 (Lanes D) to PCIe slot + +USB 3.0: two super speed USB 3.0 type A ports + +UART: supports two UARTs up to 115200 bps for console + +Details about LS1043A RDB board can be found at `ls1043ardb`_. + +4. LS1046A + +- SoC Overview: + +The LS1046A is a cost-effective, power-efficient, and highly integrated +system-on-chip (SoC) design that extends the reach of the NXP value-performance +line of QorIQ communications processors. Featuring power-efficient 64-bit +Arm Cortex-A72 cores with ECC-protected L1 and L2 cache memories for high +reliability, running up to 1.8 GHz. + +Details about LS1046A can be found at `ls1046a`_. + +- LS1046ARDB Board: + +The LS1046A reference design board (RDB) is a high-performance computing, +evaluation, and development platform that supports the Layerscape LS1046A +architecture processor. The LS1046ARDB board supports the Layerscape LS1046A +processor and is optimized to support the DDR4 memory and a full complement +of high-speed SerDes ports. + +Details about LS1046A RDB board can be found at `ls1046ardb`_. + +- LS1046AFRWY Board: + +The LS1046A Freeway board (FRWY) is a high-performance computing, evaluation, +and development platform that supports the LS1046A architecture processor +capable of support more than 32,000 CoreMark performance. The FRWY-LS1046A +board supports the LS1046A processor, onboard DDR4 memory, multiple Gigabit +Ethernet, USB3.0 and M2_Type_E interfaces for Wi-Fi, FRWY-LS1046A-AC includes +the Wi-Fi card. + +Details about LS1046A FRWY board can be found at `ls1046afrwy`_. + +5. LS1088A + +- SoC Overview: + +The LS1088A family of multicore communications processors combines up to and eight +Arm Cortex-A53 cores with the advanced, high-performance data path and network +peripheral interfaces required for wireless access points, networking infrastructure, +intelligent edge access, including virtual customer premise equipment (vCPE) and +high-performance industrial applications. + +Details about LS1088A can be found at `ls1088a`_. + +- LS1088ARDB Board: + +The LS1088A reference design board provides a comprehensive platform that +enables design and evaluation of the product (LS1088A processor). This RDB +comes pre-loaded with a board support package (BSP) based on a standard +Linux kernel. + +Details about LS1088A RDB board can be found at `ls1088ardb`_. + +Table of supported boot-modes by each platform & platform that needs FIP-DDR: +----------------------------------------------------------------------------- + ++---------------------+---------------------------------------------------------------------+-----------------+ +| | BOOT_MODE | | +| PLAT +-------+--------+-------+-------+-------+-------------+--------------+ fip_ddr_needed | +| | sd | qspi | nor | nand | emmc | flexspi_nor | flexspi_nand | | ++=====================+=======+========+=======+=======+=======+=============+==============+=================+ +| lx2160ardb | yes | | | | yes | yes | | yes | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1028ardb | yes | | | | yes | yes | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1043ardb | yes | | yes | yes | | | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1046ardb | yes | yes | | | yes | | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1046afrwy | yes | yes | | | | | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1088ardb | yes | yes | | | | | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ + + +Boot Sequence +------------- +:: + ++ Secure World | Normal World ++ EL0 | ++ | ++ EL1 BL32(Tee OS) | kernel ++ ^ | | ^ ++ | | | | ++ EL2 | | | BL33(u-boot) ++ | | | ^ ++ | v | / ++ EL3 BootROM --> BL2 --> BL31 ---------------/ ++ + +Boot Sequence with FIP-DDR +-------------------------- +:: + ++ Secure World | Normal World ++ EL0 | ++ | ++ EL1 fip-ddr BL32(Tee OS) | kernel ++ ^ | ^ | | ^ ++ | | | | | | ++ EL2 | | | | | BL33(u-boot) ++ | | | | | ^ ++ | v | v | / ++ EL3 BootROM --> BL2 -----> BL31 ---------------/ ++ + +DDR Memory Layout +-------------------------- + +NXP Platforms divide DRAM into banks: + +- DRAM0 Bank: Maximum size of this bank is fixed to 2GB, DRAM0 size is defined in platform_def.h if it is less than 2GB. + +- DRAM1 ~ DRAMn Bank: Greater than 2GB belongs to DRAM1 and following banks, and size of DRAMn Bank varies for one platform to others. + +The following diagram is default DRAM0 memory layout in which secure memory is at top of DRAM0. + +:: + + high +---------------------------------------------+ + | | + | Secure EL1 Payload Shared Memory (2 MB) | + | | + +---------------------------------------------+ + | | + | Secure Memory (64 MB) | + | | + +---------------------------------------------+ + | | + | Non Secure Memory | + | | + low +---------------------------------------------+ + +How to build +============= + +Code Locations +-------------- + +- OP-TEE: + `link `__ + +- U-Boot: + `link `__ + +- RCW: + `link `__ + +- ddr-phy-binary: Required by platforms that need fip-ddr. + `link `__ + +- cst: Required for TBBR. + `link `__ + +Build Procedure +--------------- + +- Fetch all the above repositories into local host. + +- Prepare AARCH64 toolchain and set the environment variable "CROSS_COMPILE". + + .. code:: shell + + export CROSS_COMPILE=.../bin/aarch64-linux-gnu- + +- Build RCW. Refer README from the respective cloned folder for more details. + +- Build u-boot and OPTee firstly, and get binary images: u-boot.bin and tee.bin. + For u-boot you can use the _tfa_defconfig for build. + +- Copy/clone the repo "ddr-phy-binary" to the tfa directory for platform needing ddr-fip. + +- Below are the steps to build TF-A images for the supported platforms. + +Compilation steps without BL32 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +BUILD BL2: + +-To compile + .. code:: shell + + make PLAT=$PLAT \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + pbl + +BUILD FIP: + + .. code:: shell + + make PLAT=$PLAT \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip + +Compilation steps with BL32 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +BUILD BL2: + +-To compile + .. code:: shell + + make PLAT=$PLAT \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + pbl + +BUILD FIP: + + .. code:: shell + + make PLAT=$PLAT \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip + + +BUILD fip-ddr (Mandatory for certain platforms, refer table above): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +-To compile additional fip-ddr for selected platforms(Refer above table if the platform needs fip-ddr). + .. code:: shell + + make PLAT= fip-ddr + + +Deploy ATF Images +================= + +Note: The size in the standard uboot commands for copy to nor, qspi, nand or sd +should be modified based on the binary size of the image to be copied. + +- Deploy ATF images on flexspi-Nor or QSPI flash Alt Bank from U-Boot prompt. + + -- Commands to flash images for bl2_xxx.pbl and fip.bin + + Notes: ls1028ardb has no flexspi-Nor Alt Bank, so use "sf probe 0:0" for current bank. + + .. code:: shell + + tftp 82000000 $path/bl2_xxx.pbl; + + i2c mw 66 50 20;sf probe 0:1; sf erase 0 +$filesize; sf write 0x82000000 0x0 $filesize; + + tftp 82000000 $path/fip.bin; + i2c mw 66 50 20;sf probe 0:1; sf erase 0x100000 +$filesize; sf write 0x82000000 0x100000 $filesize; + + -- Next step is valid for platform where FIP-DDR is needed. + + .. code:: shell + + tftp 82000000 $path/ddr_fip.bin; + i2c mw 66 50 20;sf probe 0:1; sf erase 0x800000 +$filesize; sf write 0x82000000 0x800000 $filesize; + + -- Then reset to alternate bank to boot up ATF. + + Command for lx2160a, ls1088a and ls1028a platforms: + + .. code:: shell + + qixisreset altbank; + + Command for ls1046a platforms: + + .. code:: shell + + cpld reset altbank; + +- Deploy ATF images on SD/eMMC from U-Boot prompt. + -- file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512) + + .. code:: shell + + mmc dev ; (idx = 1 for eMMC; idx = 0 for SD) + + tftp 82000000 $path/bl2__or_.pbl; + mmc write 82000000 8 ; + + tftp 82000000 $path/fip.bin; + mmc write 82000000 0x800 ; + + -- Next step is valid for platform that needs FIP-DDR. + + .. code:: shell + + tftp 82000000 $path/ddr_fip.bin; + mmc write 82000000 0x4000 ; + + -- Then reset to sd/emmc to boot up ATF from sd/emmc as boot-source. + + Command for lx2160A, ls1088a and ls1028a platforms: + + .. code:: shell + + qixisreset ; + + Command for ls1043a and ls1046a platform: + + .. code:: shell + + cpld reset ; + +- Deploy ATF images on IFC nor flash from U-Boot prompt. + + .. code:: shell + + tftp 82000000 $path/bl2_nor.pbl; + protect off 64000000 +$filesize; erase 64000000 +$filesize; cp.b 82000000 64000000 $filesize; + + tftp 82000000 $path/fip.bin; + protect off 64100000 +$filesize; erase 64100000 +$filesize; cp.b 82000000 64100000 $filesize; + + -- Then reset to alternate bank to boot up ATF. + + Command for ls1043a platform: + + .. code:: shell + + cpld reset altbank; + +- Deploy ATF images on IFC nand flash from U-Boot prompt. + + .. code:: shell + + tftp 82000000 $path/bl2_nand.pbl; + nand erase 0x0 $filesize; nand write 82000000 0x0 $filesize; + + tftp 82000000 $path/fip.bin; + nand erase 0x100000 $filesize;nand write 82000000 0x100000 $filesize; + + -- Then reset to nand flash to boot up ATF. + + Command for ls1043a platform: + + .. code:: shell + + cpld reset nand; + + + +Trusted Board Boot: +=================== + +For TBBR, the binary name changes: + ++-------------+--------------------------+---------+-------------------+ +| Boot Type | BL2 | FIP | FIP-DDR | ++=============+==========================+=========+===================+ +| Normal Boot | bl2_.pbl | fip.bin | ddr_fip.bin | ++-------------+--------------------------+---------+-------------------+ +| TBBR Boot | bl2__sec.pbl | fip.bin | ddr_fip_sec.bin | ++-------------+--------------------------+---------+-------------------+ + +Refer `nxp-ls-tbbr.rst`_ for detailed user steps. + + +.. _lx2160a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-lx2160a-lx2120a-lx2080a-processors:LX2160A +.. _lx2160ardb: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-communication-process/layerscape-lx2160a-multicore-communications-processor:LX2160A +.. _ls1028a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1028a-applications-processor:LS1028A +.. _ls1028ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1028a-reference-design-board:LS1028ARDB +.. _ls1043a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1043a-and-1023a-processors:LS1043A +.. _ls1043ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1043a-reference-design-board:LS1043A-RDB +.. _ls1046a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1046a-and-1026a-processors:LS1046A +.. _ls1046ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1046a-reference-design-board:LS1046A-RDB +.. _ls1046afrwy: https://www.nxp.com/design/qoriq-developer-resources/ls1046a-freeway-board:FRWY-LS1046A +.. _ls1088a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1088a-and-1048a-processor:LS1088A +.. _ls1088ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1088a-reference-design-board:LS1088A-RDB +.. _nxp-ls-tbbr.rst: ./nxp-ls-tbbr.rst diff --git a/arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst b/arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst new file mode 100644 index 0000000..64e1c6f --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst @@ -0,0 +1,271 @@ + +Steps to blow fuses on NXP LS SoC: +================================== + + +- Enable POVDD + -- Refer board GSG(Getting Started Guide) for the steps to enable POVDD. + -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk. + ++---+-----------------+-----------+------------+-----------------+-----------------------------+ +| | Platform | Jumper | Switch | LED to Verify | Through GPIO Pin (=number) | ++===+=================+===========+============+=================+=============================+ +| 1.| lx2160ardb | J9 | | | no | ++---+-----------------+-----------+------------+-----------------+-----------------------------+ +| 2.| lx2160aqds | J35 | | | no | ++---+-----------------+-----------+------------+-----------------+-----------------------------+ +| 3.| lx2162aqds | J35 | SW9[4] = 1 | D15 | no | ++---+-----------------+-----------+------------+-----------------+-----------------------------+ + +- SFP registers to be written to: + ++---+----------------------------------+----------------------+----------------------+ +| | Platform | OTPMKR0..OTPMKR7 | SRKHR0..SRKHR7 | ++===+==================================+======================+======================+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x1e80234..0x1e80250 | 0x1e80254..0x1e80270 | ++---+----------------------------------+----------------------+----------------------+ + +- At U-Boot prompt, verify that SNVS register - HPSR, whether OTPMK was written, already: + ++---+----------------------------------+-------------------------------------------+---------------+ +| | Platform | OTPMK_ZERO_BIT(=value) | SNVS_HPSR_REG | ++===+==================================+===========================================+===============+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 27 (= 1 means not blown, =0 means blown) | 0x01E90014 | ++---+----------------------------------+-------------------------------------------+---------------+ + +From u-boot prompt: + + -- Check for the OTPMK. + .. code:: shell + + md $SNVS_HPSR_REG + + Command Output: + 01e90014: 88000900 + + In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap). + +0 +4 +8 +C + [0x01E90014] 88000900 + + Note: OTPMK_ZERO_BIT is 1, indicating that the OTPMK is not blown. + + -- Check for the SRK Hash. + .. code:: shell + + md $SRKHR0 0x10 + + Command Output: + 01e80254: 00000000 00000000 00000000 00000000 ................ + 01e80264: 00000000 00000000 00000000 00000000 ................ + + Note: Zero means that SRK hash is not blown. + +- If not blown, then from the U-Boot prompt, using following commands: + -- Provision the OTPMK. + + .. code:: shell + + mw.l $OTPMKR0 + mw.l $OTPMKR1 + mw.l $OTPMKR2 + mw.l $OTPMKR3 + mw.l $OTPMKR4 + mw.l $OTPMKR5 + mw.l $OTPMKR6 + mw.l $OTPMKR7 + + -- Provision the SRK Hash. + + .. code:: shell + + mw.l $SRKHR0 + mw.l $SRKHR1 + mw.l $SRKHR2 + mw.l $SRKHR3 + mw.l $SRKHR4 + mw.l $SRKHR5 + mw.l $SRKHR6 + mw.l $SRKHR7 + + Note: SRK Hash should be carefully written keeping in mind the SFP Block Endianness. + +- At U-Boot prompt, verify that SNVS registers for OTPMK are correctly written: + + -- Check for the OTPMK. + .. code:: shell + + md $SNVS_HPSR_REG + + Command Output: + 01e90014: 80000900 + + OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown. + + Note: In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap). + + .. code:: shell + + md $OTPMKR0 0x10 + + Command Output: + 01e80234: ffffffff ffffffff ffffffff ffffffff ................ + 01e80244: ffffffff ffffffff ffffffff ffffffff ................ + + Note: OTPMK will never be visible in plain. + + -- Check for the SRK Hash. For example, if following SRK hash is written: + + SFP SRKHR0 = fdc2fed4 + SFP SRKHR1 = 317f569e + SFP SRKHR2 = 1828425c + SFP SRKHR3 = e87b5cfd + SFP SRKHR4 = 34beab8f + SFP SRKHR5 = df792a70 + SFP SRKHR6 = 2dff85e1 + SFP SRKHR7 = 32a29687, + + then following would be the value on dumping SRK hash. + + .. code:: shell + + md $SRKHR0 0x10 + + Command Output: + 01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8 ....1.V..(B\.{\. + 01e80264: 8fabbe34 702a79df e185ff2d 8796a232 4....y*p-...2... + + Note: SRK Hash is visible in plain based on the SFP Block Endianness. + +- Caution: Donot proceed to the next step, until you are sure that OTPMK and SRKH are correctly blown from above steps. + -- After the next step, there is no turning back. + -- Fuses will be burnt, which cannot be undo. + +- Write SFP_INGR[INST] with the PROGFB(0x2) instruction to blow the fuses. + -- User need to save the SRK key pair and OTPMK Key forever, to continue using this board. + ++---+----------------------------------+-------------------------------------------+-----------+ +| | Platform | SFP_INGR_REG | SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE | ++===+==================================+=======================================================+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x01E80020 | 0x2 | ++---+----------------------------------+--------------+----------------------------------------+ + + .. code:: shell + + md $SFP_INGR_REG $SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE + +- On reset, if the SFP register were read from u-boot, it will show the following: + -- Check for the OTPMK. + + .. code:: shell + + md $SNVS_HPSR_REG + + Command Output: + 01e90014: 80000900 + + In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap). + +0 +4 +8 +C + [0x01E90014] 80000900 + + Note: OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown. + + .. code:: shell + + md $OTPMKR0 0x10 + + Command Output: + 01e80234: ffffffff ffffffff ffffffff ffffffff ................ + 01e80244: ffffffff ffffffff ffffffff ffffffff ................ + + Note: OTPMK will never be visible in plain. + + -- SRK Hash + + .. code:: shell + + md $SRKHR0 0x10 + + Command Output: + 01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8 ....1.V..(B\.{\. + 01e80264: 8fabbe34 702a79df e185ff2d 8796a232 4....y*p-...2... + + Note: SRK Hash is visible in plain based on the SFP Block Endianness. + +Second method to do the fuse provsioning: +========================================= + +This method is used for quick way to provision fuses. +Typically used by those who needs to provision number of boards. + +- Enable POVDD: + -- Refer the table above to enable POVDD. + + Note: If GPIO Pin supports enabling POVDD, it can be done through the below input_fuse_file. + + -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk. + +- User need to populate the "input_fuse_file", corresponding to the platform for: + + -- OTPMK + -- SRKH + + Table of fuse provisioning input file for every supported platform: + ++---+----------------------------------+-----------------------------------------------------------------+ +| | Platform | FUSE_PROV_FILE | ++===+==================================+=================================================================+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | ${CST_DIR}/input_files/gen_fusescr/ls2088_1088/input_fuse_file | ++---+----------------------------------+--------------+--------------------------------------------------+ + +- Create the TF-A binary with FUSE_PROG=1. + + .. code:: shell + + make PLAT=$PLAT FUSE_PROG=1\ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip \ + fip_fuse \ + FUSE_PROV_FILE=../../apps/security/cst/input_files/gen_fusescr/ls2088_1088/input_fuse_file + +- Deployment: + -- Refer the nxp-layerscape.rst for deploying TF-A images. + -- Deploying fip_fuse.bin: + + For Flexspi-Nor: + + .. code:: shell + + tftp 82000000 $path/fuse_fip.bin; + i2c mw 66 50 20;sf probe 0:0; sf erase 0x880000 +$filesize; sf write 0x82000000 0x880000 $filesize; + + For SD or eMMC [file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512)]: + + .. code:: shell + + tftp 82000000 $path/fuse_fip.bin; + mmc write 82000000 0x4408 ; + +- Valiation: + ++---+----------------------------------+---------------------------------------------------+ +| | Platform | Error_Register | Error_Register_Address | ++===+==================================+===================================================+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | DCFG scratch 4 register | 0x01EE020C | ++---+----------------------------------+---------------------------------------------------+ + + At the U-Boot prompt, check DCFG scratch 4 register for any error. + + .. code:: shell + + md $Error_Register_Address 1 + + Command Ouput: + 01ee020c: 00000000 + + Note: + - 0x00000000 shows no error, then fuse provisioning is successful. + - For non-zero value, refer the code header file ".../drivers/nxp/sfp/sfp_error_codes.h" diff --git a/arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst b/arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst new file mode 100644 index 0000000..43e15f7 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst @@ -0,0 +1,210 @@ + +-------------- +NXP Platforms: +-------------- +TRUSTED_BOARD_BOOT option can be enabled by specifying TRUSTED_BOARD_BOOT=1 on command line during make. + + + +Bare-Minimum Preparation to run TBBR on NXP Platforms: +======================================================= +- OTPMK(One Time Programable Key) needs to be burnt in fuses. + -- It is the 256 bit key that stores a secret value used by the NXP SEC 4.0 IP in Trusted or Secure mode. + + Note: It is primarily for the purpose of decrypting additional secrets stored in system non-volatile memory. + + -- NXP CST tool gives an option to generate it. + + Use the below command from directory 'cst', with correct options. + + .. code:: shell + + ./gen_otpmk_drbg + +- SRKH (Super Root Key Hash) needs to be burnt in fuses. + -- It is the 256 bit hash of the list of the public keys of the SRK key pair. + -- NXP CST tool gives an option to generate the RSA key pair and its hash. + + Use the below command from directory 'cst', with correct options. + + .. code:: shell + + ./gen_keys + +Refer fuse frovisioning readme 'nxp-ls-fuse-prov.rst' for steps to blow these keys. + + + +Two options are provided for TRUSTED_BOARD_BOOT: +================================================ + +------------------------------------------------------------------------- +Option 1: CoT using X 509 certificates +------------------------------------------------------------------------- + +- This CoT is as provided by ARM. + +- To use this option user needs to specify mbedtld dir path in MBEDTLS_DIR. + +- To generate CSF header, path of CST repository needs to be specified as CST_DIR + +- CSF header is embedded to each of the BL2 image. + +- GENERATE_COT=1 adds the tool 'cert_create' to the build environment to generate: + -- X509 Certificates as (.crt) files. + -- X509 Pem key file as (.pem) files. + +- SAVE_KEYS=1 saves the keys and certificates, if GENERATE_COT=1. + -- For this to work, file name for cert and keys are provided as part of compilation or build command. + + --- default file names will be used, incase not provided as part compilation or build command. + --- default folder 'BUILD_PLAT' will be used to store them. + +- ROTPK for x.509 certificates is generated and embedded in bl2.bin and + verified as part of CoT by Boot ROM during secure boot. + +- Compilation steps: + +All Images + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH CST_DIR=$CST_DIR_PATH \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip + +Additional FIP_DDR Image (For NXP platforms like lx2160a) + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH fip_ddr + + Note: make target 'fip_ddr' should never be combine with other make target 'fip', 'pbl' & 'bl2'. + +------------------------------------------------------------------------- +Option 2: CoT using NXP CSF headers. +------------------------------------------------------------------------- + +- This option is automatically selected when TRUSTED_BOARD_BOOT is set but MBEDTLS_DIR path is not specified. + +- CSF header is embedded to each of the BL31, BL32 and BL33 image. + +- To generate CSF header, path of CST repository needs to be specified as CST_DIR + +- Default input files for CSF header generation is added in this repo. + +- Default input file requires user to generate RSA key pair named + -- srk.pri, and + -- srk.pub, and add them in ATF repo. + -- These keys can be generated using gen_keys tool of CST. + +- To change the input file , user can use the options BL33_INPUT_FILE, BL32_INPUT_FILE, BL31_INPUT_FILE + +- There are 2 paths in secure boot flow : + -- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0) + + --- In this flow , even on ROTPK comparison failure, flow would continue. + --- However SNVS is transitioned to non-secure state + + -- Production mode (SFP->OSPR, ITS = 1) + + --- Any failure is fatal failure + +- Compilation steps: + +All Images + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip + +Additional FIP_DDR Image (For NXP platforms like lx2160a) + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH fip_ddr + +- Compilation Steps with build option for generic image processing filters to prepend CSF header: + -- Generic image processing filters to prepend CSF header + + BL32_INPUT_FILE = < file name> + BL33_INPUT_FILE = + + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + BL33_INPUT_FILE = \ + BL32_INPUT_FILE = \ + BL31_INPUT_FILE = \ + pbl \ + fip + + +Deploy ATF Images +================= +Same steps as mentioned in the readme "nxp-layerscape.rst". + + + +Verification to check if Secure state is achieved: +================================================== + ++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+ +| | Platform | SNVS_HPSR_REG | SYS_SECURE_BIT(=value) | SYSTEM_SECURE_CONFIG_BIT(=value) | SSM_STATE | ++===+================+=================+========================+==================================+===============================+ +| 1.| lx2160ardb or | 0x01E90014 | 15 | 14-12 | 11-8 | +| | lx2160aqds or | | ( = 1, BootROM Booted) | ( = 010 means Intent to Secure, | (=1111 means secure boot) | +| | lx2162aqds | | | ( = 000 Unsecure) | (=1011 means Non-secure Boot) | ++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+ + +- Production mode (SFP->OSPR, ITS = 1) + -- Linux prompt will successfully come. if the TBBR is successful. + + --- Else, Linux boot will be successful. + + -- For secure-boot status, read SNVS Register $SNVS_HPSR_REG from u-boot prompt: + + .. code:: shell + + md $SNVS_HPSR_REG + + Command Output: + 1e90014: 8000AF00 + + In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap). + +0 +4 +8 +C + [0x01E90014] 8000AF00 + + +- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0) + -- Refer the SoC specific table to read the register to interpret whether the secure boot is achieved or not. + -- Using JTAG (in development environment only, using CW tap): + + --- For secure-boot status, read SNVS Register $SNVS_HPSR_REG + + .. code:: shell + + ccs::display_regs 86 0x01E90014 4 0 1 + + Command Output: + Using the SAP chain position number 86, following is the output. + + +0 +4 +8 +C + [0x01E90014] 8000AF00 + + Note: Chain position number will vary from one SoC to other SoC. + +- Interpretation of the value: + + -- 0xA indicates BootROM booted, with intent to secure. + -- 0xF = secure boot, as SSM_STATE. diff --git a/arm-trusted-firmware/docs/plat/poplar.rst b/arm-trusted-firmware/docs/plat/poplar.rst new file mode 100644 index 0000000..215f551 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/poplar.rst @@ -0,0 +1,176 @@ +Poplar +====== + +Poplar is the first development board compliant with the 96Boards Enterprise +Edition TV Platform specification. + +The board features the Hi3798C V200 with an integrated quad-core 64-bit +Arm Cortex A53 processor and high performance Mali T720 GPU, making it capable +of running any commercial set-top solution based on Linux or Android. + +It supports a premium user experience with up to H.265 HEVC decoding of 4K +video at 60 frames per second. + +:: + + SOC Hisilicon Hi3798CV200 + CPU Quad-core Arm Cortex-A53 64 bit + DRAM DDR3/3L/4 SDRAM interface, maximum 32-bit data width 2 GB + USB Two USB 2.0 ports One USB 3.0 ports + CONSOLE USB-micro port for console support + ETHERNET 1 GBe Ethernet + PCIE One PCIe 2.0 interfaces + JTAG 8-Pin JTAG + EXPANSION INTERFACE Linaro 96Boards Low Speed Expansion slot + DIMENSION Standard 160×120 mm 96Boards Enterprice Edition form factor + WIFI 802.11AC 2*2 with Bluetooth + CONNECTORS One connector for Smart Card One connector for TSI + +At the start of the boot sequence, the bootROM executes the so called l-loader +binary whose main role is to change the processor state to 64bit mode. This +must happen prior to invoking Trusted Firmware-A: + +:: + + l-loader --> Trusted Firmware-A --> u-boot + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- l-loader: + `link `__ + +- u-boot: + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 3 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Prepare the AARCH64 toolchain. + +- Build u-boot using poplar_defconfig + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- poplar_defconfig + make CROSS_COMPILE=aarch64-linux-gnu- + +- Build atf providing the previously generated u-boot.bin as the BL33 image + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- all fip SPD=none PLAT=poplar + BL33=u-boot.bin + +- Build l-loader (generated the final fastboot.bin) + 1. copy the atf generated files fip.bin and bl1.bin to l-loader/atf/ + 2. export ARM_TRUSTED_FIRMWARE=${ATF_SOURCE_PATH) + 3. make + +Install Procedure +----------------- + +- Copy l-loader/fastboot.bin to a FAT partition on a USB pen drive. + +- Plug the USB pen drive to any of the USB2 ports + +- Power the board while keeping S3 pressed (usb_boot) + +The system will boot into a u-boot shell which you can then use to write the +working firmware to eMMC. + +Boot trace +---------- + +:: + + Bootrom start + Boot Media: eMMC + Decrypt auxiliary code ...OK + + lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000 + + Entry boot auxiliary code + + Auxiliary code - v1.00 + DDR code - V1.1.2 20160205 + Build: Mar 24 2016 - 17:09:44 + Reg Version: v134 + Reg Time: 2016/03/18 09:44:55 + Reg Name: hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg + + Boot auxiliary code success + Bootrom success + + LOADER: Switched to aarch64 mode + LOADER: Entering ARM TRUSTED FIRMWARE + LOADER: CPU0 executes at 0x000ce000 + + INFO: BL1: 0xe1000 - 0xe7000 [size = 24576] + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL1: Built : 17:51:33, Apr 30 2017 + INFO: BL1: RAM 0xe1000 - 0xe7000 + INFO: BL1: Loading BL2 + INFO: Loading image id=1 at address 0xe9000 + INFO: Image id=1 loaded at address 0xe9000, size = 0x5008 + NOTICE: BL1: Booting BL2 + INFO: Entry point address = 0xe9000 + INFO: SPSR = 0x3c5 + NOTICE: BL2: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL2: Built : 17:51:33, Apr 30 2017 + INFO: BL2: Loading BL31 + INFO: Loading image id=3 at address 0x129000 + INFO: Image id=3 loaded at address 0x129000, size = 0x8038 + INFO: BL2: Loading BL33 + INFO: Loading image id=5 at address 0x37000000 + INFO: Image id=5 loaded at address 0x37000000, size = 0x58f17 + NOTICE: BL1: Booting BL31 + INFO: Entry point address = 0x129000 + INFO: SPSR = 0x3cd + INFO: Boot bl33 from 0x37000000 for 364311 Bytes + NOTICE: BL31: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL31: Built : 17:51:33, Apr 30 2017 + INFO: BL31: Initializing runtime services + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x37000000 + INFO: SPSR = 0x3c9 + + + U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar + + Model: HiSilicon Poplar Development Board + BOARD: Hisilicon HI3798cv200 Poplar + DRAM: 1 GiB + MMC: Hisilicon DWMMC: 0 + In: serial@f8b00000 + Out: serial@f8b00000 + Err: serial@f8b00000 + Net: Net Initialization Skipped + No ethernet found. + + Hit any key to stop autoboot: 0 + starting USB... + USB0: USB EHCI 1.00 + scanning bus 0 for devices... 1 USB Device(s) found + USB1: USB EHCI 1.00 + scanning bus 1 for devices... 4 USB Device(s) found + scanning usb for storage devices... 1 Storage Device(s) found + scanning usb for ethernet devices... 1 Ethernet Device(s) found + + USB device 0: + Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade + Type: Removable Hard Disk + Capacity: 7632.0 MB = 7.4 GB (15630336 x 512) + ... is now current device + Scanning usb 0:1... + => diff --git a/arm-trusted-firmware/docs/plat/qemu-sbsa.rst b/arm-trusted-firmware/docs/plat/qemu-sbsa.rst new file mode 100644 index 0000000..bc82ae5 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/qemu-sbsa.rst @@ -0,0 +1,56 @@ +QEMU SBSA Target +================ + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QEMU SBSA +Armv8-A. While running Qemu from command line, we need to supply two Flash +images. First Secure BootRom is supplied by -pflash argument. This Flash image +is made by EDK2 build system by composing BL1 and FIP. Second parameter for Qemu +is responsible for Non-secure rom which also given with -pflash argument and +contains of UEFI and EFI variables (also made by EDK2 build system). Semihosting +is not used + +When QEMU starts all CPUs are released simultaneously, BL1 selects a +primary CPU to handle the boot and the secondaries are placed in a polling +loop to be released by normal world via PSCI. + +BL2 edits the FDT, generated by QEMU at run-time to add a node describing PSCI +and also enable methods for the CPUs. + +Current limitations: + +- Only cold boot is supported + +To build TF-A: + +:: + + git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git tfa + cd tfa + export CROSS_COMPILE=aarch64-none-elf- + make PLAT=qemu_sbsa all fip + +To build TF-A with BL32 and SPM enabled(StandaloneMM as a Secure Payload): + +:: + + git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git tfa + cd tfa + export CROSS_COMPILE=aarch64-none-elf- + make PLAT=qemu_sbsa BL32=../STANDALONE_MM.fd SPM_MM=1 EL3_EXCEPTION_HANDLING=1 all fip + +Images will be placed at build/qemu_sbsa/release (bl1.bin and fip.bin). +Need to copy them into top directory for EDK2 compilation. + +:: + + cp build/qemu_sbsa/release/bl1.bin ../ + cp build/qemu_sbsa/release/fip.bin ../ + +Those images cannot be used by itself (no semihosing support). Flash images are built by +EDK2 build system, refer to edk2-platform repo for full build instructions. + +:: + + git clone https://github.com/tianocore/edk2-platforms.git + Platform/Qemu/SbsaQemu/Readme.md + diff --git a/arm-trusted-firmware/docs/plat/qemu.rst b/arm-trusted-firmware/docs/plat/qemu.rst new file mode 100644 index 0000000..66b8247 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/qemu.rst @@ -0,0 +1,138 @@ +QEMU virt Armv8-A +================= + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QEMU virt +Armv8-A. BL1 is used as the BootROM, supplied with the -bios argument. +When QEMU starts all CPUs are released simultaneously, BL1 selects a +primary CPU to handle the boot and the secondaries are placed in a polling +loop to be released by normal world via PSCI. + +BL2 edits the Flattened Device Tree, FDT, generated by QEMU at run-time to +add a node describing PSCI and also enable methods for the CPUs. + +If ``ARM_LINUX_KERNEL_AS_BL33`` is set to 1 then this FDT will be passed to BL33 +via register x0, as expected by a Linux kernel. This allows a Linux kernel image +to be booted directly as BL33 rather than using a bootloader. + +An ARM64 defconfig v5.5 Linux kernel is known to boot, FDT doesn't need to be +provided as it's generated by QEMU. + +Current limitations: + +- Only cold boot is supported + +Getting non-TF images +--------------------- + +``QEMU_EFI.fd`` can be downloaded from +http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC5/QEMU_EFI.fd + +or, can be built as follows: + +.. code:: shell + + git clone https://github.com/tianocore/edk2.git + cd edk2 + git submodule update --init + make -C BaseTools + source edksetup.sh + export GCC5_AARCH64_PREFIX=aarch64-linux-gnu- + build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemuKernel.dsc + +```` + +Then, you will get ``Build/ArmVirtQemuKernel-AARCH64/DEBUG_GCC5/FV/QEMU_EFI.fd`` + +Please note you do not need to use GCC 5 in spite of the environment variable +``GCC5_AARCH64_PREFIX`` + +The rootfs can be built by using Buildroot as follows: + +.. code:: shell + + git clone git://git.buildroot.net/buildroot.git + cd buildroot + make qemu_aarch64_virt_defconfig + utils/config -e BR2_TARGET_ROOTFS_CPIO + utils/config -e BR2_TARGET_ROOTFS_CPIO_GZIP + make olddefconfig + make + +Then, you will get ``output/images/rootfs.cpio.gz``. + +Booting via semi-hosting option +------------------------------- + +Boot binaries, except BL1, are primarily loaded via semi-hosting so all +binaries has to reside in the same directory as QEMU is started from. This +is conveniently achieved with symlinks the local names as: + +- ``bl2.bin`` -> BL2 +- ``bl31.bin`` -> BL31 +- ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``) +- ``Image`` -> linux/arch/arm64/boot/Image + +To build: + +.. code:: shell + + make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu + +To start (QEMU v5.0.0): + +.. code:: shell + + qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \ + -kernel Image \ + -append "console=ttyAMA0,38400 keep_bootcon" \ + -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios bl1.bin \ + -d unimp -semihosting-config enable,target=native + +Booting via flash based firmwares +--------------------------------- + +Boot firmwares are loaded via secure FLASH0 device so ``bl1.bin`` and +``fip.bin`` should be concatenated to create a ``flash.bin`` that is flashed +onto secure FLASH0. + +- ``bl32.bin`` -> BL32 (``tee-header_v2.bin``) +- ``bl32_extra1.bin`` -> BL32 Extra1 (``tee-pager_v2.bin``) +- ``bl32_extra2.bin`` -> BL32 Extra2 (``tee-pageable_v2.bin``) +- ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``) +- ``Image`` -> linux/arch/arm64/boot/Image + +To build: + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \ + BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \ + BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip + +To build with TBBR enabled, BL31 and BL32 encrypted with test key: + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \ + BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \ + BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip \ + MBEDTLS_DIR= TRUSTED_BOARD_BOOT=1 \ + GENERATE_COT=1 DECRYPTION_SUPPORT=aes_gcm FW_ENC_STATUS=0 \ + ENCRYPT_BL31=1 ENCRYPT_BL32=1 + +To build flash.bin: + +.. code:: shell + + dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc + dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc + +To start (QEMU v5.0.0): + +.. code:: shell + + qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \ + -kernel Image -no-acpi \ + -append 'console=ttyAMA0,38400 keep_bootcon' \ + -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios flash.bin \ + -d unimp diff --git a/arm-trusted-firmware/docs/plat/qti-msm8916.rst b/arm-trusted-firmware/docs/plat/qti-msm8916.rst new file mode 100644 index 0000000..09a79b7 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/qti-msm8916.rst @@ -0,0 +1,116 @@ +Qualcomm Snapdragon 410 (MSM8916/APQ8016) +========================================= + +The `Qualcomm Snapdragon 410`_ is Qualcomm's first 64-bit SoC, released in 2014 +with four ARM Cortex-A53 cores. There are differents variants (MSM8916, +APQ8016(E), ...) that are all very similar. A popular device based on APQ8016E +is the `DragonBoard 410c`_ single-board computer, but the SoC is also used in +various mid-range smartphones/tablets. + +The TF-A/BL31 port for MSM8916 provides a minimal, community-maintained +EL3 firmware. It is primarily based on information from the public +`Snapdragon 410E Technical Reference Manual`_ combined with a lot of +trial and error to actually make it work. + +.. note:: + Unlike the :doc:`QTI SC7180/SC7280 ` ports, this port does **not** + make use of a proprietary binary components (QTISECLIB). It is fully + open-source but therefore limited to publicly documented hardware + components. + +Functionality +------------- + +The BL31 port is much more minimal compared to the original firmware and +therefore expects the non-secure world (e.g. Linux) to manage more hardware, +such as the SMMUs and all remote processors (RPM, WCNSS, Venus, Modem). +Everything except modem is currently functional with a slightly modified version +of mainline Linux. + +.. warning:: + This port is **not secure**. There is no special secure memory and the + used DRAM is available from both the non-secure and secure worlds. + Unfortunately, the hardware used for memory protection is not described + in the APQ8016E documentation. + +The port is primarily intended as a minimal PSCI implementation (without a +separate secure world) where this limitation is not a big problem. Booting +secondary CPU cores (PSCI ``CPU_ON``) is supported. Basic CPU core power +management (``CPU_SUSPEND``) is functional but still work-in-progress and +will be added later once ready. + +Boot Flow +--------- +BL31 replaces the original ``tz`` firmware in the boot flow:: + + Boot ROM (PBL) -> SBL -> BL31 (EL3) -> U-Boot (EL2) -> Linux (EL2) + +By default, BL31 enters the non-secure world in EL2 AArch64 state at address +``0x8f600000``. The original hypervisor firmware (``hyp``) is not used, you can +use KVM or another hypervisor. The entry address is fixed in the BL31 binary +but can be changed using the ``PRELOADED_BL33_BASE`` make file parameter. + +Using an AArch64 bootloader (such as `U-Boot for DragonBoard 410c`_) is +recommended. AArch32 bootloaders (such as the original Little Kernel bootloader +from Qualcomm) are not directly supported, although it is possible to use an EL2 +shim loader to temporarily switch to AArch32 state. + +Installation +------------ +First, setup the cross compiler for AArch64 and build TF-A for ``msm8916``:: + + $ make CROSS_COMPILE=aarch64-linux-gnu- PLAT=msm8916 + +The BL31 ELF image is generated in ``build/msm8916/release/bl31/bl31.elf``. +This image must be "signed" before flashing it, even if the board has secure +boot disabled. In this case the signature does not provide any security, +but it provides the firmware with required metadata. + +The `DragonBoard 410c`_ does not have secure boot enabled by default. In this +case you can simply sign the ELF image using a randomly generated key. You can +use e.g. `qtestsign`_:: + + $ ./qtestsign.py tz build/msm8916/release/bl31/bl31.elf + +Then install the resulting ``build/msm8916/release/bl31/bl31-test-signed.mbn`` +to the ``tz`` partition on the device. BL31 should be running after a reboot. + +.. warning:: + Do not flash incorrectly signed firmware on devices that have secure + boot enabled! Make sure that you have a way to recover the board in case + of problems (e.g. using EDL). + +Boot Trace +---------- +BL31 prints some lines on the debug console UART2, which will usually look like +this (with ``DEBUG=1``, otherwise only the ``NOTICE`` lines are shown):: + + ... + S - DDR Frequency, 400 MHz + NOTICE: BL31: v2.6(debug):v2.6 + NOTICE: BL31: Built : 20:00:00, Dec 01 2021 + INFO: BL31: Platform setup start + INFO: ARM GICv2 driver initialized + INFO: BL31: Platform setup done + INFO: BL31: Initializing runtime services + INFO: BL31: cortex_a53: CPU workaround for 819472 was applied + INFO: BL31: cortex_a53: CPU workaround for 824069 was applied + INFO: BL31: cortex_a53: CPU workaround for 826319 was applied + INFO: BL31: cortex_a53: CPU workaround for 827319 was applied + INFO: BL31: cortex_a53: CPU workaround for 835769 was applied + INFO: BL31: cortex_a53: CPU workaround for disable_non_temporal_hint was applied + INFO: BL31: cortex_a53: CPU workaround for 843419 was applied + INFO: BL31: cortex_a53: CPU workaround for 1530924 was applied + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x8f600000 + INFO: SPSR = 0x3c9 + + U-Boot 2021.10 (Dec 01 2021 - 20:00:00 +0000) + Qualcomm-DragonBoard 410C + ... + +.. _Qualcomm Snapdragon 410: https://www.qualcomm.com/products/snapdragon-processors-410 +.. _DragonBoard 410c: https://www.96boards.org/product/dragonboard410c/ +.. _Snapdragon 410E Technical Reference Manual: https://developer.qualcomm.com/download/sd410/snapdragon-410e-technical-reference-manual.pdf +.. _U-Boot for DragonBoard 410c: https://u-boot.readthedocs.io/en/latest/board/qualcomm/dragonboard410c.html +.. _qtestsign: https://github.com/msm8916-mainline/qtestsign diff --git a/arm-trusted-firmware/docs/plat/qti.rst b/arm-trusted-firmware/docs/plat/qti.rst new file mode 100644 index 0000000..1d483e7 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/qti.rst @@ -0,0 +1,43 @@ +Qualcomm Technologies, Inc. +=========================== + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QTI SC7180, +SC7280. + +Boot Trace +------------- + +Bootrom --> BL1/BL2 --> BL31 --> BL33 --> Linux kernel + +BL1/2 and BL33 can currently be supplied from Coreboot + Depthcharge + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +QTI SoC expects TF-A's BL31 to get integrated with other boot software +Coreboot, so only bl31.elf need to get build from the TF-A repository. + +The build command looks like + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sc7180 COREBOOT=1 + +update value of CROSS_COMPILE argument with your cross-compilation toolchain. + +Additional QTISECLIB_PATH= can be added in build command. +if QTISECLIB_PATH is not added in build command stub implementation of qtiseclib +is picked. qtiseclib with stub implementation doesn't boot device. This was +added to satisfy compilation. + +QTISELIB for SC7180 is available at +`link `__ +QTISELIB for SC7280 is available at +`link `__ diff --git a/arm-trusted-firmware/docs/plat/rcar-gen3.rst b/arm-trusted-firmware/docs/plat/rcar-gen3.rst new file mode 100644 index 0000000..7107bea --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rcar-gen3.rst @@ -0,0 +1,268 @@ +Renesas R-Car +============= + +"R-Car" is the nickname for Renesas' system-on-chip (SoC) family for +car information systems designed for the next-generation of automotive +computing for the age of autonomous vehicles. + +The scalable R-Car hardware platform and flexible software platform +cover the full product range, from the premium class to the entry +level. Plug-ins are available for multiple open-source software tools. + + +Renesas R-Car Gen3 evaluation boards: +------------------------------------- + ++------------+-----------------+-----------------------------+ +| | Standard | Low Cost Boards (LCB) | ++============+=================+=============================+ +| R-Car H3 | - Salvator-X | - R-Car Starter Kit Premier | +| | - Salvator-XS | | ++------------+-----------------+-----------------------------+ +| R-Car M3-W | - Salvator-X | | +| | - Salvator-XS | - R-Car Starter Kit Pro | ++------------+-----------------+-----------------------------+ +| R-Car M3-N | - Salvator-X | | +| | - Salvator-XS | | ++------------+-----------------+-----------------------------+ +| R-Car V3M | - Eagle | - Starter Kit | ++------------+-----------------+-----------------------------+ +| R-Car V3H | - Condor | - Starter Kit | ++------------+-----------------+-----------------------------+ +| R-Car D3 | - Draak | | ++------------+-----------------+-----------------------------+ + +`boards info `__ + +The current TF-A port has been tested on the R-Car H3 Salvator-X +Soc_id r8a7795 revision ES1.1 (uses a Secure Payload Dispatcher) + + +:: + + ARM CA57 (ARMv8) 1.5 GHz quad core, with NEON/VFPv4, L1$ I/D + 48K/32K, L2$ 2MB + ARM CA53 (ARMv8) 1.2 GHz quad core, with NEON/VFPv4, L1$ I/D 32K/32K, + L2$ 512K + Memory controller for LPDDR4-3200 4GB in 2 channels, each 64-bit wide + Two- and three-dimensional graphics engines, + Video processing units, + 3 channels Display Output, + 6 channels Video Input, + SD card host interface, + USB3.0 and USB2.0 interfaces, + CAN interfaces + Ethernet AVB + PCI Express Interfaces + Memories + INTERNAL 384KB SYSTEM RAM + DDR 4 GB LPDDR4 + HYPERFLASH 64 MB HYPER FLASH (512 MBITS, 160 MHZ, 320 MBYTES/S) + QSPI FLASH 16MB QSPI (128 MBITS,80 MHZ,80 MBYTES/S)1 HEADER QSPI + MODULE + EMMC 32 GB EMMC (HS400 240 MBYTES/S) + MICROSD-CARD SLOT (SDR104 100 MBYTES/S) + + +Overview +-------- +On the rcar-gen3 the BOOTROM starts the cpu at EL3; for this port BL2 +will therefore be entered at this exception level (the Renesas' ATF +reference tree [1] resets into EL1 before entering BL2 - see its +bl2.ld.S) + +BL2 initializes DDR (and on some platforms i2c to interface to the +PMIC) before determining the boot reason (cold or warm). + +During suspend all CPUs are switched off and the DDR is put in backup +mode (some kind of self-refresh mode). This means that BL2 is always +entered in a cold boot scenario. + +Once BL2 boots, it determines the boot reason, writes it to shared +memory (BOOT_KIND_BASE) together with the BL31 parameters +(PARAMS_BASE) and jumps to BL31. + +To all effects, BL31 is as if it is being entered in reset mode since +it still needs to initialize the rest of the cores; this is the reason +behind using direct shared memory access to BOOT_KIND_BASE _and_ +PARAMS_BASE instead of using registers to get to those locations (see +el3_common_macros.S and bl31_entrypoint.S for the RESET_TO_BL31 use +case). + +Depending on the boot reason BL31 initializes the rest of the cores: +in case of suspend, it uses a MBOX memory region to recover the +program counters. + +[1] https://github.com/renesas-rcar/arm-trusted-firmware + + +How to build +------------ + +The TF-A build options depend on the target board so you will have to +refer to those specific instructions. What follows is customized to +the H3 SiP Salvator-X development system used in this port. + +Build Tested: +~~~~~~~~~~~~~ +RCAR_OPT="LSI=H3 RCAR_DRAM_SPLIT=1 RCAR_LOSSY_ENABLE=1" +MBEDTLS_DIR=$mbedtls_src + +$ MBEDTLS_DIR=$mbedtls_src_tree make clean bl2 bl31 rcar_layout_tool \ +PLAT=rcar ${RCAR_OPT} SPD=opteed + +System Tested: +~~~~~~~~~~~~~~ +* mbed_tls: + git@github.com:ARMmbed/mbedtls.git [devel] + + commit 552754a6ee82bab25d1bdf28c8261a4518e65e4d + Merge: 68dbc94 f34a4c1 + Author: Simon Butcher + Date: Thu Aug 30 00:57:28 2018 +0100 + +* optee_os: + https://github.com/BayLibre/optee_os + + Until it gets merged into OP-TEE, the port requires Renesas' + Trusted Environment with a modification to support power + management. + commit 80105192cba9e704ebe8df7ab84095edc2922f84 + + Author: Jorge Ramirez-Ortiz + Date: Thu Aug 30 16:49:49 2018 +0200 + plat-rcar: cpu-suspend: handle the power level + Signed-off-by: Jorge Ramirez-Ortiz + +* u-boot: + The port has beent tested using mainline uboot. + + commit 4cdeda511f8037015b568396e6dcc3d8fb41e8c0 + Author: Fabio Estevam + Date: Tue Sep 4 10:23:12 2018 -0300 + +* linux: + The port has beent tested using mainline kernel. + + commit 7876320f88802b22d4e2daf7eb027dd14175a0f8 + Author: Linus Torvalds + Date: Sun Sep 16 11:52:37 2018 -0700 + Linux 4.19-rc4 + +TF-A Build Procedure +~~~~~~~~~~~~~~~~~~~~ + +- Fetch all the above 4 repositories. + +- Prepare the AARCH64 toolchain. + +- Build u-boot using r8a7795_salvator-x_defconfig. + Result: u-boot-elf.srec + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- + r8a7795_salvator-x_defconfig + + make CROSS_COMPILE=aarch64-linux-gnu- + +- Build atf + Result: bootparam_sa0.srec, cert_header_sa6.srec, bl2.srec, bl31.srec + +.. code:: bash + + RCAR_OPT="LSI=H3 RCAR_DRAM_SPLIT=1 RCAR_LOSSY_ENABLE=1" + + MBEDTLS_DIR=$mbedtls_src_tree make clean bl2 bl31 rcar \ + PLAT=rcar ${RCAR_OPT} SPD=opteed + +- Build optee-os + Result: tee.srec + +.. code:: bash + + make -j8 PLATFORM="rcar" CFG_ARM64_core=y + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- Boot the board in Mini-monitor mode and enable access to the + Hyperflash. + + +- Use the XSL2 Mini-monitor utility to accept all the SREC ascii + transfers over serial. + + +Boot trace +---------- + +Notice that BL31 traces are not accessible via the console and that in +order to verbose the BL2 output you will have to compile TF-A with +LOG_LEVEL=50 and DEBUG=1 + +:: + + Initial Program Loader(CA57) Rev.1.0.22 + NOTICE: BL2: PRR is R-Car H3 Ver.1.1 + NOTICE: BL2: Board is Salvator-X Rev.1.0 + NOTICE: BL2: Boot device is HyperFlash(80MHz) + NOTICE: BL2: LCM state is CM + NOTICE: AVS setting succeeded. DVFS_SetVID=0x53 + NOTICE: BL2: DDR1600(rev.0.33)NOTICE: [COLD_BOOT]NOTICE: ..0 + NOTICE: BL2: DRAM Split is 4ch + NOTICE: BL2: QoS is default setting(rev.0.37) + NOTICE: BL2: Lossy Decomp areas + NOTICE: Entry 0: DCMPAREACRAx:0x80000540 DCMPAREACRBx:0x570 + NOTICE: Entry 1: DCMPAREACRAx:0x40000000 DCMPAREACRBx:0x0 + NOTICE: Entry 2: DCMPAREACRAx:0x20000000 DCMPAREACRBx:0x0 + NOTICE: BL2: v2.0(release):v2.0-rc0-32-gbcda69a + NOTICE: BL2: Built : 16:41:23, Oct 2 2018 + NOTICE: BL2: Normal boot + INFO: BL2: Doing platform setup + INFO: BL2: Loading image id 3 + NOTICE: BL2: dst=0xe6322000 src=0x8180000 len=512(0x200) + NOTICE: BL2: dst=0x43f00000 src=0x8180400 len=6144(0x1800) + WARNING: r-car ignoring the BL31 size from certificate,using + RCAR_TRUSTED_SRAM_SIZE instead + INFO: Loading image id=3 at address 0x44000000 + NOTICE: rcar_file_len: len: 0x0003e000 + NOTICE: BL2: dst=0x44000000 src=0x81c0000 len=253952(0x3e000) + INFO: Image id=3 loaded: 0x44000000 - 0x4403e000 + INFO: BL2: Loading image id 4 + INFO: Loading image id=4 at address 0x44100000 + NOTICE: rcar_file_len: len: 0x00100000 + NOTICE: BL2: dst=0x44100000 src=0x8200000 len=1048576(0x100000) + INFO: Image id=4 loaded: 0x44100000 - 0x44200000 + INFO: BL2: Loading image id 5 + INFO: Loading image id=5 at address 0x50000000 + NOTICE: rcar_file_len: len: 0x00100000 + NOTICE: BL2: dst=0x50000000 src=0x8640000 len=1048576(0x100000) + INFO: Image id=5 loaded: 0x50000000 - 0x50100000 + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0x44000000 + INFO: SPSR = 0x3cd + VERBOSE: Argument #0 = 0xe6325578 + VERBOSE: Argument #1 = 0x0 + VERBOSE: Argument #2 = 0x0 + VERBOSE: Argument #3 = 0x0 + VERBOSE: Argument #4 = 0x0 + VERBOSE: Argument #5 = 0x0 + VERBOSE: Argument #6 = 0x0 + VERBOSE: Argument #7 = 0x0 + + + U-Boot 2018.09-rc3-00028-g3711616 (Sep 27 2018 - 18:50:24 +0200) + + CPU: Renesas Electronics R8A7795 rev 1.1 + Model: Renesas Salvator-X board based on r8a7795 ES2.0+ + DRAM: 3.5 GiB + Flash: 64 MiB + MMC: sd@ee100000: 0, sd@ee140000: 1, sd@ee160000: 2 + Loading Environment from MMC... OK + In: serial@e6e88000 + Out: serial@e6e88000 + Err: serial@e6e88000 + Net: eth0: ethernet@e6800000 + Hit any key to stop autoboot: 0 + => diff --git a/arm-trusted-firmware/docs/plat/rockchip.rst b/arm-trusted-firmware/docs/plat/rockchip.rst new file mode 100644 index 0000000..b7c43fb --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rockchip.rst @@ -0,0 +1,55 @@ +Rockchip SoCs +============= + +Trusted Firmware-A supports a number of Rockchip ARM SoCs from both +AARCH32 and AARCH64 fields. + +This includes right now: +- px30: Quad-Core Cortex-A53 +- rk3288: Quad-Core Cortex-A17 (past A12) +- rk3328: Quad-Core Cortex-A53 +- rk3368: Octa-Core Cortex-A53 +- rk3399: Hexa-Core Cortex-A53/A72 + + +Boot Sequence +------------- + +For AARCH32: + Bootrom --> BL1/BL2 --> BL32 --> BL33 --> Linux kernel + +For AARCH64: + Bootrom --> BL1/BL2 --> BL31 --> BL33 --> Linux kernel + +BL1/2 and BL33 can currently be supplied from either: +- Coreboot + Depthcharge +- U-Boot - either separately as TPL+SPL or only SPL + + +How to build +------------ + +Rockchip SoCs expect TF-A's BL31 (AARCH64) or BL32 (AARCH32) to get +integrated with other boot software like U-Boot or Coreboot, so only +these images need to get build from the TF-A repository. + +For AARCH64 architectures the build command looks like + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3399 bl32 + +while AARCH32 needs a slightly different command + + make ARCH=aarch32 CROSS_COMPILE=arm-linux-gnueabihf- PLAT=rk3288 AARCH32_SP=sp_min bl32 + +Both need replacing the PLAT argument with the platform from above you +want to build for and the CROSS_COMPILE argument with you cross- +compilation toolchain. + + +How to deploy +------------- + +Both upstream U-Boot and Coreboot projects contain instructions on where +to put the built images during their respective build process. +So after successfully building TF-A just follow their build instructions +to continue. diff --git a/arm-trusted-firmware/docs/plat/rpi3.rst b/arm-trusted-firmware/docs/plat/rpi3.rst new file mode 100644 index 0000000..38c3dfa --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rpi3.rst @@ -0,0 +1,466 @@ +Raspberry Pi 3 +============== + +The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four +Arm Cortex-A53 cores. + +The following instructions explain how to use this port of the TF-A with the +default distribution of `Raspbian`_ because that's the distribution officially +supported by the Raspberry Pi Foundation. At the moment of writing this, the +officially supported kernel is a AArch32 kernel. This doesn't mean that this +port of TF-A can't boot a AArch64 kernel. The `Linux tree fork`_ maintained by +the Foundation can be compiled for AArch64 by following the steps in +`AArch64 kernel build instructions`_. + +**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM, +which is available from both the Non-secure and Secure worlds. This port +shouldn't be considered more than a prototype to play with and implement +elements like PSCI to support the Linux kernel. + +Design +------ + +The SoC used by the Raspberry Pi 3 is the Broadcom BCM2837. It is a SoC with a +VideoCore IV that acts as primary processor (and loads everything from the SD +card) and is located between all Arm cores and the DRAM. Check the `Raspberry Pi +3 documentation`_ for more information. + +This explains why it is possible to change the execution state (AArch64/AArch32) +depending on a few files on the SD card. We only care about the cases in which +the cores boot in AArch64 mode. + +The rules are simple: + +- If a file called ``kernel8.img`` is located on the ``boot`` partition of the + SD card, it will load it and execute in EL2 in AArch64. Basically, it executes + a `default AArch64 stub`_ at address **0x0** that jumps to the kernel. + +- If there is also a file called ``armstub8.bin``, it will load it at address + **0x0** (instead of the default stub) and execute it in EL3 in AArch64. All + the cores are powered on at the same time and start at address **0x0**. + +This means that we can use the default AArch32 kernel provided in the official +`Raspbian`_ distribution by renaming it to ``kernel8.img``, while TF-A and +anything else we need is in ``armstub8.bin``. This way we can forget about the +default bootstrap code. When using a AArch64 kernel, it is only needed to make +sure that the name on the SD card is ``kernel8.img``. + +Ideally, we want to load the kernel and have all cores available, which means +that we need to make the secondary cores work in the way the kernel expects, as +explained in `Secondary cores`_. In practice, a small bootstrap is needed +between TF-A and the kernel. + +To get the most out of a AArch32 kernel, we want to boot it in Hypervisor mode +in AArch32. This means that BL33 can't be in EL2 in AArch64 mode. The +architecture specifies that AArch32 Hypervisor mode isn't present when AArch64 +is used for EL2. When using a AArch64 kernel, it should simply start in EL2. + +Placement of images +~~~~~~~~~~~~~~~~~~~ + +The file ``armstub8.bin`` contains BL1 and the FIP. It is needed to add padding +between them so that the addresses they are loaded to match the ones specified +when compiling TF-A. This is done automatically by the build system. + +The device tree block is loaded by the VideoCore loader from an appropriate +file, but we can specify the address it is loaded to in ``config.txt``. + +The file ``kernel8.img`` contains a kernel image that is loaded to the address +specified in ``config.txt``. The `Linux kernel tree`_ has information about how +a AArch32 Linux kernel image is loaded in ``Documentation/arm/Booting``: + +:: + + The zImage may also be placed in system RAM and called there. The + kernel should be placed in the first 128MiB of RAM. It is recommended + that it is loaded above 32MiB in order to avoid the need to relocate + prior to decompression, which will make the boot process slightly + faster. + +There are no similar restrictions for AArch64 kernels, as specified in the file +``Documentation/arm64/booting.txt``. + +This means that we need to avoid the first 128 MiB of RAM when placing the +TF-A images (and specially the first 32 MiB, as they are directly used to +place the uncompressed AArch32 kernel image. This way, both AArch32 and +AArch64 kernels can be placed at the same address. + +In the end, the images look like the following diagram when placed in memory. +All addresses are Physical Addresses from the point of view of the Arm cores. +Again, note that this is all just part of the same DRAM that goes from +**0x00000000** to **0x3F000000**, it just has different names to simulate a real +secure platform! + +:: + + 0x00000000 +-----------------+ + | ROM | BL1 + 0x00020000 +-----------------+ + | FIP | + 0x00200000 +-----------------+ + | | + | ... | + | | + 0x01000000 +-----------------+ + | DTB | (Loaded by the VideoCore) + +-----------------+ + | | + | ... | + | | + 0x02000000 +-----------------+ + | Kernel | (Loaded by the VideoCore) + +-----------------+ + | | + | ... | + | | + 0x10000000 +-----------------+ + | Secure SRAM | BL2, BL31 + 0x10100000 +-----------------+ + | Secure DRAM | BL32 (Secure payload) + 0x11000000 +-----------------+ + | Non-secure DRAM | BL33 + +-----------------+ + | | + | ... | + | | + 0x3F000000 +-----------------+ + | I/O | + 0x40000000 +-----------------+ + +The area between **0x10000000** and **0x11000000** has to be manually protected +so that the kernel doesn't use it. The current port tries to modify the live DTB +to add a memreserve region that reserves the previously mentioned area. + +If this is not possible, the user may manually add ``memmap=16M$256M`` to the +command line passed to the kernel in ``cmdline.txt``. See the `Setup SD card`_ +instructions to see how to do it. This system is strongly discouraged. + +The last 16 MiB of DRAM can only be accessed by the VideoCore, that has +different mappings than the Arm cores in which the I/O addresses don't overlap +the DRAM. The memory reserved to be used by the VideoCore is always placed at +the end of the DRAM, so this space isn't wasted. + +Considering the 128 MiB allocated to the GPU and the 16 MiB allocated for +TF-A, there are 880 MiB available for Linux. + +Boot sequence +~~~~~~~~~~~~~ + +The boot sequence of TF-A is the usual one except when booting an AArch32 +kernel. In that case, BL33 is booted in AArch32 Hypervisor mode so that it +can jump to the kernel in the same mode and let it take over that privilege +level. If BL33 was running in EL2 in AArch64 (as in the default bootflow of +TF-A) it could only jump to the kernel in AArch32 in Supervisor mode. + +The `Linux kernel tree`_ has instructions on how to jump to the Linux kernel +in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The +bootstrap should take care of this. + +This port support a direct boot of the Linux kernel from the firmware (as a BL33 +image). Alternatively, U-Boot or other bootloaders may be used. + +Secondary cores +~~~~~~~~~~~~~~~ + +This port of the Trusted Firmware-A supports ``PSCI_CPU_ON``, +``PSCI_SYSTEM_RESET`` and ``PSCI_SYSTEM_OFF``. The last one doesn't really turn +the system off, it simply reboots it and asks the VideoCore firmware to keep it +in a low power mode permanently. + +The kernel used by `Raspbian`_ doesn't have support for PSCI, so it is needed to +use mailboxes to trap the secondary cores until they are ready to jump to the +kernel. This mailbox is located at a different address in the AArch32 default +kernel than in the AArch64 kernel. + +Kernels with PSCI support can use the PSCI calls instead for a cleaner boot. + +Also, this port of TF-A has another Trusted Mailbox in Shared BL RAM. During +cold boot, all secondary cores wait in a loop until they are given given an +address to jump to in this Mailbox (``bl31_warm_entrypoint``). + +Once BL31 has finished and the primary core has jumped to the BL33 payload, it +has to call ``PSCI_CPU_ON`` to release the secondary CPUs from the wait loop. +The payload then makes them wait in another waitloop listening from messages +from the kernel. When the primary CPU jumps into the kernel, it will send an +address to the mailbox so that the secondary CPUs jump to it and are recognised +by the kernel. + +Build Instructions +------------------ + +To boot a AArch64 kernel, only the AArch64 toolchain is required. + +To boot a AArch32 kernel, both AArch64 and AArch32 toolchains are required. The +AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit +kernel. + +The build system concatenates BL1 and the FIP so that the addresses match the +ones in the memory map. The resulting file is ``armstub8.bin``, located in the +build folder (e.g. ``build/rpi3/debug/armstub8.bin``). To know how to use this +file, follow the instructions in `Setup SD card`_. + +The following build options are supported: + +- ``RPI3_BL33_IN_AARCH32``: This port can load a AArch64 or AArch32 BL33 image. + By default this option is 0, which means that TF-A will jump to BL33 in EL2 + in AArch64 mode. If set to 1, it will jump to BL33 in Hypervisor in AArch32 + mode. + +- ``PRELOADED_BL33_BASE``: Used to specify the address of a BL33 binary that has + been preloaded by any other system than using the firmware. ``BL33`` isn't + needed in the build command line if this option is used. Specially useful + because the file ``kernel8.img`` can be loaded anywhere by modifying the file + ``config.txt``. It doesn't have to contain a kernel, it could have any + arbitrary payload. + +- ``RPI3_DIRECT_LINUX_BOOT``: Disabled by default. Set to 1 to enable the direct + boot of the Linux kernel from the firmware. Option ``RPI3_PRELOADED_DTB_BASE`` + is mandatory when the direct Linux kernel boot is used. Options + ``PRELOADED_BL33_BASE`` will most likely be needed as well because it is + unlikely that the kernel image will fit in the space reserved for BL33 images. + This option can be combined with ``RPI3_BL33_IN_AARCH32`` in order to boot a + 32-bit kernel. The only thing this option does is to set the arguments in + registers x0-x3 or r0-r2 as expected by the kernel. + +- ``RPI3_PRELOADED_DTB_BASE``: Auxiliary build option needed when using + ``RPI3_DIRECT_LINUX_BOOT=1``. This option allows to specify the location of a + DTB in memory. + +- ``RPI3_RUNTIME_UART``: Indicates whether the UART should be used at runtime + or disabled. ``-1`` (default) disables the runtime UART. Any other value + enables the default UART (currently UART1) for runtime messages. + +- ``RPI3_USE_UEFI_MAP``: Set to 1 to build ATF with the altername memory + mapping required for an UEFI firmware payload. These changes are needed + to be able to run Windows on ARM64. This option, which is disabled by + default, results in the following memory mappings: + +:: + + 0x00000000 +-----------------+ + | ROM | BL1 + 0x00010000 +-----------------+ + | DTB | (Loaded by the VideoCore) + 0x00020000 +-----------------+ + | FIP | + 0x00030000 +-----------------+ + | | + | UEFI PAYLOAD | + | | + 0x00200000 +-----------------+ + | Secure SRAM | BL2, BL31 + 0x00300000 +-----------------+ + | Secure DRAM | BL32 (Secure payload) + 0x00400000 +-----------------+ + | | + | | + | Non-secure DRAM | BL33 + | | + | | + 0x01000000 +-----------------+ + | | + | ... | + | | + 0x3F000000 +-----------------+ + | I/O | + +- ``BL32``: This port can load and run OP-TEE. The OP-TEE image is optional. + Please use the code from `here `__. + Build the Trusted Firmware with option ``BL32=tee-header_v2.bin + BL32_EXTRA1=tee-pager_v2.bin BL32_EXTRA2=tee-pageable_v2.bin`` + to put the binaries into the FIP. + + .. warning:: + If OP-TEE is used it may be needed to add the following options to the + Linux command line so that the USB driver doesn't use FIQs: + ``dwc_otg.fiq_enable=0 dwc_otg.fiq_fsm_enable=0 dwc_otg.nak_holdoff=0``. + This will unfortunately reduce the performance of the USB driver. It is + needed when using Raspbian, for example. + +- ``TRUSTED_BOARD_BOOT``: This port supports TBB. Set this option to 1 to enable + it. In order to use TBB, you might want to set ``GENERATE_COT=1`` to let the + contents of the FIP automatically signed by the build process. The ROT key + will be generated and output to ``rot_key.pem`` in the build directory. It is + able to set ROT_KEY to your own key in PEM format. Also in order to build, + you need to clone mbed TLS from `here `__. + ``MBEDTLS_DIR`` must point at the mbed TLS source directory. + +- ``ENABLE_STACK_PROTECTOR``: Disabled by default. It uses the hardware RNG of + the board. + +The following is not currently supported: + +- AArch32 for TF-A itself. + +- ``EL3_PAYLOAD_BASE``: The reason is that you can already load anything to any + address by changing the file ``armstub8.bin``, so there's no point in using + TF-A in this case. + +- ``MULTI_CONSOLE_API=0``: The multi console API must be enabled. Note that the + crash console uses the internal 16550 driver functions directly in order to be + able to print error messages during early crashes before setting up the + multi console API. + +Building the firmware for kernels that don't support PSCI +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the case for the 32-bit image of Raspbian, for example. 64-bit kernels +always support PSCI, but they may not know that the system understands PSCI due +to an incorrect DTB file. + +First, clone and compile the 32-bit version of the `Raspberry Pi 3 TF-A +bootstrap`_. Choose the one needed for the architecture of your kernel. + +Then compile TF-A. For a 32-bit kernel, use the following command line: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + RPI3_BL33_IN_AARCH32=1 \ + BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin + +For a 64-bit kernel, use this other command line: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin + +However, enabling PSCI support in a 64-bit kernel is really easy. In the +repository `Raspberry Pi 3 TF-A bootstrap`_ there is a patch that can be applied +to the Linux kernel tree maintained by the Raspberry Pi foundation. It modifes +the DTS to tell the kernel to use PSCI. Once this patch is applied, follow the +instructions in `AArch64 kernel build instructions`_ to get a working 64-bit +kernel image and supporting files. + +Building the firmware for kernels that support PSCI +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For a 64-bit kernel: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + PRELOADED_BL33_BASE=0x02000000 \ + RPI3_PRELOADED_DTB_BASE=0x01000000 \ + RPI3_DIRECT_LINUX_BOOT=1 + +For a 32-bit kernel: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + PRELOADED_BL33_BASE=0x02000000 \ + RPI3_PRELOADED_DTB_BASE=0x01000000 \ + RPI3_DIRECT_LINUX_BOOT=1 \ + RPI3_BL33_IN_AARCH32=1 + +AArch64 kernel build instructions +--------------------------------- + +The following instructions show how to install and run a AArch64 kernel by +using a SD card with the default `Raspbian`_ install as base. Skip them if you +want to use the default 32-bit kernel. + +Note that this system won't be fully 64-bit because all the tools in the +filesystem are 32-bit binaries, but it's a quick way to get it working, and it +allows the user to run 64-bit binaries in addition to 32-bit binaries. + +1. Clone the `Linux tree fork`_ maintained by the Raspberry Pi Foundation. To + speed things up, do a shallow clone of the desired branch. + +.. code:: shell + + git clone --depth=1 -b rpi-4.18.y https://github.com/raspberrypi/linux + cd linux + +2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is + 1.5 times the number of CPUs in your computer. This may take some time to + finish. + +.. code:: shell + + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig + make -j 6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- + +3. Copy the kernel image and the device tree to the SD card. Replace the path + by the corresponding path in your computers to the ``boot`` partition of the + SD card. + +.. code:: shell + + cp arch/arm64/boot/Image /path/to/boot/kernel8.img + cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/ + cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dtb /path/to/boot/ + +4. Install the kernel modules. Replace the path by the corresponding path to the + filesystem partition of the SD card on your computer. + +.. code:: shell + + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \ + INSTALL_MOD_PATH=/path/to/filesystem modules_install + +5. Follow the instructions in `Setup SD card`_ except for the step of renaming + the existing ``kernel7.img`` (we have already copied a AArch64 kernel). + +Setup SD card +------------- + +The instructions assume that you have an SD card with a fresh install of +`Raspbian`_ (or that, at least, the ``boot`` partition is untouched, or nearly +untouched). They have been tested with the image available in 2018-03-13. + +1. Insert the SD card and open the ``boot`` partition. + +2. Rename ``kernel7.img`` to ``kernel8.img``. This tricks the VideoCore + bootloader into booting the Arm cores in AArch64 mode, like TF-A needs, + even though the kernel is not compiled for AArch64. + +3. Copy ``armstub8.bin`` here. When ``kernel8.img`` is available, The VideoCore + bootloader will look for a file called ``armstub8.bin`` and load it at + address **0x0** instead of a predefined one. + +4. To enable the serial port "Mini UART" in Linux, open ``cmdline.txt`` and add + ``console=serial0,115200 console=tty1``. + +5. Open ``config.txt`` and add the following lines at the end (``enable_uart=1`` + is only needed to enable debugging through the Mini UART): + +:: + + enable_uart=1 + kernel_address=0x02000000 + device_tree_address=0x01000000 + +If you connect a serial cable to the Mini UART and your computer, and connect +to it (for example, with ``screen /dev/ttyUSB0 115200``) you should see some +text. In the case of an AArch32 kernel, you should see something like this: + +:: + + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL1: Built : 00:09:25, Nov 6 2017 + NOTICE: BL1: Booting BL2 + NOTICE: BL2: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL2: Built : 00:09:25, Nov 6 2017 + NOTICE: BL1: Booting BL31 + NOTICE: BL31: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL31: Built : 00:09:25, Nov 6 2017 + [ 0.266484] bcm2835-aux-uart 3f215040.serial: could not get clk: -517 + + Raspbian GNU/Linux 9 raspberrypi ttyS0 + raspberrypi login: + +Just enter your credentials, everything should work as expected. Note that the +HDMI output won't show any text during boot. + +.. _default Arm stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub7.S +.. _default AArch64 stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S +.. _Linux kernel tree: https://github.com/torvalds/linux +.. _Linux tree fork: https://github.com/raspberrypi/linux +.. _Raspberry Pi 3: https://www.raspberrypi.org/products/raspberry-pi-3-model-b/ +.. _Raspberry Pi 3 TF-A bootstrap: https://github.com/AntonioND/rpi3-arm-tf-bootstrap +.. _Raspberry Pi 3 documentation: https://www.raspberrypi.org/documentation/ +.. _Raspbian: https://www.raspberrypi.org/downloads/raspbian/ diff --git a/arm-trusted-firmware/docs/plat/rpi4.rst b/arm-trusted-firmware/docs/plat/rpi4.rst new file mode 100644 index 0000000..6e83fd7 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rpi4.rst @@ -0,0 +1,84 @@ +Raspberry Pi 4 +============== + +The `Raspberry Pi 4`_ is an inexpensive single-board computer that contains four +Arm Cortex-A72 cores. Also in contrast to previous Raspberry Pi versions this +model has a GICv2 interrupt controller. + +This port is a minimal port to support loading non-secure EL2 payloads such +as a 64-bit Linux kernel. Other payloads such as U-Boot or EDK-II should work +as well, but have not been tested at this point. + +**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM, +which is available from both the Non-secure and Secure worlds. The SoC does +not seem to feature a secure memory controller of any kind, so portions of +DRAM can't be protected properly from the Non-secure world. + +Build Instructions +------------------ + +There are no real configuration options at this point, so there is only +one universal binary (bl31.bin), which can be built with: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi4 DEBUG=1 + +Copy the generated build/rpi4/debug/bl31.bin to the SD card, adding an entry +starting with ``armstub=``, then followed by the respective file name to +``config.txt``. You should have AArch64 code in the file loaded as the +"kernel", as BL31 will drop into AArch64/EL2 to the respective load address. +arm64 Linux kernels are known to work this way. + +Other options that should be set in ``config.txt`` to properly boot 64-bit +kernels are: + +:: + + enable_uart=1 + arm_64bit=1 + enable_gic=1 + +The BL31 code will patch the provided device tree blob in memory to advertise +PSCI support, also will add a reserved-memory node to the DT to tell the +non-secure payload to not touch the resident TF-A code. + +If you connect a serial cable between the Mini UART and your computer, and +connect to it (for example, with ``screen /dev/ttyUSB0 115200``) you should +see some text from BL31, followed by the output of the EL2 payload. +The command line provided is read from the ``cmdline.txt`` file on the SD card. + +TF-A port design +---------------- + +In contrast to the existing Raspberry Pi 3 port this one here is a BL31-only +port, also it deviates quite a lot from the RPi3 port in many other ways. +There is not so much difference between the two models, so eventually those +two could be (more) unified in the future. + +As with the previous models, the GPU and its firmware are the first entity to +run after the SoC gets its power. The on-chip Boot ROM loads the next stage +(bootcode.bin) from flash (EEPROM), which is again GPU code. +This part knows how to access the MMC controller and how to parse a FAT +filesystem, so it will load further components and configuration files +from the first FAT partition on the SD card. + +To accommodate this existing way of configuring and setting up the board, +we use as much of this workflow as possible. +If bootcode.bin finds a file called ``armstub8.bin`` on the SD card or it gets +pointed to such code by finding a ``armstub=`` key in ``config.txt``, it will +load this file to the beginning of DRAM (address 0) and execute it in +AArch64 EL3. +But before doing that, it will also load a "kernel" and the device tree into +memory. The load addresses have a default, but can also be changed by +setting them in ``config.txt``. If the GPU firmware finds a magic value in the +armstub image file, it will put those two load addresses in memory locations +near the beginning of memory, where TF-A code picks them up. + +To keep things simple, we will just use the kernel load address as the BL33 +entry point, also put the DTB address in the x0 register, as requested by +the arm64 Linux kernel boot protocol. This does not necessarily mean that +the EL2 payload needs to be a Linux kernel, a bootloader or any other kernel +would work as well, as long as it can cope with having the DT address in +register x0. If the payload has other means of finding the device tree, it +could ignore this address as well. diff --git a/arm-trusted-firmware/docs/plat/rz-g2.rst b/arm-trusted-firmware/docs/plat/rz-g2.rst new file mode 100644 index 0000000..e7ae620 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rz-g2.rst @@ -0,0 +1,228 @@ +Renesas RZ/G +============ + +The "RZ/G" Family of high-end 64-bit Arm®-based microprocessors (MPUs) +enables the solutions required for the smart society of the future. +Through a variety of Arm Cortex®-A53 and A57-based devices, engineers can +easily implement high-resolution human machine interfaces (HMI), embedded +vision, embedded artificial intelligence (e-AI) and real-time control and +industrial ethernet connectivity. + +The scalable RZ/G hardware platform and flexible software platform +cover the full product range, from the premium class to the entry +level. Plug-ins are available for multiple open-source software tools. + + +Renesas RZ/G2 reference platforms: +---------------------------------- + ++--------------+----------------------------------------------------------------------------------+ +| Board | Details | ++==============+===============+==================================================================+ +| hihope-rzg2h | "96 boards" compatible board from Hoperun equipped with Renesas RZ/G2H SoC | +| +----------------------------------------------------------------------------------+ +| | http://hihope.org/product/musashi | ++--------------+----------------------------------------------------------------------------------+ +| hihope-rzg2m | "96 boards" compatible board from Hoperun equipped with Renesas RZ/G2M SoC | +| +----------------------------------------------------------------------------------+ +| | http://hihope.org/product/musashi | ++--------------+----------------------------------------------------------------------------------+ +| hihope-rzg2n | "96 boards" compatible board from Hoperun equipped with Renesas RZ/G2N SoC | +| +----------------------------------------------------------------------------------+ +| | http://hihope.org/product/musashi | ++--------------+----------------------------------------------------------------------------------+ +| ek874 | "96 boards" compatible board from Silicon Linux equipped with Renesas RZ/G2E SoC | +| +----------------------------------------------------------------------------------+ +| | https://www.si-linux.co.jp/index.php?CAT%2FCAT874 | ++--------------+----------------------------------------------------------------------------------+ + +`boards info `__ + +The current TF-A port has been tested on the HiHope RZ/G2M +SoC_id r8a774a1 revision ES1.3. + + +:: + + ARM CA57 (ARMv8) 1.5 GHz dual core, with NEON/VFPv4, L1$ I/D 48K/32K, L2$ 1MB + ARM CA53 (ARMv8) 1.2 GHz quad core, with NEON/VFPv4, L1$ I/D 32K/32K, L2$ 512K + Memory controller for LPDDR4-3200 4GB in 2 channels(32-bit bus mode) + Two- and three-dimensional graphics engines, + Video processing units, + Display Output, + Video Input, + SD card host interface, + USB3.0 and USB2.0 interfaces, + CAN interfaces, + Ethernet AVB, + Wi-Fi + BT, + PCI Express Interfaces, + Memories + INTERNAL 384KB SYSTEM RAM + DDR 4 GB LPDDR4 + QSPI FLASH 64MB + EMMC 32 GB EMMC (HS400 240 MBYTES/S) + MICROSD-CARD SLOT (SDR104 100 MBYTES/S) + +Overview +-------- +On RZ/G2 SoCs the BOOTROM starts the cpu at EL3; for this port BL2 +will therefore be entered at this exception level (the Renesas' ATF +reference tree [1] resets into EL1 before entering BL2 - see its +bl2.ld.S) + +BL2 initializes DDR before determining the boot reason (cold or warm). + +Once BL2 boots, it determines the boot reason, writes it to shared +memory (BOOT_KIND_BASE) together with the BL31 parameters +(PARAMS_BASE) and jumps to BL31. + +To all effects, BL31 is as if it is being entered in reset mode since +it still needs to initialize the rest of the cores; this is the reason +behind using direct shared memory access to BOOT_KIND_BASE _and_ +PARAMS_BASE instead of using registers to get to those locations (see +el3_common_macros.S and bl31_entrypoint.S for the RESET_TO_BL31 use +case). + +[1] https://github.com/renesas-rz/meta-rzg2/tree/BSP-1.0.5/recipes-bsp/arm-trusted-firmware/files + + +How to build +------------ + +The TF-A build options depend on the target board so you will have to +refer to those specific instructions. What follows is customized to +the HiHope RZ/G2M development kit used in this port. + +Build Tested: +~~~~~~~~~~~~~ + +.. code:: bash + + make bl2 bl31 rzg LOG_LEVEL=40 PLAT=rzg LSI=G2M RCAR_DRAM_SPLIT=2\ + RCAR_LOSSY_ENABLE=1 SPD="none" MBEDTLS_DIR=$mbedtls + +System Tested: +~~~~~~~~~~~~~~ +* mbed_tls: + git@github.com:ARMmbed/mbedtls.git [devel] + +| commit 72ca39737f974db44723760623d1b29980c00a88 +| Merge: ef94c4fcf dd9ec1c57 +| Author: Janos Follath +| Date: Wed Oct 7 09:21:01 2020 +0100 + +* u-boot: + The port has beent tested using mainline uboot with HiHope RZ/G2M board + specific patches. + +| commit 46ce9e777c1314ccb78906992b94001194eaa87b +| Author: Heiko Schocher +| Date: Tue Nov 3 15:22:36 2020 +0100 + +* linux: + The port has beent tested using mainline kernel. + +| commit f8394f232b1eab649ce2df5c5f15b0e528c92091 +| Author: Linus Torvalds +| Date: Sun Nov 8 16:10:16 2020 -0800 +| Linux 5.10-rc3 + +TF-A Build Procedure +~~~~~~~~~~~~~~~~~~~~ + +- Fetch all the above 3 repositories. + +- Prepare the AARCH64 toolchain. + +- Build u-boot using hihope_rzg2_defconfig. + + Result: u-boot-elf.srec + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- + hihope_rzg2_defconfig + + make CROSS_COMPILE=aarch64-linux-gnu- + +- Build TF-A + + Result: bootparam_sa0.srec, cert_header_sa6.srec, bl2.srec, bl31.srec + +.. code:: bash + + make bl2 bl31 rzg LOG_LEVEL=40 PLAT=rzg LSI=G2M RCAR_DRAM_SPLIT=2\ + RCAR_LOSSY_ENABLE=1 SPD="none" MBEDTLS_DIR=$mbedtls + + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- Boot the board in Mini-monitor mode and enable access to the + QSPI flash. + + +- Use the flash_writer utility[2] to flash all the SREC files. + +[2] https://github.com/renesas-rz/rzg2_flash_writer + + +Boot trace +---------- +:: + + INFO: ARM GICv2 driver initialized + NOTICE: BL2: RZ/G2 Initial Program Loader(CA57) Rev.2.0.6 + NOTICE: BL2: PRR is RZ/G2M Ver.1.3 + NOTICE: BL2: Board is HiHope RZ/G2M Rev.4.0 + NOTICE: BL2: Boot device is QSPI Flash(40MHz) + NOTICE: BL2: LCM state is unknown + NOTICE: BL2: DDR3200(rev.0.40) + NOTICE: BL2: [COLD_BOOT] + NOTICE: BL2: DRAM Split is 2ch + NOTICE: BL2: QoS is default setting(rev.0.19) + NOTICE: BL2: DRAM refresh interval 1.95 usec + NOTICE: BL2: Periodic Write DQ Training + NOTICE: BL2: CH0: 400000000 - 47fffffff, 2 GiB + NOTICE: BL2: CH2: 600000000 - 67fffffff, 2 GiB + NOTICE: BL2: Lossy Decomp areas + NOTICE: Entry 0: DCMPAREACRAx:0x80000540 DCMPAREACRBx:0x570 + NOTICE: Entry 1: DCMPAREACRAx:0x40000000 DCMPAREACRBx:0x0 + NOTICE: Entry 2: DCMPAREACRAx:0x20000000 DCMPAREACRBx:0x0 + NOTICE: BL2: FDT at 0xe631db30 + NOTICE: BL2: v2.3(release):v2.4-rc0-2-g1433701e5 + NOTICE: BL2: Built : 13:45:26, Nov 7 2020 + NOTICE: BL2: Normal boot + INFO: BL2: Doing platform setup + INFO: BL2: Loading image id 3 + NOTICE: BL2: dst=0xe631d200 src=0x8180000 len=512(0x200) + NOTICE: BL2: dst=0x43f00000 src=0x8180400 len=6144(0x1800) + WARNING: r-car ignoring the BL31 size from certificate,using RCAR_TRUSTED_SRAM_SIZE instead + INFO: Loading image id=3 at address 0x44000000 + NOTICE: rcar_file_len: len: 0x0003e000 + NOTICE: BL2: dst=0x44000000 src=0x81c0000 len=253952(0x3e000) + INFO: Image id=3 loaded: 0x44000000 - 0x4403e000 + INFO: BL2: Loading image id 5 + INFO: Loading image id=5 at address 0x50000000 + NOTICE: rcar_file_len: len: 0x00100000 + NOTICE: BL2: dst=0x50000000 src=0x8300000 len=1048576(0x100000) + INFO: Image id=5 loaded: 0x50000000 - 0x50100000 + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0x44000000 + INFO: SPSR = 0x3cd + + + U-Boot 2021.01-rc1-00244-gac37e14fbd (Nov 04 2020 - 20:03:34 +0000) + + CPU: Renesas Electronics R8A774A1 rev 1.3 + Model: HopeRun HiHope RZ/G2M with sub board + DRAM: 3.9 GiB + MMC: mmc@ee100000: 0, mmc@ee160000: 1 + Loading Environment from MMC... OK + In: serial@e6e88000 + Out: serial@e6e88000 + Err: serial@e6e88000 + Net: eth0: ethernet@e6800000 + Hit any key to stop autoboot: 0 + => diff --git a/arm-trusted-firmware/docs/plat/socionext-uniphier.rst b/arm-trusted-firmware/docs/plat/socionext-uniphier.rst new file mode 100644 index 0000000..9288193 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/socionext-uniphier.rst @@ -0,0 +1,116 @@ +Socionext UniPhier +================== + +Socionext UniPhier Armv8-A SoCs use Trusted Firmware-A (TF-A) as the secure +world firmware, supporting BL2 and BL31. + +UniPhier SoC family implements its internal boot ROM, which loads 64KB [1]_ +image from a non-volatile storage to the on-chip SRAM, and jumps over to it. +TF-A provides a special mode, BL2-AT-EL3, which enables BL2 to execute at EL3. +It is useful for platforms with non-TF-A boot ROM, like UniPhier. Here, a +problem is BL2 does not fit in the 64KB limit if +:ref:`Trusted Board Boot (TBB) ` is enabled. +To solve this issue, Socionext provides a first stage loader called +`UniPhier BL`_. This loader runs in the on-chip SRAM, initializes the DRAM, +expands BL2 there, and hands the control over to it. Therefore, all images +of TF-A run in DRAM. + +The UniPhier platform works with/without TBB. See below for the build process +of each case. The image authentication for the UniPhier platform fully +complies with the Trusted Board Boot Requirements (TBBR) specification. + +The UniPhier BL does not implement the authentication functionality, that is, +it can not verify the BL2 image by itself. Instead, the UniPhier BL assures +the BL2 validity in a different way; BL2 is GZIP-compressed and appended to +the UniPhier BL. The concatenation of the UniPhier BL and the compressed BL2 +fits in the 64KB limit. The concatenated image is loaded by the internal boot +ROM (and verified if the chip fuses are blown). + + +Boot Flow +--------- + +1. The Boot ROM + + This is hard-wired ROM, so never corrupted. It loads the UniPhier BL (with + compressed-BL2 appended) into the on-chip SRAM. If the SoC fuses are blown, + the image is verified by the SoC's own method. + +2. UniPhier BL + + This runs in the on-chip SRAM. After the minimum SoC initialization and DRAM + setup, it decompresses the appended BL2 image into the DRAM, then jumps to + the BL2 entry. + +3. BL2 (at EL3) + + This runs in the DRAM. It extracts more images such as BL31, BL33 (optionally + SCP_BL2, BL32 as well) from Firmware Image Package (FIP). If TBB is enabled, + they are all authenticated by the standard mechanism of TF-A. + After loading all the images, it jumps to the BL31 entry. + +4. BL31, BL32, and BL33 + + They all run in the DRAM. See :ref:`Firmware Design` for details. + + +Basic Build +----------- + +BL2 must be compressed for the reason above. The UniPhier's platform makefile +provides a build target ``bl2_gzip`` for this. + +For a non-secure boot loader (aka BL33), U-Boot is well supported for UniPhier +SoCs. The U-Boot image (``u-boot.bin``) must be built in advance. For the build +procedure of U-Boot, refer to the document in the `U-Boot`_ project. + +To build minimum functionality for UniPhier (without TBB):: + + make CROSS_COMPILE= PLAT=uniphier BL33= bl2_gzip fip + +Output images: + +- ``bl2.bin.gz`` +- ``fip.bin`` + + +Optional features +----------------- + +- Trusted Board Boot + + `mbed TLS`_ is needed as the cryptographic and image parser modules. + Refer to the :ref:`Prerequisites` document for the appropriate version of + mbed TLS. + + To enable TBB, add the following options to the build command:: + + TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR= + +- System Control Processor (SCP) + + If desired, FIP can include an SCP BL2 image. If BL2 finds an SCP BL2 image + in FIP, BL2 loads it into DRAM and kicks the SCP. Most of UniPhier boards + still work without SCP, but SCP provides better power management support. + + To include SCP BL2, add the following option to the build command:: + + SCP_BL2= + +- BL32 (Secure Payload) + + To enable BL32, add the following options to the build command:: + + SPD= BL32= + + If you use TSP for BL32, ``BL32=`` is not required. Just add the + following:: + + SPD=tspd + + +.. [1] Some SoCs can load 80KB, but the software implementation must be aligned + to the lowest common denominator. +.. _UniPhier BL: https://github.com/uniphier/uniphier-bl +.. _U-Boot: https://www.denx.de/wiki/U-Boot +.. _mbed TLS: https://tls.mbed.org/ diff --git a/arm-trusted-firmware/docs/plat/stm32mp1.rst b/arm-trusted-firmware/docs/plat/stm32mp1.rst new file mode 100644 index 0000000..7ae98b1 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/stm32mp1.rst @@ -0,0 +1,305 @@ +STMicroelectronics STM32MP1 +=========================== + +STM32MP1 is a microprocessor designed by STMicroelectronics +based on Arm Cortex-A7. +It is an Armv7-A platform, using dedicated code from TF-A. +More information can be found on `STM32MP1 Series`_ page. + + +STM32MP1 Versions +----------------- + +There are 2 variants for STM32MP1: STM32MP13 and STM32MP15 + +STM32MP13 Versions +~~~~~~~~~~~~~~~~~~ +The STM32MP13 series is available in 3 different lines which are pin-to-pin compatible: + +- STM32MP131: Single Cortex-A7 core +- STM32MP133: STM32MP131 + 2*CAN, ETH2(GMAC), ADC1 +- STM32MP135: STM32MP133 + DCMIPP, LTDC + +Each line comes with a security option (cryptography & secure boot) and a Cortex-A frequency option: + +- A Cortex-A7 @ 650 MHz +- C Secure Boot + HW Crypto + Cortex-A7 @ 650 MHz +- D Cortex-A7 @ 900 MHz +- F Secure Boot + HW Crypto + Cortex-A7 @ 900 MHz + +STM32MP15 Versions +~~~~~~~~~~~~~~~~~~ +The STM32MP15 series is available in 3 different lines which are pin-to-pin compatible: + +- STM32MP157: Dual Cortex-A7 cores, Cortex-M4 core @ 209 MHz, 3D GPU, DSI display interface and CAN FD +- STM32MP153: Dual Cortex-A7 cores, Cortex-M4 core @ 209 MHz and CAN FD +- STM32MP151: Single Cortex-A7 core, Cortex-M4 core @ 209 MHz + +Each line comes with a security option (cryptography & secure boot) and a Cortex-A frequency option: + +- A Basic + Cortex-A7 @ 650 MHz +- C Secure Boot + HW Crypto + Cortex-A7 @ 650 MHz +- D Basic + Cortex-A7 @ 800 MHz +- F Secure Boot + HW Crypto + Cortex-A7 @ 800 MHz + +The `STM32MP1 part number codification`_ page gives more information about part numbers. + +Design +------ +The STM32MP1 resets in the ROM code of the Cortex-A7. +The primary boot core (core 0) executes the boot sequence while +secondary boot core (core 1) is kept in a holding pen loop. +The ROM code boot sequence loads the TF-A binary image from boot device +to embedded SRAM. + +The TF-A image must be properly formatted with a STM32 header structure +for ROM code is able to load this image. +Tool stm32image can be used to prepend this header to the generated TF-A binary. + +Boot with FIP +~~~~~~~~~~~~~ +The use of FIP is now the recommended way to boot STM32MP1 platform. +Only BL2 (with STM32 header) is loaded by ROM code. The other binaries are +inside the FIP binary: BL32 (SP_min or OP-TEE), U-Boot and their respective +device tree blobs. + +STM32IMAGE bootchain +~~~~~~~~~~~~~~~~~~~~ +Although still supported, this way of booting is not recommended. +Pease use FIP instead. +At compilation step, BL2, BL32 and DTB file are linked together in a single +binary. The stm32image tool is also generated and the header is added to TF-A +binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32. +It can then be copied in the first partition of the boot device. + + +Memory mapping +~~~~~~~~~~~~~~ + +:: + + 0x00000000 +-----------------+ + | | ROM + 0x00020000 +-----------------+ + | | + | ... | + | | + 0x2FFC0000 +-----------------+ \ + | BL32 DTB | | + 0x2FFC5000 +-----------------+ | + | BL32 | | + 0x2FFDF000 +-----------------+ | + | ... | | + 0x2FFE3000 +-----------------+ | + | BL2 DTB | | Embedded SRAM + 0x2FFEA000 +-----------------+ | + | BL2 | | + 0x2FFFF000 +-----------------+ | + | SCMI mailbox | | + 0x30000000 +-----------------+ / + | | + | ... | + | | + 0x40000000 +-----------------+ + | | + | | Devices + | | + 0xC0000000 +-----------------+ \ + | | | + 0xC0100000 +-----------------+ | + | BL33 | | Non-secure RAM (DDR) + | ... | | + | | | + 0xFFFFFFFF +-----------------+ / + + +Boot sequence +~~~~~~~~~~~~~ + +ROM code -> BL2 (compiled with BL2_AT_EL3) -> BL32 (SP_min) -> BL33 (U-Boot) + +or if Op-TEE is used: + +ROM code -> BL2 (compiled with BL2_AT_EL3) -> OP-TEE -> BL33 (U-Boot) + + +Build Instructions +------------------ +Boot media(s) supported by BL2 must be specified in the build command. +Available storage medias are: + +- ``STM32MP_SDMMC`` +- ``STM32MP_EMMC`` +- ``STM32MP_RAW_NAND`` +- ``STM32MP_SPI_NAND`` +- ``STM32MP_SPI_NOR`` + +Serial boot devices: + +- ``STM32MP_UART_PROGRAMMER`` +- ``STM32MP_USB_PROGRAMMER`` + + +Other configuration flags: + +- | ``DTB_FILE_NAME``: to precise board device-tree blob to be used. + | Default: stm32mp157c-ev1.dtb +- | ``STM32MP_EARLY_CONSOLE``: to enable early traces before clock driver is setup. + | Default: 0 (disabled) +- | ``STM32MP_UART_BAUDRATE``: to select UART baud rate. + | Default: 115200 +- | ``STM32_TF_VERSION``: to manage BL2 monotonic counter. + | Default: 0 +- | ``STM32MP13``: to select STM32MP13 variant configuration. + | Default: 0 +- | ``STM32MP15``: to select STM32MP15 variant configuration. + | Default: 1 + + +Boot with FIP +~~~~~~~~~~~~~ +You need to build BL2, BL32 (SP_min or OP-TEE) and BL33 (U-Boot) before building FIP binary. + +U-Boot +______ + +.. code:: bash + + cd + make stm32mp15_trusted_defconfig + make DEVICE_TREE=stm32mp157c-ev1 all + +OP-TEE (optional) +_________________ + +.. code:: bash + + cd + make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \ + CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts + + +TF-A BL32 (SP_min) +__________________ +If you choose not to use OP-TEE, you can use TF-A SP_min. +To build TF-A BL32, and its device tree file: + +.. code:: bash + + make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb bl32 dtbs + +TF-A BL2 +________ +To build TF-A BL2 with its STM32 header for SD-card boot: + +.. code:: bash + + make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + DTB_FILE_NAME=stm32mp157c-ev1.dtb STM32MP_SDMMC=1 + +For other boot devices, you have to replace STM32MP_SDMMC in the previous command +with the desired device flag. + +This BL2 is independent of the BL32 used (SP_min or OP-TEE) + + +FIP +___ +With BL32 SP_min: + +.. code:: bash + + make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=sp_min \ + DTB_FILE_NAME=stm32mp157c-ev1.dtb \ + BL33=/u-boot-nodtb.bin \ + BL33_CFG=/u-boot.dtb \ + fip + +With OP-TEE: + +.. code:: bash + + make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=optee \ + DTB_FILE_NAME=stm32mp157c-ev1.dtb \ + BL33=/u-boot-nodtb.bin \ + BL33_CFG=/u-boot.dtb \ + BL32=/tee-header_v2.bin \ + BL32_EXTRA1=/tee-pager_v2.bin + BL32_EXTRA2=/tee-pageable_v2.bin + fip + + +STM32IMAGE bootchain +~~~~~~~~~~~~~~~~~~~~ +You need to add the following flag to the make command: +``STM32MP_USE_STM32IMAGE=1`` + +To build with SP_min and support for SD-card boot: + +.. code:: bash + + make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=sp_min STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \ + STM32MP_USE_STM32IMAGE=1 + + cd + make stm32mp15_trusted_defconfig + make DEVICE_TREE=stm32mp157c-ev1 all + +To build TF-A with OP-TEE support for SD-card boot: + +.. code:: bash + + make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=optee STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \ + STM32MP_USE_STM32IMAGE=1 + + cd + make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \ + CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts + + cd + make stm32mp15_trusted_defconfig + make DEVICE_TREE=stm32mp157c-ev1 all + + +The following build options are supported: + +- ``ENABLE_STACK_PROTECTOR``: To enable the stack protection. + + +Populate SD-card +---------------- + +Boot with FIP +~~~~~~~~~~~~~ +The SD-card has to be formatted with GPT. +It should contain at least those partitions: + +- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary (BL2) +- fip: which contains the FIP binary + +Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl. + +STM32IMAGE bootchain +~~~~~~~~~~~~~~~~~~~~ +The SD-card has to be formatted with GPT. +It should contain at least those partitions: + +- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary +- ssbl: to copy the u-boot.stm32 binary + +Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl. + +OP-TEE artifacts go into separate partitions as follows: + +- teeh: tee-header_v2.stm32 +- teed: tee-pageable_v2.stm32 +- teex: tee-pager_v2.stm32 + + +.. _STM32MP1 Series: https://www.st.com/en/microcontrollers-microprocessors/stm32mp1-series.html +.. _STM32MP1 part number codification: https://wiki.st.com/stm32mpu/wiki/STM32MP15_microprocessor#Part_number_codification diff --git a/arm-trusted-firmware/docs/plat/synquacer.rst b/arm-trusted-firmware/docs/plat/synquacer.rst new file mode 100644 index 0000000..dd29d29 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/synquacer.rst @@ -0,0 +1,117 @@ +Socionext Synquacer +=================== + +Socionext's Synquacer SC2A11 is a multi-core processor with 24 cores of Arm +Cortex-A53. The Developerbox, of 96boards, is a platform that contains this +processor. This port of the Trusted Firmware only supports this platform at +the moment. + +More information are listed in `link`_. + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- edk2: + `link `__ + +- edk2-platforms: + `link `__ + +- edk2-non-osi: + `link `__ + +Boot Flow +~~~~~~~~~ + +SCP firmware --> TF-A BL31 --> UEFI(edk2) + +Build Procedure +~~~~~~~~~~~~~~~ + +- Firstly, in addition to the “normal†build tools you will also need a + few specialist tools. On a Debian or Ubuntu operating system try: + + .. code:: shell + + sudo apt install acpica-tools device-tree-compiler uuid-dev + +- Secondly, create a new working directory and store the absolute path to this + directory in an environment variable, WORKSPACE. It does not matter where + this directory is created but as an example: + + .. code:: shell + + export WORKSPACE=$HOME/build/developerbox-firmware + mkdir -p $WORKSPACE + +- Run the following commands to clone the source code: + + .. code:: shell + + cd $WORKSPACE + git clone https://github.com/ARM-software/arm-trusted-firmware -b master + git clone https://github.com/tianocore/edk2.git -b master + git clone https://github.com/tianocore/edk2-platforms.git -b master + git clone https://github.com/tianocore/edk2-non-osi.git -b master + +- Build ATF: + + .. code:: shell + + cd $WORKSPACE/arm-trusted-firmware + make -j`nproc` PLAT=synquacer PRELOADED_BL33_BASE=0x8200000 bl31 fiptool + tools/fiptool/fiptool create \ + --tb-fw ./build/synquacer/release/bl31.bin \ + --soc-fw ./build/synquacer/release/bl31.bin \ + --scp-fw ./build/synquacer/release/bl31.bin \ + ../edk2-non-osi/Platform/Socionext/DeveloperBox/fip_all_arm_tf.bin + +- Build EDK2: + + .. code:: shell + + cd $WORKSPACE + export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms:$WORKSPACE/edk2-non-osi + export ACTIVE_PLATFORM="Platform/Socionext/DeveloperBox/DeveloperBox.dsc" + export GCC5_AARCH64_PREFIX=aarch64-linux-gnu- + unset ARCH + + . edk2/edksetup.sh + make -C edk2/BaseTools + + build -p $ACTIVE_PLATFORM -b RELEASE -a AARCH64 -t GCC5 -n `nproc` -D DO_X86EMU=TRUE + +- The firmware image, which comprises the option ROM, ARM trusted firmware and + EDK2 itself, can be found $WORKSPACE/../Build/DeveloperBox/RELEASE_GCC5/FV/. + Use SYNQUACERFIRMWAREUPDATECAPSULEFMPPKCS7.Cap for UEFI capsule update and + SPI_NOR_IMAGE.fd for the serial flasher. + + Note #1: -t GCC5 can be loosely translated as “enable link-time-optimizationâ€; + any version of gcc >= 5 will support this feature and may be used to build EDK2. + + Note #2: Replace -b RELEASE with -b DEBUG to build a debug. + +Install the System Firmware +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Providing your Developerbox is fully working and has on operating system + installed then you can adopt your the newly compiled system firmware using + the capsule update method:. + + .. code:: shell + + sudo apt install fwupdate + sudo fwupdate --apply {50b94ce5-8b63-4849-8af4-ea479356f0e3} \ + SYNQUACERFIRMWAREUPDATECAPSULEFMPPKCS7.Cap + sudo reboot + +- Alternatively you can install SPI_NOR_IMAGE.fd using the `board recovery method`_. + +.. _link: https://www.96boards.org/product/developerbox/ +.. _board recovery method: https://www.96boards.org/documentation/enterprise/developerbox/installation/board-recovery.md.html diff --git a/arm-trusted-firmware/docs/plat/ti-k3.rst b/arm-trusted-firmware/docs/plat/ti-k3.rst new file mode 100644 index 0000000..4843227 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/ti-k3.rst @@ -0,0 +1,57 @@ +Texas Instruments K3 +==================== + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Texas Instruments K3 SoCs. + +Boot Flow +--------- + +:: + + R5(U-Boot) --> TF-A BL31 --> BL32(OP-TEE) --> TF-A BL31 --> BL33(U-Boot) --> Linux + \ + Optional direct to Linux boot + \ + --> BL33(Linux) + +Texas Instruments K3 SoCs contain an R5 processor used as the boot master, it +loads the needed images for A53 startup, because of this we do not need BL1 or +BL2 TF-A stages. + +Build Instructions +------------------ + +https://github.com/ARM-software/arm-trusted-firmware.git + +TF-A: + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=k3 SPD=opteed all + +OP-TEE: + +.. code:: shell + + make ARCH=arm CROSS_COMPILE64=aarch64-linux-gnu- PLATFORM=k3 CFG_ARM64_core=y all + +R5 U-Boot: + +.. code:: shell + + make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- am65x_evm_r5_defconfig + make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- SYSFW= + +A53 U-Boot: + +.. code:: shell + + make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- am65x_evm_a53_defconfig + make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- ATF= TEE= + +Deploy Images +------------- + +.. code:: shell + + cp tiboot3.bin tispl.bin u-boot.img /sdcard/boot/ diff --git a/arm-trusted-firmware/docs/plat/warp7.rst b/arm-trusted-firmware/docs/plat/warp7.rst new file mode 100644 index 0000000..f98a76f --- /dev/null +++ b/arm-trusted-firmware/docs/plat/warp7.rst @@ -0,0 +1,210 @@ +NXP i.MX7 WaRP7 +=============== + +The Trusted Firmware-A port for the i.MX7Solo WaRP7 implements BL2 at EL3. +The i.MX7S contains a BootROM with a High Assurance Boot (HAB) functionality. +This functionality provides a mechanism for establishing a root-of-trust from +the reset vector to the command-line in user-space. + +Boot Flow +--------- + +BootROM --> TF-A BL2 --> BL32(OP-TEE) --> BL33(U-Boot) --> Linux + +In the WaRP7 port we encapsulate OP-TEE, DTB and U-Boot into a FIP. This FIP is +expected and required + +Build Instructions +------------------ + +We need to use a file generated by u-boot in order to generate a .imx image the +BootROM will boot. It is therefore _required_ to build u-boot before TF-A and +furthermore it is _recommended_ to use the mkimage in the u-boot/tools directory +to generate the TF-A .imx image. + +U-Boot +~~~~~~ + +https://git.linaro.org/landing-teams/working/mbl/u-boot.git + +.. code:: shell + + git checkout -b rms-atf-optee-uboot linaro-mbl/rms-atf-optee-uboot + make warp7_bl33_defconfig; + make u-boot.imx arch=ARM CROSS_COMPILE=arm-linux-gnueabihf- + +OP-TEE +~~~~~~ + +https://github.com/OP-TEE/optee_os.git + +.. code:: shell + + make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- PLATFORM=imx PLATFORM_FLAVOR=mx7swarp7 ARCH=arm CFG_PAGEABLE_ADDR=0 CFG_DT_ADDR=0x83000000 CFG_NS_ENTRY_ADDR=0x87800000 + +TF-A +~~~~ + +https://github.com/ARM-software/arm-trusted-firmware.git + +The following commands assume that a directory exits in the top-level TFA build +directory "fiptool_images". "fiptool_images" contains + +- u-boot.bin + The binary output from the u-boot instructions above + +- tee-header_v2.bin +- tee-pager_v2.bin +- tee-pageable_v2.bin + Binary outputs from the previous OPTEE build steps + +It is also assumed copy of mbedtls is available on the path path ../mbedtls + https://github.com/ARMmbed/mbedtls.git + At the time of writing HEAD points to 0592ea772aee48ca1e6d9eb84eca8e143033d973 + +.. code:: shell + + mkdir fiptool_images + cp /path/to/optee/out/arm-plat-imx/core/tee-header_v2.bin fiptool_images + cp /path/to/optee/out/arm-plat-imx/core/tee-pager_v2.bin fiptool_images + cp /path/to/optee/out/arm-plat-imx/core/tee-pageable_v2.bin fiptool_images + + make CROSS_COMPILE=${CROSS_COMPILE} PLAT=warp7 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + ARM_CORTEX_A7=yes AARCH32_SP=optee PLAT_WARP7_UART=1 GENERATE_COT=1 \ + TRUSTED_BOARD_BOOT=1 USE_TBBR_DEFS=1 MBEDTLS_DIR=../mbedtls \ + NEED_BL32=yes BL32=fiptool_images/tee-header_v2.bin \ + BL32_EXTRA1=fiptool_images/tee-pager_v2.bin \ + BL32_EXTRA2=fiptool_images/tee-pageable_v2.bin \ + BL33=fiptool_images/u-boot.bin certificates all + + /path/to/u-boot/tools/mkimage -n /path/to/u-boot/u-boot.cfgout -T imximage -e 0x9df00000 -d ./build/warp7/debug/bl2.bin ./build/warp7/debug/bl2.bin.imx + +FIP +~~~ + +.. code:: shell + + cp /path/to/uboot/u-boot.bin fiptool_images + cp /path/to/linux/arch/boot/dts/imx7s-warp.dtb fiptool_images + + tools/cert_create/cert_create -n --rot-key "build/warp7/debug/rot_key.pem" \ + --tfw-nvctr 0 \ + --ntfw-nvctr 0 \ + --trusted-key-cert fiptool_images/trusted-key-cert.key-crt \ + --tb-fw=build/warp7/debug/bl2.bin \ + --tb-fw-cert fiptool_images/trusted-boot-fw.key-crt\ + --tos-fw fiptool_images/tee-header_v2.bin \ + --tos-fw-cert fiptool_images/tee-header_v2.bin.crt \ + --tos-fw-key-cert fiptool_images/tee-header_v2.bin.key-crt \ + --tos-fw-extra1 fiptool_images/tee-pager_v2.bin \ + --tos-fw-extra2 fiptool_images/tee-pageable_v2.bin \ + --nt-fw fiptool_images/u-boot.bin \ + --nt-fw-cert fiptool_images/u-boot.bin.crt \ + --nt-fw-key-cert fiptool_images/u-boot.bin.key-crt \ + --hw-config fiptool_images/imx7s-warp.dtb + + tools/fiptool/fiptool create --tos-fw fiptool_images/tee-header_v2.bin \ + --tos-fw-extra1 fiptool_images/tee-pager_v2.bin \ + --tos-fw-extra2 fiptool_images/tee-pageable_v2.bin \ + --nt-fw fiptool_images/u-boot.bin \ + --hw-config fiptool_images/imx7s-warp.dtb \ + --tos-fw-cert fiptool_images/tee-header_v2.bin.crt \ + --tos-fw-key-cert fiptool_images/tee-header_v2.bin.key-crt \ + --nt-fw-cert fiptool_images/u-boot.bin.crt \ + --nt-fw-key-cert fiptool_images/u-boot.bin.key-crt \ + --trusted-key-cert fiptool_images/trusted-key-cert.key-crt \ + --tb-fw-cert fiptool_images/trusted-boot-fw.key-crt warp7.fip + +Deploy Images +------------- + +First place the WaRP7 into UMS mode in u-boot this should produce an entry in +/dev like /dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0\:0 + +.. code:: shell + + => ums 0 mmc 0 + +Next flash bl2.imx and warp7.fip + +bl2.imx is flashed @ 1024 bytes +warp7.fip is flash @ 1048576 bytes + +.. code:: shell + + sudo dd if=bl2.bin.imx of=/dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0\:0 bs=512 seek=2 conv=notrunc + # Offset is 1MB 1048576 => 1048576 / 512 = 2048 + sudo dd if=./warp7.fip of=/dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0\:0 bs=512 seek=2048 conv=notrunc + +Remember to umount the USB device pefore proceeding + +.. code:: shell + + sudo umount /dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0\:0* + + +Signing BL2 +----------- + +A further step is to sign BL2. + +The image_sign.sh and bl2_sign.csf files alluded to blow are available here. + +https://github.com/bryanodonoghue/atf-code-signing + +It is suggested you use this script plus the example CSF file in order to avoid +hard-coding data into your CSF files. + +Download both "image_sign.sh" and "bl2_sign.csf" to your +arm-trusted-firmware top-level directory. + +.. code:: shell + + #!/bin/bash + SIGN=image_sign.sh + TEMP=`pwd`/temp + BL2_CSF=bl2_sign.csf + BL2_IMX=bl2.bin.imx + CST_PATH=/path/to/cst-2.3.2 + CST_BIN=${CST_PATH}/linux64/cst + + #Remove temp + rm -rf ${TEMP} + mkdir ${TEMP} + + # Generate IMX header + /path/to/u-boot/tools/mkimage -n u-boot.cfgout.warp7 -T imximage -e 0x9df00000 -d ./build/warp7/debug/bl2.bin ./build/warp7/debug/bl2.bin.imx > ${TEMP}/${BL2_IMX}.log + + # Copy required items to $TEMP + cp build/warp7/debug/bl2.bin.imx ${TEMP} + cp ${CST_PATH}/keys/* ${TEMP} + cp ${CST_PATH}/crts/* ${TEMP} + cp ${BL2_CSF} ${TEMP} + + # Generate signed BL2 image + ./${SIGN} image_sign_mbl_binary ${TEMP} ${BL2_CSF} ${BL2_IMX} ${CST_BIN} + + # Copy signed BL2 to top-level directory + cp ${TEMP}/${BL2_IMX}-signed . + cp ${BL2_RECOVER_CSF} ${TEMP} + + +The resulting bl2.bin.imx-signed can replace bl2.bin.imx in the Deploy +Images section above, once done. + +Suggested flow for verifying. + +1. Followed all previous steps above and verify a non-secure ATF boot +2. Down the NXP Code Singing Tool +3. Generate keys +4. Program the fuses on your board +5. Replace bl2.bin.imx with bl2.bin.imx-signed +6. Verify inside u-boot that "hab_status" shows no events +7. Subsequently close your board. + +If you have HAB events @ step 6 - do not lock your board. + +To get a good over-view of generating keys and programming the fuses on the +board read "High Assurance Boot for Dummies" by Boundary Devices. + +https://boundarydevices.com/high-assurance-boot-hab-dummies/ diff --git a/arm-trusted-firmware/docs/plat/xilinx-versal.rst b/arm-trusted-firmware/docs/plat/xilinx-versal.rst new file mode 100644 index 0000000..d65b048 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/xilinx-versal.rst @@ -0,0 +1,53 @@ +Xilinx Versal +============= + +Trusted Firmware-A implements the EL3 firmware layer for Xilinx Versal. +The platform only uses the runtime part of TF-A as Xilinx Versal already has a +BootROM (BL1) and PMC FW (BL2). + +BL31 is TF-A. +BL32 is an optional Secure Payload. +BL33 is the non-secure world software (U-Boot, Linux etc). + +To build: +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 +``` + +To build ATF for different platform (supported are "silicon"(default) and "versal_virt") +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal VERSAL_PLATFORM=versal_virt bl31 +``` + +To build TF-A for JTAG DCC console +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 VERSAL_CONSOLE=dcc +``` + +To build TF-A with Straight-Line Speculation(SLS) +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 HARDEN_SLS_ALL=1 +``` + +Xilinx Versal platform specific build options +--------------------------------------------- + +* `VERSAL_ATF_MEM_BASE`: Specifies the base address of the bl31 binary. +* `VERSAL_ATF_MEM_SIZE`: Specifies the size of the memory region of the bl31 binary. +* `VERSAL_BL32_MEM_BASE`: Specifies the base address of the bl32 binary. +* `VERSAL_BL32_MEM_SIZE`: Specifies the size of the memory region of the bl32 binary. + +* `VERSAL_CONSOLE`: Select the console driver. Options: + - `pl011`, `pl011_0`: ARM pl011 UART 0 + - `pl011_1` : ARM pl011 UART 1 + +* `VERSAL_PLATFORM`: Select the platform. Options: + - `versal_virt` : Versal Virtual platform + +# PLM->TF-A Parameter Passing +------------------------------ +The PLM populates a data structure with image information for the TF-A. The TF-A +uses that data to hand off to the loaded images. The address of the handoff +data structure is passed in the ```PMC_GLOBAL_GLOB_GEN_STORAGE4``` register. +The register is free to be used by other software once the TF-A is bringing up +further firmware images. diff --git a/arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst b/arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst new file mode 100644 index 0000000..79c2535 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst @@ -0,0 +1,73 @@ +Xilinx Zynq UltraScale+ MPSoC +============================= + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Xilinx Zynq +UltraScale + MPSoC. +The platform only uses the runtime part of TF-A as ZynqMP already has a +BootROM (BL1) and FSBL (BL2). + +BL31 is TF-A. +BL32 is an optional Secure Payload. +BL33 is the non-secure world software (U-Boot, Linux etc). + +To build: + +.. code:: bash + + make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp bl31 + +To build bl32 TSP you have to rebuild bl31 too: + +.. code:: bash + + make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp SPD=tspd bl31 bl32 + +To build TF-A for JTAG DCC console: + +.. code:: bash + + make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp RESET_TO_BL31=1 bl31 ZYNQMP_CONSOLE=dcc + +ZynqMP platform specific build options +-------------------------------------- + +- ``ZYNQMP_ATF_MEM_BASE``: Specifies the base address of the bl31 binary. +- ``ZYNQMP_ATF_MEM_SIZE``: Specifies the size of the memory region of the bl31 binary. +- ``ZYNQMP_BL32_MEM_BASE``: Specifies the base address of the bl32 binary. +- ``ZYNQMP_BL32_MEM_SIZE``: Specifies the size of the memory region of the bl32 binary. + +- ``ZYNQMP_CONSOLE``: Select the console driver. Options: + + - ``cadence``, ``cadence0``: Cadence UART 0 + - ``cadence1`` : Cadence UART 1 + +FSBL->TF-A Parameter Passing +---------------------------- + +The FSBL populates a data structure with image information for TF-A. TF-A uses +that data to hand off to the loaded images. The address of the handoff data +structure is passed in the ``PMU_GLOBAL.GLOBAL_GEN_STORAGE6`` register. The +register is free to be used by other software once TF-A has brought up +further firmware images. + +Power Domain Tree +----------------- + +The following power domain tree represents the power domain model used by TF-A +for ZynqMP: + +:: + + +-+ + |0| + +-+ + +-------+---+---+-------+ + | | | | + | | | | + v v v v + +-+ +-+ +-+ +-+ + |0| |1| |2| |3| + +-+ +-+ +-+ +-+ + +The 4 leaf power domains represent the individual A53 cores, while resources +common to the cluster are grouped in the power domain on the top. diff --git a/arm-trusted-firmware/docs/process/code-review-guidelines.rst b/arm-trusted-firmware/docs/process/code-review-guidelines.rst new file mode 100644 index 0000000..67a211f --- /dev/null +++ b/arm-trusted-firmware/docs/process/code-review-guidelines.rst @@ -0,0 +1,216 @@ +Code Review Guidelines +====================== + +This document provides TF-A specific details about the project's code review +process. It should be read in conjunction with the `Project Maintenance +Process`_, which it supplements. + + +Why do we do code reviews? +-------------------------- + +The main goal of code reviews is to improve the code quality. By reviewing each +other's code, we can help catch issues that were missed by the author +before they are integrated in the source tree. Different people bring different +perspectives, depending on their past work, experiences and their current use +cases of TF-A in their products. + +Code reviews also play a key role in sharing knowledge within the +community. People with more expertise in one area of the code base can +help those that are less familiar with it. + +Code reviews are meant to benefit everyone through team work. It is not about +unfairly criticizing or belittling the work of any contributor. + + +Good practices +-------------- + +To ensure the code review gives the greatest possible benefit, participants in +the project should: + +- Be considerate of other people and their needs. Participants may be working + to different timescales, and have different priorities. Keep this in + mind - be gracious while waiting for action from others, and timely in your + actions when others are waiting for you. + +- Review other people's patches where possible. The more active reviewers there + are, the more quickly new patches can be reviewed and merged. Contributing to + code review helps everyone in the long run, as it creates a culture of + participation which serves everyone's interests. + + +Guidelines for patch contributors +--------------------------------- + +In addition to the rules outlined in the :ref:`Contributor's Guide`, as a patch +contributor you are expected to: + +- Answer all comments from people who took the time to review your + patches. + +- Be patient and resilient. It is quite common for patches to go through + several rounds of reviews and rework before they get approved, especially + for larger features. + + In the event that a code review takes longer than you would hope for, you + may try the following actions to speed it up: + + - Ping the reviewers on Gerrit or on the mailing list. If it is urgent, + explain why. Please remain courteous and do not abuse this. + + - If one code owner has become unresponsive, ask the other code owners for + help progressing the patch. + + - If there is only one code owner and they have become unresponsive, ask one + of the project maintainers for help. + +- Do the right thing for the project, not the fastest thing to get code merged. + + For example, if some existing piece of code - say a driver - does not quite + meet your exact needs, go the extra mile and extend the code with the missing + functionality you require - as opposed to copying the code into some other + directory to have the freedom to change it in any way. This way, your changes + benefit everyone and will be maintained over time. + + +Guidelines for all reviewers +---------------------------- + +There are no good or bad review comments. If you have any doubt about a patch or +need some clarifications, it's better to ask rather than letting a potential +issue slip. Examples of review comments could be: + +- Questions ("Why do you need to do this?", "What if X happens?") +- Bugs ("I think you need a logical \|\| rather than a bitwise \|.") +- Design issues ("This won't scale well when we introduce feature X.") +- Improvements ("Would it be better if we did Y instead?") + + +Guidelines for code owners +-------------------------- + +Code owners are listed on the :ref:`Project Maintenance` page, +along with the module(s) they look after. + +When reviewing a patch, code owners are expected to check the following: + +- The patch looks good from a technical point of view. For example: + + - The structure of the code is clear. + + - It complies with the relevant standards or technical documentation (where + applicable). + + - It leverages existing interfaces rather than introducing new ones + unnecessarily. + + - It fits well in the design of the module. + + - It adheres to the security model of the project. In particular, it does not + increase the attack surface (e.g. new SMCs) without justification. + +- The patch adheres to the TF-A :ref:`Coding Style`. The CI system should help + catch coding style violations. + +- (Only applicable to generic code) The code is MISRA-compliant (see + :ref:`misra-compliance`). The CI system should help catch violations. + +- Documentation is provided/updated (where applicable). + +- The patch has had an appropriate level of testing. Testing details are + expected to be provided by the patch author. If they are not, do not hesitate + to request this information. + +- All CI automated tests pass. + +If a code owner is happy with a patch, they should give their approval +through the ``Code-Owner-Review+1`` label in Gerrit. If instead, they have +concerns, questions, or any other type of blocking comment, they should set +``Code-Owner-Review-1``. + +Code owners are expected to behave professionally and responsibly. Here are some +guidelines for them: + +- Once you are engaged in a review, make sure you stay involved until the patch + is merged. Rejecting a patch and going away is not very helpful. You are + expected to monitor the patch author's answers to your review comments, + answer back if needed and review new revisions of their patch. + +- Provide constructive feedback. Just saying, "This is wrong, you should do X + instead." is usually not very helpful. The patch author is unlikely to + understand why you are requesting this change and might feel personally + attacked. + +- Be mindful when reviewing a patch. As a code owner, you are viewed as + the expert for the relevant module. By approving a patch, you are partially + responsible for its quality and the effects it has for all TF-A users. Make + sure you fully understand what the implications of a patch might be. + + +Guidelines for maintainers +-------------------------- + +Maintainers are listed on the :ref:`Project Maintenance` page. + +When reviewing a patch, maintainers are expected to check the following: + +- The general structure of the patch looks good. This covers things like: + + - Code organization. + + - Files and directories, names and locations. + + For example, platform code should be added under the ``plat/`` directory. + + - Naming conventions. + + For example, platform identifiers should be properly namespaced to avoid + name clashes with generic code. + + - API design. + +- Interaction of the patch with other modules in the code base. + +- The patch aims at complying with any standard or technical documentation + that applies. + +- New files must have the correct license and copyright headers. See :ref:`this + paragraph` for more information. The CI system + should help catch files with incorrect or no copyright/license headers. + +- There is no third party code or binary blobs with potential IP concerns. + Maintainers should look for copyright or license notices in code, and use + their best judgement. If they are unsure about a patch, they should ask + other maintainers for help. + +- Generally speaking, new driver code should be placed in the generic + layer. There are cases where a driver has to stay into the platform layer but + this should be the exception, rather than the rule. + +- Existing common drivers (in particular for Arm IPs like the GIC driver) should + not be copied into the platform layer to cater for platform quirks. This + type of code duplication hurts the maintainability of the project. The + duplicate driver is less likely to benefit from bug fixes and future + enhancements. In most cases, it is possible to rework a generic driver to + make it more flexible and fit slightly different use cases. That way, these + enhancements benefit everyone. + +- When a platform specific driver really is required, the burden lies with the + patch author to prove the need for it. A detailed justification should be + posted via the commit message or on the mailing list. + +- Before merging a patch, verify that all review comments have been addressed. + If this is not the case, encourage the patch author and the relevant + reviewers to resolve these together. + +If a maintainer is happy with a patch, they should give their approval +through the ``Maintainer-Review+1`` label in Gerrit. If instead, they have +concerns, questions, or any other type of blocking comment, they should set +``Maintainer-Review-1``. + +-------------- + +*Copyright (c) 2020, Arm Limited. All rights reserved.* + +.. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/ diff --git a/arm-trusted-firmware/docs/process/coding-guidelines.rst b/arm-trusted-firmware/docs/process/coding-guidelines.rst new file mode 100644 index 0000000..ef319e4 --- /dev/null +++ b/arm-trusted-firmware/docs/process/coding-guidelines.rst @@ -0,0 +1,474 @@ +Coding Guidelines +================= + +This document provides some additional guidelines to consider when writing +|TF-A| code. These are not intended to be strictly-enforced rules like the +contents of the :ref:`Coding Style`. + +Automatic Editor Configuration +------------------------------ + +Many of the rules given below (such as indentation size, use of tabs, and +newlines) can be set automatically using the `EditorConfig`_ configuration file +in the root of the repository: ``.editorconfig``. With a supported editor, the +rules set out in this file can be automatically applied when you are editing +files in the |TF-A| repository. + +Several editors include built-in support for EditorConfig files, and many others +support its functionality through plugins. + +Use of the EditorConfig file is suggested but is not required. + +.. _automatic-compliance-checking: + +Automatic Compliance Checking +----------------------------- + +To assist with coding style compliance, the project Makefile contains two +targets which both utilise the `checkpatch.pl` script that ships with the Linux +source tree. The project also defines certain *checkpatch* options in the +``.checkpatch.conf`` file in the top-level directory. + +.. note:: + Checkpatch errors will gate upstream merging of pull requests. + Checkpatch warnings will not gate merging but should be reviewed and fixed if + possible. + +To check the entire source tree, you must first download copies of +``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available +in the `Linux master tree`_ *scripts* directory, then set the ``CHECKPATCH`` +environment variable to point to ``checkpatch.pl`` (with the other 2 files in +the same directory) and build the `checkcodebase` target: + +.. code:: shell + + make CHECKPATCH=/linux/scripts/checkpatch.pl checkcodebase + +To just check the style on the files that differ between your local branch and +the remote master, use: + +.. code:: shell + + make CHECKPATCH=/linux/scripts/checkpatch.pl checkpatch + +If you wish to check your patch against something other than the remote master, +set the ``BASE_COMMIT`` variable to your desired branch. By default, +``BASE_COMMIT`` is set to ``origin/master``. + +Ignored Checkpatch Warnings +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some checkpatch warnings in the TF codebase are deliberately ignored. These +include: + +- ``**WARNING: line over 80 characters**``: Although the codebase should + generally conform to the 80 character limit this is overly restrictive in some + cases. + +- ``**WARNING: Use of volatile is usually wrong``: see + `Why the “volatile†type class should not be used`_ . Although this document + contains some very useful information, there are several legimate uses of the + volatile keyword within the TF codebase. + +Performance considerations +-------------------------- + +Avoid printf and use logging macros +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``) +which wrap ``tf_log`` and which allow the logging call to be compiled-out +depending on the ``make`` command. Use these macros to avoid print statements +being compiled unconditionally into the binary. + +Each logging macro has a numerical log level: + +.. code:: c + + #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 + +By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will +be compiled into debug builds and all statements with a log level +``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be +overridden from the command line or by the platform makefile (although it may be +necessary to clean the build directory first). + +For example, to enable ``VERBOSE`` logging on FVP: + +.. code:: shell + + make PLAT=fvp LOG_LEVEL=50 all + +Use const data where possible +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, the following code: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + + void init(struct my_struct *ptr); + + void main(void) + { + struct my_struct x; + x.arg1 = 1; + x.arg2 = 2; + init(&x); + } + +is better written as: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + + void init(const struct my_struct *ptr); + + void main(void) + { + const struct my_struct x = { 1, 2 }; + init(&x); + } + +This allows the linker to put the data in a read-only data section instead of a +writeable data section, which may result in a smaller and faster binary. Note +that this may require dependent functions (``init()`` in the above example) to +have ``const`` arguments, assuming they don't need to modify the data. + +Libc functions that are banned or to be used with caution +--------------------------------------------------------- + +Below is a list of functions that present security risks and either must not be +used (Banned) or are discouraged from use and must be used with care (Caution). + ++------------------------+-----------+--------------------------------------+ +| libc function | Status | Comments | ++========================+===========+======================================+ +| ``strcpy, wcscpy``, | Banned | use strlcpy instead | +| ``strncpy`` | | | ++------------------------+-----------+--------------------------------------+ +| ``strcat, wcscat``, | Banned | use strlcat instead | +| ``strncat`` | | | ++------------------------+-----------+--------------------------------------+ +| ``sprintf, vsprintf`` | Banned | use snprintf, vsnprintf | +| | | instead | ++------------------------+-----------+--------------------------------------+ +| ``snprintf`` | Caution | ensure result fits in buffer | +| | | i.e : snprintf(buf,size...) < size | ++------------------------+-----------+--------------------------------------+ +| ``vsnprintf`` | Caution | inspect va_list match types | +| | | specified in format string | ++------------------------+-----------+--------------------------------------+ +| ``strtok`` | Banned | use strtok_r or strsep instead | ++------------------------+-----------+--------------------------------------+ +| ``strtok_r, strsep`` | Caution | inspect for terminated input buffer | ++------------------------+-----------+--------------------------------------+ +| ``ato*`` | Banned | use equivalent strto* functions | ++------------------------+-----------+--------------------------------------+ +| ``*toa`` | Banned | Use snprintf instead | ++------------------------+-----------+--------------------------------------+ + +The `libc` component in the codebase will not add support for the banned APIs. + +Error handling and robustness +----------------------------- + +Using CASSERT to check for compile time data errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Where possible, use the ``CASSERT`` macro to check the validity of data known at +compile time instead of checking validity at runtime, to avoid unnecessary +runtime code. + +For example, this can be used to check that the assembler's and compiler's views +of the size of an array is the same. + +.. code:: c + + #include + + define MY_STRUCT_SIZE 8 /* Used by assembler source files */ + + struct my_struct { + uint32_t arg1; + uint32_t arg2; + }; + + CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch); + + +If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would +emit an error like this: + +:: + + my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative + + +Using assert() to check for programming errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be +treated as a tightly integrated package; the image builder should be aware of +and responsible for all functionality within the image, even if code within that +image is provided by multiple entities. This allows us to be more aggressive in +interpreting invalid state or bad function arguments as programming errors using +``assert()``, including arguments passed across platform porting interfaces. +This is in contrast to code in a Linux environment, which is less tightly +integrated and may attempt to be more defensive by passing the error back up the +call stack. + +Where possible, badly written TF code should fail early using ``assert()``. This +helps reduce the amount of untested conditional code. By default these +statements are not compiled into release builds, although this can be overridden +using the ``ENABLE_ASSERTIONS`` build flag. + +Examples: + +- Bad argument supplied to library function +- Bad argument provided by platform porting function +- Internal secure world image state is inconsistent + + +Handling integration errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Each secure world image may be provided by a different entity (for example, a +Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32 +image and the OEM/SoC vendor may provide the other images). + +An image may contain bugs that are only visible when the images are integrated. +The system integrator may not even have access to the debug variants of all the +images in order to check if asserts are firing. For example, the release variant +of BL1 may have already been burnt into the SoC. Therefore, TF code that detects +an integration error should _not_ consider this a programming error, and should +always take action, even in release builds. + +If an integration error is considered non-critical it should be treated as a +recoverable error. If the error is considered critical it should be treated as +an unexpected unrecoverable error. + +Handling recoverable errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **must not** crash when supplied with bad data from an external +source. For example, data from the normal world or a hardware device. Similarly, +the secure world **must not** crash if it detects a non-critical problem within +itself or the system. It must make every effort to recover from the problem by +emitting a ``WARN`` message, performing any necessary error handling and +continuing. + +Examples: + +- Secure world receives SMC from normal world with bad arguments. +- Secure world receives SMC from normal world at an unexpected time. +- BL31 receives SMC from BL32 with bad arguments. +- BL31 receives SMC from BL32 at unexpected time. +- Secure world receives recoverable error from hardware device. Retrying the + operation may help here. +- Non-critical secure world service is not functioning correctly. +- BL31 SPD discovers minor configuration problem with corresponding SP. + +Handling unrecoverable errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In some cases it may not be possible for the secure world to recover from an +error. This situation should be handled in one of the following ways: + +1. If the unrecoverable error is unexpected then emit an ``ERROR`` message and + call ``panic()``. This will end up calling the platform-specific function + ``plat_panic_handler()``. +2. If the unrecoverable error is expected to occur in certain circumstances, + then emit an ``ERROR`` message and call the platform-specific function + ``plat_error_handler()``. + +Cases 1 and 2 are subtly different. A platform may implement +``plat_panic_handler`` and ``plat_error_handler`` in the same way (for example, +by waiting for a secure watchdog to time-out or by invoking an interface on the +platform's power controller to reset the platform). However, +``plat_error_handler`` may take additional action for some errors (for example, +it may set a flag so the platform resets into a different mode). Also, +``plat_panic_handler()`` may implement additional debug functionality (for +example, invoking a hardware breakpoint). + +Examples of unexpected unrecoverable errors: + +- BL32 receives an unexpected SMC response from BL31 that it is unable to + recover from. +- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding + Trusted OS, which is critical for platform operation. +- Secure world discovers that a critical hardware device is an unexpected and + unrecoverable state. +- Secure world receives an unexpected and unrecoverable error from a critical + hardware device. +- Secure world discovers that it is running on unsupported hardware. + +Examples of expected unrecoverable errors: + +- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk. +- BL1/BL2 fails to authenticate the next image due to an invalid certificate. +- Secure world continuously receives recoverable errors from a hardware device + but is unable to proceed without a valid response. + +Handling critical unresponsiveness +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the secure world is waiting for a response from an external source (for +example, the normal world or a hardware device) which is critical for continued +operation, it must not wait indefinitely. It must have a mechanism (for example, +a secure watchdog) for resetting itself and/or the external source to prevent +the system from executing in this state indefinitely. + +Examples: + +- BL1 is waiting for the normal world to raise an SMC to proceed to the next + stage of the secure firmware update process. +- A Trusted OS is waiting for a response from a proxy in the normal world that + is critical for continued operation. +- Secure world is waiting for a hardware response that is critical for continued + operation. + +Use of built-in *C* and *libc* data types +----------------------------------------- + +The |TF-A| codebase should be kept as portable as possible, especially since +both 64-bit and 32-bit platforms are supported. To help with this, the following +data type usage guidelines should be followed: + +- Where possible, use the built-in *C* data types for variable storage (for + example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99* + types. Most code is typically only concerned with the minimum size of the + data stored, which the built-in *C* types guarantee. + +- Avoid using the exact-size standard *C99* types in general (for example, + ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the + compiler from making optimizations. There are legitimate uses for them, + for example to represent data of a known structure. When using them in struct + definitions, consider how padding in the struct will work across architectures. + For example, extra padding may be introduced in |AArch32| systems if a struct + member crosses a 32-bit boundary. + +- Use ``int`` as the default integer type - it's likely to be the fastest on all + systems. Also this can be assumed to be 32-bit as a consequence of the + `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call + Standard for the Arm 64-bit Architecture`_ . + +- Avoid use of ``short`` as this may end up being slower than ``int`` in some + systems. If a variable must be exactly 16-bit, use ``int16_t`` or + ``uint16_t``. + +- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given + that `int` is 32-bit on Arm platforms, there is no use for it. For integers of + at least 64-bit, use ``long long``. + +- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data. + +- Use ``unsigned`` for integers that can never be negative (counts, + indices, sizes, etc). TF intends to comply with MISRA "essential type" coding + rules (10.X), where signed and unsigned types are considered different + essential types. Choosing the correct type will aid this. MISRA static + analysers will pick up any implicit signed/unsigned conversions that may lead + to unexpected behaviour. + +- For pointer types: + + - If an argument in a function declaration is pointing to a known type then + simply use a pointer to that type (for example: ``struct my_struct *``). + + - If a variable (including an argument in a function declaration) is pointing + to a general, memory-mapped address, an array of pointers or another + structure that is likely to require pointer arithmetic then use + ``uintptr_t``. This will reduce the amount of casting required in the code. + Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it + may work but is less portable. + + - For other pointer arguments in a function declaration, use ``void *``. This + includes pointers to types that are abstracted away from the known API and + pointers to arbitrary data. This allows the calling function to pass a + pointer argument to the function without any explicit casting (the cast to + ``void *`` is implicit). The function implementation can then do the + appropriate casting to a specific type. + + - Avoid pointer arithmetic generally (as this violates MISRA C 2012 rule + 18.4) and especially on void pointers (as this is only supported via + language extensions and is considered non-standard). In TF-A, setting the + ``W`` build flag to ``W=3`` enables the *-Wpointer-arith* compiler flag and + this will emit warnings where pointer arithmetic is used. + + - Use ``ptrdiff_t`` to compare the difference between 2 pointers. + +- Use ``size_t`` when storing the ``sizeof()`` something. + +- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that + can also return an error code; the signed type allows for a negative return + code in case of error. This practice should be used sparingly. + +- Use ``u_register_t`` when it's important to store the contents of a register + in its native size (32-bit in |AArch32| and 64-bit in |AArch64|). This is not a + standard *C99* type but is widely available in libc implementations, + including the FreeBSD version included with the TF codebase. Where possible, + cast the variable to a more appropriate type before interpreting the data. For + example, the following struct in ``ep_info.h`` could use this type to minimize + the storage required for the set of registers: + +.. code:: c + + typedef struct aapcs64_params { + u_register_t arg0; + u_register_t arg1; + u_register_t arg2; + u_register_t arg3; + u_register_t arg4; + u_register_t arg5; + u_register_t arg6; + u_register_t arg7; + } aapcs64_params_t; + +If some code wants to operate on ``arg0`` and knows that it represents a 32-bit +unsigned integer on all systems, cast it to ``unsigned int``. + +These guidelines should be updated if additional types are needed. + +Favor C language over assembly language +--------------------------------------- + +Generally, prefer code written in C over assembly. Assembly code is less +portable, harder to understand, maintain and audit security wise. Also, static +analysis tools generally don't analyze assembly code. + +There are, however, legitimate uses of assembly language. These include: + + - Early boot code executed before the C runtime environment is setup. + + - Exception handling code. + + - Low-level code where the exact sequence of instructions executed on the CPU + matters, such as CPU reset sequences. + + - Low-level code where specific system-level instructions must be used, such + as cache maintenance operations. + +-------------- + +*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.* + +.. _`Linux master tree`: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/ +.. _`Procedure Call Standard for the Arm Architecture`: https://developer.arm.com/docs/ihi0042/latest/ +.. _`Procedure Call Standard for the Arm 64-bit Architecture`: https://developer.arm.com/docs/ihi0055/latest/ +.. _`EditorConfig`: http://editorconfig.org/ +.. _`Why the “volatile†type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html +.. _`MISRA C:2012 Guidelines`: https://www.misra.org.uk/Activities/MISRAC/tabid/160/Default.aspx +.. _`a spreadsheet`: https://developer.trustedfirmware.org/file/download/lamajxif3w7c4mpjeoo5/PHID-FILE-fp7c7acszn6vliqomyhn/MISRA-and-TF-Analysis-v1.3.ods diff --git a/arm-trusted-firmware/docs/process/coding-style.rst b/arm-trusted-firmware/docs/process/coding-style.rst new file mode 100644 index 0000000..be13b14 --- /dev/null +++ b/arm-trusted-firmware/docs/process/coding-style.rst @@ -0,0 +1,470 @@ +Coding Style +============ + +The following sections outline the |TF-A| coding style for *C* code. The style +is based on the `Linux kernel coding style`_, with a few modifications. + +The style should not be considered *set in stone*. Feel free to provide feedback +and suggestions. + +.. note:: + You will almost certainly find code in the |TF-A| repository that does not + follow the style. The intent is for all code to do so eventually. + +File Encoding +------------- + +The source code must use the **UTF-8** character encoding. Comments and +documentation may use non-ASCII characters when required (e.g. Greek letters +used for units) but code itself is still limited to ASCII characters. + +Newlines must be in **Unix** style, which means that only the Line Feed (``LF``) +character is used to break a line and reset to the first column. + +Language +-------- + +The primary language for comments and naming must be International English. In +cases where there is a conflict between the American English and British English +spellings of a word, the American English spelling is used. + +Exceptions are made when referring directly to something that does not use +international style, such as the name of a company. In these cases the existing +name should be used as-is. + +C Language Standard +------------------- + +The C language mode used for TF-A is *GNU99*. This is the "GNU dialect of ISO +C99", which implies the *ISO C99* standard with GNU extensions. + +Both GCC and Clang compiler toolchains have support for *GNU99* mode, though +Clang does lack support for a small number of GNU extensions. These +missing extensions are rarely used, however, and should not pose a problem. + +.. _misra-compliance: + +MISRA Compliance +---------------- + +TF-A attempts to comply with the `MISRA C:2012 Guidelines`_. Coverity +Static Analysis is used to regularly generate a report of current MISRA defects +and to prevent the addition of new ones. + +It is not possible for the project to follow all MISRA guidelines. We maintain +`a spreadsheet`_ that lists all rules and directives and whether we aim to +comply with them or not. A rationale is given for each deviation. + +.. note:: + Enforcing a rule does not mean that the codebase is free of defects + of that rule, only that they would ideally be removed. + +.. note:: + Third-party libraries are not considered in our MISRA analysis and we do not + intend to modify them to make them MISRA compliant. + +Indentation +----------- + +Use **tabs** for indentation. The use of spaces for indentation is forbidden +except in the case where a term is being indented to a boundary that cannot be +achieved using tabs alone. + +Tab spacing should be set to **8 characters**. + +Trailing whitespace is not allowed and must be trimmed. + +Spacing +------- + +Single spacing should be used around most operators, including: + +- Arithmetic operators (``+``, ``-``, ``/``, ``*``) +- Assignment operators (``=``, ``+=``, etc) +- Boolean operators (``&&``, ``||``) +- Comparison operators (``<``, ``>``, ``==``, etc) + +A space should also be used to separate parentheses and braces when they are not +already separated by a newline, such as for the ``if`` statement in the +following example: + +.. code:: c + + int function_foo(bool bar) + { + if (bar) { + function_baz(); + } + } + +Note that there is no space between the name of a function and the following +parentheses. + +Control statements (``if``, ``for``, ``switch``, ``while``, etc) must be +separated from the following open parenthesis by a single space. The previous +example illustrates this for an ``if`` statement. + +Line Length +----------- + +Line length *should* be at most **80 characters**. This limit does not include +non-printing characters such as the line feed. + +This rule is a *should*, not a must, and it is acceptable to exceed the limit +**slightly** where the readability of the code would otherwise be significantly +reduced. Use your judgement in these cases. + +Blank Lines +----------- + +Functions are usually separated by a single blank line. In certain cases it is +acceptable to use additional blank lines for clarity, if required. + +The file must end with a single newline character. Many editors have the option +to insert this automatically and to trim multiple blank lines at the end of the +file. + +Braces +------ + +Opening Brace Placement +^^^^^^^^^^^^^^^^^^^^^^^ + +Braces follow the **Kernighan and Ritchie (K&R)** style, where the opening brace +is **not** placed on a new line. + +Example for a ``while`` loop: + +.. code:: c + + while (condition) { + foo(); + bar(); + } + +This style applies to all blocks except for functions which, following the Linux +style, **do** place the opening brace on a new line. + +Example for a function: + +.. code:: c + + int my_function(void) + { + int a; + + a = 1; + return a; + } + +Conditional Statement Bodies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Where conditional statements (such as ``if``, ``for``, ``while`` and ``do``) are +used, braces must be placed around the statements that form the body of the +conditional. This is the case regardless of the number of statements in the +body. + +.. note:: + This is a notable departure from the Linux coding style that has been + adopted to follow MISRA guidelines more closely and to help prevent errors. + +For example, use the following style: + +.. code:: c + + if (condition) { + foo++; + } + +instead of omitting the optional braces around a single statement: + +.. code:: c + + /* This is violating MISRA C 2012: Rule 15.6 */ + if (condition) + foo++; + +The reason for this is to prevent accidental changes to control flow when +modifying the body of the conditional. For example, at a quick glance it is easy +to think that the value of ``bar`` is only incremented if ``condition`` +evaluates to ``true`` but this is not the case - ``bar`` will always be +incremented regardless of the condition evaluation. If the developer forgets to +add braces around the conditional body when adding the ``bar++;`` statement then +the program execution will not proceed as intended. + +.. code:: c + + /* This is violating MISRA C 2012: Rule 15.6 */ + if (condition) + foo++; + bar++; + +Naming +------ + +Functions +^^^^^^^^^ + +Use lowercase for function names, separating multiple words with an underscore +character (``_``). This is sometimes referred to as *Snake Case*. An example is +given below: + +.. code:: c + + void bl2_arch_setup(void) + { + ... + } + +Local Variables and Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Local variables and function parameters use the same format as function names: +lowercase with underscore separation between multiple words. An example is +given below: + +.. code:: c + + static void set_scr_el3_from_rm(uint32_t type, + uint32_t interrupt_type_flags, + uint32_t security_state) + { + uint32_t flag, bit_pos; + + ... + + } + +Preprocessor Macros +^^^^^^^^^^^^^^^^^^^ + +Identifiers that are defined using preprocessor macros are written in all +uppercase text. + +.. code:: c + + #define BUFFER_SIZE_BYTES 64 + +Function Attributes +------------------- + +Place any function attributes after the function type and before the function +name. + +.. code:: c + + void __init plat_arm_interconnect_init(void); + +Alignment +--------- + +Alignment should be performed primarily with tabs, adding spaces if required to +achieve a granularity that is smaller than the tab size. For example, with a tab +size of eight columns it would be necessary to use one tab character and two +spaces to indent text by ten columns. + +Switch Statement Alignment +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When using ``switch`` statements, align each ``case`` statement with the +``switch`` so that they are in the same column. + +.. code:: c + + switch (condition) { + case A: + foo(); + case B: + bar(); + default: + baz(); + } + +Pointer Alignment +^^^^^^^^^^^^^^^^^ + +The reference and dereference operators (ampersand and *pointer star*) must be +aligned with the name of the object on which they are operating, as opposed to +the type of the object. + +.. code:: c + + uint8_t *foo; + + foo = &bar; + + +Comments +-------- + +The general rule for comments is that the double-slash style of comment (``//``) +is not allowed. Examples of the allowed comment formats are shown below: + +.. code:: c + + /* + * This example illustrates the first allowed style for multi-line comments. + * + * Blank lines within multi-lines are allowed when they add clarity or when + * they separate multiple contexts. + * + */ + +.. code:: c + + /************************************************************************** + * This is the second allowed style for multi-line comments. + * + * In this style, the first and last lines use asterisks that run the full + * width of the comment at its widest point. + * + * This style can be used for additional emphasis. + * + *************************************************************************/ + +.. code:: c + + /* Single line comments can use this format */ + +.. code:: c + + /*************************************************************************** + * This alternative single-line comment style can also be used for emphasis. + **************************************************************************/ + +Headers and inclusion +--------------------- + +Header guards +^^^^^^^^^^^^^ + +For a header file called "some_driver.h" the style used by |TF-A| is: + +.. code:: c + + #ifndef SOME_DRIVER_H + #define SOME_DRIVER_H + +
+ + #endif /* SOME_DRIVER_H */ + +Include statement ordering +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All header files that are included by a source file must use the following, +grouped ordering. This is to improve readability (by making it easier to quickly +read through the list of headers) and maintainability. + +#. *System* includes: Header files from the standard *C* library, such as + ``stddef.h`` and ``string.h``. + +#. *Project* includes: Header files under the ``include/`` directory within + |TF-A| are *project* includes. + +#. *Platform* includes: Header files relating to a single, specific platform, + and which are located under the ``plat/`` directory within + |TF-A|, are *platform* includes. + +Within each group, ``#include`` statements must be in alphabetical order, +taking both the file and directory names into account. + +Groups must be separated by a single blank line for clarity. + +The example below illustrates the ordering rules using some contrived header +file names; this type of name reuse should be otherwise avoided. + +.. code:: c + + #include + + #include + #include + #include + #include + + #include "a_header.h" + +Include statement variants +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Two variants of the ``#include`` directive are acceptable in the |TF-A| +codebase. Correct use of the two styles improves readability by suggesting the +location of the included header and reducing ambiguity in cases where generic +and platform-specific headers share a name. + +For header files that are in the same directory as the source file that is +including them, use the ``"..."`` variant. + +For header files that are **not** in the same directory as the source file that +is including them, use the ``<...>`` variant. + +Example (bl1_fwu.c): + +.. code:: c + + #include + #include + #include + + #include "bl1_private.h" + +Typedefs +-------- + +Avoid anonymous typedefs of structs/enums in headers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, the following definition: + +.. code:: c + + typedef struct { + int arg1; + int arg2; + } my_struct_t; + + +is better written as: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + +This allows function declarations in other header files that depend on the +struct/enum to forward declare the struct/enum instead of including the +entire header: + +.. code:: c + + struct my_struct; + void my_func(struct my_struct *arg); + +instead of: + +.. code:: c + + #include + void my_func(my_struct_t *arg); + +Some TF definitions use both a struct/enum name **and** a typedef name. This +is discouraged for new definitions as it makes it difficult for TF to comply +with MISRA rule 8.3, which states that "All declarations of an object or +function shall use the same names and type qualifiers". + +The Linux coding standards also discourage new typedefs and checkpatch emits +a warning for this. + +Existing typedefs will be retained for compatibility. + +-------------- + +*Copyright (c) 2020, Arm Limited. All rights reserved.* + +.. _`Linux kernel coding style`: https://www.kernel.org/doc/html/latest/process/coding-style.html +.. _`MISRA C:2012 Guidelines`: https://www.misra.org.uk/Activities/MISRAC/tabid/160/Default.aspx +.. _`a spreadsheet`: https://developer.trustedfirmware.org/file/download/lamajxif3w7c4mpjeoo5/PHID-FILE-fp7c7acszn6vliqomyhn/MISRA-and-TF-Analysis-v1.3.ods diff --git a/arm-trusted-firmware/docs/process/commit-style.rst b/arm-trusted-firmware/docs/process/commit-style.rst new file mode 100644 index 0000000..de899ab --- /dev/null +++ b/arm-trusted-firmware/docs/process/commit-style.rst @@ -0,0 +1,162 @@ +Commit Style +============ + +When writing commit messages, please think carefully about the purpose and scope +of the change you are making: describe briefly what the change does, and +describe in detail why it does it. This helps to ensure that changes to the +code-base are transparent and approachable to reviewers, and it allows us to +keep a more accurate changelog. You may use Markdown in commit messages. + +A good commit message provides all the background information needed for +reviewers to understand the intent and rationale of the patch. This information +is also useful for future reference. + +For example: + +- What does the patch do? +- What motivated it? +- What impact does it have? +- How was it tested? +- Have alternatives been considered? Why did you choose this approach over + another one? +- If it fixes an `issue`_, include a reference. + +|TF-A| follows the `Conventional Commits`_ specification. All commits to the +main repository are expected to adhere to these guidelines, so it is +**strongly** recommended that you read at least the `quick summary`_ of the +specification. + +To briefly summarize, commit messages are expected to be of the form: + +.. code:: + + [optional scope]: + + [optional body] + + [optional footer(s)] + +The following example commit message demonstrates the use of the +``refactor`` type and the ``amu`` scope: + +.. code:: + + refactor(amu): factor out register accesses + + This change introduces a small set of register getters and setters to + avoid having to repeatedly mask and shift in complex code. + + Change-Id: Ia372f60c5efb924cd6eeceb75112e635ad13d942 + Signed-off-by: Chris Kay + +The following `types` are permissible and are strictly enforced: + ++--------------+---------------------------------------------------------------+ +| Scope | Description | ++==============+===============================================================+ +| ``feat`` | A new feature | ++--------------+---------------------------------------------------------------+ +| ``fix`` | A bug fix | ++--------------+---------------------------------------------------------------+ +| ``build`` | Changes that affect the build system or external dependencies | ++--------------+---------------------------------------------------------------+ +| ``ci`` | Changes to our CI configuration files and scripts | ++--------------+---------------------------------------------------------------+ +| ``docs`` | Documentation-only changes | ++--------------+---------------------------------------------------------------+ +| ``perf`` | A code change that improves performance | ++--------------+---------------------------------------------------------------+ +| ``refactor`` | A code change that neither fixes a bug nor adds a feature | ++--------------+---------------------------------------------------------------+ +| ``revert`` | Changes that revert a previous change | ++--------------+---------------------------------------------------------------+ +| ``style`` | Changes that do not affect the meaning of the code | +| | (white-space, formatting, missing semi-colons, etc.) | ++--------------+---------------------------------------------------------------+ +| ``test`` | Adding missing tests or correcting existing tests | ++--------------+---------------------------------------------------------------+ +| ``chore`` | Any other change | ++--------------+---------------------------------------------------------------+ + +The permissible `scopes` are more flexible, and we maintain a list of them in +our :download:`changelog configuration file <../../changelog.yaml>`. Scopes in +this file are organized by their changelog section, where each changelog section +has a single scope that is considered to be blessed, and possibly several +deprecated scopes. Please avoid using deprecated scopes. + +While we don't enforce scopes strictly, we do ask that commits use these if they +can, or add their own if no appropriate one exists (see :ref:`Adding Scopes`). + +It's highly recommended that you use the tooling installed by the optional steps +in the :ref:`prerequisites ` guide to validate commit messages +locally, as commitlint reports a live list of the acceptable scopes. + +.. _Adding Scopes: + +Adding Scopes +------------- + +Scopes that are either a) unblessed in the configuration file, or b) do not +exist in the configuration file at all are considered to be deprecated. If you +are adding a new component that does not yet have a designated scope, please +feel free to add one. + +For example, if you are adding or making modifications to `Foo`'s latest and +greatest new platform `Bar`, you would add it to the `Platforms` changelog +section, and the hierarchy should look something like this: + +.. code:: json + + { + "sections": [ + { + "title": "Platforms", + "sections": [ + { + "title": "Foo", + "scopes": ["foo"], + "sections": [ + { + "title": "Bar", + "scopes": ["bar"] + } + ] + } + ] + } + ] + } + +When creating new scopes, try to keep them short and succinct, and use kebab +case (``this-is-kebab-case``). Components with a product name (i.e. most +platforms and some drivers) should use that name (e.g. ``gic600ae``, +``flexspi``, ``stpmic1``), otherwise use a name that uniquely represents the +component (e.g. ``marvell-comphy-3700``, ``rcar3-drivers``, ``a3720-uart``). + +Mandated Trailers +----------------- + +Commits are expected to be signed off with the ``Signed-off-by:`` trailer using +your real name and email address. You can do this automatically by committing +with Git's ``-s`` flag. + +There may be multiple ``Signed-off-by:`` lines depending on the history of the +patch, but one **must** be the committer. More details may be found in the +`Gerrit Signed-off-by Lines guidelines`_. + +Ensure that each commit also has a unique ``Change-Id:`` line. If you have +followed optional steps in the prerequisites to either install the Node.js tools +or clone the repository using the "`Clone with commit-msg hook`" clone method, +then this should be done automatically for you. + +More details may be found in the `Gerrit Change-Ids documentation`_. + +-------------- + +*Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.* + +.. _Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0 +.. _Gerrit Change-Ids documentation: https://review.trustedfirmware.org/Documentation/user-changeid.html +.. _Gerrit Signed-off-by Lines guidelines: https://review.trustedfirmware.org/Documentation/user-signedoffby.html +.. _issue: https://developer.trustedfirmware.org/project/board/1/ +.. _quick summary: https://www.conventionalcommits.org/en/v1.0.0/#summary diff --git a/arm-trusted-firmware/docs/process/contributing.rst b/arm-trusted-firmware/docs/process/contributing.rst new file mode 100644 index 0000000..f80389d --- /dev/null +++ b/arm-trusted-firmware/docs/process/contributing.rst @@ -0,0 +1,304 @@ +Contributor's Guide +******************* + +Getting Started +=============== + +- Make sure you have a Github account and you are logged on both + `developer.trustedfirmware.org`_ and `review.trustedfirmware.org`_. + +- If you plan to contribute a major piece of work, it is usually a good idea to + start a discussion around it on the mailing list. This gives everyone + visibility of what is coming up, you might learn that somebody else is + already working on something similar or the community might be able to + provide some early input to help shaping the design of the feature. + + If you intend to include Third Party IP in your contribution, please mention + it explicitly in the email thread and ensure that the changes that include + Third Party IP are made in a separate patch (or patch series). + +- Clone `Trusted Firmware-A`_ on your own machine as described in + :ref:`prerequisites_get_source`. + +- Create a local topic branch based on the `Trusted Firmware-A`_ ``master`` + branch. + +Making Changes +============== + +- Ensure commits adhere to the the project's :ref:`Commit Style`. + +- Make commits of logical units. See these general `Git guidelines`_ for + contributing to a project. + +- Keep the commits on topic. If you need to fix another bug or make another + enhancement, please address it on a separate topic branch. + +- Split the patch in manageable units. Small patches are usually easier to + review so this will speed up the review process. + +- Avoid long commit series. If you do have a long series, consider whether + some commits should be squashed together or addressed in a separate topic. + +- Follow the :ref:`Coding Style` and :ref:`Coding Guidelines`. + + - Use the checkpatch.pl script provided with the Linux source tree. A + Makefile target is provided for convenience, see :ref:`this + section` for more details. + +- Where appropriate, please update the documentation. + + - Consider whether the :ref:`Porting Guide`, :ref:`Firmware Design` document + or other in-source documentation needs updating. + + - If you are submitting new files that you intend to be the code owner for + (for example, a new platform port), then also update the + :ref:`code owners` file. + + - For topics with multiple commits, you should make all documentation changes + (and nothing else) in the last commit of the series. Otherwise, include + the documentation changes within the single commit. + +.. _copyright-license-guidance: + +- Ensure that each changed file has the correct copyright and license + information. Files that entirely consist of contributions to this project + should have a copyright notice and BSD-3-Clause SPDX license identifier of + the form as shown in :ref:`license`. Files that contain changes to imported + Third Party IP files should retain their original copyright and license + notices. + + For significant contributions you may add your own copyright notice in the + following format: + + :: + + Portions copyright (c) [XXXX-]YYYY, . All rights reserved. + + where XXXX is the year of first contribution (if different to YYYY) and YYYY + is the year of most recent contribution. is your name or your company + name. + +- Ensure that each patch in the patch series compiles in all supported + configurations. Patches which do not compile will not be merged. + +- Please test your changes. As a minimum, ensure that Linux boots on the + Foundation FVP. See :ref:`Arm Fixed Virtual Platforms (FVP)` for more + information. For more extensive testing, consider running the `TF-A Tests`_ + against your patches. + +- Ensure that all CI automated tests pass. Failures should be fixed. They might + block a patch, depending on how critical they are. + +Submitting Changes +================== + +- Submit your changes for review at https://review.trustedfirmware.org + targeting the ``integration`` branch. + +- Add reviewers for your patch: + + - At least one code owner for each module modified by the patch. See the list + of modules and their :ref:`code owners`. + + - At least one maintainer. See the list of :ref:`maintainers`. + + - If some module has no code owner, try to identify a suitable (non-code + owner) reviewer. Running ``git blame`` on the module's source code can + help, as it shows who has been working the most recently on this area of + the code. + + Alternatively, if it is impractical to identify such a reviewer, you might + send an email to the `TF-A mailing list`_ to broadcast your review request + to the community. + + Note that self-reviewing a patch is prohibited, even if the patch author is + the only code owner of a module modified by the patch. Getting a second pair + of eyes on the code is essential to keep up with the quality standards the + project aspires to. + +- The changes will then undergo further review by the designated people. Any + review comments will be made directly on your patch. This may require you to + do some rework. For controversial changes, the discussion might be moved to + the `TF-A mailing list`_ to involve more of the community. + + Refer to the `Gerrit Uploading Changes documentation`_ for more details. + +- The patch submission rules are the following. For a patch to be approved + and merged in the tree, it must get: + + - One ``Code-Owner-Review+1`` for each of the modules modified by the patch. + - A ``Maintainer-Review+1``. + + In the case where a code owner could not be found for a given module, + ``Code-Owner-Review+1`` is substituted by ``Code-Review+1``. + + In addition to these various code review labels, the patch must also get a + ``Verified+1``. This is usually set by the Continuous Integration (CI) bot + when all automated tests passed on the patch. Sometimes, some of these + automated tests may fail for reasons unrelated to the patch. In this case, + the maintainers might (after analysis of the failures) override the CI bot + score to certify that the patch has been correctly tested. + + In the event where the CI system lacks proper tests for a patch, the patch + author or a reviewer might agree to perform additional manual tests + in their review and the reviewer incorporates the review of the additional + testing in the ``Code-Review+1`` or ``Code-Owner-Review+1`` as applicable to + attest that the patch works as expected. Where possible additional tests should + be added to the CI system as a follow up task. For example, for a + platform-dependent patch where the said platform is not available in the CI + system's board farm. + +- When the changes are accepted, the :ref:`maintainers` will integrate them. + + - Typically, the :ref:`maintainers` will merge the changes into the + ``integration`` branch. + + - If the changes are not based on a sufficiently-recent commit, or if they + cannot be automatically rebased, then the :ref:`maintainers` may rebase it + on the ``integration`` branch or ask you to do so. + + - After final integration testing, the changes will make their way into the + ``master`` branch. If a problem is found during integration, the + :ref:`maintainers` will request your help to solve the issue. They may + revert your patches and ask you to resubmit a reworked version of them or + they may ask you to provide a fix-up patch. + +Add CI Configurations +===================== + +- TF-A uses Jenkins tool for Continuous Integration and testing activities. + Various CI Jobs are deployed which run tests on every patch before being + merged. So each of your patches go through a series of checks before they + get merged on to the master branch. Kindly ensure, that everytime you add + new files under your platform, they are covered under the following two sections: + +Coverity Scan +------------- + +- ``Coverity Scan analysis`` is one of the tests we perform on our source code + at regular intervals. We maintain a build script ``tf-cov-make`` which contains the + build configurations of various platforms in order to cover the entire source + code being analysed by Coverity. + +- When you submit your patches for review containing new source files, please + ensure to include them for the ``Coverity Scan analysis`` by adding the + respective build configurations in the ``tf-cov-make`` build script. + +- In this section you find the details on how to append your new build + configurations for Coverity scan analysis illustrated with examples: + +#. We maintain a separate repository named `tf-a-ci-scripts repository`_ + for placing all the test scripts which will be executed by the CI Jobs. + +#. In this repository, ``tf-cov-make`` script is located at + ``tf-a-ci-scripts/script/tf-coverity/tf-cov-make`` + +#. Edit `tf-cov-make`_ script by appending all the possible build configurations with + the specific ``build-flags`` relevant to your platform, so that newly added + source files get built and analysed by Coverity. + +#. For better understanding follow the below specified examples listed in the + ``tf-cov-make`` script. + +.. code:: shell + + Example 1: + #Intel + make PLAT=stratix10 $(common_flags) all + make PLAT=agilex $(common_flags) all + +- In the above example there are two different SoCs ``stratix`` and ``agilex`` + under the Intel platform and the build configurations has been added suitably + to include most of their source files. + +.. code:: shell + + Example 2: + #Hikey + make PLAT=hikey $(common_flags) ${TBB_OPTIONS} ENABLE_PMF=1 all + make PLAT=hikey960 $(common_flags) ${TBB_OPTIONS} all + make PLAT=poplar $(common_flags) all + +- In this case for ``Hikey`` boards additional ``build-flags`` has been included + along with the ``commom_flags`` to cover most of the files relevant to it. + +- Similar to this you can still find many other different build configurations + of various other platforms listed in the ``tf-cov-make`` script. Kindly refer + them and append your build configurations respectively. + +Test Build Configuration (``tf-l1-build-plat``) +----------------------------------------------- + +- Coverity Scan analysis, runs on a daily basis and will not be triggered for + every individual trusted-firmware patch. + +- Considering this, we have other distinguished CI jobs which run a set of test + configurations on every patch, before they are being passed to ``Coverity scan analysis``. + +- ``tf-l1-build-plat`` is the test group, which holds the test configurations + to build all the platforms. So be kind enough to verify that your newly added + files are built as part of one of the existing platform configurations present + in ``tf-l1-build-plat`` test group. + +- In this section you find the details on how to add the appropriate files, + needed to build your newly introduced platform as part of ``tf-l1-build-plat`` + test group, illustrated with an example: + +- Lets consider ``Hikey`` platform: + In the `tf-a-ci-scripts repository`_ we need to add a build configuration file ``hikey-default`` + under tf_config folder, ``tf_config/hikey-default`` listing all the build parameters + relevant to it. + +.. code:: shell + + #Hikey Build Parameters + CROSS_COMPILE=aarch64-none-elf- + PLAT=hikey + +- Further a test-configuration file ``hikey-default:nil`` need to be added under the + test group, ``tf-l1-build-plat`` located at ``tf-a-ci-scripts/group/tf-l1-build-plat``, + to allow the platform to be built as part of this group. + +.. code:: shell + + # + # Copyright (c) 2019-2022 Arm Limited. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # + +- As illustrated above, you need to add the similar files supporting your platform. + +Binary Components +================= + +- Platforms may depend on binary components submitted to the `Trusted Firmware + binary repository`_ if they require code that the contributor is unable or + unwilling to open-source. This should be used as a rare exception. +- All binary components must follow the contribution guidelines (in particular + licensing rules) outlined in the `readme.rst `_ file of + the binary repository. +- Binary components must be restricted to only the specific functionality that + cannot be open-sourced and must be linked into a larger open-source platform + port. The majority of the platform port must still be implemented in open + source. Platform ports that are merely a thin wrapper around a binary + component that contains all the actual code will not be accepted. +- Only platform port code (i.e. in the ``plat/`` directory) may rely on + binary components. Generic code must always be fully open-source. + +-------------- + +*Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.* + +.. _developer.trustedfirmware.org: https://developer.trustedfirmware.org +.. _review.trustedfirmware.org: https://review.trustedfirmware.org +.. _Trusted Firmware-A: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git +.. _Git guidelines: http://git-scm.com/book/ch5-2.html +.. _Gerrit Uploading Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html +.. _TF-A Tests: https://trustedfirmware-a-tests.readthedocs.io +.. _Trusted Firmware binary repository: https://review.trustedfirmware.org/admin/repos/tf-binaries +.. _tf-binaries-readme: https://git.trustedfirmware.org/tf-binaries.git/tree/readme.rst +.. _TF-A mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a +.. _tf-a-ci-scripts repository: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/ +.. _tf-cov-make: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/tree/script/tf-coverity/tf-cov-make diff --git a/arm-trusted-firmware/docs/process/faq.rst b/arm-trusted-firmware/docs/process/faq.rst new file mode 100644 index 0000000..daab198 --- /dev/null +++ b/arm-trusted-firmware/docs/process/faq.rst @@ -0,0 +1,80 @@ +Frequently-Asked Questions (FAQ) +================================ + +How do I update my changes? +--------------------------- + +Often it is necessary to update your patch set before it is merged. Refer to the +`Gerrit Upload Patch Set documentation`_ on how to do so. + +If you need to modify an existing patch set with multiple commits, refer to the +`Gerrit Replace Changes documentation`_. + +How long will my changes take to merge into ``integration``? +------------------------------------------------------------ + +This can vary a lot, depending on: + +* How important the patch set is considered by the TF maintainers. Where + possible, you should indicate the required timescales for merging the patch + set and the impact of any delay. Feel free to add a comment to your patch set + to get an estimate of when it will be merged. + +* The quality of the patch set. Patches are likely to be merged more quickly if + they follow the coding guidelines, have already had some code review, and have + been appropriately tested. + +* The impact of the patch set. For example, a patch that changes a key generic + API is likely to receive much greater scrutiny than a local change to a + specific platform port. + +* How much opportunity for external review is required. For example, the TF + maintainers may not wait for external review comments to merge trivial + bug-fixes but may wait up to a week to merge major changes, or ones requiring + feedback from specific parties. + +* How many other patch sets are waiting to be integrated and the risk of + conflict between the topics. + +* If there is a code freeze in place in preparation for the release. Please + refer the :ref:`Release Processes` document for more details. + +* The workload of the TF maintainers. + +How long will it take for my changes to go from ``integration`` to ``master``? +------------------------------------------------------------------------------ + +This depends on how many concurrent patches are being processed at the same +time. In simple cases where all potential regressions have already been tested, +the delay will be less than 1 day. If the TF maintainers are trying to merge +several things over the course of a few days, it might take up to a week. +Typically, it will be 1-2 days. + +The worst case is if the TF maintainers are trying to make a release while also +receiving patches that will not be merged into the release. In this case, the +patches will be merged onto ``integration``, which will temporarily diverge from +the release branch. The ``integration`` branch will be rebased onto ``master`` +after the release, and then ``master`` will be fast-forwarded to ``integration`` +1-2 days later. This whole process could take up 4 weeks. Please refer to the +:ref:`Release Processes` document for code freeze dates. The TF maintainers +will inform the patch owner if this is going to happen. + +It is OK to create a patch based on commits that are only available in +``integration`` or another patch set, rather than ``master``. There is a risk +that the dependency commits will change (for example due to patch set rework or +integration problems). If this happens, the dependent patch will need reworking. + +What are these strange comments in my changes? +---------------------------------------------- + +All the comments from ``ci-bot-user`` are associated with Continuous Integration +infrastructure. The links published on the comment are not currently accessible, +but would be after the CI has been transitioned to `trustedfirmware.org`_. + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* + +.. _Gerrit Upload Patch Set documentation: https://review.trustedfirmware.org/Documentation/intro-user.html#upload-patch-set +.. _Gerrit Replace Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html#push_replace +.. _trustedfirmware.org: https://www.trustedfirmware.org/ diff --git a/arm-trusted-firmware/docs/process/index.rst b/arm-trusted-firmware/docs/process/index.rst new file mode 100644 index 0000000..bba2b40 --- /dev/null +++ b/arm-trusted-firmware/docs/process/index.rst @@ -0,0 +1,17 @@ +Processes & Policies +==================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + security + platform-compatibility-policy + commit-style + coding-style + coding-guidelines + contributing + code-review-guidelines + faq + security-hardening diff --git a/arm-trusted-firmware/docs/process/platform-compatibility-policy.rst b/arm-trusted-firmware/docs/process/platform-compatibility-policy.rst new file mode 100644 index 0000000..be1f9ba --- /dev/null +++ b/arm-trusted-firmware/docs/process/platform-compatibility-policy.rst @@ -0,0 +1,36 @@ +Platform Compatibility Policy +============================= + +Introduction +------------ + +This document clarifies the project's policy around compatibility for upstream +platforms. + +Platform compatibility policy +----------------------------- + +Platform compatibility is mainly affected by changes to Platform APIs (as +documented in the :ref:`Porting Guide`), driver APIs (like the GICv3 drivers) or +library interfaces (like xlat_table library). The project will try to maintain +compatibility for upstream platforms. Due to evolving requirements and +enhancements, there might be changes affecting platform compatibility which +means the previous interface needs to be deprecated and a new interface +introduced to replace it. In case the migration to the new interface is trivial, +the contributor of the change is expected to make good effort to migrate the +upstream platforms to the new interface. + +The deprecated interfaces are listed inside :ref:`Release Processes` as well as +the release after which each one will be removed. When an interface is +deprecated, the page must be updated to indicate the release after which the +interface will be removed. This must be at least 1 full release cycle in future. +For non-trivial interface changes, an email should be sent out to the `TF-A +public mailing list`_ to notify platforms that they should migrate away from the +deprecated interfaces. Platforms are expected to migrate before the removal of +the deprecated interface. + +-------------- + +*Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.* + +.. _TF-A public mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a diff --git a/arm-trusted-firmware/docs/process/security-hardening.rst b/arm-trusted-firmware/docs/process/security-hardening.rst new file mode 100644 index 0000000..507046f --- /dev/null +++ b/arm-trusted-firmware/docs/process/security-hardening.rst @@ -0,0 +1,175 @@ +Secure Development Guidelines +============================= + +This page contains guidance on what to check for additional security measures, +including build options that can be modified to improve security or catch issues +early in development. + +Security considerations +----------------------- + +Part of the security of a platform is handling errors correctly, as described in +the previous section. There are several other security considerations covered in +this section. + +Do not leak secrets to the normal world +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **must not** leak secrets to the normal world, for example in +response to an SMC. + +Handling Denial of Service attacks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **should never** crash or become unusable due to receiving too +many normal world requests (a *Denial of Service* or *DoS* attack). It should +have a mechanism for throttling or ignoring normal world requests. + +Preventing Secure-world timing information leakage via PMU counters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Secure world needs to implement some defenses to prevent the Non-secure +world from making it leak timing information. In general, higher privilege +levels must defend from those below when the PMU is treated as an attack +vector. + +Refer to the :ref:`Performance Monitoring Unit` guide for detailed information +on the PMU registers. + +Timing leakage attacks from the Non-secure world +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since the Non-secure world has access to the ``PMCR`` register, it can +configure the PMU to increment counters at any exception level and in both +Secure and Non-secure state. Thus, it attempts to leak timing information from +the Secure world. + +Shown below is an example of such a configuration: + +- ``PMEVTYPER0_EL0`` and ``PMCCFILTR_EL0``: + + - Set ``P`` to ``0``. + - Set ``NSK`` to ``1``. + - Set ``M`` to ``0``. + - Set ``NSH`` to ``0``. + - Set ``SH`` to ``1``. + +- ``PMCNTENSET_EL0``: + + - Set ``P[0]`` to ``1``. + - Set ``C`` to ``1``. + +- ``PMCR_EL0``: + + - Set ``DP`` to ``0``. + - Set ``E`` to ``1``. + +This configuration instructs ``PMEVCNTR0_EL0`` and ``PMCCNTR_EL0`` to increment +at Secure EL1, Secure EL2 (if implemented) and EL3. + +Since the Non-secure world has fine-grained control over where (at which +exception levels) it instructs counters to increment, obtaining event counts +would allow it to carry out side-channel timing attacks against the Secure +world. Examples include Spectre, Meltdown, as well as extracting secrets from +cryptographic algorithms with data-dependent variations in their execution +time. + +Secure world mitigation strategies +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``MDCR_EL3`` register allows EL3 to configure the PMU (among other things). +The `Arm ARM`_ details all of the bit fields in this register, but for the PMU +there are two bits which determine the permissions of the counters: + +- ``SPME`` for the programmable counters. +- ``SCCD`` for the cycle counter. + +Depending on the implemented features, the Secure world can prohibit counting +in AArch64 state via the following: + +- ARMv8.2-Debug not implemented: + + - Prohibit general event counters and the cycle counter: + ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1 && !ExternalSecureNoninvasiveDebugEnabled()``. + + - ``MDCR_EL3.SPME`` resets to ``0``, so by default general events should + not be counted in the Secure world. + - The ``PMCR_EL0.DP`` bit therefore needs to be set to ``1`` when EL3 is + entered and ``PMCR_EL0`` needs to be saved and restored in EL3. + - ``ExternalSecureNoninvasiveDebugEnabled()`` is an authentication + interface which is implementation-defined unless ARMv8.4-Debug is + implemented. The `Arm ARM`_ has detailed information on this topic. + + - The only other way is to disable the ``PMCR_EL0.E`` bit upon entering + EL3, which disables counting altogether. + +- ARMv8.2-Debug implemented: + + - Prohibit general event counters: ``MDCR_EL3.SPME == 0``. + - Prohibit cycle counter: ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1``. + ``PMCR_EL0`` therefore needs to be saved and restored in EL3. + +- ARMv8.5-PMU implemented: + + - Prohibit general event counters: as in ARMv8.2-Debug. + - Prohibit cycle counter: ``MDCR_EL3.SCCD == 1`` + +In Aarch32 execution state the ``MDCR_EL3`` alias is the ``SDCR`` register, +which has some of the bit fields of ``MDCR_EL3``, most importantly the ``SPME`` +and ``SCCD`` bits. + +Build options +------------- + +Several build options can be used to check for security issues. Refer to the +:ref:`Build Options` for detailed information on these. + +- The ``BRANCH_PROTECTION`` build flag can be used to enable Pointer + Authentication and Branch Target Identification. + +- The ``ENABLE_STACK_PROTECTOR`` build flag can be used to identify buffer + overflows. + +- The ``W`` build flag can be used to enable a number of compiler warning + options to detect potentially incorrect code. + + - W=0 (default value) + + The ``Wunused`` with ``Wno-unused-parameter``, ``Wdisabled-optimization`` + and ``Wvla`` flags are enabled. + + The ``Wunused-but-set-variable``, ``Wmaybe-uninitialized`` and + ``Wpacked-bitfield-compat`` are GCC specific flags that are also enabled. + + - W=1 + + Adds ``Wextra``, ``Wmissing-format-attribute``, ``Wmissing-prototypes``, + ``Wold-style-definition`` and ``Wunused-const-variable``. + + - W=2 + + Adds ``Waggregate-return``, ``Wcast-align``, ``Wnested-externs``, + ``Wshadow``, ``Wlogical-op``. + + - W=3 + + Adds ``Wbad-function-cast``, ``Wcast-qual``, ``Wconversion``, ``Wpacked``, + ``Wpointer-arith``, ``Wredundant-decls`` and + ``Wswitch-default``. + + Refer to the GCC or Clang documentation for more information on the individual + options: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html and + https://clang.llvm.org/docs/DiagnosticsReference.html. + + NB: The ``Werror`` flag is enabled by default in TF-A and can be disabled by + setting the ``E`` build flag to 0. + +.. rubric:: References + +- `Arm ARM`_ + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* + +.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest diff --git a/arm-trusted-firmware/docs/process/security.rst b/arm-trusted-firmware/docs/process/security.rst new file mode 100644 index 0000000..a3b9971 --- /dev/null +++ b/arm-trusted-firmware/docs/process/security.rst @@ -0,0 +1,89 @@ +Security Handling +================= + +Security Disclosures +-------------------- + +We disclose all security vulnerabilities we find, or are advised about, that are +relevant to Trusted Firmware-A. We encourage responsible disclosure of +vulnerabilities and inform users as best we can about all possible issues. + +We disclose TF-A vulnerabilities as Security Advisories, all of which are listed +at the bottom of this page. Any new ones will, additionally, be announced as +issues in the project's `issue tracker`_ with the ``security-advisory`` tag. You +can receive notification emails for these by watching the "Trusted Firmware-A" +project at https://developer.trustedfirmware.org/. + +Found a Security Issue? +----------------------- + +Although we try to keep TF-A secure, we can only do so with the help of the +community of developers and security researchers. + +.. warning:: + If you think you have found a security vulnerability, please **do not** + report it in the `issue tracker`_ or on the `mailing list`_. Instead, please + follow the `TrustedFirmware.org security incident process`_. + +One of the goals of this process is to ensure providers of products that use +TF-A have a chance to consider the implications of the vulnerability and its +remedy before it is made public. As such, please follow the disclosure plan +outlined in the process. We do our best to respond and fix any issues quickly. + +Afterwards, we encourage you to write-up your findings about the TF-A source +code. + +Attribution +----------- + +We will name and thank you in the :ref:`Change Log & Release Notes` distributed +with the source code and in any published security advisory. + +Security Advisories +------------------- + ++-----------+------------------------------------------------------------------+ +| ID | Title | ++===========+==================================================================+ +| |TFV-1| | Malformed Firmware Update SMC can result in copy of unexpectedly | +| | large data into secure memory | ++-----------+------------------------------------------------------------------+ +| |TFV-2| | Enabled secure self-hosted invasive debug interface can allow | +| | normal world to panic secure world | ++-----------+------------------------------------------------------------------+ +| |TFV-3| | RO memory is always executable at AArch64 Secure EL1 | ++-----------+------------------------------------------------------------------+ +| |TFV-4| | Malformed Firmware Update SMC can result in copy or | +| | authentication of unexpected data in secure memory in AArch32 | +| | state | ++-----------+------------------------------------------------------------------+ +| |TFV-5| | Not initializing or saving/restoring PMCR_EL0 can leak secure | +| | world timing information | ++-----------+------------------------------------------------------------------+ +| |TFV-6| | Trusted Firmware-A exposure to speculative processor | +| | vulnerabilities using cache timing side-channels | ++-----------+------------------------------------------------------------------+ +| |TFV-7| | Trusted Firmware-A exposure to cache speculation vulnerability | +| | Variant 4 | ++-----------+------------------------------------------------------------------+ +| |TFV-8| | Not saving x0 to x3 registers can leak information from one | +| | Normal World SMC client to another | ++-----------+------------------------------------------------------------------+ + +.. _issue tracker: https://developer.trustedfirmware.org/project/board/1/ +.. _mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a + +.. |TFV-1| replace:: :ref:`Advisory TFV-1 (CVE-2016-10319)` +.. |TFV-2| replace:: :ref:`Advisory TFV-2 (CVE-2017-7564)` +.. |TFV-3| replace:: :ref:`Advisory TFV-3 (CVE-2017-7563)` +.. |TFV-4| replace:: :ref:`Advisory TFV-4 (CVE-2017-9607)` +.. |TFV-5| replace:: :ref:`Advisory TFV-5 (CVE-2017-15031)` +.. |TFV-6| replace:: :ref:`Advisory TFV-6 (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754)` +.. |TFV-7| replace:: :ref:`Advisory TFV-7 (CVE-2018-3639)` +.. |TFV-8| replace:: :ref:`Advisory TFV-8 (CVE-2018-19440)` + +.. _TrustedFirmware.org security incident process: https://developer.trustedfirmware.org/w/collaboration/security_center/ + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/requirements.in b/arm-trusted-firmware/docs/requirements.in new file mode 100644 index 0000000..5d771e5 --- /dev/null +++ b/arm-trusted-firmware/docs/requirements.in @@ -0,0 +1,5 @@ +myst-parser==0.15.2 +pip-tools==6.4.0 +sphinx==4.2.0 +sphinx-rtd-theme==1.0.0 +sphinxcontrib-plantuml==0.22 diff --git a/arm-trusted-firmware/docs/requirements.txt b/arm-trusted-firmware/docs/requirements.txt new file mode 100644 index 0000000..03b1189 --- /dev/null +++ b/arm-trusted-firmware/docs/requirements.txt @@ -0,0 +1,91 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile +# +alabaster==0.7.12 + # via sphinx +attrs==21.2.0 + # via markdown-it-py +babel==2.9.1 + # via sphinx +certifi==2021.5.30 + # via requests +charset-normalizer==2.0.4 + # via requests +click==8.0.1 + # via pip-tools +docutils==0.16 + # via + # myst-parser + # sphinx + # sphinx-rtd-theme +idna==3.2 + # via requests +imagesize==1.2.0 + # via sphinx +jinja2==3.0.1 + # via + # myst-parser + # sphinx +markdown-it-py==1.1.0 + # via + # mdit-py-plugins + # myst-parser +markupsafe==2.0.1 + # via jinja2 +mdit-py-plugins==0.2.8 + # via myst-parser +myst-parser==0.15.2 + # via -r requirements.in +packaging==21.0 + # via sphinx +pep517==0.11.0 + # via pip-tools +pip-tools==6.4.0 + # via -r requirements.in +pygments==2.10.0 + # via sphinx +pyparsing==2.4.7 + # via packaging +pytz==2021.1 + # via babel +pyyaml==6.0 + # via myst-parser +requests==2.26.0 + # via sphinx +snowballstemmer==2.1.0 + # via sphinx +sphinx==4.2.0 + # via + # -r requirements.in + # myst-parser + # sphinx-rtd-theme + # sphinxcontrib-plantuml +sphinx-rtd-theme==1.0.0 + # via -r requirements.in +sphinxcontrib-applehelp==1.0.2 + # via sphinx +sphinxcontrib-devhelp==1.0.2 + # via sphinx +sphinxcontrib-htmlhelp==2.0.0 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-plantuml==0.22 + # via -r requirements.in +sphinxcontrib-qthelp==1.0.3 + # via sphinx +sphinxcontrib-serializinghtml==1.1.5 + # via sphinx +tomli==1.2.1 + # via pep517 +urllib3==1.26.6 + # via requests +wheel==0.37.0 + # via pip-tools + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff --git a/arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png b/arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png new file mode 100644 index 0000000..e7bff71 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/FIP_in_a_GPT_image.png b/arm-trusted-firmware/docs/resources/diagrams/FIP_in_a_GPT_image.png new file mode 100644 index 0000000..4bafed9 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/FIP_in_a_GPT_image.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/MMU-600.png b/arm-trusted-firmware/docs/resources/diagrams/MMU-600.png new file mode 100644 index 0000000..9cbc243 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/MMU-600.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/Makefile b/arm-trusted-firmware/docs/resources/diagrams/Makefile new file mode 100644 index 0000000..7f583b5 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/Makefile @@ -0,0 +1,74 @@ +# +# Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +# This Makefile generates the image files used in the Trusted Firmware-A +# document from the dia file. +# +# The PNG files in the present directory have been generated using Dia version +# 0.97.2, which can be obtained from https://wiki.gnome.org/Apps/Dia/Download +# + +# generate_image use the tool dia generate png from dia file +# $(1) = layers +# $(2) = image file name +# $(3) = image file format +# $(4) = addition opts +# $(5) = dia source file +define generate_image + dia --show-layers=$(1) --filter=$(3) --export=$(2) $(4) $(5) +endef + +RESET_DIA = reset_code_flow.dia +RESET_PNGS = \ + default_reset_code.png \ + reset_code_no_cpu_check.png \ + reset_code_no_boot_type_check.png \ + reset_code_no_checks.png \ + +# The $(RESET_DIA) file is organized in several layers. +# Each image is generated by combining and exporting the appropriate set of +# layers. +default_reset_code_layers = "Frontground,Background,cpu_type_check,boot_type_check" +reset_code_no_cpu_check_layers = "Frontground,Background,no_cpu_type_check,boot_type_check" +reset_code_no_boot_type_check_layers= "Frontground,Background,cpu_type_check,no_boot_type_check" +reset_code_no_checks_layers = "Frontground,Background,no_cpu_type_check,no_boot_type_check" + +default_reset_code_opts = +reset_code_no_cpu_check_opts = +reset_code_no_boot_type_check_opts = +reset_code_no_checks_opts = + +INT_DIA = int_handling.dia +INT_PNGS = \ + sec-int-handling.png \ + non-sec-int-handling.png + +# The $(INT_DIA) file is organized in several layers. +# Each image is generated by combining and exporting the appropriate set of +# layers. +non-sec-int-handling_layers = "non_sec_int_bg,legend,non_sec_int_note,non_sec_int_handling" +sec-int-handling_layers = "sec_int_bg,legend,sec_int_note,sec_int_handling" + +non-sec-int-handling_opts = --size=1692x +sec-int-handling_opts = --size=1570x + +XLAT_DIA = xlat_align.dia +XLAT_PNG = xlat_align.png + +xlat_align_layers = "bg,translations" +xlat_align_opts = + +all:$(RESET_PNGS) $(INT_PNGS) $(XLAT_PNG) + +$(RESET_PNGS):$(RESET_DIA) + $(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<) + +$(INT_PNGS):$(INT_DIA) + $(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<) + +$(XLAT_PNG):$(XLAT_DIA) + $(call generate_image,$($(patsubst %.png,%_layers,$@)),$(patsubst %.png,%.svg,$@),svg,$($(patsubst %.png,%_opts,$@)),$<) + inkscape -z $(patsubst %.png,%.svg,$@) -e $@ -d 45 diff --git a/arm-trusted-firmware/docs/resources/diagrams/arm-cca-software-arch.png b/arm-trusted-firmware/docs/resources/diagrams/arm-cca-software-arch.png new file mode 100755 index 0000000..979e083 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/arm-cca-software-arch.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png b/arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png new file mode 100644 index 0000000..6006f1c Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/cmake_framework_workflow.png b/arm-trusted-firmware/docs/resources/diagrams/cmake_framework_workflow.png new file mode 100644 index 0000000..7311529 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/cmake_framework_workflow.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/context_management_abs.png b/arm-trusted-firmware/docs/resources/diagrams/context_management_abs.png new file mode 100644 index 0000000..717ecec Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/context_management_abs.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png b/arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png new file mode 100644 index 0000000..5170960 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/context_mgmt_proposed.png b/arm-trusted-firmware/docs/resources/diagrams/context_mgmt_proposed.png new file mode 100644 index 0000000..41ae92f Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/context_mgmt_proposed.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png b/arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png new file mode 100644 index 0000000..d8675e4 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg new file mode 100644 index 0000000..c98090f --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg @@ -0,0 +1,2 @@ + +
Interrupt Management Framework
Interrupt Management Framework
Interrupt
Type
[Not supported by viewer]
Interrupt
Interrupt
NS
NS
S-EL1
S-EL1
EL3
EL3
SPD handlers
SPD handlers
Exception Handling Framework
Exception Handling Framework
GIC PMR
GIC PMR
RAS
RAS
SPM
[Not supported by viewer]
SDEI Critical
SDEI Critical
SDEI Normal
SDEI Normal
NS priorities
NS priorities
0xFF
0xFF
0x0
[Not supported by viewer]
Interrupt Priority
[Not supported by viewer]
EHF APIs
EHF APIs
Non-interrupt exceptions use EHF APIs to program GIC PMR to arbitrate priority levels
Non-interrupt exceptions use EHF APIs to program GIC PMR to arbitrate priority levels
Decreasing Priority
Decreasing Priority
Secure Priority levels
Secure Priority levels
\ No newline at end of file diff --git a/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml new file mode 100644 index 0000000..db1f91d --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml @@ -0,0 +1 @@ +7Vxbc9o4FP41PMaj++UxF2g703Yyzc5s++iCAt4azAiTkP31K2EbLMuAAzYhmaUzrX0k+XLu59Nxe/h2uvqkw/nkWzJScQ+B0aqH73oIIcCY+cdSXjIKhEBklLGORjltS3iI/lU5EeTUZTRSC2dimiRxGs1d4jCZzdQwdWih1smzO+0xid27zsOx8ggPwzD2qX9Ho3RSvAaT24HPKhpP8lsLxLOB3+Hwz1gny1l+vx7Cj+tfNjwNi2vlL7qYhKPkuUTC/R6+1UmSZkfT1a2KLXMLtmXrBjtGN8+t1SxtskDgbMVTGC9V8cjrB0tfCmasX0fZBaCHb54nUaoe5uHQjj4b+RvaJJ3G5gyaw0Wqkz8bppn3uXmM4vg2iRNtzmfJTG0mFUTDI7D+mRH/+fNXelI6VasSKX+fTyqZqlS/mCkb9ctWFLoH8vPnkiBBQZyUhEgL7Qtz7Rlvrr3loDnImVjPUOTx88ssVVov56khfwtnRnOm9uUQGOhwqp4T/cfj+AEeh4t5pvSP0crK5QDTDX/vSB8OaDv8hQQEABEuMCScUMmJw2/Eavnts3tDPIXdwue3x001MradnyY6nSTjZBbG/S31xtXwEqf/UWn6kruncJkmhrS9wtckme/UesNf/fIzv+L65Jc9CfYKYZEs9TB/6pyraajHqpiVu1X7QnslpVUcptGT68zq2JwvvU+itUbmEsZWwpxgIglBmEvoGpSoyC17xPwaW9Fdax2+lKbN7YTF3rtW7kMrmpBdcasXmzdupCqkRlNYbFh7M4qezOHYHpaNtRj+rYvRgmJuVVpTc5m/XuZq1+Sqd50k09/LxametWUjR9KoAIOScsEEIxI3sXHXLeCOTB7CGkFegsk3MmvkmzVp26obc9I3iZL+V1k6G13bzMqcDeNwsYiGLt/2ObxX8KrMGNSQMbnOGv0DEFWCv6entC7y57QT/WbFgeFqPpHpgecovetAigKKuBAQECAkct9JEh7QRh54e+FiYvL4uFDOnCMcaRGGSmrz/cH3a+1ljda3XffF4LYd30ZseJMSYkSFFFhIV2VqfBunATDhSHDMAJVE7Nagk8xRenx9uOp/hR+GtSiP6OdnbVETvM+YUZcKyrcKGsgPv/2vuGMdHQwG6PYsOkpqQsaZdLRVldwXjs+vrsW0liuXI0oMp7BxAyvB7RYcyMdWHu7vrOaEs1Gs9OI0oxmFi8l6biMLylGojrEXymBgC0ZhchgGMT4cWhuVDZzuVoTG5kXfcwgoci7HqPBFGBU1pSLEDAOOIQSbGF9fxZ+2+nST9FPX96QE8mKVgAEUMCwJoAgQwlzEqCiEdunAaxafrgJ+0dtfDdU8jZKZIX+2vjmajXv78NnLTW72O2CyLR1f64IhqhadRzlhfhH21xJW4eA6dfhF68jOcQ7aZD0QYQkpxxxJwfZlPa9cTQEOeMs4rehURxZGQqmPZK3Jgyg+kyvH+Bzq0tQssZ+pfvpiVoH7bz86dn53tC/uyNvmpfjIvJTCALXhFH2F/3F9IqC2K8S8Ql2bc5cTGGQbRRl/3Q1BWlNRN+JuGzW1D6nV7NY83H9rulnzTmVAjtXwFmSAfezt4a7/xVBudZRGwzD+OGx+Q1XHPi6Xs/l7oqcfiMlHe+s2mIw8JtutDzDXUWKVWZ2I6VRBG2r/1LLZC5ds/TuHAI6FcVAbu7/4XVfwea7tpH2Ff3zjKoGDii9rGQ3F3ab1b1j61Qm1yOm6btXhmAaQG2khwYkg1MVOKG62UXyqrtC2daUJVhvH0XyhDvvUBt1yLbhMJnnAGJJEQkmocYSuMdFNmex4zQ2o4mAtrUAtpC717aiM3rR1bmto0JJNltpO8rsYSukex8I1NZtUhdadv/6mfu52ab5RraL0ZzHPHHfjNVvf1d7hvxAyxioABAICJonb3Ua4GYUSEJ7/7V6+aRcPpySwli8QRVAKgFyXSfi+m7TlqJG5CwdYEIgFF7QC/bH9uPyB1S3vzVAfmAerwcAzBOOQ0zqQqdJjXtN2HsbReGZOh8p2uRmCde+2AL3OB6bRaBTvCimueXUSRAQmAQfb7TBXLyHFXgShJu120NmaeNIGRkXrIrIHpIAVaAikfGghgj1CpAS9nRDraqe9LdD3WV378q6kqpM0XO/m4bsr2ZmYGYMBEoAxCQmRwkOCUM1O27kEzZrkEwf6eZ32kiL6X9kqv5wCWAIp8oN7pSPzrFZ+rzWvgxH/PB28QuAAccYhYwwgyt1yihBmdxGwsWlCBDo2MRAMBMjkHZRxigmolApYNKvZjoiwrMHHXkepBTglKbwY0dN1/7iAQjCJqwWckZmps00ilMmfdiF60rBcP0b0dV+//C/6yxF9h1bfBDE9NhgAVpI/tBDwB4oFJDB1j5TSomySu51phOOgiANUsIKn7WpFU/zuCK3g3UIODbssDqE7TZGLA72wO1WtDEiwpuBDLpwr1I6eYWa8jwCUUISkyTGq2+cNdaCjj32YDyP2P5uiHFzff2l3s2swuKG8s3SdQMNliSRmAqDqN8uG80f2xbWRrfPW07ICx1t7aOKCeZzKgvD+fTQ1UoWQcyglBQTjqvskVSS9qV9eNwyVftS7sPBHO/DSPuzyPZldRaUSXRXNq8YawXKhzN9lAwXGadr96WSsw6k5KvV1ZUOh/h2lOkxVb7ONbeUXqycV+wZ+GRV+N10HPKAlD1HpEat3EUiYRRxaPSRCEsY7Kuj5sTlc3TZNNUyX4u02+p4SVS/EOUgqA4QpwVICIFglgaOs0o3Q1DXsvyysXrZFZ+DvoN+poVbhIutX34J1F2m054HljEACyZDddMk+oHakg+sb4C0uhznkhCMIhWQdGXHN971quNTKkd1le94zCdE4290QukmRN32355eiaIKkXFofywat2ezl/sqX7pTWwbalbj7prNlGhQEt/SqZOzFpfXm4kfM9td8F79v69FdDHEi4szWEM6+LfEcoOhwzzOn2/w7Lpm//hzbc/w8= \ No newline at end of file diff --git a/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg new file mode 100644 index 0000000..ff58198 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg @@ -0,0 +1,2 @@ + +

<div><br></div>
plat_ea_handler()
plat_ea_handler()
ras_ea_handler()
ras_ea_handler()
ras_interrupt_handler()
ras_interrupt_handler()
Exception Handling Framework
Exception Handling Framework
RAS
priority level handler
[Not supported by viewer]
RAS error records
RAS error records
RAS interrupts array
RAS interrupts array
RAS framework
RAS framework
Iterate and probe
<i>Iterate and probe</i>
Error handler
Error handler
Bisect and lookup
<i>Bisect and lookup</i>
Error handler
Error handler
SER helpers
SER helpers
External Abort
External Abort
Interrupt
[Not supported by viewer]
Interrupt Priority
Interrupt Priority
EHF APIs
EHF APIs
\ No newline at end of file diff --git a/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml new file mode 100644 index 0000000..ce6df3a --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml @@ -0,0 +1 @@ +5VtLc6M4EP41rto9rAs9eB2TjD0zVbtVqclhd05TipFtNhhRQk7i/fUrQGBAECsJYGcml0Ajgfi6++tWN56hm93zZ06S7V8soNEMWsHzDH2aQQgtx5H/MsmhkABgeYVkw8NAyY6Cu/A/qoSWku7DgKaNgYKxSIRJU7hicUxXoiEjnLOn5rA1i5pPTciGaoK7FYl06d9hILblazj+8cIXGm626tEedIsL92T1sOFsH6vnzSBa53/F5R0p76VeNN2SgD3VRGgxQzecMVEc7Z5vaJSBW8JWzFv2XK3WzWksjCaoGY8k2tNyyfnCxKEEI38dmk2wZuj6aRsKepeQVXb1SepfyrZiF8kzIA9TwdlDBZp8n+t1GEU3LGJcnscsltOuA5Ju8xtmM/Qll2uiXNDnmki9wmfKdlTwgxyirmKs4CztrYT36ag8WI7Z1vSGHCUkymA21b2PoMkDhVsPhug0hjSQ9qVOGRdbtmExiRZH6XUT5Rqi/1IhDspFyF4wKTre4U/Gkl7ke5FN2Z6v1MrUWgXhG1qiUoiyNb+IPqcREeFj02e6kFRTb1koF1JpDcGW1ryWMoo1qVktfVTLMFIRxh0qciKR2WL4KA83IserEN3ztkTevzFuOO2m8iXFVUZZUrCKSJqGq1K8DKNyGI2DcpDyISlR163JjGRsi2i78XgGATV7SOTKf1DyY0viIKL8t9/H5EEZFj7hBVjaw/AfaHuSo/NfNabOf3gA+kMGIWQoB1G2X/eOCawf6RRZDhvOI4zh1tDmJP2ohos9A8N1RjJcaH/kuI07jHJwmjaFUg+vmVFKmqac7xMxmW0ulwvb98exTeT7c3s668R6iDpD3vF2Iz6VsRgZuT1N3oH8uef6wIPAdgCSim4oHgNnXq5k+ExEJ6HF84omImSxFH/JHCeMN/JwycmOPjH+MJUPFSNrV6z8b6CUBTQx97yms3UFAsuaWxC7HgLYxbbvIt3zAIBzu1/9ps7nGPheFIVJSk8DTtKkKFGsw+dMSa8hfHM8oY3mwIE+9oGPbey6TgtPt7LhRlJYotUAcRAM3en4651poUSdH/5Rk/KT79nJ3DagsTdGb1uP3s65gje41DzoJb0YoezrKONRIoo0EXKoDUiywJD2Bxzc2rBhG9Y1dnp8s6wnD4oVvDUI+R0WoJVHvl3d9dVDtLEJDxkPRYZJRB/z8rDKAd9cZHlVlHs5ptWNbNQoJ2829yGq4hxuadHryigNwpw9RNnSugi3f8nJX0GudR/3p8kaoY/mjpur0cUetkHLpUE7ivYkja8lD+i0NyatGv+J8TI96CeP009rF+UKwh2kKNdFQ8NZZKPrkJ3cEiE3qHEugRZ8V6wy3E8ZhS3g6TYNBjdq44LTuDxxAfW9LrzPV+ArV1PDO4+8FpUg8fyJK8aD9H0BctJSiguaHFIVSCYp83X1fi4rvVU7jTL2GdttR35bvtzYwc/1W0GlrarhKiRADwuFQ1T1xXSWt/3J4QP7BOroWY/nEzqnF5Cue4tM8rVEF1yt1n5Ht59E4SYLsiua6UsKMpDCFYmu1IVdGARRXyWlqcEBgG/XdX1D3OEAuCOTwtJAGc4FBNau5BwNXtM1NvquRmWx9QzLXedXaaFE0OxJcZC9IGf3tLZBDYfZnk7aZGszzaRNNtRR31Z5TFUQGA9JZfYDgOibtNhHA1FPCX9q2oAdtOGejTbgadq4DtOsxl+yRsTYwz45A22MmqBM2/9Eev/gpyCOqWEcd/czLluYfSfa+FSngzrKDfUZSic6ddwtvuVajhLKx97Cj/mlzqRbeGRQGHxze6CyWvPOwNDfL7/cJkCup0M9UZMA6xvFXwl5eEbkuz4MycrVJBt1dS8pVNPEZezRh9ZRqwEBbJ15ur7tH2K/jrv261qz82tZhzLsZP6carJbX5z4eDo16bliTSfWbdWM/iUUkX3OZjd10RGsR9PFhE28KfaqrazxLb+nsV9U1x/WHMCmvkqGe2eN3sa4ZQie39JwT/NWu5UD27eyDQv+r+1uA7c70exb2Ynxfd3tcjlsvU7pu7/h1LOkxZdlFqZvv+pJ/sWyjkYxHcbea8bAhU09uKNxjjw9/kKyUNfxd6ho8T8= \ No newline at end of file diff --git a/arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png b/arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png new file mode 100644 index 0000000..605fd9b Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png b/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png new file mode 100644 index 0000000..0619cf2 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png b/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png new file mode 100644 index 0000000..f110028 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png b/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png new file mode 100755 index 0000000..c318610 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png b/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png new file mode 100755 index 0000000..b62000d Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png b/arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png new file mode 100644 index 0000000..534095f Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/fwu_states.png b/arm-trusted-firmware/docs/resources/diagrams/fwu_states.png new file mode 100644 index 0000000..fda4d8f Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/fwu_states.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/int_handling.dia b/arm-trusted-firmware/docs/resources/diagrams/int_handling.dia new file mode 100644 index 0000000..12aa186 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/int_handling.dia differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png b/arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png new file mode 100644 index 0000000..64082c9 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/bl2-loading-sp.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/bl2-loading-sp.puml new file mode 100644 index 0000000..3cf7c36 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/bl2-loading-sp.puml @@ -0,0 +1,44 @@ +/' + ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +@startuml +participant bl1 +participant FIP + +bl1 -> FIP : read(FW_CONFIG) +create FW_CONFIG +bl1 -> FW_CONFIG : load + +bl1 -> FIP : read(bl2) +create bl2 +bl1 -> bl2 : load +bl1 --> bl2 : hand off (FW_CONFIG) + +bl2 -> FW_CONFIG : read_node(SPKs) +loop for each spkg subnode + bl2 -> FW_CONFIG : read(UUID) + bl2 -> FW_CONFIG : read(load_address) + bl2 -> FIP : read(spkg@UUID) + create SPKG + bl2 -> SPKG : load +end loop + +bl2 -> FW_CONFIG : read_node(TOS_FW_CONFIG) +create TOS_FW_CONFIG +bl2 -> TOS_FW_CONFIG : load + +bl2 -> FIP : read(bl32/SPMC) +create SPMC +bl2 -> SPMC : load + +bl2 -> FIP : read(bl31) +create bl31 +bl2 -> bl31 : load +bl2 --> bl31 : hand off (TOS_FW_CONFIG) + +bl31 --> SPMC : hand off (TOS_FW_CONFIG) + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml new file mode 100644 index 0000000..e513ed4 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml @@ -0,0 +1,78 @@ +@startuml + +box "BL1 common code" + participant bl1_main + participant bl_common +end box + +box "arm platform code" #LightBlue + participant fvp_bl1_setup + participant arm_bl1_setup + participant arm_io_storage +end box + +box "platform common code" + participant plat_bl1_common + participant fconf_dyn_cfg_getter + participant fconf +end box + +bl1_main -> fvp_bl1_setup : bl1_platform_setup() +fvp_bl1_setup -> arm_bl1_setup : arm_bl1_platform_setup() +arm_bl1_setup -> arm_io_storage : plat_arm_io_setup() +note over arm_io_storage : register and setup fip +arm_bl1_setup -> fconf : set_fw_config_info(fw_config_base, max_size) +note over fconf + set fw_config information + (address, size, image_id) + in global dtb_infos array. +end note +activate fconf + arm_bl1_setup -> fconf : fconf_load_config(FW_CONFIG_ID) + fconf -> fconf : FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID) + fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(FW_CONFIG_ID) + fconf_dyn_cfg_getter -> fconf: fw_config_info + fconf -> bl_common : load_auth_image(FW_CONFIG_ID, &image_info) + activate bl_common + note over bl_common + load and auth image from fip + with info from plat_io_policy + end note + bl_common -> arm_io_storage + arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, FW_CONFIG_ID) + note over fconf: use statically defined policies in bl1 + fconf <- bl_common : image_info + deactivate bl_common + note over fconf : get fw_config_dtb from image_info + arm_bl1_setup -> fconf: FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID) + fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(FW_CONFIG_ID) + fconf_dyn_cfg_getter -> arm_bl1_setup: fw_config_info + arm_bl1_setup -> fconf_dyn_cfg_getter: populate_dtb_registry(uintptr_t dtb) + arm_bl1_setup -> fconf: fconf_load_config(TB_FW_CONFIG_ID) + fconf -> fconf : FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID) + fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(TB_FW_CONFIG_ID) + fconf_dyn_cfg_getter -> fconf: tb_fw_config_info + fconf -> bl_common : load_auth_image(TB_FW_CONFIG_ID, &image_info) + activate bl_common + note over bl_common + load and auth image from fip + with info from plat_io_policy + end note + bl_common -> arm_io_storage + arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, TB_FW_CONFIG_ID) + note over fconf: use statically defined policies in bl1 + fconf <- bl_common : image_info + deactivate bl_common + note over fconf : get tb_fw_config_dtb from image_info + fconf -> arm_bl1_setup + arm_bl1_setup -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID) + arm_bl1_setup <- plat_bl1_common : BL2_IMAGE_DESC + note over arm_bl1_setup + set ep_info.args.arg0 of BL2_IMAGE_DESC + to FW_CONFIG base address + end note +deactivate fconf + +== load & auth, prepare and jump to BL2 == + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml new file mode 100644 index 0000000..c536ee0 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml @@ -0,0 +1,49 @@ +@startuml + +box "BL2 common code" + participant bl2_entrypoint + participant bl2_main +end box + +box "platform common code" + participant fconf + participant fconf_tbbr_getter +participant fconf_dyn_cfg_getter +end box + +box "arm platform code" #LightBlue + participant arm_bl2_setup + participant arm_io_storage + participant arm_fconf_io +end box + +== bl2 setup == +bl2_entrypoint -> bl2_main : bl2_setup() +bl2_main -> arm_bl2_setup : bl2_early_platform_setup2(\n\t arg0, arg1, arg2, arg3) +note over arm_bl2_setup + arg0 = fw_config + arg1 = mem_layout +end note +arm_bl2_setup -> arm_bl2_setup : arm_bl2_early_platform_setup(\n\t fw_config, mem_layout) +activate arm_bl2_setup + arm_bl2_setup -> fconf: fconf_populate("FW_CONFIG", fw_config) + activate fconf + fconf -> fconf_dyn_cfg_getter: populate_dtb_registry(uintptr_t dtb) + note over fconf_dyn_cfg_getter: read dtb_registry properties from dtb + fconf_dyn_cfg_getter -> arm_bl2_setup + arm_bl2_setup -> fconf: FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID) + fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(TB_FW_CONFIG_ID) + fconf_dyn_cfg_getter -> arm_bl2_setup: tb_fw_config_info + arm_bl2_setup -> fconf: fconf_populate("TB_FW_CONFIG", tb_fw_config) + fconf -> fconf_tbbr_getter: fconf_populate_tbbr_dyn_config(uintptr_t dtb) + note over fconf_tbbr_getter: read tbbr properties from dtb + fconf -> arm_fconf_io: fconf_populate_arm_io_policies(uintptr_t dtb) + note over arm_fconf_io: read arm io propeties from dtb + deactivate fconf + arm_bl2_setup -> arm_io_storage : plat_arm_io_setup() + note over arm_io_storage: use populated properties +deactivate arm_bl2_setup + +== bl2 main == + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml new file mode 100644 index 0000000..9457e32 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml @@ -0,0 +1,167 @@ +/' + ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +@startuml + +folder SP_vendor_1 { + artifact sp_binary_1 + artifact sp_manifest_1 [ + sp_manifest_1 + === + UUID = xxx + load_address = 0xaaa + owner = "Sip" + ... + ] +} + +folder SP_vendor_2 { + artifact sp_binary_2 + artifact sp_manifest_2 [ + sp_manifest_2 + === + UUID = yyy + load_address = 0xbbb + owner = "Plat" + ] +} + +artifact tb_fw_config.dts [ + tb_fw_config.dts + ---- + secure-partitions + === + spkg_1 UUID + spkg_1 load_address + --- + spkg_2 UUID + spkg_2 load_address + --- + ... + === + ... +] + +artifact config.json [ + SP_LAYOUT.json + === + path to sp_binary_1 + path to sp_manifest_1 + --- + path to sp_binary_2 + path to sp_manifest_2 + --- + ... +] + +control sp_mk_generator + +artifact sp_gen [ + sp_gen.mk + === + FDT_SOURCE = ... + SPTOOL_ARGS = ... + FIP_ARGS = ... + CRT_ARGS = ... +] + +control dtc +control sptool + +artifact tb_fw_config.dtb + +artifact spkg_1 [ + sp1.pkg + === + header + --- + manifest + --- + binary +] + +artifact spkg_2 [ + sp2.pkg + === + header + --- + manifest + --- + binary +] + +artifact signed_tb_fw_config.dtb [ + tb_fw_config.dtb (signed) +] + +artifact signed_spkg_1 [ + sp1.pkg (signed) + === + header + --- + manifest + --- + binary + --- + signature +] + +artifact signed_spkg_2 [ + sp2.pkg (signed) + === + header + --- + manifest + --- + binary + --- + signature +] + +control crttool +control fiptool + +artifact fip [ + fip.bin + === + tb_fw_config.dtb (signed) + --- + ... + --- + sp1.pkg (signed & SiP owned) + --- + sp2.pkg (signed & Platform owned) + --- + ... +] + +config.json .up.> SP_vendor_1 +config.json .up.> SP_vendor_2 +config.json --> sp_mk_generator +sp_mk_generator --> sp_gen +sp_gen --> fiptool +sp_gen --> cert_create +sp_gen --> sptool + +sptool --> spkg_1 +sptool --> spkg_2 + +spkg_1 --> cert_create +spkg_2 --> cert_create +cert_create --> signed_spkg_1 +cert_create --> signed_spkg_2 + +tb_fw_config.dts --> dtc +dtc --> tb_fw_config.dtb +tb_fw_config.dtb --> cert_create +cert_create --> signed_tb_fw_config.dtb + +signed_tb_fw_config.dtb --> fiptool +signed_spkg_1 -down-> fiptool +signed_spkg_2 -down-> fiptool +fiptool -down-> fip + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml new file mode 100644 index 0000000..53594c2 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml @@ -0,0 +1,109 @@ +@startuml + +package arm_io_storage { + + class plat_io_policy { + dev_handle : uintptr_t* + image_spec : uintptr_t + {abstract} check() : fctptr + } + + class FIP_IMAGE_ID { + memmap_dev_handle + fip_block_spec + open_memmap() + } + + class BL2_IMAGE_ID{ + fip_dev_handle + bl2_uuid_spec + open_fip() + } + + class xxx_IMAGE_ID{ + fip_dev_handle + xxx_uuid_spec + open_fip() + } + + class arm_io_storage { + fip_dev_con : io_dev_connector_t* + fip_dev_handle : uintptr_t + memmap_dev_con : io_dev_connector_t* + memmap_dev_handle : uintptr_t + + fip_block_spec : io_block_spec_t + + policies : plat_io_policy[1..*] + + -open_fip() + -open_memmap() + + +arm_io_setup() + +plat_get_image_source() + } + + FIP_IMAGE_ID -up-|> plat_io_policy + BL2_IMAGE_ID -up-|> plat_io_policy + xxx_IMAGE_ID -up-|> plat_io_policy + + arm_io_storage *-"1..*" plat_io_policy +} + +package IO { + class io_storage { + io_dev_open() + io_dev_init() + io_dev_close() + + .. synchronous operations .. + io_open() + io_seek() + io_size() + io_read() + io_write() + io_close() + + io_register_device() + } + + class io_fip { + register_io_dev_fip() + .. io_dev_funcs_t interface .. + fip_dev_funcs : io_dev_funcs_t + } + + class io_memmap { + register_io_dev_memmap() + .. io_dev_funcs_t interface .. + memmap_dev_funcs : io_dev_funcs_t + } + + interface io_driver { + io_entity_t + io_dev_info_t + + .. io_dev_connector_t interface .. + dev_open() + + .. io_dev_funcs_t interface .. + type() + open() + seek() + size() + read() + write() + close() + dev_init() + dev_close() + + io_register_device() + } +} +arm_io_storage .. io_driver +arm_io_storage .. io_fip +arm_io_storage .. io_memmap +arm_io_storage .. io_storage + + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml new file mode 100644 index 0000000..b7289a2 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml @@ -0,0 +1,62 @@ +@startuml + +participant arm_io_storage +participant io_storage + + -> arm_io_storage : plat_get_image_source(image_id, &dev_handle, &image_spec) + +group init and check device (image_id) + +alt image_id = BL2_IMAGE_ID +note over arm_io_storage + get BL2_IMAGE_ID policy: + - fip_dev_handle + - open_fip() +end note +opt policy->check() + arm_io_storage -> arm_io_storage : open_fip(spec) + activate arm_io_storage + arm_io_storage -> io_storage : io_dev_init(fip_dev_handle, FIP_IMAGE_ID) + ref over io_storage : dev_init() on fip device + + arm_io_storage -> io_storage : io_open(fip_dev_handle, spec, &local_image_handle) + ref over io_storage : io_open() on fip device + + arm_io_storage -> io_storage : io_close(local_image_handle) + ref over io_storage : io_close() on fip device + + hnote over arm_io_storage + fip_dev_handle ready + end note +end opt +deactivate arm_io_storage + +else image_id = FIP_IMAGE_ID +activate arm_io_storage +note over arm_io_storage + get FIP_IMAGE_ID policy: + - memmap_dev_handle + - open_memmap() +end note +opt policy->check() + arm_io_storage -> arm_io_storage : open_memmap(spec) + activate arm_io_storage + arm_io_storage -> io_storage : io_dev_init(memmap_dev_handle, NULL) + ref over io_storage : dev_init() on memmap device + + arm_io_storage -> io_storage : io_open(memmap_dev_handle, spec, &local_image_handle) + ref over io_storage : io_open() on memmap device + + arm_io_storage -> io_storage : io_close(local_image_handle) + ref over io_storage : io_close() on memmap device + + hnote over arm_io_storage + memmap_dev_handle ready + end note + deactivate arm_io_storage +end opt +deactivate arm_io_storage +end alt + +end group +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml new file mode 100644 index 0000000..c6f330e --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml @@ -0,0 +1,52 @@ +@startuml + +participant arm_io_storage +participant io_storage +participant io_fip +participant io_memmap + + -> arm_io_storage : arm_io_setup() + +group io dev registration + +arm_io_storage -> io_fip : register_io_dev_fip(&fip_dev_con) +io_fip -> io_storage : io_register_device(&dev_info_pool[]) +note over io_storage + devices[dev_count] = (fip_)dev_info_pool + dev_count++ +end note + +arm_io_storage -> io_memmap : register_io_dev_memmap(&memmap_dev_con) +io_memmap -> io_storage : io_register_device(&memmap_dev_info) +note over io_storage + devices[dev_count] = memmap_dev_info + dev_count++ +end note + +arm_io_storage -> io_storage : io_dev_open(fip_dev_con, NULL, fip_dev_handle) + io_storage -> io_storage : dev_open(dev_con, dev_spec, handle) +activate io_storage +opt dev_open() on fip device + io_storage -> io_fip : fip_dev_open(dev_spec, dev_info) + note over io_fip + dev_info = one of the + "fip_dev_info" from + dev_info_pool[] + end note +end opt +deactivate io_storage + + +arm_io_storage -> io_storage : io_dev_open(memmap_dev_con, NULL, memmap_dev_handle) +io_storage -> io_storage : dev_open(dev_con, dev_spec, handle) +activate io_storage +opt dev_open() on memmap device + io_storage -> io_memmap : memmap_dev_open(dev_spec, dev_info) + note over io_memmap + dev_info = memmap_dev_info + end note +end opt +deactivate io_storage + +end group +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml new file mode 100644 index 0000000..b21a0ae --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml @@ -0,0 +1,59 @@ +@startuml + +participant bl_common +participant arm_io_storage +participant io_storage + +== Platform Setup == + +bl1_main -> xxx_bl1_setup : bl1_platform_setup() +xxx_bl1_setup -> arm_io_storage : plat_arm_io_setup() + +arm_io_storage -> arm_io_storage : arm_io_setup() +ref over arm_io_storage, io_storage : io device registration + +== Get Image == +bl1_main -> xxx_bl1_setup : bl1_plat_get_next_image_id() +bl1_main <-- xxx_bl1_setup : BL2_IMAGE_ID + +bl1_main -> bl1_main : bl1_load_bl2() +activate bl1_main +bl1_main -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID) +bl1_main <-- plat_bl1_common : BL2_IMAGE_DESC + +bl1_main -> plat_bl1_common : bl1_plat_handle_pre_image_load(BL2_IMAGE_ID) + +bl1_main -> bl_common : load_auth_image(BL2_IMAGE_ID, image_info) +activate bl_common +bl_common -> bl_common : load_auth_image_internal(BL2_IMAGE_ID, image_info, is_parent_image) +activate bl_common +bl_common -> bl_common : load_image(BL2_IMAGE_ID, image_info) +activate bl_common +bl_common -> arm_io_storage : plat_get_image_source(BL2_IMAGE_ID, &dev_handle, &image_spec) +ref over arm_io_storage, io_storage : init and check device (BL2_IMAGE_ID) +bl_common <-- arm_io_storage : dev_handle + +bl_common -> io_storage : io_open(dev_handle, image_spec, &image_handle) +ref over io_storage : io_open() on fip device +bl_common <-- io_storage : image_handle +bl_common -> io_storage : io_size(image_handle, &image_size) +ref over io_storage : io_size() on fip device +bl_common -> io_storage : io_read(image_handle, image_base, image_size, &bytes_read) +ref over io_storage : io_read() on fip device +bl_common -> io_storage : io_close(image_handle) +ref over io_storage : io_close() on fip device +bl_common -> io_storage : io_dev_close(dev_handle) +ref over io_storage : io_dev_close() on fip device + +deactivate bl_common +deactivate bl_common +deactivate bl_common + +== Prepare Next Image == +bl1_main -> plat_bl1_common : bl1_plat_handle_post_image_load(BL2_IMAGE_ID) + +deactivate bl1_main + +== Jump to next Image == + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml new file mode 100644 index 0000000..90ff23c --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml @@ -0,0 +1,51 @@ +/' + ' Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +@startuml + +autonumber "[#]" +participant "SDEI client" as EL2 +participant EL3 +participant SDEI +participant "RAS Driver" as RAS + +activate EL2 +EL2->EL3: **SDEI_EVENT_REGISTER**(ev, handler, ...) +EL3->EL2: success +EL2->EL3: **SDEI_EVENT_ENABLE**(ev) +EL3->EL2: success +EL2->EL3: **SDEI_PE_UNMASK**() +EL3->EL2: 1 + +... <> ... + +EL3<--]: **CRITICAL EVENT** +activate EL3 #red +note over EL3: Critical event triage +EL3->RAS: dispatch to handle +deactivate EL3 +activate RAS #salmon +note over RAS: Critical event handling +RAS-->SDEI: sdei_dispatch_event(ev) +deactivate RAS +activate SDEI #salmon +note over SDEI: Prepare SDEI dispatch +SDEI->EL2: dispatch +activate EL2 #salmon +note over EL2: SDEI handler +EL2->SDEI: **SDEI_EVENT_COMPLETE()** +deactivate EL2 +note over SDEI: Complete SDEI dispatch +SDEI-->RAS: return +deactivate SDEI +activate RAS #salmon +RAS->EL3: error handling done +deactivate RAS +EL3->EL2: resumes preempted execution + +... <> ... + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml new file mode 100644 index 0000000..ab6929a --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml @@ -0,0 +1,43 @@ +/' + ' Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +@startuml + +autonumber "[#]" +participant "SDEI client" as EL2 +participant EL3 +participant "SDEI interrupt source" as SDEI + +activate EL2 +EL2->EL3: **SDEI_INTERRUPT_BIND**(irq) +EL3->EL2: event number: ev +EL2->EL3: **SDEI_EVENT_REGISTER**(ev, handler, ...) +EL3->EL2: success +EL2->EL3: **SDEI_EVENT_ENABLE**(ev) +EL3->EL2: success +EL2->EL3: **SDEI_PE_UNMASK**() +EL3->EL2: 1 + +... <> ... + +SDEI-->EL3: SDEI interrupt +activate SDEI #salmon +activate EL3 #red +note over EL3: Prepare SDEI dispatch +EL3->EL2: dispatch +activate EL2 #salmon +note over EL2: SDEI handler +EL2->EL3: **SDEI_EVENT_COMPLETE()** +deactivate EL2 +note over EL3: Complete SDEI dispatch +EL3-->SDEI: EOI +deactivate SDEI +EL3->EL2: resumes preempted execution +deactivate EL3 + +... <> ... + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml new file mode 100644 index 0000000..ad4996e --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml @@ -0,0 +1,82 @@ +/' + ' Copyright (c) 2021, Arm Limited. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +/' +TF-A SPMC Data Flow Diagram +'/ + +@startuml +digraph tfa_dfd { + + # Allow arrows to end on cluster boundaries + compound=true + + # Default settings for edges and nodes + edge [minlen=2 color="#8c1b07"] + node [fillcolor="#ffb866" style=filled shape=box fixedsize=true width=1.6 height=0.7] + + # Nodes outside of the trust boundary + nsec [label="NS Client"] + ddr [label="External memory (DDR)"] + + # Trust boundary cluster + subgraph cluster_trusted { + graph [style=dashed color="#f22430"] + + # HW IPs cluster + subgraph cluster_ip { + label ="Hardware IPs"; + graph [style=filled color="#000000" fillcolor="#ffd29e"] + + rank="same" + gic [label="GIC" width=1.2 height=0.5] + smmu [label="SMMU" width=1.2 height=0.5] + uart [label="UART" width=1.2 height=0.5] + pe [label="PE" width=1.2 height=0.5] + } + + # TF-A cluster + subgraph cluster_tfa { + label ="EL3 monitor"; + graph [style=filled color="#000000" fillcolor="#faf9cd"] + + bl31 [label="BL31" fillcolor="#ddffb3"]; + spmd [label="SPMD" fillcolor="#ddffb3" height=1] + } + + # SPMC cluster + subgraph cluster_spmc { + label ="SPMC"; + graph [style=filled color="#000000" fillcolor="#faf9cd"] + + spmc [label="SPMC" fillcolor="#ddffb3" height=1] + } + bl2 [label="BL2" width=1.2 height=0.5] + } + + # Secure Partitions cluster + subgraph cluster_sp { + label ="Secure Partitions"; + graph [style=filled color="#000000" fillcolor="#faf9cd"] + + sp1 [label="SP1" fillcolor="#ddffb3" height=1] + sp2 [label="SP2" fillcolor="#ddffb3" height=1] + spn [label="SP..." fillcolor="#ddffb3" height=1] + } + + # Interactions between nodes + sp1 -> spmc [dir="both" label="DF1"] + spmc -> spmd [dir="both" label="DF2"] + spmd -> nsec [dir="both" label="DF3"] + sp1 -> sp2 [dir="both" label="DF4"] + spmc -> smmu [lhead=cluster_spmc label="DF5"] + bl2 -> spmc [lhead=cluster_spmc label="DF6"] + bl2 -> spn [lhead=cluster_spmc label="DF6"] + sp1 -> ddr [dir="both" label="DF7"] + spmc -> ddr [dir="both" label="DF7"] +} + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml new file mode 100644 index 0000000..0007911 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml @@ -0,0 +1,66 @@ +/' + ' Copyright (c) 2021, Arm Limited. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +/' +TF-A Data Flow Diagram +'/ + +@startuml +digraph tfa_dfd { + + # Arrange nodes from left to right + rankdir="LR" + + # Allow arrows to end on cluster boundaries + compound=true + + # Default settings for edges and nodes + edge [minlen=2 color="#8c1b07"] + node [fillcolor="#ffb866" style=filled shape=box fixedsize=true width=1.6 height=0.7] + + # Nodes outside of the trust boundary + nsec [label="Non-secure\nClients"] + sec [label="Secure\nClients"] + dbg [label="Debug & Trace"] + logs [label="Logs\n(UART)"] + nvm [label="Non-volatile\nMemory"] + + # Trust boundary cluster + subgraph cluster_trusted{ + graph [style=dashed color="#f22430"] + + # HW IPs cluster + subgraph cluster_ip{ + label ="Hardware IPs"; + graph [style=filled color="#000000" fillcolor="#ffd29e"] + + rank="same" + gic [label="GIC" width=1.2 height=0.5] + tzc [label="TZ\nController" width=1.2 height=0.5] + etc [label="..." shape=none style=none height=0.5] + } + + # TF-A cluster + subgraph cluster_tfa{ + label ="TF-A"; + graph [style=filled color="#000000" fillcolor="#faf9cd"] + + bl1 [label="Boot ROM\n(BL1)" fillcolor="#ddffb3"]; + bl2 [label="Trusted Boot\nFirmware\n(BL2)" fillcolor="#ddffb3" height=1] + bl31 [label="TF-A Runtime\n(BL31)" fillcolor="#ddffb3"] + } + } + + # Interactions between nodes + nvm -> bl31 [lhead=cluster_tfa label="DF1"] + logs -> bl31 [dir="back" lhead=cluster_tfa label="DF2"] + dbg -> bl2 [dir="both" lhead=cluster_tfa label="DF3"] + sec -> bl2 [dir="both" lhead=cluster_tfa label="DF4"] + nsec -> bl1 [dir="both" lhead=cluster_tfa, label="DF5"] + bl2 -> tzc [dir="both" ltail=cluster_tfa lhead=cluster_ip label="DF6" minlen=1] +} + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png b/arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png new file mode 100644 index 0000000..1703ea6 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia b/arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia new file mode 100644 index 0000000..133c9cf Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png b/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png new file mode 100644 index 0000000..23e865f Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_checks.png b/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_checks.png new file mode 100644 index 0000000..26a179b Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_checks.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png b/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png new file mode 100644 index 0000000..4150dbe Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia b/arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia new file mode 100644 index 0000000..d12eec0 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/romlib_design.png b/arm-trusted-firmware/docs/resources/diagrams/romlib_design.png new file mode 100644 index 0000000..bfffcde Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/romlib_design.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia b/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia new file mode 100644 index 0000000..30cfbd8 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png b/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png new file mode 100644 index 0000000..ec3a441 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png b/arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png new file mode 100644 index 0000000..1a9fa5b Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png b/arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png new file mode 100644 index 0000000..fa5c340 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_sp.png b/arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_sp.png new file mode 100644 index 0000000..5cb2ca7 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_sp.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png b/arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png new file mode 100644 index 0000000..1f2d555 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png b/arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png new file mode 100644 index 0000000..58898c5 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/xlat_align.dia b/arm-trusted-firmware/docs/resources/diagrams/xlat_align.dia new file mode 100644 index 0000000..bd88c0c Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/xlat_align.dia differ diff --git a/arm-trusted-firmware/docs/resources/diagrams/xlat_align.png b/arm-trusted-firmware/docs/resources/diagrams/xlat_align.png new file mode 100644 index 0000000..cffd3c1 Binary files /dev/null and b/arm-trusted-firmware/docs/resources/diagrams/xlat_align.png differ diff --git a/arm-trusted-firmware/docs/security_advisories/index.rst b/arm-trusted-firmware/docs/security_advisories/index.rst new file mode 100644 index 0000000..887b06a --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/index.rst @@ -0,0 +1,17 @@ +Security Advisories +=================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + security-advisory-tfv-1.rst + security-advisory-tfv-2.rst + security-advisory-tfv-3.rst + security-advisory-tfv-4.rst + security-advisory-tfv-5.rst + security-advisory-tfv-6.rst + security-advisory-tfv-7.rst + security-advisory-tfv-8.rst + security-advisory-tfv-9.rst diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-1.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-1.rst new file mode 100644 index 0000000..9d58d08 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-1.rst @@ -0,0 +1,162 @@ +Advisory TFV-1 (CVE-2016-10319) +=============================== + ++----------------+-------------------------------------------------------------+ +| Title | Malformed Firmware Update SMC can result in copy of | +| | unexpectedly large data into secure memory | ++================+=============================================================+ +| CVE ID | `CVE-2016-10319`_ | ++----------------+-------------------------------------------------------------+ +| Date | 18 Oct 2016 | ++----------------+-------------------------------------------------------------+ +| Versions | v1.2 and v1.3 (since commit `48bfb88`_) | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | Platforms that use AArch64 BL1 plus untrusted normal world | +| Affected | firmware update code executing before BL31 | ++----------------+-------------------------------------------------------------+ +| Impact | Copy of unexpectedly large data into the free secure memory | +| | reported by BL1 platform code | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #783`_ | ++----------------+-------------------------------------------------------------+ +| Credit | IOActive | ++----------------+-------------------------------------------------------------+ + +Generic Trusted Firmware (TF) BL1 code contains an SMC interface that is briefly +available after cold reset to support the Firmware Update (FWU) feature (also +known as recovery mode). This allows most FWU functionality to be implemented in +the normal world, while retaining the essential image authentication +functionality in BL1. When cold boot reaches the EL3 Runtime Software (for +example, BL31 on AArch64 systems), the FWU SMC interface is replaced by the EL3 +Runtime SMC interface. Platforms may choose how much of this FWU functionality +to use, if any. + +The BL1 FWU SMC handling code, currently only supported on AArch64, contains +several vulnerabilities that may be exploited when *all* the following +conditions apply: + +1. Platform code uses TF BL1 with the ``TRUSTED_BOARD_BOOT`` build option + enabled. + +2. Platform code arranges for untrusted normal world FWU code to be executed in + the cold boot path, before BL31 starts. Untrusted in this sense means code + that is not in ROM or has not been authenticated or has otherwise been + executed by an attacker. + +3. Platform code copies the insecure pattern described below from the ARM + platform version of ``bl1_plat_mem_check()``. + +The vulnerabilities consist of potential integer overflows in the input +validation checks while handling the ``FWU_SMC_IMAGE_COPY`` SMC. The SMC +implementation is designed to copy an image into secure memory for subsequent +authentication, but the vulnerabilities may allow an attacker to copy +unexpectedly large data into secure memory. Note that a separate vulnerability +is required to leverage these vulnerabilities; for example a way to get the +system to change its behaviour based on the unexpected secure memory contents. + +Two of the vulnerabilities are in the function ``bl1_fwu_image_copy()`` in +``bl1/bl1_fwu.c``. These are listed below, referring to the v1.3 tagged version +of the code: + +- Line 155: + + .. code:: c + + /* + * If last block is more than expected then + * clip the block to the required image size. + */ + if (image_desc->copied_size + block_size > + image_desc->image_info.image_size) { + block_size = image_desc->image_info.image_size - + image_desc->copied_size; + WARN("BL1-FWU: Copy argument block_size > remaining image size." + " Clipping block_size\n"); + } + + /* Make sure the image src/size is mapped. */ + if (bl1_plat_mem_check(image_src, block_size, flags)) { + WARN("BL1-FWU: Copy arguments source/size not mapped\n"); + return -ENOMEM; + } + + INFO("BL1-FWU: Continuing image copy in blocks\n"); + + /* Copy image for given block size. */ + base_addr += image_desc->copied_size; + image_desc->copied_size += block_size; + memcpy((void *)base_addr, (const void *)image_src, block_size); + ... + + This code fragment is executed when the image copy operation is performed in + blocks over multiple SMCs. ``block_size`` is an SMC argument and therefore + potentially controllable by an attacker. A very large value may result in an + integer overflow in the 1st ``if`` statement, which would bypass the check, + allowing an unclipped ``block_size`` to be passed into + ``bl1_plat_mem_check()``. If ``bl1_plat_mem_check()`` also passes, this may + result in an unexpectedly large copy of data into secure memory. + +- Line 206: + + .. code:: c + + /* Make sure the image src/size is mapped. */ + if (bl1_plat_mem_check(image_src, block_size, flags)) { + WARN("BL1-FWU: Copy arguments source/size not mapped\n"); + return -ENOMEM; + } + + /* Find out how much free trusted ram remains after BL1 load */ + mem_layout = bl1_plat_sec_mem_layout(); + if ((image_desc->image_info.image_base < mem_layout->free_base) || + (image_desc->image_info.image_base + image_size > + mem_layout->free_base + mem_layout->free_size)) { + WARN("BL1-FWU: Memory not available to copy\n"); + return -ENOMEM; + } + + /* Update the image size. */ + image_desc->image_info.image_size = image_size; + + /* Copy image for given size. */ + memcpy((void *)base_addr, (const void *)image_src, block_size); + ... + + This code fragment is executed during the 1st invocation of the image copy + operation. Both ``block_size`` and ``image_size`` are SMC arguments. A very + large value of ``image_size`` may result in an integer overflow in the 2nd + ``if`` statement, which would bypass the check, allowing execution to proceed. + If ``bl1_plat_mem_check()`` also passes, this may result in an unexpectedly + large copy of data into secure memory. + +If the platform's implementation of ``bl1_plat_mem_check()`` is correct then it +may help prevent the above 2 vulnerabilities from being exploited. However, the +ARM platform version of this function contains a similar vulnerability: + +- Line 88 of ``plat/arm/common/arm_bl1_fwu.c`` in function of + ``bl1_plat_mem_check()``: + + .. code:: c + + while (mmap[index].mem_size) { + if ((mem_base >= mmap[index].mem_base) && + ((mem_base + mem_size) + <= (mmap[index].mem_base + + mmap[index].mem_size))) + return 0; + + index++; + } + ... + + This function checks that the passed memory region is within one of the + regions mapped in by ARM platforms. Here, ``mem_size`` may be the + ``block_size`` passed from ``bl1_fwu_image_copy()``. A very large value of + ``mem_size`` may result in an integer overflow and the function to incorrectly + return success. Platforms that copy this insecure pattern will have the same + vulnerability. + +.. _CVE-2016-10319: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10319 +.. _48bfb88: https://github.com/ARM-software/arm-trusted-firmware/commit/48bfb88 +.. _Pull Request #783: https://github.com/ARM-software/arm-trusted-firmware/pull/783 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst new file mode 100644 index 0000000..0ed2a7f --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst @@ -0,0 +1,61 @@ +Advisory TFV-2 (CVE-2017-7564) +============================== + ++----------------+-------------------------------------------------------------+ +| Title | Enabled secure self-hosted invasive debug interface can | +| | allow normal world to panic secure world | ++================+=============================================================+ +| CVE ID | `CVE-2017-7564`_ | ++----------------+-------------------------------------------------------------+ +| Date | 02 Feb 2017 | ++----------------+-------------------------------------------------------------+ +| Versions | All versions up to v1.3 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Denial of Service (secure world panic) | ++----------------+-------------------------------------------------------------+ +| Fix Version | 15 Feb 2017 `Pull Request #841`_ | ++----------------+-------------------------------------------------------------+ +| Credit | ARM | ++----------------+-------------------------------------------------------------+ + +The ``MDCR_EL3.SDD`` bit controls AArch64 secure self-hosted invasive debug +enablement. By default, the BL1 and BL31 images of the current version of ARM +Trusted Firmware (TF) unconditionally assign this bit to ``0`` in the early +entrypoint code, which enables debug exceptions from the secure world. This can +be seen in the implementation of the ``el3_arch_init_common`` `AArch64 macro`_ . +Given that TF does not currently contain support for this feature (for example, +by saving and restoring the appropriate debug registers), this may allow a +normal world attacker to induce a panic in the secure world. + +The ``MDCR_EL3.SDD`` bit should be assigned to ``1`` to disable debug exceptions +from the secure world. + +Earlier versions of TF (prior to `commit 495f3d3`_) did not assign this bit. +Since the bit has an architecturally ``UNKNOWN`` reset value, earlier versions +may or may not have the same problem, depending on the platform. + +A similar issue applies to the ``MDCR_EL3.SPD32`` bits, which control AArch32 +secure self-hosted invasive debug enablement. TF assigns these bits to ``00`` +meaning that debug exceptions from Secure EL1 are enabled by the authentication +interface. Therefore this issue only exists for AArch32 Secure EL1 code when +secure privileged invasive debug is enabled by the authentication interface, at +which point the device is vulnerable to other, more serious attacks anyway. + +However, given that TF contains no support for handling debug exceptions, the +``MDCR_EL3.SPD32`` bits should be assigned to ``10`` to disable debug exceptions +from AArch32 Secure EL1. + +Finally, this also issue applies to AArch32 platforms that use the TF SP_MIN +image or integrate the `AArch32 equivalent`_ of the ``el3_arch_init_common`` +macro. Here the affected bits are ``SDCR.SPD``, which should also be assigned to +``10`` instead of ``00`` + +.. _CVE-2017-7564: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7564 +.. _commit 495f3d3: https://github.com/ARM-software/arm-trusted-firmware/commit/495f3d3 +.. _AArch64 macro: https://github.com/ARM-software/arm-trusted-firmware/blob/bcc2bf0/include/common/aarch64/el3_common_macros.S#L85 +.. _AArch32 equivalent: https://github.com/ARM-software/arm-trusted-firmware/blob/bcc2bf0/include/common/aarch32/el3_common_macros.S#L41 +.. _Pull Request #841: https://github.com/ARM-software/arm-trusted-firmware/pull/841 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst new file mode 100644 index 0000000..b395f13 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst @@ -0,0 +1,86 @@ +Advisory TFV-3 (CVE-2017-7563) +============================== + ++----------------+-------------------------------------------------------------+ +| Title | RO memory is always executable at AArch64 Secure EL1 | ++================+=============================================================+ +| CVE ID | `CVE-2017-7563`_ | ++----------------+-------------------------------------------------------------+ +| Date | 06 Apr 2017 | ++----------------+-------------------------------------------------------------+ +| Versions | v1.3 (since `Pull Request #662`_) | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | AArch64 BL2, TSP or other users of xlat_tables library | +| Affected | executing at AArch64 Secure EL1 | ++----------------+-------------------------------------------------------------+ +| Impact | Unexpected Privilege Escalation | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #924`_ | ++----------------+-------------------------------------------------------------+ +| Credit | ARM | ++----------------+-------------------------------------------------------------+ + +The translation table library in ARM Trusted Firmware (TF) (under +``lib/xlat_tables`` and ``lib/xlat_tables_v2``) provides APIs to help program +translation tables in the MMU. The xlat\_tables client specifies its required +memory mappings in the form of ``mmap_region`` structures. Each ``mmap_region`` +has memory attributes represented by the ``mmap_attr_t`` enumeration type. This +contains flags to control data access permissions (``MT_RO``/``MT_RW``) and +instruction execution permissions (``MT_EXECUTE``/``MT_EXECUTE_NEVER``). Thus a +mapping specifying both ``MT_RO`` and ``MT_EXECUTE_NEVER`` should result in a +Read-Only (RO), non-executable memory region. + +This feature does not work correctly for AArch64 images executing at Secure EL1. +Any memory region mapped as RO will always be executable, regardless of whether +the client specified ``MT_EXECUTE`` or ``MT_EXECUTE_NEVER``. + +The vulnerability is known to affect the BL2 and Test Secure Payload (TSP) +images on platforms that enable the ``SEPARATE_CODE_AND_RODATA`` build option, +which includes all ARM standard platforms, and the upstream Xilinx and NVidia +platforms. The RO data section for these images on these platforms is +unexpectedly executable instead of non-executable. Other platforms or +``xlat_tables`` clients may also be affected. + +The vulnerability primarily manifests itself after `Pull Request #662`_. Before +that, ``xlat_tables`` clients could not specify instruction execution +permissions separately to data access permissions. All RO normal memory regions +were implicitly executable. Before `Pull Request #662`_. the vulnerability +would only manifest itself for device memory mapped as RO; use of this mapping +is considered rare, although the upstream QEMU platform uses this mapping when +the ``DEVICE2_BASE`` build option is used. + +Note that one or more separate vulnerabilities are also required to exploit this +vulnerability. + +The vulnerability is due to incorrect handling of the execute-never bits in the +translation tables. The EL3 translation regime uses a single ``XN`` bit to +determine whether a region is executable. The Secure EL1&0 translation regime +handles 2 Virtual Address (VA) ranges and so uses 2 bits, ``UXN`` and ``PXN``. +The ``xlat_tables`` library only handles the ``XN`` bit, which maps to ``UXN`` +in the Secure EL1&0 regime. As a result, this programs the Secure EL0 execution +permissions but always leaves the memory as executable at Secure EL1. + +The vulnerability is mitigated by the following factors: + +- The xlat\_tables library ensures that all Read-Write (RW) memory regions are + non-executable by setting the ``SCTLR_ELx.WXN`` bit. This overrides any value + of the ``XN``, ``UXN`` or ``PXN`` bits in the translation tables. See the + ``enable_mmu()`` function: + + :: + + sctlr = read_sctlr_el##_el(); \ + sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT; \ + +- AArch32 configurations are unaffected. Here the ``XN`` bit controls execution + privileges of the currently executing translation regime, which is the desired + behaviour. + +- ARM TF EL3 code (for example BL1 and BL31) ensures that all non-secure memory + mapped into the secure world is non-executable by setting the ``SCR_EL3.SIF`` + bit. See the ``el3_arch_init_common`` macro in ``el3_common_macros.S``. + +.. _CVE-2017-7563: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7563 +.. _Pull Request #662: https://github.com/ARM-software/arm-trusted-firmware/pull/662 +.. _Pull Request #924: https://github.com/ARM-software/arm-trusted-firmware/pull/924 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst new file mode 100644 index 0000000..66dd542 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst @@ -0,0 +1,124 @@ +Advisory TFV-4 (CVE-2017-9607) +============================== + ++----------------+-------------------------------------------------------------+ +| Title | Malformed Firmware Update SMC can result in copy or | +| | authentication of unexpected data in secure memory in | +| | AArch32 state | ++================+=============================================================+ +| CVE ID | `CVE-2017-9607`_ | ++----------------+-------------------------------------------------------------+ +| Date | 20 Jun 2017 | ++----------------+-------------------------------------------------------------+ +| Versions | None (only between 22 May 2017 and 14 June 2017) | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | Platforms that use AArch32 BL1 plus untrusted normal world | +| Affected | firmware update code executing before BL31 | ++----------------+-------------------------------------------------------------+ +| Impact | Copy or authentication of unexpected data in the secure | +| | memory | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #979`_ (merged on 14 June 2017) | ++----------------+-------------------------------------------------------------+ +| Credit | ARM | ++----------------+-------------------------------------------------------------+ + +The ``include/lib/utils_def.h`` header file provides the +``check_uptr_overflow()`` macro, which aims at detecting arithmetic overflows +that may occur when computing the sum of a base pointer and an offset. This +macro evaluates to 1 if the sum of the given base pointer and offset would +result in a value large enough to wrap around, which may lead to unpredictable +behaviour. + +The macro code is at line 52, referring to the version of the code as of `commit +c396b73`_: + +.. code:: c + + /* + * 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)) ? 1 : 0) + +This macro does not work correctly for AArch32 images. It fails to detect +overflows when the sum of its two parameters fall into the ``[2^32, 2^64 - 1]`` +range. Therefore, any AArch32 code relying on this macro to detect such integer +overflows is actually not protected. + +The buggy code has been present in ARM Trusted Firmware (TF) since `Pull Request +#678`_ was merged (on 18 August 2016). However, the upstream code was not +vulnerable until `Pull Request #939`_ was merged (on 22 May 2017), which +introduced AArch32 support for the Trusted Board Boot (TBB) feature. Before +then, the ``check_uptr_overflow()`` macro was not used in AArch32 code. + +The vulnerability resides in the BL1 FWU SMC handling code and it may be +exploited when *all* the following conditions apply: + +- Platform code uses TF BL1 with the ``TRUSTED_BOARD_BOOT`` build option. + +- Platform code uses the Firmware Update (FWU) code provided in + ``bl1/bl1_fwu.c``, which is part of the TBB support. + +- TF BL1 is compiled with the ``ARCH=aarch32`` build option. + +In this context, the AArch32 BL1 image might fail to detect potential integer +overflows in the input validation checks while handling the +``FWU_SMC_IMAGE_COPY`` and ``FWU_SMC_IMAGE_AUTH`` SMCs. + +The ``FWU_SMC_IMAGE_COPY`` SMC handler is designed to copy an image into secure +memory for subsequent authentication. This is implemented by the +``bl1_fwu_image_copy()`` function, which has the following function prototype: + +.. code:: c + + static int bl1_fwu_image_copy(unsigned int image_id, + uintptr_t image_src, + unsigned int block_size, + unsigned int image_size, + unsigned int flags) + +``image_src`` is an SMC argument and therefore potentially controllable by an +attacker. A very large 32-bit value, for example ``2^32 -1``, may result in the +sum of ``image_src`` and ``block_size`` overflowing a 32-bit type, which +``check_uptr_overflow()`` will fail to detect. Depending on its implementation, +the platform-specific function ``bl1_plat_mem_check()`` might get defeated by +these unsanitized values and allow the following memory copy operation, that +would wrap around. This may allow an attacker to copy unexpected data into +secure memory if the memory is mapped in BL1's address space, or cause a fatal +exception if it's not. + +The ``FWU_SMC_IMAGE_AUTH`` SMC handler is designed to authenticate an image +resident in secure memory. This is implemented by the ``bl1_fwu_image_auth()`` +function, which has the following function prototype: + +.. code:: c + + static int bl1_fwu_image_auth(unsigned int image_id, + uintptr_t image_src, + unsigned int image_size, + unsigned int flags) + +Similarly, if an attacker has control over the ``image_src`` or ``image_size`` +arguments through the SMC interface and injects high values whose sum overflows, +they might defeat the ``bl1_plat_mem_check()`` function and make the +authentication module read data outside of what's normally allowed by the +platform code or crash the platform. + +Note that in both cases, a separate vulnerability is required to leverage this +vulnerability; for example a way to get the system to change its behaviour based +on the unexpected secure memory accesses. Moreover, the normal world FWU code +would need to be compromised in order to send a malformed FWU SMC that triggers +an integer overflow. + +The vulnerability is known to affect all ARM standard platforms when enabling +the ``TRUSTED_BOARD_BOOT`` and ``ARCH=aarch32`` build options. Other platforms +may also be affected if they fulfil the above conditions. + +.. _CVE-2017-9607: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9607 +.. _commit c396b73: https://github.com/ARM-software/arm-trusted-firmware/commit/c396b73 +.. _Pull Request #678: https://github.com/ARM-software/arm-trusted-firmware/pull/678 +.. _Pull Request #939: https://github.com/ARM-software/arm-trusted-firmware/pull/939 +.. _Pull Request #979: https://github.com/ARM-software/arm-trusted-firmware/pull/979 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst new file mode 100644 index 0000000..97f7cd9 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst @@ -0,0 +1,57 @@ +Advisory TFV-5 (CVE-2017-15031) +=============================== + ++----------------+-------------------------------------------------------------+ +| Title | Not initializing or saving/restoring ``PMCR_EL0`` can leak | +| | secure world timing information | ++================+=============================================================+ +| CVE ID | `CVE-2017-15031`_ | ++----------------+-------------------------------------------------------------+ +| Date | 02 Oct 2017, updated on 04 Nov 2019 | ++----------------+-------------------------------------------------------------+ +| Versions | All, up to and including v2.1 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Leakage of sensitive secure world timing information | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #1127`_ (merged on 18 October 2017) | +| | | +| | `Commit e290a8fcbc`_ (merged on 23 August 2019) | +| | | +| | `Commit c3e8b0be9b`_ (merged on 27 September 2019) | ++----------------+-------------------------------------------------------------+ +| Credit | Arm, Marek Bykowski | ++----------------+-------------------------------------------------------------+ + +The ``PMCR_EL0`` (Performance Monitors Control Register) provides details of the +Performance Monitors implementation, including the number of counters +implemented, and configures and controls the counters. If the ``PMCR_EL0.DP`` +bit is set to zero, the cycle counter (when enabled) counts during secure world +execution, even when prohibited by the debug signals. + +Since TF-A does not save and restore ``PMCR_EL0`` when switching between the +normal and secure worlds, normal world code can set ``PMCR_EL0.DP`` to zero to +cause leakage of secure world timing information. This register should be added +to the list of saved/restored registers both when entering EL3 and also +transitioning to S-EL1. + +Furthermore, ``PMCR_EL0.DP`` has an architecturally ``UNKNOWN`` reset value. +Since Arm TF does not initialize this register, it's possible that on at least +some implementations, ``PMCR_EL0.DP`` is set to zero by default. This and other +bits with an architecturally UNKNOWN reset value should be initialized to +sensible default values in the secure context. + +The same issue exists for the equivalent AArch32 register, ``PMCR``, except that +here ``PMCR_EL0.DP`` architecturally resets to zero. + +NOTE: The original pull request referenced above only fixed the issue for S-EL1 +whereas the EL3 was fixed in the later commits. + +.. _CVE-2017-15031: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15031 +.. _Pull Request #1127: https://github.com/ARM-software/arm-trusted-firmware/pull/1127 +.. _Commit e290a8fcbc: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=e290a8fcbc +.. _Commit c3e8b0be9b: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=c3e8b0be9b + diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst new file mode 100644 index 0000000..9eeaeec --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst @@ -0,0 +1,148 @@ +Advisory TFV-6 (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754) +============================================================ + ++----------------+-------------------------------------------------------------+ +| Title | Trusted Firmware-A exposure to speculative processor | +| | vulnerabilities using cache timing side-channels | ++================+=============================================================+ +| CVE ID | `CVE-2017-5753`_ / `CVE-2017-5715`_ / `CVE-2017-5754`_ | ++----------------+-------------------------------------------------------------+ +| Date | 03 Jan 2018 (Updated 11 Jan, 18 Jan, 26 Jan, 30 Jan and 07 | +| | June 2018) | ++----------------+-------------------------------------------------------------+ +| Versions | All, up to and including v1.4 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Leakage of secure world data to normal world | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #1214`_, `Pull Request #1228`_, | +| | `Pull Request #1240`_ and `Pull Request #1405`_ | ++----------------+-------------------------------------------------------------+ +| Credit | Google / Arm | ++----------------+-------------------------------------------------------------+ + +This security advisory describes the current understanding of the Trusted +Firmware-A exposure to the speculative processor vulnerabilities identified by +`Google Project Zero`_. To understand the background and wider impact of these +vulnerabilities on Arm systems, please refer to the `Arm Processor Security +Update`_. + +Variant 1 (`CVE-2017-5753`_) +---------------------------- + +At the time of writing, no vulnerable patterns have been observed in upstream TF +code, therefore no workarounds have been applied or are planned. + +Variant 2 (`CVE-2017-5715`_) +---------------------------- + +Where possible on vulnerable CPUs, Arm recommends invalidating the branch +predictor as early as possible on entry into the secure world, before any branch +instruction is executed. There are a number of implementation defined ways to +achieve this. + +For Cortex-A57 and Cortex-A72 CPUs, the Pull Requests (PRs) in this advisory +invalidate the branch predictor when entering EL3 by disabling and re-enabling +the MMU. + +For Cortex-A73 and Cortex-A75 CPUs, the PRs in this advisory invalidate the +branch predictor when entering EL3 by temporarily dropping into AArch32 +Secure-EL1 and executing the ``BPIALL`` instruction. This workaround is +significantly more complex than the "MMU disable/enable" workaround. The latter +is not effective at invalidating the branch predictor on Cortex-A73/Cortex-A75. + +Note that if other privileged software, for example a Rich OS kernel, implements +its own branch predictor invalidation during context switch by issuing an SMC +(to execute firmware branch predictor invalidation), then there is a dependency +on the PRs in this advisory being deployed in order for those workarounds to +work. If that other privileged software is able to workaround the vulnerability +locally (for example by implementing "MMU disable/enable" itself), there is no +such dependency. + +`Pull Request #1240`_ and `Pull Request #1405`_ optimise the earlier fixes by +implementing a specified `CVE-2017-5715`_ workaround SMC +(``SMCCC_ARCH_WORKAROUND_1``) for use by normal world privileged software. This +is more efficient than calling an arbitrary SMC (for example ``PSCI_VERSION``). +Details of ``SMCCC_ARCH_WORKAROUND_1`` can be found in the `CVE-2017-5715 +mitigation specification`_. The specification and implementation also enable +the normal world to discover the presence of this firmware service. + +On Juno R1 we measured the round trip latency for both the ``PSCI_VERSION`` and +``SMCCC_ARCH_WORKAROUND_1`` SMCs on Cortex-A57, using both the "MMU +disable/enable" and "BPIALL at AArch32 Secure-EL1" workarounds described above. +This includes the time spent in test code conforming to the SMC Calling +Convention (SMCCC) from AArch64. For the ``SMCCC_ARCH_WORKAROUND_1`` cases, the +test code uses SMCCC v1.1, which reduces the number of general purpose registers +it needs to save/restore. Although the ``BPIALL`` instruction is not effective +at invalidating the branch predictor on Cortex-A57, the drop into Secure-EL1 +with MMU disabled that this workaround entails effectively does invalidate the +branch predictor. Hence this is a reasonable comparison. + +The results were as follows: + ++------------------------------------------------------------------+-----------+ +| Test | Time (ns) | ++==================================================================+===========+ +| ``PSCI_VERSION`` baseline (without PRs in this advisory) | 515 | ++------------------------------------------------------------------+-----------+ +| ``PSCI_VERSION`` baseline (with PRs in this advisory) | 527 | ++------------------------------------------------------------------+-----------+ +| ``PSCI_VERSION`` with "MMU disable/enable" | 930 | ++------------------------------------------------------------------+-----------+ +| ``SMCCC_ARCH_WORKAROUND_1`` with "MMU disable/enable" | 386 | ++------------------------------------------------------------------+-----------+ +| ``PSCI_VERSION`` with "BPIALL at AArch32 Secure-EL1" | 1276 | ++------------------------------------------------------------------+-----------+ +| ``SMCCC_ARCH_WORKAROUND_1`` with "BPIALL at AArch32 Secure-EL1" | 770 | ++------------------------------------------------------------------+-----------+ + +Due to the high severity and wide applicability of this issue, the above +workarounds are enabled by default (on vulnerable CPUs only), despite some +performance and code size overhead. Platforms can choose to disable them at +compile time if they do not require them. `Pull Request #1240`_ disables the +workarounds for unaffected upstream platforms. + +For vulnerable AArch32-only CPUs (for example Cortex-A8, Cortex-A9 and +Cortex-A17), the ``BPIALL`` instruction should be used as early as possible on +entry into the secure world. For Cortex-A8, also set ``ACTLR[6]`` to 1 during +early processor initialization. Note that the ``BPIALL`` instruction is not +effective at invalidating the branch predictor on Cortex-A15. For that CPU, set +``ACTLR[0]`` to 1 during early processor initialization, and invalidate the +branch predictor by performing an ``ICIALLU`` instruction. + +On AArch32 EL3 systems, the monitor and secure-SVC code is typically tightly +integrated, for example as part of a Trusted OS. Therefore any Variant 2 +workaround should be provided by vendors of that software and is outside the +scope of TF. However, an example implementation in the minimal AArch32 Secure +Payload, ``SP_MIN`` is provided in `Pull Request #1228`_. + +Other Arm CPUs are not vulnerable to this or other variants. This includes +Cortex-A76, Cortex-A53, Cortex-A55, Cortex-A32, Cortex-A7 and Cortex-A5. + +For more information about non-Arm CPUs, please contact the CPU vendor. + +Variant 3 (`CVE-2017-5754`_) +---------------------------- + +This variant is only exploitable between Exception Levels within the same +translation regime, for example between EL0 and EL1, therefore this variant +cannot be used to access secure memory from the non-secure world, and is not +applicable for TF. However, Secure Payloads (for example, Trusted OS) should +provide mitigations on vulnerable CPUs to protect themselves from exploited +Secure-EL0 applications. + +The only Arm CPU vulnerable to this variant is Cortex-A75. + +.. _Google Project Zero: https://googleprojectzero.blogspot.co.uk/2018/01/reading-privileged-memory-with-side.html +.. _Arm Processor Security Update: http://www.arm.com/security-update +.. _CVE-2017-5753: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5753 +.. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715 +.. _CVE-2017-5754: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5754 +.. _Pull Request #1214: https://github.com/ARM-software/arm-trusted-firmware/pull/1214 +.. _Pull Request #1228: https://github.com/ARM-software/arm-trusted-firmware/pull/1228 +.. _Pull Request #1240: https://github.com/ARM-software/arm-trusted-firmware/pull/1240 +.. _Pull Request #1405: https://github.com/ARM-software/arm-trusted-firmware/pull/1405 +.. _CVE-2017-5715 mitigation specification: https://developer.arm.com/cache-speculation-vulnerability-firmware-specification diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst new file mode 100644 index 0000000..8e06762 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst @@ -0,0 +1,107 @@ +Advisory TFV-7 (CVE-2018-3639) +============================== + ++----------------+-------------------------------------------------------------+ +| Title | Trusted Firmware-A exposure to cache speculation | +| | vulnerability Variant 4 | ++================+=============================================================+ +| CVE ID | `CVE-2018-3639`_ | ++----------------+-------------------------------------------------------------+ +| Date | 21 May 2018 (Updated 7 June 2018) | ++----------------+-------------------------------------------------------------+ +| Versions | All, up to and including v1.5 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Leakage of secure world data to normal world | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #1392`_, `Pull Request #1397`_ | ++----------------+-------------------------------------------------------------+ +| Credit | Google | ++----------------+-------------------------------------------------------------+ + +This security advisory describes the current understanding of the Trusted +Firmware-A (TF-A) exposure to Variant 4 of the cache speculation vulnerabilities +identified by `Google Project Zero`_. To understand the background and wider +impact of these vulnerabilities on Arm systems, please refer to the `Arm +Processor Security Update`_. + +At the time of writing, the TF-A project is not aware of a Variant 4 exploit +that could be used against TF-A. It is likely to be very difficult to achieve an +exploit against current standard configurations of TF-A, due to the limited +interfaces into the secure world with attacker-controlled inputs. However, this +is becoming increasingly difficult to guarantee with the introduction of complex +new firmware interfaces, for example the `Software Delegated Exception Interface +(SDEI)`_. Also, the TF-A project does not have visibility of all +vendor-supplied interfaces. Therefore, the TF-A project takes a conservative +approach by mitigating Variant 4 in hardware wherever possible during secure +world execution. The mitigation is enabled by setting an implementation defined +control bit to prevent the re-ordering of stores and loads. + +For each affected CPU type, TF-A implements one of the two following mitigation +approaches in `Pull Request #1392`_ and `Pull Request #1397`_. Both approaches +have a system performance impact, which varies for each CPU type and use-case. +The mitigation code is enabled by default, but can be disabled at compile time +for platforms that are unaffected or where the risk is deemed low enough. + +Arm CPUs not mentioned below are unaffected. + +Static mitigation +----------------- + +For affected CPUs, this approach enables the mitigation during EL3 +initialization, following every PE reset. No mechanism is provided to disable +the mitigation at runtime. + +This approach permanently mitigates the entire software stack and no additional +mitigation code is required in other software components. + +TF-A implements this approach for the following affected CPUs: + +- Cortex-A57 and Cortex-A72, by setting bit 55 (Disable load pass store) of + ``CPUACTLR_EL1`` (``S3_1_C15_C2_0``). + +- Cortex-A73, by setting bit 3 of ``S3_0_C15_C0_0`` (not documented in the + Technical Reference Manual (TRM)). + +- Cortex-A75, by setting bit 35 (reserved in TRM) of ``CPUACTLR_EL1`` + (``S3_0_C15_C1_0``). + +Dynamic mitigation +------------------ + +For affected CPUs, this approach also enables the mitigation during EL3 +initialization, following every PE reset. In addition, this approach implements +``SMCCC_ARCH_WORKAROUND_2`` in the Arm architectural range to allow callers at +lower exception levels to temporarily disable the mitigation in their execution +context, where the risk is deemed low enough. This approach enables mitigation +on entry to EL3, and restores the mitigation state of the lower exception level +on exit from EL3. For more information on this approach, see `Firmware +interfaces for mitigating cache speculation vulnerabilities`_. + +This approach may be complemented by additional mitigation code in other +software components, for example code that calls ``SMCCC_ARCH_WORKAROUND_2``. +However, even without any mitigation code in other software components, this +approach will effectively permanently mitigate the entire software stack, since +the default mitigation state for firmware-managed execution contexts is enabled. + +Since the expectation in this approach is that more software executes with the +mitigation disabled, this may result in better system performance than the +static approach for some systems or use-cases. However, for other systems or +use-cases, this performance saving may be outweighed by the additional overhead +of ``SMCCC_ARCH_WORKAROUND_2`` calls and TF-A exception handling. + +TF-A implements this approach for the following affected CPU: + +- Cortex-A76, by setting and clearing bit 16 (reserved in TRM) of + ``CPUACTLR2_EL1`` (``S3_0_C15_C1_1``). + +.. _Google Project Zero: https://bugs.chromium.org/p/project-zero/issues/detail?id=1528 +.. _Arm Processor Security Update: http://www.arm.com/security-update +.. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639 +.. _Software Delegated Exception Interface (SDEI): http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _Firmware interfaces for mitigating cache speculation vulnerabilities: https://developer.arm.com/cache-speculation-vulnerability-firmware-specification +.. _Pull Request #1392: https://github.com/ARM-software/arm-trusted-firmware/pull/1392 +.. _Pull Request #1397: https://github.com/ARM-software/arm-trusted-firmware/pull/1397 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst new file mode 100644 index 0000000..ebe324e --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst @@ -0,0 +1,103 @@ +Advisory TFV-8 (CVE-2018-19440) +=============================== + ++----------------+-------------------------------------------------------------+ +| Title | Not saving x0 to x3 registers can leak information from one | +| | Normal World SMC client to another | ++================+=============================================================+ +| CVE ID | `CVE-2018-19440`_ | ++----------------+-------------------------------------------------------------+ +| Date | 27 Nov 2018 | ++----------------+-------------------------------------------------------------+ +| Versions | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | Multiple normal world SMC clients calling into AArch64 BL31 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Leakage of SMC return values from one normal world SMC | +| | client to another | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #1710`_ | ++----------------+-------------------------------------------------------------+ +| Credit | Secmation | ++----------------+-------------------------------------------------------------+ + +When taking an exception to EL3, BL31 saves the CPU context. The aim is to +restore it before returning into the lower exception level software that called +into the firmware. However, for an SMC exception, the general purpose registers +``x0`` to ``x3`` are not part of the CPU context saved on the stack. + +As per the `SMC Calling Convention`_, up to 4 values may be returned to the +caller in registers ``x0`` to ``x3``. In TF-A, these return values are written +into the CPU context, typically using one of the ``SMC_RETx()`` macros provided +in the ``include/lib/aarch64/smccc_helpers.h`` header file. + +Before returning to the caller, the ``restore_gp_registers()`` function is +called. It restores the values of all general purpose registers taken from the +CPU context stored on the stack. This includes registers ``x0`` to ``x3``, as +can be seen in the ``lib/el3_runtime/aarch64/context.S`` file at line 339 +(referring to the version of the code as of `commit c385955`_): + +:: + + /* + * This function restores all general purpose registers except x30 from the + * CPU context. x30 register must be explicitly restored by the caller. + */ + func restore_gp_registers + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + +In the case of an SMC handler that does not use all 4 return values, the +remaining ones are left unchanged in the CPU context. As a result, +``restore_gp_registers()`` restores the stale values saved by a previous SMC +request (or asynchronous exception to EL3) that used these return values. + +In the presence of multiple normal world SMC clients, this behaviour might leak +some of the return values from one client to another. For example, if a victim +client first sends an SMC that returns 4 values, a malicious client may then +send a second SMC expecting no return values (for example, a +``SDEI_EVENT_COMPLETE`` SMC) to get the 4 return values of the victim client. + +In general, the responsibility for mitigating threats due to the presence of +multiple normal world SMC clients lies with EL2 software. When present, EL2 +software must trap SMC calls from EL1 software to ensure secure behaviour. + +For this reason, TF-A does not save ``x0`` to ``x3`` in the CPU context on an +SMC synchronous exception. It has behaved this way since the first version. + +We can confirm that at least upstream KVM-based systems mitigate this threat, +and are therefore unaffected by this issue. Other EL2 software should be audited +to assess the impact of this threat. + +EL2 software might find mitigating this threat somewhat onerous, because for all +SMCs it would need to be aware of which return registers contain valid data, so +it can sanitise any unused return registers. On the other hand, mitigating this +in EL3 is relatively easy and cheap. Therefore, TF-A will now ensure that no +information is leaked through registers ``x0`` to ``x3``, by preserving the +register state over the call. + +Note that AArch32 TF-A is not affected by this issue. The SMC handling code in +``SP_MIN`` already saves all general purpose registers - including ``r0`` to +``r3``, as can be seen in the ``include/lib/aarch32/smccc_macros.S`` file at +line 19 (referring to the version of the code as of `commit c385955`_): + +.. code:: c + + /* + * Macro to save the General purpose registers (r0 - r12), the banked + * spsr, lr, sp registers and the `scr` register to the SMC context on entry + * due a SMC call. The `lr` of the current mode (monitor) is expected to be + * already saved. The `sp` must point to the `smc_ctx_t` to save to. + * Additionally, also save the 'pmcr' register as this is updated whilst + * executing in the secure world. + */ + .macro smccc_save_gp_mode_regs + /* Save r0 - r12 in the SMC context */ + stm sp, {r0-r12} + +.. _CVE-2018-19440: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19440 +.. _commit c385955: https://github.com/ARM-software/arm-trusted-firmware/commit/c385955 +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _Pull Request #1710: https://github.com/ARM-software/arm-trusted-firmware/pull/1710 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst new file mode 100644 index 0000000..74b85dc --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst @@ -0,0 +1,104 @@ +Advisory TFV-9 (CVE-2022-23960) +============================================================ + ++----------------+-------------------------------------------------------------+ +| Title | Trusted Firmware-A exposure to speculative processor | +| | vulnerabilities with branch prediction target reuse | ++================+=============================================================+ +| CVE ID | `CVE-2022-23960`_ | ++----------------+-------------------------------------------------------------+ +| Date | 08 Mar 2022 | ++----------------+-------------------------------------------------------------+ +| Versions | All, up to and including v2.6 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Potential leakage of secure world data to normal world | +| | if an attacker is able to find a TF-A exfiltration primitive| +| | that can be predicted as a valid branch target, and somehow | +| | induce misprediction onto that primitive. There are | +| | currently no known exploits. | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Gerrit topic #spectre_bhb`_ | ++----------------+-------------------------------------------------------------+ +| Credit | Systems and Network Security Group at Vrije Universiteit | +| | Amsterdam for CVE-2022-23960, Arm for patches | ++----------------+-------------------------------------------------------------+ + +This security advisory describes the current understanding of the Trusted +Firmware-A exposure to the new speculative processor vulnerability. +To understand the background and wider impact of these vulnerabilities on Arm +systems, please refer to the `Arm Processor Security Update`_. The whitepaper +referred to below describes the Spectre attack and mitigation in more detail +including implementation specific mitigation details for all impacted Arm CPUs. + + +`CVE-2022-23960`_ +----------------- + +Where possible on vulnerable CPUs that implement FEAT_CSV2, Arm recommends +inserting a loop workaround with implementation specific number of iterations +that will discard the branch history on exception entry to a higher exception +level for the given CPU. This is done as early as possible on entry into EL3, +before any branch instruction is executed. This is sufficient to mitigate +Spectre-BHB on behalf of all secure world code, assuming that no secure world +code is under attacker control. + +The below table lists the CPUs that mitigate against this vulnerability in +TF-A using the loop workaround(all cores that implement FEAT_CSV2 except the +revisions of Cortex-A73 and Cortex-A75 that implements FEAT_CSV2). + ++----------------------+ +| Core | ++----------------------+ +| Cortex-A72(from r1p0)| ++----------------------+ +| Cortex-A76 | ++----------------------+ +| Cortex-A77 | ++----------------------+ +| Cortex-A78 | ++----------------------+ +| Cortex-X2 | ++----------------------+ +| Cortex-A710 | ++----------------------+ +| Neoverse-N1 | ++----------------------+ +| Neoverse-N2 | ++----------------------+ +| Neoverse-V1 | ++----------------------+ + +For all other cores impacted by Spectre-BHB, some of which that do not implement +FEAT_CSV2 and some that do e.g. Cortex-A73, the recommended mitigation is to +flush all branch predictions via an implementation specific route. + +In case local workaround is not feasible, the Rich OS can invoke the SMC +(``SMCCC_ARCH_WORKAROUND_3``) to apply the workaround. Refer to `SMCCC Calling +Convention specification`_ for more details. + +`Gerrit topic #spectre_bhb`_ This patchset implements the Spectre-BHB loop +workaround for CPUs mentioned in the above table. It also mitigates against +this vulnerability for Cortex-A72 CPU versions that support the CSV2 feature +(from r1p0). The patch stack also includes an implementation for a specified +`CVE-2022-23960`_ workaround SMC(``SMCCC_ARCH_WORKAROUND_3``) for use by normal +world privileged software. Details of ``SMCCC_ARCH_WORKAROUND_3`` can be found +in the `SMCCC Calling Convention specification`_. The specification and +implementation also enables the normal world to discover the presence of this +firmware service. This patch also implements ``SMCCC_ARCH_WORKAROUND_3`` for +Cortex-A57, Coxtex-A72, Cortex-A73 and Cortex-A75 using the existing workaround. +for CVE-2017-5715. + +The above workaround is enabled by default (on vulnerable CPUs only). Platforms +can choose to disable them at compile time if they do not require them. + +For more information about non-Arm CPUs, please contact the CPU vendor. + +.. _Arm Processor Security Update: http://www.arm.com/security-update +.. _CVE-2022-23960: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23960 +.. _Gerrit topic #spectre_bhb: https://review.trustedfirmware.org/q/topic:"spectre_bhb"+(status:open%20OR%20status:merged) +.. _CVE-2022-23960 mitigation specification: https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability +.. _SMCCC Calling Convention specification: https://developer.arm.com/documentation/den0028/latest diff --git a/arm-trusted-firmware/docs/threat_model/index.rst b/arm-trusted-firmware/docs/threat_model/index.rst new file mode 100644 index 0000000..335937e --- /dev/null +++ b/arm-trusted-firmware/docs/threat_model/index.rst @@ -0,0 +1,22 @@ +Threat Model +============ + +Threat modeling is an important part of Secure Development Lifecycle (SDL) +that helps us identify potential threats and mitigations affecting a system. + +In the next sections, we first give a description of the target of evaluation +using a data flow diagram. Then we provide a list of threats we have identified +based on the data flow diagram and potential threat mitigations. + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + threat_model + threat_model_spm + threat_model_fvp_r + +-------------- + +*Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/threat_model/threat_model.rst b/arm-trusted-firmware/docs/threat_model/threat_model.rst new file mode 100644 index 0000000..072babc --- /dev/null +++ b/arm-trusted-firmware/docs/threat_model/threat_model.rst @@ -0,0 +1,788 @@ +Generic Threat Model +******************** + +************************ +Introduction +************************ +This document provides a generic threat model for TF-A firmware. + +.. note:: + + This threat model doesn't consider Root and Realm worlds introduced by + :ref:`Realm Management Extension (RME)`. + +************************ +Target of Evaluation +************************ +In this threat model, the target of evaluation is the Trusted +Firmware for A-class Processors (TF-A). This includes the boot ROM (BL1), +the trusted boot firmware (BL2) and the runtime EL3 firmware (BL31) as +shown on Figure 1. Everything else on Figure 1 is outside of the scope of +the evaluation. + +TF-A can be configured in various ways. In this threat model we consider +only the most basic configuration. To that end we make the following +assumptions: + +- All TF-A images are run from either ROM or on-chip trusted SRAM. This means + TF-A is not vulnerable to an attacker that can probe or tamper with off-chip + memory. + +- Trusted boot is enabled. This means an attacker can't boot arbitrary images + that are not approved by platform providers. + +- There is no Secure-EL2. We don't consider threats that may come with + Secure-EL2 software. + +Data Flow Diagram +====================== +Figure 1 shows a high-level data flow diagram for TF-A. The diagram +shows a model of the different components of a TF-A-based system and +their interactions with TF-A. A description of each diagram element +is given on Table 1. On the diagram, the red broken lines indicate +trust boundaries. Components outside of the broken lines +are considered untrusted by TF-A. + +.. uml:: ../resources/diagrams/plantuml/tfa_dfd.puml + :caption: Figure 1: TF-A Data Flow Diagram + +.. table:: Table 1: TF-A Data Flow Diagram Description + + +-----------------+--------------------------------------------------------+ + | Diagram Element | Description | + +=================+========================================================+ + | ``DF1`` | | At boot time, images are loaded from non-volatile | + | | memory and verified by TF-A boot firmware. These | + | | images include TF-A BL2 and BL31 images, as well as | + | | other secure and non-secure images. | + +-----------------+--------------------------------------------------------+ + | ``DF2`` | | TF-A log system framework outputs debug messages | + | | over a UART interface. | + +-----------------+--------------------------------------------------------+ + | ``DF3`` | | Debug and trace IP on a platform can allow access | + | | to registers and memory of TF-A. | + +-----------------+--------------------------------------------------------+ + | ``DF4`` | | Secure world software (e.g. trusted OS) interact | + | | with TF-A through SMC call interface and/or shared | + | | memory. | + +-----------------+--------------------------------------------------------+ + | ``DF5`` | | Non-secure world software (e.g. rich OS) interact | + | | with TF-A through SMC call interface and/or shared | + | | memory. | + +-----------------+--------------------------------------------------------+ + | ``DF6`` | | This path represents the interaction between TF-A and| + | | various hardware IPs such as TrustZone controller | + | | and GIC. At boot time TF-A configures/initializes the| + | | IPs and interacts with them at runtime through | + | | interrupts and registers. | + +-----------------+--------------------------------------------------------+ + + +********************* +Threat Analysis +********************* +In this section we identify and provide assessment of potential threats to TF-A +firmware. The threats are identified for each diagram element on the +data flow diagram above. + +For each threat, we identify the *asset* that is under threat, the +*threat agent* and the *threat type*. Each threat is given a *risk rating* +that represents the impact and likelihood of that threat. We also discuss +potential mitigations. + +Assets +================== +We have identified the following assets for TF-A: + +.. table:: Table 2: TF-A Assets + + +--------------------+---------------------------------------------------+ + | Asset | Description | + +====================+===================================================+ + | ``Sensitive Data`` | | These include sensitive data that an attacker | + | | must not be able to tamper with (e.g. the Root | + | | of Trust Public Key) or see (e.g. secure logs, | + | | debugging information such as crash reports). | + +--------------------+---------------------------------------------------+ + | ``Code Execution`` | | This represents the requirement that the | + | | platform should run only TF-A code approved by | + | | the platform provider. | + +--------------------+---------------------------------------------------+ + | ``Availability`` | | This represents the requirement that TF-A | + | | services should always be available for use. | + +--------------------+---------------------------------------------------+ + +Threat Agents +===================== +To understand the attack surface, it is important to identify potential +attackers, i.e. attack entry points. The following threat agents are +in scope of this threat model. + +.. table:: Table 3: Threat Agents + + +-------------------+-------------------------------------------------------+ + | Threat Agent | Description | + +===================+=======================================================+ + | ``NSCode`` | | Malicious or faulty code running in the Non-secure | + | | world, including NS-EL0 NS-EL1 and NS-EL2 levels | + +-------------------+-------------------------------------------------------+ + | ``SecCode`` | | Malicious or faulty code running in the secure | + | | world, including S-EL0 and S-EL1 levels | + +-------------------+-------------------------------------------------------+ + | ``AppDebug`` | | Physical attacker using debug signals to access | + | | TF-A resources | + +-------------------+-------------------------------------------------------+ + | ``PhysicalAccess``| | Physical attacker having access to external device | + | | communication bus and to external flash | + | | communication bus using common hardware | + +-------------------+-------------------------------------------------------+ + +.. note:: + + In this threat model an advanced physical attacker that has the capability + to tamper with a hardware (e.g. "rewiring" a chip using a focused + ion beam (FIB) workstation or decapsulate the chip using chemicals) is + considered out-of-scope. + +Threat Types +======================== +In this threat model we categorize threats using the `STRIDE threat +analysis technique`_. In this technique a threat is categorized as one +or more of these types: ``Spoofing``, ``Tampering``, ``Repudiation``, +``Information disclosure``, ``Denial of service`` or +``Elevation of privilege``. + +Threat Risk Ratings +======================== +For each threat identified, a risk rating that ranges +from *informational* to *critical* is given based on the likelihood of the +threat occuring if a mitigation is not in place, and the impact of the +threat (i.e. how severe the consequences could be). Table 4 explains each +rating in terms of score, impact and likelihood. + +.. table:: Table 4: Rating and score as applied to impact and likelihood + + +-----------------------+-------------------------+---------------------------+ + | **Rating (Score)** | **Impact** | **Likelihood** | + +=======================+=========================+===========================+ + | ``Critical (5)`` | | Extreme impact to | | Threat is almost | + | | entire organization | certain to be exploited.| + | | if exploited. | | + | | | | Knowledge of the threat | + | | | and how to exploit it | + | | | are in the public | + | | | domain. | + +-----------------------+-------------------------+---------------------------+ + | ``High (4)`` | | Major impact to entire| | Threat is relatively | + | | organization or single| easy to detect and | + | | line of business if | exploit by an attacker | + | | exploited | with little skill. | + +-----------------------+-------------------------+---------------------------+ + | ``Medium (3)`` | | Noticeable impact to | | A knowledgeable insider | + | | line of business if | or expert attacker could| + | | exploited. | exploit the threat | + | | | without much difficulty.| + +-----------------------+-------------------------+---------------------------+ + | ``Low (2)`` | | Minor damage if | | Exploiting the threat | + | | exploited or could | would require | + | | be used in conjunction| considerable expertise | + | | with other | and resources | + | | vulnerabilities to | | + | | perform a more serious| | + | | attack | | + +-----------------------+-------------------------+---------------------------+ + | ``Informational (1)`` | | Poor programming | | Threat is not likely | + | | practice or poor | to be exploited on its | + | | design decision that | own, but may be used to | + | | may not represent an | gain information for | + | | immediate risk on its | launching another | + | | own, but may have | attack | + | | security implications | | + | | if multiplied and/or | | + | | combined with other | | + | | threats. | | + +-----------------------+-------------------------+---------------------------+ + +Aggregate risk scores are assigned to identified threats; +specifically, the impact score multiplied by the likelihood score. +For example, a threat with high likelihood and low impact would have an +aggregate risk score of eight (8); that is, four (4) for high likelihood +multiplied by two (2) for low impact. The aggregate risk score determines +the finding's overall risk level, as shown in the following table. + +.. table:: Table 5: Overall risk levels and corresponding aggregate scores + + +---------------------+-----------------------------------+ + | Overall Risk Level | Aggregate Risk Score | + | | (Impact multiplied by Likelihood) | + +=====================+===================================+ + | Critical | 20–25 | + +---------------------+-----------------------------------+ + | High | 12–19 | + +---------------------+-----------------------------------+ + | Medium | 6–11 | + +---------------------+-----------------------------------+ + | Low | 2–5 | + +---------------------+-----------------------------------+ + | Informational | 1 | + +---------------------+-----------------------------------+ + +The likelihood and impact of a threat depends on the +target environment in which TF-A is running. For example, attacks +that require physical access are unlikely in server environments while +they are more common in Internet of Things(IoT) environments. +In this threat model we consider three target environments: +``Internet of Things(IoT)``, ``Mobile`` and ``Server``. + +Threat Assessment +============================ +The following threats were identified by applying STRIDE analysis on +each diagram element of the data flow diagram. + ++------------------------+----------------------------------------------------+ +| ID | 01 | ++========================+====================================================+ +| ``Threat`` | | **An attacker can mangle firmware images to | +| | execute arbitrary code** | +| | | +| | | Some TF-A images are loaded from external | +| | storage. It is possible for an attacker to access| +| | the external flash memory and change its contents| +| | physically, through the Rich OS, or using the | +| | updating mechanism to modify the non-volatile | +| | images to execute arbitrary code. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF4, DF5 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | BL2, BL31 | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Code Execution | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | PhysicalAccess, NSCode, SecCode | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering, Elevation of Privilege | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Critical (25) | Critical (25) | Critical (25) | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | | TF-A implements the `Trusted Board Boot (TBB)`_ | +| | feature which prevents malicious firmware from | +| | running on the platform by authenticating all | +| | firmware images. In addition to this, the TF-A | +| | boot firmware performs extra checks on | +| | unauthenticated data, such as FIP metadata, prior| +| | to use. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 02 | ++========================+====================================================+ +| ``Threat`` | | **An attacker may attempt to boot outdated, | +| | potentially vulnerable firmware image** | +| | | +| | | When updating firmware, an attacker may attempt | +| | to rollback to an older version that has unfixed | +| | vulnerabilities. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF4, DF5 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | BL2, BL31 | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Code Execution | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | PhysicalAccess, NSCode, SecCode | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Critical (25) | Critical (25) | Critical (25) | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | | TF-A supports anti-rollback protection using | +| | non-volatile counters (NV counters) as required | +| | by `TBBR-Client specification`_. After a firmware| +| | image is validated, the image revision number | +| | taken from a certificate extension field is | +| | compared with the corresponding NV counter stored| +| | in hardware to make sure the new counter value is| +| | larger or equal to the current counter value. | +| | Platforms must implement this protection using | +| | platform specific hardware NV counters. | ++------------------------+----------------------------------------------------+ + ++------------------------+-------------------------------------------------------+ +| ID | 03 | ++========================+=======================================================+ +| ``Threat`` | | **An attacker can use Time-of-Check-Time-of-Use | +| | (TOCTOU) attack to bypass image authentication | +| | during the boot process** | +| | | +| | | Time-of-Check-Time-of-Use (TOCTOU) threats occur | +| | when the security check is produced before the time | +| | the resource is accessed. If an attacker is sitting | +| | in the middle of the off-chip images, they could | +| | change the binary containing executable code right | +| | after the integrity and authentication check has | +| | been performed. | ++------------------------+-------------------------------------------------------+ +| ``Diagram Elements`` | DF1 | ++------------------------+-------------------------------------------------------+ +| ``Affected TF-A | BL1, BL2 | +| Components`` | | ++------------------------+-------------------------------------------------------+ +| ``Assets`` | Code Execution, Sensitive Data | ++------------------------+-------------------------------------------------------+ +| ``Threat Agent`` | PhysicalAccess | ++------------------------+-------------------------------------------------------+ +| ``Threat Type`` | Elevation of Privilege | ++------------------------+---------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+---------------------+-----------------+---------------+ +| ``Impact`` | N/A | Critical (5) | Critical (5) | ++------------------------+---------------------+-----------------+---------------+ +| ``Likelihood`` | N/A | Medium (3) | Medium (3) | ++------------------------+---------------------+-----------------+---------------+ +| ``Total Risk Rating`` | N/A | High (15) | High (15) | ++------------------------+---------------------+-----------------+---------------+ +| ``Mitigations`` | | TF-A boot firmware copies image to on-chip | +| | memory before authenticating an image. | ++------------------------+-------------------------------------------------------+ + ++------------------------+-------------------------------------------------------+ +| ID | 04 | ++========================+=======================================================+ +| ``Threat`` | | **An attacker with physical access can execute | +| | arbitrary image by bypassing the signature | +| | verification stage using glitching techniques** | +| | | +| | | Glitching (Fault injection) attacks attempt to put | +| | a hardware into a undefined state by manipulating an| +| | environmental variable such as power supply. | +| | | +| | | TF-A relies on a chain of trust that starts with the| +| | ROTPK, which is the key stored inside the chip and | +| | the root of all validation processes. If an attacker| +| | can break this chain of trust, they could execute | +| | arbitrary code on the device. This could be | +| | achieved with physical access to the device by | +| | attacking the normal execution flow of the | +| | process using glitching techniques that target | +| | points where the image is validated against the | +| | signature. | ++------------------------+-------------------------------------------------------+ +| ``Diagram Elements`` | DF1 | ++------------------------+-------------------------------------------------------+ +| ``Affected TF-A | BL1, BL2 | +| Components`` | | ++------------------------+-------------------------------------------------------+ +| ``Assets`` | Code Execution | ++------------------------+-------------------------------------------------------+ +| ``Threat Agent`` | PhysicalAccess | ++------------------------+-------------------------------------------------------+ +| ``Threat Type`` | Tampering, Elevation of Privilege | ++------------------------+---------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+---------------------+-----------------+---------------+ +| ``Impact`` | N/A | Critical (5) | Critical (5) | ++------------------------+---------------------+-----------------+---------------+ +| ``Likelihood`` | N/A | Medium (3) | Medium (3) | ++------------------------+---------------------+-----------------+---------------+ +| ``Total Risk Rating`` | N/A | High (15) | High (15) | ++------------------------+---------------------+-----------------+---------------+ +| ``Mitigations`` | | The most effective mitigation is adding glitching | +| | detection and mitigation circuit at the hardware | +| | level. However, software techniques, | +| | such as adding redundant checks when performing | +| | conditional branches that are security sensitive, | +| | can be used to harden TF-A against such attacks. | +| | **At the moment TF-A doesn't implement such | +| | mitigations.** | ++------------------------+-------------------------------------------------------+ + ++------------------------+---------------------------------------------------+ +| ID | 05 | ++========================+===================================================+ +| ``Threat`` | | **Information leak via UART logs such as | +| | crashes** | +| | | +| | | During the development stages of software it is | +| | common to include crash reports with detailed | +| | information of the CPU state including current | +| | values of the registers, privilege level and | +| | stack dumps. This information is useful when | +| | debugging problems before releasing the | +| | production version, but it could be used by an | +| | attacker to develop a working exploit if left | +| | in the production version. | ++------------------------+---------------------------------------------------+ +| ``Diagram Elements`` | DF2 | ++------------------------+---------------------------------------------------+ +| ``Affected TF-A | BL1, BL2, BL31 | +| Components`` | | ++------------------------+---------------------------------------------------+ +| ``Assets`` | Sensitive Data | ++------------------------+---------------------------------------------------+ +| ``Threat Agent`` | AppDebug | ++------------------------+---------------------------------------------------+ +| ``Threat Type`` | Information Disclosure | ++------------------------+------------------+----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+------------------+----------------+---------------+ +| ``Impact`` | N/A | Low (2) | Low (2) | ++------------------------+------------------+----------------+---------------+ +| ``Likelihood`` | N/A | High (4) | High (4) | ++------------------------+------------------+----------------+---------------+ +| ``Total Risk Rating`` | N/A | Medium (8) | Medium (8) | ++------------------------+------------------+----------------+---------------+ +| ``Mitigations`` | | In TF-A, crash reporting is only enabled for | +| | debug builds by default. Alternatively, the log | +| | level can be tuned at build time (from verbose | +| | to no output at all), independently of the | +| | build type. | ++------------------------+---------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 06 | ++========================+====================================================+ +| ``Threat`` | | **An attacker can read sensitive data and | +| | execute arbitrary code through the external | +| | debug and trace interface** | +| | | +| | | Arm processors include hardware-assisted debug | +| | and trace features that can be controlled without| +| | the need for software operating on the platform. | +| | If left enabled without authentication, this | +| | feature can be used by an attacker to inspect and| +| | modify TF-A registers and memory allowing the | +| | attacker to read sensitive data and execute | +| | arbitrary code. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | BL1, BL2, BL31 | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Code Execution, Sensitive Data | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | AppDebug | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering, Information Disclosure, | +| | Elevation of privilege | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | N/A | High (4) | High (4) | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | N/A | Critical (5) | Critical (5) | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | N/A | Critical (20) | Critical (20) | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | | Configuration of debug and trace capabilities is | +| | platform specific. Therefore, platforms must | +| | disable the debug and trace capability for | +| | production releases or enable proper debug | +| | authentication as recommended by [`DEN0034`_]. | ++------------------------+----------------------------------------------------+ + ++------------------------+------------------------------------------------------+ +| ID | 07 | ++========================+======================================================+ +| ``Threat`` | | **An attacker can perform a denial-of-service | +| | attack by using a broken SMC call that causes the | +| | system to reboot or enter into unknown state.** | +| | | +| | | Secure and non-secure clients access TF-A services | +| | through SMC calls. Malicious code can attempt to | +| | place the TF-A runtime into an inconsistent state | +| | by calling unimplemented SMC call or by passing | +| | invalid arguments. | ++------------------------+------------------------------------------------------+ +| ``Diagram Elements`` | DF4, DF5 | ++------------------------+------------------------------------------------------+ +| ``Affected TF-A | BL31 | +| Components`` | | ++------------------------+------------------------------------------------------+ +| ``Assets`` | Availability | ++------------------------+------------------------------------------------------+ +| ``Threat Agent`` | NSCode, SecCode | ++------------------------+------------------------------------------------------+ +| ``Threat Type`` | Denial of Service | ++------------------------+-------------------+----------------+-----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-------------------+----------------+-----------------+ +| ``Impact`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+-----------------+ +| ``Likelihood`` | High (4) | High (4) | High (4) | ++------------------------+-------------------+----------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | High (12) | ++------------------------+-------------------+----------------+-----------------+ +| ``Mitigations`` | | The generic TF-A code validates SMC function ids | +| | and arguments before using them. | +| | Platforms that implement SiP services must also | +| | validate SMC call arguments. | ++------------------------+------------------------------------------------------+ + ++------------------------+------------------------------------------------------+ +| ID | 08 | ++========================+======================================================+ +| ``Threat`` | | **Memory corruption due to memory overflows and | +| | lack of boundary checking when accessing resources | +| | could allow an attacker to execute arbitrary code, | +| | modify some state variable to change the normal | +| | flow of the program, or leak sensitive | +| | information** | +| | | +| | | Like in other software, the Trusted Firmware has | +| | multiple points where memory corruption security | +| | errors can arise. Memory corruption is a dangerous | +| | security issue since it could allow an attacker | +| | to execute arbitrary code, modify some state | +| | variable to change the normal flow of the program, | +| | or leak sensitive information. | +| | | +| | | Some of the errors include integer overflow, | +| | buffer overflow, incorrect array boundary checks, | +| | and incorrect error management. | +| | Improper use of asserts instead of proper input | +| | validations might also result in these kinds of | +| | errors in release builds. | ++------------------------+------------------------------------------------------+ +| ``Diagram Elements`` | DF4, DF5 | ++------------------------+------------------------------------------------------+ +| ``Affected TF-A | BL1, BL2, BL31 | +| Components`` | | ++------------------------+------------------------------------------------------+ +| ``Assets`` | Code Execution, Sensitive Data | ++------------------------+------------------------------------------------------+ +| ``Threat Agent`` | NSCode, SecCode | ++------------------------+------------------------------------------------------+ +| ``Threat Type`` | Tampering, Information Disclosure, | +| | Elevation of Privilege | ++------------------------+-------------------+-----------------+----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-------------------+-----------------+----------------+ +| ``Impact`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+-------------------+-----------------+----------------+ +| ``Likelihood`` | Medium (3 | Medium (3) | Medium (3) | ++------------------------+-------------------+-----------------+----------------+ +| ``Total Risk Rating`` | High (15) | High (15) | High (15) | ++------------------------+-------------------+-----------------+----------------+ +| ``Mitigations`` | | TF-A uses a combination of manual code reviews and | +| | automated program analysis and testing to detect | +| | and fix memory corruption bugs. All TF-A code | +| | including platform code go through manual code | +| | reviews. Additionally, static code analysis is | +| | performed using Coverity Scan on all TF-A code. | +| | The code is also tested with | +| | `Trusted Firmware-A Tests`_ on Juno and FVP | +| | platforms. | +| | | +| | | Data received from normal world, such as addresses | +| | and sizes identifying memory regions, are | +| | sanitized before being used. These security checks | +| | make sure that the normal world software does not | +| | access memory beyond its limit. | +| | | +| | | By default *asserts* are only used to check for | +| | programming errors in debug builds. Other types of | +| | errors are handled through condition checks that | +| | remain enabled in release builds. See | +| | `TF-A error handling policy`_. TF-A provides an | +| | option to use *asserts* in release builds, however | +| | we recommend using proper runtime checks instead | +| | of relying on asserts in release builds. | ++------------------------+------------------------------------------------------+ + ++------------------------+------------------------------------------------------+ +| ID | 09 | ++========================+======================================================+ +| ``Threat`` | | **Improperly handled SMC calls can leak register | +| | contents** | +| | | +| | | When switching between secure and non-secure | +| | states, register contents of Secure world or | +| | register contents of other normal world clients | +| | can be leaked. | ++------------------------+------------------------------------------------------+ +| ``Diagram Elements`` | DF5 | ++------------------------+------------------------------------------------------+ +| ``Affected TF-A | BL31 | +| Components`` | | ++------------------------+------------------------------------------------------+ +| ``Assets`` | Sensitive Data | ++------------------------+------------------------------------------------------+ +| ``Threat Agent`` | NSCode | ++------------------------+------------------------------------------------------+ +| ``Threat Type`` | Information Disclosure | ++------------------------+-------------------+----------------+-----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-------------------+----------------+-----------------+ +| ``Impact`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+-----------------+ +| ``Likelihood`` | High (4) | High (4) | High (4) | ++------------------------+-------------------+----------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | High (12) | ++------------------------+-------------------+----------------+-----------------+ +| ``Mitigations`` | | TF-A saves and restores registers | +| | by default when switching contexts. Build options | +| | are also provided to save/restore additional | +| | registers such as floating-point registers. | ++------------------------+------------------------------------------------------+ + ++------------------------+-----------------------------------------------------+ +| ID | 10 | ++========================+=====================================================+ +| ``Threat`` | | **SMC calls can leak sensitive information from | +| | TF-A memory via microarchitectural side channels**| +| | | +| | | Microarchitectural side-channel attacks such as | +| | `Spectre`_ can be used to leak data across | +| | security boundaries. An attacker might attempt to | +| | use this kind of attack to leak sensitive | +| | data from TF-A memory. | ++------------------------+-----------------------------------------------------+ +| ``Diagram Elements`` | DF4, DF5 | ++------------------------+-----------------------------------------------------+ +| ``Affected TF-A | BL31 | +| Components`` | | ++------------------------+-----------------------------------------------------+ +| ``Assets`` | Sensitive Data | ++------------------------+-----------------------------------------------------+ +| ``Threat Agent`` | SecCode, NSCode | ++------------------------+-----------------------------------------------------+ +| ``Threat Type`` | Information Disclosure | ++------------------------+-------------------+----------------+----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-------------------+----------------+----------------+ +| ``Impact`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+----------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+----------------+ +| ``Total Risk Rating`` | Medium (9) | Medium (9) | Medium (9) | ++------------------------+-------------------+----------------+----------------+ +| ``Mitigations`` | | TF-A implements software mitigations for Spectre | +| | type attacks as recommended by `Cache Speculation | +| | Side-channels`_ for the generic code. SiPs should | +| | implement similar mitigations for code that is | +| | deemed to be vulnerable to such attacks. | ++------------------------+-----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 11 | ++========================+====================================================+ +| ``Threat`` | | **Misconfiguration of the Memory Management Unit | +| | (MMU) may allow a normal world software to | +| | access sensitive data or execute arbitrary | +| | code** | +| | | +| | | A misconfiguration of the MMU could | +| | lead to an open door for software running in the | +| | normal world to access sensitive data or even | +| | execute code if the proper security mechanisms | +| | are not in place. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF5, DF6 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | BL1, BL2, BL31 | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Sensitive Data, Code execution | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NSCode | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information Disclosure, Elevation of Privilege | ++------------------------+-----------------+-----------------+----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-----------------+-----------------+----------------+ +| ``Impact`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+-----------------+-----------------+----------------+ +| ``Likelihood`` | High (4) | High (4) | High (4) | ++------------------------+-----------------+-----------------+----------------+ +| ``Total Risk Rating`` | Critical (20) | Critical (20) | Critical (20) | ++------------------------+-----------------+-----------------+----------------+ +| ``Mitigations`` | | In TF-A, configuration of the MMU is done | +| | through a translation tables library. The | +| | library provides APIs to define memory regions | +| | and assign attributes including memory types and | +| | access permissions. Memory configurations are | +| | platform specific, therefore platforms need make | +| | sure the correct attributes are assigned to | +| | memory regions. When assigning access | +| | permissions, principle of least privilege ought | +| | to be enforced, i.e. we should not grant more | +| | privileges than strictly needed, e.g. code | +| | should be read-only executable, RO data should | +| | be read-only XN, and so on. | ++------------------------+----------------------------------------------------+ + ++------------------------+-----------------------------------------------------+ +| ID | 12 | ++========================+=====================================================+ +| ``Threat`` | | **Incorrect configuration of Performance Monitor | +| | Unit (PMU) counters can allow an attacker to | +| | mount side-channel attacks using information | +| | exposed by the counters** | +| | | +| | | Non-secure software can configure PMU registers | +| | to count events at any exception level and in | +| | both Secure and Non-secure states. This allows | +| | a Non-secure software (or a lower-level Secure | +| | software) to potentially carry out | +| | side-channel timing attacks against TF-A. | ++------------------------+-----------------------------------------------------+ +| ``Diagram Elements`` | DF5, DF6 | ++------------------------+-----------------------------------------------------+ +| ``Affected TF-A | BL31 | +| Components`` | | ++------------------------+-----------------------------------------------------+ +| ``Assets`` | Sensitive Data | ++------------------------+-----------------------------------------------------+ +| ``Threat Agent`` | NSCode | ++------------------------+-----------------------------------------------------+ +| ``Threat Type`` | Information Disclosure | ++------------------------+-------------------+----------------+----------------+ +| ``Impact`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+----------------+ +| ``Likelihood`` | Low (2) | Low (2) | Low (2) | ++------------------------+-------------------+----------------+----------------+ +| ``Total Risk Rating`` | Medium (6) | Medium (6) | Medium (6) | ++------------------------+-------------------+----------------+----------------+ +| ``Mitigations`` | | TF-A follows mitigation strategies as described | +| | in `Secure Development Guidelines`_. General | +| | events and cycle counting in the Secure world is | +| | prohibited by default when applicable. However, | +| | on some implementations (e.g. PMUv3) Secure world | +| | event counting depends on external debug interface| +| | signals, i.e. Secure world event counting is | +| | enabled if external debug is enabled. | +| | Configuration of debug signals is platform | +| | specific, therefore platforms need to make sure | +| | that external debug is disabled in production or | +| | proper debug authentication is in place. | ++------------------------+-----------------------------------------------------+ + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* + + +.. _STRIDE threat analysis technique: https://docs.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats#stride-model +.. _DEN0034: https://developer.arm.com/documentation/den0034/latest +.. _Cache Speculation Side-channels: https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability +.. _Spectre: https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability +.. _TBBR-Client specification: https://developer.arm.com/documentation/den0006/d/ +.. _Trusted Board Boot (TBB): https://trustedfirmware-a.readthedocs.io/en/latest/design/trusted-board-boot.html +.. _TF-A error handling policy: https://trustedfirmware-a.readthedocs.io/en/latest/process/coding-guidelines.html#error-handling-and-robustness +.. _Secure Development Guidelines: https://trustedfirmware-a.readthedocs.io/en/latest/process/security-hardening.html#secure-development-guidelines +.. _Trusted Firmware-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/ diff --git a/arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst b/arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst new file mode 100644 index 0000000..c1462bb --- /dev/null +++ b/arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst @@ -0,0 +1,97 @@ +fvp_r-Platform Threat Model +*************************** + +************************ +Introduction +************************ +This document provides a threat model for TF-A fvp_r platform. + +************************ +Target of Evaluation +************************ +In this threat model, the target of evaluation is the fvp_r platform of Trusted +Firmware for A-class Processors (TF-A). The fvp_r platform provides limited +support of AArch64 R-class Processors (v8-R64). + +This is a delta document, only pointing out differences from the general TF-A +threat-model document, :ref:`Generic Threat Model` + +BL1 Only +======== +The most fundamental difference between the threat model for the current fvp_r +implementation compared to the general TF-A threat model, is that fvp_r is +currently limited to BL1 only. Any threats from the general TF-A threat model +unrelated to BL1 are therefore not relevant to the fvp_r implementation. + +The fvp_r BL1 implementation directly loads a customer/partner-defined runtime +system. The threat model for that runtime system, being partner-defined, is +out-of-scope for this threat-model. + +Relatedly, all exceptions, synchronous and asynchronous, are disabled during BL1 +execution. So, any references to exceptions are not relevant. + +EL3 is Unsupported and All Secure +================================= +v8-R64 cores do not support EL3, and (essentially) all operation is defined as +Secure-mode. Therefore: + + - Any threats regarding NS operation are not relevant. + + - Any mentions of SMCs are also not relevant. + + - Anything otherwise-relevant code running in EL3 is instead run in EL2. + +MPU instead of MMU +================== +v8-R64 cores, running in EL2, use an MPU for memory management, rather than an +MMU. The MPU in the fvp_r implementation is configured to function effectively +identically with the MMU for the usual BL1 implementation. There are +memory-map differences, but the MPU configuration is functionally equivalent. + +No AArch32 Support +================== +Another substantial difference between v8-A and v8-R64 cores is that v8-R64 does +not support AArch32. However, this is not believed to have any threat-modeling +ramifications. + + +Threat Assessment +================= +For this section, please reference the Threat Assessment under the general TF-A +threat-model document, :ref:`Generic Threat Model` + +The following threats from that document are still relevant to the fvp_r +implementation: + + - ID 01: An attacker can mangle firmware images to execute arbitrary code. + + - ID 03: An attacker can use Time-of-Check-Time-of-Use (TOCTOU) attack to + bypass image authentication during the boot process. + + - ID 04: An attacker with physical access can execute arbitrary image by + bypassing the signature verification stage using clock- or power-glitching + techniques. + + - ID 05: Information leak via UART logs such as crashes + + - ID 06: An attacker can read sensitive data and execute arbitrary code + through the external debug and trace interface. + + - ID 08: Memory corruption due to memory overflows and lack of boundary + checking when accessing resources could allow an attacker to execute + arbitrary code, modify some state variable to change the normal flow of + the program, or leak sensitive. + + - ID 11: Misconfiguration of the Memory Protection Unit (MPU) may allow + normal world software to access sensitive data or execute arbitrary code. + Arguably, MPUs having fewer memory regions, there may be a temptation to + share memory regions, making this a greater threat. However, since the + fvp_r implementation is limited to BL1, since BL1's regions are fixed, + and since the MPU configuration is equivalent with that for the fvp + platform and others, this is not expected to be a concern. + + + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/threat_model/threat_model_spm.rst b/arm-trusted-firmware/docs/threat_model/threat_model_spm.rst new file mode 100644 index 0000000..a7bc2a9 --- /dev/null +++ b/arm-trusted-firmware/docs/threat_model/threat_model_spm.rst @@ -0,0 +1,892 @@ +SPMC Threat Model +***************** + +************************ +Introduction +************************ +This document provides a threat model for the TF-A `Secure Partition Manager`_ +(SPM) implementation or more generally the S-EL2 reference firmware running on +systems implementing the FEAT_SEL2 (formerly Armv8.4 Secure EL2) architecture +extension. The SPM implementation is based on the `Arm Firmware Framework for +Arm A-profile`_ specification. + +In brief, the broad FF-A specification and S-EL2 firmware implementation +provide: + +- Isolation of mutually mistrusting SW components, or endpoints in the FF-A + terminology. +- Distinct sandboxes in the secure world called secure partitions. This permits + isolation of services from multiple vendors. +- A standard protocol for communication and memory sharing between FF-A + endpoints. +- Mutual isolation of the normal world and the secure world (e.g. a Trusted OS + is prevented to map an arbitrary NS physical memory region such as the kernel + or the Hypervisor). + +************************ +Target of Evaluation +************************ +In this threat model, the target of evaluation is the S-EL2 firmware or the +``Secure Partition Manager Core`` component (SPMC). +The monitor and SPMD at EL3 are covered by the `Generic TF-A threat model`_. + +The scope for this threat model is: + +- The TF-A implementation for the S-EL2 SPMC based on the Hafnium hypervisor + running in the secure world of TrustZone (at S-EL2 exception level). + The threat model is not related to the normal world Hypervisor or VMs. + The S-EL1 SPMC solution is not covered. +- The implementation complies with the FF-A v1.0 specification, and a few + features of FF-A v1.1 specification. +- Secure partitions are statically provisioned at boot time. +- Focus on the run-time part of the life-cycle (no specific emphasis on boot + time, factory firmware provisioning, firmware udpate etc.) +- Not covering advanced or invasive physical attacks such as decapsulation, + FIB etc. +- Assumes secure boot or in particular TF-A trusted boot (TBBR or dual CoT) is + enabled. An attacker cannot boot arbitrary images that are not approved by the + SiP or platform providers. + +Data Flow Diagram +====================== +Figure 1 shows a high-level data flow diagram for the SPM split into an SPMD +component at EL3 and an SPMC component at S-EL2. The SPMD mostly acts as a +relayer/pass-through between the normal world and the secure world. It is +assumed to expose small attack surface. + +A description of each diagram element is given in Table 1. In the diagram, the +red broken lines indicate trust boundaries. + +Components outside of the broken lines are considered untrusted. + +.. uml:: ../resources/diagrams/plantuml/spm_dfd.puml + :caption: Figure 1: SPMC Data Flow Diagram + +.. table:: Table 1: SPMC Data Flow Diagram Description + + +---------------------+--------------------------------------------------------+ + | Diagram Element | Description | + +=====================+========================================================+ + | ``DF1`` | SP to SPMC communication. FF-A function invocation or | + | | implementation-defined Hypervisor call. | + +---------------------+--------------------------------------------------------+ + | ``DF2`` | SPMC to SPMD FF-A call. | + +---------------------+--------------------------------------------------------+ + | ``DF3`` | SPMD to NS forwarding. | + +---------------------+--------------------------------------------------------+ + | ``DF4`` | SP to SP FF-A direct message request/response. | + | | Note as a matter of simplifying the diagram | + | | the SP to SP communication happens through the SPMC | + | | (SP1 performs a direct message request to the | + | | SPMC targeting SP2 as destination. And similarly for | + | | the direct message response from SP2 to SP1). | + +---------------------+--------------------------------------------------------+ + | ``DF5`` | HW control. | + +---------------------+--------------------------------------------------------+ + | ``DF6`` | Bootloader image loading. | + +---------------------+--------------------------------------------------------+ + | ``DF7`` | External memory access. | + +---------------------+--------------------------------------------------------+ + +********************* +Threat Analysis +********************* + +This threat model follows a similar methodology to the `Generic TF-A threat model`_. +The following sections define: + +- Trust boundaries +- Assets +- Theat agents +- Threat types + +Trust boundaries +============================ + +- Normal world is untrusted. +- Secure world and normal world are separate trust boundaries. +- EL3 monitor, SPMD and SPMC are trusted. +- Bootloaders (in particular BL1/BL2 if using TF-A) and run-time BL31 are + implicitely trusted by the usage of secure boot. +- EL3 monitor, SPMD, SPMC do not trust SPs. + +.. figure:: ../resources/diagrams/spm-threat-model-trust-boundaries.png + + Figure 2: Trust boundaries + +Assets +============================ + +The following assets are identified: + +- SPMC state. +- SP state. +- Information exchange between endpoints (partition messages). +- SPMC secrets (e.g. pointer authentication key when enabled) +- SP secrets (e.g. application keys). +- Scheduling cycles. +- Shared memory. + +Threat Agents +============================ + +The following threat agents are identified: + +- NS-Endpoint identifies a non-secure endpoint: normal world client at NS-EL2 + (Hypervisor) or NS-EL1 (VM or OS kernel). +- S-Endpoint identifies a secure endpoint typically a secure partition. +- Hardware attacks (non-invasive) requiring a physical access to the device, + such as bus probing or DRAM stress. + +Threat types +============================ + +The following threat categories as exposed in the `Generic TF-A threat model`_ +are re-used: + +- Spoofing +- Tampering +- Repudiation +- Information disclosure +- Denial of service +- Elevation of privileges + +Similarly this threat model re-uses the same threat risk ratings. The risk +analysis is evaluated based on the environment being ``Server`` or ``Mobile``. + +Threat Assessment +============================ + +The following threats are identified by applying STRIDE analysis on each diagram +element of the data flow diagram. + ++------------------------+----------------------------------------------------+ +| ID | 01 | ++========================+====================================================+ +| ``Threat`` | **An endpoint impersonates the sender or receiver | +| | FF-A ID in a direct request/response invocation.** | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMD, SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------++----------------+---------------+ +| ``Impact`` | Critical(5) | Critical(5) | | ++------------------------+------------------++----------------+---------------+ +| ``Likelihood`` | Critical(5) | Critical(5) | | ++------------------------+------------------++----------------+---------------+ +| ``Total Risk Rating`` | Critical(25) | Critical(25) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC does not mitigate this threat. | +| | The guidance below is left for a system integrator | +| | to implemented as necessary. | +| | The SPMC must enforce checks in the direct message | +| | request/response interfaces such an endpoint cannot| +| | spoof the origin and destination worlds (e.g. a NWd| +| | originated message directed to the SWd cannot use a| +| | SWd ID as the sender ID). | +| | Additionally a software component residing in the | +| | SPMC can be added for the purpose of direct | +| | request/response filtering. | +| | It can be configured with the list of known IDs | +| | and about which interaction can occur between one | +| | and another endpoint (e.g. which NWd endpoint ID | +| | sends a direct request to which SWd endpoint ID). | +| | This component checks the sender/receiver fields | +| | for a legitimate communication between endpoints. | +| | A similar component can exist in the OS kernel | +| | driver, or Hypervisor although it remains untrusted| +| | by the SPMD/SPMC. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 02 | ++========================+====================================================+ +| ``Threat`` | **Tampering with memory shared between an endpoint | +| | and the SPMC.** | +| | A malicious endpoint may attempt tampering with its| +| | RX/TX buffer contents while the SPMC is processing | +| | it (TOCTOU). | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF3, DF4, DF7 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Shared memory, Information exchange | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | High (4) | High (4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | High (16) | High (16) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | In context of FF-A v1.0 this is the case of sharing| +| | the RX/TX buffer pair and usage in the | +| | PARTITION_INFO_GET or mem sharing primitives. | +| | The SPMC must copy the contents of the TX buffer | +| | to an internal temporary buffer before processing | +| | its contents. The SPMC must implement hardened | +| | input validation on data transmitted through the TX| +| | buffer by an untrusted endpoint. | +| | The TF-A SPMC mitigates this threat by enforcing | +| | checks on data transmitted through RX/TX buffers. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 03 | ++========================+====================================================+ +| ``Threat`` | **An endpoint may tamper with its own state or the | +| | state of another endpoint.** | +| | A malicious endpoint may attempt violating: | +| | - its own or another SP state by using an unusual | +| | combination (or out-of-order) FF-A function | +| | invocations. | +| | This can also be an endpoint emitting | +| | FF-A function invocations to another endpoint while| +| | the latter in not in a state to receive it (e.g. a | +| | SP sends a direct request to the normal world early| +| | while the normal world is not booted yet). | +| | - the SPMC state itself by employing unexpected | +| | transitions in FF-A memory sharing, direct requests| +| | and responses, or handling of interrupts. | +| | This can be led by random stimuli injection or | +| | fuzzing. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMD, SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP state, SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | High (12) | High (12) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The SPMC may be vulnerable to invalid state | +| | transitions for itself or while handling an SP | +| | state. The FF-A v1.1 specification provides a | +| | guidance on those state transitions (run-time | +| | model). The TF-A SPMC will be hardened in future | +| | releases to follow this guidance. | +| | Additionally The TF-A SPMC mitigates the threat by | +| | runs of the Arm `FF-A ACS`_ compliance test suite. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 04 | ++========================+====================================================+ +| ``Threat`` | *An attacker may attempt injecting errors by the | +| | use of external DRAM stress techniques.** | +| | A malicious agent may attempt toggling an SP | +| | Stage-2 MMU descriptor bit within the page tables | +| | that the SPMC manages. This can happen in Rowhammer| +| | types of attack. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF7 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP or SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | Hardware attack | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | Low (2) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | Medium (8) | High (12) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | The TF-A SPMC does not provide mitigations to this | +| | type of attack. It can be addressed by the use of | +| | dedicated HW circuity or hardening at the chipset | +| | or platform level left to the integrator. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 05 | ++========================+====================================================+ +| ``Threat`` | **Protection of the SPMC from a DMA capable device | +| | upstream to an SMMU.** | +| | A device may attempt to tamper with the internal | +| | SPMC code/data sections. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF5 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC or SP state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering, Elevation of privileges | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | A platform may prefer assigning boot time, | +| | statically alocated memory regions through the SMMU| +| | configuration and page tables. The FF-A v1.1 | +| | specification provisions this capability through | +| | static DMA isolation. | +| | The TF-A SPMC does not mitigate this threat. | +| | It will adopt the static DMA isolation approach in | +| | a future release. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 06 | ++========================+====================================================+ +| ``Threat`` | **Replay fragments of past communication between | +| | endpoints.** | +| | A malicious endpoint may replay a message exchange | +| | that occured between two legitimate endpoint as | +| | a matter of triggering a malfunction or extracting | +| | secrets from the receiving endpoint. In particular | +| | the memory sharing operation with fragmented | +| | messages between an endpoint and the SPMC may be | +| | replayed by a malicious agent as a matter of | +| | getting access or gaining permissions to a memory | +| | region which does not belong to this agent. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Information exchange | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Repdudiation | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | High (4) | High (4) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | The TF-A SPMC does not mitigate this threat. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 07 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may attempt to extract data | +| | or state information by the use of invalid or | +| | incorrect input arguments.** | +| | Lack of input parameter validation or side effects | +| | of maliciously forged input parameters might affect| +| | the SPMC. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMD, SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP secrets, SPMC secrets, SP state, SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information discolure | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | Secure Partitions must follow security standards | +| | and best practises as a way to mitigate the risk | +| | of common vulnerabilities to be exploited. | +| | The use of software (canaries) or hardware | +| | hardening techniques (XN, WXN, BTI, pointer | +| | authentication, MTE) helps detecting and stopping | +| | an exploitation early. | +| | The TF-A SPMC mitigates this threat by implementing| +| | stack protector, pointer authentication, BTI, XN, | +| | WXN, security hardening techniques. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 08 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may forge a direct message | +| | request such that it reveals the internal state of | +| | another endpoint through the direct message | +| | response.** | +| | The secure partition or SPMC replies to a partition| +| | message by a direct message response with | +| | information which may reveal its internal state | +| | (.e.g. partition message response outside of | +| | allowed bounds). | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC or SP state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information discolure | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | Low (2) | Low (2) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | Medium (6) | Medium (6) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | For the specific case of direct requests targeting | +| | the SPMC, the latter is hardened to prevent | +| | its internal state or the state of an SP to be | +| | revealed through a direct message response. | +| | Further FF-A v1.1 guidance about run time models | +| | and partition states will be implemented in future | +| | TF-A SPMC releases. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 09 | ++========================+====================================================+ +| ``Threat`` | **Probing the FF-A communication between | +| | endpoints.** | +| | SPMC and SPs are typically loaded to external | +| | memory (protected by a TrustZone memory | +| | controller). A malicious agent may use non invasive| +| | methods to probe the external memory bus and | +| | extract the traffic between an SP and the SPMC or | +| | among SPs when shared buffers are held in external | +| | memory. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF7 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP/SPMC state, SP/SPMC secrets | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | Hardware attack | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information disclosure | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low (2) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium (6) | Medium (9) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | It is expected the platform or chipset provides | +| | guarantees in protecting the DRAM contents. | +| | The TF-A SPMC does not mitigate this class of | +| | attack and this is left to the integrator. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 10 | ++========================+====================================================+ +| ``Threat`` | **A malicious agent may attempt revealing the SPMC | +| | state or secrets by the use of software-based cache| +| | side-channel attack techniques.** | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF7 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP or SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information disclosure | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low (2) | Low (2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium (6) | Medium (6) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | From an integration perspective it is assumed | +| | platforms consuming the SPMC component at S-EL2 | +| | (hence implementing the Armv8.4 FEAT_SEL2 | +| | architecture extension) implement mitigations to | +| | Spectre, Meltdown or other cache timing | +| | side-channel type of attacks. | +| | The TF-A SPMC implements one mitigation (barrier | +| | preventing speculation past exeception returns). | +| | The SPMC may be hardened further with SW | +| | mitigations (e.g. speculation barriers) for the | +| | cases not covered in HW. Usage of hardened | +| | compilers and appropriate options, code inspection | +| | are recommended ways to mitigate Spectre types of | +| | attacks. For non-hardened cores, the usage of | +| | techniques such a kernel page table isolation can | +| | help mitigating Meltdown type of attacks. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 11 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may attempt flooding the | +| | SPMC with requests targeting a service within an | +| | endpoint such that it denies another endpoint to | +| | access this service.** | +| | Similarly, the malicious endpoint may target a | +| | a service within an endpoint such that the latter | +| | is unable to request services from another | +| | endpoint. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Denial of service | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium (9) | Medium (9) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC does not mitigate this threat. | +| | Bounding the time for operations to complete can | +| | be achieved by the usage of a trusted watchdog. | +| | Other quality of service monitoring can be achieved| +| | in the SPMC such as counting a number of operations| +| | in a limited timeframe. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 12 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may attempt to allocate | +| | notifications bitmaps in the SPMC, through the | +| | FFA_NOTIFICATION_BITMAP_CREATE.** | +| | This might be an attempt to exhaust SPMC's memory, | +| | or to allocate a bitmap for a VM that was not | +| | intended to receive notifications from SPs. Thus | +| | creating the possibility for a channel that was not| +| | meant to exist. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Denial of service, Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium(9) | Medium(9) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this threat by defining a | +| | a fixed size pool for bitmap allocation. | +| | It also limits the designated FF-A calls to be used| +| | from NWd endpoints. | +| | In the NWd the hypervisor is supposed to limit the | +| | access to the designated FF-A call. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 13 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may attempt to destroy the | +| | notifications bitmaps in the SPMC, through the | +| | FFA_NOTIFICATION_BITMAP_DESTROY.** | +| | This might be an attempt to tamper with the SPMC | +| | state such that a partition isn't able to receive | +| | notifications. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Low(4) | Low(4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this issue by limiting the | +| | designated FF-A call to be issued by the NWd. | +| | Also, the notifications bitmap can't be destroyed | +| | if there are pending notifications. | +| | In the NWd, the hypervisor must restrict the | +| | NS-endpoints that can issue the designated call. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 14 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint might attempt to give | +| | permissions to an unintended sender to set | +| | notifications targeting another receiver using the | +| | FF-A call FFA_NOTIFICATION_BIND.** | +| | This might be an attempt to tamper with the SPMC | +| | state such that an unintended, and possibly | +| | malicious, communication channel is established. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering, Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium(6) | Medium(6) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this by restricting | +| | designated FFA_NOTIFICATION_BIND call to be issued | +| | by the receiver only. The receiver is responsible | +| | for allocating the notifications IDs to one | +| | specific partition. | +| | Also, receivers that are not meant to receive | +| | notifications, must have notifications receipt | +| | disabled in the respective partition's manifest. | +| | As for calls coming from NWd, if the NWd VM has had| +| | its bitmap allocated at initialization, the TF-A | +| | SPMC can't guarantee this threat won't happen. | +| | The Hypervisor must mitigate in the NWd, similarly | +| | to SPMC for calls in SWd. Though, if the Hypervisor| +| | has been compromised, the SPMC won't be able to | +| | mitigate it for calls forwarded from NWd. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 15 | ++========================+====================================================+ +| ``Threat`` | **A malicious partition endpoint might attempt to | +| | set notifications that are not bound to it.** | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Low(4) | Low(4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this by checking the | +| | sender's ID provided in the input to the call | +| | FFA_NOTIFICATION_SET. The SPMC keeps track of which| +| | notifications are bound to which sender, for a | +| | given receiver. If the sender is an SP, the | +| | provided sender ID must match the ID of the | +| | currently running partition. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 16 | ++========================+====================================================+ +| ``Threat`` | **A malicious partition endpoint might attempt to | +| | get notifications that are not targeted to it.** | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Informational(1) | Informational(1)| | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this by checking the | +| | receiver's ID provided in the input to the call | +| | FFA_NOTIFICATION_GET. The SPMC keeps track of which| +| | notifications are pending for each receiver. | +| | The provided receiver ID must match the ID of the | +| | currently running partition, if it is an SP. | +| | For calls forwarded from NWd, the SPMC will return | +| | the pending notifications if the receiver had its | +| | bitmap created, and has pending notifications. | +| | If Hypervisor or OS kernel are compromised, the | +| | SPMC won't be able to mitigate calls from rogue NWd| +| | endpoints. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 17 | ++========================+====================================================+ +| ``Threat`` | **A malicious partition endpoint might attempt to | +| | get the information about pending notifications, | +| | through the FFA_NOTIFICATION_INFO_GET call.** | +| | This call is meant to be used by the NWd FF-A | +| | driver. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information disclosure | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium(6) | Medium(6) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this by returning error to | +| | calls made by SPs to FFA_NOTIFICATION_INFO_GET. | +| | If Hypervisor or OS kernel are compromised, the | +| | SPMC won't be able mitigate calls from rogue NWd | +| | endpoints. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 18 | ++========================+====================================================+ +| ``Threat`` | **A malicious partition endpoint might attempt to | +| | flood another partition endpoint with notifications| +| | hindering its operation.** | +| | The intent of the malicious endpoint could be to | +| | interfere with both the receiver's and/or primary | +| | endpoint execution, as they can both be preempted | +| | by the NPI and SRI, respectively. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state, SP state, CPU cycles | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | DoS | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium(6) | Medium(6) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC does not mitigate this threat. | +| | However, the impact is limited due to the | +| | architecture: | +| | - Notifications are not queued, one that has been | +| | signaled needs to be retrieved by the receiver, | +| | until it can be sent again. | +| | - Both SRI and NPI can't be pended until handled | +| | which limits the amount of spurious interrupts. | +| | - A given receiver could only bind a maximum number| +| | of notifications to a given sender, within a given | +| | execution context. | ++------------------------+----------------------------------------------------+ + +--------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* + +.. _Arm Firmware Framework for Arm A-profile: https://developer.arm.com/docs/den0077/latest +.. _Secure Partition Manager: ../components/secure-partition-manager.html +.. _Generic TF-A threat model: ./threat_model.html#threat-analysis +.. _FF-A ACS: https://github.com/ARM-software/ff-a-acs/releases diff --git a/arm-trusted-firmware/drivers/allwinner/axp/axp803.c b/arm-trusted-firmware/drivers/allwinner/axp/axp803.c new file mode 100644 index 0000000..19a9549 --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/axp/axp803.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const uint8_t axp_chip_id = AXP803_CHIP_ID; +const char *const axp_compatible = "x-powers,axp803"; + +#if SUNXI_SETUP_REGULATORS == 1 +const struct axp_regulator axp_regulators[] = { + {"aldo1", 700, 3300, 100, NA, 0x28, 0x13, 5}, + {"dcdc1", 1600, 3400, 100, NA, 0x20, 0x10, 0}, + {"dcdc5", 800, 1840, 10, 32, 0x24, 0x10, 4}, + {"dcdc6", 600, 1520, 10, 50, 0x25, 0x10, 5}, + {"dldo1", 700, 3300, 100, NA, 0x15, 0x12, 3}, + {"dldo2", 700, 4200, 100, 27, 0x16, 0x12, 4}, + {"dldo3", 700, 3300, 100, NA, 0x17, 0x12, 5}, + {"dldo4", 700, 3300, 100, NA, 0x18, 0x12, 6}, + {"fldo1", 700, 1450, 50, NA, 0x1c, 0x13, 2}, + {} +}; +#endif diff --git a/arm-trusted-firmware/drivers/allwinner/axp/axp805.c b/arm-trusted-firmware/drivers/allwinner/axp/axp805.c new file mode 100644 index 0000000..3a03fec --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/axp/axp805.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const uint8_t axp_chip_id = AXP805_CHIP_ID; +const char *const axp_compatible = "x-powers,axp805"; + +#if SUNXI_SETUP_REGULATORS == 1 +/* + * The "dcdcd" split changes the step size by a factor of 5, not 2; + * disallow values above the split to maintain accuracy. + */ +const struct axp_regulator axp_regulators[] = { + {"dcdca", 600, 1520, 10, 50, 0x12, 0x10, 0}, + {"dcdcb", 1000, 2550, 50, NA, 0x13, 0x10, 1}, + {"dcdcc", 600, 1520, 10, 50, 0x14, 0x10, 2}, + {"dcdcd", 600, 1500, 20, NA, 0x15, 0x10, 3}, + {"dcdce", 1100, 3400, 100, NA, 0x16, 0x10, 4}, + {"aldo1", 700, 3300, 100, NA, 0x17, 0x10, 5}, + {"aldo2", 700, 3300, 100, NA, 0x18, 0x10, 6}, + {"aldo3", 700, 3300, 100, NA, 0x19, 0x10, 7}, + {"bldo1", 700, 1900, 100, NA, 0x20, 0x11, 0}, + {"bldo2", 700, 1900, 100, NA, 0x21, 0x11, 1}, + {"bldo3", 700, 1900, 100, NA, 0x22, 0x11, 2}, + {"bldo4", 700, 1900, 100, NA, 0x23, 0x11, 3}, + {"cldo1", 700, 3300, 100, NA, 0x24, 0x11, 4}, + {"cldo2", 700, 4200, 100, 27, 0x25, 0x11, 5}, + {"cldo3", 700, 3300, 100, NA, 0x26, 0x11, 6}, + {} +}; +#endif diff --git a/arm-trusted-firmware/drivers/allwinner/axp/common.c b/arm-trusted-firmware/drivers/allwinner/axp/common.c new file mode 100644 index 0000000..f1250b0 --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/axp/common.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +int axp_check_id(void) +{ + int ret; + + ret = axp_read(0x03); + if (ret < 0) + return ret; + + ret &= 0xcf; + if (ret != axp_chip_id) { + ERROR("PMIC: Found unknown PMIC %02x\n", ret); + return ret; + } + + return 0; +} + +int axp_clrsetbits(uint8_t reg, uint8_t clr_mask, uint8_t set_mask) +{ + uint8_t val; + int ret; + + ret = axp_read(reg); + if (ret < 0) + return ret; + + val = (ret & ~clr_mask) | set_mask; + + return axp_write(reg, val); +} + +void axp_power_off(void) +{ + /* Set "power disable control" bit */ + axp_setbits(0x32, BIT(7)); +} + +#if SUNXI_SETUP_REGULATORS == 1 +/* + * Retrieve the voltage from a given regulator DTB node. + * Both the regulator-{min,max}-microvolt properties must be present and + * have the same value. Return that value in millivolts. + */ +static int fdt_get_regulator_millivolt(const void *fdt, int node) +{ + const fdt32_t *prop; + uint32_t min_volt; + + prop = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); + if (prop == NULL) + return -EINVAL; + min_volt = fdt32_to_cpu(*prop); + + prop = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); + if (prop == NULL) + return -EINVAL; + + if (fdt32_to_cpu(*prop) != min_volt) + return -EINVAL; + + return min_volt / 1000; +} + +static int setup_regulator(const void *fdt, int node, + const struct axp_regulator *reg) +{ + uint8_t val; + int mvolt; + + mvolt = fdt_get_regulator_millivolt(fdt, node); + if (mvolt < reg->min_volt || mvolt > reg->max_volt) + return -EINVAL; + + val = (mvolt / reg->step) - (reg->min_volt / reg->step); + if (val > reg->split) + val = ((val - reg->split) / 2) + reg->split; + + axp_write(reg->volt_reg, val); + axp_setbits(reg->switch_reg, BIT(reg->switch_bit)); + + INFO("PMIC: %s voltage: %d.%03dV\n", reg->dt_name, + mvolt / 1000, mvolt % 1000); + + return 0; +} + +static bool is_node_disabled(const void *fdt, int node) +{ + const char *cell; + cell = fdt_getprop(fdt, node, "status", NULL); + if (cell == NULL) { + return false; + } + return strcmp(cell, "okay") != 0; +} + +static bool should_enable_regulator(const void *fdt, int node) +{ + if (is_node_disabled(fdt, node)) { + return false; + } + if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) { + return true; + } + if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) { + return true; + } + return false; +} + +static bool board_uses_usb0_host_mode(const void *fdt) +{ + int node, length; + const char *prop; + + node = fdt_node_offset_by_compatible(fdt, -1, + "allwinner,sun8i-a33-musb"); + if (node < 0) { + return false; + } + + prop = fdt_getprop(fdt, node, "dr_mode", &length); + if (!prop) { + return false; + } + + return !strncmp(prop, "host", length); +} + +void axp_setup_regulators(const void *fdt) +{ + int node; + bool sw = false; + + if (fdt == NULL) + return; + + /* locate the PMIC DT node, bail out if not found */ + node = fdt_node_offset_by_compatible(fdt, -1, axp_compatible); + if (node < 0) { + WARN("PMIC: No PMIC DT node, skipping setup\n"); + return; + } + + /* This applies to AXP803 only. */ + if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL) && + board_uses_usb0_host_mode(fdt)) { + axp_clrbits(0x8f, BIT(4)); + axp_setbits(0x30, BIT(2)); + INFO("PMIC: Enabling DRIVEVBUS\n"); + } + + /* descend into the "regulators" subnode */ + node = fdt_subnode_offset(fdt, node, "regulators"); + if (node < 0) { + WARN("PMIC: No regulators DT node, skipping setup\n"); + return; + } + + /* iterate over all regulators to find used ones */ + fdt_for_each_subnode(node, fdt, node) { + const struct axp_regulator *reg; + const char *name; + int length; + + /* We only care if it's always on or referenced. */ + if (!should_enable_regulator(fdt, node)) + continue; + + name = fdt_get_name(fdt, node, &length); + + /* Enable the switch last to avoid overheating. */ + if (!strncmp(name, "dc1sw", length) || + !strncmp(name, "sw", length)) { + sw = true; + continue; + } + + for (reg = axp_regulators; reg->dt_name; reg++) { + if (!strncmp(name, reg->dt_name, length)) { + setup_regulator(fdt, node, reg); + break; + } + } + } + + /* + * On the AXP803, if DLDO2 is enabled after DC1SW, the PMIC overheats + * and shuts down. So always enable DC1SW as the very last regulator. + */ + if (sw) { + INFO("PMIC: Enabling DC SW\n"); + if (axp_chip_id == AXP803_CHIP_ID) + axp_setbits(0x12, BIT(7)); + if (axp_chip_id == AXP805_CHIP_ID) + axp_setbits(0x11, BIT(7)); + } +} +#endif /* SUNXI_SETUP_REGULATORS */ diff --git a/arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c b/arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c new file mode 100644 index 0000000..cc4a6ff --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include + +#define REMOTE_IRQ_EN_REG 0x0040 +#define REMOTE_IRQ_STAT_REG 0x0050 +#define LOCAL_IRQ_EN_REG 0x0060 +#define LOCAL_IRQ_STAT_REG 0x0070 + +#define RX_IRQ(n) BIT(0 + 2 * (n)) +#define TX_IRQ(n) BIT(1 + 2 * (n)) + +#define FIFO_STAT_REG(n) (0x0100 + 0x4 * (n)) +#define FIFO_STAT_MASK GENMASK(0, 0) + +#define MSG_STAT_REG(n) (0x0140 + 0x4 * (n)) +#define MSG_STAT_MASK GENMASK(2, 0) + +#define MSG_DATA_REG(n) (0x0180 + 0x4 * (n)) + +#define RX_CHAN 1 +#define TX_CHAN 0 + +#define MHU_MAX_SLOT_ID 31 + +#define MHU_TIMEOUT_DELAY 10 +#define MHU_TIMEOUT_ITERS 10000 + +static DEFINE_BAKERY_LOCK(mhu_secure_message_lock); + +static bool sunxi_msgbox_last_tx_done(unsigned int chan) +{ + uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + REMOTE_IRQ_STAT_REG); + + return (stat & RX_IRQ(chan)) == 0U; +} + +static bool sunxi_msgbox_peek_data(unsigned int chan) +{ + uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_STAT_REG(chan)); + + return (stat & MSG_STAT_MASK) != 0U; +} + +void mhu_secure_message_start(unsigned int slot_id __unused) +{ + uint32_t timeout = MHU_TIMEOUT_ITERS; + + bakery_lock_get(&mhu_secure_message_lock); + + /* Wait for all previous messages to be acknowledged. */ + while (!sunxi_msgbox_last_tx_done(TX_CHAN) && --timeout) + udelay(MHU_TIMEOUT_DELAY); +} + +void mhu_secure_message_send(unsigned int slot_id) +{ + mmio_write_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(TX_CHAN), BIT(slot_id)); +} + +uint32_t mhu_secure_message_wait(void) +{ + uint32_t timeout = MHU_TIMEOUT_ITERS; + uint32_t msg = 0; + + /* Wait for a message from the SCP. */ + while (!sunxi_msgbox_peek_data(RX_CHAN) && --timeout) + udelay(MHU_TIMEOUT_DELAY); + + /* Return the most recent message in the FIFO. */ + while (sunxi_msgbox_peek_data(RX_CHAN)) + msg = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(RX_CHAN)); + + return msg; +} + +void mhu_secure_message_end(unsigned int slot_id) +{ + /* Acknowledge a response by clearing the IRQ status. */ + mmio_write_32(SUNXI_MSGBOX_BASE + LOCAL_IRQ_STAT_REG, RX_IRQ(RX_CHAN)); + + bakery_lock_release(&mhu_secure_message_lock); +} diff --git a/arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c b/arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c new file mode 100644 index 0000000..67f5b7e --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +#define RSB_CTRL 0x00 +#define RSB_CCR 0x04 +#define RSB_INTE 0x08 +#define RSB_STAT 0x0c +#define RSB_DADDR0 0x10 +#define RSB_DLEN 0x18 +#define RSB_DATA0 0x1c +#define RSB_LCR 0x24 +#define RSB_PMCR 0x28 +#define RSB_CMD 0x2c +#define RSB_SADDR 0x30 + +#define RSBCMD_SRTA 0xE8 +#define RSBCMD_RD8 0x8B +#define RSBCMD_RD16 0x9C +#define RSBCMD_RD32 0xA6 +#define RSBCMD_WR8 0x4E +#define RSBCMD_WR16 0x59 +#define RSBCMD_WR32 0x63 + +#define MAX_TRIES 100000 + +static int rsb_wait_bit(const char *desc, unsigned int offset, uint32_t mask) +{ + uint32_t reg, tries = MAX_TRIES; + + do + reg = mmio_read_32(SUNXI_R_RSB_BASE + offset); + while ((reg & mask) && --tries); /* transaction in progress */ + if (reg & mask) { + ERROR("%s: timed out\n", desc); + return -ETIMEDOUT; + } + + return 0; +} + +static int rsb_wait_stat(const char *desc) +{ + uint32_t reg; + int ret = rsb_wait_bit(desc, RSB_CTRL, BIT(7)); + + if (ret) + return ret; + + reg = mmio_read_32(SUNXI_R_RSB_BASE + RSB_STAT); + if (reg == 0x01) + return 0; + + ERROR("%s: 0x%x\n", desc, reg); + return -reg; +} + +/* Initialize the RSB controller. */ +int rsb_init_controller(void) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x01); /* soft reset */ + + return rsb_wait_bit("RSB: reset controller", RSB_CTRL, BIT(0)); +} + +int rsb_read(uint8_t rt_addr, uint8_t reg_addr) +{ + int ret; + + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */ + + ret = rsb_wait_stat("RSB: read command"); + if (ret) + return ret; + + return mmio_read_32(SUNXI_R_RSB_BASE + RSB_DATA0) & 0xff; /* result */ +} + +int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_WR8); /* byte write */ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DATA0, value); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */ + + return rsb_wait_stat("RSB: write command"); +} + +int rsb_set_device_mode(uint32_t device_mode) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_PMCR, + (device_mode & 0x00ffffff) | BIT(31)); + + return rsb_wait_bit("RSB: set device to RSB", RSB_PMCR, BIT(31)); +} + +int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq) +{ + uint32_t reg; + + if (bus_freq == 0) + return -EINVAL; + + reg = source_freq / bus_freq; + if (reg < 2) + return -EINVAL; + + reg = reg / 2 - 1; + reg |= (1U << 8); /* one cycle of CD output delay */ + + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CCR, reg); + + return 0; +} + +/* Initialize the RSB PMIC connection. */ +int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16)); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_SRTA); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80); + + return rsb_wait_stat("RSB: set run-time address"); +} diff --git a/arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S b/arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S new file mode 100644 index 0000000..6d0a2d6 --- /dev/null +++ b/arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl console_meson_register + .globl console_meson_init + .globl console_meson_putc + .globl console_meson_getc + .globl console_meson_flush + .globl console_meson_core_putc + .globl console_meson_core_getc + .globl console_meson_core_flush + + /* ----------------------------------------------- + * Hardware definitions + * ----------------------------------------------- + */ +#define MESON_WFIFO_OFFSET 0x0 +#define MESON_RFIFO_OFFSET 0x4 +#define MESON_CONTROL_OFFSET 0x8 +#define MESON_STATUS_OFFSET 0xC +#define MESON_MISC_OFFSET 0x10 +#define MESON_REG5_OFFSET 0x14 + +#define MESON_CONTROL_CLR_ERROR_BIT 24 +#define MESON_CONTROL_RX_RESET_BIT 23 +#define MESON_CONTROL_TX_RESET_BIT 22 +#define MESON_CONTROL_RX_ENABLE_BIT 13 +#define MESON_CONTROL_TX_ENABLE_BIT 12 + +#define MESON_STATUS_RX_EMPTY_BIT 20 +#define MESON_STATUS_TX_FULL_BIT 21 +#define MESON_STATUS_TX_EMPTY_BIT 22 + +#define MESON_REG5_USE_XTAL_CLK_BIT 24 +#define MESON_REG5_USE_NEW_RATE_BIT 23 +#define MESON_REG5_NEW_BAUD_RATE_MASK 0x7FFFFF + + /* ----------------------------------------------- + * int console_meson_register(uintptr_t base, + * uint32_t clk, uint32_t baud, + * console_t *console); + * Function to initialize and register a new MESON + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_meson_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_meson_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register meson putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_meson_register + + /* ----------------------------------------------- + * int console_meson_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : x0-x3 + * ----------------------------------------------- + */ +func console_meson_init + cmp w0, #0 + beq init_fail + mov_imm w3, 24000000 /* TODO: This only works with a 24 MHz clock. */ + cmp w1, w3 + bne init_fail + cmp w2, #0 + beq init_fail + /* Set baud rate: value = ((clock / 3) / baudrate) - 1 */ + mov w3, #3 + udiv w3, w1, w3 + udiv w3, w3, w2 + sub w3, w3, #1 + orr w3, w3, #((1 << MESON_REG5_USE_XTAL_CLK_BIT) | \ + (1 << MESON_REG5_USE_NEW_RATE_BIT)) + str w3, [x0, #MESON_REG5_OFFSET] + /* Reset UART and clear error flag */ + ldr w3, [x0, #MESON_CONTROL_OFFSET] + orr w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \ + (1 << MESON_CONTROL_RX_RESET_BIT) | \ + (1 << MESON_CONTROL_TX_RESET_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + bic w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \ + (1 << MESON_CONTROL_RX_RESET_BIT) | \ + (1 << MESON_CONTROL_TX_RESET_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + /* Enable transfer and receive FIFO */ + orr w3, w3, #((1 << MESON_CONTROL_RX_ENABLE_BIT) | \ + (1 << MESON_CONTROL_TX_ENABLE_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + /* Success */ + mov w0, #1 + ret +init_fail: + mov w0, wzr + ret +endfunc console_meson_init + + /* -------------------------------------------------------- + * int console_meson_putc(int c, console_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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_meson_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_BASE] + b console_meson_core_putc +endfunc console_meson_putc + + /* -------------------------------------------------------- + * int console_meson_core_putc(int c, uintptr_t base_addr) + * 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 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_meson_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f + /* Wait until the transmit FIFO isn't full */ +1: ldr w2, [x1, #MESON_STATUS_OFFSET] + tbnz w2, #MESON_STATUS_TX_FULL_BIT, 1b + /* Write '\r' if needed */ + mov w2, #0xD + str w2, [x1, #MESON_WFIFO_OFFSET] + /* Wait until the transmit FIFO isn't full */ +2: ldr w2, [x1, #MESON_STATUS_OFFSET] + tbnz w2, #MESON_STATUS_TX_FULL_BIT, 2b + /* Write input character */ + str w0, [x1, #MESON_WFIFO_OFFSET] + ret +endfunc console_meson_core_putc + + /* --------------------------------------------- + * int console_meson_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - pointer to console_t structure + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_meson_core_getc +endfunc console_meson_getc + + /* --------------------------------------------- + * int console_meson_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - console base address + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + /* Is the receive FIFO empty? */ + ldr w1, [x0, #MESON_STATUS_OFFSET] + tbnz w1, #MESON_STATUS_RX_EMPTY_BIT, 1f + /* Read one character from the RX FIFO */ + ldr w0, [x0, #MESON_RFIFO_OFFSET] + ret +1: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_meson_core_getc + + /* --------------------------------------------- + * void console_meson_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_meson_core_flush +endfunc console_meson_flush + + /* --------------------------------------------- + * void console_meson_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + /* Wait until the transmit FIFO is empty */ +1: ldr w1, [x0, #MESON_STATUS_OFFSET] + tbz w1, #MESON_STATUS_TX_EMPTY_BIT, 1b + ret +endfunc console_meson_core_flush diff --git a/arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c b/arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c new file mode 100644 index 0000000..fceb1c0 --- /dev/null +++ b/arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2019, Remi Pommarel + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "aml_private.h" + +#define ASD_MODE_SHA224 0x7 +#define ASD_MODE_SHA256 0x6 + +/* SHA DMA descriptor */ +struct asd_desc { + uint32_t cfg; + uint32_t src; + uint32_t dst; +}; +#define ASD_DESC_GET(x, msk, off) (((x) >> (off)) & (msk)) +#define ASD_DESC_SET(x, v, msk, off) \ + ((x) = ((x) & ~((msk) << (off))) | (((v) & (msk)) << (off))) + +#define ASD_DESC_LEN_OFF 0 +#define ASD_DESC_LEN_MASK 0x1ffff +#define ASD_DESC_LEN(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF)) +#define ASD_DESC_LEN_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF)) + +#define ASD_DESC_IRQ_OFF 17 +#define ASD_DESC_IRQ_MASK 0x1 +#define ASD_DESC_IRQ(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF)) +#define ASD_DESC_IRQ_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF)) + +#define ASD_DESC_EOD_OFF 18 +#define ASD_DESC_EOD_MASK 0x1 +#define ASD_DESC_EOD(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF)) +#define ASD_DESC_EOD_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF)) + +#define ASD_DESC_LOOP_OFF 19 +#define ASD_DESC_LOOP_MASK 0x1 +#define ASD_DESC_LOOP(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF)) +#define ASD_DESC_LOOP_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF)) + +#define ASD_DESC_MODE_OFF 20 +#define ASD_DESC_MODE_MASK 0xf +#define ASD_DESC_MODE(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF)) +#define ASD_DESC_MODE_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF)) + +#define ASD_DESC_BEGIN_OFF 24 +#define ASD_DESC_BEGIN_MASK 0x1 +#define ASD_DESC_BEGIN(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF)) +#define ASD_DESC_BEGIN_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF)) + +#define ASD_DESC_END_OFF 25 +#define ASD_DESC_END_MASK 0x1 +#define ASD_DESC_END(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_END_MASK, ASD_DESC_END_OFF)) +#define ASD_DESC_END_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_END_MASK, ASD_DESC_END_OFF)) + +#define ASD_DESC_OP_OFF 26 +#define ASD_DESC_OP_MASK 0x2 +#define ASD_DESC_OP(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF)) +#define ASD_DESC_OP_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF)) + +#define ASD_DESC_ENCONLY_OFF 28 +#define ASD_DESC_ENCONLY_MASK 0x1 +#define ASD_DESC_ENCONLY(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF)) +#define ASD_DESC_ENCONLY_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF)) + +#define ASD_DESC_BLOCK_OFF 29 +#define ASD_DESC_BLOCK_MASK 0x1 +#define ASD_DESC_BLOCK(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF)) +#define ASD_DESC_BLOCK_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF)) + +#define ASD_DESC_ERR_OFF 30 +#define ASD_DESC_ERR_MASK 0x1 +#define ASD_DESC_ERR(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF)) +#define ASD_DESC_ERR_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF)) + +#define ASD_DESC_OWNER_OFF 31u +#define ASD_DESC_OWNER_MASK 0x1u +#define ASD_DESC_OWNER(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF)) +#define ASD_DESC_OWNER_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF)) + +static void asd_compute_sha(struct asd_ctx *ctx, void *data, size_t len, + int finalize) +{ + /* Make it cache line size aligned ? */ + struct asd_desc desc = { + .src = (uint32_t)(uintptr_t)data, + .dst = (uint32_t)(uintptr_t)ctx->digest, + }; + + /* Check data address is 32bit compatible */ + assert((uintptr_t)data == (uintptr_t)desc.src); + assert((uintptr_t)ctx->digest == (uintptr_t)desc.dst); + assert((uintptr_t)&desc == (uintptr_t)&desc); + + ASD_DESC_LEN_SET(&desc, len); + ASD_DESC_OWNER_SET(&desc, 1u); + ASD_DESC_ENCONLY_SET(&desc, 1); + ASD_DESC_EOD_SET(&desc, 1); + if (ctx->started == 0) { + ASD_DESC_BEGIN_SET(&desc, 1); + ctx->started = 1; + } + if (finalize) { + ASD_DESC_END_SET(&desc, 1); + ctx->started = 0; + } + if (ctx->mode == ASM_SHA224) + ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA224); + else + ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA256); + + flush_dcache_range((uintptr_t)&desc, sizeof(desc)); + flush_dcache_range((uintptr_t)data, len); + + mmio_write_32(AML_SHA_DMA_STATUS, 0xf); + mmio_write_32(AML_SHA_DMA_DESC, ((uintptr_t)&desc) | 2); + while (mmio_read_32(AML_SHA_DMA_STATUS) == 0) + continue; + flush_dcache_range((uintptr_t)ctx->digest, SHA256_HASHSZ); +} + +void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len) +{ + size_t nr; + + if (ctx->blocksz) { + nr = MIN(len, SHA256_BLOCKSZ - ctx->blocksz); + memcpy(ctx->block + ctx->blocksz, data, nr); + ctx->blocksz += nr; + len -= nr; + data += nr; + } + + if (ctx->blocksz == SHA256_BLOCKSZ) { + asd_compute_sha(ctx, ctx->block, SHA256_BLOCKSZ, 0); + ctx->blocksz = 0; + } + + asd_compute_sha(ctx, data, len & ~(SHA256_BLOCKSZ - 1), 0); + data += len & ~(SHA256_BLOCKSZ - 1); + + if (len & (SHA256_BLOCKSZ - 1)) { + nr = len & (SHA256_BLOCKSZ - 1); + memcpy(ctx->block + ctx->blocksz, data, nr); + ctx->blocksz += nr; + } +} + +void asd_sha_finalize(struct asd_ctx *ctx) +{ + asd_compute_sha(ctx, ctx->block, ctx->blocksz, 1); +} diff --git a/arm-trusted-firmware/drivers/arm/cci/cci.c b/arm-trusted-firmware/drivers/arm/cci/cci.c new file mode 100644 index 0000000..2adfe17 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/cci/cci.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAKE_CCI_PART_NUMBER(hi, lo) (((hi) << 8) | (lo)) +#define CCI_PART_LO_MASK U(0xff) +#define CCI_PART_HI_MASK U(0xf) + +/* CCI part number codes read from Peripheral ID registers 0 and 1 */ +#define CCI400_PART_NUM 0x420 +#define CCI500_PART_NUM 0x422 +#define CCI550_PART_NUM 0x423 + +#define CCI400_SLAVE_PORTS 5 +#define CCI500_SLAVE_PORTS 7 +#define CCI550_SLAVE_PORTS 7 + +static uintptr_t cci_base; +static const int *cci_slave_if_map; + +#if ENABLE_ASSERTIONS +static unsigned int max_master_id; +static int cci_num_slave_ports; + +static bool validate_cci_map(const int *map) +{ + unsigned int valid_cci_map = 0U; + int slave_if_id; + unsigned int i; + + /* Validate the map */ + for (i = 0U; i <= max_master_id; i++) { + slave_if_id = map[i]; + + if (slave_if_id < 0) + continue; + + if (slave_if_id >= cci_num_slave_ports) { + ERROR("Slave interface ID is invalid\n"); + return false; + } + + if ((valid_cci_map & (1UL << slave_if_id)) != 0U) { + ERROR("Multiple masters are assigned same slave interface ID\n"); + return false; + } + valid_cci_map |= 1UL << slave_if_id; + } + + if (valid_cci_map == 0U) { + ERROR("No master is assigned a valid slave interface\n"); + return false; + } + + return true; +} + +/* + * Read CCI part number from Peripheral ID registers + */ +static unsigned int read_cci_part_number(uintptr_t base) +{ + unsigned int part_lo, part_hi; + + part_lo = mmio_read_32(base + PERIPHERAL_ID0) & CCI_PART_LO_MASK; + part_hi = mmio_read_32(base + PERIPHERAL_ID1) & CCI_PART_HI_MASK; + + return MAKE_CCI_PART_NUMBER(part_hi, part_lo); +} + +/* + * Identify a CCI device, and return the number of slaves. Return -1 for an + * unidentified device. + */ +static int get_slave_ports(unsigned int part_num) +{ + int num_slave_ports = -1; + + switch (part_num) { + + case CCI400_PART_NUM: + num_slave_ports = CCI400_SLAVE_PORTS; + break; + case CCI500_PART_NUM: + num_slave_ports = CCI500_SLAVE_PORTS; + break; + case CCI550_PART_NUM: + num_slave_ports = CCI550_SLAVE_PORTS; + break; + default: + /* Do nothing in default case */ + break; + } + + return num_slave_ports; +} +#endif /* ENABLE_ASSERTIONS */ + +void __init cci_init(uintptr_t base, const int *map, + unsigned int num_cci_masters) +{ + assert(map != NULL); + assert(base != 0U); + + cci_base = base; + cci_slave_if_map = map; + +#if ENABLE_ASSERTIONS + /* + * Master Id's are assigned from zero, So in an array of size n + * the max master id is (n - 1). + */ + max_master_id = num_cci_masters - 1U; + cci_num_slave_ports = get_slave_ports(read_cci_part_number(base)); +#endif + assert(cci_num_slave_ports >= 0); + + assert(validate_cci_map(map)); +} + +void cci_enable_snoop_dvm_reqs(unsigned int master_id) +{ + int slave_if_id = cci_slave_if_map[master_id]; + + assert(master_id <= max_master_id); + assert((slave_if_id < cci_num_slave_ports) && (slave_if_id >= 0)); + assert(cci_base != 0U); + + /* + * Enable Snoops and DVM messages, no need for Read/Modify/Write as + * rest of bits are write ignore + */ + mmio_write_32(cci_base + + SLAVE_IFACE_OFFSET(slave_if_id) + SNOOP_CTRL_REG, + DVM_EN_BIT | SNOOP_EN_BIT); + + /* + * Wait for the completion of the write to the Snoop Control Register + * before testing the change_pending bit + */ + dsbish(); + + /* Wait for the dust to settle down */ + while ((mmio_read_32(cci_base + STATUS_REG) & CHANGE_PENDING_BIT) != 0U) + ; +} + +void cci_disable_snoop_dvm_reqs(unsigned int master_id) +{ + int slave_if_id = cci_slave_if_map[master_id]; + + assert(master_id <= max_master_id); + assert((slave_if_id < cci_num_slave_ports) && (slave_if_id >= 0)); + assert(cci_base != 0U); + + /* + * Disable Snoops and DVM messages, no need for Read/Modify/Write as + * rest of bits are write ignore. + */ + mmio_write_32(cci_base + + SLAVE_IFACE_OFFSET(slave_if_id) + SNOOP_CTRL_REG, + ~(DVM_EN_BIT | SNOOP_EN_BIT)); + + /* + * Wait for the completion of the write to the Snoop Control Register + * before testing the change_pending bit + */ + dsbish(); + + /* Wait for the dust to settle down */ + while ((mmio_read_32(cci_base + STATUS_REG) & CHANGE_PENDING_BIT) != 0U) + ; +} + diff --git a/arm-trusted-firmware/drivers/arm/ccn/ccn.c b/arm-trusted-firmware/drivers/arm/ccn/ccn.c new file mode 100644 index 0000000..5b13250 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/ccn/ccn.c @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "ccn_private.h" + +static const ccn_desc_t *ccn_plat_desc; +#if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) +DEFINE_BAKERY_LOCK(ccn_lock); +#endif + +/******************************************************************************* + * This function takes the base address of the CCN's programmer's view (PV), a + * region ID of one of the 256 regions (0-255) and a register offset within the + * region. It converts the first two parameters into a base address and uses it + * to read the register at the offset. + ******************************************************************************/ +static inline unsigned long long ccn_reg_read(uintptr_t periphbase, + unsigned int region_id, + unsigned int register_offset) +{ + uintptr_t region_base; + + assert(periphbase); + assert(region_id < REGION_ID_LIMIT); + + region_base = periphbase + region_id_to_base(region_id); + return mmio_read_64(region_base + register_offset); +} + +/******************************************************************************* + * This function takes the base address of the CCN's programmer's view (PV), a + * region ID of one of the 256 regions (0-255), a register offset within the + * region and a value. It converts the first two parameters into a base address + * and uses it to write the value in the register at the offset. + ******************************************************************************/ +static inline void ccn_reg_write(uintptr_t periphbase, + unsigned int region_id, + unsigned int register_offset, + unsigned long long value) +{ + uintptr_t region_base; + + assert(periphbase); + assert(region_id < REGION_ID_LIMIT); + + region_base = periphbase + region_id_to_base(region_id); + mmio_write_64(region_base + register_offset, value); +} + +#if ENABLE_ASSERTIONS + +typedef struct rn_info { + unsigned char node_desc[MAX_RN_NODES]; + } rn_info_t; + +/******************************************************************************* + * This function takes the base address of the CCN's programmer's view (PV) and + * the node ID of a Request Node (RN-D or RN-I). It returns the maximum number + * of master interfaces resident on that node. This number is equal to the least + * significant two bits of the node type ID + 1. + ******************************************************************************/ +static unsigned int ccn_get_rni_mcount(uintptr_t periphbase, + unsigned int rn_id) +{ + unsigned int rn_type_id; + + /* Use the node id to find the type of RN-I/D node */ + rn_type_id = get_node_type(ccn_reg_read(periphbase, + rn_id + RNI_REGION_ID_START, + REGION_ID_OFFSET)); + + /* Return the number master interfaces based on node type */ + return rn_type_id_to_master_cnt(rn_type_id); +} + +/******************************************************************************* + * This function reads the CCN registers to find the following information about + * the ACE/ACELite/ACELite+DVM/CHI interfaces resident on the various types of + * Request Nodes (RN-Fs, RN-Is and RN-Ds) in the system: + * + * 1. The total number of such interfaces that this CCN IP supports. This is the + * cumulative number of interfaces across all Request node types. It is + * passed back as the return value of this function. + * + * 2. The maximum number of interfaces of a type resident on a Request node of + * one of the three types. This information is populated in the 'info' + * array provided by the caller as described next. + * + * The array has 64 entries. Each entry corresponds to a Request node. The + * Miscellaneous node's programmer's view has RN-F, RN-I and RN-D ID + * registers. For each RN-I and RN-D ID indicated as being present in these + * registers, its identification register (offset 0xFF00) is read. This + * register specifies the maximum number of master interfaces the node + * supports. For RN-Fs it is assumed that there can be only a single fully + * coherent master resident on each node. The counts for each type of node + * are use to populate the array entry at the index corresponding to the node + * ID i.e. rn_info[node ID] = + ******************************************************************************/ +static unsigned int ccn_get_rn_master_info(uintptr_t periphbase, + rn_info_t *info) +{ + unsigned int num_masters = 0; + rn_types_t rn_type; + + assert (info); + + for (rn_type = RN_TYPE_RNF; rn_type < NUM_RN_TYPES; rn_type++) { + unsigned int mn_reg_off, node_id; + unsigned long long rn_bitmap; + + /* + * RN-F, RN-I, RN-D node registers in the MN region occupy + * contiguous 16 byte apart offsets. + */ + mn_reg_off = MN_RNF_NODEID_OFFSET + (rn_type << 4); + rn_bitmap = ccn_reg_read(periphbase, MN_REGION_ID, mn_reg_off); + + FOR_EACH_PRESENT_NODE_ID(node_id, rn_bitmap) { + unsigned int node_mcount; + + /* + * A RN-F does not have a node type since it does not + * export a programmer's interface. It can only have a + * single fully coherent master residing on it. If the + * offset of the MN(Miscellaneous Node) register points + * to a RN-I/D node then the master count is set to the + * maximum number of master interfaces that can possibly + * reside on the node. + */ + node_mcount = (mn_reg_off == MN_RNF_NODEID_OFFSET ? 1 : + ccn_get_rni_mcount(periphbase, node_id)); + + /* + * Use this value to increment the maximum possible + * master interfaces in the system. + */ + num_masters += node_mcount; + + /* + * Update the entry in 'info' for this node ID with + * the maximum number of masters than can sit on + * it. This information will be used to validate the + * node information passed by the platform later. + */ + info->node_desc[node_id] = node_mcount; + } + } + + return num_masters; +} + +/******************************************************************************* + * This function validates parameters passed by the platform (in a debug build). + * It collects information about the maximum number of master interfaces that: + * a) the CCN IP can accommodate and + * b) can exist on each Request node. + * It compares this with the information provided by the platform to determine + * the validity of the latter. + ******************************************************************************/ +static void __init ccn_validate_plat_params(const ccn_desc_t *plat_desc) +{ + unsigned int master_id, num_rn_masters; + rn_info_t info = { {0} }; + + assert(plat_desc); + assert(plat_desc->periphbase); + assert(plat_desc->master_to_rn_id_map); + assert(plat_desc->num_masters); + assert(plat_desc->num_masters < CCN_MAX_RN_MASTERS); + + /* + * Find the number and properties of fully coherent, IO coherent and IO + * coherent + DVM master interfaces + */ + num_rn_masters = ccn_get_rn_master_info(plat_desc->periphbase, &info); + assert(plat_desc->num_masters < num_rn_masters); + + /* + * Iterate through the Request nodes specified by the platform. + * Decrement the count of the masters in the 'info' array for each + * Request node encountered. If the count would drop below 0 then the + * platform's view of this aspect of CCN configuration is incorrect. + */ + for (master_id = 0; master_id < plat_desc->num_masters; master_id++) { + unsigned int node_id; + + node_id = plat_desc->master_to_rn_id_map[master_id]; + assert(node_id < MAX_RN_NODES); + assert(info.node_desc[node_id]); + info.node_desc[node_id]--; + } +} +#endif /* ENABLE_ASSERTIONS */ + +/******************************************************************************* + * This function validates parameters passed by the platform (in a debug build) + * and initialises its internal data structures. A lock is required to prevent + * simultaneous CCN operations at runtime (only BL31) to add and remove Request + * nodes from coherency. + ******************************************************************************/ +void __init ccn_init(const ccn_desc_t *plat_desc) +{ +#if ENABLE_ASSERTIONS + ccn_validate_plat_params(plat_desc); +#endif + + ccn_plat_desc = plat_desc; +} + +/******************************************************************************* + * This function converts a bit map of master interface IDs to a bit map of the + * Request node IDs that they reside on. + ******************************************************************************/ +static unsigned long long ccn_master_to_rn_id_map(unsigned long long master_map) +{ + unsigned long long rn_id_map = 0; + unsigned int node_id, iface_id; + + assert(master_map); + assert(ccn_plat_desc); + + FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, master_map) { + assert(iface_id < ccn_plat_desc->num_masters); + + /* Convert the master ID into the node ID */ + node_id = ccn_plat_desc->master_to_rn_id_map[iface_id]; + + /* Set the bit corresponding to this node ID */ + rn_id_map |= (1ULL << node_id); + } + + return rn_id_map; +} + +/******************************************************************************* + * This function executes the necessary operations to add or remove Request node + * IDs specified in the 'rn_id_map' bitmap from the snoop/DVM domains specified + * in the 'hn_id_map'. The 'region_id' specifies the ID of the first HN-F/MN + * on which the operation should be performed. 'op_reg_offset' specifies the + * type of operation (add/remove). 'stat_reg_offset' specifies the register + * which should be polled to determine if the operation has completed or not. + ******************************************************************************/ +static void ccn_snoop_dvm_do_op(unsigned long long rn_id_map, + unsigned long long hn_id_map, + unsigned int region_id, + unsigned int op_reg_offset, + unsigned int stat_reg_offset) +{ + unsigned int start_region_id; + + assert(ccn_plat_desc); + assert(ccn_plat_desc->periphbase); + +#if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) + bakery_lock_get(&ccn_lock); +#endif + start_region_id = region_id; + FOR_EACH_PRESENT_REGION_ID(start_region_id, hn_id_map) { + ccn_reg_write(ccn_plat_desc->periphbase, + start_region_id, + op_reg_offset, + rn_id_map); + } + + start_region_id = region_id; + + FOR_EACH_PRESENT_REGION_ID(start_region_id, hn_id_map) { + WAIT_FOR_DOMAIN_CTRL_OP_COMPLETION(start_region_id, + stat_reg_offset, + op_reg_offset, + rn_id_map); + } + +#if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) + bakery_lock_release(&ccn_lock); +#endif +} + +/******************************************************************************* + * The following functions provide the boot and runtime API to the platform for + * adding and removing master interfaces from the snoop/DVM domains. A bitmap of + * master interfaces IDs is passed as a parameter. It is converted into a bitmap + * of Request node IDs using the mapping provided by the platform while + * initialising the driver. + * For example, consider a dual cluster system where the clusters have values 0 + * & 1 in the affinity level 1 field of their respective MPIDRs. While + * initialising this driver, the platform provides the mapping between each + * cluster and the corresponding Request node. To add or remove a cluster from + * the snoop and dvm domain, the bit position corresponding to the cluster ID + * should be set in the 'master_iface_map' i.e. to remove both clusters the + * bitmap would equal 0x11. + ******************************************************************************/ +void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map) +{ + unsigned long long rn_id_map; + + rn_id_map = ccn_master_to_rn_id_map(master_iface_map); + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_HN_NODEID_MAP(ccn_plat_desc->periphbase, + MN_HNF_NODEID_OFFSET), + HNF_REGION_ID_START, + HNF_SDC_SET_OFFSET, + HNF_SDC_STAT_OFFSET); + + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase), + MN_REGION_ID, + MN_DDC_SET_OFFSET, + MN_DDC_STAT_OFFSET); +} + +void ccn_exit_snoop_dvm_domain(unsigned long long master_iface_map) +{ + unsigned long long rn_id_map; + + rn_id_map = ccn_master_to_rn_id_map(master_iface_map); + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_HN_NODEID_MAP(ccn_plat_desc->periphbase, + MN_HNF_NODEID_OFFSET), + HNF_REGION_ID_START, + HNF_SDC_CLR_OFFSET, + HNF_SDC_STAT_OFFSET); + + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase), + MN_REGION_ID, + MN_DDC_CLR_OFFSET, + MN_DDC_STAT_OFFSET); +} + +void ccn_enter_dvm_domain(unsigned long long master_iface_map) +{ + unsigned long long rn_id_map; + + rn_id_map = ccn_master_to_rn_id_map(master_iface_map); + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase), + MN_REGION_ID, + MN_DDC_SET_OFFSET, + MN_DDC_STAT_OFFSET); +} + +void ccn_exit_dvm_domain(unsigned long long master_iface_map) +{ + unsigned long long rn_id_map; + + rn_id_map = ccn_master_to_rn_id_map(master_iface_map); + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase), + MN_REGION_ID, + MN_DDC_CLR_OFFSET, + MN_DDC_STAT_OFFSET); +} + +/******************************************************************************* + * This function returns the run mode of all the L3 cache partitions in the + * system. The state is expected to be one of NO_L3, SF_ONLY, L3_HAM or + * L3_FAM. Instead of comparing the states reported by all HN-Fs, the state of + * the first present HN-F node is reported. Since the driver does not export an + * interface to program them separately, there is no reason to perform this + * check. An HN-F could report that the L3 cache is transitioning from one mode + * to another e.g. HNF_PM_NOL3_2_SFONLY. In this case, the function waits for + * the transition to complete and reports the final state. + ******************************************************************************/ +unsigned int ccn_get_l3_run_mode(void) +{ + unsigned long long hnf_pstate_stat; + + assert(ccn_plat_desc); + assert(ccn_plat_desc->periphbase); + + /* + * Wait for a L3 cache partition to enter any run mode. The pstate + * parameter is read from an HN-F P-state status register. A non-zero + * value in bits[1:0] means that the cache is transitioning to a run + * mode. + */ + do { + hnf_pstate_stat = ccn_reg_read(ccn_plat_desc->periphbase, + HNF_REGION_ID_START, + HNF_PSTATE_STAT_OFFSET); + } while (hnf_pstate_stat & 0x3); + + return PSTATE_TO_RUN_MODE(hnf_pstate_stat); +} + +/******************************************************************************* + * This function sets the run mode of all the L3 cache partitions in the + * system to one of NO_L3, SF_ONLY, L3_HAM or L3_FAM depending upon the state + * specified by the 'mode' argument. + ******************************************************************************/ +void ccn_set_l3_run_mode(unsigned int mode) +{ + unsigned long long mn_hnf_id_map, hnf_pstate_stat; + unsigned int region_id; + + assert(ccn_plat_desc); + assert(ccn_plat_desc->periphbase); + assert(mode <= CCN_L3_RUN_MODE_FAM); + + mn_hnf_id_map = ccn_reg_read(ccn_plat_desc->periphbase, + MN_REGION_ID, + MN_HNF_NODEID_OFFSET); + region_id = HNF_REGION_ID_START; + + /* Program the desired run mode */ + FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) { + ccn_reg_write(ccn_plat_desc->periphbase, + region_id, + HNF_PSTATE_REQ_OFFSET, + mode); + } + + /* Wait for the caches to transition to the run mode */ + region_id = HNF_REGION_ID_START; + FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) { + /* + * Wait for a L3 cache partition to enter a target run + * mode. The pstate parameter is read from an HN-F P-state + * status register. + */ + do { + hnf_pstate_stat = ccn_reg_read(ccn_plat_desc->periphbase, + region_id, + HNF_PSTATE_STAT_OFFSET); + } while (((hnf_pstate_stat & HNF_PSTATE_MASK) >> 2) != mode); + } +} + +/******************************************************************************* + * This function configures system address map and provides option to enable the + * 3SN striping mode of Slave node operation. The Slave node IDs and the Top + * Address bit1 and bit0 are provided as parameters to this function. This + * configuration is needed only if network contains a single SN-F or 3 SN-F and + * must be completed before the first request by the system to normal memory. + ******************************************************************************/ +void ccn_program_sys_addrmap(unsigned int sn0_id, + unsigned int sn1_id, + unsigned int sn2_id, + unsigned int top_addr_bit0, + unsigned int top_addr_bit1, + unsigned char three_sn_en) +{ + unsigned long long mn_hnf_id_map, hnf_sam_ctrl_value; + unsigned int region_id; + + assert(ccn_plat_desc); + assert(ccn_plat_desc->periphbase); + + mn_hnf_id_map = ccn_reg_read(ccn_plat_desc->periphbase, + MN_REGION_ID, + MN_HNF_NODEID_OFFSET); + region_id = HNF_REGION_ID_START; + hnf_sam_ctrl_value = MAKE_HNF_SAM_CTRL_VALUE(sn0_id, + sn1_id, + sn2_id, + top_addr_bit0, + top_addr_bit1, + three_sn_en); + + FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) { + + /* Program the SAM control register */ + ccn_reg_write(ccn_plat_desc->periphbase, + region_id, + HNF_SAM_CTRL_OFFSET, + hnf_sam_ctrl_value); + } + +} + +/******************************************************************************* + * This function returns the part0 id from the peripheralID 0 register + * in CCN. This id can be used to distinguish the CCN variant present in the + * system. + ******************************************************************************/ +int ccn_get_part0_id(uintptr_t periphbase) +{ + assert(periphbase); + return (int)(mmio_read_64(periphbase + + MN_PERIPH_ID_0_1_OFFSET) & 0xFF); +} + +/******************************************************************************* + * This function returns the region id corresponding to a node_id of node_type. + ******************************************************************************/ +static unsigned int get_region_id_for_node(node_types_t node_type, + unsigned int node_id) +{ + unsigned int mn_reg_off, region_id; + unsigned long long node_bitmap; + unsigned int loc_node_id, node_pos_in_map = 0; + + assert(node_type < NUM_NODE_TYPES); + assert(node_id < MAX_RN_NODES); + + switch (node_type) { + case NODE_TYPE_RNI: + region_id = RNI_REGION_ID_START; + break; + case NODE_TYPE_HNF: + region_id = HNF_REGION_ID_START; + break; + case NODE_TYPE_HNI: + region_id = HNI_REGION_ID_START; + break; + case NODE_TYPE_SN: + region_id = SBSX_REGION_ID_START; + break; + default: + ERROR("Un-supported Node Type = %d.\n", node_type); + assert(false); + return REGION_ID_LIMIT; + } + /* + * RN-I, HN-F, HN-I, SN node registers in the MN region + * occupy contiguous 16 byte apart offsets. + * + * RN-F and RN-D node are not supported as + * none of them exposes any memory map to + * configure any of their offset registers. + */ + + mn_reg_off = MN_RNF_NODEID_OFFSET + (node_type << 4); + node_bitmap = ccn_reg_read(ccn_plat_desc->periphbase, + MN_REGION_ID, mn_reg_off); + + assert((node_bitmap & (1ULL << (node_id))) != 0U); + + + FOR_EACH_PRESENT_NODE_ID(loc_node_id, node_bitmap) { + INFO("Index = %u with loc_nod=%u and input nod=%u\n", + node_pos_in_map, loc_node_id, node_id); + if (loc_node_id == node_id) + break; + node_pos_in_map++; + } + + if (node_pos_in_map == CCN_MAX_RN_MASTERS) { + ERROR("Node Id = %d, is not found.\n", node_id); + assert(false); + return REGION_ID_LIMIT; + } + + /* + * According to section 3.1.1 in CCN specification, region offset for + * the RN-I components is calculated as (128 + NodeID of RN-I). + */ + if (node_type == NODE_TYPE_RNI) + region_id += node_id; + else + region_id += node_pos_in_map; + + return region_id; +} + +/******************************************************************************* + * This function sets the value 'val' to the register at register_offset from + * the base address pointed to by the region_id. + * where, region id is mapped to a node_id of node_type. + ******************************************************************************/ +void ccn_write_node_reg(node_types_t node_type, unsigned int node_id, + unsigned int reg_offset, unsigned long long val) +{ + unsigned int region_id = get_region_id_for_node(node_type, node_id); + + if (reg_offset > REGION_ID_OFFSET) { + ERROR("Invalid Register offset 0x%x is provided.\n", + reg_offset); + assert(false); + return; + } + + /* Setting the value of Auxiliary Control Register of the Node */ + ccn_reg_write(ccn_plat_desc->periphbase, region_id, reg_offset, val); + VERBOSE("Value is successfully written at address 0x%lx.\n", + (ccn_plat_desc->periphbase + + region_id_to_base(region_id)) + + reg_offset); +} + +/******************************************************************************* + * This function read the value 'val' stored in the register at register_offset + * from the base address pointed to by the region_id. + * where, region id is mapped to a node_id of node_type. + ******************************************************************************/ +unsigned long long ccn_read_node_reg(node_types_t node_type, + unsigned int node_id, + unsigned int reg_offset) +{ + unsigned long long val; + unsigned int region_id = get_region_id_for_node(node_type, node_id); + + if (reg_offset > REGION_ID_OFFSET) { + ERROR("Invalid Register offset 0x%x is provided.\n", + reg_offset); + assert(false); + return ULL(0); + } + + /* Setting the value of Auxiliary Control Register of the Node */ + val = ccn_reg_read(ccn_plat_desc->periphbase, region_id, reg_offset); + VERBOSE("Value is successfully read from address 0x%lx.\n", + (ccn_plat_desc->periphbase + + region_id_to_base(region_id)) + + reg_offset); + + return val; +} diff --git a/arm-trusted-firmware/drivers/arm/ccn/ccn_private.h b/arm-trusted-firmware/drivers/arm/ccn/ccn_private.h new file mode 100644 index 0000000..8a936d9 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/ccn/ccn_private.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CCN_PRIVATE_H +#define CCN_PRIVATE_H + +/* + * A CCN implementation can have a maximum of 64 Request nodes with node IDs + * from 0-63. These IDs are split across the three types of Request nodes + * i.e. RN-F, RN-D and RN-I. + */ +#define MAX_RN_NODES 64 + +/* Enum used to loop through the 3 types of Request nodes */ +typedef enum rn_types { + RN_TYPE_RNF = 0, + RN_TYPE_RNI, + RN_TYPE_RND, + NUM_RN_TYPES +} rn_types_t; + +/* Macro to convert a region id to its base address */ +#define region_id_to_base(id) ((id) << 16) + +/* + * Macro to calculate the number of master interfaces resident on a RN-I/RN-D. + * Value of first two bits of the RN-I/D node type + 1 == Maximum number of + * ACE-Lite or ACE-Lite+DVM interfaces supported on this node. E.g. + * + * 0x14 : RN-I with 1 ACE-Lite interface + * 0x15 : RN-I with 2 ACE-Lite interfaces + * 0x16 : RN-I with 3 ACE-Lite interfaces + */ +#define rn_type_id_to_master_cnt(id) (((id) & 0x3) + 1) + +/* + * Constants used to identify a region in the programmer's view. These are + * common for all regions. + */ +#define REGION_ID_LIMIT 256 +#define REGION_ID_OFFSET 0xFF00 + +#define REGION_NODE_ID_SHIFT 8 +#define REGION_NODE_ID_MASK 0x7f +#define get_node_id(id_reg) (((id_reg) >> REGION_NODE_ID_SHIFT) \ + & REGION_NODE_ID_MASK) + +#define REGION_NODE_TYPE_SHIFT 0 +#define REGION_NODE_TYPE_MASK 0x1f +#define get_node_type(id_reg) (((id_reg) >> REGION_NODE_TYPE_SHIFT) \ + & REGION_NODE_TYPE_MASK) + +/* Common offsets of registers to enter or exit a snoop/dvm domain */ +#define DOMAIN_CTRL_STAT_OFFSET 0x0200 +#define DOMAIN_CTRL_SET_OFFSET 0x0210 +#define DOMAIN_CTRL_CLR_OFFSET 0x0220 + +/* + * Thess macros are used to determine if an operation to add or remove a Request + * node from the snoop/dvm domain has completed. 'rn_id_map' is a bit map of + * nodes. It was used to program the SET or CLEAR control register. The type of + * register is specified by 'op_reg_offset'. 'status_reg' is the bit map of + * nodes currently present in the snoop/dvm domain. 'rn_id_map' and 'status_reg' + * are logically ANDed and the result it stored back in the 'status_reg'. There + * are two outcomes of this operation: + * + * 1. If the DOMAIN_CTRL_SET_OFFSET register was programmed, then the set bits in + * 'rn_id_map' should appear in 'status_reg' when the operation completes. So + * after the AND operation, at some point of time 'status_reg' should equal + * 'rn_id_map'. + * + * 2. If the DOMAIN_CTRL_CLR_OFFSET register was programmed, then the set bits in + * 'rn_id_map' should disappear in 'status_reg' when the operation + * completes. So after the AND operation, at some point of time 'status_reg' + * should equal 0. + */ +#define WAIT_FOR_DOMAIN_CTRL_OP_COMPLETION(region_id, stat_reg_offset, \ + op_reg_offset, rn_id_map) \ + { \ + unsigned long long status_reg; \ + do { \ + status_reg = ccn_reg_read((ccn_plat_desc->periphbase), \ + (region_id), \ + (stat_reg_offset)); \ + status_reg &= (rn_id_map); \ + } while ((op_reg_offset) == DOMAIN_CTRL_SET_OFFSET ? \ + (rn_id_map) != status_reg : status_reg); \ + } + +/* + * Region ID of the Miscellaneous Node is always 0 as its located at the base of + * the programmer's view. + */ +#define MN_REGION_ID 0 + +#define MN_REGION_ID_START 0 +#define DEBUG_REGION_ID_START 1 +#define HNI_REGION_ID_START 8 +#define SBSX_REGION_ID_START 16 +#define HNF_REGION_ID_START 32 +#define XP_REGION_ID_START 64 +#define RNI_REGION_ID_START 128 + +/* Selected register offsets from the base of a HNF region */ +#define HNF_CFG_CTRL_OFFSET 0x0000 +#define HNF_SAM_CTRL_OFFSET 0x0008 +#define HNF_PSTATE_REQ_OFFSET 0x0010 +#define HNF_PSTATE_STAT_OFFSET 0x0018 +#define HNF_SDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET +#define HNF_SDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET +#define HNF_SDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET +#define HNF_AUX_CTRL_OFFSET 0x0500 + +/* Selected register offsets from the base of a MN region */ +#define MN_SAR_OFFSET 0x0000 +#define MN_RNF_NODEID_OFFSET 0x0180 +#define MN_RNI_NODEID_OFFSET 0x0190 +#define MN_RND_NODEID_OFFSET 0x01A0 +#define MN_HNF_NODEID_OFFSET 0x01B0 +#define MN_HNI_NODEID_OFFSET 0x01C0 +#define MN_SN_NODEID_OFFSET 0x01D0 +#define MN_DDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET +#define MN_DDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET +#define MN_DDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET +#define MN_PERIPH_ID_0_1_OFFSET 0xFE0 +#define MN_ID_OFFSET REGION_ID_OFFSET + +/* HNF System Address Map register bit masks and shifts */ +#define HNF_SAM_CTRL_SN_ID_MASK 0x7f +#define HNF_SAM_CTRL_SN0_ID_SHIFT 0 +#define HNF_SAM_CTRL_SN1_ID_SHIFT 8 +#define HNF_SAM_CTRL_SN2_ID_SHIFT 16 + +#define HNF_SAM_CTRL_TAB0_MASK ULL(0x3f) +#define HNF_SAM_CTRL_TAB0_SHIFT 48 +#define HNF_SAM_CTRL_TAB1_MASK ULL(0x3f) +#define HNF_SAM_CTRL_TAB1_SHIFT 56 + +#define HNF_SAM_CTRL_3SN_ENB_SHIFT 32 +#define HNF_SAM_CTRL_3SN_ENB_MASK ULL(0x01) + +/* + * Macro to create a value suitable for programming into a HNF SAM Control + * register for enabling 3SN striping. + */ +#define MAKE_HNF_SAM_CTRL_VALUE(sn0, sn1, sn2, tab0, tab1, three_sn_en) \ + ((((sn0) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN0_ID_SHIFT) | \ + (((sn1) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN1_ID_SHIFT) | \ + (((sn2) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN2_ID_SHIFT) | \ + (((tab0) & HNF_SAM_CTRL_TAB0_MASK) << HNF_SAM_CTRL_TAB0_SHIFT) | \ + (((tab1) & HNF_SAM_CTRL_TAB1_MASK) << HNF_SAM_CTRL_TAB1_SHIFT) | \ + (((three_sn_en) & HNF_SAM_CTRL_3SN_ENB_MASK) << HNF_SAM_CTRL_3SN_ENB_SHIFT)) + +/* Mask to read the power state value from an HN-F P-state register */ +#define HNF_PSTATE_MASK 0xf + +/* Macro to extract the run mode from a p-state value */ +#define PSTATE_TO_RUN_MODE(pstate) (((pstate) & HNF_PSTATE_MASK) >> 2) + +/* + * Helper macro that iterates through a given bit map. In each iteration, + * it returns the position of the set bit. + * It can be used by other utility macros to iterates through all nodes + * or masters given a bit map of them. + */ +#define FOR_EACH_BIT(bit_pos, bit_map) \ + for (bit_pos = __builtin_ctzll(bit_map); \ + bit_map; \ + bit_map &= ~(1ULL << (bit_pos)), \ + bit_pos = __builtin_ctzll(bit_map)) + +/* + * Utility macro that iterates through a bit map of node IDs. In each + * iteration, it returns the ID of the next present node in the bit map. Node + * ID of a present node == Position of set bit == Number of zeroes trailing the + * bit. + */ +#define FOR_EACH_PRESENT_NODE_ID(node_id, bit_map) \ + FOR_EACH_BIT(node_id, bit_map) + +/* + * Helper function to return number of set bits in bitmap + */ +static inline unsigned int count_set_bits(unsigned long long bitmap) +{ + unsigned int count = 0; + + for (; bitmap; bitmap &= bitmap - 1) + ++count; + + return count; +} + +/* + * Utility macro that iterates through a bit map of node IDs. In each iteration, + * it returns the ID of the next present region corresponding to a node present + * in the bit map. Region ID of a present node is in between passed region id + * and region id + number of set bits in the bitmap i.e. the number of present + * nodes. + */ +#define FOR_EACH_PRESENT_REGION_ID(region_id, bit_map) \ + for (unsigned long long region_id_limit = count_set_bits(bit_map) \ + + region_id; \ + region_id < region_id_limit; \ + region_id++) + +/* + * Same macro as FOR_EACH_PRESENT_NODE, but renamed to indicate it traverses + * through a bit map of master interfaces. + */ +#define FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, bit_map) \ + FOR_EACH_BIT(iface_id, bit_map) + +/* + * Macro that returns the node id bit map for the Miscellaneous Node + */ +#define CCN_GET_MN_NODEID_MAP(periphbase) \ + (1 << get_node_id(ccn_reg_read(periphbase, MN_REGION_ID, \ + REGION_ID_OFFSET))) + +/* + * This macro returns the bitmap of Home nodes on the basis of the + * 'mn_hn_id_reg_offset' parameter from the Miscellaneous node's (MN) + * programmer's view. The MN has a register which carries the bitmap of present + * Home nodes of each type i.e. HN-Fs, HN-Is & HN-Ds. + */ +#define CCN_GET_HN_NODEID_MAP(periphbase, mn_hn_id_reg_offset) \ + ccn_reg_read(periphbase, MN_REGION_ID, mn_hn_id_reg_offset) + +#endif /* CCN_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c b/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c new file mode 100644 index 0000000..b7faf7e --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include + +/* SCP MHU secure channel registers */ +#define SCP_INTR_S_STAT 0x200 +#define SCP_INTR_S_SET 0x208 +#define SCP_INTR_S_CLEAR 0x210 + +/* CPU MHU secure channel registers */ +#define CPU_INTR_S_STAT 0x300 +#define CPU_INTR_S_SET 0x308 +#define CPU_INTR_S_CLEAR 0x310 + +ARM_INSTANTIATE_LOCK; + +/* Weak definition may be overridden in specific CSS based platform */ +#pragma weak plat_arm_pwrc_setup + + +/* + * Slot 31 is reserved because the MHU hardware uses this register bit to + * indicate a non-secure access attempt. The total number of available slots is + * therefore 31 [30:0]. + */ +#define MHU_MAX_SLOT_ID 30 + +void mhu_secure_message_start(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + + arm_lock_get(); + + /* Make sure any previous command has finished */ + while (mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id)) + ; +} + +void mhu_secure_message_send(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + assert(!(mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id))); + + /* Send command to SCP */ + mmio_write_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id); +} + +uint32_t mhu_secure_message_wait(void) +{ + /* Wait for response from SCP */ + uint32_t response; + while (!(response = mmio_read_32(PLAT_CSS_MHU_BASE + SCP_INTR_S_STAT))) + ; + + return response; +} + +void mhu_secure_message_end(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + + /* + * Clear any response we got by writing one in the relevant slot bit to + * the CLEAR register + */ + mmio_write_32(PLAT_CSS_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id); + + arm_lock_release(); +} + +void __init mhu_secure_init(void) +{ + arm_lock_init(); + + /* + * The STAT register resets to zero. Ensure it is in the expected state, + * as a stale or garbage value would make us think it's a message we've + * already sent. + */ + assert(mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) == 0); +} + +void __init plat_arm_pwrc_setup(void) +{ + mhu_secure_init(); +} diff --git a/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c b/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c new file mode 100644 index 0000000..c51f3b1 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +void mhu_ring_doorbell(struct scmi_channel_plat_info *plat_info) +{ + MHU_RING_DOORBELL(plat_info->db_reg_addr, + plat_info->db_modify_mask, + plat_info->db_preserve_mask); + return; +} + +void mhuv2_ring_doorbell(struct scmi_channel_plat_info *plat_info) +{ + uintptr_t mhuv2_base = plat_info->db_reg_addr & MHU_V2_FRAME_BASE_MASK; + + /* wake receiver */ + MHU_V2_ACCESS_REQUEST(mhuv2_base); + + /* wait for receiver to acknowledge its ready */ + while (MHU_V2_IS_ACCESS_READY(mhuv2_base) == 0) + ; + + MHU_RING_DOORBELL(plat_info->db_reg_addr, + plat_info->db_modify_mask, + plat_info->db_preserve_mask); + + /* clear the access request for the receiver */ + MHU_V2_CLEAR_REQUEST(mhuv2_base); + + return; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c new file mode 100644 index 0000000..5941b87 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" + +/* + * API to set the SCMI AP core reset address and attributes + */ +int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_AP_CORE_PROTO_ID, + SCMI_AP_CORE_RESET_ADDR_SET_MSG, token); + mbx_mem->len = SCMI_AP_CORE_RESET_ADDR_SET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG3(mbx_mem->payload, reset_addr & 0xffffffff, + reset_addr >> 32, attr); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + assert(mbx_mem->len == SCMI_AP_CORE_RESET_ADDR_SET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to get the SCMI AP core reset address and attributes + */ +int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + uint32_t lo_addr, hi_addr; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_AP_CORE_PROTO_ID, + SCMI_AP_CORE_RESET_ADDR_GET_MSG, token); + mbx_mem->len = SCMI_AP_CORE_RESET_ADDR_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL4(mbx_mem->payload, ret, lo_addr, hi_addr, *attr); + *reset_addr = lo_addr | (uint64_t)hi_addr << 32; + assert(mbx_mem->len == SCMI_AP_CORE_RESET_ADDR_GET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c new file mode 100644 index 0000000..ec749fb --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" + +#if HW_ASSISTED_COHERENCY +#define scmi_lock_init(lock) +#define scmi_lock_get(lock) spin_lock(lock) +#define scmi_lock_release(lock) spin_unlock(lock) +#else +#define scmi_lock_init(lock) bakery_lock_init(lock) +#define scmi_lock_get(lock) bakery_lock_get(lock) +#define scmi_lock_release(lock) bakery_lock_release(lock) +#endif + + +/* + * Private helper function to get exclusive access to SCMI channel. + */ +void scmi_get_channel(scmi_channel_t *ch) +{ + assert(ch->lock); + scmi_lock_get(ch->lock); + + /* Make sure any previous command has finished */ + assert(SCMI_IS_CHANNEL_FREE( + ((mailbox_mem_t *)(ch->info->scmi_mbx_mem))->status)); +} + +/* + * Private helper function to transfer ownership of channel from AP to SCP. + */ +void scmi_send_sync_command(scmi_channel_t *ch) +{ + mailbox_mem_t *mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + + SCMI_MARK_CHANNEL_BUSY(mbx_mem->status); + + /* + * Ensure that any write to the SCMI payload area is seen by SCP before + * we write to the doorbell register. If these 2 writes were reordered + * by the CPU then SCP would read stale payload data + */ + dmbst(); + + ch->info->ring_doorbell(ch->info); + /* + * Ensure that the write to the doorbell register is ordered prior to + * checking whether the channel is free. + */ + dmbsy(); + + /* Wait for channel to be free */ + while (!SCMI_IS_CHANNEL_FREE(mbx_mem->status)) + ; + + /* + * Ensure that any read to the SCMI payload area is done after reading + * mailbox status. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); +} + +/* + * Private helper function to release exclusive access to SCMI channel. + */ +void scmi_put_channel(scmi_channel_t *ch) +{ + /* Make sure any previous command has finished */ + assert(SCMI_IS_CHANNEL_FREE( + ((mailbox_mem_t *)(ch->info->scmi_mbx_mem))->status)); + + assert(ch->lock); + scmi_lock_release(ch->lock); +} + +/* + * API to query the SCMI protocol version. + */ +int scmi_proto_version(void *p, uint32_t proto_id, uint32_t *version) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(proto_id, SCMI_PROTO_VERSION_MSG, + token); + mbx_mem->len = SCMI_PROTO_VERSION_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL2(mbx_mem->payload, ret, *version); + assert(mbx_mem->len == SCMI_PROTO_VERSION_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to query the protocol message attributes for a SCMI protocol. + */ +int scmi_proto_msg_attr(void *p, uint32_t proto_id, + uint32_t command_id, uint32_t *attr) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(proto_id, + SCMI_PROTO_MSG_ATTR_MSG, token); + mbx_mem->len = SCMI_PROTO_MSG_ATTR_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG1(mbx_mem->payload, command_id); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL2(mbx_mem->payload, ret, *attr); + assert(mbx_mem->len == SCMI_PROTO_MSG_ATTR_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * SCMI Driver initialization API. Returns initialized channel on success + * or NULL on error. The return type is an opaque void pointer. + */ +void *scmi_init(scmi_channel_t *ch) +{ + uint32_t version; + int ret; + + assert(ch && ch->info); + assert(ch->info->db_reg_addr); + assert(ch->info->db_modify_mask); + assert(ch->info->db_preserve_mask); + assert(ch->info->ring_doorbell != NULL); + + assert(ch->lock); + + scmi_lock_init(ch->lock); + + ch->is_initialized = 1; + + ret = scmi_proto_version(ch, SCMI_PWR_DMN_PROTO_ID, &version); + if (ret != SCMI_E_SUCCESS) { + WARN("SCMI power domain protocol version message failed\n"); + goto error; + } + + if (!is_scmi_version_compatible(SCMI_PWR_DMN_PROTO_VER, version)) { + WARN("SCMI power domain protocol version 0x%x incompatible with driver version 0x%x\n", + version, SCMI_PWR_DMN_PROTO_VER); + goto error; + } + + VERBOSE("SCMI power domain protocol version 0x%x detected\n", version); + + ret = scmi_proto_version(ch, SCMI_SYS_PWR_PROTO_ID, &version); + if ((ret != SCMI_E_SUCCESS)) { + WARN("SCMI system power protocol version message failed\n"); + goto error; + } + + if (!is_scmi_version_compatible(SCMI_SYS_PWR_PROTO_VER, version)) { + WARN("SCMI system power management protocol version 0x%x incompatible with driver version 0x%x\n", + version, SCMI_SYS_PWR_PROTO_VER); + goto error; + } + + VERBOSE("SCMI system power management protocol version 0x%x detected\n", + version); + + INFO("SCMI driver initialized\n"); + + return (void *)ch; + +error: + ch->is_initialized = 0; + return NULL; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h new file mode 100644 index 0000000..a684ca5 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCMI_PRIVATE_H +#define SCMI_PRIVATE_H + +#include + +/* + * SCMI power domain management protocol message and response lengths. It is + * calculated as sum of length in bytes of the message header (4) and payload + * area (the number of bytes of parameters or return values in the payload). + */ +#define SCMI_PROTO_VERSION_MSG_LEN 4 +#define SCMI_PROTO_VERSION_RESP_LEN 12 + +#define SCMI_PROTO_MSG_ATTR_MSG_LEN 8 +#define SCMI_PROTO_MSG_ATTR_RESP_LEN 12 + +#define SCMI_AP_CORE_RESET_ADDR_SET_MSG_LEN 16 +#define SCMI_AP_CORE_RESET_ADDR_SET_RESP_LEN 8 + +#define SCMI_AP_CORE_RESET_ADDR_GET_MSG_LEN 4 +#define SCMI_AP_CORE_RESET_ADDR_GET_RESP_LEN 20 + +#define SCMI_PWR_STATE_SET_MSG_LEN 16 +#define SCMI_PWR_STATE_SET_RESP_LEN 8 + +#define SCMI_PWR_STATE_GET_MSG_LEN 8 +#define SCMI_PWR_STATE_GET_RESP_LEN 12 + +#define SCMI_SYS_PWR_STATE_SET_MSG_LEN 12 +#define SCMI_SYS_PWR_STATE_SET_RESP_LEN 8 + +#define SCMI_SYS_PWR_STATE_GET_MSG_LEN 4 +#define SCMI_SYS_PWR_STATE_GET_RESP_LEN 12 + +/* SCMI message header format bit field */ +#define SCMI_MSG_ID_SHIFT 0 +#define SCMI_MSG_ID_WIDTH 8 +#define SCMI_MSG_ID_MASK ((1 << SCMI_MSG_ID_WIDTH) - 1) + +#define SCMI_MSG_TYPE_SHIFT 8 +#define SCMI_MSG_TYPE_WIDTH 2 +#define SCMI_MSG_TYPE_MASK ((1 << SCMI_MSG_TYPE_WIDTH) - 1) + +#define SCMI_MSG_PROTO_ID_SHIFT 10 +#define SCMI_MSG_PROTO_ID_WIDTH 8 +#define SCMI_MSG_PROTO_ID_MASK ((1 << SCMI_MSG_PROTO_ID_WIDTH) - 1) + +#define SCMI_MSG_TOKEN_SHIFT 18 +#define SCMI_MSG_TOKEN_WIDTH 10 +#define SCMI_MSG_TOKEN_MASK ((1 << SCMI_MSG_TOKEN_WIDTH) - 1) + + +/* SCMI mailbox flags */ +#define SCMI_FLAG_RESP_POLL 0 +#define SCMI_FLAG_RESP_INT 1 + +/* SCMI power domain protocol `POWER_STATE_SET` message flags */ +#define SCMI_PWR_STATE_SET_FLAG_SYNC 0 +#define SCMI_PWR_STATE_SET_FLAG_ASYNC 1 + +/* + * Helper macro to create an SCMI message header given protocol, message id + * and token. + */ +#define SCMI_MSG_CREATE(_protocol, _msg_id, _token) \ + ((((_protocol) & SCMI_MSG_PROTO_ID_MASK) << SCMI_MSG_PROTO_ID_SHIFT) | \ + (((_msg_id) & SCMI_MSG_ID_MASK) << SCMI_MSG_ID_SHIFT) | \ + (((_token) & SCMI_MSG_TOKEN_MASK) << SCMI_MSG_TOKEN_SHIFT)) + +/* Helper macro to get the token from a SCMI message header */ +#define SCMI_MSG_GET_TOKEN(_msg) \ + (((_msg) >> SCMI_MSG_TOKEN_SHIFT) & SCMI_MSG_TOKEN_MASK) + +/* SCMI Channel Status bit fields */ +#define SCMI_CH_STATUS_RES0_MASK 0xFFFFFFFE +#define SCMI_CH_STATUS_FREE_SHIFT 0 +#define SCMI_CH_STATUS_FREE_WIDTH 1 +#define SCMI_CH_STATUS_FREE_MASK ((1 << SCMI_CH_STATUS_FREE_WIDTH) - 1) + +/* Helper macros to check and write the channel status */ +#define SCMI_IS_CHANNEL_FREE(status) \ + (!!(((status) >> SCMI_CH_STATUS_FREE_SHIFT) & SCMI_CH_STATUS_FREE_MASK)) + +#define SCMI_MARK_CHANNEL_BUSY(status) do { \ + assert(SCMI_IS_CHANNEL_FREE(status)); \ + (status) &= ~(SCMI_CH_STATUS_FREE_MASK << \ + SCMI_CH_STATUS_FREE_SHIFT); \ + } while (0) + +/* Helper macros to copy arguments to the mailbox payload */ +#define SCMI_PAYLOAD_ARG1(payld_arr, arg1) \ + mmio_write_32((uintptr_t)&payld_arr[0], arg1) + +#define SCMI_PAYLOAD_ARG2(payld_arr, arg1, arg2) do { \ + SCMI_PAYLOAD_ARG1(payld_arr, arg1); \ + mmio_write_32((uintptr_t)&payld_arr[1], arg2); \ + } while (0) + +#define SCMI_PAYLOAD_ARG3(payld_arr, arg1, arg2, arg3) do { \ + SCMI_PAYLOAD_ARG2(payld_arr, arg1, arg2); \ + mmio_write_32((uintptr_t)&payld_arr[2], arg3); \ + } while (0) + +/* Helper macros to read return values from the mailbox payload */ +#define SCMI_PAYLOAD_RET_VAL1(payld_arr, val1) \ + (val1) = mmio_read_32((uintptr_t)&payld_arr[0]) + +#define SCMI_PAYLOAD_RET_VAL2(payld_arr, val1, val2) do { \ + SCMI_PAYLOAD_RET_VAL1(payld_arr, val1); \ + (val2) = mmio_read_32((uintptr_t)&payld_arr[1]); \ + } while (0) + +#define SCMI_PAYLOAD_RET_VAL3(payld_arr, val1, val2, val3) do { \ + SCMI_PAYLOAD_RET_VAL2(payld_arr, val1, val2); \ + (val3) = mmio_read_32((uintptr_t)&payld_arr[2]); \ + } while (0) + +#define SCMI_PAYLOAD_RET_VAL4(payld_arr, val1, val2, val3, val4) do { \ + SCMI_PAYLOAD_RET_VAL3(payld_arr, val1, val2, val3); \ + (val4) = mmio_read_32((uintptr_t)&payld_arr[3]); \ + } while (0) + +/* + * Private data structure for representing the mailbox memory layout. Refer + * the SCMI specification for more details. + */ +typedef struct mailbox_mem { + uint32_t res_a; /* Reserved */ + volatile uint32_t status; + uint64_t res_b; /* Reserved */ + uint32_t flags; + volatile uint32_t len; + volatile uint32_t msg_header; + uint32_t payload[]; +} mailbox_mem_t; + + +/* Private APIs for use within SCMI driver */ +void scmi_get_channel(scmi_channel_t *ch); +void scmi_send_sync_command(scmi_channel_t *ch); +void scmi_put_channel(scmi_channel_t *ch); + +static inline void validate_scmi_channel(scmi_channel_t *ch) +{ + assert(ch && ch->is_initialized); + assert(ch->info && ch->info->scmi_mbx_mem); +} + +/* + * SCMI vendor specific protocol + */ +#define SCMI_SYS_VENDOR_EXT_PROTO_ID 0x80 + +#endif /* SCMI_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c new file mode 100644 index 0000000..a342aa8 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" + +/* + * API to set the SCMI power domain power state. + */ +int scmi_pwr_state_set(void *p, uint32_t domain_id, + uint32_t scmi_pwr_state) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + + /* + * Only asynchronous mode of `set power state` command is allowed on + * application processors. + */ + uint32_t pwr_state_set_msg_flag = SCMI_PWR_STATE_SET_FLAG_ASYNC; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_PWR_DMN_PROTO_ID, + SCMI_PWR_STATE_SET_MSG, token); + mbx_mem->len = SCMI_PWR_STATE_SET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG3(mbx_mem->payload, pwr_state_set_msg_flag, + domain_id, scmi_pwr_state); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + assert(mbx_mem->len == SCMI_PWR_STATE_SET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to get the SCMI power domain power state. + */ +int scmi_pwr_state_get(void *p, uint32_t domain_id, + uint32_t *scmi_pwr_state) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_PWR_DMN_PROTO_ID, + SCMI_PWR_STATE_GET_MSG, token); + mbx_mem->len = SCMI_PWR_STATE_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG1(mbx_mem->payload, domain_id); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL2(mbx_mem->payload, ret, *scmi_pwr_state); + assert(mbx_mem->len == SCMI_PWR_STATE_GET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c new file mode 100644 index 0000000..c8e62d1 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" + +/* + * API to set the SCMI system power state + */ +int scmi_sys_pwr_state_set(void *p, uint32_t flags, uint32_t system_state) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_SYS_PWR_PROTO_ID, + SCMI_SYS_PWR_STATE_SET_MSG, token); + mbx_mem->len = SCMI_SYS_PWR_STATE_SET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG2(mbx_mem->payload, flags, system_state); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + assert(mbx_mem->len == SCMI_SYS_PWR_STATE_SET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to get the SCMI system power state + */ +int scmi_sys_pwr_state_get(void *p, uint32_t *system_state) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_SYS_PWR_PROTO_ID, + SCMI_SYS_PWR_STATE_GET_MSG, token); + mbx_mem->len = SCMI_SYS_PWR_STATE_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL2(mbx_mem->payload, ret, *system_state); + assert(mbx_mem->len == SCMI_SYS_PWR_STATE_GET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c b/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c new file mode 100644 index 0000000..f185424 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" +#include "scmi_sq.h" + +#include + +/* SCMI messge ID to get the available DRAM region */ +#define SCMI_VENDOR_EXT_MEMINFO_GET_MSG 0x3 + +#define SCMI_VENDOR_EXT_MEMINFO_GET_MSG_LEN 4 + +/* + * API to get the available DRAM region + */ +int scmi_get_draminfo(void *p, struct draminfo *info) +{ + mailbox_mem_t *mbx_mem; + int token = 0, ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + struct dram_info_resp response; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_SYS_VENDOR_EXT_PROTO_ID, + SCMI_VENDOR_EXT_MEMINFO_GET_MSG, token); + mbx_mem->len = SCMI_VENDOR_EXT_MEMINFO_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* + * Ensure that any read to the SCPI payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + + memcpy(&response, (void *)mbx_mem->payload, sizeof(response)); + + scmi_put_channel(ch); + + *info = response.info; + + return ret; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h b/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h new file mode 100644 index 0000000..aee1a3a --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCMI_SQ_H +#define SCMI_SQ_H + +#include +#include + +#include + +/* Structure to represent available DRAM region */ +struct dram_info_resp { + int status; + int reserved; + struct draminfo info; +}; + +/* API to get the available DRAM region */ +int scmi_get_draminfo(void *p, struct draminfo *info); + +#endif /* SCMI_SQ_H */ diff --git a/arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c b/arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c new file mode 100644 index 0000000..74121b4 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c @@ -0,0 +1,195 @@ +/* + * 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 + +/* ID of the MHU slot used for the BOM protocol */ +#define BOM_MHU_SLOT_ID 0 + +/* Boot commands sent from AP -> SCP */ +#define BOOT_CMD_INFO 0x00 +#define BOOT_CMD_DATA 0x01 + +/* BOM command header */ +typedef struct { + uint32_t id : 8; + uint32_t reserved : 24; +} bom_cmd_t; + +typedef struct { + uint32_t image_size; + uint32_t checksum; +} cmd_info_payload_t; + +/* + * Unlike the SCPI protocol, the boot protocol uses the same memory region + * for both AP -> SCP and SCP -> AP transfers; define the address of this... + */ +#define BOM_SHARED_MEM PLAT_CSS_SCP_COM_SHARED_MEM_BASE +#define BOM_CMD_HEADER ((bom_cmd_t *) BOM_SHARED_MEM) +#define BOM_CMD_PAYLOAD ((void *) (BOM_SHARED_MEM + sizeof(bom_cmd_t))) + +typedef struct { + /* Offset from the base address of the Trusted RAM */ + uint32_t offset; + uint32_t block_size; +} cmd_data_payload_t; + +/* + * All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31 + * usually resides except when ARM_BL31_IN_DRAM is + * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into shared RAM and + * the fw_config. + */ +CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2); +CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2); + +CASSERT(SCP_BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2_overflow); +CASSERT(SCP_BL2U_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow); + +static void scp_boot_message_start(void) +{ + mhu_secure_message_start(BOM_MHU_SLOT_ID); +} + +static void scp_boot_message_send(size_t payload_size) +{ + /* Ensure that any write to the BOM payload area is seen by SCP before + * we write to the MHU register. If these 2 writes were reordered by + * the CPU then SCP would read stale payload data */ + dmbst(); + + /* Send command to SCP */ + mhu_secure_message_send(BOM_MHU_SLOT_ID); +} + +static uint32_t scp_boot_message_wait(size_t size) +{ + uint32_t mhu_status; + + mhu_status = mhu_secure_message_wait(); + + /* Expect an SCP Boot Protocol message, reject any other protocol */ + if (mhu_status != (1 << BOM_MHU_SLOT_ID)) { + ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", + mhu_status); + panic(); + } + + /* Ensure that any read to the BOM payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data */ + dmbld(); + + return *(uint32_t *) BOM_SHARED_MEM; +} + +static void scp_boot_message_end(void) +{ + mhu_secure_message_end(BOM_MHU_SLOT_ID); +} + +int css_scp_boot_image_xfer(void *image, unsigned int image_size) +{ + uint32_t response; + uint32_t checksum; + cmd_info_payload_t *cmd_info_payload; + cmd_data_payload_t *cmd_data_payload; + + assert((uintptr_t) image == SCP_BL2_BASE); + + if ((image_size == 0) || (image_size % 4 != 0)) { + ERROR("Invalid size for the SCP_BL2 image. Must be a multiple of " + "4 bytes and not zero (current size = 0x%x)\n", + image_size); + return -1; + } + + /* Extract the checksum from the image */ + checksum = *(uint32_t *) image; + image = (char *) image + sizeof(checksum); + image_size -= sizeof(checksum); + + mhu_secure_init(); + + VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n"); + + /* + * Send information about the SCP firmware image about to be transferred + * to SCP + */ + scp_boot_message_start(); + + BOM_CMD_HEADER->id = BOOT_CMD_INFO; + cmd_info_payload = BOM_CMD_PAYLOAD; + cmd_info_payload->image_size = image_size; + cmd_info_payload->checksum = checksum; + + scp_boot_message_send(sizeof(*cmd_info_payload)); +#if CSS_DETECT_PRE_1_7_0_SCP + { + const uint32_t deprecated_scp_nack_cmd = 0x404; + uint32_t mhu_status; + + VERBOSE("Detecting SCP version incompatibility\n"); + + mhu_status = mhu_secure_message_wait(); + if (mhu_status == deprecated_scp_nack_cmd) { + ERROR("Detected an incompatible version of the SCP firmware.\n"); + ERROR("Only versions from v1.7.0 onwards are supported.\n"); + ERROR("Please update the SCP firmware.\n"); + return -1; + } + + VERBOSE("SCP version looks OK\n"); + } +#endif /* CSS_DETECT_PRE_1_7_0_SCP */ + response = scp_boot_message_wait(sizeof(response)); + scp_boot_message_end(); + + if (response != 0) { + ERROR("SCP BOOT_CMD_INFO returned error %u\n", response); + return -1; + } + + VERBOSE("Transferring SCP_BL2 image to SCP\n"); + + /* Transfer SCP_BL2 image to SCP */ + scp_boot_message_start(); + + BOM_CMD_HEADER->id = BOOT_CMD_DATA; + cmd_data_payload = BOM_CMD_PAYLOAD; + cmd_data_payload->offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE; + cmd_data_payload->block_size = image_size; + + scp_boot_message_send(sizeof(*cmd_data_payload)); + response = scp_boot_message_wait(sizeof(response)); + scp_boot_message_end(); + + if (response != 0) { + ERROR("SCP BOOT_CMD_DATA returned error %u\n", response); + return -1; + } + + return 0; +} + +int css_scp_boot_ready(void) +{ + VERBOSE("Waiting for SCP to signal it is ready to go on\n"); + + /* Wait for SCP to signal it's ready */ + return scpi_wait_ready(); +} diff --git a/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c b/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c new file mode 100644 index 0000000..5de2604 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c @@ -0,0 +1,468 @@ +/* + * 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 + +/* + * This file implements the SCP helper functions using SCMI protocol. + */ + +/* + * SCMI power state parameter bit field encoding for ARM CSS platforms. + * + * 31 20 19 16 15 12 11 8 7 4 3 0 + * +-------------------------------------------------------------+ + * | SBZ | Max level | Level 3 | Level 2 | Level 1 | Level 0 | + * | | | state | state | state | state | + * +-------------------------------------------------------------+ + * + * `Max level` encodes the highest level that has a valid power state + * encoded in the power state. + */ +#define SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT 16 +#define SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH 4 +#define SCMI_PWR_STATE_MAX_PWR_LVL_MASK \ + ((1 << SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH) - 1) +#define SCMI_SET_PWR_STATE_MAX_PWR_LVL(_power_state, _max_level) \ + (_power_state) |= ((_max_level) & SCMI_PWR_STATE_MAX_PWR_LVL_MASK)\ + << SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT +#define SCMI_GET_PWR_STATE_MAX_PWR_LVL(_power_state) \ + (((_power_state) >> SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT) \ + & SCMI_PWR_STATE_MAX_PWR_LVL_MASK) + +#define SCMI_PWR_STATE_LVL_WIDTH 4 +#define SCMI_PWR_STATE_LVL_MASK \ + ((1 << SCMI_PWR_STATE_LVL_WIDTH) - 1) +#define SCMI_SET_PWR_STATE_LVL(_power_state, _level, _level_state) \ + (_power_state) |= ((_level_state) & SCMI_PWR_STATE_LVL_MASK) \ + << (SCMI_PWR_STATE_LVL_WIDTH * (_level)) +#define SCMI_GET_PWR_STATE_LVL(_power_state, _level) \ + (((_power_state) >> (SCMI_PWR_STATE_LVL_WIDTH * (_level))) & \ + SCMI_PWR_STATE_LVL_MASK) + +/* + * The SCMI power state enumeration for a power domain level + */ +typedef enum { + scmi_power_state_off = 0, + scmi_power_state_on = 1, + scmi_power_state_sleep = 2, +} scmi_power_state_t; + +/* + * The global handles for invoking the SCMI driver APIs after the driver + * has been initialized. + */ +static void *scmi_handles[PLAT_ARM_SCMI_CHANNEL_COUNT]; + +/* The global SCMI channels array */ +static scmi_channel_t scmi_channels[PLAT_ARM_SCMI_CHANNEL_COUNT]; + +/* + * Channel ID for the default SCMI channel. + * The default channel is used to issue SYSTEM level SCMI requests and is + * initialized to the channel which has the boot cpu as its resource. + */ +static uint32_t default_scmi_channel_id; + +/* + * TODO: Allow use of channel specific lock instead of using a single lock for + * all the channels. + */ +ARM_SCMI_INSTANTIATE_LOCK; + +/* + * Function to obtain the SCMI Domain ID and SCMI Channel number from the linear + * core position. The SCMI Channel number is encoded in the upper 16 bits and + * the Domain ID is encoded in the lower 16 bits in each entry of the mapping + * array exported by the platform. + */ +static void css_scp_core_pos_to_scmi_channel(unsigned int core_pos, + unsigned int *scmi_domain_id, unsigned int *scmi_channel_id) +{ + unsigned int composite_id; + + composite_id = plat_css_core_pos_to_scmi_dmn_id_map[core_pos]; + + *scmi_channel_id = GET_SCMI_CHANNEL_ID(composite_id); + *scmi_domain_id = GET_SCMI_DOMAIN_ID(composite_id); +} + +/* + * Helper function to suspend a CPU power domain and its parent power domains + * if applicable. + */ +void css_scp_suspend(const struct psci_power_state *target_state) +{ + int ret; + + /* At least power domain level 0 should be specified to be suspended */ + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* Check if power down at system power domain level is requested */ + if (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF) { + /* Issue SCMI command for SYSTEM_SUSPEND on all SCMI channels */ + ret = scmi_sys_pwr_state_set( + scmi_handles[default_scmi_channel_id], + SCMI_SYS_PWR_FORCEFUL_REQ, SCMI_SYS_PWR_SUSPEND); + if (ret != SCMI_E_SUCCESS) { + ERROR("SCMI system power domain suspend return 0x%x unexpected\n", + ret); + panic(); + } + return; + } +#if !HW_ASSISTED_COHERENCY + unsigned int lvl, channel_id, domain_id; + uint32_t scmi_pwr_state = 0; + /* + * If we reach here, then assert that power down at system power domain + * level is running. + */ + assert(css_system_pwr_state(target_state) == ARM_LOCAL_STATE_RUN); + + /* For level 0, specify `scmi_power_state_sleep` as the power state */ + SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, ARM_PWR_LVL0, + scmi_power_state_sleep); + + for (lvl = ARM_PWR_LVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + if (target_state->pwr_domain_state[lvl] == ARM_LOCAL_STATE_RUN) + break; + + assert(target_state->pwr_domain_state[lvl] == + ARM_LOCAL_STATE_OFF); + /* + * Specify `scmi_power_state_off` as power state for higher + * levels. + */ + SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl, + scmi_power_state_off); + } + + SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1); + + css_scp_core_pos_to_scmi_channel(plat_my_core_pos(), + &domain_id, &channel_id); + ret = scmi_pwr_state_set(scmi_handles[channel_id], + domain_id, scmi_pwr_state); + + if (ret != SCMI_E_SUCCESS) { + ERROR("SCMI set power state command return 0x%x unexpected\n", + ret); + panic(); + } +#endif +} + +/* + * Helper function to turn off a CPU power domain and its parent power domains + * if applicable. + */ +void css_scp_off(const struct psci_power_state *target_state) +{ + unsigned int lvl = 0, channel_id, domain_id; + int ret; + uint32_t scmi_pwr_state = 0; + + /* At-least the CPU level should be specified to be OFF */ + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* PSCI CPU OFF cannot be used to turn OFF system power domain */ + assert(css_system_pwr_state(target_state) == ARM_LOCAL_STATE_RUN); + + for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + if (target_state->pwr_domain_state[lvl] == ARM_LOCAL_STATE_RUN) + break; + + assert(target_state->pwr_domain_state[lvl] == + ARM_LOCAL_STATE_OFF); + SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl, + scmi_power_state_off); + } + + SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1); + + css_scp_core_pos_to_scmi_channel(plat_my_core_pos(), + &domain_id, &channel_id); + ret = scmi_pwr_state_set(scmi_handles[channel_id], + domain_id, scmi_pwr_state); + if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) { + ERROR("SCMI set power state command return 0x%x unexpected\n", + ret); + panic(); + } +} + +/* + * Helper function to turn ON a CPU power domain and its parent power domains + * if applicable. + */ +void css_scp_on(u_register_t mpidr) +{ + unsigned int lvl = 0, channel_id, core_pos, domain_id; + int ret; + uint32_t scmi_pwr_state = 0; + + for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) + SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl, + scmi_power_state_on); + + SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1); + + core_pos = (unsigned int)plat_core_pos_by_mpidr(mpidr); + assert(core_pos < PLATFORM_CORE_COUNT); + + css_scp_core_pos_to_scmi_channel(core_pos, &domain_id, + &channel_id); + ret = scmi_pwr_state_set(scmi_handles[channel_id], + domain_id, scmi_pwr_state); + if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) { + ERROR("SCMI set power state command return 0x%x unexpected\n", + ret); + panic(); + } +} + +/* + * Helper function to get the power state of a power domain node as reported + * by the SCP. + */ +int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level) +{ + int ret; + uint32_t scmi_pwr_state = 0, lvl_state; + unsigned int channel_id, cpu_idx, domain_id; + + /* We don't support get power state at the system power domain level */ + if ((power_level > PLAT_MAX_PWR_LVL) || + (power_level == CSS_SYSTEM_PWR_DMN_LVL)) { + WARN("Invalid power level %u specified for SCMI get power state\n", + power_level); + return PSCI_E_INVALID_PARAMS; + } + + cpu_idx = (unsigned int)plat_core_pos_by_mpidr(mpidr); + assert(cpu_idx < PLATFORM_CORE_COUNT); + + css_scp_core_pos_to_scmi_channel(cpu_idx, &domain_id, &channel_id); + ret = scmi_pwr_state_get(scmi_handles[channel_id], + domain_id, &scmi_pwr_state); + + if (ret != SCMI_E_SUCCESS) { + WARN("SCMI get power state command return 0x%x unexpected\n", + ret); + return PSCI_E_INVALID_PARAMS; + } + + /* + * Find the maximum power level described in the get power state + * command. If it is less than the requested power level, then assume + * the requested power level is ON. + */ + if (SCMI_GET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state) < power_level) + return HW_ON; + + lvl_state = SCMI_GET_PWR_STATE_LVL(scmi_pwr_state, power_level); + if (lvl_state == scmi_power_state_on) + return HW_ON; + + assert((lvl_state == scmi_power_state_off) || + (lvl_state == scmi_power_state_sleep)); + return HW_OFF; +} + +void __dead2 css_scp_system_off(int state) +{ + int ret; + + /* + * Disable GIC CPU interface to prevent pending interrupt from waking + * up the AP from WFI. + */ + plat_arm_gic_cpuif_disable(); + + /* + * Issue SCMI command. First issue a graceful + * request and if that fails force the request. + */ + ret = scmi_sys_pwr_state_set(scmi_handles[default_scmi_channel_id], + SCMI_SYS_PWR_FORCEFUL_REQ, + state); + + if (ret != SCMI_E_SUCCESS) { + ERROR("SCMI system power state set 0x%x returns unexpected 0x%x\n", + state, ret); + panic(); + } + wfi(); + ERROR("CSS set power state: operation not handled.\n"); + panic(); +} + +/* + * Helper function to shutdown the system via SCMI. + */ +void __dead2 css_scp_sys_shutdown(void) +{ + css_scp_system_off(SCMI_SYS_PWR_SHUTDOWN); +} + +/* + * Helper function to reset the system via SCMI. + */ +void __dead2 css_scp_sys_reboot(void) +{ + css_scp_system_off(SCMI_SYS_PWR_COLD_RESET); +} + +static int scmi_ap_core_init(scmi_channel_t *ch) +{ +#if PROGRAMMABLE_RESET_ADDRESS + uint32_t version; + int ret; + + ret = scmi_proto_version(ch, SCMI_AP_CORE_PROTO_ID, &version); + if (ret != SCMI_E_SUCCESS) { + WARN("SCMI AP core protocol version message failed\n"); + return -1; + } + + if (!is_scmi_version_compatible(SCMI_AP_CORE_PROTO_VER, version)) { + WARN("SCMI AP core protocol version 0x%x incompatible with driver version 0x%x\n", + version, SCMI_AP_CORE_PROTO_VER); + return -1; + } + INFO("SCMI AP core protocol version 0x%x detected\n", version); +#endif + return 0; +} + +void __init plat_arm_pwrc_setup(void) +{ + unsigned int composite_id, idx; + + for (idx = 0; idx < PLAT_ARM_SCMI_CHANNEL_COUNT; idx++) { + INFO("Initializing SCMI driver on channel %d\n", idx); + + scmi_channels[idx].info = plat_css_get_scmi_info(idx); + scmi_channels[idx].lock = ARM_SCMI_LOCK_GET_INSTANCE; + scmi_handles[idx] = scmi_init(&scmi_channels[idx]); + + if (scmi_handles[idx] == NULL) { + ERROR("SCMI Initialization failed on channel %d\n", idx); + panic(); + } + + if (scmi_ap_core_init(&scmi_channels[idx]) < 0) { + ERROR("SCMI AP core protocol initialization failed\n"); + panic(); + } + } + + composite_id = plat_css_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()]; + default_scmi_channel_id = GET_SCMI_CHANNEL_ID(composite_id); +} + +/****************************************************************************** + * This function overrides the default definition for ARM platforms. Initialize + * the SCMI driver, query capability via SCMI and modify the PSCI capability + * based on that. + *****************************************************************************/ +const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops) +{ + uint32_t msg_attr; + int ret; + void *scmi_handle = scmi_handles[default_scmi_channel_id]; + + assert(scmi_handle); + + /* Check that power domain POWER_STATE_SET message is supported */ + ret = scmi_proto_msg_attr(scmi_handle, SCMI_PWR_DMN_PROTO_ID, + SCMI_PWR_STATE_SET_MSG, &msg_attr); + if (ret != SCMI_E_SUCCESS) { + ERROR("Set power state command is not supported by SCMI\n"); + panic(); + } + + /* + * Don't support PSCI NODE_HW_STATE call if SCMI doesn't support + * POWER_STATE_GET message. + */ + ret = scmi_proto_msg_attr(scmi_handle, SCMI_PWR_DMN_PROTO_ID, + SCMI_PWR_STATE_GET_MSG, &msg_attr); + if (ret != SCMI_E_SUCCESS) + ops->get_node_hw_state = NULL; + + /* Check if the SCMI SYSTEM_POWER_STATE_SET message is supported */ + ret = scmi_proto_msg_attr(scmi_handle, SCMI_SYS_PWR_PROTO_ID, + SCMI_SYS_PWR_STATE_SET_MSG, &msg_attr); + if (ret != SCMI_E_SUCCESS) { + /* System power management operations are not supported */ + ops->system_off = NULL; + ops->system_reset = NULL; + ops->get_sys_suspend_power_state = NULL; + } else { + if (!(msg_attr & SCMI_SYS_PWR_SUSPEND_SUPPORTED)) { + /* + * System power management protocol is available, but + * it does not support SYSTEM SUSPEND. + */ + ops->get_sys_suspend_power_state = NULL; + } + if (!(msg_attr & SCMI_SYS_PWR_WARM_RESET_SUPPORTED)) { + /* + * WARM reset is not available. + */ + ops->system_reset2 = NULL; + } + } + + return ops; +} + +int css_system_reset2(int is_vendor, int reset_type, u_register_t cookie) +{ + if (is_vendor || (reset_type != PSCI_RESET2_SYSTEM_WARM_RESET)) + return PSCI_E_INVALID_PARAMS; + + css_scp_system_off(SCMI_SYS_PWR_WARM_RESET); + /* + * css_scp_system_off cannot return (it is a __dead function), + * but css_system_reset2 has to return some value, even in + * this case. + */ + return 0; +} + +#if PROGRAMMABLE_RESET_ADDRESS +void plat_arm_program_trusted_mailbox(uintptr_t address) +{ + int ret, i; + + for (i = 0; i < PLAT_ARM_SCMI_CHANNEL_COUNT; i++) { + assert(scmi_handles[i]); + + ret = scmi_ap_core_set_reset_addr(scmi_handles[i], address, + SCMI_AP_CORE_LOCK_ATTR); + if (ret != SCMI_E_SUCCESS) { + ERROR("CSS: Failed to program reset address: %d\n", ret); + panic(); + } + } +} +#endif diff --git a/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c b/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c new file mode 100644 index 0000000..b4019ce --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +/* + * This file implements the SCP power management functions using SCPI protocol. + */ + +/* + * Helper function to inform power down state to SCP. + */ +void css_scp_suspend(const struct psci_power_state *target_state) +{ + uint32_t cluster_state = scpi_power_on; + uint32_t system_state = scpi_power_on; + + /* Check if power down at system power domain level is requested */ + if (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF) + system_state = scpi_power_retention; + + /* Cluster is to be turned off, so disable coherency */ + if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) + cluster_state = scpi_power_off; + + /* + * Ask the SCP to power down the appropriate components depending upon + * their state. + */ + scpi_set_css_power_state(read_mpidr_el1(), + scpi_power_off, + cluster_state, + system_state); +} + +/* + * Helper function to turn off a CPU power domain and its parent power domains + * if applicable. Since SCPI doesn't differentiate between OFF and suspend, we + * call the suspend helper here. + */ +void css_scp_off(const struct psci_power_state *target_state) +{ + css_scp_suspend(target_state); +} + +/* + * Helper function to turn ON a CPU power domain and its parent power domains + * if applicable. + */ +void css_scp_on(u_register_t mpidr) +{ + /* + * SCP takes care of powering up parent power domains so we + * only need to care about level 0 + */ + scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); +} + +/* + * Helper function to get the power state of a power domain node as reported + * by the SCP. + */ +int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level) +{ + int rc, element; + unsigned int cpu_state, cluster_state; + + /* + * The format of 'power_level' is implementation-defined, but 0 must + * mean a CPU. We also allow 1 to denote the cluster + */ + if (power_level != ARM_PWR_LVL0 && power_level != ARM_PWR_LVL1) + return PSCI_E_INVALID_PARAMS; + + /* Query SCP */ + rc = scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state); + if (rc != 0) + return PSCI_E_INVALID_PARAMS; + + /* Map power states of CPU and cluster to expected PSCI return codes */ + if (power_level == ARM_PWR_LVL0) { + /* + * The CPU state returned by SCP is an 8-bit bit mask + * corresponding to each CPU in the cluster + */ +#if ARM_PLAT_MT + /* + * The current SCPI driver only caters for single-threaded + * platforms. Hence we ignore the thread ID (which is always 0) + * for such platforms. + */ + element = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; +#else + element = mpidr & MPIDR_AFFLVL_MASK; +#endif /* ARM_PLAT_MT */ + return CSS_CPU_PWR_STATE(cpu_state, element) == + CSS_CPU_PWR_STATE_ON ? HW_ON : HW_OFF; + } else { + assert(cluster_state == CSS_CLUSTER_PWR_STATE_ON || + cluster_state == CSS_CLUSTER_PWR_STATE_OFF); + return cluster_state == CSS_CLUSTER_PWR_STATE_ON ? HW_ON : + HW_OFF; + } +} + +/* + * Helper function to shutdown the system via SCPI. + */ +void __dead2 css_scp_sys_shutdown(void) +{ + uint32_t response; + + /* + * Disable GIC CPU interface to prevent pending interrupt + * from waking up the AP from WFI. + */ + plat_arm_gic_cpuif_disable(); + + /* Send the power down request to the SCP */ + response = scpi_sys_power_state(scpi_system_shutdown); + + if (response != SCP_OK) { + ERROR("CSS System Off: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("CSS System Off: operation not handled.\n"); + panic(); +} + +/* + * Helper function to reset the system via SCPI. + */ +void __dead2 css_scp_sys_reboot(void) +{ + uint32_t response; + + /* + * Disable GIC CPU interface to prevent pending interrupt + * from waking up the AP from WFI. + */ + plat_arm_gic_cpuif_disable(); + + /* Send the system reset request to the SCP */ + response = scpi_sys_power_state(scpi_system_reboot); + + if (response != SCP_OK) { + ERROR("CSS System Reset: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("CSS System Reset: operation not handled.\n"); + panic(); +} diff --git a/arm-trusted-firmware/drivers/arm/css/scp/css_sds.c b/arm-trusted-firmware/drivers/arm/css/scp/css_sds.c new file mode 100644 index 0000000..e42ee10 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scp/css_sds.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +int css_scp_boot_image_xfer(void *image, unsigned int image_size) +{ + int ret; + unsigned int image_offset, image_flags; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SCP SDS initialization failed\n"); + panic(); + } + + VERBOSE("Writing SCP image metadata\n"); + image_offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE; + ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_ADDR_OFFSET, + &image_offset, SDS_SCP_IMG_ADDR_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) + goto sds_fail; + + ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_SIZE_OFFSET, + &image_size, SDS_SCP_IMG_SIZE_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) + goto sds_fail; + + VERBOSE("Marking SCP image metadata as valid\n"); + image_flags = SDS_SCP_IMG_VALID_FLAG_BIT; + ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_FLAG_OFFSET, + &image_flags, SDS_SCP_IMG_FLAG_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) + goto sds_fail; + + return 0; +sds_fail: + ERROR("SCP SDS write to SCP IMG struct failed\n"); + panic(); +} + +/* + * API to wait for SCP to signal till it's ready after booting the transferred + * image. + */ +int css_scp_boot_ready(void) +{ + uint32_t scp_feature_availability_flags; + int ret, retry = CSS_SCP_READY_10US_RETRIES; + + + VERBOSE("Waiting for SCP RAM to complete its initialization process\n"); + + /* Wait for the SCP RAM Firmware to complete its initialization process */ + while (retry > 0) { + ret = sds_struct_read(SDS_FEATURE_AVAIL_STRUCT_ID, 0, + &scp_feature_availability_flags, + SDS_FEATURE_AVAIL_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret == SDS_ERR_STRUCT_NOT_FINALIZED) + continue; + + if (ret != SDS_OK) { + ERROR(" sds_struct_read failed\n"); + panic(); + } + + if (scp_feature_availability_flags & + SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT) + return 0; + + udelay(10); + retry--; + } + + ERROR("Timeout of %d ms expired waiting for SCP RAM Ready flag\n", + CSS_SCP_READY_10US_RETRIES/100); + + plat_panic_handler(); +} diff --git a/arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c b/arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c new file mode 100644 index 0000000..416356b --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c @@ -0,0 +1,272 @@ +/* + * 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 + +#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_CSS_SCP_COM_SHARED_MEM_BASE +#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_CSS_SCP_COM_SHARED_MEM_BASE \ + + 0x100) + +/* Header and payload addresses for commands from AP to SCP */ +#define SCPI_CMD_HEADER_AP_TO_SCP \ + ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP) +#define SCPI_CMD_PAYLOAD_AP_TO_SCP \ + ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t))) + +/* Header and payload addresses for responses from SCP to AP */ +#define SCPI_RES_HEADER_SCP_TO_AP \ + ((scpi_cmd_t *) SCPI_SHARED_MEM_SCP_TO_AP) +#define SCPI_RES_PAYLOAD_SCP_TO_AP \ + ((void *) (SCPI_SHARED_MEM_SCP_TO_AP + sizeof(scpi_cmd_t))) + +/* ID of the MHU slot used for the SCPI protocol */ +#define SCPI_MHU_SLOT_ID 0 + +static void scpi_secure_message_start(void) +{ + mhu_secure_message_start(SCPI_MHU_SLOT_ID); +} + +static void scpi_secure_message_send(size_t payload_size) +{ + /* + * Ensure that any write to the SCPI payload area is seen by SCP before + * we write to the MHU register. If these 2 writes were reordered by + * the CPU then SCP would read stale payload data + */ + dmbst(); + + mhu_secure_message_send(SCPI_MHU_SLOT_ID); +} + +static int scpi_secure_message_receive(scpi_cmd_t *cmd) +{ + uint32_t mhu_status; + + assert(cmd != NULL); + + mhu_status = mhu_secure_message_wait(); + + /* Expect an SCPI message, reject any other protocol */ + if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) { + ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", + mhu_status); + return -1; + } + + /* + * Ensure that any read to the SCPI payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); + + memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd)); + + return 0; +} + +static void scpi_secure_message_end(void) +{ + mhu_secure_message_end(SCPI_MHU_SLOT_ID); +} + +int scpi_wait_ready(void) +{ + scpi_cmd_t scpi_cmd; + int rc; + + VERBOSE("Waiting for SCP_READY command...\n"); + + /* Get a message from the SCP */ + scpi_secure_message_start(); + rc = scpi_secure_message_receive(&scpi_cmd); + scpi_secure_message_end(); + + /* If no message was received, don't send a response */ + if (rc != 0) + return rc; + + /* We are expecting 'SCP Ready', produce correct error if it's not */ + scpi_status_t status = SCP_OK; + if (scpi_cmd.id != SCPI_CMD_SCP_READY) { + ERROR("Unexpected SCP command: expected command #%u, got command #%u\n", + SCPI_CMD_SCP_READY, scpi_cmd.id); + status = SCP_E_SUPPORT; + } else if (scpi_cmd.size != 0) { + ERROR("SCP_READY command has incorrect size: expected 0, got %u\n", + scpi_cmd.size); + status = SCP_E_SIZE; + } + + VERBOSE("Sending response for SCP_READY command\n"); + + /* + * Send our response back to SCP. + * We are using the same SCPI header, just update the status field. + */ + scpi_cmd.status = status; + scpi_secure_message_start(); + memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd)); + scpi_secure_message_send(0); + scpi_secure_message_end(); + + return status == SCP_OK ? 0 : -1; +} + +void scpi_set_css_power_state(unsigned int mpidr, + scpi_power_state_t cpu_state, scpi_power_state_t cluster_state, + scpi_power_state_t css_state) +{ + scpi_cmd_t *cmd; + uint32_t state = 0; + uint32_t *payload_addr; + +#if ARM_PLAT_MT + /* + * The current SCPI driver only caters for single-threaded platforms. + * Hence we ignore the thread ID (which is always 0) for such platforms. + */ + state |= (mpidr >> MPIDR_AFF1_SHIFT) & 0x0f; /* CPU ID */ + state |= ((mpidr >> MPIDR_AFF2_SHIFT) & 0x0f) << 4; /* Cluster ID */ +#else + state |= mpidr & 0x0f; /* CPU ID */ + state |= (mpidr & 0xf00) >> 4; /* Cluster ID */ +#endif /* ARM_PLAT_MT */ + + state |= cpu_state << 8; + state |= cluster_state << 12; + state |= css_state << 16; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SET_CSS_POWER_STATE; + cmd->set = SCPI_SET_NORMAL; + cmd->sender = 0; + cmd->size = sizeof(state); + /* Populate the command payload */ + payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; + *payload_addr = state; + scpi_secure_message_send(sizeof(state)); + /* + * SCP does not reply to this command in order to avoid MHU interrupts + * from the sender, which could interfere with its power state request. + */ + + scpi_secure_message_end(); +} + +/* + * Query and obtain CSS power state from SCP. + * + * In response to the query, SCP returns power states of all CPUs in all + * clusters of the system. The returned response is then filtered based on the + * supplied MPIDR. Power states of requested cluster and CPUs within are updated + * via supplied non-NULL pointer arguments. + * + * Returns 0 on success, or -1 on errors. + */ +int scpi_get_css_power_state(unsigned int mpidr, unsigned int *cpu_state_p, + unsigned int *cluster_state_p) +{ + scpi_cmd_t *cmd; + scpi_cmd_t response; + int power_state, cpu, cluster, rc = -1; + + /* + * Extract CPU and cluster membership of the given MPIDR. SCPI caters + * for only up to 0xf clusters, and 8 CPUs per cluster + */ +#if ARM_PLAT_MT + /* + * The current SCPI driver only caters for single-threaded platforms. + * Hence we ignore the thread ID (which is always 0) for such platforms. + */ + cpu = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cluster = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK; +#else + cpu = mpidr & MPIDR_AFFLVL_MASK; + cluster = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; +#endif /* ARM_PLAT_MT */ + if (cpu >= 8 || cluster >= 0xf) + return -1; + + scpi_secure_message_start(); + + /* Populate request headers */ + zeromem(SCPI_CMD_HEADER_AP_TO_SCP, sizeof(*cmd)); + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_GET_CSS_POWER_STATE; + + /* + * Send message and wait for SCP's response + */ + scpi_secure_message_send(0); + if (scpi_secure_message_receive(&response) != 0) + goto exit; + + if (response.status != SCP_OK) + goto exit; + + /* Validate SCP response */ + if (!CHECK_RESPONSE(response, cluster)) + goto exit; + + /* Extract power states for required cluster */ + power_state = *(((uint16_t *) SCPI_RES_PAYLOAD_SCP_TO_AP) + cluster); + if (CLUSTER_ID(power_state) != cluster) + goto exit; + + /* Update power state via pointers */ + if (cluster_state_p) + *cluster_state_p = CLUSTER_POWER_STATE(power_state); + if (cpu_state_p) + *cpu_state_p = CPU_POWER_STATE(power_state); + rc = 0; + +exit: + scpi_secure_message_end(); + return rc; +} + +uint32_t scpi_sys_power_state(scpi_system_state_t system_state) +{ + scpi_cmd_t *cmd; + uint8_t *payload_addr; + scpi_cmd_t response; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SYS_POWER_STATE; + cmd->set = 0; + cmd->sender = 0; + cmd->size = sizeof(*payload_addr); + /* Populate the command payload */ + payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; + *payload_addr = system_state & 0xff; + scpi_secure_message_send(sizeof(*payload_addr)); + + /* If no response is received, fill in an error status */ + if (scpi_secure_message_receive(&response) != 0) + response.status = SCP_E_TIMEOUT; + + scpi_secure_message_end(); + + return response.status; +} diff --git a/arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S b/arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S new file mode 100644 index 0000000..13ff0e1 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "../sds_private.h" + + .globl sds_get_primary_cpu_id + + /* + * int sds_get_primary_cpu_id(void); + * Return the primary CPU ID from SDS Structure + * Returns CPUID on success or -1 on failure + */ +func sds_get_primary_cpu_id + ldr r0, =PLAT_ARM_SDS_MEM_BASE + ldr r2, =SDS_REGION_SIGNATURE + ldr r1, [r0] + ubfx r3, r1, #0, #16 + + /* Check if the SDS region signature found */ + cmp r2, r3 + bne 2f + + /* Get the structure count from region descriptor in r1 */ + ubfx r1, r1, #SDS_REGION_STRUCT_COUNT_SHIFT, #SDS_REGION_STRUCT_COUNT_WIDTH + cmp r1, #0 + beq 2f + add r0, r0, #SDS_REGION_DESC_SIZE + + /* Initialize the loop iterator count in r3 */ + mov r3, #0 +loop_begin: + ldrh r2, [r0] + cmp r2, #SDS_AP_CPU_INFO_STRUCT_ID + bne continue_loop + + /* We have found the required structure */ + ldr r0, [r0,#(SDS_HEADER_SIZE + SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET)] + bx lr +continue_loop: + /* Increment the loop counter and exit loop if counter == structure count */ + add r3, r3, #0x1 + cmp r1, r3 + beq 2f + + /* Read the 2nd word in header */ + ldr r2, [r0,#4] + /* Get the structure size from header */ + ubfx r2, r2, #SDS_HEADER_STRUCT_SIZE_SHIFT, #SDS_HEADER_STRUCT_SIZE_WIDTH + /* Add the structure size and SDS HEADER SIZE to point to next header */ + add r2, r2, #SDS_HEADER_SIZE + add r0, r0, r2 + b loop_begin +2: + mov r0, #0xffffffff + bx lr +endfunc sds_get_primary_cpu_id diff --git a/arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S b/arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S new file mode 100644 index 0000000..3256c2b --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "../sds_private.h" + + .globl sds_get_primary_cpu_id + + /* + * int sds_get_primary_cpu_id(void); + * Return the primary CPI ID from SDS Structure + * Returns CPUID on success or -1 on failure + */ +func sds_get_primary_cpu_id + mov_imm x0, PLAT_ARM_SDS_MEM_BASE + mov w2, #SDS_REGION_SIGNATURE + ldr w1, [x0] + + /* Check if the SDS region signature found */ + cmp w2, w1, uxth + b.ne 2f + + /* Get the structure count from region descriptor in `w1 */ + ubfx w1, w1, #SDS_REGION_STRUCT_COUNT_SHIFT, #SDS_REGION_STRUCT_COUNT_WIDTH + cbz w1, 2f + add x0, x0, #SDS_REGION_DESC_SIZE + + /* Initialize the loop iterator count in w3 */ + mov w3, #0 +loop_begin: + ldrh w2, [x0] + cmp w2, #SDS_AP_CPU_INFO_STRUCT_ID + b.ne continue_loop + + /* We have found the required structure */ + ldr w0, [x0,#(SDS_HEADER_SIZE + SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET)] + ret +continue_loop: + /* Increment the loop counter and exit loop if counter == structure count */ + add w3, w3, #0x1 + cmp w1, w3 + b.eq 2f + + /* Read the 2nd word in header */ + ldr w2, [x0,#4] + /* Get the structure size from header */ + ubfx x2, x2, #SDS_HEADER_STRUCT_SIZE_SHIFT, #SDS_HEADER_STRUCT_SIZE_WIDTH + /* Add the structure size and SDS HEADER SIZE to point to next header */ + add x2, x2, #SDS_HEADER_SIZE + add x0, x0, x2 + b loop_begin +2: + mov w0, #0xffffffff + ret +endfunc sds_get_primary_cpu_id diff --git a/arm-trusted-firmware/drivers/arm/css/sds/sds.c b/arm-trusted-firmware/drivers/arm/css/sds/sds.c new file mode 100644 index 0000000..1fb196c --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/sds/sds.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "sds_private.h" + +/* + * Variables used to track and maintain the state of the memory region reserved + * for usage by the SDS framework. + */ + +/* Pointer to the base of the SDS memory region */ +static uintptr_t sds_mem_base; + +/* Size of the SDS memory region in bytes */ +static size_t sds_mem_size; + +/* + * Perform some non-exhaustive tests to determine whether any of the fields + * within a Structure Header contain obviously invalid data. + * Returns SDS_OK on success, SDS_ERR_FAIL on error. + */ +static int sds_struct_is_valid(uintptr_t header) +{ + size_t struct_size = GET_SDS_HEADER_STRUCT_SIZE(header); + + /* Zero is not a valid identifier */ + if (GET_SDS_HEADER_ID(header) == 0) + return SDS_ERR_FAIL; + + /* Check SDS Schema version */ + if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION) + return SDS_ERR_FAIL; + + /* The SDS Structure sizes have to be multiple of 8 */ + if ((struct_size == 0) || ((struct_size % 8) != 0)) + return SDS_ERR_FAIL; + + if (struct_size > sds_mem_size) + return SDS_ERR_FAIL; + + return SDS_OK; +} + +/* + * Validate the SDS structure headers. + * Returns SDS_OK on success, SDS_ERR_FAIL on error. + */ +static int validate_sds_struct_headers(void) +{ + unsigned int i, structure_count; + uintptr_t header; + + structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base); + + if (structure_count == 0) + return SDS_ERR_FAIL; + + header = sds_mem_base + SDS_REGION_DESC_SIZE; + + /* Iterate over structure headers and validate each one */ + for (i = 0; i < structure_count; i++) { + if (sds_struct_is_valid(header) != SDS_OK) { + WARN("SDS: Invalid structure header detected\n"); + return SDS_ERR_FAIL; + } + header += GET_SDS_HEADER_STRUCT_SIZE(header) + SDS_HEADER_SIZE; + } + return SDS_OK; +} + +/* + * Get the structure header pointer corresponding to the structure ID. + * Returns SDS_OK on success, SDS_ERR_STRUCT_NOT_FOUND on error. + */ +static int get_struct_header(uint32_t structure_id, struct_header_t **header) +{ + unsigned int i, structure_count; + uintptr_t current_header; + + assert(header); + + structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base); + if (structure_count == 0) + return SDS_ERR_STRUCT_NOT_FOUND; + + current_header = ((uintptr_t)sds_mem_base) + SDS_REGION_DESC_SIZE; + + /* Iterate over structure headers to find one with a matching ID */ + for (i = 0; i < structure_count; i++) { + if (GET_SDS_HEADER_ID(current_header) == structure_id) { + *header = (struct_header_t *)current_header; + return SDS_OK; + } + current_header += GET_SDS_HEADER_STRUCT_SIZE(current_header) + + SDS_HEADER_SIZE; + } + + *header = NULL; + return SDS_ERR_STRUCT_NOT_FOUND; +} + +/* + * Check if a structure header corresponding to the structure ID exists. + * Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND + * if not found. + */ +int sds_struct_exists(unsigned int structure_id) +{ + struct_header_t *header = NULL; + int ret; + + ret = get_struct_header(structure_id, &header); + if (ret == SDS_OK) { + assert(header); + } + + return ret; +} + +/* + * Read from field in the structure corresponding to `structure_id`. + * `fld_off` is the offset to the field in the structure and `mode` + * indicates whether cache maintenance need to performed prior to the read. + * The `data` is the pointer to store the read data of size specified by `size`. + * Returns SDS_OK on success or corresponding error codes on failure. + */ +int sds_struct_read(uint32_t structure_id, unsigned int fld_off, + void *data, size_t size, sds_access_mode_t mode) +{ + int status; + uintptr_t field_base; + struct_header_t *header = NULL; + + if (!data) + return SDS_ERR_INVALID_PARAMS; + + /* Check if a structure with this ID exists */ + status = get_struct_header(structure_id, &header); + if (status != SDS_OK) + return status; + + assert(header); + + if (mode == SDS_ACCESS_MODE_CACHED) + inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size); + + if (!IS_SDS_HEADER_VALID(header)) { + WARN("SDS: Reading from un-finalized structure 0x%x\n", + structure_id); + return SDS_ERR_STRUCT_NOT_FINALIZED; + } + + if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header)) + return SDS_ERR_FAIL; + + field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off; + if (check_uptr_overflow(field_base, size - 1)) + return SDS_ERR_FAIL; + + /* Copy the required field in the struct */ + memcpy(data, (void *)field_base, size); + + return SDS_OK; +} + +/* + * Write to the field in the structure corresponding to `structure_id`. + * `fld_off` is the offset to the field in the structure and `mode` + * indicates whether cache maintenance need to performed for the write. + * The `data` is the pointer to data of size specified by `size`. + * Returns SDS_OK on success or corresponding error codes on failure. + */ +int sds_struct_write(uint32_t structure_id, unsigned int fld_off, + void *data, size_t size, sds_access_mode_t mode) +{ + int status; + uintptr_t field_base; + struct_header_t *header = NULL; + + if (!data) + return SDS_ERR_INVALID_PARAMS; + + /* Check if a structure with this ID exists */ + status = get_struct_header(structure_id, &header); + if (status != SDS_OK) + return status; + + assert(header); + + if (mode == SDS_ACCESS_MODE_CACHED) + inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size); + + if (!IS_SDS_HEADER_VALID(header)) { + WARN("SDS: Writing to un-finalized structure 0x%x\n", + structure_id); + return SDS_ERR_STRUCT_NOT_FINALIZED; + } + + if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header)) + return SDS_ERR_FAIL; + + field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off; + if (check_uptr_overflow(field_base, size - 1)) + return SDS_ERR_FAIL; + + /* Copy the required field in the struct */ + memcpy((void *)field_base, data, size); + + if (mode == SDS_ACCESS_MODE_CACHED) + flush_dcache_range((uintptr_t)field_base, size); + + return SDS_OK; +} + +/* + * Initialize the SDS driver. Also verifies the SDS version and sanity of + * the SDS structure headers. + * Returns SDS_OK on success, SDS_ERR_FAIL on error. + */ +int sds_init(void) +{ + sds_mem_base = (uintptr_t)PLAT_ARM_SDS_MEM_BASE; + + if (!IS_SDS_REGION_VALID(sds_mem_base)) { + WARN("SDS: No valid SDS Memory Region found\n"); + return SDS_ERR_FAIL; + } + + if (GET_SDS_REGION_SCHEMA_VERSION(sds_mem_base) + != SDS_REGION_SCH_VERSION) { + WARN("SDS: Unsupported SDS schema version\n"); + return SDS_ERR_FAIL; + } + + sds_mem_size = GET_SDS_REGION_SIZE(sds_mem_base); + if (sds_mem_size > PLAT_ARM_SDS_MEM_SIZE_MAX) { + WARN("SDS: SDS Memory Region exceeds size limit\n"); + return SDS_ERR_FAIL; + } + + INFO("SDS: Detected SDS Memory Region (%zu bytes)\n", sds_mem_size); + + if (validate_sds_struct_headers() != SDS_OK) + return SDS_ERR_FAIL; + + return SDS_OK; +} diff --git a/arm-trusted-firmware/drivers/arm/css/sds/sds_private.h b/arm-trusted-firmware/drivers/arm/css/sds/sds_private.h new file mode 100644 index 0000000..d801a04 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/sds/sds_private.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDS_PRIVATE_H +#define SDS_PRIVATE_H + +/* SDS Header defines */ +#define SDS_HEADER_ID_SHIFT 0 +#define SDS_HEADER_ID_WIDTH 16 +#define SDS_HEADER_ID_MASK ((1 << SDS_HEADER_ID_WIDTH) - 1) + +#define SDS_HEADER_MINOR_VERSION_WIDTH 8 +#define SDS_HEADER_MINOR_VERSION_SHIFT 16 +#define SDS_HEADER_MAJOR_VERSION_WIDTH 8 + +#define MAKE_SDS_HEADER_VERSION(major, minor) \ + (((((major) & 0xff) << SDS_HEADER_MINOR_VERSION_WIDTH) | ((minor) & 0xff))) +#define SDS_HEADER_VERSION_MASK \ + ((1 << (SDS_HEADER_MINOR_VERSION_WIDTH + SDS_HEADER_MAJOR_VERSION_WIDTH)) - 1) + +#define SDS_HEADER_VERSION MAKE_SDS_HEADER_VERSION(1, 0) +#define SDS_HEADER_STRUCT_SIZE_WIDTH 23 +#define SDS_HEADER_STRUCT_SIZE_SHIFT 1 +#define SDS_HEADER_STRUCT_SIZE_MASK ((1 << SDS_HEADER_STRUCT_SIZE_WIDTH) - 1) +#define SDS_HEADER_VALID_MASK 0x1 +#define SDS_HEADER_VALID_SHIFT 0 +#define SDS_HEADER_SIZE 0x8 + +/* Arbitrary, 16 bit value that indicates a valid SDS Memory Region */ +#define SDS_REGION_SIGNATURE 0xAA7A +#define SDS_REGION_SIGNATURE_WIDTH 16 +#define SDS_REGION_SIGNATURE_SHIFT 0 +#define SDS_REGION_SIGNATURE_MASK ((1 << SDS_REGION_SIGNATURE_WIDTH) - 1) + +#define SDS_REGION_STRUCT_COUNT_SHIFT 16 +#define SDS_REGION_STRUCT_COUNT_WIDTH 8 +#define SDS_REGION_STRUCT_COUNT_MASK ((1 << SDS_REGION_STRUCT_COUNT_WIDTH) - 1) + +#define SDS_REGION_SCH_MINOR_SHIFT 24 +#define SDS_REGION_SCH_MINOR_WIDTH 4 +#define SDS_REGION_SCH_MINOR_MASK ((1 << SDS_REGION_SCH_MINOR_WIDTH) - 1) + +#define SDS_REGION_SCH_MAJOR_SHIFT 28 +#define SDS_REGION_SCH_MAJOR_WIDTH 4 +#define SDS_REGION_SCH_MAJOR_MASK ((1 << SDS_REGION_SCH_MAJOR_WIDTH) - 1) + +#define SDS_REGION_SCH_VERSION_MASK \ + ((1 << (SDS_REGION_SCH_MINOR_WIDTH + SDS_REGION_SCH_MAJOR_WIDTH)) - 1) + +#define MAKE_SDS_REGION_SCH_VERSION(maj, min) \ + ((((maj) & SDS_REGION_SCH_MAJOR_MASK) << SDS_REGION_SCH_MINOR_WIDTH) | \ + ((min) & SDS_REGION_SCH_MINOR_MASK)) + +#define SDS_REGION_SCH_VERSION MAKE_SDS_REGION_SCH_VERSION(1, 0) +#define SDS_REGION_REGIONSIZE_OFFSET 0x4 +#define SDS_REGION_DESC_SIZE 0x8 + +#ifndef __ASSEMBLER__ +#include +#include + +/* Header containing Shared Data Structure metadata */ +typedef struct structure_header { + uint32_t reg[2]; +} struct_header_t; + +#define GET_SDS_HEADER_ID(_header) \ + ((((struct_header_t *)(_header))->reg[0]) & SDS_HEADER_ID_MASK) +#define GET_SDS_HEADER_VERSION(_header) \ + (((((struct_header_t *)(_header))->reg[0]) >> SDS_HEADER_MINOR_VERSION_SHIFT)\ + & SDS_HEADER_VERSION_MASK) +#define GET_SDS_HEADER_STRUCT_SIZE(_header) \ + (((((struct_header_t *)(_header))->reg[1]) >> SDS_HEADER_STRUCT_SIZE_SHIFT)\ + & SDS_HEADER_STRUCT_SIZE_MASK) +#define IS_SDS_HEADER_VALID(_header) \ + ((((struct_header_t *)(_header))->reg[1]) & SDS_HEADER_VALID_MASK) +#define GET_SDS_STRUCT_FIELD(_header, _field_offset) \ + ((((uint8_t *)(_header)) + sizeof(struct_header_t)) + (_field_offset)) + +/* Region Descriptor describing the SDS Memory Region */ +typedef struct region_descriptor { + uint32_t reg[2]; +} region_desc_t; + +#define IS_SDS_REGION_VALID(region) \ + (((((region_desc_t *)(region))->reg[0]) & SDS_REGION_SIGNATURE_MASK) == SDS_REGION_SIGNATURE) +#define GET_SDS_REGION_STRUCTURE_COUNT(region) \ + (((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_STRUCT_COUNT_SHIFT)\ + & SDS_REGION_STRUCT_COUNT_MASK) +#define GET_SDS_REGION_SCHEMA_VERSION(region) \ + (((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_SCH_MINOR_SHIFT)\ + & SDS_REGION_SCH_VERSION_MASK) +#define GET_SDS_REGION_SIZE(region) ((((region_desc_t *)(region))->reg[1])) + +#endif /* __ASSEMBLER__ */ + +#endif /* SDS_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/dcc/dcc_console.c b/arm-trusted-firmware/drivers/arm/dcc/dcc_console.c new file mode 100644 index 0000000..0b7e541 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/dcc/dcc_console.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015-2021, Xilinx Inc. + * Written by Michal Simek. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* DCC Status Bits */ +#define DCC_STATUS_RX BIT(30) +#define DCC_STATUS_TX BIT(29) +#define TIMEOUT_COUNT_US U(0x10624) + +struct dcc_console { + struct console console; +}; + +static inline uint32_t __dcc_getstatus(void) +{ + return read_mdccsr_el0(); +} + +static inline char __dcc_getchar(void) +{ + char c; + + c = read_dbgdtrrx_el0(); + + return c; +} + +static inline void __dcc_putchar(char c) +{ + /* + * The typecast is to make absolutely certain that 'c' is + * zero-extended. + */ + write_dbgdtrtx_el0((unsigned char)c); +} + +static int32_t dcc_status_timeout(uint32_t mask) +{ + const unsigned int timeout_count = TIMEOUT_COUNT_US; + uint64_t timeout; + unsigned int status; + + timeout = timeout_init_us(timeout_count); + + do { + status = (__dcc_getstatus() & mask); + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } while ((status != 0U)); + + return 0; +} + +static int32_t dcc_console_putc(int32_t ch, struct console *console) +{ + unsigned int status; + + status = dcc_status_timeout(DCC_STATUS_TX); + if (status != 0U) { + return status; + } + __dcc_putchar(ch); + + return ch; +} + +static int32_t dcc_console_getc(struct console *console) +{ + unsigned int status; + + status = dcc_status_timeout(DCC_STATUS_RX); + if (status != 0U) { + return status; + } + + return __dcc_getchar(); +} + +int32_t dcc_console_init(unsigned long base_addr, uint32_t uart_clk, + uint32_t baud_rate) +{ + return 0; /* No init needed */ +} + +/** + * dcc_console_flush() - Function to force a write of all buffered data + * that hasn't been output. + * @console Console struct + * + */ +static void dcc_console_flush(struct console *console) +{ + unsigned int status; + + status = dcc_status_timeout(DCC_STATUS_TX); + if (status != 0U) { + return; + } +} + +static struct dcc_console dcc_console = { + .console = { + .flags = CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME, + .putc = dcc_console_putc, + .getc = dcc_console_getc, + .flush = dcc_console_flush, + }, +}; + +int console_dcc_register(void) +{ + return console_register(&dcc_console.console); +} diff --git a/arm-trusted-firmware/drivers/arm/dsu/ppu.c b/arm-trusted-firmware/drivers/arm/dsu/ppu.c new file mode 100644 index 0000000..cc00902 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/dsu/ppu.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* Global variables */ +static uint64_t ub_base; +static uint64_t ub_per_socket_mmio_size; +static uint32_t ub_num_cpus_per_socket; + +/* + * Follow the sequence from DSU-110 TRM section 6.6.1 to power on the + * core. Expect PPU_PWPR settings for the cluster and the core, from + * the platform. + */ +int dsu_ppu_core_power_on(uint32_t socket, uint32_t core, + uint32_t cluster_ppu_pwpr, uint32_t core_ppu_pwpr) +{ + uint32_t val; + uint64_t ub_base_socket; + + assert(ub_num_cpus_per_socket > 0U); + + /* Sanity check core number */ + if (core > (ub_num_cpus_per_socket - 1U)) { + ERROR("%s: invalid core %" PRIx32 "\n", __func__, core); + return -EINVAL; + } + + /* Sanity check base address */ + if (ub_base == U(0)) { + ERROR("%s: invalid base %" PRIx64 "\n", __func__, ub_base); + return -ENXIO; + } + + /* Calculate utility bus offset for the socket */ + ub_base_socket = ub_base + (ub_per_socket_mmio_size * socket); + + /* + * Set the static power mode policy to platform provided + * value + */ + dsu_ppu_cluster_write_32(core, ub_base_socket, PPU_PWPR, cluster_ppu_pwpr); + isb(); + + /* + * Poll the cluster PPU_PWSR register until the value + * read matches the value written to the PPU_PWPR + * register + */ + do { + val = dsu_ppu_cluster_read_32(core, ub_base_socket, PPU_PWSR); + } while (val != cluster_ppu_pwpr); + + /* + * Set the static power mode policy to platform provided + * value + */ + dsu_ppu_core_write_32(core, ub_base_socket, PPU_PWPR, core_ppu_pwpr); + isb(); + + /* + * Poll the core PPU_PWSR register until the value + * read matches the value written to the PPU_PWPR + * register + */ + do { + val = dsu_ppu_core_read_32(core, ub_base_socket, PPU_PWSR); + } while (val != core_ppu_pwpr); + + return 0; +} + +/* + * Follow the sequence from DSU-110 TRM section 6.6.2 to power off the + * core. Expect PPU_PWPR settings for the cluster and the core, from + * the platform. + */ +int dsu_ppu_core_power_off(uint32_t socket, uint32_t core, + uint32_t cluster_ppu_pwpr, uint32_t core_ppu_pwpr) +{ + uint64_t ub_base_socket; + + assert(ub_num_cpus_per_socket > 0U); + + /* Sanity check core number */ + if (core > (ub_num_cpus_per_socket - 1U)) { + return -EINVAL; + } + + /* Sanity check base address */ + if (ub_base == U(0)) { + ERROR("%s: invalid base %" PRIx64 "\n", __func__, ub_base); + return -ENXIO; + } + + /* Calculate utility bus offset for the socket */ + ub_base_socket = ub_base + (ub_per_socket_mmio_size * socket); + + /* + * Set the static power mode policy to platform provided + * value + */ + dsu_ppu_core_write_32(core, ub_base_socket, PPU_PWPR, core_ppu_pwpr); + isb(); + + /* + * This sets the static power mode policy to platform provided + * value + */ + dsu_ppu_cluster_write_32(core, ub_base_socket, PPU_PWPR, cluster_ppu_pwpr); + isb(); + + return 0; +} + +/* + * Setup PPU driver. Pass the utility bus base address. + */ +int dsu_ppu_setup(uint64_t base, uint64_t per_socket_mmio_size, + unsigned int num_cpus_per_socket) +{ + uint32_t num_sockets = PLATFORM_CORE_COUNT / num_cpus_per_socket; + int ret; + + if (base == U(0)) { + return -EINVAL; + } + + /* Ensure that we dont exceed UINT64 boundary */ + if ((UINT64_MAX / per_socket_mmio_size) < num_sockets) { + ERROR("%s: invalid number of sockets %" PRIx8 "\n", __func__, num_sockets); + return -ENOMEM; + } + + /* Ensure that we dont exceed UINT64 boundary */ + if ((UINT64_MAX - (per_socket_mmio_size * num_sockets)) < base) { + ERROR("%s: invalid number of sockets %" PRIx8 "\n", __func__, num_sockets); + return -ENOMEM; + } + + /* save global variables */ + ub_base = base; + ub_per_socket_mmio_size = per_socket_mmio_size; + ub_num_cpus_per_socket = num_cpus_per_socket; + + /* map memory for per-socket DSU region */ + for (unsigned int i = 0; i < num_sockets; i++) { + uint64_t socket_base = base + (i * per_socket_mmio_size); + + ret = mmap_add_dynamic_region(socket_base, socket_base, + PPU_REGION_SIZE * num_cpus_per_socket, + MT_DEVICE | MT_RW | MT_SECURE); + if (ret < 0) { + ERROR("%s: failed to map PPU region 0x%lx for socket %d - error code %d\n", + __func__, socket_base, i, ret); + return ret; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c b/arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c new file mode 100644 index 0000000..60364cd --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * Number of Arm Ethos-N NPU (NPU) cores available for a + * particular parent device + */ +#define ETHOSN_NUM_CORES \ + FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores) + +/* Address to an NPU core */ +#define ETHOSN_CORE_ADDR(core_idx) \ + FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx) + +/* NPU core sec registry address */ +#define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \ + (core_addr + reg_offset) + +/* Reset timeout in us */ +#define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000) +#define ETHOSN_RESET_WAIT_US U(1) + +#define SEC_DEL_REG U(0x0004) +#define SEC_DEL_VAL U(0x81C) +#define SEC_DEL_EXCC_MASK U(0x20) + +#define SEC_SECCTLR_REG U(0x0010) +#define SEC_SECCTLR_VAL U(0x3) + +#define SEC_DEL_MMUSID_REG U(0x2008) +#define SEC_DEL_MMUSID_VAL U(0x3FFFF) + +#define SEC_DEL_ADDR_EXT_REG U(0x201C) +#define SEC_DEL_ADDR_EXT_VAL U(0x15) + +#define SEC_SYSCTRL0_REG U(0x0018) +#define SEC_SYSCTRL0_SOFT_RESET U(3U << 29) +#define SEC_SYSCTRL0_HARD_RESET U(1U << 31) + +static bool ethosn_is_core_addr_valid(uintptr_t core_addr) +{ + for (uint32_t core_idx = 0U; core_idx < ETHOSN_NUM_CORES; core_idx++) { + if (ETHOSN_CORE_ADDR(core_idx) == core_addr) { + return true; + } + } + + return false; +} + +static void ethosn_delegate_to_ns(uintptr_t core_addr) +{ + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), + SEC_SECCTLR_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), + SEC_DEL_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG), + SEC_DEL_MMUSID_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), + SEC_DEL_ADDR_EXT_VAL); +} + +static int ethosn_is_sec(uintptr_t core_addr) +{ + if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG)) + & SEC_DEL_EXCC_MASK) != 0U) { + return 0; + } + + return 1; +} + +static bool ethosn_reset(uintptr_t core_addr, int hard_reset) +{ + unsigned int timeout; + const uintptr_t sysctrl0_reg = + ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); + const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET + : SEC_SYSCTRL0_SOFT_RESET; + + mmio_write_32(sysctrl0_reg, reset_val); + + /* Wait for reset to complete */ + for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; + timeout += ETHOSN_RESET_WAIT_US) { + + if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { + break; + } + + udelay(ETHOSN_RESET_WAIT_US); + } + + return timeout < ETHOSN_RESET_TIMEOUT_US; +} + +uintptr_t ethosn_smc_handler(uint32_t smc_fid, + u_register_t core_addr, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + int hard_reset = 0; + const uint32_t fid = smc_fid & FUNCID_NUM_MASK; + + /* Only SiP fast calls are expected */ + if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || + (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { + SMC_RET1(handle, SMC_UNK); + } + + /* Truncate parameters to 32-bits for SMC32 */ + if (GET_SMC_CC(smc_fid) == SMC_32) { + core_addr &= 0xFFFFFFFF; + x2 &= 0xFFFFFFFF; + x3 &= 0xFFFFFFFF; + x4 &= 0xFFFFFFFF; + } + + if (!is_ethosn_fid(smc_fid)) { + SMC_RET1(handle, SMC_UNK); + } + + /* Commands that do not require a valid core address */ + switch (fid) { + case ETHOSN_FNUM_VERSION: + SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); + } + + if (!ethosn_is_core_addr_valid(core_addr)) { + WARN("ETHOSN: Unknown core address given to SMC call.\n"); + SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS); + } + + /* Commands that require a valid addr */ + switch (fid) { + case ETHOSN_FNUM_IS_SEC: + SMC_RET1(handle, ethosn_is_sec(core_addr)); + case ETHOSN_FNUM_HARD_RESET: + hard_reset = 1; + /* Fallthrough */ + case ETHOSN_FNUM_SOFT_RESET: + if (!ethosn_reset(core_addr, hard_reset)) { + SMC_RET1(handle, ETHOSN_FAILURE); + } + ethosn_delegate_to_ns(core_addr); + SMC_RET1(handle, ETHOSN_SUCCESS); + default: + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c b/arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c new file mode 100644 index 0000000..75a2b66 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * TODO: Someday there will be a generic power controller api. At the moment + * each platform has its own pwrc so just exporting functions is fine. + */ +ARM_INSTANTIATE_LOCK; + +unsigned int fvp_pwrc_get_cpu_wkr(u_register_t mpidr) +{ + return PSYSR_WK(fvp_pwrc_read_psysr(mpidr)); +} + +unsigned int fvp_pwrc_read_psysr(u_register_t mpidr) +{ + unsigned int rc; + arm_lock_get(); + mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr); + rc = mmio_read_32(PWRC_BASE + PSYSR_OFF); + arm_lock_release(); + return rc; +} + +void fvp_pwrc_write_pponr(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PPONR_OFF, (unsigned int) mpidr); + arm_lock_release(); +} + +void fvp_pwrc_write_ppoffr(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PPOFFR_OFF, (unsigned int) mpidr); + arm_lock_release(); +} + +void fvp_pwrc_set_wen(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PWKUPR_OFF, + (unsigned int) (PWKUPR_WEN | mpidr)); + arm_lock_release(); +} + +void fvp_pwrc_clr_wen(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PWKUPR_OFF, + (unsigned int) mpidr); + arm_lock_release(); +} + +void fvp_pwrc_write_pcoffr(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PCOFFR_OFF, (unsigned int) mpidr); + arm_lock_release(); +} + +/* Nothing else to do here apart from initializing the lock */ +void __init plat_arm_pwrc_setup(void) +{ + arm_lock_init(); +} + + + diff --git a/arm-trusted-firmware/drivers/arm/gic/common/gic_common.c b/arm-trusted-firmware/drivers/arm/gic/common/gic_common.c new file mode 100644 index 0000000..bf6405f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h b/arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h new file mode 100644 index 0000000..1ab1bdb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c new file mode 100644 index 0000000..db9ba87 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "../common/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/arm-trusted-firmware/drivers/arm/gic/v2/gicv2.mk b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2.mk new file mode 100644 index 0000000..49996bb --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2.mk @@ -0,0 +1,15 @@ +# +# Copyright (c) 2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# No support for extended PPI and SPI range +GIC_EXT_INTID := 0 + +GICV2_SOURCES += drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/arm/gic/v2/gicdv2_helpers.c + +# Set GICv2 build option +$(eval $(call add_define,GIC_EXT_INTID)) \ No newline at end of file diff --git a/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c new file mode 100644 index 0000000..751316c --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2015-2020, 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 "gicv2_private.h" + +/* + * Accessor to read the GIC Distributor ITARGETSR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id) +{ + unsigned n = id >> ITARGETSR_SHIFT; + return mmio_read_32(base + GICD_ITARGETSR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor CPENDSGIR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id) +{ + unsigned n = id >> CPENDSGIR_SHIFT; + return mmio_read_32(base + GICD_CPENDSGIR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor SPENDSGIR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id) +{ + unsigned n = id >> SPENDSGIR_SHIFT; + return mmio_read_32(base + GICD_SPENDSGIR + (n << 2)); +} + +/* + * Accessor to write the GIC Distributor ITARGETSR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ITARGETSR_SHIFT; + mmio_write_32(base + GICD_ITARGETSR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor CPENDSGIR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned n = id >> CPENDSGIR_SHIFT; + mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor SPENDSGIR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned n = id >> SPENDSGIR_SHIFT; + mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val); +} + +/******************************************************************************* + * Get the current CPU bit mask from GICD_ITARGETSR0 + ******************************************************************************/ +unsigned int gicv2_get_cpuif_id(uintptr_t base) +{ + unsigned int val; + + val = gicd_read_itargetsr(base, 0); + return val & GIC_TARGET_CPU_MASK; +} + +/******************************************************************************* + * Helper function to configure the default attributes of SPIs. + ******************************************************************************/ +void gicv2_spis_configure_defaults(uintptr_t gicd_base) +{ + unsigned int index, num_ints; + + num_ints = gicd_read_typer(gicd_base); + num_ints &= TYPER_IT_LINES_NO_MASK; + num_ints = (num_ints + 1U) << 5; + + /* + * Treat all SPIs as G1NS by default. The number of interrupts is + * calculated as 32 * (IT_LINES + 1). We do 32 at a time. + */ + for (index = MIN_SPI_ID; index < num_ints; index += 32U) + gicd_write_igroupr(gicd_base, index, ~0U); + + /* Setup the default SPI priorities doing four at a time */ + for (index = MIN_SPI_ID; index < num_ints; index += 4U) + gicd_write_ipriorityr(gicd_base, + index, + GICD_IPRIORITYR_DEF_VAL); + + /* Treat all SPIs as level triggered by default, 16 at a time */ + for (index = MIN_SPI_ID; index < num_ints; index += 16U) + gicd_write_icfgr(gicd_base, index, 0U); +} + +/******************************************************************************* + * Helper function to configure properties of secure G0 SPIs. + ******************************************************************************/ +void gicv2_secure_spis_configure_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + unsigned int i; + const interrupt_prop_t *prop_desc; + + /* Make sure there's a valid property array */ + if (interrupt_props_num != 0U) + assert(interrupt_props != NULL); + + for (i = 0; i < interrupt_props_num; i++) { + prop_desc = &interrupt_props[i]; + + if (prop_desc->intr_num < MIN_SPI_ID) + continue; + + /* Configure this interrupt as a secure interrupt */ + assert(prop_desc->intr_grp == GICV2_INTR_GROUP0); + gicd_clr_igroupr(gicd_base, prop_desc->intr_num); + + /* Set the priority of this interrupt */ + gicd_set_ipriorityr(gicd_base, prop_desc->intr_num, + prop_desc->intr_pri); + + /* Target the secure interrupts to primary CPU */ + gicd_set_itargetsr(gicd_base, prop_desc->intr_num, + gicv2_get_cpuif_id(gicd_base)); + + /* Set interrupt configuration */ + gicd_set_icfgr(gicd_base, prop_desc->intr_num, + prop_desc->intr_cfg); + + /* Enable this interrupt */ + gicd_set_isenabler(gicd_base, prop_desc->intr_num); + } +} + +/******************************************************************************* + * Helper function to configure properties of secure G0 SGIs and PPIs. + ******************************************************************************/ +void gicv2_secure_ppi_sgi_setup_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + unsigned int i; + uint32_t sec_ppi_sgi_mask = 0; + const interrupt_prop_t *prop_desc; + + /* Make sure there's a valid property array */ + if (interrupt_props_num != 0U) + assert(interrupt_props != NULL); + + /* + * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a + * more scalable approach as it avoids clearing the enable bits in the + * GICD_CTLR. + */ + gicd_write_icenabler(gicd_base, 0U, ~0U); + + /* Setup the default PPI/SGI priorities doing four at a time */ + for (i = 0U; i < MIN_SPI_ID; i += 4U) + gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL); + + for (i = 0U; i < interrupt_props_num; i++) { + prop_desc = &interrupt_props[i]; + + if (prop_desc->intr_num >= MIN_SPI_ID) + continue; + + /* Configure this interrupt as a secure interrupt */ + assert(prop_desc->intr_grp == GICV2_INTR_GROUP0); + + /* + * Set interrupt configuration for PPIs. Configuration for SGIs + * are ignored. + */ + if ((prop_desc->intr_num >= MIN_PPI_ID) && + (prop_desc->intr_num < MIN_SPI_ID)) { + gicd_set_icfgr(gicd_base, prop_desc->intr_num, + prop_desc->intr_cfg); + } + + /* We have an SGI or a PPI. They are Group0 at reset */ + sec_ppi_sgi_mask |= (1u << prop_desc->intr_num); + + /* Set the priority of this interrupt */ + gicd_set_ipriorityr(gicd_base, prop_desc->intr_num, + prop_desc->intr_pri); + } + + /* + * Invert the bitmask to create a mask for non-secure PPIs and SGIs. + * Program the GICD_IGROUPR0 with this bit mask. + */ + gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask); + + /* Enable the Group 0 SGIs and PPIs */ + gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c new file mode 100644 index 0000000..939d097 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../common/gic_common_private.h" +#include "gicv2_private.h" + +static const gicv2_driver_data_t *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; + +/******************************************************************************* + * Enable secure interrupts and use FIQs to route them. Disable legacy bypass + * and set the priority mask register to allow all interrupts to trickle in. + ******************************************************************************/ +void gicv2_cpuif_enable(void) +{ + unsigned int val; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + /* + * Enable the Group 0 interrupts, FIQEn and disable Group 0/1 + * bypass. + */ + val = CTLR_ENABLE_G0_BIT | FIQ_EN_BIT | FIQ_BYP_DIS_GRP0; + val |= IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1; + + /* Program the idle priority in the PMR */ + gicc_write_pmr(driver_data->gicc_base, GIC_PRI_MASK); + gicc_write_ctlr(driver_data->gicc_base, val); +} + +/******************************************************************************* + * Place the cpu interface in a state where it can never make a cpu exit wfi as + * as result of an asserted interrupt. This is critical for powering down a cpu + ******************************************************************************/ +void gicv2_cpuif_disable(void) +{ + unsigned int val; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + /* Disable secure, non-secure interrupts and disable their bypass */ + val = gicc_read_ctlr(driver_data->gicc_base); + val &= ~(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1_BIT); + val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0; + val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1; + gicc_write_ctlr(driver_data->gicc_base, val); +} + +/******************************************************************************* + * Per cpu gic distributor setup which will be done by all cpus after a cold + * boot/hotplug. This marks out the secure SPIs and PPIs & enables them. + ******************************************************************************/ +void gicv2_pcpu_distif_init(void) +{ + unsigned int ctlr; + + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + gicv2_secure_ppi_sgi_setup_props(driver_data->gicd_base, + driver_data->interrupt_props, + driver_data->interrupt_props_num); + + /* Enable G0 interrupts if not already */ + ctlr = gicd_read_ctlr(driver_data->gicd_base); + if ((ctlr & CTLR_ENABLE_G0_BIT) == 0U) { + gicd_write_ctlr(driver_data->gicd_base, + ctlr | CTLR_ENABLE_G0_BIT); + } +} + +/******************************************************************************* + * Global gic distributor init which will be done by the primary cpu after a + * cold boot. It marks out the secure SPIs, PPIs & SGIs and enables them. It + * then enables the secure GIC distributor interface. + ******************************************************************************/ +void gicv2_distif_init(void) +{ + unsigned int ctlr; + + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + /* Disable the distributor before going further */ + ctlr = gicd_read_ctlr(driver_data->gicd_base); + gicd_write_ctlr(driver_data->gicd_base, + ctlr & ~(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1_BIT)); + + /* Set the default attribute of all SPIs */ + gicv2_spis_configure_defaults(driver_data->gicd_base); + + gicv2_secure_spis_configure_props(driver_data->gicd_base, + driver_data->interrupt_props, + driver_data->interrupt_props_num); + + + /* Re-enable the secure SPIs now that they have been configured */ + gicd_write_ctlr(driver_data->gicd_base, ctlr | CTLR_ENABLE_G0_BIT); +} + +/******************************************************************************* + * Initialize the ARM GICv2 driver with the provided platform inputs + ******************************************************************************/ +void gicv2_driver_init(const gicv2_driver_data_t *plat_driver_data) +{ + unsigned int gic_version; + + assert(plat_driver_data != NULL); + assert(plat_driver_data->gicd_base != 0U); + assert(plat_driver_data->gicc_base != 0U); + + assert(plat_driver_data->interrupt_props_num > 0 ? + plat_driver_data->interrupt_props != NULL : 1); + + /* Ensure that this is a GICv2 system */ + gic_version = gicd_read_pidr2(plat_driver_data->gicd_base); + gic_version = (gic_version >> PIDR2_ARCH_REV_SHIFT) + & PIDR2_ARCH_REV_MASK; + + /* + * GICv1 with security extension complies with trusted firmware + * GICv2 driver as far as virtualization and few tricky power + * features are not used. GICv2 features that are not supported + * by GICv1 with Security Extensions are: + * - virtual interrupt support. + * - wake up events. + * - writeable GIC state register (for power sequences) + * - interrupt priority drop. + * - interrupt signal bypass. + */ + assert((gic_version == ARCH_REV_GICV2) || + (gic_version == ARCH_REV_GICV1)); + + 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 or WARMBOOT_ENABLE_DCACHE_EARLY + * enabled. + */ +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + flush_dcache_range((uintptr_t) &driver_data, sizeof(driver_data)); + flush_dcache_range((uintptr_t) driver_data, sizeof(*driver_data)); +#endif + INFO("ARM GICv2 driver initialized\n"); +} + +/****************************************************************************** + * This function returns whether FIQ is enabled in the GIC CPU interface. + *****************************************************************************/ +unsigned int gicv2_is_fiq_enabled(void) +{ + unsigned int gicc_ctlr; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + gicc_ctlr = gicc_read_ctlr(driver_data->gicc_base); + return (gicc_ctlr >> FIQ_EN_SHIFT) & 0x1U; +} + +/******************************************************************************* + * 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_G1_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 gicv2_get_pending_interrupt_type(void) +{ + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + return gicc_read_hppir(driver_data->gicc_base) & INT_ID_MASK; +} + +/******************************************************************************* + * This function returns the id of the highest priority pending interrupt at + * the GIC cpu interface. GIC_SPURIOUS_INTERRUPT is returned when there is no + * interrupt pending. + ******************************************************************************/ +unsigned int gicv2_get_pending_interrupt_id(void) +{ + unsigned int id; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + id = gicc_read_hppir(driver_data->gicc_base) & INT_ID_MASK; + + /* + * Find out which non-secure interrupt it is under the assumption that + * the GICC_CTLR.AckCtl bit is 0. + */ + if (id == PENDING_G1_INTID) + id = gicc_read_ahppir(driver_data->gicc_base) & INT_ID_MASK; + + return id; +} + +/******************************************************************************* + * This functions reads the GIC cpu interface Interrupt Acknowledge register + * to start handling the pending secure 0 interrupt. It returns the + * contents of the IAR. + ******************************************************************************/ +unsigned int gicv2_acknowledge_interrupt(void) +{ + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + return gicc_read_IAR(driver_data->gicc_base); +} + +/******************************************************************************* + * This functions writes the GIC cpu interface End Of Interrupt register with + * the passed value to finish handling the active secure group 0 interrupt. + ******************************************************************************/ +void gicv2_end_of_interrupt(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + /* + * Ensure the write to peripheral registers are *complete* before the write + * to GIC_EOIR. + * + * Note: The completion gurantee depends on various factors of system design + * and the barrier is the best core can do by which execution of further + * instructions waits till the barrier is alive. + */ + dsbishst(); + gicc_write_EOIR(driver_data->gicc_base, id); +} + +/******************************************************************************* + * 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 secure or group1 non secure. It returns zero for Group 0 secure and + * one for Group 1 non secure interrupt. + ******************************************************************************/ +unsigned int gicv2_get_interrupt_group(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + return gicd_get_igroupr(driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function returns the priority of the interrupt the processor is + * currently servicing. + ******************************************************************************/ +unsigned int gicv2_get_running_priority(void) +{ + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + return gicc_read_rpr(driver_data->gicc_base); +} + +/******************************************************************************* + * This function sets the GICv2 target mask pattern for the current PE. The PE + * target mask is used to translate linear PE index (returned by platform core + * position) to a bit mask used when targeting interrupts to a PE (for example + * when raising SGIs and routing SPIs). + ******************************************************************************/ +void gicv2_set_pe_target_mask(unsigned int proc_num) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(driver_data->target_masks != NULL); + assert(proc_num < GICV2_MAX_TARGET_PE); + assert(proc_num < driver_data->target_masks_num); + + /* Return if the target mask is already populated */ + if (driver_data->target_masks[proc_num] != 0U) + return; + + /* + * Update target register corresponding to this CPU and flush for it to + * be visible to other CPUs. + */ + if (driver_data->target_masks[proc_num] == 0U) { + driver_data->target_masks[proc_num] = + gicv2_get_cpuif_id(driver_data->gicd_base); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + /* + * PEs only update their own masks. Primary updates it with + * caches on. But because secondaries does it with caches off, + * all updates go to memory directly, and there's no danger of + * secondaries overwriting each others' mask, despite + * target_masks[] not being cache line aligned. + */ + flush_dcache_range((uintptr_t) + &driver_data->target_masks[proc_num], + sizeof(driver_data->target_masks[proc_num])); +#endif + } +} + +/******************************************************************************* + * This function returns the active status of the interrupt (either because the + * state is active, or active and pending). + ******************************************************************************/ +unsigned int gicv2_get_interrupt_active(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + return gicd_get_isactiver(driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function enables the interrupt identified by id. + ******************************************************************************/ +void gicv2_enable_interrupt(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before enabling interrupt. + */ + dsbishst(); + gicd_set_isenabler(driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function disables the interrupt identified by id. + ******************************************************************************/ +void gicv2_disable_interrupt(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + /* + * Disable interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + gicd_set_icenabler(driver_data->gicd_base, id); + dsbishst(); +} + +/******************************************************************************* + * This function sets the interrupt priority as supplied for the given interrupt + * id. + ******************************************************************************/ +void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + gicd_set_ipriorityr(driver_data->gicd_base, id, priority); +} + +/******************************************************************************* + * This function assigns group for the interrupt identified by id. The group can + * be any of GICV2_INTR_GROUP* + ******************************************************************************/ +void gicv2_set_interrupt_type(unsigned int id, unsigned int type) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + /* Serialize read-modify-write to Distributor registers */ + spin_lock(&gic_lock); + switch (type) { + case GICV2_INTR_GROUP1: + gicd_set_igroupr(driver_data->gicd_base, id); + break; + case GICV2_INTR_GROUP0: + gicd_clr_igroupr(driver_data->gicd_base, id); + break; + default: + assert(false); + break; + } + spin_unlock(&gic_lock); +} + +/******************************************************************************* + * This function raises the specified SGI to requested targets. + * + * The proc_num parameter must be the linear index of the target PE in the + * system. + ******************************************************************************/ +void gicv2_raise_sgi(int sgi_num, int proc_num) +{ + unsigned int sgir_val, target; + + assert(driver_data != NULL); + assert(proc_num >= 0); + assert(proc_num < (int)GICV2_MAX_TARGET_PE); + assert(driver_data->gicd_base != 0U); + + /* + * Target masks array must have been supplied, and the core position + * should be valid. + */ + assert(driver_data->target_masks != NULL); + assert(proc_num < (int)driver_data->target_masks_num); + + /* Don't raise SGI if the mask hasn't been populated */ + target = driver_data->target_masks[proc_num]; + assert(target != 0U); + + sgir_val = GICV2_SGIR_VALUE(SGIR_TGT_SPECIFIC, target, sgi_num); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before raising SGI. + */ + dsbishst(); + gicd_write_sgir(driver_data->gicd_base, sgir_val); +} + +/******************************************************************************* + * This function sets the interrupt routing for the given SPI interrupt id. + * The interrupt routing is specified in routing mode. The proc_num parameter is + * linear index of the PE to target SPI. When proc_num < 0, the SPI may target + * all PEs. + ******************************************************************************/ +void gicv2_set_spi_routing(unsigned int id, int proc_num) +{ + unsigned int target; + + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + assert((id >= MIN_SPI_ID) && (id <= MAX_SPI_ID)); + + /* + * Target masks array must have been supplied, and the core position + * should be valid. + */ + assert(driver_data->target_masks != NULL); + assert(proc_num < (int)GICV2_MAX_TARGET_PE); + assert(driver_data->target_masks_num < INT_MAX); + assert(proc_num < (int)driver_data->target_masks_num); + + if (proc_num < 0) { + /* Target all PEs */ + target = GIC_TARGET_CPU_MASK; + } else { + /* Don't route interrupt if the mask hasn't been populated */ + target = driver_data->target_masks[proc_num]; + assert(target != 0U); + } + + gicd_set_itargetsr(driver_data->gicd_base, id, target); +} + +/******************************************************************************* + * This function clears the pending status of an interrupt identified by id. + ******************************************************************************/ +void gicv2_clear_interrupt_pending(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + /* SGIs can't be cleared pending */ + assert(id >= MIN_PPI_ID); + + /* + * Clear pending interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + gicd_set_icpendr(driver_data->gicd_base, id); + dsbishst(); +} + +/******************************************************************************* + * This function sets the pending status of an interrupt identified by id. + ******************************************************************************/ +void gicv2_set_interrupt_pending(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + /* SGIs can't be cleared pending */ + assert(id >= MIN_PPI_ID); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before setting interrupt pending. + */ + dsbishst(); + gicd_set_ispendr(driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function sets the PMR register with the supplied value. Returns the + * original PMR. + ******************************************************************************/ +unsigned int gicv2_set_pmr(unsigned int mask) +{ + unsigned int old_mask; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + old_mask = gicc_read_pmr(driver_data->gicc_base); + + /* + * Order memory updates w.r.t. PMR write, and ensure they're visible + * before potential out of band interrupt trigger because of PMR update. + */ + dmbishst(); + gicc_write_pmr(driver_data->gicc_base, mask); + dsbishst(); + + return old_mask; +} + +/******************************************************************************* + * This function updates single interrupt configuration to be level/edge + * triggered + ******************************************************************************/ +void gicv2_interrupt_set_cfg(unsigned int id, unsigned int cfg) +{ + gicd_set_icfgr(driver_data->gicd_base, id, cfg); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h new file mode 100644 index 0000000..0fbdab0 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GICV2_PRIVATE_H +#define GICV2_PRIVATE_H + +#include + +#include +#include + +/******************************************************************************* + * Private function prototypes + ******************************************************************************/ +void gicv2_spis_configure_defaults(uintptr_t gicd_base); +void gicv2_secure_spis_configure_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +void gicv2_secure_ppi_sgi_setup_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +unsigned int gicv2_get_cpuif_id(uintptr_t base); + +/******************************************************************************* + * GIC Distributor interface accessors for reading entire registers + ******************************************************************************/ +static inline unsigned int gicd_read_pidr2(uintptr_t base) +{ + return mmio_read_32(base + GICD_PIDR2_GICV2); +} + +/******************************************************************************* + * GIC Distributor interface accessors for writing entire registers + ******************************************************************************/ +static inline unsigned int gicd_get_itargetsr(uintptr_t base, unsigned int id) +{ + return mmio_read_8(base + GICD_ITARGETSR + id); +} + +static inline void gicd_set_itargetsr(uintptr_t base, unsigned int id, + unsigned int target) +{ + uint8_t val = target & GIC_TARGET_CPU_MASK; + + mmio_write_8(base + GICD_ITARGETSR + id, val); +} + +static inline void gicd_write_sgir(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICD_SGIR, val); +} + +/******************************************************************************* + * GIC CPU interface accessors for reading entire registers + ******************************************************************************/ + +static inline unsigned int gicc_read_ctlr(uintptr_t base) +{ + return mmio_read_32(base + GICC_CTLR); +} + +static inline unsigned int gicc_read_pmr(uintptr_t base) +{ + return mmio_read_32(base + GICC_PMR); +} + +static inline unsigned int gicc_read_BPR(uintptr_t base) +{ + return mmio_read_32(base + GICC_BPR); +} + +static inline unsigned int gicc_read_IAR(uintptr_t base) +{ + return mmio_read_32(base + GICC_IAR); +} + +static inline unsigned int gicc_read_EOIR(uintptr_t base) +{ + return mmio_read_32(base + GICC_EOIR); +} + +static inline unsigned int gicc_read_hppir(uintptr_t base) +{ + return mmio_read_32(base + GICC_HPPIR); +} + +static inline unsigned int gicc_read_ahppir(uintptr_t base) +{ + return mmio_read_32(base + GICC_AHPPIR); +} + +static inline unsigned int gicc_read_dir(uintptr_t base) +{ + return mmio_read_32(base + GICC_DIR); +} + +static inline unsigned int gicc_read_iidr(uintptr_t base) +{ + return mmio_read_32(base + GICC_IIDR); +} + +static inline unsigned int gicc_read_rpr(uintptr_t base) +{ + return mmio_read_32(base + GICC_RPR); +} + +/******************************************************************************* + * GIC CPU interface accessors for writing entire registers + ******************************************************************************/ + +static inline void gicc_write_ctlr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_CTLR, val); +} + +static inline void gicc_write_pmr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_PMR, val); +} + +static inline void gicc_write_BPR(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_BPR, val); +} + + +static inline void gicc_write_IAR(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_IAR, val); +} + +static inline void gicc_write_EOIR(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_EOIR, val); +} + +static inline void gicc_write_hppir(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_HPPIR, val); +} + +static inline void gicc_write_dir(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_DIR, val); +} + +#endif /* GICV2_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c b/arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c new file mode 100644 index 0000000..4489892 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c b/arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c new file mode 100644 index 0000000..aaef485 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c @@ -0,0 +1,172 @@ +/* + * 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 + +#include "gicv3_private.h" + +/* GIC-600 specific register offsets */ +#define GICR_PWRR 0x24U + +/* 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/700 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-700 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_700)); +} + +#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/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c b/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c new file mode 100644 index 0000000..5f42ad9 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c @@ -0,0 +1,254 @@ +/* + * 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 + +#include "../common/gic_common_private.h" +#include "gic600_multichip_private.h" + +/******************************************************************************* + * 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; + unsigned int gicd_iidr_val = gicd_read_iidr(base); + 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); + + switch ((gicd_iidr_val & IIDR_MODEL_MASK)) { + case IIDR_MODEL_ARM_GIC_600: + chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr, + spi_block_min, + spi_blocks); + break; + case IIDR_MODEL_ARM_GIC_700: + chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr, + spi_block_min, + spi_blocks); + break; + default: + ERROR("Unsupported GIC model 0x%x for multichip setup.\n", + gicd_iidr_val); + panic(); + break; + } + chipr_n_val |= 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); + + /* + * 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/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h b/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h new file mode 100644 index 0000000..5d1ff6a --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h @@ -0,0 +1,105 @@ +/* + * 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 + +/* Other shifts and masks remain the same between GIC-600 and GIC-700. */ +#define GIC_700_SPI_BLOCK_MIN_SHIFT 9 +#define GIC_700_SPI_BLOCKS_SHIFT 3 +#define GIC_600_SPI_BLOCK_MIN_SHIFT 10 +#define GIC_600_SPI_BLOCKS_SHIFT 5 + +#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_GIC_700(chip_addr, spi_block_min, spi_blocks) \ + (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ + ((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GIC_700_SPI_BLOCKS_SHIFT)) +#define GICD_CHIPR_VALUE_GIC_600(chip_addr, spi_block_min, spi_blocks) \ + (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ + ((spi_block_min) << GIC_600_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GIC_600_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/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c b/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c new file mode 100644 index 0000000..7a033bd --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Driver for GIC-600AE Fault Management Unit + */ + +#include +#include + +#include +#include +#include +#include + +/* GIC-600 AE FMU specific register offsets */ + +/* GIC-600 AE FMU specific macros */ +#define FMU_ERRIDR_NUM U(44) +#define FMU_ERRIDR_NUM_MASK U(0xFFFF) + +/* Safety mechanisms for GICD block */ +static char *gicd_sm_info[] = { + "Reserved", + "GICD dual lockstep error", + "GICD AXI4 slave interface error", + "GICD-PPI AXI4-Stream interface error", + "GICD-ITS AXI4-Stream interface error", + "GICD-SPI-Collator AXI4-Stream interface error", + "GICD AXI4 master interface error", + "SPI RAM DED error", + "SGI RAM DED error", + "Reserved", + "LPI RAM DED error", + "GICD-remote-GICD AXI4-Stream interface error", + "GICD Q-Channel interface error", + "GICD P-Channel interface error", + "SPI RAM address decode error", + "SGI RAM address decode error", + "Reserved", + "LPI RAM address decode error", + "FMU dual lockstep error", + "FMU ping ACK error", + "FMU APB parity error", + "GICD-Wake AXI4-Stream interface error", + "GICD PageOffset or Chip ID error", + "MBIST REQ error", + "SPI RAM SEC error", + "SGI RAM SEC error", + "Reserved", + "LPI RAM SEC error", + "User custom SM0 error", + "User custom SM1 error", + "GICD-ITS Monolithic switch error", + "GICD-ITS Q-Channel interface error", + "GICD-ITS Monolithic interface error", + "GICD FMU ClkGate override" +}; + +/* Safety mechanisms for PPI block */ +static char *ppi_sm_info[] = { + "Reserved", + "PPI dual lockstep error", + "PPI-GICD AXI4-Stream interface error", + "PPI-CPU-IF AXI4-Stream interface error", + "PPI Q-Channel interface error", + "PPI RAM DED error", + "PPI RAM address decode error", + "PPI RAM SEC error", + "PPI User0 SM", + "PPI User1 SM", + "MBIST REQ error", + "PPI interrupt parity protection error", + "PPI FMU ClkGate override" +}; + +/* Safety mechanisms for ITS block */ +static char *its_sm_info[] = { + "Reserved", + "ITS dual lockstep error", + "ITS-GICD AXI4-Stream interface error", + "ITS AXI4 slave interface error", + "ITS AXI4 master interface error", + "ITS Q-Channel interface error", + "ITS RAM DED error", + "ITS RAM address decode error", + "Bypass ACE switch error", + "ITS RAM SEC error", + "ITS User0 SM", + "ITS User1 SM", + "ITS-GICD Monolithic interface error", + "MBIST REQ error", + "ITS FMU ClkGate override" +}; + +/* Safety mechanisms for SPI Collator block */ +static char *spicol_sm_info[] = { + "Reserved", + "SPI Collator dual lockstep error", + "SPI-Collator-GICD AXI4-Stream interface error", + "SPI Collator Q-Channel interface error", + "SPI Collator Q-Channel clock error", + "SPI interrupt parity error" +}; + +/* Safety mechanisms for Wake Request block */ +static char *wkrqst_sm_info[] = { + "Reserved", + "Wake dual lockstep error", + "Wake-GICD AXI4-Stream interface error" +}; + +/* Helper function to find detailed information for a specific IERR */ +static char *ras_ierr_to_str(unsigned int blkid, unsigned int ierr) +{ + char *str = NULL; + + /* Find the correct record */ + switch (blkid) { + case FMU_BLK_GICD: + assert(ierr < ARRAY_SIZE(gicd_sm_info)); + str = gicd_sm_info[ierr]; + break; + + case FMU_BLK_SPICOL: + assert(ierr < ARRAY_SIZE(spicol_sm_info)); + str = spicol_sm_info[ierr]; + break; + + case FMU_BLK_WAKERQ: + assert(ierr < ARRAY_SIZE(wkrqst_sm_info)); + str = wkrqst_sm_info[ierr]; + break; + + case FMU_BLK_ITS0...FMU_BLK_ITS7: + assert(ierr < ARRAY_SIZE(its_sm_info)); + str = its_sm_info[ierr]; + break; + + case FMU_BLK_PPI0...FMU_BLK_PPI31: + assert(ierr < ARRAY_SIZE(ppi_sm_info)); + str = ppi_sm_info[ierr]; + break; + + default: + assert(1); + break; + } + + return str; +} + +/* + * Probe for error in memory-mapped registers containing error records. + * Upon detecting an error, set probe data to the index of the record + * in error, and return 1; otherwise, return 0. + */ +int gic600_fmu_probe(uint64_t base, int *probe_data) +{ + uint64_t gsr; + + assert(base != 0UL); + + /* + * Read ERR_GSR to find the error record 'M' + */ + gsr = gic_fmu_read_errgsr(base); + if (gsr == U(0)) { + return 0; + } + + /* Return the index of the record in error */ + if (probe_data != NULL) { + *probe_data = (int)__builtin_ctzll(gsr); + } + + return 1; +} + +/* + * The handler function to read RAS records and find the safety + * mechanism with the error. + */ +int gic600_fmu_ras_handler(uint64_t base, int probe_data) +{ + uint64_t errstatus; + unsigned int blkid, ierr, serr; + + assert(base != 0UL); + assert((unsigned int)probe_data <= FMU_BLK_PPI31); + + /* + * Find more information by reading FMU_ERRSTATUS + * register + */ + errstatus = gic_fmu_read_errstatus(base, probe_data); + + /* + * If FMU_ERRSTATUS.V is set to 0, no RAS records + * need to be scanned. + */ + if ((errstatus & FMU_ERRSTATUS_V_BIT) == U(0)) { + return 0; + } + + /* + * FMU_ERRGSR indicates the ID of the GIC + * block that faulted. + */ + blkid = (unsigned int)probe_data; + assert(blkid <= FMU_BLK_PPI31); + + /* + * FMU_ERRSTATUS.IERR indicates which Safety Mechanism + * reported the error. + */ + ierr = (errstatus >> FMU_ERRSTATUS_IERR_SHIFT) & + FMU_ERRSTATUS_IERR_MASK; + + /* + * FMU_ERRSTATUS.SERR indicates architecturally + * defined primary error code. + */ + serr = errstatus & FMU_ERRSTATUS_SERR_MASK; + + ERROR("**************************************\n"); + ERROR("RAS %s Error detected by GIC600 AE FMU\n", + ((errstatus & FMU_ERRSTATUS_UE_BIT) != 0U) ? + "Uncorrectable" : "Corrected"); + ERROR("\tStatus = 0x%" PRIx64 "\n", errstatus); + ERROR("\tBlock ID = 0x%x\n", blkid); + ERROR("\tSafety Mechanism ID = 0x%x (%s)\n", ierr, + ras_ierr_to_str(blkid, ierr)); + ERROR("\tArchitecturally defined primary error code = 0x%x\n", + serr); + ERROR("**************************************\n"); + + /* Clear FMU_ERRSTATUS */ + gic_fmu_write_errstatus(base, probe_data, errstatus); + + return 0; +} + +/* + * Initialization sequence for the FMU + * + * 1. enable error detection for error records that are passed in the blk_present_mask + * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records + * that are present on the platform + * + * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`. + */ +void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, + bool errctlr_ce_en, bool errctlr_ue_en) +{ + unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK; + uint64_t errctlr; + uint32_t smen; + + INFO("GIC600-AE FMU supports %d error records\n", num_blk); + + assert(num_blk == FMU_ERRIDR_NUM); + + /* sanitize block present mask */ + blk_present_mask &= FMU_BLK_PRESENT_MASK; + + /* Enable error detection for all error records */ + for (unsigned int i = 0U; i < num_blk; i++) { + + /* Skip next steps if the block is not present */ + if ((blk_present_mask & BIT(i)) == 0U) { + continue; + } + + /* Read the error record control register */ + errctlr = gic_fmu_read_errctlr(base, i); + + /* Enable error reporting and logging, if it is disabled */ + if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) { + errctlr |= FMU_ERRCTLR_ED_BIT; + } + + /* Enable client provided ERRCTLR settings */ + errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0); + errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U); + + gic_fmu_write_errctlr(base, i, errctlr); + } + + /* + * Disable all safety mechanisms for blocks that are not + * present + */ + for (unsigned int i = FMU_BLK_GICD; i <= FMU_BLK_PPI31; i++) { + if ((blk_present_mask & BIT(i)) == 0U) { + gic_fmu_disable_all_sm_blkid(base, i); + } + } + + /* + * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for + * all blocks + * + * GICD, SMID 23 and SMID 33 + * PPI, SMID 10 and SMID 12 + * ITS, SMID 13 and SMID 14 + */ + if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) { + smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + + smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + } + + for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) { + if ((blk_present_mask & BIT(i)) != 0U) { + smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + + smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + } + } + + for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) { + if ((blk_present_mask & BIT(i)) != 0U) { + smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + + smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + } + } +} + +/* + * This function enable the GICD background ping engine. The GICD sends ping + * messages to each remote GIC block, and expects a PING_ACK back within the + * specified timeout. Pings need to be enabled after programming the timeout + * value. + */ +void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask, + unsigned int timeout_val, unsigned int interval_diff) +{ + /* + * Populate the PING Mask to skip a specific block while generating + * background ping messages and enable the ping mechanism. + */ + gic_fmu_write_pingmask(base, ~blk_present_mask); + gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) | + (timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT); +} + +/* Print the safety mechanism description for a given block */ +void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid) +{ + if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) { + INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]); + } + + if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) { + INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]); + } + + if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) { + INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]); + } + + if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) { + INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]); + } + + if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) { + INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]); + } +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c new file mode 100644 index 0000000..b1abd0a --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#define GICFMU_IDLE_TIMEOUT_US U(2000000) + +/* Macro to write 32-bit FMU registers */ +#define GIC_FMU_WRITE_32(base, reg, val) \ + do { \ + /* \ + * This register receives the unlock key that is required for \ + * writes to FMU registers to be successful. \ + */ \ + mmio_write_32(base + GICFMU_KEY, 0xBE); \ + /* Perform the actual write */ \ + mmio_write_32((base) + (reg), (val)); \ + } while (false) + +/* Macro to write 64-bit FMU registers */ +#define GIC_FMU_WRITE_64(base, reg, n, val) \ + do { \ + /* \ + * This register receives the unlock key that is required for \ + * writes to FMU registers to be successful. \ + */ \ + mmio_write_32(base + GICFMU_KEY, 0xBE); \ + /* \ + * APB bus is 32-bit wide; so split the 64-bit write into \ + * two 32-bit writes \ + */ \ + mmio_write_32((base) + reg##_LO + (n * 64), (val)); \ + mmio_write_32((base) + reg##_HI + (n * 64), (val)); \ + } while (false) + +/* Helper function to wait until FMU is ready to accept the next command */ +static void wait_until_fmu_is_idle(uintptr_t base) +{ + uint32_t timeout_count = GICFMU_IDLE_TIMEOUT_US; + uint64_t status; + + /* wait until status is 'busy' */ + do { + status = (gic_fmu_read_status(base) & BIT(0)); + + if (timeout_count-- == 0U) { + ERROR("GIC600 AE FMU is not responding\n"); + panic(); + } + + udelay(1U); + + } while (status == U(0)); +} + +#define GIC_FMU_WRITE_ON_IDLE_32(base, reg, val) \ + do { \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + /* Actual register write */ \ + GIC_FMU_WRITE_32(base, reg, val); \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + } while (false) + +#define GIC_FMU_WRITE_ON_IDLE_64(base, reg, n, val) \ + do { \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + /* Actual register write */ \ + GIC_FMU_WRITE_64(base, reg, n, val); \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + } while (false) + +/******************************************************************************* + * GIC FMU functions for accessing the Fault Management Unit registers + ******************************************************************************/ + +/* + * Accessors to read the Error Record Feature Register bits corresponding + * to an error record 'n' + */ +uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRFR_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRFR_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Record Control Register bits corresponding + * to an error record 'n' + */ +uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Record Primary Status Register bits + * corresponding to an error record 'n' + */ +uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Group Status Register + */ +uint64_t gic_fmu_read_errgsr(uintptr_t base) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRGSR_LO); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRGSR_HI) << 32); + return reg_val; +} + +/* + * Accessors to read the Ping Control Register + */ +uint32_t gic_fmu_read_pingctlr(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_PINGCTLR); +} + +/* + * Accessors to read the Ping Now Register + */ +uint32_t gic_fmu_read_pingnow(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_PINGNOW); +} + +/* + * Accessors to read the Ping Mask Register + */ +uint64_t gic_fmu_read_pingmask(uintptr_t base) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_PINGMASK_LO); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_PINGMASK_HI) << 32); + return reg_val; +} + +/* + * Accessors to read the FMU Status Register + */ +uint32_t gic_fmu_read_status(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_STATUS); +} + +/* + * Accessors to read the Error Record ID Register + */ +uint32_t gic_fmu_read_erridr(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_ERRIDR); +} + +/* + * Accessors to write a 64 bit value to the Error Record Control Register + */ +void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val) +{ + GIC_FMU_WRITE_64(base, GICFMU_ERRCTLR, n, val); +} + +/* + * Accessors to write a 64 bit value to the Error Record Primary Status + * Register + */ +void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_64(base, GICFMU_ERRSTATUS, n, val); +} + +/* + * Accessors to write a 32 bit value to the Ping Control Register + */ +void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val) +{ + GIC_FMU_WRITE_32(base, GICFMU_PINGCTLR, val); +} + +/* + * Accessors to write a 32 bit value to the Ping Now Register + */ +void gic_fmu_write_pingnow(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_PINGNOW, val); +} + +/* + * Accessors to write a 32 bit value to the Safety Mechanism Enable Register + */ +void gic_fmu_write_smen(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMEN, val); +} + +/* + * Accessors to write a 32 bit value to the Safety Mechanism Inject Error + * Register + */ +void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMINJERR, val); +} + +/* + * Accessors to write a 64 bit value to the Ping Mask Register + */ +void gic_fmu_write_pingmask(uintptr_t base, uint64_t val) +{ + GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val); +} + +/* + * Helper function to disable all safety mechanisms for a given block + */ +void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid) +{ + uint32_t smen, max_smid = U(0); + + /* Sanity check block ID */ + assert((blkid >= FMU_BLK_GICD) && (blkid <= FMU_BLK_PPI31)); + + /* Find the max safety mechanism ID for the block */ + switch (blkid) { + case FMU_BLK_GICD: + max_smid = FMU_SMID_GICD_MAX; + break; + + case FMU_BLK_SPICOL: + max_smid = FMU_SMID_SPICOL_MAX; + break; + + case FMU_BLK_WAKERQ: + max_smid = FMU_SMID_WAKERQ_MAX; + break; + + case FMU_BLK_ITS0...FMU_BLK_ITS7: + max_smid = FMU_SMID_ITS_MAX; + break; + + case FMU_BLK_PPI0...FMU_BLK_PPI31: + max_smid = FMU_SMID_PPI_MAX; + break; + + default: + assert(1); + break; + } + + /* Disable all Safety Mechanisms for a given block id */ + for (unsigned int i = 0; i < max_smid; i++) { + smen = (blkid << FMU_SMEN_BLK_SHIFT) | (i << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(base, smen); + } +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c new file mode 100644 index 0000000..987be69 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c new file mode 100644 index 0000000..3004054 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/arm/gic/v3/gicv3.mk b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3.mk new file mode 100644 index 0000000..8891ff5 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3.mk @@ -0,0 +1,50 @@ +# +# Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2021, NVIDIA Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Default configuration values +GICV3_SUPPORT_GIC600 ?= 0 +GICV3_SUPPORT_GIC600AE_FMU ?= 0 +GICV3_IMPL_GIC600_MULTICHIP ?= 0 +GICV3_OVERRIDE_DISTIF_PWR_OPS ?= 0 +GIC_ENABLE_V4_EXTN ?= 0 +GIC_EXT_INTID ?= 0 +GICV3_RESTRICT_GICT_GICP_ACCESS ?= 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_SUPPORT_GIC600AE_FMU}, 1) +GICV3_SOURCES += drivers/arm/gic/v3/gic600ae_fmu.c \ + drivers/arm/gic/v3/gic600ae_fmu_helpers.c +endif + +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 GIC-600AE FMU support +$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU)) +$(eval $(call add_define,GICV3_SUPPORT_GIC600AE_FMU)) + +# 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/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c new file mode 100644 index 0000000..753d995 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c @@ -0,0 +1,410 @@ +/* + * 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 += gicv3_redist_size(typer_val); + } while ((typer_val & TYPER_LAST_BIT) == 0U); +} + +/******************************************************************************* + * Helper function to get the maximum SPI INTID + 1. + ******************************************************************************/ +unsigned int gicv3_get_spi_limit(uintptr_t gicd_base) +{ + unsigned int spi_limit; + unsigned int typer_reg = gicd_read_typer(gicd_base); + + /* (maximum SPI INTID + 1) is equal to 32 * (GICD_TYPER.ITLinesNumber+1) */ + spi_limit = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5; + + /* Filter out special INTIDs 1020-1023 */ + if (spi_limit > (MAX_SPI_ID + 1U)) { + return MAX_SPI_ID + 1U; + } + + return spi_limit; +} + +#if GIC_EXT_INTID +/******************************************************************************* + * Helper function to get the maximum ESPI INTID + 1. + ******************************************************************************/ +unsigned int gicv3_get_espi_limit(uintptr_t gicd_base) +{ + unsigned int typer_reg = gicd_read_typer(gicd_base); + + /* Check if extended SPI range is implemented */ + if ((typer_reg & TYPER_ESPI) != 0U) { + /* + * (maximum ESPI INTID + 1) is equal to + * 32 * (GICD_TYPER.ESPI_range + 1) + 4096 + */ + return ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) & + TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID; + } + + return 0U; +} +#endif /* GIC_EXT_INTID */ + +/******************************************************************************* + * 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 + + num_ints = gicv3_get_spi_limit(gicd_base); + 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 + num_eints = gicv3_get_espi_limit(gicd_base); + if (num_eints != 0U) { + 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 { + 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 = 1U; count < PLATFORM_CORE_COUNT; count++) { + uint64_t typer_val = gicr_read_typer(rdistif_base); + + if ((typer_val & TYPER_LAST_BIT) != 0U) { + break; + } + rdistif_base += gicv3_redist_size(typer_val); + } + + return count; +} + +unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame) +{ + unsigned int part_id; + + /* + * The lower 8 bits of PIDR0, complemented by the lower 4 bits of + * PIDR1 contain a part number identifying the GIC component at a + * particular base address. + */ + part_id = mmio_read_32(gic_frame + GICD_PIDR0_GICV3) & 0xff; + part_id |= (mmio_read_32(gic_frame + GICD_PIDR1_GICV3) << 8) & 0xf00; + + return part_id; +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c new file mode 100644 index 0000000..6c2dc4b --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c @@ -0,0 +1,1350 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. 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_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); + +#if GICV3_RESTRICT_GICT_GICP_ACCESS + /* + * Restrict access to GIC Trace and PMU to secure only by + * Set TNS and PNS bit in GICD_SAC register + */ + bitmap = gicd_read_sac(gicv3_driver_data->gicd_base); + bitmap &= ~(SAC_GICTNS | SAC_GICPNS); + gicd_write_sac(gicv3_driver_data->gicd_base, bitmap); +#endif + + 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(); + /* Add DSB to ensure visibility of System register writes */ + dsb(); +} + +/******************************************************************************* + * 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(); + /* Add DSB to ensure visibility of System register writes */ + dsb(); + + /* 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); + } + + flush_dcache_range((uint64_t)rdist_ctx, sizeof(gicv3_redist_ctx_t)); + + /* + * 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) +{ + 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; + unsigned int num_ints = gicv3_get_spi_limit(gicd_base); +#if GIC_EXT_INTID + unsigned int num_eints = gicv3_get_espi_limit(gicd_base); +#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); + + flush_dcache_range((uint64_t)dist_ctx, sizeof(gicv3_dist_ctx_t)); + + /* + * 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) +{ + 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); + + unsigned int num_ints = gicv3_get_spi_limit(gicd_base); +#if GIC_EXT_INTID + unsigned int num_eints = gicv3_get_espi_limit(gicd_base); +#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 += gicv3_redist_size(typer_val); + } 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/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h new file mode 100644 index 0000000..f56a5be --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h @@ -0,0 +1,718 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. 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 & MPIDR_AFFINITY_MASK) | + ((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 + ******************************************************************************/ +unsigned int gicv3_get_spi_limit(uintptr_t gicd_base); +unsigned int gicv3_get_espi_limit(uintptr_t gicd_base); +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); + } +} + +static inline uint32_t gicd_read_sac(uintptr_t base) +{ + return mmio_read_32(base + GICD_SAC); +} + +static inline void gicd_write_sac(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GICD_SAC, val); +} + +/******************************************************************************* + * 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/arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S b/arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S new file mode 100644 index 0000000..9caeb0c --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writeable memory and are thus safe to call in BL1 crash context. + */ + .globl console_pl011_core_init + .globl console_pl011_core_putc + .globl console_pl011_core_getc + .globl console_pl011_core_flush + + .globl console_pl011_putc + .globl console_pl011_getc + .globl console_pl011_flush + + + /* ----------------------------------------------- + * int console_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: r0 - console base address + * r1 - Uart clock in Hz + * r2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : r1, r2, r3 + * ----------------------------------------------- + */ +func console_pl011_core_init + /* Check the input base address */ + cmp r0, #0 + beq core_init_fail +#if !PL011_GENERIC_UART + /* Check baud rate and uart clock for sanity */ + cmp r1, #0 + beq core_init_fail + cmp r2, #0 + beq core_init_fail + /* Disable the UART before initialization */ + ldr r3, [r0, #UARTCR] + bic r3, r3, #PL011_UARTCR_UARTEN + str r3, [r0, #UARTCR] + /* Program the baudrate */ + /* Divisor = (Uart clock * 4) / baudrate */ + lsl r1, r1, #2 +#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + push {r0,r3} + softudiv r0,r1,r2,r3 + mov r2, r0 + pop {r0,r3} +#else + udiv r2, r1, r2 +#endif + /* IBRD = Divisor >> 6 */ + lsr r1, r2, #6 + /* Write the IBRD */ + str r1, [r0, #UARTIBRD] + /* FBRD = Divisor & 0x3F */ + and r1, r2, #0x3f + /* Write the FBRD */ + str r1, [r0, #UARTFBRD] + mov r1, #PL011_LINE_CONTROL + str r1, [r0, #UARTLCR_H] + /* Clear any pending errors */ + mov r1, #0 + str r1, [r0, #UARTECR] + /* Enable tx, rx, and uart overall */ + ldr r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) + str r1, [r0, #UARTCR] +#endif + mov r0, #1 + bx lr +core_init_fail: + mov r0, #0 + bx lr +endfunc console_pl011_core_init + + .globl console_pl011_register + + /* ------------------------------------------------------- + * int console_pl011_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new PL011 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: r0 - UART register base address + * r1 - UART clock in Hz + * r2 - Baud rate + * r3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : r0, r1, r2 + * ------------------------------------------------------- + */ +func console_pl011_register + push {r4, lr} + mov r4, r3 + cmp r4, #0 + beq register_fail + str r0, [r4, #CONSOLE_T_BASE] + + bl console_pl011_core_init + cmp r0, #0 + beq register_fail + + mov r0, r4 + pop {r4, lr} + finish_console_register pl011 putc=1, getc=1, flush=1 + +register_fail: + pop {r4, pc} +endfunc console_pl011_register + + /* -------------------------------------------------------- + * int console_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +func console_pl011_core_putc + /* Check the input parameter */ + cmp r1, #0 + beq putc_error + /* Prepend '\r' to '\n' */ + cmp r0, #0xA + bne 2f +1: + /* Check if the transmit FIFO is full */ + ldr r2, [r1, #UARTFR] + tst r2, #PL011_UARTFR_TXFF + bne 1b + mov r2, #0xD + str r2, [r1, #UARTDR] +2: + /* Check if the transmit FIFO is full */ + ldr r2, [r1, #UARTFR] + tst r2, #PL011_UARTFR_TXFF + bne 2b + str r0, [r1, #UARTDR] + bx lr +putc_error: + mov r0, #-1 + bx lr +endfunc console_pl011_core_putc + + /* -------------------------------------------------------- + * int console_pl011_putc(int c, console_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In: r0 - character to be printed + * r1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list: r2 + * ------------------------------------------------------- + */ +func console_pl011_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r1, [r1, #CONSOLE_T_BASE] + b console_pl011_core_putc +endfunc console_pl011_putc + + /* --------------------------------------------- + * int console_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on error. + * In : r0 - console base address + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_pl011_core_getc + cmp r0, #0 + beq getc_error +1: + /* Check if the receive FIFO is empty */ + ldr r1, [r0, #UARTFR] + tst r1, #PL011_UARTFR_RXFE + bne 1b + ldr r1, [r0, #UARTDR] + mov r0, r1 + bx lr +getc_error: + mov r0, #-1 + bx lr +endfunc console_pl011_core_getc + + /* ------------------------------------------------ + * int console_pl011_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : r0 - pointer to console_t structure + * Out: r0 - character if available, else -1 + * Clobber list: r0, r1 + * ------------------------------------------------ + */ +func console_pl011_getc +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_pl011_core_getc +endfunc console_pl011_getc + + /* --------------------------------------------- + * void console_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - console base address + * Out : void + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_pl011_core_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + +1: + /* Loop while the transmit FIFO is busy */ + ldr r1, [r0, #UARTFR] + tst r1, #PL011_UARTFR_BUSY + bne 1b + + bx lr +endfunc console_pl011_core_flush + + /* --------------------------------------------- + * void console_pl011_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - pointer to console_t structure + * Out : void + * Clobber list: r0, r1 + * --------------------------------------------- + */ +func console_pl011_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_pl011_core_flush +endfunc console_pl011_flush diff --git a/arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S b/arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S new file mode 100644 index 0000000..861d2ed --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_pl011_core_init + .globl console_pl011_core_putc + .globl console_pl011_core_getc + .globl console_pl011_core_flush + + .globl console_pl011_putc + .globl console_pl011_getc + .globl console_pl011_flush + + /* ----------------------------------------------- + * int console_pl011_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : x1, x2, x3, x4 + * ----------------------------------------------- + */ +func console_pl011_core_init + /* Check the input base address */ + cbz x0, core_init_fail +#if !PL011_GENERIC_UART + /* Check baud rate and uart clock for sanity */ + cbz w1, core_init_fail + cbz w2, core_init_fail + /* Disable uart before programming */ + ldr w3, [x0, #UARTCR] + mov w4, #PL011_UARTCR_UARTEN + bic w3, w3, w4 + str w3, [x0, #UARTCR] + /* Program the baudrate */ + /* Divisor = (Uart clock * 4) / baudrate */ + lsl w1, w1, #2 + udiv w2, w1, w2 + /* IBRD = Divisor >> 6 */ + lsr w1, w2, #6 + /* Write the IBRD */ + str w1, [x0, #UARTIBRD] + /* FBRD = Divisor & 0x3F */ + and w1, w2, #0x3f + /* Write the FBRD */ + str w1, [x0, #UARTFBRD] + mov w1, #PL011_LINE_CONTROL + str w1, [x0, #UARTLCR_H] + /* Clear any pending errors */ + str wzr, [x0, #UARTECR] + /* Enable tx, rx, and uart overall */ + mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) + str w1, [x0, #UARTCR] +#endif + mov w0, #1 + ret +core_init_fail: + mov w0, wzr + ret +endfunc console_pl011_core_init + + .globl console_pl011_register + + /* ----------------------------------------------- + * int console_pl011_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new PL011 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_pl011_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_pl011_core_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register pl011 putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_pl011_register + + /* -------------------------------------------------------- + * int console_pl011_core_putc(int c, uintptr_t base_addr) + * 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 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_pl011_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f +1: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #UARTFR] + tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b + mov w2, #0xD + str w2, [x1, #UARTDR] +2: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #UARTFR] + tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b + str w0, [x1, #UARTDR] + ret +endfunc console_pl011_core_putc + + /* -------------------------------------------------------- + * int console_pl011_putc(int c, console_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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_pl011_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_BASE] + b console_pl011_core_putc +endfunc console_pl011_putc + + /* --------------------------------------------- + * int console_pl011_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - console base address + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_pl011_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ + ldr w1, [x0, #UARTFR] + tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char + ldr w1, [x0, #UARTDR] + mov w0, w1 + ret +no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_pl011_core_getc + + /* --------------------------------------------- + * int console_pl011_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - pointer to console_t structure + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_pl011_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_pl011_core_getc +endfunc console_pl011_getc + + /* --------------------------------------------- + * void console_pl011_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_pl011_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ +1: + /* Loop until the transmit FIFO is empty */ + ldr w1, [x0, #UARTFR] + tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b + ret +endfunc console_pl011_core_flush + + /* --------------------------------------------- + * void console_pl011_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : void + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_pl011_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_pl011_core_flush +endfunc console_pl011_flush diff --git a/arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c b/arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c new file mode 100644 index 0000000..97013e8 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * ARM PL061 GPIO Driver. + * Reference to ARM DDI 0190B document. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#if !PLAT_PL061_MAX_GPIOS +# define PLAT_PL061_MAX_GPIOS 32 +#endif /* PLAT_PL061_MAX_GPIOS */ + +CASSERT(PLAT_PL061_MAX_GPIOS > 0, assert_plat_pl061_max_gpios); + +#define MAX_GPIO_DEVICES ((PLAT_PL061_MAX_GPIOS + \ + (GPIOS_PER_PL061 - 1)) / GPIOS_PER_PL061) + +#define PL061_GPIO_DIR 0x400 + +#define GPIOS_PER_PL061 8 + +static int pl061_get_direction(int gpio); +static void pl061_set_direction(int gpio, int direction); +static int pl061_get_value(int gpio); +static void pl061_set_value(int gpio, int value); + +static uintptr_t pl061_reg_base[MAX_GPIO_DEVICES]; + +static const gpio_ops_t pl061_gpio_ops = { + .get_direction = pl061_get_direction, + .set_direction = pl061_set_direction, + .get_value = pl061_get_value, + .set_value = pl061_set_value, +}; + +static int pl061_get_direction(int gpio) +{ + uintptr_t base_addr; + unsigned int data, offset; + + assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS)); + + base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061]; + offset = gpio % GPIOS_PER_PL061; + data = mmio_read_8(base_addr + PL061_GPIO_DIR); + if (data & BIT(offset)) + return GPIO_DIR_OUT; + return GPIO_DIR_IN; +} + +static void pl061_set_direction(int gpio, int direction) +{ + uintptr_t base_addr; + unsigned int data, offset; + + assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS)); + + base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061]; + offset = gpio % GPIOS_PER_PL061; + if (direction == GPIO_DIR_OUT) { + data = mmio_read_8(base_addr + PL061_GPIO_DIR) | BIT(offset); + mmio_write_8(base_addr + PL061_GPIO_DIR, data); + } else { + data = mmio_read_8(base_addr + PL061_GPIO_DIR) & ~BIT(offset); + mmio_write_8(base_addr + PL061_GPIO_DIR, data); + } +} + +/* + * The offset of GPIODATA register is 0. + * The values read from GPIODATA are determined for each bit, by the mask bit + * derived from the address used to access the data register, PADDR[9:2]. + * Bits that are 1 in the address mask cause the corresponding bits in GPIODATA + * to be read, and bits that are 0 in the address mask cause the corresponding + * bits in GPIODATA to be read as 0, regardless of their value. + */ +static int pl061_get_value(int gpio) +{ + uintptr_t base_addr; + unsigned int offset; + + assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS)); + + base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061]; + offset = gpio % GPIOS_PER_PL061; + if (mmio_read_8(base_addr + BIT(offset + 2))) + return GPIO_LEVEL_HIGH; + return GPIO_LEVEL_LOW; +} + +/* + * In order to write GPIODATA, the corresponding bits in the mask, resulting + * from the address bus, PADDR[9:2], must be HIGH. Otherwise the bit values + * remain unchanged by the write. + */ +static void pl061_set_value(int gpio, int value) +{ + uintptr_t base_addr; + int offset; + + assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS)); + + base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061]; + offset = gpio % GPIOS_PER_PL061; + if (value == GPIO_LEVEL_HIGH) + mmio_write_8(base_addr + BIT(offset + 2), BIT(offset)); + else + mmio_write_8(base_addr + BIT(offset + 2), 0); +} + + +/* + * Register the PL061 GPIO controller with a base address and the offset + * of start pin in this GPIO controller. + * This function is called after pl061_gpio_ops_init(). + */ +void pl061_gpio_register(uintptr_t base_addr, int gpio_dev) +{ + assert((gpio_dev >= 0) && (gpio_dev < MAX_GPIO_DEVICES)); + + pl061_reg_base[gpio_dev] = base_addr; +} + +/* + * Initialize PL061 GPIO controller with the total GPIO numbers in SoC. + */ +void pl061_gpio_init(void) +{ + gpio_init(&pl061_gpio_ops); +} diff --git a/arm-trusted-firmware/drivers/arm/sbsa/sbsa.c b/arm-trusted-firmware/drivers/arm/sbsa/sbsa.c new file mode 100644 index 0000000..79c6f26 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/sbsa/sbsa.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +void sbsa_watchdog_offset_reg_write(uintptr_t base, uint64_t value) +{ + assert((value >> SBSA_WDOG_WOR_WIDTH) == 0); + mmio_write_32(base + SBSA_WDOG_WOR_LOW_OFFSET, + ((uint32_t)value & UINT32_MAX)); + mmio_write_32(base + SBSA_WDOG_WOR_HIGH_OFFSET, (uint32_t)(value >> 32)); +} + +/* + * Start the watchdog timer at base address "base" for a + * period of "ms" milliseconds.The watchdog has to be + * refreshed within this time period. + */ +void sbsa_wdog_start(uintptr_t base, uint64_t ms) +{ + uint64_t counter_freq; + uint64_t offset_reg_value; + + counter_freq = (uint64_t)plat_get_syscnt_freq2(); + offset_reg_value = ms * counter_freq / 1000; + + sbsa_watchdog_offset_reg_write(base, offset_reg_value); + mmio_write_32(base + SBSA_WDOG_WCS_OFFSET, SBSA_WDOG_WCS_EN); +} + +/* Stop the watchdog */ +void sbsa_wdog_stop(uintptr_t base) +{ + mmio_write_32(base + SBSA_WDOG_WCS_OFFSET, (0x0)); +} diff --git a/arm-trusted-firmware/drivers/arm/scu/scu.c b/arm-trusted-firmware/drivers/arm/scu/scu.c new file mode 100644 index 0000000..aceac92 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/scu/scu.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/******************************************************************************* + * Turn ON snoop control unit. This is needed to synchronize the data between + * CPU's. + ******************************************************************************/ +void enable_snoop_ctrl_unit(uintptr_t base) +{ + uint32_t scu_ctrl; + + INFO("[SCU]: enabling snoop control unit ... \n"); + + assert(base != 0U); + scu_ctrl = mmio_read_32(base + SCU_CTRL_REG); + + /* already enabled? */ + if ((scu_ctrl & SCU_ENABLE_BIT) != 0) { + return; + } + + scu_ctrl |= SCU_ENABLE_BIT; + mmio_write_32(base + SCU_CTRL_REG, scu_ctrl); +} + +/******************************************************************************* + * Snoop Control Unit configuration register. This is read-only register and + * contains information such as + * - number of CPUs present + * - is a particular CPU operating in SMP mode or AMP mode + * - data cache size of a particular CPU + * - does SCU has ACP port + * - is L2CPRESENT + * NOTE: user of this API should interpert the bits in this register according + * to the TRM + ******************************************************************************/ +uint32_t read_snoop_ctrl_unit_cfg(uintptr_t base) +{ + assert(base != 0U); + + return mmio_read_32(base + SCU_CFG_REG); +} diff --git a/arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c b/arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c new file mode 100644 index 0000000..a082a81 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* SMMU poll number of retries */ +#define SMMU_POLL_TIMEOUT_US U(1000) + +static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask, + uint32_t value) +{ + uint32_t reg_val; + uint64_t timeout; + + /* Set 1ms timeout value */ + timeout = timeout_init_us(SMMU_POLL_TIMEOUT_US); + do { + reg_val = mmio_read_32(smmu_reg); + if ((reg_val & mask) == value) + return 0; + } while (!timeout_elapsed(timeout)); + + ERROR("Timeout polling SMMUv3 register @%p\n", (void *)smmu_reg); + ERROR("Read value 0x%x, expected 0x%x\n", reg_val, + value == 0U ? reg_val & ~mask : reg_val | mask); + return -1; +} + +/* + * Abort all incoming transactions in order to implement a default + * deny policy on reset. + */ +int __init smmuv3_security_init(uintptr_t smmu_base) +{ + /* Attribute update has completed when SMMU_(S)_GBPA.Update bit is 0 */ + if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U) + return -1; + + /* + * SMMU_(S)_CR0 resets to zero with all streams bypassing the SMMU, + * so just abort all incoming transactions. + */ + mmio_setbits_32(smmu_base + SMMU_GBPA, + SMMU_GBPA_UPDATE | SMMU_GBPA_ABORT); + + if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U) + return -1; + + /* Check if the SMMU supports secure state */ + if ((mmio_read_32(smmu_base + SMMU_S_IDR1) & + SMMU_S_IDR1_SECURE_IMPL) == 0U) + return 0; + + /* Abort all incoming secure transactions */ + if (smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U) != 0U) + return -1; + + mmio_setbits_32(smmu_base + SMMU_S_GBPA, + SMMU_S_GBPA_UPDATE | SMMU_S_GBPA_ABORT); + + return smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U); +} + +/* + * Initialize the SMMU by invalidating all secure caches and TLBs. + * Abort all incoming transactions in order to implement a default + * deny policy on reset + */ +int __init smmuv3_init(uintptr_t smmu_base) +{ + /* Abort all incoming transactions */ + if (smmuv3_security_init(smmu_base) != 0) + return -1; + + /* Check if the SMMU supports secure state */ + if ((mmio_read_32(smmu_base + SMMU_S_IDR1) & + SMMU_S_IDR1_SECURE_IMPL) == 0U) + return 0; + /* + * Initiate invalidation of secure caches and TLBs if the SMMU + * supports secure state. If not, it's implementation defined + * as to how SMMU_S_INIT register is accessed. + */ + mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL); + + /* Wait for global invalidation operation to finish */ + return smmuv3_poll(smmu_base + SMMU_S_INIT, + SMMU_S_INIT_INV_ALL, 0U); +} diff --git a/arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c b/arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c new file mode 100644 index 0000000..9c5e762 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +uintptr_t sp804_base_addr; + +#define SP804_TIMER1_LOAD (sp804_base_addr + 0x000) +#define SP804_TIMER1_VALUE (sp804_base_addr + 0x004) +#define SP804_TIMER1_CONTROL (sp804_base_addr + 0x008) +#define SP804_TIMER1_BGLOAD (sp804_base_addr + 0x018) + +#define TIMER_CTRL_ONESHOT (1 << 0) +#define TIMER_CTRL_32BIT (1 << 1) +#define TIMER_CTRL_DIV1 (0 << 2) +#define TIMER_CTRL_DIV16 (1 << 2) +#define TIMER_CTRL_DIV256 (2 << 2) +#define TIMER_CTRL_IE (1 << 5) +#define TIMER_CTRL_PERIODIC (1 << 6) +#define TIMER_CTRL_ENABLE (1 << 7) + +/******************************************************************** + * The SP804 timer delay function + ********************************************************************/ +uint32_t sp804_get_timer_value(void) +{ + return mmio_read_32(SP804_TIMER1_VALUE); +} + +/******************************************************************** + * Initialize the 1st timer in the SP804 dual timer with a base + * address and a timer ops + ********************************************************************/ +void sp804_timer_ops_init(uintptr_t base_addr, const timer_ops_t *ops) +{ + assert(base_addr != 0); + assert(ops != 0 && ops->get_timer_value == sp804_get_timer_value); + + sp804_base_addr = base_addr; + timer_init(ops); + + /* disable timer1 */ + mmio_write_32(SP804_TIMER1_CONTROL, 0); + mmio_write_32(SP804_TIMER1_LOAD, UINT32_MAX); + mmio_write_32(SP804_TIMER1_VALUE, UINT32_MAX); + + /* enable as a free running 32-bit counter */ + mmio_write_32(SP804_TIMER1_CONTROL, + TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE); +} diff --git a/arm-trusted-firmware/drivers/arm/sp805/sp805.c b/arm-trusted-firmware/drivers/arm/sp805/sp805.c new file mode 100644 index 0000000..ffca1ce --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/sp805/sp805.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* Inline register access functions */ + +static inline void sp805_write_wdog_load(uintptr_t base, uint32_t value) +{ + mmio_write_32(base + SP805_WDOG_LOAD_OFF, value); +} + +static inline void sp805_write_wdog_ctrl(uintptr_t base, uint32_t value) +{ + mmio_write_32(base + SP805_WDOG_CTR_OFF, value); +} + +static inline void sp805_write_wdog_lock(uintptr_t base, uint32_t value) +{ + mmio_write_32(base + SP805_WDOG_LOCK_OFF, value); +} + + +/* Public API implementation */ + +void sp805_start(uintptr_t base, unsigned int ticks) +{ + sp805_write_wdog_load(base, ticks); + sp805_write_wdog_ctrl(base, SP805_CTR_RESEN | SP805_CTR_INTEN); + /* Lock registers access */ + sp805_write_wdog_lock(base, 0U); +} + +void sp805_stop(uintptr_t base) +{ + sp805_write_wdog_lock(base, WDOG_UNLOCK_KEY); + sp805_write_wdog_ctrl(base, 0U); +} + +void sp805_refresh(uintptr_t base, unsigned int ticks) +{ + sp805_write_wdog_lock(base, WDOG_UNLOCK_KEY); + sp805_write_wdog_load(base, ticks); + sp805_write_wdog_lock(base, 0U); +} diff --git a/arm-trusted-firmware/drivers/arm/tzc/tzc380.c b/arm-trusted-firmware/drivers/arm/tzc/tzc380.c new file mode 100644 index 0000000..9518748 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc380.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +struct tzc380_instance { + uintptr_t base; + uint8_t addr_width; + uint8_t num_regions; +}; + +struct tzc380_instance tzc380; + +static unsigned int tzc380_read_build_config(uintptr_t base) +{ + return mmio_read_32(base + TZC380_CONFIGURATION_OFF); +} + +static void tzc380_write_action(uintptr_t base, unsigned int action) +{ + mmio_write_32(base + ACTION_OFF, action); +} + +static void tzc380_write_region_base_low(uintptr_t base, unsigned int region, + unsigned int val) +{ + mmio_write_32(base + REGION_SETUP_LOW_OFF(region), val); +} + +static void tzc380_write_region_base_high(uintptr_t base, unsigned int region, + unsigned int val) +{ + mmio_write_32(base + REGION_SETUP_HIGH_OFF(region), val); +} + +static void tzc380_write_region_attributes(uintptr_t base, unsigned int region, + unsigned int val) +{ + mmio_write_32(base + REGION_ATTRIBUTES_OFF(region), val); +} + +void tzc380_init(uintptr_t base) +{ + unsigned int tzc_build; + + assert(base != 0U); + tzc380.base = base; + + /* Save values we will use later. */ + tzc_build = tzc380_read_build_config(tzc380.base); + tzc380.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & + BUILD_CONFIG_AW_MASK) + 1; + tzc380.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & + BUILD_CONFIG_NR_MASK) + 1; +} + +static uint32_t addr_low(uintptr_t addr) +{ + return (uint32_t)addr; +} + +static uint32_t addr_high(uintptr_t addr __unused) +{ +#if (UINTPTR_MAX == UINT64_MAX) + return addr >> 32; +#else + return 0; +#endif +} + +/* + * `tzc380_configure_region` is used to program regions into the TrustZone + * controller. + */ +void tzc380_configure_region(uint8_t region, uintptr_t region_base, unsigned int attr) +{ + assert(tzc380.base != 0U); + + assert(region < tzc380.num_regions); + + tzc380_write_region_base_low(tzc380.base, region, addr_low(region_base)); + tzc380_write_region_base_high(tzc380.base, region, addr_high(region_base)); + tzc380_write_region_attributes(tzc380.base, region, attr); +} + +void tzc380_set_action(unsigned int action) +{ + assert(tzc380.base != 0U); + + /* + * - Currently no handler is provided to trap an error via interrupt + * or exception. + * - The interrupt action has not been tested. + */ + tzc380_write_action(tzc380.base, action); +} diff --git a/arm-trusted-firmware/drivers/arm/tzc/tzc400.c b/arm-trusted-firmware/drivers/arm/tzc/tzc400.c new file mode 100644 index 0000000..759824d --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc400.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2016-2022, 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_UPDATE_FILTERS(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_update_filters(unsigned int region, unsigned int filters) +{ + /* Do range checks on filters and regions. */ + assert(((filters >> tzc400.num_filters) == 0U) && + (region < tzc400.num_regions)); + + _tzc400_update_filters(tzc400.base, region, tzc400.num_filters, filters); +} + +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) { + /* Filter 0 is special and cannot be disabled. + * So here we allow it being already enabled. */ + if (filter == 0U) { + continue; + } + /* + * 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 %u Gatekeeper already enabled.\n", + filter); + panic(); + } + _tzc400_set_gate_keeper(tzc400.base, filter, 1); + } +} + +void tzc400_disable_filters(void) +{ + unsigned int filter; + unsigned int state; + unsigned int start = 0U; + + assert(tzc400.base != 0U); + + /* Filter 0 is special and cannot be disabled. */ + state = _tzc400_get_gate_keeper(tzc400.base, 0); + if (state != 0U) { + start++; + } + for (filter = start; 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/arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h b/arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h new file mode 100644 index 0000000..2090944 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2016-2021, 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 modify the filters status for a defined region. + */ +#define DEFINE_TZC_COMMON_UPDATE_FILTERS(fn_name, macro_name) \ + static inline void _tzc##fn_name##_update_filters( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned int nbfilters, \ + unsigned int filters) \ + { \ + uint32_t filters_mask = GENMASK(nbfilters - 1U, 0); \ + \ + mmio_clrsetbits_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + region_no) + \ + TZC_##macro_name##_REGION_ATTR_0_OFFSET, \ + filters_mask << TZC_REGION_ATTR_F_EN_SHIFT, \ + filters << TZC_REGION_ATTR_F_EN_SHIFT); \ + } + +/* + * 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/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c b/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c new file mode 100644 index 0000000..e45fbf8 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include "tzc_common_private.h" + +/* + * Macros which will be used by common core functions. + */ +#define TZC_DMC500_REGION_BASE_LOW_0_OFFSET 0x054 +#define TZC_DMC500_REGION_BASE_HIGH_0_OFFSET 0x058 +#define TZC_DMC500_REGION_TOP_LOW_0_OFFSET 0x05C +#define TZC_DMC500_REGION_TOP_HIGH_0_OFFSET 0x060 +#define TZC_DMC500_REGION_ATTR_0_OFFSET 0x064 +#define TZC_DMC500_REGION_ID_ACCESS_0_OFFSET 0x068 + +#define TZC_DMC500_ACTION_OFF 0x50 + +/* Pointer to the tzc_dmc500_driver_data structure populated by the platform */ +static const tzc_dmc500_driver_data_t *g_driver_data; +static unsigned int g_sys_if_count; + +#define verify_region_attr(region, attr) \ + ((g_conf_regions[(region)].sec_attr == \ + ((attr) >> TZC_REGION_ATTR_SEC_SHIFT)) \ + && ((attr) & (0x1 << TZC_REGION_ATTR_F_EN_SHIFT))) + +/* + * Structure for configured regions attributes in DMC500. + */ +typedef struct tzc_dmc500_regions { + unsigned int sec_attr; + int is_enabled; +} tzc_dmc500_regions_t; + +/* + * Array storing the attributes of the configured regions. This array + * will be used by the `tzc_dmc500_verify_complete` to verify the flush + * completion. + */ +static tzc_dmc500_regions_t g_conf_regions[MAX_REGION_VAL + 1]; + +/* Helper Macros for making the code readable */ +#define DMC_INST_BASE_ADDR(instance) (g_driver_data->dmc_base[instance]) +#define DMC_INST_SI_BASE(instance, interface) \ + (DMC_INST_BASE_ADDR(instance) + IFACE_OFFSET(interface)) + +DEFINE_TZC_COMMON_WRITE_ACTION(_dmc500, DMC500) +DEFINE_TZC_COMMON_WRITE_REGION_BASE(_dmc500, DMC500) +DEFINE_TZC_COMMON_WRITE_REGION_TOP(_dmc500, DMC500) +DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(_dmc500, DMC500) +DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(_dmc500, DMC500) + +DEFINE_TZC_COMMON_CONFIGURE_REGION0(_dmc500) +DEFINE_TZC_COMMON_CONFIGURE_REGION(_dmc500) + +static inline unsigned int _tzc_dmc500_read_region_attr_0( + uintptr_t dmc_si_base, + unsigned int region_no) +{ + return mmio_read_32(dmc_si_base + + TZC_REGION_OFFSET(TZC_DMC500_REGION_SIZE, region_no) + + TZC_DMC500_REGION_ATTR_0_OFFSET); +} + +static inline void _tzc_dmc500_write_flush_control(uintptr_t dmc_si_base) +{ + mmio_write_32(dmc_si_base + SI_FLUSH_CTRL_OFFSET, 1); +} + +/* + * Sets the Flush controls for all the DMC Instances and System Interfaces. + * This initiates the flush of configuration settings from the shadow + * registers to the actual configuration register. The caller should poll + * changed register to confirm update. + */ +void tzc_dmc500_config_complete(void) +{ + int dmc_inst, sys_if; + + assert(g_driver_data); + + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + for (sys_if = 0; sys_if < g_sys_if_count; sys_if++) + _tzc_dmc500_write_flush_control( + DMC_INST_SI_BASE(dmc_inst, sys_if)); + } +} + +/* + * This function reads back the secure attributes from the configuration + * register for each DMC Instance and System Interface and compares it with + * the configured value. The successful verification of the region attributes + * confirms that the flush operation has completed. + * If the verification fails, the caller is expected to invoke this API again + * till it succeeds. + * Returns 0 on success and 1 on failure. + */ +int tzc_dmc500_verify_complete(void) +{ + int dmc_inst, sys_if, region_no; + unsigned int attr; + + assert(g_driver_data); + /* Region 0 must be configured */ + assert(g_conf_regions[0].is_enabled); + + /* Iterate over all configured regions */ + for (region_no = 0; region_no <= MAX_REGION_VAL; region_no++) { + if (!g_conf_regions[region_no].is_enabled) + continue; + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; + dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + for (sys_if = 0; sys_if < g_sys_if_count; + sys_if++) { + attr = _tzc_dmc500_read_region_attr_0( + DMC_INST_SI_BASE(dmc_inst, sys_if), + region_no); + VERBOSE("Verifying DMC500 region:%d" + " dmc_inst:%d sys_if:%d attr:%x\n", + region_no, dmc_inst, sys_if, attr); + if (!verify_region_attr(region_no, attr)) + return 1; + } + } + } + + return 0; +} + +/* + * `tzc_dmc500_configure_region0` is used to program region 0 in both the + * system interfaces of all the DMC-500 instances. Region 0 covers the whole + * address space that is not mapped to any other region for a system interface, + * and is always enabled; this cannot be changed. This function only changes + * the access permissions. + */ +void tzc_dmc500_configure_region0(unsigned int sec_attr, + unsigned int nsaid_permissions) +{ + int dmc_inst, sys_if; + + /* Assert if DMC-500 is not initialized */ + assert(g_driver_data); + + /* Configure region_0 in all DMC instances */ + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + for (sys_if = 0; sys_if < g_sys_if_count; sys_if++) + _tzc_dmc500_configure_region0( + DMC_INST_SI_BASE(dmc_inst, sys_if), + sec_attr, nsaid_permissions); + } + + g_conf_regions[0].sec_attr = sec_attr; + g_conf_regions[0].is_enabled = 1; +} + +/* + * `tzc_dmc500_configure_region` is used to program a region into all system + * interfaces of all the DMC instances. + * NOTE: + * Region 0 is special; it is preferable to use tzc_dmc500_configure_region0 + * for this region (see comment for that function). + */ +void tzc_dmc500_configure_region(unsigned int region_no, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int nsaid_permissions) +{ + int dmc_inst, sys_if; + + assert(g_driver_data); + /* Do range checks on regions. */ + assert((region_no >= 0U) && (region_no <= MAX_REGION_VAL)); + + /* + * Do address range check based on DMC-TZ configuration. A 43bit address + * is the max and expected case. + */ + assert(((region_top <= (UINT64_MAX >> (64U - 43U))) && + (region_base < region_top))); + + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); + + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + for (sys_if = 0; sys_if < g_sys_if_count; sys_if++) + _tzc_dmc500_configure_region( + DMC_INST_SI_BASE(dmc_inst, sys_if), + TZC_DMC500_REGION_ATTR_F_EN_MASK, + region_no, region_base, region_top, + sec_attr, nsaid_permissions); + } + + g_conf_regions[region_no].sec_attr = sec_attr; + g_conf_regions[region_no].is_enabled = 1; +} + +/* Sets the action value for all the DMC instances */ +void tzc_dmc500_set_action(unsigned int action) +{ + int dmc_inst; + + assert(g_driver_data); + + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + /* + * - Currently no handler is provided to trap an error via + * interrupt or exception. + * - The interrupt action has not been tested. + */ + _tzc_dmc500_write_action(DMC_INST_BASE_ADDR(dmc_inst), action); + } +} + +/* + * A DMC-500 instance must be present at each base address provided by the + * platform. It also expects platform to pass at least one instance of + * DMC-500. + */ +static void validate_plat_driver_data( + const tzc_dmc500_driver_data_t *plat_driver_data) +{ +#if ENABLE_ASSERTIONS + int i; + unsigned int dmc_id; + uintptr_t dmc_base; + + assert(plat_driver_data); + assert(plat_driver_data->dmc_count > 0 && + (plat_driver_data->dmc_count <= MAX_DMC_COUNT)); + + for (i = 0; i < plat_driver_data->dmc_count; i++) { + dmc_base = plat_driver_data->dmc_base[i]; + assert(dmc_base); + + dmc_id = _tzc_read_peripheral_id(dmc_base); + assert(dmc_id == DMC500_PERIPHERAL_ID); + } +#endif /* ENABLE_ASSERTIONS */ +} + + +/* + * Initializes the base address and count of DMC instances. + * + * Note : Only pointer to plat_driver_data is saved, so it is caller's + * responsibility to keep it valid until the driver is used. + */ +void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data) +{ + /* Check valid pointer is passed */ + assert(plat_driver_data); + + /* + * NOTE: This driver expects the DMC-500 controller is already in + * READY state. Hence, it uses the reconfiguration method for + * programming TrustZone regions + */ + /* Validates the information passed by platform */ + validate_plat_driver_data(plat_driver_data); + g_driver_data = plat_driver_data; + + /* Check valid system interface count */ + assert(g_driver_data->sys_if_count <= MAX_SYS_IF_COUNT); + + g_sys_if_count = g_driver_data->sys_if_count; + + /* If interface count is not present then assume max */ + if (g_sys_if_count == 0U) + g_sys_if_count = MAX_SYS_IF_COUNT; +} diff --git a/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c b/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c new file mode 100644 index 0000000..7e307ee --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/* Mask to extract bit 31 to 16 */ +#define MASK_31_16 UINT64_C(0x0000ffff0000) +/* Mask to extract bit 47 to 32 */ +#define MASK_47_32 UINT64_C(0xffff00000000) + +/* Helper macro for getting dmc_base addr of a dmc_inst */ +#define DMC_BASE(plat_data, dmc_inst) \ + ((uintptr_t)((plat_data)->dmc_base[(dmc_inst)])) + +/* Pointer to the tzc_dmc620_config_data structure populated by the platform */ +static const tzc_dmc620_config_data_t *g_plat_config_data; + +#if ENABLE_ASSERTIONS +/* + * Helper function to check if the DMC-620 instance is present at the + * base address provided by the platform and also check if at least + * one dmc instance is present. + */ +static void tzc_dmc620_validate_plat_driver_data( + const tzc_dmc620_driver_data_t *plat_driver_data) +{ + unsigned int dmc_inst, dmc_count, dmc_id; + uintptr_t base; + + assert(plat_driver_data != NULL); + + dmc_count = plat_driver_data->dmc_count; + assert(dmc_count > 0U); + + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + base = DMC_BASE(plat_driver_data, dmc_inst); + dmc_id = mmio_read_32(base + DMC620_PERIPHERAL_ID_0); + assert(dmc_id == DMC620_PERIPHERAL_ID_0_VALUE); + } +} +#endif + +/* + * Program a region with region base and region top addresses of all + * DMC-620 instances. + */ +static void tzc_dmc620_configure_region(int region_no, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr) +{ + uint32_t min_31_00, min_47_32; + uint32_t max_31_00, max_47_32; + unsigned int dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + assert(plat_driver_data != NULL); + + /* Do range checks on regions. */ + assert((region_no >= 0) && (region_no <= DMC620_ACC_ADDR_COUNT)); + + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); + + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + min_31_00 = (uint32_t)((region_base & MASK_31_16) | sec_attr); + min_47_32 = (uint32_t)((region_base & MASK_47_32) + >> DMC620_ACC_ADDR_WIDTH); + max_31_00 = (uint32_t)(region_top & MASK_31_16); + max_47_32 = (uint32_t)((region_top & MASK_47_32) + >> DMC620_ACC_ADDR_WIDTH); + + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + /* Configure access address region registers */ + mmio_write_32(base + DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no), + min_31_00); + mmio_write_32(base + DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no), + min_47_32); + mmio_write_32(base + DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no), + max_31_00); + mmio_write_32(base + DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no), + max_47_32); + } +} + +/* + * Set the action value for all the DMC-620 instances. + */ +static void tzc_dmc620_set_action(void) +{ + unsigned int dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + /* Switch to READY */ + mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_GO); + mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_EXECUTE); + } +} + +/* + * Verify whether the DMC-620 configuration is complete by reading back + * configuration registers and comparing it with the configured value. If + * configuration is incomplete, loop till the configured value is reflected in + * the register. + */ +static void tzc_dmc620_verify_complete(void) +{ + unsigned int dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + while ((mmio_read_32(base + DMC620_MEMC_STATUS) & + DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) { + continue; + } + } +} + +/* + * Initialize the DMC-620 TrustZone Controller using the region configuration + * supplied by the platform. The DMC620 controller should be enabled elsewhere + * before invoking this function. + */ +void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data) +{ + uint8_t i; + + /* Check if valid pointer is passed */ + assert(plat_config_data != NULL); + + /* + * Check if access address count passed by the platform is less than or + * equal to DMC620's access address count + */ + assert(plat_config_data->acc_addr_count <= DMC620_ACC_ADDR_COUNT); + +#if ENABLE_ASSERTIONS + /* Validates the information passed by platform */ + tzc_dmc620_validate_plat_driver_data(plat_config_data->plat_drv_data); +#endif + + g_plat_config_data = plat_config_data; + + INFO("Configuring DMC-620 TZC settings\n"); + for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) { + tzc_dmc620_configure_region(i, + g_plat_config_data->plat_acc_addr_data[i].region_base, + g_plat_config_data->plat_acc_addr_data[i].region_top, + g_plat_config_data->plat_acc_addr_data[i].sec_attr); + } + + tzc_dmc620_set_action(); + tzc_dmc620_verify_complete(); + INFO("DMC-620 TZC setup completed\n"); +} diff --git a/arm-trusted-firmware/drivers/auth/auth_mod.c b/arm-trusted-firmware/drivers/auth/auth_mod.c new file mode 100644 index 0000000..a99a2c7 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/auth_mod.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2015-2022, 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 + +/* ASN.1 tags */ +#define ASN1_INTEGER 0x02 + +#define return_if_error(rc) \ + do { \ + if (rc != 0) { \ + return rc; \ + } \ + } while (0) + +#pragma weak plat_set_nv_ctr2 + + +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 by matching the data hash + * + * This function implements 'AUTH_METHOD_HASH'. To authenticate an image using + * this method, the image must contain: + * + * - The data to calculate the hash from + * + * The parent image must contain: + * + * - The hash to be matched with (including hash algorithm) + * + * For a successful authentication, both hashes must match. The function calls + * the crypto-module to check this matching. + * + * Parameters: + * param: parameters to perform the hash authentication + * img_desc: pointer to image descriptor so we can know the image type + * and parent image + * img: pointer to image in memory + * img_len: length of image (in bytes) + * + * Return: + * 0 = success, Otherwise = error + */ +static int auth_hash(const auth_method_param_hash_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len) +{ + void *data_ptr, *hash_der_ptr; + unsigned int data_len, hash_der_len; + int rc = 0; + + /* Get the hash from the parent image. This hash will be DER encoded + * and contain the hash algorithm */ + rc = auth_get_param(param->hash, img_desc->parent, + &hash_der_ptr, &hash_der_len); + return_if_error(rc); + + /* Get the data to be hashed 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 the crypto module to verify this hash */ + rc = crypto_mod_verify_hash(data_ptr, data_len, + hash_der_ptr, hash_der_len); + + return rc; +} + +/* + * Authenticate by digital signature + * + * This function implements 'AUTH_METHOD_SIG'. To authenticate an image using + * this method, the image must contain: + * + * - Data to be signed + * - Signature + * - Signature algorithm + * + * We rely on the image parser module to extract this data from the image. + * The parent image must contain: + * + * - Public key (or a hash of it) + * + * If the parent image contains only a hash of the key, we will try to obtain + * the public key from the image itself (i.e. self-signed certificates). In that + * case, the signature verification is considered just an integrity check and + * the authentication is established by calculating the hash of the key and + * comparing it with the hash obtained from the parent. + * + * If the image has no parent (NULL), it means it has to be authenticated using + * the ROTPK stored in the platform. Again, this ROTPK could be the key itself + * or a hash of it. + * + * Return: 0 = success, Otherwise = error + */ +static int auth_signature(const auth_method_param_sig_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len) +{ + void *data_ptr, *pk_ptr, *pk_hash_ptr, *sig_ptr, *sig_alg_ptr; + unsigned int data_len, pk_len, pk_hash_len, sig_len, sig_alg_len; + unsigned int flags = 0; + int rc = 0; + + /* Get the data to be signed from 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); + + /* Get the signature from current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->sig, + img, img_len, &sig_ptr, &sig_len); + return_if_error(rc); + + /* Get the signature algorithm from current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->alg, + img, img_len, &sig_alg_ptr, &sig_alg_len); + return_if_error(rc); + + /* Get the public key from the parent. If there is no parent (NULL), + * the certificate has been signed with the ROTPK, so we have to get + * the PK from the platform */ + if (img_desc->parent) { + rc = auth_get_param(param->pk, img_desc->parent, + &pk_ptr, &pk_len); + } else { + rc = plat_get_rotpk_info(param->pk->cookie, &pk_ptr, &pk_len, + &flags); + } + return_if_error(rc); + + if (flags & (ROTPK_IS_HASH | ROTPK_NOT_DEPLOYED)) { + /* If the PK is a hash of the key or if the ROTPK is not + deployed on the platform, retrieve the key from the image */ + pk_hash_ptr = pk_ptr; + pk_hash_len = pk_len; + rc = img_parser_get_auth_param(img_desc->img_type, + param->pk, img, img_len, + &pk_ptr, &pk_len); + return_if_error(rc); + + /* Ask the crypto module to verify the signature */ + rc = crypto_mod_verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); + return_if_error(rc); + + if (flags & ROTPK_NOT_DEPLOYED) { + NOTICE("ROTPK is not deployed on platform. " + "Skipping ROTPK verification.\n"); + } else { + /* Ask the crypto-module to verify the key hash */ + rc = crypto_mod_verify_hash(pk_ptr, pk_len, + pk_hash_ptr, pk_hash_len); + } + } else { + /* Ask the crypto module to verify the signature */ + rc = crypto_mod_verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); + } + + return rc; +} + +/* + * Authenticate by Non-Volatile counter + * + * To protect the system against rollback, the platform includes a non-volatile + * counter whose value can only be increased. All certificates include a counter + * value that should not be lower than the value stored in the platform. If the + * value is larger, the counter in the platform must be updated to the new value + * (provided it has been authenticated). + * + * Return: 0 = success, Otherwise = error + * Returns additionally, + * cert_nv_ctr -> NV counter value present in the certificate + * need_nv_ctr_upgrade = 0 -> platform NV counter upgrade is not needed + * need_nv_ctr_upgrade = 1 -> platform NV counter upgrade is needed + */ +static int auth_nvctr(const auth_method_param_nv_ctr_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len, + unsigned int *cert_nv_ctr, + bool *need_nv_ctr_upgrade) +{ + char *p; + void *data_ptr = NULL; + unsigned int data_len, len, i; + unsigned int plat_nv_ctr; + int rc = 0; + bool is_trial_run = false; + + /* Get the counter value from current image. The AM expects the IPM + * to return the counter value as a DER encoded integer */ + rc = img_parser_get_auth_param(img_desc->img_type, param->cert_nv_ctr, + img, img_len, &data_ptr, &data_len); + return_if_error(rc); + + /* Parse the DER encoded integer */ + assert(data_ptr); + p = (char *)data_ptr; + if (*p != ASN1_INTEGER) { + /* Invalid ASN.1 integer */ + return 1; + } + p++; + + /* NV-counters are unsigned integers up to 32-bit */ + len = (unsigned int)(*p & 0x7f); + if ((*p & 0x80) || (len > 4)) { + return 1; + } + p++; + + /* Check the number is not negative */ + if (*p & 0x80) { + return 1; + } + + /* Convert to unsigned int. This code is for a little-endian CPU */ + *cert_nv_ctr = 0; + for (i = 0; i < len; i++) { + *cert_nv_ctr = (*cert_nv_ctr << 8) | *p++; + } + + /* Get the counter from the platform */ + rc = plat_get_nv_ctr(param->plat_nv_ctr->cookie, &plat_nv_ctr); + return_if_error(rc); + + if (*cert_nv_ctr < plat_nv_ctr) { + /* Invalid NV-counter */ + return 1; + } else if (*cert_nv_ctr > plat_nv_ctr) { +#if PSA_FWU_SUPPORT && IMAGE_BL2 + is_trial_run = fwu_is_trial_run_state(); +#endif /* PSA_FWU_SUPPORT && IMAGE_BL2 */ + *need_nv_ctr_upgrade = !is_trial_run; + } + + return 0; +} + +int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc __unused, + unsigned int nv_ctr) +{ + return plat_set_nv_ctr(cookie, nv_ctr); +} + +/* + * 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 = FCONF_GET_PROPERTY(tbbr, cot, 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); + + /* 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; + unsigned int cert_nv_ctr = 0; + bool need_nv_ctr_upgrade = false; + bool sig_auth_done = false; + const auth_method_param_nv_ctr_t *nv_ctr_param = NULL; + + /* Get the image descriptor from the chain of trust */ + img_desc = FCONF_GET_PROPERTY(tbbr, cot, 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_HASH: + rc = auth_hash(&auth_method->param.hash, + img_desc, img_ptr, img_len); + break; + case AUTH_METHOD_SIG: + rc = auth_signature(&auth_method->param.sig, + img_desc, img_ptr, img_len); + sig_auth_done = true; + break; + case AUTH_METHOD_NV_CTR: + nv_ctr_param = &auth_method->param.nv_ctr; + rc = auth_nvctr(nv_ctr_param, + img_desc, img_ptr, img_len, + &cert_nv_ctr, &need_nv_ctr_upgrade); + break; + default: + /* Unknown authentication method */ + rc = 1; + break; + } + return_if_error(rc); + } + + /* + * Do platform NV counter upgrade only if the certificate gets + * authenticated, and platform NV-counter upgrade is needed. + */ + if (need_nv_ctr_upgrade && sig_auth_done) { + rc = plat_set_nv_ctr2(nv_ctr_param->plat_nv_ctr->cookie, + img_desc, cert_nv_ctr); + 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/arm-trusted-firmware/drivers/auth/crypto_mod.c b/arm-trusted-firmware/drivers/auth/crypto_mod.c new file mode 100644 index 0000000..eada357 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/crypto_mod.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* Variable exported by the crypto library through REGISTER_CRYPTO_LIB() */ + +/* + * The crypto module is responsible for verifying digital signatures and hashes. + * It relies on a crypto library to perform the cryptographic operations. + * + * The crypto module itself does not impose any specific format on signatures, + * signature algorithm, keys or hashes, but most cryptographic libraries will + * take the parameters as the following DER encoded ASN.1 structures: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * SignatureAlgorithm ::= AlgorithmIdentifier + * + * SignatureValue ::= BIT STRING + */ + +/* + * Perform some static checking and call the library initialization function + */ +void crypto_mod_init(void) +{ + assert(crypto_lib_desc.name != NULL); + assert(crypto_lib_desc.init != NULL); +#if TRUSTED_BOARD_BOOT + assert(crypto_lib_desc.verify_signature != NULL); + assert(crypto_lib_desc.verify_hash != NULL); +#endif /* TRUSTED_BOARD_BOOT */ +#if MEASURED_BOOT + assert(crypto_lib_desc.calc_hash != NULL); +#endif /* MEASURED_BOOT */ + + /* Initialize the cryptographic library */ + crypto_lib_desc.init(); + INFO("Using crypto library '%s'\n", crypto_lib_desc.name); +} + +/* + * Function to verify a digital signature + * + * Parameters: + * + * data_ptr, data_len: signed data + * sig_ptr, sig_len: the digital signature + * sig_alg_ptr, sig_alg_len: the digital signature algorithm + * pk_ptr, pk_len: the public key + */ +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) +{ + assert(data_ptr != NULL); + assert(data_len != 0); + assert(sig_ptr != NULL); + assert(sig_len != 0); + assert(sig_alg_ptr != NULL); + assert(sig_alg_len != 0); + assert(pk_ptr != NULL); + assert(pk_len != 0); + + return crypto_lib_desc.verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); +} + +/* + * Verify a hash by comparison + * + * Parameters: + * + * data_ptr, data_len: data to be hashed + * digest_info_ptr, digest_info_len: hash to be compared + */ +int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + assert(data_ptr != NULL); + assert(data_len != 0); + assert(digest_info_ptr != NULL); + assert(digest_info_len != 0); + + return crypto_lib_desc.verify_hash(data_ptr, data_len, + digest_info_ptr, digest_info_len); +} + +#if MEASURED_BOOT +/* + * Calculate a hash + * + * Parameters: + * + * alg: message digest algorithm + * data_ptr, data_len: data to be hashed + * output: resulting hash + */ +int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, + unsigned int data_len, + unsigned char output[CRYPTO_MD_MAX_SIZE]) +{ + assert(data_ptr != NULL); + assert(data_len != 0); + assert(output != NULL); + + return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output); +} +#endif /* MEASURED_BOOT */ + +/* + * Authenticated decryption of data + * + * Parameters: + * + * dec_algo: authenticated decryption algorithm + * data_ptr, len: data to be decrypted (inout param) + * key, key_len, key_flags: symmetric decryption key + * iv, iv_len: initialization vector + * tag, tag_len: authentication tag + */ +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) +{ + assert(crypto_lib_desc.auth_decrypt != NULL); + assert(data_ptr != NULL); + assert(len != 0U); + assert(key != NULL); + assert(key_len != 0U); + assert(iv != NULL); + assert((iv_len != 0U) && (iv_len <= CRYPTO_MAX_IV_SIZE)); + assert(tag != NULL); + assert((tag_len != 0U) && (tag_len <= CRYPTO_MAX_TAG_SIZE)); + + return crypto_lib_desc.auth_decrypt(dec_algo, data_ptr, len, key, + key_len, key_flags, iv, iv_len, tag, + tag_len); +} diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c b/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c new file mode 100644 index 0000000..c7ee36f --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c @@ -0,0 +1,306 @@ +/* + * 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 +#include + +#include +#include + +#define LIB_NAME "CryptoCell 712 SBROM" +#define RSA_SALT_LEN 32 +#define RSA_EXPONENT 65537 + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm, + * maskGenAlgorithm [1] MaskGenAlgorithm, + * saltLength [2] INTEGER, + * trailerField [3] TrailerField DEFAULT trailerFieldBC + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + CCError_t ret; + uint32_t lcs; + + /* Initialize CC SBROM */ + ret = CC_BsvSbromInit((uintptr_t)PLAT_CRYPTOCELL_BASE); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvSbromInit() error %x\n", ret); + panic(); + } + + /* Initialize lifecycle state */ + ret = CC_BsvLcsGetAndInit((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvLcsGetAndInit() error %x\n", ret); + panic(); + } + + /* If the lifecyclestate is `SD`, then stop further execution */ + if (lcs == CC_BSV_SECURITY_DISABLED_LCS) { + ERROR("CryptoCell LCS is security-disabled\n"); + panic(); + } +} + +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static 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) +{ + CCError_t error; + CCSbNParams_t pk; + CCSbSignature_t signature; + int rc, exp; + mbedtls_asn1_buf sig_oid, alg_oid, params; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; + mbedtls_pk_rsassa_pss_options pss_opts; + size_t len; + uint8_t *p, *end; + /* Temp buf to store the public key modulo (N) in LE format */ + uint32_t RevN[SB_RSA_MOD_SIZE_IN_WORDS]; + + /* Verify the signature algorithm */ + /* Get pointers to signature OID and parameters */ + p = sig_alg; + end = p + sig_alg_len; + rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* Get the actual signature algorithm (MD + PK) */ + rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports RSASSA-PSS signature */ + if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the RSASSA-PSS params */ + /* The trailer field is verified to be 0xBC internally by this API */ + rc = mbedtls_x509_get_rsassa_pss_params(¶ms, &md_alg, + &pss_opts.mgf1_hash_id, + &pss_opts.expected_salt_len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports SHA256 as hash algorithm */ + if (md_alg != MBEDTLS_MD_SHA256 || pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_SIGNATURE; + + if (pss_opts.expected_salt_len != RSA_SALT_LEN) + return CRYPTO_ERR_SIGNATURE; + + /* Parse the public key */ + p = pk_ptr; + end = p + pk_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + end = p + len; + rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0) + return CRYPTO_ERR_SIGNATURE; + + if (pk_alg != MBEDTLS_PK_RSA) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (*p == 0) { + p++; len--; + } + if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * The CCSbVerifySignature() API expects N and Np in BE format and + * the signature in LE format. Copy N from certificate. + */ + memcpy(pk.N, p, RSA_MOD_SIZE_IN_BYTES); + + /* Verify the RSA exponent */ + p += len; + rc = mbedtls_asn1_get_int(&p, end, &exp); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (exp != RSA_EXPONENT) + return CRYPTO_ERR_SIGNATURE; + + /* + * Calculate the Np (Barrett n' value). The RSA_CalcNp() API expects + * N in LE format. Hence reverse N into a temporary buffer `RevN`. + */ + UTIL_ReverseMemCopy((uint8_t *)RevN, (uint8_t *)pk.N, sizeof(RevN)); + + RSA_CalcNp((uintptr_t)PLAT_CRYPTOCELL_BASE, RevN, pk.Np); + + /* Np is in LE format. Reverse it to BE */ + UTIL_ReverseBuff((uint8_t *)pk.Np, sizeof(pk.Np)); + + /* Get the signature (bitstring) */ + p = sig_ptr; + end = p + sig_len; + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * The signature is BE format. Convert it to LE before calling + * CCSbVerifySignature(). + */ + UTIL_ReverseMemCopy((uint8_t *)signature.sig, p, RSA_MOD_SIZE_IN_BYTES); + + /* + * CryptoCell utilises DMA internally to transfer data. Flush the data + * from caches. + */ + flush_dcache_range((uintptr_t)data_ptr, data_len); + + /* Verify the signature */ + error = CCSbVerifySignature((uintptr_t)PLAT_CRYPTOCELL_BASE, + (uint32_t *)data_ptr, &pk, &signature, + data_len, RSA_PSS); + if (error != CC_OK) + return CRYPTO_ERR_SIGNATURE; + + /* Signature verification success */ + return CRYPTO_SUCCESS; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + mbedtls_asn1_buf hash_oid, params; + mbedtls_md_type_t md_alg; + uint8_t *p, *end, *hash; + CCHashResult_t pubKeyHash; + size_t len; + int rc; + CCError_t error; + + /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ + p = digest_info_ptr; + end = p + digest_info_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Get the hash algorithm */ + rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_HASH; + + rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) + return CRYPTO_ERR_HASH; + /* Verify that hash algorithm is SHA256 */ + if (md_alg != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_HASH; + + /* Hash should be octet string type */ + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Length of hash must match the algorithm's size */ + if (len != HASH_RESULT_SIZE_IN_BYTES) + return CRYPTO_ERR_HASH; + + /* + * CryptoCell utilises DMA internally to transfer data. Flush the data + * from caches. + */ + flush_dcache_range((uintptr_t)data_ptr, data_len); + + hash = p; + error = SBROM_CryptoHash((uintptr_t)PLAT_CRYPTOCELL_BASE, + (uintptr_t)data_ptr, data_len, pubKeyHash); + if (error != CC_OK) + return CRYPTO_ERR_HASH; + + rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES); + if (rc != 0) + return CRYPTO_ERR_HASH; + + return CRYPTO_SUCCESS; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); + diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c b/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c new file mode 100644 index 0000000..53d77db --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +/* + * Return the ROTPK hash + * + * dst: buffer into which the ROTPK hash will be copied into + * len: length of the provided buffer, which must be at least enough for a + * SHA256 hash + * flags: a pointer to integer that will be set to indicate the ROTPK status + * + * Return: 0 = success, Otherwise = error + */ +int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, unsigned int *flags) +{ + CCError_t error; + uint32_t lcs; + + assert(dst != NULL); + assert(len >= HASH_RESULT_SIZE_IN_WORDS); + assert(flags != NULL); + + error = NVM_GetLCS(PLAT_CRYPTOCELL_BASE, &lcs); + if (error != CC_OK) + return 1; + + /* If the lifecycle state is `SD`, return failure */ + if (lcs == CC_BSV_SECURITY_DISABLED_LCS) + return 1; + + /* + * If the lifecycle state is `CM` or `DM`, ROTPK shouldn't be verified. + * Return success after setting ROTPK_NOT_DEPLOYED flag + */ + if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) || + (lcs == CC_BSV_DEVICE_MANUFACTURE_LCS)) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + /* Copy the DER header */ + error = NVM_ReadHASHPubKey(PLAT_CRYPTOCELL_BASE, + CC_SB_HASH_BOOT_KEY_256B, + (uint32_t *)dst, HASH_RESULT_SIZE_IN_WORDS); + if (error != CC_OK) + return 1; + + *flags = ROTPK_IS_HASH; + return 0; +} + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * specifies the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER1, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER2, nv_ctr); + } + + return (error != CC_OK); +} + +/* + * Store a new non-volatile counter value in the counter specified by the OID + * in the cookie. This function is not expected to be called if the Lifecycle + * state is RMA as the values in the certificate are expected to always match + * the nvcounter values. But if called when the LCS is RMA, the underlying + * helper functions will return success but without updating the counter. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER1, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER2, nv_ctr); + } + + return (error != CC_OK); +} + diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c b/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c new file mode 100644 index 0000000..077317e --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c @@ -0,0 +1,274 @@ +/* + * 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 + +#define LIB_NAME "CryptoCell 713 SBROM" +#define RSA_SALT_LEN 32 +#define RSA_EXPONENT 65537 + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm, + * maskGenAlgorithm [1] MaskGenAlgorithm, + * saltLength [2] INTEGER, + * trailerField [3] TrailerField DEFAULT trailerFieldBC + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + CCError_t ret; + uint32_t lcs; + + /* Initialize CC SBROM */ + ret = CC_BsvInit((uintptr_t)PLAT_CRYPTOCELL_BASE); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvInit() error %x\n", ret); + panic(); + } + + /* Initialize lifecycle state */ + ret = CC_BsvGetAndInitLcs((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvGetAndInitLcs() error %x\n", ret); + panic(); + } +} + +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static 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) +{ + CCError_t error; + CCBsvNBuff_t NBuff; + CCBsvSignature_t signature; + int rc, exp; + mbedtls_asn1_buf sig_oid, alg_oid, params; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; + mbedtls_pk_rsassa_pss_options pss_opts; + size_t len; + uint8_t *p, *end; + CCHashResult_t digest; + CCBool_t is_verified; + /* This is a rather large array, we don't want it on stack */ + static uint32_t workspace[BSV_RSA_WORKSPACE_MIN_SIZE]; + + /* Verify the signature algorithm */ + /* Get pointers to signature OID and parameters */ + p = sig_alg; + end = p + sig_alg_len; + rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* Get the actual signature algorithm (MD + PK) */ + rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports RSASSA-PSS signature */ + if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the RSASSA-PSS params */ + /* The trailer field is verified to be 0xBC internally by this API */ + rc = mbedtls_x509_get_rsassa_pss_params(¶ms, &md_alg, + &pss_opts.mgf1_hash_id, + &pss_opts.expected_salt_len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports SHA256 as hash algorithm */ + if (md_alg != MBEDTLS_MD_SHA256 || + pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_SIGNATURE; + + if (pss_opts.expected_salt_len != RSA_SALT_LEN) + return CRYPTO_ERR_SIGNATURE; + + /* Parse the public key */ + p = pk_ptr; + end = p + pk_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + end = p + len; + rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0) + return CRYPTO_ERR_SIGNATURE; + + if (pk_alg != MBEDTLS_PK_RSA) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (*p == 0) { + p++; len--; + } + if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * Copy N from certificate. + */ + memcpy(NBuff, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES); + + /* Verify the RSA exponent */ + p += len; + rc = mbedtls_asn1_get_int(&p, end, &exp); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (exp != RSA_EXPONENT) + return CRYPTO_ERR_SIGNATURE; + + /* Get the signature (bitstring) */ + p = sig_ptr; + end = p + sig_len; + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * Copy the signature (in BE format) + */ + memcpy((uint8_t *)signature, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES); + + error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, + data_ptr, data_len, digest); + if (error != CC_OK) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the signature */ + error = CC_BsvRsaPssVerify((uintptr_t)PLAT_CRYPTOCELL_BASE, NBuff, + NULL, signature, digest, workspace, + BSV_RSA_WORKSPACE_MIN_SIZE, &is_verified); + if ((error != CC_OK) || (is_verified != CC_TRUE)) + return CRYPTO_ERR_SIGNATURE; + + /* Signature verification success */ + return CRYPTO_SUCCESS; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + mbedtls_asn1_buf hash_oid, params; + mbedtls_md_type_t md_alg; + uint8_t *p, *end, *hash; + CCHashResult_t pubKeyHash; + size_t len; + int rc; + CCError_t error; + + /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ + p = digest_info_ptr; + end = p + digest_info_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Get the hash algorithm */ + rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_HASH; + + rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) + return CRYPTO_ERR_HASH; + /* Verify that hash algorithm is SHA256 */ + if (md_alg != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_HASH; + + /* Hash should be octet string type */ + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Length of hash must match the algorithm's size */ + if (len != HASH_RESULT_SIZE_IN_BYTES) + return CRYPTO_ERR_HASH; + + hash = p; + error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, data_ptr, + data_len, pubKeyHash); + if (error != CC_OK) + return CRYPTO_ERR_HASH; + + rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES); + if (rc != 0) + return CRYPTO_ERR_HASH; + + return CRYPTO_SUCCESS; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c b/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c new file mode 100644 index 0000000..17e1280 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c @@ -0,0 +1,109 @@ +/* + * 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 + +/* + * Return the ROTPK hash + * + * Return: 0 = success, Otherwise = error + */ +int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, unsigned int *flags) +{ + CCError_t error; + uint32_t lcs; + int i; + uint32_t *key = (uint32_t *)dst; + + assert(dst != NULL); + assert(len >= HASH_RESULT_SIZE_IN_WORDS); + assert(flags != NULL); + + error = CC_BsvLcsGet(PLAT_CRYPTOCELL_BASE, &lcs); + if (error != CC_OK) + return 1; + + if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) || (lcs == CC_BSV_RMA_LCS)) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + error = CC_BsvPubKeyHashGet(PLAT_CRYPTOCELL_BASE, + CC_SB_HASH_BOOT_KEY_256B, + key, HASH_RESULT_SIZE_IN_WORDS); + + if (error == CC_BSV_HASH_NOT_PROGRAMMED_ERR) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + if (error == CC_OK) { + + /* Keys are stored in OTP in little-endian format */ + for (i = 0; i < HASH_RESULT_SIZE_IN_WORDS; i++) + key[i] = le32toh(key[i]); + + *flags = ROTPK_IS_HASH; + return 0; + } + + return 1; +} + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * specifies the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionGet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_TRUSTED, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionGet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_NON_TRUSTED, nv_ctr); + } + + return (error != CC_OK); +} + +/* + * Store a new non-volatile counter value in the counter specified by the OID + * in the cookie. This function is not expected to be called if the Lifecycle + * state is RMA as the values in the certificate are expected to always match + * the nvcounter values. But if called when the LCS is RMA, the underlying + * helper functions will return success but without updating the counter. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionSet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_TRUSTED, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionSet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_NON_TRUSTED, nv_ctr); + } + + return (error != CC_OK); +} + diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/cryptocell_crypto.mk b/arm-trusted-firmware/drivers/auth/cryptocell/cryptocell_crypto.mk new file mode 100644 index 0000000..db39047 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/cryptocell_crypto.mk @@ -0,0 +1,40 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/auth/mbedtls/mbedtls_common.mk + +# The algorithm is RSA when using Cryptocell crypto driver +TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA + +# Needs to be set to drive mbed TLS configuration correctly +$(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID)) + +$(eval $(call add_define,KEY_SIZE)) + +# CCSBROM_LIB_PATH must be set to the Cryptocell SBROM library path +ifeq (${CCSBROM_LIB_PATH},) + $(error Error: CCSBROM_LIB_PATH not set) +endif + +CRYPTOCELL_VERSION ?= 712 +ifeq (${CRYPTOCELL_VERSION},712) + CCSBROM_LIB_FILENAME := cc_712sbromx509 +else ifeq (${CRYPTOCELL_VERSION},713) + CCSBROM_LIB_FILENAME := cc_713bsv +else + $(error Error: CRYPTOCELL_VERSION set to invalid version) +endif + +CRYPTOCELL_SRC_DIR := drivers/auth/cryptocell/${CRYPTOCELL_VERSION}/ + +CRYPTOCELL_SOURCES := ${CRYPTOCELL_SRC_DIR}/cryptocell_crypto.c \ + ${CRYPTOCELL_SRC_DIR}/cryptocell_plat_helpers.c + +TF_LDFLAGS += -L$(CCSBROM_LIB_PATH) +LDLIBS += -l$(CCSBROM_LIB_FILENAME) + +BL1_SOURCES += ${CRYPTOCELL_SOURCES} +BL2_SOURCES += ${CRYPTOCELL_SOURCES} diff --git a/arm-trusted-firmware/drivers/auth/dualroot/cot.c b/arm-trusted-firmware/drivers/auth/dualroot/cot.c new file mode 100644 index 0000000..8368503 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/dualroot/cot.c @@ -0,0 +1,959 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include MBEDTLS_CONFIG_FILE +#include +#include + +/* + * Allocate static buffers to store the authentication parameters extracted from + * the certificates. + */ +static unsigned char fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tb_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char hw_config_hash_buf[HASH_DER_LEN]; +static unsigned char scp_fw_hash_buf[HASH_DER_LEN]; +static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN]; + +#ifdef IMAGE_BL2 +static unsigned char soc_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN]; +static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; +#if defined(SPD_spmd) +static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN]; +#endif /* SPD_spmd */ + +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +#endif + +/* + * Parameter type descriptors. + */ +static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, 0); +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + +static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID); +static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, HW_CONFIG_HASH_OID); +static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, FW_CONFIG_HASH_OID); +#ifdef IMAGE_BL1 +static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID); +static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID); +static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, FWU_HASH_OID); +#endif /* IMAGE_BL1 */ + +#ifdef IMAGE_BL2 +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); + +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, PROT_PK_OID); + +static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SCP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID); +static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID); +static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); +#if defined(SPD_spmd) +static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG1_HASH_OID); +static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG2_HASH_OID); +static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG3_HASH_OID); +static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG4_HASH_OID); +static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG5_HASH_OID); +static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG6_HASH_OID); +static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG7_HASH_OID); +static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG8_HASH_OID); +#endif /* SPD_spmd */ +#endif /* IMAGE_BL2 */ + + +/* BL2 */ +static const auth_img_desc_t trusted_boot_fw_cert = { + .img_id = TRUSTED_BOOT_FW_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tb_fw_hash, + .data = { + .ptr = (void *)tb_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tb_fw_config_hash, + .data = { + .ptr = (void *)tb_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &hw_config_hash, + .data = { + .ptr = (void *)hw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &fw_config_hash, + .data = { + .ptr = (void *)fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +#ifdef IMAGE_BL1 +static const auth_img_desc_t bl2_image = { + .img_id = BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tb_fw_hash + } + } + } +}; +#endif /* IMAGE_BL1 */ + +/* HW Config */ +static const auth_img_desc_t hw_config = { + .img_id = HW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &hw_config_hash + } + } + } +}; + +/* TB FW Config */ +#ifdef IMAGE_BL1 +static const auth_img_desc_t tb_fw_config = { + .img_id = TB_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tb_fw_config_hash + } + } + } +}; + +static const auth_img_desc_t fw_config = { + .img_id = FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &fw_config_hash + } + } + } +}; + +#endif /* IMAGE_BL1 */ + +#ifdef IMAGE_BL2 +/* Trusted key certificate */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + } +}; + +/* SCP Firmware */ +static const auth_img_desc_t scp_fw_key_cert = { + .img_id = SCP_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; + +static const auth_img_desc_t scp_fw_content_cert = { + .img_id = SCP_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &scp_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &scp_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_fw_hash, + .data = { + .ptr = (void *)scp_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +static const auth_img_desc_t scp_bl2_image = { + .img_id = SCP_BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &scp_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &scp_fw_hash + } + } + } +}; + +/* SoC Firmware */ +static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; + +static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } +}; + +/* SOC FW Config */ +static const auth_img_desc_t soc_fw_config = { + .img_id = SOC_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_config_hash + } + } + } +}; + +/* 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_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; + +static const auth_img_desc_t trusted_os_fw_content_cert = { + .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_os_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tos_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_hash, + .data = { + .ptr = (void *)tos_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tos_fw_extra1_hash, + .data = { + .ptr = (void *)tos_fw_extra1_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &tos_fw_extra2_hash, + .data = { + .ptr = (void *)tos_fw_extra2_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &tos_fw_config_hash, + .data = { + .ptr = (void *)tos_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_hash + } + } + } +}; + +static const auth_img_desc_t bl32_extra1_image = { + .img_id = BL32_EXTRA1_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra1_hash + } + } + } +}; + +static const auth_img_desc_t bl32_extra2_image = { + .img_id = BL32_EXTRA2_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra2_hash + } + } + } +}; + +/* TOS FW Config */ +static const auth_img_desc_t tos_fw_config = { + .img_id = TOS_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_config_hash + } + } + } +}; + +/* Non-Trusted Firmware */ +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, /* Root certificate. */ + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &prot_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; + +/* NT FW Config */ +static const auth_img_desc_t nt_fw_config = { + .img_id = NT_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_fw_config_hash + } + } + } +}; + +/* + * Secure Partitions + */ +#if defined(SPD_spmd) +static const auth_img_desc_t sip_sp_content_cert = { + .img_id = SIP_SP_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &sp_pkg1_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[0], + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &sp_pkg2_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[1], + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &sp_pkg3_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[2], + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &sp_pkg4_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[3], + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +DEFINE_SIP_SP_PKG(1); +DEFINE_SIP_SP_PKG(2); +DEFINE_SIP_SP_PKG(3); +DEFINE_SIP_SP_PKG(4); + +static const auth_img_desc_t plat_sp_content_cert = { + .img_id = PLAT_SP_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &prot_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &sp_pkg5_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[4], + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &sp_pkg6_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[5], + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &sp_pkg7_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[6], + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &sp_pkg8_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[7], + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +DEFINE_PLAT_SP_PKG(5); +DEFINE_PLAT_SP_PKG(6); +DEFINE_PLAT_SP_PKG(7); +DEFINE_PLAT_SP_PKG(8); +#endif /* SPD_spmd */ + +#else /* IMAGE_BL2 */ + +/* FWU auth descriptor */ +static const auth_img_desc_t fwu_cert = { + .img_id = FWU_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_bl2u_hash, + .data = { + .ptr = (void *)scp_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &bl2u_hash, + .data = { + .ptr = (void *)tb_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &ns_bl2u_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +/* SCP_BL2U */ +static const auth_img_desc_t scp_bl2u_image = { + .img_id = SCP_BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &scp_bl2u_hash + } + } + } +}; + +/* BL2U */ +static const auth_img_desc_t bl2u_image = { + .img_id = BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl2u_hash + } + } + } +}; + +/* NS_BL2U */ +static const auth_img_desc_t ns_bl2u_image = { + .img_id = NS_BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ns_bl2u_hash + } + } + } +}; +#endif /* IMAGE_BL2 */ + +/* + * Chain of trust definition + */ +#ifdef IMAGE_BL1 +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert, + [BL2_IMAGE_ID] = &bl2_image, + [HW_CONFIG_ID] = &hw_config, + [TB_FW_CONFIG_ID] = &tb_fw_config, + [FW_CONFIG_ID] = &fw_config, + [FWU_CERT_ID] = &fwu_cert, + [SCP_BL2U_IMAGE_ID] = &scp_bl2u_image, + [BL2U_IMAGE_ID] = &bl2u_image, + [NS_BL2U_IMAGE_ID] = &ns_bl2u_image +}; +#else /* IMAGE_BL2 */ +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert, + [HW_CONFIG_ID] = &hw_config, + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert, + [SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert, + [SCP_BL2_IMAGE_ID] = &scp_bl2_image, + [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert, + [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert, + [BL31_IMAGE_ID] = &bl31_image, + [SOC_FW_CONFIG_ID] = &soc_fw_config, + [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, + [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image, + [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image, + [TOS_FW_CONFIG_ID] = &tos_fw_config, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, + [BL33_IMAGE_ID] = &bl33_image, + [NT_FW_CONFIG_ID] = &nt_fw_config, +#if defined(SPD_spmd) + [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert, + [PLAT_SP_CONTENT_CERT_ID] = &plat_sp_content_cert, + [SP_PKG1_ID] = &sp_pkg1, + [SP_PKG2_ID] = &sp_pkg2, + [SP_PKG3_ID] = &sp_pkg3, + [SP_PKG4_ID] = &sp_pkg4, + [SP_PKG5_ID] = &sp_pkg5, + [SP_PKG6_ID] = &sp_pkg6, + [SP_PKG7_ID] = &sp_pkg7, + [SP_PKG8_ID] = &sp_pkg8, +#endif +}; +#endif + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/auth/img_parser_mod.c b/arm-trusted-firmware/drivers/auth/img_parser_mod.c new file mode 100644 index 0000000..535695d --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/img_parser_mod.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +IMPORT_SYM(uintptr_t, __PARSER_LIB_DESCS_START__, PARSER_LIB_DESCS_START); +IMPORT_SYM(uintptr_t, __PARSER_LIB_DESCS_END__, PARSER_LIB_DESCS_END); +static unsigned int parser_lib_indices[IMG_MAX_TYPES]; +static img_parser_lib_desc_t *parser_lib_descs; + +#define INVALID_IDX UINT_MAX + +static void validate_desc(img_parser_lib_desc_t *desc) +{ + assert(desc != NULL); + assert(desc->init != NULL); + assert(desc->name != NULL); + assert(desc->check_integrity != NULL); + assert(desc->get_auth_param != NULL); +} + +void img_parser_init(void) +{ + unsigned int index, mod_num; + + /* Initialise internal variables to invalid state */ + for (index = 0; index < IMG_MAX_TYPES; index++) { + parser_lib_indices[index] = INVALID_IDX; + } + + /* Calculate how many image parsers are registered. At least one parser + * must be present */ + mod_num = PARSER_LIB_DESCS_END - PARSER_LIB_DESCS_START; + mod_num /= sizeof(img_parser_lib_desc_t); + assert(mod_num > 0); + + parser_lib_descs = (img_parser_lib_desc_t *) PARSER_LIB_DESCS_START; + for (index = 0; index < mod_num; index++) { + + /* Check that the image parser library descriptor is valid */ + validate_desc(&parser_lib_descs[index]); + + /* Initialize image parser */ + parser_lib_descs[index].init(); + + /* Ensure only one parser is registered for each image type */ + assert(parser_lib_indices[parser_lib_descs[index].img_type] == + INVALID_IDX); + + /* Keep the index of this hash calculator */ + parser_lib_indices[parser_lib_descs[index].img_type] = index; + } +} + +int img_parser_check_integrity(img_type_t img_type, + void *img_ptr, unsigned int img_len) +{ + unsigned int idx; + + assert(img_ptr != NULL); + assert(img_len != 0); + + /* No integrity checks on raw images */ + if (img_type == IMG_RAW) { + return IMG_PARSER_OK; + } + + /* Find the index of the required image parser */ + idx = parser_lib_indices[img_type]; + assert(idx != INVALID_IDX); + + /* Call the function to check the image integrity */ + return parser_lib_descs[idx].check_integrity(img_ptr, img_len); +} + +/* + * Extract an authentication parameter from an image + * + * Parameters: + * img_type: image type (certificate, raw image, etc) + * type_desc: provides info to obtain the parameter + * img_ptr: pointer to image data + * img_len: image length + * param_ptr: [out] stores a pointer to the parameter + * param_len: [out] stores the length of the parameter + */ +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) +{ + unsigned int idx; + + assert(type_desc != NULL); + assert(img_ptr != NULL); + assert(img_len != 0); + assert(param_ptr != NULL); + assert(param_len != NULL); + + /* In a raw image we can only get the data itself */ + if (img_type == IMG_RAW) { + assert(type_desc->type == AUTH_PARAM_RAW_DATA); + *param_ptr = img_ptr; + *param_len = img_len; + return IMG_PARSER_OK; + } + + /* Find the index of the required image parser library */ + idx = parser_lib_indices[img_type]; + assert(idx != INVALID_IDX); + + /* Call the function to obtain the parameter */ + return parser_lib_descs[idx].get_auth_param(type_desc, img_ptr, img_len, + param_ptr, param_len); +} diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c new file mode 100644 index 0000000..a12e49c --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* mbed TLS headers */ +#include +#include + +#include +#include +#include MBEDTLS_CONFIG_FILE +#include + +static void cleanup(void) +{ + ERROR("EXIT from BL2\n"); + panic(); +} + +/* + * mbed TLS initialization function + */ +void mbedtls_init(void) +{ + static int ready; + void *heap_addr; + size_t heap_size = 0; + int err; + + if (!ready) { + if (atexit(cleanup)) + panic(); + + err = plat_get_mbedtls_heap(&heap_addr, &heap_size); + + /* Ensure heap setup is proper */ + if (err < 0) { + ERROR("Mbed TLS failed to get a heap\n"); + panic(); + } + assert(heap_size >= TF_MBEDTLS_HEAP_SIZE); + + /* Initialize the mbed TLS heap */ + mbedtls_memory_buffer_alloc_init(heap_addr, heap_size); + +#ifdef MBEDTLS_PLATFORM_SNPRINTF_ALT + mbedtls_platform_set_snprintf(snprintf); +#endif + ready = 1; + } +} + +/* + * The following helper function simply returns the default allocated heap. + * It can be used by platforms for their plat_get_mbedtls_heap() implementation. + */ +int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size) +{ + static unsigned char heap[TF_MBEDTLS_HEAP_SIZE]; + + assert(heap_addr != NULL); + assert(heap_size != NULL); + + *heap_addr = heap; + *heap_size = sizeof(heap); + return 0; +} diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.mk b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.mk new file mode 100644 index 0000000..0a4775d --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.mk @@ -0,0 +1,126 @@ +# +# Copyright (c) 2015-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${MBEDTLS_COMMON_MK},1) +MBEDTLS_COMMON_MK := 1 + +# MBEDTLS_DIR must be set to the mbed TLS main directory (it must contain +# the 'include' and 'library' subdirectories). +ifeq (${MBEDTLS_DIR},) + $(error Error: MBEDTLS_DIR not set) +endif + +MBEDTLS_INC = -I${MBEDTLS_DIR}/include + +# Specify mbed TLS configuration file +MBEDTLS_CONFIG_FILE ?= "" +$(eval $(call add_define,MBEDTLS_CONFIG_FILE)) + +MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_common.c + + +LIBMBEDTLS_SRCS := $(addprefix ${MBEDTLS_DIR}/library/, \ + aes.c \ + asn1parse.c \ + asn1write.c \ + cipher.c \ + cipher_wrap.c \ + memory_buffer_alloc.c \ + oid.c \ + platform.c \ + platform_util.c \ + bignum.c \ + gcm.c \ + md.c \ + pk.c \ + pk_wrap.c \ + pkparse.c \ + pkwrite.c \ + sha256.c \ + sha512.c \ + ecdsa.c \ + ecp_curves.c \ + ecp.c \ + rsa.c \ + rsa_internal.c \ + x509.c \ + x509_crt.c \ + ) + +# The platform may define the variable 'TF_MBEDTLS_KEY_ALG' to select the key +# algorithm to use. If the variable is not defined, select it based on +# algorithm used for key generation `KEY_ALG`. If `KEY_ALG` is not defined, +# then it is set to `rsa`. +ifeq (${TF_MBEDTLS_KEY_ALG},) + ifeq (${KEY_ALG}, ecdsa) + TF_MBEDTLS_KEY_ALG := ecdsa + else + TF_MBEDTLS_KEY_ALG := rsa + endif +endif + +ifeq (${TF_MBEDTLS_KEY_SIZE},) + ifneq ($(findstring rsa,${TF_MBEDTLS_KEY_ALG}),) + ifeq (${KEY_SIZE},) + TF_MBEDTLS_KEY_SIZE := 2048 + else + TF_MBEDTLS_KEY_SIZE := ${KEY_SIZE} + endif + endif +endif + +ifeq (${HASH_ALG}, sha384) + TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA384 +else ifeq (${HASH_ALG}, sha512) + TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA512 +else + TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA256 +endif + +ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa) + TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_ECDSA +else ifeq (${TF_MBEDTLS_KEY_ALG},rsa) + TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA +else ifeq (${TF_MBEDTLS_KEY_ALG},rsa+ecdsa) + TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA_AND_ECDSA +else + $(error "TF_MBEDTLS_KEY_ALG=${TF_MBEDTLS_KEY_ALG} not supported on mbed TLS") +endif + +ifeq (${DECRYPTION_SUPPORT}, aes_gcm) + TF_MBEDTLS_USE_AES_GCM := 1 +else + TF_MBEDTLS_USE_AES_GCM := 0 +endif + +ifeq ($(MEASURED_BOOT),1) + ifeq (${TPM_HASH_ALG}, sha256) + TF_MBEDTLS_TPM_HASH_ALG_ID := TF_MBEDTLS_SHA256 + else ifeq (${TPM_HASH_ALG}, sha384) + TF_MBEDTLS_TPM_HASH_ALG_ID := TF_MBEDTLS_SHA384 + else ifeq (${TPM_HASH_ALG}, sha512) + TF_MBEDTLS_TPM_HASH_ALG_ID := TF_MBEDTLS_SHA512 + else + $(error "TPM_HASH_ALG not defined.") + endif +endif + +# Needs to be set to drive mbed TLS configuration correctly +$(eval $(call add_defines,\ + $(sort \ + TF_MBEDTLS_KEY_ALG_ID \ + TF_MBEDTLS_KEY_SIZE \ + TF_MBEDTLS_HASH_ALG_ID \ + TF_MBEDTLS_USE_AES_GCM \ +))) + +ifeq ($(MEASURED_BOOT),1) + $(eval $(call add_define,TF_MBEDTLS_TPM_HASH_ALG_ID)) +endif + +$(eval $(call MAKE_LIB,mbedtls)) + +endif diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c new file mode 100644 index 0000000..0901d04 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* mbed TLS headers */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define LIB_NAME "mbed TLS" + +#if MEASURED_BOOT +/* + * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available + * so make sure that mbed TLS MD maximum size must be lesser than this. + */ +CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, + assert_mbedtls_md_size_overflow); + +#endif /* MEASURED_BOOT */ + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + /* Initialize mbed TLS */ + mbedtls_init(); +} + +#if TRUSTED_BOARD_BOOT +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static 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) +{ + mbedtls_asn1_buf sig_oid, sig_params; + mbedtls_asn1_buf signature; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; + mbedtls_pk_context pk = {0}; + int rc; + void *sig_opts = NULL; + const mbedtls_md_info_t *md_info; + unsigned char *p, *end; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + /* Get pointers to signature OID and parameters */ + p = (unsigned char *)sig_alg; + end = (unsigned char *)(p + sig_alg_len); + rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); + if (rc != 0) { + return CRYPTO_ERR_SIGNATURE; + } + + /* Get the actual signature algorithm (MD + PK) */ + rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts); + if (rc != 0) { + return CRYPTO_ERR_SIGNATURE; + } + + /* Parse the public key */ + mbedtls_pk_init(&pk); + p = (unsigned char *)pk_ptr; + end = (unsigned char *)(p + pk_len); + rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end2; + } + + /* Get the signature (bitstring) */ + p = (unsigned char *)sig_ptr; + end = (unsigned char *)(p + sig_len); + signature.tag = *p; + rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end1; + } + signature.p = p; + + /* Calculate the hash of the data */ + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + rc = CRYPTO_ERR_SIGNATURE; + goto end1; + } + p = (unsigned char *)data_ptr; + rc = mbedtls_md(md_info, p, data_len, hash); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end1; + } + + /* Verify the signature */ + rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, + mbedtls_md_get_size(md_info), + signature.p, signature.len); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end1; + } + + /* Signature verification success */ + rc = CRYPTO_SUCCESS; + +end1: + mbedtls_pk_free(&pk); +end2: + mbedtls_free(sig_opts); + return rc; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + mbedtls_asn1_buf hash_oid, params; + mbedtls_md_type_t md_alg; + const mbedtls_md_info_t *md_info; + unsigned char *p, *end, *hash; + unsigned char data_hash[MBEDTLS_MD_MAX_SIZE]; + size_t len; + int rc; + + /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ + p = (unsigned char *)digest_info_ptr; + end = p + digest_info_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Get the hash algorithm */ + rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return CRYPTO_ERR_HASH; + } + + /* Hash should be octet string type */ + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Length of hash must match the algorithm's size */ + if (len != mbedtls_md_get_size(md_info)) { + return CRYPTO_ERR_HASH; + } + hash = p; + + /* Calculate the hash of the data */ + p = (unsigned char *)data_ptr; + rc = mbedtls_md(md_info, p, data_len, data_hash); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Compare values */ + rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + return CRYPTO_SUCCESS; +} +#endif /* TRUSTED_BOARD_BOOT */ + +#if MEASURED_BOOT +/* + * Map a generic crypto message digest algorithm to the corresponding macro used + * by Mbed TLS. + */ +static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo) +{ + switch (algo) { + case CRYPTO_MD_SHA512: + return MBEDTLS_MD_SHA512; + case CRYPTO_MD_SHA384: + return MBEDTLS_MD_SHA384; + case CRYPTO_MD_SHA256: + return MBEDTLS_MD_SHA256; + default: + /* Invalid hash algorithm. */ + return MBEDTLS_MD_NONE; + } +} + +/* + * Calculate a hash + * + * output points to the computed hash + */ +static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, + unsigned int data_len, + unsigned char output[CRYPTO_MD_MAX_SIZE]) +{ + const mbedtls_md_info_t *md_info; + + md_info = mbedtls_md_info_from_type(md_type(md_algo)); + if (md_info == NULL) { + return CRYPTO_ERR_HASH; + } + + /* + * Calculate the hash of the data, it is safe to pass the + * 'output' hash buffer pointer considering its size is always + * bigger than or equal to MBEDTLS_MD_MAX_SIZE. + */ + return mbedtls_md(md_info, data_ptr, data_len, output); +} +#endif /* MEASURED_BOOT */ + +#if TF_MBEDTLS_USE_AES_GCM +/* + * Stack based buffer allocation for decryption operation. It could + * be configured to balance stack usage vs execution speed. + */ +#define DEC_OP_BUF_SIZE 128 + +static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, + unsigned int key_len, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len) +{ + mbedtls_gcm_context ctx; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + unsigned char buf[DEC_OP_BUF_SIZE]; + unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; + unsigned char *pt = data_ptr; + size_t dec_len; + int diff, i, rc; + + mbedtls_gcm_init(&ctx); + + rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + while (len > 0) { + dec_len = MIN(sizeof(buf), len); + + rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + memcpy(pt, buf, dec_len); + pt += dec_len; + len -= dec_len; + } + + rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + /* Check tag in "constant-time" */ + for (diff = 0, i = 0; i < tag_len; i++) + diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; + + if (diff != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + /* GCM decryption success */ + rc = CRYPTO_SUCCESS; + +exit_gcm: + mbedtls_gcm_free(&ctx); + return rc; +} + +/* + * Authenticated decryption of an image + */ +static 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) +{ + int rc; + + assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); + + switch (dec_algo) { + case CRYPTO_GCM_DECRYPT: + rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, + tag, tag_len); + if (rc != 0) + return rc; + break; + default: + return CRYPTO_ERR_DECRYPTION; + } + + return CRYPTO_SUCCESS; +} +#endif /* TF_MBEDTLS_USE_AES_GCM */ + +/* + * Register crypto library descriptor + */ +#if MEASURED_BOOT && TRUSTED_BOARD_BOOT +#if TF_MBEDTLS_USE_AES_GCM +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, + auth_decrypt); +#else +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, + NULL); +#endif +#elif TRUSTED_BOARD_BOOT +#if TF_MBEDTLS_USE_AES_GCM +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, + auth_decrypt); +#else +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); +#endif +#elif MEASURED_BOOT +REGISTER_CRYPTO_LIB(LIB_NAME, init, calc_hash); +#endif /* MEASURED_BOOT && TRUSTED_BOARD_BOOT */ diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.mk b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.mk new file mode 100644 index 0000000..2a9fbbf --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/auth/mbedtls/mbedtls_common.mk + +MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_crypto.c + + diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509.mk b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509.mk new file mode 100644 index 0000000..a0557e2 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509.mk @@ -0,0 +1,9 @@ +# +# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/auth/mbedtls/mbedtls_common.mk + +MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_x509_parser.c diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c new file mode 100644 index 0000000..129566b --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * X509 parser based on mbed TLS + * + * This module implements functions to check the integrity of a X509v3 + * certificate ASN.1 structure and extract authentication parameters from the + * extensions field, such as an image hash or a public key. + */ + +#include +#include +#include +#include + +/* mbed TLS headers */ +#include +#include +#include + +#include +#include +#include +#include + +/* Maximum OID string length ("a.b.c.d.e.f ...") */ +#define MAX_OID_STR_LEN 64 + +#define LIB_NAME "mbed TLS X509v3" + +/* Temporary variables to speed up the authentication parameters search. These + * variables are assigned once during the integrity check and used any time an + * authentication parameter is requested, so we do not have to parse the image + * again */ +static mbedtls_asn1_buf tbs; +static mbedtls_asn1_buf v3_ext; +static mbedtls_asn1_buf pk; +static mbedtls_asn1_buf sig_alg; +static mbedtls_asn1_buf signature; + +/* + * 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); + + ZERO_AND_CLEAN(tbs) + ZERO_AND_CLEAN(v3_ext); + ZERO_AND_CLEAN(pk); + ZERO_AND_CLEAN(sig_alg); + ZERO_AND_CLEAN(signature); + +#undef ZERO_AND_CLEAN +} + +/* + * Get X509v3 extension + * + * Global variable 'v3_ext' must point to the extensions region + * in the certificate. No need to check for errors since the image has passed + * the integrity check. + */ +static int get_ext(const char *oid, void **ext, unsigned int *ext_len) +{ + int oid_len; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + unsigned char *p; + const unsigned char *end; + char oid_str[MAX_OID_STR_LEN]; + mbedtls_asn1_buf extn_oid; + int is_critical; + + assert(oid != NULL); + + p = v3_ext.p; + end = v3_ext.p + v3_ext.len; + + mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + + while (p < end) { + zeromem(&extn_oid, sizeof(extn_oid)); + is_critical = 0; /* DEFAULT FALSE */ + + mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + end_ext_data = p + len; + + /* Get extension ID */ + extn_oid.tag = *p; + mbedtls_asn1_get_tag(&p, end, &extn_oid.len, MBEDTLS_ASN1_OID); + extn_oid.p = p; + p += extn_oid.len; + + /* Get optional critical */ + mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical); + + /* Extension data */ + mbedtls_asn1_get_tag(&p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING); + end_ext_octet = p + len; + + /* Detect requested extension */ + oid_len = mbedtls_oid_get_numeric_string(oid_str, + MAX_OID_STR_LEN, + &extn_oid); + if (oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { + return IMG_PARSER_ERR; + } + if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { + *ext = (void *)p; + *ext_len = (unsigned int)len; + return IMG_PARSER_OK; + } + + /* Next */ + p = end_ext_octet; + } + + return IMG_PARSER_ERR_NOT_FOUND; +} + + +/* + * Check the integrity of the certificate ASN.1 structure. + * + * Extract the relevant data that will be used later during authentication. + * + * This function doesn't clear the static variables located on the top of this + * file in case of an error. It is only called from check_integrity(), which + * performs the cleanup if necessary. + */ +static int cert_parse(void *img, unsigned int img_len) +{ + int ret, is_critical; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_asn1_buf sig_alg1, sig_alg2; + + p = (unsigned char *)img; + len = img_len; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + if (len > (size_t)(end - p)) { + return IMG_PARSER_ERR_FORMAT; + } + crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + tbs.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + end = p + len; + tbs.len = end - tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * CertificateSerialNumber ::= INTEGER + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * signature AlgorithmIdentifier + */ + sig_alg1.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + if ((end - p) < 1) { + return IMG_PARSER_ERR_FORMAT; + } + sig_alg1.len = (p + len) - sig_alg1.p; + p += len; + + /* + * issuer Name + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * subject Name + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * SubjectPublicKeyInfo + */ + pk.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + pk.len = (p + len) - pk.p; + p += len; + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 1); + if (ret != 0) { + if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return IMG_PARSER_ERR_FORMAT; + } + } else { + p += len; + } + + /* + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 2); + if (ret != 0) { + if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return IMG_PARSER_ERR_FORMAT; + } + } else { + p += len; + } + + /* + * extensions [3] EXPLICIT Extensions OPTIONAL + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + v3_ext.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + v3_ext.len = (p + len) - v3_ext.p; + + /* + * Check extensions integrity + */ + while (p < end) { + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + /* Get extension ID */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* Get optional critical */ + ret = mbedtls_asn1_get_bool(&p, end, &is_critical); + if ((ret != 0) && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { + return IMG_PARSER_ERR_FORMAT; + } + + /* Data should be octet string type */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_OCTET_STRING); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + } + + if (p != end) { + return IMG_PARSER_ERR_FORMAT; + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier + */ + sig_alg2.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + if ((end - p) < 1) { + return IMG_PARSER_ERR_FORMAT; + } + sig_alg2.len = (p + len) - sig_alg2.p; + p += len; + + /* Compare both signature algorithms */ + if (sig_alg1.len != sig_alg2.len) { + return IMG_PARSER_ERR_FORMAT; + } + if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) { + return IMG_PARSER_ERR_FORMAT; + } + memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg)); + + /* + * signatureValue BIT STRING + */ + signature.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_BIT_STRING); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + signature.len = (p + len) - signature.p; + p += len; + + /* Check certificate length */ + if (p != end) { + return IMG_PARSER_ERR_FORMAT; + } + + return IMG_PARSER_OK; +} + + +/* Exported functions */ + +static void init(void) +{ + mbedtls_init(); +} + +/* + * 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 = cert_parse(img, img_len); + + if (rc != IMG_PARSER_OK) + clear_temp_vars(); + + return rc; +} + +/* + * Extract an authentication parameter from an X509v3 certificate + * + * This function returns a pointer to the extracted data and its length. + * Depending on the type of parameter, a pointer to the data stored in the + * certificate may be returned (i.e. an octet string containing a hash). Other + * data may need to be copied and formatted (i.e. integers). In the later case, + * a buffer of the correct type needs to be statically allocated, filled and + * returned. + */ +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; + + /* We do not use img because the check_integrity function has already + * extracted the relevant data (v3_ext, pk, sig_alg, etc) */ + + switch (type_desc->type) { + case AUTH_PARAM_RAW_DATA: + /* Data to be signed */ + *param = (void *)tbs.p; + *param_len = (unsigned int)tbs.len; + break; + case AUTH_PARAM_HASH: + case AUTH_PARAM_NV_CTR: + /* All these parameters are included as X509v3 extensions */ + rc = get_ext(type_desc->cookie, param, param_len); + break; + case AUTH_PARAM_PUB_KEY: + if (type_desc->cookie != 0) { + /* Get public key from extension */ + rc = get_ext(type_desc->cookie, param, param_len); + } else { + /* Get the subject public key */ + *param = (void *)pk.p; + *param_len = (unsigned int)pk.len; + } + break; + case AUTH_PARAM_SIG_ALG: + /* Get the certificate signature algorithm */ + *param = (void *)sig_alg.p; + *param_len = (unsigned int)sig_alg.len; + break; + case AUTH_PARAM_SIG: + /* Get the certificate signature */ + *param = (void *)signature.p; + *param_len = (unsigned int)signature.len; + break; + default: + rc = IMG_PARSER_ERR_NOT_FOUND; + break; + } + + return rc; +} + +REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \ + check_integrity, get_auth_param); diff --git a/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c new file mode 100644 index 0000000..44f8638 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include MBEDTLS_CONFIG_FILE + +#include +#include +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID); +static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID); +static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, FWU_HASH_OID); + +static const auth_img_desc_t bl2_image = { + .img_id = BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tb_fw_hash + } + } + } +}; + +/* + * FWU auth descriptor. + */ +static const auth_img_desc_t fwu_cert = { + .img_id = FWU_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_bl2u_hash, + .data = { + .ptr = (void *)scp_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &bl2u_hash, + .data = { + .ptr = (void *)tb_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &ns_bl2u_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +/* + * SCP_BL2U + */ +static const auth_img_desc_t scp_bl2u_image = { + .img_id = SCP_BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &scp_bl2u_hash + } + } + } +}; +/* + * BL2U + */ +static const auth_img_desc_t bl2u_image = { + .img_id = BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl2u_hash + } + } + } +}; +/* + * NS_BL2U + */ +static const auth_img_desc_t ns_bl2u_image = { + .img_id = NS_BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ns_bl2u_hash + } + } + } +}; +/* + * TB_FW_CONFIG + */ +static const auth_img_desc_t tb_fw_config = { + .img_id = TB_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tb_fw_config_hash + } + } + } +}; + +static const auth_img_desc_t fw_config = { + .img_id = FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &fw_config_hash + } + } + } +}; + +/* + * TBBR Chain of trust definition + */ +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert, + [BL2_IMAGE_ID] = &bl2_image, + [HW_CONFIG_ID] = &hw_config, + [TB_FW_CONFIG_ID] = &tb_fw_config, + [FW_CONFIG_ID] = &fw_config, + [FWU_CERT_ID] = &fwu_cert, + [SCP_BL2U_IMAGE_ID] = &scp_bl2u_image, + [BL2U_IMAGE_ID] = &bl2u_image, + [NS_BL2U_IMAGE_ID] = &ns_bl2u_image +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c new file mode 100644 index 0000000..78e38f6 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include MBEDTLS_CONFIG_FILE +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#endif +#include + + +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char non_trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; + +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); +/* + * Trusted key certificate + */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +/* + * 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_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &non_trusted_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &nt_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; + +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [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); diff --git a/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c new file mode 100644 index 0000000..11e2f46 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c @@ -0,0 +1,688 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include MBEDTLS_CONFIG_FILE + +#include +#include +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +static unsigned char soc_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN]; +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char non_trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; +#if defined(SPD_spmd) +static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN]; +#endif /* SPD_spmd */ + +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SCP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID); +static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID); +static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); +#if defined(SPD_spmd) +static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG1_HASH_OID); +static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG2_HASH_OID); +static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG3_HASH_OID); +static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG4_HASH_OID); +static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG5_HASH_OID); +static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG6_HASH_OID); +static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG7_HASH_OID); +static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG8_HASH_OID); +#endif /* SPD_spmd */ + +/* + * Trusted key certificate + */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +/* + * SCP Firmware + */ +static const auth_img_desc_t scp_fw_key_cert = { + .img_id = SCP_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t scp_fw_content_cert = { + .img_id = SCP_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &scp_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &scp_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_fw_hash, + .data = { + .ptr = (void *)scp_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t scp_bl2_image = { + .img_id = SCP_BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &scp_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &scp_fw_hash + } + } + } +}; +/* + * SoC Firmware + */ +static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } +}; +/* SOC FW Config */ +static const auth_img_desc_t soc_fw_config = { + .img_id = SOC_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_config_hash + } + } + } +}; +/* + * 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_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t trusted_os_fw_content_cert = { + .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_os_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tos_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_hash, + .data = { + .ptr = (void *)tos_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tos_fw_extra1_hash, + .data = { + .ptr = (void *)tos_fw_extra1_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &tos_fw_extra2_hash, + .data = { + .ptr = (void *)tos_fw_extra2_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &tos_fw_config_hash, + .data = { + .ptr = (void *)tos_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_hash + } + } + } +}; +static const auth_img_desc_t bl32_extra1_image = { + .img_id = BL32_EXTRA1_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra1_hash + } + } + } +}; +static const auth_img_desc_t bl32_extra2_image = { + .img_id = BL32_EXTRA2_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra2_hash + } + } + } +}; +/* TOS FW Config */ +static const auth_img_desc_t tos_fw_config = { + .img_id = TOS_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_config_hash + } + } + } +}; +/* + * 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_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &non_trusted_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &nt_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; +/* NT FW Config */ +static const auth_img_desc_t nt_fw_config = { + .img_id = NT_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_fw_config_hash + } + } + } +}; +/* Secure Partitions */ +#if defined(SPD_spmd) +static const auth_img_desc_t sip_sp_content_cert = { + .img_id = SIP_SP_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &sp_pkg1_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[0], + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &sp_pkg2_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[1], + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &sp_pkg3_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[2], + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &sp_pkg4_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[3], + .len = (unsigned int)HASH_DER_LEN + } + }, + [4] = { + .type_desc = &sp_pkg5_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[4], + .len = (unsigned int)HASH_DER_LEN + } + }, + [5] = { + .type_desc = &sp_pkg6_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[5], + .len = (unsigned int)HASH_DER_LEN + } + }, + [6] = { + .type_desc = &sp_pkg7_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[6], + .len = (unsigned int)HASH_DER_LEN + } + }, + [7] = { + .type_desc = &sp_pkg8_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[7], + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +DEFINE_SIP_SP_PKG(1); +DEFINE_SIP_SP_PKG(2); +DEFINE_SIP_SP_PKG(3); +DEFINE_SIP_SP_PKG(4); +DEFINE_SIP_SP_PKG(5); +DEFINE_SIP_SP_PKG(6); +DEFINE_SIP_SP_PKG(7); +DEFINE_SIP_SP_PKG(8); +#endif /* SPD_spmd */ + +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert, + [HW_CONFIG_ID] = &hw_config, + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert, + [SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert, + [SCP_BL2_IMAGE_ID] = &scp_bl2_image, + [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert, + [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert, + [BL31_IMAGE_ID] = &bl31_image, + [SOC_FW_CONFIG_ID] = &soc_fw_config, + [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, + [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image, + [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image, + [TOS_FW_CONFIG_ID] = &tos_fw_config, + [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, + [NT_FW_CONFIG_ID] = &nt_fw_config, +#if defined(SPD_spmd) + [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert, + [SP_PKG1_ID] = &sp_pkg1, + [SP_PKG2_ID] = &sp_pkg2, + [SP_PKG3_ID] = &sp_pkg3, + [SP_PKG4_ID] = &sp_pkg4, + [SP_PKG5_ID] = &sp_pkg5, + [SP_PKG6_ID] = &sp_pkg6, + [SP_PKG7_ID] = &sp_pkg7, + [SP_PKG8_ID] = &sp_pkg8, +#endif +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c new file mode 100644 index 0000000..0983d42 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include MBEDTLS_CONFIG_FILE + +#include +#include +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +/* + * The platform must allocate buffers to store the authentication parameters + * extracted from the certificates. In this case, because of the way the CoT is + * established, we can reuse some of the buffers on different stages + */ + +static unsigned char fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char hw_config_hash_buf[HASH_DER_LEN]; +unsigned char tb_fw_hash_buf[HASH_DER_LEN]; +unsigned char scp_fw_hash_buf[HASH_DER_LEN]; +unsigned char nt_world_bl_hash_buf[HASH_DER_LEN]; + +/* + * common Parameter type descriptors across BL1 and BL2 + */ +auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID); +auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, 0); +auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + +/* common hash used across BL1 and BL2 */ +auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID); +auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID); +auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, FW_CONFIG_HASH_OID); +static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, HW_CONFIG_HASH_OID); + +/* trusted_boot_fw_cert */ +const auth_img_desc_t trusted_boot_fw_cert = { + .img_id = TRUSTED_BOOT_FW_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tb_fw_hash, + .data = { + .ptr = (void *)tb_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tb_fw_config_hash, + .data = { + .ptr = (void *)tb_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &hw_config_hash, + .data = { + .ptr = (void *)hw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &fw_config_hash, + .data = { + .ptr = (void *)fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +/* HW Config */ +const auth_img_desc_t hw_config = { + .img_id = HW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &hw_config_hash + } + } + } +}; diff --git a/arm-trusted-firmware/drivers/brcm/chimp.c b/arm-trusted-firmware/drivers/brcm/chimp.c new file mode 100644 index 0000000..81767bb --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/chimp.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#define CHIMP_DEFAULT_STARTUP_ADDR 0xb4300000 + +/* ChiMP's view of APE scratchpad memory for fastboot */ +#define CHIMP_FASTBOOT_ADDR 0x61000000 + +#define CHIMP_PREPARE_ACCESS_WINDOW(addr) \ + (\ + mmio_write_32(\ + NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT, \ + addr & 0xffc00000)\ + ) +#define CHIMP_INDIRECT_TGT_ADDR(addr) \ + (CHIMP_INDIRECT_BASE + (addr & CHIMP_INDIRECT_ADDR_MASK)) + +#define CHIMP_CTRL_ADDR(x) (CHIMP_REG_CTRL_BASE + x) + +/* For non-PAXC builds */ +#ifndef CHIMP_FB1_ENTRY +#define CHIMP_FB1_ENTRY 0 +#endif + +#define CHIMP_DBG VERBOSE + +void bcm_chimp_write(uintptr_t addr, uint32_t value) +{ + CHIMP_PREPARE_ACCESS_WINDOW(addr); + mmio_write_32(CHIMP_INDIRECT_TGT_ADDR(addr), value); +} + +uint32_t bcm_chimp_read(uintptr_t addr) +{ + CHIMP_PREPARE_ACCESS_WINDOW(addr); + return mmio_read_32(CHIMP_INDIRECT_TGT_ADDR(addr)); +} + +void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits) +{ + CHIMP_PREPARE_ACCESS_WINDOW(addr); + mmio_clrbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits); +} + +void bcm_chimp_setbits(uintptr_t addr, uint32_t bits) +{ + CHIMP_PREPARE_ACCESS_WINDOW(addr); + mmio_setbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits); +} + +int bcm_chimp_is_nic_mode(void) +{ + uint32_t val; + + /* Check if ChiMP straps are set */ + val = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW); + val &= CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK; + + return val == CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK; +} + +void bcm_chimp_fru_prog_done(bool is_done) +{ + uint32_t val; + + val = is_done ? (1 << CHIMP_FRU_PROG_DONE_BIT) : 0; + bcm_chimp_setbits(CHIMP_REG_ECO_RESERVED, val); +} + +int bcm_chimp_handshake_done(void) +{ + uint32_t value; + + value = bcm_chimp_read(CHIMP_REG_ECO_RESERVED); + value &= (1 << CHIMP_FLASH_ACCESS_DONE_BIT); + + return value != 0; +} + +int bcm_chimp_wait_handshake(void) +{ + uint32_t timeout = CHIMP_HANDSHAKE_TIMEOUT_MS; + uint32_t status; + + INFO("Waiting for ChiMP handshake...\n"); + do { + if (bcm_chimp_handshake_done()) + break; + /* No need to wait if ChiMP reported an error */ + status = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG); + if (status & CHIMP_ERROR_MASK) { + ERROR("ChiMP error 0x%x. Wait aborted\n", status); + break; + } + mdelay(1); + } while (--timeout); + + if (!bcm_chimp_handshake_done()) { + if (timeout == 0) { + WARN("Timeout waiting for ChiMP handshake\n"); + } + } else { + INFO("Got handshake from ChiMP!\n"); + } + + return bcm_chimp_handshake_done(); +} + +uint32_t bcm_chimp_read_ctrl(uint32_t offset) +{ + return bcm_chimp_read(CHIMP_CTRL_ADDR(offset)); +} + +static int bcm_chimp_nitro_reset(void) +{ + uint32_t timeout; + + /* Perform tasks done by M0 in NIC mode */ + CHIMP_DBG("Taking Nitro out of reset\n"); + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, + /* MHB_RESET_N */ + (1 << CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R) | + /* PCI_RESET_N */ + (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) | + /* PM_RESET_N */ + (1 << CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R) | + /* NIC_RESET_N */ + (1 << CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R) + ); + + /* Wait until Nitro is out of reset */ + timeout = NIC_RESET_RELEASE_TIMEOUT_US; + do { + uint32_t value; + + value = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG); + if ((value & CHIMP_BPE_MODE_ID_MASK) == + CHIMP_BPE_MODE_ID_PATTERN) + break; + udelay(1); + } while (--timeout); + + if (timeout == 0) { + ERROR("NIC reset release timed out\n"); + return -1; + } + + return 0; +} + +static void bcm_nitro_secure_mode_enable(void) +{ + mmio_setbits_32(CDRU_NITRO_CONTROL, + (1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R) | + (1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R)); + mmio_write_32(NITRO_TZPC_TZPCDECPROT0clr, + /* NITRO_TZPC */ + 1 << NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R); +} + +static int bcm_chimp_reset_and_initial_setup(void) +{ + + int err; + uint32_t handshake_reg; + + err = bcm_chimp_nitro_reset(); + if (err) + return err; + + /* Enable Nitro secure mode */ + bcm_nitro_secure_mode_enable(); + + /* Force ChiMP back into reset */ + bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG), + 1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R); + + handshake_reg = (1 << SR_IN_SMARTNIC_MODE_BIT); + + /* Get OTP secure Chimp boot status */ + if (mmio_read_32(CRMU_OTP_STATUS) & (1 << CRMU_OTP_STATUS_BIT)) + handshake_reg |= (1 << SR_CHIMP_SECURE_BOOT_BIT); + + bcm_chimp_write(CHIMP_REG_ECO_RESERVED, handshake_reg); + + CHIMP_DBG("ChiMP reset and initial handshake parameters set\n"); + + return 0; +} + +static void bcm_nitro_chimp_release_reset(void) +{ + bcm_chimp_clrbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG), + 1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R); + + CHIMP_DBG("Nitro Reset Released\n"); +} + +static void bcm_chimp_set_fastboot(int mode) +{ + uint32_t fb_entry; + + /* 1. Enable fastboot */ + bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG), + (1 << CHIMP_FAST_BOOT_MODE_BIT)); + fb_entry = CHIMP_FASTBOOT_ADDR | mode; + if (mode == CHIMP_FASTBOOT_JUMP_IN_PLACE) + fb_entry = CHIMP_FB1_ENTRY; + /* 2. Write startup address and mode */ + INFO("Setting fastboot type %d entry to 0x%x\n", mode, fb_entry); + bcm_chimp_write( + CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_FSTBOOT_PTR_REG), + fb_entry); +} + +#ifndef CHIMPFW_USE_SIDELOAD +static void bcm_chimp_load_fw_from_spi(uintptr_t spi_addr, size_t size) +{ + uintptr_t ape_scpad; + uintptr_t dest; + size_t bytes_left; + + ape_scpad = CHIMP_REG_CHIMP_APE_SCPAD; + dest = CHIMP_INDIRECT_TGT_ADDR(CHIMP_REG_CHIMP_APE_SCPAD); + bytes_left = size; + + while (bytes_left) { + uint32_t delta; + + delta = bytes_left > CHIMP_WINDOW_SIZE ? + bytes_left - CHIMP_WINDOW_SIZE : bytes_left; + CHIMP_PREPARE_ACCESS_WINDOW(ape_scpad); + INFO("Transferring %d byte(s) from 0x%lx to 0x%lx\n", + delta, spi_addr, dest); + /* + * This single memcpy call takes significant amount of time + * on Palladium. Be patient + */ + memcpy((void *)dest, (void *)spi_addr, delta); + bytes_left -= delta; + INFO("Transferred %d byte(s) from 0x%lx to 0x%lx (%lu%%)\n", + delta, spi_addr, dest, + ((size - bytes_left) * 100)/size); + spi_addr += delta; + dest += delta; + ape_scpad += delta; + } +} + +static int bcm_chimp_find_fw_in_spi(uintptr_t *addr, size_t *size) +{ + int i; + bnxnvm_master_block_header_t *master_block_hdr; + bnxnvm_directory_block_header_t *dir_block_hdr; + bnxnvm_directory_entry_t *dir_entry; + int found; + + found = 0; + + /* Read the master block */ + master_block_hdr = + (bnxnvm_master_block_header_t *)(uintptr_t)QSPI_BASE_ADDR; + if (master_block_hdr->sig != BNXNVM_MASTER_BLOCK_SIG) { + WARN("Invalid masterblock 0x%x (expected 0x%x)\n", + master_block_hdr->sig, + BNXNVM_MASTER_BLOCK_SIG); + return -NV_NOT_NVRAM; + } + if ((master_block_hdr->block_size > NV_MAX_BLOCK_SIZE) || + (master_block_hdr->directory_offset >= + master_block_hdr->nvram_size)) { + WARN("Invalid masterblock block size 0x%x or directory offset 0x%x\n", + master_block_hdr->block_size, + master_block_hdr->directory_offset); + return -NV_BAD_MB; + } + + /* Skip to the Directory block start */ + dir_block_hdr = + (bnxnvm_directory_block_header_t *) + ((uintptr_t)QSPI_BASE_ADDR + + master_block_hdr->directory_offset); + if (dir_block_hdr->sig != BNXNVM_DIRECTORY_BLOCK_SIG) { + WARN("Invalid directory header 0x%x (expected 0x%x)\n", + dir_block_hdr->sig, + BNXNVM_DIRECTORY_BLOCK_SIG); + return -NV_BAD_DIR_HEADER; + } + + /* Locate the firmware */ + for (i = 0; i < dir_block_hdr->entries; i++) { + *addr = ((uintptr_t)dir_block_hdr + dir_block_hdr->length + + i * dir_block_hdr->entry_length); + dir_entry = (bnxnvm_directory_entry_t *)(*addr); + if ((dir_entry->type == BNX_DIR_TYPE_BOOTCODE) || + (dir_entry->type == BNX_DIR_TYPE_BOOTCODE_2)) { + found = 1; + break; + } + } + + if (!found) + return -NV_FW_NOT_FOUND; + + *addr = QSPI_BASE_ADDR + dir_entry->item_location; + *size = dir_entry->data_length; + + INFO("Found chimp firmware at 0x%lx, size %lu byte(s)\n", + *addr, *size); + + return NV_OK; +} +#endif + +int bcm_chimp_initiate_fastboot(int fastboot_type) +{ + int err; + + if ((fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) && + (fastboot_type <= CHIMP_FASTBOOT_JUMP_DECOMPRESS)) { + CHIMP_DBG("Initiating ChiMP fastboot type %d\n", fastboot_type); + } + + /* + * If we are here, M0 did not setup Nitro because NIC mode + * strap was not present + */ + err = bcm_chimp_reset_and_initial_setup(); + if (err) + return err; + + if (fastboot_type > CHIMP_FASTBOOT_JUMP_DECOMPRESS) { + WARN("ChiMP setup deferred\n"); + return -1; + } + + if (fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) { + + if ((fastboot_type == CHIMP_FASTBOOT_JUMP_IN_PLACE) && + (CHIMP_FB1_ENTRY == 0)) { + ERROR("Missing ESAL entry point for fastboot type 1.\n" + "Fastboot failed\n"); + return -1; + } + + /* + * TODO: We need to think of the way to load the ChiMP fw. + * This could be SPI, NAND, etc. + * For now we temporarily stick to the SPI load unless + * CHIMPFW_USE_SIDELOAD is defined. Note that for the SPI NVRAM + * image we need to parse directory and get the image. + * When we load image from other media there is no need to + * parse because fw image can be directly placed into the APE's + * scratchpad. + * For sideload method we simply reset the ChiMP, set bpe_reg + * to do fastboot with the type we define, and release from + * reset so that ROM loader would initiate fastboot immediately + */ +#ifndef CHIMPFW_USE_SIDELOAD + { + uintptr_t spi_addr; + size_t size; + + err = bcm_chimp_find_fw_in_spi(&spi_addr, &size); + if (!err) { + INFO("Loading ChiMP firmware, addr 0x%lx, size %lu byte(s)\n", + spi_addr, size); + bcm_chimp_load_fw_from_spi(spi_addr, size); + } else { + ERROR("Error %d ChiMP firmware not in NVRAM directory!\n", + err); + } + } +#else + INFO("Skip ChiMP QSPI fastboot type %d due to sideload requested\n", + fastboot_type); +#endif + if (!err) { + INFO("Instruct ChiMP to fastboot\n"); + bcm_chimp_set_fastboot(fastboot_type); + INFO("Fastboot mode set\n"); + } + } + + bcm_nitro_chimp_release_reset(); + + return err; +} diff --git a/arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c b/arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c new file mode 100644 index 0000000..34d761c --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c @@ -0,0 +1,1017 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include + +#include "bcm_emmc.h" +#include "emmc_chal_types.h" +#include "emmc_chal_sd.h" +#include "emmc_pboot_hal_memory_drv.h" + +extern void emmc_soft_reset(void); + +#define SD_VDD_WINDOW_1_6_TO_1_7 0x00000010 // 1.6 V to 1.7 Volts +#define SD_VDD_WINDOW_1_7_TO_1_8 0x00000020 // 1.7 V to 1.8 Volts +#define SD_VDD_WINDOW_1_8_TO_1_9 0x00000040 // 1.8 V to 1.9 Volts +#define SD_VDD_WINDOW_1_9_TO_2_0 0x00000080 // 1.9 V to 2.0 Volts +#define SD_VDD_WINDOW_2_0_TO_2_1 0x00000100 // 2.0 V to 2.1 Volts +#define SD_VDD_WINDOW_2_1_TO_2_2 0x00000200 // 2.1 V to 2.2 Volts +#define SD_VDD_WINDOW_2_2_TO_2_3 0x00000400 // 2.2 V to 2.3 Volts +#define SD_VDD_WINDOW_2_3_TO_2_4 0x00000800 // 2.3 V to 2.4 Volts +#define SD_VDD_WINDOW_2_4_TO_2_5 0x00001000 // 2.4 V to 2.5 Volts +#define SD_VDD_WINDOW_2_5_TO_2_6 0x00002000 // 2.5 V to 2.6 Volts +#define SD_VDD_WINDOW_2_6_TO_2_7 0x00004000 // 2.6 V to 2.7 Volts +#define SD_VDD_WINDOW_2_7_TO_2_8 0x00008000 // 2.7 V to 2.8 Volts +#define SD_VDD_WINDOW_2_8_TO_2_9 0x00010000 // 2.8 V to 2.9 Volts +#define SD_VDD_WINDOW_2_9_TO_3_0 0x00020000 // 2.9 V to 3.0 Volts +#define SD_VDD_WINDOW_3_0_TO_3_1 0x00040000 // 3.0 V to 3.1 Volts +#define SD_VDD_WINDOW_3_1_TO_3_2 0x00080000 // 3.1 V to 3.2 Volts +#define SD_VDD_WINDOW_3_2_TO_3_3 0x00100000 // 3.2 V to 3.3 Volts +#define SD_VDD_WINDOW_3_3_TO_3_4 0x00200000 // 3.3 V to 3.4 Volts +#define SD_VDD_WINDOW_3_4_TO_3_5 0x00400000 // 3.4 V to 3.5 Volts +#define SD_VDD_WINDOW_3_5_TO_3_6 0x00800000 // 3.5 V to 3.6 Volts + +#define SD_VDD_WINDOW_1_6_TO_2_6 (SD_VDD_WINDOW_1_6_TO_1_7 | \ + SD_VDD_WINDOW_1_7_TO_1_8 | \ + SD_VDD_WINDOW_1_8_TO_1_9 | \ + SD_VDD_WINDOW_1_9_TO_2_0 | \ + SD_VDD_WINDOW_2_0_TO_2_1 | \ + SD_VDD_WINDOW_2_1_TO_2_2 | \ + SD_VDD_WINDOW_2_2_TO_2_3 | \ + SD_VDD_WINDOW_2_3_TO_2_4 | \ + SD_VDD_WINDOW_2_4_TO_2_5 | \ + SD_VDD_WINDOW_2_5_TO_2_6) + +#define SD_VDD_WINDOW_2_6_TO_3_2 (SD_VDD_WINDOW_2_6_TO_2_7 | \ + SD_VDD_WINDOW_2_7_TO_2_8 | \ + SD_VDD_WINDOW_2_8_TO_2_9 | \ + SD_VDD_WINDOW_2_9_TO_3_0 | \ + SD_VDD_WINDOW_3_0_TO_3_1 | \ + SD_VDD_WINDOW_3_1_TO_3_2) + +#define SD_VDD_WINDOW_3_2_TO_3_6 (SD_VDD_WINDOW_3_2_TO_3_3 | \ + SD_VDD_WINDOW_3_3_TO_3_4 | \ + SD_VDD_WINDOW_3_4_TO_3_5 | \ + SD_VDD_WINDOW_3_5_TO_3_6) + + +static int32_t chal_sd_set_power(struct sd_dev *handle, + uint32_t voltage, uint32_t state); + +static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary); + +static int32_t chal_sd_setup_handler(struct sd_dev *handle, + uint32_t sdBbase, uint32_t hostBase); + +/* + * Configure host controller pwr settings, + * to match voltage requirements by SD Card + */ +static int32_t chal_sd_set_power(struct sd_dev *handle, + uint32_t voltage, uint32_t state) +{ + int32_t rc, rval = SD_FAIL; + uint32_t time = 0; + + if (handle == NULL) + return SD_INVALID_HANDLE; + + mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET, + (SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK | + SD4_EMMC_TOP_CTRL_SDPWR_MASK), + (voltage << 9)); + + /* + * Long delay is required here in emulation. Without this, the initial + * commands sent to the eMMC card timeout. We don't know if this + * delay is necessary with silicon, leaving in for safety. + * It is observed that 403ms on emulation system and as per the clock + * calculations it is expected to complete with in 1ms on chip + */ + do { + rc = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET); + + if ((rc & SD4_EMMC_TOP_INTR_CRDINS_MASK) == + SD4_EMMC_TOP_INTR_CRDINS_MASK) + break; + + mdelay(1); + } while (time++ < EMMC_CARD_DETECT_TIMEOUT_MS); + + if (time >= EMMC_CARD_DETECT_TIMEOUT_MS) { + ERROR("EMMC: Card insert event detection timeout\n"); + return rval; + } + + VERBOSE("EMMC: Card detection delay: %dms\n", time); + + if (state) + mmio_setbits_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET, + SD4_EMMC_TOP_CTRL_SDPWR_MASK); + + /* dummy write & ack to verify if the sdio is ready to send commads */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, 0); + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, 0); + + /* + * 63ms observed on emulation system, As per clock calculations + * it will complete < 1ms on chip. + */ + time = 0; + do { + rc = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET); + + if (rc & SD4_EMMC_TOP_INTR_ERRIRQ_MASK) + break; + + if ((rc & SD4_EMMC_TOP_INTR_CMDDONE_MASK) == + SD4_EMMC_TOP_INTR_CMDDONE_MASK) + break; + + mdelay(1); + } while (time++ < EMMC_CMD_TIMEOUT_MS); + + if (time >= EMMC_CMD_TIMEOUT_MS) { + WARN("%s %d Initial dummy command timeout is happened\n", + __func__, __LINE__); + return rval; + } + + VERBOSE("EMMC: Dummy Command delay: %dms\n", time); + + return SD_OK; +} + +/* + * Configure DMA Boundaries + */ +static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary) +{ + if (handle == NULL) + return; + + mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BLOCK_OFFSET, + SD4_EMMC_TOP_BLOCK_HSBS_MASK, boundary); +} + +static int32_t chal_sd_setup_handler(struct sd_dev *handle, uint32_t sdBase, + uint32_t hostBase) +{ + if (handle == NULL) + return SD_INVALID_HANDLE; + + handle->ctrl.sdRegBaseAddr = sdBase; + handle->ctrl.hostRegBaseAddr = hostBase; + handle->ctrl.present = 0; + handle->ctrl.rca = 0; + handle->ctrl.blkGapEnable = 0; + handle->ctrl.cmdStatus = 0; + + return SD_OK; +} + +/* + * Initialize SD Host controller + */ +int32_t chal_sd_init(CHAL_HANDLE *sd_handle) +{ + uint32_t cap_val_l = 0; + uint32_t ctl_val, voltage; + uint32_t timeout_val; + struct sd_dev *handle; + uint32_t reg_val; + int32_t rval = SD_FAIL; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + /* + * Set SDIO Host Controller capabilities register + */ + EMMC_TRACE("Set Host Controller Capabilities register\n"); + + reg_val = 0; + reg_val |= (1 << ICFG_SDIO0_CAP0__SLOT_TYPE_R); + reg_val |= (0 << ICFG_SDIO0_CAP0__INT_MODE_R); + reg_val |= (0 << ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__SUSPEND_RESUME_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__SDMA_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__HIGH_SPEED_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__ADMA2_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R); + reg_val |= (2 << ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R); + reg_val |= (0xd0 << ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R); + reg_val |= (0x30 << ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R); + + mmio_write_32(ICFG_SDIO0_CAP0, reg_val); + + reg_val = 0; + reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_MODE_R); + reg_val |= (0 << ICFG_SDIO0_CAP1__CLK_MULT_R); + reg_val |= (0 << ICFG_SDIO0_CAP1__RETUNING_MODE_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__TUNE_SDR50_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__TIME_RETUNE_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_D_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_C_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_A_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__DDR50_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__SDR104_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__SDR50_R); + + mmio_write_32(ICFG_SDIO0_CAP1, reg_val); + + /* Reset the SDIO controller */ + chal_sd_stop(); + + /* Turn on SD clock */ + chal_sd_set_clock(sd_handle, + chal_sd_freq_2_div_ctrl_setting(INIT_CLK_FREQ), 1); + + /* program data time out value to the max */ + timeout_val = SD_HOST_CORE_TIMEOUT; + + ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + ctl_val |= ((timeout_val & 0xf) << SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT); + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + ctl_val); + + /* enable all interrupt status */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET, + 0); + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET, + 0); + + SD_US_DELAY(100); + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET, + SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS); + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET, + SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS); + + /* Select SD bus voltage */ + cap_val_l = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CAPABILITIES1_OFFSET); + handle->cfg.voltage = 0; + voltage = 0x7; + + if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V33_MASK) { + handle->cfg.voltage |= SD_VDD_WINDOW_3_3_TO_3_4; + voltage = 0x7; + } else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V3_MASK) { + handle->cfg.voltage |= SD_VDD_WINDOW_3_0_TO_3_1; + voltage = 0x6; + } else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V18_MASK) { + handle->cfg.voltage |= SD_VDD_WINDOW_1_8_TO_1_9; + voltage = 0x5; + } + + rval = chal_sd_set_power(handle, voltage, SD4_EMMC_TOP_CTRL_SDPWR_MASK); + + ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_HCVERSIRQ_OFFSET); + handle->ctrl.version = ((ctl_val >> 16) & 0xFF); + + return rval; +} + +void chal_sd_set_speed(CHAL_HANDLE *sd_handle, uint32_t speed) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return; + + handle = (struct sd_dev *) sd_handle; + + if (speed) { + EMMC_TRACE("enable HighSpeed\n"); + mmio_setbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET, + SD4_EMMC_TOP_CTRL_HSEN_MASK); + } else { + EMMC_TRACE("disable HighSpeed\n"); + mmio_clrbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET, + SD4_EMMC_TOP_CTRL_HSEN_MASK); + } +} + +int32_t chal_sd_stop(void) +{ + uintptr_t idm_rst_ctrl_addr = EMMC_IDM_RESET_CTRL_ADDR; + + /* Configure IO pins */ + emmc_soft_reset(); + + /* Reset the SDIO controller */ + mmio_write_32(idm_rst_ctrl_addr, 1); + SD_US_DELAY(100); + mmio_write_32(idm_rst_ctrl_addr, 0); + SD_US_DELAY(100); + + return SD_OK; +} + +/* + * Check if host supports specified capability + * returns -ve val on error, 0 if capability not supported else 1. + */ +int32_t chal_sd_check_cap(CHAL_HANDLE *sd_handle, uint32_t caps) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + if (caps & mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CAPABILITIES1_OFFSET)) + return 1; + else + return 0; +} + +int32_t chal_sd_start(CHAL_HANDLE *sd_handle, + uint32_t mode, uint32_t sd_base, uint32_t host_base) +{ + + struct sd_dev *handle; + int32_t rval = SD_FAIL; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + handle->cfg.mode = SD_PIO_MODE; /* set to PIO mode first for init */ + handle->cfg.dma = SD_DMA_OFF; + + chal_sd_setup_handler(handle, sd_base, host_base); + + /* init and start hw */ + rval = chal_sd_init(sd_handle); + if (rval != SD_OK) + return rval; + + chal_sd_clear_pending_irq(sd_handle); + + handle->ctrl.eventList = 0; + handle->cfg.mode = mode; + + return SD_OK; +} + +/* + * Function to check 8bits of err generated from auto CMD12 + */ +int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + return (mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_ERRSTAT_OFFSET) & 0xFF); +} + +/* + * Read present state register + */ +uint32_t chal_sd_get_present_status(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + return mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_PSTATE_OFFSET); +} + +/* + * Set SD bus width + */ +int32_t chal_sd_config_bus_width(CHAL_HANDLE *sd_handle, int32_t width) +{ + uint32_t ctl_val; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET); + + switch (width) { +#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT + case SD_BUS_DATA_WIDTH_8BIT: + ctl_val &= ~SD_BUS_DATA_WIDTH_4BIT; + ctl_val |= SD_BUS_DATA_WIDTH_8BIT; + break; +#endif + case SD_BUS_DATA_WIDTH_4BIT: + ctl_val &= ~SD_BUS_DATA_WIDTH_8BIT; + ctl_val |= SD_BUS_DATA_WIDTH_4BIT; + break; + case SD_BUS_DATA_WIDTH_1BIT: + ctl_val &= ~(SD_BUS_DATA_WIDTH_4BIT | SD_BUS_DATA_WIDTH_8BIT); + break; + default: + return SD_INV_DATA_WIDTH; + }; + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET, + ctl_val); + + return SD_OK; +} + +/* + * Function to enable or disable DMA control. + */ +int32_t chal_sd_set_dma(CHAL_HANDLE *sd_handle, uint32_t mode) +{ + uint32_t val; + struct sd_dev *handle; + int32_t rc; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + if (mode) { + rc = chal_sd_check_cap(sd_handle, + SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK | + SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK); + if (rc < 0) + return rc; + + if (rc) { + + handle->cfg.dma = mode; + val = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET); + val &= ~(SD4_EMMC_TOP_CTRL_DMASEL_MASK); + val |= handle->cfg.dma - 1; + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET, val); + return SD_OK; + } + } + handle->cfg.dma = 0; + + return SD_FAIL; +} + +/* + * Get current DMA address. + * Called only when there is no data transaction activity. + */ +uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + if (handle->cfg.dma == SD_DMA_OFF) + return 0; + + return (uintptr_t)mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_SYSADDR_OFFSET); +} + +int32_t chal_sd_send_cmd(CHAL_HANDLE *sd_handle, uint32_t cmd_idx, + uint32_t argument, uint32_t options) +{ + uint32_t cmd_mode_reg = 0; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + EMMC_TRACE("%s %d cmd:%d argReg:%x options:%x\n", + __func__, __LINE__, cmd_idx, argument, options); + + /* Configure the value for command and mode registers */ + cmd_mode_reg = (cmd_idx << 24) | options; + + /* + * 1. Write block size reg & block count reg, + * this is done in the tx or rx setup + */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_BLOCK_OFFSET, + handle->ctrl.blkReg); + + /* 2. Write argument reg */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, + argument); + handle->ctrl.argReg = argument; + + /* + * 3. Write transfer mode reg & command reg, check the DMA bit which is + * set before this function call if it is selected. + */ + if (cmd_idx == 24 || cmd_idx == 25 || cmd_idx == 18 || cmd_idx == 17 || + cmd_idx == 42 || cmd_idx == 51 || cmd_idx == 53) + cmd_mode_reg |= ((handle->cfg.dma) ? 1 : 0); + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, + cmd_mode_reg); + + handle->ctrl.cmdIndex = cmd_idx; + + return SD_OK; +} + +int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sd_handle, uintptr_t address) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + if (handle->cfg.dma == SD_DMA_OFF) + return SD_FAIL; + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET, + address); + return SD_OK; +} + +uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq) +{ + /* + * Divider control setting represents 1/2 of the actual divider value. + * + * DesiredFreq = BaseClockFreq / (2 * div_ctrl_setting) + * + * ==> div_ctrl_setting = BaseClockFreq / (2 * DesiredFreq) + */ + uint32_t div_ctrl_setting; + uint32_t actual_freq; + + assert(desired_freq != 0); + + /* Special case, 0 = divider of 1. */ + if (desired_freq >= BASE_CLK_FREQ) + return 0; + + /* Normal case, desired_freq < BASE_CLK_FREQ */ + div_ctrl_setting = BASE_CLK_FREQ / (2 * desired_freq); + + actual_freq = BASE_CLK_FREQ / (2 * div_ctrl_setting); + + if (actual_freq > desired_freq) { + /* + * Division does not result in exact freqency match. + * Make sure resulting frequency does not exceed requested freq. + */ + div_ctrl_setting++; + } + + return div_ctrl_setting; +} + +int32_t chal_sd_set_clock(CHAL_HANDLE *sd_handle, uint32_t div_ctrl_setting, + uint32_t on) +{ + uint32_t value; + struct sd_dev *handle; + uint32_t time; + uint32_t clk_sel_high_byte = 0xFF & (div_ctrl_setting >> 8); + uint32_t clk_sel_low_byte = 0xFF & div_ctrl_setting; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + EMMC_TRACE("set_clock(div_ctrl_setting=%d,on=%d)\n", + div_ctrl_setting, on); + + handle = (struct sd_dev *) sd_handle; + + /* Read control register content. */ + value = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + + /* Disable Clock */ + value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK); + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + value); + + /* Clear bits of interest. */ + value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK | + SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK); + + /* Set bits of interest to new value. */ + value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK & + (clk_sel_low_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT)); + value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK & + (clk_sel_high_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT)); + value |= SD4_EMMC_TOP_CTRL1_ICLKEN_MASK; + + /* Write updated value back to control register. */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + value); + + time = 0; + do { + value = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + + if ((value & SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) == + SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) + break; + + mdelay(1); + } while (time++ < EMMC_CLOCK_SETTING_TIMEOUT_MS); + + if (time >= EMMC_CLOCK_SETTING_TIMEOUT_MS) + WARN("%s %d clock settings timeout happenedi (%dms)\n", + __func__, __LINE__, time); + + VERBOSE("EMMC: clock settings delay: %dms\n", time); + + value = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + + if (on) + value |= SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK; + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + value); + + return SD_OK; +} + +/* + * function to setup DMA buffer and data length, calculates block + * size and the number of blocks to be transferred and return + * the DMA buffer address. + */ +int32_t chal_sd_setup_xfer(CHAL_HANDLE *sd_handle, + uint8_t *data, uint32_t length, int32_t dir) +{ + uint32_t blocks = 0; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + if (length <= handle->cfg.blockSize) { + handle->ctrl.blkReg = length | handle->cfg.dmaBoundary; + } else { + blocks = length / handle->cfg.blockSize; + handle->ctrl.blkReg = (blocks << 16) | handle->cfg.blockSize | + handle->cfg.dmaBoundary; + } + + if (handle->cfg.dma != SD_DMA_OFF) { + /* For DMA target address setting, physical address should be used */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET, + (uintptr_t)data); + } + + return SD_OK; +} + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +/* + * function to write one block data directly to the + * host controller's FIFO which is 1K uint8_t or + * 2K uint8_t in size. + * It is used in Non-DMA mode for data transmission. + */ +int32_t chal_sd_write_buffer(CHAL_HANDLE *sd_handle, uint32_t length, + uint8_t *data) +{ + uint32_t i, leftOver = 0, blockSize, size, value = 0; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + blockSize = handle->cfg.blockSize; + + if (length == 0) + return SD_OK; + + /* PIO mode, push into fifo word by word */ + if (length >= blockSize) { + size = blockSize; + } else { + size = ((length >> 2) << 2); + leftOver = length % 4; + } + + for (i = 0; i < size; i += 4) { + value = *(uint32_t *)(data + i); + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET, value); + } +/* + * BUG ALERT: + * This implementation has TWO issues that must be addressed before you + * can safely INCLUDE_EMMC_DRIVER_WRITE_CODE. + * + * (1) For the last leftOver bytes, driver writes full word, which means + * some of the eMMC content (i.e. "4 - leftOver" will be erroneously + * overwritten). + * (2) eMMC is a block device. What happens when less than a full block of + * data is submitted??? + */ + if (leftOver > 0) { + value = ((*(uint32_t *)(data + i)) << (4 - leftOver)); + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET, value); + } + + return SD_OK; +} +#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */ + +/* + * Function to read maximal one block data directly + * from the data port of the host controller (FIFO). It is used + * in Non-DMA mode for data transmission. + */ +int32_t chal_sd_read_buffer(CHAL_HANDLE *sd_handle, uint32_t length, + uint8_t *data) +{ + uint32_t i, size, leftOver, blockSize, value; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + value = 0; + + blockSize = handle->cfg.blockSize; + + /* PIO mode, extract fifo word by word */ + if (length >= blockSize) { + size = blockSize; + leftOver = 0; + } else { + leftOver = length % 4; + size = ((length >> 2) << 2); + } + + for (i = 0; i < size; i += 4) { + value = + mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET); + memcpy((void *)(data + i), &value, sizeof(uint32_t)); + } + + if (leftOver > 0) { + value = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET); + + /* + * Copy remaining non-full word bytes. + * (We run ARM as Little Endian) + */ + uint8_t j = 0; + + for (j = 0; j < leftOver; j++) { + data[i + j] = (value >> (j * 8)) & 0xFF; + } + } + + return SD_OK; +} + +/* + * Resets both DAT or CMD line. + */ +int32_t chal_sd_reset_line(CHAL_HANDLE *sd_handle, uint32_t line) +{ + uint32_t control, flag; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + flag = SD4_EMMC_TOP_CTRL1_CMDRST_MASK | SD4_EMMC_TOP_CTRL1_DATRST_MASK; + + if (flag != (line | flag)) + return SD_FAIL; + + control = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + control |= line; + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + control); + + /* reset CMD and DATA line should always work, no need to timed out */ + do { + control = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + } while (control & line); + + return SD_OK; +} + +/* + * Function to be called once a SD command is done to read + * back it's response data. + */ +int32_t chal_sd_get_response(CHAL_HANDLE *sd_handle, uint32_t *resp) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + resp[0] = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_RESP0_OFFSET); + resp[1] = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_RESP2_OFFSET); + resp[2] = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_RESP4_OFFSET); + resp[3] = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_RESP6_OFFSET); + + return SD_OK; +} + +/* + * The function is called to clean all the pending interrupts. + */ +int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sd_handle) +{ + uint32_t status = SD_OK; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + /* Make sure clean all interrupts */ + do { + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET, 0xFFFFFFFF); + SD_US_DELAY(10); + } while (mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET)); + + return status; +} + +/* + * The function returns interrupt status register value. + */ +int32_t chal_sd_get_irq_status(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + return (mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET)); +} + +/* + * The function clears interrupt(s) specified in the mask. + */ +int32_t chal_sd_clear_irq(CHAL_HANDLE *sd_handle, uint32_t mask) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + /* Make sure clean masked interrupts */ + do { + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET, mask); + SD_US_DELAY(10); + } while (mask & + mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET)); + + return SD_OK; +} + +/* + * Description: The function configures the SD host controller. + */ +int32_t chal_sd_config(CHAL_HANDLE *sd_handle, uint32_t speed, uint32_t retry, + uint32_t boundary, uint32_t blkSize, uint32_t dma) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + handle->cfg.speedMode = speed; + handle->cfg.retryLimit = retry; + handle->cfg.dmaBoundary = boundary; + handle->cfg.blockSize = blkSize; + + chal_sd_set_dma(sd_handle, dma); + SD_US_DELAY(100); + chal_sd_set_dma_boundary(handle, boundary); + SD_US_DELAY(100); + + chal_sd_set_speed(sd_handle, speed); + + SD_US_DELAY(100); + return SD_OK; +} + +/* + * Cleans up HC FIFO. + */ +void chal_sd_dump_fifo(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return; + + handle = (struct sd_dev *)sd_handle; + + /* in case there still data in the host buffer */ + while (mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_PSTATE_OFFSET) & 0x800) { + mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET); + }; +} + +/* + * Enable or disable a SD interrupt signal. + */ +void chal_sd_set_irq_signal(CHAL_HANDLE *sd_handle, uint32_t mask, + uint32_t state) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return; + + handle = (struct sd_dev *)sd_handle; + + if (state) + mmio_setbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTREN2_OFFSET, mask); + else + mmio_clrbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTREN2_OFFSET, mask); +} diff --git a/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c b/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c new file mode 100644 index 0000000..9e2c618 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c @@ -0,0 +1,1089 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "bcm_emmc.h" +#include "emmc_chal_types.h" +#include "emmc_csl_sdprot.h" +#include "emmc_chal_sd.h" +#include "emmc_csl_sdcmd.h" +#include "emmc_csl_sd.h" +#include "emmc_pboot_hal_memory_drv.h" + +#define SD_CARD_BUSY 0x80000000 +#define SD_CARD_RETRY_LIMIT 1000 +#define SD_CARD_HIGH_SPEED_PS 13 +#define SD_CHK_HIGH_SPEED_MODE 0x00FFFFF1 +#define SD_SET_HIGH_SPEED_MODE 0x80FFFFF1 +#define SD_MMC_ENABLE_HIGH_SPEED 0x03b90100 //0x03b90103 +#define SD_MMC_8BIT_MODE 0x03b70200 +#define SD_MMC_4BIT_MODE 0x03b70100 +#define SD_MMC_1BIT_MODE 0x03b70000 + +#define SD_MMC_BOOT_8BIT_MODE 0x03b10200 +#define SD_MMC_BOOT_4BIT_MODE 0x03b10100 +#define SD_MMC_BOOT_1BIT_MODE 0x03b10000 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_CNF 0X03B30000 + +#ifdef USE_EMMC_FIP_TOC_CACHE +/* + * Cache size mirrors the size of the global eMMC temp buffer + * which is used for non-image body reads such as headers, ToC etc. + */ +#define CACHE_SIZE ((EMMC_BLOCK_SIZE) * 2) +#define PARTITION_BLOCK_ADDR ((PLAT_FIP_ATTEMPT_OFFSET)/(EMMC_BLOCK_SIZE)) + +static uint32_t cached_partition_block; +static uint8_t cached_block[CACHE_SIZE]; +#endif + +static int set_card_data_width(struct sd_handle *handle, int width); +static int abort_err(struct sd_handle *handle); +static int err_recovery(struct sd_handle *handle, uint32_t errors); +static int xfer_data(struct sd_handle *handle, uint32_t mode, uint32_t addr, + uint32_t length, uint8_t *base); + +int set_boot_config(struct sd_handle *handle, uint32_t config) +{ + return mmc_cmd6(handle, SDIO_HW_EMMC_EXT_CSD_BOOT_CNF | config); +} + +void process_csd_mmc_speed(struct sd_handle *handle, uint32_t csd_mmc_speed) +{ + uint32_t div_ctrl_setting; + + /* CSD field TRAN_SPEED: + * Bits [2:0] 0 = 100 KHz + * 1 = 1 MHz + * 2 = 10 MHz + * 3 = 100 MHz + * 4...7 Reserved. + * Bits [6:3] 0 = Reserved + * 1 = 1.0 + * 2 = 1.2 + * 3 = 1.3 + * 4 = 1.5 + * 5 = 2.0 + * 6 = 2.6 + * 7 = 3.0 + * 8 = 3.5 + * 9 = 4.0 + * A = 4.5 + * B = 5.2 + * C = 5.5 + * D = 6.0 + * E = 7.0 + * F = 8.0 + * For cards supporting version 4.0, 4.1, and 4.2 of the standard, + * the value shall be 20 MHz (0x2A). + * For cards supporting version 4.3 , the value shall be 26 MHz (0x32) + */ + + switch (csd_mmc_speed & 0x7F) { + case 0x2A: + EMMC_TRACE("Speeding up eMMC clock to 20MHz\n"); + div_ctrl_setting = + chal_sd_freq_2_div_ctrl_setting(20 * 1000 * 1000); + break; + case 0x32: + EMMC_TRACE("Speeding up eMMC clock to 26MHz\n"); + div_ctrl_setting = + chal_sd_freq_2_div_ctrl_setting(26 * 1000 * 1000); + break; + default: + /* Unknown */ + return; + } + + chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 0); + + chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 1); + + SD_US_DELAY(1000); +} + + +/* + * The function changes SD/SDIO/MMC card data width if + * the card support configurable data width. The host controller + * and the card has to be in the same bus data width. + */ +int set_card_data_width(struct sd_handle *handle, int width) +{ + uint32_t data_width = 0; + int is_valid_arg = 1; + int rc = SD_FAIL; + char *bitwidth_str = " "; + char *result_str = "failed"; + + switch (width) { +#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT + case SD_BUS_DATA_WIDTH_8BIT: + data_width = SD_MMC_8BIT_MODE; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + bitwidth_str = "8_BIT"; +#endif + break; +#endif + case SD_BUS_DATA_WIDTH_4BIT: + data_width = SD_MMC_4BIT_MODE; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + bitwidth_str = "4_BIT"; +#endif + break; + + case SD_BUS_DATA_WIDTH_1BIT: + data_width = SD_MMC_1BIT_MODE; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + bitwidth_str = "1_BIT"; +#endif + break; + + default: + is_valid_arg = 0; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + bitwidth_str = "unknown"; +#endif + break; + } + + if (is_valid_arg) { + rc = mmc_cmd6(handle, data_width); + if (rc == SD_OK) { +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + result_str = "succeeded"; +#endif + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + width); + } else { +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + result_str = "failed"; +#endif + } + } else { + rc = SD_FAIL; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + result_str = "ignored"; +#endif + } + + VERBOSE("SDIO Data Width(%s) %s.\n", bitwidth_str, result_str); + + return rc; +} + + +/* + * Error handling routine. Does abort data + * transmission if error is found. + */ +static int abort_err(struct sd_handle *handle) +{ + uint32_t present, options, event, rel = 0; + struct sd_resp cmdRsp; + + handle->device->ctrl.argReg = 0; + handle->device->ctrl.cmdIndex = SD_CMD_STOP_TRANSMISSION; + + options = (SD_CMD_STOP_TRANSMISSION << 24) | + (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + chal_sd_send_cmd((CHAL_HANDLE *) handle->device, + handle->device->ctrl.cmdIndex, + handle->device->ctrl.argReg, options); + + event = wait_for_event(handle, + SD4_EMMC_TOP_INTR_CMDDONE_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (event & SD_CMD_ERROR_INT) { + rel = SD_ERROR_NON_RECOVERABLE; + } else { + if (event & SD_DAT_TIMEOUT) { + return SD_ERROR_NON_RECOVERABLE; + } + + chal_sd_get_response((CHAL_HANDLE *) handle->device, + (uint32_t *)&cmdRsp); + + process_cmd_response(handle, handle->device->ctrl.cmdIndex, + cmdRsp.data.r2.rsp1, cmdRsp.data.r2.rsp2, + cmdRsp.data.r2.rsp3, cmdRsp.data.r2.rsp4, + &cmdRsp); + + SD_US_DELAY(2000); + + present = + chal_sd_get_present_status((CHAL_HANDLE *) handle->device); + + if ((present & 0x00F00000) == 0x00F00000) + rel = SD_ERROR_RECOVERABLE; + else + rel = SD_ERROR_NON_RECOVERABLE; + } + + return rel; +} + + +/* + * The function handles real data transmission on both DMA and + * none DMA mode, In None DMA mode the data transfer starts + * when the command is sent to the card, data has to be written + * into the host contollers buffer at this time one block + * at a time. + * In DMA mode, the real data transfer is done by the DMA engine + * and this functions just waits for the data transfer to complete. + * + */ +int process_data_xfer(struct sd_handle *handle, uint8_t *buffer, uint32_t addr, + uint32_t length, int dir) +{ + if (dir == SD_XFER_HOST_TO_CARD) { +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + if (handle->device->cfg.dma == SD_DMA_OFF) { + /* + * In NON DMA mode, the real data xfer starts from here + */ + if (write_buffer(handle, length, buffer)) + return SD_WRITE_ERROR; + } else { + wait_for_event(handle, + SD4_EMMC_TOP_INTR_TXDONE_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus == SD_OK) + return SD_OK; + + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_WRITE_ERROR; + } +#else + return SD_WRITE_ERROR; +#endif + } else { /* SD_XFER_CARD_TO_HOST */ + + if (handle->device->cfg.dma == SD_DMA_OFF) { + /* In NON DMA mode, the real data + * transfer starts from here + */ + if (read_buffer(handle, length, buffer)) + return SD_READ_ERROR; + + } else { /* for DMA mode */ + + /* + * once the data transmission is done + * copy data to the host buffer. + */ + wait_for_event(handle, + SD4_EMMC_TOP_INTR_TXDONE_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus == SD_OK) + return SD_OK; + + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_READ_ERROR; + } + } + return SD_OK; +} + + +/* + * The function sets block size for the next SD/SDIO/MMC + * card read/write command. + */ +int select_blk_sz(struct sd_handle *handle, uint16_t size) +{ + return sd_cmd16(handle, size); +} + + +/* + * The function initalizes the SD/SDIO/MMC/CEATA and detects + * the card according to the flag of detection. + * Once this function is called, the card is put into ready state + * so application can do data transfer to and from the card. + */ +int init_card(struct sd_handle *handle, int detection) +{ + /* + * After Reset, eMMC comes up in 1 Bit Data Width by default. + * Set host side to match. + */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_1BIT); + +#ifdef USE_EMMC_FIP_TOC_CACHE + cached_partition_block = 0; +#endif + handle->device->ctrl.present = 0; /* init card present to be no card */ + + init_mmc_card(handle); + + handle->device->ctrl.present = 1; /* card is detected */ + + /* switch the data width back */ + if (handle->card->type != SD_CARD_MMC) + return SD_FAIL; + + /* + * Dynamically set Data Width to highest supported value. + * Try different data width settings (highest to lowest). + * Verify each setting by reading EXT_CSD and comparing + * against the EXT_CSD contents previously read in call to + * init_mmc_card() earlier. Stop at first verified data width + * setting. + */ + { +#define EXT_CSD_PROPERTIES_SECTION_START_INDEX 192 +#define EXT_CSD_PROPERTIES_SECTION_END_INDEX 511 + uint8_t buffer[EXT_CSD_SIZE]; +#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT + /* Try 8 Bit Data Width */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_8BIT); + if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_8BIT)) && + (!mmc_cmd8(handle, buffer)) && + (!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX], + &(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]), + EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1))) + + return SD_OK; +#endif + /* Fall back to 4 Bit Data Width */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_4BIT); + if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_4BIT)) && + (!mmc_cmd8(handle, buffer)) && + (!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX], + &(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]), + EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1))) + + return SD_OK; + + /* Fall back to 1 Bit Data Width */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_1BIT); + /* Just use 1 Bit Data Width then. */ + if (!set_card_data_width(handle, SD_BUS_DATA_WIDTH_1BIT)) + return SD_OK; + + } + return SD_CARD_INIT_ERROR; +} + + +/* + * The function handles MMC/CEATA card initalization. + */ +int init_mmc_card(struct sd_handle *handle) +{ + uint32_t ocr = 0, newOcr, rc, limit = 0; + uint32_t cmd1_option = 0x40300000; + uint32_t sec_count; + + handle->card->type = SD_CARD_MMC; + + do { + SD_US_DELAY(1000); + newOcr = 0; + ocr = 0; + rc = sd_cmd1(handle, cmd1_option, &newOcr); + limit++; + + if (rc == SD_OK) + ocr = newOcr; + + } while (((ocr & SD_CARD_BUSY) == 0) && (limit < SD_CARD_RETRY_LIMIT)); + + if (limit >= SD_CARD_RETRY_LIMIT) { + handle->card->type = SD_CARD_UNKNOWN; + EMMC_TRACE("CMD1 Timeout: Device is not ready\n"); + return SD_CARD_UNKNOWN; + } + + /* Save the ocr register */ + handle->device->ctrl.ocr = ocr; + + /* Ready State */ + rc = sd_cmd2(handle); + if (rc != SD_OK) { + handle->card->type = SD_CARD_UNKNOWN; + return SD_CARD_UNKNOWN; + } + + rc = sd_cmd3(handle); + if (rc != SD_OK) { + handle->card->type = SD_CARD_UNKNOWN; + return SD_CARD_UNKNOWN; + } + /* read CSD */ + rc = sd_cmd9(handle, &emmc_global_vars_ptr->cardData); + if (rc != SD_OK) { + handle->card->type = SD_CARD_UNKNOWN; + return SD_CARD_UNKNOWN; + } + + /* Increase clock frequency according to what the card advertises */ + EMMC_TRACE("From CSD... cardData.csd.mmc.speed = 0x%X\n", + emmc_global_vars_ptr->cardData.csd.mmc.speed); + process_csd_mmc_speed(handle, + emmc_global_vars_ptr->cardData.csd.mmc.speed); + + /* goto transfer mode */ + rc = sd_cmd7(handle, handle->device->ctrl.rca); + if (rc != SD_OK) { + handle->card->type = SD_CARD_UNKNOWN; + return SD_CARD_UNKNOWN; + } + + rc = mmc_cmd8(handle, emmc_global_buf_ptr->u.Ext_CSD_storage); + if (rc == SD_OK) { + /* calcul real capacity */ + sec_count = emmc_global_buf_ptr->u.Ext_CSD_storage[212] | + emmc_global_buf_ptr->u.Ext_CSD_storage[213] << 8 | + emmc_global_buf_ptr->u.Ext_CSD_storage[214] << 16 | + emmc_global_buf_ptr->u.Ext_CSD_storage[215] << 24; + + EMMC_TRACE("Device density = %ldMBytes\n", + handle->card->size / (1024 * 1024)); + + if (sec_count > 0) { + handle->card->size = (uint64_t)sec_count * 512; + + EMMC_TRACE("Updated Device density = %ldMBytes\n", + handle->card->size / (1024 * 1024)); + } + + if (sec_count > (2u * 1024 * 1024 * 1024) / 512) { + handle->device->ctrl.ocr |= SD_CARD_HIGH_CAPACITY; + handle->device->cfg.blockSize = 512; + } + + if (handle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) + EMMC_TRACE("Sector addressing\n"); + else + EMMC_TRACE("Byte addressing\n"); + + EMMC_TRACE("Ext_CSD_storage[162]: 0x%02X Ext_CSD_storage[179]: 0x%02X\n", + emmc_global_buf_ptr->u.Ext_CSD_storage[162], + emmc_global_buf_ptr->u.Ext_CSD_storage[179]); + } + + return handle->card->type; +} + + +/* + * The function send reset command to the card. + * The card will be in ready status after the reset. + */ +int reset_card(struct sd_handle *handle) +{ + int res = SD_OK; + + /* on reset, card's RCA should return to 0 */ + handle->device->ctrl.rca = 0; + + res = sd_cmd0(handle); + + if (res != SD_OK) + return SD_RESET_ERROR; + + return res; +} + + +/* + * The function sends command to the card and starts + * data transmission. + */ +static int xfer_data(struct sd_handle *handle, + uint32_t mode, + uint32_t addr, uint32_t length, uint8_t *base) +{ + int rc = SD_OK; + + VERBOSE("XFER: dest: 0x%" PRIx64 ", addr: 0x%x, size: 0x%x bytes\n", + (uint64_t)base, addr, length); + + if ((length / handle->device->cfg.blockSize) > 1) { + if (mode == SD_OP_READ) { + inv_dcache_range((uintptr_t)base, (uint64_t)length); + rc = sd_cmd18(handle, addr, length, base); + } else { +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + flush_dcache_range((uintptr_t)base, (uint64_t)length); + rc = sd_cmd25(handle, addr, length, base); +#else + rc = SD_DATA_XFER_ERROR; +#endif + } + } else { + if (mode == SD_OP_READ) { + inv_dcache_range((uintptr_t)base, (uint64_t)length); + rc = sd_cmd17(handle, addr, + handle->device->cfg.blockSize, base); + } else { +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + flush_dcache_range((uintptr_t)base, (uint64_t)length); + rc = sd_cmd24(handle, addr, + handle->device->cfg.blockSize, base); +#else + rc = SD_DATA_XFER_ERROR; +#endif + } + } + + if (rc != SD_OK) + return SD_DATA_XFER_ERROR; + + return SD_OK; +} + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks) +{ + uint32_t end_addr; + + INFO("ERASE: addr: 0x%x, num of sectors: 0x%x\n", addr, blocks); + + if (sd_cmd35(handle, addr) != SD_OK) + return SD_FAIL; + + end_addr = addr + blocks - 1; + if (sd_cmd36(handle, end_addr) != SD_OK) + return SD_FAIL; + + if (sd_cmd38(handle) != SD_OK) + return SD_FAIL; + + return SD_OK; +} +#endif + +/* + * The function reads block data from a card. + */ +#ifdef USE_EMMC_FIP_TOC_CACHE +int read_block(struct sd_handle *handle, + uint8_t *dst, uint32_t addr, uint32_t len) +{ + int rel = SD_OK; + + /* + * Avoid doing repeated reads of the partition block + * by caching. + */ + if (cached_partition_block && + addr == PARTITION_BLOCK_ADDR && + len == CACHE_SIZE) { + memcpy(dst, cached_block, len); + } else { + rel = xfer_data(handle, SD_OP_READ, addr, len, dst); + + if (len == CACHE_SIZE && addr == PARTITION_BLOCK_ADDR) { + cached_partition_block = 1; + memcpy(cached_block, dst, len); + } + } + + return rel; +} +#else +int read_block(struct sd_handle *handle, + uint8_t *dst, uint32_t addr, uint32_t len) +{ + return xfer_data(handle, SD_OP_READ, addr, len, dst); +} +#endif + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + +/* + * The function writes block data to a card. + */ +int write_block(struct sd_handle *handle, + uint8_t *src, uint32_t addr, uint32_t len) +{ + int rel = SD_OK; + + /* + * Current HC has problem to get response of cmd16 after cmd12, + * the delay is necessary to sure the next cmd16 will not be timed out. + * The delay has to be at least 4 ms. + * The code removed cmd16 and use cmd13 to get card status before + * sending cmd18 or cmd25 to make sure the card is ready and thus + * no need to have delay here. + */ + + rel = xfer_data(handle, SD_OP_WRITE, addr, len, src); + + EMMC_TRACE("wr_blk addr:0x%08X src:0x%08X len:0x%08X result:%d\n", + addr, src, len, rel); + + return rel; +} + + +/* + * The function is called to write one block data directly to + * a card's data buffer. + * it is used in Non-DMA mode for card data transmission. + */ +int write_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data) +{ + uint32_t rem, blockSize, event; + uint8_t *pData = data; + + blockSize = handle->device->cfg.blockSize; + rem = length; + + if (rem == 0) + return SD_OK; + + while (rem > 0) { + + event = wait_for_event(handle, + SD4_EMMC_TOP_INTR_BWRDY_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus) { + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_WRITE_ERROR; + } + + if (rem >= blockSize) + chal_sd_write_buffer((CHAL_HANDLE *) handle->device, + blockSize, pData); + else + chal_sd_write_buffer((CHAL_HANDLE *) handle->device, + rem, pData); + + if (rem > blockSize) { + rem -= blockSize; + pData += blockSize; + } else { + pData += rem; + rem = 0; + } + } + + if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) != + SD4_EMMC_TOP_INTR_TXDONE_MASK) { + event = wait_for_event(handle, + SD4_EMMC_TOP_INTR_TXDONE_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus != SD_OK) { + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_WRITE_ERROR; + } + } else { + handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK; + } + + return SD_OK; +} +#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */ + + +/* + * The function is called to read maximal one block data + * directly from a card + * It is used in Non-DMA mode for card data transmission. + */ +int read_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data) +{ + uint32_t rem, blockSize, event = 0; + uint8_t *pData = data; + + blockSize = handle->device->cfg.blockSize; + rem = length; + + if (rem == 0) + return SD_OK; + + while (rem > 0) { + event = wait_for_event(handle, + SD4_EMMC_TOP_INTR_BRRDY_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus) { + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_READ_ERROR; + } + + if (rem >= blockSize) + chal_sd_read_buffer((CHAL_HANDLE *) handle->device, + blockSize, pData); + else + chal_sd_read_buffer((CHAL_HANDLE *) handle->device, rem, + pData); + + if (rem > blockSize) { + rem -= blockSize; + pData += blockSize; + } else { + pData += rem; + rem = 0; + } + } + + /* In case, there are extra data in the SD FIFO, just dump them. */ + chal_sd_dump_fifo((CHAL_HANDLE *) handle->device); + + if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) != + SD4_EMMC_TOP_INTR_TXDONE_MASK) { + event = wait_for_event(handle, SD4_EMMC_TOP_INTR_TXDONE_MASK, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus) { + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_READ_ERROR; + } + } else { + handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK; + } + + return SD_OK; +} + + +/* + * Error handling routine. + * The function just reset the DAT + * and CMD line if an error occures during data transmission. + */ +int check_error(struct sd_handle *handle, uint32_t ints) +{ + uint32_t rel; + + chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device, + SD_ERR_INTERRUPTS, 0); + + if (ints & SD4_EMMC_TOP_INTR_CMDERROR_MASK) { + + chal_sd_reset_line((CHAL_HANDLE *) handle->device, + SD4_EMMC_TOP_CTRL1_CMDRST_MASK); + rel = abort_err(handle); + + chal_sd_reset_line((CHAL_HANDLE *) handle->device, + SD4_EMMC_TOP_CTRL1_DATRST_MASK); + chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device, + SD_ERR_INTERRUPTS, 1); + + return (rel == SD_ERROR_NON_RECOVERABLE) ? + SD_ERROR_NON_RECOVERABLE : SD_ERROR_RECOVERABLE; + } else { + rel = err_recovery(handle, ints); + } + + chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device, + SD_ERR_INTERRUPTS, 1); + + return rel; +} + + +/* + * Error recovery routine. + * Try to recover from the error. + */ +static int err_recovery(struct sd_handle *handle, uint32_t errors) +{ + uint32_t rel = 0; + + /* + * In case of timeout error, the cmd line and data line maybe + * still active or stuck at atcitve so it is needed to reset + * either data line or cmd line to make sure a new cmd can be sent. + */ + + if (errors & SD_CMD_ERROR_INT) + chal_sd_reset_line((CHAL_HANDLE *) handle->device, + SD4_EMMC_TOP_CTRL1_CMDRST_MASK); + + if (errors & SD_DAT_ERROR_INT) + chal_sd_reset_line((CHAL_HANDLE *) handle->device, + SD4_EMMC_TOP_CTRL1_DATRST_MASK); + + /* Abort transaction by sending out stop command */ + if ((handle->device->ctrl.cmdIndex == 18) || + (handle->device->ctrl.cmdIndex == 25)) + rel = abort_err(handle); + + return rel; +} + + +/* + * The function is called to read one block data directly from a card. + * It is used in Non-DMA mode for card data transmission. + */ +int process_cmd_response(struct sd_handle *handle, + uint32_t cmdIndex, + uint32_t rsp0, + uint32_t rsp1, + uint32_t rsp2, uint32_t rsp3, struct sd_resp *resp) +{ + int result = SD_OK; + + /* R6 */ + uint32_t rca = (rsp0 >> 16) & 0xffff; + uint32_t cardStatus = rsp0; + + /* R4 */ + uint32_t cBit = (rsp0 >> 31) & 0x1; + uint32_t funcs = (rsp0 >> 28) & 0x7; + uint32_t memPresent = (rsp0 >> 27) & 0x1; + + resp->r1 = 0x3f; + resp->cardStatus = cardStatus; + + if (cmdIndex == SD_CMD_IO_SEND_OP_COND) { + resp->data.r4.cardReady = cBit; + resp->data.r4.funcs = funcs; + resp->data.r4.memPresent = memPresent; + resp->data.r4.ocr = cardStatus; + } + + if (cmdIndex == SD_CMD_MMC_SET_RCA) { + resp->data.r6.rca = rca; + resp->data.r6.cardStatus = cardStatus & 0xFFFF; + } + + if (cmdIndex == SD_CMD_SELECT_DESELECT_CARD) { + resp->data.r7.rca = rca; + } + + if (cmdIndex == SD_CMD_IO_RW_DIRECT) { + if (((rsp0 >> 16) & 0xffff) != 0) + result = SD_CMD_ERR_INVALID_RESPONSE; + + resp->data.r5.data = rsp0 & 0xff; + } + + if (cmdIndex == SD_CMD_IO_RW_EXTENDED) { + if (((rsp0 >> 16) & 0xffff) != 0) + result = SD_CMD_ERR_INVALID_RESPONSE; + + resp->data.r5.data = rsp0 & 0xff; + } + + if (cmdIndex == SD_ACMD_SD_SEND_OP_COND || + cmdIndex == SD_CMD_SEND_OPCOND) + resp->data.r3.ocr = cardStatus; + + if (cmdIndex == SD_CMD_SEND_CSD || + cmdIndex == SD_CMD_SEND_CID || + cmdIndex == SD_CMD_ALL_SEND_CID) { + resp->data.r2.rsp4 = rsp3; + resp->data.r2.rsp3 = rsp2; + resp->data.r2.rsp2 = rsp1; + resp->data.r2.rsp1 = rsp0; + } + + if ((cmdIndex == SD_CMD_READ_EXT_CSD) && + (handle->card->type == SD_CARD_SD)) { + if ((resp->cardStatus & 0xAA) != 0xAA) { + result = SD_CMD_ERR_INVALID_RESPONSE; + } + } + + return result; +} + + +/* + * The function sets DMA buffer and data length, process + * block size and the number of blocks to be transferred. + * It returns the DMA buffer address. + * It copies dma data from user buffer to the DMA buffer + * if the operation is to write data to the SD card. + */ +void data_xfer_setup(struct sd_handle *handle, uint8_t *data, uint32_t length, + int dir) +{ + chal_sd_setup_xfer((CHAL_HANDLE *)handle->device, data, length, dir); +} + + +/* + * The function does soft reset the host SD controller. After + * the function call all host controller's register are reset + * to default vallue; + * + * Note This function only resets the host controller it does not + * reset the controller's handler. + */ +int reset_host_ctrl(struct sd_handle *handle) +{ + chal_sd_stop(); + + return SD_OK; +} + +static void pstate_log(struct sd_handle *handle) +{ + ERROR("PSTATE: 0x%x\n", mmio_read_32 + (handle->device->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_PSTATE_SD4_OFFSET)); + ERROR("ERRSTAT: 0x%x\n", mmio_read_32 + (handle->device->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_ERRSTAT_OFFSET)); +} + +/* + * The function waits for one or a group of interrupts specified + * by mask. The function returns if any one the interrupt status + * is set. If interrupt mode is not enabled then it will poll + * the interrupt status register until a interrupt status is set + * an error interrupt happens. If interrupt mode is enabled then + * this function should be called after the interrupt + * is received by ISR routine. + */ +uint32_t wait_for_event(struct sd_handle *handle, + uint32_t mask, uint32_t retry) +{ + uint32_t regval, cmd12, time = 0; + + handle->device->ctrl.cmdStatus = 0; /* no error */ + EMMC_TRACE("%s %d mask:0x%x timeout:%d irq_status:0x%x\n", + __func__, __LINE__, mask, retry, + chal_sd_get_irq_status((CHAL_HANDLE *)handle->device)); + + /* Polling mode */ + do { + regval = chal_sd_get_irq_status((CHAL_HANDLE *)handle->device); + + if (regval & SD4_EMMC_TOP_INTR_DMAIRQ_MASK) { + chal_sd_set_dma_addr((CHAL_HANDLE *)handle->device, + (uintptr_t) + chal_sd_get_dma_addr((CHAL_HANDLE *) + handle->device)); + chal_sd_clear_irq((CHAL_HANDLE *)handle->device, + SD4_EMMC_TOP_INTR_DMAIRQ_MASK); + } + + if (time++ > retry) { + ERROR("EMMC: No response (cmd%d) after %dus.\n", + handle->device->ctrl.cmdIndex, + time * EMMC_WFE_RETRY_DELAY_US); + handle->device->ctrl.cmdStatus = SD_CMD_MISSING; + pstate_log(handle); + ERROR("EMMC: INT[0x%x]\n", regval); + break; + } + + if (regval & SD4_EMMC_TOP_INTR_CTOERR_MASK) { + ERROR("EMMC: Cmd%d timeout INT[0x%x]\n", + handle->device->ctrl.cmdIndex, regval); + handle->device->ctrl.cmdStatus = + SD4_EMMC_TOP_INTR_CTOERR_MASK; + pstate_log(handle); + break; + } + if (regval & SD_CMD_ERROR_FLAGS) { + ERROR("EMMC: Cmd%d error INT[0x%x]\n", + handle->device->ctrl.cmdIndex, regval); + handle->device->ctrl.cmdStatus = SD_CMD_ERROR_FLAGS; + pstate_log(handle); + break; + } + + cmd12 = chal_sd_get_atuo12_error((CHAL_HANDLE *)handle->device); + if (cmd12) { + ERROR("EMMC: Cmd%d auto cmd12 err:0x%x\n", + handle->device->ctrl.cmdIndex, cmd12); + handle->device->ctrl.cmdStatus = cmd12; + pstate_log(handle); + break; + } + + if (SD_DATA_ERROR_FLAGS & regval) { + ERROR("EMMC: Data for cmd%d error, INT[0x%x]\n", + handle->device->ctrl.cmdIndex, regval); + handle->device->ctrl.cmdStatus = + (SD_DATA_ERROR_FLAGS & regval); + pstate_log(handle); + break; + } + + if ((regval & mask) == 0) + udelay(EMMC_WFE_RETRY_DELAY_US); + + } while ((regval & mask) == 0); + + /* clear the interrupt since it is processed */ + chal_sd_clear_irq((CHAL_HANDLE *)handle->device, (regval & mask)); + + return (regval & mask); +} + +int32_t set_config(struct sd_handle *handle, uint32_t speed, uint32_t retry, + uint32_t dma, uint32_t dmaBound, uint32_t blkSize, + uint32_t wfe_retry) +{ + int32_t rel = 0; + + if (handle == NULL) + return SD_FAIL; + + handle->device->cfg.wfe_retry = wfe_retry; + + rel = chal_sd_config((CHAL_HANDLE *)handle->device, speed, retry, + dmaBound, blkSize, dma); + return rel; + +} + +int mmc_cmd1(struct sd_handle *handle) +{ + uint32_t newOcr, res; + uint32_t cmd1_option = MMC_OCR_OP_VOLT | MMC_OCR_SECTOR_ACCESS_MODE; + + /* + * After Reset, eMMC comes up in 1 Bit Data Width by default. + * Set host side to match. + */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_1BIT); + +#ifdef USE_EMMC_FIP_TOC_CACHE + cached_partition_block = 0; +#endif + handle->device->ctrl.present = 0; /* init card present to be no card */ + + handle->card->type = SD_CARD_MMC; + + res = sd_cmd1(handle, cmd1_option, &newOcr); + + if (res != SD_OK) { + EMMC_TRACE("CMD1 Timeout: Device is not ready\n"); + res = SD_CARD_UNKNOWN; + } + return res; +} diff --git a/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c b/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c new file mode 100644 index 0000000..c62886c --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c @@ -0,0 +1,842 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "bcm_emmc.h" +#include "emmc_chal_types.h" +#include "emmc_chal_sd.h" +#include "emmc_csl_sdprot.h" +#include "emmc_csl_sdcmd.h" +#include "emmc_csl_sd.h" +#include "emmc_chal_sd.h" +#include "emmc_pboot_hal_memory_drv.h" + +int sd_cmd0(struct sd_handle *handle) +{ + int res; + uint32_t argument = 0x0; /* Go to IDLE state. */ + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_GO_IDLE_STATE, argument, 0, NULL); + + if (res == SD_OK) { + /* Clear all other interrupts */ + chal_sd_clear_irq((void *)handle->device, 0xffffffff); + } + + return res; +} + +int sd_cmd1(struct sd_handle *handle, uint32_t ocr, uint32_t *ocr_output) +{ + int res; + uint32_t options; + struct sd_resp resp; + + options = SD_CMDR_RSP_TYPE_R3_4 << SD_CMDR_RSP_TYPE_S; + + if (ocr_output == NULL) { + EMMC_TRACE("Invalid args\n"); + return SD_FAIL; + } + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SEND_OPCOND, ocr, options, &resp); + + if (res == SD_OK) + *ocr_output = resp.data.r3.ocr; + + return res; +} + +int sd_cmd2(struct sd_handle *handle) +{ + uint32_t options; + struct sd_resp resp; + + /* send cmd and parse result */ + options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S; + + return send_cmd(handle, SD_CMD_ALL_SEND_CID, 0, options, &resp); +} + +int sd_cmd3(struct sd_handle *handle) +{ + int res; + uint32_t options = 0; + uint32_t argument; + struct sd_resp resp; + + /* use non zero and non 0x1 value for rca */ + handle->device->ctrl.rca = 0x5; + argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_MMC_SET_RCA, argument, options, &resp); + + if (res != SD_OK) + handle->device->ctrl.rca = 0; + + return res; +} + +int sd_cmd7(struct sd_handle *handle, uint32_t rca) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + argument = (rca << SD_CMD7_ARG_RCA_SHIFT); + + /* + * Response to CMD7 is: + * R1 while selectiing from Stand-By State to Transfer State + * R1b while selecting from Disconnected State to Programming State. + * + * In this driver, we only issue a CMD7 once, to go to transfer mode + * during init_mmc_card(). + */ + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SELECT_DESELECT_CARD, argument, options, + &resp); + + if (res == SD_OK) + /* Clear all other interrupts */ + chal_sd_clear_irq((void *)handle->device, 0xffffffff); + + return res; +} + + +/* + * CMD8 Get CSD_EXT + */ +int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg) +{ + uint32_t res, options; + struct sd_resp resp; + + data_xfer_setup(handle, extCsdReg, CEATA_EXT_CSDBLOCK_SIZE, + SD_XFER_CARD_TO_HOST); + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_READ_EXT_CSD, 0, options, &resp); + + if (res == SD_OK) + res = process_data_xfer(handle, extCsdReg, 0, + CEATA_EXT_CSDBLOCK_SIZE, + SD_XFER_CARD_TO_HOST); + + return res; +} + +int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card) +{ + int res; + uint32_t argument, options, iBlkNum, multiFactor = 1; + uint32_t maxReadBlockLen = 1, maxWriteBlockLen = 1; + struct sd_resp resp; + + argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; + + options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SEND_CSD, argument, options, &resp); + + if (res != SD_OK) + return res; + + if (handle->card->type == SD_CARD_MMC) { + card->csd.mmc.structure = (resp.data.r2.rsp4 >> 22) & 0x3; + card->csd.mmc.csdSpecVer = (resp.data.r2.rsp4 >> 18) & 0x0f; + card->csd.mmc.taac = (resp.data.r2.rsp4 >> 8) & 0xff; + card->csd.mmc.nsac = resp.data.r2.rsp4 & 0xff; + card->csd.mmc.speed = resp.data.r2.rsp3 >> 24; + card->csd.mmc.classes = (resp.data.r2.rsp3 >> 12) & 0xfff; + card->csd.mmc.rdBlkLen = (resp.data.r2.rsp3 >> 8) & 0xf; + card->csd.mmc.rdBlkPartial = (resp.data.r2.rsp3 >> 7) & 0x01; + card->csd.mmc.wrBlkMisalign = (resp.data.r2.rsp3 >> 6) & 0x1; + card->csd.mmc.rdBlkMisalign = (resp.data.r2.rsp3 >> 5) & 0x1; + card->csd.mmc.dsr = (resp.data.r2.rsp2 >> 4) & 0x01; + card->csd.mmc.size = + ((resp.data.r2.rsp3 & 0x3) << 10) + + ((resp.data.r2.rsp2 >> 22) & 0x3ff); + card->csd.mmc.vddRdCurrMin = (resp.data.r2.rsp2 >> 19) & 0x7; + card->csd.mmc.vddRdCurrMax = (resp.data.r2.rsp2 >> 16) & 0x7; + card->csd.mmc.vddWrCurrMin = (resp.data.r2.rsp2 >> 13) & 0x7; + card->csd.mmc.vddWrCurrMax = (resp.data.r2.rsp2 >> 10) & 0x7; + card->csd.mmc.devSizeMulti = (resp.data.r2.rsp2 >> 7) & 0x7; + card->csd.mmc.eraseGrpSize = (resp.data.r2.rsp2 >> 2) & 0x1f; + card->csd.mmc.eraseGrpSizeMulti = + ((resp.data.r2.rsp2 & 0x3) << 3) + + ((resp.data.r2.rsp1 >> 29) & 0x7); + card->csd.mmc.wrProtGroupSize = + ((resp.data.r2.rsp1 >> 24) & 0x1f); + card->csd.mmc.wrProtGroupEnable = + (resp.data.r2.rsp1 >> 23) & 0x1; + card->csd.mmc.manuDefEcc = (resp.data.r2.rsp1 >> 21) & 0x3; + card->csd.mmc.wrSpeedFactor = (resp.data.r2.rsp1 >> 18) & 0x7; + card->csd.mmc.wrBlkLen = (resp.data.r2.rsp1 >> 14) & 0xf; + card->csd.mmc.wrBlkPartial = (resp.data.r2.rsp1 >> 13) & 0x1; + card->csd.mmc.protAppl = (resp.data.r2.rsp1 >> 8) & 0x1; + card->csd.mmc.copyFlag = (resp.data.r2.rsp1 >> 7) & 0x1; + card->csd.mmc.permWrProt = (resp.data.r2.rsp1 >> 6) & 0x1; + card->csd.mmc.tmpWrProt = (resp.data.r2.rsp1 >> 5) & 0x1; + card->csd.mmc.fileFormat = (resp.data.r2.rsp1 >> 4) & 0x03; + card->csd.mmc.eccCode = resp.data.r2.rsp1 & 0x03; + maxReadBlockLen <<= card->csd.mmc.rdBlkLen; + maxWriteBlockLen <<= card->csd.mmc.wrBlkLen; + + iBlkNum = card->csd.mmc.size + 1; + multiFactor = (1 << (card->csd.mmc.devSizeMulti + 2)); + + handle->card->size = + iBlkNum * multiFactor * (1 << card->csd.mmc.rdBlkLen); + } + + handle->card->maxRdBlkLen = maxReadBlockLen; + handle->card->maxWtBlkLen = maxWriteBlockLen; + + if (handle->card->size < 0xA00000) { + /* + * 10MB Too small size mean, cmd9 response is wrong, + * Use default value 1G + */ + handle->card->size = 0x40000000; + handle->card->maxRdBlkLen = 512; + handle->card->maxWtBlkLen = 512; + } + + if ((handle->card->maxRdBlkLen > 512) || + (handle->card->maxWtBlkLen > 512)) { + handle->card->maxRdBlkLen = 512; + handle->card->maxWtBlkLen = 512; + } else if ((handle->card->maxRdBlkLen == 0) || + (handle->card->maxWtBlkLen == 0)) { + handle->card->maxRdBlkLen = 512; + handle->card->maxWtBlkLen = 512; + } + + handle->device->cfg.blockSize = handle->card->maxRdBlkLen; + + return res; +} + +int sd_cmd13(struct sd_handle *handle, uint32_t *status) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SEND_STATUS, argument, options, &resp); + + if (res == SD_OK) { + *status = resp.cardStatus; + } + + return res; +} + +int sd_cmd16(struct sd_handle *handle, uint32_t length) +{ + int res; + uint32_t argument, options, ntry; + struct sd_resp resp; + + argument = length; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd13 failed before cmd16: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd16\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + + } while (1); + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SET_BLOCKLEN, argument, options, &resp); + + return res; +} + +int sd_cmd17(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer) +{ + int res; + uint32_t argument, options, ntry; + struct sd_resp resp; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd17: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd17\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + + } while (1); + + data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST); + + /* send cmd and parse result */ + argument = addr; + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + res = send_cmd(handle, SD_CMD_READ_SINGLE_BLOCK, argument, options, + &resp); + + if (res != SD_OK) + return res; + + res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST); + + return res; +} + +int sd_cmd18(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer) +{ + int res; + uint32_t argument, options, ntry; + struct sd_resp resp; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd18: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd18\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + } while (1); + + data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST); + + argument = addr; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | + SD4_EMMC_TOP_CMD_MSBS_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK | + SD4_EMMC_TOP_CMD_BCEN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK | + BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT); + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_READ_MULTIPLE_BLOCK, argument, options, + &resp); + + if (res != SD_OK) + return res; + + res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST); + + return res; +} + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +static int card_sts_resp(struct sd_handle *handle, uint32_t *status) +{ + int res; + uint32_t ntry = 0; + + do { + res = sd_cmd13(handle, status); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd35: rca 0x%0x, return %d\n", + handle->device->ctrl.rca, res); + return res; + } + + if (*status & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd35\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + } while (1); + + return SD_OK; +} + +int sd_cmd35(struct sd_handle *handle, uint32_t start) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + res = card_sts_resp(handle, &resp.cardStatus); + if (res != SD_OK) + return res; + + argument = start; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_ERASE_GROUP_START, + argument, options, &resp); + + if (res != SD_OK) + return res; + + return res; +} + +int sd_cmd36(struct sd_handle *handle, uint32_t end) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + res = card_sts_resp(handle, &resp.cardStatus); + if (res != SD_OK) + return res; + + argument = end; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_ERASE_GROUP_END, + argument, options, &resp); + + if (res != SD_OK) + return res; + + return res; +} + +int sd_cmd38(struct sd_handle *handle) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + res = card_sts_resp(handle, &resp.cardStatus); + if (res != SD_OK) + return res; + + argument = 0; + + options = (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_ERASE, argument, options, &resp); + + if (res != SD_OK) + return res; + + return res; +} +#endif + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + +int sd_cmd24(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer) +{ + int res; + uint32_t argument, options, ntry; + struct sd_resp resp; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd24: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, &resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd24\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + + } while (1); + + data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD); + + argument = addr; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_WRITE_BLOCK, argument, options, &resp); + + if (res != SD_OK) + return res; + + res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD); + + return res; +} + +int sd_cmd25(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer) +{ + int res = SD_OK; + uint32_t argument, options, ntry; + struct sd_resp resp; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd25: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, &resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd25\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + } while (1); + + data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD); + + argument = addr; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_MSBS_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_BCEN_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT); + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_WRITE_MULTIPLE_BLOCK, + argument, options, &resp); + + if (res != SD_OK) + return res; + + res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD); + + return res; +} +#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */ + +int mmc_cmd6(struct sd_handle *handle, uint32_t argument) +{ + int res; + uint32_t options; + struct sd_resp resp; + + options = SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + EMMC_TRACE("Sending CMD6 with argument 0x%X\n", argument); + + /* send cmd and parse result */ + res = send_cmd(handle, SD_ACMD_SET_BUS_WIDTH, argument, options, &resp); + + /* + * For R1b type response: + * controller issues a COMMAND COMPLETE interrupt when the R1 + * response is received, + * then controller monitors DAT0 for busy status, + * controller issues a TRANSFER COMPLETE interrupt when busy signal + * clears. + */ + wait_for_event(handle, + SD4_EMMC_TOP_INTR_TXDONE_MASK | SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (res == SD_OK) { + /* Check result of Cmd6 using Cmd13 to check card status */ + + /* Check status using Cmd13 */ + res = sd_cmd13(handle, &resp.cardStatus); + + if (res == SD_OK) { + /* Check bit 7 (SWITCH_ERROR) in card status */ + if ((resp.cardStatus & 0x80) != 0) { + EMMC_TRACE("cmd6 failed: SWITCH_ERROR\n"); + res = SD_FAIL; + } + } else { + EMMC_TRACE("cmd13 failed after cmd6: "); + EMMC_TRACE("rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, resp.cardStatus); + } + } + + return res; +} + + +#define SD_BUSY_CHECK 0x00203000 +#define DAT0_LEVEL_MASK 0x100000 /* bit20 in PSTATE */ +#define DEV_BUSY_TIMEOUT 600000 /* 60 Sec : 600000 * 100us */ + +int send_cmd(struct sd_handle *handle, uint32_t cmdIndex, uint32_t argument, + uint32_t options, struct sd_resp *resp) +{ + int status = SD_OK; + uint32_t event = 0, present, timeout = 0, retry = 0, mask = 3; + uint32_t temp_resp[4]; + + if (handle == NULL) { + EMMC_TRACE("Invalid handle for cmd%d\n", cmdIndex); + return SD_INVALID_HANDLE; + } + + mask = (SD_BUSY_CHECK & options) ? 3 : 1; + +RETRY_WRITE_CMD: + do { + /* Make sure it is ok to send command */ + present = + chal_sd_get_present_status((CHAL_HANDLE *) handle->device); + timeout++; + + if (present & mask) + SD_US_DELAY(1000); + else + break; + + } while (timeout < EMMC_BUSY_CMD_TIMEOUT_MS); + + if (timeout >= EMMC_BUSY_CMD_TIMEOUT_MS) { + status = SD_CMD_MISSING; + EMMC_TRACE("cmd%d timedout %dms\n", cmdIndex, timeout); + } + + /* Reset both DAT and CMD line if only of them are stuck */ + if (present & mask) + check_error(handle, SD4_EMMC_TOP_INTR_CMDERROR_MASK); + + handle->device->ctrl.argReg = argument; + chal_sd_send_cmd((CHAL_HANDLE *) handle->device, cmdIndex, + handle->device->ctrl.argReg, options); + + handle->device->ctrl.cmdIndex = cmdIndex; + + event = wait_for_event(handle, + (SD4_EMMC_TOP_INTR_CMDDONE_MASK | + SD_ERR_INTERRUPTS), + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus == SD_CMD_MISSING) { + retry++; + + if (retry >= handle->device->cfg.retryLimit) { + status = SD_CMD_MISSING; + EMMC_TRACE("cmd%d retry reaches the limit %d\n", + cmdIndex, retry); + } else { + /* reset both DAT & CMD line if one of them is stuck */ + present = chal_sd_get_present_status((CHAL_HANDLE *) + handle->device); + + if (present & mask) + check_error(handle, + SD4_EMMC_TOP_INTR_CMDERROR_MASK); + + EMMC_TRACE("cmd%d retry %d PSTATE[0x%08x]\n", + cmdIndex, retry, + chal_sd_get_present_status((CHAL_HANDLE *) + handle->device)); + goto RETRY_WRITE_CMD; + } + } + + if (handle->device->ctrl.cmdStatus == SD_OK) { + if (resp != NULL) { + status = + chal_sd_get_response((CHAL_HANDLE *) handle->device, + temp_resp); + process_cmd_response(handle, + handle->device->ctrl.cmdIndex, + temp_resp[0], temp_resp[1], + temp_resp[2], temp_resp[3], resp); + } + + /* Check Device busy after CMD */ + if ((cmdIndex == 5) || (cmdIndex == 6) || (cmdIndex == 7) || + (cmdIndex == 28) || (cmdIndex == 29) || (cmdIndex == 38)) { + + timeout = 0; + do { + present = + chal_sd_get_present_status((CHAL_HANDLE *) + handle->device); + + timeout++; + + /* Dat[0]:bit20 low means device busy */ + if ((present & DAT0_LEVEL_MASK) == 0) { + EMMC_TRACE("Device busy: "); + EMMC_TRACE( + "cmd%d arg:0x%08x: PSTATE[0x%08x]\n", + cmdIndex, argument, present); + SD_US_DELAY(100); + } else { + break; + } + } while (timeout < DEV_BUSY_TIMEOUT); + } + } else if (handle->device->ctrl.cmdStatus && + handle->device->ctrl.cmdStatus != SD_CMD_MISSING) { + retry++; + status = check_error(handle, handle->device->ctrl.cmdStatus); + + EMMC_TRACE( + "cmd%d error: cmdStatus:0x%08x error_status:0x%08x\n", + cmdIndex, handle->device->ctrl.cmdStatus, status); + + if ((handle->device->ctrl.cmdIndex == 1) || + (handle->device->ctrl.cmdIndex == 5)) { + status = event; + } else if ((handle->device->ctrl.cmdIndex == 7) || + (handle->device->ctrl.cmdIndex == 41)) { + status = event; + } else if ((status == SD_ERROR_RECOVERABLE) && + (retry < handle->device->cfg.retryLimit)) { + EMMC_TRACE("cmd%d recoverable error ", cmdIndex); + EMMC_TRACE("retry %d PSTATE[0x%08x].\n", retry, + chal_sd_get_present_status((CHAL_HANDLE *) + handle->device)); + goto RETRY_WRITE_CMD; + } else { + EMMC_TRACE("cmd%d retry reaches the limit %d\n", + cmdIndex, retry); + status = event; + } + } + + handle->device->ctrl.blkReg = 0; + /* clear error status for next command */ + handle->device->ctrl.cmdStatus = 0; + + return status; +} diff --git a/arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c b/arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c new file mode 100644 index 0000000..68f93e7 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#define MAX_CMD_RETRY 10 + +#if EMMC_USE_DMA +#define USE_DMA 1 +#else +#define USE_DMA 0 +#endif + +struct emmc_global_buffer emmc_global_buf; +struct emmc_global_buffer *emmc_global_buf_ptr = &emmc_global_buf; + +struct emmc_global_vars emmc_global_vars; +struct emmc_global_vars *emmc_global_vars_ptr = &emmc_global_vars; + +static struct sd_handle *sdio_gethandle(void); +static uint32_t sdio_idle(struct sd_handle *p_sdhandle); + +static uint32_t sdio_read(struct sd_handle *p_sdhandle, + uintptr_t mem_addr, + uintptr_t storage_addr, + size_t storage_size, + size_t bytes_to_read); + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +static uint32_t sdio_write(struct sd_handle *p_sdhandle, + uintptr_t mem_addr, + uintptr_t data_addr, + size_t bytes_to_write); +#endif + +static struct sd_handle *sdio_init(void); +static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle); + +static void init_globals(void) +{ + memset((void *)emmc_global_buf_ptr, 0, sizeof(*emmc_global_buf_ptr)); + memset((void *)emmc_global_vars_ptr, 0, sizeof(*emmc_global_vars_ptr)); +} + +/* + * This function is used to change partition + */ +uint32_t emmc_partition_select(uint32_t partition) +{ + int rc; + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + EMMC_TRACE("eMMC init is not done"); + return 0; + } + + switch (partition) { + case EMMC_BOOT_PARTITION1: + rc = set_boot_config(sd_handle, + SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1); + EMMC_TRACE( + "Change to Boot Partition 1 result:%d (0 means SD_OK)\n", + rc); + break; + + case EMMC_BOOT_PARTITION2: + rc = set_boot_config(sd_handle, + SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2); + EMMC_TRACE( + "Change to Boot Partition 2 result:%d (0 means SD_OK)\n", + rc); + break; + + case EMMC_USE_CURRENT_PARTITION: + rc = SD_OK; + EMMC_TRACE("Stay on current partition"); + break; + + case EMMC_USER_AREA: + default: + rc = set_boot_config(sd_handle, + SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER); + EMMC_TRACE("Change to User area result:%d (0 means SD_OK)\n", + rc); + break; + + } + return (rc == SD_OK); +} + +/* + * Initialize emmc controller for eMMC + * Returns 0 on fail condition + */ +uint32_t bcm_emmc_init(bool card_rdy_only) +{ + struct sd_handle *p_sdhandle; + uint32_t result = 0; + + EMMC_TRACE("Enter emmc_controller_init()\n"); + + /* If eMMC is already initialized, skip init */ + if (emmc_global_vars_ptr->init_done) + return 1; + + init_globals(); + + p_sdhandle = sdio_init(); + + if (p_sdhandle == NULL) { + ERROR("eMMC init failed"); + return result; + } + + if (card_rdy_only) { + /* Put the card in Ready state, Not complete init */ + result = bcm_emmc_card_ready_state(p_sdhandle); + return !result; + } + + if (sdio_idle(p_sdhandle) == EMMC_BOOT_OK) { + set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, USE_DMA, + SD_DMA_BOUNDARY_256K, EMMC_BLOCK_SIZE, + EMMC_WFE_RETRY); + + if (!select_blk_sz(p_sdhandle, + p_sdhandle->device->cfg.blockSize)) { + emmc_global_vars_ptr->init_done = 1; + result = 1; + } else { + ERROR("Select Block Size failed\n"); + } + } else { + ERROR("eMMC init failed"); + } + + /* Initialization is failed, so deinit HW setting */ + if (result == 0) + emmc_deinit(); + + return result; +} + +/* + * Function to de-init SDIO controller for eMMC + */ +void emmc_deinit(void) +{ + emmc_global_vars_ptr->init_done = 0; + emmc_global_vars_ptr->sdHandle.card = 0; + emmc_global_vars_ptr->sdHandle.device = 0; +} + +/* + * Read eMMC memory + * Returns read_size + */ +uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr, + size_t storage_size, size_t bytes_to_read) +{ + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + EMMC_TRACE("eMMC init is not done"); + return 0; + } + + return sdio_read(sdio_gethandle(), mem_addr, storage_addr, + storage_size, bytes_to_read); +} + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +#define EXT_CSD_ERASE_GRP_SIZE 224 + +static int emmc_block_erase(uintptr_t mem_addr, size_t blocks) +{ + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + ERROR("eMMC init is not done"); + return -1; + } + + return erase_card(sdio_gethandle(), mem_addr, blocks); +} + +int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition) +{ + int err = 0; + size_t block_count = 0, blocks = 0; + size_t erase_group = 0; + + erase_group = + emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_ERASE_GRP_SIZE]*1024; + + INFO("eMMC Erase Group Size=0x%lx\n", erase_group); + + emmc_partition_select(partition); + + while (block_count < num_of_blocks) { + blocks = ((num_of_blocks - block_count) > erase_group) ? + erase_group : (num_of_blocks - block_count); + err = emmc_block_erase(mem_addr + block_count, blocks); + if (err) + break; + + block_count += blocks; + } + + if (err == 0) + INFO("eMMC Erase of partition %d successful\n", partition); + else + ERROR("eMMC Erase of partition %d Failed(%i)\n", partition, err); + + return err; +} +#endif + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +/* + * Write to eMMC memory + * Returns written_size + */ +uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr, + size_t bytes_to_write) +{ + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + EMMC_TRACE("eMMC init is not done"); + return 0; + } + + return sdio_write(sd_handle, mem_addr, data_addr, bytes_to_write); +} +#endif + +/* + * Send SDIO Cmd + * Return 0 for pass condition + */ +uint32_t send_sdio_cmd(uint32_t cmdIndex, uint32_t argument, + uint32_t options, struct sd_resp *resp) +{ + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + EMMC_TRACE("eMMC init is not done"); + return 1; + } + + return send_cmd(sd_handle, cmdIndex, argument, options, resp); +} + + +/* + * This function return SDIO handle + */ +struct sd_handle *sdio_gethandle(void) +{ + return &emmc_global_vars_ptr->sdHandle; +} + +/* + * Initialize SDIO controller + */ +struct sd_handle *sdio_init(void) +{ + uint32_t SDIO_base; + struct sd_handle *p_sdhandle = &emmc_global_vars_ptr->sdHandle; + + SDIO_base = EMMC_CTRL_REGS_BASE_ADDR; + + if (SDIO_base == SDIO0_EMMCSDXC_SYSADDR) + EMMC_TRACE(" ---> for SDIO 0 Controller\n\n"); + + memset(p_sdhandle, 0, sizeof(struct sd_handle)); + + p_sdhandle->device = &emmc_global_vars_ptr->sdDevice; + p_sdhandle->card = &emmc_global_vars_ptr->sdCard; + + memset(p_sdhandle->device, 0, sizeof(struct sd_dev)); + memset(p_sdhandle->card, 0, sizeof(struct sd_card_info)); + + if (chal_sd_start((CHAL_HANDLE *) p_sdhandle->device, + SD_PIO_MODE, SDIO_base, SDIO_base) != SD_OK) + return NULL; + + set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, SD_DMA_OFF, + SD_DMA_BOUNDARY_4K, EMMC_BLOCK_SIZE, EMMC_WFE_RETRY); + + return &emmc_global_vars_ptr->sdHandle; +} + +uint32_t sdio_idle(struct sd_handle *p_sdhandle) +{ + reset_card(p_sdhandle); + + SD_US_DELAY(1000); + + if (init_card(p_sdhandle, SD_CARD_DETECT_MMC) != SD_OK) { + reset_card(p_sdhandle); + reset_host_ctrl(p_sdhandle); + return EMMC_BOOT_NO_CARD; + } + + return EMMC_BOOT_OK; +} + +/* + * This function read eMMC + */ +uint32_t sdio_read(struct sd_handle *p_sdhandle, + uintptr_t mem_addr, + uintptr_t storage_addr, + size_t storage_size, size_t bytes_to_read) +{ + uint32_t offset = 0, blockAddr, readLen = 0, rdCount; + uint32_t remSize, manual_copy_size; + uint8_t *outputBuf = (uint8_t *) storage_addr; + const size_t blockSize = p_sdhandle->device->cfg.blockSize; + + VERBOSE("EMMC READ: dst=0x%lx, src=0x%lx, size=0x%lx\n", + storage_addr, mem_addr, bytes_to_read); + + if (storage_size < bytes_to_read) + /* Don't have sufficient storage to complete the operation */ + return 0; + + /* Range check non high capacity memory */ + if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) { + if (mem_addr > 0x80000000) + return 0; + } + + /* High capacity card use block address mode */ + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) { + blockAddr = (uint32_t) (mem_addr / blockSize); + offset = (uint32_t) (mem_addr - (blockAddr * blockSize)); + } else { + blockAddr = (uint32_t) (mem_addr / blockSize) * blockSize; + offset = (uint32_t) (mem_addr - blockAddr); + } + + remSize = bytes_to_read; + + rdCount = 0; + + /* Process first unaligned block of MAX_READ_LENGTH */ + if (offset > 0) { + if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf, + blockAddr, SD_MAX_READ_LENGTH)) { + + if (remSize < (blockSize - offset)) { + rdCount += remSize; + manual_copy_size = remSize; + remSize = 0; /* read is done */ + } else { + remSize -= (blockSize - offset); + rdCount += (blockSize - offset); + manual_copy_size = blockSize - offset; + } + + /* Check for overflow */ + if (manual_copy_size > storage_size || + (((uintptr_t)outputBuf + manual_copy_size) > + (storage_addr + storage_size))) { + ERROR("EMMC READ: Overflow 1\n"); + return 0; + } + + memcpy(outputBuf, + (void *)((uintptr_t) + (emmc_global_buf_ptr->u.tempbuf + offset)), + manual_copy_size); + + /* Update Physical address */ + outputBuf += manual_copy_size; + + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) + blockAddr++; + else + blockAddr += blockSize; + } else { + return 0; + } + } + + while (remSize >= blockSize) { + + if (remSize >= SD_MAX_BLK_TRANSFER_LENGTH) + readLen = SD_MAX_BLK_TRANSFER_LENGTH; + else + readLen = (remSize / blockSize) * blockSize; + + /* Check for overflow */ + if ((rdCount + readLen) > storage_size || + (((uintptr_t) outputBuf + readLen) > + (storage_addr + storage_size))) { + ERROR("EMMC READ: Overflow\n"); + return 0; + } + + if (!read_block(p_sdhandle, outputBuf, blockAddr, readLen)) { + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) + blockAddr += (readLen / blockSize); + else + blockAddr += readLen; + + remSize -= readLen; + rdCount += readLen; + + /* Update Physical address */ + outputBuf += readLen; + } else { + return 0; + } + } + + /* process the last unaligned block reading */ + if (remSize > 0) { + if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf, + blockAddr, SD_MAX_READ_LENGTH)) { + + rdCount += remSize; + /* Check for overflow */ + if (rdCount > storage_size || + (((uintptr_t) outputBuf + remSize) > + (storage_addr + storage_size))) { + ERROR("EMMC READ: Overflow\n"); + return 0; + } + + memcpy(outputBuf, + emmc_global_buf_ptr->u.tempbuf, remSize); + + /* Update Physical address */ + outputBuf += remSize; + } else { + rdCount = 0; + } + } + + return rdCount; +} + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +static uint32_t sdio_write(struct sd_handle *p_sdhandle, uintptr_t mem_addr, + uintptr_t data_addr, size_t bytes_to_write) +{ + + uint32_t offset, blockAddr, writeLen, wtCount = 0; + uint32_t remSize, manual_copy_size = 0; + + uint8_t *inputBuf = (uint8_t *)data_addr; + + /* range check non high capacity memory */ + if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) { + if (mem_addr > 0x80000000) + return 0; + } + + /* the high capacity card use block address mode */ + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) { + blockAddr = + (uint32_t)(mem_addr / p_sdhandle->device->cfg.blockSize); + offset = + (uint32_t)(mem_addr - + blockAddr * p_sdhandle->device->cfg.blockSize); + } else { + blockAddr = + ((uint32_t)mem_addr / p_sdhandle->device->cfg.blockSize) * + p_sdhandle->device->cfg.blockSize; + offset = (uint32_t) mem_addr - blockAddr; + } + + remSize = bytes_to_write; + + wtCount = 0; + + /* process first unaligned block */ + if (offset > 0) { + if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf, + blockAddr, p_sdhandle->device->cfg.blockSize)) { + + if (remSize < + (p_sdhandle->device->cfg.blockSize - offset)) + manual_copy_size = remSize; + else + manual_copy_size = + p_sdhandle->device->cfg.blockSize - offset; + + memcpy((void *)((uintptr_t) + (emmc_global_buf_ptr->u.tempbuf + offset)), + inputBuf, + manual_copy_size); + + /* Update Physical address */ + + if (!write_block(p_sdhandle, + emmc_global_buf_ptr->u.tempbuf, + blockAddr, + p_sdhandle->device->cfg.blockSize)) { + + if (remSize < + (p_sdhandle->device->cfg.blockSize - + offset)) { + wtCount += remSize; + manual_copy_size = remSize; + remSize = 0; /* read is done */ + } else { + remSize -= + (p_sdhandle->device->cfg.blockSize - + offset); + wtCount += + (p_sdhandle->device->cfg.blockSize - + offset); + manual_copy_size = + p_sdhandle->device->cfg.blockSize - + offset; + } + + inputBuf += manual_copy_size; + + if (p_sdhandle->device->ctrl.ocr & + SD_CARD_HIGH_CAPACITY) + blockAddr++; + else + blockAddr += + p_sdhandle->device->cfg.blockSize; + } else + return 0; + } else { + return 0; + } + } + + /* process block writing */ + while (remSize >= p_sdhandle->device->cfg.blockSize) { + if (remSize >= SD_MAX_READ_LENGTH) { + writeLen = SD_MAX_READ_LENGTH; + } else { + writeLen = + (remSize / p_sdhandle->device->cfg.blockSize) * + p_sdhandle->device->cfg.blockSize; + } + + if (!write_block(p_sdhandle, inputBuf, blockAddr, writeLen)) { + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) + blockAddr += + (writeLen / + p_sdhandle->device->cfg.blockSize); + else + blockAddr += writeLen; + + remSize -= writeLen; + wtCount += writeLen; + inputBuf += writeLen; + } else { + return 0; + } + } + + /* process the last unaligned block reading */ + if (remSize > 0) { + if (!read_block(p_sdhandle, + emmc_global_buf_ptr->u.tempbuf, + blockAddr, p_sdhandle->device->cfg.blockSize)) { + + memcpy(emmc_global_buf_ptr->u.tempbuf, + inputBuf, remSize); + + /* Update Physical address */ + + if (!write_block(p_sdhandle, + emmc_global_buf_ptr->u.tempbuf, + blockAddr, + p_sdhandle->device->cfg.blockSize)) { + wtCount += remSize; + inputBuf += remSize; + } else { + return 0; + } + } else { + wtCount = 0; + } + } + + return wtCount; +} +#endif + +/* + * Function to put the card in Ready state by sending CMD0 and CMD1 + */ +static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle) +{ + int32_t result = 0; + uint32_t argument = MMC_CMD_IDLE_RESET_ARG; /* Exit from Boot mode */ + + if (p_sdhandle) { + send_sdio_cmd(SD_CMD_GO_IDLE_STATE, argument, 0, NULL); + + result = reset_card(p_sdhandle); + if (result != SD_OK) { + EMMC_TRACE("eMMC Reset error\n"); + return SD_RESET_ERROR; + } + SD_US_DELAY(2000); + result = mmc_cmd1(p_sdhandle); + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/brcm/i2c/i2c.c b/arm-trusted-firmware/drivers/brcm/i2c/i2c.c new file mode 100644 index 0000000..2096a82 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/i2c/i2c.c @@ -0,0 +1,886 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +/* Max instances */ +#define MAX_I2C 2U + +/* Transaction error codes defined in Master command register (0x30) */ +#define MSTR_STS_XACT_SUCCESS 0U +#define MSTR_STS_LOST_ARB 1U +#define MSTR_STS_NACK_FIRST_BYTE 2U + /* NACK on a byte other than the first byte */ +#define MSTR_STS_NACK_NON_FIRST_BYTE 3U + +#define MSTR_STS_TTIMEOUT_EXCEEDED 4U +#define MSTR_STS_TX_TLOW_MEXT_EXCEEDED 5U +#define MSTR_STS_RX_TLOW_MEXT_EXCEEDED 6U + +/* SMBUS protocol values defined in register 0x30 */ +#define SMBUS_PROT_QUICK_CMD 0U +#define SMBUS_PROT_SEND_BYTE 1U +#define SMBUS_PROT_RECV_BYTE 2U +#define SMBUS_PROT_WR_BYTE 3U +#define SMBUS_PROT_RD_BYTE 4U +#define SMBUS_PROT_WR_WORD 5U +#define SMBUS_PROT_RD_WORD 6U +#define SMBUS_PROT_BLK_WR 7U +#define SMBUS_PROT_BLK_RD 8U +#define SMBUS_PROT_PROC_CALL 9U +#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10U + +/* Number can be changed later */ +#define BUS_BUSY_COUNT 100000U + +#define IPROC_I2C_INVALID_ADDR 0xFFU + +#define I2C_SMBUS_BLOCK_MAX 32U + +/* + * Enum to specify clock speed. The user will provide it during initialization. + * If needed, it can be changed dynamically + */ +typedef enum iproc_smb_clk_freq { + IPROC_SMB_SPEED_100KHz = 0, + IPROC_SMB_SPEED_400KHz = 1, + IPROC_SMB_SPEED_INVALID = 255 +} smb_clk_freq_t; + +/* Structure used to pass information to read/write functions. */ +struct iproc_xact_info { + /* Bus Identifier */ + uint32_t bus_id; + /* Device Address */ + uint8_t devaddr; + /* Passed by caller to send SMBus command cod e*/ + uint8_t command; + /* actual data passed by the caller */ + uint8_t *data; + /* Size of data buffer passed */ + uint32_t size; + /* Sent by caller specifying PEC, 10-bit addresses */ + uint16_t flags; + /* SMBus protocol to use to perform transaction */ + uint8_t smb_proto; + /* true if command field below is valid. Otherwise, false */ + uint32_t cmd_valid; +}; + +static const uintptr_t smbus_base_reg_addr[MAX_I2C] = { + SMBUS0_REGS_BASE, + SMBUS1_REGS_BASE +}; + +/* Function to read a value from specified register. */ +static uint32_t iproc_i2c_reg_read(uint32_t bus_id, unsigned long reg_addr) +{ + uint32_t val; + uintptr_t smbus; + + smbus = smbus_base_reg_addr[bus_id]; + + val = mmio_read_32(smbus + reg_addr); + VERBOSE("i2c %u: reg %p read 0x%x\n", bus_id, + (void *)(smbus + reg_addr), val); + return val; +} + +/* Function to write a value ('val') in to a specified register. */ +static void iproc_i2c_reg_write(uint32_t bus_id, + unsigned long reg_addr, + uint32_t val) +{ + uintptr_t smbus; + + smbus = smbus_base_reg_addr[bus_id]; + + mmio_write_32((smbus + reg_addr), val); + VERBOSE("i2c %u: reg %p wrote 0x%x\n", bus_id, + (void *)(smbus + reg_addr), val); +} + +/* Function to clear and set bits in a specified register. */ +static void iproc_i2c_reg_clearset(uint32_t bus_id, + unsigned long reg_addr, + uint32_t clear, + uint32_t set) +{ + uintptr_t smbus; + + smbus = smbus_base_reg_addr[bus_id]; + + mmio_clrsetbits_32((smbus + reg_addr), clear, set); + VERBOSE("i2c %u: reg %p clear 0x%x, set 0x%x\n", bus_id, + (void *)(smbus + reg_addr), clear, set); +} + +/* Function to dump all SMBUS register */ +#ifdef BCM_I2C_DEBUG +static int iproc_dump_i2c_regs(uint32_t bus_id) +{ + uint32_t regval; + + if (bus_id > MAX_I2C) { + return -1; + } + + INFO("----------------------------------------------\n"); + INFO("%s: Dumping SMBus %u registers...\n", __func__, bus_id); + + regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG); + INFO("SMB_CFG_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG); + INFO("SMB_TIMGCFG_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_ADDR_REG); + INFO("SMB_ADDR_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRFIFOCTL_REG); + INFO("SMB_MSTRFIFOCTL_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_SLVFIFOCTL_REG); + INFO("SMB_SLVFIFOCTL_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_BITBANGCTL_REG); + INFO("SMB_BITBANGCTL_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG); + INFO("SMB_MSTRCMD_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_SLVCMD_REG); + INFO("SMB_SLVCMD_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_EVTEN_REG); + INFO("SMB_EVTEN_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG); + INFO("SMB_EVTSTS_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATAWR_REG); + INFO("SMB_MSTRDATAWR_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATARD_REG); + INFO("SMB_MSTRDATARD_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATAWR_REG); + INFO("SMB_SLVDATAWR_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATARD_REG); + INFO("SMB_SLVDATARD_REG=0x%x\n", regval); + + INFO("----------------------------------------------\n"); + return 0; +} +#endif + +/* + * Function to ensure that the previous transaction was completed before + * initiating a new transaction. It can also be used in polling mode to + * check status of completion of a command + */ +static int iproc_i2c_startbusy_wait(uint32_t bus_id) +{ + uint32_t regval; + uint32_t retry = 0U; + + /* + * Check if an operation is in progress. During probe it won't be. + * Want to make sure that the transaction in progress is completed. + */ + do { + udelay(1U); + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG); + regval &= SMB_MSTRSTARTBUSYCMD_MASK; + if (retry++ > BUS_BUSY_COUNT) { + ERROR("%s: START_BUSY bit didn't clear, exiting\n", + __func__); + return -1; + } + + } while (regval != 0U); + + return 0; +} + +/* + * This function copies data to SMBus's Tx FIFO. Valid for write transactions + * info: Data to copy in to Tx FIFO. For read commands, the size should be + * set to zero by the caller + */ +static void iproc_i2c_write_trans_data(struct iproc_xact_info *info) +{ + uint32_t regval; + uint8_t devaddr; + uint32_t i; + uint32_t num_data_bytes = 0U; + +#ifdef BCM_I2C_DEBUG + INFO("%s:dev_addr=0x%x,cmd_valid=%d, cmd=0x%x, size=%u proto=%d\n", + __func__, info->devaddr, info->cmd_valid, info->command, + info->size, info->smb_proto); +#endif + /* Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n */ + devaddr = (info->devaddr << 1); + + /* + * Depending on the SMBus protocol, we need to write additional + * transaction data in to Tx FIFO. Refer to section 5.5 of SMBus spec + * for sequence for a transaction + */ + switch (info->smb_proto) { + case SMBUS_PROT_RECV_BYTE: + /* No additional data to be written */ + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr | 0x1U | SMB_MSTRWRSTS_MASK); + break; + case SMBUS_PROT_SEND_BYTE: + num_data_bytes = info->size; + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr); + break; + case SMBUS_PROT_RD_BYTE: + case SMBUS_PROT_RD_WORD: + case SMBUS_PROT_BLK_RD: + /* Write slave address with R/W~ set (bit #0) */ + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr | 0x1U); + break; + case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL: + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr | 0x1U | SMB_MSTRWRSTS_MASK); + break; + case SMBUS_PROT_WR_BYTE: + case SMBUS_PROT_WR_WORD: + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr); + /* + * No additional bytes to be written. Data portion is written + * in the 'for' loop below + */ + num_data_bytes = info->size; + break; + case SMBUS_PROT_BLK_WR: + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr); + /* 3rd byte is byte count */ + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + info->size); + num_data_bytes = info->size; + break; + default: + return; + } + + /* If the protocol needs command code, copy it */ + if (info->cmd_valid) { + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + info->command); + } + + /* + * Copy actual data from caller. In general, for reads, + * no data is copied. + */ + for (i = 0U; num_data_bytes; --num_data_bytes, i++) { + /* For the last byte, set MASTER_WR_STATUS bit */ + regval = (num_data_bytes == 1U) ? + info->data[i] | SMB_MSTRWRSTS_MASK : info->data[i]; + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + regval); + } +} + +/* + * This function writes to the master command register and + * then polls for completion + */ +static int iproc_i2c_write_master_command(uint32_t mastercmd, + struct iproc_xact_info *info) +{ + uint32_t retry = 0U; + uint32_t regval; + + iproc_i2c_reg_write(info->bus_id, SMB_MSTRCMD_REG, mastercmd); + + /* Check for Master Busy status */ + regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG); + while ((regval & SMB_MSTRSTARTBUSYCMD_MASK) != 0U) { + udelay(1U); + if (retry++ > BUS_BUSY_COUNT) { + ERROR("%s: START_BUSY bit didn't clear, exiting\n", + __func__); + return -1; + } + regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG); + } + + /* If start_busy bit cleared, check if there are any errors */ + if (!(regval & SMB_MSTRSTARTBUSYCMD_MASK)) { + /* start_busy bit cleared, check master_status field now */ + regval &= SMB_MSTRSTS_MASK; + regval >>= SMB_MSTRSTS_SHIFT; + if (regval != MSTR_STS_XACT_SUCCESS) { + /* Error We can flush Tx FIFO here */ + ERROR("%s: ERROR: %u exiting\n", __func__, regval); + return -1; + } + } + return 0; + +} +/* Function to initiate data send and verify completion status */ +static int iproc_i2c_data_send(struct iproc_xact_info *info) +{ + int rc; + uint32_t mastercmd; + + /* Make sure the previous transaction completed */ + rc = iproc_i2c_startbusy_wait(info->bus_id); + + if (rc < 0) { + WARN("%s: Send: bus is busy, exiting\n", __func__); + return rc; + } + /* Write transaction bytes to Tx FIFO */ + iproc_i2c_write_trans_data(info); + + /* + * Program master command register (0x30) with protocol type and set + * start_busy_command bit to initiate the write transaction + */ + mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) | + SMB_MSTRSTARTBUSYCMD_MASK; + + if (iproc_i2c_write_master_command(mastercmd, info)) { + return -1; + } + + return 0; +} + +/* + * Function to initiate data receive, verify completion status, + * and read from SMBUS Read FIFO + */ +static int iproc_i2c_data_recv(struct iproc_xact_info *info, + uint32_t *num_bytes_read) +{ + int rc; + uint32_t mastercmd; + uint32_t regval; + + /* Make sure the previous transaction completed */ + rc = iproc_i2c_startbusy_wait(info->bus_id); + + if (rc < 0) { + WARN("%s: Receive: Bus is busy, exiting\n", __func__); + return rc; + } + + /* Program all transaction bytes into master Tx FIFO */ + iproc_i2c_write_trans_data(info); + + /* + * Program master command register (0x30) with protocol type and set + * start_busy_command bit to initiate the write transaction + */ + mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) | + SMB_MSTRSTARTBUSYCMD_MASK | info->size; + + if (iproc_i2c_write_master_command(mastercmd, info)) { + return -1; + } + + /* Read received byte(s), after TX out address etc */ + regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRDATARD_REG); + + /* For block read, protocol (hw) returns byte count,as the first byte */ + if (info->smb_proto == SMBUS_PROT_BLK_RD) { + uint32_t i; + + *num_bytes_read = regval & SMB_MSTRRDDATA_MASK; + /* + * Limit to reading a max of 32 bytes only; just a safeguard. + * If # bytes read is a number > 32, check transaction set up, + * and contact hw engg. + * Assumption: PEC is disabled + */ + for (i = 0U; (i < *num_bytes_read) && + (i < I2C_SMBUS_BLOCK_MAX); i++) { + /* Read Rx FIFO for data bytes */ + regval = iproc_i2c_reg_read(info->bus_id, + SMB_MSTRDATARD_REG); + info->data[i] = regval & SMB_MSTRRDDATA_MASK; + } + } else { + /* 1 Byte data */ + *info->data = regval & SMB_MSTRRDDATA_MASK; + *num_bytes_read = 1U; + } + + return 0; +} + +/* + * This function set clock frequency for SMBus block. As per hardware + * engineering, the clock frequency can be changed dynamically. + */ +static int iproc_i2c_set_clk_freq(uint32_t bus_id, smb_clk_freq_t freq) +{ + uint32_t val; + + switch (freq) { + case IPROC_SMB_SPEED_100KHz: + val = 0U; + break; + case IPROC_SMB_SPEED_400KHz: + val = 1U; + break; + default: + return -1; + } + + iproc_i2c_reg_clearset(bus_id, SMB_TIMGCFG_REG, + SMB_TIMGCFG_MODE400_MASK, + val << SMB_TIMGCFG_MODE400_SHIFT); + + return 0; +} + +/* Helper function to fill the iproc_xact_info structure */ +static void iproc_i2c_fill_info(struct iproc_xact_info *info, uint32_t bus_id, + uint8_t devaddr, uint8_t cmd, uint8_t *value, + uint8_t smb_proto, uint32_t cmd_valid) +{ + info->bus_id = bus_id; + info->devaddr = devaddr; + info->command = (uint8_t)cmd; + info->smb_proto = smb_proto; + info->data = value; + info->size = 1U; + info->flags = 0U; + info->cmd_valid = cmd_valid; +} + +/* This function initializes the SMBUS */ +static void iproc_i2c_init(uint32_t bus_id, int speed) +{ + uint32_t regval; + +#ifdef BCM_I2C_DEBUG + INFO("%s: Enter Init\n", __func__); +#endif + + /* Put controller in reset */ + regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG); + regval |= BIT(SMB_CFG_RST_SHIFT); + regval &= ~(BIT(SMB_CFG_SMBEN_SHIFT)); + iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval); + + /* Wait 100 usec per spec */ + udelay(100U); + + /* Bring controller out of reset */ + regval &= ~(BIT(SMB_CFG_RST_SHIFT)); + iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval); + + /* + * Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0. + * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts + */ + regval = SMB_MSTRRXFIFOFLSH_MASK | SMB_MSTRTXFIFOFLSH_MASK; + iproc_i2c_reg_write(bus_id, SMB_MSTRFIFOCTL_REG, regval); + + /* + * Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero + * since there will be only one master + */ + + regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG); + regval |= SMB_CFG_SMBEN_MASK; + iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval); + /* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */ + mdelay(10U); + + /* If error then set default speed */ + if (i2c_set_bus_speed(bus_id, speed)) { + i2c_set_bus_speed(bus_id, I2C_SPEED_DEFAULT); + } + + /* Disable intrs */ + regval = 0x0U; + iproc_i2c_reg_write(bus_id, SMB_EVTEN_REG, regval); + + /* Clear intrs (W1TC) */ + regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG); + iproc_i2c_reg_write(bus_id, SMB_EVTSTS_REG, regval); + +#ifdef BCM_I2C_DEBUG + iproc_dump_i2c_regs(bus_id); + + INFO("%s: Exit Init Successfully\n", __func__); +#endif +} + +/* + * Function Name: i2c_init + * + * Description: + * This function initializes the SMBUS. + * + * Parameters: + * bus_id - I2C bus ID + * speed - I2C bus speed in Hz + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_init(uint32_t bus_id, int speed) +{ + if (bus_id > MAX_I2C) { + WARN("%s: Invalid Bus %u\n", __func__, bus_id); + return -1; + } + + iproc_i2c_init(bus_id, speed); + return 0U; +} + +/* + * Function Name: i2c_probe + * + * Description: + * This function probes the I2C bus for the existence of the specified + * device. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_probe(uint32_t bus_id, uint8_t devaddr) +{ + uint32_t regval; + int rc; + + /* + * i2c_init() Initializes internal regs, disable intrs (and then clear intrs), + * set fifo thresholds, etc. + * Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n + */ + regval = (devaddr << 1U); + iproc_i2c_reg_write(bus_id, SMB_MSTRDATAWR_REG, regval); + + regval = ((SMBUS_PROT_QUICK_CMD << SMB_MSTRSMBUSPROTO_SHIFT) | + SMB_MSTRSTARTBUSYCMD_MASK); + iproc_i2c_reg_write(bus_id, SMB_MSTRCMD_REG, regval); + + rc = iproc_i2c_startbusy_wait(bus_id); + + if (rc < 0) { + WARN("%s: Probe: bus is busy, exiting\n", __func__); + return rc; + } + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG); + if (((regval & SMB_MSTRSTS_MASK) >> SMB_MSTRSTS_SHIFT) == 0) + VERBOSE("i2c device address: 0x%x\n", devaddr); + else + return -1; + +#ifdef BCM_I2C_DEBUG + iproc_dump_i2c_regs(bus_id); +#endif + return 0; +} + +/* + * Function Name: i2c_recv_byte + * + * Description: + * This function reads I2C data from a device without specifying + * a command regsiter. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * value - Data Read + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_recv_byte(uint32_t bus_id, uint8_t devaddr, uint8_t *value) +{ + int rc; + struct iproc_xact_info info; + uint32_t num_bytes_read = 0; + + iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, value, + SMBUS_PROT_RECV_BYTE, 0U); + + /* Refer to i2c_smbus_read_byte for params passed. */ + rc = iproc_i2c_data_recv(&info, &num_bytes_read); + + if (rc < 0) { + printf("%s: %s error accessing device 0x%x\n", + __func__, "Read", devaddr); + } + + return rc; +} + +/* + * Function Name: i2c_send_byte + * + * Description: + * This function send I2C data to a device without specifying + * a command regsiter. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * value - Data Send + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_send_byte(uint32_t bus_id, uint8_t devaddr, uint8_t value) +{ + int rc; + struct iproc_xact_info info; + + iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, &value, + SMBUS_PROT_SEND_BYTE, 0U); + + /* Refer to i2c_smbus_write_byte params passed. */ + rc = iproc_i2c_data_send(&info); + + if (rc < 0) { + ERROR("%s: %s error accessing device 0x%x\n", + __func__, "Write", devaddr); + } + + return rc; +} + +/* Helper function to read a single byte */ +static int i2c_read_byte(uint32_t bus_id, + uint8_t devaddr, + uint8_t regoffset, + uint8_t *value) +{ + int rc; + struct iproc_xact_info info; + uint32_t num_bytes_read = 0U; + + iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, value, + SMBUS_PROT_RD_BYTE, 1U); + + /* Refer to i2c_smbus_read_byte for params passed. */ + rc = iproc_i2c_data_recv(&info, &num_bytes_read); + + if (rc < 0) { + ERROR("%s: %s error accessing device 0x%x\n", + __func__, "Read", devaddr); + } + return rc; +} + +/* + * Function Name: i2c_read + * + * Description: + * This function reads I2C data from a device with a designated + * command register + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * addr - Register Offset + * alen - Address Length, 1 for byte, 2 for word (not supported) + * buffer - Data Buffer + * len - Data Length in bytes + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_read(uint32_t bus_id, + uint8_t devaddr, + uint32_t addr, + int alen, + uint8_t *buffer, + int len) +{ + uint32_t i; + + if (alen > 1) { + WARN("I2C read: addr len %d not supported\n", alen); + return -1; + } + + if (addr + len > 256) { + WARN("I2C read: address out of range\n"); + return -1; + } + + for (i = 0U; i < len; i++) { + if (i2c_read_byte(bus_id, devaddr, addr + i, &buffer[i])) { + ERROR("I2C read: I/O error\n"); + iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id)); + return -1; + } + } + + return 0; +} + +/* Helper function to write a single byte */ +static int i2c_write_byte(uint32_t bus_id, + uint8_t devaddr, + uint8_t regoffset, + uint8_t value) +{ + int rc; + struct iproc_xact_info info; + + iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, &value, + SMBUS_PROT_WR_BYTE, 1U); + + /* Refer to i2c_smbus_write_byte params passed. */ + rc = iproc_i2c_data_send(&info); + + if (rc < 0) { + ERROR("%s: %s error accessing device 0x%x\n", + __func__, "Write", devaddr); + return -1; + } + + return 0; +} + +/* + * Function Name: i2c_write + * + * Description: + * This function write I2C data to a device with a designated + * command register + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * addr - Register Offset + * alen - Address Length, 1 for byte, 2 for word (not supported) + * buffer - Data Buffer + * len - Data Length in bytes + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_write(uint32_t bus_id, + uint8_t devaddr, + uint32_t addr, + int alen, + uint8_t *buffer, + int len) +{ + uint32_t i; + + if (alen > 1) { + WARN("I2C write: addr len %d not supported\n", alen); + return -1; + } + + if (addr + len > 256U) { + WARN("I2C write: address out of range\n"); + return -1; + } + + for (i = 0U; i < len; i++) { + if (i2c_write_byte(bus_id, devaddr, addr + i, buffer[i])) { + ERROR("I2C write: I/O error\n"); + iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id)); + return -1; + } + } + return 0; +} + +/* + * Function Name: i2c_set_bus_speed + * + * Description: + * This function configures the SMBUS speed + * + * Parameters: + * bus_id - I2C bus ID + * speed - I2C bus speed in Hz + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_set_bus_speed(uint32_t bus_id, uint32_t speed) +{ + switch (speed) { + case I2C_SPEED_100KHz: + iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_100KHz); + break; + + case I2C_SPEED_400KHz: + iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_400KHz); + break; + + default: + return -1; + } + return 0; +} + +/* + * Function Name: i2c_get_bus_speed + * + * Description: + * This function returns the SMBUS speed. + * + * Parameters: + * bus_id - I2C bus ID + * + * Return: + * Bus speed in Hz, 0 on failure + */ +uint32_t i2c_get_bus_speed(uint32_t bus_id) +{ + uint32_t regval; + uint32_t retval = 0U; + + regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG); + regval &= SMB_TIMGCFG_MODE400_MASK; + regval >>= SMB_TIMGCFG_MODE400_SHIFT; + + switch (regval) { + case IPROC_SMB_SPEED_100KHz: + retval = I2C_SPEED_100KHz; + break; + + case IPROC_SMB_SPEED_400KHz: + retval = I2C_SPEED_400KHz; + break; + + default: + break; + } + return retval; +} + diff --git a/arm-trusted-firmware/drivers/brcm/iproc_gpio.c b/arm-trusted-firmware/drivers/brcm/iproc_gpio.c new file mode 100644 index 0000000..f61a3bc --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/iproc_gpio.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#define IPROC_GPIO_DATA_IN_OFFSET 0x00 +#define IPROC_GPIO_DATA_OUT_OFFSET 0x04 +#define IPROC_GPIO_OUT_EN_OFFSET 0x08 +#define IPROC_GPIO_PAD_RES_OFFSET 0x34 +#define IPROC_GPIO_RES_EN_OFFSET 0x38 + +#define PINMUX_OFFSET(gpio) ((gpio) * 4) +#define PINCONF_OFFSET(gpio) ((gpio) * 4) +#define PINCONF_PULL_UP BIT(4) +#define PINCONF_PULL_DOWN BIT(5) + +/* + * iProc GPIO bank is always 0x200 per bank, + * with each bank supporting 32 GPIOs. + */ +#define GPIO_BANK_SIZE 0x200 +#define NGPIOS_PER_BANK 32 +#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK) + +#define IPROC_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg)) +#define IPROC_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK) + +#define MUX_GPIO_MODE 0x3 + +/* + * @base: base address of the gpio controller + * @pinconf_base: base address of the pinconf + * @pinmux_base: base address of the mux controller + * @nr_gpios: maxinum number of GPIOs + */ +struct iproc_gpio { + uintptr_t base; + uintptr_t pinconf_base; + uintptr_t pinmux_base; + int nr_gpios; +}; + +static struct iproc_gpio iproc_gpio; + +static void gpio_set_bit(uintptr_t base, unsigned int reg, int gpio, bool set) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, reg); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + uint32_t val; + + val = mmio_read_32(base + offset); + if (set) + val |= BIT(shift); + else + val &= ~BIT(shift); + + mmio_write_32(base + offset, val); +} + +static bool gpio_get_bit(uintptr_t base, unsigned int reg, int gpio) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, reg); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + + return !!(mmio_read_32(base + offset) & BIT(shift)); +} + +static void mux_to_gpio(struct iproc_gpio *g, int gpio) +{ + /* mux pad to GPIO if IOPAD configuration is mandatory */ + if (g->pinmux_base) + mmio_write_32(g->pinmux_base + PINMUX_OFFSET(gpio), + MUX_GPIO_MODE); +} + +static void set_direction(int gpio, int direction) +{ + struct iproc_gpio *g = &iproc_gpio; + bool dir = (direction == GPIO_DIR_OUT) ? true : false; + + assert(gpio < g->nr_gpios); + + mux_to_gpio(g, gpio); + gpio_set_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio, dir); +} + +static int get_direction(int gpio) +{ + struct iproc_gpio *g = &iproc_gpio; + int dir; + + assert(gpio < g->nr_gpios); + + mux_to_gpio(g, gpio); + dir = gpio_get_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio) ? + GPIO_DIR_OUT : GPIO_DIR_IN; + + return dir; +} + +static int get_value(int gpio) +{ + struct iproc_gpio *g = &iproc_gpio; + unsigned int offset; + + assert(gpio < g->nr_gpios); + + mux_to_gpio(g, gpio); + + /* + * If GPIO is configured as output, read from the GPIO_OUT register; + * otherwise, read from the GPIO_IN register + */ + offset = gpio_get_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio) ? + IPROC_GPIO_DATA_OUT_OFFSET : IPROC_GPIO_DATA_IN_OFFSET; + + return gpio_get_bit(g->base, offset, gpio); +} + +static void set_value(int gpio, int val) +{ + struct iproc_gpio *g = &iproc_gpio; + + assert(gpio < g->nr_gpios); + + mux_to_gpio(g, gpio); + + /* make sure GPIO is configured to output, and then set the value */ + gpio_set_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio, true); + gpio_set_bit(g->base, IPROC_GPIO_DATA_OUT_OFFSET, gpio, !!(val)); +} + +static int get_pull(int gpio) +{ + struct iproc_gpio *g = &iproc_gpio; + uint32_t val; + + assert(gpio < g->nr_gpios); + mux_to_gpio(g, gpio); + + /* when there's a valid pinconf_base, use it */ + if (g->pinconf_base) { + val = mmio_read_32(g->pinconf_base + PINCONF_OFFSET(gpio)); + + if (val & PINCONF_PULL_UP) + return GPIO_PULL_UP; + else if (val & PINCONF_PULL_DOWN) + return GPIO_PULL_DOWN; + else + return GPIO_PULL_NONE; + } + + /* no pinconf_base. fall back to GPIO internal pull control */ + if (!gpio_get_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio)) + return GPIO_PULL_NONE; + + return gpio_get_bit(g->base, IPROC_GPIO_PAD_RES_OFFSET, gpio) ? + GPIO_PULL_UP : GPIO_PULL_DOWN; +} + +static void set_pull(int gpio, int pull) +{ + struct iproc_gpio *g = &iproc_gpio; + uint32_t val; + + assert(gpio < g->nr_gpios); + mux_to_gpio(g, gpio); + + /* when there's a valid pinconf_base, use it */ + if (g->pinconf_base) { + val = mmio_read_32(g->pinconf_base + PINCONF_OFFSET(gpio)); + + if (pull == GPIO_PULL_NONE) { + val &= ~(PINCONF_PULL_UP | PINCONF_PULL_DOWN); + } else if (pull == GPIO_PULL_UP) { + val |= PINCONF_PULL_UP; + val &= ~PINCONF_PULL_DOWN; + } else if (pull == GPIO_PULL_DOWN) { + val |= PINCONF_PULL_DOWN; + val &= ~PINCONF_PULL_UP; + } else { + return; + } + mmio_write_32(g->pinconf_base + PINCONF_OFFSET(gpio), val); + } + + /* no pinconf_base. fall back to GPIO internal pull control */ + if (pull == GPIO_PULL_NONE) { + gpio_set_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio, false); + return; + } + + /* enable pad register and pull up or down */ + gpio_set_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio, true); + gpio_set_bit(g->base, IPROC_GPIO_PAD_RES_OFFSET, gpio, + !!(pull == GPIO_PULL_UP)); +} + +const gpio_ops_t iproc_gpio_ops = { + .get_direction = get_direction, + .set_direction = set_direction, + .get_value = get_value, + .set_value = set_value, + .get_pull = get_pull, + .set_pull = set_pull, +}; + +void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base, + uintptr_t pinconf_base) +{ + iproc_gpio.base = base; + iproc_gpio.nr_gpios = nr_gpios; + + /* pinmux/pinconf base is optional for some SoCs */ + if (pinmux_base) + iproc_gpio.pinmux_base = pinmux_base; + + if (pinconf_base) + iproc_gpio.pinconf_base = pinconf_base; + + gpio_init(&iproc_gpio_ops); +} diff --git a/arm-trusted-firmware/drivers/brcm/mdio/mdio.c b/arm-trusted-firmware/drivers/brcm/mdio/mdio.c new file mode 100644 index 0000000..1cf9d66 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/mdio/mdio.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include + +#include +#include +#include +#include + +static int mdio_op_status(uint32_t result) +{ + uint32_t timeout = 1000000U; /* loop for 1s */ + uint32_t val; + + do { + val = mmio_read_32(CMIC_MIIM_STAT); + if ((val & MDIO_STAT_DONE) == result) { + return 0; + } + + udelay(1U); + } while (timeout-- != 0U); + return -1; +} + +static int mdio_op(uint16_t busid, uint16_t phyid, uint32_t reg, + uint16_t val, uint8_t op) +{ + uint32_t param; + int ret; + + mmio_write_32(CMIC_MIIM_CTRL, 0U); + ret = mdio_op_status(0U); + if (ret != 0) { + goto err; + } + + param = 0U; + param |= 1U << MDIO_PARAM_INTERNAL_SEL; + param |= (busid & MDIO_PARAM_BUSID_MASK) << MDIO_PARAM_BUSID; + param |= (phyid & MDIO_PARAM_PHYID_MASK) << MDIO_PARAM_PHYID; + param |= (val & MDIO_PARAM_DATA_MASK) << MDIO_PARAM_DATA; + + mmio_write_32(CMIC_MIIM_PARAM, param); + + mmio_write_32(CMIC_MIIM_ADDRESS, reg); + + mmio_write_32(CMIC_MIIM_CTRL, op); + + ret = mdio_op_status(1U); + if (ret != 0) { + goto err; + } + + if (op == MDIO_CTRL_READ_OP) { + ret = mmio_read_32(CMIC_MIIM_READ_DATA) & MDIO_READ_DATA_MASK; + } +err: + return ret; +} + +int mdio_write(uint16_t busid, uint16_t phyid, uint32_t reg, uint16_t val) +{ + int ret; + + ret = mdio_op(busid, phyid, reg, val, MDIO_CTRL_WRITE_OP); + if (ret == -1) { + INFO("MDIO write fail\n"); + } + return ret; +} + +int mdio_read(uint16_t busid, uint16_t phyid, uint32_t reg) +{ + int ret; + + ret = mdio_op(busid, phyid, reg, 0U, MDIO_CTRL_READ_OP); + if (ret == -1) { + INFO("MDIO read fail\n"); + } + return ret; +} diff --git a/arm-trusted-firmware/drivers/brcm/ocotp.c b/arm-trusted-firmware/drivers/brcm/ocotp.c new file mode 100644 index 0000000..6ff8554 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/ocotp.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#define OTP_MAP 2 +#define OTP_NUM_WORDS 2048 +/* + * # of tries for OTP Status. The time to execute a command varies. The slowest + * commands are writes which also vary based on the # of bits turned on. Writing + * 0xffffffff takes ~3800 us. + */ +#define OTPC_RETRIES_US 5000 + +/* Sequence to enable OTP program */ +#define OTPC_PROG_EN_SEQ { 0xf, 0x4, 0x8, 0xd } + +/* OTPC Commands */ +#define OTPC_CMD_READ 0x0 +#define OTPC_CMD_OTP_PROG_ENABLE 0x2 +#define OTPC_CMD_OTP_PROG_DISABLE 0x3 +#define OTPC_CMD_PROGRAM 0x8 +#define OTPC_CMD_ECC 0x10 +#define OTPC_ECC_ADDR 0x1A +#define OTPC_ECC_VAL 0x00EC0000 + +/* OTPC Status Bits */ +#define OTPC_STAT_CMD_DONE BIT(1) +#define OTPC_STAT_PROG_OK BIT(2) + +/* OTPC register definition */ +#define OTPC_MODE_REG_OFFSET 0x0 +#define OTPC_MODE_REG_OTPC_MODE 0 +#define OTPC_COMMAND_OFFSET 0x4 +#define OTPC_COMMAND_COMMAND_WIDTH 6 +#define OTPC_CMD_START_OFFSET 0x8 +#define OTPC_CMD_START_START 0 +#define OTPC_CPU_STATUS_OFFSET 0xc +#define OTPC_CPUADDR_REG_OFFSET 0x28 +#define OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH 16 +#define OTPC_CPU_WRITE_REG_OFFSET 0x2c + +#define OTPC_CMD_MASK (BIT(OTPC_COMMAND_COMMAND_WIDTH) - 1) +#define OTPC_ADDR_MASK (BIT(OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH) - 1) + +#define OTPC_MODE_REG OCOTP_REGS_BASE + +struct chip_otp_cfg { + uint32_t base; + uint32_t num_words; +}; + +struct chip_otp_cfg ocotp_cfg = { + .base = OTPC_MODE_REG, + .num_words = 2048, +}; + +struct otpc_priv { + uint32_t base; + struct otpc_map *map; + int size; + int state; +}; + +struct otpc_priv otpc_info; + +static inline void set_command(uint32_t base, uint32_t command) +{ + mmio_write_32(base + OTPC_COMMAND_OFFSET, command & OTPC_CMD_MASK); +} + +static inline void set_cpu_address(uint32_t base, uint32_t addr) +{ + mmio_write_32(base + OTPC_CPUADDR_REG_OFFSET, addr & OTPC_ADDR_MASK); +} + +static inline void set_start_bit(uint32_t base) +{ + mmio_write_32(base + OTPC_CMD_START_OFFSET, 1 << OTPC_CMD_START_START); +} + +static inline void reset_start_bit(uint32_t base) +{ + mmio_write_32(base + OTPC_CMD_START_OFFSET, 0); +} + +static inline void write_cpu_data(uint32_t base, uint32_t value) +{ + mmio_write_32(base + OTPC_CPU_WRITE_REG_OFFSET, value); +} + +static int poll_cpu_status(uint32_t base, uint32_t value) +{ + uint32_t status; + uint32_t retries; + + for (retries = 0; retries < OTPC_RETRIES_US; retries++) { + status = mmio_read_32(base + OTPC_CPU_STATUS_OFFSET); + if (status & value) + break; + udelay(1); + } + if (retries == OTPC_RETRIES_US) + return -1; + + return 0; +} + +static int bcm_otpc_ecc(uint32_t enable) +{ + struct otpc_priv *priv = &otpc_info; + int ret; + + set_command(priv->base, OTPC_CMD_ECC); + set_cpu_address(priv->base, OTPC_ECC_ADDR); + + if (!enable) + write_cpu_data(priv->base, OTPC_ECC_VAL); + else + write_cpu_data(priv->base, ~OTPC_ECC_VAL); + + set_start_bit(priv->base); + ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE); + if (ret) { + ERROR("otp ecc op error: 0x%x", ret); + return -1; + } + reset_start_bit(priv->base); + + return 0; +} + +/* + * bcm_otpc_read read otp data in the size of 8 byte rows. + * bytes has to be the multiple of 8. + * return -1 in error case, return read bytes in success. + */ +int bcm_otpc_read(unsigned int offset, void *val, uint32_t bytes, + uint32_t ecc_flag) +{ + struct otpc_priv *priv = &otpc_info; + uint32_t *buf = val; + uint32_t bytes_read; + uint32_t address = offset / priv->map->word_size; + int i, ret; + + if (!priv->state) { + ERROR("OCOTP read failed\n"); + return -1; + } + + bcm_otpc_ecc(ecc_flag); + + for (bytes_read = 0; (bytes_read + priv->map->word_size) <= bytes;) { + set_command(priv->base, OTPC_CMD_READ); + set_cpu_address(priv->base, address++); + set_start_bit(priv->base); + ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE); + if (ret) { + ERROR("otp read error: 0x%x", ret); + return -1; + } + + for (i = 0; i < priv->map->otpc_row_size; i++) { + *buf++ = mmio_read_32(priv->base + + priv->map->data_r_offset[i]); + bytes_read += sizeof(*buf); + } + + reset_start_bit(priv->base); + } + + return bytes_read; +} + +int bcm_otpc_init(struct otpc_map *map) +{ + struct otpc_priv *priv; + + priv = &otpc_info; + priv->base = ocotp_cfg.base; + priv->map = map; + + priv->size = 4 * ocotp_cfg.num_words; + + /* Enable CPU access to OTPC. */ + mmio_setbits_32(priv->base + OTPC_MODE_REG_OFFSET, + BIT(OTPC_MODE_REG_OTPC_MODE)); + reset_start_bit(priv->base); + priv->state = 1; + VERBOSE("OTPC Initialization done\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/brcm/rng.c b/arm-trusted-firmware/drivers/brcm/rng.c new file mode 100644 index 0000000..ee2e656 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/rng.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define RNG_CTRL_REG (RNG_BASE_ADDR + 0x00) +#define RNG_CTRL_MASK 0x00001FFF +#define RNG_CTRL_ENABLE 0x00000001 +#define RNG_CTRL_DISABLE 0x00000000 + +#define RNG_SOFT_RESET_REG (RNG_BASE_ADDR + 0x04) +#define RNG_SOFT_RESET_MASK 0x00000001 + +#define RNG_FIFO_DATA_REG (RNG_BASE_ADDR + 0x20) + +#define RNG_FIFO_COUNT_REG (RNG_BASE_ADDR + 0x24) +#define RNG_FIFO_COUNT_MASK 0x000000FF + +#define RNG_FIFO_WORDS_MAX 16 +#define MAX_WAIT_COUNT_50US 20000 + + +static void rng_reset(void) +{ + /* Disable RBG */ + mmio_clrbits_32(RNG_CTRL_REG, RNG_CTRL_MASK); + + /* Reset RNG and RBG */ + mmio_setbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK); + + /* Take all out of reset */ + mmio_clrbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK); +} + +static void rng_enable(void) +{ + /* Setup RNG. */ + mmio_clrsetbits_32(RNG_CTRL_REG, RNG_CTRL_MASK, RNG_CTRL_ENABLE); +} + +int rng_init(void) +{ + rng_reset(); + + rng_enable(); + + return 0; +} + +int rng_read(uint32_t *p_out, uint32_t *words_read) +{ + uint32_t available_words; + uint32_t i; + uint32_t word_processed = 0; + uint32_t wait_count = MAX_WAIT_COUNT_50US; + + if (*words_read == 0) { + ERROR("RNG Parameter: No word requested\n"); + return -1; + } + + do { + available_words = mmio_read_32(RNG_FIFO_COUNT_REG); + available_words &= RNG_FIFO_COUNT_MASK; + + if (available_words != 0) { + available_words = MIN(available_words, + *words_read - word_processed); + + for (i = 0; i < available_words; i++) + p_out[word_processed + i] = + mmio_read_32(RNG_FIFO_DATA_REG); + word_processed += available_words; + } else { + udelay(50); + } + + if (word_processed == *words_read) + break; + + } while (--wait_count); + + if (word_processed != *words_read) { + ERROR("RNG Timeout: requested %d word(s) got %d\n", + *words_read, word_processed); + *words_read = word_processed; + return -1; + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/brcm/scp.c b/arm-trusted-firmware/drivers/brcm/scp.c new file mode 100644 index 0000000..6196073 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/scp.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* MCU binary image structure:
+ * + * Header structure: + * + * + * { }* + * + * + * MCU data () consists of several sections of code/data, to be + * installed (copied) into MCU memories. + * Header (
) gives information about sections contained in . + * + * The installer code iterates over sections in MCU binary. + * For each section, it copies the section into MCU memory. + * + * The header contains: + * - - 32-bit magic number to mark header start + * - - number of sections in + * - tuples. Each tuple describes a section. + * A tuple contains three 32-bit words. + * - - 32-bit magic number to mark header end + * + * Each section is describes by a tuple, consisting of three 32-bit words: + * - offset of section within MCU binary (relative to beginning of ) + * - section size (in bytes) in MCU binary + * - target address (in MCU memory). Section is copied to this location. + * + * All fields are 32-bit unsigned integers in little endian format. + * All sizes are assumed to be 32-bit aligned. + */ + +#define SCP_BIN_HEADER_MAGIC_START 0xfa587D01 +#define SCP_BIN_HEADER_MAGIC_END 0xf3e06a85 + +int download_scp_patch(void *image, unsigned int image_size) +{ + unsigned int *pheader = (unsigned int *)(image); + unsigned int header_size; + unsigned char *pdata; + void *dest; + unsigned int num_sections; + unsigned int section_src_offset; + unsigned int section_size; + + if (pheader && (pheader[0] != SCP_BIN_HEADER_MAGIC_START)) { + ERROR("SCP: Could not find SCP header.\n"); + return -1; + } + + num_sections = pheader[1]; + INFO("...Number of sections: %d\n", num_sections); + header_size = 4 * (1 + 1 + 3 * num_sections + 1); + + if (image_size < header_size) { + ERROR("SCP: Wrong size.\n"); + return -1; + } + + if (*(pheader + header_size/4 - 1) != SCP_BIN_HEADER_MAGIC_END) { + ERROR("SCP: Could not find SCP footer.\n"); + return -1; + } + + VERBOSE("SCP image header validated successfully\n"); + pdata = (unsigned char *)pheader + header_size; + + for (pheader += 2; num_sections > 0; num_sections--) { + + section_src_offset = pheader[0]; + section_size = pheader[1]; + dest = (void *)(unsigned long)pheader[2]; + + INFO("section: src:0x%x, size:%d, dst:0x%x\n", + section_src_offset, section_size, pheader[2]); + + if ((section_src_offset + section_size) > image_size) { + ERROR("SCP: Section points to outside of patch.\n"); + return -1; + } + + /* copy from source to target section */ + memcpy(dest, pdata + section_src_offset, section_size); + flush_dcache_range((uintptr_t)dest, section_size); + + /* next section */ + pheader += 3; + } + return 0; +} diff --git a/arm-trusted-firmware/drivers/brcm/sotp.c b/arm-trusted-firmware/drivers/brcm/sotp.c new file mode 100644 index 0000000..63c4820 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/sotp.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#ifdef USE_SOFT_SOTP +extern uint64_t soft_sotp[]; +#endif + +#define SOTP_PROG_CONTROL (SOTP_REGS_OTP_BASE + 0x0000) +#define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN 15 +#define SOTP_PROG_CONTROL__OTP_DISABLE_ECC 9 +#define SOTP_PROG_CONTROL__OTP_ECC_WREN 8 + +#define SOTP_WRDATA_0 (SOTP_REGS_OTP_BASE + 0x0004) +#define SOTP_WRDATA_1 (SOTP_REGS_OTP_BASE + 0x0008) + +#define SOTP_ADDR (SOTP_REGS_OTP_BASE + 0x000c) +#define SOTP_ADDR__OTP_ROW_ADDR_R 6 +#define SOTP_ADDR_MASK 0x3FF + +#define SOTP_CTRL_0 (SOTP_REGS_OTP_BASE + 0x0010) +#define SOTP_CTRL_0__START 0 +#define SOTP_CTRL_0__OTP_CMD 1 + +#define SOTP_STATUS_0 (SOTP_REGS_OTP_BASE + 0x0018) +#define SOTP_STATUS__FDONE 3 + +#define SOTP_STATUS_1 (SOTP_REGS_OTP_BASE + 0x001c) +#define SOTP_STATUS_1__CMD_DONE 1 +#define SOTP_STATUS_1__ECC_DET 17 + +#define SOTP_RDDATA_0 (SOTP_REGS_OTP_BASE + 0x0020) +#define SOTP_RDDATA_1 (SOTP_REGS_OTP_BASE + 0x0024) + +#define SOTP_READ 0 + +#define SOTP_PROG_WORD 10 +#define SOTP_STATUS__PROGOK 2 +#define SOTP_PROG_ENABLE 2 + +#define SOTP_ROW_DATA_MASK 0xffffffff +#define SOTP_ECC_ERR_BITS_MASK 0x1ff00000000 + +#define SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES 4 +#define SOTP_CHIP_CTRL_SW_MANU_PROG 5 +#define SOTP_CHIP_CTRL_SW_CID_PROG 6 +#define SOTP_CHIP_CTRL_SW_AB_DEVICE 8 +#define SOTP_CHIP_CTRL_SW_AB_DEV_MODE 9 +#define CHIP_STATE_UNPROGRAMMED 0x1 +#define CHIP_STATE_UNASSIGNED 0x2 + +uint64_t sotp_mem_read(uint32_t offset, uint32_t sotp_add_ecc) +{ +#ifdef USE_SOFT_SOTP + (void)sotp_add_ecc; + + return soft_sotp[offset]; +#else + uint64_t read_data = 0; + uint64_t read_data1 = 0; + uint64_t read_data2 = 0; + + /* Check for FDONE status */ + while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) != + BIT(SOTP_STATUS__FDONE)) + ; + + /* Enable OTP access by CPU */ + mmio_setbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN)); + + if (sotp_add_ecc == 1) { + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC)); + } + + if (sotp_add_ecc == 0) { + mmio_setbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC)); + } + + mmio_write_32(SOTP_ADDR, + ((offset & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R)); + mmio_write_32(SOTP_CTRL_0, (SOTP_READ << SOTP_CTRL_0__OTP_CMD)); + + /* Start bit to tell SOTP to send command to the OTP controller */ + mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + /* Wait for SOTP command done to be set */ + while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) != + BIT(SOTP_STATUS_1__CMD_DONE)) + ; + + /* Clr Start bit after command done */ + mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + if ((offset > SOTP_DEVICE_SECURE_CFG3_ROW) && + (mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__ECC_DET))) { + ERROR("SOTP ECC ERROR Detected row offset %d\n", offset); + read_data = SOTP_ECC_ERR_DETECT; + } else { + read_data1 = (uint64_t)mmio_read_32(SOTP_RDDATA_0); + read_data1 = read_data1 & 0xFFFFFFFF; + read_data2 = (uint64_t)mmio_read_32(SOTP_RDDATA_1); + read_data2 = (read_data2 & 0x1ff) << 32; + read_data = read_data1 | read_data2; + } + + /* Command done is cleared */ + mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE)); + + /* disable OTP access by CPU */ + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN)); + + return read_data; +#endif +} + +void sotp_mem_write(uint32_t addr, uint32_t sotp_add_ecc, uint64_t wdata) +{ +#ifdef USE_SOFT_SOTP + (void)sotp_add_ecc; + + soft_sotp[addr] = wdata; +#else + uint32_t loop; + uint8_t prog_array[4] = { 0x0F, 0x04, 0x08, 0x0D }; + + uint32_t chip_state_default = + (CHIP_STATE_UNASSIGNED|CHIP_STATE_UNPROGRAMMED); + uint32_t chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES); + uint32_t chip_ctrl_default = 0; + + /* + * The override settings is required to allow the customer to program + * the application specific keys into SOTP, before the conversion to + * one of the AB modes. + * At the end of write operation, the chip ctrl settings will restored + * to the state prior to write call + */ + if (chip_state & chip_state_default) { + uint32_t chip_ctrl; + + chip_ctrl_default = mmio_read_32(SOTP_CHIP_CTRL); + INFO("SOTP: enable special prog mode\n"); + + chip_ctrl = BIT(SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES) | + BIT(SOTP_CHIP_CTRL_SW_MANU_PROG) | + BIT(SOTP_CHIP_CTRL_SW_CID_PROG) | + BIT(SOTP_CHIP_CTRL_SW_AB_DEVICE); + mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl); + } + + /* Check for FDONE status */ + while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) != + BIT(SOTP_STATUS__FDONE)) + ; + + /* Enable OTP acces by CPU */ + mmio_setbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN)); + + if (addr > SOTP_DEVICE_SECURE_CFG3_ROW) { + if (sotp_add_ecc == 0) { + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN)); + } + if (sotp_add_ecc == 1) { + mmio_setbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN)); + } + } else { + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN)); + } + + mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_ENABLE << 1)); + + /* + * In order to avoid unintentional writes / programming of the OTP + * array, the OTP Controller must be put into programming mode before + * it will accept program commands. This is done by writing 0xF, 0x4, + * 0x8, 0xD with program commands prior to starting the actual + * programming sequence + */ + for (loop = 0; loop < 4; loop++) { + mmio_write_32(SOTP_WRDATA_0, prog_array[loop]); + + /* + * Start bit to tell SOTP to send command to the OTP controller + */ + mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + /* Wait for SOTP command done to <-- be set */ + while ((mmio_read_32(SOTP_STATUS_1) & + BIT(SOTP_STATUS_1__CMD_DONE)) != + BIT(SOTP_STATUS_1__CMD_DONE)) + ; + + /* Command done is cleared w1c */ + mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE)); + + /* Clr Start bit after command done */ + mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + } + + /* Check for PROGOK */ + while ((mmio_read_32(SOTP_STATUS_0) & 0x4) != BIT(SOTP_STATUS__PROGOK)) + ; + + /* Set 10 bit row address */ + mmio_write_32(SOTP_ADDR, + ((addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R)); + + /* Set SOTP Row data */ + mmio_write_32(SOTP_WRDATA_0, (wdata & SOTP_ROW_DATA_MASK)); + + /* Set SOTP ECC and error bits */ + mmio_write_32(SOTP_WRDATA_1, ((wdata & SOTP_ECC_ERR_BITS_MASK) >> 32)); + + /* Set prog_word command */ + mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_WORD << 1)); + + /* Start bit to tell SOTP to send command to the OTP controller */ + mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + /* Wait for SOTP command done to be set */ + while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) != + BIT(SOTP_STATUS_1__CMD_DONE)) + ; + + /* Command done is cleared w1c */ + mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE)); + + /* disable OTP acces by CPU */ + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN)); + + /* Clr Start bit after command done */ + mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + if (chip_state & chip_state_default) + mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl_default); + +#endif +} + +int sotp_read_key(uint8_t *key, size_t keysize, int start_row, int end_row) +{ + int row; + uint32_t status = 0; + uint32_t status2 = 0xFFFFFFFF; + uint64_t row_data; + uint32_t data; + uint32_t *temp_key = (uint32_t *)key; + + row = start_row; + while ((keysize > 0) && (row <= end_row)) { + row_data = sotp_mem_read(row, SOTP_ROW_ECC); + if (!(row_data & (SOTP_ECC_ERR_DETECT | SOTP_FAIL_BITS))) { + memcpy(temp_key++, &row_data, sizeof(uint32_t)); + keysize -= sizeof(uint32_t); + data = (uint32_t)(row_data & SOTP_ROW_DATA_MASK); + status |= data; + status2 &= data; + } + row++; + } + + if ((status2 == 0xFFFFFFFF) || (status == 0) || (row > end_row)) + return -1; + + return 0; +} + +int sotp_key_erased(void) +{ + uint64_t row_data; + int status = 0; + + row_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0); + if (row_data & SOTP_DEVICE_SECURE_CFG0_OTP_ERASED_MASK) + status = 1; + + else if (mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES) & + SOTP_REGS_SOTP_CHIP_STATES_OTP_ERASED_MASK) + status = 1; + + return status; +} + +/* + * This function optimise the SOTP redundancy + * by considering the 00- zero and 01,10,11 - one + */ +uint32_t sotp_redundancy_reduction(uint32_t sotp_row_data) +{ + uint32_t opt_data; + uint32_t opt_loop; + uint32_t temp_data; + + opt_data = 0; + + for (opt_loop = 0; opt_loop < 16; opt_loop = opt_loop + 1) { + temp_data = ((sotp_row_data >> (opt_loop * 2)) & 0x3); + + if (temp_data != 0x0) + opt_data = (opt_data | (1 << opt_loop)); + } + return opt_data; +} diff --git a/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c b/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c new file mode 100644 index 0000000..4c533d5 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "iproc_qspi.h" + +struct bcmspi_priv spi_cfg; + +/* Redefined by platform to force appropriate information */ +#pragma weak plat_spi_init +int plat_spi_init(uint32_t *max_hz) +{ + return 0; +} + +/* Initialize & setup iproc qspi controller */ +int iproc_qspi_setup(uint32_t bus, uint32_t cs, uint32_t max_hz, uint32_t mode) +{ + struct bcmspi_priv *priv = NULL; + uint32_t spbr; + + priv = &spi_cfg; + priv->spi_mode = mode; + priv->state = QSPI_STATE_DISABLED; + priv->bspi_hw = QSPI_BSPI_MODE_REG_BASE; + priv->mspi_hw = QSPI_MSPI_MODE_REG_BASE; + + /* Initialize clock and platform specific */ + if (plat_spi_init(&max_hz) != 0) + return -1; + + priv->max_hz = max_hz; + + /* MSPI: Basic hardware initialization */ + mmio_write_32(priv->mspi_hw + MSPI_SPCR1_LSB_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_SPCR1_MSB_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_NEWQP_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_ENDQP_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG, 0); + + /* MSPI: SCK configuration */ + spbr = (QSPI_AXI_CLK - 1) / (2 * priv->max_hz) + 1; + spbr = MIN(spbr, SPBR_DIV_MAX); + spbr = MAX(spbr, SPBR_DIV_MIN); + mmio_write_32(priv->mspi_hw + MSPI_SPCR0_LSB_REG, spbr); + + /* MSPI: Mode configuration (8 bits by default) */ + priv->mspi_16bit = 0; + mmio_write_32(priv->mspi_hw + MSPI_SPCR0_MSB_REG, + BIT(MSPI_SPCR0_MSB_REG_MSTR_SHIFT) | /* Master */ + MSPI_SPCR0_MSB_REG_16_BITS_PER_WD_SHIFT | /* 16 bits per word */ + (priv->spi_mode & MSPI_SPCR0_MSB_REG_MODE_MASK)); /* mode: CPOL / CPHA */ + + /* Display bus info */ + VERBOSE("SPI: SPCR0_LSB: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR0_LSB_REG)); + VERBOSE("SPI: SPCR0_MSB: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR0_MSB_REG)); + VERBOSE("SPI: SPCR1_LSB: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR1_LSB_REG)); + VERBOSE("SPI: SPCR1_MSB: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR1_MSB_REG)); + VERBOSE("SPI: SPCR2: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR2_REG)); + VERBOSE("SPI: CLK: %d\n", priv->max_hz); + + return 0; +} + +void bcmspi_enable_bspi(struct bcmspi_priv *priv) +{ + if (priv->state != QSPI_STATE_BSPI) { + /* Switch to BSPI */ + mmio_write_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG, 0); + + priv->state = QSPI_STATE_BSPI; + } +} + +static int bcmspi_disable_bspi(struct bcmspi_priv *priv) +{ + uint32_t retry; + + if (priv->state == QSPI_STATE_MSPI) + return 0; + + /* Switch to MSPI if not yet */ + if ((mmio_read_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG) & + MSPI_CTRL_MASK) == 0) { + retry = QSPI_RETRY_COUNT_US_MAX; + do { + if ((mmio_read_32( + priv->bspi_hw + BSPI_BUSY_STATUS_REG) & + BSPI_BUSY_MASK) == 0) { + mmio_write_32(priv->bspi_hw + + BSPI_MAST_N_BOOT_CTRL_REG, + MSPI_CTRL_MASK); + udelay(1); + break; + } + udelay(1); + } while (retry--); + + if ((mmio_read_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG) & + MSPI_CTRL_MASK) != MSPI_CTRL_MASK) { + ERROR("QSPI: Switching to QSPI error.\n"); + return -1; + } + } + + /* Update state */ + priv->state = QSPI_STATE_MSPI; + + return 0; +} + +int iproc_qspi_claim_bus(void) +{ + struct bcmspi_priv *priv = &spi_cfg; + + /* Switch to MSPI by default */ + if (bcmspi_disable_bspi(priv) != 0) + return -1; + + return 0; +} + +void iproc_qspi_release_bus(void) +{ + struct bcmspi_priv *priv = &spi_cfg; + + /* Switch to BSPI by default */ + bcmspi_enable_bspi(priv); +} + +static int mspi_xfer(struct bcmspi_priv *priv, uint32_t bytes, + const uint8_t *tx, uint8_t *rx, uint32_t flag) +{ + uint32_t retry; + uint32_t mode = CDRAM_PCS0; + + if (flag & SPI_XFER_QUAD) { + mode |= CDRAM_QUAD_MODE; + VERBOSE("SPI: QUAD mode\n"); + + if (!tx) { + VERBOSE("SPI: 4 lane input\n"); + mode |= CDRAM_RBIT_INPUT; + } + } + + /* Use 8-bit queue for odd-bytes transfer */ + if (bytes & 1) + priv->mspi_16bit = 0; + else { + priv->mspi_16bit = 1; + mode |= CDRAM_BITS_EN; + } + + while (bytes) { + uint32_t chunk; + uint32_t queues; + uint32_t i; + + /* Separate code for 16bit and 8bit transfers for performance */ + if (priv->mspi_16bit) { + VERBOSE("SPI: 16 bits xfer\n"); + /* Determine how many bytes to process this time */ + chunk = MIN(bytes, NUM_CDRAM_BYTES * 2); + queues = (chunk - 1) / 2 + 1; + bytes -= chunk; + + /* Fill CDRAMs */ + for (i = 0; i < queues; i++) + mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG + + (i << 2), mode | CDRAM_CONT); + + /* Fill TXRAMs */ + for (i = 0; i < chunk; i++) + if (tx) + mmio_write_32(priv->mspi_hw + + MSPI_TXRAM_REG + + (i << 2), tx[i]); + } else { + VERBOSE("SPI: 8 bits xfer\n"); + /* Determine how many bytes to process this time */ + chunk = MIN(bytes, NUM_CDRAM_BYTES); + queues = chunk; + bytes -= chunk; + + /* Fill CDRAMs and TXRAMS */ + for (i = 0; i < chunk; i++) { + mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG + + (i << 2), mode | CDRAM_CONT); + if (tx) + mmio_write_32(priv->mspi_hw + + MSPI_TXRAM_REG + + (i << 3), tx[i]); + } + } + + /* Advance pointers */ + if (tx) + tx += chunk; + + /* Setup queue pointers */ + mmio_write_32(priv->mspi_hw + MSPI_NEWQP_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_ENDQP_REG, queues - 1); + + /* Remove CONT on the last byte command */ + if (bytes == 0 && (flag & SPI_XFER_END)) + mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG + + ((queues - 1) << 2), mode); + + /* Kick off */ + mmio_write_32(priv->mspi_hw + MSPI_STATUS_REG, 0); + if (bytes == 0 && (flag & SPI_XFER_END)) + mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG, MSPI_SPE); + else + mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG, + MSPI_SPE | MSPI_CONT_AFTER_CMD); + + /* Wait for completion */ + retry = QSPI_RETRY_COUNT_US_MAX; + do { + if (mmio_read_32(priv->mspi_hw + MSPI_STATUS_REG) & + MSPI_CMD_COMPLETE_MASK) + break; + udelay(1); + } while (retry--); + + if ((mmio_read_32(priv->mspi_hw + MSPI_STATUS_REG) & + MSPI_CMD_COMPLETE_MASK) == 0) { + ERROR("SPI: Completion timeout.\n"); + return -1; + } + + /* Read data out */ + if (rx) { + if (priv->mspi_16bit) { + for (i = 0; i < chunk; i++) { + rx[i] = mmio_read_32(priv->mspi_hw + + MSPI_RXRAM_REG + + (i << 2)) + & 0xff; + } + } else { + for (i = 0; i < chunk; i++) { + rx[i] = mmio_read_32(priv->mspi_hw + + MSPI_RXRAM_REG + + (((i << 1) + 1) << 2)) + & 0xff; + } + } + rx += chunk; + } + } + + return 0; +} + +int iproc_qspi_xfer(uint32_t bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct bcmspi_priv *priv; + const uint8_t *tx = dout; + uint8_t *rx = din; + uint32_t bytes = bitlen / 8; + int ret = 0; + + priv = &spi_cfg; + + if (priv->state == QSPI_STATE_DISABLED) { + ERROR("QSPI: state disabled\n"); + return -1; + } + + /* we can only do 8 bit transfers */ + if (bitlen % 8) { + ERROR("QSPI: Only support 8 bit transfers (requested %d)\n", + bitlen); + return -1; + } + + /* MSPI: Enable write lock at the beginning */ + if (flags & SPI_XFER_BEGIN) { + /* Switch to MSPI if not yet */ + if (bcmspi_disable_bspi(priv) != 0) { + ERROR("QSPI: Switch to MSPI failed\n"); + return -1; + } + + mmio_write_32(priv->mspi_hw + MSPI_WRITE_LOCK_REG, 1); + } + + /* MSPI: Transfer it */ + if (bytes) + ret = mspi_xfer(priv, bytes, tx, rx, flags); + + /* MSPI: Disable write lock if it's done */ + if (flags & SPI_XFER_END) + mmio_write_32(priv->mspi_hw + MSPI_WRITE_LOCK_REG, 0); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h b/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h new file mode 100644 index 0000000..7a8bd91 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IPROC_QSPI_H +#define IPROC_QSPI_H + +#include + +/*SPI configuration enable*/ +#define IPROC_QSPI_CLK_SPEED 62500000 +#define SPI_CPHA (1 << 0) +#define SPI_CPOL (1 << 1) +#define IPROC_QSPI_MODE0 0 +#define IPROC_QSPI_MODE3 (SPI_CPOL|SPI_CPHA) + +#define IPROC_QSPI_BUS 0 +#define IPROC_QSPI_CS 0 +#define IPROC_QSPI_BASE_REG QSPI_CTRL_BASE_ADDR +#define IPROC_QSPI_CRU_CONTROL_REG QSPI_CLK_CTRL + +#define QSPI_AXI_CLK 200000000 + +#define QSPI_RETRY_COUNT_US_MAX 200000 + +/* Chip attributes */ +#define QSPI_REG_BASE IPROC_QSPI_BASE_REG +#define CRU_CONTROL_REG IPROC_QSPI_CRU_CONTROL_REG +#define SPBR_DIV_MIN 8U +#define SPBR_DIV_MAX 255U +#define NUM_CDRAM_BYTES 16U + +/* Register fields */ +#define MSPI_SPCR0_MSB_BITS_8 0x00000020 + +/* Flash opcode and parameters */ +#define CDRAM_PCS0 2 +#define CDRAM_CONT (1 << 7) +#define CDRAM_BITS_EN (1 << 6) +#define CDRAM_QUAD_MODE (1 << 8) +#define CDRAM_RBIT_INPUT (1 << 10) + +/* MSPI registers */ +#define QSPI_MSPI_MODE_REG_BASE (QSPI_REG_BASE + 0x200) +#define MSPI_SPCR0_LSB_REG 0x000 +#define MSPI_SPCR0_MSB_REG 0x004 +#define MSPI_SPCR1_LSB_REG 0x008 +#define MSPI_SPCR1_MSB_REG 0x00c +#define MSPI_NEWQP_REG 0x010 +#define MSPI_ENDQP_REG 0x014 +#define MSPI_SPCR2_REG 0x018 +#define MSPI_STATUS_REG 0x020 +#define MSPI_CPTQP_REG 0x024 +#define MSPI_TXRAM_REG 0x040 +#define MSPI_RXRAM_REG 0x0c0 +#define MSPI_CDRAM_REG 0x140 +#define MSPI_WRITE_LOCK_REG 0x180 +#define MSPI_DISABLE_FLUSH_GEN_REG 0x184 + +#define MSPI_SPCR0_MSB_REG_MSTR_SHIFT 7 +#define MSPI_SPCR0_MSB_REG_16_BITS_PER_WD_SHIFT (0 << 2) +#define MSPI_SPCR0_MSB_REG_MODE_MASK 0x3 + +/* BSPI registers */ +#define QSPI_BSPI_MODE_REG_BASE QSPI_REG_BASE +#define BSPI_MAST_N_BOOT_CTRL_REG 0x008 +#define BSPI_BUSY_STATUS_REG 0x00c + +#define MSPI_CMD_COMPLETE_MASK 1 +#define BSPI_BUSY_MASK 1 +#define MSPI_CTRL_MASK 1 + +#define MSPI_SPE (1 << 6) +#define MSPI_CONT_AFTER_CMD (1 << 7) + +/* State */ +enum bcm_qspi_state { + QSPI_STATE_DISABLED, + QSPI_STATE_MSPI, + QSPI_STATE_BSPI +}; + +/* QSPI private data */ +struct bcmspi_priv { + /* Specified SPI parameters */ + uint32_t max_hz; + uint32_t spi_mode; + + /* State */ + enum bcm_qspi_state state; + int mspi_16bit; + + /* Registers */ + uintptr_t mspi_hw; + uintptr_t bspi_hw; +}; + +int iproc_qspi_setup(uint32_t bus, uint32_t cs, + uint32_t max_hz, uint32_t mode); +int iproc_qspi_claim_bus(void); +void iproc_qspi_release_bus(void); +int iproc_qspi_xfer(uint32_t bitlen, const void *dout, + void *din, unsigned long flags); + +#endif /* _IPROC_QSPI_H_ */ diff --git a/arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c b/arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c new file mode 100644 index 0000000..551e587 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "iproc_qspi.h" + +int spi_init(void) +{ + return iproc_qspi_setup(IPROC_QSPI_BUS, IPROC_QSPI_CS, + IPROC_QSPI_CLK_SPEED, IPROC_QSPI_MODE0); +} + +int spi_claim_bus(void) +{ + return iproc_qspi_claim_bus(); +} + +void spi_release_bus(void) +{ + iproc_qspi_release_bus(); +} + +int spi_xfer(uint32_t bitlen, const void *dout, + void *din, uint32_t flags) +{ + return iproc_qspi_xfer(bitlen, dout, din, flags); +} diff --git a/arm-trusted-firmware/drivers/brcm/spi_flash.c b/arm-trusted-firmware/drivers/brcm/spi_flash.c new file mode 100644 index 0000000..336d230 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi_flash.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define SPI_FLASH_CMD_LEN 4 +#define QSPI_WAIT_TIMEOUT_US 200000U /* usec */ + +#define FINFO(jedec_id, ext_id, _sector_size, _n_sectors, _page_size, _flags) \ + .id = { \ + ((jedec_id) >> 16) & 0xff, \ + ((jedec_id) >> 8) & 0xff, \ + (jedec_id) & 0xff, \ + ((ext_id) >> 8) & 0xff, \ + (ext_id) & 0xff, \ + }, \ + .id_len = (!(jedec_id) ? 0 : (3 + ((ext_id) ? 2 : 0))), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = _page_size, \ + .flags = (_flags), + +/* SPI/QSPI flash device params structure */ +const struct spi_flash_info spi_flash_ids[] = { + {"W25Q64CV", FINFO(0xef4017, 0x0, 64 * 1024, 128, 256, WR_QPP | SECT_4K)}, + {"W25Q64DW", FINFO(0xef6017, 0x0, 64 * 1024, 128, 256, WR_QPP | SECT_4K)}, + {"W25Q32", FINFO(0xef4016, 0x0, 64 * 1024, 64, 256, SECT_4K)}, + {"MX25l3205D", FINFO(0xc22016, 0x0, 64 * 1024, 64, 256, SECT_4K)}, +}; + +static void spi_flash_addr(uint32_t addr, uint8_t *cmd) +{ + /* + * cmd[0] holds a SPI Flash command, stored earlier + * cmd[1/2/3] holds 24bit flash address + */ + cmd[1] = addr >> 16; + cmd[2] = addr >> 8; + cmd[3] = addr >> 0; +} + +static const struct spi_flash_info *spi_flash_read_id(void) +{ + const struct spi_flash_info *info; + uint8_t id[SPI_FLASH_MAX_ID_LEN]; + int ret; + + ret = spi_flash_cmd(CMD_READ_ID, id, SPI_FLASH_MAX_ID_LEN); + if (ret < 0) { + ERROR("SF: Error %d reading JEDEC ID\n", ret); + return NULL; + } + + for (info = spi_flash_ids; info->name != NULL; info++) { + if (info->id_len) { + if (!memcmp(info->id, id, info->id_len)) + return info; + } + } + + printf("SF: unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); + return NULL; +} + +/* Enable writing on the SPI flash */ +static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) +{ + return spi_flash_cmd(CMD_WRITE_ENABLE, NULL, 0); +} + +static int spi_flash_cmd_wait(struct spi_flash *flash) +{ + uint8_t cmd; + uint32_t i; + uint8_t status; + int ret; + + i = 0; + while (1) { + cmd = CMD_RDSR; + ret = spi_flash_cmd_read(&cmd, 1, &status, 1); + if (ret < 0) { + ERROR("SF: cmd wait failed\n"); + break; + } + if (!(status & STATUS_WIP)) + break; + + i++; + if (i >= QSPI_WAIT_TIMEOUT_US) { + ERROR("SF: cmd wait timeout\n"); + ret = -1; + break; + } + udelay(1); + } + + return ret; +} + +static int spi_flash_write_common(struct spi_flash *flash, const uint8_t *cmd, + size_t cmd_len, const void *buf, + size_t buf_len) +{ + int ret; + + ret = spi_flash_cmd_write_enable(flash); + if (ret < 0) { + ERROR("SF: enabling write failed\n"); + return ret; + } + + ret = spi_flash_cmd_write(cmd, cmd_len, buf, buf_len); + if (ret < 0) { + ERROR("SF: write cmd failed\n"); + return ret; + } + + ret = spi_flash_cmd_wait(flash); + if (ret < 0) { + ERROR("SF: write timed out\n"); + return ret; + } + + return ret; +} + +static int spi_flash_read_common(const uint8_t *cmd, size_t cmd_len, + void *data, size_t data_len) +{ + int ret; + + ret = spi_flash_cmd_read(cmd, cmd_len, data, data_len); + if (ret < 0) { + ERROR("SF: read cmd failed\n"); + return ret; + } + + return ret; +} + +int spi_flash_read(struct spi_flash *flash, uint32_t offset, + uint32_t len, void *data) +{ + uint32_t read_len = 0, read_addr; + uint8_t cmd[SPI_FLASH_CMD_LEN]; + int ret; + + ret = spi_claim_bus(); + if (ret) { + ERROR("SF: unable to claim SPI bus\n"); + return ret; + } + + cmd[0] = CMD_READ_NORMAL; + while (len) { + read_addr = offset; + read_len = MIN(flash->page_size, (len - read_len)); + spi_flash_addr(read_addr, cmd); + + ret = spi_flash_read_common(cmd, sizeof(cmd), data, read_len); + if (ret < 0) { + ERROR("SF: read failed\n"); + break; + } + + offset += read_len; + len -= read_len; + data += read_len; + } + SPI_DEBUG("SF read done\n"); + + spi_release_bus(); + return ret; +} + +int spi_flash_write(struct spi_flash *flash, uint32_t offset, + uint32_t len, void *buf) +{ + unsigned long byte_addr, page_size; + uint8_t cmd[SPI_FLASH_CMD_LEN]; + uint32_t chunk_len, actual; + uint32_t write_addr; + int ret; + + ret = spi_claim_bus(); + if (ret) { + ERROR("SF: unable to claim SPI bus\n"); + return ret; + } + + page_size = flash->page_size; + + cmd[0] = flash->write_cmd; + for (actual = 0; actual < len; actual += chunk_len) { + write_addr = offset; + byte_addr = offset % page_size; + chunk_len = MIN(len - actual, + (uint32_t)(page_size - byte_addr)); + spi_flash_addr(write_addr, cmd); + + SPI_DEBUG("SF:0x%p=>cmd:{0x%02x 0x%02x%02x%02x} chunk_len:%d\n", + buf + actual, cmd[0], cmd[1], + cmd[2], cmd[3], chunk_len); + + ret = spi_flash_write_common(flash, cmd, sizeof(cmd), + buf + actual, chunk_len); + if (ret < 0) { + ERROR("SF: write cmd failed\n"); + break; + } + + offset += chunk_len; + } + SPI_DEBUG("SF write done\n"); + + spi_release_bus(); + return ret; +} + +int spi_flash_erase(struct spi_flash *flash, uint32_t offset, uint32_t len) +{ + uint8_t cmd[SPI_FLASH_CMD_LEN]; + uint32_t erase_size, erase_addr; + int ret; + + erase_size = flash->erase_size; + + if (offset % erase_size || len % erase_size) { + ERROR("SF: Erase offset/length not multiple of erase size\n"); + return -1; + } + + ret = spi_claim_bus(); + if (ret) { + ERROR("SF: unable to claim SPI bus\n"); + return ret; + } + + cmd[0] = flash->erase_cmd; + while (len) { + erase_addr = offset; + spi_flash_addr(erase_addr, cmd); + + SPI_DEBUG("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], + cmd[2], cmd[3], erase_addr); + + ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); + if (ret < 0) { + ERROR("SF: erase failed\n"); + break; + } + + offset += erase_size; + len -= erase_size; + } + SPI_DEBUG("sf erase done\n"); + + spi_release_bus(); + return ret; +} + +int spi_flash_probe(struct spi_flash *flash) +{ + const struct spi_flash_info *info = NULL; + int ret; + + ret = spi_claim_bus(); + if (ret) { + ERROR("SF: Unable to claim SPI bus\n"); + ERROR("SF: probe failed\n"); + return ret; + } + + info = spi_flash_read_id(); + if (!info) + goto probe_fail; + + INFO("Flash Name: %s sectors %x, sec size %x\n", + info->name, info->n_sectors, + info->sector_size); + flash->size = info->n_sectors * info->sector_size; + flash->sector_size = info->sector_size; + flash->page_size = info->page_size; + flash->flags = info->flags; + + flash->read_cmd = CMD_READ_NORMAL; + flash->write_cmd = CMD_PAGE_PROGRAM; + flash->erase_cmd = CMD_ERASE_64K; + flash->erase_size = ERASE_SIZE_64K; + +probe_fail: + spi_release_bus(); + return ret; +} diff --git a/arm-trusted-firmware/drivers/brcm/spi_sf.c b/arm-trusted-firmware/drivers/brcm/spi_sf.c new file mode 100644 index 0000000..8bbb09f --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi_sf.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#define BITS_PER_BYTE 8 +#define CMD_LEN1 1 + +static int spi_flash_read_write(const uint8_t *cmd, + size_t cmd_len, + const uint8_t *data_out, + uint8_t *data_in, + size_t data_len) +{ + unsigned long flags = SPI_XFER_BEGIN; + int ret; + + if (data_len == 0) + flags |= SPI_XFER_END; + + ret = spi_xfer(cmd_len * BITS_PER_BYTE, cmd, NULL, flags); + if (ret) { + ERROR("SF: Failed to send command (%zu bytes): %d\n", + cmd_len, ret); + } else if (data_len != 0) { + ret = spi_xfer(data_len * BITS_PER_BYTE, data_out, + data_in, SPI_XFER_END); + if (ret) + ERROR("SF: Failed to transfer %zu bytes of data: %d\n", + data_len, ret); + } + + return ret; +} + +int spi_flash_cmd_read(const uint8_t *cmd, + size_t cmd_len, + void *data, + size_t data_len) +{ + return spi_flash_read_write(cmd, cmd_len, NULL, data, data_len); +} + +int spi_flash_cmd(uint8_t cmd, void *response, size_t len) +{ + return spi_flash_cmd_read(&cmd, CMD_LEN1, response, len); +} + +int spi_flash_cmd_write(const uint8_t *cmd, + size_t cmd_len, + const void *data, + size_t data_len) +{ + return spi_flash_read_write(cmd, cmd_len, data, NULL, data_len); +} diff --git a/arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S b/arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S new file mode 100644 index 0000000..4c1a80e --- /dev/null +++ b/arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_cdns_core_init + .globl console_cdns_core_putc + .globl console_cdns_core_getc + .globl console_cdns_core_flush + + .globl console_cdns_putc + .globl console_cdns_getc + .globl console_cdns_flush + + /* ----------------------------------------------- + * int console_cdns_core_init(uintptr_t base_addr) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * We assume that the bootloader already set up + * the HW (baud, ...) and only enable the trans- + * mitter and receiver here. + * In: x0 - console base address + * Out: return 1 on success else 0 on error + * Clobber list : x1, x2, x3 + * ----------------------------------------------- + */ +func console_cdns_core_init + /* Check the input base address */ + cbz x0, core_init_fail + + /* RX/TX enabled & reset */ + mov w3, #(R_UART_CR_TX_EN | R_UART_CR_RX_EN | R_UART_CR_TXRST | R_UART_CR_RXRST) + str w3, [x0, #R_UART_CR] + + mov w0, #1 + ret +core_init_fail: + mov w0, wzr + ret +endfunc console_cdns_core_init + + .globl console_cdns_register + + /* ----------------------------------------------- + * int console_cdns_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new CDNS + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_cdns_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_cdns_core_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register cdns putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_cdns_register + + /* -------------------------------------------------------- + * int console_cdns_core_putc(int c, uintptr_t base_addr) + * 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 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_cdns_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f +1: + /* Check if the transmit FIFO is empty */ + ldr w2, [x1, #R_UART_SR] + tbz w2, #UART_SR_INTR_TEMPTY_BIT, 1b + mov w2, #0xD + str w2, [x1, #R_UART_TX] +2: + /* Check if the transmit FIFO is empty */ + ldr w2, [x1, #R_UART_SR] + tbz w2, #UART_SR_INTR_TEMPTY_BIT, 2b + str w0, [x1, #R_UART_TX] + ret +endfunc console_cdns_core_putc + + /* -------------------------------------------------------- + * int console_cdns_putc(int c, console_t *cdns) + * 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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_cdns_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_BASE] + b console_cdns_core_putc +endfunc console_cdns_putc + + /* --------------------------------------------- + * int console_cdns_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - console base address + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_cdns_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ + ldr w1, [x0, #R_UART_SR] + tbnz w1, #UART_SR_INTR_REMPTY_BIT, no_char + ldr w1, [x0, #R_UART_RX] + mov w0, w1 + ret +no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_cdns_core_getc + + /* --------------------------------------------- + * int console_cdns_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - pointer to console_t structure + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_cdns_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_cdns_core_getc +endfunc console_cdns_getc + + /* --------------------------------------------- + * void console_cdns_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : void + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_cdns_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + /* Placeholder */ + ret +endfunc console_cdns_core_flush + + /* --------------------------------------------- + * void console_cdns_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_cdns_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_cdns_core_flush +endfunc console_cdns_flush diff --git a/arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c b/arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c new file mode 100644 index 0000000..6690189 --- /dev/null +++ b/arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * This file supplies a low level interface to the vexpress NOR flash + * memory of juno and fvp. This memory is organized as an interleaved + * memory of two chips with a 16 bit word. It means that every 32 bit + * access is going to access to two different chips. This is very + * important when we send commands or read status of the chips. + */ + +/* + * DWS ready poll retries. The number of retries in this driver have been + * obtained empirically from Juno. FVP implements a zero wait state NOR flash + * model + */ +#define DWS_WORD_PROGRAM_RETRIES 1000 +#define DWS_WORD_ERASE_RETRIES 3000000 +#define DWS_WORD_LOCK_RETRIES 1000 + +/* Helper macro to detect end of command */ +#define NOR_CMD_END (NOR_DWS | (NOR_DWS << 16l)) + +/* Helper macros to access two flash banks in parallel */ +#define NOR_2X16(d) ((d << 16) | (d & 0xffff)) + +static unsigned int nor_status(uintptr_t base_addr) +{ + unsigned long status; + + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + status |= status >> 16; /* merge status from both flash banks */ + + return status & 0xFFFF; +} + +/* + * Poll Write State Machine. + * Return values: + * 0 = WSM ready + * -EBUSY = WSM busy after the number of retries + */ +static int nor_poll_dws(uintptr_t base_addr, unsigned long int retries) +{ + unsigned long status; + + do { + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + if ((status & NOR_CMD_END) == NOR_CMD_END) + return 0; + } while (retries-- > 0); + + return -EBUSY; +} + +/* + * Return values: + * 0 = success + * -EPERM = Device protected or Block locked + * -EIO = General I/O error + */ +static int nor_full_status_check(uintptr_t base_addr) +{ + unsigned long status; + + /* Full status check */ + status = nor_status(base_addr); + + if (status & (NOR_PS | NOR_BLS | NOR_ESS | NOR_PSS)) + return -EPERM; + if (status & (NOR_VPPS | NOR_ES)) + return -EIO; + return 0; +} + +void nor_send_cmd(uintptr_t base_addr, unsigned long cmd) +{ + mmio_write_32(base_addr, NOR_2X16(cmd)); +} + +/* + * This function programs a word in the flash. Be aware that it only + * can reset bits that were previously set. It cannot set bits that + * were previously reset. The resulting bits = old_bits & new bits. + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_word_program(uintptr_t base_addr, unsigned long data) +{ + uint32_t status; + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + /* Set the device in write word mode */ + nor_send_cmd(base_addr, NOR_CMD_WORD_PROGRAM); + mmio_write_32(base_addr, data); + + ret = nor_poll_dws(base_addr, DWS_WORD_PROGRAM_RETRIES); + if (ret == 0) { + /* Full status check */ + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + + if (status & (NOR_PS | NOR_BLS)) { + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + ret = -EPERM; + } + } + + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * Erase a full 256K block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_erase(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_BLOCK_ERASE); + nor_send_cmd(base_addr, NOR_CMD_BLOCK_ERASE_ACK); + + ret = nor_poll_dws(base_addr, DWS_WORD_ERASE_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * Lock a full 256 block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_lock(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK); + nor_send_cmd(base_addr, NOR_LOCK_BLOCK); + + ret = nor_poll_dws(base_addr, DWS_WORD_LOCK_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * unlock a full 256 block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_unlock(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK); + nor_send_cmd(base_addr, NOR_UNLOCK_BLOCK); + + ret = nor_poll_dws(base_addr, DWS_WORD_LOCK_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/clk/clk.c b/arm-trusted-firmware/drivers/clk/clk.c new file mode 100644 index 0000000..4cbc0f7 --- /dev/null +++ b/arm-trusted-firmware/drivers/clk/clk.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * Author(s): Ludovic Barre, for STMicroelectronics. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +static const struct clk_ops *ops; + +int clk_enable(unsigned long id) +{ + assert((ops != NULL) && (ops->enable != NULL)); + + return ops->enable(id); +} + +void clk_disable(unsigned long id) +{ + assert((ops != NULL) && (ops->disable != NULL)); + + ops->disable(id); +} + +unsigned long clk_get_rate(unsigned long id) +{ + assert((ops != NULL) && (ops->get_rate != NULL)); + + return ops->get_rate(id); +} + +int clk_get_parent(unsigned long id) +{ + assert((ops != NULL) && (ops->get_parent != NULL)); + + return ops->get_parent(id); +} + +bool clk_is_enabled(unsigned long id) +{ + assert((ops != NULL) && (ops->is_enabled != NULL)); + + return ops->is_enabled(id); +} + +/* + * Initialize the clk. The fields in the provided clk + * ops pointer must be valid. + */ +void clk_register(const struct clk_ops *ops_ptr) +{ + assert((ops_ptr != NULL) && + (ops_ptr->enable != NULL) && + (ops_ptr->disable != NULL) && + (ops_ptr->get_rate != NULL) && + (ops_ptr->get_parent != NULL) && + (ops_ptr->is_enabled != NULL)); + + ops = ops_ptr; +} diff --git a/arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S b/arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S new file mode 100644 index 0000000..a9e13ec --- /dev/null +++ b/arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2016-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 register + * r12, but may never depend on it retaining its value 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 : r0 - pointer to empty console_t structure + * r1 through r7: additional parameters as desired + * Out: r0 - 1 on success, 0 on error + * Clobber list : r0 - r7 + * ----------------------------------------------- + */ +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 r1, [r0, #CONSOLE_T_BASE] + str r2, [r0, #CONSOLE_T_XXX_SOME_OTHER_VALUE] + + /* + * Initialize console hardware, using r1 - r7 parameters as needed. + * Keep console_t pointer in r0 for later. + */ + + /* + * Macro to finish up registration and return (needs valid r0 + lr). + * 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 r0, #0 + bx lr +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 : r0 - character to be printed + * r1 - pointer to console_t struct + * Out: r0 - printed character on success, < 0 on error. + * Clobber list : r0, r1, r2 + * -------------------------------------------------------- + */ +func console_xxx_putc + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by r1. + * Example: + */ + ldr r1, [r1, #CONSOLE_T_BASE] + + /* + * Write r0 to hardware. + */ + + bx lr + + /* Jump here if output fails for any reason. */ +putc_error: + mov r0, #-1 + bx lr +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 : r0 - pointer to console_t struct + * Out: r0 - character on success, + * ERROR_NO_PENDING_CHAR if no char, + * < -1 on error + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_xxx_getc + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by r0. + * Example: + */ + ldr r1, [r0, #CONSOLE_T_BASE] + + /* + * Try to read character into r0 from hardware. + */ + + bx lr + + /* Jump here if there is no character available at this time. */ +getc_no_char: + mov r0, #ERROR_NO_PENDING_CHAR + bx lr + + /* Jump here if there was any hardware error. */ +getc_error: + mov r0, #-2 /* may pick error codes between -2 and -127 */ + bx lr +endfunc console_xxx_getc + + /* --------------------------------------------- + * int console_xxx_flush(console_xxx_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - pointer to console_xxx_t struct + * Out: void + * Clobber list : r0, r1, r2, r3, r4, r5 + * --------------------------------------------- + */ +func console_xxx_flush + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by r0. + * Example: + */ + ldr r1, [r0, #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. + */ + + bx lr +endfunc console_xxx_flush diff --git a/arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S b/arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S new file mode 100644 index 0000000..7ea2eec --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/console/multi_console.c b/arm-trusted-firmware/drivers/console/multi_console.c new file mode 100644 index 0000000..08b8e9f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S new file mode 100644 index 0000000..db07e6c --- /dev/null +++ b/arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* + * This driver implements access to coreboot's in-memory console + * (CBMEM console). For the original implementation, see + * /src/lib/cbmem_console.c. + */ + + .globl console_cbmc_register + .globl console_cbmc_putc + .globl console_cbmc_flush + + /* ----------------------------------------------- + * int console_cbmc_register(uintptr_t base, + * console_cbmc_t *console); + * Registers a new CBMEM console instance. Reads + * the size field from the buffer header structure + * and stores it in our console_cbmc_t struct, so + * that we keep the size in secure memory where we + * can trust it. A malicious EL1 could manipulate + * the console buffer (including the header), so we + * must not trust its contents after boot. + * In: x0 - CBMEM console base address + * x1 - pointer to empty console_cbmc_t struct + * Out: x0 - 1 to indicate success + * Clobber list: x0, x1, x2, x7 + * ----------------------------------------------- + */ +func console_cbmc_register + str x0, [x1, #CONSOLE_T_BASE] + ldr w2, [x0] + str w2, [x1, #CONSOLE_T_CBMC_SIZE] + mov x0, x1 + finish_console_register cbmc putc=1, flush=1 +endfunc console_cbmc_register + + /* ----------------------------------------------- + * int console_cbmc_puts(int c, console_cbmc_t *console) + * Writes a character to the CBMEM console buffer, + * including overflow handling of the cursor field. + * The character must be preserved in x0. + * In: x0 - character to be stored + * x1 - pointer to console_cbmc_t struct + * Clobber list: x1, x2, x16, x17 + * ----------------------------------------------- + */ +func console_cbmc_putc + ldr w2, [x1, #CONSOLE_T_CBMC_SIZE] + ldr x1, [x1, #CONSOLE_T_BASE] + add x1, x1, #8 /* keep address of body in x1 */ + + ldr w16, [x1, #-4] /* load cursor (one u32 before body) */ + and w17, w16, #0xf0000000 /* keep flags part in w17 */ + and w16, w16, #0x0fffffff /* keep actual cursor part in w16 */ + + cmp w16, w2 /* sanity check that cursor < size */ + b.lo putc_within_bounds + mov w0, #-1 /* cursor >= size must be malicious */ + ret /* so return error, don't write char */ + +putc_within_bounds: + strb w0, [x1, w16, uxtw] /* body[cursor] = character */ + add w16, w16, #1 /* cursor++ */ + cmp w16, w2 /* if cursor < size... */ + b.lo putc_write_back /* ...skip overflow handling */ + + mov w16, #0 /* on overflow, set cursor back to 0 */ + orr w17, w17, #(1 << 31) /* and set overflow flag */ + +putc_write_back: + orr w16, w16, w17 /* merge cursor and flags back */ + str w16, [x1, #-4] /* write back cursor to memory */ + ret +endfunc console_cbmc_putc + + /* ----------------------------------------------- + * void console_cbmc_flush(console_cbmc_t *console) + * Flushes the CBMEM console by flushing the + * console buffer from the CPU's data cache. + * In: x0 - pointer to console_cbmc_t struct + * Out: void + * Clobber list: x0, x1, x2, x3 + * ----------------------------------------------- + */ +func console_cbmc_flush + ldr x1, [x0, #CONSOLE_T_CBMC_SIZE] + ldr x0, [x0, #CONSOLE_T_BASE] + add x1, x1, #8 /* add size of console header */ + b clean_dcache_range /* (clobbers x2 and x3) */ +endfunc console_cbmc_flush diff --git a/arm-trusted-firmware/drivers/delay_timer/delay_timer.c b/arm-trusted-firmware/drivers/delay_timer/delay_timer.c new file mode 100644 index 0000000..a3fd7bf --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c b/arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c new file mode 100644 index 0000000..ca522e0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/fwu/fwu.c b/arm-trusted-firmware/drivers/fwu/fwu.c new file mode 100644 index 0000000..ff432be --- /dev/null +++ b/arm-trusted-firmware/drivers/fwu/fwu.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* + * Assert that crc_32 is the first member of fwu_metadata structure. + * It avoids accessing data outside of the metadata structure during + * CRC32 computation if the crc_32 field gets moved due the structure + * member(s) addition in the future. + */ +CASSERT((offsetof(struct fwu_metadata, crc_32) == 0), + crc_32_must_be_first_member_of_structure); + +static struct fwu_metadata metadata; +static bool is_metadata_initialized __unused; + +/******************************************************************************* + * Compute CRC32 of the FWU metadata, and check it against the CRC32 value + * present in the FWU metadata. + * + * return -1 on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_crc_check(void) +{ + unsigned char *data = (unsigned char *)&metadata; + + uint32_t calc_crc = tf_crc32(0U, data + sizeof(metadata.crc_32), + (sizeof(metadata) - + sizeof(metadata.crc_32))); + + if (metadata.crc_32 != calc_crc) { + return -1; + } + + return 0; +} + +/******************************************************************************* + * Check the sanity of FWU metadata. + * + * return -1 on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_sanity_check(void) +{ + /* ToDo: add more conditions for sanity check */ + if ((metadata.active_index >= NR_OF_FW_BANKS) || + (metadata.previous_active_index >= NR_OF_FW_BANKS)) { + return -1; + } + + return 0; +} + +/******************************************************************************* + * Verify and load specified FWU metadata image to local FWU metadata structure. + * + * @image_id: FWU metadata image id (either FWU_METADATA_IMAGE_ID or + * BKUP_FWU_METADATA_IMAGE_ID) + * + * return a negative value on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_load(unsigned int image_id) +{ + int result; + uintptr_t dev_handle, image_handle, image_spec; + size_t bytes_read; + + assert((image_id == FWU_METADATA_IMAGE_ID) || + (image_id == BKUP_FWU_METADATA_IMAGE_ID)); + + result = plat_fwu_set_metadata_image_source(image_id, + &dev_handle, + &image_spec); + if (result != 0) { + WARN("Failed to set reference to image id=%u (%i)\n", + image_id, result); + return result; + } + + result = io_open(dev_handle, image_spec, &image_handle); + if (result != 0) { + WARN("Failed to load image id id=%u (%i)\n", + image_id, result); + return result; + } + + result = io_read(image_handle, (uintptr_t)&metadata, + sizeof(struct fwu_metadata), &bytes_read); + + if (result != 0) { + WARN("Failed to read image id=%u (%i)\n", image_id, result); + goto exit; + } + + if (sizeof(struct fwu_metadata) != bytes_read) { + /* return -1 in case of partial/no read */ + result = -1; + WARN("Read bytes (%zu) instead of expected (%zu) bytes\n", + bytes_read, sizeof(struct fwu_metadata)); + goto exit; + } + + /* sanity check on loaded parameters */ + result = fwu_metadata_sanity_check(); + if (result != 0) { + WARN("Sanity %s\n", "check failed on FWU metadata"); + goto exit; + } + + /* CRC check on loaded parameters */ + result = fwu_metadata_crc_check(); + if (result != 0) { + WARN("CRC %s\n", "check failed on FWU metadata"); + } + +exit: + (void)io_close(image_handle); + + return result; +} + +/******************************************************************************* + * The system runs in the trial run state if any of the images in the active + * firmware bank has not been accepted yet. + * + * Returns true if the system is running in the trial state. + ******************************************************************************/ +bool fwu_is_trial_run_state(void) +{ + bool trial_run = false; + + assert(is_metadata_initialized); + + for (unsigned int i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) { + struct fwu_image_entry *entry = &metadata.img_entry[i]; + struct fwu_image_properties *img_props = + &entry->img_props[metadata.active_index]; + if (img_props->accepted == 0) { + trial_run = true; + break; + } + } + + return trial_run; +} + +const struct fwu_metadata *fwu_get_metadata(void) +{ + assert(is_metadata_initialized); + + return &metadata; +} + +/******************************************************************************* + * Load verified copy of FWU metadata image kept in the platform NV storage + * into local FWU metadata structure. + * Also, update platform I/O policies with the offset address and length of + * firmware-updated images kept in the platform NV storage. + ******************************************************************************/ +void fwu_init(void) +{ + /* Load FWU metadata which will be used to load the images in the + * active bank as per PSA FWU specification + */ + int result = fwu_metadata_load(FWU_METADATA_IMAGE_ID); + + if (result != 0) { + WARN("loading of FWU-Metadata failed, " + "using Bkup-FWU-Metadata\n"); + + result = fwu_metadata_load(BKUP_FWU_METADATA_IMAGE_ID); + if (result != 0) { + ERROR("loading of Bkup-FWU-Metadata failed\n"); + panic(); + } + } + + is_metadata_initialized = true; + + plat_fwu_set_images_source(&metadata); +} diff --git a/arm-trusted-firmware/drivers/fwu/fwu.mk b/arm-trusted-firmware/drivers/fwu/fwu.mk new file mode 100644 index 0000000..f4452e0 --- /dev/null +++ b/arm-trusted-firmware/drivers/fwu/fwu.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +FWU_SRC_DIR := drivers/fwu/ + +FWU_SRCS := ${FWU_SRC_DIR}fwu.c + +BL2_SOURCES += ${FWU_SRCS} diff --git a/arm-trusted-firmware/drivers/gpio/gpio.c b/arm-trusted-firmware/drivers/gpio/gpio.c new file mode 100644 index 0000000..76612b2 --- /dev/null +++ b/arm-trusted-firmware/drivers/gpio/gpio.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * GPIO -- General Purpose Input/Output + * + * Defines a simple and generic interface to access GPIO device. + * + */ + +#include +#include + +#include + +/* + * The gpio implementation + */ +static const gpio_ops_t *ops; + +int gpio_get_direction(int gpio) +{ + assert(ops); + assert(ops->get_direction != 0); + assert(gpio >= 0); + + return ops->get_direction(gpio); +} + +void gpio_set_direction(int gpio, int direction) +{ + assert(ops); + assert(ops->set_direction != 0); + assert((direction == GPIO_DIR_OUT) || (direction == GPIO_DIR_IN)); + assert(gpio >= 0); + + ops->set_direction(gpio, direction); +} + +int gpio_get_value(int gpio) +{ + assert(ops); + assert(ops->get_value != 0); + assert(gpio >= 0); + + return ops->get_value(gpio); +} + +void gpio_set_value(int gpio, int value) +{ + assert(ops); + assert(ops->set_value != 0); + assert((value == GPIO_LEVEL_LOW) || (value == GPIO_LEVEL_HIGH)); + assert(gpio >= 0); + + ops->set_value(gpio, value); +} + +void gpio_set_pull(int gpio, int pull) +{ + assert(ops); + assert(ops->set_pull != 0); + assert((pull == GPIO_PULL_NONE) || (pull == GPIO_PULL_UP) || + (pull == GPIO_PULL_DOWN)); + assert(gpio >= 0); + + ops->set_pull(gpio, pull); +} + +int gpio_get_pull(int gpio) +{ + assert(ops); + assert(ops->get_pull != 0); + assert(gpio >= 0); + + return ops->get_pull(gpio); +} + +/* + * Initialize the gpio. The fields in the provided gpio + * ops pointer must be valid. + */ +void gpio_init(const gpio_ops_t *ops_ptr) +{ + assert(ops_ptr != 0 && + (ops_ptr->get_direction != 0) && + (ops_ptr->set_direction != 0) && + (ops_ptr->get_value != 0) && + (ops_ptr->set_value != 0)); + + ops = ops_ptr; +} diff --git a/arm-trusted-firmware/drivers/imx/timer/imx_gpt.c b/arm-trusted-firmware/drivers/imx/timer/imx_gpt.c new file mode 100644 index 0000000..464efe9 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/timer/imx_gpt.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#define GPTCR_SWR BIT(15) /* Software reset */ +#define GPTCR_24MEN BIT(10) /* Enable 24MHz clock input */ +#define GPTCR_CLKSOURCE_OSC (5 << 6) /* Clock source OSC */ +#define GPTCR_CLKSOURCE_MASK (0x7 << 6) +#define GPTCR_TEN 1 /* Timer enable */ + +#define GPTPR_PRESCL_24M_SHIFT 12 + +#define SYS_COUNTER_FREQ_IN_MHZ 3 + +#define GPTPR_TIMER_CTRL (imx_base_addr + 0x000) +#define GPTPR_TIMER_PRESCL (imx_base_addr + 0x004) +#define GPTPR_TIMER_CNTR (imx_base_addr + 0x024) + +static uintptr_t imx_base_addr; + +uint32_t imx_get_timer_value(void) +{ + return ~mmio_read_32(GPTPR_TIMER_CNTR); +} + +static const timer_ops_t imx_gpt_ops = { + .get_timer_value = imx_get_timer_value, + .clk_mult = 1, + .clk_div = SYS_COUNTER_FREQ_IN_MHZ, +}; + +void imx_gpt_ops_init(uintptr_t base_addr) +{ + int val; + + assert(base_addr != 0); + + imx_base_addr = base_addr; + + /* setup GP Timer */ + mmio_write_32(GPTPR_TIMER_CTRL, GPTCR_SWR); + mmio_write_32(GPTPR_TIMER_CTRL, 0); + + /* get 3MHz from 24MHz */ + mmio_write_32(GPTPR_TIMER_PRESCL, (7 << GPTPR_PRESCL_24M_SHIFT)); + + val = mmio_read_32(GPTPR_TIMER_CTRL); + val &= ~GPTCR_CLKSOURCE_MASK; + val |= GPTCR_24MEN | GPTCR_CLKSOURCE_OSC | GPTCR_TEN; + mmio_write_32(GPTPR_TIMER_CTRL, val); + + timer_init(&imx_gpt_ops); +} diff --git a/arm-trusted-firmware/drivers/imx/timer/imx_gpt.h b/arm-trusted-firmware/drivers/imx/timer/imx_gpt.h new file mode 100644 index 0000000..2432633 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/timer/imx_gpt.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_GPT_H +#define IMX_GPT_H + +#include + +void imx_gpt_ops_init(uintptr_t reg_base); + +#endif /* IMX_GPT_H */ diff --git a/arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S b/arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S new file mode 100644 index 0000000..aa987b3 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S @@ -0,0 +1,131 @@ +/* + * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + + .globl imx_crash_uart_init + .globl imx_crash_uart_putc + + /* ----------------------------------------------- + * int imx_crash_uart_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: r0 - console base address + * r1 - Uart clock in Hz + * r2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : r1, r2, r3, r4 + * ----------------------------------------------- + */ +func imx_crash_uart_init + /* Free up r1 as a scratch reg */ + mov r4, r0 + mov r0, r1 + + /* Reset UART via CR2 */ + add r1, r4, #IMX_UART_CR2_OFFSET + movs r3, #0 + str r3, [r4, #IMX_UART_CR2_OFFSET] + + /* Wait for reset complete */ +__wait_cr2_reset: + ldr r3, [r1, #0] + ands r3, #IMX_UART_CR2_SRST + beq __wait_cr2_reset + + /* Enable UART */ + movs r3, #IMX_UART_CR1_UARTEN + mov r1, r2 + str r3, [r4, #IMX_UART_CR1_OFFSET] + + /* + * Ignore RTC/CTS - disable reset + * Magic value #16423 => + * IMX_UART_CR2_IRTS | IMX_UART_CR2_WS | IMX_UART_CR2_TXEN | IMX_UART_CR2_RXEN | IMX_UART_CR2_SRST + */ + movw r3, #16423 + str r3, [r4, #IMX_UART_CR2_OFFSET] + + /* + * No parity, autobaud detect-old, rxdmuxsel=1 (fixed i.mx7) + * Magic value => #132 + * IMX_UART_CR3_ADNIMP | IMX_UART_CR3_RXDMUXSEL + */ + movs r3, #132 + str r3, [r4, #IMX_UART_CR3_OFFSET] + + /* + * Set CTS FIFO trigger to 32 bytes bits 15:10 + * Magic value => #32768 + * FIFO trigger bitmask 100000 + * */ + mov r3, #32768 + str r3, [r4, #IMX_UART_CR4_OFFSET] + + /* + * TX/RX-thresh = 2 bytes, DCE (bit6 = 0), refclk @24MHz / 4 + * Magic value #2562 + * IMX_UART_FCR_TXTL(TX_RX_THRESH) | IMX_UART_FCR_RXTL(TX_RX_THRESH) | IMX_UART_FCR_RFDIV2 + */ + #ifdef IMX_UART_DTE + movw r3, #2626 + #else + movw r3, #2562 + #endif + str r3, [r4, #IMX_UART_FCR_OFFSET] + + /* This BIR should be set to 0x0F prior to writing the BMR */ + movs r3, #15 + str r3, [r4, #IMX_UART_BIR_OFFSET] + + /* Hard-code to 115200 @ 24 MHz */ + movs r0, #104 + str r0, [r4, #IMX_UART_BMR_OFFSET] + + /* Indicate success */ + movs r0, #1 + bx lr +endfunc imx_crash_uart_init + + /* -------------------------------------------------------- + * int imx_crash_uart_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +func imx_crash_uart_putc + /* Output specified character to UART shift-register */ + str r0, [r1, #IMX_UART_TXD_OFFSET] + + /* Wait for transmit IMX_UART_STAT2_OFFSET.IMX_UART_STAT2_TXDC == 1 */ +__putc_spin_ready: + ldr r2, [r1, #IMX_UART_STAT2_OFFSET] + ands r2, #IMX_UART_STAT2_TXDC + beq __putc_spin_ready + + /* Transmit complete do we need to fixup \n to \n\r */ + cmp r0, #10 + beq __putc_fixup_lf + + /* No fixup necessary - exit here */ + movs r0, #0 + bx lr + + /* Fixup \n to \n\r */ +__putc_fixup_lf: + movs r0, #13 + b imx_crash_uart_putc +endfunc imx_crash_uart_putc diff --git a/arm-trusted-firmware/drivers/imx/uart/imx_uart.c b/arm-trusted-firmware/drivers/imx/uart/imx_uart.c new file mode 100644 index 0000000..dfe2e92 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/uart/imx_uart.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#include + +/* TX/RX FIFO threshold */ +#define TX_RX_THRESH 2 + +struct clk_div_factors { + uint32_t fcr_div; + uint32_t bmr_div; +}; + +static struct clk_div_factors clk_div[] = { + { + .fcr_div = IMX_UART_FCR_RFDIV1, + .bmr_div = 1, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV2, + .bmr_div = 2, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV3, + .bmr_div = 3, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV4, + .bmr_div = 4, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV5, + .bmr_div = 5, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV6, + .bmr_div = 6, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV7, + .bmr_div = 7, + }, +}; + +static void write_reg(uintptr_t base, uint32_t offset, uint32_t val) +{ + mmio_write_32(base + offset, val); +} + +static uint32_t read_reg(uintptr_t base, uint32_t offset) +{ + return mmio_read_32(base + offset); +} + +int console_imx_uart_core_init(uintptr_t base_addr, unsigned int uart_clk, + unsigned int baud_rate) +{ + uint32_t val; + uint8_t clk_idx = 1; + + /* Reset UART */ + write_reg(base_addr, IMX_UART_CR2_OFFSET, 0); + do { + val = read_reg(base_addr, IMX_UART_CR2_OFFSET); + } while (!(val & IMX_UART_CR2_SRST)); + + /* Enable UART */ + write_reg(base_addr, IMX_UART_CR1_OFFSET, IMX_UART_CR1_UARTEN); + + /* Ignore RTS, 8N1, enable tx/rx, disable reset */ + val = (IMX_UART_CR2_IRTS | IMX_UART_CR2_WS | IMX_UART_CR2_TXEN | + IMX_UART_CR2_RXEN | IMX_UART_CR2_SRST); + write_reg(base_addr, IMX_UART_CR2_OFFSET, val); + + /* No parity, autobaud detect-old, rxdmuxsel=1 (fixed i.mx7) */ + val = IMX_UART_CR3_ADNIMP | IMX_UART_CR3_RXDMUXSEL; + write_reg(base_addr, IMX_UART_CR3_OFFSET, val); + + /* Set CTS FIFO trigger to 32 bytes bits 15:10 */ + write_reg(base_addr, IMX_UART_CR4_OFFSET, 0x8000); + + /* TX/RX-thresh = 2 bytes, DTE (bit6 = 0), refclk @24MHz / 4 */ + val = IMX_UART_FCR_TXTL(TX_RX_THRESH) | IMX_UART_FCR_RXTL(TX_RX_THRESH) | + clk_div[clk_idx].fcr_div; + #ifdef IMX_UART_DTE + /* Set DTE (bit6 = 1) */ + val |= IMX_UART_FCR_DCEDTE; + #endif + write_reg(base_addr, IMX_UART_FCR_OFFSET, val); + + /* + * The equation for BAUD rate calculation is + * RefClk = Supplied clock / FCR_DIVx + * + * BAUD = Refclk + * ------------ + * 16 x (UBMR + 1/ UBIR + 1) + * + * We write 0x0f into UBIR to remove the 16 mult + * BAUD = 6000000 + * ------------ + * 16 x (UBMR + 1/ 15 + 1) + */ + + write_reg(base_addr, IMX_UART_BIR_OFFSET, 0x0f); + val = ((uart_clk / clk_div[clk_idx].bmr_div) / baud_rate) - 1; + write_reg(base_addr, IMX_UART_BMR_OFFSET, val); + + return 0; +} + +/* -------------------------------------------------------- + * int console_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +int console_imx_uart_core_putc(int c, uintptr_t base_addr) +{ + uint32_t val; + + if (c == '\n') + console_imx_uart_core_putc('\r', base_addr); + + /* Write data */ + write_reg(base_addr, IMX_UART_TXD_OFFSET, c); + + /* Wait for transmit */ + do { + val = read_reg(base_addr, IMX_UART_STAT2_OFFSET); + } while (!(val & IMX_UART_STAT2_TXDC)); + + return 0; +} + +/* + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on error. + * In : r0 - console base address + * Clobber list : r0, r1 + * --------------------------------------------- + */ +int console_imx_uart_core_getc(uintptr_t base_addr) +{ + uint32_t val; + + val = read_reg(base_addr, IMX_UART_TS_OFFSET); + if (val & IMX_UART_TS_RXEMPTY) + return -1; + + val = read_reg(base_addr, IMX_UART_RXD_OFFSET); + return (int)(val & 0x000000FF); +} + +/* + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - console base address + * Out : void + * Clobber list : r0, r1 + * --------------------------------------------- + */ +void console_imx_uart_core_flush(uintptr_t base_addr) +{ +} + diff --git a/arm-trusted-firmware/drivers/imx/uart/imx_uart.h b/arm-trusted-firmware/drivers/imx/uart/imx_uart.h new file mode 100644 index 0000000..a133024 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/uart/imx_uart.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef IMX_UART_H +#define IMX_UART_H + +#include + +#define IMX_UART_RXD_OFFSET 0x00 +#define IMX_UART_RXD_CHARRDY BIT(15) +#define IMX_UART_RXD_ERR BIT(14) +#define IMX_UART_RXD_OVERRUN BIT(13) +#define IMX_UART_RXD_FRMERR BIT(12) +#define IMX_UART_RXD_BRK BIT(11) +#define IMX_UART_RXD_PRERR BIT(10) + +#define IMX_UART_TXD_OFFSET 0x40 + +#define IMX_UART_CR1_OFFSET 0x80 +#define IMX_UART_CR1_ADEN BIT(15) +#define IMX_UART_CR1_ADBR BIT(14) +#define IMX_UART_CR1_TRDYEN BIT(13) +#define IMX_UART_CR1_IDEN BIT(12) +#define IMX_UART_CR1_RRDYEN BIT(9) +#define IMX_UART_CR1_RXDMAEN BIT(8) +#define IMX_UART_CR1_IREN BIT(7) +#define IMX_UART_CR1_TXMPTYEN BIT(6) +#define IMX_UART_CR1_RTSDEN BIT(5) +#define IMX_UART_CR1_SNDBRK BIT(4) +#define IMX_UART_CR1_TXDMAEN BIT(3) +#define IMX_UART_CR1_ATDMAEN BIT(2) +#define IMX_UART_CR1_DOZE BIT(1) +#define IMX_UART_CR1_UARTEN BIT(0) + +#define IMX_UART_CR2_OFFSET 0x84 +#define IMX_UART_CR2_ESCI BIT(15) +#define IMX_UART_CR2_IRTS BIT(14) +#define IMX_UART_CR2_CTSC BIT(13) +#define IMX_UART_CR2_CTS BIT(12) +#define IMX_UART_CR2_ESCEN BIT(11) +#define IMX_UART_CR2_PREN BIT(8) +#define IMX_UART_CR2_PROE BIT(7) +#define IMX_UART_CR2_STPB BIT(6) +#define IMX_UART_CR2_WS BIT(5) +#define IMX_UART_CR2_RTSEN BIT(4) +#define IMX_UART_CR2_ATEN BIT(3) +#define IMX_UART_CR2_TXEN BIT(2) +#define IMX_UART_CR2_RXEN BIT(1) +#define IMX_UART_CR2_SRST BIT(0) + +#define IMX_UART_CR3_OFFSET 0x88 +#define IMX_UART_CR3_DTREN BIT(13) +#define IMX_UART_CR3_PARERREN BIT(12) +#define IMX_UART_CR3_FARERREN BIT(11) +#define IMX_UART_CR3_DSD BIT(10) +#define IMX_UART_CR3_DCD BIT(9) +#define IMX_UART_CR3_RI BIT(8) +#define IMX_UART_CR3_ADNIMP BIT(7) +#define IMX_UART_CR3_RXDSEN BIT(6) +#define IMX_UART_CR3_AIRINTEN BIT(5) +#define IMX_UART_CR3_AWAKEN BIT(4) +#define IMX_UART_CR3_DTRDEN BIT(3) +#define IMX_UART_CR3_RXDMUXSEL BIT(2) +#define IMX_UART_CR3_INVT BIT(1) +#define IMX_UART_CR3_ACIEN BIT(0) + +#define IMX_UART_CR4_OFFSET 0x8c +#define IMX_UART_CR4_INVR BIT(9) +#define IMX_UART_CR4_ENIRI BIT(8) +#define IMX_UART_CR4_WKEN BIT(7) +#define IMX_UART_CR4_IDDMAEN BIT(6) +#define IMX_UART_CR4_IRSC BIT(5) +#define IMX_UART_CR4_LPBYP BIT(4) +#define IMX_UART_CR4_TCEN BIT(3) +#define IMX_UART_CR4_BKEN BIT(2) +#define IMX_UART_CR4_OREN BIT(1) +#define IMX_UART_CR4_DREN BIT(0) + +#define IMX_UART_FCR_OFFSET 0x90 +#define IMX_UART_FCR_TXTL_MASK (BIT(15) | BIT(14) | BIT(13) | BIT(12) |\ + BIT(11) | BIT(10)) +#define IMX_UART_FCR_TXTL(x) ((x) << 10) +#define IMX_UART_FCR_RFDIV_MASK (BIT(9) | BIT(8) | BIT(7)) +#define IMX_UART_FCR_RFDIV7 (BIT(9) | BIT(8)) +#define IMX_UART_FCR_RFDIV1 (BIT(9) | BIT(7)) +#define IMX_UART_FCR_RFDIV2 BIT(9) +#define IMX_UART_FCR_RFDIV3 (BIT(8) | BIT(7)) +#define IMX_UART_FCR_RFDIV4 BIT(8) +#define IMX_UART_FCR_RFDIV5 BIT(7) +#define IMX_UART_FCR_RFDIV6 0 +#define IMX_UART_FCR_DCEDTE BIT(6) +#define IMX_UART_FCR_RXTL_MASK (BIT(5) | BIT(4) | BIT(3) | BIT(2) |\ + BIT(1) | BIT(0)) +#define IMX_UART_FCR_RXTL(x) x + +#define IMX_UART_STAT1_OFFSET 0x94 +#define IMX_UART_STAT1_PARITYERR BIT(15) +#define IMX_UART_STAT1_RTSS BIT(14) +#define IMX_UART_STAT1_TRDY BIT(13) +#define IMX_UART_STAT1_RTSD BIT(12) +#define IMX_UART_STAT1_ESCF BIT(11) +#define IMX_UART_STAT1_FRAMEERR BIT(10) +#define IMX_UART_STAT1_RRDY BIT(9) +#define IMX_UART_STAT1_AGTIM BIT(8) +#define IMX_UART_STAT1_DTRD BIT(7) +#define IMX_UART_STAT1_RXDS BIT(6) +#define IMX_UART_STAT1_AIRINT BIT(5) +#define IMX_UART_STAT1_AWAKE BIT(4) +#define IMX_UART_STAT1_SAD BIT(3) + +#define IMX_UART_STAT2_OFFSET 0x98 +#define IMX_UART_STAT2_ADET BIT(15) +#define IMX_UART_STAT2_TXFE BIT(14) +#define IMX_UART_STAT2_DTRF BIT(13) +#define IMX_UART_STAT2_IDLE BIT(12) +#define IMX_UART_STAT2_ACST BIT(11) +#define IMX_UART_STAT2_RIDELT BIT(10) +#define IMX_UART_STAT2_RIIN BIT(9) +#define IMX_UART_STAT2_IRINT BIT(8) +#define IMX_UART_STAT2_WAKE BIT(7) +#define IMX_UART_STAT2_DCDDELT BIT(6) +#define IMX_UART_STAT2_DCDIN BIT(5) +#define IMX_UART_STAT2_RTSF BIT(4) +#define IMX_UART_STAT2_TXDC BIT(3) +#define IMX_UART_STAT2_BRCD BIT(2) +#define IMX_UART_STAT2_ORE BIT(1) +#define IMX_UART_STAT2_RCR BIT(0) + +#define IMX_UART_ESC_OFFSET 0x9c + +#define IMX_UART_TIM_OFFSET 0xa0 + +#define IMX_UART_BIR_OFFSET 0xa4 + +#define IMX_UART_BMR_OFFSET 0xa8 + +#define IMX_UART_BRC_OFFSET 0xac + +#define IMX_UART_ONEMS_OFFSET 0xb0 + +#define IMX_UART_TS_OFFSET 0xb4 +#define IMX_UART_TS_FRCPERR BIT(13) +#define IMX_UART_TS_LOOP BIT(12) +#define IMX_UART_TS_DBGEN BIT(11) +#define IMX_UART_TS_LOOPIR BIT(10) +#define IMX_UART_TS_RXDBG BIT(9) +#define IMX_UART_TS_TXEMPTY BIT(6) +#define IMX_UART_TS_RXEMPTY BIT(5) +#define IMX_UART_TS_TXFULL BIT(4) +#define IMX_UART_TS_RXFULL BIT(3) +#define IMX_UART_TS_SOFTRST BIT(0) + +#ifndef __ASSEMBLER__ + +int console_imx_uart_register(uintptr_t baseaddr, + uint32_t clock, + uint32_t baud, + console_t *console); +#endif /*__ASSEMBLER__*/ + +#endif /* IMX_UART_H */ diff --git a/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c b/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c new file mode 100644 index 0000000..07f55b7 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +static void imx_usdhc_initialize(void); +static int imx_usdhc_send_cmd(struct mmc_cmd *cmd); +static int imx_usdhc_set_ios(unsigned int clk, unsigned int width); +static int imx_usdhc_prepare(int lba, uintptr_t buf, size_t size); +static int imx_usdhc_read(int lba, uintptr_t buf, size_t size); +static int imx_usdhc_write(int lba, uintptr_t buf, size_t size); + +static const struct mmc_ops imx_usdhc_ops = { + .init = imx_usdhc_initialize, + .send_cmd = imx_usdhc_send_cmd, + .set_ios = imx_usdhc_set_ios, + .prepare = imx_usdhc_prepare, + .read = imx_usdhc_read, + .write = imx_usdhc_write, +}; + +static imx_usdhc_params_t imx_usdhc_params; + +#define IMX7_MMC_SRC_CLK_RATE (200 * 1000 * 1000) +static void imx_usdhc_set_clk(int clk) +{ + int div = 1; + int pre_div = 1; + unsigned int sdhc_clk = IMX7_MMC_SRC_CLK_RATE; + uintptr_t reg_base = imx_usdhc_params.reg_base; + + assert(clk > 0); + + while (sdhc_clk / (16 * pre_div) > clk && pre_div < 256) + pre_div *= 2; + + while (sdhc_clk / div > clk && div < 16) + div++; + + pre_div >>= 1; + div -= 1; + clk = (pre_div << 8) | (div << 4); + + mmio_clrbits32(reg_base + VENDSPEC, VENDSPEC_CARD_CLKEN); + mmio_clrsetbits32(reg_base + SYSCTRL, SYSCTRL_CLOCK_MASK, clk); + udelay(10000); + + mmio_setbits32(reg_base + VENDSPEC, VENDSPEC_PER_CLKEN | VENDSPEC_CARD_CLKEN); +} + +static void imx_usdhc_initialize(void) +{ + unsigned int timeout = 10000; + uintptr_t reg_base = imx_usdhc_params.reg_base; + + assert((imx_usdhc_params.reg_base & MMC_BLOCK_MASK) == 0); + + /* reset the controller */ + mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTA); + + /* wait for reset done */ + while ((mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTA)) { + if (!timeout) + ERROR("IMX MMC reset timeout.\n"); + timeout--; + } + + mmio_write_32(reg_base + MMCBOOT, 0); + mmio_write_32(reg_base + MIXCTRL, 0); + mmio_write_32(reg_base + CLKTUNECTRLSTS, 0); + + mmio_write_32(reg_base + VENDSPEC, VENDSPEC_INIT); + mmio_write_32(reg_base + DLLCTRL, 0); + mmio_setbits32(reg_base + VENDSPEC, VENDSPEC_IPG_CLKEN | VENDSPEC_PER_CLKEN); + + /* Set the initial boot clock rate */ + imx_usdhc_set_clk(MMC_BOOT_CLK_RATE); + udelay(100); + + /* Clear read/write ready status */ + mmio_clrbits32(reg_base + INTSTATEN, INTSTATEN_BRR | INTSTATEN_BWR); + + /* configure as little endian */ + mmio_write_32(reg_base + PROTCTRL, PROTCTRL_LE); + + /* Set timeout to the maximum value */ + mmio_clrsetbits32(reg_base + SYSCTRL, SYSCTRL_TIMEOUT_MASK, + SYSCTRL_TIMEOUT(15)); + + /* set wartermark level as 16 for safe for MMC */ + mmio_clrsetbits32(reg_base + WATERMARKLEV, WMKLV_MASK, 16 | (16 << 16)); +} + +#define FSL_CMD_RETRIES 1000 + +static int imx_usdhc_send_cmd(struct mmc_cmd *cmd) +{ + uintptr_t reg_base = imx_usdhc_params.reg_base; + unsigned int xfertype = 0, mixctl = 0, multiple = 0, data = 0, err = 0; + unsigned int state, flags = INTSTATEN_CC | INTSTATEN_CTOE; + unsigned int cmd_retries = 0; + + assert(cmd); + + /* clear all irq status */ + mmio_write_32(reg_base + INTSTAT, 0xffffffff); + + /* Wait for the bus to be idle */ + do { + state = mmio_read_32(reg_base + PSTATE); + } while (state & (PSTATE_CDIHB | PSTATE_CIHB)); + + while (mmio_read_32(reg_base + PSTATE) & PSTATE_DLA) + ; + + mmio_write_32(reg_base + INTSIGEN, 0); + udelay(1000); + + switch (cmd->cmd_idx) { + case MMC_CMD(12): + xfertype |= XFERTYPE_CMDTYP_ABORT; + break; + case MMC_CMD(18): + multiple = 1; + /* fall thru for read op */ + case MMC_CMD(17): + case MMC_CMD(8): + mixctl |= MIXCTRL_DTDSEL; + data = 1; + break; + case MMC_CMD(25): + multiple = 1; + /* fall thru for data op flag */ + case MMC_CMD(24): + data = 1; + break; + default: + break; + } + + if (multiple) { + mixctl |= MIXCTRL_MSBSEL; + mixctl |= MIXCTRL_BCEN; + } + + if (data) { + xfertype |= XFERTYPE_DPSEL; + mixctl |= MIXCTRL_DMAEN; + } + + if (cmd->resp_type & MMC_RSP_48 && cmd->resp_type != MMC_RESPONSE_R2) + xfertype |= XFERTYPE_RSPTYP_48; + else if (cmd->resp_type & MMC_RSP_136) + xfertype |= XFERTYPE_RSPTYP_136; + else if (cmd->resp_type & MMC_RSP_BUSY) + xfertype |= XFERTYPE_RSPTYP_48_BUSY; + + if (cmd->resp_type & MMC_RSP_CMD_IDX) + xfertype |= XFERTYPE_CICEN; + + if (cmd->resp_type & MMC_RSP_CRC) + xfertype |= XFERTYPE_CCCEN; + + xfertype |= XFERTYPE_CMD(cmd->cmd_idx); + + /* Send the command */ + mmio_write_32(reg_base + CMDARG, cmd->cmd_arg); + mmio_clrsetbits32(reg_base + MIXCTRL, MIXCTRL_DATMASK, mixctl); + mmio_write_32(reg_base + XFERTYPE, xfertype); + + /* Wait for the command done */ + do { + state = mmio_read_32(reg_base + INTSTAT); + if (cmd_retries) + udelay(1); + } while ((!(state & flags)) && ++cmd_retries < FSL_CMD_RETRIES); + + if ((state & (INTSTATEN_CTOE | CMD_ERR)) || cmd_retries == FSL_CMD_RETRIES) { + if (cmd_retries == FSL_CMD_RETRIES) + err = -ETIMEDOUT; + else + err = -EIO; + ERROR("imx_usdhc mmc cmd %d state 0x%x errno=%d\n", + cmd->cmd_idx, state, err); + goto out; + } + + /* Copy the response to the response buffer */ + if (cmd->resp_type & MMC_RSP_136) { + unsigned int cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; + + cmdrsp3 = mmio_read_32(reg_base + CMDRSP3); + cmdrsp2 = mmio_read_32(reg_base + CMDRSP2); + cmdrsp1 = mmio_read_32(reg_base + CMDRSP1); + cmdrsp0 = mmio_read_32(reg_base + CMDRSP0); + cmd->resp_data[3] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); + cmd->resp_data[2] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); + cmd->resp_data[1] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); + cmd->resp_data[0] = (cmdrsp0 << 8); + } else { + cmd->resp_data[0] = mmio_read_32(reg_base + CMDRSP0); + } + + /* Wait until all of the blocks are transferred */ + if (data) { + flags = DATA_COMPLETE; + do { + state = mmio_read_32(reg_base + INTSTAT); + + if (state & (INTSTATEN_DTOE | DATA_ERR)) { + err = -EIO; + ERROR("imx_usdhc mmc data state 0x%x\n", state); + goto out; + } + } while ((state & flags) != flags); + } + +out: + /* Reset CMD and DATA on error */ + if (err) { + mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTC); + while (mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTC) + ; + + if (data) { + mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTD); + while (mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTD) + ; + } + } + + /* clear all irq status */ + mmio_write_32(reg_base + INTSTAT, 0xffffffff); + + return err; +} + +static int imx_usdhc_set_ios(unsigned int clk, unsigned int width) +{ + uintptr_t reg_base = imx_usdhc_params.reg_base; + + imx_usdhc_set_clk(clk); + + if (width == MMC_BUS_WIDTH_4) + mmio_clrsetbits32(reg_base + PROTCTRL, PROTCTRL_WIDTH_MASK, + PROTCTRL_WIDTH_4); + else if (width == MMC_BUS_WIDTH_8) + mmio_clrsetbits32(reg_base + PROTCTRL, PROTCTRL_WIDTH_MASK, + PROTCTRL_WIDTH_8); + + return 0; +} + +static int imx_usdhc_prepare(int lba, uintptr_t buf, size_t size) +{ + uintptr_t reg_base = imx_usdhc_params.reg_base; + + mmio_write_32(reg_base + DSADDR, buf); + mmio_write_32(reg_base + BLKATT, + (size / MMC_BLOCK_SIZE) << 16 | MMC_BLOCK_SIZE); + + return 0; +} + +static int imx_usdhc_read(int lba, uintptr_t buf, size_t size) +{ + return 0; +} + +static int imx_usdhc_write(int lba, uintptr_t buf, size_t size) +{ + return 0; +} + +void imx_usdhc_init(imx_usdhc_params_t *params, + struct mmc_device_info *mmc_dev_info) +{ + assert((params != 0) && + ((params->reg_base & MMC_BLOCK_MASK) == 0) && + (params->clk_rate > 0) && + ((params->bus_width == MMC_BUS_WIDTH_1) || + (params->bus_width == MMC_BUS_WIDTH_4) || + (params->bus_width == MMC_BUS_WIDTH_8))); + + memcpy(&imx_usdhc_params, params, sizeof(imx_usdhc_params_t)); + mmc_init(&imx_usdhc_ops, params->clk_rate, params->bus_width, + params->flags, mmc_dev_info); +} diff --git a/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h b/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h new file mode 100644 index 0000000..e063316 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_USDHC_H +#define IMX_USDHC_H + +#include + +typedef struct imx_usdhc_params { + uintptr_t reg_base; + int clk_rate; + int bus_width; + unsigned int flags; +} imx_usdhc_params_t; + +void imx_usdhc_init(imx_usdhc_params_t *params, + struct mmc_device_info *mmc_dev_info); + +/* iMX MMC registers definition */ +#define DSADDR 0x000 +#define BLKATT 0x004 +#define CMDARG 0x008 +#define CMDRSP0 0x010 +#define CMDRSP1 0x014 +#define CMDRSP2 0x018 +#define CMDRSP3 0x01c + +#define XFERTYPE 0x00c +#define XFERTYPE_CMD(x) (((x) & 0x3f) << 24) +#define XFERTYPE_CMDTYP_ABORT (3 << 22) +#define XFERTYPE_DPSEL BIT(21) +#define XFERTYPE_CICEN BIT(20) +#define XFERTYPE_CCCEN BIT(19) +#define XFERTYPE_RSPTYP_136 BIT(16) +#define XFERTYPE_RSPTYP_48 BIT(17) +#define XFERTYPE_RSPTYP_48_BUSY (BIT(16) | BIT(17)) + +#define PSTATE 0x024 +#define PSTATE_DAT0 BIT(24) +#define PSTATE_DLA BIT(2) +#define PSTATE_CDIHB BIT(1) +#define PSTATE_CIHB BIT(0) + +#define PROTCTRL 0x028 +#define PROTCTRL_LE BIT(5) +#define PROTCTRL_WIDTH_4 BIT(1) +#define PROTCTRL_WIDTH_8 BIT(2) +#define PROTCTRL_WIDTH_MASK 0x6 + +#define SYSCTRL 0x02c +#define SYSCTRL_RSTD BIT(26) +#define SYSCTRL_RSTC BIT(25) +#define SYSCTRL_RSTA BIT(24) +#define SYSCTRL_CLOCK_MASK 0x0000fff0 +#define SYSCTRL_TIMEOUT_MASK 0x000f0000 +#define SYSCTRL_TIMEOUT(x) ((0xf & (x)) << 16) + +#define INTSTAT 0x030 +#define INTSTAT_DMAE BIT(28) +#define INTSTAT_DEBE BIT(22) +#define INTSTAT_DCE BIT(21) +#define INTSTAT_DTOE BIT(20) +#define INTSTAT_CIE BIT(19) +#define INTSTAT_CEBE BIT(18) +#define INTSTAT_CCE BIT(17) +#define INTSTAT_DINT BIT(3) +#define INTSTAT_BGE BIT(2) +#define INTSTAT_TC BIT(1) +#define INTSTAT_CC BIT(0) +#define CMD_ERR (INTSTAT_CIE | INTSTAT_CEBE | INTSTAT_CCE) +#define DATA_ERR (INTSTAT_DMAE | INTSTAT_DEBE | INTSTAT_DCE | \ + INTSTAT_DTOE) +#define DATA_COMPLETE (INTSTAT_DINT | INTSTAT_TC) + +#define INTSTATEN 0x034 +#define INTSTATEN_DEBE BIT(22) +#define INTSTATEN_DCE BIT(21) +#define INTSTATEN_DTOE BIT(20) +#define INTSTATEN_CIE BIT(19) +#define INTSTATEN_CEBE BIT(18) +#define INTSTATEN_CCE BIT(17) +#define INTSTATEN_CTOE BIT(16) +#define INTSTATEN_CINT BIT(8) +#define INTSTATEN_BRR BIT(5) +#define INTSTATEN_BWR BIT(4) +#define INTSTATEN_DINT BIT(3) +#define INTSTATEN_TC BIT(1) +#define INTSTATEN_CC BIT(0) +#define EMMC_INTSTATEN_BITS (INTSTATEN_CC | INTSTATEN_TC | INTSTATEN_DINT | \ + INTSTATEN_BWR | INTSTATEN_BRR | INTSTATEN_CINT | \ + INTSTATEN_CTOE | INTSTATEN_CCE | INTSTATEN_CEBE | \ + INTSTATEN_CIE | INTSTATEN_DTOE | INTSTATEN_DCE | \ + INTSTATEN_DEBE) + +#define INTSIGEN 0x038 + +#define WATERMARKLEV 0x044 +#define WMKLV_RD_MASK 0xff +#define WMKLV_WR_MASK 0x00ff0000 +#define WMKLV_MASK (WMKLV_RD_MASK | WMKLV_WR_MASK) + +#define MIXCTRL 0x048 +#define MIXCTRL_MSBSEL BIT(5) +#define MIXCTRL_DTDSEL BIT(4) +#define MIXCTRL_DDREN BIT(3) +#define MIXCTRL_AC12EN BIT(2) +#define MIXCTRL_BCEN BIT(1) +#define MIXCTRL_DMAEN BIT(0) +#define MIXCTRL_DATMASK 0x7f + +#define DLLCTRL 0x060 + +#define CLKTUNECTRLSTS 0x068 + +#define VENDSPEC 0x0c0 +#define VENDSPEC_RSRV1 BIT(29) +#define VENDSPEC_CARD_CLKEN BIT(14) +#define VENDSPEC_PER_CLKEN BIT(13) +#define VENDSPEC_AHB_CLKEN BIT(12) +#define VENDSPEC_IPG_CLKEN BIT(11) +#define VENDSPEC_AC12_CHKBUSY BIT(3) +#define VENDSPEC_EXTDMA BIT(0) +#define VENDSPEC_INIT (VENDSPEC_RSRV1 | VENDSPEC_CARD_CLKEN | \ + VENDSPEC_PER_CLKEN | VENDSPEC_AHB_CLKEN | \ + VENDSPEC_IPG_CLKEN | VENDSPEC_AC12_CHKBUSY | \ + VENDSPEC_EXTDMA) + +#define MMCBOOT 0x0c4 + +#define mmio_clrsetbits32(addr, clear, set) mmio_write_32(addr, (mmio_read_32(addr) & ~(clear)) | (set)) +#define mmio_clrbits32(addr, clear) mmio_write_32(addr, mmio_read_32(addr) & ~(clear)) +#define mmio_setbits32(addr, set) mmio_write_32(addr, mmio_read_32(addr) | (set)) + +#endif /* IMX_USDHC_H */ diff --git a/arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c b/arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c new file mode 100644 index 0000000..dcd1991 --- /dev/null +++ b/arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "qspi/cadence_qspi.h" + +/* 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; +} file_state_t; + +static file_state_t current_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 const 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 = (io_dev_info_t *)&memmap_dev_info; /* cast away const */ + + 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_file.in_use == 0) { + assert(block_spec != NULL); + assert(entity != NULL); + + current_file.in_use = 1; + current_file.base = block_spec->offset; + /* File cursor offset for seek and incremental reads etc. */ + current_file.file_pos = 0; + current_file.size = block_spec->length; + entity->info = (uintptr_t)¤t_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; + file_state_t *fp; + + /* We only support IO_SEEK_SET for the moment. */ + if (mode == IO_SEEK_SET) { + assert(entity != NULL); + + fp = (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 = 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 = ((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) +{ + file_state_t *fp; + unsigned long long pos_after; + + assert(entity != NULL); + assert(length_read != NULL); + + fp = (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 *)(fp->base + fp->file_pos), length); + cad_qspi_read((void *)buffer, 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) +{ + file_state_t *fp; + unsigned long long pos_after; + + assert(entity != NULL); + assert(length_written != NULL); + + fp = (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 *)(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_file, sizeof(current_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/arm-trusted-firmware/drivers/io/io_block.c b/arm-trusted-firmware/drivers/io/io_block.c new file mode 100644 index 0000000..5d45c2f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/io/io_dummy.c b/arm-trusted-firmware/drivers/io/io_dummy.c new file mode 100644 index 0000000..4f0cda6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/io/io_encrypted.c b/arm-trusted-firmware/drivers/io/io_encrypted.c new file mode 100644 index 0000000..744ca83 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/io/io_fip.c b/arm-trusted-firmware/drivers/io/io_fip.c new file mode 100644 index 0000000..6e15295 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/io/io_memmap.c b/arm-trusted-firmware/drivers/io/io_memmap.c new file mode 100644 index 0000000..eb69163 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/io/io_mtd.c b/arm-trusted-firmware/drivers/io/io_mtd.c new file mode 100644 index 0000000..5d86592 --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_mtd.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2019-2022, 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 pos; /* Offset in bytes */ + unsigned long long size; /* Size of device in bytes */ + unsigned long long extra_offset; /* Extra offset 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_add_extra_offset(mtd_dev_state_t *cur, size_t *extra_offset) +{ + io_mtd_ops_t *ops = &cur->dev_spec->ops; + int ret; + + if (ops->seek == NULL) { + return 0; + } + + ret = ops->seek(cur->base, cur->pos, extra_offset); + if (ret != 0) { + ERROR("%s: Seek error %d\n", __func__, ret); + return ret; + } + + 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; + io_block_spec_t *region; + size_t extra_offset = 0U; + int ret; + + assert((dev_info->info != 0UL) && (entity->info == 0UL)); + + region = (io_block_spec_t *)spec; + cur = (mtd_dev_state_t *)dev_info->info; + entity->info = (uintptr_t)cur; + cur->base = region->offset; + cur->pos = 0U; + cur->extra_offset = 0U; + + ret = mtd_add_extra_offset(cur, &extra_offset); + if (ret != 0) { + return ret; + } + + cur->base += extra_offset; + + 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; + size_t extra_offset = 0U; + int ret; + + 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->pos = offset; + break; + case IO_SEEK_CUR: + if (((cur->base + cur->pos + (unsigned long long)offset) >= + cur->size) || + ((cur->base + cur->pos + (unsigned long long)offset) < + cur->base + cur->pos)) { + return -EINVAL; + } + + cur->pos += (unsigned long long)offset; + break; + default: + return -EINVAL; + } + + ret = mtd_add_extra_offset(cur, &extra_offset); + if (ret != 0) { + return ret; + } + + cur->extra_offset = extra_offset; + + 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 %zu\n", + cur->base + cur->pos, buffer, length); + if ((cur->base + cur->pos + length) > cur->dev_spec->device_size) { + return -EINVAL; + } + + ret = ops->read(cur->base + cur->pos + cur->extra_offset, buffer, + length, out_length); + if (ret < 0) { + return ret; + } + + assert(*out_length == length); + cur->pos += *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/arm-trusted-firmware/drivers/io/io_semihosting.c b/arm-trusted-firmware/drivers/io/io_semihosting.c new file mode 100644 index 0000000..1c2f84d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/io/io_storage.c b/arm-trusted-firmware/drivers/io/io_storage.c new file mode 100644 index 0000000..0534268 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/marvell/amb_adec.c b/arm-trusted-firmware/drivers/marvell/amb_adec.c new file mode 100644 index 0000000..d78fa25 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/amb_adec.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AXI to M-Bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs */ + +#include +#include + +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) + +#define MVEBU_AMB_ADEC_OFFSET (0x70ff00) + +#define AMB_WIN_CR_OFFSET(win) (amb_base + 0x0 + (0x8 * win)) +#define AMB_ATTR_OFFSET 8 +#define AMB_ATTR_MASK 0xFF +#define AMB_SIZE_OFFSET 16 +#define AMB_SIZE_MASK 0xFF + +#define AMB_WIN_BASE_OFFSET(win) (amb_base + 0x4 + (0x8 * win)) +#define AMB_BASE_OFFSET 16 +#define AMB_BASE_ADDR_MASK ((1 << (32 - AMB_BASE_OFFSET)) - 1) + +#define AMB_WIN_ALIGNMENT_64K (0x10000) +#define AMB_WIN_ALIGNMENT_1M (0x100000) + +uintptr_t amb_base; + +static void amb_check_win(struct addr_map_win *win, uint32_t win_num) +{ + uint32_t base_addr; + + /* make sure the base address is in 16-bit range */ + if (win->base_addr > AMB_BASE_ADDR_MASK) { + WARN("Window %d: base address is too big 0x%" PRIx64 "\n", + win_num, win->base_addr); + win->base_addr = AMB_BASE_ADDR_MASK; + WARN("Set the base address to 0x%" PRIx64 "\n", win->base_addr); + } + + base_addr = win->base_addr << AMB_BASE_OFFSET; + /* for AMB The base is always 1M aligned */ + /* check if address is aligned to 1M */ + if (IS_NOT_ALIGN(base_addr, AMB_WIN_ALIGNMENT_1M)) { + win->base_addr = ALIGN_UP(base_addr, AMB_WIN_ALIGNMENT_1M); + WARN("Window %d: base address unaligned to 0x%x\n", + win_num, AMB_WIN_ALIGNMENT_1M); + WARN("Align up the base address to 0x%" PRIx64 "\n", win->base_addr); + } + + /* size parameter validity check */ + if (!IS_POWER_OF_2(win->win_size)) { + WARN("Window %d: window size is not power of 2 (0x%" PRIx64 ")\n", + win_num, win->win_size); + win->win_size = ROUND_UP_TO_POW_OF_2(win->win_size); + WARN("Rounding size to 0x%" PRIx64 "\n", win->win_size); + } +} + +static void amb_enable_win(struct addr_map_win *win, uint32_t win_num) +{ + uint32_t ctrl, base, size; + + /* + * size is 64KB granularity. + * The number of ones specifies the size of the + * window in 64 KB granularity. 0 is 64KB + */ + size = (win->win_size / AMB_WIN_ALIGNMENT_64K) - 1; + ctrl = (size << AMB_SIZE_OFFSET) | (win->target_id << AMB_ATTR_OFFSET); + base = win->base_addr << AMB_BASE_OFFSET; + + mmio_write_32(AMB_WIN_BASE_OFFSET(win_num), base); + mmio_write_32(AMB_WIN_CR_OFFSET(win_num), ctrl); + + /* enable window after configuring window size (and attributes) */ + ctrl |= WIN_ENABLE_BIT; + mmio_write_32(AMB_WIN_CR_OFFSET(win_num), ctrl); +} + +#ifdef DEBUG_ADDR_MAP +static void dump_amb_adec(void) +{ + uint32_t ctrl, base, win_id, attr; + uint32_t size, size_count; + + /* Dump all AMB windows */ + printf("bank attribute base size\n"); + printf("--------------------------------------------\n"); + for (win_id = 0; win_id < AMB_MAX_WIN_ID; win_id++) { + ctrl = mmio_read_32(AMB_WIN_CR_OFFSET(win_id)); + if (ctrl & WIN_ENABLE_BIT) { + base = mmio_read_32(AMB_WIN_BASE_OFFSET(win_id)); + attr = (ctrl >> AMB_ATTR_OFFSET) & AMB_ATTR_MASK; + size_count = (ctrl >> AMB_SIZE_OFFSET) & AMB_SIZE_MASK; + size = (size_count + 1) * AMB_WIN_ALIGNMENT_64K; + printf("amb 0x%04x 0x%08x 0x%08x\n", + attr, base, size); + } + } +} +#endif + +int init_amb_adec(uintptr_t base) +{ + struct addr_map_win *win; + uint32_t win_id, win_reg; + uint32_t win_count; + + INFO("Initializing AXI to MBus Bridge Address decoding\n"); + + /* Get the base address of the AMB address decoding */ + amb_base = base + MVEBU_AMB_ADEC_OFFSET; + + /* Get the array of the windows and its size */ + marvell_get_amb_memory_map(&win, &win_count, base); + if (win_count <= 0) + INFO("no windows configurations found\n"); + + if (win_count > AMB_MAX_WIN_ID) { + INFO("number of windows is bigger than %d\n", AMB_MAX_WIN_ID); + return 0; + } + + /* disable all AMB windows */ + for (win_id = 0; win_id < AMB_MAX_WIN_ID; win_id++) { + win_reg = mmio_read_32(AMB_WIN_CR_OFFSET(win_id)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(AMB_WIN_CR_OFFSET(win_id), win_reg); + } + + /* enable relevant windows */ + for (win_id = 0; win_id < win_count; win_id++, win++) { + amb_check_win(win, win_id); + amb_enable_win(win, win_id); + } + +#ifdef DEBUG_ADDR_MAP + dump_amb_adec(); +#endif + + INFO("Done AXI to MBus Bridge Address decoding Initializing\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c b/arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c new file mode 100644 index 0000000..c1f8619 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include + +#include + +/* Notify bootloader on DRAM setup */ +#define AP807_CPU_ARO_CTRL(cluster) \ + (MVEBU_RFU_BASE + 0x82A8 + (0xA58 * (cluster))) + +/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */ +#define AP807_CPU_ARO_CLK_EN_OFFSET 0 +#define AP807_CPU_ARO_CLK_EN_MASK (0x1 << AP807_CPU_ARO_CLK_EN_OFFSET) + +/* 0 - ARO is the clock source, 1 - PLL is the clock source */ +#define AP807_CPU_ARO_SEL_PLL_OFFSET 5 +#define AP807_CPU_ARO_SEL_PLL_MASK (0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET) + +/* AP807 clusters count */ +#define AP807_CLUSTER_NUM 2 + +/* PLL frequency values */ +#define PLL_FREQ_1200 0x2AE5F002 /* 1200 */ +#define PLL_FREQ_2000 0x2FC9F002 /* 2000 */ +#define PLL_FREQ_2200 0x2AC57001 /* 2200 */ +#define PLL_FREQ_2400 0x2AE5F001 /* 2400 */ + +/* CPU PLL control registers */ +#define AP807_CPU_PLL_CTRL(cluster) \ + (MVEBU_RFU_BASE + 0x82E0 + (0x8 * (cluster))) + +#define AP807_CPU_PLL_PARAM(cluster) AP807_CPU_PLL_CTRL(cluster) +#define AP807_CPU_PLL_CFG(cluster) (AP807_CPU_PLL_CTRL(cluster) + 0x4) +#define AP807_CPU_PLL_CFG_BYPASS_MODE (0x1) +#define AP807_CPU_PLL_FRC_DSCHG (0x2) +#define AP807_CPU_PLL_CFG_USE_REG_FILE (0x1 << 9) + +static void pll_set_freq(unsigned int freq_val) +{ + int i; + + if (freq_val != PLL_FREQ_2200) + return; + + for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) { + /* Set parameter of cluster i PLL to 2.2GHz */ + mmio_write_32(AP807_CPU_PLL_PARAM(i), freq_val); + /* Set apll_lpf_frc_dschg - Control + * voltage of internal VCO is discharged + */ + mmio_write_32(AP807_CPU_PLL_CFG(i), + AP807_CPU_PLL_FRC_DSCHG); + /* Set use_rf_conf load PLL parameter from register */ + mmio_write_32(AP807_CPU_PLL_CFG(i), + AP807_CPU_PLL_FRC_DSCHG | + AP807_CPU_PLL_CFG_USE_REG_FILE); + /* Un-set apll_lpf_frc_dschg */ + mmio_write_32(AP807_CPU_PLL_CFG(i), + AP807_CPU_PLL_CFG_USE_REG_FILE); + } +} + +/* Switch to ARO from PLL in ap807 */ +static void aro_to_pll(void) +{ + unsigned int reg; + int i; + + for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) { + /* switch from ARO to PLL */ + reg = mmio_read_32(AP807_CPU_ARO_CTRL(i)); + reg |= AP807_CPU_ARO_SEL_PLL_MASK; + mmio_write_32(AP807_CPU_ARO_CTRL(i), reg); + + mdelay(100); + + /* disable ARO clk driver */ + reg = mmio_read_32(AP807_CPU_ARO_CTRL(i)); + reg |= (AP807_CPU_ARO_CLK_EN_MASK); + mmio_write_32(AP807_CPU_ARO_CTRL(i), reg); + } +} + +/* switch from ARO to PLL + * in case of default frequency option, configure PLL registers + * to be aligned with new default frequency. + */ +void ap807_clocks_init(unsigned int freq_option) +{ + /* Modifications in frequency table: + * 0x0: 764x: change to 2000 MHz. + * 0x2: 744x change to 1800 MHz, 764x change to 2200/2400. + * 0x3: 3900/744x/764x change to 1200 MHz. + */ + + if (freq_option == CPU_2200_DDR_1200_RCLK_1200) + pll_set_freq(PLL_FREQ_2200); + + /* Switch from ARO to PLL */ + aro_to_pll(); + +} diff --git a/arm-trusted-firmware/drivers/marvell/cache_llc.c b/arm-trusted-firmware/drivers/marvell/cache_llc.c new file mode 100644 index 0000000..4b06b47 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/cache_llc.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* LLC driver is the Last Level Cache (L3C) driver + * for Marvell SoCs in AP806, AP807, and AP810 + */ + +#include + +#include +#include +#include +#include + +#include + +#define CCU_HTC_CR(ap_index) (MVEBU_CCU_BASE(ap_index) + 0x200) +#define CCU_SET_POC_OFFSET 5 + +extern void ca72_l2_enable_unique_clean(void); + +void llc_cache_sync(int ap_index) +{ + mmio_write_32(LLC_SYNC(ap_index), 0); + /* Atomic write, no need to wait */ +} + +void llc_flush_all(int ap_index) +{ + mmio_write_32(LLC_CLEAN_INV_WAY(ap_index), LLC_ALL_WAYS_MASK); + llc_cache_sync(ap_index); +} + +void llc_clean_all(int ap_index) +{ + mmio_write_32(LLC_CLEAN_WAY(ap_index), LLC_ALL_WAYS_MASK); + llc_cache_sync(ap_index); +} + +void llc_inv_all(int ap_index) +{ + mmio_write_32(LLC_INV_WAY(ap_index), LLC_ALL_WAYS_MASK); + llc_cache_sync(ap_index); +} + +void llc_disable(int ap_index) +{ + llc_flush_all(ap_index); + mmio_write_32(LLC_CTRL(ap_index), 0); + dsbishst(); +} + +void llc_enable(int ap_index, int excl_mode) +{ + uint32_t val; + + dsbsy(); + llc_inv_all(ap_index); + dsbsy(); + + val = LLC_CTRL_EN; + if (excl_mode) + val |= LLC_EXCLUSIVE_EN; + + mmio_write_32(LLC_CTRL(ap_index), val); + dsbsy(); +} + +int llc_is_exclusive(int ap_index) +{ + uint32_t reg; + + reg = mmio_read_32(LLC_CTRL(ap_index)); + + if ((reg & (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) == + (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) + return 1; + + return 0; +} + +void llc_runtime_enable(int ap_index) +{ + uint32_t reg; + + reg = mmio_read_32(LLC_CTRL(ap_index)); + if (reg & LLC_CTRL_EN) + return; + + INFO("Enabling LLC\n"); + + /* + * Enable L2 UniqueClean evictions with data + * Note: this configuration assumes that LLC is configured + * in exclusive mode. + * Later on in the code this assumption will be validated + */ + ca72_l2_enable_unique_clean(); + llc_enable(ap_index, 1); + + /* Set point of coherency to DDR. + * This is required by units which have SW cache coherency + */ + reg = mmio_read_32(CCU_HTC_CR(ap_index)); + reg |= (0x1 << CCU_SET_POC_OFFSET); + mmio_write_32(CCU_HTC_CR(ap_index), reg); +} + +#if LLC_SRAM +int llc_sram_enable(int ap_index, int size) +{ + uint32_t tc, way, ways_to_allocate; + uint32_t way_addr; + + if ((size <= 0) || (size > LLC_SIZE) || (size % LLC_WAY_SIZE)) + return -1; + + llc_enable(ap_index, 1); + llc_inv_all(ap_index); + + ways_to_allocate = size / LLC_WAY_SIZE; + + /* Lockdown all available ways for all traffic classes */ + for (tc = 0; tc < LLC_TC_NUM; tc++) + mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_ALL_WAYS_MASK); + + /* Clear the high bits of SRAM address */ + mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0); + + way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE; + for (way = 0; way < ways_to_allocate; way++) { + /* Trigger allocation block command */ + mmio_write_32(LLC_BLK_ALOC(ap_index), + LLC_BLK_ALOC_BASE_ADDR(way_addr) | + LLC_BLK_ALOC_WAY_DATA_SET | + LLC_BLK_ALOC_WAY_ID(way)); + way_addr += LLC_WAY_SIZE; + } + return 0; +} + +void llc_sram_disable(int ap_index) +{ + uint32_t tc; + + /* Disable the line lockings */ + for (tc = 0; tc < LLC_TC_NUM; tc++) + mmio_write_32(LLC_TCN_LOCK(ap_index, tc), 0); + + /* Invalidate all ways */ + llc_inv_all(ap_index); +} + +int llc_sram_test(int ap_index, int size, char *msg) +{ + uintptr_t addr, end_addr; + uint32_t data = 0; + + if ((size <= 0) || (size > LLC_SIZE)) + return -1; + + INFO("=== LLC SRAM WRITE test %s\n", msg); + for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE, + end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size; + addr < end_addr; addr += 4) { + mmio_write_32(addr, addr); + } + INFO("=== LLC SRAM WRITE test %s PASSED\n", msg); + INFO("=== LLC SRAM READ test %s\n", msg); + for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE, + end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size; + addr < end_addr; addr += 4) { + data = mmio_read_32(addr); + if (data != addr) { + INFO("=== LLC SRAM READ test %s FAILED @ 0x%08lx)\n", + msg, addr); + return -1; + } + } + INFO("=== LLC SRAM READ test %s PASSED (last read = 0x%08x)\n", + msg, data); + return 0; +} + +#endif /* LLC_SRAM */ diff --git a/arm-trusted-firmware/drivers/marvell/ccu.c b/arm-trusted-firmware/drivers/marvell/ccu.c new file mode 100644 index 0000000..c206f11 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/ccu.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* CCU unit device driver for Marvell AP807, AP807 and AP810 SoCs */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) +/* Physical address of the base of the window = {AddrLow[19:0],20'h0} */ +#define ADDRESS_SHIFT (20 - 4) +#define ADDRESS_MASK (0xFFFFFFF0) +#define CCU_WIN_ALIGNMENT (0x100000) + +/* + * Physical address of the highest address of window bits[31:19] = 0x6FF + * Physical address of the lowest address of window bits[18:6] = 0x6E0 + * Unit Id bits [5:2] = 2 + * RGF Window Enable bit[0] = 1 + * 0x37f9b809 - 11011111111 0011011100000 0010 0 1 + */ +#define ERRATA_WA_CCU_WIN4 0x37f9b809U + +/* + * Physical address of the highest address of window bits[31:19] = 0xFFF + * Physical address of the lowest address of window bits[18:6] = 0x800 + * Unit Id bits [5:2] = 2 + * RGF Window Enable bit[0] = 1 + * 0x7ffa0009 - 111111111111 0100000000000 0010 0 1 + */ +#define ERRATA_WA_CCU_WIN5 0x7ffa0009U + +/* + * Physical address of the highest address of window bits[31:19] = 0x1FFF + * Physical address of the lowest address of window bits[18:6] = 0x1000 + * Unit Id bits [5:2] = 2 + * RGF Window Enable bit[0] = 1 + * 0xfffc000d - 1111111111111 1000000000000 0011 0 1 + */ +#define ERRATA_WA_CCU_WIN6 0xfffc000dU + +#define IS_DRAM_TARGET(tgt) ((((tgt) == DRAM_0_TID) || \ + ((tgt) == DRAM_1_TID) || \ + ((tgt) == RAR_TID)) ? 1 : 0) + +#define CCU_RGF(win) (MVEBU_CCU_BASE(MVEBU_AP0) + \ + 0x90 + 4 * (win)) + +/* For storage of CR, SCR, ALR, AHR abd GCR */ +static uint32_t ccu_regs_save[MVEBU_CCU_MAX_WINS * 4 + 1]; + +#ifdef DEBUG_ADDR_MAP +static void dump_ccu(int ap_index) +{ + uint32_t win_id, win_cr, alr, ahr; + uint8_t target_id; + uint64_t start, end; + + /* Dump all AP windows */ + printf("\tbank target start end\n"); + printf("\t----------------------------------------------------\n"); + for (win_id = 0; win_id < MVEBU_CCU_MAX_WINS; win_id++) { + win_cr = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + if (win_cr & WIN_ENABLE_BIT) { + target_id = (win_cr >> CCU_TARGET_ID_OFFSET) & + CCU_TARGET_ID_MASK; + alr = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_index, + win_id)); + ahr = mmio_read_32(CCU_WIN_AHR_OFFSET(ap_index, + win_id)); + start = ((uint64_t)alr << ADDRESS_SHIFT); + end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); + printf("\tccu%d %02x 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + win_id, target_id, start, end); + } + } + win_cr = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_index)); + target_id = (win_cr >> CCU_GCR_TARGET_OFFSET) & CCU_GCR_TARGET_MASK; + printf("\tccu GCR %d - all other transactions\n", target_id); +} +#endif + +void ccu_win_check(struct addr_map_win *win) +{ + /* check if address is aligned to 1M */ + if (IS_NOT_ALIGN(win->base_addr, CCU_WIN_ALIGNMENT)) { + win->base_addr = ALIGN_UP(win->base_addr, CCU_WIN_ALIGNMENT); + NOTICE("%s: Align up the base address to 0x%" PRIx64 "\n", + __func__, win->base_addr); + } + + /* size parameter validity check */ + if (IS_NOT_ALIGN(win->win_size, CCU_WIN_ALIGNMENT)) { + win->win_size = ALIGN_UP(win->win_size, CCU_WIN_ALIGNMENT); + NOTICE("%s: Aligning size to 0x%" PRIx64 "\n", + __func__, win->win_size); + } +} + +int ccu_is_win_enabled(int ap_index, uint32_t win_id) +{ + return mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)) & + WIN_ENABLE_BIT; +} + +void ccu_enable_win(int ap_index, struct addr_map_win *win, uint32_t win_id) +{ + uint32_t ccu_win_reg; + uint32_t alr, ahr; + uint64_t end_addr; + + if ((win_id == 0) || (win_id > MVEBU_CCU_MAX_WINS)) { + ERROR("Enabling wrong CCU window %d!\n", win_id); + return; + } + + end_addr = (win->base_addr + win->win_size - 1); + alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + + mmio_write_32(CCU_WIN_ALR_OFFSET(ap_index, win_id), alr); + mmio_write_32(CCU_WIN_AHR_OFFSET(ap_index, win_id), ahr); + + ccu_win_reg = WIN_ENABLE_BIT; + ccu_win_reg |= (win->target_id & CCU_TARGET_ID_MASK) + << CCU_TARGET_ID_OFFSET; + mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), ccu_win_reg); +} + +static void ccu_disable_win(int ap_index, uint32_t win_id) +{ + uint32_t win_reg; + + if ((win_id == 0) || (win_id > MVEBU_CCU_MAX_WINS)) { + ERROR("Disabling wrong CCU window %d!\n", win_id); + return; + } + + win_reg = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), win_reg); +} + +/* Insert/Remove temporary window for using the out-of reset default + * CPx base address to access the CP configuration space prior to + * the further base address update in accordance with address mapping + * design. + * + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void ccu_temp_win_insert(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + win_id = MVEBU_CCU_MAX_WINS - 1 - i; + ccu_win_check(win); + ccu_enable_win(ap_index, win, win_id); + win++; + } +} + +/* + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void ccu_temp_win_remove(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + uint64_t base; + uint32_t target; + + win_id = MVEBU_CCU_MAX_WINS - 1 - i; + + target = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + target >>= CCU_TARGET_ID_OFFSET; + target &= CCU_TARGET_ID_MASK; + + base = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_index, win_id)); + base <<= ADDRESS_SHIFT; + + if ((win->target_id != target) || (win->base_addr != base)) { + ERROR("%s: Trying to remove bad window-%d!\n", + __func__, win_id); + continue; + } + ccu_disable_win(ap_index, win_id); + win++; + } +} + +/* Returns current DRAM window target (DRAM_0_TID, DRAM_1_TID, RAR_TID) + * NOTE: Call only once for each AP. + * The AP0 DRAM window is located at index 2 only at the BL31 execution start. + * Then it relocated to index 1 for matching the rest of APs DRAM settings. + * Calling this function after relocation will produce wrong results on AP0 + */ +static uint32_t ccu_dram_target_get(int ap_index) +{ + /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. + * All the rest of detected APs will use window at index 1. + * The AP0 DRAM window is moved from index 2 to 1 during + * init_ccu() execution. + */ + const uint32_t win_id = (ap_index == 0) ? 2 : 1; + uint32_t target; + + target = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + target >>= CCU_TARGET_ID_OFFSET; + target &= CCU_TARGET_ID_MASK; + + return target; +} + +void ccu_dram_target_set(int ap_index, uint32_t target) +{ + /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. + * All the rest of detected APs will use window at index 1. + * The AP0 DRAM window is moved from index 2 to 1 + * during init_ccu() execution. + */ + const uint32_t win_id = (ap_index == 0) ? 2 : 1; + uint32_t dram_cr; + + dram_cr = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + dram_cr &= ~(CCU_TARGET_ID_MASK << CCU_TARGET_ID_OFFSET); + dram_cr |= (target & CCU_TARGET_ID_MASK) << CCU_TARGET_ID_OFFSET; + mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), dram_cr); +} + +/* Setup CCU DRAM window and enable it */ +void ccu_dram_win_config(int ap_index, struct addr_map_win *win) +{ +#if IMAGE_BLE /* BLE */ + /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. + * Since the BootROM is not accessing DRAM at BLE stage, + * the DRAM window can be temporarely disabled. + */ + const uint32_t win_id = (ap_index == 0) ? 2 : 1; +#else /* end of BLE */ + /* At the ccu_init() execution stage, DRAM windows of all APs + * are arranged at index 1. + * The AP0 still has the old window BootROM DRAM at index 2, so + * the window-1 can be safely disabled without breaking the DRAM access. + */ + const uint32_t win_id = 1; +#endif + + ccu_disable_win(ap_index, win_id); + /* enable write secure (and clear read secure) */ + mmio_write_32(CCU_WIN_SCR_OFFSET(ap_index, win_id), + CCU_WIN_ENA_WRITE_SECURE); + ccu_win_check(win); + ccu_enable_win(ap_index, win, win_id); +} + +/* Save content of CCU window + GCR */ +static void ccu_save_win_range(int ap_id, int win_first, + int win_last, uint32_t *buffer) +{ + int win_id, idx; + /* Save CCU */ + for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { + buffer[idx++] = mmio_read_32(CCU_WIN_CR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(CCU_WIN_SCR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(CCU_WIN_AHR_OFFSET(ap_id, win_id)); + } + buffer[idx] = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_id)); +} + +/* Restore content of CCU window + GCR */ +static void ccu_restore_win_range(int ap_id, int win_first, + int win_last, uint32_t *buffer) +{ + int win_id, idx; + /* Restore CCU */ + for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { + mmio_write_32(CCU_WIN_CR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(CCU_WIN_SCR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(CCU_WIN_ALR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(CCU_WIN_AHR_OFFSET(ap_id, win_id), buffer[idx++]); + } + mmio_write_32(CCU_WIN_GCR_OFFSET(ap_id), buffer[idx]); +} + +void ccu_save_win_all(int ap_id) +{ + ccu_save_win_range(ap_id, 0, MVEBU_CCU_MAX_WINS - 1, ccu_regs_save); +} + +void ccu_restore_win_all(int ap_id) +{ + ccu_restore_win_range(ap_id, 0, MVEBU_CCU_MAX_WINS - 1, ccu_regs_save); +} + +int init_ccu(int ap_index) +{ + struct addr_map_win *win, *dram_win; + uint32_t win_id, win_reg; + uint32_t win_count, array_id; + uint32_t dram_target; +#if IMAGE_BLE + /* In BootROM context CCU Window-1 + * has SRAM_TID target and should not be disabled + */ + const uint32_t win_start = 2; +#else + const uint32_t win_start = 1; +#endif + + INFO("Initializing CCU Address decoding\n"); + + /* Get the array of the windows and fill the map data */ + marvell_get_ccu_memory_map(ap_index, &win, &win_count); + if (win_count <= 0) { + INFO("No windows configurations found\n"); + } else if (win_count > (MVEBU_CCU_MAX_WINS - 1)) { + ERROR("CCU mem map array > than max available windows (%d)\n", + MVEBU_CCU_MAX_WINS); + win_count = MVEBU_CCU_MAX_WINS; + } + + /* Need to set GCR to DRAM before all CCU windows are disabled for + * securing the normal access to DRAM location, which the ATF is running + * from. Once all CCU windows are set, which have to include the + * dedicated DRAM window as well, the GCR can be switched to the target + * defined by the platform configuration. + */ + dram_target = ccu_dram_target_get(ap_index); + win_reg = (dram_target & CCU_GCR_TARGET_MASK) << CCU_GCR_TARGET_OFFSET; + mmio_write_32(CCU_WIN_GCR_OFFSET(ap_index), win_reg); + + /* If the DRAM window was already configured at the BLE stage, + * only the window target considered valid, the address range should be + * updated according to the platform configuration. + */ + for (dram_win = win, array_id = 0; array_id < win_count; + array_id++, dram_win++) { + if (IS_DRAM_TARGET(dram_win->target_id)) { + dram_win->target_id = dram_target; + break; + } + } + + /* Disable all AP CCU windows + * Window-0 is always bypassed since it already contains + * data allowing the internal configuration space access + */ + for (win_id = win_start; win_id < MVEBU_CCU_MAX_WINS; win_id++) { + ccu_disable_win(ap_index, win_id); + /* enable write secure (and clear read secure) */ + mmio_write_32(CCU_WIN_SCR_OFFSET(ap_index, win_id), + CCU_WIN_ENA_WRITE_SECURE); + } + + /* win_id is the index of the current ccu window + * array_id is the index of the current memory map window entry + */ + for (win_id = win_start, array_id = 0; + ((win_id < MVEBU_CCU_MAX_WINS) && (array_id < win_count)); + win_id++) { + ccu_win_check(win); + ccu_enable_win(ap_index, win, win_id); + win++; + array_id++; + } + + /* Get & set the default target according to board topology */ + win_reg = (marvell_get_ccu_gcr_target(ap_index) & CCU_GCR_TARGET_MASK) + << CCU_GCR_TARGET_OFFSET; + mmio_write_32(CCU_WIN_GCR_OFFSET(ap_index), win_reg); + +#ifdef DEBUG_ADDR_MAP + dump_ccu(ap_index); +#endif + + INFO("Done CCU Address decoding Initializing\n"); + + return 0; +} + +void errata_wa_init(void) +{ + /* + * EERATA ID: RES-3033912 - Internal Address Space Init state causes + * a hang upon accesses to [0xf070_0000, 0xf07f_ffff] + * Workaround: Boot Firmware (ATF) should configure CCU_RGF_WIN(4) to + * split [0x6e_0000, 0x1ff_ffff] to values [0x6e_0000, 0x6f_ffff] and + * [0x80_0000, 0xff_ffff] and [0x100_0000, 0x1ff_ffff],that cause + * accesses to the segment of [0xf070_0000, 0xf1ff_ffff] + * to act as RAZWI. + */ + mmio_write_32(CCU_RGF(4), ERRATA_WA_CCU_WIN4); + mmio_write_32(CCU_RGF(5), ERRATA_WA_CCU_WIN5); + mmio_write_32(CCU_RGF(6), ERRATA_WA_CCU_WIN6); +} diff --git a/arm-trusted-firmware/drivers/marvell/comphy.h b/arm-trusted-firmware/drivers/marvell/comphy.h new file mode 100644 index 0000000..fab564e --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy.h @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Driver for COMPHY unit that is part or Marvell A8K SoCs */ + +#ifndef COMPHY_H +#define COMPHY_H + +/* COMPHY registers */ +#define COMMON_PHY_CFG1_REG 0x0 +#define COMMON_PHY_CFG1_PWR_UP_OFFSET 1 +#define COMMON_PHY_CFG1_PWR_UP_MASK \ + (0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET) +#define COMMON_PHY_CFG1_PIPE_SELECT_OFFSET 2 +#define COMMON_PHY_CFG1_PIPE_SELECT_MASK \ + (0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET) +#define COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET 13 +#define COMMON_PHY_CFG1_PWR_ON_RESET_MASK \ + (0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET) +#define COMMON_PHY_CFG1_CORE_RSTN_OFFSET 14 +#define COMMON_PHY_CFG1_CORE_RSTN_MASK \ + (0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET) +#define COMMON_PHY_PHY_MODE_OFFSET 15 +#define COMMON_PHY_PHY_MODE_MASK \ + (0x1 << COMMON_PHY_PHY_MODE_OFFSET) + +#define COMMON_SELECTOR_PHY_OFFSET 0x140 +#define COMMON_SELECTOR_PIPE_OFFSET 0x144 + +#define COMMON_PHY_SD_CTRL1 0x148 +#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET 0 +#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK 0xFFFF +#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET 24 +#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET) +#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET 25 +#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET) + +#define DFX_DEV_GEN_CTRL12 0x80 +#define DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET 7 +#define DFX_DEV_GEN_PCIE_CLK_SRC_MASK \ + (0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET) + +/* HPIPE register */ +#define HPIPE_PWR_PLL_REG 0x4 +#define HPIPE_PWR_PLL_REF_FREQ_OFFSET 0 +#define HPIPE_PWR_PLL_REF_FREQ_MASK \ + (0x1f << HPIPE_PWR_PLL_REF_FREQ_OFFSET) +#define HPIPE_PWR_PLL_PHY_MODE_OFFSET 5 +#define HPIPE_PWR_PLL_PHY_MODE_MASK \ + (0x7 << HPIPE_PWR_PLL_PHY_MODE_OFFSET) + +#define HPIPE_DFE_REG0 0x01C +#define HPIPE_DFE_RES_FORCE_OFFSET 15 +#define HPIPE_DFE_RES_FORCE_MASK \ + (0x1 << HPIPE_DFE_RES_FORCE_OFFSET) + +#define HPIPE_G2_SET_1_REG 0x040 +#define HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET 0 +#define HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET 3 +#define HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK \ + (0x7 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET 6 +#define HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK \ + (0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET) + +#define HPIPE_G3_SETTINGS_1_REG 0x048 +#define HPIPE_G3_RX_SELMUPI_OFFSET 0 +#define HPIPE_G3_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G3_RX_SELMUPI_OFFSET) +#define HPIPE_G3_RX_SELMUPF_OFFSET 3 +#define HPIPE_G3_RX_SELMUPF_MASK \ + (0x7 << HPIPE_G3_RX_SELMUPF_OFFSET) +#define HPIPE_G3_SETTING_BIT_OFFSET 13 +#define HPIPE_G3_SETTING_BIT_MASK \ + (0x1 << HPIPE_G3_SETTING_BIT_OFFSET) + +#define HPIPE_INTERFACE_REG 0x94 +#define HPIPE_INTERFACE_GEN_MAX_OFFSET 10 +#define HPIPE_INTERFACE_GEN_MAX_MASK \ + (0x3 << HPIPE_INTERFACE_GEN_MAX_OFFSET) +#define HPIPE_INTERFACE_DET_BYPASS_OFFSET 12 +#define HPIPE_INTERFACE_DET_BYPASS_MASK \ + (0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET) +#define HPIPE_INTERFACE_LINK_TRAIN_OFFSET 14 +#define HPIPE_INTERFACE_LINK_TRAIN_MASK \ + (0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET) + +#define HPIPE_VDD_CAL_CTRL_REG 0x114 +#define HPIPE_EXT_SELLV_RXSAMPL_OFFSET 5 +#define HPIPE_EXT_SELLV_RXSAMPL_MASK \ + (0x1f << HPIPE_EXT_SELLV_RXSAMPL_OFFSET) + +#define HPIPE_PCIE_REG0 0x120 +#define HPIPE_PCIE_IDLE_SYNC_OFFSET 12 +#define HPIPE_PCIE_IDLE_SYNC_MASK \ + (0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET) +#define HPIPE_PCIE_SEL_BITS_OFFSET 13 +#define HPIPE_PCIE_SEL_BITS_MASK \ + (0x3 << HPIPE_PCIE_SEL_BITS_OFFSET) + +#define HPIPE_LANE_ALIGN_REG 0x124 +#define HPIPE_LANE_ALIGN_OFF_OFFSET 12 +#define HPIPE_LANE_ALIGN_OFF_MASK \ + (0x1 << HPIPE_LANE_ALIGN_OFF_OFFSET) + +#define HPIPE_MISC_REG 0x13C +#define HPIPE_MISC_CLK100M_125M_OFFSET 4 +#define HPIPE_MISC_CLK100M_125M_MASK \ + (0x1 << HPIPE_MISC_CLK100M_125M_OFFSET) +#define HPIPE_MISC_ICP_FORCE_OFFSET 5 +#define HPIPE_MISC_ICP_FORCE_MASK \ + (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET) +#define HPIPE_MISC_TXDCLK_2X_OFFSET 6 +#define HPIPE_MISC_TXDCLK_2X_MASK \ + (0x1 << HPIPE_MISC_TXDCLK_2X_OFFSET) +#define HPIPE_MISC_CLK500_EN_OFFSET 7 +#define HPIPE_MISC_CLK500_EN_MASK \ + (0x1 << HPIPE_MISC_CLK500_EN_OFFSET) +#define HPIPE_MISC_REFCLK_SEL_OFFSET 10 +#define HPIPE_MISC_REFCLK_SEL_MASK \ + (0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET) + +#define HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG 0x16C +#define HPIPE_SMAPLER_OFFSET 12 +#define HPIPE_SMAPLER_MASK (0x1 << HPIPE_SMAPLER_OFFSET) + +#define HPIPE_PWR_CTR_DTL_REG 0x184 +#define HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET 2 +#define HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET) + +#define HPIPE_FRAME_DET_CONTROL_REG 0x220 +#define HPIPE_FRAME_DET_LOCK_LOST_TO_OFFSET 12 +#define HPIPE_FRAME_DET_LOCK_LOST_TO_MASK \ + (0x1 << HPIPE_FRAME_DET_LOCK_LOST_TO_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_0_REG 0x268 +#define HPIPE_TX_TRAIN_P2P_HOLD_OFFSET 15 +#define HPIPE_TX_TRAIN_P2P_HOLD_MASK \ + (0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_REG 0x26C +#define HPIPE_TX_TRAIN_CTRL_G1_OFFSET 0 +#define HPIPE_TX_TRAIN_CTRL_G1_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET) +#define HPIPE_TX_TRAIN_CTRL_GN1_OFFSET 1 +#define HPIPE_TX_TRAIN_CTRL_GN1_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET) +#define HPIPE_TX_TRAIN_CTRL_G0_OFFSET 2 +#define HPIPE_TX_TRAIN_CTRL_G0_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_4_REG 0x278 +#define HPIPE_TRX_TRAIN_TIMER_OFFSET 0 +#define HPIPE_TRX_TRAIN_TIMER_MASK \ + (0x3FF << HPIPE_TRX_TRAIN_TIMER_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_5_REG 0x2A4 +#define HPIPE_TX_TRAIN_START_SQ_EN_OFFSET 11 +#define HPIPE_TX_TRAIN_START_SQ_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET) +#define HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET 12 +#define HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET) +#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET 13 +#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET) +#define HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET 14 +#define HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET) + +#define HPIPE_TX_TRAIN_REG 0x31C +#define HPIPE_TX_TRAIN_CHK_INIT_OFFSET 4 +#define HPIPE_TX_TRAIN_CHK_INIT_MASK \ + (0x1 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET) +#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET 7 +#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK \ + (0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET) + +#define HPIPE_CDR_CONTROL_REG 0x418 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET 14 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK \ + (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET) +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET 12 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK \ + (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET) +#define HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET 9 +#define HPIPE_CDR_MAX_DFE_ADAPT_0_MASK \ + (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET) +#define HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET 6 +#define HPIPE_CDR_MAX_DFE_ADAPT_1_MASK \ + (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_11_REG 0x438 +#define HPIPE_TX_STATUS_CHECK_MODE_OFFSET 6 +#define HPIPE_TX_TX_STATUS_CHECK_MODE_MASK \ + (0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET) +#define HPIPE_TX_NUM_OF_PRESET_OFFSET 10 +#define HPIPE_TX_NUM_OF_PRESET_MASK \ + (0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET) +#define HPIPE_TX_SWEEP_PRESET_EN_OFFSET 15 +#define HPIPE_TX_SWEEP_PRESET_EN_MASK \ + (0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET) +#define HPIPE_G2_SETTINGS_4_REG 0x44C +#define HPIPE_G2_DFE_RES_OFFSET 8 +#define HPIPE_G2_DFE_RES_MASK (0x3 << HPIPE_G2_DFE_RES_OFFSET) + +#define HPIPE_G3_SETTING_3_REG 0x450 +#define HPIPE_G3_FFE_CAP_SEL_OFFSET 0 +#define HPIPE_G3_FFE_CAP_SEL_MASK \ + (0xf << HPIPE_G3_FFE_CAP_SEL_OFFSET) +#define HPIPE_G3_FFE_RES_SEL_OFFSET 4 +#define HPIPE_G3_FFE_RES_SEL_MASK \ + (0x7 << HPIPE_G3_FFE_RES_SEL_OFFSET) +#define HPIPE_G3_FFE_SETTING_FORCE_OFFSET 7 +#define HPIPE_G3_FFE_SETTING_FORCE_MASK \ + (0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET) +#define HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET 12 +#define HPIPE_G3_FFE_DEG_RES_LEVEL_MASK \ + (0x3 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET) +#define HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET 14 +#define HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK \ + (0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET) + +#define HPIPE_G3_SETTING_4_REG 0x454 +#define HPIPE_G3_DFE_RES_OFFSET 8 +#define HPIPE_G3_DFE_RES_MASK (0x3 << HPIPE_G3_DFE_RES_OFFSET) + +#define HPIPE_DFE_CONTROL_REG 0x470 +#define HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET 14 +#define HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK \ + (0x3 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET) + +#define HPIPE_DFE_CTRL_28_REG 0x49C +#define HPIPE_DFE_CTRL_28_PIPE4_OFFSET 7 +#define HPIPE_DFE_CTRL_28_PIPE4_MASK \ + (0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET) + +#define HPIPE_G3_SETTING_5_REG 0x548 +#define HPIPE_G3_SETTING_5_G3_ICP_OFFSET 0 +#define HPIPE_G3_SETTING_5_G3_ICP_MASK \ + (0xf << HPIPE_G3_SETTING_5_G3_ICP_OFFSET) + +#define HPIPE_LANE_STATUS1_REG 0x60C +#define HPIPE_LANE_STATUS1_PCLK_EN_OFFSET 0 +#define HPIPE_LANE_STATUS1_PCLK_EN_MASK \ + (0x1 << HPIPE_LANE_STATUS1_PCLK_EN_OFFSET) + +#define HPIPE_LANE_CFG4_REG 0x620 +#define HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET 3 +#define HPIPE_LANE_CFG4_DFE_EN_SEL_MASK \ + (0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET) + +#define HPIPE_LANE_EQU_CONFIG_0_REG 0x69C +#define HPIPE_CFG_EQ_FS_OFFSET 0 +#define HPIPE_CFG_EQ_FS_MASK (0x3f << HPIPE_CFG_EQ_FS_OFFSET) +#define HPIPE_CFG_EQ_LF_OFFSET 6 +#define HPIPE_CFG_EQ_LF_MASK (0x3f << HPIPE_CFG_EQ_LF_OFFSET) +#define HPIPE_CFG_PHY_RC_EP_OFFSET 12 +#define HPIPE_CFG_PHY_RC_EP_MASK \ + (0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET) + +#define HPIPE_LANE_EQ_CFG1_REG 0x6a0 +#define HPIPE_CFG_UPDATE_POLARITY_OFFSET 12 +#define HPIPE_CFG_UPDATE_POLARITY_MASK \ + (0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET) + +#define HPIPE_LANE_EQ_CFG2_REG 0x6a4 +#define HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET 14 +#define HPIPE_CFG_EQ_BUNDLE_DIS_MASK \ + (0x1 << HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET) + +#define HPIPE_LANE_PRESET_CFG0_REG 0x6a8 +#define HPIPE_CFG_CURSOR_PRESET0_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET0_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET0_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET1_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET1_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET1_OFFSET) + +#define HPIPE_LANE_PRESET_CFG1_REG 0x6ac +#define HPIPE_CFG_CURSOR_PRESET2_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET2_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET2_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET3_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET3_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET3_OFFSET) + +#define HPIPE_LANE_PRESET_CFG2_REG 0x6b0 +#define HPIPE_CFG_CURSOR_PRESET4_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET4_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET4_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET5_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET5_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET5_OFFSET) + +#define HPIPE_LANE_PRESET_CFG3_REG 0x6b4 +#define HPIPE_CFG_CURSOR_PRESET6_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET6_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET6_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET7_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET7_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET7_OFFSET) + +#define HPIPE_LANE_PRESET_CFG4_REG 0x6b8 +#define HPIPE_CFG_CURSOR_PRESET8_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET8_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET8_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET9_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET9_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET9_OFFSET) + +#define HPIPE_LANE_PRESET_CFG5_REG 0x6bc +#define HPIPE_CFG_CURSOR_PRESET10_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET10_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET10_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET11_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET11_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET11_OFFSET) + +#define HPIPE_LANE_PRESET_CFG6_REG 0x6c0 +#define HPIPE_CFG_PRE_CURSOR_PRESET0_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET0_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET0_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET0_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET0_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET0_OFFSET) + +#define HPIPE_LANE_PRESET_CFG7_REG 0x6c4 +#define HPIPE_CFG_PRE_CURSOR_PRESET1_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET1_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET1_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET1_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET1_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET1_OFFSET) + +#define HPIPE_LANE_PRESET_CFG8_REG 0x6c8 +#define HPIPE_CFG_PRE_CURSOR_PRESET2_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET2_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET2_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET2_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET2_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET2_OFFSET) + +#define HPIPE_LANE_PRESET_CFG9_REG 0x6cc +#define HPIPE_CFG_PRE_CURSOR_PRESET3_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET3_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET3_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET3_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET3_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET3_OFFSET) + +#define HPIPE_LANE_PRESET_CFG10_REG 0x6d0 +#define HPIPE_CFG_PRE_CURSOR_PRESET4_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET4_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET4_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET4_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET4_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET4_OFFSET) + +#define HPIPE_LANE_PRESET_CFG11_REG 0x6d4 +#define HPIPE_CFG_PRE_CURSOR_PRESET5_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET5_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET5_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET5_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET5_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET5_OFFSET) + +#define HPIPE_LANE_PRESET_CFG12_REG 0x6d8 +#define HPIPE_CFG_PRE_CURSOR_PRESET6_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET6_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET6_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET6_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET6_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET6_OFFSET) + +#define HPIPE_LANE_PRESET_CFG13_REG 0x6dc +#define HPIPE_CFG_PRE_CURSOR_PRESET7_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET7_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET7_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET7_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET7_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET7_OFFSET) + +#define HPIPE_LANE_PRESET_CFG14_REG 0x6e0 +#define HPIPE_CFG_PRE_CURSOR_PRESET8_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET8_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET8_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET8_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET8_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET8_OFFSET) + +#define HPIPE_LANE_PRESET_CFG15_REG 0x6e4 +#define HPIPE_CFG_PRE_CURSOR_PRESET9_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET9_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET9_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET9_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET9_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET9_OFFSET) + +#define HPIPE_LANE_PRESET_CFG16_REG 0x6e8 +#define HPIPE_CFG_PRE_CURSOR_PRESET10_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET10_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET10_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET10_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET10_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET10_OFFSET) + +#define HPIPE_LANE_EQ_REMOTE_SETTING_REG 0x6f8 +#define HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET 0 +#define HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK \ + (0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET) +#define HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET 1 +#define HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK \ + (0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET) +#define HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET 2 +#define HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK \ + (0xf << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET) + +#define HPIPE_RST_CLK_CTRL_REG 0x704 +#define HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET 0 +#define HPIPE_RST_CLK_CTRL_PIPE_RST_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET) +#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET 2 +#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET) +#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET 3 +#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET) +#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET 9 +#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET) + +#define HPIPE_CLK_SRC_LO_REG 0x70c +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET 1 +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK \ + (0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET) +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET 2 +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK \ + (0x3 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET) +#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET 5 +#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK \ + (0x7 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET) + +#define HPIPE_CLK_SRC_HI_REG 0x710 +#define HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET 0 +#define HPIPE_CLK_SRC_HI_LANE_STRT_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET) +#define HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET 1 +#define HPIPE_CLK_SRC_HI_LANE_BREAK_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET) +#define HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET 2 +#define HPIPE_CLK_SRC_HI_LANE_MASTER_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET) +#define HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET 7 +#define HPIPE_CLK_SRC_HI_MODE_PIPE_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET) + +#define HPIPE_GLOBAL_PM_CTRL 0x740 +#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET 0 +#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK \ + (0xFF << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET) + +#endif /* COMPHY_H */ diff --git a/arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h b/arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h new file mode 100644 index 0000000..af5c715 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h @@ -0,0 +1,914 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Marvell CP110 SoC COMPHY unit driver */ + +#ifndef COMPHY_CP110_H +#define COMPHY_CP110_H + +#define SD_ADDR(base, lane) (base + 0x1000 * lane) +#define HPIPE_ADDR(base, lane) (SD_ADDR(base, lane) + 0x800) +#define COMPHY_ADDR(base, lane) (base + 0x28 * lane) + +#define MAX_NUM_OF_FFE 8 +#define RX_TRAINING_TIMEOUT 500 + +/* Comphy registers */ +#define COMMON_PHY_CFG1_REG 0x0 +#define COMMON_PHY_CFG1_PWR_UP_OFFSET 1 +#define COMMON_PHY_CFG1_PWR_UP_MASK \ + (0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET) +#define COMMON_PHY_CFG1_PIPE_SELECT_OFFSET 2 +#define COMMON_PHY_CFG1_PIPE_SELECT_MASK \ + (0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET) +#define COMMON_PHY_CFG1_CORE_RSTN_OFFSET 13 +#define COMMON_PHY_CFG1_CORE_RSTN_MASK \ + (0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET) +#define COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET 14 +#define COMMON_PHY_CFG1_PWR_ON_RESET_MASK \ + (0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET) +#define COMMON_PHY_PHY_MODE_OFFSET 15 +#define COMMON_PHY_PHY_MODE_MASK \ + (0x1 << COMMON_PHY_PHY_MODE_OFFSET) + +#define COMMON_PHY_CFG6_REG 0x14 +#define COMMON_PHY_CFG6_IF_40_SEL_OFFSET 18 +#define COMMON_PHY_CFG6_IF_40_SEL_MASK \ + (0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET) + +#define COMMON_PHY_CFG6_REG 0x14 +#define COMMON_PHY_CFG6_IF_40_SEL_OFFSET 18 +#define COMMON_PHY_CFG6_IF_40_SEL_MASK \ + (0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET) + +#define COMMON_SELECTOR_PHY_REG_OFFSET 0x140 +#define COMMON_SELECTOR_PIPE_REG_OFFSET 0x144 +#define COMMON_SELECTOR_COMPHY_MASK 0xf +#define COMMON_SELECTOR_COMPHYN_FIELD_WIDTH 4 +#define COMMON_SELECTOR_COMPHYN_SATA 0x4 +#define COMMON_SELECTOR_PIPE_COMPHY_PCIE 0x4 +#define COMMON_SELECTOR_PIPE_COMPHY_USBH 0x1 +#define COMMON_SELECTOR_PIPE_COMPHY_USBD 0x2 + +/* SGMII/Base-X/SFI/RXAUI */ +#define COMMON_SELECTOR_COMPHY0_1_2_NETWORK 0x1 +#define COMMON_SELECTOR_COMPHY3_RXAUI 0x1 +#define COMMON_SELECTOR_COMPHY3_SGMII 0x2 +#define COMMON_SELECTOR_COMPHY4_PORT1 0x1 +#define COMMON_SELECTOR_COMPHY4_ALL_OTHERS 0x2 +#define COMMON_SELECTOR_COMPHY5_RXAUI 0x2 +#define COMMON_SELECTOR_COMPHY5_SGMII 0x1 + +#define COMMON_PHY_SD_CTRL1 0x148 +#define COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET 0 +#define COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET 4 +#define COMMON_PHY_SD_CTRL1_COMPHY_2_PORT_OFFSET 8 +#define COMMON_PHY_SD_CTRL1_COMPHY_3_PORT_OFFSET 12 +#define COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK 0xFFFF +#define COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK 0xFF +#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET 24 +#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET) +#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET 25 +#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET) +#define COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET 26 +#define COMMON_PHY_SD_CTRL1_RXAUI1_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET) +#define COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET 27 +#define COMMON_PHY_SD_CTRL1_RXAUI0_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET) + +/* DFX register */ +#define DFX_BASE (0x400000) +#define DFX_DEV_GEN_CTRL12_REG (0x280) +#define DFX_DEV_GEN_PCIE_CLK_SRC_MUX (0x3) +#define DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET 7 +#define DFX_DEV_GEN_PCIE_CLK_SRC_MASK \ + (0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET) + +/* SerDes IP registers */ +#define SD_EXTERNAL_CONFIG0_REG 0 +#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET 1 +#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK \ + (1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET) +#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET 3 +#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK \ + (0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET) +#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET 7 +#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK \ + (0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET) +#define SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET 11 +#define SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK \ + (1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET) +#define SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET 12 +#define SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK \ + (1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET) +#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET 14 +#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK \ + (1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET) +#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET 15 +#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK \ + (0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET) + +#define SD_EXTERNAL_CONFIG1_REG 0x4 +#define SD_EXTERNAL_CONFIG1_TX_IDLE_OFFSET 2 +#define SD_EXTERNAL_CONFIG1_TX_IDLE_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_TX_IDLE_OFFSET) +#define SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET 3 +#define SD_EXTERNAL_CONFIG1_RESET_IN_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET) +#define SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET 4 +#define SD_EXTERNAL_CONFIG1_RX_INIT_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET) +#define SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET 5 +#define SD_EXTERNAL_CONFIG1_RESET_CORE_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET) +#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET 6 +#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET) + +#define SD_EXTERNAL_CONFIG2_REG 0x8 +#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET 4 +#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK \ + (0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET) +#define SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET 7 +#define SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK \ + (0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET) + +#define SD_EXTERNAL_STATUS_REG 0xc +#define SD_EXTERNAL_STATUS_START_RX_TRAINING_OFFSET 7 +#define SD_EXTERNAL_STATUS_START_RX_TRAINING_MASK \ + (1 << SD_EXTERNAL_STATUS_START_RX_TRAINING_OFFSET) + +#define SD_EXTERNAL_STATUS0_REG 0x18 +#define SD_EXTERNAL_STATUS0_PLL_TX_OFFSET 2 +#define SD_EXTERNAL_STATUS0_PLL_TX_MASK \ + (0x1 << SD_EXTERNAL_STATUS0_PLL_TX_OFFSET) +#define SD_EXTERNAL_STATUS0_PLL_RX_OFFSET 3 +#define SD_EXTERNAL_STATUS0_PLL_RX_MASK \ + (0x1 << SD_EXTERNAL_STATUS0_PLL_RX_OFFSET) +#define SD_EXTERNAL_STATUS0_RX_INIT_OFFSET 4 +#define SD_EXTERNAL_STATUS0_RX_INIT_MASK \ + (0x1 << SD_EXTERNAL_STATUS0_RX_INIT_OFFSET) + +#define SD_EXTERNAL_STATAUS1_REG 0x1c +#define SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_COMP_OFFSET 0 +#define SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_COMP_MASK \ + (1 << SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_COMP_OFFSET) +#define SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_FAILED_OFFSET 1 +#define SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_FAILED_MASK \ + (1 << SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_FAILED_OFFSET) + +/* HPIPE registers */ +#define HPIPE_PWR_PLL_REG 0x4 +#define HPIPE_PWR_PLL_REF_FREQ_OFFSET 0 +#define HPIPE_PWR_PLL_REF_FREQ_MASK \ + (0x1f << HPIPE_PWR_PLL_REF_FREQ_OFFSET) +#define HPIPE_PWR_PLL_PHY_MODE_OFFSET 5 +#define HPIPE_PWR_PLL_PHY_MODE_MASK \ + (0x7 << HPIPE_PWR_PLL_PHY_MODE_OFFSET) + +#define HPIPE_CAL_REG1_REG 0xc +#define HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET 10 +#define HPIPE_CAL_REG_1_EXT_TXIMP_MASK \ + (0x1f << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET) +#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET 15 +#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK \ + (0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET) + +#define HPIPE_SQUELCH_FFE_SETTING_REG 0x18 +#define HPIPE_SQUELCH_THRESH_IN_OFFSET 8 +#define HPIPE_SQUELCH_THRESH_IN_MASK \ + (0xf << HPIPE_SQUELCH_THRESH_IN_OFFSET) +#define HPIPE_SQUELCH_DETECTED_OFFSET 14 +#define HPIPE_SQUELCH_DETECTED_MASK \ + (0x1 << HPIPE_SQUELCH_DETECTED_OFFSET) + +#define HPIPE_DFE_REG0 0x1c +#define HPIPE_DFE_RES_FORCE_OFFSET 15 +#define HPIPE_DFE_RES_FORCE_MASK \ + (0x1 << HPIPE_DFE_RES_FORCE_OFFSET) + +#define HPIPE_DFE_F3_F5_REG 0x28 +#define HPIPE_DFE_F3_F5_DFE_EN_OFFSET 14 +#define HPIPE_DFE_F3_F5_DFE_EN_MASK \ + (0x1 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET) +#define HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET 15 +#define HPIPE_DFE_F3_F5_DFE_CTRL_MASK \ + (0x1 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET) + +#define HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG 0x30 +#define HPIPE_ADAPTED_DFE_RES_OFFSET 13 +#define HPIPE_ADAPTED_DFE_RES_MASK \ + (0x3 << HPIPE_ADAPTED_DFE_RES_OFFSET) + +#define HPIPE_G1_SET_0_REG 0x34 +#define HPIPE_G1_SET_0_G1_TX_AMP_OFFSET 1 +#define HPIPE_G1_SET_0_G1_TX_AMP_MASK \ + (0x1f << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET) +#define HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET 6 +#define HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK \ + (0x1 << HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET) +#define HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET 7 +#define HPIPE_G1_SET_0_G1_TX_EMPH1_MASK \ + (0xf << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET) +#define HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET 11 +#define HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK \ + (0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET) + +#define HPIPE_G1_SET_1_REG 0x38 +#define HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET 0 +#define HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET 3 +#define HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK \ + (0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET 6 +#define HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK \ + (0x3 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET 8 +#define HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK \ + (0x3 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET 10 +#define HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK \ + (0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET 11 +#define HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK \ + (0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET) + +#define HPIPE_G2_SET_0_REG 0x3c +#define HPIPE_G2_SET_0_G2_TX_AMP_OFFSET 1 +#define HPIPE_G2_SET_0_G2_TX_AMP_MASK \ + (0x1f << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET) +#define HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET 6 +#define HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK \ + (0x1 << HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET) +#define HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET 7 +#define HPIPE_G2_SET_0_G2_TX_EMPH1_MASK \ + (0xf << HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET) +#define HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET 11 +#define HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK \ + (0x1 << HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET) + +#define HPIPE_G2_SET_1_REG 0x40 +#define HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET 0 +#define HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET 3 +#define HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK \ + (0x7 << HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET 6 +#define HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK \ + (0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET 8 +#define HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK \ + (0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_DFE_EN_OFFSET 10 +#define HPIPE_G2_SET_1_G2_RX_DFE_EN_MASK \ + (0x1 << HPIPE_G2_SET_1_G2_RX_DFE_EN_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET 11 +#define HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK \ + (0x3 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET) + +#define HPIPE_G3_SET_0_REG 0x44 +#define HPIPE_G3_SET_0_G3_TX_AMP_OFFSET 1 +#define HPIPE_G3_SET_0_G3_TX_AMP_MASK \ + (0x1f << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET 6 +#define HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK \ + (0x1 << HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET 7 +#define HPIPE_G3_SET_0_G3_TX_EMPH1_MASK \ + (0xf << HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET 11 +#define HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK \ + (0x1 << HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET 12 +#define HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK \ + (0x7 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET 15 +#define HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK \ + (0x1 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET) + +#define HPIPE_G3_SET_1_REG 0x48 +#define HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET 0 +#define HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET 3 +#define HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK \ + (0x7 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET 6 +#define HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK \ + (0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET 8 +#define HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK \ + (0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET 10 +#define HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK \ + (0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET 11 +#define HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK \ + (0x3 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET) +#define HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET 13 +#define HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK \ + (0x1 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET) + +#define HPIPE_PHY_TEST_CONTROL_REG 0x54 +#define HPIPE_PHY_TEST_PATTERN_SEL_OFFSET 4 +#define HPIPE_PHY_TEST_PATTERN_SEL_MASK \ + (0xf << HPIPE_PHY_TEST_PATTERN_SEL_OFFSET) +#define HPIPE_PHY_TEST_RESET_OFFSET 14 +#define HPIPE_PHY_TEST_RESET_MASK \ + (0x1 << HPIPE_PHY_TEST_RESET_OFFSET) +#define HPIPE_PHY_TEST_EN_OFFSET 15 +#define HPIPE_PHY_TEST_EN_MASK \ + (0x1 << HPIPE_PHY_TEST_EN_OFFSET) + +#define HPIPE_PHY_TEST_DATA_REG 0x6c +#define HPIPE_PHY_TEST_DATA_OFFSET 0 +#define HPIPE_PHY_TEST_DATA_MASK \ + (0xffff << HPIPE_PHY_TEST_DATA_OFFSET) + +#define HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG 0x80 + +#define HPIPE_PHY_TEST_OOB_0_REGISTER 0x84 +#define HPIPE_PHY_PT_OOB_EN_OFFSET 14 +#define HPIPE_PHY_PT_OOB_EN_MASK \ + (0x1 << HPIPE_PHY_PT_OOB_EN_OFFSET) +#define HPIPE_PHY_TEST_PT_TESTMODE_OFFSET 12 +#define HPIPE_PHY_TEST_PT_TESTMODE_MASK \ + (0x3 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET) + +#define HPIPE_LOOPBACK_REG 0x8c +#define HPIPE_LOOPBACK_SEL_OFFSET 1 +#define HPIPE_LOOPBACK_SEL_MASK \ + (0x7 << HPIPE_LOOPBACK_SEL_OFFSET) +#define HPIPE_CDR_LOCK_OFFSET 7 +#define HPIPE_CDR_LOCK_MASK \ + (0x1 << HPIPE_CDR_LOCK_OFFSET) +#define HPIPE_CDR_LOCK_DET_EN_OFFSET 8 +#define HPIPE_CDR_LOCK_DET_EN_MASK \ + (0x1 << HPIPE_CDR_LOCK_DET_EN_OFFSET) + +#define HPIPE_SYNC_PATTERN_REG 0x090 +#define HPIPE_SYNC_PATTERN_TXD_INV_OFFSET 10 +#define HPIPE_SYNC_PATTERN_TXD_INV_MASK \ + (0x1 << HPIPE_SYNC_PATTERN_TXD_INV_OFFSET) +#define HPIPE_SYNC_PATTERN_RXD_INV_OFFSET 11 +#define HPIPE_SYNC_PATTERN_RXD_INV_MASK \ + (0x1 << HPIPE_SYNC_PATTERN_RXD_INV_OFFSET) + +#define HPIPE_INTERFACE_REG 0x94 +#define HPIPE_INTERFACE_GEN_MAX_OFFSET 10 +#define HPIPE_INTERFACE_GEN_MAX_MASK \ + (0x3 << HPIPE_INTERFACE_GEN_MAX_OFFSET) +#define HPIPE_INTERFACE_DET_BYPASS_OFFSET 12 +#define HPIPE_INTERFACE_DET_BYPASS_MASK \ + (0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET) +#define HPIPE_INTERFACE_LINK_TRAIN_OFFSET 14 +#define HPIPE_INTERFACE_LINK_TRAIN_MASK \ + (0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET) + +#define HPIPE_G1_SET_2_REG 0xf4 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET 0 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_MASK \ + (0xf << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET) +#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET 4 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK \ + (0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET) + +#define HPIPE_G2_SET_2_REG 0xf8 +#define HPIPE_G2_SET_2_G2_TX_EMPH0_OFFSET 0 +#define HPIPE_G2_SET_2_G2_TX_EMPH0_MASK \ + (0xf << HPIPE_G2_SET_2_G2_TX_EMPH0_OFFSET) +#define HPIPE_G2_SET_2_G2_TX_EMPH0_EN_OFFSET 4 +#define HPIPE_G2_SET_2_G2_TX_EMPH0_EN_MASK \ + (0x1 << HPIPE_G2_SET_2_G2_TX_EMPH0_EN_OFFSET) +#define HPIPE_G2_TX_SSC_AMP_OFFSET 9 +#define HPIPE_G2_TX_SSC_AMP_MASK \ + (0x7f << HPIPE_G2_TX_SSC_AMP_OFFSET) + +#define HPIPE_G3_SET_2_REG 0xfc +#define HPIPE_G3_SET_2_G3_TX_EMPH0_OFFSET 0 +#define HPIPE_G3_SET_2_G3_TX_EMPH0_MASK \ + (0xf << HPIPE_G3_SET_2_G3_TX_EMPH0_OFFSET) +#define HPIPE_G3_SET_2_G3_TX_EMPH0_EN_OFFSET 4 +#define HPIPE_G3_SET_2_G3_TX_EMPH0_EN_MASK \ + (0x1 << HPIPE_G3_SET_2_G3_TX_EMPH0_EN_OFFSET) +#define HPIPE_G3_TX_SSC_AMP_OFFSET 9 +#define HPIPE_G3_TX_SSC_AMP_MASK \ + (0x7f << HPIPE_G3_TX_SSC_AMP_OFFSET) + +#define HPIPE_VDD_CAL_0_REG 0x108 +#define HPIPE_CAL_VDD_CONT_MODE_OFFSET 15 +#define HPIPE_CAL_VDD_CONT_MODE_MASK \ + (0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET) + +#define HPIPE_VDD_CAL_CTRL_REG 0x114 +#define HPIPE_EXT_SELLV_RXSAMPL_OFFSET 5 +#define HPIPE_EXT_SELLV_RXSAMPL_MASK \ + (0x1f << HPIPE_EXT_SELLV_RXSAMPL_OFFSET) + +#define HPIPE_PCIE_REG0 0x120 +#define HPIPE_PCIE_IDLE_SYNC_OFFSET 12 +#define HPIPE_PCIE_IDLE_SYNC_MASK \ + (0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET) +#define HPIPE_PCIE_SEL_BITS_OFFSET 13 +#define HPIPE_PCIE_SEL_BITS_MASK \ + (0x3 << HPIPE_PCIE_SEL_BITS_OFFSET) + +#define HPIPE_LANE_ALIGN_REG 0x124 +#define HPIPE_LANE_ALIGN_OFF_OFFSET 12 +#define HPIPE_LANE_ALIGN_OFF_MASK \ + (0x1 << HPIPE_LANE_ALIGN_OFF_OFFSET) + +#define HPIPE_MISC_REG 0x13C +#define HPIPE_MISC_CLK100M_125M_OFFSET 4 +#define HPIPE_MISC_CLK100M_125M_MASK \ + (0x1 << HPIPE_MISC_CLK100M_125M_OFFSET) +#define HPIPE_MISC_ICP_FORCE_OFFSET 5 +#define HPIPE_MISC_ICP_FORCE_MASK \ + (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET) +#define HPIPE_MISC_TXDCLK_2X_OFFSET 6 +#define HPIPE_MISC_TXDCLK_2X_MASK \ + (0x1 << HPIPE_MISC_TXDCLK_2X_OFFSET) +#define HPIPE_MISC_CLK500_EN_OFFSET 7 +#define HPIPE_MISC_CLK500_EN_MASK \ + (0x1 << HPIPE_MISC_CLK500_EN_OFFSET) +#define HPIPE_MISC_REFCLK_SEL_OFFSET 10 +#define HPIPE_MISC_REFCLK_SEL_MASK \ + (0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET) + +#define HPIPE_RX_CONTROL_1_REG 0x140 +#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET 11 +#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK \ + (0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET) +#define HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET 12 +#define HPIPE_RX_CONTROL_1_CLK8T_EN_MASK \ + (0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET) + +#define HPIPE_PWR_CTR_REG 0x148 +#define HPIPE_PWR_CTR_RST_DFE_OFFSET 0 +#define HPIPE_PWR_CTR_RST_DFE_MASK \ + (0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET) +#define HPIPE_PWR_CTR_SFT_RST_OFFSET 10 +#define HPIPE_PWR_CTR_SFT_RST_MASK \ + (0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET) + +#define HPIPE_SPD_DIV_FORCE_REG 0x154 +#define HPIPE_TXDIGCK_DIV_FORCE_OFFSET 7 +#define HPIPE_TXDIGCK_DIV_FORCE_MASK \ + (0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET) +#define HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET 8 +#define HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK \ + (0x3 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET) +#define HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET 10 +#define HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK \ + (0x1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET) +#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET 13 +#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK \ + (0x3 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET) +#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET 15 +#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK \ + (0x1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET) + +/* HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIBRATION_CTRL_REG */ +#define HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG 0x168 +#define HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET 15 +#define HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK \ + (0x1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET) +#define HPIPE_CAL_OS_PH_EXT_OFFSET 8 +#define HPIPE_CAL_OS_PH_EXT_MASK \ + (0x7f << HPIPE_CAL_OS_PH_EXT_OFFSET) + +#define HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG 0x16C +#define HPIPE_RX_SAMPLER_OS_GAIN_OFFSET 6 +#define HPIPE_RX_SAMPLER_OS_GAIN_MASK \ + (0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET) +#define HPIPE_SMAPLER_OFFSET 12 +#define HPIPE_SMAPLER_MASK \ + (0x1 << HPIPE_SMAPLER_OFFSET) + +#define HPIPE_TX_REG1_REG 0x174 +#define HPIPE_TX_REG1_TX_EMPH_RES_OFFSET 5 +#define HPIPE_TX_REG1_TX_EMPH_RES_MASK \ + (0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET) +#define HPIPE_TX_REG1_SLC_EN_OFFSET 10 +#define HPIPE_TX_REG1_SLC_EN_MASK \ + (0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET) + +#define HPIPE_PWR_CTR_DTL_REG 0x184 +#define HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET 0 +#define HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET) +#define HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET 1 +#define HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET) +#define HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET 2 +#define HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET) +#define HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET 4 +#define HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK \ + (0x7 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET) +#define HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET 10 +#define HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET) +#define HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET 12 +#define HPIPE_PWR_CTR_DTL_CLK_MODE_MASK \ + (0x3 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET) +#define HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET 14 +#define HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK \ + (1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET) + +#define HPIPE_PHASE_CONTROL_REG 0x188 +#define HPIPE_OS_PH_OFFSET_OFFSET 0 +#define HPIPE_OS_PH_OFFSET_MASK \ + (0x7f << HPIPE_OS_PH_OFFSET_OFFSET) +#define HPIPE_OS_PH_OFFSET_FORCE_OFFSET 7 +#define HPIPE_OS_PH_OFFSET_FORCE_MASK \ + (0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET) +#define HPIPE_OS_PH_VALID_OFFSET 8 +#define HPIPE_OS_PH_VALID_MASK \ + (0x1 << HPIPE_OS_PH_VALID_OFFSET) + +#define HPIPE_DATA_PHASE_OFF_CTRL_REG 0x1A0 +#define HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET 9 +#define HPIPE_DATA_PHASE_ADAPTED_OS_PH_MASK \ + (0x7f << HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET) + +#define HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG 0x1A4 +#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET 12 +#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_MASK \ + (0x3 << HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET) +#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET 8 +#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_MASK \ + (0xf << HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET) + +#define HPIPE_SQ_GLITCH_FILTER_CTRL 0x1c8 +#define HPIPE_SQ_DEGLITCH_WIDTH_P_OFFSET 0 +#define HPIPE_SQ_DEGLITCH_WIDTH_P_MASK \ + (0xf << HPIPE_SQ_DEGLITCH_WIDTH_P_OFFSET) +#define HPIPE_SQ_DEGLITCH_WIDTH_N_OFFSET 4 +#define HPIPE_SQ_DEGLITCH_WIDTH_N_MASK \ + (0xf << HPIPE_SQ_DEGLITCH_WIDTH_N_OFFSET) +#define HPIPE_SQ_DEGLITCH_EN_OFFSET 8 +#define HPIPE_SQ_DEGLITCH_EN_MASK \ + (0x1 << HPIPE_SQ_DEGLITCH_EN_OFFSET) + +#define HPIPE_FRAME_DETECT_CTRL_0_REG 0x214 +#define HPIPE_TRAIN_PAT_NUM_OFFSET 0x7 +#define HPIPE_TRAIN_PAT_NUM_MASK \ + (0x1FF << HPIPE_TRAIN_PAT_NUM_OFFSET) + +#define HPIPE_FRAME_DETECT_CTRL_3_REG 0x220 +#define HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET 12 +#define HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK \ + (0x1 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET) + +#define HPIPE_DME_REG 0x228 +#define HPIPE_DME_ETHERNET_MODE_OFFSET 7 +#define HPIPE_DME_ETHERNET_MODE_MASK \ + (0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET) + +#define HPIPE_TRX_TRAIN_CTRL_0_REG 0x22c +#define HPIPE_TRX_TX_F0T_EO_BASED_OFFSET 14 +#define HPIPE_TRX_TX_F0T_EO_BASED_MASK \ + (1 << HPIPE_TRX_TX_F0T_EO_BASED_OFFSET) +#define HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET 6 +#define HPIPE_TRX_UPDATE_THEN_HOLD_MASK \ + (1 << HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET) +#define HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET 5 +#define HPIPE_TRX_TX_CTRL_CLK_EN_MASK \ + (1 << HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET) +#define HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET 4 +#define HPIPE_TRX_RX_ANA_IF_CLK_ENE_MASK \ + (1 << HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET) +#define HPIPE_TRX_TX_TRAIN_EN_OFFSET 1 +#define HPIPE_TRX_TX_TRAIN_EN_MASK \ + (1 << HPIPE_TRX_TX_TRAIN_EN_OFFSET) +#define HPIPE_TRX_RX_TRAIN_EN_OFFSET 0 +#define HPIPE_TRX_RX_TRAIN_EN_MASK \ + (1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_0_REG 0x268 +#define HPIPE_TX_TRAIN_P2P_HOLD_OFFSET 15 +#define HPIPE_TX_TRAIN_P2P_HOLD_MASK \ + (0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_REG 0x26C +#define HPIPE_TX_TRAIN_CTRL_G1_OFFSET 0 +#define HPIPE_TX_TRAIN_CTRL_G1_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET) +#define HPIPE_TX_TRAIN_CTRL_GN1_OFFSET 1 +#define HPIPE_TX_TRAIN_CTRL_GN1_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET) +#define HPIPE_TX_TRAIN_CTRL_G0_OFFSET 2 +#define HPIPE_TX_TRAIN_CTRL_G0_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_4_REG 0x278 +#define HPIPE_TRX_TRAIN_TIMER_OFFSET 0 +#define HPIPE_TRX_TRAIN_TIMER_MASK \ + (0x3FF << HPIPE_TRX_TRAIN_TIMER_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_5_REG 0x2A4 +#define HPIPE_RX_TRAIN_TIMER_OFFSET 0 +#define HPIPE_RX_TRAIN_TIMER_MASK \ + (0x3ff << HPIPE_RX_TRAIN_TIMER_OFFSET) +#define HPIPE_TX_TRAIN_START_SQ_EN_OFFSET 11 +#define HPIPE_TX_TRAIN_START_SQ_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET) +#define HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET 12 +#define HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET) +#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET 13 +#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET) +#define HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET 14 +#define HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET) + +#define HPIPE_INTERRUPT_1_REGISTER 0x2AC +#define HPIPE_TRX_TRAIN_FAILED_OFFSET 6 +#define HPIPE_TRX_TRAIN_FAILED_MASK \ + (1 << HPIPE_TRX_TRAIN_FAILED_OFFSET) +#define HPIPE_TRX_TRAIN_TIME_OUT_INT_OFFSET 5 +#define HPIPE_TRX_TRAIN_TIME_OUT_INT_MASK \ + (1 << HPIPE_TRX_TRAIN_TIME_OUT_INT_OFFSET) +#define HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET 4 +#define HPIPE_INTERRUPT_TRX_TRAIN_DONE_MASK \ + (1 << HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET) +#define HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET 3 +#define HPIPE_INTERRUPT_DFE_DONE_INT_MASK \ + (1 << HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET) +#define HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_OFFSET 1 +#define HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_MASK \ + (1 << HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_OFFSET) + +#define HPIPE_TX_TRAIN_REG 0x31C +#define HPIPE_TX_TRAIN_CHK_INIT_OFFSET 4 +#define HPIPE_TX_TRAIN_CHK_INIT_MASK \ + (0x1 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET) +#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET 7 +#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK \ + (0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET) +#define HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET 8 +#define HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET) +#define HPIPE_TX_TRAIN_PAT_SEL_OFFSET 9 +#define HPIPE_TX_TRAIN_PAT_SEL_MASK \ + (0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET) + +#define HPIPE_SAVED_DFE_VALUES_REG 0x328 +#define HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET 10 +#define HPIPE_SAVED_DFE_VALUES_SAV_F0D_MASK \ + (0x3f << HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET) + +#define HPIPE_CDR_CONTROL_REG 0x418 +#define HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET 0 +#define HPIPE_CRD_MIDPOINT_PHASE_OS_MASK \ + (0x3f << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET) +#define HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET 6 +#define HPIPE_CDR_MAX_DFE_ADAPT_1_MASK \ + (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET) +#define HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET 9 +#define HPIPE_CDR_MAX_DFE_ADAPT_0_MASK \ + (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET) +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET 12 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK \ + (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET) +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET 14 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK \ + (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET) + + +#define HPIPE_CDR_CONTROL1_REG 0x41c +#define HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF 12 +#define HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK \ + (0xf << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF) + +#define HPIPE_CDR_CONTROL2_REG 0x420 +#define HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF 12 +#define HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK \ + (0xf << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF) + +#define HPIPE_TX_TRAIN_CTRL_11_REG 0x438 +#define HPIPE_TX_STATUS_CHECK_MODE_OFFSET 6 +#define HPIPE_TX_TX_STATUS_CHECK_MODE_MASK \ + (0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET) +#define HPIPE_TX_NUM_OF_PRESET_OFFSET 10 +#define HPIPE_TX_NUM_OF_PRESET_MASK \ + (0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET) +#define HPIPE_TX_SWEEP_PRESET_EN_OFFSET 15 +#define HPIPE_TX_SWEEP_PRESET_EN_MASK \ + (0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET) + +#define HPIPE_G1_SETTINGS_3_REG 0x440 +#define HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET 0 +#define HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK \ + (0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET 4 +#define HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK \ + (0x7 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET 7 +#define HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK \ + (0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET 9 +#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK \ + (0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET 12 +#define HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK \ + (0x3 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET 14 +#define HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK \ + (0x3 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET) + +#define HPIPE_G1_SETTINGS_4_REG 0x444 +#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET 8 +#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK \ + (0x3 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET) + +#define HPIPE_G2_SETTINGS_4_REG 0x44c +#define HPIPE_G2_DFE_RES_OFFSET 8 +#define HPIPE_G2_DFE_RES_MASK \ + (0x3 << HPIPE_G2_DFE_RES_OFFSET) + +#define HPIPE_G3_SETTING_3_REG 0x450 +#define HPIPE_G3_FFE_CAP_SEL_OFFSET 0 +#define HPIPE_G3_FFE_CAP_SEL_MASK \ + (0xf << HPIPE_G3_FFE_CAP_SEL_OFFSET) +#define HPIPE_G3_FFE_RES_SEL_OFFSET 4 +#define HPIPE_G3_FFE_RES_SEL_MASK \ + (0x7 << HPIPE_G3_FFE_RES_SEL_OFFSET) +#define HPIPE_G3_FFE_SETTING_FORCE_OFFSET 7 +#define HPIPE_G3_FFE_SETTING_FORCE_MASK \ + (0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET) +#define HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET 12 +#define HPIPE_G3_FFE_DEG_RES_LEVEL_MASK \ + (0x3 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET) +#define HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET 14 +#define HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK \ + (0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET) + +#define HPIPE_G3_SETTING_4_REG 0x454 +#define HPIPE_G3_DFE_RES_OFFSET 8 +#define HPIPE_G3_DFE_RES_MASK (0x3 << HPIPE_G3_DFE_RES_OFFSET) + +#define HPIPE_TX_PRESET_INDEX_REG 0x468 +#define HPIPE_TX_PRESET_INDEX_OFFSET 0 +#define HPIPE_TX_PRESET_INDEX_MASK \ + (0xf << HPIPE_TX_PRESET_INDEX_OFFSET) + +#define HPIPE_DFE_CONTROL_REG 0x470 +#define HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET 14 +#define HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK \ + (0x3 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET) + +#define HPIPE_DFE_CTRL_28_REG 0x49C +#define HPIPE_DFE_CTRL_28_PIPE4_OFFSET 7 +#define HPIPE_DFE_CTRL_28_PIPE4_MASK \ + (0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET) + +#define HPIPE_TRX0_REG 0x4cc /*in doc 0x133*4*/ +#define HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF 2 +#define HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK \ + (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF) +#define HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF 0 +#define HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK \ + (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF) + +#define HPIPE_TRX_REG1 0x4d0 /*in doc 0x134*4*/ +#define HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF 3 +#define HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK \ + (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF) +#define HPIPE_TRX_REG1_SUMFTAP_EN_OFF 10 +#define HPIPE_TRX_REG1_SUMFTAP_EN_MASK \ + (0x3f << HPIPE_TRX_REG1_SUMFTAP_EN_OFF) + +#define HPIPE_TRX_REG2 0x4d8 /*in doc 0x136*4*/ +#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF 11 +#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK \ + (0x1f << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF) +#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF 7 +#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK \ + (0xf << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF) + +#define HPIPE_G1_SETTING_5_REG 0x538 +#define HPIPE_G1_SETTING_5_G1_ICP_OFFSET 0 +#define HPIPE_G1_SETTING_5_G1_ICP_MASK \ + (0xf << HPIPE_G1_SETTING_5_G1_ICP_OFFSET) + +#define HPIPE_G3_SETTING_5_REG 0x548 +#define HPIPE_G3_SETTING_5_G3_ICP_OFFSET 0 +#define HPIPE_G3_SETTING_5_G3_ICP_MASK \ + (0xf << HPIPE_G3_SETTING_5_G3_ICP_OFFSET) + +#define HPIPE_LANE_CONFIG0_REG 0x600 +#define HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET 0 +#define HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK \ + (0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET) + +#define HPIPE_LANE_STATUS1_REG 0x60C +#define HPIPE_LANE_STATUS1_PCLK_EN_OFFSET 0 +#define HPIPE_LANE_STATUS1_PCLK_EN_MASK \ + (0x1 << HPIPE_LANE_STATUS1_PCLK_EN_OFFSET) + +#define HPIPE_LANE_CFG4_REG 0x620 +#define HPIPE_LANE_CFG4_DFE_CTRL_OFFSET 0 +#define HPIPE_LANE_CFG4_DFE_CTRL_MASK \ + (0x7 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET) +#define HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET 3 +#define HPIPE_LANE_CFG4_DFE_EN_SEL_MASK \ + (0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET) +#define HPIPE_LANE_CFG4_DFE_OVER_OFFSET 6 +#define HPIPE_LANE_CFG4_DFE_OVER_MASK \ + (0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET) +#define HPIPE_LANE_CFG4_SSC_CTRL_OFFSET 7 +#define HPIPE_LANE_CFG4_SSC_CTRL_MASK \ + (0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET) + +#define HPIPE_LANE_EQ_REMOTE_SETTING_REG 0x6f8 +#define HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET 0 +#define HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK \ + (0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET) +#define HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET 1 +#define HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK \ + (0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET) +#define HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET 2 +#define HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK \ + (0xf << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET) + +#define HPIPE_LANE_EQU_CONFIG_0_REG 0x69C +#define HPIPE_CFG_PHY_RC_EP_OFFSET 12 +#define HPIPE_CFG_PHY_RC_EP_MASK \ + (0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET) + +#define HPIPE_LANE_EQ_CFG1_REG 0x6a0 +#define HPIPE_CFG_UPDATE_POLARITY_OFFSET 12 +#define HPIPE_CFG_UPDATE_POLARITY_MASK \ + (0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET) + +#define HPIPE_LANE_EQ_CFG2_REG 0x6a4 +#define HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET 14 +#define HPIPE_CFG_EQ_BUNDLE_DIS_MASK \ + (0x1 << HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET) + +#define HPIPE_RST_CLK_CTRL_REG 0x704 +#define HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET 0 +#define HPIPE_RST_CLK_CTRL_PIPE_RST_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET) +#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET 2 +#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET) +#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET 3 +#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET) +#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET 9 +#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET) + +#define HPIPE_TST_MODE_CTRL_REG 0x708 +#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET 2 +#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK \ + (0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET) + +#define HPIPE_CLK_SRC_LO_REG 0x70c +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET 1 +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK \ + (0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET) +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET 2 +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK \ + (0x3 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET) +#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET 5 +#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK \ + (0x7 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET) + +#define HPIPE_CLK_SRC_HI_REG 0x710 +#define HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET 0 +#define HPIPE_CLK_SRC_HI_LANE_STRT_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET) +#define HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET 1 +#define HPIPE_CLK_SRC_HI_LANE_BREAK_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET) +#define HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET 2 +#define HPIPE_CLK_SRC_HI_LANE_MASTER_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET) +#define HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET 7 +#define HPIPE_CLK_SRC_HI_MODE_PIPE_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET) + +#define HPIPE_GLOBAL_MISC_CTRL 0x718 +#define HPIPE_GLOBAL_PM_CTRL 0x740 +#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET 0 +#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK \ + (0xFF << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET) + +/* General defines */ +#define PLL_LOCK_TIMEOUT 15000 + +#endif /* COMPHY_CP110_H */ diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c new file mode 100644 index 0000000..1a97753 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c @@ -0,0 +1,1065 @@ +/* + * Copyright (C) 2018-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "phy-comphy-3700.h" +#include "phy-comphy-common.h" + +/* + * COMPHY_INDIRECT_REG points to ahci address space but the ahci region used in + * Linux is up to 0x178 so none will access it from Linux in runtime + * concurrently. + */ +#define COMPHY_INDIRECT_REG (MVEBU_REGS_BASE + 0xE0178) + +/* The USB3_GBE1_PHY range is above USB3 registers used in dts */ +#define USB3_GBE1_PHY (MVEBU_REGS_BASE + 0x5C000) +#define COMPHY_SD_ADDR (MVEBU_REGS_BASE + 0x1F000) + +struct sgmii_phy_init_data_fix { + uint16_t addr; + uint16_t value; +}; + +/* Changes to 40M1G25 mode data required for running 40M3G125 init mode */ +static struct sgmii_phy_init_data_fix sgmii_phy_init_fix[] = { + {0x005, 0x07CC}, {0x015, 0x0000}, {0x01B, 0x0000}, {0x01D, 0x0000}, + {0x01E, 0x0000}, {0x01F, 0x0000}, {0x020, 0x0000}, {0x021, 0x0030}, + {0x026, 0x0888}, {0x04D, 0x0152}, {0x04F, 0xA020}, {0x050, 0x07CC}, + {0x053, 0xE9CA}, {0x055, 0xBD97}, {0x071, 0x3015}, {0x076, 0x03AA}, + {0x07C, 0x0FDF}, {0x0C2, 0x3030}, {0x0C3, 0x8000}, {0x0E2, 0x5550}, + {0x0E3, 0x12A4}, {0x0E4, 0x7D00}, {0x0E6, 0x0C83}, {0x101, 0xFCC0}, + {0x104, 0x0C10} +}; + +/* 40M1G25 mode init data */ +static uint16_t sgmii_phy_init[512] = { + /* 0 1 2 3 4 5 6 7 */ + /*-----------------------------------------------------------*/ + /* 8 9 A B C D E F */ + 0x3110, 0xFD83, 0x6430, 0x412F, 0x82C0, 0x06FA, 0x4500, 0x6D26, /* 00 */ + 0xAFC0, 0x8000, 0xC000, 0x0000, 0x2000, 0x49CC, 0x0BC9, 0x2A52, /* 08 */ + 0x0BD2, 0x0CDE, 0x13D2, 0x0CE8, 0x1149, 0x10E0, 0x0000, 0x0000, /* 10 */ + 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x4134, 0x0D2D, 0xFFFF, /* 18 */ + 0xFFE0, 0x4030, 0x1016, 0x0030, 0x0000, 0x0800, 0x0866, 0x0000, /* 20 */ + 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* 28 */ + 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ + 0x0000, 0x0000, 0x000F, 0x6A62, 0x1988, 0x3100, 0x3100, 0x3100, /* 38 */ + 0x3100, 0xA708, 0x2430, 0x0830, 0x1030, 0x4610, 0xFF00, 0xFF00, /* 40 */ + 0x0060, 0x1000, 0x0400, 0x0040, 0x00F0, 0x0155, 0x1100, 0xA02A, /* 48 */ + 0x06FA, 0x0080, 0xB008, 0xE3ED, 0x5002, 0xB592, 0x7A80, 0x0001, /* 50 */ + 0x020A, 0x8820, 0x6014, 0x8054, 0xACAA, 0xFC88, 0x2A02, 0x45CF, /* 58 */ + 0x000F, 0x1817, 0x2860, 0x064F, 0x0000, 0x0204, 0x1800, 0x6000, /* 60 */ + 0x810F, 0x4F23, 0x4000, 0x4498, 0x0850, 0x0000, 0x000E, 0x1002, /* 68 */ + 0x9D3A, 0x3009, 0xD066, 0x0491, 0x0001, 0x6AB0, 0x0399, 0x3780, /* 70 */ + 0x0040, 0x5AC0, 0x4A80, 0x0000, 0x01DF, 0x0000, 0x0007, 0x0000, /* 78 */ + 0x2D54, 0x00A1, 0x4000, 0x0100, 0xA20A, 0x0000, 0x0000, 0x0000, /* 80 */ + 0x0000, 0x0000, 0x0000, 0x7400, 0x0E81, 0x1000, 0x1242, 0x0210, /* 88 */ + 0x80DF, 0x0F1F, 0x2F3F, 0x4F5F, 0x6F7F, 0x0F1F, 0x2F3F, 0x4F5F, /* 90 */ + 0x6F7F, 0x4BAD, 0x0000, 0x0000, 0x0800, 0x0000, 0x2400, 0xB651, /* 98 */ + 0xC9E0, 0x4247, 0x0A24, 0x0000, 0xAF19, 0x1004, 0x0000, 0x0000, /* A0 */ + 0x0000, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* A8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* B0 */ + 0x0000, 0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000, /* B8 */ + 0x0000, 0x0000, 0x3010, 0xFA00, 0x0000, 0x0000, 0x0000, 0x0003, /* C0 */ + 0x1618, 0x8200, 0x8000, 0x0400, 0x050F, 0x0000, 0x0000, 0x0000, /* C8 */ + 0x4C93, 0x0000, 0x1000, 0x1120, 0x0010, 0x1242, 0x1242, 0x1E00, /* D0 */ + 0x0000, 0x0000, 0x0000, 0x00F8, 0x0000, 0x0041, 0x0800, 0x0000, /* D8 */ + 0x82A0, 0x572E, 0x2490, 0x14A9, 0x4E00, 0x0000, 0x0803, 0x0541, /* E0 */ + 0x0C15, 0x0000, 0x0000, 0x0400, 0x2626, 0x0000, 0x0000, 0x4200, /* E8 */ + 0x0000, 0xAA55, 0x1020, 0x0000, 0x0000, 0x5010, 0x0000, 0x0000, /* F0 */ + 0x0000, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, 0x02F2, 0x0000, /* F8 */ + 0x101F, 0xFDC0, 0x4000, 0x8010, 0x0110, 0x0006, 0x0000, 0x0000, /*100 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*108 */ + 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04C6, 0x0000, /*110 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*118 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*120 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*128 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*130 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*138 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*140 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*148 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*150 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*158 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*160 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*168 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*170 */ + 0x0000, 0x0000, 0x0000, 0x00F0, 0x08A2, 0x3112, 0x0A14, 0x0000, /*178 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*180 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*188 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*190 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*198 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1F0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /*1F8 */ +}; + +/* PHY selector configures with corresponding modes */ +static int mvebu_a3700_comphy_set_phy_selector(uint8_t comphy_index, + uint32_t comphy_mode) +{ + uint32_t reg; + int mode = COMPHY_GET_MODE(comphy_mode); + + reg = mmio_read_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG); + switch (mode) { + case (COMPHY_SATA_MODE): + /* SATA must be in Lane2 */ + if (comphy_index == COMPHY_LANE2) + reg &= ~COMPHY_SELECTOR_USB3_PHY_SEL_BIT; + else + goto error; + break; + + case (COMPHY_SGMII_MODE): + case (COMPHY_2500BASEX_MODE): + if (comphy_index == COMPHY_LANE0) + reg &= ~COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; + else if (comphy_index == COMPHY_LANE1) + reg &= ~COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; + else + goto error; + break; + + case (COMPHY_USB3H_MODE): + case (COMPHY_USB3D_MODE): + case (COMPHY_USB3_MODE): + if (comphy_index == COMPHY_LANE2) + reg |= COMPHY_SELECTOR_USB3_PHY_SEL_BIT; + else if (comphy_index == COMPHY_LANE0) + reg |= COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; + else + goto error; + break; + + case (COMPHY_PCIE_MODE): + /* PCIE must be in Lane1 */ + if (comphy_index == COMPHY_LANE1) + reg |= COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; + else + goto error; + break; + + default: + goto error; + } + + mmio_write_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG, reg); + return 0; +error: + ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode); + return -EINVAL; +} + +/* + * This is something like the inverse of the previous function: for given + * lane it returns COMPHY_*_MODE. + * + * It is useful when powering the phy off. + * + * This function returns COMPHY_USB3_MODE even if the phy was configured + * with COMPHY_USB3D_MODE or COMPHY_USB3H_MODE. (The usb3 phy initialization + * code does not differentiate between these modes.) + * Also it returns COMPHY_SGMII_MODE even if the phy was configures with + * COMPHY_2500BASEX_MODE. (The sgmii phy initialization code does differentiate + * between these modes, but it is irrelevant when powering the phy off.) + */ +static int mvebu_a3700_comphy_get_mode(uint8_t comphy_index) +{ + uint32_t reg; + + reg = mmio_read_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG); + switch (comphy_index) { + case COMPHY_LANE0: + if ((reg & COMPHY_SELECTOR_USB3_GBE1_SEL_BIT) != 0) + return COMPHY_USB3_MODE; + else + return COMPHY_SGMII_MODE; + case COMPHY_LANE1: + if ((reg & COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT) != 0) + return COMPHY_PCIE_MODE; + else + return COMPHY_SGMII_MODE; + case COMPHY_LANE2: + if ((reg & COMPHY_SELECTOR_USB3_PHY_SEL_BIT) != 0) + return COMPHY_USB3_MODE; + else + return COMPHY_SATA_MODE; + } + + return COMPHY_UNUSED; +} + +/* It is only used for SATA and USB3 on comphy lane2. */ +static void comphy_set_indirect(uintptr_t addr, uint32_t offset, uint16_t data, + uint16_t mask, bool is_sata) +{ + /* + * When Lane 2 PHY is for USB3, access the PHY registers + * through indirect Address and Data registers: + * INDIR_ACC_PHY_ADDR (RD00E0178h [31:0]), + * INDIR_ACC_PHY_DATA (RD00E017Ch [31:0]), + * within the SATA Host Controller registers, Lane 2 base register + * offset is 0x200 + */ + if (is_sata) { + mmio_write_32(addr + COMPHY_LANE2_INDIR_ADDR_OFFSET, offset); + } else { + mmio_write_32(addr + COMPHY_LANE2_INDIR_ADDR_OFFSET, + offset + USB3PHY_LANE2_REG_BASE_OFFSET); + } + + reg_set(addr + COMPHY_LANE2_INDIR_DATA_OFFSET, data, mask); +} + +/* It is only used for SATA on comphy lane2. */ +static void comphy_sata_set_indirect(uintptr_t addr, uint32_t reg_offset, + uint16_t data, uint16_t mask) +{ + comphy_set_indirect(addr, reg_offset, data, mask, true); +} + +/* It is only used for USB3 indirect access on comphy lane2. */ +static void comphy_usb3_set_indirect(uintptr_t addr, uint32_t reg_offset, + uint16_t data, uint16_t mask) +{ + comphy_set_indirect(addr, reg_offset, data, mask, false); +} + +/* It is only used for USB3 direct access not on comphy lane2. */ +static void comphy_usb3_set_direct(uintptr_t addr, uint32_t reg_offset, + uint16_t data, uint16_t mask) +{ + reg_set16((reg_offset * PHY_SHFT(USB3) + addr), data, mask); +} + +static void comphy_sgmii_phy_init(uintptr_t sd_ip_addr, bool is_1gbps) +{ + const int fix_arr_sz = ARRAY_SIZE(sgmii_phy_init_fix); + int addr, fix_idx; + uint16_t val; + + fix_idx = 0; + for (addr = 0; addr < 512; addr++) { + /* + * All PHY register values are defined in full for 3.125Gbps + * SERDES speed. The values required for 1.25 Gbps are almost + * the same and only few registers should be "fixed" in + * comparison to 3.125 Gbps values. These register values are + * stored in "sgmii_phy_init_fix" array. + */ + if (!is_1gbps && sgmii_phy_init_fix[fix_idx].addr == addr) { + /* Use new value */ + val = sgmii_phy_init_fix[fix_idx].value; + if (fix_idx < fix_arr_sz) + fix_idx++; + } else { + val = sgmii_phy_init[addr]; + } + + reg_set16(SGMIIPHY_ADDR(addr, sd_ip_addr), val, 0xFFFF); + } +} + +static int mvebu_a3700_comphy_sata_power_on(uint8_t comphy_index, + uint32_t comphy_mode) +{ + int ret; + uint32_t offset, data = 0, ref_clk; + uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG; + int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); + + debug_enter(); + + /* Configure phy selector for SATA */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + + /* Clear phy isolation mode to make it work in normal mode */ + offset = COMPHY_ISOLATION_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, 0, PHY_ISOLATE_MODE); + + /* 0. Check the Polarity invert bits */ + if (invert & COMPHY_POLARITY_TXD_INVERT) + data |= TXD_INVERT_BIT; + if (invert & COMPHY_POLARITY_RXD_INVERT) + data |= RXD_INVERT_BIT; + + offset = COMPHY_SYNC_PATTERN + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, data, TXD_INVERT_BIT | + RXD_INVERT_BIT); + + /* 1. Select 40-bit data width width */ + offset = COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, DATA_WIDTH_40BIT, + SEL_DATA_WIDTH_MASK); + + /* 2. Select reference clock(25M) and PHY mode (SATA) */ + offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + if (get_ref_clk() == 40) + ref_clk = REF_FREF_SEL_SERDES_40MHZ; + else + ref_clk = REF_FREF_SEL_SERDES_25MHZ; + + comphy_sata_set_indirect(comphy_indir_regs, offset, ref_clk | PHY_MODE_SATA, + REF_FREF_SEL_MASK | PHY_MODE_MASK); + + /* 3. Use maximum PLL rate (no power save) */ + offset = COMPHY_KVCO_CAL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, USE_MAX_PLL_RATE_BIT, + USE_MAX_PLL_RATE_BIT); + + /* 4. Reset reserved bit */ + comphy_sata_set_indirect(comphy_indir_regs, COMPHY_RESERVED_REG, 0, + PHYCTRL_FRM_PIN_BIT); + + /* 5. Set vendor-specific configuration (It is done in sata driver) */ + /* XXX: in U-Boot below sequence was executed in this place, in Linux + * not. Now it is done only in U-Boot before this comphy + * initialization - tests shows that it works ok, but in case of any + * future problem it is left for reference. + * reg_set(MVEBU_REGS_BASE + 0xe00a0, 0, 0xffffffff); + * reg_set(MVEBU_REGS_BASE + 0xe00a4, BIT(6), BIT(6)); + */ + + /* Wait for > 55 us to allow PLL be enabled */ + udelay(PLL_SET_DELAY_US); + + /* Polling status */ + mmio_write_32(comphy_indir_regs + COMPHY_LANE2_INDIR_ADDR_OFFSET, + COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET); + + ret = polling_with_timeout(comphy_indir_regs + + COMPHY_LANE2_INDIR_DATA_OFFSET, + PLL_READY_TX_BIT, PLL_READY_TX_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + return -ETIMEDOUT; + } + + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, + uint32_t comphy_mode) +{ + int ret; + uint32_t mask, data; + uintptr_t offset; + uintptr_t sd_ip_addr; + int mode = COMPHY_GET_MODE(comphy_mode); + int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); + + debug_enter(); + + /* Set selector */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + + /* Serdes IP Base address + * COMPHY Lane0 -- USB3/GBE1 + * COMPHY Lane1 -- PCIe/GBE0 + */ + if (comphy_index == COMPHY_LANE0) { + /* Get usb3 and gbe */ + sd_ip_addr = USB3_GBE1_PHY; + } else + sd_ip_addr = COMPHY_SD_ADDR; + + /* + * 1. Reset PHY by setting PHY input port PIN_RESET=1. + * 2. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep + * PHY TXP/TXN output to idle state during PHY initialization + * 3. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0. + */ + data = PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT | PIN_RESET_COMPHY_BIT; + mask = data | PIN_RESET_CORE_BIT | PIN_PU_PLL_BIT | PIN_PU_RX_BIT | + PIN_PU_TX_BIT; + offset = MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index); + reg_set(offset, data, mask); + + /* 4. Release reset to the PHY by setting PIN_RESET=0. */ + data = 0; + mask = PIN_RESET_COMPHY_BIT; + reg_set(offset, data, mask); + + /* + * 5. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide COMPHY + * bit rate + */ + if (mode == COMPHY_SGMII_MODE) { + /* SGMII 1G, SerDes speed 1.25G */ + data |= SD_SPEED_1_25_G << GEN_RX_SEL_OFFSET; + data |= SD_SPEED_1_25_G << GEN_TX_SEL_OFFSET; + } else if (mode == COMPHY_2500BASEX_MODE) { + /* 2500Base-X, SerDes speed 3.125G */ + data |= SD_SPEED_3_125_G << GEN_RX_SEL_OFFSET; + data |= SD_SPEED_3_125_G << GEN_TX_SEL_OFFSET; + } else { + /* Other rates are not supported */ + ERROR("unsupported SGMII speed on comphy lane%d\n", + comphy_index); + return -EINVAL; + } + mask = GEN_RX_SEL_MASK | GEN_TX_SEL_MASK; + reg_set(offset, data, mask); + + /* + * 6. Wait 10mS for bandgap and reference clocks to stabilize; then + * start SW programming. + */ + mdelay(10); + + /* 7. Program COMPHY register PHY_MODE */ + data = PHY_MODE_SGMII; + mask = PHY_MODE_MASK; + reg_set16(SGMIIPHY_ADDR(COMPHY_POWER_PLL_CTRL, sd_ip_addr), data, mask); + + /* + * 8. Set COMPHY register REFCLK_SEL to select the correct REFCLK + * source + */ + data = 0; + mask = PHY_REF_CLK_SEL; + reg_set16(SGMIIPHY_ADDR(COMPHY_MISC_CTRL0, sd_ip_addr), data, mask); + + /* + * 9. Set correct reference clock frequency in COMPHY register + * REF_FREF_SEL. + */ + if (get_ref_clk() == 40) + data = REF_FREF_SEL_SERDES_50MHZ; + else + data = REF_FREF_SEL_SERDES_25MHZ; + + mask = REF_FREF_SEL_MASK; + reg_set16(SGMIIPHY_ADDR(COMPHY_POWER_PLL_CTRL, sd_ip_addr), data, mask); + + /* 10. Program COMPHY register PHY_GEN_MAX[1:0] + * This step is mentioned in the flow received from verification team. + * However the PHY_GEN_MAX value is only meaningful for other interfaces + * (not SGMII). For instance, it selects SATA speed 1.5/3/6 Gbps or PCIe + * speed 2.5/5 Gbps + */ + + /* + * 11. Program COMPHY register SEL_BITS to set correct parallel data + * bus width + */ + data = DATA_WIDTH_10BIT; + mask = SEL_DATA_WIDTH_MASK; + reg_set16(SGMIIPHY_ADDR(COMPHY_DIG_LOOPBACK_EN, sd_ip_addr), + data, mask); + + /* + * 12. As long as DFE function needs to be enabled in any mode, + * COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F + * for real chip during COMPHY power on. + * The step 14 exists (and empty) in the original initialization flow + * obtained from the verification team. According to the functional + * specification DFE_UPDATE_EN already has the default value 0x3F + */ + + /* + * 13. Program COMPHY GEN registers. + * These registers should be programmed based on the lab testing result + * to achieve optimal performance. Please contact the CEA group to get + * the related GEN table during real chip bring-up. We only required to + * run though the entire registers programming flow defined by + * "comphy_sgmii_phy_init" when the REF clock is 40 MHz. For REF clock + * 25 MHz the default values stored in PHY registers are OK. + */ + debug("Running C-DPI phy init %s mode\n", + mode == COMPHY_2500BASEX_MODE ? "2G5" : "1G"); + if (get_ref_clk() == 40) + comphy_sgmii_phy_init(sd_ip_addr, mode != COMPHY_2500BASEX_MODE); + + /* + * 14. [Simulation Only] should not be used for real chip. + * By pass power up calibration by programming EXT_FORCE_CAL_DONE + * (R02h[9]) to 1 to shorten COMPHY simulation time. + */ + + /* + * 15. [Simulation Only: should not be used for real chip] + * Program COMPHY register FAST_DFE_TIMER_EN=1 to shorten RX training + * simulation time. + */ + + /* + * 16. Check the PHY Polarity invert bit + */ + data = 0x0; + if (invert & COMPHY_POLARITY_TXD_INVERT) + data |= TXD_INVERT_BIT; + if (invert & COMPHY_POLARITY_RXD_INVERT) + data |= RXD_INVERT_BIT; + mask = TXD_INVERT_BIT | RXD_INVERT_BIT; + reg_set16(SGMIIPHY_ADDR(COMPHY_SYNC_PATTERN, sd_ip_addr), data, mask); + + /* + * 17. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 to + * start PHY power up sequence. All the PHY register programming should + * be done before PIN_PU_PLL=1. There should be no register programming + * for normal PHY operation from this point. + */ + reg_set(MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index), + PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT, + PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT); + + /* + * 18. Wait for PHY power up sequence to finish by checking output ports + * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1. + */ + ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE + + COMPHY_PHY_STATUS_OFFSET(comphy_index), + PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, + PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + ERROR("Failed to lock PLL for SGMII PHY %d\n", comphy_index); + return -ETIMEDOUT; + } + + /* + * 19. Set COMPHY input port PIN_TX_IDLE=0 + */ + reg_set(MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index), + 0x0, PIN_TX_IDLE_BIT); + + /* + * 20. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1. To + * start RX initialization. PIN_RX_INIT_DONE will be cleared to 0 by the + * PHY After RX initialization is done, PIN_RX_INIT_DONE will be set to + * 1 by COMPHY Set PIN_RX_INIT=0 after PIN_RX_INIT_DONE= 1. Please + * refer to RX initialization part for details. + */ + reg_set(MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index), + PHY_RX_INIT_BIT, PHY_RX_INIT_BIT); + + ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE + + COMPHY_PHY_STATUS_OFFSET(comphy_index), + PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, + PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + ERROR("Failed to lock PLL for SGMII PHY %d\n", comphy_index); + return -ETIMEDOUT; + } + + ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE + + COMPHY_PHY_STATUS_OFFSET(comphy_index), + PHY_RX_INIT_DONE_BIT, PHY_RX_INIT_DONE_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + ERROR("Failed to init RX of SGMII PHY %d\n", comphy_index); + return -ETIMEDOUT; + } + + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_sgmii_power_off(uint8_t comphy_index) +{ + uintptr_t offset; + uint32_t mask, data; + + debug_enter(); + + data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT; + mask = data; + offset = MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index); + reg_set(offset, data, mask); + + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, + uint32_t comphy_mode) +{ + int ret; + uintptr_t reg_base = 0; + uintptr_t addr; + uint32_t mask, data, cfg, ref_clk; + void (*usb3_reg_set)(uintptr_t addr, uint32_t reg_offset, uint16_t data, + uint16_t mask); + int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); + + debug_enter(); + + /* Set phy seclector */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + + /* Set usb3 reg access func, Lane2 is indirect access */ + if (comphy_index == COMPHY_LANE2) { + usb3_reg_set = &comphy_usb3_set_indirect; + reg_base = COMPHY_INDIRECT_REG; + } else { + /* Get the direct access register resource and map */ + usb3_reg_set = &comphy_usb3_set_direct; + reg_base = USB3_GBE1_PHY; + } + + /* + * 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The + * register belong to UTMI module, so it is set in UTMI phy driver. + */ + + /* + * 1. Set PRD_TXDEEMPH (3.5db de-emph) + */ + mask = PRD_TXDEEMPH0_MASK | PRD_TXMARGIN_MASK | PRD_TXSWING_MASK | + CFG_TX_ALIGN_POS_MASK; + usb3_reg_set(reg_base, COMPHY_LANE_CFG0, PRD_TXDEEMPH0_MASK, mask); + + /* + * 2. Set BIT0: enable transmitter in high impedance mode + * Set BIT[3:4]: delay 2 clock cycles for HiZ off latency + * Set BIT6: Tx detect Rx at HiZ mode + * Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db + * together with bit 0 of COMPHY_LANE_CFG0 register + */ + mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK | + TX_ELEC_IDLE_MODE_EN; + data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN; + usb3_reg_set(reg_base, COMPHY_LANE_CFG1, data, mask); + + /* + * 3. Set Spread Spectrum Clock Enabled + */ + usb3_reg_set(reg_base, COMPHY_LANE_CFG4, + SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN); + + /* + * 4. Set Override Margining Controls From the MAC: + * Use margining signals from lane configuration + */ + usb3_reg_set(reg_base, COMPHY_TEST_MODE_CTRL, + MODE_MARGIN_OVERRIDE, REG_16_BIT_MASK); + + /* + * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles + * set Mode Clock Source = PCLK is generated from REFCLK + */ + usb3_reg_set(reg_base, COMPHY_CLK_SRC_LO, 0x0, + (MODE_CLK_SRC | BUNDLE_PERIOD_SEL | + BUNDLE_PERIOD_SCALE_MASK | BUNDLE_SAMPLE_CTRL | + PLL_READY_DLY_MASK)); + + /* + * 6. Set G2 Spread Spectrum Clock Amplitude at 4K + */ + usb3_reg_set(reg_base, COMPHY_GEN2_SET2, + GS2_TX_SSC_AMP_VALUE_20, GS2_TX_SSC_AMP_MASK); + + /* + * 7. Unset G3 Spread Spectrum Clock Amplitude + * set G3 TX and RX Register Master Current Select + */ + mask = GS2_TX_SSC_AMP_MASK | GS2_VREG_RXTX_MAS_ISET_MASK | + GS2_RSVD_6_0_MASK; + usb3_reg_set(reg_base, COMPHY_GEN3_SET2, + GS2_VREG_RXTX_MAS_ISET_60U, mask); + + /* + * 8. Check crystal jumper setting and program the Power and PLL Control + * accordingly Change RX wait + */ + if (get_ref_clk() == 40) { + ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ; + cfg = CFG_PM_RXDLOZ_WAIT_12_UNIT; + + } else { + /* 25 MHz */ + ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ; + cfg = CFG_PM_RXDLOZ_WAIT_7_UNIT; + } + + mask = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | + PU_TX_INTP_BIT | PU_DFE_BIT | PLL_LOCK_BIT | PHY_MODE_MASK | + REF_FREF_SEL_MASK; + data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | + PU_TX_INTP_BIT | PU_DFE_BIT | PHY_MODE_USB3 | ref_clk; + usb3_reg_set(reg_base, COMPHY_POWER_PLL_CTRL, data, mask); + + mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | + CFG_PM_RXDLOZ_WAIT_MASK; + data = CFG_PM_RXDEN_WAIT_1_UNIT | cfg; + usb3_reg_set(reg_base, COMPHY_PWR_MGM_TIM1, data, mask); + + /* + * 9. Enable idle sync + */ + data = IDLE_SYNC_EN_DEFAULT_VALUE | IDLE_SYNC_EN; + usb3_reg_set(reg_base, COMPHY_IDLE_SYNC_EN, data, REG_16_BIT_MASK); + + /* + * 10. Enable the output of 500M clock + */ + data = MISC_CTRL0_DEFAULT_VALUE | CLK500M_EN; + usb3_reg_set(reg_base, COMPHY_MISC_CTRL0, data, REG_16_BIT_MASK); + + /* + * 11. Set 20-bit data width + */ + usb3_reg_set(reg_base, COMPHY_DIG_LOOPBACK_EN, DATA_WIDTH_20BIT, + REG_16_BIT_MASK); + + /* + * 12. Override Speed_PLL value and use MAC PLL + */ + usb3_reg_set(reg_base, COMPHY_KVCO_CAL_CTRL, + (SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT), + REG_16_BIT_MASK); + + /* + * 13. Check the Polarity invert bit + */ + data = 0U; + if (invert & COMPHY_POLARITY_TXD_INVERT) { + data |= TXD_INVERT_BIT; + } + if (invert & COMPHY_POLARITY_RXD_INVERT) { + data |= RXD_INVERT_BIT; + } + mask = TXD_INVERT_BIT | RXD_INVERT_BIT; + usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN, data, mask); + + /* + * 14. Set max speed generation to USB3.0 5Gbps + */ + usb3_reg_set(reg_base, COMPHY_SYNC_MASK_GEN, PHY_GEN_MAX_USB3_5G, + PHY_GEN_MAX_MASK); + + /* + * 15. Set capacitor value for FFE gain peaking to 0xF + */ + usb3_reg_set(reg_base, COMPHY_GEN2_SET3, + GS3_FFE_CAP_SEL_VALUE, GS3_FFE_CAP_SEL_MASK); + + /* + * 16. Release SW reset + */ + data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32 | MODE_REFDIV_BY_4; + usb3_reg_set(reg_base, COMPHY_RST_CLK_CTRL, data, REG_16_BIT_MASK); + + /* Wait for > 55 us to allow PCLK be enabled */ + udelay(PLL_SET_DELAY_US); + + if (comphy_index == COMPHY_LANE2) { + data = COMPHY_LANE_STAT1 + USB3PHY_LANE2_REG_BASE_OFFSET; + mmio_write_32(reg_base + COMPHY_LANE2_INDIR_ADDR_OFFSET, + data); + + addr = reg_base + COMPHY_LANE2_INDIR_DATA_OFFSET; + ret = polling_with_timeout(addr, TXDCLK_PCLK_EN, TXDCLK_PCLK_EN, + COMPHY_PLL_TIMEOUT, REG_32BIT); + } else { + ret = polling_with_timeout(LANE_STAT1_ADDR(USB3) + reg_base, + TXDCLK_PCLK_EN, TXDCLK_PCLK_EN, + COMPHY_PLL_TIMEOUT, REG_16BIT); + } + if (ret) { + ERROR("Failed to lock USB3 PLL\n"); + return -ETIMEDOUT; + } + + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_pcie_power_on(uint8_t comphy_index, + uint32_t comphy_mode) +{ + int ret; + uint32_t ref_clk; + uint32_t mask, data; + int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); + + debug_enter(); + + /* Configure phy selector for PCIe */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + + /* 1. Enable max PLL. */ + reg_set16(LANE_CFG1_ADDR(PCIE) + COMPHY_SD_ADDR, + USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN); + + /* 2. Select 20 bit SERDES interface. */ + reg_set16(CLK_SRC_LO_ADDR(PCIE) + COMPHY_SD_ADDR, + CFG_SEL_20B, CFG_SEL_20B); + + /* 3. Force to use reg setting for PCIe mode */ + reg_set16(MISC_CTRL1_ADDR(PCIE) + COMPHY_SD_ADDR, + SEL_BITS_PCIE_FORCE, SEL_BITS_PCIE_FORCE); + + /* 4. Change RX wait */ + reg_set16(PWR_MGM_TIM1_ADDR(PCIE) + COMPHY_SD_ADDR, + CFG_PM_RXDEN_WAIT_1_UNIT | CFG_PM_RXDLOZ_WAIT_12_UNIT, + (CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | + CFG_PM_RXDLOZ_WAIT_MASK)); + + /* 5. Enable idle sync */ + reg_set16(IDLE_SYNC_EN_ADDR(PCIE) + COMPHY_SD_ADDR, + IDLE_SYNC_EN_DEFAULT_VALUE | IDLE_SYNC_EN, REG_16_BIT_MASK); + + /* 6. Enable the output of 100M/125M/500M clock */ + reg_set16(MISC_CTRL0_ADDR(PCIE) + COMPHY_SD_ADDR, + MISC_CTRL0_DEFAULT_VALUE | CLK500M_EN | TXDCLK_2X_SEL | CLK100M_125M_EN, + REG_16_BIT_MASK); + + /* + * 7. Enable TX, PCIE global register, 0xd0074814, it is done in + * PCI-E driver + */ + + /* + * 8. Check crystal jumper setting and program the Power and PLL + * Control accordingly + */ + + if (get_ref_clk() == 40) + ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ; + else + ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ; + + reg_set16(PWR_PLL_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR, + (PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | + PU_TX_INTP_BIT | PU_DFE_BIT | ref_clk | PHY_MODE_PCIE), + REG_16_BIT_MASK); + + /* 9. Override Speed_PLL value and use MAC PLL */ + reg_set16(KVCO_CAL_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR, + SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT, REG_16_BIT_MASK); + + /* 10. Check the Polarity invert bit */ + data = 0U; + if (invert & COMPHY_POLARITY_TXD_INVERT) { + data |= TXD_INVERT_BIT; + } + if (invert & COMPHY_POLARITY_RXD_INVERT) { + data |= RXD_INVERT_BIT; + } + mask = TXD_INVERT_BIT | RXD_INVERT_BIT; + reg_set16(SYNC_PATTERN_ADDR(PCIE) + COMPHY_SD_ADDR, data, mask); + + /* 11. Release SW reset */ + data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32; + mask = data | SOFT_RESET | MODE_REFDIV_MASK; + reg_set16(RST_CLK_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR, data, mask); + + /* Wait for > 55 us to allow PCLK be enabled */ + udelay(PLL_SET_DELAY_US); + + ret = polling_with_timeout(LANE_STAT1_ADDR(PCIE) + COMPHY_SD_ADDR, + TXDCLK_PCLK_EN, TXDCLK_PCLK_EN, + COMPHY_PLL_TIMEOUT, REG_16BIT); + if (ret) { + ERROR("Failed to lock PCIE PLL\n"); + return -ETIMEDOUT; + } + + debug_exit(); + + return 0; +} + +int mvebu_3700_comphy_power_on(uint8_t comphy_index, uint32_t comphy_mode) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + int ret = 0; + + debug_enter(); + + switch (mode) { + case(COMPHY_SATA_MODE): + ret = mvebu_a3700_comphy_sata_power_on(comphy_index, + comphy_mode); + break; + case(COMPHY_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): + ret = mvebu_a3700_comphy_sgmii_power_on(comphy_index, + comphy_mode); + break; + case (COMPHY_USB3_MODE): + case (COMPHY_USB3H_MODE): + ret = mvebu_a3700_comphy_usb3_power_on(comphy_index, + comphy_mode); + break; + case (COMPHY_PCIE_MODE): + ret = mvebu_a3700_comphy_pcie_power_on(comphy_index, + comphy_mode); + break; + default: + ERROR("comphy%d: unsupported comphy mode\n", comphy_index); + ret = -EINVAL; + break; + } + + debug_exit(); + + return ret; +} + +static int mvebu_a3700_comphy_usb3_power_off(void) +{ + /* + * Currently the USB3 MAC will control the USB3 PHY to set it to low + * state, thus do not need to power off USB3 PHY again. + */ + debug_enter(); + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_sata_power_off(void) +{ + uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG; + uint32_t offset; + + debug_enter(); + + /* Set phy isolation mode */ + offset = COMPHY_ISOLATION_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, PHY_ISOLATE_MODE, + PHY_ISOLATE_MODE); + + /* Power off PLL, Tx, Rx */ + offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, 0, + PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT); + + debug_exit(); + + return 0; +} + +int mvebu_3700_comphy_power_off(uint8_t comphy_index, uint32_t comphy_mode) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + int err = 0; + + debug_enter(); + + if (!mode) { + /* + * The user did not specify which mode should be powered off. + * In this case we can identify this by reading the phy selector + * register. + */ + mode = mvebu_a3700_comphy_get_mode(comphy_index); + } + + switch (mode) { + case(COMPHY_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): + err = mvebu_a3700_comphy_sgmii_power_off(comphy_index); + break; + case (COMPHY_USB3_MODE): + case (COMPHY_USB3H_MODE): + err = mvebu_a3700_comphy_usb3_power_off(); + break; + case (COMPHY_SATA_MODE): + err = mvebu_a3700_comphy_sata_power_off(); + break; + + default: + debug("comphy%d: power off is not implemented for mode %d\n", + comphy_index, mode); + break; + } + + debug_exit(); + + return err; +} + +static int mvebu_a3700_comphy_sata_is_pll_locked(void) +{ + uint32_t data, addr; + uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG; + int ret = 0; + + debug_enter(); + + /* Polling status */ + mmio_write_32(comphy_indir_regs + COMPHY_LANE2_INDIR_ADDR_OFFSET, + COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET); + addr = comphy_indir_regs + COMPHY_LANE2_INDIR_DATA_OFFSET; + data = polling_with_timeout(addr, PLL_READY_TX_BIT, PLL_READY_TX_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + + if (data != 0) { + ERROR("TX PLL is not locked\n"); + ret = -ETIMEDOUT; + } + + debug_exit(); + + return ret; +} + +int mvebu_3700_comphy_is_pll_locked(uint8_t comphy_index, uint32_t comphy_mode) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + int ret = 0; + + debug_enter(); + + switch (mode) { + case(COMPHY_SATA_MODE): + ret = mvebu_a3700_comphy_sata_is_pll_locked(); + break; + + default: + ERROR("comphy[%d] mode[%d] doesn't support PLL lock check\n", + comphy_index, mode); + ret = -EINVAL; + break; + } + + debug_exit(); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h new file mode 100644 index 0000000..ed07624 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2018-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PHY_COMPHY_3700_H +#define PHY_COMPHY_3700_H + +#define PLL_SET_DELAY_US 600 +#define COMPHY_PLL_TIMEOUT 1000 +#define REG_16_BIT_MASK 0xFFFF + +#define COMPHY_SELECTOR_PHY_REG 0xFC +/* bit0: 0: Lane1 is GbE0; 1: Lane1 is PCIE */ +#define COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT BIT(0) +/* bit4: 0: Lane0 is GbE1; 1: Lane0 is USB3 */ +#define COMPHY_SELECTOR_USB3_GBE1_SEL_BIT BIT(4) +/* bit8: 0: Lane0 is USB3 instead of GbE1, Lane2 is SATA; 1: Lane2 is USB3 */ +#define COMPHY_SELECTOR_USB3_PHY_SEL_BIT BIT(8) + +/* SATA PHY register offset */ +#define SATAPHY_LANE2_REG_BASE_OFFSET 0x200 + +/* USB3 PHY offset compared to SATA PHY */ +#define USB3PHY_LANE2_REG_BASE_OFFSET 0x200 + +/* Comphy lane2 indirect access register offset */ +#define COMPHY_LANE2_INDIR_ADDR_OFFSET 0x0 +#define COMPHY_LANE2_INDIR_DATA_OFFSET 0x4 + +/* PHY shift to get related register address */ +enum { + PCIE = 1, + USB3, +}; + +#define PCIEPHY_SHFT 2 +#define USB3PHY_SHFT 2 +#define PHY_SHFT(unit) ((unit == PCIE) ? PCIEPHY_SHFT : USB3PHY_SHFT) + +/* PHY register */ +#define COMPHY_POWER_PLL_CTRL 0x01 +#define PWR_PLL_CTRL_ADDR(unit) (COMPHY_POWER_PLL_CTRL * PHY_SHFT(unit)) +#define PU_IVREF_BIT BIT(15) +#define PU_PLL_BIT BIT(14) +#define PU_RX_BIT BIT(13) +#define PU_TX_BIT BIT(12) +#define PU_TX_INTP_BIT BIT(11) +#define PU_DFE_BIT BIT(10) +#define RESET_DTL_RX_BIT BIT(9) +#define PLL_LOCK_BIT BIT(8) +#define REF_FREF_SEL_OFFSET 0 +#define REF_FREF_SEL_MASK (0x1F << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_SERDES_25MHZ (0x1 << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_SERDES_40MHZ (0x3 << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_SERDES_50MHZ (0x4 << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_PCIE_USB3_25MHZ (0x2 << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_PCIE_USB3_40MHZ (0x3 << REF_FREF_SEL_OFFSET) +#define PHY_MODE_OFFSET 5 +#define PHY_MODE_MASK (7 << PHY_MODE_OFFSET) +#define PHY_MODE_SATA (0x0 << PHY_MODE_OFFSET) +#define PHY_MODE_PCIE (0x3 << PHY_MODE_OFFSET) +#define PHY_MODE_SGMII (0x4 << PHY_MODE_OFFSET) +#define PHY_MODE_USB3 (0x5 << PHY_MODE_OFFSET) + +#define COMPHY_KVCO_CAL_CTRL 0x02 +#define KVCO_CAL_CTRL_ADDR(unit) (COMPHY_KVCO_CAL_CTRL * PHY_SHFT(unit)) +#define USE_MAX_PLL_RATE_BIT BIT(12) +#define SPEED_PLL_OFFSET 2 +#define SPEED_PLL_MASK (0x3F << SPEED_PLL_OFFSET) +#define SPEED_PLL_VALUE_16 (0x10 << SPEED_PLL_OFFSET) + +#define COMPHY_DIG_LOOPBACK_EN 0x23 +#define DIG_LOOPBACK_EN_ADDR(unit) (COMPHY_DIG_LOOPBACK_EN * \ + PHY_SHFT(unit)) +#define SEL_DATA_WIDTH_OFFSET 10 +#define SEL_DATA_WIDTH_MASK (0x3 << SEL_DATA_WIDTH_OFFSET) +#define DATA_WIDTH_10BIT (0x0 << SEL_DATA_WIDTH_OFFSET) +#define DATA_WIDTH_20BIT (0x1 << SEL_DATA_WIDTH_OFFSET) +#define DATA_WIDTH_40BIT (0x2 << SEL_DATA_WIDTH_OFFSET) +#define PLL_READY_TX_BIT BIT(4) + +#define COMPHY_SYNC_PATTERN 0x24 +#define SYNC_PATTERN_ADDR(unit) (COMPHY_SYNC_PATTERN * PHY_SHFT(unit)) +#define TXD_INVERT_BIT BIT(10) +#define RXD_INVERT_BIT BIT(11) + +#define COMPHY_SYNC_MASK_GEN 0x25 +#define PHY_GEN_MAX_OFFSET 10 +#define PHY_GEN_MAX_MASK (3 << PHY_GEN_MAX_OFFSET) +#define PHY_GEN_MAX_USB3_5G (1 << PHY_GEN_MAX_OFFSET) + +#define COMPHY_ISOLATION_CTRL 0x26 +#define ISOLATION_CTRL_ADDR(unit) (COMPHY_ISOLATION_REG * PHY_SHFT(unit)) +#define PHY_ISOLATE_MODE BIT(15) + +#define COMPHY_GEN2_SET2 0x3e +#define GEN2_SET2_ADDR(unit) (COMPHY_GEN2_SET2 * PHY_SHFT(unit)) +#define GS2_TX_SSC_AMP_VALUE_20 BIT(14) +#define GS2_TX_SSC_AMP_OFF 9 +#define GS2_TX_SSC_AMP_LEN 7 +#define GS2_TX_SSC_AMP_MASK (((1 << GS2_TX_SSC_AMP_LEN) - 1) << \ + GS2_TX_SSC_AMP_OFF) +#define GS2_VREG_RXTX_MAS_ISET_OFF 7 +#define GS2_VREG_RXTX_MAS_ISET_60U (0 << GS2_VREG_RXTX_MAS_ISET_OFF) +#define GS2_VREG_RXTX_MAS_ISET_80U (1 << GS2_VREG_RXTX_MAS_ISET_OFF) +#define GS2_VREG_RXTX_MAS_ISET_100U (2 << GS2_VREG_RXTX_MAS_ISET_OFF) +#define GS2_VREG_RXTX_MAS_ISET_120U (3 << GS2_VREG_RXTX_MAS_ISET_OFF) +#define GS2_VREG_RXTX_MAS_ISET_MASK (BIT(7) | BIT(8)) +#define GS2_RSVD_6_0_OFF 0 +#define GS2_RSVD_6_0_LEN 7 +#define GS2_RSVD_6_0_MASK (((1 << GS2_RSVD_6_0_LEN) - 1) << \ + GS2_RSVD_6_0_OFF) + +#define COMPHY_GEN3_SET2 0x3f +#define GEN3_SET2_ADDR(unit) (COMPHY_GEN3_SET2 * PHY_SHFT(unit)) + +#define COMPHY_IDLE_SYNC_EN 0x48 +#define IDLE_SYNC_EN_ADDR(unit) (COMPHY_IDLE_SYNC_EN * PHY_SHFT(unit)) +#define IDLE_SYNC_EN BIT(12) +#define IDLE_SYNC_EN_DEFAULT_VALUE 0x60 + +#define COMPHY_MISC_CTRL0 0x4F +#define MISC_CTRL0_ADDR(unit) (COMPHY_MISC_CTRL0 * PHY_SHFT(unit)) +#define CLK100M_125M_EN BIT(4) +#define TXDCLK_2X_SEL BIT(6) +#define CLK500M_EN BIT(7) +#define PHY_REF_CLK_SEL BIT(10) +#define MISC_CTRL0_DEFAULT_VALUE 0xA00D + +#define COMPHY_MISC_CTRL1 0x73 +#define MISC_CTRL1_ADDR(unit) (COMPHY_MISC_CTRL1 * PHY_SHFT(unit)) +#define SEL_BITS_PCIE_FORCE BIT(15) + +#define COMPHY_GEN2_SET3 0x112 +#define GS3_FFE_CAP_SEL_MASK 0xF +#define GS3_FFE_CAP_SEL_VALUE 0xF + +#define COMPHY_LANE_CFG0 0x180 +#define LANE_CFG0_ADDR(unit) (COMPHY_LANE_CFG0 * PHY_SHFT(unit)) +#define PRD_TXDEEMPH0_MASK BIT(0) +#define PRD_TXMARGIN_MASK (BIT(1) | BIT(2) | BIT(3)) +#define PRD_TXSWING_MASK BIT(4) +#define CFG_TX_ALIGN_POS_MASK (BIT(5) | BIT(6) | BIT(7) | BIT(8)) + +#define COMPHY_LANE_CFG1 0x181 +#define LANE_CFG1_ADDR(unit) (COMPHY_LANE_CFG1 * PHY_SHFT(unit)) +#define PRD_TXDEEMPH1_MASK BIT(15) +#define USE_MAX_PLL_RATE_EN BIT(9) +#define TX_DET_RX_MODE BIT(6) +#define GEN2_TX_DATA_DLY_MASK (BIT(3) | BIT(4)) +#define GEN2_TX_DATA_DLY_DEFT (2 << 3) +#define TX_ELEC_IDLE_MODE_EN BIT(0) + +#define COMPHY_LANE_STAT1 0x183 +#define LANE_STAT1_ADDR(unit) (COMPHY_LANE_STAT1 * PHY_SHFT(unit)) +#define TXDCLK_PCLK_EN BIT(0) + +#define COMPHY_LANE_CFG4 0x188 +#define LANE_CFG4_ADDR(unit) (COMPHY_LANE_CFG4 * PHY_SHFT(unit)) +#define SPREAD_SPECTRUM_CLK_EN BIT(7) + +#define COMPHY_RST_CLK_CTRL 0x1C1 +#define RST_CLK_CTRL_ADDR(unit) (COMPHY_RST_CLK_CTRL * PHY_SHFT(unit)) +#define SOFT_RESET BIT(0) +#define MODE_CORE_CLK_FREQ_SEL BIT(9) +#define MODE_PIPE_WIDTH_32 BIT(3) +#define MODE_REFDIV_OFFSET 4 +#define MODE_REFDIV_LEN 2 +#define MODE_REFDIV_MASK (0x3 << MODE_REFDIV_OFFSET) +#define MODE_REFDIV_BY_4 (0x2 << MODE_REFDIV_OFFSET) + +#define COMPHY_TEST_MODE_CTRL 0x1C2 +#define TEST_MODE_CTRL_ADDR(unit) (COMPHY_TEST_MODE_CTRL * PHY_SHFT(unit)) +#define MODE_MARGIN_OVERRIDE BIT(2) + +#define COMPHY_CLK_SRC_LO 0x1C3 +#define CLK_SRC_LO_ADDR(unit) (COMPHY_CLK_SRC_LO * PHY_SHFT(unit)) +#define MODE_CLK_SRC BIT(0) +#define BUNDLE_PERIOD_SEL BIT(1) +#define BUNDLE_PERIOD_SCALE_MASK (BIT(2) | BIT(3)) +#define BUNDLE_SAMPLE_CTRL BIT(4) +#define PLL_READY_DLY_MASK (BIT(5) | BIT(6) | BIT(7)) +#define CFG_SEL_20B BIT(15) + +#define COMPHY_PWR_MGM_TIM1 0x1D0 +#define PWR_MGM_TIM1_ADDR(unit) (COMPHY_PWR_MGM_TIM1 * PHY_SHFT(unit)) +#define CFG_PM_OSCCLK_WAIT_OFF 12 +#define CFG_PM_OSCCLK_WAIT_LEN 4 +#define CFG_PM_OSCCLK_WAIT_MASK (((1 << CFG_PM_OSCCLK_WAIT_LEN) - 1) \ + << CFG_PM_OSCCLK_WAIT_OFF) +#define CFG_PM_RXDEN_WAIT_OFF 8 +#define CFG_PM_RXDEN_WAIT_LEN 4 +#define CFG_PM_RXDEN_WAIT_MASK (((1 << CFG_PM_RXDEN_WAIT_LEN) - 1) \ + << CFG_PM_RXDEN_WAIT_OFF) +#define CFG_PM_RXDEN_WAIT_1_UNIT (1 << CFG_PM_RXDEN_WAIT_OFF) +#define CFG_PM_RXDLOZ_WAIT_OFF 0 +#define CFG_PM_RXDLOZ_WAIT_LEN 8 +#define CFG_PM_RXDLOZ_WAIT_MASK (((1 << CFG_PM_RXDLOZ_WAIT_LEN) - 1) \ + << CFG_PM_RXDLOZ_WAIT_OFF) +#define CFG_PM_RXDLOZ_WAIT_7_UNIT (7 << CFG_PM_RXDLOZ_WAIT_OFF) +#define CFG_PM_RXDLOZ_WAIT_12_UNIT (0xC << CFG_PM_RXDLOZ_WAIT_OFF) + +/* + * This register is not from PHY lane register space. It only exists in the + * indirect register space, before the actual PHY lane 2 registers. So the + * offset is absolute, not relative to SATAPHY_LANE2_REG_BASE_OFFSET. + * It is used only for SATA PHY initialization. + */ +#define COMPHY_RESERVED_REG 0x0E +#define PHYCTRL_FRM_PIN_BIT BIT(13) + +/* SGMII */ +#define COMPHY_PHY_CFG1_OFFSET(lane) ((1 - (lane)) * 0x28) +#define PIN_PU_IVREF_BIT BIT(1) +#define PIN_RESET_CORE_BIT BIT(11) +#define PIN_RESET_COMPHY_BIT BIT(12) +#define PIN_PU_PLL_BIT BIT(16) +#define PIN_PU_RX_BIT BIT(17) +#define PIN_PU_TX_BIT BIT(18) +#define PIN_TX_IDLE_BIT BIT(19) +#define GEN_RX_SEL_OFFSET 22 +#define GEN_RX_SEL_MASK (0xF << GEN_RX_SEL_OFFSET) +#define GEN_TX_SEL_OFFSET 26 +#define GEN_TX_SEL_MASK (0xF << GEN_TX_SEL_OFFSET) +#define PHY_RX_INIT_BIT BIT(30) +#define SD_SPEED_1_25_G 0x6 +#define SD_SPEED_3_125_G 0x8 + +/* COMPHY status reg: + * lane0: USB3/GbE1 PHY Status 1 + * lane1: PCIe/GbE0 PHY Status 1 + */ +#define COMPHY_PHY_STATUS_OFFSET(lane) (0x18 + (1 - (lane)) * 0x28) +#define PHY_RX_INIT_DONE_BIT BIT(0) +#define PHY_PLL_READY_RX_BIT BIT(2) +#define PHY_PLL_READY_TX_BIT BIT(3) + +#define SGMIIPHY_ADDR(off, base) ((((off) & 0x00007FF) * 2) + (base)) + +#define MAX_LANE_NR 3 + +/* comphy API */ +int mvebu_3700_comphy_is_pll_locked(uint8_t comphy_index, uint32_t comphy_mode); +int mvebu_3700_comphy_power_off(uint8_t comphy_index, uint32_t comphy_mode); +int mvebu_3700_comphy_power_on(uint8_t comphy_index, uint32_t comphy_mode); +#endif /* PHY_COMPHY_3700_H */ diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h new file mode 100644 index 0000000..ba5d255 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2018-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Marvell CP110 ana A3700 common */ + +#ifndef PHY_COMPHY_COMMON_H +#define PHY_COMPHY_COMMON_H + +/* #define DEBUG_COMPHY */ +#ifdef DEBUG_COMPHY +#define debug(format...) printf(format) +#else +#define debug(format, arg...) +#endif + +/* A lane is described by 4 fields: + * - bit 1~0 represent comphy polarity invert + * - bit 7~2 represent comphy speed + * - bit 11~8 represent unit index + * - bit 16~12 represent mode + * - bit 17 represent comphy indication of clock source + * - bit 20~18 represents pcie width (in case of pcie comphy config.) + * - bit 21 represents the source of the request (Linux/Bootloader), + * (reguired only for PCIe!) + * - bit 31~22 reserved + */ + +#define COMPHY_INVERT_OFFSET 0 +#define COMPHY_INVERT_LEN 2 +#define COMPHY_INVERT_MASK COMPHY_MASK(COMPHY_INVERT_OFFSET, \ + COMPHY_INVERT_LEN) +#define COMPHY_SPEED_OFFSET (COMPHY_INVERT_OFFSET + COMPHY_INVERT_LEN) +#define COMPHY_SPEED_LEN 6 +#define COMPHY_SPEED_MASK COMPHY_MASK(COMPHY_SPEED_OFFSET, \ + COMPHY_SPEED_LEN) +#define COMPHY_UNIT_ID_OFFSET (COMPHY_SPEED_OFFSET + COMPHY_SPEED_LEN) +#define COMPHY_UNIT_ID_LEN 4 +#define COMPHY_UNIT_ID_MASK COMPHY_MASK(COMPHY_UNIT_ID_OFFSET, \ + COMPHY_UNIT_ID_LEN) +#define COMPHY_MODE_OFFSET (COMPHY_UNIT_ID_OFFSET + COMPHY_UNIT_ID_LEN) +#define COMPHY_MODE_LEN 5 +#define COMPHY_MODE_MASK COMPHY_MASK(COMPHY_MODE_OFFSET, COMPHY_MODE_LEN) +#define COMPHY_CLK_SRC_OFFSET (COMPHY_MODE_OFFSET + COMPHY_MODE_LEN) +#define COMPHY_CLK_SRC_LEN 1 +#define COMPHY_CLK_SRC_MASK COMPHY_MASK(COMPHY_CLK_SRC_OFFSET, \ + COMPHY_CLK_SRC_LEN) +#define COMPHY_PCI_WIDTH_OFFSET (COMPHY_CLK_SRC_OFFSET + COMPHY_CLK_SRC_LEN) +#define COMPHY_PCI_WIDTH_LEN 3 +#define COMPHY_PCI_WIDTH_MASK COMPHY_MASK(COMPHY_PCI_WIDTH_OFFSET, \ + COMPHY_PCI_WIDTH_LEN) +#define COMPHY_PCI_CALLER_OFFSET \ + (COMPHY_PCI_WIDTH_OFFSET + COMPHY_PCI_WIDTH_LEN) +#define COMPHY_PCI_CALLER_LEN 1 +#define COMPHY_PCI_CALLER_MASK COMPHY_MASK(COMPHY_PCI_CALLER_OFFSET, \ + COMPHY_PCI_CALLER_LEN) + +#define COMPHY_MASK(offset, len) (((1 << (len)) - 1) << (offset)) + +/* Macro which extracts mode from lane description */ +#define COMPHY_GET_MODE(x) (((x) & COMPHY_MODE_MASK) >> \ + COMPHY_MODE_OFFSET) +/* Macro which extracts unit index from lane description */ +#define COMPHY_GET_ID(x) (((x) & COMPHY_UNIT_ID_MASK) >> \ + COMPHY_UNIT_ID_OFFSET) +/* Macro which extracts speed from lane description */ +#define COMPHY_GET_SPEED(x) (((x) & COMPHY_SPEED_MASK) >> \ + COMPHY_SPEED_OFFSET) +/* Macro which extracts clock source indication from lane description */ +#define COMPHY_GET_CLK_SRC(x) (((x) & COMPHY_CLK_SRC_MASK) >> \ + COMPHY_CLK_SRC_OFFSET) +/* Macro which extracts pcie width indication from lane description */ +#define COMPHY_GET_PCIE_WIDTH(x) (((x) & COMPHY_PCI_WIDTH_MASK) >> \ + COMPHY_PCI_WIDTH_OFFSET) + +/* Macro which extracts the caller for pcie power on from lane description */ +#define COMPHY_GET_CALLER(x) (((x) & COMPHY_PCI_CALLER_MASK) >> \ + COMPHY_PCI_CALLER_OFFSET) + +/* Macro which extracts the polarity invert from lane description */ +#define COMPHY_GET_POLARITY_INVERT(x) (((x) & COMPHY_INVERT_MASK) >> \ + COMPHY_INVERT_OFFSET) + + +#define COMPHY_SATA_MODE 0x1 +#define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */ +#define COMPHY_2500BASEX_MODE 0x3 /* 2500Base-X */ +#define COMPHY_USB3H_MODE 0x4 +#define COMPHY_USB3D_MODE 0x5 +#define COMPHY_PCIE_MODE 0x6 +#define COMPHY_RXAUI_MODE 0x7 +#define COMPHY_XFI_MODE 0x8 +#define COMPHY_SFI_MODE 0x9 +#define COMPHY_USB3_MODE 0xa +#define COMPHY_AP_MODE 0xb + +#define COMPHY_UNUSED 0xFFFFFFFF + +/* Polarity invert macro */ +#define COMPHY_POLARITY_NO_INVERT 0 +#define COMPHY_POLARITY_TXD_INVERT 1 +#define COMPHY_POLARITY_RXD_INVERT 2 +#define COMPHY_POLARITY_ALL_INVERT (COMPHY_POLARITY_TXD_INVERT | \ + COMPHY_POLARITY_RXD_INVERT) + +enum reg_width_type { + REG_16BIT = 0, + REG_32BIT, +}; + +enum { + COMPHY_LANE0 = 0, + COMPHY_LANE1, + COMPHY_LANE2, + COMPHY_LANE3, + COMPHY_LANE4, + COMPHY_LANE5, + COMPHY_LANE_MAX, +}; + +static inline uint32_t polling_with_timeout(uintptr_t addr, uint32_t val, + uint32_t mask, + uint32_t usec_timeout, + enum reg_width_type type) +{ + uint32_t data; + + do { + udelay(1); + if (type == REG_16BIT) + data = mmio_read_16(addr) & mask; + else + data = mmio_read_32(addr) & mask; + } while (data != val && --usec_timeout > 0); + + if (usec_timeout == 0) + return data; + + return 0; +} + +static inline void reg_set(uintptr_t addr, uint32_t data, uint32_t mask) +{ + debug(": WR to addr = 0x%lx, data = 0x%x (mask = 0x%x) - ", + addr, data, mask); + debug("old value = 0x%x ==> ", mmio_read_32(addr)); + mmio_clrsetbits_32(addr, mask, data & mask); + + debug("new val 0x%x\n", mmio_read_32(addr)); +} + +static inline void __unused reg_set16(uintptr_t addr, uint16_t data, + uint16_t mask) +{ + + debug(": WR to addr = 0x%lx, data = 0x%x (mask = 0x%x) - ", + addr, data, mask); + debug("old value = 0x%x ==> ", mmio_read_16(addr)); + mmio_clrsetbits_16(addr, mask, data & mask); + + debug("new val 0x%x\n", mmio_read_16(addr)); +} + +#endif /* PHY_COMPHY_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c new file mode 100644 index 0000000..fa9fe41 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c @@ -0,0 +1,2528 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Marvell CP110 SoC COMPHY unit driver */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "mvebu.h" +#include "comphy-cp110.h" +#include "phy-comphy-cp110.h" +#include "phy-comphy-common.h" + +#if __has_include("phy-porting-layer.h") +#include "phy-porting-layer.h" +#else +#include "phy-default-porting-layer.h" +#endif + +/* COMPHY speed macro */ +#define COMPHY_SPEED_1_25G 0 /* SGMII 1G */ +#define COMPHY_SPEED_2_5G 1 +#define COMPHY_SPEED_3_125G 2 /* 2500Base-X */ +#define COMPHY_SPEED_5G 3 +#define COMPHY_SPEED_5_15625G 4 /* XFI 5G */ +#define COMPHY_SPEED_6G 5 +#define COMPHY_SPEED_10_3125G 6 /* XFI 10G */ +#define COMPHY_SPEED_MAX 0x3F +/* The default speed for IO with fixed known speed */ +#define COMPHY_SPEED_DEFAULT COMPHY_SPEED_MAX + +/* Commands for comphy driver */ +#define COMPHY_COMMAND_DIGITAL_PWR_OFF 0x00000001 +#define COMPHY_COMMAND_DIGITAL_PWR_ON 0x00000002 + +#define COMPHY_PIPE_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + 0x120000) + +/* System controller registers */ +#define PCIE_MAC_RESET_MASK_PORT0 BIT(13) +#define PCIE_MAC_RESET_MASK_PORT1 BIT(11) +#define PCIE_MAC_RESET_MASK_PORT2 BIT(12) +#define SYS_CTRL_UINIT_SOFT_RESET_REG 0x268 +#define SYS_CTRL_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + 0x440000) + +/* DFX register spaces */ +#define SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET (30) +#define SAR_RST_PCIE0_CLOCK_CONFIG_CP0_MASK (0x1UL << \ + SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET) +#define SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET (31) +#define SAR_RST_PCIE1_CLOCK_CONFIG_CP0_MASK (0x1UL << \ + SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET) +#define SAR_STATUS_0_REG 0x40600 +#define DFX_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + DFX_BASE) +/* Common Phy training */ +#define COMPHY_TRX_TRAIN_COMPHY_OFFS 0x1000 +#define COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE 0x1 +#define COMPHY_TRX_RELATIVE_ADDR(comphy_index) (comphy_train_base + \ + (comphy_index) * COMPHY_TRX_TRAIN_COMPHY_OFFS) + +/* The same Units Soft Reset Config register are accessed in all PCIe ports + * initialization, so a spin lock is defined in case when more than 1 CPUs + * resets PCIe MAC and need to access the register in the same time. The spin + * lock is shared by all CP110 units. + */ +spinlock_t cp110_mac_reset_lock; + +/* These values come from the PCI Express Spec */ +enum pcie_link_width { + PCIE_LNK_WIDTH_RESRV = 0x00, + PCIE_LNK_X1 = 0x01, + PCIE_LNK_X2 = 0x02, + PCIE_LNK_X4 = 0x04, + PCIE_LNK_X8 = 0x08, + PCIE_LNK_X12 = 0x0C, + PCIE_LNK_X16 = 0x10, + PCIE_LNK_X32 = 0x20, + PCIE_LNK_WIDTH_UNKNOWN = 0xFF, +}; + +_Bool rx_trainng_done[AP_NUM][CP_NUM][MAX_LANE_NR] = {0}; + +static void mvebu_cp110_get_ap_and_cp_nr(uint8_t *ap_nr, uint8_t *cp_nr, + uint64_t comphy_base) +{ +#if (AP_NUM == 1) + *ap_nr = 0; +#else + *ap_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(0)) / + AP_IO_OFFSET); +#endif + + *cp_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(*ap_nr)) / + MVEBU_CP_OFFSET); + + debug("cp_base 0x%" PRIx64 ", ap_io_base 0x%lx, cp_offset 0x%lx\n", + comphy_base, (unsigned long)MVEBU_AP_IO_BASE(*ap_nr), + (unsigned long)MVEBU_CP_OFFSET); +} + +/* Clear PIPE selector - avoid collision with previous configuration */ +static void mvebu_cp110_comphy_clr_pipe_selector(uint64_t comphy_base, + uint8_t comphy_index) +{ + uint32_t reg, mask, field; + uint32_t comphy_offset = + COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index; + + mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset; + reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET); + field = reg & mask; + + if (field) { + reg &= ~mask; + mmio_write_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET, + reg); + } +} + +/* Clear PHY selector - avoid collision with previous configuration */ +static void mvebu_cp110_comphy_clr_phy_selector(uint64_t comphy_base, + uint8_t comphy_index) +{ + uint32_t reg, mask, field; + uint32_t comphy_offset = + COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index; + + mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset; + reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET); + field = reg & mask; + + /* Clear comphy selector - if it was already configured. + * (might be that this comphy was configured as PCIe/USB, + * in such case, no need to clear comphy selector because PCIe/USB + * are controlled by hpipe selector). + */ + if (field) { + reg &= ~mask; + mmio_write_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET, + reg); + } +} + +/* PHY selector configures SATA and Network modes */ +static void mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uint32_t reg, mask; + uint32_t comphy_offset = + COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index; + int mode; + + /* If phy selector is used the pipe selector should be marked as + * unconnected. + */ + mvebu_cp110_comphy_clr_pipe_selector(comphy_base, comphy_index); + + /* Comphy mode (compound of the IO mode and id). Here, only the IO mode + * is required to distinguish between SATA and network modes. + */ + mode = COMPHY_GET_MODE(comphy_mode); + + mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset; + reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET); + reg &= ~mask; + + /* SATA port 0/1 require the same configuration */ + if (mode == COMPHY_SATA_MODE) { + /* SATA selector values is always 4 */ + reg |= COMMON_SELECTOR_COMPHYN_SATA << comphy_offset; + } else { + switch (comphy_index) { + case(0): + case(1): + case(2): + /* For comphy 0,1, and 2: + * Network selector value is always 1. + */ + reg |= COMMON_SELECTOR_COMPHY0_1_2_NETWORK << + comphy_offset; + break; + case(3): + /* For comphy 3: + * 0x1 = RXAUI_Lane1 + * 0x2 = SGMII/Base-X Port1 + */ + if (mode == COMPHY_RXAUI_MODE) + reg |= COMMON_SELECTOR_COMPHY3_RXAUI << + comphy_offset; + else + reg |= COMMON_SELECTOR_COMPHY3_SGMII << + comphy_offset; + break; + case(4): + /* For comphy 4: + * 0x1 = SGMII/Base-X Port1, XFI1/SFI1 + * 0x2 = SGMII/Base-X Port0: XFI0/SFI0, RXAUI_Lane0 + * + * We want to check if SGMII1 is the + * requested mode in order to determine which value + * should be set (all other modes use the same value) + * so we need to strip the mode, and check the ID + * because we might handle SGMII0 too. + */ + /* TODO: need to distinguish between CP110 and CP115 + * as SFI1/XFI1 available only for CP115. + */ + if ((mode == COMPHY_SGMII_MODE || + mode == COMPHY_2500BASEX_MODE || + mode == COMPHY_SFI_MODE || + mode == COMPHY_XFI_MODE || + mode == COMPHY_AP_MODE) + && COMPHY_GET_ID(comphy_mode) == 1) + reg |= COMMON_SELECTOR_COMPHY4_PORT1 << + comphy_offset; + else + reg |= COMMON_SELECTOR_COMPHY4_ALL_OTHERS << + comphy_offset; + break; + case(5): + /* For comphy 5: + * 0x1 = SGMII/Base-X Port2 + * 0x2 = RXAUI Lane1 + */ + if (mode == COMPHY_RXAUI_MODE) + reg |= COMMON_SELECTOR_COMPHY5_RXAUI << + comphy_offset; + else + reg |= COMMON_SELECTOR_COMPHY5_SGMII << + comphy_offset; + break; + } + } + + mmio_write_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET, reg); +} + +/* PIPE selector configures for PCIe, USB 3.0 Host, and USB 3.0 Device mode */ +static void mvebu_cp110_comphy_set_pipe_selector(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uint32_t reg; + uint32_t shift = COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index; + int mode = COMPHY_GET_MODE(comphy_mode); + uint32_t mask = COMMON_SELECTOR_COMPHY_MASK << shift; + uint32_t pipe_sel = 0x0; + + /* If pipe selector is used the phy selector should be marked as + * unconnected. + */ + mvebu_cp110_comphy_clr_phy_selector(comphy_base, comphy_index); + + reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET); + reg &= ~mask; + + switch (mode) { + case (COMPHY_PCIE_MODE): + /* For lanes support PCIE, selector value are all same */ + pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_PCIE; + break; + + case (COMPHY_USB3H_MODE): + /* Only lane 1-4 support USB host, selector value is same */ + if (comphy_index == COMPHY_LANE0 || + comphy_index == COMPHY_LANE5) + ERROR("COMPHY[%d] mode[%d] is invalid\n", + comphy_index, mode); + else + pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_USBH; + break; + + case (COMPHY_USB3D_MODE): + /* Lane 1 and 4 support USB device, selector value is same */ + if (comphy_index == COMPHY_LANE1 || + comphy_index == COMPHY_LANE4) + pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_USBD; + else + ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, + mode); + break; + + default: + ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode); + break; + } + + mmio_write_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET, reg | + (pipe_sel << shift)); +} + +int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base, uint8_t comphy_index) +{ + uintptr_t sd_ip_addr, addr; + uint32_t mask, data; + int ret = 0; + + debug_enter(); + + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_TX_MASK & + SD_EXTERNAL_STATUS0_PLL_RX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, + PLL_LOCK_TIMEOUT, REG_32BIT); + if (data != 0) { + if (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK) + ERROR("RX PLL is not locked\n"); + if (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK) + ERROR("TX PLL is not locked\n"); + + ret = -ETIMEDOUT; + } + + debug_exit(); + + return ret; +} + +static void mvebu_cp110_polarity_invert(uintptr_t addr, uint8_t phy_polarity_invert) +{ + uint32_t mask, data; + + /* Set RX / TX polarity */ + data = mask = 0x0U; + if ((phy_polarity_invert & COMPHY_POLARITY_TXD_INVERT) != 0) { + data |= (1 << HPIPE_SYNC_PATTERN_TXD_INV_OFFSET); + mask |= HPIPE_SYNC_PATTERN_TXD_INV_MASK; + debug("%s: inverting TX polarity\n", __func__); + } + + if ((phy_polarity_invert & COMPHY_POLARITY_RXD_INVERT) != 0) { + data |= (1 << HPIPE_SYNC_PATTERN_RXD_INV_OFFSET); + mask |= HPIPE_SYNC_PATTERN_RXD_INV_MASK; + debug("%s: inverting RX polarity\n", __func__); + } + + reg_set(addr, data, mask); +} + +static int mvebu_cp110_comphy_sata_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uintptr_t hpipe_addr, sd_ip_addr, comphy_addr; + uint32_t mask, data; + uint8_t ap_nr, cp_nr, phy_polarity_invert; + int ret = 0; + + debug_enter(); + + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + const struct sata_params *sata_static_values = + &sata_static_values_tab[ap_nr][cp_nr][comphy_index]; + + phy_polarity_invert = sata_static_values->polarity_invert; + + /* configure phy selector for SATA */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, + comphy_index, comphy_mode); + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + + debug(" add hpipe 0x%lx, sd 0x%lx, comphy 0x%lx\n", + hpipe_addr, sd_ip_addr, comphy_addr); + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Set select data width 40Bit - SATA mode only */ + reg_set(comphy_addr + COMMON_PHY_CFG6_REG, + 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET, + COMMON_PHY_CFG6_IF_40_SEL_MASK); + + /* release from hard reset in SD external */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + debug("stage: Comphy configuration\n"); + /* Start comphy Configuration */ + /* Set reference clock to comes from group 1 - choose 25Mhz */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Reference frequency select set 1 (for SATA = 25Mhz) */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + /* PHY mode select (set SATA = 0x0 */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Set max PHY generation setting - 6Gbps */ + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, + 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET, + HPIPE_INTERFACE_GEN_MAX_MASK); + /* Set select data width 40Bit (SEL_BITS[2:0]) */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); + + debug("stage: Analog parameters from ETP(HW)\n"); + /* G1 settings */ + mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data = sata_static_values->g1_rx_selmupi << + HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK; + data |= sata_static_values->g1_rx_selmupf << + HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; + data |= sata_static_values->g1_rx_selmufi << + HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; + data |= sata_static_values->g1_rx_selmuff << + HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + + mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; + data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; + data |= 0x2 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* G2 settings */ + mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; + data = sata_static_values->g2_rx_selmupi << + HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK; + data |= sata_static_values->g2_rx_selmupf << + HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; + data |= sata_static_values->g2_rx_selmufi << + HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK; + data |= sata_static_values->g2_rx_selmuff << + HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK; + data |= 0x1 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); + + /* G3 settings */ + mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; + data = sata_static_values->g3_rx_selmupi << + HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; + data |= sata_static_values->g3_rx_selmupf << + HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK; + data |= sata_static_values->g3_rx_selmufi << + HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK; + data |= sata_static_values->g3_rx_selmuff << + HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK; + data |= 0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK; + data |= 0x2 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET; + mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; + data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); + + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK; + data = 0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Trigger sampler enable pulse */ + mask = HPIPE_SMAPLER_MASK; + data = 0x1 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + mask = HPIPE_SMAPLER_MASK; + data = 0x0 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + + /* VDD Calibration Control 3 */ + mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; + data = 0x10 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; + reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); + + /* DFE Resolution Control */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* DFE F3-F5 Coefficient Control */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* G3 Setting 3 */ + mask = HPIPE_G3_FFE_CAP_SEL_MASK; + data = sata_static_values->g3_ffe_cap_sel << + HPIPE_G3_FFE_CAP_SEL_OFFSET; + mask |= HPIPE_G3_FFE_RES_SEL_MASK; + data |= sata_static_values->g3_ffe_res_sel << + HPIPE_G3_FFE_RES_SEL_OFFSET; + mask |= HPIPE_G3_FFE_SETTING_FORCE_MASK; + data |= 0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET; + mask |= HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; + data |= 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; + mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; + data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); + + /* G3 Setting 4 */ + mask = HPIPE_G3_DFE_RES_MASK; + data = sata_static_values->g3_dfe_res << HPIPE_G3_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); + + /* Offset Phase Control */ + mask = HPIPE_OS_PH_OFFSET_MASK; + data = sata_static_values->align90 << HPIPE_OS_PH_OFFSET_OFFSET; + mask |= HPIPE_OS_PH_OFFSET_FORCE_MASK; + data |= 0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET; + mask |= HPIPE_OS_PH_VALID_MASK; + data |= 0x0 << HPIPE_OS_PH_VALID_OFFSET; + reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); + mask = HPIPE_OS_PH_VALID_MASK; + data = 0x1 << HPIPE_OS_PH_VALID_OFFSET; + reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); + mask = HPIPE_OS_PH_VALID_MASK; + data = 0x0 << HPIPE_OS_PH_VALID_OFFSET; + reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); + + /* Set G1 TX amplitude and TX post emphasis value */ + mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; + data = sata_static_values->g1_amp << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK; + data |= sata_static_values->g1_tx_amp_adj << + HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; + data |= sata_static_values->g1_emph << + HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK; + data |= sata_static_values->g1_emph_en << + HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); + + /* Set G1 emph */ + mask = HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; + data = sata_static_values->g1_tx_emph_en << + HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; + mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; + data |= sata_static_values->g1_tx_emph << + HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); + + /* Set G2 TX amplitude and TX post emphasis value */ + mask = HPIPE_G2_SET_0_G2_TX_AMP_MASK; + data = sata_static_values->g2_amp << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET; + mask |= HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK; + data |= sata_static_values->g2_tx_amp_adj << + HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET; + mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_MASK; + data |= sata_static_values->g2_emph << + HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET; + mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK; + data |= sata_static_values->g2_emph_en << + HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_0_REG, data, mask); + + /* Set G2 emph */ + mask = HPIPE_G2_SET_2_G2_TX_EMPH0_EN_MASK; + data = sata_static_values->g2_tx_emph_en << + HPIPE_G2_SET_2_G2_TX_EMPH0_EN_OFFSET; + mask |= HPIPE_G2_SET_2_G2_TX_EMPH0_MASK; + data |= sata_static_values->g2_tx_emph << + HPIPE_G2_SET_2_G2_TX_EMPH0_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_2_REG, data, mask); + + /* Set G3 TX amplitude and TX post emphasis value */ + mask = HPIPE_G3_SET_0_G3_TX_AMP_MASK; + data = sata_static_values->g3_amp << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK; + data |= sata_static_values->g3_tx_amp_adj << + HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_MASK; + data |= sata_static_values->g3_emph << + HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK; + data |= sata_static_values->g3_emph_en << + HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK; + data |= 0x4 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK; + data |= 0x0 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SET_0_REG, data, mask); + + /* Set G3 emph */ + mask = HPIPE_G3_SET_2_G3_TX_EMPH0_EN_MASK; + data = sata_static_values->g3_tx_emph_en << + HPIPE_G3_SET_2_G3_TX_EMPH0_EN_OFFSET; + mask |= HPIPE_G3_SET_2_G3_TX_EMPH0_MASK; + data |= sata_static_values->g3_tx_emph << + HPIPE_G3_SET_2_G3_TX_EMPH0_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SET_2_REG, data, mask); + + /* SERDES External Configuration 2 register */ + mask = SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); + + /* DFE reset sequence */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET, + HPIPE_PWR_CTR_RST_DFE_MASK); + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET, + HPIPE_PWR_CTR_RST_DFE_MASK); + + if (phy_polarity_invert != 0) + mvebu_cp110_polarity_invert(hpipe_addr + HPIPE_SYNC_PATTERN_REG, + phy_polarity_invert); + + /* SW reset for interrupt logic */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET, + HPIPE_PWR_CTR_SFT_RST_MASK); + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET, + HPIPE_PWR_CTR_SFT_RST_MASK); + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_sgmii_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr; + uint32_t mask, data, sgmii_speed = COMPHY_GET_SPEED(comphy_mode); + int ret = 0; + + debug_enter(); + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + + /* configure phy selector for SGMII */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index, + comphy_mode); + + /* Confiugre the lane */ + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + + if (sgmii_speed == COMPHY_SPEED_1_25G) { + /* SGMII 1G, SerDes speed 1.25G */ + data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + } else if (sgmii_speed == COMPHY_SPEED_3_125G) { + /* 2500Base-X, SerDes speed 3.125G */ + data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + } else { + /* Other rates are not supported */ + ERROR("unsupported SGMII speed on comphy%d\n", comphy_index); + return -EINVAL; + } + + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* Set hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Release hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Make sure that 40 data bits is disabled + * This bit is not cleared by reset + */ + mask = COMMON_PHY_CFG6_IF_40_SEL_MASK; + data = 0 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG6_REG, data, mask); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + mask = HPIPE_MISC_REFCLK_SEL_MASK; + data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + mask = HPIPE_LOOPBACK_SEL_MASK; + data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Set analog parameters from ETP(HW) - for now use the default data */ + debug("stage: Analog parameters from ETP(HW)\n"); + + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, + 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, + HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + ret = mvebu_cp110_comphy_is_pll_locked(comphy_base, comphy_index); + if (ret) + return ret; + + /* RX init */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100, REG_32BIT); + if (data != 0) { + ERROR("RX init failed\n"); + ret = -ETIMEDOUT; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_xfi_power_on(uint64_t comphy_base, + uint8_t comphy_index, + uint32_t comphy_mode, + uint64_t comphy_train_base) +{ + uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr; + uint32_t mask, data, speed = COMPHY_GET_SPEED(comphy_mode); + int ret = 0; + uint8_t ap_nr, cp_nr; + + debug_enter(); + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) { + debug("Skip %s for comphy[%d][%d][%d], due to rx training\n", + __func__, ap_nr, cp_nr, comphy_index); + return 0; + } + + const struct xfi_params *xfi_static_values = + &xfi_static_values_tab[ap_nr][cp_nr][comphy_index]; + + debug("%s: the ap_nr = %d, cp_nr = %d, comphy_index %d\n", + __func__, ap_nr, cp_nr, comphy_index); + + debug("g1_ffe_cap_sel= 0x%x, g1_ffe_res_sel= 0x%x, g1_dfe_res= 0x%x\n", + xfi_static_values->g1_ffe_cap_sel, + xfi_static_values->g1_ffe_res_sel, + xfi_static_values->g1_dfe_res); + + if (!xfi_static_values->valid) { + ERROR("[ap%d][cp[%d][comphy:%d]: Has no valid static params\n", + ap_nr, cp_nr, comphy_index); + ERROR("[ap%d][cp[%d][comphy:%d]: porting layer needs update\n", + ap_nr, cp_nr, comphy_index); + return -EINVAL; + } + + if ((speed != COMPHY_SPEED_5_15625G) && + (speed != COMPHY_SPEED_10_3125G) && + (speed != COMPHY_SPEED_DEFAULT)) { + ERROR("comphy:%d: unsupported sfi/xfi speed\n", comphy_index); + return -EINVAL; + } + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + + /* configure phy selector for XFI/SFI */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index, + comphy_mode); + + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Make sure that 40 data bits is disabled + * This bit is not cleared by reset + */ + mask = COMMON_PHY_CFG6_IF_40_SEL_MASK; + data = 0 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG6_REG, data, mask); + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_TX_IDLE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_TX_IDLE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* + * Erratum IPCE_COMPHY-1353: toggle TX_IDLE bit in + * addition to the PHY reset + */ + mask = SD_EXTERNAL_CONFIG1_TX_IDLE_MASK; + data = 0x0U; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + mask = HPIPE_MISC_ICP_FORCE_MASK; + data = (speed == COMPHY_SPEED_5_15625G) ? + (0x0 << HPIPE_MISC_ICP_FORCE_OFFSET) : + (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET); + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + mask = HPIPE_LOOPBACK_SEL_MASK; + data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Transmitter/Receiver Speed Divider Force */ + if (speed == COMPHY_SPEED_5_15625G) { + mask = HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK; + data = 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET; + mask |= HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK; + data |= 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET; + mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK; + data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET; + mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK; + data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET; + } else { + mask = HPIPE_TXDIGCK_DIV_FORCE_MASK; + data = 0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET; + } + reg_set(hpipe_addr + HPIPE_SPD_DIV_FORCE_REG, data, mask); + + /* Set analog parameters from ETP(HW) */ + debug("stage: Analog parameters from ETP(HW)\n"); + /* SERDES External Configuration 2 */ + mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); + /* 0x7-DFE Resolution control */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + /* 0xd-G1_Setting_0 */ + if (speed == COMPHY_SPEED_5_15625G) { + mask = HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; + data = 0x6 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; + } else { + mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; + data = xfi_static_values->g1_amp << + HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; + data |= xfi_static_values->g1_emph << + HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; + + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK; + data |= xfi_static_values->g1_emph_en << + HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK; + data |= xfi_static_values->g1_tx_amp_adj << + HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET; + } + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); + /* Genration 1 setting 2 (G1_Setting_2) */ + mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; + data = xfi_static_values->g1_tx_emph << + HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; + mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; + data |= xfi_static_values->g1_tx_emph_en << + HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); + /* Transmitter Slew Rate Control register (tx_reg1) */ + mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK; + data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET; + mask |= HPIPE_TX_REG1_SLC_EN_MASK; + data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask); + /* Impedance Calibration Control register (cal_reg1) */ + mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK; + data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; + mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK; + data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask); + /* Generation 1 Setting 5 (g1_setting_5) */ + mask = HPIPE_G1_SETTING_5_G1_ICP_MASK; + data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask); + + /* 0xE-G1_Setting_1 */ + mask = HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; + data = 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; + if (speed == COMPHY_SPEED_5_15625G) { + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET; + } else { + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data |= xfi_static_values->g1_rx_selmupi << + HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK; + data |= xfi_static_values->g1_rx_selmupf << + HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; + data |= xfi_static_values->g1_rx_selmufi << + HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; + data |= xfi_static_values->g1_rx_selmuff << + HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; + data |= 0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; + } + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + + /* 0xA-DFE_Reg3 */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* 0x111-G1_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + /* Genration 1 setting 3 (G1_Setting_3) */ + mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET; + if (speed == COMPHY_SPEED_5_15625G) { + /* Force FFE (Feed Forward Equalization) to 5G */ + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; + data |= 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; + data |= 0x4 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + } else { + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; + data |= xfi_static_values->g1_ffe_cap_sel << + HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; + data |= xfi_static_values->g1_ffe_res_sel << + HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Use the value from CAL_OS_PH_EXT */ + mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK; + data = 1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET; + reg_set(hpipe_addr + + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, + data, mask); + + /* Update align90 */ + mask = HPIPE_CAL_OS_PH_EXT_MASK; + data = xfi_static_values->align90 << HPIPE_CAL_OS_PH_EXT_OFFSET; + reg_set(hpipe_addr + + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, + data, mask); + + /* Force DFE resolution (use gen table value) */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* 0x111-G1 DFE_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = xfi_static_values->g1_dfe_res << + HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + } + + /* Connfigure RX training timer */ + mask = HPIPE_RX_TRAIN_TIMER_MASK; + data = 0x13 << HPIPE_RX_TRAIN_TIMER_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); + + /* Enable TX train peak to peak hold */ + mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; + data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); + + /* Configure TX preset index */ + mask = HPIPE_TX_PRESET_INDEX_MASK; + data = 0x2 << HPIPE_TX_PRESET_INDEX_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_PRESET_INDEX_REG, data, mask); + + /* Disable pattern lock lost timeout */ + mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; + data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); + + /* Configure TX training pattern and TX training 16bit auto */ + mask = HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK; + data = 0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET; + mask |= HPIPE_TX_TRAIN_PAT_SEL_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); + + /* Configure Training patten number */ + mask = HPIPE_TRAIN_PAT_NUM_MASK; + data = 0x88 << HPIPE_TRAIN_PAT_NUM_OFFSET; + reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_0_REG, data, mask); + + /* Configure differencial manchester encoter to ethernet mode */ + mask = HPIPE_DME_ETHERNET_MODE_MASK; + data = 0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_DME_REG, data, mask); + + /* Configure VDD Continuous Calibration */ + mask = HPIPE_CAL_VDD_CONT_MODE_MASK; + data = 0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_VDD_CAL_0_REG, data, mask); + + /* Trigger sampler enable pulse (by toggleing the bit) */ + mask = HPIPE_RX_SAMPLER_OS_GAIN_MASK; + data = 0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET; + mask |= HPIPE_SMAPLER_MASK; + data |= 0x1 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + mask = HPIPE_SMAPLER_MASK; + data = 0x0 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + + /* Set External RX Regulator Control */ + mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; + data = 0x1A << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; + reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, + PLL_LOCK_TIMEOUT, REG_32BIT); + if (data != 0) { + if (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK) + ERROR("RX PLL is not locked\n"); + if (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK) + ERROR("TX PLL is not locked\n"); + + ret = -ETIMEDOUT; + } + + /* RX init */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100, REG_32BIT); + if (data != 0) { + ERROR("RX init failed\n"); + ret = -ETIMEDOUT; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Force rx training on 10G port */ + data = mmio_read_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index)); + data |= COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE; + mmio_write_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index), data); + mdelay(200); + data &= ~COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE; + mmio_write_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index), data); + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_pcie_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + int ret = 0; + uint32_t reg, mask, data, pcie_width; + uint32_t clk_dir; + uintptr_t hpipe_addr, comphy_addr, addr; + _Bool clk_src = COMPHY_GET_CLK_SRC(comphy_mode); + _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode); + + /* In Armada 8K DB boards, PCIe initialization can be executed + * only once (PCIe reset performed during chip power on and + * it cannot be executed via GPIO later). + * This means that power on can be executed only once, so let's + * mark if the caller is bootloader or Linux. + * If bootloader -> run power on. + * If Linux -> exit. + * + * TODO: In MacciatoBIN, PCIe reset is connected via GPIO, + * so after GPIO reset is added to Linux Kernel, it can be + * powered-on by Linux. + */ + if (!called_from_uboot) + return ret; + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + pcie_width = COMPHY_GET_PCIE_WIDTH(comphy_mode); + + debug_enter(); + + spin_lock(&cp110_mac_reset_lock); + + reg = mmio_read_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) + + SYS_CTRL_UINIT_SOFT_RESET_REG); + switch (comphy_index) { + case COMPHY_LANE0: + reg |= PCIE_MAC_RESET_MASK_PORT0; + break; + case COMPHY_LANE4: + reg |= PCIE_MAC_RESET_MASK_PORT1; + break; + case COMPHY_LANE5: + reg |= PCIE_MAC_RESET_MASK_PORT2; + break; + } + + mmio_write_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) + + SYS_CTRL_UINIT_SOFT_RESET_REG, reg); + spin_unlock(&cp110_mac_reset_lock); + + /* Configure PIPE selector for PCIE */ + mvebu_cp110_comphy_set_pipe_selector(comphy_base, comphy_index, + comphy_mode); + + /* + * Read SAR (Sample-At-Reset) configuration for the PCIe clock + * direction. + * + * SerDes Lane 4/5 got the PCIe ref-clock #1, + * and SerDes Lane 0 got PCIe ref-clock #0 + */ + reg = mmio_read_32(DFX_FROM_COMPHY_ADDR(comphy_base) + + SAR_STATUS_0_REG); + if (comphy_index == COMPHY_LANE4 || comphy_index == COMPHY_LANE5) + clk_dir = (reg & SAR_RST_PCIE1_CLOCK_CONFIG_CP0_MASK) >> + SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET; + else + clk_dir = (reg & SAR_RST_PCIE0_CLOCK_CONFIG_CP0_MASK) >> + SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET; + + debug("On lane %d\n", comphy_index); + debug("PCIe clock direction = %x\n", clk_dir); + debug("PCIe Width = %d\n", pcie_width); + + /* enable PCIe X4 and X2 */ + if (comphy_index == COMPHY_LANE0) { + if (pcie_width == PCIE_LNK_X4) { + data = 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET; + mask = COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK; + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + data, mask); + } else if (pcie_width == PCIE_LNK_X2) { + data = 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET; + mask = COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK; + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, data, mask); + } + } + + /* If PCIe clock is output and clock source from SerDes lane 5, + * need to configure the clock-source MUX. + * By default, the clock source is from lane 4 + */ + if (clk_dir && clk_src && (comphy_index == COMPHY_LANE5)) { + data = DFX_DEV_GEN_PCIE_CLK_SRC_MUX << + DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET; + mask = DFX_DEV_GEN_PCIE_CLK_SRC_MASK; + reg_set(DFX_FROM_COMPHY_ADDR(comphy_base) + + DFX_DEV_GEN_CTRL12_REG, data, mask); + } + + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + mask |= COMMON_PHY_PHY_MODE_MASK; + data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* release from hard reset */ + mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* Set PIPE soft reset */ + mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; + data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; + /* Set PHY datapath width mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; + data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; + /* Set Data bus width USB mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; + /* Set CORE_CLK output frequency for 250Mhz */ + mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); + /* Set PLL ready delay for 0x2 */ + data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET; + mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK; + if (pcie_width != PCIE_LNK_X1) { + data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET; + mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK; + data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET; + mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK; + } + reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask); + + /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */ + data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET; + mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK; + if (pcie_width != PCIE_LNK_X1) { + mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK; + mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK; + mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK; + if (comphy_index == 0) { + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET; + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET; + } else if (comphy_index == (pcie_width - 1)) { + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET; + } + } + reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask); + /* Config update polarity equalization */ + data = 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET; + mask = HPIPE_CFG_UPDATE_POLARITY_MASK; + reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG, data, mask); + /* Set PIPE version 4 to mode enable */ + data = 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET; + mask = HPIPE_DFE_CTRL_28_PIPE4_MASK; + reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG, data, mask); + /* TODO: check if pcie clock is output/input - for bringup use input*/ + /* Enable PIN clock 100M_125M */ + mask = 0; + data = 0; + /* Only if clock is output, configure the clock-source mux */ + if (clk_dir) { + mask |= HPIPE_MISC_CLK100M_125M_MASK; + data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET; + } + /* Set PIN_TXDCLK_2X Clock Freq. Selection for outputs 500MHz clock */ + mask |= HPIPE_MISC_TXDCLK_2X_MASK; + data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET; + /* Enable 500MHz Clock */ + mask |= HPIPE_MISC_CLK500_EN_MASK; + data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET; + if (clk_dir) { /* output */ + /* Set reference clock comes from group 1 */ + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + } else { + /* Set reference clock comes from group 2 */ + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET; + } + mask |= HPIPE_MISC_ICP_FORCE_MASK; + data |= 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + if (clk_dir) { /* output */ + /* Set reference frequcency select - 0x2 for 25MHz*/ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + } else { + /* Set reference frequcency select - 0x0 for 100MHz*/ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + } + /* Set PHY mode to PCIe */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + + /* ref clock alignment */ + if (pcie_width != PCIE_LNK_X1) { + mask = HPIPE_LANE_ALIGN_OFF_MASK; + data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask); + } + + /* Set the amount of time spent in the LoZ state - set for 0x7 only if + * the PCIe clock is output + */ + if (clk_dir) + reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, + 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, + HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); + + /* Set Maximal PHY Generation Setting(8Gbps) */ + mask = HPIPE_INTERFACE_GEN_MAX_MASK; + data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET; + /* Bypass frame detection and sync detection for RX DATA */ + mask |= HPIPE_INTERFACE_DET_BYPASS_MASK; + data |= 0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET; + /* Set Link Train Mode (Tx training control pins are used) */ + mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK; + data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET; + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask); + + /* Set Idle_sync enable */ + mask = HPIPE_PCIE_IDLE_SYNC_MASK; + data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET; + /* Select bits for PCIE Gen3(32bit) */ + mask |= HPIPE_PCIE_SEL_BITS_MASK; + data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET; + reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask); + + /* Enable Tx_adapt_g1 */ + mask = HPIPE_TX_TRAIN_CTRL_G1_MASK; + data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET; + /* Enable Tx_adapt_gn1 */ + mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET; + /* Disable Tx_adapt_g0 */ + mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); + + /* Set reg_tx_train_chk_init */ + mask = HPIPE_TX_TRAIN_CHK_INIT_MASK; + data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET; + /* Enable TX_COE_FM_PIN_PCIE3_EN */ + mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); + + debug("stage: TRx training parameters\n"); + /* Set Preset sweep configurations */ + mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK; + data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET; + mask |= HPIPE_TX_NUM_OF_PRESET_MASK; + data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET; + mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK; + data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask); + + /* Tx train start configuration */ + mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK; + data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET; + mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET; + mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET; + mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); + + /* Enable Tx train P2P */ + mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; + data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); + + /* Configure Tx train timeout */ + mask = HPIPE_TRX_TRAIN_TIMER_MASK; + data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask); + + /* Disable G0/G1/GN1 adaptation */ + mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK + | HPIPE_TX_TRAIN_CTRL_G0_OFFSET; + data = 0; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); + + /* Disable DTL frequency loop */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Configure G3 DFE */ + mask = HPIPE_G3_DFE_RES_MASK; + data = 0x3 << HPIPE_G3_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); + + /* Use TX/RX training result for DFE */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* Configure initial and final coefficient value for receiver */ + mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; + + mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; + + mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; + data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); + + /* Trigger sampler enable pulse */ + mask = HPIPE_SMAPLER_MASK; + data = 0x1 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + udelay(5); + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask); + + /* FFE resistor tuning for different bandwidth */ + mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; + data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; + mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; + data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); + + /* Pattern lock lost timeout disable */ + mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; + data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); + + /* Configure DFE adaptations */ + mask = HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK; + data = 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET; + mask |= HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK; + data |= 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET; + mask |= HPIPE_CDR_MAX_DFE_ADAPT_0_MASK; + data |= 0x0 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET; + mask |= HPIPE_CDR_MAX_DFE_ADAPT_1_MASK; + data |= 0x1 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET; + reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask); + + mask = HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK; + data = 0x0 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_CONTROL_REG, data, mask); + + /* Genration 2 setting 1*/ + mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; + data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; + data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); + + /* DFE enable */ + mask = HPIPE_G2_DFE_RES_MASK; + data = 0x3 << HPIPE_G2_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SETTINGS_4_REG, data, mask); + + /* Configure DFE Resolution */ + mask = HPIPE_LANE_CFG4_DFE_EN_SEL_MASK; + data = 0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); + + /* VDD calibration control */ + mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; + data = 0x16 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; + reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); + + /* Set PLL Charge-pump Current Control */ + mask = HPIPE_G3_SETTING_5_G3_ICP_MASK; + data = 0x4 << HPIPE_G3_SETTING_5_G3_ICP_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_5_REG, data, mask); + + /* Set lane rqualization remote setting */ + mask = HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK; + data = 0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET; + mask |= HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK; + data |= 0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET; + mask |= HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK; + data |= 0x6 << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_EQ_REMOTE_SETTING_REG, data, mask); + + mask = HPIPE_CFG_EQ_BUNDLE_DIS_MASK; + data = 0x1 << HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG2_REG, data, mask); + + debug("stage: Comphy power up\n"); + + /* For PCIe X4 or X2: + * release from reset only after finish to configure all lanes + */ + if ((pcie_width == PCIE_LNK_X1) || (comphy_index == (pcie_width - 1))) { + uint32_t i, start_lane, end_lane; + + if (pcie_width != PCIE_LNK_X1) { + /* allows writing to all lanes in one write */ + data = 0x0; + if (pcie_width == PCIE_LNK_X2) + mask = COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK; + else if (pcie_width == PCIE_LNK_X4) + mask = COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK; + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, data, mask); + start_lane = 0; + end_lane = pcie_width; + + /* Release from PIPE soft reset + * For PCIe by4 or by2: + * release from soft reset all lanes - can't use + * read modify write + */ + reg_set(HPIPE_ADDR( + COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), 0) + + HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff); + } else { + start_lane = comphy_index; + end_lane = comphy_index + 1; + + /* Release from PIPE soft reset + * for PCIe by4 or by2: + * release from soft reset all lanes + */ + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, + 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, + HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); + } + + if (pcie_width != PCIE_LNK_X1) { + /* disable writing to all lanes with one write */ + if (pcie_width == PCIE_LNK_X2) { + data = (COMPHY_LANE0 << + COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET) | + (COMPHY_LANE1 << + COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET); + mask = COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK; + } else if (pcie_width == PCIE_LNK_X4) { + data = (COMPHY_LANE0 << + COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET) | + (COMPHY_LANE1 << + COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET) | + (COMPHY_LANE2 << + COMMON_PHY_SD_CTRL1_COMPHY_2_PORT_OFFSET) | + (COMPHY_LANE3 << + COMMON_PHY_SD_CTRL1_COMPHY_3_PORT_OFFSET); + mask = COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK; + } + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + data, mask); + } + + debug("stage: Check PLL\n"); + /* Read lane status */ + for (i = start_lane; i < end_lane; i++) { + addr = HPIPE_ADDR( + COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), i) + + HPIPE_LANE_STATUS1_REG; + data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, + PLL_LOCK_TIMEOUT, + REG_32BIT); + if (data) { + ERROR("Failed to lock PCIE PLL\n"); + ret = -ETIMEDOUT; + } + } + } + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_rxaui_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr; + uint32_t mask, data; + int ret = 0; + + debug_enter(); + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + /* configure phy selector for RXAUI */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index, + comphy_mode); + + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + if (comphy_index == 2) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET, + COMMON_PHY_SD_CTRL1_RXAUI0_MASK); + } + if (comphy_index == 4) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET, + COMMON_PHY_SD_CTRL1_RXAUI1_MASK); + } + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, + 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET, + HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK); + + /* Set analog parameters from ETP(HW) */ + debug("stage: Analog parameters from ETP(HW)\n"); + /* SERDES External Configuration 2 */ + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, + 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET, + SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK); + /* 0x7-DFE Resolution control */ + reg_set(hpipe_addr + HPIPE_DFE_REG0, 0x1 << HPIPE_DFE_RES_FORCE_OFFSET, + HPIPE_DFE_RES_FORCE_MASK); + /* 0xd-G1_Setting_0 */ + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, + 0xd << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, + HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); + /* 0xE-G1_Setting_1 */ + mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + /* 0xA-DFE_Reg3 */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* 0x111-G1_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000, REG_32BIT); + if (data != 0) { + debug("Read from reg = %lx - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + ERROR("SD_EXTERNAL_STATUS0_PLL_RX is %d, -\"-_PLL_TX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); + ret = -ETIMEDOUT; + } + + /* RX init */ + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, + 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET, + SD_EXTERNAL_CONFIG1_RX_INIT_MASK); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100, REG_32BIT); + if (data != 0) { + debug("Read from reg = %lx - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + ERROR("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); + ret = -ETIMEDOUT; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_usb3_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uintptr_t hpipe_addr, comphy_addr, addr; + uint32_t mask, data; + uint8_t ap_nr, cp_nr, phy_polarity_invert; + int ret = 0; + + debug_enter(); + + /* Configure PIPE selector for USB3 */ + mvebu_cp110_comphy_set_pipe_selector(comphy_base, comphy_index, + comphy_mode); + + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + const struct usb_params *usb_static_values = + &usb_static_values_tab[ap_nr][cp_nr][comphy_index]; + + phy_polarity_invert = usb_static_values->polarity_invert; + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + mask |= COMMON_PHY_PHY_MODE_MASK; + data |= 0x1 << COMMON_PHY_PHY_MODE_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* release from hard reset */ + mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* Set PIPE soft reset */ + mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; + data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; + /* Set PHY datapath width mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; + /* Set Data bus width USB mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; + /* Set CORE_CLK output frequency for 250Mhz */ + mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); + /* Set PLL ready delay for 0x2 */ + reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, + 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET, + HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK); + /* Set reference clock to come from group 1 - 25Mhz */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Set reference frequcency select - 0x2 */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + /* Set PHY mode to USB - 0x5 */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x5 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Set the amount of time spent in the LoZ state - set for 0x7 */ + reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, + 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, + HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); + /* Set max PHY generation setting - 5Gbps */ + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, + 0x1 << HPIPE_INTERFACE_GEN_MAX_OFFSET, + HPIPE_INTERFACE_GEN_MAX_MASK); + /* Set select data width 20Bit (SEL_BITS[2:0]) */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, + HPIPE_LOOPBACK_SEL_MASK); + /* select de-emphasize 3.5db */ + reg_set(hpipe_addr + HPIPE_LANE_CONFIG0_REG, + 0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET, + HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK); + /* override tx margining from the MAC */ + reg_set(hpipe_addr + HPIPE_TST_MODE_CTRL_REG, + 0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET, + HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK); + + /* The polarity inversion for USB was not tested due to lack of hw + * design which requires it. Support is added for customer needs. + */ + if (phy_polarity_invert) + mvebu_cp110_polarity_invert(hpipe_addr + HPIPE_SYNC_PATTERN_REG, + phy_polarity_invert); + + /* Start analog parameters from ETP(HW) */ + debug("stage: Analog parameters from ETP(HW)\n"); + /* Set Pin DFE_PAT_DIS -> Bit[1]: PIN_DFE_PAT_DIS = 0x0 */ + mask = HPIPE_LANE_CFG4_DFE_CTRL_MASK; + data = 0x1 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET; + /* Set Override PHY DFE control pins for 0x1 */ + mask |= HPIPE_LANE_CFG4_DFE_OVER_MASK; + data |= 0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET; + /* Set Spread Spectrum Clock Enable fot 0x1 */ + mask |= HPIPE_LANE_CFG4_SSC_CTRL_MASK; + data |= 0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); + /* Confifure SSC amplitude */ + mask = HPIPE_G2_TX_SSC_AMP_MASK; + data = 0x1f << HPIPE_G2_TX_SSC_AMP_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_2_REG, data, mask); + /* End of analog parameters */ + + debug("stage: Comphy power up\n"); + /* Release from PIPE soft reset */ + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, + 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, + HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); + + /* wait 15ms - for comphy calibration done */ + debug("stage: Check PLL\n"); + /* Read lane status */ + addr = hpipe_addr + HPIPE_LANE_STATUS1_REG; + data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000, REG_32BIT); + if (data != 0) { + debug("Read from reg = %lx - value = 0x%x\n", + hpipe_addr + HPIPE_LANE_STATUS1_REG, data); + ERROR("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); + ret = -ETIMEDOUT; + } + + debug_exit(); + + return ret; +} + +static void rx_pre_train(uint64_t comphy_base, uint8_t comphy_index) +{ + uintptr_t hpipe_addr; + uint32_t mask, data; + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + debug("rx_training preparation\n\n"); + + mask = HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK; + data = (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF); + mask |= HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK; + data |= (0x0 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF); + reg_set(hpipe_addr + HPIPE_TRX0_REG, data, mask); + + + mask = HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK; + data = (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF); + mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK; + data |= (0x0 << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF); + reg_set(hpipe_addr + HPIPE_TRX_REG2, data, mask); + + mask = HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK; + data = (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF); + reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask); + + mask = HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK; + data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF); + reg_set(hpipe_addr + HPIPE_CDR_CONTROL1_REG, data, mask); + + mask = HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK; + data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF); + reg_set(hpipe_addr + HPIPE_CDR_CONTROL2_REG, data, mask); + + mask = HPIPE_CRD_MIDPOINT_PHASE_OS_MASK; + data = (0x0 << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET); + reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask); + + mask = HPIPE_TRX_REG1_SUMFTAP_EN_MASK; + data = (0x38 << HPIPE_TRX_REG1_SUMFTAP_EN_OFF); + mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK; + data |= (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF); + reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask); +} + +int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base, + uint8_t comphy_index) +{ + uint32_t mask, data, timeout; + uint32_t g1_ffe_cap_sel, g1_ffe_res_sel, align90, g1_dfe_res; + uintptr_t hpipe_addr; + + uint8_t ap_nr, cp_nr; + + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + debug_enter(); + + rx_pre_train(comphy_base, comphy_index); + + debug("Preparation for rx_training\n\n"); + + /* Use the FFE table */ + mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data = 0 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Use auto-calibration value */ + mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK; + data = 0 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, + data, mask); + + /* Use Tx/Rx training results */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + debug("Enable RX training\n\n"); + + mask = HPIPE_TRX_RX_TRAIN_EN_MASK; + data = 0x1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask); + + /* Check the result of RX training */ + timeout = RX_TRAINING_TIMEOUT; + mask = HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET | + HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET | + HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_MASK; + while (timeout) { + data = mmio_read_32(hpipe_addr + HPIPE_INTERRUPT_1_REGISTER); + if (data & mask) + break; + mdelay(1); + timeout--; + } + + debug("RX training result: interrupt reg 0x%lx = 0x%x\n\n", + hpipe_addr + HPIPE_INTERRUPT_1_REGISTER, data); + + if (timeout == 0 || data & HPIPE_TRX_TRAIN_TIME_OUT_INT_MASK) { + ERROR("Rx training timeout...\n"); + return -ETIMEDOUT; + } + + if (data & HPIPE_TRX_TRAIN_FAILED_MASK) { + ERROR("Rx training failed...\n"); + return -EINVAL; + } + + mask = HPIPE_TRX_RX_TRAIN_EN_MASK; + data = 0x0 << HPIPE_TRX_RX_TRAIN_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask); + + debug("Training done, reading results...\n\n"); + + mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_MASK; + g1_ffe_res_sel = ((mmio_read_32(hpipe_addr + + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG) + & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET); + + mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_MASK; + g1_ffe_cap_sel = ((mmio_read_32(hpipe_addr + + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG) + & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET); + + mask = HPIPE_DATA_PHASE_ADAPTED_OS_PH_MASK; + align90 = ((mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG) + & mask) >> HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET); + + mask = HPIPE_ADAPTED_DFE_RES_MASK; + g1_dfe_res = ((mmio_read_32(hpipe_addr + + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG) + & mask) >> HPIPE_ADAPTED_DFE_RES_OFFSET); + + debug("================================================\n"); + debug("Switching to static configuration:\n"); + debug("FFE_RES = 0x%x FFE_CAP = 0x%x align90 = 0x%x g1_dfe_res 0x%x\n", + g1_ffe_res_sel, g1_ffe_cap_sel, align90, g1_dfe_res); + debug("Result after training: 0x%lx= 0x%x, 0x%lx= 0x%x, 0x%lx = 0x%x\n", + (hpipe_addr + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG), + mmio_read_32(hpipe_addr + + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG), + (hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG), + mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG), + (hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG), + mmio_read_32(hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG)); + debug("================================================\n"); + + /* Update FFE_RES */ + mask = HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; + data = g1_ffe_res_sel << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Update FFE_CAP */ + mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; + data = g1_ffe_cap_sel << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Bypass the FFE table settings and use the FFE settings directly from + * registers FFE_RES_SEL and FFE_CAP_SEL + */ + mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data = 1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Force DFE resolution (use gen table value) */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* 0x111-G1 DFE_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = g1_dfe_res << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + + printf("########################################################\n"); + printf("# To use trained values update the ATF sources:\n"); + printf("# plat/marvell/armada/a8k//board/phy-porting-layer.h "); + printf("file\n# with new values as below (for appropriate AP nr %d", + ap_nr); + printf("and CP nr: %d comphy_index %d\n\n", + cp_nr, comphy_index); + printf("static struct xfi_params xfi_static_values_tab[AP_NUM]"); + printf("[CP_NUM][MAX_LANE_NR] = {\n"); + printf("\t...\n"); + printf("\t.g1_ffe_res_sel = 0x%x,\n", g1_ffe_res_sel); + printf("\t.g1_ffe_cap_sel = 0x%x,\n", g1_ffe_cap_sel); + printf("\t.align90 = 0x%x,\n", align90); + printf("\t.g1_dfe_res = 0x%x\n", g1_dfe_res); + printf("\t...\n"); + printf("};\n\n"); + printf("########################################################\n"); + + rx_trainng_done[ap_nr][cp_nr][comphy_index] = 1; + + return 0; +} + +/* During AP the proper mode is auto-negotiated and the mac, pcs and serdes + * configuration are done by the firmware loaded to the MG's CM3 for appropriate + * negotiated mode. Therefore there is no need to configure the mac, pcs and + * serdes from u-boot. The only thing that need to be setup is powering up + * the comphy, which is done through Common PHY Configuration 1 Register + * (CP0: 0xF2441000, CP1: 0xF4441000). This step can't be done by MG's CM3, + * since it doesn't have an access to this register-set (but it has access to + * the network registers like: MG, AP, MAC, PCS, Serdes etc.) + */ +static int mvebu_cp110_comphy_ap_power_on(uint64_t comphy_base, + uint8_t comphy_index, + uint32_t comphy_mode) +{ + uint32_t mask, data; + uintptr_t comphy_addr = comphy_addr = + COMPHY_ADDR(comphy_base, comphy_index); + + /* configure phy selector for XFI/SFI */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index, + comphy_mode); + debug_enter(); + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + debug_exit(); + +#if MSS_SUPPORT + do { + uint8_t ap_nr, cp_nr; + + /* start ap fw */ + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + mg_start_ap_fw(cp_nr, comphy_index); + + } while (0); +#endif + return 0; +} + +/* + * This function allows to reset the digital synchronizers between + * the MAC and the PHY, it is required when the MAC changes its state. + */ +int mvebu_cp110_comphy_digital_reset(uint64_t comphy_base, + uint8_t comphy_index, + uint32_t comphy_mode, uint32_t command) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + uintptr_t sd_ip_addr; + uint32_t mask, data; + + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + switch (mode) { + case (COMPHY_SGMII_MODE): + case (COMPHY_2500BASEX_MODE): + case (COMPHY_XFI_MODE): + case (COMPHY_SFI_MODE): + case (COMPHY_RXAUI_MODE): + mask = SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data = ((command == COMPHY_COMMAND_DIGITAL_PWR_OFF) ? + 0x0 : 0x1) << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + break; + default: + ERROR("comphy%d: Digital PWR ON/OFF is not supported\n", + comphy_index); + return -EINVAL; + } + + return 0; +} + +int mvebu_cp110_comphy_power_on(uint64_t comphy_base, + uint8_t comphy_index, + uint64_t comphy_mode, + uint64_t comphy_train_base) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + int err = 0; + + debug_enter(); + + switch (mode) { + case(COMPHY_SATA_MODE): + err = mvebu_cp110_comphy_sata_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + case(COMPHY_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): + err = mvebu_cp110_comphy_sgmii_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + /* From comphy perspective, XFI and SFI are the same */ + case (COMPHY_XFI_MODE): + case (COMPHY_SFI_MODE): + err = mvebu_cp110_comphy_xfi_power_on(comphy_base, + comphy_index, + comphy_mode, + comphy_train_base); + break; + case (COMPHY_PCIE_MODE): + err = mvebu_cp110_comphy_pcie_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + case (COMPHY_RXAUI_MODE): + err = mvebu_cp110_comphy_rxaui_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + case (COMPHY_USB3H_MODE): + case (COMPHY_USB3D_MODE): + err = mvebu_cp110_comphy_usb3_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + case (COMPHY_AP_MODE): + err = mvebu_cp110_comphy_ap_power_on(comphy_base, comphy_index, + comphy_mode); + break; + default: + ERROR("comphy%d: unsupported comphy mode\n", comphy_index); + err = -EINVAL; + break; + } + + debug_exit(); + + return err; +} + +int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index, + uint64_t comphy_mode) +{ + uintptr_t sd_ip_addr, comphy_ip_addr; + uint32_t mask, data; + uint8_t ap_nr, cp_nr; + _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode); + + debug_enter(); + + /* Power-off might happen because of 2 things: + * 1. Bootloader turns off unconnected lanes + * 2. Linux turns off all lanes during boot + * (and then reconfigure it). + * + * For PCIe, there's a problem: + * In Armada 8K DB boards, PCIe initialization can be executed + * only once (PCIe reset performed during chip power on and + * it cannot be executed via GPIO later) so a lane configured to + * PCIe should not be powered off by Linux. + * + * So, check 2 things: + * 1. Is Linux called for power-off? + * 2. Is the comphy configured to PCIe? + * If the answer is YES for both 1 and 2, skip the power-off. + * + * TODO: In MacciatoBIN, PCIe reset is connected via GPIO, + * so after GPIO reset is added to Linux Kernel, it can be + * powered-off. + */ + if (!called_from_uboot) { + data = mmio_read_32(comphy_base + + COMMON_SELECTOR_PIPE_REG_OFFSET); + data >>= (COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index); + data &= COMMON_SELECTOR_COMPHY_MASK; + if (data == COMMON_SELECTOR_PIPE_COMPHY_PCIE) + return 0; + } + + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) { + debug("Skip %s for comphy[%d][%d][%d], due to rx training\n", + __func__, ap_nr, cp_nr, comphy_index); + return 0; + } + + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_ip_addr = COMPHY_ADDR(comphy_base, comphy_index); + + /* Hard reset the comphy, for Ethernet modes and Sata */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* PCIe reset */ + spin_lock(&cp110_mac_reset_lock); + + /* The mvebu_cp110_comphy_power_off will be called only from Linux (to + * override settings done by bootloader) and it will be relevant only + * to PCIe (called before check if to skip pcie power off or not). + */ + data = mmio_read_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) + + SYS_CTRL_UINIT_SOFT_RESET_REG); + switch (comphy_index) { + case COMPHY_LANE0: + data &= ~PCIE_MAC_RESET_MASK_PORT0; + break; + case COMPHY_LANE4: + data &= ~PCIE_MAC_RESET_MASK_PORT1; + break; + case COMPHY_LANE5: + data &= ~PCIE_MAC_RESET_MASK_PORT2; + break; + } + + mmio_write_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) + + SYS_CTRL_UINIT_SOFT_RESET_REG, data); + spin_unlock(&cp110_mac_reset_lock); + + /* Hard reset the comphy, for PCIe and usb3 */ + mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data = 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_ip_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Clear comphy PHY and PIPE selector, can't rely on previous config. */ + mvebu_cp110_comphy_clr_phy_selector(comphy_base, comphy_index); + mvebu_cp110_comphy_clr_pipe_selector(comphy_base, comphy_index); + + debug_exit(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h new file mode 100644 index 0000000..0be6c26 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Those are parameters for xfi mode, which need to be tune for each board type. + * For known DB boards the parameters was already calibrated and placed under + * the plat/marvell/armada/a8k//board/phy-porting-layer.h + */ +struct xfi_params { + uint8_t g1_ffe_res_sel; + uint8_t g1_ffe_cap_sel; + uint8_t align90; + uint8_t g1_dfe_res; + uint8_t g1_amp; + uint8_t g1_emph; + uint8_t g1_emph_en; + uint8_t g1_tx_amp_adj; + uint8_t g1_tx_emph_en; + uint8_t g1_tx_emph; + uint8_t g1_rx_selmuff; + uint8_t g1_rx_selmufi; + uint8_t g1_rx_selmupf; + uint8_t g1_rx_selmupi; + _Bool valid; +}; + +struct sata_params { + uint8_t g1_amp; + uint8_t g2_amp; + uint8_t g3_amp; + + uint8_t g1_emph; + uint8_t g2_emph; + uint8_t g3_emph; + + uint8_t g1_emph_en; + uint8_t g2_emph_en; + uint8_t g3_emph_en; + + uint8_t g1_tx_amp_adj; + uint8_t g2_tx_amp_adj; + uint8_t g3_tx_amp_adj; + + uint8_t g1_tx_emph_en; + uint8_t g2_tx_emph_en; + uint8_t g3_tx_emph_en; + + uint8_t g1_tx_emph; + uint8_t g2_tx_emph; + uint8_t g3_tx_emph; + + uint8_t g3_dfe_res; + + uint8_t g3_ffe_res_sel; + + uint8_t g3_ffe_cap_sel; + + uint8_t align90; + + uint8_t g1_rx_selmuff; + uint8_t g2_rx_selmuff; + uint8_t g3_rx_selmuff; + + uint8_t g1_rx_selmufi; + uint8_t g2_rx_selmufi; + uint8_t g3_rx_selmufi; + + uint8_t g1_rx_selmupf; + uint8_t g2_rx_selmupf; + uint8_t g3_rx_selmupf; + + uint8_t g1_rx_selmupi; + uint8_t g2_rx_selmupi; + uint8_t g3_rx_selmupi; + + uint8_t polarity_invert; + + _Bool valid; +}; + +struct usb_params { + uint8_t polarity_invert; +}; + +int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base, + uint8_t comphy_index); +int mvebu_cp110_comphy_power_off(uint64_t comphy_base, + uint8_t comphy_index, uint64_t comphy_mode); +int mvebu_cp110_comphy_power_on(uint64_t comphy_base, uint8_t comphy_index, + uint64_t comphy_mode, + uint64_t comphy_train_base); +int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base, + uint8_t comphy_index); +int mvebu_cp110_comphy_digital_reset(uint64_t comphy_base, uint8_t comphy_index, + uint32_t comphy_mode, uint32_t command); + +#define COMPHY_POLARITY_NO_INVERT 0 +#define COMPHY_POLARITY_TXD_INVERT 1 +#define COMPHY_POLARITY_RXD_INVERT 2 diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h b/arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h new file mode 100644 index 0000000..3c63c64 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PHY_DEFAULT_PORTING_LAYER_H +#define PHY_DEFAULT_PORTING_LAYER_H + + +#define MAX_LANE_NR 6 + +#warning "Using default comphy params - you may need to suit them to your board" + +static const struct xfi_params + xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = { + .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, .g1_tx_emph_en = 0x1, + .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, .valid = 1 + } +}; + +static const struct sata_params + sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = { + .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e, + .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe, + .g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1, + .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, + .g3_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, + .g3_tx_emph_en = 0x0, + .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1, + .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf, + .align90 = 0x61, + .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, + .g3_rx_selmuff = 0x3, + .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, + .g3_rx_selmufi = 0x3, + .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, + .g3_rx_selmupf = 0x2, + .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, + .g3_rx_selmupi = 0x2, + .polarity_invert = COMPHY_POLARITY_NO_INVERT, + .valid = 0x1 + }, +}; + +static const struct usb_params + usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = { + .polarity_invert = COMPHY_POLARITY_NO_INVERT + }, +}; +#endif /* PHY_DEFAULT_PORTING_LAYER_H */ diff --git a/arm-trusted-firmware/drivers/marvell/ddr_phy_access.c b/arm-trusted-firmware/drivers/marvell/ddr_phy_access.c new file mode 100644 index 0000000..352d1ef --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/ddr_phy_access.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include "ddr_phy_access.h" +#include +#include +#include + +#define DDR_PHY_END_ADDRESS 0x100000 + +#ifdef DDR_PHY_DEBUG +#define debug_printf(...) printf(__VA_ARGS__) +#else +#define debug_printf(...) +#endif + + +/* + * This routine writes 'data' to specified 'address' offset, + * with optional debug print support + */ +int snps_fw_write(uintptr_t offset, uint16_t data) +{ + debug_printf("In %s\n", __func__); + + if (offset < DDR_PHY_END_ADDRESS) { + mmio_write_16(DDR_PHY_BASE_ADDR + (2 * offset), data); + return 0; + } + debug_printf("%s: illegal offset value: 0x%x\n", __func__, offset); + return -EINVAL; +} + +int snps_fw_read(uintptr_t offset, uint16_t *read) +{ + debug_printf("In %s\n", __func__); + + if (offset < DDR_PHY_END_ADDRESS) { + *read = mmio_read_16(DDR_PHY_BASE_ADDR + (2 * offset)); + return 0; + } + debug_printf("%s: illegal offset value: 0x%x\n", __func__, offset); + return -EINVAL; +} + +int mvebu_ddr_phy_write(uintptr_t offset, uint16_t data) +{ + return snps_fw_write(offset, data); +} + +int mvebu_ddr_phy_read(uintptr_t offset, uint16_t *read) +{ + return snps_fw_read(offset, read); +} diff --git a/arm-trusted-firmware/drivers/marvell/ddr_phy_access.h b/arm-trusted-firmware/drivers/marvell/ddr_phy_access.h new file mode 100644 index 0000000..5f9a668 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/ddr_phy_access.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#define DEVICE_BASE 0xF0000000 +#define DDR_PHY_OFFSET 0x1000000 +#define DDR_PHY_BASE_ADDR (DEVICE_BASE + DDR_PHY_OFFSET) + +int mvebu_ddr_phy_write(uintptr_t offset, uint16_t data); +int mvebu_ddr_phy_read(uintptr_t offset, uint16_t *read); diff --git a/arm-trusted-firmware/drivers/marvell/gwin.c b/arm-trusted-firmware/drivers/marvell/gwin.c new file mode 100644 index 0000000..fa59cb0 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/gwin.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* GWIN unit device driver for Marvell AP810 SoC */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) +#define WIN_TARGET_MASK (0xF) +#define WIN_TARGET_SHIFT (0x8) +#define WIN_TARGET(tgt) (((tgt) & WIN_TARGET_MASK) \ + << WIN_TARGET_SHIFT) + +/* Bits[43:26] of the physical address are the window base, + * which is aligned to 64MB + */ +#define ADDRESS_RSHIFT (26) +#define ADDRESS_LSHIFT (10) +#define GWIN_ALIGNMENT_64M (0x4000000) + +/* AP registers */ +#define GWIN_CR_OFFSET(ap, win) (MVEBU_GWIN_BASE(ap) + 0x0 + \ + (0x10 * (win))) +#define GWIN_ALR_OFFSET(ap, win) (MVEBU_GWIN_BASE(ap) + 0x8 + \ + (0x10 * (win))) +#define GWIN_AHR_OFFSET(ap, win) (MVEBU_GWIN_BASE(ap) + 0xc + \ + (0x10 * (win))) + +#define CCU_GRU_CR_OFFSET(ap) (MVEBU_CCU_GRU_BASE(ap)) +#define CCR_GRU_CR_GWIN_MBYPASS (1 << 1) + +static void gwin_check(struct addr_map_win *win) +{ + /* The base is always 64M aligned */ + if (IS_NOT_ALIGN(win->base_addr, GWIN_ALIGNMENT_64M)) { + win->base_addr &= ~(GWIN_ALIGNMENT_64M - 1); + NOTICE("%s: Align the base address to 0x%" PRIx64 "\n", + __func__, win->base_addr); + } + + /* size parameter validity check */ + if (IS_NOT_ALIGN(win->win_size, GWIN_ALIGNMENT_64M)) { + win->win_size = ALIGN_UP(win->win_size, GWIN_ALIGNMENT_64M); + NOTICE("%s: Aligning window size to 0x%" PRIx64 "\n", + __func__, win->win_size); + } +} + +static void gwin_enable_window(int ap_index, struct addr_map_win *win, + uint32_t win_num) +{ + uint32_t alr, ahr; + uint64_t end_addr; + + if ((win->target_id & WIN_TARGET_MASK) != win->target_id) { + ERROR("target ID = %d, is invalid\n", win->target_id); + return; + } + + /* calculate 64bit end-address */ + end_addr = (win->base_addr + win->win_size - 1); + + alr = (uint32_t)((win->base_addr >> ADDRESS_RSHIFT) << ADDRESS_LSHIFT); + ahr = (uint32_t)((end_addr >> ADDRESS_RSHIFT) << ADDRESS_LSHIFT); + + /* write start address and end address for GWIN */ + mmio_write_32(GWIN_ALR_OFFSET(ap_index, win_num), alr); + mmio_write_32(GWIN_AHR_OFFSET(ap_index, win_num), ahr); + + /* write the target ID and enable the window */ + mmio_write_32(GWIN_CR_OFFSET(ap_index, win_num), + WIN_TARGET(win->target_id) | WIN_ENABLE_BIT); +} + +static void gwin_disable_window(int ap_index, uint32_t win_num) +{ + uint32_t win_reg; + + win_reg = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_num)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(GWIN_CR_OFFSET(ap_index, win_num), win_reg); +} + +/* Insert/Remove temporary window for using the out-of reset default + * CPx base address to access the CP configuration space prior to + * the further base address update in accordance with address mapping + * design. + * + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void gwin_temp_win_insert(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + win_id = MVEBU_GWIN_MAX_WINS - i - 1; + gwin_check(win); + gwin_enable_window(ap_index, win, win_id); + win++; + } +} + +/* + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void gwin_temp_win_remove(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + uint64_t base; + uint32_t target; + + win_id = MVEBU_GWIN_MAX_WINS - i - 1; + + target = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_id)); + target >>= WIN_TARGET_SHIFT; + target &= WIN_TARGET_MASK; + + base = mmio_read_32(GWIN_ALR_OFFSET(ap_index, win_id)); + base >>= ADDRESS_LSHIFT; + base <<= ADDRESS_RSHIFT; + + if (win->target_id != target) { + ERROR("%s: Trying to remove bad window-%d!\n", + __func__, win_id); + continue; + } + gwin_disable_window(ap_index, win_id); + win++; + } +} + +#ifdef DEBUG_ADDR_MAP +static void dump_gwin(int ap_index) +{ + uint32_t win_num; + + /* Dump all GWIN windows */ + printf("\tbank target start end\n"); + printf("\t----------------------------------------------------\n"); + for (win_num = 0; win_num < MVEBU_GWIN_MAX_WINS; win_num++) { + uint32_t cr; + uint64_t alr, ahr; + + cr = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_num)); + /* Window enabled */ + if (cr & WIN_ENABLE_BIT) { + alr = mmio_read_32(GWIN_ALR_OFFSET(ap_index, win_num)); + alr = (alr >> ADDRESS_LSHIFT) << ADDRESS_RSHIFT; + ahr = mmio_read_32(GWIN_AHR_OFFSET(ap_index, win_num)); + ahr = (ahr >> ADDRESS_LSHIFT) << ADDRESS_RSHIFT; + printf("\tgwin %d 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + (cr >> 8) & 0xF, alr, ahr); + } + } +} +#endif + +int init_gwin(int ap_index) +{ + struct addr_map_win *win; + uint32_t win_id; + uint32_t win_count; + uint32_t win_reg; + + INFO("Initializing GWIN Address decoding\n"); + + /* Get the array of the windows and its size */ + marvell_get_gwin_memory_map(ap_index, &win, &win_count); + if (win_count <= 0) { + INFO("no windows configurations found\n"); + return 0; + } + + if (win_count > MVEBU_GWIN_MAX_WINS) { + ERROR("number of windows is bigger than %d\n", + MVEBU_GWIN_MAX_WINS); + return 0; + } + + /* disable all windows */ + for (win_id = 0; win_id < MVEBU_GWIN_MAX_WINS; win_id++) + gwin_disable_window(ap_index, win_id); + + /* enable relevant windows */ + for (win_id = 0; win_id < win_count; win_id++, win++) { + gwin_check(win); + gwin_enable_window(ap_index, win, win_id); + } + + /* GWIN Miss feature has not verified, therefore any access towards + * remote AP should be accompanied with proper configuration to + * GWIN registers group and therefore the GWIN Miss feature + * should be set into Bypass mode, need to make sure all GWIN regions + * are defined correctly that will assure no GWIN miss occurrance + * JIRA-AURORA2-1630 + */ + INFO("Update GWIN miss bypass\n"); + win_reg = mmio_read_32(CCU_GRU_CR_OFFSET(ap_index)); + win_reg |= CCR_GRU_CR_GWIN_MBYPASS; + mmio_write_32(CCU_GRU_CR_OFFSET(ap_index), win_reg); + +#ifdef DEBUG_ADDR_MAP + dump_gwin(ap_index); +#endif + + INFO("Done GWIN Address decoding Initializing\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/io_win.c b/arm-trusted-firmware/drivers/marvell/io_win.c new file mode 100644 index 0000000..124382a --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/io_win.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* IO Window unit device driver for Marvell AP807, AP807 and AP810 SoCs */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) +/* Physical address of the base of the window = {Addr[19:0],20`h0} */ +#define ADDRESS_SHIFT (20 - 4) +#define ADDRESS_MASK (0xFFFFFFF0) +#define IO_WIN_ALIGNMENT_1M (0x100000) +#define IO_WIN_ALIGNMENT_64K (0x10000) + +/* AP registers */ +#define IO_WIN_ALR_OFFSET(ap, win) (MVEBU_IO_WIN_BASE(ap) + 0x0 + \ + (0x10 * win)) +#define IO_WIN_AHR_OFFSET(ap, win) (MVEBU_IO_WIN_BASE(ap) + 0x8 + \ + (0x10 * win)) +#define IO_WIN_CR_OFFSET(ap, win) (MVEBU_IO_WIN_BASE(ap) + 0xC + \ + (0x10 * win)) + +/* For storage of CR, ALR, AHR abd GCR */ +static uint32_t io_win_regs_save[MVEBU_IO_WIN_MAX_WINS * 3 + 1]; + +static void io_win_check(struct addr_map_win *win) +{ + /* for IO The base is always 1M aligned */ + /* check if address is aligned to 1M */ + if (IS_NOT_ALIGN(win->base_addr, IO_WIN_ALIGNMENT_1M)) { + win->base_addr = ALIGN_UP(win->base_addr, IO_WIN_ALIGNMENT_1M); + NOTICE("%s: Align up the base address to 0x%" PRIx64 "\n", + __func__, win->base_addr); + } + + /* size parameter validity check */ + if (IS_NOT_ALIGN(win->win_size, IO_WIN_ALIGNMENT_1M)) { + win->win_size = ALIGN_UP(win->win_size, IO_WIN_ALIGNMENT_1M); + NOTICE("%s: Aligning size to 0x%" PRIx64 "\n", + __func__, win->win_size); + } +} + +static void io_win_enable_window(int ap_index, struct addr_map_win *win, + uint32_t win_num) +{ + uint32_t alr, ahr; + uint64_t end_addr; + + if (win->target_id < 0 || win->target_id >= MVEBU_IO_WIN_MAX_WINS) { + ERROR("target ID = %d, is invalid\n", win->target_id); + return; + } + + if ((win_num == 0) || (win_num > MVEBU_IO_WIN_MAX_WINS)) { + ERROR("Enabling wrong IOW window %d!\n", win_num); + return; + } + + /* calculate the end-address */ + end_addr = (win->base_addr + win->win_size - 1); + + alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + alr |= WIN_ENABLE_BIT; + ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + + /* write start address and end address for IO window */ + mmio_write_32(IO_WIN_ALR_OFFSET(ap_index, win_num), alr); + mmio_write_32(IO_WIN_AHR_OFFSET(ap_index, win_num), ahr); + + /* write window target */ + mmio_write_32(IO_WIN_CR_OFFSET(ap_index, win_num), win->target_id); +} + +static void io_win_disable_window(int ap_index, uint32_t win_num) +{ + uint32_t win_reg; + + if ((win_num == 0) || (win_num > MVEBU_IO_WIN_MAX_WINS)) { + ERROR("Disabling wrong IOW window %d!\n", win_num); + return; + } + + win_reg = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_num)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(IO_WIN_ALR_OFFSET(ap_index, win_num), win_reg); +} + +/* Insert/Remove temporary window for using the out-of reset default + * CPx base address to access the CP configuration space prior to + * the further base address update in accordance with address mapping + * design. + * + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void iow_temp_win_insert(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + win_id = MVEBU_IO_WIN_MAX_WINS - i - 1; + io_win_check(win); + io_win_enable_window(ap_index, win, win_id); + win++; + } +} + +/* + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void iow_temp_win_remove(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + /* Start from the last window and do not touch Win0 */ + for (int i = 0; i < size; i++) { + uint64_t base; + uint32_t target; + + win_id = MVEBU_IO_WIN_MAX_WINS - i - 1; + + target = mmio_read_32(IO_WIN_CR_OFFSET(ap_index, win_id)); + base = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_id)); + base &= ~WIN_ENABLE_BIT; + base <<= ADDRESS_SHIFT; + + if ((win->target_id != target) || (win->base_addr != base)) { + ERROR("%s: Trying to remove bad window-%d!\n", + __func__, win_id); + continue; + } + io_win_disable_window(ap_index, win_id); + win++; + } +} + +#ifdef DEBUG_ADDR_MAP +static void dump_io_win(int ap_index) +{ + uint32_t trgt_id, win_id; + uint32_t alr, ahr; + uint64_t start, end; + + /* Dump all IO windows */ + printf("\tbank target start end\n"); + printf("\t----------------------------------------------------\n"); + for (win_id = 0; win_id < MVEBU_IO_WIN_MAX_WINS; win_id++) { + alr = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_id)); + if (alr & WIN_ENABLE_BIT) { + alr &= ~WIN_ENABLE_BIT; + ahr = mmio_read_32(IO_WIN_AHR_OFFSET(ap_index, win_id)); + trgt_id = mmio_read_32(IO_WIN_CR_OFFSET(ap_index, + win_id)); + start = ((uint64_t)alr << ADDRESS_SHIFT); + end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); + printf("\tio-win %d 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + trgt_id, start, end); + } + } + printf("\tio-win gcr is %x\n", + mmio_read_32(MVEBU_IO_WIN_BASE(ap_index) + + MVEBU_IO_WIN_GCR_OFFSET)); +} +#endif + +static void iow_save_win_range(int ap_id, int win_first, int win_last, + uint32_t *buffer) +{ + int win_id, idx; + + /* Save IOW */ + for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { + buffer[idx++] = mmio_read_32(IO_WIN_CR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(IO_WIN_ALR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(IO_WIN_AHR_OFFSET(ap_id, win_id)); + } + buffer[idx] = mmio_read_32(MVEBU_IO_WIN_BASE(ap_id) + + MVEBU_IO_WIN_GCR_OFFSET); +} + +static void iow_restore_win_range(int ap_id, int win_first, int win_last, + uint32_t *buffer) +{ + int win_id, idx; + + /* Restore IOW */ + for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { + mmio_write_32(IO_WIN_CR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(IO_WIN_ALR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(IO_WIN_AHR_OFFSET(ap_id, win_id), buffer[idx++]); + } + mmio_write_32(MVEBU_IO_WIN_BASE(ap_id) + MVEBU_IO_WIN_GCR_OFFSET, + buffer[idx++]); +} + +void iow_save_win_all(int ap_id) +{ + iow_save_win_range(ap_id, 0, MVEBU_IO_WIN_MAX_WINS - 1, + io_win_regs_save); +} + +void iow_restore_win_all(int ap_id) +{ + iow_restore_win_range(ap_id, 0, MVEBU_IO_WIN_MAX_WINS - 1, + io_win_regs_save); +} + +int init_io_win(int ap_index) +{ + struct addr_map_win *win; + uint32_t win_id, win_reg; + uint32_t win_count; + + INFO("Initializing IO WIN Address decoding\n"); + + /* Get the array of the windows and its size */ + marvell_get_io_win_memory_map(ap_index, &win, &win_count); + if (win_count <= 0) + INFO("no windows configurations found\n"); + + if (win_count > MVEBU_IO_WIN_MAX_WINS) { + INFO("number of windows is bigger than %d\n", + MVEBU_IO_WIN_MAX_WINS); + return 0; + } + + /* Get the default target id to set the GCR */ + win_reg = marvell_get_io_win_gcr_target(ap_index); + mmio_write_32(MVEBU_IO_WIN_BASE(ap_index) + MVEBU_IO_WIN_GCR_OFFSET, + win_reg); + + /* disable all IO windows */ + for (win_id = 1; win_id < MVEBU_IO_WIN_MAX_WINS; win_id++) + io_win_disable_window(ap_index, win_id); + + /* enable relevant windows, starting from win_id = 1 because + * index 0 dedicated for BootROM + */ + for (win_id = 1; win_id <= win_count; win_id++, win++) { + io_win_check(win); + io_win_enable_window(ap_index, win, win_id); + } + +#ifdef DEBUG_ADDR_MAP + dump_io_win(ap_index); +#endif + + INFO("Done IO WIN Address decoding Initializing\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/iob.c b/arm-trusted-firmware/drivers/marvell/iob.c new file mode 100644 index 0000000..1f39395 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/iob.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2016 - 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* IOW unit device driver for Marvell CP110 and CP115 SoCs */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +#define MVEBU_IOB_OFFSET (0x190000) +#define MVEBU_IOB_MAX_WINS 16 + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) +/* Physical address of the base of the window = {AddrLow[19:0],20`h0} */ +#define ADDRESS_SHIFT (20 - 4) +#define ADDRESS_MASK (0xFFFFFFF0) +#define IOB_WIN_ALIGNMENT (0x100000) + +/* IOB registers */ +#define IOB_WIN_CR_OFFSET(win) (iob_base + 0x0 + (0x20 * win)) +#define IOB_TARGET_ID_OFFSET (8) +#define IOB_TARGET_ID_MASK (0xF) + +#define IOB_WIN_SCR_OFFSET(win) (iob_base + 0x4 + (0x20 * win)) +#define IOB_WIN_ENA_CTRL_WRITE_SECURE (0x1) +#define IOB_WIN_ENA_CTRL_READ_SECURE (0x2) +#define IOB_WIN_ENA_WRITE_SECURE (0x4) +#define IOB_WIN_ENA_READ_SECURE (0x8) + +#define IOB_WIN_ALR_OFFSET(win) (iob_base + 0x8 + (0x20 * win)) +#define IOB_WIN_AHR_OFFSET(win) (iob_base + 0xC + (0x20 * win)) + +#define IOB_WIN_DIOB_CR_OFFSET(win) (iob_base + 0x10 + (0x20 * win)) +#define IOB_WIN_XOR0_DIOB_EN BIT(0) +#define IOB_WIN_XOR1_DIOB_EN BIT(1) + +uintptr_t iob_base; + +static void iob_win_check(struct addr_map_win *win, uint32_t win_num) +{ + /* check if address is aligned to the size */ + if (IS_NOT_ALIGN(win->base_addr, IOB_WIN_ALIGNMENT)) { + win->base_addr = ALIGN_UP(win->base_addr, IOB_WIN_ALIGNMENT); + ERROR("Window %d: base address unaligned to 0x%x\n", + win_num, IOB_WIN_ALIGNMENT); + printf("Align up the base address to 0x%" PRIx64 "\n", + win->base_addr); + } + + /* size parameter validity check */ + if (IS_NOT_ALIGN(win->win_size, IOB_WIN_ALIGNMENT)) { + win->win_size = ALIGN_UP(win->win_size, IOB_WIN_ALIGNMENT); + ERROR("Window %d: window size unaligned to 0x%x\n", win_num, + IOB_WIN_ALIGNMENT); + printf("Aligning size to 0x%" PRIx64 "\n", win->win_size); + } +} + +static void iob_enable_win(struct addr_map_win *win, uint32_t win_id) +{ + uint32_t iob_win_reg; + uint32_t alr, ahr; + uint64_t end_addr; + uint32_t reg_en; + + /* move XOR (DMA) to use WIN1 which is used for PCI-EP address space */ + reg_en = IOB_WIN_XOR0_DIOB_EN | IOB_WIN_XOR1_DIOB_EN; + iob_win_reg = mmio_read_32(IOB_WIN_DIOB_CR_OFFSET(0)); + iob_win_reg &= ~reg_en; + mmio_write_32(IOB_WIN_DIOB_CR_OFFSET(0), iob_win_reg); + + iob_win_reg = mmio_read_32(IOB_WIN_DIOB_CR_OFFSET(1)); + iob_win_reg |= reg_en; + mmio_write_32(IOB_WIN_DIOB_CR_OFFSET(1), iob_win_reg); + + end_addr = (win->base_addr + win->win_size - 1); + alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + + mmio_write_32(IOB_WIN_ALR_OFFSET(win_id), alr); + mmio_write_32(IOB_WIN_AHR_OFFSET(win_id), ahr); + + iob_win_reg = WIN_ENABLE_BIT; + iob_win_reg |= (win->target_id & IOB_TARGET_ID_MASK) + << IOB_TARGET_ID_OFFSET; + mmio_write_32(IOB_WIN_CR_OFFSET(win_id), iob_win_reg); + +} + +#ifdef DEBUG_ADDR_MAP +static void dump_iob(void) +{ + uint32_t win_id, win_cr, alr, ahr; + uint8_t target_id; + uint64_t start, end; + char *iob_target_name[IOB_MAX_TID] = { + "CFG ", "MCI0 ", "PEX1 ", "PEX2 ", + "PEX0 ", "NAND ", "RUNIT", "MCI1 " }; + + /* Dump all IOB windows */ + printf("bank id target start end\n"); + printf("----------------------------------------------------\n"); + for (win_id = 0; win_id < MVEBU_IOB_MAX_WINS; win_id++) { + win_cr = mmio_read_32(IOB_WIN_CR_OFFSET(win_id)); + if (win_cr & WIN_ENABLE_BIT) { + target_id = (win_cr >> IOB_TARGET_ID_OFFSET) & + IOB_TARGET_ID_MASK; + alr = mmio_read_32(IOB_WIN_ALR_OFFSET(win_id)); + start = ((uint64_t)alr << ADDRESS_SHIFT); + if (win_id != 0) { + ahr = mmio_read_32(IOB_WIN_AHR_OFFSET(win_id)); + end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); + } else { + /* Window #0 size is hardcoded to 16MB, as it's + * reserved for CP configuration space. + */ + end = start + (16 << 20); + } + printf("iob %02d %s 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + win_id, iob_target_name[target_id], + start, end); + } + } +} +#endif + +void iob_cfg_space_update(int ap_idx, int cp_idx, uintptr_t base, + uintptr_t new_base) +{ + debug_enter(); + + iob_base = base + MVEBU_IOB_OFFSET; + + NOTICE("Change the base address of AP%d-CP%d to %lx\n", + ap_idx, cp_idx, new_base); + mmio_write_32(IOB_WIN_ALR_OFFSET(0), new_base >> ADDRESS_SHIFT); + + iob_base = new_base + MVEBU_IOB_OFFSET; + + /* Make sure the address was configured by the CPU before + * any possible access to the CP. + */ + dsb(); + + debug_exit(); +} + +int init_iob(uintptr_t base) +{ + struct addr_map_win *win; + uint32_t win_id, win_reg; + uint32_t win_count; + + INFO("Initializing IOB Address decoding\n"); + + /* Get the base address of the address decoding MBUS */ + iob_base = base + MVEBU_IOB_OFFSET; + + /* Get the array of the windows and fill the map data */ + marvell_get_iob_memory_map(&win, &win_count, base); + if (win_count <= 0) { + INFO("no windows configurations found\n"); + return 0; + } else if (win_count > (MVEBU_IOB_MAX_WINS - 1)) { + ERROR("IOB mem map array > than max available windows (%d)\n", + MVEBU_IOB_MAX_WINS); + win_count = MVEBU_IOB_MAX_WINS; + } + + /* disable all IOB windows, start from win_id = 1 + * because can't disable internal register window + */ + for (win_id = 1; win_id < MVEBU_IOB_MAX_WINS; win_id++) { + win_reg = mmio_read_32(IOB_WIN_CR_OFFSET(win_id)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(IOB_WIN_CR_OFFSET(win_id), win_reg); + + win_reg = ~IOB_WIN_ENA_CTRL_WRITE_SECURE; + win_reg &= ~IOB_WIN_ENA_CTRL_READ_SECURE; + win_reg &= ~IOB_WIN_ENA_WRITE_SECURE; + win_reg &= ~IOB_WIN_ENA_READ_SECURE; + mmio_write_32(IOB_WIN_SCR_OFFSET(win_id), win_reg); + } + + for (win_id = 1; win_id < win_count + 1; win_id++, win++) { + iob_win_check(win, win_id); + iob_enable_win(win, win_id); + } + +#ifdef DEBUG_ADDR_MAP + dump_iob(); +#endif + + INFO("Done IOB Address decoding Initializing\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c b/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c new file mode 100644 index 0000000..648bd0e --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include +#include +#include + +#include + +#include "mc_trustzone.h" + +#define TZ_SIZE(x) ((x) >> 13) + +static int fls(int x) +{ + if (!x) + return 0; + + return 32 - __builtin_clz(x); +} + +/* To not duplicate types, the addr_map_win is used, but the "target" + * filed is referring to attributes instead of "target". + */ +void tz_enable_win(int ap_index, const struct addr_map_win *win, int win_id) +{ + int tz_size; + uint32_t val, base = win->base_addr; + + if ((win_id < 0) || (win_id > MVEBU_TZ_MAX_WINS)) { + ERROR("Enabling wrong MC TrustZone window %d!\n", win_id); + return; + } + + /* map the window size to trustzone register convention */ + tz_size = fls(TZ_SIZE(win->win_size)); + + VERBOSE("%s: window size = 0x%" PRIx64 " maps to tz_size %d\n", + __func__, win->win_size, tz_size); + if (tz_size < 0 || tz_size > 31) { + ERROR("Using not allowed size for MC TrustZone window %d!\n", + win_id); + return; + } + + if (base & 0xfff) { + base = base & ~0xfff; + WARN("Attempt to open MC TZ win. at 0x%" PRIx64 ", truncate to 0x%x\n", + win->base_addr, base); + } + + val = base | (tz_size << 7) | win->target_id | TZ_VALID; + + VERBOSE("%s: base 0x%x, tz_size moved 0x%x, attr 0x%x, val 0x%x\n", + __func__, base, (tz_size << 7), win->target_id, val); + + mmio_write_32(MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap_index, win_id), val); + + VERBOSE("%s: Win%d[0x%x] configured to 0x%x\n", __func__, win_id, + MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap_index, win_id), + mmio_read_32(MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap_index, win_id))); + + mmio_write_32(MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap_index, win_id), + (win->base_addr >> 32)); + + VERBOSE("%s: Win%d[0x%x] configured to 0x%x\n", __func__, win_id, + MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap_index, win_id), + mmio_read_32(MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap_index, win_id))); +} diff --git a/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h b/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h new file mode 100644 index 0000000..296dce8 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MC_TRUSTZONE_H +#define MC_TRUSTZONE_H + +#include + +#define MVEBU_TZ_MAX_WINS 16 + +#define TZ_VALID (1 << 0) +#define TZ_PERM(x) ((x) << 1) +#define TZ_RZ_ENABLE (1 << 3) + +/* tz attr definitions */ +#define TZ_PERM_RW (TZ_PERM(0)) +#define TZ_PERM_RO (TZ_PERM(1)) +#define TZ_PERM_WO (TZ_PERM(2)) +#define TZ_PERM_ABORT (TZ_PERM(3)) + +void tz_enable_win(int ap_index, const struct addr_map_win *win, int win_id); + +#endif /* MC_TRUSTZONE_H */ diff --git a/arm-trusted-firmware/drivers/marvell/mci.c b/arm-trusted-firmware/drivers/marvell/mci.c new file mode 100644 index 0000000..2b54700 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mci.c @@ -0,0 +1,834 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* MCI bus driver for Marvell ARMADA 8K and 8K+ SoCs */ + +#include +#include +#include +#include + +#include +#include +#include + +/* /HB /Units /Direct_regs /Direct regs + * /Configuration Register Write/Read Data Register + */ +#define MCI_WRITE_READ_DATA_REG(mci_index) \ + MVEBU_MCI_REG_BASE_REMAP(mci_index) +/* /HB /Units /Direct_regs /Direct regs + * /Configuration Register Access Command Register + */ +#define MCI_ACCESS_CMD_REG(mci_index) \ + (MVEBU_MCI_REG_BASE_REMAP(mci_index) + 0x4) + +/* Access Command fields : + * bit[3:0] - Sub command: 1 => Peripheral Config Register Read, + * 0 => Peripheral Config Register Write, + * 2 => Peripheral Assign ID request, + * 3 => Circular Config Write + * bit[5] - 1 => Local (same chip access) 0 => Remote + * bit[15:8] - Destination hop ID. Put Global ID (GID) here (see scheme below). + * bit[23:22] - 0x3 IHB PHY REG address space, 0x0 IHB Controller space + * bit[21:16] - Low 6 bits of offset. Hight 2 bits are taken from bit[28:27] + * of IHB_PHY_CTRL + * (must be set before any PHY register access occurs): + * /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Version Control Register + * + * ixi_ihb_top IHB PHY + * AXI ----------------------------- ------------- + * <--| axi_hb_top | ihb_pipe_top |-->| | + * -->| GID=1 | GID=0 |<--| | + * ----------------------------- ------------- + */ +#define MCI_INDIRECT_CTRL_READ_CMD 0x1 +#define MCI_INDIRECT_CTRL_ASSIGN_CMD 0x2 +#define MCI_INDIRECT_CTRL_CIRCULAR_CMD 0x3 +#define MCI_INDIRECT_CTRL_LOCAL_PKT (1 << 5) +#define MCI_INDIRECT_CTRL_CMD_DONE_OFFSET 6 +#define MCI_INDIRECT_CTRL_CMD_DONE \ + (1 << MCI_INDIRECT_CTRL_CMD_DONE_OFFSET) +#define MCI_INDIRECT_CTRL_DATA_READY_OFFSET 7 +#define MCI_INDIRECT_CTRL_DATA_READY \ + (1 << MCI_INDIRECT_CTRL_DATA_READY_OFFSET) +#define MCI_INDIRECT_CTRL_HOPID_OFFSET 8 +#define MCI_INDIRECT_CTRL_HOPID(id) \ + (((id) & 0xFF) << MCI_INDIRECT_CTRL_HOPID_OFFSET) +#define MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET 16 +#define MCI_INDIRECT_REG_CTRL_ADDR(reg_num) \ + (reg_num << MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET) + +/* Hop ID values */ +#define GID_IHB_PIPE 0 +#define GID_AXI_HB 1 +#define GID_IHB_EXT 2 + +#define MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG 0x2 +/* Target MCi Local ID (LID, which is = self DID) */ +#define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(val) (((val) & 0xFF) << 16) +/* Bits [15:8]: Number of MCis on chip of target MCi */ +#define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(val) (((val) & 0xFF) << 8) +/* Bits [7:0]: Number of hops on chip of target MCi */ +#define MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(val) (((val) & 0xFF) << 0) + +/* IHB_REG domain registers */ +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ + * Rx Memory Configuration Register (RX_MEM_CFG) + */ +#define MCI_CTRL_RX_MEM_CFG_REG_NUM 0x0 +#define MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(val) (((val) & 0xFF) << 24) +#define MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(val) (((val) & 0xFF) << 16) +#define MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(val) (((val) & 0xFF) << 8) +#define MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(val) (((val) & 0xF) << 4) +#define MCI_CTRL_RX_TX_MEM_CFG_RTC(val) (((val) & 0x3) << 2) +#define MCI_CTRL_RX_TX_MEM_CFG_WTC(val) (((val) & 0x3) << 0) +#define MCI_CTRL_RX_MEM_CFG_REG_DEF_CP_VAL \ + (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x07) | \ + MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x3f) | \ + MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x3f) | \ + MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(0xf) | \ + MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ + MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) + +#define MCI_CTRL_RX_MEM_CFG_REG_DEF_AP_VAL \ + (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x3f) | \ + MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x03) | \ + MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x3f) | \ + MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(0xf) | \ + MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ + MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) + + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ + * Tx Memory Configuration Register (TX_MEM_CFG) + */ +#define MCI_CTRL_TX_MEM_CFG_REG_NUM 0x1 +/* field mapping for TX mem config register + * are the same as for RX register - see register above + */ +#define MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL \ + (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x20) | \ + MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x20) | \ + MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x20) | \ + MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(2) | \ + MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ + MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Link CRC Control + */ +/* MCi Link CRC Control Register (MCi_CRC_CTRL) */ +#define MCI_LINK_CRC_CTRL_REG_NUM 0x4 + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Status Register + */ +/* MCi Status Register (MCi_STS) */ +#define MCI_CTRL_STATUS_REG_NUM 0x5 +#define MCI_CTRL_STATUS_REG_PHY_READY (1 << 12) +#define MCI_CTRL_STATUS_REG_LINK_PRESENT (1 << 15) +#define MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET 24 +#define MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK \ + (0xF << MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET) +/* Expected successful Link result, including reserved bit */ +#define MCI_CTRL_PHY_READY (MCI_CTRL_STATUS_REG_PHY_READY | \ + MCI_CTRL_STATUS_REG_LINK_PRESENT | \ + MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK) + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ + * MCi PHY Speed Settings Register (MCi_PHY_SETTING) + */ +#define MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM 0x8 +#define MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(val) (((val) & 0xF) << 28) +#define MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(val) (((val) & 0xF) << 12) +#define MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(val) (((val) & 0xF) << 8) +#define MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(val) (((val) & 0xF) << 4) +#define MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(val) (((val) & 0x1) << 1) +#define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL \ + (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \ + MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \ + MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x2) | \ + MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1)) +#define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 \ + (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \ + MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \ + MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x5) | \ + MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1)) + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Mode Config + */ +#define MCI_CTRL_IHB_MODE_CFG_REG_NUM 0x25 +#define MCI_CTRL_IHB_MODE_HBCLK_DIV(val) ((val) & 0xFF) +#define MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET 8 +#define MCI_CTRL_IHB_MODE_CHUNK_MOD \ + (1 << MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET) +#define MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET 9 +#define MCI_CTRL_IHB_MODE_FWD_MOD \ + (1 << MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET) +#define MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(val) (((val) & 0xF) << 12) +#define MCI_CTRL_IHB_MODE_RX_COMB_THRESH(val) (((val) & 0xFF) << 16) +#define MCI_CTRL_IHB_MODE_TX_COMB_THRESH(val) (((val) & 0xFF) << 24) + +#define MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL \ + (MCI_CTRL_IHB_MODE_HBCLK_DIV(6) | \ + MCI_CTRL_IHB_MODE_FWD_MOD | \ + MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(0xF) | \ + MCI_CTRL_IHB_MODE_RX_COMB_THRESH(0x3f) | \ + MCI_CTRL_IHB_MODE_TX_COMB_THRESH(0x40)) +/* AXI_HB registers */ +#define MCI_AXI_ACCESS_DATA_REG_NUM 0x0 +#define MCI_AXI_ACCESS_PCIE_MODE 1 +#define MCI_AXI_ACCESS_CACHE_CHECK_OFFSET 5 +#define MCI_AXI_ACCESS_CACHE_CHECK \ + (1 << MCI_AXI_ACCESS_CACHE_CHECK_OFFSET) +#define MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET 6 +#define MCI_AXI_ACCESS_FORCE_POST_WR \ + (1 << MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET) +#define MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET 9 +#define MCI_AXI_ACCESS_DISABLE_CLK_GATING \ + (1 << MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET) + +/* /HB /Units /HB_REG /HB_REGHopping Bus Registers + * /Window 0 Address Mask Register + */ +#define MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM 0x2 + +/* /HB /Units /HB_REG /HB_REGHopping Bus Registers + * /Window 0 Destination Register + */ +#define MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM 0x3 +#define MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(val) (((val) & 0x1) << 16) +#define MCI_HB_CTRL_WIN0_DEST_ID(val) (((val) & 0xFF) << 0) + +/* /HB /Units /HB_REG /HB_REGHopping Bus Registers /Tx Control Register */ +#define MCI_HB_CTRL_TX_CTRL_REG_NUM 0xD +#define MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET 24 +#define MCI_HB_CTRL_TX_CTRL_PCIE_MODE \ + (1 << MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET) +#define MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(val) (((val) & 0xF) << 12) +#define MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(val) (((val) & 0x1F) << 6) +#define MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(val) (((val) & 0x1F) << 0) + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Version Control Register + */ +#define MCI_PHY_CTRL_REG_NUM 0x7 +#define MCI_PHY_CTRL_MCI_MINOR 0x8 /* BITS [3:0] */ +#define MCI_PHY_CTRL_MCI_MAJOR_OFFSET 4 +#define MCI_PHY_CTRL_MCI_MAJOR \ + (1 << MCI_PHY_CTRL_MCI_MAJOR_OFFSET) +#define MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET 11 +#define MCI_PHY_CTRL_MCI_SLEEP_REQ \ + (1 << MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET) +/* Host=1 / Device=0 PHY mode */ +#define MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET 24 +#define MCI_PHY_CTRL_MCI_PHY_MODE_HOST \ + (1 << MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET) +/* Register=1 / PWM=0 interface */ +#define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET 25 +#define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE \ + (1 << MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET) + /* PHY code InReset=1 */ +#define MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET 26 +#define MCI_PHY_CTRL_MCI_PHY_RESET_CORE \ + (1 << MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET) +#define MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET 27 +#define MCI_PHY_CTRL_PHY_ADDR_MSB(addr) \ + (((addr) & 0x3) << \ + MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET) +#define MCI_PHY_CTRL_PIDI_MODE_OFFSET 31 +#define MCI_PHY_CTRL_PIDI_MODE \ + (1U << MCI_PHY_CTRL_PIDI_MODE_OFFSET) + +/* Number of times to wait for the MCI link ready after MCI configurations + * Normally takes 34-35 successive reads + */ +#define LINK_READY_TIMEOUT 100 + +enum mci_register_type { + MCI_REG_TYPE_PHY = 0, + MCI_REG_TYPE_CTRL, +}; + +enum { + MCI_CMD_WRITE, + MCI_CMD_READ +}; + +/* Write wrapper callback for debug: + * will print written data in case LOG_LEVEL >= 40 + */ +static void mci_mmio_write_32(uintptr_t addr, uint32_t value) +{ + VERBOSE("Write:\t0x%x = 0x%x\n", (uint32_t)addr, value); + mmio_write_32(addr, value); +} +/* Read wrapper callback for debug: + * will print read data in case LOG_LEVEL >= 40 + */ +static uint32_t mci_mmio_read_32(uintptr_t addr) +{ + uint32_t value; + + value = mmio_read_32(addr); + VERBOSE("Read:\t0x%x = 0x%x\n", (uint32_t)addr, value); + return value; +} + +/* MCI indirect access command completion polling: + * Each write/read command done via MCI indirect registers must be polled + * for command completions status. + * + * Returns 1 in case of error + * Returns 0 in case of command completed successfully. + */ +static int mci_poll_command_completion(int mci_index, int command_type) +{ + uint32_t mci_cmd_value = 0, retry_count = 100, ret = 0; + uint32_t completion_flags = MCI_INDIRECT_CTRL_CMD_DONE; + + debug_enter(); + /* Read commands require validating that requested data is ready */ + if (command_type == MCI_CMD_READ) + completion_flags |= MCI_INDIRECT_CTRL_DATA_READY; + + do { + /* wait 1 ms before each polling */ + mdelay(1); + mci_cmd_value = mci_mmio_read_32(MCI_ACCESS_CMD_REG(mci_index)); + } while (((mci_cmd_value & completion_flags) != completion_flags) && + (retry_count-- > 0)); + + if (retry_count == 0) { + ERROR("%s: MCI command timeout (command status = 0x%x)\n", + __func__, mci_cmd_value); + ret = 1; + } + + debug_exit(); + return ret; +} + +int mci_read(int mci_idx, uint32_t cmd, uint32_t *value) +{ + int rval; + + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_idx), cmd); + + rval = mci_poll_command_completion(mci_idx, MCI_CMD_READ); + + *value = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_idx)); + + return rval; +} + +int mci_write(int mci_idx, uint32_t cmd, uint32_t data) +{ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_idx), data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_idx), cmd); + + return mci_poll_command_completion(mci_idx, MCI_CMD_WRITE); +} + +/* Perform 3 configurations in one command: PCI mode, + * queues separation and cache bit + */ +static int mci_axi_set_pcie_mode(int mci_index) +{ + uint32_t reg_data, ret = 1; + + debug_enter(); + /* This configuration makes MCI IP behave consistently with AXI protocol + * It should be configured at one side only (for example locally at AP). + * The IP takes care of performing the same configurations at MCI on + * another side (for example remotely at CP). + */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_AXI_ACCESS_PCIE_MODE | + MCI_AXI_ACCESS_CACHE_CHECK | + MCI_AXI_ACCESS_FORCE_POST_WR | + MCI_AXI_ACCESS_DISABLE_CLK_GATING); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_AXI_ACCESS_DATA_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT | + MCI_INDIRECT_CTRL_CIRCULAR_CMD); + + /* if Write command was successful, verify PCIe mode */ + if (mci_poll_command_completion(mci_index, MCI_CMD_WRITE) == 0) { + /* Verify the PCIe mode selected */ + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_TX_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT | + MCI_INDIRECT_CTRL_READ_CMD); + /* if read was completed, verify PCIe mode */ + if (mci_poll_command_completion(mci_index, MCI_CMD_READ) == 0) { + reg_data = mci_mmio_read_32( + MCI_WRITE_READ_DATA_REG(mci_index)); + if (reg_data & MCI_HB_CTRL_TX_CTRL_PCIE_MODE) + ret = 0; + } + } + + debug_exit(); + return ret; +} + +/* Reduce sequence FIFO timer expiration threshold */ +static int mci_axi_set_fifo_thresh(int mci_index) +{ + uint32_t reg_data, ret = 0; + + debug_enter(); + /* This configuration reduces sequence FIFO timer expiration threshold + * (to 0x7 instead of 0xA). + * In MCI 1.6 version this configuration prevents possible functional + * issues. + * In version 1.82 the configuration prevents performance degradation + */ + + /* Configure local AP side */ + reg_data = MCI_PHY_CTRL_PIDI_MODE | + MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE | + MCI_PHY_CTRL_MCI_PHY_MODE_HOST | + MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_MINOR; + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Reduce the threshold */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL); + + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_IHB_MODE_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Exit PIDI mode */ + reg_data = MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE | + MCI_PHY_CTRL_MCI_PHY_MODE_HOST | + MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_MINOR; + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Configure remote CP side */ + reg_data = MCI_PHY_CTRL_PIDI_MODE | + MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_MINOR | + MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE; + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_CTRL_IHB_MODE_FWD_MOD); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Reduce the threshold */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_IHB_MODE_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Exit PIDI mode */ + reg_data = MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_MINOR | + MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE; + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_CTRL_IHB_MODE_FWD_MOD); + + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + debug_exit(); + return ret; +} + +/* Configure: + * 1. AP & CP TX thresholds and delta configurations + * 2. DLO & DLI FIFO full threshold + * 3. RX thresholds and delta configurations + * 4. CP AR and AW outstanding + * 5. AP AR and AW outstanding + */ +static int mci_axi_set_fifo_rx_tx_thresh(int mci_index) +{ + uint32_t ret = 0; + + debug_enter(); + /* AP TX thresholds and delta configurations (IHB_reg 0x1) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_TX_MEM_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* CP TX thresholds and delta configurations (IHB_reg 0x1) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_TX_MEM_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* AP DLO & DLI FIFO full threshold & Auto-Link enable (IHB_reg 0x8) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL | + MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* CP DLO & DLI FIFO full threshold (IHB_reg 0x8) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* AP RX thresholds and delta configurations (IHB_reg 0x0) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_RX_MEM_CFG_REG_DEF_AP_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_RX_MEM_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* CP RX thresholds and delta configurations (IHB_reg 0x0) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_RX_MEM_CFG_REG_DEF_CP_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_RX_MEM_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* AP AR & AW maximum AXI outstanding request cfg (HB_reg 0xd) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) | + MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(3) | + MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(3)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_TX_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* CP AR & AW maximum AXI outstanding request cfg (HB_reg 0xd) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) | + MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(0xB) | + MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(0x11)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_TX_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + debug_exit(); + return ret; +} + +/* configure MCI to allow read & write transactions to arrive at the same time. + * Without the below configuration, MCI won't sent response to CPU for + * transactions which arrived simultaneously and will lead to CPU hang. + * The below will configure MCI to be able to pass transactions from/to CP/AP. + */ +static int mci_enable_simultaneous_transactions(int mci_index) +{ + uint32_t ret = 0; + + debug_enter(); + /* ID assignment (assigning global ID offset to CP) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(2) | + MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(2) | + MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(2)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG) | + MCI_INDIRECT_CTRL_ASSIGN_CMD); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Assigning dest. ID=3 to all transactions entering from AXI at AP */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) | + MCI_HB_CTRL_WIN0_DEST_ID(3)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Assigning dest. ID=1 to all transactions entering from AXI at CP */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) | + MCI_HB_CTRL_WIN0_DEST_ID(1)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* End address to all transactions entering from AXI at AP. + * This will lead to get match for any AXI address + * and receive destination ID=3 + */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* End address to all transactions entering from AXI at CP. + * This will lead to get match for any AXI address + * and receive destination ID=1 + */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + debug_exit(); + return ret; +} + +/* Check if MCI simultaneous transaction was already enabled. + * Currently bootrom does this mci configuration only when the boot source is + * SAR_MCIX4, in other cases it should be done at this stage. + * It is worth noticing that in case of booting from uart, the bootrom + * flow is different and this mci initialization is skipped even if boot + * source is SAR_MCIX4. Therefore new verification bases on appropriate mci's + * register content: if the appropriate reg contains 0x0 it means that the + * bootrom didn't perform required mci configuration. + * + * Returns: + * 0 - configuration already done + * 1 - configuration missing + */ +static _Bool mci_simulatenous_trans_missing(int mci_index) +{ + uint32_t reg, ret; + + /* read 'Window 0 Destination ID assignment' from HB register 0x3 + * (TX_CFG_W0_DST_ID) to check whether ID assignment was already + * performed by BootROM. + */ + debug_enter(); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT | + MCI_INDIRECT_CTRL_READ_CMD); + ret = mci_poll_command_completion(mci_index, MCI_CMD_READ); + + reg = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_index)); + + if (ret) + ERROR("Failed to verify MCI simultaneous read/write status\n"); + + debug_exit(); + /* default ID assignment is 0, so if register doesn't contain zeros + * it means that bootrom already performed required configuration. + */ + if (reg != 0) + return 0; + + return 1; +} + +/* For A1 revision, configure the MCI link for performance improvement: + * - set MCI to support read/write transactions to arrive at the same time + * - Switch AXI to PCIe mode + * - Reduce sequence FIFO threshold + * - Configure RX/TX FIFO thresholds + * + * Note: + * We don't exit on error code from any sub routine, to try (best effort) to + * complete the MCI configuration. + * (If we exit - Bootloader will surely fail to boot) + */ +int mci_configure(int mci_index) +{ + int rval; + + debug_enter(); + /* According to design guidelines the MCI simultaneous transaction + * shouldn't be enabled more then once - therefore make sure that it + * wasn't already enabled in bootrom. + */ + if (mci_simulatenous_trans_missing(mci_index)) { + VERBOSE("Enabling MCI simultaneous transaction for mci%d\n", + mci_index); + /* set MCI to support read/write transactions + * to arrive at the same time + */ + rval = mci_enable_simultaneous_transactions(mci_index); + if (rval) + ERROR("Failed to set MCI simultaneous read/write\n"); + } else + VERBOSE("Skip MCI ID assignment - already done by bootrom\n"); + + /* Configure MCI for more consistent behavior with AXI protocol */ + rval = mci_axi_set_pcie_mode(mci_index); + if (rval) + ERROR("Failed to set MCI to AXI PCIe mode\n"); + + /* reduce FIFO global threshold */ + rval = mci_axi_set_fifo_thresh(mci_index); + if (rval) + ERROR("Failed to set MCI FIFO global threshold\n"); + + /* configure RX/TX FIFO thresholds */ + rval = mci_axi_set_fifo_rx_tx_thresh(mci_index); + if (rval) + ERROR("Failed to set MCI RX/TX FIFO threshold\n"); + + debug_exit(); + return 1; +} + +int mci_get_link_status(void) +{ + uint32_t cmd, data; + + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_STATUS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT | MCI_INDIRECT_CTRL_READ_CMD); + if (mci_read(0, cmd, &data)) { + ERROR("Failed to read status register\n"); + return -1; + } + + /* Check if the link is ready */ + if (data != MCI_CTRL_PHY_READY) { + ERROR("Bad link status %x\n", data); + return -1; + } + + return 0; +} + +void mci_turn_link_down(void) +{ + uint32_t cmd, data; + int rval = 0; + + debug_enter(); + + /* Turn off auto-link */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = (MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 | + MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(0)); + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to turn off auto-link\n"); + + /* Reset AP PHY */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = (MCI_PHY_CTRL_MCI_MINOR | + MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_PHY_MODE_HOST | + MCI_PHY_CTRL_MCI_PHY_RESET_CORE); + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to reset AP PHY\n"); + + /* Clear all status & CRC values */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_LINK_CRC_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = 0x0; + mci_write(0, cmd, data); + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_STATUS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = 0x0; + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to reset AP PHY\n"); + + /* Wait 5ms before un-reset the PHY */ + mdelay(5); + + /* Un-reset AP PHY */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = (MCI_PHY_CTRL_MCI_MINOR | MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_PHY_MODE_HOST); + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to un-reset AP PHY\n"); + + debug_exit(); +} + +void mci_turn_link_on(void) +{ + uint32_t cmd, data; + int rval = 0; + + debug_enter(); + /* Turn on auto-link */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = (MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 | + MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1)); + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to turn on auto-link\n"); + + debug_exit(); +} + +/* Initialize MCI for performance improvements */ +int mci_link_tune(int mci_index) +{ + int ret; + + debug_enter(); + INFO("MCI%d initialization:\n", mci_index); + + ret = mci_configure(mci_index); + + debug_exit(); + return ret; +} diff --git a/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c b/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c new file mode 100644 index 0000000..98e1896 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include + +/* CONFI REGISTERS */ +#define MG_CM3_CONFI_BASE(CP) (MVEBU_CP_REGS_BASE(CP) + 0x100000) +#define MG_CM3_SRAM_BASE(CP) MG_CM3_CONFI_BASE(CP) +#define MG_CM3_CONFI_GLOB_CFG_REG(CP) (MG_CM3_CONFI_BASE(CP) + 0x2B500) +#define CM3_CPU_EN_BIT BIT(28) +#define MG_CM3_MG_INT_MFX_REG(CP) (MG_CM3_CONFI_BASE(CP) + 0x2B054) +#define CM3_SYS_RESET_BIT BIT(0) + +#define MG_CM3_SHARED_MEM_BASE(CP) (MG_CM3_SRAM_BASE(CP) + 0x1FC00ULL) + +#define MG_SRAM_SIZE 0x20000 /* 128KB */ + +#define MG_ACK_TIMEOUT 10 + +/** + * struct ap_sharedmem_ctrl - used to pass information between the HOST and CM3 + * @init_done: Set by CM3 when ap_proces initialzied. Host check if CM3 set + * this flag to confirm that the process is running + * @lane_nr: Set by Host to mark which comphy lane should be configure. E.g.: + * - A8K development board uses comphy lane 2 for eth0 + * - CN913x development board uses comphy lane 4 for eth0 + */ +struct ap_sharedmem_ctrl { + uint32_t init_done; + uint32_t lane_nr; +}; + +int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index) +{ + uintptr_t mg_regs = MG_CM3_SRAM_BASE(cp_index); + + if (size > MG_SRAM_SIZE) { + ERROR("image is too big to fit into MG CM3 memory\n"); + return 1; + } + + NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n", + src_addr, size, mg_regs); + + /* Copy image to MG CM3 SRAM */ + memcpy((void *)mg_regs, (void *)src_addr, size); + + /* Don't release MG CM3 from reset - it will be done by next step + * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which + * has enabeld 802.3. auto-neg) will be choosen. + */ + + return 0; +} + +void mg_start_ap_fw(int cp_nr, uint8_t comphy_index) +{ + volatile struct ap_sharedmem_ctrl *ap_shared_ctrl = + (void *)MG_CM3_SHARED_MEM_BASE(cp_nr); + int timeout = MG_ACK_TIMEOUT; + + if (mmio_read_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr)) & CM3_CPU_EN_BIT) { + VERBOSE("cm3 already running\n"); + return; /* cm3 already running */ + } + + /* + * Mark which comphy lane should be used - it will be read via shared + * mem by ap process + */ + ap_shared_ctrl->lane_nr = comphy_index; + /* Make sure it took place before enabling cm3 */ + dmbst(); + + mmio_setbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr), CM3_CPU_EN_BIT); + mmio_setbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr), CM3_SYS_RESET_BIT); + + /* Check for ap process initialization by fw */ + while (ap_shared_ctrl->init_done != 1 && timeout--) + VERBOSE("Waiting for ap process ack, timeout %d\n", timeout); + + if (timeout == 0) { + ERROR("AP process failed, disabling cm3\n"); + mmio_clrbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr), + CM3_SYS_RESET_BIT); + mmio_clrbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr), + CM3_CPU_EN_BIT); + } +} diff --git a/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h b/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h new file mode 100644 index 0000000..e2756de --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +void mg_start_ap_fw(int cp_nr, uint8_t comphy_index); +int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index); diff --git a/arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c b/arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c new file mode 100644 index 0000000..75e9654 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AP807 Marvell SoC driver */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SMMU_sACR (MVEBU_SMMU_BASE + 0x10) +#define SMMU_sACR_PG_64K (1 << 16) + +#define CCU_GSPMU_CR (MVEBU_CCU_BASE(MVEBU_AP0) \ + + 0x3F0) +#define GSPMU_CPU_CONTROL (0x1 << 0) + +#define CCU_HTC_CR (MVEBU_CCU_BASE(MVEBU_AP0) \ + + 0x200) +#define CCU_SET_POC_OFFSET 5 + +#define DSS_CR0 (MVEBU_RFU_BASE + 0x100) +#define DVM_48BIT_VA_ENABLE (1 << 21) + + +/* SoC RFU / IHBx4 Control */ +#define MCIX4_807_REG_START_ADDR_REG(unit_id) (MVEBU_RFU_BASE + \ + 0x4258 + (unit_id * 0x4)) + +/* Secure MoChi incoming access */ +#define SEC_MOCHI_IN_ACC_REG (MVEBU_RFU_BASE + 0x4738) +#define SEC_MOCHI_IN_ACC_IHB0_EN (1) +#define SEC_MOCHI_IN_ACC_IHB1_EN (1 << 3) +#define SEC_MOCHI_IN_ACC_IHB2_EN (1 << 6) +#define SEC_MOCHI_IN_ACC_PIDI_EN (1 << 9) +#define SEC_IN_ACCESS_ENA_ALL_MASTERS (SEC_MOCHI_IN_ACC_IHB0_EN | \ + SEC_MOCHI_IN_ACC_IHB1_EN | \ + SEC_MOCHI_IN_ACC_IHB2_EN | \ + SEC_MOCHI_IN_ACC_PIDI_EN) +#define MOCHI_IN_ACC_LEVEL_FORCE_NONSEC (0) +#define MOCHI_IN_ACC_LEVEL_FORCE_SEC (1) +#define MOCHI_IN_ACC_LEVEL_LEAVE_ORIG (2) +#define MOCHI_IN_ACC_LEVEL_MASK_ALL (3) +#define SEC_MOCHI_IN_ACC_IHB0_LEVEL(l) ((l) << 1) +#define SEC_MOCHI_IN_ACC_IHB1_LEVEL(l) ((l) << 4) +#define SEC_MOCHI_IN_ACC_PIDI_LEVEL(l) ((l) << 10) + + +/* SYSRST_OUTn Config definitions */ +#define MVEBU_SYSRST_OUT_CONFIG_REG (MVEBU_MISC_SOC_BASE + 0x4) +#define WD_MASK_SYS_RST_OUT (1 << 2) + +/* DSS PHY for DRAM */ +#define DSS_SCR_REG (MVEBU_RFU_BASE + 0x208) +#define DSS_PPROT_OFFS 4 +#define DSS_PPROT_MASK 0x7 +#define DSS_PPROT_PRIV_SECURE_DATA 0x1 + +/* Used for Units of AP-807 (e.g. SDIO and etc) */ +#define MVEBU_AXI_ATTR_BASE (MVEBU_REGS_BASE + 0x6F4580) +#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_BASE + \ + 0x4 * index) + +#define XOR_STREAM_ID_REG(ch) (MVEBU_REGS_BASE + 0x410010 + (ch) * 0x20000) +#define XOR_STREAM_ID_MASK 0xFFFF +#define SDIO_STREAM_ID_REG (MVEBU_RFU_BASE + 0x4600) +#define SDIO_STREAM_ID_MASK 0xFF + +/* Do not use the default Stream ID 0 */ +#define A807_STREAM_ID_BASE (0x1) + +static uintptr_t stream_id_reg[] = { + XOR_STREAM_ID_REG(0), + XOR_STREAM_ID_REG(1), + XOR_STREAM_ID_REG(2), + XOR_STREAM_ID_REG(3), + SDIO_STREAM_ID_REG, + 0 +}; + +enum axi_attr { + AXI_SDIO_ATTR = 0, + AXI_DFX_ATTR, + AXI_MAX_ATTR, +}; + +static void ap_sec_masters_access_en(uint32_t enable) +{ + /* Open/Close incoming access for all masters. + * The access is disabled in trusted boot mode + * Could only be done in EL3 + */ + if (enable != 0) { + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, 0x0U, /* no clear */ + SEC_IN_ACCESS_ENA_ALL_MASTERS); +#if LLC_SRAM + /* Do not change access security level + * for PIDI masters + */ + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_MASK_ALL), + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_LEAVE_ORIG)); +#endif + } else { + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_IN_ACCESS_ENA_ALL_MASTERS, + 0x0U /* no set */); +#if LLC_SRAM + /* Return PIDI access level to the default */ + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_MASK_ALL), + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_FORCE_NONSEC)); +#endif + } +} + +static void setup_smmu(void) +{ + uint32_t reg; + + /* Set the SMMU page size to 64 KB */ + reg = mmio_read_32(SMMU_sACR); + reg |= SMMU_sACR_PG_64K; + mmio_write_32(SMMU_sACR, reg); +} + +static void init_aurora2(void) +{ + uint32_t reg; + + /* Enable GSPMU control by CPU */ + reg = mmio_read_32(CCU_GSPMU_CR); + reg |= GSPMU_CPU_CONTROL; + mmio_write_32(CCU_GSPMU_CR, reg); + +#if LLC_ENABLE + /* Enable LLC for AP807 in exclusive mode */ + llc_enable(0, 1); + + /* Set point of coherency to DDR. + * This is required by units which have + * SW cache coherency + */ + reg = mmio_read_32(CCU_HTC_CR); + reg |= (0x1 << CCU_SET_POC_OFFSET); + mmio_write_32(CCU_HTC_CR, reg); +#endif /* LLC_ENABLE */ + + errata_wa_init(); +} + + +/* MCIx indirect access register are based by default at 0xf4000000/0xf6000000 + * to avoid conflict of internal registers of units connected via MCIx, which + * can be based on the same address (i.e CP1 base is also 0xf4000000), + * the following routines remaps the MCIx indirect bases to another domain + */ +static void mci_remap_indirect_access_base(void) +{ + uint32_t mci; + + for (mci = 0; mci < MCI_MAX_UNIT_ID; mci++) + mmio_write_32(MCIX4_807_REG_START_ADDR_REG(mci), + MVEBU_MCI_REG_BASE_REMAP(mci) >> + MCI_REMAP_OFF_SHIFT); +} + +/* Set a unique stream id for all DMA capable devices */ +static void ap807_stream_id_init(void) +{ + uint32_t i; + + for (i = 0; + stream_id_reg[i] != 0 && i < ARRAY_SIZE(stream_id_reg); i++) { + uint32_t mask = stream_id_reg[i] == SDIO_STREAM_ID_REG ? + SDIO_STREAM_ID_MASK : XOR_STREAM_ID_MASK; + + mmio_clrsetbits_32(stream_id_reg[i], mask, + i + A807_STREAM_ID_BASE); + } +} + +static void ap807_axi_attr_init(void) +{ + uint32_t index, data; + + /* Initialize AXI attributes for AP807 */ + /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */ + for (index = 0; index < AXI_MAX_ATTR; index++) { + switch (index) { + /* DFX works with no coherent only - + * there's no option to configure the Ax-Cache and Ax-Domain + */ + case AXI_DFX_ATTR: + continue; + default: + /* Set Ax-Cache as cacheable, no allocate, modifiable, + * bufferable. + * The values are different because Read & Write + * definition is different in Ax-Cache + */ + data = mmio_read_32(MVEBU_AXI_ATTR_REG(index)); + data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK; + data |= (CACHE_ATTR_WRITE_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_ARCACHE_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK; + data |= (CACHE_ATTR_READ_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_AWCACHE_OFFSET; + /* Set Ax-Domain as Outer domain */ + data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_ARDOMAIN_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_AWDOMAIN_OFFSET; + mmio_write_32(MVEBU_AXI_ATTR_REG(index), data); + } + } +} + +static void misc_soc_configurations(void) +{ + uint32_t reg; + + /* Enable 48-bit VA */ + mmio_setbits_32(DSS_CR0, DVM_48BIT_VA_ENABLE); + + /* Un-mask Watchdog reset from influencing the SYSRST_OUTn. + * Otherwise, upon WD timeout, the WD reset signal won't trigger reset + */ + reg = mmio_read_32(MVEBU_SYSRST_OUT_CONFIG_REG); + reg &= ~(WD_MASK_SYS_RST_OUT); + mmio_write_32(MVEBU_SYSRST_OUT_CONFIG_REG, reg); +} + +/* + * By default all external CPs start with configuration address space set to + * 0xf200_0000. To overcome this issue, go in the loop and initialize the + * CP one by one, using temporary window configuration which allows to access + * each CP and update its configuration space according to decoding + * windows scheme defined for each platform. + */ +void update_cp110_default_win(int cp_id) +{ + int mci_id = cp_id - 1; + uintptr_t cp110_base, cp110_temp_base; + + /* CP110 default configuration address space */ + cp110_temp_base = MVEBU_AP_IO_BASE(MVEBU_AP0); + + struct addr_map_win iowin_temp_win = { + .base_addr = cp110_temp_base, + .win_size = MVEBU_CP_OFFSET, + }; + + iowin_temp_win.target_id = mci_id; + iow_temp_win_insert(0, &iowin_temp_win, 1); + + /* Calculate the new CP110 - base address */ + cp110_base = MVEBU_CP_REGS_BASE(cp_id); + /* Go and update the CP110 configuration address space */ + iob_cfg_space_update(0, cp_id, cp110_temp_base, cp110_base); + + /* Remove the temporary IO-WIN window */ + iow_temp_win_remove(0, &iowin_temp_win, 1); +} + +void ap_init(void) +{ + /* Setup Aurora2. */ + init_aurora2(); + + /* configure MCI mapping */ + mci_remap_indirect_access_base(); + + /* configure IO_WIN windows */ + init_io_win(MVEBU_AP0); + + /* configure CCU windows */ + init_ccu(MVEBU_AP0); + + /* Set the stream IDs for DMA masters */ + ap807_stream_id_init(); + + /* configure the SMMU */ + setup_smmu(); + + /* Open AP incoming access for all masters */ + ap_sec_masters_access_en(1); + + /* configure axi for AP */ + ap807_axi_attr_init(); + + /* misc configuration of the SoC */ + misc_soc_configurations(); +} + +static void ap807_dram_phy_access_config(void) +{ + uint32_t reg_val; + /* Update DSS port access permission to DSS_PHY */ + reg_val = mmio_read_32(DSS_SCR_REG); + reg_val &= ~(DSS_PPROT_MASK << DSS_PPROT_OFFS); + reg_val |= ((DSS_PPROT_PRIV_SECURE_DATA & DSS_PPROT_MASK) << + DSS_PPROT_OFFS); + mmio_write_32(DSS_SCR_REG, reg_val); +} + +void ap_ble_init(void) +{ + /* Enable DSS port */ + ap807_dram_phy_access_config(); +} + +int ap_get_count(void) +{ + return 1; +} + + diff --git a/arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c b/arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c new file mode 100644 index 0000000..5c71fed --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AP806 Marvell SoC driver */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SMMU_sACR (MVEBU_SMMU_BASE + 0x10) +#define SMMU_sACR_PG_64K (1 << 16) + +#define CCU_GSPMU_CR (MVEBU_CCU_BASE(MVEBU_AP0) + \ + 0x3F0) +#define GSPMU_CPU_CONTROL (0x1 << 0) + +#define CCU_HTC_CR (MVEBU_CCU_BASE(MVEBU_AP0) + \ + 0x200) +#define CCU_SET_POC_OFFSET 5 + +#define DSS_CR0 (MVEBU_RFU_BASE + 0x100) +#define DVM_48BIT_VA_ENABLE (1 << 21) + +/* Secure MoChi incoming access */ +#define SEC_MOCHI_IN_ACC_REG (MVEBU_RFU_BASE + 0x4738) +#define SEC_MOCHI_IN_ACC_IHB0_EN (1) +#define SEC_MOCHI_IN_ACC_IHB1_EN (1 << 3) +#define SEC_MOCHI_IN_ACC_IHB2_EN (1 << 6) +#define SEC_MOCHI_IN_ACC_PIDI_EN (1 << 9) +#define SEC_IN_ACCESS_ENA_ALL_MASTERS (SEC_MOCHI_IN_ACC_IHB0_EN | \ + SEC_MOCHI_IN_ACC_IHB1_EN | \ + SEC_MOCHI_IN_ACC_IHB2_EN | \ + SEC_MOCHI_IN_ACC_PIDI_EN) +#define MOCHI_IN_ACC_LEVEL_FORCE_NONSEC (0) +#define MOCHI_IN_ACC_LEVEL_FORCE_SEC (1) +#define MOCHI_IN_ACC_LEVEL_LEAVE_ORIG (2) +#define MOCHI_IN_ACC_LEVEL_MASK_ALL (3) +#define SEC_MOCHI_IN_ACC_IHB0_LEVEL(l) ((l) << 1) +#define SEC_MOCHI_IN_ACC_IHB1_LEVEL(l) ((l) << 4) +#define SEC_MOCHI_IN_ACC_PIDI_LEVEL(l) ((l) << 10) + + +/* SYSRST_OUTn Config definitions */ +#define MVEBU_SYSRST_OUT_CONFIG_REG (MVEBU_MISC_SOC_BASE + 0x4) +#define WD_MASK_SYS_RST_OUT (1 << 2) + +/* Generic Timer System Controller */ +#define MVEBU_MSS_GTCR_REG (MVEBU_REGS_BASE + 0x581000) +#define MVEBU_MSS_GTCR_ENABLE_BIT 0x1 + +/* + * AXI Configuration. + */ + +/* Used for Units of AP-806 (e.g. SDIO and etc) */ +#define MVEBU_AXI_ATTR_BASE (MVEBU_REGS_BASE + 0x6F4580) +#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_BASE + \ + 0x4 * index) + +#define XOR_STREAM_ID_REG(ch) (MVEBU_REGS_BASE + 0x410010 + (ch) * 0x20000) +#define XOR_STREAM_ID_MASK 0xFFFF +#define SDIO_STREAM_ID_REG (MVEBU_RFU_BASE + 0x4600) +#define SDIO_STREAM_ID_MASK 0xFF + +/* Do not use the default Stream ID 0 */ +#define A806_STREAM_ID_BASE (0x1) + +static uintptr_t stream_id_reg[] = { + XOR_STREAM_ID_REG(0), + XOR_STREAM_ID_REG(1), + XOR_STREAM_ID_REG(2), + XOR_STREAM_ID_REG(3), + SDIO_STREAM_ID_REG, + 0 +}; + +enum axi_attr { + AXI_SDIO_ATTR = 0, + AXI_DFX_ATTR, + AXI_MAX_ATTR, +}; + +static void apn_sec_masters_access_en(uint32_t enable) +{ + /* Open/Close incoming access for all masters. + * The access is disabled in trusted boot mode + * Could only be done in EL3 + */ + if (enable != 0) { + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, 0x0U, /* no clear */ + SEC_IN_ACCESS_ENA_ALL_MASTERS); +#if LLC_SRAM + /* Do not change access security level + * for PIDI masters + */ + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_MASK_ALL), + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_LEAVE_ORIG)); +#endif + } else { + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_IN_ACCESS_ENA_ALL_MASTERS, + 0x0U /* no set */); +#if LLC_SRAM + /* Return PIDI access level to the default */ + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_MASK_ALL), + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_FORCE_NONSEC)); +#endif + } +} + +static void setup_smmu(void) +{ + uint32_t reg; + + /* Set the SMMU page size to 64 KB */ + reg = mmio_read_32(SMMU_sACR); + reg |= SMMU_sACR_PG_64K; + mmio_write_32(SMMU_sACR, reg); +} + +static void init_aurora2(void) +{ + uint32_t reg; + + /* Enable GSPMU control by CPU */ + reg = mmio_read_32(CCU_GSPMU_CR); + reg |= GSPMU_CPU_CONTROL; + mmio_write_32(CCU_GSPMU_CR, reg); + +#if LLC_ENABLE + /* Enable LLC for AP806 in exclusive mode */ + llc_enable(0, 1); + + /* Set point of coherency to DDR. + * This is required by units which have + * SW cache coherency + */ + reg = mmio_read_32(CCU_HTC_CR); + reg |= (0x1 << CCU_SET_POC_OFFSET); + mmio_write_32(CCU_HTC_CR, reg); +#endif /* LLC_ENABLE */ + + errata_wa_init(); +} + + +/* MCIx indirect access register are based by default at 0xf4000000/0xf6000000 + * to avoid conflict of internal registers of units connected via MCIx, which + * can be based on the same address (i.e CP1 base is also 0xf4000000), + * the following routines remaps the MCIx indirect bases to another domain + */ +static void mci_remap_indirect_access_base(void) +{ + uint32_t mci; + + for (mci = 0; mci < MCI_MAX_UNIT_ID; mci++) + mmio_write_32(MCIX4_REG_START_ADDRESS_REG(mci), + MVEBU_MCI_REG_BASE_REMAP(mci) >> + MCI_REMAP_OFF_SHIFT); +} + +/* Set a unique stream id for all DMA capable devices */ +static void ap806_stream_id_init(void) +{ + int i; + + for (i = 0; stream_id_reg[i] != 0; i++) { + uint32_t mask = stream_id_reg[i] == SDIO_STREAM_ID_REG ? + SDIO_STREAM_ID_MASK : XOR_STREAM_ID_MASK; + + mmio_clrsetbits_32(stream_id_reg[i], mask, + i + A806_STREAM_ID_BASE); + } +} + +static void apn806_axi_attr_init(void) +{ + uint32_t index, data; + + /* Initialize AXI attributes for APN806 */ + + /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */ + for (index = 0; index < AXI_MAX_ATTR; index++) { + switch (index) { + /* DFX works with no coherent only - + * there's no option to configure the Ax-Cache and Ax-Domain + */ + case AXI_DFX_ATTR: + continue; + default: + /* Set Ax-Cache as cacheable, no allocate, modifiable, + * bufferable + * The values are different because Read & Write + * definition is different in Ax-Cache + */ + data = mmio_read_32(MVEBU_AXI_ATTR_REG(index)); + data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK; + data |= (CACHE_ATTR_WRITE_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_ARCACHE_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK; + data |= (CACHE_ATTR_READ_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_AWCACHE_OFFSET; + /* Set Ax-Domain as Outer domain */ + data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_ARDOMAIN_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_AWDOMAIN_OFFSET; + mmio_write_32(MVEBU_AXI_ATTR_REG(index), data); + } + } +} + +static void dss_setup(void) +{ + /* Enable 48-bit VA */ + mmio_setbits_32(DSS_CR0, DVM_48BIT_VA_ENABLE); +} + +void misc_soc_configurations(void) +{ + uint32_t reg; + + /* Un-mask Watchdog reset from influencing the SYSRST_OUTn. + * Otherwise, upon WD timeout, the WD reset signal won't trigger reset + */ + reg = mmio_read_32(MVEBU_SYSRST_OUT_CONFIG_REG); + reg &= ~(WD_MASK_SYS_RST_OUT); + mmio_write_32(MVEBU_SYSRST_OUT_CONFIG_REG, reg); +} + +void ap_init(void) +{ + /* Setup Aurora2. */ + init_aurora2(); + + /* configure MCI mapping */ + mci_remap_indirect_access_base(); + + /* configure IO_WIN windows */ + init_io_win(MVEBU_AP0); + + /* configure CCU windows */ + init_ccu(MVEBU_AP0); + + /* configure DSS */ + dss_setup(); + + /* Set the stream IDs for DMA masters */ + ap806_stream_id_init(); + + /* configure the SMMU */ + setup_smmu(); + + /* Open APN incoming access for all masters */ + apn_sec_masters_access_en(1); + + /* configure axi for APN*/ + apn806_axi_attr_init(); + + /* misc configuration of the SoC */ + misc_soc_configurations(); +} + +void ap_ble_init(void) +{ +} + +int ap_get_count(void) +{ + return 1; +} + +void update_cp110_default_win(int cp_id) +{ +} diff --git a/arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c b/arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c new file mode 100644 index 0000000..f12da0e --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2018-2020 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* CP110 Marvell SoC driver */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * AXI Configuration. + */ + + /* Used for Units of CP-110 (e.g. USB device, USB Host, and etc) */ +#define MVEBU_AXI_ATTR_OFFSET (0x441300) +#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_OFFSET + \ + 0x4 * index) + +/* AXI Protection bits */ +#define MVEBU_AXI_PROT_OFFSET (0x441200) + +/* AXI Protection regs */ +#define MVEBU_AXI_PROT_REG(index) ((index <= 4) ? \ + (MVEBU_AXI_PROT_OFFSET + \ + 0x4 * index) : \ + (MVEBU_AXI_PROT_OFFSET + 0x18)) +#define MVEBU_AXI_PROT_REGS_NUM (6) + +#define MVEBU_SOC_CFGS_OFFSET (0x441900) +#define MVEBU_SOC_CFG_REG(index) (MVEBU_SOC_CFGS_OFFSET + \ + 0x4 * index) +#define MVEBU_SOC_CFG_REG_NUM (0) +#define MVEBU_SOC_CFG_GLOG_SECURE_EN_MASK (0xE) + +/* SATA3 MBUS to AXI regs */ +#define MVEBU_BRIDGE_WIN_DIS_REG (MVEBU_SOC_CFGS_OFFSET + 0x10) +#define MVEBU_BRIDGE_WIN_DIS_OFF (0x0) + +/* SATA3 MBUS to AXI regs */ +#define MVEBU_SATA_M2A_AXI_PORT_CTRL_REG (0x54ff04) + +/* AXI to MBUS bridge registers */ +#define MVEBU_AMB_IP_OFFSET (0x13ff00) +#define MVEBU_AMB_IP_BRIDGE_WIN_REG(win) (MVEBU_AMB_IP_OFFSET + \ + (win * 0x8)) +#define MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET 0 +#define MVEBU_AMB_IP_BRIDGE_WIN_EN_MASK \ + (0x1 << MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET) +#define MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET 16 +#define MVEBU_AMB_IP_BRIDGE_WIN_SIZE_MASK \ + (0xffffu << MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET) + +#define MVEBU_SAMPLE_AT_RESET_REG (0x440600) +#define SAR_PCIE1_CLK_CFG_OFFSET 31 +#define SAR_PCIE1_CLK_CFG_MASK (0x1u << SAR_PCIE1_CLK_CFG_OFFSET) +#define SAR_PCIE0_CLK_CFG_OFFSET 30 +#define SAR_PCIE0_CLK_CFG_MASK (0x1 << SAR_PCIE0_CLK_CFG_OFFSET) +#define SAR_I2C_INIT_EN_OFFSET 24 +#define SAR_I2C_INIT_EN_MASK (1 << SAR_I2C_INIT_EN_OFFSET) + +/******************************************************************************* + * PCIE clock buffer control + ******************************************************************************/ +#define MVEBU_PCIE_REF_CLK_BUF_CTRL (0x4404F0) +#define PCIE1_REFCLK_BUFF_SOURCE 0x800 +#define PCIE0_REFCLK_BUFF_SOURCE 0x400 + +/******************************************************************************* + * MSS Device Push Set Register + ******************************************************************************/ +#define MVEBU_CP_MSS_DPSHSR_REG (0x280040) +#define MSS_DPSHSR_REG_PCIE_CLK_SEL 0x8 + +/******************************************************************************* + * RTC Configuration + ******************************************************************************/ +#define MVEBU_RTC_BASE (0x284000) +#define MVEBU_RTC_STATUS_REG (MVEBU_RTC_BASE + 0x0) +#define MVEBU_RTC_STATUS_ALARM1_MASK 0x1 +#define MVEBU_RTC_STATUS_ALARM2_MASK 0x2 +#define MVEBU_RTC_IRQ_1_CONFIG_REG (MVEBU_RTC_BASE + 0x4) +#define MVEBU_RTC_IRQ_2_CONFIG_REG (MVEBU_RTC_BASE + 0x8) +#define MVEBU_RTC_TIME_REG (MVEBU_RTC_BASE + 0xC) +#define MVEBU_RTC_ALARM_1_REG (MVEBU_RTC_BASE + 0x10) +#define MVEBU_RTC_ALARM_2_REG (MVEBU_RTC_BASE + 0x14) +#define MVEBU_RTC_CCR_REG (MVEBU_RTC_BASE + 0x18) +#define MVEBU_RTC_NOMINAL_TIMING 0x2000 +#define MVEBU_RTC_NOMINAL_TIMING_MASK 0x7FFF +#define MVEBU_RTC_TEST_CONFIG_REG (MVEBU_RTC_BASE + 0x1C) +#define MVEBU_RTC_BRIDGE_TIMING_CTRL0_REG (MVEBU_RTC_BASE + 0x80) +#define MVEBU_RTC_WRCLK_PERIOD_MASK 0xFFFF +#define MVEBU_RTC_WRCLK_PERIOD_DEFAULT 0x3FF +#define MVEBU_RTC_WRCLK_SETUP_OFFS 16 +#define MVEBU_RTC_WRCLK_SETUP_MASK 0xFFFF0000 +#define MVEBU_RTC_WRCLK_SETUP_DEFAULT 0x29 +#define MVEBU_RTC_BRIDGE_TIMING_CTRL1_REG (MVEBU_RTC_BASE + 0x84) +#define MVEBU_RTC_READ_OUTPUT_DELAY_MASK 0xFFFF +#define MVEBU_RTC_READ_OUTPUT_DELAY_DEFAULT 0x1F + +/******************************************************************************* + * TRNG Configuration + ******************************************************************************/ +#define MVEBU_TRNG_BASE (0x760000) +#define MVEBU_EFUSE_TRNG_ENABLE_EFUSE_WORD MVEBU_AP_LDX_220_189_EFUSE_OFFS +#define MVEBU_EFUSE_TRNG_ENABLE_BIT_OFFSET 13 /* LD0[202] */ + +enum axi_attr { + AXI_ADUNIT_ATTR = 0, + AXI_COMUNIT_ATTR, + AXI_EIP197_ATTR, + AXI_USB3D_ATTR, + AXI_USB3H0_ATTR, + AXI_USB3H1_ATTR, + AXI_SATA0_ATTR, + AXI_SATA1_ATTR, + AXI_DAP_ATTR, + AXI_DFX_ATTR, + AXI_DBG_TRC_ATTR = 12, + AXI_SDIO_ATTR, + AXI_MSS_ATTR, + AXI_MAX_ATTR, +}; + +/* Most stream IDS are configured centrally in the CP-110 RFU + * but some are configured inside the unit registers + */ +#define RFU_STREAM_ID_BASE (0x450000) +#define USB3H_0_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0xC) +#define USB3H_1_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x10) +#define SATA_0_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x14) +#define SATA_1_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x18) +#define SDIO_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x28) + +#define CP_DMA_0_STREAM_ID_REG (0x6B0010) +#define CP_DMA_1_STREAM_ID_REG (0x6D0010) + +/* We allocate IDs 128-255 for PCIe */ +#define MAX_STREAM_ID (0x80) + +static uintptr_t stream_id_reg[] = { + USB3H_0_STREAM_ID_REG, + USB3H_1_STREAM_ID_REG, + CP_DMA_0_STREAM_ID_REG, + CP_DMA_1_STREAM_ID_REG, + SATA_0_STREAM_ID_REG, + SATA_1_STREAM_ID_REG, + SDIO_STREAM_ID_REG, + 0 +}; + +static void cp110_errata_wa_init(uintptr_t base) +{ + uint32_t data; + + /* ERRATA GL-4076863: + * Reset value for global_secure_enable inputs must be changed + * from '1' to '0'. + * When asserted, only "secured" transactions can enter IHB + * configuration space. + * However, blocking AXI transactions is performed by IOB. + * Performing it also at IHB/HB complicates programming model. + * + * Enable non-secure access in SOC configuration register + */ + data = mmio_read_32(base + MVEBU_SOC_CFG_REG(MVEBU_SOC_CFG_REG_NUM)); + data &= ~MVEBU_SOC_CFG_GLOG_SECURE_EN_MASK; + mmio_write_32(base + MVEBU_SOC_CFG_REG(MVEBU_SOC_CFG_REG_NUM), data); +} + +static void cp110_pcie_clk_cfg(uintptr_t base) +{ + uint32_t pcie0_clk, pcie1_clk, reg; + + /* + * Determine the pcie0/1 clock direction (input/output) from the + * sample at reset. + */ + reg = mmio_read_32(base + MVEBU_SAMPLE_AT_RESET_REG); + pcie0_clk = (reg & SAR_PCIE0_CLK_CFG_MASK) >> SAR_PCIE0_CLK_CFG_OFFSET; + pcie1_clk = (reg & SAR_PCIE1_CLK_CFG_MASK) >> SAR_PCIE1_CLK_CFG_OFFSET; + + /* CP110 revision A2 or CN913x */ + if (cp110_rev_id_get(base) == MVEBU_CP110_REF_ID_A2 || + cp110_device_id_get(base) == MVEBU_CN9130_DEV_ID) { + /* + * PCIe Reference Clock Buffer Control register must be + * set according to the clock direction (input/output) + */ + reg = mmio_read_32(base + MVEBU_PCIE_REF_CLK_BUF_CTRL); + reg &= ~(PCIE0_REFCLK_BUFF_SOURCE | PCIE1_REFCLK_BUFF_SOURCE); + if (!pcie0_clk) + reg |= PCIE0_REFCLK_BUFF_SOURCE; + if (!pcie1_clk) + reg |= PCIE1_REFCLK_BUFF_SOURCE; + + mmio_write_32(base + MVEBU_PCIE_REF_CLK_BUF_CTRL, reg); + } + + /* CP110 revision A1 */ + if (cp110_rev_id_get(base) == MVEBU_CP110_REF_ID_A1) { + if (!pcie0_clk || !pcie1_clk) { + /* + * if one of the pcie clocks is set to input, + * we need to set mss_push[131] field, otherwise, + * the pcie clock might not work. + */ + reg = mmio_read_32(base + MVEBU_CP_MSS_DPSHSR_REG); + reg |= MSS_DPSHSR_REG_PCIE_CLK_SEL; + mmio_write_32(base + MVEBU_CP_MSS_DPSHSR_REG, reg); + } + } +} + +/* Set a unique stream id for all DMA capable devices */ +static void cp110_stream_id_init(uintptr_t base, uint32_t stream_id) +{ + int i = 0; + + while (stream_id_reg[i]) { + if (i > MAX_STREAM_ID_PER_CP) { + NOTICE("Only first %d (maximum) Stream IDs allocated\n", + MAX_STREAM_ID_PER_CP); + return; + } + + if ((stream_id_reg[i] == CP_DMA_0_STREAM_ID_REG) || + (stream_id_reg[i] == CP_DMA_1_STREAM_ID_REG)) + mmio_write_32(base + stream_id_reg[i], + stream_id << 16 | stream_id); + else + mmio_write_32(base + stream_id_reg[i], stream_id); + + /* SATA port 0/1 are in the same SATA unit, and they should use + * the same STREAM ID number + */ + if (stream_id_reg[i] != SATA_0_STREAM_ID_REG) + stream_id++; + + i++; + } +} + +static void cp110_axi_attr_init(uintptr_t base) +{ + uint32_t index, data; + + /* Initialize AXI attributes for Armada-7K/8K SoC */ + + /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */ + for (index = 0; index < AXI_MAX_ATTR; index++) { + switch (index) { + /* DFX and MSS unit works with no coherent only - + * there's no option to configure the Ax-Cache and Ax-Domain + */ + case AXI_DFX_ATTR: + case AXI_MSS_ATTR: + continue; + default: + /* Set Ax-Cache as cacheable, no allocate, modifiable, + * bufferable + * The values are different because Read & Write + * definition is different in Ax-Cache + */ + data = mmio_read_32(base + MVEBU_AXI_ATTR_REG(index)); + data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK; + data |= (CACHE_ATTR_WRITE_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_ARCACHE_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK; + data |= (CACHE_ATTR_READ_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_AWCACHE_OFFSET; + /* Set Ax-Domain as Outer domain */ + data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_ARDOMAIN_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_AWDOMAIN_OFFSET; + mmio_write_32(base + MVEBU_AXI_ATTR_REG(index), data); + } + } + + /* SATA IOCC supported, cache attributes + * for SATA MBUS to AXI configuration. + */ + data = mmio_read_32(base + MVEBU_SATA_M2A_AXI_PORT_CTRL_REG); + data &= ~MVEBU_SATA_M2A_AXI_AWCACHE_MASK; + data |= (CACHE_ATTR_WRITE_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET; + data &= ~MVEBU_SATA_M2A_AXI_ARCACHE_MASK; + data |= (CACHE_ATTR_READ_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET; + mmio_write_32(base + MVEBU_SATA_M2A_AXI_PORT_CTRL_REG, data); + + /* Set all IO's AXI attribute to non-secure access. */ + for (index = 0; index < MVEBU_AXI_PROT_REGS_NUM; index++) + mmio_write_32(base + MVEBU_AXI_PROT_REG(index), + DOMAIN_SYSTEM_SHAREABLE); +} + +void cp110_amb_init(uintptr_t base) +{ + uint32_t reg; + + /* Open AMB bridge Window to Access COMPHY/MDIO registers */ + reg = mmio_read_32(base + MVEBU_AMB_IP_BRIDGE_WIN_REG(0)); + reg &= ~(MVEBU_AMB_IP_BRIDGE_WIN_SIZE_MASK | + MVEBU_AMB_IP_BRIDGE_WIN_EN_MASK); + reg |= (0x7ff << MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET) | + (0x1 << MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET); + mmio_write_32(base + MVEBU_AMB_IP_BRIDGE_WIN_REG(0), reg); +} + +static void cp110_rtc_init(uintptr_t base) +{ + /* Update MBus timing parameters before accessing RTC registers */ + mmio_clrsetbits_32(base + MVEBU_RTC_BRIDGE_TIMING_CTRL0_REG, + MVEBU_RTC_WRCLK_PERIOD_MASK, + MVEBU_RTC_WRCLK_PERIOD_DEFAULT); + + mmio_clrsetbits_32(base + MVEBU_RTC_BRIDGE_TIMING_CTRL0_REG, + MVEBU_RTC_WRCLK_SETUP_MASK, + MVEBU_RTC_WRCLK_SETUP_DEFAULT << + MVEBU_RTC_WRCLK_SETUP_OFFS); + + mmio_clrsetbits_32(base + MVEBU_RTC_BRIDGE_TIMING_CTRL1_REG, + MVEBU_RTC_READ_OUTPUT_DELAY_MASK, + MVEBU_RTC_READ_OUTPUT_DELAY_DEFAULT); + + /* + * Issue reset to the RTC if Clock Correction register + * contents did not sustain the reboot/power-on. + */ + if ((mmio_read_32(base + MVEBU_RTC_CCR_REG) & + MVEBU_RTC_NOMINAL_TIMING_MASK) != MVEBU_RTC_NOMINAL_TIMING) { + /* Reset Test register */ + mmio_write_32(base + MVEBU_RTC_TEST_CONFIG_REG, 0); + mdelay(500); + + /* Reset Status register */ + mmio_write_32(base + MVEBU_RTC_STATUS_REG, + (MVEBU_RTC_STATUS_ALARM1_MASK | + MVEBU_RTC_STATUS_ALARM2_MASK)); + udelay(62); + + /* Turn off Int1 and Int2 sources & clear the Alarm count */ + mmio_write_32(base + MVEBU_RTC_IRQ_1_CONFIG_REG, 0); + mmio_write_32(base + MVEBU_RTC_IRQ_2_CONFIG_REG, 0); + mmio_write_32(base + MVEBU_RTC_ALARM_1_REG, 0); + mmio_write_32(base + MVEBU_RTC_ALARM_2_REG, 0); + + /* Setup nominal register access timing */ + mmio_write_32(base + MVEBU_RTC_CCR_REG, + MVEBU_RTC_NOMINAL_TIMING); + + /* Reset Status register */ + mmio_write_32(base + MVEBU_RTC_STATUS_REG, + (MVEBU_RTC_STATUS_ALARM1_MASK | + MVEBU_RTC_STATUS_ALARM2_MASK)); + udelay(50); + } +} + +static void cp110_amb_adec_init(uintptr_t base) +{ + /* enable AXI-MBUS by clearing "Bridge Windows Disable" */ + mmio_clrbits_32(base + MVEBU_BRIDGE_WIN_DIS_REG, + (1 << MVEBU_BRIDGE_WIN_DIS_OFF)); + + /* configure AXI-MBUS windows for CP */ + init_amb_adec(base); +} + +static void cp110_trng_init(uintptr_t base) +{ + static bool done; + int ret; + uint32_t reg_val, efuse; + + /* Set access to LD0 */ + reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG); + reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_MASK; + mmio_write_32(MVEBU_AP_EFUSE_SRV_CTRL_REG, reg_val); + + /* Obtain the AP LD0 bit defining TRNG presence */ + efuse = mmio_read_32(MVEBU_EFUSE_TRNG_ENABLE_EFUSE_WORD); + efuse >>= MVEBU_EFUSE_TRNG_ENABLE_BIT_OFFSET; + efuse &= 1; + + if (efuse == 0) { + VERBOSE("TRNG is not present, skipping"); + return; + } + + if (!done) { + ret = eip76_rng_probe(base + MVEBU_TRNG_BASE); + if (ret != 0) { + ERROR("Failed to init TRNG @ 0x%lx\n", base); + return; + } + done = true; + } +} +void cp110_init(uintptr_t cp110_base, uint32_t stream_id) +{ + INFO("%s: Initialize CPx - base = %lx\n", __func__, cp110_base); + + /* configure IOB windows for CP0*/ + init_iob(cp110_base); + + /* configure AXI-MBUS windows for CP0*/ + cp110_amb_adec_init(cp110_base); + + /* configure axi for CP0*/ + cp110_axi_attr_init(cp110_base); + + /* Execute SW WA for erratas */ + cp110_errata_wa_init(cp110_base); + + /* Confiure pcie clock according to clock direction */ + cp110_pcie_clk_cfg(cp110_base); + + /* configure stream id for CP0 */ + cp110_stream_id_init(cp110_base, stream_id); + + /* Open AMB bridge for comphy for CP0 & CP1*/ + cp110_amb_init(cp110_base); + + /* Reset RTC if needed */ + cp110_rtc_init(cp110_base); + + /* TRNG init - for CP0 only */ + cp110_trng_init(cp110_base); +} + +/* Do the minimal setup required to configure the CP in BLE */ +void cp110_ble_init(uintptr_t cp110_base) +{ +#if PCI_EP_SUPPORT + INFO("%s: Initialize CPx - base = %lx\n", __func__, cp110_base); + + cp110_amb_init(cp110_base); + + /* Configure PCIe clock */ + cp110_pcie_clk_cfg(cp110_base); + + /* Configure PCIe endpoint */ + ble_plat_pcie_ep_setup(); +#endif +} diff --git a/arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c new file mode 100644 index 0000000..4f7191b --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ +#include +#include +#include +#include +#include +#include +#include "dfx.h" + +/* #define DEBUG_DFX */ +#ifdef DEBUG_DFX +#define debug(format...) NOTICE(format) +#else +#define debug(format, arg...) +#endif + +#define TSEN_CTRL0 0xf06f8084 + #define TSEN_CTRL0_START BIT(0) + #define TSEN_CTRL0_RESET BIT(1) + #define TSEN_CTRL0_ENABLE BIT(2) + #define TSEN_CTRL0_AVG_BYPASS BIT(6) + #define TSEN_CTRL0_CHAN_SHIFT 13 + #define TSEN_CTRL0_CHAN_MASK 0xF + #define TSEN_CTRL0_OSR_SHIFT 24 + #define TSEN_CTRL0_OSR_MAX 0x3 + #define TSEN_CTRL0_MODE_SHIFT 30 + #define TSEN_CTRL0_MODE_EXTERNAL 0x2U + #define TSEN_CTRL0_MODE_MASK 0x3U + +#define TSEN_CTRL1 0xf06f8088 + #define TSEN_CTRL1_INT_EN BIT(25) + #define TSEN_CTRL1_HYST_SHIFT 19 + #define TSEN_CTRL1_HYST_MASK (0x3 << TSEN_CTRL1_HYST_SHIFT) + #define TSEN_CTRL1_THRESH_SHIFT 3 + #define TSEN_CTRL1_THRESH_MASK (0x3ff << TSEN_CTRL1_THRESH_SHIFT) + +#define TSEN_STATUS 0xf06f808c + #define TSEN_STATUS_VALID_OFFSET 16 + #define TSEN_STATUS_VALID_MASK (0x1 << TSEN_STATUS_VALID_OFFSET) + #define TSEN_STATUS_TEMP_OUT_OFFSET 0 + #define TSEN_STATUS_TEMP_OUT_MASK (0x3FF << TSEN_STATUS_TEMP_OUT_OFFSET) + +#define DFX_SERVER_IRQ_SUM_MASK_REG 0xf06f8104 + #define DFX_SERVER_IRQ_EN BIT(1) + +#define DFX_IRQ_CAUSE_REG 0xf06f8108 + +#define DFX_IRQ_MASK_REG 0xf06f810c + #define DFX_IRQ_TSEN_OVERHEAT_OFFSET BIT(22) + +#define THERMAL_SEN_OUTPUT_MSB 512 +#define THERMAL_SEN_OUTPUT_COMP 1024 + +#define COEF_M 423 +#define COEF_B -150000LL + +static void armada_ap806_thermal_read(u_register_t *temp) +{ + uint32_t reg; + + reg = mmio_read_32(TSEN_STATUS); + + reg = ((reg & TSEN_STATUS_TEMP_OUT_MASK) >> + TSEN_STATUS_TEMP_OUT_OFFSET); + + /* + * TSEN output format is signed as a 2s complement number + * ranging from-512 to +511. when MSB is set, need to + * calculate the complement number + */ + if (reg >= THERMAL_SEN_OUTPUT_MSB) + reg -= THERMAL_SEN_OUTPUT_COMP; + + *temp = ((COEF_M * ((signed int)reg)) - COEF_B); +} + +static void armada_ap806_thermal_irq(void) +{ + /* Dummy read, register ROC */ + mmio_read_32(DFX_IRQ_CAUSE_REG); +} + +static void armada_ap806_thermal_overheat_irq_init(void) +{ + uint32_t reg; + + /* Clear DFX temperature IRQ cause */ + reg = mmio_read_32(DFX_IRQ_CAUSE_REG); + + /* Enable DFX Temperature IRQ */ + reg = mmio_read_32(DFX_IRQ_MASK_REG); + reg |= DFX_IRQ_TSEN_OVERHEAT_OFFSET; + mmio_write_32(DFX_IRQ_MASK_REG, reg); + + /* Enable DFX server IRQ */ + reg = mmio_read_32(DFX_SERVER_IRQ_SUM_MASK_REG); + reg |= DFX_SERVER_IRQ_EN; + mmio_write_32(DFX_SERVER_IRQ_SUM_MASK_REG, reg); + + /* Enable overheat interrupt */ + reg = mmio_read_32(TSEN_CTRL1); + reg |= TSEN_CTRL1_INT_EN; + mmio_write_32(TSEN_CTRL1, reg); +} + +static unsigned int armada_mc_to_reg_temp(unsigned int temp_mc) +{ + unsigned int sample; + + sample = (temp_mc + COEF_B) / COEF_M; + + return sample & 0x3ff; +} + +/* + * The documentation states: + * high/low watermark = threshold +/- 0.4761 * 2^(hysteresis + 2) + * which is the mathematical derivation for: + * 0x0 <=> 1.9°C, 0x1 <=> 3.8°C, 0x2 <=> 7.6°C, 0x3 <=> 15.2°C + */ +static unsigned int hyst_levels_mc[] = {1900, 3800, 7600, 15200}; + +static unsigned int armada_mc_to_reg_hyst(int hyst_mc) +{ + int i; + + /* + * We will always take the smallest possible hysteresis to avoid risking + * the hardware integrity by enlarging the threshold by +8°C in the + * worst case. + */ + for (i = ARRAY_SIZE(hyst_levels_mc) - 1; i > 0; i--) + if (hyst_mc >= hyst_levels_mc[i]) + break; + + return i; +} + +static void armada_ap806_thermal_threshold(int thresh_mc, int hyst_mc) +{ + uint32_t ctrl1; + unsigned int threshold = armada_mc_to_reg_temp(thresh_mc); + unsigned int hysteresis = armada_mc_to_reg_hyst(hyst_mc); + + ctrl1 = mmio_read_32(TSEN_CTRL1); + /* Set Threshold */ + if (thresh_mc >= 0) { + ctrl1 &= ~(TSEN_CTRL1_THRESH_MASK); + ctrl1 |= threshold << TSEN_CTRL1_THRESH_SHIFT; + } + + /* Set Hysteresis */ + if (hyst_mc >= 0) { + ctrl1 &= ~(TSEN_CTRL1_HYST_MASK); + ctrl1 |= hysteresis << TSEN_CTRL1_HYST_SHIFT; + } + + mmio_write_32(TSEN_CTRL1, ctrl1); +} + +static void armada_select_channel(int channel) +{ + uint32_t ctrl0; + + /* Stop the measurements */ + ctrl0 = mmio_read_32(TSEN_CTRL0); + ctrl0 &= ~TSEN_CTRL0_START; + mmio_write_32(TSEN_CTRL0, ctrl0); + + /* Reset the mode, internal sensor will be automatically selected */ + ctrl0 &= ~(TSEN_CTRL0_MODE_MASK << TSEN_CTRL0_MODE_SHIFT); + + /* Other channels are external and should be selected accordingly */ + if (channel) { + /* Change the mode to external */ + ctrl0 |= TSEN_CTRL0_MODE_EXTERNAL << + TSEN_CTRL0_MODE_SHIFT; + /* Select the sensor */ + ctrl0 &= ~(TSEN_CTRL0_CHAN_MASK << TSEN_CTRL0_CHAN_SHIFT); + ctrl0 |= (channel - 1) << TSEN_CTRL0_CHAN_SHIFT; + } + + /* Actually set the mode/channel */ + mmio_write_32(TSEN_CTRL0, ctrl0); + + /* Re-start the measurements */ + ctrl0 |= TSEN_CTRL0_START; + mmio_write_32(TSEN_CTRL0, ctrl0); +} + +static void armada_ap806_thermal_init(void) +{ + uint32_t reg; + + reg = mmio_read_32(TSEN_CTRL0); + reg &= ~TSEN_CTRL0_RESET; + reg |= TSEN_CTRL0_START | TSEN_CTRL0_ENABLE; + + /* Sample every ~2ms */ + reg |= TSEN_CTRL0_OSR_MAX << TSEN_CTRL0_OSR_SHIFT; + + /* Enable average (2 samples by default) */ + reg &= ~TSEN_CTRL0_AVG_BYPASS; + + mmio_write_32(TSEN_CTRL0, reg); + + debug("thermal: Initialization done\n"); +} + +static void armada_is_valid(u_register_t *read) +{ + *read = (mmio_read_32(TSEN_STATUS) & TSEN_STATUS_VALID_MASK); +} + +int mvebu_dfx_thermal_handle(u_register_t func, u_register_t *read, + u_register_t x2, u_register_t x3) +{ + debug_enter(); + + switch (func) { + case MV_SIP_DFX_THERMAL_INIT: + armada_ap806_thermal_init(); + break; + case MV_SIP_DFX_THERMAL_READ: + armada_ap806_thermal_read(read); + break; + case MV_SIP_DFX_THERMAL_IRQ: + armada_ap806_thermal_irq(); + break; + case MV_SIP_DFX_THERMAL_THRESH: + armada_ap806_thermal_threshold(x2, x3); + armada_ap806_thermal_overheat_irq_init(); + break; + case MV_SIP_DFX_THERMAL_IS_VALID: + armada_is_valid(read); + break; + case MV_SIP_DFX_THERMAL_SEL_CHANNEL: + armada_select_channel(x2); + break; + default: + ERROR("unsupported dfx func\n"); + return -EINVAL; + } + + debug_exit(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h new file mode 100644 index 0000000..88c4de8 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* DFX sub-FID */ +#define MV_SIP_DFX_THERMAL_INIT 1 +#define MV_SIP_DFX_THERMAL_READ 2 +#define MV_SIP_DFX_THERMAL_IS_VALID 3 +#define MV_SIP_DFX_THERMAL_IRQ 4 +#define MV_SIP_DFX_THERMAL_THRESH 5 +#define MV_SIP_DFX_THERMAL_SEL_CHANNEL 6 + +#define MV_SIP_DFX_SREAD 20 +#define MV_SIP_DFX_SWRITE 21 + +int mvebu_dfx_thermal_handle(u_register_t func, u_register_t *read, + u_register_t x2, u_register_t x3); +int mvebu_dfx_misc_handle(u_register_t func, u_register_t *read, + u_register_t addr, u_register_t val); diff --git a/arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c new file mode 100644 index 0000000..189105f --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include "dfx.h" +#include +#include +#include + +/* #define DEBUG_DFX */ +#ifdef DEBUG_DFX +#define debug(format...) NOTICE(format) +#else +#define debug(format, arg...) +#endif + +#define SAR_BASE (MVEBU_REGS_BASE + 0x6F8200) +#define SAR_SIZE 0x4 +#define AP_DEV_ID_STATUS_REG (MVEBU_REGS_BASE + 0x6F8240) +#define JTAG_DEV_ID_STATUS_REG (MVEBU_REGS_BASE + 0x6F8244) +#define EFUSE_CTRL (MVEBU_REGS_BASE + 0x6F8008) +#define EFUSE_LD_BASE (MVEBU_REGS_BASE + 0x6F8F00) +#define EFUSE_LD_SIZE 0x1C +#define EFUSE_HD_BASE (MVEBU_REGS_BASE + 0x6F9000) +#define EFUSE_HD_SIZE 0x3F8 + +/* AP806 CPU DFS register mapping*/ +#define AP806_CA72MP2_0_PLL_CR_0_BASE (MVEBU_REGS_BASE + 0x6F8278) +#define AP806_CA72MP2_0_PLL_CR_1_BASE (MVEBU_REGS_BASE + 0x6F8280) +#define AP806_CA72MP2_0_PLL_CR_2_BASE (MVEBU_REGS_BASE + 0x6F8284) +#define AP806_CA72MP2_0_PLL_SR_BASE (MVEBU_REGS_BASE + 0x6F8C94) + +/* AP807 CPU DFS register mapping */ +#define AP807_DEVICE_GENERAL_CR_10_BASE (MVEBU_REGS_BASE + 0x6F8278) +#define AP807_DEVICE_GENERAL_CR_11_BASE (MVEBU_REGS_BASE + 0x6F827C) +#define AP807_DEVICE_GENERAL_STATUS_6_BASE (MVEBU_REGS_BASE + 0x6F8C98) + +#ifdef MVEBU_SOC_AP807 + #define CLUSTER_OFFSET 0x8 + #define CLK_DIVIDER_REG AP807_DEVICE_GENERAL_CR_10_BASE + #define CLK_FORCE_REG AP807_DEVICE_GENERAL_CR_11_BASE + #define CLK_RATIO_REG AP807_DEVICE_GENERAL_CR_11_BASE + #define CLK_RATIO_STATE_REG AP807_DEVICE_GENERAL_STATUS_6_BASE +#else + #define CLUSTER_OFFSET 0x14 + #define CLK_DIVIDER_REG AP806_CA72MP2_0_PLL_CR_0_BASE + #define CLK_FORCE_REG AP806_CA72MP2_0_PLL_CR_1_BASE + #define CLK_RATIO_REG AP806_CA72MP2_0_PLL_CR_2_BASE + #define CLK_RATIO_STATE_REG AP806_CA72MP2_0_PLL_SR_BASE +#endif /* MVEBU_SOC_AP807 */ + +static _Bool is_valid(u_register_t addr) +{ + switch (addr) { + case AP_DEV_ID_STATUS_REG: + case JTAG_DEV_ID_STATUS_REG: + case SAR_BASE ... (SAR_BASE + SAR_SIZE): + case EFUSE_LD_BASE ... (EFUSE_LD_BASE + EFUSE_LD_SIZE): + case EFUSE_HD_BASE ... (EFUSE_HD_BASE + EFUSE_HD_SIZE): + case EFUSE_CTRL: + /* cpu-clk related registers */ + case CLK_DIVIDER_REG: + case CLK_DIVIDER_REG + CLUSTER_OFFSET: + case CLK_FORCE_REG: + case CLK_FORCE_REG + CLUSTER_OFFSET: +#ifndef MVEBU_SOC_AP807 + case CLK_RATIO_REG: + case CLK_RATIO_REG + CLUSTER_OFFSET: +#endif + case CLK_RATIO_STATE_REG: + case CLK_RATIO_STATE_REG + CLUSTER_OFFSET: + return true; + default: + return false; + } +} + +static int armada_dfx_sread(u_register_t *read, u_register_t addr) +{ + if (!is_valid(addr)) + return -EINVAL; + + *read = mmio_read_32(addr); + + return 0; +} + +static int armada_dfx_swrite(u_register_t addr, u_register_t val) +{ + if (!is_valid(addr)) + return -EINVAL; + + mmio_write_32(addr, val); + + return 0; +} + +int mvebu_dfx_misc_handle(u_register_t func, u_register_t *read, + u_register_t addr, u_register_t val) +{ + debug_enter(); + + debug("func %ld, addr 0x%lx, val 0x%lx\n", func, addr, val); + + switch (func) { + case MV_SIP_DFX_SREAD: + return armada_dfx_sread(read, addr); + case MV_SIP_DFX_SWRITE: + return armada_dfx_swrite(addr, val); + default: + ERROR("unsupported dfx misc sub-func\n"); + return -EINVAL; + } + + debug_exit(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/thermal.c b/arm-trusted-firmware/drivers/marvell/thermal.c new file mode 100644 index 0000000..a501ab4 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/thermal.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Driver for thermal unit located in Marvell ARMADA 8K and compatible SoCs */ + +#include +#include + +int marvell_thermal_init(struct tsen_config *tsen_cfg) +{ + if (tsen_cfg->tsen_ready == 1) { + INFO("thermal sensor is already initialized\n"); + return 0; + } + + if (tsen_cfg->ptr_tsen_probe == NULL) { + ERROR("initial thermal sensor configuration is missing\n"); + return -1; + } + + if (tsen_cfg->ptr_tsen_probe(tsen_cfg)) { + ERROR("thermal sensor initialization failed\n"); + return -1; + } + + VERBOSE("thermal sensor was initialized\n"); + + return 0; +} + +int marvell_thermal_read(struct tsen_config *tsen_cfg, int *temp) +{ + if (temp == NULL) { + ERROR("NULL pointer for temperature read\n"); + return -1; + } + + if (tsen_cfg->ptr_tsen_read == NULL || + tsen_cfg->tsen_ready == 0) { + ERROR("thermal sensor was not initialized\n"); + return -1; + } + + if (tsen_cfg->ptr_tsen_read(tsen_cfg, temp)) { + ERROR("temperature read failed\n"); + return -1; + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/uart/a3700_console.S b/arm-trusted-firmware/drivers/marvell/uart/a3700_console.S new file mode 100644 index 0000000..c7eb165 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/uart/a3700_console.S @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_a3700_core_putc + .globl console_a3700_core_init + .globl console_a3700_core_getc + .globl console_a3700_core_flush + + .globl console_a3700_putc + .globl console_a3700_getc + .globl console_a3700_flush + + /* ----------------------------------------------- + * int console_a3700_core_init(unsigned long base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success + * Clobber list : x1, x2, x3, x4 + * ----------------------------------------------- + */ +func console_a3700_core_init + /* Check the input base address */ + cbz x0, init_fail + /* Check baud rate and uart clock for sanity */ + cbz w1, init_fail + cbz w2, init_fail + + /* + * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is + * still not empty, TX FIFO will reset by all means. + */ + mov w4, #30 /* max time out 30 * 100 us */ +2: + /* Check whether TX (THR and TSR) is empty */ + ldr w3, [x0, #UART_STATUS_REG] + and w3, w3, #UARTLSR_TXEMPTY + cmp w3, #0 + b.ne 4f + + /* Delay */ + mov w3, #60000 /* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */ +3: + sub w3, w3, #1 + cmp w3, #0 + b.ne 3b + + /* Check whether wait timeout expired */ + sub w4, w4, #1 + cmp w4, #0 + b.ne 2b + +4: + /* Reset UART via North Bridge Peripheral */ + mov_imm x4, MVEBU_NB_RESET_REG + ldr w3, [x4] + bic w3, w3, #MVEBU_NB_RESET_UART_N + str w3, [x4] + orr w3, w3, #MVEBU_NB_RESET_UART_N + str w3, [x4] + + /* Reset FIFO */ + mov w3, #UART_CTRL_RXFIFO_RESET + orr w3, w3, #UART_CTRL_TXFIFO_RESET + str w3, [x0, #UART_CTRL_REG] + + /* Delay */ + mov w3, #2000 +1: + sub w3, w3, #1 + cmp w3, #0 + b.ne 1b + + /* Program the baudrate */ + /* Divisor = Round(Uartclock / (16 * baudrate)) */ + lsl w2, w2, #4 + add w1, w1, w2, lsr #1 + udiv w2, w1, w2 + and w2, w2, #0x3ff /* clear all other bits to use default clock */ + + str w2, [x0, #UART_BAUD_REG]/* set baud rate divisor */ + + /* Set UART to default 16X scheme */ + mov w3, #0 + str w3, [x0, #UART_POSSR_REG] + + /* No Parity, 1 Stop */ + mov w3, #0 + str w3, [x0, #UART_CTRL_REG] + + mov w0, #1 + ret +init_fail: + mov w0, #0 + ret +endfunc console_a3700_core_init + + .globl console_a3700_register + + /* ----------------------------------------------- + * int console_a3700_register(console_t *console, + uintptr_t base, uint32_t clk, uint32_t baud) + * Function to initialize and register a new a3700 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x3, x4, x6, x7, x14 + * ----------------------------------------------- + */ +func console_a3700_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_a3700_core_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register a3700, putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_a3700_register + + /* -------------------------------------------------------- + * int console_a3700_core_putc(int c, unsigned int base_addr) + * 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 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_a3700_core_putc + /* Check the input parameter */ + cbz x1, putc_error + + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f + /* Check if the transmit FIFO is full */ +1: ldr w2, [x1, #UART_STATUS_REG] + and w2, w2, #UARTLSR_TXFIFOFULL + cmp w2, #UARTLSR_TXFIFOFULL + b.eq 1b + mov w2, #0xD /* '\r' */ + str w2, [x1, #UART_TX_REG] + + /* Check if the transmit FIFO is full */ +2: ldr w2, [x1, #UART_STATUS_REG] + and w2, w2, #UARTLSR_TXFIFOFULL + cmp w2, #UARTLSR_TXFIFOFULL + b.eq 2b + str w0, [x1, #UART_TX_REG] + ret +putc_error: + mov w0, #-1 + ret +endfunc console_a3700_core_putc + + /* -------------------------------------------------------- + * int console_a3700_putc(int c, console_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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_a3700_putc + ldr x1, [x1, #CONSOLE_T_BASE] + b console_a3700_core_putc +endfunc console_a3700_putc + + /* --------------------------------------------- + * int console_a3700_core_getc(void) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : w0 - console base address + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_a3700_core_getc + /* Check if there is a pending character */ + ldr w1, [x0, #UART_STATUS_REG] + and w1, w1, #UARTLSR_RXRDY + cmp w1, #UARTLSR_RXRDY + b.ne getc_no_char + ldr w0, [x0, #UART_RX_REG] + and w0, w0, #0xff + ret +getc_no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_a3700_core_getc + + /* --------------------------------------------- + * int console_a3700_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - pointer to console_t structure + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_a3700_getc + ldr x0, [x0, #CONSOLE_T_BASE] + b console_a3700_core_getc +endfunc console_a3700_getc + + /* --------------------------------------------- + * void console_a3700_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_a3700_core_flush + /* Wait for the TX (THR and TSR) to be empty */ +1: ldr w1, [x0, #UART_STATUS_REG] + and w1, w1, #UARTLSR_TXEMPTY + cmp w1, #UARTLSR_TXEMPTY + b.ne 1b + ret +endfunc console_a3700_core_flush + + /* --------------------------------------------- + * void console_a3700_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_a3700_flush + ldr x0, [x0, #CONSOLE_T_BASE] + b console_a3700_core_flush +endfunc console_a3700_flush + diff --git a/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c b/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c new file mode 100644 index 0000000..792f235 --- /dev/null +++ b/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#if TPM_ALG_ID == TPM_ALG_SHA512 +#define CRYPTO_MD_ID CRYPTO_MD_SHA512 +#elif TPM_ALG_ID == TPM_ALG_SHA384 +#define CRYPTO_MD_ID CRYPTO_MD_SHA384 +#elif TPM_ALG_ID == TPM_ALG_SHA256 +#define CRYPTO_MD_ID CRYPTO_MD_SHA256 +#else +# error Invalid TPM algorithm. +#endif /* TPM_ALG_ID */ + +/* Running Event Log Pointer */ +static uint8_t *log_ptr; + +/* Pointer to the first byte past end of the Event Log buffer */ +static uintptr_t log_end; + +/* Pointer to event_log_metadata_t */ +static const event_log_metadata_t *plat_metadata_ptr; + +/* TCG_EfiSpecIdEvent */ +static const id_event_headers_t id_event_header = { + .header = { + .pcr_index = PCR_0, + .event_type = EV_NO_ACTION, + .digest = {0}, + .event_size = (uint32_t)(sizeof(id_event_struct_t) + + (sizeof(id_event_algorithm_size_t) * + HASH_ALG_COUNT)) + }, + + .struct_header = { + .signature = TCG_ID_EVENT_SIGNATURE_03, + .platform_class = PLATFORM_CLASS_CLIENT, + .spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2, + .spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2, + .spec_errata = TCG_SPEC_ERRATA_TPM2, + .uintn_size = (uint8_t)(sizeof(unsigned int) / + sizeof(uint32_t)), + .number_of_algorithms = HASH_ALG_COUNT + } +}; + +static const event2_header_t locality_event_header = { + /* + * All EV_NO_ACTION events SHALL set + * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified + */ + .pcr_index = PCR_0, + + /* + * All EV_NO_ACTION events SHALL set + * TCG_PCR_EVENT2.eventType = 03h + */ + .event_type = EV_NO_ACTION, + + /* + * All EV_NO_ACTION events SHALL set TCG_PCR_EVENT2.digests to all + * 0x00's for each allocated Hash algorithm + */ + .digests = { + .count = HASH_ALG_COUNT + } +}; + +/* + * Record a measurement as a TCG_PCR_EVENT2 event + * + * @param[in] hash Pointer to hash data of TCG_DIGEST_SIZE bytes + * @param[in] metadata_ptr Pointer to event_log_metadata_t structure + * + * There must be room for storing this new event into the event log buffer. + */ +static void event_log_record(const uint8_t *hash, + const event_log_metadata_t *metadata_ptr) +{ + void *ptr = log_ptr; + uint32_t name_len; + + assert(hash != NULL); + assert(metadata_ptr != NULL); + assert(metadata_ptr->name != NULL); + /* event_log_init() must have been called prior to this. */ + assert(log_ptr != NULL); + + name_len = (uint32_t)strlen(metadata_ptr->name) + 1U; + + /* Check for space in Event Log buffer */ + assert(((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) < + log_end); + + /* + * As per TCG specifications, firmware components that are measured + * into PCR[0] must be logged in the event log using the event type + * EV_POST_CODE. + */ + /* TCG_PCR_EVENT2.PCRIndex */ + ((event2_header_t *)ptr)->pcr_index = metadata_ptr->pcr; + + /* TCG_PCR_EVENT2.EventType */ + ((event2_header_t *)ptr)->event_type = EV_POST_CODE; + + /* TCG_PCR_EVENT2.Digests.Count */ + ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests); + ((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT; + + /* TCG_PCR_EVENT2.Digests[] */ + ptr = (uint8_t *)((uintptr_t)ptr + + offsetof(tpml_digest_values, digests)); + + /* TCG_PCR_EVENT2.Digests[].AlgorithmId */ + ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID; + + /* TCG_PCR_EVENT2.Digests[].Digest[] */ + ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest)); + + /* Copy digest */ + (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE); + + /* TCG_PCR_EVENT2.EventSize */ + ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE); + ((event2_data_t *)ptr)->event_size = name_len; + + /* Copy event data to TCG_PCR_EVENT2.Event */ + (void)memcpy((void *)(((event2_data_t *)ptr)->event), + (const void *)metadata_ptr->name, name_len); + + /* End of event data */ + log_ptr = (uint8_t *)((uintptr_t)ptr + + offsetof(event2_data_t, event) + name_len); +} + +/* + * Initialise Event Log global variables, used during the recording + * of various payload measurements into the Event Log buffer + * + * @param[in] event_log_start Base address of Event Log buffer + * @param[in] event_log_finish End address of Event Log buffer, + * it is a first byte past end of the + * buffer + */ +void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish) +{ + assert(event_log_start != NULL); + assert(event_log_finish > event_log_start); + + log_ptr = event_log_start; + log_end = (uintptr_t)event_log_finish; + + /* Get pointer to platform's event_log_metadata_t structure */ + plat_metadata_ptr = plat_event_log_get_metadata(); + assert(plat_metadata_ptr != NULL); +} + +/* + * Initialises Event Log by writing Specification ID and + * Startup Locality events + */ +void event_log_write_header(void) +{ + const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE; + void *ptr = log_ptr; + + /* event_log_init() must have been called prior to this. */ + assert(log_ptr != NULL); + + /* + * Add Specification ID Event first + * + * Copy TCG_EfiSpecIDEventStruct structure header + */ + (void)memcpy(ptr, (const void *)&id_event_header, + sizeof(id_event_header)); + ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_header)); + + /* TCG_EfiSpecIdEventAlgorithmSize structure */ + ((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID; + ((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE; + ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_algorithm_size_t)); + + /* + * TCG_EfiSpecIDEventStruct.vendorInfoSize + * No vendor data + */ + ((id_event_struct_data_t *)ptr)->vendor_info_size = 0; + ptr = (uint8_t *)((uintptr_t)ptr + + offsetof(id_event_struct_data_t, vendor_info)); + + /* + * The Startup Locality event should be placed in the log before + * any event which extends PCR[0]. + * + * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3 + */ + + /* Copy Startup Locality Event Header */ + (void)memcpy(ptr, (const void *)&locality_event_header, + sizeof(locality_event_header)); + ptr = (uint8_t *)((uintptr_t)ptr + sizeof(locality_event_header)); + + /* TCG_PCR_EVENT2.Digests[].AlgorithmId */ + ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID; + + /* TCG_PCR_EVENT2.Digests[].Digest[] */ + (void)memset(&((tpmt_ha *)ptr)->digest, 0, TPM_ALG_ID); + ptr = (uint8_t *)((uintptr_t)ptr + + offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE); + + /* TCG_PCR_EVENT2.EventSize */ + ((event2_data_t *)ptr)->event_size = + (uint32_t)sizeof(startup_locality_event_t); + ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event)); + + /* TCG_EfiStartupLocalityEvent.Signature */ + (void)memcpy(ptr, (const void *)locality_signature, + sizeof(TCG_STARTUP_LOCALITY_SIGNATURE)); + + /* + * TCG_EfiStartupLocalityEvent.StartupLocality = 0: + * the platform's boot firmware + */ + ((startup_locality_event_t *)ptr)->startup_locality = 0U; + log_ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t)); +} + +/* + * Calculate and write hash of image, configuration data, etc. + * to Event Log. + * + * @param[in] data_base Address of data + * @param[in] data_size Size of data + * @param[in] data_id Data ID + * @return: + * 0 = success + * < 0 = error + */ +int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size, + uint32_t data_id) +{ + unsigned char hash_data[CRYPTO_MD_MAX_SIZE]; + int rc; + const event_log_metadata_t *metadata_ptr = plat_metadata_ptr; + + /* Get the metadata associated with this image. */ + while ((metadata_ptr->id != EVLOG_INVALID_ID) && + (metadata_ptr->id != data_id)) { + metadata_ptr++; + } + assert(metadata_ptr->id != EVLOG_INVALID_ID); + + /* Calculate hash */ + rc = crypto_mod_calc_hash(CRYPTO_MD_ID, + (void *)data_base, data_size, hash_data); + if (rc != 0) { + return rc; + } + + event_log_record(hash_data, metadata_ptr); + + return 0; +} + +/* + * Get current Event Log buffer size i.e. used space of Event Log buffer + * + * @param[in] event_log_start Base Pointer to Event Log buffer + * + * @return: current Size of Event Log buffer + */ +size_t event_log_get_cur_size(uint8_t *event_log_start) +{ + assert(event_log_start != NULL); + assert(log_ptr >= event_log_start); + + return (size_t)((uintptr_t)log_ptr - (uintptr_t)event_log_start); +} diff --git a/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.mk b/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.mk new file mode 100644 index 0000000..1ff4aa8 --- /dev/null +++ b/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.mk @@ -0,0 +1,36 @@ +# +# Copyright (c) 2020-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Default log level to dump the event log (LOG_LEVEL_INFO) +EVENT_LOG_LEVEL ?= 40 + +# TPM hash algorithm. +# SHA-256 (or stronger) is required for all devices that are TPM 2.0 compliant. +TPM_HASH_ALG := sha256 + +ifeq (${TPM_HASH_ALG}, sha512) + TPM_ALG_ID := TPM_ALG_SHA512 + TCG_DIGEST_SIZE := 64U +else ifeq (${TPM_HASH_ALG}, sha384) + TPM_ALG_ID := TPM_ALG_SHA384 + TCG_DIGEST_SIZE := 48U +else + TPM_ALG_ID := TPM_ALG_SHA256 + TCG_DIGEST_SIZE := 32U +endif #TPM_HASH_ALG + +# Set definitions for Measured Boot driver. +$(eval $(call add_defines,\ + $(sort \ + TPM_ALG_ID \ + TCG_DIGEST_SIZE \ + EVENT_LOG_LEVEL \ +))) + +EVENT_LOG_SRC_DIR := drivers/measured_boot/event_log/ + +EVENT_LOG_SOURCES := ${EVENT_LOG_SRC_DIR}event_log.c \ + ${EVENT_LOG_SRC_DIR}event_print.c diff --git a/arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c b/arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c new file mode 100644 index 0000000..e2ba174 --- /dev/null +++ b/arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#if LOG_LEVEL >= EVENT_LOG_LEVEL + +/* + * Print TCG_EfiSpecIDEventStruct + * + * @param[in/out] log_addr Pointer to Event Log + * @param[in/out] log_size Pointer to Event Log size + */ +static void id_event_print(uint8_t **log_addr, size_t *log_size) +{ + unsigned int i; + uint8_t info_size, *info_size_ptr; + void *ptr = *log_addr; + id_event_headers_t *event = (id_event_headers_t *)ptr; + id_event_algorithm_size_t *alg_ptr; + uint32_t event_size, number_of_algorithms; + size_t digest_len; +#if ENABLE_ASSERTIONS + const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size); + bool valid = true; +#endif + + assert(*log_size >= sizeof(id_event_headers_t)); + + /* The fields of the event log header are defined to be PCRIndex of 0, + * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and + * Event content defined as TCG_EfiSpecIDEventStruct. + */ + LOG_EVENT("TCG_EfiSpecIDEvent:\n"); + LOG_EVENT(" PCRIndex : %u\n", event->header.pcr_index); + assert(event->header.pcr_index == (uint32_t)PCR_0); + + LOG_EVENT(" EventType : %u\n", event->header.event_type); + assert(event->header.event_type == EV_NO_ACTION); + + LOG_EVENT(" Digest :"); + for (i = 0U; i < sizeof(event->header.digest); ++i) { + uint8_t val = event->header.digest[i]; + + (void)printf(" %02x", val); + if ((i & U(0xF)) == 0U) { + (void)printf("\n"); + LOG_EVENT("\t\t :"); + } +#if ENABLE_ASSERTIONS + if (val != 0U) { + valid = false; + } +#endif + } + if ((i & U(0xF)) != 0U) { + (void)printf("\n"); + } + + assert(valid); + + /* EventSize */ + event_size = event->header.event_size; + LOG_EVENT(" EventSize : %u\n", event_size); + + LOG_EVENT(" Signature : %s\n", + event->struct_header.signature); + LOG_EVENT(" PlatformClass : %u\n", + event->struct_header.platform_class); + LOG_EVENT(" SpecVersion : %u.%u.%u\n", + event->struct_header.spec_version_major, + event->struct_header.spec_version_minor, + event->struct_header.spec_errata); + LOG_EVENT(" UintnSize : %u\n", + event->struct_header.uintn_size); + + /* NumberOfAlgorithms */ + number_of_algorithms = event->struct_header.number_of_algorithms; + LOG_EVENT(" NumberOfAlgorithms : %u\n", number_of_algorithms); + + /* Address of DigestSizes[] */ + alg_ptr = event->struct_header.digest_size; + + /* Size of DigestSizes[] */ + digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t); + assert(((uintptr_t)alg_ptr + digest_len) <= (uintptr_t)end_ptr); + + LOG_EVENT(" DigestSizes :\n"); + for (i = 0U; i < number_of_algorithms; ++i) { + LOG_EVENT(" #%u AlgorithmId : SHA", i); + uint16_t algorithm_id = alg_ptr[i].algorithm_id; + + switch (algorithm_id) { + case TPM_ALG_SHA256: + (void)printf("256\n"); + break; + case TPM_ALG_SHA384: + (void)printf("384\n"); + break; + case TPM_ALG_SHA512: + (void)printf("512\n"); + break; + default: + (void)printf("?\n"); + ERROR("Algorithm 0x%x not found\n", algorithm_id); + assert(false); + } + + LOG_EVENT(" DigestSize : %u\n", + alg_ptr[i].digest_size); + } + + /* Address of VendorInfoSize */ + info_size_ptr = (uint8_t *)((uintptr_t)alg_ptr + digest_len); + assert((uintptr_t)info_size_ptr <= (uintptr_t)end_ptr); + + info_size = *info_size_ptr++; + LOG_EVENT(" VendorInfoSize : %u\n", info_size); + + /* Check VendorInfo end address */ + assert(((uintptr_t)info_size_ptr + info_size) <= (uintptr_t)end_ptr); + + /* Check EventSize */ + assert(event_size == (sizeof(id_event_struct_t) + + digest_len + info_size)); + if (info_size != 0U) { + LOG_EVENT(" VendorInfo :"); + for (i = 0U; i < info_size; ++i) { + (void)printf(" %02x", *info_size_ptr++); + } + (void)printf("\n"); + } + + *log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr; + *log_addr = info_size_ptr; +} + +/* + * Print TCG_PCR_EVENT2 + * + * @param[in/out] log_addr Pointer to Event Log + * @param[in/out] log_size Pointer to Event Log size + */ +static void event2_print(uint8_t **log_addr, size_t *log_size) +{ + uint32_t event_size, count; + size_t sha_size, digests_size = 0U; + void *ptr = *log_addr; +#if ENABLE_ASSERTIONS + const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size); +#endif + + assert(*log_size >= sizeof(event2_header_t)); + + LOG_EVENT("PCR_Event2:\n"); + LOG_EVENT(" PCRIndex : %u\n", + ((event2_header_t *)ptr)->pcr_index); + LOG_EVENT(" EventType : %u\n", + ((event2_header_t *)ptr)->event_type); + + count = ((event2_header_t *)ptr)->digests.count; + LOG_EVENT(" Digests Count : %u\n", count); + + /* Address of TCG_PCR_EVENT2.Digests[] */ + ptr = (uint8_t *)ptr + sizeof(event2_header_t); + assert(((uintptr_t)ptr <= (uintptr_t)end_ptr) && (count != 0U)); + + for (unsigned int i = 0U; i < count; ++i) { + /* Check AlgorithmId address */ + assert(((uintptr_t)ptr + + offsetof(tpmt_ha, digest)) <= (uintptr_t)end_ptr); + + LOG_EVENT(" #%u AlgorithmId : SHA", i); + switch (((tpmt_ha *)ptr)->algorithm_id) { + case TPM_ALG_SHA256: + sha_size = SHA256_DIGEST_SIZE; + (void)printf("256\n"); + break; + case TPM_ALG_SHA384: + sha_size = SHA384_DIGEST_SIZE; + (void)printf("384\n"); + break; + case TPM_ALG_SHA512: + sha_size = SHA512_DIGEST_SIZE; + (void)printf("512\n"); + break; + default: + (void)printf("?\n"); + ERROR("Algorithm 0x%x not found\n", + ((tpmt_ha *)ptr)->algorithm_id); + panic(); + } + + /* End of Digest[] */ + ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest)); + assert(((uintptr_t)ptr + sha_size) <= (uintptr_t)end_ptr); + + /* Total size of all digests */ + digests_size += sha_size; + + LOG_EVENT(" Digest :"); + for (unsigned int j = 0U; j < sha_size; ++j) { + (void)printf(" %02x", *(uint8_t *)ptr++); + if ((j & U(0xF)) == U(0xF)) { + (void)printf("\n"); + if (j < (sha_size - 1U)) { + LOG_EVENT("\t\t :"); + } + } + } + } + + /* TCG_PCR_EVENT2.EventSize */ + assert(((uintptr_t)ptr + offsetof(event2_data_t, event)) <= (uintptr_t)end_ptr); + + event_size = ((event2_data_t *)ptr)->event_size; + LOG_EVENT(" EventSize : %u\n", event_size); + + /* Address of TCG_PCR_EVENT2.Event[EventSize] */ + ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event)); + + /* End of TCG_PCR_EVENT2.Event[EventSize] */ + assert(((uintptr_t)ptr + event_size) <= (uintptr_t)end_ptr); + + if ((event_size == sizeof(startup_locality_event_t)) && + (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) { + LOG_EVENT(" Signature : %s\n", + ((startup_locality_event_t *)ptr)->signature); + LOG_EVENT(" StartupLocality : %u\n", + ((startup_locality_event_t *)ptr)->startup_locality); + } else { + LOG_EVENT(" Event : %s\n", (uint8_t *)ptr); + } + + *log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr; + *log_addr = (uint8_t *)ptr + event_size; +} +#endif /* LOG_LEVEL >= EVENT_LOG_LEVEL */ + +/* + * Print Event Log + * + * @param[in] log_addr Pointer to Event Log + * @param[in] log_size Event Log size + */ +void dump_event_log(uint8_t *log_addr, size_t log_size) +{ +#if LOG_LEVEL >= EVENT_LOG_LEVEL + assert(log_addr != NULL); + + /* Print TCG_EfiSpecIDEvent */ + id_event_print(&log_addr, &log_size); + + while (log_size != 0U) { + event2_print(&log_addr, &log_size); + } +#endif +} diff --git a/arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c b/arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c new file mode 100644 index 0000000..b0270c9 --- /dev/null +++ b/arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c @@ -0,0 +1,614 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * Copyright (C) 2018 Icenowy Zheng + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* + * This driver is for Mentor Graphics Inventra MI2CV IP core, which is used + * for Marvell and Allwinner SoCs in ATF. + */ + +#include + +#include +#include +#include +#include + +#include + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +#define DEBUG_I2C +#endif + +#define I2C_TIMEOUT_VALUE 0x500 +#define I2C_MAX_RETRY_CNT 1000 +#define I2C_CMD_WRITE 0x0 +#define I2C_CMD_READ 0x1 + +#define I2C_DATA_ADDR_7BIT_OFFS 0x1 +#define I2C_DATA_ADDR_7BIT_MASK (0xFF << I2C_DATA_ADDR_7BIT_OFFS) + +#define I2C_CONTROL_ACK 0x00000004 +#define I2C_CONTROL_IFLG 0x00000008 +#define I2C_CONTROL_STOP 0x00000010 +#define I2C_CONTROL_START 0x00000020 +#define I2C_CONTROL_TWSIEN 0x00000040 +#define I2C_CONTROL_INTEN 0x00000080 + +#define I2C_STATUS_START 0x08 +#define I2C_STATUS_REPEATED_START 0x10 +#define I2C_STATUS_ADDR_W_ACK 0x18 +#define I2C_STATUS_DATA_W_ACK 0x28 +#define I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER 0x38 +#define I2C_STATUS_ADDR_R_ACK 0x40 +#define I2C_STATUS_DATA_R_ACK 0x50 +#define I2C_STATUS_DATA_R_NAK 0x58 +#define I2C_STATUS_LOST_ARB_GENERAL_CALL 0x78 +#define I2C_STATUS_IDLE 0xF8 + +#define I2C_UNSTUCK_TRIGGER 0x1 +#define I2C_UNSTUCK_ONGOING 0x2 +#define I2C_UNSTUCK_ERROR 0x4 + +static struct mentor_i2c_regs *base; + +static int mentor_i2c_lost_arbitration(uint32_t *status) +{ + *status = mmio_read_32((uintptr_t)&base->status); + if ((*status == I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER) || + (*status == I2C_STATUS_LOST_ARB_GENERAL_CALL)) + return -EAGAIN; + + return 0; +} + +static void mentor_i2c_interrupt_clear(void) +{ + uint32_t reg; + + reg = mmio_read_32((uintptr_t)&base->control); +#ifndef I2C_INTERRUPT_CLEAR_INVERTED + reg &= ~(I2C_CONTROL_IFLG); +#else + reg |= I2C_CONTROL_IFLG; +#endif + mmio_write_32((uintptr_t)&base->control, reg); + /* Wait for 1 us for the clear to take effect */ + udelay(1); +} + +static bool mentor_i2c_interrupt_get(void) +{ + uint32_t reg; + + /* get the interrupt flag bit */ + reg = mmio_read_32((uintptr_t)&base->control); + reg &= I2C_CONTROL_IFLG; + return (reg != 0U); +} + +static int mentor_i2c_wait_interrupt(void) +{ + uint32_t timeout = 0; + + while (!mentor_i2c_interrupt_get() && (timeout++ < I2C_TIMEOUT_VALUE)) + ; + if (timeout >= I2C_TIMEOUT_VALUE) + return -ETIMEDOUT; + + return 0; +} + +static int mentor_i2c_start_bit_set(void) +{ + int is_int_flag = 0; + uint32_t status; + + if (mentor_i2c_interrupt_get()) + is_int_flag = 1; + + /* set start bit */ + mmio_write_32((uintptr_t)&base->control, + mmio_read_32((uintptr_t)&base->control) | + I2C_CONTROL_START); + + /* in case that the int flag was set before i.e. repeated start bit */ + if (is_int_flag) { + VERBOSE("%s: repeated start Bit\n", __func__); + mentor_i2c_interrupt_clear(); + } + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + + /* check that start bit went down */ + if ((mmio_read_32((uintptr_t)&base->control) & + I2C_CONTROL_START) != 0) { + ERROR("Start bit didn't went down\n"); + return -EPERM; + } + + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if ((status != I2C_STATUS_START) && + (status != I2C_STATUS_REPEATED_START)) { + ERROR("Got status %x after enable start bit.\n", status); + return -EPERM; + } + + return 0; +} + +static int mentor_i2c_stop_bit_set(void) +{ + int timeout; + uint32_t status; + + /* Generate stop bit */ + mmio_write_32((uintptr_t)&base->control, + mmio_read_32((uintptr_t)&base->control) | + I2C_CONTROL_STOP); + mentor_i2c_interrupt_clear(); + + timeout = 0; + /* Read control register, check the control stop bit */ + while ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) && + (timeout++ < I2C_TIMEOUT_VALUE)) + ; + if (timeout >= I2C_TIMEOUT_VALUE) { + ERROR("Stop bit didn't went down\n"); + return -ETIMEDOUT; + } + + /* check that stop bit went down */ + if ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) != 0) { + ERROR("Stop bit didn't went down\n"); + return -EPERM; + } + + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if (status != I2C_STATUS_IDLE) { + ERROR("Got status %x after enable stop bit.\n", status); + return -EPERM; + } + + return 0; +} + +static int mentor_i2c_address_set(uint8_t chain, int command) +{ + uint32_t reg, status; + + reg = (chain << I2C_DATA_ADDR_7BIT_OFFS) & I2C_DATA_ADDR_7BIT_MASK; + reg |= command; + mmio_write_32((uintptr_t)&base->data, reg); + udelay(1); + + mentor_i2c_interrupt_clear(); + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if (((status != I2C_STATUS_ADDR_R_ACK) && (command == I2C_CMD_READ)) || + ((status != I2C_STATUS_ADDR_W_ACK) && (command == I2C_CMD_WRITE))) { + /* only in debug, since in boot we try to read the SPD + * of both DRAM, and we don't want error messages in cas + * DIMM doesn't exist. + */ + INFO("%s: ERROR - status %x addr in %s mode.\n", __func__, + status, (command == I2C_CMD_WRITE) ? "Write" : "Read"); + return -EPERM; + } + + return 0; +} + +/* + * The I2C module contains a clock divider to generate the SCL clock. + * This function calculates and sets the and fields in the I2C Baud + * Rate Register (t=01) to obtain given 'requested_speed'. + * The requested_speed will be equal to: + * CONFIG_SYS_TCLK / (10 * (M + 1) * (2 << N)) + * Where M is the value represented by bits[6:3] and N is the value represented + * by bits[2:0] of "I2C Baud Rate Register". + * Therefore max M which can be set is 16 (2^4) and max N is 8 (2^3). So the + * lowest possible baudrate is: + * CONFIG_SYS_TCLK/(10 * (16 +1) * (2 << 8), which equals to: + * CONFIG_SYS_TCLK/87040. Assuming that CONFIG_SYS_TCLK=250MHz, the lowest + * possible frequency is ~2,872KHz. + */ +static unsigned int mentor_i2c_bus_speed_set(unsigned int requested_speed) +{ + unsigned int n, m, freq, margin, min_margin = 0xffffffff; + unsigned int actual_n = 0, actual_m = 0; + int val; + + /* Calculate N and M for the TWSI clock baud rate */ + for (n = 0; n < 8; n++) { + for (m = 0; m < 16; m++) { + freq = CONFIG_SYS_TCLK / (10 * (m + 1) * (2 << n)); + val = requested_speed - freq; + margin = (val > 0) ? val : -val; + + if ((freq <= requested_speed) && + (margin < min_margin)) { + min_margin = margin; + actual_n = n; + actual_m = m; + } + } + } + VERBOSE("%s: actual_n = %u, actual_m = %u\n", + __func__, actual_n, actual_m); + /* Set the baud rate */ + mmio_write_32((uintptr_t)&base->baudrate, (actual_m << 3) | actual_n); + + return 0; +} + +#ifdef DEBUG_I2C +static int mentor_i2c_probe(uint8_t chip) +{ + int ret = 0; + + ret = mentor_i2c_start_bit_set(); + if (ret != 0) { + mentor_i2c_stop_bit_set(); + ERROR("%s - %d: %s", __func__, __LINE__, + "mentor_i2c_start_bit_set failed\n"); + return -EPERM; + } + + ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); + if (ret != 0) { + mentor_i2c_stop_bit_set(); + ERROR("%s - %d: %s", __func__, __LINE__, + "mentor_i2c_address_set failed\n"); + return -EPERM; + } + + mentor_i2c_stop_bit_set(); + + VERBOSE("%s: successful I2C probe\n", __func__); + + return ret; +} +#endif + +/* regular i2c transaction */ +static int mentor_i2c_data_receive(uint8_t *p_block, uint32_t block_size) +{ + uint32_t reg, status, block_size_read = block_size; + + /* Wait for cause interrupt */ + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + while (block_size_read) { + if (block_size_read == 1) { + reg = mmio_read_32((uintptr_t)&base->control); + reg &= ~(I2C_CONTROL_ACK); + mmio_write_32((uintptr_t)&base->control, reg); + } + mentor_i2c_interrupt_clear(); + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if ((status != I2C_STATUS_DATA_R_ACK) && + (block_size_read != 1)) { + ERROR("Status %x in read transaction\n", status); + return -EPERM; + } + if ((status != I2C_STATUS_DATA_R_NAK) && + (block_size_read == 1)) { + ERROR("Status %x in Rd Terminate\n", status); + return -EPERM; + } + + /* read the data */ + *p_block = (uint8_t) mmio_read_32((uintptr_t)&base->data); + VERBOSE("%s: place %d read %x\n", __func__, + block_size - block_size_read, *p_block); + p_block++; + block_size_read--; + } + + return 0; +} + +static int mentor_i2c_data_transmit(uint8_t *p_block, uint32_t block_size) +{ + uint32_t status, block_size_write = block_size; + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + + while (block_size_write) { + /* write the data */ + mmio_write_32((uintptr_t)&base->data, (uint32_t) *p_block); + VERBOSE("%s: index = %d, data = %x\n", __func__, + block_size - block_size_write, *p_block); + p_block++; + block_size_write--; + + mentor_i2c_interrupt_clear(); + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if (status != I2C_STATUS_DATA_W_ACK) { + ERROR("Status %x in write transaction\n", status); + return -EPERM; + } + } + + return 0; +} + +static int mentor_i2c_target_offset_set(uint8_t chip, uint32_t addr, int alen) +{ + uint8_t off_block[2]; + uint32_t off_size; + + if (alen == 2) { /* 2-byte addresses support */ + off_block[0] = (addr >> 8) & 0xff; + off_block[1] = addr & 0xff; + off_size = 2; + } else { /* 1-byte addresses support */ + off_block[0] = addr & 0xff; + off_size = 1; + } + VERBOSE("%s: off_size = %x addr1 = %x addr2 = %x\n", __func__, + off_size, off_block[0], off_block[1]); + return mentor_i2c_data_transmit(off_block, off_size); +} + +#ifdef I2C_CAN_UNSTUCK +static int mentor_i2c_unstuck(int ret) +{ + uint32_t v; + + if (ret != -ETIMEDOUT) + return ret; + VERBOSE("Trying to \"unstuck i2c\"... "); + i2c_init(base); + mmio_write_32((uintptr_t)&base->unstuck, I2C_UNSTUCK_TRIGGER); + do { + v = mmio_read_32((uintptr_t)&base->unstuck); + } while (v & I2C_UNSTUCK_ONGOING); + + if (v & I2C_UNSTUCK_ERROR) { + VERBOSE("failed - soft reset i2c\n"); + ret = -EPERM; + } else { + VERBOSE("ok\n"); + i2c_init(base); + ret = -EAGAIN; + } + return ret; +} +#else +static int mentor_i2c_unstuck(int ret) +{ + VERBOSE("Cannot \"unstuck i2c\" - soft reset i2c\n"); + return -EPERM; +} +#endif + +/* + * API Functions + */ +void i2c_init(void *i2c_base) +{ + /* For I2C speed and slave address, now we do not set them since + * we just provide the working speed and slave address otherwhere + * for i2c_init + */ + base = (struct mentor_i2c_regs *)i2c_base; + + /* Reset the I2C logic */ + mmio_write_32((uintptr_t)&base->soft_reset, 0); + + udelay(200); + + mentor_i2c_bus_speed_set(CONFIG_SYS_I2C_SPEED); + + /* Enable the I2C and slave */ + mmio_write_32((uintptr_t)&base->control, + I2C_CONTROL_TWSIEN | I2C_CONTROL_ACK); + + /* set the I2C slave address */ + mmio_write_32((uintptr_t)&base->xtnd_slave_addr, 0); + mmio_write_32((uintptr_t)&base->slave_address, CONFIG_SYS_I2C_SLAVE); + + /* unmask I2C interrupt */ + mmio_write_32((uintptr_t)&base->control, + mmio_read_32((uintptr_t)&base->control) | + I2C_CONTROL_INTEN); + + udelay(10); +} + +/* + * i2c_read: - Read multiple bytes from an i2c device + * + * The higher level routines take into account that this function is only + * called with len < page length of the device (see configuration file) + * + * @chip: address of the chip which is to be read + * @addr: i2c data address within the chip + * @alen: length of the i2c data address (1..2 bytes) + * @buffer: where to write the data + * @len: how much byte do we want to read + * @return: 0 in case of success + */ +int i2c_read(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len) +{ + int ret = 0; + uint32_t counter = 0; + +#ifdef DEBUG_I2C + mentor_i2c_probe(chip); +#endif + + do { + if (ret != -EAGAIN && ret) { + ERROR("i2c transaction failed, after %d retries\n", + counter); + mentor_i2c_stop_bit_set(); + return ret; + } + + /* wait for 1 us for the interrupt clear to take effect */ + if (counter > 0) + udelay(1); + counter++; + + ret = mentor_i2c_start_bit_set(); + if (ret) { + ret = mentor_i2c_unstuck(ret); + continue; + } + + /* if EEPROM device */ + if (alen != 0) { + ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); + if (ret) + continue; + + ret = mentor_i2c_target_offset_set(chip, addr, alen); + if (ret) + continue; + ret = mentor_i2c_start_bit_set(); + if (ret) + continue; + } + + ret = mentor_i2c_address_set(chip, I2C_CMD_READ); + if (ret) + continue; + + ret = mentor_i2c_data_receive(buffer, len); + if (ret) + continue; + + ret = mentor_i2c_stop_bit_set(); + } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT)); + + if (counter == I2C_MAX_RETRY_CNT) { + ERROR("I2C transactions failed, got EAGAIN %d times\n", + I2C_MAX_RETRY_CNT); + ret = -EPERM; + } + mmio_write_32((uintptr_t)&base->control, + mmio_read_32((uintptr_t)&base->control) | + I2C_CONTROL_ACK); + + udelay(1); + return ret; +} + +/* + * i2c_write: - Write multiple bytes to an i2c device + * + * The higher level routines take into account that this function is only + * called with len < page length of the device (see configuration file) + * + * @chip: address of the chip which is to be written + * @addr: i2c data address within the chip + * @alen: length of the i2c data address (1..2 bytes) + * @buffer: where to find the data to be written + * @len: how much byte do we want to read + * @return: 0 in case of success + */ +int i2c_write(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len) +{ + int ret = 0; + uint32_t counter = 0; + + do { + if (ret != -EAGAIN && ret) { + ERROR("i2c transaction failed\n"); + mentor_i2c_stop_bit_set(); + return ret; + } + /* wait for 1 us for the interrupt clear to take effect */ + if (counter > 0) + udelay(1); + counter++; + + ret = mentor_i2c_start_bit_set(); + if (ret) { + ret = mentor_i2c_unstuck(ret); + continue; + } + + ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); + if (ret) + continue; + + /* if EEPROM device */ + if (alen != 0) { + ret = mentor_i2c_target_offset_set(chip, addr, alen); + if (ret) + continue; + } + + ret = mentor_i2c_data_transmit(buffer, len); + if (ret) + continue; + + ret = mentor_i2c_stop_bit_set(); + } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT)); + + if (counter == I2C_MAX_RETRY_CNT) { + ERROR("I2C transactions failed, got EAGAIN %d times\n", + I2C_MAX_RETRY_CNT); + ret = -EPERM; + } + + udelay(1); + return ret; +} diff --git a/arm-trusted-firmware/drivers/mmc/mmc.c b/arm-trusted-firmware/drivers/mmc/mmc.c new file mode 100644 index 0000000..c327e71 --- /dev/null +++ b/arm-trusted-firmware/drivers/mmc/mmc.c @@ -0,0 +1,811 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Define a simple and generic interface to access eMMC and SD-card devices. */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MMC_DEFAULT_MAX_RETRIES 5 +#define SEND_OP_COND_MAX_RETRIES 100 + +#define MULT_BY_512K_SHIFT 19 + +static const struct mmc_ops *ops; +static unsigned int mmc_ocr_value; +static struct mmc_csd_emmc mmc_csd; +static unsigned char mmc_ext_csd[512] __aligned(16); +static unsigned int mmc_flags; +static struct mmc_device_info *mmc_dev_info; +static unsigned int rca; +static unsigned int scr[2]__aligned(16) = { 0 }; + +static const unsigned char tran_speed_base[16] = { + 0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80 +}; + +static const unsigned char sd_tran_speed_base[16] = { + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 +}; + +static bool is_cmd23_enabled(void) +{ + return ((mmc_flags & MMC_FLAG_CMD23) != 0U); +} + +static int mmc_send_cmd(unsigned int idx, unsigned int arg, + unsigned int r_type, unsigned int *r_data) +{ + struct mmc_cmd cmd; + int ret; + + zeromem(&cmd, sizeof(struct mmc_cmd)); + + cmd.cmd_idx = idx; + cmd.cmd_arg = arg; + cmd.resp_type = r_type; + + ret = ops->send_cmd(&cmd); + + if ((ret == 0) && (r_data != NULL)) { + int i; + + for (i = 0; i < 4; i++) { + *r_data = cmd.resp_data[i]; + r_data++; + } + } + + if (ret != 0) { + VERBOSE("Send command %u error: %d\n", idx, ret); + } + + return ret; +} + +static int mmc_device_state(void) +{ + int retries = MMC_DEFAULT_MAX_RETRIES; + unsigned int resp_data[4]; + + do { + int ret; + + if (retries == 0) { + ERROR("CMD13 failed after %d retries\n", + MMC_DEFAULT_MAX_RETRIES); + return -EIO; + } + + ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R1, &resp_data[0]); + if (ret != 0) { + retries--; + continue; + } + + if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) { + return -EIO; + } + + retries--; + } while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U); + + return MMC_GET_STATE(resp_data[0]); +} + +static int mmc_send_part_switch_cmd(unsigned int part_config) +{ + int ret; + unsigned int part_time = 0; + + ret = mmc_send_cmd(MMC_CMD(6), + EXTCSD_WRITE_BYTES | + EXTCSD_CMD(CMD_EXTCSD_PARTITION_CONFIG) | + EXTCSD_VALUE(part_config) | + EXTCSD_CMD_SET_NORMAL, + MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return ret; + } + + /* Partition switch timing is in 10ms units */ + part_time = mmc_ext_csd[CMD_EXTCSD_PART_SWITCH_TIME] * 10; + + mdelay(part_time); + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret == MMC_STATE_PRG); + + return 0; +} + +static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value) +{ + int ret; + + ret = mmc_send_cmd(MMC_CMD(6), + EXTCSD_WRITE_BYTES | EXTCSD_CMD(ext_cmd) | + EXTCSD_VALUE(value) | EXTCSD_CMD_SET_NORMAL, + MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret == MMC_STATE_PRG); + + return 0; +} + +static int mmc_sd_switch(unsigned int bus_width) +{ + int ret; + int retries = MMC_DEFAULT_MAX_RETRIES; + unsigned int bus_width_arg = 0; + + ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr)); + if (ret != 0) { + return ret; + } + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R5, NULL); + if (ret != 0) { + return ret; + } + + /* ACMD51: SEND_SCR */ + do { + ret = mmc_send_cmd(MMC_ACMD(51), 0, MMC_RESPONSE_R1, NULL); + if ((ret != 0) && (retries == 0)) { + ERROR("ACMD51 failed after %d retries (ret=%d)\n", + MMC_DEFAULT_MAX_RETRIES, ret); + return ret; + } + + retries--; + } while (ret != 0); + + ret = ops->read(0, (uintptr_t)&scr, sizeof(scr)); + if (ret != 0) { + return ret; + } + + if (((scr[0] & SD_SCR_BUS_WIDTH_4) != 0U) && + (bus_width == MMC_BUS_WIDTH_4)) { + bus_width_arg = 2; + } + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R5, NULL); + if (ret != 0) { + return ret; + } + + /* ACMD6: SET_BUS_WIDTH */ + ret = mmc_send_cmd(MMC_ACMD(6), bus_width_arg, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret == MMC_STATE_PRG); + + return 0; +} + +static int mmc_set_ios(unsigned int clk, unsigned int bus_width) +{ + int ret; + unsigned int width = bus_width; + + if (mmc_dev_info->mmc_dev_type != MMC_IS_EMMC) { + if (width == MMC_BUS_WIDTH_8) { + WARN("Wrong bus config for SD-card, force to 4\n"); + width = MMC_BUS_WIDTH_4; + } + ret = mmc_sd_switch(width); + if (ret != 0) { + return ret; + } + } else if (mmc_csd.spec_vers == 4U) { + ret = mmc_set_ext_csd(CMD_EXTCSD_BUS_WIDTH, + (unsigned int)width); + if (ret != 0) { + return ret; + } + } else { + VERBOSE("Wrong MMC type or spec version\n"); + } + + return ops->set_ios(clk, width); +} + +static int mmc_fill_device_info(void) +{ + unsigned long long c_size; + unsigned int speed_idx; + unsigned int nb_blocks; + unsigned int freq_unit; + int ret = 0; + struct mmc_csd_sd_v2 *csd_sd_v2; + + switch (mmc_dev_info->mmc_dev_type) { + case MMC_IS_EMMC: + mmc_dev_info->block_size = MMC_BLOCK_SIZE; + + ret = ops->prepare(0, (uintptr_t)&mmc_ext_csd, + sizeof(mmc_ext_csd)); + if (ret != 0) { + return ret; + } + + /* MMC CMD8: SEND_EXT_CSD */ + ret = mmc_send_cmd(MMC_CMD(8), 0, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + + ret = ops->read(0, (uintptr_t)&mmc_ext_csd, + sizeof(mmc_ext_csd)); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret != MMC_STATE_TRAN); + + nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 3] << 24); + + mmc_dev_info->device_size = (unsigned long long)nb_blocks * + mmc_dev_info->block_size; + + break; + + case MMC_IS_SD: + /* + * Use the same mmc_csd struct, as required fields here + * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC. + */ + mmc_dev_info->block_size = BIT_32(mmc_csd.read_bl_len); + + c_size = ((unsigned long long)mmc_csd.c_size_high << 2U) | + (unsigned long long)mmc_csd.c_size_low; + assert(c_size != 0xFFFU); + + mmc_dev_info->device_size = (c_size + 1U) * + BIT_64(mmc_csd.c_size_mult + 2U) * + mmc_dev_info->block_size; + + break; + + case MMC_IS_SD_HC: + assert(mmc_csd.csd_structure == 1U); + + mmc_dev_info->block_size = MMC_BLOCK_SIZE; + + /* Need to use mmc_csd_sd_v2 struct */ + csd_sd_v2 = (struct mmc_csd_sd_v2 *)&mmc_csd; + c_size = ((unsigned long long)csd_sd_v2->c_size_high << 16) | + (unsigned long long)csd_sd_v2->c_size_low; + + mmc_dev_info->device_size = (c_size + 1U) << MULT_BY_512K_SHIFT; + + break; + + default: + ret = -EINVAL; + break; + } + + if (ret < 0) { + return ret; + } + + speed_idx = (mmc_csd.tran_speed & CSD_TRAN_SPEED_MULT_MASK) >> + CSD_TRAN_SPEED_MULT_SHIFT; + + assert(speed_idx > 0U); + + if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { + mmc_dev_info->max_bus_freq = tran_speed_base[speed_idx]; + } else { + mmc_dev_info->max_bus_freq = sd_tran_speed_base[speed_idx]; + } + + freq_unit = mmc_csd.tran_speed & CSD_TRAN_SPEED_UNIT_MASK; + while (freq_unit != 0U) { + mmc_dev_info->max_bus_freq *= 10U; + --freq_unit; + } + + mmc_dev_info->max_bus_freq *= 10000U; + + return 0; +} + +static int sd_send_op_cond(void) +{ + int n; + unsigned int resp_data[4]; + + for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) { + int ret; + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), 0, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + + /* ACMD41: SD_SEND_OP_COND */ + ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS | + mmc_dev_info->ocr_voltage, MMC_RESPONSE_R3, + &resp_data[0]); + if (ret != 0) { + return ret; + } + + if ((resp_data[0] & OCR_POWERUP) != 0U) { + mmc_ocr_value = resp_data[0]; + + if ((mmc_ocr_value & OCR_HCS) != 0U) { + mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC; + } else { + mmc_dev_info->mmc_dev_type = MMC_IS_SD; + } + + return 0; + } + + mdelay(10); + } + + ERROR("ACMD41 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES); + + return -EIO; +} + +static int mmc_reset_to_idle(void) +{ + int ret; + + /* CMD0: reset to IDLE */ + ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL); + if (ret != 0) { + return ret; + } + + mdelay(2); + + return 0; +} + +static int mmc_send_op_cond(void) +{ + int ret, n; + unsigned int resp_data[4]; + + ret = mmc_reset_to_idle(); + if (ret != 0) { + return ret; + } + + for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) { + ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE | + OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7, + MMC_RESPONSE_R3, &resp_data[0]); + if (ret != 0) { + return ret; + } + + if ((resp_data[0] & OCR_POWERUP) != 0U) { + mmc_ocr_value = resp_data[0]; + return 0; + } + + mdelay(10); + } + + ERROR("CMD1 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES); + + return -EIO; +} + +static int mmc_enumerate(unsigned int clk, unsigned int bus_width) +{ + int ret; + unsigned int resp_data[4]; + + ops->init(); + + ret = mmc_reset_to_idle(); + if (ret != 0) { + return ret; + } + + if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { + ret = mmc_send_op_cond(); + } else { + /* CMD8: Send Interface Condition Command */ + ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN, + MMC_RESPONSE_R5, &resp_data[0]); + + if ((ret == 0) && ((resp_data[0] & 0xffU) == CMD8_CHECK_PATTERN)) { + ret = sd_send_op_cond(); + } + } + if (ret != 0) { + return ret; + } + + /* CMD2: Card Identification */ + ret = mmc_send_cmd(MMC_CMD(2), 0, MMC_RESPONSE_R2, NULL); + if (ret != 0) { + return ret; + } + + /* CMD3: Set Relative Address */ + if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { + rca = MMC_FIX_RCA; + ret = mmc_send_cmd(MMC_CMD(3), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + } else { + ret = mmc_send_cmd(MMC_CMD(3), 0, + MMC_RESPONSE_R6, &resp_data[0]); + if (ret != 0) { + return ret; + } + + rca = (resp_data[0] & 0xFFFF0000U) >> 16; + } + + /* CMD9: CSD Register */ + ret = mmc_send_cmd(MMC_CMD(9), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R2, &resp_data[0]); + if (ret != 0) { + return ret; + } + + memcpy(&mmc_csd, &resp_data, sizeof(resp_data)); + + /* CMD7: Select Card */ + ret = mmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret != MMC_STATE_TRAN); + + ret = mmc_set_ios(clk, bus_width); + if (ret != 0) { + return ret; + } + + return mmc_fill_device_info(); +} + +size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size) +{ + int ret; + unsigned int cmd_idx, cmd_arg; + + assert((ops != NULL) && + (ops->read != NULL) && + (size != 0U) && + ((size & MMC_BLOCK_MASK) == 0U)); + + ret = ops->prepare(lba, buf, size); + if (ret != 0) { + return 0; + } + + if (is_cmd23_enabled()) { + /* Set block count */ + ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + cmd_idx = MMC_CMD(18); + } else { + if (size > MMC_BLOCK_SIZE) { + cmd_idx = MMC_CMD(18); + } else { + cmd_idx = MMC_CMD(17); + } + } + + if (((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) && + (mmc_dev_info->mmc_dev_type != MMC_IS_SD_HC)) { + cmd_arg = lba * MMC_BLOCK_SIZE; + } else { + cmd_arg = lba; + } + + ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + ret = ops->read(lba, buf, size); + if (ret != 0) { + return 0; + } + + /* Wait buffer empty */ + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_DATA)); + + if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { + ret = mmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return 0; + } + } + + return size; +} + +size_t mmc_write_blocks(int lba, const uintptr_t buf, size_t size) +{ + int ret; + unsigned int cmd_idx, cmd_arg; + + assert((ops != NULL) && + (ops->write != NULL) && + (size != 0U) && + ((buf & MMC_BLOCK_MASK) == 0U) && + ((size & MMC_BLOCK_MASK) == 0U)); + + ret = ops->prepare(lba, buf, size); + if (ret != 0) { + return 0; + } + + if (is_cmd23_enabled()) { + /* Set block count */ + ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + cmd_idx = MMC_CMD(25); + } else { + if (size > MMC_BLOCK_SIZE) { + cmd_idx = MMC_CMD(25); + } else { + cmd_idx = MMC_CMD(24); + } + } + + if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) { + cmd_arg = lba * MMC_BLOCK_SIZE; + } else { + cmd_arg = lba; + } + + ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + ret = ops->write(lba, buf, size); + if (ret != 0) { + return 0; + } + + /* Wait buffer empty */ + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV)); + + if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { + ret = mmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return 0; + } + } + + return size; +} + +size_t mmc_erase_blocks(int lba, size_t size) +{ + int ret; + + assert(ops != NULL); + assert((size != 0U) && ((size & MMC_BLOCK_MASK) == 0U)); + + ret = mmc_send_cmd(MMC_CMD(35), lba, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + ret = mmc_send_cmd(MMC_CMD(36), lba + (size / MMC_BLOCK_SIZE) - 1U, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + ret = mmc_send_cmd(MMC_CMD(38), lba, MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return 0; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while (ret != MMC_STATE_TRAN); + + return size; +} + +static inline void mmc_rpmb_enable(void) +{ + mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG, + PART_CFG_BOOT_PARTITION1_ENABLE | + PART_CFG_BOOT_PARTITION1_ACCESS); +} + +static inline void mmc_rpmb_disable(void) +{ + mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG, + PART_CFG_BOOT_PARTITION1_ENABLE); +} + +size_t mmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size) +{ + size_t size_read; + + mmc_rpmb_enable(); + size_read = mmc_read_blocks(lba, buf, size); + mmc_rpmb_disable(); + + return size_read; +} + +size_t mmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size) +{ + size_t size_written; + + mmc_rpmb_enable(); + size_written = mmc_write_blocks(lba, buf, size); + mmc_rpmb_disable(); + + return size_written; +} + +size_t mmc_rpmb_erase_blocks(int lba, size_t size) +{ + size_t size_erased; + + mmc_rpmb_enable(); + size_erased = mmc_erase_blocks(lba, size); + mmc_rpmb_disable(); + + return size_erased; +} + +static int mmc_part_switch(unsigned int part_type) +{ + uint8_t part_config = mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG]; + + part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; + part_config |= part_type; + + return mmc_send_part_switch_cmd(part_config); +} + +static unsigned char mmc_current_boot_part(void) +{ + return PART_CFG_CURRENT_BOOT_PARTITION(mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG]); +} + +size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size) +{ + size_t size_read; + int ret; + unsigned char current_boot_part = mmc_current_boot_part(); + + if (current_boot_part != 1U && + current_boot_part != 2U) { + ERROR("Got unexpected value for active boot partition, %u\n", current_boot_part); + return 0; + } + + ret = mmc_part_switch(current_boot_part); + if (ret < 0) { + ERROR("Failed to switch to boot partition, %d\n", ret); + return 0; + } + + size_read = mmc_read_blocks(lba, buf, size); + + ret = mmc_part_switch(0); + if (ret < 0) { + ERROR("Failed to switch back to user partition, %d\n", ret); + return 0; + } + + return size_read; +} + +int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk, + unsigned int width, unsigned int flags, + struct mmc_device_info *device_info) +{ + assert((ops_ptr != NULL) && + (ops_ptr->init != NULL) && + (ops_ptr->send_cmd != NULL) && + (ops_ptr->set_ios != NULL) && + (ops_ptr->prepare != NULL) && + (ops_ptr->read != NULL) && + (ops_ptr->write != NULL) && + (device_info != NULL) && + (clk != 0) && + ((width == MMC_BUS_WIDTH_1) || + (width == MMC_BUS_WIDTH_4) || + (width == MMC_BUS_WIDTH_8) || + (width == MMC_BUS_WIDTH_DDR_4) || + (width == MMC_BUS_WIDTH_DDR_8))); + + ops = ops_ptr; + mmc_flags = flags; + mmc_dev_info = device_info; + + return mmc_enumerate(clk, width); +} diff --git a/arm-trusted-firmware/drivers/mtd/nand/core.c b/arm-trusted-firmware/drivers/mtd/nand/core.c new file mode 100644 index 0000000..9f0331a --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/nand/core.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +/* + * Define a single nand_device used by specific NAND frameworks. + */ +static struct nand_device nand_dev; +static uint8_t scratch_buff[PLATFORM_MTD_MAX_PAGE_SIZE]; + +int nand_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read) +{ + unsigned int block = offset / nand_dev.block_size; + unsigned int end_block = (offset + length - 1U) / nand_dev.block_size; + unsigned int page_start = + (offset % nand_dev.block_size) / nand_dev.page_size; + unsigned int nb_pages = nand_dev.block_size / nand_dev.page_size; + unsigned int start_offset = offset % nand_dev.page_size; + unsigned int page; + unsigned int bytes_read; + int is_bad; + int ret; + + VERBOSE("Block %u - %u, page_start %u, nb %u, length %zu, offset %u\n", + block, end_block, page_start, nb_pages, length, offset); + + *length_read = 0UL; + + if (((start_offset != 0U) || (length % nand_dev.page_size) != 0U) && + (sizeof(scratch_buff) < nand_dev.page_size)) { + return -EINVAL; + } + + while (block <= end_block) { + is_bad = nand_dev.mtd_block_is_bad(block); + if (is_bad < 0) { + return is_bad; + } + + if (is_bad == 1) { + /* Skip the block */ + uint32_t max_block = + nand_dev.size / nand_dev.block_size; + + block++; + end_block++; + if ((block < max_block) && (end_block < max_block)) { + continue; + } + + return -EIO; + } + + for (page = page_start; page < nb_pages; page++) { + if ((start_offset != 0U) || + (length < nand_dev.page_size)) { + ret = nand_dev.mtd_read_page( + &nand_dev, + (block * nb_pages) + page, + (uintptr_t)scratch_buff); + if (ret != 0) { + return ret; + } + + bytes_read = MIN((size_t)(nand_dev.page_size - + start_offset), + length); + + memcpy((uint8_t *)buffer, + scratch_buff + start_offset, + bytes_read); + + start_offset = 0U; + } else { + ret = nand_dev.mtd_read_page(&nand_dev, + (block * nb_pages) + page, + buffer); + if (ret != 0) { + return ret; + } + + bytes_read = nand_dev.page_size; + } + + length -= bytes_read; + buffer += bytes_read; + *length_read += bytes_read; + + if (length == 0U) { + break; + } + } + + page_start = 0U; + block++; + } + + return 0; +} + +int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset) +{ + unsigned int block; + unsigned int offset_block; + unsigned int max_block; + int is_bad; + size_t count_bb = 0U; + + block = base / nand_dev.block_size; + + if (offset != 0U) { + offset_block = (base + offset - 1U) / nand_dev.block_size; + } else { + offset_block = block; + } + + max_block = nand_dev.size / nand_dev.block_size; + + while (block <= offset_block) { + if (offset_block >= max_block) { + return -EIO; + } + + is_bad = nand_dev.mtd_block_is_bad(block); + if (is_bad < 0) { + return is_bad; + } + + if (is_bad == 1) { + count_bb++; + offset_block++; + } + + block++; + } + + *extra_offset = count_bb * nand_dev.block_size; + + return 0; +} + +struct nand_device *get_nand_device(void) +{ + return &nand_dev; +} diff --git a/arm-trusted-firmware/drivers/mtd/nand/raw_nand.c b/arm-trusted-firmware/drivers/mtd/nand/raw_nand.c new file mode 100644 index 0000000..021e30b --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/nand/raw_nand.c @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define ONFI_SIGNATURE_ADDR 0x20U + +/* CRC calculation */ +#define CRC_POLYNOM 0x8005U +#define CRC_INIT_VALUE 0x4F4EU + +/* Status register */ +#define NAND_STATUS_READY BIT(6) + +static struct rawnand_device rawnand_dev; + +#pragma weak plat_get_raw_nand_data +int plat_get_raw_nand_data(struct rawnand_device *device) +{ + return 0; +} + +static int nand_send_cmd(uint8_t cmd, unsigned int tim) +{ + struct nand_req req; + + zeromem(&req, sizeof(struct nand_req)); + req.nand = rawnand_dev.nand_dev; + req.type = NAND_REQ_CMD | cmd; + req.inst_delay = tim; + + return rawnand_dev.ops->exec(&req); +} + +static int nand_send_addr(uint8_t addr, unsigned int tim) +{ + struct nand_req req; + + zeromem(&req, sizeof(struct nand_req)); + req.nand = rawnand_dev.nand_dev; + req.type = NAND_REQ_ADDR; + req.addr = &addr; + req.inst_delay = tim; + + return rawnand_dev.ops->exec(&req); +} + +static int nand_send_wait(unsigned int delay, unsigned int tim) +{ + struct nand_req req; + + zeromem(&req, sizeof(struct nand_req)); + req.nand = rawnand_dev.nand_dev; + req.type = NAND_REQ_WAIT; + req.inst_delay = tim; + req.delay_ms = delay; + + return rawnand_dev.ops->exec(&req); +} + + +static int nand_read_data(uint8_t *data, unsigned int length, bool use_8bit) +{ + struct nand_req req; + + zeromem(&req, sizeof(struct nand_req)); + req.nand = rawnand_dev.nand_dev; + req.type = NAND_REQ_DATAIN | (use_8bit ? NAND_REQ_BUS_WIDTH_8 : 0U); + req.addr = data; + req.length = length; + + return rawnand_dev.ops->exec(&req); +} + +int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer, + unsigned int len) +{ + int ret; + uint8_t addr[2]; + unsigned int i; + + ret = nand_send_cmd(NAND_CMD_CHANGE_1ST, 0U); + if (ret != 0) { + return ret; + } + + if (rawnand_dev.nand_dev->buswidth == NAND_BUS_WIDTH_16) { + offset /= 2U; + } + + addr[0] = offset; + addr[1] = offset >> 8; + + for (i = 0; i < 2U; i++) { + ret = nand_send_addr(addr[i], 0U); + if (ret != 0) { + return ret; + } + } + + ret = nand_send_cmd(NAND_CMD_CHANGE_2ND, NAND_TCCS_MIN); + if (ret != 0) { + return ret; + } + + return nand_read_data((uint8_t *)buffer, len, false); +} + +int nand_read_page_cmd(unsigned int page, unsigned int offset, + uintptr_t buffer, unsigned int len) +{ + uint8_t addr[5]; + uint8_t i = 0U; + uint8_t j; + int ret; + + VERBOSE(">%s page %u offset %u buffer 0x%lx\n", __func__, page, offset, + buffer); + + if (rawnand_dev.nand_dev->buswidth == NAND_BUS_WIDTH_16) { + offset /= 2U; + } + + addr[i++] = offset; + addr[i++] = offset >> 8; + + addr[i++] = page; + addr[i++] = page >> 8; + if (rawnand_dev.nand_dev->size > SZ_128M) { + addr[i++] = page >> 16; + } + + ret = nand_send_cmd(NAND_CMD_READ_1ST, 0U); + if (ret != 0) { + return ret; + } + + for (j = 0U; j < i; j++) { + ret = nand_send_addr(addr[j], 0U); + if (ret != 0) { + return ret; + } + } + + ret = nand_send_cmd(NAND_CMD_READ_2ND, NAND_TWB_MAX); + if (ret != 0) { + return ret; + } + + ret = nand_send_wait(PSEC_TO_MSEC(NAND_TR_MAX), NAND_TRR_MIN); + if (ret != 0) { + return ret; + } + + if (buffer != 0U) { + ret = nand_read_data((uint8_t *)buffer, len, false); + } + + return ret; +} + +static int nand_status(uint8_t *status) +{ + int ret; + + ret = nand_send_cmd(NAND_CMD_STATUS, NAND_TWHR_MIN); + if (ret != 0) { + return ret; + } + + if (status != NULL) { + ret = nand_read_data(status, 1U, true); + } + + return ret; +} + +int nand_wait_ready(unsigned int delay_ms) +{ + uint8_t status; + int ret; + uint64_t timeout; + + /* Wait before reading status */ + udelay(1); + + ret = nand_status(NULL); + if (ret != 0) { + return ret; + } + + timeout = timeout_init_us(delay_ms * 1000U); + while (!timeout_elapsed(timeout)) { + ret = nand_read_data(&status, 1U, true); + if (ret != 0) { + return ret; + } + + if ((status & NAND_STATUS_READY) != 0U) { + return nand_send_cmd(NAND_CMD_READ_1ST, 0U); + } + + udelay(10); + } + + return -ETIMEDOUT; +} + +#if NAND_ONFI_DETECT +static uint16_t nand_check_crc(uint16_t crc, uint8_t *data_in, + unsigned int data_len) +{ + uint32_t i; + uint32_t j; + uint32_t bit; + + for (i = 0U; i < data_len; i++) { + uint8_t cur_param = *data_in++; + + for (j = BIT(7); j != 0U; j >>= 1) { + bit = crc & BIT(15); + crc <<= 1; + + if ((cur_param & j) != 0U) { + bit ^= BIT(15); + } + + if (bit != 0U) { + crc ^= CRC_POLYNOM; + } + } + + crc &= GENMASK(15, 0); + } + + return crc; +} + +static int nand_read_id(uint8_t addr, uint8_t *id, unsigned int size) +{ + int ret; + + ret = nand_send_cmd(NAND_CMD_READID, 0U); + if (ret != 0) { + return ret; + } + + ret = nand_send_addr(addr, NAND_TWHR_MIN); + if (ret != 0) { + return ret; + } + + return nand_read_data(id, size, true); +} + +static int nand_reset(void) +{ + int ret; + + ret = nand_send_cmd(NAND_CMD_RESET, NAND_TWB_MAX); + if (ret != 0) { + return ret; + } + + return nand_send_wait(PSEC_TO_MSEC(NAND_TRST_MAX), 0U); +} + +static int nand_read_param_page(void) +{ + struct nand_param_page page; + uint8_t addr = 0U; + int ret; + + ret = nand_send_cmd(NAND_CMD_READ_PARAM_PAGE, 0U); + if (ret != 0) { + return ret; + } + + ret = nand_send_addr(addr, NAND_TWB_MAX); + if (ret != 0) { + return ret; + } + + ret = nand_send_wait(PSEC_TO_MSEC(NAND_TR_MAX), NAND_TRR_MIN); + if (ret != 0) { + return ret; + } + + ret = nand_read_data((uint8_t *)&page, sizeof(page), true); + if (ret != 0) { + return ret; + } + + if (strncmp((char *)&page.page_sig, "ONFI", 4) != 0) { + WARN("Error ONFI detection\n"); + return -EINVAL; + } + + if (nand_check_crc(CRC_INIT_VALUE, (uint8_t *)&page, 254U) != + page.crc16) { + WARN("Error reading param\n"); + return -EINVAL; + } + + if ((page.features & ONFI_FEAT_BUS_WIDTH_16) != 0U) { + rawnand_dev.nand_dev->buswidth = NAND_BUS_WIDTH_16; + } else { + rawnand_dev.nand_dev->buswidth = NAND_BUS_WIDTH_8; + } + + rawnand_dev.nand_dev->block_size = page.num_pages_per_blk * + page.bytes_per_page; + rawnand_dev.nand_dev->page_size = page.bytes_per_page; + rawnand_dev.nand_dev->size = page.num_pages_per_blk * + page.bytes_per_page * + page.num_blk_in_lun * page.num_lun; + + if (page.nb_ecc_bits != GENMASK_32(7, 0)) { + rawnand_dev.nand_dev->ecc.max_bit_corr = page.nb_ecc_bits; + rawnand_dev.nand_dev->ecc.size = SZ_512; + } + + VERBOSE("Page size %u, block_size %u, Size %llu, ecc %u, buswidth %u\n", + rawnand_dev.nand_dev->page_size, + rawnand_dev.nand_dev->block_size, rawnand_dev.nand_dev->size, + rawnand_dev.nand_dev->ecc.max_bit_corr, + rawnand_dev.nand_dev->buswidth); + + return 0; +} + +static int detect_onfi(void) +{ + int ret; + char id[4]; + + ret = nand_reset(); + if (ret != 0) { + return ret; + } + + ret = nand_read_id(ONFI_SIGNATURE_ADDR, (uint8_t *)id, sizeof(id)); + if (ret != 0) { + return ret; + } + + if (strncmp(id, "ONFI", sizeof(id)) != 0) { + WARN("NAND Non ONFI detected\n"); + return -ENODEV; + } + + return nand_read_param_page(); +} +#endif + +static int nand_mtd_block_is_bad(unsigned int block) +{ + unsigned int nbpages_per_block = rawnand_dev.nand_dev->block_size / + rawnand_dev.nand_dev->page_size; + uint8_t bbm_marker[2]; + uint8_t page; + int ret; + + for (page = 0U; page < 2U; page++) { + ret = nand_read_page_cmd(block * nbpages_per_block, + rawnand_dev.nand_dev->page_size, + (uintptr_t)bbm_marker, + sizeof(bbm_marker)); + if (ret != 0) { + return ret; + } + + if ((bbm_marker[0] != GENMASK_32(7, 0)) || + (bbm_marker[1] != GENMASK_32(7, 0))) { + WARN("Block %u is bad\n", block); + return 1; + } + } + + return 0; +} + +static int nand_mtd_read_page_raw(struct nand_device *nand, unsigned int page, + uintptr_t buffer) +{ + return nand_read_page_cmd(page, 0U, buffer, + rawnand_dev.nand_dev->page_size); +} + +void nand_raw_ctrl_init(const struct nand_ctrl_ops *ops) +{ + rawnand_dev.ops = ops; +} + +int nand_raw_init(unsigned long long *size, unsigned int *erase_size) +{ + rawnand_dev.nand_dev = get_nand_device(); + if (rawnand_dev.nand_dev == NULL) { + return -EINVAL; + } + + rawnand_dev.nand_dev->mtd_block_is_bad = nand_mtd_block_is_bad; + rawnand_dev.nand_dev->mtd_read_page = nand_mtd_read_page_raw; + rawnand_dev.nand_dev->ecc.mode = NAND_ECC_NONE; + + if ((rawnand_dev.ops->setup == NULL) || + (rawnand_dev.ops->exec == NULL)) { + return -ENODEV; + } + +#if NAND_ONFI_DETECT + if (detect_onfi() != 0) { + WARN("Detect ONFI failed\n"); + } +#endif + + if (plat_get_raw_nand_data(&rawnand_dev) != 0) { + return -EINVAL; + } + + assert((rawnand_dev.nand_dev->page_size != 0U) && + (rawnand_dev.nand_dev->block_size != 0U) && + (rawnand_dev.nand_dev->size != 0U)); + + *size = rawnand_dev.nand_dev->size; + *erase_size = rawnand_dev.nand_dev->block_size; + + rawnand_dev.ops->setup(rawnand_dev.nand_dev); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/mtd/nand/spi_nand.c b/arm-trusted-firmware/drivers/mtd/nand/spi_nand.c new file mode 100644 index 0000000..542b614 --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/nand/spi_nand.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define SPI_NAND_MAX_ID_LEN 4U +#define DELAY_US_400MS 400000U +#define MACRONIX_ID 0xC2U + +static struct spinand_device spinand_dev; + +#pragma weak plat_get_spi_nand_data +int plat_get_spi_nand_data(struct spinand_device *device) +{ + return 0; +} + +static int spi_nand_reg(bool read_reg, uint8_t reg, uint8_t *val, + enum spi_mem_data_dir dir) +{ + struct spi_mem_op op; + + zeromem(&op, sizeof(struct spi_mem_op)); + if (read_reg) { + op.cmd.opcode = SPI_NAND_OP_GET_FEATURE; + } else { + op.cmd.opcode = SPI_NAND_OP_SET_FEATURE; + } + + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.addr.val = reg; + op.addr.nbytes = 1U; + op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.dir = dir; + op.data.nbytes = 1U; + op.data.buf = val; + + return spi_mem_exec_op(&op); +} + +static int spi_nand_read_reg(uint8_t reg, uint8_t *val) +{ + return spi_nand_reg(true, reg, val, SPI_MEM_DATA_IN); +} + +static int spi_nand_write_reg(uint8_t reg, uint8_t val) +{ + return spi_nand_reg(false, reg, &val, SPI_MEM_DATA_OUT); +} + +static int spi_nand_update_cfg(uint8_t mask, uint8_t val) +{ + int ret; + uint8_t cfg = spinand_dev.cfg_cache; + + cfg &= ~mask; + cfg |= val; + + if (cfg == spinand_dev.cfg_cache) { + return 0; + } + + ret = spi_nand_write_reg(SPI_NAND_REG_CFG, cfg); + if (ret == 0) { + spinand_dev.cfg_cache = cfg; + } + + return ret; +} + +static int spi_nand_ecc_enable(bool enable) +{ + return spi_nand_update_cfg(SPI_NAND_CFG_ECC_EN, + enable ? SPI_NAND_CFG_ECC_EN : 0U); +} + +static int spi_nand_quad_enable(uint8_t manufacturer_id) +{ + bool enable = false; + + if (manufacturer_id != MACRONIX_ID) { + return 0; + } + + if (spinand_dev.spi_read_cache_op.data.buswidth == + SPI_MEM_BUSWIDTH_4_LINE) { + enable = true; + } + + return spi_nand_update_cfg(SPI_NAND_CFG_QE, + enable ? SPI_NAND_CFG_QE : 0U); +} + +static int spi_nand_wait_ready(uint8_t *status) +{ + int ret; + uint64_t timeout = timeout_init_us(DELAY_US_400MS); + + while (!timeout_elapsed(timeout)) { + ret = spi_nand_read_reg(SPI_NAND_REG_STATUS, status); + if (ret != 0) { + return ret; + } + + VERBOSE("%s Status %x\n", __func__, *status); + if ((*status & SPI_NAND_STATUS_BUSY) == 0U) { + return 0; + } + } + + return -ETIMEDOUT; +} + +static int spi_nand_reset(void) +{ + struct spi_mem_op op; + uint8_t status; + int ret; + + zeromem(&op, sizeof(struct spi_mem_op)); + op.cmd.opcode = SPI_NAND_OP_RESET; + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + + ret = spi_mem_exec_op(&op); + if (ret != 0) { + return ret; + } + + return spi_nand_wait_ready(&status); +} + +static int spi_nand_read_id(uint8_t *id) +{ + struct spi_mem_op op; + + zeromem(&op, sizeof(struct spi_mem_op)); + op.cmd.opcode = SPI_NAND_OP_READ_ID; + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.dir = SPI_MEM_DATA_IN; + op.data.nbytes = SPI_NAND_MAX_ID_LEN; + op.data.buf = id; + op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + + return spi_mem_exec_op(&op); +} + +static int spi_nand_load_page(unsigned int page) +{ + struct spi_mem_op op; + uint32_t block_nb = page / spinand_dev.nand_dev->block_size; + uint32_t page_nb = page - (block_nb * spinand_dev.nand_dev->page_size); + uint32_t nbpages_per_block = spinand_dev.nand_dev->block_size / + spinand_dev.nand_dev->page_size; + uint32_t block_sh = __builtin_ctz(nbpages_per_block) + 1U; + + zeromem(&op, sizeof(struct spi_mem_op)); + op.cmd.opcode = SPI_NAND_OP_LOAD_PAGE; + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.addr.val = (block_nb << block_sh) | page_nb; + op.addr.nbytes = 3U; + op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + + return spi_mem_exec_op(&op); +} + +static int spi_nand_read_from_cache(unsigned int page, unsigned int offset, + uint8_t *buffer, unsigned int len) +{ + uint32_t nbpages_per_block = spinand_dev.nand_dev->block_size / + spinand_dev.nand_dev->page_size; + uint32_t block_nb = page / nbpages_per_block; + uint32_t page_sh = __builtin_ctz(spinand_dev.nand_dev->page_size) + 1U; + + spinand_dev.spi_read_cache_op.addr.val = offset; + + if ((spinand_dev.nand_dev->nb_planes > 1U) && ((block_nb % 2U) == 1U)) { + spinand_dev.spi_read_cache_op.addr.val |= 1U << page_sh; + } + + spinand_dev.spi_read_cache_op.data.buf = buffer; + spinand_dev.spi_read_cache_op.data.nbytes = len; + + return spi_mem_exec_op(&spinand_dev.spi_read_cache_op); +} + +static int spi_nand_read_page(unsigned int page, unsigned int offset, + uint8_t *buffer, unsigned int len, + bool ecc_enabled) +{ + uint8_t status; + int ret; + + ret = spi_nand_ecc_enable(ecc_enabled); + if (ret != 0) { + return ret; + } + + ret = spi_nand_load_page(page); + if (ret != 0) { + return ret; + } + + ret = spi_nand_wait_ready(&status); + if (ret != 0) { + return ret; + } + + ret = spi_nand_read_from_cache(page, offset, buffer, len); + if (ret != 0) { + return ret; + } + + if (ecc_enabled && ((status & SPI_NAND_STATUS_ECC_UNCOR) != 0U)) { + return -EBADMSG; + } + + return 0; +} + +static int spi_nand_mtd_block_is_bad(unsigned int block) +{ + unsigned int nbpages_per_block = spinand_dev.nand_dev->block_size / + spinand_dev.nand_dev->page_size; + uint8_t bbm_marker[2]; + int ret; + + ret = spi_nand_read_page(block * nbpages_per_block, + spinand_dev.nand_dev->page_size, + bbm_marker, sizeof(bbm_marker), false); + if (ret != 0) { + return ret; + } + + if ((bbm_marker[0] != GENMASK_32(7, 0)) || + (bbm_marker[1] != GENMASK_32(7, 0))) { + WARN("Block %u is bad\n", block); + return 1; + } + + return 0; +} + +static int spi_nand_mtd_read_page(struct nand_device *nand, unsigned int page, + uintptr_t buffer) +{ + return spi_nand_read_page(page, 0, (uint8_t *)buffer, + spinand_dev.nand_dev->page_size, true); +} + +int spi_nand_init(unsigned long long *size, unsigned int *erase_size) +{ + uint8_t id[SPI_NAND_MAX_ID_LEN]; + int ret; + + spinand_dev.nand_dev = get_nand_device(); + if (spinand_dev.nand_dev == NULL) { + return -EINVAL; + } + + spinand_dev.nand_dev->mtd_block_is_bad = spi_nand_mtd_block_is_bad; + spinand_dev.nand_dev->mtd_read_page = spi_nand_mtd_read_page; + spinand_dev.nand_dev->nb_planes = 1; + + spinand_dev.spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE; + spinand_dev.spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + spinand_dev.spi_read_cache_op.addr.nbytes = 2U; + spinand_dev.spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + spinand_dev.spi_read_cache_op.dummy.nbytes = 1U; + spinand_dev.spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + spinand_dev.spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + + if (plat_get_spi_nand_data(&spinand_dev) != 0) { + return -EINVAL; + } + + assert((spinand_dev.nand_dev->page_size != 0U) && + (spinand_dev.nand_dev->block_size != 0U) && + (spinand_dev.nand_dev->size != 0U)); + + ret = spi_nand_reset(); + if (ret != 0) { + return ret; + } + + ret = spi_nand_read_id(id); + if (ret != 0) { + return ret; + } + + ret = spi_nand_read_reg(SPI_NAND_REG_CFG, &spinand_dev.cfg_cache); + if (ret != 0) { + return ret; + } + + ret = spi_nand_quad_enable(id[1]); + if (ret != 0) { + return ret; + } + + VERBOSE("SPI_NAND Detected ID 0x%x\n", id[1]); + + VERBOSE("Page size %u, Block size %u, size %llu\n", + spinand_dev.nand_dev->page_size, + spinand_dev.nand_dev->block_size, + spinand_dev.nand_dev->size); + + *size = spinand_dev.nand_dev->size; + *erase_size = spinand_dev.nand_dev->block_size; + + return 0; +} diff --git a/arm-trusted-firmware/drivers/mtd/nor/spi_nor.c b/arm-trusted-firmware/drivers/mtd/nor/spi_nor.c new file mode 100644 index 0000000..2e34344 --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/nor/spi_nor.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#define SR_WIP BIT(0) /* Write in progress */ +#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ +#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */ +#define FSR_READY BIT(7) /* Device status, 0 = Busy, 1 = Ready */ + +/* Defined IDs for supported memories */ +#define SPANSION_ID 0x01U +#define MACRONIX_ID 0xC2U +#define MICRON_ID 0x2CU + +#define BANK_SIZE 0x1000000U + +#define SPI_READY_TIMEOUT_US 40000U + +static struct nor_device nor_dev; + +#pragma weak plat_get_nor_data +int plat_get_nor_data(struct nor_device *device) +{ + return 0; +} + +static int spi_nor_reg(uint8_t reg, uint8_t *buf, size_t len, + enum spi_mem_data_dir dir) +{ + struct spi_mem_op op; + + zeromem(&op, sizeof(struct spi_mem_op)); + op.cmd.opcode = reg; + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.dir = dir; + op.data.nbytes = len; + op.data.buf = buf; + + return spi_mem_exec_op(&op); +} + +static inline int spi_nor_read_id(uint8_t *id) +{ + return spi_nor_reg(SPI_NOR_OP_READ_ID, id, 1U, SPI_MEM_DATA_IN); +} + +static inline int spi_nor_read_cr(uint8_t *cr) +{ + return spi_nor_reg(SPI_NOR_OP_READ_CR, cr, 1U, SPI_MEM_DATA_IN); +} + +static inline int spi_nor_read_sr(uint8_t *sr) +{ + return spi_nor_reg(SPI_NOR_OP_READ_SR, sr, 1U, SPI_MEM_DATA_IN); +} + +static inline int spi_nor_read_fsr(uint8_t *fsr) +{ + return spi_nor_reg(SPI_NOR_OP_READ_FSR, fsr, 1U, SPI_MEM_DATA_IN); +} + +static inline int spi_nor_write_en(void) +{ + return spi_nor_reg(SPI_NOR_OP_WREN, NULL, 0U, SPI_MEM_DATA_OUT); +} + +/* + * Check if device is ready. + * + * Return 0 if ready, 1 if busy or a negative error code otherwise + */ +static int spi_nor_ready(void) +{ + uint8_t sr; + int ret; + + ret = spi_nor_read_sr(&sr); + if (ret != 0) { + return ret; + } + + if ((nor_dev.flags & SPI_NOR_USE_FSR) != 0U) { + uint8_t fsr; + + ret = spi_nor_read_fsr(&fsr); + if (ret != 0) { + return ret; + } + + return (((fsr & FSR_READY) != 0U) && ((sr & SR_WIP) == 0U)) ? + 0 : 1; + } + + return (((sr & SR_WIP) == 0U) ? 0 : 1); +} + +static int spi_nor_wait_ready(void) +{ + int ret; + uint64_t timeout = timeout_init_us(SPI_READY_TIMEOUT_US); + + while (!timeout_elapsed(timeout)) { + ret = spi_nor_ready(); + if (ret <= 0) { + return ret; + } + } + + return -ETIMEDOUT; +} + +static int spi_nor_macronix_quad_enable(void) +{ + uint8_t sr; + int ret; + + ret = spi_nor_read_sr(&sr); + if (ret != 0) { + return ret; + } + + if ((sr & SR_QUAD_EN_MX) != 0U) { + return 0; + } + + ret = spi_nor_write_en(); + if (ret != 0) { + return ret; + } + + sr |= SR_QUAD_EN_MX; + ret = spi_nor_reg(SPI_NOR_OP_WRSR, &sr, 1U, SPI_MEM_DATA_OUT); + if (ret != 0) { + return ret; + } + + ret = spi_nor_wait_ready(); + if (ret != 0) { + return ret; + } + + ret = spi_nor_read_sr(&sr); + if ((ret != 0) || ((sr & SR_QUAD_EN_MX) == 0U)) { + return -EINVAL; + } + + return 0; +} + +static int spi_nor_write_sr_cr(uint8_t *sr_cr) +{ + int ret; + + ret = spi_nor_write_en(); + if (ret != 0) { + return ret; + } + + ret = spi_nor_reg(SPI_NOR_OP_WRSR, sr_cr, 2U, SPI_MEM_DATA_OUT); + if (ret != 0) { + return -EINVAL; + } + + ret = spi_nor_wait_ready(); + if (ret != 0) { + return ret; + } + + return 0; +} + +static int spi_nor_quad_enable(void) +{ + uint8_t sr_cr[2]; + int ret; + + ret = spi_nor_read_cr(&sr_cr[1]); + if (ret != 0) { + return ret; + } + + if ((sr_cr[1] & CR_QUAD_EN_SPAN) != 0U) { + return 0; + } + + sr_cr[1] |= CR_QUAD_EN_SPAN; + ret = spi_nor_read_sr(&sr_cr[0]); + if (ret != 0) { + return ret; + } + + ret = spi_nor_write_sr_cr(sr_cr); + if (ret != 0) { + return ret; + } + + ret = spi_nor_read_cr(&sr_cr[1]); + if ((ret != 0) || ((sr_cr[1] & CR_QUAD_EN_SPAN) == 0U)) { + return -EINVAL; + } + + return 0; +} + +static int spi_nor_clean_bar(void) +{ + int ret; + + if (nor_dev.selected_bank == 0U) { + return 0; + } + + nor_dev.selected_bank = 0U; + + ret = spi_nor_write_en(); + if (ret != 0) { + return ret; + } + + return spi_nor_reg(nor_dev.bank_write_cmd, &nor_dev.selected_bank, + 1U, SPI_MEM_DATA_OUT); +} + +static int spi_nor_write_bar(uint32_t offset) +{ + uint8_t selected_bank = offset / BANK_SIZE; + int ret; + + if (selected_bank == nor_dev.selected_bank) { + return 0; + } + + ret = spi_nor_write_en(); + if (ret != 0) { + return ret; + } + + ret = spi_nor_reg(nor_dev.bank_write_cmd, &selected_bank, + 1U, SPI_MEM_DATA_OUT); + if (ret != 0) { + return ret; + } + + nor_dev.selected_bank = selected_bank; + + return 0; +} + +static int spi_nor_read_bar(void) +{ + uint8_t selected_bank = 0U; + int ret; + + ret = spi_nor_reg(nor_dev.bank_read_cmd, &selected_bank, + 1U, SPI_MEM_DATA_IN); + if (ret != 0) { + return ret; + } + + nor_dev.selected_bank = selected_bank; + + return 0; +} + +int spi_nor_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read) +{ + size_t remain_len; + int ret; + + *length_read = 0U; + nor_dev.read_op.addr.val = offset; + nor_dev.read_op.data.buf = (void *)buffer; + + VERBOSE("%s offset %u length %zu\n", __func__, offset, length); + + while (length != 0U) { + if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { + ret = spi_nor_write_bar(nor_dev.read_op.addr.val); + if (ret != 0) { + return ret; + } + + remain_len = (BANK_SIZE * (nor_dev.selected_bank + 1)) - + nor_dev.read_op.addr.val; + nor_dev.read_op.data.nbytes = MIN(length, remain_len); + } else { + nor_dev.read_op.data.nbytes = length; + } + + ret = spi_mem_exec_op(&nor_dev.read_op); + if (ret != 0) { + spi_nor_clean_bar(); + return ret; + } + + length -= nor_dev.read_op.data.nbytes; + nor_dev.read_op.addr.val += nor_dev.read_op.data.nbytes; + nor_dev.read_op.data.buf += nor_dev.read_op.data.nbytes; + *length_read += nor_dev.read_op.data.nbytes; + } + + if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { + ret = spi_nor_clean_bar(); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +int spi_nor_init(unsigned long long *size, unsigned int *erase_size) +{ + int ret; + uint8_t id; + + /* Default read command used */ + nor_dev.read_op.cmd.opcode = SPI_NOR_OP_READ; + nor_dev.read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + nor_dev.read_op.addr.nbytes = 3U; + nor_dev.read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + nor_dev.read_op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + nor_dev.read_op.data.dir = SPI_MEM_DATA_IN; + + if (plat_get_nor_data(&nor_dev) != 0) { + return -EINVAL; + } + + assert(nor_dev.size != 0U); + + if (nor_dev.size > BANK_SIZE) { + nor_dev.flags |= SPI_NOR_USE_BANK; + } + + *size = nor_dev.size; + + ret = spi_nor_read_id(&id); + if (ret != 0) { + return ret; + } + + if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { + switch (id) { + case SPANSION_ID: + nor_dev.bank_read_cmd = SPINOR_OP_BRRD; + nor_dev.bank_write_cmd = SPINOR_OP_BRWR; + break; + default: + nor_dev.bank_read_cmd = SPINOR_OP_RDEAR; + nor_dev.bank_write_cmd = SPINOR_OP_WREAR; + break; + } + } + + if (nor_dev.read_op.data.buswidth == 4U) { + switch (id) { + case MACRONIX_ID: + INFO("Enable Macronix quad support\n"); + ret = spi_nor_macronix_quad_enable(); + break; + case MICRON_ID: + break; + default: + ret = spi_nor_quad_enable(); + break; + } + } + + if ((ret == 0) && ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U)) { + ret = spi_nor_read_bar(); + } + + return ret; +} diff --git a/arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c b/arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c new file mode 100644 index 0000000..c43d519 --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#define SPI_MEM_DEFAULT_SPEED_HZ 100000U + +/* + * struct spi_slave - Representation of a SPI slave. + * + * @max_hz: Maximum speed for this slave in Hertz. + * @cs: ID of the chip select connected to the slave. + * @mode: SPI mode to use for this slave (see SPI mode flags). + * @ops: Ops defined by the bus. + */ +struct spi_slave { + unsigned int max_hz; + unsigned int cs; + unsigned int mode; + const struct spi_bus_ops *ops; +}; + +static struct spi_slave spi_slave; + +static bool spi_mem_check_buswidth_req(uint8_t buswidth, bool tx) +{ + switch (buswidth) { + case 1U: + return true; + + case 2U: + if ((tx && (spi_slave.mode & (SPI_TX_DUAL | SPI_TX_QUAD)) != + 0U) || + (!tx && (spi_slave.mode & (SPI_RX_DUAL | SPI_RX_QUAD)) != + 0U)) { + return true; + } + break; + + case 4U: + if ((tx && (spi_slave.mode & SPI_TX_QUAD) != 0U) || + (!tx && (spi_slave.mode & SPI_RX_QUAD) != 0U)) { + return true; + } + break; + + default: + break; + } + + return false; +} + +static bool spi_mem_supports_op(const struct spi_mem_op *op) +{ + if (!spi_mem_check_buswidth_req(op->cmd.buswidth, true)) { + return false; + } + + if ((op->addr.nbytes != 0U) && + !spi_mem_check_buswidth_req(op->addr.buswidth, true)) { + return false; + } + + if ((op->dummy.nbytes != 0U) && + !spi_mem_check_buswidth_req(op->dummy.buswidth, true)) { + return false; + } + + if ((op->data.nbytes != 0U) && + !spi_mem_check_buswidth_req(op->data.buswidth, + op->data.dir == SPI_MEM_DATA_OUT)) { + return false; + } + + return true; +} + +static int spi_mem_set_speed_mode(void) +{ + const struct spi_bus_ops *ops = spi_slave.ops; + int ret; + + ret = ops->set_speed(spi_slave.max_hz); + if (ret != 0) { + VERBOSE("Cannot set speed (err=%d)\n", ret); + return ret; + } + + ret = ops->set_mode(spi_slave.mode); + if (ret != 0) { + VERBOSE("Cannot set mode (err=%d)\n", ret); + return ret; + } + + return 0; +} + +static int spi_mem_check_bus_ops(const struct spi_bus_ops *ops) +{ + bool error = false; + + if (ops->claim_bus == NULL) { + VERBOSE("Ops claim bus is not defined\n"); + error = true; + } + + if (ops->release_bus == NULL) { + VERBOSE("Ops release bus is not defined\n"); + error = true; + } + + if (ops->exec_op == NULL) { + VERBOSE("Ops exec op is not defined\n"); + error = true; + } + + if (ops->set_speed == NULL) { + VERBOSE("Ops set speed is not defined\n"); + error = true; + } + + if (ops->set_mode == NULL) { + VERBOSE("Ops set mode is not defined\n"); + error = true; + } + + return error ? -EINVAL : 0; +} + +/* + * spi_mem_exec_op() - Execute a memory operation. + * @op: The memory operation to execute. + * + * This function first checks that @op is supported and then tries to execute + * it. + * + * Return: 0 in case of success, a negative error code otherwise. + */ +int spi_mem_exec_op(const struct spi_mem_op *op) +{ + const struct spi_bus_ops *ops = spi_slave.ops; + int ret; + + VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addqr:%" PRIx64 " len:%x\n", + __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, + op->dummy.buswidth, op->data.buswidth, + op->addr.val, op->data.nbytes); + + if (!spi_mem_supports_op(op)) { + WARN("Error in spi_mem_support\n"); + return -ENOTSUP; + } + + ret = ops->claim_bus(spi_slave.cs); + if (ret != 0) { + WARN("Error claim_bus\n"); + return ret; + } + + ret = ops->exec_op(op); + + ops->release_bus(); + + return ret; +} + +/* + * spi_mem_init_slave() - SPI slave device initialization. + * @fdt: Pointer to the device tree blob. + * @bus_node: Offset of the bus node. + * @ops: The SPI bus ops defined. + * + * This function first checks that @ops are supported and then tries to find + * a SPI slave device. + * + * Return: 0 in case of success, a negative error code otherwise. + */ +int spi_mem_init_slave(void *fdt, int bus_node, const struct spi_bus_ops *ops) +{ + int ret; + int mode = 0; + int nchips = 0; + int bus_subnode = 0; + const fdt32_t *cuint = NULL; + + ret = spi_mem_check_bus_ops(ops); + if (ret != 0) { + return ret; + } + + fdt_for_each_subnode(bus_subnode, fdt, bus_node) { + nchips++; + } + + if (nchips != 1) { + ERROR("Only one SPI device is currently supported\n"); + return -EINVAL; + } + + fdt_for_each_subnode(bus_subnode, fdt, bus_node) { + /* Get chip select */ + cuint = fdt_getprop(fdt, bus_subnode, "reg", NULL); + if (cuint == NULL) { + ERROR("Chip select not well defined\n"); + return -EINVAL; + } + spi_slave.cs = fdt32_to_cpu(*cuint); + + /* Get max slave frequency */ + spi_slave.max_hz = SPI_MEM_DEFAULT_SPEED_HZ; + cuint = fdt_getprop(fdt, bus_subnode, + "spi-max-frequency", NULL); + if (cuint != NULL) { + spi_slave.max_hz = fdt32_to_cpu(*cuint); + } + + /* Get mode */ + if ((fdt_getprop(fdt, bus_subnode, "spi-cpol", NULL)) != NULL) { + mode |= SPI_CPOL; + } + if ((fdt_getprop(fdt, bus_subnode, "spi-cpha", NULL)) != NULL) { + mode |= SPI_CPHA; + } + if ((fdt_getprop(fdt, bus_subnode, "spi-cs-high", NULL)) != + NULL) { + mode |= SPI_CS_HIGH; + } + if ((fdt_getprop(fdt, bus_subnode, "spi-3wire", NULL)) != + NULL) { + mode |= SPI_3WIRE; + } + if ((fdt_getprop(fdt, bus_subnode, "spi-half-duplex", NULL)) != + NULL) { + mode |= SPI_PREAMBLE; + } + + /* Get dual/quad mode */ + cuint = fdt_getprop(fdt, bus_subnode, "spi-tx-bus-width", NULL); + if (cuint != NULL) { + switch (fdt32_to_cpu(*cuint)) { + case 1U: + break; + case 2U: + mode |= SPI_TX_DUAL; + break; + case 4U: + mode |= SPI_TX_QUAD; + break; + default: + WARN("spi-tx-bus-width %u not supported\n", + fdt32_to_cpu(*cuint)); + return -EINVAL; + } + } + + cuint = fdt_getprop(fdt, bus_subnode, "spi-rx-bus-width", NULL); + if (cuint != NULL) { + switch (fdt32_to_cpu(*cuint)) { + case 1U: + break; + case 2U: + mode |= SPI_RX_DUAL; + break; + case 4U: + mode |= SPI_RX_QUAD; + break; + default: + WARN("spi-rx-bus-width %u not supported\n", + fdt32_to_cpu(*cuint)); + return -EINVAL; + } + } + + spi_slave.mode = mode; + spi_slave.ops = ops; + } + + return spi_mem_set_speed_mode(); +} diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c new file mode 100644 index 0000000..4502ed6 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#endif + + +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t sig_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, 0); + +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); + +/* + * TBBR Chain of trust definition + */ +static const auth_img_desc_t bl31_image = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t scp_bl2_image = { + .img_id = SCP_BL2_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t bl32_image = { + .img_id = BL32_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t bl33_image = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +#ifdef POLICY_FUSE_PROVISION +static const auth_img_desc_t fuse_prov_img = { + .img_id = FUSE_PROV_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t fuse_upgrade_img = { + .img_id = FUSE_UP_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +#endif +#ifdef CONFIG_DDR_FIP_IMAGE +static const auth_img_desc_t ddr_imem_udimm_1d_img = { + .img_id = DDR_IMEM_UDIMM_1D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_udimm_2d_img = { + .img_id = DDR_IMEM_UDIMM_2D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_udimm_1d_img = { + .img_id = DDR_DMEM_UDIMM_1D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_udimm_2d_img = { + .img_id = DDR_DMEM_UDIMM_2D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_rdimm_1d_img = { + .img_id = DDR_IMEM_RDIMM_1D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_rdimm_2d_img = { + .img_id = DDR_IMEM_RDIMM_2D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_rdimm_1d_img = { + .img_id = DDR_DMEM_RDIMM_1D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_rdimm_2d_img = { + .img_id = DDR_DMEM_RDIMM_2D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +#endif + +static const auth_img_desc_t * const cot_desc[] = { + [BL31_IMAGE_ID] = &bl31_image, + [SCP_BL2_IMAGE_ID] = &scp_bl2_image, + [BL32_IMAGE_ID] = &bl32_image, + [BL33_IMAGE_ID] = &bl33_image, +#ifdef POLICY_FUSE_PROVISION + [FUSE_PROV_IMAGE_ID] = &fuse_prov_img, + [FUSE_UP_IMAGE_ID] = &fuse_upgrade_img, +#endif +#ifdef CONFIG_DDR_FIP_IMAGE + [DDR_IMEM_UDIMM_1D_IMAGE_ID] = &ddr_imem_udimm_1d_img, + [DDR_IMEM_UDIMM_2D_IMAGE_ID] = &ddr_imem_udimm_2d_img, + [DDR_DMEM_UDIMM_1D_IMAGE_ID] = &ddr_dmem_udimm_1d_img, + [DDR_DMEM_UDIMM_2D_IMAGE_ID] = &ddr_dmem_udimm_2d_img, + [DDR_IMEM_RDIMM_1D_IMAGE_ID] = &ddr_imem_rdimm_1d_img, + [DDR_IMEM_RDIMM_2D_IMAGE_ID] = &ddr_imem_rdimm_2d_img, + [DDR_DMEM_RDIMM_1D_IMAGE_ID] = &ddr_dmem_rdimm_1d_img, + [DDR_DMEM_RDIMM_2D_IMAGE_ID] = &ddr_dmem_rdimm_2d_img, +#endif +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk new file mode 100644 index 0000000..1af51f8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk @@ -0,0 +1,64 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +CSF_HDR_SOURCES := $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/csf_hdr_parser.c + +CSF_HDR_SOURCES += $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/plat_img_parser.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/auth/csf_hdr_parser/ + +$(eval $(call add_define, CSF_HEADER_PREPENDED)) + + +# Path to CST directory is required to generate the CSF header +# and prepend it to image before fip image gets generated +ifeq (${CST_DIR},) + $(error Error: CST_DIR not set) +endif + +# Rules are created for generating and appending CSF header to images before +# FIT image generation + +# CST_BL31 +define CST_BL31_RULE +$(1): $(2) + @echo " Generating CSF Header for $$@ $$<" + $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \ + --app $(2) ${BL31_INPUT_FILE} +endef + +CST_BL31_SUFFIX := .cst + +# CST_BL32 +define CST_BL32_RULE +$(1): $(2) + @echo " Generating CSF Header for $$@ $$<" + $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \ + --app $(2) ${BL32_INPUT_FILE} +endef + +CST_BL32_SUFFIX := .cst + +# CST_BL33 +define CST_BL33_RULE +$(1): $(2) + @echo " Generating CSF Header for $$@ $$<" + $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \ + --app $(2) ${BL33_INPUT_FILE} +endef + +CST_BL33_SUFFIX := .cst + +# CST_SCP_BL2 +define CST_SCP_BL2_RULE +$(1): $(2) + @echo " Generating CSF Header for $$@ $$<" + $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \ + --app $(2) ${FUSE_INPUT_FILE} +endef + +CST_SCP_BL2_SUFFIX := .cst diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c new file mode 100644 index 0000000..b878082 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Maximum OID string length ("a.b.c.d.e.f ...") */ +#define MAX_OID_STR_LEN 64 + +#define LIB_NAME "NXP CSFv2" + +#ifdef CSF_HDR_CH3 +/* Barker Code for LS Ch3 ESBC Header */ +static const uint8_t barker_code[CSF_BARKER_LEN] = { 0x12, 0x19, 0x20, 0x01 }; +#else +static const uint8_t barker_code[CSF_BARKER_LEN] = { 0x68, 0x39, 0x27, 0x81 }; +#endif + +#define CHECK_KEY_LEN(key_len) (((key_len) == 2 * RSA_1K_KEY_SZ_BYTES) || \ + ((key_len) == 2 * RSA_2K_KEY_SZ_BYTES) || \ + ((key_len) == 2 * RSA_4K_KEY_SZ_BYTES)) + +/* Flag to indicate if values are there in rotpk_hash_table */ +bool rotpk_not_dpld = true; +uint8_t rotpk_hash_table[MAX_KEY_ENTRIES][SHA256_BYTES]; +uint32_t num_rotpk_hash_entries; + +/* + * This function deploys the hashes of the various platform keys in + * rotpk_hash_table. This is done in case of secure boot after comparison + * of table's hash with the hash in SFP fuses. This installation is done + * only in the first header parsing. + */ +static int deploy_rotpk_hash_table(void *srk_buffer, uint16_t num_srk) +{ + void *ctx; + int ret = 0; + int i, j = 0; + unsigned int digest_size = SHA256_BYTES; + enum hash_algo algo = SHA256; + uint8_t hash[SHA256_BYTES]; + uint32_t srk_hash[SHA256_BYTES/4] __aligned(CACHE_WRITEBACK_GRANULE); + struct srk_table *srktbl = (void *)srk_buffer; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(get_sfp_addr() + + SFP_FUSE_REGS_OFFSET); + + + if (num_srk > MAX_KEY_ENTRIES) { + return -1; + } + + ret = hash_init(algo, &ctx); + if (ret != 0) { + return -1; + } + + /* Update hash with that of SRK table */ + ret = hash_update(algo, ctx, (uint8_t *)((uint8_t *)srk_buffer), + num_srk * sizeof(struct srk_table)); + if (ret != 0) { + return -1; + } + + /* Copy hash at destination buffer */ + ret = hash_final(algo, ctx, hash, digest_size); + if (ret != 0) { + return -1; + } + + /* Add comparison of hash with SFP hash here */ + for (i = 0; i < SHA256_BYTES/4; i++) { + srk_hash[i] = + mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]); + } + + VERBOSE("SRK table HASH\n"); + for (i = 0; i < 8; i++) { + VERBOSE("%x\n", *((uint32_t *)hash + i)); + } + + if (memcmp(hash, srk_hash, SHA256_BYTES) != 0) { + ERROR("Error in installing ROTPK table\n"); + ERROR("SRK hash doesn't match the fuse hash\n"); + return -1; + } + + /* Hash table already deployed */ + if (rotpk_not_dpld == false) { + return 0; + } + + for (i = 0; i < num_srk; i++) { + ret = hash_init(algo, &ctx); + if (ret != 0) { + return -1; + } + + /* Update hash with that of SRK table */ + ret = hash_update(algo, ctx, srktbl[i].pkey, srktbl[i].key_len); + if (ret != 0) { + return -1; + } + + /* Copy hash at destination buffer */ + ret = hash_final(algo, ctx, rotpk_hash_table[i], digest_size); + if (ret != 0) { + return -1; + } + VERBOSE("Table key %d HASH\n", i); + for (j = 0; j < 8; j++) { + VERBOSE("%x\n", *((uint32_t *)rotpk_hash_table[i] + j)); + } + } + rotpk_not_dpld = false; + num_rotpk_hash_entries = num_srk; + + return 0; +} + +/* + * Calculate hash of ESBC hdr and ESBC. This function calculates the + * single hash of ESBC header and ESBC image + */ +int calc_img_hash(struct csf_hdr *hdr, + void *img_addr, uint32_t img_size, + uint8_t *img_hash, uint32_t *hash_len) +{ + void *ctx; + int ret = 0; + unsigned int digest_size = SHA256_BYTES; + enum hash_algo algo = SHA256; + + ret = hash_init(algo, &ctx); + /* Copy hash at destination buffer */ + if (ret != 0) { + return -1; + } + + /* Update hash for CSF Header */ + ret = hash_update(algo, ctx, (uint8_t *)hdr, sizeof(struct csf_hdr)); + if (ret != 0) { + return -1; + } + + /* Update hash with that of SRK table */ + ret = hash_update(algo, ctx, + (uint8_t *)((uint8_t *)hdr + hdr->srk_tbl_off), + hdr->len_kr.num_srk * sizeof(struct srk_table)); + if (ret != 0) { + return -1; + } + + /* Update hash for actual Image */ + ret = hash_update(algo, ctx, (uint8_t *)(img_addr), img_size); + if (ret != 0) { + return -1; + } + + /* Copy hash at destination buffer */ + ret = hash_final(algo, ctx, img_hash, digest_size); + if (ret != 0) { + return -1; + } + + *hash_len = digest_size; + + VERBOSE("IMG encoded HASH\n"); + for (int i = 0; i < 8; i++) { + VERBOSE("%x\n", *((uint32_t *)img_hash + i)); + } + + return 0; +} + +/* This function checks if selected key is revoked or not.*/ +static uint32_t is_key_revoked(uint32_t keynum, uint32_t rev_flag) +{ + if (keynum == UNREVOCABLE_KEY) { + return 0; + } + + if (((uint32_t)(1 << (REVOC_KEY_ALIGN - keynum)) & rev_flag) != 0) { + return 1; + } + + return 0; +} + +/* Parse the header to extract the type of key, + * Check if key is not revoked + * and return the key , key length and key_type + */ +static int32_t get_key(struct csf_hdr *hdr, uint8_t **key, uint32_t *len, + enum sig_alg *key_type) +{ + int i = 0; + uint32_t ret = 0U; + uint32_t key_num, key_revoc_flag; + void *esbc = hdr; + struct srk_table *srktbl = (void *)((uint8_t *)esbc + hdr->srk_tbl_off); + bool sb; + uint32_t mode; + + /* We currently support only RSA keys and signature */ + *key_type = RSA; + + /* Check for number of SRK entries */ + if ((hdr->len_kr.num_srk == 0) || + (hdr->len_kr.num_srk > MAX_KEY_ENTRIES)) { + ERROR("Error in NUM entries in SRK Table\n"); + return -1; + } + + /* + * Check the key number field. It should be not greater than + * number of entries in SRK table. + */ + key_num = hdr->len_kr.srk_sel; + if ((key_num == 0) || (key_num > hdr->len_kr.num_srk)) { + ERROR("Invalid Key number\n"); + return -1; + } + + /* Get revoc key from sfp */ + key_revoc_flag = get_key_revoc(); + + /* Check if selected key has been revoked */ + ret = is_key_revoked(key_num, key_revoc_flag); + if (ret != 0) { + ERROR("Selected key has been revoked\n"); + return -1; + } + + /* Check for valid key length - allowed key sized 1k, 2k and 4K */ + for (i = 0; i < hdr->len_kr.num_srk; i++) { + if (CHECK_KEY_LEN(srktbl[i].key_len) == 0) { + ERROR("Invalid key length\n"); + return -1; + } + } + + /* We don't return error from here. While parsing we just try to + * install the srk table. Failure needs to be taken care of in + * case of secure boot. This failure will be handled at the time + * of rotpk comparison in plat_get_rotpk_info function + */ + sb = check_boot_mode_secure(&mode); + if (sb) { + ret = deploy_rotpk_hash_table(srktbl, hdr->len_kr.num_srk); + if (ret != 0) { + ERROR("ROTPK FAILURE\n"); + /* For ITS =1 , return failure */ + if (mode != 0) { + return -1; + } + ERROR("SECURE BOOT DEV-ENV MODE:\n"); + ERROR("\tCHECK ROTPK !\n"); + ERROR("\tCONTINUING ON FAILURE...\n"); + } + } + + /* Return the length of the selected key */ + *len = srktbl[key_num - 1].key_len; + + /* Point key to the selected key */ + *key = (uint8_t *)&(srktbl[key_num - 1].pkey); + + return 0; +} + +/* + * This function would parse the CSF header and do the following: + * 1. Basic integrity checks + * 2. Key checks and extract the key from SRK/IE Table + * 3. Key hash comparison with SRKH in fuses in case of SRK Table + * 4. OEM/UID checks - To be added + * 5. Hash calculation for various components used in signature + * 6. Signature integrity checks + * return -> 0 on success, -1 on failure + */ +int validate_esbc_header(void *img_hdr, void **img_key, uint32_t *key_len, + void **img_sign, uint32_t *sign_len, + enum sig_alg *algo) +{ + struct csf_hdr *hdr = img_hdr; + uint8_t *s; + int32_t ret = 0; + void *esbc = (uint8_t *)img_hdr; + uint8_t *key; + uint32_t klen; + + /* check barker code */ + if (memcmp(hdr->barker, barker_code, CSF_BARKER_LEN) != 0) { + ERROR("Wrong barker code in header\n"); + return -1; + } + + ret = get_key(hdr, &key, &klen, algo); + if (ret != 0) { + return -1; + } + + /* check signaure */ + if (klen == (2 * hdr->sign_len)) { + /* check signature length */ + if (((hdr->sign_len == RSA_1K_KEY_SZ_BYTES) || + (hdr->sign_len == RSA_2K_KEY_SZ_BYTES) || + (hdr->sign_len == RSA_4K_KEY_SZ_BYTES)) == 0) { + ERROR("Wrong Signature length in header\n"); + return -1; + } + } else { + ERROR("RSA key length not twice the signature length\n"); + return -1; + } + + /* modulus most significant bit should be set */ + + if ((key[0] & 0x80) == 0U) { + ERROR("RSA Public key MSB not set\n"); + return -1; + } + + /* modulus value should be odd */ + if ((key[klen / 2 - 1] & 0x1) == 0U) { + ERROR("Public key Modulus in header not odd\n"); + return -1; + } + + /* Check signature value < modulus value */ + s = (uint8_t *)(esbc + hdr->psign); + + if (!(memcmp(s, key, hdr->sign_len) < 0)) { + ERROR("Signature not less than modulus"); + return -1; + } + + /* Populate the return addresses */ + *img_sign = (void *)(s); + + /* Save the length of signature */ + *sign_len = hdr->sign_len; + + *img_key = (uint8_t *)key; + + *key_len = klen; + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 new file mode 100644 index 0000000..bf8934b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - 1010/1040/2041/3041/4080/5020/5040/9131/9132/9164/4240/C290/LS1 +PLATFORM=LS1043 +# ESBC Flag. Specify ESBC=0 to sign u-boot and ESBC=1 to sign ESBC images.(default is 0) +ESBC=0 +--------------------------------------------------- +# Entry Point/Image start address field in the header.[Mandatory] +# (default=ADDRESS of first file specified in images) +ENTRY_POINT=10000000 +--------------------------------------------------- +# Specify the file name of the keys separated by comma. +# The number of files and key select should lie between 1 and 4 for 1040 and C290. +# For rest of the platforms only one key is required and key select should not be provided. + +# USAGE (for 4080/5020/5040/3041/2041/1010/913x): PRI_KEY = +# USAGE (for 1040/C290/9164/4240/LS1): PRI_KEY = , , , + +# PRI_KEY (Default private key :srk.pri) - [Optional] +PRI_KEY=srk.pri +# PUB_KEY (Default public key :srk.pub) - [Optional] +PUB_KEY=srk.pub +# Please provide KEY_SELECT(between 1 to 4) (Required for 1040/C290/9164/4240/LS1 only) - [Optional] +KEY_SELECT= +--------------------------------------------------- +# Specify SG table address, only for (2041/3041/4080/5020/5040) with ESBC=0 - [Optional] +SG_TABLE_ADDR= +--------------------------------------------------- +# Specify the target where image will be loaded. (Default is NOR_16B) - [Optional] +# Only required for Non-PBL Devices (1010/1040/9131/9132i/C290) +# Select from - NOR_8B/NOR_16B/NAND_8B_512/NAND_8B_2K/NAND_8B_4K/NAND_16B_512/NAND_16B_2K/NAND_16B_4K/SD/MMC/SPI +IMAGE_TARGET= +--------------------------------------------------- +# Specify IMAGE, Max 8 images are possible. DST_ADDR is required only for Non-PBL Platform. [Mandatory] +# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR} +IMAGE_1={bl2.bin,10000000,ffffffff} +IMAGE_2={,,} +IMAGE_3={,,} +IMAGE_4={,,} +IMAGE_5={,,} +IMAGE_6={,,} +IMAGE_7={,,} +IMAGE_8={,,} +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +--------------------------------------------------- +# Specify the file names of csf header and sg table. (Default :hdr.out) [Optional] +OUTPUT_HDR_FILENAME=hdr_bl2.out + +# Specify the file names of hash file and sign file. +HASH_FILENAME=img_hash.out +INPUT_SIGN_FILENAME=sign.out + +# Specify the signature size.It is mandatory when neither public key nor private key is specified. +# Signature size would be [0x80 for 1k key, 0x100 for 2k key, and 0x200 for 4k key]. +SIGN_SIZE= +--------------------------------------------------- +# Specify the output file name of sg table. (Default :sg_table.out). [Optional] +# Please note that OUTPUT SG BIN is only required for 2041/3041/4080/5020/5040 when ESBC flag is not set. +OUTPUT_SG_BIN= +--------------------------------------------------- +# Following fields are Required for 4240/9164/1040/C290 only + +# Specify House keeping Area +# Required for 4240/9164/1040/C290 only when ESBC flag is not set. [Mandatory] +HK_AREA_POINTER= +HK_AREA_SIZE= +--------------------------------------------------- +# Following field Required for 4240/9164/1040/C290 only +# Specify Secondary Image Flag. (0 or 1) - [Optional] +# (Default is 0) +SEC_IMAGE=0 +# Specify Manufacturing Protection Flag. (0 or 1) - [Optional] +# Required only for LS1(Default is 0) +MP_FLAG=1 +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 new file mode 100644 index 0000000..5fdad9c --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 @@ -0,0 +1,65 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.2: LX2160 +PLATFORM=LS2088 +--------------------------------------------------- +# Entry Point/Image start address field in the header.[Mandatory] +# (default=ADDRESS of first file specified in images) +# Address can be 64 bit +ENTRY_POINT=1800A000 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri +--------------------------------------------------- +# Specify IMAGE, Max 8 images are possible. +# DST_ADDR is required only for Non-PBL Platform. [Mandatory] +# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR} +# Address can be 64 bit +IMAGE_1={bl2.bin,1800A000,ffffffff} +IMAGE_2={,,} +IMAGE_3={,,} +IMAGE_4={,,} +IMAGE_5={,,} +IMAGE_6={,,} +IMAGE_7={,,} +IMAGE_8={,,} +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- +# Specify the output file names [Optional]. +# Default Values chosen in Tool +OUTPUT_HDR_FILENAME=hdr_bl2.out +IMAGE_HASH_FILENAME= +RSA_SIGN_FILENAME= +--------------------------------------------------- +# Specify The Flags. (0 or 1) - [Optional] +MP_FLAG=0 +ISS_FLAG=1 +LW_FLAG=0 +--------------------------------------------------- +# Specify VERBOSE as 1, if you want to Display Header Information [Optional] +VERBOSE=1 diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 new file mode 100644 index 0000000..cc7c07c --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 @@ -0,0 +1,65 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.2: LX2160 +PLATFORM=LX2160 +--------------------------------------------------- +# Entry Point/Image start address field in the header.[Mandatory] +# (default=ADDRESS of first file specified in images) +# Address can be 64 bit +ENTRY_POINT=1800D000 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri +--------------------------------------------------- +# Specify IMAGE, Max 8 images are possible. +# DST_ADDR is required only for Non-PBL Platform. [Mandatory] +# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR} +# Address can be 64 bit +IMAGE_1={bl2.bin,1800D000,ffffffff} +IMAGE_2={,,} +IMAGE_3={,,} +IMAGE_4={,,} +IMAGE_5={,,} +IMAGE_6={,,} +IMAGE_7={,,} +IMAGE_8={,,} +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- +# Specify the output file names [Optional]. +# Default Values chosen in Tool +OUTPUT_HDR_FILENAME=hdr_bl2.out +IMAGE_HASH_FILENAME= +RSA_SIGN_FILENAME= +--------------------------------------------------- +# Specify The Flags. (0 or 1) - [Optional] +MP_FLAG=0 +ISS_FLAG=1 +LW_FLAG=0 +--------------------------------------------------- +# Specify VERBOSE as 1, if you want to Display Header Information [Optional] +VERBOSE=1 diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 new file mode 100644 index 0000000..93b020b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 @@ -0,0 +1,30 @@ +/* + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - 1010/1040/2041/3041/4080/5020/5040/9131/9132/9164/4240/C290/LS1 +PLATFORM=LS1043 +# ESBC Flag. Specify ESBC=0 to sign u-boot and ESBC=1 to sign ESBC images.(default is 0) +ESBC=1 +--------------------------------------------------- +# Specify the file name of the keys separated by comma. + +# PRI_KEY (Default private key :srk.pri) - [Optional] +PRI_KEY=srk.pri +# PUB_KEY (Default public key :srk.pub) - [Optional] +PUB_KEY=srk.pub +# Please provide KEY_SELECT(between 1 to 4) (Required for 1040/C290/9164/4240 only) - [Optional] +KEY_SELECT=1 +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 new file mode 100644 index 0000000..18e8e3b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 @@ -0,0 +1,37 @@ +/* + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +ESBC=1 +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.0: LS2085 +# TRUST 3.1: LS2088, LS1088 +PLATFORM=LS2088 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri + +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 new file mode 100644 index 0000000..9111a2a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 @@ -0,0 +1,43 @@ +/* + * Copyright 2016-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.0: LS2085 +# TRUST 3.1: LS2088, LS1088 +PLATFORM=LS2088 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- +# Specify The Flags. (0 or 1) - [Optional] +MP_FLAG=0 +ISS_FLAG=1 +LW_FLAG=0 +--------------------------------------------------- +# Specify VERBOSE as 1, if you want to Display Header Information [Optional] +VERBOSE=1 +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 new file mode 100644 index 0000000..c2d7ce4 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 @@ -0,0 +1,43 @@ +/* + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.0: LS2085 +# TRUST 3.1: LS2088, LS1088 +PLATFORM=LX2160 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- +# Specify The Flags. (0 or 1) - [Optional] +MP_FLAG=0 +ISS_FLAG=1 +LW_FLAG=0 +--------------------------------------------------- +# Specify VERBOSE as 1, if you want to Display Header Information [Optional] +VERBOSE=1 +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c new file mode 100644 index 0000000..43b78e5 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Temporary variables to speed up the authentication parameters search. These + * variables are assigned once during the integrity check and used any time an + * authentication parameter is requested, so we do not have to parse the image + * again. + */ + +/* Hash of Image + CSF Header + SRK table */ +uint8_t img_hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE); +uint32_t hash_len; + +/* Key being used for authentication + * Points to the key in CSF header copied in DDR + * ESBC client key + */ +void *img_key; +uint32_t key_len; + +/* ESBC client signature */ +void *img_sign; +uint32_t sign_len; +enum sig_alg alg; + +/* Maximum OID string length ("a.b.c.d.e.f ...") */ +#define MAX_OID_STR_LEN 64 + +#define LIB_NAME "NXP CSFv2" + +/* + * 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) + + ZERO_AND_CLEAN(img_key); + ZERO_AND_CLEAN(img_sign); + ZERO_AND_CLEAN(img_hash); + ZERO_AND_CLEAN(key_len); + ZERO_AND_CLEAN(hash_len); + ZERO_AND_CLEAN(sign_len); + +#undef ZERO_AND_CLEAN +} + +/* Exported functions */ + +static void init(void) +{ + clear_temp_vars(); +} + +/* + * This function would check the integrity of the CSF header + */ +static int check_integrity(void *img, unsigned int img_len) +{ + int ret; + + /* + * The image file has been successfully loaded till here. + * + * Flush the image to main memory so that it can be authenticated + * by CAAM, a HW accelerator regardless of cache and MMU state. + */ + flush_dcache_range((uintptr_t) img, img_len); + + /* + * Image is appended at an offset of 16K (IMG_OFFSET) to the header. + * So the size in header should be equal to img_len - IMG_OFFSET + */ + VERBOSE("Barker code is %x\n", *(unsigned int *)img); + ret = validate_esbc_header(img, &img_key, &key_len, &img_sign, + &sign_len, &alg); + if (ret < 0) { + ERROR("Header authentication failed\n"); + clear_temp_vars(); + return IMG_PARSER_ERR; + } + /* Calculate the hash of various components from the image */ + ret = calc_img_hash(img, (uint8_t *)img + CSF_HDR_SZ, + img_len - CSF_HDR_SZ, img_hash, &hash_len); + if (ret != 0) { + ERROR("Issue in hash calculation %d\n", ret); + clear_temp_vars(); + return IMG_PARSER_ERR; + } + + return IMG_PARSER_OK; +} + +/* + * Extract an authentication parameter from CSF header + * + * CSF header has already been parsed and the required information like + * hash of data, signature, length stored in global variables has been + * extracted in chek_integrity function. This data + * is returned back to the caller. + */ +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; + + /* We do not use img because the check_integrity function has already + * extracted the relevant data ( pk, sig_alg, etc) + */ + + switch (type_desc->type) { + + /* Hash will be returned for comparison with signature */ + case AUTH_PARAM_HASH: + *param = (void *)img_hash; + *param_len = (unsigned int)SHA256_BYTES; + break; + + /* Return the public key used for signature extracted from the SRK table + * after checks with key revocation + */ + case AUTH_PARAM_PUB_KEY: + /* Get the subject public key */ + /* For a 1K key - the length would be 2k/8 = 0x100 bytes + * 2K RSA key - 0x200 , 4K RSA - 0x400 + */ + *param = img_key; + *param_len = (unsigned int)key_len; + break; + + /* Call a function to tell if signature is RSA or ECDSA. ECDSA to be + * supported in later platforms like LX2 etc + */ + case AUTH_PARAM_SIG_ALG: + /* Algo will be signature - RSA or ECDSA on hash */ + *param = (void *)&alg; + *param_len = 4U; + break; + + /* Return the signature */ + case AUTH_PARAM_SIG: + *param = img_sign; + *param_len = (unsigned int)sign_len; + break; + + case AUTH_PARAM_NV_CTR: + + 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/arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c b/arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c new file mode 100644 index 0000000..bb21fa0 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c @@ -0,0 +1,820 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#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 + +/* + * The platform must allocate buffers to store the authentication parameters + * extracted from the certificates. In this case, because of the way the CoT is + * established, we can reuse some of the buffers on different stages + */ + +static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN]; + +static unsigned char soc_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN]; +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char non_trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; + +#ifdef CONFIG_DDR_FIP_IMAGE +static unsigned char ddr_fw_content_pk_buf[PK_DER_LEN]; +static unsigned char ddr_imem_udimm_1d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_imem_udimm_2d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_dmem_udimm_1d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_dmem_udimm_2d_hash_buf[HASH_DER_LEN]; + +static unsigned char ddr_imem_rdimm_1d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_imem_rdimm_2d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_dmem_rdimm_1d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_dmem_rdimm_2d_hash_buf[HASH_DER_LEN]; +#endif + +/* + * Parameter type descriptors + */ +static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID); + +static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, 0); +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + + +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID); +static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID); +static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); + +#ifdef CONFIG_DDR_FIP_IMAGE +static auth_param_type_desc_t ddr_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, DDR_FW_CONTENT_CERT_PK_OID); + +static auth_param_type_desc_t ddr_imem_udimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_IMEM_UDIMM_1D_HASH_OID); +static auth_param_type_desc_t ddr_imem_udimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_IMEM_UDIMM_2D_HASH_OID); +static auth_param_type_desc_t ddr_dmem_udimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_DMEM_UDIMM_1D_HASH_OID); +static auth_param_type_desc_t ddr_dmem_udimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_DMEM_UDIMM_2D_HASH_OID); + +static auth_param_type_desc_t ddr_imem_rdimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_IMEM_RDIMM_1D_HASH_OID); +static auth_param_type_desc_t ddr_imem_rdimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_IMEM_RDIMM_2D_HASH_OID); +static auth_param_type_desc_t ddr_dmem_rdimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_DMEM_RDIMM_1D_HASH_OID); +static auth_param_type_desc_t ddr_dmem_rdimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_DMEM_RDIMM_2D_HASH_OID); +#endif + + +/* + * Trusted key certificate + */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; + +/* + * SoC Firmware + */ +static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } +}; +/* SOC FW Config */ +static const auth_img_desc_t soc_fw_config = { + .img_id = SOC_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_config_hash + } + } + } +}; +/* + * 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_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t trusted_os_fw_content_cert = { + .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_os_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tos_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_hash, + .data = { + .ptr = (void *)tos_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tos_fw_extra1_hash, + .data = { + .ptr = (void *)tos_fw_extra1_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &tos_fw_extra2_hash, + .data = { + .ptr = (void *)tos_fw_extra2_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &tos_fw_config_hash, + .data = { + .ptr = (void *)tos_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_hash + } + } + } +}; +static const auth_img_desc_t bl32_extra1_image = { + .img_id = BL32_EXTRA1_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra1_hash + } + } + } +}; +static const auth_img_desc_t bl32_extra2_image = { + .img_id = BL32_EXTRA2_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra2_hash + } + } + } +}; +/* TOS FW Config */ +static const auth_img_desc_t tos_fw_config = { + .img_id = TOS_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_config_hash + } + } + } +}; +/* + * 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_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &non_trusted_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &nt_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; +/* NT FW Config */ +static const auth_img_desc_t nt_fw_config = { + .img_id = NT_FW_CONFIG_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_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_fw_config_hash + } + } + } +}; +#ifdef CONFIG_DDR_FIP_IMAGE +/* + * DDR Firmware + */ +static const auth_img_desc_t ddr_fw_key_cert = { + .img_id = DDR_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &ddr_fw_content_pk, + .data = { + .ptr = (void *)ddr_fw_content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t ddr_udimm_fw_content_cert = { + .img_id = DDR_UDIMM_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &ddr_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &ddr_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &ddr_imem_udimm_1d_fw_hash, + .data = { + .ptr = (void *)ddr_imem_udimm_1d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &ddr_imem_udimm_2d_fw_hash, + .data = { + .ptr = (void *)ddr_imem_udimm_2d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &ddr_dmem_udimm_1d_fw_hash, + .data = { + .ptr = (void *)ddr_dmem_udimm_1d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &ddr_dmem_udimm_2d_fw_hash, + .data = { + .ptr = (void *)ddr_dmem_udimm_2d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + } +}; + +static const auth_img_desc_t ddr_imem_udimm_1d_img = { + .img_id = DDR_IMEM_UDIMM_1D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_udimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_imem_udimm_1d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_udimm_2d_img = { + .img_id = DDR_IMEM_UDIMM_2D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_udimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_imem_udimm_2d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_udimm_1d_img = { + .img_id = DDR_DMEM_UDIMM_1D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_udimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_dmem_udimm_1d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_udimm_2d_img = { + .img_id = DDR_DMEM_UDIMM_2D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_udimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_dmem_udimm_2d_fw_hash + } + } + } +}; + +static const auth_img_desc_t ddr_rdimm_fw_content_cert = { + .img_id = DDR_RDIMM_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &ddr_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &ddr_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &ddr_imem_rdimm_1d_fw_hash, + .data = { + .ptr = (void *)ddr_imem_rdimm_1d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &ddr_imem_rdimm_2d_fw_hash, + .data = { + .ptr = (void *)ddr_imem_rdimm_2d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &ddr_dmem_rdimm_1d_fw_hash, + .data = { + .ptr = (void *)ddr_dmem_rdimm_1d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &ddr_dmem_rdimm_2d_fw_hash, + .data = { + .ptr = (void *)ddr_dmem_rdimm_2d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + } +}; + +static const auth_img_desc_t ddr_imem_rdimm_1d_img = { + .img_id = DDR_IMEM_RDIMM_1D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_rdimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_imem_rdimm_1d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_rdimm_2d_img = { + .img_id = DDR_IMEM_RDIMM_2D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_rdimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_imem_rdimm_2d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_rdimm_1d_img = { + .img_id = DDR_DMEM_RDIMM_1D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_rdimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_dmem_rdimm_1d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_rdimm_2d_img = { + .img_id = DDR_DMEM_RDIMM_2D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_rdimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_dmem_rdimm_2d_fw_hash + } + } + } +}; +#endif + +/* + * TBBR Chain of trust definition + */ + +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert, + [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert, + [BL31_IMAGE_ID] = &bl31_image, + [SOC_FW_CONFIG_ID] = &soc_fw_config, + [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, + [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image, + [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image, + [TOS_FW_CONFIG_ID] = &tos_fw_config, + [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, + [NT_FW_CONFIG_ID] = &nt_fw_config, +#ifdef CONFIG_DDR_FIP_IMAGE + [DDR_FW_KEY_CERT_ID] = &ddr_fw_key_cert, + [DDR_UDIMM_FW_CONTENT_CERT_ID] = &ddr_udimm_fw_content_cert, + [DDR_RDIMM_FW_CONTENT_CERT_ID] = &ddr_rdimm_fw_content_cert, + [DDR_IMEM_UDIMM_1D_IMAGE_ID] = &ddr_imem_udimm_1d_img, + [DDR_IMEM_UDIMM_2D_IMAGE_ID] = &ddr_imem_udimm_2d_img, + [DDR_DMEM_UDIMM_1D_IMAGE_ID] = &ddr_dmem_udimm_1d_img, + [DDR_DMEM_UDIMM_2D_IMAGE_ID] = &ddr_dmem_udimm_2d_img, + [DDR_IMEM_RDIMM_1D_IMAGE_ID] = &ddr_imem_rdimm_1d_img, + [DDR_IMEM_RDIMM_2D_IMAGE_ID] = &ddr_imem_rdimm_2d_img, + [DDR_DMEM_RDIMM_1D_IMAGE_ID] = &ddr_dmem_rdimm_1d_img, + [DDR_DMEM_RDIMM_2D_IMAGE_ID] = &ddr_dmem_rdimm_2d_img, +#endif +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/nxp/console/16550_console.S b/arm-trusted-firmware/drivers/nxp/console/16550_console.S new file mode 100644 index 0000000..044d3d0 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/console/16550_console.S @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/* UART16550 Registers */ +#define UARTTX 0x0 +#define UARTRX 0x0 +#define UARTDLL 0x0 +#define UARTIER 0x1 +#define UARTDLLM 0x1 +#define UARTFCR 0x2 +#define UARTLCR 0x3 +#define UARTLSR 0x5 +#define UARTMCR 0x4 + +/* FIFO Control Register bits */ +#define UARTFCR_FIFOMD_16450 (0 << 6) +#define UARTFCR_FIFOMD_16550 (1 << 6) +#define UARTFCR_RXTRIG_1 (0 << 6) +#define UARTFCR_RXTRIG_4 (1 << 6) +#define UARTFCR_RXTRIG_8 (2 << 6) +#define UARTFCR_RXTRIG_16 (3 << 6) +#define UARTFCR_TXTRIG_1 (0 << 4) +#define UARTFCR_TXTRIG_4 (1 << 4) +#define UARTFCR_TXTRIG_8 (2 << 4) +#define UARTFCR_TXTRIG_16 (3 << 4) +#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */ +#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */ +#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */ +#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */ +#define UARTFCR_64FIFO (1 << 5) + +/* Line Control Register bits */ +#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */ +#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */ +#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */ +#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */ +#define UARTLCR_PAR (1 << 3) /* Parity */ +#define UARTLCR_STOP (1 << 2) /* Stop Bit */ +#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */ +#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */ +#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */ +#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */ + +/* Line Status Register bits */ +#define UARTLSR_RXFIFOEMT (1 << 9) /* Rx Fifo Empty */ +#define UARTLSR_TXFIFOFULL (1 << 8) /* Tx Fifo Full */ +#define UARTLSR_RXFIFOERR (1 << 7) /* Rx Fifo Error */ +#define UARTLSR_TEMT (1 << 6) /* Tx Shift Register Empty */ +#define UARTLSR_THRE (1 << 5) /* Tx Holding Register Empty */ +#define UARTLSR_BRK (1 << 4) /* Break Condition Detected */ +#define UARTLSR_FERR (1 << 3) /* Framing Error */ +#define UARTLSR_PERR (1 << 3) /* Parity Error */ +#define UARTLSR_OVRF (1 << 2) /* Rx Overrun Error */ +#define UARTLSR_RDR (1 << 2) /* Rx Data Ready */ + +#define CONSOLE_T_16550_BASE CONSOLE_T_BASE + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl nxp_console_16550_core_init + .globl nxp_console_16550_core_putc + .globl nxp_console_16550_core_getc + .globl nxp_console_16550_core_flush + + .globl console_16550_putc + .globl console_16550_getc + .globl console_16550_flush + + /* ----------------------------------------------- + * int nxp_console_16550_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success, 0 on error + * Clobber list : x1, x2, x3 + * ----------------------------------------------- + */ +func nxp_console_16550_core_init + /* Check the input base address */ + cbz x0, init_fail + /* Check baud rate and uart clock for sanity */ + cbz w1, init_fail + cbz w2, init_fail + + /* Program the baudrate */ + /* Divisor = Uart clock / (16 * baudrate) */ + lsl w2, w2, #4 + udiv w2, w1, w2 + and w1, w2, #0xff /* w1 = DLL */ + lsr w2, w2, #8 + and w2, w2, #0xff /* w2 = DLLM */ + ldrb w3, [x0, #UARTLCR] + orr w3, w3, #UARTLCR_DLAB + strb w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */ + strb w1, [x0, #UARTDLL] /* program DLL */ + strb w2, [x0, #UARTDLLM] /* program DLLM */ + mov w2, #~UARTLCR_DLAB + and w3, w3, w2 + strb w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */ + + /* 8n1 */ + mov w3, #3 + strb w3, [x0, #UARTLCR] + /* no interrupt */ + mov w3, #0 + strb w3, [x0, #UARTIER] + /* enable fifo, DMA */ + mov w3, #(UARTFCR_FIFOEN |UARTFCR_TXCLR | UARTFCR_RXCLR) + strb w3, [x0, #UARTFCR] + /* DTR + RTS */ + mov w3, #3 + str w3, [x0, #UARTMCR] + mov w0, #1 + ret +init_fail: + mov w0, #0 + ret +endfunc nxp_console_16550_core_init + + .globl nxp_console_16550_register + + /* ----------------------------------------------- + * int nxp_console_16550_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new 16550 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * If w1 (UART clock) is 0, initialisation will be + * skipped, relying on previous code to have done + * this already. w2 is ignored then as well. + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate (ignored if w1 is 0) + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func nxp_console_16550_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_16550_BASE] + + /* A clock rate of zero means to skip the initialisation. */ + cbz w1, register_16550 + + bl nxp_console_16550_core_init + cbz x0, register_fail + +register_16550: + mov x0, x6 + mov x30, x7 + finish_console_register 16550 putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc nxp_console_16550_register + + /* -------------------------------------------------------- + * int console_16550_core_putc(int c, uintptr_t base_addr) + * 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 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func nxp_console_16550_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp w0, #'\n' + b.ne 2f + /* Check if the transmit FIFO is full */ +1: ldrb w2, [x1, #UARTLSR] + and w2, w2, #UARTLSR_THRE /* #(UARTLSR_TEMT | UARTLSR_THRE)*/ + cmp w2, #(UARTLSR_THRE) + b.ne 1b + mov w2, #'\r' + strb w2, [x1, #UARTTX] + ldrb w2, [x1, #UARTFCR] + orr w2, w2, #UARTFCR_TXCLR + + /* Check if the transmit FIFO is full */ +2: ldrb w2, [x1, #UARTLSR] + and w2, w2, #(UARTLSR_THRE) + cmp w2, #(UARTLSR_THRE) + b.ne 2b + strb w0, [x1, #UARTTX] + ret +endfunc nxp_console_16550_core_putc + + /* -------------------------------------------------------- + * int console_16550_putc(int c, console_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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_16550_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_16550_BASE] + b nxp_console_16550_core_putc +endfunc console_16550_putc + + /* --------------------------------------------- + * int console_16550_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - console base address + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func nxp_console_16550_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ +1: ldrb w1, [x0, #UARTLSR] + tbz w1, #UARTLSR_RDR, 1b + ldrb w0, [x0, #UARTRX] + ret +no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc nxp_console_16550_core_getc + + /* --------------------------------------------- + * int console_16550_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - pointer to console_t structure + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_getc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_16550_BASE] + b nxp_console_16550_core_getc +endfunc console_16550_getc + + /* --------------------------------------------- + * int console_16550_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func nxp_console_16550_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Loop until the transmit FIFO is empty */ +1: ldrb w1, [x0, #UARTLSR] + and w1, w1, #(UARTLSR_THRE) + cmp w1, #(UARTLSR_THRE) + b.ne 1b + + mov w0, #0 + ret +endfunc nxp_console_16550_core_flush + + /* --------------------------------------------- + * int console_16550_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_16550_BASE] + b nxp_console_16550_core_flush +endfunc console_16550_flush diff --git a/arm-trusted-firmware/drivers/nxp/console/console.mk b/arm-trusted-firmware/drivers/nxp/console/console.mk new file mode 100644 index 0000000..6174650 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/console/console.mk @@ -0,0 +1,46 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the CORE files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_CONSOLE},) + +ADD_CONSOLE := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/console + +ifeq ($(CONSOLE), NS16550) +NXP_CONSOLE := NS16550 + +$(eval $(call add_define_val,NXP_CONSOLE,${NXP_CONSOLE})) + +CONSOLE_SOURCES := $(PLAT_DRIVERS_PATH)/console/16550_console.S \ + $(PLAT_DRIVERS_PATH)/console/console_16550.c +else +ifeq ($(CONSOLE), PL011) +CONSOLE_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \ + ${PLAT_DRIVERS_PATH}/console/console_pl011.c +else + $(error -> CONSOLE not set!) +endif +endif + +ifeq (${BL_COMM_CONSOLE_NEEDED},yes) +BL_COMMON_SOURCES += ${CONSOLE_SOURCES} +else +ifeq (${BL2_CONSOLE_NEEDED},yes) +BL2_SOURCES += ${CONSOLE_SOURCES} +endif +ifeq (${BL31_CONSOLE_NEEDED},yes) +BL31_SOURCES += ${CONSOLE_SOURCES} +endif +endif +endif +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/console/console_16550.c b/arm-trusted-firmware/drivers/nxp/console/console_16550.c new file mode 100644 index 0000000..fa5c5bb --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/console/console_16550.c @@ -0,0 +1,33 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include + +/* + * Perform Arm specific early platform setup. At this moment we only initialize + * the console and the memory layout. + */ +void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div, + uint32_t baud) +{ + struct sysinfo sys; + static console_t nxp_console; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + panic(); + } + nxp_console_16550_register(nxp_console_addr, + (sys.freq_platform/uart_clk_div), + baud, &nxp_console); +} diff --git a/arm-trusted-firmware/drivers/nxp/console/console_pl011.c b/arm-trusted-firmware/drivers/nxp/console/console_pl011.c new file mode 100644 index 0000000..93f2fc2 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/console/console_pl011.c @@ -0,0 +1,35 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include +#include + +/* + * Perform Arm specific early platform setup. At this moment we only initialize + * the console and the memory layout. + */ +void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div, + uint32_t baud) +{ + struct sysinfo sys; + static console_t nxp_console; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + panic(); + } + + console_pl011_register(nxp_console_addr, + (sys.freq_platform/uart_clk_div), + baud, &nxp_console); +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/caam.mk b/arm-trusted-firmware/drivers/nxp/crypto/caam/caam.mk new file mode 100644 index 0000000..f929f53 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/caam.mk @@ -0,0 +1,27 @@ +# +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +ifeq (${ADD_CAAM},) + +ADD_CAAM := 1 + +CAAM_DRIVER_SOURCES += $(wildcard $(PLAT_DRIVERS_PATH)/crypto/caam/src/*.c) + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/crypto/caam + +ifeq (${BL_COMM_CRYPTO_NEEDED},yes) +BL_COMMON_SOURCES += ${CAAM_DRIVER_SOURCES} +else +ifeq (${BL2_CRYPTO_NEEDED},yes) +BL2_SOURCES += ${CAAM_DRIVER_SOURCES} +endif +ifeq (${BL31_CRYPTO_NEEDED},yes) +BL31_SOURCES += ${CAAM_DRIVER_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/auth.mk b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/auth.mk new file mode 100644 index 0000000..d1f8c75 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/auth.mk @@ -0,0 +1,12 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +SEC_DRIVERS_PATH := drivers/nxp/crypto/caam + +ifeq (${TRUSTED_BOARD_BOOT},1) +AUTH_SOURCES += $(wildcard $(SEC_DRIVERS_PATH)/src/auth/*.c) +endif diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c new file mode 100644 index 0000000..1665df1 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c @@ -0,0 +1,155 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include + +#include "hash.h" +#include "jobdesc.h" +#include "sec_hw_specific.h" + +/* Since no Allocator is available . Taking a global static ctx. + * This would mean that only one active ctx can be there at a time. + */ + +static struct hash_ctx glbl_ctx; + +static void hash_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("Hash Desc SUCCESS with status %x\n", status); +} + +/*************************************************************************** + * Function : hash_init + * Arguments : ctx - SHA context + * Return : init, + * Description : This function initializes the context for SHA calculation + ***************************************************************************/ +int hash_init(enum hash_algo algo, void **ctx) +{ + if (glbl_ctx.active == false) { + memset(&glbl_ctx, 0, sizeof(struct hash_ctx)); + glbl_ctx.active = true; + glbl_ctx.algo = algo; + *ctx = &glbl_ctx; + return 0; + } else { + return -1; + } +} + +/*************************************************************************** + * Function : hash_update + * Arguments : ctx - SHA context + * buffer - Data + * length - Length + * Return : -1 on error + * 0 on SUCCESS + * Description : This function creates SG entry of the data provided + ***************************************************************************/ +int hash_update(enum hash_algo algo, void *context, void *data_ptr, + unsigned int data_len) +{ + struct hash_ctx *ctx = context; + /* MAX_SG would be MAX_SG_ENTRIES + key + hdr + sg table */ + if (ctx->sg_num >= MAX_SG) { + ERROR("Reached limit for calling %s\n", __func__); + ctx->active = false; + return -EINVAL; + + } + + if (ctx->algo != algo) { + ERROR("ctx for algo not correct\n"); + ctx->active = false; + return -EINVAL; + } + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)data_ptr, data_len); + dmbsy(); +#endif + +#ifdef CONFIG_PHYS_64BIT + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, + (uint32_t) ((uintptr_t) data_ptr >> 32)); +#else + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0); +#endif + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uintptr_t) data_ptr); + + sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, + (data_len & SG_ENTRY_LENGTH_MASK)); + + ctx->sg_num++; + + ctx->len += data_len; + + return 0; +} + +/*************************************************************************** + * Function : hash_final + * Arguments : ctx - SHA context + * Return : SUCCESS or FAILURE + * Description : This function sets the final bit and enqueues the decriptor + ***************************************************************************/ +int hash_final(enum hash_algo algo, void *context, void *hash_ptr, + unsigned int hash_len) +{ + int ret = 0; + struct hash_ctx *ctx = context; + uint32_t final = 0U; + + struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE); + + jobdesc.arg = NULL; + jobdesc.callback = hash_done; + + if (ctx->algo != algo) { + ERROR("ctx for algo not correct\n"); + ctx->active = false; + return -EINVAL; + } + + final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | + SG_ENTRY_FINAL_BIT; + sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); + + dsb(); + + /* create the hw_rng descriptor */ + cnstr_hash_jobdesc(jobdesc.desc, (uint8_t *) ctx->sg_tbl, + ctx->len, hash_ptr); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)ctx->sg_tbl, + (sizeof(struct sg_entry) * MAX_SG)); + inv_dcache_range((uintptr_t)hash_ptr, hash_len); + + dmbsy(); +#endif + + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(&jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } + ctx->active = false; + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c new file mode 100644 index 0000000..646e981 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c @@ -0,0 +1,123 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include "caam.h" +#include +#include + +#include "hash.h" +#include "rsa.h" + +#define LIB_NAME "NXP crypto" + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + /* Initialize NXP crypto library`:*/ + NOTICE("Initializing & configuring SEC block.\n"); + + if (config_sec_block() < 0) { + ERROR("Init & config failure for caam.\n"); + } +} + +/* + * Verify a signature. + * + * For IMG_PLAT - data points to a PKCS#1.5 encoded HASH + * sig_alg will be RSA or ECC + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sign_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + int ret = CRYPTO_SUCCESS; + + enum sig_alg alg = *(enum sig_alg *)sign_alg; + + switch (alg) { + case RSA: + NOTICE("Verifying RSA\n"); + ret = rsa_verify_signature(data_ptr, data_len, sig_ptr, sig_len, + pk_ptr, pk_len); + break; + case ECC: + default: + ret = CRYPTO_ERR_SIGNATURE; + break; + } + + if (ret != 0) { + ERROR("RSA verification Failed\n"); + } + return ret; + +} + +/* + * Match a hash + * + * Digest info is passed as a table of SHA-26 hashes and digest_info_len + * is number of entries in the table + * This implementation is very specific to the CSF header parser ROTPK + * comparison. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + void *ctx = NULL; + int i = 0, ret = 0; + enum hash_algo algo = SHA256; + uint8_t hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE) = {0}; + uint32_t digest_size = SHA256_BYTES; + uint8_t *hash_tbl = digest_info_ptr; + + NOTICE("Verifying hash\n"); + ret = hash_init(algo, &ctx); + if (ret != 0) { + return CRYPTO_ERR_HASH; + } + + /* Update hash with that of SRK table */ + ret = hash_update(algo, ctx, data_ptr, data_len); + if (ret != 0) { + return CRYPTO_ERR_HASH; + } + + /* Copy hash at destination buffer */ + ret = hash_final(algo, ctx, hash, digest_size); + if (ret != 0) { + return CRYPTO_ERR_HASH; + } + + VERBOSE("%s Calculated hash\n", __func__); + for (i = 0; i < SHA256_BYTES/4; i++) { + VERBOSE("%x\n", *((uint32_t *)hash + i)); + } + + for (i = 0; i < digest_info_len; i++) { + if (memcmp(hash, (hash_tbl + (i * digest_size)), + digest_size) == 0) { + return CRYPTO_SUCCESS; + } + } + + return CRYPTO_ERR_HASH; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c new file mode 100644 index 0000000..0c44462 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c @@ -0,0 +1,179 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include + +#include "jobdesc.h" +#include "rsa.h" +#include "sec_hw_specific.h" + +/* This array contains DER value for SHA-256 */ +static const uint8_t hash_identifier[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, + 0x04, 0x20 +}; + +static void rsa_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("RSA Desc SUCCESS with status %x\n", status); +} + +static int rsa_public_verif_sec(uint8_t *sign, uint8_t *to, + uint8_t *rsa_pub_key, uint32_t klen) +{ + int ret = 0; + struct rsa_context ctx __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE); + + jobdesc.arg = NULL; + jobdesc.callback = rsa_done; + + memset(&ctx, 0, sizeof(struct rsa_context)); + + ctx.pkin.a = sign; + ctx.pkin.a_siz = klen; + ctx.pkin.n = rsa_pub_key; + ctx.pkin.n_siz = klen; + ctx.pkin.e = rsa_pub_key + klen; + ctx.pkin.e_siz = klen; + + cnstr_jobdesc_pkha_rsaexp(jobdesc.desc, &ctx.pkin, to, klen); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)sign, klen); + flush_dcache_range((uintptr_t)rsa_pub_key, 2 * klen); + flush_dcache_range((uintptr_t)&ctx.pkin, sizeof(ctx.pkin)); + inv_dcache_range((uintptr_t)to, klen); + + dmbsy(); + dsbsy(); + isb(); +#endif + + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(&jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range((uintptr_t)to, klen); + dmbsy(); + dsbsy(); + isb(); +#endif + return ret; +} + +/* + * Construct encoded hash EM' wrt PKCSv1.5. This function calculates the + * pointers for padding, DER value and hash. And finally, constructs EM' + * which includes hash of complete CSF header and ESBC image. If SG flag + * is on, hash of SG table and entries is also included. + */ +static int construct_img_encoded_hash_second(uint8_t *hash, uint8_t hash_len, + uint8_t *encoded_hash_second, + unsigned int key_len) +{ + /* + * RSA PKCSv1.5 encoding format for encoded message is below + * EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash + * PS is Padding String + * DER is DER value for SHA-256 + * Hash is SHA-256 hash + * ********************************************************* + * representative points to first byte of EM initially and is + * filled with 0x0 + * representative is incremented by 1 and second byte is filled + * with 0x1 + * padding points to third byte of EM + * digest points to full length of EM - 32 bytes + * hash_id (DER value) points to 19 bytes before pDigest + * separator is one byte which separates padding and DER + */ + + unsigned int len; + uint8_t *representative; + uint8_t *padding, *digest; + uint8_t *hash_id, *separator; + int i; + int ret = 0; + + if (hash_len != SHA256_BYTES) { + return -1; + } + + /* Key length = Modulus length */ + len = (key_len / 2U) - 1U; + representative = encoded_hash_second; + representative[0] = 0U; + representative[1] = 1U; /* block type 1 */ + + padding = &representative[2]; + digest = &representative[1] + len - 32; + hash_id = digest - sizeof(hash_identifier); + separator = hash_id - 1; + + /* fill padding area pointed by padding with 0xff */ + memset(padding, 0xff, separator - padding); + + /* fill byte pointed by separator */ + *separator = 0U; + + /* fill SHA-256 DER value pointed by HashId */ + memcpy(hash_id, hash_identifier, sizeof(hash_identifier)); + + /* fill hash pointed by Digest */ + for (i = 0; i < SHA256_BYTES; i++) { + digest[i] = hash[i]; + } + + return ret; +} + +int rsa_verify_signature(void *hash_ptr, unsigned int hash_len, + void *sig_ptr, unsigned int sig_len, + void *pk_ptr, unsigned int pk_len) +{ + uint8_t img_encoded_hash_second[RSA_4K_KEY_SZ_BYTES]; + uint8_t encoded_hash[RSA_4K_KEY_SZ_BYTES] __aligned(CACHE_WRITEBACK_GRANULE); + int ret = 0; + + ret = construct_img_encoded_hash_second(hash_ptr, hash_len, + img_encoded_hash_second, + pk_len); + if (ret != 0) { + ERROR("Encoded Hash Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + ret = rsa_public_verif_sec(sig_ptr, encoded_hash, pk_ptr, pk_len / 2); + if (ret != 0) { + ERROR("RSA signature Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + ret = memcmp(img_encoded_hash_second, encoded_hash, sig_len); + if (ret != 0) { + ERROR("Comparison Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + return CRYPTO_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c new file mode 100644 index 0000000..e594f7b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c @@ -0,0 +1,339 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include "jobdesc.h" +#include "sec_hw_specific.h" + +static uintptr_t g_nxp_caam_addr; +static void *job_ring; + +uintptr_t get_caam_addr(void) +{ + if (g_nxp_caam_addr == 0) { + ERROR("Sec Init is not done.\n"); + panic(); + } + return g_nxp_caam_addr; +} + +/* This function sets the TZ bit for the Job ring number passed as @num */ +static void config_tz(int num) +{ + uint32_t jricid; + + /* Setting TZ bit of job ring */ + switch (num) { + case 0: + jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET); + sec_out32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET, + jricid | JRICID_MS_TZ); + break; + case 1: + jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET); + sec_out32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET, + jricid | JRICID_MS_TZ); + break; + case 2: + jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET); + sec_out32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET, + jricid | JRICID_MS_TZ); + break; + case 3: + jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET); + sec_out32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET, + jricid | JRICID_MS_TZ); + break; + default: + break; + } +} + +/* This function checks if Virtualization is enabled for JR and + * accordingly sets the bot for starting JR in JRSTARTR register + */ +static inline void start_jr(int num) +{ + uint32_t ctpr = sec_in32((g_nxp_caam_addr + SEC_REG_CTPR_MS_OFFSET)); + uint32_t tmp = sec_in32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET)); + uint32_t scfgr = sec_in32((g_nxp_caam_addr + SEC_REG_SCFGR_OFFSET)); + bool start = false; + + if ((ctpr & CTPR_VIRT_EN_INC) != 0U) { + if (((ctpr & CTPR_VIRT_EN_POR) != 0U) || + ((scfgr & SCFGR_VIRT_EN) != 0U)) { + start = true; + } + } else { + if ((ctpr & CTPR_VIRT_EN_POR) != 0U) { + start = true; + } + } + + if (start == true) { + switch (num) { + case 0: + tmp |= JRSTARTR_STARTJR0; + break; + case 1: + tmp |= JRSTARTR_STARTJR1; + break; + case 2: + tmp |= JRSTARTR_STARTJR2; + break; + case 3: + tmp |= JRSTARTR_STARTJR3; + break; + default: + break; + } + } + sec_out32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET), tmp); +} + +/* This functions configures the Job Ring + * JR3 is reserved for use by Secure world + */ +static int configure_jr(int num) +{ + int ret; + void *reg_base_addr; + + switch (num) { + case 0: + reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR0_OFFSET); + break; + case 1: + reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR1_OFFSET); + break; + case 2: + reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR2_OFFSET); + break; + case 3: + reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR3_OFFSET); + break; + default: + break; + } + + /* Initialize the JR library */ + ret = sec_jr_lib_init(); + if (ret != 0) { + ERROR("Error in sec_jr_lib_init"); + return -1; + } + + start_jr(num); + + /* Do HW configuration of the JR */ + job_ring = init_job_ring(SEC_NOTIFICATION_TYPE_POLL, 0, 0, + reg_base_addr, 0); + + if (job_ring == NULL) { + ERROR("Error in init_job_ring"); + return -1; + } + + return ret; +} + +/* TBD - Configures and locks the ICID values for various JR */ +static inline void configure_icid(void) +{ +} + +/* TBD configures the TZ settings of RTIC */ +static inline void configure_rtic(void) +{ +} + +int sec_init(uintptr_t nxp_caam_addr) +{ + g_nxp_caam_addr = nxp_caam_addr; + return config_sec_block(); +} + +/* This function configure SEC block: + * - It does basic parameter setting + * - Configures the default Job ring assigned to TZ /secure world + * - Instantiates the RNG + */ +int config_sec_block(void) +{ + int ret = 0; + uint32_t mcfgr; + + if (g_nxp_caam_addr == 0) { + ERROR("Sec Init is not done.\n"); + return -1; + } else if (job_ring != NULL) { + NOTICE("Sec is already initialized and configured.\n"); + return ret; + } + + mcfgr = sec_in32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET); + + /* Modify CAAM Read/Write attributes + * AXI Write - Cacheable, WB and WA + * AXI Read - Cacheable, RA + */ +#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS2088A) + mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0xb << MCFGR_AWCACHE_SHIFT); + mcfgr = (mcfgr & ~MCFGR_ARCACHE_MASK) | (0x6 << MCFGR_ARCACHE_SHIFT); +#else + mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0x2 << MCFGR_AWCACHE_SHIFT); +#endif + + /* Set PS bit to 1 */ +#ifdef CONFIG_PHYS_64BIT + mcfgr |= (1 << MCFGR_PS_SHIFT); +#endif + sec_out32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET, mcfgr); + + /* Asssign ICID to all Job rings and lock them for usage */ + configure_icid(); + + /* Configure the RTIC */ + configure_rtic(); + + /* Configure the default JR for usage */ + ret = configure_jr(DEFAULT_JR); + if (ret != 0) { + ERROR("\nFSL_JR: configuration failure\n"); + return -1; + } + /* Do TZ configuration of default JR for sec firmware */ + config_tz(DEFAULT_JR); + +#ifdef CONFIG_RNG_INIT + /* Instantiate the RNG */ + ret = hw_rng_instantiate(); + if (ret != 0) { + ERROR("\nRNG Instantiation failure\n"); + return -1; + } +#endif + + return ret; +} + +/* This function is used for sumbitting job to the Job Ring + * [param] [in] - jobdesc to be submitted + * Return - -1 in case of error and 0 in case of SUCCESS + */ +int run_descriptor_jr(struct job_descriptor *jobdesc) +{ + int i = 0, ret = 0; + uint32_t *desc_addr = jobdesc->desc; + uint32_t desc_len = desc_length(jobdesc->desc); + uint32_t desc_word; + + for (i = 0; i < desc_len; i++) { + desc_word = desc_addr[i]; + VERBOSE("%x\n", desc_word); + sec_out32((uint32_t *)&desc_addr[i], desc_word); + } + dsb(); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)desc_addr, desc_len * 4); + dmbsy(); + dsbsy(); + isb(); +#endif + + ret = enq_jr_desc(job_ring, jobdesc); + if (ret == 0) { + VERBOSE("JR enqueue done...\n"); + } else { + ERROR("Error in Enqueue\n"); + return ret; + } + + VERBOSE("Dequeue in progress"); + + ret = dequeue_jr(job_ring, -1); + if (ret >= 0) { + VERBOSE("Dequeue of %x desc success\n", ret); + ret = 0; + } else { + ERROR("deq_ret %x\n", ret); + ret = -1; + } + + return ret; +} + +/* this function returns a random number using HW RNG Algo + * In case of failure, random number returned is 0 + * prngWidth = 0 - 32 bit random number + * prngWidth > 0 means 64 bit random number + */ +unsigned long long get_random(int rngWidth) +{ + unsigned long long result = 0; + uint8_t rand_byte[64] __aligned(CACHE_WRITEBACK_GRANULE); + uint8_t rand_byte_swp[8]; + int bytes = 0; + int i = 0; + int ret = 0; + +#ifdef CAAM_TEST + rand_byte[0] = U(0x12); + rand_byte[1] = U(0x34); + rand_byte[2] = U(0x56); + rand_byte[3] = U(0x78); + rand_byte[4] = U(0x9a); + rand_byte[5] = U(0xbc); + rand_byte[6] = U(0xde); + rand_byte[7] = U(0xf1); +#endif + + if (rngWidth == 0U) { + bytes = 4; + } else { + bytes = 8; + } + + memset(rand_byte, 0, 64); + + ret = get_rand_bytes_hw(rand_byte, bytes); + + for (i = 0; i < bytes; i++) { + if (ret != 0) { + /* Return 0 in case of failure */ + rand_byte_swp[i] = 0; + } else { + rand_byte_swp[i] = rand_byte[bytes - i - 1]; + result = (result << 8) | rand_byte_swp[i]; + } + } + + INFO("result %llx\n", result); + + return result; + +} /* _get_RNG() */ + +unsigned int _get_hw_unq_key(uint64_t hw_key_phy_addr, unsigned int size) +{ + int ret = 0; + uint8_t *hw_key = (uint8_t *) ptov((phys_addr_t *) hw_key_phy_addr); + + ret = get_hw_unq_key_blob_hw(hw_key, size); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c new file mode 100644 index 0000000..0720695 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c @@ -0,0 +1,81 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include "caam.h" +#include +#include "jobdesc.h" +#include "sec_hw_specific.h" + + +/* Callback function after Instantiation decsriptor is submitted to SEC + */ +static void blob_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("Blob Desc SUCCESS with status %x\n", status); +} + +/* @brief Submit descriptor to create blob + * @retval 0 on success + * @retval -1 on error + */ +int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size) +{ + int ret = 0; + int i = 0; + + uint32_t key_sz = KEY_IDNFR_SZ_BYTES; + uint8_t key_data[KEY_IDNFR_SZ_BYTES]; + uint8_t in_data[16]; + uint8_t out_data[16 + KEY_BLOB_SIZE + MAC_SIZE]; + struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor *jobdesc = &desc; + uint32_t in_sz = 16U; + + /* Output blob will have 32 bytes key blob in beginning and + * 16 byte HMAC identifier at end of data blob + */ + uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE; + + uint32_t operation = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | + OP_PCLID_BLOB | BLOB_PROTO_INFO; + + memset(key_data, 0xff, KEY_IDNFR_SZ_BYTES); + memset(in_data, 0x00, in_sz); + memset(out_data, 0x00, in_sz); + + jobdesc->arg = NULL; + jobdesc->callback = blob_done; + + INFO("\nGenerating Master Key Verification Blob.\n"); + + /* Create the hw_rng descriptor */ + ret = cnstr_hw_encap_blob_jobdesc(jobdesc->desc, key_data, key_sz, + CLASS_2, in_data, in_sz, out_data, + out_sz, operation); + + /* Finally, generate the blob. */ + ret = run_descriptor_jr(jobdesc); + if (ret != 0) { + ERROR("Error in running hw unq key blob descriptor\n"); + return -1; + } + /* Copying alternate bytes of the Master Key Verification Blob. + */ + for (i = 0; i < size; i++) { + hw_key[i] = out_data[2 * i]; + } + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c new file mode 100644 index 0000000..f559c4b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c @@ -0,0 +1,236 @@ +/* + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include "caam.h" +#include +#include "jobdesc.h" +#include "rsa.h" +#include "sec_hw_specific.h" + + +/* Return Length of desctiptr from first word */ +uint32_t desc_length(uint32_t *desc) +{ + return desc[0] & DESC_LEN_MASK; +} + +/*Update start index in first word of descriptor */ +void desc_update_start_index(uint32_t *desc, uint32_t index) +{ + desc[0] |= (index << DESC_START_SHIFT); +} + +/* Initialize the descriptor */ +void desc_init(uint32_t *desc) +{ + *desc = 0; +} + +/* Add word in the descriptor and increment the length */ +void desc_add_word(uint32_t *desc, uint32_t word) +{ + uint32_t len = desc_length(desc); + + /* Add Word at Last */ + uint32_t *last = desc + len; + *last = word; + + /* Increase the length */ + desc[0] += 1; +} + +/* Add Pointer to the descriptor */ +void desc_add_ptr(uint32_t *desc, phys_addr_t *ptr) +{ + uint32_t len = desc_length(desc); + + /* Add Word at Last */ + phys_addr_t *last = (phys_addr_t *) (desc + len); + +#ifdef CONFIG_PHYS_64BIT + ptr_addr_t *ptr_addr = (ptr_addr_t *) last; + + ptr_addr->high = PHYS_ADDR_HI(ptr); + ptr_addr->low = PHYS_ADDR_LO(ptr); +#else + *last = ptr; +#endif + + /* Increase the length */ + desc[0] += (uint32_t) (sizeof(phys_addr_t) / sizeof(uint32_t)); +} + +/* Descriptor to generate Random words */ +int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle, + uint32_t *add_inp, uint32_t add_ip_len, + uint8_t *out_data, uint32_t len) +{ + phys_addr_t *phys_addr_out = vtop(out_data); + + /* Current descriptor support only 64K length */ + if (len > U(0xffff)) + return -1; + /* Additional Input not supported by current descriptor */ + if (add_ip_len > 0U) + return -1; + + VERBOSE("Constructing descriptor\n"); + desc_init(desc); + /* Class1 Alg Operation,RNG Optype, Generate */ + desc_add_word(desc, U(0xb0800000)); + desc_add_word(desc, U(0x82500000) | (state_handle << ALG_AAI_SH_SHIFT)); + desc_add_word(desc, U(0x60340000) | len); + desc_add_ptr(desc, phys_addr_out); + + return 0; + +} + +/* Construct descriptor to instantiate RNG */ +int cnstr_rng_instantiate_jobdesc(uint32_t *desc) +{ + desc_init(desc); + desc_add_word(desc, U(0xb0800000)); + /* Class1 Alg Operation,RNG Optype, Instantiate */ + desc_add_word(desc, U(0x82500004)); + /* Wait for done */ + desc_add_word(desc, U(0xa2000001)); + /*Load to clear written */ + desc_add_word(desc, U(0x10880004)); + /*Pri Mode Reg clear */ + desc_add_word(desc, U(0x00000001)); + /* Generate secure keys */ + desc_add_word(desc, U(0x82501000)); + + return 0; +} + +/* Construct descriptor to generate hw key blob */ +int cnstr_hw_encap_blob_jobdesc(uint32_t *desc, + uint8_t *key_idnfr, uint32_t key_sz, + uint32_t key_class, uint8_t *plain_txt, + uint32_t in_sz, uint8_t *enc_blob, + uint32_t out_sz, uint32_t operation) +{ + phys_addr_t *phys_key_idnfr, *phys_addr_in, *phys_addr_out; + int i = 0; + + phys_key_idnfr = vtop((void *)key_idnfr); + phys_addr_in = vtop((void *)plain_txt); + phys_addr_out = vtop((void *)enc_blob); + + desc_init(desc); + + desc_add_word(desc, U(0xb0800000)); + + /* Key Identifier */ + desc_add_word(desc, (key_class | key_sz)); + desc_add_ptr(desc, phys_key_idnfr); + + /* Source Address */ + desc_add_word(desc, U(0xf0400000)); + desc_add_ptr(desc, phys_addr_in); + + /* In Size = 0x10 */ + desc_add_word(desc, in_sz); + + /* Out Address */ + desc_add_word(desc, U(0xf8400000)); + desc_add_ptr(desc, phys_addr_out); + + /* Out Size = 0x10 */ + desc_add_word(desc, out_sz); + + /* Operation */ + desc_add_word(desc, operation); + + for (i = 0; i < 15; i++) + VERBOSE("desc word %x\n", desc[i]); + + return 0; +} + +/*************************************************************************** + * Function : inline_cnstr_jobdesc_pkha_rsaexp + * Arguments : desc - Pointer to Descriptor + * pkin - Pointer to Input Params + * out - Pointer to Output + * out_siz - Output Size + * Return : Void + * Description : Creates the descriptor for PKHA RSA + ***************************************************************************/ +void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, + struct pk_in_params *pkin, uint8_t *out, + uint32_t out_siz) +{ + phys_addr_t *ptr_addr_e, *ptr_addr_a, *ptr_addr_n, *ptr_addr_out; + + ptr_addr_e = vtop((void *)(pkin->e)); + ptr_addr_a = vtop((void *)(pkin->a)); + ptr_addr_n = vtop((void *)(pkin->n)); + ptr_addr_out = vtop((void *)(out)); + + desc_init(desc); + desc_add_word(desc, U(0xb0800000)); + desc_add_word(desc, U(0x02010000) | pkin->e_siz); + desc_add_ptr(desc, ptr_addr_e); + desc_add_word(desc, U(0x220c0000) | pkin->a_siz); + desc_add_ptr(desc, ptr_addr_a); + desc_add_word(desc, U(0x22080000) | pkin->n_siz); + desc_add_ptr(desc, ptr_addr_n); + desc_add_word(desc, U(0x81800006)); + desc_add_word(desc, U(0x620d0000) | out_siz); + desc_add_ptr(desc, ptr_addr_out); +} + +/*************************************************************************** + * Function : inline_cnstr_jobdesc_sha256 + * Arguments : desc - Pointer to Descriptor + * msg - Pointer to SG Table + * msgsz - Size of SG Table + * digest - Pointer to Output Digest + * Return : Void + * Description : Creates the descriptor for SHA256 HASH calculation + ***************************************************************************/ +void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz, + uint8_t *digest) +{ + /* SHA 256 , output is of length 32 words */ + phys_addr_t *ptr_addr_in, *ptr_addr_out; + + ptr_addr_in = (void *)vtop(msg); + ptr_addr_out = (void *)vtop(digest); + + desc_init(desc); + desc_add_word(desc, U(0xb0800000)); + + /* Operation Command + * OP_TYPE_CLASS2_ALG | OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HASH | + * OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT | OP_ALG_ICV_OFF) + */ + desc_add_word(desc, U(0x8443000d)); + + if (msgsz > U(0xffff)) { + desc_add_word(desc, U(0x25540000)); /* FIFO Load */ + desc_add_ptr(desc, ptr_addr_in); /* Pointer to msg */ + desc_add_word(desc, msgsz); /* Size */ + desc_add_word(desc, U(0x54200020)); /* FIFO Store */ + desc_add_ptr(desc, ptr_addr_out); /* Pointer to Result */ + } else { + desc_add_word(desc, U(0x25140000) | msgsz); + desc_add_ptr(desc, ptr_addr_in); + desc_add_word(desc, U(0x54200020)); + desc_add_ptr(desc, ptr_addr_out); + } + +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c new file mode 100644 index 0000000..0b9d87d --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c @@ -0,0 +1,251 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include "jobdesc.h" +#include "sec_hw_specific.h" + + +/* Callback function after Instantiation decsriptor is submitted to SEC */ +static void rng_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("RNG Desc SUCCESS with status %x\n", status); +} + +/* Is the HW RNG instantiated? + * Return code: + * 0 - Not in the instantiated state + * 1 - In the instantiated state + * state_handle - 0 for SH0, 1 for SH1 + */ +static int is_hw_rng_instantiated(uint32_t *state_handle) +{ + int ret_code = 0; + uint32_t rdsta; + + rdsta = sec_in32(get_caam_addr() + RNG_REG_RDSTA_OFFSET); + + /*Check if either of the two state handles has been instantiated */ + if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) { + *state_handle = 0; + ret_code = 1; + } else if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) { + *state_handle = 1; + ret_code = 1; + } + + return ret_code; +} + +/* @brief Kick the TRNG block of the RNG HW Engine + * @param [in] ent_delay Entropy delay to be used + * By default, the TRNG runs for 200 clocks per sample; + * 1200 clocks per sample generates better entropy. + * @retval 0 on success + * @retval -1 on error + */ +static void kick_trng(int ent_delay) +{ + uint32_t val; + + /* put RNG4 into program mode */ + val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET); + val = val | RTMCTL_PRGM; + sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val); + + /* rtsdctl bits 0-15 contain "Entropy Delay, which defines the + * length (in system clocks) of each Entropy sample taken + */ + val = sec_in32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET); + val = (val & ~RTSDCTL_ENT_DLY_MASK) | + (ent_delay << RTSDCTL_ENT_DLY_SHIFT); + sec_out32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET, val); + /* min. freq. count, equal to 1/4 of the entropy sample length */ + sec_out32(get_caam_addr() + RNG_REG_RTFRQMIN_OFFSET, ent_delay >> 2); + /* disable maximum frequency count */ + sec_out32(get_caam_addr() + RNG_REG_RTFRQMAX_OFFSET, RTFRQMAX_DISABLE); + + /* select raw sampling in both entropy shifter + * and statistical checker + */ + val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET); + val = val | RTMCTL_SAMP_MODE_RAW_ES_SC; + sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val); + + /* put RNG4 into run mode */ + val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET); + val = val & ~RTMCTL_PRGM; + sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val); +} + +/* @brief Submit descriptor to instantiate the RNG + * @retval 0 on success + * @retval -1 on error + */ +static int instantiate_rng(void) +{ + int ret = 0; + struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor *jobdesc = &desc; + + jobdesc->arg = NULL; + jobdesc->callback = rng_done; + + /* create the hw_rng descriptor */ + cnstr_rng_instantiate_jobdesc(jobdesc->desc); + + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } + return ret; +} + +/* Generate Random Data using HW RNG + * Parameters: + * uint8_t* add_input - user specified optional input byte array + * uint32_t add_input_len - number of bytes of additional input + * uint8_t* out - user specified output byte array + * uint32_t out_len - number of bytes to store in output byte array + * Return code: + * 0 - SUCCESS + * -1 - ERROR + */ +static int +hw_rng_generate(uint32_t *add_input, uint32_t add_input_len, + uint8_t *out, uint32_t out_len, uint32_t state_handle) +{ + int ret = 0; + struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor *jobdesc = &desc; + + jobdesc->arg = NULL; + jobdesc->callback = rng_done; + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range((uintptr_t)out, out_len); + dmbsy(); +#endif + + /* create the hw_rng descriptor */ + ret = cnstr_rng_jobdesc(jobdesc->desc, state_handle, + add_input, add_input_len, out, out_len); + if (ret != 0) { + ERROR("Descriptor construction failed\n"); + ret = -1; + goto out; + } + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } + +out: + return ret; +} + +/* this function instantiates the rng + * + * Return code: + * 0 - All is well + * <0 - Error occurred somewhere + */ +int hw_rng_instantiate(void) +{ + int ret = 0; + int ent_delay = RTSDCTL_ENT_DLY_MIN; + uint32_t state_handle; + + ret = is_hw_rng_instantiated(&state_handle); + if (ret != 0) { + NOTICE("RNG already instantiated\n"); + return 0; + } + do { + kick_trng(ent_delay); + ent_delay += 400; + /*if instantiate_rng(...) fails, the loop will rerun + *and the kick_trng(...) function will modify the + *upper and lower limits of the entropy sampling + *interval, leading to a sucessful initialization of + */ + ret = instantiate_rng(); + } while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX)); + if (ret != 0) { + ERROR("RNG: Failed to instantiate RNG\n"); + return ret; + } + + NOTICE("RNG: INSTANTIATED\n"); + + /* Enable RDB bit so that RNG works faster */ + // sec_setbits32(&sec->scfgr, SEC_SCFGR_RDBENABLE); + + return ret; +} + +/* Generate random bytes, and stuff them into the bytes buffer + * + * If the HW RNG has not already been instantiated, + * it will be instantiated before data is generated. + * + * Parameters: + * uint8_t* bytes - byte buffer large enough to hold the requested random date + * int byte_len - number of random bytes to generate + * + * Return code: + * 0 - All is well + * ~0 - Error occurred somewhere + */ +int get_rand_bytes_hw(uint8_t *bytes, int byte_len) +{ + int ret_code = 0; + uint32_t state_handle; + + /* If this is the first time this routine is called, + * then the hash_drbg will not already be instantiated. + * Therefore, before generating data, instantiate the hash_drbg + */ + ret_code = is_hw_rng_instantiated(&state_handle); + if (ret_code == 0) { + INFO("Instantiating the HW RNG\n"); + + /* Instantiate the hw RNG */ + ret_code = hw_rng_instantiate(); + if (ret_code != 0) { + ERROR("HW RNG Instantiate failed\n"); + return ret_code; + } + } + /* If HW RNG is still not instantiated, something must have gone wrong, + * it must be in the error state, we will not generate any random data + */ + if (is_hw_rng_instantiated(&state_handle) == 0) { + ERROR("HW RNG is in an Error state, and cannot be used\n"); + return -1; + } + /* Generate a random 256-bit value, as 32 bytes */ + ret_code = hw_rng_generate(0, 0, bytes, byte_len, state_handle); + if (ret_code != 0) { + ERROR("HW RNG Generate failed\n"); + return ret_code; + } + + return ret_code; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c new file mode 100644 index 0000000..92b7762 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c @@ -0,0 +1,635 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include "jobdesc.h" +#include "sec_hw_specific.h" + + +/* Job rings used for communication with SEC HW */ +extern struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS]; + +/* The current state of SEC user space driver */ +extern volatile sec_driver_state_t g_driver_state; + +/* The number of job rings used by SEC user space driver */ +extern int g_job_rings_no; + +/* LOCAL FUNCTIONS */ +static inline void hw_set_input_ring_start_addr(struct jobring_regs *regs, + phys_addr_t *start_addr) +{ +#if defined(CONFIG_PHYS_64BIT) + sec_out32(®s->irba_h, PHYS_ADDR_HI(start_addr)); +#else + sec_out32(®s->irba_h, 0); +#endif + sec_out32(®s->irba_l, PHYS_ADDR_LO(start_addr)); +} + +static inline void hw_set_output_ring_start_addr(struct jobring_regs *regs, + phys_addr_t *start_addr) +{ +#if defined(CONFIG_PHYS_64BIT) + sec_out32(®s->orba_h, PHYS_ADDR_HI(start_addr)); +#else + sec_out32(®s->orba_h, 0); +#endif + sec_out32(®s->orba_l, PHYS_ADDR_LO(start_addr)); +} + +/* ORJR - Output Ring Jobs Removed Register shows how many jobs were + * removed from the Output Ring for processing by software. This is done after + * the software has processed the entries. + */ +static inline void hw_remove_entries(sec_job_ring_t *jr, int num) +{ + struct jobring_regs *regs = + (struct jobring_regs *)jr->register_base_addr; + + sec_out32(®s->orjr, num); +} + +/* IRSA - Input Ring Slots Available register holds the number of entries in + * the Job Ring's input ring. Once a job is enqueued, the value returned is + * decremented by the hardware by the number of jobs enqueued. + */ +static inline int hw_get_available_slots(sec_job_ring_t *jr) +{ + struct jobring_regs *regs = + (struct jobring_regs *)jr->register_base_addr; + + return sec_in32(®s->irsa); +} + +/* ORSFR - Output Ring Slots Full register holds the number of jobs which were + * processed by the SEC and can be retrieved by the software. Once a job has + * been processed by software, the user will call hw_remove_one_entry in order + * to notify the SEC that the entry was processed + */ +static inline int hw_get_no_finished_jobs(sec_job_ring_t *jr) +{ + struct jobring_regs *regs = + (struct jobring_regs *)jr->register_base_addr; + + return sec_in32(®s->orsf); +} + +/* @brief Process Jump Halt Condition related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_jmp_halt_cond_err(union hw_error_code error_code) +{ + ERROR("JMP %x\n", error_code.error_desc.jmp_halt_cond_src.jmp); + ERROR("Descriptor Index: %d\n", + error_code.error_desc.jmp_halt_cond_src.desc_idx); + ERROR(" Condition %x\n", error_code.error_desc.jmp_halt_cond_src.cond); +} + +/* @brief Process DECO related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_deco_err(union hw_error_code error_code) +{ + ERROR("JMP %x\n", error_code.error_desc.deco_src.jmp); + ERROR("Descriptor Index: 0x%x", + error_code.error_desc.deco_src.desc_idx); + + switch (error_code.error_desc.deco_src.desc_err) { + case SEC_HW_ERR_DECO_HFN_THRESHOLD: + WARN(" Descriptor completed but exceeds the Threshold"); + break; + default: + ERROR("Error 0x%04x not implemented", + error_code.error_desc.deco_src.desc_err); + break; + } +} + +/* @brief Process Jump Halt User Status related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_jmp_halt_user_err(union hw_error_code error_code) +{ + WARN(" Not implemented"); +} + +/* @brief Process CCB related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_ccb_err(union hw_error_code hw_error_code) +{ + WARN(" Not implemented"); +} + +/* @brief Process Job Ring related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_jr_err(union hw_error_code hw_error_code) +{ + WARN(" Not implemented"); +} + +/* GLOBAL FUNCTIONS */ + +int hw_reset_job_ring(sec_job_ring_t *job_ring) +{ + int ret = 0; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* First reset the job ring in hw */ + ret = hw_shutdown_job_ring(job_ring); + if (ret != 0) { + ERROR("Failed resetting job ring in hardware"); + return ret; + } + /* In order to have the HW JR in a workable state + *after a reset, I need to re-write the input + * queue size, input start address, output queue + * size and output start address + * Write the JR input queue size to the HW register + */ + sec_out32(®s->irs, SEC_JOB_RING_SIZE); + + /* Write the JR output queue size to the HW register */ + sec_out32(®s->ors, SEC_JOB_RING_SIZE); + + /* Write the JR input queue start address */ + hw_set_input_ring_start_addr(regs, vtop(job_ring->input_ring)); + + /* Write the JR output queue start address */ + hw_set_output_ring_start_addr(regs, vtop(job_ring->output_ring)); + + return 0; +} + +int hw_shutdown_job_ring(sec_job_ring_t *job_ring) +{ + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + unsigned int timeout = SEC_TIMEOUT; + uint32_t tmp = 0U; + + VERBOSE("Resetting Job ring\n"); + + /* + * Mask interrupts since we are going to poll + * for reset completion status + * Also, at POR, interrupts are ENABLED on a JR, thus + * this is the point where I can disable them without + * changing the code logic too much + */ + + jr_disable_irqs(job_ring); + + /* initiate flush (required prior to reset) */ + sec_out32(®s->jrcr, JR_REG_JRCR_VAL_RESET); + + /* dummy read */ + tmp = sec_in32(®s->jrcr); + + do { + tmp = sec_in32(®s->jrint); + } while (((tmp & JRINT_ERR_HALT_MASK) == + JRINT_ERR_HALT_INPROGRESS) && ((--timeout) != 0U)); + + if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE || + timeout == 0U) { + ERROR("Failed to flush hw job ring %x\n %u", tmp, timeout); + /* unmask interrupts */ + if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) { + jr_enable_irqs(job_ring); + } + return -1; + } + /* Initiate reset */ + timeout = SEC_TIMEOUT; + sec_out32(®s->jrcr, JR_REG_JRCR_VAL_RESET); + + do { + tmp = sec_in32(®s->jrcr); + } while (((tmp & JR_REG_JRCR_VAL_RESET) != 0U) && + ((--timeout) != 0U)); + + if (timeout == 0U) { + ERROR("Failed to reset hw job ring\n"); + /* unmask interrupts */ + if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) { + jr_enable_irqs(job_ring); + } + return -1; + } + /* unmask interrupts */ + if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) { + jr_enable_irqs(job_ring); + } + return 0; + +} + +void hw_handle_job_ring_error(sec_job_ring_t *job_ring, uint32_t error_code) +{ + union hw_error_code hw_err_code; + + hw_err_code.error = error_code; + + switch (hw_err_code.error_desc.value.ssrc) { + case SEC_HW_ERR_SSRC_NO_SRC: + INFO("No Status Source "); + break; + case SEC_HW_ERR_SSRC_CCB_ERR: + INFO("CCB Status Source"); + hw_handle_ccb_err(hw_err_code); + break; + case SEC_HW_ERR_SSRC_JMP_HALT_U: + INFO("Jump Halt User Status Source"); + hw_handle_jmp_halt_user_err(hw_err_code); + break; + case SEC_HW_ERR_SSRC_DECO: + INFO("DECO Status Source"); + hw_handle_deco_err(hw_err_code); + break; + case SEC_HW_ERR_SSRC_JR: + INFO("Job Ring Status Source"); + hw_handle_jr_err(hw_err_code); + break; + case SEC_HW_ERR_SSRC_JMP_HALT_COND: + INFO("Jump Halt Condition Codes"); + hw_handle_jmp_halt_cond_err(hw_err_code); + break; + default: + INFO("Unknown SSRC"); + break; + } +} + +int hw_job_ring_error(sec_job_ring_t *job_ring) +{ + uint32_t jrint_error_code; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + if (JR_REG_JRINT_JRE_EXTRACT(sec_in32(®s->jrint)) == 0) { + return 0; + } + + jrint_error_code = + JR_REG_JRINT_ERR_TYPE_EXTRACT(sec_in32(®s->jrint)); + switch (jrint_error_code) { + case JRINT_ERR_WRITE_STATUS: + ERROR("Error writing status to Output Ring "); + break; + case JRINT_ERR_BAD_INPUT_BASE: + ERROR("Bad Input Ring Base (not on a 4-byte boundary)\n"); + break; + case JRINT_ERR_BAD_OUTPUT_BASE: + ERROR("Bad Output Ring Base (not on a 4-byte boundary)\n"); + break; + case JRINT_ERR_WRITE_2_IRBA: + ERROR("Invalid write to Input Ring Base Address Register\n"); + break; + case JRINT_ERR_WRITE_2_ORBA: + ERROR("Invalid write to Output Ring Base Address Register\n"); + break; + case JRINT_ERR_RES_B4_HALT: + ERROR("Job Ring released before Job Ring is halted\n"); + break; + case JRINT_ERR_REM_TOO_MANY: + ERROR("Removed too many jobs from job ring\n"); + break; + case JRINT_ERR_ADD_TOO_MANY: + ERROR("Added too many jobs on job ring\n"); + break; + default: + ERROR("Unknown SEC JR Error :%d\n", jrint_error_code); + break; + } + return jrint_error_code; +} + +int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Set descriptor count coalescing */ + reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT); + + /* Set coalescing timer value */ + reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT); + + /* Update parameters in HW */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Set coalescing params on jr\n"); + + return 0; +} + +int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Get the current value of the register */ + reg_val = sec_in32(®s->jrcfg1); + + /* Enable coalescing */ + reg_val |= JR_REG_JRCFG_LO_ICEN_EN; + + /* Write in hw */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Enabled coalescing on jr\n"); + + return 0; +} + +int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Get the current value of the register */ + reg_val = sec_in32(®s->jrcfg1); + + /* Disable coalescing */ + reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN; + + /* Write in hw */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Disabled coalescing on jr"); + + return 0; + +} + +void hw_flush_job_ring(struct sec_job_ring_t *job_ring, + uint32_t do_notify, + uint32_t error_code, uint32_t *notified_descs) +{ + int32_t jobs_no_to_discard = 0; + int32_t discarded_descs_no = 0; + int32_t number_of_jobs_available = 0; + + VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx); + VERBOSE("error code %x\n", error_code); + VERBOSE("Notify_desc = %d\n", do_notify); + + number_of_jobs_available = hw_get_no_finished_jobs(job_ring); + + /* Discard all jobs */ + jobs_no_to_discard = number_of_jobs_available; + + VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx); + VERBOSE("Discarding desc = %d\n", jobs_no_to_discard); + + while (jobs_no_to_discard > discarded_descs_no) { + discarded_descs_no++; + /* Now increment the consumer index for the current job ring, + * AFTER saving job in temporary location! + * Increment the consumer index for the current job ring + */ + + job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx, + SEC_JOB_RING_SIZE); + + hw_remove_entries(job_ring, 1); + } + + if (do_notify == true) { + if (notified_descs == NULL) { + return; + } + *notified_descs = discarded_descs_no; + } +} + +/* return >0 in case of success + * -1 in case of error from SEC block + * 0 in case job not yet processed by SEC + * or Descriptor returned is NULL after dequeue + */ +int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit) +{ + int32_t jobs_no_to_notify = 0; + int32_t number_of_jobs_available = 0; + int32_t notified_descs_no = 0; + uint32_t error_descs_no = 0U; + uint32_t sec_error_code = 0U; + uint32_t do_driver_shutdown = false; + phys_addr_t *fnptr, *arg_addr; + user_callback usercall = NULL; + uint8_t *current_desc; + void *arg; + uintptr_t current_desc_addr; + phys_addr_t current_desc_loc; + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range((uintptr_t)job_ring->register_base_addr, sizeof(struct jobring_regs)); + dmbsy(); +#endif + + /* check here if any JR error that cannot be written + * in the output status word has occurred + */ + sec_error_code = hw_job_ring_error(job_ring); + if (unlikely(sec_error_code) != 0) { + ERROR("Error here itself %x\n", sec_error_code); + return -1; + } + /* Compute the number of notifications that need to be raised to UA + * If limit < 0 -> notify all done jobs + * If limit > total number of done jobs -> notify all done jobs + * If limit = 0 -> error + * If limit > 0 && limit < total number of done jobs -> notify a number + * of done jobs equal with limit + */ + + /*compute the number of jobs available in the job ring based on the + * producer and consumer index values. + */ + + number_of_jobs_available = hw_get_no_finished_jobs(job_ring); + jobs_no_to_notify = (limit < 0 || limit > number_of_jobs_available) ? + number_of_jobs_available : limit; + VERBOSE("JR - pi %d, ci %d, ", job_ring->pidx, job_ring->cidx); + VERBOSE("Jobs submitted %d", number_of_jobs_available); + VERBOSE("Jobs to notify %d\n", jobs_no_to_notify); + + while (jobs_no_to_notify > notified_descs_no) { + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range( + (uintptr_t)(&job_ring->output_ring[job_ring->cidx]), + sizeof(struct sec_outring_entry)); + dmbsy(); +#endif + + /* Get job status here */ + sec_error_code = + sec_in32(&(job_ring->output_ring[job_ring->cidx].status)); + + /* Get completed descriptor + */ + current_desc_loc = (uintptr_t) + &job_ring->output_ring[job_ring->cidx].desc; + current_desc_addr = sec_read_addr(current_desc_loc); + + current_desc = ptov((phys_addr_t *) current_desc_addr); + if (current_desc == 0) { + ERROR("No descriptor returned from SEC"); + assert(current_desc); + return 0; + } + /* now increment the consumer index for the current job ring, + * AFTER saving job in temporary location! + */ + job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx, + SEC_JOB_RING_SIZE); + + if (sec_error_code != 0) { + ERROR("desc at cidx %d\n ", job_ring->cidx); + ERROR("generated error %x\n", sec_error_code); + + sec_handle_desc_error(job_ring, + sec_error_code, + &error_descs_no, + &do_driver_shutdown); + hw_remove_entries(job_ring, 1); + + return -1; + } + /* Signal that the job has been processed & the slot is free */ + hw_remove_entries(job_ring, 1); + notified_descs_no++; + + arg_addr = (phys_addr_t *) (current_desc + + (MAX_DESC_SIZE_WORDS * sizeof(uint32_t))); + + fnptr = (phys_addr_t *) (current_desc + + (MAX_DESC_SIZE_WORDS * sizeof(uint32_t) + + sizeof(void *))); + + arg = (void *)*(arg_addr); + if (*fnptr != 0) { + VERBOSE("Callback Function called\n"); + usercall = (user_callback) *(fnptr); + (*usercall) ((uint32_t *) current_desc, + sec_error_code, arg, job_ring); + } + } + + return notified_descs_no; +} + +void sec_handle_desc_error(sec_job_ring_t *job_ring, + uint32_t sec_error_code, + uint32_t *notified_descs, + uint32_t *do_driver_shutdown) +{ + /* Analyze the SEC error on this job ring */ + hw_handle_job_ring_error(job_ring, sec_error_code); +} + +void flush_job_rings(void) +{ + struct sec_job_ring_t *job_ring = NULL; + int i = 0; + + for (i = 0; i < g_job_rings_no; i++) { + job_ring = &g_job_rings[i]; + /* Producer index is frozen. If consumer index is not equal + * with producer index, then we have descs to flush. + */ + while (job_ring->pidx != job_ring->cidx) { + hw_flush_job_ring(job_ring, false, 0, /* no error */ + NULL); + } + } +} + +int shutdown_job_ring(struct sec_job_ring_t *job_ring) +{ + int ret = 0; + + ret = hw_shutdown_job_ring(job_ring); + if (ret != 0) { + ERROR("Failed to shutdown hardware job ring\n"); + return ret; + } + + if (job_ring->coalescing_en != 0) { + hw_job_ring_disable_coalescing(job_ring); + } + + if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) { + ret = jr_disable_irqs(job_ring); + if (ret != 0) { + ERROR("Failed to disable irqs for job ring"); + return ret; + } + } + + return 0; +} + +int jr_enable_irqs(struct sec_job_ring_t *job_ring) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Get the current value of the register */ + reg_val = sec_in32(®s->jrcfg1); + + /* Enable interrupts by disabling interrupt masking*/ + reg_val &= ~JR_REG_JRCFG_LO_IMSK_EN; + + /* Update parameters in HW */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Enable interrupts on JR\n"); + + return 0; +} + +int jr_disable_irqs(struct sec_job_ring_t *job_ring) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Get the current value of the register */ + reg_val = sec_in32(®s->jrcfg1); + + /* Disable interrupts by enabling interrupt masking*/ + reg_val |= JR_REG_JRCFG_LO_IMSK_EN; + + /* Update parameters in HW */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Disable interrupts on JR\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c new file mode 100644 index 0000000..1fe7007 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c @@ -0,0 +1,241 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include "jobdesc.h" +#include "nxp_timer.h" +#include "sec_hw_specific.h" +#include "sec_jr_driver.h" + + +/* Job rings used for communication with SEC HW */ +struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS]; + +/* The current state of SEC user space driver */ +volatile sec_driver_state_t g_driver_state = SEC_DRIVER_STATE_IDLE; + +int g_job_rings_no; + +uint8_t ip_ring[SEC_DMA_MEM_INPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE); +uint8_t op_ring[SEC_DMA_MEM_OUTPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE); + +void *init_job_ring(uint8_t jr_mode, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count, + void *reg_base_addr, uint32_t irq_id) +{ + struct sec_job_ring_t *job_ring = &g_job_rings[g_job_rings_no++]; + int ret = 0; + + job_ring->register_base_addr = reg_base_addr; + job_ring->jr_mode = jr_mode; + job_ring->irq_fd = irq_id; + + job_ring->input_ring = vtop(ip_ring); + memset(job_ring->input_ring, 0, SEC_DMA_MEM_INPUT_RING_SIZE); + + job_ring->output_ring = (struct sec_outring_entry *)vtop(op_ring); + memset(job_ring->output_ring, 0, SEC_DMA_MEM_OUTPUT_RING_SIZE); + + dsb(); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)(job_ring->input_ring), + SEC_DMA_MEM_INPUT_RING_SIZE), + flush_dcache_range((uintptr_t)(job_ring->output_ring), + SEC_DMA_MEM_OUTPUT_RING_SIZE), + + dmbsy(); +#endif + /* Reset job ring in SEC hw and configure job ring registers */ + ret = hw_reset_job_ring(job_ring); + if (ret != 0) { + ERROR("Failed to reset hardware job ring\n"); + return NULL; + } + + if (jr_mode == SEC_NOTIFICATION_TYPE_IRQ) { + /* Enable IRQ if driver work sin interrupt mode */ + ERROR("Enabling DONE IRQ generation on job ring\n"); + ret = jr_enable_irqs(job_ring); + if (ret != 0) { + ERROR("Failed to enable irqs for job ring\n"); + return NULL; + } + } + if ((irq_coalescing_timer != 0) || (irq_coalescing_count != 0)) { + hw_job_ring_set_coalescing_param(job_ring, + irq_coalescing_timer, + irq_coalescing_count); + + hw_job_ring_enable_coalescing(job_ring); + job_ring->coalescing_en = 1; + } + + job_ring->jr_state = SEC_JOB_RING_STATE_STARTED; + + return job_ring; +} + +int sec_release(void) +{ + int i; + + /* Validate driver state */ + if (g_driver_state == SEC_DRIVER_STATE_RELEASE) { + ERROR("Driver release is already in progress"); + return SEC_DRIVER_RELEASE_IN_PROGRESS; + } + /* Update driver state */ + g_driver_state = SEC_DRIVER_STATE_RELEASE; + + /* If any descriptors in flight , poll and wait + * until all descriptors are received and silently discarded. + */ + + flush_job_rings(); + + for (i = 0; i < g_job_rings_no; i++) { + shutdown_job_ring(&g_job_rings[i]); + } + g_job_rings_no = 0; + g_driver_state = SEC_DRIVER_STATE_IDLE; + + return SEC_SUCCESS; +} + +int sec_jr_lib_init(void) +{ + /* Validate driver state */ + if (g_driver_state != SEC_DRIVER_STATE_IDLE) { + ERROR("Driver already initialized\n"); + return 0; + } + + memset(g_job_rings, 0, sizeof(g_job_rings)); + g_job_rings_no = 0; + + /* Update driver state */ + g_driver_state = SEC_DRIVER_STATE_STARTED; + return 0; +} + +int dequeue_jr(void *job_ring_handle, int32_t limit) +{ + int ret = 0; + int notified_descs_no = 0; + struct sec_job_ring_t *job_ring = (sec_job_ring_t *) job_ring_handle; + uint64_t start_time; + + /* Validate driver state */ + if (g_driver_state != SEC_DRIVER_STATE_STARTED) { + ERROR("Driver release in progress or driver not initialized\n"); + return -1; + } + + /* Validate input arguments */ + if (job_ring == NULL) { + ERROR("job_ring_handle is NULL\n"); + return -1; + } + if (((limit == 0) || (limit > SEC_JOB_RING_SIZE))) { + ERROR("Invalid limit parameter configuration\n"); + return -1; + } + + VERBOSE("JR Polling limit[%d]\n", limit); + + /* Poll job ring + * If limit < 0 -> poll JR until no more notifications are available. + * If limit > 0 -> poll JR until limit is reached. + */ + + start_time = get_timer_val(0); + + while (notified_descs_no == 0) { + /* Run hw poll job ring */ + notified_descs_no = hw_poll_job_ring(job_ring, limit); + if (notified_descs_no < 0) { + ERROR("Error polling SEC engine job ring "); + return notified_descs_no; + } + VERBOSE("Jobs notified[%d]. ", notified_descs_no); + + if (get_timer_val(start_time) >= CAAM_TIMEOUT) { + break; + } + } + + if (job_ring->jr_mode == SEC_NOTIFICATION_TYPE_IRQ) { + + /* Always enable IRQ generation when in pure IRQ mode */ + ret = jr_enable_irqs(job_ring); + if (ret != 0) { + ERROR("Failed to enable irqs for job ring"); + return ret; + } + } + return notified_descs_no; +} + +int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr) +{ + struct sec_job_ring_t *job_ring; + + job_ring = (struct sec_job_ring_t *)job_ring_handle; + + /* Validate driver state */ + if (g_driver_state != SEC_DRIVER_STATE_STARTED) { + ERROR("Driver release in progress or driver not initialized\n"); + return -1; + } + + /* Check job ring state */ + if (job_ring->jr_state != SEC_JOB_RING_STATE_STARTED) { + ERROR("Job ring is currently resetting\n"); + return -1; + } + + if (SEC_JOB_RING_IS_FULL(job_ring->pidx, job_ring->cidx, + SEC_JOB_RING_SIZE, SEC_JOB_RING_SIZE)) { + ERROR("Job ring is full\n"); + return -1; + } + + /* Set ptr in input ring to current descriptor */ + sec_write_addr(&job_ring->input_ring[job_ring->pidx], + (phys_addr_t) vtop(jobdescr->desc)); + + dsb(); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)(&job_ring->input_ring[job_ring->pidx]), + sizeof(phys_addr_t)); + + inv_dcache_range((uintptr_t)(&job_ring->output_ring[job_ring->cidx]), + sizeof(struct sec_outring_entry)); + dmbsy(); +#endif + /* Notify HW that a new job is enqueued */ + hw_enqueue_desc_on_job_ring( + (struct jobring_regs *)job_ring->register_base_addr, 1); + + /* increment the producer index for the current job ring */ + job_ring->pidx = SEC_CIRCULAR_COUNTER(job_ring->pidx, + SEC_JOB_RING_SIZE); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/csu/csu.c b/arm-trusted-firmware/drivers/nxp/csu/csu.c new file mode 100644 index 0000000..9f90fe0 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/csu/csu.c @@ -0,0 +1,34 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include + +void enable_layerscape_ns_access(struct csu_ns_dev_st *csu_ns_dev, + uint32_t num, uintptr_t nxp_csu_addr) +{ + uint32_t *base = (uint32_t *)nxp_csu_addr; + uint32_t *reg; + uint32_t val; + int i; + + for (i = 0; i < num; i++) { + reg = base + csu_ns_dev[i].ind / 2U; + val = be32toh(mmio_read_32((uintptr_t)reg)); + if (csu_ns_dev[i].ind % 2U == 0U) { + val &= 0x0000ffffU; + val |= csu_ns_dev[i].val << 16U; + } else { + val &= 0xffff0000U; + val |= csu_ns_dev[i].val; + } + mmio_write_32((uintptr_t)reg, htobe32(val)); + } +} diff --git a/arm-trusted-firmware/drivers/nxp/csu/csu.mk b/arm-trusted-firmware/drivers/nxp/csu/csu.mk new file mode 100644 index 0000000..bc16035 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/csu/csu.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${CSU_ADDED},) + +CSU_ADDED := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/csu + +CSU_SOURCES += $(PLAT_DRIVERS_PATH)/csu/csu.c + +ifeq (${BL_COMM_CSU_NEEDED},yes) +BL_COMMON_SOURCES += ${CSU_SOURCES} +else +ifeq (${BL2_CSU_NEEDED},yes) +BL2_SOURCES += ${CSU_SOURCES} +endif +ifeq (${BL31_CSU_NEEDED},yes) +BL31_SOURCES += ${CSU_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c b/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c new file mode 100644 index 0000000..e5c4db4 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c @@ -0,0 +1,156 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "dcfg.h" +#include +#ifdef NXP_SFP_ENABLED +#include +#endif + +static soc_info_t soc_info = {0}; +static devdisr5_info_t devdisr5_info = {0}; +static dcfg_init_info_t *dcfg_init_info; + +/* Read the PORSR1 register */ +uint32_t read_reg_porsr1(void) +{ + unsigned int *porsr1_addr = NULL; + + if (dcfg_init_info->porsr1 != 0U) { + return dcfg_init_info->porsr1; + } + + porsr1_addr = (void *) + (dcfg_init_info->g_nxp_dcfg_addr + DCFG_PORSR1_OFFSET); + dcfg_init_info->porsr1 = gur_in32(porsr1_addr); + + return dcfg_init_info->porsr1; +} + + +const soc_info_t *get_soc_info(void) +{ + uint32_t reg; + + if (soc_info.is_populated == true) { + return (const soc_info_t *) &soc_info; + } + + reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_SVR_OFFSET); + + soc_info.svr_reg.val = reg; + + /* zero means SEC enabled. */ + soc_info.sec_enabled = + (((reg & SVR_SEC_MASK) >> SVR_SEC_SHIFT) == 0) ? true : false; + + soc_info.is_populated = true; + return (const soc_info_t *) &soc_info; +} + +void dcfg_init(dcfg_init_info_t *dcfg_init_data) +{ + dcfg_init_info = dcfg_init_data; + read_reg_porsr1(); + get_soc_info(); +} + +bool is_sec_enabled(void) +{ + return soc_info.sec_enabled; +} + +const devdisr5_info_t *get_devdisr5_info(void) +{ + uint32_t reg; + + if (devdisr5_info.is_populated == true) + return (const devdisr5_info_t *) &devdisr5_info; + + reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_DEVDISR5_OFFSET); + + devdisr5_info.ddrc1_present = (reg & DISR5_DDRC1_MASK) ? 0 : 1; +#if defined(CONFIG_CHASSIS_3_2) + devdisr5_info.ddrc2_present = (reg & DISR5_DDRC2_MASK) ? 0 : 1; +#endif + devdisr5_info.ocram_present = (reg & DISR5_OCRAM_MASK) ? 0 : 1; + devdisr5_info.is_populated = true; + + return (const devdisr5_info_t *) &devdisr5_info; +} + +int get_clocks(struct sysinfo *sys) +{ + unsigned int *rcwsr0 = NULL; + const unsigned long sysclk = dcfg_init_info->nxp_sysclk_freq; + const unsigned long ddrclk = dcfg_init_info->nxp_ddrclk_freq; + + rcwsr0 = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR0_OFFSET); + sys->freq_platform = sysclk; + sys->freq_ddr_pll0 = ddrclk; + sys->freq_ddr_pll1 = ddrclk; + + sys->freq_platform *= (gur_in32(rcwsr0) >> + RCWSR0_SYS_PLL_RAT_SHIFT) & + RCWSR0_SYS_PLL_RAT_MASK; + + sys->freq_platform /= dcfg_init_info->nxp_plat_clk_divider; + + sys->freq_ddr_pll0 *= (gur_in32(rcwsr0) >> + RCWSR0_MEM_PLL_RAT_SHIFT) & + RCWSR0_MEM_PLL_RAT_MASK; + sys->freq_ddr_pll1 *= (gur_in32(rcwsr0) >> + RCWSR0_MEM2_PLL_RAT_SHIFT) & + RCWSR0_MEM2_PLL_RAT_MASK; + if (sys->freq_platform == 0) { + return 1; + } else { + return 0; + } +} + +#ifdef NXP_SFP_ENABLED +/******************************************************************************* + * Returns true if secur eboot is enabled on board + * mode = 0 (development mode - sb_en = 1) + * mode = 1 (production mode - ITS = 1) + ******************************************************************************/ +bool check_boot_mode_secure(uint32_t *mode) +{ + uint32_t val = 0U; + uint32_t *rcwsr = NULL; + *mode = 0U; + + if (sfp_check_its() == 1) { + /* ITS =1 , Production mode */ + *mode = 1U; + return true; + } + + rcwsr = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR_SB_EN_OFFSET); + + val = (gur_in32(rcwsr) >> RCWSR_SBEN_SHIFT) & + RCWSR_SBEN_MASK; + + if (val == RCWSR_SBEN_MASK) { + *mode = 0U; + return true; + } + + return false; +} +#endif + +void error_handler(int error_code) +{ + /* Dump error code in SCRATCH4 register */ + INFO("Error in Fuse Provisioning: %x\n", error_code); + gur_out32((void *) + (dcfg_init_info->g_nxp_dcfg_addr + DCFG_SCRATCH4_OFFSET), + error_code); +} diff --git a/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.mk b/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.mk new file mode 100644 index 0000000..206595f --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_DCFG},) + +ADD_DCFG := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/dcfg + +DCFG_SOURCES += $(PLAT_DRIVERS_PATH)/dcfg/dcfg.c + +ifeq (${BL_COMM_DCFG_NEEDED},yes) +BL_COMMON_SOURCES += ${DCFG_SOURCES} +else +ifeq (${BL2_DCFG_NEEDED},yes) +BL2_SOURCES += ${DCFG_SOURCES} +endif +ifeq (${BL31_DCFG_NEEDED},yes) +BL31_SOURCES += ${DCFG_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/ddr.mk b/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/ddr.mk new file mode 100644 index 0000000..afccb62 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/ddr.mk @@ -0,0 +1,19 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- + +# MMDC ddr cntlr driver files + +DDR_DRIVERS_PATH := drivers/nxp/ddr + +DDR_CNTLR_SOURCES := ${PLAT_DRIVERS_PATH}/ddr/fsl-mmdc/fsl_mmdc.c \ + ${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/utility.c \ + ${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/ddr.c \ + ${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/ddrc.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr \ + -I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr/fsl-mmdc +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c b/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c new file mode 100644 index 0000000..7e6504e --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c @@ -0,0 +1,176 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* + * Generic driver for Freescale MMDC(Multi Mode DDR Controller). + */ + +#include +#include +#include +#include +#include + +#include +#include "ddr_io.h" +#include +#include + +static void set_wait_for_bits_clear(void *ptr, unsigned int value, + unsigned int bits) +{ + int timeout = 1000; + + ddr_out32(ptr, value); + + while ((ddr_in32(ptr) & bits) != 0) { + udelay(100); + timeout--; + } + if (timeout <= 0) { + INFO("Error: %llx", (unsigned long long)ptr); + INFO(" wait for clear timeout.\n"); + } +} + +void mmdc_init(const struct fsl_mmdc_info *priv, uintptr_t nxp_ddr_addr) +{ + struct mmdc_regs *mmdc = (struct mmdc_regs *)nxp_ddr_addr; + unsigned int tmp; + + /* 1. set configuration request */ + ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ); + + /* 2. configure the desired timing parameters */ + ddr_out32(&mmdc->mdotc, priv->mdotc); + ddr_out32(&mmdc->mdcfg0, priv->mdcfg0); + ddr_out32(&mmdc->mdcfg1, priv->mdcfg1); + ddr_out32(&mmdc->mdcfg2, priv->mdcfg2); + + /* 3. configure DDR type and other miscellaneous parameters */ + ddr_out32(&mmdc->mdmisc, priv->mdmisc); + ddr_out32(&mmdc->mpmur0, MMDC_MPMUR0_FRC_MSR); + ddr_out32(&mmdc->mdrwd, priv->mdrwd); + ddr_out32(&mmdc->mpodtctrl, priv->mpodtctrl); + + /* 4. configure the required delay while leaving reset */ + ddr_out32(&mmdc->mdor, priv->mdor); + + /* 5. configure DDR physical parameters */ + /* set row/column address width, burst length, data bus width */ + tmp = priv->mdctl & ~(MDCTL_SDE0 | MDCTL_SDE1); + ddr_out32(&mmdc->mdctl, tmp); + /* configure address space partition */ + ddr_out32(&mmdc->mdasp, priv->mdasp); + + /* 6. perform a ZQ calibration - not needed here, doing in #8b */ + + /* 7. enable MMDC with the desired chip select */ +#if (DDRC_NUM_CS == 1) + ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0); +#elif (DDRC_NUM_CS == 2) + ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0 | MDCTL_SDE1); +#else +#error "Unsupported DDRC_NUM_CS" +#endif + + /* 8a. dram init sequence: update MRs for ZQ, ODT, PRE, etc */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(8) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_2); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_3); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_1); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x19) | + CMD_ADDR_LSB_MR_ADDR(0x30) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0); + + /* 8b. ZQ calibration */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x4) | + MDSCR_ENABLE_CON_REQ | + CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0); + + set_wait_for_bits_clear(&mmdc->mpzqhwctrl, priv->mpzqhwctrl, + MPZQHWCTRL_ZQ_HW_FORCE); + + /* 9a. calibrations now, wr lvl */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0x84) | MDSCR_WL_EN | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1); + + set_wait_for_bits_clear(&mmdc->mpwlgcr, MPWLGCR_HW_WL_EN, + MPWLGCR_HW_WL_EN); + + mdelay(1); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1); + + ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ); + + mdelay(1); + + /* 9b. read DQS gating calibration */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ | + CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3); + + ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN); + + /* set absolute read delay offset */ + if (priv->mprddlctl != 0) { + ddr_out32(&mmdc->mprddlctl, priv->mprddlctl); + } else { + ddr_out32(&mmdc->mprddlctl, MMDC_MPRDDLCTL_DEFAULT_DELAY); + } + + set_wait_for_bits_clear(&mmdc->mpdgctrl0, + AUTO_RD_DQS_GATING_CALIBRATION_EN, + AUTO_RD_DQS_GATING_CALIBRATION_EN); + + ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_3); + + /* 9c. read calibration */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ | + CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0); + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3); + ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN); + set_wait_for_bits_clear(&mmdc->mprddlhwctl, + MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN, + MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN); + + ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_3); + + /* 10. configure power-down, self-refresh entry, exit parameters */ + ddr_out32(&mmdc->mdpdc, priv->mdpdc); + ddr_out32(&mmdc->mapsr, MMDC_MAPSR_PWR_SAV_CTRL_STAT); + + /* 11. ZQ config again? do nothing here */ + + /* 12. refresh scheme */ + set_wait_for_bits_clear(&mmdc->mdref, priv->mdref, + MDREF_START_REFRESH); + + /* 13. disable CON_REQ */ + ddr_out32(&mmdc->mdscr, MDSCR_DISABLE_CFG_REQ); +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt new file mode 100644 index 0000000..8796302 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt @@ -0,0 +1,31 @@ +Table for dynamic ODT for DDR4 with PHY generation 2 +==================================================== +Two-slot system +Only symmetric configurations are supported for interleaving. Non-symmetric +configurations are possible but not covered here. First slot empty is possbile +but prohibited for simplicity. ++-----------------------+-------------+---------------+-----------------------------+-----------------------------+ +| Configuration | |DRAM controller| Slot 1 | Slot 2 | ++-----------+-----------+-------------+-------+-------+--------------+--------------+--------------+--------------+ +| | | | | | Rank 1 | Rank 2 | Rank 1 | Rank 2 | +| Slot 1 | Slot 2 | Write/Read | Write | Read |-------+------+-------+------+-------+------+-------+------+ +| | | | | | Write | Read | Write | Read | Write | Read | Write | Read | ++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | |Rank 1| off | 60 | 240 | off | 60 | 240 | 60 | 60 | 60 | 60 | +| | |Slot 1|------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | |Rank 2| off | 60 | 60 | 240 | 240 | off | 60 | 60 | 60 | 60 | +| Dual Rank | Dual Rank |------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | |Rank 1| off | 60 | 60 | 60 | 60 | 60 | 240 | off | 60 | 240 | +| | |Slot 2|------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | |Rank 2| off | 60 | 60 | 60 | 60 | 60 | 60 | 240 | 240 | off | ++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | Slot 1 | off | 60 | 80 | off | | | | | | | +|Single Rank|Single Rank|-------------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | Slot 2 | off | 60 | | | | | 80 | off | ++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+ +| | | |Rank 1| off | 80 | 80 | off | off | off | +| Dual Rank | |Slot 1|------+-------+-------+-------+------+-------+------+ +| | | |Rank 2| off | 80 | 80 | off | off | off | ++-----------+-----------+-------------+-------+-------+-------+------+-------+------+ +|Single Rank| | Slot 1 | off | 80 | 80 | off | ++-----------+-----------+-------------+-------+-------+-------+------+ diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c new file mode 100644 index 0000000..c051b3b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c @@ -0,0 +1,931 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#ifndef CONFIG_DDR_NODIMM +#include +#endif +#include + +struct dynamic_odt { + unsigned int odt_rd_cfg; + unsigned int odt_wr_cfg; + unsigned int odt_rtt_norm; + unsigned int odt_rtt_wr; +}; + +#ifndef CONFIG_STATIC_DDR +#if defined(PHY_GEN2_FW_IMAGE_BUFFER) && !defined(NXP_DDR_PHY_GEN2) +#error Missing NXP_DDR_PHY_GEN2 +#endif +#ifdef NXP_DDR_PHY_GEN2 +static const struct dynamic_odt single_D[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_NEVER, + DDR_ODT_NEVER, + DDR4_RTT_OFF, + DDR4_RTT_WR_OFF + }, + {}, + {} +}; + +static const struct dynamic_odt single_S[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {}, + {}, +}; + +static const struct dynamic_odt dual_DD[4] = { + { /* cs0 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_60_OHM, + DDR4_RTT_WR_240_OHM + }, + { /* cs1 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_60_OHM, + DDR4_RTT_WR_240_OHM + }, + { /* cs2 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_60_OHM, + DDR4_RTT_WR_240_OHM + }, + { /* cs3 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_60_OHM, + DDR4_RTT_WR_240_OHM + } +}; + +static const struct dynamic_odt dual_SS[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {}, + { /* cs2 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {} +}; + +static const struct dynamic_odt dual_D0[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_SAME_DIMM, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_NEVER, + DDR_ODT_NEVER, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {} +}; + +static const struct dynamic_odt dual_S0[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_CS, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {}, + {} +}; +#else +static const struct dynamic_odt single_D[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_40_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_NEVER, + DDR_ODT_NEVER, + DDR4_RTT_OFF, + DDR4_RTT_WR_OFF + }, + {}, + {} +}; + +static const struct dynamic_odt single_S[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_40_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {}, + {}, +}; + +static const struct dynamic_odt dual_DD[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_SAME_DIMM, + DDR4_RTT_120_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_OTHER_DIMM, + DDR4_RTT_34_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs2 */ + DDR_ODT_NEVER, + DDR_ODT_SAME_DIMM, + DDR4_RTT_120_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs3 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_OTHER_DIMM, + DDR4_RTT_34_OHM, + DDR4_RTT_WR_OFF + } +}; + +static const struct dynamic_odt dual_SS[4] = { + { /* cs0 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_34_OHM, + DDR4_RTT_WR_120_OHM + }, + {}, + { /* cs2 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_34_OHM, + DDR4_RTT_WR_120_OHM + }, + {} +}; + +static const struct dynamic_odt dual_D0[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_SAME_DIMM, + DDR4_RTT_40_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_NEVER, + DDR_ODT_NEVER, + DDR4_RTT_OFF, + DDR4_RTT_WR_OFF + }, + {}, + {} +}; + +static const struct dynamic_odt dual_S0[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_CS, + DDR4_RTT_40_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {}, + {} +}; +#endif /* NXP_DDR_PHY_GEN2 */ + +/* + * Automatically select bank interleaving mode based on DIMMs + * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null. + * This function only deal with one or two slots per controller. + */ +static inline unsigned int auto_bank_intlv(const int cs_in_use, + const struct dimm_params *pdimm) +{ + switch (cs_in_use) { + case 0xf: + return DDR_BA_INTLV_CS0123; + case 0x3: + return DDR_BA_INTLV_CS01; + case 0x1: + return DDR_BA_NONE; + case 0x5: + return DDR_BA_NONE; + default: + break; + } + + return 0U; +} + +static int cal_odt(const unsigned int clk, + struct memctl_opt *popts, + struct ddr_conf *conf, + struct dimm_params *pdimm, + const int dimm_slot_per_ctrl) + +{ + unsigned int i; + const struct dynamic_odt *pdodt = NULL; + + const static struct dynamic_odt *table[2][5] = { + {single_S, single_D, NULL, NULL}, + {dual_SS, dual_DD, NULL, NULL}, + }; + + if (dimm_slot_per_ctrl != 1 && dimm_slot_per_ctrl != 2) { + ERROR("Unsupported number of DIMMs\n"); + return -EINVAL; + } + + pdodt = table[dimm_slot_per_ctrl - 1][pdimm->n_ranks - 1]; + if (pdodt == dual_SS) { + pdodt = (conf->cs_in_use == 0x5) ? dual_SS : + ((conf->cs_in_use == 0x1) ? dual_S0 : NULL); + } else if (pdodt == dual_DD) { + pdodt = (conf->cs_in_use == 0xf) ? dual_DD : + ((conf->cs_in_use == 0x3) ? dual_D0 : NULL); + } + if (pdodt == dual_DD && pdimm->package_3ds) { + ERROR("Too many 3DS DIMMs.\n"); + return -EINVAL; + } + + if (pdodt == NULL) { + ERROR("Error determing ODT.\n"); + return -EINVAL; + } + + /* Pick chip-select local options. */ + for (i = 0U; i < DDRC_NUM_CS; i++) { + debug("cs %d\n", i); + popts->cs_odt[i].odt_rd_cfg = pdodt[i].odt_rd_cfg; + debug(" odt_rd_cfg 0x%x\n", + popts->cs_odt[i].odt_rd_cfg); + popts->cs_odt[i].odt_wr_cfg = pdodt[i].odt_wr_cfg; + debug(" odt_wr_cfg 0x%x\n", + popts->cs_odt[i].odt_wr_cfg); + popts->cs_odt[i].odt_rtt_norm = pdodt[i].odt_rtt_norm; + debug(" odt_rtt_norm 0x%x\n", + popts->cs_odt[i].odt_rtt_norm); + popts->cs_odt[i].odt_rtt_wr = pdodt[i].odt_rtt_wr; + debug(" odt_rtt_wr 0x%x\n", + popts->cs_odt[i].odt_rtt_wr); + popts->cs_odt[i].auto_precharge = 0; + debug(" auto_precharge %d\n", + popts->cs_odt[i].auto_precharge); + } + + return 0; +} + +static int cal_opts(const unsigned int clk, + struct memctl_opt *popts, + struct ddr_conf *conf, + struct dimm_params *pdimm, + const int dimm_slot_per_ctrl, + const unsigned int ip_rev) +{ + popts->rdimm = pdimm->rdimm; + popts->mirrored_dimm = pdimm->mirrored_dimm; +#ifdef CONFIG_DDR_ECC_EN + popts->ecc_mode = pdimm->edc_config == 0x02 ? 1 : 0; +#endif + popts->ctlr_init_ecc = popts->ecc_mode; + debug("ctlr_init_ecc %d\n", popts->ctlr_init_ecc); + popts->self_refresh_in_sleep = 1; + popts->dynamic_power = 0; + + /* + * check sdram width, allow platform override + * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit + */ + if (pdimm->primary_sdram_width == 64) { + popts->data_bus_dimm = DDR_DBUS_64; + popts->otf_burst_chop_en = 1; + } else if (pdimm->primary_sdram_width == 32) { + popts->data_bus_dimm = DDR_DBUS_32; + popts->otf_burst_chop_en = 0; + } else if (pdimm->primary_sdram_width == 16) { + popts->data_bus_dimm = DDR_DBUS_16; + popts->otf_burst_chop_en = 0; + } else { + ERROR("primary sdram width invalid!\n"); + return -EINVAL; + } + popts->data_bus_used = popts->data_bus_dimm; + popts->x4_en = (pdimm->device_width == 4) ? 1 : 0; + debug("x4_en %d\n", popts->x4_en); + + /* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */ + if (popts->rdimm != 0) { + popts->ap_en = 1; /* 0 = disable, 1 = enable */ + } else { + popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */ + } + + if (ip_rev == 0x50500) { + popts->ap_en = 0; + } + + debug("ap_en %d\n", popts->ap_en); + + /* BSTTOPRE precharge interval uses 1/4 of refint value. */ + popts->bstopre = picos_to_mclk(clk, pdimm->refresh_rate_ps) >> 2; + popts->tfaw_ps = pdimm->tfaw_ps; + + return 0; +} + +static void cal_intlv(const int num_ctlrs, + struct memctl_opt *popts, + struct ddr_conf *conf, + struct dimm_params *pdimm) +{ +#ifdef NXP_DDR_INTLV_256B + if (num_ctlrs == 2) { + popts->ctlr_intlv = 1; + popts->ctlr_intlv_mode = DDR_256B_INTLV; + } +#endif + debug("ctlr_intlv %d\n", popts->ctlr_intlv); + debug("ctlr_intlv_mode %d\n", popts->ctlr_intlv_mode); + + popts->ba_intlv = auto_bank_intlv(conf->cs_in_use, pdimm); + debug("ba_intlv 0x%x\n", popts->ba_intlv); +} + +static int update_burst_length(struct memctl_opt *popts) +{ + /* Choose burst length. */ + if ((popts->data_bus_used == DDR_DBUS_32) || + (popts->data_bus_used == DDR_DBUS_16)) { + /* 32-bit or 16-bit bus */ + popts->otf_burst_chop_en = 0; + popts->burst_length = DDR_BL8; + } else if (popts->otf_burst_chop_en != 0) { /* on-the-fly burst chop */ + popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */ + } else { + popts->burst_length = DDR_BL8; + } + debug("data_bus_used %d\n", popts->data_bus_used); + debug("otf_burst_chop_en %d\n", popts->otf_burst_chop_en); + debug("burst_length 0x%x\n", popts->burst_length); + /* + * If a reduced data width is requested, but the SPD + * specifies a physically wider device, adjust the + * computed dimm capacities accordingly before + * assigning addresses. + * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit + */ + if (popts->data_bus_dimm > popts->data_bus_used) { + ERROR("Data bus configuration error\n"); + return -EINVAL; + } + popts->dbw_cap_shift = popts->data_bus_used - popts->data_bus_dimm; + debug("dbw_cap_shift %d\n", popts->dbw_cap_shift); + + return 0; +} + +int cal_board_params(struct ddr_info *priv, + const struct board_timing *dimm, + int len) +{ + const unsigned long speed = priv->clk / 1000000; + const struct dimm_params *pdimm = &priv->dimm; + struct memctl_opt *popts = &priv->opt; + struct rc_timing const *prt = NULL; + struct rc_timing const *chosen = NULL; + int i; + + for (i = 0; i < len; i++) { + if (pdimm->rc == dimm[i].rc) { + prt = dimm[i].p; + break; + } + } + if (prt == NULL) { + ERROR("Board parameters no match.\n"); + return -EINVAL; + } + while (prt->speed_bin != 0) { + if (speed <= prt->speed_bin) { + chosen = prt; + break; + } + prt++; + } + if (chosen == NULL) { + ERROR("timing no match for speed %lu\n", speed); + return -EINVAL; + } + popts->clk_adj = prt->clk_adj; + popts->wrlvl_start = prt->wrlvl; + popts->wrlvl_ctl_2 = (prt->wrlvl * 0x01010101 + dimm[i].add1) & + 0xFFFFFFFF; + popts->wrlvl_ctl_3 = (prt->wrlvl * 0x01010101 + dimm[i].add2) & + 0xFFFFFFFF; + + return 0; +} + +static int synthesize_ctlr(struct ddr_info *priv) +{ + int ret; + + ret = cal_odt(priv->clk, + &priv->opt, + &priv->conf, + &priv->dimm, + priv->dimm_on_ctlr); + if (ret != 0) { + return ret; + } + + ret = cal_opts(priv->clk, + &priv->opt, + &priv->conf, + &priv->dimm, + priv->dimm_on_ctlr, + priv->ip_rev); + + if (ret != 0) { + return ret; + } + + cal_intlv(priv->num_ctlrs, &priv->opt, &priv->conf, &priv->dimm); + ret = ddr_board_options(priv); + if (ret != 0) { + ERROR("Failed matching board timing.\n"); + } + + ret = update_burst_length(&priv->opt); + + return ret; +} + +/* Return the bit mask of valid DIMMs found */ +static int parse_spd(struct ddr_info *priv) +{ + struct ddr_conf *conf = &priv->conf; + struct dimm_params *dimm = &priv->dimm; + int j, valid_mask = 0; + +#ifdef CONFIG_DDR_NODIMM + valid_mask = ddr_get_ddr_params(dimm, conf); + if (valid_mask < 0) { + ERROR("DDR params error\n"); + return valid_mask; + } +#else + const int *spd_addr = priv->spd_addr; + const int num_ctlrs = priv->num_ctlrs; + const int num_dimm = priv->dimm_on_ctlr; + struct ddr4_spd spd[2]; + unsigned int spd_checksum[2]; + int addr_idx = 0; + int spd_idx = 0; + int ret, addr, i; + + /* Scan all DIMMs */ + for (i = 0; i < num_ctlrs; i++) { + debug("Controller %d\n", i); + for (j = 0; j < num_dimm; j++, addr_idx++) { + debug("DIMM %d\n", j); + addr = spd_addr[addr_idx]; + if (addr == 0) { + if (j == 0) { + ERROR("First SPD addr wrong.\n"); + return -EINVAL; + } + continue; + } + debug("addr 0x%x\n", addr); + ret = read_spd(addr, &spd[spd_idx], + sizeof(struct ddr4_spd)); + if (ret != 0) { /* invalid */ + debug("Invalid SPD at address 0x%x\n", addr); + continue; + } + + spd_checksum[spd_idx] = + (spd[spd_idx].crc[1] << 24) | + (spd[spd_idx].crc[0] << 16) | + (spd[spd_idx].mod_section.uc[127] << 8) | + (spd[spd_idx].mod_section.uc[126] << 0); + debug("checksum 0x%x\n", spd_checksum[spd_idx]); + if (spd_checksum[spd_idx] == 0) { + debug("Bad checksum, ignored.\n"); + continue; + } + if (spd_idx == 0) { + /* first valid SPD */ + ret = cal_dimm_params(&spd[0], dimm); + if (ret != 0) { + ERROR("SPD calculation error\n"); + return -EINVAL; + } + } + + if (spd_idx != 0 && spd_checksum[0] != + spd_checksum[spd_idx]) { + ERROR("Not identical DIMMs.\n"); + return -EINVAL; + } + conf->dimm_in_use[j] = 1; + valid_mask |= 1 << addr_idx; + spd_idx = 1; + } + debug("done with controller %d\n", i); + } + switch (num_ctlrs) { + case 1: + if ((valid_mask & 0x1) == 0) { + ERROR("First slot cannot be empty.\n"); + return -EINVAL; + } + break; + case 2: + switch (num_dimm) { + case 1: + if (valid_mask == 0) { + ERROR("Both slot empty\n"); + return -EINVAL; + } + break; + case 2: + if (valid_mask != 0x5 && + valid_mask != 0xf && + (valid_mask & 0x7) != 0x4 && + (valid_mask & 0xd) != 0x1) { + ERROR("Invalid DIMM combination.\n"); + return -EINVAL; + } + break; + default: + ERROR("Invalid number of DIMMs.\n"); + return -EINVAL; + } + break; + default: + ERROR("Invalid number of controllers.\n"); + return -EINVAL; + } + /* now we have valid and identical DIMMs on controllers */ +#endif /* CONFIG_DDR_NODIMM */ + + debug("cal cs\n"); + conf->cs_in_use = 0; + for (j = 0; j < DDRC_NUM_DIMM; j++) { + if (conf->dimm_in_use[j] == 0) { + continue; + } + switch (dimm->n_ranks) { + case 4: + ERROR("Quad-rank DIMM not supported\n"); + return -EINVAL; + case 2: + conf->cs_on_dimm[j] = 0x3 << (j * CONFIG_CS_PER_SLOT); + conf->cs_in_use |= conf->cs_on_dimm[j]; + break; + case 1: + conf->cs_on_dimm[j] = 0x1 << (j * CONFIG_CS_PER_SLOT); + conf->cs_in_use |= conf->cs_on_dimm[j]; + break; + default: + ERROR("SPD error with n_ranks\n"); + return -EINVAL; + } + debug("cs_in_use = %x\n", conf->cs_in_use); + debug("cs_on_dimm[%d] = %x\n", j, conf->cs_on_dimm[j]); + } +#ifndef CONFIG_DDR_NODIMM + if (priv->dimm.rdimm != 0) { + NOTICE("RDIMM %s\n", priv->dimm.mpart); + } else { + NOTICE("UDIMM %s\n", priv->dimm.mpart); + } +#else + NOTICE("%s\n", priv->dimm.mpart); +#endif + + return valid_mask; +} + +static unsigned long long assign_intlv_addr( + const struct dimm_params *pdimm, + const struct memctl_opt *opt, + struct ddr_conf *conf, + const unsigned long long current_mem_base) +{ + int i; + int ctlr_density_mul = 0; + const unsigned long long rank_density = pdimm->rank_density >> + opt->dbw_cap_shift; + unsigned long long total_ctlr_mem; + + debug("rank density 0x%llx\n", rank_density); + switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) { + case DDR_BA_INTLV_CS0123: + ctlr_density_mul = 4; + break; + case DDR_BA_INTLV_CS01: + ctlr_density_mul = 2; + break; + default: + ctlr_density_mul = 1; + break; + } + debug("ctlr density mul %d\n", ctlr_density_mul); + switch (opt->ctlr_intlv_mode) { + case DDR_256B_INTLV: + total_ctlr_mem = 2 * ctlr_density_mul * rank_density; + break; + default: + ERROR("Unknown interleaving mode"); + return 0; + } + conf->base_addr = current_mem_base; + conf->total_mem = total_ctlr_mem; + + /* overwrite cs_in_use bitmask with controller interleaving */ + conf->cs_in_use = (1 << ctlr_density_mul) - 1; + debug("Overwrite cs_in_use as %x\n", conf->cs_in_use); + + /* Fill addr with each cs in use */ + for (i = 0; i < ctlr_density_mul; i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = total_ctlr_mem; + debug("CS %d\n", i); + debug(" base_addr 0x%llx\n", conf->cs_base_addr[i]); + debug(" size 0x%llx\n", conf->cs_size[i]); + } + + return total_ctlr_mem; +} + +static unsigned long long assign_non_intlv_addr( + const struct dimm_params *pdimm, + const struct memctl_opt *opt, + struct ddr_conf *conf, + unsigned long long current_mem_base) +{ + int i; + const unsigned long long rank_density = pdimm->rank_density >> + opt->dbw_cap_shift; + unsigned long long total_ctlr_mem = 0ULL; + + debug("rank density 0x%llx\n", rank_density); + conf->base_addr = current_mem_base; + + /* assign each cs */ + switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) { + case DDR_BA_INTLV_CS0123: + for (i = 0; i < DDRC_NUM_CS; i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = rank_density << 2; + total_ctlr_mem += rank_density; + } + break; + case DDR_BA_INTLV_CS01: + for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && i < 2; i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = rank_density << 1; + total_ctlr_mem += rank_density; + } + current_mem_base += total_ctlr_mem; + for (; ((conf->cs_in_use & (1 << i)) != 0) && i < DDRC_NUM_CS; + i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = rank_density; + total_ctlr_mem += rank_density; + current_mem_base += rank_density; + } + break; + case DDR_BA_NONE: + for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && + (i < DDRC_NUM_CS); i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = rank_density; + current_mem_base += rank_density; + total_ctlr_mem += rank_density; + } + break; + default: + ERROR("Unsupported bank interleaving\n"); + return 0; + } + for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && + (i < DDRC_NUM_CS); i++) { + debug("CS %d\n", i); + debug(" base_addr 0x%llx\n", conf->cs_base_addr[i]); + debug(" size 0x%llx\n", conf->cs_size[i]); + } + + return total_ctlr_mem; +} + +unsigned long long assign_addresses(struct ddr_info *priv) + __attribute__ ((weak)); + +unsigned long long assign_addresses(struct ddr_info *priv) +{ + struct memctl_opt *opt = &priv->opt; + const struct dimm_params *dimm = &priv->dimm; + struct ddr_conf *conf = &priv->conf; + unsigned long long current_mem_base = priv->mem_base; + unsigned long long total_mem; + + total_mem = 0ULL; + debug("ctlr_intlv %d\n", opt->ctlr_intlv); + if (opt->ctlr_intlv != 0) { + total_mem = assign_intlv_addr(dimm, opt, conf, + current_mem_base); + } else { + /* + * Simple linear assignment if memory controllers are not + * interleaved. This is only valid for SoCs with single DDRC. + */ + total_mem = assign_non_intlv_addr(dimm, opt, conf, + current_mem_base); + } + conf->total_mem = total_mem; + debug("base 0x%llx\n", current_mem_base); + debug("Total mem by assignment is 0x%llx\n", total_mem); + + return total_mem; +} + +static int cal_ddrc_regs(struct ddr_info *priv) +{ + int ret; + + ret = compute_ddrc(priv->clk, + &priv->opt, + &priv->conf, + &priv->ddr_reg, + &priv->dimm, + priv->ip_rev); + if (ret != 0) { + ERROR("Calculating DDR registers failed\n"); + } + + return ret; +} + +#endif /* CONFIG_STATIC_DDR */ + +static int write_ddrc_regs(struct ddr_info *priv) +{ + int i; + int ret; + + for (i = 0; i < priv->num_ctlrs; i++) { + ret = ddrc_set_regs(priv->clk, &priv->ddr_reg, priv->ddr[i], 0); + if (ret != 0) { + ERROR("Writing DDR register(s) failed\n"); + return ret; + } + } + + return 0; +} + +long long dram_init(struct ddr_info *priv +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , uintptr_t nxp_ccn_hn_f0_addr +#endif + ) +{ + uint64_t time __unused; + long long dram_size; + int ret; + const uint64_t time_base = get_timer_val(0); + unsigned int ip_rev = get_ddrc_version(priv->ddr[0]); + + int valid_spd_mask __unused; + int scratch = 0x0; + + priv->ip_rev = ip_rev; + +#ifndef CONFIG_STATIC_DDR + INFO("time base %" PRIu64 " ms\n", time_base); + debug("Parse DIMM SPD(s)\n"); + valid_spd_mask = parse_spd(priv); + + if (valid_spd_mask < 0) { + ERROR("Parsing DIMM Error\n"); + return valid_spd_mask; + } + +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + if (priv->num_ctlrs == 2 || priv->num_ctlrs == 1) { + ret = disable_unused_ddrc(priv, valid_spd_mask, + nxp_ccn_hn_f0_addr); + if (ret != 0) { + return ret; + } + } +#endif + + time = get_timer_val(time_base); + INFO("Time after parsing SPD %" PRIu64 " ms\n", time); + debug("Synthesize configurations\n"); + ret = synthesize_ctlr(priv); + if (ret != 0) { + ERROR("Synthesize config error\n"); + return ret; + } + + debug("Assign binding addresses\n"); + dram_size = assign_addresses(priv); + if (dram_size == 0) { + ERROR("Assigning address error\n"); + return -EINVAL; + } + + debug("Calculate controller registers\n"); + ret = cal_ddrc_regs(priv); + if (ret != 0) { + ERROR("Calculate register error\n"); + return ret; + } + + ret = compute_ddr_phy(priv); + if (ret != 0) + ERROR("Calculating DDR PHY registers failed.\n"); + +#else + dram_size = board_static_ddr(priv); + if (dram_size == 0) { + ERROR("Error getting static DDR settings.\n"); + return -EINVAL; + } +#endif + + if (priv->warm_boot_flag == DDR_WARM_BOOT) { + scratch = (priv->ddr_reg).sdram_cfg[1]; + scratch = scratch & ~(SDRAM_CFG2_D_INIT); + priv->ddr_reg.sdram_cfg[1] = scratch; + } + + time = get_timer_val(time_base); + INFO("Time before programming controller %" PRIu64 " ms\n", time); + debug("Program controller registers\n"); + ret = write_ddrc_regs(priv); + if (ret != 0) { + ERROR("Programing DDRC error\n"); + return ret; + } + + puts(""); + NOTICE("%lld GB ", dram_size >> 30); + print_ddr_info(priv->ddr[0]); + + time = get_timer_val(time_base); + INFO("Time used by DDR driver %" PRIu64 " ms\n", time); + + return dram_size; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.mk b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.mk new file mode 100644 index 0000000..f827a1b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.mk @@ -0,0 +1,80 @@ +# +# Copyright 2021-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq ($(PLAT_DDR_PHY), PHY_GEN2) +$(eval $(call add_define, PHY_GEN2)) +PLAT_DDR_PHY_DIR := phy-gen2 +ifeq (${APPLY_MAX_CDD},yes) +$(eval $(call add_define,NXP_APPLY_MAX_CDD)) +endif + +ifeq (${ERRATA_DDR_A011396}, 1) +$(eval $(call add_define,ERRATA_DDR_A011396)) +endif + +ifeq (${ERRATA_DDR_A050450}, 1) +$(eval $(call add_define,ERRATA_DDR_A050450)) +endif + +ifeq (${ERRATA_DDR_A050958}, 1) +$(eval $(call add_define,ERRATA_DDR_A050958)) +endif + +endif + +ifeq ($(PLAT_DDR_PHY), PHY_GEN1) +PLAT_DDR_PHY_DIR := phy-gen1 + +ifeq (${ERRATA_DDR_A008511},1) +$(eval $(call add_define,ERRATA_DDR_A008511)) +endif + +ifeq (${ERRATA_DDR_A009803},1) +$(eval $(call add_define,ERRATA_DDR_A009803)) +endif + +ifeq (${ERRATA_DDR_A009942},1) +$(eval $(call add_define,ERRATA_DDR_A009942)) +endif + +ifeq (${ERRATA_DDR_A010165},1) +$(eval $(call add_define,ERRATA_DDR_A010165)) +endif + +endif + +ifeq ($(DDR_BIST), yes) +$(eval $(call add_define, BIST_EN)) +endif + +ifeq ($(DDR_DEBUG), yes) +$(eval $(call add_define, DDR_DEBUG)) +endif + +ifeq ($(DDR_PHY_DEBUG), yes) +$(eval $(call add_define, DDR_PHY_DEBUG)) +endif + +ifeq ($(DEBUG_PHY_IO), yes) +$(eval $(call add_define, DEBUG_PHY_IO)) +endif + +ifeq ($(DEBUG_WARM_RESET), yes) +$(eval $(call add_define, DEBUG_WARM_RESET)) +endif + +ifeq ($(DEBUG_DDR_INPUT_CONFIG), yes) +$(eval $(call add_define, DEBUG_DDR_INPUT_CONFIG)) +endif + +DDR_CNTLR_SOURCES := $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddr.c \ + $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddrc.c \ + $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/dimm.c \ + $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/regs.c \ + $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/utility.c \ + $(PLAT_DRIVERS_PATH)/ddr/$(PLAT_DDR_PHY_DIR)/phy.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c new file mode 100644 index 0000000..17a2b6a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c @@ -0,0 +1,594 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define BIST_CR 0x80060000 +#define BIST_CR_EN 0x80000000 +#define BIST_CR_STAT 0x00000001 +#define CTLR_INTLV_MASK 0x20000000 + +#pragma weak run_bist + +bool run_bist(void) +{ +#ifdef BIST_EN + return true; +#else + return false; +#endif +} + +/* + * Perform build-in test on memory + * timeout value in 10ms + */ +int bist(const struct ccsr_ddr *ddr, int timeout) +{ + const unsigned int test_pattern[10] = { + 0xffffffff, + 0x00000000, + 0xaaaaaaaa, + 0x55555555, + 0xcccccccc, + 0x33333333, + 0x12345678, + 0xabcdef01, + 0xaa55aa55, + 0x55aa55aa + }; + unsigned int mtcr, err_detect, err_sbe; + unsigned int cs0_config; + unsigned int csn_bnds[4]; + int ret = 0; + uint32_t i; +#ifdef CONFIG_DDR_ADDR_DEC + uint32_t dec_9 = ddr_in32(&ddr->dec[9]); + uint32_t pos = 0U; + uint32_t map_save = 0U; + uint32_t temp32 = 0U; + uint32_t map, shift, highest; +#endif + + cs0_config = ddr_in32(&ddr->csn_cfg[0]); + if ((cs0_config & CTLR_INTLV_MASK) != 0U) { + /* set bnds to non-interleaving */ + for (i = 0U; i < 4U; i++) { + csn_bnds[i] = ddr_in32(&ddr->bnds[i].a); + ddr_out32(&ddr->bnds[i].a, + (csn_bnds[i] & U(0xfffefffe)) >> 1U); + } + ddr_out32(&ddr->csn_cfg[0], cs0_config & ~CTLR_INTLV_MASK); +#ifdef CONFIG_DDR_ADDR_DEC + if ((dec_9 & 0x1U) != 0U) { + highest = (dec_9 >> 26U) == U(0x3F) ? 0U : dec_9 >> 26U; + pos = 37U; + for (i = 0U; i < 36U; i++) { /* Go through all 37 */ + if ((i % 4U) == 0U) { + temp32 = ddr_in32(&ddr->dec[i >> 2U]); + } + shift = (3U - i % 4U) * 8U + 2U; + map = (temp32 >> shift) & U(0x3F); + if (map > highest && map != U(0x3F)) { + highest = map; + pos = i; + } + } + debug("\nFound highest position %d, mapping to %d, ", + pos, highest); + map_save = ddr_in32(&ddr->dec[pos >> 2]); + shift = (3U - pos % 4U) * 8U + 2U; + debug("in dec[%d], bit %d (0x%x)\n", + pos >> 2U, shift, map_save); + temp32 = map_save & ~(U(0x3F) << shift); + temp32 |= 8U << shift; + ddr_out32(&ddr->dec[pos >> 2U], temp32); + timeout <<= 2U; + debug("Increase wait time to %d ms\n", timeout * 10); + } +#endif + } + for (i = 0U; i < 10U; i++) { + ddr_out32(&ddr->mtp[i], test_pattern[i]); + } + mtcr = BIST_CR; + ddr_out32(&ddr->mtcr, mtcr); + do { + mdelay(10); + mtcr = ddr_in32(&ddr->mtcr); + } while (timeout-- > 0 && ((mtcr & BIST_CR_EN) != 0)); + if (timeout <= 0) { + ERROR("Timeout\n"); + } else { + debug("Timer remains %d\n", timeout); + } + + err_detect = ddr_in32(&ddr->err_detect); + err_sbe = ddr_in32(&ddr->err_sbe); + if (err_detect != 0U || ((err_sbe & U(0xffff)) != 0U)) { + ERROR("ECC error detected\n"); + ret = -EIO; + } + + if ((cs0_config & CTLR_INTLV_MASK) != 0) { + for (i = 0U; i < 4U; i++) { + ddr_out32(&ddr->bnds[i].a, csn_bnds[i]); + } + ddr_out32(&ddr->csn_cfg[0], cs0_config); +#ifdef CONFIG_DDR_ADDR_DEC + if ((dec_9 & U(0x1)) != 0U) { + ddr_out32(&ddr->dec[pos >> 2], map_save); + } +#endif + } + if ((mtcr & BIST_CR_STAT) != 0) { + ERROR("Built-in self test failed\n"); + ret = -EIO; + } else { + NOTICE("Build-in self test passed\n"); + } + + return ret; +} + +void dump_ddrc(unsigned int *ddr) +{ +#ifdef DDR_DEBUG + uint32_t i; + unsigned long val; + + for (i = 0U; i < U(0x400); i++, ddr++) { + val = ddr_in32(ddr); + if (val != 0U) { /* skip zeros */ + debug("*0x%lx = 0x%lx\n", (unsigned long)ddr, val); + } + } +#endif +} + +#ifdef ERRATA_DDR_A009803 +static void set_wait_for_bits_clear(const void *ptr, + unsigned int value, + unsigned int bits) +{ + int timeout = 1000; + + ddr_out32(ptr, value); + do { + udelay(100); + } while (timeout-- > 0 && ((ddr_in32(ptr) & bits) != 0)); + + if (timeout <= 0) { + ERROR("wait for clear timeout.\n"); + } +} +#endif + +#if (DDRC_NUM_CS > 4) +#error Invalid setting for DDRC_NUM_CS +#endif + +/* + * If supported by the platform, writing to DDR controller takes two + * passes to deassert DDR reset to comply with JEDEC specs for RDIMMs. + */ +int ddrc_set_regs(const unsigned long clk, + const struct ddr_cfg_regs *regs, + const struct ccsr_ddr *ddr, + int twopass) +{ + unsigned int i, bus_width; + unsigned int temp_sdram_cfg; + unsigned int total_mem_per_ctrl, total_mem_per_ctrl_adj; + const int mod_bnds = regs->cs[0].config & CTLR_INTLV_MASK; + int timeout; + int ret = 0; +#if defined(ERRATA_DDR_A009942) || defined(ERRATA_DDR_A010165) + unsigned long ddr_freq; + unsigned int tmp; +#ifdef ERRATA_DDR_A009942 + unsigned int check; + unsigned int cpo_min = U(0xff); + unsigned int cpo_max = 0U; +#endif +#endif + + if (twopass == 2U) { + goto after_reset; + } + + /* Set cdr1 first in case 0.9v VDD is enabled for some SoCs*/ + ddr_out32(&ddr->ddr_cdr1, regs->cdr[0]); + + ddr_out32(&ddr->sdram_clk_cntl, regs->clk_cntl); + + for (i = 0U; i < DDRC_NUM_CS; i++) { + if (mod_bnds != 0U) { + ddr_out32(&ddr->bnds[i].a, + (regs->cs[i].bnds & U(0xfffefffe)) >> 1U); + } else { + ddr_out32(&ddr->bnds[i].a, regs->cs[i].bnds); + } + ddr_out32(&ddr->csn_cfg_2[i], regs->cs[i].config_2); + } + + ddr_out32(&ddr->timing_cfg_0, regs->timing_cfg[0]); + ddr_out32(&ddr->timing_cfg_1, regs->timing_cfg[1]); + ddr_out32(&ddr->timing_cfg_2, regs->timing_cfg[2]); + ddr_out32(&ddr->timing_cfg_3, regs->timing_cfg[3]); + ddr_out32(&ddr->timing_cfg_4, regs->timing_cfg[4]); + ddr_out32(&ddr->timing_cfg_5, regs->timing_cfg[5]); + ddr_out32(&ddr->timing_cfg_6, regs->timing_cfg[6]); + ddr_out32(&ddr->timing_cfg_7, regs->timing_cfg[7]); + ddr_out32(&ddr->timing_cfg_8, regs->timing_cfg[8]); + ddr_out32(&ddr->timing_cfg_9, regs->timing_cfg[9]); + ddr_out32(&ddr->zq_cntl, regs->zq_cntl); + for (i = 0U; i < 4U; i++) { + ddr_out32(&ddr->dq_map[i], regs->dq_map[i]); + } + ddr_out32(&ddr->sdram_cfg_3, regs->sdram_cfg[2]); + ddr_out32(&ddr->sdram_mode, regs->sdram_mode[0]); + ddr_out32(&ddr->sdram_mode_2, regs->sdram_mode[1]); + ddr_out32(&ddr->sdram_mode_3, regs->sdram_mode[2]); + ddr_out32(&ddr->sdram_mode_4, regs->sdram_mode[3]); + ddr_out32(&ddr->sdram_mode_5, regs->sdram_mode[4]); + ddr_out32(&ddr->sdram_mode_6, regs->sdram_mode[5]); + ddr_out32(&ddr->sdram_mode_7, regs->sdram_mode[6]); + ddr_out32(&ddr->sdram_mode_8, regs->sdram_mode[7]); + ddr_out32(&ddr->sdram_mode_9, regs->sdram_mode[8]); + ddr_out32(&ddr->sdram_mode_10, regs->sdram_mode[9]); + ddr_out32(&ddr->sdram_mode_11, regs->sdram_mode[10]); + ddr_out32(&ddr->sdram_mode_12, regs->sdram_mode[11]); + ddr_out32(&ddr->sdram_mode_13, regs->sdram_mode[12]); + ddr_out32(&ddr->sdram_mode_14, regs->sdram_mode[13]); + ddr_out32(&ddr->sdram_mode_15, regs->sdram_mode[14]); + ddr_out32(&ddr->sdram_mode_16, regs->sdram_mode[15]); + ddr_out32(&ddr->sdram_md_cntl, regs->md_cntl); +#ifdef ERRATA_DDR_A009663 + ddr_out32(&ddr->sdram_interval, + regs->interval & ~SDRAM_INTERVAL_BSTOPRE); +#else + ddr_out32(&ddr->sdram_interval, regs->interval); +#endif + ddr_out32(&ddr->sdram_data_init, regs->data_init); + if (regs->eor != 0) { + ddr_out32(&ddr->eor, regs->eor); + } + + ddr_out32(&ddr->wrlvl_cntl, regs->wrlvl_cntl[0]); +#ifndef NXP_DDR_EMU + /* + * Skip these two registers if running on emulator + * because emulator doesn't have skew between bytes. + */ + + if (regs->wrlvl_cntl[1] != 0) { + ddr_out32(&ddr->ddr_wrlvl_cntl_2, regs->wrlvl_cntl[1]); + } + if (regs->wrlvl_cntl[2] != 0) { + ddr_out32(&ddr->ddr_wrlvl_cntl_3, regs->wrlvl_cntl[2]); + } +#endif + + ddr_out32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr); + ddr_out32(&ddr->ddr_sdram_rcw_1, regs->sdram_rcw[0]); + ddr_out32(&ddr->ddr_sdram_rcw_2, regs->sdram_rcw[1]); + ddr_out32(&ddr->ddr_sdram_rcw_3, regs->sdram_rcw[2]); + ddr_out32(&ddr->ddr_sdram_rcw_4, regs->sdram_rcw[3]); + ddr_out32(&ddr->ddr_sdram_rcw_5, regs->sdram_rcw[4]); + ddr_out32(&ddr->ddr_sdram_rcw_6, regs->sdram_rcw[5]); + ddr_out32(&ddr->ddr_cdr2, regs->cdr[1]); + ddr_out32(&ddr->sdram_cfg_2, regs->sdram_cfg[1]); + ddr_out32(&ddr->init_addr, regs->init_addr); + ddr_out32(&ddr->init_ext_addr, regs->init_ext_addr); + +#ifdef ERRATA_DDR_A009803 + /* part 1 of 2 */ + if ((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) { + if ((regs->sdram_cfg[0] & SDRAM_CFG_RD_EN) != 0) { + ddr_out32(&ddr->ddr_sdram_rcw_2, + regs->sdram_rcw[1] & ~0xf0); + } + + ddr_out32(&ddr->err_disable, + regs->err_disable | DDR_ERR_DISABLE_APED); + } +#else + ddr_out32(&ddr->err_disable, regs->err_disable); +#endif + ddr_out32(&ddr->err_int_en, regs->err_int_en); + + /* For DDRC 5.05 only */ + if (get_ddrc_version(ddr) == 0x50500) { + ddr_out32(&ddr->tx_cfg[1], 0x1f1f1f1f); + ddr_out32(&ddr->debug[3], 0x124a02c0); + } + + for (i = 0U; i < 4U; i++) { + if (regs->tx_cfg[i] != 0) { + ddr_out32(&ddr->tx_cfg[i], regs->tx_cfg[i]); + } + } + for (i = 0U; i < 64U; i++) { + if (regs->debug[i] != 0) { +#ifdef ERRATA_DDR_A009942 + if (i == 28U) { + continue; + } +#endif + ddr_out32(&ddr->debug[i], regs->debug[i]); + } + } +#ifdef CONFIG_DDR_ADDR_DEC + if ((regs->dec[9] & 1) != 0U) { + for (i = 0U; i < 10U; i++) { + ddr_out32(&ddr->dec[i], regs->dec[i]); + } + if (mod_bnds != 0) { + debug("Disable address decoding\n"); + ddr_out32(&ddr->dec[9], 0); + } + } +#endif + +#ifdef ERRATA_DDR_A008511 + /* Part 1 of 2 */ + /* This erraum only applies to verion 5.2.1 */ + if (get_ddrc_version(ddr) == 0x50200) { + ERROR("Unsupported SoC.\n"); + } else if (get_ddrc_version(ddr) == 0x50201) { + ddr_out32(&ddr->debug[37], (U(1) << 31)); + ddr_out32(&ddr->ddr_cdr2, + regs->cdr[1] | DDR_CDR2_VREF_TRAIN_EN); + } else { + debug("Erratum A008511 doesn't apply.\n"); + } +#endif + +#ifdef ERRATA_DDR_A009942 + ddr_freq = clk / 1000000U; + tmp = ddr_in32(&ddr->debug[28]); + tmp &= U(0xff0fff00); + tmp |= ddr_freq <= 1333U ? U(0x0080006a) : + (ddr_freq <= 1600U ? U(0x0070006f) : + (ddr_freq <= 1867U ? U(0x00700076) : U(0x0060007b))); + if (regs->debug[28] != 0) { + tmp &= ~0xff; + tmp |= regs->debug[28] & 0xff; + } else { + WARN("Warning: Optimal CPO value not set.\n"); + } + ddr_out32(&ddr->debug[28], tmp); +#endif + +#ifdef ERRATA_DDR_A010165 + ddr_freq = clk / 1000000U; + if ((ddr_freq > 1900) && (ddr_freq < 2300)) { + tmp = ddr_in32(&ddr->debug[28]); + ddr_out32(&ddr->debug[28], tmp | 0x000a0000); + } +#endif + /* + * For RDIMMs, JEDEC spec requires clocks to be stable before reset is + * deasserted. Clocks start when any chip select is enabled and clock + * control register is set. Because all DDR components are connected to + * one reset signal, this needs to be done in two steps. Step 1 is to + * get the clocks started. Step 2 resumes after reset signal is + * deasserted. + */ + if (twopass == 1) { + udelay(200); + return 0; + } + + /* As per new sequence flow shall be write CSn_CONFIG registers needs to + * be set after all the other DDR controller registers are set, then poll + * for PHY_INIT_CMPLT = 1 , then wait at least 100us (micro seconds), + * then set the MEM_EN = 1 + */ + for (i = 0U; i < DDRC_NUM_CS; i++) { + if (mod_bnds != 0U && i == 0U) { + ddr_out32(&ddr->csn_cfg[i], + (regs->cs[i].config & ~CTLR_INTLV_MASK)); + } else { + ddr_out32(&ddr->csn_cfg[i], regs->cs[i].config); + } + } + +after_reset: + /* Set, but do not enable the memory */ + temp_sdram_cfg = regs->sdram_cfg[0]; + temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); + ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg); + + if (get_ddrc_version(ddr) < U(0x50500)) { + /* + * 500 painful micro-seconds must elapse between + * the DDR clock setup and the DDR config enable. + * DDR2 need 200 us, and DDR3 need 500 us from spec, + * we choose the max, that is 500 us for all of case. + */ + udelay(500); + /* applied memory barrier */ + mb(); + isb(); + } else { + /* wait for PHY complete */ + timeout = 40; + while (((ddr_in32(&ddr->ddr_dsr2) & 0x4) != 0) && + (timeout > 0)) { + udelay(500); + timeout--; + } + if (timeout <= 0) { + printf("PHY handshake timeout, ddr_dsr2 = %x\n", + ddr_in32(&ddr->ddr_dsr2)); + } else { + debug("PHY handshake completed, timer remains %d\n", + timeout); + } + } + + temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg); + /* Let the controller go */ + udelay(100); + ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN); + + /* applied memory barrier */ + mb(); + isb(); + + total_mem_per_ctrl = 0; + for (i = 0; i < DDRC_NUM_CS; i++) { + if ((regs->cs[i].config & 0x80000000) == 0) { + continue; + } + total_mem_per_ctrl += 1 << ( + ((regs->cs[i].config >> 14) & 0x3) + 2 + + ((regs->cs[i].config >> 8) & 0x7) + 12 + + ((regs->cs[i].config >> 4) & 0x3) + 0 + + ((regs->cs[i].config >> 0) & 0x7) + 8 + + ((regs->sdram_cfg[2] >> 4) & 0x3) + + 3 - ((regs->sdram_cfg[0] >> 19) & 0x3) - + 26); /* minus 26 (count of 64M) */ + } + total_mem_per_ctrl_adj = total_mem_per_ctrl; + /* + * total memory / bus width = transactions needed + * transactions needed / data rate = seconds + * to add plenty of buffer, double the time + * For example, 2GB on 666MT/s 64-bit bus takes about 402ms + * Let's wait for 800ms + */ + bus_width = 3 - ((ddr_in32(&ddr->sdram_cfg) & SDRAM_CFG_DBW_MASK) + >> SDRAM_CFG_DBW_SHIFT); + timeout = ((total_mem_per_ctrl_adj << (6 - bus_width)) * 100 / + (clk >> 20)) << 2; + total_mem_per_ctrl_adj >>= 4; /* shift down to gb size */ + if ((ddr_in32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) != 0) { + debug("total size %d GB\n", total_mem_per_ctrl_adj); + debug("Need to wait up to %d ms\n", timeout * 10); + + do { + mdelay(10); + } while (timeout-- > 0 && + ((ddr_in32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT)) != 0); + + if (timeout <= 0) { + if (ddr_in32(&ddr->debug[1]) & 0x3d00) { + ERROR("Found training error(s): 0x%x\n", + ddr_in32(&ddr->debug[1])); + } + ERROR("Error: Waiting for D_INIT timeout.\n"); + return -EIO; + } + } + + if (mod_bnds != 0U) { + debug("Restore original bnds\n"); + for (i = 0U; i < DDRC_NUM_CS; i++) { + ddr_out32(&ddr->bnds[i].a, regs->cs[i].bnds); + } + ddr_out32(&ddr->csn_cfg[0], regs->cs[0].config); +#ifdef CONFIG_DDR_ADDR_DEC + if ((regs->dec[9] & U(0x1)) != 0U) { + debug("Restore address decoding\n"); + ddr_out32(&ddr->dec[9], regs->dec[9]); + } +#endif + } + +#ifdef ERRATA_DDR_A009803 + /* Part 2 of 2 */ + if ((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) { + timeout = 400; + do { + mdelay(1); + } while (timeout-- > 0 && ((ddr_in32(&ddr->debug[1]) & 0x2) == 0)); + + if ((regs->sdram_cfg[0] & SDRAM_CFG_RD_EN) != 0) { + for (i = 0U; i < DDRC_NUM_CS; i++) { + if ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) == 0) { + continue; + } + set_wait_for_bits_clear(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL(i) | + 0x070000ed, + MD_CNTL_MD_EN); + udelay(1); + } + } + + ddr_out32(&ddr->err_disable, + regs->err_disable & ~DDR_ERR_DISABLE_APED); + } +#endif + +#ifdef ERRATA_DDR_A009663 + ddr_out32(&ddr->sdram_interval, regs->interval); +#endif + +#ifdef ERRATA_DDR_A009942 + timeout = 400; + do { + mdelay(1); + } while (timeout-- > 0 && ((ddr_in32(&ddr->debug[1]) & 0x2) == 0)); + tmp = (regs->sdram_cfg[0] >> 19) & 0x3; + check = (tmp == DDR_DBUS_64) ? 4 : ((tmp == DDR_DBUS_32) ? 2 : 1); + for (i = 0; i < check; i++) { + tmp = ddr_in32(&ddr->debug[9 + i]); + debug("Reading debug[%d] as 0x%x\n", i + 9, tmp); + cpo_min = min(cpo_min, + min((tmp >> 24) & 0xff, (tmp >> 8) & 0xff)); + cpo_max = max(cpo_max, + max((tmp >> 24) & 0xff, (tmp >> 8) & 0xff)); + } + if ((regs->sdram_cfg[0] & SDRAM_CFG_ECC_EN) != 0) { + tmp = ddr_in32(&ddr->debug[13]); + cpo_min = min(cpo_min, (tmp >> 24) & 0xff); + cpo_max = max(cpo_max, (tmp >> 24) & 0xff); + } + debug("cpo_min 0x%x\n", cpo_min); + debug("cpo_max 0x%x\n", cpo_max); + tmp = ddr_in32(&ddr->debug[28]); + debug("debug[28] 0x%x\n", tmp); + if ((cpo_min + 0x3B) < (tmp & 0xff)) { + WARN("Warning: A009942 requires setting cpo_sample to 0x%x\n", + (cpo_min + cpo_max) / 2 + 0x27); + } else { + debug("Optimal cpo_sample 0x%x\n", + (cpo_min + cpo_max) / 2 + 0x27); + } +#endif + if (run_bist() != 0) { + if ((ddr_in32(&ddr->debug[1]) & + ((get_ddrc_version(ddr) == 0x50500) ? 0x3c00 : 0x3d00)) != 0) { + ERROR("Found training error(s): 0x%x\n", + ddr_in32(&ddr->debug[1])); + return -EIO; + } + INFO("Running built-in self test ...\n"); + /* give it 10x time to cover whole memory */ + timeout = ((total_mem_per_ctrl << (6 - bus_width)) * + 100 / (clk >> 20)) * 10; + INFO("\tWait up to %d ms\n", timeout * 10); + ret = bist(ddr, timeout); + } + dump_ddrc((void *)ddr); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c new file mode 100644 index 0000000..a82db6c --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c @@ -0,0 +1,399 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +int read_spd(unsigned char chip, void *buf, int len) +{ + unsigned char dummy = 0U; + int ret; + + if (len < 256) { + ERROR("Invalid SPD length\n"); + return -EINVAL; + } + + i2c_write(SPD_SPA0_ADDRESS, 0, 1, &dummy, 1); + ret = i2c_read(chip, 0, 1, buf, 256); + if (ret == 0) { + i2c_write(SPD_SPA1_ADDRESS, 0, 1, &dummy, 1); + ret = i2c_read(chip, 0, 1, buf + 256, min(256, len - 256)); + } + if (ret != 0) { + zeromem(buf, len); + } + + return ret; +} + +int crc16(unsigned char *ptr, int count) +{ + int i; + int crc = 0; + + while (--count >= 0) { + crc = crc ^ (int)*ptr++ << 8; + for (i = 0; i < 8; ++i) { + if ((crc & 0x8000) != 0) { + crc = crc << 1 ^ 0x1021; + } else { + crc = crc << 1; + } + } + } + return crc & 0xffff; +} + +static int ddr4_spd_check(const struct ddr4_spd *spd) +{ + void *p = (void *)spd; + int csum16; + int len; + char crc_lsb; /* byte 126 */ + char crc_msb; /* byte 127 */ + + len = 126; + csum16 = crc16(p, len); + + crc_lsb = (char) (csum16 & 0xff); + crc_msb = (char) (csum16 >> 8); + + if (spd->crc[0] != crc_lsb || spd->crc[1] != crc_msb) { + ERROR("SPD CRC = 0x%x%x, computed CRC = 0x%x%x\n", + spd->crc[1], spd->crc[0], crc_msb, crc_lsb); + return -EINVAL; + } + + p = (void *)spd + 128; + len = 126; + csum16 = crc16(p, len); + + crc_lsb = (char) (csum16 & 0xff); + crc_msb = (char) (csum16 >> 8); + + if (spd->mod_section.uc[126] != crc_lsb || + spd->mod_section.uc[127] != crc_msb) { + ERROR("SPD CRC = 0x%x%x, computed CRC = 0x%x%x\n", + spd->mod_section.uc[127], spd->mod_section.uc[126], + crc_msb, crc_lsb); + return -EINVAL; + } + + return 0; +} + +static unsigned long long +compute_ranksize(const struct ddr4_spd *spd) +{ + unsigned long long bsize; + + int nbit_sdram_cap_bsize = 0; + int nbit_primary_bus_width = 0; + int nbit_sdram_width = 0; + int die_count = 0; + bool package_3ds; + + if ((spd->density_banks & 0xf) <= 7) { + nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28; + } + if ((spd->bus_width & 0x7) < 4) { + nbit_primary_bus_width = (spd->bus_width & 0x7) + 3; + } + if ((spd->organization & 0x7) < 4) { + nbit_sdram_width = (spd->organization & 0x7) + 2; + } + package_3ds = (spd->package_type & 0x3) == 0x2; + if (package_3ds) { + die_count = (spd->package_type >> 4) & 0x7; + } + + bsize = 1ULL << (nbit_sdram_cap_bsize - 3 + + nbit_primary_bus_width - nbit_sdram_width + + die_count); + + return bsize; +} + +int cal_dimm_params(const struct ddr4_spd *spd, struct dimm_params *pdimm) +{ + int ret; + int i; + static const unsigned char udimm_rc_e_dq[18] = { + 0x0c, 0x2c, 0x15, 0x35, 0x15, 0x35, 0x0b, 0x2c, 0x15, + 0x35, 0x0b, 0x35, 0x0b, 0x2c, 0x0b, 0x35, 0x15, 0x36 + }; + int spd_error = 0; + unsigned char *ptr; + unsigned char val; + + if (spd->mem_type != SPD_MEMTYPE_DDR4) { + ERROR("Not a DDR4 DIMM.\n"); + return -EINVAL; + } + + ret = ddr4_spd_check(spd); + if (ret != 0) { + ERROR("DIMM SPD checksum mismatch\n"); + return -EINVAL; + } + + /* + * The part name in ASCII in the SPD EEPROM is not null terminated. + * Guarantee null termination here by presetting all bytes to 0 + * and copying the part name in ASCII from the SPD onto it + */ + if ((spd->info_size_crc & 0xF) > 2) { + memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); + } + + /* DIMM organization parameters */ + pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1; + debug("n_ranks %d\n", pdimm->n_ranks); + pdimm->rank_density = compute_ranksize(spd); + if (pdimm->rank_density == 0) { + return -EINVAL; + } + + debug("rank_density 0x%llx\n", pdimm->rank_density); + pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; + debug("capacity 0x%llx\n", pdimm->capacity); + pdimm->die_density = spd->density_banks & 0xf; + debug("die density 0x%x\n", pdimm->die_density); + pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7)); + debug("primary_sdram_width %d\n", pdimm->primary_sdram_width); + if (((spd->bus_width >> 3) & 0x3) != 0) { + pdimm->ec_sdram_width = 8; + } else { + pdimm->ec_sdram_width = 0; + } + debug("ec_sdram_width %d\n", pdimm->ec_sdram_width); + pdimm->device_width = 1 << ((spd->organization & 0x7) + 2); + debug("device_width %d\n", pdimm->device_width); + pdimm->package_3ds = (spd->package_type & 0x3) == 0x2 ? + (spd->package_type >> 4) & 0x7 : 0; + debug("package_3ds %d\n", pdimm->package_3ds); + + switch (spd->module_type & DDR4_SPD_MODULETYPE_MASK) { + case DDR4_SPD_RDIMM: + case DDR4_SPD_MINI_RDIMM: + case DDR4_SPD_72B_SO_RDIMM: + pdimm->rdimm = 1; + pdimm->rc = spd->mod_section.registered.ref_raw_card & 0x9f; + if ((spd->mod_section.registered.reg_map & 0x1) != 0) { + pdimm->mirrored_dimm = 1; + } + val = spd->mod_section.registered.ca_stren; + pdimm->rcw[3] = val >> 4; + pdimm->rcw[4] = ((val & 0x3) << 2) | ((val & 0xc) >> 2); + val = spd->mod_section.registered.clk_stren; + pdimm->rcw[5] = ((val & 0x3) << 2) | ((val & 0xc) >> 2); + pdimm->rcw[6] = 0xf; + /* A17 used for 16Gb+, C[2:0] used for 3DS */ + pdimm->rcw[8] = pdimm->die_density >= 0x6 ? 0x0 : 0x8 | + (pdimm->package_3ds > 0x3 ? 0x0 : + (pdimm->package_3ds > 0x1 ? 0x1 : + (pdimm->package_3ds > 0 ? 0x2 : 0x3))); + if (pdimm->package_3ds != 0 || pdimm->n_ranks != 4) { + pdimm->rcw[13] = 0x4; + } else { + pdimm->rcw[13] = 0x5; + } + pdimm->rcw[13] |= pdimm->mirrored_dimm ? 0x8 : 0; + break; + + case DDR4_SPD_UDIMM: + case DDR4_SPD_SO_DIMM: + case DDR4_SPD_MINI_UDIMM: + case DDR4_SPD_72B_SO_UDIMM: + case DDR4_SPD_16B_SO_DIMM: + case DDR4_SPD_32B_SO_DIMM: + pdimm->rc = spd->mod_section.unbuffered.ref_raw_card & 0x9f; + if ((spd->mod_section.unbuffered.addr_mapping & 0x1) != 0) { + pdimm->mirrored_dimm = 1; + } + if ((spd->mod_section.unbuffered.mod_height & 0xe0) == 0 && + (spd->mod_section.unbuffered.ref_raw_card == 0x04)) { + /* Fix SPD error found on DIMMs with raw card E0 */ + for (i = 0; i < 18; i++) { + if (spd->mapping[i] == udimm_rc_e_dq[i]) { + continue; + } + spd_error = 1; + ptr = (unsigned char *)&spd->mapping[i]; + *ptr = udimm_rc_e_dq[i]; + } + if (spd_error != 0) { + INFO("SPD DQ mapping error fixed\n"); + } + } + break; + + default: + ERROR("Unknown module_type 0x%x\n", spd->module_type); + return -EINVAL; + } + debug("rdimm %d\n", pdimm->rdimm); + debug("mirrored_dimm %d\n", pdimm->mirrored_dimm); + debug("rc 0x%x\n", pdimm->rc); + + /* SDRAM device parameters */ + pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12; + debug("n_row_addr %d\n", pdimm->n_row_addr); + pdimm->n_col_addr = (spd->addressing & 0x7) + 9; + debug("n_col_addr %d\n", pdimm->n_col_addr); + pdimm->bank_addr_bits = (spd->density_banks >> 4) & 0x3; + debug("bank_addr_bits %d\n", pdimm->bank_addr_bits); + pdimm->bank_group_bits = (spd->density_banks >> 6) & 0x3; + debug("bank_group_bits %d\n", pdimm->bank_group_bits); + + if (pdimm->ec_sdram_width != 0) { + pdimm->edc_config = 0x02; + } else { + pdimm->edc_config = 0x00; + } + debug("edc_config %d\n", pdimm->edc_config); + + /* DDR4 spec has BL8 -bit3, BC4 -bit2 */ + pdimm->burst_lengths_bitmask = 0x0c; + debug("burst_lengths_bitmask 0x%x\n", pdimm->burst_lengths_bitmask); + + /* MTB - medium timebase + * The MTB in the SPD spec is 125ps, + * + * FTB - fine timebase + * use 1/10th of ps as our unit to avoid floating point + * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps + */ + if ((spd->timebases & 0xf) == 0x0) { + pdimm->mtb_ps = 125; + pdimm->ftb_10th_ps = 10; + + } else { + ERROR("Unknown Timebases\n"); + return -EINVAL; + } + + /* sdram minimum cycle time */ + pdimm->tckmin_x_ps = spd_to_ps(spd->tck_min, spd->fine_tck_min); + debug("tckmin_x_ps %d\n", pdimm->tckmin_x_ps); + + /* sdram max cycle time */ + pdimm->tckmax_ps = spd_to_ps(spd->tck_max, spd->fine_tck_max); + debug("tckmax_ps %d\n", pdimm->tckmax_ps); + + /* + * CAS latency supported + * bit0 - CL7 + * bit4 - CL11 + * bit8 - CL15 + * bit12- CL19 + * bit16- CL23 + */ + pdimm->caslat_x = (spd->caslat_b1 << 7) | + (spd->caslat_b2 << 15) | + (spd->caslat_b3 << 23); + debug("caslat_x 0x%x\n", pdimm->caslat_x); + + if (spd->caslat_b4 != 0) { + WARN("Unhandled caslat_b4 value\n"); + } + + /* + * min CAS latency time + */ + pdimm->taa_ps = spd_to_ps(spd->taa_min, spd->fine_taa_min); + debug("taa_ps %d\n", pdimm->taa_ps); + + /* + * min RAS to CAS delay time + */ + pdimm->trcd_ps = spd_to_ps(spd->trcd_min, spd->fine_trcd_min); + debug("trcd_ps %d\n", pdimm->trcd_ps); + + /* + * Min Row Precharge Delay Time + */ + pdimm->trp_ps = spd_to_ps(spd->trp_min, spd->fine_trp_min); + debug("trp_ps %d\n", pdimm->trp_ps); + + /* min active to precharge delay time */ + pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) + + spd->tras_min_lsb) * pdimm->mtb_ps; + debug("tras_ps %d\n", pdimm->tras_ps); + + /* min active to actice/refresh delay time */ + pdimm->trc_ps = spd_to_ps((((spd->tras_trc_ext & 0xf0) << 4) + + spd->trc_min_lsb), spd->fine_trc_min); + debug("trc_ps %d\n", pdimm->trc_ps); + /* Min Refresh Recovery Delay Time */ + pdimm->trfc1_ps = ((spd->trfc1_min_msb << 8) | (spd->trfc1_min_lsb)) * + pdimm->mtb_ps; + debug("trfc1_ps %d\n", pdimm->trfc1_ps); + pdimm->trfc2_ps = ((spd->trfc2_min_msb << 8) | (spd->trfc2_min_lsb)) * + pdimm->mtb_ps; + debug("trfc2_ps %d\n", pdimm->trfc2_ps); + pdimm->trfc4_ps = ((spd->trfc4_min_msb << 8) | (spd->trfc4_min_lsb)) * + pdimm->mtb_ps; + debug("trfc4_ps %d\n", pdimm->trfc4_ps); + /* min four active window delay time */ + pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) * + pdimm->mtb_ps; + debug("tfaw_ps %d\n", pdimm->tfaw_ps); + + /* min row active to row active delay time, different bank group */ + pdimm->trrds_ps = spd_to_ps(spd->trrds_min, spd->fine_trrds_min); + debug("trrds_ps %d\n", pdimm->trrds_ps); + /* min row active to row active delay time, same bank group */ + pdimm->trrdl_ps = spd_to_ps(spd->trrdl_min, spd->fine_trrdl_min); + debug("trrdl_ps %d\n", pdimm->trrdl_ps); + /* min CAS to CAS Delay Time (tCCD_Lmin), same bank group */ + pdimm->tccdl_ps = spd_to_ps(spd->tccdl_min, spd->fine_tccdl_min); + debug("tccdl_ps %d\n", pdimm->tccdl_ps); + if (pdimm->package_3ds != 0) { + if (pdimm->die_density > 5) { + debug("Unsupported logical rank density 0x%x\n", + pdimm->die_density); + return -EINVAL; + } + pdimm->trfc_slr_ps = (pdimm->die_density <= 4) ? + 260000 : 350000; + } + debug("trfc_slr_ps %d\n", pdimm->trfc_slr_ps); + + /* 15ns for all speed bins */ + pdimm->twr_ps = 15000; + debug("twr_ps %d\n", pdimm->twr_ps); + + /* + * Average periodic refresh interval + * tREFI = 7.8 us at normal temperature range + */ + pdimm->refresh_rate_ps = 7800000; + debug("refresh_rate_ps %d\n", pdimm->refresh_rate_ps); + + for (i = 0; i < 18; i++) { + pdimm->dq_mapping[i] = spd->mapping[i]; + debug("dq_mapping 0x%x\n", pdimm->dq_mapping[i]); + } + + pdimm->dq_mapping_ors = ((spd->mapping[0] >> 6) & 0x3) == 0 ? 1 : 0; + debug("dq_mapping_ors %d\n", pdimm->dq_mapping_ors); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c new file mode 100644 index 0000000..cedd7ca --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c @@ -0,0 +1,1394 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +static inline unsigned int cal_cwl(const unsigned long clk) +{ + const unsigned int mclk_ps = get_memory_clk_ps(clk); + + return mclk_ps >= 1250U ? 9U : + (mclk_ps >= 1070U ? 10U : + (mclk_ps >= 935U ? 11U : + (mclk_ps >= 833U ? 12U : + (mclk_ps >= 750U ? 14U : + (mclk_ps >= 625U ? 16U : 18U))))); +} + +static void cal_csn_config(int i, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm) +{ + unsigned int intlv_en = 0U; + unsigned int intlv_ctl = 0U; + const unsigned int cs_n_en = 1U; + const unsigned int ap_n_en = popts->cs_odt[i].auto_precharge; + const unsigned int odt_rd_cfg = popts->cs_odt[i].odt_rd_cfg; + const unsigned int odt_wr_cfg = popts->cs_odt[i].odt_wr_cfg; + const unsigned int ba_bits_cs_n = pdimm->bank_addr_bits; + const unsigned int row_bits_cs_n = pdimm->n_row_addr - 12U; + const unsigned int col_bits_cs_n = pdimm->n_col_addr - 8U; + const unsigned int bg_bits_cs_n = pdimm->bank_group_bits; + + if (i == 0) { + /* These fields only available in CS0_CONFIG */ + if (popts->ctlr_intlv != 0) { + switch (popts->ctlr_intlv_mode) { + case DDR_256B_INTLV: + intlv_en = popts->ctlr_intlv; + intlv_ctl = popts->ctlr_intlv_mode; + break; + default: + break; + } + } + } + regs->cs[i].config = ((cs_n_en & 0x1) << 31) | + ((intlv_en & 0x3) << 29) | + ((intlv_ctl & 0xf) << 24) | + ((ap_n_en & 0x1) << 23) | + ((odt_rd_cfg & 0x7) << 20) | + ((odt_wr_cfg & 0x7) << 16) | + ((ba_bits_cs_n & 0x3) << 14) | + ((row_bits_cs_n & 0x7) << 8) | + ((bg_bits_cs_n & 0x3) << 4) | + ((col_bits_cs_n & 0x7) << 0); + debug("cs%d\n", i); + debug(" _config = 0x%x\n", regs->cs[i].config); +} + +static inline int avoid_odt_overlap(const struct ddr_conf *conf, + const struct dimm_params *pdimm) +{ + if ((conf->cs_in_use == 0xf) != 0) { + return 2; + } + +#if DDRC_NUM_DIMM >= 2 + if (conf->dimm_in_use[0] != 0 && conf->dimm_in_use[1] != 0) { + return 1; + } +#endif + return 0; +} + +/* Requires rcw2 set first */ +static void cal_timing_cfg(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm, + const struct ddr_conf *conf, + unsigned int cas_latency, + unsigned int additive_latency) +{ + const unsigned int mclk_ps = get_memory_clk_ps(clk); + /* tXP=max(4nCK, 6ns) */ + const int txp = max((int)mclk_ps * 4, 6000); + /* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */ + static const int wrrec_table[] = { + 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, + 12, 12, 14, 14, 16, + 16, 18, 18, 20, 20, + 24, 24, 24, 24, + }; + int trwt_mclk = (clk / 1000000 > 1900) ? 3 : 2; + int twrt_mclk; + int trrt_mclk; + int twwt_mclk; + const int act_pd_exit_mclk = picos_to_mclk(clk, txp); + const int pre_pd_exit_mclk = act_pd_exit_mclk; + const int taxpd_mclk = 0; + /* + * MRS_CYC = max(tMRD, tMOD) + * tMRD = 8nCK, tMOD = max(24nCK, 15ns) + */ + const int tmrd_mclk = max(24U, picos_to_mclk(clk, 15000)); + const int pretoact_mclk = picos_to_mclk(clk, pdimm->trp_ps); + const int acttopre_mclk = picos_to_mclk(clk, pdimm->tras_ps); + const int acttorw_mclk = picos_to_mclk(clk, pdimm->trcd_ps); + const int caslat_ctrl = (cas_latency - 1) << 1; + const int trfc1_min = pdimm->die_density >= 0x3 ? 16000 : + (pdimm->die_density == 0x4 ? 26000 : + (pdimm->die_density == 0x5 ? 35000 : + 55000)); + const int refrec_ctrl = picos_to_mclk(clk, + pdimm->trfc1_ps) - 8; + int wrrec_mclk = picos_to_mclk(clk, pdimm->twr_ps); + const int acttoact_mclk = max(picos_to_mclk(clk, + pdimm->trrds_ps), + 4U); + int wrtord_mclk = max(2U, picos_to_mclk(clk, 2500)); + const unsigned int cpo = 0U; + const int wr_lat = cal_cwl(clk); + int rd_to_pre = picos_to_mclk(clk, 7500); + const int wr_data_delay = popts->wr_data_delay; + const int cke_pls = max(3U, picos_to_mclk(clk, 5000)); +#ifdef ERRATA_DDR_A050450 + const unsigned short four_act = ((popts->twot_en == 0) && + (popts->threet_en == 0) && + (popts->tfaw_ps % 2 == 0)) ? + (picos_to_mclk(clk, popts->tfaw_ps) + 1) : + picos_to_mclk(clk, popts->tfaw_ps); +#else + const unsigned short four_act = picos_to_mclk(clk, + popts->tfaw_ps); +#endif + const unsigned int cntl_adj = 0U; + const unsigned int ext_pretoact = picos_to_mclk(clk, + pdimm->trp_ps) >> 4U; + const unsigned int ext_acttopre = picos_to_mclk(clk, + pdimm->tras_ps) >> 4U; + const unsigned int ext_acttorw = picos_to_mclk(clk, + pdimm->trcd_ps) >> 4U; + const unsigned int ext_caslat = (2U * cas_latency - 1U) >> 4U; + const unsigned int ext_add_lat = additive_latency >> 4U; + const unsigned int ext_refrec = (picos_to_mclk(clk, + pdimm->trfc1_ps) - 8U) >> 4U; + const unsigned int ext_wrrec = (picos_to_mclk(clk, pdimm->twr_ps) + + (popts->otf_burst_chop_en ? 2U : 0U)) >> 4U; + const unsigned int rwt_same_cs = 0U; + const unsigned int wrt_same_cs = 0U; + const unsigned int rrt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U; + const unsigned int wwt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U; + const unsigned int dll_lock = 2U; + unsigned int rodt_on = 0U; + const unsigned int rodt_off = 4U; + const unsigned int wodt_on = 1U; + const unsigned int wodt_off = 4U; + const unsigned int hs_caslat = 0U; + const unsigned int hs_wrlat = 0U; + const unsigned int hs_wrrec = 0U; + const unsigned int hs_clkadj = 0U; + const unsigned int hs_wrlvl_start = 0U; + const unsigned int txpr = max(5U, + picos_to_mclk(clk, + pdimm->trfc1_ps + 10000U)); + const unsigned int tcksre = max(5U, picos_to_mclk(clk, 10000U)); + const unsigned int tcksrx = max(5U, picos_to_mclk(clk, 10000U)); + const unsigned int cs_to_cmd = 0U; + const unsigned int cke_rst = txpr <= 200U ? 0U : + (txpr <= 256U ? 1U : + (txpr <= 512U ? 2U : 3U)); + const unsigned int cksre = tcksre <= 19U ? tcksre - 5U : 15U; + const unsigned int cksrx = tcksrx <= 19U ? tcksrx - 5U : 15U; + unsigned int par_lat = 0U; + const int tccdl = max(5U, picos_to_mclk(clk, pdimm->tccdl_ps)); + int rwt_bg = cas_latency + 2 + 4 - wr_lat; + int wrt_bg = wr_lat + 4 + 1 - cas_latency; + const int rrt_bg = popts->burst_length == DDR_BL8 ? + tccdl - 4 : tccdl - 2; + const int wwt_bg = popts->burst_length == DDR_BL8 ? + tccdl - 4 : tccdl - 2; + const unsigned int acttoact_bg = picos_to_mclk(clk, pdimm->trrdl_ps); + const unsigned int wrtord_bg = max(4U, picos_to_mclk(clk, 7500)) + + (popts->otf_burst_chop_en ? 2 : 0); + const unsigned int pre_all_rec = 0; + const unsigned int refrec_cid_mclk = pdimm->package_3ds ? + picos_to_mclk(clk, pdimm->trfc_slr_ps) : 0; + const unsigned int acttoact_cid_mclk = pdimm->package_3ds ? 4U : 0; + + + /* for two dual-rank DIMMs to avoid ODT overlap */ + if (avoid_odt_overlap(conf, pdimm) == 2) { + twrt_mclk = 2; + twwt_mclk = 2; + trrt_mclk = 2; + } else { + twrt_mclk = 1; + twwt_mclk = 1; + trrt_mclk = 0; + } + + if (popts->trwt_override != 0) { + trwt_mclk = popts->trwt; + if (popts->twrt != 0) { + twrt_mclk = popts->twrt; + } + if (popts->trrt != 0) { + trrt_mclk = popts->trrt; + } + if (popts->twwt != 0) { + twwt_mclk = popts->twwt; + } + } + regs->timing_cfg[0] = (((trwt_mclk & 0x3) << 30) | + ((twrt_mclk & 0x3) << 28) | + ((trrt_mclk & 0x3) << 26) | + ((twwt_mclk & 0x3) << 24) | + ((act_pd_exit_mclk & 0xf) << 20) | + ((pre_pd_exit_mclk & 0xF) << 16) | + ((taxpd_mclk & 0xf) << 8) | + ((tmrd_mclk & 0x1f) << 0)); + debug("timing_cfg[0] = 0x%x\n", regs->timing_cfg[0]); + + if ((wrrec_mclk < 1) || (wrrec_mclk > 24)) { + ERROR("WRREC doesn't support clock %d\n", wrrec_mclk); + } else { + wrrec_mclk = wrrec_table[wrrec_mclk - 1]; + } + + if (popts->otf_burst_chop_en != 0) { + wrrec_mclk += 2; + wrtord_mclk += 2; + } + + if (pdimm->trfc1_ps < trfc1_min) { + ERROR("trfc1_ps (%d) < %d\n", pdimm->trfc1_ps, trfc1_min); + } + + regs->timing_cfg[1] = (((pretoact_mclk & 0x0F) << 28) | + ((acttopre_mclk & 0x0F) << 24) | + ((acttorw_mclk & 0xF) << 20) | + ((caslat_ctrl & 0xF) << 16) | + ((refrec_ctrl & 0xF) << 12) | + ((wrrec_mclk & 0x0F) << 8) | + ((acttoact_mclk & 0x0F) << 4) | + ((wrtord_mclk & 0x0F) << 0)); + debug("timing_cfg[1] = 0x%x\n", regs->timing_cfg[1]); + + if (rd_to_pre < 4) { + rd_to_pre = 4; + } + if (popts->otf_burst_chop_en) { + rd_to_pre += 2; + } + + regs->timing_cfg[2] = (((additive_latency & 0xf) << 28) | + ((cpo & 0x1f) << 23) | + ((wr_lat & 0xf) << 19) | + (((wr_lat & 0x10) >> 4) << 18) | + ((rd_to_pre & 0xf) << 13) | + ((wr_data_delay & 0xf) << 9) | + ((cke_pls & 0x7) << 6) | + ((four_act & 0x3f) << 0)); + debug("timing_cfg[2] = 0x%x\n", regs->timing_cfg[2]); + + regs->timing_cfg[3] = (((ext_pretoact & 0x1) << 28) | + ((ext_acttopre & 0x3) << 24) | + ((ext_acttorw & 0x1) << 22) | + ((ext_refrec & 0x3F) << 16) | + ((ext_caslat & 0x3) << 12) | + ((ext_add_lat & 0x1) << 10) | + ((ext_wrrec & 0x1) << 8) | + ((cntl_adj & 0x7) << 0)); + debug("timing_cfg[3] = 0x%x\n", regs->timing_cfg[3]); + + regs->timing_cfg[4] = (((rwt_same_cs & 0xf) << 28) | + ((wrt_same_cs & 0xf) << 24) | + ((rrt_same_cs & 0xf) << 20) | + ((wwt_same_cs & 0xf) << 16) | + ((trwt_mclk & 0xc) << 12) | + ((twrt_mclk & 0x4) << 10) | + ((trrt_mclk & 0x4) << 8) | + ((twwt_mclk & 0x4) << 6) | + (dll_lock & 0x3)); + debug("timing_cfg[4] = 0x%x\n", regs->timing_cfg[4]); + + /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */ + if (cas_latency >= wr_lat) { + rodt_on = cas_latency - wr_lat + 1; + } + + regs->timing_cfg[5] = (((rodt_on & 0x1f) << 24) | + ((rodt_off & 0x7) << 20) | + ((wodt_on & 0x1f) << 12) | + (wodt_off & 0x7) << 8); + debug("timing_cfg[5] = 0x%x\n", regs->timing_cfg[5]); + + regs->timing_cfg[6] = (((hs_caslat & 0x1f) << 24) | + ((hs_wrlat & 0x1f) << 19) | + ((hs_wrrec & 0x1f) << 12) | + ((hs_clkadj & 0x1f) << 6) | + ((hs_wrlvl_start & 0x1f) << 0)); + debug("timing_cfg[6] = 0x%x\n", regs->timing_cfg[6]); + + if (popts->ap_en != 0) { + par_lat = (regs->sdram_rcw[1] & 0xf) + 1; + debug("PAR_LAT = 0x%x\n", par_lat); + } + + regs->timing_cfg[7] = (((cke_rst & 0x3) << 28) | + ((cksre & 0xf) << 24) | + ((cksrx & 0xf) << 20) | + ((par_lat & 0xf) << 16) | + ((cs_to_cmd & 0xf) << 4)); + debug("timing_cfg[7] = 0x%x\n", regs->timing_cfg[7]); + + if (rwt_bg < tccdl) { + rwt_bg = tccdl - rwt_bg; + } else { + rwt_bg = 0; + } + if (wrt_bg < tccdl) { + wrt_bg = tccdl - wrt_bg; + } else { + wrt_bg = 0; + } + regs->timing_cfg[8] = (((rwt_bg & 0xf) << 28) | + ((wrt_bg & 0xf) << 24) | + ((rrt_bg & 0xf) << 20) | + ((wwt_bg & 0xf) << 16) | + ((acttoact_bg & 0xf) << 12) | + ((wrtord_bg & 0xf) << 8) | + ((pre_all_rec & 0x1f) << 0)); + debug("timing_cfg[8] = 0x%x\n", regs->timing_cfg[8]); + + regs->timing_cfg[9] = (refrec_cid_mclk & 0x3ff) << 16 | + (acttoact_cid_mclk & 0xf) << 8; + debug("timing_cfg[9] = 0x%x\n", regs->timing_cfg[9]); +} + +static void cal_ddr_sdram_rcw(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm) +{ + const unsigned int freq = clk / 1000000U; + unsigned int rc0a, rc0f; + + if (pdimm->rdimm == 0) { + return; + } + + rc0a = freq > 3200U ? 7U : + (freq > 2933U ? 6U : + (freq > 2666U ? 5U : + (freq > 2400U ? 4U : + (freq > 2133U ? 3U : + (freq > 1866U ? 2U : + (freq > 1600U ? 1U : 0U)))))); + rc0f = freq > 3200U ? 3U : + (freq > 2400U ? 2U : + (freq > 2133U ? 1U : 0U)); + rc0f = (regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) ? rc0f : 4; + regs->sdram_rcw[0] = + pdimm->rcw[0] << 28 | + pdimm->rcw[1] << 24 | + pdimm->rcw[2] << 20 | + pdimm->rcw[3] << 16 | + pdimm->rcw[4] << 12 | + pdimm->rcw[5] << 8 | + pdimm->rcw[6] << 4 | + pdimm->rcw[7]; + regs->sdram_rcw[1] = + pdimm->rcw[8] << 28 | + pdimm->rcw[9] << 24 | + rc0a << 20 | + pdimm->rcw[11] << 16 | + pdimm->rcw[12] << 12 | + pdimm->rcw[13] << 8 | + pdimm->rcw[14] << 4 | + rc0f; + regs->sdram_rcw[2] = + ((freq - 1260 + 19) / 20) << 8; + + debug("sdram_rcw[0] = 0x%x\n", regs->sdram_rcw[0]); + debug("sdram_rcw[1] = 0x%x\n", regs->sdram_rcw[1]); + debug("sdram_rcw[2] = 0x%x\n", regs->sdram_rcw[2]); +} + +static void cal_ddr_sdram_cfg(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm, + const unsigned int ip_rev) +{ + const unsigned int mem_en = 1U; + const unsigned int sren = popts->self_refresh_in_sleep; + const unsigned int ecc_en = popts->ecc_mode; + const unsigned int rd_en = (pdimm->rdimm != 0U) ? 1U : 0U; + const unsigned int dyn_pwr = popts->dynamic_power; + const unsigned int dbw = popts->data_bus_used; + const unsigned int eight_be = (dbw == 1U || + popts->burst_length == DDR_BL8) ? 1U : 0U; + const unsigned int ncap = 0U; + const unsigned int threet_en = popts->threet_en; + const unsigned int twot_en = pdimm->rdimm ? + 0U : popts->twot_en; + const unsigned int ba_intlv = popts->ba_intlv; + const unsigned int x32_en = 0U; + const unsigned int pchb8 = 0U; + const unsigned int hse = popts->half_strength_drive_en; + const unsigned int acc_ecc_en = (dbw != 0U && ecc_en == 1U) ? 1U : 0U; + const unsigned int mem_halt = 0U; +#ifdef PHY_GEN2 + const unsigned int bi = 1U; +#else + const unsigned int bi = 0U; +#endif + const unsigned int sdram_type = SDRAM_TYPE_DDR4; + unsigned int odt_cfg = 0U; + const unsigned int frc_sr = 0U; + const unsigned int sr_ie = popts->self_refresh_irq_en; + const unsigned int num_pr = pdimm->package_3ds + 1U; + const unsigned int slow = (clk < 1249000000U) ? 1U : 0U; + const unsigned int x4_en = popts->x4_en; + const unsigned int obc_cfg = popts->otf_burst_chop_en; + const unsigned int ap_en = ip_rev == 0x50500U ? 0U : popts->ap_en; + const unsigned int d_init = popts->ctlr_init_ecc; + const unsigned int rcw_en = popts->rdimm; + const unsigned int md_en = popts->mirrored_dimm; + const unsigned int qd_en = popts->quad_rank_present; + const unsigned int unq_mrs_en = ip_rev < 0x50500U ? 1U : 0U; + const unsigned int rd_pre = popts->quad_rank_present; + int i; + + regs->sdram_cfg[0] = ((mem_en & 0x1) << 31) | + ((sren & 0x1) << 30) | + ((ecc_en & 0x1) << 29) | + ((rd_en & 0x1) << 28) | + ((sdram_type & 0x7) << 24) | + ((dyn_pwr & 0x1) << 21) | + ((dbw & 0x3) << 19) | + ((eight_be & 0x1) << 18) | + ((ncap & 0x1) << 17) | + ((threet_en & 0x1) << 16) | + ((twot_en & 0x1) << 15) | + ((ba_intlv & 0x7F) << 8) | + ((x32_en & 0x1) << 5) | + ((pchb8 & 0x1) << 4) | + ((hse & 0x1) << 3) | + ((acc_ecc_en & 0x1) << 2) | + ((mem_halt & 0x1) << 1) | + ((bi & 0x1) << 0); + debug("sdram_cfg[0] = 0x%x\n", regs->sdram_cfg[0]); + + for (i = 0; i < DDRC_NUM_CS; i++) { + if (popts->cs_odt[i].odt_rd_cfg != 0 || + popts->cs_odt[i].odt_wr_cfg != 0) { + odt_cfg = SDRAM_CFG2_ODT_ONLY_READ; + break; + } + } + + regs->sdram_cfg[1] = (0 + | ((frc_sr & 0x1) << 31) + | ((sr_ie & 0x1) << 30) + | ((odt_cfg & 0x3) << 21) + | ((num_pr & 0xf) << 12) + | ((slow & 1) << 11) + | (x4_en << 10) + | (qd_en << 9) + | (unq_mrs_en << 8) + | ((obc_cfg & 0x1) << 6) + | ((ap_en & 0x1) << 5) + | ((d_init & 0x1) << 4) + | ((rcw_en & 0x1) << 2) + | ((md_en & 0x1) << 0) + ); + debug("sdram_cfg[1] = 0x%x\n", regs->sdram_cfg[1]); + + regs->sdram_cfg[2] = (rd_pre & 0x1) << 16 | + (popts->rdimm ? 1 : 0); + if (pdimm->package_3ds != 0) { + if (((pdimm->package_3ds + 1) & 0x1) != 0) { + WARN("Unsupported 3DS DIMM\n"); + } else { + regs->sdram_cfg[2] |= ((pdimm->package_3ds + 1) >> 1) + << 4; + } + } + debug("sdram_cfg[2] = 0x%x\n", regs->sdram_cfg[2]); +} + + +static void cal_ddr_sdram_interval(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm) +{ + const unsigned int refint = picos_to_mclk(clk, pdimm->refresh_rate_ps); + const unsigned int bstopre = popts->bstopre; + + regs->interval = ((refint & 0xFFFF) << 16) | + ((bstopre & 0x3FFF) << 0); + debug("interval = 0x%x\n", regs->interval); +} + +/* Require cs and cfg first */ +static void cal_ddr_sdram_mode(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct ddr_conf *conf, + const struct dimm_params *pdimm, + unsigned int cas_latency, + unsigned int additive_latency, + const unsigned int ip_rev) +{ + int i; + unsigned short esdmode; /* Extended SDRAM mode */ + unsigned short sdmode; /* SDRAM mode */ + + /* Mode Register - MR1 */ + const unsigned int qoff = 0; + const unsigned int tdqs_en = 0; + unsigned int rtt; + const unsigned int wrlvl_en = 0; + unsigned int al = 0; + unsigned int dic = 0; + const unsigned int dll_en = 1; + + /* Mode Register - MR0 */ + unsigned int wr = 0; + const unsigned int dll_rst = 0; + const unsigned int mode = 0; + unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */ + /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */ + const unsigned int bt = 0; + const unsigned int bl = popts->burst_length == DDR_BL8 ? 0 : + (popts->burst_length == DDR_BC4 ? 2 : 1); + + const unsigned int wr_mclk = picos_to_mclk(clk, pdimm->twr_ps); + /* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */ + static const int wr_table[] = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6 + }; + /* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */ + static const int cas_latency_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 13, 8, + 14, 9, 15, 10, 12, 11, 16, 17, + 18, 19, 20, 21, 22, 23 + }; + const unsigned int unq_mrs_en = ip_rev < U(0x50500) ? 1U : 0U; + unsigned short esdmode2 = 0U; + unsigned short esdmode3 = 0U; + const unsigned int wr_crc = 0U; + unsigned int rtt_wr = 0U; + const unsigned int srt = 0U; + unsigned int cwl = cal_cwl(clk); + const unsigned int mpr = 0U; + const unsigned int mclk_ps = get_memory_clk_ps(clk); + const unsigned int wc_lat = 0U; + unsigned short esdmode4 = 0U; + unsigned short esdmode5; + int rtt_park_all = 0; + unsigned int rtt_park; + const bool four_cs = conf->cs_in_use == 0xf ? true : false; + unsigned short esdmode6 = 0U; /* Extended SDRAM mode 6 */ + unsigned short esdmode7 = 0U; /* Extended SDRAM mode 7 */ + const unsigned int tccdl_min = max(5U, + picos_to_mclk(clk, pdimm->tccdl_ps)); + + if (popts->rtt_override != 0U) { + rtt = popts->rtt_override_value; + } else { + rtt = popts->cs_odt[0].odt_rtt_norm; + } + + if (additive_latency == (cas_latency - 1)) { + al = 1; + } + if (additive_latency == (cas_latency - 2)) { + al = 2; + } + + if (popts->quad_rank_present != 0 || popts->output_driver_impedance != 0) { + dic = 1; /* output driver impedance 240/7 ohm */ + } + + esdmode = (((qoff & 0x1) << 12) | + ((tdqs_en & 0x1) << 11) | + ((rtt & 0x7) << 8) | + ((wrlvl_en & 0x1) << 7) | + ((al & 0x3) << 3) | + ((dic & 0x3) << 1) | + ((dll_en & 0x1) << 0)); + + if (wr_mclk >= 10 && wr_mclk <= 24) { + wr = wr_table[wr_mclk - 10]; + } else { + ERROR("unsupported wc_mclk = %d for mode register\n", wr_mclk); + } + + /* look up table to get the cas latency bits */ + if (cas_latency >= 9 && cas_latency <= 32) { + caslat = cas_latency_table[cas_latency - 9]; + } else { + WARN("Error: unsupported cas latency for mode register\n"); + } + + sdmode = (((caslat & 0x10) << 8) | + ((wr & 0x7) << 9) | + ((dll_rst & 0x1) << 8) | + ((mode & 0x1) << 7) | + (((caslat >> 1) & 0x7) << 4) | + ((bt & 0x1) << 3) | + ((caslat & 1) << 2) | + ((bl & 0x3) << 0)); + + regs->sdram_mode[0] = (((esdmode & 0xFFFF) << 16) | + ((sdmode & 0xFFFF) << 0)); + debug("sdram_mode[0] = 0x%x\n", regs->sdram_mode[0]); + + switch (cwl) { + case 9: + case 10: + case 11: + case 12: + cwl -= 9; + break; + case 14: + cwl -= 10; + break; + case 16: + cwl -= 11; + break; + case 18: + cwl -= 12; + break; + case 20: + cwl -= 13; + break; + default: + printf("Error CWL\n"); + break; + } + + if (popts->rtt_override != 0) { + rtt_wr = popts->rtt_wr_override_value; + } else { + rtt_wr = popts->cs_odt[0].odt_rtt_wr; + } + + esdmode2 = ((wr_crc & 0x1) << 12) | + ((rtt_wr & 0x7) << 9) | + ((srt & 0x3) << 6) | + ((cwl & 0x7) << 3); + esdmode3 = ((mpr & 0x3) << 11) | ((wc_lat & 0x3) << 9); + + regs->sdram_mode[1] = ((esdmode2 & 0xFFFF) << 16) | + ((esdmode3 & 0xFFFF) << 0); + debug("sdram_mode[1] = 0x%x\n", regs->sdram_mode[1]); + + esdmode6 = ((tccdl_min - 4) & 0x7) << 10; + if (popts->vref_dimm != 0) { + esdmode6 |= popts->vref_dimm & 0x7f; + } else if ((popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2) != 0) { + esdmode6 |= 1 << 6; /* Range 2 */ + } + + regs->sdram_mode[9] = ((esdmode6 & 0xffff) << 16) | + ((esdmode7 & 0xffff) << 0); + debug("sdram_mode[9] = 0x%x\n", regs->sdram_mode[9]); + + rtt_park = (popts->rtt_park != 0) ? popts->rtt_park : 240; + switch (rtt_park) { + case 240: + rtt_park = 0x4; + break; + case 120: + rtt_park = 0x2; + break; + case 80: + rtt_park = 0x6; + break; + case 60: + rtt_park = 0x1; + break; + case 48: + rtt_park = 0x5; + break; + case 40: + rtt_park = 0x3; + break; + case 34: + rtt_park = 0x7; + break; + default: + rtt_park = 0; + break; + } + + for (i = 0; i < DDRC_NUM_CS; i++) { + if (i != 0 && unq_mrs_en == 0) { + break; + } + + if (popts->rtt_override != 0) { + rtt = popts->rtt_override_value; + rtt_wr = popts->rtt_wr_override_value; + } else { + rtt = popts->cs_odt[i].odt_rtt_norm; + rtt_wr = popts->cs_odt[i].odt_rtt_wr; + } + + esdmode &= 0xF8FF; /* clear bit 10,9,8 for rtt */ + esdmode |= (rtt & 0x7) << 8; + esdmode2 &= 0xF9FF; /* clear bit 10, 9 */ + esdmode2 |= (rtt_wr & 0x3) << 9; + esdmode5 = (popts->x4_en) ? 0 : 0x400; /* data mask */ + + if (rtt_park_all == 0 && + ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) != 0)) { + esdmode5 |= rtt_park << 6; + rtt_park_all = four_cs ? 0 : 1; + } + + if (((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) && + (popts->rdimm == 0)) { + if (mclk_ps >= 935) { + esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; + } else if (mclk_ps >= 833) { + esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; + } else { + esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; + WARN("mclk_ps not supported %d", mclk_ps); + + } + } + + switch (i) { + case 0: + regs->sdram_mode[8] = ((esdmode4 & 0xffff) << 16) | + ((esdmode5 & 0xffff) << 0); + debug("sdram_mode[8] = 0x%x\n", regs->sdram_mode[8]); + break; + case 1: + regs->sdram_mode[2] = (((esdmode & 0xFFFF) << 16) | + ((sdmode & 0xFFFF) << 0)); + regs->sdram_mode[3] = ((esdmode2 & 0xFFFF) << 16) | + ((esdmode3 & 0xFFFF) << 0); + regs->sdram_mode[10] = ((esdmode4 & 0xFFFF) << 16) | + ((esdmode5 & 0xFFFF) << 0); + regs->sdram_mode[11] = ((esdmode6 & 0xFFFF) << 16) | + ((esdmode7 & 0xFFFF) << 0); + debug("sdram_mode[2] = 0x%x\n", regs->sdram_mode[2]); + debug("sdram_mode[3] = 0x%x\n", regs->sdram_mode[3]); + debug("sdram_mode[10] = 0x%x\n", regs->sdram_mode[10]); + debug("sdram_mode[11] = 0x%x\n", regs->sdram_mode[11]); + break; + case 2: + regs->sdram_mode[4] = (((esdmode & 0xFFFF) << 16) | + ((sdmode & 0xFFFF) << 0)); + regs->sdram_mode[5] = ((esdmode2 & 0xFFFF) << 16) | + ((esdmode3 & 0xFFFF) << 0); + regs->sdram_mode[12] = ((esdmode4 & 0xFFFF) << 16) | + ((esdmode5 & 0xFFFF) << 0); + regs->sdram_mode[13] = ((esdmode6 & 0xFFFF) << 16) | + ((esdmode7 & 0xFFFF) << 0); + debug("sdram_mode[4] = 0x%x\n", regs->sdram_mode[4]); + debug("sdram_mode[5] = 0x%x\n", regs->sdram_mode[5]); + debug("sdram_mode[12] = 0x%x\n", regs->sdram_mode[12]); + debug("sdram_mode[13] = 0x%x\n", regs->sdram_mode[13]); + break; + case 3: + regs->sdram_mode[6] = (((esdmode & 0xFFFF) << 16) | + ((sdmode & 0xFFFF) << 0)); + regs->sdram_mode[7] = ((esdmode2 & 0xFFFF) << 16) | + ((esdmode3 & 0xFFFF) << 0); + regs->sdram_mode[14] = ((esdmode4 & 0xFFFF) << 16) | + ((esdmode5 & 0xFFFF) << 0); + regs->sdram_mode[15] = ((esdmode6 & 0xFFFF) << 16) | + ((esdmode7 & 0xFFFF) << 0); + debug("sdram_mode[6] = 0x%x\n", regs->sdram_mode[6]); + debug("sdram_mode[7] = 0x%x\n", regs->sdram_mode[7]); + debug("sdram_mode[14] = 0x%x\n", regs->sdram_mode[14]); + debug("sdram_mode[15] = 0x%x\n", regs->sdram_mode[15]); + break; + default: + break; + } + } +} + +#ifndef CONFIG_MEM_INIT_VALUE +#define CONFIG_MEM_INIT_VALUE 0xDEADBEEF +#endif +static void cal_ddr_data_init(struct ddr_cfg_regs *regs) +{ + regs->data_init = CONFIG_MEM_INIT_VALUE; +} + +static void cal_ddr_dq_mapping(struct ddr_cfg_regs *regs, + const struct dimm_params *pdimm) +{ + const unsigned int acc_ecc_en = (regs->sdram_cfg[0] >> 2) & 0x1; +/* FIXME: revert the dq mapping from DIMM */ + regs->dq_map[0] = ((pdimm->dq_mapping[0] & 0x3F) << 26) | + ((pdimm->dq_mapping[1] & 0x3F) << 20) | + ((pdimm->dq_mapping[2] & 0x3F) << 14) | + ((pdimm->dq_mapping[3] & 0x3F) << 8) | + ((pdimm->dq_mapping[4] & 0x3F) << 2); + + regs->dq_map[1] = ((pdimm->dq_mapping[5] & 0x3F) << 26) | + ((pdimm->dq_mapping[6] & 0x3F) << 20) | + ((pdimm->dq_mapping[7] & 0x3F) << 14) | + ((pdimm->dq_mapping[10] & 0x3F) << 8) | + ((pdimm->dq_mapping[11] & 0x3F) << 2); + + regs->dq_map[2] = ((pdimm->dq_mapping[12] & 0x3F) << 26) | + ((pdimm->dq_mapping[13] & 0x3F) << 20) | + ((pdimm->dq_mapping[14] & 0x3F) << 14) | + ((pdimm->dq_mapping[15] & 0x3F) << 8) | + ((pdimm->dq_mapping[16] & 0x3F) << 2); + + /* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */ + regs->dq_map[3] = ((pdimm->dq_mapping[17] & 0x3F) << 26) | + ((pdimm->dq_mapping[8] & 0x3F) << 20) | + ((acc_ecc_en != 0) ? 0 : + (pdimm->dq_mapping[9] & 0x3F) << 14) | + pdimm->dq_mapping_ors; + debug("dq_map[0] = 0x%x\n", regs->dq_map[0]); + debug("dq_map[1] = 0x%x\n", regs->dq_map[1]); + debug("dq_map[2] = 0x%x\n", regs->dq_map[2]); + debug("dq_map[3] = 0x%x\n", regs->dq_map[3]); +} +static void cal_ddr_zq_cntl(struct ddr_cfg_regs *regs) +{ + const unsigned int zqinit = 10U; /* 1024 clocks */ + const unsigned int zqoper = 9U; /* 512 clocks */ + const unsigned int zqcs = 7U; /* 128 clocks */ + const unsigned int zqcs_init = 5U; /* 1024 refresh seqences */ + const unsigned int zq_en = 1U; /* enabled */ + + regs->zq_cntl = ((zq_en & 0x1) << 31) | + ((zqinit & 0xF) << 24) | + ((zqoper & 0xF) << 16) | + ((zqcs & 0xF) << 8) | + ((zqcs_init & 0xF) << 0); + debug("zq_cntl = 0x%x\n", regs->zq_cntl); +} + +static void cal_ddr_sr_cntr(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + const unsigned int sr_it = (popts->auto_self_refresh_en) ? + popts->sr_it : 0; + + regs->ddr_sr_cntr = (sr_it & 0xF) << 16; + debug("ddr_sr_cntr = 0x%x\n", regs->ddr_sr_cntr); +} + +static void cal_ddr_eor(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + if (popts->addr_hash != 0) { + regs->eor = 0x40000000; /* address hash enable */ + debug("eor = 0x%x\n", regs->eor); + } +} + +static void cal_ddr_csn_bnds(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct ddr_conf *conf, + const struct dimm_params *pdimm) +{ + int i; + unsigned long long ea, sa; + + /* Chip Select Memory Bounds (CSn_BNDS) */ + for (i = 0; + i < DDRC_NUM_CS && conf->cs_size[i]; + i++) { + debug("cs_in_use = 0x%x\n", conf->cs_in_use); + if (conf->cs_in_use != 0) { + sa = conf->cs_base_addr[i]; + ea = sa + conf->cs_size[i] - 1; + sa >>= 24; + ea >>= 24; + regs->cs[i].bnds = ((sa & 0xffff) << 16) | + ((ea & 0xffff) << 0); + cal_csn_config(i, regs, popts, pdimm); + } else { + /* setting bnds to 0xffffffff for inactive CS */ + regs->cs[i].bnds = 0xffffffff; + } + + debug("cs[%d].bnds = 0x%x\n", i, regs->cs[i].bnds); + } +} + +static void cal_ddr_addr_dec(struct ddr_cfg_regs *regs) +{ +#ifdef CONFIG_DDR_ADDR_DEC + unsigned int ba_bits __unused; + char p __unused; + const unsigned int cs0_config = regs->cs[0].config; + const int cacheline = PLATFORM_CACHE_LINE_SHIFT; + unsigned int bg_bits; + unsigned int row_bits; + unsigned int col_bits; + unsigned int cs; + unsigned int map_row[18]; + unsigned int map_col[11]; + unsigned int map_ba[2]; + unsigned int map_cid[2] = {0x3F, 0x3F}; + unsigned int map_bg[2] = {0x3F, 0x3F}; + unsigned int map_cs[2] = {0x3F, 0x3F}; + unsigned int dbw; + unsigned int ba_intlv; + int placement; + int intlv; + int abort = 0; + int i; + int j; + + col_bits = (cs0_config >> 0) & 0x7; + if (col_bits < 4) { + col_bits += 8; + } else if (col_bits < 7 || col_bits > 10) { + ERROR("Error %s col_bits = %d\n", __func__, col_bits); + } + row_bits = ((cs0_config >> 8) & 0x7) + 12; + ba_bits = ((cs0_config >> 14) & 0x3) + 2; + bg_bits = ((cs0_config >> 4) & 0x3) + 0; + intlv = (cs0_config >> 24) & 0xf; + ba_intlv = (regs->sdram_cfg[0] >> 8) & 0x7f; + switch (ba_intlv) { + case DDR_BA_INTLV_CS01: + cs = 1; + break; + case DDR_BA_INTLV_CS0123: + cs = 2; + break; + case DDR_BA_NONE: + cs = 0; + break; + default: + ERROR("%s ba_intlv 0x%x\n", __func__, ba_intlv); + return; + } + debug("col %d, row %d, ba %d, bg %d, intlv %d\n", + col_bits, row_bits, ba_bits, bg_bits, intlv); + /* + * Example mapping of 15x2x2x10 + * ---- --rr rrrr rrrr rrrr rCBB Gccc cccI cGcc cbbb + */ + dbw = (regs->sdram_cfg[0] >> 19) & 0x3; + switch (dbw) { + case 0: /* 64-bit */ + placement = 3; + break; + case 1: /* 32-bit */ + placement = 2; + break; + default: + ERROR("%s dbw = %d\n", __func__, dbw); + return; + } + debug("cacheline size %d\n", cacheline); + for (i = 0; placement < cacheline; i++) { + map_col[i] = placement++; + } + map_bg[0] = placement++; + for ( ; i < col_bits; i++) { + map_col[i] = placement++; + if (placement == intlv) { + placement++; + } + } + for ( ; i < 11; i++) { + map_col[i] = 0x3F; /* unused col bits */ + } + + if (bg_bits >= 2) { + map_bg[1] = placement++; + } + map_ba[0] = placement++; + map_ba[1] = placement++; + if (cs != 0U) { + map_cs[0] = placement++; + if (cs == 2U) { + map_cs[1] = placement++; + } + } else { + map_cs[0] = U(0x3F); + } + + for (i = 0; i < row_bits; i++) { + map_row[i] = placement++; + } + + for ( ; i < 18; i++) { + map_row[i] = 0x3F; /* unused row bits */ + } + + for (i = 39; i >= 0 ; i--) { + if (i == intlv) { + placement = 8; + p = 'I'; + } else if (i < 3) { + p = 'b'; + placement = 0; + } else { + placement = 0; + p = '-'; + } + for (j = 0; j < 18; j++) { + if (map_row[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'r'; + } + for (j = 0; j < 11; j++) { + if (map_col[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'c'; + } + for (j = 0; j < 2; j++) { + if (map_ba[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'B'; + } + for (j = 0; j < 2; j++) { + if (map_bg[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'G'; + } + for (j = 0; j < 2; j++) { + if (map_cs[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'C'; + } +#ifdef DDR_DEBUG + printf("%c", p); + if ((i % 4) == 0) { + printf(" "); + } +#endif + } +#ifdef DDR_DEBUG + puts("\n"); +#endif + + if (abort != 0) { + return; + } + + regs->dec[0] = map_row[17] << 26 | + map_row[16] << 18 | + map_row[15] << 10 | + map_row[14] << 2; + regs->dec[1] = map_row[13] << 26 | + map_row[12] << 18 | + map_row[11] << 10 | + map_row[10] << 2; + regs->dec[2] = map_row[9] << 26 | + map_row[8] << 18 | + map_row[7] << 10 | + map_row[6] << 2; + regs->dec[3] = map_row[5] << 26 | + map_row[4] << 18 | + map_row[3] << 10 | + map_row[2] << 2; + regs->dec[4] = map_row[1] << 26 | + map_row[0] << 18 | + map_col[10] << 10 | + map_col[9] << 2; + regs->dec[5] = map_col[8] << 26 | + map_col[7] << 18 | + map_col[6] << 10 | + map_col[5] << 2; + regs->dec[6] = map_col[4] << 26 | + map_col[3] << 18 | + map_col[2] << 10 | + map_col[1] << 2; + regs->dec[7] = map_col[0] << 26 | + map_ba[1] << 18 | + map_ba[0] << 10 | + map_cid[1] << 2; + regs->dec[8] = map_cid[1] << 26 | + map_cs[1] << 18 | + map_cs[0] << 10 | + map_bg[1] << 2; + regs->dec[9] = map_bg[0] << 26 | + 1; + for (i = 0; i < 10; i++) { + debug("dec[%d] = 0x%x\n", i, regs->dec[i]); + } +#endif +} +static unsigned int skip_caslat(unsigned int tckmin_ps, + unsigned int taamin_ps, + unsigned int mclk_ps, + unsigned int package_3ds) +{ + int i, j, k; + struct cas { + const unsigned int tckmin_ps; + const unsigned int caslat[4]; + }; + struct speed { + const struct cas *cl; + const unsigned int taamin_ps[4]; + }; + const struct cas cl_3200[] = { + {625, {0xa00000, 0xb00000, 0xf000000,} }, + {750, { 0x20000, 0x60000, 0xe00000,} }, + {833, { 0x8000, 0x18000, 0x38000,} }, + {937, { 0x4000, 0x4000, 0xc000,} }, + {1071, { 0x1000, 0x1000, 0x3000,} }, + {1250, { 0x400, 0x400, 0xc00,} }, + {1500, { 0, 0x600, 0x200,} }, + }; + const struct cas cl_2933[] = { + {682, { 0, 0x80000, 0x180000, 0x380000} }, + {750, { 0x20000, 0x60000, 0x60000, 0xe0000} }, + {833, { 0x8000, 0x18000, 0x18000, 0x38000} }, + {937, { 0x4000, 0x4000, 0x4000, 0xc000} }, + {1071, { 0x1000, 0x1000, 0x1000, 0x3000} }, + {1250, { 0x400, 0x400, 0x400, 0xc00} }, + {1500, { 0, 0x200, 0x200, 0x200} }, + }; + const struct cas cl_2666[] = { + {750, { 0, 0x20000, 0x60000, 0xe0000} }, + {833, { 0x8000, 0x18000, 0x18000, 0x38000} }, + {937, { 0x4000, 0x4000, 0x4000, 0xc000} }, + {1071, { 0x1000, 0x1000, 0x1000, 0x3000} }, + {1250, { 0x400, 0x400, 0x400, 0xc00} }, + {1500, { 0, 0, 0x200, 0x200} }, + }; + const struct cas cl_2400[] = { + {833, { 0, 0x8000, 0x18000, 0x38000} }, + {937, { 0xc000, 0x4000, 0x4000, 0xc000} }, + {1071, { 0x3000, 0x1000, 0x1000, 0x3000} }, + {1250, { 0xc00, 0x400, 0x400, 0xc00} }, + {1500, { 0, 0x400, 0x200, 0x200} }, + }; + const struct cas cl_2133[] = { + {937, { 0, 0x4000, 0xc000,} }, + {1071, { 0x2000, 0, 0x2000,} }, + {1250, { 0x800, 0, 0x800,} }, + {1500, { 0, 0x400, 0x200,} }, + }; + const struct cas cl_1866[] = { + {1071, { 0, 0x1000, 0x3000,} }, + {1250, { 0xc00, 0x400, 0xc00,} }, + {1500, { 0, 0x400, 0x200,} }, + }; + const struct cas cl_1600[] = { + {1250, { 0, 0x400, 0xc00,} }, + {1500, { 0, 0x400, 0x200,} }, + }; + const struct speed bin_0[] = { + {cl_3200, {12500, 13750, 15000,} }, + {cl_2933, {12960, 13640, 13750, 15000,} }, + {cl_2666, {12750, 13500, 13750, 15000,} }, + {cl_2400, {12500, 13320, 13750, 15000,} }, + {cl_2133, {13130, 13500, 15000,} }, + {cl_1866, {12850, 13500, 15000,} }, + {cl_1600, {12500, 13500, 15000,} } + }; + const struct cas cl_3200_3ds[] = { + {625, { 0xa000000, 0xb000000, 0xf000000,} }, + {750, { 0xaa00000, 0xab00000, 0xef00000,} }, + {833, { 0xaac0000, 0xaac0000, 0xebc0000,} }, + {937, { 0xaab0000, 0xaab0000, 0xeaf0000,} }, + {1071, { 0xaaa4000, 0xaaac000, 0xeaec000,} }, + {1250, { 0xaaa0000, 0xaaa2000, 0xeaeb000,} }, + }; + const struct cas cl_2666_3ds[] = { + {750, { 0xa00000, 0xb00000, 0xf00000,} }, + {833, { 0xac0000, 0xac0000, 0xbc0000,} }, + {937, { 0xab0000, 0xab0000, 0xaf0000,} }, + {1071, { 0xaa4000, 0xaac000, 0xaac000,} }, + {1250, { 0xaa0000, 0xaaa000, 0xaaa000,} }, + }; + const struct cas cl_2400_3ds[] = { + {833, { 0xe00000, 0xe40000, 0xec0000, 0xb00000} }, + {937, { 0xe00000, 0xe00000, 0xea0000, 0xae0000} }, + {1071, { 0xe00000, 0xe04000, 0xeac000, 0xaec000} }, + {1250, { 0xe00000, 0xe00000, 0xeaa000, 0xae2000} }, + }; + const struct cas cl_2133_3ds[] = { + {937, { 0x90000, 0xb0000, 0xf0000,} }, + {1071, { 0x84000, 0xac000, 0xec000,} }, + {1250, { 0x80000, 0xa2000, 0xe2000,} }, + }; + const struct cas cl_1866_3ds[] = { + {1071, { 0, 0x4000, 0xc000,} }, + {1250, { 0, 0x1000, 0x3000,} }, + }; + const struct cas cl_1600_3ds[] = { + {1250, { 0, 0x1000, 0x3000,} }, + }; + const struct speed bin_3ds[] = { + {cl_3200_3ds, {15000, 16250, 17140,} }, + {cl_2666_3ds, {15000, 16500, 17140,} }, + {cl_2400_3ds, {15000, 15830, 16670, 17140} }, + {cl_2133_3ds, {15950, 16880, 17140,} }, + {cl_1866_3ds, {15000, 16070, 17140,} }, + {cl_1600_3ds, {15000, 16250, 17500,} }, + }; + const struct speed *bin; + int size; + unsigned int taamin_max, tck_max; + + if (taamin_ps > ((package_3ds != 0) ? 21500 : 18000)) { + ERROR("taamin_ps %u invalid\n", taamin_ps); + return 0; + } + if (package_3ds != 0) { + bin = bin_3ds; + size = ARRAY_SIZE(bin_3ds); + taamin_max = 1250; + tck_max = 1500; + } else { + bin = bin_0; + size = ARRAY_SIZE(bin_0); + taamin_max = 1500; + tck_max = 1600; + } + if (mclk_ps < 625 || mclk_ps > tck_max) { + ERROR("mclk %u invalid\n", mclk_ps); + return 0; + } + + for (i = 0; i < size; i++) { + if (bin[i].cl[0].tckmin_ps >= tckmin_ps) { + break; + } + } + if (i >= size) { + ERROR("speed bin not found\n"); + return 0; + } + if (bin[i].cl[0].tckmin_ps > tckmin_ps && i > 0) { + i--; + } + + for (j = 0; j < 4; j++) { + if ((bin[i].taamin_ps[j] == 0) || + bin[i].taamin_ps[j] >= taamin_ps) { + break; + } + } + + if (j >= 4) { + ERROR("taamin_ps out of range.\n"); + return 0; + } + + if ((bin[i].taamin_ps[j] == 0) || + (bin[i].taamin_ps[j] > taamin_ps && j > 0)) { + j--; + } + + for (k = 0; bin[i].cl[k].tckmin_ps < mclk_ps && + bin[i].cl[k].tckmin_ps < taamin_max; k++) + ; + if (bin[i].cl[k].tckmin_ps > mclk_ps && k > 0) { + k--; + } + + debug("Skip CL mask for this speed 0x%x\n", bin[i].cl[k].caslat[j]); + + return bin[i].cl[k].caslat[j]; +} + +int compute_ddrc(const unsigned long clk, + const struct memctl_opt *popts, + const struct ddr_conf *conf, + struct ddr_cfg_regs *regs, + const struct dimm_params *pdimm, + unsigned int ip_rev) +{ + unsigned int cas_latency; + unsigned int caslat_skip; + unsigned int additive_latency; + const unsigned int mclk_ps = get_memory_clk_ps(clk); + int i; + + zeromem(regs, sizeof(struct ddr_cfg_regs)); + + if (mclk_ps < pdimm->tckmin_x_ps) { + ERROR("DDR Clk: MCLK cycle is %u ps.\n", mclk_ps); + ERROR("DDR Clk is faster than DIMM can support.\n"); + } + + /* calculate cas latency, override first */ + cas_latency = (popts->caslat_override != 0) ? + popts->caslat_override_value : + (pdimm->taa_ps + mclk_ps - 1) / mclk_ps; + + /* skip unsupported caslat based on speed bin */ + caslat_skip = skip_caslat(pdimm->tckmin_x_ps, + pdimm->taa_ps, + mclk_ps, + pdimm->package_3ds); + debug("Skip caslat 0x%x\n", caslat_skip); + + /* Check if DIMM supports the cas latency */ + i = 24; + while (((pdimm->caslat_x & ~caslat_skip & (1 << cas_latency)) == 0) && + (i-- > 0)) { + cas_latency++; + } + + if (i <= 0) { + ERROR("Failed to find a proper cas latency\n"); + return -EINVAL; + } + /* Verify cas latency does not exceed 18ns for DDR4 */ + if (cas_latency * mclk_ps > 18000) { + ERROR("cas latency is too large %d\n", cas_latency); + return -EINVAL; + } + + additive_latency = (popts->addt_lat_override != 0) ? + popts->addt_lat_override_value : 0; + + cal_ddr_csn_bnds(regs, popts, conf, pdimm); + cal_ddr_sdram_cfg(clk, regs, popts, pdimm, ip_rev); + cal_ddr_sdram_rcw(clk, regs, popts, pdimm); + cal_timing_cfg(clk, regs, popts, pdimm, conf, cas_latency, + additive_latency); + cal_ddr_dq_mapping(regs, pdimm); + + if (ip_rev >= 0x50500) { + cal_ddr_addr_dec(regs); + } + + cal_ddr_sdram_mode(clk, regs, popts, conf, pdimm, cas_latency, + additive_latency, ip_rev); + cal_ddr_eor(regs, popts); + cal_ddr_data_init(regs); + cal_ddr_sdram_interval(clk, regs, popts, pdimm); + cal_ddr_zq_cntl(regs); + cal_ddr_sr_cntr(regs, popts); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c new file mode 100644 index 0000000..b6dffc8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c @@ -0,0 +1,288 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define UL_5POW12 244140625UL +#define ULL_2E12 2000000000000ULL +#define UL_2POW13 (1UL << 13) +#define ULL_8FS 0xFFFFFFFFULL + +#define do_div(n, base) ({ \ + unsigned int __base = (base); \ + unsigned int __rem; \ + __rem = ((unsigned long long)(n)) % __base; \ + (n) = ((unsigned long long)(n)) / __base; \ + __rem; \ +}) + +#define CCN_HN_F_SAM_NODEID_MASK 0x7f +#ifdef NXP_HAS_CCN504 +#define CCN_HN_F_SAM_NODEID_DDR0 0x4 +#define CCN_HN_F_SAM_NODEID_DDR1 0xe +#elif defined(NXP_HAS_CCN508) +#define CCN_HN_F_SAM_NODEID_DDR0_0 0x3 +#define CCN_HN_F_SAM_NODEID_DDR0_1 0x8 +#define CCN_HN_F_SAM_NODEID_DDR1_0 0x13 +#define CCN_HN_F_SAM_NODEID_DDR1_1 0x18 +#endif + +unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num) +{ + if (sys->freq_ddr_pll0 == 0) { + get_clocks(sys); + } + + switch (ctrl_num) { + case 0: + return sys->freq_ddr_pll0; + case 1: + return sys->freq_ddr_pll0; + case 2: + return sys->freq_ddr_pll1; + } + + return 0; +} + +unsigned int get_memory_clk_ps(const unsigned long data_rate) +{ + unsigned int result; + /* Round to nearest 10ps, being careful about 64-bit multiply/divide */ + unsigned long long rem, mclk_ps = ULL_2E12; + + /* Now perform the big divide, the result fits in 32-bits */ + rem = do_div(mclk_ps, data_rate); + result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps; + + return result; +} + +unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos) +{ + unsigned long long clks, clks_rem; + + /* Short circuit for zero picos */ + if ((picos == 0U) || (data_rate == 0UL)) { + return 0U; + } + + /* First multiply the time by the data rate (32x32 => 64) */ + clks = picos * (unsigned long long)data_rate; + /* + * Now divide by 5^12 and track the 32-bit remainder, then divide + * by 2*(2^12) using shifts (and updating the remainder). + */ + clks_rem = do_div(clks, UL_5POW12); + clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12; + clks >>= 13U; + + /* If we had a remainder greater than the 1ps error, then round up */ + if (clks_rem > data_rate) { + clks++; + } + + /* Clamp to the maximum representable value */ + if (clks > ULL_8FS) { + clks = ULL_8FS; + } + return (unsigned int) clks; +} + +/* valid_spd_mask has been checked by parse_spd */ +int disable_unused_ddrc(struct ddr_info *priv, + int valid_spd_mask, uintptr_t nxp_ccn_hn_f0_addr) +{ +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + void *hnf_sam_ctrl = (void *)(nxp_ccn_hn_f0_addr + CCN_HN_F_SAM_CTL); + uint32_t val, nodeid; +#ifdef NXP_HAS_CCN504 + uint32_t num_hnf_nodes = 4U; +#else + uint32_t num_hnf_nodes = 8U; +#endif + int disable_ddrc = 0; + int i; + + if (priv->num_ctlrs < 2) { + debug("%s: nothing to do.\n", __func__); + } + + switch (priv->dimm_on_ctlr) { + case 1: + disable_ddrc = ((valid_spd_mask &0x2) == 0) ? 2 : 0; + disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc; + break; + case 2: + disable_ddrc = ((valid_spd_mask &0x4) == 0) ? 2 : 0; + disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc; + break; + default: + ERROR("Invalid number of DIMMs %d\n", priv->dimm_on_ctlr); + return -EINVAL; + } + + if (disable_ddrc != 0) { + debug("valid_spd_mask = 0x%x\n", valid_spd_mask); + } + + switch (disable_ddrc) { + case 1: + priv->num_ctlrs = 1; + priv->spd_addr = &priv->spd_addr[priv->dimm_on_ctlr]; + priv->ddr[0] = priv->ddr[1]; + priv->ddr[1] = NULL; + priv->phy[0] = priv->phy[0]; + priv->phy[1] = NULL; + debug("Disable first DDR controller\n"); + break; + case 2: + priv->num_ctlrs = 1; + priv->ddr[1] = NULL; + priv->phy[1] = NULL; + debug("Disable second DDR controller\n"); + /* fallthrough */ + case 0: + break; + default: + ERROR("Program error.\n"); + return -EINVAL; + } + + if (disable_ddrc == 0) { + debug("Both controllers in use.\n"); + return 0; + } + + for (i = 0; i < num_hnf_nodes; i++) { + val = mmio_read_64((uintptr_t)hnf_sam_ctrl); +#ifdef NXP_HAS_CCN504 + nodeid = disable_ddrc == 1 ? CCN_HN_F_SAM_NODEID_DDR1 : + (disable_ddrc == 2 ? CCN_HN_F_SAM_NODEID_DDR0 : + 0x0); /*Failure condition. never hit */ +#elif defined(NXP_HAS_CCN508) + if (disable_ddrc == 1) { + nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR1_1 : + CCN_HN_F_SAM_NODEID_DDR1_0; + } else if (disable_ddrc == 2) { + nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR0_0 : + CCN_HN_F_SAM_NODEID_DDR0_1; + } else { + nodeid = 0; /* Failure condition. never hit */ + } +#endif + if (nodeid != (val & CCN_HN_F_SAM_NODEID_MASK)) { + debug("Setting HN-F node %d\n", i); + debug("nodeid = 0x%x\n", nodeid); + val &= ~CCN_HN_F_SAM_NODEID_MASK; + val |= nodeid; + mmio_write_64((uintptr_t)hnf_sam_ctrl, val); + } + hnf_sam_ctrl += CCN_HN_F_REGION_SIZE; + } +#endif + return 0; +} + +unsigned int get_ddrc_version(const struct ccsr_ddr *ddr) +{ + unsigned int ver; + + ver = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8U; + ver |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8U; + + return ver; +} + +void print_ddr_info(struct ccsr_ddr *ddr) +{ + unsigned int cs0_config = ddr_in32(&ddr->csn_cfg[0]); + unsigned int sdram_cfg = ddr_in32(&ddr->sdram_cfg); + int cas_lat; + + if ((sdram_cfg & SDRAM_CFG_MEM_EN) == 0U) { + printf(" (DDR not enabled)\n"); + return; + } + + printf("DDR"); + switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >> + SDRAM_CFG_SDRAM_TYPE_SHIFT) { + case SDRAM_TYPE_DDR4: + printf("4"); + break; + default: + printf("?"); + break; + } + + switch (sdram_cfg & SDRAM_CFG_DBW_MASK) { + case SDRAM_CFG_32_BW: + printf(", 32-bit"); + break; + case SDRAM_CFG_16_BW: + printf(", 16-bit"); + break; + case SDRAM_CFG_8_BW: + printf(", 8-bit"); + break; + default: + printf(", 64-bit"); + break; + } + + /* Calculate CAS latency based on timing cfg values */ + cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf); + cas_lat += 2; /* for DDRC newer than 4.4 */ + cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4; + printf(", CL=%d", cas_lat >> 1); + if ((cas_lat & 0x1) != 0) { + printf(".5"); + } + + if ((sdram_cfg & SDRAM_CFG_ECC_EN) != 0) { + printf(", ECC on"); + } else { + printf(", ECC off"); + } + + if ((cs0_config & 0x20000000) != 0) { + printf(", "); + switch ((cs0_config >> 24) & 0xf) { + case DDR_256B_INTLV: + printf("256B"); + break; + default: + printf("invalid"); + break; + } + } + + if (((sdram_cfg >> 8) & 0x7f) != 0) { + printf(", "); + switch (sdram_cfg >> 8 & 0x7f) { + case DDR_BA_INTLV_CS0123: + printf("CS0+CS1+CS2+CS3"); + break; + case DDR_BA_INTLV_CS01: + printf("CS0+CS1"); + break; + default: + printf("invalid"); + break; + } + } + printf("\n"); +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c new file mode 100644 index 0000000..4b66d38 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c @@ -0,0 +1,97 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +static void cal_ddr_sdram_clk_cntl(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + const unsigned int clk_adj = popts->clk_adj; + const unsigned int ss_en = 0U; + + regs->clk_cntl = ((ss_en & U(0x1)) << 31U) | + ((clk_adj & U(0x1F)) << 22U); + debug("clk_cntl = 0x%x\n", regs->clk_cntl); +} + +static void cal_ddr_cdr(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + regs->cdr[0] = popts->ddr_cdr1; + regs->cdr[1] = popts->ddr_cdr2; + debug("cdr[0] = 0x%x\n", regs->cdr[0]); + debug("cdr[1] = 0x%x\n", regs->cdr[1]); +} + +static void cal_ddr_wrlvl_cntl(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + const unsigned int wrlvl_en = 1U; /* enabled */ + const unsigned int wrlvl_mrd = U(0x6); /* > 40nCK */ + const unsigned int wrlvl_odten = U(0x7); /* 128 */ + const unsigned int wrlvl_dqsen = U(0x5); /* > 25nCK */ + const unsigned int wrlvl_wlr = U(0x6); /* > tWLO + 6 */ + const unsigned int wrlvl_smpl = popts->wrlvl_override ? + popts->wrlvl_sample : U(0xf); + const unsigned int wrlvl_start = popts->wrlvl_start; + + regs->wrlvl_cntl[0] = ((wrlvl_en & U(0x1)) << 31U) | + ((wrlvl_mrd & U(0x7)) << 24U) | + ((wrlvl_odten & U(0x7)) << 20U) | + ((wrlvl_dqsen & U(0x7)) << 16U) | + ((wrlvl_smpl & U(0xf)) << 12U) | + ((wrlvl_wlr & U(0x7)) << 8U) | + ((wrlvl_start & U(0x1F)) << 0U); + regs->wrlvl_cntl[1] = popts->wrlvl_ctl_2; + regs->wrlvl_cntl[2] = popts->wrlvl_ctl_3; + debug("wrlvl_cntl[0] = 0x%x\n", regs->wrlvl_cntl[0]); + debug("wrlvl_cntl[1] = 0x%x\n", regs->wrlvl_cntl[1]); + debug("wrlvl_cntl[2] = 0x%x\n", regs->wrlvl_cntl[2]); + +} + +static void cal_ddr_dbg(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + if (popts->cswl_override != 0) { + regs->debug[18] = popts->cswl_override; + } + +#ifdef CONFIG_SYS_FSL_DDR_EMU + /* disable DDR training for emulator */ + regs->debug[2] = U(0x00000400); + regs->debug[4] = U(0xff800800); + regs->debug[5] = U(0x08000800); + regs->debug[6] = U(0x08000800); + regs->debug[7] = U(0x08000800); + regs->debug[8] = U(0x08000800); +#endif + if (popts->cpo_sample != 0U) { + regs->debug[28] = popts->cpo_sample; + debug("debug[28] = 0x%x\n", regs->debug[28]); + } +} + +int compute_ddr_phy(struct ddr_info *priv) +{ + const struct memctl_opt *popts = &priv->opt; + struct ddr_cfg_regs *regs = &priv->ddr_reg; + + cal_ddr_sdram_clk_cntl(regs, popts); + cal_ddr_cdr(regs, popts); + cal_ddr_wrlvl_cntl(regs, popts); + cal_ddr_dbg(regs, popts); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h new file mode 100644 index 0000000..ee7b4d8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h @@ -0,0 +1,151 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CSR_H +#define CSR_H + +#define t_anib 0 +#define t_dbyte 0x10000 +#define t_master 0x20000 +#define t_acsm 0x40000 +#define t_initeng 0x90000 +#define t_drtub 0xc0000 +#define t_apbonly 0xd0000 +#define csr_dbyte_misc_mode_addr 0x00 +#define csr_micro_cont_mux_sel_addr 0x00 +#define csr_uct_shadow_regs 0x04 +#define csr_cal_uclk_info_addr 0x08 +#define csr_seq0bdly0_addr 0x0b +#define csr_seq0bdly1_addr 0x0c +#define csr_seq0bdly2_addr 0x0d +#define csr_seq0bdly3_addr 0x0e +#define csr_seq0bdisable_flag0_addr 0x0c +#define csr_seq0bdisable_flag1_addr 0x0d +#define csr_seq0bdisable_flag2_addr 0x0e +#define csr_seq0bdisable_flag3_addr 0x0f +#define csr_seq0bdisable_flag4_addr 0x10 +#define csr_seq0bdisable_flag5_addr 0x11 +#define csr_seq0bdisable_flag6_addr 0x12 +#define csr_seq0bdisable_flag7_addr 0x13 +#define csr_dfi_mode_addr 0x18 +#define csr_tristate_mode_ca_addr 0x19 +#define csr_dfiphyupd_addr 0x21 +#define csr_dqs_preamble_control_addr 0x24 +#define csr_master_x4config_addr 0x25 +#define csr_enable_cs_multicast_addr 0x27 +#define csr_acx4_anib_dis_addr 0x2c +#define csr_dmipin_present_addr 0x2d +#define csr_ard_ptr_init_val_addr 0x2e +#define csr_dct_write_prot 0x31 +#define csr_uct_write_only_shadow 0x32 +#define csr_uct_write_prot 0x33 +#define csr_uct_dat_write_only_shadow 0x34 +#define csr_dbyte_dll_mode_cntrl_addr 0x3a +#define csr_atx_impedance_addr 0x43 +#define csr_dq_dqs_rcv_cntrl_addr 0x43 +#define csr_cal_offsets_addr 0x45 +#define csr_tx_impedance_ctrl1_addr 0x49 +#define csr_dq_dqs_rcv_cntrl1_addr 0x4a +#define csr_tx_odt_drv_stren_addr 0x4d +#define csr_cal_drv_str0_addr 0x50 +#define csr_atx_slew_rate_addr 0x55 +#define csr_proc_odt_time_ctl_addr 0x56 +#define csr_mem_alert_control_addr 0x5b +#define csr_mem_alert_control2_addr 0x5c +#define csr_tx_slew_rate_addr 0x5f +#define csr_mem_reset_l_addr 0x60 +#define csr_dfi_camode_addr 0x75 +#define csr_dll_gain_ctl_addr 0x7c +#define csr_dll_lockparam_addr 0x7d +#define csr_ucclk_hclk_enables_addr 0x80 +#define csr_acsm_playback0x0_addr 0x80 +#define csr_acsm_playback1x0_addr 0x81 +#define csr_cal_rate_addr 0x88 +#define csr_cal_zap_addr 0x89 +#define csr_cal_misc2_addr 0x98 +#define csr_micro_reset_addr 0x99 +#define csr_dfi_rd_data_cs_dest_map_addr 0xb0 +#define csr_vref_in_global_addr 0xb2 +#define csr_dfi_wr_data_cs_dest_map_addr 0xb4 +#define csr_pll_pwr_dn_addr 0xc3 +#define csr_pll_ctrl2_addr 0xc5 +#define csr_pll_ctrl1_addr 0xc7 +#define csr_pll_test_mode_addr 0xca +#define csr_pll_ctrl4_addr 0xcc +#define csr_dfi_freq_xlat0_addr 0xf0 +#define csr_acsm_ctrl0_addr 0xf0 +#define csr_dfi_freq_ratio_addr 0xfa +#define csr_acsm_ctrl13_addr 0xfd +#define csr_tx_pre_drv_mode_lsb 8 +#define csr_tx_pre_n_lsb 4 +#define csr_tx_pre_p_lsb 0 +#define csr_atx_pre_drv_mode_lsb 8 +#define csr_atx_pre_n_lsb 4 +#define csr_atx_pre_p_lsb 0 +#define csr_wdqsextension_lsb 8 +#define csr_lp4sttc_pre_bridge_rx_en_lsb 7 +#define csr_lp4postamble_ext_lsb 6 +#define csr_lp4tgl_two_tck_tx_dqs_pre_lsb 5 +#define csr_position_dfe_init_lsb 2 +#define csr_two_tck_tx_dqs_pre_lsb 1 +#define csr_two_tck_rx_dqs_pre_lsb 0 +#define csr_dll_rx_preamble_mode_lsb 1 +#define csr_odtstren_n_lsb 6 +#define csr_drv_stren_fsdq_n_lsb 6 +#define csr_drv_stren_fsdq_p_lsb 0 +#define csr_adrv_stren_n_lsb 5 +#define csr_adrv_stren_p_lsb 0 +#define csr_cal_drv_str_pu50_lsb 4 +#define csr_cal_once_lsb 5 +#define csr_cal_interval_lsb 0 +#define csr_cal_run_lsb 4 +#define csr_global_vref_in_dac_lsb 3 +#define csr_gain_curr_adj_lsb 7 +#define csr_major_mode_dbyte_lsb 4 +#define csr_dfe_ctrl_lsb 2 +#define csr_ext_vref_range_lsb 1 +#define csr_sel_analog_vref_lsb 0 +#define csr_malertsync_bypass_lsb 0 +#define csr_ck_dis_val_lsb 2 +#define csr_ddr2tmode_lsb 1 +#define csr_dis_dyn_adr_tri_lsb 0 +#define csr_dbyte_disable_lsb 2 +#define csr_power_down_rcvr_lsb 0 +#define csr_power_down_rcvr_dqs_lsb 9 +#define csr_rx_pad_standby_en_lsb 10 +#define csr_rx_pad_standby_en_mask 0x400 +#define csr_x4tg_lsb 0 +#define csr_reset_to_micro_mask 0x8 +#define csr_protect_mem_reset_mask 0x2 +#define csr_stall_to_micro_mask 0x1 +#define uct_write_prot_shadow_mask 0x1 +#define csr_acsm_par_mode_mask 0x4000 +#define csr_acsm_cke_enb_lsb 0 +#define csr_dfiphyupd_threshold_lsb 8 +#define csr_dfiphyupd_threshold_msb 11 +#define csr_dfiphyupd_threshold_mask 0xf00 +#define csr_dfi_rd_destm0_lsb 0 +#define csr_dfi_rd_destm1_lsb 2 +#define csr_dfi_rd_destm2_lsb 4 +#define csr_dfi_rd_destm3_lsb 6 +#define csr_dfi_wr_destm0_lsb 0 +#define csr_dfi_wr_destm1_lsb 2 +#define csr_dfi_wr_destm2_lsb 4 +#define csr_dfi_wr_destm3_lsb 6 +#define csr_acsm_2t_mode_mask 0x40 +#define csr_cal_misc2_err_dis 13 +#define csr_cal_offset_pdc_lsb 6 +#define csr_cal_offset_pdc_msb 9 +#define csr_cal_offset_pdc_mask 0xe0 +#define csr_cal_drv_pdth_mask 0x3c0 + + +struct impedance_mapping { + int ohm; + int code; +}; + +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h new file mode 100644 index 0000000..f17f2e7 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h @@ -0,0 +1,2897 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR4FW +#define DDR4FW + +#define PHY_GEN2_MAX_IMAGE_SIZE 32768 +#define PHY_GEN2_IMEM_ADDR 0x50000 +#define PHY_GEN2_DMEM_ADDR 0x54000 + +struct ddr4u1d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t reserved19[0x1B - 0x19]; + uint8_t share2dvref_result; + uint8_t reserved1c[0x22 - 0x1c]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + int8_t cdd_rr_3_2; + int8_t cdd_rr_3_1; + int8_t cdd_rr_3_0; + int8_t cdd_rr_2_3; + int8_t cdd_rr_2_1; + int8_t cdd_rr_2_0; + int8_t cdd_rr_1_3; + int8_t cdd_rr_1_2; + int8_t cdd_rr_1_0; + int8_t cdd_rr_0_3; + int8_t cdd_rr_0_2; + int8_t cdd_rr_0_1; + int8_t cdd_ww_3_2; + int8_t cdd_ww_3_1; + int8_t cdd_ww_3_0; + int8_t cdd_ww_2_3; + int8_t cdd_ww_2_1; + int8_t cdd_ww_2_0; + int8_t cdd_ww_1_3; + int8_t cdd_ww_1_2; + int8_t cdd_ww_1_0; + int8_t cdd_ww_0_3; + int8_t cdd_ww_0_2; + int8_t cdd_ww_0_1; + int8_t cdd_rw_3_3; + int8_t cdd_rw_3_2; + int8_t cdd_rw_3_1; + int8_t cdd_rw_3_0; + int8_t cdd_rw_2_3; + int8_t cdd_rw_2_2; + int8_t cdd_rw_2_1; + int8_t cdd_rw_2_0; + int8_t cdd_rw_1_3; + int8_t cdd_rw_1_2; + int8_t cdd_rw_1_1; + int8_t cdd_rw_1_0; + int8_t cdd_rw_0_3; + int8_t cdd_rw_0_2; + int8_t cdd_rw_0_1; + int8_t cdd_rw_0_0; + int8_t cdd_wr_3_3; + int8_t cdd_wr_3_2; + int8_t cdd_wr_3_1; + int8_t cdd_wr_3_0; + int8_t cdd_wr_2_3; + int8_t cdd_wr_2_2; + int8_t cdd_wr_2_1; + int8_t cdd_wr_2_0; + int8_t cdd_wr_1_3; + int8_t cdd_wr_1_2; + int8_t cdd_wr_1_1; + int8_t cdd_wr_1_0; + int8_t cdd_wr_0_3; + int8_t cdd_wr_0_2; + int8_t cdd_wr_0_1; + int8_t cdd_wr_0_0; + uint8_t reserved5d; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t reserved_d6[0x3f6 - 0xd6]; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4u2d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t rx2d_train_opt; + uint8_t tx2d_train_opt; + uint8_t share2dvref_result; + uint8_t delay_weight2d; + uint8_t voltage_weight2d; + uint8_t reserved1e[0x22 - 0x1e]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + uint8_t r0_rx_clk_dly_margin; + uint8_t r0_vref_dac_margin; + uint8_t r0_tx_dq_dly_margin; + uint8_t r0_device_vref_margin; + uint8_t reserved29[0x33 - 0x29]; + uint8_t r1_rx_clk_dly_margin; + uint8_t r1_vref_dac_margin; + uint8_t r1_tx_dq_dly_margin; + uint8_t r1_device_vref_margin; + uint8_t reserved37[0x41 - 0x37]; + uint8_t r2_rx_clk_dly_margin; + uint8_t r2_vref_dac_margin; + uint8_t r2_tx_dq_dly_margin; + uint8_t r2_device_vref_margin; + uint8_t reserved45[0x4f - 0x45]; + uint8_t r3_rx_clk_dly_margin; + uint8_t r3_vref_dac_margin; + uint8_t r3_tx_dq_dly_margin; + uint8_t r3_device_vref_margin; + uint8_t reserved53[0x5e - 0x53]; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t reserved_d6[0x3f6 - 0xd6]; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4r1d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t reserved19[0x22 - 0x19]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + int8_t cdd_rr_3_2; + int8_t cdd_rr_3_1; + int8_t cdd_rr_3_0; + int8_t cdd_rr_2_3; + int8_t cdd_rr_2_1; + int8_t cdd_rr_2_0; + int8_t cdd_rr_1_3; + int8_t cdd_rr_1_2; + int8_t cdd_rr_1_0; + int8_t cdd_rr_0_3; + int8_t cdd_rr_0_2; + int8_t cdd_rr_0_1; + int8_t cdd_ww_3_2; + int8_t cdd_ww_3_1; + int8_t cdd_ww_3_0; + int8_t cdd_ww_2_3; + int8_t cdd_ww_2_1; + int8_t cdd_ww_2_0; + int8_t cdd_ww_1_3; + int8_t cdd_ww_1_2; + int8_t cdd_ww_1_0; + int8_t cdd_ww_0_3; + int8_t cdd_ww_0_2; + int8_t cdd_ww_0_1; + int8_t cdd_rw_3_3; + int8_t cdd_rw_3_2; + int8_t cdd_rw_3_1; + int8_t cdd_rw_3_0; + int8_t cdd_rw_2_3; + int8_t cdd_rw_2_2; + int8_t cdd_rw_2_1; + int8_t cdd_rw_2_0; + int8_t cdd_rw_1_3; + int8_t cdd_rw_1_2; + int8_t cdd_rw_1_1; + int8_t cdd_rw_1_0; + int8_t cdd_rw_0_3; + int8_t cdd_rw_0_2; + int8_t cdd_rw_0_1; + int8_t cdd_rw_0_0; + int8_t cdd_wr_3_3; + int8_t cdd_wr_3_2; + int8_t cdd_wr_3_1; + int8_t cdd_wr_3_0; + int8_t cdd_wr_2_3; + int8_t cdd_wr_2_2; + int8_t cdd_wr_2_1; + int8_t cdd_wr_2_0; + int8_t cdd_wr_1_3; + int8_t cdd_wr_1_2; + int8_t cdd_wr_1_1; + int8_t cdd_wr_1_0; + int8_t cdd_wr_0_3; + int8_t cdd_wr_0_2; + int8_t cdd_wr_0_1; + int8_t cdd_wr_0_0; + uint8_t reserved5d; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t f0rc00_d0; + uint8_t f0rc01_d0; + uint8_t f0rc02_d0; + uint8_t f0rc03_d0; + uint8_t f0rc04_d0; + uint8_t f0rc05_d0; + uint8_t f0rc06_d0; + uint8_t f0rc07_d0; + uint8_t f0rc08_d0; + uint8_t f0rc09_d0; + uint8_t f0rc0a_d0; + uint8_t f0rc0b_d0; + uint8_t f0rc0c_d0; + uint8_t f0rc0d_d0; + uint8_t f0rc0e_d0; + uint8_t f0rc0f_d0; + uint8_t f0rc1x_d0; + uint8_t f0rc2x_d0; + uint8_t f0rc3x_d0; + uint8_t f0rc4x_d0; + uint8_t f0rc5x_d0; + uint8_t f0rc6x_d0; + uint8_t f0rc7x_d0; + uint8_t f0rc8x_d0; + uint8_t f0rc9x_d0; + uint8_t f0rcax_d0; + uint8_t f0rcbx_d0; + uint8_t f1rc00_d0; + uint8_t f1rc01_d0; + uint8_t f1rc02_d0; + uint8_t f1rc03_d0; + uint8_t f1rc04_d0; + uint8_t f1rc05_d0; + uint8_t f1rc06_d0; + uint8_t f1rc07_d0; + uint8_t f1rc08_d0; + uint8_t f1rc09_d0; + uint8_t f1rc0a_d0; + uint8_t f1rc0b_d0; + uint8_t f1rc0c_d0; + uint8_t f1rc0d_d0; + uint8_t f1rc0e_d0; + uint8_t f1rc0f_d0; + uint8_t f1rc1x_d0; + uint8_t f1rc2x_d0; + uint8_t f1rc3x_d0; + uint8_t f1rc4x_d0; + uint8_t f1rc5x_d0; + uint8_t f1rc6x_d0; + uint8_t f1rc7x_d0; + uint8_t f1rc8x_d0; + uint8_t f1rc9x_d0; + uint8_t f1rcax_d0; + uint8_t f1rcbx_d0; + uint8_t f0rc00_d1; + uint8_t f0rc01_d1; + uint8_t f0rc02_d1; + uint8_t f0rc03_d1; + uint8_t f0rc04_d1; + uint8_t f0rc05_d1; + uint8_t f0rc06_d1; + uint8_t f0rc07_d1; + uint8_t f0rc08_d1; + uint8_t f0rc09_d1; + uint8_t f0rc0a_d1; + uint8_t f0rc0b_d1; + uint8_t f0rc0c_d1; + uint8_t f0rc0d_d1; + uint8_t f0rc0e_d1; + uint8_t f0rc0f_d1; + uint8_t f0rc1x_d1; + uint8_t f0rc2x_d1; + uint8_t f0rc3x_d1; + uint8_t f0rc4x_d1; + uint8_t f0rc5x_d1; + uint8_t f0rc6x_d1; + uint8_t f0rc7x_d1; + uint8_t f0rc8x_d1; + uint8_t f0rc9x_d1; + uint8_t f0rcax_d1; + uint8_t f0rcbx_d1; + uint8_t f1rc00_d1; + uint8_t f1rc01_d1; + uint8_t f1rc02_d1; + uint8_t f1rc03_d1; + uint8_t f1rc04_d1; + uint8_t f1rc05_d1; + uint8_t f1rc06_d1; + uint8_t f1rc07_d1; + uint8_t f1rc08_d1; + uint8_t f1rc09_d1; + uint8_t f1rc0a_d1; + uint8_t f1rc0b_d1; + uint8_t f1rc0c_d1; + uint8_t f1rc0d_d1; + uint8_t f1rc0e_d1; + uint8_t f1rc0f_d1; + uint8_t f1rc1x_d1; + uint8_t f1rc2x_d1; + uint8_t f1rc3x_d1; + uint8_t f1rc4x_d1; + uint8_t f1rc5x_d1; + uint8_t f1rc6x_d1; + uint8_t f1rc7x_d1; + uint8_t f1rc8x_d1; + uint8_t f1rc9x_d1; + uint8_t f1rcax_d1; + uint8_t f1rcbx_d1; + uint8_t reserved142[0x3f6 - 0x142]; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4r2d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t rx2d_train_opt; + uint8_t tx2d_train_opt; + uint8_t share2dvref_result; + uint8_t delay_weight2d; + uint8_t voltage_weight2d; + uint8_t reserved1e[0x22-0x1e]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + uint8_t r0_rx_clk_dly_margin; + uint8_t r0_vref_dac_margin; + uint8_t r0_tx_dq_dly_margin; + uint8_t r0_device_vref_margin; + uint8_t reserved29[0x33-0x29]; + uint8_t r1_rx_clk_dly_margin; + uint8_t r1_vref_dac_margin; + uint8_t r1_tx_dq_dly_margin; + uint8_t r1_device_vref_margin; + uint8_t reserved37[0x41-0x37]; + uint8_t r2_rx_clk_dly_margin; + uint8_t r2_vref_dac_margin; + uint8_t r2_tx_dq_dly_margin; + uint8_t r2_device_vref_margin; + uint8_t reserved45[0x4f - 0x45]; + uint8_t r3_rx_clk_dly_margin; + uint8_t r3_vref_dac_margin; + uint8_t r3_tx_dq_dly_margin; + uint8_t r3_device_vref_margin; + uint8_t reserved53[0x5e - 0x53]; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t f0rc00_d0; + uint8_t f0rc01_d0; + uint8_t f0rc02_d0; + uint8_t f0rc03_d0; + uint8_t f0rc04_d0; + uint8_t f0rc05_d0; + uint8_t f0rc06_d0; + uint8_t f0rc07_d0; + uint8_t f0rc08_d0; + uint8_t f0rc09_d0; + uint8_t f0rc0a_d0; + uint8_t f0rc0b_d0; + uint8_t f0rc0c_d0; + uint8_t f0rc0d_d0; + uint8_t f0rc0e_d0; + uint8_t f0rc0f_d0; + uint8_t f0rc1x_d0; + uint8_t f0rc2x_d0; + uint8_t f0rc3x_d0; + uint8_t f0rc4x_d0; + uint8_t f0rc5x_d0; + uint8_t f0rc6x_d0; + uint8_t f0rc7x_d0; + uint8_t f0rc8x_d0; + uint8_t f0rc9x_d0; + uint8_t f0rcax_d0; + uint8_t f0rcbx_d0; + uint8_t f1rc00_d0; + uint8_t f1rc01_d0; + uint8_t f1rc02_d0; + uint8_t f1rc03_d0; + uint8_t f1rc04_d0; + uint8_t f1rc05_d0; + uint8_t f1rc06_d0; + uint8_t f1rc07_d0; + uint8_t f1rc08_d0; + uint8_t f1rc09_d0; + uint8_t f1rc0a_d0; + uint8_t f1rc0b_d0; + uint8_t f1rc0c_d0; + uint8_t f1rc0d_d0; + uint8_t f1rc0e_d0; + uint8_t f1rc0f_d0; + uint8_t f1rc1x_d0; + uint8_t f1rc2x_d0; + uint8_t f1rc3x_d0; + uint8_t f1rc4x_d0; + uint8_t f1rc5x_d0; + uint8_t f1rc6x_d0; + uint8_t f1rc7x_d0; + uint8_t f1rc8x_d0; + uint8_t f1rc9x_d0; + uint8_t f1rcax_d0; + uint8_t f1rcbx_d0; + uint8_t f0rc00_d1; + uint8_t f0rc01_d1; + uint8_t f0rc02_d1; + uint8_t f0rc03_d1; + uint8_t f0rc04_d1; + uint8_t f0rc05_d1; + uint8_t f0rc06_d1; + uint8_t f0rc07_d1; + uint8_t f0rc08_d1; + uint8_t f0rc09_d1; + uint8_t f0rc0a_d1; + uint8_t f0rc0b_d1; + uint8_t f0rc0c_d1; + uint8_t f0rc0d_d1; + uint8_t f0rc0e_d1; + uint8_t f0rc0f_d1; + uint8_t f0rc1x_d1; + uint8_t f0rc2x_d1; + uint8_t f0rc3x_d1; + uint8_t f0rc4x_d1; + uint8_t f0rc5x_d1; + uint8_t f0rc6x_d1; + uint8_t f0rc7x_d1; + uint8_t f0rc8x_d1; + uint8_t f0rc9x_d1; + uint8_t f0rcax_d1; + uint8_t f0rcbx_d1; + uint8_t f1rc00_d1; + uint8_t f1rc01_d1; + uint8_t f1rc02_d1; + uint8_t f1rc03_d1; + uint8_t f1rc04_d1; + uint8_t f1rc05_d1; + uint8_t f1rc06_d1; + uint8_t f1rc07_d1; + uint8_t f1rc08_d1; + uint8_t f1rc09_d1; + uint8_t f1rc0a_d1; + uint8_t f1rc0b_d1; + uint8_t f1rc0c_d1; + uint8_t f1rc0d_d1; + uint8_t f1rc0e_d1; + uint8_t f1rc0f_d1; + uint8_t f1rc1x_d1; + uint8_t f1rc2x_d1; + uint8_t f1rc3x_d1; + uint8_t f1rc4x_d1; + uint8_t f1rc5x_d1; + uint8_t f1rc6x_d1; + uint8_t f1rc7x_d1; + uint8_t f1rc8x_d1; + uint8_t f1rc9x_d1; + uint8_t f1rcax_d1; + uint8_t f1rcbx_d1; + uint8_t reserved142[0x3f6 - 0x142]; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4lr1d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t reserved19[0x22 - 0x19]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + int8_t cdd_rr_3_2; + int8_t cdd_rr_3_1; + int8_t cdd_rr_3_0; + int8_t cdd_rr_2_3; + int8_t cdd_rr_2_1; + int8_t cdd_rr_2_0; + int8_t cdd_rr_1_3; + int8_t cdd_rr_1_2; + int8_t cdd_rr_1_0; + int8_t cdd_rr_0_3; + int8_t cdd_rr_0_2; + int8_t cdd_rr_0_1; + int8_t cdd_ww_3_2; + int8_t cdd_ww_3_1; + int8_t cdd_ww_3_0; + int8_t cdd_ww_2_3; + int8_t cdd_ww_2_1; + int8_t cdd_ww_2_0; + int8_t cdd_ww_1_3; + int8_t cdd_ww_1_2; + int8_t cdd_ww_1_0; + int8_t cdd_ww_0_3; + int8_t cdd_ww_0_2; + int8_t cdd_ww_0_1; + int8_t cdd_rw_3_3; + int8_t cdd_rw_3_2; + int8_t cdd_rw_3_1; + int8_t cdd_rw_3_0; + int8_t cdd_rw_2_3; + int8_t cdd_rw_2_2; + int8_t cdd_rw_2_1; + int8_t cdd_rw_2_0; + int8_t cdd_rw_1_3; + int8_t cdd_rw_1_2; + int8_t cdd_rw_1_1; + int8_t cdd_rw_1_0; + int8_t cdd_rw_0_3; + int8_t cdd_rw_0_2; + int8_t cdd_rw_0_1; + int8_t cdd_rw_0_0; + int8_t cdd_wr_3_3; + int8_t cdd_wr_3_2; + int8_t cdd_wr_3_1; + int8_t cdd_wr_3_0; + int8_t cdd_wr_2_3; + int8_t cdd_wr_2_2; + int8_t cdd_wr_2_1; + int8_t cdd_wr_2_0; + int8_t cdd_wr_1_3; + int8_t cdd_wr_1_2; + int8_t cdd_wr_1_1; + int8_t cdd_wr_1_0; + int8_t cdd_wr_0_3; + int8_t cdd_wr_0_2; + int8_t cdd_wr_0_1; + int8_t cdd_wr_0_0; + uint8_t reserved5d; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t f0rc00_d0; + uint8_t f0rc01_d0; + uint8_t f0rc02_d0; + uint8_t f0rc03_d0; + uint8_t f0rc04_d0; + uint8_t f0rc05_d0; + uint8_t f0rc06_d0; + uint8_t f0rc07_d0; + uint8_t f0rc08_d0; + uint8_t f0rc09_d0; + uint8_t f0rc0a_d0; + uint8_t f0rc0b_d0; + uint8_t f0rc0c_d0; + uint8_t f0rc0d_d0; + uint8_t f0rc0e_d0; + uint8_t f0rc0f_d0; + uint8_t f0rc1x_d0; + uint8_t f0rc2x_d0; + uint8_t f0rc3x_d0; + uint8_t f0rc4x_d0; + uint8_t f0rc5x_d0; + uint8_t f0rc6x_d0; + uint8_t f0rc7x_d0; + uint8_t f0rc8x_d0; + uint8_t f0rc9x_d0; + uint8_t f0rcax_d0; + uint8_t f0rcbx_d0; + uint8_t f1rc00_d0; + uint8_t f1rc01_d0; + uint8_t f1rc02_d0; + uint8_t f1rc03_d0; + uint8_t f1rc04_d0; + uint8_t f1rc05_d0; + uint8_t f1rc06_d0; + uint8_t f1rc07_d0; + uint8_t f1rc08_d0; + uint8_t f1rc09_d0; + uint8_t f1rc0a_d0; + uint8_t f1rc0b_d0; + uint8_t f1rc0c_d0; + uint8_t f1rc0d_d0; + uint8_t f1rc0e_d0; + uint8_t f1rc0f_d0; + uint8_t f1rc1x_d0; + uint8_t f1rc2x_d0; + uint8_t f1rc3x_d0; + uint8_t f1rc4x_d0; + uint8_t f1rc5x_d0; + uint8_t f1rc6x_d0; + uint8_t f1rc7x_d0; + uint8_t f1rc8x_d0; + uint8_t f1rc9x_d0; + uint8_t f1rcax_d0; + uint8_t f1rcbx_d0; + uint8_t f0rc00_d1; + uint8_t f0rc01_d1; + uint8_t f0rc02_d1; + uint8_t f0rc03_d1; + uint8_t f0rc04_d1; + uint8_t f0rc05_d1; + uint8_t f0rc06_d1; + uint8_t f0rc07_d1; + uint8_t f0rc08_d1; + uint8_t f0rc09_d1; + uint8_t f0rc0a_d1; + uint8_t f0rc0b_d1; + uint8_t f0rc0c_d1; + uint8_t f0rc0d_d1; + uint8_t f0rc0e_d1; + uint8_t f0rc0f_d1; + uint8_t f0rc1x_d1; + uint8_t f0rc2x_d1; + uint8_t f0rc3x_d1; + uint8_t f0rc4x_d1; + uint8_t f0rc5x_d1; + uint8_t f0rc6x_d1; + uint8_t f0rc7x_d1; + uint8_t f0rc8x_d1; + uint8_t f0rc9x_d1; + uint8_t f0rcax_d1; + uint8_t f0rcbx_d1; + uint8_t f1rc00_d1; + uint8_t f1rc01_d1; + uint8_t f1rc02_d1; + uint8_t f1rc03_d1; + uint8_t f1rc04_d1; + uint8_t f1rc05_d1; + uint8_t f1rc06_d1; + uint8_t f1rc07_d1; + uint8_t f1rc08_d1; + uint8_t f1rc09_d1; + uint8_t f1rc0a_d1; + uint8_t f1rc0b_d1; + uint8_t f1rc0c_d1; + uint8_t f1rc0d_d1; + uint8_t f1rc0e_d1; + uint8_t f1rc0f_d1; + uint8_t f1rc1x_d1; + uint8_t f1rc2x_d1; + uint8_t f1rc3x_d1; + uint8_t f1rc4x_d1; + uint8_t f1rc5x_d1; + uint8_t f1rc6x_d1; + uint8_t f1rc7x_d1; + uint8_t f1rc8x_d1; + uint8_t f1rc9x_d1; + uint8_t f1rcax_d1; + uint8_t f1rcbx_d1; + uint8_t bc00_d0; + uint8_t bc01_d0; + uint8_t bc02_d0; + uint8_t bc03_d0; + uint8_t bc04_d0; + uint8_t bc05_d0; + uint8_t bc06_d0; + uint8_t bc07_d0; + uint8_t bc08_d0; + uint8_t bc09_d0; + uint8_t bc0a_d0; + uint8_t bc0b_d0; + uint8_t bc0c_d0; + uint8_t bc0d_d0; + uint8_t bc0e_d0; + uint8_t f0bc6x_d0; + uint8_t f0bccx_d0; + uint8_t f0bcdx_d0; + uint8_t f0bcex_d0; + uint8_t f0bcfx_d0; + uint8_t f1bccx_d0; + uint8_t f1bcdx_d0; + uint8_t f1bcex_d0; + uint8_t f1bcfx_d0; + uint8_t f0bc2x_b0_d0; + uint8_t f0bc3x_b0_d0; + uint8_t f0bc4x_b0_d0; + uint8_t f0bc5x_b0_d0; + uint8_t f0bc8x_b0_d0; + uint8_t f0bc9x_b0_d0; + uint8_t f0bcax_b0_d0; + uint8_t f0bcbx_b0_d0; + uint8_t f1bc2x_b0_d0; + uint8_t f1bc3x_b0_d0; + uint8_t f1bc4x_b0_d0; + uint8_t f1bc5x_b0_d0; + uint8_t f1bc8x_b0_d0; + uint8_t f1bc9x_b0_d0; + uint8_t f1bcax_b0_d0; + uint8_t f1bcbx_b0_d0; + uint8_t f2bc2x_b0_d0; + uint8_t f2bc3x_b0_d0; + uint8_t f2bc4x_b0_d0; + uint8_t f2bc5x_b0_d0; + uint8_t f2bc8x_b0_d0; + uint8_t f2bc9x_b0_d0; + uint8_t f2bcax_b0_d0; + uint8_t f2bcbx_b0_d0; + uint8_t f3bc2x_b0_d0; + uint8_t f3bc3x_b0_d0; + uint8_t f3bc4x_b0_d0; + uint8_t f3bc5x_b0_d0; + uint8_t f3bc8x_b0_d0; + uint8_t f3bc9x_b0_d0; + uint8_t f3bcax_b0_d0; + uint8_t f3bcbx_b0_d0; + uint8_t f0bc2x_b1_d0; + uint8_t f0bc3x_b1_d0; + uint8_t f0bc4x_b1_d0; + uint8_t f0bc5x_b1_d0; + uint8_t f0bc8x_b1_d0; + uint8_t f0bc9x_b1_d0; + uint8_t f0bcax_b1_d0; + uint8_t f0bcbx_b1_d0; + uint8_t f1bc2x_b1_d0; + uint8_t f1bc3x_b1_d0; + uint8_t f1bc4x_b1_d0; + uint8_t f1bc5x_b1_d0; + uint8_t f1bc8x_b1_d0; + uint8_t f1bc9x_b1_d0; + uint8_t f1bcax_b1_d0; + uint8_t f1bcbx_b1_d0; + uint8_t f2bc2x_b1_d0; + uint8_t f2bc3x_b1_d0; + uint8_t f2bc4x_b1_d0; + uint8_t f2bc5x_b1_d0; + uint8_t f2bc8x_b1_d0; + uint8_t f2bc9x_b1_d0; + uint8_t f2bcax_b1_d0; + uint8_t f2bcbx_b1_d0; + uint8_t f3bc2x_b1_d0; + uint8_t f3bc3x_b1_d0; + uint8_t f3bc4x_b1_d0; + uint8_t f3bc5x_b1_d0; + uint8_t f3bc8x_b1_d0; + uint8_t f3bc9x_b1_d0; + uint8_t f3bcax_b1_d0; + uint8_t f3bcbx_b1_d0; + uint8_t f0bc2x_b2_d0; + uint8_t f0bc3x_b2_d0; + uint8_t f0bc4x_b2_d0; + uint8_t f0bc5x_b2_d0; + uint8_t f0bc8x_b2_d0; + uint8_t f0bc9x_b2_d0; + uint8_t f0bcax_b2_d0; + uint8_t f0bcbx_b2_d0; + uint8_t f1bc2x_b2_d0; + uint8_t f1bc3x_b2_d0; + uint8_t f1bc4x_b2_d0; + uint8_t f1bc5x_b2_d0; + uint8_t f1bc8x_b2_d0; + uint8_t f1bc9x_b2_d0; + uint8_t f1bcax_b2_d0; + uint8_t f1bcbx_b2_d0; + uint8_t f2bc2x_b2_d0; + uint8_t f2bc3x_b2_d0; + uint8_t f2bc4x_b2_d0; + uint8_t f2bc5x_b2_d0; + uint8_t f2bc8x_b2_d0; + uint8_t f2bc9x_b2_d0; + uint8_t f2bcax_b2_d0; + uint8_t f2bcbx_b2_d0; + uint8_t f3bc2x_b2_d0; + uint8_t f3bc3x_b2_d0; + uint8_t f3bc4x_b2_d0; + uint8_t f3bc5x_b2_d0; + uint8_t f3bc8x_b2_d0; + uint8_t f3bc9x_b2_d0; + uint8_t f3bcax_b2_d0; + uint8_t f3bcbx_b2_d0; + uint8_t f0bc2x_b3_d0; + uint8_t f0bc3x_b3_d0; + uint8_t f0bc4x_b3_d0; + uint8_t f0bc5x_b3_d0; + uint8_t f0bc8x_b3_d0; + uint8_t f0bc9x_b3_d0; + uint8_t f0bcax_b3_d0; + uint8_t f0bcbx_b3_d0; + uint8_t f1bc2x_b3_d0; + uint8_t f1bc3x_b3_d0; + uint8_t f1bc4x_b3_d0; + uint8_t f1bc5x_b3_d0; + uint8_t f1bc8x_b3_d0; + uint8_t f1bc9x_b3_d0; + uint8_t f1bcax_b3_d0; + uint8_t f1bcbx_b3_d0; + uint8_t f2bc2x_b3_d0; + uint8_t f2bc3x_b3_d0; + uint8_t f2bc4x_b3_d0; + uint8_t f2bc5x_b3_d0; + uint8_t f2bc8x_b3_d0; + uint8_t f2bc9x_b3_d0; + uint8_t f2bcax_b3_d0; + uint8_t f2bcbx_b3_d0; + uint8_t f3bc2x_b3_d0; + uint8_t f3bc3x_b3_d0; + uint8_t f3bc4x_b3_d0; + uint8_t f3bc5x_b3_d0; + uint8_t f3bc8x_b3_d0; + uint8_t f3bc9x_b3_d0; + uint8_t f3bcax_b3_d0; + uint8_t f3bcbx_b3_d0; + uint8_t f0bc2x_b4_d0; + uint8_t f0bc3x_b4_d0; + uint8_t f0bc4x_b4_d0; + uint8_t f0bc5x_b4_d0; + uint8_t f0bc8x_b4_d0; + uint8_t f0bc9x_b4_d0; + uint8_t f0bcax_b4_d0; + uint8_t f0bcbx_b4_d0; + uint8_t f1bc2x_b4_d0; + uint8_t f1bc3x_b4_d0; + uint8_t f1bc4x_b4_d0; + uint8_t f1bc5x_b4_d0; + uint8_t f1bc8x_b4_d0; + uint8_t f1bc9x_b4_d0; + uint8_t f1bcax_b4_d0; + uint8_t f1bcbx_b4_d0; + uint8_t f2bc2x_b4_d0; + uint8_t f2bc3x_b4_d0; + uint8_t f2bc4x_b4_d0; + uint8_t f2bc5x_b4_d0; + uint8_t f2bc8x_b4_d0; + uint8_t f2bc9x_b4_d0; + uint8_t f2bcax_b4_d0; + uint8_t f2bcbx_b4_d0; + uint8_t f3bc2x_b4_d0; + uint8_t f3bc3x_b4_d0; + uint8_t f3bc4x_b4_d0; + uint8_t f3bc5x_b4_d0; + uint8_t f3bc8x_b4_d0; + uint8_t f3bc9x_b4_d0; + uint8_t f3bcax_b4_d0; + uint8_t f3bcbx_b4_d0; + uint8_t f0bc2x_b5_d0; + uint8_t f0bc3x_b5_d0; + uint8_t f0bc4x_b5_d0; + uint8_t f0bc5x_b5_d0; + uint8_t f0bc8x_b5_d0; + uint8_t f0bc9x_b5_d0; + uint8_t f0bcax_b5_d0; + uint8_t f0bcbx_b5_d0; + uint8_t f1bc2x_b5_d0; + uint8_t f1bc3x_b5_d0; + uint8_t f1bc4x_b5_d0; + uint8_t f1bc5x_b5_d0; + uint8_t f1bc8x_b5_d0; + uint8_t f1bc9x_b5_d0; + uint8_t f1bcax_b5_d0; + uint8_t f1bcbx_b5_d0; + uint8_t f2bc2x_b5_d0; + uint8_t f2bc3x_b5_d0; + uint8_t f2bc4x_b5_d0; + uint8_t f2bc5x_b5_d0; + uint8_t f2bc8x_b5_d0; + uint8_t f2bc9x_b5_d0; + uint8_t f2bcax_b5_d0; + uint8_t f2bcbx_b5_d0; + uint8_t f3bc2x_b5_d0; + uint8_t f3bc3x_b5_d0; + uint8_t f3bc4x_b5_d0; + uint8_t f3bc5x_b5_d0; + uint8_t f3bc8x_b5_d0; + uint8_t f3bc9x_b5_d0; + uint8_t f3bcax_b5_d0; + uint8_t f3bcbx_b5_d0; + uint8_t f0bc2x_b6_d0; + uint8_t f0bc3x_b6_d0; + uint8_t f0bc4x_b6_d0; + uint8_t f0bc5x_b6_d0; + uint8_t f0bc8x_b6_d0; + uint8_t f0bc9x_b6_d0; + uint8_t f0bcax_b6_d0; + uint8_t f0bcbx_b6_d0; + uint8_t f1bc2x_b6_d0; + uint8_t f1bc3x_b6_d0; + uint8_t f1bc4x_b6_d0; + uint8_t f1bc5x_b6_d0; + uint8_t f1bc8x_b6_d0; + uint8_t f1bc9x_b6_d0; + uint8_t f1bcax_b6_d0; + uint8_t f1bcbx_b6_d0; + uint8_t f2bc2x_b6_d0; + uint8_t f2bc3x_b6_d0; + uint8_t f2bc4x_b6_d0; + uint8_t f2bc5x_b6_d0; + uint8_t f2bc8x_b6_d0; + uint8_t f2bc9x_b6_d0; + uint8_t f2bcax_b6_d0; + uint8_t f2bcbx_b6_d0; + uint8_t f3bc2x_b6_d0; + uint8_t f3bc3x_b6_d0; + uint8_t f3bc4x_b6_d0; + uint8_t f3bc5x_b6_d0; + uint8_t f3bc8x_b6_d0; + uint8_t f3bc9x_b6_d0; + uint8_t f3bcax_b6_d0; + uint8_t f3bcbx_b6_d0; + uint8_t f0bc2x_b7_d0; + uint8_t f0bc3x_b7_d0; + uint8_t f0bc4x_b7_d0; + uint8_t f0bc5x_b7_d0; + uint8_t f0bc8x_b7_d0; + uint8_t f0bc9x_b7_d0; + uint8_t f0bcax_b7_d0; + uint8_t f0bcbx_b7_d0; + uint8_t f1bc2x_b7_d0; + uint8_t f1bc3x_b7_d0; + uint8_t f1bc4x_b7_d0; + uint8_t f1bc5x_b7_d0; + uint8_t f1bc8x_b7_d0; + uint8_t f1bc9x_b7_d0; + uint8_t f1bcax_b7_d0; + uint8_t f1bcbx_b7_d0; + uint8_t f2bc2x_b7_d0; + uint8_t f2bc3x_b7_d0; + uint8_t f2bc4x_b7_d0; + uint8_t f2bc5x_b7_d0; + uint8_t f2bc8x_b7_d0; + uint8_t f2bc9x_b7_d0; + uint8_t f2bcax_b7_d0; + uint8_t f2bcbx_b7_d0; + uint8_t f3bc2x_b7_d0; + uint8_t f3bc3x_b7_d0; + uint8_t f3bc4x_b7_d0; + uint8_t f3bc5x_b7_d0; + uint8_t f3bc8x_b7_d0; + uint8_t f3bc9x_b7_d0; + uint8_t f3bcax_b7_d0; + uint8_t f3bcbx_b7_d0; + uint8_t f0bc2x_b8_d0; + uint8_t f0bc3x_b8_d0; + uint8_t f0bc4x_b8_d0; + uint8_t f0bc5x_b8_d0; + uint8_t f0bc8x_b8_d0; + uint8_t f0bc9x_b8_d0; + uint8_t f0bcax_b8_d0; + uint8_t f0bcbx_b8_d0; + uint8_t f1bc2x_b8_d0; + uint8_t f1bc3x_b8_d0; + uint8_t f1bc4x_b8_d0; + uint8_t f1bc5x_b8_d0; + uint8_t f1bc8x_b8_d0; + uint8_t f1bc9x_b8_d0; + uint8_t f1bcax_b8_d0; + uint8_t f1bcbx_b8_d0; + uint8_t f2bc2x_b8_d0; + uint8_t f2bc3x_b8_d0; + uint8_t f2bc4x_b8_d0; + uint8_t f2bc5x_b8_d0; + uint8_t f2bc8x_b8_d0; + uint8_t f2bc9x_b8_d0; + uint8_t f2bcax_b8_d0; + uint8_t f2bcbx_b8_d0; + uint8_t f3bc2x_b8_d0; + uint8_t f3bc3x_b8_d0; + uint8_t f3bc4x_b8_d0; + uint8_t f3bc5x_b8_d0; + uint8_t f3bc8x_b8_d0; + uint8_t f3bc9x_b8_d0; + uint8_t f3bcax_b8_d0; + uint8_t f3bcbx_b8_d0; + uint8_t f5bc5x_d0; + uint8_t f5bc6x_d0; + uint8_t f4bc8x_d0; + uint8_t f4bc9x_d0; + uint8_t f4bcax_d0; + uint8_t f4bcbx_d0; + uint8_t f4bccx_d0; + uint8_t f4bcdx_d0; + uint8_t f4bcex_d0; + uint8_t f4bcfx_d0; + uint8_t f5bc8x_d0; + uint8_t f5bc9x_d0; + uint8_t f5bcax_d0; + uint8_t f5bcbx_d0; + uint8_t f5bccx_d0; + uint8_t f5bcdx_d0; + uint8_t f5bcex_d0; + uint8_t f5bcfx_d0; + uint8_t f6bc8x_d0; + uint8_t f6bc9x_d0; + uint8_t f6bcax_d0; + uint8_t f6bcbx_d0; + uint8_t f6bccx_d0; + uint8_t f6bcdx_d0; + uint8_t f6bcex_d0; + uint8_t f6bcfx_d0; + uint8_t f7bc8x_d0; + uint8_t f7bc9x_d0; + uint8_t f7bcax_d0; + uint8_t f7bcbx_d0; + uint8_t f7bccx_d0; + uint8_t f7bcdx_d0; + uint8_t f7bcex_d0; + uint8_t f7bcfx_d0; + uint8_t bc00_d1; + uint8_t bc01_d1; + uint8_t bc02_d1; + uint8_t bc03_d1; + uint8_t bc04_d1; + uint8_t bc05_d1; + uint8_t bc06_d1; + uint8_t bc07_d1; + uint8_t bc08_d1; + uint8_t bc09_d1; + uint8_t bc0a_d1; + uint8_t bc0b_d1; + uint8_t bc0c_d1; + uint8_t bc0d_d1; + uint8_t bc0e_d1; + uint8_t f0bc6x_d1; + uint8_t f0bccx_d1; + uint8_t f0bcdx_d1; + uint8_t f0bcex_d1; + uint8_t f0bcfx_d1; + uint8_t f1bccx_d1; + uint8_t f1bcdx_d1; + uint8_t f1bcex_d1; + uint8_t f1bcfx_d1; + uint8_t f0bc2x_b0_d1; + uint8_t f0bc3x_b0_d1; + uint8_t f0bc4x_b0_d1; + uint8_t f0bc5x_b0_d1; + uint8_t f0bc8x_b0_d1; + uint8_t f0bc9x_b0_d1; + uint8_t f0bcax_b0_d1; + uint8_t f0bcbx_b0_d1; + uint8_t f1bc2x_b0_d1; + uint8_t f1bc3x_b0_d1; + uint8_t f1bc4x_b0_d1; + uint8_t f1bc5x_b0_d1; + uint8_t f1bc8x_b0_d1; + uint8_t f1bc9x_b0_d1; + uint8_t f1bcax_b0_d1; + uint8_t f1bcbx_b0_d1; + uint8_t f2bc2x_b0_d1; + uint8_t f2bc3x_b0_d1; + uint8_t f2bc4x_b0_d1; + uint8_t f2bc5x_b0_d1; + uint8_t f2bc8x_b0_d1; + uint8_t f2bc9x_b0_d1; + uint8_t f2bcax_b0_d1; + uint8_t f2bcbx_b0_d1; + uint8_t f3bc2x_b0_d1; + uint8_t f3bc3x_b0_d1; + uint8_t f3bc4x_b0_d1; + uint8_t f3bc5x_b0_d1; + uint8_t f3bc8x_b0_d1; + uint8_t f3bc9x_b0_d1; + uint8_t f3bcax_b0_d1; + uint8_t f3bcbx_b0_d1; + uint8_t f0bc2x_b1_d1; + uint8_t f0bc3x_b1_d1; + uint8_t f0bc4x_b1_d1; + uint8_t f0bc5x_b1_d1; + uint8_t f0bc8x_b1_d1; + uint8_t f0bc9x_b1_d1; + uint8_t f0bcax_b1_d1; + uint8_t f0bcbx_b1_d1; + uint8_t f1bc2x_b1_d1; + uint8_t f1bc3x_b1_d1; + uint8_t f1bc4x_b1_d1; + uint8_t f1bc5x_b1_d1; + uint8_t f1bc8x_b1_d1; + uint8_t f1bc9x_b1_d1; + uint8_t f1bcax_b1_d1; + uint8_t f1bcbx_b1_d1; + uint8_t f2bc2x_b1_d1; + uint8_t f2bc3x_b1_d1; + uint8_t f2bc4x_b1_d1; + uint8_t f2bc5x_b1_d1; + uint8_t f2bc8x_b1_d1; + uint8_t f2bc9x_b1_d1; + uint8_t f2bcax_b1_d1; + uint8_t f2bcbx_b1_d1; + uint8_t f3bc2x_b1_d1; + uint8_t f3bc3x_b1_d1; + uint8_t f3bc4x_b1_d1; + uint8_t f3bc5x_b1_d1; + uint8_t f3bc8x_b1_d1; + uint8_t f3bc9x_b1_d1; + uint8_t f3bcax_b1_d1; + uint8_t f3bcbx_b1_d1; + uint8_t f0bc2x_b2_d1; + uint8_t f0bc3x_b2_d1; + uint8_t f0bc4x_b2_d1; + uint8_t f0bc5x_b2_d1; + uint8_t f0bc8x_b2_d1; + uint8_t f0bc9x_b2_d1; + uint8_t f0bcax_b2_d1; + uint8_t f0bcbx_b2_d1; + uint8_t f1bc2x_b2_d1; + uint8_t f1bc3x_b2_d1; + uint8_t f1bc4x_b2_d1; + uint8_t f1bc5x_b2_d1; + uint8_t f1bc8x_b2_d1; + uint8_t f1bc9x_b2_d1; + uint8_t f1bcax_b2_d1; + uint8_t f1bcbx_b2_d1; + uint8_t f2bc2x_b2_d1; + uint8_t f2bc3x_b2_d1; + uint8_t f2bc4x_b2_d1; + uint8_t f2bc5x_b2_d1; + uint8_t f2bc8x_b2_d1; + uint8_t f2bc9x_b2_d1; + uint8_t f2bcax_b2_d1; + uint8_t f2bcbx_b2_d1; + uint8_t f3bc2x_b2_d1; + uint8_t f3bc3x_b2_d1; + uint8_t f3bc4x_b2_d1; + uint8_t f3bc5x_b2_d1; + uint8_t f3bc8x_b2_d1; + uint8_t f3bc9x_b2_d1; + uint8_t f3bcax_b2_d1; + uint8_t f3bcbx_b2_d1; + uint8_t f0bc2x_b3_d1; + uint8_t f0bc3x_b3_d1; + uint8_t f0bc4x_b3_d1; + uint8_t f0bc5x_b3_d1; + uint8_t f0bc8x_b3_d1; + uint8_t f0bc9x_b3_d1; + uint8_t f0bcax_b3_d1; + uint8_t f0bcbx_b3_d1; + uint8_t f1bc2x_b3_d1; + uint8_t f1bc3x_b3_d1; + uint8_t f1bc4x_b3_d1; + uint8_t f1bc5x_b3_d1; + uint8_t f1bc8x_b3_d1; + uint8_t f1bc9x_b3_d1; + uint8_t f1bcax_b3_d1; + uint8_t f1bcbx_b3_d1; + uint8_t f2bc2x_b3_d1; + uint8_t f2bc3x_b3_d1; + uint8_t f2bc4x_b3_d1; + uint8_t f2bc5x_b3_d1; + uint8_t f2bc8x_b3_d1; + uint8_t f2bc9x_b3_d1; + uint8_t f2bcax_b3_d1; + uint8_t f2bcbx_b3_d1; + uint8_t f3bc2x_b3_d1; + uint8_t f3bc3x_b3_d1; + uint8_t f3bc4x_b3_d1; + uint8_t f3bc5x_b3_d1; + uint8_t f3bc8x_b3_d1; + uint8_t f3bc9x_b3_d1; + uint8_t f3bcax_b3_d1; + uint8_t f3bcbx_b3_d1; + uint8_t f0bc2x_b4_d1; + uint8_t f0bc3x_b4_d1; + uint8_t f0bc4x_b4_d1; + uint8_t f0bc5x_b4_d1; + uint8_t f0bc8x_b4_d1; + uint8_t f0bc9x_b4_d1; + uint8_t f0bcax_b4_d1; + uint8_t f0bcbx_b4_d1; + uint8_t f1bc2x_b4_d1; + uint8_t f1bc3x_b4_d1; + uint8_t f1bc4x_b4_d1; + uint8_t f1bc5x_b4_d1; + uint8_t f1bc8x_b4_d1; + uint8_t f1bc9x_b4_d1; + uint8_t f1bcax_b4_d1; + uint8_t f1bcbx_b4_d1; + uint8_t f2bc2x_b4_d1; + uint8_t f2bc3x_b4_d1; + uint8_t f2bc4x_b4_d1; + uint8_t f2bc5x_b4_d1; + uint8_t f2bc8x_b4_d1; + uint8_t f2bc9x_b4_d1; + uint8_t f2bcax_b4_d1; + uint8_t f2bcbx_b4_d1; + uint8_t f3bc2x_b4_d1; + uint8_t f3bc3x_b4_d1; + uint8_t f3bc4x_b4_d1; + uint8_t f3bc5x_b4_d1; + uint8_t f3bc8x_b4_d1; + uint8_t f3bc9x_b4_d1; + uint8_t f3bcax_b4_d1; + uint8_t f3bcbx_b4_d1; + uint8_t f0bc2x_b5_d1; + uint8_t f0bc3x_b5_d1; + uint8_t f0bc4x_b5_d1; + uint8_t f0bc5x_b5_d1; + uint8_t f0bc8x_b5_d1; + uint8_t f0bc9x_b5_d1; + uint8_t f0bcax_b5_d1; + uint8_t f0bcbx_b5_d1; + uint8_t f1bc2x_b5_d1; + uint8_t f1bc3x_b5_d1; + uint8_t f1bc4x_b5_d1; + uint8_t f1bc5x_b5_d1; + uint8_t f1bc8x_b5_d1; + uint8_t f1bc9x_b5_d1; + uint8_t f1bcax_b5_d1; + uint8_t f1bcbx_b5_d1; + uint8_t f2bc2x_b5_d1; + uint8_t f2bc3x_b5_d1; + uint8_t f2bc4x_b5_d1; + uint8_t f2bc5x_b5_d1; + uint8_t f2bc8x_b5_d1; + uint8_t f2bc9x_b5_d1; + uint8_t f2bcax_b5_d1; + uint8_t f2bcbx_b5_d1; + uint8_t f3bc2x_b5_d1; + uint8_t f3bc3x_b5_d1; + uint8_t f3bc4x_b5_d1; + uint8_t f3bc5x_b5_d1; + uint8_t f3bc8x_b5_d1; + uint8_t f3bc9x_b5_d1; + uint8_t f3bcax_b5_d1; + uint8_t f3bcbx_b5_d1; + uint8_t f0bc2x_b6_d1; + uint8_t f0bc3x_b6_d1; + uint8_t f0bc4x_b6_d1; + uint8_t f0bc5x_b6_d1; + uint8_t f0bc8x_b6_d1; + uint8_t f0bc9x_b6_d1; + uint8_t f0bcax_b6_d1; + uint8_t f0bcbx_b6_d1; + uint8_t f1bc2x_b6_d1; + uint8_t f1bc3x_b6_d1; + uint8_t f1bc4x_b6_d1; + uint8_t f1bc5x_b6_d1; + uint8_t f1bc8x_b6_d1; + uint8_t f1bc9x_b6_d1; + uint8_t f1bcax_b6_d1; + uint8_t f1bcbx_b6_d1; + uint8_t f2bc2x_b6_d1; + uint8_t f2bc3x_b6_d1; + uint8_t f2bc4x_b6_d1; + uint8_t f2bc5x_b6_d1; + uint8_t f2bc8x_b6_d1; + uint8_t f2bc9x_b6_d1; + uint8_t f2bcax_b6_d1; + uint8_t f2bcbx_b6_d1; + uint8_t f3bc2x_b6_d1; + uint8_t f3bc3x_b6_d1; + uint8_t f3bc4x_b6_d1; + uint8_t f3bc5x_b6_d1; + uint8_t f3bc8x_b6_d1; + uint8_t f3bc9x_b6_d1; + uint8_t f3bcax_b6_d1; + uint8_t f3bcbx_b6_d1; + uint8_t f0bc2x_b7_d1; + uint8_t f0bc3x_b7_d1; + uint8_t f0bc4x_b7_d1; + uint8_t f0bc5x_b7_d1; + uint8_t f0bc8x_b7_d1; + uint8_t f0bc9x_b7_d1; + uint8_t f0bcax_b7_d1; + uint8_t f0bcbx_b7_d1; + uint8_t f1bc2x_b7_d1; + uint8_t f1bc3x_b7_d1; + uint8_t f1bc4x_b7_d1; + uint8_t f1bc5x_b7_d1; + uint8_t f1bc8x_b7_d1; + uint8_t f1bc9x_b7_d1; + uint8_t f1bcax_b7_d1; + uint8_t f1bcbx_b7_d1; + uint8_t f2bc2x_b7_d1; + uint8_t f2bc3x_b7_d1; + uint8_t f2bc4x_b7_d1; + uint8_t f2bc5x_b7_d1; + uint8_t f2bc8x_b7_d1; + uint8_t f2bc9x_b7_d1; + uint8_t f2bcax_b7_d1; + uint8_t f2bcbx_b7_d1; + uint8_t f3bc2x_b7_d1; + uint8_t f3bc3x_b7_d1; + uint8_t f3bc4x_b7_d1; + uint8_t f3bc5x_b7_d1; + uint8_t f3bc8x_b7_d1; + uint8_t f3bc9x_b7_d1; + uint8_t f3bcax_b7_d1; + uint8_t f3bcbx_b7_d1; + uint8_t f0bc2x_b8_d1; + uint8_t f0bc3x_b8_d1; + uint8_t f0bc4x_b8_d1; + uint8_t f0bc5x_b8_d1; + uint8_t f0bc8x_b8_d1; + uint8_t f0bc9x_b8_d1; + uint8_t f0bcax_b8_d1; + uint8_t f0bcbx_b8_d1; + uint8_t f1bc2x_b8_d1; + uint8_t f1bc3x_b8_d1; + uint8_t f1bc4x_b8_d1; + uint8_t f1bc5x_b8_d1; + uint8_t f1bc8x_b8_d1; + uint8_t f1bc9x_b8_d1; + uint8_t f1bcax_b8_d1; + uint8_t f1bcbx_b8_d1; + uint8_t f2bc2x_b8_d1; + uint8_t f2bc3x_b8_d1; + uint8_t f2bc4x_b8_d1; + uint8_t f2bc5x_b8_d1; + uint8_t f2bc8x_b8_d1; + uint8_t f2bc9x_b8_d1; + uint8_t f2bcax_b8_d1; + uint8_t f2bcbx_b8_d1; + uint8_t f3bc2x_b8_d1; + uint8_t f3bc3x_b8_d1; + uint8_t f3bc4x_b8_d1; + uint8_t f3bc5x_b8_d1; + uint8_t f3bc8x_b8_d1; + uint8_t f3bc9x_b8_d1; + uint8_t f3bcax_b8_d1; + uint8_t f3bcbx_b8_d1; + uint8_t f5bc5x_d1; + uint8_t f5bc6x_d1; + uint8_t f4bc8x_d1; + uint8_t f4bc9x_d1; + uint8_t f4bcax_d1; + uint8_t f4bcbx_d1; + uint8_t f4bccx_d1; + uint8_t f4bcdx_d1; + uint8_t f4bcex_d1; + uint8_t f4bcfx_d1; + uint8_t f5bc8x_d1; + uint8_t f5bc9x_d1; + uint8_t f5bcax_d1; + uint8_t f5bcbx_d1; + uint8_t f5bccx_d1; + uint8_t f5bcdx_d1; + uint8_t f5bcex_d1; + uint8_t f5bcfx_d1; + uint8_t f6bc8x_d1; + uint8_t f6bc9x_d1; + uint8_t f6bcax_d1; + uint8_t f6bcbx_d1; + uint8_t f6bccx_d1; + uint8_t f6bcdx_d1; + uint8_t f6bcex_d1; + uint8_t f6bcfx_d1; + uint8_t f7bc8x_d1; + uint8_t f7bc9x_d1; + uint8_t f7bcax_d1; + uint8_t f7bcbx_d1; + uint8_t f7bccx_d1; + uint8_t f7bcdx_d1; + uint8_t f7bcex_d1; + uint8_t f7bcfx_d1; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4lr2d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t rx2d_train_opt; + uint8_t tx2d_train_opt; + uint8_t share2dvref_result; + uint8_t delay_weight2d; + uint8_t voltage_weight2d; + uint8_t reserved1e[0x22 - 0x1e]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + uint8_t r0_rx_clk_dly_margin; + uint8_t r0_vref_dac_margin; + uint8_t r0_tx_dq_dly_margin; + uint8_t r0_device_vref_margin; + uint8_t reserved29[0x33 - 0x29]; + uint8_t r1_rx_clk_dly_margin; + uint8_t r1_vref_dac_margin; + uint8_t r1_tx_dq_dly_margin; + uint8_t r1_device_vref_margin; + uint8_t reserved37[0x41 - 0x37]; + uint8_t r2_rx_clk_dly_margin; + uint8_t r2_vref_dac_margin; + uint8_t r2_tx_dq_dly_margin; + uint8_t r2_device_vref_margin; + uint8_t reserved45[0x4f - 0x45]; + uint8_t r3_rx_clk_dly_margin; + uint8_t r3_vref_dac_margin; + uint8_t r3_tx_dq_dly_margin; + uint8_t r3_device_vref_margin; + uint8_t reserved53[0x5e - 0x53]; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t f0rc00_d0; + uint8_t f0rc01_d0; + uint8_t f0rc02_d0; + uint8_t f0rc03_d0; + uint8_t f0rc04_d0; + uint8_t f0rc05_d0; + uint8_t f0rc06_d0; + uint8_t f0rc07_d0; + uint8_t f0rc08_d0; + uint8_t f0rc09_d0; + uint8_t f0rc0a_d0; + uint8_t f0rc0b_d0; + uint8_t f0rc0c_d0; + uint8_t f0rc0d_d0; + uint8_t f0rc0e_d0; + uint8_t f0rc0f_d0; + uint8_t f0rc1x_d0; + uint8_t f0rc2x_d0; + uint8_t f0rc3x_d0; + uint8_t f0rc4x_d0; + uint8_t f0rc5x_d0; + uint8_t f0rc6x_d0; + uint8_t f0rc7x_d0; + uint8_t f0rc8x_d0; + uint8_t f0rc9x_d0; + uint8_t f0rcax_d0; + uint8_t f0rcbx_d0; + uint8_t f1rc00_d0; + uint8_t f1rc01_d0; + uint8_t f1rc02_d0; + uint8_t f1rc03_d0; + uint8_t f1rc04_d0; + uint8_t f1rc05_d0; + uint8_t f1rc06_d0; + uint8_t f1rc07_d0; + uint8_t f1rc08_d0; + uint8_t f1rc09_d0; + uint8_t f1rc0a_d0; + uint8_t f1rc0b_d0; + uint8_t f1rc0c_d0; + uint8_t f1rc0d_d0; + uint8_t f1rc0e_d0; + uint8_t f1rc0f_d0; + uint8_t f1rc1x_d0; + uint8_t f1rc2x_d0; + uint8_t f1rc3x_d0; + uint8_t f1rc4x_d0; + uint8_t f1rc5x_d0; + uint8_t f1rc6x_d0; + uint8_t f1rc7x_d0; + uint8_t f1rc8x_d0; + uint8_t f1rc9x_d0; + uint8_t f1rcax_d0; + uint8_t f1rcbx_d0; + uint8_t f0rc00_d1; + uint8_t f0rc01_d1; + uint8_t f0rc02_d1; + uint8_t f0rc03_d1; + uint8_t f0rc04_d1; + uint8_t f0rc05_d1; + uint8_t f0rc06_d1; + uint8_t f0rc07_d1; + uint8_t f0rc08_d1; + uint8_t f0rc09_d1; + uint8_t f0rc0a_d1; + uint8_t f0rc0b_d1; + uint8_t f0rc0c_d1; + uint8_t f0rc0d_d1; + uint8_t f0rc0e_d1; + uint8_t f0rc0f_d1; + uint8_t f0rc1x_d1; + uint8_t f0rc2x_d1; + uint8_t f0rc3x_d1; + uint8_t f0rc4x_d1; + uint8_t f0rc5x_d1; + uint8_t f0rc6x_d1; + uint8_t f0rc7x_d1; + uint8_t f0rc8x_d1; + uint8_t f0rc9x_d1; + uint8_t f0rcax_d1; + uint8_t f0rcbx_d1; + uint8_t f1rc00_d1; + uint8_t f1rc01_d1; + uint8_t f1rc02_d1; + uint8_t f1rc03_d1; + uint8_t f1rc04_d1; + uint8_t f1rc05_d1; + uint8_t f1rc06_d1; + uint8_t f1rc07_d1; + uint8_t f1rc08_d1; + uint8_t f1rc09_d1; + uint8_t f1rc0a_d1; + uint8_t f1rc0b_d1; + uint8_t f1rc0c_d1; + uint8_t f1rc0d_d1; + uint8_t f1rc0e_d1; + uint8_t f1rc0f_d1; + uint8_t f1rc1x_d1; + uint8_t f1rc2x_d1; + uint8_t f1rc3x_d1; + uint8_t f1rc4x_d1; + uint8_t f1rc5x_d1; + uint8_t f1rc6x_d1; + uint8_t f1rc7x_d1; + uint8_t f1rc8x_d1; + uint8_t f1rc9x_d1; + uint8_t f1rcax_d1; + uint8_t f1rcbx_d1; + uint8_t bc00_d0; + uint8_t bc01_d0; + uint8_t bc02_d0; + uint8_t bc03_d0; + uint8_t bc04_d0; + uint8_t bc05_d0; + uint8_t bc06_d0; + uint8_t bc07_d0; + uint8_t bc08_d0; + uint8_t bc09_d0; + uint8_t bc0a_d0; + uint8_t bc0b_d0; + uint8_t bc0c_d0; + uint8_t bc0d_d0; + uint8_t bc0e_d0; + uint8_t f0bc6x_d0; + uint8_t f0bccx_d0; + uint8_t f0bcdx_d0; + uint8_t f0bcex_d0; + uint8_t f0bcfx_d0; + uint8_t f1bccx_d0; + uint8_t f1bcdx_d0; + uint8_t f1bcex_d0; + uint8_t f1bcfx_d0; + uint8_t f0bc2x_b0_d0; + uint8_t f0bc3x_b0_d0; + uint8_t f0bc4x_b0_d0; + uint8_t f0bc5x_b0_d0; + uint8_t f0bc8x_b0_d0; + uint8_t f0bc9x_b0_d0; + uint8_t f0bcax_b0_d0; + uint8_t f0bcbx_b0_d0; + uint8_t f1bc2x_b0_d0; + uint8_t f1bc3x_b0_d0; + uint8_t f1bc4x_b0_d0; + uint8_t f1bc5x_b0_d0; + uint8_t f1bc8x_b0_d0; + uint8_t f1bc9x_b0_d0; + uint8_t f1bcax_b0_d0; + uint8_t f1bcbx_b0_d0; + uint8_t f2bc2x_b0_d0; + uint8_t f2bc3x_b0_d0; + uint8_t f2bc4x_b0_d0; + uint8_t f2bc5x_b0_d0; + uint8_t f2bc8x_b0_d0; + uint8_t f2bc9x_b0_d0; + uint8_t f2bcax_b0_d0; + uint8_t f2bcbx_b0_d0; + uint8_t f3bc2x_b0_d0; + uint8_t f3bc3x_b0_d0; + uint8_t f3bc4x_b0_d0; + uint8_t f3bc5x_b0_d0; + uint8_t f3bc8x_b0_d0; + uint8_t f3bc9x_b0_d0; + uint8_t f3bcax_b0_d0; + uint8_t f3bcbx_b0_d0; + uint8_t f0bc2x_b1_d0; + uint8_t f0bc3x_b1_d0; + uint8_t f0bc4x_b1_d0; + uint8_t f0bc5x_b1_d0; + uint8_t f0bc8x_b1_d0; + uint8_t f0bc9x_b1_d0; + uint8_t f0bcax_b1_d0; + uint8_t f0bcbx_b1_d0; + uint8_t f1bc2x_b1_d0; + uint8_t f1bc3x_b1_d0; + uint8_t f1bc4x_b1_d0; + uint8_t f1bc5x_b1_d0; + uint8_t f1bc8x_b1_d0; + uint8_t f1bc9x_b1_d0; + uint8_t f1bcax_b1_d0; + uint8_t f1bcbx_b1_d0; + uint8_t f2bc2x_b1_d0; + uint8_t f2bc3x_b1_d0; + uint8_t f2bc4x_b1_d0; + uint8_t f2bc5x_b1_d0; + uint8_t f2bc8x_b1_d0; + uint8_t f2bc9x_b1_d0; + uint8_t f2bcax_b1_d0; + uint8_t f2bcbx_b1_d0; + uint8_t f3bc2x_b1_d0; + uint8_t f3bc3x_b1_d0; + uint8_t f3bc4x_b1_d0; + uint8_t f3bc5x_b1_d0; + uint8_t f3bc8x_b1_d0; + uint8_t f3bc9x_b1_d0; + uint8_t f3bcax_b1_d0; + uint8_t f3bcbx_b1_d0; + uint8_t f0bc2x_b2_d0; + uint8_t f0bc3x_b2_d0; + uint8_t f0bc4x_b2_d0; + uint8_t f0bc5x_b2_d0; + uint8_t f0bc8x_b2_d0; + uint8_t f0bc9x_b2_d0; + uint8_t f0bcax_b2_d0; + uint8_t f0bcbx_b2_d0; + uint8_t f1bc2x_b2_d0; + uint8_t f1bc3x_b2_d0; + uint8_t f1bc4x_b2_d0; + uint8_t f1bc5x_b2_d0; + uint8_t f1bc8x_b2_d0; + uint8_t f1bc9x_b2_d0; + uint8_t f1bcax_b2_d0; + uint8_t f1bcbx_b2_d0; + uint8_t f2bc2x_b2_d0; + uint8_t f2bc3x_b2_d0; + uint8_t f2bc4x_b2_d0; + uint8_t f2bc5x_b2_d0; + uint8_t f2bc8x_b2_d0; + uint8_t f2bc9x_b2_d0; + uint8_t f2bcax_b2_d0; + uint8_t f2bcbx_b2_d0; + uint8_t f3bc2x_b2_d0; + uint8_t f3bc3x_b2_d0; + uint8_t f3bc4x_b2_d0; + uint8_t f3bc5x_b2_d0; + uint8_t f3bc8x_b2_d0; + uint8_t f3bc9x_b2_d0; + uint8_t f3bcax_b2_d0; + uint8_t f3bcbx_b2_d0; + uint8_t f0bc2x_b3_d0; + uint8_t f0bc3x_b3_d0; + uint8_t f0bc4x_b3_d0; + uint8_t f0bc5x_b3_d0; + uint8_t f0bc8x_b3_d0; + uint8_t f0bc9x_b3_d0; + uint8_t f0bcax_b3_d0; + uint8_t f0bcbx_b3_d0; + uint8_t f1bc2x_b3_d0; + uint8_t f1bc3x_b3_d0; + uint8_t f1bc4x_b3_d0; + uint8_t f1bc5x_b3_d0; + uint8_t f1bc8x_b3_d0; + uint8_t f1bc9x_b3_d0; + uint8_t f1bcax_b3_d0; + uint8_t f1bcbx_b3_d0; + uint8_t f2bc2x_b3_d0; + uint8_t f2bc3x_b3_d0; + uint8_t f2bc4x_b3_d0; + uint8_t f2bc5x_b3_d0; + uint8_t f2bc8x_b3_d0; + uint8_t f2bc9x_b3_d0; + uint8_t f2bcax_b3_d0; + uint8_t f2bcbx_b3_d0; + uint8_t f3bc2x_b3_d0; + uint8_t f3bc3x_b3_d0; + uint8_t f3bc4x_b3_d0; + uint8_t f3bc5x_b3_d0; + uint8_t f3bc8x_b3_d0; + uint8_t f3bc9x_b3_d0; + uint8_t f3bcax_b3_d0; + uint8_t f3bcbx_b3_d0; + uint8_t f0bc2x_b4_d0; + uint8_t f0bc3x_b4_d0; + uint8_t f0bc4x_b4_d0; + uint8_t f0bc5x_b4_d0; + uint8_t f0bc8x_b4_d0; + uint8_t f0bc9x_b4_d0; + uint8_t f0bcax_b4_d0; + uint8_t f0bcbx_b4_d0; + uint8_t f1bc2x_b4_d0; + uint8_t f1bc3x_b4_d0; + uint8_t f1bc4x_b4_d0; + uint8_t f1bc5x_b4_d0; + uint8_t f1bc8x_b4_d0; + uint8_t f1bc9x_b4_d0; + uint8_t f1bcax_b4_d0; + uint8_t f1bcbx_b4_d0; + uint8_t f2bc2x_b4_d0; + uint8_t f2bc3x_b4_d0; + uint8_t f2bc4x_b4_d0; + uint8_t f2bc5x_b4_d0; + uint8_t f2bc8x_b4_d0; + uint8_t f2bc9x_b4_d0; + uint8_t f2bcax_b4_d0; + uint8_t f2bcbx_b4_d0; + uint8_t f3bc2x_b4_d0; + uint8_t f3bc3x_b4_d0; + uint8_t f3bc4x_b4_d0; + uint8_t f3bc5x_b4_d0; + uint8_t f3bc8x_b4_d0; + uint8_t f3bc9x_b4_d0; + uint8_t f3bcax_b4_d0; + uint8_t f3bcbx_b4_d0; + uint8_t f0bc2x_b5_d0; + uint8_t f0bc3x_b5_d0; + uint8_t f0bc4x_b5_d0; + uint8_t f0bc5x_b5_d0; + uint8_t f0bc8x_b5_d0; + uint8_t f0bc9x_b5_d0; + uint8_t f0bcax_b5_d0; + uint8_t f0bcbx_b5_d0; + uint8_t f1bc2x_b5_d0; + uint8_t f1bc3x_b5_d0; + uint8_t f1bc4x_b5_d0; + uint8_t f1bc5x_b5_d0; + uint8_t f1bc8x_b5_d0; + uint8_t f1bc9x_b5_d0; + uint8_t f1bcax_b5_d0; + uint8_t f1bcbx_b5_d0; + uint8_t f2bc2x_b5_d0; + uint8_t f2bc3x_b5_d0; + uint8_t f2bc4x_b5_d0; + uint8_t f2bc5x_b5_d0; + uint8_t f2bc8x_b5_d0; + uint8_t f2bc9x_b5_d0; + uint8_t f2bcax_b5_d0; + uint8_t f2bcbx_b5_d0; + uint8_t f3bc2x_b5_d0; + uint8_t f3bc3x_b5_d0; + uint8_t f3bc4x_b5_d0; + uint8_t f3bc5x_b5_d0; + uint8_t f3bc8x_b5_d0; + uint8_t f3bc9x_b5_d0; + uint8_t f3bcax_b5_d0; + uint8_t f3bcbx_b5_d0; + uint8_t f0bc2x_b6_d0; + uint8_t f0bc3x_b6_d0; + uint8_t f0bc4x_b6_d0; + uint8_t f0bc5x_b6_d0; + uint8_t f0bc8x_b6_d0; + uint8_t f0bc9x_b6_d0; + uint8_t f0bcax_b6_d0; + uint8_t f0bcbx_b6_d0; + uint8_t f1bc2x_b6_d0; + uint8_t f1bc3x_b6_d0; + uint8_t f1bc4x_b6_d0; + uint8_t f1bc5x_b6_d0; + uint8_t f1bc8x_b6_d0; + uint8_t f1bc9x_b6_d0; + uint8_t f1bcax_b6_d0; + uint8_t f1bcbx_b6_d0; + uint8_t f2bc2x_b6_d0; + uint8_t f2bc3x_b6_d0; + uint8_t f2bc4x_b6_d0; + uint8_t f2bc5x_b6_d0; + uint8_t f2bc8x_b6_d0; + uint8_t f2bc9x_b6_d0; + uint8_t f2bcax_b6_d0; + uint8_t f2bcbx_b6_d0; + uint8_t f3bc2x_b6_d0; + uint8_t f3bc3x_b6_d0; + uint8_t f3bc4x_b6_d0; + uint8_t f3bc5x_b6_d0; + uint8_t f3bc8x_b6_d0; + uint8_t f3bc9x_b6_d0; + uint8_t f3bcax_b6_d0; + uint8_t f3bcbx_b6_d0; + uint8_t f0bc2x_b7_d0; + uint8_t f0bc3x_b7_d0; + uint8_t f0bc4x_b7_d0; + uint8_t f0bc5x_b7_d0; + uint8_t f0bc8x_b7_d0; + uint8_t f0bc9x_b7_d0; + uint8_t f0bcax_b7_d0; + uint8_t f0bcbx_b7_d0; + uint8_t f1bc2x_b7_d0; + uint8_t f1bc3x_b7_d0; + uint8_t f1bc4x_b7_d0; + uint8_t f1bc5x_b7_d0; + uint8_t f1bc8x_b7_d0; + uint8_t f1bc9x_b7_d0; + uint8_t f1bcax_b7_d0; + uint8_t f1bcbx_b7_d0; + uint8_t f2bc2x_b7_d0; + uint8_t f2bc3x_b7_d0; + uint8_t f2bc4x_b7_d0; + uint8_t f2bc5x_b7_d0; + uint8_t f2bc8x_b7_d0; + uint8_t f2bc9x_b7_d0; + uint8_t f2bcax_b7_d0; + uint8_t f2bcbx_b7_d0; + uint8_t f3bc2x_b7_d0; + uint8_t f3bc3x_b7_d0; + uint8_t f3bc4x_b7_d0; + uint8_t f3bc5x_b7_d0; + uint8_t f3bc8x_b7_d0; + uint8_t f3bc9x_b7_d0; + uint8_t f3bcax_b7_d0; + uint8_t f3bcbx_b7_d0; + uint8_t f0bc2x_b8_d0; + uint8_t f0bc3x_b8_d0; + uint8_t f0bc4x_b8_d0; + uint8_t f0bc5x_b8_d0; + uint8_t f0bc8x_b8_d0; + uint8_t f0bc9x_b8_d0; + uint8_t f0bcax_b8_d0; + uint8_t f0bcbx_b8_d0; + uint8_t f1bc2x_b8_d0; + uint8_t f1bc3x_b8_d0; + uint8_t f1bc4x_b8_d0; + uint8_t f1bc5x_b8_d0; + uint8_t f1bc8x_b8_d0; + uint8_t f1bc9x_b8_d0; + uint8_t f1bcax_b8_d0; + uint8_t f1bcbx_b8_d0; + uint8_t f2bc2x_b8_d0; + uint8_t f2bc3x_b8_d0; + uint8_t f2bc4x_b8_d0; + uint8_t f2bc5x_b8_d0; + uint8_t f2bc8x_b8_d0; + uint8_t f2bc9x_b8_d0; + uint8_t f2bcax_b8_d0; + uint8_t f2bcbx_b8_d0; + uint8_t f3bc2x_b8_d0; + uint8_t f3bc3x_b8_d0; + uint8_t f3bc4x_b8_d0; + uint8_t f3bc5x_b8_d0; + uint8_t f3bc8x_b8_d0; + uint8_t f3bc9x_b8_d0; + uint8_t f3bcax_b8_d0; + uint8_t f3bcbx_b8_d0; + uint8_t f5bc5x_d0; + uint8_t f5bc6x_d0; + uint8_t f4bc8x_d0; + uint8_t f4bc9x_d0; + uint8_t f4bcax_d0; + uint8_t f4bcbx_d0; + uint8_t f4bccx_d0; + uint8_t f4bcdx_d0; + uint8_t f4bcex_d0; + uint8_t f4bcfx_d0; + uint8_t f5bc8x_d0; + uint8_t f5bc9x_d0; + uint8_t f5bcax_d0; + uint8_t f5bcbx_d0; + uint8_t f5bccx_d0; + uint8_t f5bcdx_d0; + uint8_t f5bcex_d0; + uint8_t f5bcfx_d0; + uint8_t f6bc8x_d0; + uint8_t f6bc9x_d0; + uint8_t f6bcax_d0; + uint8_t f6bcbx_d0; + uint8_t f6bccx_d0; + uint8_t f6bcdx_d0; + uint8_t f6bcex_d0; + uint8_t f6bcfx_d0; + uint8_t f7bc8x_d0; + uint8_t f7bc9x_d0; + uint8_t f7bcax_d0; + uint8_t f7bcbx_d0; + uint8_t f7bccx_d0; + uint8_t f7bcdx_d0; + uint8_t f7bcex_d0; + uint8_t f7bcfx_d0; + uint8_t bc00_d1; + uint8_t bc01_d1; + uint8_t bc02_d1; + uint8_t bc03_d1; + uint8_t bc04_d1; + uint8_t bc05_d1; + uint8_t bc06_d1; + uint8_t bc07_d1; + uint8_t bc08_d1; + uint8_t bc09_d1; + uint8_t bc0a_d1; + uint8_t bc0b_d1; + uint8_t bc0c_d1; + uint8_t bc0d_d1; + uint8_t bc0e_d1; + uint8_t f0bc6x_d1; + uint8_t f0bccx_d1; + uint8_t f0bcdx_d1; + uint8_t f0bcex_d1; + uint8_t f0bcfx_d1; + uint8_t f1bccx_d1; + uint8_t f1bcdx_d1; + uint8_t f1bcex_d1; + uint8_t f1bcfx_d1; + uint8_t f0bc2x_b0_d1; + uint8_t f0bc3x_b0_d1; + uint8_t f0bc4x_b0_d1; + uint8_t f0bc5x_b0_d1; + uint8_t f0bc8x_b0_d1; + uint8_t f0bc9x_b0_d1; + uint8_t f0bcax_b0_d1; + uint8_t f0bcbx_b0_d1; + uint8_t f1bc2x_b0_d1; + uint8_t f1bc3x_b0_d1; + uint8_t f1bc4x_b0_d1; + uint8_t f1bc5x_b0_d1; + uint8_t f1bc8x_b0_d1; + uint8_t f1bc9x_b0_d1; + uint8_t f1bcax_b0_d1; + uint8_t f1bcbx_b0_d1; + uint8_t f2bc2x_b0_d1; + uint8_t f2bc3x_b0_d1; + uint8_t f2bc4x_b0_d1; + uint8_t f2bc5x_b0_d1; + uint8_t f2bc8x_b0_d1; + uint8_t f2bc9x_b0_d1; + uint8_t f2bcax_b0_d1; + uint8_t f2bcbx_b0_d1; + uint8_t f3bc2x_b0_d1; + uint8_t f3bc3x_b0_d1; + uint8_t f3bc4x_b0_d1; + uint8_t f3bc5x_b0_d1; + uint8_t f3bc8x_b0_d1; + uint8_t f3bc9x_b0_d1; + uint8_t f3bcax_b0_d1; + uint8_t f3bcbx_b0_d1; + uint8_t f0bc2x_b1_d1; + uint8_t f0bc3x_b1_d1; + uint8_t f0bc4x_b1_d1; + uint8_t f0bc5x_b1_d1; + uint8_t f0bc8x_b1_d1; + uint8_t f0bc9x_b1_d1; + uint8_t f0bcax_b1_d1; + uint8_t f0bcbx_b1_d1; + uint8_t f1bc2x_b1_d1; + uint8_t f1bc3x_b1_d1; + uint8_t f1bc4x_b1_d1; + uint8_t f1bc5x_b1_d1; + uint8_t f1bc8x_b1_d1; + uint8_t f1bc9x_b1_d1; + uint8_t f1bcax_b1_d1; + uint8_t f1bcbx_b1_d1; + uint8_t f2bc2x_b1_d1; + uint8_t f2bc3x_b1_d1; + uint8_t f2bc4x_b1_d1; + uint8_t f2bc5x_b1_d1; + uint8_t f2bc8x_b1_d1; + uint8_t f2bc9x_b1_d1; + uint8_t f2bcax_b1_d1; + uint8_t f2bcbx_b1_d1; + uint8_t f3bc2x_b1_d1; + uint8_t f3bc3x_b1_d1; + uint8_t f3bc4x_b1_d1; + uint8_t f3bc5x_b1_d1; + uint8_t f3bc8x_b1_d1; + uint8_t f3bc9x_b1_d1; + uint8_t f3bcax_b1_d1; + uint8_t f3bcbx_b1_d1; + uint8_t f0bc2x_b2_d1; + uint8_t f0bc3x_b2_d1; + uint8_t f0bc4x_b2_d1; + uint8_t f0bc5x_b2_d1; + uint8_t f0bc8x_b2_d1; + uint8_t f0bc9x_b2_d1; + uint8_t f0bcax_b2_d1; + uint8_t f0bcbx_b2_d1; + uint8_t f1bc2x_b2_d1; + uint8_t f1bc3x_b2_d1; + uint8_t f1bc4x_b2_d1; + uint8_t f1bc5x_b2_d1; + uint8_t f1bc8x_b2_d1; + uint8_t f1bc9x_b2_d1; + uint8_t f1bcax_b2_d1; + uint8_t f1bcbx_b2_d1; + uint8_t f2bc2x_b2_d1; + uint8_t f2bc3x_b2_d1; + uint8_t f2bc4x_b2_d1; + uint8_t f2bc5x_b2_d1; + uint8_t f2bc8x_b2_d1; + uint8_t f2bc9x_b2_d1; + uint8_t f2bcax_b2_d1; + uint8_t f2bcbx_b2_d1; + uint8_t f3bc2x_b2_d1; + uint8_t f3bc3x_b2_d1; + uint8_t f3bc4x_b2_d1; + uint8_t f3bc5x_b2_d1; + uint8_t f3bc8x_b2_d1; + uint8_t f3bc9x_b2_d1; + uint8_t f3bcax_b2_d1; + uint8_t f3bcbx_b2_d1; + uint8_t f0bc2x_b3_d1; + uint8_t f0bc3x_b3_d1; + uint8_t f0bc4x_b3_d1; + uint8_t f0bc5x_b3_d1; + uint8_t f0bc8x_b3_d1; + uint8_t f0bc9x_b3_d1; + uint8_t f0bcax_b3_d1; + uint8_t f0bcbx_b3_d1; + uint8_t f1bc2x_b3_d1; + uint8_t f1bc3x_b3_d1; + uint8_t f1bc4x_b3_d1; + uint8_t f1bc5x_b3_d1; + uint8_t f1bc8x_b3_d1; + uint8_t f1bc9x_b3_d1; + uint8_t f1bcax_b3_d1; + uint8_t f1bcbx_b3_d1; + uint8_t f2bc2x_b3_d1; + uint8_t f2bc3x_b3_d1; + uint8_t f2bc4x_b3_d1; + uint8_t f2bc5x_b3_d1; + uint8_t f2bc8x_b3_d1; + uint8_t f2bc9x_b3_d1; + uint8_t f2bcax_b3_d1; + uint8_t f2bcbx_b3_d1; + uint8_t f3bc2x_b3_d1; + uint8_t f3bc3x_b3_d1; + uint8_t f3bc4x_b3_d1; + uint8_t f3bc5x_b3_d1; + uint8_t f3bc8x_b3_d1; + uint8_t f3bc9x_b3_d1; + uint8_t f3bcax_b3_d1; + uint8_t f3bcbx_b3_d1; + uint8_t f0bc2x_b4_d1; + uint8_t f0bc3x_b4_d1; + uint8_t f0bc4x_b4_d1; + uint8_t f0bc5x_b4_d1; + uint8_t f0bc8x_b4_d1; + uint8_t f0bc9x_b4_d1; + uint8_t f0bcax_b4_d1; + uint8_t f0bcbx_b4_d1; + uint8_t f1bc2x_b4_d1; + uint8_t f1bc3x_b4_d1; + uint8_t f1bc4x_b4_d1; + uint8_t f1bc5x_b4_d1; + uint8_t f1bc8x_b4_d1; + uint8_t f1bc9x_b4_d1; + uint8_t f1bcax_b4_d1; + uint8_t f1bcbx_b4_d1; + uint8_t f2bc2x_b4_d1; + uint8_t f2bc3x_b4_d1; + uint8_t f2bc4x_b4_d1; + uint8_t f2bc5x_b4_d1; + uint8_t f2bc8x_b4_d1; + uint8_t f2bc9x_b4_d1; + uint8_t f2bcax_b4_d1; + uint8_t f2bcbx_b4_d1; + uint8_t f3bc2x_b4_d1; + uint8_t f3bc3x_b4_d1; + uint8_t f3bc4x_b4_d1; + uint8_t f3bc5x_b4_d1; + uint8_t f3bc8x_b4_d1; + uint8_t f3bc9x_b4_d1; + uint8_t f3bcax_b4_d1; + uint8_t f3bcbx_b4_d1; + uint8_t f0bc2x_b5_d1; + uint8_t f0bc3x_b5_d1; + uint8_t f0bc4x_b5_d1; + uint8_t f0bc5x_b5_d1; + uint8_t f0bc8x_b5_d1; + uint8_t f0bc9x_b5_d1; + uint8_t f0bcax_b5_d1; + uint8_t f0bcbx_b5_d1; + uint8_t f1bc2x_b5_d1; + uint8_t f1bc3x_b5_d1; + uint8_t f1bc4x_b5_d1; + uint8_t f1bc5x_b5_d1; + uint8_t f1bc8x_b5_d1; + uint8_t f1bc9x_b5_d1; + uint8_t f1bcax_b5_d1; + uint8_t f1bcbx_b5_d1; + uint8_t f2bc2x_b5_d1; + uint8_t f2bc3x_b5_d1; + uint8_t f2bc4x_b5_d1; + uint8_t f2bc5x_b5_d1; + uint8_t f2bc8x_b5_d1; + uint8_t f2bc9x_b5_d1; + uint8_t f2bcax_b5_d1; + uint8_t f2bcbx_b5_d1; + uint8_t f3bc2x_b5_d1; + uint8_t f3bc3x_b5_d1; + uint8_t f3bc4x_b5_d1; + uint8_t f3bc5x_b5_d1; + uint8_t f3bc8x_b5_d1; + uint8_t f3bc9x_b5_d1; + uint8_t f3bcax_b5_d1; + uint8_t f3bcbx_b5_d1; + uint8_t f0bc2x_b6_d1; + uint8_t f0bc3x_b6_d1; + uint8_t f0bc4x_b6_d1; + uint8_t f0bc5x_b6_d1; + uint8_t f0bc8x_b6_d1; + uint8_t f0bc9x_b6_d1; + uint8_t f0bcax_b6_d1; + uint8_t f0bcbx_b6_d1; + uint8_t f1bc2x_b6_d1; + uint8_t f1bc3x_b6_d1; + uint8_t f1bc4x_b6_d1; + uint8_t f1bc5x_b6_d1; + uint8_t f1bc8x_b6_d1; + uint8_t f1bc9x_b6_d1; + uint8_t f1bcax_b6_d1; + uint8_t f1bcbx_b6_d1; + uint8_t f2bc2x_b6_d1; + uint8_t f2bc3x_b6_d1; + uint8_t f2bc4x_b6_d1; + uint8_t f2bc5x_b6_d1; + uint8_t f2bc8x_b6_d1; + uint8_t f2bc9x_b6_d1; + uint8_t f2bcax_b6_d1; + uint8_t f2bcbx_b6_d1; + uint8_t f3bc2x_b6_d1; + uint8_t f3bc3x_b6_d1; + uint8_t f3bc4x_b6_d1; + uint8_t f3bc5x_b6_d1; + uint8_t f3bc8x_b6_d1; + uint8_t f3bc9x_b6_d1; + uint8_t f3bcax_b6_d1; + uint8_t f3bcbx_b6_d1; + uint8_t f0bc2x_b7_d1; + uint8_t f0bc3x_b7_d1; + uint8_t f0bc4x_b7_d1; + uint8_t f0bc5x_b7_d1; + uint8_t f0bc8x_b7_d1; + uint8_t f0bc9x_b7_d1; + uint8_t f0bcax_b7_d1; + uint8_t f0bcbx_b7_d1; + uint8_t f1bc2x_b7_d1; + uint8_t f1bc3x_b7_d1; + uint8_t f1bc4x_b7_d1; + uint8_t f1bc5x_b7_d1; + uint8_t f1bc8x_b7_d1; + uint8_t f1bc9x_b7_d1; + uint8_t f1bcax_b7_d1; + uint8_t f1bcbx_b7_d1; + uint8_t f2bc2x_b7_d1; + uint8_t f2bc3x_b7_d1; + uint8_t f2bc4x_b7_d1; + uint8_t f2bc5x_b7_d1; + uint8_t f2bc8x_b7_d1; + uint8_t f2bc9x_b7_d1; + uint8_t f2bcax_b7_d1; + uint8_t f2bcbx_b7_d1; + uint8_t f3bc2x_b7_d1; + uint8_t f3bc3x_b7_d1; + uint8_t f3bc4x_b7_d1; + uint8_t f3bc5x_b7_d1; + uint8_t f3bc8x_b7_d1; + uint8_t f3bc9x_b7_d1; + uint8_t f3bcax_b7_d1; + uint8_t f3bcbx_b7_d1; + uint8_t f0bc2x_b8_d1; + uint8_t f0bc3x_b8_d1; + uint8_t f0bc4x_b8_d1; + uint8_t f0bc5x_b8_d1; + uint8_t f0bc8x_b8_d1; + uint8_t f0bc9x_b8_d1; + uint8_t f0bcax_b8_d1; + uint8_t f0bcbx_b8_d1; + uint8_t f1bc2x_b8_d1; + uint8_t f1bc3x_b8_d1; + uint8_t f1bc4x_b8_d1; + uint8_t f1bc5x_b8_d1; + uint8_t f1bc8x_b8_d1; + uint8_t f1bc9x_b8_d1; + uint8_t f1bcax_b8_d1; + uint8_t f1bcbx_b8_d1; + uint8_t f2bc2x_b8_d1; + uint8_t f2bc3x_b8_d1; + uint8_t f2bc4x_b8_d1; + uint8_t f2bc5x_b8_d1; + uint8_t f2bc8x_b8_d1; + uint8_t f2bc9x_b8_d1; + uint8_t f2bcax_b8_d1; + uint8_t f2bcbx_b8_d1; + uint8_t f3bc2x_b8_d1; + uint8_t f3bc3x_b8_d1; + uint8_t f3bc4x_b8_d1; + uint8_t f3bc5x_b8_d1; + uint8_t f3bc8x_b8_d1; + uint8_t f3bc9x_b8_d1; + uint8_t f3bcax_b8_d1; + uint8_t f3bcbx_b8_d1; + uint8_t f5bc5x_d1; + uint8_t f5bc6x_d1; + uint8_t f4bc8x_d1; + uint8_t f4bc9x_d1; + uint8_t f4bcax_d1; + uint8_t f4bcbx_d1; + uint8_t f4bccx_d1; + uint8_t f4bcdx_d1; + uint8_t f4bcex_d1; + uint8_t f4bcfx_d1; + uint8_t f5bc8x_d1; + uint8_t f5bc9x_d1; + uint8_t f5bcax_d1; + uint8_t f5bcbx_d1; + uint8_t f5bccx_d1; + uint8_t f5bcdx_d1; + uint8_t f5bcex_d1; + uint8_t f5bcfx_d1; + uint8_t f6bc8x_d1; + uint8_t f6bc9x_d1; + uint8_t f6bcax_d1; + uint8_t f6bcbx_d1; + uint8_t f6bccx_d1; + uint8_t f6bcdx_d1; + uint8_t f6bcex_d1; + uint8_t f6bcfx_d1; + uint8_t f7bc8x_d1; + uint8_t f7bc9x_d1; + uint8_t f7bcax_d1; + uint8_t f7bcbx_d1; + uint8_t f7bccx_d1; + uint8_t f7bcdx_d1; + uint8_t f7bcex_d1; + uint8_t f7bcfx_d1; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddrphy.mk b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddrphy.mk new file mode 100644 index 0000000..ba5c774 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddrphy.mk @@ -0,0 +1,20 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#----------------------------------------------------------------------------- + +# SNPS ddr phy driver files + +DDR_PHY_C = +DDR_PHY_H = + +$(DDR_PHY_C): $(DDR_PHY_H) $(COMMON_HDRS) src + @cp -r "$(DDR_PHY_PATH)/$@" "$(SRC_DIR)/$@" + +$(DDR_PHY_H): src + @cp -r "$(DDR_PHY_PATH)/$@" "$(SRC_DIR)/$@" + +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h new file mode 100644 index 0000000..dbcd1ae --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h @@ -0,0 +1,106 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _INPUT_H_ +#define _INPUT_H_ + +enum dram_types { + DDR4, + DDR3, + LPDDR4, + LPDDR3, + LPDDR2, + DDR5, +}; + +enum dimm_types { + UDIMM, + SODIMM, + RDIMM, + LRDIMM, + NODIMM, +}; + +struct input_basic { + enum dram_types dram_type; + enum dimm_types dimm_type; + int lp4x_mode; /* 0x1 = lpddr4x mode, when dram_type is lpddr4 + */ + /* not used for protocols other than lpddr4 */ + int num_dbyte; /* number of dbytes physically instantiated */ + int num_active_dbyte_dfi0; /* number of active dbytes to be + * controlled by dfi0 + */ + int num_active_dbyte_dfi1; /* number of active dbytes to be + * controlled by dfi1. Not used for + * protocols other than lpddr3 and + * lpddr4 + */ + int num_anib; /* number of anibs physically instantiated */ + int num_rank_dfi0; /* number of ranks in dfi0 channel */ + int num_rank_dfi1; /* number of ranks in dfi1 channel */ + int dram_data_width; /* 4,8,16 or 32 depending on protocol and dram + * type + */ + int num_pstates; + int frequency; /* memclk frequency in mhz -- round up */ + int pll_bypass; /* pll bypass enable */ + int dfi_freq_ratio; /* selected dfi frequency ratio */ + int dfi1exists; /* whether they phy config has dfi1 channel */ + int train2d; + int hard_macro_ver; + int read_dbienable; + int dfi_mode; /* no longer used */ +}; + +struct input_advanced { + int d4rx_preamble_length; + int d4tx_preamble_length; + int ext_cal_res_val; /* external pull-down resistor */ + int is2ttiming; + int odtimpedance; + int tx_impedance; + int atx_impedance; + int mem_alert_en; + int mem_alert_puimp; + int mem_alert_vref_level; + int mem_alert_sync_bypass; + int dis_dyn_adr_tri; + int phy_mstr_train_interval; + int phy_mstr_max_req_to_ack; + int wdqsext; + int cal_interval; + int cal_once; + int dram_byte_swap; + int rx_en_back_off; + int train_sequence_ctrl; + int phy_gen2_umctl_opt; + int phy_gen2_umctl_f0rc5x; + int tx_slew_rise_dq; + int tx_slew_fall_dq; + int tx_slew_rise_ac; + int tx_slew_fall_ac; + int enable_high_clk_skew_fix; + int disable_unused_addr_lns; + int phy_init_sequence_num; + int cs_mode; /* rdimm */ + int cast_cs_to_cid; /* rdimm */ +}; + +struct input { + struct input_basic basic; + struct input_advanced adv; + unsigned int mr[7]; + unsigned int cs_d0; + unsigned int cs_d1; + unsigned int mirror; + unsigned int odt[4]; + unsigned int rcw[16]; + unsigned int rcw3x; + unsigned int vref; +}; + +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h new file mode 100644 index 0000000..7dec7df --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h @@ -0,0 +1,2909 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef MESSAGE_H +#define MESSAGE_H + +#ifdef DEBUG +struct phy_msg { + uint32_t index; + const char *msg; +}; + +const static struct phy_msg messages_1d[] = { + {0x00000001, + "PMU1:prbsGenCtl:%x\n" + }, + {0x00010000, + "PMU1: loading 2D acsm sequence\n" + }, + {0x00020000, + "PMU1: loading 1D acsm sequence\n" + }, + {0x00030002, + "PMU3: %d memclocks @ %d to get half of 300ns\n" + }, + {0x00040000, + "PMU: Error: User requested MPR read pattern for read DQS training in DDR3 Mode\n" + }, + {0x00050000, + "PMU3: Running 1D search for left eye edge\n" + }, + {0x00060001, + "PMU1: In Phase Left Edge Search cs %d\n" + }, + {0x00070001, + "PMU1: Out of Phase Left Edge Search cs %d\n" + }, + {0x00080000, + "PMU3: Running 1D search for right eye edge\n" + }, + {0x00090001, + "PMU1: In Phase Right Edge Search cs %d\n" + }, + {0x000a0001, + "PMU1: Out of Phase Right Edge Search cs %d\n" + }, + {0x000b0001, + "PMU1: mxRdLat training pstate %d\n" + }, + {0x000c0001, + "PMU1: mxRdLat search for cs %d\n" + }, + {0x000d0001, + "PMU0: MaxRdLat non consistent DtsmLoThldXingInd 0x%03x\n" + }, + {0x000e0003, + "PMU4: CS %d Dbyte %d worked with DFIMRL = %d DFICLKs\n" + }, + {0x000f0004, + "PMU3: MaxRdLat Read Lane err mask for csn %d, DFIMRL %2d DFIClks, dbyte %d = 0x%03x\n" + }, + {0x00100003, + "PMU3: MaxRdLat Read Lane err mask for csn %d DFIMRL %2d, All dbytes = 0x%03x\n" + }, + {0x00110001, + "PMU: Error: CS%d failed to find a DFIMRL setting that worked for all bytes during MaxRdLat training\n" + }, + {0x00120002, + "PMU3: Smallest passing DFIMRL for all dbytes in CS%d = %d DFIClks\n" + }, + {0x00130000, + "PMU: Error: No passing DFIMRL value found for any chip select during MaxRdLat training\n" + }, + {0x00140003, + "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n" + }, + {0x00150006, + "PMU10: Adjusting rxclkdly db %d nib %d from %d+%d=%d->%d\n" + }, + {0x00160000, + "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00170005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00180002, + "PMU2: TXDQ delayLeft[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00190004, + "PMU2: TXDQ delayLeft[%2d] = %3d oopScaled = %3d selectOop %d\n" + }, + {0x001a0002, + "PMU2: TXDQ delayRight[%2d] = %3d (DISCONNECTED)\n" + }, + {0x001b0004, + "PMU2: TXDQ delayRight[%2d] = %3d oopScaled = %3d selectOop %d\n" + }, + {0x001c0003, + "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n" + }, + {0x001d0000, + "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x001e0002, + "PMU4: DB %d Lane %d: (DISCONNECTED)\n" + }, + {0x001f0005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00200002, + "PMU3: Running 1D search csn %d for DM Right/NotLeft(%d) eye edge\n" + }, + {0x00210002, + "PMU3: WrDq DM byte%2d with Errcnt %d\n" + }, + {0x00220002, + "PMU3: WrDq DM byte%2d avgDly 0x%04x\n" + }, + {0x00230002, + "PMU1: WrDq DM byte%2d with Errcnt %d\n" + }, + {0x00240001, + "PMU: Error: Dbyte %d txDqDly DM training did not start inside the eye\n" + }, + {0x00250000, + "PMU4: DM TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00260002, + "PMU4: DB %d Lane %d: (DISCONNECTED)\n" + }, + {0x00270005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00280003, + "PMU: Error: Dbyte %d lane %d txDqDly DM passing region is too small (width = %d)\n" + }, + {0x00290004, + "PMU3: Errcnt for MRD/MWD search nib %2d delay = (%d, 0x%02x) = %d\n" + }, + {0x002a0000, + "PMU3: Precharge all open banks\n" + }, + {0x002b0002, + "PMU: Error: Dbyte %d nibble %d found mutliple working coarse delay setting for MRD/MWD\n" + }, + {0x002c0000, + "PMU4: MRD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n" + }, + {0x002d0000, + "PMU4: MWD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n" + }, + {0x002e0004, + "PMU10: Warning: DB %d nibble %d has multiple working coarse delays, %d and %d, choosing the smaller delay\n" + }, + {0x002f0003, + "PMU: Error: Dbyte %d nibble %d MRD/MWD passing region is too small (width = %d)\n" + }, + {0x00300006, + "PMU4: DB %d nibble %d: %3d, %3d %3d -> %3d\n" + }, + {0x00310002, + "PMU1: Start MRD/nMWD %d for csn %d\n" + }, + {0x00320002, + "PMU2: RXDQS delayLeft[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00330006, + "PMU2: RXDQS delayLeft[%2d] = %3d delayOop[%2d] = %3d OopScaled %4d, selectOop %d\n" + }, + {0x00340002, + "PMU2: RXDQS delayRight[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00350006, + "PMU2: RXDQS delayRight[%2d] = %3d delayOop[%2d] = %4d OopScaled %4d, selectOop %d\n" + }, + {0x00360000, + "PMU4: RxClkDly Passing Regions (EyeLeft EyeRight -> EyeCenter)\n" + }, + {0x00370002, + "PMU4: DB %d nibble %d: (DISCONNECTED)\n" + }, + {0x00380005, + "PMU4: DB %d nibble %d: %3d %3d -> %3d\n" + }, + {0x00390003, + "PMU: Error: Dbyte %d nibble %d rxClkDly passing region is too small (width = %d)\n" + }, + {0x003a0002, + "PMU0: goodbar = %d for RDWR_BLEN %d\n" + }, + {0x003b0001, + "PMU3: RxClkDly = %d\n" + }, + {0x003c0005, + "PMU0: db %d l %d absLane %d -> bottom %d top %d\n" + }, + {0x003d0009, + "PMU3: BYTE %d - %3d %3d %3d %3d %3d %3d %3d %3d\n" + }, + {0x003e0002, + "PMU: Error: dbyte %d lane %d's per-lane vrefDAC's had no passing region\n" + }, + {0x003f0004, + "PMU0: db%d l%d - %d %d\n" + }, + {0x00400002, + "PMU0: goodbar = %d for RDWR_BLEN %d\n" + }, + {0x00410004, + "PMU3: db%d l%d saw %d issues at rxClkDly %d\n" + }, + {0x00420003, + "PMU3: db%d l%d first saw a pass->fail edge at rxClkDly %d\n" + }, + {0x00430002, + "PMU3: lane %d PBD = %d\n" + }, + {0x00440003, + "PMU3: db%d l%d first saw a DBI pass->fail edge at rxClkDly %d\n" + }, + {0x00450003, + "PMU2: db%d l%d already passed rxPBD = %d\n" + }, + {0x00460003, + "PMU0: db%d l%d, PBD = %d\n" + }, + {0x00470002, + "PMU: Error: dbyte %d lane %d failed read deskew\n" + }, + {0x00480003, + "PMU0: db%d l%d, inc PBD = %d\n" + }, + {0x00490003, + "PMU1: Running lane deskew on pstate %d csn %d rdDBIEn %d\n" + }, + {0x004a0000, + "PMU: Error: Read deskew training has been requested, but csrMajorModeDbyte[2] is set\n" + }, + {0x004b0002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x004c0002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x004d0001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3U Type\n" + }, + {0x004e0001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3R Type\n" + }, + {0x004f0001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4U Type\n" + }, + {0x00500001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4R Type\n" + }, + {0x00510001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4LR Type\n" + }, + {0x00520000, + "PMU: Error: Both 2t timing mode and ddr4 geardown mode specified in the messageblock's PhyCfg and MR3 fields. Only one can be enabled\n" + }, + {0x00530003, + "PMU10: PHY TOTALS - NUM_DBYTES %d NUM_NIBBLES %d NUM_ANIBS %d\n" + }, + {0x00540006, + "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR3\n" + }, + {0x00550006, + "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR4\n" + }, + {0x00560008, + "PMU10: CS=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, 2T=%d, MMISC=%d AddrMirror=%d DRAMFreq=%dMT DramType=%d\n" + }, + {0x00570004, + "PMU10: Pstate%d MR0=0x%04x MR1=0x%04x MR2=0x%04x\n" + }, + {0x00580008, + "PMU10: Pstate%d MRS MR0=0x%04x MR1=0x%04x MR2=0x%04x MR3=0x%04x MR4=0x%04x MR5=0x%04x MR6=0x%04x\n" + }, + {0x00590005, + "PMU10: Pstate%d MRS MR1_A0=0x%04x MR2_A0=0x%04x MR3_A0=0x%04x MR11_A0=0x%04x\n" + }, + {0x005a0000, + "PMU10: UseBroadcastMR set. All ranks and channels use MRXX_A0 for MR settings.\n" + }, + {0x005b0005, + "PMU10: Pstate%d MRS MR01_A0=0x%02x MR02_A0=0x%02x MR03_A0=0x%02x MR11_A0=0x%02x\n" + }, + {0x005c0005, + "PMU10: Pstate%d MRS MR12_A0=0x%02x MR13_A0=0x%02x MR14_A0=0x%02x MR22_A0=0x%02x\n" + }, + {0x005d0005, + "PMU10: Pstate%d MRS MR01_A1=0x%02x MR02_A1=0x%02x MR03_A1=0x%02x MR11_A1=0x%02x\n" + }, + {0x005e0005, + "PMU10: Pstate%d MRS MR12_A1=0x%02x MR13_A1=0x%02x MR14_A1=0x%02x MR22_A1=0x%02x\n" + }, + {0x005f0005, + "PMU10: Pstate%d MRS MR01_B0=0x%02x MR02_B0=0x%02x MR03_B0=0x%02x MR11_B0=0x%02x\n" + }, + {0x00600005, + "PMU10: Pstate%d MRS MR12_B0=0x%02x MR13_B0=0x%02x MR14_B0=0x%02x MR22_B0=0x%02x\n" + }, + {0x00610005, + "PMU10: Pstate%d MRS MR01_B1=0x%02x MR02_B1=0x%02x MR03_B1=0x%02x MR11_B1=0x%02x\n" + }, + {0x00620005, + "PMU10: Pstate%d MRS MR12_B1=0x%02x MR13_B1=0x%02x MR14_B1=0x%02x MR22_B1=0x%02x\n" + }, + {0x00630002, + "PMU1: AcsmOdtCtrl%02d 0x%02x\n" + }, + {0x00640002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00650002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00660000, + "PMU1: HwtCAMode set\n" + }, + {0x00670001, + "PMU3: DDR4 infinite preamble enter/exit mode %d\n" + }, + {0x00680002, + "PMU1: In rxenb_train() csn=%d pstate=%d\n" + }, + {0x00690000, + "PMU3: Finding DQS falling edge\n" + }, + {0x006a0000, + "PMU3: Searching for DDR3/LPDDR3/LPDDR4 read preamble\n" + }, + {0x006b0009, + "PMU3: dtsm fails Even Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n" + }, + {0x006c0009, + "PMU3: dtsm fails Odd Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n" + }, + {0x006d0002, + "PMU3: Preamble search pass=%d anyfail=%d\n" + }, + {0x006e0000, + "PMU: Error: RxEn training preamble not found\n" + }, + {0x006f0000, + "PMU3: Found DQS pre-amble\n" + }, + {0x00700001, + "PMU: Error: Dbyte %d couldn't find the rising edge of DQS during RxEn Training\n" + }, + {0x00710000, + "PMU3: RxEn aligning to first rising edge of burst\n" + }, + {0x00720001, + "PMU3: Decreasing RxEn delay by %d fine step to allow full capture of reads\n" + }, + {0x00730001, + "PMU3: MREP Delay = %d\n" + }, + {0x00740003, + "PMU3: Errcnt for MREP nib %2d delay = %2d is %d\n" + }, + {0x00750002, + "PMU3: MREP nibble %d sampled a 1 at data buffer delay %d\n" + }, + {0x00760002, + "PMU3: MREP nibble %d saw a 0 to 1 transition at data buffer delay %d\n" + }, + {0x00770000, + "PMU2: MREP did not find a 0 to 1 transition for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n" + }, + {0x00780002, + "PMU2: Rising edge found in alias window, setting rxDly for nibble %d = %d\n" + }, + {0x00790002, + "PMU: Error: Failed MREP for nib %d with %d one\n" + }, + {0x007a0003, + "PMU2: Rising edge not found in alias window with %d one, leaving rxDly for nibble %d = %d\n" + }, + {0x007b0002, + "PMU3: Training DIMM %d CSn %d\n" + }, + {0x007c0001, + "PMU3: exitCAtrain_lp3 cs 0x%x\n" + }, + {0x007d0001, + "PMU3: enterCAtrain_lp3 cs 0x%x\n" + }, + {0x007e0001, + "PMU3: CAtrain_switchmsb_lp3 cs 0x%x\n" + }, + {0x007f0001, + "PMU3: CATrain_rdwr_lp3 looking for pattern %x\n" + }, + {0x00800000, + "PMU3: exitCAtrain_lp4\n" + }, + {0x00810001, + "PMU3: DEBUG enterCAtrain_lp4 1: cs 0x%x\n" + }, + {0x00820001, + "PMU3: DEBUG enterCAtrain_lp4 3: Put dbyte %d in async mode\n" + }, + {0x00830000, + "PMU3: DEBUG enterCAtrain_lp4 5: Send MR13 to turn on CA training\n" + }, + {0x00840003, + "PMU3: DEBUG enterCAtrain_lp4 7: idx = %d vref = %x mr12 = %x\n" + }, + {0x00850001, + "PMU3: CATrain_rdwr_lp4 looking for pattern %x\n" + }, + {0x00860004, + "PMU3: Phase %d CAreadbackA db:%d %x xo:%x\n" + }, + {0x00870005, + "PMU3: DEBUG lp4SetCatrVref 1: cs=%d chan=%d mr12=%x vref=%d.%d%%\n" + }, + {0x00880003, + "PMU3: DEBUG lp4SetCatrVref 3: mr12 = %x send vref= %x to db=%d\n" + }, + {0x00890000, + "PMU10:Optimizing vref\n" + }, + {0x008a0004, + "PMU4:mr12:%2x cs:%d chan %d r:%4x\n" + }, + {0x008b0005, + "PMU3: i:%2d bstr:%2d bsto:%2d st:%d r:%d\n" + }, + {0x008c0002, + "Failed to find sufficient CA Vref Passing Region for CS %d ch. %d\n" + }, + {0x008d0005, + "PMU3:Found %d.%d%% MR12:%x for cs:%d chan %d\n" + }, + {0x008e0002, + "PMU3:Calculated %d for AtxImpedence from acx %d.\n" + }, + {0x008f0000, + "PMU3:CA Odt impedence ==0. Use default vref.\n" + }, + {0x00900003, + "PMU3:Calculated %d.%d%% for Vref MR12=0x%x.\n" + }, + {0x00910000, + "PMU3: CAtrain_lp\n" + }, + {0x00920000, + "PMU3: CAtrain Begins.\n" + }, + {0x00930001, + "PMU3: CAtrain_lp testing dly %d\n" + }, + {0x00940001, + "PMU5: CA bitmap dump for cs %x\n" + }, + {0x00950001, + "PMU5: CAA%d " + }, + {0x00960001, "%02x" + }, + {0x00970000, "\n" + }, + {0x00980001, + "PMU5: CAB%d " + }, + {0x00990001, "%02x" + }, + {0x009a0000, "\n" + }, + {0x009b0003, + "PMU3: anibi=%d, anibichan[anibi]=%d ,chan=%d\n" + }, + {0x009c0001, "%02x" + }, + {0x009d0001, "\nPMU3:Raw CA setting :%x" + }, + {0x009e0002, "\nPMU3:ATxDly setting:%x margin:%d\n" + }, + {0x009f0002, "\nPMU3:InvClk ATxDly setting:%x margin:%d\n" + }, + {0x00a00000, "\nPMU3:No Range found!\n" + }, + {0x00a10003, + "PMU3: 2 anibi=%d, anibichan[anibi]=%d ,chan=%d" + }, + {0x00a20002, "\nPMU3: no neg clock => CA setting anib=%d, :%d\n" + }, + {0x00a30001, + "PMU3:Normal margin:%d\n" + }, + {0x00a40001, + "PMU3:Inverted margin:%d\n" + }, + {0x00a50000, + "PMU3:Using Inverted clock\n" + }, + {0x00a60000, + "PMU3:Using normal clk\n" + }, + {0x00a70003, + "PMU3: 3 anibi=%d, anibichan[anibi]=%d ,chan=%d\n" + }, + {0x00a80002, + "PMU3: Setting ATxDly for anib %x to %x\n" + }, + {0x00a90000, + "PMU: Error: CA Training Failed.\n" + }, + {0x00aa0000, + "PMU1: Writing MRs\n" + }, + {0x00ab0000, + "PMU4:Using MR12 values from 1D CA VREF training.\n" + }, + {0x00ac0000, + "PMU3:Writing all MRs to fsp 1\n" + }, + {0x00ad0000, + "PMU10:Lp4Quickboot mode.\n" + }, + {0x00ae0000, + "PMU3: Writing MRs\n" + }, + {0x00af0001, + "PMU10: Setting boot clock divider to %d\n" + }, + {0x00b00000, + "PMU3: Resetting DRAM\n" + }, + {0x00b10000, + "PMU3: setup for RCD initalization\n" + }, + {0x00b20000, + "PMU3: pmu_exit_SR from dev_init()\n" + }, + {0x00b30000, + "PMU3: initializing RCD\n" + }, + {0x00b40000, + "PMU10: **** Executing 2D Image ****\n" + }, + {0x00b50001, + "PMU10: **** Start DDR4 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x00b60001, + "PMU10: **** Start DDR3 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x00b70001, + "PMU10: **** Start LPDDR3 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x00b80001, + "PMU10: **** Start LPDDR4 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x00b90000, + "PMU: Error: Mismatched internal revision between DCCM and ICCM images\n" + }, + {0x00ba0001, + "PMU10: **** Testchip %d Specific Firmware ****\n" + }, + {0x00bb0000, + "PMU1: LRDIMM with EncodedCS mode, one DIMM\n" + }, + {0x00bc0000, + "PMU1: LRDIMM with EncodedCS mode, two DIMMs\n" + }, + {0x00bd0000, + "PMU1: RDIMM with EncodedCS mode, one DIMM\n" + }, + {0x00be0000, + "PMU2: Starting LRDIMM MREP training for all ranks\n" + }, + {0x00bf0000, + "PMU199: LRDIMM MREP training for all ranks completed\n" + }, + {0x00c00000, + "PMU2: Starting LRDIMM DWL training for all ranks\n" + }, + {0x00c10000, + "PMU199: LRDIMM DWL training for all ranks completed\n" + }, + {0x00c20000, + "PMU2: Starting LRDIMM MRD training for all ranks\n" + }, + {0x00c30000, + "PMU199: LRDIMM MRD training for all ranks completed\n" + }, + {0x00c40000, + "PMU2: Starting RXEN training for all ranks\n" + }, + {0x00c50000, + "PMU2: Starting write leveling fine delay training for all ranks\n" + }, + {0x00c60000, + "PMU2: Starting LRDIMM MWD training for all ranks\n" + }, + {0x00c70000, + "PMU199: LRDIMM MWD training for all ranks completed\n" + }, + {0x00c80000, + "PMU2: Starting write leveling fine delay training for all ranks\n" + }, + {0x00c90000, + "PMU2: Starting read deskew training\n" + }, + {0x00ca0000, + "PMU2: Starting SI friendly 1d RdDqs training for all ranks\n" + }, + {0x00cb0000, + "PMU2: Starting write leveling coarse delay training for all ranks\n" + }, + {0x00cc0000, + "PMU2: Starting 1d WrDq training for all ranks\n" + }, + {0x00cd0000, + "PMU2: Running DQS2DQ Oscillator for all ranks\n" + }, + {0x00ce0000, + "PMU2: Starting again read deskew training but with PRBS\n" + }, + {0x00cf0000, + "PMU2: Starting 1d RdDqs training for all ranks\n" + }, + {0x00d00000, + "PMU2: Starting again 1d WrDq training for all ranks\n" + }, + {0x00d10000, + "PMU2: Starting MaxRdLat training\n" + }, + {0x00d20000, + "PMU2: Starting 2d WrDq training for all ranks\n" + }, + {0x00d30000, + "PMU2: Starting 2d RdDqs training for all ranks\n" + }, + {0x00d40002, + "PMU3:read_fifo %x %x\n" + }, + {0x00d50001, + "PMU: Error: Invalid PhyDrvImpedance of 0x%x specified in message block.\n" + }, + {0x00d60001, + "PMU: Error: Invalid PhyOdtImpedance of 0x%x specified in message block.\n" + }, + {0x00d70001, + "PMU: Error: Invalid BPZNResVal of 0x%x specified in message block.\n" + }, + {0x00d80005, + "PMU3: fixRxEnBackOff csn:%d db:%d dn:%d bo:%d dly:%x\n" + }, + {0x00d90001, + "PMU3: fixRxEnBackOff dly:%x\n" + }, + {0x00da0000, + "PMU3: Entering setupPpt\n" + }, + {0x00db0000, + "PMU3: Start lp4PopulateHighLowBytes\n" + }, + {0x00dc0002, + "PMU3:Dbyte Detect: db%d received %x\n" + }, + {0x00dd0002, + "PMU3:getDqs2Dq read %x from dbyte %d\n" + }, + {0x00de0002, + "PMU3:getDqs2Dq(2) read %x from dbyte %d\n" + }, + {0x00df0001, + "PMU: Error: Dbyte %d read 0 from the DQS oscillator it is connected to\n" + }, + {0x00e00002, + "PMU4: Dbyte %d dqs2dq = %d/32 UI\n" + }, + {0x00e10003, + "PMU3:getDqs2Dq set dqs2dq:%d/32 ui (%d ps) from dbyte %d\n" + }, + {0x00e20003, + "PMU3: Setting coarse delay in AtxDly chiplet %d from 0x%02x to 0x%02x\n" + }, + {0x00e30003, + "PMU3: Clearing coarse delay in AtxDly chiplet %d from 0x%02x to 0x%02x\n" + }, + {0x00e40000, + "PMU3: Performing DDR4 geardown sync sequence\n" + }, + {0x00e50000, + "PMU1: Enter self refresh\n" + }, + {0x00e60000, + "PMU1: Exit self refresh\n" + }, + {0x00e70000, + "PMU: Error: No dbiEnable with lp4\n" + }, + {0x00e80000, + "PMU: Error: No dbiDisable with lp4\n" + }, + {0x00e90001, + "PMU1: DDR4 update Rx DBI Setting disable %d\n" + }, + {0x00ea0001, + "PMU1: DDR4 update 2nCk WPre Setting disable %d\n" + }, + {0x00eb0005, + "PMU1: read_delay: db%d lane%d delays[%2d] = 0x%02x (max 0x%02x)\n" + }, + {0x00ec0004, + "PMU1: write_delay: db%d lane%d delays[%2d] = 0x%04x\n" + }, + {0x00ed0001, + "PMU5: ID=%d -- db0 db1 db2 db3 db4 db5 db6 db7 db8 db9 --\n" + }, + {0x00ee000b, + "PMU5: [%d]:0x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n" + }, + {0x00ef0003, + "PMU2: dump delays - pstate=%d dimm=%d csn=%d\n" + }, + {0x00f00000, + "PMU3: Printing Mid-Training Delay Information\n" + }, + {0x00f10001, + "PMU5: CS%d <> 0 TrainingCntr <> coarse(15:10) fine(9:0)\n" + }, + {0x00f20001, + "PMU5: CS%d <> 0 RxEnDly, 1 RxClkDly <> coarse(10:6) fine(5:0)\n" + }, + {0x00f30001, + "PMU5: CS%d <> 0 TxDqsDly, 1 TxDqDly <> coarse(9:6) fine(5:0)\n" + }, + {0x00f40001, + "PMU5: CS%d <> 0 RxPBDly <> 1 Delay Unit ~= 7ps\n" + }, + {0x00f50000, + "PMU5: all CS <> 0 DFIMRL <> Units = DFI clocks\n" + }, + {0x00f60000, + "PMU5: all CS <> VrefDACs <> DAC(6:0)\n" + }, + {0x00f70000, + "PMU1: Set DMD in MR13 and wrDBI in MR3 for training\n" + }, + {0x00f80000, + "PMU: Error: getMaxRxen() failed to find largest rxen nibble delay\n" + }, + {0x00f90003, + "PMU2: getMaxRxen(): maxDly %d maxTg %d maxNib %d\n" + }, + {0x00fa0003, + "PMU2: getRankMaxRxen(): maxDly %d Tg %d maxNib %d\n" + }, + {0x00fb0000, + "PMU1: skipping CDD calculation in 2D image\n" + }, + {0x00fc0001, + "PMU3: Calculating CDDs for pstate %d\n" + }, + {0x00fd0003, + "PMU3: rxFromDly[%d][%d] = %d\n" + }, + {0x00fe0003, + "PMU3: rxToDly [%d][%d] = %d\n" + }, + {0x00ff0003, + "PMU3: rxDly [%d][%d] = %d\n" + }, + {0x01000003, + "PMU3: txDly [%d][%d] = %d\n" + }, + {0x01010003, + "PMU3: allFine CDD_RR_%d_%d = %d\n" + }, + {0x01020003, + "PMU3: allFine CDD_WW_%d_%d = %d\n" + }, + {0x01030003, + "PMU3: CDD_RR_%d_%d = %d\n" + }, + {0x01040003, + "PMU3: CDD_WW_%d_%d = %d\n" + }, + {0x01050003, + "PMU3: allFine CDD_RW_%d_%d = %d\n" + }, + {0x01060003, + "PMU3: allFine CDD_WR_%d_%d = %d\n" + }, + {0x01070003, + "PMU3: CDD_RW_%d_%d = %d\n" + }, + {0x01080003, + "PMU3: CDD_WR_%d_%d = %d\n" + }, + {0x01090004, + "PMU3: F%dBC2x_B%d_D%d = 0x%02x\n" + }, + {0x010a0004, + "PMU3: F%dBC3x_B%d_D%d = 0x%02x\n" + }, + {0x010b0004, + "PMU3: F%dBC4x_B%d_D%d = 0x%02x\n" + }, + {0x010c0004, + "PMU3: F%dBC5x_B%d_D%d = 0x%02x\n" + }, + {0x010d0004, + "PMU3: F%dBC8x_B%d_D%d = 0x%02x\n" + }, + {0x010e0004, + "PMU3: F%dBC9x_B%d_D%d = 0x%02x\n" + }, + {0x010f0004, + "PMU3: F%dBCAx_B%d_D%d = 0x%02x\n" + }, + {0x01100004, + "PMU3: F%dBCBx_B%d_D%d = 0x%02x\n" + }, + {0x01110000, + "PMU10: Entering context_switch_postamble\n" + }, + {0x01120003, + "PMU10: context_switch_postamble is enabled for DIMM %d, RC0A=0x%x, RC3x=0x%x\n" + }, + {0x01130000, + "PMU10: Setting bcw fspace 0\n" + }, + {0x01140001, + "PMU10: Sending BC0A = 0x%x\n" + }, + {0x01150001, + "PMU10: Sending BC6x = 0x%x\n" + }, + {0x01160001, + "PMU10: Sending RC0A = 0x%x\n" + }, + {0x01170001, + "PMU10: Sending RC3x = 0x%x\n" + }, + {0x01180001, + "PMU10: Sending RC0A = 0x%x\n" + }, + {0x01190001, + "PMU1: enter_lp3: DEBUG: pstate = %d\n" + }, + {0x011a0001, + "PMU1: enter_lp3: DEBUG: dfifreqxlat_pstate = %d\n" + }, + {0x011b0001, + "PMU1: enter_lp3: DEBUG: pllbypass = %d\n" + }, + {0x011c0001, + "PMU1: enter_lp3: DEBUG: forcecal = %d\n" + }, + {0x011d0001, + "PMU1: enter_lp3: DEBUG: pllmaxrange = 0x%x\n" + }, + {0x011e0001, + "PMU1: enter_lp3: DEBUG: dacval_out = 0x%x\n" + }, + {0x011f0001, + "PMU1: enter_lp3: DEBUG: pllctrl3 = 0x%x\n" + }, + {0x01200000, + "PMU3: Loading DRAM with BIOS supplied MR values and entering self refresh prior to exiting PMU code.\n" + }, + {0x01210002, + "PMU3: Setting DataBuffer function space of dimmcs 0x%02x to %d\n" + }, + {0x01220002, + "PMU4: Setting RCW FxRC%Xx = 0x%02x\n" + }, + {0x01230002, + "PMU4: Setting RCW FxRC%02x = 0x%02x\n" + }, + {0x01240001, + "PMU1: DDR4 update Rd Pre Setting disable %d\n" + }, + {0x01250002, + "PMU2: Setting BCW FxBC%Xx = 0x%02x\n" + }, + {0x01260002, + "PMU2: Setting BCW BC%02x = 0x%02x\n" + }, + {0x01270002, + "PMU2: Setting BCW PBA mode FxBC%Xx = 0x%02x\n" + }, + {0x01280002, + "PMU2: Setting BCW PBA mode BC%02x = 0x%02x\n" + }, + {0x01290003, + "PMU4: BCW value for dimm %d, fspace %d, addr 0x%04x\n" + }, + {0x012a0002, + "PMU4: DB %d, value 0x%02x\n" + }, + {0x012b0000, + "PMU6: WARNING MREP underflow, set to min value -2 coarse, 0 fine\n" + }, + {0x012c0004, + "PMU6: LRDIMM Writing final data buffer fine delay value nib %2d, trainDly %3d, fineDly code %2d, new MREP fine %2d\n" + }, + {0x012d0003, + "PMU6: LRDIMM Writing final data buffer fine delay value nib %2d, trainDly %3d, fineDly code %2d\n" + }, + {0x012e0003, + "PMU6: LRDIMM Writing data buffer fine delay type %d nib %2d, code %2d\n" + }, + {0x012f0002, + "PMU6: Writing final data buffer coarse delay value dbyte %2d, coarse = 0x%02x\n" + }, + {0x01300003, + "PMU4: data 0x%04x at MB addr 0x%08x saved at CSR addr 0x%08x\n" + }, + {0x01310003, + "PMU4: data 0x%04x at MB addr 0x%08x restored from CSR addr 0x%08x\n" + }, + {0x01320003, + "PMU4: data 0x%04x at MB addr 0x%08x saved at CSR addr 0x%08x\n" + }, + {0x01330003, + "PMU4: data 0x%04x at MB addr 0x%08x restored from CSR addr 0x%08x\n" + }, + {0x01340001, + "PMU3: Update BC00, BC01, BC02 for rank-dimm 0x%02x\n" + }, + {0x01350000, + "PMU3: Writing D4 RDIMM RCD Control words F0RC00 -> F0RC0F\n" + }, + {0x01360000, + "PMU3: Disable parity in F0RC0E\n" + }, + {0x01370000, + "PMU3: Writing D4 RDIMM RCD Control words F1RC00 -> F1RC05\n" + }, + {0x01380000, + "PMU3: Writing D4 RDIMM RCD Control words F1RC1x -> F1RC9x\n" + }, + {0x01390000, + "PMU3: Writing D4 Data buffer Control words BC00 -> BC0E\n" + }, + {0x013a0002, + "PMU1: setAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x013b0002, + "PMU1: restoreFromAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x013c0002, + "PMU1: restoreAcsmFromAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x013d0002, + "PMU2: Setting D3R RC%d = 0x%01x\n" + }, + {0x013e0000, + "PMU3: Writing D3 RDIMM RCD Control words RC0 -> RC11\n" + }, + {0x013f0002, + "PMU0: VrefDAC0/1 vddqStart %d dacToVddq %d\n" + }, + {0x01400001, + "PMU: Error: Messageblock phyVref=0x%x is above the limit for TSMC28's attenuated LPDDR4 receivers. Please see the pub databook\n" + }, + {0x01410001, + "PMU: Error: Messageblock phyVref=0x%x is above the limit for TSMC28's attenuated DDR4 receivers. Please see the pub databook\n" + }, + {0x01420001, + "PMU0: PHY VREF @ (%d/1000) VDDQ\n" + }, + {0x01430002, + "PMU0: initalizing phy vrefDacs to %d ExtVrefRange %x\n" + }, + {0x01440002, + "PMU0: initalizing global vref to %d range %d\n" + }, + {0x01450002, + "PMU4: Setting initial device vrefDQ for CS%d to MR6 = 0x%04x\n" + }, + {0x01460003, + "PMU1: In write_level_fine() csn=%d dimm=%d pstate=%d\n" + }, + {0x01470000, + "PMU3: Fine write leveling hardware search increasing TxDqsDly until full bursts are seen\n" + }, + {0x01480000, + "PMU4: WL normalized pos : ........................|........................\n" + }, + {0x01490007, + "PMU4: WL margin for nib %2d: %08x%08x%08x%08x%08x%08x\n" + }, + {0x014a0000, + "PMU4: WL normalized pos : ........................|........................\n" + }, + {0x014b0000, + "PMU3: Exiting write leveling mode\n" + }, + {0x014c0001, + "PMU3: got %d for cl in load_wrlvl_acsm\n" + }, + {0x014d0003, + "PMU1: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x014e0003, + "PMU3: left eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x014f0003, + "PMU3: right eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01500004, + "PMU3: eye center db:%d ln:%d dly:0x%x (maxdq:%x)\n" + }, + {0x01510003, + "PMU3: Wrote to TxDqDly db:%d ln:%d dly:0x%x\n" + }, + {0x01520003, + "PMU3: Wrote to TxDqDly db:%d ln:%d dly:0x%x\n" + }, + {0x01530002, + "PMU3: Coarse write leveling dbyte%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01540002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x01550000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01560001, + "PMU3: got %d for cl in load_wrlvl_acsm\n" + }, + {0x01570003, + "PMU3: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01580003, + "PMU3: left eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01590003, + "PMU3: right eye edge search db: %d ln: %d dly: 0x%x\n" + }, + {0x015a0004, + "PMU3: eye center db: %d ln: %d dly: 0x%x (maxdq: 0x%x)\n" + }, + {0x015b0003, + "PMU3: Wrote to TxDqDly db: %d ln: %d dly: 0x%x\n" + }, + {0x015c0003, + "PMU3: Wrote to TxDqDly db: %d ln: %d dly: 0x%x\n" + }, + {0x015d0002, + "PMU3: Coarse write leveling nibble%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x015e0002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x015f0000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01600000, + "PMU4: WL normalized pos : ................................|................................\n" + }, + {0x01610009, + "PMU4: WL margin for nib %2d: %08x%08x%08x%08x%08x%08x%08x%08x\n" + }, + {0x01620000, + "PMU4: WL normalized pos : ................................|................................\n" + }, + {0x01630001, + "PMU8: Adjust margin after WL coarse to be larger than %d\n" + }, + {0x01640001, + "PMU: Error: All margin after write leveling coarse are smaller than minMargin %d\n" + }, + {0x01650002, + "PMU8: Decrement nib %d TxDqsDly by %d fine step\n" + }, + {0x01660003, + "PMU3: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01670005, + "PMU2: Write level: dbyte %d nib%d dq/dmbi %2d dqsfine 0x%04x dqDly 0x%04x\n" + }, + {0x01680002, + "PMU3: Coarse write leveling nibble%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01690002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x016a0000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x016b0001, + "PMU3: DWL delay = %d\n" + }, + {0x016c0003, + "PMU3: Errcnt for DWL nib %2d delay = %2d is %d\n" + }, + {0x016d0002, + "PMU3: DWL nibble %d sampled a 1 at delay %d\n" + }, + {0x016e0003, + "PMU3: DWL nibble %d passed at delay %d. Rising edge was at %d\n" + }, + {0x016f0000, + "PMU2: DWL did nto find a rising edge of memclk for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n" + }, + {0x01700002, + "PMU2: Rising edge found in alias window, setting wrlvlDly for nibble %d = %d\n" + }, + {0x01710002, + "PMU: Error: Failed DWL for nib %d with %d one\n" + }, + {0x01720003, + "PMU2: Rising edge not found in alias window with %d one, leaving wrlvlDly for nibble %d = %d\n" + }, + {0x04000000, + "PMU: Error:Mailbox Buffer Overflowed.\n" + }, + {0x04010000, + "PMU: Error:Mailbox Buffer Overflowed.\n" + }, + {0x04020000, + "PMU: ***** Assertion Error - terminating *****\n" + }, + {0x04030002, + "PMU1: swapByte db %d by %d\n" + }, + {0x04040003, + "PMU3: get_cmd_dly max(%d ps, %d memclk) = %d\n" + }, + {0x04050002, + "PMU0: Write CSR 0x%06x 0x%04x\n" + }, + {0x04060002, + "PMU0: hwt_init_ppgc_prbs(): Polynomial: %x, Deg: %d\n" + }, + {0x04070001, + "PMU: Error: acsm_set_cmd to non existent instruction address %d\n" + }, + {0x04080001, + "PMU: Error: acsm_set_cmd with unknown ddr cmd 0x%x\n" + }, + {0x0409000c, + "PMU1: acsm_addr %02x, acsm_flgs %04x, ddr_cmd %02x, cmd_dly %02x, ddr_addr %04x, ddr_bnk %02x, ddr_cs %02x, cmd_rcnt %02x, AcsmSeq0/1/2/3 %04x %04x %04x %04x\n" + }, + {0x040a0000, + "PMU: Error: Polling on ACSM done failed to complete in acsm_poll_done()...\n" + }, + {0x040b0000, + "PMU1: acsm RUN\n" + }, + {0x040c0000, + "PMU1: acsm STOPPED\n" + }, + {0x040d0002, + "PMU1: acsm_init: acsm_mode %04x mxrdlat %04x\n" + }, + {0x040e0002, + "PMU: Error: setAcsmCLCWL: cl and cwl must be each >= 2 and 5, resp. CL=%d CWL=%d\n" + }, + {0x040f0002, + "PMU: Error: setAcsmCLCWL: cl and cwl must be each >= 5. CL=%d CWL=%d\n" + }, + {0x04100002, + "PMU1: setAcsmCLCWL: CASL %04d WCASL %04d\n" + }, + {0x04110001, + "PMU: Error: Reserved value of register F0RC0F found in message block: 0x%04x\n" + }, + {0x04120001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x04130001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x04140000, + "PMU3: Entering Boot Freq Mode.\n" + }, + {0x04150001, + "PMU: Error: Boot clock divider setting of %d is too small\n" + }, + {0x04160000, + "PMU3: Exiting Boot Freq Mode.\n" + }, + {0x04170002, + "PMU3: Writing MR%d OP=%x\n" + }, + {0x04180000, + "PMU: Error: Delay too large in slomo\n" + }, + {0x04190001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x041a0000, + "PMU3: Enable Channel A\n" + }, + {0x041b0000, + "PMU3: Enable Channel B\n" + }, + {0x041c0000, + "PMU3: Enable All Channels\n" + }, + {0x041d0002, + "PMU2: Use PDA mode to set MR%d with value 0x%02x\n" + }, + {0x041e0001, + "PMU3: Written Vref with PDA to CS=0x%02x\n" + }, + {0x041f0000, + "PMU1: start_cal: DEBUG: setting CalRun to 1\n" + }, + {0x04200000, + "PMU1: start_cal: DEBUG: setting CalRun to 0\n" + }, + {0x04210001, + "PMU1: lock_pll_dll: DEBUG: pstate = %d\n" + }, + {0x04220001, + "PMU1: lock_pll_dll: DEBUG: dfifreqxlat_pstate = %d\n" + }, + {0x04230001, + "PMU1: lock_pll_dll: DEBUG: pllbypass = %d\n" + }, + {0x04240001, + "PMU3: SaveLcdlSeed: Saving seed %d\n" + }, + {0x04250000, + "PMU1: in phy_defaults()\n" + }, + {0x04260003, + "PMU3: ACXConf:%d MaxNumDbytes:%d NumDfi:%d\n" + }, + {0x04270005, + "PMU1: setAltAcsmCLCWL setting cl=%d cwl=%d\n" + }, +}; + +const static struct phy_msg messages_2d[] = { + {0x00000001, + "PMU0: Converting %d into an MR\n" + }, + {0x00010003, + "PMU DEBUG: vref_idx %d -= %d, range_idx = %d\n" + }, + {0x00020002, + "PMU0: vrefIdx. Passing range %d, remaining vrefidx = %d\n" + }, + {0x00030002, + "PMU0: VrefIdx %d -> MR[6:0] 0x%02x\n" + }, + {0x00040001, + "PMU0: Converting MR 0x%04x to vrefIdx\n" + }, + {0x00050002, + "PMU0: DAC %d Range %d\n" + }, + {0x00060003, + "PMU0: Range %d, Range_idx %d, vref_idx offset %d\n" + }, + {0x00070002, + "PMU0: MR 0x%04x -> VrefIdx %d\n" + }, + {0x00080001, + "PMU: Error: Illegal timing group number ,%d, in getPtrVrefDq\n" + }, + {0x00090003, + "PMU1: VrefDqR%dNib%d = %d\n" + }, + {0x000a0003, + "PMU0: VrefDqR%dNib%d = %d\n" + }, + {0x000b0000, + "PMU0: ----------------MARGINS-------\n" + }, + {0x000c0002, + "PMU0: R%d_RxClkDly_Margin = %d\n" + }, + {0x000d0002, + "PMU0: R%d_VrefDac_Margin = %d\n" + }, + {0x000e0002, + "PMU0: R%d_TxDqDly_Margin = %d\n" + }, + {0x000f0002, + "PMU0: R%d_DeviceVref_Margin = %d\n" + }, + {0x00100000, + "PMU0: -----------------------\n" + }, + {0x00110003, + "PMU0: eye %d's for all TG's is [%d ... %d]\n" + }, + {0x00120000, + "PMU0: ------- settingWeight -----\n" + }, + {0x00130002, + "PMU0: Weight %d @ Setting %d\n" + }, + {0x0014001f, + "PMU4: %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d >%3d< %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n" + }, + {0x00150002, + "PMU3: Voltage Range = [%d, %d]\n" + }, + {0x00160004, + "PMU4: -- DB%d L%d -- centers: delay = %d, voltage = %d\n" + }, + {0x00170001, + "PMU5: <> 0 TxDqDlyTg%d <> coarse(6:6) fine(5:0)\n" + }, + {0x00180001, + "PMU5: <> 0 messageBlock VrefDqR%d <> MR6(6:0)\n" + }, + {0x00190001, + "PMU5: <> 0 RxClkDlyTg%d <> fine(5:0)\n" + }, + {0x001a0003, + "PMU0: tgToCsn: tg %d + 0x%04x -> csn %d\n" + }, + {0x001b0002, + "PMU: Error: LP4 rank %d cannot be mapped on tg %d\n" + }, + {0x001c0002, + "PMU3: Sending vref %d, Mr = 0X%05x, to all devices\n" + }, + {0x001d0004, + "PMU4: -------- %dD Write Scanning TG %d (CS 0x%x) Lanes 0x%03x --------\n" + }, + {0x001e0002, + "PMU0: training lanes 0x%03x using lanes 0x%03x\n" + }, + {0x001f0003, + "PMU4: ------- 2D-DFE Read Scanning TG %d (CS 0x%x) Lanes 0x%03x -------\n" + }, + {0x00200004, + "PMU4: ------- %dD Read Scanning TG %d (CS 0x%x) Lanes 0x%03x -------\n" + }, + {0x00210003, + "PMU4: TG%d MR1[13,6,5]=0x%x MR6[13,9,8]=0x%x\n" + }, + {0x00220002, + "PMU0: training lanes 0x%03x using lanes 0x%03x\n" + }, + {0x00230003, + "PMU4: ------- 2D-DFE Read Scanning TG %d (CS 0x%x) Lanes 0x%03x -------\n" + }, + {0x00240004, + "PMU4: ------- %dD Read Scanning TG %d (CS 0x%x) Lanes 0x%03x -------\n" + }, + {0x00250002, + "PMU0: training lanes 0x%03x using lanes 0x%03x\n" + }, + {0x00260002, + "PMU3: Sending vref %d, Mr = 0X%05x, to all devices\n" + }, + {0x00270004, + "PMU4: -------- %dD Write Scanning TG %d (CS 0x%x) Lanes 0x%03x --------\n" + }, + {0x00280001, + "PMU0: input %d\n" + }, + {0x00290002, + "PMU4: Programmed Voltage Search Range [%d, %d]\n" + }, + {0x002a0002, + "PMU3: Delay Stepsize = %d Fine, Voltage Stepsize = %d DAC\n" + }, + {0x002b0002, + "PMU4: Delay Weight = %d, Voltage Weight = %d\n" + }, + {0x002c0003, + "PMU0: raw 0x%x allFine %d incDec %d" + }, + {0x002d0008, + "PMU0: db%d l%d, voltage 0x%x (u_r %d) delay 0x%x (u_r %d) - lcdl %d mask 0x%x\n" + }, + {0x002e0005, + "PMU0: DB%d L%d, Eye %d, Seed = (0x%x, 0x%x)\n" + }, + {0x002f0002, + "PMU3: 2D Enables : %d, 1, %d\n" + }, + {0x00300006, + "PMU3: 2D Delay Ranges: OOPL[0x%04x,0x%04x], IP[0x%04x,0x%04x], OOPR[0x%04x,0x%04x]\n" + }, + {0x00310002, + "PMU3: 2D Voltage Search Range : [%d, %d]\n" + }, + {0x00320002, + "PMU4: Found Voltage Search Range [%d, %d]\n" + }, + {0x00330002, + "PMU0: User Weight = %d, Voltage Weight = %d\n" + }, + {0x00340005, + "PMU0: D(%d,%d) V(%d,%d | %d)\n" + }, + {0x00350002, + "PMU0: Norm Weight = %d, Voltage Weight = %d\n" + }, + {0x00360002, + "PMU0: seed 0 = (%d,%d) (center)\n" + }, + {0x00370003, + "PMU0: seed 1 = (%d,%d).min edge at idx %d\n" + }, + {0x00380003, + "PMU0: seed 2 = (%d,%d) max edge at idx %d\n" + }, + {0x00390003, + "PMU0: Search point %d = (%d,%d)\n" + }, + {0x003a0005, + "PMU0: YMARGIN: ^ %d, - %d, v %d. rate %d = %d\n" + }, + {0x003b0003, + "PMU0: XMARGIN: center %d, edge %d. = %d\n" + }, + {0x003c0002, + "PMU0: ----------- weighting (%d,%d) ----------------\n" + }, + {0x003d0003, + "PMU0: X margin - L %d R %d - Min %d\n" + }, + {0x003e0003, + "PMU0: Y margin - L %d R %d - Min %d\n" + }, + {0x003f0003, + "PMU0: center (%d,%d) weight = %d\n" + }, + {0x00400003, + "PMU4: Eye argest blob area %d from %d to %d\n" + }, + {0x00410002, + "PMU0: Compute centroid min_x %d max_x %d\n" + }, + {0x00420003, + "PMU0: Compute centroid sumLnDlyWidth %d sumLnVrefWidth %d sumLnWidht %d\n" + }, + {0x00430000, + "PMU: Error: No passing region found for 1 or more lanes. Set hdtCtrl=4 to see passing regions\n" + }, + {0x00440003, + "PMU0: Centroid ( %d, %d ) found with sumLnWidht %d\n" + }, + {0x00450003, + "PMU0: Optimal allFine Center ( %d + %d ,%d )\n" + }, + {0x00460003, + "PMU3: point %d starting at (%d,%d)\n" + }, + {0x00470002, + "PMU0: picking left (%d > %d)\n" + }, + {0x00480002, + "PMU0: picking right (%d > %d)\n" + }, + {0x00490002, + "PMU0: picking down (%d > %d)\n" + }, + {0x004a0002, + "PMU0: picking up (%d > %d)\n" + }, + {0x004b0009, + "PMU3: new center @ (%3d, %3d). Moved (%2i, %2i) -- L %d, R %d, C %d, U %d, D %d\n" + }, + {0x004c0003, + "PMU3: cordNum %d imporved %d to %d\n" + }, + {0x004d0000, + "PMU: Error: No passing region found for 1 or more lanes. Set hdtCtrl=4 to see passing regions\n" + }, + {0x004e0004, + "PMU0: Optimal allFine Center ( %d + %d ,%d ), found with weight %d.\n" + }, + {0x004f0003, + "PMU0: merging lanes=%d..%d, centerMerge_t %d\n" + }, + {0x00500001, + "PMU0: laneVal %d is disable\n" + }, + {0x00510002, + "PMU0: checking common center %d against current center %d\n" + }, + {0x00520001, + "PMU: Error: getCompoundEye Called on lane%d eye with non-compatible centers\n" + }, + {0x00530001, + "PMU0: laneItr %d is disable\n" + }, + {0x00540005, + "PMU0: lane %d, data_idx %d, offset_idx %d, = [%d..%d]\n" + }, + {0x00550003, + "PMU0: lane %d, data_idx %d, offset_idx %d, offset_idx out of range!\n" + }, + {0x00560003, + "PMU0: mergeData[%d] = max_v_low %d, min_v_high %d\n" + }, + {0x00570005, + "PMU1: writing merged center (%d,%d) back to dataBlock[%d]. doDelay %d, doVoltage %d\n" + }, + {0x00580005, + "PMU0: applying relative (%i,%i) back to dataBlock[%d]. doDelay %d, doVoltage %d\n" + }, + {0x00590002, + "PMU0: drvstren %x is idx %d in the table\n" + }, + {0x005a0000, + "PMU4: truncating FFE drive strength search range. Out of drive strengths to check.\n" + }, + {0x005b0002, + "PMU5: Weak 1 changed to pull-up %5d ohms, pull-down %5d ohms\n" + }, + {0x005c0002, + "PMU5: Weak 0 changed to pull-up %5d ohms, pull-down %5d ohms\n" + }, + {0x005d0003, + "PMU0: dlyMargin L %02d R %02d, min %02d\n" + }, + {0x005e0003, + "PMU0: vrefMargin T %02d B %02d, min %02d\n" + }, + {0x005f0002, + "PMU3: new minimum VrefMargin (%d < %d) recorded\n" + }, + {0x00600002, + "PMU3: new minimum DlyMargin (%d < %d) recorded\n" + }, + {0x00610000, + "PMU0: RX finding the per-nibble, per-tg rxClkDly values\n" + }, + {0x00620003, + "PMU0: Merging collected eyes [%d..%d) and analyzing for nibble %d's optimal rxClkDly\n" + }, + {0x00630002, + "PMU0: -- centers: delay = %d, voltage = %d\n" + }, + {0x00640003, + "PMU0: dumping optimized eye -- centers: delay = %d (%d), voltage = %d\n" + }, + {0x00650000, + "PMU0: TX optimizing txDqDelays\n" + }, + {0x00660001, + "PMU3: Analyzing collected eye %d for a lane's optimal TxDqDly\n" + }, + {0x00670001, + "PMU0: eye-lane %d is disable\n" + }, + {0x00680000, + "PMU0: TX optimizing device voltages\n" + }, + {0x00690002, + "PMU0: Merging collected eyes [%d..%d) and analyzing for optimal device txVref\n" + }, + {0x006a0002, + "PMU0: -- centers: delay = %d, voltage = %d\n" + }, + {0x006b0003, + "PMU0: dumping optimized eye -- centers: delay = %d (%d), voltage = %d\n" + }, + {0x006c0000, + "PMU4: VrefDac (compound all TG) Bottom Top -> Center\n" + }, + {0x006d0005, + "PMU4: DB%d L%d %3d %3d -> %3d (DISCONNECTED)\n" + }, + {0x006e0005, + "PMU4: DB%d L%d %3d %3d -> %3d\n" + }, + {0x006f0005, + "PMU0: writing rxClkDelay for tg%d db%1d nib%1d to 0x%02x from eye[%02d] (DISCONNECTED)\n" + }, + {0x00700003, + "PMU: Error: Dbyte %d nibble %d's optimal rxClkDly of 0x%x is out of bounds\n" + }, + {0x00710005, + "PMU0: writing rxClkDelay for tg%d db%1d nib%1d to 0x%02x from eye[%02d]\n" + }, + {0x00720005, + "PMU0: tx voltage for tg%2d nib%2d to %3d (%d) from eye[%02d]\n" + }, + {0x00730001, + "PMU0: vref Sum = %d\n" + }, + {0x00740004, + "PMU0: tx voltage total is %d/%d -> %d -> %d\n" + }, + {0x00750007, + "PMU0: writing txDqDelay for tg%1d db%1d ln%1d to 0x%02x (%d coarse, %d fine) from eye[%02d] (DISCONNECTED)\n" + }, + {0x00760003, + "PMU: Error: Dbyte %d lane %d's optimal txDqDly of 0x%x is out of bounds\n" + }, + {0x00770007, + "PMU0: writing txDqDelay for tg%1d db%1d l%1d to 0x%02x (%d coarse, %d fine) from eye[%02d]\n" + }, + {0x00780002, + "PMU0: %d (0=tx, 1=rx) TgMask for this simulation: %x\n" + }, + {0x00790001, + "PMU0: eye-byte %d is disable\n" + }, + {0x007a0001, + "PMU0: eye-lane %d is disable\n" + }, + {0x007b0003, + "PMU10: Start d4_2d_lrdimm_rx_dfe dimm %d nbTap %d biasStepMode %d\n" + }, + {0x007c0001, + "PMU10: DB DFE feature not fully supported, F2BCEx value is 0x%02x\n" + }, + {0x007d0001, + "PMU10: DB DFE feature fully supported, F2BCEx value is 0x%02x\n" + }, + {0x007e0002, + "PMU8: Start d4_2d_lrdimm_rx_dfe for tap %d biasStepInc %d\n" + }, + {0x007f0001, + "PMU7: Start d4_2d_lrdimm_rx_dfe tapCoff 0x%0x\n" + }, + {0x00800003, + "PMU6: d4_2d_lrdimm_rx_dfe db %d lane %d area %d\n" + }, + {0x00810004, + "PMU7: d4_2d_lrdimm_rx_dfe db %d lane %d max area %d best bias 0x%0x\n" + }, + {0x00820001, + "PMU0: eye-lane %d is disable\n" + }, + {0x00830003, + "PMU5: Setting 0x%x improved rank weight (%4d < %4d)\n" + }, + {0x00840001, + "PMU4: Setting 0x%x still optimal\n" + }, + {0x00850002, + "PMU5: ---- Training CS%d MR%d DRAM Equalization ----\n" + }, + {0x00860001, + "PMU0: eye-lane %d is disable\n" + }, + {0x00870003, + "PMU0: eye %d weight %d allTgWeight %d\n" + }, + {0x00880002, + "PMU5: FFE figure of merit improved from %d to %d\n" + }, + {0x00890002, + "PMU: Error: LP4 rank %d cannot be mapped on tg %d\n" + }, + {0x008a0000, + "PMU4: Adjusting vrefDac0 for just 1->x transitions\n" + }, + {0x008b0000, + "PMU4: Adjusting vrefDac1 for just 0->x transitions\n" + }, + {0x008c0001, + "PMU5: Strong 1, pull-up %d ohms\n" + }, + {0x008d0001, + "PMU5: Strong 0, pull-down %d ohms\n" + }, + {0x008e0000, + "PMU4: Enabling weak drive strengths (FFE)\n" + }, + {0x008f0000, + "PMU5: Changing all weak driver strengths\n" + }, + {0x00900000, + "PMU5: Finalizing weak drive strengths\n" + }, + {0x00910000, + "PMU4: retraining with optimal drive strength settings\n" + }, + {0x00920002, + "PMU0: targeting CsX = %d and CsY = %d\n" + }, + {0x00930001, + "PMU1:prbsGenCtl:%x\n" + }, + {0x00940000, + "PMU1: loading 2D acsm sequence\n" + }, + {0x00950000, + "PMU1: loading 1D acsm sequence\n" + }, + {0x00960002, + "PMU3: %d memclocks @ %d to get half of 300ns\n" + }, + {0x00970000, + "PMU: Error: User requested MPR read pattern for read DQS training in DDR3 Mode\n" + }, + {0x00980000, + "PMU3: Running 1D search for left eye edge\n" + }, + {0x00990001, + "PMU1: In Phase Left Edge Search cs %d\n" + }, + {0x009a0001, + "PMU1: Out of Phase Left Edge Search cs %d\n" + }, + {0x009b0000, + "PMU3: Running 1D search for right eye edge\n" + }, + {0x009c0001, + "PMU1: In Phase Right Edge Search cs %d\n" + }, + {0x009d0001, + "PMU1: Out of Phase Right Edge Search cs %d\n" + }, + {0x009e0001, + "PMU1: mxRdLat training pstate %d\n" + }, + {0x009f0001, + "PMU1: mxRdLat search for cs %d\n" + }, + {0x00a00001, + "PMU0: MaxRdLat non consistent DtsmLoThldXingInd 0x%03x\n" + }, + {0x00a10003, + "PMU4: CS %d Dbyte %d worked with DFIMRL = %d DFICLKs\n" + }, + {0x00a20004, + "PMU3: MaxRdLat Read Lane err mask for csn %d, DFIMRL %2d DFIClks, dbyte %d = 0x%03x\n" + }, + {0x00a30003, + "PMU3: MaxRdLat Read Lane err mask for csn %d DFIMRL %2d, All dbytes = 0x%03x\n" + }, + {0x00a40001, + "PMU: Error: CS%d failed to find a DFIMRL setting that worked for all bytes during MaxRdLat training\n" + }, + {0x00a50002, + "PMU3: Smallest passing DFIMRL for all dbytes in CS%d = %d DFIClks\n" + }, + {0x00a60000, + "PMU: Error: No passing DFIMRL value found for any chip select during MaxRdLat training\n" + }, + {0x00a70003, + "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n" + }, + {0x00a80006, + "PMU10: Adjusting rxclkdly db %d nib %d from %d+%d=%d->%d\n" + }, + {0x00a90000, + "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00aa0005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00ab0002, + "PMU2: TXDQ delayLeft[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00ac0004, + "PMU2: TXDQ delayLeft[%2d] = %3d oopScaled = %3d selectOop %d\n" + }, + {0x00ad0002, + "PMU2: TXDQ delayRight[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00ae0004, + "PMU2: TXDQ delayRight[%2d] = %3d oopScaled = %3d selectOop %d\n" + }, + {0x00af0003, + "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n" + }, + {0x00b00000, + "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00b10002, + "PMU4: DB %d Lane %d: (DISCONNECTED)\n" + }, + {0x00b20005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00b30002, + "PMU3: Running 1D search csn %d for DM Right/NotLeft(%d) eye edge\n" + }, + {0x00b40002, + "PMU3: WrDq DM byte%2d with Errcnt %d\n" + }, + {0x00b50002, + "PMU3: WrDq DM byte%2d avgDly 0x%04x\n" + }, + {0x00b60002, + "PMU1: WrDq DM byte%2d with Errcnt %d\n" + }, + {0x00b70001, + "PMU: Error: Dbyte %d txDqDly DM training did not start inside the eye\n" + }, + {0x00b80000, + "PMU4: DM TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00b90002, + "PMU4: DB %d Lane %d: (DISCONNECTED)\n" + }, + {0x00ba0005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00bb0003, + "PMU: Error: Dbyte %d lane %d txDqDly DM passing region is too small (width = %d)\n" + }, + {0x00bc0004, + "PMU3: Errcnt for MRD/MWD search nib %2d delay = (%d, 0x%02x) = %d\n" + }, + {0x00bd0000, + "PMU3: Precharge all open banks\n" + }, + {0x00be0002, + "PMU: Error: Dbyte %d nibble %d found mutliple working coarse delay setting for MRD/MWD\n" + }, + {0x00bf0000, + "PMU4: MRD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n" + }, + {0x00c00000, + "PMU4: MWD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n" + }, + {0x00c10004, + "PMU10: Warning: DB %d nibble %d has multiple working coarse delays, %d and %d, choosing the smaller delay\n" + }, + {0x00c20003, + "PMU: Error: Dbyte %d nibble %d MRD/MWD passing region is too small (width = %d)\n" + }, + {0x00c30006, + "PMU4: DB %d nibble %d: %3d, %3d %3d -> %3d\n" + }, + {0x00c40002, + "PMU1: Start MRD/nMWD %d for csn %d\n" + }, + {0x00c50002, + "PMU2: RXDQS delayLeft[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00c60006, + "PMU2: RXDQS delayLeft[%2d] = %3d delayOop[%2d] = %3d OopScaled %4d, selectOop %d\n" + }, + {0x00c70002, + "PMU2: RXDQS delayRight[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00c80006, + "PMU2: RXDQS delayRight[%2d] = %3d delayOop[%2d] = %4d OopScaled %4d, selectOop %d\n" + }, + {0x00c90000, + "PMU4: RxClkDly Passing Regions (EyeLeft EyeRight -> EyeCenter)\n" + }, + {0x00ca0002, + "PMU4: DB %d nibble %d: (DISCONNECTED)\n" + }, + {0x00cb0005, + "PMU4: DB %d nibble %d: %3d %3d -> %3d\n" + }, + {0x00cc0003, + "PMU: Error: Dbyte %d nibble %d rxClkDly passing region is too small (width = %d)\n" + }, + {0x00cd0002, + "PMU0: goodbar = %d for RDWR_BLEN %d\n" + }, + {0x00ce0001, + "PMU3: RxClkDly = %d\n" + }, + {0x00cf0005, + "PMU0: db %d l %d absLane %d -> bottom %d top %d\n" + }, + {0x00d00009, + "PMU3: BYTE %d - %3d %3d %3d %3d %3d %3d %3d %3d\n" + }, + {0x00d10002, + "PMU: Error: dbyte %d lane %d's per-lane vrefDAC's had no passing region\n" + }, + {0x00d20004, + "PMU0: db%d l%d - %d %d\n" + }, + {0x00d30002, + "PMU0: goodbar = %d for RDWR_BLEN %d\n" + }, + {0x00d40004, + "PMU3: db%d l%d saw %d issues at rxClkDly %d\n" + }, + {0x00d50003, + "PMU3: db%d l%d first saw a pass->fail edge at rxClkDly %d\n" + }, + {0x00d60002, + "PMU3: lane %d PBD = %d\n" + }, + {0x00d70003, + "PMU3: db%d l%d first saw a DBI pass->fail edge at rxClkDly %d\n" + }, + {0x00d80003, + "PMU2: db%d l%d already passed rxPBD = %d\n" + }, + {0x00d90003, + "PMU0: db%d l%d, PBD = %d\n" + }, + {0x00da0002, + "PMU: Error: dbyte %d lane %d failed read deskew\n" + }, + {0x00db0003, + "PMU0: db%d l%d, inc PBD = %d\n" + }, + {0x00dc0003, + "PMU1: Running lane deskew on pstate %d csn %d rdDBIEn %d\n" + }, + {0x00dd0000, + "PMU: Error: Read deskew training has been requested, but csrMajorModeDbyte[2] is set\n" + }, + {0x00de0002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00df0002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00e00001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3U Type\n" + }, + {0x00e10001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3R Type\n" + }, + {0x00e20001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4U Type\n" + }, + {0x00e30001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4R Type\n" + }, + {0x00e40001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4LR Type\n" + }, + {0x00e50000, + "PMU: Error: Both 2t timing mode and ddr4 geardown mode specified in the messageblock's PhyCfg and MR3 fields. Only one can be enabled\n" + }, + {0x00e60003, + "PMU10: PHY TOTALS - NUM_DBYTES %d NUM_NIBBLES %d NUM_ANIBS %d\n" + }, + {0x00e70006, + "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR3\n" + }, + {0x00e80006, + "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR4\n" + }, + {0x00e90008, + "PMU10: CS=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, 2T=%d, MMISC=%d AddrMirror=%d DRAMFreq=%dMT DramType=%d\n" + }, + {0x00ea0004, + "PMU10: Pstate%d MR0=0x%04x MR1=0x%04x MR2=0x%04x\n" + }, + {0x00eb0008, + "PMU10: Pstate%d MRS MR0=0x%04x MR1=0x%04x MR2=0x%04x MR3=0x%04x MR4=0x%04x MR5=0x%04x MR6=0x%04x\n" + }, + {0x00ec0005, + "PMU10: Pstate%d MRS MR1_A0=0x%04x MR2_A0=0x%04x MR3_A0=0x%04x MR11_A0=0x%04x\n" + }, + {0x00ed0000, + "PMU10: UseBroadcastMR set. All ranks and channels use MRXX_A0 for MR settings.\n" + }, + {0x00ee0005, + "PMU10: Pstate%d MRS MR01_A0=0x%02x MR02_A0=0x%02x MR03_A0=0x%02x MR11_A0=0x%02x\n" + }, + {0x00ef0005, + "PMU10: Pstate%d MRS MR12_A0=0x%02x MR13_A0=0x%02x MR14_A0=0x%02x MR22_A0=0x%02x\n" + }, + {0x00f00005, + "PMU10: Pstate%d MRS MR01_A1=0x%02x MR02_A1=0x%02x MR03_A1=0x%02x MR11_A1=0x%02x\n" + }, + {0x00f10005, + "PMU10: Pstate%d MRS MR12_A1=0x%02x MR13_A1=0x%02x MR14_A1=0x%02x MR22_A1=0x%02x\n" + }, + {0x00f20005, + "PMU10: Pstate%d MRS MR01_B0=0x%02x MR02_B0=0x%02x MR03_B0=0x%02x MR11_B0=0x%02x\n" + }, + {0x00f30005, + "PMU10: Pstate%d MRS MR12_B0=0x%02x MR13_B0=0x%02x MR14_B0=0x%02x MR22_B0=0x%02x\n" + }, + {0x00f40005, + "PMU10: Pstate%d MRS MR01_B1=0x%02x MR02_B1=0x%02x MR03_B1=0x%02x MR11_B1=0x%02x\n" + }, + {0x00f50005, + "PMU10: Pstate%d MRS MR12_B1=0x%02x MR13_B1=0x%02x MR14_B1=0x%02x MR22_B1=0x%02x\n" + }, + {0x00f60002, + "PMU1: AcsmOdtCtrl%02d 0x%02x\n" + }, + {0x00f70002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00f80002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00f90000, + "PMU1: HwtCAMode set\n" + }, + {0x00fa0001, + "PMU3: DDR4 infinite preamble enter/exit mode %d\n" + }, + {0x00fb0002, + "PMU1: In rxenb_train() csn=%d pstate=%d\n" + }, + {0x00fc0000, + "PMU3: Finding DQS falling edge\n" + }, + {0x00fd0000, + "PMU3: Searching for DDR3/LPDDR3/LPDDR4 read preamble\n" + }, + {0x00fe0009, + "PMU3: dtsm fails Even Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n" + }, + {0x00ff0009, + "PMU3: dtsm fails Odd Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n" + }, + {0x01000002, + "PMU3: Preamble search pass=%d anyfail=%d\n" + }, + {0x01010000, + "PMU: Error: RxEn training preamble not found\n" + }, + {0x01020000, + "PMU3: Found DQS pre-amble\n" + }, + {0x01030001, + "PMU: Error: Dbyte %d couldn't find the rising edge of DQS during RxEn Training\n" + }, + {0x01040000, + "PMU3: RxEn aligning to first rising edge of burst\n" + }, + {0x01050001, + "PMU3: Decreasing RxEn delay by %d fine step to allow full capture of reads\n" + }, + {0x01060001, + "PMU3: MREP Delay = %d\n" + }, + {0x01070003, + "PMU3: Errcnt for MREP nib %2d delay = %2d is %d\n" + }, + {0x01080002, + "PMU3: MREP nibble %d sampled a 1 at data buffer delay %d\n" + }, + {0x01090002, + "PMU3: MREP nibble %d saw a 0 to 1 transition at data buffer delay %d\n" + }, + {0x010a0000, + "PMU2: MREP did not find a 0 to 1 transition for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n" + }, + {0x010b0002, + "PMU2: Rising edge found in alias window, setting rxDly for nibble %d = %d\n" + }, + {0x010c0002, + "PMU: Error: Failed MREP for nib %d with %d one\n" + }, + {0x010d0003, + "PMU2: Rising edge not found in alias window with %d one, leaving rxDly for nibble %d = %d\n" + }, + {0x010e0002, + "PMU3: Training DIMM %d CSn %d\n" + }, + {0x010f0001, + "PMU3: exitCAtrain_lp3 cs 0x%x\n" + }, + {0x01100001, + "PMU3: enterCAtrain_lp3 cs 0x%x\n" + }, + {0x01110001, + "PMU3: CAtrain_switchmsb_lp3 cs 0x%x\n" + }, + {0x01120001, + "PMU3: CATrain_rdwr_lp3 looking for pattern %x\n" + }, + {0x01130000, + "PMU3: exitCAtrain_lp4\n" + }, + {0x01140001, + "PMU3: DEBUG enterCAtrain_lp4 1: cs 0x%x\n" + }, + {0x01150001, + "PMU3: DEBUG enterCAtrain_lp4 3: Put dbyte %d in async mode\n" + }, + {0x01160000, + "PMU3: DEBUG enterCAtrain_lp4 5: Send MR13 to turn on CA training\n" + }, + {0x01170003, + "PMU3: DEBUG enterCAtrain_lp4 7: idx = %d vref = %x mr12 = %x\n" + }, + {0x01180001, + "PMU3: CATrain_rdwr_lp4 looking for pattern %x\n" + }, + {0x01190004, + "PMU3: Phase %d CAreadbackA db:%d %x xo:%x\n" + }, + {0x011a0005, + "PMU3: DEBUG lp4SetCatrVref 1: cs=%d chan=%d mr12=%x vref=%d.%d%%\n" + }, + {0x011b0003, + "PMU3: DEBUG lp4SetCatrVref 3: mr12 = %x send vref= %x to db=%d\n" + }, + {0x011c0000, + "PMU10:Optimizing vref\n" + }, + {0x011d0004, + "PMU4:mr12:%2x cs:%d chan %d r:%4x\n" + }, + {0x011e0005, + "PMU3: i:%2d bstr:%2d bsto:%2d st:%d r:%d\n" + }, + {0x011f0002, + "Failed to find sufficient CA Vref Passing Region for CS %d ch. %d\n" + }, + {0x01200005, + "PMU3:Found %d.%d%% MR12:%x for cs:%d chan %d\n" + }, + {0x01210002, + "PMU3:Calculated %d for AtxImpedence from acx %d.\n" + }, + {0x01220000, + "PMU3:CA Odt impedence ==0. Use default vref.\n" + }, + {0x01230003, + "PMU3:Calculated %d.%d%% for Vref MR12=0x%x.\n" + }, + {0x01240000, + "PMU3: CAtrain_lp\n" + }, + {0x01250000, + "PMU3: CAtrain Begins.\n" + }, + {0x01260001, + "PMU3: CAtrain_lp testing dly %d\n" + }, + {0x01270001, + "PMU5: CA bitmap dump for cs %x\n" + }, + {0x01280001, + "PMU5: CAA%d " + }, + {0x01290001, "%02x" + }, + {0x012a0000, "\n" + }, + {0x012b0001, + "PMU5: CAB%d " + }, + {0x012c0001, "%02x" + }, + {0x012d0000, "\n" + }, + {0x012e0003, + "PMU3: anibi=%d, anibichan[anibi]=%d ,chan=%d\n" + }, + {0x012f0001, "%02x" + }, + {0x01300001, "\nPMU3:Raw CA setting :%x" + }, + {0x01310002, "\nPMU3:ATxDly setting:%x margin:%d\n" + }, + {0x01320002, "\nPMU3:InvClk ATxDly setting:%x margin:%d\n" + }, + {0x01330000, "\nPMU3:No Range found!\n" + }, + {0x01340003, + "PMU3: 2 anibi=%d, anibichan[anibi]=%d ,chan=%d" + }, + {0x01350002, "\nPMU3: no neg clock => CA setting anib=%d, :%d\n" + }, + {0x01360001, + "PMU3:Normal margin:%d\n" + }, + {0x01370001, + "PMU3:Inverted margin:%d\n" + }, + {0x01380000, + "PMU3:Using Inverted clock\n" + }, + {0x01390000, + "PMU3:Using normal clk\n" + }, + {0x013a0003, + "PMU3: 3 anibi=%d, anibichan[anibi]=%d ,chan=%d\n" + }, + {0x013b0002, + "PMU3: Setting ATxDly for anib %x to %x\n" + }, + {0x013c0000, + "PMU: Error: CA Training Failed.\n" + }, + {0x013d0000, + "PMU1: Writing MRs\n" + }, + {0x013e0000, + "PMU4:Using MR12 values from 1D CA VREF training.\n" + }, + {0x013f0000, + "PMU3:Writing all MRs to fsp 1\n" + }, + {0x01400000, + "PMU10:Lp4Quickboot mode.\n" + }, + {0x01410000, + "PMU3: Writing MRs\n" + }, + {0x01420001, + "PMU10: Setting boot clock divider to %d\n" + }, + {0x01430000, + "PMU3: Resetting DRAM\n" + }, + {0x01440000, + "PMU3: setup for RCD initalization\n" + }, + {0x01450000, + "PMU3: pmu_exit_SR from dev_init()\n" + }, + {0x01460000, + "PMU3: initializing RCD\n" + }, + {0x01470000, + "PMU10: **** Executing 2D Image ****\n" + }, + {0x01480001, + "PMU10: **** Start DDR4 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x01490001, + "PMU10: **** Start DDR3 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x014a0001, + "PMU10: **** Start LPDDR3 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x014b0001, + "PMU10: **** Start LPDDR4 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x014c0000, + "PMU: Error: Mismatched internal revision between DCCM and ICCM images\n" + }, + {0x014d0001, + "PMU10: **** Testchip %d Specific Firmware ****\n" + }, + {0x014e0000, + "PMU1: LRDIMM with EncodedCS mode, one DIMM\n" + }, + {0x014f0000, + "PMU1: LRDIMM with EncodedCS mode, two DIMMs\n" + }, + {0x01500000, + "PMU1: RDIMM with EncodedCS mode, one DIMM\n" + }, + {0x01510000, + "PMU2: Starting LRDIMM MREP training for all ranks\n" + }, + {0x01520000, + "PMU199: LRDIMM MREP training for all ranks completed\n" + }, + {0x01530000, + "PMU2: Starting LRDIMM DWL training for all ranks\n" + }, + {0x01540000, + "PMU199: LRDIMM DWL training for all ranks completed\n" + }, + {0x01550000, + "PMU2: Starting LRDIMM MRD training for all ranks\n" + }, + {0x01560000, + "PMU199: LRDIMM MRD training for all ranks completed\n" + }, + {0x01570000, + "PMU2: Starting RXEN training for all ranks\n" + }, + {0x01580000, + "PMU2: Starting write leveling fine delay training for all ranks\n" + }, + {0x01590000, + "PMU2: Starting LRDIMM MWD training for all ranks\n" + }, + {0x015a0000, + "PMU199: LRDIMM MWD training for all ranks completed\n" + }, + {0x015b0000, + "PMU2: Starting write leveling fine delay training for all ranks\n" + }, + {0x015c0000, + "PMU2: Starting read deskew training\n" + }, + {0x015d0000, + "PMU2: Starting SI friendly 1d RdDqs training for all ranks\n" + }, + {0x015e0000, + "PMU2: Starting write leveling coarse delay training for all ranks\n" + }, + {0x015f0000, + "PMU2: Starting 1d WrDq training for all ranks\n" + }, + {0x01600000, + "PMU2: Running DQS2DQ Oscillator for all ranks\n" + }, + {0x01610000, + "PMU2: Starting again read deskew training but with PRBS\n" + }, + {0x01620000, + "PMU2: Starting 1d RdDqs training for all ranks\n" + }, + {0x01630000, + "PMU2: Starting again 1d WrDq training for all ranks\n" + }, + {0x01640000, + "PMU2: Starting MaxRdLat training\n" + }, + {0x01650000, + "PMU2: Starting 2d WrDq training for all ranks\n" + }, + {0x01660000, + "PMU2: Starting 2d RdDqs training for all ranks\n" + }, + {0x01670002, + "PMU3:read_fifo %x %x\n" + }, + {0x01680001, + "PMU: Error: Invalid PhyDrvImpedance of 0x%x specified in message block.\n" + }, + {0x01690001, + "PMU: Error: Invalid PhyOdtImpedance of 0x%x specified in message block.\n" + }, + {0x016a0001, + "PMU: Error: Invalid BPZNResVal of 0x%x specified in message block.\n" + }, + {0x016b0005, + "PMU3: fixRxEnBackOff csn:%d db:%d dn:%d bo:%d dly:%x\n" + }, + {0x016c0001, + "PMU3: fixRxEnBackOff dly:%x\n" + }, + {0x016d0000, + "PMU3: Entering setupPpt\n" + }, + {0x016e0000, + "PMU3: Start lp4PopulateHighLowBytes\n" + }, + {0x016f0002, + "PMU3:Dbyte Detect: db%d received %x\n" + }, + {0x01700002, + "PMU3:getDqs2Dq read %x from dbyte %d\n" + }, + {0x01710002, + "PMU3:getDqs2Dq(2) read %x from dbyte %d\n" + }, + {0x01720001, + "PMU: Error: Dbyte %d read 0 from the DQS oscillator it is connected to\n" + }, + {0x01730002, + "PMU4: Dbyte %d dqs2dq = %d/32 UI\n" + }, + {0x01740003, + "PMU3:getDqs2Dq set dqs2dq:%d/32 ui (%d ps) from dbyte %d\n" + }, + {0x01750003, + "PMU3: Setting coarse delay in AtxDly chiplet %d from 0x%02x to 0x%02x\n" + }, + {0x01760003, + "PMU3: Clearing coarse delay in AtxDly chiplet %d from 0x%02x to 0x%02x\n" + }, + {0x01770000, + "PMU3: Performing DDR4 geardown sync sequence\n" + }, + {0x01780000, + "PMU1: Enter self refresh\n" + }, + {0x01790000, + "PMU1: Exit self refresh\n" + }, + {0x017a0000, + "PMU: Error: No dbiEnable with lp4\n" + }, + {0x017b0000, + "PMU: Error: No dbiDisable with lp4\n" + }, + {0x017c0001, + "PMU1: DDR4 update Rx DBI Setting disable %d\n" + }, + {0x017d0001, + "PMU1: DDR4 update 2nCk WPre Setting disable %d\n" + }, + {0x017e0005, + "PMU1: read_delay: db%d lane%d delays[%2d] = 0x%02x (max 0x%02x)\n" + }, + {0x017f0004, + "PMU1: write_delay: db%d lane%d delays[%2d] = 0x%04x\n" + }, + {0x01800001, + "PMU5: ID=%d -- db0 db1 db2 db3 db4 db5 db6 db7 db8 db9 --\n" + }, + {0x0181000b, + "PMU5: [%d]:0x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n" + }, + {0x01820003, + "PMU2: dump delays - pstate=%d dimm=%d csn=%d\n" + }, + {0x01830000, + "PMU3: Printing Mid-Training Delay Information\n" + }, + {0x01840001, + "PMU5: CS%d <> 0 TrainingCntr <> coarse(15:10) fine(9:0)\n" + }, + {0x01850001, + "PMU5: CS%d <> 0 RxEnDly, 1 RxClkDly <> coarse(10:6) fine(5:0)\n" + }, + {0x01860001, + "PMU5: CS%d <> 0 TxDqsDly, 1 TxDqDly <> coarse(9:6) fine(5:0)\n" + }, + {0x01870001, + "PMU5: CS%d <> 0 RxPBDly <> 1 Delay Unit ~= 7ps\n" + }, + {0x01880000, + "PMU5: all CS <> 0 DFIMRL <> Units = DFI clocks\n" + }, + {0x01890000, + "PMU5: all CS <> VrefDACs <> DAC(6:0)\n" + }, + {0x018a0000, + "PMU1: Set DMD in MR13 and wrDBI in MR3 for training\n" + }, + {0x018b0000, + "PMU: Error: getMaxRxen() failed to find largest rxen nibble delay\n" + }, + {0x018c0003, + "PMU2: getMaxRxen(): maxDly %d maxTg %d maxNib %d\n" + }, + {0x018d0003, + "PMU2: getRankMaxRxen(): maxDly %d Tg %d maxNib %d\n" + }, + {0x018e0000, + "PMU1: skipping CDD calculation in 2D image\n" + }, + {0x018f0001, + "PMU3: Calculating CDDs for pstate %d\n" + }, + {0x01900003, + "PMU3: rxFromDly[%d][%d] = %d\n" + }, + {0x01910003, + "PMU3: rxToDly [%d][%d] = %d\n" + }, + {0x01920003, + "PMU3: rxDly [%d][%d] = %d\n" + }, + {0x01930003, + "PMU3: txDly [%d][%d] = %d\n" + }, + {0x01940003, + "PMU3: allFine CDD_RR_%d_%d = %d\n" + }, + {0x01950003, + "PMU3: allFine CDD_WW_%d_%d = %d\n" + }, + {0x01960003, + "PMU3: CDD_RR_%d_%d = %d\n" + }, + {0x01970003, + "PMU3: CDD_WW_%d_%d = %d\n" + }, + {0x01980003, + "PMU3: allFine CDD_RW_%d_%d = %d\n" + }, + {0x01990003, + "PMU3: allFine CDD_WR_%d_%d = %d\n" + }, + {0x019a0003, + "PMU3: CDD_RW_%d_%d = %d\n" + }, + {0x019b0003, + "PMU3: CDD_WR_%d_%d = %d\n" + }, + {0x019c0004, + "PMU3: F%dBC2x_B%d_D%d = 0x%02x\n" + }, + {0x019d0004, + "PMU3: F%dBC3x_B%d_D%d = 0x%02x\n" + }, + {0x019e0004, + "PMU3: F%dBC4x_B%d_D%d = 0x%02x\n" + }, + {0x019f0004, + "PMU3: F%dBC5x_B%d_D%d = 0x%02x\n" + }, + {0x01a00004, + "PMU3: F%dBC8x_B%d_D%d = 0x%02x\n" + }, + {0x01a10004, + "PMU3: F%dBC9x_B%d_D%d = 0x%02x\n" + }, + {0x01a20004, + "PMU3: F%dBCAx_B%d_D%d = 0x%02x\n" + }, + {0x01a30004, + "PMU3: F%dBCBx_B%d_D%d = 0x%02x\n" + }, + {0x01a40000, + "PMU10: Entering context_switch_postamble\n" + }, + {0x01a50003, + "PMU10: context_switch_postamble is enabled for DIMM %d, RC0A=0x%x, RC3x=0x%x\n" + }, + {0x01a60000, + "PMU10: Setting bcw fspace 0\n" + }, + {0x01a70001, + "PMU10: Sending BC0A = 0x%x\n" + }, + {0x01a80001, + "PMU10: Sending BC6x = 0x%x\n" + }, + {0x01a90001, + "PMU10: Sending RC0A = 0x%x\n" + }, + {0x01aa0001, + "PMU10: Sending RC3x = 0x%x\n" + }, + {0x01ab0001, + "PMU10: Sending RC0A = 0x%x\n" + }, + {0x01ac0001, + "PMU1: enter_lp3: DEBUG: pstate = %d\n" + }, + {0x01ad0001, + "PMU1: enter_lp3: DEBUG: dfifreqxlat_pstate = %d\n" + }, + {0x01ae0001, + "PMU1: enter_lp3: DEBUG: pllbypass = %d\n" + }, + {0x01af0001, + "PMU1: enter_lp3: DEBUG: forcecal = %d\n" + }, + {0x01b00001, + "PMU1: enter_lp3: DEBUG: pllmaxrange = 0x%x\n" + }, + {0x01b10001, + "PMU1: enter_lp3: DEBUG: dacval_out = 0x%x\n" + }, + {0x01b20001, + "PMU1: enter_lp3: DEBUG: pllctrl3 = 0x%x\n" + }, + {0x01b30000, + "PMU3: Loading DRAM with BIOS supplied MR values and entering self refresh prior to exiting PMU code.\n" + }, + {0x01b40002, + "PMU3: Setting DataBuffer function space of dimmcs 0x%02x to %d\n" + }, + {0x01b50002, + "PMU4: Setting RCW FxRC%Xx = 0x%02x\n" + }, + {0x01b60002, + "PMU4: Setting RCW FxRC%02x = 0x%02x\n" + }, + {0x01b70001, + "PMU1: DDR4 update Rd Pre Setting disable %d\n" + }, + {0x01b80002, + "PMU2: Setting BCW FxBC%Xx = 0x%02x\n" + }, + {0x01b90002, + "PMU2: Setting BCW BC%02x = 0x%02x\n" + }, + {0x01ba0002, + "PMU2: Setting BCW PBA mode FxBC%Xx = 0x%02x\n" + }, + {0x01bb0002, + "PMU2: Setting BCW PBA mode BC%02x = 0x%02x\n" + }, + {0x01bc0003, + "PMU4: BCW value for dimm %d, fspace %d, addr 0x%04x\n" + }, + {0x01bd0002, + "PMU4: DB %d, value 0x%02x\n" + }, + {0x01be0000, + "PMU6: WARNING MREP underflow, set to min value -2 coarse, 0 fine\n" + }, + {0x01bf0004, + "PMU6: LRDIMM Writing final data buffer fine delay value nib %2d, trainDly %3d, fineDly code %2d, new MREP fine %2d\n" + }, + {0x01c00003, + "PMU6: LRDIMM Writing final data buffer fine delay value nib %2d, trainDly %3d, fineDly code %2d\n" + }, + {0x01c10003, + "PMU6: LRDIMM Writing data buffer fine delay type %d nib %2d, code %2d\n" + }, + {0x01c20002, + "PMU6: Writing final data buffer coarse delay value dbyte %2d, coarse = 0x%02x\n" + }, + {0x01c30003, + "PMU4: data 0x%04x at MB addr 0x%08x saved at CSR addr 0x%08x\n" + }, + {0x01c40003, + "PMU4: data 0x%04x at MB addr 0x%08x restored from CSR addr 0x%08x\n" + }, + {0x01c50003, + "PMU4: data 0x%04x at MB addr 0x%08x saved at CSR addr 0x%08x\n" + }, + {0x01c60003, + "PMU4: data 0x%04x at MB addr 0x%08x restored from CSR addr 0x%08x\n" + }, + {0x01c70001, + "PMU3: Update BC00, BC01, BC02 for rank-dimm 0x%02x\n" + }, + {0x01c80000, + "PMU3: Writing D4 RDIMM RCD Control words F0RC00 -> F0RC0F\n" + }, + {0x01c90000, + "PMU3: Disable parity in F0RC0E\n" + }, + {0x01ca0000, + "PMU3: Writing D4 RDIMM RCD Control words F1RC00 -> F1RC05\n" + }, + {0x01cb0000, + "PMU3: Writing D4 RDIMM RCD Control words F1RC1x -> F1RC9x\n" + }, + {0x01cc0000, + "PMU3: Writing D4 Data buffer Control words BC00 -> BC0E\n" + }, + {0x01cd0002, + "PMU1: setAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x01ce0002, + "PMU1: restoreFromAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x01cf0002, + "PMU1: restoreAcsmFromAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x01d00002, + "PMU2: Setting D3R RC%d = 0x%01x\n" + }, + {0x01d10000, + "PMU3: Writing D3 RDIMM RCD Control words RC0 -> RC11\n" + }, + {0x01d20002, + "PMU0: VrefDAC0/1 vddqStart %d dacToVddq %d\n" + }, + {0x01d30001, + "PMU: Error: Messageblock phyVref=0x%x is above the limit for TSMC28's attenuated LPDDR4 receivers. Please see the pub databook\n" + }, + {0x01d40001, + "PMU: Error: Messageblock phyVref=0x%x is above the limit for TSMC28's attenuated DDR4 receivers. Please see the pub databook\n" + }, + {0x01d50001, + "PMU0: PHY VREF @ (%d/1000) VDDQ\n" + }, + {0x01d60002, + "PMU0: initalizing phy vrefDacs to %d ExtVrefRange %x\n" + }, + {0x01d70002, + "PMU0: initalizing global vref to %d range %d\n" + }, + {0x01d80002, + "PMU4: Setting initial device vrefDQ for CS%d to MR6 = 0x%04x\n" + }, + {0x01d90003, + "PMU1: In write_level_fine() csn=%d dimm=%d pstate=%d\n" + }, + {0x01da0000, + "PMU3: Fine write leveling hardware search increasing TxDqsDly until full bursts are seen\n" + }, + {0x01db0000, + "PMU4: WL normalized pos : ........................|........................\n" + }, + {0x01dc0007, + "PMU4: WL margin for nib %2d: %08x%08x%08x%08x%08x%08x\n" + }, + {0x01dd0000, + "PMU4: WL normalized pos : ........................|........................\n" + }, + {0x01de0000, + "PMU3: Exiting write leveling mode\n" + }, + {0x01df0001, + "PMU3: got %d for cl in load_wrlvl_acsm\n" + }, + {0x01e00003, + "PMU1: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01e10003, + "PMU3: left eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01e20003, + "PMU3: right eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01e30004, + "PMU3: eye center db:%d ln:%d dly:0x%x (maxdq:%x)\n" + }, + {0x01e40003, + "PMU3: Wrote to TxDqDly db:%d ln:%d dly:0x%x\n" + }, + {0x01e50003, + "PMU3: Wrote to TxDqDly db:%d ln:%d dly:0x%x\n" + }, + {0x01e60002, + "PMU3: Coarse write leveling dbyte%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01e70002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x01e80000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01e90001, + "PMU3: got %d for cl in load_wrlvl_acsm\n" + }, + {0x01ea0003, + "PMU3: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01eb0003, + "PMU3: left eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01ec0003, + "PMU3: right eye edge search db: %d ln: %d dly: 0x%x\n" + }, + {0x01ed0004, + "PMU3: eye center db: %d ln: %d dly: 0x%x (maxdq: 0x%x)\n" + }, + {0x01ee0003, + "PMU3: Wrote to TxDqDly db: %d ln: %d dly: 0x%x\n" + }, + {0x01ef0003, + "PMU3: Wrote to TxDqDly db: %d ln: %d dly: 0x%x\n" + }, + {0x01f00002, + "PMU3: Coarse write leveling nibble%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01f10002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x01f20000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01f30000, + "PMU4: WL normalized pos : ................................|................................\n" + }, + {0x01f40009, + "PMU4: WL margin for nib %2d: %08x%08x%08x%08x%08x%08x%08x%08x\n" + }, + {0x01f50000, + "PMU4: WL normalized pos : ................................|................................\n" + }, + {0x01f60001, + "PMU8: Adjust margin after WL coarse to be larger than %d\n" + }, + {0x01f70001, + "PMU: Error: All margin after write leveling coarse are smaller than minMargin %d\n" + }, + {0x01f80002, + "PMU8: Decrement nib %d TxDqsDly by %d fine step\n" + }, + {0x01f90003, + "PMU3: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01fa0005, + "PMU2: Write level: dbyte %d nib%d dq/dmbi %2d dqsfine 0x%04x dqDly 0x%04x\n" + }, + {0x01fb0002, + "PMU3: Coarse write leveling nibble%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01fc0002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x01fd0000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01fe0001, + "PMU3: DWL delay = %d\n" + }, + {0x01ff0003, + "PMU3: Errcnt for DWL nib %2d delay = %2d is %d\n" + }, + {0x02000002, + "PMU3: DWL nibble %d sampled a 1 at delay %d\n" + }, + {0x02010003, + "PMU3: DWL nibble %d passed at delay %d. Rising edge was at %d\n" + }, + {0x02020000, + "PMU2: DWL did nto find a rising edge of memclk for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n" + }, + {0x02030002, + "PMU2: Rising edge found in alias window, setting wrlvlDly for nibble %d = %d\n" + }, + {0x02040002, + "PMU: Error: Failed DWL for nib %d with %d one\n" + }, + {0x02050003, + "PMU2: Rising edge not found in alias window with %d one, leaving wrlvlDly for nibble %d = %d\n" + }, + {0x04000000, + "PMU: Error:Mailbox Buffer Overflowed.\n" + }, + {0x04010000, + "PMU: Error:Mailbox Buffer Overflowed.\n" + }, + {0x04020000, + "PMU: ***** Assertion Error - terminating *****\n" + }, + {0x04030002, + "PMU1: swapByte db %d by %d\n" + }, + {0x04040003, + "PMU3: get_cmd_dly max(%d ps, %d memclk) = %d\n" + }, + {0x04050002, + "PMU0: Write CSR 0x%06x 0x%04x\n" + }, + {0x04060002, + "PMU0: hwt_init_ppgc_prbs(): Polynomial: %x, Deg: %d\n" + }, + {0x04070001, + "PMU: Error: acsm_set_cmd to non existent instruction address %d\n" + }, + {0x04080001, + "PMU: Error: acsm_set_cmd with unknown ddr cmd 0x%x\n" + }, + {0x0409000c, + "PMU1: acsm_addr %02x, acsm_flgs %04x, ddr_cmd %02x, cmd_dly %02x, ddr_addr %04x, ddr_bnk %02x, ddr_cs %02x, cmd_rcnt %02x, AcsmSeq0/1/2/3 %04x %04x %04x %04x\n" + }, + {0x040a0000, + "PMU: Error: Polling on ACSM done failed to complete in acsm_poll_done()...\n" + }, + {0x040b0000, + "PMU1: acsm RUN\n" + }, + {0x040c0000, + "PMU1: acsm STOPPED\n" + }, + {0x040d0002, + "PMU1: acsm_init: acsm_mode %04x mxrdlat %04x\n" + }, + {0x040e0002, + "PMU: Error: setAcsmCLCWL: cl and cwl must be each >= 2 and 5, resp. CL=%d CWL=%d\n" + }, + {0x040f0002, + "PMU: Error: setAcsmCLCWL: cl and cwl must be each >= 5. CL=%d CWL=%d\n" + }, + {0x04100002, + "PMU1: setAcsmCLCWL: CASL %04d WCASL %04d\n" + }, + {0x04110001, + "PMU: Error: Reserved value of register F0RC0F found in message block: 0x%04x\n" + }, + {0x04120001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x04130001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x04140000, + "PMU3: Entering Boot Freq Mode.\n" + }, + {0x04150001, + "PMU: Error: Boot clock divider setting of %d is too small\n" + }, + {0x04160000, + "PMU3: Exiting Boot Freq Mode.\n" + }, + {0x04170002, + "PMU3: Writing MR%d OP=%x\n" + }, + {0x04180000, + "PMU: Error: Delay too large in slomo\n" + }, + {0x04190001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x041a0000, + "PMU3: Enable Channel A\n" + }, + {0x041b0000, + "PMU3: Enable Channel B\n" + }, + {0x041c0000, + "PMU3: Enable All Channels\n" + }, + {0x041d0002, + "PMU2: Use PDA mode to set MR%d with value 0x%02x\n" + }, + {0x041e0001, + "PMU3: Written Vref with PDA to CS=0x%02x\n" + }, + {0x041f0000, + "PMU1: start_cal: DEBUG: setting CalRun to 1\n" + }, + {0x04200000, + "PMU1: start_cal: DEBUG: setting CalRun to 0\n" + }, + {0x04210001, + "PMU1: lock_pll_dll: DEBUG: pstate = %d\n" + }, + {0x04220001, + "PMU1: lock_pll_dll: DEBUG: dfifreqxlat_pstate = %d\n" + }, + {0x04230001, + "PMU1: lock_pll_dll: DEBUG: pllbypass = %d\n" + }, + {0x04240001, + "PMU3: SaveLcdlSeed: Saving seed %d\n" + }, + {0x04250000, + "PMU1: in phy_defaults()\n" + }, + {0x04260003, + "PMU3: ACXConf:%d MaxNumDbytes:%d NumDfi:%d\n" + }, + {0x04270005, + "PMU1: setAltAcsmCLCWL setting cl=%d cwl=%d\n" + }, +}; +#endif /* DEBUG */ +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c new file mode 100644 index 0000000..7dbe3a3 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c @@ -0,0 +1,2673 @@ +/* + * Copyright 2021-2022 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include "csr.h" +#include +#include "ddr4fw.h" +#include +#ifdef NXP_WARM_BOOT +#include +#endif +#include "input.h" +#include +#include +#include +#ifdef DDR_PHY_DEBUG +#include "messages.h" +#endif +#ifdef NXP_WARM_BOOT +#include "phy.h" +#endif +#include "pie.h" + +#define TIMEOUTDEFAULT 500 +#define MAP_PHY_ADDR(pstate, n, instance, offset, c) \ + ((((pstate * n) + instance + c) << 12) + offset) + +static uint32_t map_phy_addr_space(uint32_t addr) +{ + /* 23 bit addressing */ + uint32_t pstate = (addr & U(0x700000)) >> 20U; /* bit 22:20 */ + uint32_t block_type = (addr & U(0x0f0000)) >> 16U; /* bit 19:16 */ + uint32_t instance = (addr & U(0x00f000)) >> 12U; /* bit 15:12 */ + uint32_t offset = (addr & U(0x000fff)); /* bit 11:0 */ + + switch (block_type) { + case 0x0: /* 0x0 : ANIB */ + return MAP_PHY_ADDR(pstate, 12, instance, offset, 0); + case 0x1: /* 0x1 : DBYTE */ + return MAP_PHY_ADDR(pstate, 10, instance, offset, 0x30); + case 0x2: /* 0x2 : MASTER */ + return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x58); + case 0x4: /* 0x4 : ACSM */ + return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x5c); + case 0x5: /* 0x5 : μCTL Memory */ + return MAP_PHY_ADDR(pstate, 0, instance, offset, 0x60); + case 0x7: /* 0x7 : PPGC */ + return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x68); + case 0x9: /* 0x9 : INITENG */ + return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x69); + case 0xc: /* 0xC : DRTUB */ + return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6d); + case 0xd: /* 0xD : APB Only */ + return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6e); + default: + printf("ERR: Invalid block_type = 0x%x\n", block_type); + return 0; + } +} + +static inline uint16_t *phy_io_addr(void *phy, uint32_t addr) +{ + return phy + (map_phy_addr_space(addr) << 2); +} + +static inline void phy_io_write16(uint16_t *phy, uint32_t addr, uint16_t data) +{ + mmio_write_16((uintptr_t)phy_io_addr(phy, addr), data); +#ifdef DEBUG_PHY_IO + printf("0x%06x,0x%x\n", addr, data); +#endif +} + +static inline uint16_t phy_io_read16(uint16_t *phy, uint32_t addr) +{ + uint16_t reg = mmio_read_16((uintptr_t) phy_io_addr(phy, addr)); + +#ifdef DEBUG_PHY_IO + printf("R: 0x%06x,0x%x\n", addr, reg); +#endif + + return reg; +} + +#ifdef NXP_APPLY_MAX_CDD + +#define CDD_VAL_READ_ADDR (0x054012) +#define CDD_DATA_LEN (60) + +static void read_phy_reg(uint16_t *phy, uint32_t addr, + uint16_t *buf, uint32_t len) +{ + uint32_t i = 0U; + + for (i = 0U; i < len/2; i++) { + buf[i] = phy_io_read16(phy, (addr + i)); + } +} + +static uint32_t findrank(uint32_t cs_in_use) +{ + uint32_t val = 0U; + + switch (cs_in_use) { + case U(0xf): + val = 4U; + break; + case U(0x3): + val = 2U; + break; + case U(0x1): + val = 1U; + break; + default: + printf("Error - Invalid cs_in_use value\n"); + } + return val; +} + +static uint8_t findmax(uint8_t *buf, uint32_t len) +{ + uint8_t max = 0U; + uint32_t i = 0U; + + for (i = 0U; i < len; i++) { + if (buf[i] > max) { + max = buf[i]; + } + } + + return max; +} + +static void get_cdd_val(uint16_t **phy_ptr, uint32_t rank, uint32_t freq, + uint32_t *tcfg0, uint32_t *tcfg4) +{ + uint8_t cdd[CDD_DATA_LEN+4] = {0U}; + uint32_t i, val = 0U; + uint16_t *phy; + uint8_t buf[16] = {U(0x0)}; + uint8_t trr = 0U, tww = 0U, trw = 0U, twr = 0U; + uint8_t rrmax = 0U, wwmax = 0U, rwmax = 0U, wrmax = 0U; + uint8_t tmp = U(0x0); + uint8_t *c = NULL; + + for (i = 0U; i < NUM_OF_DDRC; i++) { + + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, U(0x0)); + + read_phy_reg(phy, CDD_VAL_READ_ADDR, + (uint16_t *)&cdd, CDD_DATA_LEN); + + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, U(0x1)); + + /* CDD values and address + * + * 0x054012 0x24 cdd[0] CDD[X][X] + * 0x054012 0x25 cdd[1] RR[3][2] + * 0x054013 0x26 cdd[2] RR[3][1] + * 0x054013 0x27 cdd[3] RR[3][0] + * 0x054014 0x28 cdd[4] RR[2][3] + * 0x054014 0x29 cdd[5] RR[2][1] + * 0x054015 0x2a cdd[6] RR[2][0] + * 0x054015 0x2b cdd[7] RR[1][3] + * 0x054016 0x2c cdd[8] RR[1][2] + * 0x054016 0x2d cdd[9] RR[1][0] + * 0x054017 0x2e cdd[10] RR[0][3] + * 0x054017 0x2f cdd[11] RR[0][2] + * 0x054018 0x30 cdd[12] RR[0][1] + + * 0x054018 0x31 cdd[13] WW[3][2] + * 0x054019 0x32 cdd[14] WW[3][1] + * 0x054019 0x33 cdd[15] WW[3][0] + * 0x05401a 0x34 cdd[16] WW[2][3] + * 0x05401a 0x35 cdd[17] WW[2][1] + * 0x05401b 0x36 cdd[18] WW[2][0] + * 0x05401b 0x37 cdd[19] WW[1][3] + * 0x05401c 0x38 cdd[20] WW[1][2] + * 0x05401c 0x39 cdd[21] WW[1][0] + * 0x05401d 0x3a cdd[22] WW[0][3] + * 0x05401d 0x3b cdd[23] WW[0][2] + * 0x05401e 0x3c cdd[24] WW[0][1] + + * 0x05401e 0x3d cdd[25] RW[3][3] + * 0x05401f 0x3e cdd[26] RW[3][2] + * 0x05401f 0x3f cdd[27] RW[3][1] + * 0x054020 0x40 cdd[28] RW[3][0] + * 0x054020 0x41 cdd[29] RW[2][3] + * 0x054021 0x42 cdd[30] RW[2][2] + * 0x054021 0x43 cdd[31] RW[2][1] + * 0x054022 0x44 cdd[32] RW[2][0] + * 0x054022 0x45 cdd[33] RW[1][3] + * 0x054023 0x46 cdd[34] RW[1][2] + * 0x054023 0x47 cdd[35] RW[1][1] + * 0x054024 0x48 cdd[36] RW[1][0] + * 0x054024 0x49 cdd[37] RW[0][3] + * 0x054025 0x4a cdd[38] RW[0][2] + * 0x054025 0x4b cdd[39] RW[0][1] + * 0x054026 0x4c cdd[40] RW[0][0] + + * 0x054026 0x4d cdd[41] WR[3][3] + * 0x054027 0x4e cdd[42] WR[3][2] + * 0x054027 0x4f cdd[43] WR[3][1] + * 0x054028 0x50 cdd[44] WR[3][0] + * 0x054028 0x51 cdd[45] WR[2][3] + * 0x054029 0x52 cdd[46] WR[2][2] + * 0x054029 0x53 cdd[47] WR[2][1] + * 0x05402a 0x54 cdd[48] WR[2][0] + * 0x05402a 0x55 cdd[49] WR[1][3] + * 0x05402b 0x56 cdd[50] WR[1][2] + * 0x05402b 0x57 cdd[51] WR[1][1] + * 0x05402c 0x58 cdd[52] WR[1][0] + * 0x05402c 0x59 cdd[53] WR[0][3] + * 0x05402d 0x5a cdd[54] WR[0][2] + * 0x05402d 0x5b cdd[55] WR[0][1] + * 0x05402e 0x5c cdd[56] WR[0][0] + * 0x05402e 0x5d cdd[57] CDD[Y][Y] + */ + + switch (rank) { + case 1U: + tmp = rwmax; + rwmax = cdd[40]; + if (tmp > rwmax) { + rwmax = tmp; + } + + tmp = wrmax; + wrmax = cdd[56]; + if (tmp > wrmax) { + wrmax = tmp; + } + + break; + + case 2U: + buf[0] = cdd[12]; + buf[1] = cdd[9]; + tmp = rrmax; + rrmax = findmax(buf, 2U); + if (tmp > rrmax) { + rrmax = tmp; + } + + buf[0] = cdd[24]; + buf[1] = cdd[21]; + tmp = wwmax; + wwmax = findmax(buf, 2U); + if (tmp > wwmax) { + wwmax = tmp; + } + + buf[0] = cdd[40]; + buf[1] = cdd[39]; + buf[2] = cdd[36]; + buf[3] = cdd[35]; + tmp = rwmax; + rwmax = findmax(buf, 4U); + if (tmp > rwmax) { + rwmax = tmp; + } + + buf[0] = cdd[56]; + buf[1] = cdd[55]; + buf[2] = cdd[52]; + buf[3] = cdd[51]; + tmp = wrmax; + wrmax = findmax(buf, 4U); + if (tmp > wrmax) { + wrmax = tmp; + } + + break; + + case 4U: + tmp = rrmax; + c = &cdd[1]; + rrmax = findmax(c, 12U); + if (tmp > rrmax) { + rrmax = tmp; + } + + tmp = wwmax; + c = &cdd[13]; + wwmax = findmax(c, 12U); + if (tmp > wwmax) { + wwmax = tmp; + } + + tmp = rwmax; + c = &cdd[25]; + rwmax = findmax(c, 16U); + if (tmp > rwmax) { + rwmax = tmp; + } + + tmp = wrmax; + c = &cdd[41]; + wrmax = findmax(c, 16U); + if (tmp > wrmax) { + wrmax = tmp; + } + + break; + + } + } + + rrmax += 3U; + wwmax += 4U; + + if (wwmax > 7U) { + wwmax = 7U; + } + + if (rrmax > 7U) { + rrmax = 7U; + } + + if (wrmax > U(0xf)) { + wrmax = 0U; + } + + if (rwmax > U(0x7)) { + rwmax = U(0x7); + } + + val = *tcfg0; + tww = (val >> 24U) & U(0x3); + trr = (val >> 26U) & U(0x3); + twr = (val >> 28U) & U(0x3); + trw = (val >> 30U) & U(0x3); + + val = *tcfg4; + tww = tww | (((val >> 8U) & U(0x1)) << 2U); + trr = trr | (((val >> 10U) & U(0x1)) << 2U); + twr = twr | (((val >> 12U) & U(0x1)) << 2U); + trw = trw | (((val >> 14U) & U(0x3)) << 2U); + + if (trr > rrmax) { + rrmax = trr; + } + + if (tww > wwmax) { + wwmax = tww; + } + + if (trw > rwmax) { + rwmax = trw; + } + + if (twr > wrmax) { + wrmax = twr; + } + + debug("CDD rrmax %x wwmax %x rwmax %x wrmax %x\n", + rrmax, wwmax, rwmax, wrmax); + + val = ((wwmax & U(0x3)) << 24U) + | ((rrmax & U(0x3)) << 26U) + | ((wrmax & U(0x3)) << 28U) + | ((rwmax & U(0x3)) << 30U); + + *tcfg0 = (*tcfg0 & U(0x00FFFFFF)) | (val); + + val = (((wwmax >> 2U) & U(0x1)) << 8U) + | (((rrmax >> 2U) & U(0x1)) << 10U) + | (((wrmax >> 2U) & U(0x1)) << 12U) + | (((rwmax >> 2U) & U(0x3)) << 14U); + + *tcfg4 = (*tcfg4 & U(0xffff00ff)) | val; +} +#endif + +#ifdef NXP_WARM_BOOT +int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store, + uint32_t num_of_phy, int train2d) +{ + uint16_t *phy = NULL, value = 0x0; + uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U; + int i = 0, j = 0, ret = -EINVAL; + + ret = xspi_sector_erase(address_to_store, PHY_ERASE_SIZE); + if (ret != 0) { + return -EINVAL; + } + + for (j = 0; j < num_of_phy; j++) { + /* Save training values of all PHYs */ + phy = phy_ptr[j]; + size = sizeof(training_1D_values); + num_of_regs = ARRAY_SIZE(training_1D_values); + + /* Enable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, 0x0); + /* Enable clocks in case they were disabled. */ + phy_io_write16(phy, t_drtub | + csr_ucclk_hclk_enables_addr, 0x3); + if (train2d != 0) { + /* Address to store training values is + * to be appended for next PHY + */ + phy_store = address_to_store + (j * + (sizeof(training_1D_values) + + sizeof(training_2D_values))); + } else { + phy_store = address_to_store + (j * + (sizeof(training_1D_values))); + } + debug("Saving 1D Training reg val at: %d\n", phy_store); + for (i = 0; i < num_of_regs; i++) { + value = phy_io_read16(phy, training_1D_values[i].addr); +#ifdef DEBUG_WARM_RESET + debug("%d. Reg: %x, value: %x PHY: %p\n", i, + training_1D_values[i].addr, value, + phy_io_addr(phy, + training_1D_values[i].addr)); +#endif + training_1D_values[i].data = value; + } + /* Storing 1D training values on flash */ + ret = xspi_write(phy_store, (void *)training_1D_values, size); + if (train2d != 0) { + phy_store = phy_store+size; + size = sizeof(training_2D_values); + num_of_regs = ARRAY_SIZE(training_2D_values); + debug("Saving 2D Training reg val at:%d\n", phy_store); + for (i = 0; i < num_of_regs; i++) { + value = phy_io_read16(phy, + training_2D_values[i].addr); + training_2D_values[i].data = value; +#ifdef DEBUG_WARM_RESET + debug("%d.2D addr:0x%x,val:0x%x,PHY:0x%p\n", + i, training_2D_values[i].addr, + value, phy_io_addr(phy, + training_2D_values[i].addr)); +#endif + } + /* Storing 2D training values on flash */ + ret = xspi_write(phy_store, training_2D_values, + size); + } + /* Disable clocks in case they were disabled. */ + phy_io_write16(phy, t_drtub | + csr_ucclk_hclk_enables_addr, 0x0); + /* Disable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, 0x1); + } + if (ret != 0) { + return -EINVAL; + } + + return 0; +} + +int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore, + uint32_t num_of_phy, int train2d) +{ + uint16_t *phy = NULL; + uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U; + int i = 0, j = 0, ret = -EINVAL; + + debug("Restoring Training register values\n"); + for (j = 0; j < num_of_phy; j++) { + phy = phy_ptr[j]; + size = sizeof(training_1D_values); + num_of_regs = ARRAY_SIZE(training_1D_values); + if (train2d != 0) { + /* The address to restore training values is + * to be appended for next PHY + */ + phy_store = address_to_restore + (j * + (sizeof(training_1D_values) + + sizeof(training_2D_values))); + } else { + phy_store = address_to_restore + (j * + (sizeof(training_1D_values))); + } + /* Enable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, 0x0); + /* Enable clocks in case they were disabled. */ + phy_io_write16(phy, t_drtub | + csr_ucclk_hclk_enables_addr, 0x3); + + /* Reading 1D training values from flash*/ + ret = xspi_read(phy_store, (uint32_t *)training_1D_values, + size); + debug("Restoring 1D Training reg val at:%08x\n", phy_store); + for (i = 0; i < num_of_regs; i++) { + phy_io_write16(phy, training_1D_values[i].addr, + training_1D_values[i].data); +#ifdef DEBUG_WARM_RESET + debug("%d. Reg: %x, value: %x PHY: %p\n", i, + training_1D_values[i].addr, + training_1D_values[i].data, + phy_io_addr(phy, + training_1D_values[i].addr)); +#endif + } + if (train2d != 0) { + phy_store = phy_store + size; + size = sizeof(training_2D_values); + num_of_regs = ARRAY_SIZE(training_2D_values); + /* Reading 2D training values from flash */ + ret = xspi_read(phy_store, + (uint32_t *)training_2D_values, size); + debug("Restoring 2D Training reg val at:%08x\n", + phy_store); + for (i = 0; i < num_of_regs; i++) { + phy_io_write16(phy, training_2D_values[i].addr, + training_2D_values[i].data); +#ifdef DEBUG_WARM_RESET + debug("%d. Reg: %x, value: %x PHY: %p\n", i, + training_2D_values[i].addr, + training_2D_values[i].data, + phy_io_addr(phy, + training_1D_values[i].addr)); +#endif + } + } + /* Disable clocks in case they were disabled. */ + phy_io_write16(phy, t_drtub | + csr_ucclk_hclk_enables_addr, 0x0); + /* Disable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, 0x1); + } + if (ret != 0) { + return -EINVAL; + } + return 0; +} +#endif + +static void load_pieimage(uint16_t *phy, + enum dimm_types dimm_type) +{ + int i; + int size; + const struct pie *image = NULL; + + switch (dimm_type) { + case UDIMM: + case SODIMM: + case NODIMM: + image = pie_udimm; + size = ARRAY_SIZE(pie_udimm); + break; + case RDIMM: + image = pie_rdimm; + size = ARRAY_SIZE(pie_rdimm); + break; + case LRDIMM: + image = pie_lrdimm; + size = ARRAY_SIZE(pie_lrdimm); + break; + default: + printf("Unsupported DIMM type\n"); + break; + } + + if (image != NULL) { + for (i = 0; i < size; i++) + phy_io_write16(phy, image[i].addr, image[i].data); + } +} + +static void prog_acsm_playback(uint16_t *phy, + const struct input *input, const void *msg) +{ + int vec; + const struct ddr4r1d *msg_blk; + uint16_t acsmplayback[2][3]; + uint32_t f0rc0a; + uint32_t f0rc3x; + uint32_t f0rc5x; + + if (input->basic.dimm_type != RDIMM) { + return; + } + + msg_blk = msg; + f0rc0a = (msg_blk->f0rc0a_d0 & U(0xf)) | U(0xa0); + f0rc3x = (msg_blk->f0rc3x_d0 & U(0xff)) | U(0x300); + f0rc5x = (input->adv.phy_gen2_umctl_f0rc5x & U(0xff)) | U(0x500); + + acsmplayback[0][0] = U(0x3ff) & f0rc0a; + acsmplayback[1][0] = (U(0x1c00) & f0rc0a) >> 10U; + acsmplayback[0][1] = U(0x3ff) & f0rc3x; + acsmplayback[1][1] = (U(0x1c00) & f0rc3x) >> 10U; + acsmplayback[0][2] = U(0x3ff) & f0rc5x; + acsmplayback[1][2] = (U(0x1c00) & f0rc5x) >> 10U; + for (vec = 0; vec < 3; vec++) { + phy_io_write16(phy, t_acsm | (csr_acsm_playback0x0_addr + + (vec << 1)), acsmplayback[0][vec]); + phy_io_write16(phy, t_acsm | (csr_acsm_playback1x0_addr + + (vec << 1)), acsmplayback[1][vec]); + } +} + +static void prog_acsm_ctr(uint16_t *phy, + const struct input *input) +{ + if (input->basic.dimm_type != RDIMM) { + return; + } + + phy_io_write16(phy, t_acsm | csr_acsm_ctrl13_addr, + 0xf << csr_acsm_cke_enb_lsb); + + phy_io_write16(phy, t_acsm | csr_acsm_ctrl0_addr, + csr_acsm_par_mode_mask | csr_acsm_2t_mode_mask); +} + +static void prog_cal_rate_run(uint16_t *phy, + const struct input *input) +{ + int cal_rate; + int cal_interval; + int cal_once; + uint32_t addr; + + cal_interval = input->adv.cal_interval; + cal_once = input->adv.cal_once; + cal_rate = 0x1 << csr_cal_run_lsb | + cal_once << csr_cal_once_lsb | + cal_interval << csr_cal_interval_lsb; + addr = t_master | csr_cal_rate_addr; + phy_io_write16(phy, addr, cal_rate); +} + +static void prog_seq0bdly0(uint16_t *phy, + const struct input *input) +{ + int ps_count[4]; + int frq; + uint32_t addr; + int lower_freq_opt = 0; + + __unused const soc_info_t *soc_info; + + frq = input->basic.frequency >> 1; + ps_count[0] = frq >> 3; /* 0.5 * frq / 4*/ + if (input->basic.frequency < 400) { + lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 7 : 3; + } else if (input->basic.frequency < 533) { + lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 14 : 11; + } + + /* 1.0 * frq / 4 - lower_freq */ + ps_count[1] = (frq >> 2) - lower_freq_opt; + ps_count[2] = (frq << 1) + (frq >> 1); /* 10.0 * frq / 4 */ + +#ifdef DDR_PLL_FIX + soc_info = get_soc_info(); + if (soc_info->svr_reg.bf.maj_ver == 1) { + ps_count[0] = 0x520; /* seq0bdly0 */ + ps_count[1] = 0xa41; /* seq0bdly1 */ + ps_count[2] = 0x668a; /* seq0bdly2 */ + } +#endif + if (frq > 266) { + ps_count[3] = 44; + } else if (frq > 200) { + ps_count[3] = 33; + } else { + ps_count[3] = 16; + } + + addr = t_master | csr_seq0bdly0_addr; + phy_io_write16(phy, addr, ps_count[0]); + + debug("seq0bdly0 = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_seq0bdly1_addr; + phy_io_write16(phy, addr, ps_count[1]); + + debug("seq0bdly1 = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_seq0bdly2_addr; + phy_io_write16(phy, addr, ps_count[2]); + + debug("seq0bdly2 = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_seq0bdly3_addr; + phy_io_write16(phy, addr, ps_count[3]); + + debug("seq0bdly3 = 0x%x\n", phy_io_read16(phy, addr)); +} + +/* Only RDIMM requires msg_blk */ +static void i_load_pie(uint16_t **phy_ptr, + const struct input *input, + const void *msg) +{ + int i; + uint16_t *phy; + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + phy_io_write16(phy, + t_apbonly | csr_micro_cont_mux_sel_addr, + 0U); + + load_pieimage(phy, input->basic.dimm_type); + + prog_seq0bdly0(phy, input); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag0_addr, + U(0x0000)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag1_addr, + U(0x0173)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag2_addr, + U(0x0060)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag3_addr, + U(0x6110)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag4_addr, + U(0x2152)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag5_addr, + U(0xdfbd)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag6_addr, + input->basic.dimm_type == RDIMM && + input->adv.phy_gen2_umctl_opt == 1U ? + U(0x6000) : U(0xffff)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag7_addr, + U(0x6152)); + prog_acsm_playback(phy, input, msg); /* rdimm */ + prog_acsm_ctr(phy, input); /* rdimm */ + + phy_io_write16(phy, t_master | csr_cal_zap_addr, U(0x1)); + prog_cal_rate_run(phy, input); + + phy_io_write16(phy, t_drtub | csr_ucclk_hclk_enables_addr, + input->basic.dimm_type == RDIMM ? U(0x2) : 0U); + + phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 1U); + } +} + +static void phy_gen2_init_input(struct input *input) +{ + int i; + + input->adv.dram_byte_swap = 0; + input->adv.ext_cal_res_val = 0; + input->adv.tx_slew_rise_dq = 0xf; + input->adv.tx_slew_fall_dq = 0xf; + input->adv.tx_slew_rise_ac = 0xf; + input->adv.tx_slew_fall_ac = 0xf; + input->adv.mem_alert_en = 0; + input->adv.mem_alert_puimp = 5; + input->adv.mem_alert_vref_level = 0x29; + input->adv.mem_alert_sync_bypass = 0; + input->adv.cal_interval = 0x9; + input->adv.cal_once = 0; + input->adv.dis_dyn_adr_tri = 0; + input->adv.is2ttiming = 0; + input->adv.d4rx_preamble_length = 0; + input->adv.d4tx_preamble_length = 0; + + for (i = 0; i < 7; i++) { + debug("mr[%d] = 0x%x\n", i, input->mr[i]); + } + + debug("input->cs_d0 = 0x%x\n", input->cs_d0); + debug("input->cs_d1 = 0x%x\n", input->cs_d1); + debug("input->mirror = 0x%x\n", input->mirror); + debug("PHY ODT impedance = %d ohm\n", input->adv.odtimpedance); + debug("PHY DQ driver impedance = %d ohm\n", input->adv.tx_impedance); + debug("PHY Addr driver impedance = %d ohm\n", input->adv.atx_impedance); + + for (i = 0; i < 4; i++) { + debug("odt[%d] = 0x%x\n", i, input->odt[i]); + } + + if (input->basic.dimm_type == RDIMM) { + for (i = 0; i < 16; i++) { + debug("input->rcw[%d] = 0x%x\n", i, input->rcw[i]); + } + debug("input->rcw3x = 0x%x\n", input->rcw3x); + } +} + +/* + * All protocols share the same base structure of message block. + * RDIMM and LRDIMM have more entries defined than UDIMM. + * Create message blocks for 1D and 2D training. + * Update len with message block size. + */ +static int phy_gen2_msg_init(void *msg_1d, + void *msg_2d, + const struct input *input) +{ + struct ddr4u1d *msg_blk = msg_1d; + struct ddr4u2d *msg_blk_2d = msg_2d; + struct ddr4r1d *msg_blk_r; + struct ddr4lr1d *msg_blk_lr; + + switch (input->basic.dimm_type) { + case UDIMM: + case SODIMM: + case NODIMM: + msg_blk->dram_type = U(0x2); + break; + case RDIMM: + msg_blk->dram_type = U(0x4); + break; + case LRDIMM: + msg_blk->dram_type = U(0x5); + break; + default: + ERROR("Unsupported DIMM type\n"); + return -EINVAL; + } + msg_blk->pstate = 0U; + + /*Enable quickRd2D, a substage of read deskew, to 1D training.*/ + msg_blk->reserved00 = U(0x20); + + /*Enable High-Effort WrDQ1D.*/ + msg_blk->reserved00 |= U(0x40); + + /* Enable 1D extra effort training.*/ + msg_blk->reserved1c[3] = U(0x3); + + if (input->basic.dimm_type == LRDIMM) { + msg_blk->sequence_ctrl = U(0x3f1f); + } else { + msg_blk->sequence_ctrl = U(0x031f); + } + msg_blk->phy_config_override = 0U; +#ifdef DDR_PHY_DEBUG + msg_blk->hdt_ctrl = U(0x5); +#else + msg_blk->hdt_ctrl = U(0xc9); +#endif + msg_blk->msg_misc = U(0x0); + msg_blk->dfimrlmargin = U(0x1); + msg_blk->phy_vref = input->vref ? input->vref : U(0x61); + msg_blk->cs_present = input->cs_d0 | input->cs_d1; + msg_blk->cs_present_d0 = input->cs_d0; + msg_blk->cs_present_d1 = input->cs_d1; + if (input->mirror != 0) { + msg_blk->addr_mirror = U(0x0a); /* odd CS are mirrored */ + } + msg_blk->share2dvref_result = 1U; + + msg_blk->acsm_odt_ctrl0 = input->odt[0]; + msg_blk->acsm_odt_ctrl1 = input->odt[1]; + msg_blk->acsm_odt_ctrl2 = input->odt[2]; + msg_blk->acsm_odt_ctrl3 = input->odt[3]; + msg_blk->enabled_dqs = (input->basic.num_active_dbyte_dfi0 + + input->basic.num_active_dbyte_dfi1) * 8; + msg_blk->x16present = input->basic.dram_data_width == 0x10 ? + msg_blk->cs_present : 0; + msg_blk->d4misc = U(0x1); + msg_blk->cs_setup_gddec = U(0x1); + msg_blk->rtt_nom_wr_park0 = 0U; + msg_blk->rtt_nom_wr_park1 = 0U; + msg_blk->rtt_nom_wr_park2 = 0U; + msg_blk->rtt_nom_wr_park3 = 0U; + msg_blk->rtt_nom_wr_park4 = 0U; + msg_blk->rtt_nom_wr_park5 = 0U; + msg_blk->rtt_nom_wr_park6 = 0U; + msg_blk->rtt_nom_wr_park7 = 0U; + msg_blk->mr0 = input->mr[0]; + msg_blk->mr1 = input->mr[1]; + msg_blk->mr2 = input->mr[2]; + msg_blk->mr3 = input->mr[3]; + msg_blk->mr4 = input->mr[4]; + msg_blk->mr5 = input->mr[5]; + msg_blk->mr6 = input->mr[6]; + if ((msg_blk->mr4 & U(0x1c0)) != 0U) { + ERROR("Setting DRAM CAL mode is not supported\n"); + } + + msg_blk->alt_cas_l = 0U; + msg_blk->alt_wcas_l = 0U; + + msg_blk->dramfreq = input->basic.frequency * 2U; + msg_blk->pll_bypass_en = input->basic.pll_bypass; + msg_blk->dfi_freq_ratio = input->basic.dfi_freq_ratio == 0U ? 1U : + input->basic.dfi_freq_ratio == 1U ? 2U : + 4U; + msg_blk->bpznres_val = input->adv.ext_cal_res_val; + msg_blk->disabled_dbyte = 0U; + + debug("msg_blk->dram_type = 0x%x\n", msg_blk->dram_type); + debug("msg_blk->sequence_ctrl = 0x%x\n", msg_blk->sequence_ctrl); + debug("msg_blk->phy_cfg = 0x%x\n", msg_blk->phy_cfg); + debug("msg_blk->x16present = 0x%x\n", msg_blk->x16present); + debug("msg_blk->dramfreq = 0x%x\n", msg_blk->dramfreq); + debug("msg_blk->pll_bypass_en = 0x%x\n", msg_blk->pll_bypass_en); + debug("msg_blk->dfi_freq_ratio = 0x%x\n", msg_blk->dfi_freq_ratio); + debug("msg_blk->phy_odt_impedance = 0x%x\n", + msg_blk->phy_odt_impedance); + debug("msg_blk->phy_drv_impedance = 0x%x\n", + msg_blk->phy_drv_impedance); + debug("msg_blk->bpznres_val = 0x%x\n", msg_blk->bpznres_val); + debug("msg_blk->enabled_dqs = 0x%x\n", msg_blk->enabled_dqs); + debug("msg_blk->acsm_odt_ctrl0 = 0x%x\n", msg_blk->acsm_odt_ctrl0); + debug("msg_blk->acsm_odt_ctrl1 = 0x%x\n", msg_blk->acsm_odt_ctrl1); + debug("msg_blk->acsm_odt_ctrl2 = 0x%x\n", msg_blk->acsm_odt_ctrl2); + debug("msg_blk->acsm_odt_ctrl3 = 0x%x\n", msg_blk->acsm_odt_ctrl3); + + /* RDIMM only */ + if (input->basic.dimm_type == RDIMM || + input->basic.dimm_type == LRDIMM) { + msg_blk_r = (struct ddr4r1d *)msg_blk; + if (msg_blk_r->cs_present_d0 != 0U) { + msg_blk_r->f0rc00_d0 = input->rcw[0]; + msg_blk_r->f0rc01_d0 = input->rcw[1]; + msg_blk_r->f0rc02_d0 = input->rcw[2]; + msg_blk_r->f0rc03_d0 = input->rcw[3]; + msg_blk_r->f0rc04_d0 = input->rcw[4]; + msg_blk_r->f0rc05_d0 = input->rcw[5]; + msg_blk_r->f0rc06_d0 = input->rcw[6]; + msg_blk_r->f0rc07_d0 = input->rcw[7]; + msg_blk_r->f0rc08_d0 = input->rcw[8]; + msg_blk_r->f0rc09_d0 = input->rcw[9]; + msg_blk_r->f0rc0a_d0 = input->rcw[10]; + msg_blk_r->f0rc0b_d0 = input->rcw[11]; + msg_blk_r->f0rc0c_d0 = input->rcw[12]; + msg_blk_r->f0rc0d_d0 = input->rcw[13]; + msg_blk_r->f0rc0e_d0 = input->rcw[14]; + msg_blk_r->f0rc0f_d0 = input->rcw[15]; + msg_blk_r->f0rc3x_d0 = input->rcw3x; + } + if (msg_blk_r->cs_present_d1 != 0) { + msg_blk_r->f0rc00_d1 = input->rcw[0]; + msg_blk_r->f0rc01_d1 = input->rcw[1]; + msg_blk_r->f0rc02_d1 = input->rcw[2]; + msg_blk_r->f0rc03_d1 = input->rcw[3]; + msg_blk_r->f0rc04_d1 = input->rcw[4]; + msg_blk_r->f0rc05_d1 = input->rcw[5]; + msg_blk_r->f0rc06_d1 = input->rcw[6]; + msg_blk_r->f0rc07_d1 = input->rcw[7]; + msg_blk_r->f0rc08_d1 = input->rcw[8]; + msg_blk_r->f0rc09_d1 = input->rcw[9]; + msg_blk_r->f0rc0a_d1 = input->rcw[10]; + msg_blk_r->f0rc0b_d1 = input->rcw[11]; + msg_blk_r->f0rc0c_d1 = input->rcw[12]; + msg_blk_r->f0rc0d_d1 = input->rcw[13]; + msg_blk_r->f0rc0e_d1 = input->rcw[14]; + msg_blk_r->f0rc0f_d1 = input->rcw[15]; + msg_blk_r->f0rc3x_d1 = input->rcw3x; + } + if (input->basic.dimm_type == LRDIMM) { + msg_blk_lr = (struct ddr4lr1d *)msg_blk; + msg_blk_lr->bc0a_d0 = msg_blk_lr->f0rc0a_d0; + msg_blk_lr->bc0a_d1 = msg_blk_lr->f0rc0a_d1; + msg_blk_lr->f0bc6x_d0 = msg_blk_lr->f0rc3x_d0; + msg_blk_lr->f0bc6x_d1 = msg_blk_lr->f0rc3x_d1; + } + } + + /* below is different for 1D and 2D message block */ + if (input->basic.train2d != 0) { + memcpy(msg_blk_2d, msg_blk, sizeof(struct ddr4u1d)); + /*High-Effort WrDQ1D is applicable to 2D traning also*/ + msg_blk_2d->reserved00 |= U(0x40); + msg_blk_2d->sequence_ctrl = U(0x0061); + msg_blk_2d->rx2d_train_opt = 0U; + msg_blk_2d->tx2d_train_opt = 0U; + msg_blk_2d->share2dvref_result = 1U; + msg_blk_2d->delay_weight2d = U(0x20); + msg_blk_2d->voltage_weight2d = U(0x80); + debug("rx2d_train_opt %d, tx2d_train_opt %d\n", + msg_blk_2d->rx2d_train_opt, + msg_blk_2d->tx2d_train_opt); + } + + msg_blk->phy_cfg = (((msg_blk->mr3 & U(0x8)) != 0U) || + ((msg_blk_2d->mr3 & 0x8) != 0U)) ? 0U + : input->adv.is2ttiming; + + return 0; +} + +static void prog_tx_pre_drv_mode(uint16_t *phy, + const struct input *input) +{ + int lane, byte, b_addr, c_addr, p_addr; + int tx_slew_rate, tx_pre_p, tx_pre_n; + int tx_pre_drv_mode = 0x2; + uint32_t addr; + + /* Program TxPreDrvMode with 0x2 */ + /* FIXME: TxPreDrvMode depends on DramType? */ + tx_pre_p = input->adv.tx_slew_rise_dq; + tx_pre_n = input->adv.tx_slew_fall_dq; + tx_slew_rate = tx_pre_drv_mode << csr_tx_pre_drv_mode_lsb | + tx_pre_p << csr_tx_pre_p_lsb | + tx_pre_n << csr_tx_pre_n_lsb; + p_addr = 0; + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + for (lane = 0; lane <= 1; lane++) { + b_addr = lane << 8; + addr = p_addr | t_dbyte | c_addr | b_addr | + csr_tx_slew_rate_addr; + phy_io_write16(phy, addr, tx_slew_rate); + } + } +} + +static void prog_atx_pre_drv_mode(uint16_t *phy, + const struct input *input) +{ + int anib, c_addr; + int atx_slew_rate, atx_pre_p, atx_pre_n, atx_pre_drv_mode, + ck_anib_inst[2]; + uint32_t addr; + + atx_pre_n = input->adv.tx_slew_fall_ac; + atx_pre_p = input->adv.tx_slew_rise_ac; + + if (input->basic.num_anib == 8) { + ck_anib_inst[0] = 1; + ck_anib_inst[1] = 1; + } else if (input->basic.num_anib == 10 || input->basic.num_anib == 12 || + input->basic.num_anib == 13) { + ck_anib_inst[0] = 4; + ck_anib_inst[1] = 5; + } else { + ERROR("Invalid number of aNIBs: %d\n", input->basic.num_anib); + return; + } + + for (anib = 0; anib < input->basic.num_anib; anib++) { + c_addr = anib << 12; + if (anib == ck_anib_inst[0] || anib == ck_anib_inst[1]) { + atx_pre_drv_mode = 0; + } else { + atx_pre_drv_mode = 3; + } + atx_slew_rate = atx_pre_drv_mode << csr_atx_pre_drv_mode_lsb | + atx_pre_n << csr_atx_pre_n_lsb | + atx_pre_p << csr_atx_pre_p_lsb; + addr = t_anib | c_addr | csr_atx_slew_rate_addr; + phy_io_write16(phy, addr, atx_slew_rate); + } +} + +static void prog_enable_cs_multicast(uint16_t *phy, + const struct input *input) +{ + uint32_t addr = t_master | csr_enable_cs_multicast_addr; + + if (input->basic.dimm_type != RDIMM && + input->basic.dimm_type != LRDIMM) { + return; + } + + phy_io_write16(phy, addr, input->adv.cast_cs_to_cid); +} + +static void prog_dfi_rd_data_cs_dest_map(uint16_t *phy, + unsigned int ip_rev, + const struct input *input, + const struct ddr4lr1d *msg) +{ + const struct ddr4lr1d *msg_blk; + uint16_t dfi_xxdestm0 = 0U; + uint16_t dfi_xxdestm1 = 0U; + uint16_t dfi_xxdestm2 = 0U; + uint16_t dfi_xxdestm3 = 0U; + uint16_t dfi_rd_data_cs_dest_map; + uint16_t dfi_wr_data_cs_dest_map; + __unused const soc_info_t *soc_info; + +#ifdef ERRATA_DDR_A011396 + /* Only apply to DDRC 5.05.00 */ + soc_info = get_soc_info(); + if ((soc_info->svr_reg.bf.maj_ver == 1U) && (ip_rev == U(0x50500))) { + phy_io_write16(phy, + t_master | csr_dfi_rd_data_cs_dest_map_addr, + 0U); + return; + } +#endif + + msg_blk = msg; + + switch (input->basic.dimm_type) { + case UDIMM: + case SODIMM: + case NODIMM: + if ((msg_blk->msg_misc & U(0x40)) != 0U) { + dfi_rd_data_cs_dest_map = U(0xa0); + dfi_wr_data_cs_dest_map = U(0xa0); + + phy_io_write16(phy, + t_master | csr_dfi_rd_data_cs_dest_map_addr, + dfi_rd_data_cs_dest_map); + phy_io_write16(phy, + t_master | csr_dfi_wr_data_cs_dest_map_addr, + dfi_wr_data_cs_dest_map); + } + break; + case LRDIMM: + if (msg->cs_present_d1 != 0U) { + dfi_xxdestm2 = 1U; + dfi_xxdestm3 = 1U; + } + + dfi_rd_data_cs_dest_map = + dfi_xxdestm0 << csr_dfi_rd_destm0_lsb | + dfi_xxdestm1 << csr_dfi_rd_destm1_lsb | + dfi_xxdestm2 << csr_dfi_rd_destm2_lsb | + dfi_xxdestm3 << csr_dfi_rd_destm3_lsb; + dfi_wr_data_cs_dest_map = + dfi_xxdestm0 << csr_dfi_wr_destm0_lsb | + dfi_xxdestm1 << csr_dfi_wr_destm1_lsb | + dfi_xxdestm2 << csr_dfi_wr_destm2_lsb | + dfi_xxdestm3 << csr_dfi_wr_destm3_lsb; + phy_io_write16(phy, t_master | csr_dfi_rd_data_cs_dest_map_addr, + dfi_rd_data_cs_dest_map); + phy_io_write16(phy, t_master | csr_dfi_wr_data_cs_dest_map_addr, + dfi_wr_data_cs_dest_map); + + break; + default: + break; + } +} + +static void prog_pll_ctrl(uint16_t *phy, + const struct input *input) +{ + uint32_t addr; + int pll_ctrl1 = 0x21; /* 000100001b */ + int pll_ctrl4 = 0x17f; /* 101111111b */ + int pll_test_mode = 0x24; /* 00100100b */ + + addr = t_master | csr_pll_ctrl1_addr; + phy_io_write16(phy, addr, pll_ctrl1); + + debug("pll_ctrl1 = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_pll_test_mode_addr; + phy_io_write16(phy, addr, pll_test_mode); + + debug("pll_test_mode = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_pll_ctrl4_addr; + phy_io_write16(phy, addr, pll_ctrl4); + + debug("pll_ctrl4 = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_pll_ctrl2(uint16_t *phy, + const struct input *input) +{ + int pll_ctrl2; + uint32_t addr = t_master | csr_pll_ctrl2_addr; + + if (input->basic.frequency / 2 < 235) { + pll_ctrl2 = 0x7; + } else if (input->basic.frequency / 2 < 313) { + pll_ctrl2 = 0x6; + } else if (input->basic.frequency / 2 < 469) { + pll_ctrl2 = 0xb; + } else if (input->basic.frequency / 2 < 625) { + pll_ctrl2 = 0xa; + } else if (input->basic.frequency / 2 < 938) { + pll_ctrl2 = 0x19; + } else if (input->basic.frequency / 2 < 1067) { + pll_ctrl2 = 0x18; + } else { + pll_ctrl2 = 0x19; + } + + phy_io_write16(phy, addr, pll_ctrl2); + + debug("pll_ctrl2 = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_dll_lck_param(uint16_t *phy, const struct input *input) +{ + uint32_t addr = t_master | csr_dll_lockparam_addr; + + phy_io_write16(phy, addr, U(0x212)); + debug("dll_lck_param = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_dll_gain_ctl(uint16_t *phy, const struct input *input) +{ + uint32_t addr = t_master | csr_dll_gain_ctl_addr; + + phy_io_write16(phy, addr, U(0x61)); + debug("dll_gain_ctl = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_pll_pwr_dn(uint16_t *phy, + const struct input *input) +{ + uint32_t addr; + + addr = t_master | csr_pll_pwr_dn_addr; + phy_io_write16(phy, addr, 0U); + + debug("pll_pwrdn = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_ard_ptr_init_val(uint16_t *phy, + const struct input *input) +{ + int ard_ptr_init_val; + uint32_t addr = t_master | csr_ard_ptr_init_val_addr; + + if (input->basic.frequency >= 933) { + ard_ptr_init_val = 0x2; + } else { + ard_ptr_init_val = 0x1; + } + + phy_io_write16(phy, addr, ard_ptr_init_val); +} + +static void prog_dqs_preamble_control(uint16_t *phy, + const struct input *input) +{ + int data; + uint32_t addr = t_master | csr_dqs_preamble_control_addr; + const int wdqsextension = 0; + const int lp4sttc_pre_bridge_rx_en = 0; + const int lp4postamble_ext = 0; + const int lp4tgl_two_tck_tx_dqs_pre = 0; + const int position_dfe_init = 2; + const int dll_rx_preamble_mode = 1; + int two_tck_tx_dqs_pre = input->adv.d4tx_preamble_length; + int two_tck_rx_dqs_pre = input->adv.d4rx_preamble_length; + + data = wdqsextension << csr_wdqsextension_lsb | + lp4sttc_pre_bridge_rx_en << csr_lp4sttc_pre_bridge_rx_en_lsb | + lp4postamble_ext << csr_lp4postamble_ext_lsb | + lp4tgl_two_tck_tx_dqs_pre << csr_lp4tgl_two_tck_tx_dqs_pre_lsb | + position_dfe_init << csr_position_dfe_init_lsb | + two_tck_tx_dqs_pre << csr_two_tck_tx_dqs_pre_lsb | + two_tck_rx_dqs_pre << csr_two_tck_rx_dqs_pre_lsb; + phy_io_write16(phy, addr, data); + + data = dll_rx_preamble_mode << csr_dll_rx_preamble_mode_lsb; + addr = t_master | csr_dbyte_dll_mode_cntrl_addr; + phy_io_write16(phy, addr, data); +} + +static void prog_proc_odt_time_ctl(uint16_t *phy, + const struct input *input) +{ + int proc_odt_time_ctl; + uint32_t addr = t_master | csr_proc_odt_time_ctl_addr; + + if (input->adv.wdqsext != 0) { + proc_odt_time_ctl = 0x3; + } else if (input->basic.frequency <= 933) { + proc_odt_time_ctl = 0xa; + } else if (input->basic.frequency <= 1200) { + if (input->adv.d4rx_preamble_length == 1) { + proc_odt_time_ctl = 0x2; + } else { + proc_odt_time_ctl = 0x6; + } + } else { + if (input->adv.d4rx_preamble_length == 1) { + proc_odt_time_ctl = 0x3; + } else { + proc_odt_time_ctl = 0x7; + } + } + phy_io_write16(phy, addr, proc_odt_time_ctl); +} + +static const struct impedance_mapping map[] = { + { 29, 0x3f }, + { 31, 0x3e }, + { 33, 0x3b }, + { 36, 0x3a }, + { 39, 0x39 }, + { 42, 0x38 }, + { 46, 0x1b }, + { 51, 0x1a }, + { 57, 0x19 }, + { 64, 0x18 }, + { 74, 0x0b }, + { 88, 0x0a }, + { 108, 0x09 }, + { 140, 0x08 }, + { 200, 0x03 }, + { 360, 0x02 }, + { 481, 0x01 }, + {} +}; + +static int map_impedance(int strength) +{ + const struct impedance_mapping *tbl = map; + int val = 0; + + if (strength == 0) { + return 0; + } + + while (tbl->ohm != 0U) { + if (strength < tbl->ohm) { + val = tbl->code; + break; + } + tbl++; + } + + return val; +} + +static int map_odtstren_p(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 0) { + val = 0; + } else if (strength == 120) { + val = 0x8; + } else if (strength == 60) { + val = 0x18; + } else if (strength == 40) { + val = 0x38; + } else { + printf("error: unsupported ODTStrenP %d\n", strength); + } + } else { + val = map_impedance(strength); + } + + return val; +} + +static void prog_tx_odt_drv_stren(uint16_t *phy, + const struct input *input) +{ + int lane, byte, b_addr, c_addr; + int tx_odt_drv_stren; + int odtstren_p, odtstren_n; + uint32_t addr; + + odtstren_p = map_odtstren_p(input->adv.odtimpedance, + input->basic.hard_macro_ver); + if (odtstren_p < 0) { + return; + } + + odtstren_n = 0; /* always high-z */ + tx_odt_drv_stren = odtstren_n << csr_odtstren_n_lsb | odtstren_p; + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + for (lane = 0; lane <= 1; lane++) { + b_addr = lane << 8; + addr = t_dbyte | c_addr | b_addr | + csr_tx_odt_drv_stren_addr; + phy_io_write16(phy, addr, tx_odt_drv_stren); + } + } +} + +static int map_drvstren_fsdq_p(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 0) { + val = 0x07; + } else if (strength == 120) { + val = 0x0F; + } else if (strength == 60) { + val = 0x1F; + } else if (strength == 40) { + val = 0x3F; + } else { + printf("error: unsupported drv_stren_fSDq_p %d\n", + strength); + } + } else { + val = map_impedance(strength); + } + + return val; +} + +static int map_drvstren_fsdq_n(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 0) { + val = 0x00; + } else if (strength == 120) { + val = 0x08; + } else if (strength == 60) { + val = 0x18; + } else if (strength == 40) { + val = 0x38; + } else { + printf("error: unsupported drvStrenFSDqN %d\n", + strength); + } + } else { + val = map_impedance(strength); + } + + return val; +} + +static void prog_tx_impedance_ctrl1(uint16_t *phy, + const struct input *input) +{ + int lane, byte, b_addr, c_addr; + int tx_impedance_ctrl1; + int drv_stren_fsdq_p, drv_stren_fsdq_n; + uint32_t addr; + + drv_stren_fsdq_p = map_drvstren_fsdq_p(input->adv.tx_impedance, + input->basic.hard_macro_ver); + drv_stren_fsdq_n = map_drvstren_fsdq_n(input->adv.tx_impedance, + input->basic.hard_macro_ver); + tx_impedance_ctrl1 = drv_stren_fsdq_n << csr_drv_stren_fsdq_n_lsb | + drv_stren_fsdq_p << csr_drv_stren_fsdq_p_lsb; + + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + for (lane = 0; lane <= 1; lane++) { + b_addr = lane << 8; + addr = t_dbyte | c_addr | b_addr | + csr_tx_impedance_ctrl1_addr; + phy_io_write16(phy, addr, tx_impedance_ctrl1); + } + } +} + +static int map_adrv_stren_p(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 120) { + val = 0x1c; + } else if (strength == 60) { + val = 0x1d; + } else if (strength == 40) { + val = 0x1f; + } else { + printf("error: unsupported aDrv_stren_p %d\n", + strength); + } + } else { + if (strength == 120) { + val = 0x00; + } else if (strength == 60) { + val = 0x01; + } else if (strength == 40) { + val = 0x03; + } else if (strength == 30) { + val = 0x07; + } else if (strength == 24) { + val = 0x0f; + } else if (strength == 20) { + val = 0x1f; + } else { + printf("error: unsupported aDrv_stren_p %d\n", + strength); + } + } + + return val; +} + +static int map_adrv_stren_n(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 120) { + val = 0x00; + } else if (strength == 60) { + val = 0x01; + } else if (strength == 40) { + val = 0x03; + } else { + printf("Error: unsupported ADrvStrenP %d\n", strength); + } + } else { + if (strength == 120) { + val = 0x00; + } else if (strength == 60) { + val = 0x01; + } else if (strength == 40) { + val = 0x03; + } else if (strength == 30) { + val = 0x07; + } else if (strength == 24) { + val = 0x0f; + } else if (strength == 20) { + val = 0x1f; + } else { + printf("Error: unsupported ADrvStrenP %d\n", strength); + } + } + + return val; +} + +static void prog_atx_impedance(uint16_t *phy, + const struct input *input) +{ + int anib, c_addr; + int atx_impedance; + int adrv_stren_p; + int adrv_stren_n; + uint32_t addr; + + if (input->basic.hard_macro_ver == 4 && + input->adv.atx_impedance == 20) { + printf("Error:ATxImpedance has to be 40 for HardMacroVer 4\n"); + return; + } + + adrv_stren_p = map_adrv_stren_p(input->adv.atx_impedance, + input->basic.hard_macro_ver); + adrv_stren_n = map_adrv_stren_n(input->adv.atx_impedance, + input->basic.hard_macro_ver); + atx_impedance = adrv_stren_n << csr_adrv_stren_n_lsb | + adrv_stren_p << csr_adrv_stren_p_lsb; + for (anib = 0; anib < input->basic.num_anib; anib++) { + c_addr = anib << 12; + addr = t_anib | c_addr | csr_atx_impedance_addr; + phy_io_write16(phy, addr, atx_impedance); + } +} + +static void prog_dfi_mode(uint16_t *phy, + const struct input *input) +{ + int dfi_mode; + uint32_t addr; + + if (input->basic.dfi1exists == 1) { + dfi_mode = 0x5; /* DFI1 exists but disabled */ + } else { + dfi_mode = 0x1; /* DFI1 does not physically exists */ + } + addr = t_master | csr_dfi_mode_addr; + phy_io_write16(phy, addr, dfi_mode); +} + +static void prog_acx4_anib_dis(uint16_t *phy, const struct input *input) +{ + uint32_t addr; + + addr = t_master | csr_acx4_anib_dis_addr; + phy_io_write16(phy, addr, 0x0); + debug("%s 0x%x\n", __func__, phy_io_read16(phy, addr)); +} + +static void prog_dfi_camode(uint16_t *phy, + const struct input *input) +{ + int dfi_camode = 2; + uint32_t addr = t_master | csr_dfi_camode_addr; + + phy_io_write16(phy, addr, dfi_camode); +} + +static void prog_cal_drv_str0(uint16_t *phy, + const struct input *input) +{ + int cal_drv_str0; + int cal_drv_str_pd50; + int cal_drv_str_pu50; + uint32_t addr; + + cal_drv_str_pu50 = input->adv.ext_cal_res_val; + cal_drv_str_pd50 = cal_drv_str_pu50; + cal_drv_str0 = cal_drv_str_pu50 << csr_cal_drv_str_pu50_lsb | + cal_drv_str_pd50; + addr = t_master | csr_cal_drv_str0_addr; + phy_io_write16(phy, addr, cal_drv_str0); +} + +static void prog_cal_uclk_info(uint16_t *phy, + const struct input *input) +{ + int cal_uclk_ticks_per1u_s; + uint32_t addr; + + cal_uclk_ticks_per1u_s = input->basic.frequency >> 1; + if (cal_uclk_ticks_per1u_s < 24) { + cal_uclk_ticks_per1u_s = 24; + } + + addr = t_master | csr_cal_uclk_info_addr; + phy_io_write16(phy, addr, cal_uclk_ticks_per1u_s); +} + +static void prog_cal_rate(uint16_t *phy, + const struct input *input) +{ + int cal_rate; + int cal_interval; + int cal_once; + uint32_t addr; + + cal_interval = input->adv.cal_interval; + cal_once = input->adv.cal_once; + cal_rate = cal_once << csr_cal_once_lsb | + cal_interval << csr_cal_interval_lsb; + addr = t_master | csr_cal_rate_addr; + phy_io_write16(phy, addr, cal_rate); +} + +static void prog_vref_in_global(uint16_t *phy, + const struct input *input, + const struct ddr4u1d *msg) +{ + int vref_in_global; + int global_vref_in_dac = 0; + int global_vref_in_sel = 0; + uint32_t addr; + + /* + * phy_vref_prcnt = msg->phy_vref / 128.0 + * global_vref_in_dac = (phy_vref_prcnt - 0.345) / 0.005; + */ + global_vref_in_dac = (msg->phy_vref * 1000 - 345 * 128 + 320) / + (5 * 128); + + vref_in_global = global_vref_in_dac << csr_global_vref_in_dac_lsb | + global_vref_in_sel; + addr = t_master | csr_vref_in_global_addr; + phy_io_write16(phy, addr, vref_in_global); +} + +static void prog_dq_dqs_rcv_cntrl(uint16_t *phy, + const struct input *input) +{ + int lane, byte, b_addr, c_addr; + int dq_dqs_rcv_cntrl; + int gain_curr_adj_defval = 0xb; + int major_mode_dbyte = 3; + int dfe_ctrl_defval = 0; + int ext_vref_range_defval = 0; + int sel_analog_vref = 1; + uint32_t addr; + +#ifdef ERRATA_DDR_A050958 + gain_curr_adj_defval = 0x1f; +#endif + + dq_dqs_rcv_cntrl = gain_curr_adj_defval << csr_gain_curr_adj_lsb | + major_mode_dbyte << csr_major_mode_dbyte_lsb | + dfe_ctrl_defval << csr_dfe_ctrl_lsb | + ext_vref_range_defval << csr_ext_vref_range_lsb | + sel_analog_vref << csr_sel_analog_vref_lsb; + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + for (lane = 0; lane <= 1; lane++) { + b_addr = lane << 8; + addr = t_dbyte | c_addr | b_addr | + csr_dq_dqs_rcv_cntrl_addr; + phy_io_write16(phy, addr, dq_dqs_rcv_cntrl); + } + } +} + +static void prog_mem_alert_control(uint16_t *phy, + const struct input *input) +{ + int mem_alert_control; + int mem_alert_control2; + int malertpu_en; + int malertrx_en; + int malertvref_level; + int malertpu_stren; + int malertsync_bypass; + int malertdisable_val_defval = 1; + uint32_t addr; + + if (input->basic.dram_type == DDR4 && input->adv.mem_alert_en == 1) { + malertpu_en = 1; + malertrx_en = 1; + malertpu_stren = input->adv.mem_alert_puimp; + malertvref_level = input->adv.mem_alert_vref_level; + malertsync_bypass = input->adv.mem_alert_sync_bypass; + mem_alert_control = malertdisable_val_defval << 14 | + malertrx_en << 13 | + malertpu_en << 12 | + malertpu_stren << 8 | + malertvref_level; + mem_alert_control2 = malertsync_bypass << + csr_malertsync_bypass_lsb; + addr = t_master | csr_mem_alert_control_addr; + phy_io_write16(phy, addr, mem_alert_control); + addr = t_master | csr_mem_alert_control2_addr; + phy_io_write16(phy, addr, mem_alert_control2); + } +} + +static void prog_dfi_freq_ratio(uint16_t *phy, + const struct input *input) +{ + int dfi_freq_ratio; + uint32_t addr = t_master | csr_dfi_freq_ratio_addr; + + dfi_freq_ratio = input->basic.dfi_freq_ratio; + phy_io_write16(phy, addr, dfi_freq_ratio); +} + +static void prog_tristate_mode_ca(uint16_t *phy, + const struct input *input) +{ + int tristate_mode_ca; + int dis_dyn_adr_tri; + int ddr2tmode; + int ck_dis_val_def = 1; + uint32_t addr = t_master | csr_tristate_mode_ca_addr; + + dis_dyn_adr_tri = input->adv.dis_dyn_adr_tri; + ddr2tmode = input->adv.is2ttiming; + tristate_mode_ca = ck_dis_val_def << csr_ck_dis_val_lsb | + ddr2tmode << csr_ddr2tmode_lsb | + dis_dyn_adr_tri << csr_dis_dyn_adr_tri_lsb; + phy_io_write16(phy, addr, tristate_mode_ca); +} + +static void prog_dfi_xlat(uint16_t *phy, + const struct input *input) +{ + uint16_t loop_vector; + int dfifreqxlat_dat; + int pllbypass_dat; + uint32_t addr; + + /* fIXME: Shall unused P1, P2, P3 be bypassed? */ + pllbypass_dat = input->basic.pll_bypass; /* only [0] is used */ + for (loop_vector = 0; loop_vector < 8; loop_vector++) { + if (loop_vector == 0) { + dfifreqxlat_dat = pllbypass_dat + 0x5555; + } else if (loop_vector == 7) { + dfifreqxlat_dat = 0xf000; + } else { + dfifreqxlat_dat = 0x5555; + } + addr = t_master | (csr_dfi_freq_xlat0_addr + loop_vector); + phy_io_write16(phy, addr, dfifreqxlat_dat); + } +} + +static void prog_dbyte_misc_mode(uint16_t *phy, + const struct input *input, + const struct ddr4u1d *msg) +{ + int dbyte_misc_mode; + int dq_dqs_rcv_cntrl1; + int dq_dqs_rcv_cntrl1_1; + int byte, c_addr; + uint32_t addr; + + dbyte_misc_mode = 0x1 << csr_dbyte_disable_lsb; + dq_dqs_rcv_cntrl1 = 0x1ff << csr_power_down_rcvr_lsb | + 0x1 << csr_power_down_rcvr_dqs_lsb | + 0x1 << csr_rx_pad_standby_en_lsb; + dq_dqs_rcv_cntrl1_1 = (0x100 << csr_power_down_rcvr_lsb | + csr_rx_pad_standby_en_mask); + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + if (byte <= input->basic.num_active_dbyte_dfi0 - 1) { + /* disable RDBI lane if not used. */ + if ((input->basic.dram_data_width != 4) && + (((msg->mr5 >> 12) & 0x1) == 0)) { + addr = t_dbyte + | c_addr + | csr_dq_dqs_rcv_cntrl1_addr; + phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1_1); + } + } else { + addr = t_dbyte | c_addr | csr_dbyte_misc_mode_addr; + phy_io_write16(phy, addr, dbyte_misc_mode); + addr = t_dbyte | c_addr | csr_dq_dqs_rcv_cntrl1_addr; + phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1); + } + } +} + +static void prog_master_x4config(uint16_t *phy, + const struct input *input) +{ + int master_x4config; + int x4tg; + uint32_t addr = t_master | csr_master_x4config_addr; + + x4tg = input->basic.dram_data_width == 4 ? 0xf : 0; + master_x4config = x4tg << csr_x4tg_lsb; + phy_io_write16(phy, addr, master_x4config); +} + +static void prog_dmipin_present(uint16_t *phy, + const struct input *input, + const struct ddr4u1d *msg) +{ + int dmipin_present; + uint32_t addr = t_master | csr_dmipin_present_addr; + + dmipin_present = (msg->mr5 >> 12) & 0x1; + phy_io_write16(phy, addr, dmipin_present); +} + +static void prog_dfi_phyupd(uint16_t *phy, + const struct input *input) +{ + int dfiphyupd_dat; + uint32_t addr; + + addr = t_master | (csr_dfiphyupd_addr); + dfiphyupd_dat = phy_io_read16(phy, addr) & + ~csr_dfiphyupd_threshold_mask; + + phy_io_write16(phy, addr, dfiphyupd_dat); +} + +static void prog_cal_misc2(uint16_t *phy, + const struct input *input) +{ + int cal_misc2_dat, cal_drv_pdth_data, cal_offsets_dat; + uint32_t addr; + + addr = t_master | (csr_cal_misc2_addr); + cal_misc2_dat = phy_io_read16(phy, addr) | + (1 << csr_cal_misc2_err_dis); + + phy_io_write16(phy, addr, cal_misc2_dat); + + addr = t_master | (csr_cal_offsets_addr); + + cal_drv_pdth_data = 0x9 << 6; + cal_offsets_dat = (phy_io_read16(phy, addr) & ~csr_cal_drv_pdth_mask) + | cal_drv_pdth_data; + + phy_io_write16(phy, addr, cal_offsets_dat); +} + +static int c_init_phy_config(uint16_t **phy_ptr, + unsigned int ip_rev, + const struct input *input, + const void *msg) +{ + int i; + uint16_t *phy; + __unused const soc_info_t *soc_info; + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + debug("Initialize PHY %d config\n", i); + prog_dfi_phyupd(phy, input); + prog_cal_misc2(phy, input); + prog_tx_pre_drv_mode(phy, input); + prog_atx_pre_drv_mode(phy, input); + prog_enable_cs_multicast(phy, input); /* rdimm and lrdimm */ + prog_dfi_rd_data_cs_dest_map(phy, ip_rev, input, msg); + prog_pll_ctrl2(phy, input); +#ifdef DDR_PLL_FIX + soc_info = get_soc_info(); + debug("SOC_SI_REV = %x\n", soc_info->svr_reg.bf.maj_ver); + if (soc_info->svr_reg.bf.maj_ver == 1) { + prog_pll_pwr_dn(phy, input); + + /*Enable FFE aka TxEqualizationMode for rev1 SI*/ + phy_io_write16(phy, 0x010048, 0x1); + } +#endif + prog_ard_ptr_init_val(phy, input); + prog_dqs_preamble_control(phy, input); + prog_dll_lck_param(phy, input); + prog_dll_gain_ctl(phy, input); + prog_proc_odt_time_ctl(phy, input); + prog_tx_odt_drv_stren(phy, input); + prog_tx_impedance_ctrl1(phy, input); + prog_atx_impedance(phy, input); + prog_dfi_mode(phy, input); + prog_dfi_camode(phy, input); + prog_cal_drv_str0(phy, input); + prog_cal_uclk_info(phy, input); + prog_cal_rate(phy, input); + prog_vref_in_global(phy, input, msg); + prog_dq_dqs_rcv_cntrl(phy, input); + prog_mem_alert_control(phy, input); + prog_dfi_freq_ratio(phy, input); + prog_tristate_mode_ca(phy, input); + prog_dfi_xlat(phy, input); + prog_dbyte_misc_mode(phy, input, msg); + prog_master_x4config(phy, input); + prog_dmipin_present(phy, input, msg); + prog_acx4_anib_dis(phy, input); + } + + return 0; +} + +static uint32_t get_mail(uint16_t *phy, int stream) +{ + int timeout; + uint32_t mail = 0U; + + timeout = TIMEOUTDEFAULT; + while (((--timeout) != 0) && + ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs) + & uct_write_prot_shadow_mask) != 0)) { + mdelay(10); + } + if (timeout == 0) { + ERROR("Timeout getting mail from PHY\n"); + return 0xFFFF; + } + + mail = phy_io_read16(phy, t_apbonly | + csr_uct_write_only_shadow); + if (stream != 0) { + mail |= phy_io_read16(phy, t_apbonly | + csr_uct_dat_write_only_shadow) << 16; + } + + /* Ack */ + phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 0); + + timeout = TIMEOUTDEFAULT; + while (((--timeout) != 0) && + ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs) + & uct_write_prot_shadow_mask) == 0)) { + mdelay(1); + } + if (timeout == 0) { + ERROR("Timeout ack PHY mail\n"); + } + + /* completed */ + phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 1U); + + return mail; +} + +#ifdef DDR_PHY_DEBUG +static const char *lookup_msg(uint32_t index, int train2d) +{ + int i; + int size; + const struct phy_msg *messages; + const char *ptr = NULL; + + if (train2d != 0) { + messages = messages_2d; + size = ARRAY_SIZE(messages_2d); + } else { + messages = messages_1d; + size = ARRAY_SIZE(messages_1d); + } + for (i = 0; i < size; i++) { + if (messages[i].index == index) { + ptr = messages[i].msg; + break; + } + } + + return ptr; +} +#endif + +#define MAX_ARGS 32 +static void decode_stream_message(uint16_t *phy, int train2d) +{ + uint32_t index __unused; + + __unused const char *format; + __unused uint32_t args[MAX_ARGS]; + __unused int i; + +#ifdef DDR_PHY_DEBUG + index = get_mail(phy, 1); + if ((index & 0xffff) > MAX_ARGS) { /* up to MAX_ARGS args so far */ + printf("Program error in %s\n", __func__); + } + for (i = 0; i < (index & 0xffff) && i < MAX_ARGS; i++) { + args[i] = get_mail(phy, 1); + } + + format = lookup_msg(index, train2d); + if (format != NULL) { + printf("0x%08x: ", index); + printf(format, args[0], args[1], args[2], args[3], args[4], + args[5], args[6], args[7], args[8], args[9], args[10], + args[11], args[12], args[13], args[14], args[15], + args[16], args[17], args[18], args[19], args[20], + args[21], args[22], args[23], args[24], args[25], + args[26], args[27], args[28], args[29], args[30], + args[31]); + } +#endif +} + +static int wait_fw_done(uint16_t *phy, int train2d) +{ + uint32_t mail = 0U; + + while (mail == U(0x0)) { + mail = get_mail(phy, 0); + switch (mail) { + case U(0x7): + debug("%s Training completed\n", train2d ? "2D" : "1D"); + break; + case U(0xff): + debug("%s Training failure\n", train2d ? "2D" : "1D"); + break; + case U(0x0): + debug("End of initialization\n"); + mail = 0U; + break; + case U(0x1): + debug("End of fine write leveling\n"); + mail = 0U; + break; + case U(0x2): + debug("End of read enable training\n"); + mail = 0U; + break; + case U(0x3): + debug("End of read delay center optimization\n"); + mail = 0U; + break; + case U(0x4): + debug("End of write delay center optimization\n"); + mail = 0U; + break; + case U(0x5): + debug("End of 2D read delay/voltage center optimztn\n"); + mail = 0U; + break; + case U(0x6): + debug("End of 2D write delay/voltage center optmztn\n"); + mail = 0U; + break; + case U(0x8): + decode_stream_message(phy, train2d); + mail = 0U; + break; + case U(0x9): + debug("End of max read latency training\n"); + mail = 0U; + break; + case U(0xa): + debug("End of read dq deskew training\n"); + mail = 0U; + break; + case U(0xc): + debug("End of LRDIMM Specific training, including:\n"); + debug("/tDWL, MREP, MRD and MWD\n"); + mail = 0U; + break; + case U(0xd): + debug("End of CA training\n"); + mail = 0U; + break; + case U(0xfd): + debug("End of MPR read delay center optimization\n"); + mail = 0U; + break; + case U(0xfe): + debug("End of Write leveling coarse delay\n"); + mail = 0U; + break; + case U(0xffff): + debug("Timed out\n"); + break; + default: + mail = 0U; + break; + } + } + + if (mail == U(0x7)) { + return 0; + } else if (mail == U(0xff)) { + return -EIO; + } else if (mail == U(0xffff)) { + return -ETIMEDOUT; + } + + debug("PHY_GEN2 FW: Unxpected mail = 0x%x\n", mail); + + return -EINVAL; +} + +static int g_exec_fw(uint16_t **phy_ptr, int train2d, struct input *input) +{ + int ret = -EINVAL; + int i; + uint16_t *phy; + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + debug("Applying PLL optimal settings\n"); + prog_pll_ctrl2(phy, input); + prog_pll_ctrl(phy, input); + phy_io_write16(phy, + t_apbonly | csr_micro_cont_mux_sel_addr, + 0x1); + phy_io_write16(phy, + t_apbonly | csr_micro_reset_addr, + csr_reset_to_micro_mask | + csr_stall_to_micro_mask); + phy_io_write16(phy, + t_apbonly | csr_micro_reset_addr, + csr_stall_to_micro_mask); + phy_io_write16(phy, + t_apbonly | csr_micro_reset_addr, + 0); + + ret = wait_fw_done(phy, train2d); + if (ret == -ETIMEDOUT) { + ERROR("Wait timed out: Firmware execution on PHY %d\n", + i); + } + } + return ret; +} + +static inline int send_fw(uint16_t *phy, + uint32_t dst, + uint16_t *img, + uint32_t size) +{ + uint32_t i; + + if ((size % 2U) != 0U) { + ERROR("Wrong image size 0x%x\n", size); + return -EINVAL; + } + + for (i = 0U; i < size / 2; i++) { + phy_io_write16(phy, dst + i, *(img + i)); + } + + return 0; +} + +static int load_fw(uint16_t **phy_ptr, + struct input *input, + int train2d, + void *msg, + size_t len, + uintptr_t phy_gen2_fw_img_buf, + int (*img_loadr)(unsigned int, uintptr_t *, uint32_t *), + uint32_t warm_boot_flag) +{ + uint32_t imem_id, dmem_id; + uintptr_t image_buf; + uint32_t size; + int ret; + int i; + uint16_t *phy; + + switch (input->basic.dimm_type) { + case UDIMM: + case SODIMM: + case NODIMM: + imem_id = train2d ? DDR_IMEM_UDIMM_2D_IMAGE_ID : + DDR_IMEM_UDIMM_1D_IMAGE_ID; + dmem_id = train2d ? DDR_DMEM_UDIMM_2D_IMAGE_ID : + DDR_DMEM_UDIMM_1D_IMAGE_ID; + break; + case RDIMM: + imem_id = train2d ? DDR_IMEM_RDIMM_2D_IMAGE_ID : + DDR_IMEM_RDIMM_1D_IMAGE_ID; + dmem_id = train2d ? DDR_DMEM_RDIMM_2D_IMAGE_ID : + DDR_DMEM_RDIMM_1D_IMAGE_ID; + break; + default: + ERROR("Unsupported DIMM type\n"); + return -EINVAL; + } + + size = PHY_GEN2_MAX_IMAGE_SIZE; + image_buf = (uintptr_t)phy_gen2_fw_img_buf; + mmap_add_dynamic_region(phy_gen2_fw_img_buf, + phy_gen2_fw_img_buf, + PHY_GEN2_MAX_IMAGE_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); + ret = img_loadr(imem_id, &image_buf, &size); + if (ret != 0) { + ERROR("Failed to load %d firmware.\n", imem_id); + return ret; + } + debug("Loaded Imaged id %d of size %x at address %lx\n", + imem_id, size, image_buf); + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + if (warm_boot_flag != DDR_WARM_BOOT) { + if (train2d == 0) { + phy_io_write16(phy, t_master | + csr_mem_reset_l_addr, + csr_protect_mem_reset_mask); + } + } + /* Enable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 0); + + ret = send_fw(phy, PHY_GEN2_IMEM_ADDR, + (uint16_t *)image_buf, size); + if (ret != 0) { + return ret; + } + } + + size = PHY_GEN2_MAX_IMAGE_SIZE; + image_buf = (uintptr_t)phy_gen2_fw_img_buf; + ret = img_loadr(dmem_id, &image_buf, &size); + if (ret != 0) { + ERROR("Failed to load %d firmware.\n", dmem_id); + return ret; + } + debug("Loaded Imaged id %d of size %x at address %lx\n", + dmem_id, size, image_buf); + image_buf += len; + size -= len; + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + ret = send_fw(phy, PHY_GEN2_DMEM_ADDR, msg, len); + if (ret != 0) { + return ret; + } + + ret = send_fw(phy, PHY_GEN2_DMEM_ADDR + len / 2, + (uint16_t *)image_buf, size); + if (ret != 0) { + return ret; + } + } + + return ret; +} + +static void parse_odt(const unsigned int val, + const int read, + const int i, + const unsigned int cs_d0, + const unsigned int cs_d1, + unsigned int *odt) +{ + int shift = read ? 4 : 0; + int j; + + if (i < 0 || i > 3) { + printf("Error: invalid chip-select value\n"); + } + switch (val) { + case DDR_ODT_CS: + odt[i] |= (1 << i) << shift; + break; + case DDR_ODT_ALL_OTHER_CS: + for (j = 0; j < DDRC_NUM_CS; j++) { + if (i == j) { + continue; + } + if (((cs_d0 | cs_d1) & (1 << j)) == 0) { + continue; + } + odt[j] |= (1 << i) << shift; + } + break; + case DDR_ODT_CS_AND_OTHER_DIMM: + odt[i] |= (1 << i) << 4; + /* fallthrough */ + case DDR_ODT_OTHER_DIMM: + for (j = 0; j < DDRC_NUM_CS; j++) { + if ((((cs_d0 & (1 << i)) != 0) && + ((cs_d1 & (1 << j)) != 0)) || + (((cs_d1 & (1 << i)) != 0) && + ((cs_d0 & (1 << j)) != 0))) { + odt[j] |= (1 << i) << shift; + } + } + break; + case DDR_ODT_ALL: + for (j = 0; j < DDRC_NUM_CS; j++) { + if (((cs_d0 | cs_d1) & (1 << j)) == 0) { + continue; + } + odt[j] |= (1 << i) << shift; + } + break; + case DDR_ODT_SAME_DIMM: + for (j = 0; j < DDRC_NUM_CS; j++) { + if ((((cs_d0 & (1 << i)) != 0) && + ((cs_d0 & (1 << j)) != 0)) || + (((cs_d1 & (1 << i)) != 0) && + ((cs_d1 & (1 << j)) != 0))) { + odt[j] |= (1 << i) << shift; + } + } + break; + case DDR_ODT_OTHER_CS_ONSAMEDIMM: + for (j = 0; j < DDRC_NUM_CS; j++) { + if (i == j) { + continue; + } + if ((((cs_d0 & (1 << i)) != 0) && + ((cs_d0 & (1 << j)) != 0)) || + (((cs_d1 & (1 << i)) != 0) && + ((cs_d1 & (1 << j)) != 0))) { + odt[j] |= (1 << i) << shift; + } + } + break; + case DDR_ODT_NEVER: + break; + default: + break; + } +} + +#ifdef DEBUG_DDR_INPUT_CONFIG +char *dram_types_str[] = { + "DDR4", + "DDR3", + "LDDDR4", + "LPDDR3", + "LPDDR2", + "DDR5" +}; + +char *dimm_types_str[] = { + "UDIMM", + "SODIMM", + "RDIMM", + "LRDIMM", + "NODIMM", +}; + + +static void print_jason_format(struct input *input, + struct ddr4u1d *msg_1d, + struct ddr4u2d *msg_2d) +{ + + printf("\n{"); + printf("\n \"dram_type\": \"%s\",", dram_types_str[input->basic.dram_type]); + printf("\n \"dimm_type\": \"%s\",", dimm_types_str[input->basic.dimm_type]); + printf("\n \"hard_macro_ver\": \"%d\",", input->basic.hard_macro_ver); + printf("\n \"num_dbyte\": \"0x%04x\",", (unsigned int)input->basic.num_dbyte); + printf("\n \"num_active_dbyte_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_active_dbyte_dfi0); + printf("\n \"num_anib\": \"0x%04x\",", (unsigned int)input->basic.num_anib); + printf("\n \"num_rank_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_rank_dfi0); + printf("\n \"num_pstates\": \"0x%04x\",", (unsigned int)input->basic.num_pstates); + printf("\n \"frequency\": \"%d\",", input->basic.frequency); + printf("\n \"pll_bypass\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio); + printf("\n \"dfi_freq_ratio\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio); + printf("\n \"dfi1_exists\": \"0x%04x\",", (unsigned int)input->basic.dfi1exists); + printf("\n \"dram_data_width\": \"0x%04x\",", (unsigned int)input->basic.dram_data_width); + printf("\n \"dram_byte_swap\": \"0x%04x\",", (unsigned int)input->adv.dram_byte_swap); + printf("\n \"ext_cal_res_val\": \"0x%04x\",", (unsigned int)input->adv.ext_cal_res_val); + printf("\n \"tx_slew_rise_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_dq); + printf("\n \"tx_slew_fall_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_dq); + printf("\n \"tx_slew_rise_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_ac); + printf("\n \"tx_slew_fall_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_ac); + printf("\n \"odt_impedance\": \"%d\",", input->adv.odtimpedance); + printf("\n \"tx_impedance\": \"%d\",", input->adv.tx_impedance); + printf("\n \"atx_impedance\": \"%d\",", input->adv.atx_impedance); + printf("\n \"mem_alert_en\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_en); + printf("\n \"mem_alert_pu_imp\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_puimp); + printf("\n \"mem_alert_vref_level\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_vref_level); + printf("\n \"mem_alert_sync_bypass\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_sync_bypass); + printf("\n \"cal_interval\": \"0x%04x\",", (unsigned int)input->adv.cal_interval); + printf("\n \"cal_once\": \"0x%04x\",", (unsigned int)input->adv.cal_once); + printf("\n \"dis_dyn_adr_tri\": \"0x%04x\",", (unsigned int)input->adv.dis_dyn_adr_tri); + printf("\n \"is2t_timing\": \"0x%04x\",", (unsigned int)input->adv.is2ttiming); + printf("\n \"d4rx_preabmle_length\": \"0x%04x\",", (unsigned int)input->adv.d4rx_preamble_length); + printf("\n \"d4tx_preamble_length\": \"0x%04x\",", (unsigned int)input->adv.d4tx_preamble_length); + printf("\n \"msg_misc\": \"0x%02x\",", (unsigned int)msg_1d->msg_misc); + printf("\n \"reserved00\": \"0x%01x\",", (unsigned int)msg_1d->reserved00); + printf("\n \"hdt_ctrl\": \"0x%02x\",", (unsigned int)msg_1d->hdt_ctrl); + printf("\n \"cs_present\": \"0x%02x\",", (unsigned int)msg_1d->cs_present); + printf("\n \"phy_vref\": \"0x%02x\",", (unsigned int)msg_1d->phy_vref); + printf("\n \"dfi_mrl_margin\": \"0x%02x\",", (unsigned int)msg_1d->dfimrlmargin); + printf("\n \"addr_mirror\": \"0x%02x\",", (unsigned int)msg_1d->addr_mirror); + printf("\n \"wr_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0x0f)); + printf("\n \"wr_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0x0f)); + printf("\n \"wr_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0x0f)); + printf("\n \"wr_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0x0f)); + printf("\n \"rd_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0xf0)); + printf("\n \"rd_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0xf0)); + printf("\n \"rd_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0xf0)); + printf("\n \"rd_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0xf0)); + printf("\n \"d4_misc\": \"0x%01x\",", (unsigned int)msg_1d->d4misc); + printf("\n \"share_2d_vref_results\": \"0x%01x\",", (unsigned int)msg_1d->share2dvref_result); + printf("\n \"sequence_ctrl\": \"0x%04x\",", (unsigned int)msg_1d->sequence_ctrl); + printf("\n \"mr0\": \"0x%04x\",", (unsigned int)msg_1d->mr0); + printf("\n \"mr1\": \"0x%04x\",", (unsigned int)msg_1d->mr1); + printf("\n \"mr2\": \"0x%04x\",", (unsigned int)msg_1d->mr2); + printf("\n \"mr3\": \"0x%04x\",", (unsigned int)msg_1d->mr3); + printf("\n \"mr4\": \"0x%04x\",", (unsigned int)msg_1d->mr4); + printf("\n \"mr5\": \"0x%04x\",", (unsigned int)msg_1d->mr5); + printf("\n \"mr6\": \"0x%04x\",", (unsigned int)msg_1d->mr6); + printf("\n \"alt_cal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_cas_l); + printf("\n \"alt_wcal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_wcas_l); + printf("\n \"sequence_ctrl_2d\": \"0x%04x\",", (unsigned int)msg_2d->sequence_ctrl); + printf("\n \"rtt_nom_wr_park0\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park0); + printf("\n \"rtt_nom_wr_park1\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park1); + printf("\n \"rtt_nom_wr_park2\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park2); + printf("\n \"rtt_nom_wr_park3\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park3); + printf("\n \"rtt_nom_wr_park4\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park4); + printf("\n \"rtt_nom_wr_park5\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park5); + printf("\n \"rtt_nom_wr_park6\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park6); + printf("\n \"rtt_nom_wr_park7\": \"0x%01x\"", (unsigned int)msg_1d->rtt_nom_wr_park7); + printf("\n}"); + printf("\n"); +} +#endif + +int compute_ddr_phy(struct ddr_info *priv) +{ + const unsigned long clk = priv->clk; + const struct memctl_opt *popts = &priv->opt; + const struct ddr_conf *conf = &priv->conf; + const struct dimm_params *dimm_param = &priv->dimm; + struct ddr_cfg_regs *regs = &priv->ddr_reg; + int ret; + static struct input input; + static struct ddr4u1d msg_1d; + static struct ddr4u2d msg_2d; + unsigned int i; + unsigned int odt_rd, odt_wr; + __unused const soc_info_t *soc_info; +#ifdef NXP_APPLY_MAX_CDD + unsigned int tcfg0, tcfg4, rank; +#endif + + if (dimm_param == NULL) { + ERROR("Empty DIMM parameters.\n"); + return -EINVAL; + } + + zeromem(&input, sizeof(input)); + zeromem(&msg_1d, sizeof(msg_1d)); + zeromem(&msg_2d, sizeof(msg_2d)); + + input.basic.dram_type = DDR4; + /* FIXME: Add condition for LRDIMM */ + input.basic.dimm_type = (dimm_param->rdimm != 0) ? RDIMM : UDIMM; + input.basic.num_dbyte = dimm_param->primary_sdram_width / 8 + + dimm_param->ec_sdram_width / 8; + input.basic.num_active_dbyte_dfi0 = input.basic.num_dbyte; + input.basic.num_rank_dfi0 = dimm_param->n_ranks; + input.basic.dram_data_width = dimm_param->device_width; + input.basic.hard_macro_ver = 0xa; + input.basic.num_pstates = 1; + input.basic.dfi_freq_ratio = 1; + input.basic.num_anib = 0xc; + input.basic.train2d = popts->skip2d ? 0 : 1; + input.basic.frequency = (int) (clk / 2000000ul); + debug("frequency = %dMHz\n", input.basic.frequency); + input.cs_d0 = conf->cs_on_dimm[0]; +#if DDRC_NUM_DIMM > 1 + input.cs_d1 = conf->cs_on_dimm[1]; +#endif + input.mirror = dimm_param->mirrored_dimm; + input.mr[0] = regs->sdram_mode[0] & U(0xffff); + input.mr[1] = regs->sdram_mode[0] >> 16U; + input.mr[2] = regs->sdram_mode[1] >> 16U; + input.mr[3] = regs->sdram_mode[1] & U(0xffff); + input.mr[4] = regs->sdram_mode[8] >> 16U; + input.mr[5] = regs->sdram_mode[8] & U(0xffff); + input.mr[6] = regs->sdram_mode[9] >> 16U; + input.vref = popts->vref_phy; + debug("Vref_phy = %d percent\n", (input.vref * 100U) >> 7U); + for (i = 0U; i < DDRC_NUM_CS; i++) { + if ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) == 0U) { + continue; + } + odt_rd = (regs->cs[i].config >> 20U) & U(0x7); + odt_wr = (regs->cs[i].config >> 16U) & U(0x7); + parse_odt(odt_rd, true, i, input.cs_d0, input.cs_d1, + input.odt); + parse_odt(odt_wr, false, i, input.cs_d0, input.cs_d1, + input.odt); + } + + /* Do not set sdram_cfg[RD_EN] or sdram_cfg2[RCW_EN] for RDIMM */ + if (dimm_param->rdimm != 0U) { + regs->sdram_cfg[0] &= ~(1 << 28U); + regs->sdram_cfg[1] &= ~(1 << 2U); + input.rcw[0] = (regs->sdram_rcw[0] >> 28U) & U(0xf); + input.rcw[1] = (regs->sdram_rcw[0] >> 24U) & U(0xf); + input.rcw[2] = (regs->sdram_rcw[0] >> 20U) & U(0xf); + input.rcw[3] = (regs->sdram_rcw[0] >> 16U) & U(0xf); + input.rcw[4] = (regs->sdram_rcw[0] >> 12U) & U(0xf); + input.rcw[5] = (regs->sdram_rcw[0] >> 8U) & U(0xf); + input.rcw[6] = (regs->sdram_rcw[0] >> 4U) & U(0xf); + input.rcw[7] = (regs->sdram_rcw[0] >> 0U) & U(0xf); + input.rcw[8] = (regs->sdram_rcw[1] >> 28U) & U(0xf); + input.rcw[9] = (regs->sdram_rcw[1] >> 24U) & U(0xf); + input.rcw[10] = (regs->sdram_rcw[1] >> 20U) & U(0xf); + input.rcw[11] = (regs->sdram_rcw[1] >> 16U) & U(0xf); + input.rcw[12] = (regs->sdram_rcw[1] >> 12U) & U(0xf); + input.rcw[13] = (regs->sdram_rcw[1] >> 8U) & U(0xf); + input.rcw[14] = (regs->sdram_rcw[1] >> 4U) & U(0xf); + input.rcw[15] = (regs->sdram_rcw[1] >> 0U) & U(0xf); + input.rcw3x = (regs->sdram_rcw[2] >> 8U) & U(0xff); + } + + input.adv.odtimpedance = popts->odt ? popts->odt : 60; + input.adv.tx_impedance = popts->phy_tx_impedance ? + popts->phy_tx_impedance : 28; + input.adv.atx_impedance = popts->phy_atx_impedance ? + popts->phy_atx_impedance : 30; + + debug("Initializing input adv data structure\n"); + phy_gen2_init_input(&input); + + debug("Initializing message block\n"); + ret = phy_gen2_msg_init(&msg_1d, &msg_2d, &input); + if (ret != 0) { + ERROR("Init msg failed (error code %d)\n", ret); + return ret; + } + + ret = c_init_phy_config(priv->phy, priv->ip_rev, &input, &msg_1d); + if (ret != 0) { + ERROR("Init PHY failed (error code %d)\n", ret); + return ret; + } +#ifdef NXP_WARM_BOOT + debug("Warm boot flag value %0x\n", priv->warm_boot_flag); + if (priv->warm_boot_flag == DDR_WARM_BOOT) { + debug("Restoring the Phy training data\n"); + // Restore the training data + ret = restore_phy_training_values(priv->phy, + PHY_TRAINING_REGS_ON_FLASH, + priv->num_ctlrs, + input.basic.train2d); + if (ret != 0) { + ERROR("Restoring of training data failed %d\n", ret); + return ret; + } + } else { +#endif + + debug("Load 1D firmware\n"); + ret = load_fw(priv->phy, &input, 0, &msg_1d, + sizeof(struct ddr4u1d), priv->phy_gen2_fw_img_buf, + priv->img_loadr, priv->warm_boot_flag); + if (ret != 0) { + ERROR("Loading firmware failed (error code %d)\n", ret); + return ret; + } + + debug("Execute firmware\n"); + ret = g_exec_fw(priv->phy, 0, &input); + if (ret != 0) { + ERROR("Execution FW failed (error code %d)\n", ret); + } + +#ifdef NXP_APPLY_MAX_CDD + soc_info = get_soc_info(); + if (soc_info->svr_reg.bf.maj_ver == 2) { + tcfg0 = regs->timing_cfg[0]; + tcfg4 = regs->timing_cfg[4]; + rank = findrank(conf->cs_in_use); + get_cdd_val(priv->phy, rank, input.basic.frequency, + &tcfg0, &tcfg4); + regs->timing_cfg[0] = tcfg0; + regs->timing_cfg[4] = tcfg4; + } +#endif + + if ((ret == 0) && (input.basic.train2d != 0)) { + /* 2D training starts here */ + debug("Load 2D firmware\n"); + ret = load_fw(priv->phy, &input, 1, &msg_2d, + sizeof(struct ddr4u2d), + priv->phy_gen2_fw_img_buf, + priv->img_loadr, + priv->warm_boot_flag); + if (ret != 0) { + ERROR("Loading fw failed (err code %d)\n", ret); + } else { + debug("Execute 2D firmware\n"); + ret = g_exec_fw(priv->phy, 1, &input); + if (ret != 0) { + ERROR("Execution FW failed (err %d)\n", + ret); + } + } + } +#ifdef NXP_WARM_BOOT + if (priv->warm_boot_flag != DDR_WRM_BOOT_NT_SUPPORTED && + ret == 0) { + debug("save the phy training data\n"); + //Save training data TBD + ret = save_phy_training_values(priv->phy, + PHY_TRAINING_REGS_ON_FLASH, + priv->num_ctlrs, + input.basic.train2d); + if (ret != 0) { + ERROR("Saving training data failed."); + ERROR("Warm boot will fail. Error=%d.\n", ret); + } + } + } /* else */ +#endif + + if (ret == 0) { + debug("Load PIE\n"); + i_load_pie(priv->phy, &input, &msg_1d); + + NOTICE("DDR4 %s with %d-rank %d-bit bus (x%d)\n", + input.basic.dimm_type == RDIMM ? "RDIMM" : + input.basic.dimm_type == LRDIMM ? "LRDIMM" : + "UDIMM", + dimm_param->n_ranks, + dimm_param->primary_sdram_width, + dimm_param->device_width); + } +#ifdef DEBUG_DDR_INPUT_CONFIG + print_jason_format(&input, &msg_1d, &msg_2d); +#endif + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h new file mode 100644 index 0000000..15e80d1 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h @@ -0,0 +1,334 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if !defined(PHY_H) && defined(NXP_WARM_BOOT) +#define PHY_H + +#include + +/* To store sector size to be erase on flash*/ +#define PHY_ERASE_SIZE F_SECTOR_ERASE_SZ + +/*Structure to implement address-data map tuples to store PHY training values*/ +struct phy_training_values { + uint32_t addr; + uint16_t data; +}; +/* Saves PHY Training Register values after cold reset + *@param[in] phy_ptr array to store addresses of PHYs + *@param[in] address_to_store address to save PHY training register values + *on flash + *@param[in] num_of_phy the number of PHY for which training values are + *to be saved + *@param[in] train2d flag to store whether 2D training registers are to + *be saved or not + * + *PHY training values will be stored on flash at contigous memory in the order: + *1D training registers, 2D training registers + *for each PHY + * + *if train2d is false saving 2D training registers will be skipped + */ +int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store, + uint32_t num_of_phy, int train2d); + +/*Restores PHY Training Register values after warm reset + *@param[in] phy_ptr array to store addresses of PHYs + *@param[in] address_to_store address to retrieve PHY training register + *values from flash + *@param[in] num_of_phy the number of PHY for which training values are + *to be restored + *@param[in] train2d flag to store whether 2D training registers are + *to be restored or not + * + *if train2d is false saving 2D training registers will be skipped + */ + +int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore, + uint32_t num_of_phy, int train2d); + +/* + * Address data tuples to store the PHY 1D + */ + +struct phy_training_values training_1D_values[] = { + {0x200B2, 0}, {0x200CB, 0}, {0x10043, 0}, {0x11043, 0}, + {0x12043, 0}, {0x13043, 0}, {0x14043, 0}, {0x15043, 0}, + {0x16043, 0}, {0x17043, 0}, {0x18043, 0}, {0x10143, 0}, + {0x11143, 0}, {0x12143, 0}, {0x13143, 0}, {0x14143, 0}, + {0x15143, 0}, {0x16143, 0}, {0x17143, 0}, {0x18143, 0}, + {0x10080, 0}, {0x11080, 0}, {0x12080, 0}, {0x13080, 0}, + {0x14080, 0}, {0x15080, 0}, {0x16080, 0}, {0x17080, 0}, + {0x18080, 0}, {0x10180, 0}, {0x11180, 0}, {0x12180, 0}, + {0x13180, 0}, {0x14180, 0}, {0x15180, 0}, {0x16180, 0}, + {0x17180, 0}, {0x18180, 0}, {0x10081, 0}, {0x11081, 0}, + {0x12081, 0}, {0x13081, 0}, {0x14081, 0}, {0x15081, 0}, + {0x16081, 0}, {0x17081, 0}, {0x18081, 0}, {0x10181, 0}, + {0x11181, 0}, {0x12181, 0}, {0x13181, 0}, {0x14181, 0}, + {0x15181, 0}, {0x16181, 0}, {0x17181, 0}, {0x18181, 0}, + {0x10082, 0}, {0x11082, 0}, {0x12082, 0}, {0x13082, 0}, + {0x14082, 0}, {0x15082, 0}, {0x16082, 0}, {0x17082, 0}, + {0x18082, 0}, {0x10182, 0}, {0x11182, 0}, {0x12182, 0}, + {0x13182, 0}, {0x14182, 0}, {0x15182, 0}, {0x16182, 0}, + {0x17182, 0}, {0x18182, 0}, {0x10083, 0}, {0x11083, 0}, + {0x12083, 0}, {0x13083, 0}, {0x14083, 0}, {0x15083, 0}, + {0x16083, 0}, {0x17083, 0}, {0x18083, 0}, {0x10183, 0}, + {0x11183, 0}, {0x12183, 0}, {0x13183, 0}, {0x14183, 0}, + {0x15183, 0}, {0x16183, 0}, {0x17183, 0}, {0x18183, 0}, + {0x100D0, 0}, {0x110D0, 0}, {0x120D0, 0}, {0x130D0, 0}, + {0x140D0, 0}, {0x150D0, 0}, {0x160D0, 0}, {0x170D0, 0}, + {0x180D0, 0}, {0x101D0, 0}, {0x111D0, 0}, {0x121D0, 0}, + {0x131D0, 0}, {0x141D0, 0}, {0x151D0, 0}, {0x161D0, 0}, + {0x171D0, 0}, {0x181D0, 0}, {0x100D1, 0}, {0x110D1, 0}, + {0x120D1, 0}, {0x130D1, 0}, {0x140D1, 0}, {0x150D1, 0}, + {0x160D1, 0}, {0x170D1, 0}, {0x180D1, 0}, {0x101D1, 0}, + {0x111D1, 0}, {0x121D1, 0}, {0x131D1, 0}, {0x141D1, 0}, + {0x151D1, 0}, {0x161D1, 0}, {0x171D1, 0}, {0x181D1, 0}, + {0x100D2, 0}, {0x110D2, 0}, {0x120D2, 0}, {0x130D2, 0}, + {0x140D2, 0}, {0x150D2, 0}, {0x160D2, 0}, {0x170D2, 0}, + {0x180D2, 0}, {0x101D2, 0}, {0x111D2, 0}, {0x121D2, 0}, + {0x131D2, 0}, {0x141D2, 0}, {0x151D2, 0}, {0x161D2, 0}, + {0x171D2, 0}, {0x181D2, 0}, {0x100D3, 0}, {0x110D3, 0}, + {0x120D3, 0}, {0x130D3, 0}, {0x140D3, 0}, {0x150D3, 0}, + {0x160D3, 0}, {0x170D3, 0}, {0x180D3, 0}, {0x101D3, 0}, + {0x111D3, 0}, {0x121D3, 0}, {0x131D3, 0}, {0x141D3, 0}, + {0x151D3, 0}, {0x161D3, 0}, {0x171D3, 0}, {0x181D3, 0}, + {0x10068, 0}, {0x11068, 0}, {0x12068, 0}, {0x13068, 0}, + {0x14068, 0}, {0x15068, 0}, {0x16068, 0}, {0x17068, 0}, + {0x18068, 0}, {0x10168, 0}, {0x11168, 0}, {0x12168, 0}, + {0x13168, 0}, {0x14168, 0}, {0x15168, 0}, {0x16168, 0}, + {0x17168, 0}, {0x18168, 0}, {0x10268, 0}, {0x11268, 0}, + {0x12268, 0}, {0x13268, 0}, {0x14268, 0}, {0x15268, 0}, + {0x16268, 0}, {0x17268, 0}, {0x18268, 0}, {0x10368, 0}, + {0x11368, 0}, {0x12368, 0}, {0x13368, 0}, {0x14368, 0}, + {0x15368, 0}, {0x16368, 0}, {0x17368, 0}, {0x18368, 0}, + {0x10468, 0}, {0x11468, 0}, {0x12468, 0}, {0x13468, 0}, + {0x14468, 0}, {0x15468, 0}, {0x16468, 0}, {0x17468, 0}, + {0x18468, 0}, {0x10568, 0}, {0x11568, 0}, {0x12568, 0}, + {0x13568, 0}, {0x14568, 0}, {0x15568, 0}, {0x16568, 0}, + {0x17568, 0}, {0x18568, 0}, {0x10668, 0}, {0x11668, 0}, + {0x12668, 0}, {0x13668, 0}, {0x14668, 0}, {0x15668, 0}, + {0x16668, 0}, {0x17668, 0}, {0x18668, 0}, {0x10768, 0}, + {0x11768, 0}, {0x12768, 0}, {0x13768, 0}, {0x14768, 0}, + {0x15768, 0}, {0x16768, 0}, {0x17768, 0}, {0x18768, 0}, + {0x10868, 0}, {0x11868, 0}, {0x12868, 0}, {0x13868, 0}, + {0x14868, 0}, {0x15868, 0}, {0x16868, 0}, {0x17868, 0}, + {0x18868, 0}, {0x10069, 0}, {0x11069, 0}, {0x12069, 0}, + {0x13069, 0}, {0x14069, 0}, {0x15069, 0}, {0x16069, 0}, + {0x17069, 0}, {0x18069, 0}, {0x10169, 0}, {0x11169, 0}, + {0x12169, 0}, {0x13169, 0}, {0x14169, 0}, {0x15169, 0}, + {0x16169, 0}, {0x17169, 0}, {0x18169, 0}, {0x10269, 0}, + {0x11269, 0}, {0x12269, 0}, {0x13269, 0}, {0x14269, 0}, + {0x15269, 0}, {0x16269, 0}, {0x17269, 0}, {0x18269, 0}, + {0x10369, 0}, {0x11369, 0}, {0x12369, 0}, {0x13369, 0}, + {0x14369, 0}, {0x15369, 0}, {0x16369, 0}, {0x17369, 0}, + {0x18369, 0}, {0x10469, 0}, {0x11469, 0}, {0x12469, 0}, + {0x13469, 0}, {0x14469, 0}, {0x15469, 0}, {0x16469, 0}, + {0x17469, 0}, {0x18469, 0}, {0x10569, 0}, {0x11569, 0}, + {0x12569, 0}, {0x13569, 0}, {0x14569, 0}, {0x15569, 0}, + {0x16569, 0}, {0x17569, 0}, {0x18569, 0}, {0x10669, 0}, + {0x11669, 0}, {0x12669, 0}, {0x13669, 0}, {0x14669, 0}, + {0x15669, 0}, {0x16669, 0}, {0x17669, 0}, {0x18669, 0}, + {0x10769, 0}, {0x11769, 0}, {0x12769, 0}, {0x13769, 0}, + {0x14769, 0}, {0x15769, 0}, {0x16769, 0}, {0x17769, 0}, + {0x18769, 0}, {0x10869, 0}, {0x11869, 0}, {0x12869, 0}, + {0x13869, 0}, {0x14869, 0}, {0x15869, 0}, {0x16869, 0}, + {0x17869, 0}, {0x18869, 0}, {0x1006A, 0}, {0x1106A, 0}, + {0x1206A, 0}, {0x1306A, 0}, {0x1406A, 0}, {0x1506A, 0}, + {0x1606A, 0}, {0x1706A, 0}, {0x1806A, 0}, {0x1016A, 0}, + {0x1116A, 0}, {0x1216A, 0}, {0x1316A, 0}, {0x1416A, 0}, + {0x1516A, 0}, {0x1616A, 0}, {0x1716A, 0}, {0x1816A, 0}, + {0x1026A, 0}, {0x1126A, 0}, {0x1226A, 0}, {0x1326A, 0}, + {0x1426A, 0}, {0x1526A, 0}, {0x1626A, 0}, {0x1726A, 0}, + {0x1826A, 0}, {0x1036A, 0}, {0x1136A, 0}, {0x1236A, 0}, + {0x1336A, 0}, {0x1436A, 0}, {0x1536A, 0}, {0x1636A, 0}, + {0x1736A, 0}, {0x1836A, 0}, {0x1046A, 0}, {0x1146A, 0}, + {0x1246A, 0}, {0x1346A, 0}, {0x1446A, 0}, {0x1546A, 0}, + {0x1646A, 0}, {0x1746A, 0}, {0x1846A, 0}, {0x1056A, 0}, + {0x1156A, 0}, {0x1256A, 0}, {0x1356A, 0}, {0x1456A, 0}, + {0x1556A, 0}, {0x1656A, 0}, {0x1756A, 0}, {0x1856A, 0}, + {0x1066A, 0}, {0x1166A, 0}, {0x1266A, 0}, {0x1366A, 0}, + {0x1466A, 0}, {0x1566A, 0}, {0x1666A, 0}, {0x1766A, 0}, + {0x1866A, 0}, {0x1076A, 0}, {0x1176A, 0}, {0x1276A, 0}, + {0x1376A, 0}, {0x1476A, 0}, {0x1576A, 0}, {0x1676A, 0}, + {0x1776A, 0}, {0x1876A, 0}, {0x1086A, 0}, {0x1186A, 0}, + {0x1286A, 0}, {0x1386A, 0}, {0x1486A, 0}, {0x1586A, 0}, + {0x1686A, 0}, {0x1786A, 0}, {0x1886A, 0}, {0x1006B, 0}, + {0x1106B, 0}, {0x1206B, 0}, {0x1306B, 0}, {0x1406B, 0}, + {0x1506B, 0}, {0x1606B, 0}, {0x1706B, 0}, {0x1806B, 0}, + {0x1016B, 0}, {0x1116B, 0}, {0x1216B, 0}, {0x1316B, 0}, + {0x1416B, 0}, {0x1516B, 0}, {0x1616B, 0}, {0x1716B, 0}, + {0x1816B, 0}, {0x1026B, 0}, {0x1126B, 0}, {0x1226B, 0}, + {0x1326B, 0}, {0x1426B, 0}, {0x1526B, 0}, {0x1626B, 0}, + {0x1726B, 0}, {0x1826B, 0}, {0x1036B, 0}, {0x1136B, 0}, + {0x1236B, 0}, {0x1336B, 0}, {0x1436B, 0}, {0x1536B, 0}, + {0x1636B, 0}, {0x1736B, 0}, {0x1836B, 0}, {0x1046B, 0}, + {0x1146B, 0}, {0x1246B, 0}, {0x1346B, 0}, {0x1446B, 0}, + {0x1546B, 0}, {0x1646B, 0}, {0x1746B, 0}, {0x1846B, 0}, + {0x1056B, 0}, {0x1156B, 0}, {0x1256B, 0}, {0x1356B, 0}, + {0x1456B, 0}, {0x1556B, 0}, {0x1656B, 0}, {0x1756B, 0}, + {0x1856B, 0}, {0x1066B, 0}, {0x1166B, 0}, {0x1266B, 0}, + {0x1366B, 0}, {0x1466B, 0}, {0x1566B, 0}, {0x1666B, 0}, + {0x1766B, 0}, {0x1866B, 0}, {0x1076B, 0}, {0x1176B, 0}, + {0x1276B, 0}, {0x1376B, 0}, {0x1476B, 0}, {0x1576B, 0}, + {0x1676B, 0}, {0x1776B, 0}, {0x1876B, 0}, {0x1086B, 0}, + {0x1186B, 0}, {0x1286B, 0}, {0x1386B, 0}, {0x1486B, 0}, + {0x1586B, 0}, {0x1686B, 0}, {0x1786B, 0}, {0x1886B, 0}, + {0x1008C, 0}, {0x1108C, 0}, {0x1208C, 0}, {0x1308C, 0}, + {0x1408C, 0}, {0x1508C, 0}, {0x1608C, 0}, {0x1708C, 0}, + {0x1808C, 0}, {0x1018C, 0}, {0x1118C, 0}, {0x1218C, 0}, + {0x1318C, 0}, {0x1418C, 0}, {0x1518C, 0}, {0x1618C, 0}, + {0x1718C, 0}, {0x1818C, 0}, {0x1008D, 0}, {0x1108D, 0}, + {0x1208D, 0}, {0x1308D, 0}, {0x1408D, 0}, {0x1508D, 0}, + {0x1608D, 0}, {0x1708D, 0}, {0x1808D, 0}, {0x1018D, 0}, + {0x1118D, 0}, {0x1218D, 0}, {0x1318D, 0}, {0x1418D, 0}, + {0x1518D, 0}, {0x1618D, 0}, {0x1718D, 0}, {0x1818D, 0}, + {0x1008E, 0}, {0x1108E, 0}, {0x1208E, 0}, {0x1308E, 0}, + {0x1408E, 0}, {0x1508E, 0}, {0x1608E, 0}, {0x1708E, 0}, + {0x1808E, 0}, {0x1018E, 0}, {0x1118E, 0}, {0x1218E, 0}, + {0x1318E, 0}, {0x1418E, 0}, {0x1518E, 0}, {0x1618E, 0}, + {0x1718E, 0}, {0x1818E, 0}, {0x1008F, 0}, {0x1108F, 0}, + {0x1208F, 0}, {0x1308F, 0}, {0x1408F, 0}, {0x1508F, 0}, + {0x1608F, 0}, {0x1708F, 0}, {0x1808F, 0}, {0x1018F, 0}, + {0x1118F, 0}, {0x1218F, 0}, {0x1318F, 0}, {0x1418F, 0}, + {0x1518F, 0}, {0x1618F, 0}, {0x1718F, 0}, {0x1818F, 0}, + {0x100C0, 0}, {0x110C0, 0}, {0x120C0, 0}, {0x130C0, 0}, + {0x140C0, 0}, {0x150C0, 0}, {0x160C0, 0}, {0x170C0, 0}, + {0x180C0, 0}, {0x101C0, 0}, {0x111C0, 0}, {0x121C0, 0}, + {0x131C0, 0}, {0x141C0, 0}, {0x151C0, 0}, {0x161C0, 0}, + {0x171C0, 0}, {0x181C0, 0}, {0x102C0, 0}, {0x112C0, 0}, + {0x122C0, 0}, {0x132C0, 0}, {0x142C0, 0}, {0x152C0, 0}, + {0x162C0, 0}, {0x172C0, 0}, {0x182C0, 0}, {0x103C0, 0}, + {0x113C0, 0}, {0x123C0, 0}, {0x133C0, 0}, {0x143C0, 0}, + {0x153C0, 0}, {0x163C0, 0}, {0x173C0, 0}, {0x183C0, 0}, + {0x104C0, 0}, {0x114C0, 0}, {0x124C0, 0}, {0x134C0, 0}, + {0x144C0, 0}, {0x154C0, 0}, {0x164C0, 0}, {0x174C0, 0}, + {0x184C0, 0}, {0x105C0, 0}, {0x115C0, 0}, {0x125C0, 0}, + {0x135C0, 0}, {0x145C0, 0}, {0x155C0, 0}, {0x165C0, 0}, + {0x175C0, 0}, {0x185C0, 0}, {0x106C0, 0}, {0x116C0, 0}, + {0x126C0, 0}, {0x136C0, 0}, {0x146C0, 0}, {0x156C0, 0}, + {0x166C0, 0}, {0x176C0, 0}, {0x186C0, 0}, {0x107C0, 0}, + {0x117C0, 0}, {0x127C0, 0}, {0x137C0, 0}, {0x147C0, 0}, + {0x157C0, 0}, {0x167C0, 0}, {0x177C0, 0}, {0x187C0, 0}, + {0x108C0, 0}, {0x118C0, 0}, {0x128C0, 0}, {0x138C0, 0}, + {0x148C0, 0}, {0x158C0, 0}, {0x168C0, 0}, {0x178C0, 0}, + {0x188C0, 0}, {0x100C1, 0}, {0x110C1, 0}, {0x120C1, 0}, + {0x130C1, 0}, {0x140C1, 0}, {0x150C1, 0}, {0x160C1, 0}, + {0x170C1, 0}, {0x180C1, 0}, {0x101C1, 0}, {0x111C1, 0}, + {0x121C1, 0}, {0x131C1, 0}, {0x141C1, 0}, {0x151C1, 0}, + {0x161C1, 0}, {0x171C1, 0}, {0x181C1, 0}, {0x102C1, 0}, + {0x112C1, 0}, {0x122C1, 0}, {0x132C1, 0}, {0x142C1, 0}, + {0x152C1, 0}, {0x162C1, 0}, {0x172C1, 0}, {0x182C1, 0}, + {0x103C1, 0}, {0x113C1, 0}, {0x123C1, 0}, {0x133C1, 0}, + {0x143C1, 0}, {0x153C1, 0}, {0x163C1, 0}, {0x173C1, 0}, + {0x183C1, 0}, {0x104C1, 0}, {0x114C1, 0}, {0x124C1, 0}, + {0x134C1, 0}, {0x144C1, 0}, {0x154C1, 0}, {0x164C1, 0}, + {0x174C1, 0}, {0x184C1, 0}, {0x105C1, 0}, {0x115C1, 0}, + {0x125C1, 0}, {0x135C1, 0}, {0x145C1, 0}, {0x155C1, 0}, + {0x165C1, 0}, {0x175C1, 0}, {0x185C1, 0}, {0x106C1, 0}, + {0x116C1, 0}, {0x126C1, 0}, {0x136C1, 0}, {0x146C1, 0}, + {0x156C1, 0}, {0x166C1, 0}, {0x176C1, 0}, {0x186C1, 0}, + {0x107C1, 0}, {0x117C1, 0}, {0x127C1, 0}, {0x137C1, 0}, + {0x147C1, 0}, {0x157C1, 0}, {0x167C1, 0}, {0x177C1, 0}, + {0x187C1, 0}, {0x108C1, 0}, {0x118C1, 0}, {0x128C1, 0}, + {0x138C1, 0}, {0x148C1, 0}, {0x158C1, 0}, {0x168C1, 0}, + {0x178C1, 0}, {0x188C1, 0}, {0x100C2, 0}, {0x110C2, 0}, + {0x120C2, 0}, {0x130C2, 0}, {0x140C2, 0}, {0x150C2, 0}, + {0x160C2, 0}, {0x170C2, 0}, {0x180C2, 0}, {0x101C2, 0}, + {0x111C2, 0}, {0x121C2, 0}, {0x131C2, 0}, {0x141C2, 0}, + {0x151C2, 0}, {0x161C2, 0}, {0x171C2, 0}, {0x181C2, 0}, + {0x102C2, 0}, {0x112C2, 0}, {0x122C2, 0}, {0x132C2, 0}, + {0x142C2, 0}, {0x152C2, 0}, {0x162C2, 0}, {0x172C2, 0}, + {0x182C2, 0}, {0x103C2, 0}, {0x113C2, 0}, {0x123C2, 0}, + {0x133C2, 0}, {0x143C2, 0}, {0x153C2, 0}, {0x163C2, 0}, + {0x173C2, 0}, {0x183C2, 0}, {0x104C2, 0}, {0x114C2, 0}, + {0x124C2, 0}, {0x134C2, 0}, {0x144C2, 0}, {0x154C2, 0}, + {0x164C2, 0}, {0x174C2, 0}, {0x184C2, 0}, {0x105C2, 0}, + {0x115C2, 0}, {0x125C2, 0}, {0x135C2, 0}, {0x145C2, 0}, + {0x155C2, 0}, {0x165C2, 0}, {0x175C2, 0}, {0x185C2, 0}, + {0x106C2, 0}, {0x116C2, 0}, {0x126C2, 0}, {0x136C2, 0}, + {0x146C2, 0}, {0x156C2, 0}, {0x166C2, 0}, {0x176C2, 0}, + {0x186C2, 0}, {0x107C2, 0}, {0x117C2, 0}, {0x127C2, 0}, + {0x137C2, 0}, {0x147C2, 0}, {0x157C2, 0}, {0x167C2, 0}, + {0x177C2, 0}, {0x187C2, 0}, {0x108C2, 0}, {0x118C2, 0}, + {0x128C2, 0}, {0x138C2, 0}, {0x148C2, 0}, {0x158C2, 0}, + {0x168C2, 0}, {0x178C2, 0}, {0x188C2, 0}, {0x100C3, 0}, + {0x110C3, 0}, {0x120C3, 0}, {0x130C3, 0}, {0x140C3, 0}, + {0x150C3, 0}, {0x160C3, 0}, {0x170C3, 0}, {0x180C3, 0}, + {0x101C3, 0}, {0x111C3, 0}, {0x121C3, 0}, {0x131C3, 0}, + {0x141C3, 0}, {0x151C3, 0}, {0x161C3, 0}, {0x171C3, 0}, + {0x181C3, 0}, {0x102C3, 0}, {0x112C3, 0}, {0x122C3, 0}, + {0x132C3, 0}, {0x142C3, 0}, {0x152C3, 0}, {0x162C3, 0}, + {0x172C3, 0}, {0x182C3, 0}, {0x103C3, 0}, {0x113C3, 0}, + {0x123C3, 0}, {0x133C3, 0}, {0x143C3, 0}, {0x153C3, 0}, + {0x163C3, 0}, {0x173C3, 0}, {0x183C3, 0}, {0x104C3, 0}, + {0x114C3, 0}, {0x124C3, 0}, {0x134C3, 0}, {0x144C3, 0}, + {0x154C3, 0}, {0x164C3, 0}, {0x174C3, 0}, {0x184C3, 0}, + {0x105C3, 0}, {0x115C3, 0}, {0x125C3, 0}, {0x135C3, 0}, + {0x145C3, 0}, {0x155C3, 0}, {0x165C3, 0}, {0x175C3, 0}, + {0x185C3, 0}, {0x106C3, 0}, {0x116C3, 0}, {0x126C3, 0}, + {0x136C3, 0}, {0x146C3, 0}, {0x156C3, 0}, {0x166C3, 0}, + {0x176C3, 0}, {0x186C3, 0}, {0x107C3, 0}, {0x117C3, 0}, + {0x127C3, 0}, {0x137C3, 0}, {0x147C3, 0}, {0x157C3, 0}, + {0x167C3, 0}, {0x177C3, 0}, {0x187C3, 0}, {0x108C3, 0}, + {0x118C3, 0}, {0x128C3, 0}, {0x138C3, 0}, {0x148C3, 0}, + {0x158C3, 0}, {0x168C3, 0}, {0x178C3, 0}, {0x188C3, 0}, + {0x10020, 0}, {0x11020, 0}, {0x12020, 0}, {0x13020, 0}, + {0x14020, 0}, {0x15020, 0}, {0x16020, 0}, {0x17020, 0}, + {0x18020, 0}, {0x2007D, 0}, {0x20077, 0} +}; + +/* + *Array to store the PHY 2D Training register addresses + */ +struct phy_training_values training_2D_values[] = { + {0x1008C, 0}, {0x1108C, 0}, {0x1208C, 0}, {0x1308C, 0}, + {0x1408C, 0}, {0x1508C, 0}, {0x1608C, 0}, {0x1708C, 0}, + {0x1808C, 0}, {0x1018C, 0}, {0x1118C, 0}, {0x1218C, 0}, + {0x1318C, 0}, {0x1418C, 0}, {0x1518C, 0}, {0x1618C, 0}, + {0x1718C, 0}, {0x1818C, 0}, {0x10040, 0}, {0x11040, 0}, + {0x12040, 0}, {0x13040, 0}, {0x14040, 0}, {0x15040, 0}, + {0x16040, 0}, {0x17040, 0}, {0x18040, 0}, {0x10140, 0}, + {0x11140, 0}, {0x12140, 0}, {0x13140, 0}, {0x14140, 0}, + {0x15140, 0}, {0x16140, 0}, {0x17140, 0}, {0x18140, 0}, + {0x10240, 0}, {0x11240, 0}, {0x12240, 0}, {0x13240, 0}, + {0x14240, 0}, {0x15240, 0}, {0x16240, 0}, {0x17240, 0}, + {0x18240, 0}, {0x10340, 0}, {0x11340, 0}, {0x12340, 0}, + {0x13340, 0}, {0x14340, 0}, {0x15340, 0}, {0x16340, 0}, + {0x17340, 0}, {0x18340, 0}, {0x10440, 0}, {0x11440, 0}, + {0x12440, 0}, {0x13440, 0}, {0x14440, 0}, {0x15440, 0}, + {0x16440, 0}, {0x17440, 0}, {0x18440, 0}, {0x10540, 0}, + {0x11540, 0}, {0x12540, 0}, {0x13540, 0}, {0x14540, 0}, + {0x15540, 0}, {0x16540, 0}, {0x17540, 0}, {0x18540, 0}, + {0x10640, 0}, {0x11640, 0}, {0x12640, 0}, {0x13640, 0}, + {0x14640, 0}, {0x15640, 0}, {0x16640, 0}, {0x17640, 0}, + {0x18640, 0}, {0x10740, 0}, {0x11740, 0}, {0x12740, 0}, + {0x13740, 0}, {0x14740, 0}, {0x15740, 0}, {0x16740, 0}, + {0x17740, 0}, {0x18740, 0}, {0x10840, 0}, {0x11840, 0}, + {0x12840, 0}, {0x13840, 0}, {0x14840, 0}, {0x15840, 0}, + {0x16840, 0}, {0x17840, 0}, {0x18840, 0}, {0x10030, 0}, + {0x11030, 0}, {0x12030, 0}, {0x13030, 0}, {0x14030, 0}, + {0x15030, 0}, {0x16030, 0}, {0x17030, 0}, {0x18030, 0}, + {0x10130, 0}, {0x11130, 0}, {0x12130, 0}, {0x13130, 0}, + {0x14130, 0}, {0x15130, 0}, {0x16130, 0}, {0x17130, 0}, + {0x18130, 0}, {0x10230, 0}, {0x11230, 0}, {0x12230, 0}, + {0x13230, 0}, {0x14230, 0}, {0x15230, 0}, {0x16230, 0}, + {0x17230, 0}, {0x18230, 0}, {0x10330, 0}, {0x11330, 0}, + {0x12330, 0}, {0x13330, 0}, {0x14330, 0}, {0x15330, 0}, + {0x16330, 0}, {0x17330, 0}, {0x18330, 0}, {0x10430, 0}, + {0x11430, 0}, {0x12430, 0}, {0x13430, 0}, {0x14430, 0}, + {0x15430, 0}, {0x16430, 0}, {0x17430, 0}, {0x18430, 0}, + {0x10530, 0}, {0x11530, 0}, {0x12530, 0}, {0x13530, 0}, + {0x14530, 0}, {0x15530, 0}, {0x16530, 0}, {0x17530, 0}, + {0x18530, 0}, {0x10630, 0}, {0x11630, 0}, {0x12630, 0}, + {0x13630, 0}, {0x14630, 0}, {0x15630, 0}, {0x16630, 0}, + {0x17630, 0}, {0x18630, 0}, {0x10730, 0}, {0x11730, 0}, + {0x12730, 0}, {0x13730, 0}, {0x14730, 0}, {0x15730, 0}, + {0x16730, 0}, {0x17730, 0}, {0x18730, 0}, {0x10830, 0}, + {0x11830, 0}, {0x12830, 0}, {0x13830, 0}, {0x14830, 0}, + {0x15830, 0}, {0x16830, 0}, {0x17830, 0}, {0x18830, 0} +}; + +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h new file mode 100644 index 0000000..b89066a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h @@ -0,0 +1,632 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PIE_H +#define PIE_H + +struct pie { + uint32_t addr; + uint16_t data; +}; + +static const struct pie pie_udimm[] = { + {0x90000, 0x10}, + {0x90001, 0x400}, + {0x90002, 0x10e}, + {0x90003, 0x0}, + {0x90004, 0x0}, + {0x90005, 0x8}, + {0x90029, 0xb}, + {0x9002a, 0x480}, + {0x9002b, 0x109}, + {0x9002c, 0x8}, + {0x9002d, 0x448}, + {0x9002e, 0x139}, + {0x9002f, 0x8}, + {0x90030, 0x478}, + {0x90031, 0x109}, + {0x90032, 0x2}, + {0x90033, 0x10}, + {0x90034, 0x139}, + {0x90035, 0xb}, + {0x90036, 0x7c0}, + {0x90037, 0x139}, + {0x90038, 0x44}, + {0x90039, 0x633}, + {0x9003a, 0x159}, + {0x9003b, 0x14f}, + {0x9003c, 0x630}, + {0x9003d, 0x159}, + {0x9003e, 0x47}, + {0x9003f, 0x633}, + {0x90040, 0x149}, + {0x90041, 0x4f}, + {0x90042, 0x633}, + {0x90043, 0x179}, + {0x90044, 0x8}, + {0x90045, 0xe0}, + {0x90046, 0x109}, + {0x90047, 0x0}, + {0x90048, 0x7c8}, + {0x90049, 0x109}, + {0x9004a, 0x0}, + {0x9004b, 0x1}, + {0x9004c, 0x8}, + {0x9004d, 0x0}, + {0x9004e, 0x45a}, + {0x9004f, 0x9}, + {0x90050, 0x0}, + {0x90051, 0x448}, + {0x90052, 0x109}, + {0x90053, 0x40}, + {0x90054, 0x633}, + {0x90055, 0x179}, + {0x90056, 0x1}, + {0x90057, 0x618}, + {0x90058, 0x109}, + {0x90059, 0x40c0}, + {0x9005a, 0x633}, + {0x9005b, 0x149}, + {0x9005c, 0x8}, + {0x9005d, 0x4}, + {0x9005e, 0x48}, + {0x9005f, 0x4040}, + {0x90060, 0x633}, + {0x90061, 0x149}, + {0x90062, 0x0}, + {0x90063, 0x4}, + {0x90064, 0x48}, + {0x90065, 0x40}, + {0x90066, 0x633}, + {0x90067, 0x149}, + {0x90068, 0x10}, + {0x90069, 0x4}, + {0x9006a, 0x18}, + {0x9006b, 0x0}, + {0x9006c, 0x4}, + {0x9006d, 0x78}, + {0x9006e, 0x549}, + {0x9006f, 0x633}, + {0x90070, 0x159}, + {0x90071, 0xd49}, + {0x90072, 0x633}, + {0x90073, 0x159}, + {0x90074, 0x94a}, + {0x90075, 0x633}, + {0x90076, 0x159}, + {0x90077, 0x441}, + {0x90078, 0x633}, + {0x90079, 0x149}, + {0x9007a, 0x42}, + {0x9007b, 0x633}, + {0x9007c, 0x149}, + {0x9007d, 0x1}, + {0x9007e, 0x633}, + {0x9007f, 0x149}, + {0x90080, 0x0}, + {0x90081, 0xe0}, + {0x90082, 0x109}, + {0x90083, 0xa}, + {0x90084, 0x10}, + {0x90085, 0x109}, + {0x90086, 0x9}, + {0x90087, 0x3c0}, + {0x90088, 0x149}, + {0x90089, 0x9}, + {0x9008a, 0x3c0}, + {0x9008b, 0x159}, + {0x9008c, 0x18}, + {0x9008d, 0x10}, + {0x9008e, 0x109}, + {0x9008f, 0x0}, + {0x90090, 0x3c0}, + {0x90091, 0x109}, + {0x90092, 0x18}, + {0x90093, 0x4}, + {0x90094, 0x48}, + {0x90095, 0x18}, + {0x90096, 0x4}, + {0x90097, 0x58}, + {0x90098, 0xb}, + {0x90099, 0x10}, + {0x9009a, 0x109}, + {0x9009b, 0x1}, + {0x9009c, 0x10}, + {0x9009d, 0x109}, + {0x9009e, 0x5}, + {0x9009f, 0x7c0}, + {0x900a0, 0x109}, + {0x900a1, 0x0}, + {0x900a2, 0x8140}, + {0x900a3, 0x10c}, + {0x900a4, 0x10}, + {0x900a5, 0x8138}, + {0x900a6, 0x10c}, + {0x900a7, 0x8}, + {0x900a8, 0x7c8}, + {0x900a9, 0x101}, + {0x900aa, 0x8}, + {0x900ab, 0x448}, + {0x900ac, 0x109}, + {0x900ad, 0xf}, + {0x900ae, 0x7c0}, + {0x900af, 0x109}, + {0x900b0, 0x47}, + {0x900b1, 0x630}, + {0x900b2, 0x109}, + {0x900b3, 0x8}, + {0x900b4, 0x618}, + {0x900b5, 0x109}, + {0x900b6, 0x8}, + {0x900b7, 0xe0}, + {0x900b8, 0x109}, + {0x900b9, 0x0}, + {0x900ba, 0x7c8}, + {0x900bb, 0x109}, + {0x900bc, 0x8}, + {0x900bd, 0x8140}, + {0x900be, 0x10c}, + {0x900bf, 0x0}, + {0x900c0, 0x478}, + {0x900c1, 0x109}, + {0x900c2, 0x0}, + {0x900c3, 0x1}, + {0x900c4, 0x8}, + {0x900c5, 0x8}, + {0x900c6, 0x4}, + {0x900c7, 0x8}, + {0x900c8, 0x8}, + {0x900c9, 0x7c8}, + {0x900ca, 0x101}, + {0x90006, 0x0}, + {0x90007, 0x0}, + {0x90008, 0x8}, + {0x90009, 0x0}, + {0x9000a, 0x0}, + {0x9000b, 0x0}, + {0xd00e7, 0x400}, + {0x90017, 0x0}, + {0x90026, 0x2b}, +}; + +static const struct pie pie_rdimm[] = { + {0x90000, 0x10}, + {0x90001, 0x400}, + {0x90002, 0x10e}, + {0x90003, 0x0}, + {0x90004, 0x0}, + {0x90005, 0x8}, + {0x40000, 0x10}, + {0x40020, 0x0}, + {0x40040, 0x0}, + {0x40060, 0x0}, + {0x40001, 0x70a}, + {0x40021, 0x7005}, + {0x40041, 0x0}, + {0x40061, 0x2001}, + {0x40002, 0x4010}, + {0x40022, 0x0}, + {0x40042, 0x0}, + {0x40062, 0x0}, + {0x90029, 0x10}, + {0x9002a, 0x400}, + {0x9002b, 0x16e}, + {0x9002c, 0x8}, + {0x9002d, 0x370}, + {0x9002e, 0x169}, + {0x9002f, 0x8}, + {0x90030, 0x7aa}, + {0x90031, 0x6a}, + {0x90032, 0x10}, + {0x90033, 0x7b2}, + {0x90034, 0x6a}, + {0x90035, 0x0}, + {0x90036, 0x48a}, + {0x90037, 0x6a}, + {0x90038, 0x9}, + {0x90039, 0x480}, + {0x9003a, 0x16a}, + {0x9003b, 0x4}, + {0x9003c, 0x790}, + {0x9003d, 0x16a}, + {0x9003e, 0xc}, + {0x9003f, 0x408}, + {0x90040, 0x169}, + {0x90041, 0xa}, + {0x90042, 0x0}, + {0x90043, 0x68}, + {0x90044, 0x0}, + {0x90045, 0x408}, + {0x90046, 0x169}, + {0x90047, 0x1}, + {0x90048, 0x480}, + {0x90049, 0x16a}, + {0x9004a, 0xb}, + {0x9004b, 0x480}, + {0x9004c, 0x109}, + {0x9004d, 0x8}, + {0x9004e, 0x448}, + {0x9004f, 0x139}, + {0x90050, 0x78}, + {0x90051, 0x8}, + {0x90052, 0x139}, + {0x90053, 0x2}, + {0x90054, 0x10}, + {0x90055, 0x139}, + {0x90056, 0xb}, + {0x90057, 0x7c0}, + {0x90058, 0x139}, + {0x90059, 0x44}, + {0x9005a, 0x633}, + {0x9005b, 0x159}, + {0x9005c, 0x14f}, + {0x9005d, 0x630}, + {0x9005e, 0x159}, + {0x9005f, 0x47}, + {0x90060, 0x633}, + {0x90061, 0x149}, + {0x90062, 0x4f}, + {0x90063, 0x633}, + {0x90064, 0x179}, + {0x90065, 0x8}, + {0x90066, 0xe0}, + {0x90067, 0x109}, + {0x90068, 0x0}, + {0x90069, 0x7c8}, + {0x9006a, 0x109}, + {0x9006b, 0x0}, + {0x9006c, 0x1}, + {0x9006d, 0x8}, + {0x9006e, 0x0}, + {0x9006f, 0x45a}, + {0x90070, 0x9}, + {0x90071, 0x0}, + {0x90072, 0x448}, + {0x90073, 0x109}, + {0x90074, 0x40}, + {0x90075, 0x633}, + {0x90076, 0x179}, + {0x90077, 0x1}, + {0x90078, 0x618}, + {0x90079, 0x109}, + {0x9007a, 0x40c0}, + {0x9007b, 0x633}, + {0x9007c, 0x149}, + {0x9007d, 0x8}, + {0x9007e, 0x4}, + {0x9007f, 0x48}, + {0x90080, 0x4040}, + {0x90081, 0x633}, + {0x90082, 0x149}, + {0x90083, 0x0}, + {0x90084, 0x4}, + {0x90085, 0x48}, + {0x90086, 0x40}, + {0x90087, 0x633}, + {0x90088, 0x149}, + {0x90089, 0x10}, + {0x9008a, 0x4}, + {0x9008b, 0x18}, + {0x9008c, 0x0}, + {0x9008d, 0x4}, + {0x9008e, 0x78}, + {0x9008f, 0x549}, + {0x90090, 0x633}, + {0x90091, 0x159}, + {0x90092, 0xd49}, + {0x90093, 0x633}, + {0x90094, 0x159}, + {0x90095, 0x94a}, + {0x90096, 0x633}, + {0x90097, 0x159}, + {0x90098, 0x441}, + {0x90099, 0x633}, + {0x9009a, 0x149}, + {0x9009b, 0x42}, + {0x9009c, 0x633}, + {0x9009d, 0x149}, + {0x9009e, 0x1}, + {0x9009f, 0x633}, + {0x900a0, 0x149}, + {0x900a1, 0x0}, + {0x900a2, 0xe0}, + {0x900a3, 0x109}, + {0x900a4, 0xa}, + {0x900a5, 0x10}, + {0x900a6, 0x109}, + {0x900a7, 0x9}, + {0x900a8, 0x3c0}, + {0x900a9, 0x149}, + {0x900aa, 0x9}, + {0x900ab, 0x3c0}, + {0x900ac, 0x159}, + {0x900ad, 0x18}, + {0x900ae, 0x10}, + {0x900af, 0x109}, + {0x900b0, 0x0}, + {0x900b1, 0x3c0}, + {0x900b2, 0x109}, + {0x900b3, 0x18}, + {0x900b4, 0x4}, + {0x900b5, 0x48}, + {0x900b6, 0x18}, + {0x900b7, 0x4}, + {0x900b8, 0x58}, + {0x900b9, 0xb}, + {0x900ba, 0x10}, + {0x900bb, 0x109}, + {0x900bc, 0x1}, + {0x900bd, 0x10}, + {0x900be, 0x109}, + {0x900bf, 0x5}, + {0x900c0, 0x7c0}, + {0x900c1, 0x109}, + {0x900c2, 0x3}, + {0x900c3, 0x370}, + {0x900c4, 0x169}, + {0x900c5, 0x3}, + {0x900c6, 0x8}, + {0x900c7, 0x139}, + {0x900c8, 0x0}, + {0x900c9, 0x400}, + {0x900ca, 0x16e}, + {0x900cb, 0x8}, + {0x900cc, 0x478}, + {0x900cd, 0x109}, + {0x900ce, 0x0}, + {0x900cf, 0x8140}, + {0x900d0, 0x10c}, + {0x900d1, 0x10}, + {0x900d2, 0x8138}, + {0x900d3, 0x10c}, + {0x900d4, 0x8}, + {0x900d5, 0x7c8}, + {0x900d6, 0x101}, + {0x900d7, 0x7a}, + {0x900d8, 0x8}, + {0x900d9, 0x109}, + {0x900da, 0x8}, + {0x900db, 0x448}, + {0x900dc, 0x109}, + {0x900dd, 0xf}, + {0x900de, 0x7c0}, + {0x900df, 0x109}, + {0x900e0, 0x47}, + {0x900e1, 0x630}, + {0x900e2, 0x109}, + {0x900e3, 0x8}, + {0x900e4, 0x618}, + {0x900e5, 0x109}, + {0x900e6, 0x8}, + {0x900e7, 0xe0}, + {0x900e8, 0x109}, + {0x900e9, 0x0}, + {0x900ea, 0x8}, + {0x900eb, 0x109}, + {0x900ec, 0x0}, + {0x900ed, 0x7c8}, + {0x900ee, 0x109}, + {0x900ef, 0x8}, + {0x900f0, 0x8140}, + {0x900f1, 0x10c}, + {0x900f2, 0x0}, + {0x900f3, 0x478}, + {0x900f4, 0x109}, + {0x900f5, 0x0}, + {0x900f6, 0x1}, + {0x900f7, 0x8}, + {0x900f8, 0x8}, + {0x900f9, 0x4}, + {0x900fa, 0x8}, + {0x900fb, 0x8}, + {0x900fc, 0x7c8}, + {0x900fd, 0x101}, + {0x90006, 0x0}, + {0x90007, 0x0}, + {0x90008, 0x8}, + {0x90009, 0x0}, + {0x9000a, 0x0}, + {0x9000b, 0x0}, + {0xd00e7, 0x400}, + {0x90017, 0x0}, + {0x90026, 0x3a}, +}; + +static const struct pie pie_lrdimm[] = { + {0x90000, 0x10}, + {0x90001, 0x400}, + {0x90002, 0x10e}, + {0x90003, 0x0}, + {0x90004, 0x0}, + {0x90005, 0x8}, + {0x90029, 0xb}, + {0x9002a, 0x480}, + {0x9002b, 0x109}, + {0x9002c, 0x8}, + {0x9002d, 0x448}, + {0x9002e, 0x139}, + {0x9002f, 0x78}, + {0x90030, 0x8}, + {0x90031, 0x139}, + {0x90032, 0x2}, + {0x90033, 0x10}, + {0x90034, 0x139}, + {0x90035, 0xb}, + {0x90036, 0x7c0}, + {0x90037, 0x139}, + {0x90038, 0x44}, + {0x90039, 0x633}, + {0x9003a, 0x159}, + {0x9003b, 0x14f}, + {0x9003c, 0x630}, + {0x9003d, 0x159}, + {0x9003e, 0x47}, + {0x9003f, 0x633}, + {0x90040, 0x149}, + {0x90041, 0x4f}, + {0x90042, 0x633}, + {0x90043, 0x179}, + {0x90044, 0x8}, + {0x90045, 0xe0}, + {0x90046, 0x109}, + {0x90047, 0x0}, + {0x90048, 0x7c8}, + {0x90049, 0x109}, + {0x9004a, 0x0}, + {0x9004b, 0x1}, + {0x9004c, 0x8}, + {0x9004d, 0x0}, + {0x9004e, 0x45a}, + {0x9004f, 0x9}, + {0x90050, 0x0}, + {0x90051, 0x448}, + {0x90052, 0x109}, + {0x90053, 0x40}, + {0x90054, 0x633}, + {0x90055, 0x179}, + {0x90056, 0x1}, + {0x90057, 0x618}, + {0x90058, 0x109}, + {0x90059, 0x40c0}, + {0x9005a, 0x633}, + {0x9005b, 0x149}, + {0x9005c, 0x8}, + {0x9005d, 0x4}, + {0x9005e, 0x48}, + {0x9005f, 0x4040}, + {0x90060, 0x633}, + {0x90061, 0x149}, + {0x90062, 0x0}, + {0x90063, 0x4}, + {0x90064, 0x48}, + {0x90065, 0x40}, + {0x90066, 0x633}, + {0x90067, 0x149}, + {0x90068, 0x10}, + {0x90069, 0x4}, + {0x9006a, 0x18}, + {0x9006b, 0x0}, + {0x9006c, 0x4}, + {0x9006d, 0x78}, + {0x9006e, 0x549}, + {0x9006f, 0x633}, + {0x90070, 0x159}, + {0x90071, 0xd49}, + {0x90072, 0x633}, + {0x90073, 0x159}, + {0x90074, 0x94a}, + {0x90075, 0x633}, + {0x90076, 0x159}, + {0x90077, 0x441}, + {0x90078, 0x633}, + {0x90079, 0x149}, + {0x9007a, 0x42}, + {0x9007b, 0x633}, + {0x9007c, 0x149}, + {0x9007d, 0x1}, + {0x9007e, 0x633}, + {0x9007f, 0x149}, + {0x90080, 0x0}, + {0x90081, 0xe0}, + {0x90082, 0x109}, + {0x90083, 0xa}, + {0x90084, 0x10}, + {0x90085, 0x109}, + {0x90086, 0x9}, + {0x90087, 0x3c0}, + {0x90088, 0x149}, + {0x90089, 0x9}, + {0x9008a, 0x3c0}, + {0x9008b, 0x159}, + {0x9008c, 0x18}, + {0x9008d, 0x10}, + {0x9008e, 0x109}, + {0x9008f, 0x0}, + {0x90090, 0x3c0}, + {0x90091, 0x109}, + {0x90092, 0x18}, + {0x90093, 0x4}, + {0x90094, 0x48}, + {0x90095, 0x18}, + {0x90096, 0x4}, + {0x90097, 0x58}, + {0x90098, 0xb}, + {0x90099, 0x10}, + {0x9009a, 0x109}, + {0x9009b, 0x1}, + {0x9009c, 0x10}, + {0x9009d, 0x109}, + {0x9009e, 0x5}, + {0x9009f, 0x7c0}, + {0x900a0, 0x109}, + {0x900a1, 0x3}, + {0x900a2, 0x8}, + {0x900a3, 0x139}, + {0x900a4, 0x0}, + {0x900a5, 0x400}, + {0x900a6, 0x16e}, + {0x900a7, 0x8}, + {0x900a8, 0x478}, + {0x900a9, 0x109}, + {0x900aa, 0x0}, + {0x900ab, 0x8140}, + {0x900ac, 0x10c}, + {0x900ad, 0x10}, + {0x900ae, 0x8138}, + {0x900af, 0x10c}, + {0x900b0, 0x8}, + {0x900b1, 0x7c8}, + {0x900b2, 0x101}, + {0x900b3, 0x7a}, + {0x900b4, 0x8}, + {0x900b5, 0x109}, + {0x900b6, 0x8}, + {0x900b7, 0x448}, + {0x900b8, 0x109}, + {0x900b9, 0xf}, + {0x900ba, 0x7c0}, + {0x900bb, 0x109}, + {0x900bc, 0x47}, + {0x900bd, 0x630}, + {0x900be, 0x109}, + {0x900bf, 0x8}, + {0x900c0, 0x618}, + {0x900c1, 0x109}, + {0x900c2, 0x8}, + {0x900c3, 0xe0}, + {0x900c4, 0x109}, + {0x900c5, 0x0}, + {0x900c6, 0x8}, + {0x900c7, 0x109}, + {0x900c8, 0x0}, + {0x900c9, 0x7c8}, + {0x900ca, 0x109}, + {0x900cb, 0x8}, + {0x900cc, 0x8140}, + {0x900cd, 0x10c}, + {0x900ce, 0x0}, + {0x900cf, 0x478}, + {0x900d0, 0x109}, + {0x900d1, 0x0}, + {0x900d2, 0x1}, + {0x900d3, 0x8}, + {0x900d4, 0x8}, + {0x900d5, 0x4}, + {0x900d6, 0x8}, + {0x900d7, 0x8}, + {0x900d8, 0x7c8}, + {0x900d9, 0x101}, + {0x90006, 0x0}, + {0x90007, 0x0}, + {0x90008, 0x8}, + {0x90009, 0x0}, + {0x9000a, 0x0}, + {0x9000b, 0x0}, + {0xd00e7, 0x400}, + {0x90017, 0x0}, + {0x90026, 0x2e}, +}; +#endif diff --git a/arm-trusted-firmware/drivers/nxp/drivers.mk b/arm-trusted-firmware/drivers/nxp/drivers.mk new file mode 100644 index 0000000..d77e985 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/drivers.mk @@ -0,0 +1,99 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +############################################################################### + + +PLAT_DRIVERS_PATH := drivers/nxp +PLAT_DRIVERS_INCLUDE_PATH := include/drivers/nxp + +ifeq (${SMMU_NEEDED},yes) +PLAT_INCLUDES += -Iinclude/drivers/nxp/smmu/ +endif + +ifeq (${DCFG_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/dcfg/dcfg.mk +endif + +ifeq (${CSU_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/csu/csu.mk +endif + +ifeq (${TIMER_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/timer/timer.mk +endif + +ifeq (${INTERCONNECT_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/interconnect/interconnect.mk +endif + +ifeq (${GIC_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/gic/gic.mk +endif + +ifeq (${SD_MMC_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/sd/sd_mmc.mk +endif + +ifeq (${CONSOLE_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/console/console.mk +endif + +ifeq (${SFP_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/sfp/sfp.mk +endif + +ifeq (${XSPI_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/flexspi/nor/flexspi_nor.mk +endif + +ifeq (${QSPI_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/qspi/qspi.mk +endif + +ifeq (${SNVS_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/sec_mon/sec_mon.mk +endif + +ifeq ($(I2C_NEEDED),yes) +$(eval $(call add_define, I2C_INIT)) +include $(PLAT_DRIVERS_PATH)/i2c/i2c.mk +endif + +ifeq ($(DDR_DRIVER_NEEDED),yes) +$(eval $(call add_define, DDR_INIT)) +# define DDR_CNTRL_SOURCES +ifeq ($(DDRCNTLR),MMDC) +include $(PLAT_DRIVERS_PATH)/ddr/fsl-mmdc/ddr.mk +else +include $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddr.mk +endif # DDR_CNTRL_SOURCES +endif + +ifeq (${PMU_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/pmu/pmu.mk +endif + +ifeq (${CRYPTO_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/crypto/caam/caam.mk +endif + +ifeq (${TZASC_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/tzc/tzc.mk +endif + +ifeq (${GPIO_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/gpio/gpio.mk +endif + +ifeq (${IFC_NOR_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/ifc/nor/ifc_nor.mk +endif + +ifeq (${IFC_NAND_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/ifc/nand/ifc_nand.mk +endif diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c new file mode 100644 index 0000000..748228d --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c @@ -0,0 +1,25 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include + +int flexspi_nor_io_setup(uintptr_t nxp_flexspi_flash_addr, + size_t nxp_flexspi_flash_size, uint32_t fspi_base_reg_addr) +{ + int ret = 0; + + ret = fspi_init(fspi_base_reg_addr, nxp_flexspi_flash_addr); + /* Adding NOR Memory Map in XLAT Table */ + mmap_add_region(nxp_flexspi_flash_addr, nxp_flexspi_flash_addr, + nxp_flexspi_flash_size, MT_MEMORY | MT_RW); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h new file mode 100644 index 0000000..61fc236 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h @@ -0,0 +1,15 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FLEXSPI_NOR_H +#define FLEXSPI_NOR_H + +int flexspi_nor_io_setup(uintptr_t nxp_flexspi_flash_addr, + size_t nxp_flexspi_flash_size, + uint32_t fspi_base_reg_addr); + +#endif /* FLEXSPI_NOR_H */ diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.mk b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.mk new file mode 100644 index 0000000..6d9eebb --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.mk @@ -0,0 +1,35 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${XSPI_NOR},) +XSPI_NOR := 1 + +FLEXSPI_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/flexspi/nor + +PLAT_XSPI_INCLUDES += -I$(FLEXSPI_DRIVERS_PATH) + +XSPI_BOOT_SOURCES += $(FLEXSPI_DRIVERS_PATH)/flexspi_nor.c \ + ${FLEXSPI_DRIVERS_PATH}/fspi.c +ifeq ($(DEBUG),1) +XSPI_BOOT_SOURCES += ${FLEXSPI_DRIVERS_PATH}/test_fspi.c +endif + +PLAT_XSPI_INCLUDES += -Iinclude/drivers/nxp/flexspi + +PLAT_INCLUDES += ${PLAT_XSPI_INCLUDES} + +ifeq (${BL_COMM_XSPI_NEEDED},yes) +BL_COMMON_SOURCES += ${XSPI_BOOT_SOURCES} +else +ifeq (${BL2_XSPI_NEEDED},yes) +BL2_SOURCES += ${XSPI_BOOT_SOURCES} +endif +ifeq (${BL31_XSPI_NEEDED},yes) +BL31_SOURCES += ${XSPI_BOOT_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c b/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c new file mode 100644 index 0000000..7c919b8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c @@ -0,0 +1,853 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * NXP FlexSpi Controller Driver. + * Copyright 2021 NXP + * + */ +#include +#include +#include +#include + +#include +#include +#include "fspi.h" +#include +#include + +#ifdef DEBUG_FLEXSPI +#define PR printf("In [%s][%d]\n", __func__, __LINE__) +#define PRA(a, b) printf("In [%s][%d] %s="a"\n", __func__, __LINE__, #b, b) +#else +#define PR +#define PRA(a, b) +#endif + +/* + * This errata is valid for all NXP SoC. + */ +#define ERRATA_FLASH_A050272 1 + +static uintptr_t fspi_base_reg_addr; +static uintptr_t fspi_flash_base_addr; + +static void fspi_RDSR(uint32_t *, const void *, uint32_t); + +static void fspi_writel(uint32_t x_addr, uint32_t x_val) +{ + fspi_out32((uint32_t *)(fspi_base_reg_addr + x_addr), + (uint32_t) x_val); +} + +static uint32_t fspi_readl(uint32_t x_addr) +{ + return fspi_in32((uint32_t *)(fspi_base_reg_addr + x_addr)); +} + +static void fspi_MDIS(uint8_t x_disable) +{ + uint32_t ui_reg; + + ui_reg = fspi_readl(FSPI_MCR0); + if (x_disable != 0U) { + ui_reg |= FSPI_MCR0_MDIS; + } else { + ui_reg &= (uint32_t) (~FSPI_MCR0_MDIS); + } + + fspi_writel(FSPI_MCR0, ui_reg); +} + +static void fspi_lock_LUT(void) +{ + fspi_writel(FSPI_LUTKEY, FSPI_LUTKEY_VALUE); + VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); + fspi_writel(FSPI_LCKCR, FSPI_LCKER_LOCK); + VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); +} + +static void fspi_unlock_LUT(void) +{ + fspi_writel(FSPI_LUTKEY, FSPI_LUTKEY_VALUE); + VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); + fspi_writel(FSPI_LCKCR, FSPI_LCKER_UNLOCK); + VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); +} + +static void fspi_op_setup(uint32_t fspi_op_seq_id, bool ignore_flash_sz) +{ + uint32_t x_addr, x_instr0 = 0, x_instr1 = 0, x_instr2 = 0; + uint32_t cmd_id1, cmd_id2; + + VERBOSE("In func %s\n", __func__); + + switch (fspi_op_seq_id) { + case FSPI_READ_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_READ; + cmd_id2 = FSPI_NOR_CMD_READ_4B; + x_instr2 = FSPI_INSTR_OPRND0(0) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE0(FSPI_LUT_READ); + break; + case FSPI_FASTREAD_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_FASTREAD; + cmd_id2 = FSPI_NOR_CMD_FASTREAD_4B; + x_instr2 = FSPI_INSTR_OPRND0(8) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE0(FSPI_DUMMY_SDR) + | FSPI_INSTR_OPRND1(0) + | FSPI_INSTR_PAD1(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE1(FSPI_LUT_READ); + break; + case FSPI_WRITE_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_PP; + cmd_id2 = FSPI_NOR_CMD_PP_4B; + x_instr2 = FSPI_INSTR_OPRND0(0) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE0(FSPI_LUT_WRITE); + break; + case FSPI_WREN_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_WREN; + cmd_id2 = FSPI_NOR_CMD_WREN; + break; + case FSPI_SE_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_SE_64K; + cmd_id2 = FSPI_NOR_CMD_SE_64K_4B; + break; + case FSPI_4K_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_SE_4K; + cmd_id2 = FSPI_NOR_CMD_SE_4K_4B; + break; + case FSPI_BE_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_BE; + cmd_id2 = FSPI_NOR_CMD_BE; + break; + case FSPI_RDSR_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_RDSR; + cmd_id2 = FSPI_NOR_CMD_RDSR; + break; + } + + x_addr = FSPI_LUTREG_OFFSET + (uint32_t)(0x10 * fspi_op_seq_id); + if ((F_FLASH_SIZE_BYTES <= SZ_16M_BYTES) || (ignore_flash_sz)) { + x_instr0 = FSPI_INSTR_OPRND0(cmd_id1); + x_instr1 = FSPI_INSTR_OPRND1(FSPI_LUT_ADDR24BIT); + VERBOSE("CMD_ID = %x offset = 0x%x\n", cmd_id1, x_addr); + } else { + x_instr0 = FSPI_INSTR_OPRND0(cmd_id2); + x_instr1 = FSPI_INSTR_OPRND1(FSPI_LUT_ADDR32BIT); + VERBOSE("CMD_ID = %x offset = 0x%x\n", cmd_id2, x_addr); + } + x_instr0 |= FSPI_INSTR_PAD0(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE0(FSPI_LUT_CMD); + + x_instr1 |= FSPI_INSTR_PAD1(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE1(FSPI_LUT_ADDR); + + if (fspi_op_seq_id == FSPI_RDSR_SEQ_ID) { + x_instr0 |= FSPI_INSTR_OPRND1(1) | FSPI_INSTR_PAD1(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE1(FSPI_LUT_READ); + } else if ((fspi_op_seq_id != FSPI_BE_SEQ_ID) + && (fspi_op_seq_id != FSPI_WREN_SEQ_ID)) { + x_instr0 |= x_instr1; + } + + fspi_writel((x_addr), x_instr0); + fspi_writel((x_addr + U(0x4)), x_instr2); + fspi_writel((x_addr + U(0x8)), (uint32_t) 0x0); /* STOP command */ + fspi_writel((x_addr + U(0xc)), (uint32_t) 0x0); /* STOP command */ +} + +static void fspi_setup_LUT(void) +{ + VERBOSE("In func %s\n", __func__); + fspi_unlock_LUT(); + + /* LUT Setup for READ Command 3-Byte low Frequency */ + fspi_op_setup(FSPI_READ_SEQ_ID, false); + + /* LUT Setup for FAST READ Command 3-Byte/4-Byte high Frequency */ + fspi_op_setup(FSPI_FASTREAD_SEQ_ID, false); + + /* LUT Setup for Page Program */ + fspi_op_setup(FSPI_WRITE_SEQ_ID, false); + + /* LUT Setup for WREN */ + fspi_op_setup(FSPI_WREN_SEQ_ID, true); + + /* LUT Setup for Sector_Erase */ + fspi_op_setup(FSPI_SE_SEQ_ID, false); + + /* LUT Setup for Sub Sector 4K Erase */ + fspi_op_setup(FSPI_4K_SEQ_ID, false); + + /* LUT Setup for Bulk_Erase */ + fspi_op_setup(FSPI_BE_SEQ_ID, true); + + /* Read Status */ + fspi_op_setup(FSPI_RDSR_SEQ_ID, true); + + fspi_lock_LUT(); +} + +static inline void fspi_ahb_invalidate(void) +{ + uint32_t reg; + + VERBOSE("In func %s %d\n", __func__, __LINE__); + reg = fspi_readl(FSPI_MCR0); + reg |= FSPI_MCR0_SWRST; + fspi_writel(FSPI_MCR0, reg); + while ((fspi_readl(FSPI_MCR0) & FSPI_MCR0_SWRST) != 0) + ; /* FSPI_MCR0_SWRESET_MASK */ + VERBOSE("In func %s %d\n", __func__, __LINE__); +} + +#if defined(CONFIG_FSPI_AHB) +static void fspi_init_ahb(void) +{ + uint32_t i, x_flash_cr2, seq_id; + + x_flash_cr2 = 0; + /* Reset AHB RX buffer CR configuration */ + for (i = 0; i < 8; i++) { + fspi_writel((FSPI_AHBRX_BUF0CR0 + 4 * i), 0U); + } + + /* Set ADATSZ with the maximum AHB buffer size */ + fspi_writel(FSPI_AHBRX_BUF7CR0, + ((uint32_t) ((FSPI_RX_MAX_AHBBUF_SIZE / 8U) | + FSPI_AHBRXBUF0CR7_PREF))); + + /* Known limitation handling: prefetch and + * no start address alignment.*/ + fspi_writel(FSPI_AHBCR, FSPI_AHBCR_PREF_EN); + INFO("xAhbcr=0x%x\n", fspi_readl(FSPI_AHBCR)); + + // Setup AHB READ sequenceID for all flashes. + x_flash_cr2 = fspi_readl(FSPI_FLSHA1CR2); + INFO("x_flash_cr2=0x%x\n", x_flash_cr2); + + seq_id = CONFIG_FSPI_FASTREAD ? + FSPI_FASTREAD_SEQ_ID : FSPI_READ_SEQ_ID; + x_flash_cr2 |= ((seq_id << FSPI_FLSHXCR2_ARDSEQI_SHIFT) & 0x1f); + + INFO("x_flash_cr2=0x%x\n", x_flash_cr2); + + fspi_writel(FSPI_FLSHA1CR2, x_flash_cr2); + x_flash_cr2 = fspi_readl(FSPI_FLSHA1CR2); + INFO("x_flash_cr2=0x%x\n", x_flash_cr2); +} +#endif + +int xspi_read(uint32_t pc_rx_addr, uint32_t *pc_rx_buf, uint32_t x_size_bytes) +{ + if (x_size_bytes == 0) { + ERROR("Zero length reads are not allowed\n"); + return XSPI_READ_FAIL; + } + +#if defined(CONFIG_FSPI_AHB) + return xspi_ahb_read(pc_rx_addr, pc_rx_buf, x_size_bytes); +#else + return xspi_ip_read(pc_rx_addr, pc_rx_buf, x_size_bytes); +#endif +} +#if defined(CONFIG_FSPI_AHB) +int xspi_ahb_read(uint32_t pc_rx_addr, uint32_t *pc_rx_buf, uint32_t x_size_bytes) +{ + VERBOSE("In func %s 0x%x\n", __func__, (pc_rx_addr)); + + if (F_FLASH_SIZE_BYTES <= SZ_16M_BYTES) { + pc_rx_addr = ((uint32_t)(pcRxAddr & MASK_24BIT_ADDRESS)); + } else { + pc_rx_addr = ((uint32_t)(pcRxAddr & MASK_32BIT_ADDRESS)); + } + + pc_rx_addr = ((uint32_t)(pcRxAddr + fspi_flash_base_addr)); + + if (((pc_rx_addr % 4) != 0) || (((uintptr_t)pc_rx_buf % 4) != 0)) { + WARN("%s: unaligned Start Address src=%ld dst=0x%p\n", + __func__, (pc_rx_addr - fspi_flash_base_addr), pc_rx_buf); + } + + /* Directly copy from AHB Buffer */ + memcpy(pc_rx_buf, (void *)(uintptr_t)pc_rx_addr, x_size_bytes); + + fspi_ahb_invalidate(); + return XSPI_SUCCESS; +} +#endif + +int xspi_ip_read(uint32_t pc_rx_addr, uint32_t *pv_rx_buf, uint32_t ui_len) +{ + + uint32_t i = 0U, j = 0U, x_rem = 0U; + uint32_t x_iteration = 0U, x_size_rx = 0U, x_size_wm, temp_size; + uint32_t data = 0U; + uint32_t x_len_bytes; + uint32_t x_addr, sts0, intr, seq_id; + + x_addr = (uint32_t) pc_rx_addr; + x_len_bytes = ui_len; + + /* Watermark level : 8 bytes. (BY DEFAULT) */ + x_size_wm = 8U; + + /* Clear RX Watermark interrupt in INT register, if any existing. */ + fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA); + PRA("0x%x", fspi_readl(FSPI_INTR)); + /* Invalid the RXFIFO, to run next IP Command */ + /* Clears data entries in IP Rx FIFOs, Also reset R/W pointers */ + fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); + fspi_writel(FSPI_INTR, FSPI_INTEN_IPCMDDONE); + + while (x_len_bytes) { + + /* FlexSPI can store no more than FSPI_RX_IPBUF_SIZE */ + x_size_rx = (x_len_bytes > FSPI_RX_IPBUF_SIZE) ? + FSPI_RX_IPBUF_SIZE : x_len_bytes; + + /* IP Control Register0 - SF Address to be read */ + fspi_writel(FSPI_IPCR0, x_addr); + PRA("0x%x", fspi_readl(FSPI_IPCR0)); + /* IP Control Register1 - SEQID_READ operation, Size */ + + seq_id = CONFIG_FSPI_FASTREAD ? + FSPI_FASTREAD_SEQ_ID : FSPI_READ_SEQ_ID; + + fspi_writel(FSPI_IPCR1, + (uint32_t)(seq_id << FSPI_IPCR1_ISEQID_SHIFT) | + (uint16_t) x_size_rx); + + PRA("0x%x", fspi_readl(FSPI_IPCR1)); + + do { + sts0 = fspi_readl(FSPI_STS0); + } while (((sts0 & FSPI_STS0_ARB_IDLE) == 0) && + ((sts0 & FSPI_STS0_SEQ_IDLE) == 0)); + + /* Trigger IP Read Command */ + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + PRA("0x%x", fspi_readl(FSPI_IPCMD)); + + intr = fspi_readl(FSPI_INTR); + if (((intr & FSPI_INTR_IPCMDGE) != 0) || + ((intr & FSPI_INTR_IPCMDERR) != 0)) { + ERROR("Error in IP READ INTR=0x%x\n", intr); + return -XSPI_IP_READ_FAIL; + } + /* Will read in n iterations of each 8 FIFO's(WM level) */ + x_iteration = x_size_rx / x_size_wm; + for (i = 0U; i < x_iteration; i++) { + if ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPRXWA_MASK) == 0) { + PRA("0x%x", fspi_readl(FSPI_INTR)); + } + /* Wait for IP Rx Watermark Fill event */ + while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPRXWA_MASK)) { + PRA("0x%x", fspi_readl(FSPI_INTR)); + } + + /* Read RX FIFO's(upto WM level) & copy to rxbuffer */ + for (j = 0U; j < x_size_wm; j += 4U) { + /* Read FIFO Data Register */ + data = fspi_readl(FSPI_RFDR + j); +#if FSPI_IPDATA_SWAP /* Just In case you want swap */ + data = bswap32(data); +#endif + memcpy(pv_rx_buf++, &data, 4); + } + + /* Clear IP_RX_WATERMARK Event in INTR register */ + /* Reset FIFO Read pointer for next iteration.*/ + fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA); + } + + x_rem = x_size_rx % x_size_wm; + + if (x_rem != 0U) { + /* Wait for data filled */ + while (!(fspi_readl(FSPI_IPRXFSTS) & FSPI_IPRXFSTS_FILL_MASK)) { + PRA("0x%x", fspi_readl(FSPI_IPRXFSTS)); + } + + temp_size = 0; + j = 0U; + while (x_rem > 0U) { + data = 0U; + data = fspi_readl(FSPI_RFDR + j); +#if FSPI_IPDATA_SWAP /* Just In case you want swap */ + data = bswap32(data); +#endif + temp_size = (x_rem < 4) ? x_rem : 4; + memcpy(pv_rx_buf++, &data, temp_size); + x_rem -= temp_size; + } + } + + + while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK)) { + PRA("0x%x", fspi_readl(FSPI_INTR)); + } + + /* Invalid the RX FIFO, to run next IP Command */ + fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); + /* Clear IP Command Done flag in interrupt register*/ + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + + /* Update remaining len, Increment x_addr read pointer. */ + x_len_bytes -= x_size_rx; + x_addr += x_size_rx; + } + PR; + return XSPI_SUCCESS; +} + +void xspi_ip_write(uint32_t pc_wr_addr, uint32_t *pv_wr_buf, uint32_t ui_len) +{ + + uint32_t x_iteration = 0U, x_rem = 0U; + uint32_t x_size_tx = 0U, x_size_wm, temp_size; + uint32_t i = 0U, j = 0U; + uint32_t ui_data = 0U; + uint32_t x_addr, x_len_bytes; + + + x_size_wm = 8U; /* Default TX WaterMark level: 8 Bytes. */ + x_addr = (uint32_t)pc_wr_addr; + x_len_bytes = ui_len; + VERBOSE("In func %s[%d] x_addr =0x%x xLen_bytes=%d\n", + __func__, __LINE__, x_addr, x_len_bytes); + + while (x_len_bytes != 0U) { + + x_size_tx = (x_len_bytes > FSPI_TX_IPBUF_SIZE) ? + FSPI_TX_IPBUF_SIZE : x_len_bytes; + + /* IP Control Register0 - SF Address to be read */ + fspi_writel(FSPI_IPCR0, x_addr); + INFO("In func %s[%d] x_addr =0x%x xLen_bytes=%d\n", + __func__, __LINE__, x_addr, x_len_bytes); + + /* + * Fill TX FIFO's.. + * + */ + + x_iteration = x_size_tx / x_size_wm; + for (i = 0U; i < x_iteration; i++) { + + /* Ensure TX FIFO Watermark Available */ + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPTXWE_MASK) == 0) + ; + + + /* Fill TxFIFO's ( upto watermark level) */ + for (j = 0U; j < x_size_wm; j += 4U) { + memcpy(&ui_data, pv_wr_buf++, 4); + /* Write TX FIFO Data Register */ + fspi_writel((FSPI_TFDR + j), ui_data); + + } + + /* Clear IP_TX_WATERMARK Event in INTR register */ + /* Reset the FIFO Write pointer for next iteration */ + fspi_writel(FSPI_INTR, FSPI_INTR_IPTXWE); + } + + x_rem = x_size_tx % x_size_wm; + + if (x_rem != 0U) { + /* Wait for TXFIFO empty */ + while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPTXWE)) + ; + + temp_size = 0U; + j = 0U; + while (x_rem > 0U) { + ui_data = 0U; + temp_size = (x_rem < 4U) ? x_rem : 4U; + memcpy(&ui_data, pv_wr_buf++, temp_size); + INFO("%d ---> pv_wr_buf=0x%p\n", __LINE__, pv_wr_buf); + fspi_writel((FSPI_TFDR + j), ui_data); + x_rem -= temp_size; + j += 4U ; /* TODO: May not be needed*/ + } + /* Clear IP_TX_WATERMARK Event in INTR register */ + /* Reset FIFO's Write pointer for next iteration.*/ + fspi_writel(FSPI_INTR, FSPI_INTR_IPTXWE); + } + + /* IP Control Register1 - SEQID_WRITE operation, Size */ + fspi_writel(FSPI_IPCR1, (uint32_t)(FSPI_WRITE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | (uint16_t) x_size_tx); + /* Trigger IP Write Command */ + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + + /* Wait for IP Write command done */ + while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK)) + ; + + /* Invalidate TX FIFOs & acknowledge IP_CMD_DONE event */ + fspi_writel(FSPI_IPTXFCR, FSPI_IPTXFCR_CLR); + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + + /* for next iteration */ + x_len_bytes -= x_size_tx; + x_addr += x_size_tx; + } + +} + +int xspi_write(uint32_t pc_wr_addr, void *pv_wr_buf, uint32_t ui_len) +{ + + uint32_t x_addr; + uint32_t x_page1_len = 0U, x_page_l_len = 0U; + uint32_t i, j = 0U; + void *buf = pv_wr_buf; + + VERBOSE("\nIn func %s\n", __func__); + + x_addr = (uint32_t)(pc_wr_addr); + if ((ui_len <= F_PAGE_256) && ((x_addr % F_PAGE_256) == 0)) { + x_page1_len = ui_len; + INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); + } else if ((ui_len <= F_PAGE_256) && ((x_addr % F_PAGE_256) != 0)) { + x_page1_len = (F_PAGE_256 - (x_addr % F_PAGE_256)); + if (ui_len > x_page1_len) { + x_page_l_len = (ui_len - x_page1_len) % F_PAGE_256; + } else { + x_page1_len = ui_len; + x_page_l_len = 0; + } + j = 0U; + INFO("%d 0x%x 0x%x\n", x_addr % F_PAGE_256, x_addr % F_PAGE_256, F_PAGE_256); + INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); + } else if ((ui_len > F_PAGE_256) && ((x_addr % F_PAGE_256) == 0)) { + j = ui_len / F_PAGE_256; + x_page_l_len = ui_len % F_PAGE_256; + INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); + } else if ((ui_len > F_PAGE_256) && ((x_addr % F_PAGE_256) != 0)) { + x_page1_len = (F_PAGE_256 - (x_addr % F_PAGE_256)); + j = (ui_len - x_page1_len) / F_PAGE_256; + x_page_l_len = (ui_len - x_page1_len) % F_PAGE_256; + INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); + } + + if (x_page1_len != 0U) { + xspi_wren(x_addr); + xspi_ip_write(x_addr, (uint32_t *)buf, x_page1_len); + while (is_flash_busy()) + ; + INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", + __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); + INFO("Initial Buf pv_wr_buf=%p, final Buf=%p\n", pv_wr_buf, buf); + x_addr += x_page1_len; + /* TODO What is buf start is not 4 aligned */ + buf = buf + x_page1_len; + } + + for (i = 0U; i < j; i++) { + INFO("In for loop Buf pv_wr_buf=%p, final Buf=%p x_addr=0x%x offset_buf %d.\n", + pv_wr_buf, buf, x_addr, x_page1_len/4); + xspi_wren(x_addr); + xspi_ip_write(x_addr, (uint32_t *)buf, F_PAGE_256); + while (is_flash_busy()) + ; + INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", + __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); + x_addr += F_PAGE_256; + /* TODO What is buf start is not 4 aligned */ + buf = buf + F_PAGE_256; + INFO("Initial Buf pv_wr_buf=%p, final Buf=%p\n", pv_wr_buf, buf); + } + + if (x_page_l_len != 0U) { + INFO("%d Initial Buf pv_wr_buf=%p, final Buf=%p x_page_l_len=0x%x\n", __LINE__, pv_wr_buf, buf, x_page_l_len); + xspi_wren(x_addr); + xspi_ip_write(x_addr, (uint32_t *)buf, x_page_l_len); + while (is_flash_busy()) + ; + INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", + __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); + } + + VERBOSE("Now calling func call Invalidate%s\n", __func__); + fspi_ahb_invalidate(); + return XSPI_SUCCESS; +} + +int xspi_wren(uint32_t pc_wr_addr) +{ + VERBOSE("In func %s Addr=0x%x\n", __func__, pc_wr_addr); + + fspi_writel(FSPI_IPTXFCR, FSPI_IPTXFCR_CLR); + + fspi_writel(FSPI_IPCR0, (uint32_t)pc_wr_addr); + fspi_writel(FSPI_IPCR1, ((FSPI_WREN_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) + ; + + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + return XSPI_SUCCESS; +} + +static void fspi_bbluk_er(void) +{ + VERBOSE("In func %s\n", __func__); + fspi_writel(FSPI_IPCR0, 0x0); + fspi_writel(FSPI_IPCR1, ((FSPI_BE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 20)); + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) + ; + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + +} + +static void fspi_RDSR(uint32_t *rxbuf, const void *p_addr, uint32_t size) +{ + uint32_t iprxfcr = 0U; + uint32_t data = 0U; + + iprxfcr = fspi_readl(FSPI_IPRXFCR); + /* IP RX FIFO would be read by processor */ + iprxfcr = iprxfcr & (uint32_t)~FSPI_IPRXFCR_CLR; + /* Invalid data entries in IP RX FIFO */ + iprxfcr = iprxfcr | FSPI_IPRXFCR_CLR; + fspi_writel(FSPI_IPRXFCR, iprxfcr); + + fspi_writel(FSPI_IPCR0, (uintptr_t) p_addr); + fspi_writel(FSPI_IPCR1, + (uint32_t) ((FSPI_RDSR_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) + | (uint16_t) size)); + /* Trigger the command */ + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + /* Wait for command done */ + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) + ; + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + + data = fspi_readl(FSPI_RFDR); + memcpy(rxbuf, &data, size); + + /* Rx FIFO invalidation needs to be done prior w1c of INTR.IPRXWA bit */ + fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); + fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA_MASK); + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + +} + +bool is_flash_busy(void) +{ +#define FSPI_ONE_BYTE 1 + uint8_t data[4]; + + VERBOSE("In func %s\n\n", __func__); + fspi_RDSR((uint32_t *) data, 0, FSPI_ONE_BYTE); + + return !!((uint32_t) data[0] & FSPI_NOR_SR_WIP_MASK); +} + +int xspi_bulk_erase(void) +{ + VERBOSE("In func %s\n", __func__); + xspi_wren((uint32_t) 0x0); + fspi_bbluk_er(); + while (is_flash_busy()) + ; + fspi_ahb_invalidate(); + return XSPI_SUCCESS; +} + +static void fspi_sec_er(uint32_t pc_wr_addr) +{ + uint32_t x_addr; + + VERBOSE("In func %s\n", __func__); + x_addr = (uint32_t)(pc_wr_addr); + + fspi_writel(FSPI_IPCR0, x_addr); + INFO("In [%s][%d] Erase address 0x%x\n", __func__, __LINE__, (x_addr)); +#if CONFIG_FSPI_ERASE_4K + fspi_writel(FSPI_IPCR1, ((FSPI_4K_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); +#else + fspi_writel(FSPI_IPCR1, ((FSPI_SE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); +#endif + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) { + PRA("0x%x", fspi_readl(FSPI_INTR)); + } + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); +} + +int xspi_sector_erase(uint32_t pc_wr_addr, uint32_t ui_len) +{ + uint32_t x_addr, x_len_bytes, i, num_sector = 0U; + + VERBOSE("In func %s\n", __func__); + x_addr = (uint32_t)(pc_wr_addr); + if ((x_addr % F_SECTOR_ERASE_SZ) != 0) { + ERROR("!!! In func %s, unalinged start address can only be in multiples of 0x%x\n", + __func__, F_SECTOR_ERASE_SZ); + return -XSPI_ERASE_FAIL; + } + + x_len_bytes = ui_len * 1; + if (x_len_bytes < F_SECTOR_ERASE_SZ) { + ERROR("!!! In func %s, Less than 1 sector can only be in multiples of 0x%x\n", + __func__, F_SECTOR_ERASE_SZ); + return -XSPI_ERASE_FAIL; + } + + num_sector = x_len_bytes/F_SECTOR_ERASE_SZ; + num_sector += x_len_bytes % F_SECTOR_ERASE_SZ ? 1U : 0U; + INFO("F_SECTOR_ERASE_SZ: 0x%08x, num_sector: %d\n", F_SECTOR_ERASE_SZ, num_sector); + + for (i = 0U; i < num_sector ; i++) { + xspi_wren(x_addr + (F_SECTOR_ERASE_SZ * i)); + fspi_sec_er(x_addr + (F_SECTOR_ERASE_SZ * i)); + while (is_flash_busy()) + ; + } + fspi_ahb_invalidate(); + return XSPI_SUCCESS; +} + + +__attribute__((unused)) static void fspi_delay_ms(uint32_t x) +{ + volatile unsigned long ul_count; + + for (ul_count = 0U; ul_count < (30U * x); ul_count++) + ; + +} + + +#if defined(DEBUG_FLEXSPI) +static void fspi_dump_regs(void) +{ + uint32_t i; + + VERBOSE("\nRegisters Dump:\n"); + VERBOSE("Flexspi: Register FSPI_MCR0(0x%x) = 0x%08x\n", FSPI_MCR0, fspi_readl(FSPI_MCR0)); + VERBOSE("Flexspi: Register FSPI_MCR2(0x%x) = 0x%08x\n", FSPI_MCR2, fspi_readl(FSPI_MCR2)); + VERBOSE("Flexspi: Register FSPI_DLL_A_CR(0x%x) = 0x%08x\n", FSPI_DLLACR, fspi_readl(FSPI_DLLACR)); + VERBOSE("\n"); + + for (i = 0U; i < 8U; i++) { + VERBOSE("Flexspi: Register FSPI_AHBRX_BUF0CR0(0x%x) = 0x%08x\n", FSPI_AHBRX_BUF0CR0 + i * 4, fspi_readl((FSPI_AHBRX_BUF0CR0 + i * 4))); + } + VERBOSE("\n"); + + VERBOSE("Flexspi: Register FSPI_AHBRX_BUF7CR0(0x%x) = 0x%08x\n", FSPI_AHBRX_BUF7CR0, fspi_readl(FSPI_AHBRX_BUF7CR0)); + VERBOSE("Flexspi: Register FSPI_AHB_CR(0x%x) \t = 0x%08x\n", FSPI_AHBCR, fspi_readl(FSPI_AHBCR)); + VERBOSE("\n"); + + for (i = 0U; i < 4U; i++) { + VERBOSE("Flexspi: Register FSPI_FLSH_A1_CR2,(0x%x) = 0x%08x\n", FSPI_FLSHA1CR2 + i * 4, fspi_readl(FSPI_FLSHA1CR2 + i * 4)); + } +} +#endif + +int fspi_init(uint32_t base_reg_addr, uint32_t flash_start_addr) +{ + uint32_t mcrx; + uint32_t flash_size; + + if (fspi_base_reg_addr != 0U) { + INFO("FSPI is already initialized.\n"); + return XSPI_SUCCESS; + } + + fspi_base_reg_addr = base_reg_addr; + fspi_flash_base_addr = flash_start_addr; + + INFO("Flexspi driver: Version v1.0\n"); + INFO("Flexspi: Default MCR0 = 0x%08x, before reset\n", fspi_readl(FSPI_MCR0)); + VERBOSE("Flexspi: Resetting controller...\n"); + + /* Reset FlexSpi Controller */ + fspi_writel(FSPI_MCR0, FSPI_MCR0_SWRST); + while ((fspi_readl(FSPI_MCR0) & FSPI_MCR0_SWRST)) + ; /* FSPI_MCR0_SWRESET_MASK */ + + + /* Disable Controller Module before programming its registersi, especially MCR0 (Master Control Register0) */ + fspi_MDIS(1); + /* + * Program MCR0 with default values, AHB Timeout(0xff), IP Timeout(0xff). {FSPI_MCR0- 0xFFFF0000} + */ + + /* Timeout wait cycle for AHB command grant */ + mcrx = fspi_readl(FSPI_MCR0); + mcrx |= (uint32_t)((FSPI_MAX_TIMEOUT_AHBCMD << FSPI_MCR0_AHBGRANTWAIT_SHIFT) & (FSPI_MCR0_AHBGRANTWAIT_MASK)); + + /* Time out wait cycle for IP command grant*/ + mcrx |= (uint32_t) (FSPI_MAX_TIMEOUT_IPCMD << FSPI_MCR0_IPGRANTWAIT_SHIFT) & (FSPI_MCR0_IPGRANTWAIT_MASK); + + /* TODO why BE64 set BE32*/ + mcrx |= (uint32_t) (FSPI_ENDCFG_LE64 << FSPI_MCR0_ENDCFG_SHIFT) & FSPI_MCR0_ENDCFG_MASK; + + fspi_writel(FSPI_MCR0, mcrx); + + /* Reset the DLL register to default value */ + fspi_writel(FSPI_DLLACR, FSPI_DLLACR_OVRDEN); + fspi_writel(FSPI_DLLBCR, FSPI_DLLBCR_OVRDEN); + +#if ERRATA_FLASH_A050272 /* ERRATA DLL */ + for (uint8_t delay = 100U; delay > 0U; delay--) { + __asm__ volatile ("nop"); + } +#endif + + /* Configure flash control registers for different chip select */ + flash_size = (F_FLASH_SIZE_BYTES * FLASH_NUM) / FSPI_BYTES_PER_KBYTES; + fspi_writel(FSPI_FLSHA1CR0, flash_size); + fspi_writel(FSPI_FLSHA2CR0, 0U); + fspi_writel(FSPI_FLSHB1CR0, 0U); + fspi_writel(FSPI_FLSHB2CR0, 0U); + +#if defined(CONFIG_FSPI_AHB) + fspi_init_ahb(); +#endif + /* RE-Enable Controller Module */ + fspi_MDIS(0); + INFO("Flexspi: After MCR0 = 0x%08x,\n", fspi_readl(FSPI_MCR0)); + fspi_setup_LUT(); + + /* Dump of all registers, ensure controller not disabled anymore*/ +#if defined(DEBUG_FLEXSPI) + fspi_dump_regs(); +#endif + + INFO("Flexspi: Init done!!\n"); + +#if DEBUG_FLEXSPI + + uint32_t xspi_addr = SZ_57M; + + /* + * Second argument of fspi_test is the size of buffer(s) passed + * to the function. + * SIZE_BUFFER defined in test_fspi.c is kept large enough to + * accommodate variety of sizes for regressive tests. + */ + fspi_test(xspi_addr, 0x40, 0); + fspi_test(xspi_addr, 0x15, 2); + fspi_test(xspi_addr, 0x80, 0); + fspi_test(xspi_addr, 0x81, 0); + fspi_test(xspi_addr, 0x79, 3); + + fspi_test(xspi_addr + 0x11, 0x15, 0); + fspi_test(xspi_addr + 0x11, 0x40, 0); + fspi_test(xspi_addr + 0xff, 0x40, 1); + fspi_test(xspi_addr + 0x25, 0x81, 2); + fspi_test(xspi_addr + 0xef, 0x6f, 3); + + fspi_test((xspi_addr - F_SECTOR_ERASE_SZ), 0x229, 0); +#endif + + return XSPI_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h b/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h new file mode 100644 index 0000000..da2e269 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h @@ -0,0 +1,385 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * FlexSpi Registers & Bits definition. + * + */ + +#ifndef FSPI_H +#define FSPI_H + +#ifndef __ASSEMBLER__ +#include + +#ifdef NXP_FSPI_BE +#define fspi_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define fspi_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_FSPI_LE) +#define fspi_in32(a) mmio_read_32((uintptr_t)(a)) +#define fspi_out32(a, v) mmio_write_32((uintptr_t)(a), v) +#else +#error Please define FSPI register endianness +#endif + +#endif + +/* All LE so not swap needed */ +#define FSPI_IPDATA_SWAP 0U +#define FSPI_AHBDATA_SWAP 0U + +#define CONFIG_FSPI_FASTREAD 1U + +#define FSPI_BYTES_PER_KBYTES 0x400U +#define FLASH_NUM 1U + +#define FSPI_READ_SEQ_ID 0U +#define FSPI_WREN_SEQ_ID 1U +#define FSPI_WRITE_SEQ_ID 2U +#define FSPI_SE_SEQ_ID 3U +#define FSPI_RDSR_SEQ_ID 4U +#define FSPI_BE_SEQ_ID 5U +#define FSPI_FASTREAD_SEQ_ID 6U +#define FSPI_4K_SEQ_ID 7U + +/* + * LUT register layout: + * + * --------------------------------------------------- + * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 | + * --------------------------------------------------- + * + * INSTR_SHIFT- 10, PAD_SHIFT - 8, OPRND_SHIFT -0 + */ +#define FSPI_INSTR_OPRND0_SHIFT 0 +#define FSPI_INSTR_OPRND0(x) (x << FSPI_INSTR_OPRND0_SHIFT) +#define FSPI_INSTR_PAD0_SHIFT 8 +#define FSPI_INSTR_PAD0(x) ((x) << FSPI_INSTR_PAD0_SHIFT) +#define FSPI_INSTR_OPCODE0_SHIFT 10 +#define FSPI_INSTR_OPCODE0(x) ((x) << FSPI_INSTR_OPCODE0_SHIFT) +#define FSPI_INSTR_OPRND1_SHIFT 16 +#define FSPI_INSTR_OPRND1(x) ((x) << FSPI_INSTR_OPRND1_SHIFT) +#define FSPI_INSTR_PAD1_SHIFT 24 +#define FSPI_INSTR_PAD1(x) ((x) << FSPI_INSTR_PAD1_SHIFT) +#define FSPI_INSTR_OPCODE1_SHIFT 26 +#define FSPI_INSTR_OPCODE1(x) ((x) << FSPI_INSTR_OPCODE1_SHIFT) + +/* Instruction set for the LUT register. */ +#define LUT_STOP 0x00 +#define LUT_CMD 0x01 +#define LUT_ADDR 0x02 +#define LUT_CADDR_SDR 0x03 +#define LUT_MODE 0x04 +#define LUT_MODE2 0x05 +#define LUT_MODE4 0x06 +#define LUT_MODE8 0x07 +#define LUT_NXP_WRITE 0x08 +#define LUT_NXP_READ 0x09 + +#define LUT_LEARN_SDR 0x0A +#define LUT_DATSZ_SDR 0x0B +#define LUT_DUMMY 0x0C +#define LUT_DUMMY_RWDS_SDR 0x0D +#define LUT_JMP_ON_CS 0x1F +#define LUT_CMD_DDR 0x21 +#define LUT_ADDR_DDR 0x22 +#define LUT_CADDR_DDR 0x23 +#define LUT_MODE_DDR 0x24 +#define LUT_MODE2_DDR 0x25 +#define LUT_MODE4_DDR 0x26 +#define LUT_MODE8_DDR 0x27 +#define LUT_WRITE_DDR 0x28 +#define LUT_READ_DDR 0x29 +#define LUT_LEARN_DDR 0x2A +#define LUT_DATSZ_DDR 0x2B +#define LUT_DUMMY_DDR 0x2C +#define LUT_DUMMY_RWDS_DDR 0x2D + +#define FSPI_NOR_CMD_READ 0x03 +#define FSPI_NOR_CMD_READ_4B 0x13 +#define FSPI_NOR_CMD_FASTREAD 0x0b +#define FSPI_NOR_CMD_FASTREAD_4B 0x0c +#define FSPI_NOR_CMD_PP 0x02 +#define FSPI_NOR_CMD_PP_4B 0x12 +#define FSPI_NOR_CMD_WREN 0x06 +#define FSPI_NOR_CMD_SE_64K 0xd8 +#define FSPI_NOR_CMD_SE_64K_4B 0xdc +#define FSPI_NOR_CMD_SE_4K 0x20 +#define FSPI_NOR_CMD_SE_4K_4B 0x21 +#define FSPI_NOR_CMD_BE 0x60 +#define FSPI_NOR_CMD_RDSR 0x05 +#define FSPI_NOR_CMD_WREN_STOP 0x04 + +#define FSPI_LUT_STOP 0x00 +#define FSPI_LUT_CMD 0x01 +#define FSPI_LUT_ADDR 0x02 + +#define FSPI_LUT_PAD1 0 +#define FSPI_LUT_PAD2 1 +#define FSPI_LUT_PAD4 2 +#define FSPI_LUT_PAD8 3 + +#define FSPI_LUT_ADDR24BIT 0x18 +#define FSPI_LUT_ADDR32BIT 0x20 + +#define FSPI_LUT_WRITE 0x08 +#define FSPI_LUT_READ 0x09 +#define FSPI_DUMMY_SDR 0x0c + +/* TODO Check size if functional*/ +#define FSPI_RX_IPBUF_SIZE 0x200 /* 64*64 bits */ +#define FSPI_TX_IPBUF_SIZE 0x400 /* 128*64 bits */ + +#define FSPI_RX_MAX_AHBBUF_SIZE 0x800 /* 256 * 64bits */ +#define FSPI_TX_MAX_AHBBUF_SIZE 0x40 /* 8 * 64bits */ + +#define FSPI_LUTREG_OFFSET 0x200ul + +#define FSPI_MAX_TIMEOUT_AHBCMD 0xFFU +#define FSPI_MAX_TIMEOUT_IPCMD 0xFF +#define FSPI_SER_CLK_DIV 0x04 +#define FSPI_HSEN 0 +#define FSPI_ENDCFG_BE64 0x01 +#define FSPI_ENDCFG_BE32 0x03 +#define FSPI_ENDCFG_LE32 0x02 +#define FSPI_ENDCFG_LE64 0x0 + +#define MASK_24BIT_ADDRESS 0x00ffffff +#define MASK_32BIT_ADDRESS 0xffffffff + +/* Registers used by the driver */ +#define FSPI_MCR0 0x0ul +#define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24) +#define FSPI_MCR0_IP_TIMEOUT(x) ((x) << 16) +#define FSPI_MCR0_LEARN_EN BIT(15) +#define FSPI_MCR0_SCRFRUN_EN BIT(14) +#define FSPI_MCR0_OCTCOMB_EN BIT(13) +#define FSPI_MCR0_DOZE_EN BIT(12) +#define FSPI_MCR0_HSEN BIT(11) +#define FSPI_MCR0_SERCLKDIV BIT(8) +#define FSPI_MCR0_ATDF_EN BIT(7) +#define FSPI_MCR0_ARDF_EN BIT(6) +#define FSPI_MCR0_RXCLKSRC(x) ((x) << 4) +#define FSPI_MCR0_END_CFG(x) ((x) << 2) +#define FSPI_MCR0_MDIS BIT(1) +#define FSPI_MCR0_SWRST BIT(0) + +#define FSPI_MCR0_AHBGRANTWAIT_SHIFT 24 +#define FSPI_MCR0_AHBGRANTWAIT_MASK (0xFFU << FSPI_MCR0_AHBGRANTWAIT_SHIFT) +#define FSPI_MCR0_IPGRANTWAIT_SHIFT 16 +#define FSPI_MCR0_IPGRANTWAIT_MASK (0xFF << FSPI_MCR0_IPGRANTWAIT_SHIFT) +#define FSPI_MCR0_HSEN_SHIFT 11 +#define FSPI_MCR0_HSEN_MASK (1 << FSPI_MCR0_HSEN_SHIFT) +#define FSPI_MCR0_SERCLKDIV_SHIFT 8 +#define FSPI_MCR0_SERCLKDIV_MASK (7 << FSPI_MCR0_SERCLKDIV_SHIFT) +#define FSPI_MCR0_ENDCFG_SHIFT 2 +#define FSPI_MCR0_ENDCFG_MASK (3 << FSPI_MCR0_ENDCFG_SHIFT) +#define FSPI_MCR0_RXCLKSRC_SHIFT 4 +#define FSPI_MCR0_RXCLKSRC_MASK (3 << FSPI_MCR0_RXCLKSRC_SHIFT) + +#define FSPI_MCR1 0x04 +#define FSPI_MCR1_SEQ_TIMEOUT(x) ((x) << 16) +#define FSPI_MCR1_AHB_TIMEOUT(x) (x) + +#define FSPI_MCR2 0x08 +#define FSPI_MCR2_IDLE_WAIT(x) ((x) << 24) +#define FSPI_MCR2_SAMEDEVICEEN BIT(15) +#define FSPI_MCR2_CLRLRPHS BIT(14) +#define FSPI_MCR2_ABRDATSZ BIT(8) +#define FSPI_MCR2_ABRLEARN BIT(7) +#define FSPI_MCR2_ABR_READ BIT(6) +#define FSPI_MCR2_ABRWRITE BIT(5) +#define FSPI_MCR2_ABRDUMMY BIT(4) +#define FSPI_MCR2_ABR_MODE BIT(3) +#define FSPI_MCR2_ABRCADDR BIT(2) +#define FSPI_MCR2_ABRRADDR BIT(1) +#define FSPI_MCR2_ABR_CMD BIT(0) + +#define FSPI_AHBCR 0x0c +#define FSPI_AHBCR_RDADDROPT BIT(6) +#define FSPI_AHBCR_PREF_EN BIT(5) +#define FSPI_AHBCR_BUFF_EN BIT(4) +#define FSPI_AHBCR_CACH_EN BIT(3) +#define FSPI_AHBCR_CLRTXBUF BIT(2) +#define FSPI_AHBCR_CLRRXBUF BIT(1) +#define FSPI_AHBCR_PAR_EN BIT(0) + +#define FSPI_INTEN 0x10 +#define FSPI_INTEN_SCLKSBWR BIT(9) +#define FSPI_INTEN_SCLKSBRD BIT(8) +#define FSPI_INTEN_DATALRNFL BIT(7) +#define FSPI_INTEN_IPTXWE BIT(6) +#define FSPI_INTEN_IPRXWA BIT(5) +#define FSPI_INTEN_AHBCMDERR BIT(4) +#define FSPI_INTEN_IPCMDERR BIT(3) +#define FSPI_INTEN_AHBCMDGE BIT(2) +#define FSPI_INTEN_IPCMDGE BIT(1) +#define FSPI_INTEN_IPCMDDONE BIT(0) + +#define FSPI_INTR 0x14 +#define FSPI_INTR_SCLKSBWR BIT(9) +#define FSPI_INTR_SCLKSBRD BIT(8) +#define FSPI_INTR_DATALRNFL BIT(7) +#define FSPI_INTR_IPTXWE BIT(6) +#define FSPI_INTR_IPRXWA BIT(5) +#define FSPI_INTR_AHBCMDERR BIT(4) +#define FSPI_INTR_IPCMDERR BIT(3) +#define FSPI_INTR_AHBCMDGE BIT(2) +#define FSPI_INTR_IPCMDGE BIT(1) +#define FSPI_INTR_IPCMDDONE BIT(0) + +#define FSPI_LUTKEY 0x18 +#define FSPI_LUTKEY_VALUE 0x5AF05AF0 + +#define FSPI_LCKCR 0x1C + +#define FSPI_LCKER_LOCK 0x1 +#define FSPI_LCKER_UNLOCK 0x2 + +#define FSPI_BUFXCR_INVALID_MSTRID 0xE +#define FSPI_AHBRX_BUF0CR0 0x20 +#define FSPI_AHBRX_BUF1CR0 0x24 +#define FSPI_AHBRX_BUF2CR0 0x28 +#define FSPI_AHBRX_BUF3CR0 0x2C +#define FSPI_AHBRX_BUF4CR0 0x30 +#define FSPI_AHBRX_BUF5CR0 0x34 +#define FSPI_AHBRX_BUF6CR0 0x38 +#define FSPI_AHBRX_BUF7CR0 0x3C + +#define FSPI_AHBRXBUF0CR7_PREF BIT(31) + +#define FSPI_AHBRX_BUF0CR1 0x40 +#define FSPI_AHBRX_BUF1CR1 0x44 +#define FSPI_AHBRX_BUF2CR1 0x48 +#define FSPI_AHBRX_BUF3CR1 0x4C +#define FSPI_AHBRX_BUF4CR1 0x50 +#define FSPI_AHBRX_BUF5CR1 0x54 +#define FSPI_AHBRX_BUF6CR1 0x58 +#define FSPI_AHBRX_BUF7CR1 0x5C + +#define FSPI_FLSHA1CR0 0x60 +#define FSPI_FLSHA2CR0 0x64 +#define FSPI_FLSHB1CR0 0x68 +#define FSPI_FLSHB2CR0 0x6C +#define FSPI_FLSHXCR0_SZ_KB 10 +#define FSPI_FLSHXCR0_SZ(x) ((x) >> FSPI_FLSHXCR0_SZ_KB) + +#define FSPI_FLSHA1CR1 0x70 +#define FSPI_FLSHA2CR1 0x74 +#define FSPI_FLSHB1CR1 0x78 +#define FSPI_FLSHB2CR1 0x7C +#define FSPI_FLSHXCR1_CSINTR(x) ((x) << 16) +#define FSPI_FLSHXCR1_CAS(x) ((x) << 11) +#define FSPI_FLSHXCR1_WA BIT(10) +#define FSPI_FLSHXCR1_TCSH(x) ((x) << 5) +#define FSPI_FLSHXCR1_TCSS(x) (x) + +#define FSPI_FLSHXCR1_TCSH_SHIFT 5 +#define FSPI_FLSHXCR1_TCSH_MASK (0x1F << FSPI_FLSHXCR1_TCSH_SHIFT) +#define FSPI_FLSHXCR1_TCSS_SHIFT 0 +#define FSPI_FLSHXCR1_TCSS_MASK (0x1F << FSPI_FLSHXCR1_TCSS_SHIFT) + +#define FSPI_FLSHA1CR2 0x80 +#define FSPI_FLSHA2CR2 0x84 +#define FSPI_FLSHB1CR2 0x88 +#define FSPI_FLSHB2CR2 0x8C +#define FSPI_FLSHXCR2_CLRINSP BIT(24) +#define FSPI_FLSHXCR2_AWRWAIT BIT(16) +#define FSPI_FLSHXCR2_AWRSEQN_SHIFT 13 +#define FSPI_FLSHXCR2_AWRSEQI_SHIFT 8 +#define FSPI_FLSHXCR2_ARDSEQN_SHIFT 5 +#define FSPI_FLSHXCR2_ARDSEQI_SHIFT 0 + +#define FSPI_IPCR0 0xA0 + +#define FSPI_IPCR1 0xA4 +#define FSPI_IPCR1_IPAREN BIT(31) +#define FSPI_IPCR1_SEQNUM_SHIFT 24 +#define FSPI_IPCR1_SEQID_SHIFT 16 +#define FSPI_IPCR1_IDATSZ(x) (x) + +#define FSPI_IPCMD 0xB0 +#define FSPI_IPCMD_TRG BIT(0) + + +/* IP Command Register */ +#define FSPI_IPCMD_TRG_SHIFT 0 +#define FSPI_IPCMD_TRG_MASK (1 << FSPI_IPCMD_TRG_SHIFT) + +#define FSPI_INTR_IPRXWA_SHIFT 5 +#define FSPI_INTR_IPRXWA_MASK (1 << FSPI_INTR_IPRXWA_SHIFT) + +#define FSPI_INTR_IPCMDDONE_SHIFT 0 +#define FSPI_INTR_IPCMDDONE_MASK (1 << FSPI_INTR_IPCMDDONE_SHIFT) + +#define FSPI_INTR_IPTXWE_SHIFT 6 +#define FSPI_INTR_IPTXWE_MASK (1 << FSPI_INTR_IPTXWE_SHIFT) + +#define FSPI_IPTXFSTS_FILL_SHIFT 0 +#define FSPI_IPTXFSTS_FILL_MASK (0xFF << FSPI_IPTXFSTS_FILL_SHIFT) + +#define FSPI_IPCR1_ISEQID_SHIFT 16 +#define FSPI_IPCR1_ISEQID_MASK (0x1F << FSPI_IPCR1_ISEQID_SHIFT) + +#define FSPI_IPRXFSTS_FILL_SHIFT 0 +#define FSPI_IPRXFSTS_FILL_MASK (0xFF << FSPI_IPRXFSTS_FILL_SHIFT) + +#define FSPI_DLPR 0xB4 + +#define FSPI_IPRXFCR 0xB8 +#define FSPI_IPRXFCR_CLR BIT(0) +#define FSPI_IPRXFCR_DMA_EN BIT(1) +#define FSPI_IPRXFCR_WMRK(x) ((x) << 2) + +#define FSPI_IPTXFCR 0xBC +#define FSPI_IPTXFCR_CLR BIT(0) +#define FSPI_IPTXFCR_DMA_EN BIT(1) +#define FSPI_IPTXFCR_WMRK(x) ((x) << 2) + +#define FSPI_DLLACR 0xC0 +#define FSPI_DLLACR_OVRDEN BIT(8) + +#define FSPI_DLLBCR 0xC4 +#define FSPI_DLLBCR_OVRDEN BIT(8) + +#define FSPI_STS0 0xE0 +#define FSPI_STS0_DLPHB(x) ((x) << 8) +#define FSPI_STS0_DLPHA(x) ((x) << 4) +#define FSPI_STS0_CMD_SRC(x) ((x) << 2) +#define FSPI_STS0_ARB_IDLE BIT(1) +#define FSPI_STS0_SEQ_IDLE BIT(0) + +#define FSPI_STS1 0xE4 +#define FSPI_STS1_IP_ERRCD(x) ((x) << 24) +#define FSPI_STS1_IP_ERRID(x) ((x) << 16) +#define FSPI_STS1_AHB_ERRCD(x) ((x) << 8) +#define FSPI_STS1_AHB_ERRID(x) (x) + +#define FSPI_AHBSPNST 0xEC +#define FSPI_AHBSPNST_DATLFT(x) ((x) << 16) +#define FSPI_AHBSPNST_BUFID(x) ((x) << 1) +#define FSPI_AHBSPNST_ACTIVE BIT(0) + +#define FSPI_IPRXFSTS 0xF0 +#define FSPI_IPRXFSTS_RDCNTR(x) ((x) << 16) +#define FSPI_IPRXFSTS_FILL(x) (x) + +#define FSPI_IPTXFSTS 0xF4 +#define FSPI_IPTXFSTS_WRCNTR(x) ((x) << 16) +#define FSPI_IPTXFSTS_FILL(x) (x) + +#define FSPI_NOR_SR_WIP_SHIFT (0) +#define FSPI_NOR_SR_WIP_MASK (1 << FSPI_NOR_SR_WIP_SHIFT) + +#define FSPI_RFDR 0x100 +#define FSPI_TFDR 0x180 + +#define FSPI_LUT_BASE 0x200 +#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) +#define FSPI_LUT_REG(idx) \ + (FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4) + +/* register map end */ + +#endif diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c b/arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c new file mode 100644 index 0000000..c36c5b8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c @@ -0,0 +1,91 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include +#include +#include "fspi.h" +#include + +/* + * The macros are defined to be used as test vector for testing fspi. + */ +#define SIZE_BUFFER 0x250 + +/* + * You may choose fspi_swap based on core endianness and flexspi IP/AHB + * buffer endianness set in MCR. + */ +#define fspi_swap32(A) (A) + +void fspi_test(uint32_t fspi_test_addr, uint32_t size, int extra) +{ + uint32_t buffer[SIZE_BUFFER]; + uint32_t count = 1; + uint32_t failed, i; + + NOTICE("-------------------------- %d----------------------------------\n", count++); + INFO("Sector Erase size: 0x%08x, size: %d\n", F_SECTOR_ERASE_SZ, size); + /* Test Sector Erase */ + xspi_sector_erase(fspi_test_addr - fspi_test_addr % F_SECTOR_ERASE_SZ, + F_SECTOR_ERASE_SZ); + + /* Test Erased data using IP read */ + xspi_ip_read((fspi_test_addr), buffer, size * 4); + + failed = 0; + for (i = 0; i < size; i++) + if (fspi_swap32(0xffffffff) != buffer[i]) { + failed = 1; + break; + } + + if (failed == 0) { + NOTICE("[%d]: Success Erase: data in buffer[%d] 0x%08x\n", __LINE__, i-3, buffer[i-3]); + } else { + ERROR("Erase: Failed -->xxx with buffer[%d]=0x%08x\n", i, buffer[i]); + } + + for (i = 0; i < SIZE_BUFFER; i++) + buffer[i] = 0x12345678; + + /* Write data from buffer to flash */ + xspi_write(fspi_test_addr, (void *)buffer, (size * 4 + extra)); + /* Check written data using IP read */ + xspi_ip_read(fspi_test_addr, buffer, (size * 4 + extra)); + failed = 0; + for (i = 0; i < size; i++) + if (fspi_swap32(0x12345678) != buffer[i]) { + failed = 1; + break; + } + + if (failed == 0) { + NOTICE("[%d]: Success IpWrite with IP READ in buffer[%d] 0x%08x\n", __LINE__, i-3, buffer[i-3]); + } else { + ERROR("Write: Failed -->xxxx with IP READ in buffer[%d]=0x%08x\n", i, buffer[i]); + return; + } + + /* xspi_read may use AHB read */ + xspi_read((fspi_test_addr), buffer, (size * 4 + extra)); + failed = 0; + for (i = 0; i < size; i++) + if (fspi_swap32(0x12345678) != buffer[i]) { + failed = 1; + break; + } + + if (failed == 0) { + NOTICE("[%d]: Success IpWrite with AHB OR IP READ on buffer[%d] 0x%08x\n", __LINE__, i-3, buffer[i-3]); + } else { + ERROR("Write: Failed -->xxxx with AHB READ on buffer[%d]=0x%08x\n", i, buffer[i]); + return; + } +} diff --git a/arm-trusted-firmware/drivers/nxp/gic/gic.mk b/arm-trusted-firmware/drivers/nxp/gic/gic.mk new file mode 100644 index 0000000..d75e071 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gic/gic.mk @@ -0,0 +1,46 @@ +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the GIC files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_GIC},) +ADD_GIC := 1 +ifeq ($(GIC), GIC400) +include drivers/arm/gic/v2/gicv2.mk +GIC_SOURCES += ${GICV2_SOURCES} +GIC_SOURCES += ${PLAT_DRIVERS_PATH}/gic/ls_gicv2.c \ + plat/common/plat_gicv2.c + +PLAT_INCLUDES += -I${PLAT_DRIVERS_INCLUDE_PATH}/gic/gicv2 +else +ifeq ($(GIC), GIC500) +include drivers/arm/gic/v3/gicv3.mk +GIC_SOURCES += ${GICV3_SOURCES} +GIC_SOURCES += ${PLAT_DRIVERS_PATH}/gic/ls_gicv3.c \ + plat/common/plat_gicv3.c + +PLAT_INCLUDES += -I${PLAT_DRIVERS_INCLUDE_PATH}/gic/gicv3 +else + $(error -> GIC type not set!) +endif +endif + +ifeq (${BL_COMM_GIC_NEEDED},yes) +BL_COMMON_SOURCES += ${GIC_SOURCES} +else +ifeq (${BL2_GIC_NEEDED},yes) +BL2_SOURCES += ${GIC_SOURCES} +endif +ifeq (${BL31_GIC_NEEDED},yes) +BL31_SOURCES += ${GIC_SOURCES} +endif +endif +endif + +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c b/arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c new file mode 100644 index 0000000..62bc8db --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c @@ -0,0 +1,76 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + + +/* + * NXP common helper to initialize the GICv3 only driver. + */ +void plat_ls_gic_driver_init(uintptr_t nxp_gicd_addr, + uintptr_t nxp_gicc_addr, + uint8_t plat_core_count, + interrupt_prop_t *ls_interrupt_props, + uint8_t ls_interrupt_prop_count, + uint32_t *target_mask_array) +{ + static struct gicv2_driver_data ls_gic_data; + + ls_gic_data.gicd_base = nxp_gicd_addr; + ls_gic_data.gicc_base = nxp_gicc_addr; + ls_gic_data.target_masks = target_mask_array; + ls_gic_data.target_masks_num = plat_core_count; + ls_gic_data.interrupt_props = ls_interrupt_props; + ls_gic_data.interrupt_props_num = ls_interrupt_prop_count; + + gicv2_driver_init(&ls_gic_data); +} + +void plat_ls_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * ARM common helper to enable the GICv2 CPU interface + *****************************************************************************/ +void plat_ls_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * ARM common helper to disable the GICv2 CPU interface + *****************************************************************************/ +void plat_ls_gic_cpuif_disable(void) +{ + gicv2_cpuif_disable(); +} + +/****************************************************************************** + * NXP common helper to initialize GICv2 per cpu + *****************************************************************************/ +void plat_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Stubs for Redistributor power management. Although GICv2 doesn't have + * Redistributor interface, these are provided for the sake of uniform GIC API + *****************************************************************************/ +void plat_ls_gic_redistif_on(void) +{ +} + +void plat_ls_gic_redistif_off(void) +{ +} diff --git a/arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c b/arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c new file mode 100644 index 0000000..9c02bd6 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c @@ -0,0 +1,78 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +/* + * NXP common helper to initialize the GICv3 only driver. + */ +void plat_ls_gic_driver_init(uintptr_t nxp_gicd_addr, + uintptr_t nxp_gicr_addr, + uint8_t plat_core_count, + interrupt_prop_t *ls_interrupt_props, + uint8_t ls_interrupt_prop_count, + uintptr_t *target_mask_array, + mpidr_hash_fn mpidr_to_core_pos) +{ + static struct gicv3_driver_data ls_gic_data; + + ls_gic_data.gicd_base = nxp_gicd_addr; + ls_gic_data.gicr_base = nxp_gicr_addr; + ls_gic_data.interrupt_props = ls_interrupt_props; + ls_gic_data.interrupt_props_num = ls_interrupt_prop_count; + ls_gic_data.rdistif_num = plat_core_count; + ls_gic_data.rdistif_base_addrs = target_mask_array; + ls_gic_data.mpidr_to_core_pos = mpidr_to_core_pos; + + gicv3_driver_init(&ls_gic_data); +} + +void plat_ls_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/* + * NXP common helper to enable the GICv3 CPU interface + */ +void plat_ls_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/* + * NXP common helper to disable the GICv3 CPU interface + */ +void plat_ls_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/* + * NXP common helper to initialize the per cpu distributor interface in GICv3 + */ +void plat_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/* + * Stubs for Redistributor power management. Although GICv3 doesn't have + * Redistributor interface, these are provided for the sake of uniform GIC API + */ +void plat_ls_gic_redistif_on(void) +{ +} + +void plat_ls_gic_redistif_off(void) +{ +} diff --git a/arm-trusted-firmware/drivers/nxp/gpio/gpio.mk b/arm-trusted-firmware/drivers/nxp/gpio/gpio.mk new file mode 100644 index 0000000..74f0dc4 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gpio/gpio.mk @@ -0,0 +1,28 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- + +ifeq (${GPIO_ADDED},) + +GPIO_ADDED := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/gpio + +GPIO_SOURCES := $(PLAT_DRIVERS_PATH)/gpio/nxp_gpio.c + +ifeq (${BL_COMM_GPIO_NEEDED},yes) +BL_COMMON_SOURCES += ${GPIO_SOURCES} +else +ifeq (${BL2_GPIO_NEEDED},yes) +BL2_SOURCES += ${GPIO_SOURCES} +endif +ifeq (${BL31_GPIO_NEEDED},yes) +BL31_SOURCES += ${GPIO_SOURCES} +endif +endif + +endif +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c b/arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c new file mode 100644 index 0000000..28c9db9 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c @@ -0,0 +1,144 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +static gpio_init_info_t *gpio_init_info; + +void gpio_init(gpio_init_info_t *gpio_init_data) +{ + gpio_init_info = gpio_init_data; +} + +/* This function set GPIO pin for raising POVDD. */ +int set_gpio_bit(uint32_t *gpio_base_addr, + uint32_t bit_num) +{ + uint32_t val = 0U; + uint32_t *gpdir = NULL; + uint32_t *gpdat = NULL; + + if (gpio_init_info == NULL) { + ERROR("GPIO is not initialized.\n"); + return GPIO_FAILURE; + } + + gpdir = gpio_base_addr + GPDIR_REG_OFFSET; + gpdat = gpio_base_addr + (GPDAT_REG_OFFSET >> 2); + + /* + * Set the corresponding bit in direction register + * to configure the GPIO as output. + */ + val = gpio_read32(gpdir); + val = val | bit_num; + gpio_write32(gpdir, val); + + /* Set the corresponding bit in GPIO data register */ + val = gpio_read32(gpdat); + val = val | bit_num; + gpio_write32(gpdat, val); + + val = gpio_read32(gpdat); + + if ((val & bit_num) == 0U) { + return GPIO_FAILURE; + } + + return GPIO_SUCCESS; +} + +/* This function reset GPIO pin set for raising POVDD. */ +int clr_gpio_bit(uint32_t *gpio_base_addr, uint32_t bit_num) +{ + uint32_t val = 0U; + uint32_t *gpdir = NULL; + uint32_t *gpdat = NULL; + + + if (gpio_init_info == NULL) { + ERROR("GPIO is not initialized.\n"); + return GPIO_FAILURE; + } + + gpdir = gpio_base_addr + GPDIR_REG_OFFSET; + gpdat = gpio_base_addr + GPDAT_REG_OFFSET; + + /* + * Reset the corresponding bit in direction and data register + * to configure the GPIO as input. + */ + val = gpio_read32(gpdat); + val = val & ~(bit_num); + gpio_write32(gpdat, val); + + val = gpio_read32(gpdat); + + val = gpio_read32(gpdir); + val = val & ~(bit_num); + gpio_write32(gpdir, val); + + val = gpio_read32(gpdat); + + if ((val & bit_num) != 0U) { + return GPIO_FAILURE; + } + + return GPIO_SUCCESS; +} + +uint32_t *select_gpio_n_bitnum(uint32_t povdd_gpio, uint32_t *bit_num) +{ + uint32_t *ret_gpio; + uint32_t povdd_gpio_val = 0U; + uint32_t gpio_num = 0U; + + if (gpio_init_info == NULL) { + ERROR("GPIO is not initialized.\n"); + } + /* + * Subtract 1 from fuse_hdr povdd_gpio value as + * for 0x1 value, bit 0 is to be set + * for 0x20 value i.e 32, bit 31 i.e. 0x1f is to be set. + * 0x1f - 0x00 : GPIO_1 + * 0x3f - 0x20 : GPIO_2 + * 0x5f - 0x40 : GPIO_3 + * 0x7f - 0x60 : GPIO_4 + */ + povdd_gpio_val = (povdd_gpio - 1U) & GPIO_SEL_MASK; + + /* Right shift by 5 to divide by 32 */ + gpio_num = povdd_gpio_val >> GPIO_ID_BASE_ADDR_SHIFT; + *bit_num = 1U << (GPIO_BITS_PER_BASE_REG + - (povdd_gpio_val & GPIO_BIT_MASK) + - 1U); + + switch (gpio_num) { + case GPIO_0: + ret_gpio = (uint32_t *) gpio_init_info->gpio1_base_addr; + break; + case GPIO_1: + ret_gpio = (uint32_t *) gpio_init_info->gpio2_base_addr; + break; + case GPIO_2: + ret_gpio = (uint32_t *) gpio_init_info->gpio3_base_addr; + break; + case GPIO_3: + ret_gpio = (uint32_t *) gpio_init_info->gpio4_base_addr; + break; + default: + ret_gpio = NULL; + } + + if (ret_gpio == NULL) { + INFO("GPIO_NUM = %d doesn't exist.\n", gpio_num); + } + + return ret_gpio; +} diff --git a/arm-trusted-firmware/drivers/nxp/i2c/i2c.c b/arm-trusted-firmware/drivers/nxp/i2c/i2c.c new file mode 100644 index 0000000..9281409 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/i2c/i2c.c @@ -0,0 +1,257 @@ +/* + * Copyright 2016-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include "i2c.h" +#include + +static uintptr_t g_nxp_i2c_addr; + +void i2c_init(uintptr_t nxp_i2c_addr) +{ + struct ls_i2c *ccsr_i2c = (void *)nxp_i2c_addr; + + g_nxp_i2c_addr = nxp_i2c_addr; + /* Presume workaround for erratum a009203 applied */ + i2c_out(&ccsr_i2c->cr, I2C_CR_DIS); + i2c_out(&ccsr_i2c->fd, I2C_FD_CONSERV); + i2c_out(&ccsr_i2c->sr, I2C_SR_RST); + i2c_out(&ccsr_i2c->cr, I2C_CR_EN); +} + +static int wait_for_state(struct ls_i2c *ccsr_i2c, + unsigned char state, unsigned char mask) +{ + unsigned char sr; + uint64_t start_time = get_timer_val(0); + uint64_t timer; + + do { + sr = i2c_in(&ccsr_i2c->sr); + if (sr & I2C_SR_AL) { + i2c_out(&ccsr_i2c->sr, sr); + WARN("I2C arbitration lost\n"); + return -EIO; + } + if ((sr & mask) == state) { + return (int)sr; + } + + timer = get_timer_val(start_time); + if (timer > I2C_TIMEOUT) + break; + mdelay(1); + } while (1); + WARN("I2C: Timeout waiting for state 0x%x, sr = 0x%x\n", state, sr); + + return -ETIMEDOUT; +} + +static int tx_byte(struct ls_i2c *ccsr_i2c, unsigned char c) +{ + int ret; + + i2c_out(&ccsr_i2c->sr, I2C_SR_IF); + i2c_out(&ccsr_i2c->dr, c); + ret = wait_for_state(ccsr_i2c, I2C_SR_IF, I2C_SR_IF); + if (ret < 0) { + WARN("%s: state error\n", __func__); + return ret; + } + if (ret & I2C_SR_RX_NAK) { + WARN("%s: nodev\n", __func__); + return -ENODEV; + } + + return 0; +} + +static int gen_stop(struct ls_i2c *ccsr_i2c) +{ + unsigned char cr; + int ret; + + cr = i2c_in(&ccsr_i2c->cr); + cr &= ~(I2C_CR_MA | I2C_CR_TX); + i2c_out(&ccsr_i2c->cr, cr); + ret = wait_for_state(ccsr_i2c, I2C_SR_IDLE, I2C_SR_BB); + if (ret < 0) { + WARN("I2C: Generating stop failed.\n"); + } + return ret; +} + +static int i2c_write_addr(struct ls_i2c *ccsr_i2c, unsigned char chip, + int addr, int alen) +{ + int ret; + unsigned char cr; + + if (alen != 1) { + WARN("I2C: Unsupported address len [%d]\n", alen); + return -EIO; + } + + if (i2c_in(&ccsr_i2c->ad) == (chip << 1)) { + WARN("I2C: slave address same as self\n"); + return -ENODEV; + } + i2c_out(&ccsr_i2c->sr, I2C_SR_IF); + ret = wait_for_state(ccsr_i2c, I2C_SR_IDLE, I2C_SR_BB); + if (ret < 0) { + return ret; + } + + cr = i2c_in(&ccsr_i2c->cr); + cr |= I2C_CR_MA; + i2c_out(&ccsr_i2c->cr, cr); + ret = wait_for_state(ccsr_i2c, I2C_SR_BB, I2C_SR_BB); + if (ret < 0) { + return ret; + } + + VERBOSE("Before writing chip %d\n", chip); + cr |= I2C_CR_TX | I2C_CR_TX_NAK; + i2c_out(&ccsr_i2c->cr, cr); + ret = tx_byte(ccsr_i2c, chip << 1); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + + VERBOSE("Before writing addr\n"); + while (alen--) { + ret = tx_byte(ccsr_i2c, (addr >> (alen << 3)) & 0xff); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + } + + return 0; +} + +static int read_data(struct ls_i2c *ccsr_i2c, unsigned char chip, + unsigned char *buf, int len) +{ + int i; + int ret; + unsigned char cr; + + cr = i2c_in(&ccsr_i2c->cr); + cr &= ~(I2C_CR_TX | I2C_CR_TX_NAK); + if (len == 1) { + cr |= I2C_CR_TX_NAK; + } + i2c_out(&ccsr_i2c->cr, cr); + i2c_out(&ccsr_i2c->sr, I2C_SR_IF); + i2c_in(&ccsr_i2c->dr); /* dummy read */ + for (i = 0; i < len; i++) { + ret = wait_for_state(ccsr_i2c, I2C_SR_IF, I2C_SR_IF); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + if (i == (len - 1)) { + gen_stop(ccsr_i2c); + } else if (i == (len - 2)) { + /* Updating the command to send + * No ACK. + */ + cr = i2c_in(&ccsr_i2c->cr); + cr |= I2C_CR_TX_NAK; + i2c_out(&ccsr_i2c->cr, cr); + } + i2c_out(&ccsr_i2c->sr, I2C_SR_IF); + buf[i] = i2c_in(&ccsr_i2c->dr); + } + + return 0; +} + +static int write_data(struct ls_i2c *ccsr_i2c, unsigned char chip, + const unsigned char *buf, int len) +{ + int i; + int ret; + + for (i = 0; i < len; i++) { + ret = tx_byte(ccsr_i2c, buf[i]); + if (ret < 0) { + break; + } + } + ret = gen_stop(ccsr_i2c); + + return ret; +} + + +int i2c_read(unsigned char chip, int addr, int alen, + unsigned char *buf, int len) +{ + int ret; + unsigned char cr; + struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; + + ret = i2c_write_addr(ccsr_i2c, chip, addr, alen); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + + cr = i2c_in(&ccsr_i2c->cr); + cr |= I2C_CR_RSTA; + i2c_out(&ccsr_i2c->cr, cr); + + ret = tx_byte(ccsr_i2c, (chip << 1) | 1); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + + return read_data(ccsr_i2c, chip, buf, len); +} + +int i2c_write(unsigned char chip, int addr, int alen, + const unsigned char *buf, int len) +{ + int ret; + struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; + + ret = i2c_write_addr(ccsr_i2c, chip, addr, alen); + if (ret < 0) { + return ret; + } + + return write_data(ccsr_i2c, chip, buf, len); +} + +int i2c_probe_chip(unsigned char chip) +{ + int ret; + struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; + + ret = i2c_write_addr(ccsr_i2c, chip, 0, 0); + if (ret < 0) { + WARN("write addr failed\n"); + return ret; + } + + ret = gen_stop(ccsr_i2c); + if (ret < 0) { + WARN("I2C: Probe not complete.\n"); + } + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/i2c/i2c.mk b/arm-trusted-firmware/drivers/nxp/i2c/i2c.mk new file mode 100644 index 0000000..716e14a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/i2c/i2c.mk @@ -0,0 +1,25 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_I2C},) + +ADD_I2C := 1 + +I2C_SOURCES += $(PLAT_DRIVERS_PATH)/i2c/i2c.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/i2c + +ifeq (${BL_COMM_I2C_NEEDED},yes) +BL_COMMON_SOURCES += ${I2C_SOURCES} +else +ifeq (${BL2_I2C_NEEDED},yes) +BL2_SOURCES += ${I2C_SOURCES} +endif +ifeq (${BL31_I2C_NEEDED},yes) +BL31_SOURCES += ${I2C_SOURCES} +endif +endif +endif diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h new file mode 100644 index 0000000..56c5f92 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h @@ -0,0 +1,329 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IFC_H +#define IFC_H + +#include + +#include + +#define NXP_IFC_RUN_TIME_ADDR U(0x1000) + +/* CPSR - Chip Select Property Register Offset */ +#define EXT_CSPR(n) (U(0x000C) + (n * 0xC)) +#define CSPR(n) (U(0x0010) + (n * 0xC)) +#define CSOR(n) (U(0x0130) + (n * 0xC)) +#define EXT_CSOR(n) (U(0x0134) + (n * 0xC)) +#define IFC_AMASK_CS0 U(0x00A0) + +/* NAND specific Registers Offset */ +#define NCFGR (NXP_IFC_RUN_TIME_ADDR + U(0x0000)) +#define NAND_FCR0 (NXP_IFC_RUN_TIME_ADDR + U(0x0014)) + +#define ROW0 (NXP_IFC_RUN_TIME_ADDR + U(0x003C)) +#define ROW1 (NXP_IFC_RUN_TIME_ADDR + U(0x004C)) +#define COL0 (NXP_IFC_RUN_TIME_ADDR + U(0x0044)) +#define COL1 (NXP_IFC_RUN_TIME_ADDR + U(0x0054)) + +#define NAND_BC (NXP_IFC_RUN_TIME_ADDR + U(0x0108)) +#define NAND_FIR0 (NXP_IFC_RUN_TIME_ADDR + U(0x0110)) +#define NAND_FIR1 (NXP_IFC_RUN_TIME_ADDR + U(0x0114)) +#define NAND_FIR2 (NXP_IFC_RUN_TIME_ADDR + U(0x0118)) +#define NAND_CSEL (NXP_IFC_RUN_TIME_ADDR + U(0x015C)) +#define NANDSEQ_STRT (NXP_IFC_RUN_TIME_ADDR + U(0x0164)) +#define NAND_EVTER_STAT (NXP_IFC_RUN_TIME_ADDR + U(0x016C)) +#define NAND_AUTOBOOT_TRGR (NXP_IFC_RUN_TIME_ADDR + U(0x0284)) + +/* Size of SRAM Buffer */ +#define CSPR_PS U(0x00000180) +#define CSPR_PS_SHIFT 7 +#define CSPR_PS_8 0x1 // Port Size 8 bit +#define CSPR_PS_16 0x2 // Port Size 16 bit +#define CSPR_PS_32 0x3 // Port Size 32 bit + +/* Chip Select Option Register NAND Machine */ +#define CSOR_NAND_PGS U(0x00380000) +#define CSOR_NAND_PGS_SHIFT 19 +#define CSOR_NAND_PGS_512 U(0x00000000) +#define CSOR_NAND_PGS_2K U(0x00080000) +#define CSOR_NAND_PGS_4K U(0x00100000) +#define CSOR_NAND_PGS_8K U(0x00180000) +#define CSOR_NAND_PGS_16K U(0x00200000) + + +#define CSOR_NAND_PB U(0x00000700) +#define CSOR_NAND_PB_32 U(0x00000000) +#define CSOR_NAND_PB_64 U(0x00000100) +#define CSOR_NAND_PB_128 U(0x00000200) +#define CSOR_NAND_PB_256 U(0x00000300) +#define CSOR_NAND_PB_512 U(0x00000400) +#define CSOR_NAND_PB_1024 U(0x00000500) +#define CSOR_NAND_PB_2048 U(0x00000600) +#define CSOR_NAND_PPB_32 32 +#define CSOR_NAND_PPB_64 64 +#define CSOR_NAND_PPB_128 128 +#define CSOR_NAND_PPB_256 256 +#define CSOR_NAND_PPB_512 512 +#define CSOR_NAND_PPB_1024 1024 +#define CSOR_NAND_PPB_2048 2048 + +/* NAND Chip select register */ +#define NAND_CSEL_SHIFT 26 +#define NAND_COL_MS_SHIFT 31 + +/* FCR - Flash Command Register */ +#define FCR_CMD0 U(0xFF000000) +#define FCR_CMD0_SHIFT 24 +#define FCR_CMD1 U(0x00FF0000) +#define FCR_CMD1_SHIFT 16 +#define FCR_CMD2 U(0x0000FF00) +#define FCR_CMD2_SHIFT 8 +#define FCR_CMD3 U(0x000000FF) +#define FCR_CMD3_SHIFT 0 + +/* FIR - Flash Instruction Register Opcode */ +#define FIR_OP0 U(0xFC000000) +#define FIR_OP0_SHIFT 26 +#define FIR_OP1 U(0x03F00000) +#define FIR_OP1_SHIFT 20 +#define FIR_OP2 U(0x000FC000) +#define FIR_OP2_SHIFT 14 +#define FIR_OP3 U(0x00003F00) +#define FIR_OP3_SHIFT 8 +#define FIR_OP4 U(0x000000FC) +#define FIR_OP4_SHIFT 2 +#define FIR_OP5 U(0xFC000000) +#define FIR_OP5_SHIFT 26 +#define FIR_OP6 U(0x03F00000) +#define FIR_OP6_SHIFT 20 + +/* Instruction Opcode - 6 bits */ +#define FIR_OP_NOP 0x00 +#define FIR_OP_CA0 0x01 /* Issue current column address */ +#define FIR_OP_CA1 0x02 /* Issue current column address */ +#define FIR_OP_RA0 0x05 /* Issue current column address */ +#define FIR_OP_RA1 0x06 /* Issue current column address */ +#define FIR_OP_CMD0 0x09 /* Issue command from FCR[CMD0] */ +#define FIR_OP_CMD1 0x0a /* Issue command from FCR[CMD1] */ +#define FIR_OP_CMD2 0x0b /* Issue command from FCR[CMD2] */ +#define FIR_OP_CMD3 0x0c /* Issue command from FCR[CMD3] */ +#define FIR_OP_CW0 0x11 /* Wait then issue FCR[CMD0] */ +#define FIR_OP_CW1 0x12 /* Wait then issue FCR[CMD1] */ +#define FIR_OP_CW2 0x13 /* Wait then issue FCR[CMD1] */ +#define FIR_OP_CW3 0x14 /* Wait then issue FCR[CMD1] */ +#define FIR_OP_WBCD 0x19 /* Wait then read FBCR bytes */ +#define FIR_OP_RBCD 0x1a /* Wait then read 1 or 2 bytes */ +#define FIR_OP_BTRD 0x1b /* Wait then read 1 or 2 bytes */ +#define FIR_OP_RDSTAT 0x1c /* Wait then read 1 or 2 bytes */ +#define FIR_OP_NWAIT 0x1d /* Wait then read 1 or 2 bytes */ +#define FIR_OP_WFR 0x1e /* Wait then read 1 or 2 bytes */ + +#define NAND_SEQ_STRT_FIR_STRT U(0x80000000) +#define NAND_SEQ_STRT_FIR_STRT_SHIFT 31 + +#define NAND_EVTER_STAT_FTOER U(0x08000000) +#define NAND_EVTER_STAT_WPER U(0x04000000) +#define NAND_EVTER_STAT_ECCER U(0x02000000) +#define NAND_EVTER_STAT_DQSER U(0x01000000) +#define NAND_EVTER_STAT_RCW_DN U(0x00008000) +#define NAND_EVTER_STAT_BOOT_DN U(0x00004000) +#define NAND_EVTER_STAT_RCW_DN U(0x00008000) +#define NAND_EVTER_STAT_OPC_DN U(0x80000000) +#define NAND_EVTER_STAT_BBI_SRCH_SEL U(0x00000800) +#define NCFGR_BOOT U(0x80000000) +#define NAND_AUTOBOOT_TRGR_RCW_LD U(0x80000000) +#define NAND_AUTOBOOT_TRGR_BOOT_LD U(0x20000000) + +/* ECC ERROR STATUS Registers */ +#define NAND_RCW_LD U(0x80000000) +#define NAND_BOOT_LD U(0x20000000) + +/*Other Temp Defines */ +/*256 bad Blocks supported */ +#define BBT_SIZE 256 + +/*Standard NAND flash commands */ +#define NAND_CMD_READ0 0 +#define NAND_CMD_READ1 1 +#define NAND_CMD_READOOB 0x50 + +/*Extended commands for large page devices */ +#define NAND_CMD_READSTART 0x30 + +#define NAND_TIMEOUT_MS 40 + +#define EMPTY_VAL_CHECK U(0xFFFFFFFF) +#define EMPTY_VAL 0xFF + + +#define MAIN 0 +#define SPARE 1 + +#define GOOD_BLK 1 +#define BAD_BLK 0 +#define DIV_2 2 + +#define ATTRIBUTE_PGSZ 0xa +#define ATTRIBUTE_PPB 0xb + +#define CSPR_PORT_SIZE_8 (0x1 << 7) +#define CSPR_PORT_SIZE_16 (0x2 << 7) +#define CSPR_PORT_SIZE_32 (0x3 << 7) + +/* NAND specific */ +#define RCW_SRC_NAND_PORT_MASK U(0x00000080) + +#define NAND_DEFAULT_CSPR U(0x00000053) +#define NAND_DEFAULT_CSOR U(0x0180C00C) +#define NAND_DEFAULT_EXT_CSPR U(0x00000000) +#define NAND_DEFAULT_EXT_CSOR U(0x00000000) +#define NAND_DEFAULT_FTIM0 U(0x181c0c10) +#define NAND_DEFAULT_FTIM1 U(0x5454141e) +#define NAND_DEFAULT_FTIM2 U(0x03808034) +#define NAND_DEFAULT_FTIM3 U(0x2c000000) + +#define NAND_CSOR_ECC_MODE_DISABLE U(0x00000000) +#define NAND_CSOR_ECC_MODE0 U(0x84000000) +#define NAND_CSOR_ECC_MODE1 U(0x94000000) +#define NAND_CSOR_ECC_MODE2 U(0xa4000000) +#define NAND_CSOR_ECC_MODE3 U(0xb4000000) +#define NAND_CSOR_PAGE_SIZE_2K (0x1 << 19) +#define NAND_CSOR_PAGE_SIZE_4K (0x2 << 19) +#define NAND_CSOR_PAGE_SIZE_8K (0x3 << 19) +#define NAND_CSOR_PAGE_SIZE_16K (0x4 << 19) +#define NAND_CSOR_PPB_64 (0x1 << 8) +#define NAND_CSOR_PPB_128 (0x2 << 8) +#define NAND_CSOR_PPB_256 (0x3 << 8) +#define NAND_CSOR_PPB_512 (0x4 << 8) + +/* BBI INDICATOR for NAND_2K(CFG_RCW_SRC[1]) for + * devices greater than 2K page size(CFG_RCW_SRC[3]) + */ +#define RCW_SRC_NAND_BBI_MASK U(0x00000008) +#define RCW_SRC_NAND_BBI_MASK_NAND_2K U(0x00000002) +#define NAND_BBI_ONFI_2K (0x1 << 1) +#define NAND_BBI_ONFI (0x1 << 3) + +#define RCW_SRC_NAND_PAGE_MASK U(0x00000070) +#define RCW_SRC_NAND_PAGE_MASK_NAND_2K U(0x0000000C) +#define NAND_2K_XXX 0x00 +#define NAND_2K_64 0x04 +#define NAND_2K_128 0x08 +#define NAND_4K_128 0x10 +#define NAND_4K_256 0x20 +#define NAND_4K_512 0x30 +#define NAND_8K_128 0x40 +#define NAND_8K_256 0x50 +#define NAND_8K_512 0x60 +#define NAND_16K_512 0x70 +#define BLOCK_LEN_2K 2048 + +#define RCW_SRC_NAND_ECC_MASK U(0x00000007) +#define RCW_SRC_NAND_ECC_MASK_NAND_2K U(0x00000001) +#define NAND_ECC_DISABLE 0x0 +#define NAND_ECC_4_520 0x1 +#define NAND_ECC_8_528 0x5 +#define NAND_ECC_24_1K 0x6 +#define NAND_ECC_40_1K 0x7 + +#define NAND_SPARE_2K U(0x00000040) +#define NAND_SPARE_4K_ECC_M0 U(0x00000080) +#define NAND_SPARE_4K_ECC_M1 U(0x000000D2) +#define NAND_SPARE_4K_ECC_M2 U(0x000000B0) +#define NAND_SPARE_4K_ECC_M3 U(0x00000120) +#define NAND_SPARE_8K_ECC_M0 U(0x00000088) +#define NAND_SPARE_8K_ECC_M1 U(0x00000108) +#define NAND_SPARE_8K_ECC_M2 U(0x00000158) +#define NAND_SPARE_8K_ECC_M3 U(0x00000238) +#define NAND_SPARE_16K_ECC_M0 U(0x00000108) +#define NAND_SPARE_16K_ECC_M1 U(0x00000208) +#define NAND_SPARE_16K_ECC_M2 U(0x000002A8) +#define NAND_SPARE_16K_ECC_M3 U(0x00000468) + +struct nand_info { + uintptr_t ifc_register_addr; + uintptr_t ifc_region_addr; + uint32_t page_size; + uint32_t port_size; + uint32_t blk_size; + uint32_t ppb; + uint32_t pi_width; /* Bits Required to index a page in block */ + uint32_t ral; + uint32_t ibr_flow; + uint32_t bbt[BBT_SIZE]; + uint32_t lgb; /* Last Good Block */ + uint32_t bbt_max; /* Total entries in bbt */ + uint32_t bzero_good; + uint8_t bbs; + uint8_t bad_marker_loc; + uint8_t onfi_dev_flag; + uint8_t init_time_boot_flag; + uint8_t *buf; +}; + +struct ifc_regs { + uint32_t ext_cspr; + uint32_t cspr; + uint32_t csor; + uint32_t ext_csor; +}; + +struct sec_nand_info { + uint32_t cspr_port_size; + uint32_t csor_ecc_mode; + uint32_t csor_page_size; + uint32_t csor_ppb; + uint32_t ext_csor_spare_size; + uint32_t onfi_flag; +}; + +struct sec_nor_info { + uint32_t cspr_port_size; + uint32_t csor_nor_mode; + uint32_t csor_adm_shift; + uint32_t port_size; + uint32_t addr_bits; +}; + +enum ifc_chip_sel { + IFC_CS0, + IFC_CS1, + IFC_CS2, + IFC_CS3, + IFC_CS4, + IFC_CS5, + IFC_CS6, + IFC_CS7, +}; + +enum ifc_ftims { + IFC_FTIM0, + IFC_FTIM1, + IFC_FTIM2, + IFC_FTIM3, +}; + +#ifdef NXP_IFC_BE +#define nand_in32(a) bswap32(mmio_read_32((uintptr_t)a)) +#define nand_out32(a, v) mmio_write_32((uintptr_t)a, bswap32(v)) +#else +#define nand_in32(a) mmio_read_32((uintptr_t)a) +#define nand_out32(a, v) mmio_write_32((uintptr_t)a, v) +#endif + +/* Read Write on IFC registers */ +static inline void write_reg(struct nand_info *nand, uint32_t reg, uint32_t val) +{ + nand_out32(nand->ifc_register_addr + reg, val); +} + +static inline uint32_t read_reg(struct nand_info *nand, uint32_t reg) +{ + return nand_in32(nand->ifc_register_addr + reg); +} + +#endif /* IFC_H */ diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c new file mode 100644 index 0000000..1f7092a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c @@ -0,0 +1,658 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include "ifc.h" +#include +#include + +/* Private structure for NAND driver data */ +static struct nand_info nand_drv_data; + +static int update_bbt(uint32_t idx, uint32_t blk, uint32_t *updated, + struct nand_info *nand); + +static int nand_wait(struct nand_info *nand) +{ + int timeout = 1; + uint32_t neesr; + unsigned long start_time; + + start_time = get_timer_val(0); + + while (get_timer_val(start_time) < NAND_TIMEOUT_MS) { + /* clear the OPC event */ + neesr = read_reg(nand, NAND_EVTER_STAT); + if (neesr & NAND_EVTER_STAT_OPC_DN) { + write_reg(nand, NAND_EVTER_STAT, neesr); + timeout = 0; + + /* check for other errors */ + if (neesr & NAND_EVTER_STAT_FTOER) { + ERROR("%s NAND_EVTER_STAT_FTOER occurs\n", + __func__); + return -1; + } else if (neesr & NAND_EVTER_STAT_ECCER) { + ERROR("%s NAND_EVTER_STAT_ECCER occurs\n", + __func__); + return -1; + } else if (neesr & NAND_EVTER_STAT_DQSER) { + ERROR("%s NAND_EVTER_STAT_DQSER occurs\n", + __func__); + return -1; + } + + break; + } + } + + if (timeout) { + ERROR("%s ERROR_NAND_TIMEOUT occurs\n", __func__); + return -1; + } + + return 0; +} + +static uint32_t nand_get_port_size(struct nand_info *nand) +{ + uint32_t port_size = U(0); + uint32_t cs_reg; + uint32_t cur_cs; + + cur_cs = U(0); + cs_reg = CSPR(cur_cs); + port_size = (read_reg(nand, cs_reg) & CSPR_PS) >> CSPR_PS_SHIFT; + switch (port_size) { + case CSPR_PS_8: + port_size = U(8); + break; + case CSPR_PS_16: + port_size = U(16); + break; + case CSPR_PS_32: + port_size = U(32); + break; + default: + port_size = U(8); + } + + return port_size; +} + +static uint32_t nand_get_page_size(struct nand_info *nand) +{ + uint32_t pg_size; + uint32_t cs_reg; + uint32_t cur_cs; + + cur_cs = 0; + cs_reg = CSOR(cur_cs); + pg_size = read_reg(nand, cs_reg) & CSOR_NAND_PGS; + switch (pg_size) { + case CSOR_NAND_PGS_2K: + pg_size = U(2048); + break; + case CSOR_NAND_PGS_4K: + pg_size = U(4096); + break; + case CSOR_NAND_PGS_8K: + pg_size = U(8192); + break; + case CSOR_NAND_PGS_16K: + pg_size = U(16384); + break; + default: + pg_size = U(512); + } + + return pg_size; +} + +static uint32_t nand_get_pages_per_blk(struct nand_info *nand) +{ + uint32_t pages_per_blk; + uint32_t cs_reg; + uint32_t cur_cs; + + cur_cs = 0; + cs_reg = CSOR(cur_cs); + pages_per_blk = (read_reg(nand, cs_reg) & CSOR_NAND_PB); + switch (pages_per_blk) { + case CSOR_NAND_PB_32: + pages_per_blk = U(32); + break; + case CSOR_NAND_PB_64: + pages_per_blk = U(64); + break; + case CSOR_NAND_PB_128: + pages_per_blk = U(128); + break; + case CSOR_NAND_PB_256: + pages_per_blk = U(256); + break; + case CSOR_NAND_PB_512: + pages_per_blk = U(512); + break; + case CSOR_NAND_PB_1024: + pages_per_blk = U(1024); + break; + case CSOR_NAND_PB_2048: + pages_per_blk = U(2048); + break; + default: + pages_per_blk = U(0); + } + + return pages_per_blk; +} + +static uint32_t get_page_index_width(uint32_t ppb) +{ + switch (ppb) { + case CSOR_NAND_PPB_32: + return U(5); + case CSOR_NAND_PPB_64: + return U(6); + case CSOR_NAND_PPB_128: + return U(7); + case CSOR_NAND_PPB_256: + return U(8); + case CSOR_NAND_PPB_512: + return U(9); + case CSOR_NAND_PPB_1024: + return U(10); + case CSOR_NAND_PPB_2048: + return U(11); + default: + return U(5); + } +} + +static void nand_get_params(struct nand_info *nand) +{ + nand->port_size = nand_get_port_size(nand); + + nand->page_size = nand_get_page_size(nand); + + /* + * Set Bad marker Location for LP / SP + * Small Page : 8 Bit : 0x5 + * Small Page : 16 Bit : 0xa + * Large Page : 8 /16 Bit : 0x0 + */ + nand->bad_marker_loc = (nand->page_size == 512) ? + ((nand->port_size == 8) ? 0x5 : 0xa) : 0; + + /* check for the device is ONFI compliant or not */ + nand->onfi_dev_flag = + (read_reg(nand, NAND_EVTER_STAT) & NAND_EVTER_STAT_BBI_SRCH_SEL) + ? 1 : 0; + + /* NAND Blk serached count for incremental Bad block search cnt */ + nand->bbs = 0; + + /* pages per Block */ + nand->ppb = nand_get_pages_per_blk(nand); + + /* Blk size */ + nand->blk_size = nand->page_size * nand->ppb; + + /* get_page_index_width */ + nand->pi_width = get_page_index_width(nand->ppb); + + /* bad block table init */ + nand->lgb = 0; + nand->bbt_max = 0; + nand->bzero_good = 0; + memset(nand->bbt, EMPTY_VAL, BBT_SIZE * sizeof(nand->bbt[0])); +} + +static int nand_init(struct nand_info *nand) +{ + uint32_t ncfgr = 0; + + /* Get nand Parameters from IFC */ + nand_get_params(nand); + + /* Clear all errors */ + write_reg(nand, NAND_EVTER_STAT, U(0xffffffff)); + + /* + * Disable autoboot in NCFGR. Mapping will change from + * physical to logical for SRAM buffer + */ + ncfgr = read_reg(nand, NCFGR); + write_reg(nand, NCFGR, (ncfgr & ~NCFGR_BOOT)); + + return 0; +} + +static int nand_read_data( + uintptr_t ifc_region_addr, + uint32_t row_add, + uint32_t col_add, + uint32_t byte_cnt, + uint8_t *data, + uint32_t main_spare, + struct nand_info *nand) +{ + uint32_t page_size_add_bits = U(0); + uint32_t page_add_in_actual, page_add; + uintptr_t sram_addr_calc; + int ret; + uint32_t col_val; + + /* Programming MS bit to read from spare area.*/ + col_val = (main_spare << NAND_COL_MS_SHIFT) | col_add; + + write_reg(nand, NAND_BC, byte_cnt); + + write_reg(nand, ROW0, row_add); + write_reg(nand, COL0, col_val); + + /* Program FCR for small Page */ + if (nand->page_size == U(512)) { + if (byte_cnt == 0 || + (byte_cnt != 0 && main_spare == 0 && col_add <= 255)) { + write_reg(nand, NAND_FCR0, + (NAND_CMD_READ0 << FCR_CMD0_SHIFT)); + } else if (main_spare == 0) { + write_reg(nand, NAND_FCR0, + (NAND_CMD_READ1 << FCR_CMD0_SHIFT)); + } else { + write_reg(nand, NAND_FCR0, + (NAND_CMD_READOOB << FCR_CMD0_SHIFT)); + } + + } else { + /* Program FCR for Large Page */ + write_reg(nand, NAND_FCR0, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | + (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); + } + if (nand->page_size == U(512)) { + write_reg(nand, NAND_FIR0, ((FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA0 << FIR_OP1_SHIFT) | + (FIR_OP_RA0 << FIR_OP2_SHIFT) | + (FIR_OP_BTRD << FIR_OP3_SHIFT) | + (FIR_OP_NOP << FIR_OP4_SHIFT))); + write_reg(nand, NAND_FIR1, U(0x00000000)); + } else { + write_reg(nand, NAND_FIR0, ((FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA0 << FIR_OP1_SHIFT) | + (FIR_OP_RA0 << FIR_OP2_SHIFT) | + (FIR_OP_CMD1 << FIR_OP3_SHIFT) | + (FIR_OP_BTRD << FIR_OP4_SHIFT))); + + write_reg(nand, NAND_FIR1, (FIR_OP_NOP << FIR_OP5_SHIFT)); + } + write_reg(nand, NANDSEQ_STRT, NAND_SEQ_STRT_FIR_STRT); + + ret = nand_wait(nand); + if (ret != 0) + return ret; + + /* calculate page_size_add_bits i.e bits + * in sram address corresponding to area + * within a page for sram + */ + if (nand->page_size == U(512)) + page_size_add_bits = U(10); + else if (nand->page_size == U(2048)) + page_size_add_bits = U(12); + else if (nand->page_size == U(4096)) + page_size_add_bits = U(13); + else if (nand->page_size == U(8192)) + page_size_add_bits = U(14); + else if (nand->page_size == U(16384)) + page_size_add_bits = U(15); + + page_add = row_add; + + page_add_in_actual = (page_add << page_size_add_bits) & U(0x0000FFFF); + + if (byte_cnt == 0) + col_add = U(0); + + /* Calculate SRAM address for main and spare area */ + if (main_spare == 0) + sram_addr_calc = ifc_region_addr | page_add_in_actual | col_add; + else + sram_addr_calc = ifc_region_addr | page_add_in_actual | + (col_add + nand->page_size); + + /* Depending Byte_count copy full page or partial page from SRAM */ + if (byte_cnt == 0) + memcpy(data, (void *)sram_addr_calc, + nand->page_size); + else + memcpy(data, (void *)sram_addr_calc, byte_cnt); + + return 0; +} + +static int nand_read(struct nand_info *nand, int32_t src_addr, + uintptr_t dst, uint32_t size) +{ + uint32_t log_blk = U(0); + uint32_t pg_no = U(0); + uint32_t col_off = U(0); + uint32_t row_off = U(0); + uint32_t byte_cnt = U(0); + uint32_t read_cnt = U(0); + uint32_t i = U(0); + uint32_t updated = U(0); + + int ret = 0; + uint8_t *out = (uint8_t *)dst; + + uint32_t pblk; + + /* loop till size */ + while (size) { + log_blk = (src_addr / nand->blk_size); + pg_no = ((src_addr - (log_blk * nand->blk_size)) / + nand->page_size); + pblk = log_blk; + + // iterate the bbt to find the block + for (i = 0; i <= nand->bbt_max; i++) { + if (nand->bbt[i] == EMPTY_VAL_CHECK) { + ret = update_bbt(i, pblk, &updated, nand); + + if (ret != 0) + return ret; + /* + * if table not updated and we reached + * end of table + */ + if (!updated) + break; + } + + if (pblk < nand->bbt[i]) + break; + else if (pblk >= nand->bbt[i]) + pblk++; + } + + col_off = (src_addr % nand->page_size); + if (col_off) { + if ((col_off + size) < nand->page_size) + byte_cnt = size; + else + byte_cnt = nand->page_size - col_off; + + row_off = (pblk << nand->pi_width) | pg_no; + + ret = nand_read_data( + nand->ifc_region_addr, + row_off, + col_off, + byte_cnt, out, MAIN, nand); + + if (ret != 0) + return ret; + } else { + /* + * fullpage/Partial Page + * if byte_cnt = 0 full page + * else partial page + */ + if (size < nand->page_size) { + byte_cnt = size; + read_cnt = size; + } else { + byte_cnt = nand->page_size; + read_cnt = 0; + } + row_off = (pblk << nand->pi_width) | pg_no; + + ret = nand_read_data( + nand->ifc_region_addr, + row_off, + 0, + read_cnt, out, MAIN, nand); + + if (ret != 0) { + ERROR("Error from nand-read_data %d\n", ret); + return ret; + } + } + src_addr += byte_cnt; + out += byte_cnt; + size -= byte_cnt; + } + return 0; +} + +static int isgoodblock(uint32_t blk, uint32_t *gb, struct nand_info *nand) +{ + uint8_t buf[2]; + int ret; + uint32_t row_add; + + *gb = 0; + + /* read Page 0 of blk */ + ret = nand_read_data( + nand->ifc_region_addr, + blk << nand->pi_width, + nand->bad_marker_loc, + 0x2, buf, 1, nand); + + if (ret != 0) + return ret; + + /* For ONFI devices check Page 0 and Last page of block for + * Bad Marker and for NON-ONFI Page 0 and 1 for Bad Marker + */ + row_add = (blk << nand->pi_width); + if (nand->port_size == 8) { + /* port size is 8 Bit */ + /* check if page 0 has 0xff */ + if (buf[0] == 0xff) { + /* check page 1 */ + if (nand->onfi_dev_flag) + ret = nand_read_data( + nand->ifc_region_addr, + row_add | (nand->ppb - 1), + nand->bad_marker_loc, + 0x2, buf, SPARE, nand); + else + ret = nand_read_data( + nand->ifc_region_addr, + row_add | 1, + nand->bad_marker_loc, + 0x2, buf, SPARE, nand); + + if (ret != 0) + return ret; + + if (buf[0] == 0xff) + *gb = GOOD_BLK; + else + *gb = BAD_BLK; + } else { + /* no, so it is bad blk */ + *gb = BAD_BLK; + } + } else { + /* Port size 16-Bit */ + /* check if page 0 has 0xffff */ + if ((buf[0] == 0xff) && + (buf[1] == 0xff)) { + /* check page 1 for 0xffff */ + if (nand->onfi_dev_flag) { + ret = nand_read_data( + nand->ifc_region_addr, + row_add | (nand->ppb - 1), + nand->bad_marker_loc, + 0x2, buf, SPARE, nand); + } else { + ret = nand_read_data( + nand->ifc_region_addr, + row_add | 1, + nand->bad_marker_loc, + 0x2, buf, SPARE, nand); + } + + if (ret != 0) + return ret; + + if ((buf[0] == 0xff) && + (buf[1] == 0xff)) { + *gb = GOOD_BLK; + } else { + *gb = BAD_BLK; + } + } else { + /* no, so it is bad blk */ + *gb = BAD_BLK; + } + } + return 0; +} + +static int update_bbt(uint32_t idx, uint32_t blk, + uint32_t *updated, struct nand_info *nand) +{ + uint32_t sblk; + uint32_t lgb; + int ret; + + if (nand->bzero_good && blk == 0) + return 0; + + /* special case for lgb == 0 */ + /* if blk <= lgb retrun */ + if (nand->lgb != 0 && blk <= nand->lgb) + return 0; + + *updated = 0; + + /* if blk is more than lgb, iterate from lgb till a good block + * is found for blk + */ + + if (nand->lgb < blk) + sblk = nand->lgb; + else + /* this is when lgb = 0 */ + sblk = blk; + + + lgb = nand->lgb; + + /* loop from blk to find a good block */ + while (1) { + while (lgb <= sblk) { + uint32_t gb = 0; + + ret = isgoodblock(lgb, &gb, nand); + if (ret != 0) + return ret; + + /* special case block 0 is good then set this flag */ + if (lgb == 0 && gb == GOOD_BLK) + nand->bzero_good = 1; + + if (gb == BAD_BLK) { + if (idx >= BBT_SIZE) { + ERROR("NAND BBT Table full\n"); + return -1; + } + *updated = 1; + nand->bbt[idx] = lgb; + idx++; + blk++; + sblk++; + if (idx > nand->bbt_max) + nand->bbt_max = idx; + } + lgb++; + } + /* the access block found */ + if (sblk == blk) { + /* when good block found update lgb */ + nand->lgb = blk; + break; + } + sblk++; + } + + return 0; +} + +static size_t ifc_nand_read(int lba, uintptr_t buf, size_t size) +{ + int ret; + uint32_t page_size; + uint32_t src_addr; + struct nand_info *nand = &nand_drv_data; + + page_size = nand_get_page_size(nand); + src_addr = lba * page_size; + ret = nand_read(nand, src_addr, buf, size); + return ret ? 0 : size; +} + +static struct io_block_dev_spec ifc_nand_spec = { + .buffer = { + .offset = 0, + .length = 0, + }, + .ops = { + .read = ifc_nand_read, + }, + /* + * Default block size assumed as 2K + * Would be updated based on actual size + */ + .block_size = UL(2048), +}; + +int ifc_nand_init(uintptr_t *block_dev_spec, + uintptr_t ifc_region_addr, + uintptr_t ifc_register_addr, + size_t ifc_sram_size, + uintptr_t ifc_nand_blk_offset, + size_t ifc_nand_blk_size) +{ + struct nand_info *nand = NULL; + int ret; + + nand = &nand_drv_data; + memset(nand, 0, sizeof(struct nand_info)); + + nand->ifc_region_addr = ifc_region_addr; + nand->ifc_register_addr = ifc_register_addr; + + VERBOSE("nand_init\n"); + ret = nand_init(nand); + if (ret) { + ERROR("nand init failed\n"); + return ret; + } + + ifc_nand_spec.buffer.offset = ifc_nand_blk_offset; + ifc_nand_spec.buffer.length = ifc_nand_blk_size; + + ifc_nand_spec.block_size = nand_get_page_size(nand); + + VERBOSE("Page size is %ld\n", ifc_nand_spec.block_size); + + *block_dev_spec = (uintptr_t)&ifc_nand_spec; + + /* Adding NAND SRAM< Buffer in XLAT Table */ + mmap_add_region(ifc_region_addr, ifc_region_addr, + ifc_sram_size, MT_DEVICE | MT_RW); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.mk b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.mk new file mode 100644 index 0000000..890fd23 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.mk @@ -0,0 +1,29 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${NAND_ADDED},) + +NAND_ADDED := 1 + +NAND_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/ifc/nand + +NAND_SOURCES := $(NAND_DRIVERS_PATH)/ifc_nand.c \ + drivers/io/io_block.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/ifc + +ifeq (${BL_COMM_IFC_NAND_NEEDED},yes) +BL_COMMON_SOURCES += ${NAND_SOURCES} +else +ifeq (${BL2_IFC_NAND_NEEDED},yes) +BL2_SOURCES += ${NAND_SOURCES} +endif +ifeq (${BL31_IFC_NAND_NEEDED},yes) +BL31_SOURCES += ${NAND_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c b/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c new file mode 100644 index 0000000..24fc308 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c @@ -0,0 +1,18 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include +#include + +#include + +int ifc_nor_init(uintptr_t flash_addr, size_t flash_size) +{ + /* Adding NOR Memory Map in XLAT Table */ + mmap_add_region(flash_addr, flash_addr, flash_size, MT_MEMORY | MT_RW); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.mk b/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.mk new file mode 100644 index 0000000..0022a81 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.mk @@ -0,0 +1,28 @@ +# +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${NOR_ADDED},) + +NOR_ADDED := 1 + +NOR_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/ifc/nor + +NOR_SOURCES := $(NOR_DRIVERS_PATH)/ifc_nor.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/ifc + +ifeq (${BL_COMM_IFC_NOR_NEEDED},yes) +BL_COMMON_SOURCES += ${NOR_SOURCES} +else +ifeq (${BL2_IFC_NOR_NEEDED},yes) +BL2_SOURCES += ${NOR_SOURCES} +endif +ifeq (${BL31_IFC_NOR_NEEDED},yes) +BL31_SOURCES += ${NOR_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/interconnect/interconnect.mk b/arm-trusted-firmware/drivers/nxp/interconnect/interconnect.mk new file mode 100644 index 0000000..aa51be4 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/interconnect/interconnect.mk @@ -0,0 +1,44 @@ +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the Interconnect files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_INTERCONNECT},) + +ADD_INTERCONNECT := 1 +PLAT_INCLUDES += -I${PLAT_DRIVERS_INCLUDE_PATH}/interconnect + +ifeq (, $(filter $(INTERCONNECT), CCI400 CCN502 CCN504 CCN508)) + $(error -> Interconnect type not set!) +else +$(eval $(call add_define_val,INTERCONNECT,${INTERCONNECT})) +ifeq ($(INTERCONNECT), $(filter $(INTERCONNECT), CCN502 CCN504 CCN508)) +INTERCONNECT_SOURCES := drivers/arm/ccn/ccn.c \ + ${PLAT_DRIVERS_PATH}/interconnect/ls_ccn.c +else +ifeq ($(INTERCONNECT), CCI400) +INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \ + ${PLAT_DRIVERS_PATH}/interconnect/ls_cci.c +endif +endif +endif + +ifeq (${BL_COMM_INTERCONNECT_NEEDED},yes) +BL_COMMON_SOURCES += ${INTERCONNECT_SOURCES} +else +ifeq (${BL2_INTERCONNECT_NEEDED},yes) +BL2_SOURCES += ${INTERCONNECT_SOURCES} +endif +ifeq (${BL31_INTERCONNECT_NEEDED},yes) +BL31_SOURCES += ${INTERCONNECT_SOURCES} +endif +endif +endif + +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c b/arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c new file mode 100644 index 0000000..72a898a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c @@ -0,0 +1,38 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way ARM CCI driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_arm_interconnect_enter_coherency +#pragma weak plat_arm_interconnect_exit_coherency + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_ls_interconnect_enter_coherency(unsigned int num_clusters) +{ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + for (uint32_t index = 1U; index < num_clusters; index++) { + cci_enable_snoop_dvm_reqs(index); + } +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_ls_interconnect_exit_coherency(void) +{ + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c b/arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c new file mode 100644 index 0000000..8f90325 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c @@ -0,0 +1,31 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_ls_interconnect_enter_coherency(unsigned int num_clusters) +{ + ccn_enter_snoop_dvm_domain(1ULL << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + for (uint32_t index = 1U; index < num_clusters; index++) { + ccn_enter_snoop_dvm_domain(1ULL << index); + } +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_ls_interconnect_exit_coherency(void) +{ + ccn_exit_snoop_dvm_domain(1ULL << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/drivers/nxp/pmu/pmu.c b/arm-trusted-firmware/drivers/nxp/pmu/pmu.c new file mode 100644 index 0000000..2a907c8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/pmu/pmu.c @@ -0,0 +1,45 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +void enable_timer_base_to_cluster(uintptr_t nxp_pmu_addr) +{ + uint32_t *cltbenr = NULL; + uint32_t cltbenr_val = 0U; + + cltbenr = (uint32_t *)(nxp_pmu_addr + + CLUST_TIMER_BASE_ENBL_OFFSET); + + cltbenr_val = mmio_read_32((uintptr_t)cltbenr); + + cltbenr_val = cltbenr_val + | (1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + mmio_write_32((uintptr_t)cltbenr, cltbenr_val); + + VERBOSE("Enable cluster time base\n"); +} + +/* + * Enable core timebase. In certain Layerscape SoCs, the clock for each core's + * has an enable bit in the PMU Physical Core Time Base Enable + * Register (PCTBENR), which allows the watchdog to operate. + */ + +void enable_core_tb(uintptr_t nxp_pmu_addr) +{ + uint32_t *pctbenr = (uint32_t *) (nxp_pmu_addr + + CORE_TIMEBASE_ENBL_OFFSET); + + mmio_write_32((uintptr_t)pctbenr, 0xff); +} diff --git a/arm-trusted-firmware/drivers/nxp/pmu/pmu.mk b/arm-trusted-firmware/drivers/nxp/pmu/pmu.mk new file mode 100644 index 0000000..8d2ef07 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/pmu/pmu.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${PMU_ADDED},) + +PMU_ADDED := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/pmu + +PMU_SOURCES += $(PLAT_DRIVERS_PATH)/pmu/pmu.c + +ifeq (${BL_COMM_PMU_NEEDED},yes) +BL_COMMON_SOURCES += ${PMU_SOURCES} +else +ifeq (${BL2_PMU_NEEDED},yes) +BL2_SOURCES += ${PMU_SOURCES} +endif +ifeq (${BL31_PMU_NEEDED},yes) +BL31_SOURCES += ${PMU_SOURCES} +endif +endif +endif +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/qspi/qspi.c b/arm-trusted-firmware/drivers/nxp/qspi/qspi.c new file mode 100644 index 0000000..97b2a19 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/qspi/qspi.c @@ -0,0 +1,29 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include + +int qspi_io_setup(uintptr_t nxp_qspi_flash_addr, + size_t nxp_qspi_flash_size, + uintptr_t fip_offset) +{ + uint32_t qspi_mcr_val = qspi_in32(CHS_QSPI_MCR); + + /* Enable and change endianness of QSPI IP */ + qspi_out32(CHS_QSPI_MCR, (qspi_mcr_val | CHS_QSPI_64LE)); + + /* Adding QSPI Memory Map in XLAT Table */ + mmap_add_region(nxp_qspi_flash_addr, nxp_qspi_flash_addr, + nxp_qspi_flash_size, MT_MEMORY | MT_RW); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/qspi/qspi.mk b/arm-trusted-firmware/drivers/nxp/qspi/qspi.mk new file mode 100644 index 0000000..450aeca --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/qspi/qspi.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${QSPI_ADDED},) + +QSPI_ADDED := 1 + +QSPI_SOURCES := $(PLAT_DRIVERS_PATH)/qspi/qspi.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/qspi + +ifeq (${BL_COMM_QSPI_NEEDED},yes) +BL_COMMON_SOURCES += ${QSPI_SOURCES} +else +ifeq (${BL2_QSPI_NEEDED},yes) +BL2_SOURCES += ${QSPI_SOURCES} +endif +ifeq (${BL31_QSPI_NEEDED},yes) +BL31_SOURCES += ${QSPI_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c b/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c new file mode 100644 index 0000000..f7f48e7 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c @@ -0,0 +1,1496 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include "nxp_timer.h" +#include "sd_mmc.h" +#include +#include + + +/* Private structure for MMC driver data */ +static struct mmc mmc_drv_data; + +#ifndef NXP_POLICY_OTA +/* + * For NXP_POLICY_OTA, SD needs to do R/W on OCRAM. OCRAM is secure memory at + * default. SD can only do non-secure DMA. Configuring SD to work in PIO mode + * instead of DMA mode will make SD R/W on OCRAM available. + */ +/* To debug without dma comment this MACRO */ +#define NXP_SD_DMA_CAPABILITY +#endif +#define SD_TIMEOUT 1000 /* ms */ +#define SD_TIMEOUT_HIGH 20000 /* ms */ +#define SD_BLOCK_TIMEOUT 8 /* ms */ + +#define ERROR_ESDHC_CARD_DETECT_FAIL -1 +#define ERROR_ESDHC_UNUSABLE_CARD -2 +#define ERROR_ESDHC_COMMUNICATION_ERROR -3 +#define ERROR_ESDHC_BLOCK_LENGTH -4 +#define ERROR_ESDHC_DMA_ERROR -5 +#define ERROR_ESDHC_BUSY -6 + +/*************************************************************** + * Function : set_speed + * Arguments : mmc - Pointer to mmc struct + * clock - Clock Value to be set + * Return : void + * Description : Calculates the value of SDCLKFS and DVS to be set + * for getting the required clock assuming the base_clk + * as a fixed value (MAX_PLATFORM_CLOCK) + *****************************************************************/ +static void set_speed(struct mmc *mmc, uint32_t clock) +{ + /* sdhc_clk = (base clock) / [(SDCLKFS × 2) × (DVS +1)] */ + + uint32_t dvs = 1U; + uint32_t sdclkfs = 2U; + /* TBD - Change this to actual platform clock by reading via RCW */ + uint32_t base_clk = MAX_PLATFORM_CLOCK; + + if (base_clk / 16 > clock) { + for (sdclkfs = 2U; sdclkfs < 256U; sdclkfs *= 2U) { + if ((base_clk / sdclkfs) <= (clock * 16)) { + break; + } + } + } + + for (dvs = 1U; dvs <= 16U; dvs++) { + if ((base_clk / (dvs * sdclkfs)) <= clock) { + break; + } + } + + sdclkfs >>= 1U; + dvs -= 1U; + + esdhc_out32(&mmc->esdhc_regs->sysctl, + (ESDHC_SYSCTL_DTOCV(TIMEOUT_COUNTER_SDCLK_2_27) | + ESDHC_SYSCTL_SDCLKFS(sdclkfs) | ESDHC_SYSCTL_DVS(dvs) | + ESDHC_SYSCTL_SDCLKEN)); +} + +/*************************************************************************** + * Function : esdhc_init + * Arguments : mmc - Pointer to mmc struct + * card_detect - flag to indicate if card insert needs + * to be detected or not. For SDHC2 controller, Card detect + * is not present, so this field will be false + * Return : SUCCESS or Error Code + * Description : 1. Set Initial Clock Speed + * 2. Card Detect if not eMMC + * 3. Enable Controller Clock + * 4. Send 80 ticks for card to power up + * 5. Set LE mode and Bus Width as 1 bit. + ***************************************************************************/ +static int esdhc_init(struct mmc *mmc, bool card_detect) +{ + uint32_t val; + uint64_t start_time; + + /* Reset the entire host controller */ + val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_RSTA; + esdhc_out32(&mmc->esdhc_regs->sysctl, val); + + /* Wait until the controller is available */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_RSTA; + if (val == 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->sysctl) & + (ESDHC_SYSCTL_RSTA); + if (val != 0U) { + ERROR("SD Reset failed\n"); + return ERROR_ESDHC_BUSY; + } + + /* Set initial clock speed */ + set_speed(mmc, CARD_IDENTIFICATION_FREQ); + + if (card_detect) { + /* Check CINS in prsstat register */ + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + ESDHC_PRSSTAT_CINS; + if (val == 0) { + ERROR("CINS not set in prsstat\n"); + return ERROR_ESDHC_CARD_DETECT_FAIL; + } + } + + /* Enable controller clock */ + val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_SDCLKEN; + esdhc_out32(&mmc->esdhc_regs->sysctl, val); + + /* Send 80 clock ticks for the card to power up */ + val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_INITA; + esdhc_out32(&mmc->esdhc_regs->sysctl, val); + + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT) { + val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_INITA; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_INITA; + if (val == 0U) { + ERROR("Failed to power up the card\n"); + return ERROR_ESDHC_CARD_DETECT_FAIL; + } + + INFO("Card detected successfully\n"); + + val = esdhc_in32(&mmc->esdhc_regs->proctl); + val = val | (ESDHC_PROCTL_EMODE_LE | ESDHC_PROCTL_DTW_1BIT); + + /* Set little endian mode, set bus width as 1-bit */ + esdhc_out32(&mmc->esdhc_regs->proctl, val); + + /* Enable cache snooping for DMA transactions */ + val = esdhc_in32(&mmc->esdhc_regs->ctl) | ESDHC_DCR_SNOOP; + esdhc_out32(&mmc->esdhc_regs->ctl, val); + + return 0; +} + +/*************************************************************************** + * Function : esdhc_send_cmd + * Arguments : mmc - Pointer to mmc struct + * cmd - Command Number + * args - Command Args + * Return : SUCCESS is 0, or Error Code ( < 0) + * Description : Updates the eSDHC registers cmdargs and xfertype + ***************************************************************************/ +static int esdhc_send_cmd(struct mmc *mmc, uint32_t cmd, uint32_t args) +{ + uint32_t val; + uint64_t start_time; + uint32_t xfertyp = 0; + + esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); + + /* Wait for the command line & data line to be free */ + /* (poll the CIHB,CDIHB bit of the present state register) */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + (ESDHC_PRSSTAT_CIHB | ESDHC_PRSSTAT_CDIHB); + if (val == 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + (ESDHC_PRSSTAT_CIHB | ESDHC_PRSSTAT_CDIHB); + if (val != 0U) { + ERROR("SD send cmd: Command Line or Data Line Busy cmd = %x\n", + cmd); + return ERROR_ESDHC_BUSY; + } + + if (cmd == CMD2 || cmd == CMD9) { + xfertyp |= ESDHC_XFERTYP_RSPTYP_136; + } else if (cmd == CMD7 || (cmd == CMD6 && mmc->card.type == MMC_CARD)) { + xfertyp |= ESDHC_XFERTYP_RSPTYP_48_BUSY; + } else if (cmd != CMD0) { + xfertyp |= ESDHC_XFERTYP_RSPTYP_48; + } + + if (cmd == CMD2 || cmd == CMD9) { + xfertyp |= ESDHC_XFERTYP_CCCEN; /* Command index check enable */ + } else if ((cmd != CMD0) && (cmd != ACMD41) && (cmd != CMD1)) { + xfertyp = xfertyp | ESDHC_XFERTYP_CCCEN | ESDHC_XFERTYP_CICEN; + } + + if ((cmd == CMD8 || cmd == CMD14 || cmd == CMD19) && + mmc->card.type == MMC_CARD) { + xfertyp |= ESDHC_XFERTYP_DPSEL; + if (cmd != CMD19) { + xfertyp |= ESDHC_XFERTYP_DTDSEL; + } + } + + if (cmd == CMD6 || cmd == CMD17 || cmd == CMD18 || cmd == CMD24 || + cmd == ACMD51) { + if (!(mmc->card.type == MMC_CARD && cmd == CMD6)) { + if (cmd == CMD24) { + xfertyp |= ESDHC_XFERTYP_DPSEL; + } else { + xfertyp |= (ESDHC_XFERTYP_DPSEL | + ESDHC_XFERTYP_DTDSEL); + } + } + + if (cmd == CMD18) { + xfertyp |= ESDHC_XFERTYP_BCEN; + if (mmc->dma_support != 0) { + /* Set BCEN of XFERTYP */ + xfertyp |= ESDHC_XFERTYP_DMAEN; + } + } + + if ((cmd == CMD17 || cmd == CMD24) && (mmc->dma_support != 0)) { + xfertyp |= ESDHC_XFERTYP_DMAEN; + } + } + + xfertyp |= ((cmd & 0x3F) << 24); + esdhc_out32(&mmc->esdhc_regs->cmdarg, args); + esdhc_out32(&mmc->esdhc_regs->xfertyp, xfertyp); + +#ifdef NXP_SD_DEBUG + INFO("cmd = %d\n", cmd); + INFO("args = %x\n", args); + INFO("xfertyp: = %x\n", xfertyp); +#endif + return 0; +} + +/*************************************************************************** + * Function : esdhc_wait_response + * Arguments : mmc - Pointer to mmc struct + * response - Value updated + * Return : SUCCESS - Response Received + * COMMUNICATION_ERROR - Command not Complete + * COMMAND_ERROR - CIE, CCE or CEBE error + * RESP_TIMEOUT - CTOE error + * Description : Checks for successful command completion. + * Clears the CC bit at the end. + ***************************************************************************/ +static int esdhc_wait_response(struct mmc *mmc, uint32_t *response) +{ + uint32_t val; + uint64_t start_time; + uint32_t status = 0U; + + /* Wait for the command to complete */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_CC; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_CC; + if (val == 0U) { + ERROR("%s:IRQSTAT Cmd not complete(CC not set)\n", __func__); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + + /* Check whether the interrupt is a CRC, CTOE or CIE error */ + if ((status & (ESDHC_IRQSTAT_CIE | ESDHC_IRQSTAT_CEBE | + ESDHC_IRQSTAT_CCE)) != 0) { + ERROR("%s: IRQSTAT CRC, CEBE or CIE error = %x\n", + __func__, status); + return COMMAND_ERROR; + } + + if ((status & ESDHC_IRQSTAT_CTOE) != 0) { + INFO("%s: IRQSTAT CTOE set = %x\n", __func__, status); + return RESP_TIMEOUT; + } + + if ((status & ESDHC_IRQSTAT_DMAE) != 0) { + ERROR("%s: IRQSTAT DMAE set = %x\n", __func__, status); + return ERROR_ESDHC_DMA_ERROR; + } + + if (response != NULL) { + /* Get response values from eSDHC CMDRSPx registers. */ + response[0] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[0]); + response[1] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[1]); + response[2] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[2]); + response[3] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[3]); +#ifdef NXP_SD_DEBUG + INFO("Resp R1 R2 R3 R4\n"); + INFO("Resp R1 = %x\n", response[0]); + INFO("R2 = %x\n", response[1]); + INFO("R3 = %x\n", response[2]); + INFO("R4 = %x\n", response[3]); + INFO("\n"); +#endif + } + + /* Clear the CC bit - w1c */ + val = esdhc_in32(&mmc->esdhc_regs->irqstat) | ESDHC_IRQSTAT_CC; + esdhc_out32(&mmc->esdhc_regs->irqstat, val); + + return 0; +} + +/*************************************************************************** + * Function : mmc_switch_to_high_frquency + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : mmc card bellow ver 4.0 does not support high speed + * freq = 20 MHz + * Send CMD6 (CMD_SWITCH_FUNC) With args 0x03B90100 + * Send CMD13 (CMD_SEND_STATUS) + * if SWITCH Error, freq = 26 MHz + * if no error, freq = 52 MHz + ***************************************************************************/ +static int mmc_switch_to_high_frquency(struct mmc *mmc) +{ + int error; + uint32_t response[4]; + uint64_t start_time; + + mmc->card.bus_freq = MMC_SS_20MHZ; + /* mmc card bellow ver 4.0 does not support high speed */ + if (mmc->card.version < MMC_CARD_VERSION_4_X) { + return 0; + } + + /* send switch cmd to change the card to High speed */ + error = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, SET_EXT_CSD_HS_TIMING); + if (error != 0) { + return error; + } + error = esdhc_wait_response(mmc, response); + if (error != 0) { + return error; + } + + start_time = get_timer_val(0); + do { + /* check the status for which error */ + error = esdhc_send_cmd(mmc, + CMD_SEND_STATUS, mmc->card.rca << 16); + if (error != 0) { + return error; + } + + error = esdhc_wait_response(mmc, response); + if (error != 0) { + return error; + } + } while (((response[0] & SWITCH_ERROR) != 0) && + (get_timer_val(start_time) < SD_TIMEOUT)); + + /* Check for the present state of card */ + if ((response[0] & SWITCH_ERROR) != 0) { + mmc->card.bus_freq = MMC_HS_26MHZ; + } else { + mmc->card.bus_freq = MMC_HS_52MHZ; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_set_data_attributes + * Arguments : mmc - Pointer to mmc struct + * blkcnt + * blklen + * Return : SUCCESS or Error Code + * Description : Set block attributes and watermark level register + ***************************************************************************/ +static int esdhc_set_data_attributes(struct mmc *mmc, uint32_t *dest_ptr, + uint32_t blkcnt, uint32_t blklen) +{ + uint32_t val; + uint64_t start_time; + uint32_t wml; + uint32_t wl; + uint32_t dst = (uint32_t)((uint64_t)(dest_ptr)); + + /* set blkattr when no transactions are executing */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA; + if (val == 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA; + if (val != 0U) { + ERROR("%s: Data line active.Can't set attribute\n", __func__); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + wml = esdhc_in32(&mmc->esdhc_regs->wml); + wml &= ~(ESDHC_WML_WR_BRST_MASK | ESDHC_WML_RD_BRST_MASK | + ESDHC_WML_RD_WML_MASK | ESDHC_WML_WR_WML_MASK); + + if ((mmc->dma_support != 0) && (dest_ptr != NULL)) { + /* Set burst length to 128 bytes */ + esdhc_out32(&mmc->esdhc_regs->wml, + wml | ESDHC_WML_WR_BRST(BURST_128_BYTES)); + esdhc_out32(&mmc->esdhc_regs->wml, + wml | ESDHC_WML_RD_BRST(BURST_128_BYTES)); + + /* Set DMA System Destination Address */ + esdhc_out32(&mmc->esdhc_regs->dsaddr, dst); + } else { + wl = (blklen >= BLOCK_LEN_512) ? + WML_512_BYTES : ((blklen + 3) / 4); + /* Set 'Read Water Mark Level' register */ + esdhc_out32(&mmc->esdhc_regs->wml, wml | ESDHC_WML_RD_WML(wl)); + } + + /* Configure block Attributes register */ + esdhc_out32(&mmc->esdhc_regs->blkattr, + ESDHC_BLKATTR_BLKCNT(blkcnt) | ESDHC_BLKATTR_BLKSZE(blklen)); + + mmc->block_len = blklen; + + return 0; +} + +/*************************************************************************** + * Function : esdhc_read_data_nodma + * Arguments : mmc - Pointer to mmc struct + * dest_ptr - Bufffer where read data is to be copied + * len - Length of Data to be read + * Return : SUCCESS or Error Code + * Description : Read data from the sdhc buffer without using DMA + * and using polling mode + ***************************************************************************/ +static int esdhc_read_data_nodma(struct mmc *mmc, void *dest_ptr, uint32_t len) +{ + uint32_t i = 0U; + uint32_t status; + uint32_t num_blocks; + uint32_t *dst = (uint32_t *)dest_ptr; + uint32_t val; + uint64_t start_time; + + num_blocks = len / mmc->block_len; + + while ((num_blocks--) != 0U) { + + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + ESDHC_PRSSTAT_BREN; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->prsstat) + & ESDHC_PRSSTAT_BREN; + if (val == 0U) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + for (i = 0U, status = esdhc_in32(&mmc->esdhc_regs->irqstat); + i < mmc->block_len / 4; i++, dst++) { + /* get data from data port */ + val = mmio_read_32( + (uintptr_t)&mmc->esdhc_regs->datport); + esdhc_out32(dst, val); + /* Increment destination pointer */ + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + } + /* Check whether the interrupt is an DTOE/DCE/DEBE */ + if ((status & (ESDHC_IRQSTAT_DTOE | ESDHC_IRQSTAT_DCE | + ESDHC_IRQSTAT_DEBE)) != 0) { + ERROR("SD read error - DTOE, DCE, DEBE bit set = %x\n", + status); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + } + + /* Wait for TC */ + + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; + if (val == 0U) { + ERROR("SD read timeout: Transfer bit not set in IRQSTAT\n"); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_write_data_nodma + * Arguments : mmc - Pointer to mmc struct + * src_ptr - Buffer where data is copied from + * len - Length of Data to be written + * Return : SUCCESS or Error Code + * Description : Write data to the sdhc buffer without using DMA + * and using polling mode + ***************************************************************************/ +static int esdhc_write_data_nodma(struct mmc *mmc, void *src_ptr, uint32_t len) +{ + uint32_t i = 0U; + uint32_t status; + uint32_t num_blocks; + uint32_t *src = (uint32_t *)src_ptr; + uint32_t val; + uint64_t start_time; + + num_blocks = len / mmc->block_len; + + while ((num_blocks--) != 0U) { + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + ESDHC_PRSSTAT_BWEN; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + ESDHC_PRSSTAT_BWEN; + if (val == 0U) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + for (i = 0U, status = esdhc_in32(&mmc->esdhc_regs->irqstat); + i < mmc->block_len / 4; i++, src++) { + val = esdhc_in32(src); + /* put data to data port */ + mmio_write_32((uintptr_t)&mmc->esdhc_regs->datport, + val); + /* Increment source pointer */ + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + } + /* Check whether the interrupt is an DTOE/DCE/DEBE */ + if ((status & (ESDHC_IRQSTAT_DTOE | ESDHC_IRQSTAT_DCE | + ESDHC_IRQSTAT_DEBE)) != 0) { + ERROR("SD write error - DTOE, DCE, DEBE bit set = %x\n", + status); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + } + + /* Wait for TC */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; + if (val == 0U) { + ERROR("SD write timeout: Transfer bit not set in IRQSTAT\n"); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_read_data_dma + * Arguments : mmc - Pointer to mmc struct + * len - Length of Data to be read + * Return : SUCCESS or Error Code + * Description : Read data from the sd card using DMA. + ***************************************************************************/ +static int esdhc_read_data_dma(struct mmc *mmc, uint32_t len) +{ + uint32_t status; + uint32_t tblk; + uint64_t start_time; + + tblk = SD_BLOCK_TIMEOUT * (len / mmc->block_len); + + start_time = get_timer_val(0); + + /* poll till TC is set */ + do { + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + + if ((status & (ESDHC_IRQSTAT_DEBE | ESDHC_IRQSTAT_DCE + | ESDHC_IRQSTAT_DTOE)) != 0) { + ERROR("SD read error - DTOE, DCE, DEBE bit set = %x\n", + status); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if ((status & ESDHC_IRQSTAT_DMAE) != 0) { + ERROR("SD read error - DMA error = %x\n", status); + return ERROR_ESDHC_DMA_ERROR; + } + + } while (((status & ESDHC_IRQSTAT_TC) == 0) && + ((esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA) != 0) && + (get_timer_val(start_time) < SD_TIMEOUT_HIGH + tblk)); + + if (get_timer_val(start_time) > SD_TIMEOUT_HIGH + tblk) { + ERROR("SD read DMA timeout\n"); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_write_data_dma + * Arguments : mmc - Pointer to mmc struct + * len - Length of Data to be written + * Return : SUCCESS or Error Code + * Description : Write data to the sd card using DMA. + ***************************************************************************/ +static int esdhc_write_data_dma(struct mmc *mmc, uint32_t len) +{ + uint32_t status; + uint32_t tblk; + uint64_t start_time; + + tblk = SD_BLOCK_TIMEOUT * (len / mmc->block_len); + + start_time = get_timer_val(0); + + /* poll till TC is set */ + do { + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + + if ((status & (ESDHC_IRQSTAT_DEBE | ESDHC_IRQSTAT_DCE + | ESDHC_IRQSTAT_DTOE)) != 0) { + ERROR("SD write error - DTOE, DCE, DEBE bit set = %x\n", + status); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if ((status & ESDHC_IRQSTAT_DMAE) != 0) { + ERROR("SD write error - DMA error = %x\n", status); + return ERROR_ESDHC_DMA_ERROR; + } + } while (((status & ESDHC_IRQSTAT_TC) == 0) && + ((esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA) != 0) && + (get_timer_val(start_time) < SD_TIMEOUT_HIGH + tblk)); + + if (get_timer_val(start_time) > SD_TIMEOUT_HIGH + tblk) { + ERROR("SD write DMA timeout\n"); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_read_data + * Arguments : mmc - Pointer to mmc struct + * dest_ptr - Bufffer where read data is to be copied + * len - Length of Data to be read + * Return : SUCCESS or Error Code + * Description : Calls esdhc_read_data_nodma and clear interrupt status + ***************************************************************************/ +int esdhc_read_data(struct mmc *mmc, void *dest_ptr, uint32_t len) +{ + int ret; + + if (mmc->dma_support && len > 64) { + ret = esdhc_read_data_dma(mmc, len); + } else { + ret = esdhc_read_data_nodma(mmc, dest_ptr, len); + } + + /* clear interrupt status */ + esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); + + return ret; +} + +/*************************************************************************** + * Function : esdhc_write_data + * Arguments : mmc - Pointer to mmc struct + * src_ptr - Buffer where data is copied from + * len - Length of Data to be written + * Return : SUCCESS or Error Code + * Description : Calls esdhc_write_data_nodma and clear interrupt status + ***************************************************************************/ +int esdhc_write_data(struct mmc *mmc, void *src_ptr, uint32_t len) +{ + int ret; + + if (mmc->dma_support && len > 64) { + ret = esdhc_write_data_dma(mmc, len); + } else { + ret = esdhc_write_data_nodma(mmc, src_ptr, len); + } + + /* clear interrupt status */ + esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); + + return ret; +} + +/*************************************************************************** + * Function : sd_switch_to_high_freq + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send ACMD51 (CMD_SEND_SCR) + * 2. Read the SCR to check if card supports higher freq + * 3. check version from SCR + * 4. If SD 1.0, return (no Switch) freq = 25 MHz. + * 5. Send CMD6 (CMD_SWITCH_FUNC) with args 0x00FFFFF1 to + * check the status of switch func + * 6. Send CMD6 (CMD_SWITCH_FUNC) With args 0x80FFFFF1 to + * switch to high frequency = 50 Mhz + ***************************************************************************/ +static int sd_switch_to_high_freq(struct mmc *mmc) +{ + int err; + uint8_t scr[8]; + uint8_t status[64]; + uint32_t response[4]; + uint32_t version; + uint32_t count; + uint32_t sd_versions[] = {SD_CARD_VERSION_1_0, SD_CARD_VERSION_1_10, + SD_CARD_VERSION_2_0}; + + mmc->card.bus_freq = SD_SS_25MHZ; + /* Send Application command */ + err = esdhc_send_cmd(mmc, CMD_APP_CMD, mmc->card.rca << 16); + if (err != 0) { + return err; + } + + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + esdhc_set_data_attributes(mmc, NULL, 1, 8); + /* Read the SCR to find out if this card supports higher speeds */ + err = esdhc_send_cmd(mmc, CMD_SEND_SCR, mmc->card.rca << 16); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + /* read 8 bytes of scr data */ + err = esdhc_read_data(mmc, scr, 8U); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + /* check version from SCR */ + version = scr[0] & U(0xF); + if (version <= 2U) { + mmc->card.version = sd_versions[version]; + } else { + mmc->card.version = SD_CARD_VERSION_2_0; + } + + /* does not support switch func */ + if (mmc->card.version == SD_CARD_VERSION_1_0) { + return 0; + } + + /* read 64 bytes of status */ + esdhc_set_data_attributes(mmc, NULL, 1U, 64U); + + /* check the status of switch func */ + for (count = 0U; count < 4U; count++) { + err = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, + SD_SWITCH_FUNC_CHECK_MODE); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + /* read 64 bytes of scr data */ + err = esdhc_read_data(mmc, status, 64U); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if ((status[29] & SD_SWITCH_FUNC_HIGH_SPEED) == 0) { + break; + } + } + + if ((status[13] & SD_SWITCH_FUNC_HIGH_SPEED) == 0) { + return 0; + } + + /* SWITCH */ + esdhc_set_data_attributes(mmc, NULL, 1, 64); + err = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, SD_SWITCH_FUNC_SWITCH_MODE); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + err = esdhc_read_data(mmc, status, 64U); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if ((status[16]) == U(0x01)) { + mmc->card.bus_freq = SD_HS_50MHZ; + } + + return 0; +} + +/*************************************************************************** + * Function : change_state_to_transfer_state + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send CMD7 (CMD_SELECT_CARD) to toggles the card + * between stand-by and transfer state + * 2. Send CMD13 (CMD_SEND_STATUS) to check state as + * Transfer State + ***************************************************************************/ +static int change_state_to_transfer_state(struct mmc *mmc) +{ + int error = 0; + uint32_t response[4]; + uint64_t start_time; + + /* Command CMD_SELECT_CARD/CMD7 toggles the card between stand-by + * and transfer states + */ + error = esdhc_send_cmd(mmc, CMD_SELECT_CARD, mmc->card.rca << 16); + if (error != 0) { + return error; + } + error = esdhc_wait_response(mmc, response); + if (error != 0) { + return error; + } + + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + /* send CMD13 to check card status */ + error = esdhc_send_cmd(mmc, + CMD_SEND_STATUS, mmc->card.rca << 16); + if (error != 0) { + return error; + } + error = esdhc_wait_response(mmc, response); + if ((error != 0) || ((response[0] & R1_ERROR) != 0)) { + return error; + } + + /* Check for the present state of card */ + if (((response[0] >> 9U) & U(0xF)) == STATE_TRAN) { + break; + } + } + if (((response[0] >> 9U) & U(0xF)) == STATE_TRAN) { + return 0; + } else { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } +} + +/*************************************************************************** + * Function : get_cid_rca_csd + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send CMD2 (CMD_ALL_SEND_CID) + * 2. get RCA for SD cards, set rca for mmc cards + * Send CMD3 (CMD_SEND_RELATIVE_ADDR) + * 3. Send CMD9 (CMD_SEND_CSD) + * 4. Get MMC Version from CSD + ***************************************************************************/ +static int get_cid_rca_csd(struct mmc *mmc) +{ + int err; + uint32_t version; + uint32_t response[4]; + uint32_t mmc_version[] = {MMC_CARD_VERSION_1_2, MMC_CARD_VERSION_1_4, + MMC_CARD_VERSION_2_X, MMC_CARD_VERSION_3_X, + MMC_CARD_VERSION_4_X}; + + err = esdhc_send_cmd(mmc, CMD_ALL_SEND_CID, 0); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + /* get RCA for SD cards, set rca for mmc cards */ + mmc->card.rca = SD_MMC_CARD_RCA; + + /* send RCA cmd */ + err = esdhc_send_cmd(mmc, CMD_SEND_RELATIVE_ADDR, mmc->card.rca << 16); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + /* for SD, get the the RCA */ + if (mmc->card.type == SD_CARD) { + mmc->card.rca = (response[0] >> 16) & 0xFFFF; + } + + /* Get the CSD (card specific data) from card. */ + err = esdhc_send_cmd(mmc, CMD_SEND_CSD, mmc->card.rca << 16); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + version = (response[3] >> 18U) & U(0xF); + if (mmc->card.type == MMC_CARD) { + if (version <= MMC_CARD_VERSION_4_X) { + mmc->card.version = mmc_version[version]; + } else { + mmc->card.version = MMC_CARD_VERSION_4_X; + } + } + + mmc->card.block_len = 1 << ((response[2] >> 8) & 0xF); + + if (mmc->card.block_len > BLOCK_LEN_512) { + mmc->card.block_len = BLOCK_LEN_512; + } + + return 0; +} + +/*************************************************************************** + * Function : identify_mmc_card + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send Reset Command + * 2. Send CMD1 with args to set voltage range and Sector + * Mode. (Voltage Args = 0xFF8) + * 3. Check the OCR Response + ***************************************************************************/ +static int identify_mmc_card(struct mmc *mmc) +{ + uint64_t start_time; + uint32_t resp[4]; + int ret; + uint32_t args; + + /* card reset */ + ret = esdhc_send_cmd(mmc, CMD_GO_IDLE_STATE, 0U); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret != 0) { + return ret; + } + + /* Send CMD1 to get the ocr value repeatedly till the card */ + /* busy is clear. timeout = 20sec */ + + start_time = get_timer_val(0); + do { + /* set the bits for the voltage ranges supported by host */ + args = mmc->voltages_caps | MMC_OCR_SECTOR_MODE; + ret = esdhc_send_cmd(mmc, CMD_MMC_SEND_OP_COND, args); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret != 0) { + return ERROR_ESDHC_UNUSABLE_CARD; + } + } while (((resp[0] & MMC_OCR_BUSY) == 0U) && + (get_timer_val(start_time) < SD_TIMEOUT_HIGH)); + + if (get_timer_val(start_time) > SD_TIMEOUT_HIGH) { + return ERROR_ESDHC_UNUSABLE_CARD; + } + + if ((resp[0] & MMC_OCR_CCS) == MMC_OCR_CCS) { + mmc->card.is_high_capacity = 1; + } + + return MMC_CARD; +} + +/*************************************************************************** + * Function : check_for_sd_card + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send Reset Command + * 2. Send CMD8 with pattern 0xAA (to check for SD 2.0) + * 3. Send ACMD41 with args to set voltage range and HCS + * HCS is set only for SD Card > 2.0 + * Voltage Caps = 0xFF8 + * 4. Check the OCR Response + ***************************************************************************/ +static int check_for_sd_card(struct mmc *mmc) +{ + uint64_t start_time; + uint32_t args; + int ret; + uint32_t resp[4]; + + /* Send reset command */ + ret = esdhc_send_cmd(mmc, CMD_GO_IDLE_STATE, 0U); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret != 0) { + return ret; + } + + /* send CMD8 with pattern 0xAA */ + args = MMC_VDD_HIGH_VOLTAGE | 0xAA; + ret = esdhc_send_cmd(mmc, CMD_SEND_IF_COND, args); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret == RESP_TIMEOUT) { /* sd ver 1.x or not sd */ + mmc->card.is_high_capacity = 0; + } else if ((resp[0] & U(0xFF)) == U(0xAA)) { /* ver 2.0 or later */ + mmc->card.version = SD_CARD_VERSION_2_0; + } else { + return NOT_SD_CARD; + } + /* Send Application command-55 to get the ocr value repeatedly till + * the card busy is clear. timeout = 20sec + */ + + start_time = get_timer_val(0); + do { + ret = esdhc_send_cmd(mmc, CMD_APP_CMD, 0U); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret == COMMAND_ERROR) { + return ERROR_ESDHC_UNUSABLE_CARD; + } + + /* set the bits for the voltage ranges supported by host */ + args = mmc->voltages_caps; + if (mmc->card.version == SD_CARD_VERSION_2_0) { + args |= SD_OCR_HCS; + } + + /* Send ACMD41 to set voltage range */ + ret = esdhc_send_cmd(mmc, CMD_SD_SEND_OP_COND, args); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret == COMMAND_ERROR) { + return ERROR_ESDHC_UNUSABLE_CARD; + } else if (ret == RESP_TIMEOUT) { + return NOT_SD_CARD; + } + } while (((resp[0] & MMC_OCR_BUSY) == 0U) && + (get_timer_val(start_time) < SD_TIMEOUT_HIGH)); + + if (get_timer_val(start_time) > SD_TIMEOUT_HIGH) { + INFO("SD_TIMEOUT_HIGH\n"); + return ERROR_ESDHC_UNUSABLE_CARD; + } + + /* bit set in card capacity status */ + if ((resp[0] & MMC_OCR_CCS) == MMC_OCR_CCS) { + mmc->card.is_high_capacity = 1; + } + + return SD_CARD; +} + +/*************************************************************************** + * Function : esdhc_emmc_init + * Arguments : mmc - Pointer to mmc struct + * src_emmc - Flag to Indicate SRC as emmc + * Return : SUCCESS or Error Code (< 0) + * Description : Base Function called from sd_mmc_init or emmc_init + ***************************************************************************/ +int esdhc_emmc_init(struct mmc *mmc, bool card_detect) +{ + int error = 0; + int ret = 0; + + error = esdhc_init(mmc, card_detect); + if (error != 0) { + return error; + } + + mmc->card.bus_freq = CARD_IDENTIFICATION_FREQ; + mmc->card.rca = 0; + mmc->card.is_high_capacity = 0; + mmc->card.type = ERROR_ESDHC_UNUSABLE_CARD; + + /* Set Voltage caps as FF8 i.e all supported */ + /* high voltage bits 2.7 - 3.6 */ + mmc->voltages_caps = MMC_OCR_VDD_FF8; + +#ifdef NXP_SD_DMA_CAPABILITY + /* Getting host DMA capabilities. */ + mmc->dma_support = esdhc_in32(&mmc->esdhc_regs->hostcapblt) & + ESDHC_HOSTCAPBLT_DMAS; +#else + mmc->dma_support = 0; +#endif + + ret = NOT_SD_CARD; + /* If SRC is not EMMC, check for SD or MMC */ + ret = check_for_sd_card(mmc); + switch (ret) { + case SD_CARD: + mmc->card.type = SD_CARD; + break; + + case NOT_SD_CARD: + /* try for MMC card */ + if (identify_mmc_card(mmc) == MMC_CARD) { + mmc->card.type = MMC_CARD; + } else { + return ERROR_ESDHC_UNUSABLE_CARD; + } + break; + + default: + return ERROR_ESDHC_UNUSABLE_CARD; + } + + /* get CID, RCA and CSD. For MMC, set the rca */ + error = get_cid_rca_csd(mmc); + if (error != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + /* change state to Transfer mode */ + error = change_state_to_transfer_state(mmc); + if (error != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + /* change to high frequency if supported */ + if (mmc->card.type == SD_CARD) { + error = sd_switch_to_high_freq(mmc); + } else { + error = mmc_switch_to_high_frquency(mmc); + } + if (error != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + /* mmc: 20000000, 26000000, 52000000 */ + /* sd: 25000000, 50000000 */ + set_speed(mmc, mmc->card.bus_freq); + + INFO("init done:\n"); + return 0; +} + +/*************************************************************************** + * Function : sd_mmc_init + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : Base Function called via hal_init for SD/MMC + * initialization + ***************************************************************************/ +int sd_mmc_init(uintptr_t nxp_esdhc_addr, bool card_detect) +{ + struct mmc *mmc = NULL; + int ret; + + mmc = &mmc_drv_data; + memset(mmc, 0, sizeof(struct mmc)); + mmc->esdhc_regs = (struct esdhc_regs *)nxp_esdhc_addr; + + INFO("esdhc_emmc_init\n"); + ret = esdhc_emmc_init(mmc, card_detect); + return ret; +} + +/*************************************************************************** + * Function : esdhc_read_block + * Arguments : mmc - Pointer to mmc struct + * dst - Destination Pointer + * block - Block Number + * Return : SUCCESS or Error Code + * Description : Read a Single block to Destination Pointer + * 1. Send CMD16 (CMD_SET_BLOCKLEN) with args as blocklen + * 2. Send CMD17 (CMD_READ_SINGLE_BLOCK) with args offset + ***************************************************************************/ +static int esdhc_read_block(struct mmc *mmc, void *dst, uint32_t block) +{ + uint32_t offset; + int err; + + /* send cmd16 to set the block size. */ + err = esdhc_send_cmd(mmc, CMD_SET_BLOCKLEN, mmc->card.block_len); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, NULL); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if (mmc->card.is_high_capacity != 0) { + offset = block; + } else { + offset = block * mmc->card.block_len; + } + + esdhc_set_data_attributes(mmc, dst, 1, mmc->card.block_len); + err = esdhc_send_cmd(mmc, CMD_READ_SINGLE_BLOCK, offset); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, NULL); + if (err != 0) { + return err; + } + + err = esdhc_read_data(mmc, dst, mmc->card.block_len); + + return err; +} + +/*************************************************************************** + * Function : esdhc_write_block + * Arguments : mmc - Pointer to mmc struct + * src - Source Pointer + * block - Block Number + * Return : SUCCESS or Error Code + * Description : Write a Single block from Source Pointer + * 1. Send CMD16 (CMD_SET_BLOCKLEN) with args as blocklen + * 2. Send CMD24 (CMD_WRITE_SINGLE_BLOCK) with args offset + ***************************************************************************/ +static int esdhc_write_block(struct mmc *mmc, void *src, uint32_t block) +{ + uint32_t offset; + int err; + + /* send cmd16 to set the block size. */ + err = esdhc_send_cmd(mmc, CMD_SET_BLOCKLEN, mmc->card.block_len); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, NULL); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if (mmc->card.is_high_capacity != 0) { + offset = block; + } else { + offset = block * mmc->card.block_len; + } + + esdhc_set_data_attributes(mmc, src, 1, mmc->card.block_len); + err = esdhc_send_cmd(mmc, CMD_WRITE_SINGLE_BLOCK, offset); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, NULL); + if (err != 0) { + return err; + } + + err = esdhc_write_data(mmc, src, mmc->card.block_len); + + return err; +} + +/*************************************************************************** + * Function : esdhc_read + * Arguments : src_offset - offset on sd/mmc to read from. Should be block + * size aligned + * dst - Destination Pointer + * size - Length of Data ( Multiple of block size) + * Return : SUCCESS or Error Code + * Description : Calls esdhc_read_block repeatedly for reading the + * data. + ***************************************************************************/ +int esdhc_read(struct mmc *mmc, uint32_t src_offset, uintptr_t dst, size_t size) +{ + int error = 0; + uint32_t blk, num_blocks; + uint8_t *buff = (uint8_t *)dst; + +#ifdef NXP_SD_DEBUG + INFO("sd mmc read\n"); + INFO("src = %x, dst = %lxsize = %lu\n", src_offset, dst, size); +#endif + + /* check for size */ + if (size == 0) { + return 0; + } + + if ((size % mmc->card.block_len) != 0) { + ERROR("Size is not block aligned\n"); + return -1; + } + + if ((src_offset % mmc->card.block_len) != 0) { + ERROR("Size is not block aligned\n"); + return -1; + } + + /* start block */ + blk = src_offset / mmc->card.block_len; +#ifdef NXP_SD_DEBUG + INFO("blk = %x\n", blk); +#endif + + /* Number of blocks to be read */ + num_blocks = size / mmc->card.block_len; + + while (num_blocks) { + error = esdhc_read_block(mmc, buff, blk); + if (error != 0) { + ERROR("Read error = %x\n", error); + return error; + } + + buff = buff + mmc->card.block_len; + blk++; + num_blocks--; + } + + INFO("sd-mmc read done.\n"); + return error; +} + +/*************************************************************************** + * Function : esdhc_write + * Arguments : src - Source Pointer + * dst_offset - offset on sd/mmc to write to. Should be block + * size aligned + * size - Length of Data (Multiple of block size) + * Return : SUCCESS or Error Code + * Description : Calls esdhc_write_block repeatedly for writing the + * data. + ***************************************************************************/ +int esdhc_write(struct mmc *mmc, uintptr_t src, uint32_t dst_offset, + size_t size) +{ + int error = 0; + uint32_t blk, num_blocks; + uint8_t *buff = (uint8_t *)src; + +#ifdef NXP_SD_DEBUG + INFO("sd mmc write\n"); + INFO("src = %x, dst = %lxsize = %lu\n", src, dst_offset, size); +#endif + + /* check for size */ + if (size == 0) { + return 0; + } + + if ((size % mmc->card.block_len) != 0) { + ERROR("Size is not block aligned\n"); + return -1; + } + + if ((dst_offset % mmc->card.block_len) != 0) { + ERROR("Size is not block aligned\n"); + return -1; + } + + /* start block */ + blk = dst_offset / mmc->card.block_len; +#ifdef NXP_SD_DEBUG + INFO("blk = %x\n", blk); +#endif + + /* Number of blocks to be written */ + num_blocks = size / mmc->card.block_len; + + while (num_blocks != 0U) { + error = esdhc_write_block(mmc, buff, blk); + if (error != 0U) { + ERROR("Write error = %x\n", error); + return error; + } + + buff = buff + mmc->card.block_len; + blk++; + num_blocks--; + } + + INFO("sd-mmc write done.\n"); + return error; +} + +static size_t ls_sd_emmc_read(int lba, uintptr_t buf, size_t size) +{ + struct mmc *mmc = NULL; + int ret; + + mmc = &mmc_drv_data; + lba *= BLOCK_LEN_512; + ret = esdhc_read(mmc, lba, buf, size); + return ret ? 0 : size; +} + +static struct io_block_dev_spec ls_emmc_dev_spec = { + .buffer = { + .offset = 0, + .length = 0, + }, + .ops = { + .read = ls_sd_emmc_read, + }, + .block_size = BLOCK_LEN_512, +}; + +int sd_emmc_init(uintptr_t *block_dev_spec, + uintptr_t nxp_esdhc_addr, + size_t nxp_sd_block_offset, + size_t nxp_sd_block_size, + bool card_detect) +{ + int ret; + + ret = sd_mmc_init(nxp_esdhc_addr, card_detect); + if (ret != 0) { + return ret; + } + + ls_emmc_dev_spec.buffer.offset = nxp_sd_block_offset; + ls_emmc_dev_spec.buffer.length = nxp_sd_block_size; + *block_dev_spec = (uintptr_t)&ls_emmc_dev_spec; + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.mk b/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.mk new file mode 100644 index 0000000..c83b1bd --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_SD_MMC},) + +ADD_SD_MMC := 1 + +SD_MMC_BOOT_SOURCES += ${PLAT_DRIVERS_PATH}/sd/sd_mmc.c \ + drivers/io/io_block.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/sd + +ifeq (${BL_COMM_SD_MMC_NEEDED},yes) +BL_COMMON_SOURCES += ${SD_MMC_BOOT_SOURCES} +else +ifeq (${BL2_SD_MMC_NEEDED},yes) +BL2_SOURCES += ${SD_MMC_BOOT_SOURCES} +endif +ifeq (${BL3_SD_MMC_NEEDED},yes) +BL31_SOURCES += ${SD_MMC_BOOT_SOURCES} +endif +endif +endif diff --git a/arm-trusted-firmware/drivers/nxp/sec_mon/sec_mon.mk b/arm-trusted-firmware/drivers/nxp/sec_mon/sec_mon.mk new file mode 100644 index 0000000..aaac53f --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sec_mon/sec_mon.mk @@ -0,0 +1,25 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_SNVS},) + +ADD_SNVS := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/sec_mon + +SNVS_SOURCES += $(PLAT_DRIVERS_PATH)/sec_mon/snvs.c + +ifeq (${BL_COMM_SNVS_NEEDED},yes) +BL_COMMON_SOURCES += ${SNVS_SOURCES} +else +ifeq (${BL2_SNVS_NEEDED},yes) +BL2_SOURCES += ${SNVS_SOURCES} +endif +ifeq (${BL31_SNVS_NEEDED},yes) +BL31_SOURCES += ${SNVS_SOURCES} +endif +endif +endif diff --git a/arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c b/arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c new file mode 100644 index 0000000..6208b67 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c @@ -0,0 +1,186 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#include + +static uintptr_t g_nxp_snvs_addr; + +void snvs_init(uintptr_t nxp_snvs_addr) +{ + g_nxp_snvs_addr = nxp_snvs_addr; +} + +uint32_t get_snvs_state(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + + return (snvs_read32(&snvs->hp_stat) & HPSTS_MASK_SSM_ST); +} + +static uint32_t do_snvs_state_transition(uint32_t state_transtion_bit, + uint32_t target_state) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + uint32_t fetch_cnt = 16U; + uint32_t val = snvs_read32(&snvs->hp_com) | state_transtion_bit; + + snvs_write32(&snvs->hp_com, val); + + /* polling loop till SNVS is in target state */ + do { + sts = get_snvs_state(); + } while ((sts != target_state) && ((--fetch_cnt) != 0)); + + return sts; +} +void transition_snvs_non_secure(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + + switch (sts) { + /* If initial state is check or Non-Secure, then + * set the Software Security Violation Bit and + * transition to Non-Secure State. + */ + case HPSTS_CHECK_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST); + break; + + /* If initial state is Trusted, Secure or Soft-Fail, then + * first set the Software Security Violation Bit and + * transition to Soft-Fail State. + */ + case HPSTS_TRUST_SSM_ST: + case HPSTS_SECURE_SSM_ST: + case HPSTS_SOFT_FAIL_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST); + + /* If SSM Soft Fail to Non-Secure State Transition + * Disable is not set, then set SSM_ST bit and + * transition to Non-Secure State. + */ + if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_SFNS_DIS) == 0) { + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_NON_SECURE_SSM_ST); + } + break; + default: + break; + } +} + +void transition_snvs_soft_fail(void) +{ + do_snvs_state_transition(HPCOM_SW_FSV, HPSTS_SOFT_FAIL_SSM_ST); +} + +uint32_t transition_snvs_trusted(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + + switch (sts) { + /* If initial state is check, set the SSM_ST bit to + * change the state to trusted. + */ + case HPSTS_CHECK_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + break; + /* If SSM Secure to Trusted State Transition Disable + * is not set, then set SSM_ST bit and + * transition to Trusted State. + */ + case HPSTS_SECURE_SSM_ST: + if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_ST_DIS) == 0) { + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + } + break; + /* If initial state is Soft-Fail or Non-Secure, then + * transition to Trusted is not Possible. + */ + default: + break; + } + + return sts; +} + +uint32_t transition_snvs_secure(void) +{ + uint32_t sts = get_snvs_state(); + + if (sts == HPSTS_SECURE_SSM_ST) { + return sts; + } + + if (sts != HPSTS_TRUST_SSM_ST) { + sts = transition_snvs_trusted(); + if (sts != HPSTS_TRUST_SSM_ST) { + return sts; + } + } + + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + + return sts; +} + +void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val) +{ + if (flag_val) { + snvs_write32(g_nxp_snvs_addr + offset, + (snvs_read32(g_nxp_snvs_addr + offset)) + | (1 << bit_pos)); + } else { + snvs_write32(g_nxp_snvs_addr + offset, + (snvs_read32(g_nxp_snvs_addr + offset)) + & ~(1 << bit_pos)); + } +} + +uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos) +{ + return (snvs_read32(g_nxp_snvs_addr + offset) & (1 << bit_pos)); +} + +void snvs_disable_zeroize_lp_gpr(void) +{ + snvs_write_lp_gpr_bit(NXP_LPCR_OFFSET, + NXP_GPR_Z_DIS_BIT, + true); +} + +#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB) +void snvs_write_app_data_bit(uint32_t bit_pos) +{ + snvs_write_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, + bit_pos, + true); +} + +uint32_t snvs_read_app_data(void) +{ + return snvs_read32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET); +} + +uint32_t snvs_read_app_data_bit(uint32_t bit_pos) +{ + uint8_t ret = snvs_read_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, bit_pos); + + return ((ret != 0U) ? 1U : 0U); +} + +void snvs_clear_app_data(void) +{ + snvs_write32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET, 0x0); +} +#endif diff --git a/arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c b/arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c new file mode 100644 index 0000000..165474f --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c @@ -0,0 +1,462 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +static int write_a_fuse(uint32_t *fuse_addr, uint32_t *fuse_hdr_val, + uint32_t mask) +{ + uint32_t last_stored_val = sfp_read32(fuse_addr); + + /* Check if fuse already blown or not */ + if ((last_stored_val & mask) == mask) { + return ERROR_ALREADY_BLOWN; + } + + /* Write fuse in mirror registers */ + sfp_write32(fuse_addr, last_stored_val | (*fuse_hdr_val & mask)); + + /* Read back to check if write success */ + if (sfp_read32(fuse_addr) != (last_stored_val | (*fuse_hdr_val & mask))) { + return ERROR_WRITE; + } + + return 0; +} + +static int write_fuses(uint32_t *fuse_addr, uint32_t *fuse_hdr_val, uint8_t len) +{ + int i; + + /* Check if fuse already blown or not */ + for (i = 0; i < len; i++) { + if (sfp_read32(&fuse_addr[i]) != 0) { + return ERROR_ALREADY_BLOWN; + } + } + + /* Write fuse in mirror registers */ + for (i = 0; i < len; i++) { + sfp_write32(&fuse_addr[i], fuse_hdr_val[i]); + } + + /* Read back to check if write success */ + for (i = 0; i < len; i++) { + if (sfp_read32(&fuse_addr[i]) != fuse_hdr_val[i]) { + return ERROR_WRITE; + } + } + + return 0; +} + +/* + * This function program Super Root Key Hash (SRKH) in fuse + * registers. + */ +static int prog_srkh(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret = 0; + + ret = write_fuses(sfp_ccsr_regs->srk_hash, fuse_hdr->srkh, 8); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_SRKH_ALREADY_BLOWN : ERROR_SRKH_WRITE; + } + + return ret; +} + +/* This function program OEMUID[0-4] in fuse registers. */ +static int prog_oemuid(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int i, ret = 0; + + for (i = 0; i < 5; i++) { + /* Check OEMUIDx to be blown or not */ + if (((fuse_hdr->flags >> (FLAG_OUID0_SHIFT + i)) & 0x1) != 0) { + /* Check if OEMUID[i] already blown or not */ + ret = write_fuses(&sfp_ccsr_regs->oem_uid[i], + &fuse_hdr->oem_uid[i], 1); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_OEMUID_ALREADY_BLOWN + : ERROR_OEMUID_WRITE; + } + } + } + return ret; +} + +/* This function program DCV[0-1], DRV[0-1] in fuse registers. */ +static int prog_debug(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret; + + /* Check DCV to be blown or not */ + if (((fuse_hdr->flags >> (FLAG_DCV0_SHIFT)) & 0x3) != 0) { + /* Check if DCV[i] already blown or not */ + ret = write_fuses(sfp_ccsr_regs->dcv, fuse_hdr->dcv, 2); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_DCV_ALREADY_BLOWN + : ERROR_DCV_WRITE; + } + } + + /* Check DRV to be blown or not */ + if ((((fuse_hdr->flags >> (FLAG_DRV0_SHIFT)) & 0x3)) != 0) { + /* Check if DRV[i] already blown or not */ + ret = write_fuses(sfp_ccsr_regs->drv, fuse_hdr->drv, 2); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_DRV_ALREADY_BLOWN + : ERROR_DRV_WRITE; + } else { + /* Check for DRV hamming error */ + if (sfp_read32((void *)(get_sfp_addr() + + SFP_SVHESR_OFFSET)) + & SFP_SVHESR_DRV_MASK) { + return ERROR_DRV_HAMMING_ERROR; + } + } + } + + return 0; +} + + /* + * Turn a 256-bit random value (32 bytes) into an OTPMK code word + * modifying the input data array in place + */ +static void otpmk_make_code_word_256(uint8_t *otpmk, bool minimal_flag) +{ + int i; + uint8_t parity_bit; + uint8_t code_bit; + + if (minimal_flag == true) { + /* + * Force bits 252, 253, 254 and 255 to 1 + * This is because these fuses may have already been blown + * and the OTPMK cannot force them back to 0 + */ + otpmk[252/8] |= (1 << (252%8)); + otpmk[253/8] |= (1 << (253%8)); + otpmk[254/8] |= (1 << (254%8)); + otpmk[255/8] |= (1 << (255%8)); + } + + /* Generate the hamming code for the code word */ + parity_bit = 0; + code_bit = 0; + for (i = 0; i < 256; i += 1) { + if ((otpmk[i/8] & (1 << (i%8))) != 0) { + parity_bit ^= 1; + code_bit ^= i; + } + } + + /* Inverting otpmk[code_bit] will cause the otpmk + * to become a valid code word (except for overall parity) + */ + if (code_bit < 252) { + otpmk[code_bit/8] ^= (1 << (code_bit % 8)); + parity_bit ^= 1; // account for flipping a bit changing parity + } else { + /* Invert two bits: (code_bit - 4) and 4 + * Because we invert two bits, no need to touch the parity bit + */ + otpmk[(code_bit - 4)/8] ^= (1 << ((code_bit - 4) % 8)); + otpmk[4/8] ^= (1 << (4 % 8)); + } + + /* Finally, adjust the overall parity of the otpmk + * otpmk bit 0 + */ + otpmk[0] ^= parity_bit; +} + +/* This function program One Time Programmable Master Key (OTPMK) + * in fuse registers. + */ +static int prog_otpmk(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret = 0; + uint32_t otpmk_flags; + uint32_t otpmk_random[8] __aligned(CACHE_WRITEBACK_GRANULE); + + otpmk_flags = (fuse_hdr->flags >> (FLAG_OTPMK_SHIFT)) & FLAG_OTPMK_MASK; + + switch (otpmk_flags) { + case PROG_OTPMK_MIN: + memset(fuse_hdr->otpmk, 0, sizeof(fuse_hdr->otpmk)); + + /* Minimal OTPMK value (252-255 bits set to 1) */ + fuse_hdr->otpmk[0] |= OTPMK_MIM_BITS_MASK; + break; + + case PROG_OTPMK_RANDOM: + if (is_sec_enabled() == false) { + ret = ERROR_OTPMK_SEC_DISABLED; + goto out; + } + + /* Generate Random number using CAAM for OTPMK */ + memset(otpmk_random, 0, sizeof(otpmk_random)); + if (get_rand_bytes_hw((uint8_t *)otpmk_random, + sizeof(otpmk_random)) != 0) { + ret = ERROR_OTPMK_SEC_ERROR; + goto out; + } + + /* Run hamming over random no. to make OTPMK */ + otpmk_make_code_word_256((uint8_t *)otpmk_random, false); + + /* Swap OTPMK */ + fuse_hdr->otpmk[0] = otpmk_random[7]; + fuse_hdr->otpmk[1] = otpmk_random[6]; + fuse_hdr->otpmk[2] = otpmk_random[5]; + fuse_hdr->otpmk[3] = otpmk_random[4]; + fuse_hdr->otpmk[4] = otpmk_random[3]; + fuse_hdr->otpmk[5] = otpmk_random[2]; + fuse_hdr->otpmk[6] = otpmk_random[1]; + fuse_hdr->otpmk[7] = otpmk_random[0]; + break; + + case PROG_OTPMK_USER: + break; + + case PROG_OTPMK_RANDOM_MIN: + /* Here assumption is that user is aware of minimal OTPMK + * already blown. + */ + + /* Generate Random number using CAAM for OTPMK */ + if (is_sec_enabled() == false) { + ret = ERROR_OTPMK_SEC_DISABLED; + goto out; + } + + memset(otpmk_random, 0, sizeof(otpmk_random)); + if (get_rand_bytes_hw((uint8_t *)otpmk_random, + sizeof(otpmk_random)) != 0) { + ret = ERROR_OTPMK_SEC_ERROR; + goto out; + } + + /* Run hamming over random no. to make OTPMK */ + otpmk_make_code_word_256((uint8_t *)otpmk_random, true); + + /* Swap OTPMK */ + fuse_hdr->otpmk[0] = otpmk_random[7]; + fuse_hdr->otpmk[1] = otpmk_random[6]; + fuse_hdr->otpmk[2] = otpmk_random[5]; + fuse_hdr->otpmk[3] = otpmk_random[4]; + fuse_hdr->otpmk[4] = otpmk_random[3]; + fuse_hdr->otpmk[5] = otpmk_random[2]; + fuse_hdr->otpmk[6] = otpmk_random[1]; + fuse_hdr->otpmk[7] = otpmk_random[0]; + break; + + case PROG_OTPMK_USER_MIN: + /* + * Here assumption is that user is aware of minimal OTPMK + * already blown. Check if minimal bits are set in user + * supplied OTPMK. + */ + if ((fuse_hdr->otpmk[0] & OTPMK_MIM_BITS_MASK) != + OTPMK_MIM_BITS_MASK) { + ret = ERROR_OTPMK_USER_MIN; + goto out; + } + break; + + default: + ret = 0; + goto out; + } + + ret = write_fuses(sfp_ccsr_regs->otpmk, fuse_hdr->otpmk, 8); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_OTPMK_ALREADY_BLOWN + : ERROR_OTPMK_WRITE; + } else { + /* Check for DRV hamming error */ + if ((sfp_read32((void *)(get_sfp_addr() + SFP_SVHESR_OFFSET)) + & SFP_SVHESR_OTPMK_MASK) != 0) { + ret = ERROR_OTPMK_HAMMING_ERROR; + } + } + +out: + return ret; +} + +/* This function program OSPR1 in fuse registers. + */ +static int prog_ospr1(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret; + uint32_t mask = 0; + +#ifdef NXP_SFP_VER_3_4 + if (((fuse_hdr->flags >> FLAG_MC_SHIFT) & 0x1) != 0) { + mask = OSPR1_MC_MASK; + } +#endif + if (((fuse_hdr->flags >> FLAG_DBG_LVL_SHIFT) & 0x1) != 0) { + mask = mask | OSPR1_DBG_LVL_MASK; + } + + ret = write_a_fuse(&sfp_ccsr_regs->ospr1, &fuse_hdr->ospr1, mask); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_OSPR1_ALREADY_BLOWN + : ERROR_OSPR1_WRITE; + } + + return ret; +} + +/* This function program SYSCFG in fuse registers. + */ +static int prog_syscfg(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret; + + /* Check if SYSCFG already blown or not */ + ret = write_a_fuse(&sfp_ccsr_regs->ospr, &fuse_hdr->sc, OSPR0_SC_MASK); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_SC_ALREADY_BLOWN + : ERROR_SC_WRITE; + } + + return ret; +} + +/* This function does fuse provisioning. + */ +int provision_fuses(unsigned long long fuse_scr_addr, + bool en_povdd_status) +{ + struct fuse_hdr_t *fuse_hdr = NULL; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(get_sfp_addr() + + SFP_FUSE_REGS_OFFSET); + int ret = 0; + + fuse_hdr = (struct fuse_hdr_t *)fuse_scr_addr; + + /* + * Check for Write Protect (WP) fuse. If blown then do + * no fuse provisioning. + */ + if ((sfp_read32(&sfp_ccsr_regs->ospr) & 0x1) != 0) { + goto out; + } + + /* Check if SRKH to be blown or not */ + if (((fuse_hdr->flags >> FLAG_SRKH_SHIFT) & 0x1) != 0) { + INFO("Fuse: Program SRKH\n"); + ret = prog_srkh(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + /* Check if OEMUID to be blown or not */ + if (((fuse_hdr->flags >> FLAG_OUID0_SHIFT) & FLAG_OUID_MASK) != 0) { + INFO("Fuse: Program OEMUIDs\n"); + ret = prog_oemuid(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + /* Check if Debug values to be blown or not */ + if (((fuse_hdr->flags >> FLAG_DCV0_SHIFT) & FLAG_DEBUG_MASK) != 0) { + INFO("Fuse: Program Debug values\n"); + ret = prog_debug(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + /* Check if OTPMK values to be blown or not */ + if (((fuse_hdr->flags >> FLAG_OTPMK_SHIFT) & PROG_NO_OTPMK) != + PROG_NO_OTPMK) { + INFO("Fuse: Program OTPMK\n"); + ret = prog_otpmk(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + + /* Check if MC or DBG LVL to be blown or not */ + if ((((fuse_hdr->flags >> FLAG_MC_SHIFT) & 0x1) != 0) || + (((fuse_hdr->flags >> FLAG_DBG_LVL_SHIFT) & 0x1) != 0)) { + INFO("Fuse: Program OSPR1\n"); + ret = prog_ospr1(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + /* Check if SYSCFG to be blown or not */ + if (((fuse_hdr->flags >> FLAG_SYSCFG_SHIFT) & 0x1) != 0) { + INFO("Fuse: Program SYSCFG\n"); + ret = prog_syscfg(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + if (en_povdd_status) { + ret = sfp_program_fuses(); + if (ret != 0) { + error_handler(ret); + goto out; + } + } +out: + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/sfp/sfp.c b/arm-trusted-firmware/drivers/nxp/sfp/sfp.c new file mode 100644 index 0000000..e06c6b9 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sfp/sfp.c @@ -0,0 +1,167 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static uintptr_t g_nxp_sfp_addr; +static uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)] + __aligned(CACHE_WRITEBACK_GRANULE); + +void sfp_init(uintptr_t nxp_sfp_addr) +{ + g_nxp_sfp_addr = nxp_sfp_addr; +} + +uintptr_t get_sfp_addr(void) +{ + return g_nxp_sfp_addr; +} + +uint32_t *get_sfp_srk_hash(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = + (void *) (g_nxp_sfp_addr + SFP_FUSE_REGS_OFFSET); + int i = 0; + + /* Add comparison of hash with SFP hash here */ + for (i = 0; i < SRK_HASH_SIZE/sizeof(uint32_t); i++) + srk_hash[i] = + mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]); + + return srk_hash; +} + +void set_sfp_wr_disable(void) +{ + /* + * Mark SFP Write Disable and Write Disable Lock + * Bit to prevent write to SFP fuses like + * OUID's, Key Revocation fuse etc + */ + void *sfpcr = (void *)(g_nxp_sfp_addr + SFP_SFPCR_OFFSET); + uint32_t sfpcr_val; + + sfpcr_val = sfp_read32(sfpcr); + sfpcr_val |= (SFP_SFPCR_WD | SFP_SFPCR_WDL); + sfp_write32(sfpcr, sfpcr_val); +} + +int sfp_program_fuses(void) +{ + uint32_t ingr; + uint32_t sfp_cmd_status = 0U; + int ret = 0; + + /* Program SFP fuses from mirror registers */ + sfp_write32((void *)(g_nxp_sfp_addr + SFP_INGR_OFFSET), + SFP_INGR_PROGFB_CMD); + + /* Wait until fuse programming is successful */ + do { + ingr = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET); + } while (ingr & SFP_INGR_PROGFB_CMD); + + /* Check for SFP fuse programming error */ + sfp_cmd_status = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET) + & SFP_INGR_ERROR_MASK; + + if (sfp_cmd_status != 0U) { + return ERROR_PROGFB_CMD; + } + + return ret; +} + +uint32_t sfp_read_oem_uid(uint8_t oem_uid) +{ + uint32_t val = 0U; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if (oem_uid > MAX_OEM_UID) { + ERROR("Invalid OEM UID received.\n"); + return ERROR_OEMUID_WRITE; + } + + val = sfp_read32(&sfp_ccsr_regs->oem_uid[oem_uid]); + + return val; +} + +/* + * return val: 0 - No update required. + * 1 - successful update done. + * ERROR_OEMUID_WRITE - Invalid OEM UID + */ +uint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val) +{ + uint32_t val = 0U; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + val = sfp_read_oem_uid(oem_uid); + + if (val == ERROR_OEMUID_WRITE) { + return ERROR_OEMUID_WRITE; + } + + /* Counter already set. No need to do anything */ + if ((val & sfp_val) != 0U) { + return 0U; + } + + val |= sfp_val; + + INFO("SFP Value is %x for setting sfp_val = %d\n", val, sfp_val); + + sfp_write32(&sfp_ccsr_regs->oem_uid[oem_uid], val); + + return 1U; +} + +int sfp_check_its(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_ITS_MASK) != 0) { + return 1; + } else { + return 0; + } +} + +int sfp_check_oem_wp(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_WP_MASK) != 0) { + return 1; + } else { + return 0; + } +} + +/* This function returns ospr's key_revoc values.*/ +uint32_t get_key_revoc(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + return (sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_KEY_REVOC_MASK) >> + OSPR_KEY_REVOC_SHIFT; +} diff --git a/arm-trusted-firmware/drivers/nxp/sfp/sfp.mk b/arm-trusted-firmware/drivers/nxp/sfp/sfp.mk new file mode 100644 index 0000000..de708c5 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sfp/sfp.mk @@ -0,0 +1,33 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${SFP_ADDED},) + +SFP_ADDED := 1 +$(eval $(call add_define, NXP_SFP_ENABLED)) + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/sfp + +SFP_SOURCES += $(PLAT_DRIVERS_PATH)/sfp/sfp.c + +ifeq (${FUSE_PROG}, 1) +SFP_BL2_SOURCES += $(PLAT_DRIVERS_PATH)/sfp/fuse_prov.c +endif + +ifeq (${BL_COMM_SFP_NEEDED},yes) +BL_COMMON_SOURCES += ${SFP_SOURCES} +BL2_SOURCES += ${SFP_BL2_SOURCES} +else +ifeq (${BL2_SFP_NEEDED},yes) +BL2_SOURCES += ${SFP_SOURCES}\ + ${SFP_BL2_SOURCES} +endif +ifeq (${BL31_SFP_NEEDED},yes) +BL31_SOURCES += ${SFP_SOURCES} +endif +endif +endif +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c b/arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c new file mode 100644 index 0000000..8eecd2e --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c @@ -0,0 +1,143 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static uintptr_t g_nxp_timer_addr; +static timer_ops_t ops; + +uint64_t get_timer_val(uint64_t start) +{ + uint64_t cntpct; + + isb(); + cntpct = read_cntpct_el0(); + return (cntpct * 1000ULL / read_cntfrq_el0() - start); +} + +static uint32_t timer_get_value(void) +{ + uint64_t cntpct; + + isb(); + cntpct = read_cntpct_el0(); +#ifdef ERRATA_SOC_A008585 + uint8_t max_fetch_count = 10U; + /* This erratum number needs to be confirmed to match ARM document */ + uint64_t temp; + + isb(); + temp = read_cntpct_el0(); + + while (temp != cntpct && max_fetch_count) { + isb(); + cntpct = read_cntpct_el0(); + isb(); + temp = read_cntpct_el0(); + max_fetch_count--; + } +#endif + + /* + * 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)(~cntpct); +} + +static void delay_timer_init_args(uint32_t mult, uint32_t div) +{ + ops.get_timer_value = timer_get_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); +} + +/* + * Initialise the nxp on-chip free rolling usec counter as the delay + * timer. + */ +void delay_timer_init(uintptr_t nxp_timer_addr) +{ + /* Value in ticks */ + unsigned int mult = MHZ_TICKS_PER_SEC; + + unsigned int div; + + unsigned int counter_base_frequency = plat_get_syscnt_freq2(); + + g_nxp_timer_addr = nxp_timer_addr; + /* Rounding off the Counter Frequency to MHZ_TICKS_PER_SEC */ + if (counter_base_frequency > MHZ_TICKS_PER_SEC) { + counter_base_frequency = (counter_base_frequency + / MHZ_TICKS_PER_SEC) + * MHZ_TICKS_PER_SEC; + } else { + counter_base_frequency = (counter_base_frequency + / KHZ_TICKS_PER_SEC) + * KHZ_TICKS_PER_SEC; + } + + /* Value in ticks per second (Hz) */ + div = counter_base_frequency; + + /* Reduce multiplier and divider by dividing them repeatedly by 10 */ + while ((mult % 10U == 0U) && (div % 10U == 0U)) { + mult /= 10U; + div /= 10U; + } + + /* Enable and initialize the System level generic timer */ + mmio_write_32(g_nxp_timer_addr + CNTCR_OFF, + CNTCR_FCREQ(0) | CNTCR_EN); + + delay_timer_init_args(mult, div); +} + + +#ifdef IMAGE_BL31 +/******************************************************************************* + * TBD: Configures access to the system counter timer module. + ******************************************************************************/ +void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base, + uint8_t ls_config_cntacr, + uint8_t plat_ls_ns_timer_frame_id) +{ + unsigned int reg_val; + + if (ls_config_cntacr == 1U) { + reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT); + reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT); + reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT); + mmio_write_32(ls_sys_timctl_base + + CNTACR_BASE(plat_ls_ns_timer_frame_id), reg_val); + mmio_write_32(ls_sys_timctl_base, plat_get_syscnt_freq2()); + } + + reg_val = (1U << CNTNSAR_NS_SHIFT(plat_ls_ns_timer_frame_id)); + mmio_write_32(ls_sys_timctl_base + CNTNSAR, reg_val); +} + +void enable_init_timer(void) +{ + /* Enable and initialize the System level generic timer */ + mmio_write_32(g_nxp_timer_addr + CNTCR_OFF, + CNTCR_FCREQ(0) | CNTCR_EN); +} +#endif diff --git a/arm-trusted-firmware/drivers/nxp/timer/timer.mk b/arm-trusted-firmware/drivers/nxp/timer/timer.mk new file mode 100644 index 0000000..d658d19 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/timer/timer.mk @@ -0,0 +1,25 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_TIMER},) + +ADD_TIMER := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/timer +TIMER_SOURCES += drivers/delay_timer/delay_timer.c \ + $(PLAT_DRIVERS_PATH)/timer/nxp_timer.c + +ifeq (${BL_COMM_TIMER_NEEDED},yes) +BL_COMMON_SOURCES += ${TIMER_SOURCES} +else +ifeq (${BL2_TIMER_NEEDED},yes) +BL2_SOURCES += ${TIMER_SOURCES} +endif +ifeq (${BL31_TIMER_NEEDED},yes) +BL31_SOURCES += ${TIMER_SOURCES} +endif +endif +endif diff --git a/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c b/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c new file mode 100644 index 0000000..13cf3b9 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c @@ -0,0 +1,152 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#pragma weak populate_tzc380_reg_list + +#ifdef DEFAULT_TZASC_CONFIG +/* + * Typical Memory map of DRAM0 + * |-----------NXP_NS_DRAM_ADDR ( = NXP_DRAM0_ADDR)----------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * | | + * |------- (NXP_NS_DRAM_ADDR + NXP_NS_DRAM_SIZE - 1) -------| + * |-----------------NXP_SECURE_DRAM_ADDR--------------------| + * | | + * | | + * | | + * | SECURE REGION (= 64MB) | + * | | + * | | + * | | + * |--- (NXP_SECURE_DRAM_ADDR + NXP_SECURE_DRAM_SIZE - 1)----| + * |-----------------NXP_SP_SHRD_DRAM_ADDR-------------------| + * | | + * | Secure EL1 Payload SHARED REGION (= 2MB) | + * | | + * |-----------(NXP_DRAM0_ADDR + NXP_DRAM0_SIZE - 1)---------| + * + * + * + * Typical Memory map of DRAM1 + * |---------------------NXP_DRAM1_ADDR----------------------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * |---(NXP_DRAM1_ADDR + Dynamically calculated Size - 1) ---| + * + * + * Typical Memory map of DRAM2 + * |---------------------NXP_DRAM2_ADDR----------------------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * |---(NXP_DRAM2_ADDR + Dynamically calculated Size - 1) ---| + */ + +/***************************************************************************** + * This function sets up access permissions on memory regions + * + * Input: + * tzc380_reg_list : TZC380 Region List + * dram_idx : DRAM index + * list_idx : TZC380 Region List Index + * dram_start_addr : Start address of DRAM at dram_idx. + * dram_size : Size of DRAM at dram_idx. + * secure_dram_sz : Secure DRAM Size + * shrd_dram_sz : Shared DRAM Size + * + * Out: + * list_idx : last populated index + 1 + * + ****************************************************************************/ +int populate_tzc380_reg_list(struct tzc380_reg *tzc380_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz) +{ + /* Region 0: Default region marked as Non-Secure */ + if (list_idx == 0) { + tzc380_reg_list[list_idx].secure = TZC_ATTR_SP_NS_RW; + tzc380_reg_list[list_idx].enabled = TZC_ATTR_REGION_DISABLE; + tzc380_reg_list[list_idx].addr = UL(0x0); + tzc380_reg_list[list_idx].size = 0x0; + tzc380_reg_list[list_idx].sub_mask = 0x0; /* all enabled */ + list_idx++; + } + /* Continue with list entries for index > 0 */ + if (dram_idx == 0) { + /* TZC Region 1 on DRAM0 for Secure Memory*/ + tzc380_reg_list[list_idx].secure = TZC_ATTR_SP_S_RW; + tzc380_reg_list[list_idx].enabled = TZC_ATTR_REGION_ENABLE; + tzc380_reg_list[list_idx].addr = dram_start_addr + dram_size; + tzc380_reg_list[list_idx].size = secure_dram_sz; + tzc380_reg_list[list_idx].sub_mask = 0x0; /* all enabled */ + list_idx++; + + /* TZC Region 2 on DRAM0 for Shared Memory*/ + tzc380_reg_list[list_idx].secure = TZC_ATTR_SP_S_RW; + tzc380_reg_list[list_idx].enabled = TZC_ATTR_REGION_ENABLE; + tzc380_reg_list[list_idx].addr = dram_start_addr + dram_size + secure_dram_sz; + tzc380_reg_list[list_idx].size = shrd_dram_sz; + tzc380_reg_list[list_idx].sub_mask = 0x0; /* all enabled */ + list_idx++; + + } + + return list_idx; +} +#else +int populate_tzc380_reg_list(struct tzc380_reg *tzc380_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz) +{ + ERROR("tzc380_reg_list used is not a default list\n"); + ERROR("%s needs to be over-written.\n", __func__); + return 0; +} +#endif /* DEFAULT_TZASC_CONFIG */ + + +void mem_access_setup(uintptr_t base, uint32_t total_regions, + struct tzc380_reg *tzc380_reg_list) +{ + uint32_t indx = 0; + unsigned int attr_value; + + VERBOSE("Configuring TrustZone Controller tzc380\n"); + + tzc380_init(base); + + tzc380_set_action(TZC_ACTION_NONE); + + for (indx = 0; indx < total_regions; indx++) { + attr_value = tzc380_reg_list[indx].secure | + TZC_ATTR_SUBREG_DIS(tzc380_reg_list[indx].sub_mask) | + TZC_ATTR_REGION_SIZE(tzc380_reg_list[indx].size) | + tzc380_reg_list[indx].enabled; + + tzc380_configure_region(indx, tzc380_reg_list[indx].addr, + attr_value); + } + + tzc380_set_action(TZC_ACTION_ERR); +} diff --git a/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c b/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c new file mode 100644 index 0000000..4fe5221 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c @@ -0,0 +1,187 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include + +#pragma weak populate_tzc400_reg_list + +#ifdef DEFAULT_TZASC_CONFIG +/* + * Typical Memory map of DRAM0 + * |-----------NXP_NS_DRAM_ADDR ( = NXP_DRAM0_ADDR)----------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * | | + * |------- (NXP_NS_DRAM_ADDR + NXP_NS_DRAM_SIZE - 1) -------| + * |-----------------NXP_SECURE_DRAM_ADDR--------------------| + * | | + * | | + * | | + * | SECURE REGION (= 64MB) | + * | | + * | | + * | | + * |--- (NXP_SECURE_DRAM_ADDR + NXP_SECURE_DRAM_SIZE - 1)----| + * |-----------------NXP_SP_SHRD_DRAM_ADDR-------------------| + * | | + * | Secure EL1 Payload SHARED REGION (= 2MB) | + * | | + * |-----------(NXP_DRAM0_ADDR + NXP_DRAM0_SIZE - 1)---------| + * + * + * + * Typical Memory map of DRAM1 + * |---------------------NXP_DRAM1_ADDR----------------------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * |---(NXP_DRAM1_ADDR + Dynamically calculated Size - 1) ---| + * + * + * Typical Memory map of DRAM2 + * |---------------------NXP_DRAM2_ADDR----------------------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * |---(NXP_DRAM2_ADDR + Dynamically calculated Size - 1) ---| + */ + +/***************************************************************************** + * This function sets up access permissions on memory regions + * + * Input: + * tzc400_reg_list : TZC400 Region List + * dram_idx : DRAM index + * list_idx : TZC400 Region List Index + * dram_start_addr : Start address of DRAM at dram_idx. + * dram_size : Size of DRAM at dram_idx. + * secure_dram_sz : Secure DRAM Size + * shrd_dram_sz : Shared DRAM Size + * + * Out: + * list_idx : last populated index + 1 + * + ****************************************************************************/ +int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz) +{ + if (list_idx == 0) { + /* No need to configure TZC Region 0 in this list. + */ + list_idx++; + } + /* Continue with list entries for index > 0 */ + if (dram_idx == 0) { + /* TZC Region 1 on DRAM0 for Secure Memory*/ + tzc400_reg_list[list_idx].reg_filter_en = 1; + tzc400_reg_list[list_idx].start_addr = dram_start_addr + dram_size; + tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size + + secure_dram_sz - 1; + tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR; + tzc400_reg_list[list_idx].nsaid_permissions = TZC_REGION_NS_NONE; + list_idx++; + + /* TZC Region 2 on DRAM0 for Shared Memory*/ + tzc400_reg_list[list_idx].reg_filter_en = 1; + tzc400_reg_list[list_idx].start_addr = dram_start_addr + dram_size + + secure_dram_sz; + tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size + + secure_dram_sz + + shrd_dram_sz + - 1; + tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR; + tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID; + list_idx++; + + /* TZC Region 3 on DRAM0 for Non-Secure Memory*/ + tzc400_reg_list[list_idx].reg_filter_en = 1; + tzc400_reg_list[list_idx].start_addr = dram_start_addr; + tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size + - 1; + tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR; + tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID; + list_idx++; + } else { + /* TZC Region 3+i on DRAM(> 0) for Non-Secure Memory*/ + tzc400_reg_list[list_idx].reg_filter_en = 1; + tzc400_reg_list[list_idx].start_addr = dram_start_addr; + tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size + - 1; + tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR; + tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID; + list_idx++; + } + + return list_idx; +} +#else +int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz) +{ + ERROR("tzc400_reg_list used is not a default list\n"); + ERROR("%s needs to be over-written.\n", __func__); + return 0; +} +#endif /* DEFAULT_TZASC_CONFIG */ + +/******************************************************************************* + * Configure memory access permissions + * - Region 0 with no access; + * - Region 1 to 4 as per the tzc400_reg_list populated by + * function populate_tzc400_reg_list() with default for all the SoC. + ******************************************************************************/ +void mem_access_setup(uintptr_t base, uint32_t total_regions, + struct tzc400_reg *tzc400_reg_list) +{ + uint32_t list_indx = 0U; + + INFO("Configuring TrustZone Controller\n"); + + tzc400_init(base); + + /* Disable filters. */ + tzc400_disable_filters(); + + /* Region 0 set to no access by default */ + tzc400_configure_region0(TZC_REGION_S_NONE, 0U); + + for (list_indx = 1U; list_indx < total_regions; list_indx++) { + tzc400_configure_region( + tzc400_reg_list[list_indx].reg_filter_en, + list_indx, + tzc400_reg_list[list_indx].start_addr, + tzc400_reg_list[list_indx].end_addr, + tzc400_reg_list[list_indx].sec_attr, + tzc400_reg_list[list_indx].nsaid_permissions); + } + + /* + * Raise an exception if a NS device tries to access secure memory + * TODO: Add interrupt handling support. + */ + tzc400_set_action(TZC_ACTION_ERR); + + /* Enable filters. */ + tzc400_enable_filters(); +} diff --git a/arm-trusted-firmware/drivers/nxp/tzc/tzc.mk b/arm-trusted-firmware/drivers/nxp/tzc/tzc.mk new file mode 100644 index 0000000..4418bfc --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/tzc/tzc.mk @@ -0,0 +1,40 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_TZASC},) + +ADD_TZASC := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/tzc + +ifeq ($(TZC_ID), TZC400) +TZASC_SOURCES += drivers/arm/tzc/tzc400.c\ + $(PLAT_DRIVERS_PATH)/tzc/plat_tzc400.c +else +ifeq ($(TZC_ID), TZC380) +TZASC_SOURCES += drivers/arm/tzc/tzc380.c\ + $(PLAT_DRIVERS_PATH)/tzc/plat_tzc380.c +else +ifeq ($(TZC_ID), NONE) + $(info -> No TZC present on platform) +else + $(error -> TZC type not set!) +endif +endif +endif + +ifeq (${BL_COMM_TZASC_NEEDED},yes) +BL_COMMON_SOURCES += ${TZASC_SOURCES} +else +ifeq (${BL2_TZASC_NEEDED},yes) +BL2_SOURCES += ${TZASC_SOURCES} +endif +ifeq (${BL31_TZASC_NEEDED},yes) +BL31_SOURCES += ${TZASC_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/partition/gpt.c b/arm-trusted-firmware/drivers/partition/gpt.c new file mode 100644 index 0000000..ee0bddf --- /dev/null +++ b/arm-trusted-firmware/drivers/partition/gpt.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +static int unicode_to_ascii(unsigned short *str_in, unsigned char *str_out) +{ + uint8_t *name; + int i; + + assert((str_in != NULL) && (str_out != NULL)); + + name = (uint8_t *)str_in; + + assert(name[0] != '\0'); + + /* check whether the unicode string is valid */ + for (i = 1; i < (EFI_NAMELEN << 1); i += 2) { + if (name[i] != '\0') + return -EINVAL; + } + /* convert the unicode string to ascii string */ + for (i = 0; i < (EFI_NAMELEN << 1); i += 2) { + str_out[i >> 1] = name[i]; + if (name[i] == '\0') + break; + } + return 0; +} + +int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry) +{ + int result; + + assert((gpt_entry != NULL) && (entry != NULL)); + + if ((gpt_entry->first_lba == 0) && (gpt_entry->last_lba == 0)) { + return -EINVAL; + } + + zeromem(entry, sizeof(partition_entry_t)); + result = unicode_to_ascii(gpt_entry->name, (uint8_t *)entry->name); + if (result != 0) { + return result; + } + entry->start = (uint64_t)gpt_entry->first_lba * + PLAT_PARTITION_BLOCK_SIZE; + entry->length = (uint64_t)(gpt_entry->last_lba - + gpt_entry->first_lba + 1) * + PLAT_PARTITION_BLOCK_SIZE; + guidcpy(&entry->part_guid, &gpt_entry->unique_uuid); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/partition/partition.c b/arm-trusted-firmware/drivers/partition/partition.c new file mode 100644 index 0000000..7706f88 --- /dev/null +++ b/arm-trusted-firmware/drivers/partition/partition.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static uint8_t mbr_sector[PLAT_PARTITION_BLOCK_SIZE]; +static partition_entry_list_t list; + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +static void dump_entries(int num) +{ + char name[EFI_NAMELEN]; + int i, j, len; + + VERBOSE("Partition table with %d entries:\n", num); + for (i = 0; i < num; i++) { + len = snprintf(name, EFI_NAMELEN, "%s", list.list[i].name); + for (j = 0; j < EFI_NAMELEN - len - 1; j++) { + name[len + j] = ' '; + } + name[EFI_NAMELEN - 1] = '\0'; + VERBOSE("%d: %s %" PRIx64 "-%" PRIx64 "\n", i + 1, name, list.list[i].start, + list.list[i].start + list.list[i].length - 4); + } +} +#else +#define dump_entries(num) ((void)num) +#endif + +/* + * Load the first sector that carries MBR header. + * The MBR boot signature should be always valid whether it's MBR or GPT. + */ +static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) +{ + size_t bytes_read; + uintptr_t offset; + int result; + + assert(mbr_entry != NULL); + /* MBR partition table is in LBA0. */ + result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); + if (result != 0) { + WARN("Failed to seek (%i)\n", result); + return result; + } + result = io_read(image_handle, (uintptr_t)&mbr_sector, + PLAT_PARTITION_BLOCK_SIZE, &bytes_read); + if (result != 0) { + WARN("Failed to read data (%i)\n", result); + return result; + } + + /* Check MBR boot signature. */ + if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || + (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { + return -ENOENT; + } + offset = (uintptr_t)&mbr_sector + MBR_PRIMARY_ENTRY_OFFSET; + memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t)); + return 0; +} + +/* + * Load GPT header and check the GPT signature. + * If partition numbers could be found, check & update it. + */ +static int load_gpt_header(uintptr_t image_handle) +{ + gpt_header_t header; + size_t bytes_read; + int result; + + result = io_seek(image_handle, IO_SEEK_SET, GPT_HEADER_OFFSET); + if (result != 0) { + return result; + } + result = io_read(image_handle, (uintptr_t)&header, + sizeof(gpt_header_t), &bytes_read); + if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) { + return result; + } + if (memcmp(header.signature, GPT_SIGNATURE, + sizeof(header.signature)) != 0) { + return -EINVAL; + } + + /* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */ + list.entry_count = header.list_num; + if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) { + list.entry_count = PLAT_PARTITION_MAX_ENTRIES; + } + return 0; +} + +static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry, + int part_number) +{ + size_t bytes_read; + uintptr_t offset; + int result; + + assert(mbr_entry != NULL); + /* MBR partition table is in LBA0. */ + result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); + if (result != 0) { + WARN("Failed to seek (%i)\n", result); + return result; + } + result = io_read(image_handle, (uintptr_t)&mbr_sector, + PLAT_PARTITION_BLOCK_SIZE, &bytes_read); + if (result != 0) { + WARN("Failed to read data (%i)\n", result); + return result; + } + + /* Check MBR boot signature. */ + if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || + (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { + return -ENOENT; + } + offset = (uintptr_t)&mbr_sector + + MBR_PRIMARY_ENTRY_OFFSET + + MBR_PRIMARY_ENTRY_SIZE * part_number; + memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t)); + + return 0; +} + +static int load_mbr_entries(uintptr_t image_handle) +{ + mbr_entry_t mbr_entry; + int i; + + list.entry_count = MBR_PRIMARY_ENTRY_NUMBER; + + for (i = 0; i < list.entry_count; i++) { + load_mbr_entry(image_handle, &mbr_entry, i); + list.list[i].start = mbr_entry.first_lba * 512; + list.list[i].length = mbr_entry.sector_nums * 512; + list.list[i].name[0] = mbr_entry.type; + } + + return 0; +} + +static int load_gpt_entry(uintptr_t image_handle, gpt_entry_t *entry) +{ + size_t bytes_read; + int result; + + assert(entry != NULL); + result = io_read(image_handle, (uintptr_t)entry, sizeof(gpt_entry_t), + &bytes_read); + if (sizeof(gpt_entry_t) != bytes_read) + return -EINVAL; + return result; +} + +static int verify_partition_gpt(uintptr_t image_handle) +{ + gpt_entry_t entry; + int result, i; + + for (i = 0; i < list.entry_count; i++) { + result = load_gpt_entry(image_handle, &entry); + assert(result == 0); + result = parse_gpt_entry(&entry, &list.list[i]); + if (result != 0) { + break; + } + } + if (i == 0) { + return -EINVAL; + } + /* + * Only records the valid partition number that is loaded from + * partition table. + */ + list.entry_count = i; + dump_entries(list.entry_count); + + return 0; +} + +int load_partition_table(unsigned int image_id) +{ + uintptr_t dev_handle, image_handle, image_spec = 0; + mbr_entry_t mbr_entry; + int result; + + result = plat_get_image_source(image_id, &dev_handle, &image_spec); + if (result != 0) { + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, result); + return result; + } + + result = io_open(dev_handle, image_spec, &image_handle); + if (result != 0) { + WARN("Failed to access image id=%u (%i)\n", image_id, result); + return result; + } + + result = load_mbr_header(image_handle, &mbr_entry); + if (result != 0) { + WARN("Failed to access image id=%u (%i)\n", image_id, result); + return result; + } + if (mbr_entry.type == PARTITION_TYPE_GPT) { + result = load_gpt_header(image_handle); + assert(result == 0); + result = io_seek(image_handle, IO_SEEK_SET, GPT_ENTRY_OFFSET); + assert(result == 0); + result = verify_partition_gpt(image_handle); + } else { + result = load_mbr_entries(image_handle); + } + + io_close(image_handle); + return result; +} + +const partition_entry_t *get_partition_entry(const char *name) +{ + int i; + + for (i = 0; i < list.entry_count; i++) { + if (strcmp(name, list.list[i].name) == 0) { + return &list.list[i]; + } + } + return NULL; +} + +const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid) +{ + int i; + + for (i = 0; i < list.entry_count; i++) { + if (guidcmp(part_uuid, &list.list[i].part_guid) == 0) { + return &list.list[i]; + } + } + + return NULL; +} + +const partition_entry_list_t *get_partition_entry_list(void) +{ + return &list; +} + +void partition_init(unsigned int image_id) +{ + load_partition_table(image_id); +} diff --git a/arm-trusted-firmware/drivers/rambus/trng_ip_76.c b/arm-trusted-firmware/drivers/rambus/trng_ip_76.c new file mode 100644 index 0000000..8de12e9 --- /dev/null +++ b/arm-trusted-firmware/drivers/rambus/trng_ip_76.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved. + * + * Based on Linux kernel omap-rng.c - RNG driver for TI OMAP CPU family + * + * Author: Deepak Saxena + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * Mostly based on original driver: + * + * Copyright (C) 2005 Nokia Corporation + * Author: Juha Yrjölä + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define RNG_REG_STATUS_RDY (1 << 0) + +#define RNG_REG_INTACK_RDY_MASK (1 << 0) + +#define RNG_CONTROL_ENABLE_TRNG_MASK (1 << 10) + +#define RNG_CONFIG_NOISE_BLOCKS(val) ((0xff & (val)) << 0) +#define RNG_CONFIG_NOISE_BLK_VAL 0x5 + +#define RNG_CONFIG_SAMPLE_CYCLES(val) ((0xff & (val)) << 16) +#define RNG_CONFIG_SAMPLE_CYCLES_VAL 0x22 + +#define RNG_REG_FRO_ENABLE_MASK 0xffffff +#define RNG_REG_FRO_DETUNE_MASK 0x0 + +#define EIP76_RNG_OUTPUT_SIZE 0x10 +#define EIP76_RNG_WAIT_ROUNDS 10 + +#define RNG_HW_IS_EIP76(ver) ((ver) & (0xff == 0x4C)) +#define RNG_HW_VER_MAJOR(ver) (((ver) & (0xf << 24)) >> 24) +#define RNG_HW_VER_MINOR(ver) (((ver) & (0xf << 20)) >> 20) +#define RNG_HW_VER_PATCH(ver) (((ver) & (0xf << 16)) >> 16) + + +enum { + RNG_OUTPUT_0_REG = 0, + RNG_OUTPUT_1_REG, + RNG_OUTPUT_2_REG, + RNG_OUTPUT_3_REG, + RNG_STATUS_REG, + RNG_INTMASK_REG, + RNG_INTACK_REG, + RNG_CONTROL_REG, + RNG_CONFIG_REG, + RNG_ALARMCNT_REG, + RNG_FROENABLE_REG, + RNG_FRODETUNE_REG, + RNG_ALARMMASK_REG, + RNG_ALARMSTOP_REG, + RNG_REV_REG +}; + +static uint16_t reg_map_eip76[] = { + [RNG_OUTPUT_0_REG] = 0x0, + [RNG_OUTPUT_1_REG] = 0x4, + [RNG_OUTPUT_2_REG] = 0x8, + [RNG_OUTPUT_3_REG] = 0xc, + [RNG_STATUS_REG] = 0x10, + [RNG_INTACK_REG] = 0x10, + [RNG_CONTROL_REG] = 0x14, + [RNG_CONFIG_REG] = 0x18, + [RNG_ALARMCNT_REG] = 0x1c, + [RNG_FROENABLE_REG] = 0x20, + [RNG_FRODETUNE_REG] = 0x24, + [RNG_ALARMMASK_REG] = 0x28, + [RNG_ALARMSTOP_REG] = 0x2c, + [RNG_REV_REG] = 0x7c, +}; + +struct eip76_rng_dev { + uintptr_t base; + uint16_t *regs; +}; + +/* Locals */ +static struct eip76_rng_dev eip76_dev; +static spinlock_t rng_lock; + +static inline uint32_t eip76_rng_read(struct eip76_rng_dev *dev, uint16_t reg) +{ + return mmio_read_32(dev->base + dev->regs[reg]); +} + +static inline void eip76_rng_write(struct eip76_rng_dev *dev, + uint16_t reg, uint32_t val) +{ + mmio_write_32(dev->base + dev->regs[reg], val); +} + +static void eip76_rng_init(struct eip76_rng_dev *dev) +{ + uint32_t val; + + /* Return if RNG is already running. */ + if (eip76_rng_read(dev, RNG_CONTROL_REG) & + RNG_CONTROL_ENABLE_TRNG_MASK) { + return; + } + + /* This field sets the number of 512-bit blocks of raw Noise Source + * output data that must be processed by either the Conditioning + * Function or the SP 800-90 DRBG ‘BC_DF’ functionality to yield + * a ‘full entropy’ output value. As according to [SP 800-90B draft] + * the amount of entropy input to this functionality must be twice + * the amount that is output and the 8-bit samples output by the Noise + * Source are supposed to have one bit of entropy each, the settings + * for this field are as follows: + * - SHA-1 Conditioning Function: + * generates 160 bits output, requiring 2560 sample bits, + * equivalent to 5 blocks of raw Noise Source input. + * - SHA-256 Conditioning Function: + * generates 256 bits output, requiring 4096 sample bits, equivalent + * to 8 blocks of raw Noise Source input. Note that two blocks of 256 + * bits are needed to start or re-seed the SP 800-90 DRBG + * (in the EIP-76d-*-SHA2 configurations) + * - SP 800-90 DRBG ‘BC_DF’ functionality: + * generates 384 bits output, requiring 6144 sample bits, equivalent + * to 12 blocks of raw Noise Source input. + * This field can only be modified when ‘enable_trng’ in TRNG_CONTROL + * is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’ + * bits in TRNG_TEST is ‘1’. Value 0 in this field selects 256 blocks + * of 512 bits to be processed. + */ + val = RNG_CONFIG_NOISE_BLOCKS(RNG_CONFIG_NOISE_BLK_VAL); + + /* This field sets the number of FRO samples that are XOR-ed together + * into one bit to be shifted into the main shift register. + * This value must be such that there is at least one bit of entropy + * (in total) in each 8 bits that are shifted. + * This field can only be modified when ‘enable_trng’ in TRNG_CONTROL + * is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’ + * bits in TRNG_TEST is ‘1’. Value 0 in this field selects 65536 FRO + * samples to be XOR-ed together + */ + val |= RNG_CONFIG_SAMPLE_CYCLES(RNG_CONFIG_SAMPLE_CYCLES_VAL); + eip76_rng_write(dev, RNG_CONFIG_REG, val); + + /* Enable all available FROs */ + eip76_rng_write(dev, RNG_FRODETUNE_REG, RNG_REG_FRO_DETUNE_MASK); + eip76_rng_write(dev, RNG_FROENABLE_REG, RNG_REG_FRO_ENABLE_MASK); + + /* Enable TRNG */ + eip76_rng_write(dev, RNG_CONTROL_REG, RNG_CONTROL_ENABLE_TRNG_MASK); +} + +int32_t eip76_rng_read_rand_buf(void *data, bool wait) +{ + uint32_t i, present; + + if (!eip76_dev.base) /* not initialized */ + return -1; + + for (i = 0; i < EIP76_RNG_WAIT_ROUNDS; i++) { + present = eip76_rng_read(&eip76_dev, RNG_STATUS_REG) & + RNG_REG_STATUS_RDY; + if (present || !wait) { + break; + } + + udelay(10); + } + + if (present != 0U) { + return 0; + } + + memcpy(data, + (void *)(eip76_dev.base + eip76_dev.regs[RNG_OUTPUT_0_REG]), + EIP76_RNG_OUTPUT_SIZE); + + eip76_rng_write(&eip76_dev, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK); + + return EIP76_RNG_OUTPUT_SIZE; +} + +int32_t eip76_rng_probe(uintptr_t base_addr) +{ + uint32_t ver; + + eip76_dev.base = base_addr; + eip76_dev.regs = reg_map_eip76; + + eip76_rng_init(&eip76_dev); + + ver = eip76_rng_read(&eip76_dev, RNG_REV_REG); + + INFO("%s Random Number Generator HW ver. %01x.%01x.%01x\n", + RNG_HW_IS_EIP76(ver) ? "TRNG-IP-76" : "Unknown", + RNG_HW_VER_MAJOR(ver), RNG_HW_VER_MINOR(ver), + RNG_HW_VER_PATCH(ver)); + + return 0; +} + +int32_t eip76_rng_get_random(uint8_t *data, uint32_t len) +{ + static uint8_t rand[EIP76_RNG_OUTPUT_SIZE]; + static uint8_t pos; + uint32_t i; + int32_t ret = 0; + + if (!data) + return -1; + + spin_lock(&rng_lock); + + for (i = 0; i < len; i++) { + if (pos >= EIP76_RNG_OUTPUT_SIZE) { + pos = 0; + } + + if (pos != 0U) { + ret = eip76_rng_read_rand_buf(rand, true); + } + + /* Only advance FIFO index if it is non zero or + * the update from TRNG HW was successful + */ + if (pos || ret > 0) { + data[i] = rand[pos++]; + ret = 0; + } else { + ret = -1; + break; + } + } + + spin_unlock(&rng_lock); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c b/arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c new file mode 100644 index 0000000..4aa86e2 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include "rom_api.h" + +typedef int32_t(*secure_boot_api_f) (uint32_t a, uint32_t b, void *c); +extern int32_t rcar_get_certificate(const int32_t name, uint32_t *cert_addr); + +#define RCAR_IMAGE_ID_MAX (10) +#define RCAR_CERT_MAGIC_NUM (0xE291F358U) +#define RCAR_BOOT_KEY_CERT (0xE6300C00U) +#define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U) +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) +#define MFISOFTMDR (0xE6260600U) +#define MODEMR_MD5_MASK (0x00000020U) +#define MODEMR_MD5_SHIFT (5U) +#define SOFTMD_BOOTMODE_MASK (0x00000001U) +#define SOFTMD_NORMALBOOT (0x1U) + +static secure_boot_api_f secure_boot_api; + +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id) +{ + return 1; +} + +int auth_mod_verify_img(unsigned int img_id, void *ptr, unsigned int len) +{ + int32_t ret = 0, index = 0; + uint32_t cert_addr = 0U; + static const struct img_to_cert_t { + uint32_t id; + int32_t cert; + const char *name; + } image[RCAR_IMAGE_ID_MAX] = { + { BL31_IMAGE_ID, SOC_FW_CONTENT_CERT_ID, "BL31" }, + { BL32_IMAGE_ID, TRUSTED_OS_FW_CONTENT_CERT_ID, "BL32" }, + { BL33_IMAGE_ID, NON_TRUSTED_FW_CONTENT_CERT_ID, "BL33" }, + { BL332_IMAGE_ID, BL332_CERT_ID, "BL332" }, + { BL333_IMAGE_ID, BL333_CERT_ID, "BL333" }, + { BL334_IMAGE_ID, BL334_CERT_ID, "BL334" }, + { BL335_IMAGE_ID, BL335_CERT_ID, "BL335" }, + { BL336_IMAGE_ID, BL336_CERT_ID, "BL336" }, + { BL337_IMAGE_ID, BL337_CERT_ID, "BL337" }, + { BL338_IMAGE_ID, BL338_CERT_ID, "BL338" }, + }; + +#if IMAGE_BL2 + switch (img_id) { + case TRUSTED_KEY_CERT_ID: + case SOC_FW_KEY_CERT_ID: + case TRUSTED_OS_FW_KEY_CERT_ID: + case NON_TRUSTED_FW_KEY_CERT_ID: + case BL332_KEY_CERT_ID: + case BL333_KEY_CERT_ID: + case BL334_KEY_CERT_ID: + case BL335_KEY_CERT_ID: + case BL336_KEY_CERT_ID: + case BL337_KEY_CERT_ID: + case BL338_KEY_CERT_ID: + case SOC_FW_CONTENT_CERT_ID: + case TRUSTED_OS_FW_CONTENT_CERT_ID: + case NON_TRUSTED_FW_CONTENT_CERT_ID: + case BL332_CERT_ID: + case BL333_CERT_ID: + case BL334_CERT_ID: + case BL335_CERT_ID: + case BL336_CERT_ID: + case BL337_CERT_ID: + case BL338_CERT_ID: + return ret; + case BL31_IMAGE_ID: + case BL32_IMAGE_ID: + case BL33_IMAGE_ID: + case BL332_IMAGE_ID: + case BL333_IMAGE_ID: + case BL334_IMAGE_ID: + case BL335_IMAGE_ID: + case BL336_IMAGE_ID: + case BL337_IMAGE_ID: + case BL338_IMAGE_ID: + goto verify_image; + default: + return -1; + } + +verify_image: + for (index = 0; index < RCAR_IMAGE_ID_MAX; index++) { + if (img_id != image[index].id) + continue; + + ret = rcar_get_certificate(image[index].cert, &cert_addr); + break; + } + + if (ret || (index == RCAR_IMAGE_ID_MAX)) { + ERROR("Verification Failed for image id = %d\n", img_id); + return ret; + } +#if RCAR_BL2_DCACHE == 1 + /* clean and disable */ + write_sctlr_el3(read_sctlr_el3() & ~SCTLR_C_BIT); + dcsw_op_all(DCCISW); +#endif + ret = (mmio_read_32(RCAR_BOOT_KEY_CERT_NEW) == RCAR_CERT_MAGIC_NUM) ? + secure_boot_api(RCAR_BOOT_KEY_CERT_NEW, cert_addr, NULL) : + secure_boot_api(RCAR_BOOT_KEY_CERT, cert_addr, NULL); + if (ret) + ERROR("Verification Failed 0x%x, %s\n", ret, image[index].name); + +#if RCAR_BL2_DCACHE == 1 + /* enable */ + write_sctlr_el3(read_sctlr_el3() | SCTLR_C_BIT); +#endif /* RCAR_BL2_DCACHE */ + +#endif /* IMAGE_BL2 */ + return ret; +} + +static int32_t normal_boot_verify(uint32_t a, uint32_t b, void *c) +{ + return 0; +} + +void auth_mod_init(void) +{ +#if RCAR_SECURE_BOOT + uint32_t soft_md = mmio_read_32(MFISOFTMDR) & SOFTMD_BOOTMODE_MASK; + uint32_t md = mmio_read_32(RST_MODEMR) & MODEMR_MD5_MASK; + uint32_t lcs, ret; + + secure_boot_api = (secure_boot_api_f) &rcar_rom_secure_boot_api; + + ret = rcar_rom_get_lcs(&lcs); + if (ret) { + ERROR("BL2: Failed to get the LCS. (%d)\n", ret); + panic(); + } + + switch (lcs) { + case LCS_SE: + if (soft_md == SOFTMD_NORMALBOOT) + secure_boot_api = &normal_boot_verify; + break; + case LCS_SD: + secure_boot_api = &normal_boot_verify; + break; + default: + if (md >> MODEMR_MD5_SHIFT) + secure_boot_api = &normal_boot_verify; + } + + NOTICE("BL2: %s boot\n", + secure_boot_api == &normal_boot_verify ? "Normal" : "Secure"); +#else + NOTICE("BL2: Normal boot\n"); + secure_boot_api = &normal_boot_verify; +#endif +} diff --git a/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c b/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c new file mode 100644 index 0000000..2c939cd --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c @@ -0,0 +1,630 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "avs_driver.h" +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" + +#if (AVS_SETTING_ENABLE == 1) +#if PMIC_ROHM_BD9571 +/* Read PMIC register for debug. 1:enable / 0:disable */ +#define AVS_READ_PMIC_REG_ENABLE 0 +/* The re-try number of times of the AVS setting. */ +#define AVS_RETRY_NUM (1U) +#endif /* PMIC_ROHM_BD9571 */ + +/* Base address of Adaptive Voltage Scaling module registers*/ +#define AVS_BASE (0xE60A0000U) +/* Adaptive Dynamic Voltage ADJust Parameter2 registers */ +#define ADVADJP2 (AVS_BASE + 0x013CU) + +/* Mask VOLCOND bit in ADVADJP2 registers */ +#define ADVADJP2_VOLCOND_MASK (0x000001FFU) /* VOLCOND[8:0] */ + +#if PMIC_ROHM_BD9571 +/* I2C for DVFS bit in CPG registers for module standby and software reset*/ +#define CPG_SYS_DVFS_BIT (0x04000000U) +#endif /* PMIC_ROHM_BD9571 */ +/* ADVFS Module bit in CPG registers for module standby and software reset*/ +#define CPG_SYS_ADVFS_BIT (0x02000000U) + +#if PMIC_ROHM_BD9571 +/* Base address of IICDVFS registers*/ +#define IIC_DVFS_BASE (0xE60B0000U) +/* IIC bus data register */ +#define IIC_ICDR (IIC_DVFS_BASE + 0x0000U) +/* IIC bus control register */ +#define IIC_ICCR (IIC_DVFS_BASE + 0x0004U) +/* IIC bus status register */ +#define IIC_ICSR (IIC_DVFS_BASE + 0x0008U) +/* IIC interrupt control register */ +#define IIC_ICIC (IIC_DVFS_BASE + 0x000CU) +/* IIC clock control register low */ +#define IIC_ICCL (IIC_DVFS_BASE + 0x0010U) +/* IIC clock control register high */ +#define IIC_ICCH (IIC_DVFS_BASE + 0x0014U) + +/* Bit in ICSR register */ +#define ICSR_BUSY (0x10U) +#define ICSR_AL (0x08U) +#define ICSR_TACK (0x04U) +#define ICSR_WAIT (0x02U) +#define ICSR_DTE (0x01U) + +/* Bit in ICIC register */ +#define ICIC_TACKE (0x04U) +#define ICIC_WAITE (0x02U) +#define ICIC_DTEE (0x01U) + +/* I2C bus interface enable */ +#define ICCR_ENABLE (0x80U) +/* Start condition */ +#define ICCR_START (0x94U) +/* Stop condition */ +#define ICCR_STOP (0x90U) +/* Restart condition with change to receive mode change */ +#define ICCR_START_RECV (0x81U) +/* Stop condition for receive mode */ +#define ICCR_STOP_RECV (0xC0U) + +/* Low-level period of SCL */ +#define ICCL_FREQ_8p33M (0x07U) /* for CP Phy 8.3333MHz */ +#define ICCL_FREQ_10M (0x09U) /* for CP Phy 10MHz */ +#define ICCL_FREQ_12p5M (0x0BU) /* for CP Phy 12.5MHz */ +#define ICCL_FREQ_16p66M (0x0EU) /* for CP Phy 16.6666MHz */ +/* High-level period of SCL */ +#define ICCH_FREQ_8p33M (0x01U) /* for CP Phy 8.3333MHz */ +#define ICCH_FREQ_10M (0x02U) /* for CP Phy 10MHz */ +#define ICCH_FREQ_12p5M (0x03U) /* for CP Phy 12.5MHz */ +#define ICCH_FREQ_16p66M (0x05U) /* for CP Phy 16.6666MHz */ + +/* PMIC */ +/* ROHM BD9571 slave address + (W) */ +#define PMIC_W_SLAVE_ADDRESS (0x60U) +/* ROHM BD9571 slave address + (R) */ +#define PMIC_R_SLAVE_ADDRESS (0x61U) +/* ROHM BD9571 DVFS SetVID register */ +#define PMIC_DVFS_SETVID (0x54U) +#endif /* PMIC_ROHM_BD9571 */ + +/* Individual information */ +#define EFUSE_AVS0 (0U) +#define EFUSE_AVS_NUM ARRAY_SIZE(init_vol_tbl) + +typedef struct { + uint32_t avs; /* AVS code */ + uint8_t vol; /* Voltage */ +} initial_voltage_t; + +static const initial_voltage_t init_vol_tbl[] = { + /* AVS code, ROHM BD9571 DVFS SetVID register */ + {0x00U, 0x53U}, /* AVS0, 0.83V */ + {0x01U, 0x52U}, /* AVS1, 0.82V */ + {0x02U, 0x51U}, /* AVS2, 0.81V */ + {0x04U, 0x50U}, /* AVS3, 0.80V */ + {0x08U, 0x4FU}, /* AVS4, 0.79V */ + {0x10U, 0x4EU}, /* AVS5, 0.78V */ + {0x20U, 0x4DU}, /* AVS6, 0.77V */ + {0x40U, 0x4CU} /* AVS7, 0.76V */ +}; + +#if PMIC_ROHM_BD9571 +/* Kind of AVS settings status */ +typedef enum { + avs_status_none = 0, + avs_status_init, + avs_status_start_condition, + avs_status_set_slave_addr, + avs_status_write_reg_addr, + avs_status_write_reg_data, + avs_status_stop_condition, + avs_status_end, + avs_status_complete, + avs_status_al_start, + avs_status_al_transfer, + avs_status_nack, + avs_status_error_stop, + ave_status_error_end +} avs_status_t; + +/* Kind of AVS error */ +typedef enum { + avs_error_none = 0, + avs_error_al, + avs_error_nack +} avs_error_t; + +static avs_status_t avs_status; +static uint32_t avs_retry; +#endif /* PMIC_ROHM_BD9571 */ +static uint32_t efuse_avs = EFUSE_AVS0; + +#if PMIC_ROHM_BD9571 +/* prototype */ +static avs_error_t avs_check_error(void); +static void avs_set_iic_clock(void); +#if AVS_READ_PMIC_REG_ENABLE == 1 +static uint8_t avs_read_pmic_reg(uint8_t addr); +static void avs_poll(uint8_t bit_pos, uint8_t val); +#endif +#endif /* PMIC_ROHM_BD9571 */ +#endif /* (AVS_SETTING_ENABLE==1) */ + +/* + * Initialize to enable the AVS setting. + */ +void rcar_avs_init(void) +{ +#if (AVS_SETTING_ENABLE == 1) + uint32_t val; + +#if PMIC_ROHM_BD9571 + /* Initialize AVS status */ + avs_status = avs_status_init; +#endif /* PMIC_ROHM_BD9571 */ + + /* Enable clock supply to ADVFS. */ + mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, CPG_SYS_ADVFS_BIT); + + /* Read AVS code (Initial values are derived from eFuse) */ + val = mmio_read_32(ADVADJP2) & ADVADJP2_VOLCOND_MASK; + + for (efuse_avs = 0U; efuse_avs < EFUSE_AVS_NUM; efuse_avs++) { + if (val == init_vol_tbl[efuse_avs].avs) + break; + } + + if (efuse_avs >= EFUSE_AVS_NUM) + efuse_avs = EFUSE_AVS0; /* Not applicable */ +#if PMIC_ROHM_BD9571 + /* Enable clock supply to DVFS. */ + mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, CPG_SYS_DVFS_BIT); + + /* Disable I2C module and All internal registers initialized. */ + mmio_write_8(IIC_ICCR, 0x00U); + while ((mmio_read_8(IIC_ICCR) & ICCR_ENABLE) != 0U) { + /* Disable I2C module and all internal registers initialized. */ + mmio_write_8(IIC_ICCR, 0x00U); + } + + /* Set next status */ + avs_status = avs_status_start_condition; + +#endif /* PMIC_ROHM_BD9571 */ +#endif /* (AVS_SETTING_ENABLE==1) */ +} + +/* + * Set the value of register corresponding to the voltage + * by transfer of I2C to PIMC. + */ +void rcar_avs_setting(void) +{ +#if (AVS_SETTING_ENABLE == 1) +#if PMIC_ROHM_BD9571 + avs_error_t err; + + switch (avs_status) { + case avs_status_start_condition: + /* Set ICCR.ICE=1 to activate the I2C module. */ + mmio_write_8(IIC_ICCR, mmio_read_8(IIC_ICCR) | ICCR_ENABLE); + /* Set frequency of 400kHz */ + avs_set_iic_clock(); + /* Set ICIC.TACKE=1, ICIC.WAITE=1, ICIC.DTEE=1 to */ + /* enable interrupt control. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) + | ICIC_TACKE | ICIC_WAITE | ICIC_DTEE); + /* Write H'94 in ICCR to issue start condition */ + mmio_write_8(IIC_ICCR, ICCR_START); + /* Set next status */ + avs_status = avs_status_set_slave_addr; + break; + case avs_status_set_slave_addr: + /* Check error. */ + err = avs_check_error(); + if (err == avs_error_al) { + /* Recovery sequence of just after start. */ + avs_status = avs_status_al_start; + } else if (err == avs_error_nack) { + /* Recovery sequence of detected NACK */ + avs_status = avs_status_nack; + } else { + /* Was data transmission enabled ? */ + if ((mmio_read_8(IIC_ICSR) & ICSR_DTE) == ICSR_DTE) { + /* Clear ICIC.DTEE to disable a DTE interrupt */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) + & (uint8_t) (~ICIC_DTEE)); + /* Send PMIC slave address + (W) */ + mmio_write_8(IIC_ICDR, PMIC_W_SLAVE_ADDRESS); + /* Set next status */ + avs_status = avs_status_write_reg_addr; + } + } + break; + case avs_status_write_reg_addr: + /* Check error. */ + err = avs_check_error(); + if (err == avs_error_al) { + /* Recovery sequence of during data transfer. */ + avs_status = avs_status_al_transfer; + } else if (err == avs_error_nack) { + /* Recovery sequence of detected NACK */ + avs_status = avs_status_nack; + } else { + /* If wait state after data transmission. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) { + /* Write PMIC DVFS_SetVID address */ + mmio_write_8(IIC_ICDR, PMIC_DVFS_SETVID); + /* Clear ICSR.WAIT to exit from wait state. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_WAIT)); + /* Set next status */ + avs_status = avs_status_write_reg_data; + } + } + break; + case avs_status_write_reg_data: + /* Check error. */ + err = avs_check_error(); + if (err == avs_error_al) { + /* Recovery sequence of during data transfer. */ + avs_status = avs_status_al_transfer; + } else if (err == avs_error_nack) { + /* Recovery sequence of detected NACK */ + avs_status = avs_status_nack; + } else { + /* If wait state after data transmission. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) { + /* Dose efuse_avs exceed the number of */ + /* the tables? */ + if (efuse_avs >= EFUSE_AVS_NUM) { + ERROR("%s%s=%u\n", "AVS number of ", + "eFuse is out of range. number", + efuse_avs); + /* Infinite loop */ + panic(); + } + /* Write PMIC DVFS_SetVID value */ + mmio_write_8(IIC_ICDR, + init_vol_tbl[efuse_avs].vol); + /* Clear ICSR.WAIT to exit from wait state. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_WAIT)); + /* Set next status */ + avs_status = avs_status_stop_condition; + } + } + break; + case avs_status_stop_condition: + err = avs_check_error(); + if (err == avs_error_al) { + /* Recovery sequence of during data transfer. */ + avs_status = avs_status_al_transfer; + } else if (err == avs_error_nack) { + /* Recovery sequence of detected NACK */ + avs_status = avs_status_nack; + } else { + /* If wait state after data transmission. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) { + /* Write H'90 in ICCR to issue stop condition */ + mmio_write_8(IIC_ICCR, ICCR_STOP); + /* Clear ICSR.WAIT to exit from wait state. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_WAIT)); + /* Set next status */ + avs_status = avs_status_end; + } + } + break; + case avs_status_end: + /* Is this module not busy?. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_BUSY) == 0U) { + /* Set ICCR=H'00 to disable the I2C module. */ + mmio_write_8(IIC_ICCR, 0x00U); + /* Set next status */ + avs_status = avs_status_complete; + } + break; + case avs_status_al_start: + /* Clear ICSR.AL bit */ + mmio_write_8(IIC_ICSR, (mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_AL))); + /* Transmit a clock pulse */ + mmio_write_8(IIC_ICDR, init_vol_tbl[EFUSE_AVS0].vol); + /* Set next status */ + avs_status = avs_status_error_stop; + break; + case avs_status_al_transfer: + /* Clear ICSR.AL bit */ + mmio_write_8(IIC_ICSR, (mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_AL))); + /* Set next status */ + avs_status = avs_status_error_stop; + break; + case avs_status_nack: + /* Write H'90 in ICCR to issue stop condition */ + mmio_write_8(IIC_ICCR, ICCR_STOP); + /* Disable a WAIT and DTEE interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) + & (uint8_t) (~(ICIC_WAITE | ICIC_DTEE))); + /* Clear ICSR.TACK bit */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_TACK)); + /* Set next status */ + avs_status = ave_status_error_end; + break; + case avs_status_error_stop: + /* If wait state after data transmission. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) { + /* Write H'90 in ICCR to issue stop condition */ + mmio_write_8(IIC_ICCR, ICCR_STOP); + /* Clear ICSR.WAIT to exit from wait state. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_WAIT)); + /* Set next status */ + avs_status = ave_status_error_end; + } + break; + case ave_status_error_end: + /* Is this module not busy?. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_BUSY) == 0U) { + /* Set ICCR=H'00 to disable the I2C module. */ + mmio_write_8(IIC_ICCR, 0x00U); + /* Increment the re-try number of times. */ + avs_retry++; + /* Set start a re-try to status. */ + avs_status = avs_status_start_condition; + } + break; + case avs_status_complete: + /* After "avs_status" became the "avs_status_complete", */ + /* "avs_setting()" function may be called. */ + break; + default: + /* This case is not possible. */ + ERROR("AVS setting is in invalid status. status=%u\n", + avs_status); + /* Infinite loop */ + panic(); + break; + } +#endif /* PMIC_ROHM_BD9571 */ +#endif /* (AVS_SETTING_ENABLE==1) */ +} + +/* + * Finish the AVS setting. + */ +void rcar_avs_end(void) +{ +#if (AVS_SETTING_ENABLE == 1) + uint32_t mstp; + +#if PMIC_ROHM_BD9571 + /* While status is not completion, be repeated. */ + while (avs_status != avs_status_complete) + rcar_avs_setting(); + + NOTICE("AVS setting succeeded. DVFS_SetVID=0x%x\n", + init_vol_tbl[efuse_avs].vol); + +#if AVS_READ_PMIC_REG_ENABLE == 1 + { + uint8_t addr = PMIC_DVFS_SETVID; + uint8_t value = avs_read_pmic_reg(addr); + + NOTICE("Read PMIC register. address=0x%x value=0x%x\n", + addr, value); + } +#endif + + /* Bit of the module which wants to disable clock supply. */ + mstp = CPG_SYS_DVFS_BIT; + /* Disables the supply of clock signal to a module. */ + cpg_write(CPG_SMSTPCR9, mmio_read_32(CPG_SMSTPCR9) | mstp); +#endif /* PMIC_ROHM_BD9571 */ + + /* Bit of the module which wants to disable clock supply. */ + mstp = CPG_SYS_ADVFS_BIT; + /* Disables the supply of clock signal to a module. */ + cpg_write(CPG_SMSTPCR9, mmio_read_32(CPG_SMSTPCR9) | mstp); + +#endif /* (AVS_SETTING_ENABLE==1) */ +} + +#if (AVS_SETTING_ENABLE == 1) +#if PMIC_ROHM_BD9571 +/* + * Check error and judge re-try. + */ +static avs_error_t avs_check_error(void) +{ + avs_error_t ret; + + if ((mmio_read_8(IIC_ICSR) & ICSR_AL) == ICSR_AL) { + NOTICE("%s AVS status=%d Retry=%u\n", + "Loss of arbitration is detected.", avs_status, avs_retry); + /* Check of retry number of times */ + if (avs_retry >= AVS_RETRY_NUM) { + ERROR("AVS setting failed in retry. max=%u\n", + AVS_RETRY_NUM); + /* Infinite loop */ + panic(); + } + /* Set the error detected to error status. */ + ret = avs_error_al; + } else if ((mmio_read_8(IIC_ICSR) & ICSR_TACK) == ICSR_TACK) { + NOTICE("%s AVS status=%d Retry=%u\n", + "Non-acknowledge is detected.", avs_status, avs_retry); + /* Check of retry number of times */ + if (avs_retry >= AVS_RETRY_NUM) { + ERROR("AVS setting failed in retry. max=%u\n", + AVS_RETRY_NUM); + /* Infinite loop */ + panic(); + } + /* Set the error detected to error status. */ + ret = avs_error_nack; + } else { + /* Not error. */ + ret = avs_error_none; + } + return ret; +} + +/* + * Set I2C for DVFS clock. + */ +static void avs_set_iic_clock(void) +{ + uint32_t md_pin; + + /* Read Mode pin register. */ + md_pin = mmio_read_32(RCAR_MODEMR) & CHECK_MD13_MD14; + /* Set the module clock (CP phy) for the IIC-DVFS. */ + /* CP phy is EXTAL / 2. */ + switch (md_pin) { + case MD14_MD13_TYPE_0: /* EXTAL = 16.6666MHz */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_8p33M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_8p33M); + break; + case MD14_MD13_TYPE_1: /* EXTAL = 20MHz */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_10M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_10M); + break; + case MD14_MD13_TYPE_2: /* EXTAL = 25MHz (H3/M3) */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_12p5M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_12p5M); + break; + case MD14_MD13_TYPE_3: /* EXTAL = 33.3333MHz */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_16p66M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_16p66M); + break; + default: /* This case is not possible. */ + /* CP Phy frequency is to be set for the 16.66MHz */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_16p66M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_16p66M); + break; + } +} + +#if AVS_READ_PMIC_REG_ENABLE == 1 +/* + * Read the value of the register of PMIC. + */ +static uint8_t avs_read_pmic_reg(uint8_t addr) +{ + uint8_t reg; + + /* Set ICCR.ICE=1 to activate the I2C module. */ + mmio_write_8(IIC_ICCR, mmio_read_8(IIC_ICCR) | ICCR_ENABLE); + + /* Set frequency of 400kHz */ + avs_set_iic_clock(); + + /* + * Set ICIC.WAITE=1, ICIC.DTEE=1 to enable data transmission + * interrupt and wait interrupt. + */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_WAITE | ICIC_DTEE); + + /* Write H'94 in ICCR to issue start condition */ + mmio_write_8(IIC_ICCR, ICCR_START); + + /* Wait for a until ICSR.DTE becomes 1. */ + avs_poll(ICSR_DTE, 1U); + + /* Clear ICIC.DTEE to disable a DTE interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE)); + /* Send slave address of PMIC */ + mmio_write_8(IIC_ICDR, PMIC_W_SLAVE_ADDRESS); + + /* Wait for a until ICSR.WAIT becomes 1. */ + avs_poll(ICSR_WAIT, 1U); + + /* write PMIC address */ + mmio_write_8(IIC_ICDR, addr); + /* Clear ICSR.WAIT to exit from WAIT status. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT)); + + /* Wait for a until ICSR.WAIT becomes 1. */ + avs_poll(ICSR_WAIT, 1U); + + /* Write H'94 in ICCR to issue restart condition */ + mmio_write_8(IIC_ICCR, ICCR_START); + /* Clear ICSR.WAIT to exit from WAIT status. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT)); + /* Set ICIC.DTEE=1 to enable data transmission interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_DTEE); + + /* Wait for a until ICSR.DTE becomes 1. */ + avs_poll(ICSR_DTE, 1U); + + /* Clear ICIC.DTEE to disable a DTE interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE)); + /* Send slave address of PMIC */ + mmio_write_8(IIC_ICDR, PMIC_R_SLAVE_ADDRESS); + + /* Wait for a until ICSR.WAIT becomes 1. */ + avs_poll(ICSR_WAIT, 1U); + + /* Write H'81 to ICCR to issue the repeated START condition */ + /* for changing the transmission mode to the receive mode. */ + mmio_write_8(IIC_ICCR, ICCR_START_RECV); + /* Clear ICSR.WAIT to exit from WAIT status. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT)); + + /* Wait for a until ICSR.WAIT becomes 1. */ + avs_poll(ICSR_WAIT, 1U); + + /* Set ICCR to H'C0 for the STOP condition */ + mmio_write_8(IIC_ICCR, ICCR_STOP_RECV); + /* Clear ICSR.WAIT to exit from WAIT status. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT)); + /* Set ICIC.DTEE=1 to enable data transmission interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_DTEE); + + /* Wait for a until ICSR.DTE becomes 1. */ + avs_poll(ICSR_DTE, 1U); + + /* Receive DVFS SetVID register */ + /* Clear ICIC.DTEE to disable a DTE interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE)); + /* Receive DVFS SetVID register */ + reg = mmio_read_8(IIC_ICDR); + + /* Wait until ICSR.BUSY is cleared. */ + avs_poll(ICSR_BUSY, 0U); + + /* Set ICCR=H'00 to disable the I2C module. */ + mmio_write_8(IIC_ICCR, 0x00U); + + return reg; +} + +/* + * Wait processing by the polling. + */ +static void avs_poll(uint8_t bit_pos, uint8_t val) +{ + uint8_t bit_val = 0U; + + if (val != 0U) + bit_val = bit_pos; + + while (1) { + if ((mmio_read_8(IIC_ICSR) & bit_pos) == bit_val) + break; + } +} +#endif /* AVS_READ_PMIC_REG_ENABLE */ +#endif /* PMIC_ROHM_BD9571 */ +#endif /* (AVS_SETTING_ENABLE==1) */ diff --git a/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h b/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h new file mode 100644 index 0000000..aa773b6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AVS_DRIVER_H +#define AVS_DRIVER_H + +/* AVS Setting. 1:enable / 0:disable */ +#ifndef AVS_SETTING_ENABLE +#define AVS_SETTING_ENABLE 1 +#endif /* AVS_SETTING_ENABLE */ + +void rcar_avs_init(void); +void rcar_avs_setting(void); +void rcar_avs_end(void); + +#endif /* AVS_DRIVER_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/common.c b/arm-trusted-firmware/drivers/renesas/common/common.c new file mode 100644 index 0000000..a0aa480 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/common.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "cpg_registers.h" +#include "rcar_private.h" + +#if IMAGE_BL31 +void __attribute__ ((section(".system_ram"))) cpg_write(uintptr_t regadr, uint32_t regval) +#else +void cpg_write(uintptr_t regadr, uint32_t regval) +#endif +{ + uint32_t value = regval; + + mmio_write_32(CPG_CPGWPR, ~value); + mmio_write_32(regadr, value); +} + +#if IMAGE_BL31 +void __attribute__ ((section(".system_ram"))) mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, + uint32_t target_bit) +#else +void mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, uint32_t target_bit) +#endif +{ + uint32_t reg; + + reg = mmio_read_32(mstpcr); + reg &= ~target_bit; + cpg_write(mstpcr, reg); + while ((mmio_read_32(mstpsr) & target_bit) != 0U) { + } +} diff --git a/arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S b/arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S new file mode 100644 index 0000000..b683d7b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl console_rcar_register + .globl console_rcar_init + .globl console_rcar_putc + .globl console_rcar_flush + + .extern rcar_log_init + .extern rcar_set_log_data + + /* ----------------------------------------------- + * int console_rcar_register( + * uintptr_t base, uint32_t clk, uint32_t baud, + * console_t *console) + * Function to initialize and register a new rcar + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_rcar_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl rcar_log_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register rcar, putc=1, getc=0, flush=1 + +register_fail: + ret x7 +endfunc console_rcar_register + + /* --------------------------------------------- + * int console_rcar_init(unsigned long base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func console_rcar_init + mov w0, #1 + ret +endfunc console_rcar_init + + /* -------------------------------------------------------- + * int console_rcar_putc(int c, console_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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_rcar_putc + b rcar_set_log_data +endfunc console_rcar_putc + + /* --------------------------------------------- + * void console_rcar_flush(void) + * Function to force a write of all buffered + * data that hasn't been output. It returns void + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_rcar_flush + ret +endfunc console_rcar_flush diff --git a/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c b/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c new file mode 100644 index 0000000..ad074fe --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include + +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_printf.h" + +#define INDEX_TIMER_COUNT (4U) + +#define RCAR_LOG_HEAD (('T' << 0) | ('L' << 8) | ('O' << 16) | ('G' << 24)) + +/* + * The log is initialized and used before BL31 xlat tables are initialized, + * therefore the log memory is a device memory at that point. Make sure the + * memory is correclty aligned and accessed only with up-to 32bit, aligned, + * writes. + */ +CASSERT((RCAR_BL31_LOG_BASE & 0x7) == 0, assert_bl31_log_base_unaligned); +CASSERT((RCAR_BL31_LOG_MAX & 0x7) == 0, assert_bl31_log_max_unaligned); + +extern RCAR_INSTANTIATE_LOCK typedef struct log_head { + uint32_t head; + uint32_t index; + uint32_t size; + uint32_t res; +} loghead_t; + +typedef struct log_map { + loghead_t header; + uint8_t log_data[RCAR_BL31_LOG_MAX]; + uint8_t res_data[RCAR_LOG_RES_SIZE]; +} logmap_t; + +int32_t rcar_set_log_data(int32_t c) +{ + logmap_t *t_log; + + t_log = (logmap_t *) RCAR_BL31_LOG_BASE; + + rcar_lock_get(); + + /* + * If index is broken, then index and size initialize + */ + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + t_log->header.index = 0U; + t_log->header.size = 0U; + } + /* + * data store to log area then index and size renewal + */ + t_log->log_data[t_log->header.index] = (uint8_t) c; + t_log->header.index++; + if (t_log->header.size < t_log->header.index) { + t_log->header.size = t_log->header.index; + } + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + t_log->header.index = 0U; + } + + rcar_lock_release(); + + return 1; +} + +int32_t rcar_log_init(void) +{ + logmap_t *t_log = (logmap_t *)RCAR_BL31_LOG_BASE; + uint32_t *log_data = (uint32_t *)t_log->log_data; + int16_t init_flag = 0; + int i; + + if (t_log->header.head != RCAR_LOG_HEAD) { + /* + * Log header is not "TLOG", then log area initialize + */ + init_flag = 1; + } + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + /* + * index is broken, then log area initialize + */ + init_flag = 1; + } + if (init_flag == 1) { + for (i = 0; i < RCAR_BL31_LOG_MAX; i += 4) + *log_data++ = 0; + + t_log->header.head = RCAR_LOG_HEAD; + t_log->header.index = 0U; + t_log->header.size = 0U; + } + rcar_lock_init(); + + return 1; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h b/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h new file mode 100644 index 0000000..5da70e6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_PRINTF_H +#define RCAR_PRINTF_H + +#include + +int32_t rcar_set_log_data(int32_t c); +int32_t rcar_log_init(void); + +#endif /* RCAR_PRINTF_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h b/arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h new file mode 100644 index 0000000..ac237b2 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOOT_INIT_DRAM_H +#define BOOT_INIT_DRAM_H + +extern int32_t rcar_dram_init(void); + +#define INITDRAM_OK 0 +#define INITDRAM_NG 0xffffffff +#define INITDRAM_ERR_I 0xffffffff +#define INITDRAM_ERR_O 0xfffffffe +#define INITDRAM_ERR_T 0xfffffff0 + +#endif /* BOOT_INIT_DRAM_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr.mk b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr.mk new file mode 100644 index 0000000..9483686 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr.mk @@ -0,0 +1,17 @@ +# +# Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq ($(RCAR_LSI),$(filter $(RCAR_LSI),${RCAR_E3} ${RZ_G2E})) + include drivers/renesas/common/ddr/ddr_a/ddr_a.mk + BL2_SOURCES += drivers/renesas/common/ddr/dram_sub_func.c +else ifeq (${RCAR_LSI},${RCAR_D3}) + include drivers/renesas/common/ddr/ddr_a/ddr_a.mk +else ifeq (${RCAR_LSI},${RCAR_V3M}) + include drivers/renesas/common/ddr/ddr_a/ddr_a.mk +else + include drivers/renesas/common/ddr/ddr_b/ddr_b.mk + BL2_SOURCES += drivers/renesas/common/ddr/dram_sub_func.c +endif diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h new file mode 100644 index 0000000..0f89b43 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../ddr_regs.h" diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_a.mk b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_a.mk new file mode 100644 index 0000000..cd6433d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_a.mk @@ -0,0 +1,13 @@ +# +# Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq ($(RCAR_LSI),$(filter $(RCAR_LSI),${RCAR_E3} ${RZ_G2E})) +BL2_SOURCES += drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c +else ifeq (${RCAR_LSI},${RCAR_D3}) +BL2_SOURCES += drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c +else +BL2_SOURCES += drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c +endif diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c new file mode 100644 index 0000000..f0113f1 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c @@ -0,0 +1,735 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "rcar_def.h" +#include "../ddr_regs.h" + +#define RCAR_DDR_VERSION "rev.0.02" + +/* Average periodic refresh interval[ns]. Support 3900,7800 */ +#define REFRESH_RATE 3900 + + +#if RCAR_LSI != RCAR_D3 +#error "Don't have DDR initialize routine." +#endif + +static void init_ddr_d3_1866(void) +{ + uint32_t i, r2, r3, r5, r6, r7, r12; + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a01); + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + mmio_write_32(DBSC_DBTR0, 0x0000000D); + mmio_write_32(DBSC_DBTR1, 0x00000009); + mmio_write_32(DBSC_DBTR2, 0x00000000); + mmio_write_32(DBSC_DBTR3, 0x0000000D); + mmio_write_32(DBSC_DBTR4, 0x000D000D); + mmio_write_32(DBSC_DBTR5, 0x0000002D); + mmio_write_32(DBSC_DBTR6, 0x00000020); + mmio_write_32(DBSC_DBTR7, 0x00060006); + mmio_write_32(DBSC_DBTR8, 0x00000021); + mmio_write_32(DBSC_DBTR9, 0x00000007); + mmio_write_32(DBSC_DBTR10, 0x0000000E); + mmio_write_32(DBSC_DBTR11, 0x0000000C); + mmio_write_32(DBSC_DBTR12, 0x00140014); + mmio_write_32(DBSC_DBTR13, 0x000000F2); + mmio_write_32(DBSC_DBTR14, 0x00170006); + mmio_write_32(DBSC_DBTR15, 0x00060005); + mmio_write_32(DBSC_DBTR16, 0x09210507); + mmio_write_32(DBSC_DBTR17, 0x040E0000); + mmio_write_32(DBSC_DBTR18, 0x00000200); + mmio_write_32(DBSC_DBTR19, 0x0129004B); + mmio_write_32(DBSC_DBTR20, 0x020000FB); + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + mmio_write_32(DBSC_DBSCHRW1, 0x00000046); + mmio_write_32(DBSC_SCFCTST0, 0x0C050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0305030C); + + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01000001); + mmio_write_32(DBSC_DBCMD, 0x08000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A04); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BBAD); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058A00); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + mmio_write_32(DBSC_DBPDRGD_0, + (uint32_t) (REFRESH_RATE * 928 / 125) - 400 + + 0x0A300000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + mmio_write_32(DBSC_DBPDRGD_0, 0x35A00D77); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + mmio_write_32(DBSC_DBPDRGD_0, 0x2A8A2C28); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + mmio_write_32(DBSC_DBPDRGD_0, 0x30005E00); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + mmio_write_32(DBSC_DBPDRGD_0, 0x0014CB49); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000F14); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + if (REFRESH_RATE > 3900) { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000020); + } else { + mmio_write_32(DBSC_DBPDRGD_0, 0x000000A0); + } + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); + mmio_write_32(DBSC_DBPDRGD_0, 0x33C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000000E); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0x0000FF00) >> 0x9; + r3 = (r2 << 16) + (r2 << 8) + r2; + r6 = (r2 << 24) + (r2 << 16) + (r2 << 8) + r2; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000011); + mmio_write_32(DBSC_DBPDRGD_0, r3); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000012); + mmio_write_32(DBSC_DBPDRGD_0, r3); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000016); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000017); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000018); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000019); + mmio_write_32(DBSC_DBPDRGD_0, r6); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010181); + mmio_write_32(DBSC_DBCMD, 0x08000001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010601); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 2; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + (r5 << 1)) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00C0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00D8); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x0001F001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); + r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); + mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 2; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = ((mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + r12 = (r5 >> 0x2); + + if (r12 < r6) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 - r12) & 0xFF)); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | (r7 & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + r5 + + (r5 >> 1) + r12) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + mmio_write_32(DBSC_DBCALCNF, + (uint32_t) (64000000 / REFRESH_RATE) + 0x01000000); + mmio_write_32(DBSC_DBRFCNF1, + (uint32_t) (REFRESH_RATE * 116 / 125) + 0x00080000); + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + +#ifdef ddr_qos_init_setting // only for non qos_init + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + mmio_write_32(DBSC_DBSCHCNT0, 0x000f0037); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS91, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS92, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010); + mmio_write_32(0xE67F0018, 0x00000001); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); +#endif +} + +static void init_ddr_d3_1600(void) +{ + uint32_t i, r2, r3, r5, r6, r7, r12; + + mmio_write_32(CPG_CPGWPR, 0x5A5AFFFF); + mmio_write_32(CPG_CPGWPCR, 0xA5A50000); + + mmio_write_32(CPG_SRCR4, 0x20000000); + + mmio_write_32(0xE61500DC, 0xe2200000); + while (!(mmio_read_32(CPG_PLLECR) & BIT(11))) + ; + + mmio_write_32(CPG_SRSTCLR4, 0x20000000); + + mmio_write_32(CPG_CPGWPCR, 0xA5A50001); + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a01); + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + mmio_write_32(DBSC_DBTR0, 0x0000000B); + mmio_write_32(DBSC_DBTR1, 0x00000008); + mmio_write_32(DBSC_DBTR2, 0x00000000); + mmio_write_32(DBSC_DBTR3, 0x0000000B); + mmio_write_32(DBSC_DBTR4, 0x000B000B); + mmio_write_32(DBSC_DBTR5, 0x00000027); + mmio_write_32(DBSC_DBTR6, 0x0000001C); + mmio_write_32(DBSC_DBTR7, 0x00060006); + mmio_write_32(DBSC_DBTR8, 0x00000020); + mmio_write_32(DBSC_DBTR9, 0x00000006); + mmio_write_32(DBSC_DBTR10, 0x0000000C); + mmio_write_32(DBSC_DBTR11, 0x0000000A); + mmio_write_32(DBSC_DBTR12, 0x00120012); + mmio_write_32(DBSC_DBTR13, 0x000000CE); + mmio_write_32(DBSC_DBTR14, 0x00140005); + mmio_write_32(DBSC_DBTR15, 0x00050004); + mmio_write_32(DBSC_DBTR16, 0x071F0305); + mmio_write_32(DBSC_DBTR17, 0x040C0000); + mmio_write_32(DBSC_DBTR18, 0x00000200); + mmio_write_32(DBSC_DBTR19, 0x01000040); + mmio_write_32(DBSC_DBTR20, 0x020000D6); + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + mmio_write_32(DBSC_DBSCHRW1, 0x00000046); + mmio_write_32(DBSC_SCFCTST0, 0x0D050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0306030C); + + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01000001); + mmio_write_32(DBSC_DBCMD, 0x08000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058904); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BBAD); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + mmio_write_32(DBSC_DBPDRGD_0, + (uint32_t) (REFRESH_RATE * 792 / 125) - 400 + 0x08B00000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88B400); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + mmio_write_32(DBSC_DBPDRGD_0, 0x0014A9C9); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000D70); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + if (REFRESH_RATE > 3900) { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000018); + } else { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000098); + } + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); + mmio_write_32(DBSC_DBPDRGD_0, 0x33C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000000E); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0x0000FF00) >> 0x9; + r3 = (r2 << 16) + (r2 << 8) + r2; + r6 = (r2 << 24) + (r2 << 16) + (r2 << 8) + r2; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000011); + mmio_write_32(DBSC_DBPDRGD_0, r3); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000012); + mmio_write_32(DBSC_DBPDRGD_0, r3); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000016); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000017); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000018); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000019); + mmio_write_32(DBSC_DBPDRGD_0, r6); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010181); + mmio_write_32(DBSC_DBCMD, 0x08000001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010601); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 2; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + (r5 << 1)) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00C0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00D8); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x0001F001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); + r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); + mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 2; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + r12 = (r5 >> 0x2); + + if (r12 < r6) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 - r12) & 0xFF)); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | (r7 & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + r5 + + (r5 >> 1) + r12) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + mmio_write_32(DBSC_DBCALCNF, + (uint32_t) (64000000 / REFRESH_RATE) + 0x01000000); + mmio_write_32(DBSC_DBRFCNF1, + (uint32_t) (REFRESH_RATE * 99 / 125) + 0x00080000); + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + +#ifdef ddr_qos_init_setting // only for non qos_init + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + mmio_write_32(DBSC_DBSCHCNT0, 0x000f0037); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS91, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS92, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010); + mmio_write_32(0xE67F0018, 0x00000001); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); +#endif +} + +#define PRR 0xFFF00044U +#define PRR_PRODUCT_MASK 0x00007F00U +#define PRR_PRODUCT_D3 0x00005800U + +#define MODEMR_MD19 BIT(19) + +int32_t rcar_dram_init(void) +{ + uint32_t reg; + uint32_t ddr_mbps; + + reg = mmio_read_32(PRR); + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_D3) { + ERROR("LSI Product ID (PRR=0x%x) DDR initialize not supported.\n", + reg); + panic(); + } + + reg = mmio_read_32(RST_MODEMR); + if (reg & MODEMR_MD19) { + init_ddr_d3_1866(); + ddr_mbps = 1866; + } else { + init_ddr_d3_1600(); + ddr_mbps = 1600; + } + + NOTICE("BL2: DDR%d(%s)\n", ddr_mbps, RCAR_DDR_VERSION); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c new file mode 100644 index 0000000..fc278ef --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c @@ -0,0 +1,1712 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include "boot_init_dram.h" +#include "rcar_def.h" +#include "../ddr_regs.h" + +#include "../dram_sub_func.h" + +#define RCAR_E3_DDR_VERSION "rev.0.12" + +/* Average periodic refresh interval[ns]. Support 3900,7800 */ +#ifdef ddr_qos_init_setting +#define REFRESH_RATE 3900U +#else +#if RCAR_REF_INT == 1 +#define REFRESH_RATE 7800U +#else +#define REFRESH_RATE 3900U +#endif +#endif + +/* + * Initialize ddr + */ +uint32_t init_ddr(void) +{ + uint32_t i, r2, r5, r6, r7, r12; + uint32_t ddr_md; + uint32_t regval, j; + uint32_t dqsgd_0c, bdlcount_0c, bdlcount_0c_div2, bdlcount_0c_div4; + uint32_t bdlcount_0c_div8, bdlcount_0c_div16; + uint32_t gatesl_0c, rdqsd_0c, rdqsnd_0c, rbd_0c[4]; + uint32_t pdqsr_ctl, lcdl_ctl, lcdl_judge1, lcdl_judge2; + uint32_t pdr_ctl; + uint32_t byp_ctl; + + if ((mmio_read_32(0xFFF00044) & 0x000000FF) == 0x00000000) { + pdqsr_ctl = 1; + lcdl_ctl = 1; + pdr_ctl = 1; + byp_ctl = 1; + } else { + pdqsr_ctl = 0; + lcdl_ctl = 0; + pdr_ctl = 0; + byp_ctl = 0; + } + + /* Judge the DDR bit rate (ddr_md : 0 = 1584Mbps, 1 = 1856Mbps) */ + ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & BIT(0); + + /* 1584Mbps setting */ + if (ddr_md == 0) { + mmio_write_32(CPG_CPGWPR, 0x5A5AFFFF); + mmio_write_32(CPG_CPGWPCR, 0xA5A50000); + + mmio_write_32(CPG_SRCR4, 0x20000000); + + mmio_write_32(0xE61500DC, 0xe2200000); /* Change to 1584Mbps */ + while (!(mmio_read_32(CPG_PLLECR) & BIT(11))) + ; + + mmio_write_32(CPG_SRSTCLR4, 0x20000000); + + mmio_write_32(CPG_CPGWPCR, 0xA5A50001); + } + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); + +#if RCAR_DRAM_DDR3L_MEMCONF == 0 + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a02); /* 1GB */ +#else + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x10030a02); /* 2GB(default) */ +#endif + +#if RCAR_DRAM_DDR3L_MEMDUAL == 1 + r2 = mmio_read_32(0xE6790614); + mmio_write_32(0xE6790614, r2 | 0x3); /* MCS1_N/MODT1 are activated. */ +#endif + + mmio_write_32(DBSC_DBPHYCONF0, 0x1); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR0, 0xB); + mmio_write_32(DBSC_DBTR1, 0x8); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR0, 0xD); + mmio_write_32(DBSC_DBTR1, 0x9); + } + + mmio_write_32(DBSC_DBTR2, 0x00000000); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR3, 0x0000000B); + mmio_write_32(DBSC_DBTR4, 0x000B000B); + mmio_write_32(DBSC_DBTR5, 0x00000027); + mmio_write_32(DBSC_DBTR6, 0x0000001C); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR3, 0x0000000D); + mmio_write_32(DBSC_DBTR4, 0x000D000D); + mmio_write_32(DBSC_DBTR5, 0x0000002D); + mmio_write_32(DBSC_DBTR6, 0x00000020); + } + + mmio_write_32(DBSC_DBTR7, 0x00060006); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR8, 0x00000020); + mmio_write_32(DBSC_DBTR9, 0x00000006); + mmio_write_32(DBSC_DBTR10, 0x0000000C); + mmio_write_32(DBSC_DBTR11, 0x0000000A); + mmio_write_32(DBSC_DBTR12, 0x00120012); + mmio_write_32(DBSC_DBTR13, 0x000000CE); + mmio_write_32(DBSC_DBTR14, 0x00140005); + mmio_write_32(DBSC_DBTR15, 0x00050004); + mmio_write_32(DBSC_DBTR16, 0x071F0305); + mmio_write_32(DBSC_DBTR17, 0x040C0000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR8, 0x00000021); + mmio_write_32(DBSC_DBTR9, 0x00000007); + mmio_write_32(DBSC_DBTR10, 0x0000000E); + mmio_write_32(DBSC_DBTR11, 0x0000000C); + mmio_write_32(DBSC_DBTR12, 0x00140014); + mmio_write_32(DBSC_DBTR13, 0x000000F2); + mmio_write_32(DBSC_DBTR14, 0x00170006); + mmio_write_32(DBSC_DBTR15, 0x00060005); + mmio_write_32(DBSC_DBTR16, 0x09210507); + mmio_write_32(DBSC_DBTR17, 0x040E0000); + } + + mmio_write_32(DBSC_DBTR18, 0x00000200); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR19, 0x01000040); + mmio_write_32(DBSC_DBTR20, 0x020000D6); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR19, 0x0129004B); + mmio_write_32(DBSC_DBTR20, 0x020000FB); + } + + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + mmio_write_32(DBSC_DBSCHRW1, 0x00000046); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_SCFCTST0, 0x0D050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0306030C); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_SCFCTST0, 0x0C050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0305030C); + } + + /* + * Initial_Step0( INITBYP ) + */ + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01840001); + mmio_write_32(DBSC_DBCMD, 0x08840000); + NOTICE("BL2: [COLD_BOOT]\n"); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step1( ZCAL,PLLINIT,DCAL,PHYRST training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058904); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A04); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BBAD); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step2( DRAMRST/DRAMINT training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + if (byp_ctl == 1) + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C720); + else + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, (REFRESH_RATE * 792 / 125) - + 400 + 0x08B00000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, (REFRESH_RATE * 928 / 125) - + 400 + 0x0A300000); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x35A00D77); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88B400); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2A8A2C28); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x30005E00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0014A9C9); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0014CB49); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000D70); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000F14); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + if (REFRESH_RATE > 3900) /* [7]SRT=0 */ + mmio_write_32(DBSC_DBPDRGD_0, 0x18); + else /* [7]SRT=1 */ + mmio_write_32(DBSC_DBPDRGD_0, 0x98); + } else { /* 1856Mbps */ + if (REFRESH_RATE > 3900) /* [7]SRT=0 */ + mmio_write_32(DBSC_DBPDRGD_0, 0x20); + else /* [7]SRT=1 */ + mmio_write_32(DBSC_DBPDRGD_0, 0xA0); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); + mmio_write_32(DBSC_DBPDRGD_0, 0x33C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000107); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000108); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000109); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010181); + mmio_write_32(DBSC_DBCMD, 0x08840001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step3( WL/QSG training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010601); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + ((r5) << 1)) & + 0xFF)); + } + } + + /* + * Initial_Step4( WLADJ training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00C0); + + if (pdqsr_ctl == 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step5(Read Data Bit Deskew) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00D8); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00011001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + /* + * Initial_Step6(Write Data Bit Deskew) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00012001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step7(Read Data Eye Training) + */ + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00014001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + /* + * Initial_Step8(Write Data Eye Training) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00018001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step3_2( DQS Gate Training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = ((mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + r12 = (r5 >> 0x2); + if (r12 < r6) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 - r12) & 0xFF)); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | (r7 & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 + r5 + + (r5 >> 1) + r12) & 0xFF)); + } + } + + /* + * Initial_Step5-2_7-2( Rd bit Rd eye ) + */ + if (pdqsr_ctl == 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (lcdl_ctl == 1) { + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + dqsgd_0c = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + bdlcount_0c = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> + 8; + bdlcount_0c_div2 = bdlcount_0c >> 1; + bdlcount_0c_div4 = bdlcount_0c >> 2; + bdlcount_0c_div8 = bdlcount_0c >> 3; + bdlcount_0c_div16 = bdlcount_0c >> 4; + + if (ddr_md == 0) { /* 1584Mbps */ + lcdl_judge1 = bdlcount_0c_div2 + + bdlcount_0c_div4 + + bdlcount_0c_div8; + lcdl_judge2 = bdlcount_0c + + bdlcount_0c_div4 + + bdlcount_0c_div16; + } else { /* 1856Mbps */ + lcdl_judge1 = bdlcount_0c_div2 + + bdlcount_0c_div4; + lcdl_judge2 = bdlcount_0c + + bdlcount_0c_div4; + } + + if (dqsgd_0c <= lcdl_judge1) + continue; + + if (dqsgd_0c <= lcdl_judge2) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGD_0, + (dqsgd_0c - bdlcount_0c_div8) | + regval); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + gatesl_0c = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGD_0, regval | + (gatesl_0c + 1)); + mmio_write_32(DBSC_DBPDRGA_0, 0xAF + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rdqsd_0c = (regval & 0xFF00) >> 8; + rdqsnd_0c = (regval & 0xFF0000) >> 16; + mmio_write_32(DBSC_DBPDRGA_0, 0xAF + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, + (regval & 0xFF0000FF) | + ((rdqsd_0c + + bdlcount_0c_div4) << 8) | + ((rdqsnd_0c + + bdlcount_0c_div4) << 16)); + mmio_write_32(DBSC_DBPDRGA_0, 0xAA + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rbd_0c[0] = (regval) & 0x1f; + rbd_0c[1] = (regval >> 8) & 0x1f; + rbd_0c[2] = (regval >> 16) & 0x1f; + rbd_0c[3] = (regval >> 24) & 0x1f; + mmio_write_32(DBSC_DBPDRGA_0, 0xAA + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xE0E0E0E0; + for (j = 0; j < 4; j++) { + rbd_0c[j] = rbd_0c[j] + + bdlcount_0c_div4; + if (rbd_0c[j] > 0x1F) + rbd_0c[j] = 0x1F; + regval = regval | (rbd_0c[j] << 8 * j); + } + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0xAB + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rbd_0c[0] = (regval) & 0x1f; + rbd_0c[1] = (regval >> 8) & 0x1f; + rbd_0c[2] = (regval >> 16) & 0x1f; + rbd_0c[3] = (regval >> 24) & 0x1f; + mmio_write_32(DBSC_DBPDRGA_0, 0xAB + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xE0E0E0E0; + for (j = 0; j < 4; j++) { + rbd_0c[j] = rbd_0c[j] + + bdlcount_0c_div4; + if (rbd_0c[j] > 0x1F) + rbd_0c[j] = 0x1F; + regval = regval | (rbd_0c[j] << 8 * j); + } + mmio_write_32(DBSC_DBPDRGD_0, regval); + } + } + mmio_write_32(DBSC_DBPDRGA_0, 0x2); + mmio_write_32(DBSC_DBPDRGD_0, 0x7D81E37); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + if (byp_ctl == 1) + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C720); + else + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + mmio_write_32(DBSC_DBCALCNF, (64000000 / REFRESH_RATE) + 0x01000000); + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBRFCNF1, + (REFRESH_RATE * 99 / 125) + 0x00080000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBRFCNF1, + (REFRESH_RATE * 116 / 125) + 0x00080000); + } + + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + + if (pdqsr_ctl == 1) { + mmio_write_32(0xE67F0018, 0x00000001); + regval = mmio_read_32(0x40000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + /* + * Initial_Step9( Initial End ) + */ + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + +#ifdef ddr_qos_init_setting /* only for non qos_init */ + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + mmio_write_32(DBSC_DBSCHCNT0, 0x000f0037); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010); + + if (pdqsr_ctl == 0) + mmio_write_32(0xE67F0018, 0x00000001); + + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); +#endif + + return 1; +} + +static uint32_t recovery_from_backup_mode(uint32_t ddr_backup) +{ + /* + * recovery_Step0(DBSC Setting 1) / same "init_ddr" + */ + uint32_t r2, r5, r6, r7, r12, i; + uint32_t ddr_md; + uint32_t err; + uint32_t regval, j; + uint32_t dqsgd_0c, bdlcount_0c, bdlcount_0c_div2, bdlcount_0c_div4; + uint32_t bdlcount_0c_div8, bdlcount_0c_div16; + uint32_t gatesl_0c, rdqsd_0c, rdqsnd_0c, rbd_0c[4]; + uint32_t pdqsr_ctl, lcdl_ctl, lcdl_judge1, lcdl_judge2; + uint32_t pdr_ctl; + uint32_t byp_ctl; + + if ((mmio_read_32(0xFFF00044) & 0x000000FF) == 0x00000000) { + pdqsr_ctl = 1; + lcdl_ctl = 1; + pdr_ctl = 1; + byp_ctl = 1; + } else { + pdqsr_ctl = 0; + lcdl_ctl = 0; + pdr_ctl = 0; + byp_ctl = 0; + } + + /* Judge the DDR bit rate (ddr_md : 0 = 1584Mbps, 1 = 1856Mbps) */ + ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & BIT(0); + + /* 1584Mbps setting */ + if (ddr_md == 0) { + mmio_write_32(CPG_CPGWPR, 0x5A5AFFFF); + mmio_write_32(CPG_CPGWPCR, 0xA5A50000); + + mmio_write_32(CPG_SRCR4, 0x20000000); + + mmio_write_32(0xE61500DC, 0xe2200000); /* Change to 1584Mbps */ + while (!(mmio_read_32(CPG_PLLECR) & BIT(11))) + ; + + mmio_write_32(CPG_SRSTCLR4, 0x20000000); + + mmio_write_32(CPG_CPGWPCR, 0xA5A50001); + } + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); + +#if RCAR_DRAM_DDR3L_MEMCONF == 0 + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a02); +#else + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x10030a02); +#endif + +#if RCAR_DRAM_DDR3L_MEMDUAL == 1 + r2 = mmio_read_32(0xE6790614); + mmio_write_32(0xE6790614, r2 | 0x3); /* MCS1_N/MODT1 are activated. */ +#endif + + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR0, 0x0000000B); + mmio_write_32(DBSC_DBTR1, 0x00000008); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR0, 0x0000000D); + mmio_write_32(DBSC_DBTR1, 0x00000009); + } + + mmio_write_32(DBSC_DBTR2, 0x00000000); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR3, 0x0000000B); + mmio_write_32(DBSC_DBTR4, 0x000B000B); + mmio_write_32(DBSC_DBTR5, 0x00000027); + mmio_write_32(DBSC_DBTR6, 0x0000001C); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR3, 0x0000000D); + mmio_write_32(DBSC_DBTR4, 0x000D000D); + mmio_write_32(DBSC_DBTR5, 0x0000002D); + mmio_write_32(DBSC_DBTR6, 0x00000020); + } + + mmio_write_32(DBSC_DBTR7, 0x00060006); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR8, 0x00000020); + mmio_write_32(DBSC_DBTR9, 0x00000006); + mmio_write_32(DBSC_DBTR10, 0x0000000C); + mmio_write_32(DBSC_DBTR11, 0x0000000A); + mmio_write_32(DBSC_DBTR12, 0x00120012); + mmio_write_32(DBSC_DBTR13, 0x000000CE); + mmio_write_32(DBSC_DBTR14, 0x00140005); + mmio_write_32(DBSC_DBTR15, 0x00050004); + mmio_write_32(DBSC_DBTR16, 0x071F0305); + mmio_write_32(DBSC_DBTR17, 0x040C0000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR8, 0x00000021); + mmio_write_32(DBSC_DBTR9, 0x00000007); + mmio_write_32(DBSC_DBTR10, 0x0000000E); + mmio_write_32(DBSC_DBTR11, 0x0000000C); + mmio_write_32(DBSC_DBTR12, 0x00140014); + mmio_write_32(DBSC_DBTR13, 0x000000F2); + mmio_write_32(DBSC_DBTR14, 0x00170006); + mmio_write_32(DBSC_DBTR15, 0x00060005); + mmio_write_32(DBSC_DBTR16, 0x09210507); + mmio_write_32(DBSC_DBTR17, 0x040E0000); + } + + mmio_write_32(DBSC_DBTR18, 0x00000200); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR19, 0x01000040); + mmio_write_32(DBSC_DBTR20, 0x020000D6); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR19, 0x0129004B); + mmio_write_32(DBSC_DBTR20, 0x020000FB); + } + + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + mmio_write_32(DBSC_DBSCHRW1, 0x00000046); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_SCFCTST0, 0x0D050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0306030C); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_SCFCTST0, 0x0C050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0305030C); + } + + /* + * recovery_Step1(PHY setting 1) + */ + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01840001); + mmio_write_32(DBSC_DBCMD, 0x0A840000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); /* DDR_PLLCR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); /* DDR_PGCR1 */ + if (byp_ctl == 1) + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C720); + else + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); /* DDR_DXCCR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); /* DDR_ACIOCR0 */ + mmio_write_32(DBSC_DBPDRGD_0, 0x33C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, (REFRESH_RATE * 792 / 125) - + 400 + 0x08B00000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, (REFRESH_RATE * 928 / 125) - + 400 + 0x0A300000); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x35A00D77); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88B400); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2A8A2C28); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x30005E00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0014A9C9); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0014CB49); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000D70); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000F14); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + if (REFRESH_RATE > 3900) + mmio_write_32(DBSC_DBPDRGD_0, 0x18); /* [7]SRT=0 */ + else + mmio_write_32(DBSC_DBPDRGD_0, 0x98); /* [7]SRT=1 */ + } else { /* 1856Mbps */ + if (REFRESH_RATE > 3900) + mmio_write_32(DBSC_DBPDRGD_0, 0x20); /* [7]SRT=0 */ + else + mmio_write_32(DBSC_DBPDRGD_0, 0xA0); /* [7]SRT=1 */ + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BBAD); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); /* DDR_DSGCR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x40010000); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000092); /* DDR_ZQ0DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0xC2C59AB5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000096); /* DDR_ZQ1DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0xC4285FBF); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000009A); /* DDR_ZQ2DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0xC2C59AB5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); /* DDR_ZQCR */ + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); /* DDR_ZQCR */ + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00050001); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* ddr backupmode end */ + if (ddr_backup) + NOTICE("BL2: [WARM_BOOT]\n"); + else + NOTICE("BL2: [COLD_BOOT]\n"); + + err = rcar_dram_update_boot_status(ddr_backup); + if (err) { + NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n"); + return INITDRAM_ERR_I; + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000092); /* DDR_ZQ0DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x02C59AB5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000096); /* DDR_ZQ1DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04285FBF); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000009A); /* DDR_ZQ2DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x02C59AB5); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x08000000); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000003); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); /* DDR_ZQCR */ + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); /* DDR_ZQCR */ + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000000C); + mmio_write_32(DBSC_DBPDRGD_0, 0x18000040); + + /* + * recovery_Step2(PHY setting 2) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000107); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000108); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000109); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + + mmio_write_32(DBSC_DBCALCNF, (64000000 / REFRESH_RATE) + 0x01000000); + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBRFCNF1, + (REFRESH_RATE * 99 / 125) + 0x00080000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBRFCNF1, + (REFRESH_RATE * 116 / 125) + 0x00080000); + } + + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBCMD, 0x0A840001); + while (mmio_read_32(DBSC_DBWAIT) & BIT(0)) + ; + + mmio_write_32(DBSC_DBCMD, 0x00000000); + + mmio_write_32(DBSC_DBCMD, 0x04840010); + while (mmio_read_32(DBSC_DBWAIT) & BIT(0)) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00010701); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, + r2 | ((r6 + (r5 << 1)) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00C0); + + if (pdqsr_ctl == 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00D8); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00011001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00012001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00014001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00018001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = ((mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + r12 = r5 >> 0x2; + + if (r12 < r6) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 - r12) & 0xFF)); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | (r7 & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, + r2 | + ((r6 + r5 + (r5 >> 1) + r12) & 0xFF)); + } + } + + if (pdqsr_ctl == 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (lcdl_ctl == 1) { + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000B0 + i * 0x20); + dqsgd_0c = mmio_read_32(DBSC_DBPDRGD_0) & 0x000000FF; + mmio_write_32(DBSC_DBPDRGA_0, 0x000000B1 + i * 0x20); + bdlcount_0c = (mmio_read_32(DBSC_DBPDRGD_0) & + 0x0000FF00) >> 8; + bdlcount_0c_div2 = (bdlcount_0c >> 1); + bdlcount_0c_div4 = (bdlcount_0c >> 2); + bdlcount_0c_div8 = (bdlcount_0c >> 3); + bdlcount_0c_div16 = (bdlcount_0c >> 4); + + if (ddr_md == 0) { /* 1584Mbps */ + lcdl_judge1 = bdlcount_0c_div2 + + bdlcount_0c_div4 + + bdlcount_0c_div8; + lcdl_judge2 = bdlcount_0c + + bdlcount_0c_div4 + + bdlcount_0c_div16; + } else { /* 1856Mbps */ + lcdl_judge1 = bdlcount_0c_div2 + + bdlcount_0c_div4; + lcdl_judge2 = bdlcount_0c + + bdlcount_0c_div4; + } + + if (dqsgd_0c <= lcdl_judge1) + continue; + + if (dqsgd_0c <= lcdl_judge2) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGD_0, + (dqsgd_0c - bdlcount_0c_div8) | + regval); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + gatesl_0c = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGD_0, + regval | (gatesl_0c + 1)); + mmio_write_32(DBSC_DBPDRGA_0, 0xAF + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0); + rdqsd_0c = (regval & 0xFF00) >> 8; + rdqsnd_0c = (regval & 0xFF0000) >> 16; + mmio_write_32(DBSC_DBPDRGA_0, 0xAF + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, + (regval & 0xFF0000FF) | + ((rdqsd_0c + + bdlcount_0c_div4) << 8) | + ((rdqsnd_0c + + bdlcount_0c_div4) << 16)); + mmio_write_32(DBSC_DBPDRGA_0, 0xAA + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rbd_0c[0] = (regval) & 0x1f; + rbd_0c[1] = (regval >> 8) & 0x1f; + rbd_0c[2] = (regval >> 16) & 0x1f; + rbd_0c[3] = (regval >> 24) & 0x1f; + mmio_write_32(DBSC_DBPDRGA_0, 0xAA + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xE0E0E0E0; + for (j = 0; j < 4; j++) { + rbd_0c[j] = rbd_0c[j] + + bdlcount_0c_div4; + if (rbd_0c[j] > 0x1F) + rbd_0c[j] = 0x1F; + regval = regval | (rbd_0c[j] << 8 * j); + } + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0xAB + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rbd_0c[0] = regval & 0x1f; + rbd_0c[1] = (regval >> 8) & 0x1f; + rbd_0c[2] = (regval >> 16) & 0x1f; + rbd_0c[3] = (regval >> 24) & 0x1f; + mmio_write_32(DBSC_DBPDRGA_0, 0xAB + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xE0E0E0E0; + for (j = 0; j < 4; j++) { + rbd_0c[j] = rbd_0c[j] + + bdlcount_0c_div4; + if (rbd_0c[j] > 0x1F) + rbd_0c[j] = 0x1F; + regval = regval | (rbd_0c[j] << 8 * j); + } + mmio_write_32(DBSC_DBPDRGD_0, regval); + } + } + mmio_write_32(DBSC_DBPDRGA_0, 0x00000002); + mmio_write_32(DBSC_DBPDRGD_0, 0x07D81E37); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + if (byp_ctl == 1) + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C720); + else + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + /* + * recovery_Step3(DBSC Setting 2) + */ + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + + if (pdqsr_ctl == 1) { + mmio_write_32(0xE67F0018, 0x00000001); + regval = mmio_read_32(0x40000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + +#ifdef ddr_qos_init_setting /* only for non qos_init */ + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + mmio_write_32(DBSC_DBSCHCNT0, 0x000f0037); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010); + + if (pdqsr_ctl == 0) + mmio_write_32(0xE67F0018, 0x00000001); + + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); +#endif + + return 1; + +} /* recovery_from_backup_mode */ + +/* + * init_ddr : MD19=0,DDR3L,1584Mbps / MD19=1,DDR3L,1856Mbps + */ + +/* + * DDR Initialize entry for IPL + */ +int32_t rcar_dram_init(void) +{ + uint32_t dataL; + uint32_t failcount; + uint32_t md = 0; + uint32_t ddr = 0; + uint32_t ddr_backup; + + md = *((volatile uint32_t*)RST_MODEMR); + ddr = (md & 0x00080000) >> 19; + if (ddr == 0x0) + NOTICE("BL2: DDR1584(%s)\n", RCAR_E3_DDR_VERSION); + else if (ddr == 0x1) + NOTICE("BL2: DDR1856(%s)\n", RCAR_E3_DDR_VERSION); + + rcar_dram_get_boot_status(&ddr_backup); + + if (ddr_backup == DRAM_BOOT_STATUS_WARM) + dataL = recovery_from_backup_mode(ddr_backup); /* WARM boot */ + else + dataL = init_ddr(); /* COLD boot */ + + if (dataL == 1) + failcount = 0; + else + failcount = 1; + + if (failcount == 0) + return INITDRAM_OK; + else + return INITDRAM_NG; + +} diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c new file mode 100644 index 0000000..5410771 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "boot_init_dram.h" +#include "rcar_def.h" +#include "../ddr_regs.h" + +static uint32_t init_ddr_v3m_1600(void) +{ + uint32_t i, r2, r5, r6, r7, r12; + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); +#if RCAR_DRAM_DDR3L_MEMCONF == 0 + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a02); // 1GB: Eagle +#else + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x10030a02); // 2GB: V3MSK +#endif + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + mmio_write_32(DBSC_DBTR0, 0x0000000B); + mmio_write_32(DBSC_DBTR1, 0x00000008); + mmio_write_32(DBSC_DBTR3, 0x0000000B); + mmio_write_32(DBSC_DBTR4, 0x000B000B); + mmio_write_32(DBSC_DBTR5, 0x00000027); + mmio_write_32(DBSC_DBTR6, 0x0000001C); + mmio_write_32(DBSC_DBTR7, 0x00060006); + mmio_write_32(DBSC_DBTR8, 0x00000020); + mmio_write_32(DBSC_DBTR9, 0x00000006); + mmio_write_32(DBSC_DBTR10, 0x0000000C); + mmio_write_32(DBSC_DBTR11, 0x0000000B); + mmio_write_32(DBSC_DBTR12, 0x00120012); + mmio_write_32(DBSC_DBTR13, 0x01180118); + mmio_write_32(DBSC_DBTR14, 0x00140005); + mmio_write_32(DBSC_DBTR15, 0x00050004); + mmio_write_32(DBSC_DBTR16, 0x071D0305); + mmio_write_32(DBSC_DBTR17, 0x040C0010); + mmio_write_32(DBSC_DBTR18, 0x00000200); + mmio_write_32(DBSC_DBTR19, 0x01000040); + mmio_write_32(DBSC_DBTR20, 0x02000120); + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00082010); + mmio_write_32(DBSC_DBCAM0CNF2, 0x00002000); + mmio_write_32(DBSC_DBSCHCNT0, 0x080f003f); + mmio_write_32(DBSC_DBSCHCNT1, 0x00001010); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x00000200); + mmio_write_32(DBSC_DBSCHRW1, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000600); + mmio_write_32(DBSC_DBSCHQOS41, 0x00000480); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000180); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000400); + mmio_write_32(DBSC_DBSCHQOS91, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS92, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS131, 0x00000240); + mmio_write_32(DBSC_DBSCHQOS132, 0x00000180); + mmio_write_32(DBSC_DBSCHQOS133, 0x000000c0); + mmio_write_32(DBSC_DBSCHQOS140, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS141, 0x00000180); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS151, 0x000000c0); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000040); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00040C04); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000001c4); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000003); + mmio_write_32(DBSC_DBSCHRW1, 0x001a0080); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01000001); + mmio_write_32(DBSC_DBCMD, 0x08000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058904); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + mmio_write_32(DBSC_DBPDRGD_0, 0x08C0C170); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88C400); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + mmio_write_32(DBSC_DBPDRGD_0, 0x0014A9C9); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000D70); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000004); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000018); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); + mmio_write_32(DBSC_DBPDRGD_0, 0x13C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000107); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000108); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000109); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010181); + mmio_write_32(DBSC_DBCMD, 0x08000001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010601); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, ((r7 + 1) & 0x7) | r2); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + (((r5 << 1) + r6) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00A0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00B8); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x0001F001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = (mmio_read_32(DBSC_DBPDRGD_0) & 0x7); + r12 = (r5 >> 2); + if (r6 - r12 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, ((r7 + 1) & 0x7) | r2); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, ((r6 - r12) & 0xFF) | r2); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, (r7 & 0x7) | r2); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + r5 + + (r5 >> 1) + r12) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000000); + mmio_write_32(DBSC_DBBUS0CNF0, 0x00010001); + mmio_write_32(DBSC_DBCALCNF, 0x0100200E); + mmio_write_32(DBSC_DBRFCNF1, 0x00081860); + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(0xE67F0024, 0x00000001); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + + return INITDRAM_OK; +} + +int32_t rcar_dram_init(void) +{ + return init_ddr_v3m_1600(); +} diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c new file mode 100644 index 0000000..8d002de --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c @@ -0,0 +1,4484 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#include "ddr_regdef.h" +#include "init_dram_tbl_h3.h" +#include "init_dram_tbl_m3.h" +#include "init_dram_tbl_h3ver2.h" +#include "init_dram_tbl_m3n.h" +#include "boot_init_dram_regdef.h" +#include "boot_init_dram.h" +#include "dram_sub_func.h" +#include "micro_delay.h" +#include "rcar_def.h" + +#define DDR_BACKUPMODE +#define FATAL_MSG(x) NOTICE(x) + +/* variables */ +#ifdef RCAR_DDR_FIXED_LSI_TYPE +#ifndef RCAR_AUTO +#define RCAR_AUTO 99 +#define RCAR_H3 0 +#define RCAR_M3 1 +#define RCAR_M3N 2 +#define RCAR_E3 3 /* NON */ +#define RCAR_H3N 4 + +#define RZ_G2M 100U +#define RZ_G2H 101U +#define RZ_G2N 102U + +#define RCAR_CUT_10 0 +#define RCAR_CUT_11 1 +#define RCAR_CUT_20 10 +#define RCAR_CUT_30 20 +#endif +#ifndef RCAR_LSI +#define RCAR_LSI RCAR_AUTO +#endif + +#if (RCAR_LSI == RCAR_AUTO) +static uint32_t prr_product; +static uint32_t prr_cut; +#else +#if (RCAR_LSI == RCAR_H3) +static const uint32_t prr_product = PRR_PRODUCT_H3; +#elif(RCAR_LSI == RCAR_M3 || RCAR_LSI == RZ_G2M) +static const uint32_t prr_product = PRR_PRODUCT_M3; +#elif(RCAR_LSI == RCAR_M3N || RCAR_LSI == RZ_G2N) +static const uint32_t prr_product = PRR_PRODUCT_M3N; +#elif(RCAR_LSI == RCAR_H3N || RCAR_LSI == RZ_G2H) +static const uint32_t prr_product = PRR_PRODUCT_H3; +#endif /* RCAR_LSI */ + +#ifndef RCAR_LSI_CUT +static uint32_t prr_cut; +#else /* RCAR_LSI_CUT */ +#if (RCAR_LSI_CUT == RCAR_CUT_10) +static const uint32_t prr_cut = PRR_PRODUCT_10; +#elif(RCAR_LSI_CUT == RCAR_CUT_11) +static const uint32_t prr_cut = PRR_PRODUCT_11; +#elif(RCAR_LSI_CUT == RCAR_CUT_20) +static const uint32_t prr_cut = PRR_PRODUCT_20; +#elif(RCAR_LSI_CUT == RCAR_CUT_30) +static const uint32_t prr_cut = PRR_PRODUCT_30; +#endif /* RCAR_LSI_CUT */ +#endif /* RCAR_LSI_CUT */ +#endif /* RCAR_AUTO_NON */ +#else /* RCAR_DDR_FIXED_LSI_TYPE */ +static uint32_t prr_product; +static uint32_t prr_cut; +#endif /* RCAR_DDR_FIXED_LSI_TYPE */ + +static const uint32_t *p_ddr_regdef_tbl; +static uint32_t brd_clk; +static uint32_t brd_clkdiv; +static uint32_t brd_clkdiva; +static uint32_t ddr_mbps; +static uint32_t ddr_mbpsdiv; +static uint32_t ddr_tccd; +static uint32_t ddr_phycaslice; +static const struct _boardcnf *board_cnf; +static uint32_t ddr_phyvalid; +static uint32_t ddr_density[DRAM_CH_CNT][CS_CNT]; +static uint32_t ch_have_this_cs[CS_CNT] __aligned(64); +static uint32_t rdqdm_dly[DRAM_CH_CNT][CSAB_CNT][SLICE_CNT * 2][9]; +static uint32_t max_density; +static uint32_t ddr0800_mul; +static uint32_t ddr_mul; +static uint32_t DDR_PHY_SLICE_REGSET_OFS; +static uint32_t DDR_PHY_ADR_V_REGSET_OFS; +static uint32_t DDR_PHY_ADR_I_REGSET_OFS; +static uint32_t DDR_PHY_ADR_G_REGSET_OFS; +static uint32_t DDR_PI_REGSET_OFS; +static uint32_t DDR_PHY_SLICE_REGSET_SIZE; +static uint32_t DDR_PHY_ADR_V_REGSET_SIZE; +static uint32_t DDR_PHY_ADR_I_REGSET_SIZE; +static uint32_t DDR_PHY_ADR_G_REGSET_SIZE; +static uint32_t DDR_PI_REGSET_SIZE; +static uint32_t DDR_PHY_SLICE_REGSET_NUM; +static uint32_t DDR_PHY_ADR_V_REGSET_NUM; +static uint32_t DDR_PHY_ADR_I_REGSET_NUM; +static uint32_t DDR_PHY_ADR_G_REGSET_NUM; +static uint32_t DDR_PI_REGSET_NUM; +static uint32_t DDR_PHY_ADR_I_NUM; +#define DDR_PHY_REGSET_MAX 128 +#define DDR_PI_REGSET_MAX 320 +static uint32_t _cnf_DDR_PHY_SLICE_REGSET[DDR_PHY_REGSET_MAX]; +static uint32_t _cnf_DDR_PHY_ADR_V_REGSET[DDR_PHY_REGSET_MAX]; +static uint32_t _cnf_DDR_PHY_ADR_I_REGSET[DDR_PHY_REGSET_MAX]; +static uint32_t _cnf_DDR_PHY_ADR_G_REGSET[DDR_PHY_REGSET_MAX]; +static uint32_t _cnf_DDR_PI_REGSET[DDR_PI_REGSET_MAX]; +static uint32_t pll3_mode; +static uint32_t loop_max; +#ifdef DDR_BACKUPMODE +uint32_t ddr_backup; +/* #define DDR_BACKUPMODE_HALF //for Half channel(ch0,1 only) */ +#endif + +#ifdef ddr_qos_init_setting /* only for non qos_init */ +#define OPERATING_FREQ (400U) /* Mhz */ +#define BASE_SUB_SLOT_NUM (0x6U) +#define SUB_SLOT_CYCLE (0x7EU) /* 126 */ +#define QOSWT_WTSET0_CYCLE \ + ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / \ + OPERATING_FREQ) /* unit:ns */ + +uint32_t get_refperiod(void) +{ + return QOSWT_WTSET0_CYCLE; +} +#else /* ddr_qos_init_setting // only for non qos_init */ +extern uint32_t get_refperiod(void); +#endif /* ddr_qos_init_setting // only for non qos_init */ + +#define _reg_PHY_RX_CAL_X_NUM 11 +static const uint32_t _reg_PHY_RX_CAL_X[_reg_PHY_RX_CAL_X_NUM] = { + _reg_PHY_RX_CAL_DQ0, + _reg_PHY_RX_CAL_DQ1, + _reg_PHY_RX_CAL_DQ2, + _reg_PHY_RX_CAL_DQ3, + _reg_PHY_RX_CAL_DQ4, + _reg_PHY_RX_CAL_DQ5, + _reg_PHY_RX_CAL_DQ6, + _reg_PHY_RX_CAL_DQ7, + _reg_PHY_RX_CAL_DM, + _reg_PHY_RX_CAL_DQS, + _reg_PHY_RX_CAL_FDBK +}; + +#define _reg_PHY_CLK_WRX_SLAVE_DELAY_NUM 10 +static const uint32_t _reg_PHY_CLK_WRX_SLAVE_DELAY + [_reg_PHY_CLK_WRX_SLAVE_DELAY_NUM] = { + _reg_PHY_CLK_WRDQ0_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ1_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ2_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ3_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ4_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ5_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ6_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ7_SLAVE_DELAY, + _reg_PHY_CLK_WRDM_SLAVE_DELAY, + _reg_PHY_CLK_WRDQS_SLAVE_DELAY +}; + +#define _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM 9 +static const uint32_t _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY + [_reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM] = { + _reg_PHY_RDDQS_DQ0_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ1_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ2_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ3_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ4_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ5_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ6_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ7_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DM_FALL_SLAVE_DELAY +}; + +#define _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM 9 +static const uint32_t _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY + [_reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM] = { + _reg_PHY_RDDQS_DQ0_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ1_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ2_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ3_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ4_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ5_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ6_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ7_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DM_RISE_SLAVE_DELAY +}; + +#define _reg_PHY_PAD_TERM_X_NUM 8 +static const uint32_t _reg_PHY_PAD_TERM_X[_reg_PHY_PAD_TERM_X_NUM] = { + _reg_PHY_PAD_FDBK_TERM, + _reg_PHY_PAD_DATA_TERM, + _reg_PHY_PAD_DQS_TERM, + _reg_PHY_PAD_ADDR_TERM, + _reg_PHY_PAD_CLK_TERM, + _reg_PHY_PAD_CKE_TERM, + _reg_PHY_PAD_RST_TERM, + _reg_PHY_PAD_CS_TERM +}; + +#define _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM 10 +static const uint32_t _reg_PHY_CLK_CACS_SLAVE_DELAY_X + [_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM] = { + _reg_PHY_ADR0_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR1_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR2_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR3_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR4_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR5_CLK_WR_SLAVE_DELAY, + + _reg_PHY_GRP_SLAVE_DELAY_0, + _reg_PHY_GRP_SLAVE_DELAY_1, + _reg_PHY_GRP_SLAVE_DELAY_2, + _reg_PHY_GRP_SLAVE_DELAY_3 +}; + +/* Prototypes */ +static inline uint32_t vch_nxt(uint32_t pos); +static void cpg_write_32(uint32_t a, uint32_t v); +static void pll3_control(uint32_t high); +static inline void dsb_sev(void); +static void wait_dbcmd(void); +static void send_dbcmd(uint32_t cmd); +static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd); +static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata); +static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata); +static inline uint32_t ddr_regdef(uint32_t _regdef); +static inline uint32_t ddr_regdef_adr(uint32_t _regdef); +static inline uint32_t ddr_regdef_lsb(uint32_t _regdef); +static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef, + uint32_t val); +static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef); +static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val); +static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val); +static void ddr_setval_ach(uint32_t regdef, uint32_t val); +static void ddr_setval_ach_as(uint32_t regdef, uint32_t val); +static uint32_t ddr_getval(uint32_t ch, uint32_t regdef); +static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p); +static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p); +static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size); +static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val); +static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef); +static uint32_t ddrphy_regif_chk(void); +static inline void ddrphy_regif_idle(void); +static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps, + uint16_t cyc); +static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, + uint16_t *_js2); +static int16_t _f_scale_adj(int16_t ps); +static void ddrtbl_load(void); +static void ddr_config_sub(void); +static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz); +static void ddr_config_sub_h3v1x(void); +static void ddr_config(void); +static void dbsc_regset(void); +static void dbsc_regset_post(void); +static uint32_t dfi_init_start(void); +static void change_lpddr4_en(uint32_t mode); +static uint32_t set_term_code(void); +static void ddr_register_set(void); +static inline uint32_t wait_freqchgreq(uint32_t assert); +static inline void set_freqchgack(uint32_t assert); +static inline void set_dfifrequency(uint32_t freq); +static uint32_t pll3_freq(uint32_t on); +static void update_dly(void); +static uint32_t pi_training_go(void); +static uint32_t init_ddr(void); +static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick); +static uint32_t wdqdm_man1(void); +static uint32_t wdqdm_man(void); +static uint32_t rdqdm_man1(void); +static uint32_t rdqdm_man(void); + +static int32_t _find_change(uint64_t val, uint32_t dir); +static uint32_t _rx_offset_cal_updn(uint32_t code); +static uint32_t rx_offset_cal(void); +static uint32_t rx_offset_cal_hw(void); +static void adjust_rddqs_latency(void); +static void adjust_wpath_latency(void); + +struct ddrt_data { + int32_t init_temp; /* Initial Temperature (do) */ + uint32_t init_cal[4]; /* Initial io-code (4 is for H3) */ + uint32_t tcomp_cal[4]; /* Temp. compensated io-code (4 is for H3) */ +}; + +static struct ddrt_data tcal; + +static void pvtcode_update(void); +static void pvtcode_update2(void); +static void ddr_padcal_tcompensate_getinit(uint32_t override); + +/* load board configuration */ +#include "boot_init_dram_config.c" + +#ifndef DDR_FAST_INIT +static uint32_t rdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9]; +static uint32_t rdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9]; +static uint32_t rdqdm_nw[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9]; +static uint32_t rdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; +static uint32_t rdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2]; +static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn); +static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn); + +static uint32_t wdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9]; +static uint32_t wdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9]; +static uint32_t wdqdm_dly[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9]; +static uint32_t wdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; +static uint32_t wdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; +static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn); +static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn); +#endif/* DDR_FAST_INIT */ + +/* macro for channel selection loop */ +static inline uint32_t vch_nxt(uint32_t pos) +{ + uint32_t posn; + + for (posn = pos; posn < DRAM_CH_CNT; posn++) { + if (ddr_phyvalid & (1U << posn)) + break; + } + return posn; +} + +#define foreach_vch(ch) \ +for (ch = vch_nxt(0); ch < DRAM_CH_CNT; ch = vch_nxt(ch + 1)) + +#define foreach_ech(ch) \ +for (ch = 0; ch < DRAM_CH_CNT; ch++) + +/* Printing functions */ +#define MSG_LF(...) + +/* clock settings, reset control */ +static void cpg_write_32(uint32_t a, uint32_t v) +{ + mmio_write_32(CPG_CPGWPR, ~v); + mmio_write_32(a, v); +} + +static void pll3_control(uint32_t high) +{ + uint32_t data_l, data_div, data_mul, tmp_div; + + if (high) { + tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) / + (brd_clk * ddr_mul) / 2; + data_mul = ((ddr_mul * tmp_div) - 1) << 24; + pll3_mode = 1; + loop_max = 2; + } else { + tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) / + (brd_clk * ddr0800_mul) / 2; + data_mul = ((ddr0800_mul * tmp_div) - 1) << 24; + pll3_mode = 0; + loop_max = 8; + } + + switch (tmp_div) { + case 1: + data_div = 0; + break; + case 2: + case 3: + case 4: + data_div = tmp_div; + break; + default: + data_div = 6; + data_mul = (data_mul * tmp_div) / 3; + break; + } + data_mul = data_mul | (brd_clkdiva << 7); + + /* PLL3 disable */ + data_l = mmio_read_32(CPG_PLLECR) & ~CPG_PLLECR_PLL3E_BIT; + cpg_write_32(CPG_PLLECR, data_l); + dsb_sev(); + + if ((prr_product == PRR_PRODUCT_M3) || + ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_20))) { + /* PLL3 DIV resetting(Lowest value:3) */ + data_l = 0x00030003 | (0xFF80FF80 & mmio_read_32(CPG_FRQCRD)); + cpg_write_32(CPG_FRQCRD, data_l); + dsb_sev(); + + /* zb3 clk stop */ + data_l = CPG_ZB3CKCR_ZB3ST_BIT | mmio_read_32(CPG_ZB3CKCR); + cpg_write_32(CPG_ZB3CKCR, data_l); + dsb_sev(); + + /* PLL3 enable */ + data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR); + cpg_write_32(CPG_PLLECR, data_l); + dsb_sev(); + + do { + data_l = mmio_read_32(CPG_PLLECR); + } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0); + dsb_sev(); + + /* PLL3 DIV resetting (Highest value:0) */ + data_l = (0xFF80FF80 & mmio_read_32(CPG_FRQCRD)); + cpg_write_32(CPG_FRQCRD, data_l); + dsb_sev(); + + /* DIV SET KICK */ + data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB); + cpg_write_32(CPG_FRQCRB, data_l); + dsb_sev(); + + /* PLL3 multiplie set */ + cpg_write_32(CPG_PLL3CR, data_mul); + dsb_sev(); + + do { + data_l = mmio_read_32(CPG_PLLECR); + } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0); + dsb_sev(); + + /* PLL3 DIV resetting(Target value) */ + data_l = (data_div << 16) | data_div | + (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80); + cpg_write_32(CPG_FRQCRD, data_l); + dsb_sev(); + + /* DIV SET KICK */ + data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB); + cpg_write_32(CPG_FRQCRB, data_l); + dsb_sev(); + + do { + data_l = mmio_read_32(CPG_PLLECR); + } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0); + dsb_sev(); + + /* zb3 clk start */ + data_l = (~CPG_ZB3CKCR_ZB3ST_BIT) & mmio_read_32(CPG_ZB3CKCR); + cpg_write_32(CPG_ZB3CKCR, data_l); + dsb_sev(); + + } else { /* H3Ver.3.0/M3N/V3H */ + + /* PLL3 multiplie set */ + cpg_write_32(CPG_PLL3CR, data_mul); + dsb_sev(); + + /* PLL3 DIV set(Target value) */ + data_l = (data_div << 16) | data_div | + (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80); + cpg_write_32(CPG_FRQCRD, data_l); + + /* DIV SET KICK */ + data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB); + cpg_write_32(CPG_FRQCRB, data_l); + dsb_sev(); + + /* PLL3 enable */ + data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR); + cpg_write_32(CPG_PLLECR, data_l); + dsb_sev(); + + do { + data_l = mmio_read_32(CPG_PLLECR); + } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0); + dsb_sev(); + } +} + +/* barrier */ +static inline void dsb_sev(void) +{ + __asm__ __volatile__("dsb sy"); +} + +/* DDR memory register access */ +static void wait_dbcmd(void) +{ + uint32_t data_l; + /* dummy read */ + data_l = mmio_read_32(DBSC_DBCMD); + dsb_sev(); + while (1) { + /* wait DBCMD 1=busy, 0=ready */ + data_l = mmio_read_32(DBSC_DBWAIT); + dsb_sev(); + if ((data_l & 0x00000001) == 0x00) + break; + } +} + +static void send_dbcmd(uint32_t cmd) +{ + /* dummy read */ + wait_dbcmd(); + mmio_write_32(DBSC_DBCMD, cmd); + dsb_sev(); +} + +static void dbwait_loop(uint32_t wait_loop) +{ + uint32_t i; + + for (i = 0; i < wait_loop; i++) + wait_dbcmd(); +} + +/* DDRPHY register access (raw) */ +static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd) +{ + uint32_t val; + uint32_t loop; + + val = 0; + if ((prr_product != PRR_PRODUCT_M3N) && + (prr_product != PRR_PRODUCT_V3H)) { + mmio_write_32(DBSC_DBPDRGA(phyno), regadd); + dsb_sev(); + + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + } + dsb_sev(); + + for (loop = 0; loop < loop_max; loop++) { + val = mmio_read_32(DBSC_DBPDRGD(phyno)); + dsb_sev(); + } + (void)val; + } else { + mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00004000); + dsb_sev(); + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != + (regadd | 0x0000C000)) { + dsb_sev(); + }; + val = mmio_read_32(DBSC_DBPDRGA(phyno)); + mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000); + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + }; + dsb_sev(); + + mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000); + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + }; + + dsb_sev(); + val = mmio_read_32(DBSC_DBPDRGD(phyno)); + dsb_sev(); + (void)val; + } + return val; +} + +static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata) +{ + uint32_t val; + uint32_t loop; + + if ((prr_product != PRR_PRODUCT_M3N) && + (prr_product != PRR_PRODUCT_V3H)) { + mmio_write_32(DBSC_DBPDRGA(phyno), regadd); + dsb_sev(); + for (loop = 0; loop < loop_max; loop++) { + val = mmio_read_32(DBSC_DBPDRGA(phyno)); + dsb_sev(); + } + mmio_write_32(DBSC_DBPDRGD(phyno), regdata); + dsb_sev(); + + for (loop = 0; loop < loop_max; loop++) { + val = mmio_read_32(DBSC_DBPDRGD(phyno)); + dsb_sev(); + } + } else { + mmio_write_32(DBSC_DBPDRGA(phyno), regadd); + dsb_sev(); + + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + }; + dsb_sev(); + + mmio_write_32(DBSC_DBPDRGD(phyno), regdata); + dsb_sev(); + + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != + (regadd | 0x00008000)) { + dsb_sev(); + }; + mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000); + + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + }; + dsb_sev(); + + mmio_write_32(DBSC_DBPDRGA(phyno), regadd); + } + (void)val; +} + +static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata) +{ + uint32_t ch; + uint32_t val; + uint32_t loop; + + if ((prr_product != PRR_PRODUCT_M3N) && + (prr_product != PRR_PRODUCT_V3H)) { + foreach_vch(ch) { + mmio_write_32(DBSC_DBPDRGA(ch), regadd); + dsb_sev(); + } + + foreach_vch(ch) { + mmio_write_32(DBSC_DBPDRGD(ch), regdata); + dsb_sev(); + } + + for (loop = 0; loop < loop_max; loop++) { + val = mmio_read_32(DBSC_DBPDRGD(0)); + dsb_sev(); + } + (void)val; + } else { + foreach_vch(ch) { + reg_ddrphy_write(ch, regadd, regdata); + dsb_sev(); + } + } +} + +static inline void ddrphy_regif_idle(void) +{ + uint32_t val; + + val = reg_ddrphy_read(0, ddr_regdef_adr(_reg_PI_INT_STATUS)); + dsb_sev(); + (void)val; +} + +/* DDRPHY register access (field modify) */ +static inline uint32_t ddr_regdef(uint32_t _regdef) +{ + return p_ddr_regdef_tbl[_regdef]; +} + +static inline uint32_t ddr_regdef_adr(uint32_t _regdef) +{ + return DDR_REGDEF_ADR(p_ddr_regdef_tbl[_regdef]); +} + +static inline uint32_t ddr_regdef_lsb(uint32_t _regdef) +{ + return DDR_REGDEF_LSB(p_ddr_regdef_tbl[_regdef]); +} + +static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef, + uint32_t val) +{ + uint32_t adr; + uint32_t lsb; + uint32_t len; + uint32_t msk; + uint32_t tmp; + uint32_t regdef; + + regdef = ddr_regdef(_regdef); + adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice; + len = DDR_REGDEF_LEN(regdef); + lsb = DDR_REGDEF_LSB(regdef); + if (len == 0x20) + msk = 0xffffffff; + else + msk = ((1U << len) - 1) << lsb; + + tmp = reg_ddrphy_read(ch, adr); + tmp = (tmp & (~msk)) | ((val << lsb) & msk); + reg_ddrphy_write(ch, adr, tmp); +} + +static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef) +{ + uint32_t adr; + uint32_t lsb; + uint32_t len; + uint32_t msk; + uint32_t tmp; + uint32_t regdef; + + regdef = ddr_regdef(_regdef); + adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice; + len = DDR_REGDEF_LEN(regdef); + lsb = DDR_REGDEF_LSB(regdef); + if (len == 0x20) + msk = 0xffffffff; + else + msk = ((1U << len) - 1); + + tmp = reg_ddrphy_read(ch, adr); + tmp = (tmp >> lsb) & msk; + + return tmp; +} + +static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val) +{ + ddr_setval_s(ch, 0, regdef, val); +} + +static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val) +{ + uint32_t ch; + + foreach_vch(ch) + ddr_setval_s(ch, slice, regdef, val); +} + +static void ddr_setval_ach(uint32_t regdef, uint32_t val) +{ + ddr_setval_ach_s(0, regdef, val); +} + +static void ddr_setval_ach_as(uint32_t regdef, uint32_t val) +{ + uint32_t slice; + + for (slice = 0; slice < SLICE_CNT; slice++) + ddr_setval_ach_s(slice, regdef, val); +} + +static uint32_t ddr_getval(uint32_t ch, uint32_t regdef) +{ + return ddr_getval_s(ch, 0, regdef); +} + +static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p) +{ + uint32_t ch; + + foreach_vch(ch) + p[ch] = ddr_getval_s(ch, 0, regdef); + return p[0]; +} + +static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p) +{ + uint32_t ch, slice; + uint32_t *pp; + + pp = p; + foreach_vch(ch) + for (slice = 0; slice < SLICE_CNT; slice++) + *pp++ = ddr_getval_s(ch, slice, regdef); + return p[0]; +} + +/* handling functions for setteing ddrphy value table */ +static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size) +{ + uint32_t i; + + for (i = 0; i < size; i++) { + to[i] = from[i]; + } +} + +static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val) +{ + uint32_t adr; + uint32_t lsb; + uint32_t len; + uint32_t msk; + uint32_t tmp; + uint32_t adrmsk; + uint32_t regdef; + + regdef = ddr_regdef(_regdef); + adr = DDR_REGDEF_ADR(regdef); + len = DDR_REGDEF_LEN(regdef); + lsb = DDR_REGDEF_LSB(regdef); + if (len == 0x20) + msk = 0xffffffff; + else + msk = ((1U << len) - 1) << lsb; + + if (adr < 0x400) { + adrmsk = 0xff; + } else { + adrmsk = 0x7f; + } + + tmp = tbl[adr & adrmsk]; + tmp = (tmp & (~msk)) | ((val << lsb) & msk); + tbl[adr & adrmsk] = tmp; +} + +static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef) +{ + uint32_t adr; + uint32_t lsb; + uint32_t len; + uint32_t msk; + uint32_t tmp; + uint32_t adrmsk; + uint32_t regdef; + + regdef = ddr_regdef(_regdef); + adr = DDR_REGDEF_ADR(regdef); + len = DDR_REGDEF_LEN(regdef); + lsb = DDR_REGDEF_LSB(regdef); + if (len == 0x20) + msk = 0xffffffff; + else + msk = ((1U << len) - 1); + + if (adr < 0x400) { + adrmsk = 0xff; + } else { + adrmsk = 0x7f; + } + + tmp = tbl[adr & adrmsk]; + tmp = (tmp >> lsb) & msk; + + return tmp; +} + +/* DDRPHY register access handling */ +static uint32_t ddrphy_regif_chk(void) +{ + uint32_t tmp_ach[DRAM_CH_CNT]; + uint32_t ch; + uint32_t err; + uint32_t PI_VERSION_CODE; + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3)) { + PI_VERSION_CODE = 0x2041; /* H3 Ver.1.x/M3-W */ + } else { + PI_VERSION_CODE = 0x2040; /* H3 Ver.2.0 or later/M3-N/V3H */ + } + + ddr_getval_ach(_reg_PI_VERSION, (uint32_t *)tmp_ach); + err = 0; + foreach_vch(ch) { + if (tmp_ach[ch] != PI_VERSION_CODE) + err = 1; + } + return err; +} + +/* functions and parameters for timing setting */ +struct _jedec_spec1 { + uint16_t fx3; + uint8_t rlwodbi; + uint8_t rlwdbi; + uint8_t WL; + uint8_t nwr; + uint8_t nrtp; + uint8_t odtlon; + uint8_t MR1; + uint8_t MR2; +}; + +#define JS1_USABLEC_SPEC_LO 2 +#define JS1_USABLEC_SPEC_HI 5 +#define JS1_FREQ_TBL_NUM 8 +#define JS1_MR1(f) (0x04 | ((f) << 4)) +#define JS1_MR2(f) (0x00 | ((f) << 3) | (f)) +const struct _jedec_spec1 js1[JS1_FREQ_TBL_NUM] = { + /* 533.333Mbps */ + { 800, 6, 6, 4, 6, 8, 0, JS1_MR1(0), JS1_MR2(0) | 0x40 }, + /* 1066.666Mbps */ + { 1600, 10, 12, 8, 10, 8, 0, JS1_MR1(1), JS1_MR2(1) | 0x40 }, + /* 1600.000Mbps */ + { 2400, 14, 16, 12, 16, 8, 6, JS1_MR1(2), JS1_MR2(2) | 0x40 }, + /* 2133.333Mbps */ + { 3200, 20, 22, 10, 20, 8, 4, JS1_MR1(3), JS1_MR2(3) }, + /* 2666.666Mbps */ + { 4000, 24, 28, 12, 24, 10, 4, JS1_MR1(4), JS1_MR2(4) }, + /* 3200.000Mbps */ + { 4800, 28, 32, 14, 30, 12, 6, JS1_MR1(5), JS1_MR2(5) }, + /* 3733.333Mbps */ + { 5600, 32, 36, 16, 34, 14, 6, JS1_MR1(6), JS1_MR2(6) }, + /* 4266.666Mbps */ + { 6400, 36, 40, 18, 40, 16, 8, JS1_MR1(7), JS1_MR2(7) } +}; + +struct _jedec_spec2 { + uint16_t ps; + uint16_t cyc; +}; + +#define js2_tsr 0 +#define js2_txp 1 +#define js2_trtp 2 +#define js2_trcd 3 +#define js2_trppb 4 +#define js2_trpab 5 +#define js2_tras 6 +#define js2_twr 7 +#define js2_twtr 8 +#define js2_trrd 9 +#define js2_tppd 10 +#define js2_tfaw 11 +#define js2_tdqsck 12 +#define js2_tckehcmd 13 +#define js2_tckelcmd 14 +#define js2_tckelpd 15 +#define js2_tmrr 16 +#define js2_tmrw 17 +#define js2_tmrd 18 +#define js2_tzqcalns 19 +#define js2_tzqlat 20 +#define js2_tiedly 21 +#define js2_tODTon_min 22 +#define JS2_TBLCNT 23 + +#define js2_trcpb (JS2_TBLCNT) +#define js2_trcab (JS2_TBLCNT + 1) +#define js2_trfcab (JS2_TBLCNT + 2) +#define JS2_CNT (JS2_TBLCNT + 3) + +#ifndef JS2_DERATE +#define JS2_DERATE 0 +#endif +const struct _jedec_spec2 jedec_spec2[2][JS2_TBLCNT] = { + { +/*tSR */ {15000, 3}, +/*tXP */ {7500, 3}, +/*tRTP */ {7500, 8}, +/*tRCD */ {18000, 4}, +/*tRPpb */ {18000, 3}, +/*tRPab */ {21000, 3}, +/*tRAS */ {42000, 3}, +/*tWR */ {18000, 4}, +/*tWTR */ {10000, 8}, +/*tRRD */ {10000, 4}, +/*tPPD */ {0, 0}, +/*tFAW */ {40000, 0}, +/*tDQSCK*/ {3500, 0}, +/*tCKEHCMD*/ {7500, 3}, +/*tCKELCMD*/ {7500, 3}, +/*tCKELPD*/ {7500, 3}, +/*tMRR*/ {0, 8}, +/*tMRW*/ {10000, 10}, +/*tMRD*/ {14000, 10}, +/*tZQCALns*/ {1000 * 10, 0}, +/*tZQLAT*/ {30000, 10}, +/*tIEdly*/ {12500, 0}, +/*tODTon_min*/ {1500, 0} + }, { +/*tSR */ {15000, 3}, +/*tXP */ {7500, 3}, +/*tRTP */ {7500, 8}, +/*tRCD */ {19875, 4}, +/*tRPpb */ {19875, 3}, +/*tRPab */ {22875, 3}, +/*tRAS */ {43875, 3}, +/*tWR */ {18000, 4}, +/*tWTR */ {10000, 8}, +/*tRRD */ {11875, 4}, +/*tPPD */ {0, 0}, +/*tFAW */ {40000, 0}, +/*tDQSCK*/ {3600, 0}, +/*tCKEHCMD*/ {7500, 3}, +/*tCKELCMD*/ {7500, 3}, +/*tCKELPD*/ {7500, 3}, +/*tMRR*/ {0, 8}, +/*tMRW*/ {10000, 10}, +/*tMRD*/ {14000, 10}, +/*tZQCALns*/ {1000 * 10, 0}, +/*tZQLAT*/ {30000, 10}, +/*tIEdly*/ {12500, 0}, +/*tODTon_min*/ {1500, 0} + } +}; + +const uint16_t jedec_spec2_trfc_ab[7] = { +/* 4Gb, 6Gb, 8Gb,12Gb, 16Gb, 24Gb(non), 32Gb(non) */ + 130, 180, 180, 280, 280, 560, 560 +}; + +static uint32_t js1_ind; +static uint16_t js2[JS2_CNT]; +static uint8_t RL; +static uint8_t WL; + +static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps, + uint16_t cyc) +{ + uint32_t tmp; + uint32_t div; + + tmp = (((uint32_t)(ps) + 9) / 10) * _ddr_mbps; + div = tmp / (200000 * _ddr_mbpsdiv); + if (tmp != (div * 200000 * _ddr_mbpsdiv)) + div = div + 1; + + if (div > cyc) + return (uint16_t)div; + return cyc; +} + +static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, + uint16_t *_js2) +{ + int i; + + for (i = 0; i < JS2_TBLCNT; i++) { + _js2[i] = _f_scale(_ddr_mbps, _ddr_mbpsdiv, + 1UL * jedec_spec2[JS2_DERATE][i].ps, + jedec_spec2[JS2_DERATE][i].cyc); + } + + _js2[js2_trcpb] = _js2[js2_tras] + _js2[js2_trppb]; + _js2[js2_trcab] = _js2[js2_tras] + _js2[js2_trpab]; +} + +/* scaler for DELAY value */ +static int16_t _f_scale_adj(int16_t ps) +{ + int32_t tmp; + /* + * tmp = (int32_t)512 * ps * ddr_mbps /2 / ddr_mbpsdiv / 1000 / 1000; + * = ps * ddr_mbps /2 / ddr_mbpsdiv *512 / 8 / 8 / 125 / 125 + * = ps * ddr_mbps / ddr_mbpsdiv *4 / 125 / 125 + */ + tmp = + (int32_t)4 * (int32_t)ps * (int32_t)ddr_mbps / + (int32_t)ddr_mbpsdiv; + tmp = (int32_t)tmp / (int32_t)15625; + + return (int16_t)tmp; +} + +static const uint32_t reg_pi_mr1_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR1_DATA_F0_0, + _reg_PI_MR1_DATA_F0_1, + _reg_PI_MR1_DATA_F0_2, + _reg_PI_MR1_DATA_F0_3}, + { + _reg_PI_MR1_DATA_F1_0, + _reg_PI_MR1_DATA_F1_1, + _reg_PI_MR1_DATA_F1_2, + _reg_PI_MR1_DATA_F1_3} +}; + +static const uint32_t reg_pi_mr2_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR2_DATA_F0_0, + _reg_PI_MR2_DATA_F0_1, + _reg_PI_MR2_DATA_F0_2, + _reg_PI_MR2_DATA_F0_3}, + { + _reg_PI_MR2_DATA_F1_0, + _reg_PI_MR2_DATA_F1_1, + _reg_PI_MR2_DATA_F1_2, + _reg_PI_MR2_DATA_F1_3} +}; + +static const uint32_t reg_pi_mr3_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR3_DATA_F0_0, + _reg_PI_MR3_DATA_F0_1, + _reg_PI_MR3_DATA_F0_2, + _reg_PI_MR3_DATA_F0_3}, + { + _reg_PI_MR3_DATA_F1_0, + _reg_PI_MR3_DATA_F1_1, + _reg_PI_MR3_DATA_F1_2, + _reg_PI_MR3_DATA_F1_3} +}; + +const uint32_t reg_pi_mr11_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR11_DATA_F0_0, + _reg_PI_MR11_DATA_F0_1, + _reg_PI_MR11_DATA_F0_2, + _reg_PI_MR11_DATA_F0_3}, + { + _reg_PI_MR11_DATA_F1_0, + _reg_PI_MR11_DATA_F1_1, + _reg_PI_MR11_DATA_F1_2, + _reg_PI_MR11_DATA_F1_3} +}; + +const uint32_t reg_pi_mr12_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR12_DATA_F0_0, + _reg_PI_MR12_DATA_F0_1, + _reg_PI_MR12_DATA_F0_2, + _reg_PI_MR12_DATA_F0_3}, + { + _reg_PI_MR12_DATA_F1_0, + _reg_PI_MR12_DATA_F1_1, + _reg_PI_MR12_DATA_F1_2, + _reg_PI_MR12_DATA_F1_3} +}; + +const uint32_t reg_pi_mr14_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR14_DATA_F0_0, + _reg_PI_MR14_DATA_F0_1, + _reg_PI_MR14_DATA_F0_2, + _reg_PI_MR14_DATA_F0_3}, + { + _reg_PI_MR14_DATA_F1_0, + _reg_PI_MR14_DATA_F1_1, + _reg_PI_MR14_DATA_F1_2, + _reg_PI_MR14_DATA_F1_3} +}; + +/* + * regif pll w/a ( REGIF H3 Ver.2.0 or later/M3-N/V3H WA ) + */ +static void regif_pll_wa(void) +{ + uint32_t ch; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + // PLL setting for PHY : H3 Ver.1.x + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT), + (0x0064U << + ddr_regdef_lsb(_reg_PHY_PLL_WAIT))); + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL), + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PLL_CTRL)); + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL), + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_PLL_CTRL)); + + } else { + /* PLL setting for PHY : M3-W/M3-N/V3H/H3 Ver.2.0 or later */ + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT), + (0x5064U << + ddr_regdef_lsb(_reg_PHY_PLL_WAIT))); + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL), + (ddrtbl_getval + (_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PLL_CTRL_TOP) << 16) | + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PLL_CTRL)); + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL_CA), + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PLL_CTRL_CA)); + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL), + (ddrtbl_getval + (_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_PLL_CTRL_CA) << 16) | + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_PLL_CTRL)); + reg_ddrphy_write_a(ddr_regdef_adr + (_reg_PHY_LP4_BOOT_TOP_PLL_CTRL), + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_TOP_PLL_CTRL + )); + } + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LPDDR3_CS), + _cnf_DDR_PHY_ADR_G_REGSET + [ddr_regdef_adr(_reg_PHY_LPDDR3_CS) - + DDR_PHY_ADR_G_REGSET_OFS]); + + /* protect register interface */ + ddrphy_regif_idle(); + pll3_control(0); + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + /* non */ + } else { + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_DLL_RST_EN), + (0x01U << + ddr_regdef_lsb(_reg_PHY_DLL_RST_EN))); + ddrphy_regif_idle(); + } + + /* init start */ + /* dbdficnt0: + * dfi_dram_clk_disable=1 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =0 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10); + dsb_sev(); + + /* dbdficnt0: + * dfi_dram_clk_disable=1 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =1 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11); + dsb_sev(); + + foreach_ech(ch) + if ((board_cnf->phyvalid) & BIT(ch)) + while ((mmio_read_32(DBSC_PLL_LOCK(ch)) & 0x1f) != 0x1f) + ; + dsb_sev(); +} + +/* load table data into DDR registers */ +static void ddrtbl_load(void) +{ + uint32_t i; + uint32_t slice; + uint32_t csab; + uint32_t adr; + uint32_t data_l; + uint32_t tmp[3]; + uint16_t dataS; + + /* TIMING REGISTERS */ + /* search jedec_spec1 index */ + for (i = JS1_USABLEC_SPEC_LO; i < JS1_FREQ_TBL_NUM - 1; i++) { + if (js1[i].fx3 * 2U * ddr_mbpsdiv >= ddr_mbps * 3U) + break; + } + if (i > JS1_USABLEC_SPEC_HI) + js1_ind = JS1_USABLEC_SPEC_HI; + else + js1_ind = i; + + if (board_cnf->dbi_en) + RL = js1[js1_ind].rlwdbi; + else + RL = js1[js1_ind].rlwodbi; + + WL = js1[js1_ind].WL; + + /* calculate jedec_spec2 */ + _f_scale_js2(ddr_mbps, ddr_mbpsdiv, js2); + + /* PREPARE TBL */ + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut <= PRR_PRODUCT_11) { + /* H3 Ver.1.x */ + _tblcopy(_cnf_DDR_PHY_SLICE_REGSET, + DDR_PHY_SLICE_REGSET_H3, + DDR_PHY_SLICE_REGSET_NUM_H3); + _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, + DDR_PHY_ADR_V_REGSET_H3, + DDR_PHY_ADR_V_REGSET_NUM_H3); + _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, + DDR_PHY_ADR_I_REGSET_H3, + DDR_PHY_ADR_I_REGSET_NUM_H3); + _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, + DDR_PHY_ADR_G_REGSET_H3, + DDR_PHY_ADR_G_REGSET_NUM_H3); + _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3, + DDR_PI_REGSET_NUM_H3); + + DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_H3; + DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_H3; + DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_H3; + DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_H3; + DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3; + DDR_PHY_SLICE_REGSET_SIZE = + DDR_PHY_SLICE_REGSET_SIZE_H3; + DDR_PHY_ADR_V_REGSET_SIZE = + DDR_PHY_ADR_V_REGSET_SIZE_H3; + DDR_PHY_ADR_I_REGSET_SIZE = + DDR_PHY_ADR_I_REGSET_SIZE_H3; + DDR_PHY_ADR_G_REGSET_SIZE = + DDR_PHY_ADR_G_REGSET_SIZE_H3; + DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3; + DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_H3; + DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_H3; + DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_H3; + DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_H3; + DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3; + + DDR_PHY_ADR_I_NUM = 1; + } else { + /* H3 Ver.2.0 or later */ + _tblcopy(_cnf_DDR_PHY_SLICE_REGSET, + DDR_PHY_SLICE_REGSET_H3VER2, + DDR_PHY_SLICE_REGSET_NUM_H3VER2); + _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, + DDR_PHY_ADR_V_REGSET_H3VER2, + DDR_PHY_ADR_V_REGSET_NUM_H3VER2); + _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, + DDR_PHY_ADR_G_REGSET_H3VER2, + DDR_PHY_ADR_G_REGSET_NUM_H3VER2); + _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3VER2, + DDR_PI_REGSET_NUM_H3VER2); + + DDR_PHY_SLICE_REGSET_OFS = + DDR_PHY_SLICE_REGSET_OFS_H3VER2; + DDR_PHY_ADR_V_REGSET_OFS = + DDR_PHY_ADR_V_REGSET_OFS_H3VER2; + DDR_PHY_ADR_G_REGSET_OFS = + DDR_PHY_ADR_G_REGSET_OFS_H3VER2; + DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3VER2; + DDR_PHY_SLICE_REGSET_SIZE = + DDR_PHY_SLICE_REGSET_SIZE_H3VER2; + DDR_PHY_ADR_V_REGSET_SIZE = + DDR_PHY_ADR_V_REGSET_SIZE_H3VER2; + DDR_PHY_ADR_G_REGSET_SIZE = + DDR_PHY_ADR_G_REGSET_SIZE_H3VER2; + DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3VER2; + DDR_PHY_SLICE_REGSET_NUM = + DDR_PHY_SLICE_REGSET_NUM_H3VER2; + DDR_PHY_ADR_V_REGSET_NUM = + DDR_PHY_ADR_V_REGSET_NUM_H3VER2; + DDR_PHY_ADR_G_REGSET_NUM = + DDR_PHY_ADR_G_REGSET_NUM_H3VER2; + DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3VER2; + + DDR_PHY_ADR_I_NUM = 0; + } + } else if (prr_product == PRR_PRODUCT_M3) { + /* M3-W */ + _tblcopy(_cnf_DDR_PHY_SLICE_REGSET, + DDR_PHY_SLICE_REGSET_M3, DDR_PHY_SLICE_REGSET_NUM_M3); + _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, + DDR_PHY_ADR_V_REGSET_M3, DDR_PHY_ADR_V_REGSET_NUM_M3); + _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, + DDR_PHY_ADR_I_REGSET_M3, DDR_PHY_ADR_I_REGSET_NUM_M3); + _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, + DDR_PHY_ADR_G_REGSET_M3, DDR_PHY_ADR_G_REGSET_NUM_M3); + _tblcopy(_cnf_DDR_PI_REGSET, + DDR_PI_REGSET_M3, DDR_PI_REGSET_NUM_M3); + + DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3; + DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3; + DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3; + DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3; + DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3; + DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3; + DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3; + DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3; + DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3; + DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3; + DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3; + DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3; + DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3; + DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3; + DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3; + + DDR_PHY_ADR_I_NUM = 2; + } else { + /* M3-N/V3H */ + _tblcopy(_cnf_DDR_PHY_SLICE_REGSET, + DDR_PHY_SLICE_REGSET_M3N, + DDR_PHY_SLICE_REGSET_NUM_M3N); + _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, DDR_PHY_ADR_V_REGSET_M3N, + DDR_PHY_ADR_V_REGSET_NUM_M3N); + _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, DDR_PHY_ADR_I_REGSET_M3N, + DDR_PHY_ADR_I_REGSET_NUM_M3N); + _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, DDR_PHY_ADR_G_REGSET_M3N, + DDR_PHY_ADR_G_REGSET_NUM_M3N); + _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_M3N, + DDR_PI_REGSET_NUM_M3N); + + DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3N; + DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3N; + DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3N; + DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3N; + DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3N; + DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3N; + DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3N; + DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3N; + DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3N; + DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3N; + DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3N; + DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3N; + DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3N; + DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3N; + DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3N; + + DDR_PHY_ADR_I_NUM = 2; + } + + /* PLL CODE CHANGE */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) { + ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, _reg_PHY_PLL_CTRL, + 0x1142); + ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_PLL_CTRL, 0x1142); + } + + /* on fly gate adjust */ + if ((prr_product == PRR_PRODUCT_M3) && (prr_cut == PRR_PRODUCT_10)) { + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_ON_FLY_GATE_ADJUST_EN, 0x00); + } + + /* Adjust PI parameters */ +#ifdef _def_LPDDR4_ODT + for (i = 0; i < 2; i++) { + for (csab = 0; csab < CSAB_CNT; csab++) { + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr11_data_fx_csx[i][csab], + _def_LPDDR4_ODT); + } + } +#endif /* _def_LPDDR4_ODT */ + +#ifdef _def_LPDDR4_VREFCA + for (i = 0; i < 2; i++) { + for (csab = 0; csab < CSAB_CNT; csab++) { + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr12_data_fx_csx[i][csab], + _def_LPDDR4_VREFCA); + } + } +#endif /* _def_LPDDR4_VREFCA */ + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 7000, 0) + 7U; + if (js2[js2_tiedly] > (RL)) + js2[js2_tiedly] = RL; + } else if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) { + js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 9000, 0) + 4U; + } else if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 10000, 0); + } + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + if ((js2[js2_tiedly]) >= 0x1e) + dataS = 0x1e; + else + dataS = js2[js2_tiedly]; + } else { + if ((js2[js2_tiedly]) >= 0x0e) + dataS = 0x0e; + else + dataS = js2[js2_tiedly]; + } + + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_DLY, dataS); + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_TSEL_DLY, + (dataS - 2)); + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_RDDATA_EN_OE_DLY, dataS - 2); + } + ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1, RL - dataS); + + if (ddrtbl_getval + (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD)) { + data_l = WL - 1; + } else { + data_l = WL; + } + ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1, data_l - 2); + ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1, data_l); + + if (board_cnf->dbi_en) { + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE, + 0x01); + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_WDQLVL_DATADM_MASK, 0x000); + } else { + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE, + 0x00); + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_WDQLVL_DATADM_MASK, 0x100); + } + + tmp[0] = js1[js1_ind].MR1; + tmp[1] = js1[js1_ind].MR2; + data_l = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_MR3_DATA_F1_0); + if (board_cnf->dbi_en) + tmp[2] = data_l | 0xc0; + else + tmp[2] = data_l & (~0xc0); + + for (i = 0; i < 2; i++) { + for (csab = 0; csab < CSAB_CNT; csab++) { + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr1_data_fx_csx[i][csab], tmp[0]); + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr2_data_fx_csx[i][csab], tmp[1]); + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr3_data_fx_csx[i][csab], tmp[2]); + } + } + + /* DDRPHY INT START */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + /* non */ + } else { + regif_pll_wa(); + dbwait_loop(5); + } + + /* FREQ_SEL_MULTICAST & PER_CS_TRAINING_MULTICAST SET (for safety) */ + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN), + BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN))); + ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x01); + + /* SET DATA SLICE TABLE */ + for (slice = 0; slice < SLICE_CNT; slice++) { + adr = + DDR_PHY_SLICE_REGSET_OFS + + DDR_PHY_SLICE_REGSET_SIZE * slice; + for (i = 0; i < DDR_PHY_SLICE_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, + _cnf_DDR_PHY_SLICE_REGSET[i]); + } + } + + /* SET ADR SLICE TABLE */ + adr = DDR_PHY_ADR_V_REGSET_OFS; + for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_V_REGSET[i]); + } + + if (((prr_product == PRR_PRODUCT_M3) || + (prr_product == PRR_PRODUCT_M3N)) && + ((0x00ffffff & (uint32_t)((board_cnf->ch[0].ca_swap) >> 40)) + != 0x00)) { + adr = DDR_PHY_ADR_I_REGSET_OFS + DDR_PHY_ADR_I_REGSET_SIZE; + for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, + _cnf_DDR_PHY_ADR_V_REGSET[i]); + } + ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_ADR_DISABLE, 0x02); + DDR_PHY_ADR_I_NUM -= 1; + ddr_phycaslice = 1; + +#ifndef _def_LPDDR4_ODT + for (i = 0; i < 2; i++) { + for (csab = 0; csab < CSAB_CNT; csab++) { + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr11_data_fx_csx[i][csab], + 0x66); + } + } +#endif/* _def_LPDDR4_ODT */ + } else { + ddr_phycaslice = 0; + } + + if (DDR_PHY_ADR_I_NUM > 0) { + for (slice = 0; slice < DDR_PHY_ADR_I_NUM; slice++) { + adr = + DDR_PHY_ADR_I_REGSET_OFS + + DDR_PHY_ADR_I_REGSET_SIZE * slice; + for (i = 0; i < DDR_PHY_ADR_I_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, + _cnf_DDR_PHY_ADR_I_REGSET + [i]); + } + } + } + + /* SET ADRCTRL SLICE TABLE */ + adr = DDR_PHY_ADR_G_REGSET_OFS; + for (i = 0; i < DDR_PHY_ADR_G_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_G_REGSET[i]); + } + + /* SET PI REGISTERS */ + adr = DDR_PI_REGSET_OFS; + for (i = 0; i < DDR_PI_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, _cnf_DDR_PI_REGSET[i]); + } +} + +/* CONFIGURE DDR REGISTERS */ +static void ddr_config_sub(void) +{ + uint32_t i; + uint32_t ch, slice; + uint32_t data_l; + uint32_t tmp; + uint8_t high_byte[SLICE_CNT]; + const uint32_t _par_CALVL_DEVICE_MAP = 1; + + foreach_vch(ch) { + /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */ + for (slice = 0; slice < SLICE_CNT; slice++) { + high_byte[slice] = + (board_cnf->ch[ch].dqs_swap >> (4 * slice)) % 2; + ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE0, + board_cnf->ch[ch].dq_swap[slice]); + ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE1, + board_cnf->ch[ch].dm_swap[slice]); + if (high_byte[slice]) { + /* HIGHER 16 BYTE */ + ddr_setval_s(ch, slice, + _reg_PHY_CALVL_VREF_DRIVING_SLICE, + 0x00); + } else { + /* LOWER 16 BYTE */ + ddr_setval_s(ch, slice, + _reg_PHY_CALVL_VREF_DRIVING_SLICE, + 0x01); + } + } + + /* BOARD SETTINGS (CA,ADDR_SEL) */ + data_l = (0x00ffffff & (uint32_t)(board_cnf->ch[ch].ca_swap)) | + 0x00888888; + + /* --- ADR_CALVL_SWIZZLE --- */ + if (prr_product == PRR_PRODUCT_M3) { + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, data_l); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0, + 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, data_l); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1, + 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP, + _par_CALVL_DEVICE_MAP); + } else { + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0, data_l); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1, 0x00000000); + ddr_setval(ch, _reg_PHY_CALVL_DEVICE_MAP, + _par_CALVL_DEVICE_MAP); + } + + /* --- ADR_ADDR_SEL --- */ + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) { + data_l = 0x00FFFFFF & board_cnf->ch[ch].ca_swap; + } else { + data_l = 0; + tmp = board_cnf->ch[ch].ca_swap; + for (i = 0; i < 6; i++) { + data_l |= ((tmp & 0x0f) << (i * 5)); + tmp = tmp >> 4; + } + } + ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, data_l); + if (ddr_phycaslice == 1) { + /* ----------- adr slice2 swap ----------- */ + tmp = (uint32_t)((board_cnf->ch[ch].ca_swap) >> 40); + data_l = (tmp & 0x00ffffff) | 0x00888888; + + /* --- ADR_CALVL_SWIZZLE --- */ + if (prr_product == PRR_PRODUCT_M3) { + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE0_0, + data_l); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE1_0, + 0x00000000); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE0_1, + data_l); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE1_1, + 0x00000000); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_DEVICE_MAP, + _par_CALVL_DEVICE_MAP); + } else { + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE0, + data_l); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE1, + 0x00000000); + ddr_setval_s(ch, 2, + _reg_PHY_CALVL_DEVICE_MAP, + _par_CALVL_DEVICE_MAP); + } + + /* --- ADR_ADDR_SEL --- */ + data_l = 0; + for (i = 0; i < 6; i++) { + data_l |= ((tmp & 0x0f) << (i * 5)); + tmp = tmp >> 4; + } + + ddr_setval_s(ch, 2, _reg_PHY_ADR_ADDR_SEL, data_l); + } + + /* BOARD SETTINGS (BYTE_ORDER_SEL) */ + if (prr_product == PRR_PRODUCT_M3) { + /* --- DATA_BYTE_SWAP --- */ + data_l = 0; + tmp = board_cnf->ch[ch].dqs_swap; + for (i = 0; i < 4; i++) { + data_l |= ((tmp & 0x03) << (i * 2)); + tmp = tmp >> 4; + } + } else { + /* --- DATA_BYTE_SWAP --- */ + data_l = board_cnf->ch[ch].dqs_swap; + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_EN, 0x01); + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE0, + (data_l) & 0x0f); + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE1, + (data_l >> 4 * 1) & 0x0f); + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE2, + (data_l >> 4 * 2) & 0x0f); + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE3, + (data_l >> 4 * 3) & 0x0f); + + ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL_HIGH, 0x00); + } + ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL, data_l); + } +} + +static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz) +{ + uint32_t slice; + uint32_t tmp; + uint32_t tgt; + + if (ddr_csn / 2) { + tgt = 3; + } else { + tgt = 1; + } + + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (tgt == tmp) + break; + } + tmp = 0x00FFFFFF & board_cnf->ch[ch].ca_swap; + if (slice % 2) + tmp |= 0x00888888; + *p_swz = tmp; +} + +static void ddr_config_sub_h3v1x(void) +{ + uint32_t ch, slice; + uint32_t data_l; + uint32_t tmp; + uint8_t high_byte[SLICE_CNT]; + uint32_t ca_swizzle; + uint32_t ca; + uint32_t csmap; + uint32_t o_inv; + uint32_t inv; + uint32_t bit_soc; + uint32_t bit_mem; + uint32_t j; + + const uint8_t o_mr15 = 0x55; + const uint8_t o_mr20 = 0x55; + const uint16_t o_mr32_mr40 = 0x5a3c; + + foreach_vch(ch) { + /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */ + csmap = 0; + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & + 0x0f; + high_byte[slice] = tmp % 2; + if (tmp == 1 && (slice >= 2)) + csmap |= 0x05; + if (tmp == 3 && (slice >= 2)) + csmap |= 0x50; + ddr_setval_s(ch, slice, _reg_PHY_DQ_SWIZZLING, + board_cnf->ch[ch].dq_swap[slice]); + if (high_byte[slice]) { + /* HIGHER 16 BYTE */ + ddr_setval_s(ch, slice, + _reg_PHY_CALVL_VREF_DRIVING_SLICE, + 0x00); + } else { + /* LOWER 16 BYTE */ + ddr_setval_s(ch, slice, + _reg_PHY_CALVL_VREF_DRIVING_SLICE, + 0x01); + } + } + /* BOARD SETTINGS (CA,ADDR_SEL) */ + ca = 0x00FFFFFF & board_cnf->ch[ch].ca_swap; + ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, ca); + ddr_setval(ch, _reg_PHY_CALVL_CS_MAP, csmap); + + get_ca_swizzle(ch, 0, &ca_swizzle); + + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, ca_swizzle); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0, 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1, 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP, 0x01); + + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_NUM, + 0x01); + ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_START, + 0x08); + + if (high_byte[slice]) + o_inv = o_mr20; + else + o_inv = o_mr15; + + tmp = board_cnf->ch[ch].dq_swap[slice]; + inv = 0; + j = 0; + for (bit_soc = 0; bit_soc < 8; bit_soc++) { + bit_mem = (tmp >> (4 * bit_soc)) & 0x0f; + j |= (1U << bit_mem); + if (o_inv & (1U << bit_mem)) + inv |= (1U << bit_soc); + } + data_l = o_mr32_mr40; + if (!high_byte[slice]) + data_l |= (inv << 24); + if (high_byte[slice]) + data_l |= (inv << 16); + ddr_setval_s(ch, slice, _reg_PHY_LP4_RDLVL_PATT8, + data_l); + } + } +} + +static void ddr_config(void) +{ + int32_t i; + uint32_t ch, slice; + uint32_t data_l; + uint32_t tmp; + int8_t _adj; + int16_t adj; + uint32_t dq; + union { + uint32_t ui32[4]; + uint8_t ui8[16]; + } patt; + uint16_t patm; + + /* configure ddrphy registers */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + ddr_config_sub_h3v1x(); + } else { /* H3 Ver.2.0 or later/M3-N/V3H is same as M3-W */ + ddr_config_sub(); + } + + /* WDQ_USER_PATT */ + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + patm = 0; + for (i = 0; i < 16; i++) { + tmp = board_cnf->ch[ch].wdqlvl_patt[i]; + patt.ui8[i] = tmp & 0xff; + if (tmp & 0x100) + patm |= (1U << i); + } + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT0, + patt.ui32[0]); + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT1, + patt.ui32[1]); + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT2, + patt.ui32[2]); + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT3, + patt.ui32[3]); + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT4, patm); + } + } + + /* CACS DLY */ + data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj); + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN), + 0x00U); + foreach_vch(ch) { + for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4; i++) { + adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]); + ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET, + _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i], + data_l + adj); + reg_ddrphy_write(ch, + ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]), + _cnf_DDR_PHY_ADR_V_REGSET + [ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) - + DDR_PHY_ADR_V_REGSET_OFS]); + } + + for (i = (_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4); + i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) { + adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]); + ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i], + data_l + adj); + reg_ddrphy_write(ch, + ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]), + _cnf_DDR_PHY_ADR_G_REGSET + [ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) - + DDR_PHY_ADR_G_REGSET_OFS]); + } + + if (ddr_phycaslice == 1) { + for (i = 0; i < 6; i++) { + adj = _f_scale_adj + (board_cnf->ch[ch].cacs_adj + [i + + _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]); + ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET, + _reg_PHY_CLK_CACS_SLAVE_DELAY_X + [i], + data_l + adj); + reg_ddrphy_write(ch, + ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) + + 0x0100, + _cnf_DDR_PHY_ADR_V_REGSET + [ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) - + DDR_PHY_ADR_V_REGSET_OFS]); + } + } + } + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN), + BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN))); + + /* WDQDM DLY */ + data_l = board_cnf->dqdm_dly_w; + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (i = 0; i <= 8; i++) { + dq = slice * 8 + i; + if (i == 8) + _adj = board_cnf->ch[ch].dm_adj_w[slice]; + else + _adj = board_cnf->ch[ch].dq_adj_w[dq]; + adj = _f_scale_adj(_adj); + ddr_setval_s(ch, slice, + _reg_PHY_CLK_WRX_SLAVE_DELAY[i], + data_l + adj); + } + } + } + + /* RDQDM DLY */ + data_l = board_cnf->dqdm_dly_r; + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (i = 0; i <= 8; i++) { + dq = slice * 8 + i; + if (i == 8) + _adj = board_cnf->ch[ch].dm_adj_r[slice]; + else + _adj = board_cnf->ch[ch].dq_adj_r[dq]; + adj = _f_scale_adj(_adj); + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY + [i], data_l + adj); + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY + [i], data_l + adj); + } + } + } +} + +/* DBSC register setting functions */ +static void dbsc_regset_pre(void) +{ + uint32_t ch, csab; + uint32_t data_l; + + /* PRIMARY SETTINGS */ + /* LPDDR4, BL=16, DFI interface */ + mmio_write_32(DBSC_DBKIND, 0x0000000a); + mmio_write_32(DBSC_DBBL, 0x00000002); + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + + /* FREQRATIO=2 */ + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + + /* Chanel map (H3 Ver.1.x) */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) + mmio_write_32(DBSC_DBSCHCNT1, 0x00001010); + + /* DRAM SIZE REGISTER: + * set all ranks as density=0(4Gb) for PHY initialization + */ + foreach_vch(ch) { + for (csab = 0; csab < 4; csab++) { + mmio_write_32(DBSC_DBMEMCONF(ch, csab), + DBMEMCONF_REGD(0)); + } + } + + if (prr_product == PRR_PRODUCT_M3) { + data_l = 0xe4e4e4e4; + foreach_ech(ch) { + if ((ddr_phyvalid & (1U << ch))) + data_l = (data_l & (~(0x000000FF << (ch * 8)))) + | (((board_cnf->ch[ch].dqs_swap & 0x0003) + | ((board_cnf->ch[ch].dqs_swap & 0x0030) + >> 2) + | ((board_cnf->ch[ch].dqs_swap & 0x0300) + >> 4) + | ((board_cnf->ch[ch].dqs_swap & 0x3000) + >> 6)) << (ch * 8)); + } + mmio_write_32(DBSC_DBBSWAP, data_l); + } +} + +static void dbsc_regset(void) +{ + int32_t i; + uint32_t ch; + uint32_t data_l; + uint32_t data_l2; + uint32_t tmp[4]; + + /* RFC */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_20) && + (max_density == 0)) { + js2[js2_trfcab] = + _f_scale(ddr_mbps, ddr_mbpsdiv, + 1UL * jedec_spec2_trfc_ab[1] * 1000, 0); + } else { + js2[js2_trfcab] = + _f_scale(ddr_mbps, ddr_mbpsdiv, + 1UL * jedec_spec2_trfc_ab[max_density] * + 1000, 0); + } + + /* DBTR0.CL : RL */ + mmio_write_32(DBSC_DBTR(0), RL); + + /* DBTR1.CWL : WL */ + mmio_write_32(DBSC_DBTR(1), WL); + + /* DBTR2.AL : 0 */ + mmio_write_32(DBSC_DBTR(2), 0); + + /* DBTR3.TRCD: tRCD */ + mmio_write_32(DBSC_DBTR(3), js2[js2_trcd]); + + /* DBTR4.TRPA,TRP: tRPab,tRPpb */ + mmio_write_32(DBSC_DBTR(4), (js2[js2_trpab] << 16) | js2[js2_trppb]); + + /* DBTR5.TRC : use tRCpb */ + mmio_write_32(DBSC_DBTR(5), js2[js2_trcpb]); + + /* DBTR6.TRAS : tRAS */ + mmio_write_32(DBSC_DBTR(6), js2[js2_tras]); + + /* DBTR7.TRRD : tRRD */ + mmio_write_32(DBSC_DBTR(7), (js2[js2_trrd] << 16) | js2[js2_trrd]); + + /* DBTR8.TFAW : tFAW */ + mmio_write_32(DBSC_DBTR(8), js2[js2_tfaw]); + + /* DBTR9.TRDPR : tRTP */ + mmio_write_32(DBSC_DBTR(9), js2[js2_trtp]); + + /* DBTR10.TWR : nWR */ + mmio_write_32(DBSC_DBTR(10), js1[js1_ind].nwr); + + /* + * DBTR11.TRDWR : RL + BL / 2 + Rounddown(tRPST) + PHY_ODTLoff - + * odtlon + tDQSCK - tODTon,min + + * PCB delay (out+in) + tPHY_ODToff + */ + mmio_write_32(DBSC_DBTR(11), + RL + (16 / 2) + 1 + 2 - js1[js1_ind].odtlon + + js2[js2_tdqsck] - js2[js2_tODTon_min] + + _f_scale(ddr_mbps, ddr_mbpsdiv, 1300, 0)); + + /* DBTR12.TWRRD : WL + 1 + BL/2 + tWTR */ + data_l = WL + 1 + (16 / 2) + js2[js2_twtr]; + mmio_write_32(DBSC_DBTR(12), (data_l << 16) | data_l); + + /* DBTR13.TRFCAB : tRFCab */ + mmio_write_32(DBSC_DBTR(13), (js2[js2_trfcab])); + + /* DBTR14.TCKEHDLL,tCKEH : tCKEHCMD,tCKEHCMD */ + mmio_write_32(DBSC_DBTR(14), + (js2[js2_tckehcmd] << 16) | (js2[js2_tckehcmd])); + + /* DBTR15.TCKESR,TCKEL : tSR,tCKELPD */ + mmio_write_32(DBSC_DBTR(15), (js2[js2_tsr] << 16) | (js2[js2_tckelpd])); + + /* DBTR16 */ + /* WDQL : tphy_wrlat + tphy_wrdata */ + tmp[0] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1); + /* DQENLTNCY : tphy_wrlat = WL-2 : PHY_WRITE_PATH_LAT_ADD == 0 + * tphy_wrlat = WL-3 : PHY_WRITE_PATH_LAT_ADD != 0 + */ + tmp[1] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1); + /* DQL : tphy_rdlat + trdata_en */ + /* it is not important for dbsc */ + tmp[2] = RL + 16; + /* DQIENLTNCY : trdata_en */ + tmp[3] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1) - 1; + mmio_write_32(DBSC_DBTR(16), + (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* DBTR24 */ + /* WRCSLAT = WRLAT -5 */ + tmp[0] -= 5; + /* WRCSGAP = 5 */ + tmp[1] = 5; + /* RDCSLAT = RDLAT_ADJ +2 */ + if (prr_product == PRR_PRODUCT_M3) { + tmp[2] = tmp[3]; + } else { + tmp[2] = tmp[3] + 2; + } + /* RDCSGAP = 6 */ + if (prr_product == PRR_PRODUCT_M3) { + tmp[3] = 4; + } else { + tmp[3] = 6; + } + mmio_write_32(DBSC_DBTR(24), + (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* DBTR17.TMODRD,TMOD,TRDMR: tMRR,tMRD,(0) */ + mmio_write_32(DBSC_DBTR(17), + (js2[js2_tmrr] << 24) | (js2[js2_tmrd] << 16)); + + /* DBTR18.RODTL, RODTA, WODTL, WODTA : do not use in LPDDR4 */ + mmio_write_32(DBSC_DBTR(18), 0); + + /* DBTR19.TZQCL, TZQCS : do not use in LPDDR4 */ + mmio_write_32(DBSC_DBTR(19), 0); + + /* DBTR20.TXSDLL, TXS : tRFCab+tCKEHCMD */ + data_l = js2[js2_trfcab] + js2[js2_tckehcmd]; + mmio_write_32(DBSC_DBTR(20), (data_l << 16) | data_l); + + /* DBTR21.TCCD */ + /* DBTR23.TCCD */ + /* H3 Ver.1.0 cannot use TBTR23 feature */ + if (ddr_tccd == 8 && + !((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_10)) + ) { + data_l = 8; + mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l); + mmio_write_32(DBSC_DBTR(23), 0x00000002); + } else if (ddr_tccd <= 11) { + data_l = 11; + mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l); + mmio_write_32(DBSC_DBTR(23), 0x00000000); + } else { + data_l = ddr_tccd; + mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l); + mmio_write_32(DBSC_DBTR(23), 0x00000000); + } + + /* DBTR22.ZQLAT : */ + data_l = js2[js2_tzqcalns] * 100; /* 1000 * 1000 ps */ + data_l = (data_l << 16) | (js2[js2_tzqlat] + 24 + 20); + mmio_write_32(DBSC_DBTR(22), data_l); + + /* DBTR25 : do not use in LPDDR4 */ + mmio_write_32(DBSC_DBTR(25), 0); + + /* DBRNK : */ + /* + * DBSC_DBRNK2 rkrr + * DBSC_DBRNK3 rkrw + * DBSC_DBRNK4 rkwr + * DBSC_DBRNK5 rkww + */ +#define _par_DBRNK_VAL (0x7007) + + for (i = 0; i < 4; i++) { + data_l = (_par_DBRNK_VAL >> (i * 4)) & 0x0f; + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11) && (i == 0)) { + data_l += 1; + } + data_l2 = 0; + foreach_vch(ch) { + data_l2 = data_l2 | (data_l << (4 * ch)); + } + mmio_write_32(DBSC_DBRNK(2 + i), data_l2); + } + mmio_write_32(DBSC_DBADJ0, 0x00000000); + + /* timing registers for Scheduler */ + /* SCFCTST0 */ + /* SCFCTST0 ACT-ACT */ + tmp[3] = 1UL * js2[js2_trcpb] * 800 * ddr_mbpsdiv / ddr_mbps; + /* SCFCTST0 RDA-ACT */ + tmp[2] = + 1UL * ((16 / 2) + js2[js2_trtp] - 8 + + js2[js2_trppb]) * 800 * ddr_mbpsdiv / ddr_mbps; + /* SCFCTST0 WRA-ACT */ + tmp[1] = + 1UL * (WL + 1 + (16 / 2) + + js1[js1_ind].nwr) * 800 * ddr_mbpsdiv / ddr_mbps; + /* SCFCTST0 PRE-ACT */ + tmp[0] = 1UL * js2[js2_trppb]; + mmio_write_32(DBSC_SCFCTST0, + (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* SCFCTST1 */ + /* SCFCTST1 RD-WR */ + tmp[3] = + 1UL * (mmio_read_32(DBSC_DBTR(11)) & 0xff) * 800 * ddr_mbpsdiv / + ddr_mbps; + /* SCFCTST1 WR-RD */ + tmp[2] = + 1UL * (mmio_read_32(DBSC_DBTR(12)) & 0xff) * 800 * ddr_mbpsdiv / + ddr_mbps; + /* SCFCTST1 ACT-RD/WR */ + tmp[1] = 1UL * js2[js2_trcd] * 800 * ddr_mbpsdiv / ddr_mbps; + /* SCFCTST1 ASYNCOFS */ + tmp[0] = 12; + mmio_write_32(DBSC_SCFCTST1, + (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* DBSCHRW1 */ + /* DBSCHRW1 SCTRFCAB */ + tmp[0] = 1UL * js2[js2_trfcab] * 800 * ddr_mbpsdiv / ddr_mbps; + data_l = (((mmio_read_32(DBSC_DBTR(16)) & 0x00FF0000) >> 16) + + (mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF) + + (0x28 * 2)) * 400 * 2 * ddr_mbpsdiv / ddr_mbps + 7; + if (tmp[0] < data_l) + tmp[0] = data_l; + + if ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30)) { + mmio_write_32(DBSC_DBSCHRW1, tmp[0] + + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF) + * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) / + ddr_mbps - 3); + } else { + mmio_write_32(DBSC_DBSCHRW1, tmp[0] + + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF) + * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) / + ddr_mbps); + } + + /* QOS and CAM */ +#ifdef ddr_qos_init_setting /* only for non qos_init */ + /*wbkwait(0004), wbkmdhi(4,2),wbkmdlo(1,8) */ + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + /*0(fillunit),8(dirtymax),4(dirtymin) */ + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + /*stop_tolerance */ + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + /*rd-wr/wr-rd toggle priority */ + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHCNT0, 0x000F0037); + + /* QoS Settings */ + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00U); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00U); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000U); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000U); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300U); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0U); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200U); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100U); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000100U); + mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0U); + mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0U); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS120, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS121, 0x00000030U); + mmio_write_32(DBSC_DBSCHQOS122, 0x00000020U); + mmio_write_32(DBSC_DBSCHQOS123, 0x00000010U); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100U); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0U); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0U); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0U); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0U); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080U); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030U); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020U); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* ddr_qos_init_setting */ + /* H3 Ver.1.1 need to set monitor function */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) { + mmio_write_32(DBSC_DBMONCONF4, 0x00700000); + } + + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut == PRR_PRODUCT_10) { + /* resrdis, simple mode, sc off */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000007); + } else if (prr_cut == PRR_PRODUCT_11) { + /* resrdis, simple mode */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000005); + } else if (prr_cut < PRR_PRODUCT_30) { + /* H3 Ver.2.0 */ + /* resrdis */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + } else { /* H3 Ver.3.0(include H3N) */ + /* exprespque */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000010); + } + } else { /* M3-W/M3-N/V3H */ + /* resrdis */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + } +} + +static void dbsc_regset_post(void) +{ + uint32_t ch, cs; + uint32_t data_l; + uint32_t slice, rdlat_max, rdlat_min; + + rdlat_max = 0; + rdlat_min = 0xffff; + foreach_vch(ch) { + for (cs = 0; cs < CS_CNT; cs++) { + if ((ch_have_this_cs[cs] & (1U << ch)) != 0) { + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_INDEX, + cs); + data_l = ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_LATENCY_ADJUST); + if (data_l > rdlat_max) + rdlat_max = data_l; + if (data_l < rdlat_min) + rdlat_min = data_l; + } + } + } + } + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) { +#if RCAR_DRAM_SPLIT == 2 + if (board_cnf->phyvalid == 0x05) { + mmio_write_32(DBSC_DBTR(24), + (rdlat_max << 24) + (rdlat_min << 16) + + mmio_read_32(DBSC_DBTR(24))); + } else { + mmio_write_32(DBSC_DBTR(24), + ((rdlat_max * 2 - rdlat_min + 4) << 24) + + ((rdlat_min + 2) << 16) + + mmio_read_32(DBSC_DBTR(24))); + } +#else /*RCAR_DRAM_SPLIT == 2 */ + mmio_write_32(DBSC_DBTR(24), + ((rdlat_max * 2 - rdlat_min + 4) << 24) + + ((rdlat_min + 2) << 16) + + mmio_read_32(DBSC_DBTR(24))); +#endif /*RCAR_DRAM_SPLIT == 2 */ + } else { + mmio_write_32(DBSC_DBTR(24), + ((rdlat_max + 2) << 24) + + ((rdlat_max + 2) << 16) + + mmio_read_32(DBSC_DBTR(24))); + } + + /* set ddr density information */ + foreach_ech(ch) { + for (cs = 0; cs < CS_CNT; cs++) { + if (ddr_density[ch][cs] == 0xff) { + mmio_write_32(DBSC_DBMEMCONF(ch, cs), 0x00); + } else { + mmio_write_32(DBSC_DBMEMCONF(ch, cs), + DBMEMCONF_REGD(ddr_density[ch] + [cs])); + } + } + mmio_write_32(DBSC_DBMEMCONF(ch, 2), 0x00000000); + mmio_write_32(DBSC_DBMEMCONF(ch, 3), 0x00000000); + } + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + + /*set DBI */ + if (board_cnf->dbi_en) + mmio_write_32(DBSC_DBDBICNT, 0x00000003); + + /* H3 Ver.2.0 or later/M3-N/V3H DBI wa */ + if ((((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) && + board_cnf->dbi_en) + reg_ddrphy_write_a(0x00001010, 0x01000000); + + /*set REFCYCLE */ + data_l = (get_refperiod()) * ddr_mbps / 2000 / ddr_mbpsdiv; + mmio_write_32(DBSC_DBRFCNF1, 0x00080000 | (data_l & 0x0000ffff)); + mmio_write_32(DBSC_DBRFCNF2, 0x00010000 | DBSC_REFINTS); + +#if RCAR_REWT_TRAINING != 0 + /* Periodic-WriteDQ Training seeting */ + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut == PRR_PRODUCT_10))) { + /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */ + } else { + /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */ + mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000); + + ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04); + ddr_setval_ach_as(_reg_PHY_WDQLVL_QTR_DLY_STEP, 0x0F); + ddr_setval_ach_as(_reg_PHY_WDQLVL_DLY_STEP, 0x50); + ddr_setval_ach_as(_reg_PHY_WDQLVL_DQDM_SLV_DLY_START, 0x0300); + + ddr_setval_ach(_reg_PI_WDQLVL_CS_MAP, + ddrtbl_getval(_cnf_DDR_PI_REGSET, + _reg_PI_WDQLVL_CS_MAP)); + ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f); + ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00); + ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01); + ddr_setval_ach(_reg_PI_TREF_F0, 0x0000); + ddr_setval_ach(_reg_PI_TREF_F1, 0x0000); + ddr_setval_ach(_reg_PI_TREF_F2, 0x0000); + + if (prr_product == PRR_PRODUCT_M3) { + ddr_setval_ach(_reg_PI_WDQLVL_EN, 0x02); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_EN_F1, 0x02); + } + ddr_setval_ach(_reg_PI_WDQLVL_PERIODIC, 0x01); + + /* DFI_PHYMSTR_ACK , WTmode setting */ + /* DFI_PHYMSTR_ACK: WTmode =b'01 */ + mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011); + } +#endif /* RCAR_REWT_TRAINING */ + /* periodic dram zqcal enable */ + mmio_write_32(DBSC_DBCALCNF, 0x01000010); + + /* periodic phy ctrl update enable */ + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut < PRR_PRODUCT_30))) { + /* non : H3 Ver.1.x/M3-W Ver.1.x not support */ + } else { +#if RCAR_DRAM_SPLIT == 2 + if ((prr_product == PRR_PRODUCT_H3) && + (board_cnf->phyvalid == 0x05)) + mmio_write_32(DBSC_DBDFICUPDCNF, 0x2a240001); + else + mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001); +#else /* RCAR_DRAM_SPLIT == 2 */ + mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001); +#endif /* RCAR_DRAM_SPLIT == 2 */ + } + +#ifdef DDR_BACKUPMODE + /* SRX */ + if (ddr_backup == DRAM_BOOT_STATUS_WARM) { +#ifdef DDR_BACKUPMODE_HALF /* for Half channel(ch0, 1 only) */ + NOTICE("BL2: [DEBUG_MESS] DDR_BACKUPMODE_HALF\n"); + send_dbcmd(0x0A040001); + if (Prr_Product == PRR_PRODUCT_H3) + send_dbcmd(0x0A140001); +#else /* DDR_BACKUPMODE_HALF */ /* for All channels */ + send_dbcmd(0x0A840001); +#endif /* DDR_BACKUPMODE_HALF */ + } +#endif /* DDR_BACKUPMODE */ + + /* set Auto Refresh */ + mmio_write_32(DBSC_DBRFEN, 0x00000001); + +#if RCAR_REWT_TRAINING != 0 + /* Periodic WriteDQ Traning */ + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut == PRR_PRODUCT_10))) { + /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */ + } else { + /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */ + ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100); + } +#endif /* RCAR_REWT_TRAINING */ + + /* dram access enable */ + mmio_write_32(DBSC_DBACEN, 0x00000001); + + MSG_LF(__func__ "(done)"); +} + +/* DFI_INIT_START */ +static uint32_t dfi_init_start(void) +{ + uint32_t ch; + uint32_t phytrainingok; + uint32_t retry; + uint32_t data_l; + const uint32_t RETRY_MAX = 0x10000; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + /* PLL3 Disable */ + /* protect register interface */ + ddrphy_regif_idle(); + + pll3_control(0); + + /* init start */ + /* dbdficnt0: + * dfi_dram_clk_disable=1 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =0 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10); + dsb_sev(); + + /* dbdficnt0: + * dfi_dram_clk_disable=1 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =1 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11); + dsb_sev(); + + } else { + ddr_setval_ach_as(_reg_PHY_DLL_RST_EN, 0x02); + dsb_sev(); + ddrphy_regif_idle(); + } + + /* dll_rst negate */ + foreach_vch(ch) + mmio_write_32(DBSC_DBPDCNT3(ch), 0x0000CF01); + dsb_sev(); + + /* wait init_complete */ + phytrainingok = 0; + retry = 0; + while (retry++ < RETRY_MAX) { + foreach_vch(ch) { + data_l = mmio_read_32(DBSC_DBDFISTAT(ch)); + if (data_l & 0x00000001) + phytrainingok |= (1U << ch); + } + dsb_sev(); + if (phytrainingok == ddr_phyvalid) + break; + if (retry % 256 == 0) + ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01); + } + + /* all ch ok? */ + if ((phytrainingok & ddr_phyvalid) != ddr_phyvalid) + return 0xff; + + /* dbdficnt0: + * dfi_dram_clk_disable=0 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =0 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000010); + dsb_sev(); + + return 0; +} + +/* drivablity setting : CMOS MODE ON/OFF */ +static void change_lpddr4_en(uint32_t mode) +{ + uint32_t ch; + uint32_t i; + uint32_t data_l; + const uint32_t _reg_PHY_PAD_DRIVE_X[3] = { + _reg_PHY_PAD_ADDR_DRIVE, + _reg_PHY_PAD_CLK_DRIVE, + _reg_PHY_PAD_CS_DRIVE + }; + + foreach_vch(ch) { + for (i = 0; i < 3; i++) { + data_l = ddr_getval(ch, _reg_PHY_PAD_DRIVE_X[i]); + if (mode) { + data_l |= (1U << 14); + } else { + data_l &= ~(1U << 14); + } + ddr_setval(ch, _reg_PHY_PAD_DRIVE_X[i], data_l); + } + } +} + +/* drivablity setting */ +static uint32_t set_term_code(void) +{ + int32_t i; + uint32_t ch, index; + uint32_t data_l; + uint32_t chip_id[2]; + uint32_t term_code; + uint32_t override; + uint32_t pvtr; + uint32_t pvtp; + uint32_t pvtn; + + term_code = ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PAD_DATA_TERM); + override = 0; + for (i = 0; i < 2; i++) + chip_id[i] = mmio_read_32(LIFEC_CHIPID(i)); + + index = 0; + while (1) { + if (termcode_by_sample[index][0] == 0xffffffff) { + break; + } + if ((termcode_by_sample[index][0] == chip_id[0]) && + (termcode_by_sample[index][1] == chip_id[1])) { + term_code = termcode_by_sample[index][2]; + override = 1; + break; + } + index++; + } + + if (override) { + for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; index++) { + data_l = + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PAD_TERM_X[index]); + data_l = (data_l & 0xfffe0000) | term_code; + ddr_setval_ach(_reg_PHY_PAD_TERM_X[index], data_l); + } + } else if ((prr_product == PRR_PRODUCT_M3) && + (prr_cut == PRR_PRODUCT_10)) { + /* non */ + } else { + ddr_setval_ach(_reg_PHY_PAD_TERM_X[0], + (ddrtbl_getval + (_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PAD_TERM_X[0]) & 0xFFFE0000)); + ddr_setval_ach(_reg_PHY_CAL_CLEAR_0, 0x01); + ddr_setval_ach(_reg_PHY_CAL_START_0, 0x01); + foreach_vch(ch) { + do { + data_l = + ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0); + } while (!(data_l & 0x00800000)); + } + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + foreach_vch(ch) { + data_l = ddr_getval(ch, _reg_PHY_PAD_TERM_X[0]); + pvtr = (data_l >> 12) & 0x1f; + pvtr += 8; + if (pvtr > 0x1f) + pvtr = 0x1f; + data_l = + ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0); + pvtn = (data_l >> 6) & 0x03f; + pvtp = (data_l >> 0) & 0x03f; + + for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; + index++) { + data_l = + ddrtbl_getval + (_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PAD_TERM_X[index]); + data_l = (data_l & 0xfffe0000) + | (pvtr << 12) + | (pvtn << 6) + | (pvtp); + ddr_setval(ch, + _reg_PHY_PAD_TERM_X[index], + data_l); + } + } + } else { + /* M3-W Ver.1.1 or later/H3 Ver.2.0 or later/M3-N/V3H */ + foreach_vch(ch) { + for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; + index++) { + data_l = + ddr_getval(ch, + _reg_PHY_PAD_TERM_X + [index]); + ddr_setval(ch, + _reg_PHY_PAD_TERM_X[index], + (data_l & 0xFFFE0FFF) | + 0x00015000); + } + } + } + } + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + /* non */ + } else { + ddr_padcal_tcompensate_getinit(override); + } + + return 0; +} + +/* DDR mode register setting */ +static void ddr_register_set(void) +{ + int32_t fspwp; + uint32_t tmp; + + for (fspwp = 1; fspwp >= 0; fspwp--) { + /*MR13, fspwp */ + send_dbcmd(0x0e840d08 | ((2 - fspwp) << 6)); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr1_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840100 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr2_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840200 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr3_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840300 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr11_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840b00 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr12_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840c00 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr14_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840e00 | tmp); + /* MR22 */ + send_dbcmd(0x0e841616); + + /* ZQCAL start */ + send_dbcmd(0x0d84004F); + + /* ZQLAT */ + send_dbcmd(0x0d840051); + } + + /* MR13, fspwp */ + send_dbcmd(0x0e840d08); +} + +/* Training handshake functions */ +static inline uint32_t wait_freqchgreq(uint32_t assert) +{ + uint32_t data_l; + uint32_t count; + uint32_t ch; + + count = 100000; + + /* H3 Ver.1.x cannot see frqchg_req */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + return 0; + } + + if (assert) { + do { + data_l = 1; + foreach_vch(ch) { + data_l &= mmio_read_32(DBSC_DBPDSTAT(ch)); + } + count = count - 1; + } while (((data_l & 0x01) != 0x01) & (count != 0)); + } else { + do { + data_l = 0; + foreach_vch(ch) { + data_l |= mmio_read_32(DBSC_DBPDSTAT(ch)); + } + count = count - 1; + } while (((data_l & 0x01) != 0x00) & (count != 0)); + } + + return (count == 0); +} + +static inline void set_freqchgack(uint32_t assert) +{ + uint32_t ch; + uint32_t data_l; + + if (assert) + data_l = 0x0CF20000; + else + data_l = 0x00000000; + + foreach_vch(ch) + mmio_write_32(DBSC_DBPDCNT2(ch), data_l); +} + +static inline void set_dfifrequency(uint32_t freq) +{ + uint32_t ch; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + foreach_vch(ch) + mmio_clrsetbits_32(DBSC_DBPDCNT1(ch), 0x1fU, freq); + } else { + foreach_vch(ch) { + mmio_clrsetbits_32(DBSC_DBDFICNT(ch), 0x1fU << 24, + (freq << 24)); + } + } + dsb_sev(); +} + +static uint32_t pll3_freq(uint32_t on) +{ + uint32_t timeout; + + timeout = wait_freqchgreq(1); + + if (timeout) { + return 1; + } + + pll3_control(on); + set_dfifrequency(on); + + set_freqchgack(1); + timeout = wait_freqchgreq(0); + set_freqchgack(0); + + if (timeout) { + FATAL_MSG("BL2: Time out[2]\n"); + return 1; + } + return 0; +} + +/* update dly */ +static void update_dly(void) +{ + ddr_setval_ach(_reg_SC_PHY_MANUAL_UPDATE, 0x01); + ddr_setval_ach(_reg_PHY_ADRCTL_MANUAL_UPDATE, 0x01); +} + +/* training by pi */ +static uint32_t pi_training_go(void) +{ + uint32_t flag; + uint32_t data_l; + uint32_t retry; + const uint32_t RETRY_MAX = 4096 * 16; + uint32_t ch; + + uint32_t mst_ch; + uint32_t cur_frq; + uint32_t complete; + uint32_t frqchg_req; + + /* pi_start */ + ddr_setval_ach(_reg_PI_START, 0x01); + foreach_vch(ch) + ddr_getval(ch, _reg_PI_INT_STATUS); + + /* set dfi_phymstr_ack = 1 */ + mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000001); + dsb_sev(); + + /* wait pi_int_status[0] */ + mst_ch = 0; + flag = 0; + complete = 0; + cur_frq = 0; + retry = RETRY_MAX; + do { + frqchg_req = mmio_read_32(DBSC_DBPDSTAT(mst_ch)) & 0x01; + + /* H3 Ver.1.x cannot see frqchg_req */ + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + if ((retry % 4096) == 1) { + frqchg_req = 1; + } else { + frqchg_req = 0; + } + } + + if (frqchg_req) { + if (cur_frq) { + /* Low frequency */ + flag = pll3_freq(0); + cur_frq = 0; + } else { + /* High frequency */ + flag = pll3_freq(1); + cur_frq = 1; + } + if (flag) + break; + } else { + if (cur_frq) { + foreach_vch(ch) { + if (complete & (1U << ch)) + continue; + data_l = + ddr_getval(ch, _reg_PI_INT_STATUS); + if (data_l & 0x01) { + complete |= (1U << ch); + } + } + if (complete == ddr_phyvalid) + break; + } + } + } while (--retry); + foreach_vch(ch) { + /* dummy read */ + data_l = ddr_getval_s(ch, 0, _reg_PHY_CAL_RESULT2_OBS_0); + data_l = ddr_getval(ch, _reg_PI_INT_STATUS); + ddr_setval(ch, _reg_PI_INT_ACK, data_l); + } + if (ddrphy_regif_chk()) { + return 0xfd; + } + return complete; +} + +/* Initialize DDR */ +static uint32_t init_ddr(void) +{ + int32_t i; + uint32_t data_l; + uint32_t phytrainingok; + uint32_t ch, slice; + uint32_t err; + int16_t adj; + + MSG_LF(__func__ ":0\n"); + +#ifdef DDR_BACKUPMODE + rcar_dram_get_boot_status(&ddr_backup); +#endif + + /* unlock phy */ + /* Unlock DDRPHY register(AGAIN) */ + foreach_vch(ch) + mmio_write_32(DBSC_DBPDLK(ch), 0x0000A55A); + dsb_sev(); + + if ((((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) && board_cnf->dbi_en) + reg_ddrphy_write_a(0x00001010, 0x01000001); + else + reg_ddrphy_write_a(0x00001010, 0x00000001); + /* DBSC register pre-setting */ + dbsc_regset_pre(); + + /* load ddrphy registers */ + + ddrtbl_load(); + + /* configure ddrphy registers */ + ddr_config(); + + /* dfi_reset assert */ + foreach_vch(ch) + mmio_write_32(DBSC_DBPDCNT0(ch), 0x01); + dsb_sev(); + + /* dbsc register set */ + dbsc_regset(); + MSG_LF(__func__ ":1\n"); + + /* dfi_reset negate */ + foreach_vch(ch) + mmio_write_32(DBSC_DBPDCNT0(ch), 0x00); + dsb_sev(); + + /* dfi_init_start (start ddrphy) */ + err = dfi_init_start(); + if (err) { + return INITDRAM_ERR_I; + } + MSG_LF(__func__ ":2\n"); + + /* ddr backupmode end */ +#ifdef DDR_BACKUPMODE + if (ddr_backup) { + NOTICE("BL2: [WARM_BOOT]\n"); + } else { + NOTICE("BL2: [COLD_BOOT]\n"); + } + err = rcar_dram_update_boot_status(ddr_backup); + if (err) { + NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n"); + return INITDRAM_ERR_I; + } +#endif + MSG_LF(__func__ ":3\n"); + + /* override term code after dfi_init_complete */ + err = set_term_code(); + if (err) { + return INITDRAM_ERR_I; + } + MSG_LF(__func__ ":4\n"); + + /* rx offset calibration */ + if ((prr_cut > PRR_PRODUCT_11) || (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + err = rx_offset_cal_hw(); + } else { + err = rx_offset_cal(); + } + if (err) + return INITDRAM_ERR_O; + MSG_LF(__func__ ":5\n"); + + /* Dummy PDE */ + send_dbcmd(0x08840000); + + /* PDX */ + send_dbcmd(0x08840001); + + /* check register i/f is alive */ + err = ddrphy_regif_chk(); + if (err) { + return INITDRAM_ERR_O; + } + MSG_LF(__func__ ":6\n"); + + /* phy initialize end */ + + /* setup DDR mode registers */ + /* CMOS MODE */ + change_lpddr4_en(0); + + /* MRS */ + ddr_register_set(); + + /* Thermal sensor setting */ + /* THCTR Bit6: PONM=0 , Bit0: THSST=1 */ + data_l = (mmio_read_32(THS1_THCTR) & 0xFFFFFFBF) | 0x00000001; + mmio_write_32(THS1_THCTR, data_l); + + /* LPDDR4 MODE */ + change_lpddr4_en(1); + + MSG_LF(__func__ ":7\n"); + + /* mask CS_MAP if RANKx is not found */ + foreach_vch(ch) { + data_l = ddr_getval(ch, _reg_PI_CS_MAP); + if (!(ch_have_this_cs[1] & (1U << ch))) + data_l = data_l & 0x05; + ddr_setval(ch, _reg_PI_CS_MAP, data_l); + } + + /* exec pi_training */ + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN), + BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN))); + ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x00); + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_EN, 0x01); + } else { + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_EN, + ((ch_have_this_cs[1]) >> ch) + & 0x01); + } + } + } + + phytrainingok = pi_training_go(); + + if (ddr_phyvalid != (phytrainingok & ddr_phyvalid)) { + return INITDRAM_ERR_T | phytrainingok; + } + + MSG_LF(__func__ ":8\n"); + + /* CACS DLY ADJUST */ + data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj); + foreach_vch(ch) { + for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) { + adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]); + ddr_setval(ch, _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i], + data_l + adj); + } + + if (ddr_phycaslice == 1) { + for (i = 0; i < 6; i++) { + adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj + [i + + _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]); + ddr_setval_s(ch, 2, + _reg_PHY_CLK_CACS_SLAVE_DELAY_X + [i], + data_l + adj + ); + } + } + } + + update_dly(); + MSG_LF(__func__ ":9\n"); + + /* H3 fix rd latency to avoid bug in elasitic buffer */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) + adjust_rddqs_latency(); + + /* Adjust Write path latency */ + if (ddrtbl_getval + (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD)) + adjust_wpath_latency(); + + /* RDQLVL Training */ + if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE)) + ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x01); + + err = rdqdm_man(); + + if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE)) + ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x00); + + if (err) { + return INITDRAM_ERR_T; + } + update_dly(); + MSG_LF(__func__ ":10\n"); + + /* WDQLVL Training */ + err = wdqdm_man(); + if (err) { + return INITDRAM_ERR_T; + } + update_dly(); + MSG_LF(__func__ ":11\n"); + + /* training complete, setup DBSC */ + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach_as(_reg_PHY_DFI40_POLARITY, 0x00); + ddr_setval_ach(_reg_PI_DFI40_POLARITY, 0x00); + } + + dbsc_regset_post(); + MSG_LF(__func__ ":12\n"); + + return phytrainingok; +} + +/* SW LEVELING COMMON */ +static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick) +{ + uint32_t ch; + uint32_t data_l; + uint32_t retry; + uint32_t waiting; + uint32_t err; + + const uint32_t RETRY_MAX = 0x1000; + + err = 0; + /* set EXIT -> OP_DONE is cleared */ + ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01); + + /* kick */ + foreach_vch(ch) { + if (ch_have_this_cs[ddr_csn % 2] & (1U << ch)) { + ddr_setval(ch, reg_cs, ddr_csn); + ddr_setval(ch, reg_kick, 0x01); + } + } + foreach_vch(ch) { + /*PREPARE ADDR REGISTER (for SWLVL_OP_DONE) */ + ddr_getval(ch, _reg_PI_SWLVL_OP_DONE); + } + waiting = ch_have_this_cs[ddr_csn % 2]; + dsb_sev(); + retry = RETRY_MAX; + do { + foreach_vch(ch) { + if (!(waiting & (1U << ch))) + continue; + data_l = ddr_getval(ch, _reg_PI_SWLVL_OP_DONE); + if (data_l & 0x01) + waiting &= ~(1U << ch); + } + retry--; + } while (waiting && (retry > 0)); + if (retry == 0) { + err = 1; + } + + dsb_sev(); + /* set EXIT -> OP_DONE is cleared */ + ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01); + dsb_sev(); + + return err; +} + +/* WDQ TRAINING */ +#ifndef DDR_FAST_INIT +static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn) +{ + int32_t i, k; + uint32_t cs, slice; + uint32_t data_l; + + /* clr of training results buffer */ + cs = ddr_csn % 2; + data_l = board_cnf->dqdm_dly_w; + for (slice = 0; slice < SLICE_CNT; slice++) { + k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2))) + continue; + + for (i = 0; i <= 8; i++) { + if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) + wdqdm_dly[ch][cs][slice][i] = + wdqdm_dly[ch][CS_CNT - 1 - cs][slice][i]; + else + wdqdm_dly[ch][cs][slice][i] = data_l; + wdqdm_le[ch][cs][slice][i] = 0; + wdqdm_te[ch][cs][slice][i] = 0; + } + wdqdm_st[ch][cs][slice] = 0; + wdqdm_win[ch][cs][slice] = 0; + } +} + +static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn) +{ + int32_t i, k; + uint32_t cs, slice; + uint32_t data_l; + uint32_t err; + const uint32_t _par_WDQLVL_RETRY_THRES = 0x7c0; + + int32_t min_win; + int32_t win; + int8_t _adj; + int16_t adj; + uint32_t dq; + + /* analysis of training results */ + err = 0; + for (slice = 0; slice < SLICE_CNT; slice += 1) { + k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2))) + continue; + + cs = ddr_csn % 2; + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs); + for (i = 0; i < 9; i++) { + dq = slice * 8 + i; + if (i == 8) + _adj = board_cnf->ch[ch].dm_adj_w[slice]; + else + _adj = board_cnf->ch[ch].dq_adj_w[dq]; + adj = _f_scale_adj(_adj); + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_CLK_WRX_SLAVE_DELAY[i]) + adj; + ddr_setval_s(ch, slice, _reg_PHY_CLK_WRX_SLAVE_DELAY[i], + data_l); + wdqdm_dly[ch][cs][slice][i] = data_l; + } + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, 0x00); + data_l = ddr_getval_s(ch, slice, _reg_PHY_WDQLVL_STATUS_OBS); + wdqdm_st[ch][cs][slice] = data_l; + min_win = INT_LEAST32_MAX; + for (i = 0; i <= 8; i++) { + ddr_setval_s(ch, slice, _reg_PHY_WDQLVL_DQDM_OBS_SELECT, + i); + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_WDQLVL_DQDM_TE_DLY_OBS); + wdqdm_te[ch][cs][slice][i] = data_l; + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS); + wdqdm_le[ch][cs][slice][i] = data_l; + win = + (int32_t)wdqdm_te[ch][cs][slice][i] - + wdqdm_le[ch][cs][slice][i]; + if (min_win > win) + min_win = win; + if (data_l >= _par_WDQLVL_RETRY_THRES) + err = 2; + } + wdqdm_win[ch][cs][slice] = min_win; + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, + 0x01); + } else { + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, + ((ch_have_this_cs[1]) >> ch) & 0x01); + } + } + return err; +} +#endif/* DDR_FAST_INIT */ + +static void wdqdm_cp(uint32_t ddr_csn, uint32_t restore) +{ + uint32_t i; + uint32_t ch, slice; + uint32_t tgt_cs, src_cs; + uint32_t tmp_r; + + /* copy of training results */ + foreach_vch(ch) { + for (tgt_cs = 0; tgt_cs < CS_CNT; tgt_cs++) { + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_INDEX, + tgt_cs); + src_cs = ddr_csn % 2; + if (!(ch_have_this_cs[1] & (1U << ch))) + src_cs = 0; + for (i = 0; i <= 4; i += 4) { + if (restore) + tmp_r = + rdqdm_dly[ch][tgt_cs][slice] + [i]; + else + tmp_r = + rdqdm_dly[ch][src_cs][slice] + [i]; + + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY + [i], tmp_r); + } + } + } + } +} + +static uint32_t wdqdm_man1(void) +{ + int32_t k; + uint32_t ch, cs, slice; + uint32_t ddr_csn; + uint32_t data_l; + uint32_t err; + uint32_t high_dq[DRAM_CH_CNT]; + uint32_t mr14_csab0_bak[DRAM_CH_CNT]; +#ifndef DDR_FAST_INIT + uint32_t err_flg; +#endif/* DDR_FAST_INIT */ + + /* manual execution of training */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + foreach_vch(ch) { + high_dq[ch] = 0; + for (slice = 0; slice < SLICE_CNT; slice++) { + k = (board_cnf->ch[ch].dqs_swap >> + (4 * slice)) & 0x0f; + if (k >= 2) + high_dq[ch] |= (1U << slice); + } + ddr_setval(ch, _reg_PI_16BIT_DRAM_CONNECT, 0x00); + } + } + err = 0; + /* CLEAR PREV RESULT */ + for (cs = 0; cs < CS_CNT; cs++) { + ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_INDEX, cs); + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach_as(_reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS, + 0x01); + } else { + ddr_setval_ach_as(_reg_PHY_WDQLVL_CLR_PREV_RESULTS, + 0x01); + } + } + ddrphy_regif_idle(); + +#ifndef DDR_FAST_INIT + err_flg = 0; +#endif/* DDR_FAST_INIT */ + for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) { + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + foreach_vch(ch) { + data_l = mmio_read_32(DBSC_DBDFICNT(ch)); + data_l &= ~(0x00ffU << 16); + + if (ddr_csn >= 2) + k = (high_dq[ch] ^ 0x0f); + else + k = high_dq[ch]; + data_l |= (k << 16); + mmio_write_32(DBSC_DBDFICNT(ch), data_l); + ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, k); + } + } + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut == PRR_PRODUCT_10))) { + wdqdm_cp(ddr_csn, 0); + } + + foreach_vch(ch) { + data_l = + ddr_getval(ch, + reg_pi_mr14_data_fx_csx[1][ddr_csn]); + ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], data_l); + } + + /* KICK WDQLVL */ + err = swlvl1(ddr_csn, _reg_PI_WDQLVL_CS, _reg_PI_WDQLVL_REQ); + if (err) + goto err_exit; + + if (ddr_csn == 0) + foreach_vch(ch) { + mr14_csab0_bak[ch] = + ddr_getval(ch, reg_pi_mr14_data_fx_csx[1][0]); + } else + foreach_vch(ch) { + ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], + mr14_csab0_bak[ch]); + } +#ifndef DDR_FAST_INIT + foreach_vch(ch) { + if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) { + wdqdm_clr1(ch, ddr_csn); + continue; + } + err = wdqdm_ana1(ch, ddr_csn); + if (err) + err_flg |= (1U << (ddr_csn * 4 + ch)); + ddrphy_regif_idle(); + } +#endif/* DDR_FAST_INIT */ + } +err_exit: +#ifndef DDR_FAST_INIT + err |= err_flg; +#endif/* DDR_FAST_INIT */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + ddr_setval_ach(_reg_PI_16BIT_DRAM_CONNECT, 0x01); + foreach_vch(ch) { + data_l = mmio_read_32(DBSC_DBDFICNT(ch)); + data_l &= ~(0x00ffU << 16); + mmio_write_32(DBSC_DBDFICNT(ch), data_l); + ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, 0x00); + } + } + return err; +} + +static uint32_t wdqdm_man(void) +{ + uint32_t err, retry_cnt; + const uint32_t retry_max = 0x10; + uint32_t datal, ch, ddr_csn, mr14_bkup[4][4]; + + datal = RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2 + 19; + if ((mmio_read_32(DBSC_DBTR(11)) & 0xFF) > datal) + datal = mmio_read_32(DBSC_DBTR(11)) & 0xFF; + ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW, datal); + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F0, + (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10); + ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F1, + (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10); + } else { + ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR, + (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10); + } + ddr_setval_ach(_reg_PI_TRFC_F0, mmio_read_32(DBSC_DBTR(13)) & 0x1FF); + ddr_setval_ach(_reg_PI_TRFC_F1, mmio_read_32(DBSC_DBTR(13)) & 0x1FF); + + retry_cnt = 0; + err = 0; + do { + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + err = wdqdm_man1(); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x01); + ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE, + 0x01); + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1, + 0x0C); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x0C); + } + dsb_sev(); + err = wdqdm_man1(); + foreach_vch(ch) { + for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) { + mr14_bkup[ch][ddr_csn] = + ddr_getval(ch, + reg_pi_mr14_data_fx_csx + [1][ddr_csn]); + dsb_sev(); + } + } + + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1, + 0x04); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x04); + } + pvtcode_update(); + err = wdqdm_man1(); + foreach_vch(ch) { + for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) { + mr14_bkup[ch][ddr_csn] = + (mr14_bkup[ch][ddr_csn] + + ddr_getval(ch, + reg_pi_mr14_data_fx_csx + [1][ddr_csn])) / 2; + ddr_setval(ch, + reg_pi_mr14_data_fx_csx[1] + [ddr_csn], + mr14_bkup[ch][ddr_csn]); + } + } + + ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE, + 0x00); + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1, + 0x00); + ddr_setval_ach + (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1, + 0x00); + ddr_setval_ach + (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1, + 0x00); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x00); + ddr_setval_ach + (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT, + 0x00); + ddr_setval_ach + (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT, + 0x00); + } + ddr_setval_ach(_reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE, + 0x00); + + pvtcode_update2(); + err = wdqdm_man1(); + ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00); + } + } while (err && (++retry_cnt < retry_max)); + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && (prr_cut <= PRR_PRODUCT_10))) { + wdqdm_cp(0, 1); + } + + return (retry_cnt >= retry_max); +} + +/* RDQ TRAINING */ +#ifndef DDR_FAST_INIT +static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn) +{ + int32_t i, k; + uint32_t cs, slice; + uint32_t data_l; + + /* clr of training results buffer */ + cs = ddr_csn % 2; + data_l = board_cnf->dqdm_dly_r; + for (slice = 0; slice < SLICE_CNT; slice++) { + k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2))) + continue; + + for (i = 0; i <= 8; i++) { + if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) { + rdqdm_dly[ch][cs][slice][i] = + rdqdm_dly[ch][CS_CNT - 1 - cs][slice][i]; + rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = + rdqdm_dly[ch][CS_CNT - 1 - cs][slice + + SLICE_CNT] + [i]; + } else { + rdqdm_dly[ch][cs][slice][i] = data_l; + rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = + data_l; + } + rdqdm_le[ch][cs][slice][i] = 0; + rdqdm_le[ch][cs][slice + SLICE_CNT][i] = 0; + rdqdm_te[ch][cs][slice][i] = 0; + rdqdm_te[ch][cs][slice + SLICE_CNT][i] = 0; + rdqdm_nw[ch][cs][slice][i] = 0; + rdqdm_nw[ch][cs][slice + SLICE_CNT][i] = 0; + } + rdqdm_st[ch][cs][slice] = 0; + rdqdm_win[ch][cs][slice] = 0; + } +} + +static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn) +{ + int32_t i, k; + uint32_t cs, slice; + uint32_t data_l; + uint32_t err; + int8_t _adj; + int16_t adj; + uint32_t dq; + int32_t min_win; + int32_t win; + uint32_t rdq_status_obs_select; + + /* analysis of training results */ + err = 0; + for (slice = 0; slice < SLICE_CNT; slice++) { + k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2))) + continue; + + cs = ddr_csn % 2; + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs); + ddrphy_regif_idle(); + + ddr_getval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX); + ddrphy_regif_idle(); + + for (i = 0; i <= 8; i++) { + dq = slice * 8 + i; + if (i == 8) + _adj = board_cnf->ch[ch].dm_adj_r[slice]; + else + _adj = board_cnf->ch[ch].dq_adj_r[dq]; + + adj = _f_scale_adj(_adj); + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + + adj; + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], + data_l); + rdqdm_dly[ch][cs][slice][i] = data_l; + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + + adj; + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], + data_l); + rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = data_l; + } + min_win = INT_LEAST32_MAX; + for (i = 0; i <= 8; i++) { + data_l = + ddr_getval_s(ch, slice, _reg_PHY_RDLVL_STATUS_OBS); + rdqdm_st[ch][cs][slice] = data_l; + rdqdm_st[ch][cs][slice + SLICE_CNT] = data_l; + /* k : rise/fall */ + for (k = 0; k < 2; k++) { + if (i == 8) { + rdq_status_obs_select = 16 + 8 * k; + } else { + rdq_status_obs_select = i + k * 8; + } + ddr_setval_s(ch, slice, + _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT, + rdq_status_obs_select); + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS); + rdqdm_le[ch][cs][slice + SLICE_CNT * k][i] = + data_l; + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS); + rdqdm_te[ch][cs][slice + SLICE_CNT * k][i] = + data_l; + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS); + rdqdm_nw[ch][cs][slice + SLICE_CNT * k][i] = + data_l; + + win = + (int32_t)rdqdm_te[ch][cs][slice + + SLICE_CNT * + k][i] - + rdqdm_le[ch][cs][slice + SLICE_CNT * k][i]; + if (i != 8) { + if (min_win > win) + min_win = win; + } + } + } + rdqdm_win[ch][cs][slice] = min_win; + if (min_win <= 0) { + err = 2; + } + } + return err; +} +#endif/* DDR_FAST_INIT */ + +static uint32_t rdqdm_man1(void) +{ + uint32_t ch; + uint32_t ddr_csn; +#ifdef DDR_FAST_INIT + uint32_t slice; + uint32_t i, adj, data_l; +#endif/* DDR_FAST_INIT */ + uint32_t err; + + /* manual execution of training */ + err = 0; + + for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) { + /* KICK RDQLVL */ + err = swlvl1(ddr_csn, _reg_PI_RDLVL_CS, _reg_PI_RDLVL_REQ); + if (err) + goto err_exit; +#ifndef DDR_FAST_INIT + foreach_vch(ch) { + if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) { + rdqdm_clr1(ch, ddr_csn); + ddrphy_regif_idle(); + continue; + } + err = rdqdm_ana1(ch, ddr_csn); + ddrphy_regif_idle(); + if (err) + goto err_exit; + } +#else/* DDR_FAST_INIT */ + foreach_vch(ch) { + if (ch_have_this_cs[ddr_csn] & (1U << ch)) { + for (slice = 0; slice < SLICE_CNT; slice++) { + if (ddr_getval_s(ch, slice, + _reg_PHY_RDLVL_STATUS_OBS) != + 0x0D00FFFF) { + err = (1U << ch) | + (0x10U << slice); + goto err_exit; + } + } + } + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut <= PRR_PRODUCT_10))) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (i = 0; i <= 8; i++) { + if (i == 8) + adj = _f_scale_adj(board_cnf->ch[ch].dm_adj_r[slice]); + else + adj = _f_scale_adj(board_cnf->ch[ch].dq_adj_r[slice * 8 + i]); + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, ddr_csn); + data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + adj; + ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], data_l); + rdqdm_dly[ch][ddr_csn][slice][i] = data_l; + rdqdm_dly[ch][ddr_csn | 1][slice][i] = data_l; + + data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + adj; + ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], data_l); + rdqdm_dly[ch][ddr_csn][slice + SLICE_CNT][i] = data_l; + rdqdm_dly[ch][ddr_csn | 1][slice + SLICE_CNT][i] = data_l; + } + } + } + } + ddrphy_regif_idle(); + +#endif/* DDR_FAST_INIT */ + } + +err_exit: + return err; +} + +static uint32_t rdqdm_man(void) +{ + uint32_t err, retry_cnt; + const uint32_t retry_max = 0x01; + + ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE, + 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQ_TSEL_ENABLE)); + ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE, + 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQS_TSEL_ENABLE)); + ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT, + 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQ_TSEL_SELECT)); + ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT, + 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQS_TSEL_SELECT)); + + retry_cnt = 0; + do { + err = rdqdm_man1(); + ddrphy_regif_idle(); + } while (err && (++retry_cnt < retry_max)); + ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE, + ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQ_TSEL_ENABLE)); + ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE, + ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQS_TSEL_ENABLE)); + ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT, + ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQ_TSEL_SELECT)); + ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT, + ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQS_TSEL_SELECT)); + + return (retry_cnt >= retry_max); +} + +/* rx offset calibration */ +static int32_t _find_change(uint64_t val, uint32_t dir) +{ + int32_t i; + uint32_t startval; + uint32_t curval; + const int32_t VAL_END = 0x3f; + + if (dir == 0) { + startval = (val & 0x01); + for (i = 1; i <= VAL_END; i++) { + curval = (val >> i) & 0x01; + if (curval != startval) + return i; + } + return VAL_END; + } + + startval = (val >> dir) & 0x01; + for (i = dir - 1; i >= 0; i--) { + curval = (val >> i) & 0x01; + if (curval != startval) + return i; + } + return 0; +} + +static uint32_t _rx_offset_cal_updn(uint32_t code) +{ + const uint32_t CODE_MAX = 0x40; + uint32_t tmp; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + if (code == 0) + tmp = (1U << 6) | (CODE_MAX - 1); + else if (code <= 0x20) + tmp = + ((CODE_MAX - 1 - + (0x20 - code) * 2) << 6) | (CODE_MAX - 1); + else + tmp = + ((CODE_MAX - 1) << 6) | (CODE_MAX - 1 - + (code - 0x20) * 2); + } else { + if (code == 0) + tmp = (1U << 6) | (CODE_MAX - 1); + else + tmp = (code << 6) | (CODE_MAX - code); + } + return tmp; +} + +static uint32_t rx_offset_cal(void) +{ + uint32_t index; + uint32_t code; + const uint32_t CODE_MAX = 0x40; + const uint32_t CODE_STEP = 2; + uint32_t ch, slice; + uint32_t tmp; + uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT]; + uint64_t val[DRAM_CH_CNT][SLICE_CNT][_reg_PHY_RX_CAL_X_NUM]; + uint64_t tmpval; + int32_t lsb, msb; + + ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x01); + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) + val[ch][slice][index] = 0; + } + } + + for (code = 0; code < CODE_MAX / CODE_STEP; code++) { + tmp = _rx_offset_cal_updn(code * CODE_STEP); + for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) { + ddr_setval_ach_as(_reg_PHY_RX_CAL_X[index], tmp); + } + dsb_sev(); + ddr_getval_ach_as(_reg_PHY_RX_CAL_OBS, (uint32_t *)tmp_ach_as); + + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = tmp_ach_as[ch][slice]; + for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; + index++) { + if (tmp & (1U << index)) { + val[ch][slice][index] |= + (1ULL << code); + } else { + val[ch][slice][index] &= + ~(1ULL << code); + } + } + } + } + } + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; + index++) { + tmpval = val[ch][slice][index]; + lsb = _find_change(tmpval, 0); + msb = + _find_change(tmpval, + (CODE_MAX / CODE_STEP) - 1); + tmp = (lsb + msb) >> 1; + + tmp = _rx_offset_cal_updn(tmp * CODE_STEP); + ddr_setval_s(ch, slice, + _reg_PHY_RX_CAL_X[index], tmp); + } + } + } + ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00); + + return 0; +} + +static uint32_t rx_offset_cal_hw(void) +{ + uint32_t ch, slice; + uint32_t retry; + uint32_t complete; + uint32_t tmp; + uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT]; + + ddr_setval_ach_as(_reg_PHY_RX_CAL_X[9], 0x00); + ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00); + ddr_setval_ach_as(_reg_PHY_RX_CAL_SAMPLE_WAIT, 0x0f); + + retry = 0; + while (retry < 4096) { + if ((retry & 0xff) == 0) { + ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01); + } + foreach_vch(ch) + for (slice = 0; slice < SLICE_CNT; slice++) + tmp_ach_as[ch][slice] = + ddr_getval_s(ch, slice, _reg_PHY_RX_CAL_X[9]); + + complete = 1; + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = tmp_ach_as[ch][slice]; + tmp = (tmp & 0x3f) + ((tmp >> 6) & 0x3f); + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + if (tmp != 0x3E) + complete = 0; + } else { + if (tmp != 0x40) + complete = 0; + } + } + } + if (complete) + break; + + retry++; + } + + return (complete == 0); +} + +/* adjust rddqs latency */ +static void adjust_rddqs_latency(void) +{ + uint32_t ch, slice; + uint32_t dly; + uint32_t maxlatx2; + uint32_t tmp; + uint32_t rdlat_adjx2[SLICE_CNT]; + + foreach_vch(ch) { + maxlatx2 = 0; + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, + 0x00); + + dly = + ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_GATE_SLAVE_DELAY); + tmp = + ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_LATENCY_ADJUST); + /* note gate_slave_delay[9] is always 0 */ + tmp = (tmp << 1) + (dly >> 8); + rdlat_adjx2[slice] = tmp; + if (maxlatx2 < tmp) + maxlatx2 = tmp; + } + maxlatx2 = ((maxlatx2 + 1) >> 1) << 1; + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = maxlatx2 - rdlat_adjx2[slice]; + tmp = (tmp >> 1); + if (tmp) { + ddr_setval_s(ch, slice, _reg_PHY_RPTR_UPDATE, + ddr_getval_s(ch, slice, + _reg_PHY_RPTR_UPDATE) + + 1); + } + } + } +} + +/* adjust wpath latency */ +static void adjust_wpath_latency(void) +{ + uint32_t ch, cs, slice; + uint32_t dly; + uint32_t wpath_add; + const uint32_t _par_EARLY_THRESHOLD_VAL = 0x180; + + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice += 1) { + for (cs = 0; cs < CS_CNT; cs++) { + ddr_setval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_INDEX, + cs); + ddr_getval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_INDEX); + dly = + ddr_getval_s(ch, slice, + _reg_PHY_CLK_WRDQS_SLAVE_DELAY); + if (dly <= _par_EARLY_THRESHOLD_VAL) + continue; + + wpath_add = + ddr_getval_s(ch, slice, + _reg_PHY_WRITE_PATH_LAT_ADD); + ddr_setval_s(ch, slice, + _reg_PHY_WRITE_PATH_LAT_ADD, + wpath_add - 1); + } + } + } +} + +/* DDR Initialize entry */ +int32_t rcar_dram_init(void) +{ + uint32_t ch, cs; + uint32_t data_l; + uint32_t bus_mbps, bus_mbpsdiv; + uint32_t tmp_tccd; + uint32_t failcount; + uint32_t cnf_boardtype; + + /* Thermal sensor setting */ + data_l = mmio_read_32(CPG_MSTPSR5); + if (data_l & BIT(22)) { /* case THS/TSC Standby */ + data_l &= ~BIT(22); + cpg_write_32(CPG_SMSTPCR5, data_l); + while (mmio_read_32(CPG_MSTPSR5) & BIT(22)) + ; /* wait bit=0 */ + } + + /* THCTR Bit6: PONM=0 , Bit0: THSST=0 */ + data_l = mmio_read_32(THS1_THCTR); + if (data_l & 0x00000040U) { + data_l = data_l & 0xFFFFFFBEU; + } else { + data_l = data_l | BIT(1); + } + + mmio_write_32(THS1_THCTR, data_l); + + /* Judge product and cut */ +#ifdef RCAR_DDR_FIXED_LSI_TYPE +#if (RCAR_LSI == RCAR_AUTO) + prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK; + prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK; +#else /* RCAR_LSI */ +#ifndef RCAR_LSI_CUT + prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK; +#endif /* RCAR_LSI_CUT */ +#endif /* RCAR_LSI */ +#else /* RCAR_DDR_FIXED_LSI_TYPE */ + prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK; + prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK; +#endif /* RCAR_DDR_FIXED_LSI_TYPE */ + + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut <= PRR_PRODUCT_11) { + p_ddr_regdef_tbl = + (const uint32_t *)&DDR_REGDEF_TBL[0][0]; + } else { + p_ddr_regdef_tbl = + (const uint32_t *)&DDR_REGDEF_TBL[2][0]; + } + } else if (prr_product == PRR_PRODUCT_M3) { + p_ddr_regdef_tbl = + (const uint32_t *)&DDR_REGDEF_TBL[1][0]; + } else if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + p_ddr_regdef_tbl = + (const uint32_t *)&DDR_REGDEF_TBL[3][0]; + } else { + FATAL_MSG("BL2: DDR:Unknown Product\n"); + return 0xff; + } + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) { + /* non : H3 Ver.1.x/M3-W Ver.1.x not support */ + } else { + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + } + + /* Judge board type */ + cnf_boardtype = boardcnf_get_brd_type(); + if (cnf_boardtype >= BOARDNUM) { + FATAL_MSG("BL2: DDR:Unknown Board\n"); + return 0xff; + } + board_cnf = (const struct _boardcnf *)&boardcnfs[cnf_boardtype]; + +/* RCAR_DRAM_SPLIT_2CH (2U) */ +#if RCAR_DRAM_SPLIT == 2 + /* H3(Test for future H3-N): Swap ch2 and ch1 for 2ch-split */ + if ((prr_product == PRR_PRODUCT_H3) && (board_cnf->phyvalid == 0x05)) { + mmio_write_32(DBSC_DBMEMSWAPCONF0, 0x00000006); + ddr_phyvalid = 0x03; + } else { + ddr_phyvalid = board_cnf->phyvalid; + } +#else /* RCAR_DRAM_SPLIT_2CH */ + ddr_phyvalid = board_cnf->phyvalid; +#endif /* RCAR_DRAM_SPLIT_2CH */ + + max_density = 0; + + for (cs = 0; cs < CS_CNT; cs++) { + ch_have_this_cs[cs] = 0; + } + + foreach_ech(ch) + for (cs = 0; cs < CS_CNT; cs++) + ddr_density[ch][cs] = 0xff; + + foreach_vch(ch) { + for (cs = 0; cs < CS_CNT; cs++) { + data_l = board_cnf->ch[ch].ddr_density[cs]; + ddr_density[ch][cs] = data_l; + + if (data_l == 0xff) + continue; + if (data_l > max_density) + max_density = data_l; + if ((cs == 1) && (prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) + continue; + ch_have_this_cs[cs] |= (1U << ch); + } + } + + /* Judge board clock frequency (in MHz) */ + boardcnf_get_brd_clk(cnf_boardtype, &brd_clk, &brd_clkdiv); + if ((brd_clk / brd_clkdiv) > 25) { + brd_clkdiva = 1; + } else { + brd_clkdiva = 0; + } + + /* Judge ddr operating frequency clock(in Mbps) */ + boardcnf_get_ddr_mbps(cnf_boardtype, &ddr_mbps, &ddr_mbpsdiv); + + ddr0800_mul = CLK_DIV(800, 2, brd_clk, brd_clkdiv * (brd_clkdiva + 1)); + + ddr_mul = CLK_DIV(ddr_mbps, ddr_mbpsdiv * 2, brd_clk, + brd_clkdiv * (brd_clkdiva + 1)); + + /* Adjust tccd */ + data_l = (0x00006000 & mmio_read_32(RST_MODEMR)) >> 13; + bus_mbps = 0; + bus_mbpsdiv = 0; + switch (data_l) { + case 0: + bus_mbps = brd_clk * 0x60 * 2; + bus_mbpsdiv = brd_clkdiv * 1; + break; + case 1: + bus_mbps = brd_clk * 0x50 * 2; + bus_mbpsdiv = brd_clkdiv * 1; + break; + case 2: + bus_mbps = brd_clk * 0x40 * 2; + bus_mbpsdiv = brd_clkdiv * 1; + break; + case 3: + bus_mbps = brd_clk * 0x60 * 2; + bus_mbpsdiv = brd_clkdiv * 2; + break; + default: + bus_mbps = brd_clk * 0x60 * 2; + bus_mbpsdiv = brd_clkdiv * 2; + break; + } + tmp_tccd = CLK_DIV(ddr_mbps * 8, ddr_mbpsdiv, bus_mbps, bus_mbpsdiv); + if (8 * ddr_mbps * bus_mbpsdiv != tmp_tccd * bus_mbps * ddr_mbpsdiv) + tmp_tccd = tmp_tccd + 1; + + if (tmp_tccd < 8) + ddr_tccd = 8; + else + ddr_tccd = tmp_tccd; + + NOTICE("BL2: DDR%d(%s)\n", ddr_mbps / ddr_mbpsdiv, RCAR_DDR_VERSION); + + MSG_LF("Start\n"); + + /* PLL Setting */ + pll3_control(1); + + /* initialize DDR */ + data_l = init_ddr(); + if (data_l == ddr_phyvalid) { + failcount = 0; + } else { + failcount = 1; + } + + foreach_vch(ch) + mmio_write_32(DBSC_DBPDLK(ch), 0x00000000); + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) { + /* non : H3 Ver.1.x/M3-W Ver.1.x not support */ + } else { + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + } + + if (failcount == 0) { + return INITDRAM_OK; + } else { + return INITDRAM_NG; + } +} + +void pvtcode_update(void) +{ + uint32_t ch; + uint32_t data_l; + uint32_t pvtp[4], pvtn[4], pvtp_init, pvtn_init; + int32_t pvtp_tmp, pvtn_tmp; + + foreach_vch(ch) { + pvtn_init = (tcal.tcomp_cal[ch] & 0xFC0) >> 6; + pvtp_init = (tcal.tcomp_cal[ch] & 0x03F) >> 0; + + if (8912 * pvtp_init > 44230) { + pvtp_tmp = (5000 + 8912 * pvtp_init - 44230) / 10000; + } else { + pvtp_tmp = + -((-(5000 + 8912 * pvtp_init - 44230)) / 10000); + } + pvtn_tmp = (5000 + 5776 * pvtn_init + 30280) / 10000; + + pvtn[ch] = pvtn_tmp + pvtn_init; + pvtp[ch] = pvtp_tmp + pvtp_init; + + if (pvtn[ch] > 63) { + pvtn[ch] = 63; + pvtp[ch] = + (pvtp_tmp) * (63 - 6 * pvtn_tmp - + pvtn_init) / (pvtn_tmp) + + 6 * pvtp_tmp + pvtp_init; + } + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + data_l = pvtp[ch] | (pvtn[ch] << 6) | + (tcal.tcomp_cal[ch] & 0xfffff000); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM), + data_l | 0x00020000); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_CS_TERM), + data_l); + } else { + data_l = pvtp[ch] | (pvtn[ch] << 6) | 0x00015000; + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM), + data_l | 0x00020000); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_CS_TERM), + data_l); + } + } +} + +void pvtcode_update2(void) +{ + uint32_t ch; + + foreach_vch(ch) { + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM), + tcal.init_cal[ch] | 0x00020000); + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM), + tcal.init_cal[ch]); + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM), + tcal.init_cal[ch]); + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM), + tcal.init_cal[ch]); + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_CS_TERM), + tcal.init_cal[ch]); + } +} + +void ddr_padcal_tcompensate_getinit(uint32_t override) +{ + uint32_t ch; + uint32_t data_l; + uint32_t pvtp, pvtn; + + tcal.init_temp = 0; + for (ch = 0; ch < 4; ch++) { + tcal.init_cal[ch] = 0; + tcal.tcomp_cal[ch] = 0; + } + + foreach_vch(ch) { + tcal.init_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]); + tcal.tcomp_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]); + } + + if (!override) { + data_l = mmio_read_32(THS1_TEMP); + if (data_l < 2800) { + tcal.init_temp = + (143 * (int32_t)data_l - 359000) / 1000; + } else { + tcal.init_temp = + (121 * (int32_t)data_l - 296300) / 1000; + } + + foreach_vch(ch) { + pvtp = (tcal.init_cal[ch] >> 0) & 0x000003F; + pvtn = (tcal.init_cal[ch] >> 6) & 0x000003F; + if ((int32_t)pvtp > + ((tcal.init_temp * 29 - 3625) / 1000)) + pvtp = + (int32_t)pvtp + + ((3625 - tcal.init_temp * 29) / 1000); + else + pvtp = 0; + + if ((int32_t)pvtn > + ((tcal.init_temp * 54 - 6750) / 1000)) + pvtn = + (int32_t)pvtn + + ((6750 - tcal.init_temp * 54) / 1000); + else + pvtn = 0; + + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + tcal.init_cal[ch] = + (tcal.init_cal[ch] & 0xfffff000) | + (pvtn << 6) | + pvtp; + } else { + tcal.init_cal[ch] = + 0x00015000 | (pvtn << 6) | pvtp; + } + } + tcal.init_temp = 125; + } +} + +#ifndef ddr_qos_init_setting +/* For QoS init */ +uint8_t get_boardcnf_phyvalid(void) +{ + return ddr_phyvalid; +} +#endif /* ddr_qos_init_setting */ diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c new file mode 100644 index 0000000..bbb0200 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c @@ -0,0 +1,2108 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RZG_SOC +#define RZG_SOC 0 +#endif + +#if (RZG_SOC == 1) +#define BOARDNUM 4 +#else + +#include + +#define BOARDNUM 22 +#endif /* RZG_SOC == 1 */ +#define BOARD_JUDGE_AUTO + +#ifdef BOARD_JUDGE_AUTO +static uint32_t _board_judge(void); + +static uint32_t boardcnf_get_brd_type(void) +{ + return _board_judge(); +} +#else +static uint32_t boardcnf_get_brd_type(void) +{ + return 1; +} +#endif + +#define DDR_FAST_INIT + +struct _boardcnf_ch { + uint8_t ddr_density[CS_CNT]; + uint64_t ca_swap; + uint16_t dqs_swap; + uint32_t dq_swap[SLICE_CNT]; + uint8_t dm_swap[SLICE_CNT]; + uint16_t wdqlvl_patt[16]; + int8_t cacs_adj[16]; + int8_t dm_adj_w[SLICE_CNT]; + int8_t dq_adj_w[SLICE_CNT * 8]; + int8_t dm_adj_r[SLICE_CNT]; + int8_t dq_adj_r[SLICE_CNT * 8]; +}; + +struct _boardcnf { + uint8_t phyvalid; + uint8_t dbi_en; + uint16_t cacs_dly; + int16_t cacs_dly_adj; + uint16_t dqdm_dly_w; + uint16_t dqdm_dly_r; + struct _boardcnf_ch ch[DRAM_CH_CNT]; +}; + +#define WDQLVL_PAT {\ + 0x00AA,\ + 0x0055,\ + 0x00AA,\ + 0x0155,\ + 0x01CC,\ + 0x0133,\ + 0x00CC,\ + 0x0033,\ + 0x00F0,\ + 0x010F,\ + 0x01F0,\ + 0x010F,\ + 0x00F0,\ + 0x00F0,\ + 0x000F,\ + 0x010F} + +#if (RZG_SOC == 1) +static const struct _boardcnf boardcnfs[BOARDNUM] = { + { +/* boardcnf[0] HopeRun HiHope RZ/G2M 16Gbit/1rank/2ch board with G2M SoC */ + .phyvalid = 0x03U, + .dbi_en = 0x01U, + .cacs_dly = 0x02c0U, + .cacs_dly_adj = 0x0U, + .dqdm_dly_w = 0x0300U, + .dqdm_dly_r = 0x00a0U, + .ch = { + { + { 0x04U, 0xffU }, + 0x00345201UL, + 0x3201U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0x04U, 0xffU }, + 0x00302154UL, + 0x2310U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + } + } + }, +/* boardcnf[1] HopeRun HiHope RZ/G2M 8Gbit/2rank/2ch board with G2M SoC */ + { + 0x03U, + 0x01U, + 0x02c0U, + 0x0U, + 0x0300U, + 0x00a0U, + { + { + { 0x02U, 0x02U }, + 0x00345201UL, + 0x3201U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0x02U, 0x02U }, + 0x00302154UL, + 0x2310, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + } + } + }, +/* boardcnf[2] HopeRun HiHope RZ/G2H board 16Gbit/1rank/2ch */ + { + 0x05U, + 0x01U, + 0x0300U, + 0, + 0x0300U, + 0x00a0U, + { + { + { 0x04U, 0xffU }, + 0x00345201UL, + 0x3201U, + { 0x01672543U, 0x45367012U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0x04U, 0xffU }, + 0x00302154UL, + 0x2310U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0x04U, 0xffU }, + 0x00302154UL, + 0x2310U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0xffU, 0xffU }, + 0UL, + 0U, + { 0U, 0U, 0U, 0U }, + { 0U, 0U, 0U, 0U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + } + } + }, +/* boardcnf[3] HopeRun HiHope RZ/G2N board 16Gbit/2rank/1ch */ + { + 0x01U, + 0x01U, + 0x0300U, + 0, + 0x0300U, + 0x00a0U, + { + { + { 0x04U, 0x04U }, + 0x00345201UL, + 0x3201U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + } + } + }, +}; +#else +static const struct _boardcnf boardcnfs[BOARDNUM] = { + { +/* boardcnf[0] RENESAS SALVATOR-X board with M3-W/SIP */ + .phyvalid = 0x03, + .dbi_en = 0x01, + .cacs_dly = 0x02c0, + .cacs_dly_adj = 0, + .dqdm_dly_w = 0x0300, + .dqdm_dly_r = 0x00a0, + .ch = { + { + {0x02, 0x02}, + 0x00543210U, + 0x3201U, + {0x70612543, 0x43251670, 0x45326170, 0x10672534}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + + { + {0x02, 0x02}, + 0x00543210, + 0x2310, + {0x01327654, 0x34526107, 0x35421670, 0x70615324}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[1] RENESAS KRIEK board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x2c0, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[2] RENESAS SALVATOR-X board with H3 Ver.1.x/SIP(8Gbit 1rank) */ + { + 0x0f, + 0x00, + 0x300, + -320, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00543210, + 0x3210, + {0x20741365, 0x34256107, 0x57460321, 0x70614532}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x3102, + {0x23547610, 0x34526107, 0x67452310, 0x32106754}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x0213, + {0x30216754, 0x67453210, 0x70165243, 0x07162345}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x0213, + {0x01327654, 0x70615432, 0x54760123, 0x07162345}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[3] RENESAS Starter Kit board with M3-W/SIP(8Gbit 1rank) */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x02, 0xFF}, + 0x00543210U, + 0x3201, + {0x70612543, 0x43251670, 0x45326170, 0x10672534}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xFF}, + 0x00543210, + 0x2310, + {0x01327654, 0x34526107, 0x35421670, 0x70615324}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[4] RENESAS SALVATOR-M(1rank) board with H3 Ver.1.x/SoC */ + { + 0x0f, + 0x00, + 0x2c0, + -320, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00315024, + 0x3120, + {0x30671254, 0x26541037, 0x17054623, 0x12307645}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00025143, + 0x3210, + {0x70613542, 0x16245307, 0x30712645, 0x21706354}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00523104, + 0x2301, + {0x70613542, 0x16245307, 0x30712645, 0x21706354}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00153402, + 0x2031, + {0x30671254, 0x26541037, 0x17054623, 0x12307645}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[5] RENESAS KRIEK-1rank board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x2c0, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[6] RENESAS SALVATOR-X board with H3 Ver.1.x/SIP(8Gbit 2rank) */ + { + 0x0f, + 0x00, + 0x300, + -320, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00543210, + 0x3210, + {0x20741365, 0x34256107, 0x57460321, 0x70614532}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00543210, + 0x3102, + {0x23547610, 0x34526107, 0x67452310, 0x32106754}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00543210, + 0x0213, + {0x30216754, 0x67453210, 0x70165243, 0x07162345}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00543210, + 0x0213, + {0x01327654, 0x70615432, 0x54760123, 0x07162345}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* + * boardcnf[7] RENESAS SALVATOR-X board with + * H3 Ver.2.0 or later/SIP(8Gbit 1rank) + */ + { + 0x0f, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00543210, + 0x2310, + {0x70631425, 0x34527016, 0x43527610, 0x32104567}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00105432, + 0x3210, + {0x43256107, 0x07162354, 0x10234567, 0x01235467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x2301, + {0x12034765, 0x23105467, 0x23017645, 0x32106745}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* + * boardcnf[8] RENESAS SALVATOR-X board with + * H3 Ver.2.0 or later/SIP(8Gbit 2rank) + */ + { +#if RCAR_DRAM_CHANNEL == 5 + 0x05, +#else + 0x0f, +#endif + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00543210, + 0x2310, + {0x70631425, 0x34527016, 0x43527610, 0x32104567}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#if ((RCAR_DRAM_CHANNEL == 5) && (RCAR_DRAM_SPLIT == 2)) + { + {0x02, 0x02}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#else + { + {0x02, 0x02}, + 0x00105432, + 0x3210, + {0x43256107, 0x07162354, 0x10234567, 0x01235467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#endif + { + {0x02, 0x02}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00543210, + 0x2301, + {0x12034765, 0x23105467, 0x23017645, 0x32106745}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[9] RENESAS SALVATOR-MS(1rank) board with H3 Ver.2.0 or later/SoC */ + { + 0x0f, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00543210, + 0x3210, + {0x27645310, 0x75346210, 0x53467210, 0x23674510}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x2301, + {0x23764510, 0x43257610, 0x43752610, 0x37652401}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {-128, -128, -128, -128, -128, -128, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00452103, + 0x3210, + {0x32764510, 0x43257610, 0x43752610, 0x26573401}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00520413, + 0x2301, + {0x47652301, 0x75346210, 0x53467210, 0x32674501}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {30, 30, 30, 30, 30, 30, 30, 30, + 30, 30}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[10] RENESAS Kriek(2rank) board with M3-N/SoC */ + { + 0x01, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[11] RENESAS SALVATOR-X board with M3-N/SIP(8Gbit 2rank) */ + { + 0x01, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { +#if (RCAR_DRAM_LPDDR4_MEMCONF == 2) + {0x04, 0x04}, +#else + {0x02, 0x02}, +#endif + 0x00342501, + 0x3201, + {0x10672534, 0x43257106, 0x34527601, 0x71605243}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[12] RENESAS CONDOR board with V3H/SoC */ + { + 0x01, + 0x1, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00501342, + 0x3201, + {0x70562134, 0x34526071, 0x23147506, 0x12430567}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[13] RENESAS KRIEK board with PM3/SoC */ + { + 0x05, + 0x00, + 0x2c0, + -320, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0xff, 0xff}, + 0, + 0, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[14] SALVATOR-X board with H3 Ver.2.0 or later/SIP(16Gbit 1rank) */ + { +#if RCAR_DRAM_CHANNEL == 5 + 0x05, +#else + 0x0f, +#endif + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x04, 0xff}, + 0x00543210, + 0x2310, + {0x70631425, 0x34527016, 0x43527610, 0x32104567}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#if ((RCAR_DRAM_CHANNEL == 5) && (RCAR_DRAM_SPLIT == 2)) + { + {0x04, 0xff}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#else + { + {0x04, 0xff}, + 0x00105432, + 0x3210, + {0x43256107, 0x07162354, 0x10234567, 0x01235467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#endif + { + {0x04, 0xff}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0xff}, + 0x00543210, + 0x2301, + {0x12034765, 0x23105467, 0x23017645, 0x32106745}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[15] RENESAS KRIEK board with H3N */ + { + 0x05, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00345201, + 0x3201, + {0x01672543, 0x45367012, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0xff, 0xff}, + 0, + 0, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[16] RENESAS KRIEK-P2P board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x0320, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0x04}, + 0x520314FFFF523041, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0x04}, + 0x314250FFFF312405, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[17] RENESAS KRIEK-P2P board with M3-N/SoC */ + { + 0x01, + 0x01, + 0x0300, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0x04}, + 0x520314FFFF523041, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[18] RENESAS SALVATOR-X board with M3-W/SIP(16Gbit 2rank) */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0x04}, + 0x00543210, + 0x3201, + {0x70612543, 0x43251670, 0x45326170, 0x10672534}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0x04}, + 0x00543210, + 0x2310, + {0x01327654, 0x34526107, 0x35421670, 0x70615324}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[19] RENESAS SALVATOR-X board with M3-W/SIP(16Gbit 1rank) */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0xff}, + 0x00543210, + 0x3201, + {0x70612543, 0x43251670, 0x45326170, 0x10672534}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0xff}, + 0x00543210, + 0x2310, + {0x01327654, 0x34526107, 0x35421670, 0x70615324}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[20] RENESAS KRIEK 16Gbit/2rank/2ch board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0x04}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0x04}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[21] RENESAS KRIEK 16Gbit/1rank/2ch board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0xff}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0xff}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + } +}; +#endif /* RZG_SOC == 1 */ + +void boardcnf_get_brd_clk(uint32_t brd, uint32_t *clk, uint32_t *div) +{ + uint32_t md; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_10)) { + *clk = 50; + *div = 3; + } else { + md = (mmio_read_32(RST_MODEMR) >> 13) & 0x3; + switch (md) { + case 0x0: + *clk = 50; + *div = 3; + break; + case 0x1: + *clk = 60; + *div = 3; + break; + case 0x2: + *clk = 75; + *div = 3; + break; + case 0x3: + *clk = 100; + *div = 3; + break; + } + } + (void)brd; +} + +void boardcnf_get_ddr_mbps(uint32_t brd, uint32_t *mbps, uint32_t *div) +{ + uint32_t md; + + if (prr_product == PRR_PRODUCT_V3H) { + md = (mmio_read_32(RST_MODEMR) >> 19) & 0x1; + md = (md | (md << 1)) & 0x3; /* 0 or 3 */ + } else { + md = (mmio_read_32(RST_MODEMR) >> 17) & 0x5; + md = (md | (md >> 1)) & 0x3; + } + switch (md) { + case 0x0: + *mbps = 3200; + *div = 1; + break; + case 0x1: + *mbps = 2800; + *div = 1; + break; + case 0x2: + *mbps = 2400; + *div = 1; + break; + case 0x3: + *mbps = 1600; + *div = 1; + break; + } + (void)brd; +} + +#define _def_REFPERIOD 1890 + +#define M3_SAMPLE_TT_A84 0xB866CC10, 0x3B250421 +#define M3_SAMPLE_TT_A85 0xB866CC10, 0x3AA50421 +#define M3_SAMPLE_TT_A86 0xB866CC10, 0x3AA48421 +#define M3_SAMPLE_FF_B45 0xB866CC10, 0x3AB00C21 +#define M3_SAMPLE_FF_B49 0xB866CC10, 0x39B10C21 +#define M3_SAMPLE_FF_B56 0xB866CC10, 0x3AAF8C21 +#define M3_SAMPLE_SS_E24 0xB866CC10, 0x3BA39421 +#define M3_SAMPLE_SS_E28 0xB866CC10, 0x3C231421 +#define M3_SAMPLE_SS_E32 0xB866CC10, 0x3C241421 + +static const uint32_t termcode_by_sample[20][3] = { + {M3_SAMPLE_TT_A84, 0x000158D5}, + {M3_SAMPLE_TT_A85, 0x00015955}, + {M3_SAMPLE_TT_A86, 0x00015955}, + {M3_SAMPLE_FF_B45, 0x00015690}, + {M3_SAMPLE_FF_B49, 0x00015753}, + {M3_SAMPLE_FF_B56, 0x00015793}, + {M3_SAMPLE_SS_E24, 0x00015996}, + {M3_SAMPLE_SS_E28, 0x000159D7}, + {M3_SAMPLE_SS_E32, 0x00015997}, + {0xFFFFFFFF, 0xFFFFFFFF, 0x0001554F} +}; + +#ifdef BOARD_JUDGE_AUTO +/* + * SAMPLE board detect function + */ +#define PFC_PMMR 0xE6060000U +#define PFC_PUEN5 0xE6060414U +#define PFC_PUEN6 0xE6060418U +#define PFC_PUD5 0xE6060454U +#define PFC_PUD6 0xE6060458U +#define GPIO_INDT5 0xE605500CU +#define GPIO_GPSR6 0xE6060118U + +#if (RCAR_GEN3_ULCB == 0) && (RZG_SOC == 0) +static void pfc_write_and_poll(uint32_t a, uint32_t v) +{ + mmio_write_32(PFC_PMMR, ~v); + v = ~mmio_read_32(PFC_PMMR); + mmio_write_32(a, v); + while (v != mmio_read_32(a)) + ; + dsb_sev(); +} +#endif + +#ifndef RCAR_GEN3_ULCB +#define RCAR_GEN3_ULCB 0 +#endif + +#if (RCAR_GEN3_ULCB == 0) && (RZG_SOC == 0) /* non Starter Kit */ + +static uint32_t opencheck_SSI_WS6(void) +{ + uint32_t dataL, down, up; + uint32_t gpsr6_bak; + uint32_t puen5_bak; + uint32_t pud5_bak; + + gpsr6_bak = mmio_read_32(GPIO_GPSR6); + puen5_bak = mmio_read_32(PFC_PUEN5); + pud5_bak = mmio_read_32(PFC_PUD5); + dsb_sev(); + + dataL = (gpsr6_bak & ~BIT(15)); + pfc_write_and_poll(GPIO_GPSR6, dataL); + + /* Pull-Up/Down Enable (PUEN5[22]=1) */ + dataL = puen5_bak; + dataL |= (BIT(22)); + pfc_write_and_poll(PFC_PUEN5, dataL); + + /* Pull-Down-Enable (PUD5[22]=0, PUEN5[22]=1) */ + dataL = pud5_bak; + dataL &= ~(BIT(22)); + pfc_write_and_poll(PFC_PUD5, dataL); + /* GPSR6[15]=SSI_WS6 */ + rcar_micro_delay(10); + down = (mmio_read_32(GPIO_INDT6) >> 15) & 0x1; + dsb_sev(); + + /* Pull-Up-Enable (PUD5[22]=1, PUEN5[22]=1) */ + dataL = pud5_bak; + dataL |= (BIT(22)); + pfc_write_and_poll(PFC_PUD5, dataL); + + /* GPSR6[15]=SSI_WS6 */ + rcar_micro_delay(10); + up = (mmio_read_32(GPIO_INDT6) >> 15) & 0x1; + + dsb_sev(); + + pfc_write_and_poll(GPIO_GPSR6, gpsr6_bak); + pfc_write_and_poll(PFC_PUEN5, puen5_bak); + pfc_write_and_poll(PFC_PUD5, pud5_bak); + + if (down == up) { + /* Same = Connect */ + return 0; + } + + /* Diff = Open */ + return 1; +} + +#endif + +#if (RZG_SOC == 1) +#define LPDDR4_2RANK (0x01U << 25U) + +static uint32_t rzg2_board_judge(void) +{ + uint32_t brd; + + switch (prr_product) { + case PRR_PRODUCT_M3: + brd = 1U; + if ((mmio_read_32(PRR) & PRR_CUT_MASK) != RCAR_M3_CUT_VER11) { + if ((mmio_read_32(GPIO_INDT5) & LPDDR4_2RANK) == 0U) { + brd = 0U; + } + } + break; + case PRR_PRODUCT_H3: + brd = 2U; + break; + case PRR_PRODUCT_M3N: + brd = 3U; + break; + default: + brd = 99U; + } + + return brd; +} +#endif /* RZG_SOC == 1 */ + +#if (RZG_SOC == 0) && (RCAR_DRAM_LPDDR4_MEMCONF != 0) +static uint32_t ddr_rank_judge(void) +{ + uint32_t brd; + +#if (RCAR_DRAM_MEMRANK == 0) + int32_t ret; + uint32_t type = 0U; + uint32_t rev = 0U; + + brd = 99U; + ret = rcar_get_board_type(&type, &rev); + if ((ret == 0) && (rev != 0xFFU)) { + if (type == (uint32_t)BOARD_SALVATOR_XS) { + if (rev == 0x11U) { + brd = 14U; + } else { + brd = 8U; + } + } else if (type == (uint32_t)BOARD_STARTER_KIT_PRE) { + if (rev == 0x21U) { + brd = 14U; + } else { + brd = 8U; + } + } + } +#elif (RCAR_DRAM_MEMRANK == 1) + brd = 14U; +#elif (RCAR_DRAM_MEMRANK == 2) + brd = 8U; +#else +#error Invalid value was set to RCAR_DRAM_MEMRANK +#endif /* (RCAR_DRAM_MEMRANK == 0) */ + return brd; +} +#endif /* (RCAR_DRAM_LPDDR4_MEMCONF != 0) */ + +static uint32_t _board_judge(void) +{ + uint32_t brd; + +#if (RZG_SOC == 1) + brd = rzg2_board_judge(); +#else +#if (RCAR_GEN3_ULCB == 1) + /* Starter Kit */ + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut <= PRR_PRODUCT_11) { + /* RENESAS Starter Kit(H3 Ver.1.x/SIP) board */ + brd = 2; + } else { + /* RENESAS Starter Kit(H3 Ver.2.0 or later/SIP) board */ +#if (RCAR_DRAM_LPDDR4_MEMCONF == 0) + brd = 7; +#else + brd = ddr_rank_judge(); +#endif + } + } else if (prr_product == PRR_PRODUCT_M3) { + if (prr_cut >= PRR_PRODUCT_30) { + /* RENESAS Starter Kit (M3-W Ver.3.0/SIP) */ + brd = 18; + } else { + /* RENESAS Starter Kit(M3-W/SIP 8Gbit 1rank) board */ + brd = 3; + } + } else { + /* RENESAS Starter Kit(M3-N/SIP) board */ + brd = 11; + } +#else + uint32_t usb2_ovc_open; + + usb2_ovc_open = opencheck_SSI_WS6(); + + /* RENESAS Eva-board */ + brd = 99; + if (prr_product == PRR_PRODUCT_V3H) { + /* RENESAS Condor board */ + brd = 12; + } else if (usb2_ovc_open) { + if (prr_product == PRR_PRODUCT_M3N) { + /* RENESAS Kriek board with M3-N */ + brd = 10; + } else if (prr_product == PRR_PRODUCT_M3) { + /* RENESAS Kriek board with M3-W */ + brd = 1; + } else if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + /* RENESAS Kriek board with PM3 */ + brd = 13; + } else if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_20)) { + /* RENESAS Kriek board with H3N */ + brd = 15; + } + } else { + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut <= PRR_PRODUCT_11) { + /* RENESAS SALVATOR-X (H3 Ver.1.x/SIP) */ + brd = 2; + } else if (prr_cut < PRR_PRODUCT_30) { + /* RENESAS SALVATOR-X (H3 Ver.2.0/SIP) */ + brd = 7; // 8Gbit/1rank + } else { + /* RENESAS SALVATOR-X (H3 Ver.3.0/SIP) */ +#if (RCAR_DRAM_LPDDR4_MEMCONF == 0) + brd = 7; +#else + brd = ddr_rank_judge(); +#endif + } + } else if (prr_product == PRR_PRODUCT_M3N) { + /* RENESAS SALVATOR-X (M3-N/SIP) */ + brd = 11; + } else if ((prr_product == PRR_PRODUCT_M3) && + (prr_cut <= PRR_PRODUCT_20)) { + /* RENESAS SALVATOR-X (M3-W/SIP) */ + brd = 0; + } else if ((prr_product == PRR_PRODUCT_M3) && + (prr_cut < PRR_PRODUCT_30)) { + /* RENESAS SALVATOR-X (M3-W Ver.1.x/SIP) */ + brd = 19; + } else if ((prr_product == PRR_PRODUCT_M3) && + (prr_cut >= PRR_PRODUCT_30)) { + /* RENESAS SALVATOR-X (M3-W ver.3.0/SIP) */ + brd = 18; + } + } +#endif +#endif /* RZG_SOC == 1 */ + + return brd; +} +#endif diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h new file mode 100644 index 0000000..3cb1975 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define RCAR_DDR_VERSION "rev.0.41" +#define DRAM_CH_CNT 0x04 +#define SLICE_CNT 0x04 +#define CS_CNT 0x02 + +/* order : CS0A, CS0B, CS1A, CS1B */ +#define CSAB_CNT (CS_CNT * 2) + +/* order : CH0A, CH0B, CH1A, CH1B, CH2A, CH2B, CH3A, CH3B */ +#define CHAB_CNT (DRAM_CH_CNT * 2) + +/* pll setting */ +#define CLK_DIV(a, diva, b, divb) (((a) * (divb)) / ((b) * (diva))) +#define CLK_MUL(a, diva, b, divb) (((a) * (b)) / ((diva) * (divb))) + +/* for ddr deisity setting */ +#define DBMEMCONF_REG(d3, row, bank, col, dw) \ + (((d3) << 30) | ((row) << 24) | ((bank) << 16) | ((col) << 8) | (dw)) + +#define DBMEMCONF_REGD(density) \ + (DBMEMCONF_REG((density) % 2, ((density) + 1) / \ + 2 + (29 - 3 - 10 - 2), 3, 10, 2)) + +#define DBMEMCONF_VAL(ch, cs) (DBMEMCONF_REGD(DBMEMCONF_DENS(ch, cs))) + +/* refresh mode */ +#define DBSC_REFINTS (0x0) + +/* system registers */ +#define CPG_FRQCRB (CPG_BASE + 0x0004U) + +#define CPG_PLLECR (CPG_BASE + 0x00D0U) +#define CPG_MSTPSR5 (CPG_BASE + 0x003CU) +#define CPG_SRCR4 (CPG_BASE + 0x00BCU) +#define CPG_PLL3CR (CPG_BASE + 0x00DCU) +#define CPG_ZB3CKCR (CPG_BASE + 0x0380U) +#define CPG_FRQCRD (CPG_BASE + 0x00E4U) +#define CPG_SMSTPCR5 (CPG_BASE + 0x0144U) +#define CPG_CPGWPR (CPG_BASE + 0x0900U) +#define CPG_SRSTCLR4 (CPG_BASE + 0x0950U) + +#define CPG_FRQCRB_KICK_BIT BIT(31) +#define CPG_PLLECR_PLL3E_BIT BIT(3) +#define CPG_PLLECR_PLL3ST_BIT BIT(11) +#define CPG_ZB3CKCR_ZB3ST_BIT BIT(11) + +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) + +#define LIFEC_CHIPID(x) (0xE6110040U + 0x04U * (x)) + +/* DBSC registers */ +#include "../ddr_regs.h" + +#define DBSC_DBMONCONF4 0xE6793010U + +#define DBSC_PLL_LOCK(ch) (0xE6794054U + 0x100U * (ch)) +#define DBSC_PLL_LOCK_0 0xE6794054U +#define DBSC_PLL_LOCK_1 0xE6794154U +#define DBSC_PLL_LOCK_2 0xE6794254U +#define DBSC_PLL_LOCK_3 0xE6794354U + +/* STAT registers */ +#define MSTAT_SL_INIT 0xE67E8000U +#define MSTAT_REF_ARS 0xE67E8004U +#define MSTATQ_STATQC 0xE67E8008U +#define MSTATQ_WTENABLE 0xE67E8030U +#define MSTATQ_WTREFRESH 0xE67E8034U +#define MSTATQ_WTSETTING0 0xE67E8038U +#define MSTATQ_WTSETTING1 0xE67E803CU + +#define QOS_BASE1 (0xE67F0000U) +#define QOSCTRL_RAS (QOS_BASE1 + 0x0000U) +#define QOSCTRL_FIXTH (QOS_BASE1 + 0x0004U) +#define QOSCTRL_RAEN (QOS_BASE1 + 0x0018U) +#define QOSCTRL_REGGD (QOS_BASE1 + 0x0020U) +#define QOSCTRL_DANN (QOS_BASE1 + 0x0030U) +#define QOSCTRL_DANT (QOS_BASE1 + 0x0038U) +#define QOSCTRL_EC (QOS_BASE1 + 0x003CU) +#define QOSCTRL_EMS (QOS_BASE1 + 0x0040U) +#define QOSCTRL_INSFC (QOS_BASE1 + 0x0050U) +#define QOSCTRL_BERR (QOS_BASE1 + 0x0054U) +#define QOSCTRL_RACNT0 (QOS_BASE1 + 0x0080U) +#define QOSCTRL_STATGEN0 (QOS_BASE1 + 0x0088U) + +/* other module */ +#define THS1_THCTR 0xE6198020U +#define THS1_TEMP 0xE6198028U diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_b.mk b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_b.mk new file mode 100644 index 0000000..0334780 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_b.mk @@ -0,0 +1,7 @@ +# +# Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL2_SOURCES += drivers/renesas/common/ddr/ddr_b/boot_init_dram.c diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h new file mode 100644 index 0000000..adf8dab --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h @@ -0,0 +1,5887 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define _reg_PHY_DQ_DM_SWIZZLE0 0x00000000U +#define _reg_PHY_DQ_DM_SWIZZLE1 0x00000001U +#define _reg_PHY_CLK_WR_BYPASS_SLAVE_DELAY 0x00000002U +#define _reg_PHY_RDDQS_GATE_BYPASS_SLAVE_DELAY 0x00000003U +#define _reg_PHY_BYPASS_TWO_CYC_PREAMBLE 0x00000004U +#define _reg_PHY_CLK_BYPASS_OVERRIDE 0x00000005U +#define _reg_PHY_SW_WRDQ0_SHIFT 0x00000006U +#define _reg_PHY_SW_WRDQ1_SHIFT 0x00000007U +#define _reg_PHY_SW_WRDQ2_SHIFT 0x00000008U +#define _reg_PHY_SW_WRDQ3_SHIFT 0x00000009U +#define _reg_PHY_SW_WRDQ4_SHIFT 0x0000000aU +#define _reg_PHY_SW_WRDQ5_SHIFT 0x0000000bU +#define _reg_PHY_SW_WRDQ6_SHIFT 0x0000000cU +#define _reg_PHY_SW_WRDQ7_SHIFT 0x0000000dU +#define _reg_PHY_SW_WRDM_SHIFT 0x0000000eU +#define _reg_PHY_SW_WRDQS_SHIFT 0x0000000fU +#define _reg_PHY_DQ_TSEL_ENABLE 0x00000010U +#define _reg_PHY_DQ_TSEL_SELECT 0x00000011U +#define _reg_PHY_DQS_TSEL_ENABLE 0x00000012U +#define _reg_PHY_DQS_TSEL_SELECT 0x00000013U +#define _reg_PHY_TWO_CYC_PREAMBLE 0x00000014U +#define _reg_PHY_DBI_MODE 0x00000015U +#define _reg_PHY_PER_RANK_CS_MAP 0x00000016U +#define _reg_PHY_PER_CS_TRAINING_MULTICAST_EN 0x00000017U +#define _reg_PHY_PER_CS_TRAINING_INDEX 0x00000018U +#define _reg_PHY_LP4_BOOT_RDDATA_EN_IE_DLY 0x00000019U +#define _reg_PHY_LP4_BOOT_RDDATA_EN_DLY 0x0000001aU +#define _reg_PHY_LP4_BOOT_RDDATA_EN_TSEL_DLY 0x0000001bU +#define _reg_PHY_LP4_BOOT_RPTR_UPDATE 0x0000001cU +#define _reg_PHY_LP4_BOOT_RDDQS_GATE_SLAVE_DELAY 0x0000001dU +#define _reg_PHY_LP4_BOOT_RDDQS_LATENCY_ADJUST 0x0000001eU +#define _reg_PHY_LP4_BOOT_WRPATH_GATE_DISABLE 0x0000001fU +#define _reg_PHY_LP4_BOOT_RDDATA_EN_OE_DLY 0x00000020U +#define _reg_PHY_LPBK_CONTROL 0x00000021U +#define _reg_PHY_LPBK_DFX_TIMEOUT_EN 0x00000022U +#define _reg_PHY_AUTO_TIMING_MARGIN_CONTROL 0x00000023U +#define _reg_PHY_AUTO_TIMING_MARGIN_OBS 0x00000024U +#define _reg_PHY_SLICE_PWR_RDC_DISABLE 0x00000025U +#define _reg_PHY_PRBS_PATTERN_START 0x00000026U +#define _reg_PHY_PRBS_PATTERN_MASK 0x00000027U +#define _reg_PHY_RDDQS_DQ_BYPASS_SLAVE_DELAY 0x00000028U +#define _reg_PHY_GATE_ERROR_DELAY_SELECT 0x00000029U +#define _reg_SC_PHY_SNAP_OBS_REGS 0x0000002aU +#define _reg_PHY_LPDDR 0x0000002bU +#define _reg_PHY_LPDDR_TYPE 0x0000002cU +#define _reg_PHY_GATE_SMPL1_SLAVE_DELAY 0x0000002dU +#define _reg_PHY_GATE_SMPL2_SLAVE_DELAY 0x0000002eU +#define _reg_ON_FLY_GATE_ADJUST_EN 0x0000002fU +#define _reg_PHY_GATE_TRACKING_OBS 0x00000030U +#define _reg_PHY_DFI40_POLARITY 0x00000031U +#define _reg_PHY_LP4_PST_AMBLE 0x00000032U +#define _reg_PHY_RDLVL_PATT8 0x00000033U +#define _reg_PHY_RDLVL_PATT9 0x00000034U +#define _reg_PHY_RDLVL_PATT10 0x00000035U +#define _reg_PHY_RDLVL_PATT11 0x00000036U +#define _reg_PHY_LP4_RDLVL_PATT8 0x00000037U +#define _reg_PHY_LP4_RDLVL_PATT9 0x00000038U +#define _reg_PHY_LP4_RDLVL_PATT10 0x00000039U +#define _reg_PHY_LP4_RDLVL_PATT11 0x0000003aU +#define _reg_PHY_SLAVE_LOOP_CNT_UPDATE 0x0000003bU +#define _reg_PHY_SW_FIFO_PTR_RST_DISABLE 0x0000003cU +#define _reg_PHY_MASTER_DLY_LOCK_OBS_SELECT 0x0000003dU +#define _reg_PHY_RDDQ_ENC_OBS_SELECT 0x0000003eU +#define _reg_PHY_RDDQS_DQ_ENC_OBS_SELECT 0x0000003fU +#define _reg_PHY_WR_ENC_OBS_SELECT 0x00000040U +#define _reg_PHY_WR_SHIFT_OBS_SELECT 0x00000041U +#define _reg_PHY_FIFO_PTR_OBS_SELECT 0x00000042U +#define _reg_PHY_LVL_DEBUG_MODE 0x00000043U +#define _reg_SC_PHY_LVL_DEBUG_CONT 0x00000044U +#define _reg_PHY_WRLVL_CAPTURE_CNT 0x00000045U +#define _reg_PHY_WRLVL_UPDT_WAIT_CNT 0x00000046U +#define _reg_PHY_WRLVL_DQ_MASK 0x00000047U +#define _reg_PHY_GTLVL_CAPTURE_CNT 0x00000048U +#define _reg_PHY_GTLVL_UPDT_WAIT_CNT 0x00000049U +#define _reg_PHY_RDLVL_CAPTURE_CNT 0x0000004aU +#define _reg_PHY_RDLVL_UPDT_WAIT_CNT 0x0000004bU +#define _reg_PHY_RDLVL_OP_MODE 0x0000004cU +#define _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT 0x0000004dU +#define _reg_PHY_RDLVL_DATA_MASK 0x0000004eU +#define _reg_PHY_RDLVL_DATA_SWIZZLE 0x0000004fU +#define _reg_PHY_WDQLVL_BURST_CNT 0x00000050U +#define _reg_PHY_WDQLVL_PATT 0x00000051U +#define _reg_PHY_WDQLVL_DQDM_SLV_DLY_JUMP_OFFSET 0x00000052U +#define _reg_PHY_WDQLVL_UPDT_WAIT_CNT 0x00000053U +#define _reg_PHY_WDQLVL_DQDM_OBS_SELECT 0x00000054U +#define _reg_PHY_WDQLVL_QTR_DLY_STEP 0x00000055U +#define _reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS 0x00000056U +#define _reg_PHY_WDQLVL_CLR_PREV_RESULTS 0x00000057U +#define _reg_PHY_WDQLVL_DATADM_MASK 0x00000058U +#define _reg_PHY_USER_PATT0 0x00000059U +#define _reg_PHY_USER_PATT1 0x0000005aU +#define _reg_PHY_USER_PATT2 0x0000005bU +#define _reg_PHY_USER_PATT3 0x0000005cU +#define _reg_PHY_USER_PATT4 0x0000005dU +#define _reg_PHY_DQ_SWIZZLING 0x0000005eU +#define _reg_PHY_CALVL_VREF_DRIVING_SLICE 0x0000005fU +#define _reg_SC_PHY_MANUAL_CLEAR 0x00000060U +#define _reg_PHY_FIFO_PTR_OBS 0x00000061U +#define _reg_PHY_LPBK_RESULT_OBS 0x00000062U +#define _reg_PHY_LPBK_ERROR_COUNT_OBS 0x00000063U +#define _reg_PHY_MASTER_DLY_LOCK_OBS 0x00000064U +#define _reg_PHY_RDDQ_SLV_DLY_ENC_OBS 0x00000065U +#define _reg_PHY_RDDQS_BASE_SLV_DLY_ENC_OBS 0x00000066U +#define _reg_PHY_RDDQS_DQ_RISE_ADDER_SLV_DLY_ENC_OBS 0x00000067U +#define _reg_PHY_RDDQS_DQ_FALL_ADDER_SLV_DLY_ENC_OBS 0x00000068U +#define _reg_PHY_RDDQS_GATE_SLV_DLY_ENC_OBS 0x00000069U +#define _reg_PHY_WRDQS_BASE_SLV_DLY_ENC_OBS 0x0000006aU +#define _reg_PHY_WRDQ_BASE_SLV_DLY_ENC_OBS 0x0000006bU +#define _reg_PHY_WR_ADDER_SLV_DLY_ENC_OBS 0x0000006cU +#define _reg_PHY_WR_SHIFT_OBS 0x0000006dU +#define _reg_PHY_WRLVL_HARD0_DELAY_OBS 0x0000006eU +#define _reg_PHY_WRLVL_HARD1_DELAY_OBS 0x0000006fU +#define _reg_PHY_WRLVL_STATUS_OBS 0x00000070U +#define _reg_PHY_GATE_SMPL1_SLV_DLY_ENC_OBS 0x00000071U +#define _reg_PHY_GATE_SMPL2_SLV_DLY_ENC_OBS 0x00000072U +#define _reg_PHY_WRLVL_ERROR_OBS 0x00000073U +#define _reg_PHY_GTLVL_HARD0_DELAY_OBS 0x00000074U +#define _reg_PHY_GTLVL_HARD1_DELAY_OBS 0x00000075U +#define _reg_PHY_GTLVL_STATUS_OBS 0x00000076U +#define _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS 0x00000077U +#define _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS 0x00000078U +#define _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS 0x00000079U +#define _reg_PHY_RDLVL_STATUS_OBS 0x0000007aU +#define _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS 0x0000007bU +#define _reg_PHY_WDQLVL_DQDM_TE_DLY_OBS 0x0000007cU +#define _reg_PHY_WDQLVL_STATUS_OBS 0x0000007dU +#define _reg_PHY_DDL_MODE 0x0000007eU +#define _reg_PHY_DDL_TEST_OBS 0x0000007fU +#define _reg_PHY_DDL_TEST_MSTR_DLY_OBS 0x00000080U +#define _reg_PHY_DDL_TRACK_UPD_THRESHOLD 0x00000081U +#define _reg_PHY_LP4_WDQS_OE_EXTEND 0x00000082U +#define _reg_SC_PHY_RX_CAL_START 0x00000083U +#define _reg_PHY_RX_CAL_OVERRIDE 0x00000084U +#define _reg_PHY_RX_CAL_SAMPLE_WAIT 0x00000085U +#define _reg_PHY_RX_CAL_DQ0 0x00000086U +#define _reg_PHY_RX_CAL_DQ1 0x00000087U +#define _reg_PHY_RX_CAL_DQ2 0x00000088U +#define _reg_PHY_RX_CAL_DQ3 0x00000089U +#define _reg_PHY_RX_CAL_DQ4 0x0000008aU +#define _reg_PHY_RX_CAL_DQ5 0x0000008bU +#define _reg_PHY_RX_CAL_DQ6 0x0000008cU +#define _reg_PHY_RX_CAL_DQ7 0x0000008dU +#define _reg_PHY_RX_CAL_DM 0x0000008eU +#define _reg_PHY_RX_CAL_DQS 0x0000008fU +#define _reg_PHY_RX_CAL_FDBK 0x00000090U +#define _reg_PHY_RX_CAL_OBS 0x00000091U +#define _reg_PHY_RX_CAL_LOCK_OBS 0x00000092U +#define _reg_PHY_RX_CAL_DISABLE 0x00000093U +#define _reg_PHY_CLK_WRDQ0_SLAVE_DELAY 0x00000094U +#define _reg_PHY_CLK_WRDQ1_SLAVE_DELAY 0x00000095U +#define _reg_PHY_CLK_WRDQ2_SLAVE_DELAY 0x00000096U +#define _reg_PHY_CLK_WRDQ3_SLAVE_DELAY 0x00000097U +#define _reg_PHY_CLK_WRDQ4_SLAVE_DELAY 0x00000098U +#define _reg_PHY_CLK_WRDQ5_SLAVE_DELAY 0x00000099U +#define _reg_PHY_CLK_WRDQ6_SLAVE_DELAY 0x0000009aU +#define _reg_PHY_CLK_WRDQ7_SLAVE_DELAY 0x0000009bU +#define _reg_PHY_CLK_WRDM_SLAVE_DELAY 0x0000009cU +#define _reg_PHY_CLK_WRDQS_SLAVE_DELAY 0x0000009dU +#define _reg_PHY_WRLVL_THRESHOLD_ADJUST 0x0000009eU +#define _reg_PHY_RDDQ0_SLAVE_DELAY 0x0000009fU +#define _reg_PHY_RDDQ1_SLAVE_DELAY 0x000000a0U +#define _reg_PHY_RDDQ2_SLAVE_DELAY 0x000000a1U +#define _reg_PHY_RDDQ3_SLAVE_DELAY 0x000000a2U +#define _reg_PHY_RDDQ4_SLAVE_DELAY 0x000000a3U +#define _reg_PHY_RDDQ5_SLAVE_DELAY 0x000000a4U +#define _reg_PHY_RDDQ6_SLAVE_DELAY 0x000000a5U +#define _reg_PHY_RDDQ7_SLAVE_DELAY 0x000000a6U +#define _reg_PHY_RDDM_SLAVE_DELAY 0x000000a7U +#define _reg_PHY_RDDQS_DQ0_RISE_SLAVE_DELAY 0x000000a8U +#define _reg_PHY_RDDQS_DQ0_FALL_SLAVE_DELAY 0x000000a9U +#define _reg_PHY_RDDQS_DQ1_RISE_SLAVE_DELAY 0x000000aaU +#define _reg_PHY_RDDQS_DQ1_FALL_SLAVE_DELAY 0x000000abU +#define _reg_PHY_RDDQS_DQ2_RISE_SLAVE_DELAY 0x000000acU +#define _reg_PHY_RDDQS_DQ2_FALL_SLAVE_DELAY 0x000000adU +#define _reg_PHY_RDDQS_DQ3_RISE_SLAVE_DELAY 0x000000aeU +#define _reg_PHY_RDDQS_DQ3_FALL_SLAVE_DELAY 0x000000afU +#define _reg_PHY_RDDQS_DQ4_RISE_SLAVE_DELAY 0x000000b0U +#define _reg_PHY_RDDQS_DQ4_FALL_SLAVE_DELAY 0x000000b1U +#define _reg_PHY_RDDQS_DQ5_RISE_SLAVE_DELAY 0x000000b2U +#define _reg_PHY_RDDQS_DQ5_FALL_SLAVE_DELAY 0x000000b3U +#define _reg_PHY_RDDQS_DQ6_RISE_SLAVE_DELAY 0x000000b4U +#define _reg_PHY_RDDQS_DQ6_FALL_SLAVE_DELAY 0x000000b5U +#define _reg_PHY_RDDQS_DQ7_RISE_SLAVE_DELAY 0x000000b6U +#define _reg_PHY_RDDQS_DQ7_FALL_SLAVE_DELAY 0x000000b7U +#define _reg_PHY_RDDQS_DM_RISE_SLAVE_DELAY 0x000000b8U +#define _reg_PHY_RDDQS_DM_FALL_SLAVE_DELAY 0x000000b9U +#define _reg_PHY_RDDQS_GATE_SLAVE_DELAY 0x000000baU +#define _reg_PHY_RDDQS_LATENCY_ADJUST 0x000000bbU +#define _reg_PHY_WRITE_PATH_LAT_ADD 0x000000bcU +#define _reg_PHY_WRLVL_DELAY_EARLY_THRESHOLD 0x000000bdU +#define _reg_PHY_WRLVL_DELAY_PERIOD_THRESHOLD 0x000000beU +#define _reg_PHY_WRLVL_EARLY_FORCE_ZERO 0x000000bfU +#define _reg_PHY_GTLVL_RDDQS_SLV_DLY_START 0x000000c0U +#define _reg_PHY_GTLVL_LAT_ADJ_START 0x000000c1U +#define _reg_PHY_WDQLVL_DQDM_SLV_DLY_START 0x000000c2U +#define _reg_PHY_RDLVL_RDDQS_DQ_SLV_DLY_START 0x000000c3U +#define _reg_PHY_FDBK_PWR_CTRL 0x000000c4U +#define _reg_PHY_DQ_OE_TIMING 0x000000c5U +#define _reg_PHY_DQ_TSEL_RD_TIMING 0x000000c6U +#define _reg_PHY_DQ_TSEL_WR_TIMING 0x000000c7U +#define _reg_PHY_DQS_OE_TIMING 0x000000c8U +#define _reg_PHY_DQS_TSEL_RD_TIMING 0x000000c9U +#define _reg_PHY_DQS_OE_RD_TIMING 0x000000caU +#define _reg_PHY_DQS_TSEL_WR_TIMING 0x000000cbU +#define _reg_PHY_PER_CS_TRAINING_EN 0x000000ccU +#define _reg_PHY_DQ_IE_TIMING 0x000000cdU +#define _reg_PHY_DQS_IE_TIMING 0x000000ceU +#define _reg_PHY_RDDATA_EN_IE_DLY 0x000000cfU +#define _reg_PHY_IE_MODE 0x000000d0U +#define _reg_PHY_RDDATA_EN_DLY 0x000000d1U +#define _reg_PHY_RDDATA_EN_TSEL_DLY 0x000000d2U +#define _reg_PHY_RDDATA_EN_OE_DLY 0x000000d3U +#define _reg_PHY_SW_MASTER_MODE 0x000000d4U +#define _reg_PHY_MASTER_DELAY_START 0x000000d5U +#define _reg_PHY_MASTER_DELAY_STEP 0x000000d6U +#define _reg_PHY_MASTER_DELAY_WAIT 0x000000d7U +#define _reg_PHY_MASTER_DELAY_HALF_MEASURE 0x000000d8U +#define _reg_PHY_RPTR_UPDATE 0x000000d9U +#define _reg_PHY_WRLVL_DLY_STEP 0x000000daU +#define _reg_PHY_WRLVL_RESP_WAIT_CNT 0x000000dbU +#define _reg_PHY_GTLVL_DLY_STEP 0x000000dcU +#define _reg_PHY_GTLVL_RESP_WAIT_CNT 0x000000ddU +#define _reg_PHY_GTLVL_BACK_STEP 0x000000deU +#define _reg_PHY_GTLVL_FINAL_STEP 0x000000dfU +#define _reg_PHY_WDQLVL_DLY_STEP 0x000000e0U +#define _reg_PHY_TOGGLE_PRE_SUPPORT 0x000000e1U +#define _reg_PHY_RDLVL_DLY_STEP 0x000000e2U +#define _reg_PHY_WRPATH_GATE_DISABLE 0x000000e3U +#define _reg_PHY_WRPATH_GATE_TIMING 0x000000e4U +#define _reg_PHY_ADR0_SW_WRADDR_SHIFT 0x000000e5U +#define _reg_PHY_ADR1_SW_WRADDR_SHIFT 0x000000e6U +#define _reg_PHY_ADR2_SW_WRADDR_SHIFT 0x000000e7U +#define _reg_PHY_ADR3_SW_WRADDR_SHIFT 0x000000e8U +#define _reg_PHY_ADR4_SW_WRADDR_SHIFT 0x000000e9U +#define _reg_PHY_ADR5_SW_WRADDR_SHIFT 0x000000eaU +#define _reg_PHY_ADR_CLK_WR_BYPASS_SLAVE_DELAY 0x000000ebU +#define _reg_PHY_ADR_CLK_BYPASS_OVERRIDE 0x000000ecU +#define _reg_SC_PHY_ADR_MANUAL_CLEAR 0x000000edU +#define _reg_PHY_ADR_LPBK_RESULT_OBS 0x000000eeU +#define _reg_PHY_ADR_LPBK_ERROR_COUNT_OBS 0x000000efU +#define _reg_PHY_ADR_MASTER_DLY_LOCK_OBS_SELECT 0x000000f0U +#define _reg_PHY_ADR_MASTER_DLY_LOCK_OBS 0x000000f1U +#define _reg_PHY_ADR_BASE_SLV_DLY_ENC_OBS 0x000000f2U +#define _reg_PHY_ADR_ADDER_SLV_DLY_ENC_OBS 0x000000f3U +#define _reg_PHY_ADR_SLAVE_LOOP_CNT_UPDATE 0x000000f4U +#define _reg_PHY_ADR_SLV_DLY_ENC_OBS_SELECT 0x000000f5U +#define _reg_SC_PHY_ADR_SNAP_OBS_REGS 0x000000f6U +#define _reg_PHY_ADR_TSEL_ENABLE 0x000000f7U +#define _reg_PHY_ADR_LPBK_CONTROL 0x000000f8U +#define _reg_PHY_ADR_PRBS_PATTERN_START 0x000000f9U +#define _reg_PHY_ADR_PRBS_PATTERN_MASK 0x000000faU +#define _reg_PHY_ADR_PWR_RDC_DISABLE 0x000000fbU +#define _reg_PHY_ADR_TYPE 0x000000fcU +#define _reg_PHY_ADR_WRADDR_SHIFT_OBS 0x000000fdU +#define _reg_PHY_ADR_IE_MODE 0x000000feU +#define _reg_PHY_ADR_DDL_MODE 0x000000ffU +#define _reg_PHY_ADR_DDL_TEST_OBS 0x00000100U +#define _reg_PHY_ADR_DDL_TEST_MSTR_DLY_OBS 0x00000101U +#define _reg_PHY_ADR_CALVL_START 0x00000102U +#define _reg_PHY_ADR_CALVL_COARSE_DLY 0x00000103U +#define _reg_PHY_ADR_CALVL_QTR 0x00000104U +#define _reg_PHY_ADR_CALVL_SWIZZLE0 0x00000105U +#define _reg_PHY_ADR_CALVL_SWIZZLE1 0x00000106U +#define _reg_PHY_ADR_CALVL_SWIZZLE0_0 0x00000107U +#define _reg_PHY_ADR_CALVL_SWIZZLE1_0 0x00000108U +#define _reg_PHY_ADR_CALVL_SWIZZLE0_1 0x00000109U +#define _reg_PHY_ADR_CALVL_SWIZZLE1_1 0x0000010aU +#define _reg_PHY_ADR_CALVL_DEVICE_MAP 0x0000010bU +#define _reg_PHY_ADR_CALVL_RANK_CTRL 0x0000010cU +#define _reg_PHY_ADR_CALVL_NUM_PATTERNS 0x0000010dU +#define _reg_PHY_ADR_CALVL_CAPTURE_CNT 0x0000010eU +#define _reg_PHY_ADR_CALVL_RESP_WAIT_CNT 0x0000010fU +#define _reg_PHY_ADR_CALVL_DEBUG_MODE 0x00000110U +#define _reg_SC_PHY_ADR_CALVL_DEBUG_CONT 0x00000111U +#define _reg_SC_PHY_ADR_CALVL_ERROR_CLR 0x00000112U +#define _reg_PHY_ADR_CALVL_OBS_SELECT 0x00000113U +#define _reg_PHY_ADR_CALVL_OBS0 0x00000114U +#define _reg_PHY_ADR_CALVL_OBS1 0x00000115U +#define _reg_PHY_ADR_CALVL_RESULT 0x00000116U +#define _reg_PHY_ADR_CALVL_FG_0 0x00000117U +#define _reg_PHY_ADR_CALVL_BG_0 0x00000118U +#define _reg_PHY_ADR_CALVL_FG_1 0x00000119U +#define _reg_PHY_ADR_CALVL_BG_1 0x0000011aU +#define _reg_PHY_ADR_CALVL_FG_2 0x0000011bU +#define _reg_PHY_ADR_CALVL_BG_2 0x0000011cU +#define _reg_PHY_ADR_CALVL_FG_3 0x0000011dU +#define _reg_PHY_ADR_CALVL_BG_3 0x0000011eU +#define _reg_PHY_ADR_ADDR_SEL 0x0000011fU +#define _reg_PHY_ADR_LP4_BOOT_SLV_DELAY 0x00000120U +#define _reg_PHY_ADR_BIT_MASK 0x00000121U +#define _reg_PHY_ADR_SEG_MASK 0x00000122U +#define _reg_PHY_ADR_CALVL_TRAIN_MASK 0x00000123U +#define _reg_PHY_ADR_CSLVL_TRAIN_MASK 0x00000124U +#define _reg_PHY_ADR_SW_TXIO_CTRL 0x00000125U +#define _reg_PHY_ADR_TSEL_SELECT 0x00000126U +#define _reg_PHY_ADR0_CLK_WR_SLAVE_DELAY 0x00000127U +#define _reg_PHY_ADR1_CLK_WR_SLAVE_DELAY 0x00000128U +#define _reg_PHY_ADR2_CLK_WR_SLAVE_DELAY 0x00000129U +#define _reg_PHY_ADR3_CLK_WR_SLAVE_DELAY 0x0000012aU +#define _reg_PHY_ADR4_CLK_WR_SLAVE_DELAY 0x0000012bU +#define _reg_PHY_ADR5_CLK_WR_SLAVE_DELAY 0x0000012cU +#define _reg_PHY_ADR_SW_MASTER_MODE 0x0000012dU +#define _reg_PHY_ADR_MASTER_DELAY_START 0x0000012eU +#define _reg_PHY_ADR_MASTER_DELAY_STEP 0x0000012fU +#define _reg_PHY_ADR_MASTER_DELAY_WAIT 0x00000130U +#define _reg_PHY_ADR_MASTER_DELAY_HALF_MEASURE 0x00000131U +#define _reg_PHY_ADR_CALVL_DLY_STEP 0x00000132U +#define _reg_PHY_FREQ_SEL 0x00000133U +#define _reg_PHY_FREQ_SEL_FROM_REGIF 0x00000134U +#define _reg_PHY_FREQ_SEL_MULTICAST_EN 0x00000135U +#define _reg_PHY_FREQ_SEL_INDEX 0x00000136U +#define _reg_PHY_SW_GRP_SHIFT_0 0x00000137U +#define _reg_PHY_SW_GRP_SHIFT_1 0x00000138U +#define _reg_PHY_SW_GRP_SHIFT_2 0x00000139U +#define _reg_PHY_SW_GRP_SHIFT_3 0x0000013aU +#define _reg_PHY_GRP_BYPASS_SLAVE_DELAY 0x0000013bU +#define _reg_PHY_SW_GRP_BYPASS_SHIFT 0x0000013cU +#define _reg_PHY_GRP_BYPASS_OVERRIDE 0x0000013dU +#define _reg_SC_PHY_MANUAL_UPDATE 0x0000013eU +#define _reg_SC_PHY_MANUAL_UPDATE_PHYUPD_ENABLE 0x0000013fU +#define _reg_PHY_LP4_BOOT_DISABLE 0x00000140U +#define _reg_PHY_CSLVL_ENABLE 0x00000141U +#define _reg_PHY_CSLVL_CS_MAP 0x00000142U +#define _reg_PHY_CSLVL_START 0x00000143U +#define _reg_PHY_CSLVL_QTR 0x00000144U +#define _reg_PHY_CSLVL_COARSE_CHK 0x00000145U +#define _reg_PHY_CSLVL_CAPTURE_CNT 0x00000146U +#define _reg_PHY_CSLVL_COARSE_DLY 0x00000147U +#define _reg_PHY_CSLVL_COARSE_CAPTURE_CNT 0x00000148U +#define _reg_PHY_CSLVL_DEBUG_MODE 0x00000149U +#define _reg_SC_PHY_CSLVL_DEBUG_CONT 0x0000014aU +#define _reg_SC_PHY_CSLVL_ERROR_CLR 0x0000014bU +#define _reg_PHY_CSLVL_OBS0 0x0000014cU +#define _reg_PHY_CSLVL_OBS1 0x0000014dU +#define _reg_PHY_CALVL_CS_MAP 0x0000014eU +#define _reg_PHY_GRP_SLV_DLY_ENC_OBS_SELECT 0x0000014fU +#define _reg_PHY_GRP_SHIFT_OBS_SELECT 0x00000150U +#define _reg_PHY_GRP_SLV_DLY_ENC_OBS 0x00000151U +#define _reg_PHY_GRP_SHIFT_OBS 0x00000152U +#define _reg_PHY_ADRCTL_SLAVE_LOOP_CNT_UPDATE 0x00000153U +#define _reg_PHY_ADRCTL_SNAP_OBS_REGS 0x00000154U +#define _reg_PHY_DFI_PHYUPD_TYPE 0x00000155U +#define _reg_PHY_ADRCTL_LPDDR 0x00000156U +#define _reg_PHY_LP4_ACTIVE 0x00000157U +#define _reg_PHY_LPDDR3_CS 0x00000158U +#define _reg_PHY_CALVL_RESULT_MASK 0x00000159U +#define _reg_SC_PHY_UPDATE_CLK_CAL_VALUES 0x0000015aU +#define _reg_PHY_SW_TXIO_CTRL_0 0x0000015bU +#define _reg_PHY_SW_TXIO_CTRL_1 0x0000015cU +#define _reg_PHY_SW_TXIO_CTRL_2 0x0000015dU +#define _reg_PHY_SW_TXIO_CTRL_3 0x0000015eU +#define _reg_PHY_MEMCLK_SW_TXIO_CTRL 0x0000015fU +#define _reg_PHY_CA_SW_TXPWR_CTRL 0x00000160U +#define _reg_PHY_MEMCLK_SW_TXPWR_CTRL 0x00000161U +#define _reg_PHY_USER_DEF_REG_AC_0 0x00000162U +#define _reg_PHY_USER_DEF_REG_AC_1 0x00000163U +#define _reg_PHY_USER_DEF_REG_AC_2 0x00000164U +#define _reg_PHY_USER_DEF_REG_AC_3 0x00000165U +#define _reg_PHY_UPDATE_CLK_CAL_VALUES 0x00000166U +#define _reg_PHY_CONTINUOUS_CLK_CAL_UPDATE 0x00000167U +#define _reg_PHY_PLL_CTRL 0x00000168U +#define _reg_PHY_PLL_CTRL_TOP 0x00000169U +#define _reg_PHY_PLL_CTRL_CA 0x0000016aU +#define _reg_PHY_PLL_BYPASS 0x0000016bU +#define _reg_PHY_LOW_FREQ_SEL 0x0000016cU +#define _reg_PHY_PAD_VREF_CTRL_DQ_0 0x0000016dU +#define _reg_PHY_PAD_VREF_CTRL_DQ_1 0x0000016eU +#define _reg_PHY_PAD_VREF_CTRL_DQ_2 0x0000016fU +#define _reg_PHY_PAD_VREF_CTRL_DQ_3 0x00000170U +#define _reg_PHY_PAD_VREF_CTRL_AC 0x00000171U +#define _reg_PHY_CSLVL_DLY_STEP 0x00000172U +#define _reg_PHY_SET_DFI_INPUT_0 0x00000173U +#define _reg_PHY_SET_DFI_INPUT_1 0x00000174U +#define _reg_PHY_SET_DFI_INPUT_2 0x00000175U +#define _reg_PHY_SET_DFI_INPUT_3 0x00000176U +#define _reg_PHY_GRP_SLAVE_DELAY_0 0x00000177U +#define _reg_PHY_GRP_SLAVE_DELAY_1 0x00000178U +#define _reg_PHY_GRP_SLAVE_DELAY_2 0x00000179U +#define _reg_PHY_GRP_SLAVE_DELAY_3 0x0000017aU +#define _reg_PHY_CS_ACS_ALLOCATION_0 0x0000017bU +#define _reg_PHY_CS_ACS_ALLOCATION_1 0x0000017cU +#define _reg_PHY_CS_ACS_ALLOCATION_2 0x0000017dU +#define _reg_PHY_CS_ACS_ALLOCATION_3 0x0000017eU +#define _reg_PHY_LP4_BOOT_PLL_CTRL 0x0000017fU +#define _reg_PHY_LP4_BOOT_PLL_CTRL_CA 0x00000180U +#define _reg_PHY_LP4_BOOT_TOP_PLL_CTRL 0x00000181U +#define _reg_PHY_PLL_CTRL_OVERRIDE 0x00000182U +#define _reg_PHY_PLL_WAIT 0x00000183U +#define _reg_PHY_PLL_WAIT_TOP 0x00000184U +#define _reg_PHY_PLL_OBS_0 0x00000185U +#define _reg_PHY_PLL_OBS_1 0x00000186U +#define _reg_PHY_PLL_OBS_2 0x00000187U +#define _reg_PHY_PLL_OBS_3 0x00000188U +#define _reg_PHY_PLL_OBS_4 0x00000189U +#define _reg_PHY_PLL_TESTOUT_SEL 0x0000018aU +#define _reg_PHY_TCKSRE_WAIT 0x0000018bU +#define _reg_PHY_LP4_BOOT_LOW_FREQ_SEL 0x0000018cU +#define _reg_PHY_LP_WAKEUP 0x0000018dU +#define _reg_PHY_LS_IDLE_EN 0x0000018eU +#define _reg_PHY_LP_CTRLUPD_CNTR_CFG 0x0000018fU +#define _reg_PHY_TDFI_PHY_WRDELAY 0x00000190U +#define _reg_PHY_PAD_FDBK_DRIVE 0x00000191U +#define _reg_PHY_PAD_DATA_DRIVE 0x00000192U +#define _reg_PHY_PAD_DQS_DRIVE 0x00000193U +#define _reg_PHY_PAD_ADDR_DRIVE 0x00000194U +#define _reg_PHY_PAD_CLK_DRIVE 0x00000195U +#define _reg_PHY_PAD_FDBK_TERM 0x00000196U +#define _reg_PHY_PAD_DATA_TERM 0x00000197U +#define _reg_PHY_PAD_DQS_TERM 0x00000198U +#define _reg_PHY_PAD_ADDR_TERM 0x00000199U +#define _reg_PHY_PAD_CLK_TERM 0x0000019aU +#define _reg_PHY_PAD_CKE_DRIVE 0x0000019bU +#define _reg_PHY_PAD_CKE_TERM 0x0000019cU +#define _reg_PHY_PAD_RST_DRIVE 0x0000019dU +#define _reg_PHY_PAD_RST_TERM 0x0000019eU +#define _reg_PHY_PAD_CS_DRIVE 0x0000019fU +#define _reg_PHY_PAD_CS_TERM 0x000001a0U +#define _reg_PHY_PAD_ODT_DRIVE 0x000001a1U +#define _reg_PHY_PAD_ODT_TERM 0x000001a2U +#define _reg_PHY_ADRCTL_RX_CAL 0x000001a3U +#define _reg_PHY_ADRCTL_LP3_RX_CAL 0x000001a4U +#define _reg_PHY_TST_CLK_PAD_CTRL 0x000001a5U +#define _reg_PHY_TST_CLK_PAD_CTRL2 0x000001a6U +#define _reg_PHY_CAL_MODE_0 0x000001a7U +#define _reg_PHY_CAL_CLEAR_0 0x000001a8U +#define _reg_PHY_CAL_START_0 0x000001a9U +#define _reg_PHY_CAL_INTERVAL_COUNT_0 0x000001aaU +#define _reg_PHY_CAL_SAMPLE_WAIT_0 0x000001abU +#define _reg_PHY_LP4_BOOT_CAL_CLK_SELECT_0 0x000001acU +#define _reg_PHY_CAL_CLK_SELECT_0 0x000001adU +#define _reg_PHY_CAL_RESULT_OBS_0 0x000001aeU +#define _reg_PHY_CAL_RESULT2_OBS_0 0x000001afU +#define _reg_PHY_CAL_CPTR_CNT_0 0x000001b0U +#define _reg_PHY_CAL_SETTLING_PRD_0 0x000001b1U +#define _reg_PHY_CAL_PU_FINE_ADJ_0 0x000001b2U +#define _reg_PHY_CAL_PD_FINE_ADJ_0 0x000001b3U +#define _reg_PHY_CAL_RCV_FINE_ADJ_0 0x000001b4U +#define _reg_PHY_CAL_DBG_CFG_0 0x000001b5U +#define _reg_SC_PHY_PAD_DBG_CONT_0 0x000001b6U +#define _reg_PHY_CAL_RESULT3_OBS_0 0x000001b7U +#define _reg_PHY_ADRCTL_PVT_MAP_0 0x000001b8U +#define _reg_PHY_CAL_SLOPE_ADJ_0 0x000001b9U +#define _reg_PHY_CAL_SLOPE_ADJ_PASS2_0 0x000001baU +#define _reg_PHY_CAL_TWO_PASS_CFG_0 0x000001bbU +#define _reg_PHY_CAL_SW_CAL_CFG_0 0x000001bcU +#define _reg_PHY_CAL_RANGE_MIN_0 0x000001bdU +#define _reg_PHY_CAL_RANGE_MAX_0 0x000001beU +#define _reg_PHY_PAD_ATB_CTRL 0x000001bfU +#define _reg_PHY_ADRCTL_MANUAL_UPDATE 0x000001c0U +#define _reg_PHY_AC_LPBK_ERR_CLEAR 0x000001c1U +#define _reg_PHY_AC_LPBK_OBS_SELECT 0x000001c2U +#define _reg_PHY_AC_LPBK_ENABLE 0x000001c3U +#define _reg_PHY_AC_LPBK_CONTROL 0x000001c4U +#define _reg_PHY_AC_PRBS_PATTERN_START 0x000001c5U +#define _reg_PHY_AC_PRBS_PATTERN_MASK 0x000001c6U +#define _reg_PHY_AC_LPBK_RESULT_OBS 0x000001c7U +#define _reg_PHY_AC_CLK_LPBK_OBS_SELECT 0x000001c8U +#define _reg_PHY_AC_CLK_LPBK_ENABLE 0x000001c9U +#define _reg_PHY_AC_CLK_LPBK_CONTROL 0x000001caU +#define _reg_PHY_AC_CLK_LPBK_RESULT_OBS 0x000001cbU +#define _reg_PHY_AC_PWR_RDC_DISABLE 0x000001ccU +#define _reg_PHY_DATA_BYTE_ORDER_SEL 0x000001cdU +#define _reg_PHY_DATA_BYTE_ORDER_SEL_HIGH 0x000001ceU +#define _reg_PHY_LPDDR4_CONNECT 0x000001cfU +#define _reg_PHY_CALVL_DEVICE_MAP 0x000001d0U +#define _reg_PHY_ADR_DISABLE 0x000001d1U +#define _reg_PHY_ADRCTL_MSTR_DLY_ENC_SEL 0x000001d2U +#define _reg_PHY_CS_DLY_UPT_PER_AC_SLICE 0x000001d3U +#define _reg_PHY_DDL_AC_ENABLE 0x000001d4U +#define _reg_PHY_DDL_AC_MODE 0x000001d5U +#define _reg_PHY_PAD_BACKGROUND_CAL 0x000001d6U +#define _reg_PHY_INIT_UPDATE_CONFIG 0x000001d7U +#define _reg_PHY_DDL_TRACK_UPD_THRESHOLD_AC 0x000001d8U +#define _reg_PHY_DLL_RST_EN 0x000001d9U +#define _reg_PHY_AC_INIT_COMPLETE_OBS 0x000001daU +#define _reg_PHY_DS_INIT_COMPLETE_OBS 0x000001dbU +#define _reg_PHY_UPDATE_MASK 0x000001dcU +#define _reg_PHY_PLL_SWITCH_CNT 0x000001ddU +#define _reg_PI_START 0x000001deU +#define _reg_PI_DRAM_CLASS 0x000001dfU +#define _reg_PI_VERSION 0x000001e0U +#define _reg_PI_NORMAL_LVL_SEQ 0x000001e1U +#define _reg_PI_INIT_LVL_EN 0x000001e2U +#define _reg_PI_NOTCARE_PHYUPD 0x000001e3U +#define _reg_PI_ONBUS_MBIST 0x000001e4U +#define _reg_PI_TCMD_GAP 0x000001e5U +#define _reg_PI_MASTER_ACK_DURATION_MIN 0x000001e6U +#define _reg_PI_DFI_VERSION 0x000001e7U +#define _reg_PI_TDFI_PHYMSTR_TYPE0 0x000001e8U +#define _reg_PI_TDFI_PHYMSTR_TYPE1 0x000001e9U +#define _reg_PI_TDFI_PHYMSTR_TYPE2 0x000001eaU +#define _reg_PI_TDFI_PHYMSTR_TYPE3 0x000001ebU +#define _reg_PI_DFI_PHYMSTR_TYPE 0x000001ecU +#define _reg_PI_DFI_PHYMSTR_CS_STATE_R 0x000001edU +#define _reg_PI_DFI_PHYMSTR_STATE_SEL_R 0x000001eeU +#define _reg_PI_TDFI_PHYMSTR_MAX_F0 0x000001efU +#define _reg_PI_TDFI_PHYMSTR_RESP_F0 0x000001f0U +#define _reg_PI_TDFI_PHYMSTR_MAX_F1 0x000001f1U +#define _reg_PI_TDFI_PHYMSTR_RESP_F1 0x000001f2U +#define _reg_PI_TDFI_PHYMSTR_MAX_F2 0x000001f3U +#define _reg_PI_TDFI_PHYMSTR_RESP_F2 0x000001f4U +#define _reg_PI_TDFI_PHYUPD_RESP_F0 0x000001f5U +#define _reg_PI_TDFI_PHYUPD_TYPE0_F0 0x000001f6U +#define _reg_PI_TDFI_PHYUPD_TYPE1_F0 0x000001f7U +#define _reg_PI_TDFI_PHYUPD_TYPE2_F0 0x000001f8U +#define _reg_PI_TDFI_PHYUPD_TYPE3_F0 0x000001f9U +#define _reg_PI_TDFI_PHYUPD_RESP_F1 0x000001faU +#define _reg_PI_TDFI_PHYUPD_TYPE0_F1 0x000001fbU +#define _reg_PI_TDFI_PHYUPD_TYPE1_F1 0x000001fcU +#define _reg_PI_TDFI_PHYUPD_TYPE2_F1 0x000001fdU +#define _reg_PI_TDFI_PHYUPD_TYPE3_F1 0x000001feU +#define _reg_PI_TDFI_PHYUPD_RESP_F2 0x000001ffU +#define _reg_PI_TDFI_PHYUPD_TYPE0_F2 0x00000200U +#define _reg_PI_TDFI_PHYUPD_TYPE1_F2 0x00000201U +#define _reg_PI_TDFI_PHYUPD_TYPE2_F2 0x00000202U +#define _reg_PI_TDFI_PHYUPD_TYPE3_F2 0x00000203U +#define _reg_PI_CONTROL_ERROR_STATUS 0x00000204U +#define _reg_PI_EXIT_AFTER_INIT_CALVL 0x00000205U +#define _reg_PI_FREQ_MAP 0x00000206U +#define _reg_PI_INIT_WORK_FREQ 0x00000207U +#define _reg_PI_INIT_DFS_CALVL_ONLY 0x00000208U +#define _reg_PI_POWER_ON_SEQ_BYPASS_ARRAY 0x00000209U +#define _reg_PI_POWER_ON_SEQ_END_ARRAY 0x0000020aU +#define _reg_PI_SEQ1_PAT 0x0000020bU +#define _reg_PI_SEQ1_PAT_MASK 0x0000020cU +#define _reg_PI_SEQ2_PAT 0x0000020dU +#define _reg_PI_SEQ2_PAT_MASK 0x0000020eU +#define _reg_PI_SEQ3_PAT 0x0000020fU +#define _reg_PI_SEQ3_PAT_MASK 0x00000210U +#define _reg_PI_SEQ4_PAT 0x00000211U +#define _reg_PI_SEQ4_PAT_MASK 0x00000212U +#define _reg_PI_SEQ5_PAT 0x00000213U +#define _reg_PI_SEQ5_PAT_MASK 0x00000214U +#define _reg_PI_SEQ6_PAT 0x00000215U +#define _reg_PI_SEQ6_PAT_MASK 0x00000216U +#define _reg_PI_SEQ7_PAT 0x00000217U +#define _reg_PI_SEQ7_PAT_MASK 0x00000218U +#define _reg_PI_SEQ8_PAT 0x00000219U +#define _reg_PI_SEQ8_PAT_MASK 0x0000021aU +#define _reg_PI_WDT_DISABLE 0x0000021bU +#define _reg_PI_SW_RST_N 0x0000021cU +#define _reg_RESERVED_R0 0x0000021dU +#define _reg_PI_CS_MAP 0x0000021eU +#define _reg_PI_TDELAY_RDWR_2_BUS_IDLE_F0 0x0000021fU +#define _reg_PI_TDELAY_RDWR_2_BUS_IDLE_F1 0x00000220U +#define _reg_PI_TDELAY_RDWR_2_BUS_IDLE_F2 0x00000221U +#define _reg_PI_TMRR 0x00000222U +#define _reg_PI_WRLAT_F0 0x00000223U +#define _reg_PI_ADDITIVE_LAT_F0 0x00000224U +#define _reg_PI_CASLAT_LIN_F0 0x00000225U +#define _reg_PI_WRLAT_F1 0x00000226U +#define _reg_PI_ADDITIVE_LAT_F1 0x00000227U +#define _reg_PI_CASLAT_LIN_F1 0x00000228U +#define _reg_PI_WRLAT_F2 0x00000229U +#define _reg_PI_ADDITIVE_LAT_F2 0x0000022aU +#define _reg_PI_CASLAT_LIN_F2 0x0000022bU +#define _reg_PI_PREAMBLE_SUPPORT 0x0000022cU +#define _reg_PI_AREFRESH 0x0000022dU +#define _reg_PI_MCAREF_FORWARD_ONLY 0x0000022eU +#define _reg_PI_TRFC_F0 0x0000022fU +#define _reg_PI_TREF_F0 0x00000230U +#define _reg_PI_TRFC_F1 0x00000231U +#define _reg_PI_TREF_F1 0x00000232U +#define _reg_PI_TRFC_F2 0x00000233U +#define _reg_PI_TREF_F2 0x00000234U +#define _reg_RESERVED_H3VER2 0x00000235U +#define _reg_PI_TREF_INTERVAL 0x00000236U +#define _reg_PI_FREQ_CHANGE_REG_COPY 0x00000237U +#define _reg_PI_FREQ_SEL_FROM_REGIF 0x00000238U +#define _reg_PI_SWLVL_LOAD 0x00000239U +#define _reg_PI_SWLVL_OP_DONE 0x0000023aU +#define _reg_PI_SW_WRLVL_RESP_0 0x0000023bU +#define _reg_PI_SW_WRLVL_RESP_1 0x0000023cU +#define _reg_PI_SW_WRLVL_RESP_2 0x0000023dU +#define _reg_PI_SW_WRLVL_RESP_3 0x0000023eU +#define _reg_PI_SW_RDLVL_RESP_0 0x0000023fU +#define _reg_PI_SW_RDLVL_RESP_1 0x00000240U +#define _reg_PI_SW_RDLVL_RESP_2 0x00000241U +#define _reg_PI_SW_RDLVL_RESP_3 0x00000242U +#define _reg_PI_SW_CALVL_RESP_0 0x00000243U +#define _reg_PI_SW_LEVELING_MODE 0x00000244U +#define _reg_PI_SWLVL_START 0x00000245U +#define _reg_PI_SWLVL_EXIT 0x00000246U +#define _reg_PI_SWLVL_WR_SLICE_0 0x00000247U +#define _reg_PI_SWLVL_RD_SLICE_0 0x00000248U +#define _reg_PI_SWLVL_VREF_UPDATE_SLICE_0 0x00000249U +#define _reg_PI_SW_WDQLVL_RESP_0 0x0000024aU +#define _reg_PI_SWLVL_WR_SLICE_1 0x0000024bU +#define _reg_PI_SWLVL_RD_SLICE_1 0x0000024cU +#define _reg_PI_SWLVL_VREF_UPDATE_SLICE_1 0x0000024dU +#define _reg_PI_SW_WDQLVL_RESP_1 0x0000024eU +#define _reg_PI_SWLVL_WR_SLICE_2 0x0000024fU +#define _reg_PI_SWLVL_RD_SLICE_2 0x00000250U +#define _reg_PI_SWLVL_VREF_UPDATE_SLICE_2 0x00000251U +#define _reg_PI_SW_WDQLVL_RESP_2 0x00000252U +#define _reg_PI_SWLVL_WR_SLICE_3 0x00000253U +#define _reg_PI_SWLVL_RD_SLICE_3 0x00000254U +#define _reg_PI_SWLVL_VREF_UPDATE_SLICE_3 0x00000255U +#define _reg_PI_SW_WDQLVL_RESP_3 0x00000256U +#define _reg_PI_SW_WDQLVL_VREF 0x00000257U +#define _reg_PI_SWLVL_SM2_START 0x00000258U +#define _reg_PI_SWLVL_SM2_WR 0x00000259U +#define _reg_PI_SWLVL_SM2_RD 0x0000025aU +#define _reg_PI_SEQUENTIAL_LVL_REQ 0x0000025bU +#define _reg_PI_DFS_PERIOD_EN 0x0000025cU +#define _reg_PI_SRE_PERIOD_EN 0x0000025dU +#define _reg_PI_DFI40_POLARITY 0x0000025eU +#define _reg_PI_16BIT_DRAM_CONNECT 0x0000025fU +#define _reg_PI_TDFI_CTRL_DELAY_F0 0x00000260U +#define _reg_PI_TDFI_CTRL_DELAY_F1 0x00000261U +#define _reg_PI_TDFI_CTRL_DELAY_F2 0x00000262U +#define _reg_PI_WRLVL_REQ 0x00000263U +#define _reg_PI_WRLVL_CS 0x00000264U +#define _reg_PI_WLDQSEN 0x00000265U +#define _reg_PI_WLMRD 0x00000266U +#define _reg_PI_WRLVL_EN_F0 0x00000267U +#define _reg_PI_WRLVL_EN_F1 0x00000268U +#define _reg_PI_WRLVL_EN_F2 0x00000269U +#define _reg_PI_WRLVL_EN 0x0000026aU +#define _reg_PI_WRLVL_INTERVAL 0x0000026bU +#define _reg_PI_WRLVL_PERIODIC 0x0000026cU +#define _reg_PI_WRLVL_ON_SREF_EXIT 0x0000026dU +#define _reg_PI_WRLVL_DISABLE_DFS 0x0000026eU +#define _reg_PI_WRLVL_RESP_MASK 0x0000026fU +#define _reg_PI_WRLVL_ROTATE 0x00000270U +#define _reg_PI_WRLVL_CS_MAP 0x00000271U +#define _reg_PI_WRLVL_ERROR_STATUS 0x00000272U +#define _reg_PI_TDFI_WRLVL_EN 0x00000273U +#define _reg_PI_TDFI_WRLVL_WW_F0 0x00000274U +#define _reg_PI_TDFI_WRLVL_WW_F1 0x00000275U +#define _reg_PI_TDFI_WRLVL_WW_F2 0x00000276U +#define _reg_PI_TDFI_WRLVL_WW 0x00000277U +#define _reg_PI_TDFI_WRLVL_RESP 0x00000278U +#define _reg_PI_TDFI_WRLVL_MAX 0x00000279U +#define _reg_PI_WRLVL_STROBE_NUM 0x0000027aU +#define _reg_PI_WRLVL_MRR_DQ_RETURN_HIZ 0x0000027bU +#define _reg_PI_WRLVL_EN_DEASSERT_2_MRR 0x0000027cU +#define _reg_PI_TODTL_2CMD_F0 0x0000027dU +#define _reg_PI_ODT_EN_F0 0x0000027eU +#define _reg_PI_TODTL_2CMD_F1 0x0000027fU +#define _reg_PI_ODT_EN_F1 0x00000280U +#define _reg_PI_TODTL_2CMD_F2 0x00000281U +#define _reg_PI_ODT_EN_F2 0x00000282U +#define _reg_PI_TODTH_WR 0x00000283U +#define _reg_PI_TODTH_RD 0x00000284U +#define _reg_PI_ODT_RD_MAP_CS0 0x00000285U +#define _reg_PI_ODT_WR_MAP_CS0 0x00000286U +#define _reg_PI_ODT_RD_MAP_CS1 0x00000287U +#define _reg_PI_ODT_WR_MAP_CS1 0x00000288U +#define _reg_PI_ODT_RD_MAP_CS2 0x00000289U +#define _reg_PI_ODT_WR_MAP_CS2 0x0000028aU +#define _reg_PI_ODT_RD_MAP_CS3 0x0000028bU +#define _reg_PI_ODT_WR_MAP_CS3 0x0000028cU +#define _reg_PI_EN_ODT_ASSERT_EXCEPT_RD 0x0000028dU +#define _reg_PI_ODTLON_F0 0x0000028eU +#define _reg_PI_TODTON_MIN_F0 0x0000028fU +#define _reg_PI_ODTLON_F1 0x00000290U +#define _reg_PI_TODTON_MIN_F1 0x00000291U +#define _reg_PI_ODTLON_F2 0x00000292U +#define _reg_PI_TODTON_MIN_F2 0x00000293U +#define _reg_PI_WR_TO_ODTH_F0 0x00000294U +#define _reg_PI_WR_TO_ODTH_F1 0x00000295U +#define _reg_PI_WR_TO_ODTH_F2 0x00000296U +#define _reg_PI_RD_TO_ODTH_F0 0x00000297U +#define _reg_PI_RD_TO_ODTH_F1 0x00000298U +#define _reg_PI_RD_TO_ODTH_F2 0x00000299U +#define _reg_PI_ADDRESS_MIRRORING 0x0000029aU +#define _reg_PI_RDLVL_REQ 0x0000029bU +#define _reg_PI_RDLVL_GATE_REQ 0x0000029cU +#define _reg_PI_RDLVL_CS 0x0000029dU +#define _reg_PI_RDLVL_PAT_0 0x0000029eU +#define _reg_PI_RDLVL_PAT_1 0x0000029fU +#define _reg_PI_RDLVL_PAT_2 0x000002a0U +#define _reg_PI_RDLVL_PAT_3 0x000002a1U +#define _reg_PI_RDLVL_PAT_4 0x000002a2U +#define _reg_PI_RDLVL_PAT_5 0x000002a3U +#define _reg_PI_RDLVL_PAT_6 0x000002a4U +#define _reg_PI_RDLVL_PAT_7 0x000002a5U +#define _reg_PI_RDLVL_SEQ_EN 0x000002a6U +#define _reg_PI_RDLVL_GATE_SEQ_EN 0x000002a7U +#define _reg_PI_RDLVL_PERIODIC 0x000002a8U +#define _reg_PI_RDLVL_ON_SREF_EXIT 0x000002a9U +#define _reg_PI_RDLVL_DISABLE_DFS 0x000002aaU +#define _reg_PI_RDLVL_GATE_PERIODIC 0x000002abU +#define _reg_PI_RDLVL_GATE_ON_SREF_EXIT 0x000002acU +#define _reg_PI_RDLVL_GATE_DISABLE_DFS 0x000002adU +#define _reg_RESERVED_R1 0x000002aeU +#define _reg_PI_RDLVL_ROTATE 0x000002afU +#define _reg_PI_RDLVL_GATE_ROTATE 0x000002b0U +#define _reg_PI_RDLVL_CS_MAP 0x000002b1U +#define _reg_PI_RDLVL_GATE_CS_MAP 0x000002b2U +#define _reg_PI_TDFI_RDLVL_RR 0x000002b3U +#define _reg_PI_TDFI_RDLVL_RESP 0x000002b4U +#define _reg_PI_RDLVL_RESP_MASK 0x000002b5U +#define _reg_PI_TDFI_RDLVL_EN 0x000002b6U +#define _reg_PI_RDLVL_EN_F0 0x000002b7U +#define _reg_PI_RDLVL_GATE_EN_F0 0x000002b8U +#define _reg_PI_RDLVL_EN_F1 0x000002b9U +#define _reg_PI_RDLVL_GATE_EN_F1 0x000002baU +#define _reg_PI_RDLVL_EN_F2 0x000002bbU +#define _reg_PI_RDLVL_GATE_EN_F2 0x000002bcU +#define _reg_PI_RDLVL_EN 0x000002bdU +#define _reg_PI_RDLVL_GATE_EN 0x000002beU +#define _reg_PI_TDFI_RDLVL_MAX 0x000002bfU +#define _reg_PI_RDLVL_ERROR_STATUS 0x000002c0U +#define _reg_PI_RDLVL_INTERVAL 0x000002c1U +#define _reg_PI_RDLVL_GATE_INTERVAL 0x000002c2U +#define _reg_PI_RDLVL_PATTERN_START 0x000002c3U +#define _reg_PI_RDLVL_PATTERN_NUM 0x000002c4U +#define _reg_PI_RDLVL_STROBE_NUM 0x000002c5U +#define _reg_PI_RDLVL_GATE_STROBE_NUM 0x000002c6U +#define _reg_PI_LPDDR4_RDLVL_PATTERN_8 0x000002c7U +#define _reg_PI_LPDDR4_RDLVL_PATTERN_9 0x000002c8U +#define _reg_PI_LPDDR4_RDLVL_PATTERN_10 0x000002c9U +#define _reg_PI_LPDDR4_RDLVL_PATTERN_11 0x000002caU +#define _reg_PI_RD_PREAMBLE_TRAINING_EN 0x000002cbU +#define _reg_PI_REG_DIMM_ENABLE 0x000002ccU +#define _reg_PI_RDLAT_ADJ_F0 0x000002cdU +#define _reg_PI_RDLAT_ADJ_F1 0x000002ceU +#define _reg_PI_RDLAT_ADJ_F2 0x000002cfU +#define _reg_PI_TDFI_RDDATA_EN 0x000002d0U +#define _reg_PI_WRLAT_ADJ_F0 0x000002d1U +#define _reg_PI_WRLAT_ADJ_F1 0x000002d2U +#define _reg_PI_WRLAT_ADJ_F2 0x000002d3U +#define _reg_PI_TDFI_PHY_WRLAT 0x000002d4U +#define _reg_PI_TDFI_WRCSLAT_F0 0x000002d5U +#define _reg_PI_TDFI_WRCSLAT_F1 0x000002d6U +#define _reg_PI_TDFI_WRCSLAT_F2 0x000002d7U +#define _reg_PI_TDFI_RDCSLAT_F0 0x000002d8U +#define _reg_PI_TDFI_RDCSLAT_F1 0x000002d9U +#define _reg_PI_TDFI_RDCSLAT_F2 0x000002daU +#define _reg_PI_TDFI_PHY_WRDATA_F0 0x000002dbU +#define _reg_PI_TDFI_PHY_WRDATA_F1 0x000002dcU +#define _reg_PI_TDFI_PHY_WRDATA_F2 0x000002ddU +#define _reg_PI_TDFI_PHY_WRDATA 0x000002deU +#define _reg_PI_CALVL_REQ 0x000002dfU +#define _reg_PI_CALVL_CS 0x000002e0U +#define _reg_RESERVED_R2 0x000002e1U +#define _reg_RESERVED_R3 0x000002e2U +#define _reg_PI_CALVL_SEQ_EN 0x000002e3U +#define _reg_PI_CALVL_PERIODIC 0x000002e4U +#define _reg_PI_CALVL_ON_SREF_EXIT 0x000002e5U +#define _reg_PI_CALVL_DISABLE_DFS 0x000002e6U +#define _reg_PI_CALVL_ROTATE 0x000002e7U +#define _reg_PI_CALVL_CS_MAP 0x000002e8U +#define _reg_PI_TDFI_CALVL_EN 0x000002e9U +#define _reg_PI_TDFI_CALVL_CC_F0 0x000002eaU +#define _reg_PI_TDFI_CALVL_CAPTURE_F0 0x000002ebU +#define _reg_PI_TDFI_CALVL_CC_F1 0x000002ecU +#define _reg_PI_TDFI_CALVL_CAPTURE_F1 0x000002edU +#define _reg_PI_TDFI_CALVL_CC_F2 0x000002eeU +#define _reg_PI_TDFI_CALVL_CAPTURE_F2 0x000002efU +#define _reg_PI_TDFI_CALVL_RESP 0x000002f0U +#define _reg_PI_TDFI_CALVL_MAX 0x000002f1U +#define _reg_PI_CALVL_RESP_MASK 0x000002f2U +#define _reg_PI_CALVL_EN_F0 0x000002f3U +#define _reg_PI_CALVL_EN_F1 0x000002f4U +#define _reg_PI_CALVL_EN_F2 0x000002f5U +#define _reg_PI_CALVL_EN 0x000002f6U +#define _reg_PI_CALVL_ERROR_STATUS 0x000002f7U +#define _reg_PI_CALVL_INTERVAL 0x000002f8U +#define _reg_PI_TCACKEL 0x000002f9U +#define _reg_PI_TCAMRD 0x000002faU +#define _reg_PI_TCACKEH 0x000002fbU +#define _reg_PI_TMRZ_F0 0x000002fcU +#define _reg_PI_TCAENT_F0 0x000002fdU +#define _reg_PI_TMRZ_F1 0x000002feU +#define _reg_PI_TCAENT_F1 0x000002ffU +#define _reg_PI_TMRZ_F2 0x00000300U +#define _reg_PI_TCAENT_F2 0x00000301U +#define _reg_PI_TCAEXT 0x00000302U +#define _reg_PI_CA_TRAIN_VREF_EN 0x00000303U +#define _reg_PI_TDFI_CACSCA_F0 0x00000304U +#define _reg_PI_TDFI_CASEL_F0 0x00000305U +#define _reg_PI_TVREF_SHORT_F0 0x00000306U +#define _reg_PI_TVREF_LONG_F0 0x00000307U +#define _reg_PI_TDFI_CACSCA_F1 0x00000308U +#define _reg_PI_TDFI_CASEL_F1 0x00000309U +#define _reg_PI_TVREF_SHORT_F1 0x0000030aU +#define _reg_PI_TVREF_LONG_F1 0x0000030bU +#define _reg_PI_TDFI_CACSCA_F2 0x0000030cU +#define _reg_PI_TDFI_CASEL_F2 0x0000030dU +#define _reg_PI_TVREF_SHORT_F2 0x0000030eU +#define _reg_PI_TVREF_LONG_F2 0x0000030fU +#define _reg_PI_CALVL_VREF_INITIAL_START_POINT_F0 0x00000310U +#define _reg_PI_CALVL_VREF_INITIAL_STOP_POINT_F0 0x00000311U +#define _reg_PI_CALVL_VREF_INITIAL_START_POINT_F1 0x00000312U +#define _reg_PI_CALVL_VREF_INITIAL_STOP_POINT_F1 0x00000313U +#define _reg_PI_CALVL_VREF_INITIAL_START_POINT_F2 0x00000314U +#define _reg_PI_CALVL_VREF_INITIAL_STOP_POINT_F2 0x00000315U +#define _reg_PI_CALVL_VREF_INITIAL_START_POINT 0x00000316U +#define _reg_PI_CALVL_VREF_INITIAL_STOP_POINT 0x00000317U +#define _reg_PI_CALVL_VREF_INITIAL_STEPSIZE 0x00000318U +#define _reg_PI_CALVL_VREF_NORMAL_STEPSIZE 0x00000319U +#define _reg_PI_CALVL_VREF_DELTA_F0 0x0000031aU +#define _reg_PI_CALVL_VREF_DELTA_F1 0x0000031bU +#define _reg_PI_CALVL_VREF_DELTA_F2 0x0000031cU +#define _reg_PI_CALVL_VREF_DELTA 0x0000031dU +#define _reg_PI_TDFI_INIT_START_MIN 0x0000031eU +#define _reg_PI_TDFI_INIT_COMPLETE_MIN 0x0000031fU +#define _reg_PI_TDFI_CALVL_STROBE_F0 0x00000320U +#define _reg_PI_TXP_F0 0x00000321U +#define _reg_PI_TMRWCKEL_F0 0x00000322U +#define _reg_PI_TCKELCK_F0 0x00000323U +#define _reg_PI_TDFI_CALVL_STROBE_F1 0x00000324U +#define _reg_PI_TXP_F1 0x00000325U +#define _reg_PI_TMRWCKEL_F1 0x00000326U +#define _reg_PI_TCKELCK_F1 0x00000327U +#define _reg_PI_TDFI_CALVL_STROBE_F2 0x00000328U +#define _reg_PI_TXP_F2 0x00000329U +#define _reg_PI_TMRWCKEL_F2 0x0000032aU +#define _reg_PI_TCKELCK_F2 0x0000032bU +#define _reg_PI_TCKCKEH 0x0000032cU +#define _reg_PI_CALVL_STROBE_NUM 0x0000032dU +#define _reg_PI_SW_CA_TRAIN_VREF 0x0000032eU +#define _reg_PI_TDFI_INIT_START_F0 0x0000032fU +#define _reg_PI_TDFI_INIT_COMPLETE_F0 0x00000330U +#define _reg_PI_TDFI_INIT_START_F1 0x00000331U +#define _reg_PI_TDFI_INIT_COMPLETE_F1 0x00000332U +#define _reg_PI_TDFI_INIT_START_F2 0x00000333U +#define _reg_PI_TDFI_INIT_COMPLETE_F2 0x00000334U +#define _reg_PI_CLKDISABLE_2_INIT_START 0x00000335U +#define _reg_PI_INIT_STARTORCOMPLETE_2_CLKDISABLE 0x00000336U +#define _reg_PI_DRAM_CLK_DISABLE_DEASSERT_SEL 0x00000337U +#define _reg_PI_REFRESH_BETWEEN_SEGMENT_DISABLE 0x00000338U +#define _reg_PI_TCKEHDQS_F0 0x00000339U +#define _reg_PI_TCKEHDQS_F1 0x0000033aU +#define _reg_PI_TCKEHDQS_F2 0x0000033bU +#define _reg_PI_MC_DFS_PI_SET_VREF_ENABLE 0x0000033cU +#define _reg_PI_WDQLVL_VREF_EN 0x0000033dU +#define _reg_PI_WDQLVL_BST_NUM 0x0000033eU +#define _reg_PI_TDFI_WDQLVL_WR_F0 0x0000033fU +#define _reg_PI_TDFI_WDQLVL_WR_F1 0x00000340U +#define _reg_PI_TDFI_WDQLVL_WR_F2 0x00000341U +#define _reg_PI_TDFI_WDQLVL_WR 0x00000342U +#define _reg_PI_TDFI_WDQLVL_RW 0x00000343U +#define _reg_PI_WDQLVL_RESP_MASK 0x00000344U +#define _reg_PI_WDQLVL_ROTATE 0x00000345U +#define _reg_PI_WDQLVL_CS_MAP 0x00000346U +#define _reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F0 0x00000347U +#define _reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F0 0x00000348U +#define _reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1 0x00000349U +#define _reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1 0x0000034aU +#define _reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F2 0x0000034bU +#define _reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F2 0x0000034cU +#define _reg_PI_WDQLVL_VREF_INITIAL_START_POINT 0x0000034dU +#define _reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT 0x0000034eU +#define _reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE 0x0000034fU +#define _reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE 0x00000350U +#define _reg_PI_WDQLVL_VREF_DELTA_F0 0x00000351U +#define _reg_PI_WDQLVL_VREF_DELTA_F1 0x00000352U +#define _reg_PI_WDQLVL_VREF_DELTA_F2 0x00000353U +#define _reg_PI_WDQLVL_VREF_DELTA 0x00000354U +#define _reg_PI_WDQLVL_PERIODIC 0x00000355U +#define _reg_PI_WDQLVL_REQ 0x00000356U +#define _reg_PI_WDQLVL_CS 0x00000357U +#define _reg_PI_TDFI_WDQLVL_EN 0x00000358U +#define _reg_PI_TDFI_WDQLVL_RESP 0x00000359U +#define _reg_PI_TDFI_WDQLVL_MAX 0x0000035aU +#define _reg_PI_WDQLVL_INTERVAL 0x0000035bU +#define _reg_PI_WDQLVL_EN_F0 0x0000035cU +#define _reg_PI_WDQLVL_EN_F1 0x0000035dU +#define _reg_PI_WDQLVL_EN_F2 0x0000035eU +#define _reg_PI_WDQLVL_EN 0x0000035fU +#define _reg_PI_WDQLVL_ON_SREF_EXIT 0x00000360U +#define _reg_PI_WDQLVL_DISABLE_DFS 0x00000361U +#define _reg_PI_WDQLVL_ERROR_STATUS 0x00000362U +#define _reg_PI_MR1_DATA_F0_0 0x00000363U +#define _reg_PI_MR2_DATA_F0_0 0x00000364U +#define _reg_PI_MR3_DATA_F0_0 0x00000365U +#define _reg_PI_MR11_DATA_F0_0 0x00000366U +#define _reg_PI_MR12_DATA_F0_0 0x00000367U +#define _reg_PI_MR14_DATA_F0_0 0x00000368U +#define _reg_PI_MR22_DATA_F0_0 0x00000369U +#define _reg_PI_MR1_DATA_F1_0 0x0000036aU +#define _reg_PI_MR2_DATA_F1_0 0x0000036bU +#define _reg_PI_MR3_DATA_F1_0 0x0000036cU +#define _reg_PI_MR11_DATA_F1_0 0x0000036dU +#define _reg_PI_MR12_DATA_F1_0 0x0000036eU +#define _reg_PI_MR14_DATA_F1_0 0x0000036fU +#define _reg_PI_MR22_DATA_F1_0 0x00000370U +#define _reg_PI_MR1_DATA_F2_0 0x00000371U +#define _reg_PI_MR2_DATA_F2_0 0x00000372U +#define _reg_PI_MR3_DATA_F2_0 0x00000373U +#define _reg_PI_MR11_DATA_F2_0 0x00000374U +#define _reg_PI_MR12_DATA_F2_0 0x00000375U +#define _reg_PI_MR14_DATA_F2_0 0x00000376U +#define _reg_PI_MR22_DATA_F2_0 0x00000377U +#define _reg_PI_MR13_DATA_0 0x00000378U +#define _reg_PI_MR1_DATA_F0_1 0x00000379U +#define _reg_PI_MR2_DATA_F0_1 0x0000037aU +#define _reg_PI_MR3_DATA_F0_1 0x0000037bU +#define _reg_PI_MR11_DATA_F0_1 0x0000037cU +#define _reg_PI_MR12_DATA_F0_1 0x0000037dU +#define _reg_PI_MR14_DATA_F0_1 0x0000037eU +#define _reg_PI_MR22_DATA_F0_1 0x0000037fU +#define _reg_PI_MR1_DATA_F1_1 0x00000380U +#define _reg_PI_MR2_DATA_F1_1 0x00000381U +#define _reg_PI_MR3_DATA_F1_1 0x00000382U +#define _reg_PI_MR11_DATA_F1_1 0x00000383U +#define _reg_PI_MR12_DATA_F1_1 0x00000384U +#define _reg_PI_MR14_DATA_F1_1 0x00000385U +#define _reg_PI_MR22_DATA_F1_1 0x00000386U +#define _reg_PI_MR1_DATA_F2_1 0x00000387U +#define _reg_PI_MR2_DATA_F2_1 0x00000388U +#define _reg_PI_MR3_DATA_F2_1 0x00000389U +#define _reg_PI_MR11_DATA_F2_1 0x0000038aU +#define _reg_PI_MR12_DATA_F2_1 0x0000038bU +#define _reg_PI_MR14_DATA_F2_1 0x0000038cU +#define _reg_PI_MR22_DATA_F2_1 0x0000038dU +#define _reg_PI_MR13_DATA_1 0x0000038eU +#define _reg_PI_MR1_DATA_F0_2 0x0000038fU +#define _reg_PI_MR2_DATA_F0_2 0x00000390U +#define _reg_PI_MR3_DATA_F0_2 0x00000391U +#define _reg_PI_MR11_DATA_F0_2 0x00000392U +#define _reg_PI_MR12_DATA_F0_2 0x00000393U +#define _reg_PI_MR14_DATA_F0_2 0x00000394U +#define _reg_PI_MR22_DATA_F0_2 0x00000395U +#define _reg_PI_MR1_DATA_F1_2 0x00000396U +#define _reg_PI_MR2_DATA_F1_2 0x00000397U +#define _reg_PI_MR3_DATA_F1_2 0x00000398U +#define _reg_PI_MR11_DATA_F1_2 0x00000399U +#define _reg_PI_MR12_DATA_F1_2 0x0000039aU +#define _reg_PI_MR14_DATA_F1_2 0x0000039bU +#define _reg_PI_MR22_DATA_F1_2 0x0000039cU +#define _reg_PI_MR1_DATA_F2_2 0x0000039dU +#define _reg_PI_MR2_DATA_F2_2 0x0000039eU +#define _reg_PI_MR3_DATA_F2_2 0x0000039fU +#define _reg_PI_MR11_DATA_F2_2 0x000003a0U +#define _reg_PI_MR12_DATA_F2_2 0x000003a1U +#define _reg_PI_MR14_DATA_F2_2 0x000003a2U +#define _reg_PI_MR22_DATA_F2_2 0x000003a3U +#define _reg_PI_MR13_DATA_2 0x000003a4U +#define _reg_PI_MR1_DATA_F0_3 0x000003a5U +#define _reg_PI_MR2_DATA_F0_3 0x000003a6U +#define _reg_PI_MR3_DATA_F0_3 0x000003a7U +#define _reg_PI_MR11_DATA_F0_3 0x000003a8U +#define _reg_PI_MR12_DATA_F0_3 0x000003a9U +#define _reg_PI_MR14_DATA_F0_3 0x000003aaU +#define _reg_PI_MR22_DATA_F0_3 0x000003abU +#define _reg_PI_MR1_DATA_F1_3 0x000003acU +#define _reg_PI_MR2_DATA_F1_3 0x000003adU +#define _reg_PI_MR3_DATA_F1_3 0x000003aeU +#define _reg_PI_MR11_DATA_F1_3 0x000003afU +#define _reg_PI_MR12_DATA_F1_3 0x000003b0U +#define _reg_PI_MR14_DATA_F1_3 0x000003b1U +#define _reg_PI_MR22_DATA_F1_3 0x000003b2U +#define _reg_PI_MR1_DATA_F2_3 0x000003b3U +#define _reg_PI_MR2_DATA_F2_3 0x000003b4U +#define _reg_PI_MR3_DATA_F2_3 0x000003b5U +#define _reg_PI_MR11_DATA_F2_3 0x000003b6U +#define _reg_PI_MR12_DATA_F2_3 0x000003b7U +#define _reg_PI_MR14_DATA_F2_3 0x000003b8U +#define _reg_PI_MR22_DATA_F2_3 0x000003b9U +#define _reg_PI_MR13_DATA_3 0x000003baU +#define _reg_PI_BANK_DIFF 0x000003bbU +#define _reg_PI_ROW_DIFF 0x000003bcU +#define _reg_PI_TFC_F0 0x000003bdU +#define _reg_PI_TFC_F1 0x000003beU +#define _reg_PI_TFC_F2 0x000003bfU +#define _reg_PI_TCCD 0x000003c0U +#define _reg_PI_TRTP_F0 0x000003c1U +#define _reg_PI_TRP_F0 0x000003c2U +#define _reg_PI_TRCD_F0 0x000003c3U +#define _reg_PI_TWTR_F0 0x000003c4U +#define _reg_PI_TWR_F0 0x000003c5U +#define _reg_PI_TRAS_MAX_F0 0x000003c6U +#define _reg_PI_TRAS_MIN_F0 0x000003c7U +#define _reg_PI_TDQSCK_MAX_F0 0x000003c8U +#define _reg_PI_TCCDMW_F0 0x000003c9U +#define _reg_PI_TSR_F0 0x000003caU +#define _reg_PI_TMRD_F0 0x000003cbU +#define _reg_PI_TMRW_F0 0x000003ccU +#define _reg_PI_TMOD_F0 0x000003cdU +#define _reg_PI_TRTP_F1 0x000003ceU +#define _reg_PI_TRP_F1 0x000003cfU +#define _reg_PI_TRCD_F1 0x000003d0U +#define _reg_PI_TWTR_F1 0x000003d1U +#define _reg_PI_TWR_F1 0x000003d2U +#define _reg_PI_TRAS_MAX_F1 0x000003d3U +#define _reg_PI_TRAS_MIN_F1 0x000003d4U +#define _reg_PI_TDQSCK_MAX_F1 0x000003d5U +#define _reg_PI_TCCDMW_F1 0x000003d6U +#define _reg_PI_TSR_F1 0x000003d7U +#define _reg_PI_TMRD_F1 0x000003d8U +#define _reg_PI_TMRW_F1 0x000003d9U +#define _reg_PI_TMOD_F1 0x000003daU +#define _reg_PI_TRTP_F2 0x000003dbU +#define _reg_PI_TRP_F2 0x000003dcU +#define _reg_PI_TRCD_F2 0x000003ddU +#define _reg_PI_TWTR_F2 0x000003deU +#define _reg_PI_TWR_F2 0x000003dfU +#define _reg_PI_TRAS_MAX_F2 0x000003e0U +#define _reg_PI_TRAS_MIN_F2 0x000003e1U +#define _reg_PI_TDQSCK_MAX_F2 0x000003e2U +#define _reg_PI_TCCDMW_F2 0x000003e3U +#define _reg_PI_TSR_F2 0x000003e4U +#define _reg_PI_TMRD_F2 0x000003e5U +#define _reg_PI_TMRW_F2 0x000003e6U +#define _reg_PI_TMOD_F2 0x000003e7U +#define _reg_RESERVED_R4 0x000003e8U +#define _reg_RESERVED_R5 0x000003e9U +#define _reg_RESERVED_R6 0x000003eaU +#define _reg_RESERVED_R7 0x000003ebU +#define _reg_RESERVED_R8 0x000003ecU +#define _reg_RESERVED_R9 0x000003edU +#define _reg_RESERVED_R10 0x000003eeU +#define _reg_RESERVED_R11 0x000003efU +#define _reg_RESERVED_R12 0x000003f0U +#define _reg_RESERVED_R13 0x000003f1U +#define _reg_RESERVED_R14 0x000003f2U +#define _reg_RESERVED_R15 0x000003f3U +#define _reg_RESERVED_R16 0x000003f4U +#define _reg_RESERVED_R17 0x000003f5U +#define _reg_RESERVED_R18 0x000003f6U +#define _reg_RESERVED_R19 0x000003f7U +#define _reg_RESERVED_R20 0x000003f8U +#define _reg_RESERVED_R21 0x000003f9U +#define _reg_RESERVED_R22 0x000003faU +#define _reg_RESERVED_R23 0x000003fbU +#define _reg_PI_INT_STATUS 0x000003fcU +#define _reg_PI_INT_ACK 0x000003fdU +#define _reg_PI_INT_MASK 0x000003feU +#define _reg_PI_BIST_EXP_DATA_P0 0x000003ffU +#define _reg_PI_BIST_EXP_DATA_P1 0x00000400U +#define _reg_PI_BIST_EXP_DATA_P2 0x00000401U +#define _reg_PI_BIST_EXP_DATA_P3 0x00000402U +#define _reg_PI_BIST_FAIL_DATA_P0 0x00000403U +#define _reg_PI_BIST_FAIL_DATA_P1 0x00000404U +#define _reg_PI_BIST_FAIL_DATA_P2 0x00000405U +#define _reg_PI_BIST_FAIL_DATA_P3 0x00000406U +#define _reg_PI_BIST_FAIL_ADDR_P0 0x00000407U +#define _reg_PI_BIST_FAIL_ADDR_P1 0x00000408U +#define _reg_PI_BSTLEN 0x00000409U +#define _reg_PI_LONG_COUNT_MASK 0x0000040aU +#define _reg_PI_CMD_SWAP_EN 0x0000040bU +#define _reg_PI_CKE_MUX_0 0x0000040cU +#define _reg_PI_CKE_MUX_1 0x0000040dU +#define _reg_PI_CKE_MUX_2 0x0000040eU +#define _reg_PI_CKE_MUX_3 0x0000040fU +#define _reg_PI_CS_MUX_0 0x00000410U +#define _reg_PI_CS_MUX_1 0x00000411U +#define _reg_PI_CS_MUX_2 0x00000412U +#define _reg_PI_CS_MUX_3 0x00000413U +#define _reg_PI_RAS_N_MUX 0x00000414U +#define _reg_PI_CAS_N_MUX 0x00000415U +#define _reg_PI_WE_N_MUX 0x00000416U +#define _reg_PI_BANK_MUX_0 0x00000417U +#define _reg_PI_BANK_MUX_1 0x00000418U +#define _reg_PI_BANK_MUX_2 0x00000419U +#define _reg_PI_ODT_MUX_0 0x0000041aU +#define _reg_PI_ODT_MUX_1 0x0000041bU +#define _reg_PI_ODT_MUX_2 0x0000041cU +#define _reg_PI_ODT_MUX_3 0x0000041dU +#define _reg_PI_RESET_N_MUX_0 0x0000041eU +#define _reg_PI_RESET_N_MUX_1 0x0000041fU +#define _reg_PI_RESET_N_MUX_2 0x00000420U +#define _reg_PI_RESET_N_MUX_3 0x00000421U +#define _reg_PI_DATA_BYTE_SWAP_EN 0x00000422U +#define _reg_PI_DATA_BYTE_SWAP_SLICE0 0x00000423U +#define _reg_PI_DATA_BYTE_SWAP_SLICE1 0x00000424U +#define _reg_PI_DATA_BYTE_SWAP_SLICE2 0x00000425U +#define _reg_PI_DATA_BYTE_SWAP_SLICE3 0x00000426U +#define _reg_PI_CTRLUPD_REQ_PER_AREF_EN 0x00000427U +#define _reg_PI_TDFI_CTRLUPD_MIN 0x00000428U +#define _reg_PI_TDFI_CTRLUPD_MAX_F0 0x00000429U +#define _reg_PI_TDFI_CTRLUPD_INTERVAL_F0 0x0000042aU +#define _reg_PI_TDFI_CTRLUPD_MAX_F1 0x0000042bU +#define _reg_PI_TDFI_CTRLUPD_INTERVAL_F1 0x0000042cU +#define _reg_PI_TDFI_CTRLUPD_MAX_F2 0x0000042dU +#define _reg_PI_TDFI_CTRLUPD_INTERVAL_F2 0x0000042eU +#define _reg_PI_UPDATE_ERROR_STATUS 0x0000042fU +#define _reg_PI_BIST_GO 0x00000430U +#define _reg_PI_BIST_RESULT 0x00000431U +#define _reg_PI_ADDR_SPACE 0x00000432U +#define _reg_PI_BIST_DATA_CHECK 0x00000433U +#define _reg_PI_BIST_ADDR_CHECK 0x00000434U +#define _reg_PI_BIST_START_ADDRESS_P0 0x00000435U +#define _reg_PI_BIST_START_ADDRESS_P1 0x00000436U +#define _reg_PI_BIST_DATA_MASK_P0 0x00000437U +#define _reg_PI_BIST_DATA_MASK_P1 0x00000438U +#define _reg_PI_BIST_ERR_COUNT 0x00000439U +#define _reg_PI_BIST_ERR_STOP 0x0000043aU +#define _reg_PI_BIST_ADDR_MASK_0_P0 0x0000043bU +#define _reg_PI_BIST_ADDR_MASK_0_P1 0x0000043cU +#define _reg_PI_BIST_ADDR_MASK_1_P0 0x0000043dU +#define _reg_PI_BIST_ADDR_MASK_1_P1 0x0000043eU +#define _reg_PI_BIST_ADDR_MASK_2_P0 0x0000043fU +#define _reg_PI_BIST_ADDR_MASK_2_P1 0x00000440U +#define _reg_PI_BIST_ADDR_MASK_3_P0 0x00000441U +#define _reg_PI_BIST_ADDR_MASK_3_P1 0x00000442U +#define _reg_PI_BIST_ADDR_MASK_4_P0 0x00000443U +#define _reg_PI_BIST_ADDR_MASK_4_P1 0x00000444U +#define _reg_PI_BIST_ADDR_MASK_5_P0 0x00000445U +#define _reg_PI_BIST_ADDR_MASK_5_P1 0x00000446U +#define _reg_PI_BIST_ADDR_MASK_6_P0 0x00000447U +#define _reg_PI_BIST_ADDR_MASK_6_P1 0x00000448U +#define _reg_PI_BIST_ADDR_MASK_7_P0 0x00000449U +#define _reg_PI_BIST_ADDR_MASK_7_P1 0x0000044aU +#define _reg_PI_BIST_ADDR_MASK_8_P0 0x0000044bU +#define _reg_PI_BIST_ADDR_MASK_8_P1 0x0000044cU +#define _reg_PI_BIST_ADDR_MASK_9_P0 0x0000044dU +#define _reg_PI_BIST_ADDR_MASK_9_P1 0x0000044eU +#define _reg_PI_BIST_MODE 0x0000044fU +#define _reg_PI_BIST_ADDR_MODE 0x00000450U +#define _reg_PI_BIST_PAT_MODE 0x00000451U +#define _reg_PI_BIST_USER_PAT_P0 0x00000452U +#define _reg_PI_BIST_USER_PAT_P1 0x00000453U +#define _reg_PI_BIST_USER_PAT_P2 0x00000454U +#define _reg_PI_BIST_USER_PAT_P3 0x00000455U +#define _reg_PI_BIST_PAT_NUM 0x00000456U +#define _reg_PI_BIST_STAGE_0 0x00000457U +#define _reg_PI_BIST_STAGE_1 0x00000458U +#define _reg_PI_BIST_STAGE_2 0x00000459U +#define _reg_PI_BIST_STAGE_3 0x0000045aU +#define _reg_PI_BIST_STAGE_4 0x0000045bU +#define _reg_PI_BIST_STAGE_5 0x0000045cU +#define _reg_PI_BIST_STAGE_6 0x0000045dU +#define _reg_PI_BIST_STAGE_7 0x0000045eU +#define _reg_PI_COL_DIFF 0x0000045fU +#define _reg_PI_SELF_REFRESH_EN 0x00000460U +#define _reg_PI_TXSR_F0 0x00000461U +#define _reg_PI_TXSR_F1 0x00000462U +#define _reg_PI_TXSR_F2 0x00000463U +#define _reg_PI_MONITOR_SRC_SEL_0 0x00000464U +#define _reg_PI_MONITOR_CAP_SEL_0 0x00000465U +#define _reg_PI_MONITOR_0 0x00000466U +#define _reg_PI_MONITOR_SRC_SEL_1 0x00000467U +#define _reg_PI_MONITOR_CAP_SEL_1 0x00000468U +#define _reg_PI_MONITOR_1 0x00000469U +#define _reg_PI_MONITOR_SRC_SEL_2 0x0000046aU +#define _reg_PI_MONITOR_CAP_SEL_2 0x0000046bU +#define _reg_PI_MONITOR_2 0x0000046cU +#define _reg_PI_MONITOR_SRC_SEL_3 0x0000046dU +#define _reg_PI_MONITOR_CAP_SEL_3 0x0000046eU +#define _reg_PI_MONITOR_3 0x0000046fU +#define _reg_PI_MONITOR_SRC_SEL_4 0x00000470U +#define _reg_PI_MONITOR_CAP_SEL_4 0x00000471U +#define _reg_PI_MONITOR_4 0x00000472U +#define _reg_PI_MONITOR_SRC_SEL_5 0x00000473U +#define _reg_PI_MONITOR_CAP_SEL_5 0x00000474U +#define _reg_PI_MONITOR_5 0x00000475U +#define _reg_PI_MONITOR_SRC_SEL_6 0x00000476U +#define _reg_PI_MONITOR_CAP_SEL_6 0x00000477U +#define _reg_PI_MONITOR_6 0x00000478U +#define _reg_PI_MONITOR_SRC_SEL_7 0x00000479U +#define _reg_PI_MONITOR_CAP_SEL_7 0x0000047aU +#define _reg_PI_MONITOR_7 0x0000047bU +#define _reg_PI_MONITOR_STROBE 0x0000047cU +#define _reg_PI_DLL_LOCK 0x0000047dU +#define _reg_PI_FREQ_NUMBER_STATUS 0x0000047eU +#define _reg_RESERVED_R24 0x0000047fU +#define _reg_PI_PHYMSTR_TYPE 0x00000480U +#define _reg_PI_POWER_REDUC_EN 0x00000481U +#define _reg_RESERVED_R25 0x00000482U +#define _reg_RESERVED_R26 0x00000483U +#define _reg_RESERVED_R27 0x00000484U +#define _reg_RESERVED_R28 0x00000485U +#define _reg_RESERVED_R29 0x00000486U +#define _reg_RESERVED_R30 0x00000487U +#define _reg_RESERVED_R31 0x00000488U +#define _reg_RESERVED_R32 0x00000489U +#define _reg_RESERVED_R33 0x0000048aU +#define _reg_RESERVED_R34 0x0000048bU +#define _reg_RESERVED_R35 0x0000048cU +#define _reg_RESERVED_R36 0x0000048dU +#define _reg_RESERVED_R37 0x0000048eU +#define _reg_RESERVED_R38 0x0000048fU +#define _reg_RESERVED_R39 0x00000490U +#define _reg_PI_WRLVL_MAX_STROBE_PEND 0x00000491U +#define _reg_PI_TSDO_F0 0x00000492U +#define _reg_PI_TSDO_F1 0x00000493U +#define _reg_PI_TSDO_F2 0x00000494U + +#define DDR_REGDEF_ADR(regdef) ((regdef) & 0xffff) +#define DDR_REGDEF_LEN(regdef) (((regdef) >> 16) & 0xff) +#define DDR_REGDEF_LSB(regdef) (((regdef) >> 24) & 0xff) + +static const uint32_t DDR_REGDEF_TBL[4][1173] = { + { +/*0000*/ 0xffffffffU, +/*0001*/ 0xffffffffU, +/*0002*/ 0x000b0400U, +/*0003*/ 0xffffffffU, +/*0004*/ 0xffffffffU, +/*0005*/ 0x10010400U, +/*0006*/ 0x18050400U, +/*0007*/ 0x00050401U, +/*0008*/ 0x08050401U, +/*0009*/ 0x10050401U, +/*000a*/ 0x18050401U, +/*000b*/ 0x00050402U, +/*000c*/ 0x08050402U, +/*000d*/ 0x10050402U, +/*000e*/ 0x18050402U, +/*000f*/ 0x00040403U, +/*0010*/ 0x08030403U, +/*0011*/ 0x00180404U, +/*0012*/ 0x18030404U, +/*0013*/ 0x00180405U, +/*0014*/ 0x18020405U, +/*0015*/ 0x00010406U, +/*0016*/ 0x08020406U, +/*0017*/ 0x10010406U, +/*0018*/ 0x18010406U, +/*0019*/ 0x00020407U, +/*001a*/ 0x08040407U, +/*001b*/ 0x10040407U, +/*001c*/ 0x18040407U, +/*001d*/ 0x000a0408U, +/*001e*/ 0x10040408U, +/*001f*/ 0xffffffffU, +/*0020*/ 0xffffffffU, +/*0021*/ 0x18070408U, +/*0022*/ 0xffffffffU, +/*0023*/ 0xffffffffU, +/*0024*/ 0xffffffffU, +/*0025*/ 0xffffffffU, +/*0026*/ 0xffffffffU, +/*0027*/ 0xffffffffU, +/*0028*/ 0x000a0409U, +/*0029*/ 0x10040409U, +/*002a*/ 0x18010409U, +/*002b*/ 0x0001040aU, +/*002c*/ 0x0802040aU, +/*002d*/ 0x1009040aU, +/*002e*/ 0x0009040bU, +/*002f*/ 0x1002040bU, +/*0030*/ 0x0020040cU, +/*0031*/ 0xffffffffU, +/*0032*/ 0x0001040dU, +/*0033*/ 0xffffffffU, +/*0034*/ 0xffffffffU, +/*0035*/ 0xffffffffU, +/*0036*/ 0xffffffffU, +/*0037*/ 0x0020040eU, +/*0038*/ 0x0020040fU, +/*0039*/ 0x00200410U, +/*003a*/ 0x00200411U, +/*003b*/ 0x00030412U, +/*003c*/ 0x08010412U, +/*003d*/ 0x10030412U, +/*003e*/ 0x18030412U, +/*003f*/ 0x00040413U, +/*0040*/ 0x08040413U, +/*0041*/ 0x10040413U, +/*0042*/ 0x18040413U, +/*0043*/ 0x00010414U, +/*0044*/ 0x08010414U, +/*0045*/ 0x10060414U, +/*0046*/ 0x18040414U, +/*0047*/ 0xffffffffU, +/*0048*/ 0x00060415U, +/*0049*/ 0x08040415U, +/*004a*/ 0x10060415U, +/*004b*/ 0x18040415U, +/*004c*/ 0x00020416U, +/*004d*/ 0x08050416U, +/*004e*/ 0x10080416U, +/*004f*/ 0x00200417U, +/*0050*/ 0x00060418U, +/*0051*/ 0x08030418U, +/*0052*/ 0x100b0418U, +/*0053*/ 0x00040419U, +/*0054*/ 0x08040419U, +/*0055*/ 0x10040419U, +/*0056*/ 0xffffffffU, +/*0057*/ 0x18010419U, +/*0058*/ 0x0009041aU, +/*0059*/ 0x0020041bU, +/*005a*/ 0x0020041cU, +/*005b*/ 0x0020041dU, +/*005c*/ 0x0020041eU, +/*005d*/ 0x0010041fU, +/*005e*/ 0x00200420U, +/*005f*/ 0x00010421U, +/*0060*/ 0x08060421U, +/*0061*/ 0x10080421U, +/*0062*/ 0x00200422U, +/*0063*/ 0xffffffffU, +/*0064*/ 0x000a0423U, +/*0065*/ 0x10060423U, +/*0066*/ 0x18070423U, +/*0067*/ 0x00080424U, +/*0068*/ 0x08080424U, +/*0069*/ 0x100a0424U, +/*006a*/ 0x00070425U, +/*006b*/ 0x08080425U, +/*006c*/ 0x10080425U, +/*006d*/ 0x18030425U, +/*006e*/ 0x000a0426U, +/*006f*/ 0x100a0426U, +/*0070*/ 0x00110427U, +/*0071*/ 0x00090428U, +/*0072*/ 0x10090428U, +/*0073*/ 0x00100429U, +/*0074*/ 0x100e0429U, +/*0075*/ 0x000e042aU, +/*0076*/ 0x100c042aU, +/*0077*/ 0x000a042bU, +/*0078*/ 0x100a042bU, +/*0079*/ 0x0002042cU, +/*007a*/ 0x0020042dU, +/*007b*/ 0x000b042eU, +/*007c*/ 0x100b042eU, +/*007d*/ 0x0020042fU, +/*007e*/ 0x00120430U, +/*007f*/ 0x00200431U, +/*0080*/ 0x00200432U, +/*0081*/ 0xffffffffU, +/*0082*/ 0xffffffffU, +/*0083*/ 0x00010433U, +/*0084*/ 0x08010433U, +/*0085*/ 0x10080433U, +/*0086*/ 0x000c0434U, +/*0087*/ 0x100c0434U, +/*0088*/ 0x000c0435U, +/*0089*/ 0x100c0435U, +/*008a*/ 0x000c0436U, +/*008b*/ 0x100c0436U, +/*008c*/ 0x000c0437U, +/*008d*/ 0x100c0437U, +/*008e*/ 0x000c0438U, +/*008f*/ 0x100c0438U, +/*0090*/ 0x000c0439U, +/*0091*/ 0x100b0439U, +/*0092*/ 0xffffffffU, +/*0093*/ 0xffffffffU, +/*0094*/ 0x000b043aU, +/*0095*/ 0x100b043aU, +/*0096*/ 0x000b043bU, +/*0097*/ 0x100b043bU, +/*0098*/ 0x000b043cU, +/*0099*/ 0x100b043cU, +/*009a*/ 0x000b043dU, +/*009b*/ 0x100b043dU, +/*009c*/ 0x000b043eU, +/*009d*/ 0x100a043eU, +/*009e*/ 0xffffffffU, +/*009f*/ 0x000a043fU, +/*00a0*/ 0x100a043fU, +/*00a1*/ 0x000a0440U, +/*00a2*/ 0x100a0440U, +/*00a3*/ 0x000a0441U, +/*00a4*/ 0x100a0441U, +/*00a5*/ 0x000a0442U, +/*00a6*/ 0x100a0442U, +/*00a7*/ 0xffffffffU, +/*00a8*/ 0x000a0443U, +/*00a9*/ 0x100a0443U, +/*00aa*/ 0x000a0444U, +/*00ab*/ 0x100a0444U, +/*00ac*/ 0x000a0445U, +/*00ad*/ 0x100a0445U, +/*00ae*/ 0x000a0446U, +/*00af*/ 0x100a0446U, +/*00b0*/ 0x000a0447U, +/*00b1*/ 0x100a0447U, +/*00b2*/ 0x000a0448U, +/*00b3*/ 0x100a0448U, +/*00b4*/ 0x000a0449U, +/*00b5*/ 0x100a0449U, +/*00b6*/ 0x000a044aU, +/*00b7*/ 0x100a044aU, +/*00b8*/ 0x000a044bU, +/*00b9*/ 0x100a044bU, +/*00ba*/ 0x000a044cU, +/*00bb*/ 0x1004044cU, +/*00bc*/ 0x1803044cU, +/*00bd*/ 0x000a044dU, +/*00be*/ 0x100a044dU, +/*00bf*/ 0x0001044eU, +/*00c0*/ 0x080a044eU, +/*00c1*/ 0x1804044eU, +/*00c2*/ 0x000b044fU, +/*00c3*/ 0x100a044fU, +/*00c4*/ 0xffffffffU, +/*00c5*/ 0x00080450U, +/*00c6*/ 0x08080450U, +/*00c7*/ 0x10080450U, +/*00c8*/ 0x18080450U, +/*00c9*/ 0x00080451U, +/*00ca*/ 0xffffffffU, +/*00cb*/ 0x08080451U, +/*00cc*/ 0x10010451U, +/*00cd*/ 0x18080451U, +/*00ce*/ 0x00080452U, +/*00cf*/ 0x08020452U, +/*00d0*/ 0x10020452U, +/*00d1*/ 0x18040452U, +/*00d2*/ 0x00040453U, +/*00d3*/ 0xffffffffU, +/*00d4*/ 0x08040453U, +/*00d5*/ 0x100a0453U, +/*00d6*/ 0x00060454U, +/*00d7*/ 0x08080454U, +/*00d8*/ 0xffffffffU, +/*00d9*/ 0x10040454U, +/*00da*/ 0x18040454U, +/*00db*/ 0x00050455U, +/*00dc*/ 0x08040455U, +/*00dd*/ 0x10050455U, +/*00de*/ 0x000a0456U, +/*00df*/ 0x100a0456U, +/*00e0*/ 0x00080457U, +/*00e1*/ 0xffffffffU, +/*00e2*/ 0x08040457U, +/*00e3*/ 0xffffffffU, +/*00e4*/ 0xffffffffU, +/*00e5*/ 0x00050600U, +/*00e6*/ 0x08050600U, +/*00e7*/ 0x10050600U, +/*00e8*/ 0x18050600U, +/*00e9*/ 0x00050601U, +/*00ea*/ 0x08050601U, +/*00eb*/ 0x100b0601U, +/*00ec*/ 0x00010602U, +/*00ed*/ 0x08030602U, +/*00ee*/ 0x00200603U, +/*00ef*/ 0xffffffffU, +/*00f0*/ 0x00030604U, +/*00f1*/ 0x080a0604U, +/*00f2*/ 0xffffffffU, +/*00f3*/ 0xffffffffU, +/*00f4*/ 0x18030604U, +/*00f5*/ 0x00030605U, +/*00f6*/ 0x08010605U, +/*00f7*/ 0x10010605U, +/*00f8*/ 0x18060605U, +/*00f9*/ 0xffffffffU, +/*00fa*/ 0xffffffffU, +/*00fb*/ 0xffffffffU, +/*00fc*/ 0x00020606U, +/*00fd*/ 0x08030606U, +/*00fe*/ 0x10010606U, +/*00ff*/ 0x000f0607U, +/*0100*/ 0x00200608U, +/*0101*/ 0x00200609U, +/*0102*/ 0x000b060aU, +/*0103*/ 0x100b060aU, +/*0104*/ 0x000b060bU, +/*0105*/ 0xffffffffU, +/*0106*/ 0xffffffffU, +/*0107*/ 0x0018060cU, +/*0108*/ 0x0018060dU, +/*0109*/ 0x0018060eU, +/*010a*/ 0x0018060fU, +/*010b*/ 0x1804060fU, +/*010c*/ 0x00050610U, +/*010d*/ 0x08020610U, +/*010e*/ 0x10040610U, +/*010f*/ 0x18040610U, +/*0110*/ 0x00010611U, +/*0111*/ 0x08010611U, +/*0112*/ 0x10010611U, +/*0113*/ 0x18030611U, +/*0114*/ 0x00200612U, +/*0115*/ 0x00200613U, +/*0116*/ 0x00010614U, +/*0117*/ 0x08140614U, +/*0118*/ 0x00140615U, +/*0119*/ 0x00140616U, +/*011a*/ 0x00140617U, +/*011b*/ 0x00140618U, +/*011c*/ 0x00140619U, +/*011d*/ 0x0014061aU, +/*011e*/ 0x0014061bU, +/*011f*/ 0x0018061cU, +/*0120*/ 0x000a061dU, +/*0121*/ 0x1006061dU, +/*0122*/ 0x1806061dU, +/*0123*/ 0x0006061eU, +/*0124*/ 0xffffffffU, +/*0125*/ 0xffffffffU, +/*0126*/ 0x0008061fU, +/*0127*/ 0x080b061fU, +/*0128*/ 0x000b0620U, +/*0129*/ 0x100b0620U, +/*012a*/ 0x000b0621U, +/*012b*/ 0x100b0621U, +/*012c*/ 0x000b0622U, +/*012d*/ 0x10040622U, +/*012e*/ 0x000a0623U, +/*012f*/ 0x10060623U, +/*0130*/ 0x18080623U, +/*0131*/ 0xffffffffU, +/*0132*/ 0x00040624U, +/*0133*/ 0xffffffffU, +/*0134*/ 0xffffffffU, +/*0135*/ 0x00010700U, +/*0136*/ 0x08020700U, +/*0137*/ 0x10050700U, +/*0138*/ 0x18050700U, +/*0139*/ 0x00050701U, +/*013a*/ 0x08050701U, +/*013b*/ 0x100b0701U, +/*013c*/ 0x00050702U, +/*013d*/ 0x08010702U, +/*013e*/ 0x10010702U, +/*013f*/ 0xffffffffU, +/*0140*/ 0x18010702U, +/*0141*/ 0x00010703U, +/*0142*/ 0x08040703U, +/*0143*/ 0x100b0703U, +/*0144*/ 0x000b0704U, +/*0145*/ 0xffffffffU, +/*0146*/ 0x10040704U, +/*0147*/ 0x000b0705U, +/*0148*/ 0x10040705U, +/*0149*/ 0x18010705U, +/*014a*/ 0x00010706U, +/*014b*/ 0x08010706U, +/*014c*/ 0x00200707U, +/*014d*/ 0x00200708U, +/*014e*/ 0x00080709U, +/*014f*/ 0x080a0709U, +/*0150*/ 0x18050709U, +/*0151*/ 0x000a070aU, +/*0152*/ 0x1003070aU, +/*0153*/ 0x1803070aU, +/*0154*/ 0x0001070bU, +/*0155*/ 0x0802070bU, +/*0156*/ 0x1001070bU, +/*0157*/ 0x1801070bU, +/*0158*/ 0x0001070cU, +/*0159*/ 0x0802070cU, +/*015a*/ 0xffffffffU, +/*015b*/ 0xffffffffU, +/*015c*/ 0xffffffffU, +/*015d*/ 0xffffffffU, +/*015e*/ 0xffffffffU, +/*015f*/ 0xffffffffU, +/*0160*/ 0xffffffffU, +/*0161*/ 0xffffffffU, +/*0162*/ 0xffffffffU, +/*0163*/ 0xffffffffU, +/*0164*/ 0xffffffffU, +/*0165*/ 0xffffffffU, +/*0166*/ 0x1001070cU, +/*0167*/ 0x1801070cU, +/*0168*/ 0x000d070dU, +/*0169*/ 0xffffffffU, +/*016a*/ 0xffffffffU, +/*016b*/ 0x0005070eU, +/*016c*/ 0x0001070fU, +/*016d*/ 0x080e070fU, +/*016e*/ 0x000e0710U, +/*016f*/ 0x100e0710U, +/*0170*/ 0x000e0711U, +/*0171*/ 0x100e0711U, +/*0172*/ 0x00040712U, +/*0173*/ 0xffffffffU, +/*0174*/ 0xffffffffU, +/*0175*/ 0xffffffffU, +/*0176*/ 0xffffffffU, +/*0177*/ 0x080b0712U, +/*0178*/ 0x000b0713U, +/*0179*/ 0x100b0713U, +/*017a*/ 0x000b0714U, +/*017b*/ 0xffffffffU, +/*017c*/ 0xffffffffU, +/*017d*/ 0xffffffffU, +/*017e*/ 0xffffffffU, +/*017f*/ 0x000d0715U, +/*0180*/ 0xffffffffU, +/*0181*/ 0xffffffffU, +/*0182*/ 0x10100715U, +/*0183*/ 0x00080716U, +/*0184*/ 0xffffffffU, +/*0185*/ 0x08100716U, +/*0186*/ 0x00100717U, +/*0187*/ 0x10100717U, +/*0188*/ 0x00100718U, +/*0189*/ 0x10100718U, +/*018a*/ 0x00030719U, +/*018b*/ 0x08040719U, +/*018c*/ 0x10010719U, +/*018d*/ 0x18040719U, +/*018e*/ 0xffffffffU, +/*018f*/ 0xffffffffU, +/*0190*/ 0x0001071aU, +/*0191*/ 0x0812071aU, +/*0192*/ 0x000a071bU, +/*0193*/ 0x100c071bU, +/*0194*/ 0x0012071cU, +/*0195*/ 0x0014071dU, +/*0196*/ 0x0012071eU, +/*0197*/ 0x0011071fU, +/*0198*/ 0x00110720U, +/*0199*/ 0x00120721U, +/*019a*/ 0x00120722U, +/*019b*/ 0x00120723U, +/*019c*/ 0x00120724U, +/*019d*/ 0x00120725U, +/*019e*/ 0x00120726U, +/*019f*/ 0x00120727U, +/*01a0*/ 0x00120728U, +/*01a1*/ 0xffffffffU, +/*01a2*/ 0xffffffffU, +/*01a3*/ 0x00190729U, +/*01a4*/ 0x0019072aU, +/*01a5*/ 0x0020072bU, +/*01a6*/ 0x0017072cU, +/*01a7*/ 0x1808072cU, +/*01a8*/ 0x0001072dU, +/*01a9*/ 0x0801072dU, +/*01aa*/ 0x0020072eU, +/*01ab*/ 0x0008072fU, +/*01ac*/ 0xffffffffU, +/*01ad*/ 0x0803072fU, +/*01ae*/ 0x00180730U, +/*01af*/ 0x00180731U, +/*01b0*/ 0xffffffffU, +/*01b1*/ 0xffffffffU, +/*01b2*/ 0xffffffffU, +/*01b3*/ 0xffffffffU, +/*01b4*/ 0xffffffffU, +/*01b5*/ 0xffffffffU, +/*01b6*/ 0xffffffffU, +/*01b7*/ 0xffffffffU, +/*01b8*/ 0xffffffffU, +/*01b9*/ 0xffffffffU, +/*01ba*/ 0xffffffffU, +/*01bb*/ 0xffffffffU, +/*01bc*/ 0xffffffffU, +/*01bd*/ 0xffffffffU, +/*01be*/ 0xffffffffU, +/*01bf*/ 0x00100732U, +/*01c0*/ 0x10010732U, +/*01c1*/ 0x18010732U, +/*01c2*/ 0x00050733U, +/*01c3*/ 0x00200734U, +/*01c4*/ 0x00090735U, +/*01c5*/ 0xffffffffU, +/*01c6*/ 0xffffffffU, +/*01c7*/ 0x00200736U, +/*01c8*/ 0x00040737U, +/*01c9*/ 0x08100737U, +/*01ca*/ 0x18060737U, +/*01cb*/ 0x00100738U, +/*01cc*/ 0xffffffffU, +/*01cd*/ 0xffffffffU, +/*01ce*/ 0xffffffffU, +/*01cf*/ 0xffffffffU, +/*01d0*/ 0xffffffffU, +/*01d1*/ 0xffffffffU, +/*01d2*/ 0xffffffffU, +/*01d3*/ 0xffffffffU, +/*01d4*/ 0x00200739U, +/*01d5*/ 0x000b073aU, +/*01d6*/ 0xffffffffU, +/*01d7*/ 0xffffffffU, +/*01d8*/ 0xffffffffU, +/*01d9*/ 0xffffffffU, +/*01da*/ 0xffffffffU, +/*01db*/ 0xffffffffU, +/*01dc*/ 0xffffffffU, +/*01dd*/ 0xffffffffU, +/*01de*/ 0x00010200U, +/*01df*/ 0x08040200U, +/*01e0*/ 0x10100200U, +/*01e1*/ 0x00010201U, +/*01e2*/ 0x08010201U, +/*01e3*/ 0xffffffffU, +/*01e4*/ 0xffffffffU, +/*01e5*/ 0x10100201U, +/*01e6*/ 0xffffffffU, +/*01e7*/ 0xffffffffU, +/*01e8*/ 0xffffffffU, +/*01e9*/ 0xffffffffU, +/*01ea*/ 0xffffffffU, +/*01eb*/ 0xffffffffU, +/*01ec*/ 0xffffffffU, +/*01ed*/ 0xffffffffU, +/*01ee*/ 0xffffffffU, +/*01ef*/ 0x00200202U, +/*01f0*/ 0x00100203U, +/*01f1*/ 0x00200204U, +/*01f2*/ 0x00100205U, +/*01f3*/ 0x00200206U, +/*01f4*/ 0x00100207U, +/*01f5*/ 0x10100207U, +/*01f6*/ 0x00200208U, +/*01f7*/ 0x00200209U, +/*01f8*/ 0x0020020aU, +/*01f9*/ 0x0020020bU, +/*01fa*/ 0x0010020cU, +/*01fb*/ 0x0020020dU, +/*01fc*/ 0x0020020eU, +/*01fd*/ 0x0020020fU, +/*01fe*/ 0x00200210U, +/*01ff*/ 0x00100211U, +/*0200*/ 0x00200212U, +/*0201*/ 0x00200213U, +/*0202*/ 0x00200214U, +/*0203*/ 0x00200215U, +/*0204*/ 0x00090216U, +/*0205*/ 0x10010216U, +/*0206*/ 0x00200217U, +/*0207*/ 0x00050218U, +/*0208*/ 0x08010218U, +/*0209*/ 0x10080218U, +/*020a*/ 0x18080218U, +/*020b*/ 0x001c0219U, +/*020c*/ 0x001c021aU, +/*020d*/ 0x001c021bU, +/*020e*/ 0x001c021cU, +/*020f*/ 0x001c021dU, +/*0210*/ 0x001c021eU, +/*0211*/ 0x001c021fU, +/*0212*/ 0x001c0220U, +/*0213*/ 0x001c0221U, +/*0214*/ 0x001c0222U, +/*0215*/ 0x001c0223U, +/*0216*/ 0x001c0224U, +/*0217*/ 0x001c0225U, +/*0218*/ 0x001c0226U, +/*0219*/ 0x001c0227U, +/*021a*/ 0x001c0228U, +/*021b*/ 0x00010229U, +/*021c*/ 0x08010229U, +/*021d*/ 0x10010229U, +/*021e*/ 0x18040229U, +/*021f*/ 0x0008022aU, +/*0220*/ 0x0808022aU, +/*0221*/ 0x1008022aU, +/*0222*/ 0x1804022aU, +/*0223*/ 0x0006022bU, +/*0224*/ 0xffffffffU, +/*0225*/ 0x0807022bU, +/*0226*/ 0x1006022bU, +/*0227*/ 0xffffffffU, +/*0228*/ 0x1807022bU, +/*0229*/ 0x0006022cU, +/*022a*/ 0xffffffffU, +/*022b*/ 0x0807022cU, +/*022c*/ 0x1002022cU, +/*022d*/ 0x1801022cU, +/*022e*/ 0xffffffffU, +/*022f*/ 0x000a022dU, +/*0230*/ 0x1010022dU, +/*0231*/ 0x000a022eU, +/*0232*/ 0x1010022eU, +/*0233*/ 0x000a022fU, +/*0234*/ 0x1010022fU, +/*0235*/ 0xffffffffU, +/*0236*/ 0x00100230U, +/*0237*/ 0xffffffffU, +/*0238*/ 0xffffffffU, +/*0239*/ 0x10010230U, +/*023a*/ 0x18010230U, +/*023b*/ 0x00010231U, +/*023c*/ 0x08010231U, +/*023d*/ 0x10010231U, +/*023e*/ 0x18010231U, +/*023f*/ 0x00020232U, +/*0240*/ 0x08020232U, +/*0241*/ 0x10020232U, +/*0242*/ 0x18020232U, +/*0243*/ 0x00020233U, +/*0244*/ 0x08030233U, +/*0245*/ 0x10010233U, +/*0246*/ 0x18010233U, +/*0247*/ 0x00010234U, +/*0248*/ 0x08010234U, +/*0249*/ 0xffffffffU, +/*024a*/ 0x10020234U, +/*024b*/ 0x18010234U, +/*024c*/ 0x00010235U, +/*024d*/ 0xffffffffU, +/*024e*/ 0x08020235U, +/*024f*/ 0x10010235U, +/*0250*/ 0x18010235U, +/*0251*/ 0xffffffffU, +/*0252*/ 0x00020236U, +/*0253*/ 0x08010236U, +/*0254*/ 0x10010236U, +/*0255*/ 0xffffffffU, +/*0256*/ 0x18020236U, +/*0257*/ 0x00070237U, +/*0258*/ 0x08010237U, +/*0259*/ 0x10010237U, +/*025a*/ 0x18010237U, +/*025b*/ 0x00010238U, +/*025c*/ 0x08010238U, +/*025d*/ 0x10010238U, +/*025e*/ 0xffffffffU, +/*025f*/ 0x18010238U, +/*0260*/ 0x00040239U, +/*0261*/ 0x08040239U, +/*0262*/ 0x10040239U, +/*0263*/ 0x18010239U, +/*0264*/ 0x0002023aU, +/*0265*/ 0x0806023aU, +/*0266*/ 0x1006023aU, +/*0267*/ 0xffffffffU, +/*0268*/ 0xffffffffU, +/*0269*/ 0xffffffffU, +/*026a*/ 0x1802023aU, +/*026b*/ 0x0010023bU, +/*026c*/ 0x1001023bU, +/*026d*/ 0x1801023bU, +/*026e*/ 0xffffffffU, +/*026f*/ 0x0004023cU, +/*0270*/ 0x0801023cU, +/*0271*/ 0x1004023cU, +/*0272*/ 0x1802023cU, +/*0273*/ 0x0008023dU, +/*0274*/ 0xffffffffU, +/*0275*/ 0xffffffffU, +/*0276*/ 0xffffffffU, +/*0277*/ 0x080a023dU, +/*0278*/ 0x0020023eU, +/*0279*/ 0x0020023fU, +/*027a*/ 0x00050240U, +/*027b*/ 0x08010240U, +/*027c*/ 0x10050240U, +/*027d*/ 0x18080240U, +/*027e*/ 0x00010241U, +/*027f*/ 0x08080241U, +/*0280*/ 0x10010241U, +/*0281*/ 0x18080241U, +/*0282*/ 0x00010242U, +/*0283*/ 0x08040242U, +/*0284*/ 0x10040242U, +/*0285*/ 0x18040242U, +/*0286*/ 0x00040243U, +/*0287*/ 0x08040243U, +/*0288*/ 0x10040243U, +/*0289*/ 0x18040243U, +/*028a*/ 0x00040244U, +/*028b*/ 0x08040244U, +/*028c*/ 0x10040244U, +/*028d*/ 0x18010244U, +/*028e*/ 0x00040245U, +/*028f*/ 0x08040245U, +/*0290*/ 0x10040245U, +/*0291*/ 0x18040245U, +/*0292*/ 0x00040246U, +/*0293*/ 0x08040246U, +/*0294*/ 0x10060246U, +/*0295*/ 0x18060246U, +/*0296*/ 0x00060247U, +/*0297*/ 0x08060247U, +/*0298*/ 0x10060247U, +/*0299*/ 0x18060247U, +/*029a*/ 0xffffffffU, +/*029b*/ 0x00010248U, +/*029c*/ 0x08010248U, +/*029d*/ 0x10020248U, +/*029e*/ 0xffffffffU, +/*029f*/ 0xffffffffU, +/*02a0*/ 0xffffffffU, +/*02a1*/ 0xffffffffU, +/*02a2*/ 0xffffffffU, +/*02a3*/ 0xffffffffU, +/*02a4*/ 0xffffffffU, +/*02a5*/ 0xffffffffU, +/*02a6*/ 0x18040248U, +/*02a7*/ 0x00040249U, +/*02a8*/ 0x08010249U, +/*02a9*/ 0x10010249U, +/*02aa*/ 0xffffffffU, +/*02ab*/ 0x18010249U, +/*02ac*/ 0x0001024aU, +/*02ad*/ 0xffffffffU, +/*02ae*/ 0x0801024aU, +/*02af*/ 0x1001024aU, +/*02b0*/ 0x1801024aU, +/*02b1*/ 0x0004024bU, +/*02b2*/ 0x0804024bU, +/*02b3*/ 0x100a024bU, +/*02b4*/ 0x0020024cU, +/*02b5*/ 0x0004024dU, +/*02b6*/ 0x0808024dU, +/*02b7*/ 0xffffffffU, +/*02b8*/ 0xffffffffU, +/*02b9*/ 0xffffffffU, +/*02ba*/ 0xffffffffU, +/*02bb*/ 0xffffffffU, +/*02bc*/ 0xffffffffU, +/*02bd*/ 0x1002024dU, +/*02be*/ 0x1802024dU, +/*02bf*/ 0x0020024eU, +/*02c0*/ 0x0002024fU, +/*02c1*/ 0x0810024fU, +/*02c2*/ 0x00100250U, +/*02c3*/ 0x10040250U, +/*02c4*/ 0x18040250U, +/*02c5*/ 0x00050251U, +/*02c6*/ 0x08050251U, +/*02c7*/ 0xffffffffU, +/*02c8*/ 0xffffffffU, +/*02c9*/ 0xffffffffU, +/*02ca*/ 0xffffffffU, +/*02cb*/ 0x10010251U, +/*02cc*/ 0x18010251U, +/*02cd*/ 0x00070252U, +/*02ce*/ 0x08070252U, +/*02cf*/ 0x10070252U, +/*02d0*/ 0x18070252U, +/*02d1*/ 0x00070253U, +/*02d2*/ 0x08070253U, +/*02d3*/ 0x10070253U, +/*02d4*/ 0x18070253U, +/*02d5*/ 0x00070254U, +/*02d6*/ 0x08070254U, +/*02d7*/ 0x10070254U, +/*02d8*/ 0xffffffffU, +/*02d9*/ 0xffffffffU, +/*02da*/ 0xffffffffU, +/*02db*/ 0xffffffffU, +/*02dc*/ 0xffffffffU, +/*02dd*/ 0xffffffffU, +/*02de*/ 0x18030254U, +/*02df*/ 0x00010255U, +/*02e0*/ 0x08020255U, +/*02e1*/ 0x10010255U, +/*02e2*/ 0x18040255U, +/*02e3*/ 0x00020256U, +/*02e4*/ 0x08010256U, +/*02e5*/ 0x10010256U, +/*02e6*/ 0xffffffffU, +/*02e7*/ 0x18010256U, +/*02e8*/ 0x00040257U, +/*02e9*/ 0x08080257U, +/*02ea*/ 0x100a0257U, +/*02eb*/ 0x000a0258U, +/*02ec*/ 0x100a0258U, +/*02ed*/ 0x000a0259U, +/*02ee*/ 0x100a0259U, +/*02ef*/ 0x000a025aU, +/*02f0*/ 0x0020025bU, +/*02f1*/ 0x0020025cU, +/*02f2*/ 0x0001025dU, +/*02f3*/ 0xffffffffU, +/*02f4*/ 0xffffffffU, +/*02f5*/ 0xffffffffU, +/*02f6*/ 0x0802025dU, +/*02f7*/ 0x1002025dU, +/*02f8*/ 0x0010025eU, +/*02f9*/ 0x1005025eU, +/*02fa*/ 0x1806025eU, +/*02fb*/ 0x0005025fU, +/*02fc*/ 0x0805025fU, +/*02fd*/ 0x100e025fU, +/*02fe*/ 0x00050260U, +/*02ff*/ 0x080e0260U, +/*0300*/ 0x18050260U, +/*0301*/ 0x000e0261U, +/*0302*/ 0x10050261U, +/*0303*/ 0x18010261U, +/*0304*/ 0x00050262U, +/*0305*/ 0x08050262U, +/*0306*/ 0x100a0262U, +/*0307*/ 0x000a0263U, +/*0308*/ 0x10050263U, +/*0309*/ 0x18050263U, +/*030a*/ 0x000a0264U, +/*030b*/ 0x100a0264U, +/*030c*/ 0x00050265U, +/*030d*/ 0x08050265U, +/*030e*/ 0x100a0265U, +/*030f*/ 0x000a0266U, +/*0310*/ 0xffffffffU, +/*0311*/ 0xffffffffU, +/*0312*/ 0xffffffffU, +/*0313*/ 0xffffffffU, +/*0314*/ 0xffffffffU, +/*0315*/ 0xffffffffU, +/*0316*/ 0x10070266U, +/*0317*/ 0x18070266U, +/*0318*/ 0x00040267U, +/*0319*/ 0x08040267U, +/*031a*/ 0xffffffffU, +/*031b*/ 0xffffffffU, +/*031c*/ 0xffffffffU, +/*031d*/ 0x10040267U, +/*031e*/ 0x18080267U, +/*031f*/ 0x00080268U, +/*0320*/ 0x08040268U, +/*0321*/ 0xffffffffU, +/*0322*/ 0xffffffffU, +/*0323*/ 0xffffffffU, +/*0324*/ 0x10040268U, +/*0325*/ 0xffffffffU, +/*0326*/ 0xffffffffU, +/*0327*/ 0xffffffffU, +/*0328*/ 0x18040268U, +/*0329*/ 0xffffffffU, +/*032a*/ 0xffffffffU, +/*032b*/ 0xffffffffU, +/*032c*/ 0x00040269U, +/*032d*/ 0x08050269U, +/*032e*/ 0x10070269U, +/*032f*/ 0x18080269U, +/*0330*/ 0x0010026aU, +/*0331*/ 0x1008026aU, +/*0332*/ 0x0010026bU, +/*0333*/ 0x1008026bU, +/*0334*/ 0x0010026cU, +/*0335*/ 0x1008026cU, +/*0336*/ 0x1808026cU, +/*0337*/ 0x0001026dU, +/*0338*/ 0x0801026dU, +/*0339*/ 0x1006026dU, +/*033a*/ 0x1806026dU, +/*033b*/ 0x0006026eU, +/*033c*/ 0xffffffffU, +/*033d*/ 0x0801026eU, +/*033e*/ 0x1003026eU, +/*033f*/ 0xffffffffU, +/*0340*/ 0xffffffffU, +/*0341*/ 0xffffffffU, +/*0342*/ 0x000a026fU, +/*0343*/ 0x100a026fU, +/*0344*/ 0x00040270U, +/*0345*/ 0x08010270U, +/*0346*/ 0x10040270U, +/*0347*/ 0xffffffffU, +/*0348*/ 0xffffffffU, +/*0349*/ 0xffffffffU, +/*034a*/ 0xffffffffU, +/*034b*/ 0xffffffffU, +/*034c*/ 0xffffffffU, +/*034d*/ 0x18070270U, +/*034e*/ 0x00070271U, +/*034f*/ 0x08050271U, +/*0350*/ 0x10050271U, +/*0351*/ 0xffffffffU, +/*0352*/ 0xffffffffU, +/*0353*/ 0xffffffffU, +/*0354*/ 0x18040271U, +/*0355*/ 0x00010272U, +/*0356*/ 0x08010272U, +/*0357*/ 0x10020272U, +/*0358*/ 0x18080272U, +/*0359*/ 0x00200273U, +/*035a*/ 0x00200274U, +/*035b*/ 0x00100275U, +/*035c*/ 0xffffffffU, +/*035d*/ 0xffffffffU, +/*035e*/ 0xffffffffU, +/*035f*/ 0x10020275U, +/*0360*/ 0x18010275U, +/*0361*/ 0xffffffffU, +/*0362*/ 0x00020276U, +/*0363*/ 0x08080276U, +/*0364*/ 0x10080276U, +/*0365*/ 0x18080276U, +/*0366*/ 0x00080277U, +/*0367*/ 0x08080277U, +/*0368*/ 0x10080277U, +/*0369*/ 0xffffffffU, +/*036a*/ 0x18080277U, +/*036b*/ 0x00080278U, +/*036c*/ 0x08080278U, +/*036d*/ 0x10080278U, +/*036e*/ 0x18080278U, +/*036f*/ 0x00080279U, +/*0370*/ 0xffffffffU, +/*0371*/ 0x08080279U, +/*0372*/ 0x10080279U, +/*0373*/ 0x18080279U, +/*0374*/ 0x0008027aU, +/*0375*/ 0x0808027aU, +/*0376*/ 0x1008027aU, +/*0377*/ 0xffffffffU, +/*0378*/ 0x1808027aU, +/*0379*/ 0x0008027bU, +/*037a*/ 0x0808027bU, +/*037b*/ 0x1008027bU, +/*037c*/ 0x1808027bU, +/*037d*/ 0x0008027cU, +/*037e*/ 0x0808027cU, +/*037f*/ 0xffffffffU, +/*0380*/ 0x1008027cU, +/*0381*/ 0x1808027cU, +/*0382*/ 0x0008027dU, +/*0383*/ 0x0808027dU, +/*0384*/ 0x1008027dU, +/*0385*/ 0x1808027dU, +/*0386*/ 0xffffffffU, +/*0387*/ 0x0008027eU, +/*0388*/ 0x0808027eU, +/*0389*/ 0x1008027eU, +/*038a*/ 0x1808027eU, +/*038b*/ 0x0008027fU, +/*038c*/ 0x0808027fU, +/*038d*/ 0xffffffffU, +/*038e*/ 0x1008027fU, +/*038f*/ 0x1808027fU, +/*0390*/ 0x00080280U, +/*0391*/ 0x08080280U, +/*0392*/ 0x10080280U, +/*0393*/ 0x18080280U, +/*0394*/ 0x00080281U, +/*0395*/ 0xffffffffU, +/*0396*/ 0x08080281U, +/*0397*/ 0x10080281U, +/*0398*/ 0x18080281U, +/*0399*/ 0x00080282U, +/*039a*/ 0x08080282U, +/*039b*/ 0x10080282U, +/*039c*/ 0xffffffffU, +/*039d*/ 0x18080282U, +/*039e*/ 0x00080283U, +/*039f*/ 0x08080283U, +/*03a0*/ 0x10080283U, +/*03a1*/ 0x18080283U, +/*03a2*/ 0x00080284U, +/*03a3*/ 0xffffffffU, +/*03a4*/ 0x08080284U, +/*03a5*/ 0x10080284U, +/*03a6*/ 0x18080284U, +/*03a7*/ 0x00080285U, +/*03a8*/ 0x08080285U, +/*03a9*/ 0x10080285U, +/*03aa*/ 0x18080285U, +/*03ab*/ 0xffffffffU, +/*03ac*/ 0x00080286U, +/*03ad*/ 0x08080286U, +/*03ae*/ 0x10080286U, +/*03af*/ 0x18080286U, +/*03b0*/ 0x00080287U, +/*03b1*/ 0x08080287U, +/*03b2*/ 0xffffffffU, +/*03b3*/ 0x10080287U, +/*03b4*/ 0x18080287U, +/*03b5*/ 0x00080288U, +/*03b6*/ 0x08080288U, +/*03b7*/ 0x10080288U, +/*03b8*/ 0x18080288U, +/*03b9*/ 0xffffffffU, +/*03ba*/ 0x00080289U, +/*03bb*/ 0x08020289U, +/*03bc*/ 0x10030289U, +/*03bd*/ 0x000a028aU, +/*03be*/ 0x100a028aU, +/*03bf*/ 0x000a028bU, +/*03c0*/ 0x1005028bU, +/*03c1*/ 0x1804028bU, +/*03c2*/ 0x0008028cU, +/*03c3*/ 0x0808028cU, +/*03c4*/ 0x1006028cU, +/*03c5*/ 0x1806028cU, +/*03c6*/ 0x0011028dU, +/*03c7*/ 0x1808028dU, +/*03c8*/ 0x0004028eU, +/*03c9*/ 0x0806028eU, +/*03ca*/ 0xffffffffU, +/*03cb*/ 0x1006028eU, +/*03cc*/ 0x1808028eU, +/*03cd*/ 0xffffffffU, +/*03ce*/ 0x0004028fU, +/*03cf*/ 0x0808028fU, +/*03d0*/ 0x1008028fU, +/*03d1*/ 0x1806028fU, +/*03d2*/ 0x00060290U, +/*03d3*/ 0x08110290U, +/*03d4*/ 0x00080291U, +/*03d5*/ 0x08040291U, +/*03d6*/ 0x10060291U, +/*03d7*/ 0xffffffffU, +/*03d8*/ 0x18060291U, +/*03d9*/ 0x00080292U, +/*03da*/ 0xffffffffU, +/*03db*/ 0x08040292U, +/*03dc*/ 0x10080292U, +/*03dd*/ 0x18080292U, +/*03de*/ 0x00060293U, +/*03df*/ 0x08060293U, +/*03e0*/ 0x00110294U, +/*03e1*/ 0x18080294U, +/*03e2*/ 0x00040295U, +/*03e3*/ 0x08060295U, +/*03e4*/ 0xffffffffU, +/*03e5*/ 0x10060295U, +/*03e6*/ 0x18080295U, +/*03e7*/ 0xffffffffU, +/*03e8*/ 0x00040296U, +/*03e9*/ 0x08040296U, +/*03ea*/ 0x10040296U, +/*03eb*/ 0x18040296U, +/*03ec*/ 0x00040297U, +/*03ed*/ 0x08040297U, +/*03ee*/ 0x10040297U, +/*03ef*/ 0x18040297U, +/*03f0*/ 0x00040298U, +/*03f1*/ 0x08040298U, +/*03f2*/ 0x10040298U, +/*03f3*/ 0x18040298U, +/*03f4*/ 0x00040299U, +/*03f5*/ 0x08040299U, +/*03f6*/ 0x10040299U, +/*03f7*/ 0x18040299U, +/*03f8*/ 0x0004029aU, +/*03f9*/ 0x0804029aU, +/*03fa*/ 0x1004029aU, +/*03fb*/ 0x1804029aU, +/*03fc*/ 0x0011029bU, +/*03fd*/ 0x0010029cU, +/*03fe*/ 0x0011029dU, +/*03ff*/ 0x0020029eU, +/*0400*/ 0x0020029fU, +/*0401*/ 0x002002a0U, +/*0402*/ 0x002002a1U, +/*0403*/ 0x002002a2U, +/*0404*/ 0x002002a3U, +/*0405*/ 0x002002a4U, +/*0406*/ 0x002002a5U, +/*0407*/ 0x002002a6U, +/*0408*/ 0x000202a7U, +/*0409*/ 0x080502a7U, +/*040a*/ 0x100502a7U, +/*040b*/ 0xffffffffU, +/*040c*/ 0xffffffffU, +/*040d*/ 0xffffffffU, +/*040e*/ 0xffffffffU, +/*040f*/ 0xffffffffU, +/*0410*/ 0xffffffffU, +/*0411*/ 0xffffffffU, +/*0412*/ 0xffffffffU, +/*0413*/ 0xffffffffU, +/*0414*/ 0xffffffffU, +/*0415*/ 0xffffffffU, +/*0416*/ 0xffffffffU, +/*0417*/ 0xffffffffU, +/*0418*/ 0xffffffffU, +/*0419*/ 0xffffffffU, +/*041a*/ 0xffffffffU, +/*041b*/ 0xffffffffU, +/*041c*/ 0xffffffffU, +/*041d*/ 0xffffffffU, +/*041e*/ 0xffffffffU, +/*041f*/ 0xffffffffU, +/*0420*/ 0xffffffffU, +/*0421*/ 0xffffffffU, +/*0422*/ 0xffffffffU, +/*0423*/ 0xffffffffU, +/*0424*/ 0xffffffffU, +/*0425*/ 0xffffffffU, +/*0426*/ 0xffffffffU, +/*0427*/ 0x180102a7U, +/*0428*/ 0x000402a8U, +/*0429*/ 0x081002a8U, +/*042a*/ 0x002002a9U, +/*042b*/ 0x001002aaU, +/*042c*/ 0x002002abU, +/*042d*/ 0x001002acU, +/*042e*/ 0x002002adU, +/*042f*/ 0x000702aeU, +/*0430*/ 0x080102aeU, +/*0431*/ 0x100202aeU, +/*0432*/ 0x180602aeU, +/*0433*/ 0x000102afU, +/*0434*/ 0x080102afU, +/*0435*/ 0x002002b0U, +/*0436*/ 0x000202b1U, +/*0437*/ 0x002002b2U, +/*0438*/ 0x002002b3U, +/*0439*/ 0xffffffffU, +/*043a*/ 0xffffffffU, +/*043b*/ 0xffffffffU, +/*043c*/ 0xffffffffU, +/*043d*/ 0xffffffffU, +/*043e*/ 0xffffffffU, +/*043f*/ 0xffffffffU, +/*0440*/ 0xffffffffU, +/*0441*/ 0xffffffffU, +/*0442*/ 0xffffffffU, +/*0443*/ 0xffffffffU, +/*0444*/ 0xffffffffU, +/*0445*/ 0xffffffffU, +/*0446*/ 0xffffffffU, +/*0447*/ 0xffffffffU, +/*0448*/ 0xffffffffU, +/*0449*/ 0xffffffffU, +/*044a*/ 0xffffffffU, +/*044b*/ 0xffffffffU, +/*044c*/ 0xffffffffU, +/*044d*/ 0xffffffffU, +/*044e*/ 0xffffffffU, +/*044f*/ 0xffffffffU, +/*0450*/ 0xffffffffU, +/*0451*/ 0xffffffffU, +/*0452*/ 0xffffffffU, +/*0453*/ 0xffffffffU, +/*0454*/ 0xffffffffU, +/*0455*/ 0xffffffffU, +/*0456*/ 0xffffffffU, +/*0457*/ 0xffffffffU, +/*0458*/ 0xffffffffU, +/*0459*/ 0xffffffffU, +/*045a*/ 0xffffffffU, +/*045b*/ 0xffffffffU, +/*045c*/ 0xffffffffU, +/*045d*/ 0xffffffffU, +/*045e*/ 0xffffffffU, +/*045f*/ 0x000402b4U, +/*0460*/ 0xffffffffU, +/*0461*/ 0xffffffffU, +/*0462*/ 0xffffffffU, +/*0463*/ 0xffffffffU, +/*0464*/ 0xffffffffU, +/*0465*/ 0xffffffffU, +/*0466*/ 0xffffffffU, +/*0467*/ 0xffffffffU, +/*0468*/ 0xffffffffU, +/*0469*/ 0xffffffffU, +/*046a*/ 0xffffffffU, +/*046b*/ 0xffffffffU, +/*046c*/ 0xffffffffU, +/*046d*/ 0xffffffffU, +/*046e*/ 0xffffffffU, +/*046f*/ 0xffffffffU, +/*0470*/ 0xffffffffU, +/*0471*/ 0xffffffffU, +/*0472*/ 0xffffffffU, +/*0473*/ 0xffffffffU, +/*0474*/ 0xffffffffU, +/*0475*/ 0xffffffffU, +/*0476*/ 0xffffffffU, +/*0477*/ 0xffffffffU, +/*0478*/ 0xffffffffU, +/*0479*/ 0xffffffffU, +/*047a*/ 0xffffffffU, +/*047b*/ 0xffffffffU, +/*047c*/ 0xffffffffU, +/*047d*/ 0xffffffffU, +/*047e*/ 0xffffffffU, +/*047f*/ 0xffffffffU, +/*0480*/ 0xffffffffU, +/*0481*/ 0xffffffffU, +/*0482*/ 0xffffffffU, +/*0483*/ 0xffffffffU, +/*0484*/ 0xffffffffU, +/*0485*/ 0xffffffffU, +/*0486*/ 0xffffffffU, +/*0487*/ 0xffffffffU, +/*0488*/ 0xffffffffU, +/*0489*/ 0xffffffffU, +/*048a*/ 0xffffffffU, +/*048b*/ 0xffffffffU, +/*048c*/ 0xffffffffU, +/*048d*/ 0xffffffffU, +/*048e*/ 0xffffffffU, +/*048f*/ 0xffffffffU, +/*0490*/ 0xffffffffU, +/*0491*/ 0xffffffffU, +/*0492*/ 0xffffffffU, +/*0493*/ 0xffffffffU, +/*0494*/ 0xffffffffU, + }, + { +/*0000*/ 0x00200800U, +/*0001*/ 0x00040801U, +/*0002*/ 0x080b0801U, +/*0003*/ 0xffffffffU, +/*0004*/ 0xffffffffU, +/*0005*/ 0x18010801U, +/*0006*/ 0x00050802U, +/*0007*/ 0x08050802U, +/*0008*/ 0x10050802U, +/*0009*/ 0x18050802U, +/*000a*/ 0x00050803U, +/*000b*/ 0x08050803U, +/*000c*/ 0x10050803U, +/*000d*/ 0x18050803U, +/*000e*/ 0x00050804U, +/*000f*/ 0x08040804U, +/*0010*/ 0x10030804U, +/*0011*/ 0x00180805U, +/*0012*/ 0x18030805U, +/*0013*/ 0x00180806U, +/*0014*/ 0x18020806U, +/*0015*/ 0x00010807U, +/*0016*/ 0x08020807U, +/*0017*/ 0x10010807U, +/*0018*/ 0x18010807U, +/*0019*/ 0x00020808U, +/*001a*/ 0x08040808U, +/*001b*/ 0x10040808U, +/*001c*/ 0x18040808U, +/*001d*/ 0x000a0809U, +/*001e*/ 0x10040809U, +/*001f*/ 0xffffffffU, +/*0020*/ 0xffffffffU, +/*0021*/ 0x18070809U, +/*0022*/ 0xffffffffU, +/*0023*/ 0xffffffffU, +/*0024*/ 0xffffffffU, +/*0025*/ 0xffffffffU, +/*0026*/ 0xffffffffU, +/*0027*/ 0xffffffffU, +/*0028*/ 0x000a080aU, +/*0029*/ 0x1005080aU, +/*002a*/ 0x1801080aU, +/*002b*/ 0x0001080bU, +/*002c*/ 0x0802080bU, +/*002d*/ 0x1009080bU, +/*002e*/ 0x0009080cU, +/*002f*/ 0x1002080cU, +/*0030*/ 0x0020080dU, +/*0031*/ 0xffffffffU, +/*0032*/ 0x0001080eU, +/*0033*/ 0xffffffffU, +/*0034*/ 0xffffffffU, +/*0035*/ 0xffffffffU, +/*0036*/ 0xffffffffU, +/*0037*/ 0x0020080fU, +/*0038*/ 0x00200810U, +/*0039*/ 0x00200811U, +/*003a*/ 0x00200812U, +/*003b*/ 0x00030813U, +/*003c*/ 0x08010813U, +/*003d*/ 0x10030813U, +/*003e*/ 0x18030813U, +/*003f*/ 0x00040814U, +/*0040*/ 0x08040814U, +/*0041*/ 0x10040814U, +/*0042*/ 0x18040814U, +/*0043*/ 0x00010815U, +/*0044*/ 0x08010815U, +/*0045*/ 0x10060815U, +/*0046*/ 0x18040815U, +/*0047*/ 0xffffffffU, +/*0048*/ 0x00060816U, +/*0049*/ 0x08040816U, +/*004a*/ 0x10060816U, +/*004b*/ 0x18040816U, +/*004c*/ 0x00020817U, +/*004d*/ 0x08050817U, +/*004e*/ 0x10080817U, +/*004f*/ 0x00200818U, +/*0050*/ 0x00060819U, +/*0051*/ 0x08030819U, +/*0052*/ 0x100b0819U, +/*0053*/ 0x0004081aU, +/*0054*/ 0x0804081aU, +/*0055*/ 0x1004081aU, +/*0056*/ 0xffffffffU, +/*0057*/ 0x1801081aU, +/*0058*/ 0x0009081bU, +/*0059*/ 0x0020081cU, +/*005a*/ 0x0020081dU, +/*005b*/ 0x0020081eU, +/*005c*/ 0x0020081fU, +/*005d*/ 0x00100820U, +/*005e*/ 0xffffffffU, +/*005f*/ 0x10010820U, +/*0060*/ 0x18060820U, +/*0061*/ 0x00080821U, +/*0062*/ 0x00200822U, +/*0063*/ 0xffffffffU, +/*0064*/ 0x000a0823U, +/*0065*/ 0x10060823U, +/*0066*/ 0x18070823U, +/*0067*/ 0x00080824U, +/*0068*/ 0x08080824U, +/*0069*/ 0x100a0824U, +/*006a*/ 0x00070825U, +/*006b*/ 0x08080825U, +/*006c*/ 0x10080825U, +/*006d*/ 0x18030825U, +/*006e*/ 0x000a0826U, +/*006f*/ 0x100a0826U, +/*0070*/ 0x00110827U, +/*0071*/ 0x00090828U, +/*0072*/ 0x10090828U, +/*0073*/ 0x00100829U, +/*0074*/ 0x100e0829U, +/*0075*/ 0x000e082aU, +/*0076*/ 0x100c082aU, +/*0077*/ 0x000a082bU, +/*0078*/ 0x100a082bU, +/*0079*/ 0x0002082cU, +/*007a*/ 0x0020082dU, +/*007b*/ 0x000b082eU, +/*007c*/ 0x100b082eU, +/*007d*/ 0x0020082fU, +/*007e*/ 0x00120830U, +/*007f*/ 0x00200831U, +/*0080*/ 0x00200832U, +/*0081*/ 0xffffffffU, +/*0082*/ 0xffffffffU, +/*0083*/ 0x00010833U, +/*0084*/ 0x08010833U, +/*0085*/ 0x10080833U, +/*0086*/ 0x000c0834U, +/*0087*/ 0x100c0834U, +/*0088*/ 0x000c0835U, +/*0089*/ 0x100c0835U, +/*008a*/ 0x000c0836U, +/*008b*/ 0x100c0836U, +/*008c*/ 0x000c0837U, +/*008d*/ 0x100c0837U, +/*008e*/ 0x000c0838U, +/*008f*/ 0x100c0838U, +/*0090*/ 0x000c0839U, +/*0091*/ 0x100b0839U, +/*0092*/ 0xffffffffU, +/*0093*/ 0xffffffffU, +/*0094*/ 0x000b083aU, +/*0095*/ 0x100b083aU, +/*0096*/ 0x000b083bU, +/*0097*/ 0x100b083bU, +/*0098*/ 0x000b083cU, +/*0099*/ 0x100b083cU, +/*009a*/ 0x000b083dU, +/*009b*/ 0x100b083dU, +/*009c*/ 0x000b083eU, +/*009d*/ 0x100a083eU, +/*009e*/ 0xffffffffU, +/*009f*/ 0x000a083fU, +/*00a0*/ 0x100a083fU, +/*00a1*/ 0x000a0840U, +/*00a2*/ 0x100a0840U, +/*00a3*/ 0x000a0841U, +/*00a4*/ 0x100a0841U, +/*00a5*/ 0x000a0842U, +/*00a6*/ 0x100a0842U, +/*00a7*/ 0x000a0843U, +/*00a8*/ 0x100a0843U, +/*00a9*/ 0x000a0844U, +/*00aa*/ 0x100a0844U, +/*00ab*/ 0x000a0845U, +/*00ac*/ 0x100a0845U, +/*00ad*/ 0x000a0846U, +/*00ae*/ 0x100a0846U, +/*00af*/ 0x000a0847U, +/*00b0*/ 0x100a0847U, +/*00b1*/ 0x000a0848U, +/*00b2*/ 0x100a0848U, +/*00b3*/ 0x000a0849U, +/*00b4*/ 0x100a0849U, +/*00b5*/ 0x000a084aU, +/*00b6*/ 0x100a084aU, +/*00b7*/ 0x000a084bU, +/*00b8*/ 0x100a084bU, +/*00b9*/ 0x000a084cU, +/*00ba*/ 0x100a084cU, +/*00bb*/ 0x0004084dU, +/*00bc*/ 0x0803084dU, +/*00bd*/ 0x100a084dU, +/*00be*/ 0x000a084eU, +/*00bf*/ 0x1001084eU, +/*00c0*/ 0x000a084fU, +/*00c1*/ 0x1004084fU, +/*00c2*/ 0x000b0850U, +/*00c3*/ 0x100a0850U, +/*00c4*/ 0xffffffffU, +/*00c5*/ 0x00080851U, +/*00c6*/ 0x08080851U, +/*00c7*/ 0x10080851U, +/*00c8*/ 0x18080851U, +/*00c9*/ 0x00080852U, +/*00ca*/ 0xffffffffU, +/*00cb*/ 0x08080852U, +/*00cc*/ 0x10010852U, +/*00cd*/ 0x18080852U, +/*00ce*/ 0x00080853U, +/*00cf*/ 0x08020853U, +/*00d0*/ 0x10020853U, +/*00d1*/ 0x18040853U, +/*00d2*/ 0x00040854U, +/*00d3*/ 0xffffffffU, +/*00d4*/ 0x08040854U, +/*00d5*/ 0x100a0854U, +/*00d6*/ 0x00060855U, +/*00d7*/ 0x08080855U, +/*00d8*/ 0xffffffffU, +/*00d9*/ 0x10040855U, +/*00da*/ 0x18040855U, +/*00db*/ 0x00050856U, +/*00dc*/ 0x08040856U, +/*00dd*/ 0x10050856U, +/*00de*/ 0x000a0857U, +/*00df*/ 0x100a0857U, +/*00e0*/ 0x00080858U, +/*00e1*/ 0xffffffffU, +/*00e2*/ 0x08040858U, +/*00e3*/ 0xffffffffU, +/*00e4*/ 0xffffffffU, +/*00e5*/ 0x00050a00U, +/*00e6*/ 0x08050a00U, +/*00e7*/ 0x10050a00U, +/*00e8*/ 0x18050a00U, +/*00e9*/ 0x00050a01U, +/*00ea*/ 0x08050a01U, +/*00eb*/ 0x100b0a01U, +/*00ec*/ 0x00010a02U, +/*00ed*/ 0x08030a02U, +/*00ee*/ 0x00200a03U, +/*00ef*/ 0xffffffffU, +/*00f0*/ 0x00030a04U, +/*00f1*/ 0x080a0a04U, +/*00f2*/ 0xffffffffU, +/*00f3*/ 0xffffffffU, +/*00f4*/ 0x18030a04U, +/*00f5*/ 0x00030a05U, +/*00f6*/ 0x08010a05U, +/*00f7*/ 0x10010a05U, +/*00f8*/ 0x18060a05U, +/*00f9*/ 0xffffffffU, +/*00fa*/ 0xffffffffU, +/*00fb*/ 0xffffffffU, +/*00fc*/ 0x00020a06U, +/*00fd*/ 0x08030a06U, +/*00fe*/ 0x10010a06U, +/*00ff*/ 0x000f0a07U, +/*0100*/ 0x00200a08U, +/*0101*/ 0x00200a09U, +/*0102*/ 0x000b0a0aU, +/*0103*/ 0x100b0a0aU, +/*0104*/ 0x000b0a0bU, +/*0105*/ 0xffffffffU, +/*0106*/ 0xffffffffU, +/*0107*/ 0x00180a0cU, +/*0108*/ 0x00180a0dU, +/*0109*/ 0x00180a0eU, +/*010a*/ 0x00180a0fU, +/*010b*/ 0x18040a0fU, +/*010c*/ 0x00020a10U, +/*010d*/ 0x08020a10U, +/*010e*/ 0x10040a10U, +/*010f*/ 0x18040a10U, +/*0110*/ 0x00010a11U, +/*0111*/ 0x08010a11U, +/*0112*/ 0x10010a11U, +/*0113*/ 0x18030a11U, +/*0114*/ 0x00200a12U, +/*0115*/ 0x00200a13U, +/*0116*/ 0xffffffffU, +/*0117*/ 0x00140a14U, +/*0118*/ 0x00140a15U, +/*0119*/ 0x00140a16U, +/*011a*/ 0x00140a17U, +/*011b*/ 0x00140a18U, +/*011c*/ 0x00140a19U, +/*011d*/ 0x00140a1aU, +/*011e*/ 0x00140a1bU, +/*011f*/ 0x001e0a1cU, +/*0120*/ 0x000a0a1dU, +/*0121*/ 0x10060a1dU, +/*0122*/ 0x18060a1dU, +/*0123*/ 0x00060a1eU, +/*0124*/ 0xffffffffU, +/*0125*/ 0x08060a1eU, +/*0126*/ 0x00080a1fU, +/*0127*/ 0x080b0a1fU, +/*0128*/ 0x000b0a20U, +/*0129*/ 0x100b0a20U, +/*012a*/ 0x000b0a21U, +/*012b*/ 0x100b0a21U, +/*012c*/ 0x000b0a22U, +/*012d*/ 0x10040a22U, +/*012e*/ 0x000a0a23U, +/*012f*/ 0x10060a23U, +/*0130*/ 0x18080a23U, +/*0131*/ 0xffffffffU, +/*0132*/ 0x00040a24U, +/*0133*/ 0xffffffffU, +/*0134*/ 0xffffffffU, +/*0135*/ 0x00010b80U, +/*0136*/ 0x08020b80U, +/*0137*/ 0x10050b80U, +/*0138*/ 0x18050b80U, +/*0139*/ 0x00050b81U, +/*013a*/ 0x08050b81U, +/*013b*/ 0x100b0b81U, +/*013c*/ 0x00050b82U, +/*013d*/ 0x08010b82U, +/*013e*/ 0x10010b82U, +/*013f*/ 0xffffffffU, +/*0140*/ 0x18010b82U, +/*0141*/ 0x00010b83U, +/*0142*/ 0x08040b83U, +/*0143*/ 0x100b0b83U, +/*0144*/ 0x000b0b84U, +/*0145*/ 0xffffffffU, +/*0146*/ 0x10040b84U, +/*0147*/ 0x000b0b85U, +/*0148*/ 0x10040b85U, +/*0149*/ 0x18010b85U, +/*014a*/ 0x00010b86U, +/*014b*/ 0x08010b86U, +/*014c*/ 0x00200b87U, +/*014d*/ 0x00200b88U, +/*014e*/ 0x00080b89U, +/*014f*/ 0x080a0b89U, +/*0150*/ 0x18050b89U, +/*0151*/ 0x000a0b8aU, +/*0152*/ 0x10030b8aU, +/*0153*/ 0x18030b8aU, +/*0154*/ 0x00010b8bU, +/*0155*/ 0x08020b8bU, +/*0156*/ 0x10010b8bU, +/*0157*/ 0x18010b8bU, +/*0158*/ 0x00010b8cU, +/*0159*/ 0x08030b8cU, +/*015a*/ 0xffffffffU, +/*015b*/ 0x10040b8cU, +/*015c*/ 0x18040b8cU, +/*015d*/ 0x00040b8dU, +/*015e*/ 0x08040b8dU, +/*015f*/ 0xffffffffU, +/*0160*/ 0xffffffffU, +/*0161*/ 0xffffffffU, +/*0162*/ 0xffffffffU, +/*0163*/ 0xffffffffU, +/*0164*/ 0xffffffffU, +/*0165*/ 0xffffffffU, +/*0166*/ 0xffffffffU, +/*0167*/ 0xffffffffU, +/*0168*/ 0x000d0b8eU, +/*0169*/ 0x100d0b8eU, +/*016a*/ 0x000d0b8fU, +/*016b*/ 0x00050b90U, +/*016c*/ 0x00010b91U, +/*016d*/ 0x080e0b91U, +/*016e*/ 0x000e0b92U, +/*016f*/ 0x100e0b92U, +/*0170*/ 0x000e0b93U, +/*0171*/ 0x100e0b93U, +/*0172*/ 0x00040b94U, +/*0173*/ 0x08040b94U, +/*0174*/ 0x10040b94U, +/*0175*/ 0x18040b94U, +/*0176*/ 0x00040b95U, +/*0177*/ 0x080b0b95U, +/*0178*/ 0x000b0b96U, +/*0179*/ 0x100b0b96U, +/*017a*/ 0x000b0b97U, +/*017b*/ 0xffffffffU, +/*017c*/ 0xffffffffU, +/*017d*/ 0xffffffffU, +/*017e*/ 0xffffffffU, +/*017f*/ 0x000d0b98U, +/*0180*/ 0x100d0b98U, +/*0181*/ 0x000d0b99U, +/*0182*/ 0x10100b99U, +/*0183*/ 0x10080b8dU, +/*0184*/ 0x18080b8dU, +/*0185*/ 0x00100b9aU, +/*0186*/ 0x10100b9aU, +/*0187*/ 0x00100b9bU, +/*0188*/ 0x10100b9bU, +/*0189*/ 0x00100b9cU, +/*018a*/ 0x10030b9cU, +/*018b*/ 0x18040b9cU, +/*018c*/ 0x00010b9dU, +/*018d*/ 0x08040b9dU, +/*018e*/ 0xffffffffU, +/*018f*/ 0xffffffffU, +/*0190*/ 0x10010b9dU, +/*0191*/ 0x00140b9eU, +/*0192*/ 0x000a0b9fU, +/*0193*/ 0x100c0b9fU, +/*0194*/ 0x00120ba0U, +/*0195*/ 0x00140ba1U, +/*0196*/ 0x00120ba2U, +/*0197*/ 0x00110ba3U, +/*0198*/ 0x00110ba4U, +/*0199*/ 0x00120ba5U, +/*019a*/ 0x00120ba6U, +/*019b*/ 0x00120ba7U, +/*019c*/ 0x00120ba8U, +/*019d*/ 0x00120ba9U, +/*019e*/ 0x00120baaU, +/*019f*/ 0x00120babU, +/*01a0*/ 0x00120bacU, +/*01a1*/ 0xffffffffU, +/*01a2*/ 0xffffffffU, +/*01a3*/ 0x00190badU, +/*01a4*/ 0x00190baeU, +/*01a5*/ 0x00200bafU, +/*01a6*/ 0x00170bb0U, +/*01a7*/ 0x18080bb0U, +/*01a8*/ 0x00010bb1U, +/*01a9*/ 0x08010bb1U, +/*01aa*/ 0x00200bb2U, +/*01ab*/ 0x00080bb3U, +/*01ac*/ 0xffffffffU, +/*01ad*/ 0x08030bb3U, +/*01ae*/ 0x00180bb4U, +/*01af*/ 0x00180bb5U, +/*01b0*/ 0xffffffffU, +/*01b1*/ 0xffffffffU, +/*01b2*/ 0xffffffffU, +/*01b3*/ 0xffffffffU, +/*01b4*/ 0xffffffffU, +/*01b5*/ 0xffffffffU, +/*01b6*/ 0xffffffffU, +/*01b7*/ 0xffffffffU, +/*01b8*/ 0xffffffffU, +/*01b9*/ 0xffffffffU, +/*01ba*/ 0xffffffffU, +/*01bb*/ 0xffffffffU, +/*01bc*/ 0xffffffffU, +/*01bd*/ 0xffffffffU, +/*01be*/ 0xffffffffU, +/*01bf*/ 0x00100bb6U, +/*01c0*/ 0x10010bb6U, +/*01c1*/ 0x18010bb6U, +/*01c2*/ 0x00050bb7U, +/*01c3*/ 0x00200bb8U, +/*01c4*/ 0x00090bb9U, +/*01c5*/ 0xffffffffU, +/*01c6*/ 0xffffffffU, +/*01c7*/ 0x00200bbaU, +/*01c8*/ 0x00040bbbU, +/*01c9*/ 0x08100bbbU, +/*01ca*/ 0x18060bbbU, +/*01cb*/ 0x00100bbcU, +/*01cc*/ 0xffffffffU, +/*01cd*/ 0x10080bbcU, +/*01ce*/ 0xffffffffU, +/*01cf*/ 0xffffffffU, +/*01d0*/ 0xffffffffU, +/*01d1*/ 0x18030bbcU, +/*01d2*/ 0x00020bbdU, +/*01d3*/ 0xffffffffU, +/*01d4*/ 0x00200bbeU, +/*01d5*/ 0x000b0bbfU, +/*01d6*/ 0xffffffffU, +/*01d7*/ 0xffffffffU, +/*01d8*/ 0xffffffffU, +/*01d9*/ 0x10020bbfU, +/*01da*/ 0xffffffffU, +/*01db*/ 0xffffffffU, +/*01dc*/ 0xffffffffU, +/*01dd*/ 0xffffffffU, +/*01de*/ 0x00010200U, +/*01df*/ 0x08040200U, +/*01e0*/ 0x10100200U, +/*01e1*/ 0x00010201U, +/*01e2*/ 0x08010201U, +/*01e3*/ 0xffffffffU, +/*01e4*/ 0xffffffffU, +/*01e5*/ 0x10100201U, +/*01e6*/ 0xffffffffU, +/*01e7*/ 0xffffffffU, +/*01e8*/ 0xffffffffU, +/*01e9*/ 0xffffffffU, +/*01ea*/ 0xffffffffU, +/*01eb*/ 0xffffffffU, +/*01ec*/ 0xffffffffU, +/*01ed*/ 0xffffffffU, +/*01ee*/ 0xffffffffU, +/*01ef*/ 0x00200202U, +/*01f0*/ 0x00100203U, +/*01f1*/ 0x00200204U, +/*01f2*/ 0x00100205U, +/*01f3*/ 0x00200206U, +/*01f4*/ 0x00100207U, +/*01f5*/ 0x10100207U, +/*01f6*/ 0x00200208U, +/*01f7*/ 0x00200209U, +/*01f8*/ 0x0020020aU, +/*01f9*/ 0x0020020bU, +/*01fa*/ 0x0010020cU, +/*01fb*/ 0x0020020dU, +/*01fc*/ 0x0020020eU, +/*01fd*/ 0x0020020fU, +/*01fe*/ 0x00200210U, +/*01ff*/ 0x00100211U, +/*0200*/ 0x00200212U, +/*0201*/ 0x00200213U, +/*0202*/ 0x00200214U, +/*0203*/ 0x00200215U, +/*0204*/ 0x00090216U, +/*0205*/ 0x10010216U, +/*0206*/ 0x00200217U, +/*0207*/ 0x00050218U, +/*0208*/ 0x08010218U, +/*0209*/ 0x10080218U, +/*020a*/ 0x18080218U, +/*020b*/ 0x001e0219U, +/*020c*/ 0x001e021aU, +/*020d*/ 0x001e021bU, +/*020e*/ 0x001e021cU, +/*020f*/ 0x001e021dU, +/*0210*/ 0x001e021eU, +/*0211*/ 0x001e021fU, +/*0212*/ 0x001e0220U, +/*0213*/ 0x001e0221U, +/*0214*/ 0x001e0222U, +/*0215*/ 0x001e0223U, +/*0216*/ 0x001e0224U, +/*0217*/ 0x001e0225U, +/*0218*/ 0x001e0226U, +/*0219*/ 0x001e0227U, +/*021a*/ 0x001e0228U, +/*021b*/ 0x00010229U, +/*021c*/ 0x08010229U, +/*021d*/ 0x10010229U, +/*021e*/ 0x18040229U, +/*021f*/ 0x0008022aU, +/*0220*/ 0x0808022aU, +/*0221*/ 0x1008022aU, +/*0222*/ 0x1804022aU, +/*0223*/ 0x0005022bU, +/*0224*/ 0x0806022bU, +/*0225*/ 0x1007022bU, +/*0226*/ 0x1805022bU, +/*0227*/ 0x0006022cU, +/*0228*/ 0x0807022cU, +/*0229*/ 0x1005022cU, +/*022a*/ 0x1806022cU, +/*022b*/ 0x0007022dU, +/*022c*/ 0x0802022dU, +/*022d*/ 0x1001022dU, +/*022e*/ 0xffffffffU, +/*022f*/ 0x000a022eU, +/*0230*/ 0x1010022eU, +/*0231*/ 0x000a022fU, +/*0232*/ 0x1010022fU, +/*0233*/ 0x000a0230U, +/*0234*/ 0x10100230U, +/*0235*/ 0xffffffffU, +/*0236*/ 0x00100231U, +/*0237*/ 0xffffffffU, +/*0238*/ 0xffffffffU, +/*0239*/ 0x10010231U, +/*023a*/ 0x18010231U, +/*023b*/ 0x00010232U, +/*023c*/ 0x08010232U, +/*023d*/ 0x10010232U, +/*023e*/ 0x18010232U, +/*023f*/ 0x00020233U, +/*0240*/ 0x08020233U, +/*0241*/ 0x10020233U, +/*0242*/ 0x18020233U, +/*0243*/ 0x00020234U, +/*0244*/ 0x08030234U, +/*0245*/ 0x10010234U, +/*0246*/ 0x18010234U, +/*0247*/ 0x00010235U, +/*0248*/ 0x08010235U, +/*0249*/ 0xffffffffU, +/*024a*/ 0x10020235U, +/*024b*/ 0x18010235U, +/*024c*/ 0x00010236U, +/*024d*/ 0xffffffffU, +/*024e*/ 0x08020236U, +/*024f*/ 0x10010236U, +/*0250*/ 0x18010236U, +/*0251*/ 0xffffffffU, +/*0252*/ 0x00020237U, +/*0253*/ 0x08010237U, +/*0254*/ 0x10010237U, +/*0255*/ 0xffffffffU, +/*0256*/ 0x18020237U, +/*0257*/ 0x00070238U, +/*0258*/ 0x08010238U, +/*0259*/ 0x10010238U, +/*025a*/ 0x18010238U, +/*025b*/ 0x00010239U, +/*025c*/ 0x08010239U, +/*025d*/ 0x10010239U, +/*025e*/ 0xffffffffU, +/*025f*/ 0x18010239U, +/*0260*/ 0x0004023aU, +/*0261*/ 0x0804023aU, +/*0262*/ 0x1004023aU, +/*0263*/ 0x1801023aU, +/*0264*/ 0x0002023bU, +/*0265*/ 0x0806023bU, +/*0266*/ 0x1006023bU, +/*0267*/ 0xffffffffU, +/*0268*/ 0xffffffffU, +/*0269*/ 0xffffffffU, +/*026a*/ 0x1802023bU, +/*026b*/ 0x0010023cU, +/*026c*/ 0x1001023cU, +/*026d*/ 0x1801023cU, +/*026e*/ 0xffffffffU, +/*026f*/ 0x0004023dU, +/*0270*/ 0x0801023dU, +/*0271*/ 0x1004023dU, +/*0272*/ 0x1802023dU, +/*0273*/ 0x0008023eU, +/*0274*/ 0xffffffffU, +/*0275*/ 0xffffffffU, +/*0276*/ 0xffffffffU, +/*0277*/ 0x080a023eU, +/*0278*/ 0x0020023fU, +/*0279*/ 0x00200240U, +/*027a*/ 0x00050241U, +/*027b*/ 0x08010241U, +/*027c*/ 0x10050241U, +/*027d*/ 0x18080241U, +/*027e*/ 0x00010242U, +/*027f*/ 0x08080242U, +/*0280*/ 0x10010242U, +/*0281*/ 0x18080242U, +/*0282*/ 0x00010243U, +/*0283*/ 0x08040243U, +/*0284*/ 0x10040243U, +/*0285*/ 0x18040243U, +/*0286*/ 0x00040244U, +/*0287*/ 0x08040244U, +/*0288*/ 0x10040244U, +/*0289*/ 0x18040244U, +/*028a*/ 0x00040245U, +/*028b*/ 0x08040245U, +/*028c*/ 0x10040245U, +/*028d*/ 0x18010245U, +/*028e*/ 0x00040246U, +/*028f*/ 0x08040246U, +/*0290*/ 0x10040246U, +/*0291*/ 0x18040246U, +/*0292*/ 0x00040247U, +/*0293*/ 0x08040247U, +/*0294*/ 0x10060247U, +/*0295*/ 0x18060247U, +/*0296*/ 0x00060248U, +/*0297*/ 0x08060248U, +/*0298*/ 0x10060248U, +/*0299*/ 0x18060248U, +/*029a*/ 0x00040249U, +/*029b*/ 0x08010249U, +/*029c*/ 0x10010249U, +/*029d*/ 0x18020249U, +/*029e*/ 0xffffffffU, +/*029f*/ 0xffffffffU, +/*02a0*/ 0xffffffffU, +/*02a1*/ 0xffffffffU, +/*02a2*/ 0xffffffffU, +/*02a3*/ 0xffffffffU, +/*02a4*/ 0xffffffffU, +/*02a5*/ 0xffffffffU, +/*02a6*/ 0x0004024aU, +/*02a7*/ 0x0804024aU, +/*02a8*/ 0x1001024aU, +/*02a9*/ 0x1801024aU, +/*02aa*/ 0xffffffffU, +/*02ab*/ 0x0001024bU, +/*02ac*/ 0x0801024bU, +/*02ad*/ 0xffffffffU, +/*02ae*/ 0x1001024bU, +/*02af*/ 0x1801024bU, +/*02b0*/ 0x0001024cU, +/*02b1*/ 0x0804024cU, +/*02b2*/ 0x1004024cU, +/*02b3*/ 0x000a024dU, +/*02b4*/ 0x0020024eU, +/*02b5*/ 0x0004024fU, +/*02b6*/ 0x0808024fU, +/*02b7*/ 0xffffffffU, +/*02b8*/ 0xffffffffU, +/*02b9*/ 0xffffffffU, +/*02ba*/ 0xffffffffU, +/*02bb*/ 0xffffffffU, +/*02bc*/ 0xffffffffU, +/*02bd*/ 0x1002024fU, +/*02be*/ 0x1802024fU, +/*02bf*/ 0x00200250U, +/*02c0*/ 0x00020251U, +/*02c1*/ 0x08100251U, +/*02c2*/ 0x00100252U, +/*02c3*/ 0x10040252U, +/*02c4*/ 0x18040252U, +/*02c5*/ 0x00050253U, +/*02c6*/ 0x08050253U, +/*02c7*/ 0xffffffffU, +/*02c8*/ 0xffffffffU, +/*02c9*/ 0xffffffffU, +/*02ca*/ 0xffffffffU, +/*02cb*/ 0x10010253U, +/*02cc*/ 0x18010253U, +/*02cd*/ 0x00080254U, +/*02ce*/ 0x08080254U, +/*02cf*/ 0x10080254U, +/*02d0*/ 0x18080254U, +/*02d1*/ 0x00080255U, +/*02d2*/ 0x08080255U, +/*02d3*/ 0x10080255U, +/*02d4*/ 0x18080255U, +/*02d5*/ 0x00080256U, +/*02d6*/ 0x08080256U, +/*02d7*/ 0x10080256U, +/*02d8*/ 0xffffffffU, +/*02d9*/ 0xffffffffU, +/*02da*/ 0xffffffffU, +/*02db*/ 0xffffffffU, +/*02dc*/ 0xffffffffU, +/*02dd*/ 0xffffffffU, +/*02de*/ 0x18030256U, +/*02df*/ 0x00010257U, +/*02e0*/ 0x08020257U, +/*02e1*/ 0x10010257U, +/*02e2*/ 0x18040257U, +/*02e3*/ 0x00020258U, +/*02e4*/ 0x08010258U, +/*02e5*/ 0x10010258U, +/*02e6*/ 0xffffffffU, +/*02e7*/ 0x18010258U, +/*02e8*/ 0x00040259U, +/*02e9*/ 0x08080259U, +/*02ea*/ 0x100a0259U, +/*02eb*/ 0x000a025aU, +/*02ec*/ 0x100a025aU, +/*02ed*/ 0x000a025bU, +/*02ee*/ 0x100a025bU, +/*02ef*/ 0x000a025cU, +/*02f0*/ 0x0020025dU, +/*02f1*/ 0x0020025eU, +/*02f2*/ 0x0001025fU, +/*02f3*/ 0xffffffffU, +/*02f4*/ 0xffffffffU, +/*02f5*/ 0xffffffffU, +/*02f6*/ 0x0802025fU, +/*02f7*/ 0x1002025fU, +/*02f8*/ 0x00100260U, +/*02f9*/ 0x10050260U, +/*02fa*/ 0x18060260U, +/*02fb*/ 0x00050261U, +/*02fc*/ 0x08050261U, +/*02fd*/ 0x100e0261U, +/*02fe*/ 0x00050262U, +/*02ff*/ 0x080e0262U, +/*0300*/ 0x18050262U, +/*0301*/ 0x000e0263U, +/*0302*/ 0x10050263U, +/*0303*/ 0x18010263U, +/*0304*/ 0x00050264U, +/*0305*/ 0x08050264U, +/*0306*/ 0x100a0264U, +/*0307*/ 0x000a0265U, +/*0308*/ 0x10050265U, +/*0309*/ 0x18050265U, +/*030a*/ 0x000a0266U, +/*030b*/ 0x100a0266U, +/*030c*/ 0x00050267U, +/*030d*/ 0x08050267U, +/*030e*/ 0x100a0267U, +/*030f*/ 0x000a0268U, +/*0310*/ 0xffffffffU, +/*0311*/ 0xffffffffU, +/*0312*/ 0xffffffffU, +/*0313*/ 0xffffffffU, +/*0314*/ 0xffffffffU, +/*0315*/ 0xffffffffU, +/*0316*/ 0x10070268U, +/*0317*/ 0x18070268U, +/*0318*/ 0x00040269U, +/*0319*/ 0x08040269U, +/*031a*/ 0xffffffffU, +/*031b*/ 0xffffffffU, +/*031c*/ 0xffffffffU, +/*031d*/ 0x10040269U, +/*031e*/ 0x18080269U, +/*031f*/ 0x0008026aU, +/*0320*/ 0x0804026aU, +/*0321*/ 0xffffffffU, +/*0322*/ 0xffffffffU, +/*0323*/ 0xffffffffU, +/*0324*/ 0x1004026aU, +/*0325*/ 0xffffffffU, +/*0326*/ 0xffffffffU, +/*0327*/ 0xffffffffU, +/*0328*/ 0x1804026aU, +/*0329*/ 0xffffffffU, +/*032a*/ 0xffffffffU, +/*032b*/ 0xffffffffU, +/*032c*/ 0x0004026bU, +/*032d*/ 0x0805026bU, +/*032e*/ 0x1007026bU, +/*032f*/ 0x1808026bU, +/*0330*/ 0x0010026cU, +/*0331*/ 0x1008026cU, +/*0332*/ 0x0010026dU, +/*0333*/ 0x1008026dU, +/*0334*/ 0x0010026eU, +/*0335*/ 0x1008026eU, +/*0336*/ 0x1808026eU, +/*0337*/ 0x0001026fU, +/*0338*/ 0x0801026fU, +/*0339*/ 0x1006026fU, +/*033a*/ 0x1806026fU, +/*033b*/ 0x00060270U, +/*033c*/ 0xffffffffU, +/*033d*/ 0x08010270U, +/*033e*/ 0x10030270U, +/*033f*/ 0xffffffffU, +/*0340*/ 0xffffffffU, +/*0341*/ 0xffffffffU, +/*0342*/ 0x000a0271U, +/*0343*/ 0x100a0271U, +/*0344*/ 0x00040272U, +/*0345*/ 0x08010272U, +/*0346*/ 0x10040272U, +/*0347*/ 0xffffffffU, +/*0348*/ 0xffffffffU, +/*0349*/ 0xffffffffU, +/*034a*/ 0xffffffffU, +/*034b*/ 0xffffffffU, +/*034c*/ 0xffffffffU, +/*034d*/ 0x18070272U, +/*034e*/ 0x00070273U, +/*034f*/ 0x08050273U, +/*0350*/ 0x10050273U, +/*0351*/ 0xffffffffU, +/*0352*/ 0xffffffffU, +/*0353*/ 0xffffffffU, +/*0354*/ 0x18040273U, +/*0355*/ 0x00010274U, +/*0356*/ 0x08010274U, +/*0357*/ 0x10020274U, +/*0358*/ 0x18080274U, +/*0359*/ 0x00200275U, +/*035a*/ 0x00200276U, +/*035b*/ 0x00100277U, +/*035c*/ 0xffffffffU, +/*035d*/ 0xffffffffU, +/*035e*/ 0xffffffffU, +/*035f*/ 0x10020277U, +/*0360*/ 0x18010277U, +/*0361*/ 0xffffffffU, +/*0362*/ 0x00020278U, +/*0363*/ 0x08100278U, +/*0364*/ 0x00100279U, +/*0365*/ 0x10100279U, +/*0366*/ 0x0008027aU, +/*0367*/ 0x0808027aU, +/*0368*/ 0x1008027aU, +/*0369*/ 0xffffffffU, +/*036a*/ 0x0010027bU, +/*036b*/ 0x1010027bU, +/*036c*/ 0x0010027cU, +/*036d*/ 0x1008027cU, +/*036e*/ 0x1808027cU, +/*036f*/ 0x0008027dU, +/*0370*/ 0xffffffffU, +/*0371*/ 0x0810027dU, +/*0372*/ 0x0010027eU, +/*0373*/ 0x1010027eU, +/*0374*/ 0x0008027fU, +/*0375*/ 0x0808027fU, +/*0376*/ 0x1008027fU, +/*0377*/ 0xffffffffU, +/*0378*/ 0x1808027fU, +/*0379*/ 0x00100280U, +/*037a*/ 0x10100280U, +/*037b*/ 0x00100281U, +/*037c*/ 0x10080281U, +/*037d*/ 0x18080281U, +/*037e*/ 0x00080282U, +/*037f*/ 0xffffffffU, +/*0380*/ 0x08100282U, +/*0381*/ 0x00100283U, +/*0382*/ 0x10100283U, +/*0383*/ 0x00080284U, +/*0384*/ 0x08080284U, +/*0385*/ 0x10080284U, +/*0386*/ 0xffffffffU, +/*0387*/ 0x00100285U, +/*0388*/ 0x10100285U, +/*0389*/ 0x00100286U, +/*038a*/ 0x10080286U, +/*038b*/ 0x18080286U, +/*038c*/ 0x00080287U, +/*038d*/ 0xffffffffU, +/*038e*/ 0x08080287U, +/*038f*/ 0x10100287U, +/*0390*/ 0x00100288U, +/*0391*/ 0x10100288U, +/*0392*/ 0x00080289U, +/*0393*/ 0x08080289U, +/*0394*/ 0x10080289U, +/*0395*/ 0xffffffffU, +/*0396*/ 0x0010028aU, +/*0397*/ 0x1010028aU, +/*0398*/ 0x0010028bU, +/*0399*/ 0x1008028bU, +/*039a*/ 0x1808028bU, +/*039b*/ 0x0008028cU, +/*039c*/ 0xffffffffU, +/*039d*/ 0x0810028cU, +/*039e*/ 0x0010028dU, +/*039f*/ 0x1010028dU, +/*03a0*/ 0x0008028eU, +/*03a1*/ 0x0808028eU, +/*03a2*/ 0x1008028eU, +/*03a3*/ 0xffffffffU, +/*03a4*/ 0x1808028eU, +/*03a5*/ 0x0010028fU, +/*03a6*/ 0x1010028fU, +/*03a7*/ 0x00100290U, +/*03a8*/ 0x10080290U, +/*03a9*/ 0x18080290U, +/*03aa*/ 0x00080291U, +/*03ab*/ 0xffffffffU, +/*03ac*/ 0x08100291U, +/*03ad*/ 0x00100292U, +/*03ae*/ 0x10100292U, +/*03af*/ 0x00080293U, +/*03b0*/ 0x08080293U, +/*03b1*/ 0x10080293U, +/*03b2*/ 0xffffffffU, +/*03b3*/ 0x00100294U, +/*03b4*/ 0x10100294U, +/*03b5*/ 0x00100295U, +/*03b6*/ 0x10080295U, +/*03b7*/ 0x18080295U, +/*03b8*/ 0x00080296U, +/*03b9*/ 0xffffffffU, +/*03ba*/ 0x08080296U, +/*03bb*/ 0x10020296U, +/*03bc*/ 0x18030296U, +/*03bd*/ 0x000a0297U, +/*03be*/ 0x100a0297U, +/*03bf*/ 0x000a0298U, +/*03c0*/ 0x10050298U, +/*03c1*/ 0x18040298U, +/*03c2*/ 0x00080299U, +/*03c3*/ 0x08080299U, +/*03c4*/ 0x10060299U, +/*03c5*/ 0x18060299U, +/*03c6*/ 0x0011029aU, +/*03c7*/ 0x1808029aU, +/*03c8*/ 0x0004029bU, +/*03c9*/ 0x0806029bU, +/*03ca*/ 0xffffffffU, +/*03cb*/ 0x1006029bU, +/*03cc*/ 0x1808029bU, +/*03cd*/ 0x0008029cU, +/*03ce*/ 0x0804029cU, +/*03cf*/ 0x1008029cU, +/*03d0*/ 0x1808029cU, +/*03d1*/ 0x0006029dU, +/*03d2*/ 0x0806029dU, +/*03d3*/ 0x0011029eU, +/*03d4*/ 0x1808029eU, +/*03d5*/ 0x0004029fU, +/*03d6*/ 0x0806029fU, +/*03d7*/ 0xffffffffU, +/*03d8*/ 0x1006029fU, +/*03d9*/ 0x1808029fU, +/*03da*/ 0x000802a0U, +/*03db*/ 0x080402a0U, +/*03dc*/ 0x100802a0U, +/*03dd*/ 0x180802a0U, +/*03de*/ 0x000602a1U, +/*03df*/ 0x080602a1U, +/*03e0*/ 0x001102a2U, +/*03e1*/ 0x180802a2U, +/*03e2*/ 0x000402a3U, +/*03e3*/ 0x080602a3U, +/*03e4*/ 0xffffffffU, +/*03e5*/ 0x100602a3U, +/*03e6*/ 0x180802a3U, +/*03e7*/ 0x000802a4U, +/*03e8*/ 0x080402a4U, +/*03e9*/ 0x100402a4U, +/*03ea*/ 0x180402a4U, +/*03eb*/ 0x000402a5U, +/*03ec*/ 0x080402a5U, +/*03ed*/ 0x100402a5U, +/*03ee*/ 0x180402a5U, +/*03ef*/ 0x000402a6U, +/*03f0*/ 0x080402a6U, +/*03f1*/ 0x100402a6U, +/*03f2*/ 0x180402a6U, +/*03f3*/ 0x000402a7U, +/*03f4*/ 0x080402a7U, +/*03f5*/ 0x100402a7U, +/*03f6*/ 0x180402a7U, +/*03f7*/ 0x000402a8U, +/*03f8*/ 0x080402a8U, +/*03f9*/ 0x100402a8U, +/*03fa*/ 0x180402a8U, +/*03fb*/ 0x000402a9U, +/*03fc*/ 0x081202a9U, +/*03fd*/ 0x001102aaU, +/*03fe*/ 0x001202abU, +/*03ff*/ 0x002002acU, +/*0400*/ 0x002002adU, +/*0401*/ 0x002002aeU, +/*0402*/ 0x002002afU, +/*0403*/ 0x002002b0U, +/*0404*/ 0x002002b1U, +/*0405*/ 0x002002b2U, +/*0406*/ 0x002002b3U, +/*0407*/ 0x002002b4U, +/*0408*/ 0x000302b5U, +/*0409*/ 0x080502b5U, +/*040a*/ 0x100502b5U, +/*040b*/ 0x180102b5U, +/*040c*/ 0x000502b6U, +/*040d*/ 0x080502b6U, +/*040e*/ 0x100502b6U, +/*040f*/ 0x180502b6U, +/*0410*/ 0x000502b7U, +/*0411*/ 0x080502b7U, +/*0412*/ 0x100502b7U, +/*0413*/ 0x180502b7U, +/*0414*/ 0x000502b8U, +/*0415*/ 0x080502b8U, +/*0416*/ 0x100502b8U, +/*0417*/ 0x180502b8U, +/*0418*/ 0x000502b9U, +/*0419*/ 0x080502b9U, +/*041a*/ 0x100502b9U, +/*041b*/ 0x180502b9U, +/*041c*/ 0x000502baU, +/*041d*/ 0x080502baU, +/*041e*/ 0x100502baU, +/*041f*/ 0x180502baU, +/*0420*/ 0x000502bbU, +/*0421*/ 0x080502bbU, +/*0422*/ 0x100102bbU, +/*0423*/ 0x180202bbU, +/*0424*/ 0x000202bcU, +/*0425*/ 0x080202bcU, +/*0426*/ 0x100202bcU, +/*0427*/ 0x180102bcU, +/*0428*/ 0x000402bdU, +/*0429*/ 0x081002bdU, +/*042a*/ 0x002002beU, +/*042b*/ 0x001002bfU, +/*042c*/ 0x002002c0U, +/*042d*/ 0x001002c1U, +/*042e*/ 0x002002c2U, +/*042f*/ 0x000702c3U, +/*0430*/ 0x080102c3U, +/*0431*/ 0x100202c3U, +/*0432*/ 0x180602c3U, +/*0433*/ 0x000102c4U, +/*0434*/ 0x080102c4U, +/*0435*/ 0x002002c5U, +/*0436*/ 0x000302c6U, +/*0437*/ 0x002002c7U, +/*0438*/ 0x002002c8U, +/*0439*/ 0xffffffffU, +/*043a*/ 0xffffffffU, +/*043b*/ 0xffffffffU, +/*043c*/ 0xffffffffU, +/*043d*/ 0xffffffffU, +/*043e*/ 0xffffffffU, +/*043f*/ 0xffffffffU, +/*0440*/ 0xffffffffU, +/*0441*/ 0xffffffffU, +/*0442*/ 0xffffffffU, +/*0443*/ 0xffffffffU, +/*0444*/ 0xffffffffU, +/*0445*/ 0xffffffffU, +/*0446*/ 0xffffffffU, +/*0447*/ 0xffffffffU, +/*0448*/ 0xffffffffU, +/*0449*/ 0xffffffffU, +/*044a*/ 0xffffffffU, +/*044b*/ 0xffffffffU, +/*044c*/ 0xffffffffU, +/*044d*/ 0xffffffffU, +/*044e*/ 0xffffffffU, +/*044f*/ 0xffffffffU, +/*0450*/ 0xffffffffU, +/*0451*/ 0xffffffffU, +/*0452*/ 0xffffffffU, +/*0453*/ 0xffffffffU, +/*0454*/ 0xffffffffU, +/*0455*/ 0xffffffffU, +/*0456*/ 0xffffffffU, +/*0457*/ 0xffffffffU, +/*0458*/ 0xffffffffU, +/*0459*/ 0xffffffffU, +/*045a*/ 0xffffffffU, +/*045b*/ 0xffffffffU, +/*045c*/ 0xffffffffU, +/*045d*/ 0xffffffffU, +/*045e*/ 0xffffffffU, +/*045f*/ 0x000402c9U, +/*0460*/ 0xffffffffU, +/*0461*/ 0xffffffffU, +/*0462*/ 0xffffffffU, +/*0463*/ 0xffffffffU, +/*0464*/ 0xffffffffU, +/*0465*/ 0xffffffffU, +/*0466*/ 0xffffffffU, +/*0467*/ 0xffffffffU, +/*0468*/ 0xffffffffU, +/*0469*/ 0xffffffffU, +/*046a*/ 0xffffffffU, +/*046b*/ 0xffffffffU, +/*046c*/ 0xffffffffU, +/*046d*/ 0xffffffffU, +/*046e*/ 0xffffffffU, +/*046f*/ 0xffffffffU, +/*0470*/ 0xffffffffU, +/*0471*/ 0xffffffffU, +/*0472*/ 0xffffffffU, +/*0473*/ 0xffffffffU, +/*0474*/ 0xffffffffU, +/*0475*/ 0xffffffffU, +/*0476*/ 0xffffffffU, +/*0477*/ 0xffffffffU, +/*0478*/ 0xffffffffU, +/*0479*/ 0xffffffffU, +/*047a*/ 0xffffffffU, +/*047b*/ 0xffffffffU, +/*047c*/ 0xffffffffU, +/*047d*/ 0xffffffffU, +/*047e*/ 0xffffffffU, +/*047f*/ 0xffffffffU, +/*0480*/ 0xffffffffU, +/*0481*/ 0xffffffffU, +/*0482*/ 0xffffffffU, +/*0483*/ 0xffffffffU, +/*0484*/ 0xffffffffU, +/*0485*/ 0xffffffffU, +/*0486*/ 0xffffffffU, +/*0487*/ 0xffffffffU, +/*0488*/ 0xffffffffU, +/*0489*/ 0xffffffffU, +/*048a*/ 0xffffffffU, +/*048b*/ 0xffffffffU, +/*048c*/ 0xffffffffU, +/*048d*/ 0xffffffffU, +/*048e*/ 0xffffffffU, +/*048f*/ 0xffffffffU, +/*0490*/ 0xffffffffU, +/*0491*/ 0xffffffffU, +/*0492*/ 0xffffffffU, +/*0493*/ 0xffffffffU, +/*0494*/ 0xffffffffU, + }, + { +/*0000*/ 0x00200400U, +/*0001*/ 0x00040401U, +/*0002*/ 0x080b0401U, +/*0003*/ 0x000a0402U, +/*0004*/ 0x10020402U, +/*0005*/ 0x18010402U, +/*0006*/ 0x00050403U, +/*0007*/ 0x08050403U, +/*0008*/ 0x10050403U, +/*0009*/ 0x18050403U, +/*000a*/ 0x00050404U, +/*000b*/ 0x08050404U, +/*000c*/ 0x10050404U, +/*000d*/ 0x18050404U, +/*000e*/ 0x00050405U, +/*000f*/ 0x08040405U, +/*0010*/ 0x10030405U, +/*0011*/ 0x00180406U, +/*0012*/ 0x18030406U, +/*0013*/ 0x00180407U, +/*0014*/ 0x18020407U, +/*0015*/ 0x00010408U, +/*0016*/ 0x08020408U, +/*0017*/ 0x10010408U, +/*0018*/ 0x18010408U, +/*0019*/ 0x00020409U, +/*001a*/ 0x08040409U, +/*001b*/ 0x10040409U, +/*001c*/ 0x18040409U, +/*001d*/ 0xffffffffU, +/*001e*/ 0x0004040aU, +/*001f*/ 0xffffffffU, +/*0020*/ 0xffffffffU, +/*0021*/ 0x0809040aU, +/*0022*/ 0x1801040aU, +/*0023*/ 0x0020040bU, +/*0024*/ 0x001c040cU, +/*0025*/ 0x0001040dU, +/*0026*/ 0x0807040dU, +/*0027*/ 0x1009040dU, +/*0028*/ 0x000a040eU, +/*0029*/ 0x1005040eU, +/*002a*/ 0x1801040eU, +/*002b*/ 0x1001040fU, +/*002c*/ 0x1802040fU, +/*002d*/ 0x0009040fU, +/*002e*/ 0x00090410U, +/*002f*/ 0x10020410U, +/*0030*/ 0x00200411U, +/*0031*/ 0x00010412U, +/*0032*/ 0x08020412U, +/*0033*/ 0xffffffffU, +/*0034*/ 0xffffffffU, +/*0035*/ 0xffffffffU, +/*0036*/ 0xffffffffU, +/*0037*/ 0x00200413U, +/*0038*/ 0x00200414U, +/*0039*/ 0x00200415U, +/*003a*/ 0x00200416U, +/*003b*/ 0x00030417U, +/*003c*/ 0x08010417U, +/*003d*/ 0x10040417U, +/*003e*/ 0x18030417U, +/*003f*/ 0x00040418U, +/*0040*/ 0x08040418U, +/*0041*/ 0x10040418U, +/*0042*/ 0x18040418U, +/*0043*/ 0x00010419U, +/*0044*/ 0x08010419U, +/*0045*/ 0x10060419U, +/*0046*/ 0x18040419U, +/*0047*/ 0xffffffffU, +/*0048*/ 0x0006041aU, +/*0049*/ 0x0804041aU, +/*004a*/ 0x1006041aU, +/*004b*/ 0x1804041aU, +/*004c*/ 0x0002041bU, +/*004d*/ 0x0805041bU, +/*004e*/ 0x1008041bU, +/*004f*/ 0xffffffffU, +/*0050*/ 0x1806041bU, +/*0051*/ 0x0003041cU, +/*0052*/ 0x080b041cU, +/*0053*/ 0x1804041cU, +/*0054*/ 0x0004041dU, +/*0055*/ 0x0804041dU, +/*0056*/ 0x1001041dU, +/*0057*/ 0xffffffffU, +/*0058*/ 0x0009041eU, +/*0059*/ 0x0020041fU, +/*005a*/ 0x00200420U, +/*005b*/ 0x00200421U, +/*005c*/ 0x00200422U, +/*005d*/ 0x00100423U, +/*005e*/ 0xffffffffU, +/*005f*/ 0x10010423U, +/*0060*/ 0x18060423U, +/*0061*/ 0x00080424U, +/*0062*/ 0x00200425U, +/*0063*/ 0x00100426U, +/*0064*/ 0x100a0426U, +/*0065*/ 0x00060427U, +/*0066*/ 0x08070427U, +/*0067*/ 0x10080427U, +/*0068*/ 0x18080427U, +/*0069*/ 0x000a0428U, +/*006a*/ 0x10070428U, +/*006b*/ 0x18080428U, +/*006c*/ 0x00080429U, +/*006d*/ 0x08030429U, +/*006e*/ 0x100a0429U, +/*006f*/ 0x000a042aU, +/*0070*/ 0x0011042bU, +/*0071*/ 0x0009042cU, +/*0072*/ 0x1009042cU, +/*0073*/ 0x0010042dU, +/*0074*/ 0x100e042dU, +/*0075*/ 0x000e042eU, +/*0076*/ 0x0012042fU, +/*0077*/ 0x000a0430U, +/*0078*/ 0x100a0430U, +/*0079*/ 0x00020431U, +/*007a*/ 0x00200432U, +/*007b*/ 0x000b0433U, +/*007c*/ 0x100b0433U, +/*007d*/ 0x00200434U, +/*007e*/ 0x00120435U, +/*007f*/ 0x00200436U, +/*0080*/ 0x00200437U, +/*0081*/ 0x00080438U, +/*0082*/ 0x08010438U, +/*0083*/ 0x10010438U, +/*0084*/ 0x18010438U, +/*0085*/ 0x00080439U, +/*0086*/ 0x080c0439U, +/*0087*/ 0x000c043aU, +/*0088*/ 0x100c043aU, +/*0089*/ 0x000c043bU, +/*008a*/ 0x100c043bU, +/*008b*/ 0x000c043cU, +/*008c*/ 0x100c043cU, +/*008d*/ 0x000c043dU, +/*008e*/ 0x100c043dU, +/*008f*/ 0x000c043eU, +/*0090*/ 0x100c043eU, +/*0091*/ 0x000b043fU, +/*0092*/ 0x1009043fU, +/*0093*/ 0x00010440U, +/*0094*/ 0x000b0441U, +/*0095*/ 0x100b0441U, +/*0096*/ 0x000b0442U, +/*0097*/ 0x100b0442U, +/*0098*/ 0x000b0443U, +/*0099*/ 0x100b0443U, +/*009a*/ 0x000b0444U, +/*009b*/ 0x100b0444U, +/*009c*/ 0x000b0445U, +/*009d*/ 0x100a0445U, +/*009e*/ 0x00020446U, +/*009f*/ 0x080a0446U, +/*00a0*/ 0x000a0447U, +/*00a1*/ 0x100a0447U, +/*00a2*/ 0x000a0448U, +/*00a3*/ 0x100a0448U, +/*00a4*/ 0x000a0449U, +/*00a5*/ 0x100a0449U, +/*00a6*/ 0x000a044aU, +/*00a7*/ 0x100a044aU, +/*00a8*/ 0x000a044bU, +/*00a9*/ 0x100a044bU, +/*00aa*/ 0x000a044cU, +/*00ab*/ 0x100a044cU, +/*00ac*/ 0x000a044dU, +/*00ad*/ 0x100a044dU, +/*00ae*/ 0x000a044eU, +/*00af*/ 0x100a044eU, +/*00b0*/ 0x000a044fU, +/*00b1*/ 0x100a044fU, +/*00b2*/ 0x000a0450U, +/*00b3*/ 0x100a0450U, +/*00b4*/ 0x000a0451U, +/*00b5*/ 0x100a0451U, +/*00b6*/ 0x000a0452U, +/*00b7*/ 0x100a0452U, +/*00b8*/ 0x000a0453U, +/*00b9*/ 0x100a0453U, +/*00ba*/ 0x000a0454U, +/*00bb*/ 0x10040454U, +/*00bc*/ 0x18030454U, +/*00bd*/ 0x000a0455U, +/*00be*/ 0x100a0455U, +/*00bf*/ 0x00010456U, +/*00c0*/ 0x080a0456U, +/*00c1*/ 0x18040456U, +/*00c2*/ 0x000b0457U, +/*00c3*/ 0x100a0457U, +/*00c4*/ 0x00030458U, +/*00c5*/ 0x00080459U, +/*00c6*/ 0x08080459U, +/*00c7*/ 0x10080459U, +/*00c8*/ 0x18080459U, +/*00c9*/ 0x0008045aU, +/*00ca*/ 0xffffffffU, +/*00cb*/ 0x0808045aU, +/*00cc*/ 0x1001045aU, +/*00cd*/ 0x1808045aU, +/*00ce*/ 0x0008045bU, +/*00cf*/ 0x0802045bU, +/*00d0*/ 0x1002045bU, +/*00d1*/ 0x1805045bU, +/*00d2*/ 0x0005045cU, +/*00d3*/ 0xffffffffU, +/*00d4*/ 0x0804045cU, +/*00d5*/ 0x100a045cU, +/*00d6*/ 0x0006045dU, +/*00d7*/ 0x0808045dU, +/*00d8*/ 0x1008045dU, +/*00d9*/ 0x1804045dU, +/*00da*/ 0x0004045eU, +/*00db*/ 0x0805045eU, +/*00dc*/ 0x1004045eU, +/*00dd*/ 0x1805045eU, +/*00de*/ 0x000a045fU, +/*00df*/ 0x100a045fU, +/*00e0*/ 0x00080460U, +/*00e1*/ 0xffffffffU, +/*00e2*/ 0x08040460U, +/*00e3*/ 0xffffffffU, +/*00e4*/ 0xffffffffU, +/*00e5*/ 0x00050600U, +/*00e6*/ 0x08050600U, +/*00e7*/ 0x10050600U, +/*00e8*/ 0x18050600U, +/*00e9*/ 0x00050601U, +/*00ea*/ 0x08050601U, +/*00eb*/ 0x100b0601U, +/*00ec*/ 0x00010602U, +/*00ed*/ 0x08030602U, +/*00ee*/ 0x00200603U, +/*00ef*/ 0x00100604U, +/*00f0*/ 0x10040604U, +/*00f1*/ 0x000a0605U, +/*00f2*/ 0x10090605U, +/*00f3*/ 0x00080606U, +/*00f4*/ 0x08030606U, +/*00f5*/ 0x10030606U, +/*00f6*/ 0x18010606U, +/*00f7*/ 0x00010607U, +/*00f8*/ 0x08070607U, +/*00f9*/ 0x10070607U, +/*00fa*/ 0x18050607U, +/*00fb*/ 0x00010608U, +/*00fc*/ 0x08020608U, +/*00fd*/ 0x10030608U, +/*00fe*/ 0x18010608U, +/*00ff*/ 0x000f0609U, +/*0100*/ 0x0020060aU, +/*0101*/ 0x0020060bU, +/*0102*/ 0x000b060cU, +/*0103*/ 0x100b060cU, +/*0104*/ 0x000b060dU, +/*0105*/ 0x0018060eU, +/*0106*/ 0x0018060fU, +/*0107*/ 0xffffffffU, +/*0108*/ 0xffffffffU, +/*0109*/ 0xffffffffU, +/*010a*/ 0xffffffffU, +/*010b*/ 0xffffffffU, +/*010c*/ 0x1802060fU, +/*010d*/ 0x00020610U, +/*010e*/ 0x08040610U, +/*010f*/ 0x10040610U, +/*0110*/ 0x18010610U, +/*0111*/ 0x00010611U, +/*0112*/ 0x08010611U, +/*0113*/ 0x10030611U, +/*0114*/ 0x00200612U, +/*0115*/ 0x00200613U, +/*0116*/ 0xffffffffU, +/*0117*/ 0x00140614U, +/*0118*/ 0x00140615U, +/*0119*/ 0x00140616U, +/*011a*/ 0x00140617U, +/*011b*/ 0x00140618U, +/*011c*/ 0x00140619U, +/*011d*/ 0x0014061aU, +/*011e*/ 0x0014061bU, +/*011f*/ 0x0018061cU, +/*0120*/ 0x000a061dU, +/*0121*/ 0x1006061dU, +/*0122*/ 0x1806061dU, +/*0123*/ 0x0006061eU, +/*0124*/ 0xffffffffU, +/*0125*/ 0x0806061eU, +/*0126*/ 0x0008061fU, +/*0127*/ 0x080b061fU, +/*0128*/ 0x000b0620U, +/*0129*/ 0x100b0620U, +/*012a*/ 0x000b0621U, +/*012b*/ 0x100b0621U, +/*012c*/ 0x000b0622U, +/*012d*/ 0x10040622U, +/*012e*/ 0x000a0623U, +/*012f*/ 0x10060623U, +/*0130*/ 0x18080623U, +/*0131*/ 0x00080624U, +/*0132*/ 0x08040624U, +/*0133*/ 0x00020680U, +/*0134*/ 0x00010681U, +/*0135*/ 0x08010681U, +/*0136*/ 0x10020681U, +/*0137*/ 0x18050681U, +/*0138*/ 0x00050682U, +/*0139*/ 0x08050682U, +/*013a*/ 0x10050682U, +/*013b*/ 0x000b0683U, +/*013c*/ 0x10050683U, +/*013d*/ 0x18010683U, +/*013e*/ 0x00010684U, +/*013f*/ 0xffffffffU, +/*0140*/ 0x08010684U, +/*0141*/ 0x10010684U, +/*0142*/ 0x18040684U, +/*0143*/ 0x000b0685U, +/*0144*/ 0x100b0685U, +/*0145*/ 0x000b0686U, +/*0146*/ 0x10040686U, +/*0147*/ 0x000b0687U, +/*0148*/ 0x10040687U, +/*0149*/ 0x18010687U, +/*014a*/ 0x00010688U, +/*014b*/ 0x08010688U, +/*014c*/ 0x00200689U, +/*014d*/ 0x0020068aU, +/*014e*/ 0x0008068bU, +/*014f*/ 0x080a068bU, +/*0150*/ 0x1805068bU, +/*0151*/ 0x000a068cU, +/*0152*/ 0x1003068cU, +/*0153*/ 0x1803068cU, +/*0154*/ 0x0001068dU, +/*0155*/ 0x0802068dU, +/*0156*/ 0x1001068dU, +/*0157*/ 0x1801068dU, +/*0158*/ 0x0001068eU, +/*0159*/ 0x0802068eU, +/*015a*/ 0x1001068eU, +/*015b*/ 0x0004068fU, +/*015c*/ 0x0804068fU, +/*015d*/ 0x1004068fU, +/*015e*/ 0x1804068fU, +/*015f*/ 0x00010690U, +/*0160*/ 0x08010690U, +/*0161*/ 0x10010690U, +/*0162*/ 0x00200691U, +/*0163*/ 0x00200692U, +/*0164*/ 0x00200693U, +/*0165*/ 0x00200694U, +/*0166*/ 0xffffffffU, +/*0167*/ 0x1801068eU, +/*0168*/ 0x000d0696U, +/*0169*/ 0x100d0696U, +/*016a*/ 0x000d0697U, +/*016b*/ 0x00050698U, +/*016c*/ 0x00010699U, +/*016d*/ 0x080e0699U, +/*016e*/ 0x000e069aU, +/*016f*/ 0x100e069aU, +/*0170*/ 0x000e069bU, +/*0171*/ 0x100e069bU, +/*0172*/ 0x0004069cU, +/*0173*/ 0x0804069cU, +/*0174*/ 0x1004069cU, +/*0175*/ 0x1804069cU, +/*0176*/ 0x0004069dU, +/*0177*/ 0x080b069dU, +/*0178*/ 0x000b069eU, +/*0179*/ 0x100b069eU, +/*017a*/ 0x000b069fU, +/*017b*/ 0xffffffffU, +/*017c*/ 0xffffffffU, +/*017d*/ 0xffffffffU, +/*017e*/ 0xffffffffU, +/*017f*/ 0x000d06a0U, +/*0180*/ 0x100d06a0U, +/*0181*/ 0x000d06a1U, +/*0182*/ 0x101006a1U, +/*0183*/ 0x00080695U, +/*0184*/ 0x08080695U, +/*0185*/ 0x001006a2U, +/*0186*/ 0x101006a2U, +/*0187*/ 0x001006a3U, +/*0188*/ 0x101006a3U, +/*0189*/ 0x001006a4U, +/*018a*/ 0x100306a4U, +/*018b*/ 0x180406a4U, +/*018c*/ 0x000106a5U, +/*018d*/ 0x080806a5U, +/*018e*/ 0x100106a5U, +/*018f*/ 0x180506a5U, +/*0190*/ 0x000106a6U, +/*0191*/ 0x081406a6U, +/*0192*/ 0x000a06a7U, +/*0193*/ 0x100c06a7U, +/*0194*/ 0x001206a8U, +/*0195*/ 0x001406a9U, +/*0196*/ 0x001206aaU, +/*0197*/ 0x001106abU, +/*0198*/ 0x001106acU, +/*0199*/ 0x001206adU, +/*019a*/ 0x001206aeU, +/*019b*/ 0x001206afU, +/*019c*/ 0x001206b0U, +/*019d*/ 0x001206b1U, +/*019e*/ 0x001206b2U, +/*019f*/ 0x001206b3U, +/*01a0*/ 0x001206b4U, +/*01a1*/ 0x001206b5U, +/*01a2*/ 0x001206b6U, +/*01a3*/ 0x000e06b7U, +/*01a4*/ 0x100d06b7U, +/*01a5*/ 0x002006b8U, +/*01a6*/ 0x001706b9U, +/*01a7*/ 0x000906baU, +/*01a8*/ 0x100106baU, +/*01a9*/ 0x180106baU, +/*01aa*/ 0x002006bbU, +/*01ab*/ 0x000806bcU, +/*01ac*/ 0x080306bcU, +/*01ad*/ 0x100306bcU, +/*01ae*/ 0x001806bdU, +/*01af*/ 0x001806beU, +/*01b0*/ 0x180706beU, +/*01b1*/ 0x000506bfU, +/*01b2*/ 0x080806bfU, +/*01b3*/ 0x100806bfU, +/*01b4*/ 0x180806bfU, +/*01b5*/ 0x000106c0U, +/*01b6*/ 0x080106c0U, +/*01b7*/ 0x002006c1U, +/*01b8*/ 0xffffffffU, +/*01b9*/ 0xffffffffU, +/*01ba*/ 0xffffffffU, +/*01bb*/ 0xffffffffU, +/*01bc*/ 0xffffffffU, +/*01bd*/ 0xffffffffU, +/*01be*/ 0xffffffffU, +/*01bf*/ 0x001006c2U, +/*01c0*/ 0x100106c2U, +/*01c1*/ 0x180106c2U, +/*01c2*/ 0x000206c3U, +/*01c3*/ 0x080406c3U, +/*01c4*/ 0x100906c3U, +/*01c5*/ 0x000706c4U, +/*01c6*/ 0x080406c4U, +/*01c7*/ 0x002006c5U, +/*01c8*/ 0x000106c6U, +/*01c9*/ 0x080206c6U, +/*01ca*/ 0x100606c6U, +/*01cb*/ 0x001006c7U, +/*01cc*/ 0x100106c7U, +/*01cd*/ 0x002006c8U, +/*01ce*/ 0x000806c9U, +/*01cf*/ 0x080106c9U, +/*01d0*/ 0x100506c9U, +/*01d1*/ 0xffffffffU, +/*01d2*/ 0x180206c9U, +/*01d3*/ 0x000106caU, +/*01d4*/ 0x002006cbU, +/*01d5*/ 0x000b06ccU, +/*01d6*/ 0x100106ccU, +/*01d7*/ 0x180306ccU, +/*01d8*/ 0x000806cdU, +/*01d9*/ 0x080206cdU, +/*01da*/ 0x100c06cdU, +/*01db*/ 0x000406ceU, +/*01dc*/ 0x080106ceU, +/*01dd*/ 0xffffffffU, +/*01de*/ 0x00010200U, +/*01df*/ 0x08040200U, +/*01e0*/ 0x10100200U, +/*01e1*/ 0x00010201U, +/*01e2*/ 0x08010201U, +/*01e3*/ 0x10010201U, +/*01e4*/ 0xffffffffU, +/*01e5*/ 0x00100202U, +/*01e6*/ 0x10080202U, +/*01e7*/ 0xffffffffU, +/*01e8*/ 0xffffffffU, +/*01e9*/ 0xffffffffU, +/*01ea*/ 0xffffffffU, +/*01eb*/ 0xffffffffU, +/*01ec*/ 0xffffffffU, +/*01ed*/ 0xffffffffU, +/*01ee*/ 0xffffffffU, +/*01ef*/ 0x00200203U, +/*01f0*/ 0x00100204U, +/*01f1*/ 0x00200205U, +/*01f2*/ 0x00100206U, +/*01f3*/ 0x00200207U, +/*01f4*/ 0x00100208U, +/*01f5*/ 0x00140209U, +/*01f6*/ 0x0020020aU, +/*01f7*/ 0x0020020bU, +/*01f8*/ 0x0020020cU, +/*01f9*/ 0x0020020dU, +/*01fa*/ 0x0014020eU, +/*01fb*/ 0x0020020fU, +/*01fc*/ 0x00200210U, +/*01fd*/ 0x00200211U, +/*01fe*/ 0x00200212U, +/*01ff*/ 0x00140213U, +/*0200*/ 0x00200214U, +/*0201*/ 0x00200215U, +/*0202*/ 0x00200216U, +/*0203*/ 0x00200217U, +/*0204*/ 0x00090218U, +/*0205*/ 0x10010218U, +/*0206*/ 0x00200219U, +/*0207*/ 0x0005021aU, +/*0208*/ 0x0801021aU, +/*0209*/ 0x1008021aU, +/*020a*/ 0x1808021aU, +/*020b*/ 0x001c021bU, +/*020c*/ 0x001c021cU, +/*020d*/ 0x001c021dU, +/*020e*/ 0x001c021eU, +/*020f*/ 0x001c021fU, +/*0210*/ 0x001c0220U, +/*0211*/ 0x001c0221U, +/*0212*/ 0x001c0222U, +/*0213*/ 0x001c0223U, +/*0214*/ 0x001c0224U, +/*0215*/ 0x001c0225U, +/*0216*/ 0x001c0226U, +/*0217*/ 0x001c0227U, +/*0218*/ 0x001c0228U, +/*0219*/ 0x001c0229U, +/*021a*/ 0x001c022aU, +/*021b*/ 0x0001022bU, +/*021c*/ 0x0801022bU, +/*021d*/ 0x1001022bU, +/*021e*/ 0x1804022bU, +/*021f*/ 0x0008022cU, +/*0220*/ 0x0808022cU, +/*0221*/ 0x1008022cU, +/*0222*/ 0x1804022cU, +/*0223*/ 0x0007022dU, +/*0224*/ 0xffffffffU, +/*0225*/ 0x0807022dU, +/*0226*/ 0x1007022dU, +/*0227*/ 0xffffffffU, +/*0228*/ 0x1807022dU, +/*0229*/ 0x0007022eU, +/*022a*/ 0xffffffffU, +/*022b*/ 0x0807022eU, +/*022c*/ 0x1002022eU, +/*022d*/ 0x1801022eU, +/*022e*/ 0x0001022fU, +/*022f*/ 0x080a022fU, +/*0230*/ 0x00140230U, +/*0231*/ 0x000a0231U, +/*0232*/ 0x00140232U, +/*0233*/ 0x000a0233U, +/*0234*/ 0x00140234U, +/*0235*/ 0x18010234U, +/*0236*/ 0x00100235U, +/*0237*/ 0x10050235U, +/*0238*/ 0x18010235U, +/*0239*/ 0x00010236U, +/*023a*/ 0x08010236U, +/*023b*/ 0x10010236U, +/*023c*/ 0x18010236U, +/*023d*/ 0x00010237U, +/*023e*/ 0x08010237U, +/*023f*/ 0x10020237U, +/*0240*/ 0x18020237U, +/*0241*/ 0x00020238U, +/*0242*/ 0x08020238U, +/*0243*/ 0x10020238U, +/*0244*/ 0x18030238U, +/*0245*/ 0x00010239U, +/*0246*/ 0x08010239U, +/*0247*/ 0x10010239U, +/*0248*/ 0x18010239U, +/*0249*/ 0xffffffffU, +/*024a*/ 0x0002023aU, +/*024b*/ 0x0801023aU, +/*024c*/ 0x1001023aU, +/*024d*/ 0xffffffffU, +/*024e*/ 0x1802023aU, +/*024f*/ 0x0001023bU, +/*0250*/ 0x0801023bU, +/*0251*/ 0xffffffffU, +/*0252*/ 0x1002023bU, +/*0253*/ 0x1801023bU, +/*0254*/ 0x0001023cU, +/*0255*/ 0xffffffffU, +/*0256*/ 0x0802023cU, +/*0257*/ 0x1007023cU, +/*0258*/ 0x1801023cU, +/*0259*/ 0x0001023dU, +/*025a*/ 0x0801023dU, +/*025b*/ 0x1001023dU, +/*025c*/ 0x1801023dU, +/*025d*/ 0x0001023eU, +/*025e*/ 0x0801023eU, +/*025f*/ 0x1001023eU, +/*0260*/ 0x1804023eU, +/*0261*/ 0x0004023fU, +/*0262*/ 0x0804023fU, +/*0263*/ 0x1001023fU, +/*0264*/ 0x1802023fU, +/*0265*/ 0x00060240U, +/*0266*/ 0x08060240U, +/*0267*/ 0x10020240U, +/*0268*/ 0x18020240U, +/*0269*/ 0x00020241U, +/*026a*/ 0xffffffffU, +/*026b*/ 0x08100241U, +/*026c*/ 0x18010241U, +/*026d*/ 0x00010242U, +/*026e*/ 0x08010242U, +/*026f*/ 0x10040242U, +/*0270*/ 0x18010242U, +/*0271*/ 0x00040243U, +/*0272*/ 0x08020243U, +/*0273*/ 0x10080243U, +/*0274*/ 0xffffffffU, +/*0275*/ 0xffffffffU, +/*0276*/ 0xffffffffU, +/*0277*/ 0x000a0244U, +/*0278*/ 0x00200245U, +/*0279*/ 0x00200246U, +/*027a*/ 0x00050247U, +/*027b*/ 0x08010247U, +/*027c*/ 0x10050247U, +/*027d*/ 0x18080247U, +/*027e*/ 0x00010248U, +/*027f*/ 0x08080248U, +/*0280*/ 0x10010248U, +/*0281*/ 0x18080248U, +/*0282*/ 0x00010249U, +/*0283*/ 0x08040249U, +/*0284*/ 0x10040249U, +/*0285*/ 0x18040249U, +/*0286*/ 0x0004024aU, +/*0287*/ 0x0804024aU, +/*0288*/ 0x1004024aU, +/*0289*/ 0x1804024aU, +/*028a*/ 0x0004024bU, +/*028b*/ 0x0804024bU, +/*028c*/ 0x1004024bU, +/*028d*/ 0x1801024bU, +/*028e*/ 0x0004024cU, +/*028f*/ 0x0804024cU, +/*0290*/ 0x1004024cU, +/*0291*/ 0x1804024cU, +/*0292*/ 0x0004024dU, +/*0293*/ 0x0804024dU, +/*0294*/ 0x1006024dU, +/*0295*/ 0x1806024dU, +/*0296*/ 0x0006024eU, +/*0297*/ 0x0806024eU, +/*0298*/ 0x1006024eU, +/*0299*/ 0x1806024eU, +/*029a*/ 0xffffffffU, +/*029b*/ 0x0001024fU, +/*029c*/ 0x0801024fU, +/*029d*/ 0x1002024fU, +/*029e*/ 0xffffffffU, +/*029f*/ 0xffffffffU, +/*02a0*/ 0xffffffffU, +/*02a1*/ 0xffffffffU, +/*02a2*/ 0xffffffffU, +/*02a3*/ 0xffffffffU, +/*02a4*/ 0xffffffffU, +/*02a5*/ 0xffffffffU, +/*02a6*/ 0x1804024fU, +/*02a7*/ 0x00040250U, +/*02a8*/ 0x08010250U, +/*02a9*/ 0x10010250U, +/*02aa*/ 0x18010250U, +/*02ab*/ 0x00010251U, +/*02ac*/ 0x08010251U, +/*02ad*/ 0x10010251U, +/*02ae*/ 0x18010251U, +/*02af*/ 0x00010252U, +/*02b0*/ 0x08010252U, +/*02b1*/ 0x10040252U, +/*02b2*/ 0x18040252U, +/*02b3*/ 0x000a0253U, +/*02b4*/ 0x00200254U, +/*02b5*/ 0x00040255U, +/*02b6*/ 0x08080255U, +/*02b7*/ 0x10020255U, +/*02b8*/ 0x18020255U, +/*02b9*/ 0x00020256U, +/*02ba*/ 0x08020256U, +/*02bb*/ 0x10020256U, +/*02bc*/ 0x18020256U, +/*02bd*/ 0xffffffffU, +/*02be*/ 0xffffffffU, +/*02bf*/ 0x00200257U, +/*02c0*/ 0x00020258U, +/*02c1*/ 0x08100258U, +/*02c2*/ 0x00100259U, +/*02c3*/ 0x10040259U, +/*02c4*/ 0x18040259U, +/*02c5*/ 0x0005025aU, +/*02c6*/ 0x0805025aU, +/*02c7*/ 0x0020025bU, +/*02c8*/ 0x0020025cU, +/*02c9*/ 0x0020025dU, +/*02ca*/ 0x0020025eU, +/*02cb*/ 0x0001025fU, +/*02cc*/ 0x0801025fU, +/*02cd*/ 0x1007025fU, +/*02ce*/ 0x1807025fU, +/*02cf*/ 0x00070260U, +/*02d0*/ 0x08070260U, +/*02d1*/ 0x10070260U, +/*02d2*/ 0x18070260U, +/*02d3*/ 0x00070261U, +/*02d4*/ 0x08070261U, +/*02d5*/ 0x10070261U, +/*02d6*/ 0x18070261U, +/*02d7*/ 0x00070262U, +/*02d8*/ 0x08070262U, +/*02d9*/ 0x10070262U, +/*02da*/ 0x18070262U, +/*02db*/ 0x00030263U, +/*02dc*/ 0x08030263U, +/*02dd*/ 0x10030263U, +/*02de*/ 0xffffffffU, +/*02df*/ 0x18010263U, +/*02e0*/ 0x00020264U, +/*02e1*/ 0x08010264U, +/*02e2*/ 0x10040264U, +/*02e3*/ 0x18020264U, +/*02e4*/ 0x00010265U, +/*02e5*/ 0x08010265U, +/*02e6*/ 0x10010265U, +/*02e7*/ 0x18010265U, +/*02e8*/ 0x00040266U, +/*02e9*/ 0x08080266U, +/*02ea*/ 0x100a0266U, +/*02eb*/ 0x000a0267U, +/*02ec*/ 0x100a0267U, +/*02ed*/ 0x000a0268U, +/*02ee*/ 0x100a0268U, +/*02ef*/ 0x000a0269U, +/*02f0*/ 0x0020026aU, +/*02f1*/ 0x0020026bU, +/*02f2*/ 0x0001026cU, +/*02f3*/ 0x0802026cU, +/*02f4*/ 0x1002026cU, +/*02f5*/ 0x1802026cU, +/*02f6*/ 0xffffffffU, +/*02f7*/ 0x0002026dU, +/*02f8*/ 0x0810026dU, +/*02f9*/ 0x1805026dU, +/*02fa*/ 0x0006026eU, +/*02fb*/ 0x0805026eU, +/*02fc*/ 0x1005026eU, +/*02fd*/ 0x000e026fU, +/*02fe*/ 0x1005026fU, +/*02ff*/ 0x000e0270U, +/*0300*/ 0x10050270U, +/*0301*/ 0x000e0271U, +/*0302*/ 0x10050271U, +/*0303*/ 0x18010271U, +/*0304*/ 0x00050272U, +/*0305*/ 0x08050272U, +/*0306*/ 0x100a0272U, +/*0307*/ 0x000a0273U, +/*0308*/ 0x10050273U, +/*0309*/ 0x18050273U, +/*030a*/ 0x000a0274U, +/*030b*/ 0x100a0274U, +/*030c*/ 0x00050275U, +/*030d*/ 0x08050275U, +/*030e*/ 0x100a0275U, +/*030f*/ 0x000a0276U, +/*0310*/ 0xffffffffU, +/*0311*/ 0xffffffffU, +/*0312*/ 0xffffffffU, +/*0313*/ 0xffffffffU, +/*0314*/ 0xffffffffU, +/*0315*/ 0xffffffffU, +/*0316*/ 0x10070276U, +/*0317*/ 0x18070276U, +/*0318*/ 0x00040277U, +/*0319*/ 0x08040277U, +/*031a*/ 0xffffffffU, +/*031b*/ 0xffffffffU, +/*031c*/ 0xffffffffU, +/*031d*/ 0x10040277U, +/*031e*/ 0x18080277U, +/*031f*/ 0x00080278U, +/*0320*/ 0x08040278U, +/*0321*/ 0xffffffffU, +/*0322*/ 0xffffffffU, +/*0323*/ 0xffffffffU, +/*0324*/ 0x10040278U, +/*0325*/ 0xffffffffU, +/*0326*/ 0xffffffffU, +/*0327*/ 0xffffffffU, +/*0328*/ 0x18040278U, +/*0329*/ 0xffffffffU, +/*032a*/ 0xffffffffU, +/*032b*/ 0xffffffffU, +/*032c*/ 0x00040279U, +/*032d*/ 0x08050279U, +/*032e*/ 0x10070279U, +/*032f*/ 0x18080279U, +/*0330*/ 0x0010027aU, +/*0331*/ 0x1008027aU, +/*0332*/ 0x0010027bU, +/*0333*/ 0x1008027bU, +/*0334*/ 0x0010027cU, +/*0335*/ 0x1008027cU, +/*0336*/ 0x1808027cU, +/*0337*/ 0x0001027dU, +/*0338*/ 0x0801027dU, +/*0339*/ 0x1006027dU, +/*033a*/ 0x1806027dU, +/*033b*/ 0x0006027eU, +/*033c*/ 0x0801027eU, +/*033d*/ 0x1001027eU, +/*033e*/ 0x1803027eU, +/*033f*/ 0x000a027fU, +/*0340*/ 0x100a027fU, +/*0341*/ 0x000a0280U, +/*0342*/ 0xffffffffU, +/*0343*/ 0x100a0280U, +/*0344*/ 0x00040281U, +/*0345*/ 0x08010281U, +/*0346*/ 0x10040281U, +/*0347*/ 0xffffffffU, +/*0348*/ 0xffffffffU, +/*0349*/ 0xffffffffU, +/*034a*/ 0xffffffffU, +/*034b*/ 0xffffffffU, +/*034c*/ 0xffffffffU, +/*034d*/ 0x18070281U, +/*034e*/ 0x00070282U, +/*034f*/ 0x08050282U, +/*0350*/ 0x10050282U, +/*0351*/ 0xffffffffU, +/*0352*/ 0xffffffffU, +/*0353*/ 0xffffffffU, +/*0354*/ 0x18040282U, +/*0355*/ 0x00010283U, +/*0356*/ 0x08010283U, +/*0357*/ 0x10020283U, +/*0358*/ 0x18080283U, +/*0359*/ 0x00200284U, +/*035a*/ 0x00200285U, +/*035b*/ 0x00100286U, +/*035c*/ 0x10020286U, +/*035d*/ 0x18020286U, +/*035e*/ 0x00020287U, +/*035f*/ 0xffffffffU, +/*0360*/ 0x08010287U, +/*0361*/ 0x10010287U, +/*0362*/ 0x18020287U, +/*0363*/ 0x00080288U, +/*0364*/ 0x08080288U, +/*0365*/ 0x10080288U, +/*0366*/ 0x18080288U, +/*0367*/ 0x00080289U, +/*0368*/ 0x08080289U, +/*0369*/ 0xffffffffU, +/*036a*/ 0x10080289U, +/*036b*/ 0x18080289U, +/*036c*/ 0x0008028aU, +/*036d*/ 0x0808028aU, +/*036e*/ 0x1008028aU, +/*036f*/ 0x1808028aU, +/*0370*/ 0xffffffffU, +/*0371*/ 0x0008028bU, +/*0372*/ 0x0808028bU, +/*0373*/ 0x1008028bU, +/*0374*/ 0x1808028bU, +/*0375*/ 0x0008028cU, +/*0376*/ 0x0808028cU, +/*0377*/ 0xffffffffU, +/*0378*/ 0x1008028cU, +/*0379*/ 0x1808028cU, +/*037a*/ 0x0008028dU, +/*037b*/ 0x0808028dU, +/*037c*/ 0x1008028dU, +/*037d*/ 0x1808028dU, +/*037e*/ 0x0008028eU, +/*037f*/ 0xffffffffU, +/*0380*/ 0x0808028eU, +/*0381*/ 0x1008028eU, +/*0382*/ 0x1808028eU, +/*0383*/ 0x0008028fU, +/*0384*/ 0x0808028fU, +/*0385*/ 0x1008028fU, +/*0386*/ 0xffffffffU, +/*0387*/ 0x1808028fU, +/*0388*/ 0x00080290U, +/*0389*/ 0x08080290U, +/*038a*/ 0x10080290U, +/*038b*/ 0x18080290U, +/*038c*/ 0x00080291U, +/*038d*/ 0xffffffffU, +/*038e*/ 0x08080291U, +/*038f*/ 0x10080291U, +/*0390*/ 0x18080291U, +/*0391*/ 0x00080292U, +/*0392*/ 0x08080292U, +/*0393*/ 0x10080292U, +/*0394*/ 0x18080292U, +/*0395*/ 0xffffffffU, +/*0396*/ 0x00080293U, +/*0397*/ 0x08080293U, +/*0398*/ 0x10080293U, +/*0399*/ 0x18080293U, +/*039a*/ 0x00080294U, +/*039b*/ 0x08080294U, +/*039c*/ 0xffffffffU, +/*039d*/ 0x10080294U, +/*039e*/ 0x18080294U, +/*039f*/ 0x00080295U, +/*03a0*/ 0x08080295U, +/*03a1*/ 0x10080295U, +/*03a2*/ 0x18080295U, +/*03a3*/ 0xffffffffU, +/*03a4*/ 0x00080296U, +/*03a5*/ 0x08080296U, +/*03a6*/ 0x10080296U, +/*03a7*/ 0x18080296U, +/*03a8*/ 0x00080297U, +/*03a9*/ 0x08080297U, +/*03aa*/ 0x10080297U, +/*03ab*/ 0xffffffffU, +/*03ac*/ 0x18080297U, +/*03ad*/ 0x00080298U, +/*03ae*/ 0x08080298U, +/*03af*/ 0x10080298U, +/*03b0*/ 0x18080298U, +/*03b1*/ 0x00080299U, +/*03b2*/ 0xffffffffU, +/*03b3*/ 0x08080299U, +/*03b4*/ 0x10080299U, +/*03b5*/ 0x18080299U, +/*03b6*/ 0x0008029aU, +/*03b7*/ 0x0808029aU, +/*03b8*/ 0x1008029aU, +/*03b9*/ 0xffffffffU, +/*03ba*/ 0x1808029aU, +/*03bb*/ 0x0002029bU, +/*03bc*/ 0x0803029bU, +/*03bd*/ 0x100a029bU, +/*03be*/ 0x000a029cU, +/*03bf*/ 0x100a029cU, +/*03c0*/ 0x0005029dU, +/*03c1*/ 0x0808029dU, +/*03c2*/ 0x1008029dU, +/*03c3*/ 0x1808029dU, +/*03c4*/ 0x0006029eU, +/*03c5*/ 0x0806029eU, +/*03c6*/ 0x0011029fU, +/*03c7*/ 0x1808029fU, +/*03c8*/ 0x000402a0U, +/*03c9*/ 0x080602a0U, +/*03ca*/ 0xffffffffU, +/*03cb*/ 0x100602a0U, +/*03cc*/ 0x180802a0U, +/*03cd*/ 0xffffffffU, +/*03ce*/ 0x000802a1U, +/*03cf*/ 0x080802a1U, +/*03d0*/ 0x100802a1U, +/*03d1*/ 0x180602a1U, +/*03d2*/ 0x000602a2U, +/*03d3*/ 0x081102a2U, +/*03d4*/ 0x000802a3U, +/*03d5*/ 0x080402a3U, +/*03d6*/ 0x100602a3U, +/*03d7*/ 0xffffffffU, +/*03d8*/ 0x180602a3U, +/*03d9*/ 0x000802a4U, +/*03da*/ 0xffffffffU, +/*03db*/ 0x080802a4U, +/*03dc*/ 0x100802a4U, +/*03dd*/ 0x180802a4U, +/*03de*/ 0x000602a5U, +/*03df*/ 0x080602a5U, +/*03e0*/ 0x001102a6U, +/*03e1*/ 0x180802a6U, +/*03e2*/ 0x000402a7U, +/*03e3*/ 0x080602a7U, +/*03e4*/ 0xffffffffU, +/*03e5*/ 0x100602a7U, +/*03e6*/ 0x180802a7U, +/*03e7*/ 0xffffffffU, +/*03e8*/ 0x000402a8U, +/*03e9*/ 0x080402a8U, +/*03ea*/ 0x100402a8U, +/*03eb*/ 0x180402a8U, +/*03ec*/ 0x000402a9U, +/*03ed*/ 0x080402a9U, +/*03ee*/ 0x100402a9U, +/*03ef*/ 0x180402a9U, +/*03f0*/ 0x000402aaU, +/*03f1*/ 0x080402aaU, +/*03f2*/ 0x100402aaU, +/*03f3*/ 0x180402aaU, +/*03f4*/ 0x000402abU, +/*03f5*/ 0x080402abU, +/*03f6*/ 0x100402abU, +/*03f7*/ 0x180402abU, +/*03f8*/ 0x000402acU, +/*03f9*/ 0x080402acU, +/*03fa*/ 0x100402acU, +/*03fb*/ 0x180402acU, +/*03fc*/ 0x001202adU, +/*03fd*/ 0x001102aeU, +/*03fe*/ 0x001202afU, +/*03ff*/ 0x002002b0U, +/*0400*/ 0x002002b1U, +/*0401*/ 0x002002b2U, +/*0402*/ 0x002002b3U, +/*0403*/ 0x002002b4U, +/*0404*/ 0x002002b5U, +/*0405*/ 0x002002b6U, +/*0406*/ 0x002002b7U, +/*0407*/ 0x002002b8U, +/*0408*/ 0x000202b9U, +/*0409*/ 0x080502b9U, +/*040a*/ 0x100502b9U, +/*040b*/ 0x180102b9U, +/*040c*/ 0x000402baU, +/*040d*/ 0x080402baU, +/*040e*/ 0x100402baU, +/*040f*/ 0x180402baU, +/*0410*/ 0x000402bbU, +/*0411*/ 0x080402bbU, +/*0412*/ 0x100402bbU, +/*0413*/ 0x180402bbU, +/*0414*/ 0xffffffffU, +/*0415*/ 0xffffffffU, +/*0416*/ 0xffffffffU, +/*0417*/ 0xffffffffU, +/*0418*/ 0xffffffffU, +/*0419*/ 0xffffffffU, +/*041a*/ 0x000402bcU, +/*041b*/ 0x080402bcU, +/*041c*/ 0x100402bcU, +/*041d*/ 0x180402bcU, +/*041e*/ 0x000402bdU, +/*041f*/ 0x080402bdU, +/*0420*/ 0x100402bdU, +/*0421*/ 0x180402bdU, +/*0422*/ 0x000102beU, +/*0423*/ 0x080202beU, +/*0424*/ 0x100202beU, +/*0425*/ 0x180202beU, +/*0426*/ 0x000202bfU, +/*0427*/ 0x080102bfU, +/*0428*/ 0x100402bfU, +/*0429*/ 0x001002c0U, +/*042a*/ 0x002002c1U, +/*042b*/ 0x001002c2U, +/*042c*/ 0x002002c3U, +/*042d*/ 0x001002c4U, +/*042e*/ 0x002002c5U, +/*042f*/ 0x000702c6U, +/*0430*/ 0x080102c6U, +/*0431*/ 0x100202c6U, +/*0432*/ 0x180602c6U, +/*0433*/ 0x000102c7U, +/*0434*/ 0x080102c7U, +/*0435*/ 0x002002c8U, +/*0436*/ 0x000202c9U, +/*0437*/ 0x002002caU, +/*0438*/ 0x002002cbU, +/*0439*/ 0x000c02ccU, +/*043a*/ 0x100c02ccU, +/*043b*/ 0x002002cdU, +/*043c*/ 0x000302ceU, +/*043d*/ 0x002002cfU, +/*043e*/ 0x000302d0U, +/*043f*/ 0x002002d1U, +/*0440*/ 0x000302d2U, +/*0441*/ 0x002002d3U, +/*0442*/ 0x000302d4U, +/*0443*/ 0x002002d5U, +/*0444*/ 0x000302d6U, +/*0445*/ 0x002002d7U, +/*0446*/ 0x000302d8U, +/*0447*/ 0x002002d9U, +/*0448*/ 0x000302daU, +/*0449*/ 0x002002dbU, +/*044a*/ 0x000302dcU, +/*044b*/ 0x002002ddU, +/*044c*/ 0x000302deU, +/*044d*/ 0x002002dfU, +/*044e*/ 0x000302e0U, +/*044f*/ 0x080302e0U, +/*0450*/ 0x100202e0U, +/*0451*/ 0x180202e0U, +/*0452*/ 0x002002e1U, +/*0453*/ 0x002002e2U, +/*0454*/ 0x002002e3U, +/*0455*/ 0x002002e4U, +/*0456*/ 0x000402e5U, +/*0457*/ 0x001e02e6U, +/*0458*/ 0x001e02e7U, +/*0459*/ 0x001e02e8U, +/*045a*/ 0x001e02e9U, +/*045b*/ 0x001e02eaU, +/*045c*/ 0x001e02ebU, +/*045d*/ 0x001e02ecU, +/*045e*/ 0x001e02edU, +/*045f*/ 0x000402eeU, +/*0460*/ 0xffffffffU, +/*0461*/ 0xffffffffU, +/*0462*/ 0xffffffffU, +/*0463*/ 0xffffffffU, +/*0464*/ 0x080402eeU, +/*0465*/ 0x100102eeU, +/*0466*/ 0x180802eeU, +/*0467*/ 0x000402efU, +/*0468*/ 0x080102efU, +/*0469*/ 0x100802efU, +/*046a*/ 0x180402efU, +/*046b*/ 0x000102f0U, +/*046c*/ 0x080802f0U, +/*046d*/ 0x100402f0U, +/*046e*/ 0x180102f0U, +/*046f*/ 0x000802f1U, +/*0470*/ 0x080402f1U, +/*0471*/ 0x100102f1U, +/*0472*/ 0x180802f1U, +/*0473*/ 0x000402f2U, +/*0474*/ 0x080102f2U, +/*0475*/ 0x100802f2U, +/*0476*/ 0x180402f2U, +/*0477*/ 0x000102f3U, +/*0478*/ 0x080802f3U, +/*0479*/ 0x100402f3U, +/*047a*/ 0x180102f3U, +/*047b*/ 0x000802f4U, +/*047c*/ 0x080802f4U, +/*047d*/ 0x100102f4U, +/*047e*/ 0x180502f4U, +/*047f*/ 0xffffffffU, +/*0480*/ 0xffffffffU, +/*0481*/ 0xffffffffU, +/*0482*/ 0xffffffffU, +/*0483*/ 0xffffffffU, +/*0484*/ 0xffffffffU, +/*0485*/ 0xffffffffU, +/*0486*/ 0xffffffffU, +/*0487*/ 0xffffffffU, +/*0488*/ 0xffffffffU, +/*0489*/ 0xffffffffU, +/*048a*/ 0xffffffffU, +/*048b*/ 0xffffffffU, +/*048c*/ 0xffffffffU, +/*048d*/ 0xffffffffU, +/*048e*/ 0xffffffffU, +/*048f*/ 0xffffffffU, +/*0490*/ 0xffffffffU, +/*0491*/ 0xffffffffU, +/*0492*/ 0xffffffffU, +/*0493*/ 0xffffffffU, +/*0494*/ 0xffffffffU, + }, + { +/*0000*/ 0x00200800U, +/*0001*/ 0x00040801U, +/*0002*/ 0x080b0801U, +/*0003*/ 0x000a0802U, +/*0004*/ 0x10020802U, +/*0005*/ 0x18010802U, +/*0006*/ 0x00060803U, +/*0007*/ 0x08060803U, +/*0008*/ 0x10060803U, +/*0009*/ 0x18060803U, +/*000a*/ 0x00060804U, +/*000b*/ 0x08060804U, +/*000c*/ 0x10050804U, +/*000d*/ 0x18060804U, +/*000e*/ 0x00060805U, +/*000f*/ 0x08040805U, +/*0010*/ 0x10030805U, +/*0011*/ 0x00180806U, +/*0012*/ 0x18030806U, +/*0013*/ 0x00180807U, +/*0014*/ 0x18020807U, +/*0015*/ 0x0801085eU, +/*0016*/ 0x00020808U, +/*0017*/ 0x08010808U, +/*0018*/ 0x10010808U, +/*0019*/ 0x18020808U, +/*001a*/ 0x00050809U, +/*001b*/ 0x08050809U, +/*001c*/ 0x10040809U, +/*001d*/ 0xffffffffU, +/*001e*/ 0x18040809U, +/*001f*/ 0x0002080aU, +/*0020*/ 0x0805080aU, +/*0021*/ 0x1009080aU, +/*0022*/ 0x0001080bU, +/*0023*/ 0x0020080cU, +/*0024*/ 0x001c080dU, +/*0025*/ 0x0001080eU, +/*0026*/ 0x0807080eU, +/*0027*/ 0x1009080eU, +/*0028*/ 0x000a080fU, +/*0029*/ 0x1005080fU, +/*002a*/ 0x1801080fU, +/*002b*/ 0x10010810U, +/*002c*/ 0x18020810U, +/*002d*/ 0x00090810U, +/*002e*/ 0x00090811U, +/*002f*/ 0x10020811U, +/*0030*/ 0x00200812U, +/*0031*/ 0x00010813U, +/*0032*/ 0x08020813U, +/*0033*/ 0x00200814U, +/*0034*/ 0x00200815U, +/*0035*/ 0x00200816U, +/*0036*/ 0x00200817U, +/*0037*/ 0xffffffffU, +/*0038*/ 0xffffffffU, +/*0039*/ 0xffffffffU, +/*003a*/ 0xffffffffU, +/*003b*/ 0x00030818U, +/*003c*/ 0x08010818U, +/*003d*/ 0x10040818U, +/*003e*/ 0x18030818U, +/*003f*/ 0x00040819U, +/*0040*/ 0x08040819U, +/*0041*/ 0x10040819U, +/*0042*/ 0x18040819U, +/*0043*/ 0x0001081aU, +/*0044*/ 0x0801081aU, +/*0045*/ 0x1006081aU, +/*0046*/ 0x1804081aU, +/*0047*/ 0x0008081bU, +/*0048*/ 0x0806081bU, +/*0049*/ 0x1004081bU, +/*004a*/ 0x1806081bU, +/*004b*/ 0x0004081cU, +/*004c*/ 0x0802081cU, +/*004d*/ 0x1005081cU, +/*004e*/ 0x1808081cU, +/*004f*/ 0xffffffffU, +/*0050*/ 0x0006081dU, +/*0051*/ 0x0803081dU, +/*0052*/ 0x100b081dU, +/*0053*/ 0x0004081eU, +/*0054*/ 0x0804081eU, +/*0055*/ 0x1004081eU, +/*0056*/ 0x1801081eU, +/*0057*/ 0xffffffffU, +/*0058*/ 0x0009081fU, +/*0059*/ 0x00200820U, +/*005a*/ 0x00200821U, +/*005b*/ 0x00200822U, +/*005c*/ 0x00200823U, +/*005d*/ 0x00100824U, +/*005e*/ 0xffffffffU, +/*005f*/ 0x10010824U, +/*0060*/ 0x18060824U, +/*0061*/ 0x00080825U, +/*0062*/ 0x00200826U, +/*0063*/ 0x00100827U, +/*0064*/ 0x100b0827U, +/*0065*/ 0x00070828U, +/*0066*/ 0x08070828U, +/*0067*/ 0x10090828U, +/*0068*/ 0x00090829U, +/*0069*/ 0x100b0829U, +/*006a*/ 0x0007082aU, +/*006b*/ 0x0808082aU, +/*006c*/ 0x1009082aU, +/*006d*/ 0x0003082bU, +/*006e*/ 0x080a082bU, +/*006f*/ 0x000a082cU, +/*0070*/ 0x0011082dU, +/*0071*/ 0x000a082eU, +/*0072*/ 0x100a082eU, +/*0073*/ 0x0010082fU, +/*0074*/ 0x100e082fU, +/*0075*/ 0x000e0830U, +/*0076*/ 0x00120831U, +/*0077*/ 0x000a0832U, +/*0078*/ 0x100a0832U, +/*0079*/ 0x00020833U, +/*007a*/ 0x00200834U, +/*007b*/ 0x000b0835U, +/*007c*/ 0x100b0835U, +/*007d*/ 0x00200836U, +/*007e*/ 0x00130837U, +/*007f*/ 0x00200838U, +/*0080*/ 0x00200839U, +/*0081*/ 0x0008083aU, +/*0082*/ 0x0801083aU, +/*0083*/ 0x1001083aU, +/*0084*/ 0x1801083aU, +/*0085*/ 0x0008083bU, +/*0086*/ 0x080c083bU, +/*0087*/ 0x000c083cU, +/*0088*/ 0x100c083cU, +/*0089*/ 0x000c083dU, +/*008a*/ 0x100c083dU, +/*008b*/ 0x000c083eU, +/*008c*/ 0x100c083eU, +/*008d*/ 0x000c083fU, +/*008e*/ 0x100c083fU, +/*008f*/ 0x000c0840U, +/*0090*/ 0x100c0840U, +/*0091*/ 0x000b0841U, +/*0092*/ 0x10090841U, +/*0093*/ 0x00010842U, +/*0094*/ 0x000b0843U, +/*0095*/ 0x100b0843U, +/*0096*/ 0x000b0844U, +/*0097*/ 0x100b0844U, +/*0098*/ 0x000b0845U, +/*0099*/ 0x100b0845U, +/*009a*/ 0x000b0846U, +/*009b*/ 0x100b0846U, +/*009c*/ 0x000b0847U, +/*009d*/ 0x100a0847U, +/*009e*/ 0x00020848U, +/*009f*/ 0x080a0848U, +/*00a0*/ 0x000a0849U, +/*00a1*/ 0x100a0849U, +/*00a2*/ 0x000a084aU, +/*00a3*/ 0x100a084aU, +/*00a4*/ 0x000a084bU, +/*00a5*/ 0x100a084bU, +/*00a6*/ 0x000a084cU, +/*00a7*/ 0x100a084cU, +/*00a8*/ 0x000a084dU, +/*00a9*/ 0x100a084dU, +/*00aa*/ 0x000a084eU, +/*00ab*/ 0x100a084eU, +/*00ac*/ 0x000a084fU, +/*00ad*/ 0x100a084fU, +/*00ae*/ 0x000a0850U, +/*00af*/ 0x100a0850U, +/*00b0*/ 0x000a0851U, +/*00b1*/ 0x100a0851U, +/*00b2*/ 0x000a0852U, +/*00b3*/ 0x100a0852U, +/*00b4*/ 0x000a0853U, +/*00b5*/ 0x100a0853U, +/*00b6*/ 0x000a0854U, +/*00b7*/ 0x100a0854U, +/*00b8*/ 0x000a0855U, +/*00b9*/ 0x100a0855U, +/*00ba*/ 0x000a0856U, +/*00bb*/ 0x10040856U, +/*00bc*/ 0x18030856U, +/*00bd*/ 0x000a0857U, +/*00be*/ 0x100a0857U, +/*00bf*/ 0x00010858U, +/*00c0*/ 0x080a0858U, +/*00c1*/ 0x18040858U, +/*00c2*/ 0x000b0859U, +/*00c3*/ 0x100a0859U, +/*00c4*/ 0x0003085aU, +/*00c5*/ 0x0008085bU, +/*00c6*/ 0x0808085bU, +/*00c7*/ 0x1008085bU, +/*00c8*/ 0x1808085bU, +/*00c9*/ 0x0008085cU, +/*00ca*/ 0x0808085cU, +/*00cb*/ 0x1008085cU, +/*00cc*/ 0x1801085cU, +/*00cd*/ 0x0008085dU, +/*00ce*/ 0x0808085dU, +/*00cf*/ 0x1002085dU, +/*00d0*/ 0x1802085dU, +/*00d1*/ 0x0005085eU, +/*00d2*/ 0x1005085eU, +/*00d3*/ 0x1805085eU, +/*00d4*/ 0x0004085fU, +/*00d5*/ 0x080b085fU, +/*00d6*/ 0x1806085fU, +/*00d7*/ 0x00080860U, +/*00d8*/ 0x08080860U, +/*00d9*/ 0x10040860U, +/*00da*/ 0x18040860U, +/*00db*/ 0x00060861U, +/*00dc*/ 0x08040861U, +/*00dd*/ 0x10050861U, +/*00de*/ 0x000a0862U, +/*00df*/ 0x100a0862U, +/*00e0*/ 0x00080863U, +/*00e1*/ 0x08010863U, +/*00e2*/ 0x10040863U, +/*00e3*/ 0x00020864U, +/*00e4*/ 0x08030864U, +/*00e5*/ 0x00050a00U, +/*00e6*/ 0x08050a00U, +/*00e7*/ 0x10050a00U, +/*00e8*/ 0x18050a00U, +/*00e9*/ 0x00050a01U, +/*00ea*/ 0x08050a01U, +/*00eb*/ 0x100b0a01U, +/*00ec*/ 0x00010a02U, +/*00ed*/ 0x08030a02U, +/*00ee*/ 0x00200a03U, +/*00ef*/ 0x00100a04U, +/*00f0*/ 0x10040a04U, +/*00f1*/ 0x000b0a05U, +/*00f2*/ 0x10070a05U, +/*00f3*/ 0x00090a06U, +/*00f4*/ 0x10030a06U, +/*00f5*/ 0x18030a06U, +/*00f6*/ 0x00010a07U, +/*00f7*/ 0x08010a07U, +/*00f8*/ 0x10070a07U, +/*00f9*/ 0x18070a07U, +/*00fa*/ 0x00050a08U, +/*00fb*/ 0x08010a08U, +/*00fc*/ 0x10020a08U, +/*00fd*/ 0x18030a08U, +/*00fe*/ 0x00010a09U, +/*00ff*/ 0x080f0a09U, +/*0100*/ 0x00200a0aU, +/*0101*/ 0x00200a0bU, +/*0102*/ 0x000b0a0cU, +/*0103*/ 0x100b0a0cU, +/*0104*/ 0x000b0a0dU, +/*0105*/ 0x00180a0eU, +/*0106*/ 0x00180a0fU, +/*0107*/ 0xffffffffU, +/*0108*/ 0xffffffffU, +/*0109*/ 0xffffffffU, +/*010a*/ 0xffffffffU, +/*010b*/ 0xffffffffU, +/*010c*/ 0x18020a0fU, +/*010d*/ 0x00020a10U, +/*010e*/ 0x08040a10U, +/*010f*/ 0x10040a10U, +/*0110*/ 0x18010a10U, +/*0111*/ 0x00010a11U, +/*0112*/ 0x08010a11U, +/*0113*/ 0x10030a11U, +/*0114*/ 0x00200a12U, +/*0115*/ 0x00200a13U, +/*0116*/ 0xffffffffU, +/*0117*/ 0x00140a14U, +/*0118*/ 0x00140a15U, +/*0119*/ 0x00140a16U, +/*011a*/ 0x00140a17U, +/*011b*/ 0x00140a18U, +/*011c*/ 0x00140a19U, +/*011d*/ 0x00140a1aU, +/*011e*/ 0x00140a1bU, +/*011f*/ 0x001e0a1cU, +/*0120*/ 0x000a0a1dU, +/*0121*/ 0x10060a1dU, +/*0122*/ 0x18060a1dU, +/*0123*/ 0x00060a1eU, +/*0124*/ 0x08060a1eU, +/*0125*/ 0x10060a1eU, +/*0126*/ 0x00080a1fU, +/*0127*/ 0x080b0a1fU, +/*0128*/ 0x000b0a20U, +/*0129*/ 0x100b0a20U, +/*012a*/ 0x000b0a21U, +/*012b*/ 0x100b0a21U, +/*012c*/ 0x000b0a22U, +/*012d*/ 0x10040a22U, +/*012e*/ 0x000b0a23U, +/*012f*/ 0x10060a23U, +/*0130*/ 0x18080a23U, +/*0131*/ 0x00080a24U, +/*0132*/ 0x08040a24U, +/*0133*/ 0x00020b80U, +/*0134*/ 0x00010b81U, +/*0135*/ 0x08010b81U, +/*0136*/ 0x10020b81U, +/*0137*/ 0x18050b81U, +/*0138*/ 0x00050b82U, +/*0139*/ 0x08050b82U, +/*013a*/ 0x10050b82U, +/*013b*/ 0x000b0b83U, +/*013c*/ 0x10050b83U, +/*013d*/ 0x18010b83U, +/*013e*/ 0x00010b84U, +/*013f*/ 0x08010b84U, +/*0140*/ 0x10010b84U, +/*0141*/ 0x18010b84U, +/*0142*/ 0x00040b85U, +/*0143*/ 0x080b0b85U, +/*0144*/ 0x000b0b86U, +/*0145*/ 0x100b0b86U, +/*0146*/ 0x00040b87U, +/*0147*/ 0x080b0b87U, +/*0148*/ 0x18040b87U, +/*0149*/ 0x00010b88U, +/*014a*/ 0x08010b88U, +/*014b*/ 0x10010b88U, +/*014c*/ 0x00200b89U, +/*014d*/ 0x00200b8aU, +/*014e*/ 0x00080b8bU, +/*014f*/ 0x080a0b8bU, +/*0150*/ 0x18050b8bU, +/*0151*/ 0x000b0b8cU, +/*0152*/ 0x10030b8cU, +/*0153*/ 0x18030b8cU, +/*0154*/ 0x00010b8dU, +/*0155*/ 0x08020b8dU, +/*0156*/ 0x10010b8dU, +/*0157*/ 0x18010b8dU, +/*0158*/ 0x00010b8eU, +/*0159*/ 0xffffffffU, +/*015a*/ 0x08010b8eU, +/*015b*/ 0x18040b8eU, +/*015c*/ 0x00040b8fU, +/*015d*/ 0x08040b8fU, +/*015e*/ 0x10040b8fU, +/*015f*/ 0x18010b8fU, +/*0160*/ 0x00010b90U, +/*0161*/ 0x08010b90U, +/*0162*/ 0x00200b91U, +/*0163*/ 0x00200b92U, +/*0164*/ 0x00200b93U, +/*0165*/ 0x00200b94U, +/*0166*/ 0xffffffffU, +/*0167*/ 0x10010b8eU, +/*0168*/ 0x000d0b96U, +/*0169*/ 0x100d0b96U, +/*016a*/ 0x000d0b97U, +/*016b*/ 0x00050b98U, +/*016c*/ 0x00010b99U, +/*016d*/ 0x080e0b99U, +/*016e*/ 0x000e0b9aU, +/*016f*/ 0x100e0b9aU, +/*0170*/ 0x000e0b9bU, +/*0171*/ 0x100e0b9bU, +/*0172*/ 0x00040b9cU, +/*0173*/ 0x08040b9cU, +/*0174*/ 0x10040b9cU, +/*0175*/ 0x18040b9cU, +/*0176*/ 0x00040b9dU, +/*0177*/ 0x080b0b9dU, +/*0178*/ 0x000b0b9eU, +/*0179*/ 0x100b0b9eU, +/*017a*/ 0x000b0b9fU, +/*017b*/ 0x00040ba0U, +/*017c*/ 0x08040ba0U, +/*017d*/ 0x10040ba0U, +/*017e*/ 0x18040ba0U, +/*017f*/ 0x000d0ba1U, +/*0180*/ 0x100d0ba1U, +/*0181*/ 0x000d0ba2U, +/*0182*/ 0x10100ba2U, +/*0183*/ 0x00080b95U, +/*0184*/ 0x08080b95U, +/*0185*/ 0x00100ba3U, +/*0186*/ 0x10100ba3U, +/*0187*/ 0x00100ba4U, +/*0188*/ 0x10100ba4U, +/*0189*/ 0x00100ba5U, +/*018a*/ 0x10030ba5U, +/*018b*/ 0x18040ba5U, +/*018c*/ 0x00010ba6U, +/*018d*/ 0x08080ba6U, +/*018e*/ 0x10010ba6U, +/*018f*/ 0x000a0ba7U, +/*0190*/ 0x10010ba7U, +/*0191*/ 0x00140ba8U, +/*0192*/ 0x000b0ba9U, +/*0193*/ 0x100c0ba9U, +/*0194*/ 0x00120baaU, +/*0195*/ 0x00140babU, +/*0196*/ 0x00120bacU, +/*0197*/ 0x00110badU, +/*0198*/ 0x00110baeU, +/*0199*/ 0x00120bafU, +/*019a*/ 0x00120bb0U, +/*019b*/ 0x00120bb1U, +/*019c*/ 0x00120bb2U, +/*019d*/ 0x00120bb3U, +/*019e*/ 0x00120bb4U, +/*019f*/ 0x00120bb5U, +/*01a0*/ 0x00120bb6U, +/*01a1*/ 0x00120bb7U, +/*01a2*/ 0x00120bb8U, +/*01a3*/ 0x000e0bb9U, +/*01a4*/ 0x100d0bb9U, +/*01a5*/ 0x00200bbaU, +/*01a6*/ 0x00170bbbU, +/*01a7*/ 0x000d0bbcU, +/*01a8*/ 0x10010bbcU, +/*01a9*/ 0x18010bbcU, +/*01aa*/ 0x00200bbdU, +/*01ab*/ 0x00080bbeU, +/*01ac*/ 0x08030bbeU, +/*01ad*/ 0x10030bbeU, +/*01ae*/ 0x00180bbfU, +/*01af*/ 0x00180bc0U, +/*01b0*/ 0x18070bc0U, +/*01b1*/ 0x00070bc1U, +/*01b2*/ 0x08080bc1U, +/*01b3*/ 0x10080bc1U, +/*01b4*/ 0x18080bc1U, +/*01b5*/ 0x00010bc2U, +/*01b6*/ 0x08010bc2U, +/*01b7*/ 0x00200bc3U, +/*01b8*/ 0x00070bc4U, +/*01b9*/ 0x08140bc4U, +/*01ba*/ 0x00140bc5U, +/*01bb*/ 0x00190bc6U, +/*01bc*/ 0x00170bc7U, +/*01bd*/ 0x00110bc8U, +/*01be*/ 0x00110bc9U, +/*01bf*/ 0x00100bcaU, +/*01c0*/ 0x10010bcaU, +/*01c1*/ 0x18010bcaU, +/*01c2*/ 0x00020bcbU, +/*01c3*/ 0x08040bcbU, +/*01c4*/ 0x10090bcbU, +/*01c5*/ 0x00070bccU, +/*01c6*/ 0x08040bccU, +/*01c7*/ 0x00200bcdU, +/*01c8*/ 0x00010bceU, +/*01c9*/ 0x08020bceU, +/*01ca*/ 0x10060bceU, +/*01cb*/ 0x00100bcfU, +/*01cc*/ 0x10010bcfU, +/*01cd*/ 0x00200bd0U, +/*01ce*/ 0x00080bd1U, +/*01cf*/ 0x08010bd1U, +/*01d0*/ 0x10050bd1U, +/*01d1*/ 0x18030bd1U, +/*01d2*/ 0x00020bd2U, +/*01d3*/ 0xffffffffU, +/*01d4*/ 0x00200bd3U, +/*01d5*/ 0x000b0bd4U, +/*01d6*/ 0xffffffffU, +/*01d7*/ 0x10030bd4U, +/*01d8*/ 0x18080bd4U, +/*01d9*/ 0x00020bd5U, +/*01da*/ 0x080c0bd5U, +/*01db*/ 0x18040bd5U, +/*01dc*/ 0x00010bd6U, +/*01dd*/ 0x08050bd6U, +/*01de*/ 0x00010200U, +/*01df*/ 0x08040200U, +/*01e0*/ 0x10100200U, +/*01e1*/ 0x00010201U, +/*01e2*/ 0x08010201U, +/*01e3*/ 0x10010201U, +/*01e4*/ 0x18010201U, +/*01e5*/ 0x00100202U, +/*01e6*/ 0x10080202U, +/*01e7*/ 0x18010202U, +/*01e8*/ 0x00200203U, +/*01e9*/ 0x00200204U, +/*01ea*/ 0x00200205U, +/*01eb*/ 0x00200206U, +/*01ec*/ 0x00020207U, +/*01ed*/ 0x08010207U, +/*01ee*/ 0x10010207U, +/*01ef*/ 0x00200208U, +/*01f0*/ 0x00140209U, +/*01f1*/ 0x0020020aU, +/*01f2*/ 0x0014020bU, +/*01f3*/ 0x0020020cU, +/*01f4*/ 0x0014020dU, +/*01f5*/ 0x0014020eU, +/*01f6*/ 0x0020020fU, +/*01f7*/ 0x00200210U, +/*01f8*/ 0x00200211U, +/*01f9*/ 0x00200212U, +/*01fa*/ 0x00140213U, +/*01fb*/ 0x00200214U, +/*01fc*/ 0x00200215U, +/*01fd*/ 0x00200216U, +/*01fe*/ 0x00200217U, +/*01ff*/ 0x00140218U, +/*0200*/ 0x00200219U, +/*0201*/ 0x0020021aU, +/*0202*/ 0x0020021bU, +/*0203*/ 0x0020021cU, +/*0204*/ 0x0009021dU, +/*0205*/ 0x1001021dU, +/*0206*/ 0x0020021eU, +/*0207*/ 0x0005021fU, +/*0208*/ 0x0801021fU, +/*0209*/ 0x1008021fU, +/*020a*/ 0x1808021fU, +/*020b*/ 0x001e0220U, +/*020c*/ 0x001e0221U, +/*020d*/ 0x001e0222U, +/*020e*/ 0x001e0223U, +/*020f*/ 0x001e0224U, +/*0210*/ 0x001e0225U, +/*0211*/ 0x001e0226U, +/*0212*/ 0x001e0227U, +/*0213*/ 0x001e0228U, +/*0214*/ 0x001e0229U, +/*0215*/ 0x001e022aU, +/*0216*/ 0x001e022bU, +/*0217*/ 0x001e022cU, +/*0218*/ 0x001e022dU, +/*0219*/ 0x001e022eU, +/*021a*/ 0x001e022fU, +/*021b*/ 0x00010230U, +/*021c*/ 0x08010230U, +/*021d*/ 0x10010230U, +/*021e*/ 0x18040230U, +/*021f*/ 0x00080231U, +/*0220*/ 0x08080231U, +/*0221*/ 0x10080231U, +/*0222*/ 0x18040231U, +/*0223*/ 0x00070232U, +/*0224*/ 0x08060232U, +/*0225*/ 0x10070232U, +/*0226*/ 0x18070232U, +/*0227*/ 0x00060233U, +/*0228*/ 0x08070233U, +/*0229*/ 0x10070233U, +/*022a*/ 0x18060233U, +/*022b*/ 0x00070234U, +/*022c*/ 0x08020234U, +/*022d*/ 0x10010234U, +/*022e*/ 0x18010234U, +/*022f*/ 0x000a0235U, +/*0230*/ 0x00140236U, +/*0231*/ 0x000a0237U, +/*0232*/ 0x00140238U, +/*0233*/ 0x000a0239U, +/*0234*/ 0x0014023aU, +/*0235*/ 0xffffffffU, +/*0236*/ 0xffffffffU, +/*0237*/ 0x0005023bU, +/*0238*/ 0x0001023cU, +/*0239*/ 0x1001023cU, +/*023a*/ 0x1801023cU, +/*023b*/ 0x0001023dU, +/*023c*/ 0x0801023dU, +/*023d*/ 0x1001023dU, +/*023e*/ 0x1801023dU, +/*023f*/ 0x0002023eU, +/*0240*/ 0x0802023eU, +/*0241*/ 0x1002023eU, +/*0242*/ 0x1802023eU, +/*0243*/ 0x0002023fU, +/*0244*/ 0x0803023fU, +/*0245*/ 0x1001023fU, +/*0246*/ 0x1801023fU, +/*0247*/ 0x00010240U, +/*0248*/ 0x08010240U, +/*0249*/ 0x10010240U, +/*024a*/ 0x18020240U, +/*024b*/ 0x00010241U, +/*024c*/ 0x08010241U, +/*024d*/ 0x10010241U, +/*024e*/ 0x18020241U, +/*024f*/ 0x00010242U, +/*0250*/ 0x08010242U, +/*0251*/ 0x10010242U, +/*0252*/ 0x18020242U, +/*0253*/ 0x00010243U, +/*0254*/ 0x08010243U, +/*0255*/ 0x10010243U, +/*0256*/ 0x18020243U, +/*0257*/ 0xffffffffU, +/*0258*/ 0x00010244U, +/*0259*/ 0x08010244U, +/*025a*/ 0x10010244U, +/*025b*/ 0x18010244U, +/*025c*/ 0x00010245U, +/*025d*/ 0x08010245U, +/*025e*/ 0x10010245U, +/*025f*/ 0x18010245U, +/*0260*/ 0x00040246U, +/*0261*/ 0x08040246U, +/*0262*/ 0x10040246U, +/*0263*/ 0x18010246U, +/*0264*/ 0x00020247U, +/*0265*/ 0x08060247U, +/*0266*/ 0x10060247U, +/*0267*/ 0x18020247U, +/*0268*/ 0x00020248U, +/*0269*/ 0x08020248U, +/*026a*/ 0xffffffffU, +/*026b*/ 0x10100248U, +/*026c*/ 0x00010249U, +/*026d*/ 0x08010249U, +/*026e*/ 0x10010249U, +/*026f*/ 0x18040249U, +/*0270*/ 0x0001024aU, +/*0271*/ 0x0804024aU, +/*0272*/ 0x1003024aU, +/*0273*/ 0x1808024aU, +/*0274*/ 0x000a024bU, +/*0275*/ 0x100a024bU, +/*0276*/ 0x000a024cU, +/*0277*/ 0xffffffffU, +/*0278*/ 0x0020024dU, +/*0279*/ 0x0020024eU, +/*027a*/ 0x0005024fU, +/*027b*/ 0x1801023aU, +/*027c*/ 0x0805023cU, +/*027d*/ 0x0808024fU, +/*027e*/ 0x1001024fU, +/*027f*/ 0x1808024fU, +/*0280*/ 0x00010250U, +/*0281*/ 0x08080250U, +/*0282*/ 0x10010250U, +/*0283*/ 0x18040250U, +/*0284*/ 0x00040251U, +/*0285*/ 0x08040251U, +/*0286*/ 0x10040251U, +/*0287*/ 0x18040251U, +/*0288*/ 0x00040252U, +/*0289*/ 0x08040252U, +/*028a*/ 0x10040252U, +/*028b*/ 0x18040252U, +/*028c*/ 0x00040253U, +/*028d*/ 0x08010253U, +/*028e*/ 0x10040253U, +/*028f*/ 0x18040253U, +/*0290*/ 0x00040254U, +/*0291*/ 0x08040254U, +/*0292*/ 0x10040254U, +/*0293*/ 0x18040254U, +/*0294*/ 0x00060255U, +/*0295*/ 0x08060255U, +/*0296*/ 0x10060255U, +/*0297*/ 0x18060255U, +/*0298*/ 0x00060256U, +/*0299*/ 0x08060256U, +/*029a*/ 0x10040256U, +/*029b*/ 0x18010256U, +/*029c*/ 0x00010257U, +/*029d*/ 0x08020257U, +/*029e*/ 0x00200258U, +/*029f*/ 0x00200259U, +/*02a0*/ 0x0020025aU, +/*02a1*/ 0x0020025bU, +/*02a2*/ 0x0020025cU, +/*02a3*/ 0x0020025dU, +/*02a4*/ 0x0020025eU, +/*02a5*/ 0x0020025fU, +/*02a6*/ 0x00040260U, +/*02a7*/ 0x08040260U, +/*02a8*/ 0x10010260U, +/*02a9*/ 0x18010260U, +/*02aa*/ 0x00010261U, +/*02ab*/ 0x08010261U, +/*02ac*/ 0x10010261U, +/*02ad*/ 0x18010261U, +/*02ae*/ 0x00010262U, +/*02af*/ 0x08010262U, +/*02b0*/ 0x10010262U, +/*02b1*/ 0x18040262U, +/*02b2*/ 0x00040263U, +/*02b3*/ 0x080a0263U, +/*02b4*/ 0x00200264U, +/*02b5*/ 0x00040265U, +/*02b6*/ 0x08080265U, +/*02b7*/ 0x10020265U, +/*02b8*/ 0x18020265U, +/*02b9*/ 0x00020266U, +/*02ba*/ 0x08020266U, +/*02bb*/ 0x10020266U, +/*02bc*/ 0x18020266U, +/*02bd*/ 0xffffffffU, +/*02be*/ 0xffffffffU, +/*02bf*/ 0x00200267U, +/*02c0*/ 0x00030268U, +/*02c1*/ 0x08100268U, +/*02c2*/ 0x00100269U, +/*02c3*/ 0x10040269U, +/*02c4*/ 0x18040269U, +/*02c5*/ 0x0005026aU, +/*02c6*/ 0x0805026aU, +/*02c7*/ 0xffffffffU, +/*02c8*/ 0xffffffffU, +/*02c9*/ 0xffffffffU, +/*02ca*/ 0xffffffffU, +/*02cb*/ 0x1001026aU, +/*02cc*/ 0x1801026aU, +/*02cd*/ 0x0008026bU, +/*02ce*/ 0x0808026bU, +/*02cf*/ 0x1008026bU, +/*02d0*/ 0x1808026bU, +/*02d1*/ 0x0008026cU, +/*02d2*/ 0x0808026cU, +/*02d3*/ 0x1008026cU, +/*02d4*/ 0x1808026cU, +/*02d5*/ 0x0008026dU, +/*02d6*/ 0x0808026dU, +/*02d7*/ 0x1008026dU, +/*02d8*/ 0x1808026dU, +/*02d9*/ 0x0008026eU, +/*02da*/ 0x0808026eU, +/*02db*/ 0x1003026eU, +/*02dc*/ 0x1803026eU, +/*02dd*/ 0x0003026fU, +/*02de*/ 0xffffffffU, +/*02df*/ 0x0801026fU, +/*02e0*/ 0x1002026fU, +/*02e1*/ 0x1801026fU, +/*02e2*/ 0x00040270U, +/*02e3*/ 0x08020270U, +/*02e4*/ 0x10010270U, +/*02e5*/ 0x18010270U, +/*02e6*/ 0x00010271U, +/*02e7*/ 0x08010271U, +/*02e8*/ 0x10040271U, +/*02e9*/ 0x18080271U, +/*02ea*/ 0x000a0272U, +/*02eb*/ 0x100a0272U, +/*02ec*/ 0x000a0273U, +/*02ed*/ 0x100a0273U, +/*02ee*/ 0x000a0274U, +/*02ef*/ 0x100a0274U, +/*02f0*/ 0x00200275U, +/*02f1*/ 0x00200276U, +/*02f2*/ 0x00010277U, +/*02f3*/ 0x08020277U, +/*02f4*/ 0x10020277U, +/*02f5*/ 0x18020277U, +/*02f6*/ 0xffffffffU, +/*02f7*/ 0x00020278U, +/*02f8*/ 0x08100278U, +/*02f9*/ 0x18050278U, +/*02fa*/ 0x00060279U, +/*02fb*/ 0x08050279U, +/*02fc*/ 0x10050279U, +/*02fd*/ 0x000e027aU, +/*02fe*/ 0x1005027aU, +/*02ff*/ 0x000e027bU, +/*0300*/ 0x1005027bU, +/*0301*/ 0x000e027cU, +/*0302*/ 0x1005027cU, +/*0303*/ 0x1801027cU, +/*0304*/ 0x0005027dU, +/*0305*/ 0x0805027dU, +/*0306*/ 0x100a027dU, +/*0307*/ 0x000a027eU, +/*0308*/ 0x1005027eU, +/*0309*/ 0x1805027eU, +/*030a*/ 0x000a027fU, +/*030b*/ 0x100a027fU, +/*030c*/ 0x00050280U, +/*030d*/ 0x08050280U, +/*030e*/ 0x100a0280U, +/*030f*/ 0x000a0281U, +/*0310*/ 0x10070281U, +/*0311*/ 0x18070281U, +/*0312*/ 0x00070282U, +/*0313*/ 0x08070282U, +/*0314*/ 0x10070282U, +/*0315*/ 0x18070282U, +/*0316*/ 0xffffffffU, +/*0317*/ 0xffffffffU, +/*0318*/ 0x00040283U, +/*0319*/ 0x08040283U, +/*031a*/ 0x10040283U, +/*031b*/ 0x18040283U, +/*031c*/ 0x00040284U, +/*031d*/ 0xffffffffU, +/*031e*/ 0x08080284U, +/*031f*/ 0x10080284U, +/*0320*/ 0x18040284U, +/*0321*/ 0x00050285U, +/*0322*/ 0x08080285U, +/*0323*/ 0x10050285U, +/*0324*/ 0x18040285U, +/*0325*/ 0x00050286U, +/*0326*/ 0x08080286U, +/*0327*/ 0x10050286U, +/*0328*/ 0x18040286U, +/*0329*/ 0x00050287U, +/*032a*/ 0x08080287U, +/*032b*/ 0x10050287U, +/*032c*/ 0x18040287U, +/*032d*/ 0x00050288U, +/*032e*/ 0x08070288U, +/*032f*/ 0x10080288U, +/*0330*/ 0x00100289U, +/*0331*/ 0x10080289U, +/*0332*/ 0x0010028aU, +/*0333*/ 0x1008028aU, +/*0334*/ 0x0010028bU, +/*0335*/ 0x1008028bU, +/*0336*/ 0x1808028bU, +/*0337*/ 0x0001028cU, +/*0338*/ 0x0801028cU, +/*0339*/ 0x1006028cU, +/*033a*/ 0x1806028cU, +/*033b*/ 0x0006028dU, +/*033c*/ 0x0801028dU, +/*033d*/ 0x1001028dU, +/*033e*/ 0x1803028dU, +/*033f*/ 0x000a028eU, +/*0340*/ 0x100a028eU, +/*0341*/ 0x000a028fU, +/*0342*/ 0xffffffffU, +/*0343*/ 0x100a028fU, +/*0344*/ 0x00040290U, +/*0345*/ 0x08010290U, +/*0346*/ 0x10040290U, +/*0347*/ 0x18070290U, +/*0348*/ 0x00070291U, +/*0349*/ 0x08070291U, +/*034a*/ 0x10070291U, +/*034b*/ 0x18070291U, +/*034c*/ 0x00070292U, +/*034d*/ 0xffffffffU, +/*034e*/ 0xffffffffU, +/*034f*/ 0x08050292U, +/*0350*/ 0x10050292U, +/*0351*/ 0x18040292U, +/*0352*/ 0x00040293U, +/*0353*/ 0x08040293U, +/*0354*/ 0xffffffffU, +/*0355*/ 0x10010293U, +/*0356*/ 0x18010293U, +/*0357*/ 0x00020294U, +/*0358*/ 0x08080294U, +/*0359*/ 0x00200295U, +/*035a*/ 0x00200296U, +/*035b*/ 0x00100297U, +/*035c*/ 0x10020297U, +/*035d*/ 0x18020297U, +/*035e*/ 0x00020298U, +/*035f*/ 0xffffffffU, +/*0360*/ 0x08010298U, +/*0361*/ 0x10010298U, +/*0362*/ 0x18020298U, +/*0363*/ 0x00100299U, +/*0364*/ 0x10100299U, +/*0365*/ 0x0010029aU, +/*0366*/ 0x1008029aU, +/*0367*/ 0x1808029aU, +/*0368*/ 0x0008029bU, +/*0369*/ 0x0808029bU, +/*036a*/ 0x1010029bU, +/*036b*/ 0x0010029cU, +/*036c*/ 0x1010029cU, +/*036d*/ 0x0008029dU, +/*036e*/ 0x0808029dU, +/*036f*/ 0x1008029dU, +/*0370*/ 0x1808029dU, +/*0371*/ 0x0010029eU, +/*0372*/ 0x1010029eU, +/*0373*/ 0x0010029fU, +/*0374*/ 0x1008029fU, +/*0375*/ 0x1808029fU, +/*0376*/ 0x000802a0U, +/*0377*/ 0x080802a0U, +/*0378*/ 0x100802a0U, +/*0379*/ 0x001002a1U, +/*037a*/ 0x101002a1U, +/*037b*/ 0x001002a2U, +/*037c*/ 0x100802a2U, +/*037d*/ 0x180802a2U, +/*037e*/ 0x000802a3U, +/*037f*/ 0x080802a3U, +/*0380*/ 0x101002a3U, +/*0381*/ 0x001002a4U, +/*0382*/ 0x101002a4U, +/*0383*/ 0x000802a5U, +/*0384*/ 0x080802a5U, +/*0385*/ 0x100802a5U, +/*0386*/ 0x180802a5U, +/*0387*/ 0x001002a6U, +/*0388*/ 0x101002a6U, +/*0389*/ 0x001002a7U, +/*038a*/ 0x100802a7U, +/*038b*/ 0x180802a7U, +/*038c*/ 0x000802a8U, +/*038d*/ 0x080802a8U, +/*038e*/ 0x100802a8U, +/*038f*/ 0x001002a9U, +/*0390*/ 0x101002a9U, +/*0391*/ 0x001002aaU, +/*0392*/ 0x100802aaU, +/*0393*/ 0x180802aaU, +/*0394*/ 0x000802abU, +/*0395*/ 0x080802abU, +/*0396*/ 0x101002abU, +/*0397*/ 0x001002acU, +/*0398*/ 0x101002acU, +/*0399*/ 0x000802adU, +/*039a*/ 0x080802adU, +/*039b*/ 0x100802adU, +/*039c*/ 0x180802adU, +/*039d*/ 0x001002aeU, +/*039e*/ 0x101002aeU, +/*039f*/ 0x001002afU, +/*03a0*/ 0x100802afU, +/*03a1*/ 0x180802afU, +/*03a2*/ 0x000802b0U, +/*03a3*/ 0x080802b0U, +/*03a4*/ 0x100802b0U, +/*03a5*/ 0x001002b1U, +/*03a6*/ 0x101002b1U, +/*03a7*/ 0x001002b2U, +/*03a8*/ 0x100802b2U, +/*03a9*/ 0x180802b2U, +/*03aa*/ 0x000802b3U, +/*03ab*/ 0x080802b3U, +/*03ac*/ 0x101002b3U, +/*03ad*/ 0x001002b4U, +/*03ae*/ 0x101002b4U, +/*03af*/ 0x000802b5U, +/*03b0*/ 0x080802b5U, +/*03b1*/ 0x100802b5U, +/*03b2*/ 0x180802b5U, +/*03b3*/ 0x001002b6U, +/*03b4*/ 0x101002b6U, +/*03b5*/ 0x001002b7U, +/*03b6*/ 0x100802b7U, +/*03b7*/ 0x180802b7U, +/*03b8*/ 0x000802b8U, +/*03b9*/ 0x080802b8U, +/*03ba*/ 0x100802b8U, +/*03bb*/ 0x180202b8U, +/*03bc*/ 0x000302b9U, +/*03bd*/ 0x080a02b9U, +/*03be*/ 0x000a02baU, +/*03bf*/ 0x100a02baU, +/*03c0*/ 0x000502bbU, +/*03c1*/ 0x080802bbU, +/*03c2*/ 0x100802bbU, +/*03c3*/ 0x180802bbU, +/*03c4*/ 0x000602bcU, +/*03c5*/ 0x080602bcU, +/*03c6*/ 0x001102bdU, +/*03c7*/ 0x180802bdU, +/*03c8*/ 0x000402beU, +/*03c9*/ 0x080602beU, +/*03ca*/ 0x100802beU, +/*03cb*/ 0x180802beU, +/*03cc*/ 0x000802bfU, +/*03cd*/ 0x080802bfU, +/*03ce*/ 0x100802bfU, +/*03cf*/ 0x180802bfU, +/*03d0*/ 0x000802c0U, +/*03d1*/ 0x080602c0U, +/*03d2*/ 0x100602c0U, +/*03d3*/ 0x001102c1U, +/*03d4*/ 0x180802c1U, +/*03d5*/ 0x000402c2U, +/*03d6*/ 0x080602c2U, +/*03d7*/ 0x100802c2U, +/*03d8*/ 0x180802c2U, +/*03d9*/ 0x000802c3U, +/*03da*/ 0x080802c3U, +/*03db*/ 0x100802c3U, +/*03dc*/ 0x180802c3U, +/*03dd*/ 0x000802c4U, +/*03de*/ 0x080602c4U, +/*03df*/ 0x100602c4U, +/*03e0*/ 0x001102c5U, +/*03e1*/ 0x180802c5U, +/*03e2*/ 0x000402c6U, +/*03e3*/ 0x080602c6U, +/*03e4*/ 0x100802c6U, +/*03e5*/ 0x180802c6U, +/*03e6*/ 0x000802c7U, +/*03e7*/ 0x080802c7U, +/*03e8*/ 0x100402c7U, +/*03e9*/ 0x180402c7U, +/*03ea*/ 0x000402c8U, +/*03eb*/ 0x080402c8U, +/*03ec*/ 0x100402c8U, +/*03ed*/ 0x180402c8U, +/*03ee*/ 0x000402c9U, +/*03ef*/ 0x080402c9U, +/*03f0*/ 0x100402c9U, +/*03f1*/ 0x180402c9U, +/*03f2*/ 0x000402caU, +/*03f3*/ 0x080402caU, +/*03f4*/ 0x100402caU, +/*03f5*/ 0x180402caU, +/*03f6*/ 0x000402cbU, +/*03f7*/ 0x080402cbU, +/*03f8*/ 0x100402cbU, +/*03f9*/ 0x180402cbU, +/*03fa*/ 0x000402ccU, +/*03fb*/ 0x080402ccU, +/*03fc*/ 0x001702cdU, +/*03fd*/ 0x001602ceU, +/*03fe*/ 0x001702cfU, +/*03ff*/ 0x002002d0U, +/*0400*/ 0x002002d1U, +/*0401*/ 0x002002d2U, +/*0402*/ 0x002002d3U, +/*0403*/ 0x002002d4U, +/*0404*/ 0x002002d5U, +/*0405*/ 0x002002d6U, +/*0406*/ 0x002002d7U, +/*0407*/ 0x002002d8U, +/*0408*/ 0x000202d9U, +/*0409*/ 0x080502d9U, +/*040a*/ 0x100502d9U, +/*040b*/ 0x180102d9U, +/*040c*/ 0x000502daU, +/*040d*/ 0x080502daU, +/*040e*/ 0x100502daU, +/*040f*/ 0x180502daU, +/*0410*/ 0x000502dbU, +/*0411*/ 0x080502dbU, +/*0412*/ 0x100502dbU, +/*0413*/ 0x180502dbU, +/*0414*/ 0x000502dcU, +/*0415*/ 0x080502dcU, +/*0416*/ 0x100502dcU, +/*0417*/ 0x180502dcU, +/*0418*/ 0x000502ddU, +/*0419*/ 0x080502ddU, +/*041a*/ 0x100502ddU, +/*041b*/ 0x180502ddU, +/*041c*/ 0x000502deU, +/*041d*/ 0x080502deU, +/*041e*/ 0x100502deU, +/*041f*/ 0x180502deU, +/*0420*/ 0x000502dfU, +/*0421*/ 0x080502dfU, +/*0422*/ 0x100102dfU, +/*0423*/ 0x180202dfU, +/*0424*/ 0x000202e0U, +/*0425*/ 0x080202e0U, +/*0426*/ 0x100202e0U, +/*0427*/ 0x180102e0U, +/*0428*/ 0x000802e1U, +/*0429*/ 0x081502e1U, +/*042a*/ 0x002002e2U, +/*042b*/ 0x001502e3U, +/*042c*/ 0x002002e4U, +/*042d*/ 0x001502e5U, +/*042e*/ 0x002002e6U, +/*042f*/ 0x000702e7U, +/*0430*/ 0x080102e7U, +/*0431*/ 0x100202e7U, +/*0432*/ 0x180602e7U, +/*0433*/ 0x000102e8U, +/*0434*/ 0x080102e8U, +/*0435*/ 0x002002e9U, +/*0436*/ 0x000202eaU, +/*0437*/ 0x002002ebU, +/*0438*/ 0x002002ecU, +/*0439*/ 0x000c02edU, +/*043a*/ 0x100c02edU, +/*043b*/ 0x002002eeU, +/*043c*/ 0x000302efU, +/*043d*/ 0x002002f0U, +/*043e*/ 0x000302f1U, +/*043f*/ 0x002002f2U, +/*0440*/ 0x000302f3U, +/*0441*/ 0x002002f4U, +/*0442*/ 0x000302f5U, +/*0443*/ 0x002002f6U, +/*0444*/ 0x000302f7U, +/*0445*/ 0x002002f8U, +/*0446*/ 0x000302f9U, +/*0447*/ 0x002002faU, +/*0448*/ 0x000302fbU, +/*0449*/ 0x002002fcU, +/*044a*/ 0x000302fdU, +/*044b*/ 0x002002feU, +/*044c*/ 0x000302ffU, +/*044d*/ 0x00200300U, +/*044e*/ 0x00030301U, +/*044f*/ 0x08030301U, +/*0450*/ 0x10020301U, +/*0451*/ 0x18020301U, +/*0452*/ 0x00200302U, +/*0453*/ 0x00200303U, +/*0454*/ 0x00200304U, +/*0455*/ 0x00200305U, +/*0456*/ 0x00040306U, +/*0457*/ 0x001e0307U, +/*0458*/ 0x001e0308U, +/*0459*/ 0x001e0309U, +/*045a*/ 0x001e030aU, +/*045b*/ 0x001e030bU, +/*045c*/ 0x001e030cU, +/*045d*/ 0x001e030dU, +/*045e*/ 0x001e030eU, +/*045f*/ 0x0004030fU, +/*0460*/ 0x0801030fU, +/*0461*/ 0x1010030fU, +/*0462*/ 0x00100310U, +/*0463*/ 0x10100310U, +/*0464*/ 0x00040311U, +/*0465*/ 0x08010311U, +/*0466*/ 0x10080311U, +/*0467*/ 0x18040311U, +/*0468*/ 0x00010312U, +/*0469*/ 0x08080312U, +/*046a*/ 0x10040312U, +/*046b*/ 0x18010312U, +/*046c*/ 0x00080313U, +/*046d*/ 0x08040313U, +/*046e*/ 0x10010313U, +/*046f*/ 0x18080313U, +/*0470*/ 0x00040314U, +/*0471*/ 0x08010314U, +/*0472*/ 0x10080314U, +/*0473*/ 0x18040314U, +/*0474*/ 0x00010315U, +/*0475*/ 0x08080315U, +/*0476*/ 0x10040315U, +/*0477*/ 0x18010315U, +/*0478*/ 0x00080316U, +/*0479*/ 0x08040316U, +/*047a*/ 0x10010316U, +/*047b*/ 0x18080316U, +/*047c*/ 0x00080317U, +/*047d*/ 0x00010318U, +/*047e*/ 0x08050318U, +/*047f*/ 0x10010318U, +/*0480*/ 0x18020318U, +/*0481*/ 0x00010319U, +/*0482*/ 0x08010319U, +/*0483*/ 0x10010319U, +/*0484*/ 0x18010319U, +/*0485*/ 0x0001031aU, +/*0486*/ 0x0801031aU, +/*0487*/ 0x1001031aU, +/*0488*/ 0x1801031aU, +/*0489*/ 0x0001031bU, +/*048a*/ 0x0801031bU, +/*048b*/ 0x1001031bU, +/*048c*/ 0x1801031bU, +/*048d*/ 0x0001031cU, +/*048e*/ 0x0801031cU, +/*048f*/ 0x1001031cU, +/*0490*/ 0x1801031cU, +/*0491*/ 0x0008031dU, +/*0492*/ 0x0808031dU, +/*0493*/ 0x1008031dU, +/*0494*/ 0x1808031dU, + } +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h new file mode 100644 index 0000000..357f8ba --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define DDR_PHY_SLICE_REGSET_OFS_H3 0x0400 +#define DDR_PHY_ADR_V_REGSET_OFS_H3 0x0600 +#define DDR_PHY_ADR_I_REGSET_OFS_H3 0x0680 +#define DDR_PHY_ADR_G_REGSET_OFS_H3 0x0700 +#define DDR_PI_REGSET_OFS_H3 0x0200 + +#define DDR_PHY_SLICE_REGSET_SIZE_H3 0x80 +#define DDR_PHY_ADR_V_REGSET_SIZE_H3 0x80 +#define DDR_PHY_ADR_I_REGSET_SIZE_H3 0x80 +#define DDR_PHY_ADR_G_REGSET_SIZE_H3 0x80 +#define DDR_PI_REGSET_SIZE_H3 0x100 + +#define DDR_PHY_SLICE_REGSET_NUM_H3 88 +#define DDR_PHY_ADR_V_REGSET_NUM_H3 37 +#define DDR_PHY_ADR_I_REGSET_NUM_H3 37 +#define DDR_PHY_ADR_G_REGSET_NUM_H3 59 +#define DDR_PI_REGSET_NUM_H3 181 + +static const uint32_t DDR_PHY_SLICE_REGSET_H3[DDR_PHY_SLICE_REGSET_NUM_H3] = { + /*0400*/ 0x000004f0, + /*0401*/ 0x00000000, + /*0402*/ 0x00000000, + /*0403*/ 0x00000100, + /*0404*/ 0x01003c0c, + /*0405*/ 0x02003c0c, + /*0406*/ 0x00010300, + /*0407*/ 0x04000100, + /*0408*/ 0x00000300, + /*0409*/ 0x000700c0, + /*040a*/ 0x00b00201, + /*040b*/ 0x00000020, + /*040c*/ 0x00000000, + /*040d*/ 0x00000000, + /*040e*/ 0x00000000, + /*040f*/ 0x00000000, + /*0410*/ 0x00000000, + /*0411*/ 0x00000000, + /*0412*/ 0x00000000, + /*0413*/ 0x09000000, + /*0414*/ 0x04080000, + /*0415*/ 0x04080400, + /*0416*/ 0x00000000, + /*0417*/ 0x32103210, + /*0418*/ 0x00800708, + /*0419*/ 0x000f000c, + /*041a*/ 0x00000100, + /*041b*/ 0x55aa55aa, + /*041c*/ 0x33cc33cc, + /*041d*/ 0x0ff00ff0, + /*041e*/ 0x0f0ff0f0, + /*041f*/ 0x00008e38, + /*0420*/ 0x76543210, + /*0421*/ 0x00000001, + /*0422*/ 0x00000000, + /*0423*/ 0x00000000, + /*0424*/ 0x00000000, + /*0425*/ 0x00000000, + /*0426*/ 0x00000000, + /*0427*/ 0x00000000, + /*0428*/ 0x00000000, + /*0429*/ 0x00000000, + /*042a*/ 0x00000000, + /*042b*/ 0x00000000, + /*042c*/ 0x00000000, + /*042d*/ 0x00000000, + /*042e*/ 0x00000000, + /*042f*/ 0x00000000, + /*0430*/ 0x00000000, + /*0431*/ 0x00000000, + /*0432*/ 0x00000000, + /*0433*/ 0x00200000, + /*0434*/ 0x08200820, + /*0435*/ 0x08200820, + /*0436*/ 0x08200820, + /*0437*/ 0x08200820, + /*0438*/ 0x08200820, + /*0439*/ 0x00000820, + /*043a*/ 0x03000300, + /*043b*/ 0x03000300, + /*043c*/ 0x03000300, + /*043d*/ 0x03000300, + /*043e*/ 0x00000300, + /*043f*/ 0x00000000, + /*0440*/ 0x00000000, + /*0441*/ 0x00000000, + /*0442*/ 0x00000000, + /*0443*/ 0x00a000a0, + /*0444*/ 0x00a000a0, + /*0445*/ 0x00a000a0, + /*0446*/ 0x00a000a0, + /*0447*/ 0x00a000a0, + /*0448*/ 0x00a000a0, + /*0449*/ 0x00a000a0, + /*044a*/ 0x00a000a0, + /*044b*/ 0x00a000a0, + /*044c*/ 0x01040109, + /*044d*/ 0x00000200, + /*044e*/ 0x01000000, + /*044f*/ 0x00000200, + /*0450*/ 0x4041a151, + /*0451*/ 0xc00141a0, + /*0452*/ 0x0e0100c0, + /*0453*/ 0x0010000c, + /*0454*/ 0x0c064208, + /*0455*/ 0x000f0c18, + /*0456*/ 0x00e00140, + /*0457*/ 0x00000c20 +}; + +static const uint32_t DDR_PHY_ADR_V_REGSET_H3[DDR_PHY_ADR_V_REGSET_NUM_H3] = { + /*0600*/ 0x00000000, + /*0601*/ 0x00000000, + /*0602*/ 0x00000000, + /*0603*/ 0x00000000, + /*0604*/ 0x00000000, + /*0605*/ 0x00000000, + /*0606*/ 0x00000002, + /*0607*/ 0x00000000, + /*0608*/ 0x00000000, + /*0609*/ 0x00000000, + /*060a*/ 0x00400320, + /*060b*/ 0x00000040, + /*060c*/ 0x00dcba98, + /*060d*/ 0x00000000, + /*060e*/ 0x00dcba98, + /*060f*/ 0x01000000, + /*0610*/ 0x00020003, + /*0611*/ 0x00000000, + /*0612*/ 0x00000000, + /*0613*/ 0x00000000, + /*0614*/ 0x00002a01, + /*0615*/ 0x00000015, + /*0616*/ 0x00000015, + /*0617*/ 0x0000002a, + /*0618*/ 0x00000033, + /*0619*/ 0x0000000c, + /*061a*/ 0x0000000c, + /*061b*/ 0x00000033, + /*061c*/ 0x00418820, + /*061d*/ 0x003f0000, + /*061e*/ 0x0000003f, + /*061f*/ 0x0002006e, + /*0620*/ 0x02000200, + /*0621*/ 0x02000200, + /*0622*/ 0x00000200, + /*0623*/ 0x42080010, + /*0624*/ 0x00000003 +}; + +static const uint32_t DDR_PHY_ADR_I_REGSET_H3[DDR_PHY_ADR_I_REGSET_NUM_H3] = { + /*0680*/ 0x04040404, + /*0681*/ 0x00000404, + /*0682*/ 0x00000000, + /*0683*/ 0x00000000, + /*0684*/ 0x00000000, + /*0685*/ 0x00000000, + /*0686*/ 0x00000002, + /*0687*/ 0x00000000, + /*0688*/ 0x00000000, + /*0689*/ 0x00000000, + /*068a*/ 0x00400320, + /*068b*/ 0x00000040, + /*068c*/ 0x00000000, + /*068d*/ 0x00000000, + /*068e*/ 0x00000000, + /*068f*/ 0x01000000, + /*0690*/ 0x00020003, + /*0691*/ 0x00000000, + /*0692*/ 0x00000000, + /*0693*/ 0x00000000, + /*0694*/ 0x00002a01, + /*0695*/ 0x00000015, + /*0696*/ 0x00000015, + /*0697*/ 0x0000002a, + /*0698*/ 0x00000033, + /*0699*/ 0x0000000c, + /*069a*/ 0x0000000c, + /*069b*/ 0x00000033, + /*069c*/ 0x00000000, + /*069d*/ 0x00000000, + /*069e*/ 0x00000000, + /*069f*/ 0x0002006e, + /*06a0*/ 0x02000200, + /*06a1*/ 0x02000200, + /*06a2*/ 0x00000200, + /*06a3*/ 0x42080010, + /*06a4*/ 0x00000003 +}; + +static const uint32_t DDR_PHY_ADR_G_REGSET_H3[DDR_PHY_ADR_G_REGSET_NUM_H3] = { + /*0700*/ 0x00000001, + /*0701*/ 0x00000000, + /*0702*/ 0x00000005, + /*0703*/ 0x04000f00, + /*0704*/ 0x00020080, + /*0705*/ 0x00020055, + /*0706*/ 0x00000000, + /*0707*/ 0x00000000, + /*0708*/ 0x00000000, + /*0709*/ 0x00000050, + /*070a*/ 0x00000000, + /*070b*/ 0x01010100, + /*070c*/ 0x00000200, + /*070d*/ 0x00001102, + /*070e*/ 0x00000000, + /*070f*/ 0x000f1f00, + /*0710*/ 0x0f1f0f1f, + /*0711*/ 0x0f1f0f1f, + /*0712*/ 0x00020003, + /*0713*/ 0x02000200, + /*0714*/ 0x00000200, + /*0715*/ 0x00001102, + /*0716*/ 0x00000064, + /*0717*/ 0x00000000, + /*0718*/ 0x00000000, + /*0719*/ 0x00000502, + /*071a*/ 0x027f6e00, + /*071b*/ 0x007f007f, + /*071c*/ 0x00007f3c, + /*071d*/ 0x00047f6e, + /*071e*/ 0x0003154f, + /*071f*/ 0x0001154f, + /*0720*/ 0x0001154f, + /*0721*/ 0x0001154f, + /*0722*/ 0x0001154f, + /*0723*/ 0x00003fee, + /*0724*/ 0x0001154f, + /*0725*/ 0x00003fee, + /*0726*/ 0x0001154f, + /*0727*/ 0x00007f3c, + /*0728*/ 0x0001154f, + /*0729*/ 0x00000000, + /*072a*/ 0x00000000, + /*072b*/ 0x00000000, + /*072c*/ 0x65000000, + /*072d*/ 0x00000000, + /*072e*/ 0x00000000, + /*072f*/ 0x00000201, + /*0730*/ 0x00000000, + /*0731*/ 0x00000000, + /*0732*/ 0x00000000, + /*0733*/ 0x00000000, + /*0734*/ 0x00000000, + /*0735*/ 0x00000000, + /*0736*/ 0x00000000, + /*0737*/ 0x00000000, + /*0738*/ 0x00000000, + /*0739*/ 0x00000000, + /*073a*/ 0x00000000 +}; + +static const uint32_t DDR_PI_REGSET_H3[DDR_PI_REGSET_NUM_H3] = { + /*0200*/ 0x00000b00, + /*0201*/ 0x00000100, + /*0202*/ 0x00000000, + /*0203*/ 0x0000ffff, + /*0204*/ 0x00000000, + /*0205*/ 0x0000ffff, + /*0206*/ 0x00000000, + /*0207*/ 0x304cffff, + /*0208*/ 0x00000200, + /*0209*/ 0x00000200, + /*020a*/ 0x00000200, + /*020b*/ 0x00000200, + /*020c*/ 0x0000304c, + /*020d*/ 0x00000200, + /*020e*/ 0x00000200, + /*020f*/ 0x00000200, + /*0210*/ 0x00000200, + /*0211*/ 0x0000304c, + /*0212*/ 0x00000200, + /*0213*/ 0x00000200, + /*0214*/ 0x00000200, + /*0215*/ 0x00000200, + /*0216*/ 0x00010000, + /*0217*/ 0x00000003, + /*0218*/ 0x01000001, + /*0219*/ 0x00000000, + /*021a*/ 0x00000000, + /*021b*/ 0x00000000, + /*021c*/ 0x00000000, + /*021d*/ 0x00000000, + /*021e*/ 0x00000000, + /*021f*/ 0x00000000, + /*0220*/ 0x00000000, + /*0221*/ 0x00000000, + /*0222*/ 0x00000000, + /*0223*/ 0x00000000, + /*0224*/ 0x00000000, + /*0225*/ 0x00000000, + /*0226*/ 0x00000000, + /*0227*/ 0x00000000, + /*0228*/ 0x00000000, + /*0229*/ 0x0f000101, + /*022a*/ 0x08492d25, + /*022b*/ 0x500e0c04, + /*022c*/ 0x0002500e, + /*022d*/ 0x00460003, + /*022e*/ 0x182600cf, + /*022f*/ 0x182600cf, + /*0230*/ 0x00000005, + /*0231*/ 0x00000000, + /*0232*/ 0x00000000, + /*0233*/ 0x00000000, + /*0234*/ 0x00000000, + /*0235*/ 0x00000000, + /*0236*/ 0x00000000, + /*0237*/ 0x00000000, + /*0238*/ 0x01000000, + /*0239*/ 0x00040404, + /*023a*/ 0x01280a00, + /*023b*/ 0x00000000, + /*023c*/ 0x000f0000, + /*023d*/ 0x00001803, + /*023e*/ 0x00000000, + /*023f*/ 0x00000000, + /*0240*/ 0x00060002, + /*0241*/ 0x00010001, + /*0242*/ 0x01000101, + /*0243*/ 0x04020201, + /*0244*/ 0x00080804, + /*0245*/ 0x00000000, + /*0246*/ 0x08030000, + /*0247*/ 0x15150408, + /*0248*/ 0x00000000, + /*0249*/ 0x00000000, + /*024a*/ 0x00000000, + /*024b*/ 0x001e0f0f, + /*024c*/ 0x00000000, + /*024d*/ 0x01000300, + /*024e*/ 0x00000000, + /*024f*/ 0x00000000, + /*0250*/ 0x01000000, + /*0251*/ 0x00010101, + /*0252*/ 0x000e0e0e, + /*0253*/ 0x000c0c0c, + /*0254*/ 0x02060601, + /*0255*/ 0x00000000, + /*0256*/ 0x00000003, + /*0257*/ 0x00181703, + /*0258*/ 0x00280006, + /*0259*/ 0x00280016, + /*025a*/ 0x00000016, + /*025b*/ 0x00000000, + /*025c*/ 0x00000000, + /*025d*/ 0x00000000, + /*025e*/ 0x140a0000, + /*025f*/ 0x0005010a, + /*0260*/ 0x03018d03, + /*0261*/ 0x000a018d, + /*0262*/ 0x00060100, + /*0263*/ 0x01000006, + /*0264*/ 0x018e018e, + /*0265*/ 0x018e0100, + /*0266*/ 0x1111018e, + /*0267*/ 0x10010204, + /*0268*/ 0x09090650, + /*0269*/ 0x20110202, + /*026a*/ 0x00201000, + /*026b*/ 0x00201000, + /*026c*/ 0x04041000, + /*026d*/ 0x18020100, + /*026e*/ 0x00010118, + /*026f*/ 0x004b004a, + /*0270*/ 0x050f0000, + /*0271*/ 0x0c01021e, + /*0272*/ 0x34000000, + /*0273*/ 0x00000000, + /*0274*/ 0x00000000, + /*0275*/ 0x00000000, + /*0276*/ 0x312ed400, + /*0277*/ 0xd4111132, + /*0278*/ 0x1132312e, + /*0279*/ 0x312ed411, + /*027a*/ 0x00111132, + /*027b*/ 0x32312ed4, + /*027c*/ 0x2ed41111, + /*027d*/ 0x11113231, + /*027e*/ 0x32312ed4, + /*027f*/ 0xd4001111, + /*0280*/ 0x1132312e, + /*0281*/ 0x312ed411, + /*0282*/ 0xd4111132, + /*0283*/ 0x1132312e, + /*0284*/ 0x2ed40011, + /*0285*/ 0x11113231, + /*0286*/ 0x32312ed4, + /*0287*/ 0x2ed41111, + /*0288*/ 0x11113231, + /*0289*/ 0x00020000, + /*028a*/ 0x018d018d, + /*028b*/ 0x0c08018d, + /*028c*/ 0x1f121d22, + /*028d*/ 0x4301b344, + /*028e*/ 0x10172006, + /*028f*/ 0x121d220c, + /*0290*/ 0x01b3441f, + /*0291*/ 0x17200643, + /*0292*/ 0x1d220c10, + /*0293*/ 0x00001f12, + /*0294*/ 0x4301b344, + /*0295*/ 0x10172006, + /*0296*/ 0x00020002, + /*0297*/ 0x00020002, + /*0298*/ 0x00020002, + /*0299*/ 0x00020002, + /*029a*/ 0x00020002, + /*029b*/ 0x00000000, + /*029c*/ 0x00000000, + /*029d*/ 0x00000000, + /*029e*/ 0x00000000, + /*029f*/ 0x00000000, + /*02a0*/ 0x00000000, + /*02a1*/ 0x00000000, + /*02a2*/ 0x00000000, + /*02a3*/ 0x00000000, + /*02a4*/ 0x00000000, + /*02a5*/ 0x00000000, + /*02a6*/ 0x00000000, + /*02a7*/ 0x01000400, + /*02a8*/ 0x00304c00, + /*02a9*/ 0x0001e2f8, + /*02aa*/ 0x0000304c, + /*02ab*/ 0x0001e2f8, + /*02ac*/ 0x0000304c, + /*02ad*/ 0x0001e2f8, + /*02ae*/ 0x08000000, + /*02af*/ 0x00000100, + /*02b0*/ 0x00000000, + /*02b1*/ 0x00000000, + /*02b2*/ 0x00000000, + /*02b3*/ 0x00000000, + /*02b4*/ 0x00000002 +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h new file mode 100644 index 0000000..e5258af --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define DDR_PHY_SLICE_REGSET_OFS_H3VER2 0x0400 +#define DDR_PHY_ADR_V_REGSET_OFS_H3VER2 0x0600 +#define DDR_PHY_ADR_I_REGSET_OFS_H3VER2 0x0640 +#define DDR_PHY_ADR_G_REGSET_OFS_H3VER2 0x0680 +#define DDR_PI_REGSET_OFS_H3VER2 0x0200 + +#define DDR_PHY_SLICE_REGSET_SIZE_H3VER2 0x80 +#define DDR_PHY_ADR_V_REGSET_SIZE_H3VER2 0x40 +#define DDR_PHY_ADR_I_REGSET_SIZE_H3VER2 0x40 +#define DDR_PHY_ADR_G_REGSET_SIZE_H3VER2 0x80 +#define DDR_PI_REGSET_SIZE_H3VER2 0x100 + +#define DDR_PHY_SLICE_REGSET_NUM_H3VER2 97 +#define DDR_PHY_ADR_V_REGSET_NUM_H3VER2 37 +#define DDR_PHY_ADR_I_REGSET_NUM_H3VER2 37 +#define DDR_PHY_ADR_G_REGSET_NUM_H3VER2 79 +#define DDR_PI_REGSET_NUM_H3VER2 245 + +static const uint32_t DDR_PHY_SLICE_REGSET_H3VER2 + [DDR_PHY_SLICE_REGSET_NUM_H3VER2] = { + /*0400*/ 0x76543210, + /*0401*/ 0x0004f008, + /*0402*/ 0x00020133, + /*0403*/ 0x00000000, + /*0404*/ 0x00000000, + /*0405*/ 0x00010000, + /*0406*/ 0x016e6e0e, + /*0407*/ 0x026e6e0e, + /*0408*/ 0x00010300, + /*0409*/ 0x04000100, + /*040a*/ 0x01000000, + /*040b*/ 0x00000000, + /*040c*/ 0x00000000, + /*040d*/ 0x00000100, + /*040e*/ 0x001700c0, + /*040f*/ 0x020100b0, + /*0410*/ 0x00030020, + /*0411*/ 0x00000000, + /*0412*/ 0x00000000, + /*0413*/ 0x00000000, + /*0414*/ 0x00000000, + /*0415*/ 0x00000000, + /*0416*/ 0x00000000, + /*0417*/ 0x00000000, + /*0418*/ 0x09000000, + /*0419*/ 0x04080000, + /*041a*/ 0x04080400, + /*041b*/ 0x08000000, + /*041c*/ 0x0c008007, + /*041d*/ 0x00000f00, + /*041e*/ 0x00000100, + /*041f*/ 0x55aa55aa, + /*0420*/ 0x33cc33cc, + /*0421*/ 0x0ff00ff0, + /*0422*/ 0x0f0ff0f0, + /*0423*/ 0x00018e38, + /*0424*/ 0x00000000, + /*0425*/ 0x00000000, + /*0426*/ 0x00000000, + /*0427*/ 0x00000000, + /*0428*/ 0x00000000, + /*0429*/ 0x00000000, + /*042a*/ 0x00000000, + /*042b*/ 0x00000000, + /*042c*/ 0x00000000, + /*042d*/ 0x00000000, + /*042e*/ 0x00000000, + /*042f*/ 0x00000000, + /*0430*/ 0x00000000, + /*0431*/ 0x00000000, + /*0432*/ 0x00000000, + /*0433*/ 0x00000000, + /*0434*/ 0x00000000, + /*0435*/ 0x00000000, + /*0436*/ 0x00000000, + /*0437*/ 0x00000000, + /*0438*/ 0x00000104, + /*0439*/ 0x00082020, + /*043a*/ 0x08200820, + /*043b*/ 0x08200820, + /*043c*/ 0x08200820, + /*043d*/ 0x08200820, + /*043e*/ 0x08200820, + /*043f*/ 0x00000000, + /*0440*/ 0x00000000, + /*0441*/ 0x03000300, + /*0442*/ 0x03000300, + /*0443*/ 0x03000300, + /*0444*/ 0x03000300, + /*0445*/ 0x00000300, + /*0446*/ 0x00000000, + /*0447*/ 0x00000000, + /*0448*/ 0x00000000, + /*0449*/ 0x00000000, + /*044a*/ 0x00000000, + /*044b*/ 0x00a000a0, + /*044c*/ 0x00a000a0, + /*044d*/ 0x00a000a0, + /*044e*/ 0x00a000a0, + /*044f*/ 0x00a000a0, + /*0450*/ 0x00a000a0, + /*0451*/ 0x00a000a0, + /*0452*/ 0x00a000a0, + /*0453*/ 0x00a000a0, + /*0454*/ 0x01040109, + /*0455*/ 0x00000200, + /*0456*/ 0x01000000, + /*0457*/ 0x00000200, + /*0458*/ 0x00000004, + /*0459*/ 0x4041a151, + /*045a*/ 0xc00141a0, + /*045b*/ 0x0e0000c0, + /*045c*/ 0x0010000c, + /*045d*/ 0x063e4208, + /*045e*/ 0x0f0c180c, + /*045f*/ 0x00e00140, + /*0460*/ 0x00000c20 +}; + +static const uint32_t + DDR_PHY_ADR_V_REGSET_H3VER2[DDR_PHY_ADR_V_REGSET_NUM_H3VER2] = { + /*0600*/ 0x00000000, + /*0601*/ 0x00000000, + /*0602*/ 0x00000000, + /*0603*/ 0x00000000, + /*0604*/ 0x00000000, + /*0605*/ 0x00000000, + /*0606*/ 0x00000000, + /*0607*/ 0x00010000, + /*0608*/ 0x00000200, + /*0609*/ 0x00000000, + /*060a*/ 0x00000000, + /*060b*/ 0x00000000, + /*060c*/ 0x00400320, + /*060d*/ 0x00000040, + /*060e*/ 0x00dcba98, + /*060f*/ 0x03000000, + /*0610*/ 0x00000200, + /*0611*/ 0x00000000, + /*0612*/ 0x00000000, + /*0613*/ 0x00000000, + /*0614*/ 0x0000002a, + /*0615*/ 0x00000015, + /*0616*/ 0x00000015, + /*0617*/ 0x0000002a, + /*0618*/ 0x00000033, + /*0619*/ 0x0000000c, + /*061a*/ 0x0000000c, + /*061b*/ 0x00000033, + /*061c*/ 0x00418820, + /*061d*/ 0x003f0000, + /*061e*/ 0x0000003f, + /*061f*/ 0x0002c06e, + /*0620*/ 0x02c002c0, + /*0621*/ 0x02c002c0, + /*0622*/ 0x000002c0, + /*0623*/ 0x42080010, + /*0624*/ 0x0000033e +}; + +static const uint32_t + DDR_PHY_ADR_I_REGSET_H3VER2[DDR_PHY_ADR_I_REGSET_NUM_H3VER2] = { + /*0640*/ 0x00000000, + /*0641*/ 0x00000000, + /*0642*/ 0x00000000, + /*0643*/ 0x00000000, + /*0644*/ 0x00000000, + /*0645*/ 0x00000000, + /*0646*/ 0x00000000, + /*0647*/ 0x00000000, + /*0648*/ 0x00000000, + /*0649*/ 0x00000000, + /*064a*/ 0x00000000, + /*064b*/ 0x00000000, + /*064c*/ 0x00000000, + /*064d*/ 0x00000000, + /*064e*/ 0x00000000, + /*064f*/ 0x00000000, + /*0650*/ 0x00000000, + /*0651*/ 0x00000000, + /*0652*/ 0x00000000, + /*0653*/ 0x00000000, + /*0654*/ 0x00000000, + /*0655*/ 0x00000000, + /*0656*/ 0x00000000, + /*0657*/ 0x00000000, + /*0658*/ 0x00000000, + /*0659*/ 0x00000000, + /*065a*/ 0x00000000, + /*065b*/ 0x00000000, + /*065c*/ 0x00000000, + /*065d*/ 0x00000000, + /*065e*/ 0x00000000, + /*065f*/ 0x00000000, + /*0660*/ 0x00000000, + /*0661*/ 0x00000000, + /*0662*/ 0x00000000, + /*0663*/ 0x00000000, + /*0664*/ 0x00000000 +}; + +static const uint32_t + DDR_PHY_ADR_G_REGSET_H3VER2[DDR_PHY_ADR_G_REGSET_NUM_H3VER2] = { + /*0680*/ 0x00000000, + /*0681*/ 0x00000100, + /*0682*/ 0x00000000, + /*0683*/ 0x00050000, + /*0684*/ 0x0f000000, + /*0685*/ 0x00800400, + /*0686*/ 0x00020032, + /*0687*/ 0x00020055, + /*0688*/ 0x00000000, + /*0689*/ 0x00000000, + /*068a*/ 0x00000000, + /*068b*/ 0x00000050, + /*068c*/ 0x00000000, + /*068d*/ 0x01010100, + /*068e*/ 0x01000200, + /*068f*/ 0x00000000, + /*0690*/ 0x00010100, + /*0691*/ 0x00000000, + /*0692*/ 0x00000000, + /*0693*/ 0x00000000, + /*0694*/ 0x00000000, + /*0695*/ 0x00005064, + /*0696*/ 0x01421142, + /*0697*/ 0x00000142, + /*0698*/ 0x00000000, + /*0699*/ 0x000f1100, + /*069a*/ 0x0f110f11, + /*069b*/ 0x09000f11, + /*069c*/ 0x00000003, + /*069d*/ 0x0002c000, + /*069e*/ 0x02c002c0, + /*069f*/ 0x000002c0, + /*06a0*/ 0x03421342, + /*06a1*/ 0x00000342, + /*06a2*/ 0x00000000, + /*06a3*/ 0x00000000, + /*06a4*/ 0x05020000, + /*06a5*/ 0x14000000, + /*06a6*/ 0x027f6e00, + /*06a7*/ 0x047f027f, + /*06a8*/ 0x00027f6e, + /*06a9*/ 0x00047f6e, + /*06aa*/ 0x0003554f, + /*06ab*/ 0x0001554f, + /*06ac*/ 0x0001554f, + /*06ad*/ 0x0001554f, + /*06ae*/ 0x0001554f, + /*06af*/ 0x00003fee, + /*06b0*/ 0x0001554f, + /*06b1*/ 0x00003fee, + /*06b2*/ 0x0001554f, + /*06b3*/ 0x00027f6e, + /*06b4*/ 0x0001554f, + /*06b5*/ 0x00004011, + /*06b6*/ 0x00004410, + /*06b7*/ 0x00000000, + /*06b8*/ 0x00000000, + /*06b9*/ 0x00000000, + /*06ba*/ 0x00000065, + /*06bb*/ 0x00000000, + /*06bc*/ 0x00020201, + /*06bd*/ 0x00000000, + /*06be*/ 0x03000000, + /*06bf*/ 0x00000008, + /*06c0*/ 0x00000000, + /*06c1*/ 0x00000000, + /*06c2*/ 0x00000000, + /*06c3*/ 0x00000000, + /*06c4*/ 0x00000001, + /*06c5*/ 0x00000000, + /*06c6*/ 0x00000000, + /*06c7*/ 0x00000000, + /*06c8*/ 0x000000e4, + /*06c9*/ 0x00010198, + /*06ca*/ 0x00000000, + /*06cb*/ 0x00000000, + /*06cc*/ 0x07010000, + /*06cd*/ 0x00000104, + /*06ce*/ 0x00000000 +}; + +static const uint32_t DDR_PI_REGSET_H3VER2[DDR_PI_REGSET_NUM_H3VER2] = { + /*0200*/ 0x00000b00, + /*0201*/ 0x00000100, + /*0202*/ 0x00640000, + /*0203*/ 0x00000000, + /*0204*/ 0x0000ffff, + /*0205*/ 0x00000000, + /*0206*/ 0x0000ffff, + /*0207*/ 0x00000000, + /*0208*/ 0x0000ffff, + /*0209*/ 0x0000304c, + /*020a*/ 0x00000200, + /*020b*/ 0x00000200, + /*020c*/ 0x00000200, + /*020d*/ 0x00000200, + /*020e*/ 0x0000304c, + /*020f*/ 0x00000200, + /*0210*/ 0x00000200, + /*0211*/ 0x00000200, + /*0212*/ 0x00000200, + /*0213*/ 0x0000304c, + /*0214*/ 0x00000200, + /*0215*/ 0x00000200, + /*0216*/ 0x00000200, + /*0217*/ 0x00000200, + /*0218*/ 0x00010000, + /*0219*/ 0x00000003, + /*021a*/ 0x01000001, + /*021b*/ 0x00000000, + /*021c*/ 0x00000000, + /*021d*/ 0x00000000, + /*021e*/ 0x00000000, + /*021f*/ 0x00000000, + /*0220*/ 0x00000000, + /*0221*/ 0x00000000, + /*0222*/ 0x00000000, + /*0223*/ 0x00000000, + /*0224*/ 0x00000000, + /*0225*/ 0x00000000, + /*0226*/ 0x00000000, + /*0227*/ 0x00000000, + /*0228*/ 0x00000000, + /*0229*/ 0x00000000, + /*022a*/ 0x00000000, + /*022b*/ 0x0f000101, + /*022c*/ 0x08492d25, + /*022d*/ 0x500e0c04, + /*022e*/ 0x0002500e, + /*022f*/ 0x00000301, + /*0230*/ 0x00000046, + /*0231*/ 0x000000cf, + /*0232*/ 0x00001826, + /*0233*/ 0x000000cf, + /*0234*/ 0x00001826, + /*0235*/ 0x00000005, + /*0236*/ 0x00000000, + /*0237*/ 0x00000000, + /*0238*/ 0x00000000, + /*0239*/ 0x00000000, + /*023a*/ 0x00000000, + /*023b*/ 0x00000000, + /*023c*/ 0x00000000, + /*023d*/ 0x00000000, + /*023e*/ 0x04010000, + /*023f*/ 0x00000404, + /*0240*/ 0x0101280a, + /*0241*/ 0x00000000, + /*0242*/ 0x00000000, + /*0243*/ 0x0003000f, + /*0244*/ 0x00000018, + /*0245*/ 0x00000000, + /*0246*/ 0x00000000, + /*0247*/ 0x00060002, + /*0248*/ 0x00010001, + /*0249*/ 0x01000101, + /*024a*/ 0x04020201, + /*024b*/ 0x00080804, + /*024c*/ 0x00000000, + /*024d*/ 0x08030000, + /*024e*/ 0x15150408, + /*024f*/ 0x00000000, + /*0250*/ 0x00000000, + /*0251*/ 0x00000000, + /*0252*/ 0x0f0f0000, + /*0253*/ 0x0000001e, + /*0254*/ 0x00000000, + /*0255*/ 0x01000300, + /*0256*/ 0x00000100, + /*0257*/ 0x00000000, + /*0258*/ 0x00000000, + /*0259*/ 0x01000000, + /*025a*/ 0x00000101, + /*025b*/ 0x55555a5a, + /*025c*/ 0x55555a5a, + /*025d*/ 0x55555a5a, + /*025e*/ 0x55555a5a, + /*025f*/ 0x0e0e0001, + /*0260*/ 0x0c0c000e, + /*0261*/ 0x0601000c, + /*0262*/ 0x17170106, + /*0263*/ 0x00020202, + /*0264*/ 0x03000000, + /*0265*/ 0x00000000, + /*0266*/ 0x00181703, + /*0267*/ 0x00280006, + /*0268*/ 0x00280016, + /*0269*/ 0x00000016, + /*026a*/ 0x00000000, + /*026b*/ 0x00000000, + /*026c*/ 0x00000000, + /*026d*/ 0x0a000000, + /*026e*/ 0x00010a14, + /*026f*/ 0x00030005, + /*0270*/ 0x0003018d, + /*0271*/ 0x000a018d, + /*0272*/ 0x00060100, + /*0273*/ 0x01000006, + /*0274*/ 0x018e018e, + /*0275*/ 0x018e0100, + /*0276*/ 0x1111018e, + /*0277*/ 0x10010204, + /*0278*/ 0x09090650, + /*0279*/ 0xff110202, + /*027a*/ 0x00ff1000, + /*027b*/ 0x00ff1000, + /*027c*/ 0x04041000, + /*027d*/ 0x18020100, + /*027e*/ 0x01010018, + /*027f*/ 0x004a004a, + /*0280*/ 0x004b004a, + /*0281*/ 0x050f0000, + /*0282*/ 0x0c01021e, + /*0283*/ 0x34000000, + /*0284*/ 0x00000000, + /*0285*/ 0x00000000, + /*0286*/ 0x00000000, + /*0287*/ 0x00000000, + /*0288*/ 0x36312ed4, + /*0289*/ 0x2ed41111, + /*028a*/ 0x11113631, + /*028b*/ 0x36312ed4, + /*028c*/ 0xd4001111, + /*028d*/ 0x1136312e, + /*028e*/ 0x312ed411, + /*028f*/ 0xd4111136, + /*0290*/ 0x1136312e, + /*0291*/ 0x2ed40011, + /*0292*/ 0x11113631, + /*0293*/ 0x36312ed4, + /*0294*/ 0x2ed41111, + /*0295*/ 0x11113631, + /*0296*/ 0x312ed400, + /*0297*/ 0xd4111136, + /*0298*/ 0x1136312e, + /*0299*/ 0x312ed411, + /*029a*/ 0x00111136, + /*029b*/ 0x018d0200, + /*029c*/ 0x018d018d, + /*029d*/ 0x1d220c08, + /*029e*/ 0x00001f12, + /*029f*/ 0x4301b344, + /*02a0*/ 0x10172006, + /*02a1*/ 0x121d220c, + /*02a2*/ 0x01b3441f, + /*02a3*/ 0x17200643, + /*02a4*/ 0x1d220c10, + /*02a5*/ 0x00001f12, + /*02a6*/ 0x4301b344, + /*02a7*/ 0x10172006, + /*02a8*/ 0x00020002, + /*02a9*/ 0x00020002, + /*02aa*/ 0x00020002, + /*02ab*/ 0x00020002, + /*02ac*/ 0x00020002, + /*02ad*/ 0x00000000, + /*02ae*/ 0x00000000, + /*02af*/ 0x00000000, + /*02b0*/ 0x00000000, + /*02b1*/ 0x00000000, + /*02b2*/ 0x00000000, + /*02b3*/ 0x00000000, + /*02b4*/ 0x00000000, + /*02b5*/ 0x00000000, + /*02b6*/ 0x00000000, + /*02b7*/ 0x00000000, + /*02b8*/ 0x00000000, + /*02b9*/ 0x00000400, + /*02ba*/ 0x05040302, + /*02bb*/ 0x01000f0e, + /*02bc*/ 0x07060504, + /*02bd*/ 0x03020100, + /*02be*/ 0x02010000, + /*02bf*/ 0x00000103, + /*02c0*/ 0x0000304c, + /*02c1*/ 0x0001e2f8, + /*02c2*/ 0x0000304c, + /*02c3*/ 0x0001e2f8, + /*02c4*/ 0x0000304c, + /*02c5*/ 0x0001e2f8, + /*02c6*/ 0x08000000, + /*02c7*/ 0x00000100, + /*02c8*/ 0x00000000, + /*02c9*/ 0x00000000, + /*02ca*/ 0x00000000, + /*02cb*/ 0x00000000, + /*02cc*/ 0x00010000, + /*02cd*/ 0x00000000, + /*02ce*/ 0x00000000, + /*02cf*/ 0x00000000, + /*02d0*/ 0x00000000, + /*02d1*/ 0x00000000, + /*02d2*/ 0x00000000, + /*02d3*/ 0x00000000, + /*02d4*/ 0x00000000, + /*02d5*/ 0x00000000, + /*02d6*/ 0x00000000, + /*02d7*/ 0x00000000, + /*02d8*/ 0x00000000, + /*02d9*/ 0x00000000, + /*02da*/ 0x00000000, + /*02db*/ 0x00000000, + /*02dc*/ 0x00000000, + /*02dd*/ 0x00000000, + /*02de*/ 0x00000000, + /*02df*/ 0x00000000, + /*02e0*/ 0x00000000, + /*02e1*/ 0x00000000, + /*02e2*/ 0x00000000, + /*02e3*/ 0x00000000, + /*02e4*/ 0x00000000, + /*02e5*/ 0x00000000, + /*02e6*/ 0x00000000, + /*02e7*/ 0x00000000, + /*02e8*/ 0x00000000, + /*02e9*/ 0x00000000, + /*02ea*/ 0x00000000, + /*02eb*/ 0x00000000, + /*02ec*/ 0x00000000, + /*02ed*/ 0x00000000, + /*02ee*/ 0x00000002, + /*02ef*/ 0x00000000, + /*02f0*/ 0x00000000, + /*02f1*/ 0x00000000, + /*02f2*/ 0x00000000, + /*02f3*/ 0x00000000, + /*02f4*/ 0x00000000 +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h new file mode 100644 index 0000000..b491f0e --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define DDR_PHY_SLICE_REGSET_OFS_M3 0x0800 +#define DDR_PHY_ADR_V_REGSET_OFS_M3 0x0a00 +#define DDR_PHY_ADR_I_REGSET_OFS_M3 0x0a80 +#define DDR_PHY_ADR_G_REGSET_OFS_M3 0x0b80 +#define DDR_PI_REGSET_OFS_M3 0x0200 + +#define DDR_PHY_SLICE_REGSET_SIZE_M3 0x80 +#define DDR_PHY_ADR_V_REGSET_SIZE_M3 0x80 +#define DDR_PHY_ADR_I_REGSET_SIZE_M3 0x80 +#define DDR_PHY_ADR_G_REGSET_SIZE_M3 0x80 +#define DDR_PI_REGSET_SIZE_M3 0x100 + +#define DDR_PHY_SLICE_REGSET_NUM_M3 89 +#define DDR_PHY_ADR_V_REGSET_NUM_M3 37 +#define DDR_PHY_ADR_I_REGSET_NUM_M3 37 +#define DDR_PHY_ADR_G_REGSET_NUM_M3 64 +#define DDR_PI_REGSET_NUM_M3 202 + +static const uint32_t DDR_PHY_SLICE_REGSET_M3[DDR_PHY_SLICE_REGSET_NUM_M3] = { + /*0800*/ 0x76543210, + /*0801*/ 0x0004f008, + /*0802*/ 0x00000000, + /*0803*/ 0x00000000, + /*0804*/ 0x00010000, + /*0805*/ 0x036e6e0e, + /*0806*/ 0x026e6e0e, + /*0807*/ 0x00010300, + /*0808*/ 0x04000100, + /*0809*/ 0x00000300, + /*080a*/ 0x001700c0, + /*080b*/ 0x00b00201, + /*080c*/ 0x00030020, + /*080d*/ 0x00000000, + /*080e*/ 0x00000000, + /*080f*/ 0x00000000, + /*0810*/ 0x00000000, + /*0811*/ 0x00000000, + /*0812*/ 0x00000000, + /*0813*/ 0x00000000, + /*0814*/ 0x09000000, + /*0815*/ 0x04080000, + /*0816*/ 0x04080400, + /*0817*/ 0x00000000, + /*0818*/ 0x32103210, + /*0819*/ 0x00800708, + /*081a*/ 0x000f000c, + /*081b*/ 0x00000100, + /*081c*/ 0x55aa55aa, + /*081d*/ 0x33cc33cc, + /*081e*/ 0x0ff00ff0, + /*081f*/ 0x0f0ff0f0, + /*0820*/ 0x00018e38, + /*0821*/ 0x00000000, + /*0822*/ 0x00000000, + /*0823*/ 0x00000000, + /*0824*/ 0x00000000, + /*0825*/ 0x00000000, + /*0826*/ 0x00000000, + /*0827*/ 0x00000000, + /*0828*/ 0x00000000, + /*0829*/ 0x00000000, + /*082a*/ 0x00000000, + /*082b*/ 0x00000000, + /*082c*/ 0x00000000, + /*082d*/ 0x00000000, + /*082e*/ 0x00000000, + /*082f*/ 0x00000000, + /*0830*/ 0x00000000, + /*0831*/ 0x00000000, + /*0832*/ 0x00000000, + /*0833*/ 0x00200000, + /*0834*/ 0x08200820, + /*0835*/ 0x08200820, + /*0836*/ 0x08200820, + /*0837*/ 0x08200820, + /*0838*/ 0x08200820, + /*0839*/ 0x00000820, + /*083a*/ 0x03000300, + /*083b*/ 0x03000300, + /*083c*/ 0x03000300, + /*083d*/ 0x03000300, + /*083e*/ 0x00000300, + /*083f*/ 0x00000000, + /*0840*/ 0x00000000, + /*0841*/ 0x00000000, + /*0842*/ 0x00000000, + /*0843*/ 0x00a00000, + /*0844*/ 0x00a000a0, + /*0845*/ 0x00a000a0, + /*0846*/ 0x00a000a0, + /*0847*/ 0x00a000a0, + /*0848*/ 0x00a000a0, + /*0849*/ 0x00a000a0, + /*084a*/ 0x00a000a0, + /*084b*/ 0x00a000a0, + /*084c*/ 0x010900a0, + /*084d*/ 0x02000104, + /*084e*/ 0x00000000, + /*084f*/ 0x00010000, + /*0850*/ 0x00000200, + /*0851*/ 0x4041a151, + /*0852*/ 0xc00141a0, + /*0853*/ 0x0e0100c0, + /*0854*/ 0x0010000c, + /*0855*/ 0x0c064208, + /*0856*/ 0x000f0c18, + /*0857*/ 0x00e00140, + /*0858*/ 0x00000c20 +}; + +static const uint32_t DDR_PHY_ADR_V_REGSET_M3[DDR_PHY_ADR_V_REGSET_NUM_M3] = { + /*0a00*/ 0x00000000, + /*0a01*/ 0x00000000, + /*0a02*/ 0x00000000, + /*0a03*/ 0x00000000, + /*0a04*/ 0x00000000, + /*0a05*/ 0x00000000, + /*0a06*/ 0x00000002, + /*0a07*/ 0x00000000, + /*0a08*/ 0x00000000, + /*0a09*/ 0x00000000, + /*0a0a*/ 0x00400320, + /*0a0b*/ 0x00000040, + /*0a0c*/ 0x00dcba98, + /*0a0d*/ 0x00000000, + /*0a0e*/ 0x00dcba98, + /*0a0f*/ 0x01000000, + /*0a10*/ 0x00020003, + /*0a11*/ 0x00000000, + /*0a12*/ 0x00000000, + /*0a13*/ 0x00000000, + /*0a14*/ 0x0000002a, + /*0a15*/ 0x00000015, + /*0a16*/ 0x00000015, + /*0a17*/ 0x0000002a, + /*0a18*/ 0x00000033, + /*0a19*/ 0x0000000c, + /*0a1a*/ 0x0000000c, + /*0a1b*/ 0x00000033, + /*0a1c*/ 0x0a418820, + /*0a1d*/ 0x003f0000, + /*0a1e*/ 0x0000003f, + /*0a1f*/ 0x0002c06e, + /*0a20*/ 0x02c002c0, + /*0a21*/ 0x02c002c0, + /*0a22*/ 0x000002c0, + /*0a23*/ 0x42080010, + /*0a24*/ 0x00000003 +}; + +static const uint32_t DDR_PHY_ADR_I_REGSET_M3[DDR_PHY_ADR_I_REGSET_NUM_M3] = { + /*0a80*/ 0x04040404, + /*0a81*/ 0x00000404, + /*0a82*/ 0x00000000, + /*0a83*/ 0x00000000, + /*0a84*/ 0x00000000, + /*0a85*/ 0x00000000, + /*0a86*/ 0x00000002, + /*0a87*/ 0x00000000, + /*0a88*/ 0x00000000, + /*0a89*/ 0x00000000, + /*0a8a*/ 0x00400320, + /*0a8b*/ 0x00000040, + /*0a8c*/ 0x00000000, + /*0a8d*/ 0x00000000, + /*0a8e*/ 0x00000000, + /*0a8f*/ 0x01000000, + /*0a90*/ 0x00020003, + /*0a91*/ 0x00000000, + /*0a92*/ 0x00000000, + /*0a93*/ 0x00000000, + /*0a94*/ 0x0000002a, + /*0a95*/ 0x00000015, + /*0a96*/ 0x00000015, + /*0a97*/ 0x0000002a, + /*0a98*/ 0x00000033, + /*0a99*/ 0x0000000c, + /*0a9a*/ 0x0000000c, + /*0a9b*/ 0x00000033, + /*0a9c*/ 0x00000000, + /*0a9d*/ 0x00000000, + /*0a9e*/ 0x00000000, + /*0a9f*/ 0x0002c06e, + /*0aa0*/ 0x02c002c0, + /*0aa1*/ 0x02c002c0, + /*0aa2*/ 0x000002c0, + /*0aa3*/ 0x42080010, + /*0aa4*/ 0x00000003 +}; + +static const uint32_t DDR_PHY_ADR_G_REGSET_M3[DDR_PHY_ADR_G_REGSET_NUM_M3] = { + /*0b80*/ 0x00000001, + /*0b81*/ 0x00000000, + /*0b82*/ 0x00000005, + /*0b83*/ 0x04000f00, + /*0b84*/ 0x00020080, + /*0b85*/ 0x00020055, + /*0b86*/ 0x00000000, + /*0b87*/ 0x00000000, + /*0b88*/ 0x00000000, + /*0b89*/ 0x00000050, + /*0b8a*/ 0x00000000, + /*0b8b*/ 0x01010100, + /*0b8c*/ 0x00000600, + /*0b8d*/ 0x50640000, + /*0b8e*/ 0x01421142, + /*0b8f*/ 0x00000142, + /*0b90*/ 0x00000000, + /*0b91*/ 0x000f1600, + /*0b92*/ 0x0f160f16, + /*0b93*/ 0x0f160f16, + /*0b94*/ 0x00000003, + /*0b95*/ 0x0002c000, + /*0b96*/ 0x02c002c0, + /*0b97*/ 0x000002c0, + /*0b98*/ 0x03421342, + /*0b99*/ 0x00000342, + /*0b9a*/ 0x00000000, + /*0b9b*/ 0x00000000, + /*0b9c*/ 0x05020000, + /*0b9d*/ 0x00000000, + /*0b9e*/ 0x00027f6e, + /*0b9f*/ 0x047f027f, + /*0ba0*/ 0x00027f6e, + /*0ba1*/ 0x00047f6e, + /*0ba2*/ 0x0003554f, + /*0ba3*/ 0x0001554f, + /*0ba4*/ 0x0001554f, + /*0ba5*/ 0x0001554f, + /*0ba6*/ 0x0001554f, + /*0ba7*/ 0x00003fee, + /*0ba8*/ 0x0001554f, + /*0ba9*/ 0x00003fee, + /*0baa*/ 0x0001554f, + /*0bab*/ 0x00027f6e, + /*0bac*/ 0x0001554f, + /*0bad*/ 0x00000000, + /*0bae*/ 0x00000000, + /*0baf*/ 0x00000000, + /*0bb0*/ 0x65000000, + /*0bb1*/ 0x00000000, + /*0bb2*/ 0x00000000, + /*0bb3*/ 0x00000201, + /*0bb4*/ 0x00000000, + /*0bb5*/ 0x00000000, + /*0bb6*/ 0x00000000, + /*0bb7*/ 0x00000000, + /*0bb8*/ 0x00000000, + /*0bb9*/ 0x00000000, + /*0bba*/ 0x00000000, + /*0bbb*/ 0x00000000, + /*0bbc*/ 0x06e40000, + /*0bbd*/ 0x00000000, + /*0bbe*/ 0x00000000, + /*0bbf*/ 0x00010000 +}; + +static const uint32_t DDR_PI_REGSET_M3[DDR_PI_REGSET_NUM_M3] = { + /*0200*/ 0x00000b00, + /*0201*/ 0x00000100, + /*0202*/ 0x00000000, + /*0203*/ 0x0000ffff, + /*0204*/ 0x00000000, + /*0205*/ 0x0000ffff, + /*0206*/ 0x00000000, + /*0207*/ 0x304cffff, + /*0208*/ 0x00000200, + /*0209*/ 0x00000200, + /*020a*/ 0x00000200, + /*020b*/ 0x00000200, + /*020c*/ 0x0000304c, + /*020d*/ 0x00000200, + /*020e*/ 0x00000200, + /*020f*/ 0x00000200, + /*0210*/ 0x00000200, + /*0211*/ 0x0000304c, + /*0212*/ 0x00000200, + /*0213*/ 0x00000200, + /*0214*/ 0x00000200, + /*0215*/ 0x00000200, + /*0216*/ 0x00010000, + /*0217*/ 0x00000003, + /*0218*/ 0x01000001, + /*0219*/ 0x00000000, + /*021a*/ 0x00000000, + /*021b*/ 0x00000000, + /*021c*/ 0x00000000, + /*021d*/ 0x00000000, + /*021e*/ 0x00000000, + /*021f*/ 0x00000000, + /*0220*/ 0x00000000, + /*0221*/ 0x00000000, + /*0222*/ 0x00000000, + /*0223*/ 0x00000000, + /*0224*/ 0x00000000, + /*0225*/ 0x00000000, + /*0226*/ 0x00000000, + /*0227*/ 0x00000000, + /*0228*/ 0x00000000, + /*0229*/ 0x0f000101, + /*022a*/ 0x08492d25, + /*022b*/ 0x0e0c0004, + /*022c*/ 0x000e5000, + /*022d*/ 0x00000250, + /*022e*/ 0x00460003, + /*022f*/ 0x182600cf, + /*0230*/ 0x182600cf, + /*0231*/ 0x00000005, + /*0232*/ 0x00000000, + /*0233*/ 0x00000000, + /*0234*/ 0x00000000, + /*0235*/ 0x00000000, + /*0236*/ 0x00000000, + /*0237*/ 0x00000000, + /*0238*/ 0x00000000, + /*0239*/ 0x01000000, + /*023a*/ 0x00040404, + /*023b*/ 0x01280a00, + /*023c*/ 0x00000000, + /*023d*/ 0x000f0000, + /*023e*/ 0x00001803, + /*023f*/ 0x00000000, + /*0240*/ 0x00000000, + /*0241*/ 0x00060002, + /*0242*/ 0x00010001, + /*0243*/ 0x01000101, + /*0244*/ 0x04020201, + /*0245*/ 0x00080804, + /*0246*/ 0x00000000, + /*0247*/ 0x08030000, + /*0248*/ 0x15150408, + /*0249*/ 0x00000000, + /*024a*/ 0x00000000, + /*024b*/ 0x00000000, + /*024c*/ 0x000f0f00, + /*024d*/ 0x0000001e, + /*024e*/ 0x00000000, + /*024f*/ 0x01000300, + /*0250*/ 0x00000000, + /*0251*/ 0x00000000, + /*0252*/ 0x01000000, + /*0253*/ 0x00010101, + /*0254*/ 0x000e0e0e, + /*0255*/ 0x000c0c0c, + /*0256*/ 0x02060601, + /*0257*/ 0x00000000, + /*0258*/ 0x00000003, + /*0259*/ 0x00181703, + /*025a*/ 0x00280006, + /*025b*/ 0x00280016, + /*025c*/ 0x00000016, + /*025d*/ 0x00000000, + /*025e*/ 0x00000000, + /*025f*/ 0x00000000, + /*0260*/ 0x140a0000, + /*0261*/ 0x0005010a, + /*0262*/ 0x03018d03, + /*0263*/ 0x000a018d, + /*0264*/ 0x00060100, + /*0265*/ 0x01000006, + /*0266*/ 0x018e018e, + /*0267*/ 0x018e0100, + /*0268*/ 0x1111018e, + /*0269*/ 0x10010204, + /*026a*/ 0x09090650, + /*026b*/ 0x20110202, + /*026c*/ 0x00201000, + /*026d*/ 0x00201000, + /*026e*/ 0x04041000, + /*026f*/ 0x18020100, + /*0270*/ 0x00010118, + /*0271*/ 0x004b004a, + /*0272*/ 0x050f0000, + /*0273*/ 0x0c01021e, + /*0274*/ 0x34000000, + /*0275*/ 0x00000000, + /*0276*/ 0x00000000, + /*0277*/ 0x00000000, + /*0278*/ 0x0000d400, + /*0279*/ 0x0031002e, + /*027a*/ 0x00111136, + /*027b*/ 0x002e00d4, + /*027c*/ 0x11360031, + /*027d*/ 0x0000d411, + /*027e*/ 0x0031002e, + /*027f*/ 0x00111136, + /*0280*/ 0x002e00d4, + /*0281*/ 0x11360031, + /*0282*/ 0x0000d411, + /*0283*/ 0x0031002e, + /*0284*/ 0x00111136, + /*0285*/ 0x002e00d4, + /*0286*/ 0x11360031, + /*0287*/ 0x00d40011, + /*0288*/ 0x0031002e, + /*0289*/ 0x00111136, + /*028a*/ 0x002e00d4, + /*028b*/ 0x11360031, + /*028c*/ 0x0000d411, + /*028d*/ 0x0031002e, + /*028e*/ 0x00111136, + /*028f*/ 0x002e00d4, + /*0290*/ 0x11360031, + /*0291*/ 0x0000d411, + /*0292*/ 0x0031002e, + /*0293*/ 0x00111136, + /*0294*/ 0x002e00d4, + /*0295*/ 0x11360031, + /*0296*/ 0x02000011, + /*0297*/ 0x018d018d, + /*0298*/ 0x0c08018d, + /*0299*/ 0x1f121d22, + /*029a*/ 0x4301b344, + /*029b*/ 0x10172006, + /*029c*/ 0x1d220c10, + /*029d*/ 0x00001f12, + /*029e*/ 0x4301b344, + /*029f*/ 0x10172006, + /*02a0*/ 0x1d220c10, + /*02a1*/ 0x00001f12, + /*02a2*/ 0x4301b344, + /*02a3*/ 0x10172006, + /*02a4*/ 0x02000210, + /*02a5*/ 0x02000200, + /*02a6*/ 0x02000200, + /*02a7*/ 0x02000200, + /*02a8*/ 0x02000200, + /*02a9*/ 0x00000000, + /*02aa*/ 0x00000000, + /*02ab*/ 0x00000000, + /*02ac*/ 0x00000000, + /*02ad*/ 0x00000000, + /*02ae*/ 0x00000000, + /*02af*/ 0x00000000, + /*02b0*/ 0x00000000, + /*02b1*/ 0x00000000, + /*02b2*/ 0x00000000, + /*02b3*/ 0x00000000, + /*02b4*/ 0x00000000, + /*02b5*/ 0x00000400, + /*02b6*/ 0x15141312, + /*02b7*/ 0x11100f0e, + /*02b8*/ 0x080b0c0d, + /*02b9*/ 0x05040a09, + /*02ba*/ 0x01000706, + /*02bb*/ 0x00000302, + /*02bc*/ 0x01030201, + /*02bd*/ 0x00304c00, + /*02be*/ 0x0001e2f8, + /*02bf*/ 0x0000304c, + /*02c0*/ 0x0001e2f8, + /*02c1*/ 0x0000304c, + /*02c2*/ 0x0001e2f8, + /*02c3*/ 0x08000000, + /*02c4*/ 0x00000100, + /*02c5*/ 0x00000000, + /*02c6*/ 0x00000000, + /*02c7*/ 0x00000000, + /*02c8*/ 0x00000000, + /*02c9*/ 0x00000002 +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h new file mode 100644 index 0000000..fb3032d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h @@ -0,0 +1,587 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define DDR_PHY_SLICE_REGSET_OFS_M3N 0x0800 +#define DDR_PHY_ADR_V_REGSET_OFS_M3N 0x0a00 +#define DDR_PHY_ADR_I_REGSET_OFS_M3N 0x0a80 +#define DDR_PHY_ADR_G_REGSET_OFS_M3N 0x0b80 +#define DDR_PI_REGSET_OFS_M3N 0x0200 + +#define DDR_PHY_SLICE_REGSET_SIZE_M3N 0x80 +#define DDR_PHY_ADR_V_REGSET_SIZE_M3N 0x80 +#define DDR_PHY_ADR_I_REGSET_SIZE_M3N 0x80 +#define DDR_PHY_ADR_G_REGSET_SIZE_M3N 0x80 +#define DDR_PI_REGSET_SIZE_M3N 0x100 + +#define DDR_PHY_SLICE_REGSET_NUM_M3N 101 +#define DDR_PHY_ADR_V_REGSET_NUM_M3N 37 +#define DDR_PHY_ADR_I_REGSET_NUM_M3N 37 +#define DDR_PHY_ADR_G_REGSET_NUM_M3N 87 +#define DDR_PI_REGSET_NUM_M3N 286 + +static const uint32_t DDR_PHY_SLICE_REGSET_M3N[DDR_PHY_SLICE_REGSET_NUM_M3N] = { + /*0800*/ 0x76543210, + /*0801*/ 0x0004f008, + /*0802*/ 0x00020200, + /*0803*/ 0x00000000, + /*0804*/ 0x00000000, + /*0805*/ 0x00010000, + /*0806*/ 0x036e6e0e, + /*0807*/ 0x026e6e0e, + /*0808*/ 0x00000103, + /*0809*/ 0x00040001, + /*080a*/ 0x00000103, + /*080b*/ 0x00000001, + /*080c*/ 0x00000000, + /*080d*/ 0x00000000, + /*080e*/ 0x00000100, + /*080f*/ 0x001800c0, + /*0810*/ 0x020100b0, + /*0811*/ 0x00030020, + /*0812*/ 0x00000000, + /*0813*/ 0x00000000, + /*0814*/ 0x0000aaaa, + /*0815*/ 0x00005555, + /*0816*/ 0x0000b5b5, + /*0817*/ 0x00004a4a, + /*0818*/ 0x00000000, + /*0819*/ 0x09000000, + /*081a*/ 0x04080000, + /*081b*/ 0x08040000, + /*081c*/ 0x00000004, + /*081d*/ 0x00800710, + /*081e*/ 0x000f000c, + /*081f*/ 0x00000100, + /*0820*/ 0x55aa55aa, + /*0821*/ 0x33cc33cc, + /*0822*/ 0x0ff00ff0, + /*0823*/ 0x0f0ff0f0, + /*0824*/ 0x00018e38, + /*0825*/ 0x00000000, + /*0826*/ 0x00000000, + /*0827*/ 0x00000000, + /*0828*/ 0x00000000, + /*0829*/ 0x00000000, + /*082a*/ 0x00000000, + /*082b*/ 0x00000000, + /*082c*/ 0x00000000, + /*082d*/ 0x00000000, + /*082e*/ 0x00000000, + /*082f*/ 0x00000000, + /*0830*/ 0x00000000, + /*0831*/ 0x00000000, + /*0832*/ 0x00000000, + /*0833*/ 0x00000000, + /*0834*/ 0x00000000, + /*0835*/ 0x00000000, + /*0836*/ 0x00000000, + /*0837*/ 0x00000000, + /*0838*/ 0x00000000, + /*0839*/ 0x00000000, + /*083a*/ 0x00000104, + /*083b*/ 0x00082020, + /*083c*/ 0x08200820, + /*083d*/ 0x08200820, + /*083e*/ 0x08200820, + /*083f*/ 0x08200820, + /*0840*/ 0x08200820, + /*0841*/ 0x00000000, + /*0842*/ 0x00000000, + /*0843*/ 0x03000300, + /*0844*/ 0x03000300, + /*0845*/ 0x03000300, + /*0846*/ 0x03000300, + /*0847*/ 0x00000300, + /*0848*/ 0x00000000, + /*0849*/ 0x00000000, + /*084a*/ 0x00000000, + /*084b*/ 0x00000000, + /*084c*/ 0x00000000, + /*084d*/ 0x00a000a0, + /*084e*/ 0x00a000a0, + /*084f*/ 0x00a000a0, + /*0850*/ 0x00a000a0, + /*0851*/ 0x00a000a0, + /*0852*/ 0x00a000a0, + /*0853*/ 0x00a000a0, + /*0854*/ 0x00a000a0, + /*0855*/ 0x00a000a0, + /*0856*/ 0x01040119, + /*0857*/ 0x00000200, + /*0858*/ 0x01000000, + /*0859*/ 0x00000200, + /*085a*/ 0x00000004, + /*085b*/ 0x4041a151, + /*085c*/ 0x0141a0a0, + /*085d*/ 0x0000c0c0, + /*085e*/ 0x0e0c000e, + /*085f*/ 0x10001000, + /*0860*/ 0x0c073e42, + /*0861*/ 0x000f0c28, + /*0862*/ 0x00e00140, + /*0863*/ 0x000c0020, + /*0864*/ 0x00000203 +}; + +static const uint32_t DDR_PHY_ADR_V_REGSET_M3N[DDR_PHY_ADR_V_REGSET_NUM_M3N] = { + /*0a00*/ 0x00000000, + /*0a01*/ 0x00000000, + /*0a02*/ 0x00000000, + /*0a03*/ 0x00000000, + /*0a04*/ 0x00000000, + /*0a05*/ 0x00000000, + /*0a06*/ 0x00000000, + /*0a07*/ 0x01000000, + /*0a08*/ 0x00020000, + /*0a09*/ 0x00000000, + /*0a0a*/ 0x00000000, + /*0a0b*/ 0x00000000, + /*0a0c*/ 0x00400000, + /*0a0d*/ 0x00000080, + /*0a0e*/ 0x00dcba98, + /*0a0f*/ 0x03000000, + /*0a10*/ 0x00000200, + /*0a11*/ 0x00000000, + /*0a12*/ 0x00000000, + /*0a13*/ 0x00000000, + /*0a14*/ 0x0000002a, + /*0a15*/ 0x00000015, + /*0a16*/ 0x00000015, + /*0a17*/ 0x0000002a, + /*0a18*/ 0x00000033, + /*0a19*/ 0x0000000c, + /*0a1a*/ 0x0000000c, + /*0a1b*/ 0x00000033, + /*0a1c*/ 0x0a418820, + /*0a1d*/ 0x003f0000, + /*0a1e*/ 0x0000013f, + /*0a1f*/ 0x0002c06e, + /*0a20*/ 0x02c002c0, + /*0a21*/ 0x02c002c0, + /*0a22*/ 0x000002c0, + /*0a23*/ 0x42080010, + /*0a24*/ 0x0000033e +}; + +static const uint32_t DDR_PHY_ADR_I_REGSET_M3N[DDR_PHY_ADR_I_REGSET_NUM_M3N] = { + /*0a80*/ 0x00000000, + /*0a81*/ 0x00000000, + /*0a82*/ 0x00000000, + /*0a83*/ 0x00000000, + /*0a84*/ 0x00000000, + /*0a85*/ 0x00000000, + /*0a86*/ 0x00000000, + /*0a87*/ 0x01000000, + /*0a88*/ 0x00020000, + /*0a89*/ 0x00000000, + /*0a8a*/ 0x00000000, + /*0a8b*/ 0x00000000, + /*0a8c*/ 0x00400000, + /*0a8d*/ 0x00000080, + /*0a8e*/ 0x00000000, + /*0a8f*/ 0x03000000, + /*0a90*/ 0x00000200, + /*0a91*/ 0x00000000, + /*0a92*/ 0x00000000, + /*0a93*/ 0x00000000, + /*0a94*/ 0x0000002a, + /*0a95*/ 0x00000015, + /*0a96*/ 0x00000015, + /*0a97*/ 0x0000002a, + /*0a98*/ 0x00000033, + /*0a99*/ 0x0000000c, + /*0a9a*/ 0x0000000c, + /*0a9b*/ 0x00000033, + /*0a9c*/ 0x00000000, + /*0a9d*/ 0x00000000, + /*0a9e*/ 0x00000000, + /*0a9f*/ 0x0002c06e, + /*0aa0*/ 0x02c002c0, + /*0aa1*/ 0x02c002c0, + /*0aa2*/ 0x000002c0, + /*0aa3*/ 0x42080010, + /*0aa4*/ 0x0000033e +}; + +static const uint32_t DDR_PHY_ADR_G_REGSET_M3N[DDR_PHY_ADR_G_REGSET_NUM_M3N] = { + /*0b80*/ 0x00000000, + /*0b81*/ 0x00000100, + /*0b82*/ 0x00000000, + /*0b83*/ 0x00050000, + /*0b84*/ 0x00000000, + /*0b85*/ 0x0004000f, + /*0b86*/ 0x00280080, + /*0b87*/ 0x02005502, + /*0b88*/ 0x00000000, + /*0b89*/ 0x00000000, + /*0b8a*/ 0x00000000, + /*0b8b*/ 0x00000050, + /*0b8c*/ 0x00000000, + /*0b8d*/ 0x01010100, + /*0b8e*/ 0x00010000, + /*0b8f*/ 0x00000000, + /*0b90*/ 0x00000101, + /*0b91*/ 0x00000000, + /*0b92*/ 0x00000000, + /*0b93*/ 0x00000000, + /*0b94*/ 0x00000000, + /*0b95*/ 0x00005064, + /*0b96*/ 0x01421142, + /*0b97*/ 0x00000142, + /*0b98*/ 0x00000000, + /*0b99*/ 0x000f1600, + /*0b9a*/ 0x0f160f16, + /*0b9b*/ 0x0f160f16, + /*0b9c*/ 0x00000003, + /*0b9d*/ 0x0002c000, + /*0b9e*/ 0x02c002c0, + /*0b9f*/ 0x000002c0, + /*0ba0*/ 0x08040201, + /*0ba1*/ 0x03421342, + /*0ba2*/ 0x00000342, + /*0ba3*/ 0x00000000, + /*0ba4*/ 0x00000000, + /*0ba5*/ 0x05030000, + /*0ba6*/ 0x00010700, + /*0ba7*/ 0x00000014, + /*0ba8*/ 0x00027f6e, + /*0ba9*/ 0x047f027f, + /*0baa*/ 0x00027f6e, + /*0bab*/ 0x00047f6e, + /*0bac*/ 0x0003554f, + /*0bad*/ 0x0001554f, + /*0bae*/ 0x0001554f, + /*0baf*/ 0x0001554f, + /*0bb0*/ 0x0001554f, + /*0bb1*/ 0x00003fee, + /*0bb2*/ 0x0001554f, + /*0bb3*/ 0x00003fee, + /*0bb4*/ 0x0001554f, + /*0bb5*/ 0x00027f6e, + /*0bb6*/ 0x0001554f, + /*0bb7*/ 0x00004011, + /*0bb8*/ 0x00004410, + /*0bb9*/ 0x00000000, + /*0bba*/ 0x00000000, + /*0bbb*/ 0x00000000, + /*0bbc*/ 0x00000265, + /*0bbd*/ 0x00000000, + /*0bbe*/ 0x00040401, + /*0bbf*/ 0x00000000, + /*0bc0*/ 0x03000000, + /*0bc1*/ 0x00000020, + /*0bc2*/ 0x00000000, + /*0bc3*/ 0x00000000, + /*0bc4*/ 0x04102006, + /*0bc5*/ 0x00041020, + /*0bc6*/ 0x01c98c98, + /*0bc7*/ 0x00400000, + /*0bc8*/ 0x00000000, + /*0bc9*/ 0x0001ffff, + /*0bca*/ 0x00000000, + /*0bcb*/ 0x00000000, + /*0bcc*/ 0x00000001, + /*0bcd*/ 0x00000000, + /*0bce*/ 0x00000000, + /*0bcf*/ 0x00000000, + /*0bd0*/ 0x76543210, + /*0bd1*/ 0x06010198, + /*0bd2*/ 0x00000000, + /*0bd3*/ 0x00000000, + /*0bd4*/ 0x04070000, + /*0bd5*/ 0x00000001, + /*0bd6*/ 0x00000f00 +}; + +static const uint32_t DDR_PI_REGSET_M3N[DDR_PI_REGSET_NUM_M3N] = { + /*0200*/ 0x00000b00, + /*0201*/ 0x00000101, + /*0202*/ 0x01640000, + /*0203*/ 0x00000014, + /*0204*/ 0x00000014, + /*0205*/ 0x00000014, + /*0206*/ 0x00000014, + /*0207*/ 0x00000000, + /*0208*/ 0x00000000, + /*0209*/ 0x0000ffff, + /*020a*/ 0x00000000, + /*020b*/ 0x0000ffff, + /*020c*/ 0x00000000, + /*020d*/ 0x0000ffff, + /*020e*/ 0x0000304c, + /*020f*/ 0x00000200, + /*0210*/ 0x00000200, + /*0211*/ 0x00000200, + /*0212*/ 0x00000200, + /*0213*/ 0x0000304c, + /*0214*/ 0x00000200, + /*0215*/ 0x00000200, + /*0216*/ 0x00000200, + /*0217*/ 0x00000200, + /*0218*/ 0x0000304c, + /*0219*/ 0x00000200, + /*021a*/ 0x00000200, + /*021b*/ 0x00000200, + /*021c*/ 0x00000200, + /*021d*/ 0x00010000, + /*021e*/ 0x00000003, + /*021f*/ 0x01000001, + /*0220*/ 0x00000000, + /*0221*/ 0x00000000, + /*0222*/ 0x00000000, + /*0223*/ 0x00000000, + /*0224*/ 0x00000000, + /*0225*/ 0x00000000, + /*0226*/ 0x00000000, + /*0227*/ 0x00000000, + /*0228*/ 0x00000000, + /*0229*/ 0x00000000, + /*022a*/ 0x00000000, + /*022b*/ 0x00000000, + /*022c*/ 0x00000000, + /*022d*/ 0x00000000, + /*022e*/ 0x00000000, + /*022f*/ 0x00000000, + /*0230*/ 0x0f000101, + /*0231*/ 0x084d3129, + /*0232*/ 0x0e0c0004, + /*0233*/ 0x000e5000, + /*0234*/ 0x01000250, + /*0235*/ 0x00000003, + /*0236*/ 0x00000046, + /*0237*/ 0x000000cf, + /*0238*/ 0x00001826, + /*0239*/ 0x000000cf, + /*023a*/ 0x00001826, + /*023b*/ 0x00000000, + /*023c*/ 0x00000000, + /*023d*/ 0x00000000, + /*023e*/ 0x00000000, + /*023f*/ 0x00000000, + /*0240*/ 0x00000000, + /*0241*/ 0x00000000, + /*0242*/ 0x00000000, + /*0243*/ 0x00000000, + /*0244*/ 0x00000000, + /*0245*/ 0x01000000, + /*0246*/ 0x00040404, + /*0247*/ 0x01280a00, + /*0248*/ 0x00000001, + /*0249*/ 0x00000000, + /*024a*/ 0x03000f00, + /*024b*/ 0x00200020, + /*024c*/ 0x00000020, + /*024d*/ 0x00000000, + /*024e*/ 0x00000000, + /*024f*/ 0x00010002, + /*0250*/ 0x01010001, + /*0251*/ 0x02010100, + /*0252*/ 0x08040402, + /*0253*/ 0x00000008, + /*0254*/ 0x00000000, + /*0255*/ 0x04080803, + /*0256*/ 0x00001515, + /*0257*/ 0x00000000, + /*0258*/ 0x000000aa, + /*0259*/ 0x00000055, + /*025a*/ 0x000000b5, + /*025b*/ 0x0000004a, + /*025c*/ 0x00000056, + /*025d*/ 0x000000a9, + /*025e*/ 0x000000a9, + /*025f*/ 0x000000b5, + /*0260*/ 0x00000000, + /*0261*/ 0x00000000, + /*0262*/ 0x0f000000, + /*0263*/ 0x00001e0f, + /*0264*/ 0x000007d0, + /*0265*/ 0x01000300, + /*0266*/ 0x00000100, + /*0267*/ 0x00000000, + /*0268*/ 0x00000000, + /*0269*/ 0x01000000, + /*026a*/ 0x00010101, + /*026b*/ 0x000e0e0e, + /*026c*/ 0x000c0c0c, + /*026d*/ 0x01060601, + /*026e*/ 0x04041717, + /*026f*/ 0x00000004, + /*0270*/ 0x00000300, + /*0271*/ 0x17030000, + /*0272*/ 0x00060018, + /*0273*/ 0x00160028, + /*0274*/ 0x00160028, + /*0275*/ 0x00000000, + /*0276*/ 0x00000000, + /*0277*/ 0x00000000, + /*0278*/ 0x0a000000, + /*0279*/ 0x00010a14, + /*027a*/ 0x00030005, + /*027b*/ 0x0003018d, + /*027c*/ 0x000a018d, + /*027d*/ 0x00060100, + /*027e*/ 0x01000006, + /*027f*/ 0x018e018e, + /*0280*/ 0x018e0100, + /*0281*/ 0x1e1a018e, + /*0282*/ 0x1e1a1e1a, + /*0283*/ 0x01010204, + /*0284*/ 0x06501001, + /*0285*/ 0x090d0a07, + /*0286*/ 0x090d0a07, + /*0287*/ 0x0811180f, + /*0288*/ 0x00ff1102, + /*0289*/ 0x00ff1000, + /*028a*/ 0x00ff1000, + /*028b*/ 0x04041000, + /*028c*/ 0x18020100, + /*028d*/ 0x01010018, + /*028e*/ 0x005f005f, + /*028f*/ 0x005f005f, + /*0290*/ 0x050f0000, + /*0291*/ 0x051e051e, + /*0292*/ 0x0c01021e, + /*0293*/ 0x00000c0c, + /*0294*/ 0x00003400, + /*0295*/ 0x00000000, + /*0296*/ 0x00000000, + /*0297*/ 0x00000000, + /*0298*/ 0x00000000, + /*0299*/ 0x002e00d4, + /*029a*/ 0x11360031, + /*029b*/ 0x00d41611, + /*029c*/ 0x0031002e, + /*029d*/ 0x16111136, + /*029e*/ 0x002e00d4, + /*029f*/ 0x11360031, + /*02a0*/ 0x00001611, + /*02a1*/ 0x002e00d4, + /*02a2*/ 0x11360031, + /*02a3*/ 0x00d41611, + /*02a4*/ 0x0031002e, + /*02a5*/ 0x16111136, + /*02a6*/ 0x002e00d4, + /*02a7*/ 0x11360031, + /*02a8*/ 0x00001611, + /*02a9*/ 0x002e00d4, + /*02aa*/ 0x11360031, + /*02ab*/ 0x00d41611, + /*02ac*/ 0x0031002e, + /*02ad*/ 0x16111136, + /*02ae*/ 0x002e00d4, + /*02af*/ 0x11360031, + /*02b0*/ 0x00001611, + /*02b1*/ 0x002e00d4, + /*02b2*/ 0x11360031, + /*02b3*/ 0x00d41611, + /*02b4*/ 0x0031002e, + /*02b5*/ 0x16111136, + /*02b6*/ 0x002e00d4, + /*02b7*/ 0x11360031, + /*02b8*/ 0x00001611, + /*02b9*/ 0x00018d00, + /*02ba*/ 0x018d018d, + /*02bb*/ 0x1d220c08, + /*02bc*/ 0x00001f12, + /*02bd*/ 0x4301b344, + /*02be*/ 0x17032006, + /*02bf*/ 0x220c1010, + /*02c0*/ 0x001f121d, + /*02c1*/ 0x4301b344, + /*02c2*/ 0x17062006, + /*02c3*/ 0x220c1010, + /*02c4*/ 0x001f121d, + /*02c5*/ 0x4301b344, + /*02c6*/ 0x17182006, + /*02c7*/ 0x00021010, + /*02c8*/ 0x00020002, + /*02c9*/ 0x00020002, + /*02ca*/ 0x00020002, + /*02cb*/ 0x00020002, + /*02cc*/ 0x00000002, + /*02cd*/ 0x00000000, + /*02ce*/ 0x00000000, + /*02cf*/ 0x00000000, + /*02d0*/ 0x00000000, + /*02d1*/ 0x00000000, + /*02d2*/ 0x00000000, + /*02d3*/ 0x00000000, + /*02d4*/ 0x00000000, + /*02d5*/ 0x00000000, + /*02d6*/ 0x00000000, + /*02d7*/ 0x00000000, + /*02d8*/ 0x00000000, + /*02d9*/ 0x00000400, + /*02da*/ 0x15141312, + /*02db*/ 0x11100f0e, + /*02dc*/ 0x080b0c0d, + /*02dd*/ 0x05040a09, + /*02de*/ 0x01000706, + /*02df*/ 0x00000302, + /*02e0*/ 0x01030201, + /*02e1*/ 0x00304c08, + /*02e2*/ 0x0001e2f8, + /*02e3*/ 0x0000304c, + /*02e4*/ 0x0001e2f8, + /*02e5*/ 0x0000304c, + /*02e6*/ 0x0001e2f8, + /*02e7*/ 0x08000000, + /*02e8*/ 0x00000100, + /*02e9*/ 0x00000000, + /*02ea*/ 0x00000000, + /*02eb*/ 0x00000000, + /*02ec*/ 0x00000000, + /*02ed*/ 0x00010000, + /*02ee*/ 0x00000000, + /*02ef*/ 0x00000000, + /*02f0*/ 0x00000000, + /*02f1*/ 0x00000000, + /*02f2*/ 0x00000000, + /*02f3*/ 0x00000000, + /*02f4*/ 0x00000000, + /*02f5*/ 0x00000000, + /*02f6*/ 0x00000000, + /*02f7*/ 0x00000000, + /*02f8*/ 0x00000000, + /*02f9*/ 0x00000000, + /*02fa*/ 0x00000000, + /*02fb*/ 0x00000000, + /*02fc*/ 0x00000000, + /*02fd*/ 0x00000000, + /*02fe*/ 0x00000000, + /*02ff*/ 0x00000000, + /*0300*/ 0x00000000, + /*0301*/ 0x00000000, + /*0302*/ 0x00000000, + /*0303*/ 0x00000000, + /*0304*/ 0x00000000, + /*0305*/ 0x00000000, + /*0306*/ 0x00000000, + /*0307*/ 0x00000000, + /*0308*/ 0x00000000, + /*0309*/ 0x00000000, + /*030a*/ 0x00000000, + /*030b*/ 0x00000000, + /*030c*/ 0x00000000, + /*030d*/ 0x00000000, + /*030e*/ 0x00000000, + /*030f*/ 0x00050002, + /*0310*/ 0x015c0057, + /*0311*/ 0x01000100, + /*0312*/ 0x01020001, + /*0313*/ 0x00010300, + /*0314*/ 0x05000104, + /*0315*/ 0x01060001, + /*0316*/ 0x00010700, + /*0317*/ 0x00000000, + /*0318*/ 0x00000000, + /*0319*/ 0x00000001, + /*031a*/ 0x00000000, + /*031b*/ 0x00000000, + /*031c*/ 0x00000000, + /*031d*/ 0x20080101 +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c b/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c new file mode 100644 index 0000000..ab8eabb --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "dram_sub_func.h" +#include "rcar_def.h" + +#if RCAR_SYSTEM_SUSPEND +/* Local defines */ +#define DRAM_BACKUP_GPIO_USE 0 +#include "iic_dvfs.h" +#if PMIC_ROHM_BD9571 +#define PMIC_SLAVE_ADDR 0x30U +#define PMIC_BKUP_MODE_CNT 0x20U +#define PMIC_QLLM_CNT 0x27U +#define BIT_BKUP_CTRL_OUT BIT(4) +#define BIT_QLLM_DDR0_EN BIT(0) +#define BIT_QLLM_DDR1_EN BIT(1) +#endif + +#define GPIO_BKUP_REQB_SHIFT_SALVATOR 9U /* GP1_9 (BKUP_REQB) */ +#define GPIO_BKUP_TRG_SHIFT_SALVATOR 8U /* GP1_8 (BKUP_TRG) */ +#define GPIO_BKUP_REQB_SHIFT_EBISU 14U /* GP6_14(BKUP_REQB) */ +#define GPIO_BKUP_TRG_SHIFT_EBISU 13U /* GP6_13(BKUP_TRG) */ +#define GPIO_BKUP_REQB_SHIFT_CONDOR 1U /* GP3_1 (BKUP_REQB) */ +#define GPIO_BKUP_TRG_SHIFT_CONDOR 0U /* GP3_0 (BKUP_TRG) */ + +#define DRAM_BKUP_TRG_LOOP_CNT 1000U +#endif + +void rcar_dram_get_boot_status(uint32_t *status) +{ +#if RCAR_SYSTEM_SUSPEND + uint32_t reg_data; + uint32_t product; + uint32_t shift; + uint32_t gpio; + + product = mmio_read_32(PRR) & PRR_PRODUCT_MASK; + if (product == PRR_PRODUCT_V3H) { + shift = GPIO_BKUP_TRG_SHIFT_CONDOR; + gpio = GPIO_INDT3; + } else if (product == PRR_PRODUCT_E3) { + shift = GPIO_BKUP_TRG_SHIFT_EBISU; + gpio = GPIO_INDT6; + } else { + shift = GPIO_BKUP_TRG_SHIFT_SALVATOR; + gpio = GPIO_INDT1; + } + + reg_data = mmio_read_32(gpio); + if (reg_data & BIT(shift)) + *status = DRAM_BOOT_STATUS_WARM; + else + *status = DRAM_BOOT_STATUS_COLD; +#else /* RCAR_SYSTEM_SUSPEND */ + *status = DRAM_BOOT_STATUS_COLD; +#endif /* RCAR_SYSTEM_SUSPEND */ +} + +int32_t rcar_dram_update_boot_status(uint32_t status) +{ + int32_t ret = 0; +#if RCAR_SYSTEM_SUSPEND + uint32_t reg_data; +#if PMIC_ROHM_BD9571 +#if DRAM_BACKUP_GPIO_USE == 0 + uint8_t bkup_mode_cnt = 0U; +#else + uint32_t reqb, outd; +#endif + uint8_t qllm_cnt = 0U; + int32_t i2c_dvfs_ret = -1; +#endif + uint32_t loop_count; + uint32_t product; + uint32_t trg; + uint32_t gpio; + + product = mmio_read_32(PRR) & PRR_PRODUCT_MASK; + if (product == PRR_PRODUCT_V3H) { +#if DRAM_BACKUP_GPIO_USE == 1 + reqb = GPIO_BKUP_REQB_SHIFT_CONDOR; + outd = GPIO_OUTDT3; +#endif + trg = GPIO_BKUP_TRG_SHIFT_CONDOR; + gpio = GPIO_INDT3; + } else if (product == PRR_PRODUCT_E3) { +#if DRAM_BACKUP_GPIO_USE == 1 + reqb = GPIO_BKUP_REQB_SHIFT_EBISU; + outd = GPIO_OUTDT6; +#endif + trg = GPIO_BKUP_TRG_SHIFT_EBISU; + gpio = GPIO_INDT6; + } else { +#if DRAM_BACKUP_GPIO_USE == 1 + reqb = GPIO_BKUP_REQB_SHIFT_SALVATOR; + outd = GPIO_OUTDT1; +#endif + trg = GPIO_BKUP_TRG_SHIFT_SALVATOR; + gpio = GPIO_INDT1; + } + + if (status == DRAM_BOOT_STATUS_WARM) { +#if DRAM_BACKUP_GPIO_USE == 1 + mmio_setbits_32(outd, BIT(reqb)); +#else +#if PMIC_ROHM_BD9571 + /* Set BKUP_CRTL_OUT=High (BKUP mode cnt register) */ + i2c_dvfs_ret = rcar_iic_dvfs_receive(PMIC_SLAVE_ADDR, + PMIC_BKUP_MODE_CNT, + &bkup_mode_cnt); + if (i2c_dvfs_ret) { + ERROR("BKUP mode cnt READ ERROR.\n"); + ret = DRAM_UPDATE_STATUS_ERR; + } else { + bkup_mode_cnt &= (uint8_t)~BIT_BKUP_CTRL_OUT; + i2c_dvfs_ret = rcar_iic_dvfs_send(PMIC_SLAVE_ADDR, + PMIC_BKUP_MODE_CNT, + bkup_mode_cnt); + if (i2c_dvfs_ret) { + ERROR("BKUP mode cnt WRITE ERROR. value = %d\n", + bkup_mode_cnt); + ret = DRAM_UPDATE_STATUS_ERR; + } + } +#endif /* PMIC_ROHM_BD9571 */ +#endif /* DRAM_BACKUP_GPIO_USE == 1 */ + /* Wait BKUP_TRG=Low */ + loop_count = DRAM_BKUP_TRG_LOOP_CNT; + while (loop_count > 0) { + reg_data = mmio_read_32(gpio); + if (!(reg_data & BIT(trg))) + break; + loop_count--; + } + + if (!loop_count) { + ERROR("\nWarm booting...\n" + " The potential of BKUP_TRG did not switch to Low.\n" + " If you expect the operation of cold boot,\n" + " check the board configuration (ex, Dip-SW) and/or the H/W failure.\n"); + ret = DRAM_UPDATE_STATUS_ERR; + } + } +#if PMIC_ROHM_BD9571 + if (!ret) { + qllm_cnt = BIT_QLLM_DDR0_EN | BIT_QLLM_DDR1_EN; + i2c_dvfs_ret = rcar_iic_dvfs_send(PMIC_SLAVE_ADDR, + PMIC_QLLM_CNT, + qllm_cnt); + if (i2c_dvfs_ret) { + ERROR("QLLM cnt WRITE ERROR. value = %d\n", qllm_cnt); + ret = DRAM_UPDATE_STATUS_ERR; + } + } +#endif +#endif + return ret; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h b/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h new file mode 100644 index 0000000..69c4d86 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRAM_SUB_FUNC_H +#define DRAM_SUB_FUNC_H + +#define DRAM_UPDATE_STATUS_ERR -1 +#define DRAM_BOOT_STATUS_COLD 0 +#define DRAM_BOOT_STATUS_WARM 1 + +int32_t rcar_dram_update_boot_status(uint32_t status); +void rcar_dram_get_boot_status(uint32_t *status); + +#endif /* DRAM_SUB_FUNC_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr_regs.h b/arm-trusted-firmware/drivers/renesas/common/ddr_regs.h new file mode 100644 index 0000000..ba26c69 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr_regs.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOOT_INIT_DRAM_REGDEF_H_ +#define BOOT_INIT_DRAM_REGDEF_H_ + +/* DBSC registers */ +#define DBSC_DBSYSCONF0 0xE6790000U +#define DBSC_DBSYSCONF1 0xE6790004U +#define DBSC_DBPHYCONF0 0xE6790010U +#define DBSC_DBKIND 0xE6790020U +#define DBSC_DBMEMCONF(ch, cs) (0xE6790030U + 0x10U * (ch) + 0x04U * (cs)) +#define DBSC_DBMEMCONF_0_0 0xE6790030U +#define DBSC_DBMEMCONF_0_1 0xE6790034U +#define DBSC_DBMEMCONF_0_2 0xE6790038U +#define DBSC_DBMEMCONF_0_3 0xE679003CU +#define DBSC_DBMEMCONF_1_2 0xE6790048U +#define DBSC_DBMEMCONF_1_3 0xE679004CU +#define DBSC_DBMEMCONF_1_0 0xE6790040U +#define DBSC_DBMEMCONF_1_1 0xE6790044U +#define DBSC_DBMEMCONF_2_0 0xE6790050U +#define DBSC_DBMEMCONF_2_1 0xE6790054U +#define DBSC_DBMEMCONF_2_2 0xE6790058U +#define DBSC_DBMEMCONF_2_3 0xE679005CU +#define DBSC_DBMEMCONF_3_0 0xE6790060U +#define DBSC_DBMEMCONF_3_1 0xE6790064U +#define DBSC_DBMEMCONF_3_2 0xE6790068U +#define DBSC_DBMEMCONF_3_3 0xE679006CU +#define DBSC_DBSYSCNT0 0xE6790100U +#define DBSC_DBSVCR1 0xE6790104U +#define DBSC_DBSTATE0 0xE6790108U +#define DBSC_DBSTATE1 0xE679010CU +#define DBSC_DBINTEN 0xE6790180U +#define DBSC_DBINTSTAT0 0xE6790184U +#define DBSC_DBACEN 0xE6790200U +#define DBSC_DBRFEN 0xE6790204U +#define DBSC_DBCMD 0xE6790208U +#define DBSC_DBWAIT 0xE6790210U +#define DBSC_DBSYSCTRL0 0xE6790280U +#define DBSC_DBTR(x) (0xE6790300U + 0x04U * (x)) +#define DBSC_DBTR0 0xE6790300U +#define DBSC_DBTR1 0xE6790304U +#define DBSC_DBTR2 0xE6790308U +#define DBSC_DBTR3 0xE679030CU +#define DBSC_DBTR4 0xE6790310U +#define DBSC_DBTR5 0xE6790314U +#define DBSC_DBTR6 0xE6790318U +#define DBSC_DBTR7 0xE679031CU +#define DBSC_DBTR8 0xE6790320U +#define DBSC_DBTR9 0xE6790324U +#define DBSC_DBTR10 0xE6790328U +#define DBSC_DBTR11 0xE679032CU +#define DBSC_DBTR12 0xE6790330U +#define DBSC_DBTR13 0xE6790334U +#define DBSC_DBTR14 0xE6790338U +#define DBSC_DBTR15 0xE679033CU +#define DBSC_DBTR16 0xE6790340U +#define DBSC_DBTR17 0xE6790344U +#define DBSC_DBTR18 0xE6790348U +#define DBSC_DBTR19 0xE679034CU +#define DBSC_DBTR20 0xE6790350U +#define DBSC_DBTR21 0xE6790354U +#define DBSC_DBTR22 0xE6790358U +#define DBSC_DBTR23 0xE679035CU +#define DBSC_DBTR24 0xE6790360U +#define DBSC_DBTR25 0xE6790364U +#define DBSC_DBTR26 0xE6790368U +#define DBSC_DBBL 0xE6790400U +#define DBSC_DBRFCNF1 0xE6790414U +#define DBSC_DBRFCNF2 0xE6790418U +#define DBSC_DBTSPCNF 0xE6790420U +#define DBSC_DBCALCNF 0xE6790424U +#define DBSC_DBRNK(x) (0xE6790430U + 0x04U * (x)) +#define DBSC_DBRNK2 0xE6790438U +#define DBSC_DBRNK3 0xE679043CU +#define DBSC_DBRNK4 0xE6790440U +#define DBSC_DBRNK5 0xE6790444U +#define DBSC_DBPDNCNF 0xE6790450U +#define DBSC_DBODT(x) (0xE6790460U + 0x04U * (x)) +#define DBSC_DBODT0 0xE6790460U +#define DBSC_DBODT1 0xE6790464U +#define DBSC_DBODT2 0xE6790468U +#define DBSC_DBODT3 0xE679046CU +#define DBSC_DBODT4 0xE6790470U +#define DBSC_DBODT5 0xE6790474U +#define DBSC_DBODT6 0xE6790478U +#define DBSC_DBODT7 0xE679047CU +#define DBSC_DBADJ0 0xE6790500U +#define DBSC_DBDBICNT 0xE6790518U +#define DBSC_DBDFIPMSTRCNF 0xE6790520U +#define DBSC_DBDFICUPDCNF 0xE679052CU +#define DBSC_DBDFISTAT(ch) (0xE6790600U + 0x40U * (ch)) +#define DBSC_DBDFISTAT_0 0xE6790600U +#define DBSC_DBDFISTAT_1 0xE6790640U +#define DBSC_DBDFISTAT_2 0xE6790680U +#define DBSC_DBDFISTAT_3 0xE67906C0U +#define DBSC_DBDFICNT(ch) (0xE6790604U + 0x40U * (ch)) +#define DBSC_DBDFICNT_0 0xE6790604U +#define DBSC_DBDFICNT_1 0xE6790644U +#define DBSC_DBDFICNT_2 0xE6790684U +#define DBSC_DBDFICNT_3 0xE67906C4U +#define DBSC_DBPDCNT0(ch) (0xE6790610U + 0x40U * (ch)) +#define DBSC_DBPDCNT0_0 0xE6790610U +#define DBSC_DBPDCNT0_1 0xE6790650U +#define DBSC_DBPDCNT0_2 0xE6790690U +#define DBSC_DBPDCNT0_3 0xE67906D0U +#define DBSC_DBPDCNT1(ch) (0xE6790614U + 0x40U * (ch)) +#define DBSC_DBPDCNT1_0 0xE6790614U +#define DBSC_DBPDCNT1_1 0xE6790654U +#define DBSC_DBPDCNT1_2 0xE6790694U +#define DBSC_DBPDCNT1_3 0xE67906D4U +#define DBSC_DBPDCNT2(ch) (0xE6790618U + 0x40U * (ch)) +#define DBSC_DBPDCNT2_0 0xE6790618U +#define DBSC_DBPDCNT2_1 0xE6790658U +#define DBSC_DBPDCNT2_2 0xE6790698U +#define DBSC_DBPDCNT2_3 0xE67906D8U +#define DBSC_DBPDCNT3(ch) (0xE679061CU + 0x40U * (ch)) +#define DBSC_DBPDCNT3_0 0xE679061CU +#define DBSC_DBPDCNT3_1 0xE679065CU +#define DBSC_DBPDCNT3_2 0xE679069CU +#define DBSC_DBPDCNT3_3 0xE67906DCU +#define DBSC_DBPDLK(ch) (0xE6790620U + 0x40U * (ch)) +#define DBSC_DBPDLK_0 0xE6790620U +#define DBSC_DBPDLK_1 0xE6790660U +#define DBSC_DBPDLK_2 0xE67906a0U +#define DBSC_DBPDLK_3 0xE67906e0U +#define DBSC_DBPDRGA(ch) (0xE6790624U + 0x40U * (ch)) +#define DBSC_DBPDRGD(ch) (0xE6790628U + 0x40U * (ch)) +#define DBSC_DBPDRGA_0 0xE6790624U +#define DBSC_DBPDRGD_0 0xE6790628U +#define DBSC_DBPDRGA_1 0xE6790664U +#define DBSC_DBPDRGD_1 0xE6790668U +#define DBSC_DBPDRGA_2 0xE67906A4U +#define DBSC_DBPDRGD_2 0xE67906A8U +#define DBSC_DBPDRGA_3 0xE67906E4U +#define DBSC_DBPDRGD_3 0xE67906E8U +#define DBSC_DBPDSTAT(ch) (0xE6790630U + 0x40U * (ch)) +#define DBSC_DBPDSTAT_0 0xE6790630U +#define DBSC_DBPDSTAT_1 0xE6790670U +#define DBSC_DBPDSTAT_2 0xE67906B0U +#define DBSC_DBPDSTAT_3 0xE67906F0U +#define DBSC_DBBUS0CNF0 0xE6790800U +#define DBSC_DBBUS0CNF1 0xE6790804U +#define DBSC_DBCAM0CNF1 0xE6790904U +#define DBSC_DBCAM0CNF2 0xE6790908U +#define DBSC_DBCAM0CNF3 0xE679090CU +#define DBSC_DBBSWAP 0xE67909F0U +#define DBSC_DBBCAMDIS 0xE67909FCU +#define DBSC_DBSCHCNT0 0xE6791000U +#define DBSC_DBSCHCNT1 0xE6791004U +#define DBSC_DBSCHSZ0 0xE6791010U +#define DBSC_DBSCHRW0 0xE6791020U +#define DBSC_DBSCHRW1 0xE6791024U +#define DBSC_DBSCHQOS_0(x) (0xE6791030U + 0x10U * (x)) +#define DBSC_DBSCHQOS_1(x) (0xE6791034U + 0x10U * (x)) +#define DBSC_DBSCHQOS_2(x) (0xE6791038U + 0x10U * (x)) +#define DBSC_DBSCHQOS_3(x) (0xE679103CU + 0x10U * (x)) +#define DBSC_DBSCHQOS00 0xE6791030U +#define DBSC_DBSCHQOS01 0xE6791034U +#define DBSC_DBSCHQOS02 0xE6791038U +#define DBSC_DBSCHQOS03 0xE679103CU +#define DBSC_DBSCHQOS10 0xE6791040U +#define DBSC_DBSCHQOS11 0xE6791044U +#define DBSC_DBSCHQOS12 0xE6791048U +#define DBSC_DBSCHQOS13 0xE679104CU +#define DBSC_DBSCHQOS20 0xE6791050U +#define DBSC_DBSCHQOS21 0xE6791054U +#define DBSC_DBSCHQOS22 0xE6791058U +#define DBSC_DBSCHQOS23 0xE679105CU +#define DBSC_DBSCHQOS30 0xE6791060U +#define DBSC_DBSCHQOS31 0xE6791064U +#define DBSC_DBSCHQOS32 0xE6791068U +#define DBSC_DBSCHQOS33 0xE679106CU +#define DBSC_DBSCHQOS40 0xE6791070U +#define DBSC_DBSCHQOS41 0xE6791074U +#define DBSC_DBSCHQOS42 0xE6791078U +#define DBSC_DBSCHQOS43 0xE679107CU +#define DBSC_DBSCHQOS50 0xE6791080U +#define DBSC_DBSCHQOS51 0xE6791084U +#define DBSC_DBSCHQOS52 0xE6791088U +#define DBSC_DBSCHQOS53 0xE679108CU +#define DBSC_DBSCHQOS60 0xE6791090U +#define DBSC_DBSCHQOS61 0xE6791094U +#define DBSC_DBSCHQOS62 0xE6791098U +#define DBSC_DBSCHQOS63 0xE679109CU +#define DBSC_DBSCHQOS70 0xE67910A0U +#define DBSC_DBSCHQOS71 0xE67910A4U +#define DBSC_DBSCHQOS72 0xE67910A8U +#define DBSC_DBSCHQOS73 0xE67910ACU +#define DBSC_DBSCHQOS80 0xE67910B0U +#define DBSC_DBSCHQOS81 0xE67910B4U +#define DBSC_DBSCHQOS82 0xE67910B8U +#define DBSC_DBSCHQOS83 0xE67910BCU +#define DBSC_DBSCHQOS90 0xE67910C0U +#define DBSC_DBSCHQOS91 0xE67910C4U +#define DBSC_DBSCHQOS92 0xE67910C8U +#define DBSC_DBSCHQOS93 0xE67910CCU +#define DBSC_DBSCHQOS100 0xE67910D0U +#define DBSC_DBSCHQOS101 0xE67910D4U +#define DBSC_DBSCHQOS102 0xE67910D8U +#define DBSC_DBSCHQOS103 0xE67910DCU +#define DBSC_DBSCHQOS110 0xE67910E0U +#define DBSC_DBSCHQOS111 0xE67910E4U +#define DBSC_DBSCHQOS112 0xE67910E8U +#define DBSC_DBSCHQOS113 0xE67910ECU +#define DBSC_DBSCHQOS120 0xE67910F0U +#define DBSC_DBSCHQOS121 0xE67910F4U +#define DBSC_DBSCHQOS122 0xE67910F8U +#define DBSC_DBSCHQOS123 0xE67910FCU +#define DBSC_DBSCHQOS130 0xE6791100U +#define DBSC_DBSCHQOS131 0xE6791104U +#define DBSC_DBSCHQOS132 0xE6791108U +#define DBSC_DBSCHQOS133 0xE679110CU +#define DBSC_DBSCHQOS140 0xE6791110U +#define DBSC_DBSCHQOS141 0xE6791114U +#define DBSC_DBSCHQOS142 0xE6791118U +#define DBSC_DBSCHQOS143 0xE679111CU +#define DBSC_DBSCHQOS150 0xE6791120U +#define DBSC_DBSCHQOS151 0xE6791124U +#define DBSC_DBSCHQOS152 0xE6791128U +#define DBSC_DBSCHQOS153 0xE679112CU +#define DBSC_DBSCTR0 0xE6791700U +#define DBSC_DBSCTR1 0xE6791708U +#define DBSC_DBSCHRW2 0xE679170CU +#define DBSC_SCFCTST01(x) (0xE6791700U + 0x08U * (x)) +#define DBSC_SCFCTST0 0xE6791700U +#define DBSC_SCFCTST1 0xE6791708U +#define DBSC_SCFCTST2 0xE679170CU +#define DBSC_DBMRRDR(chab) (0xE6791800U + 0x04U * (chab)) +#define DBSC_DBMRRDR_0 0xE6791800U +#define DBSC_DBMRRDR_1 0xE6791804U +#define DBSC_DBMRRDR_2 0xE6791808U +#define DBSC_DBMRRDR_3 0xE679180CU +#define DBSC_DBMRRDR_4 0xE6791810U +#define DBSC_DBMRRDR_5 0xE6791814U +#define DBSC_DBMRRDR_6 0xE6791818U +#define DBSC_DBMRRDR_7 0xE679181CU +#define DBSC_DBMEMSWAPCONF0 0xE6792000U + +/* CPG registers */ +#define CPG_BASE 0xE6150000U +#define CPG_FRQCRB (CPG_BASE + 0x0004U) +#define CPG_PLLECR (CPG_BASE + 0x00D0U) +#define CPG_MSTPSR5 (CPG_BASE + 0x003CU) +#define CPG_SRCR4 (CPG_BASE + 0x00BCU) +#define CPG_PLL3CR (CPG_BASE + 0x00DCU) +#define CPG_ZB3CKCR (CPG_BASE + 0x0380U) +#define CPG_FRQCRD (CPG_BASE + 0x00E4U) +#define CPG_SMSTPCR5 (CPG_BASE + 0x0144U) +#define CPG_CPGWPR (CPG_BASE + 0x0900U) +#define CPG_SRSTCLR4 (CPG_BASE + 0x0950U) + +#endif /* BOOT_INIT_DRAM_REGDEF_H_*/ diff --git a/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c b/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c new file mode 100644 index 0000000..a5e2a69 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "micro_delay.h" + +#define RCAR_CONV_MICROSEC 1000000U + +void +#if IMAGE_BL31 + __attribute__ ((section(".system_ram"))) +#endif + rcar_micro_delay(uint64_t micro_sec) +{ + uint64_t freq; + uint64_t base_count; + uint64_t get_count; + uint64_t wait_time = 0U; + + freq = read_cntfrq_el0(); + base_count = read_cntpct_el0(); + while (micro_sec > wait_time) { + get_count = read_cntpct_el0(); + wait_time = ((get_count - base_count) * RCAR_CONV_MICROSEC) / freq; + } +} diff --git a/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h b/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h new file mode 100644 index 0000000..37b71f8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MICRO_DELAY_H +#define MICRO_DELAY_H + +#ifndef __ASSEMBLER__ +#include +void rcar_micro_delay(uint64_t micro_sec); +#endif + +#endif /* MICRO_DELAY_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c b/arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c new file mode 100644 index 0000000..44ee985 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" + +/* DMA CHANNEL setting (0/16/32) */ +#if RCAR_LSI == RCAR_V3M +#define DMA_CH 16 +#else +#define DMA_CH 0 +#endif + +#if (DMA_CH == 0) +#define SYS_DMAC_BIT ((uint32_t)1U << 19U) +#define DMA_BASE (0xE6700000U) +#elif (DMA_CH == 16) +#define SYS_DMAC_BIT ((uint32_t)1U << 18U) +#define DMA_BASE (0xE7300000U) +#elif (DMA_CH == 32) +#define SYS_DMAC_BIT ((uint32_t)1U << 17U) +#define DMA_BASE (0xE7320000U) +#else +#define SYS_DMAC_BIT ((uint32_t)1U << 19U) +#define DMA_BASE (0xE6700000U) +#endif + +/* DMA operation */ +#define DMA_DMAOR (DMA_BASE + 0x0060U) +/* DMA secure control */ +#define DMA_DMASEC (DMA_BASE + 0x0030U) +/* DMA channel clear */ +#define DMA_DMACHCLR (DMA_BASE + 0x0080U) +/* DMA source address */ +#define DMA_DMASAR (DMA_BASE + 0x8000U) +/* DMA destination address */ +#define DMA_DMADAR (DMA_BASE + 0x8004U) +/* DMA transfer count */ +#define DMA_DMATCR (DMA_BASE + 0x8008U) +/* DMA channel control */ +#define DMA_DMACHCR (DMA_BASE + 0x800CU) +/* DMA fixed destination address */ +#define DMA_DMAFIXDAR (DMA_BASE + 0x8014U) + +#define DMA_USE_CHANNEL (0x00000001U) +#define DMAOR_INITIAL (0x0301U) +#define DMACHCLR_CH_ALL (0x0000FFFFU) +#define DMAFIXDAR_32BIT_SHIFT (32U) +#define DMAFIXDAR_DAR_MASK (0x000000FFU) +#define DMADAR_BOUNDARY_ADDR (0x100000000ULL) +#define DMATCR_CNT_SHIFT (6U) +#define DMATCR_MAX (0x00FFFFFFU) +#define DMACHCR_TRN_MODE (0x00105409U) +#define DMACHCR_DE_BIT (0x00000001U) +#define DMACHCR_TE_BIT (0x00000002U) +#define DMACHCR_CHE_BIT (0x80000000U) + +#define DMA_SIZE_UNIT FLASH_TRANS_SIZE_UNIT +#define DMA_FRACTION_MASK (0xFFU) +#define DMA_DST_LIMIT (0x10000000000ULL) + +/* transfer length limit */ +#define DMA_LENGTH_LIMIT ((DMATCR_MAX * (1U << DMATCR_CNT_SHIFT)) \ + & ~DMA_FRACTION_MASK) + +static void dma_enable(void) +{ + mstpcr_write(CPG_SMSTPCR2, CPG_MSTPSR2, SYS_DMAC_BIT); +} + +static void dma_setup(void) +{ + mmio_write_16(DMA_DMAOR, 0); + mmio_write_32(DMA_DMACHCLR, DMACHCLR_CH_ALL); +} + +static void dma_start(uintptr_t dst, uint32_t src, uint32_t len) +{ + mmio_write_16(DMA_DMAOR, DMAOR_INITIAL); + mmio_write_32(DMA_DMAFIXDAR, (dst >> DMAFIXDAR_32BIT_SHIFT) & + DMAFIXDAR_DAR_MASK); + mmio_write_32(DMA_DMADAR, dst & UINT32_MAX); + mmio_write_32(DMA_DMASAR, src); + mmio_write_32(DMA_DMATCR, len >> DMATCR_CNT_SHIFT); + mmio_write_32(DMA_DMASEC, DMA_USE_CHANNEL); + mmio_write_32(DMA_DMACHCR, DMACHCR_TRN_MODE); +} + +static void dma_end(void) +{ + while ((mmio_read_32(DMA_DMACHCR) & DMACHCR_TE_BIT) == 0) { + if ((mmio_read_32(DMA_DMACHCR) & DMACHCR_CHE_BIT) != 0U) { + ERROR("BL2: DMA - Channel Address Error\n"); + panic(); + break; + } + } + /* DMA transfer Disable */ + mmio_clrbits_32(DMA_DMACHCR, DMACHCR_DE_BIT); + while ((mmio_read_32(DMA_DMACHCR) & DMACHCR_DE_BIT) != 0) + ; + + mmio_write_32(DMA_DMASEC, 0); + mmio_write_16(DMA_DMAOR, 0); + mmio_write_32(DMA_DMACHCLR, DMA_USE_CHANNEL); +} + +void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len) +{ + uint32_t dma_len = len; + + if (len & DMA_FRACTION_MASK) + dma_len = (len + DMA_SIZE_UNIT) & ~DMA_FRACTION_MASK; + + if (!dma_len || dma_len > DMA_LENGTH_LIMIT) { + ERROR("BL2: DMA - size invalid, length (0x%x)\n", dma_len); + panic(); + } + + if (src & DMA_FRACTION_MASK) { + ERROR("BL2: DMA - src address invalid (0x%x), len=(0x%x)\n", + src, dma_len); + panic(); + } + + if ((dst & UINT32_MAX) + dma_len > DMADAR_BOUNDARY_ADDR || + (dst + dma_len > DMA_DST_LIMIT) || + (dst & DMA_FRACTION_MASK)) { + ERROR("BL2: DMA - dest address invalid (0x%lx), len=(0x%x)\n", + dst, dma_len); + panic(); + } + + dma_start(dst, src, dma_len); + dma_end(); +} + +void rcar_dma_init(void) +{ + dma_enable(); + dma_setup(); +} diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c new file mode 100644 index 0000000..d255bff --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c @@ -0,0 +1,493 @@ +/* + * 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" +#include "micro_delay.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)) { + rcar_micro_delay(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; + } + + rcar_micro_delay(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/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h new file mode 100644 index 0000000..16b6b8a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/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/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h new file mode 100644 index 0000000..178c795 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/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 rcar_emmc_init(void); +EMMC_ERROR_CODE emmc_terminate(void); +EMMC_ERROR_CODE rcar_emmc_memcard_power(uint8_t mode); +EMMC_ERROR_CODE rcar_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/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h new file mode 100644 index 0000000..0a85517 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/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/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c new file mode 100644 index 0000000..c0ec600 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015-2021, 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" +#include "rcar_private.h" +#include "cpg_registers.h" + +st_mmc_base mmc_drv_obj; + +EMMC_ERROR_CODE rcar_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; + uint32_t dataL; + + /* + * MMC power off + * the power supply of eMMC device is always turning on. + * RST_n : Hi --> Low level. + */ + result = rcar_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 */ + + dataL = mmio_read_32(SMSTPCR3); + if ((dataL & CPG_MSTP_MMC) == 0U) { + dataL |= (CPG_MSTP_MMC); + mmio_write_32(CPG_CPGWPR, (~dataL)); + mmio_write_32(SMSTPCR3, dataL); + } + + return result; +} + +static EMMC_ERROR_CODE emmc_dev_init(void) +{ + /* Enable clock supply to eMMC. */ + mstpcr_write(SMSTPCR3, CPG_MSTPSR3, CPG_MSTP_MMC); + + /* Set SD clock */ + mmio_write_32(CPG_CPGWPR, ~((uint32_t) (BIT9 | BIT0))); /* SD phy 200MHz */ + + /* Stop SDnH clock & SDn=200MHz */ + mmio_write_32(CPG_SDxCKCR, (BIT9 | BIT0)); + + /* 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 rcar_emmc_init(void) +{ + EMMC_ERROR_CODE result; + + result = emmc_reset_controller(); + if (result == EMMC_SUCCESS) { + emmc_driver_config(); + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c new file mode 100644 index 0000000..092fdfb --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c @@ -0,0 +1,217 @@ +/* + * 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" +#include "rcar_def.h" + +static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual); + +uint32_t emmc_interrupt(void) +{ + EMMC_ERROR_CODE result; + uint32_t prr_data; + uint32_t cut_ver; + uint32_t end_bit; + + prr_data = mmio_read_32((uintptr_t) RCAR_PRR); + cut_ver = prr_data & PRR_CUT_MASK; + if ((prr_data & PRR_PRODUCT_MASK) == PRR_PRODUCT_H3) { + if (cut_ver == PRR_PRODUCT_10) { + end_bit = BIT17; + } else if (cut_ver == PRR_PRODUCT_11) { + end_bit = BIT17; + } else { + end_bit = BIT20; + } + } else if ((prr_data & PRR_PRODUCT_MASK) == PRR_PRODUCT_M3) { + if (cut_ver == PRR_PRODUCT_10) { + end_bit = BIT17; + } else { + end_bit = BIT20; + } + } else { + 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/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c new file mode 100644 index 0000000..e04afd4 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c @@ -0,0 +1,686 @@ +/* + * 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" +#include "micro_delay.h" +#include "rcar_def.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) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if (reg == PRR_PRODUCT_M3_CUT10) { + 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); + } else if ((reg == PRR_PRODUCT_H3_CUT20) + || (reg == PRR_PRODUCT_M3_CUT11)) { + mmc_drv_obj.boot_partition_en = mmc_drv_obj.partition_access; + } else { + if ((mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION) != + 0U) { + mmc_drv_obj.boot_partition_en = PARTITION_ID_BOOT_2; + } else { + mmc_drv_obj.boot_partition_en = PARTITION_ID_BOOT_1; + } + } +} + +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; + } + + rcar_micro_delay(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; + } + + rcar_micro_delay(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 */ + } + rcar_micro_delay(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) +{ + uint32_t reg; + EMMC_ERROR_CODE result; + + reg = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if ((reg == PRR_PRODUCT_H3_CUT20) || (reg == PRR_PRODUCT_M3_CUT11)) { + 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 rcar_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/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c new file mode 100644 index 0000000..96e73ca --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c @@ -0,0 +1,130 @@ +/* + * 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 RCAR_BL2_DCACHE == 1 + if (transfer_mode == HAL_MEMCARD_NOT_DMA) { + flush_dcache_range((uint64_t) buff_address_virtual, + ((size_t) count << EMMC_SECTOR_SIZE_SHIFT)); + } +#endif /* RCAR_BL2_DCACHE == 1 */ + + /* 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/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h new file mode 100644 index 0000000..67d285d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2015-2021, 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 */ + +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2M) || (RCAR_LSI == RZ_G2H) || (RCAR_LSI == RZ_G2N) +#define USE_MMC_CH (MMC_CH1) /* R-Car E3 or RZ/G2{H,M,N} */ +#else /* RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2{H,M,N} */ +#define USE_MMC_CH (MMC_CH0) /* R-Car H3/M3/M3N */ +#endif /* RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2{H,M,N} */ + +#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) + +#if USE_MMC_CH == MMC_CH0 +#define CPG_SDxCKCR (CPG_SD2CKCR) /* SDHI2/MMC0 */ +#else /* USE_MMC_CH == MMC_CH0 */ +#define CPG_SDxCKCR (CPG_SD3CKCR) /* SDHI3/MMC1 */ +#endif /* USE_MMC_CH == MMC_CH0 */ + +/* Boot Status register */ +#define MFISBTSTSR (0xE6260604U) + +#define MFISBTSTSR_BOOT_PARTITION (0x00000010U) + +/* eMMC registers */ +#define MMC0_SD_BASE (0xEE140000U) +#define MMC1_SD_BASE (0xEE160000U) + +#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 + * 200MHz * 1/x = output clock + */ +#define MMC_CLK_OFF 0UL /* Clock output is disabled */ +#define MMC_400KHZ 512UL /* 200MHz * 1/512 = 390 KHz */ +#define MMC_20MHZ 16UL /* 200MHz * 1/16 = 12.5 MHz Normal speed mode */ +#define MMC_26MHZ 8UL /* 200MHz * 1/8 = 25 MHz HS mode 26Mhz */ +#define MMC_52MHZ 4UL /* 200MHz * 1/4 = 50 MHz HS mode 52Mhz */ +#define MMC_100MHZ 2UL /* 200MHz * 1/2 = 100 MHz */ +#define MMC_200MHZ 1UL /* 200MHz * 1/1 = 200 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 + +/* SYSC Registers */ +#if USE_MMC_CH == MMC_CH0 +#define CPG_MSTP_MMC (BIT12) /* SDHI2/MMC0 */ +#else /* USE_MMC_CH == MMC_CH0 */ +#define CPG_MSTP_MMC (BIT11) /* SDHI3/MMC1 */ +#endif /* USE_MMC_CH == MMC_CH0 */ + +#endif /* EMMC_REGISTERS_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h new file mode 100644 index 0000000..087c6e9 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/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/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c new file mode 100644 index 0000000..2e88abc --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/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/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c b/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c new file mode 100644 index 0000000..bf80697 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "cpg_registers.h" +#include "iic_dvfs.h" +#include "rcar_def.h" +#include "rcar_private.h" + +#define DVFS_RETRY_MAX (2U) + +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_0 (0x07U) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_1 (0x09U) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_2 (0x0BU) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_3 (0x0EU) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_E (0x15U) + +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_0 (0x01U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_1 (0x02U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_2 (0x03U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_3 (0x05U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_E (0x07U) + +#define CPG_BIT_SMSTPCR9_DVFS (0x04000000U) + +#define IIC_DVFS_REG_BASE (0xE60B0000U) +#define IIC_DVFS_REG_ICDR (IIC_DVFS_REG_BASE + 0x0000U) +#define IIC_DVFS_REG_ICCR (IIC_DVFS_REG_BASE + 0x0004U) +#define IIC_DVFS_REG_ICSR (IIC_DVFS_REG_BASE + 0x0008U) +#define IIC_DVFS_REG_ICIC (IIC_DVFS_REG_BASE + 0x000CU) +#define IIC_DVFS_REG_ICCL (IIC_DVFS_REG_BASE + 0x0010U) +#define IIC_DVFS_REG_ICCH (IIC_DVFS_REG_BASE + 0x0014U) + +#define IIC_DVFS_BIT_ICSR_BUSY (0x10U) +#define IIC_DVFS_BIT_ICSR_AL (0x08U) +#define IIC_DVFS_BIT_ICSR_TACK (0x04U) +#define IIC_DVFS_BIT_ICSR_WAIT (0x02U) +#define IIC_DVFS_BIT_ICSR_DTE (0x01U) + +#define IIC_DVFS_BIT_ICCR_ENABLE (0x80U) +#define IIC_DVFS_SET_ICCR_START (0x94U) +#define IIC_DVFS_SET_ICCR_STOP (0x90U) +#define IIC_DVFS_SET_ICCR_RETRANSMISSION (0x94U) +#define IIC_DVFS_SET_ICCR_CHANGE (0x81U) +#define IIC_DVFS_SET_ICCR_STOP_READ (0xC0U) + +#define IIC_DVFS_BIT_ICIC_TACKE (0x04U) +#define IIC_DVFS_BIT_ICIC_WAITE (0x02U) +#define IIC_DVFS_BIT_ICIC_DTEE (0x01U) + +#define DVFS_READ_MODE (0x01U) +#define DVFS_WRITE_MODE (0x00U) + +#define IIC_DVFS_SET_DUMMY (0x52U) +#define IIC_DVFS_SET_BUSY_LOOP (500000000U) + +enum dvfs_state_t { + DVFS_START = 0, + DVFS_STOP, + DVFS_RETRANSMIT, + DVFS_READ, + DVFS_STOP_READ, + DVFS_SET_SLAVE_READ, + DVFS_SET_SLAVE, + DVFS_WRITE_ADDR, + DVFS_WRITE_DATA, + DVFS_CHANGE_SEND_TO_RECEIVE, + DVFS_DONE, +}; + +#define DVFS_PROCESS (1) +#define DVFS_COMPLETE (0) +#define DVFS_ERROR (-1) + +#if IMAGE_BL31 +#define IIC_DVFS_FUNC(__name, ...) \ +static int32_t __attribute__ ((section(".system_ram"))) \ +dvfs_ ##__name(__VA_ARGS__) + +#define RCAR_DVFS_API(__name, ...) \ +int32_t __attribute__ ((section(".system_ram"))) \ +rcar_iic_dvfs_ ##__name(__VA_ARGS__) + +#else +#define IIC_DVFS_FUNC(__name, ...) \ +static int32_t dvfs_ ##__name(__VA_ARGS__) + +#define RCAR_DVFS_API(__name, ...) \ +int32_t rcar_iic_dvfs_ ##__name(__VA_ARGS__) +#endif + +IIC_DVFS_FUNC(check_error, enum dvfs_state_t *state, uint32_t *err, uint8_t mode) +{ + uint8_t icsr_al = 0U, icsr_tack = 0U; + uint8_t reg, stop; + uint32_t i = 0U; + + stop = mode == DVFS_READ_MODE ? IIC_DVFS_SET_ICCR_STOP_READ : + IIC_DVFS_SET_ICCR_STOP; + + reg = mmio_read_8(IIC_DVFS_REG_ICSR); + icsr_al = (reg & IIC_DVFS_BIT_ICSR_AL) == IIC_DVFS_BIT_ICSR_AL; + icsr_tack = (reg & IIC_DVFS_BIT_ICSR_TACK) == IIC_DVFS_BIT_ICSR_TACK; + + if (icsr_al == 0U && icsr_tack == 0U) { + return DVFS_PROCESS; + } + + if (icsr_al) { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_AL; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + if (*state == DVFS_SET_SLAVE) { + mmio_write_8(IIC_DVFS_REG_ICDR, IIC_DVFS_SET_DUMMY); + } + + do { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & + IIC_DVFS_BIT_ICSR_WAIT; + } while (reg == 0U); + + mmio_write_8(IIC_DVFS_REG_ICCR, stop); + + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + i = 0U; + do { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & + IIC_DVFS_BIT_ICSR_BUSY; + if (reg == 0U) { + break; + } + + if (i++ > IIC_DVFS_SET_BUSY_LOOP) { + panic(); + } + + } while (true); + + mmio_write_8(IIC_DVFS_REG_ICCR, 0x00U); + + (*err)++; + if (*err > DVFS_RETRY_MAX) { + return DVFS_ERROR; + } + + *state = DVFS_START; + + return DVFS_PROCESS; + + } + + /* icsr_tack */ + mmio_write_8(IIC_DVFS_REG_ICCR, stop); + + reg = mmio_read_8(IIC_DVFS_REG_ICIC); + reg &= ~(IIC_DVFS_BIT_ICIC_WAITE | IIC_DVFS_BIT_ICIC_DTEE); + mmio_write_8(IIC_DVFS_REG_ICIC, reg); + + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_TACK; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + i = 0U; + while ((mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_BUSY) != 0U) { + if (i++ > IIC_DVFS_SET_BUSY_LOOP) { + panic(); + } + } + + mmio_write_8(IIC_DVFS_REG_ICCR, 0U); + (*err)++; + + if (*err > DVFS_RETRY_MAX) { + return DVFS_ERROR; + } + + *state = DVFS_START; + + return DVFS_PROCESS; +} + +IIC_DVFS_FUNC(start, enum dvfs_state_t *state) +{ + uint8_t iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_E; + uint8_t icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_E; + int32_t result = DVFS_PROCESS; + uint32_t reg, lsi_product; + uint8_t mode; + + mode = mmio_read_8(IIC_DVFS_REG_ICCR) | IIC_DVFS_BIT_ICCR_ENABLE; + mmio_write_8(IIC_DVFS_REG_ICCR, mode); + + lsi_product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + if (lsi_product == PRR_PRODUCT_E3) { + goto start; + } + + reg = mmio_read_32(RCAR_MODEMR) & CHECK_MD13_MD14; + switch (reg) { + case MD14_MD13_TYPE_0: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_0; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_0; + break; + case MD14_MD13_TYPE_1: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_1; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_1; + break; + case MD14_MD13_TYPE_2: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_2; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_2; + break; + default: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_3; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_3; + break; + } +start: + mmio_write_8(IIC_DVFS_REG_ICCL, iccl); + mmio_write_8(IIC_DVFS_REG_ICCH, icch); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) + | IIC_DVFS_BIT_ICIC_TACKE + | IIC_DVFS_BIT_ICIC_WAITE | IIC_DVFS_BIT_ICIC_DTEE; + + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_START); + + *state = DVFS_SET_SLAVE; + + return result; +} + +IIC_DVFS_FUNC(set_slave, enum dvfs_state_t *state, uint32_t *err, uint8_t slave) +{ + uint8_t mode; + int32_t result; + uint8_t address; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + address = slave << 1; + mmio_write_8(IIC_DVFS_REG_ICDR, address); + + *state = DVFS_WRITE_ADDR; + + return result; +} + +IIC_DVFS_FUNC(write_addr, enum dvfs_state_t *state, uint32_t *err, uint8_t reg_addr) +{ + uint8_t mode; + int32_t result; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_addr); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_WRITE_DATA; + + return result; +} + +IIC_DVFS_FUNC(write_data, enum dvfs_state_t *state, uint32_t *err, + uint8_t reg_data) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_data); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_STOP; + + return result; +} + +IIC_DVFS_FUNC(stop, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_STOP); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_DONE; + + return result; +} + +IIC_DVFS_FUNC(done, void) +{ + uint32_t i; + + for (i = 0U; i < IIC_DVFS_SET_BUSY_LOOP; i++) { + if ((mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_BUSY) != 0U) { + continue; + } + goto done; + } + + panic(); +done: + mmio_write_8(IIC_DVFS_REG_ICCR, 0U); + + return DVFS_COMPLETE; +} + +IIC_DVFS_FUNC(write_reg_addr_read, enum dvfs_state_t *state, uint32_t *err, + uint8_t reg_addr) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_addr); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_RETRANSMIT; + + return result; +} + +IIC_DVFS_FUNC(retransmit, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_RETRANSMISSION); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) | IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *state = DVFS_SET_SLAVE_READ; + + return result; +} + +IIC_DVFS_FUNC(set_slave_read, enum dvfs_state_t *state, uint32_t *err, + uint8_t slave) +{ + uint8_t address; + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + address = ((uint8_t) (slave << 1) + DVFS_READ_MODE); + mmio_write_8(IIC_DVFS_REG_ICDR, address); + + *state = DVFS_CHANGE_SEND_TO_RECEIVE; + + return result; +} + +IIC_DVFS_FUNC(change_send_to_receive, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_CHANGE); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_STOP_READ; + + return result; +} + +IIC_DVFS_FUNC(stop_read, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_READ_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_STOP_READ); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) | IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *state = DVFS_READ; + + return result; +} + +IIC_DVFS_FUNC(read, enum dvfs_state_t *state, uint8_t *reg_data) +{ + uint8_t mode; + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return DVFS_PROCESS; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *reg_data = mmio_read_8(IIC_DVFS_REG_ICDR); + *state = DVFS_DONE; + + return DVFS_PROCESS; +} + +RCAR_DVFS_API(send, uint8_t slave, uint8_t reg_addr, uint8_t reg_data) +{ + enum dvfs_state_t state = DVFS_START; + int32_t result = DVFS_PROCESS; + uint32_t err = 0U; + + mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS); + mmio_write_8(IIC_DVFS_REG_ICCR, 1U); +again: + switch (state) { + case DVFS_START: + result = dvfs_start(&state); + break; + case DVFS_SET_SLAVE: + result = dvfs_set_slave(&state, &err, slave); + break; + case DVFS_WRITE_ADDR: + result = dvfs_write_addr(&state, &err, reg_addr); + break; + case DVFS_WRITE_DATA: + result = dvfs_write_data(&state, &err, reg_data); + break; + case DVFS_STOP: + result = dvfs_stop(&state, &err); + break; + case DVFS_DONE: + result = dvfs_done(); + break; + default: + panic(); + break; + } + + if (result == DVFS_PROCESS) { + goto again; + } + + return result; +} + +RCAR_DVFS_API(receive, uint8_t slave, uint8_t reg, uint8_t *data) +{ + enum dvfs_state_t state = DVFS_START; + int32_t result = DVFS_PROCESS; + uint32_t err = 0U; + + mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS); + mmio_write_8(IIC_DVFS_REG_ICCR, 1U); +again: + switch (state) { + case DVFS_START: + result = dvfs_start(&state); + break; + case DVFS_SET_SLAVE: + result = dvfs_set_slave(&state, &err, slave); + break; + case DVFS_WRITE_ADDR: + result = dvfs_write_reg_addr_read(&state, &err, reg); + break; + case DVFS_RETRANSMIT: + result = dvfs_retransmit(&state, &err); + break; + case DVFS_SET_SLAVE_READ: + result = dvfs_set_slave_read(&state, &err, slave); + break; + case DVFS_CHANGE_SEND_TO_RECEIVE: + result = dvfs_change_send_to_receive(&state, &err); + break; + case DVFS_STOP_READ: + result = dvfs_stop_read(&state, &err); + break; + case DVFS_READ: + result = dvfs_read(&state, data); + break; + case DVFS_DONE: + result = dvfs_done(); + break; + default: + panic(); + break; + } + + if (result == DVFS_PROCESS) { + goto again; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h b/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h new file mode 100644 index 0000000..244c06c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IIC_DVFS_H +#define IIC_DVFS_H + +/* PMIC slave */ +#define PMIC (0x30U) +#define BKUP_MODE_CNT (0x20U) +#define DVFS_SET_VID (0x54U) +#define REG_KEEP10 (0x79U) + +/* EEPROM slave */ +#define EEPROM (0x50U) +#define BOARD_ID (0x70U) + +int32_t rcar_iic_dvfs_receive(uint8_t slave, uint8_t reg, uint8_t *data); +int32_t rcar_iic_dvfs_send(uint8_t slave, uint8_t regr, uint8_t data); + +#endif /* IIC_DVFS_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_common.h b/arm-trusted-firmware/drivers/renesas/common/io/io_common.h new file mode 100644 index 0000000..6eb7777 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c b/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c new file mode 100644 index 0000000..c2b5f7c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c @@ -0,0 +1,179 @@ +/* + * 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 EMMC_PARTITION_ID emmcdrv_bootpartition = PARTITION_ID_USER; + +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 sector_add, sector_num, emmc_dma = 0; + int32_t result = IO_SUCCESS; + + sector_add = current_file.file_pos >> EMMC_SECTOR_SIZE_SHIFT; + sector_num = (length + EMMC_SECTOR_SIZE - 1U) >> EMMC_SECTOR_SIZE_SHIFT; + + NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%llx(%d) len=0x%lx(%d)\n", + buffer, + current_file.partition, current_file.file_pos, + sector_add, length, sector_num); + + if ((buffer + length - 1U) <= (uintptr_t)UINT32_MAX) { + emmc_dma = LOADIMAGE_FLAGS_DMA_ENABLE; + } + + if (emmc_read_sector((uint32_t *) buffer, sector_add, sector_num, + emmc_dma) != EMMC_SUCCESS) { + result = IO_FAIL; + } + + *length_read = length; + fp->file_pos += (signed long long)length; + + 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.file_pos = 0; + current_file.in_use = 1; + + if (emmcdrv_bootpartition == PARTITION_ID_USER) { + emmcdrv_bootpartition = mmc_drv_obj.boot_partition_en; + if ((emmcdrv_bootpartition == PARTITION_ID_BOOT_1) || + (emmcdrv_bootpartition == PARTITION_ID_BOOT_2)) { + current_file.partition = emmcdrv_bootpartition; + + NOTICE("BL2: eMMC boot from partition %d\n", + emmcdrv_bootpartition); + goto done; + } + return IO_FAIL; + } + + if ((block_spec->partition == PARTITION_ID_USER) || + (block_spec->partition == PARTITION_ID_BOOT_1) || + (block_spec->partition == PARTITION_ID_BOOT_2)) { + current_file.partition = block_spec->partition; + } else { + current_file.partition = emmcdrv_bootpartition; + } + +done: + 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 rcar_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/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h b/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h new file mode 100644 index 0000000..95070f2 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/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 rcar_register_io_dev_emmcdrv(const io_dev_connector_t **connector); + +#endif /* IO_EMMCDRV_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c b/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c new file mode 100644 index 0000000..1f31c0f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "io_common.h" +#include "io_memdrv.h" +#include "io_private.h" +#include "rcar_def.h" + +extern void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len); + +static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t memdrv_dev_close(io_dev_info_t *dev_info); + +/* + * 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 { + uint32_t in_use; + uintptr_t base; + signed long long file_pos; +} file_state_t; + +static file_state_t current_file = { 0 }; + +static io_type_t device_type_memdrv(void) +{ + return IO_TYPE_MEMMAP; +} + +static int32_t memdrv_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; + + /* + * 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_file.in_use != 0U) { + return IO_RESOURCES_EXHAUSTED; + } + + /* File cursor offset for seek and incremental reads etc. */ + current_file.base = block_spec->offset; + current_file.file_pos = 0; + current_file.in_use = 1; + + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t memdrv_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 memdrv_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *cnt) +{ + file_state_t *fp; + + fp = (file_state_t *) entity->info; + + NOTICE("BL2: dst=0x%lx src=0x%llx len=%ld(0x%lx)\n", + buffer, (unsigned long long)fp->base + + (unsigned long long)fp->file_pos, length, length); + + if (FLASH_MEMORY_SIZE < (fp->file_pos + (signed long long)length)) { + ERROR("BL2: check load image (source address)\n"); + return IO_FAIL; + } + + rcar_dma_exec(buffer, fp->base + (uintptr_t)fp->file_pos, length); + fp->file_pos += (signed long long)length; + *cnt = length; + + return IO_SUCCESS; +} + +static int32_t memdrv_block_close(io_entity_t *entity) +{ + entity->info = 0U; + + memset((void *)¤t_file, 0, sizeof(current_file)); + + return IO_SUCCESS; +} + +static const io_dev_funcs_t memdrv_dev_funcs = { + .type = &device_type_memdrv, + .open = &memdrv_block_open, + .seek = &memdrv_block_seek, + .size = NULL, + .read = &memdrv_block_read, + .write = NULL, + .close = &memdrv_block_close, + .dev_init = NULL, + .dev_close = &memdrv_dev_close, +}; + +static const io_dev_info_t memdrv_dev_info = { + .funcs = &memdrv_dev_funcs, + .info = 0, +}; + +static const io_dev_connector_t memdrv_dev_connector = { + .dev_open = &memdrv_dev_open +}; + +static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &memdrv_dev_info; + + return IO_SUCCESS; +} + +static int32_t memdrv_dev_close(io_dev_info_t *dev_info) +{ + return IO_SUCCESS; +} + +int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **dev_con) +{ + int32_t result; + + result = io_register_device(&memdrv_dev_info); + if (result == IO_SUCCESS) { + *dev_con = &memdrv_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h b/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h new file mode 100644 index 0000000..90e6812 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MEMDRV_H +#define IO_MEMDRV_H + +struct io_dev_connector; +int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **connector); + +#endif /* IO_MEMDRV_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_private.h b/arm-trusted-firmware/drivers/renesas/common/io/io_private.h new file mode 100644 index 0000000..207523a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c b/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c new file mode 100644 index 0000000..45ef386 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2015-2021, 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 "io_rcar.h" +#include "io_common.h" +#include "io_private.h" +#include + +extern int32_t plat_get_drv_source(uint32_t id, uintptr_t *dev, + uintptr_t *image_spec); + +static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t rcar_dev_close(io_dev_info_t *dev_info); + +typedef struct { + const int32_t name; + const uint32_t offset; + const uint32_t attr; +} plat_rcar_name_offset_t; + +typedef struct { + /* + * Put position above the struct to allow {0} on static init. + * It is a workaround for a known bug in GCC + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + */ + uint32_t position; + uint32_t no_load; + uintptr_t offset; + uint32_t size; + uintptr_t dst; + uintptr_t partition; /* for eMMC */ + /* RCAR_EMMC_PARTITION_BOOT_0 */ + /* RCAR_EMMC_PARTITION_BOOT_1 */ + /* RCAR_EMMC_PARTITION_USER */ +} file_state_t; + +#define RCAR_GET_FLASH_ADR(a, b) ((uint32_t)((0x40000U * (a)) + (b))) +#define RCAR_ATTR_SET_CALCADDR(a) ((a) & 0xF) +#define RCAR_ATTR_SET_ISNOLOAD(a) (((a) & 0x1) << 16U) +#define RCAR_ATTR_SET_CERTOFF(a) (((a) & 0xF) << 8U) +#define RCAR_ATTR_SET_ALL(a, b, c) ((uint32_t)(RCAR_ATTR_SET_CALCADDR(a) |\ + RCAR_ATTR_SET_ISNOLOAD(b) |\ + RCAR_ATTR_SET_CERTOFF(c))) + +#define RCAR_ATTR_GET_CALCADDR(a) ((a) & 0xFU) +#define RCAR_ATTR_GET_ISNOLOAD(a) (((a) >> 16) & 0x1U) +#define RCAR_ATTR_GET_CERTOFF(a) ((uint32_t)(((a) >> 8) & 0xFU)) + +#define RCAR_MAX_BL3X_IMAGE (8U) +#define RCAR_SECTOR6_CERT_OFFSET (0x400U) +#define RCAR_SDRAM_certESS (0x43F00000U) +#define RCAR_CERT_SIZE (0x800U) +#define RCAR_CERT_INFO_SIZE_OFFSET (0x264U) +#define RCAR_CERT_INFO_DST_OFFSET (0x154U) +#define RCAR_CERT_INFO_SIZE_OFFSET1 (0x364U) +#define RCAR_CERT_INFO_DST_OFFSET1 (0x1D4U) +#define RCAR_CERT_INFO_SIZE_OFFSET2 (0x464U) +#define RCAR_CERT_INFO_DST_OFFSET2 (0x254U) +#define RCAR_CERT_LOAD (1U) + +#define RCAR_FLASH_CERT_HEADER RCAR_GET_FLASH_ADR(6U, 0U) +#define RCAR_EMMC_CERT_HEADER (0x00030000U) + +#define RCAR_COUNT_LOAD_BL33 (2U) +#define RCAR_COUNT_LOAD_BL33X (3U) + +static const plat_rcar_name_offset_t name_offset[] = { + {BL31_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(0, 0, 0)}, + + /* BL3-2 is optional in the platform */ + {BL32_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(1, 0, 1)}, + {BL33_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(2, 0, 2)}, + {BL332_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(3, 0, 3)}, + {BL333_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(4, 0, 4)}, + {BL334_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(5, 0, 5)}, + {BL335_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(6, 0, 6)}, + {BL336_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(7, 0, 7)}, + {BL337_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(8, 0, 8)}, + {BL338_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(9, 0, 9)}, +}; + +#if TRUSTED_BOARD_BOOT +static const plat_rcar_name_offset_t cert_offset[] = { + /* Certificates */ + {TRUSTED_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {SOC_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {TRUSTED_OS_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {NON_TRUSTED_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {SOC_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {TRUSTED_OS_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 1)}, + {NON_TRUSTED_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 2)}, + {BL332_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 3)}, + {BL333_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 4)}, + {BL334_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 5)}, + {BL335_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 6)}, + {BL336_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 7)}, + {BL337_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 8)}, + {BL338_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 9)}, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static file_state_t current_file = { 0 }; + +static uintptr_t rcar_handle, rcar_spec; +static uint64_t rcar_image_header[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U }; +static uint64_t rcar_image_header_prttn[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U }; +static uint64_t rcar_image_number = { 0U }; +static uint32_t rcar_cert_load = { 0U }; + +static io_type_t device_type_rcar(void) +{ + return IO_TYPE_FIRMWARE_IMAGE_PACKAGE; +} + +int32_t rcar_get_certificate(const int32_t name, uint32_t *cert) +{ +#if TRUSTED_BOARD_BOOT + int32_t i; + + for (i = 0; i < ARRAY_SIZE(cert_offset); i++) { + if (name != cert_offset[i].name) { + continue; + } + + *cert = RCAR_CERT_SIZE; + *cert *= RCAR_ATTR_GET_CERTOFF(cert_offset[i].attr); + *cert += RCAR_SDRAM_certESS; + return 0; + } +#endif + return -EINVAL; +} + +#define MFISBTSTSR (0xE6260604U) +#define MFISBTSTSR_BOOT_PARTITION (0x00000010U) + +static int32_t file_to_offset(const int32_t name, uintptr_t *offset, + uint32_t *cert, uint32_t *no_load, + uintptr_t *partition) +{ + uint32_t addr; + int32_t i; + + for (i = 0; i < ARRAY_SIZE(name_offset); i++) { + if (name != name_offset[i].name) { + continue; + } + + addr = RCAR_ATTR_GET_CALCADDR(name_offset[i].attr); + if (rcar_image_number + 2U < addr) { + continue; + } + + *offset = rcar_image_header[addr]; + + if (mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION) + *offset += 0x800000; + *cert = RCAR_CERT_SIZE; + *cert *= RCAR_ATTR_GET_CERTOFF(name_offset[i].attr); + *cert += RCAR_SDRAM_certESS; + *no_load = RCAR_ATTR_GET_ISNOLOAD(name_offset[i].attr); + *partition = rcar_image_header_prttn[addr]; + return IO_SUCCESS; + } + +#if TRUSTED_BOARD_BOOT + for (i = 0; i < ARRAY_SIZE(cert_offset); i++) { + if (name != cert_offset[i].name) { + continue; + } + + *no_load = RCAR_ATTR_GET_ISNOLOAD(cert_offset[i].attr); + *partition = 0U; + *offset = 0U; + *cert = 0U; + return IO_SUCCESS; + } +#endif + return -EINVAL; +} + +#define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U) +#define RCAR_CERT_MAGIC_NUM (0xE291F358U) + +void rcar_read_certificate(uint64_t cert, uint32_t *len, uintptr_t *dst) +{ + uint32_t seed, val, info_1, info_2; + uintptr_t size, dsth, dstl; + + cert &= 0xFFFFFFFFU; + + seed = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW); + val = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW + 0xC); + info_1 = (val >> 18) & 0x3U; + val = mmio_read_32(cert + 0xC); + info_2 = (val >> 21) & 0x3; + + if (seed == RCAR_CERT_MAGIC_NUM) { + if (info_1 != 1) { + ERROR("BL2: Cert is invalid.\n"); + *dst = 0; + *len = 0; + return; + } + + if (info_2 > 2) { + ERROR("BL2: Cert is invalid.\n"); + *dst = 0; + *len = 0; + return; + } + + switch (info_2) { + case 2: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET2; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET2; + break; + case 1: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET1; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET1; + break; + case 0: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET; + break; + } + + *len = mmio_read_32(size) * 4U; + dsth = dstl + 4U; + *dst = ((uintptr_t) mmio_read_32(dsth) << 32) + + ((uintptr_t) mmio_read_32(dstl)); + return; + } + + size = cert + RCAR_CERT_INFO_SIZE_OFFSET; + *len = mmio_read_32(size) * 4U; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET; + dsth = dstl + 4U; + *dst = ((uintptr_t) mmio_read_32(dsth) << 32) + + ((uintptr_t) mmio_read_32(dstl)); +} + +static int32_t check_load_area(uintptr_t dst, uintptr_t len) +{ + uint32_t legacy = dst + len <= UINT32_MAX - 1 ? 1 : 0; + uintptr_t dram_start, dram_end; + uintptr_t prot_start, prot_end; + int32_t result = IO_SUCCESS; + + dram_start = legacy ? DRAM1_BASE : DRAM_40BIT_BASE; + + dram_end = legacy ? DRAM1_BASE + DRAM1_SIZE : + DRAM_40BIT_BASE + DRAM_40BIT_SIZE; + + prot_start = legacy ? DRAM_PROTECTED_BASE : DRAM_40BIT_PROTECTED_BASE; + + prot_end = prot_start + DRAM_PROTECTED_SIZE; + + if (dst < dram_start || dst > dram_end - len) { + ERROR("BL2: dst address is on the protected area.\n"); + result = IO_FAIL; + goto done; + } + + /* load image is within SDRAM protected area */ + if (dst >= prot_start && dst < prot_end) { + ERROR("BL2: dst address is on the protected area.\n"); + result = IO_FAIL; + } + + if (dst < prot_start && dst > prot_start - len) { + ERROR("BL2: loaded data is on the protected area.\n"); + result = IO_FAIL; + } +done: + if (result == IO_FAIL) { + ERROR("BL2: Out of range : dst=0x%lx len=0x%lx\n", dst, len); + } + + return result; +} + +static int32_t load_bl33x(void) +{ + static int32_t loaded = IO_NOT_SUPPORTED; + uintptr_t dst, partition, handle; + uint32_t noload, cert, len, i; + uintptr_t offset; + int32_t rc; + size_t cnt; + const int32_t img[] = { + BL33_IMAGE_ID, + BL332_IMAGE_ID, + BL333_IMAGE_ID, + BL334_IMAGE_ID, + BL335_IMAGE_ID, + BL336_IMAGE_ID, + BL337_IMAGE_ID, + BL338_IMAGE_ID + }; + + if (loaded != IO_NOT_SUPPORTED) { + return loaded; + } + + for (i = 1; i < rcar_image_number; i++) { + rc = file_to_offset(img[i], &offset, &cert, &noload, + &partition); + if (rc != IO_SUCCESS) { + WARN("%s: failed to get offset\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rcar_read_certificate((uint64_t) cert, &len, &dst); + ((io_drv_spec_t *) rcar_spec)->partition = partition; + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("%s: Failed to open FIP (%i)\n", __func__, rc); + loaded = IO_FAIL; + return loaded; + } + + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("%s: failed to seek\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rc = check_load_area(dst, len); + if (rc != IO_SUCCESS) { + WARN("%s: check load area\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rc = io_read(handle, dst, len, &cnt); + if (rc != IO_SUCCESS) { + WARN("%s: failed to read\n", __func__); + loaded = IO_FAIL; + return loaded; + } +#if TRUSTED_BOARD_BOOT + rc = auth_mod_verify_img(img[i], (void *)dst, len); + if (rc != 0) { + memset((void *)dst, 0x00, len); + loaded = IO_FAIL; + return loaded; + } +#endif + io_close(handle); + } + + loaded = IO_SUCCESS; + + return loaded; +} + +static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) +{ + static uint64_t header[64] __aligned(FLASH_TRANS_SIZE_UNIT) = {0UL}; + uintptr_t handle; + ssize_t offset; + uint32_t i; + int32_t rc; + size_t cnt; + + /* Obtain a reference to the image by querying the platform layer */ + rc = plat_get_drv_source(name, &rcar_handle, &rcar_spec); + if (rc != IO_SUCCESS) { + WARN("Failed to obtain reference to img %ld (%i)\n", name, rc); + return IO_FAIL; + } + + if (rcar_cert_load == RCAR_CERT_LOAD) { + return IO_SUCCESS; + } + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("Failed to access img %ld (%i)\n", name, rc); + return IO_FAIL; + } + + /* + * get start address list + * [0] address num + * [1] BL33-1 image address + * [2] BL33-2 image address + * [3] BL33-3 image address + * [4] BL33-4 image address + * [5] BL33-5 image address + * [6] BL33-6 image address + * [7] BL33-7 image address + * [8] BL33-8 image address + */ + offset = name == EMMC_DEV_ID ? RCAR_EMMC_CERT_HEADER : + RCAR_FLASH_CERT_HEADER; + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to seek\n"); + goto error; + } + + rc = io_read(handle, (uintptr_t) &header, sizeof(header), &cnt); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to read\n"); + goto error; + } + +#if RCAR_BL2_DCACHE == 1 + inv_dcache_range((uint64_t) header, sizeof(header)); +#endif + + rcar_image_number = header[0]; + for (i = 0; i < rcar_image_number + 2; i++) { + rcar_image_header[i] = header[i * 2 + 1]; + rcar_image_header_prttn[i] = header[i * 2 + 2]; + } + + if (rcar_image_number == 0 || rcar_image_number > RCAR_MAX_BL3X_IMAGE) { + WARN("Firmware Image Package header check failed.\n"); + rc = IO_FAIL; + goto error; + } + + rc = io_seek(handle, IO_SEEK_SET, offset + RCAR_SECTOR6_CERT_OFFSET); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to seek cert\n"); + goto error; + } + + rc = io_read(handle, RCAR_SDRAM_certESS, + RCAR_CERT_SIZE * (2 + rcar_image_number), &cnt); + if (rc != IO_SUCCESS) { + WARN("cert file read error.\n"); + goto error; + } + +#if RCAR_BL2_DCACHE == 1 + inv_dcache_range(RCAR_SDRAM_certESS, + RCAR_CERT_SIZE * (2 + rcar_image_number)); +#endif + + rcar_cert_load = RCAR_CERT_LOAD; +error: + + if (rc != IO_SUCCESS) { + rc = IO_FAIL; + } + + io_close(handle); + + return rc; + +} + +static int32_t rcar_file_open(io_dev_info_t *info, const uintptr_t file_spec, + io_entity_t *entity) +{ + const io_drv_spec_t *spec = (io_drv_spec_t *) file_spec; + uintptr_t partition, offset, dst; + uint32_t noload, cert, len; + int32_t rc; + + /* + * Only one file open at a time. We need to track state (ie, file + * cursor position). Since the header lives at offset zero, this entry + * should never be zero in an active file. + * Once the system supports dynamic memory allocation we will allow more + * than one open file at a time. + */ + if (current_file.offset != 0U) { + WARN("%s: Only one open file at a time.\n", __func__); + return IO_RESOURCES_EXHAUSTED; + } + + rc = file_to_offset(spec->offset, &offset, &cert, &noload, &partition); + if (rc != IO_SUCCESS) { + WARN("Failed to open file name %ld (%i)\n", spec->offset, rc); + return IO_FAIL; + } + + if (noload != 0U) { + current_file.offset = 1; + current_file.dst = 0; + current_file.size = 1; + current_file.position = 0; + current_file.no_load = noload; + current_file.partition = 0; + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; + } + + rcar_read_certificate((uint64_t) cert, &len, &dst); + + /* Baylibre: HACK */ + if (spec->offset == BL31_IMAGE_ID && len < RCAR_TRUSTED_SRAM_SIZE) { + WARN("%s,%s\n", "r-car ignoring the BL31 size from certificate", + "using RCAR_TRUSTED_SRAM_SIZE instead"); + len = RCAR_TRUSTED_SRAM_SIZE; + } + + current_file.partition = partition; + current_file.no_load = noload; + current_file.offset = offset; + current_file.position = 0; + current_file.size = len; + current_file.dst = dst; + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t rcar_file_len(io_entity_t *entity, size_t *length) +{ + *length = ((file_state_t *) entity->info)->size; + + NOTICE("%s: len: 0x%08lx\n", __func__, *length); + + return IO_SUCCESS; +} + +static int32_t rcar_file_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *cnt) +{ + file_state_t *fp = (file_state_t *) entity->info; + ssize_t offset = fp->offset + fp->position; + uintptr_t handle; + int32_t rc; + +#ifdef SPD_NONE + static uint32_t load_bl33x_counter = 1; +#else + static uint32_t load_bl33x_counter; +#endif + if (current_file.no_load != 0U) { + *cnt = length; + return IO_SUCCESS; + } + + ((io_drv_spec_t *) rcar_spec)->partition = fp->partition; + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("Failed to open FIP (%i)\n", rc); + return IO_FAIL; + } + + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("%s: failed to seek\n", __func__); + goto error; + } + + if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33) { + rc = check_load_area(buffer, length); + if (rc != IO_SUCCESS) { + WARN("%s: load area err\n", __func__); + goto error; + } + } + + rc = io_read(handle, buffer, length, cnt); + if (rc != IO_SUCCESS) { + WARN("Failed to read payload (%i)\n", rc); + goto error; + } + + fp->position += *cnt; + io_close(handle); + + load_bl33x_counter += 1; + if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33X) { + return load_bl33x(); + } + + return IO_SUCCESS; +error: + io_close(handle); + return IO_FAIL; +} + +static int32_t rcar_file_close(io_entity_t *entity) +{ + if (current_file.offset != 0U) { + memset(¤t_file, 0, sizeof(current_file)); + } + + entity->info = 0U; + + return IO_SUCCESS; +} + +static const io_dev_funcs_t rcar_dev_funcs = { + .type = &device_type_rcar, + .open = &rcar_file_open, + .seek = NULL, + .size = &rcar_file_len, + .read = &rcar_file_read, + .write = NULL, + .close = &rcar_file_close, + .dev_init = &rcar_dev_init, + .dev_close = &rcar_dev_close, +}; + +static const io_dev_info_t rcar_dev_info = { + .funcs = &rcar_dev_funcs, + .info = (uintptr_t) 0 +}; + +static const io_dev_connector_t rcar_dev_connector = { + .dev_open = &rcar_dev_open +}; + +static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &rcar_dev_info; + + return IO_SUCCESS; +} + +static int32_t rcar_dev_close(io_dev_info_t *dev_info) +{ + rcar_handle = 0; + rcar_spec = 0; + + return IO_SUCCESS; +} + +int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con) +{ + int32_t result; + + result = io_register_device(&rcar_dev_info); + if (result == IO_SUCCESS) { + *dev_con = &rcar_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h b/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h new file mode 100644 index 0000000..c26a617 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_RCAR_H +#define IO_RCAR_H + +int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con); +int32_t rcar_get_certificate(const int32_t name, uint32_t *cert); +void rcar_read_certificate(uint64_t cert, uint32_t *size, uintptr_t *dest); + +#endif /* IO_RCAR_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/pfc_regs.h b/arm-trusted-firmware/drivers/renesas/common/pfc_regs.h new file mode 100644 index 0000000..4187733 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/pfc_regs.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PFC_REGS_H +#define PFC_REGS_H + +/* GPIO base address */ +#define GPIO_BASE (0xE6050000U) + +/* GPIO registers */ +#define GPIO_IOINTSEL0 (GPIO_BASE + 0x0000U) +#define GPIO_INOUTSEL0 (GPIO_BASE + 0x0004U) +#define GPIO_OUTDT0 (GPIO_BASE + 0x0008U) +#define GPIO_INDT0 (GPIO_BASE + 0x000CU) +#define GPIO_INTDT0 (GPIO_BASE + 0x0010U) +#define GPIO_INTCLR0 (GPIO_BASE + 0x0014U) +#define GPIO_INTMSK0 (GPIO_BASE + 0x0018U) +#define GPIO_MSKCLR0 (GPIO_BASE + 0x001CU) +#define GPIO_POSNEG0 (GPIO_BASE + 0x0020U) +#define GPIO_EDGLEVEL0 (GPIO_BASE + 0x0024U) +#define GPIO_FILONOFF0 (GPIO_BASE + 0x0028U) +#define GPIO_INTMSKS0 (GPIO_BASE + 0x0038U) +#define GPIO_MSKCLRS0 (GPIO_BASE + 0x003CU) +#define GPIO_OUTDTSEL0 (GPIO_BASE + 0x0040U) +#define GPIO_OUTDTH0 (GPIO_BASE + 0x0044U) +#define GPIO_OUTDTL0 (GPIO_BASE + 0x0048U) +#define GPIO_BOTHEDGE0 (GPIO_BASE + 0x004CU) +#define GPIO_IOINTSEL1 (GPIO_BASE + 0x1000U) +#define GPIO_INOUTSEL1 (GPIO_BASE + 0x1004U) +#define GPIO_OUTDT1 (GPIO_BASE + 0x1008U) +#define GPIO_INDT1 (GPIO_BASE + 0x100CU) +#define GPIO_INTDT1 (GPIO_BASE + 0x1010U) +#define GPIO_INTCLR1 (GPIO_BASE + 0x1014U) +#define GPIO_INTMSK1 (GPIO_BASE + 0x1018U) +#define GPIO_MSKCLR1 (GPIO_BASE + 0x101CU) +#define GPIO_POSNEG1 (GPIO_BASE + 0x1020U) +#define GPIO_EDGLEVEL1 (GPIO_BASE + 0x1024U) +#define GPIO_FILONOFF1 (GPIO_BASE + 0x1028U) +#define GPIO_INTMSKS1 (GPIO_BASE + 0x1038U) +#define GPIO_MSKCLRS1 (GPIO_BASE + 0x103CU) +#define GPIO_OUTDTSEL1 (GPIO_BASE + 0x1040U) +#define GPIO_OUTDTH1 (GPIO_BASE + 0x1044U) +#define GPIO_OUTDTL1 (GPIO_BASE + 0x1048U) +#define GPIO_BOTHEDGE1 (GPIO_BASE + 0x104CU) +#define GPIO_IOINTSEL2 (GPIO_BASE + 0x2000U) +#define GPIO_INOUTSEL2 (GPIO_BASE + 0x2004U) +#define GPIO_OUTDT2 (GPIO_BASE + 0x2008U) +#define GPIO_INDT2 (GPIO_BASE + 0x200CU) +#define GPIO_INTDT2 (GPIO_BASE + 0x2010U) +#define GPIO_INTCLR2 (GPIO_BASE + 0x2014U) +#define GPIO_INTMSK2 (GPIO_BASE + 0x2018U) +#define GPIO_MSKCLR2 (GPIO_BASE + 0x201CU) +#define GPIO_POSNEG2 (GPIO_BASE + 0x2020U) +#define GPIO_EDGLEVEL2 (GPIO_BASE + 0x2024U) +#define GPIO_FILONOFF2 (GPIO_BASE + 0x2028U) +#define GPIO_INTMSKS2 (GPIO_BASE + 0x2038U) +#define GPIO_MSKCLRS2 (GPIO_BASE + 0x203CU) +#define GPIO_OUTDTSEL2 (GPIO_BASE + 0x2040U) +#define GPIO_OUTDTH2 (GPIO_BASE + 0x2044U) +#define GPIO_OUTDTL2 (GPIO_BASE + 0x2048U) +#define GPIO_BOTHEDGE2 (GPIO_BASE + 0x204CU) +#define GPIO_IOINTSEL3 (GPIO_BASE + 0x3000U) +#define GPIO_INOUTSEL3 (GPIO_BASE + 0x3004U) +#define GPIO_OUTDT3 (GPIO_BASE + 0x3008U) +#define GPIO_INDT3 (GPIO_BASE + 0x300CU) +#define GPIO_INTDT3 (GPIO_BASE + 0x3010U) +#define GPIO_INTCLR3 (GPIO_BASE + 0x3014U) +#define GPIO_INTMSK3 (GPIO_BASE + 0x3018U) +#define GPIO_MSKCLR3 (GPIO_BASE + 0x301CU) +#define GPIO_POSNEG3 (GPIO_BASE + 0x3020U) +#define GPIO_EDGLEVEL3 (GPIO_BASE + 0x3024U) +#define GPIO_FILONOFF3 (GPIO_BASE + 0x3028U) +#define GPIO_INTMSKS3 (GPIO_BASE + 0x3038U) +#define GPIO_MSKCLRS3 (GPIO_BASE + 0x303CU) +#define GPIO_OUTDTSEL3 (GPIO_BASE + 0x3040U) +#define GPIO_OUTDTH3 (GPIO_BASE + 0x3044U) +#define GPIO_OUTDTL3 (GPIO_BASE + 0x3048U) +#define GPIO_BOTHEDGE3 (GPIO_BASE + 0x304CU) +#define GPIO_IOINTSEL4 (GPIO_BASE + 0x4000U) +#define GPIO_INOUTSEL4 (GPIO_BASE + 0x4004U) +#define GPIO_OUTDT4 (GPIO_BASE + 0x4008U) +#define GPIO_INDT4 (GPIO_BASE + 0x400CU) +#define GPIO_INTDT4 (GPIO_BASE + 0x4010U) +#define GPIO_INTCLR4 (GPIO_BASE + 0x4014U) +#define GPIO_INTMSK4 (GPIO_BASE + 0x4018U) +#define GPIO_MSKCLR4 (GPIO_BASE + 0x401CU) +#define GPIO_POSNEG4 (GPIO_BASE + 0x4020U) +#define GPIO_EDGLEVEL4 (GPIO_BASE + 0x4024U) +#define GPIO_FILONOFF4 (GPIO_BASE + 0x4028U) +#define GPIO_INTMSKS4 (GPIO_BASE + 0x4038U) +#define GPIO_MSKCLRS4 (GPIO_BASE + 0x403CU) +#define GPIO_OUTDTSEL4 (GPIO_BASE + 0x4040U) +#define GPIO_OUTDTH4 (GPIO_BASE + 0x4044U) +#define GPIO_OUTDTL4 (GPIO_BASE + 0x4048U) +#define GPIO_BOTHEDGE4 (GPIO_BASE + 0x404CU) +#define GPIO_IOINTSEL5 (GPIO_BASE + 0x5000U) +#define GPIO_INOUTSEL5 (GPIO_BASE + 0x5004U) +#define GPIO_OUTDT5 (GPIO_BASE + 0x5008U) +#define GPIO_INDT5 (GPIO_BASE + 0x500CU) +#define GPIO_INTDT5 (GPIO_BASE + 0x5010U) +#define GPIO_INTCLR5 (GPIO_BASE + 0x5014U) +#define GPIO_INTMSK5 (GPIO_BASE + 0x5018U) +#define GPIO_MSKCLR5 (GPIO_BASE + 0x501CU) +#define GPIO_POSNEG5 (GPIO_BASE + 0x5020U) +#define GPIO_EDGLEVEL5 (GPIO_BASE + 0x5024U) +#define GPIO_FILONOFF5 (GPIO_BASE + 0x5028U) +#define GPIO_INTMSKS5 (GPIO_BASE + 0x5038U) +#define GPIO_MSKCLRS5 (GPIO_BASE + 0x503CU) +#define GPIO_OUTDTSEL5 (GPIO_BASE + 0x5040U) +#define GPIO_OUTDTH5 (GPIO_BASE + 0x5044U) +#define GPIO_OUTDTL5 (GPIO_BASE + 0x5048U) +#define GPIO_BOTHEDGE5 (GPIO_BASE + 0x504CU) +#define GPIO_IOINTSEL6 (GPIO_BASE + 0x5400U) +#define GPIO_INOUTSEL6 (GPIO_BASE + 0x5404U) +#define GPIO_OUTDT6 (GPIO_BASE + 0x5408U) +#define GPIO_INTDT6 (GPIO_BASE + 0x5410U) +#define GPIO_INTCLR6 (GPIO_BASE + 0x5414U) +#define GPIO_INTMSK6 (GPIO_BASE + 0x5418U) +#define GPIO_MSKCLR6 (GPIO_BASE + 0x541CU) +#define GPIO_POSNEG6 (GPIO_BASE + 0x5420U) +#define GPIO_EDGLEVEL6 (GPIO_BASE + 0x5424U) +#define GPIO_FILONOFF6 (GPIO_BASE + 0x5428U) +#define GPIO_INTMSKS6 (GPIO_BASE + 0x5438U) +#define GPIO_MSKCLRS6 (GPIO_BASE + 0x543CU) +#define GPIO_OUTDTSEL6 (GPIO_BASE + 0x5440U) +#define GPIO_OUTDTH6 (GPIO_BASE + 0x5444U) +#define GPIO_OUTDTL6 (GPIO_BASE + 0x5448U) +#define GPIO_BOTHEDGE6 (GPIO_BASE + 0x544CU) +#define GPIO_IOINTSEL7 (GPIO_BASE + 0x5800U) +#define GPIO_INOUTSEL7 (GPIO_BASE + 0x5804U) +#define GPIO_OUTDT7 (GPIO_BASE + 0x5808U) +#define GPIO_INDT7 (GPIO_BASE + 0x580CU) +#define GPIO_INTDT7 (GPIO_BASE + 0x5810U) +#define GPIO_INTCLR7 (GPIO_BASE + 0x5814U) +#define GPIO_INTMSK7 (GPIO_BASE + 0x5818U) +#define GPIO_MSKCLR7 (GPIO_BASE + 0x581CU) +#define GPIO_POSNEG7 (GPIO_BASE + 0x5820U) +#define GPIO_EDGLEVEL7 (GPIO_BASE + 0x5824U) +#define GPIO_FILONOFF7 (GPIO_BASE + 0x5828U) +#define GPIO_INTMSKS7 (GPIO_BASE + 0x5838U) +#define GPIO_MSKCLRS7 (GPIO_BASE + 0x583CU) +#define GPIO_OUTDTSEL7 (GPIO_BASE + 0x5840U) +#define GPIO_OUTDTH7 (GPIO_BASE + 0x5844U) +#define GPIO_OUTDTL7 (GPIO_BASE + 0x5848U) +#define GPIO_BOTHEDGE7 (GPIO_BASE + 0x584CU) + +/* Pin functon base address */ +#define PFC_BASE (0xE6060000U) + +/* Pin functon registers */ +#define PFC_PMMR (PFC_BASE + 0x0000U) +#define PFC_GPSR0 (PFC_BASE + 0x0100U) +#define PFC_GPSR1 (PFC_BASE + 0x0104U) +#define PFC_GPSR2 (PFC_BASE + 0x0108U) +#define PFC_GPSR3 (PFC_BASE + 0x010CU) +#define PFC_GPSR4 (PFC_BASE + 0x0110U) +#define PFC_GPSR5 (PFC_BASE + 0x0114U) +#define PFC_GPSR6 (PFC_BASE + 0x0118U) +#define PFC_GPSR7 (PFC_BASE + 0x011CU) +#define PFC_IPSR0 (PFC_BASE + 0x0200U) +#define PFC_IPSR1 (PFC_BASE + 0x0204U) +#define PFC_IPSR2 (PFC_BASE + 0x0208U) +#define PFC_IPSR3 (PFC_BASE + 0x020CU) +#define PFC_IPSR4 (PFC_BASE + 0x0210U) +#define PFC_IPSR5 (PFC_BASE + 0x0214U) +#define PFC_IPSR6 (PFC_BASE + 0x0218U) +#define PFC_IPSR7 (PFC_BASE + 0x021CU) +#define PFC_IPSR8 (PFC_BASE + 0x0220U) +#define PFC_IPSR9 (PFC_BASE + 0x0224U) +#define PFC_IPSR10 (PFC_BASE + 0x0228U) +#define PFC_IPSR11 (PFC_BASE + 0x022CU) +#define PFC_IPSR12 (PFC_BASE + 0x0230U) +#define PFC_IPSR13 (PFC_BASE + 0x0234U) +#define PFC_IPSR14 (PFC_BASE + 0x0238U) +#define PFC_IPSR15 (PFC_BASE + 0x023CU) +#define PFC_IPSR16 (PFC_BASE + 0x0240U) +#define PFC_IPSR17 (PFC_BASE + 0x0244U) +#define PFC_IPSR18 (PFC_BASE + 0x0248U) +#define PFC_DRVCTRL0 (PFC_BASE + 0x0300U) +#define PFC_DRVCTRL1 (PFC_BASE + 0x0304U) +#define PFC_DRVCTRL2 (PFC_BASE + 0x0308U) +#define PFC_DRVCTRL3 (PFC_BASE + 0x030CU) +#define PFC_DRVCTRL4 (PFC_BASE + 0x0310U) +#define PFC_DRVCTRL5 (PFC_BASE + 0x0314U) +#define PFC_DRVCTRL6 (PFC_BASE + 0x0318U) +#define PFC_DRVCTRL7 (PFC_BASE + 0x031CU) +#define PFC_DRVCTRL8 (PFC_BASE + 0x0320U) +#define PFC_DRVCTRL9 (PFC_BASE + 0x0324U) +#define PFC_DRVCTRL10 (PFC_BASE + 0x0328U) +#define PFC_DRVCTRL11 (PFC_BASE + 0x032CU) +#define PFC_DRVCTRL12 (PFC_BASE + 0x0330U) +#define PFC_DRVCTRL13 (PFC_BASE + 0x0334U) +#define PFC_DRVCTRL14 (PFC_BASE + 0x0338U) +#define PFC_DRVCTRL15 (PFC_BASE + 0x033CU) +#define PFC_DRVCTRL16 (PFC_BASE + 0x0340U) +#define PFC_DRVCTRL17 (PFC_BASE + 0x0344U) +#define PFC_DRVCTRL18 (PFC_BASE + 0x0348U) +#define PFC_DRVCTRL19 (PFC_BASE + 0x034CU) +#define PFC_DRVCTRL20 (PFC_BASE + 0x0350U) +#define PFC_DRVCTRL21 (PFC_BASE + 0x0354U) +#define PFC_DRVCTRL22 (PFC_BASE + 0x0358U) +#define PFC_DRVCTRL23 (PFC_BASE + 0x035CU) +#define PFC_DRVCTRL24 (PFC_BASE + 0x0360U) +#define PFC_POCCTRL0 (PFC_BASE + 0x0380U) +#define PFC_IOCTRL31 (PFC_BASE + 0x0384U) +#define PFC_POCCTRL2 (PFC_BASE + 0x0388U) +#define PFC_TDSELCTRL0 (PFC_BASE + 0x03C0U) +#define PFC_IOCTRL (PFC_BASE + 0x03E0U) +#define PFC_TSREG (PFC_BASE + 0x03E4U) +#define PFC_PUEN0 (PFC_BASE + 0x0400U) +#define PFC_PUEN1 (PFC_BASE + 0x0404U) +#define PFC_PUEN2 (PFC_BASE + 0x0408U) +#define PFC_PUEN3 (PFC_BASE + 0x040CU) +#define PFC_PUEN4 (PFC_BASE + 0x0410U) +#define PFC_PUEN5 (PFC_BASE + 0x0414U) +#define PFC_PUEN6 (PFC_BASE + 0x0418U) +#define PFC_PUD0 (PFC_BASE + 0x0440U) +#define PFC_PUD1 (PFC_BASE + 0x0444U) +#define PFC_PUD2 (PFC_BASE + 0x0448U) +#define PFC_PUD3 (PFC_BASE + 0x044CU) +#define PFC_PUD4 (PFC_BASE + 0x0450U) +#define PFC_PUD5 (PFC_BASE + 0x0454U) +#define PFC_PUD6 (PFC_BASE + 0x0458U) +#define PFC_MOD_SEL0 (PFC_BASE + 0x0500U) +#define PFC_MOD_SEL1 (PFC_BASE + 0x0504U) +#define PFC_MOD_SEL2 (PFC_BASE + 0x0508U) + +#endif /* PFC_REGS_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S b/arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S new file mode 100644 index 0000000..aa8644c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +.global rcar_pwrc_switch_stack + +/* + * x0 : jump address, + * x1 : stack address, + * x2 : arg, + * x3 : stack address (temporary) + */ +func rcar_pwrc_switch_stack + + /* lr to stack */ + stp x29, x30, [sp,#-16] + + /* change stack pointer */ + mov x3, sp + mov sp, x1 + + /* save stack pointer */ + sub sp, sp, #16 + stp x0, x3, [sp] + + /* data synchronization barrier */ + dsb sy + + /* jump to code */ + mov x1, x0 + mov x0, x2 + blr x1 + + /* load stack pointer */ + ldp x0, x2, [sp,#0] + + /* change stack pointer */ + mov sp, x2 + + /* return */ + ldp x29, x30, [sp,#-16] + ret +endfunc rcar_pwrc_switch_stack diff --git a/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c b/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c new file mode 100644 index 0000000..b60ccab --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c @@ -0,0 +1,917 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "iic_dvfs.h" +#include "micro_delay.h" +#include "pwrc.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "cpg_registers.h" + +/* + * Someday there will be a generic power controller api. At the moment each + * platform has its own pwrc so just exporting functions should be acceptable. + */ +RCAR_INSTANTIATE_LOCK + +#define WUP_IRQ_SHIFT (0U) +#define WUP_FIQ_SHIFT (8U) +#define WUP_CSD_SHIFT (16U) +#define BIT_SOFTRESET (1U << 15) +#define BIT_CA53_SCU (1U << 21) +#define BIT_CA57_SCU (1U << 12) +#define REQ_RESUME (1U << 1) +#define REQ_OFF (1U << 0) +#define STATUS_PWRUP (1U << 4) +#define STATUS_PWRDOWN (1U << 0) +#define STATE_CA57_CPU (27U) +#define STATE_CA53_CPU (22U) +#define MODE_L2_DOWN (0x00000002U) +#define CPU_PWR_OFF (0x00000003U) +#define RCAR_PSTR_MASK (0x00000003U) +#define ST_ALL_STANDBY (0x00003333U) +#define SYSCEXTMASK_EXTMSK0 (0x00000001U) +/* Suspend to ram */ +#define DBSC4_REG_BASE (0xE6790000U) +#define DBSC4_REG_DBSYSCNT0 (DBSC4_REG_BASE + 0x0100U) +#define DBSC4_REG_DBACEN (DBSC4_REG_BASE + 0x0200U) +#define DBSC4_REG_DBCMD (DBSC4_REG_BASE + 0x0208U) +#define DBSC4_REG_DBRFEN (DBSC4_REG_BASE + 0x0204U) +#define DBSC4_REG_DBWAIT (DBSC4_REG_BASE + 0x0210U) +#define DBSC4_REG_DBCALCNF (DBSC4_REG_BASE + 0x0424U) +#define DBSC4_REG_DBDFIPMSTRCNF (DBSC4_REG_BASE + 0x0520U) +#define DBSC4_REG_DBPDLK0 (DBSC4_REG_BASE + 0x0620U) +#define DBSC4_REG_DBPDRGA0 (DBSC4_REG_BASE + 0x0624U) +#define DBSC4_REG_DBPDRGD0 (DBSC4_REG_BASE + 0x0628U) +#define DBSC4_REG_DBCAM0CTRL0 (DBSC4_REG_BASE + 0x0940U) +#define DBSC4_REG_DBCAM0STAT0 (DBSC4_REG_BASE + 0x0980U) +#define DBSC4_REG_DBCAM1STAT0 (DBSC4_REG_BASE + 0x0990U) +#define DBSC4_REG_DBCAM2STAT0 (DBSC4_REG_BASE + 0x09A0U) +#define DBSC4_REG_DBCAM3STAT0 (DBSC4_REG_BASE + 0x09B0U) +#define DBSC4_BIT_DBACEN_ACCEN ((uint32_t)(1U << 0)) +#define DBSC4_BIT_DBRFEN_ARFEN ((uint32_t)(1U << 0)) +#define DBSC4_BIT_DBCAMxSTAT0 (0x00000001U) +#define DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN (0x00000001U) +#define DBSC4_SET_DBCMD_OPC_PRE (0x04000000U) +#define DBSC4_SET_DBCMD_OPC_SR (0x0A000000U) +#define DBSC4_SET_DBCMD_OPC_PD (0x08000000U) +#define DBSC4_SET_DBCMD_OPC_MRW (0x0E000000U) +#define DBSC4_SET_DBCMD_CH_ALL (0x00800000U) +#define DBSC4_SET_DBCMD_RANK_ALL (0x00040000U) +#define DBSC4_SET_DBCMD_ARG_ALL (0x00000010U) +#define DBSC4_SET_DBCMD_ARG_ENTER (0x00000000U) +#define DBSC4_SET_DBCMD_ARG_MRW_ODTC (0x00000B00U) +#define DBSC4_SET_DBSYSCNT0_WRITE_ENABLE (0x00001234U) +#define DBSC4_SET_DBSYSCNT0_WRITE_DISABLE (0x00000000U) +#define DBSC4_SET_DBPDLK0_PHY_ACCESS (0x0000A55AU) +#define DBSC4_SET_DBPDRGA0_ACIOCR0 (0x0000001AU) +#define DBSC4_SET_DBPDRGD0_ACIOCR0 (0x33C03C11U) +#define DBSC4_SET_DBPDRGA0_DXCCR (0x00000020U) +#define DBSC4_SET_DBPDRGD0_DXCCR (0x00181006U) +#define DBSC4_SET_DBPDRGA0_PGCR1 (0x00000003U) +#define DBSC4_SET_DBPDRGD0_PGCR1 (0x0380C600U) +#define DBSC4_SET_DBPDRGA0_ACIOCR1 (0x0000001BU) +#define DBSC4_SET_DBPDRGD0_ACIOCR1 (0xAAAAAAAAU) +#define DBSC4_SET_DBPDRGA0_ACIOCR3 (0x0000001DU) +#define DBSC4_SET_DBPDRGD0_ACIOCR3 (0xAAAAAAAAU) +#define DBSC4_SET_DBPDRGA0_ACIOCR5 (0x0000001FU) +#define DBSC4_SET_DBPDRGD0_ACIOCR5 (0x000000AAU) +#define DBSC4_SET_DBPDRGA0_DX0GCR2 (0x000000A2U) +#define DBSC4_SET_DBPDRGD0_DX0GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX1GCR2 (0x000000C2U) +#define DBSC4_SET_DBPDRGD0_DX1GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX2GCR2 (0x000000E2U) +#define DBSC4_SET_DBPDRGD0_DX2GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX3GCR2 (0x00000102U) +#define DBSC4_SET_DBPDRGD0_DX3GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_ZQCR (0x00000090U) +#define DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 (0x04058904U) +#define DBSC4_SET_DBPDRGD0_ZQCR_MD19_1 (0x04058A04U) +#define DBSC4_SET_DBPDRGA0_DX0GCR0 (0x000000A0U) +#define DBSC4_SET_DBPDRGD0_DX0GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX1GCR0 (0x000000C0U) +#define DBSC4_SET_DBPDRGD0_DX1GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX2GCR0 (0x000000E0U) +#define DBSC4_SET_DBPDRGD0_DX2GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX3GCR0 (0x00000100U) +#define DBSC4_SET_DBPDRGD0_DX3GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX0GCR1 (0x000000A1U) +#define DBSC4_SET_DBPDRGD0_DX0GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX1GCR1 (0x000000C1U) +#define DBSC4_SET_DBPDRGD0_DX1GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX2GCR1 (0x000000E1U) +#define DBSC4_SET_DBPDRGD0_DX2GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX3GCR1 (0x00000101U) +#define DBSC4_SET_DBPDRGD0_DX3GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX0GCR3 (0x000000A3U) +#define DBSC4_SET_DBPDRGD0_DX0GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX1GCR3 (0x000000C3U) +#define DBSC4_SET_DBPDRGD0_DX1GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX2GCR3 (0x000000E3U) +#define DBSC4_SET_DBPDRGD0_DX2GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX3GCR3 (0x00000103U) +#define DBSC4_SET_DBPDRGD0_DX3GCR3 (0x00008484U) +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) +#define RST_MODEMR_BIT0 (0x00000001U) + +#define RCAR_CNTCR_OFF (0x00U) +#define RCAR_CNTCVL_OFF (0x08U) +#define RCAR_CNTCVU_OFF (0x0CU) +#define RCAR_CNTFID_OFF (0x20U) + +#define RCAR_CNTCR_EN ((uint32_t)1U << 0U) +#define RCAR_CNTCR_FCREQ(x) ((uint32_t)(x) << 8U) + +#if PMIC_ROHM_BD9571 +#define BIT_BKUP_CTRL_OUT ((uint8_t)(1U << 4)) +#define PMIC_BKUP_MODE_CNT (0x20U) +#define PMIC_QLLM_CNT (0x27U) +#define PMIC_RETRY_MAX (100U) +#endif /* PMIC_ROHM_BD9571 */ +#define SCTLR_EL3_M_BIT ((uint32_t)1U << 0) +#define RCAR_CA53CPU_NUM_MAX (4U) +#define RCAR_CA57CPU_NUM_MAX (4U) +#define IS_A53A57(c) ((c) == RCAR_CLUSTER_A53A57) +#define IS_CA57(c) ((c) == RCAR_CLUSTER_CA57) +#define IS_CA53(c) ((c) == RCAR_CLUSTER_CA53) + +#ifndef __ASSEMBLER__ +IMPORT_SYM(unsigned long, __system_ram_start__, SYSTEM_RAM_START); +IMPORT_SYM(unsigned long, __system_ram_end__, SYSTEM_RAM_END); +IMPORT_SYM(unsigned long, __SRAM_COPY_START__, SRAM_COPY_START); +#endif + +uint32_t rcar_pwrc_status(u_register_t mpidr) +{ + uint32_t ret = 0; + uint64_t cm, cpu; + uint32_t reg; + uint32_t c; + + rcar_lock_get(); + + c = rcar_pwrc_get_cluster(); + cm = mpidr & MPIDR_CLUSTER_MASK; + + if (!IS_A53A57(c) && cm != 0) { + ret = RCAR_INVALID; + goto done; + } + + reg = mmio_read_32(RCAR_PRR); + cpu = mpidr & MPIDR_CPU_MASK; + + if (IS_CA53(c)) + if (reg & (1 << (STATE_CA53_CPU + cpu))) + ret = RCAR_INVALID; + if (IS_CA57(c)) + if (reg & (1 << (STATE_CA57_CPU + cpu))) + ret = RCAR_INVALID; +done: + rcar_lock_release(); + + return ret; +} + +static void scu_power_up(u_register_t mpidr) +{ + uintptr_t reg_pwrsr, reg_cpumcr, reg_pwron, reg_pwrer; + uint32_t c, sysc_reg_bit; + uint32_t lsi_product; + uint32_t lsi_cut; + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg_cpumcr = IS_CA57(c) ? RCAR_CA57CPUCMCR : RCAR_CA53CPUCMCR; + sysc_reg_bit = IS_CA57(c) ? BIT_CA57_SCU : BIT_CA53_SCU; + reg_pwron = IS_CA57(c) ? RCAR_PWRONCR5 : RCAR_PWRONCR3; + reg_pwrer = IS_CA57(c) ? RCAR_PWRER5 : RCAR_PWRER3; + reg_pwrsr = IS_CA57(c) ? RCAR_PWRSR5 : RCAR_PWRSR3; + + if ((mmio_read_32(reg_pwrsr) & STATUS_PWRDOWN) == 0) + return; + + if (mmio_read_32(reg_cpumcr) != 0) + mmio_write_32(reg_cpumcr, 0); + + lsi_product = mmio_read_32((uintptr_t)RCAR_PRR); + lsi_cut = lsi_product & PRR_CUT_MASK; + lsi_product &= PRR_PRODUCT_MASK; + + if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) || + lsi_product == PRR_PRODUCT_H3 || + lsi_product == PRR_PRODUCT_M3N || + lsi_product == PRR_PRODUCT_E3) { + mmio_setbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0); + } + + mmio_setbits_32(RCAR_SYSCIER, sysc_reg_bit); + mmio_setbits_32(RCAR_SYSCIMR, sysc_reg_bit); + + do { + while ((mmio_read_32(RCAR_SYSCSR) & REQ_RESUME) == 0) + ; + mmio_write_32(reg_pwron, 1); + } while (mmio_read_32(reg_pwrer) & 1); + + while ((mmio_read_32(RCAR_SYSCISR) & sysc_reg_bit) == 0) + ; + mmio_write_32(RCAR_SYSCISCR, sysc_reg_bit); + + if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) || + lsi_product == PRR_PRODUCT_H3 || + lsi_product == PRR_PRODUCT_M3N || + lsi_product == PRR_PRODUCT_E3) { + mmio_clrbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0); + } + + while ((mmio_read_32(reg_pwrsr) & STATUS_PWRUP) == 0) + ; +} + +void rcar_pwrc_cpuon(u_register_t mpidr) +{ + uint32_t res_data, on_data; + uintptr_t res_reg, on_reg; + uint32_t limit, c; + uint64_t cpu; + + rcar_lock_get(); + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + res_reg = IS_CA53(c) ? RCAR_CA53RESCNT : RCAR_CA57RESCNT; + on_reg = IS_CA53(c) ? RCAR_CA53WUPCR : RCAR_CA57WUPCR; + limit = IS_CA53(c) ? 0x5A5A0000 : 0xA5A50000; + + res_data = mmio_read_32(res_reg) | limit; + scu_power_up(mpidr); + cpu = mpidr & MPIDR_CPU_MASK; + on_data = 1 << cpu; + mmio_write_32(CPG_CPGWPR, ~on_data); + mmio_write_32(on_reg, on_data); + mmio_write_32(res_reg, res_data & (~(1 << (3 - cpu)))); + + rcar_lock_release(); +} + +void rcar_pwrc_cpuoff(u_register_t mpidr) +{ + uint32_t c; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_CA53CPU0CR : RCAR_CA57CPU0CR; + + if (read_mpidr_el1() != mpidr) + panic(); + + mmio_write_32(CPG_CPGWPR, ~CPU_PWR_OFF); + mmio_write_32(reg + cpu * 0x0010, CPU_PWR_OFF); + + rcar_lock_release(); +} + +void rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr) +{ + uint32_t c, shift_irq, shift_fiq; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_WUPMSKCA53 : RCAR_WUPMSKCA57; + + shift_irq = WUP_IRQ_SHIFT + cpu; + shift_fiq = WUP_FIQ_SHIFT + cpu; + + mmio_clrbits_32(reg, ((uint32_t) 1 << shift_irq) | + ((uint32_t) 1 << shift_fiq)); + rcar_lock_release(); +} + +void rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr) +{ + uint32_t c, shift_irq, shift_fiq; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_WUPMSKCA53 : RCAR_WUPMSKCA57; + + shift_irq = WUP_IRQ_SHIFT + cpu; + shift_fiq = WUP_FIQ_SHIFT + cpu; + + mmio_setbits_32(reg, ((uint32_t) 1 << shift_irq) | + ((uint32_t) 1 << shift_fiq)); + rcar_lock_release(); +} + +void rcar_pwrc_all_disable_interrupt_wakeup(void) +{ + uint32_t cpu_num; + u_register_t cl, cpu, mpidr; + + const uint32_t cluster[PLATFORM_CLUSTER_COUNT] = { + RCAR_CLUSTER_CA57, + RCAR_CLUSTER_CA53 + }; + + for (cl = 0; cl < PLATFORM_CLUSTER_COUNT; cl++) { + cpu_num = rcar_pwrc_get_cpu_num(cluster[cl]); + for (cpu = 0; cpu < cpu_num; cpu++) { + mpidr = ((cl << MPIDR_AFFINITY_BITS) | cpu); + if (mpidr == rcar_boot_mpidr) { + rcar_pwrc_enable_interrupt_wakeup(mpidr); + } else { + rcar_pwrc_disable_interrupt_wakeup(mpidr); + } + } + } +} + +void rcar_pwrc_clusteroff(u_register_t mpidr) +{ + uint32_t c, product, cut, reg; + uintptr_t dst; + + rcar_lock_get(); + + reg = mmio_read_32(RCAR_PRR); + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + dst = IS_CA53(c) ? RCAR_CA53CPUCMCR : RCAR_CA57CPUCMCR; + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { + goto done; + } + + if (product == PRR_PRODUCT_H3 && cut <= PRR_PRODUCT_20) { + goto done; + } + + /* all of the CPUs in the cluster is in the CoreStandby mode */ + mmio_write_32(dst, MODE_L2_DOWN); +done: + rcar_lock_release(); +} + +static uint64_t rcar_pwrc_saved_cntpct_el0; +static uint32_t rcar_pwrc_saved_cntfid; + +#if RCAR_SYSTEM_SUSPEND +static void rcar_pwrc_save_timer_state(void) +{ + rcar_pwrc_saved_cntpct_el0 = read_cntpct_el0(); + + rcar_pwrc_saved_cntfid = + mmio_read_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF)); +} +#endif /* RCAR_SYSTEM_SUSPEND */ + +void rcar_pwrc_restore_timer_state(void) +{ + /* Stop timer before restoring counter value */ + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), 0U); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVL_OFF), + (uint32_t)(rcar_pwrc_saved_cntpct_el0 & 0xFFFFFFFFU)); + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVU_OFF), + (uint32_t)(rcar_pwrc_saved_cntpct_el0 >> 32U)); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF), + rcar_pwrc_saved_cntfid); + + /* Start generic timer back */ + write_cntfrq_el0((u_register_t)plat_get_syscnt_freq2()); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), + (RCAR_CNTCR_FCREQ(0U) | RCAR_CNTCR_EN)); +} + +#if !PMIC_ROHM_BD9571 +void rcar_pwrc_system_reset(void) +{ + mmio_write_32(RCAR_SRESCR, 0x5AA50000U | BIT_SOFTRESET); +} +#endif /* PMIC_ROHM_BD9571 */ + +#define RST_CA53_CPU0_BARH (0xE6160080U) +#define RST_CA53_CPU0_BARL (0xE6160084U) +#define RST_CA57_CPU0_BARH (0xE61600C0U) +#define RST_CA57_CPU0_BARL (0xE61600C4U) + +void rcar_pwrc_setup(void) +{ + uintptr_t rst_barh; + uintptr_t rst_barl; + uint32_t i, j; + uint64_t reset = (uint64_t) (&plat_secondary_reset) & 0xFFFFFFFF; + + const uint32_t cluster[PLATFORM_CLUSTER_COUNT] = { + RCAR_CLUSTER_CA53, + RCAR_CLUSTER_CA57 + }; + const uintptr_t reg_barh[PLATFORM_CLUSTER_COUNT] = { + RST_CA53_CPU0_BARH, + RST_CA57_CPU0_BARH + }; + const uintptr_t reg_barl[PLATFORM_CLUSTER_COUNT] = { + RST_CA53_CPU0_BARL, + RST_CA57_CPU0_BARL + }; + + for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { + rst_barh = reg_barh[i]; + rst_barl = reg_barl[i]; + for (j = 0; j < rcar_pwrc_get_cpu_num(cluster[i]); j++) { + mmio_write_32(rst_barh, 0); + mmio_write_32(rst_barl, (uint32_t) reset); + rst_barh += 0x10; + rst_barl += 0x10; + } + } + + rcar_lock_init(); +} + +#if RCAR_SYSTEM_SUSPEND +#define DBCAM_FLUSH(__bit) \ +do { \ + ; \ +} while (!(mmio_read_32(DBSC4_REG_DBCAM##__bit##STAT0) & DBSC4_BIT_DBCAMxSTAT0)) + + +static void __attribute__ ((section(".system_ram"))) + rcar_pwrc_set_self_refresh(void) +{ + uint32_t reg = mmio_read_32(RCAR_PRR); + uint32_t cut, product; + + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { + goto self_refresh; + } + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) { + goto self_refresh; + } + + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); + +self_refresh: + + /* DFI_PHYMSTR_ACK setting */ + mmio_write_32(DBSC4_REG_DBDFIPMSTRCNF, + mmio_read_32(DBSC4_REG_DBDFIPMSTRCNF) & + (~DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN)); + + /* Set the Self-Refresh mode */ + mmio_write_32(DBSC4_REG_DBACEN, 0); + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) + rcar_micro_delay(100); + else if (product == PRR_PRODUCT_H3) { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + DBCAM_FLUSH(1); + DBCAM_FLUSH(2); + DBCAM_FLUSH(3); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } else if (product == PRR_PRODUCT_M3) { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + DBCAM_FLUSH(1); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } else { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } + + /* Set the SDRAM calibration configuration register */ + mmio_write_32(DBSC4_REG_DBCALCNF, 0); + + reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Self-Refresh entry command */ + reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Mode Register Write command. (ODT disabled) */ + reg = DBSC4_SET_DBCMD_OPC_MRW | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_MRW_ODTC; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Power Down entry command */ + reg = DBSC4_SET_DBCMD_OPC_PD | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Set the auto-refresh enable register */ + mmio_write_32(DBSC4_REG_DBRFEN, 0U); + rcar_micro_delay(1U); + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) + return; + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) + return; + + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); +} + +static void __attribute__ ((section(".system_ram"))) +rcar_pwrc_set_self_refresh_e3(void) +{ + uint32_t ddr_md; + uint32_t reg; + + ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & RST_MODEMR_BIT0; + + /* Write enable */ + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); + mmio_write_32(DBSC4_REG_DBACEN, 0); + DBCAM_FLUSH(0); + + reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* + * Set the auto-refresh enable register + * Set the ARFEN bit to 0 in the DBRFEN + */ + mmio_write_32(DBSC4_REG_DBRFEN, 0); + + mmio_write_32(DBSC4_REG_DBPDLK0, DBSC4_SET_DBPDLK0_PHY_ACCESS); + + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR0); + + /* DDR_DXCCR */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DXCCR); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DXCCR); + + /* DDR_PGCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_PGCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_PGCR1); + + /* DDR_ACIOCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR1); + + /* DDR_ACIOCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR3); + + /* DDR_ACIOCR5 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR5); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR5); + + /* DDR_DX0GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR2); + + /* DDR_DX1GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR2); + + /* DDR_DX2GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR2); + + /* DDR_DX3GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR2); + + /* DDR_ZQCR */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ZQCR); + + mmio_write_32(DBSC4_REG_DBPDRGD0, ddr_md == 0 ? + DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 : + DBSC4_SET_DBPDRGD0_ZQCR_MD19_1); + + /* DDR_DX0GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR0); + + /* DDR_DX1GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR0); + + /* DDR_DX2GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR0); + + /* DDR_DX3GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR0); + + /* DDR_DX0GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR1); + + /* DDR_DX1GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR1); + + /* DDR_DX2GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR1); + + /* DDR_DX3GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR1); + + /* DDR_DX0GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR3); + + /* DDR_DX1GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR3); + + /* DDR_DX2GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR3); + + /* DDR_DX3GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR3); + + /* Write disable */ + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); +} + +void __attribute__ ((section(".system_ram"))) __attribute__ ((noinline)) +rcar_pwrc_go_suspend_to_ram(void) +{ +#if PMIC_ROHM_BD9571 + int32_t rc = -1, qllm = -1; + uint8_t mode; + uint32_t i; +#endif + uint32_t reg, product; + + reg = mmio_read_32(RCAR_PRR); + product = reg & PRR_PRODUCT_MASK; + + if (product != PRR_PRODUCT_E3) + rcar_pwrc_set_self_refresh(); + else + rcar_pwrc_set_self_refresh_e3(); + +#if PMIC_ROHM_BD9571 + /* Set QLLM Cnt Disable */ + for (i = 0; (i < PMIC_RETRY_MAX) && (qllm != 0); i++) + qllm = rcar_iic_dvfs_send(PMIC, PMIC_QLLM_CNT, 0); + + /* Set trigger of power down to PMIV */ + for (i = 0; (i < PMIC_RETRY_MAX) && (rc != 0) && (qllm == 0); i++) { + rc = rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode); + if (rc == 0) { + mode |= BIT_BKUP_CTRL_OUT; + rc = rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode); + } + } +#endif + wfi(); + + while (1) + ; +} + +void rcar_pwrc_set_suspend_to_ram(void) +{ + uintptr_t jump = (uintptr_t) &rcar_pwrc_go_suspend_to_ram; + uintptr_t stack = (uintptr_t) (DEVICE_SRAM_STACK_BASE + + DEVICE_SRAM_STACK_SIZE); + uint32_t sctlr; + + rcar_pwrc_save_timer_state(); + + /* disable MMU */ + sctlr = (uint32_t) read_sctlr_el3(); + sctlr &= (uint32_t) ~SCTLR_EL3_M_BIT; + write_sctlr_el3((uint64_t) sctlr); + + rcar_pwrc_switch_stack(jump, stack, NULL); +} + +void rcar_pwrc_init_suspend_to_ram(void) +{ +#if PMIC_ROHM_BD9571 + uint8_t mode; + + if (rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode)) + panic(); + + mode &= (uint8_t) (~BIT_BKUP_CTRL_OUT); + if (rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode)) + panic(); +#endif +} + +void rcar_pwrc_suspend_to_ram(void) +{ +#if RCAR_SYSTEM_RESET_KEEPON_DDR + int32_t error; + + error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, 0); + if (error) { + ERROR("Failed send KEEP10 init ret=%d\n", error); + return; + } +#endif + rcar_pwrc_set_suspend_to_ram(); +} +#endif + +void rcar_pwrc_code_copy_to_system_ram(void) +{ + int ret __attribute__ ((unused)); /* in assert */ + uint32_t attr; + struct device_sram_t { + uintptr_t base; + size_t len; + } sram = { + .base = (uintptr_t) DEVICE_SRAM_BASE, + .len = DEVICE_SRAM_SIZE, + }; + struct ddr_code_t { + void *base; + size_t len; + } code = { + .base = (void *) SRAM_COPY_START, + .len = SYSTEM_RAM_END - SYSTEM_RAM_START, + }; + + attr = MT_MEMORY | MT_RW | MT_SECURE | MT_EXECUTE_NEVER; + ret = xlat_change_mem_attributes(sram.base, sram.len, attr); + assert(ret == 0); + + memcpy((void *)sram.base, code.base, code.len); + flush_dcache_range((uint64_t) sram.base, code.len); + + attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE; + ret = xlat_change_mem_attributes(sram.base, sram.len, attr); + assert(ret == 0); + + /* Invalidate instruction cache */ + plat_invalidate_icache(); + dsb(); + isb(); +} + +uint32_t rcar_pwrc_get_cluster(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); + + if (reg & (1U << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) + return RCAR_CLUSTER_CA57; + + if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) + return RCAR_CLUSTER_CA53; + + return RCAR_CLUSTER_A53A57; +} + +uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr) +{ + uint32_t c = rcar_pwrc_get_cluster(); + + if (IS_A53A57(c)) { + if (mpidr & MPIDR_CLUSTER_MASK) + return RCAR_CLUSTER_CA53; + + return RCAR_CLUSTER_CA57; + } + + return c; +} + +#if RCAR_LSI == RCAR_D3 +uint32_t rcar_pwrc_get_cpu_num(uint32_t c) +{ + return 1; +} +#else +uint32_t rcar_pwrc_get_cpu_num(uint32_t c) +{ + uint32_t reg = mmio_read_32(RCAR_PRR); + uint32_t count = 0, i; + + if (IS_A53A57(c) || IS_CA53(c)) { + if (reg & (1 << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) + goto count_ca57; + + for (i = 0; i < RCAR_CA53CPU_NUM_MAX; i++) { + if (reg & (1 << (STATE_CA53_CPU + i))) + continue; + count++; + } + } + +count_ca57: + if (IS_A53A57(c) || IS_CA57(c)) { + if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) + goto done; + + for (i = 0; i < RCAR_CA57CPU_NUM_MAX; i++) { + if (reg & (1 << (STATE_CA57_CPU + i))) + continue; + count++; + } + } + +done: + return count; +} +#endif + +int32_t rcar_pwrc_cpu_on_check(u_register_t mpidr) +{ + uint64_t i; + uint64_t j; + uint64_t cpu_count; + uintptr_t reg_PSTR; + uint32_t status; + uint64_t my_cpu; + int32_t rtn; + uint32_t my_cluster_type; + const uint32_t cluster_type[PLATFORM_CLUSTER_COUNT] = { + RCAR_CLUSTER_CA53, + RCAR_CLUSTER_CA57 + }; + const uintptr_t registerPSTR[PLATFORM_CLUSTER_COUNT] = { + RCAR_CA53PSTR, + RCAR_CA57PSTR + }; + + my_cluster_type = rcar_pwrc_get_cluster(); + + rtn = 0; + my_cpu = mpidr & ((uint64_t)(MPIDR_CPU_MASK)); + for (i = 0U; i < ((uint64_t)(PLATFORM_CLUSTER_COUNT)); i++) { + cpu_count = rcar_pwrc_get_cpu_num(cluster_type[i]); + reg_PSTR = registerPSTR[i]; + for (j = 0U; j < cpu_count; j++) { + if ((my_cluster_type != cluster_type[i]) || (my_cpu != j)) { + status = mmio_read_32(reg_PSTR) >> (j * 4U); + if ((status & 0x00000003U) == 0U) { + rtn--; + } + } + } + } + + return rtn; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h b/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h new file mode 100644 index 0000000..eefa62f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PWRC_H +#define PWRC_H + +#define PPOFFR_OFF 0x0 +#define PPONR_OFF 0x4 +#define PCOFFR_OFF 0x8 +#define PWKUPR_OFF 0xc +#define PSYSR_OFF 0x10 + +#define PWKUPR_WEN (1ull << 31) + +#define PSYSR_AFF_L2 (1U << 31) +#define PSYSR_AFF_L1 (1 << 30) +#define PSYSR_AFF_L0 (1 << 29) +#define PSYSR_WEN (1 << 28) +#define PSYSR_PC (1 << 27) +#define PSYSR_PP (1 << 26) + +#define PSYSR_WK_SHIFT (24) +#define PSYSR_WK_MASK (0x3) +#define PSYSR_WK(x) (((x) >> PSYSR_WK_SHIFT) & PSYSR_WK_MASK) + +#define WKUP_COLD 0x0 +#define WKUP_RESET 0x1 +#define WKUP_PPONR 0x2 +#define WKUP_GICREQ 0x3 + +#define RCAR_INVALID (0xffffffffU) +#define PSYSR_INVALID 0xffffffff + +#define RCAR_CLUSTER_A53A57 (0U) +#define RCAR_CLUSTER_CA53 (1U) +#define RCAR_CLUSTER_CA57 (2U) + +extern u_register_t rcar_boot_mpidr; + +#ifndef __ASSEMBLER__ +void rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr); +void rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr); +void rcar_pwrc_all_disable_interrupt_wakeup(void); +void rcar_pwrc_clusteroff(u_register_t mpidr); +void rcar_pwrc_cpuoff(u_register_t mpidr); +void rcar_pwrc_cpuon(u_register_t mpidr); +int32_t rcar_pwrc_cpu_on_check(u_register_t mpidr); +void rcar_pwrc_setup(void); + +uint32_t rcar_pwrc_get_cpu_wkr(u_register_t mpidr); +uint32_t rcar_pwrc_status(u_register_t mpidr); +uint32_t rcar_pwrc_get_cluster(void); +uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr); +uint32_t rcar_pwrc_get_cpu_num(uint32_t cluster_type); +void rcar_pwrc_restore_timer_state(void); +void plat_secondary_reset(void); + +void rcar_pwrc_code_copy_to_system_ram(void); + +#if !PMIC_ROHM_BD9571 +void rcar_pwrc_system_reset(void); +#endif + +#if RCAR_SYSTEM_SUSPEND +void rcar_pwrc_go_suspend_to_ram(void); +void rcar_pwrc_set_suspend_to_ram(void); +void rcar_pwrc_init_suspend_to_ram(void); +void rcar_pwrc_suspend_to_ram(void); +#endif + +extern uint32_t rcar_pwrc_switch_stack(uintptr_t jump, uintptr_t stack, + void *arg); +#endif + +#endif /* PWRC_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/qos_reg.h b/arm-trusted-firmware/drivers/renesas/common/qos_reg.h new file mode 100644 index 0000000..f2012fa --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/qos_reg.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_REG_H +#define QOS_REG_H + +#define RCAR_QOS_NONE 3U +#define RCAR_QOS_TYPE_DEFAULT 0U + +#define RCAR_DRAM_SPLIT_LINEAR 0U +#define RCAR_DRAM_SPLIT_4CH 1U +#define RCAR_DRAM_SPLIT_2CH 2U +#define RCAR_DRAM_SPLIT_AUTO 3U +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) + +#define DBSC_BASE 0xE6790000U +#define DBSC_DBSYSCNT0 (DBSC_BASE + 0x0100U) +#define DBSC_AXARB (DBSC_BASE + 0x0800U) +#define DBSC_DBCAM0CNF1 (DBSC_BASE + 0x0904U) +#define DBSC_DBCAM0CNF2 (DBSC_BASE + 0x0908U) +#define DBSC_DBCAM0CNF3 (DBSC_BASE + 0x090CU) +#define DBSC_DBSCHCNT0 (DBSC_BASE + 0x1000U) +#define DBSC_DBSCHCNT1 (DBSC_BASE + 0x1004U) +#define DBSC_DBSCHSZ0 (DBSC_BASE + 0x1010U) +#define DBSC_DBSCHRW0 (DBSC_BASE + 0x1020U) +#define DBSC_DBSCHRW1 (DBSC_BASE + 0x1024U) +#define DBSC_DBSCHQOS00 (DBSC_BASE + 0x1030U) +#define DBSC_DBSCHQOS01 (DBSC_BASE + 0x1034U) +#define DBSC_DBSCHQOS02 (DBSC_BASE + 0x1038U) +#define DBSC_DBSCHQOS03 (DBSC_BASE + 0x103CU) +#define DBSC_DBSCHQOS40 (DBSC_BASE + 0x1070U) +#define DBSC_DBSCHQOS41 (DBSC_BASE + 0x1074U) +#define DBSC_DBSCHQOS42 (DBSC_BASE + 0x1078U) +#define DBSC_DBSCHQOS43 (DBSC_BASE + 0x107CU) +#define DBSC_DBSCHQOS90 (DBSC_BASE + 0x10C0U) +#define DBSC_DBSCHQOS91 (DBSC_BASE + 0x10C4U) +#define DBSC_DBSCHQOS92 (DBSC_BASE + 0x10C8U) +#define DBSC_DBSCHQOS93 (DBSC_BASE + 0x10CCU) +#define DBSC_DBSCHQOS120 (DBSC_BASE + 0x10F0U) +#define DBSC_DBSCHQOS121 (DBSC_BASE + 0x10F4U) +#define DBSC_DBSCHQOS122 (DBSC_BASE + 0x10F8U) +#define DBSC_DBSCHQOS123 (DBSC_BASE + 0x10FCU) +#define DBSC_DBSCHQOS130 (DBSC_BASE + 0x1100U) +#define DBSC_DBSCHQOS131 (DBSC_BASE + 0x1104U) +#define DBSC_DBSCHQOS132 (DBSC_BASE + 0x1108U) +#define DBSC_DBSCHQOS133 (DBSC_BASE + 0x110CU) +#define DBSC_DBSCHQOS140 (DBSC_BASE + 0x1110U) +#define DBSC_DBSCHQOS141 (DBSC_BASE + 0x1114U) +#define DBSC_DBSCHQOS142 (DBSC_BASE + 0x1118U) +#define DBSC_DBSCHQOS143 (DBSC_BASE + 0x111CU) +#define DBSC_DBSCHQOS150 (DBSC_BASE + 0x1120U) +#define DBSC_DBSCHQOS151 (DBSC_BASE + 0x1124U) +#define DBSC_DBSCHQOS152 (DBSC_BASE + 0x1128U) +#define DBSC_DBSCHQOS153 (DBSC_BASE + 0x112CU) +#define DBSC_SCFCTST0 (DBSC_BASE + 0x1700U) +#define DBSC_SCFCTST1 (DBSC_BASE + 0x1708U) +#define DBSC_SCFCTST2 (DBSC_BASE + 0x170CU) + +#define AXI_BASE 0xE6784000U +#define AXI_ADSPLCR0 (AXI_BASE + 0x0008U) +#define AXI_ADSPLCR1 (AXI_BASE + 0x000CU) +#define AXI_ADSPLCR2 (AXI_BASE + 0x0010U) +#define AXI_ADSPLCR3 (AXI_BASE + 0x0014U) +#define AXI_MMCR (AXI_BASE + 0x0300U) +#define ADSPLCR0_ADRMODE_DEFAULT ((uint32_t)0U << 31U) +#define ADSPLCR0_ADRMODE_GEN2 ((uint32_t)1U << 31U) +#define ADSPLCR0_SPLITSEL(x) ((uint32_t)(x) << 16U) +#define ADSPLCR0_AREA(x) ((uint32_t)(x) << 8U) +#define ADSPLCR0_SWP 0x0CU + +#define AXI_TR3CR 0xE67D100CU +#define AXI_TR4CR 0xE67D1014U + +#define QOS_BASE0 0xE67E0000U +#define QOSBW_FIX_QOS_BANK0 (QOS_BASE0 + 0x0000U) +#define QOSBW_FIX_QOS_BANK1 (QOS_BASE0 + 0x1000U) +#define QOSBW_BE_QOS_BANK0 (QOS_BASE0 + 0x2000U) +#define QOSBW_BE_QOS_BANK1 (QOS_BASE0 + 0x3000U) +#define QOSCTRL_SL_INIT (QOS_BASE0 + 0x8000U) +#define QOSCTRL_REF_ARS (QOS_BASE0 + 0x8004U) +#define QOSCTRL_STATQC (QOS_BASE0 + 0x8008U) + +#define QOS_BASE1 0xE67F0000U +#define QOSCTRL_RAS (QOS_BASE1 + 0x0000U) +#define QOSCTRL_FIXTH (QOS_BASE1 + 0x0004U) +#define QOSCTRL_RAEN (QOS_BASE1 + 0x0018U) +#define QOSCTRL_REGGD (QOS_BASE1 + 0x0020U) +#define QOSCTRL_DANN (QOS_BASE1 + 0x0030U) +#define QOSCTRL_DANT (QOS_BASE1 + 0x0038U) +#define QOSCTRL_EC (QOS_BASE1 + 0x003CU) +#define QOSCTRL_EMS (QOS_BASE1 + 0x0040U) +#define QOSCTRL_FSS (QOS_BASE1 + 0x0048U) +#define QOSCTRL_INSFC (QOS_BASE1 + 0x0050U) +#define QOSCTRL_BERR (QOS_BASE1 + 0x0054U) +#define QOSCTRL_EARLYR (QOS_BASE1 + 0x0060U) +#define QOSCTRL_RACNT0 (QOS_BASE1 + 0x0080U) +#define QOSCTRL_STATGEN0 (QOS_BASE1 + 0x0088U) + +#define GPU_ACT_GRD 0xFD820808U +#define GPU_ACT0 0xFD820800U +#define GPU_ACT1 0xFD821800U +#define GPU_ACT2 0xFD822800U +#define GPU_ACT3 0xFD823800U +#define GPU_ACT4 0xFD824800U +#define GPU_ACT5 0xFD825800U +#define GPU_ACT6 0xFD826800U +#define GPU_ACT7 0xFD827800U + +#define RT_ACT0 0xFFC50800U +#define RT_ACT1 0xFFC51800U + +#define CPU_ACT0 0xF1300800U +#define CPU_ACT1 0xF1340800U +#define CPU_ACT2 0xF1380800U +#define CPU_ACT3 0xF13C0800U + +#define RCAR_REWT_TRAINING_DISABLE 0U +#define RCAR_REWT_TRAINING_ENABLE 1U + +#define QOSWT_FIX_WTQOS_BANK0 (QOSBW_FIX_QOS_BANK0 + 0x0800U) +#define QOSWT_FIX_WTQOS_BANK1 (QOSBW_FIX_QOS_BANK1 + 0x0800U) +#define QOSWT_BE_WTQOS_BANK0 (QOSBW_BE_QOS_BANK0 + 0x0800U) +#define QOSWT_BE_WTQOS_BANK1 (QOSBW_BE_QOS_BANK1 + 0x0800U) +#define QOSWT_WTEN (QOS_BASE0 + 0x8030U) +#define QOSWT_WTREF (QOS_BASE0 + 0x8034U) +#define QOSWT_WTSET0 (QOS_BASE0 + 0x8038U) +#define QOSWT_WTSET1 (QOS_BASE0 + 0x803CU) + +#endif /* QOS_REG_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c b/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c new file mode 100644 index 0000000..fda2815 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "rcar_def.h" +#include "rom_api.h" + +typedef uint32_t(*rom_secure_boot_api_f) (uint32_t *key, uint32_t *cert, + rom_read_flash_f pFuncReadFlash); + +typedef uint32_t(*rom_get_lcs_api_f) (uint32_t *lcs); + +#define OLD_API_TABLE1 (0U) /* H3 Ver.1.0/Ver.1.1 */ +#define OLD_API_TABLE2 (1U) /* H3 Ver.2.0 */ +#define OLD_API_TABLE3 (2U) /* M3 Ver.1.0 */ +#define NEW_API_TABLE (3U) /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ +#define NEW_API_TABLE2 (4U) /* V3M WS1.0 */ +#define API_TABLE_MAX (5U) /* table max */ + /* Later than H3 Ver.2.0 */ + +static uint32_t get_table_index(void) +{ + uint32_t product; + uint32_t cut_ver; + uint32_t index; + + product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + cut_ver = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK; + + switch (product) { + case PRR_PRODUCT_H3: + if (cut_ver == PRR_PRODUCT_10) + index = OLD_API_TABLE1; + else if (cut_ver == PRR_PRODUCT_11) + index = OLD_API_TABLE1; + else if (cut_ver == PRR_PRODUCT_20) + index = OLD_API_TABLE2; + else + /* Later than H3 Ver.2.0 */ + index = NEW_API_TABLE; + break; + case PRR_PRODUCT_M3: + if (cut_ver == PRR_PRODUCT_10) + index = OLD_API_TABLE3; + else + /* M3 Ver.1.1 or later */ + index = NEW_API_TABLE; + break; + case PRR_PRODUCT_V3M: + if (cut_ver == PRR_PRODUCT_10) + /* V3M WS1.0 */ + index = NEW_API_TABLE2; + else + /* V3M WS2.0 or later */ + index = NEW_API_TABLE; + break; + default: + index = NEW_API_TABLE; + break; + } + + return index; +} + +uint32_t rcar_rom_secure_boot_api(uint32_t *key, uint32_t *cert, + rom_read_flash_f read_flash) +{ + static const uintptr_t rom_api_table[API_TABLE_MAX] = { + 0xEB10DD64U, /* H3 Ver.1.0/Ver.1.1 */ + 0xEB116ED4U, /* H3 Ver.2.0 */ + 0xEB1102FCU, /* M3 Ver.1.0 */ + 0xEB100180U, /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ + 0xEB110128U, /* V3M WS1.0 */ + }; + rom_secure_boot_api_f secure_boot; + uint32_t index; + + index = get_table_index(); + secure_boot = (rom_secure_boot_api_f) rom_api_table[index]; + + return secure_boot(key, cert, read_flash); +} + +uint32_t rcar_rom_get_lcs(uint32_t *lcs) +{ + static const uintptr_t rom_get_lcs_table[API_TABLE_MAX] = { + 0xEB10DFE0U, /* H3 Ver.1.0/Ver.1.1 */ + 0xEB117150U, /* H3 Ver.2.0 */ + 0xEB110578U, /* M3 Ver.1.0 */ + 0xEB10018CU, /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ + 0xEB1103A4U, /* V3M WS1.0 */ + }; + rom_get_lcs_api_f get_lcs; + uint32_t index; + + index = get_table_index(); + get_lcs = (rom_get_lcs_api_f) rom_get_lcs_table[index]; + + return get_lcs(lcs); +} diff --git a/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h b/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h new file mode 100644 index 0000000..1d5b03d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ROM_API_H +#define ROM_API_H + +#include + +#define SBROM_OK (0x00000000U) +#define SBROM_ILLEGAL_INPUT_PARAM_ERR (0x0B000001U) +#define SBROM_ILLEGAL_OEM_HASH_VALUE_ERR (0x0B000008U) +#define SBROM_ILLEGAL_LCS_FOR_OPERATION_ERR (0x0B000010U) +#define SBROM_HASH_NOT_PROGRAMMED_ERR (0x0B000100U) +#define SBROM_PUB_KEY_HASH_VALIDATION_FAILURE (0xF1000006U) +#define SBROM_RSA_SIG_VERIFICATION_FAILED (0xF1000007U) + +#define LCS_CM (0x0U) +#define LCS_DM (0x1U) +#define LCS_SD (0x3U) +#define LCS_SE (0x5U) +#define LCS_FA (0x7U) + +typedef uint32_t(*rom_read_flash_f) (uint64_t src, uint8_t *dst, uint32_t len); +uint32_t rcar_rom_secure_boot_api(uint32_t *key, uint32_t *cert, + rom_read_flash_f f); +uint32_t rcar_rom_get_lcs(uint32_t *lcs); + +#endif /* ROM_API_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c b/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c new file mode 100644 index 0000000..63de5b8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "rpc_registers.h" + +#define MSTPSR9_RPC_BIT (0x00020000U) +#define RPC_CMNCR_MD_BIT (0x80000000U) +#define RPC_PHYCNT_CAL BIT(31) +#define RPC_PHYCNT_STRTIM_M3V1 (0x6 << 15UL) +#define RPC_PHYCNT_STRTIM (0x7 << 15UL) + +static void rpc_enable(void) +{ + /* Enable clock supply to RPC. */ + mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, MSTPSR9_RPC_BIT); +} + +static void rpc_setup(void) +{ + uint32_t product, cut, reg, phy_strtim; + + if (mmio_read_32(RPC_CMNCR) & RPC_CMNCR_MD_BIT) + mmio_clrbits_32(RPC_CMNCR, RPC_CMNCR_MD_BIT); + + product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + cut = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK; + + if ((product == PRR_PRODUCT_M3) && (cut < PRR_PRODUCT_30)) + phy_strtim = RPC_PHYCNT_STRTIM_M3V1; + else + phy_strtim = RPC_PHYCNT_STRTIM; + + reg = mmio_read_32(RPC_PHYCNT); + reg &= ~RPC_PHYCNT_STRTIM; + reg |= phy_strtim; + mmio_write_32(RPC_PHYCNT, reg); + reg |= RPC_PHYCNT_CAL; + mmio_write_32(RPC_PHYCNT, reg); +} + +void rcar_rpc_init(void) +{ + rpc_enable(); + rpc_setup(); +} diff --git a/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h b/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h new file mode 100644 index 0000000..79aea85 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPC_REGISTERS_H +#define RPC_REGISTERS_H + +#define RPC_BASE (0xEE200000U) +#define RPC_CMNCR (RPC_BASE + 0x0000U) +#define RPC_SSLDR (RPC_BASE + 0x0004U) +#define RPC_DRCR (RPC_BASE + 0x000CU) +#define RPC_DRCMR (RPC_BASE + 0x0010U) +#define RPC_DRENR (RPC_BASE + 0x001CU) +#define RPC_SMCR (RPC_BASE + 0x0020U) +#define RPC_SMCMR (RPC_BASE + 0x0024U) +#define RPC_SMENR (RPC_BASE + 0x0030U) +#define RPC_CMNSR (RPC_BASE + 0x0048U) +#define RPC_DRDMCR (RPC_BASE + 0x0058U) +#define RPC_DRDRENR (RPC_BASE + 0x005CU) +#define RPC_PHYCNT (RPC_BASE + 0x007CU) +#define RPC_PHYINT (RPC_BASE + 0x0088U) + +#endif /* RPC_REGISTERS_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/scif/scif.S b/arm-trusted-firmware/drivers/renesas/common/scif/scif.S new file mode 100644 index 0000000..72b5b4b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/scif/scif.S @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define SCIF_INTERNAL_CLK 0 +#define SCIF_EXTARNAL_CLK 1 +#define SCIF_CLK SCIF_INTERNAL_CLK + +/* product register */ +#define PRR (0xFFF00044) +#define PRR_PRODUCT_MASK (0x00007F00) +#define PRR_CUT_MASK (0x000000FF) +#define PRR_PRODUCT_H3_VER_10 (0x00004F00) +#define PRR_PRODUCT_E3 (0x00005700) +#define PRR_PRODUCT_D3 (0x00005800) + +/* module stop */ +#define CPG_BASE (0xE6150000) +#define CPG_SMSTPCR2 (0x0138) +#define CPG_SMSTPCR3 (0x013C) +#define CPG_MSTPSR2 (0x0040) +#define CPG_MSTPSR3 (0x0048) +#define MSTP207 (1 << 7) +#define MSTP310 (1 << 10) +#define CPG_CPGWPR (0x0900) + +/* scif */ +#define SCIF0_BASE (0xE6E60000) +#define SCIF2_BASE (0xE6E88000) +#define SCIF_SCSMR (0x00) +#define SCIF_SCBRR (0x04) +#define SCIF_SCSCR (0x08) +#define SCIF_SCFTDR (0x0C) +#define SCIF_SCFSR (0x10) +#define SCIF_SCFRDR (0x14) +#define SCIF_SCFCR (0x18) +#define SCIF_SCFDR (0x1C) +#define SCIF_SCSPTR (0x20) +#define SCIF_SCLSR (0x24) +#define SCIF_DL (0x30) +#define SCIF_CKS (0x34) + +#if RCAR_LSI == RCAR_V3M +#define SCIF_BASE SCIF0_BASE +#define CPG_SMSTPCR CPG_SMSTPCR2 +#define CPG_MSTPSR CPG_MSTPSR2 +#define MSTP MSTP207 +#else +#define SCIF_BASE SCIF2_BASE +#define CPG_SMSTPCR CPG_SMSTPCR3 +#define CPG_MSTPSR CPG_MSTPSR3 +#define MSTP MSTP310 +#endif + +/* mode pin */ +#define RST_MODEMR (0xE6160060) +#define MODEMR_MD12 (0x00001000) + +#define SCSMR_CA_MASK (1 << 7) +#define SCSMR_CA_ASYNC (0x0000) +#define SCSMR_CHR_MASK (1 << 6) +#define SCSMR_CHR_8 (0x0000) +#define SCSMR_PE_MASK (1 << 5) +#define SCSMR_PE_DIS (0x0000) +#define SCSMR_STOP_MASK (1 << 3) +#define SCSMR_STOP_1 (0x0000) +#define SCSMR_CKS_MASK (3 << 0) +#define SCSMR_CKS_DIV1 (0x0000) +#define SCSMR_INIT_DATA (SCSMR_CA_ASYNC + \ + SCSMR_CHR_8 + \ + SCSMR_PE_DIS + \ + SCSMR_STOP_1 + \ + SCSMR_CKS_DIV1) +#define SCBRR_115200BPS (17) +#define SCBRR_115200BPS_D3_SSCG (16) +#define SCBRR_115200BPS_E3_SSCG (15) +#define SCBRR_230400BPS (8) + +#define SCSCR_TE_MASK (1 << 5) +#define SCSCR_TE_DIS (0x0000) +#define SCSCR_TE_EN (0x0020) +#define SCSCR_RE_MASK (1 << 4) +#define SCSCR_RE_DIS (0x0000) +#define SCSCR_RE_EN (0x0010) +#define SCSCR_CKE_MASK (3 << 0) +#define SCSCR_CKE_INT (0x0000) +#define SCSCR_CKE_BRG (0x0002) +#if SCIF_CLK == SCIF_EXTARNAL_CLK +#define SCSCR_CKE_INT_CLK (SCSCR_CKE_BRG) +#else +#define SCFSR_TEND_MASK (1 << 6) +#define SCFSR_TEND_TRANS_END (0x0040) +#define SCSCR_CKE_INT_CLK (SCSCR_CKE_INT) +#endif +#define SCFSR_INIT_DATA (0x0000) +#define SCFCR_TTRG_MASK (3 << 4) +#define SCFCR_TTRG_8 (0x0000) +#define SCFCR_TTRG_0 (0x0030) +#define SCFCR_TFRST_MASK (1 << 2) +#define SCFCR_TFRST_DIS (0x0000) +#define SCFCR_TFRST_EN (0x0004) +#define SCFCR_RFRS_MASK (1 << 1) +#define SCFCR_RFRS_DIS (0x0000) +#define SCFCR_RFRS_EN (0x0002) +#define SCFCR_INIT_DATA (SCFCR_TTRG_8) +#define SCFDR_T_MASK (0x1f << 8) +#define DL_INIT_DATA (8) +#define CKS_CKS_DIV_MASK (1 << 15) +#define CKS_CKS_DIV_CLK (0x0000) +#define CKS_XIN_MASK (1 << 14) +#define CKS_XIN_SCIF_CLK (0x0000) +#define CKS_INIT_DATA (CKS_CKS_DIV_CLK + CKS_XIN_SCIF_CLK) + + .globl console_rcar_register + .globl console_rcar_init + .globl console_rcar_putc + .globl console_rcar_flush + + /* + * ----------------------------------------------- + * int console_rcar_register( + * uintptr_t base, uint32_t clk, uint32_t baud, + * console_t *console) + * Function to initialize and register a new rcar + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_rcar_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_rcar_init + + mov x0, x6 + mov x30, x7 + finish_console_register rcar, putc=1, getc=0, flush=1 + +register_fail: + ret x7 +endfunc console_rcar_register + + /* + * int console_rcar_init(unsigned long base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_rcar_register + * and crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success + * Clobber list : x1, x2 + */ +func console_rcar_init + ldr x0, =CPG_BASE + ldr w1, [x0, #CPG_SMSTPCR] + and w1, w1, #~MSTP + mvn w2, w1 + str w2, [x0, #CPG_CPGWPR] + str w1, [x0, #CPG_SMSTPCR] +5: + ldr w1, [x0, #CPG_MSTPSR] + and w1, w1, #MSTP + cbnz w1, 5b + + ldr x0, =SCIF_BASE + /* Clear bits TE and RE in SCSCR to 0 */ + mov w1, #(SCSCR_TE_DIS + SCSCR_RE_DIS) + strh w1, [x0, #SCIF_SCSCR] + /* Set bits TFRST and RFRST in SCFCR to 1 */ + ldrh w1, [x0, #SCIF_SCFCR] + orr w1, w1, #(SCFCR_TFRST_EN + SCFCR_RFRS_EN) + strh w1, [x0, #SCIF_SCFCR] + /* + * Read flags of ER, DR, BRK, and RDF in SCFSR and those of TO and ORER + * in SCLSR, then clear them to 0 + */ + mov w1, #SCFSR_INIT_DATA + strh w1, [x0, #SCIF_SCFSR] + mov w1, #0 + strh w1, [x0, #SCIF_SCLSR] + /* Set bits CKE[1:0] in SCSCR */ + ldrh w1, [x0, #SCIF_SCSCR] + and w1, w1, #~SCSCR_CKE_MASK + mov w2, #SCSCR_CKE_INT_CLK + orr w1, w1, w2 + strh w1, [x0, #SCIF_SCSCR] + /* Set data transfer format in SCSMR */ + mov w1, #SCSMR_INIT_DATA + strh w1, [x0, #SCIF_SCSMR] + /* Set value in SCBRR */ +#if SCIF_CLK == SCIF_INTERNAL_CLK + ldr x1, =PRR + ldr w1, [x1] + and w1, w1, #(PRR_PRODUCT_MASK | PRR_CUT_MASK) + mov w2, #PRR_PRODUCT_H3_VER_10 + cmp w1, w2 + beq 3f + and w1, w1, #PRR_PRODUCT_MASK + mov w2, #PRR_PRODUCT_D3 + cmp w1, w2 + beq 5f + and w1, w1, #PRR_PRODUCT_MASK + mov w2, #PRR_PRODUCT_E3 + cmp w1, w2 + bne 4f + + /* When SSCG(MD12) on (E3) */ + ldr x1, =RST_MODEMR + ldr w1, [x1] + and w1, w1, #MODEMR_MD12 + mov w2, #MODEMR_MD12 + cmp w1, w2 + bne 4f + + /* When SSCG(MD12) on (E3) */ + mov w1, #SCBRR_115200BPS_E3_SSCG + b 2f +5: + /* In case of D3 */ + ldr x1, =RST_MODEMR + ldr w1, [x1] + and w1, w1, #MODEMR_MD12 + mov w2, #MODEMR_MD12 + cmp w1, w2 + bne 4f + + /* When SSCG(MD12) on (D3) */ + mov w1, #SCBRR_115200BPS_D3_SSCG + b 2f +4: + /* In case of H3/M3/M3N or when SSCG(MD12) is off in E3/D3 */ + mov w1, #SCBRR_115200BPS + b 2f +3: + mov w1, #SCBRR_230400BPS +2: + strb w1, [x0, SCIF_SCBRR] +#else + mov w1, #DL_INIT_DATA + strh w1, [x0, #SCIF_DL] + mov w1, #CKS_INIT_DATA + strh w1, [x0, #SCIF_CKS] +#endif + /* 1-bit interval elapsed */ + mov w1, #100 +1: + subs w1, w1, #1 + cbnz w1, 1b + /* + * Set bits RTRG[1:0], TTRG[1:0], and MCE in SCFCR + * Clear bits FRST and RFRST to 0 + */ + mov w1, #SCFCR_INIT_DATA + strh w1, [x0, #SCIF_SCFCR] + /* Set bits TE and RE in SCSCR to 1 */ + ldrh w1, [x0, #SCIF_SCSCR] + orr w1, w1, #(SCSCR_TE_EN + SCSCR_RE_EN) + strh w1, [x0, #SCIF_SCSCR] + mov x0, #1 + + ret +endfunc console_rcar_init + + /* + * int console_rcar_putc(int c, unsigned int base_addr) + * 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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + */ +func console_rcar_putc + ldr x1, =SCIF_BASE + cmp w0, #0xA + /* Prepend '\r' to '\n' */ + bne 2f +1: + /* Check if the transmit FIFO is full */ + ldrh w2, [x1, #SCIF_SCFDR] + ubfx w2, w2, #8, #5 + cmp w2, #16 + bcs 1b + mov w2, #0x0D + strb w2, [x1, #SCIF_SCFTDR] +2: + /* Check if the transmit FIFO is full */ + ldrh w2, [x1, #SCIF_SCFDR] + ubfx w2, w2, #8, #5 + cmp w2, #16 + bcs 2b + strb w0, [x1, #SCIF_SCFTDR] + + /* Clear TEND flag */ + ldrh w2, [x1, #SCIF_SCFSR] + and w2, w2, #~SCFSR_TEND_MASK + strh w2, [x1, #SCIF_SCFSR] + + ret +endfunc console_rcar_putc + + /* + * void console_rcar_flush(void) + * Function to force a write of all buffered + * data that hasn't been output. It returns void + * Clobber list : x0, x1 + */ +func console_rcar_flush + ldr x0, =SCIF_BASE +1: + /* Check TEND flag */ + ldrh w1, [x0, #SCIF_SCFSR] + and w1, w1, #SCFSR_TEND_MASK + cmp w1, #SCFSR_TEND_TRANS_END + bne 1b + + ldr x0, =SCIF_BASE + ldrh w1, [x0, #SCIF_SCSCR] + and w1, w1, #~(SCSCR_TE_EN + SCSCR_RE_EN) + strh w1, [x0, #SCIF_SCSCR] + + ret +endfunc console_rcar_flush diff --git a/arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c b/arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c new file mode 100644 index 0000000..29ef6f4 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "rcar_def.h" + +extern void gicd_set_icenabler(uintptr_t base, unsigned int id); + +#define RST_BASE (0xE6160000U) +#define RST_WDTRSTCR (RST_BASE + 0x0054U) +#define SWDT_BASE (0xE6030000U) +#define SWDT_WTCNT (SWDT_BASE + 0x0000U) +#define SWDT_WTCSRA (SWDT_BASE + 0x0004U) +#define SWDT_WTCSRB (SWDT_BASE + 0x0008U) +#define SWDT_GICD_BASE (0xF1010000U) +#define SWDT_GICC_BASE (0xF1020000U) +#define SWDT_GICD_CTLR (SWDT_GICD_BASE + 0x0000U) +#define SWDT_GICD_IGROUPR (SWDT_GICD_BASE + 0x0080U) +#define SWDT_GICD_ISPRIORITYR (SWDT_GICD_BASE + 0x0400U) +#define SWDT_GICC_CTLR (SWDT_GICC_BASE + 0x0000U) +#define SWDT_GICC_PMR (SWDT_GICC_BASE + 0x0004U) +#define SWDT_GICD_ITARGETSR (SWDT_GICD_BASE + 0x0800U) +#define IGROUPR_NUM (16U) +#define ISPRIORITY_NUM (128U) +#define ITARGET_MASK (0x03U) + +#define WDTRSTCR_UPPER_BYTE (0xA55A0000U) +#define WTCSRA_UPPER_BYTE (0xA5A5A500U) +#define WTCSRB_UPPER_BYTE (0xA5A5A500U) +#define WTCNT_UPPER_BYTE (0x5A5A0000U) +#define WTCNT_RESET_VALUE (0xF488U) +#define WTCSRA_BIT_CKS (0x0007U) +#define WTCSRB_BIT_CKS (0x003FU) +#define SWDT_RSTMSK (1U << 1U) +#define WTCSRA_WOVFE (1U << 3U) +#define WTCSRA_WRFLG (1U << 5U) +#define SWDT_ENABLE (1U << 7U) + +#define WDTRSTCR_MASK_ALL (0x0000FFFFU) +#define WTCSRA_MASK_ALL (0x000000FFU) +#define WTCNT_INIT_DATA (WTCNT_UPPER_BYTE + WTCNT_RESET_VALUE) +#define WTCSRA_INIT_DATA (WTCSRA_UPPER_BYTE + 0x0FU) +#define WTCSRB_INIT_DATA (WTCSRB_UPPER_BYTE + 0x21U) + +#if RCAR_LSI == RCAR_D3 +#define WTCNT_COUNT_8p13k (0x10000U - 40760U) +#else +#define WTCNT_COUNT_8p13k (0x10000U - 40687U) +#endif +#define WTCNT_COUNT_8p13k_H3VER10 (0x10000U - 20343U) +#define WTCNT_COUNT_8p22k (0x10000U - 41115U) +#define WTCNT_COUNT_7p81k (0x10000U - 39062U) +#define WTCSRA_CKS_DIV16 (0x00000002U) + +static void swdt_disable(void) +{ + uint32_t rmsk; + + rmsk = mmio_read_32(RST_WDTRSTCR) & WDTRSTCR_MASK_ALL; + rmsk |= SWDT_RSTMSK; + mmio_write_32(RST_WDTRSTCR, WDTRSTCR_UPPER_BYTE | rmsk); + + mmio_write_32(SWDT_WTCNT, WTCNT_INIT_DATA); + mmio_write_32(SWDT_WTCSRA, WTCSRA_INIT_DATA); + mmio_write_32(SWDT_WTCSRB, WTCSRB_INIT_DATA); + + /* Set the interrupt clear enable register */ + gicd_set_icenabler(RCAR_GICD_BASE, ARM_IRQ_SEC_WDT); +} + +void rcar_swdt_init(void) +{ + uint32_t rmsk, sr; +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RZ_G2E) + uint32_t reg, val, product_cut, chk_data; + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + + reg = mmio_read_32(RCAR_MODEMR); + chk_data = reg & CHECK_MD13_MD14; +#endif + /* stop watchdog */ + if (mmio_read_32(SWDT_WTCSRA) & SWDT_ENABLE) + mmio_write_32(SWDT_WTCSRA, WTCSRA_UPPER_BYTE); + + mmio_write_32(SWDT_WTCSRA, WTCSRA_UPPER_BYTE | + WTCSRA_WOVFE | WTCSRA_CKS_DIV16); + +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E) + mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_7p81k); +#elif (RCAR_LSI == RCAR_D3) + mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_8p13k); +#else + val = WTCNT_UPPER_BYTE; + + switch (chk_data) { + case MD14_MD13_TYPE_0: + case MD14_MD13_TYPE_2: + val |= WTCNT_COUNT_8p13k; + break; + case MD14_MD13_TYPE_1: + val |= WTCNT_COUNT_8p22k; + break; + case MD14_MD13_TYPE_3: + val |= product_cut == (PRR_PRODUCT_H3 | PRR_PRODUCT_10) ? + WTCNT_COUNT_8p13k_H3VER10 : WTCNT_COUNT_8p13k; + break; + default: + ERROR("MODEMR ERROR value = %x\n", chk_data); + panic(); + break; + } + + mmio_write_32(SWDT_WTCNT, val); +#endif + rmsk = mmio_read_32(RST_WDTRSTCR) & WDTRSTCR_MASK_ALL; + rmsk |= SWDT_RSTMSK | WDTRSTCR_UPPER_BYTE; + mmio_write_32(RST_WDTRSTCR, rmsk); + + while ((mmio_read_8(SWDT_WTCSRA) & WTCSRA_WRFLG) != 0U) + ; + + /* Start the System WatchDog Timer */ + sr = mmio_read_32(SWDT_WTCSRA) & WTCSRA_MASK_ALL; + mmio_write_32(SWDT_WTCSRA, (WTCSRA_UPPER_BYTE | sr | SWDT_ENABLE)); +} + +void rcar_swdt_release(void) +{ + uintptr_t itarget = SWDT_GICD_ITARGETSR + + (ARM_IRQ_SEC_WDT & ~ITARGET_MASK); + uint32_t i; + + /* Disable FIQ interrupt */ + write_daifset(DAIF_FIQ_BIT); + /* FIQ interrupts are not taken to EL3 */ + write_scr_el3(read_scr_el3() & ~SCR_FIQ_BIT); + + swdt_disable(); + gicv2_cpuif_disable(); + + for (i = 0; i < IGROUPR_NUM; i++) + mmio_write_32(SWDT_GICD_IGROUPR + i * 4, 0U); + + for (i = 0; i < ISPRIORITY_NUM; i++) + mmio_write_32(SWDT_GICD_ISPRIORITYR + i * 4, 0U); + + mmio_write_32(itarget, 0U); + mmio_write_32(SWDT_GICD_CTLR, 0U); + mmio_write_32(SWDT_GICC_CTLR, 0U); + mmio_write_32(SWDT_GICC_PMR, 0U); +} + +void rcar_swdt_exec(uint64_t p) +{ + gicv2_end_of_interrupt(ARM_IRQ_SEC_WDT); + rcar_swdt_release(); + ERROR("\n"); + ERROR("System WDT overflow, occurred address is %p\n", (void *)p); + panic(); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/board/board.c b/arm-trusted-firmware/drivers/renesas/rcar/board/board.c new file mode 100644 index 0000000..dbbaed6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/board/board.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include "board.h" + +#ifndef BOARD_DEFAULT +#if (RCAR_LSI == RCAR_D3) +#define BOARD_DEFAULT (BOARD_DRAAK << BOARD_CODE_SHIFT) +#elif (RCAR_LSI == RCAR_E3) +#define BOARD_DEFAULT (BOARD_EBISU << BOARD_CODE_SHIFT) +#elif (RCAR_LSI == RCAR_V3M) +#define BOARD_DEFAULT (BOARD_EAGLE << BOARD_CODE_SHIFT) +#else +#define BOARD_DEFAULT (BOARD_SALVATOR_X << BOARD_CODE_SHIFT) +#endif +#endif + +#define BOARD_CODE_MASK (0xF8) +#define BOARD_REV_MASK (0x07) +#define BOARD_CODE_SHIFT (0x03) +#define BOARD_ID_UNKNOWN (0xFF) + +#define SXS_ID { 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define SX_ID { 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define SKP_ID { 0x10U, 0x10U, 0x20U, 0x21U, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define SK_ID { 0x10U, 0x30U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define EB4_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define EB_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define DR_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define EA_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define KK_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } + +const char *g_board_tbl[] = { + [BOARD_STARTER_KIT_PRE] = "Starter Kit Premier", + [BOARD_STARTER_KIT] = "Starter Kit", + [BOARD_SALVATOR_XS] = "Salvator-XS", + [BOARD_SALVATOR_X] = "Salvator-X", + [BOARD_EBISU_4D] = "Ebisu-4D", + [BOARD_KRIEK] = "Kriek", + [BOARD_EBISU] = "Ebisu", + [BOARD_DRAAK] = "Draak", + [BOARD_EAGLE] = "Eagle", + [BOARD_UNKNOWN] = "unknown" +}; + +int32_t rcar_get_board_type(uint32_t *type, uint32_t *rev) +{ + int32_t ret = 0; + const uint8_t board_tbl[][8] = { + [BOARD_STARTER_KIT_PRE] = SKP_ID, + [BOARD_SALVATOR_XS] = SXS_ID, + [BOARD_STARTER_KIT] = SK_ID, + [BOARD_SALVATOR_X] = SX_ID, + [BOARD_EBISU_4D] = EB4_ID, + [BOARD_EBISU] = EB_ID, + [BOARD_DRAAK] = DR_ID, + [BOARD_EAGLE] = EA_ID, + [BOARD_KRIEK] = KK_ID, + }; + static uint8_t board_id = BOARD_ID_UNKNOWN; + + if (board_id != BOARD_ID_UNKNOWN) + goto get_type; + +#if PMIC_ROHM_BD9571 + /* Board ID detection from EEPROM */ + ret = rcar_iic_dvfs_receive(EEPROM, BOARD_ID, &board_id); + if (ret) { + board_id = BOARD_ID_UNKNOWN; + goto get_type; + } + + if (board_id == BOARD_ID_UNKNOWN) + board_id = BOARD_DEFAULT; +#else + board_id = BOARD_DEFAULT; +#endif + +get_type: + *type = ((uint32_t) board_id & BOARD_CODE_MASK) >> BOARD_CODE_SHIFT; + + if (*type >= ARRAY_SIZE(board_tbl)) { + /* no revision information, set Rev0.0. */ + *rev = 0; + return ret; + } + + *rev = board_tbl[*type][(uint8_t) (board_id & BOARD_REV_MASK)]; + + return ret; +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/board/board.h b/arm-trusted-firmware/drivers/renesas/rcar/board/board.h new file mode 100644 index 0000000..51a8e30 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/board/board.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_H +#define BOARD_H + +#define BOARD_SALVATOR_X (0x00) +#define BOARD_KRIEK (0x01) +#define BOARD_STARTER_KIT (0x02) +#define BOARD_SALVATOR_XS (0x04) +#define BOARD_EBISU (0x08) +#define BOARD_STARTER_KIT_PRE (0x0B) +#define BOARD_EBISU_4D (0x0DU) +#define BOARD_DRAAK (0x0EU) +#define BOARD_EAGLE (0x0FU) +#define BOARD_UNKNOWN (BOARD_EAGLE + 1U) + +#define BOARD_REV_UNKNOWN (0xFF) + +extern const char *g_board_tbl[]; + +/************************************************************************ + * Revisions are expressed in 8 bits. + * The upper 4 bits are major version. + * The lower 4 bits are minor version. + ************************************************************************/ +#define GET_BOARD_MAJOR(a) ((uint32_t)(a) >> 0x4) +#define GET_BOARD_MINOR(a) ((uint32_t)(a) & 0xF) +#define GET_BOARD_NAME(a) (g_board_tbl[(a)]) + +int32_t rcar_get_board_type(uint32_t *type, uint32_t *rev); + +#endif /* BOARD_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c b/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c new file mode 100644 index 0000000..5ffb2e1 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "ulcb_cpld.h" + +#define SCLK 8 /* GP_6_8 */ +#define SSTBZ 3 /* GP_2_3 */ +#define MOSI 7 /* GP_6_7 */ + +#define CPLD_ADDR_RESET 0x80 /* RW */ + +/* LSI Multiplexed Pin Setting Mask Register */ +#define PFC_PMMR 0xE6060000 + +/* General output registers */ +#define GPIO_OUTDT2 0xE6052008 +#define GPIO_OUTDT6 0xE6055408 + +/* General input/output switching registers */ +#define GPIO_INOUTSEL2 0xE6052004 +#define GPIO_INOUTSEL6 0xE6055404 + +/* General IO/Interrupt Switching Register */ +#define GPIO_IOINTSEL6 0xE6055400 + +/* GPIO/perihperal function select */ +#define PFC_GPSR2 0xE6060108 +#define PFC_GPSR6 0xE6060118 + +static void gpio_set_value(uint32_t addr, uint8_t gpio, uint32_t val) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + if (val) + reg |= (1 << gpio); + else + reg &= ~(1 << gpio); + mmio_write_32(addr, reg); +} + +static void gpio_direction_output(uint32_t addr, uint8_t gpio) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg |= (1 << gpio); + mmio_write_32(addr, reg); +} + +static void gpio_pfc(uint32_t addr, uint8_t gpio) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg &= ~(1 << gpio); + mmio_write_32(PFC_PMMR, ~reg); + mmio_write_32(addr, reg); +} + +static void cpld_write(uint8_t addr, uint32_t data) +{ + int i; + + for (i = 0; i < 32; i++) { + /* MSB first */ + gpio_set_value(GPIO_OUTDT6, MOSI, data & (1U << 31)); + gpio_set_value(GPIO_OUTDT6, SCLK, 1); + data <<= 1; + gpio_set_value(GPIO_OUTDT6, SCLK, 0); + } + + for (i = 0; i < 8; i++) { + /* MSB first */ + gpio_set_value(GPIO_OUTDT6, MOSI, addr & 0x80); + gpio_set_value(GPIO_OUTDT6, SCLK, 1); + addr <<= 1; + gpio_set_value(GPIO_OUTDT6, SCLK, 0); + } + + /* WRITE */ + gpio_set_value(GPIO_OUTDT6, MOSI, 1); + gpio_set_value(GPIO_OUTDT2, SSTBZ, 0); + gpio_set_value(GPIO_OUTDT6, SCLK, 1); + gpio_set_value(GPIO_OUTDT6, SCLK, 0); + gpio_set_value(GPIO_OUTDT2, SSTBZ, 1); +} + +static void cpld_init(void) +{ + gpio_pfc(PFC_GPSR6, SCLK); + gpio_pfc(PFC_GPSR2, SSTBZ); + gpio_pfc(PFC_GPSR6, MOSI); + + gpio_set_value(GPIO_IOINTSEL6, SCLK, 0); + gpio_set_value(GPIO_OUTDT6, SCLK, 0); + gpio_set_value(GPIO_OUTDT2, SSTBZ, 1); + gpio_set_value(GPIO_OUTDT6, MOSI, 0); + + gpio_direction_output(GPIO_INOUTSEL6, SCLK); + gpio_direction_output(GPIO_INOUTSEL2, SSTBZ); + gpio_direction_output(GPIO_INOUTSEL6, MOSI); +} + +void rcar_cpld_reset_cpu(void) +{ + cpld_init(); + + cpld_write(CPLD_ADDR_RESET, 1); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h b/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h new file mode 100644 index 0000000..1616d71 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_ULCB_CPLD_H__ +#define RCAR_ULCB_CPLD_H__ + +extern void rcar_cpld_reset_cpu(void); + +#endif /* RCAR_ULCB_CPLD_H__ */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c new file mode 100644 index 0000000..aaa3b43 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "pfc_init_d3.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +/* PFC */ +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1_TANS BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0_TANS BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_HDMI1_CEC BIT(3) +#define GPSR7_HDMI0_CEC BIT(2) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_HDMI0_CEC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_HDMI1_CEC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_d3(void) +{ + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, 0x00000000U); + pfc_reg_write(PFC_MOD_SEL1, 0x00000000U); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, 0x00000001U); + pfc_reg_write(PFC_IPSR1, 0x00000000U); + pfc_reg_write(PFC_IPSR2, 0x00000000U); + pfc_reg_write(PFC_IPSR3, 0x00000000U); + pfc_reg_write(PFC_IPSR4, 0x00002000U); + pfc_reg_write(PFC_IPSR5, 0x00000000U); + pfc_reg_write(PFC_IPSR6, 0x00000000U); + pfc_reg_write(PFC_IPSR7, 0x00000000U); + pfc_reg_write(PFC_IPSR8, 0x11003301U); + pfc_reg_write(PFC_IPSR9, 0x11111111U); + pfc_reg_write(PFC_IPSR10, 0x00020000U); + pfc_reg_write(PFC_IPSR11, 0x40001110U); + pfc_reg_write(PFC_IPSR12, 0x00000000U); + pfc_reg_write(PFC_IPSR13, 0x00000000U); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, 0x0000001FU); + pfc_reg_write(PFC_GPSR1, 0x3FFFFFFFU); + pfc_reg_write(PFC_GPSR2, 0xFFFFFFFFU); + pfc_reg_write(PFC_GPSR3, 0x000003FFU); + pfc_reg_write(PFC_GPSR4, 0xFC7F0F7EU); + pfc_reg_write(PFC_GPSR5, 0x001BFFFBU); + pfc_reg_write(PFC_GPSR6, 0x00003FFFU); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, 0xC00FFFFFU); + pfc_reg_write(PFC_POCCTRL2, 0XFFFFFFFEU); + pfc_reg_write(PFC_TDSELCTRL0, 0x00000000U); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x0047C1A2U); + pfc_reg_write(PFC_PUD1, 0x4E13ABFFU); + pfc_reg_write(PFC_PUD2, 0xFFFFFFFFU); + pfc_reg_write(PFC_PUD3, 0xFF0FFFFFU); + pfc_reg_write(PFC_PUD4, 0xE0000000U); + pfc_reg_write(PFC_PUD5, 0x60000000U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000000U); + pfc_reg_write(PFC_PUEN1, 0x00000000U); + pfc_reg_write(PFC_PUEN2, 0x00000000U); + pfc_reg_write(PFC_PUEN3, 0x000F008CU); + pfc_reg_write(PFC_PUEN4, 0x00000000U); + pfc_reg_write(PFC_PUEN5, 0x00000000U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000000U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL3, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00802000U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL6, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h new file mode 100644 index 0000000..b7b1754 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_D3_H +#define PFC_INIT_D3_H + +void pfc_init_d3(void); + +#endif /* PFC_INIT_D3_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c new file mode 100644 index 0000000..bd0048e --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ +#include +#include "pfc_init_e3.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +/* PFC */ +#define GPSR0_SDA4 BIT(17) +#define GPSR0_SCL4 BIT(16) +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_WE0 BIT(22) +#define GPSR1_CS0 BIT(21) +#define GPSR1_CLKOUT BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_BIT27_REVERSED BIT(27) +#define GPSR2_BIT26_REVERSED BIT(26) +#define GPSR2_EX_WAIT0 BIT(25) +#define GPSR2_RD_WR BIT(24) +#define GPSR2_RD BIT(23) +#define GPSR2_BS BIT(22) +#define GPSR2_AVB_PHY_INT BIT(21) +#define GPSR2_AVB_TXCREFCLK BIT(20) +#define GPSR2_AVB_RD3 BIT(19) +#define GPSR2_AVB_RD2 BIT(18) +#define GPSR2_AVB_RD1 BIT(17) +#define GPSR2_AVB_RD0 BIT(16) +#define GPSR2_AVB_RXC BIT(15) +#define GPSR2_AVB_RX_CTL BIT(14) +#define GPSR2_RPC_RESET BIT(13) +#define GPSR2_RPC_RPC_INT BIT(12) +#define GPSR2_QSPI1_SSL BIT(11) +#define GPSR2_QSPI1_IO3 BIT(10) +#define GPSR2_QSPI1_IO2 BIT(9) +#define GPSR2_QSPI1_MISO_IO1 BIT(8) +#define GPSR2_QSPI1_MOSI_IO0 BIT(7) +#define GPSR2_QSPI1_SPCLK BIT(6) +#define GPSR2_QSPI0_SSL BIT(5) +#define GPSR2_QSPI0_IO3 BIT(4) +#define GPSR2_QSPI0_IO2 BIT(3) +#define GPSR2_QSPI0_MISO_IO1 BIT(2) +#define GPSR2_QSPI0_MOSI_IO0 BIT(1) +#define GPSR2_QSPI0_SPCLK BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(10) +#define GPSR4_SD3_DAT7 BIT(9) +#define GPSR4_SD3_DAT6 BIT(8) +#define GPSR4_SD3_DAT5 BIT(7) +#define GPSR4_SD3_DAT4 BIT(6) +#define GPSR4_SD3_DAT3 BIT(5) +#define GPSR4_SD3_DAT2 BIT(4) +#define GPSR4_SD3_DAT1 BIT(3) +#define GPSR4_SD3_DAT0 BIT(2) +#define GPSR4_SD3_CMD BIT(1) +#define GPSR4_SD3_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(19) +#define GPSR5_MLB_SIG BIT(18) +#define GPSR5_MLB_CLK BIT(17) +#define GPSR5_SSI_SDATA9 BIT(16) +#define GPSR5_MSIOF0_SS2 BIT(15) +#define GPSR5_MSIOF0_SS1 BIT(14) +#define GPSR5_MSIOF0_SYNC BIT(13) +#define GPSR5_MSIOF0_TXD BIT(12) +#define GPSR5_MSIOF0_RXD BIT(11) +#define GPSR5_MSIOF0_SCK BIT(10) +#define GPSR5_RX2_A BIT(9) +#define GPSR5_TX2_A BIT(8) +#define GPSR5_SCK2_A BIT(7) +#define GPSR5_TX1 BIT(6) +#define GPSR5_RX1 BIT(5) +#define GPSR5_RTS0_A BIT(4) +#define GPSR5_CTS0_A BIT(3) +#define GPSR5_TX0_A BIT(2) +#define GPSR5_RX0_A BIT(1) +#define GPSR5_SCK0_A BIT(0) +#define GPSR6_USB30_PWEN BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_USB30_OVC BIT(9) +#define GPSR6_AUDIO_CLKA BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS349 BIT(6) +#define GPSR6_SSI_SCK349 BIT(5) +#define GPSR6_SSI_SDATA2 BIT(4) +#define GPSR6_SSI_SDATA1 BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS01239 BIT(1) +#define GPSR6_SSI_SCK01239 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POCCTRL0_MASK (0x0007F000U) +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define POCCTRL2_MASK (0xFFFFFFFEU) +#define POC2_VREF_33V BIT(0) + +#define MOD_SEL0_ADGB_A ((uint32_t)0U << 29U) +#define MOD_SEL0_ADGB_B ((uint32_t)1U << 29U) +#define MOD_SEL0_ADGB_C ((uint32_t)2U << 29U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 28U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 28U) +#define MOD_SEL0_FM_A ((uint32_t)0U << 26U) +#define MOD_SEL0_FM_B ((uint32_t)1U << 26U) +#define MOD_SEL0_FM_C ((uint32_t)2U << 26U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 25U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 25U) +#define MOD_SEL0_HSCIF0_A ((uint32_t)0U << 24U) +#define MOD_SEL0_HSCIF0_B ((uint32_t)1U << 24U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 23U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 23U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 22U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_I2C1_C ((uint32_t)2U << 20U) +#define MOD_SEL0_I2C1_D ((uint32_t)3U << 20U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 17U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 17U) +#define MOD_SEL0_I2C2_C ((uint32_t)2U << 17U) +#define MOD_SEL0_I2C2_D ((uint32_t)3U << 17U) +#define MOD_SEL0_I2C2_E ((uint32_t)4U << 17U) +#define MOD_SEL0_NDFC_A ((uint32_t)0U << 16U) +#define MOD_SEL0_NDFC_B ((uint32_t)1U << 16U) +#define MOD_SEL0_PWM0_A ((uint32_t)0U << 15U) +#define MOD_SEL0_PWM0_B ((uint32_t)1U << 15U) +#define MOD_SEL0_PWM1_A ((uint32_t)0U << 14U) +#define MOD_SEL0_PWM1_B ((uint32_t)1U << 14U) +#define MOD_SEL0_PWM2_A ((uint32_t)0U << 12U) +#define MOD_SEL0_PWM2_B ((uint32_t)1U << 12U) +#define MOD_SEL0_PWM2_C ((uint32_t)2U << 12U) +#define MOD_SEL0_PWM3_A ((uint32_t)0U << 10U) +#define MOD_SEL0_PWM3_B ((uint32_t)1U << 10U) +#define MOD_SEL0_PWM3_C ((uint32_t)2U << 10U) +#define MOD_SEL0_PWM4_A ((uint32_t)0U << 9U) +#define MOD_SEL0_PWM4_B ((uint32_t)1U << 9U) +#define MOD_SEL0_PWM5_A ((uint32_t)0U << 8U) +#define MOD_SEL0_PWM5_B ((uint32_t)1U << 8U) +#define MOD_SEL0_PWM6_A ((uint32_t)0U << 7U) +#define MOD_SEL0_PWM6_B ((uint32_t)1U << 7U) +#define MOD_SEL0_REMOCON_A ((uint32_t)0U << 5U) +#define MOD_SEL0_REMOCON_B ((uint32_t)1U << 5U) +#define MOD_SEL0_REMOCON_C ((uint32_t)2U << 5U) +#define MOD_SEL0_SCIF_A ((uint32_t)0U << 4U) +#define MOD_SEL0_SCIF_B ((uint32_t)1U << 4U) +#define MOD_SEL0_SCIF0_A ((uint32_t)0U << 3U) +#define MOD_SEL0_SCIF0_B ((uint32_t)1U << 3U) +#define MOD_SEL0_SCIF2_A ((uint32_t)0U << 2U) +#define MOD_SEL0_SCIF2_B ((uint32_t)1U << 2U) +#define MOD_SEL0_SPEED_PULSE_IF_A ((uint32_t)0U << 0U) +#define MOD_SEL0_SPEED_PULSE_IF_B ((uint32_t)1U << 0U) +#define MOD_SEL0_SPEED_PULSE_IF_C ((uint32_t)2U << 0U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 31U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 31U) +#define MOD_SEL1_SSI2_A ((uint32_t)0U << 30U) +#define MOD_SEL1_SSI2_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 29U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 29U) +#define MOD_SEL1_USB20_CH0_A ((uint32_t)0U << 28U) +#define MOD_SEL1_USB20_CH0_B ((uint32_t)1U << 28U) +#define MOD_SEL1_DRIF2_A ((uint32_t)0U << 26U) +#define MOD_SEL1_DRIF2_B ((uint32_t)1U << 26U) +#define MOD_SEL1_DRIF3_A ((uint32_t)0U << 25U) +#define MOD_SEL1_DRIF3_B ((uint32_t)1U << 25U) +#define MOD_SEL1_HSCIF3_A ((uint32_t)0U << 22U) +#define MOD_SEL1_HSCIF3_B ((uint32_t)1U << 22U) +#define MOD_SEL1_HSCIF3_C ((uint32_t)2U << 22U) +#define MOD_SEL1_HSCIF3_D ((uint32_t)3U << 22U) +#define MOD_SEL1_HSCIF3_E ((uint32_t)4U << 22U) +#define MOD_SEL1_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL1_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL1_HSCIF4_C ((uint32_t)2U << 19U) +#define MOD_SEL1_HSCIF4_D ((uint32_t)3U << 19U) +#define MOD_SEL1_HSCIF4_E ((uint32_t)4U << 19U) +#define MOD_SEL1_I2C6_A ((uint32_t)0U << 18U) +#define MOD_SEL1_I2C6_B ((uint32_t)1U << 18U) +#define MOD_SEL1_I2C7_A ((uint32_t)0U << 17U) +#define MOD_SEL1_I2C7_B ((uint32_t)1U << 17U) +#define MOD_SEL1_MSIOF2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_MSIOF2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_MSIOF3_A ((uint32_t)0U << 15U) +#define MOD_SEL1_MSIOF3_B ((uint32_t)1U << 15U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF3_C ((uint32_t)2U << 13U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 11U) +#define MOD_SEL1_SCIF5_A ((uint32_t)0U << 9U) +#define MOD_SEL1_SCIF5_B ((uint32_t)1U << 9U) +#define MOD_SEL1_SCIF5_C ((uint32_t)2U << 9U) +#define MOD_SEL1_VIN4_A ((uint32_t)0U << 8U) +#define MOD_SEL1_VIN4_B ((uint32_t)1U << 8U) +#define MOD_SEL1_VIN5_A ((uint32_t)0U << 7U) +#define MOD_SEL1_VIN5_B ((uint32_t)1U << 7U) +#define MOD_SEL1_ADGC_A ((uint32_t)0U << 5U) +#define MOD_SEL1_ADGC_B ((uint32_t)1U << 5U) +#define MOD_SEL1_ADGC_C ((uint32_t)2U << 5U) +#define MOD_SEL1_SSI9_A ((uint32_t)0U << 4U) +#define MOD_SEL1_SSI9_B ((uint32_t)1U << 4U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_e3(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_ADGB_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_FM_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF0_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_NDFC_A + | MOD_SEL0_PWM0_A + | MOD_SEL0_PWM1_A + | MOD_SEL0_PWM2_A + | MOD_SEL0_PWM3_A + | MOD_SEL0_PWM4_A + | MOD_SEL0_PWM5_A + | MOD_SEL0_PWM6_A + | MOD_SEL0_REMOCON_A + | MOD_SEL0_SCIF_A + | MOD_SEL0_SCIF0_A + | MOD_SEL0_SCIF2_A + | MOD_SEL0_SPEED_PULSE_IF_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_SIMCARD_A + | MOD_SEL1_SSI2_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_USB20_CH0_B + | MOD_SEL1_DRIF2_A + | MOD_SEL1_DRIF3_A + | MOD_SEL1_HSCIF3_A + | MOD_SEL1_HSCIF4_A + | MOD_SEL1_I2C6_A + | MOD_SEL1_I2C7_A + | MOD_SEL1_MSIOF2_A + | MOD_SEL1_MSIOF3_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF5_A + | MOD_SEL1_VIN4_A + | MOD_SEL1_VIN5_A + | MOD_SEL1_ADGC_A + | MOD_SEL1_SSI9_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) /* QSPI1_MISO/IO1 */ + | IPSR_24_FUNC(0) /* QSPI1_MOSI/IO0 */ + | IPSR_20_FUNC(0) /* QSPI1_SPCLK */ + | IPSR_16_FUNC(0) /* QSPI0_IO3 */ + | IPSR_12_FUNC(0) /* QSPI0_IO2 */ + | IPSR_8_FUNC(0) /* QSPI0_MISO/IO1 */ + | IPSR_4_FUNC(0) /* QSPI0_MOSI/IO0 */ + | IPSR_0_FUNC(0)); /* QSPI0_SPCLK */ + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(0) /* AVB_RD2 */ + | IPSR_24_FUNC(0) /* AVB_RD1 */ + | IPSR_20_FUNC(0) /* AVB_RD0 */ + | IPSR_16_FUNC(0) /* RPC_RESET# */ + | IPSR_12_FUNC(0) /* RPC_INT# */ + | IPSR_8_FUNC(0) /* QSPI1_SSL */ + | IPSR_4_FUNC(0) /* QSPI1_IO3 */ + | IPSR_0_FUNC(0)); /* QSPI1_IO2 */ + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(1) /* IRQ0 */ + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(2) /* AVB_LINK */ + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) /* AVB_MDC */ + | IPSR_4_FUNC(0) /* AVB_MDIO */ + | IPSR_0_FUNC(0)); /* AVB_TXCREFCLK */ + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(5) /* DU_HSYNC */ + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(5) /* DU_DG4 */ + | IPSR_8_FUNC(5) /* DU_DOTCLKOUT0 */ + | IPSR_4_FUNC(5) /* DU_DISP */ + | IPSR_0_FUNC(1)); /* IRQ1 */ + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(5) /* DU_DB5 */ + | IPSR_24_FUNC(5) /* DU_DB4 */ + | IPSR_20_FUNC(5) /* DU_DB3 */ + | IPSR_16_FUNC(5) /* DU_DB2 */ + | IPSR_12_FUNC(5) /* DU_DG6 */ + | IPSR_8_FUNC(5) /* DU_VSYNC */ + | IPSR_4_FUNC(5) /* DU_DG5 */ + | IPSR_0_FUNC(5)); /* DU_DG7 */ + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(5) /* DU_DR3 */ + | IPSR_24_FUNC(5) /* DU_DB7 */ + | IPSR_20_FUNC(5) /* DU_DR2 */ + | IPSR_16_FUNC(5) /* DU_DR1 */ + | IPSR_12_FUNC(5) /* DU_DR0 */ + | IPSR_8_FUNC(5) /* DU_DB1 */ + | IPSR_4_FUNC(5) /* DU_DB0 */ + | IPSR_0_FUNC(5)); /* DU_DB6 */ + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(5) /* DU_DG1 */ + | IPSR_24_FUNC(5) /* DU_DG0 */ + | IPSR_20_FUNC(5) /* DU_DR7 */ + | IPSR_16_FUNC(2) /* IRQ5 */ + | IPSR_12_FUNC(5) /* DU_DR6 */ + | IPSR_8_FUNC(5) /* DU_DR5 */ + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(5)); /* DU_DR4 */ + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) /* SD0_CLK */ + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(5) /* DU_DOTCLKIN0 */ + | IPSR_16_FUNC(5) /* DU_DG3 */ + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(5)); /* DU_DG2 */ + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(0) /* SD1_DAT0 */ + | IPSR_24_FUNC(0) /* SD1_CMD */ + | IPSR_20_FUNC(0) /* SD1_CLK */ + | IPSR_16_FUNC(0) /* SD0_DAT3 */ + | IPSR_12_FUNC(0) /* SD0_DAT2 */ + | IPSR_8_FUNC(0) /* SD0_DAT1 */ + | IPSR_4_FUNC(0) /* SD0_DAT0 */ + | IPSR_0_FUNC(0)); /* SD0_CMD */ + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) /* SD3_DAT2 */ + | IPSR_24_FUNC(0) /* SD3_DAT1 */ + | IPSR_20_FUNC(0) /* SD3_DAT0 */ + | IPSR_16_FUNC(0) /* SD3_CMD */ + | IPSR_12_FUNC(0) /* SD3_CLK */ + | IPSR_8_FUNC(0) /* SD1_DAT3 */ + | IPSR_4_FUNC(0) /* SD1_DAT2 */ + | IPSR_0_FUNC(0)); /* SD1_DAT1 */ + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(0) /* SD0_WP */ + | IPSR_24_FUNC(0) /* SD0_CD */ + | IPSR_20_FUNC(0) /* SD3_DS */ + | IPSR_16_FUNC(0) /* SD3_DAT7 */ + | IPSR_12_FUNC(0) /* SD3_DAT6 */ + | IPSR_8_FUNC(0) /* SD3_DAT5 */ + | IPSR_4_FUNC(0) /* SD3_DAT4 */ + | IPSR_0_FUNC(0)); /* SD3_DAT3 */ + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(2) /* AUDIO_CLKOUT1_A */ + | IPSR_16_FUNC(2) /* AUDIO_CLKOUT_A */ + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) /* SD1_WP */ + | IPSR_0_FUNC(0)); /* SD1_CD */ + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) /* RX2_A */ + | IPSR_8_FUNC(0) /* TX2_A */ + | IPSR_4_FUNC(2) /* AUDIO_CLKB_A */ + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(2) /* AUDIO_CLKC_A */ + | IPSR_4_FUNC(1) /* HTX2_A */ + | IPSR_0_FUNC(1)); /* HRX2_A */ + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(3) /* USB0_PWEN_B */ + | IPSR_24_FUNC(0) /* SSI_SDATA4 */ + | IPSR_20_FUNC(0) /* SSI_SDATA3 */ + | IPSR_16_FUNC(0) /* SSI_WS349 */ + | IPSR_12_FUNC(0) /* SSI_SCK349 */ + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) /* SSI_SDATA1 */ + | IPSR_0_FUNC(0)); /* SSI_SDATA0 */ + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) /* USB30_OVC */ + | IPSR_24_FUNC(0) /* USB30_PWEN */ + | IPSR_20_FUNC(0) /* AUDIO_CLKA */ + | IPSR_16_FUNC(1) /* HRTS2#_A */ + | IPSR_12_FUNC(1) /* HCTS2#_A */ + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(3)); /* USB0_OVC_B */ + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_SCL4 + | GPSR0_D15 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8 + | GPSR0_D7 + | GPSR0_D6 + | GPSR0_D5 + | GPSR0_D3 + | GPSR0_D2 + | GPSR0_D1 + | GPSR0_D0); + pfc_reg_write(PFC_GPSR1, GPSR1_WE0 + | GPSR1_CS0 + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A11 + | GPSR1_A10 + | GPSR1_A9 + | GPSR1_A8 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_BIT27_REVERSED + | GPSR2_BIT26_REVERSED + | GPSR2_RD + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_TXCREFCLK + | GPSR2_AVB_RD3 + | GPSR2_AVB_RD2 + | GPSR2_AVB_RD1 + | GPSR2_AVB_RD0 + | GPSR2_AVB_RXC + | GPSR2_AVB_RX_CTL + | GPSR2_RPC_RESET + | GPSR2_RPC_RPC_INT + | GPSR2_QSPI1_SSL + | GPSR2_QSPI1_IO3 + | GPSR2_QSPI1_IO2 + | GPSR2_QSPI1_MISO_IO1 + | GPSR2_QSPI1_MOSI_IO0 + | GPSR2_QSPI1_SPCLK + | GPSR2_QSPI0_SSL + | GPSR2_QSPI0_IO3 + | GPSR2_QSPI0_IO2 + | GPSR2_QSPI0_MISO_IO1 + | GPSR2_QSPI0_MOSI_IO0 + | GPSR2_QSPI0_SPCLK); + pfc_reg_write(PFC_GPSR3, GPSR3_SD1_WP + | GPSR3_SD1_CD + | GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD1_CMD + | GPSR3_SD1_CLK + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DS + | GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT5 + | GPSR4_SD3_DAT4 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_SSI_SDATA9 + | GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2_A + | GPSR5_RTS0_A + | GPSR5_CTS0_A); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_PWEN + | GPSR6_SSI_SDATA6 + | GPSR6_SSI_WS6 + | GPSR6_SSI_WS5 + | GPSR6_SSI_SCK5 + | GPSR6_SSI_SDATA4 + | GPSR6_USB30_OVC + | GPSR6_AUDIO_CLKA + | GPSR6_SSI_SDATA3 + | GPSR6_SSI_WS349 + | GPSR6_SSI_SCK349 + | GPSR6_SSI_SDATA1 + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS01239 + | GPSR6_SSI_SCK01239); + + /* initialize POC control */ + reg = mmio_read_32(PFC_POCCTRL0); + reg = ((reg & POCCTRL0_MASK) | POC_SD1_DAT3_33V + | POC_SD1_DAT2_33V + | POC_SD1_DAT1_33V + | POC_SD1_DAT0_33V + | POC_SD1_CMD_33V + | POC_SD1_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + pfc_reg_write(PFC_POCCTRL0, reg); + reg = mmio_read_32(PFC_POCCTRL2); + reg = (reg & POCCTRL2_MASK); + pfc_reg_write(PFC_POCCTRL2, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0xFDF80000U); + pfc_reg_write(PFC_PUD1, 0xCE298464U); + pfc_reg_write(PFC_PUD2, 0xA4C380F4U); + pfc_reg_write(PFC_PUD3, 0x0000079FU); + pfc_reg_write(PFC_PUD4, 0xFFF0FFFFU); + pfc_reg_write(PFC_PUD5, 0x40000000U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0xFFF00000U); + pfc_reg_write(PFC_PUEN1, 0x00000000U); + pfc_reg_write(PFC_PUEN2, 0x00000004U); + pfc_reg_write(PFC_PUEN3, 0x00000000U); + pfc_reg_write(PFC_PUEN4, 0x07800010U); + pfc_reg_write(PFC_PUEN5, 0x00000000U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00020000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000010U); + mmio_write_32(GPIO_OUTDT1, 0x00100000U); + mmio_write_32(GPIO_OUTDT2, 0x00000000U); + mmio_write_32(GPIO_OUTDT3, 0x00008000U); + mmio_write_32(GPIO_OUTDT5, 0x00060000U); + mmio_write_32(GPIO_OUTDT6, 0x00000000U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000010U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100020U); + mmio_write_32(GPIO_INOUTSEL2, 0x03000000U); + mmio_write_32(GPIO_INOUTSEL3, 0x00008000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL5, 0x00060000U); + mmio_write_32(GPIO_INOUTSEL6, 0x00004000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h new file mode 100644 index 0000000..647a937 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_E3_H +#define PFC_INIT_E3_H + +void pfc_init_e3(void); + +#endif /* PFC_INIT_E3_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c new file mode 100644 index 0000000..effdc76 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c @@ -0,0 +1,1183 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C6_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C6_B ((uint32_t)1U << 20U) +#define MOD_SEL0_I2C6_C ((uint32_t)2U << 20U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 19U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 19U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 18U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 18U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 15U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 15U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 14U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 14U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 13U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 12U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 12U) +#define MOD_SEL0_FM_A ((uint32_t)0U << 11U) +#define MOD_SEL0_FM_B ((uint32_t)1U << 11U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 10U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 9U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 9U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 6U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 4U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 4U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 4U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 3U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A ((uint32_t)0U << 1U) +#define MOD_SEL0_ADG_B ((uint32_t)1U << 1U) +#define MOD_SEL0_ADG_C ((uint32_t)2U << 1U) +#define MOD_SEL0_ADG_D ((uint32_t)3U << 1U) +#define MOD_SEL0_5LINE_A ((uint32_t)0U << 0U) +#define MOD_SEL0_5LINE_B ((uint32_t)1U << 0U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_h3_v1(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C6_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FM_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A + | MOD_SEL0_5LINE_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_A + | MOD_SEL2_I2C_3_A + | MOD_SEL2_I2C_0_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8); + pfc_reg_write(PFC_GPSR1, GPSR1_EX_WAIT0_A + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ5 + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DS + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_MSIOF0_SYNC + | GPSR5_HRTS0 + | GPSR5_HCTS0 + | GPSR5_HTX0 + | GPSR5_HRX0 + | GPSR5_HSCK0 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2 + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_OVC + | GPSR6_USB30_PWEN + | GPSR6_USB1_OVC + | GPSR6_USB1_PWEN + | GPSR6_USB0_OVC + | GPSR6_USB0_PWEN + | GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_SDATA8 + | GPSR6_SSI_SDATA7 + | GPSR6_SSI_WS78 + | GPSR6_SSI_SCK78 + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD3_DS_33V + | POC_SD3_DAT7_33V + | POC_SD3_DAT6_33V + | POC_SD3_DAT5_33V + | POC_SD3_DAT4_33V + | POC_SD3_DAT3_33V + | POC_SD3_DAT2_33V + | POC_SD3_DAT1_33V + | POC_SD3_DAT0_33V + | POC_SD3_CMD_33V + | POC_SD3_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(2) + | DRVCTRL13_SD0_CMD(2) + | DRVCTRL13_SD0_DAT0(2) + | DRVCTRL13_SD0_DAT1(2) + | DRVCTRL13_SD0_DAT2(2) + | DRVCTRL13_SD0_DAT3(2)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(2) + | DRVCTRL15_SD3_CMD(2) + | DRVCTRL15_SD3_DAT0(2)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(2) + | DRVCTRL16_SD3_DAT2(2) + | DRVCTRL16_SD3_DAT3(2) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300FFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x0000C000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x01000A00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000400U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); +#if (RCAR_GEN3_ULCB == 1) + mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU); +#else + mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU); +#endif + mmio_write_32(GPIO_INOUTSEL6, 0x00013880U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h new file mode 100644 index 0000000..2478e1c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_H3_V1_H +#define PFC_INIT_H3_V1_H + +void pfc_init_h3_v1(void); + +#endif /* PFC_INIT_H3_V1_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c new file mode 100644 index 0000000..a54b14b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c @@ -0,0 +1,1216 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ +#include +#include "pfc_init_h3_v2.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_h3_v2(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_A + | MOD_SEL2_I2C_3_A + | MOD_SEL2_I2C_0_A + | MOD_SEL2_FM_A + | MOD_SEL2_SCIF5_A + | MOD_SEL2_I2C6_A + | MOD_SEL2_NDF_A + | MOD_SEL2_SSI2_A + | MOD_SEL2_SSI9_A + | MOD_SEL2_TIMER_TMU2_A + | MOD_SEL2_ADG_B_A + | MOD_SEL2_ADG_C_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(1) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8); + pfc_reg_write(PFC_GPSR1, GPSR1_CLKOUT + | GPSR1_EX_WAIT0_A + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ5 + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DS + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_MSIOF0_SYNC + | GPSR5_HRTS0 + | GPSR5_HCTS0 + | GPSR5_HTX0 + | GPSR5_HRX0 + | GPSR5_HSCK0 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2 + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_OVC + | GPSR6_USB30_PWEN + | GPSR6_USB1_OVC + | GPSR6_USB1_PWEN + | GPSR6_USB0_OVC + | GPSR6_USB0_PWEN + | GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_SDATA8 + | GPSR6_SSI_SDATA7 + | GPSR6_SSI_WS78 + | GPSR6_SSI_SCK78 + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD3_DS_33V + | POC_SD3_DAT7_33V + | POC_SD3_DAT6_33V + | POC_SD3_DAT5_33V + | POC_SD3_DAT4_33V + | POC_SD3_DAT3_33V + | POC_SD3_DAT2_33V + | POC_SD3_DAT1_33V + | POC_SD3_DAT0_33V + | POC_SD3_CMD_33V + | POC_SD3_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(7) + | DRVCTRL13_SD0_CMD(7) + | DRVCTRL13_SD0_DAT0(7) + | DRVCTRL13_SD0_DAT1(7) + | DRVCTRL13_SD0_DAT2(7) + | DRVCTRL13_SD0_DAT3(7)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(7) + | DRVCTRL15_SD3_CMD(7) + | DRVCTRL15_SD3_DAT0(7)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(7) + | DRVCTRL16_SD3_DAT2(7) + | DRVCTRL16_SD3_DAT3(7) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300FFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x0000C000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x01000A00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000400U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); +#if (RCAR_GEN3_ULCB == 1) + mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU); +#else + mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU); +#endif + mmio_write_32(GPIO_INOUTSEL6, 0x00013880U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h new file mode 100644 index 0000000..b02f93e --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_H3_V2_H +#define PFC_INIT_H3_V2_H + +void pfc_init_h3_v2(void); + +#endif /* PFC_INIT_H3_V2_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c new file mode 100644 index 0000000..7684c62 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c @@ -0,0 +1,1311 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ + +#include + +#include "pfc_init_m3.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +/* SCIF3 Registers for Dummy write */ +#define SCIF3_BASE (0xE6C50000U) +#define SCIF3_SCFCR (SCIF3_BASE + 0x0018U) +#define SCIF3_SCFDR (SCIF3_BASE + 0x001CU) +#define SCFCR_DATA (0x0000U) + +/* Realtime module stop control */ +#define CPG_BASE (0xE6150000U) +#define CPG_SCMSTPCR0 (CPG_BASE + 0x0B20U) +#define CPG_MSTPSR0 (CPG_BASE + 0x0030U) +#define SCMSTPCR0_RTDMAC (0x00200000U) + +/* RT-DMAC Registers */ +#define RTDMAC_CH (0U) /* choose 0 to 15 */ + +#define RTDMAC_BASE (0xFFC10000U) +#define RTDMAC_RDMOR (RTDMAC_BASE + 0x0060U) +#define RTDMAC_RDMCHCLR (RTDMAC_BASE + 0x0080U) +#define RTDMAC_RDMSAR(x) (RTDMAC_BASE + 0x8000U + (0x80U * (x))) +#define RTDMAC_RDMDAR(x) (RTDMAC_BASE + 0x8004U + (0x80U * (x))) +#define RTDMAC_RDMTCR(x) (RTDMAC_BASE + 0x8008U + (0x80U * (x))) +#define RTDMAC_RDMCHCR(x) (RTDMAC_BASE + 0x800CU + (0x80U * (x))) +#define RTDMAC_RDMCHCRB(x) (RTDMAC_BASE + 0x801CU + (0x80U * (x))) +#define RTDMAC_RDMDPBASE(x) (RTDMAC_BASE + 0x8050U + (0x80U * (x))) +#define RTDMAC_DESC_BASE (RTDMAC_BASE + 0xA000U) +#define RTDMAC_DESC_RDMSAR (RTDMAC_DESC_BASE + 0x0000U) +#define RTDMAC_DESC_RDMDAR (RTDMAC_DESC_BASE + 0x0004U) +#define RTDMAC_DESC_RDMTCR (RTDMAC_DESC_BASE + 0x0008U) + +#define RDMOR_DME (0x0001U) /* DMA Master Enable */ +#define RDMCHCR_DPM_INFINITE (0x30000000U) /* Infinite repeat mode */ +#define RDMCHCR_RPT_TCR (0x02000000U) /* enable to update TCR */ +#define RDMCHCR_TS_2 (0x00000008U) /* Word(2byte) units transfer */ +#define RDMCHCR_RS_AUTO (0x00000400U) /* Auto request */ +#define RDMCHCR_DE (0x00000001U) /* DMA Enable */ +#define RDMCHCRB_DRST (0x00008000U) /* Descriptor reset */ +#define RDMCHCRB_SLM_256 (0x00000080U) /* once in 256 clock cycle */ +#define RDMDPBASE_SEL_EXT (0x00000001U) /* External memory use */ + +static void start_rtdma0_descriptor(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); + reg &= (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if (reg == (PRR_PRODUCT_M3_CUT10)) { + /* Enable clock supply to RTDMAC. */ + mstpcr_write(CPG_SCMSTPCR0, CPG_MSTPSR0, SCMSTPCR0_RTDMAC); + + /* Initialize ch0, Reset Descriptor */ + mmio_write_32(RTDMAC_RDMCHCLR, BIT(RTDMAC_CH)); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_DRST); + + /* Enable DMA */ + mmio_write_16(RTDMAC_RDMOR, RDMOR_DME); + + /* Set first transfer */ + mmio_write_32(RTDMAC_RDMSAR(RTDMAC_CH), RCAR_PRR); + mmio_write_32(RTDMAC_RDMDAR(RTDMAC_CH), SCIF3_SCFDR); + mmio_write_32(RTDMAC_RDMTCR(RTDMAC_CH), 0x00000001U); + + /* Set descriptor */ + mmio_write_32(RTDMAC_DESC_RDMSAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMDAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMTCR, 0x00200000U); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_SLM_256); + mmio_write_32(RTDMAC_RDMDPBASE(RTDMAC_CH), RTDMAC_DESC_BASE + | RDMDPBASE_SEL_EXT); + + /* Set transfer parameter, Start transfer */ + mmio_write_32(RTDMAC_RDMCHCR(RTDMAC_CH), RDMCHCR_DPM_INFINITE + | RDMCHCR_RPT_TCR + | RDMCHCR_TS_2 + | RDMCHCR_RS_AUTO + | RDMCHCR_DE); + } +} + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + uint32_t prr; + + prr = mmio_read_32(RCAR_PRR); + prr &= (PRR_PRODUCT_MASK | PRR_CUT_MASK); + + mmio_write_32(PFC_PMMR, ~data); + if (prr == (PRR_PRODUCT_M3_CUT10)) { + mmio_write_16(SCIF3_SCFCR, SCFCR_DATA); /* Dummy write */ + } + mmio_write_32((uintptr_t)addr, data); + if (prr == (PRR_PRODUCT_M3_CUT10)) { + mmio_write_16(SCIF3_SCFCR, SCFCR_DATA); /* Dummy write */ + } +} + +void pfc_init_m3(void) +{ + uint32_t reg; + + /* Work around for PFC eratta */ + start_rtdma0_descriptor(); + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_A + | MOD_SEL2_I2C_3_A + | MOD_SEL2_I2C_0_A + | MOD_SEL2_FM_A + | MOD_SEL2_SCIF5_A + | MOD_SEL2_I2C6_A + | MOD_SEL2_NDF_A + | MOD_SEL2_SSI2_A + | MOD_SEL2_SSI9_A + | MOD_SEL2_TIMER_TMU2_A + | MOD_SEL2_ADG_B_A + | MOD_SEL2_ADG_C_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(1) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8); + pfc_reg_write(PFC_GPSR1, GPSR1_CLKOUT + | GPSR1_EX_WAIT0_A + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ5 + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DS + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_MSIOF0_SYNC + | GPSR5_HRTS0 + | GPSR5_HCTS0 + | GPSR5_HTX0 + | GPSR5_HRX0 + | GPSR5_HSCK0 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2 + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_OVC + | GPSR6_USB30_PWEN + | GPSR6_USB1_OVC + | GPSR6_USB1_PWEN + | GPSR6_USB0_OVC + | GPSR6_USB0_PWEN + | GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_SDATA8 + | GPSR6_SSI_SDATA7 + | GPSR6_SSI_WS78 + | GPSR6_SSI_SCK78 + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD3_DS_33V + | POC_SD3_DAT7_33V + | POC_SD3_DAT6_33V + | POC_SD3_DAT5_33V + | POC_SD3_DAT4_33V + | POC_SD3_DAT3_33V + | POC_SD3_DAT2_33V + | POC_SD3_DAT1_33V + | POC_SD3_DAT0_33V + | POC_SD3_CMD_33V + | POC_SD3_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(7) + | DRVCTRL13_SD0_CMD(7) + | DRVCTRL13_SD0_DAT0(7) + | DRVCTRL13_SD0_DAT1(7) + | DRVCTRL13_SD0_DAT2(7) + | DRVCTRL13_SD0_DAT3(7)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(7) + | DRVCTRL15_SD3_CMD(7) + | DRVCTRL15_SD3_DAT0(7)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(7) + | DRVCTRL16_SD3_DAT2(7) + | DRVCTRL16_SD3_DAT3(7) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300FFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x0000C000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x01000A00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000400U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); +#if (RCAR_GEN3_ULCB == 1) + mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU); +#else + mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU); +#endif + mmio_write_32(GPIO_INOUTSEL6, 0x00013880U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h new file mode 100644 index 0000000..70885de --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_M3_H +#define PFC_INIT_M3_H + +void pfc_init_m3(void); + +#endif /* PFC_INIT_M3_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c new file mode 100644 index 0000000..5014556 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c @@ -0,0 +1,1218 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ + +#include + +#include "pfc_init_m3n.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_m3n(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_A + | MOD_SEL2_I2C_3_A + | MOD_SEL2_I2C_0_A + | MOD_SEL2_FM_A + | MOD_SEL2_SCIF5_A + | MOD_SEL2_I2C6_A + | MOD_SEL2_NDF_A + | MOD_SEL2_SSI2_A + | MOD_SEL2_SSI9_A + | MOD_SEL2_TIMER_TMU2_A + | MOD_SEL2_ADG_B_A + | MOD_SEL2_ADG_C_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(1) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8); + pfc_reg_write(PFC_GPSR1, GPSR1_CLKOUT + | GPSR1_EX_WAIT0_A + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ5 + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DS + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_MSIOF0_SYNC + | GPSR5_HRTS0 + | GPSR5_HCTS0 + | GPSR5_HTX0 + | GPSR5_HRX0 + | GPSR5_HSCK0 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2 + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_OVC + | GPSR6_USB30_PWEN + | GPSR6_USB1_OVC + | GPSR6_USB1_PWEN + | GPSR6_USB0_OVC + | GPSR6_USB0_PWEN + | GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_SDATA8 + | GPSR6_SSI_SDATA7 + | GPSR6_SSI_WS78 + | GPSR6_SSI_SCK78 + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD3_DS_33V + | POC_SD3_DAT7_33V + | POC_SD3_DAT6_33V + | POC_SD3_DAT5_33V + | POC_SD3_DAT4_33V + | POC_SD3_DAT3_33V + | POC_SD3_DAT2_33V + | POC_SD3_DAT1_33V + | POC_SD3_DAT0_33V + | POC_SD3_CMD_33V + | POC_SD3_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(7) + | DRVCTRL13_SD0_CMD(7) + | DRVCTRL13_SD0_DAT0(7) + | DRVCTRL13_SD0_DAT1(7) + | DRVCTRL13_SD0_DAT2(7) + | DRVCTRL13_SD0_DAT3(7)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(7) + | DRVCTRL15_SD3_CMD(7) + | DRVCTRL15_SD3_DAT0(7)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(7) + | DRVCTRL16_SD3_DAT2(7) + | DRVCTRL16_SD3_DAT3(7) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300FFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x0000C000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x01000A00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000400U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); +#if (RCAR_GEN3_ULCB == 1) + mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU); +#else + mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU); +#endif + mmio_write_32(GPIO_INOUTSEL6, 0x00013880U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h new file mode 100644 index 0000000..3e6f879 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_M3N_H +#define PFC_INIT_M3N_H + +void pfc_init_m3n(void); + +#endif /* PFC_INIT_M3N_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c new file mode 100644 index 0000000..6063758 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c @@ -0,0 +1,906 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ +#include +#include "pfc_init_v3m.h" +#include "include/rcar_def.h" +#include "rcar_private.h" +#include "../pfc_regs.h" + +/* Pin functon bit */ +#define GPSR0_DU_EXODDF_DU_ODDF_DISP_CDE BIT(21) +#define GPSR0_DU_EXVSYNC_DU_VSYNC BIT(20) +#define GPSR0_DU_EXHSYNC_DU_HSYNC BIT(19) +#define GPSR0_DU_DOTCLKOUT BIT(18) +#define GPSR0_DU_DB7 BIT(17) +#define GPSR0_DU_DB6 BIT(16) +#define GPSR0_DU_DB5 BIT(15) +#define GPSR0_DU_DB4 BIT(14) +#define GPSR0_DU_DB3 BIT(13) +#define GPSR0_DU_DB2 BIT(12) +#define GPSR0_DU_DG7 BIT(11) +#define GPSR0_DU_DG6 BIT(10) +#define GPSR0_DU_DG5 BIT(9) +#define GPSR0_DU_DG4 BIT(8) +#define GPSR0_DU_DG3 BIT(7) +#define GPSR0_DU_DG2 BIT(6) +#define GPSR0_DU_DR7 BIT(5) +#define GPSR0_DU_DR6 BIT(4) +#define GPSR0_DU_DR5 BIT(3) +#define GPSR0_DU_DR4 BIT(2) +#define GPSR0_DU_DR3 BIT(1) +#define GPSR0_DU_DR2 BIT(0) + +#define GPSR1_DIGRF_CLKOUT BIT(27) +#define GPSR1_DIGRF_CLKIN BIT(26) +#define GPSR1_CANFD_CLK BIT(25) +#define GPSR1_CANFD1_RX BIT(24) +#define GPSR1_CANFD1_TX BIT(23) +#define GPSR1_CANFD0_RX BIT(22) +#define GPSR1_CANFD0_TX BIT(21) +#define GPSR1_AVB0_AVTP_CAPTURE BIT(20) +#define GPSR1_AVB0_AVTP_MATCH BIT(19) +#define GPSR1_AVB0_LINK BIT(18) +#define GPSR1_AVB0_PHY_INT BIT(17) +#define GPSR1_AVB0_MAGIC BIT(16) +#define GPSR1_AVB0_MDC BIT(15) +#define GPSR1_AVB0_MDIO BIT(14) +#define GPSR1_AVB0_TXCREFCLK BIT(13) +#define GPSR1_AVB0_TD3 BIT(12) +#define GPSR1_AVB0_TD2 BIT(11) +#define GPSR1_AVB0_TD1 BIT(10) +#define GPSR1_AVB0_TD0 BIT(9) +#define GPSR1_AVB0_TXC BIT(8) +#define GPSR1_AVB0_TX_CTL BIT(7) +#define GPSR1_AVB0_RD3 BIT(6) +#define GPSR1_AVB0_RD2 BIT(5) +#define GPSR1_AVB0_RD1 BIT(4) +#define GPSR1_AVB0_RD0 BIT(3) +#define GPSR1_AVB0_RXC BIT(2) +#define GPSR1_AVB0_RX_CTL BIT(1) +#define GPSR1_IRQ0 BIT(0) + +#define GPSR2_VI0_FIELD BIT(16) +#define GPSR2_VI0_DATA11 BIT(15) +#define GPSR2_VI0_DATA10 BIT(14) +#define GPSR2_VI0_DATA9 BIT(13) +#define GPSR2_VI0_DATA8 BIT(12) +#define GPSR2_VI0_DATA7 BIT(11) +#define GPSR2_VI0_DATA6 BIT(10) +#define GPSR2_VI0_DATA5 BIT(9) +#define GPSR2_VI0_DATA4 BIT(8) +#define GPSR2_VI0_DATA3 BIT(7) +#define GPSR2_VI0_DATA2 BIT(6) +#define GPSR2_VI0_DATA1 BIT(5) +#define GPSR2_VI0_DATA0 BIT(4) +#define GPSR2_VI0_VSYNC_N BIT(3) +#define GPSR2_VI0_HSYNC_N BIT(2) +#define GPSR2_VI0_CLKENB BIT(1) +#define GPSR2_VI0_CLK BIT(0) + +#define GPSR3_VI1_FIELD BIT(16) +#define GPSR3_VI1_DATA11 BIT(15) +#define GPSR3_VI1_DATA10 BIT(14) +#define GPSR3_VI1_DATA9 BIT(13) +#define GPSR3_VI1_DATA8 BIT(12) +#define GPSR3_VI1_DATA7 BIT(11) +#define GPSR3_VI1_DATA6 BIT(10) +#define GPSR3_VI1_DATA5 BIT(9) +#define GPSR3_VI1_DATA4 BIT(8) +#define GPSR3_VI1_DATA3 BIT(7) +#define GPSR3_VI1_DATA2 BIT(6) +#define GPSR3_VI1_DATA1 BIT(5) +#define GPSR3_VI1_DATA0 BIT(4) +#define GPSR3_VI1_VSYNC_N BIT(3) +#define GPSR3_VI1_HSYNC_N BIT(2) +#define GPSR3_VI1_CLKENB BIT(1) +#define GPSR3_VI1_CLK BIT(0) + +#define GPSR4_SDA2 BIT(5) +#define GPSR4_SCL2 BIT(4) +#define GPSR4_SDA1 BIT(3) +#define GPSR4_SCL1 BIT(2) +#define GPSR4_SDA0 BIT(1) +#define GPSR4_SCL0 BIT(0) + +#define GPSR5_RPC_INT_N BIT(14) +#define GPSR5_RPC_WP_N BIT(13) +#define GPSR5_RPC_RESET_N BIT(12) +#define GPSR5_QSPI1_SSL BIT(11) +#define GPSR5_QSPI1_IO3 BIT(10) +#define GPSR5_QSPI1_IO2 BIT(9) +#define GPSR5_QSPI1_MISO_IO1 BIT(8) +#define GPSR5_QSPI1_MOSI_IO0 BIT(7) +#define GPSR5_QSPI1_SPCLK BIT(6) +#define GPSR5_QSPI0_SSL BIT(5) +#define GPSR5_QSPI0_IO3 BIT(4) +#define GPSR5_QSPI0_IO2 BIT(3) +#define GPSR5_QSPI0_MISO_IO1 BIT(2) +#define GPSR5_QSPI0_MOSI_IO0 BIT(1) +#define GPSR5_QSPI0_SPCLK BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define IOCTRL30_POC_VI0_DATA5 BIT(31) +#define IOCTRL30_POC_VI0_DATA4 BIT(30) +#define IOCTRL30_POC_VI0_DATA3 BIT(29) +#define IOCTRL30_POC_VI0_DATA2 BIT(28) +#define IOCTRL30_POC_VI0_DATA1 BIT(27) +#define IOCTRL30_POC_VI0_DATA0 BIT(26) +#define IOCTRL30_POC_VI0_VSYNC_N BIT(25) +#define IOCTRL30_POC_VI0_HSYNC_N BIT(24) +#define IOCTRL30_POC_VI0_CLKENB BIT(23) +#define IOCTRL30_POC_VI0_CLK BIT(22) +#define IOCTRL30_POC_DU_EXODDF_DU_ODDF_DISP_CDE BIT(21) +#define IOCTRL30_POC_DU_EXVSYNC_DU_VSYNC BIT(20) +#define IOCTRL30_POC_DU_EXHSYNC_DU_HSYNC BIT(19) +#define IOCTRL30_POC_DU_DOTCLKOUT BIT(18) +#define IOCTRL30_POC_DU_DB7 BIT(17) +#define IOCTRL30_POC_DU_DB6 BIT(16) +#define IOCTRL30_POC_DU_DB5 BIT(15) +#define IOCTRL30_POC_DU_DB4 BIT(14) +#define IOCTRL30_POC_DU_DB3 BIT(13) +#define IOCTRL30_POC_DU_DB2 BIT(12) +#define IOCTRL30_POC_DU_DG7 BIT(11) +#define IOCTRL30_POC_DU_DG6 BIT(10) +#define IOCTRL30_POC_DU_DG5 BIT(9) +#define IOCTRL30_POC_DU_DG4 BIT(8) +#define IOCTRL30_POC_DU_DG3 BIT(7) +#define IOCTRL30_POC_DU_DG2 BIT(6) +#define IOCTRL30_POC_DU_DR7 BIT(5) +#define IOCTRL30_POC_DU_DR6 BIT(4) +#define IOCTRL30_POC_DU_DR5 BIT(3) +#define IOCTRL30_POC_DU_DR4 BIT(2) +#define IOCTRL30_POC_DU_DR3 BIT(1) +#define IOCTRL30_POC_DU_DR2 BIT(0) + +#define IOCTRL31_POC_DUMMY_31 BIT(31) +#define IOCTRL31_POC_DUMMY_30 BIT(30) +#define IOCTRL31_POC_DUMMY_29 BIT(29) +#define IOCTRL31_POC_DUMMY_28 BIT(28) +#define IOCTRL31_POC_DUMMY_27 BIT(27) +#define IOCTRL31_POC_DUMMY_26 BIT(26) +#define IOCTRL31_POC_DUMMY_25 BIT(25) +#define IOCTRL31_POC_DUMMY_24 BIT(24) +#define IOCTRL31_POC_VI1_FIELD BIT(23) +#define IOCTRL31_POC_VI1_DATA11 BIT(22) +#define IOCTRL31_POC_VI1_DATA10 BIT(21) +#define IOCTRL31_POC_VI1_DATA9 BIT(20) +#define IOCTRL31_POC_VI1_DATA8 BIT(19) +#define IOCTRL31_POC_VI1_DATA7 BIT(18) +#define IOCTRL31_POC_VI1_DATA6 BIT(17) +#define IOCTRL31_POC_VI1_DATA5 BIT(16) +#define IOCTRL31_POC_VI1_DATA4 BIT(15) +#define IOCTRL31_POC_VI1_DATA3 BIT(14) +#define IOCTRL31_POC_VI1_DATA2 BIT(13) +#define IOCTRL31_POC_VI1_DATA1 BIT(12) +#define IOCTRL31_POC_VI1_DATA0 BIT(11) +#define IOCTRL31_POC_VI1_VSYNC_N BIT(10) +#define IOCTRL31_POC_VI1_HSYNC_N BIT(9) +#define IOCTRL31_POC_VI1_CLKENB BIT(8) +#define IOCTRL31_POC_VI1_CLK BIT(7) +#define IOCTRL31_POC_VI0_FIELD BIT(6) +#define IOCTRL31_POC_VI0_DATA11 BIT(5) +#define IOCTRL31_POC_VI0_DATA10 BIT(4) +#define IOCTRL31_POC_VI0_DATA9 BIT(3) +#define IOCTRL31_POC_VI0_DATA8 BIT(2) +#define IOCTRL31_POC_VI0_DATA7 BIT(1) +#define IOCTRL31_POC_VI0_DATA6 BIT(0) +#define IOCTRL32_POC2_VREF BIT(0) +#define IOCTRL40_SD0TDSEL1 BIT(1) +#define IOCTRL40_SD0TDSEL0 BIT(0) + +#define PUEN0_PUEN_VI0_CLK BIT(31) +#define PUEN0_PUEN_TDI BIT(30) +#define PUEN0_PUEN_TMS BIT(29) +#define PUEN0_PUEN_TCK BIT(28) +#define PUEN0_PUEN_TRST_N BIT(27) +#define PUEN0_PUEN_IRQ0 BIT(26) +#define PUEN0_PUEN_FSCLKST_N BIT(25) +#define PUEN0_PUEN_EXTALR BIT(24) +#define PUEN0_PUEN_PRESETOUT_N BIT(23) +#define PUEN0_PUEN_DU_DOTCLKIN BIT(22) +#define PUEN0_PUEN_DU_EXODDF_DU_ODDF_DISP_CDE BIT(21) +#define PUEN0_PUEN_DU_EXVSYNC_DU_VSYNC BIT(20) +#define PUEN0_PUEN_DU_EXHSYNC_DU_HSYNC BIT(19) +#define PUEN0_PUEN_DU_DOTCLKOUT BIT(18) +#define PUEN0_PUEN_DU_DB7 BIT(17) +#define PUEN0_PUEN_DU_DB6 BIT(16) +#define PUEN0_PUEN_DU_DB5 BIT(15) +#define PUEN0_PUEN_DU_DB4 BIT(14) +#define PUEN0_PUEN_DU_DB3 BIT(13) +#define PUEN0_PUEN_DU_DB2 BIT(12) +#define PUEN0_PUEN_DU_DG7 BIT(11) +#define PUEN0_PUEN_DU_DG6 BIT(10) +#define PUEN0_PUEN_DU_DG5 BIT(9) +#define PUEN0_PUEN_DU_DG4 BIT(8) +#define PUEN0_PUEN_DU_DG3 BIT(7) +#define PUEN0_PUEN_DU_DG2 BIT(6) +#define PUEN0_PUEN_DU_DR7 BIT(5) +#define PUEN0_PUEN_DU_DR6 BIT(4) +#define PUEN0_PUEN_DU_DR5 BIT(3) +#define PUEN0_PUEN_DU_DR4 BIT(2) +#define PUEN0_PUEN_DU_DR3 BIT(1) +#define PUEN0_PUEN_DU_DR2 BIT(0) + +#define PUEN1_PUEN_VI1_DATA11 BIT(31) +#define PUEN1_PUEN_VI1_DATA10 BIT(30) +#define PUEN1_PUEN_VI1_DATA9 BIT(29) +#define PUEN1_PUEN_VI1_DATA8 BIT(28) +#define PUEN1_PUEN_VI1_DATA7 BIT(27) +#define PUEN1_PUEN_VI1_DATA6 BIT(26) +#define PUEN1_PUEN_VI1_DATA5 BIT(25) +#define PUEN1_PUEN_VI1_DATA4 BIT(24) +#define PUEN1_PUEN_VI1_DATA3 BIT(23) +#define PUEN1_PUEN_VI1_DATA2 BIT(22) +#define PUEN1_PUEN_VI1_DATA1 BIT(21) +#define PUEN1_PUEN_VI1_DATA0 BIT(20) +#define PUEN1_PUEN_VI1_VSYNC_N BIT(19) +#define PUEN1_PUEN_VI1_HSYNC_N BIT(18) +#define PUEN1_PUEN_VI1_CLKENB BIT(17) +#define PUEN1_PUEN_VI1_CLK BIT(16) +#define PUEN1_PUEN_VI0_FIELD BIT(15) +#define PUEN1_PUEN_VI0_DATA11 BIT(14) +#define PUEN1_PUEN_VI0_DATA10 BIT(13) +#define PUEN1_PUEN_VI0_DATA9 BIT(12) +#define PUEN1_PUEN_VI0_DATA8 BIT(11) +#define PUEN1_PUEN_VI0_DATA7 BIT(10) +#define PUEN1_PUEN_VI0_DATA6 BIT(9) +#define PUEN1_PUEN_VI0_DATA5 BIT(8) +#define PUEN1_PUEN_VI0_DATA4 BIT(7) +#define PUEN1_PUEN_VI0_DATA3 BIT(6) +#define PUEN1_PUEN_VI0_DATA2 BIT(5) +#define PUEN1_PUEN_VI0_DATA1 BIT(4) +#define PUEN1_PUEN_VI0_DATA0 BIT(3) +#define PUEN1_PUEN_VI0_VSYNC_N BIT(2) +#define PUEN1_PUEN_VI0_HSYNC_N BIT(1) +#define PUEN1_PUEN_VI0_CLKENB BIT(0) + +#define PUEN2_PUEN_CANFD_CLK BIT(31) +#define PUEN2_PUEN_CANFD1_RX BIT(30) +#define PUEN2_PUEN_CANFD1_TX BIT(29) +#define PUEN2_PUEN_CANFD0_RX BIT(28) +#define PUEN2_PUEN_CANFD0_TX BIT(27) +#define PUEN2_PUEN_AVB0_AVTP_CAPTURE BIT(26) +#define PUEN2_PUEN_AVB0_AVTP_MATCH BIT(25) +#define PUEN2_PUEN_AVB0_LINK BIT(24) +#define PUEN2_PUEN_AVB0_PHY_INT BIT(23) +#define PUEN2_PUEN_AVB0_MAGIC BIT(22) +#define PUEN2_PUEN_AVB0_MDC BIT(21) +#define PUEN2_PUEN_AVB0_MDIO BIT(20) +#define PUEN2_PUEN_AVB0_TXCREFCLK BIT(19) +#define PUEN2_PUEN_AVB0_TD3 BIT(18) +#define PUEN2_PUEN_AVB0_TD2 BIT(17) +#define PUEN2_PUEN_AVB0_TD1 BIT(16) +#define PUEN2_PUEN_AVB0_TD0 BIT(15) +#define PUEN2_PUEN_AVB0_TXC BIT(14) +#define PUEN2_PUEN_AVB0_TX_CTL BIT(13) +#define PUEN2_PUEN_AVB0_RD3 BIT(12) +#define PUEN2_PUEN_AVB0_RD2 BIT(11) +#define PUEN2_PUEN_AVB0_RD1 BIT(10) +#define PUEN2_PUEN_AVB0_RD0 BIT(9) +#define PUEN2_PUEN_AVB0_RXC BIT(8) +#define PUEN2_PUEN_AVB0_RX_CTL BIT(7) +#define PUEN2_PUEN_SDA2 BIT(6) +#define PUEN2_PUEN_SCL2 BIT(5) +#define PUEN2_PUEN_SDA1 BIT(4) +#define PUEN2_PUEN_SCL1 BIT(3) +#define PUEN2_PUEN_SDA0 BIT(2) +#define PUEN2_PUEN_SCL0 BIT(1) +#define PUEN2_PUEN_VI1_FIELD BIT(0) + +#define PUEN3_PUEN_DIGRF_CLKOUT BIT(16) +#define PUEN3_PUEN_DIGRF_CLKIN BIT(15) +#define PUEN3_PUEN_RPC_INT_N BIT(14) +#define PUEN3_PUEN_RPC_WP_N BIT(13) +#define PUEN3_PUEN_RPC_RESET_N BIT(12) +#define PUEN3_PUEN_QSPI1_SSL BIT(11) +#define PUEN3_PUEN_QSPI1_IO3 BIT(10) +#define PUEN3_PUEN_QSPI1_IO2 BIT(9) +#define PUEN3_PUEN_QSPI1_MISO_IO1 BIT(8) +#define PUEN3_PUEN_QSPI1_MOSI_IO0 BIT(7) +#define PUEN3_PUEN_QSPI1_SPCLK BIT(6) +#define PUEN3_PUEN_QSPI0_SSL BIT(5) +#define PUEN3_PUEN_QSPI0_IO3 BIT(4) +#define PUEN3_PUEN_QSPI0_IO2 BIT(3) +#define PUEN3_PUEN_QSPI0_MISO_IO1 BIT(2) +#define PUEN3_PUEN_QSPI0_MOSI_IO0 BIT(1) +#define PUEN3_PUEN_QSPI0_SPCLK BIT(0) + +#define PUD0_PUD_VI0_CLK BIT(31) +#define PUD0_PUD_IRQ0 BIT(26) +#define PUD0_PUD_FSCLKST_N BIT(25) +#define PUD0_PUD_PRESETOUT_N BIT(23) +#define PUD0_PUD_DU_EXODDF_DU_ODDF_DISP_CDE BIT(21) +#define PUD0_PUD_DU_EXVSYNC_DU_VSYNC BIT(20) +#define PUD0_PUD_DU_EXHSYNC_DU_HSYNC BIT(19) +#define PUD0_PUD_DU_DOTCLKOUT BIT(18) +#define PUD0_PUD_DU_DB7 BIT(17) +#define PUD0_PUD_DU_DB6 BIT(16) +#define PUD0_PUD_DU_DB5 BIT(15) +#define PUD0_PUD_DU_DB4 BIT(14) +#define PUD0_PUD_DU_DB3 BIT(13) +#define PUD0_PUD_DU_DB2 BIT(12) +#define PUD0_PUD_DU_DG7 BIT(11) +#define PUD0_PUD_DU_DG6 BIT(10) +#define PUD0_PUD_DU_DG5 BIT(9) +#define PUD0_PUD_DU_DG4 BIT(8) +#define PUD0_PUD_DU_DG3 BIT(7) +#define PUD0_PUD_DU_DG2 BIT(6) +#define PUD0_PUD_DU_DR7 BIT(5) +#define PUD0_PUD_DU_DR6 BIT(4) +#define PUD0_PUD_DU_DR5 BIT(3) +#define PUD0_PUD_DU_DR4 BIT(2) +#define PUD0_PUD_DU_DR3 BIT(1) +#define PUD0_PUD_DU_DR2 BIT(0) + +#define PUD1_PUD_VI1_DATA11 BIT(31) +#define PUD1_PUD_VI1_DATA10 BIT(30) +#define PUD1_PUD_VI1_DATA9 BIT(29) +#define PUD1_PUD_VI1_DATA8 BIT(28) +#define PUD1_PUD_VI1_DATA7 BIT(27) +#define PUD1_PUD_VI1_DATA6 BIT(26) +#define PUD1_PUD_VI1_DATA5 BIT(25) +#define PUD1_PUD_VI1_DATA4 BIT(24) +#define PUD1_PUD_VI1_DATA3 BIT(23) +#define PUD1_PUD_VI1_DATA2 BIT(22) +#define PUD1_PUD_VI1_DATA1 BIT(21) +#define PUD1_PUD_VI1_DATA0 BIT(20) +#define PUD1_PUD_VI1_VSYNC_N BIT(19) +#define PUD1_PUD_VI1_HSYNC_N BIT(18) +#define PUD1_PUD_VI1_CLKENB BIT(17) +#define PUD1_PUD_VI1_CLK BIT(16) +#define PUD1_PUD_VI0_FIELD BIT(15) +#define PUD1_PUD_VI0_DATA11 BIT(14) +#define PUD1_PUD_VI0_DATA10 BIT(13) +#define PUD1_PUD_VI0_DATA9 BIT(12) +#define PUD1_PUD_VI0_DATA8 BIT(11) +#define PUD1_PUD_VI0_DATA7 BIT(10) +#define PUD1_PUD_VI0_DATA6 BIT(9) +#define PUD1_PUD_VI0_DATA5 BIT(8) +#define PUD1_PUD_VI0_DATA4 BIT(7) +#define PUD1_PUD_VI0_DATA3 BIT(6) +#define PUD1_PUD_VI0_DATA2 BIT(5) +#define PUD1_PUD_VI0_DATA1 BIT(4) +#define PUD1_PUD_VI0_DATA0 BIT(3) +#define PUD1_PUD_VI0_VSYNC_N BIT(2) +#define PUD1_PUD_VI0_HSYNC_N BIT(1) +#define PUD1_PUD_VI0_CLKENB BIT(0) + +#define PUD2_PUD_CANFD_CLK BIT(31) +#define PUD2_PUD_CANFD1_RX BIT(30) +#define PUD2_PUD_CANFD1_TX BIT(29) +#define PUD2_PUD_CANFD0_RX BIT(28) +#define PUD2_PUD_CANFD0_TX BIT(27) +#define PUD2_PUD_AVB0_AVTP_CAPTURE BIT(26) +#define PUD2_PUD_AVB0_AVTP_MATCH BIT(25) +#define PUD2_PUD_AVB0_LINK BIT(24) +#define PUD2_PUD_AVB0_PHY_INT BIT(23) +#define PUD2_PUD_AVB0_MAGIC BIT(22) +#define PUD2_PUD_AVB0_MDC BIT(21) +#define PUD2_PUD_AVB0_MDIO BIT(20) +#define PUD2_PUD_AVB0_TXCREFCLK BIT(19) +#define PUD2_PUD_AVB0_TD3 BIT(18) +#define PUD2_PUD_AVB0_TD2 BIT(17) +#define PUD2_PUD_AVB0_TD1 BIT(16) +#define PUD2_PUD_AVB0_TD0 BIT(15) +#define PUD2_PUD_AVB0_TXC BIT(14) +#define PUD2_PUD_AVB0_TX_CTL BIT(13) +#define PUD2_PUD_AVB0_RD3 BIT(12) +#define PUD2_PUD_AVB0_RD2 BIT(11) +#define PUD2_PUD_AVB0_RD1 BIT(10) +#define PUD2_PUD_AVB0_RD0 BIT(9) +#define PUD2_PUD_AVB0_RXC BIT(8) +#define PUD2_PUD_AVB0_RX_CTL BIT(7) +#define PUD2_PUD_SDA2 BIT(6) +#define PUD2_PUD_SCL2 BIT(5) +#define PUD2_PUD_SDA1 BIT(4) +#define PUD2_PUD_SCL1 BIT(3) +#define PUD2_PUD_SDA0 BIT(2) +#define PUD2_PUD_SCL0 BIT(1) +#define PUD2_PUD_VI1_FIELD BIT(0) + +#define PUD3_PUD_DIGRF_CLKOUT BIT(16) +#define PUD3_PUD_DIGRF_CLKIN BIT(15) +#define PUD3_PUD_RPC_INT_N BIT(14) +#define PUD3_PUD_RPC_WP_N BIT(13) +#define PUD3_PUD_RPC_RESET_N BIT(12) +#define PUD3_PUD_QSPI1_SSL BIT(11) +#define PUD3_PUD_QSPI1_IO3 BIT(10) +#define PUD3_PUD_QSPI1_IO2 BIT(9) +#define PUD3_PUD_QSPI1_MISO_IO1 BIT(8) +#define PUD3_PUD_QSPI1_MOSI_IO0 BIT(7) +#define PUD3_PUD_QSPI1_SPCLK BIT(6) +#define PUD3_PUD_QSPI0_SSL BIT(5) +#define PUD3_PUD_QSPI0_IO3 BIT(4) +#define PUD3_PUD_QSPI0_IO2 BIT(3) +#define PUD3_PUD_QSPI0_MISO_IO1 BIT(2) +#define PUD3_PUD_QSPI0_MOSI_IO0 BIT(1) +#define PUD3_PUD_QSPI0_SPCLK BIT(0) + +#define MOD_SEL0_sel_hscif0 BIT(10) +#define MOD_SEL0_sel_scif1 BIT(9) +#define MOD_SEL0_sel_canfd0 BIT(8) +#define MOD_SEL0_sel_pwm4 BIT(7) +#define MOD_SEL0_sel_pwm3 BIT(6) +#define MOD_SEL0_sel_pwm2 BIT(5) +#define MOD_SEL0_sel_pwm1 BIT(4) +#define MOD_SEL0_sel_pwm0 BIT(3) +#define MOD_SEL0_sel_rfso BIT(2) +#define MOD_SEL0_sel_rsp BIT(1) +#define MOD_SEL0_sel_tmu BIT(0) + +/* SCIF3 Registers for Dummy write */ +#define SCIF3_BASE (0xE6C50000U) +#define SCIF3_SCFCR (SCIF3_BASE + 0x0018U) +#define SCIF3_SCFDR (SCIF3_BASE + 0x001CU) +#define SCFCR_DATA (0x0000U) + +/* Realtime module stop control */ +#define CPG_BASE (0xE6150000U) +#define CPG_MSTPSR0 (CPG_BASE + 0x0030U) +#define CPG_RMSTPCR0 (CPG_BASE + 0x0110U) +#define RMSTPCR0_RTDMAC (0x00200000U) + +/* RT-DMAC Registers */ +#define RTDMAC_CH (0U) /* choose 0 to 15 */ + +#define RTDMAC_BASE (0xFFC10000U) +#define RTDMAC_RDMOR (RTDMAC_BASE + 0x0060U) +#define RTDMAC_RDMCHCLR (RTDMAC_BASE + 0x0080U) +#define RTDMAC_RDMSAR(x) (RTDMAC_BASE + 0x8000U + (0x80U * (x))) +#define RTDMAC_RDMDAR(x) (RTDMAC_BASE + 0x8004U + (0x80U * (x))) +#define RTDMAC_RDMTCR(x) (RTDMAC_BASE + 0x8008U + (0x80U * (x))) +#define RTDMAC_RDMCHCR(x) (RTDMAC_BASE + 0x800CU + (0x80U * (x))) +#define RTDMAC_RDMCHCRB(x) (RTDMAC_BASE + 0x801CU + (0x80U * (x))) +#define RTDMAC_RDMDPBASE(x) (RTDMAC_BASE + 0x8050U + (0x80U * (x))) +#define RTDMAC_DESC_BASE (RTDMAC_BASE + 0xA000U) +#define RTDMAC_DESC_RDMSAR (RTDMAC_DESC_BASE + 0x0000U) +#define RTDMAC_DESC_RDMDAR (RTDMAC_DESC_BASE + 0x0004U) +#define RTDMAC_DESC_RDMTCR (RTDMAC_DESC_BASE + 0x0008U) + +#define RDMOR_DME (0x0001U) /* DMA Master Enable */ +#define RDMCHCR_DPM_INFINITE (0x30000000U) /* Infinite repeat mode */ +#define RDMCHCR_RPT_TCR (0x02000000U) /* enable to update TCR */ +#define RDMCHCR_TS_2 (0x00000008U) /* Word(2byte) units transfer */ +#define RDMCHCR_RS_AUTO (0x00000400U) /* Auto request */ +#define RDMCHCR_DE (0x00000001U) /* DMA Enable */ +#define RDMCHCRB_DRST (0x00008000U) /* Descriptor reset */ +#define RDMCHCRB_SLM_256 (0x00000080U) /* once in 256 clock cycle */ +#define RDMDPBASE_SEL_EXT (0x00000001U) /* External memory use */ + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +static void start_rtdma0_descriptor(void) +{ + uint32_t reg; + + /* Module stop clear */ + while ((mmio_read_32(CPG_MSTPSR0) & RMSTPCR0_RTDMAC) != 0U) { + reg = mmio_read_32(CPG_RMSTPCR0); + reg &= ~RMSTPCR0_RTDMAC; + cpg_write(CPG_RMSTPCR0, reg); + } + + /* Initialize ch0, Reset Descriptor */ + mmio_write_32(RTDMAC_RDMCHCLR, BIT(RTDMAC_CH)); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_DRST); + + /* Enable DMA */ + mmio_write_16(RTDMAC_RDMOR, RDMOR_DME); + + /* Set first transfer */ + mmio_write_32(RTDMAC_RDMSAR(RTDMAC_CH), RCAR_PRR); + mmio_write_32(RTDMAC_RDMDAR(RTDMAC_CH), SCIF3_SCFDR); + mmio_write_32(RTDMAC_RDMTCR(RTDMAC_CH), 0x00000001U); + + /* Set descriptor */ + mmio_write_32(RTDMAC_DESC_RDMSAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMDAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMTCR, 0x00200000U); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_SLM_256); + mmio_write_32(RTDMAC_RDMDPBASE(RTDMAC_CH), RTDMAC_DESC_BASE + | RDMDPBASE_SEL_EXT); + + /* Set transfer parameter, Start transfer */ + mmio_write_32(RTDMAC_RDMCHCR(RTDMAC_CH), RDMCHCR_DPM_INFINITE + | RDMCHCR_RPT_TCR + | RDMCHCR_TS_2 + | RDMCHCR_RS_AUTO + | RDMCHCR_DE); +} + +void pfc_init_v3m(void) +{ + /* Work around for PFC eratta */ + start_rtdma0_descriptor(); + + // pin function + // md[4:1]!=0000 + /* initialize GPIO/perihperal function select */ + + pfc_reg_write(PFC_GPSR0, 0x00000000); + + pfc_reg_write(PFC_GPSR1, GPSR1_CANFD_CLK); + + pfc_reg_write(PFC_GPSR2, 0x00000000); + + pfc_reg_write(PFC_GPSR3, 0x00000000); + + pfc_reg_write(PFC_GPSR4, GPSR4_SDA2 + | GPSR4_SCL2); + + pfc_reg_write(PFC_GPSR5, GPSR5_QSPI1_SSL + | GPSR5_QSPI1_IO3 + | GPSR5_QSPI1_IO2 + | GPSR5_QSPI1_MISO_IO1 + | GPSR5_QSPI1_MOSI_IO0 + | GPSR5_QSPI1_SPCLK + | GPSR5_QSPI0_SSL + | GPSR5_QSPI0_IO3 + | GPSR5_QSPI0_IO2 + | GPSR5_QSPI0_MISO_IO1 + | GPSR5_QSPI0_MOSI_IO0 + | GPSR5_QSPI0_SPCLK); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(4) + | IPSR_16_FUNC(4) + | IPSR_12_FUNC(4) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(4) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize POC Control */ + + pfc_reg_write(PFC_POCCTRL0, IOCTRL30_POC_VI0_DATA5 + | IOCTRL30_POC_VI0_DATA4 + | IOCTRL30_POC_VI0_DATA3 + | IOCTRL30_POC_VI0_DATA2 + | IOCTRL30_POC_VI0_DATA1 + | IOCTRL30_POC_VI0_DATA0 + | IOCTRL30_POC_VI0_VSYNC_N + | IOCTRL30_POC_VI0_HSYNC_N + | IOCTRL30_POC_VI0_CLKENB + | IOCTRL30_POC_VI0_CLK + | IOCTRL30_POC_DU_EXODDF_DU_ODDF_DISP_CDE + | IOCTRL30_POC_DU_EXVSYNC_DU_VSYNC + | IOCTRL30_POC_DU_EXHSYNC_DU_HSYNC + | IOCTRL30_POC_DU_DOTCLKOUT + | IOCTRL30_POC_DU_DB7 + | IOCTRL30_POC_DU_DB6 + | IOCTRL30_POC_DU_DB5 + | IOCTRL30_POC_DU_DB4 + | IOCTRL30_POC_DU_DB3 + | IOCTRL30_POC_DU_DB2 + | IOCTRL30_POC_DU_DG7 + | IOCTRL30_POC_DU_DG6 + | IOCTRL30_POC_DU_DG5 + | IOCTRL30_POC_DU_DG4 + | IOCTRL30_POC_DU_DG3 + | IOCTRL30_POC_DU_DG2 + | IOCTRL30_POC_DU_DR7 + | IOCTRL30_POC_DU_DR6 + | IOCTRL30_POC_DU_DR5 + | IOCTRL30_POC_DU_DR4 + | IOCTRL30_POC_DU_DR3 + | IOCTRL30_POC_DU_DR2); + + pfc_reg_write(PFC_IOCTRL31, IOCTRL31_POC_DUMMY_31 + | IOCTRL31_POC_DUMMY_30 + | IOCTRL31_POC_DUMMY_29 + | IOCTRL31_POC_DUMMY_28 + | IOCTRL31_POC_DUMMY_27 + | IOCTRL31_POC_DUMMY_26 + | IOCTRL31_POC_DUMMY_25 + | IOCTRL31_POC_DUMMY_24 + | IOCTRL31_POC_VI1_FIELD + | IOCTRL31_POC_VI1_DATA11 + | IOCTRL31_POC_VI1_DATA10 + | IOCTRL31_POC_VI1_DATA9 + | IOCTRL31_POC_VI1_DATA8 + | IOCTRL31_POC_VI1_DATA7 + | IOCTRL31_POC_VI1_DATA6 + | IOCTRL31_POC_VI1_DATA5 + | IOCTRL31_POC_VI1_DATA4 + | IOCTRL31_POC_VI1_DATA3 + | IOCTRL31_POC_VI1_DATA2 + | IOCTRL31_POC_VI1_DATA1 + | IOCTRL31_POC_VI1_DATA0 + | IOCTRL31_POC_VI1_VSYNC_N + | IOCTRL31_POC_VI1_HSYNC_N + | IOCTRL31_POC_VI1_CLKENB + | IOCTRL31_POC_VI1_CLK + | IOCTRL31_POC_VI0_FIELD + | IOCTRL31_POC_VI0_DATA11 + | IOCTRL31_POC_VI0_DATA10 + | IOCTRL31_POC_VI0_DATA9 + | IOCTRL31_POC_VI0_DATA8 + | IOCTRL31_POC_VI0_DATA7 + | IOCTRL31_POC_VI0_DATA6); + + pfc_reg_write(PFC_POCCTRL2, 0x00000000); + + pfc_reg_write(PFC_TDSELCTRL0, 0x00000000); + + /* initialize Pull enable */ + pfc_reg_write(PFC_PUEN0, PUEN0_PUEN_VI0_CLK + | PUEN0_PUEN_TDI + | PUEN0_PUEN_TMS + | PUEN0_PUEN_TCK + | PUEN0_PUEN_TRST_N + | PUEN0_PUEN_IRQ0 + | PUEN0_PUEN_FSCLKST_N + | PUEN0_PUEN_DU_EXHSYNC_DU_HSYNC + | PUEN0_PUEN_DU_DOTCLKOUT + | PUEN0_PUEN_DU_DB7 + | PUEN0_PUEN_DU_DB6 + | PUEN0_PUEN_DU_DB5 + | PUEN0_PUEN_DU_DB4 + | PUEN0_PUEN_DU_DB3 + | PUEN0_PUEN_DU_DB2 + | PUEN0_PUEN_DU_DG7 + | PUEN0_PUEN_DU_DG6 + | PUEN0_PUEN_DU_DG5 + | PUEN0_PUEN_DU_DG4 + | PUEN0_PUEN_DU_DG3 + | PUEN0_PUEN_DU_DG2 + | PUEN0_PUEN_DU_DR7 + | PUEN0_PUEN_DU_DR6 + | PUEN0_PUEN_DU_DR5 + | PUEN0_PUEN_DU_DR4 + | PUEN0_PUEN_DU_DR3 + | PUEN0_PUEN_DU_DR2); + + pfc_reg_write(PFC_PUEN1, PUEN1_PUEN_VI1_DATA11 + | PUEN1_PUEN_VI1_DATA10 + | PUEN1_PUEN_VI1_DATA9 + | PUEN1_PUEN_VI1_DATA8 + | PUEN1_PUEN_VI1_DATA7 + | PUEN1_PUEN_VI1_DATA6 + | PUEN1_PUEN_VI1_DATA5 + | PUEN1_PUEN_VI1_DATA4 + | PUEN1_PUEN_VI1_DATA3 + | PUEN1_PUEN_VI1_DATA2 + | PUEN1_PUEN_VI1_DATA1 + | PUEN1_PUEN_VI1_DATA0 + | PUEN1_PUEN_VI1_VSYNC_N + | PUEN1_PUEN_VI1_HSYNC_N + | PUEN1_PUEN_VI1_CLKENB + | PUEN1_PUEN_VI1_CLK + | PUEN1_PUEN_VI0_DATA11 + | PUEN1_PUEN_VI0_DATA10 + | PUEN1_PUEN_VI0_DATA9 + | PUEN1_PUEN_VI0_DATA8 + | PUEN1_PUEN_VI0_DATA7 + | PUEN1_PUEN_VI0_DATA6 + | PUEN1_PUEN_VI0_DATA5 + | PUEN1_PUEN_VI0_DATA4 + | PUEN1_PUEN_VI0_DATA3 + | PUEN1_PUEN_VI0_DATA2 + | PUEN1_PUEN_VI0_DATA1); + + pfc_reg_write(PFC_PUEN2, PUEN2_PUEN_CANFD_CLK + | PUEN2_PUEN_CANFD1_RX + | PUEN2_PUEN_CANFD1_TX + | PUEN2_PUEN_CANFD0_RX + | PUEN2_PUEN_CANFD0_TX + | PUEN2_PUEN_AVB0_AVTP_CAPTURE + | PUEN2_PUEN_AVB0_AVTP_MATCH + | PUEN2_PUEN_AVB0_LINK + | PUEN2_PUEN_AVB0_PHY_INT + | PUEN2_PUEN_AVB0_MAGIC + | PUEN2_PUEN_AVB0_TXCREFCLK + | PUEN2_PUEN_AVB0_TD3 + | PUEN2_PUEN_AVB0_TD2 + | PUEN2_PUEN_AVB0_TD1 + | PUEN2_PUEN_AVB0_TD0 + | PUEN2_PUEN_AVB0_TXC + | PUEN2_PUEN_AVB0_TX_CTL + | PUEN2_PUEN_AVB0_RD3 + | PUEN2_PUEN_AVB0_RD2 + | PUEN2_PUEN_AVB0_RD1 + | PUEN2_PUEN_AVB0_RD0 + | PUEN2_PUEN_AVB0_RXC + | PUEN2_PUEN_AVB0_RX_CTL + | PUEN2_PUEN_VI1_FIELD); + + pfc_reg_write(PFC_PUEN3, PUEN3_PUEN_DIGRF_CLKOUT + | PUEN3_PUEN_DIGRF_CLKIN); + + /* initialize PUD Control */ + pfc_reg_write(PFC_PUD0, PUD0_PUD_VI0_CLK + | PUD0_PUD_IRQ0 + | PUD0_PUD_FSCLKST_N + | PUD0_PUD_DU_EXODDF_DU_ODDF_DISP_CDE + | PUD0_PUD_DU_EXVSYNC_DU_VSYNC + | PUD0_PUD_DU_EXHSYNC_DU_HSYNC + | PUD0_PUD_DU_DOTCLKOUT + | PUD0_PUD_DU_DB7 + | PUD0_PUD_DU_DB6 + | PUD0_PUD_DU_DB5 + | PUD0_PUD_DU_DB4 + | PUD0_PUD_DU_DB3 + | PUD0_PUD_DU_DB2 + | PUD0_PUD_DU_DG7 + | PUD0_PUD_DU_DG6 + | PUD0_PUD_DU_DG5 + | PUD0_PUD_DU_DG4 + | PUD0_PUD_DU_DG3 + | PUD0_PUD_DU_DG2 + | PUD0_PUD_DU_DR7 + | PUD0_PUD_DU_DR6 + | PUD0_PUD_DU_DR5 + | PUD0_PUD_DU_DR4 + | PUD0_PUD_DU_DR3 + | PUD0_PUD_DU_DR2); + + pfc_reg_write(PFC_PUD1, PUD1_PUD_VI1_DATA11 + | PUD1_PUD_VI1_DATA10 + | PUD1_PUD_VI1_DATA9 + | PUD1_PUD_VI1_DATA8 + | PUD1_PUD_VI1_DATA7 + | PUD1_PUD_VI1_DATA6 + | PUD1_PUD_VI1_DATA5 + | PUD1_PUD_VI1_DATA4 + | PUD1_PUD_VI1_DATA3 + | PUD1_PUD_VI1_DATA2 + | PUD1_PUD_VI1_DATA1 + | PUD1_PUD_VI1_DATA0 + | PUD1_PUD_VI1_VSYNC_N + | PUD1_PUD_VI1_HSYNC_N + | PUD1_PUD_VI1_CLKENB + | PUD1_PUD_VI1_CLK + | PUD1_PUD_VI0_DATA11 + | PUD1_PUD_VI0_DATA10 + | PUD1_PUD_VI0_DATA9 + | PUD1_PUD_VI0_DATA8 + | PUD1_PUD_VI0_DATA7 + | PUD1_PUD_VI0_DATA6 + | PUD1_PUD_VI0_DATA5 + | PUD1_PUD_VI0_DATA4 + | PUD1_PUD_VI0_DATA3 + | PUD1_PUD_VI0_DATA2 + | PUD1_PUD_VI0_DATA1 + | PUD1_PUD_VI0_DATA0 + | PUD1_PUD_VI0_VSYNC_N + | PUD1_PUD_VI0_HSYNC_N + | PUD1_PUD_VI0_CLKENB); + + pfc_reg_write(PFC_PUD2, PUD2_PUD_CANFD_CLK + | PUD2_PUD_CANFD1_RX + | PUD2_PUD_CANFD1_TX + | PUD2_PUD_CANFD0_RX + | PUD2_PUD_CANFD0_TX + | PUD2_PUD_AVB0_AVTP_CAPTURE + | PUD2_PUD_VI1_FIELD); + + pfc_reg_write(PFC_PUD3, PUD3_PUD_DIGRF_CLKOUT + | PUD3_PUD_DIGRF_CLKIN); + + /* initialize Module Select */ + pfc_reg_write(PFC_MOD_SEL0, 0x00000000); + + // gpio + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000000U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000000U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL3, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h new file mode 100644 index 0000000..7bab92f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_V3M_H +#define PFC_INIT_V3M_H + +void pfc_init_v3m(void); + +#endif /* PFC_INIT_V3M_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc.mk b/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc.mk new file mode 100644 index 0000000..f1dd92c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc.mk @@ -0,0 +1,69 @@ +# +# Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${RCAR_LSI},${RCAR_AUTO}) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + BL2_SOURCES += drivers/renesas/rcar/pfc/M3/pfc_init_m3.c + BL2_SOURCES += drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c + BL2_SOURCES += drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c + +else ifdef RCAR_LSI_CUT_COMPAT + ifeq (${RCAR_LSI},${RCAR_H3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + endif + ifeq (${RCAR_LSI},${RCAR_H3N}) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + endif + ifeq (${RCAR_LSI},${RCAR_M3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/M3/pfc_init_m3.c + endif + ifeq (${RCAR_LSI},${RCAR_M3N}) + BL2_SOURCES += drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c + endif + ifeq (${RCAR_LSI},${RCAR_V3M}) + BL2_SOURCES += drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c + endif + ifeq (${RCAR_LSI},${RCAR_E3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/E3/pfc_init_e3.c + endif + ifeq (${RCAR_LSI},${RCAR_D3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/D3/pfc_init_d3.c + endif +else + ifeq (${RCAR_LSI},${RCAR_H3}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + else ifeq (${LSI_CUT},11) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + else +# LSI_CUT 20 or later + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_H3N}) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + endif + ifeq (${RCAR_LSI},${RCAR_M3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/M3/pfc_init_m3.c + endif + ifeq (${RCAR_LSI},${RCAR_M3N}) + BL2_SOURCES += drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c + endif + ifeq (${RCAR_LSI},${RCAR_V3M}) + BL2_SOURCES += drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c + endif + ifeq (${RCAR_LSI},${RCAR_E3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/E3/pfc_init_e3.c + endif + ifeq (${RCAR_LSI},${RCAR_D3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/D3/pfc_init_d3.c + endif +endif + +BL2_SOURCES += drivers/renesas/rcar/pfc/pfc_init.c diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c new file mode 100644 index 0000000..8810667 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "rcar_def.h" +#if RCAR_LSI == RCAR_AUTO +#include "H3/pfc_init_h3_v1.h" +#include "H3/pfc_init_h3_v2.h" +#include "M3/pfc_init_m3.h" +#include "M3N/pfc_init_m3n.h" +#include "V3M/pfc_init_v3m.h" +#endif +#if (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) /* H3 */ +#include "H3/pfc_init_h3_v1.h" +#include "H3/pfc_init_h3_v2.h" +#endif +#if RCAR_LSI == RCAR_M3 /* M3 */ +#include "M3/pfc_init_m3.h" +#endif +#if RCAR_LSI == RCAR_M3N /* M3N */ +#include "M3N/pfc_init_m3n.h" +#endif +#if RCAR_LSI == RCAR_V3M /* V3M */ +#include "V3M/pfc_init_v3m.h" +#endif +#if RCAR_LSI == RCAR_E3 /* E3 */ +#include "E3/pfc_init_e3.h" +#endif +#if RCAR_LSI == RCAR_D3 /* D3 */ +#include "D3/pfc_init_d3.h" +#endif + +#define PRR_PRODUCT_ERR(reg) \ + do { \ + ERROR("LSI Product ID(PRR=0x%x) PFC initialize not supported.\n", \ + reg); \ + panic(); \ + } while (0) + +#define PRR_CUT_ERR(reg) \ + do { \ + ERROR("LSI Cut ID(PRR=0x%x) PFC initialize not supported.\n", \ + reg); \ + panic();\ + } while (0) + +void rcar_pfc_init(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); +#if RCAR_LSI == RCAR_AUTO + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: /* H3 Ver.1.0 */ + pfc_init_h3_v1(); + break; + case PRR_PRODUCT_11: /* H3 Ver.1.1 */ + pfc_init_h3_v1(); + break; + default: /* H3 Ver.2.0 or later */ + pfc_init_h3_v2(); + break; + } + break; + case PRR_PRODUCT_M3: + pfc_init_m3(); + break; + case PRR_PRODUCT_M3N: + pfc_init_m3n(); + break; + case PRR_PRODUCT_V3M: + pfc_init_v3m(); + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } + +#elif RCAR_LSI_CUT_COMPAT + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: +#if (RCAR_LSI != RCAR_H3) && (RCAR_LSI != RCAR_H3N) + PRR_PRODUCT_ERR(reg); +#else + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: /* H3 Ver.1.0 */ + pfc_init_h3_v1(); + break; + case PRR_PRODUCT_11: /* H3 Ver.1.1 */ + pfc_init_h3_v1(); + break; + default: /* H3 Ver.2.0 or later */ + pfc_init_h3_v2(); + break; + } +#endif + break; + case PRR_PRODUCT_M3: +#if RCAR_LSI != RCAR_M3 + PRR_PRODUCT_ERR(reg); +#else + pfc_init_m3(); +#endif + break; + case PRR_PRODUCT_M3N: +#if RCAR_LSI != RCAR_M3N + PRR_PRODUCT_ERR(reg); +#else + pfc_init_m3n(); +#endif + break; + case PRR_PRODUCT_V3M: +#if RCAR_LSI != RCAR_V3M + PRR_PRODUCT_ERR(reg); +#else + pfc_init_v3m(); +#endif + break; + case PRR_PRODUCT_E3: +#if RCAR_LSI != RCAR_E3 + PRR_PRODUCT_ERR(reg); +#else + pfc_init_e3(); +#endif + break; + case PRR_PRODUCT_D3: +#if RCAR_LSI != RCAR_D3 + PRR_PRODUCT_ERR(reg); +#else + pfc_init_d3(); +#endif + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } + +#else +#if (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) /* H3 */ +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* H3 Ver.1.0 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_10) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_h3_v1(); +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* H3 Ver.1.1 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_11) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_h3_v1(); +#else + /* H3 Ver.2.0 or later */ + if (PRR_PRODUCT_H3 != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_h3_v2(); +#endif +#elif RCAR_LSI == RCAR_M3 /* M3 */ + if ((PRR_PRODUCT_M3) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_m3(); +#elif RCAR_LSI == RCAR_M3N /* M3N */ + if ((PRR_PRODUCT_M3N) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_m3n(); +#elif RCAR_LSI == RCAR_V3M /* V3M */ + if ((PRR_PRODUCT_V3M) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_v3m(); +#elif RCAR_LSI == RCAR_E3 /* E3 */ + if ((PRR_PRODUCT_E3) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_e3(); +#elif RCAR_LSI == RCAR_D3 /* D3 */ + if ((PRR_PRODUCT_D3) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_d3(); +#else +#error "Don't have PFC initialize routine(unknown)." +#endif +#endif +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c new file mode 100644 index 0000000..b96e822 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_d3.h" + +#define RCAR_QOS_VERSION "rev.0.05" + +#include "qos_init_d3_mstat.h" + +struct rcar_gen3_dbsc_qos_settings d3_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000300 }, + { DBSC_DBSCHQOS91, 0x000002F0 }, + { DBSC_DBSCHQOS92, 0x00000200 }, + { DBSC_DBSCHQOS93, 0x00000100 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_d3(void) +{ + rcar_qos_dbsc_setting(d3_qos, ARRAY_SIZE(d3_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH + ERROR("DRAM Split 4ch not supported.(D3)"); + panic(); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + ERROR("DRAM Split 2ch not supported.(D3)"); + panic(); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO + ERROR("DRAM Split Auto not supported.(D3)"); + panic(); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_LINEAR +/* NOTICE("BL2: DRAM Split is OFF\n"); */ + /* Split setting(DDR 1ch) */ + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + ERROR("DRAM split is an invalid value.(D3)"); + panic(); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_RAS, 0x00000020U); + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_RAEN, 0x00000001U); + io_write_32(QOSCTRL_REGGD, 0x00000000U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201U); + io_write_32(QOSCTRL_DANT, 0x00100804U); + io_write_32(QOSCTRL_EC, 0x00000000U); + io_write_64(QOSCTRL_EMS, 0x0000000000000000U); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0xC7840001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + io_write_32(QOSCTRL_EARLYR, 0x00000000U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + io_write_32(QOSCTRL_STATGEN0, 0x00000000U); + + /* GPU setting */ + io_write_32(0xFD812030U, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, 0x030500ACU); + io_write_32(QOSCTRL_REF_ARS, 0x00780000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + io_write_32(GPU_ACT_GRD, 0x00001234U); + io_write_32(GPU_ACT0, 0x00000000U); + io_write_32(GPU_ACT1, 0x00000000U); + io_write_32(GPU_ACT2, 0x00000000U); + io_write_32(GPU_ACT3, 0x00000000U); + + /* RT bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_EC, 0x00000000U); + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h new file mode 100644 index 0000000..968ee7a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H_D3__ +#define QOS_INIT_H_D3__ + +void qos_init_d3(void); + +#endif /* QOS_INIT_H_D3__ */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h new file mode 100644 index 0000000..cbf1f65 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004340000FFFFUL, + /* 0x0038, */ 0x001004140000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140B030000FFFFUL, + /* 0x0060, */ 0x001408610000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410620000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x000C041C0000FFFFUL, + /* 0x00A8, */ 0x000C04090000FFFFUL, + /* 0x00B0, */ 0x000C04110000FFFFUL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x000C041C0000FFFFUL, + /* 0x00C8, */ 0x000C04090000FFFFUL, + /* 0x00D0, */ 0x000C04110000FFFFUL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x001018570000FFFFUL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001008570000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x001008520000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00100CA30000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x000C04020000FFFFUL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04090000FFFFUL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02A0, */ 0x000C04050000FFFFUL, + /* 0x02A8, */ 0x000C04050000FFFFUL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x000C04050000FFFFUL, + /* 0x02D8, */ 0x000C04050000FFFFUL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x00110090060FA001UL, + /* 0x01C8, */ 0x00110090060FA001UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0011001006004401UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0011001006004401UL, + /* 0x0218, */ 0x0011001006009801UL, + /* 0x0220, */ 0x0011001006009801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011001006009801UL, + /* 0x0238, */ 0x0011001006009801UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x0011001006003401UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x0011001006003401UL, + /* 0x02F0, */ 0x00110090060FA001UL, + /* 0x02F8, */ 0x00110090060FA001UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001006003401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x00120090060FA001UL, + /* 0x0360, */ 0x00120090060FA001UL, + /* 0x0368, */ 0x0012001006003401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001006003401UL, +}; +#endif + diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c new file mode 100644 index 0000000..6f4c66c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_e3_v10.h" + +#define RCAR_QOS_VERSION "rev.0.05" + +#define REF_ARS_ARBSTOPCYCLE_E3 (((SL_INIT_SSLOTCLK_E3) - 5U) << 16U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_e3_v10_mstat390.h" +#else +#include "qos_init_e3_v10_mstat780.h" +#endif + +#endif + +struct rcar_gen3_dbsc_qos_settings e3_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000100 }, + { DBSC_DBSCHQOS91, 0x000000F0 }, + { DBSC_DBSCHQOS92, 0x000000A0 }, + { DBSC_DBSCHQOS93, 0x00000040 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_e3_v10(void) +{ + rcar_qos_dbsc_setting(e3_qos, ARRAY_SIZE(e3_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_E3 +#error "Don't set DRAM Split 4ch(E3)" +#else + ERROR("DRAM Split 4ch not supported.(E3)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) +#if RCAR_LSI == RCAR_E3 +#error "Don't set DRAM Split 2ch(E3)" +#else + ERROR("DRAM Split 2ch not supported.(E3)"); + panic(); +#endif +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 7.8 usec\n"); +#endif + + io_write_32(QOSCTRL_RAS, 0x00000020U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + io_write_32(QOSCTRL_DANT, 0x00100804U); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_EARLYR, 0x00000000U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_E3); + io_write_32(QOSCTRL_REF_ARS, REF_ARS_ARBSTOPCYCLE_E3); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h new file mode 100644 index 0000000..2c1d8c5 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_E3_V10_H +#define QOS_INIT_E3_V10_H + +void qos_init_e3_v10(void); + +#endif /* QOS_INIT_E3_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h new file mode 100644 index 0000000..d7f9d14 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008620000FFFFUL, + /* 0x0038, */ 0x001008620000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001415260000FFFFUL, + /* 0x0060, */ 0x001415260000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414930000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08380000FFFFUL, + /* 0x00a8, */ 0x000C04110000FFFFUL, + /* 0x00b0, */ 0x000C04150000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08380000FFFFUL, + /* 0x00c8, */ 0x000C04110000FFFFUL, + /* 0x00d0, */ 0x000C04150000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001018580000FFFFUL, + /* 0x00f8, */ 0x000C084F0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001008580000FFFFUL, + /* 0x0118, */ 0x000C21E40000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001008530000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00100C960000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001008530000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0010042A0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00101D8D0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001008530000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04020000FFFFUL, + /* 0x01f0, */ 0x000C04090000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04090000FFFFUL, + /* 0x0210, */ 0x000C04090000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFFFUL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x000C08110000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02a0, */ 0x000C04090000FFFFUL, + /* 0x02a8, */ 0x000C04090000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x000C04020000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04090000FFFFUL, + /* 0x02d8, */ 0x000C04090000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x000C04020000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005F03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060005FFFC01UL, + /* 0x01c8, */ 0x0021060005FFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010005F79801UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010005F79801UL, + /* 0x0218, */ 0x0011010005F79801UL, + /* 0x0220, */ 0x0011010005F79801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010005F79801UL, + /* 0x0238, */ 0x0011010005F79801UL, + /* 0x0240, */ 0x0012010005F79801UL, + /* 0x0248, */ 0x0011010005F79801UL, + /* 0x0250, */ 0x0012010005F79801UL, + /* 0x0258, */ 0x0011010005F79801UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060005FFFC01UL, + /* 0x02f8, */ 0x0011060005FFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001005F03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060005FFFC01UL, + /* 0x0360, */ 0x0012060005FFFC01UL, + /* 0x0368, */ 0x0012001005F03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001005F03401UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h new file mode 100644 index 0000000..439cafe --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001010C40000FFFFUL, + /* 0x0038, */ 0x001010C40000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00142A4B0000FFFFUL, + /* 0x0060, */ 0x00142A4B0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001429260000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C10700000FFFFUL, + /* 0x00a8, */ 0x000C08210000FFFFUL, + /* 0x00b0, */ 0x000C082A0000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C10700000FFFFUL, + /* 0x00c8, */ 0x000C08210000FFFFUL, + /* 0x00d0, */ 0x000C082A0000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x00102CAF0000FFFFUL, + /* 0x00f8, */ 0x000C0C9D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100CAF0000FFFFUL, + /* 0x0118, */ 0x000C43C80000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100CA50000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010152C0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100CA50000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008530000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001037190000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100CA50000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04040000FFFFUL, + /* 0x01f0, */ 0x000C08110000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04110000FFFFUL, + /* 0x0210, */ 0x000C08110000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C18530000FFFFUL, + /* 0x0268, */ 0x00141C070000FFFFUL, + /* 0x0270, */ 0x001404040000FFFFUL, + /* 0x0278, */ 0x000C0C210000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x00141C070000FFFFUL, + /* 0x0298, */ 0x001404040000FFFFUL, + /* 0x02a0, */ 0x000C04110000FFFFUL, + /* 0x02a8, */ 0x000C04110000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x000C04040000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04110000FFFFUL, + /* 0x02d8, */ 0x000C04110000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x000C04040000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04040000FFFFUL, + /* 0x0378, */ 0x000C04040000FFFFUL, + /* 0x0380, */ 0x000C04110000FFFFUL, + /* 0x0388, */ 0x000C04110000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001002F03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060002FFFC01UL, + /* 0x01c8, */ 0x0021060002FFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010002F3CC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010002F3CC01UL, + /* 0x0218, */ 0x0011010002F3CC01UL, + /* 0x0220, */ 0x0011010002F3CC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010002F3CC01UL, + /* 0x0238, */ 0x0011010002F3CC01UL, + /* 0x0240, */ 0x0012010002F3CC01UL, + /* 0x0248, */ 0x0011010002F3CC01UL, + /* 0x0250, */ 0x0012010002F3CC01UL, + /* 0x0258, */ 0x0011010002F3CC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060002FFFC01UL, + /* 0x02f8, */ 0x0011060002FFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001002F03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060002FFFC01UL, + /* 0x0360, */ 0x0012060002FFFC01UL, + /* 0x0368, */ 0x0012001002F03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001002F03401UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c new file mode 100644 index 0000000..1fb43a7 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3_v10.h" + +#define RCAR_QOS_VERSION "rev.0.36" + +#include "qos_init_h3_v10_mstat.h" + +void qos_init_h3_v10(void) +{ + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 4ch\n"); + io_write_32(AXI_ADSPLCR0, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR1, 0x00000000U); + io_write_32(AXI_ADSPLCR2, 0xA8A90000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00000000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* AR Cache setting */ + io_write_32(0xE67D1000U, 0x00000100U); + io_write_32(0xE67D1008U, 0x00000100U); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_RAS, 0x00000040U); + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_REGGD, 0x00000004U); + io_write_64(QOSCTRL_DANN, 0x0202000004040404UL); + io_write_32(QOSCTRL_DANT, 0x003C1110U); + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 v1.* */ + io_write_64(QOSCTRL_EMS, 0x0000000000000000UL); + io_write_32(QOSCTRL_INSFC, 0xC7840001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK); + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + io_write_32(0xFD820808U, 0x00001234U); + io_write_32(0xFD820800U, 0x0000003FU); + io_write_32(0xFD821800U, 0x0000003FU); + io_write_32(0xFD822800U, 0x0000003FU); + io_write_32(0xFD823800U, 0x0000003FU); + io_write_32(0xFD824800U, 0x0000003FU); + io_write_32(0xFD825800U, 0x0000003FU); + io_write_32(0xFD826800U, 0x0000003FU); + io_write_32(0xFD827800U, 0x0000003FU); + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 v1.* */ +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h new file mode 100644 index 0000000..f96182a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3_V10_H +#define QOS_INIT_H3_V10_H + +void qos_init_h3_v10(void); + +#endif /* QOS_INIT_H3_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h new file mode 100644 index 0000000..fe63236 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x00140C050000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001404030000FFFFUL, + /* 0x0060, */ 0x001408060000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00140C050000FFFFUL, + /* 0x0090, */ 0x001408060000FFFFUL, + /* 0x0098, */ 0x001404020000FFFFUL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001004020000FFFFUL, + /* 0x0140, */ 0x001004020000FFFFUL, + /* 0x0148, */ 0x001004020000FFFFUL, + /* 0x0150, */ 0x001008050000FFFFUL, + /* 0x0158, */ 0x001008050000FFFFUL, + /* 0x0160, */ 0x001008050000FFFFUL, + /* 0x0168, */ 0x001008050000FFFFUL, + /* 0x0170, */ 0x001008050000FFFFUL, + /* 0x0178, */ 0x001004030000FFFFUL, + /* 0x0180, */ 0x001004030000FFFFUL, + /* 0x0188, */ 0x001004030000FFFFUL, + /* 0x0190, */ 0x001014140000FFFFUL, + /* 0x0198, */ 0x001014140000FFFFUL, + /* 0x01A0, */ 0x001008060000FFFFUL, + /* 0x01A8, */ 0x001008060000FFFFUL, + /* 0x01B0, */ 0x001008060000FFFFUL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x001000100C8FFC01UL, + /* 0x0008, */ 0x001000100C8FFC01UL, + /* 0x0010, */ 0x001000100C8FFC01UL, + /* 0x0018, */ 0x001000100C8FFC01UL, + /* 0x0020, */ 0x001000100C8FFC01UL, + /* 0x0028, */ 0x001000100C8FFC01UL, + /* 0x0030, */ 0x001000100C8FFC01UL, + /* 0x0038, */ 0x001000100C8FFC01UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001000100C8FFC01UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x001000100C8FFC01UL, + /* 0x0070, */ 0x001000100C8FFC01UL, + /* 0x0078, */ 0x001000100C8FFC01UL, + /* 0x0080, */ 0x001000100C8FFC01UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x001000100C8FFC01UL, + /* 0x00A8, */ 0x001000100C8FFC01UL, + /* 0x00B0, */ 0x001000100C8FFC01UL, + /* 0x00B8, */ 0x001000100C8FFC01UL, + /* 0x00C0, */ 0x001000100C8FFC01UL, + /* 0x00C8, */ 0x001000100C8FFC01UL, + /* 0x00D0, */ 0x001000100C8FFC01UL, + /* 0x00D8, */ 0x002000200C8FFC01UL, + /* 0x00E0, */ 0x002000200C8FFC01UL, + /* 0x00E8, */ 0x001000100C8FFC01UL, + /* 0x00F0, */ 0x001000100C8FFC01UL, + /* 0x00F8, */ 0x001000100C8FFC01UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x002000200C8FFC01UL, + /* 0x0110, */ 0x001000100C8FFC01UL, + /* 0x0118, */ 0x001000100C8FFC01UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x002000200C8FFC01UL, + /* 0x0130, */ 0x001000100C8FFC01UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x001000100C8FFC01UL, + /* 0x01C0, */ 0x001000200C8FFC01UL, + /* 0x01C8, */ 0x001000200C8FFC01UL, + /* 0x01D0, */ 0x001000200C8FFC01UL, + /* 0x01D8, */ 0x001000200C8FFC01UL, + /* 0x01E0, */ 0x001000100C8FFC01UL, + /* 0x01E8, */ 0x001000100C8FFC01UL, + /* 0x01F0, */ 0x001000100C8FFC01UL, + /* 0x01F8, */ 0x001000100C8FFC01UL, + /* 0x0200, */ 0x001000100C8FFC01UL, + /* 0x0208, */ 0x001000100C8FFC01UL, + /* 0x0210, */ 0x001000100C8FFC01UL, + /* 0x0218, */ 0x001000100C8FFC01UL, + /* 0x0220, */ 0x001000100C8FFC01UL, + /* 0x0228, */ 0x001000100C8FFC01UL, + /* 0x0230, */ 0x001000100C8FFC01UL, + /* 0x0238, */ 0x001000100C8FFC01UL, + /* 0x0240, */ 0x001000100C8FFC01UL, + /* 0x0248, */ 0x001000100C8FFC01UL, + /* 0x0250, */ 0x001000100C8FFC01UL, + /* 0x0258, */ 0x001000100C8FFC01UL, + /* 0x0260, */ 0x001000100C8FFC01UL, + /* 0x0268, */ 0x001000100C8FFC01UL, + /* 0x0270, */ 0x001000100C8FFC01UL, + /* 0x0278, */ 0x001000100C8FFC01UL, + /* 0x0280, */ 0x001000100C8FFC01UL, + /* 0x0288, */ 0x001000100C8FFC01UL, + /* 0x0290, */ 0x001000100C8FFC01UL, + /* 0x0298, */ 0x001000100C8FFC01UL, + /* 0x02A0, */ 0x001000100C8FFC01UL, + /* 0x02A8, */ 0x001000100C8FFC01UL, + /* 0x02B0, */ 0x001000100C8FFC01UL, + /* 0x02B8, */ 0x001000100C8FFC01UL, + /* 0x02C0, */ 0x001000100C8FFC01UL, + /* 0x02C8, */ 0x001000100C8FFC01UL, + /* 0x02D0, */ 0x001000100C8FFC01UL, + /* 0x02D8, */ 0x001000100C8FFC01UL, + /* 0x02E0, */ 0x001000100C8FFC01UL, + /* 0x02E8, */ 0x001000100C8FFC01UL, + /* 0x02F0, */ 0x001000200C8FFC01UL, + /* 0x02F8, */ 0x001000300C8FFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001000200C8FFC01UL, + /* 0x0310, */ 0x001000300C8FFC01UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x001000200C8FFC01UL, + /* 0x0328, */ 0x001000300C8FFC01UL, + /* 0x0330, */ 0x001000200C8FFC01UL, + /* 0x0338, */ 0x001000300C8FFC01UL, +}; +#endif diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c new file mode 100644 index 0000000..329bcb8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3_v11.h" + +#define RCAR_QOS_VERSION "rev.0.37" + +#include "qos_init_h3_v11_mstat.h" + +struct rcar_gen3_dbsc_qos_settings h3_v11_qos[] = { + /* BUFCAM settings */ + /* DBSC_DBCAM0CNF0 not set */ + { DBSC_DBCAM0CNF1, 0x00044218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + /* DBSC_DBCAM0CNF3 not set */ + { DBSC_DBSCHCNT0, 0x080F0037 }, + { DBSC_DBSCHCNT1, 0x00001010 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x0000F000 }, + { DBSC_DBSCHQOS01, 0x0000E000 }, + { DBSC_DBSCHQOS02, 0x00007000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000E00 }, + { DBSC_DBSCHQOS41, 0x00000DFF }, + { DBSC_DBSCHQOS42, 0x00000400 }, + { DBSC_DBSCHQOS43, 0x00000200 }, + { DBSC_DBSCHQOS90, 0x00000C00 }, + { DBSC_DBSCHQOS91, 0x00000BFF }, + { DBSC_DBSCHQOS92, 0x00000400 }, + { DBSC_DBSCHQOS93, 0x00000200 }, + { DBSC_DBSCHQOS130, 0x00000980 }, + { DBSC_DBSCHQOS131, 0x0000097F }, + { DBSC_DBSCHQOS132, 0x00000300 }, + { DBSC_DBSCHQOS133, 0x00000180 }, + { DBSC_DBSCHQOS140, 0x00000800 }, + { DBSC_DBSCHQOS141, 0x000007FF }, + { DBSC_DBSCHQOS142, 0x00000300 }, + { DBSC_DBSCHQOS143, 0x00000180 }, + { DBSC_DBSCHQOS150, 0x000007D0 }, + { DBSC_DBSCHQOS151, 0x000007CF }, + { DBSC_DBSCHQOS152, 0x000005D0 }, + { DBSC_DBSCHQOS153, 0x000003D0 }, +}; + +void qos_init_h3_v11(void) +{ + rcar_qos_dbsc_setting(h3_v11_qos, ARRAY_SIZE(h3_v11_qos), false); + + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 4ch\n"); + io_write_32(AXI_ADSPLCR0, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR1, 0x00000000U); + io_write_32(AXI_ADSPLCR2, 0xA8A90000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00000000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* AR Cache setting */ + io_write_32(0xE67D1000U, 0x00000100U); + io_write_32(0xE67D1008U, 0x00000100U); + + /* Resource Alloc setting */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + io_write_32(QOSCTRL_RAS, 0x00000020U); +#else + io_write_32(QOSCTRL_RAS, 0x00000040U); +#endif + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_REGGD, 0x00000000U); +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + io_write_64(QOSCTRL_DANN, 0x0101010102020201UL); + io_write_32(QOSCTRL_DANT, 0x00181008U); +#else + io_write_64(QOSCTRL_DANN, 0x0101000004040401UL); + io_write_32(QOSCTRL_DANT, 0x003C2010U); +#endif + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 v1.* */ + io_write_64(QOSCTRL_EMS, 0x0000000000000000UL); + io_write_32(QOSCTRL_INSFC, 0xC7840001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + io_write_32(QOSCTRL_RACNT0, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK); + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + io_write_32(0xFD820808U, 0x00001234U); + io_write_32(0xFD820800U, 0x0000003FU); + io_write_32(0xFD821800U, 0x0000003FU); + io_write_32(0xFD822800U, 0x0000003FU); + io_write_32(0xFD823800U, 0x0000003FU); + io_write_32(0xFD824800U, 0x0000003FU); + io_write_32(0xFD825800U, 0x0000003FU); + io_write_32(0xFD826800U, 0x0000003FU); + io_write_32(0xFD827800U, 0x0000003FU); + + /* VIO bus Leaf setting */ + io_write_32(0xFEB89800, 0x00000001U); + io_write_32(0xFEB8A800, 0x00000001U); + io_write_32(0xFEB8B800, 0x00000001U); + io_write_32(0xFEB8C800, 0x00000001U); + + /* HSC bus Leaf setting */ + io_write_32(0xE6430800, 0x00000001U); + io_write_32(0xE6431800, 0x00000001U); + io_write_32(0xE6432800, 0x00000001U); + io_write_32(0xE6433800, 0x00000001U); + + /* MP bus Leaf setting */ + io_write_32(0xEC620800, 0x00000001U); + io_write_32(0xEC621800, 0x00000001U); + + /* PERIE bus Leaf setting */ + io_write_32(0xE7760800, 0x00000001U); + io_write_32(0xE7768800, 0x00000001U); + + /* PERIW bus Leaf setting */ + io_write_32(0xE6760800, 0x00000001U); + io_write_32(0xE6768800, 0x00000001U); + + /* RT bus Leaf setting */ + io_write_32(0xFFC50800, 0x00000001U); + io_write_32(0xFFC51800, 0x00000001U); + + /* CCI bus Leaf setting */ + uint32_t modemr = io_read_32(RCAR_MODEMR); + + modemr &= MODEMR_BOOT_CPU_MASK; + + if ((modemr == MODEMR_BOOT_CPU_CA57) || + (modemr == MODEMR_BOOT_CPU_CA53)) { + io_write_32(0xF1300800, 0x00000001U); + io_write_32(0xF1340800, 0x00000001U); + io_write_32(0xF1380800, 0x00000001U); + io_write_32(0xF13C0800, 0x00000001U); + } + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 v1.* */ +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h new file mode 100644 index 0000000..3faeb4f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3_V11_H +#define QOS_INIT_H3_V11_H + +void qos_init_h3_v11(void); + +#endif /* QOS_INIT_H3_V11_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h new file mode 100644 index 0000000..46c68c8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004030000FFFFUL, + /* 0x0038, */ 0x001008060000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001410010000FFFFUL, + /* 0x0058, */ 0x00140C0C0000FFFFUL, + /* 0x0060, */ 0x00140C0C0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001410010000FFFFUL, + /* 0x0078, */ 0x001008060000FFFFUL, + /* 0x0080, */ 0x001004020000FFFFUL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x00140C0C0000FFFFUL, + /* 0x0098, */ 0x001408080000FFFFUL, + /* 0x00A0, */ 0x000C08020000FFFFUL, + /* 0x00A8, */ 0x000C04010000FFFFUL, + /* 0x00B0, */ 0x000C04010000FFFFUL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x000C08020000FFFFUL, + /* 0x00C8, */ 0x000C04010000FFFFUL, + /* 0x00D0, */ 0x000C04010000FFFFUL, + /* 0x00D8, */ 0x000C04030000FFFFUL, + /* 0x00E0, */ 0x000C100F0000FFFFUL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x001010080000FFFFUL, + /* 0x00F8, */ 0x001010080000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x000C04030000FFFFUL, + /* 0x0110, */ 0x001010080000FFFFUL, + /* 0x0118, */ 0x001010080000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x000C100E0000FFFFUL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001008050000FFFFUL, + /* 0x0140, */ 0x001008050000FFFFUL, + /* 0x0148, */ 0x001008050000FFFFUL, + /* 0x0150, */ 0x001008050000FFFFUL, + /* 0x0158, */ 0x001008050000FFFFUL, + /* 0x0160, */ 0x001008050000FFFFUL, + /* 0x0168, */ 0x001008050000FFFFUL, + /* 0x0170, */ 0x001008050000FFFFUL, + /* 0x0178, */ 0x001004030000FFFFUL, + /* 0x0180, */ 0x001004030000FFFFUL, + /* 0x0188, */ 0x001004030000FFFFUL, + /* 0x0190, */ 0x001014140000FFFFUL, + /* 0x0198, */ 0x001014140000FFFFUL, + /* 0x01A0, */ 0x001008050000FFFFUL, + /* 0x01A8, */ 0x001008050000FFFFUL, + /* 0x01B0, */ 0x001008050000FFFFUL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02A0, */ 0x000C04010000FFFFUL, + /* 0x02A8, */ 0x000C04010000FFFFUL, + /* 0x02B0, */ 0x001404010000FFFFUL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x000C04010000FFFFUL, + /* 0x02D8, */ 0x000C04010000FFFFUL, + /* 0x02E0, */ 0x001404010000FFFFUL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200100C89C401UL, + /* 0x0008, */ 0x001200100C89C401UL, + /* 0x0010, */ 0x001200100C89C401UL, + /* 0x0018, */ 0x001200100C89C401UL, + /* 0x0020, */ 0x001100100C803401UL, + /* 0x0028, */ 0x001100100C80FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x001100100C803401UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x001100100C803401UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x001100100C803401UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x001100100C803401UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x001100100C803401UL, + /* 0x01C0, */ 0x001100800C8FFC01UL, + /* 0x01C8, */ 0x001100800C8FFC01UL, + /* 0x01D0, */ 0x001100800C8FFC01UL, + /* 0x01D8, */ 0x001100800C8FFC01UL, + /* 0x01E0, */ 0x001100100C80FC01UL, + /* 0x01E8, */ 0x001200100C80FC01UL, + /* 0x01F0, */ 0x001100100C80FC01UL, + /* 0x01F8, */ 0x001100100C803401UL, + /* 0x0200, */ 0x001100100C80FC01UL, + /* 0x0208, */ 0x001200100C80FC01UL, + /* 0x0210, */ 0x001100100C80FC01UL, + /* 0x0218, */ 0x001100100C825801UL, + /* 0x0220, */ 0x001100100C825801UL, + /* 0x0228, */ 0x001100100C803401UL, + /* 0x0230, */ 0x001100100C825801UL, + /* 0x0238, */ 0x001100100C825801UL, + /* 0x0240, */ 0x001200100C8BB801UL, + /* 0x0248, */ 0x001100200C8FFC01UL, + /* 0x0250, */ 0x001200100C8BB801UL, + /* 0x0258, */ 0x001100200C8FFC01UL, + /* 0x0260, */ 0x001100100C84E401UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x001100100C81F401UL, + /* 0x0280, */ 0x001100100C803401UL, + /* 0x0288, */ 0x001100100C803401UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x001100100C803401UL, + /* 0x02C0, */ 0x001100100C803401UL, + /* 0x02C8, */ 0x001100100C803401UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x001100100C803401UL, + /* 0x02F0, */ 0x001100300C8FFC01UL, + /* 0x02F8, */ 0x001100500C8FFC01UL, + /* 0x0300, */ 0x001100100C803401UL, + /* 0x0308, */ 0x001100300C8FFC01UL, + /* 0x0310, */ 0x001100500C8FFC01UL, + /* 0x0318, */ 0x001200100C803401UL, + /* 0x0320, */ 0x001100300C8FFC01UL, + /* 0x0328, */ 0x001100500C8FFC01UL, + /* 0x0330, */ 0x001100300C8FFC01UL, + /* 0x0338, */ 0x001100500C8FFC01UL, +}; +#endif diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c new file mode 100644 index 0000000..c20ab08 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3_v20.h" + +#define RCAR_QOS_VERSION "rev.0.21" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3_20 (SL_INIT_SSLOTCLK_H3_20 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_H3_20 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_H3_20) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_H3_20 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_H3_20) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3_v20_mstat195.h" +#else +#include "qos_init_h3_v20_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3_v20_qoswt195.h" +#else +#include "qos_init_h3_v20_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + +#endif + +struct rcar_gen3_dbsc_qos_settings h3_v20_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_h3_v20(void) +{ + rcar_qos_dbsc_setting(h3_v20_qos, ARRAY_SIZE(h3_v20_qos), true); + + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 4ch\n"); + io_write_32(AXI_ADSPLCR0, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR1, 0x00000000U); + io_write_32(AXI_ADSPLCR2, 0x00001054U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404010002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + /* GPU Boost Mode */ + io_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_H3_20); +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + io_write_32(QOSCTRL_REF_ARS, + ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3_20 << 16))); +#else + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, + qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, + qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* 3DG bus Leaf setting */ + io_write_32(GPU_ACT0, 0x00000000U); + io_write_32(GPU_ACT1, 0x00000000U); + io_write_32(GPU_ACT2, 0x00000000U); + io_write_32(GPU_ACT3, 0x00000000U); + io_write_32(GPU_ACT4, 0x00000000U); + io_write_32(GPU_ACT5, 0x00000000U); + io_write_32(GPU_ACT6, 0x00000000U); + io_write_32(GPU_ACT7, 0x00000000U); + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_H3_20 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_H3_20 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h new file mode 100644 index 0000000..9b7619e --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3_V20_H +#define QOS_INIT_H3_V20_H + +void qos_init_h3_v20(void); + +#endif /* QOS_INIT_H3_V20_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h new file mode 100644 index 0000000..3995df3 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424110000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001410100000FFFFUL, + /* 0x0060, */ 0x0014100D0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008070000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424110000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x001024090000FFFFUL, + /* 0x00e0, */ 0x00100C090000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x000C08070000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x000C10100000FFFFUL, + /* 0x0120, */ 0x000C10100000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x00100C0B0000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0010100D0000FFFFUL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x00100C0B0000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x001008060000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x00102C2C0000FFFFUL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x00100C0B0000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200200BDFFC01UL, + /* 0x0008, */ 0x001200200BDFFC01UL, + /* 0x0010, */ 0x001200200BDFFC01UL, + /* 0x0018, */ 0x001200200BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100700BDFFC01UL, + /* 0x01c8, */ 0x002100700BDFFC01UL, + /* 0x01d0, */ 0x002100700BDFFC01UL, + /* 0x01d8, */ 0x002100700BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100200BDFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100200BDFFC01UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x001100400BDFFC01UL, + /* 0x0328, */ 0x001100600BDFFC01UL, + /* 0x0330, */ 0x001100400BDFFC01UL, + /* 0x0338, */ 0x001100600BDFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x001200100BD0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h new file mode 100644 index 0000000..770c022 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x0010100D0000FFFFUL, + /* 0x0040, */ 0x001444210000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x0014201F0000FFFFUL, + /* 0x0060, */ 0x00141C190000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x0010100D0000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001444210000FFFFUL, + /* 0x0090, */ 0x00141C190000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x001044110000FFFFUL, + /* 0x00e0, */ 0x001014110000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x000C100D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x000C20200000FFFFUL, + /* 0x0120, */ 0x000C20200000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x001018150000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x00101C190000FFFFUL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x001018150000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x00100C0B0000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x001058570000FFFFUL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x001018150000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100D005EFFC01UL, + /* 0x01c8, */ 0x002100D005EFFC01UL, + /* 0x01d0, */ 0x002100D005EFFC01UL, + /* 0x01d8, */ 0x002100D005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0011007005EFFC01UL, + /* 0x0328, */ 0x001100B005EFFC01UL, + /* 0x0330, */ 0x0011007005EFFC01UL, + /* 0x0338, */ 0x001100B005EFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0012001005E0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h new file mode 100644 index 0000000..82e4b01 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424110000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001410100000C010UL, + /* 0x0060, */ 0x0014100D0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008070000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424110000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h new file mode 100644 index 0000000..f3e7360 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x0010100D0000C010UL, + /* 0x0040, */ 0x001444210000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0014201F0000C010UL, + /* 0x0060, */ 0x00141C190000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0010100D0000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001444210000FFF0UL, + /* 0x0090, */ 0x00141C190000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c new file mode 100644 index 0000000..1fe6182 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3_v30.h" + +#define RCAR_QOS_VERSION "rev.0.11" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3_30 (SL_INIT_SSLOTCLK_H3_30 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_H3_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_H3_30) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_H3_30 (QOSWT_WTSET0_PERIOD0_H3_30) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_SSLOT0) +#define QOSWT_WTSET1_SLOTSLOT1 (QOSWT_WTSET0_SLOTSLOT0) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3_v30_mstat195.h" +#else +#include "qos_init_h3_v30_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3_v30_qoswt195.h" +#else +#include "qos_init_h3_v30_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + +#endif + +struct rcar_gen3_dbsc_qos_settings h3_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_h3_v30(void) +{ + unsigned int split_area; + + rcar_qos_dbsc_setting(h3_v30_qos, ARRAY_SIZE(h3_v30_qos), true); + +#if RCAR_DRAM_LPDDR4_MEMCONF == 0 /* 1GB */ + split_area = 0x1BU; +#else /* default 2GB */ + split_area = 0x1CU; +#endif + + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 4ch(DDR %x)\n", (int)qos_init_ddr_phyvalid); + + io_write_32(AXI_ADSPLCR0, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(split_area) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR1, 0x00000000U); + io_write_32(AXI_ADSPLCR2, 0x00001054U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + NOTICE("BL2: DRAM Split is 2ch(DDR %x)\n", (int)qos_init_ddr_phyvalid); + + io_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(split_area) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + io_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + NOTICE("BL2: DRAM Split is OFF(DDR %x)\n", (int)qos_init_ddr_phyvalid); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404010002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + /* GPU Boost Mode */ + io_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_H3_30); + io_write_32(QOSCTRL_REF_ARS, + ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3_30 << 16))); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, + qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, + qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* AXI setting */ + io_write_32(AXI_MMCR, 0x00010008U); + io_write_32(AXI_TR3CR, 0x00010000U); + io_write_32(AXI_TR4CR, 0x00010000U); + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_H3_30 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_H3_30 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h new file mode 100644 index 0000000..d33b43c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3_V30_H +#define QOS_INIT_H3_V30_H + +void qos_init_h3_v30(void); + +#endif /* QOS_INIT_H3_V30_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h new file mode 100644 index 0000000..28a240f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001410070000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x0014100D0000FFFFUL, + /* 0x0060, */ 0x0014100D0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008070000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x001024090000FFFFUL, + /* 0x00e0, */ 0x00100C090000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x000C100D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x000C1C1B0000FFFFUL, + /* 0x0120, */ 0x000C1C1B0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x00100C0B0000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0010100D0000FFFFUL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x00100C0B0000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x001008060000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x00102C2C0000FFFFUL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x00100C0B0000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200600BDFFC01UL, + /* 0x0008, */ 0x001200600BDFFC01UL, + /* 0x0010, */ 0x001200600BDFFC01UL, + /* 0x0018, */ 0x001200600BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100100BDF2401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100100BDF2401UL, + /* 0x0218, */ 0x001100100BDF2401UL, + /* 0x0220, */ 0x001100100BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100BDF2401UL, + /* 0x0238, */ 0x001100100BDF2401UL, + /* 0x0240, */ 0x001200100BDF2401UL, + /* 0x0248, */ 0x001100100BDF2401UL, + /* 0x0250, */ 0x001200100BDF2401UL, + /* 0x0258, */ 0x001100100BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100600BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100600BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x001100600BDFFC01UL, + /* 0x0328, */ 0x001100600BDFFC01UL, + /* 0x0330, */ 0x001100600BDFFC01UL, + /* 0x0338, */ 0x001100600BDFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x001200100BD0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h new file mode 100644 index 0000000..def6585 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x0010100D0000FFFFUL, + /* 0x0040, */ 0x00141C0E0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001408010000FFFFUL, + /* 0x0058, */ 0x00141C190000FFFFUL, + /* 0x0060, */ 0x00141C190000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001408010000FFFFUL, + /* 0x0078, */ 0x0010100D0000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFFFUL, + /* 0x0090, */ 0x00141C190000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x001044110000FFFFUL, + /* 0x00e0, */ 0x001014110000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x000C1C1A0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x000C38360000FFFFUL, + /* 0x0120, */ 0x000C38360000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x001018150000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x00101C190000FFFFUL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x001018150000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x00100C0B0000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x001058570000FFFFUL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x001018150000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012006005EFFC01UL, + /* 0x0008, */ 0x0012006005EFFC01UL, + /* 0x0010, */ 0x0012006005EFFC01UL, + /* 0x0018, */ 0x0012006005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021006005EFFC01UL, + /* 0x01c8, */ 0x0021006005EFFC01UL, + /* 0x01d0, */ 0x0021006005EFFC01UL, + /* 0x01d8, */ 0x0021006005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021001005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021001005E79401UL, + /* 0x0218, */ 0x0011001005E79401UL, + /* 0x0220, */ 0x0011001005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011001005E79401UL, + /* 0x0238, */ 0x0011001005E79401UL, + /* 0x0240, */ 0x0012001005E79401UL, + /* 0x0248, */ 0x0011001005E79401UL, + /* 0x0250, */ 0x0012001005E79401UL, + /* 0x0258, */ 0x0011001005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011006005EFFC01UL, + /* 0x02f8, */ 0x0011006005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011006005EFFC01UL, + /* 0x0310, */ 0x0011006005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0011006005EFFC01UL, + /* 0x0328, */ 0x0011006005EFFC01UL, + /* 0x0330, */ 0x0011006005EFFC01UL, + /* 0x0338, */ 0x0011006005EFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0012001005E0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h new file mode 100644 index 0000000..b0c11cc --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001410070000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0014100D0000C010UL, + /* 0x0060, */ 0x0014100D0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008070000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h new file mode 100644 index 0000000..a1e4c72 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x0010100D0000C010UL, + /* 0x0040, */ 0x00141C0E0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00141C190000C010UL, + /* 0x0060, */ 0x00141C190000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0010100D0000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFF0UL, + /* 0x0090, */ 0x00141C190000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c new file mode 100644 index 0000000..f1ee41b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3n_v30.h" + +#define RCAR_QOS_VERSION "rev.0.07" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3N (SL_INIT_SSLOTCLK_H3N - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_H3N \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_H3N) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_H3N (QOSWT_WTSET0_PERIOD0_H3N) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_SSLOT0) +#define QOSWT_WTSET1_SLOTSLOT1 (QOSWT_WTSET0_SLOTSLOT0) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3n_v30_mstat195.h" +#else +#include "qos_init_h3n_v30_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3n_v30_qoswt195.h" +#else +#include "qos_init_h3n_v30_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + +#endif + +struct rcar_gen3_dbsc_qos_settings h3n_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_h3n_v30(void) +{ + unsigned int split_area; + + rcar_qos_dbsc_setting(h3n_v30_qos, ARRAY_SIZE(h3n_v30_qos), true); + + /* use 1(2GB) for RCAR_DRAM_LPDDR4_MEMCONF for H3N */ + split_area = 0x1CU; + + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) +#if RCAR_LSI == RCAR_H3N +#error "Don't set DRAM Split 4ch(H3N)" +#else + ERROR("DRAM Split 4ch not supported.(H3N)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch(DDR %x)\n", (int)qos_init_ddr_phyvalid); + + io_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(split_area) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + io_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + NOTICE("BL2: DRAM Split is OFF(DDR %x)\n", (int)qos_init_ddr_phyvalid); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + /* GPU Boost Mode */ + io_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_H3N); + io_write_32(QOSCTRL_REF_ARS, + ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3N << 16))); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, + qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, + qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* AXI setting */ + io_write_32(AXI_MMCR, 0x00010008U); + io_write_32(AXI_TR3CR, 0x00010000U); + io_write_32(AXI_TR4CR, 0x00010000U); + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_H3N << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_H3N << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h new file mode 100644 index 0000000..46f3440 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3N_V30_H +#define QOS_INIT_H3N_V30_H + +void qos_init_h3n_v30(void); + +#endif /* QOS_INIT_H3N_V30_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h new file mode 100644 index 0000000..6dbc88a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001410070000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x0014100D0000FFFFUL, + /* 0x0060, */ 0x0014100D0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x001024090000FFFFUL, + /* 0x00e0, */ 0x00100C090000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x000C100D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x000C1C1B0000FFFFUL, + /* 0x0120, */ 0x000C1C1B0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x00100C0B0000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0010100D0000FFFFUL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x00100C0B0000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x001008060000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x00102C2C0000FFFFUL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x00100C0B0000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200600BDFFC01UL, + /* 0x0008, */ 0x001200600BDFFC01UL, + /* 0x0010, */ 0x001200600BDFFC01UL, + /* 0x0018, */ 0x001200600BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100100BDF2401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100100BDF2401UL, + /* 0x0218, */ 0x001100100BDF2401UL, + /* 0x0220, */ 0x001100100BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100BDF2401UL, + /* 0x0238, */ 0x001100100BDF2401UL, + /* 0x0240, */ 0x001200100BDF2401UL, + /* 0x0248, */ 0x001100100BDF2401UL, + /* 0x0250, */ 0x001200100BDF2401UL, + /* 0x0258, */ 0x001100100BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100600BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100600BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x001100600BDFFC01UL, + /* 0x0328, */ 0x001100600BDFFC01UL, + /* 0x0330, */ 0x001100600BDFFC01UL, + /* 0x0338, */ 0x001100600BDFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x001200100BD0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h new file mode 100644 index 0000000..880211c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x0010100D0000FFFFUL, + /* 0x0040, */ 0x00141C0E0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001408010000FFFFUL, + /* 0x0058, */ 0x00141C190000FFFFUL, + /* 0x0060, */ 0x00141C190000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001408010000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x001044110000FFFFUL, + /* 0x00e0, */ 0x001014110000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x000C1C1A0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x000C38360000FFFFUL, + /* 0x0120, */ 0x000C38360000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x001018150000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x00101C190000FFFFUL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x001018150000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x00100C0B0000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x001058570000FFFFUL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x001018150000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012006005EFFC01UL, + /* 0x0008, */ 0x0012006005EFFC01UL, + /* 0x0010, */ 0x0012006005EFFC01UL, + /* 0x0018, */ 0x0012006005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021006005EFFC01UL, + /* 0x01c8, */ 0x0021006005EFFC01UL, + /* 0x01d0, */ 0x0021006005EFFC01UL, + /* 0x01d8, */ 0x0021006005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021001005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021001005E79401UL, + /* 0x0218, */ 0x0011001005E79401UL, + /* 0x0220, */ 0x0011001005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011001005E79401UL, + /* 0x0238, */ 0x0011001005E79401UL, + /* 0x0240, */ 0x0012001005E79401UL, + /* 0x0248, */ 0x0011001005E79401UL, + /* 0x0250, */ 0x0012001005E79401UL, + /* 0x0258, */ 0x0011001005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011006005EFFC01UL, + /* 0x02f8, */ 0x0011006005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011006005EFFC01UL, + /* 0x0310, */ 0x0011006005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0011006005EFFC01UL, + /* 0x0328, */ 0x0011006005EFFC01UL, + /* 0x0330, */ 0x0011006005EFFC01UL, + /* 0x0338, */ 0x0011006005EFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0012001005E0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h new file mode 100644 index 0000000..affd013 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001410070000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0014100D0000C010UL, + /* 0x0060, */ 0x0014100D0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h new file mode 100644 index 0000000..1c48d28 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x0010100D0000C010UL, + /* 0x0040, */ 0x00141C0E0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00141C190000C010UL, + /* 0x0060, */ 0x00141C190000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c new file mode 100644 index 0000000..a8264cb --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_m3_v10.h" + +#define RCAR_QOS_VERSION "rev.0.19" + +#include "qos_init_m3_v10_mstat.h" + +struct rcar_gen3_dbsc_qos_settings m3_v10_qos[] = { + /* BUFCAM settings */ + /* DBSC_DBCAM0CNF0 not set */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBCAM0CNF3, 0x00000000 }, + { DBSC_DBSCHCNT0, 0x080F0037 }, + /* DBSC_DBSCHCNT1 not set */ + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000300 }, + { DBSC_DBSCHQOS91, 0x000002F0 }, + { DBSC_DBSCHQOS92, 0x00000200 }, + { DBSC_DBSCHQOS93, 0x00000100 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_m3_v10(void) +{ + rcar_qos_dbsc_setting(m3_v10_qos, ARRAY_SIZE(m3_v10_qos), false); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_M3 +#error "Don't set DRAM Split 4ch(M3)" +#else + ERROR("DRAM Split 4ch not supported.(M3)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1CU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x089A0000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_RAS, 0x00000028U); + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_REGGD, 0x00000000U); + io_write_64(QOSCTRL_DANN, 0x0101010102020201UL); + io_write_32(QOSCTRL_DANT, 0x00100804U); + io_write_32(QOSCTRL_EC, 0x00000000U); + io_write_64(QOSCTRL_EMS, 0x0000000000000000UL); + io_write_32(QOSCTRL_FSS, 0x000003e8U); + io_write_32(QOSCTRL_INSFC, 0xC7840001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + io_write_32(QOSCTRL_RACNT0, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK); + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + io_write_32(0xFD820808U, 0x00001234U); + io_write_32(0xFD820800U, 0x00000006U); + io_write_32(0xFD821800U, 0x00000006U); + io_write_32(0xFD822800U, 0x00000006U); + io_write_32(0xFD823800U, 0x00000006U); + io_write_32(0xFD824800U, 0x00000006U); + io_write_32(0xFD825800U, 0x00000006U); + io_write_32(0xFD826800U, 0x00000006U); + io_write_32(0xFD827800U, 0x00000006U); + + /* RT bus Leaf setting */ + io_write_32(0xFFC50800U, 0x00000000U); + io_write_32(0xFFC51800U, 0x00000000U); + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_EC, 0x00000000U); + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h new file mode 100644 index 0000000..01ef46c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_M3_V10_H +#define QOS_INIT_M3_V10_H + +void qos_init_m3_v10(void); + +#endif /* QOS_INIT_M3_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h new file mode 100644 index 0000000..b78b5f1 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004030000FFFFUL, + /* 0x0038, */ 0x001004030000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001410010000FFFFUL, + /* 0x0058, */ 0x00140C090000FFFFUL, + /* 0x0060, */ 0x00140C090000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001410010000FFFFUL, + /* 0x0078, */ 0x001004020000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408060000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x000C08020000FFFFUL, + /* 0x00A8, */ 0x000C04010000FFFFUL, + /* 0x00B0, */ 0x000C04010000FFFFUL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x000C08020000FFFFUL, + /* 0x00C8, */ 0x000C04010000FFFFUL, + /* 0x00D0, */ 0x000C04010000FFFFUL, + /* 0x00D8, */ 0x000C04030000FFFFUL, + /* 0x00E0, */ 0x000C100F0000FFFFUL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x001010080000FFFFUL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001010080000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0A0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00100C0A0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0A0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008050000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001028280000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x00100C0A0000FFFFUL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02A0, */ 0x000C04010000FFFFUL, + /* 0x02A8, */ 0x000C04010000FFFFUL, + /* 0x02B0, */ 0x001404010000FFFFUL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x000C04010000FFFFUL, + /* 0x02D8, */ 0x000C04010000FFFFUL, + /* 0x02E0, */ 0x001404010000FFFFUL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200100C89C401UL, + /* 0x0008, */ 0x001200100C89C401UL, + /* 0x0010, */ 0x001200100C89C401UL, + /* 0x0018, */ 0x001200100C89C401UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001100100C803401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x001100500C8FFC01UL, + /* 0x01C8, */ 0x001100500C8FFC01UL, + /* 0x01D0, */ 0x001100500C8FFC01UL, + /* 0x01D8, */ 0x001100500C8FFC01UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x001200100C803401UL, + /* 0x01F0, */ 0x001100100C80FC01UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x001200100C80FC01UL, + /* 0x0210, */ 0x001100100C80FC01UL, + /* 0x0218, */ 0x001100100C825801UL, + /* 0x0220, */ 0x001100100C825801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100C825801UL, + /* 0x0238, */ 0x001100100C825801UL, + /* 0x0240, */ 0x001200100C8BB801UL, + /* 0x0248, */ 0x001100100C8EA401UL, + /* 0x0250, */ 0x001200100C8BB801UL, + /* 0x0258, */ 0x001100100C8EA401UL, + /* 0x0260, */ 0x001100100C84E401UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x001100100C81F401UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x001100100C803401UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x001100100C803401UL, + /* 0x02F0, */ 0x001100300C8FFC01UL, + /* 0x02F8, */ 0x001100500C8FFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100300C8FFC01UL, + /* 0x0310, */ 0x001100500C8FFC01UL, + /* 0x0318, */ 0x001200100C803401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; +#endif diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c new file mode 100644 index 0000000..22fd83a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_m3_v11.h" + +#define RCAR_QOS_VERSION "rev.0.19" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_11 (SL_INIT_SSLOTCLK_M3_11 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_M3_11 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3_11) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_M3_11 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3_11) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3_v11_mstat195.h" +#else +#include "qos_init_m3_v11_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3_v11_qoswt195.h" +#else +#include "qos_init_m3_v11_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif + +struct rcar_gen3_dbsc_qos_settings m3_v11_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBCAM0CNF3, 0x00000000 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000100 }, + { DBSC_DBSCHQOS91, 0x000000F0 }, + { DBSC_DBSCHQOS92, 0x000000A0 }, + { DBSC_DBSCHQOS93, 0x00000040 }, + { DBSC_DBSCHQOS120, 0x00000040 }, + { DBSC_DBSCHQOS121, 0x00000030 }, + { DBSC_DBSCHQOS122, 0x00000020 }, + { DBSC_DBSCHQOS123, 0x00000010 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_m3_v11(void) +{ + rcar_qos_dbsc_setting(m3_v11_qos, ARRAY_SIZE(m3_v11_qos), false); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_M3 +#error "Don't set DRAM Split 4ch(M3)" +#else + ERROR("DRAM Split 4ch not supported.(M3)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1CU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_RACNT0, 0x02010003U); /* GPU Boost Mode ON */ + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_M3_11); +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + io_write_32(QOSCTRL_REF_ARS, + ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_11 << 16))); +#else + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* 3DG bus Leaf setting */ + io_write_32(GPU_ACT_GRD, 0x00001234U); + io_write_32(GPU_ACT0, 0x00000000U); + io_write_32(GPU_ACT1, 0x00000000U); + io_write_32(GPU_ACT2, 0x00000000U); + io_write_32(GPU_ACT3, 0x00000000U); + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_M3_11 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_M3_11 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h new file mode 100644 index 0000000..1552fb6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_M3_V11_H +#define QOS_INIT_M3_V11_H + +void qos_init_m3_v11(void); + +#endif /* QOS_INIT_M3_V11_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h new file mode 100644 index 0000000..d7e7777 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x00140C0A0000FFFFUL, + /* 0x0060, */ 0x00140C0A0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408070000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x000C08050000FFFFUL, + /* 0x00e0, */ 0x000C14120000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200200BDFFC01UL, + /* 0x0008, */ 0x001200200BDFFC01UL, + /* 0x0010, */ 0x001200200BDFFC01UL, + /* 0x0018, */ 0x001200200BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100200BDFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100200BDFFC01UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h new file mode 100644 index 0000000..a9520c3 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424120000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001414130000FFFFUL, + /* 0x0060, */ 0x001414130000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008050000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x000C0C0A0000FFFFUL, + /* 0x00e0, */ 0x000C24230000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100B005EFFC01UL, + /* 0x01c8, */ 0x002100B005EFFC01UL, + /* 0x01d0, */ 0x002100B005EFFC01UL, + /* 0x01d8, */ 0x002100B005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h new file mode 100644 index 0000000..04c7efd --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001004040000C010UL, + /* 0x0040, */ 0x001414090000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C0A0000C010UL, + /* 0x0060, */ 0x00140C0A0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001004030000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFF0UL, + /* 0x0090, */ 0x001408070000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h new file mode 100644 index 0000000..73f81f5 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424120000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001414130000C010UL, + /* 0x0060, */ 0x001414130000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008050000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c new file mode 100644 index 0000000..43d21d7 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_m3_v30.h" + +#define RCAR_QOS_VERSION "rev.0.04" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_30 (SL_INIT_SSLOTCLK_M3_30 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_M3_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3_30) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_M3_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3_30) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3_v30_mstat195.h" +#else +#include "qos_init_m3_v30_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3_v30_qoswt195.h" +#else +#include "qos_init_m3_v30_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif + +struct rcar_gen3_dbsc_qos_settings m3_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBCAM0CNF3, 0x00000000 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000100 }, + { DBSC_DBSCHQOS91, 0x000000F0 }, + { DBSC_DBSCHQOS92, 0x000000A0 }, + { DBSC_DBSCHQOS93, 0x00000040 }, + { DBSC_DBSCHQOS120, 0x00000040 }, + { DBSC_DBSCHQOS121, 0x00000030 }, + { DBSC_DBSCHQOS122, 0x00000020 }, + { DBSC_DBSCHQOS123, 0x00000010 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_m3_v30(void) +{ + rcar_qos_dbsc_setting(m3_v30_qos, ARRAY_SIZE(m3_v30_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH + #if RCAR_LSI == RCAR_M3 + #error "Don't set DRAM Split 4ch(M3)" + #else + ERROR("DRAM Split 4ch not supported.(M3)"); + panic(); + #endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1DU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_EARLYR, 0x00000001U); + io_write_32(QOSCTRL_RACNT0, 0x02010003U); /* GPU Boost Mode ON */ + + /* GPU Boost Mode */ + io_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + io_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_M3_30); + io_write_32(QOSCTRL_REF_ARS, ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_30 << 16))); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, ((QOSWT_WTSET0_PERIOD0_M3_30 << 16) | (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, ((QOSWT_WTSET1_PERIOD1_M3_30 << 16) | (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h new file mode 100644 index 0000000..a89d512 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H_M3_V30__ +#define QOS_INIT_H_M3_V30__ + +void qos_init_m3_v30(void); + +#endif /* QOS_INIT_H_M3_V30__ */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h new file mode 100644 index 0000000..2ab14da --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x00140C0A0000FFFFUL, + /* 0x0060, */ 0x00140C0A0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408070000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x000C08050000FFFFUL, + /* 0x00e0, */ 0x000C10100000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x000C10100000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200200BDFFC01UL, + /* 0x0008, */ 0x001200200BDFFC01UL, + /* 0x0010, */ 0x001200200BDFFC01UL, + /* 0x0018, */ 0x001200200BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100200BDFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100200BDFFC01UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h new file mode 100644 index 0000000..faac3d9 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424120000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001414130000FFFFUL, + /* 0x0060, */ 0x001414130000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008050000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x000C0C0A0000FFFFUL, + /* 0x00e0, */ 0x000C201F0000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x000C201F0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100B005EFFC01UL, + /* 0x01c8, */ 0x002100B005EFFC01UL, + /* 0x01d0, */ 0x002100B005EFFC01UL, + /* 0x01d8, */ 0x002100B005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h new file mode 100644 index 0000000..6761f5d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001004040000C010UL, + /* 0x0040, */ 0x001414090000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C0A0000C010UL, + /* 0x0060, */ 0x00140C0A0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001004030000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFF0UL, + /* 0x0090, */ 0x001408070000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h new file mode 100644 index 0000000..1deed59 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424120000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001414130000C010UL, + /* 0x0060, */ 0x001414130000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008050000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c new file mode 100644 index 0000000..446340b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_m3n_v10.h" + +#define RCAR_QOS_VERSION "rev.0.09" + +#define REF_ARS_ARBSTOPCYCLE_M3N \ + (((SL_INIT_SSLOTCLK_M3N) - 5U) << 16U) + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN QOSWT_WTREF_SLOT0_EN + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_M3N \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3N) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_M3N QOSWT_WTSET0_PERIOD0_M3N +#define QOSWT_WTSET1_SSLOT1 QOSWT_WTSET0_SSLOT0 +#define QOSWT_WTSET1_SLOTSLOT1 QOSWT_WTSET0_SLOTSLOT0 + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3n_v10_mstat195.h" +#else +#include "qos_init_m3n_v10_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3n_v10_qoswt195.h" +#else +#include "qos_init_m3n_v10_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif + +struct rcar_gen3_dbsc_qos_settings m3n_v10_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000100 }, + { DBSC_DBSCHQOS91, 0x000000F0 }, + { DBSC_DBSCHQOS92, 0x000000A0 }, + { DBSC_DBSCHQOS93, 0x00000040 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_m3n_v10(void) +{ + rcar_qos_dbsc_setting(m3n_v10_qos, ARRAY_SIZE(m3n_v10_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_M3N +#error "Don't set DRAM Split 4ch(M3N)" +#else + ERROR("DRAM Split 4ch not supported.(M3N)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) +#if RCAR_LSI == RCAR_M3N +#error "Don't set DRAM Split 2ch(M3N)" +#else + ERROR("DRAM Split 2ch not supported.(M3N)"); + panic(); +#endif +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000028U); + io_write_64(QOSCTRL_DANN, 0x0402000002020201UL); + io_write_32(QOSCTRL_DANT, 0x00100804U); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_EARLYR, 0x00000001U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_M3N); + io_write_32(QOSCTRL_REF_ARS, REF_ARS_ARBSTOPCYCLE_M3N); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, + qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, + qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_M3N << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_M3N << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h new file mode 100644 index 0000000..0cd0c85 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_M3N_V10_H +#define QOS_INIT_M3N_V10_H + +void qos_init_m3n_v10(void); + +#endif /* QOS_INIT_M3N_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h new file mode 100644 index 0000000..9b8b9e9 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004320000FFFFUL, + /* 0x0038, */ 0x001004320000FFFFUL, + /* 0x0040, */ 0x00140C5D0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404040000FFFFUL, + /* 0x0058, */ 0x00140C940000FFFFUL, + /* 0x0060, */ 0x00140C940000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404040000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014041F0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C041D0000FFFFUL, + /* 0x00a8, */ 0x000C04090000FFFFUL, + /* 0x00b0, */ 0x000C040B0000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C041D0000FFFFUL, + /* 0x00c8, */ 0x000C04090000FFFFUL, + /* 0x00d0, */ 0x000C040B0000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024840000FFFFUL, + /* 0x00f8, */ 0x000C084F0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C840000FFFFUL, + /* 0x0118, */ 0x000C21E60000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100CA50000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x001010C90000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100CA50000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008530000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00101D9D0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100CA50000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04050000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04050000FFFFUL, + /* 0x0210, */ 0x000C04050000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08150000FFFFUL, + /* 0x0268, */ 0x001408020000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04090000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408020000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04050000FFFFUL, + /* 0x02a8, */ 0x000C04050000FFFFUL, + /* 0x02b0, */ 0x001408050000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04050000FFFFUL, + /* 0x02d8, */ 0x000C04050000FFFFUL, + /* 0x02e0, */ 0x001408050000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04010000FFFFUL, + /* 0x0378, */ 0x000C04010000FFFFUL, + /* 0x0380, */ 0x000C04050000FFFFUL, + /* 0x0388, */ 0x000C04050000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002106000BDFFC01UL, + /* 0x01c8, */ 0x002106000BDFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002101000BDF2401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002101000BDF2401UL, + /* 0x0218, */ 0x001101000BDF2401UL, + /* 0x0220, */ 0x001101000BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001101000BDF2401UL, + /* 0x0238, */ 0x001101000BDF2401UL, + /* 0x0240, */ 0x001201000BDF2401UL, + /* 0x0248, */ 0x001101000BDF2401UL, + /* 0x0250, */ 0x001201000BDF2401UL, + /* 0x0258, */ 0x001101000BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001106000BDFFC01UL, + /* 0x02f8, */ 0x001106000BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x001206000BDFFC01UL, + /* 0x0360, */ 0x001206000BDFFC01UL, + /* 0x0368, */ 0x001200100BD03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x001200100BD03401UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h new file mode 100644 index 0000000..19143ed --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008630000FFFFUL, + /* 0x0038, */ 0x001008630000FFFFUL, + /* 0x0040, */ 0x001418BA0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404070000FFFFUL, + /* 0x0058, */ 0x001415270000FFFFUL, + /* 0x0060, */ 0x001415270000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404070000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014083E0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08390000FFFFUL, + /* 0x00a8, */ 0x000C04110000FFFFUL, + /* 0x00b0, */ 0x000C04150000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08390000FFFFUL, + /* 0x00c8, */ 0x000C04110000FFFFUL, + /* 0x00d0, */ 0x000C04150000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001045080000FFFFUL, + /* 0x00f8, */ 0x000C0C9E0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001015080000FFFFUL, + /* 0x0118, */ 0x000C43CB0000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0010194A0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101D910000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0010194A0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100CA50000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001037390000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0010194A0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04020000FFFFUL, + /* 0x01f0, */ 0x000C04090000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04090000FFFFUL, + /* 0x0210, */ 0x000C04090000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFFFUL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x000C08110000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02a0, */ 0x000C04090000FFFFUL, + /* 0x02a8, */ 0x000C04090000FFFFUL, + /* 0x02b0, */ 0x00140C090000FFFFUL, + /* 0x02b8, */ 0x000C04020000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04090000FFFFUL, + /* 0x02d8, */ 0x000C04090000FFFFUL, + /* 0x02e0, */ 0x00140C090000FFFFUL, + /* 0x02e8, */ 0x000C04020000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060005EFFC01UL, + /* 0x01c8, */ 0x0021060005EFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010005E79401UL, + /* 0x0218, */ 0x0011010005E79401UL, + /* 0x0220, */ 0x0011010005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010005E79401UL, + /* 0x0238, */ 0x0011010005E79401UL, + /* 0x0240, */ 0x0012010005E79401UL, + /* 0x0248, */ 0x0011010005E79401UL, + /* 0x0250, */ 0x0012010005E79401UL, + /* 0x0258, */ 0x0011010005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060005EFFC01UL, + /* 0x02f8, */ 0x0011060005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060005EFFC01UL, + /* 0x0360, */ 0x0012060005EFFC01UL, + /* 0x0368, */ 0x0012001005E03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001005E03401UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h new file mode 100644 index 0000000..d2e8040 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004320000C010UL, + /* 0x0038, */ 0x001004320000C010UL, + /* 0x0040, */ 0x00140C5D0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C940000C010UL, + /* 0x0060, */ 0x00140C940000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014041F0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08150000FFF0UL, + /* 0x0268, */ 0x001408020000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04090000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408020000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h new file mode 100644 index 0000000..84f657a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008630000C010UL, + /* 0x0038, */ 0x001008630000C010UL, + /* 0x0040, */ 0x001418BA0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001415270000C010UL, + /* 0x0060, */ 0x001415270000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014083E0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFF0UL, + /* 0x0268, */ 0x001410040000FFF0UL, + /* 0x0270, */ 0x001404020000FFF0UL, + /* 0x0278, */ 0x000C08110000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFF0UL, + /* 0x0298, */ 0x001404020000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c new file mode 100644 index 0000000..076876c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_v3m.h" + +#define RCAR_QOS_VERSION "rev.0.01" + +#include "qos_init_v3m_mstat.h" + +struct rcar_gen3_dbsc_qos_settings v3m_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00044218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBSCHCNT0, 0x080F003F }, + { DBSC_DBSCHCNT1, 0x00001010 }, + + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + { DBSC_DBSCHRW1, 0x00180034 }, + { DBSC_SCFCTST0, 0x180B1708 }, + { DBSC_SCFCTST1, 0x0808070C }, + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x0000F000 }, + { DBSC_DBSCHQOS01, 0x0000E000 }, + { DBSC_DBSCHQOS02, 0x00007000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x0000F000 }, + { DBSC_DBSCHQOS41, 0x0000EFFF }, + { DBSC_DBSCHQOS42, 0x0000B000 }, + { DBSC_DBSCHQOS43, 0x00000000 }, + { DBSC_DBSCHQOS90, 0x0000F000 }, + { DBSC_DBSCHQOS91, 0x0000EFFF }, + { DBSC_DBSCHQOS92, 0x0000D000 }, + { DBSC_DBSCHQOS93, 0x00000000 }, + { DBSC_DBSCHQOS130, 0x0000F000 }, + { DBSC_DBSCHQOS131, 0x0000EFFF }, + { DBSC_DBSCHQOS132, 0x0000E800 }, + { DBSC_DBSCHQOS133, 0x00007000 }, + { DBSC_DBSCHQOS140, 0x0000F000 }, + { DBSC_DBSCHQOS141, 0x0000EFFF }, + { DBSC_DBSCHQOS142, 0x0000E800 }, + { DBSC_DBSCHQOS143, 0x0000B000 }, + { DBSC_DBSCHQOS150, 0x000007D0 }, + { DBSC_DBSCHQOS151, 0x000007CF }, + { DBSC_DBSCHQOS152, 0x000005D0 }, + { DBSC_DBSCHQOS153, 0x000003D0 }, +}; + +void qos_init_v3m(void) +{ +return; + + rcar_qos_dbsc_setting(v3m_qos, ARRAY_SIZE(v3m_qos), false); + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_RAS, 0x00000020U); + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_REGGD, 0x00000004U); + io_write_64(QOSCTRL_DANN, 0x0202020104040200U); + io_write_32(QOSCTRL_DANT, 0x00201008U); + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 ES1 */ + io_write_64(QOSCTRL_EMS, 0x0000000000000000U); + io_write_32(QOSCTRL_INSFC, 0x63C20001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, 0x0305007DU); + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* AXI-IF arbitration setting */ + io_write_32(DBSC_AXARB, 0x18010000U); + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); + +#else + NOTICE("BL2: QoS is None\n"); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h new file mode 100644 index 0000000..2c4278b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H_V3M__ +#define QOS_INIT_H_V3M__ + +void qos_init_v3m(void); + +#endif /* QOS_INIT_H_V3M__ */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h new file mode 100644 index 0000000..d0b7fc3 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x000000000000FFFFUL, + /* 0x0008, */ 0x000000000000FFFFUL, + /* 0x0010, */ 0x000000000000FFFFUL, + /* 0x0018, */ 0x000000000000FFFFUL, + /* 0x0020, */ 0x001414090000FFFFUL, + /* 0x0028, */ 0x000C00000000FFFFUL, + /* 0x0030, */ 0x001008040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001004040000FFFFUL, + /* 0x0048, */ 0x000000000000FFFFUL, + /* 0x0050, */ 0x001004040000FFFFUL, + /* 0x0058, */ 0x001004040000FFFFUL, + /* 0x0060, */ 0x000000000000FFFFUL, + /* 0x0068, */ 0x001404040000FFFFUL, + /* 0x0070, */ 0x001008030000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x001004030000FFFFUL, + /* 0x0088, */ 0x000000000000FFFFUL, + /* 0x0090, */ 0x001004040000FFFFUL, + /* 0x0098, */ 0x001004040000FFFFUL, + /* 0x00A0, */ 0x000000000000FFFFUL, + /* 0x00A8, */ 0x000000000000FFFFUL, + /* 0x00B0, */ 0x000000000000FFFFUL, + /* 0x00B8, */ 0x000000000000FFFFUL, + /* 0x00C0, */ 0x000000000000FFFFUL, + /* 0x00C8, */ 0x000000000000FFFFUL, + /* 0x00D0, */ 0x000000000000FFFFUL, + /* 0x00D8, */ 0x000000000000FFFFUL, + /* 0x00E0, */ 0x001404020000FFFFUL, + /* 0x00E8, */ 0x000000000000FFFFUL, + /* 0x00F0, */ 0x000000000000FFFFUL, + /* 0x00F8, */ 0x000000000000FFFFUL, + /* 0x0100, */ 0x000000000000FFFFUL, + /* 0x0108, */ 0x000C04020000FFFFUL, + /* 0x0110, */ 0x000000000000FFFFUL, + /* 0x0118, */ 0x001404020000FFFFUL, + /* 0x0120, */ 0x000000000000FFFFUL, + /* 0x0128, */ 0x000000000000FFFFUL, + /* 0x0130, */ 0x000000000000FFFFUL, + /* 0x0138, */ 0x000000000000FFFFUL, + /* 0x0140, */ 0x000000000000FFFFUL, + /* 0x0148, */ 0x000000000000FFFFUL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x00100020447FFC01UL, + /* 0x0008, */ 0x00100020447FFC01UL, + /* 0x0010, */ 0x00100040447FFC01UL, + /* 0x0018, */ 0x00100040447FFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x00100010447FFC01UL, + /* 0x00A8, */ 0x00100010447FFC01UL, + /* 0x00B0, */ 0x00100010447FFC01UL, + /* 0x00B8, */ 0x00100010447FFC01UL, + /* 0x00C0, */ 0x00100010447FFC01UL, + /* 0x00C8, */ 0x00100010447FFC01UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x00100010447FFC01UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x00100010447FFC01UL, + /* 0x00F0, */ 0x00100010447FFC01UL, + /* 0x00F8, */ 0x00100010447FFC01UL, + /* 0x0100, */ 0x00100010447FFC01UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100010447FFC01UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x00100010447FFC01UL, + /* 0x0128, */ 0x00100010447FFC01UL, + /* 0x0130, */ 0x00100010447FFC01UL, + /* 0x0138, */ 0x00100010447FFC01UL, + /* 0x0140, */ 0x00100020447FFC01UL, + /* 0x0148, */ 0x00100020447FFC01UL, +}; +#endif diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/qos.mk b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos.mk new file mode 100644 index 0000000..da10da2 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos.mk @@ -0,0 +1,106 @@ +# +# Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${RCAR_LSI},${RCAR_AUTO}) +# E3, H3N not available for LSI_AUTO + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/V3M/qos_init_v3m.c +else ifdef RCAR_LSI_CUT_COMPAT + ifeq (${RCAR_LSI},${RCAR_H3}) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c + endif + ifeq (${RCAR_LSI},${RCAR_H3N}) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c + endif + ifeq (${RCAR_LSI},${RCAR_M3}) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c + endif + ifeq (${RCAR_LSI},${RCAR_M3N}) + BL2_SOURCES += drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c + endif + ifeq (${RCAR_LSI},${RCAR_V3M}) + BL2_SOURCES += drivers/renesas/rcar/qos/V3M/qos_init_v3m.c + endif + ifeq (${RCAR_LSI},${RCAR_E3}) + BL2_SOURCES += drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c + endif + ifeq (${RCAR_LSI},${RCAR_D3}) + BL2_SOURCES += drivers/renesas/rcar/qos/D3/qos_init_d3.c + endif +else + ifeq (${RCAR_LSI},${RCAR_H3}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c + else ifeq (${LSI_CUT},11) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c + else ifeq (${LSI_CUT},20) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c + else ifeq (${LSI_CUT},30) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c + else +# LSI_CUT 30 or later + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_H3N}) + ifeq (${LSI_CUT},30) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c + else +# LSI_CUT 30 or later + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_M3}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c + else ifeq (${LSI_CUT},11) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c + else ifeq (${LSI_CUT},13) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c + else ifeq (${LSI_CUT},30) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c + else +# LSI_CUT 30 or later + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_M3N}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c + else +# LSI_CUT 10 or later + BL2_SOURCES += drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_V3M}) + BL2_SOURCES += drivers/renesas/rcar/qos/V3M/qos_init_v3m.c + endif + ifeq (${RCAR_LSI},${RCAR_E3}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c + else +# LSI_CUT 10 or later + BL2_SOURCES += drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_D3}) + BL2_SOURCES += drivers/renesas/rcar/qos/E3/qos_init_d3.c + endif +endif + +BL2_SOURCES += drivers/renesas/rcar/qos/qos_init.c diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h new file mode 100644 index 0000000..2c130ae --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_COMMON_H +#define QOS_COMMON_H + +#define RCAR_REF_DEFAULT 0U + +/* define used for get_refperiod. */ +/* REFPERIOD_CYCLE need smaller than QOSWT_WTSET0_CYCLEs */ +/* refere to plat/renesas/rcar/ddr/ddr_a/ddr_init_e3.h for E3. */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF default */ +#define REFPERIOD_CYCLE /* unit:ns */ \ + ((126 * BASE_SUB_SLOT_NUM * 1000U) / 400) +#else /* REF option */ +#define REFPERIOD_CYCLE /* unit:ns */ \ + ((252 * BASE_SUB_SLOT_NUM * 1000U) / 400) +#endif + +#if (RCAR_LSI == RCAR_E3) +/* define used for E3 */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_E3 0xAFU /* 175 */ +#else /* REF 7.8usec */ +#define SUB_SLOT_CYCLE_E3 0x15EU /* 350 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define OPERATING_FREQ_E3 266U /* MHz */ +#define SL_INIT_SSLOTCLK_E3 (SUB_SLOT_CYCLE_E3 - 1U) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) +/* define used for M3N */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_M3N 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_M3N 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_M3N (SUB_SLOT_CYCLE_M3N - 1U) +#define QOSWT_WTSET0_CYCLE_M3N /* unit:ns */ \ + ((SUB_SLOT_CYCLE_M3N * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) +/* define used for H3 */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_H3_20 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_H3_20 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_H3_20 (SUB_SLOT_CYCLE_H3_20 - 1U) +#define QOSWT_WTSET0_CYCLE_H3_20 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_H3_20 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +/* define used for H3 Cut 30 */ +#define SUB_SLOT_CYCLE_H3_30 (SUB_SLOT_CYCLE_H3_20) /* same as H3 Cut 20 */ +#define SL_INIT_SSLOTCLK_H3_30 (SUB_SLOT_CYCLE_H3_30 - 1U) +#define QOSWT_WTSET0_CYCLE_H3_30 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_H3_30 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +#endif + +#if (RCAR_LSI == RCAR_H3N) +/* define used for H3N */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_H3N 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_H3N 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_H3N (SUB_SLOT_CYCLE_H3N - 1U) +#define QOSWT_WTSET0_CYCLE_H3N /* unit:ns */ \ + ((SUB_SLOT_CYCLE_H3N * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) +/* define used for M3 */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_M3_11 0x7EU /* 126 */ +#define SUB_SLOT_CYCLE_M3_30 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_M3_11 0xFCU /* 252 */ +#define SUB_SLOT_CYCLE_M3_30 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_M3_11 (SUB_SLOT_CYCLE_M3_11 - 1U) +#define SL_INIT_SSLOTCLK_M3_30 (SUB_SLOT_CYCLE_M3_30 - 1U) +#define QOSWT_WTSET0_CYCLE_M3_11 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_M3_11 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#define QOSWT_WTSET0_CYCLE_M3_30 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_M3_30 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif + +#define OPERATING_FREQ 400U /* MHz */ +#define BASE_SUB_SLOT_NUM 0x6U +#define SUB_SLOT_CYCLE 0x7EU /* 126 */ + +#define QOSWT_WTSET0_CYCLE /* unit:ns */ \ + ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +#define SL_INIT_REFFSSLOT (0x3U << 24U) +#define SL_INIT_SLOTSSLOT ((BASE_SUB_SLOT_NUM - 1U) << 16U) +#define SL_INIT_SSLOTCLK (SUB_SLOT_CYCLE - 1U) + +static inline void io_write_32(uintptr_t addr, uint32_t value) +{ + *(volatile uint32_t *)addr = value; +} + +static inline uint32_t io_read_32(uintptr_t addr) +{ + return *(volatile uint32_t *)addr; +} + +static inline void io_write_64(uintptr_t addr, uint64_t value) +{ + *(volatile uint64_t *)addr = value; +} + +typedef struct { + uintptr_t addr; + uint64_t value; +} mstat_slot_t; + +struct rcar_gen3_dbsc_qos_settings { + uint32_t reg; + uint32_t val; +}; + +extern uint32_t qos_init_ddr_ch; +extern uint8_t qos_init_ddr_phyvalid; + +void rcar_qos_dbsc_setting(struct rcar_gen3_dbsc_qos_settings *qos, + unsigned int qos_size, bool dbsc_wren); + +#endif /* QOS_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c new file mode 100644 index 0000000..d0f1730 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "qos_init.h" +#include "qos_common.h" +#include "qos_reg.h" +#include "rcar_def.h" +#if RCAR_LSI == RCAR_AUTO +#include "H3/qos_init_h3_v10.h" +#include "H3/qos_init_h3_v11.h" +#include "H3/qos_init_h3_v20.h" +#include "H3/qos_init_h3_v30.h" +#include "M3/qos_init_m3_v10.h" +#include "M3/qos_init_m3_v11.h" +#include "M3/qos_init_m3_v30.h" +#include "M3N/qos_init_m3n_v10.h" +#include "V3M/qos_init_v3m.h" +#endif +#if RCAR_LSI == RCAR_H3 /* H3 */ +#include "H3/qos_init_h3_v10.h" +#include "H3/qos_init_h3_v11.h" +#include "H3/qos_init_h3_v20.h" +#include "H3/qos_init_h3_v30.h" +#endif +#if RCAR_LSI == RCAR_H3N /* H3 */ +#include "H3/qos_init_h3n_v30.h" +#endif +#if RCAR_LSI == RCAR_M3 /* M3 */ +#include "M3/qos_init_m3_v10.h" +#include "M3/qos_init_m3_v11.h" +#include "M3/qos_init_m3_v30.h" +#endif +#if RCAR_LSI == RCAR_M3N /* M3N */ +#include "M3N/qos_init_m3n_v10.h" +#endif +#if RCAR_LSI == RCAR_V3M /* V3M */ +#include "V3M/qos_init_v3m.h" +#endif +#if RCAR_LSI == RCAR_E3 /* E3 */ +#include "E3/qos_init_e3_v10.h" +#endif +#if RCAR_LSI == RCAR_D3 /* D3 */ +#include "D3/qos_init_d3.h" +#endif + +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RCAR_V3M) + +#define DRAM_CH_CNT 0x04 +uint32_t qos_init_ddr_ch; +uint8_t qos_init_ddr_phyvalid; +#endif + +#define PRR_PRODUCT_ERR(reg) \ + do { \ + ERROR("LSI Product ID(PRR=0x%x) QoS " \ + "initialize not supported.\n", reg); \ + panic(); \ + } while (0) + +#define PRR_CUT_ERR(reg) \ + do { \ + ERROR("LSI Cut ID(PRR=0x%x) QoS " \ + "initialize not supported.\n", reg); \ + panic(); \ + } while (0) + +void rcar_qos_init(void) +{ + uint32_t reg; +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RCAR_V3M) + uint32_t i; + + qos_init_ddr_ch = 0; + qos_init_ddr_phyvalid = get_boardcnf_phyvalid(); + for (i = 0; i < DRAM_CH_CNT; i++) { + if ((qos_init_ddr_phyvalid & (1 << i))) { + qos_init_ddr_ch++; + } + } +#endif + + reg = mmio_read_32(PRR); +#if (RCAR_LSI == RCAR_AUTO) || RCAR_LSI_CUT_COMPAT + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + qos_init_h3_v10(); + break; + case PRR_PRODUCT_11: + qos_init_h3_v11(); + break; + case PRR_PRODUCT_20: + qos_init_h3_v20(); + break; + case PRR_PRODUCT_30: + default: + qos_init_h3_v30(); + break; + } +#elif (RCAR_LSI == RCAR_H3N) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_30: + default: + qos_init_h3n_v30(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_M3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + qos_init_m3_v10(); + break; + case PRR_PRODUCT_21: /* M3 Cut 13 */ + qos_init_m3_v11(); + break; + case PRR_PRODUCT_30: /* M3 Cut 30 */ + default: + qos_init_m3_v30(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_M3N: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_m3n_v10(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_V3M: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_V3M) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + case PRR_PRODUCT_20: + default: + qos_init_v3m(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_E3: +#if (RCAR_LSI == RCAR_E3) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_e3_v10(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_D3: +#if (RCAR_LSI == RCAR_D3) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_d3(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } +#else +#if RCAR_LSI == RCAR_H3 /* H3 */ +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* H3 Cut 10 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_10) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3_v10(); +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* H3 Cut 11 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_11) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3_v11(); +#elif RCAR_LSI_CUT == RCAR_CUT_20 + /* H3 Cut 20 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_20) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3_v20(); +#else + /* H3 Cut 30 or later */ + if ((PRR_PRODUCT_H3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3_v30(); +#endif +#elif RCAR_LSI == RCAR_H3N /* H3 */ + /* H3N Cut 30 or later */ + if ((PRR_PRODUCT_H3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3n_v30(); +#elif RCAR_LSI == RCAR_M3 /* M3 */ +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* M3 Cut 10 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_10) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3_v10(); +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* M3 Cut 11 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_20) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3_v11(); +#elif RCAR_LSI_CUT == RCAR_CUT_13 + /* M3 Cut 13 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_21) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3_v11(); +#else + /* M3 Cut 30 or later */ + if ((PRR_PRODUCT_M3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3_v30(); +#endif +#elif RCAR_LSI == RCAR_M3N /* M3N */ + /* M3N Cut 10 or later */ + if ((PRR_PRODUCT_M3N) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3n_v10(); +#elif RCAR_LSI == RCAR_V3M /* V3M */ + /* V3M Cut 10 or later */ + if ((PRR_PRODUCT_V3M) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_v3m(); +#elif RCAR_LSI == RCAR_D3 /* D3 */ + /* D3 Cut 10 or later */ + if ((PRR_PRODUCT_D3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_d3(); +#elif RCAR_LSI == RCAR_E3 /* E3 */ + /* E3 Cut 10 or later */ + if ((PRR_PRODUCT_E3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_e3_v10(); +#else +#error "Don't have QoS initialize routine(Unknown chip)." +#endif +#endif +} + +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RCAR_V3M) +uint32_t get_refperiod(void) +{ + uint32_t refperiod = QOSWT_WTSET0_CYCLE; + +#if (RCAR_LSI == RCAR_AUTO) || RCAR_LSI_CUT_COMPAT + uint32_t reg; + + reg = mmio_read_32(PRR); + switch (reg & PRR_PRODUCT_MASK) { +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) + case PRR_PRODUCT_H3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + case PRR_PRODUCT_11: + break; + case PRR_PRODUCT_20: + case PRR_PRODUCT_30: + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#elif (RCAR_LSI == RCAR_H3N) + case PRR_PRODUCT_H3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_30: + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#endif +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) + case PRR_PRODUCT_M3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + break; + case PRR_PRODUCT_20: /* M3 Cut 11 */ + case PRR_PRODUCT_21: /* M3 Cut 13 */ + case PRR_PRODUCT_30: /* M3 Cut 30 */ + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#endif +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) + case PRR_PRODUCT_M3N: + refperiod = REFPERIOD_CYCLE; + break; +#endif + default: + break; + } +#elif RCAR_LSI == RCAR_H3 +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* H3 Cut 10 */ +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* H3 Cut 11 */ +#else + /* H3 Cut 20 */ + /* H3 Cut 30 or later */ + refperiod = REFPERIOD_CYCLE; +#endif +#elif RCAR_LSI == RCAR_H3N + /* H3N Cut 30 or later */ + refperiod = REFPERIOD_CYCLE; +#elif RCAR_LSI == RCAR_M3 +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* M3 Cut 10 */ +#else + /* M3 Cut 11 */ + /* M3 Cut 13 */ + /* M3 Cut 30 or later */ + refperiod = REFPERIOD_CYCLE; +#endif +#elif RCAR_LSI == RCAR_M3N /* for M3N */ + refperiod = REFPERIOD_CYCLE; +#endif + + return refperiod; +} +#endif + +void rcar_qos_dbsc_setting(struct rcar_gen3_dbsc_qos_settings *qos, + unsigned int qos_size, bool dbsc_wren) +{ + int i; + + /* Register write enable */ + if (dbsc_wren) + io_write_32(DBSC_DBSYSCNT0, 0x00001234U); + + for (i = 0; i < qos_size; i++) + io_write_32(qos[i].reg, qos[i].val); + + /* Register write protect */ + if (dbsc_wren) + io_write_32(DBSC_DBSYSCNT0, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h new file mode 100644 index 0000000..1b64992 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H +#define QOS_INIT_H + +extern void rcar_qos_init(void); +extern uint8_t get_boardcnf_phyvalid(void); + +#endif /* QOS_INIT_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/board/board.c b/arm-trusted-firmware/drivers/renesas/rzg/board/board.c new file mode 100644 index 0000000..7636372 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/board/board.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "board.h" +#include "rcar_def.h" + +#ifndef BOARD_DEFAULT +#if (RCAR_LSI == RZ_G2H) +#define BOARD_DEFAULT (BOARD_HIHOPE_RZ_G2H << BOARD_CODE_SHIFT) +#elif (RCAR_LSI == RZ_G2N) +#define BOARD_DEFAULT (BOARD_HIHOPE_RZ_G2N << BOARD_CODE_SHIFT) +#elif (RCAR_LSI == RZ_G2E) +#define BOARD_DEFAULT (BOARD_EK874_RZ_G2E << BOARD_CODE_SHIFT) +#else +#define BOARD_DEFAULT (BOARD_HIHOPE_RZ_G2M << BOARD_CODE_SHIFT) +#endif /* RCAR_LSI == RZ_G2H */ +#endif /* BOARD_DEFAULT */ + +#define BOARD_CODE_MASK (0xF8U) +#define BOARD_REV_MASK (0x07U) +#define BOARD_CODE_SHIFT (0x03) +#define BOARD_ID_UNKNOWN (0xFFU) + +#define GPIO_INDT5 0xE605500C +#define GP5_19_BIT (0x01U << 19) +#define GP5_21_BIT (0x01U << 21) +#define GP5_25_BIT (0x01U << 25) + +#define HM_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define HH_ID HM_ID +#define HN_ID { 0x20U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define EK_ID HM_ID + +const char *g_board_tbl[] = { + [BOARD_HIHOPE_RZ_G2M] = "HiHope RZ/G2M", + [BOARD_HIHOPE_RZ_G2H] = "HiHope RZ/G2H", + [BOARD_HIHOPE_RZ_G2N] = "HiHope RZ/G2N", + [BOARD_EK874_RZ_G2E] = "EK874 RZ/G2E", + [BOARD_UNKNOWN] = "unknown" +}; + +void rzg_get_board_type(uint32_t *type, uint32_t *rev) +{ + static uint8_t board_id = BOARD_ID_UNKNOWN; + const uint8_t board_tbl[][8] = { + [BOARD_HIHOPE_RZ_G2M] = HM_ID, + [BOARD_HIHOPE_RZ_G2H] = HH_ID, + [BOARD_HIHOPE_RZ_G2N] = HN_ID, + [BOARD_EK874_RZ_G2E] = EK_ID, + }; + uint32_t reg; +#if (RCAR_LSI != RZ_G2E) + uint32_t boardInfo; +#endif /* RCAR_LSI == RZ_G2E */ + + if (board_id == BOARD_ID_UNKNOWN) { + board_id = BOARD_DEFAULT; + } + + *type = ((uint32_t) board_id & BOARD_CODE_MASK) >> BOARD_CODE_SHIFT; + + if (*type >= ARRAY_SIZE(board_tbl)) { + /* no revision information, set Rev0.0. */ + *rev = 0; + return; + } + + reg = mmio_read_32(RCAR_PRR); +#if (RCAR_LSI == RZ_G2E) + if (reg & RCAR_MINOR_MASK) { + *rev = 0x30U; + } else { + *rev = board_tbl[*type][(uint8_t)(board_id & BOARD_REV_MASK)]; + } +#else + if ((reg & PRR_CUT_MASK) == RCAR_M3_CUT_VER11) { + *rev = board_tbl[*type][(uint8_t)(board_id & BOARD_REV_MASK)]; + } else { + reg = mmio_read_32(GPIO_INDT5); + if (reg & GP5_25_BIT) { + *rev = board_tbl[*type][(uint8_t)(board_id & BOARD_REV_MASK)]; + } else { + boardInfo = reg & (GP5_19_BIT | GP5_21_BIT); + *rev = (((boardInfo & GP5_19_BIT) >> 14) | + ((boardInfo & GP5_21_BIT) >> 17)) + 0x30U; + } + } +#endif /* RCAR_LSI == RZ_G2E */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/board/board.h b/arm-trusted-firmware/drivers/renesas/rzg/board/board.h new file mode 100644 index 0000000..1a76849 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/board/board.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RZ_G2_BOARD_H +#define RZ_G2_BOARD_H + +enum rzg2_board_id { + BOARD_HIHOPE_RZ_G2M = 0, + BOARD_HIHOPE_RZ_G2H, + BOARD_HIHOPE_RZ_G2N, + BOARD_EK874_RZ_G2E, + BOARD_UNKNOWN +}; + +#define BOARD_REV_UNKNOWN (0xFFU) + +extern const char *g_board_tbl[]; + +/************************************************************************ + * Revisions are expressed in 8 bits. + * The upper 4 bits are major version. + * The lower 4 bits are minor version. + ************************************************************************/ +#define GET_BOARD_MAJOR(a) ((uint32_t)(a) >> 0x4) +#define GET_BOARD_MINOR(a) ((uint32_t)(a) & 0xF) +#define GET_BOARD_NAME(a) (g_board_tbl[(a)]) + +void rzg_get_board_type(uint32_t *type, uint32_t *rev); + +#endif /* RZ_G2_BOARD_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c new file mode 100644 index 0000000..663df50 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "pfc_init_g2e.h" +#include "rcar_def.h" + +#include "../pfc_regs.h" + +/* PFC */ +#define GPSR0_SDA4 BIT(17) +#define GPSR0_SCL4 BIT(16) +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_WE0 BIT(22) +#define GPSR1_CS0 BIT(21) +#define GPSR1_CLKOUT BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_BIT27_REVERSED BIT(27) +#define GPSR2_BIT26_REVERSED BIT(26) +#define GPSR2_EX_WAIT0 BIT(25) +#define GPSR2_RD_WR BIT(24) +#define GPSR2_RD BIT(23) +#define GPSR2_BS BIT(22) +#define GPSR2_AVB_PHY_INT BIT(21) +#define GPSR2_AVB_TXCREFCLK BIT(20) +#define GPSR2_AVB_RD3 BIT(19) +#define GPSR2_AVB_RD2 BIT(18) +#define GPSR2_AVB_RD1 BIT(17) +#define GPSR2_AVB_RD0 BIT(16) +#define GPSR2_AVB_RXC BIT(15) +#define GPSR2_AVB_RX_CTL BIT(14) +#define GPSR2_RPC_RESET BIT(13) +#define GPSR2_RPC_RPC_INT BIT(12) +#define GPSR2_QSPI1_SSL BIT(11) +#define GPSR2_QSPI1_IO3 BIT(10) +#define GPSR2_QSPI1_IO2 BIT(9) +#define GPSR2_QSPI1_MISO_IO1 BIT(8) +#define GPSR2_QSPI1_MOSI_IO0 BIT(7) +#define GPSR2_QSPI1_SPCLK BIT(6) +#define GPSR2_QSPI0_SSL BIT(5) +#define GPSR2_QSPI0_IO3 BIT(4) +#define GPSR2_QSPI0_IO2 BIT(3) +#define GPSR2_QSPI0_MISO_IO1 BIT(2) +#define GPSR2_QSPI0_MOSI_IO0 BIT(1) +#define GPSR2_QSPI0_SPCLK BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(10) +#define GPSR4_SD3_DAT7 BIT(9) +#define GPSR4_SD3_DAT6 BIT(8) +#define GPSR4_SD3_DAT5 BIT(7) +#define GPSR4_SD3_DAT4 BIT(6) +#define GPSR4_SD3_DAT3 BIT(5) +#define GPSR4_SD3_DAT2 BIT(4) +#define GPSR4_SD3_DAT1 BIT(3) +#define GPSR4_SD3_DAT0 BIT(2) +#define GPSR4_SD3_CMD BIT(1) +#define GPSR4_SD3_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(19) +#define GPSR5_MLB_SIG BIT(18) +#define GPSR5_MLB_CLK BIT(17) +#define GPSR5_SSI_SDATA9 BIT(16) +#define GPSR5_MSIOF0_SS2 BIT(15) +#define GPSR5_MSIOF0_SS1 BIT(14) +#define GPSR5_MSIOF0_SYNC BIT(13) +#define GPSR5_MSIOF0_TXD BIT(12) +#define GPSR5_MSIOF0_RXD BIT(11) +#define GPSR5_MSIOF0_SCK BIT(10) +#define GPSR5_RX2_A BIT(9) +#define GPSR5_TX2_A BIT(8) +#define GPSR5_SCK2_A BIT(7) +#define GPSR5_TX1 BIT(6) +#define GPSR5_RX1 BIT(5) +#define GPSR5_RTS0_A BIT(4) +#define GPSR5_CTS0_A BIT(3) +#define GPSR5_TX0_A BIT(2) +#define GPSR5_RX0_A BIT(1) +#define GPSR5_SCK0_A BIT(0) +#define GPSR6_USB30_PWEN BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_USB30_OVC BIT(9) +#define GPSR6_AUDIO_CLKA BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS349 BIT(6) +#define GPSR6_SSI_SCK349 BIT(5) +#define GPSR6_SSI_SDATA2 BIT(4) +#define GPSR6_SSI_SDATA1 BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS01239 BIT(1) +#define GPSR6_SSI_SCK01239 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POCCTRL0_MASK (0x0007F000U) +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define POCCTRL2_MASK (0xFFFFFFFEU) +#define POC2_VREF_33V BIT(0) + +#define MOD_SEL0_ADGB_A ((uint32_t)0U << 29U) +#define MOD_SEL0_ADGB_B ((uint32_t)1U << 29U) +#define MOD_SEL0_ADGB_C ((uint32_t)2U << 29U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 28U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 28U) +#define MOD_SEL0_FM_A ((uint32_t)0U << 26U) +#define MOD_SEL0_FM_B ((uint32_t)1U << 26U) +#define MOD_SEL0_FM_C ((uint32_t)2U << 26U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 25U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 25U) +#define MOD_SEL0_HSCIF0_A ((uint32_t)0U << 24U) +#define MOD_SEL0_HSCIF0_B ((uint32_t)1U << 24U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 23U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 23U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 22U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_I2C1_C ((uint32_t)2U << 20U) +#define MOD_SEL0_I2C1_D ((uint32_t)3U << 20U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 17U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 17U) +#define MOD_SEL0_I2C2_C ((uint32_t)2U << 17U) +#define MOD_SEL0_I2C2_D ((uint32_t)3U << 17U) +#define MOD_SEL0_I2C2_E ((uint32_t)4U << 17U) +#define MOD_SEL0_NDFC_A ((uint32_t)0U << 16U) +#define MOD_SEL0_NDFC_B ((uint32_t)1U << 16U) +#define MOD_SEL0_PWM0_A ((uint32_t)0U << 15U) +#define MOD_SEL0_PWM0_B ((uint32_t)1U << 15U) +#define MOD_SEL0_PWM1_A ((uint32_t)0U << 14U) +#define MOD_SEL0_PWM1_B ((uint32_t)1U << 14U) +#define MOD_SEL0_PWM2_A ((uint32_t)0U << 12U) +#define MOD_SEL0_PWM2_B ((uint32_t)1U << 12U) +#define MOD_SEL0_PWM2_C ((uint32_t)2U << 12U) +#define MOD_SEL0_PWM3_A ((uint32_t)0U << 10U) +#define MOD_SEL0_PWM3_B ((uint32_t)1U << 10U) +#define MOD_SEL0_PWM3_C ((uint32_t)2U << 10U) +#define MOD_SEL0_PWM4_A ((uint32_t)0U << 9U) +#define MOD_SEL0_PWM4_B ((uint32_t)1U << 9U) +#define MOD_SEL0_PWM5_A ((uint32_t)0U << 8U) +#define MOD_SEL0_PWM5_B ((uint32_t)1U << 8U) +#define MOD_SEL0_PWM6_A ((uint32_t)0U << 7U) +#define MOD_SEL0_PWM6_B ((uint32_t)1U << 7U) +#define MOD_SEL0_REMOCON_A ((uint32_t)0U << 5U) +#define MOD_SEL0_REMOCON_B ((uint32_t)1U << 5U) +#define MOD_SEL0_REMOCON_C ((uint32_t)2U << 5U) +#define MOD_SEL0_SCIF_A ((uint32_t)0U << 4U) +#define MOD_SEL0_SCIF_B ((uint32_t)1U << 4U) +#define MOD_SEL0_SCIF0_A ((uint32_t)0U << 3U) +#define MOD_SEL0_SCIF0_B ((uint32_t)1U << 3U) +#define MOD_SEL0_SCIF2_A ((uint32_t)0U << 2U) +#define MOD_SEL0_SCIF2_B ((uint32_t)1U << 2U) +#define MOD_SEL0_SPEED_PULSE_IF_A ((uint32_t)0U << 0U) +#define MOD_SEL0_SPEED_PULSE_IF_B ((uint32_t)1U << 0U) +#define MOD_SEL0_SPEED_PULSE_IF_C ((uint32_t)2U << 0U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 31U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 31U) +#define MOD_SEL1_SSI2_A ((uint32_t)0U << 30U) +#define MOD_SEL1_SSI2_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 29U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 29U) +#define MOD_SEL1_USB20_CH0_A ((uint32_t)0U << 28U) +#define MOD_SEL1_USB20_CH0_B ((uint32_t)1U << 28U) +#define MOD_SEL1_DRIF2_A ((uint32_t)0U << 26U) +#define MOD_SEL1_DRIF2_B ((uint32_t)1U << 26U) +#define MOD_SEL1_DRIF3_A ((uint32_t)0U << 25U) +#define MOD_SEL1_DRIF3_B ((uint32_t)1U << 25U) +#define MOD_SEL1_HSCIF3_A ((uint32_t)0U << 22U) +#define MOD_SEL1_HSCIF3_B ((uint32_t)1U << 22U) +#define MOD_SEL1_HSCIF3_C ((uint32_t)2U << 22U) +#define MOD_SEL1_HSCIF3_D ((uint32_t)3U << 22U) +#define MOD_SEL1_HSCIF3_E ((uint32_t)4U << 22U) +#define MOD_SEL1_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL1_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL1_HSCIF4_C ((uint32_t)2U << 19U) +#define MOD_SEL1_HSCIF4_D ((uint32_t)3U << 19U) +#define MOD_SEL1_HSCIF4_E ((uint32_t)4U << 19U) +#define MOD_SEL1_I2C6_A ((uint32_t)0U << 18U) +#define MOD_SEL1_I2C6_B ((uint32_t)1U << 18U) +#define MOD_SEL1_I2C7_A ((uint32_t)0U << 17U) +#define MOD_SEL1_I2C7_B ((uint32_t)1U << 17U) +#define MOD_SEL1_MSIOF2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_MSIOF2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_MSIOF3_A ((uint32_t)0U << 15U) +#define MOD_SEL1_MSIOF3_B ((uint32_t)1U << 15U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF3_C ((uint32_t)2U << 13U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 11U) +#define MOD_SEL1_SCIF5_A ((uint32_t)0U << 9U) +#define MOD_SEL1_SCIF5_B ((uint32_t)1U << 9U) +#define MOD_SEL1_SCIF5_C ((uint32_t)2U << 9U) +#define MOD_SEL1_VIN4_A ((uint32_t)0U << 8U) +#define MOD_SEL1_VIN4_B ((uint32_t)1U << 8U) +#define MOD_SEL1_VIN5_A ((uint32_t)0U << 7U) +#define MOD_SEL1_VIN5_B ((uint32_t)1U << 7U) +#define MOD_SEL1_ADGC_A ((uint32_t)0U << 5U) +#define MOD_SEL1_ADGC_B ((uint32_t)1U << 5U) +#define MOD_SEL1_ADGC_C ((uint32_t)2U << 5U) +#define MOD_SEL1_SSI9_A ((uint32_t)0U << 4U) +#define MOD_SEL1_SSI9_B ((uint32_t)1U << 4U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_g2e(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, + MOD_SEL0_ADGB_A | + MOD_SEL0_DRIF0_A | + MOD_SEL0_FM_A | + MOD_SEL0_FSO_A | + MOD_SEL0_HSCIF0_A | + MOD_SEL0_HSCIF1_A | + MOD_SEL0_HSCIF2_A | + MOD_SEL0_I2C1_A | + MOD_SEL0_I2C2_A | + MOD_SEL0_NDFC_A | + MOD_SEL0_PWM0_A | + MOD_SEL0_PWM1_A | + MOD_SEL0_PWM2_A | + MOD_SEL0_PWM3_A | + MOD_SEL0_PWM4_A | + MOD_SEL0_PWM5_A | + MOD_SEL0_PWM6_A | + MOD_SEL0_REMOCON_A | + MOD_SEL0_SCIF_A | + MOD_SEL0_SCIF0_A | + MOD_SEL0_SCIF2_A | + MOD_SEL0_SPEED_PULSE_IF_A); + + pfc_reg_write(PFC_MOD_SEL1, + MOD_SEL1_SIMCARD_A | + MOD_SEL1_SSI2_A | + MOD_SEL1_TIMER_TMU_A | + MOD_SEL1_USB20_CH0_B | + MOD_SEL1_DRIF2_A | + MOD_SEL1_DRIF3_A | + MOD_SEL1_HSCIF3_C | + MOD_SEL1_HSCIF4_B | + MOD_SEL1_I2C6_A | + MOD_SEL1_I2C7_A | + MOD_SEL1_MSIOF2_A | + MOD_SEL1_MSIOF3_A | + MOD_SEL1_SCIF3_A | + MOD_SEL1_SCIF4_A | + MOD_SEL1_SCIF5_A | + MOD_SEL1_VIN4_A | + MOD_SEL1_VIN5_A | + MOD_SEL1_ADGC_A | + MOD_SEL1_SSI9_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, + IPSR_28_FUNC(2) | /* HRX4_B */ + IPSR_24_FUNC(2) | /* HTX4_B */ + IPSR_20_FUNC(0) | /* QSPI1_SPCLK */ + IPSR_16_FUNC(0) | /* QSPI0_IO3 */ + IPSR_12_FUNC(0) | /* QSPI0_IO2 */ + IPSR_8_FUNC(0) | /* QSPI0_MISO/IO1 */ + IPSR_4_FUNC(0) | /* QSPI0_MOSI/IO0 */ + IPSR_0_FUNC(0)); /* QSPI0_SPCLK */ + + pfc_reg_write(PFC_IPSR1, + IPSR_28_FUNC(0) | /* AVB_RD2 */ + IPSR_24_FUNC(0) | /* AVB_RD1 */ + IPSR_20_FUNC(0) | /* AVB_RD0 */ + IPSR_16_FUNC(0) | /* RPC_RESET# */ + IPSR_12_FUNC(0) | /* RPC_INT# */ + IPSR_8_FUNC(0) | /* QSPI1_SSL */ + IPSR_4_FUNC(2) | /* HRX3_C */ + IPSR_0_FUNC(2)); /* HTX3_C */ + + pfc_reg_write(PFC_IPSR2, + IPSR_28_FUNC(1) | /* IRQ0 */ + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(2) | /* AVB_LINK */ + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | /* AVB_MDC */ + IPSR_4_FUNC(0) | /* AVB_MDIO */ + IPSR_0_FUNC(0)); /* AVB_TXCREFCLK */ + + pfc_reg_write(PFC_IPSR3, + IPSR_28_FUNC(5) | /* DU_HSYNC */ + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(5) | /* DU_DG4 */ + IPSR_8_FUNC(5) | /* DU_DOTCLKOUT0 */ + IPSR_4_FUNC(5) | /* DU_DISP */ + IPSR_0_FUNC(1)); /* IRQ1 */ + + pfc_reg_write(PFC_IPSR4, + IPSR_28_FUNC(5) | /* DU_DB5 */ + IPSR_24_FUNC(5) | /* DU_DB4 */ + IPSR_20_FUNC(5) | /* DU_DB3 */ + IPSR_16_FUNC(5) | /* DU_DB2 */ + IPSR_12_FUNC(5) | /* DU_DG6 */ + IPSR_8_FUNC(5) | /* DU_VSYNC */ + IPSR_4_FUNC(5) | /* DU_DG5 */ + IPSR_0_FUNC(5)); /* DU_DG7 */ + + pfc_reg_write(PFC_IPSR5, + IPSR_28_FUNC(5) | /* DU_DR3 */ + IPSR_24_FUNC(5) | /* DU_DB7 */ + IPSR_20_FUNC(5) | /* DU_DR2 */ + IPSR_16_FUNC(5) | /* DU_DR1 */ + IPSR_12_FUNC(5) | /* DU_DR0 */ + IPSR_8_FUNC(5) | /* DU_DB1 */ + IPSR_4_FUNC(5) | /* DU_DB0 */ + IPSR_0_FUNC(5)); /* DU_DB6 */ + + pfc_reg_write(PFC_IPSR6, + IPSR_28_FUNC(5) | /* DU_DG1 */ + IPSR_24_FUNC(5) | /* DU_DG0 */ + IPSR_20_FUNC(5) | /* DU_DR7 */ + IPSR_16_FUNC(1) | /* CANFD1_RX */ + IPSR_12_FUNC(5) | /* DU_DR6 */ + IPSR_8_FUNC(5) | /* DU_DR5 */ + IPSR_4_FUNC(1) | /* CANFD1_TX */ + IPSR_0_FUNC(5)); /* DU_DR4 */ + + pfc_reg_write(PFC_IPSR7, + IPSR_28_FUNC(0) | /* SD0_CLK */ + IPSR_24_FUNC(0) | + IPSR_20_FUNC(5) | /* DU_DOTCLKIN0 */ + IPSR_16_FUNC(5) | /* DU_DG3 */ + IPSR_12_FUNC(1) | /* CAN_CLK */ + IPSR_8_FUNC(1) | /* CANFD0_RX */ + IPSR_4_FUNC(1) | /* CANFD0_TX */ + IPSR_0_FUNC(5)); /* DU_DG2 */ + + pfc_reg_write(PFC_IPSR8, + IPSR_28_FUNC(0) | /* SD1_DAT0 */ + IPSR_24_FUNC(0) | /* SD1_CMD */ + IPSR_20_FUNC(0) | /* SD1_CLK */ + IPSR_16_FUNC(0) | /* SD0_DAT3 */ + IPSR_12_FUNC(0) | /* SD0_DAT2 */ + IPSR_8_FUNC(0) | /* SD0_DAT1 */ + IPSR_4_FUNC(0) | /* SD0_DAT0 */ + IPSR_0_FUNC(0)); /* SD0_CMD */ + + pfc_reg_write(PFC_IPSR9, + IPSR_28_FUNC(0) | /* SD3_DAT2 */ + IPSR_24_FUNC(0) | /* SD3_DAT1 */ + IPSR_20_FUNC(0) | /* SD3_DAT0 */ + IPSR_16_FUNC(0) | /* SD3_CMD */ + IPSR_12_FUNC(0) | /* SD3_CLK */ + IPSR_8_FUNC(0) | /* SD1_DAT3 */ + IPSR_4_FUNC(0) | /* SD1_DAT2 */ + IPSR_0_FUNC(0)); /* SD1_DAT1 */ + + pfc_reg_write(PFC_IPSR10, + IPSR_24_FUNC(0) | /* SD0_CD */ + IPSR_20_FUNC(0) | /* SD3_DS */ + IPSR_16_FUNC(0) | /* SD3_DAT7 */ + IPSR_12_FUNC(0) | /* SD3_DAT6 */ + IPSR_8_FUNC(0) | /* SD3_DAT5 */ + IPSR_4_FUNC(0) | /* SD3_DAT4 */ + IPSR_0_FUNC(0)); /* SD3_DAT3 */ + + pfc_reg_write(PFC_IPSR11, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(8) | /* USB0_ID */ + IPSR_20_FUNC(2) | /* AUDIO_CLKOUT1_A */ + IPSR_16_FUNC(0) | /* CTS0#_A */ + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | /* SD1_WP */ + IPSR_0_FUNC(0)); /* SD1_CD */ + + pfc_reg_write(PFC_IPSR12, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | /* RX2_A */ + IPSR_8_FUNC(0) | /* TX2_A */ + IPSR_4_FUNC(0) | /* SCK2_A */ + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR13, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(4) | /* SDA1_B */ + IPSR_12_FUNC(4) | /* SCL1_B */ + IPSR_8_FUNC(0) | /* SSI_SDATA9 */ + IPSR_4_FUNC(1) | /* HTX2_A */ + IPSR_0_FUNC(1)); /* HRX2_A */ + + pfc_reg_write(PFC_IPSR14, + IPSR_28_FUNC(0) | /* SSI_SCK5 */ + IPSR_24_FUNC(0) | /* SSI_SDATA4 */ + IPSR_20_FUNC(0) | /* SSI_SDATA3 */ + IPSR_16_FUNC(0) | /* SSI_WS349 */ + IPSR_12_FUNC(0) | /* SSI_SCK349 */ + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | /* SSI_SDATA1 */ + IPSR_0_FUNC(0));/* SSI_SDATA0 */ + + pfc_reg_write(PFC_IPSR15, + IPSR_28_FUNC(0) | /* USB30_OVC */ + IPSR_24_FUNC(0) | /* USB30_PWEN */ + IPSR_20_FUNC(0) | /* AUDIO_CLKA */ + IPSR_16_FUNC(1) | /* HRTS2#_A */ + IPSR_12_FUNC(1) | /* HCTS2#_A */ + IPSR_8_FUNC(3) | /* TPU0TO1 */ + IPSR_4_FUNC(3) | /* TPU0TO0 */ + IPSR_0_FUNC(0)); /* SSI_WS5 */ + + /* initialize GPIO/peripheral function select */ + pfc_reg_write(PFC_GPSR0, + GPSR0_SCL4 | + GPSR0_D15 | + GPSR0_D14 | + GPSR0_D13 | + GPSR0_D12 | + GPSR0_D11 | + GPSR0_D10 | + GPSR0_D9 | + GPSR0_D8 | + GPSR0_D7 | + GPSR0_D6 | + GPSR0_D5 | + GPSR0_D4 | + GPSR0_D3 | + GPSR0_D2 | + GPSR0_D1 | + GPSR0_D0); + + pfc_reg_write(PFC_GPSR1, + GPSR1_WE0 | + GPSR1_CS0 | + GPSR1_A19 | + GPSR1_A18 | + GPSR1_A17 | + GPSR1_A16 | + GPSR1_A15 | + GPSR1_A14 | + GPSR1_A13 | + GPSR1_A12 | + GPSR1_A11 | + GPSR1_A10 | + GPSR1_A9 | + GPSR1_A8 | + GPSR1_A4 | + GPSR1_A3 | + GPSR1_A2 | + GPSR1_A1 | + GPSR1_A0); + + pfc_reg_write(PFC_GPSR2, + GPSR2_BIT27_REVERSED | + GPSR2_BIT26_REVERSED | + GPSR2_AVB_PHY_INT | + GPSR2_AVB_TXCREFCLK | + GPSR2_AVB_RD3 | + GPSR2_AVB_RD2 | + GPSR2_AVB_RD1 | + GPSR2_AVB_RD0 | + GPSR2_AVB_RXC | + GPSR2_AVB_RX_CTL | + GPSR2_RPC_RESET | + GPSR2_RPC_RPC_INT | + GPSR2_QSPI1_IO3 | + GPSR2_QSPI1_IO2 | + GPSR2_QSPI1_MISO_IO1 | + GPSR2_QSPI1_MOSI_IO0 | + GPSR2_QSPI0_SSL | + GPSR2_QSPI0_IO3 | + GPSR2_QSPI0_IO2 | + GPSR2_QSPI0_MISO_IO1 | + GPSR2_QSPI0_MOSI_IO0 | + GPSR2_QSPI0_SPCLK); + + pfc_reg_write(PFC_GPSR3, + GPSR3_SD0_CD | + GPSR3_SD1_DAT3 | + GPSR3_SD1_DAT2 | + GPSR3_SD1_DAT1 | + GPSR3_SD1_DAT0 | + GPSR3_SD1_CMD | + GPSR3_SD1_CLK | + GPSR3_SD0_DAT3 | + GPSR3_SD0_DAT2 | + GPSR3_SD0_DAT1 | + GPSR3_SD0_DAT0 | + GPSR3_SD0_CMD | + GPSR3_SD0_CLK); + + pfc_reg_write(PFC_GPSR4, + GPSR4_SD3_DAT3 | + GPSR4_SD3_DAT2 | + GPSR4_SD3_DAT1 | + GPSR4_SD3_DAT0 | + GPSR4_SD3_CMD | + GPSR4_SD3_CLK); + + pfc_reg_write(PFC_GPSR5, + GPSR5_MLB_SIG | + GPSR5_MLB_CLK | + GPSR5_SSI_SDATA9 | + GPSR5_MSIOF0_SS2 | + GPSR5_MSIOF0_SS1 | + GPSR5_MSIOF0_SYNC | + GPSR5_MSIOF0_TXD | + GPSR5_MSIOF0_RXD | + GPSR5_MSIOF0_SCK | + GPSR5_RX2_A | + GPSR5_TX2_A | + GPSR5_RTS0_A | + GPSR5_SCK0_A); + + pfc_reg_write(PFC_GPSR6, + GPSR6_USB30_PWEN | + GPSR6_SSI_SDATA6 | + GPSR6_SSI_WS6 | + GPSR6_SSI_SCK6 | + GPSR6_SSI_SDATA5 | + GPSR6_SSI_SCK5 | + GPSR6_SSI_SDATA4 | + GPSR6_USB30_OVC | + GPSR6_AUDIO_CLKA | + GPSR6_SSI_SDATA3 | + GPSR6_SSI_WS349 | + GPSR6_SSI_SCK349 | + GPSR6_SSI_SDATA0 | + GPSR6_SSI_WS01239 | + GPSR6_SSI_SCK01239); + + /* initialize POC control */ + reg = mmio_read_32(PFC_POCCTRL0); + reg = (reg & POCCTRL0_MASK) | + POC_SD1_DAT3_33V | + POC_SD1_DAT2_33V | + POC_SD1_DAT1_33V | + POC_SD1_DAT0_33V | + POC_SD1_CMD_33V | + POC_SD1_CLK_33V | + POC_SD0_DAT3_33V | + POC_SD0_DAT2_33V | + POC_SD0_DAT1_33V | + POC_SD0_DAT0_33V | + POC_SD0_CMD_33V | + POC_SD0_CLK_33V; + pfc_reg_write(PFC_POCCTRL0, reg); + + reg = mmio_read_32(PFC_POCCTRL2); + reg = ((reg & POCCTRL2_MASK) & ~POC2_VREF_33V); + pfc_reg_write(PFC_POCCTRL2, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00080000U); + pfc_reg_write(PFC_PUD1, 0xCE398464U); + pfc_reg_write(PFC_PUD2, 0xA4C380F4U); + pfc_reg_write(PFC_PUD3, 0x0000079FU); + pfc_reg_write(PFC_PUD4, 0xFFF0FFFFU); + pfc_reg_write(PFC_PUD5, 0x40000000U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000000U); + pfc_reg_write(PFC_PUEN1, 0x00300000U); + pfc_reg_write(PFC_PUEN2, 0x00400074U); + pfc_reg_write(PFC_PUEN3, 0x00000000U); + pfc_reg_write(PFC_PUEN4, 0x07900600U); + pfc_reg_write(PFC_PUEN5, 0x00000000U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000000U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000000U); + mmio_write_32(GPIO_OUTDT3, 0x00006000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + mmio_write_32(GPIO_OUTDT6, 0x00000000U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00020000U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100000U); + mmio_write_32(GPIO_INOUTSEL2, 0x03000000U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000E000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000440U); + mmio_write_32(GPIO_INOUTSEL5, 0x00080000U); + mmio_write_32(GPIO_INOUTSEL6, 0x00000010U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h new file mode 100644 index 0000000..677591a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_G2E_H +#define PFC_INIT_G2E_H + +void pfc_init_g2e(void); + +#endif /* PFC_INIT_G2E_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c new file mode 100644 index 0000000..90a1c99 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c @@ -0,0 +1,1310 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "pfc_init_g2h.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_g2h(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, + MOD_SEL0_MSIOF3_A | + MOD_SEL0_MSIOF2_A | + MOD_SEL0_MSIOF1_A | + MOD_SEL0_LBSC_A | + MOD_SEL0_IEBUS_A | + MOD_SEL0_I2C2_A | + MOD_SEL0_I2C1_A | + MOD_SEL0_HSCIF4_A | + MOD_SEL0_HSCIF3_A | + MOD_SEL0_HSCIF1_A | + MOD_SEL0_FSO_A | + MOD_SEL0_HSCIF2_A | + MOD_SEL0_ETHERAVB_A | + MOD_SEL0_DRIF3_A | + MOD_SEL0_DRIF2_A | + MOD_SEL0_DRIF1_A | + MOD_SEL0_DRIF0_A | + MOD_SEL0_CANFD0_A | + MOD_SEL0_ADG_A_A); + + pfc_reg_write(PFC_MOD_SEL1, + MOD_SEL1_TSIF1_A | + MOD_SEL1_TSIF0_A | + MOD_SEL1_TIMER_TMU_A | + MOD_SEL1_SSP1_1_A | + MOD_SEL1_SSP1_0_A | + MOD_SEL1_SSI_A | + MOD_SEL1_SPEED_PULSE_IF_A | + MOD_SEL1_SIMCARD_A | + MOD_SEL1_SDHI2_A | + MOD_SEL1_SCIF4_A | + MOD_SEL1_SCIF3_A | + MOD_SEL1_SCIF2_A | + MOD_SEL1_SCIF1_A | + MOD_SEL1_SCIF_A | + MOD_SEL1_REMOCON_A | + MOD_SEL1_RCAN0_A | + MOD_SEL1_PWM6_A | + MOD_SEL1_PWM5_A | + MOD_SEL1_PWM4_A | + MOD_SEL1_PWM3_A | + MOD_SEL1_PWM2_A | + MOD_SEL1_PWM1_A); + + pfc_reg_write(PFC_MOD_SEL2, + MOD_SEL2_I2C_5_B | + MOD_SEL2_I2C_3_B | + MOD_SEL2_I2C_0_B | + MOD_SEL2_FM_A | + MOD_SEL2_SCIF5_A | + MOD_SEL2_I2C6_A | + MOD_SEL2_NDF_A | + MOD_SEL2_SSI2_A | + MOD_SEL2_SSI9_A | + MOD_SEL2_TIMER_TMU2_A | + MOD_SEL2_ADG_B_A | + MOD_SEL2_ADG_C_A | + MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR1, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(3) | + IPSR_8_FUNC(3) | + IPSR_4_FUNC(3) | + IPSR_0_FUNC(3)); + + pfc_reg_write(PFC_IPSR2, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR3, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR4, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR5, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR6, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR7, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR8, + IPSR_28_FUNC(1) | + IPSR_24_FUNC(1) | + IPSR_20_FUNC(1) | + IPSR_16_FUNC(1) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR9, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR10, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR11, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(4) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR12, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(4) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR13, + IPSR_28_FUNC(8) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(3) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR14, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(3) | + IPSR_0_FUNC(8)); + + pfc_reg_write(PFC_IPSR15, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR16, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR17, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(1) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR18, + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + /* initialize GPIO/peripheral function select */ + pfc_reg_write(PFC_GPSR0, + GPSR0_D15 | + GPSR0_D14 | + GPSR0_D13 | + GPSR0_D12 | + GPSR0_D11 | + GPSR0_D10 | + GPSR0_D9 | + GPSR0_D8 | + GPSR0_D7 | + GPSR0_D6 | + GPSR0_D5 | + GPSR0_D4 | + GPSR0_D3 | + GPSR0_D2 | + GPSR0_D0); + + pfc_reg_write(PFC_GPSR1, + GPSR1_CLKOUT | + GPSR1_EX_WAIT0_A | + GPSR1_WE1 | + GPSR1_RD | + GPSR1_RD_WR | + GPSR1_CS0 | + GPSR1_A19 | + GPSR1_A18 | + GPSR1_A17 | + GPSR1_A16 | + GPSR1_A15 | + GPSR1_A14 | + GPSR1_A13 | + GPSR1_A12 | + GPSR1_A7 | + GPSR1_A6 | + GPSR1_A5 | + GPSR1_A4 | + GPSR1_A3 | + GPSR1_A2 | + GPSR1_A1 | + GPSR1_A0); + + pfc_reg_write(PFC_GPSR2, + GPSR2_AVB_AVTP_CAPTURE_A | + GPSR2_AVB_AVTP_MATCH_A | + GPSR2_AVB_LINK | + GPSR2_AVB_PHY_INT | + GPSR2_AVB_MDC | + GPSR2_PWM2_A | + GPSR2_PWM1_A | + GPSR2_IRQ4 | + GPSR2_IRQ3 | + GPSR2_IRQ2 | + GPSR2_IRQ1 | + GPSR2_IRQ0); + + pfc_reg_write(PFC_GPSR3, + GPSR3_SD0_CD | + GPSR3_SD1_DAT3 | + GPSR3_SD1_DAT2 | + GPSR3_SD1_DAT1 | + GPSR3_SD1_DAT0 | + GPSR3_SD0_DAT3 | + GPSR3_SD0_DAT2 | + GPSR3_SD0_DAT1 | + GPSR3_SD0_DAT0 | + GPSR3_SD0_CMD | + GPSR3_SD0_CLK); + + pfc_reg_write(PFC_GPSR4, + GPSR4_SD3_DS | + GPSR4_SD3_DAT7 | + GPSR4_SD3_DAT6 | + GPSR4_SD3_DAT5 | + GPSR4_SD3_DAT4 | + GPSR4_SD3_DAT3 | + GPSR4_SD3_DAT2 | + GPSR4_SD3_DAT1 | + GPSR4_SD3_DAT0 | + GPSR4_SD3_CMD | + GPSR4_SD3_CLK | + GPSR4_SD2_DAT3 | + GPSR4_SD2_DAT2 | + GPSR4_SD2_DAT1 | + GPSR4_SD2_DAT0 | + GPSR4_SD2_CMD | + GPSR4_SD2_CLK); + + pfc_reg_write(PFC_GPSR5, + GPSR5_MSIOF0_RXD | + GPSR5_MSIOF0_TXD | + GPSR5_MSIOF0_SYNC | + GPSR5_MSIOF0_SCK | + GPSR5_RX2_A | + GPSR5_TX2_A | + GPSR5_RTS1 | + GPSR5_CTS1 | + GPSR5_TX1_A | + GPSR5_RX1_A | + GPSR5_RTS0 | + GPSR5_SCK0); + + pfc_reg_write(PFC_GPSR6, + GPSR6_AUDIO_CLKB_B | + GPSR6_AUDIO_CLKA_A | + GPSR6_SSI_WS6 | + GPSR6_SSI_SCK6 | + GPSR6_SSI_SDATA4 | + GPSR6_SSI_WS4 | + GPSR6_SSI_SCK4 | + GPSR6_SSI_SDATA1_A | + GPSR6_SSI_SDATA0 | + GPSR6_SSI_WS0129 | + GPSR6_SSI_SCK0129); + + pfc_reg_write(PFC_GPSR7, + GPSR7_AVS2 | + GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, + POC_SD0_DAT3_33V | + POC_SD0_DAT2_33V | + POC_SD0_DAT1_33V | + POC_SD0_DAT0_33V | + POC_SD0_CMD_33V | + POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = (reg & DRVCTRL0_MASK) | + DRVCTRL0_QSPI0_SPCLK(3) | + DRVCTRL0_QSPI0_MOSI_IO0(3) | + DRVCTRL0_QSPI0_MISO_IO1(3) | + DRVCTRL0_QSPI0_IO2(3) | + DRVCTRL0_QSPI0_IO3(3) | + DRVCTRL0_QSPI0_SSL(3) | + DRVCTRL0_QSPI1_SPCLK(3) | + DRVCTRL0_QSPI1_MOSI_IO0(3); + pfc_reg_write(PFC_DRVCTRL0, reg); + + reg = mmio_read_32(PFC_DRVCTRL1); + reg = (reg & DRVCTRL1_MASK) | + DRVCTRL1_QSPI1_MISO_IO1(3) | + DRVCTRL1_QSPI1_IO2(3) | + DRVCTRL1_QSPI1_IO3(3) | + DRVCTRL1_QSPI1_SS(3) | + DRVCTRL1_RPC_INT(3) | + DRVCTRL1_RPC_WP(3) | + DRVCTRL1_RPC_RESET(3) | + DRVCTRL1_AVB_RX_CTL(7); + pfc_reg_write(PFC_DRVCTRL1, reg); + + reg = mmio_read_32(PFC_DRVCTRL2); + reg = (reg & DRVCTRL2_MASK) | + DRVCTRL2_AVB_RXC(7) | + DRVCTRL2_AVB_RD0(7) | + DRVCTRL2_AVB_RD1(7) | + DRVCTRL2_AVB_RD2(7) | + DRVCTRL2_AVB_RD3(7) | + DRVCTRL2_AVB_TX_CTL(3) | + DRVCTRL2_AVB_TXC(3) | + DRVCTRL2_AVB_TD0(3); + pfc_reg_write(PFC_DRVCTRL2, reg); + + reg = mmio_read_32(PFC_DRVCTRL3); + reg = (reg & DRVCTRL3_MASK) | + DRVCTRL3_AVB_TD1(3) | + DRVCTRL3_AVB_TD2(3) | + DRVCTRL3_AVB_TD3(3) | + DRVCTRL3_AVB_TXCREFCLK(7) | + DRVCTRL3_AVB_MDIO(7) | + DRVCTRL3_AVB_MDC(7) | + DRVCTRL3_AVB_MAGIC(7) | + DRVCTRL3_AVB_PHY_INT(7); + pfc_reg_write(PFC_DRVCTRL3, reg); + + reg = mmio_read_32(PFC_DRVCTRL4); + reg = (reg & DRVCTRL4_MASK) | + DRVCTRL4_AVB_LINK(7) | + DRVCTRL4_AVB_AVTP_MATCH(7) | + DRVCTRL4_AVB_AVTP_CAPTURE(7) | + DRVCTRL4_IRQ0(7) | + DRVCTRL4_IRQ1(7) | + DRVCTRL4_IRQ2(7) | + DRVCTRL4_IRQ3(7) | + DRVCTRL4_IRQ4(7); + pfc_reg_write(PFC_DRVCTRL4, reg); + + reg = mmio_read_32(PFC_DRVCTRL5); + reg = (reg & DRVCTRL5_MASK) | + DRVCTRL5_IRQ5(7) | + DRVCTRL5_PWM0(7) | + DRVCTRL5_PWM1(7) | + DRVCTRL5_PWM2(7) | + DRVCTRL5_A0(3) | + DRVCTRL5_A1(3) | + DRVCTRL5_A2(3) | + DRVCTRL5_A3(3); + pfc_reg_write(PFC_DRVCTRL5, reg); + + reg = mmio_read_32(PFC_DRVCTRL6); + reg = (reg & DRVCTRL6_MASK) | + DRVCTRL6_A4(3) | + DRVCTRL6_A5(3) | + DRVCTRL6_A6(3) | + DRVCTRL6_A7(3) | + DRVCTRL6_A8(7) | + DRVCTRL6_A9(7) | + DRVCTRL6_A10(7) | + DRVCTRL6_A11(7); + pfc_reg_write(PFC_DRVCTRL6, reg); + + reg = mmio_read_32(PFC_DRVCTRL7); + reg = (reg & DRVCTRL7_MASK) | + DRVCTRL7_A12(3) | + DRVCTRL7_A13(3) | + DRVCTRL7_A14(3) | + DRVCTRL7_A15(3) | + DRVCTRL7_A16(3) | + DRVCTRL7_A17(3) | + DRVCTRL7_A18(3) | + DRVCTRL7_A19(3); + pfc_reg_write(PFC_DRVCTRL7, reg); + + reg = mmio_read_32(PFC_DRVCTRL8); + reg = (reg & DRVCTRL8_MASK) | + DRVCTRL8_CLKOUT(7) | + DRVCTRL8_CS0(7) | + DRVCTRL8_CS1_A2(7) | + DRVCTRL8_BS(7) | + DRVCTRL8_RD(7) | + DRVCTRL8_RD_W(7) | + DRVCTRL8_WE0(7) | + DRVCTRL8_WE1(7); + pfc_reg_write(PFC_DRVCTRL8, reg); + + reg = mmio_read_32(PFC_DRVCTRL9); + reg = (reg & DRVCTRL9_MASK) | + DRVCTRL9_EX_WAIT0(7) | + DRVCTRL9_PRESETOU(7) | + DRVCTRL9_D0(7) | + DRVCTRL9_D1(7) | + DRVCTRL9_D2(7) | + DRVCTRL9_D3(7) | + DRVCTRL9_D4(7) | + DRVCTRL9_D5(7); + pfc_reg_write(PFC_DRVCTRL9, reg); + + reg = mmio_read_32(PFC_DRVCTRL10); + reg = (reg & DRVCTRL10_MASK) | + DRVCTRL10_D6(7) | + DRVCTRL10_D7(7) | + DRVCTRL10_D8(3) | + DRVCTRL10_D9(3) | + DRVCTRL10_D10(3) | + DRVCTRL10_D11(3) | + DRVCTRL10_D12(3) | + DRVCTRL10_D13(3); + pfc_reg_write(PFC_DRVCTRL10, reg); + + reg = mmio_read_32(PFC_DRVCTRL11); + reg = (reg & DRVCTRL11_MASK) | + DRVCTRL11_D14(3) | + DRVCTRL11_D15(3) | + DRVCTRL11_AVS1(7) | + DRVCTRL11_AVS2(7) | + DRVCTRL11_GP7_02(7) | + DRVCTRL11_GP7_03(7) | + DRVCTRL11_DU_DOTCLKIN0(3) | + DRVCTRL11_DU_DOTCLKIN1(3); + pfc_reg_write(PFC_DRVCTRL11, reg); + + reg = mmio_read_32(PFC_DRVCTRL12); + reg = (reg & DRVCTRL12_MASK) | + DRVCTRL12_DU_DOTCLKIN2(3) | + DRVCTRL12_DU_DOTCLKIN3(3) | + DRVCTRL12_DU_FSCLKST(3) | + DRVCTRL12_DU_TMS(3); + pfc_reg_write(PFC_DRVCTRL12, reg); + + reg = mmio_read_32(PFC_DRVCTRL13); + reg = (reg & DRVCTRL13_MASK) | + DRVCTRL13_TDO(3) | + DRVCTRL13_ASEBRK(3) | + DRVCTRL13_SD0_CLK(7) | + DRVCTRL13_SD0_CMD(7) | + DRVCTRL13_SD0_DAT0(7) | + DRVCTRL13_SD0_DAT1(7) | + DRVCTRL13_SD0_DAT2(7) | + DRVCTRL13_SD0_DAT3(7); + pfc_reg_write(PFC_DRVCTRL13, reg); + + reg = mmio_read_32(PFC_DRVCTRL14); + reg = (reg & DRVCTRL14_MASK) | + DRVCTRL14_SD1_CLK(7) | + DRVCTRL14_SD1_CMD(7) | + DRVCTRL14_SD1_DAT0(5) | + DRVCTRL14_SD1_DAT1(5) | + DRVCTRL14_SD1_DAT2(5) | + DRVCTRL14_SD1_DAT3(5) | + DRVCTRL14_SD2_CLK(5) | + DRVCTRL14_SD2_CMD(5); + pfc_reg_write(PFC_DRVCTRL14, reg); + + reg = mmio_read_32(PFC_DRVCTRL15); + reg = (reg & DRVCTRL15_MASK) | + DRVCTRL15_SD2_DAT0(5) | + DRVCTRL15_SD2_DAT1(5) | + DRVCTRL15_SD2_DAT2(5) | + DRVCTRL15_SD2_DAT3(5) | + DRVCTRL15_SD2_DS(5) | + DRVCTRL15_SD3_CLK(7) | + DRVCTRL15_SD3_CMD(7) | + DRVCTRL15_SD3_DAT0(7); + pfc_reg_write(PFC_DRVCTRL15, reg); + + reg = mmio_read_32(PFC_DRVCTRL16); + reg = (reg & DRVCTRL16_MASK) | + DRVCTRL16_SD3_DAT1(7) | + DRVCTRL16_SD3_DAT2(7) | + DRVCTRL16_SD3_DAT3(7) | + DRVCTRL16_SD3_DAT4(7) | + DRVCTRL16_SD3_DAT5(7) | + DRVCTRL16_SD3_DAT6(7) | + DRVCTRL16_SD3_DAT7(7) | + DRVCTRL16_SD3_DS(7); + pfc_reg_write(PFC_DRVCTRL16, reg); + + reg = mmio_read_32(PFC_DRVCTRL17); + reg = (reg & DRVCTRL17_MASK) | + DRVCTRL17_SD0_CD(7) | + DRVCTRL17_SD0_WP(7) | + DRVCTRL17_SD1_CD(7) | + DRVCTRL17_SD1_WP(7) | + DRVCTRL17_SCK0(7) | + DRVCTRL17_RX0(7) | + DRVCTRL17_TX0(7) | + DRVCTRL17_CTS0(7); + pfc_reg_write(PFC_DRVCTRL17, reg); + + reg = mmio_read_32(PFC_DRVCTRL18); + reg = (reg & DRVCTRL18_MASK) | + DRVCTRL18_RTS0_TANS(7) | + DRVCTRL18_RX1(7) | + DRVCTRL18_TX1(7) | + DRVCTRL18_CTS1(7) | + DRVCTRL18_RTS1_TANS(7) | + DRVCTRL18_SCK2(7) | + DRVCTRL18_TX2(7) | + DRVCTRL18_RX2(7); + pfc_reg_write(PFC_DRVCTRL18, reg); + + reg = mmio_read_32(PFC_DRVCTRL19); + reg = (reg & DRVCTRL19_MASK) | + DRVCTRL19_HSCK0(7) | + DRVCTRL19_HRX0(7) | + DRVCTRL19_HTX0(7) | + DRVCTRL19_HCTS0(7) | + DRVCTRL19_HRTS0(7) | + DRVCTRL19_MSIOF0_SCK(7) | + DRVCTRL19_MSIOF0_SYNC(7) | + DRVCTRL19_MSIOF0_SS1(7); + pfc_reg_write(PFC_DRVCTRL19, reg); + + reg = mmio_read_32(PFC_DRVCTRL20); + reg = (reg & DRVCTRL20_MASK) | + DRVCTRL20_MSIOF0_TXD(7) | + DRVCTRL20_MSIOF0_SS2(7) | + DRVCTRL20_MSIOF0_RXD(7) | + DRVCTRL20_MLB_CLK(7) | + DRVCTRL20_MLB_SIG(7) | + DRVCTRL20_MLB_DAT(7) | + DRVCTRL20_MLB_REF(7) | + DRVCTRL20_SSI_SCK0129(7); + pfc_reg_write(PFC_DRVCTRL20, reg); + + reg = mmio_read_32(PFC_DRVCTRL21); + reg = (reg & DRVCTRL21_MASK) | + DRVCTRL21_SSI_WS0129(7) | + DRVCTRL21_SSI_SDATA0(7) | + DRVCTRL21_SSI_SDATA1(7) | + DRVCTRL21_SSI_SDATA2(7) | + DRVCTRL21_SSI_SCK34(7) | + DRVCTRL21_SSI_WS34(7) | + DRVCTRL21_SSI_SDATA3(7) | + DRVCTRL21_SSI_SCK4(7); + pfc_reg_write(PFC_DRVCTRL21, reg); + + reg = mmio_read_32(PFC_DRVCTRL22); + reg = (reg & DRVCTRL22_MASK) | + DRVCTRL22_SSI_WS4(7) | + DRVCTRL22_SSI_SDATA4(7) | + DRVCTRL22_SSI_SCK5(7) | + DRVCTRL22_SSI_WS5(7) | + DRVCTRL22_SSI_SDATA5(7) | + DRVCTRL22_SSI_SCK6(7) | + DRVCTRL22_SSI_WS6(7) | + DRVCTRL22_SSI_SDATA6(7); + pfc_reg_write(PFC_DRVCTRL22, reg); + + reg = mmio_read_32(PFC_DRVCTRL23); + reg = (reg & DRVCTRL23_MASK) | + DRVCTRL23_SSI_SCK78(7) | + DRVCTRL23_SSI_WS78(7) | + DRVCTRL23_SSI_SDATA7(7) | + DRVCTRL23_SSI_SDATA8(7) | + DRVCTRL23_SSI_SDATA9(7) | + DRVCTRL23_AUDIO_CLKA(7) | + DRVCTRL23_AUDIO_CLKB(7) | + DRVCTRL23_USB0_PWEN(7); + pfc_reg_write(PFC_DRVCTRL23, reg); + + reg = mmio_read_32(PFC_DRVCTRL24); + reg = (reg & DRVCTRL24_MASK) | + DRVCTRL24_USB0_OVC(7) | + DRVCTRL24_USB1_PWEN(7) | + DRVCTRL24_USB1_OVC(7) | + DRVCTRL24_USB30_PWEN(7) | + DRVCTRL24_USB30_OVC(7) | + DRVCTRL24_USB31_PWEN(7) | + DRVCTRL24_USB31_OVC(7); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300EFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000001U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + mmio_write_32(GPIO_OUTDT6, 0x00003800U); + mmio_write_32(GPIO_OUTDT7, 0x00000003U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000001U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100B00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000418U); + mmio_write_32(GPIO_INOUTSEL3, 0x00002000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000040U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000208U); + mmio_write_32(GPIO_INOUTSEL6, 0x00013F00U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000003U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h new file mode 100644 index 0000000..5efce45 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_G2H_H +#define PFC_INIT_G2H_H + +void pfc_init_g2h(void); + +#endif /* PFC_INIT_G2H_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c new file mode 100644 index 0000000..f76b83f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c @@ -0,0 +1,1300 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ + +#include + +#include "pfc_init_g2m.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +/* SCIF3 Registers for Dummy write */ +#define SCIF3_BASE (0xE6C50000U) +#define SCIF3_SCFCR (SCIF3_BASE + 0x0018U) +#define SCIF3_SCFDR (SCIF3_BASE + 0x001CU) +#define SCFCR_DATA (0x0000U) + +/* Realtime module stop control */ +#define CPG_BASE (0xE6150000U) +#define CPG_SCMSTPCR0 (CPG_BASE + 0x0B20U) +#define CPG_MSTPSR0 (CPG_BASE + 0x0030U) +#define SCMSTPCR0_RTDMAC (0x00200000U) + +/* RT-DMAC Registers */ +#define RTDMAC_CH (0U) /* choose 0 to 15 */ + +#define RTDMAC_BASE (0xFFC10000U) +#define RTDMAC_RDMOR (RTDMAC_BASE + 0x0060U) +#define RTDMAC_RDMCHCLR (RTDMAC_BASE + 0x0080U) +#define RTDMAC_RDMSAR(x) (RTDMAC_BASE + 0x8000U + (0x80U * (x))) +#define RTDMAC_RDMDAR(x) (RTDMAC_BASE + 0x8004U + (0x80U * (x))) +#define RTDMAC_RDMTCR(x) (RTDMAC_BASE + 0x8008U + (0x80U * (x))) +#define RTDMAC_RDMCHCR(x) (RTDMAC_BASE + 0x800CU + (0x80U * (x))) +#define RTDMAC_RDMCHCRB(x) (RTDMAC_BASE + 0x801CU + (0x80U * (x))) +#define RTDMAC_RDMDPBASE(x) (RTDMAC_BASE + 0x8050U + (0x80U * (x))) +#define RTDMAC_DESC_BASE (RTDMAC_BASE + 0xA000U) +#define RTDMAC_DESC_RDMSAR (RTDMAC_DESC_BASE + 0x0000U) +#define RTDMAC_DESC_RDMDAR (RTDMAC_DESC_BASE + 0x0004U) +#define RTDMAC_DESC_RDMTCR (RTDMAC_DESC_BASE + 0x0008U) + +#define RDMOR_DME (0x0001U) /* DMA Master Enable */ +#define RDMCHCR_DPM_INFINITE (0x30000000U) /* Infinite repeat mode */ +#define RDMCHCR_RPT_TCR (0x02000000U) /* enable to update TCR */ +#define RDMCHCR_TS_2 (0x00000008U) /* Word(2byte) units transfer */ +#define RDMCHCR_RS_AUTO (0x00000400U) /* Auto request */ +#define RDMCHCR_DE (0x00000001U) /* DMA Enable */ +#define RDMCHCRB_DRST (0x00008000U) /* Descriptor reset */ +#define RDMCHCRB_SLM_256 (0x00000080U) /* once in 256 clock cycle */ +#define RDMDPBASE_SEL_EXT (0x00000001U) /* External memory use */ + +static void start_rtdma0_descriptor(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); + reg &= (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if (reg == (PRR_PRODUCT_M3_CUT10)) { + /* Enable clock supply to RTDMAC. */ + mstpcr_write(CPG_SCMSTPCR0, CPG_MSTPSR0, SCMSTPCR0_RTDMAC); + + /* Initialize ch0, Reset Descriptor */ + mmio_write_32(RTDMAC_RDMCHCLR, BIT(RTDMAC_CH)); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_DRST); + + /* Enable DMA */ + mmio_write_16(RTDMAC_RDMOR, RDMOR_DME); + + /* Set first transfer */ + mmio_write_32(RTDMAC_RDMSAR(RTDMAC_CH), RCAR_PRR); + mmio_write_32(RTDMAC_RDMDAR(RTDMAC_CH), SCIF3_SCFDR); + mmio_write_32(RTDMAC_RDMTCR(RTDMAC_CH), 0x00000001U); + + /* Set descriptor */ + mmio_write_32(RTDMAC_DESC_RDMSAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMDAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMTCR, 0x00200000U); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_SLM_256); + mmio_write_32(RTDMAC_RDMDPBASE(RTDMAC_CH), RTDMAC_DESC_BASE + | RDMDPBASE_SEL_EXT); + + /* Set transfer parameter, Start transfer */ + mmio_write_32(RTDMAC_RDMCHCR(RTDMAC_CH), RDMCHCR_DPM_INFINITE + | RDMCHCR_RPT_TCR + | RDMCHCR_TS_2 + | RDMCHCR_RS_AUTO + | RDMCHCR_DE); + } +} + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + uint32_t prr; + + prr = mmio_read_32(RCAR_PRR); + prr &= (PRR_PRODUCT_MASK | PRR_CUT_MASK); + + mmio_write_32(PFC_PMMR, ~data); + if (prr == (PRR_PRODUCT_M3_CUT10)) { + mmio_write_16(SCIF3_SCFCR, SCFCR_DATA); /* Dummy write */ + } + mmio_write_32((uintptr_t)addr, data); + if (prr == (PRR_PRODUCT_M3_CUT10)) { + mmio_write_16(SCIF3_SCFCR, SCFCR_DATA); /* Dummy write */ + } +} + +void pfc_init_g2m(void) +{ + uint32_t reg; + + /* + * PFC write access problem seen on older SoC's. Added a workaround + * in RT-DMAC for fixing the same. + */ + start_rtdma0_descriptor(); + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_B + | MOD_SEL2_I2C_3_B + | MOD_SEL2_I2C_0_B + | MOD_SEL2_FM_A + | MOD_SEL2_SCIF5_A + | MOD_SEL2_I2C6_A + | MOD_SEL2_NDF_A + | MOD_SEL2_SSI2_A + | MOD_SEL2_SSI9_A + | MOD_SEL2_TIMER_TMU2_A + | MOD_SEL2_ADG_B_A + | MOD_SEL2_ADG_C_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8 + | GPSR0_D7 + | GPSR0_D6 + | GPSR0_D5 + | GPSR0_D4 + | GPSR0_D3 + | GPSR0_D2 + | GPSR0_D0); + pfc_reg_write(PFC_GPSR1, GPSR1_CLKOUT + | GPSR1_EX_WAIT0_A + | GPSR1_WE1 + | GPSR1_RD + | GPSR1_RD_WR + | GPSR1_CS0 + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DS + | GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT5 + | GPSR4_SD3_DAT4 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_RXD + | GPSR5_MSIOF0_TXD + | GPSR5_MSIOF0_SYNC + | GPSR5_MSIOF0_SCK + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(7) + | DRVCTRL13_SD0_CMD(7) + | DRVCTRL13_SD0_DAT0(7) + | DRVCTRL13_SD0_DAT1(7) + | DRVCTRL13_SD0_DAT2(7) + | DRVCTRL13_SD0_DAT3(7)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(7) + | DRVCTRL15_SD3_CMD(7) + | DRVCTRL15_SD3_DAT0(7)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(7) + | DRVCTRL16_SD3_DAT2(7) + | DRVCTRL16_SD3_DAT3(7) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300EFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000001U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + mmio_write_32(GPIO_OUTDT6, 0x00003800U); + mmio_write_32(GPIO_OUTDT7, 0x00000003U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000001U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100B00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000418U); + mmio_write_32(GPIO_INOUTSEL3, 0x00002000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000040U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000208U); + mmio_write_32(GPIO_INOUTSEL6, 0x00013F00U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000003U); + +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h new file mode 100644 index 0000000..3315cd6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_G2M_H +#define PFC_INIT_G2M_H + +void pfc_init_g2m(void); + +#endif /* PFC_INIT_G2M_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c new file mode 100644 index 0000000..c951e0a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c @@ -0,0 +1,1306 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "pfc_init_g2n.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_g2n(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, + MOD_SEL0_MSIOF3_A | + MOD_SEL0_MSIOF2_A | + MOD_SEL0_MSIOF1_A | + MOD_SEL0_LBSC_A | + MOD_SEL0_IEBUS_A | + MOD_SEL0_I2C2_A | + MOD_SEL0_I2C1_A | + MOD_SEL0_HSCIF4_A | + MOD_SEL0_HSCIF3_A | + MOD_SEL0_HSCIF1_A | + MOD_SEL0_FSO_A | + MOD_SEL0_HSCIF2_A | + MOD_SEL0_ETHERAVB_A | + MOD_SEL0_DRIF3_A | + MOD_SEL0_DRIF2_A | + MOD_SEL0_DRIF1_A | + MOD_SEL0_DRIF0_A | + MOD_SEL0_CANFD0_A | + MOD_SEL0_ADG_A_A); + + pfc_reg_write(PFC_MOD_SEL1, + MOD_SEL1_TSIF1_A | + MOD_SEL1_TSIF0_A | + MOD_SEL1_TIMER_TMU_A | + MOD_SEL1_SSP1_1_A | + MOD_SEL1_SSP1_0_A | + MOD_SEL1_SSI_A | + MOD_SEL1_SPEED_PULSE_IF_A | + MOD_SEL1_SIMCARD_A | + MOD_SEL1_SDHI2_A | + MOD_SEL1_SCIF4_A | + MOD_SEL1_SCIF3_A | + MOD_SEL1_SCIF2_A | + MOD_SEL1_SCIF1_A | + MOD_SEL1_SCIF_A | + MOD_SEL1_REMOCON_A | + MOD_SEL1_RCAN0_A | + MOD_SEL1_PWM6_A | + MOD_SEL1_PWM5_A | + MOD_SEL1_PWM4_A | + MOD_SEL1_PWM3_A | + MOD_SEL1_PWM2_A | + MOD_SEL1_PWM1_A); + + pfc_reg_write(PFC_MOD_SEL2, + MOD_SEL2_I2C_5_B | + MOD_SEL2_I2C_3_B | + MOD_SEL2_I2C_0_B | + MOD_SEL2_FM_A | + MOD_SEL2_SCIF5_A | + MOD_SEL2_I2C6_A | + MOD_SEL2_NDF_A | + MOD_SEL2_SSI2_A | + MOD_SEL2_SSI9_A | + MOD_SEL2_TIMER_TMU2_A | + MOD_SEL2_ADG_B_A | + MOD_SEL2_ADG_C_A | + MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR1, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(3) | + IPSR_8_FUNC(3) | + IPSR_4_FUNC(3) | + IPSR_0_FUNC(3)); + + pfc_reg_write(PFC_IPSR2, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR3, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR4, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR5, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR6, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR7, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR8, + IPSR_28_FUNC(1) | + IPSR_24_FUNC(1) | + IPSR_20_FUNC(1) | + IPSR_16_FUNC(1) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR9, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR10, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR11, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(4) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR12, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(4) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR13, + IPSR_28_FUNC(8) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(3) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR14, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(3) | + IPSR_0_FUNC(8)); + + pfc_reg_write(PFC_IPSR15, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR16, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR17, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(1) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) | IPSR_0_FUNC(0)); + + /* initialize GPIO/peripheral function select */ + pfc_reg_write(PFC_GPSR0, + GPSR0_D15 | + GPSR0_D14 | + GPSR0_D13 | + GPSR0_D12 | + GPSR0_D11 | + GPSR0_D10 | + GPSR0_D9 | + GPSR0_D8 | + GPSR0_D7 | + GPSR0_D6 | + GPSR0_D5 | + GPSR0_D4 | + GPSR0_D3 | + GPSR0_D2 | + GPSR0_D0); + + pfc_reg_write(PFC_GPSR1, + GPSR1_CLKOUT | + GPSR1_EX_WAIT0_A | + GPSR1_WE1 | + GPSR1_RD | + GPSR1_RD_WR | + GPSR1_CS0 | + GPSR1_A19 | + GPSR1_A18 | + GPSR1_A17 | + GPSR1_A16 | + GPSR1_A15 | + GPSR1_A14 | + GPSR1_A13 | + GPSR1_A12 | + GPSR1_A7 | + GPSR1_A6 | + GPSR1_A5 | + GPSR1_A4 | + GPSR1_A3 | + GPSR1_A2 | + GPSR1_A1 | + GPSR1_A0); + + pfc_reg_write(PFC_GPSR2, + GPSR2_AVB_AVTP_CAPTURE_A | + GPSR2_AVB_AVTP_MATCH_A | + GPSR2_AVB_LINK | + GPSR2_AVB_PHY_INT | + GPSR2_AVB_MDC | + GPSR2_PWM2_A | + GPSR2_PWM1_A | + GPSR2_IRQ4 | + GPSR2_IRQ3 | + GPSR2_IRQ2 | + GPSR2_IRQ1 | + GPSR2_IRQ0); + + pfc_reg_write(PFC_GPSR3, + GPSR3_SD0_CD | + GPSR3_SD1_DAT3 | + GPSR3_SD1_DAT2 | + GPSR3_SD1_DAT1 | + GPSR3_SD1_DAT0 | + GPSR3_SD0_DAT3 | + GPSR3_SD0_DAT2 | + GPSR3_SD0_DAT1 | + GPSR3_SD0_DAT0 | + GPSR3_SD0_CMD | + GPSR3_SD0_CLK); + + pfc_reg_write(PFC_GPSR4, + GPSR4_SD3_DS | + GPSR4_SD3_DAT7 | + GPSR4_SD3_DAT6 | + GPSR4_SD3_DAT5 | + GPSR4_SD3_DAT4 | + GPSR4_SD3_DAT3 | + GPSR4_SD3_DAT2 | + GPSR4_SD3_DAT1 | + GPSR4_SD3_DAT0 | + GPSR4_SD3_CMD | + GPSR4_SD3_CLK | + GPSR4_SD2_DAT3 | + GPSR4_SD2_DAT2 | + GPSR4_SD2_DAT1 | + GPSR4_SD2_DAT0 | + GPSR4_SD2_CMD | + GPSR4_SD2_CLK); + + pfc_reg_write(PFC_GPSR5, + GPSR5_MSIOF0_RXD | + GPSR5_MSIOF0_TXD | + GPSR5_MSIOF0_SYNC | + GPSR5_MSIOF0_SCK | + GPSR5_RX2_A | + GPSR5_TX2_A | + GPSR5_RTS1 | + GPSR5_CTS1 | + GPSR5_TX1_A | + GPSR5_RX1_A | + GPSR5_RTS0 | + GPSR5_SCK0); + + pfc_reg_write(PFC_GPSR6, + GPSR6_AUDIO_CLKB_B | + GPSR6_AUDIO_CLKA_A | + GPSR6_SSI_WS6 | + GPSR6_SSI_SCK6 | + GPSR6_SSI_SDATA4 | + GPSR6_SSI_WS4 | + GPSR6_SSI_SCK4 | + GPSR6_SSI_SDATA1_A | + GPSR6_SSI_SDATA0 | + GPSR6_SSI_WS0129 | + GPSR6_SSI_SCK0129); + + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, + POC_SD0_DAT3_33V | + POC_SD0_DAT2_33V | + POC_SD0_DAT1_33V | + POC_SD0_DAT0_33V | + POC_SD0_CMD_33V | + POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = (reg & DRVCTRL0_MASK) | + DRVCTRL0_QSPI0_SPCLK(3) | + DRVCTRL0_QSPI0_MOSI_IO0(3) | + DRVCTRL0_QSPI0_MISO_IO1(3) | + DRVCTRL0_QSPI0_IO2(3) | + DRVCTRL0_QSPI0_IO3(3) | + DRVCTRL0_QSPI0_SSL(3) | + DRVCTRL0_QSPI1_SPCLK(3) | + DRVCTRL0_QSPI1_MOSI_IO0(3); + pfc_reg_write(PFC_DRVCTRL0, reg); + + reg = mmio_read_32(PFC_DRVCTRL1); + reg = (reg & DRVCTRL1_MASK) | + DRVCTRL1_QSPI1_MISO_IO1(3) | + DRVCTRL1_QSPI1_IO2(3) | + DRVCTRL1_QSPI1_IO3(3) | + DRVCTRL1_QSPI1_SS(3) | + DRVCTRL1_RPC_INT(3) | + DRVCTRL1_RPC_WP(3) | + DRVCTRL1_RPC_RESET(3) | + DRVCTRL1_AVB_RX_CTL(7); + pfc_reg_write(PFC_DRVCTRL1, reg); + + reg = mmio_read_32(PFC_DRVCTRL2); + reg = (reg & DRVCTRL2_MASK) | + DRVCTRL2_AVB_RXC(7) | + DRVCTRL2_AVB_RD0(7) | + DRVCTRL2_AVB_RD1(7) | + DRVCTRL2_AVB_RD2(7) | + DRVCTRL2_AVB_RD3(7) | + DRVCTRL2_AVB_TX_CTL(3) | + DRVCTRL2_AVB_TXC(3) | + DRVCTRL2_AVB_TD0(3); + pfc_reg_write(PFC_DRVCTRL2, reg); + + reg = mmio_read_32(PFC_DRVCTRL3); + reg = (reg & DRVCTRL3_MASK) | + DRVCTRL3_AVB_TD1(3) | + DRVCTRL3_AVB_TD2(3) | + DRVCTRL3_AVB_TD3(3) | + DRVCTRL3_AVB_TXCREFCLK(7) | + DRVCTRL3_AVB_MDIO(7) | + DRVCTRL3_AVB_MDC(7) | + DRVCTRL3_AVB_MAGIC(7) | + DRVCTRL3_AVB_PHY_INT(7); + pfc_reg_write(PFC_DRVCTRL3, reg); + + reg = mmio_read_32(PFC_DRVCTRL4); + reg = (reg & DRVCTRL4_MASK) | + DRVCTRL4_AVB_LINK(7) | + DRVCTRL4_AVB_AVTP_MATCH(7) | + DRVCTRL4_AVB_AVTP_CAPTURE(7) | + DRVCTRL4_IRQ0(7) | + DRVCTRL4_IRQ1(7) | + DRVCTRL4_IRQ2(7) | + DRVCTRL4_IRQ3(7) | + DRVCTRL4_IRQ4(7); + pfc_reg_write(PFC_DRVCTRL4, reg); + + reg = mmio_read_32(PFC_DRVCTRL5); + reg = (reg & DRVCTRL5_MASK) | + DRVCTRL5_IRQ5(7) | + DRVCTRL5_PWM0(7) | + DRVCTRL5_PWM1(7) | + DRVCTRL5_PWM2(7) | + DRVCTRL5_A0(3) | + DRVCTRL5_A1(3) | + DRVCTRL5_A2(3) | + DRVCTRL5_A3(3); + pfc_reg_write(PFC_DRVCTRL5, reg); + + reg = mmio_read_32(PFC_DRVCTRL6); + reg = (reg & DRVCTRL6_MASK) | + DRVCTRL6_A4(3) | + DRVCTRL6_A5(3) | + DRVCTRL6_A6(3) | + DRVCTRL6_A7(3) | + DRVCTRL6_A8(7) | + DRVCTRL6_A9(7) | + DRVCTRL6_A10(7) | + DRVCTRL6_A11(7); + pfc_reg_write(PFC_DRVCTRL6, reg); + + reg = mmio_read_32(PFC_DRVCTRL7); + reg = (reg & DRVCTRL7_MASK) | + DRVCTRL7_A12(3) | + DRVCTRL7_A13(3) | + DRVCTRL7_A14(3) | + DRVCTRL7_A15(3) | + DRVCTRL7_A16(3) | + DRVCTRL7_A17(3) | + DRVCTRL7_A18(3) | + DRVCTRL7_A19(3); + pfc_reg_write(PFC_DRVCTRL7, reg); + + reg = mmio_read_32(PFC_DRVCTRL8); + reg = (reg & DRVCTRL8_MASK) | + DRVCTRL8_CLKOUT(7) | + DRVCTRL8_CS0(7) | + DRVCTRL8_CS1_A2(7) | + DRVCTRL8_BS(7) | + DRVCTRL8_RD(7) | + DRVCTRL8_RD_W(7) | + DRVCTRL8_WE0(7) | + DRVCTRL8_WE1(7); + pfc_reg_write(PFC_DRVCTRL8, reg); + + reg = mmio_read_32(PFC_DRVCTRL9); + reg = (reg & DRVCTRL9_MASK) | + DRVCTRL9_EX_WAIT0(7) | + DRVCTRL9_PRESETOU(7) | + DRVCTRL9_D0(7) | + DRVCTRL9_D1(7) | + DRVCTRL9_D2(7) | + DRVCTRL9_D3(7) | + DRVCTRL9_D4(7) | + DRVCTRL9_D5(7); + pfc_reg_write(PFC_DRVCTRL9, reg); + + reg = mmio_read_32(PFC_DRVCTRL10); + reg = (reg & DRVCTRL10_MASK) | + DRVCTRL10_D6(7) | + DRVCTRL10_D7(7) | + DRVCTRL10_D8(3) | + DRVCTRL10_D9(3) | + DRVCTRL10_D10(3) | + DRVCTRL10_D11(3) | + DRVCTRL10_D12(3) | + DRVCTRL10_D13(3); + pfc_reg_write(PFC_DRVCTRL10, reg); + + reg = mmio_read_32(PFC_DRVCTRL11); + reg = (reg & DRVCTRL11_MASK) | + DRVCTRL11_D14(3) | + DRVCTRL11_D15(3) | + DRVCTRL11_AVS1(7) | + DRVCTRL11_AVS2(7) | + DRVCTRL11_GP7_02(7) | + DRVCTRL11_GP7_03(7) | + DRVCTRL11_DU_DOTCLKIN0(3) | + DRVCTRL11_DU_DOTCLKIN1(3); + pfc_reg_write(PFC_DRVCTRL11, reg); + + reg = mmio_read_32(PFC_DRVCTRL12); + reg = (reg & DRVCTRL12_MASK) | + DRVCTRL12_DU_DOTCLKIN2(3) | + DRVCTRL12_DU_DOTCLKIN3(3) | + DRVCTRL12_DU_FSCLKST(3) | + DRVCTRL12_DU_TMS(3); + pfc_reg_write(PFC_DRVCTRL12, reg); + + reg = mmio_read_32(PFC_DRVCTRL13); + reg = (reg & DRVCTRL13_MASK) | + DRVCTRL13_TDO(3) | + DRVCTRL13_ASEBRK(3) | + DRVCTRL13_SD0_CLK(7) | + DRVCTRL13_SD0_CMD(7) | + DRVCTRL13_SD0_DAT0(7) | + DRVCTRL13_SD0_DAT1(7) | + DRVCTRL13_SD0_DAT2(7) | + DRVCTRL13_SD0_DAT3(7); + pfc_reg_write(PFC_DRVCTRL13, reg); + + reg = mmio_read_32(PFC_DRVCTRL14); + reg = (reg & DRVCTRL14_MASK) | + DRVCTRL14_SD1_CLK(7) | + DRVCTRL14_SD1_CMD(7) | + DRVCTRL14_SD1_DAT0(5) | + DRVCTRL14_SD1_DAT1(5) | + DRVCTRL14_SD1_DAT2(5) | + DRVCTRL14_SD1_DAT3(5) | + DRVCTRL14_SD2_CLK(5) | + DRVCTRL14_SD2_CMD(5); + pfc_reg_write(PFC_DRVCTRL14, reg); + + reg = mmio_read_32(PFC_DRVCTRL15); + reg = (reg & DRVCTRL15_MASK) | + DRVCTRL15_SD2_DAT0(5) | + DRVCTRL15_SD2_DAT1(5) | + DRVCTRL15_SD2_DAT2(5) | + DRVCTRL15_SD2_DAT3(5) | + DRVCTRL15_SD2_DS(5) | + DRVCTRL15_SD3_CLK(7) | + DRVCTRL15_SD3_CMD(7) | + DRVCTRL15_SD3_DAT0(7); + pfc_reg_write(PFC_DRVCTRL15, reg); + + reg = mmio_read_32(PFC_DRVCTRL16); + reg = (reg & DRVCTRL16_MASK) | + DRVCTRL16_SD3_DAT1(7) | + DRVCTRL16_SD3_DAT2(7) | + DRVCTRL16_SD3_DAT3(7) | + DRVCTRL16_SD3_DAT4(7) | + DRVCTRL16_SD3_DAT5(7) | + DRVCTRL16_SD3_DAT6(7) | + DRVCTRL16_SD3_DAT7(7) | + DRVCTRL16_SD3_DS(7); + pfc_reg_write(PFC_DRVCTRL16, reg); + + reg = mmio_read_32(PFC_DRVCTRL17); + reg = (reg & DRVCTRL17_MASK) | + DRVCTRL17_SD0_CD(7) | + DRVCTRL17_SD0_WP(7) | + DRVCTRL17_SD1_CD(7) | + DRVCTRL17_SD1_WP(7) | + DRVCTRL17_SCK0(7) | + DRVCTRL17_RX0(7) | + DRVCTRL17_TX0(7) | + DRVCTRL17_CTS0(7); + pfc_reg_write(PFC_DRVCTRL17, reg); + + reg = mmio_read_32(PFC_DRVCTRL18); + reg = (reg & DRVCTRL18_MASK) | + DRVCTRL18_RTS0_TANS(7) | + DRVCTRL18_RX1(7) | + DRVCTRL18_TX1(7) | + DRVCTRL18_CTS1(7) | + DRVCTRL18_RTS1_TANS(7) | + DRVCTRL18_SCK2(7) | + DRVCTRL18_TX2(7) | + DRVCTRL18_RX2(7); + pfc_reg_write(PFC_DRVCTRL18, reg); + + reg = mmio_read_32(PFC_DRVCTRL19); + reg = (reg & DRVCTRL19_MASK) | + DRVCTRL19_HSCK0(7) | + DRVCTRL19_HRX0(7) | + DRVCTRL19_HTX0(7) | + DRVCTRL19_HCTS0(7) | + DRVCTRL19_HRTS0(7) | + DRVCTRL19_MSIOF0_SCK(7) | + DRVCTRL19_MSIOF0_SYNC(7) | + DRVCTRL19_MSIOF0_SS1(7); + pfc_reg_write(PFC_DRVCTRL19, reg); + + reg = mmio_read_32(PFC_DRVCTRL20); + reg = (reg & DRVCTRL20_MASK) | + DRVCTRL20_MSIOF0_TXD(7) | + DRVCTRL20_MSIOF0_SS2(7) | + DRVCTRL20_MSIOF0_RXD(7) | + DRVCTRL20_MLB_CLK(7) | + DRVCTRL20_MLB_SIG(7) | + DRVCTRL20_MLB_DAT(7) | + DRVCTRL20_MLB_REF(7) | + DRVCTRL20_SSI_SCK0129(7); + pfc_reg_write(PFC_DRVCTRL20, reg); + + reg = mmio_read_32(PFC_DRVCTRL21); + reg = (reg & DRVCTRL21_MASK) | + DRVCTRL21_SSI_WS0129(7) | + DRVCTRL21_SSI_SDATA0(7) | + DRVCTRL21_SSI_SDATA1(7) | + DRVCTRL21_SSI_SDATA2(7) | + DRVCTRL21_SSI_SCK34(7) | + DRVCTRL21_SSI_WS34(7) | + DRVCTRL21_SSI_SDATA3(7) | + DRVCTRL21_SSI_SCK4(7); + pfc_reg_write(PFC_DRVCTRL21, reg); + + reg = mmio_read_32(PFC_DRVCTRL22); + reg = (reg & DRVCTRL22_MASK) | + DRVCTRL22_SSI_WS4(7) | + DRVCTRL22_SSI_SDATA4(7) | + DRVCTRL22_SSI_SCK5(7) | + DRVCTRL22_SSI_WS5(7) | + DRVCTRL22_SSI_SDATA5(7) | + DRVCTRL22_SSI_SCK6(7) | + DRVCTRL22_SSI_WS6(7) | + DRVCTRL22_SSI_SDATA6(7); + pfc_reg_write(PFC_DRVCTRL22, reg); + + reg = mmio_read_32(PFC_DRVCTRL23); + reg = (reg & DRVCTRL23_MASK) | + DRVCTRL23_SSI_SCK78(7) | + DRVCTRL23_SSI_WS78(7) | + DRVCTRL23_SSI_SDATA7(7) | + DRVCTRL23_SSI_SDATA8(7) | + DRVCTRL23_SSI_SDATA9(7) | + DRVCTRL23_AUDIO_CLKA(7) | + DRVCTRL23_AUDIO_CLKB(7) | + DRVCTRL23_USB0_PWEN(7); + + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = (reg & DRVCTRL24_MASK) | + DRVCTRL24_USB0_OVC(7) | + DRVCTRL24_USB1_PWEN(7) | + DRVCTRL24_USB1_OVC(7) | + DRVCTRL24_USB30_PWEN(7) | + DRVCTRL24_USB30_OVC(7) | + DRVCTRL24_USB31_PWEN(7) | + DRVCTRL24_USB31_OVC(7); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300EFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000001U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + mmio_write_32(GPIO_OUTDT6, 0x00003800U); + mmio_write_32(GPIO_OUTDT7, 0x00000003U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000001U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100B00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000418U); + mmio_write_32(GPIO_INOUTSEL3, 0x00002000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000040U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000208U); + mmio_write_32(GPIO_INOUTSEL6, 0x00013F00U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000003U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h new file mode 100644 index 0000000..f0616b6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_G2N_H +#define PFC_INIT_G2N_H + +void pfc_init_g2n(void); + +#endif /* PFC_INIT_G2N_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc.mk b/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc.mk new file mode 100644 index 0000000..15d0e8d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc.mk @@ -0,0 +1,41 @@ +# +# Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${RCAR_LSI},${RCAR_AUTO}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c + BL2_SOURCES += drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c + BL2_SOURCES += drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c + BL2_SOURCES += drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c + +else ifdef RCAR_LSI_CUT_COMPAT + ifeq (${RCAR_LSI},${RZ_G2M}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c + endif + ifeq (${RCAR_LSI},${RZ_G2H}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c + endif + ifeq (${RCAR_LSI},${RZ_G2N}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c + endif + ifeq (${RCAR_LSI},${RZ_G2E}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c + endif +else + ifeq (${RCAR_LSI},${RZ_G2M}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c + endif + ifeq (${RCAR_LSI},${RZ_G2H}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c + endif + ifeq (${RCAR_LSI},${RZ_G2N}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c + endif + ifeq (${RCAR_LSI},${RZ_G2E}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c + endif +endif + +BL2_SOURCES += drivers/renesas/rzg/pfc/pfc_init.c diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c new file mode 100644 index 0000000..762450c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include + +#if RCAR_LSI == RCAR_AUTO +#include "G2E/pfc_init_g2e.h" +#include "G2H/pfc_init_g2h.h" +#include "G2M/pfc_init_g2m.h" +#include "G2N/pfc_init_g2n.h" +#endif /* RCAR_LSI == RCAR_AUTO */ +#if (RCAR_LSI == RZ_G2E) +#include "G2E/pfc_init_g2e.h" +#endif /* RCAR_LSI == RZ_G2N */ +#if (RCAR_LSI == RZ_G2H) +#include "G2H/pfc_init_g2h.h" +#endif /* RCAR_LSI == RZ_G2H */ +#if (RCAR_LSI == RZ_G2M) +#include "G2M/pfc_init_g2m.h" +#endif /* RCAR_LSI == RZ_G2M */ +#if (RCAR_LSI == RZ_G2N) +#include "G2N/pfc_init_g2n.h" +#endif /* RCAR_LSI == RZ_G2N */ +#include "rcar_def.h" + +#define PRR_PRODUCT_ERR(reg) \ + do { \ + ERROR("LSI Product ID(PRR=0x%x) PFC init not supported.\n", \ + reg); \ + panic(); \ + } while (0) + +#define PRR_CUT_ERR(reg) \ + do { \ + ERROR("LSI Cut ID(PRR=0x%x) PFC init not supported.\n", \ + reg); \ + panic();\ + } while (0) + +void rzg_pfc_init(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); +#if RCAR_LSI == RCAR_AUTO + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_M3: + pfc_init_g2m(); + break; + case PRR_PRODUCT_H3: + pfc_init_g2h(); + break; + case PRR_PRODUCT_M3N: + pfc_init_g2n(); + break; + case PRR_PRODUCT_E3: + pfc_init_g2e(); + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } + +#elif RCAR_LSI_CUT_COMPAT /* RCAR_LSI == RCAR_AUTO */ + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_M3: +#if RCAR_LSI != RZ_G2M + PRR_PRODUCT_ERR(reg); +#else /* RCAR_LSI != RZ_G2M */ + pfc_init_g2m(); +#endif /* RCAR_LSI != RZ_G2M */ + break; + case PRR_PRODUCT_H3: +#if (RCAR_LSI != RZ_G2H) + PRR_PRODUCT_ERR(reg); +#else /* RCAR_LSI != RZ_G2H */ + pfc_init_g2h(); +#endif /* RCAR_LSI != RZ_G2H */ + break; + case PRR_PRODUCT_M3N: +#if RCAR_LSI != RZ_G2N + PRR_PRODUCT_ERR(reg); +#else + pfc_init_g2n(); +#endif /* RCAR_LSI != RZ_G2N */ + break; + case PRR_PRODUCT_E3: +#if RCAR_LSI != RZ_G2E + PRR_PRODUCT_ERR(reg); +#else + pfc_init_g2e(); +#endif + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } + +#else /* RCAR_LSI == RCAR_AUTO */ +#if (RCAR_LSI == RZ_G2M) + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_M3) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_m3(); +#elif (RCAR_LSI == RZ_G2H) + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_H3) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_g2h(); +#elif (RCAR_LSI == RZ_G2N) /* G2N */ + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_M3N) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_g2n(); +#elif (RCAR_LSI == RZ_G2E) + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_E3) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_g2e(); +#else /* RCAR_LSI == RZ_G2M */ +#error "Don't have PFC initialize routine(unknown)." +#endif /* RCAR_LSI == RZ_G2M */ +#endif /* RCAR_LSI == RCAR_AUTO */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c new file mode 100644 index 0000000..14ccc21 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "qos_init_g2e_v10.h" +#include "../qos_common.h" +#include "../qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.05" + +#define REF_ARS_ARBSTOPCYCLE_G2E (((SL_INIT_SSLOTCLK_G2E) - 5U) << 16U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2e_v10_mstat390.h" +#else +#include "qos_init_g2e_v10_mstat780.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ + +static const struct rcar_gen3_dbsc_qos_settings g2e_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2e_v10(void) +{ + rzg_qos_dbsc_setting(g2e_qos, ARRAY_SIZE(g2e_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_RZ_G2E +#error "Don't set DRAM Split 4ch(G2E)" +#else + ERROR("DRAM Split 4ch not supported.(G2E)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) +#if RCAR_LSI == RCAR_RZ_G2E +#error "Don't set DRAM Split 2ch(G2E)" +#else + ERROR("DRAM Split 2ch not supported.(G2E)"); + panic(); +#endif +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 7.8 usec\n"); +#endif + + mmio_write_32(QOSCTRL_RAS, 0x00000020U); + mmio_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x00100804U); + mmio_write_32(QOSCTRL_FSS, 0x0000000AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_EARLYR, 0x00000000U); + mmio_write_32(QOSCTRL_RACNT0, 0x00010003U); + + mmio_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | + SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_G2E); + mmio_write_32(QOSCTRL_REF_ARS, REF_ARS_ARBSTOPCYCLE_G2E); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h new file mode 100644 index 0000000..d27de1b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2E_V10_H +#define QOS_INIT_G2E_V10_H + +void qos_init_g2e_v10(void); + +#endif /* QOS_INIT_G2E_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h new file mode 100644 index 0000000..63b08c4 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2E_V10_MSTAT390_H +#define QOS_INIT_G2E_V10_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008620000FFFFUL, + /* 0x0038, */ 0x001008620000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001415260000FFFFUL, + /* 0x0060, */ 0x001415260000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414930000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08380000FFFFUL, + /* 0x00a8, */ 0x000C04110000FFFFUL, + /* 0x00b0, */ 0x000C04150000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08380000FFFFUL, + /* 0x00c8, */ 0x000C04110000FFFFUL, + /* 0x00d0, */ 0x000C04150000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x000C084F0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x000C21E40000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001008530000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00100C960000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001008530000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0010042A0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00101D8D0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001008530000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02a0, */ 0x000C04090000FFFFUL, + /* 0x02a8, */ 0x000C04090000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04090000FFFFUL, + /* 0x02d8, */ 0x000C04090000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005F03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060005FFFC01UL, + /* 0x01c8, */ 0x0021060005FFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0011010005F79801UL, + /* 0x0220, */ 0x0011010005F79801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010005F79801UL, + /* 0x0238, */ 0x0011010005F79801UL, + /* 0x0240, */ 0x0012010005F79801UL, + /* 0x0248, */ 0x0011010005F79801UL, + /* 0x0250, */ 0x0012010005F79801UL, + /* 0x0258, */ 0x0011010005F79801UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060005FFFC01UL, + /* 0x02f8, */ 0x0011060005FFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001005F03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060005FFFC01UL, + /* 0x0360, */ 0x0012060005FFFC01UL, + /* 0x0368, */ 0x0012001005F03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001005F03401UL, +}; +#endif /* QOS_INIT_G2E_V10_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h new file mode 100644 index 0000000..3b888ea --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2E_V10_MSTAT780_H +#define QOS_INIT_G2E_V10_MSTAT780_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001010C40000FFFFUL, + /* 0x0038, */ 0x001010C40000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00142A4B0000FFFFUL, + /* 0x0060, */ 0x00142A4B0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001429260000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C10700000FFFFUL, + /* 0x00a8, */ 0x000C08210000FFFFUL, + /* 0x00b0, */ 0x000C082A0000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C10700000FFFFUL, + /* 0x00c8, */ 0x000C08210000FFFFUL, + /* 0x00d0, */ 0x000C082A0000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x00102CAF0000FFFFUL, + /* 0x00f8, */ 0x000C0C9D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100CAF0000FFFFUL, + /* 0x0118, */ 0x000C43C80000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100CA50000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010152C0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100CA50000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008530000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001037190000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100CA50000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04040000FFFFUL, + /* 0x01f0, */ 0x000C08110000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04110000FFFFUL, + /* 0x0210, */ 0x000C08110000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C18530000FFFFUL, + /* 0x0268, */ 0x00141C070000FFFFUL, + /* 0x0270, */ 0x001404040000FFFFUL, + /* 0x0278, */ 0x000C0C210000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x00141C070000FFFFUL, + /* 0x0298, */ 0x001404040000FFFFUL, + /* 0x02a0, */ 0x000C04110000FFFFUL, + /* 0x02a8, */ 0x000C04110000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x000C04040000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04110000FFFFUL, + /* 0x02d8, */ 0x000C04110000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x000C04040000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04040000FFFFUL, + /* 0x0378, */ 0x000C04040000FFFFUL, + /* 0x0380, */ 0x000C04110000FFFFUL, + /* 0x0388, */ 0x000C04110000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001002F03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060002FFFC01UL, + /* 0x01c8, */ 0x0021060002FFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010002F3CC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010002F3CC01UL, + /* 0x0218, */ 0x0011010002F3CC01UL, + /* 0x0220, */ 0x0011010002F3CC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010002F3CC01UL, + /* 0x0238, */ 0x0011010002F3CC01UL, + /* 0x0240, */ 0x0012010002F3CC01UL, + /* 0x0248, */ 0x0011010002F3CC01UL, + /* 0x0250, */ 0x0012010002F3CC01UL, + /* 0x0258, */ 0x0011010002F3CC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060002FFFC01UL, + /* 0x02f8, */ 0x0011060002FFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001002F03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060002FFFC01UL, + /* 0x0360, */ 0x0012060002FFFC01UL, + /* 0x0368, */ 0x0012001002F03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001002F03401UL, +}; + +#endif /* QOS_INIT_G2E_V10_MSTAT780_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h new file mode 100644 index 0000000..7bb34aa --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_MSTAT195_H +#define QOS_INIT_G2H_MSTAT195_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001410070000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x0014100D0000FFFFUL, + /* 0x0060, */ 0x0014100D0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x001024090000FFFFUL, + /* 0x00e0, */ 0x00100C090000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x000C100D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x000C1C1B0000FFFFUL, + /* 0x0120, */ 0x000C1C1B0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x00100C0B0000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0010100D0000FFFFUL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x00100C0B0000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x001008060000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x00102C2C0000FFFFUL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x00100C0B0000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200600BDFFC01UL, + /* 0x0008, */ 0x001200600BDFFC01UL, + /* 0x0010, */ 0x001200600BDFFC01UL, + /* 0x0018, */ 0x001200600BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100100BDF2401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100100BDF2401UL, + /* 0x0218, */ 0x001100100BDF2401UL, + /* 0x0220, */ 0x001100100BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100BDF2401UL, + /* 0x0238, */ 0x001100100BDF2401UL, + /* 0x0240, */ 0x001200100BDF2401UL, + /* 0x0248, */ 0x001100100BDF2401UL, + /* 0x0250, */ 0x001200100BDF2401UL, + /* 0x0258, */ 0x001100100BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100600BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100600BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x001100600BDFFC01UL, + /* 0x0328, */ 0x001100600BDFFC01UL, + /* 0x0330, */ 0x001100600BDFFC01UL, + /* 0x0338, */ 0x001100600BDFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x001200100BD0FC01UL, +}; + +#endif /* QOS_INIT_G2H_MSTAT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h new file mode 100644 index 0000000..9696a40 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_MSTAT390_H +#define QOS_INIT_G2H_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x0010100D0000FFFFUL, + /* 0x0040, */ 0x00141C0E0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001408010000FFFFUL, + /* 0x0058, */ 0x00141C190000FFFFUL, + /* 0x0060, */ 0x00141C190000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001408010000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x001044110000FFFFUL, + /* 0x00e0, */ 0x001014110000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x000C1C1A0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x000C38360000FFFFUL, + /* 0x0120, */ 0x000C38360000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x001018150000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x00101C190000FFFFUL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x001018150000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x00100C0B0000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x001058570000FFFFUL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x001018150000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012006005EFFC01UL, + /* 0x0008, */ 0x0012006005EFFC01UL, + /* 0x0010, */ 0x0012006005EFFC01UL, + /* 0x0018, */ 0x0012006005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021006005EFFC01UL, + /* 0x01c8, */ 0x0021006005EFFC01UL, + /* 0x01d0, */ 0x0021006005EFFC01UL, + /* 0x01d8, */ 0x0021006005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021001005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021001005E79401UL, + /* 0x0218, */ 0x0011001005E79401UL, + /* 0x0220, */ 0x0011001005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011001005E79401UL, + /* 0x0238, */ 0x0011001005E79401UL, + /* 0x0240, */ 0x0012001005E79401UL, + /* 0x0248, */ 0x0011001005E79401UL, + /* 0x0250, */ 0x0012001005E79401UL, + /* 0x0258, */ 0x0011001005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011006005EFFC01UL, + /* 0x02f8, */ 0x0011006005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011006005EFFC01UL, + /* 0x0310, */ 0x0011006005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0011006005EFFC01UL, + /* 0x0328, */ 0x0011006005EFFC01UL, + /* 0x0330, */ 0x0011006005EFFC01UL, + /* 0x0338, */ 0x0011006005EFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0012001005E0FC01UL, +}; + +#endif /* QOS_INIT_G2H_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h new file mode 100644 index 0000000..044f246 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_QOSWT195_H +#define QOS_INIT_G2H_QOSWT195_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001410070000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0014100D0000C010UL, + /* 0x0060, */ 0x0014100D0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2H_QOSWT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h new file mode 100644 index 0000000..2ae07ab --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_QOSWT390_H +#define QOS_INIT_G2H_QOSWT390_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x0010100D0000C010UL, + /* 0x0040, */ 0x00141C0E0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00141C190000C010UL, + /* 0x0060, */ 0x00141C190000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2H_QOSWT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c new file mode 100644 index 0000000..7f466c8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "qos_init_g2h_v30.h" +#include "../qos_common.h" +#include "../qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.07" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2H (SL_INIT_SSLOTCLK_G2H - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_G2H ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2H) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_G2H (QOSWT_WTSET0_PERIOD0_G2H) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_SSLOT0) +#define QOSWT_WTSET1_SLOTSLOT1 (QOSWT_WTSET0_SLOTSLOT0) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2h_mstat195.h" +#else +#include "qos_init_g2h_mstat390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2h_qoswt195.h" +#else +#include "qos_init_g2h_qoswt390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ + +static const struct rcar_gen3_dbsc_qos_settings g2h_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2h_v30(void) +{ + unsigned int split_area; + + rzg_qos_dbsc_setting(g2h_v30_qos, ARRAY_SIZE(g2h_v30_qos), true); + + /* use 1(2GB) for RCAR_DRAM_LPDDR4_MEMCONF for G2H */ + split_area = 0x1CU; + + /* DRAM split address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) +#if RCAR_LSI == RZ_G2H +#error "Don't set DRAM Split 4ch(G2H)" +#else /* RCAR_LSI == RZ_G2H */ + ERROR("DRAM split 4ch not supported.(G2H)"); + panic(); +#endif /* RCAR_LSI == RZ_G2H */ +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch(DDR %x)\n", (int)qos_init_ddr_phyvalid); + + mmio_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + mmio_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT | + ADSPLCR0_SPLITSEL(0xFFU) | ADSPLCR0_AREA(split_area) | + ADSPLCR0_SWP); + mmio_write_32(AXI_ADSPLCR2, 0x00001004U); + mmio_write_32(AXI_ADSPLCR3, 0x00000000U); +#else /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + mmio_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + NOTICE("BL2: DRAM Split is OFF(DDR %x)\n", (int)qos_init_ddr_phyvalid); +#endif /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_RAS, 0x00000044U); + mmio_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x0020100AU); + mmio_write_32(QOSCTRL_FSS, 0x0000000AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_RACNT0, 0x00010003U); + + /* GPU Boost Mode */ + mmio_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + mmio_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | + SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_G2H); + mmio_write_32(QOSCTRL_REF_ARS, ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2H << 16))); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + mmio_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8U, qoswt_fix[i]); + mmio_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8U, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + mmio_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8U, qoswt_be[i]); + mmio_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8U, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* AXI setting */ + mmio_write_32(AXI_MMCR, 0x00010008U); + mmio_write_32(AXI_TR3CR, 0x00010000U); + mmio_write_32(AXI_TR4CR, 0x00010000U); + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + mmio_write_32(CPU_ACT2, 0x00000003U); + mmio_write_32(CPU_ACT3, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + mmio_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + mmio_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_G2H << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + mmio_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_G2H << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + mmio_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h new file mode 100644 index 0000000..acd9627 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_V30_H +#define QOS_INIT_G2H_V30_H + +void qos_init_g2h_v30(void); + +#endif /* QOS_INIT_G2H_V30_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c new file mode 100644 index 0000000..ceaad25 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "../qos_common.h" +#include "qos_init_g2m_v10.h" +#include "qos_init_g2m_v10_mstat.h" +#include "qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.19" + +static const struct rcar_gen3_dbsc_qos_settings g2m_v10_qos[] = { + /* BUFCAM settings */ + /* DBSC_DBCAM0CNF0 not set */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x080F0037U }, + /* DBSC_DBSCHCNT1 not set */ + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000300U }, + { DBSC_DBSCHQOS91, 0x000002F0U }, + { DBSC_DBSCHQOS92, 0x00000200U }, + { DBSC_DBSCHQOS93, 0x00000100U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2m_v10(void) +{ + rzg_qos_dbsc_setting(g2m_v10_qos, ARRAY_SIZE(g2m_v10_qos), false); + + /* DRAM split address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RZ_G2M +#error "Don't set DRAM Split 4ch(G2M)" +#else /* RCAR_LSI == RZ_G2M */ + ERROR("DRAM Split 4ch not supported.(G2M)"); + panic(); +#endif /* RCAR_LSI == RZ_G2M */ +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + mmio_write_32(AXI_ADSPLCR0, 0x00000000U); + mmio_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT | + ADSPLCR0_SPLITSEL(0xFFU) | ADSPLCR0_AREA(0x1CU) | + ADSPLCR0_SWP); + mmio_write_32(AXI_ADSPLCR2, 0x089A0000U); + mmio_write_32(AXI_ADSPLCR3, 0x00000000U); +#else /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + NOTICE("BL2: DRAM Split is OFF\n"); +#endif /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* Resource Alloc setting */ + mmio_write_32(QOSCTRL_RAS, 0x00000028U); + mmio_write_32(QOSCTRL_FIXTH, 0x000F0005U); + mmio_write_32(QOSCTRL_REGGD, 0x00000000U); + mmio_write_64(QOSCTRL_DANN, 0x0101010102020201UL); + mmio_write_32(QOSCTRL_DANT, 0x00100804U); + mmio_write_32(QOSCTRL_EC, 0x00000000U); + mmio_write_64(QOSCTRL_EMS, 0x0000000000000000UL); + mmio_write_32(QOSCTRL_FSS, 0x000003e8U); + mmio_write_32(QOSCTRL_INSFC, 0xC7840001U); + mmio_write_32(QOSCTRL_BERR, 0x00000000U); + mmio_write_32(QOSCTRL_RACNT0, 0x00000000U); + + /* QOSBW setting */ + mmio_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK); + mmio_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + mmio_write_32(0xFD820808U, 0x00001234U); + mmio_write_32(0xFD820800U, 0x00000006U); + mmio_write_32(0xFD821800U, 0x00000006U); + mmio_write_32(0xFD822800U, 0x00000006U); + mmio_write_32(0xFD823800U, 0x00000006U); + mmio_write_32(0xFD824800U, 0x00000006U); + mmio_write_32(0xFD825800U, 0x00000006U); + mmio_write_32(0xFD826800U, 0x00000006U); + mmio_write_32(0xFD827800U, 0x00000006U); + + /* RT bus Leaf setting */ + mmio_write_32(0xFFC50800U, 0x00000000U); + mmio_write_32(0xFFC51800U, 0x00000000U); + + /* Resource Alloc start */ + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + mmio_write_32(QOSCTRL_EC, 0x00000000U); + /* Resource Alloc start */ + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h new file mode 100644 index 0000000..627974a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V10_H +#define QOS_INIT_G2M_V10_H + +void qos_init_g2m_v10(void); + +#endif /* QOS_INIT_G2M_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h new file mode 100644 index 0000000..c37915c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V10_MSTAT_H +#define QOS_INIT_G2M_V10_MSTAT_H + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004030000FFFFUL, + /* 0x0038, */ 0x001004030000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001410010000FFFFUL, + /* 0x0058, */ 0x00140C090000FFFFUL, + /* 0x0060, */ 0x00140C090000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001410010000FFFFUL, + /* 0x0078, */ 0x001004020000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408060000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x000C08020000FFFFUL, + /* 0x00A8, */ 0x000C04010000FFFFUL, + /* 0x00B0, */ 0x000C04010000FFFFUL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x000C08020000FFFFUL, + /* 0x00C8, */ 0x000C04010000FFFFUL, + /* 0x00D0, */ 0x000C04010000FFFFUL, + /* 0x00D8, */ 0x000C04030000FFFFUL, + /* 0x00E0, */ 0x000C100F0000FFFFUL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x001010080000FFFFUL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001010080000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0A0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00100C0A0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0A0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008050000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001028280000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x00100C0A0000FFFFUL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02A0, */ 0x000C04010000FFFFUL, + /* 0x02A8, */ 0x000C04010000FFFFUL, + /* 0x02B0, */ 0x001404010000FFFFUL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x000C04010000FFFFUL, + /* 0x02D8, */ 0x000C04010000FFFFUL, + /* 0x02E0, */ 0x001404010000FFFFUL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200100C89C401UL, + /* 0x0008, */ 0x001200100C89C401UL, + /* 0x0010, */ 0x001200100C89C401UL, + /* 0x0018, */ 0x001200100C89C401UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001100100C803401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x001100500C8FFC01UL, + /* 0x01C8, */ 0x001100500C8FFC01UL, + /* 0x01D0, */ 0x001100500C8FFC01UL, + /* 0x01D8, */ 0x001100500C8FFC01UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x001200100C803401UL, + /* 0x01F0, */ 0x001100100C80FC01UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x001200100C80FC01UL, + /* 0x0210, */ 0x001100100C80FC01UL, + /* 0x0218, */ 0x001100100C825801UL, + /* 0x0220, */ 0x001100100C825801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100C825801UL, + /* 0x0238, */ 0x001100100C825801UL, + /* 0x0240, */ 0x001200100C8BB801UL, + /* 0x0248, */ 0x001100100C8EA401UL, + /* 0x0250, */ 0x001200100C8BB801UL, + /* 0x0258, */ 0x001100100C8EA401UL, + /* 0x0260, */ 0x001100100C84E401UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x001100100C81F401UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x001100100C803401UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x001100100C803401UL, + /* 0x02F0, */ 0x001100300C8FFC01UL, + /* 0x02F8, */ 0x001100500C8FFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100300C8FFC01UL, + /* 0x0310, */ 0x001100500C8FFC01UL, + /* 0x0318, */ 0x001200100C803401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ + +#endif /* QOS_INIT_G2M_V10_MSTAT_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c new file mode 100644 index 0000000..db61858 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "../qos_common.h" +#include "qos_init_g2m_v11.h" +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2m_v11_mstat195.h" +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#include "qos_init_g2m_v11_mstat390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2m_v11_qoswt195.h" +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#include "qos_init_g2m_v11_qoswt390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ +#include "qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.19" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2M_11 (SL_INIT_SSLOTCLK_G2M_11 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_G2M_11 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2M_11) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_G2M_11 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2M_11) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +static const struct rcar_gen3_dbsc_qos_settings g2m_v11_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2m_v11(void) +{ + uint32_t i; + + rzg_qos_dbsc_setting(g2m_v11_qos, ARRAY_SIZE(g2m_v11_qos), false); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RZ_G2M +#error "Don't set DRAM Split 4ch(G2M)" +#else /* RCAR_LSI == RZ_G2M */ + ERROR("DRAM Split 4ch not supported.(G2M)"); + panic(); +#endif /* RCAR_LSI == RZ_G2M */ +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + mmio_write_32(AXI_ADSPLCR0, 0x00000000U); + mmio_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT | + ADSPLCR0_SPLITSEL(0xFFU) | ADSPLCR0_AREA(0x1CU) | + ADSPLCR0_SWP); + mmio_write_32(AXI_ADSPLCR2, 0x00001004U); + mmio_write_32(AXI_ADSPLCR3, 0x00000000U); +#else /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + NOTICE("BL2: DRAM Split is OFF\n"); +#endif /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_RAS, 0x00000044U); + mmio_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x0020100AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_RACNT0, 0x02010003U); /* GPU Boost Mode ON */ + + mmio_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_G2M_11); +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + mmio_write_32(QOSCTRL_REF_ARS, + QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2M_11 << 16); +#else /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + mmio_write_32(QOSCTRL_REF_ARS, 0x00330000U); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + mmio_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8U, qoswt_fix[i]); + mmio_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8U, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + mmio_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8U, qoswt_be[i]); + mmio_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8U, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* 3DG bus Leaf setting */ + mmio_write_32(GPU_ACT_GRD, 0x00001234U); + mmio_write_32(GPU_ACT0, 0x00000000U); + mmio_write_32(GPU_ACT1, 0x00000000U); + mmio_write_32(GPU_ACT2, 0x00000000U); + mmio_write_32(GPU_ACT3, 0x00000000U); + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + mmio_write_32(CPU_ACT2, 0x00000003U); + mmio_write_32(CPU_ACT3, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + mmio_write_32(QOSWT_WTREF, + (QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN); + mmio_write_32(QOSWT_WTSET0, + (QOSWT_WTSET0_PERIOD0_G2M_11 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0); + mmio_write_32(QOSWT_WTSET1, + (QOSWT_WTSET1_PERIOD1_G2M_11 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1); + + mmio_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h new file mode 100644 index 0000000..d042493 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_H +#define QOS_INIT_G2M_V11_H + +void qos_init_g2m_v11(void); + +#endif /* QOS_INIT_G2M_V11_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h new file mode 100644 index 0000000..950abd6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_MSTAT195_H +#define QOS_INIT_G2M_V11_MSTAT195_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x00140C0A0000FFFFUL, + /* 0x0060, */ 0x00140C0A0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408070000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x000C08050000FFFFUL, + /* 0x00e0, */ 0x000C14120000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V11_MSTAT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h new file mode 100644 index 0000000..5c6fd24 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_MSTAT390_H +#define QOS_INIT_G2M_V11_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424120000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001414130000FFFFUL, + /* 0x0060, */ 0x001414130000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008050000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x000C0C0A0000FFFFUL, + /* 0x00e0, */ 0x000C24230000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100B005EFFC01UL, + /* 0x01c8, */ 0x002100B005EFFC01UL, + /* 0x01d0, */ 0x002100B005EFFC01UL, + /* 0x01d8, */ 0x002100B005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V11_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h new file mode 100644 index 0000000..f526a82 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_QOSWT195_H +#define QOS_INIT_G2M_V11_QOSWT195_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001004040000C010UL, + /* 0x0040, */ 0x001414090000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C0A0000C010UL, + /* 0x0060, */ 0x00140C0A0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001004030000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFF0UL, + /* 0x0090, */ 0x001408070000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V11_QOSWT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h new file mode 100644 index 0000000..bfb80e3 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_QOSWT390_H +#define QOS_INIT_G2M_V11_QOSWT390_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424120000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001414130000C010UL, + /* 0x0060, */ 0x001414130000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008050000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V11_QOSWT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c new file mode 100644 index 0000000..321cd2b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "../qos_common.h" +#include "qos_init_g2m_v30.h" +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2m_v30_mstat195.h" +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#include "qos_init_g2m_v30_mstat390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2m_v30_qoswt195.h" +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#include "qos_init_g2m_v30_qoswt390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ +#include "qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.04" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2M_30 (SL_INIT_SSLOTCLK_G2M_30 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_G2M_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2M_30) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_G2M_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2M_30) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +static const struct rcar_gen3_dbsc_qos_settings g2m_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2m_v30(void) +{ + uint32_t i; + + rzg_qos_dbsc_setting(g2m_v30_qos, ARRAY_SIZE(g2m_v30_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RZ_G2M + #error "Don't set DRAM Split 4ch(G2M)" +#else /* RCAR_LSI == RZ_G2M */ + ERROR("DRAM Split 4ch not supported.(G2M)"); + panic(); +#endif /* RCAR_LSI == RZ_G2M */ +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + mmio_write_32(AXI_ADSPLCR0, 0x00000000U); + mmio_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT | + ADSPLCR0_SPLITSEL(0xFFU) | ADSPLCR0_AREA(0x1DU) | + ADSPLCR0_SWP); + mmio_write_32(AXI_ADSPLCR2, 0x00001004U); + mmio_write_32(AXI_ADSPLCR3, 0x00000000U); +#else /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + NOTICE("BL2: DRAM Split is OFF\n"); +#endif /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_RAS, 0x00000044U); + mmio_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x0020100AU); + mmio_write_32(QOSCTRL_FSS, 0x0000000AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_EARLYR, 0x00000001U); + mmio_write_32(QOSCTRL_RACNT0, 0x02010003U); /* GPU Boost Mode ON */ + + /* GPU Boost Mode */ + mmio_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + mmio_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_G2M_30); + mmio_write_32(QOSCTRL_REF_ARS, + QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2M_30 << 16); + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + mmio_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8U, qoswt_fix[i]); + mmio_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8U, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + mmio_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8U, qoswt_be[i]); + mmio_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8U, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + mmio_write_32(CPU_ACT2, 0x00000003U); + mmio_write_32(CPU_ACT3, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + mmio_write_32(QOSWT_WTREF, + (QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN); + mmio_write_32(QOSWT_WTSET0, (QOSWT_WTSET0_PERIOD0_G2M_30 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0); + mmio_write_32(QOSWT_WTSET1, (QOSWT_WTSET1_PERIOD1_G2M_30 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1); + + mmio_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h new file mode 100644 index 0000000..f89eabf --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_H +#define QOS_INIT_G2M_V30_H + +void qos_init_g2m_v30(void); + +#endif /* QOS_INIT_G2M_V30_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h new file mode 100644 index 0000000..fd15788 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_MSTAT195_H +#define QOS_INIT_G2M_V30_MSTAT195_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x00140C0A0000FFFFUL, + /* 0x0060, */ 0x00140C0A0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408070000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x000C08050000FFFFUL, + /* 0x00e0, */ 0x000C10100000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x000C10100000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200200BDFFC01UL, + /* 0x0008, */ 0x001200200BDFFC01UL, + /* 0x0010, */ 0x001200200BDFFC01UL, + /* 0x0018, */ 0x001200200BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100200BDFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100200BDFFC01UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V30_MSTAT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h new file mode 100644 index 0000000..aa2036d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_MSTAT390_H +#define QOS_INIT_G2M_V30_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424120000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001414130000FFFFUL, + /* 0x0060, */ 0x001414130000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008050000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x000C0C0A0000FFFFUL, + /* 0x00e0, */ 0x000C201F0000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x000C201F0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100B005EFFC01UL, + /* 0x01c8, */ 0x002100B005EFFC01UL, + /* 0x01d0, */ 0x002100B005EFFC01UL, + /* 0x01d8, */ 0x002100B005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V30_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h new file mode 100644 index 0000000..27c9c51 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_QOSWT195_H +#define QOS_INIT_G2M_V30_QOSWT195_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001004040000C010UL, + /* 0x0040, */ 0x001414090000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C0A0000C010UL, + /* 0x0060, */ 0x00140C0A0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001004030000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFF0UL, + /* 0x0090, */ 0x001408070000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V30_QOSWT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h new file mode 100644 index 0000000..5d18212 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_QOSWT390_H +#define QOS_INIT_G2M_V30_QOSWT390_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424120000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001414130000C010UL, + /* 0x0060, */ 0x001414130000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008050000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V30_QOSWT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c new file mode 100644 index 0000000..00b0948 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "qos_init_g2n_v10.h" + +#include "../qos_common.h" +#include "../qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.09" + +#define REF_ARS_ARBSTOPCYCLE_G2N (((SL_INIT_SSLOTCLK_G2N) - 5U) << 16U) + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN QOSWT_WTREF_SLOT0_EN + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_G2N ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2N) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_G2N QOSWT_WTSET0_PERIOD0_G2N +#define QOSWT_WTSET1_SSLOT1 QOSWT_WTSET0_SSLOT0 +#define QOSWT_WTSET1_SLOTSLOT1 QOSWT_WTSET0_SLOTSLOT0 + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2n_v10_mstat195.h" +#else +#include "qos_init_g2n_v10_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2n_v10_qoswt195.h" +#else +#include "qos_init_g2n_v10_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif + +static const struct rcar_gen3_dbsc_qos_settings g2n_v10_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2n_v10(void) +{ + rzg_qos_dbsc_setting(g2n_v10_qos, ARRAY_SIZE(g2n_v10_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RZ_G2N +#error "Don't set DRAM Split 4ch(G2N)" +#else + ERROR("DRAM Split 4ch not supported.(G2N)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) +#if RCAR_LSI == RZ_G2N +#error "Don't set DRAM Split 2ch(G2N)" +#else + ERROR("DRAM Split 2ch not supported.(G2N)"); + panic(); +#endif +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_RAS, 0x00000028U); + mmio_write_64(QOSCTRL_DANN, 0x0402000002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x00100804U); + mmio_write_32(QOSCTRL_FSS, 0x0000000AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_EARLYR, 0x00000001U); + mmio_write_32(QOSCTRL_RACNT0, 0x00010003U); + + mmio_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | + SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_G2N); + mmio_write_32(QOSCTRL_REF_ARS, REF_ARS_ARBSTOPCYCLE_G2N); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + mmio_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8U, qoswt_fix[i]); + mmio_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8U, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + mmio_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8U, qoswt_be[i]); + mmio_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8U, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + mmio_write_32(QOSWT_WTREF, ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + mmio_write_32(QOSWT_WTSET0, ((QOSWT_WTSET0_PERIOD0_G2N << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + mmio_write_32(QOSWT_WTSET1, ((QOSWT_WTSET1_PERIOD1_G2N << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + mmio_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h new file mode 100644 index 0000000..c7f02d9 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_V10_H +#define QOS_INIT_G2N_V10_H + +void qos_init_g2n_v10(void); + +#endif /* QOS_INIT_G2N_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h new file mode 100644 index 0000000..6e304b0 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_MSTAT195_H +#define QOS_INIT_G2N_MSTAT195_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004320000FFFFUL, + /* 0x0038, */ 0x001004320000FFFFUL, + /* 0x0040, */ 0x00140C5D0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404040000FFFFUL, + /* 0x0058, */ 0x00140C940000FFFFUL, + /* 0x0060, */ 0x00140C940000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404040000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014041F0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C041D0000FFFFUL, + /* 0x00a8, */ 0x000C04090000FFFFUL, + /* 0x00b0, */ 0x000C040B0000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C041D0000FFFFUL, + /* 0x00c8, */ 0x000C04090000FFFFUL, + /* 0x00d0, */ 0x000C040B0000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x000C084F0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x000C21E60000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100CA50000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x001010C90000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100CA50000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008530000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00101D9D0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100CA50000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408020000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408020000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04050000FFFFUL, + /* 0x02a8, */ 0x000C04050000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04050000FFFFUL, + /* 0x02d8, */ 0x000C04050000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x000C04050000FFFFUL, + /* 0x0388, */ 0x000C04050000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002106000BDFFC01UL, + /* 0x01c8, */ 0x002106000BDFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x001101000BDF2401UL, + /* 0x0220, */ 0x001101000BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001101000BDF2401UL, + /* 0x0238, */ 0x001101000BDF2401UL, + /* 0x0240, */ 0x001201000BDF2401UL, + /* 0x0248, */ 0x001101000BDF2401UL, + /* 0x0250, */ 0x001201000BDF2401UL, + /* 0x0258, */ 0x001101000BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001106000BDFFC01UL, + /* 0x02f8, */ 0x001106000BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x001206000BDFFC01UL, + /* 0x0360, */ 0x001206000BDFFC01UL, + /* 0x0368, */ 0x001200100BD03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x001200100BD03401UL, +}; +#endif /* QOS_INIT_G2N_MSTAT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h new file mode 100644 index 0000000..4632413 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_MSTAT390_H +#define QOS_INIT_G2N_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008630000FFFFUL, + /* 0x0038, */ 0x001008630000FFFFUL, + /* 0x0040, */ 0x001418BA0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404070000FFFFUL, + /* 0x0058, */ 0x001415270000FFFFUL, + /* 0x0060, */ 0x001415270000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404070000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014083E0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08390000FFFFUL, + /* 0x00a8, */ 0x000C04110000FFFFUL, + /* 0x00b0, */ 0x000C04150000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08390000FFFFUL, + /* 0x00c8, */ 0x000C04110000FFFFUL, + /* 0x00d0, */ 0x000C04150000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001045080000FFFFUL, + /* 0x00f8, */ 0x000C0C9E0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001015080000FFFFUL, + /* 0x0118, */ 0x000C43CB0000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0010194A0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101D910000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0010194A0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100CA50000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001037390000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0010194A0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04020000FFFFUL, + /* 0x01f0, */ 0x000C04090000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04090000FFFFUL, + /* 0x0210, */ 0x000C04090000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFFFUL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x000C08110000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02a0, */ 0x000C04090000FFFFUL, + /* 0x02a8, */ 0x000C04090000FFFFUL, + /* 0x02b0, */ 0x00140C090000FFFFUL, + /* 0x02b8, */ 0x000C04020000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04090000FFFFUL, + /* 0x02d8, */ 0x000C04090000FFFFUL, + /* 0x02e0, */ 0x00140C090000FFFFUL, + /* 0x02e8, */ 0x000C04020000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060005EFFC01UL, + /* 0x01c8, */ 0x0021060005EFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010005E79401UL, + /* 0x0218, */ 0x0011010005E79401UL, + /* 0x0220, */ 0x0011010005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010005E79401UL, + /* 0x0238, */ 0x0011010005E79401UL, + /* 0x0240, */ 0x0012010005E79401UL, + /* 0x0248, */ 0x0011010005E79401UL, + /* 0x0250, */ 0x0012010005E79401UL, + /* 0x0258, */ 0x0011010005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060005EFFC01UL, + /* 0x02f8, */ 0x0011060005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060005EFFC01UL, + /* 0x0360, */ 0x0012060005EFFC01UL, + /* 0x0368, */ 0x0012001005E03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001005E03401UL, +}; +#endif /* QOS_INIT_G2N_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h new file mode 100644 index 0000000..eea1fce --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_QOSWT195_H +#define QOS_INIT_G2N_QOSWT195_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004320000C010UL, + /* 0x0038, */ 0x001004320000C010UL, + /* 0x0040, */ 0x00140C5D0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C940000C010UL, + /* 0x0060, */ 0x00140C940000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014041F0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08150000FFF0UL, + /* 0x0268, */ 0x001408020000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04090000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408020000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; +#endif /* QOS_INIT_G2N_QOSWT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h new file mode 100644 index 0000000..7043303 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_QOSWT390_H +#define QOS_INIT_G2N_QOSWT390_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008630000C010UL, + /* 0x0038, */ 0x001008630000C010UL, + /* 0x0040, */ 0x001418BA0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001415270000C010UL, + /* 0x0060, */ 0x001415270000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014083E0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFF0UL, + /* 0x0268, */ 0x001410040000FFF0UL, + /* 0x0270, */ 0x001404020000FFF0UL, + /* 0x0278, */ 0x000C08110000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFF0UL, + /* 0x0298, */ 0x001404020000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; +#endif /* QOS_INIT_G2N_QOSWT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/qos.mk b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos.mk new file mode 100644 index 0000000..f05d126 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos.mk @@ -0,0 +1,60 @@ +# +# Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${RCAR_LSI},${RCAR_AUTO}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c +else ifeq (${RCAR_LSI_CUT_COMPAT},1) + ifeq (${RCAR_LSI},${RZ_G2M}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c + endif + ifeq (${RCAR_LSI},${RZ_G2H}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c + endif + ifeq (${RCAR_LSI},${RZ_G2N}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c + endif + ifeq (${RCAR_LSI},${RZ_G2E}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c + endif +else + ifeq (${RCAR_LSI},${RZ_G2M}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c + else ifeq (${LSI_CUT},11) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c + else ifeq (${LSI_CUT},13) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c + else ifeq (${LSI_CUT},30) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c + else +# LSI_CUT 30 or later + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c + endif + endif + ifeq (${RCAR_LSI},${RZ_G2H}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c + endif + ifeq (${RCAR_LSI},${RZ_G2N}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c + else +# LSI_CUT 10 or later + BL2_SOURCES += drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c + endif + endif + ifeq (${RCAR_LSI},${RZ_G2E}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c + endif +endif + +BL2_SOURCES += drivers/renesas/rzg/qos/qos_init.c diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h new file mode 100644 index 0000000..535bf4c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_COMMON_H +#define QOS_COMMON_H + +#define RCAR_REF_DEFAULT 0U + +/* define used for get_refperiod. */ +/* REFPERIOD_CYCLE need smaller than QOSWT_WTSET0_CYCLEs */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF default */ +#define REFPERIOD_CYCLE /* unit:ns */ \ + ((126U * BASE_SUB_SLOT_NUM * 1000U) / 400U) +#else /* REF option */ +#define REFPERIOD_CYCLE /* unit:ns */ \ + ((252U * BASE_SUB_SLOT_NUM * 1000U) / 400U) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) +/* define used for G2M */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_G2M_11 0x7EU /* 126 */ +#define SUB_SLOT_CYCLE_G2M_30 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_G2M_11 0xFCU /* 252 */ +#define SUB_SLOT_CYCLE_G2M_30 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_G2M_11 (SUB_SLOT_CYCLE_G2M_11 - 1U) +#define SL_INIT_SSLOTCLK_G2M_30 (SUB_SLOT_CYCLE_G2M_30 - 1U) +#define QOSWT_WTSET0_CYCLE_G2M_11 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_G2M_11 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#define QOSWT_WTSET0_CYCLE_G2M_30 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_G2M_30 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) +/* define used for G2N */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_G2N 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_G2N 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_G2N (SUB_SLOT_CYCLE_G2N - 1U) +#define QOSWT_WTSET0_CYCLE_G2N /* unit:ns */ \ + ((SUB_SLOT_CYCLE_G2N * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif /* (RCAR_LSI == RZ_G2N) */ + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) +/* define used for G2H */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_G2H 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_G2H 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_G2H (SUB_SLOT_CYCLE_G2H - 1U) +#define QOSWT_WTSET0_CYCLE_G2H /* unit:ns */ \ + ((SUB_SLOT_CYCLE_G2H * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2E) +/* define used for G2E */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_G2E 0xAFU /* 175 */ +#else /* REF 7.8usec */ +#define SUB_SLOT_CYCLE_G2E 0x15EU /* 350 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define OPERATING_FREQ_G2E 266U /* MHz */ +#define SL_INIT_SSLOTCLK_G2E (SUB_SLOT_CYCLE_G2E - 1U) +#endif + +#define OPERATING_FREQ 400U /* MHz */ +#define BASE_SUB_SLOT_NUM 0x6U +#define SUB_SLOT_CYCLE 0x7EU /* 126 */ + +#define QOSWT_WTSET0_CYCLE /* unit:ns */ \ + ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +#define SL_INIT_REFFSSLOT (0x3U << 24U) +#define SL_INIT_SLOTSSLOT ((BASE_SUB_SLOT_NUM - 1U) << 16U) +#define SL_INIT_SSLOTCLK (SUB_SLOT_CYCLE - 1U) + +typedef struct { + uintptr_t addr; + uint64_t value; +} mstat_slot_t; + +struct rcar_gen3_dbsc_qos_settings { + uint32_t reg; + uint32_t val; +}; + +extern uint32_t qos_init_ddr_ch; +extern uint8_t qos_init_ddr_phyvalid; + +void rzg_qos_dbsc_setting(const struct rcar_gen3_dbsc_qos_settings *qos, + unsigned int qos_size, bool dbsc_wren); + +#endif /* QOS_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c new file mode 100644 index 0000000..e527a61 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#if RCAR_LSI == RCAR_AUTO +#include "G2E/qos_init_g2e_v10.h" +#include "G2H/qos_init_g2h_v30.h" +#include "G2M/qos_init_g2m_v10.h" +#include "G2M/qos_init_g2m_v11.h" +#include "G2M/qos_init_g2m_v30.h" +#include "G2N/qos_init_g2n_v10.h" +#endif /* RCAR_LSI == RCAR_AUTO */ +#if (RCAR_LSI == RZ_G2M) +#include "G2M/qos_init_g2m_v10.h" +#include "G2M/qos_init_g2m_v11.h" +#include "G2M/qos_init_g2m_v30.h" +#endif /* RCAR_LSI == RZ_G2M */ +#if RCAR_LSI == RZ_G2H +#include "G2H/qos_init_g2h_v30.h" +#endif /* RCAR_LSI == RZ_G2H */ +#if RCAR_LSI == RZ_G2N +#include "G2N/qos_init_g2n_v10.h" +#endif /* RCAR_LSI == RZ_G2N */ +#if RCAR_LSI == RZ_G2E +#include "G2E/qos_init_g2e_v10.h" +#endif /* RCAR_LSI == RZ_G2E */ +#include "qos_common.h" +#include "qos_init.h" +#include "qos_reg.h" +#include "rcar_def.h" + +#if (RCAR_LSI != RZ_G2E) +#define DRAM_CH_CNT 0x04U +uint32_t qos_init_ddr_ch; +uint8_t qos_init_ddr_phyvalid; +#endif /* RCAR_LSI != RZ_G2E */ + +#define PRR_PRODUCT_ERR(reg) \ + { \ + ERROR("LSI Product ID(PRR=0x%x) QoS " \ + "initialize not supported.\n", reg); \ + panic(); \ + } + +#define PRR_CUT_ERR(reg) \ + { \ + ERROR("LSI Cut ID(PRR=0x%x) QoS " \ + "initialize not supported.\n", reg); \ + panic(); \ + } + +void rzg_qos_init(void) +{ + uint32_t reg; +#if (RCAR_LSI != RZ_G2E) + uint32_t i; + + qos_init_ddr_ch = 0U; + qos_init_ddr_phyvalid = get_boardcnf_phyvalid(); + for (i = 0U; i < DRAM_CH_CNT; i++) { + if ((qos_init_ddr_phyvalid & (1U << i))) { + qos_init_ddr_ch++; + } + } +#endif /* RCAR_LSI != RZ_G2E */ + + reg = mmio_read_32(PRR); +#if (RCAR_LSI == RCAR_AUTO) || RCAR_LSI_CUT_COMPAT + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_M3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + qos_init_g2m_v10(); + break; + case PRR_PRODUCT_21: /* G2M Cut 13 */ + qos_init_g2m_v11(); + break; + case PRR_PRODUCT_30: /* G2M Cut 30 */ + default: + qos_init_g2m_v30(); + break; + } +#else /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) */ + PRR_PRODUCT_ERR(reg); +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) */ + break; + case PRR_PRODUCT_H3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_30: + default: + qos_init_g2h_v30(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) */ + break; + case PRR_PRODUCT_M3N: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_g2n_v10(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) */ + break; + case PRR_PRODUCT_E3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2E) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_g2e_v10(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2E) */ + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } +#else /* RCAR_LSI == RCAR_AUTO || RCAR_LSI_CUT_COMPAT */ +#if (RCAR_LSI == RZ_G2M) +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* G2M Cut 10 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_10) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2m_v10(); +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* G2M Cut 11 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_20) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2m_v11(); +#elif RCAR_LSI_CUT == RCAR_CUT_13 + /* G2M Cut 13 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_21) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2m_v11(); +#else + /* G2M Cut 30 or later */ + if ((PRR_PRODUCT_M3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2m_v30(); +#endif /* RCAR_LSI_CUT == RCAR_CUT_10 */ +#elif (RCAR_LSI == RZ_G2H) + /* G2H Cut 30 or later */ + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_H3) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2h_v30(); +#elif (RCAR_LSI == RZ_G2N) + /* G2N Cut 10 or later */ + if ((reg & (PRR_PRODUCT_MASK)) != PRR_PRODUCT_M3N) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2n_v10(); +#elif RCAR_LSI == RZ_G2E + /* G2E Cut 10 or later */ + if ((reg & (PRR_PRODUCT_MASK)) != PRR_PRODUCT_E3) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2e_v10(); +#else /* (RCAR_LSI == RZ_G2M) */ +#error "Don't have QoS initialize routine(Unknown chip)." +#endif /* (RCAR_LSI == RZ_G2M) */ +#endif /* RCAR_LSI == RCAR_AUTO || RCAR_LSI_CUT_COMPAT */ +} + +#if (RCAR_LSI != RZ_G2E) +uint32_t get_refperiod(void) +{ + uint32_t refperiod = QOSWT_WTSET0_CYCLE; + +#if (RCAR_LSI == RCAR_AUTO) || RCAR_LSI_CUT_COMPAT + uint32_t reg; + + reg = mmio_read_32(PRR); + switch (reg & PRR_PRODUCT_MASK) { +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) + case PRR_PRODUCT_M3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + break; + case PRR_PRODUCT_20: /* G2M Cut 11 */ + case PRR_PRODUCT_21: /* G2M Cut 13 */ + case PRR_PRODUCT_30: /* G2M Cut 30 */ + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) */ +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) + case PRR_PRODUCT_H3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_30: + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) */ +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) + case PRR_PRODUCT_M3N: + refperiod = REFPERIOD_CYCLE; + break; +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) */ + default: + break; + } +#elif RCAR_LSI == RZ_G2M +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* G2M Cut 10 */ +#else /* RCAR_LSI_CUT == RCAR_CUT_10 */ + /* G2M Cut 11|13|30 or later */ + refperiod = REFPERIOD_CYCLE; +#endif /* RCAR_LSI_CUT == RCAR_CUT_10 */ +#elif RCAR_LSI == RZ_G2N + refperiod = REFPERIOD_CYCLE; +#elif RCAR_LSI == RZ_G2H + /* G2H Cut 30 or later */ + refperiod = REFPERIOD_CYCLE; +#endif /* RCAR_LSI == RCAR_AUTO || RCAR_LSI_CUT_COMPAT */ + return refperiod; +} +#endif /* RCAR_LSI != RZ_G2E */ + +void rzg_qos_dbsc_setting(const struct rcar_gen3_dbsc_qos_settings *qos, + unsigned int qos_size, bool dbsc_wren) +{ + unsigned int i; + + /* Register write enable */ + if (dbsc_wren) { + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234U); + } + + for (i = 0; i < qos_size; i++) { + mmio_write_32(qos[i].reg, qos[i].val); + } + + /* Register write protect */ + if (dbsc_wren) { + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000U); + } +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h new file mode 100644 index 0000000..3d62744 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RZG_QOS_INIT_H +#define RZG_QOS_INIT_H + +void rzg_qos_init(void); +uint8_t get_boardcnf_phyvalid(void); + +#endif /* RZG_QOS_INIT_H */ diff --git a/arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c b/arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c new file mode 100644 index 0000000..f938f56 --- /dev/null +++ b/arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static uintptr_t reg_base; + +static int rpi3_gpio_get_direction(int gpio); +static void rpi3_gpio_set_direction(int gpio, int direction); +static int rpi3_gpio_get_value(int gpio); +static void rpi3_gpio_set_value(int gpio, int value); +static void rpi3_gpio_set_pull(int gpio, int pull); + +static const gpio_ops_t rpi3_gpio_ops = { + .get_direction = rpi3_gpio_get_direction, + .set_direction = rpi3_gpio_set_direction, + .get_value = rpi3_gpio_get_value, + .set_value = rpi3_gpio_set_value, + .set_pull = rpi3_gpio_set_pull, +}; + +/** + * Get selection of GPIO pinmux settings. + * + * @param gpio The pin number of GPIO. From 0 to 53. + * @return The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input, + * RPI3_GPIO_FUNC_OUTPUT: output, + * RPI3_GPIO_FUNC_ALT0: alt-0, + * RPI3_GPIO_FUNC_ALT1: alt-1, + * RPI3_GPIO_FUNC_ALT2: alt-2, + * RPI3_GPIO_FUNC_ALT3: alt-3, + * RPI3_GPIO_FUNC_ALT4: alt-4, + * RPI3_GPIO_FUNC_ALT5: alt-5 + */ +int rpi3_gpio_get_select(int gpio) +{ + int ret; + int regN = gpio / 10; + int shift = 3 * (gpio % 10); + uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN); + uint32_t sel = mmio_read_32(reg_sel); + + ret = (sel >> shift) & 0x07; + + return ret; +} + +/** + * Set selection of GPIO pinmux settings. + * + * @param gpio The pin number of GPIO. From 0 to 53. + * @param fsel The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input, + * RPI3_GPIO_FUNC_OUTPUT: output, + * RPI3_GPIO_FUNC_ALT0: alt-0, + * RPI3_GPIO_FUNC_ALT1: alt-1, + * RPI3_GPIO_FUNC_ALT2: alt-2, + * RPI3_GPIO_FUNC_ALT3: alt-3, + * RPI3_GPIO_FUNC_ALT4: alt-4, + * RPI3_GPIO_FUNC_ALT5: alt-5 + */ +void rpi3_gpio_set_select(int gpio, int fsel) +{ + int regN = gpio / 10; + int shift = 3 * (gpio % 10); + uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN); + uint32_t sel = mmio_read_32(reg_sel); + uint32_t mask = U(0x07) << shift; + + sel = (sel & (~mask)) | ((fsel << shift) & mask); + mmio_write_32(reg_sel, sel); +} + +static int rpi3_gpio_get_direction(int gpio) +{ + int result = rpi3_gpio_get_select(gpio); + + if (result == RPI3_GPIO_FUNC_INPUT) + return GPIO_DIR_IN; + else if (result == RPI3_GPIO_FUNC_OUTPUT) + return GPIO_DIR_OUT; + + return GPIO_DIR_IN; +} + +static void rpi3_gpio_set_direction(int gpio, int direction) +{ + switch (direction) { + case GPIO_DIR_IN: + rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_INPUT); + break; + case GPIO_DIR_OUT: + rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_OUTPUT); + break; + } +} + +static int rpi3_gpio_get_value(int gpio) +{ + int regN = gpio / 32; + int shift = gpio % 32; + uintptr_t reg_lev = reg_base + RPI3_GPIO_GPLEV(regN); + uint32_t value = mmio_read_32(reg_lev); + + if ((value >> shift) & 0x01) + return GPIO_LEVEL_HIGH; + return GPIO_LEVEL_LOW; +} + +static void rpi3_gpio_set_value(int gpio, int value) +{ + int regN = gpio / 32; + int shift = gpio % 32; + uintptr_t reg_set = reg_base + RPI3_GPIO_GPSET(regN); + uintptr_t reg_clr = reg_base + RPI3_GPIO_GPSET(regN); + + switch (value) { + case GPIO_LEVEL_LOW: + mmio_write_32(reg_clr, U(1) << shift); + break; + case GPIO_LEVEL_HIGH: + mmio_write_32(reg_set, U(1) << shift); + break; + } +} + +static void rpi3_gpio_set_pull(int gpio, int pull) +{ + int regN = gpio / 32; + int shift = gpio % 32; + uintptr_t reg_pud = reg_base + RPI3_GPIO_GPPUD; + uintptr_t reg_clk = reg_base + RPI3_GPIO_GPPUDCLK(regN); + + switch (pull) { + case GPIO_PULL_NONE: + mmio_write_32(reg_pud, 0x0); + break; + case GPIO_PULL_UP: + mmio_write_32(reg_pud, 0x2); + break; + case GPIO_PULL_DOWN: + mmio_write_32(reg_pud, 0x1); + break; + } + mdelay(150); + mmio_write_32(reg_clk, U(1) << shift); + mdelay(150); + mmio_write_32(reg_clk, 0x0); + mmio_write_32(reg_pud, 0x0); +} + +void rpi3_gpio_init(void) +{ + reg_base = RPI3_GPIO_BASE; + gpio_init(&rpi3_gpio_ops); +} diff --git a/arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c b/arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c new file mode 100644 index 0000000..aef1f39 --- /dev/null +++ b/arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +#include + +#define RPI3_MAILBOX_MAX_RETRIES U(1000000) + +/******************************************************************************* + * Routine to send requests to the VideoCore using the mailboxes. + ******************************************************************************/ +void rpi3_vc_mailbox_request_send(rpi3_mbox_request_t *req, int req_size) +{ + uint32_t st, data; + uintptr_t resp_addr, addr; + unsigned int retries; + + /* This is the location of the request buffer */ + addr = (uintptr_t)req; + + /* Make sure that the changes are seen by the VideoCore */ + flush_dcache_range(addr, req_size); + + /* Wait until the outbound mailbox is empty */ + retries = 0U; + + do { + st = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX1_STATUS_OFFSET); + + retries++; + if (retries == RPI3_MAILBOX_MAX_RETRIES) { + ERROR("rpi3: mbox: Send request timeout\n"); + return; + } + + } while ((st & RPI3_MBOX_STATUS_EMPTY_MASK) == 0U); + + /* Send base address of this message to start request */ + mmio_write_32(RPI3_MBOX_BASE + RPI3_MBOX1_WRITE_OFFSET, + RPI3_CHANNEL_ARM_TO_VC | (uint32_t) addr); + + /* Wait until the inbound mailbox isn't empty */ + retries = 0U; + + do { + st = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX0_STATUS_OFFSET); + + retries++; + if (retries == RPI3_MAILBOX_MAX_RETRIES) { + ERROR("rpi3: mbox: Receive response timeout\n"); + return; + } + + } while ((st & RPI3_MBOX_STATUS_EMPTY_MASK) != 0U); + + /* Get location and channel */ + data = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX0_READ_OFFSET); + + if ((data & RPI3_CHANNEL_MASK) != RPI3_CHANNEL_ARM_TO_VC) { + ERROR("rpi3: mbox: Wrong channel: 0x%08x\n", data); + panic(); + } + + resp_addr = (uintptr_t)(data & ~RPI3_CHANNEL_MASK); + if (addr != resp_addr) { + ERROR("rpi3: mbox: Unexpected address: 0x%08x\n", data); + panic(); + } + + /* Make sure that the data seen by the CPU is up to date */ + inv_dcache_range(addr, req_size); +} diff --git a/arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c b/arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c new file mode 100644 index 0000000..b6bf005 --- /dev/null +++ b/arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include + +/* Initial amount of values to discard */ +#define RNG_WARMUP_COUNT U(0x40000) + +static void rpi3_rng_initialize(void) +{ + uint32_t int_mask, ctrl; + + /* Return if it is already enabled */ + ctrl = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET); + if ((ctrl & RPI3_RNG_CTRL_ENABLE) != 0U) { + return; + } + + /* Mask interrupts */ + int_mask = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET); + int_mask |= RPI3_RNG_INT_MASK_DISABLE; + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET, int_mask); + + /* Discard several values when initializing to give it time to warmup */ + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET, RNG_WARMUP_COUNT); + + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET, + RPI3_RNG_CTRL_ENABLE); +} + +static uint32_t rpi3_rng_get_word(void) +{ + size_t nwords; + + do { + /* Get number of available words to read */ + nwords = (mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET) + >> RPI3_RNG_STATUS_NUM_WORDS_SHIFT) + & RPI3_RNG_STATUS_NUM_WORDS_MASK; + } while (nwords == 0U); + + return mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_DATA_OFFSET); +} + +void rpi3_rng_read(void *buf, size_t len) +{ + uint32_t data; + size_t left = len; + uint32_t *dst = buf; + + assert(buf != NULL); + assert(len != 0U); + assert(check_uptr_overflow((uintptr_t) buf, (uintptr_t) len) == 0); + + rpi3_rng_initialize(); + + while (left >= sizeof(uint32_t)) { + data = rpi3_rng_get_word(); + *dst++ = data; + left -= sizeof(uint32_t); + } + + if (left > 0U) { + data = rpi3_rng_get_word(); + memcpy(dst, &data, left); + } +} diff --git a/arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c b/arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c new file mode 100644 index 0000000..c4b6fca --- /dev/null +++ b/arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void rpi3_sdhost_initialize(void); +static int rpi3_sdhost_send_cmd(struct mmc_cmd *cmd); +static int rpi3_sdhost_set_ios(unsigned int clk, unsigned int width); +static int rpi3_sdhost_prepare(int lba, uintptr_t buf, size_t size); +static int rpi3_sdhost_read(int lba, uintptr_t buf, size_t size); +static int rpi3_sdhost_write(int lba, uintptr_t buf, size_t size); + +static const struct mmc_ops rpi3_sdhost_ops = { + .init = rpi3_sdhost_initialize, + .send_cmd = rpi3_sdhost_send_cmd, + .set_ios = rpi3_sdhost_set_ios, + .prepare = rpi3_sdhost_prepare, + .read = rpi3_sdhost_read, + .write = rpi3_sdhost_write, +}; + +static struct rpi3_sdhost_params rpi3_sdhost_params; + +/** + * Wait for command being processed. + * + * This function waits the command being processed. It compares + * the ENABLE flag of the HC_COMMAND register. When ENABLE flag disappeared + * it means the command is processed by the SDHOST. + * The timeout is currently 1000*100 us = 100 ms. + * + * @return 0: command finished. 1: command timed out. + */ +static int rpi3_sdhost_waitcommand(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + volatile int timeout = 1000; + + while ((mmio_read_32(reg_base + HC_COMMAND) & HC_CMD_ENABLE) + && (--timeout > 0)) { + udelay(100); + } + + return ((timeout > 0) ? 0 : (-(ETIMEDOUT))); +} + +/** + * Send the command and argument to the SDHOST + * + * This function will wait for the previous command finished. And then + * clear any error status of previous command. And then + * send out the command and args. The command will be turned on the ENABLE + * flag before sending out. + */ +static void send_command_raw(unsigned int cmd, unsigned int arg) +{ + unsigned int status; + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + /* wait for previous command finish */ + rpi3_sdhost_waitcommand(); + + /* clean error status */ + status = mmio_read_32(reg_base + HC_HOSTSTATUS); + if (status & HC_HSTST_MASK_ERROR_ALL) + mmio_write_32(reg_base + HC_HOSTSTATUS, status); + + /* recording the command */ + rpi3_sdhost_params.current_cmd = cmd & HC_CMD_COMMAND_MASK; + + /* send the argument and command */ + mmio_write_32(reg_base + HC_ARGUMENT, arg); + mmio_write_32(reg_base + HC_COMMAND, cmd | HC_CMD_ENABLE); +} + +/** + * Send the command and argument to the SDHOST, decorated with control + * flags. + * + * This function will use send_command_raw to send the commands to SDHOST. + * But before sending it will decorate the command with control flags specific + * to SDHOST. + */ +static void send_command_decorated(unsigned int cmd, unsigned int arg) +{ + unsigned int cmd_flags = 0; + + switch (cmd & HC_CMD_COMMAND_MASK) { + case MMC_CMD(0): + cmd_flags |= HC_CMD_RESPONSE_NONE; + break; + case MMC_ACMD(51): + cmd_flags |= HC_CMD_READ; + break; + case MMC_CMD(8): + case MMC_CMD(11): + case MMC_CMD(17): + case MMC_CMD(18): + cmd_flags |= HC_CMD_READ; + break; + case MMC_CMD(20): + case MMC_CMD(24): + case MMC_CMD(25): + cmd_flags |= HC_CMD_WRITE; + break; + case MMC_CMD(12): + cmd_flags |= HC_CMD_BUSY; + break; + default: + break; + } + send_command_raw(cmd | cmd_flags, arg); +} + +/** + * drains the FIFO on DATA port + * + * This function drains any data left in the DATA port. + */ +static void rpi3_drain_fifo(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + volatile int timeout = 100000; + + rpi3_sdhost_waitcommand(); + + while (mmio_read_32(reg_base + HC_HOSTSTATUS) & HC_HSTST_HAVEDATA) { + mmio_read_32(reg_base + HC_DATAPORT); + udelay(100); + } + + while (1) { + uint32_t edm, fsm; + + edm = mmio_read_32(reg_base + HC_DEBUG); + fsm = edm & HC_DBG_FSM_MASK; + + if ((fsm == HC_DBG_FSM_IDENTMODE) || + (fsm == HC_DBG_FSM_DATAMODE)) + break; + + if ((fsm == HC_DBG_FSM_READWAIT) || + (fsm == HC_DBG_FSM_WRITESTART1) || + (fsm == HC_DBG_FSM_READDATA)) { + mmio_write_32(reg_base + HC_DEBUG, + edm | HC_DBG_FORCE_DATA_MODE); + break; + } + + if (--timeout <= 0) { + ERROR("rpi3_sdhost: %s cannot recover stat\n", + __func__); + return; + } + } +} + +/** + * Dump SDHOST registers + */ +static void rpi3_sdhost_print_regs(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + INFO("rpi3_sdhost: HC_COMMAND: 0x%08x\n", + mmio_read_32(reg_base + HC_COMMAND)); + INFO("rpi3_sdhost: HC_ARGUMENT: 0x%08x\n", + mmio_read_32(reg_base + HC_ARGUMENT)); + INFO("rpi3_sdhost: HC_TIMEOUTCOUNTER: 0x%08x\n", + mmio_read_32(reg_base + HC_TIMEOUTCOUNTER)); + INFO("rpi3_sdhost: HC_CLOCKDIVISOR: 0x%08x\n", + mmio_read_32(reg_base + HC_CLOCKDIVISOR)); + INFO("rpi3_sdhost: HC_RESPONSE_0: 0x%08x\n", + mmio_read_32(reg_base + HC_RESPONSE_0)); + INFO("rpi3_sdhost: HC_RESPONSE_1: 0x%08x\n", + mmio_read_32(reg_base + HC_RESPONSE_1)); + INFO("rpi3_sdhost: HC_RESPONSE_2: 0x%08x\n", + mmio_read_32(reg_base + HC_RESPONSE_2)); + INFO("rpi3_sdhost: HC_RESPONSE_3: 0x%08x\n", + mmio_read_32(reg_base + HC_RESPONSE_3)); + INFO("rpi3_sdhost: HC_HOSTSTATUS: 0x%08x\n", + mmio_read_32(reg_base + HC_HOSTSTATUS)); + INFO("rpi3_sdhost: HC_POWER: 0x%08x\n", + mmio_read_32(reg_base + HC_POWER)); + INFO("rpi3_sdhost: HC_DEBUG: 0x%08x\n", + mmio_read_32(reg_base + HC_DEBUG)); + INFO("rpi3_sdhost: HC_HOSTCONFIG: 0x%08x\n", + mmio_read_32(reg_base + HC_HOSTCONFIG)); + INFO("rpi3_sdhost: HC_BLOCKSIZE: 0x%08x\n", + mmio_read_32(reg_base + HC_BLOCKSIZE)); + INFO("rpi3_sdhost: HC_BLOCKCOUNT: 0x%08x\n", + mmio_read_32(reg_base + HC_BLOCKCOUNT)); +} + +/** + * Reset SDHOST + */ +static void rpi3_sdhost_reset(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + unsigned int dbg; + uint32_t tmp1; + + mmio_write_32(reg_base + HC_POWER, 0); + mmio_write_32(reg_base + HC_COMMAND, 0); + mmio_write_32(reg_base + HC_ARGUMENT, 0); + + mmio_write_32(reg_base + HC_TIMEOUTCOUNTER, HC_TIMEOUT_DEFAULT); + mmio_write_32(reg_base + HC_CLOCKDIVISOR, 0); + mmio_write_32(reg_base + HC_HOSTSTATUS, HC_HSTST_RESET); + mmio_write_32(reg_base + HC_HOSTCONFIG, 0); + mmio_write_32(reg_base + HC_BLOCKSIZE, 0); + mmio_write_32(reg_base + HC_BLOCKCOUNT, 0); + + dbg = mmio_read_32(reg_base + HC_DEBUG); + dbg &= ~((HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_READ_SHIFT) | + (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_WRITE_SHIFT)); + dbg |= (HC_FIFO_THRESH_READ << HC_DBG_FIFO_THRESH_READ_SHIFT) | + (HC_FIFO_THRESH_WRITE << HC_DBG_FIFO_THRESH_WRITE_SHIFT); + mmio_write_32(reg_base + HC_DEBUG, dbg); + mdelay(250); + mmio_write_32(reg_base + HC_POWER, 1); + mdelay(250); + rpi3_sdhost_params.clk_rate = 0; + + mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_MAXVAL); + tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG); + mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1 | HC_HSTCF_INT_BUSY); +} + +static void rpi3_sdhost_initialize(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + assert((rpi3_sdhost_params.reg_base & MMC_BLOCK_MASK) == 0); + + rpi3_sdhost_reset(); + + mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_PREFERVAL); + udelay(300); +} + +static int rpi3_sdhost_send_cmd(struct mmc_cmd *cmd) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + int err = 0; + uint32_t cmd_idx; + uint32_t cmd_arg; + uint32_t cmd_flags = 0; + uint32_t intmask; + + /* Wait for the command done */ + err = rpi3_sdhost_waitcommand(); + if (err != 0) { + WARN("previous command not done yet\n"); + return err; + } + + cmd_idx = cmd->cmd_idx & HC_CMD_COMMAND_MASK; + + cmd_arg = cmd->cmd_arg; + if (cmd_idx == MMC_ACMD(51)) { + /* if previous cmd send to SDHOST is not MMC_CMD(55). + * It means this MMC_ACMD(51) is a resend. + * And we must also resend MMC_CMD(55) in this case + */ + if (rpi3_sdhost_params.current_cmd != MMC_CMD(55)) { + send_command_decorated( + MMC_CMD(55), + rpi3_sdhost_params.sdcard_rca << + RCA_SHIFT_OFFSET); + rpi3_sdhost_params.mmc_app_cmd = 1; + rpi3_sdhost_waitcommand(); + + /* Also we need to call prepare to clean the buffer */ + rpi3_sdhost_prepare(0, (uintptr_t)NULL, 8); + } + } + + /* We ignore MMC_CMD(12) sending from the TF-A's MMC driver + * because we send MMC_CMD(12) by ourselves. + */ + if (cmd_idx == MMC_CMD(12)) + return 0; + + if ((cmd->resp_type & MMC_RSP_136) && + (cmd->resp_type & MMC_RSP_BUSY)) { + ERROR("rpi3_sdhost: unsupported response type!\n"); + return -(EOPNOTSUPP); + } + + if (cmd->resp_type & MMC_RSP_48 && cmd->resp_type != MMC_RESPONSE_R2) { + /* 48-bit command + * We don't need to set any flags here because it is default. + */ + } else if (cmd->resp_type & MMC_RSP_136) { + /* 136-bit command */ + cmd_flags |= HC_CMD_RESPONSE_LONG; + } else { + /* no respond command */ + cmd_flags |= HC_CMD_RESPONSE_NONE; + } + + rpi3_sdhost_params.cmdbusy = 0; + if (cmd->resp_type & MMC_RSP_BUSY) { + cmd_flags |= HC_CMD_BUSY; + rpi3_sdhost_params.cmdbusy = 1; + } + + if (rpi3_sdhost_params.mmc_app_cmd) { + switch (cmd_idx) { + case MMC_ACMD(41): + if (cmd_arg == OCR_HCS) + cmd_arg |= OCR_3_3_3_4; + break; + default: + break; + } + rpi3_sdhost_params.mmc_app_cmd = 0; + } + + if (cmd_idx == MMC_CMD(55)) + rpi3_sdhost_params.mmc_app_cmd = 1; + + send_command_decorated(cmd_idx | cmd_flags, cmd_arg); + + intmask = mmio_read_32(reg_base + HC_HOSTSTATUS); + if (rpi3_sdhost_params.cmdbusy && (intmask & HC_HSTST_INT_BUSY)) { + mmio_write_32(reg_base + HC_HOSTSTATUS, HC_HSTST_INT_BUSY); + rpi3_sdhost_params.cmdbusy = 0; + } + + if (!(cmd_flags & HC_CMD_RESPONSE_NONE)) { + err = rpi3_sdhost_waitcommand(); + if (err != 0) + ERROR("rpi3_sdhost: cmd cannot be finished\n"); + } + + cmd->resp_data[0] = mmio_read_32(reg_base + HC_RESPONSE_0); + cmd->resp_data[1] = mmio_read_32(reg_base + HC_RESPONSE_1); + cmd->resp_data[2] = mmio_read_32(reg_base + HC_RESPONSE_2); + cmd->resp_data[3] = mmio_read_32(reg_base + HC_RESPONSE_3); + + if (mmio_read_32(reg_base + HC_COMMAND) & HC_CMD_FAILED) { + uint32_t sdhsts = mmio_read_32(reg_base + HC_HOSTSTATUS); + + mmio_write_32(reg_base + HC_HOSTSTATUS, + HC_HSTST_MASK_ERROR_ALL); + + /* + * If the command SEND_OP_COND returns with CRC7 error, + * it can be considered as having completed successfully. + */ + if (!(sdhsts & HC_HSTST_ERROR_CRC7) + || (cmd_idx != MMC_CMD(1))) { + if (sdhsts & HC_HSTST_TIMEOUT_CMD) { + ERROR("rpi3_sdhost: timeout status 0x%x\n", + sdhsts); + err = -(ETIMEDOUT); + } else { + ERROR("rpi3_sdhost: unknown err, cmd = 0x%x\n", + mmio_read_32(reg_base + HC_COMMAND)); + ERROR("rpi3_sdhost status: 0x%x\n", sdhsts); + err = -(EILSEQ); + } + } + } + + if ((!err) && (cmd_idx == MMC_CMD(3))) { + /* we keep the RCA in case to send MMC_CMD(55) ourselves */ + rpi3_sdhost_params.sdcard_rca = (cmd->resp_data[0] + & 0xFFFF0000U) >> 16; + } + + return err; +} + +static int rpi3_sdhost_set_clock(unsigned int clk) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + uint32_t max_clk = 250000000; + uint32_t div; + + if (clk < 100000) { + mmio_write_32(reg_base + HC_CLOCKDIVISOR, + HC_CLOCKDIVISOR_MAXVAL); + return 0; + } + + div = max_clk / clk; + if (div < 2) + div = 2; + + if ((max_clk / div) > clk) + div++; + + div -= 2; + if (div > HC_CLOCKDIVISOR_MAXVAL) + div = HC_CLOCKDIVISOR_MAXVAL; + + rpi3_sdhost_params.clk_rate = max_clk / (div + 2); + rpi3_sdhost_params.ns_per_fifo_word = (1000000000 / + rpi3_sdhost_params.clk_rate) + * 8; + + mmio_write_32(reg_base + HC_CLOCKDIVISOR, div); + return 0; +} + +static int rpi3_sdhost_set_ios(unsigned int clk, unsigned int width) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + uint32_t tmp1; + + rpi3_sdhost_set_clock(clk); + VERBOSE("rpi3_sdhost: Changing clock to %dHz for data mode\n", clk); + + if (width != MMC_BUS_WIDTH_4 && width != MMC_BUS_WIDTH_1) { + ERROR("rpi3_sdhost: width %d not supported\n", width); + return -(EOPNOTSUPP); + } + rpi3_sdhost_params.bus_width = width; + + tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG); + tmp1 &= ~(HC_HSTCF_EXTBUS_4BIT); + if (rpi3_sdhost_params.bus_width == MMC_BUS_WIDTH_4) + tmp1 |= HC_HSTCF_EXTBUS_4BIT; + + mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1); + tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG); + mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1 | + HC_HSTCF_SLOW_CARD | HC_HSTCF_INTBUS_WIDE); + + return 0; +} + +static int rpi3_sdhost_prepare(int lba, uintptr_t buf, size_t size) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + size_t blocks; + size_t blocksize; + + if (size < 512) { + blocksize = size; + blocks = 1; + } else { + blocksize = 512; + blocks = size / blocksize; + if (size % blocksize != 0) + blocks++; + } + + rpi3_drain_fifo(); + + mmio_write_32(reg_base + HC_BLOCKSIZE, blocksize); + mmio_write_32(reg_base + HC_BLOCKCOUNT, blocks); + udelay(100); + return 0; +} + +static int rpi3_sdhost_read(int lba, uintptr_t buf, size_t size) +{ + int err = 0; + uint32_t *buf1 = ((uint32_t *) buf); + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + int timeout = 100000; + int remaining_words = 0; + + for (int i = 0; i < size / 4; i++) { + volatile int t = timeout; + uint32_t hsts_err; + + while ((mmio_read_32(reg_base + HC_HOSTSTATUS) + & HC_HSTST_HAVEDATA) == 0) { + if (t == 0) { + ERROR("rpi3_sdhost: fifo timeout after %dus\n", + timeout); + err = -(ETIMEDOUT); + break; + } + t--; + udelay(10); + } + if (t == 0) + break; + + uint32_t data = mmio_read_32(reg_base + HC_DATAPORT); + + hsts_err = mmio_read_32(reg_base + HC_HOSTSTATUS) + & HC_HSTST_MASK_ERROR_ALL; + if (hsts_err) { + ERROR("rpi3_sdhost: transfer FIFO word %d: 0x%x\n", + i, + mmio_read_32(reg_base + HC_HOSTSTATUS)); + rpi3_sdhost_print_regs(); + + err = -(EILSEQ); + + /* clean the error status */ + mmio_write_32(reg_base + HC_HOSTSTATUS, hsts_err); + } + + if (buf1) + buf1[i] = data; + + /* speeding up if the remaining words are still a lot */ + remaining_words = (mmio_read_32(reg_base + HC_DEBUG) >> 4) + & HC_DBG_FIFO_THRESH_MASK; + if (remaining_words >= 7) + continue; + + /* delay. slowing down the read process */ + udelay(100); + } + + /* We decide to stop by ourselves. + * It is because MMC_CMD(18) -> MMC_CMD(13) -> MMC_CMD(12) + * doesn't work for RPi3 SDHost. + */ + if (rpi3_sdhost_params.current_cmd == MMC_CMD(18)) + send_command_decorated(MMC_CMD(12), 0); + + return err; +} + +static int rpi3_sdhost_write(int lba, uintptr_t buf, size_t size) +{ + uint32_t *buf1 = ((uint32_t *) buf); + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + int err = 0; + int remaining_words = 0; + + for (int i = 0; i < size / 4; i++) { + uint32_t hsts_err; + uint32_t data = buf1[i]; + uint32_t dbg; + uint32_t fsm_state; + + mmio_write_32(reg_base + HC_DATAPORT, data); + + dbg = mmio_read_32(reg_base + HC_DEBUG); + fsm_state = dbg & HC_DBG_FSM_MASK; + if (fsm_state != HC_DBG_FSM_WRITEDATA + && fsm_state != HC_DBG_FSM_WRITESTART1 + && fsm_state != HC_DBG_FSM_WRITESTART2 + && fsm_state != HC_DBG_FSM_WRITECRC + && fsm_state != HC_DBG_FSM_WRITEWAIT1 + && fsm_state != HC_DBG_FSM_WRITEWAIT2) { + hsts_err = mmio_read_32(reg_base + HC_HOSTSTATUS) + & HC_HSTST_MASK_ERROR_ALL; + if (hsts_err) + err = -(EILSEQ); + } + + /* speeding up if the remaining words are not many */ + remaining_words = (mmio_read_32(reg_base + HC_DEBUG) >> 4) + & HC_DBG_FIFO_THRESH_MASK; + if (remaining_words <= 4) + continue; + + udelay(100); + } + + /* We decide to stop by ourselves. + * It is because MMC_CMD(25) -> MMC_CMD(13) -> MMC_CMD(12) + * doesn't work for RPi3 SDHost. + */ + if (rpi3_sdhost_params.current_cmd == MMC_CMD(25)) + send_command_decorated(MMC_CMD(12), 0); + + return err; +} + +void rpi3_sdhost_init(struct rpi3_sdhost_params *params, + struct mmc_device_info *mmc_dev_info) +{ + assert((params != 0) && + ((params->reg_base & MMC_BLOCK_MASK) == 0)); + + memcpy(&rpi3_sdhost_params, params, sizeof(struct rpi3_sdhost_params)); + + /* backup GPIO 48 to 53 configurations */ + for (int i = 48; i <= 53; i++) { + rpi3_sdhost_params.gpio48_pinselect[i - 48] + = rpi3_gpio_get_select(i); + VERBOSE("rpi3_sdhost: Original GPIO state %d: %d\n", + i, + rpi3_sdhost_params.gpio48_pinselect[i - 48]); + } + + /* setting pull resistors for 48 to 53. + * It is debatable to set SD_CLK to UP or NONE. We massively + * tested different brands of SD Cards and found NONE works + * most stable. + * + * GPIO 48 (SD_CLK) to GPIO_PULL_NONE + * GPIO 49 (SD_CMD) to GPIO_PULL_UP + * GPIO 50 (SD_D0) to GPIO_PULL_UP + * GPIO 51 (SD_D1) to GPIO_PULL_UP + * GPIO 52 (SD_D2) to GPIO_PULL_UP + * GPIO 53 (SD_D3) to GPIO_PULL_UP + */ + gpio_set_pull(48, GPIO_PULL_NONE); + for (int i = 49; i <= 53; i++) + gpio_set_pull(i, GPIO_PULL_UP); + + /* Set pin 48-53 to alt-0. It means route SDHOST to card slot */ + for (int i = 48; i <= 53; i++) + rpi3_gpio_set_select(i, RPI3_GPIO_FUNC_ALT0); + + mmc_init(&rpi3_sdhost_ops, params->clk_rate, params->bus_width, + params->flags, mmc_dev_info); +} + +void rpi3_sdhost_stop(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + VERBOSE("rpi3_sdhost: Shutting down: drain FIFO out\n"); + rpi3_drain_fifo(); + + VERBOSE("rpi3_sdhost: Shutting down: slowing down the clock\n"); + mmio_write_32(reg_base+HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_SLOWVAL); + udelay(500); + + VERBOSE("rpi3_sdhost: Shutting down: put SDHost into idle state\n"); + send_command_decorated(MMC_CMD(0), 0); + udelay(500); + + mmio_write_32(reg_base + HC_COMMAND, 0); + mmio_write_32(reg_base + HC_ARGUMENT, 0); + mmio_write_32(reg_base + HC_TIMEOUTCOUNTER, HC_TIMEOUT_IDLE); + mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_STOPVAL); + + udelay(100); + + mmio_write_32(reg_base + HC_POWER, 0); + mmio_write_32(reg_base + HC_HOSTCONFIG, 0); + mmio_write_32(reg_base + HC_BLOCKSIZE, 0x400); + mmio_write_32(reg_base + HC_BLOCKCOUNT, 0); + mmio_write_32(reg_base + HC_HOSTSTATUS, 0x7f8); + + mmio_write_32(reg_base + HC_COMMAND, 0); + mmio_write_32(reg_base + HC_ARGUMENT, 0); + + udelay(100); + + /* Restore the pinmux to original state */ + for (int i = 48; i <= 53; i++) { + rpi3_gpio_set_select(i, + rpi3_sdhost_params.gpio48_pinselect[i-48]); + } + + /* Reset the pull resistors before entering BL33. + * GPIO 48 (SD_CLK) to GPIO_PULL_UP + * GPIO 49 (SD_CMD) to GPIO_PULL_UP + * GPIO 50 (SD_D0) to GPIO_PULL_UP + * GPIO 51 (SD_D1) to GPIO_PULL_UP + * GPIO 52 (SD_D2) to GPIO_PULL_UP + * GPIO 53 (SD_D3) to GPIO_PULL_UP + */ + for (int i = 48; i <= 53; i++) + gpio_set_pull(i, GPIO_PULL_UP); +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/base.c b/arm-trusted-firmware/drivers/scmi-msg/base.c new file mode 100644 index 0000000..2d72034 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/base.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include + +#include +#include +#include +#include + +#include "common.h" + +static bool message_id_is_supported(unsigned int message_id); + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_BASE, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + size_t protocol_count = plat_scmi_protocol_count(); + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* Null agent count since agent discovery is not supported */ + .attributes = SCMI_BASE_PROTOCOL_ATTRIBUTES(protocol_count, 0U), + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0U, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_vendor(struct scmi_msg *msg) +{ + const char *name = plat_scmi_vendor_name(); + struct scmi_base_discover_vendor_p2a return_values = { + .status = SCMI_SUCCESS, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + COPY_NAME_IDENTIFIER(return_values.vendor_identifier, name); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_sub_vendor(struct scmi_msg *msg) +{ + const char *name = plat_scmi_sub_vendor_name(); + struct scmi_base_discover_sub_vendor_p2a return_values = { + .status = SCMI_SUCCESS, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + COPY_NAME_IDENTIFIER(return_values.sub_vendor_identifier, name); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_implementation_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_IMPL_VERSION, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static unsigned int count_protocols_in_list(const uint8_t *protocol_list) +{ + unsigned int count = 0U; + + if (protocol_list != NULL) { + while (protocol_list[count] != 0U) { + count++; + } + } + + return count; +} + +#define MAX_PROTOCOL_IN_LIST 8U + +static void discover_list_protocols(struct scmi_msg *msg) +{ + const struct scmi_base_discover_list_protocols_a2p *a2p = NULL; + struct scmi_base_discover_list_protocols_p2a p2a = { + .status = SCMI_SUCCESS, + }; + uint8_t outargs[sizeof(p2a) + MAX_PROTOCOL_IN_LIST] = { 0U }; + const uint8_t *list = NULL; + unsigned int count = 0U; + + if (msg->in_size != sizeof(*a2p)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + assert(msg->out_size > sizeof(outargs)); + + a2p = (void *)msg->in; + + list = plat_scmi_protocol_list(msg->agent_id); + count = count_protocols_in_list(list); + if (count > a2p->skip) { + count = MIN(count - a2p->skip, MAX_PROTOCOL_IN_LIST); + } else { + count = 0U; + } + + p2a.num_protocols = count; + + memcpy(outargs, &p2a, sizeof(p2a)); + memcpy(outargs + sizeof(p2a), list + a2p->skip, count); + + scmi_write_response(msg, outargs, sizeof(outargs)); +} + +static const scmi_msg_handler_t scmi_base_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_BASE_DISCOVER_VENDOR] = discover_vendor, + [SCMI_BASE_DISCOVER_SUB_VENDOR] = discover_sub_vendor, + [SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION] = + discover_implementation_version, + [SCMI_BASE_DISCOVER_LIST_PROTOCOLS] = discover_list_protocols, +}; + +static bool message_id_is_supported(unsigned int message_id) +{ + return (message_id < ARRAY_SIZE(scmi_base_handler_table)) && + (scmi_base_handler_table[message_id] != NULL); +} + +scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg) +{ + unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); + + if (message_id >= ARRAY_SIZE(scmi_base_handler_table)) { + VERBOSE("Base handle not found %u\n", msg->message_id); + return NULL; + } + + return scmi_base_handler_table[message_id]; +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/base.h b/arm-trusted-firmware/drivers/scmi-msg/base.h new file mode 100644 index 0000000..c4a9c64 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/base.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ + +#ifndef SCMI_MSG_BASE_H +#define SCMI_MSG_BASE_H + +#include + +#define SCMI_PROTOCOL_VERSION_BASE 0x20000U + +#define SCMI_DEFAULT_STRING_LENGTH 16U + +enum scmi_base_message_id { + SCMI_BASE_DISCOVER_VENDOR = 0x003, + SCMI_BASE_DISCOVER_SUB_VENDOR = 0x004, + SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION = 0x005, + SCMI_BASE_DISCOVER_LIST_PROTOCOLS = 0x006, + SCMI_BASE_DISCOVER_AGENT = 0x007, + SCMI_BASE_NOTIFY_ERRORS = 0x008, +}; + +/* + * PROTOCOL_ATTRIBUTES + */ + +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS 0 +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS 8 + +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK 0xFFU +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK 0xFF00U + +#define SCMI_BASE_PROTOCOL_ATTRIBUTES(NUM_PROTOCOLS, NUM_AGENTS) \ + ((((NUM_PROTOCOLS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS) & \ + SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK) | \ + (((NUM_AGENTS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS) & \ + SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK)) + +/* + * BASE_DISCOVER_VENDOR + */ +struct scmi_base_discover_vendor_p2a { + int32_t status; + char vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; +}; + +/* + * BASE_DISCOVER_SUB_VENDOR + */ +struct scmi_base_discover_sub_vendor_p2a { + int32_t status; + char sub_vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; +}; + +/* + * BASE_DISCOVER_IMPLEMENTATION_VERSION + * No special structure right now, see protocol_version. + */ + +/* + * BASE_DISCOVER_LIST_PROTOCOLS + */ +struct scmi_base_discover_list_protocols_a2p { + uint32_t skip; +}; + +struct scmi_base_discover_list_protocols_p2a { + int32_t status; + uint32_t num_protocols; + uint32_t protocols[]; +}; + +#endif /* SCMI_MSG_BASE_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/clock.c b/arm-trusted-firmware/drivers/scmi-msg/clock.c new file mode 100644 index 0000000..e96cede --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/clock.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include + +#include +#include +#include + +#include "common.h" + +#pragma weak plat_scmi_clock_count +#pragma weak plat_scmi_clock_get_name +#pragma weak plat_scmi_clock_rates_array +#pragma weak plat_scmi_clock_rates_by_step +#pragma weak plat_scmi_clock_get_rate +#pragma weak plat_scmi_clock_set_rate +#pragma weak plat_scmi_clock_get_state +#pragma weak plat_scmi_clock_set_state + +static bool message_id_is_supported(unsigned int message_id); + +size_t plat_scmi_clock_count(unsigned int agent_id __unused) +{ + return 0U; +} + +const char *plat_scmi_clock_get_name(unsigned int agent_id __unused, + unsigned int scmi_id __unused) +{ + return NULL; +} + +int32_t plat_scmi_clock_rates_array(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + unsigned long *rates __unused, + size_t *nb_elts __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + unsigned long *steps __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +unsigned long plat_scmi_clock_get_rate(unsigned int agent_id __unused, + unsigned int scmi_id __unused) +{ + return 0U; +} + +int32_t plat_scmi_clock_set_rate(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + unsigned long rate __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_clock_get_state(unsigned int agent_id __unused, + unsigned int scmi_id __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_clock_set_state(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + bool enable_not_disable __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_CLOCK, + }; + + if (msg->in_size != 0) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + size_t agent_count = plat_scmi_clock_count(msg->agent_id); + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1U, agent_count), + }; + + if (msg->in_size != 0) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0U, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_attributes(struct scmi_msg *msg) +{ + const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in; + struct scmi_clock_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + }; + const char *name = NULL; + unsigned int clock_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + + name = plat_scmi_clock_get_name(msg->agent_id, clock_id); + if (name == NULL) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + COPY_NAME_IDENTIFIER(return_values.clock_name, name); + + return_values.attributes = plat_scmi_clock_get_state(msg->agent_id, + clock_id); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_rate_get(struct scmi_msg *msg) +{ + const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in; + unsigned long rate = 0U; + struct scmi_clock_rate_get_p2a return_values = { + .status = SCMI_SUCCESS, + }; + unsigned int clock_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + rate = plat_scmi_clock_get_rate(msg->agent_id, clock_id); + + return_values.rate[0] = (uint32_t)rate; + return_values.rate[1] = (uint32_t)((uint64_t)rate >> 32); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_rate_set(struct scmi_msg *msg) +{ + const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in; + unsigned long rate = 0U; + int32_t status = 0; + unsigned int clock_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + rate = (unsigned long)(((uint64_t)in_args->rate[1] << 32) | + in_args->rate[0]); + + status = plat_scmi_clock_set_rate(msg->agent_id, clock_id, rate); + + scmi_status_response(msg, status); +} + +static void scmi_clock_config_set(struct scmi_msg *msg) +{ + const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in; + int32_t status = SCMI_GENERIC_ERROR; + bool enable = false; + unsigned int clock_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK; + + status = plat_scmi_clock_set_state(msg->agent_id, clock_id, enable); + + scmi_status_response(msg, status); +} + +#define RATES_ARRAY_SIZE_MAX (SCMI_PLAYLOAD_MAX - \ + sizeof(struct scmi_clock_describe_rates_p2a)) + +#define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \ + SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \ + SCMI_CLOCK_RATE_FORMAT_LIST, \ + (_rem_rates)) +#define SCMI_RATES_BY_STEP \ + SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3U, \ + SCMI_CLOCK_RATE_FORMAT_RANGE, \ + 0U) + +#define RATE_DESC_SIZE sizeof(struct scmi_clock_rate) + +static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates, + size_t nb_elt) +{ + uint32_t *out = (uint32_t *)(uintptr_t)dest; + size_t n; + + ASSERT_SYM_PTR_ALIGN(out); + + for (n = 0U; n < nb_elt; n++) { + out[2 * n] = (uint32_t)rates[n]; + out[2 * n + 1] = (uint32_t)((uint64_t)rates[n] >> 32); + } +} + +static void scmi_clock_describe_rates(struct scmi_msg *msg) +{ + const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in; + struct scmi_clock_describe_rates_p2a p2a = { + .status = SCMI_SUCCESS, + }; + size_t nb_rates; + int32_t status; + unsigned int clock_id; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + /* Platform may support array rate description */ + status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, NULL, + &nb_rates); + if (status == SCMI_SUCCESS) { + /* Currently 12 cells mex, so it's affordable for the stack */ + unsigned long plat_rates[RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE]; + size_t max_nb = RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE; + size_t ret_nb = MIN(nb_rates - in_args->rate_index, max_nb); + size_t rem_nb = nb_rates - in_args->rate_index - ret_nb; + + status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, + plat_rates, &ret_nb); + if (status == SCMI_SUCCESS) { + write_rate_desc_array_in_buffer(msg->out + sizeof(p2a), + plat_rates, ret_nb); + + p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(ret_nb, + rem_nb); + p2a.status = SCMI_SUCCESS; + + memcpy(msg->out, &p2a, sizeof(p2a)); + msg->out_size_out = sizeof(p2a) + + ret_nb * RATE_DESC_SIZE; + } + } else if (status == SCMI_NOT_SUPPORTED) { + unsigned long triplet[3] = { 0U, 0U, 0U }; + + /* Platform may support min§max/step triplet description */ + status = plat_scmi_clock_rates_by_step(msg->agent_id, clock_id, + triplet); + if (status == SCMI_SUCCESS) { + write_rate_desc_array_in_buffer(msg->out + sizeof(p2a), + triplet, 3U); + + p2a.num_rates_flags = SCMI_RATES_BY_STEP; + p2a.status = SCMI_SUCCESS; + + memcpy(msg->out, &p2a, sizeof(p2a)); + msg->out_size_out = sizeof(p2a) + (3U * RATE_DESC_SIZE); + } + } else { + /* Fallthrough generic exit sequence below with error status */ + } + + if (status != SCMI_SUCCESS) { + scmi_status_response(msg, status); + } else { + /* + * Message payload is already writen to msg->out, and + * msg->out_size_out updated. + */ + } +} + +static const scmi_msg_handler_t scmi_clock_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes, + [SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates, + [SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set, + [SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get, + [SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set, +}; + +static bool message_id_is_supported(size_t message_id) +{ + return (message_id < ARRAY_SIZE(scmi_clock_handler_table)) && + (scmi_clock_handler_table[message_id] != NULL); +} + +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg) +{ + const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table); + unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); + + if (message_id >= array_size) { + VERBOSE("Clock handle not found %u", msg->message_id); + return NULL; + } + + return scmi_clock_handler_table[message_id]; +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/clock.h b/arm-trusted-firmware/drivers/scmi-msg/clock.h new file mode 100644 index 0000000..a637934 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/clock.h @@ -0,0 +1,150 @@ +/* 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_CLOCK_H +#define SCMI_MSG_CLOCK_H + +#include + +#include + +#define SCMI_PROTOCOL_VERSION_CLOCK 0x20000U + +/* + * Identifiers of the SCMI Clock Management Protocol commands + */ +enum scmi_clock_command_id { + SCMI_CLOCK_ATTRIBUTES = 0x003, + SCMI_CLOCK_DESCRIBE_RATES = 0x004, + SCMI_CLOCK_RATE_SET = 0x005, + SCMI_CLOCK_RATE_GET = 0x006, + SCMI_CLOCK_CONFIG_SET = 0x007, +}; + +/* Protocol attributes */ +#define SCMI_CLOCK_CLOCK_COUNT_MASK GENMASK(15, 0) +#define SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK GENMASK(23, 16) + +#define SCMI_CLOCK_PROTOCOL_ATTRIBUTES(_max_pending, _clk_count) \ + ((((_max_pending) << 16) & SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK) | \ + (((_clk_count) & SCMI_CLOCK_CLOCK_COUNT_MASK))) + +struct scmi_clock_attributes_a2p { + uint32_t clock_id; +}; + +#define SCMI_CLOCK_NAME_LENGTH_MAX 16U + +struct scmi_clock_attributes_p2a { + int32_t status; + uint32_t attributes; + char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX]; +}; + +/* + * Clock Rate Get + */ + +struct scmi_clock_rate_get_a2p { + uint32_t clock_id; +}; + +struct scmi_clock_rate_get_p2a { + int32_t status; + uint32_t rate[2]; +}; + +/* + * Clock Rate Set + */ + +/* If set, set the new clock rate asynchronously */ +#define SCMI_CLOCK_RATE_SET_ASYNC_POS 0 +/* If set, do not send a delayed asynchronous response */ +#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS 1 +/* Round up, if set, otherwise round down */ +#define SCMI_CLOCK_RATE_SET_ROUND_UP_POS 2 +/* If set, the platform chooses the appropriate rounding mode */ +#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS 3 + +#define SCMI_CLOCK_RATE_SET_ASYNC_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ASYNC_POS) +#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_MASK \ + BIT(SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS) +#define SCMI_CLOCK_RATE_SET_ROUND_UP_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ROUND_UP_POS) +#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS) + +struct scmi_clock_rate_set_a2p { + uint32_t flags; + uint32_t clock_id; + uint32_t rate[2]; +}; + +struct scmi_clock_rate_set_p2a { + int32_t status; +}; + +/* + * Clock Config Set + */ + +#define SCMI_CLOCK_CONFIG_SET_ENABLE_POS 0 + +#define SCMI_CLOCK_CONFIG_SET_ENABLE_MASK \ + BIT(SCMI_CLOCK_CONFIG_SET_ENABLE_POS) + +struct scmi_clock_config_set_a2p { + uint32_t clock_id; + uint32_t attributes; +}; + +struct scmi_clock_config_set_p2a { + int32_t status; +}; + +/* + * Clock Describe Rates + */ + +#define SCMI_CLOCK_RATE_FORMAT_RANGE 1U +#define SCMI_CLOCK_RATE_FORMAT_LIST 0U + +#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK GENMASK_32(31, 16) +#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS 16 + +#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK BIT(12) +#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS 12 + +#define SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK GENMASK_32(11, 0) + +#define SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(_count, _fmt, _rem_rates) \ + ( \ + ((_count) & SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK) | \ + (((_rem_rates) << SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS) & \ + SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK) | \ + (((_fmt) << SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS) & \ + SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK) \ + ) + +struct scmi_clock_rate { + uint32_t low; + uint32_t high; +}; + +struct scmi_clock_describe_rates_a2p { + uint32_t clock_id; + uint32_t rate_index; +}; + +struct scmi_clock_describe_rates_p2a { + int32_t status; + uint32_t num_rates_flags; + struct scmi_clock_rate rates[]; +}; + +#endif /* SCMI_MSG_CLOCK_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/common.h b/arm-trusted-firmware/drivers/scmi-msg/common.h new file mode 100644 index 0000000..62f3087 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/common.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#ifndef SCMI_MSG_COMMON_H +#define SCMI_MSG_COMMON_H + +#include +#include +#include +#include + +#include "base.h" +#include "clock.h" +#include "power_domain.h" +#include "reset_domain.h" + +#define SCMI_VERSION 0x20000U +#define SCMI_IMPL_VERSION 0U + +#define SCMI_PLAYLOAD_MAX 92U + +/* + * Copy name identifier in target buffer following the SCMI specification + * that state name identifier shall be a null terminated string. + */ +#define COPY_NAME_IDENTIFIER(_dst_array, _name) \ + do { \ + assert(strlen(_name) < sizeof(_dst_array)); \ + strlcpy((_dst_array), (_name), sizeof(_dst_array)); \ + } while (0) + +/* Common command identifiers shared by all procotols */ +enum scmi_common_message_id { + SCMI_PROTOCOL_VERSION = 0x000, + SCMI_PROTOCOL_ATTRIBUTES = 0x001, + SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x002 +}; + +/* Common platform-to-agent (p2a) PROTOCOL_VERSION structure */ +struct scmi_protocol_version_p2a { + int32_t status; + uint32_t version; +}; + +/* Generic platform-to-agent (p2a) PROTOCOL_ATTRIBUTES structure */ +struct scmi_protocol_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* Generic agent-to-platform (a2p) PROTOCOL_MESSAGE_ATTRIBUTES structure */ +struct scmi_protocol_message_attributes_a2p { + uint32_t message_id; +}; + +/* Generic platform-to-agent (p2a) PROTOCOL_MESSAGE_ATTRIBUTES structure */ +struct scmi_protocol_message_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* + * struct scmi_msg - SCMI message context + * + * @agent_id: SCMI agent ID, safely set from secure world + * @protocol_id: SCMI protocol ID for the related message, set by caller agent + * @message_id: SCMI message ID for the related message, set by caller agent + * @in: Address of the incoming message payload copied in secure memory + * @in_size: Byte length of the incoming message payload, set by caller agent + * @out: Address of of the output message payload message in non-secure memory + * @out_size: Byte length of the provisionned output buffer + * @out_size_out: Byte length of the output message payload + */ +struct scmi_msg { + unsigned int agent_id; + unsigned int protocol_id; + unsigned int message_id; + char *in; + size_t in_size; + char *out; + size_t out_size; + size_t out_size_out; +}; + +/* + * Type scmi_msg_handler_t is used by procotol drivers to safely find + * the handler function for the incoming message ID. + */ +typedef void (*scmi_msg_handler_t)(struct scmi_msg *msg); + +/* + * scmi_msg_get_base_handler - Return a handler for a base message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg); + +/* + * scmi_msg_get_clock_handler - Return a handler for a clock message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg); + +/* + * scmi_msg_get_rstd_handler - Return a handler for a reset domain message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg); + +/* + * scmi_msg_get_pd_handler - Return a handler for a power domain message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg); + +/* + * Process Read, process and write response for input SCMI message + * + * @msg: SCMI message context + */ +void scmi_process_message(struct scmi_msg *msg); + +/* + * Write SCMI response payload to output message shared memory + * + * @msg: SCMI message context + * @payload: Output message payload + * @size: Byte size of output message payload + */ +void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size); + +/* + * Write status only SCMI response payload to output message shared memory + * + * @msg: SCMI message context + * @status: SCMI status value returned to caller + */ +void scmi_status_response(struct scmi_msg *msg, int32_t status); +#endif /* SCMI_MSG_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/entry.c b/arm-trusted-firmware/drivers/scmi-msg/entry.c new file mode 100644 index 0000000..399115c --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/entry.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ + +#include + +#include +#include + +#include "common.h" + +#pragma weak scmi_msg_get_clock_handler +#pragma weak scmi_msg_get_rstd_handler +#pragma weak scmi_msg_get_pd_handler +#pragma weak scmi_msg_get_voltage_handler + +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} + +scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} + +scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} + +scmi_msg_handler_t scmi_msg_get_voltage_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} + +void scmi_status_response(struct scmi_msg *msg, int32_t status) +{ + assert(msg->out && msg->out_size >= sizeof(int32_t)); + + memcpy(msg->out, &status, sizeof(int32_t)); + msg->out_size_out = sizeof(int32_t); +} + +void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size) +{ + /* + * Output payload shall be at least the size of the status + * Output buffer shall be at least be the size of the status + * Output paylaod shall fit in output buffer + */ + assert(payload && size >= sizeof(int32_t) && size <= msg->out_size && + msg->out && msg->out_size >= sizeof(int32_t)); + + memcpy(msg->out, payload, size); + msg->out_size_out = size; +} + +void scmi_process_message(struct scmi_msg *msg) +{ + scmi_msg_handler_t handler = NULL; + + switch (msg->protocol_id) { + case SCMI_PROTOCOL_ID_BASE: + handler = scmi_msg_get_base_handler(msg); + break; + case SCMI_PROTOCOL_ID_CLOCK: + handler = scmi_msg_get_clock_handler(msg); + break; + case SCMI_PROTOCOL_ID_RESET_DOMAIN: + handler = scmi_msg_get_rstd_handler(msg); + break; + case SCMI_PROTOCOL_ID_POWER_DOMAIN: + handler = scmi_msg_get_pd_handler(msg); + break; + default: + break; + } + + if (handler) { + handler(msg); + return; + } + + ERROR("Agent %u Protocol 0x%x Message 0x%x: not supported\n", + msg->agent_id, msg->protocol_id, msg->message_id); + + scmi_status_response(msg, SCMI_NOT_SUPPORTED); +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/power_domain.c b/arm-trusted-firmware/drivers/scmi-msg/power_domain.c new file mode 100644 index 0000000..c4e1289 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/power_domain.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include + +#include +#include +#include + +#include "common.h" + +#pragma weak plat_scmi_pd_count +#pragma weak plat_scmi_pd_get_name +#pragma weak plat_scmi_pd_get_state +#pragma weak plat_scmi_pd_set_state +#pragma weak plat_scmi_pd_statistics +#pragma weak plat_scmi_pd_get_attributes + +static bool message_id_is_supported(size_t message_id); + +size_t plat_scmi_pd_count(unsigned int agent_id __unused) +{ + return 0U; +} + +const char *plat_scmi_pd_get_name(unsigned int agent_id __unused, + unsigned int pd_id __unused) +{ + return NULL; +} + +unsigned int plat_scmi_pd_statistics(unsigned int agent_id __unused, + unsigned long *pd_id __unused) +{ + return 0U; +} + +unsigned int plat_scmi_pd_get_attributes(unsigned int agent_id __unused, + unsigned int pd_id __unused) +{ + return 0U; +} + +unsigned int plat_scmi_pd_get_state(unsigned int agent_id __unused, + unsigned int pd_id __unused) +{ + return 0U; +} + +int32_t plat_scmi_pd_set_state(unsigned int agent_id __unused, + unsigned int flags __unused, + unsigned int pd_id __unused, + unsigned int state __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_PD, + }; + + if (msg->in_size != 0) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + unsigned long addr = 0UL; + unsigned int len; + + struct scmi_protocol_attributes_p2a_pd return_values = { + .status = SCMI_SUCCESS, + }; + + if (msg->in_size != 0) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + return_values.attributes = plat_scmi_pd_count(msg->agent_id); + len = plat_scmi_pd_statistics(msg->agent_id, &addr); + if (len != 0U) { + return_values.statistics_addr_low = (unsigned int)addr; + return_values.statistics_addr_high = (uint32_t)(addr >> 32); + return_values.statistics_len = len; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0U, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_pd_attributes(struct scmi_msg *msg) +{ + const struct scmi_pd_attributes_a2p *in_args = (void *)msg->in; + struct scmi_pd_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + }; + const char *name = NULL; + unsigned int pd_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id); + + if (pd_id >= plat_scmi_pd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + name = plat_scmi_pd_get_name(msg->agent_id, pd_id); + if (name == NULL) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + COPY_NAME_IDENTIFIER(return_values.pd_name, name); + + return_values.attributes = plat_scmi_pd_get_attributes(msg->agent_id, pd_id); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_pd_state_get(struct scmi_msg *msg) +{ + const struct scmi_pd_state_get_a2p *in_args = (void *)msg->in; + unsigned int state = 0U; + struct scmi_pd_state_get_p2a return_values = { + .status = SCMI_SUCCESS, + }; + unsigned int pd_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id); + + if (pd_id >= plat_scmi_pd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + state = plat_scmi_pd_get_state(msg->agent_id, pd_id); + + return_values.power_state = state; + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_pd_state_set(struct scmi_msg *msg) +{ + const struct scmi_pd_state_set_a2p *in_args = (void *)msg->in; + unsigned int flags = 0U; + int32_t status = 0; + unsigned int pd_id = 0U; + unsigned int state = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id); + + if (pd_id >= plat_scmi_pd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + flags = SPECULATION_SAFE_VALUE(in_args->flags); + state = SPECULATION_SAFE_VALUE(in_args->power_state); + + status = plat_scmi_pd_set_state(msg->agent_id, flags, pd_id, state); + + scmi_status_response(msg, status); +} + +static const scmi_msg_handler_t scmi_pd_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_PD_ATTRIBUTES] = scmi_pd_attributes, + [SCMI_PD_STATE_SET] = scmi_pd_state_set, + [SCMI_PD_STATE_GET] = scmi_pd_state_get, +}; + +static bool message_id_is_supported(size_t message_id) +{ + return (message_id < ARRAY_SIZE(scmi_pd_handler_table)) && + (scmi_pd_handler_table[message_id] != NULL); +} + +scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg) +{ + const size_t array_size = ARRAY_SIZE(scmi_pd_handler_table); + unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); + + if (message_id >= array_size) { + VERBOSE("pd handle not found %u", msg->message_id); + return NULL; + } + + return scmi_pd_handler_table[message_id]; +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/power_domain.h b/arm-trusted-firmware/drivers/scmi-msg/power_domain.h new file mode 100644 index 0000000..48551fd --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/power_domain.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright 2021 NXP + */ + +#ifndef SCMI_MSG_PD_H +#define SCMI_MSG_PD_H + +#include + +#include + +#define SCMI_PROTOCOL_VERSION_PD 0x21000U + +/* + * Identifiers of the SCMI POWER DOMAIN Protocol commands + */ +enum scmi_pd_command_id { + SCMI_PD_ATTRIBUTES = 0x003, + SCMI_PD_STATE_SET = 0x004, + SCMI_PD_STATE_GET = 0x005, +}; + +/* Protocol attributes */ +struct scmi_pd_attributes_a2p { + uint32_t pd_id; +}; + +struct scmi_protocol_attributes_p2a_pd { + int32_t status; + uint32_t attributes; + uint32_t statistics_addr_low; + uint32_t statistics_addr_high; + uint32_t statistics_len; +}; + +#define SCMI_PD_NAME_LENGTH_MAX 16U + +struct scmi_pd_attributes_p2a { + int32_t status; + uint32_t attributes; + char pd_name[SCMI_PD_NAME_LENGTH_MAX]; +}; + +/* + * Power Domain State Get + */ + +struct scmi_pd_state_get_a2p { + uint32_t pd_id; +}; + +struct scmi_pd_state_get_p2a { + int32_t status; + uint32_t power_state; +}; + +/* + * Power domain State Set + */ + +struct scmi_pd_state_set_a2p { + uint32_t flags; + uint32_t pd_id; + uint32_t power_state; +}; + +struct scmi_pd_state_set_p2a { + int32_t status; +}; + +#endif /* SCMI_MSG_PD_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/reset_domain.c b/arm-trusted-firmware/drivers/scmi-msg/reset_domain.c new file mode 100644 index 0000000..76ac47e --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/reset_domain.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include + +#include +#include +#include +#include + +#include "common.h" + +static bool message_id_is_supported(unsigned int message_id); + +#pragma weak plat_scmi_rstd_count +#pragma weak plat_scmi_rstd_get_name +#pragma weak plat_scmi_rstd_autonomous +#pragma weak plat_scmi_rstd_set_state + +size_t plat_scmi_rstd_count(unsigned int agent_id __unused) +{ + return 0U; +} + +const char *plat_scmi_rstd_get_name(unsigned int agent_id __unused, + unsigned int scmi_id __unused) +{ + return NULL; +} + +int32_t plat_scmi_rstd_autonomous(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + unsigned int state __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_rstd_set_state(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + bool assert_not_deassert __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = plat_scmi_rstd_count(msg->agent_id), + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0U, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void reset_domain_attributes(struct scmi_msg *msg) +{ + struct scmi_reset_domain_attributes_a2p *in_args = (void *)msg->in; + struct scmi_reset_domain_attributes_p2a return_values; + const char *name = NULL; + unsigned int domain_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id); + + if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + name = plat_scmi_rstd_get_name(msg->agent_id, domain_id); + if (name == NULL) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + zeromem(&return_values, sizeof(return_values)); + COPY_NAME_IDENTIFIER(return_values.name, name); + return_values.status = SCMI_SUCCESS; + return_values.flags = 0U; /* Async and Notif are not supported */ + return_values.latency = SCMI_RESET_DOMAIN_ATTR_UNK_LAT; + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void reset_request(struct scmi_msg *msg) +{ + struct scmi_reset_domain_request_a2p *in_args = (void *)msg->in; + struct scmi_reset_domain_request_p2a out_args = { + .status = SCMI_SUCCESS, + }; + unsigned int domain_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id); + + if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + if ((in_args->flags & SCMI_RESET_DOMAIN_AUTO) != 0U) { + out_args.status = plat_scmi_rstd_autonomous(msg->agent_id, + domain_id, + in_args->reset_state); + } else if ((in_args->flags & SCMI_RESET_DOMAIN_EXPLICIT) != 0U) { + out_args.status = plat_scmi_rstd_set_state(msg->agent_id, + domain_id, true); + } else { + out_args.status = plat_scmi_rstd_set_state(msg->agent_id, + domain_id, false); + } + + if (out_args.status != SCMI_SUCCESS) { + scmi_status_response(msg, out_args.status); + } else { + scmi_write_response(msg, &out_args, sizeof(out_args)); + } +} + +static const scmi_msg_handler_t scmi_rstd_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_RESET_DOMAIN_ATTRIBUTES] = reset_domain_attributes, + [SCMI_RESET_DOMAIN_REQUEST] = reset_request, +}; + +static bool message_id_is_supported(unsigned int message_id) +{ + return (message_id < ARRAY_SIZE(scmi_rstd_handler_table)) && + (scmi_rstd_handler_table[message_id] != NULL); +} + +scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg) +{ + unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); + + if (message_id >= ARRAY_SIZE(scmi_rstd_handler_table)) { + VERBOSE("Reset domain handle not found %u\n", msg->message_id); + return NULL; + } + + return scmi_rstd_handler_table[message_id]; +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/reset_domain.h b/arm-trusted-firmware/drivers/scmi-msg/reset_domain.h new file mode 100644 index 0000000..47bee5e --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/reset_domain.h @@ -0,0 +1,122 @@ +/* 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_RESET_DOMAIN_H +#define SCMI_MSG_RESET_DOMAIN_H + +#include +#include + +#include + +#define SCMI_PROTOCOL_VERSION_RESET_DOMAIN 0x10000U + +#define SCMI_RESET_STATE_ARCH BIT(31) +#define SCMI_RESET_STATE_IMPL 0U + +/* + * Identifiers of the SCMI Reset Domain Management Protocol commands + */ +enum scmi_reset_domain_command_id { + SCMI_RESET_DOMAIN_ATTRIBUTES = 0x03, + SCMI_RESET_DOMAIN_REQUEST = 0x04, + SCMI_RESET_DOMAIN_NOTIFY = 0x05, +}; + +/* + * Identifiers of the SCMI Reset Domain Management Protocol responses + */ +enum scmi_reset_domain_response_id { + SCMI_RESET_ISSUED = 0x00, + SCMI_RESET_COMPLETE = 0x04, +}; + +/* + * PROTOCOL_ATTRIBUTES + */ + +#define SCMI_RESET_DOMAIN_COUNT_MASK GENMASK_32(15, 0) + +struct scmi_reset_domain_protocol_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* Value for scmi_reset_domain_attributes_p2a:flags */ +#define SCMI_RESET_DOMAIN_ATTR_ASYNC BIT(31) +#define SCMI_RESET_DOMAIN_ATTR_NOTIF BIT(30) + +/* Value for scmi_reset_domain_attributes_p2a:latency */ +#define SCMI_RESET_DOMAIN_ATTR_UNK_LAT 0x7fffffffU +#define SCMI_RESET_DOMAIN_ATTR_MAX_LAT 0x7ffffffeU + +/* Macro for scmi_reset_domain_attributes_p2a:name */ +#define SCMI_RESET_DOMAIN_ATTR_NAME_SZ 16U + +struct scmi_reset_domain_attributes_a2p { + uint32_t domain_id; +}; + +struct scmi_reset_domain_attributes_p2a { + int32_t status; + uint32_t flags; + uint32_t latency; + char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ]; +}; + +/* + * RESET + */ + +/* Values for scmi_reset_domain_request_a2p:flags */ +#define SCMI_RESET_DOMAIN_ASYNC BIT(2) +#define SCMI_RESET_DOMAIN_EXPLICIT BIT(1) +#define SCMI_RESET_DOMAIN_AUTO BIT(0) + +struct scmi_reset_domain_request_a2p { + uint32_t domain_id; + uint32_t flags; + uint32_t reset_state; +}; + +struct scmi_reset_domain_request_p2a { + int32_t status; +}; + +/* + * RESET_NOTIFY + */ + +/* Values for scmi_reset_notify_p2a:flags */ +#define SCMI_RESET_DOMAIN_DO_NOTIFY BIT(0) + +struct scmi_reset_domain_notify_a2p { + uint32_t domain_id; + uint32_t notify_enable; +}; + +struct scmi_reset_domain_notify_p2a { + int32_t status; +}; + +/* + * RESET_COMPLETE + */ + +struct scmi_reset_domain_complete_p2a { + int32_t status; + uint32_t domain_id; +}; + +/* + * RESET_ISSUED + */ + +struct scmi_reset_domain_issued_p2a { + uint32_t domain_id; + uint32_t reset_state; +}; + +#endif /* SCMI_MSG_RESET_DOMAIN_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/smt.c b/arm-trusted-firmware/drivers/scmi-msg/smt.c new file mode 100644 index 0000000..9b079c7 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/smt.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/* Legacy SMT/SCMI messages are 128 bytes at most including SMT header */ +#define SCMI_PLAYLOAD_MAX 92U +#define SCMI_PLAYLOAD_U32_MAX (SCMI_PLAYLOAD_MAX / sizeof(uint32_t)) + +/** + * struct smt_header - SMT formatted header for SMT base shared memory transfer + * + * @status: Bit flags, see SMT_STATUS_* + * @flags: Bit flags, see SMT_FLAG_* + * @length: Byte size of message payload (variable) + ::message_header (32bit) + * payload: SCMI message payload data + */ +struct smt_header { + uint32_t reserved0; + uint32_t status; + uint64_t reserved1; + uint32_t flags; + uint32_t length; /* message_header + payload */ + uint32_t message_header; + uint32_t payload[]; +}; + +CASSERT(SCMI_PLAYLOAD_MAX + sizeof(struct smt_header) <= SMT_BUF_SLOT_SIZE, + assert_scmi_message_max_length_fits_in_smt_buffer_slot); + +/* Flag set in smt_header::status when SMT does not contain pending message */ +#define SMT_STATUS_FREE BIT_32(0) +/* Flag set in smt_header::status when SMT reports an error */ +#define SMT_STATUS_ERROR BIT_32(1) + +/* Flag set in smt_header::flags when SMT uses interrupts */ +#define SMT_FLAG_INTR_ENABLED BIT_32(1) + +/* Bit fields packed in smt_header::message_header */ +#define SMT_MSG_ID_MASK GENMASK_32(7, 0) +#define SMT_HDR_MSG_ID(_hdr) ((_hdr) & SMT_MSG_ID_MASK) + +#define SMT_MSG_TYPE_MASK GENMASK_32(9, 8) +#define SMT_HDR_TYPE_ID(_hdr) (((_hdr) & SMT_MSG_TYPE_MASK) >> 8) + +#define SMT_MSG_PROT_ID_MASK GENMASK_32(17, 10) +#define SMT_HDR_PROT_ID(_hdr) (((_hdr) & SMT_MSG_PROT_ID_MASK) >> 10) + +/* + * Provision input message payload buffers for fastcall SMC context entries + * and for interrupt context execution entries. + */ +static uint32_t fast_smc_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX]; +static uint32_t interrupt_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX]; + +/* SMP protection on channel access */ +static struct spinlock smt_channels_lock; + +/* If channel is not busy, set busy and return true, otherwise return false */ +static bool channel_set_busy(struct scmi_msg_channel *chan) +{ + bool channel_is_busy; + + spin_lock(&smt_channels_lock); + + channel_is_busy = chan->busy; + + if (!channel_is_busy) { + chan->busy = true; + } + + spin_unlock(&smt_channels_lock); + + return !channel_is_busy; +} + +static void channel_release_busy(struct scmi_msg_channel *chan) +{ + chan->busy = false; +} + +static struct smt_header *channel_to_smt_hdr(struct scmi_msg_channel *chan) +{ + return (struct smt_header *)chan->shm_addr; +} + +/* + * Creates a SCMI message instance in secure memory and pushes it in the SCMI + * message drivers. Message structure contains SCMI protocol meta-data and + * references to input payload in secure memory and output message buffer + * in shared memory. + */ +static void scmi_proccess_smt(unsigned int agent_id, uint32_t *payload_buf) +{ + struct scmi_msg_channel *chan; + struct smt_header *smt_hdr; + size_t in_payload_size; + uint32_t smt_status; + struct scmi_msg msg; + bool error = true; + + chan = plat_scmi_get_channel(agent_id); + if (chan == NULL) { + return; + } + + smt_hdr = channel_to_smt_hdr(chan); + assert(smt_hdr); + + smt_status = __atomic_load_n(&smt_hdr->status, __ATOMIC_RELAXED); + + if (!channel_set_busy(chan)) { + VERBOSE("SCMI channel %u busy", agent_id); + goto out; + } + + in_payload_size = __atomic_load_n(&smt_hdr->length, __ATOMIC_RELAXED) - + sizeof(smt_hdr->message_header); + + if (in_payload_size > SCMI_PLAYLOAD_MAX) { + VERBOSE("SCMI payload too big %zu", in_payload_size); + goto out; + } + + if ((smt_status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)) != 0U) { + VERBOSE("SCMI channel bad status 0x%x", + smt_hdr->status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)); + goto out; + } + + /* Fill message */ + zeromem(&msg, sizeof(msg)); + msg.in = (char *)payload_buf; + msg.in_size = in_payload_size; + msg.out = (char *)smt_hdr->payload; + msg.out_size = chan->shm_size - sizeof(*smt_hdr); + + assert((msg.out != NULL) && (msg.out_size >= sizeof(int32_t))); + + /* Here the payload is copied in secure memory */ + memcpy(msg.in, smt_hdr->payload, in_payload_size); + + msg.protocol_id = SMT_HDR_PROT_ID(smt_hdr->message_header); + msg.message_id = SMT_HDR_MSG_ID(smt_hdr->message_header); + msg.agent_id = agent_id; + + scmi_process_message(&msg); + + /* Update message length with the length of the response message */ + smt_hdr->length = msg.out_size_out + sizeof(smt_hdr->message_header); + + channel_release_busy(chan); + error = false; + +out: + if (error) { + VERBOSE("SCMI error"); + smt_hdr->status |= SMT_STATUS_ERROR | SMT_STATUS_FREE; + } else { + smt_hdr->status |= SMT_STATUS_FREE; + } +} + +void scmi_smt_fastcall_smc_entry(unsigned int agent_id) +{ + scmi_proccess_smt(agent_id, + fast_smc_payload[plat_my_core_pos()]); +} + +void scmi_smt_interrupt_entry(unsigned int agent_id) +{ + scmi_proccess_smt(agent_id, + interrupt_payload[plat_my_core_pos()]); +} + +/* Init a SMT header for a shared memory buffer: state it a free/no-error */ +void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan) +{ + if (chan != NULL) { + struct smt_header *smt_header = channel_to_smt_hdr(chan); + + if (smt_header != NULL) { + memset(smt_header, 0, sizeof(*smt_header)); + smt_header->status = SMT_STATUS_FREE; + + return; + } + } + + panic(); +} diff --git a/arm-trusted-firmware/drivers/st/bsec/bsec2.c b/arm-trusted-firmware/drivers/st/bsec/bsec2.c new file mode 100644 index 0000000..68d3a5b --- /dev/null +++ b/arm-trusted-firmware/drivers/st/bsec/bsec2.c @@ -0,0 +1,961 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BSEC_IP_VERSION_1_1 U(0x11) +#define BSEC_IP_VERSION_2_0 U(0x20) +#define BSEC_IP_ID_2 U(0x100032) + +#define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT) + +static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __unused; + +static uint32_t bsec_power_safmem(bool power); + +/* BSEC access protection */ +static spinlock_t bsec_spinlock; +static uintptr_t bsec_base; + +static void bsec_lock(void) +{ + if (stm32mp_lock_available()) { + spin_lock(&bsec_spinlock); + } +} + +static void bsec_unlock(void) +{ + if (stm32mp_lock_available()) { + spin_unlock(&bsec_spinlock); + } +} + +static bool is_otp_invalid_mode(void) +{ + bool ret = ((bsec_get_status() & BSEC_MODE_INVALID) == BSEC_MODE_INVALID); + + if (ret) { + ERROR("OTP mode is OTP-INVALID\n"); + } + + return ret; +} + +#if defined(IMAGE_BL32) +static int bsec_get_dt_node(struct dt_node_info *info) +{ + int node; + + node = dt_get_node(info, -1, DT_BSEC_COMPAT); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + return node; +} + +static void enable_non_secure_access(uint32_t otp) +{ + otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT); + + if (bsec_shadow_register(otp) != BSEC_OK) { + panic(); + } +} + +static bool non_secure_can_access(uint32_t otp) +{ + return (otp_nsec_access[otp / __WORD_BIT] & + BIT(otp % __WORD_BIT)) != 0U; +} + +static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node) +{ + int bsec_subnode; + + fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { + const fdt32_t *cuint; + uint32_t otp; + uint32_t i; + uint32_t size; + uint32_t offset; + uint32_t length; + + cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL); + if (cuint == NULL) { + panic(); + } + + offset = fdt32_to_cpu(*cuint); + cuint++; + length = fdt32_to_cpu(*cuint); + + otp = offset / sizeof(uint32_t); + + if (otp < STM32MP1_UPPER_OTP_START) { + unsigned int otp_end = round_up(offset + length, + sizeof(uint32_t)) / + sizeof(uint32_t); + + if (otp_end > STM32MP1_UPPER_OTP_START) { + /* + * OTP crosses Lower/Upper boundary, consider + * only the upper part. + */ + otp = STM32MP1_UPPER_OTP_START; + length -= (STM32MP1_UPPER_OTP_START * + sizeof(uint32_t)) - offset; + offset = STM32MP1_UPPER_OTP_START * + sizeof(uint32_t); + + WARN("OTP crosses Lower/Upper boundary\n"); + } else { + continue; + } + } + + if ((fdt_getprop(fdt, bsec_subnode, + "st,non-secure-otp", NULL)) == NULL) { + continue; + } + + if (((offset % sizeof(uint32_t)) != 0U) || + ((length % sizeof(uint32_t)) != 0U)) { + ERROR("Unaligned non-secure OTP\n"); + panic(); + } + + size = length / sizeof(uint32_t); + + for (i = otp; i < (otp + size); i++) { + enable_non_secure_access(i); + } + } +} + +static void bsec_late_init(void) +{ + void *fdt; + int node; + struct dt_node_info bsec_info; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + node = bsec_get_dt_node(&bsec_info); + if (node < 0) { + panic(); + } + + assert(bsec_base == bsec_info.base); + + bsec_dt_otp_nsec_access(fdt, node); +} +#endif + +static uint32_t otp_bank_offset(uint32_t otp) +{ + assert(otp <= STM32MP1_OTP_MAX_ID); + + return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) * + sizeof(uint32_t); +} + +/* + * bsec_check_error: check BSEC error status. + * otp: OTP number. + * check_disturbed: check only error (false), + * or error and disturbed status (true). + * return value: BSEC_OK if no error. + */ +static uint32_t bsec_check_error(uint32_t otp, bool check_disturbed) +{ + uint32_t bit = BIT(otp & BSEC_OTP_MASK); + uint32_t bank = otp_bank_offset(otp); + + if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) { + return BSEC_ERROR; + } + + if (!check_disturbed) { + return BSEC_OK; + } + + if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { + return BSEC_DISTURBED; + } + + return BSEC_OK; +} + +/* + * bsec_probe: initialize BSEC driver. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_probe(void) +{ + bsec_base = BSEC_BASE; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if ((((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_1_1) && + ((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_2_0)) || + (bsec_get_id() != BSEC_IP_ID_2)) { + panic(); + } + +#if defined(IMAGE_BL32) + bsec_late_init(); +#endif + return BSEC_OK; +} + +/* + * bsec_get_base: return BSEC base address. + */ +uint32_t bsec_get_base(void) +{ + return bsec_base; +} + +/* + * bsec_set_config: enable and configure BSEC. + * cfg: pointer to param structure used to set register. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_config(struct bsec_config *cfg) +{ + uint32_t value; + uint32_t result; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) & + BSEC_CONF_FRQ_MASK) | + (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) & + BSEC_CONF_PRG_WIDTH_MASK) | + (((uint32_t)cfg->tread << BSEC_CONF_TREAD_SHIFT) & + BSEC_CONF_TREAD_MASK)); + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, value); + + bsec_unlock(); + + result = bsec_power_safmem((bool)cfg->power & + BSEC_CONF_POWER_UP_MASK); + if (result != BSEC_OK) { + return result; + } + + value = ((((uint32_t)cfg->upper_otp_lock << UPPER_OTP_LOCK_SHIFT) & + UPPER_OTP_LOCK_MASK) | + (((uint32_t)cfg->den_lock << DENREG_LOCK_SHIFT) & + DENREG_LOCK_MASK) | + (((uint32_t)cfg->prog_lock << GPLOCK_LOCK_SHIFT) & + GPLOCK_LOCK_MASK)); + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_LOCK_OFF, value); + + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_get_config: return config parameters set in BSEC registers. + * cfg: config param return. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_get_config(struct bsec_config *cfg) +{ + uint32_t value; + + if (cfg == NULL) { + return BSEC_INVALID_PARAM; + } + + value = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); + cfg->power = (uint8_t)((value & BSEC_CONF_POWER_UP_MASK) >> + BSEC_CONF_POWER_UP_SHIFT); + cfg->freq = (uint8_t)((value & BSEC_CONF_FRQ_MASK) >> + BSEC_CONF_FRQ_SHIFT); + cfg->pulse_width = (uint8_t)((value & BSEC_CONF_PRG_WIDTH_MASK) >> + BSEC_CONF_PRG_WIDTH_SHIFT); + cfg->tread = (uint8_t)((value & BSEC_CONF_TREAD_MASK) >> + BSEC_CONF_TREAD_SHIFT); + + value = mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF); + cfg->upper_otp_lock = (uint8_t)((value & UPPER_OTP_LOCK_MASK) >> + UPPER_OTP_LOCK_SHIFT); + cfg->den_lock = (uint8_t)((value & DENREG_LOCK_MASK) >> + DENREG_LOCK_SHIFT); + cfg->prog_lock = (uint8_t)((value & GPLOCK_LOCK_MASK) >> + GPLOCK_LOCK_SHIFT); + + return BSEC_OK; +} + +/* + * bsec_shadow_register: copy SAFMEM OTP to BSEC data. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_shadow_register(uint32_t otp) +{ + uint32_t result; + bool value; + bool power_up = false; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + result = bsec_read_sr_lock(otp, &value); + if (result != BSEC_OK) { + ERROR("BSEC: %u Sticky-read bit read Error %u\n", otp, result); + return result; + } + + if (value) { + VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n", + otp); + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_READ); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + result = bsec_check_error(otp, true); + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_read_otp: read an OTP data value. + * val: read value. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) +{ + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + *val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF + + (otp * sizeof(uint32_t))); + + return BSEC_OK; +} + +/* + * bsec_write_otp: write value in BSEC data register. + * val: value to write. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_write_otp(uint32_t val, uint32_t otp) +{ + uint32_t result; + bool value; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + result = bsec_read_sw_lock(otp, &value); + if (result != BSEC_OK) { + ERROR("BSEC: %u Sticky-write bit read Error %u\n", otp, result); + return result; + } + + if (value) { + VERBOSE("BSEC: OTP %u is locked and write will be ignored\n", + otp); + } + + /* Ensure integrity of each register access sequence */ + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF + + (otp * sizeof(uint32_t)), val); + + bsec_unlock(); + + return result; +} + +/* + * bsec_program_otp: program a bit in SAFMEM after the prog. + * The OTP data is not refreshed. + * val: value to program. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_program_otp(uint32_t val, uint32_t otp) +{ + uint32_t result; + bool power_up = false; + bool sp_lock; + bool perm_lock; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + result = bsec_read_sp_lock(otp, &sp_lock); + if (result != BSEC_OK) { + ERROR("BSEC: %u Sticky-prog bit read Error %u\n", otp, result); + return result; + } + + result = bsec_read_permanent_lock(otp, &perm_lock); + if (result != BSEC_OK) { + ERROR("BSEC: %u permanent bit read Error %u\n", otp, result); + return result; + } + + if (sp_lock || perm_lock) { + WARN("BSEC: OTP locked, prog will be ignored\n"); + return BSEC_PROG_FAIL; + } + + if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) & + BIT(BSEC_LOCK_PROGRAM)) != 0U) { + WARN("BSEC: GPLOCK activated, prog will be ignored\n"); + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val); + + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { + result = BSEC_PROG_FAIL; + } else { + result = bsec_check_error(otp, true); + } + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_permanent_lock_otp(uint32_t otp) +{ + uint32_t result; + bool power_up = false; + uint32_t data; + uint32_t addr; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + if (otp < STM32MP1_UPPER_OTP_START) { + addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT; + data = DATA_LOWER_OTP_PERLOCK_BIT << + ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U); + } else { + addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U; + data = DATA_UPPER_OTP_PERLOCK_BIT << + (otp & DATA_UPPER_OTP_PERLOCK_MASK); + } + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data); + + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, + addr | BSEC_WRITE | BSEC_LOCK); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { + result = BSEC_PROG_FAIL; + } else { + result = bsec_check_error(otp, false); + } + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_write_debug_conf: write value in debug feature. + * to enable/disable debug service. + * val: value to write. + * return value: none. + */ +void bsec_write_debug_conf(uint32_t val) +{ + if (is_otp_invalid_mode()) { + return; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_DEN_OFF, val & BSEC_DEN_ALL_MSK); + bsec_unlock(); +} + +/* + * bsec_read_debug_conf: return debug configuration register value. + */ +uint32_t bsec_read_debug_conf(void) +{ + return mmio_read_32(bsec_base + BSEC_DEN_OFF); +} + +/* + * bsec_write_scratch: write value in scratch register. + * val: value to write. + * return value: none. + */ +void bsec_write_scratch(uint32_t val) +{ +#if defined(IMAGE_BL32) + if (is_otp_invalid_mode()) { + return; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_SCRATCH_OFF, val); + bsec_unlock(); +#else + mmio_write_32(BSEC_BASE + BSEC_SCRATCH_OFF, val); +#endif +} + +/* + * bsec_read_scratch: return scratch register value. + */ +uint32_t bsec_read_scratch(void) +{ + return mmio_read_32(bsec_base + BSEC_SCRATCH_OFF); +} + +/* + * bsec_get_status: return status register value. + */ +uint32_t bsec_get_status(void) +{ + return mmio_read_32(bsec_base + BSEC_OTP_STATUS_OFF); +} + +/* + * bsec_get_hw_conf: return hardware configuration register value. + */ +uint32_t bsec_get_hw_conf(void) +{ + return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF); +} + +/* + * bsec_get_version: return BSEC version register value. + */ +uint32_t bsec_get_version(void) +{ + return mmio_read_32(bsec_base + BSEC_IPVR_OFF); +} + +/* + * bsec_get_id: return BSEC ID register value. + */ +uint32_t bsec_get_id(void) +{ + return mmio_read_32(bsec_base + BSEC_IP_ID_OFF); +} + +/* + * bsec_get_magic_id: return BSEC magic number register value. + */ +uint32_t bsec_get_magic_id(void) +{ + return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF); +} + +/* + * bsec_set_sr_lock: set shadow-read lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sr_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, otp_mask); + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_read_sr_lock: read shadow-read lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sr_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); + + *value = ((bank_value & otp_mask) != 0U); + + return BSEC_OK; +} + +/* + * bsec_set_sw_lock: set shadow-write lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sw_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, otp_mask); + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_read_sw_lock: read shadow-write lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sw_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); + + *value = ((bank_value & otp_mask) != 0U); + + return BSEC_OK; +} + +/* + * bsec_set_sp_lock: set shadow-program lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sp_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, otp_mask); + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_read_sp_lock: read shadow-program lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sp_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank); + + *value = ((bank_value & otp_mask) != 0U); + + return BSEC_OK; +} + +/* + * bsec_read_permanent_lock: Read permanent lock status. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bank_value = mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank); + + *value = ((bank_value & otp_mask) != 0U); + + return BSEC_OK; +} + +/* + * bsec_otp_lock: Lock Upper OTP or Global Programming or Debug Enable. + * service: Service to lock, see header file. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_otp_lock(uint32_t service) +{ + uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + switch (service) { + case BSEC_LOCK_UPPER_OTP: + mmio_write_32(reg, BIT(BSEC_LOCK_UPPER_OTP)); + break; + case BSEC_LOCK_DEBUG: + mmio_write_32(reg, BIT(BSEC_LOCK_DEBUG)); + break; + case BSEC_LOCK_PROGRAM: + mmio_write_32(reg, BIT(BSEC_LOCK_PROGRAM)); + break; + default: + return BSEC_INVALID_PARAM; + } + + return BSEC_OK; +} + +/* + * bsec_power_safmem: Activate or deactivate SAFMEM power. + * power: true to power up, false to power down. + * return value: BSEC_OK if no error. + */ +static uint32_t bsec_power_safmem(bool power) +{ + uint32_t register_val; + uint32_t timeout = BSEC_TIMEOUT_VALUE; + + bsec_lock(); + + register_val = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); + + if (power) { + register_val |= BSEC_CONF_POWER_UP_MASK; + } else { + register_val &= ~BSEC_CONF_POWER_UP_MASK; + } + + mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, register_val); + + if (power) { + while (((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) && + (timeout != 0U)) { + timeout--; + } + } else { + while (((bsec_get_status() & BSEC_MODE_PWR_MASK) != 0U) && + (timeout != 0U)) { + timeout--; + } + } + + bsec_unlock(); + + if (timeout == 0U) { + return BSEC_TIMEOUT; + } + + return BSEC_OK; +} + +/* + * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value. + * otp_value: read value. + * word: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word) +{ + uint32_t result; + + result = bsec_shadow_register(word); + if (result != BSEC_OK) { + ERROR("BSEC: %u Shadowing Error %u\n", word, result); + return result; + } + + result = bsec_read_otp(otp_value, word); + if (result != BSEC_OK) { + ERROR("BSEC: %u Read Error %u\n", word, result); + } + + return result; +} + +/* + * bsec_check_nsec_access_rights: check non-secure access rights to target OTP. + * otp: OTP number. + * return value: BSEC_OK if authorized access. + */ +uint32_t bsec_check_nsec_access_rights(uint32_t otp) +{ +#if defined(IMAGE_BL32) + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + if (otp >= STM32MP1_UPPER_OTP_START) { + if (!non_secure_can_access(otp)) { + return BSEC_ERROR; + } + } +#endif + + return BSEC_OK; +} + diff --git a/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c b/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c new file mode 100644 index 0000000..355c9da --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c @@ -0,0 +1,1097 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include + +#include "clk-stm32-core.h" +#include +#include +#include +#include +#include +#include +#include + +static struct spinlock reg_lock; +static struct spinlock refcount_lock; + +static struct stm32_clk_priv *stm32_clock_data; + +const struct stm32_clk_ops clk_mux_ops; + +struct stm32_clk_priv *clk_stm32_get_priv(void) +{ + return stm32_clock_data; +} + +static void stm32mp1_clk_lock(struct spinlock *lock) +{ + if (stm32mp_lock_available()) { + /* Assume interrupts are masked */ + spin_lock(lock); + } +} + +static void stm32mp1_clk_unlock(struct spinlock *lock) +{ + if (stm32mp_lock_available()) { + spin_unlock(lock); + } +} + +void stm32mp1_clk_rcc_regs_lock(void) +{ + stm32mp1_clk_lock(®_lock); +} + +void stm32mp1_clk_rcc_regs_unlock(void) +{ + stm32mp1_clk_unlock(®_lock); +} + +#define TIMEOUT_US_1S U(1000000) +#define OSCRDY_TIMEOUT TIMEOUT_US_1S + +struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_osc_cfg *osc_cfg = clk->clock_cfg; + int osc_id = osc_cfg->osc_id; + + return &priv->osci_data[osc_id]; +} + +void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + struct stm32_clk_bypass *bypass_data = osc_data->bypass; + uintptr_t address; + + if (bypass_data == NULL) { + return; + } + + address = priv->base + bypass_data->offset; + + if (digbyp) { + mmio_setbits_32(address, BIT(bypass_data->bit_digbyp)); + } + + if (bypass || digbyp) { + mmio_setbits_32(address, BIT(bypass_data->bit_byp)); + } +} + +void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + struct stm32_clk_css *css_data = osc_data->css; + uintptr_t address; + + if (css_data == NULL) { + return; + } + + address = priv->base + css_data->offset; + + if (css) { + mmio_setbits_32(address, BIT(css_data->bit_css)); + } +} + +void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + struct stm32_clk_drive *drive_data = osc_data->drive; + uintptr_t address; + uint32_t mask; + uint32_t value; + + if (drive_data == NULL) { + return; + } + + address = priv->base + drive_data->offset; + + mask = (BIT(drive_data->drv_width) - 1U) << drive_data->drv_shift; + + /* + * Warning: not recommended to switch directly from "high drive" + * to "medium low drive", and vice-versa. + */ + value = (mmio_read_32(address) & mask) >> drive_data->drv_shift; + + while (value != lsedrv) { + if (value > lsedrv) { + value--; + } else { + value++; + } + + mmio_clrsetbits_32(address, mask, value << drive_data->drv_shift); + } +} + +int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + return _clk_stm32_gate_wait_ready(priv, osc_data->gate_id, ready_on); +} + +int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id) +{ + return clk_oscillator_wait_ready(priv, id, true); +} + +int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id) +{ + return clk_oscillator_wait_ready(priv, id, false); +} + +static int clk_gate_enable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_gate_cfg *cfg = clk->clock_cfg; + + mmio_setbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx)); + + return 0; +} + +static void clk_gate_disable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_gate_cfg *cfg = clk->clock_cfg; + + mmio_clrbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx)); +} + +static bool clk_gate_is_enabled(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_gate_cfg *cfg = clk->clock_cfg; + + return ((mmio_read_32(priv->base + cfg->offset) & BIT(cfg->bit_idx)) != 0U); +} + +const struct stm32_clk_ops clk_gate_ops = { + .enable = clk_gate_enable, + .disable = clk_gate_disable, + .is_enabled = clk_gate_is_enabled, +}; + +void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id) +{ + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t addr = priv->base + gate->offset; + + if (gate->set_clr != 0U) { + mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); + } else { + mmio_clrbits_32(addr, BIT(gate->bit_idx)); + } +} + +int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id) +{ + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t addr = priv->base + gate->offset; + + if (gate->set_clr != 0U) { + mmio_write_32(addr, BIT(gate->bit_idx)); + + } else { + mmio_setbits_32(addr, BIT(gate->bit_idx)); + } + + return 0; +} + +const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id) +{ + return priv->clks[id].name; +} + +const char *clk_stm32_get_name(struct stm32_clk_priv *priv, + unsigned long binding_id) +{ + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return NULL; + } + + return _clk_stm32_get_name(priv, id); +} + +const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id) +{ + if ((unsigned int)id < priv->num) { + return &priv->clks[id]; + } + + return NULL; +} + +#define clk_div_mask(_width) GENMASK(((_width) - 1U), 0U) + +static unsigned int _get_table_div(const struct clk_div_table *table, + unsigned int val) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) { + if (clkt->val == val) { + return clkt->div; + } + } + + return 0; +} + +static unsigned int _get_div(const struct clk_div_table *table, + unsigned int val, unsigned long flags, + uint8_t width) +{ + if ((flags & CLK_DIVIDER_ONE_BASED) != 0UL) { + return val; + } + + if ((flags & CLK_DIVIDER_POWER_OF_TWO) != 0UL) { + return BIT(val); + } + + if ((flags & CLK_DIVIDER_MAX_AT_ZERO) != 0UL) { + return (val != 0U) ? val : BIT(width); + } + + if (table != NULL) { + return _get_table_div(table, val); + } + + return val + 1U; +} + +#define TIMEOUT_US_200MS U(200000) +#define CLKSRC_TIMEOUT TIMEOUT_US_200MS + +int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel) +{ + const struct parent_cfg *parents = &priv->parents[pid & MUX_PARENT_MASK]; + const struct mux_cfg *mux = parents->mux; + uintptr_t address = priv->base + mux->offset; + uint32_t mask; + uint64_t timeout; + + mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); + + mmio_clrsetbits_32(address, mask, (sel << mux->shift) & mask); + + if (mux->bitrdy == MUX_NO_BIT_RDY) { + return 0; + } + + timeout = timeout_init_us(CLKSRC_TIMEOUT); + + mask = BIT(mux->bitrdy); + + while ((mmio_read_32(address) & mask) == 0U) { + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } + + return 0; +} + +int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int clk, int clkp) +{ + const struct parent_cfg *parents; + uint16_t pid; + uint8_t sel; + int old_parent; + + pid = priv->clks[clk].parent; + + if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) { + return -EINVAL; + } + + old_parent = _clk_stm32_get_parent(priv, clk); + if (old_parent == clkp) { + return 0; + } + + parents = &priv->parents[pid & MUX_PARENT_MASK]; + + for (sel = 0; sel < parents->num_parents; sel++) { + if (parents->id_parents[sel] == (uint16_t)clkp) { + bool clk_was_enabled = _clk_stm32_is_enabled(priv, clk); + int err = 0; + + /* Enable the parents (for glitch free mux) */ + _clk_stm32_enable(priv, clkp); + _clk_stm32_enable(priv, old_parent); + + err = clk_mux_set_parent(priv, pid, sel); + + _clk_stm32_disable(priv, old_parent); + + if (clk_was_enabled) { + _clk_stm32_disable(priv, old_parent); + } else { + _clk_stm32_disable(priv, clkp); + } + + return err; + } + } + + return -EINVAL; +} + +int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id) +{ + const struct parent_cfg *parent; + const struct mux_cfg *mux; + uint32_t mask; + + if (mux_id >= priv->nb_parents) { + panic(); + } + + parent = &priv->parents[mux_id]; + mux = parent->mux; + + mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); + + return (mmio_read_32(priv->base + mux->offset) & mask) >> mux->shift; +} + +int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel) +{ + uint16_t pid; + + pid = priv->clks[clk].parent; + + if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) { + return -EINVAL; + } + + return clk_mux_set_parent(priv, pid, sel); +} + +int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int clk_id) +{ + const struct clk_stm32 *clk = _clk_get(priv, clk_id); + const struct parent_cfg *parent; + uint16_t mux_id; + int sel; + + mux_id = priv->clks[clk_id].parent; + if (mux_id == CLK_IS_ROOT) { + return CLK_IS_ROOT; + } + + if (mux_id < MUX_MAX_PARENTS) { + return mux_id & MUX_PARENT_MASK; + } + + mux_id &= MUX_PARENT_MASK; + parent = &priv->parents[mux_id]; + + if (clk->ops->get_parent != NULL) { + sel = clk->ops->get_parent(priv, clk_id); + } else { + sel = clk_mux_get_parent(priv, mux_id); + } + + if (sel < parent->num_parents) { + return parent->id_parents[sel]; + } + + return -EINVAL; +} + +int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id) +{ + uint16_t mux_id; + + mux_id = priv->clks[clk_id].parent; + if (mux_id == CLK_IS_ROOT) { + return CLK_IS_ROOT; + } + + if (mux_id < MUX_MAX_PARENTS) { + return mux_id & MUX_PARENT_MASK; + } + + mux_id &= MUX_PARENT_MASK; + + return clk_mux_get_parent(priv, mux_id); +} + +int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx) +{ + const struct parent_cfg *parent; + uint16_t mux_id; + + mux_id = priv->clks[clk_id].parent; + if (mux_id == CLK_IS_ROOT) { + return CLK_IS_ROOT; + } + + if (mux_id < MUX_MAX_PARENTS) { + return mux_id & MUX_PARENT_MASK; + } + + mux_id &= MUX_PARENT_MASK; + parent = &priv->parents[mux_id]; + + if (idx < parent->num_parents) { + return parent->id_parents[idx]; + } + + return -EINVAL; +} + +int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id) +{ + unsigned int i; + + for (i = 0U; i < priv->num; i++) { + if (binding_id == priv->clks[i].binding) { + return (int)i; + } + } + + return -EINVAL; +} + +unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + int parent; + unsigned long rate = 0UL; + + if ((unsigned int)id >= priv->num) { + return rate; + } + + parent = _clk_stm32_get_parent(priv, id); + + if (clk->ops->recalc_rate != NULL) { + unsigned long prate = 0UL; + + if (parent != CLK_IS_ROOT) { + prate = _clk_stm32_get_rate(priv, parent); + } + + rate = clk->ops->recalc_rate(priv, id, prate); + + return rate; + } + + switch (parent) { + case CLK_IS_ROOT: + panic(); + + default: + rate = _clk_stm32_get_rate(priv, parent); + break; + } + return rate; + +} + +unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id) +{ + int parent_id = _clk_stm32_get_parent(priv, id); + + return _clk_stm32_get_rate(priv, parent_id); +} + +static uint8_t _stm32_clk_get_flags(struct stm32_clk_priv *priv, int id) +{ + return priv->clks[id].flags; +} + +bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag) +{ + if (_stm32_clk_get_flags(priv, id) & flag) { + return true; + } + + return false; +} + +int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + + if (clk->ops->enable != NULL) { + clk->ops->enable(priv, id); + } + + return 0; +} + +static int _clk_stm32_enable_core(struct stm32_clk_priv *priv, int id) +{ + int parent; + int ret = 0; + + if (priv->gate_refcounts[id] == 0U) { + parent = _clk_stm32_get_parent(priv, id); + if (parent != CLK_IS_ROOT) { + ret = _clk_stm32_enable_core(priv, parent); + if (ret) { + return ret; + } + } + clk_stm32_enable_call_ops(priv, id); + } + + priv->gate_refcounts[id]++; + + if (priv->gate_refcounts[id] == UINT_MAX) { + ERROR("%s: %d max enable count !", __func__, id); + panic(); + } + + return 0; +} + +int _clk_stm32_enable(struct stm32_clk_priv *priv, int id) +{ + int ret; + + stm32mp1_clk_lock(&refcount_lock); + ret = _clk_stm32_enable_core(priv, id); + stm32mp1_clk_unlock(&refcount_lock); + + return ret; +} + +void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + + if (clk->ops->disable != NULL) { + clk->ops->disable(priv, id); + } +} + +static void _clk_stm32_disable_core(struct stm32_clk_priv *priv, int id) +{ + int parent; + + if ((priv->gate_refcounts[id] == 1U) && _stm32_clk_is_flags(priv, id, CLK_IS_CRITICAL)) { + return; + } + + if (priv->gate_refcounts[id] == 0U) { + /* case of clock ignore unused */ + if (_clk_stm32_is_enabled(priv, id)) { + clk_stm32_disable_call_ops(priv, id); + return; + } + VERBOSE("%s: %d already disabled !\n\n", __func__, id); + return; + } + + if (--priv->gate_refcounts[id] > 0U) { + return; + } + + clk_stm32_disable_call_ops(priv, id); + + parent = _clk_stm32_get_parent(priv, id); + if (parent != CLK_IS_ROOT) { + _clk_stm32_disable_core(priv, parent); + } +} + +void _clk_stm32_disable(struct stm32_clk_priv *priv, int id) +{ + stm32mp1_clk_lock(&refcount_lock); + + _clk_stm32_disable_core(priv, id); + + stm32mp1_clk_unlock(&refcount_lock); +} + +bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + + if (clk->ops->is_enabled != NULL) { + return clk->ops->is_enabled(priv, id); + } + + return priv->gate_refcounts[id]; +} + +static int clk_stm32_enable(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return id; + } + + return _clk_stm32_enable(priv, id); +} + +static void clk_stm32_disable(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id != -EINVAL) { + _clk_stm32_disable(priv, id); + } +} + +static bool clk_stm32_is_enabled(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return false; + } + + return _clk_stm32_is_enabled(priv, id); +} + +static unsigned long clk_stm32_get_rate(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return 0UL; + } + + return _clk_stm32_get_rate(priv, id); +} + +static int clk_stm32_get_parent(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return id; + } + + return _clk_stm32_get_parent(priv, id); +} + +static const struct clk_ops stm32mp_clk_ops = { + .enable = clk_stm32_enable, + .disable = clk_stm32_disable, + .is_enabled = clk_stm32_is_enabled, + .get_rate = clk_stm32_get_rate, + .get_parent = clk_stm32_get_parent, +}; + +void clk_stm32_enable_critical_clocks(void) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + unsigned int i; + + for (i = 0U; i < priv->num; i++) { + if (_stm32_clk_is_flags(priv, i, CLK_IS_CRITICAL)) { + _clk_stm32_enable(priv, i); + } + } +} + +static void stm32_clk_register(void) +{ + clk_register(&stm32mp_clk_ops); +} + +uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id) +{ + const struct div_cfg *divider = &priv->div[div_id]; + uint32_t val = 0; + + val = mmio_read_32(priv->base + divider->offset) >> divider->shift; + val &= clk_div_mask(divider->width); + + return val; +} + +unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv, + int div_id, + unsigned long prate) +{ + const struct div_cfg *divider = &priv->div[div_id]; + uint32_t val = clk_stm32_div_get_value(priv, div_id); + unsigned int div = 0U; + + div = _get_div(divider->table, val, divider->flags, divider->width); + if (div == 0U) { + return prate; + } + + return div_round_up((uint64_t)prate, div); +} + +unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int id, + unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_div_cfg *div_cfg = clk->clock_cfg; + + return _clk_stm32_divider_recalc(priv, div_cfg->id, prate); +} + +const struct stm32_clk_ops clk_stm32_divider_ops = { + .recalc_rate = clk_stm32_divider_recalc, +}; + +int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value) +{ + const struct div_cfg *divider; + uintptr_t address; + uint64_t timeout; + uint32_t mask; + + if (div_id >= priv->nb_div) { + panic(); + } + + divider = &priv->div[div_id]; + address = priv->base + divider->offset; + + mask = MASK_WIDTH_SHIFT(divider->width, divider->shift); + mmio_clrsetbits_32(address, mask, (value << divider->shift) & mask); + + if (divider->bitrdy == DIV_NO_BIT_RDY) { + return 0; + } + + timeout = timeout_init_us(CLKSRC_TIMEOUT); + mask = BIT(divider->bitrdy); + + while ((mmio_read_32(address) & mask) == 0U) { + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } + + return 0; +} + +int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, + bool ready_on) +{ + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t address = priv->base + gate->offset; + uint32_t mask_rdy = BIT(gate->bit_idx); + uint64_t timeout; + uint32_t mask_test; + + if (ready_on) { + mask_test = BIT(gate->bit_idx); + } else { + mask_test = 0U; + } + + timeout = timeout_init_us(OSCRDY_TIMEOUT); + + while ((mmio_read_32(address) & mask_rdy) != mask_test) { + if (timeout_elapsed(timeout)) { + break; + } + } + + if ((mmio_read_32(address) & mask_rdy) != mask_test) + return -ETIMEDOUT; + + return 0; +} + +int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; + const struct gate_cfg *gate = &priv->gates[cfg->id]; + uintptr_t addr = priv->base + gate->offset; + + if (gate->set_clr != 0U) { + mmio_write_32(addr, BIT(gate->bit_idx)); + + } else { + mmio_setbits_32(addr, BIT(gate->bit_idx)); + } + + return 0; +} + +void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; + const struct gate_cfg *gate = &priv->gates[cfg->id]; + uintptr_t addr = priv->base + gate->offset; + + if (gate->set_clr != 0U) { + mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); + } else { + mmio_clrbits_32(addr, BIT(gate->bit_idx)); + } +} + +bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id) +{ + const struct gate_cfg *gate; + uint32_t addr; + + gate = &priv->gates[gate_id]; + addr = priv->base + gate->offset; + + return ((mmio_read_32(addr) & BIT(gate->bit_idx)) != 0U); +} + +bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; + + return _clk_stm32_gate_is_enabled(priv, cfg->id); +} + +const struct stm32_clk_ops clk_stm32_gate_ops = { + .enable = clk_stm32_gate_enable, + .disable = clk_stm32_gate_disable, + .is_enabled = clk_stm32_gate_is_enabled, +}; + +const struct stm32_clk_ops clk_fixed_factor_ops = { + .recalc_rate = fixed_factor_recalc_rate, +}; + +unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv, + int id, unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + const struct fixed_factor_cfg *cfg = clk->clock_cfg; + unsigned long long rate; + + rate = (unsigned long long)prate * cfg->mult; + + if (cfg->div == 0U) { + ERROR("division by zero\n"); + panic(); + } + + return (unsigned long)(rate / cfg->div); +}; + +#define APB_DIV_MASK GENMASK(2, 0) +#define TIM_PRE_MASK BIT(0) + +static unsigned long timer_recalc_rate(struct stm32_clk_priv *priv, + int id, unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + const struct clk_timer_cfg *cfg = clk->clock_cfg; + uint32_t prescaler, timpre; + uintptr_t rcc_base = priv->base; + + prescaler = mmio_read_32(rcc_base + cfg->apbdiv) & + APB_DIV_MASK; + + timpre = mmio_read_32(rcc_base + cfg->timpre) & + TIM_PRE_MASK; + + if (prescaler == 0U) { + return prate; + } + + return prate * (timpre + 1U) * 2U; +}; + +const struct stm32_clk_ops clk_timer_ops = { + .recalc_rate = timer_recalc_rate, +}; + +static unsigned long clk_fixed_rate_recalc(struct stm32_clk_priv *priv, int id, + unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_fixed_rate_cfg *cfg = clk->clock_cfg; + + return cfg->rate; +} + +const struct stm32_clk_ops clk_stm32_fixed_rate_ops = { + .recalc_rate = clk_fixed_rate_recalc, +}; + +static unsigned long clk_stm32_osc_recalc_rate(struct stm32_clk_priv *priv, + int id, unsigned long prate) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + return osc_data->frequency; +}; + +bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + return _clk_stm32_gate_is_enabled(priv, osc_data->gate_id); + +} + +int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + _clk_stm32_gate_enable(priv, osc_data->gate_id); + + if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, true) != 0U) { + ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__); + panic(); + } + + return 0; +} + +void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + _clk_stm32_gate_disable(priv, osc_data->gate_id); + + if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, false) != 0U) { + ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__); + panic(); + } +} + +static unsigned long clk_stm32_get_dt_oscillator_frequency(const char *name) +{ + void *fdt = NULL; + int node = 0; + int subnode = 0; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return 0UL; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar = NULL; + const fdt32_t *cuint = NULL; + int ret = 0; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + continue; + } + + if (strncmp(cchar, name, (size_t)ret) || + fdt_get_status(subnode) == DT_DISABLED) { + continue; + } + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); + if (cuint == NULL) { + return 0UL; + } + + return fdt32_to_cpu(*cuint); + } + + return 0UL; +} + +void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + const char *name = osc_data->name; + + osc_data->frequency = clk_stm32_get_dt_oscillator_frequency(name); +} + +const struct stm32_clk_ops clk_stm32_osc_ops = { + .recalc_rate = clk_stm32_osc_recalc_rate, + .is_enabled = clk_stm32_osc_gate_is_enabled, + .enable = clk_stm32_osc_gate_enable, + .disable = clk_stm32_osc_gate_disable, + .init = clk_stm32_osc_init, +}; + +const struct stm32_clk_ops clk_stm32_osc_nogate_ops = { + .recalc_rate = clk_stm32_osc_recalc_rate, + .init = clk_stm32_osc_init, +}; + +int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb) +{ + const fdt32_t *cell; + int len = 0; + uint32_t i; + + cell = fdt_getprop(fdt, node, name, &len); + if (cell != NULL) { + for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { + uint32_t val = fdt32_to_cpu(cell[i]); + + tab[i] = val; + } + } + + *nb = (uint32_t)len / sizeof(uint32_t); + + return 0; +} + +int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base) +{ + unsigned int i; + + stm32_clock_data = priv; + + priv->base = base; + + for (i = 0U; i < priv->num; i++) { + const struct clk_stm32 *clk = _clk_get(priv, i); + + assert(clk->ops != NULL); + + if (clk->ops->init != NULL) { + clk->ops->init(priv, i); + } + } + + stm32_clk_register(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h b/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h new file mode 100644 index 0000000..809d05f --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef CLK_STM32_CORE_H +#define CLK_STM32_CORE_H + +struct mux_cfg { + uint16_t offset; + uint8_t shift; + uint8_t width; + uint8_t bitrdy; +}; + +struct gate_cfg { + uint16_t offset; + uint8_t bit_idx; + uint8_t set_clr; +}; + +struct clk_div_table { + unsigned int val; + unsigned int div; +}; + +struct div_cfg { + uint16_t offset; + uint8_t shift; + uint8_t width; + uint8_t flags; + uint8_t bitrdy; + const struct clk_div_table *table; +}; + +struct parent_cfg { + uint8_t num_parents; + const uint16_t *id_parents; + struct mux_cfg *mux; +}; + +struct stm32_clk_priv; + +struct stm32_clk_ops { + unsigned long (*recalc_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate); + int (*get_parent)(struct stm32_clk_priv *priv, int id); + int (*set_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate, + unsigned long prate); + int (*enable)(struct stm32_clk_priv *priv, int id); + void (*disable)(struct stm32_clk_priv *priv, int id); + bool (*is_enabled)(struct stm32_clk_priv *priv, int id); + void (*init)(struct stm32_clk_priv *priv, int id); +}; + +struct clk_stm32 { + const char *name; + uint16_t binding; + uint16_t parent; + uint8_t flags; + void *clock_cfg; + const struct stm32_clk_ops *ops; +}; + +struct stm32_clk_priv { + uintptr_t base; + const uint32_t num; + const struct clk_stm32 *clks; + const struct parent_cfg *parents; + const uint32_t nb_parents; + const struct gate_cfg *gates; + const uint32_t nb_gates; + const struct div_cfg *div; + const uint32_t nb_div; + struct clk_oscillator_data *osci_data; + const uint32_t nb_osci_data; + uint32_t *gate_refcounts; + void *pdata; +}; + +struct stm32_clk_bypass { + uint16_t offset; + uint8_t bit_byp; + uint8_t bit_digbyp; +}; + +struct stm32_clk_css { + uint16_t offset; + uint8_t bit_css; +}; + +struct stm32_clk_drive { + uint16_t offset; + uint8_t drv_shift; + uint8_t drv_width; + uint8_t drv_default; +}; + +struct clk_oscillator_data { + const char *name; + uint16_t id_clk; + unsigned long frequency; + uint16_t gate_id; + uint16_t gate_rdy_id; + struct stm32_clk_bypass *bypass; + struct stm32_clk_css *css; + struct stm32_clk_drive *drive; +}; + +struct clk_fixed_rate { + const char *name; + unsigned long fixed_rate; +}; + +struct clk_gate_cfg { + uint32_t offset; + uint8_t bit_idx; +}; + +/* CLOCK FLAGS */ +#define CLK_IS_CRITICAL BIT(0) +#define CLK_IGNORE_UNUSED BIT(1) +#define CLK_SET_RATE_PARENT BIT(2) + +#define CLK_DIVIDER_ONE_BASED BIT(0) +#define CLK_DIVIDER_POWER_OF_TWO BIT(1) +#define CLK_DIVIDER_ALLOW_ZERO BIT(2) +#define CLK_DIVIDER_HIWORD_MASK BIT(3) +#define CLK_DIVIDER_ROUND_CLOSEST BIT(4) +#define CLK_DIVIDER_READ_ONLY BIT(5) +#define CLK_DIVIDER_MAX_AT_ZERO BIT(6) +#define CLK_DIVIDER_BIG_ENDIAN BIT(7) + +#define MUX_MAX_PARENTS U(0x8000) +#define MUX_PARENT_MASK GENMASK(14, 0) +#define MUX_FLAG U(0x8000) +#define MUX(mux) ((mux) | MUX_FLAG) + +#define NO_GATE 0 +#define _NO_ID UINT16_MAX +#define CLK_IS_ROOT UINT16_MAX +#define MUX_NO_BIT_RDY UINT8_MAX +#define DIV_NO_BIT_RDY UINT8_MAX + +#define MASK_WIDTH_SHIFT(_width, _shift) \ + GENMASK(((_width) + (_shift) - 1U), (_shift)) + +int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base); +void clk_stm32_enable_critical_clocks(void); + +struct stm32_clk_priv *clk_stm32_get_priv(void); + +int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id); +const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id); + +void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass); +void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv); +void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css); + +int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, bool ready_on); + +int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on); +int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id); +int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id); + +const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id); +const char *clk_stm32_get_name(struct stm32_clk_priv *priv, unsigned long binding_id); +int clk_stm32_get_counter(unsigned long binding_id); + +void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id); +int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id); + +int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int id, int src_id); +int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel); + +int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int id); +int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx); +int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id); + +unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id); +unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id); + +bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag); + +int _clk_stm32_enable(struct stm32_clk_priv *priv, int id); +void _clk_stm32_disable(struct stm32_clk_priv *priv, int id); + +int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id); +void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id); + +bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id); + +int _clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int div_id, + unsigned long rate, unsigned long parent_rate); + +int clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int id, unsigned long rate, + unsigned long prate); + +unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv, + int div_id, + unsigned long prate); + +unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int idx, + unsigned long prate); + +int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int idx); +void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int idx); + +bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id); +bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int idx); + +uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id); +int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value); +int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel); +int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id); + +int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb); + +#ifdef CFG_STM32_CLK_DEBUG +void clk_stm32_display_clock_info(void); +#endif + +struct clk_stm32_div_cfg { + int id; +}; + +#define STM32_DIV(idx, _binding, _parent, _flags, _div_id) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (_parent),\ + .flags = (_flags),\ + .clock_cfg = &(struct clk_stm32_div_cfg){\ + .id = (_div_id),\ + },\ + .ops = &clk_stm32_divider_ops,\ + } + +struct clk_stm32_gate_cfg { + int id; +}; + +#define STM32_GATE(idx, _binding, _parent, _flags, _gate_id) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (_parent),\ + .flags = (_flags),\ + .clock_cfg = &(struct clk_stm32_gate_cfg){\ + .id = (_gate_id),\ + },\ + .ops = &clk_stm32_gate_ops,\ + } + +struct fixed_factor_cfg { + unsigned int mult; + unsigned int div; +}; + +unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv, + int _idx, unsigned long prate); + +#define FIXED_FACTOR(idx, _idx, _parent, _mult, _div) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_idx),\ + .parent = (_parent),\ + .clock_cfg = &(struct fixed_factor_cfg){\ + .mult = (_mult),\ + .div = (_div),\ + },\ + .ops = &clk_fixed_factor_ops,\ + } + +#define GATE(idx, _binding, _parent, _flags, _offset, _bit_idx) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (_parent),\ + .flags = (_flags),\ + .clock_cfg = &(struct clk_gate_cfg){\ + .offset = (_offset),\ + .bit_idx = (_bit_idx),\ + },\ + .ops = &clk_gate_ops,\ + } + +#define STM32_MUX(idx, _binding, _mux_id, _flags) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (MUX(_mux_id)),\ + .flags = (_flags),\ + .clock_cfg = NULL,\ + .ops = (&clk_mux_ops),\ + } + +struct clk_timer_cfg { + uint32_t apbdiv; + uint32_t timpre; +}; + +#define CK_TIMER(idx, _idx, _parent, _flags, _apbdiv, _timpre) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_idx),\ + .parent = (_parent),\ + .flags = (CLK_SET_RATE_PARENT | (_flags)),\ + .clock_cfg = &(struct clk_timer_cfg){\ + .apbdiv = (_apbdiv),\ + .timpre = (_timpre),\ + },\ + .ops = &clk_timer_ops,\ + } + +struct clk_stm32_fixed_rate_cfg { + unsigned long rate; +}; + +#define CLK_FIXED_RATE(idx, _binding, _rate) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (CLK_IS_ROOT),\ + .clock_cfg = &(struct clk_stm32_fixed_rate_cfg){\ + .rate = (_rate),\ + },\ + .ops = &clk_stm32_fixed_rate_ops,\ + } + +#define BYPASS(_offset, _bit_byp, _bit_digbyp) &(struct stm32_clk_bypass){\ + .offset = (_offset),\ + .bit_byp = (_bit_byp),\ + .bit_digbyp = (_bit_digbyp),\ +} + +#define CSS(_offset, _bit_css) &(struct stm32_clk_css){\ + .offset = (_offset),\ + .bit_css = (_bit_css),\ +} + +#define DRIVE(_offset, _shift, _width, _default) &(struct stm32_clk_drive){\ + .offset = (_offset),\ + .drv_shift = (_shift),\ + .drv_width = (_width),\ + .drv_default = (_default),\ +} + +#define OSCILLATOR(idx_osc, _id, _name, _gate_id, _gate_rdy_id, _bypass, _css, _drive) \ + [(idx_osc)] = (struct clk_oscillator_data){\ + .name = (_name),\ + .id_clk = (_id),\ + .gate_id = (_gate_id),\ + .gate_rdy_id = (_gate_rdy_id),\ + .bypass = (_bypass),\ + .css = (_css),\ + .drive = (_drive),\ + } + +struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id); + +void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id); +bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id); +int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id); +void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id); + +struct stm32_osc_cfg { + int osc_id; +}; + +#define CLK_OSC(idx, _idx, _parent, _osc_id) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_idx),\ + .parent = (_parent),\ + .flags = CLK_IS_CRITICAL,\ + .clock_cfg = &(struct stm32_osc_cfg){\ + .osc_id = (_osc_id),\ + },\ + .ops = &clk_stm32_osc_ops,\ + } + +#define CLK_OSC_FIXED(idx, _idx, _parent, _osc_id) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_idx),\ + .parent = (_parent),\ + .flags = CLK_IS_CRITICAL,\ + .clock_cfg = &(struct stm32_osc_cfg){\ + .osc_id = (_osc_id),\ + },\ + .ops = &clk_stm32_osc_nogate_ops,\ + } + +extern const struct stm32_clk_ops clk_mux_ops; +extern const struct stm32_clk_ops clk_stm32_divider_ops; +extern const struct stm32_clk_ops clk_stm32_gate_ops; +extern const struct stm32_clk_ops clk_fixed_factor_ops; +extern const struct stm32_clk_ops clk_gate_ops; +extern const struct stm32_clk_ops clk_timer_ops; +extern const struct stm32_clk_ops clk_stm32_fixed_rate_ops; +extern const struct stm32_clk_ops clk_stm32_osc_ops; +extern const struct stm32_clk_ops clk_stm32_osc_nogate_ops; + +#endif /* CLK_STM32_CORE_H */ diff --git a/arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c b/arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c new file mode 100644 index 0000000..d360767 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c @@ -0,0 +1,2334 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include "clk-stm32-core.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct stm32_osci_dt_cfg { + unsigned long freq; + bool bypass; + bool digbyp; + bool css; + uint32_t drive; +}; + +enum pll_mn { + PLL_CFG_M, + PLL_CFG_N, + PLL_DIV_MN_NB +}; + +enum pll_pqr { + PLL_CFG_P, + PLL_CFG_Q, + PLL_CFG_R, + PLL_DIV_PQR_NB +}; + +enum pll_csg { + PLL_CSG_MOD_PER, + PLL_CSG_INC_STEP, + PLL_CSG_SSCG_MODE, + PLL_CSG_NB +}; + +struct stm32_pll_vco { + uint32_t status; + uint32_t src; + uint32_t div_mn[PLL_DIV_MN_NB]; + uint32_t frac; + bool csg_enabled; + uint32_t csg[PLL_CSG_NB]; +}; + +struct stm32_pll_output { + uint32_t output[PLL_DIV_PQR_NB]; +}; + +struct stm32_pll_dt_cfg { + struct stm32_pll_vco vco; + struct stm32_pll_output output; +}; + +struct stm32_clk_platdata { + uint32_t nosci; + struct stm32_osci_dt_cfg *osci; + uint32_t npll; + struct stm32_pll_dt_cfg *pll; + uint32_t nclksrc; + uint32_t *clksrc; + uint32_t nclkdiv; + uint32_t *clkdiv; +}; + +enum stm32_clock { + /* ROOT CLOCKS */ + _CK_OFF, + _CK_HSI, + _CK_HSE, + _CK_CSI, + _CK_LSI, + _CK_LSE, + _I2SCKIN, + _CSI_DIV122, + _HSE_DIV, + _HSE_DIV2, + _CK_PLL1, + _CK_PLL2, + _CK_PLL3, + _CK_PLL4, + _PLL1P, + _PLL1P_DIV, + _PLL2P, + _PLL2Q, + _PLL2R, + _PLL3P, + _PLL3Q, + _PLL3R, + _PLL4P, + _PLL4Q, + _PLL4R, + _PCLK1, + _PCLK2, + _PCLK3, + _PCLK4, + _PCLK5, + _PCLK6, + _CKMPU, + _CKAXI, + _CKMLAHB, + _CKPER, + _CKTIMG1, + _CKTIMG2, + _CKTIMG3, + _USB_PHY_48, + _MCO1_K, + _MCO2_K, + _TRACECK, + /* BUS and KERNEL CLOCKS */ + _DDRC1, + _DDRC1LP, + _DDRPHYC, + _DDRPHYCLP, + _DDRCAPB, + _DDRCAPBLP, + _AXIDCG, + _DDRPHYCAPB, + _DDRPHYCAPBLP, + _SYSCFG, + _DDRPERFM, + _IWDG2APB, + _USBPHY_K, + _USBO_K, + _RTCAPB, + _TZC, + _ETZPC, + _IWDG1APB, + _BSEC, + _STGENC, + _USART1_K, + _USART2_K, + _I2C3_K, + _I2C4_K, + _I2C5_K, + _TIM12, + _TIM15, + _RTCCK, + _GPIOA, + _GPIOB, + _GPIOC, + _GPIOD, + _GPIOE, + _GPIOF, + _GPIOG, + _GPIOH, + _GPIOI, + _PKA, + _SAES_K, + _CRYP1, + _HASH1, + _RNG1_K, + _BKPSRAM, + _SDMMC1_K, + _SDMMC2_K, + _DBGCK, + _USART3_K, + _UART4_K, + _UART5_K, + _UART7_K, + _UART8_K, + _USART6_K, + _MCE, + _FMC_K, + _QSPI_K, +#if defined(IMAGE_BL32) + _LTDC, + _DMA1, + _DMA2, + _MDMA, + _ETH1MAC, + _USBH, + _TIM2, + _TIM3, + _TIM4, + _TIM5, + _TIM6, + _TIM7, + _LPTIM1_K, + _SPI2_K, + _SPI3_K, + _SPDIF_K, + _TIM1, + _TIM8, + _SPI1_K, + _SAI1_K, + _SAI2_K, + _DFSDM, + _FDCAN_K, + _TIM13, + _TIM14, + _TIM16, + _TIM17, + _SPI4_K, + _SPI5_K, + _I2C1_K, + _I2C2_K, + _ADFSDM, + _LPTIM2_K, + _LPTIM3_K, + _LPTIM4_K, + _LPTIM5_K, + _VREF, + _DTS, + _PMBCTRL, + _HDP, + _STGENRO, + _DCMIPP_K, + _DMAMUX1, + _DMAMUX2, + _DMA3, + _ADC1_K, + _ADC2_K, + _TSC, + _AXIMC, + _ETH1CK, + _ETH1TX, + _ETH1RX, + _CRC1, + _ETH2CK, + _ETH2TX, + _ETH2RX, + _ETH2MAC, +#endif + CK_LAST +}; + +/* PARENT CONFIG */ +static const uint16_t RTC_src[] = { + _CK_OFF, _CK_LSE, _CK_LSI, _CK_HSE +}; + +static const uint16_t MCO1_src[] = { + _CK_HSI, _CK_HSE, _CK_CSI, _CK_LSI, _CK_LSE +}; + +static const uint16_t MCO2_src[] = { + _CKMPU, _CKAXI, _CKMLAHB, _PLL4P, _CK_HSE, _CK_HSI +}; + +static const uint16_t PLL12_src[] = { + _CK_HSI, _CK_HSE +}; + +static const uint16_t PLL3_src[] = { + _CK_HSI, _CK_HSE, _CK_CSI +}; + +static const uint16_t PLL4_src[] = { + _CK_HSI, _CK_HSE, _CK_CSI, _I2SCKIN +}; + +static const uint16_t MPU_src[] = { + _CK_HSI, _CK_HSE, _PLL1P, _PLL1P_DIV +}; + +static const uint16_t AXI_src[] = { + _CK_HSI, _CK_HSE, _PLL2P +}; + +static const uint16_t MLAHBS_src[] = { + _CK_HSI, _CK_HSE, _CK_CSI, _PLL3P +}; + +static const uint16_t CKPER_src[] = { + _CK_HSI, _CK_CSI, _CK_HSE, _CK_OFF +}; + +static const uint16_t I2C12_src[] = { + _PCLK1, _PLL4R, _CK_HSI, _CK_CSI +}; + +static const uint16_t I2C3_src[] = { + _PCLK6, _PLL4R, _CK_HSI, _CK_CSI +}; + +static const uint16_t I2C4_src[] = { + _PCLK6, _PLL4R, _CK_HSI, _CK_CSI +}; + +static const uint16_t I2C5_src[] = { + _PCLK6, _PLL4R, _CK_HSI, _CK_CSI +}; + +static const uint16_t SPI1_src[] = { + _PLL4P, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R +}; + +static const uint16_t SPI23_src[] = { + _PLL4P, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R +}; + +static const uint16_t SPI4_src[] = { + _PCLK6, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE, _I2SCKIN +}; + +static const uint16_t SPI5_src[] = { + _PCLK6, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t UART1_src[] = { + _PCLK6, _PLL3Q, _CK_HSI, _CK_CSI, _PLL4Q, _CK_HSE +}; + +static const uint16_t UART2_src[] = { + _PCLK6, _PLL3Q, _CK_HSI, _CK_CSI, _PLL4Q, _CK_HSE +}; + +static const uint16_t UART35_src[] = { + _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t UART4_src[] = { + _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t UART6_src[] = { + _PCLK2, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t UART78_src[] = { + _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t LPTIM1_src[] = { + _PCLK1, _PLL4P, _PLL3Q, _CK_LSE, _CK_LSI, _CKPER +}; + +static const uint16_t LPTIM2_src[] = { + _PCLK3, _PLL4Q, _CKPER, _CK_LSE, _CK_LSI +}; + +static const uint16_t LPTIM3_src[] = { + _PCLK3, _PLL4Q, _CKPER, _CK_LSE, _CK_LSI +}; + +static const uint16_t LPTIM45_src[] = { + _PCLK3, _PLL4P, _PLL3Q, _CK_LSE, _CK_LSI, _CKPER +}; + +static const uint16_t SAI1_src[] = { + _PLL4Q, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R +}; + +static const uint16_t SAI2_src[] = { + _PLL4Q, _PLL3Q, _I2SCKIN, _CKPER, _NO_ID, _PLL3R +}; + +static const uint16_t FDCAN_src[] = { + _CK_HSE, _PLL3Q, _PLL4Q, _PLL4R +}; + +static const uint16_t SPDIF_src[] = { + _PLL4P, _PLL3Q, _CK_HSI +}; + +static const uint16_t ADC1_src[] = { + _PLL4R, _CKPER, _PLL3Q +}; + +static const uint16_t ADC2_src[] = { + _PLL4R, _CKPER, _PLL3Q +}; + +static const uint16_t SDMMC1_src[] = { + _CKAXI, _PLL3R, _PLL4P, _CK_HSI +}; + +static const uint16_t SDMMC2_src[] = { + _CKAXI, _PLL3R, _PLL4P, _CK_HSI +}; + +static const uint16_t ETH1_src[] = { + _PLL4P, _PLL3Q +}; + +static const uint16_t ETH2_src[] = { + _PLL4P, _PLL3Q +}; + +static const uint16_t USBPHY_src[] = { + _CK_HSE, _PLL4R, _HSE_DIV2 +}; + +static const uint16_t USBO_src[] = { + _PLL4R, _USB_PHY_48 +}; + +static const uint16_t QSPI_src[] = { + _CKAXI, _PLL3R, _PLL4P, _CKPER +}; + +static const uint16_t FMC_src[] = { + _CKAXI, _PLL3R, _PLL4P, _CKPER +}; + +/* Position 2 of RNG1 mux is reserved */ +static const uint16_t RNG1_src[] = { + _CK_CSI, _PLL4R, _CK_OFF, _CK_LSI +}; + +static const uint16_t STGEN_src[] = { + _CK_HSI, _CK_HSE +}; + +static const uint16_t DCMIPP_src[] = { + _CKAXI, _PLL2Q, _PLL4P, _CKPER +}; + +static const uint16_t SAES_src[] = { + _CKAXI, _CKPER, _PLL4R, _CK_LSI +}; + +#define MUX_CFG(id, src, _offset, _shift, _witdh)[id] = {\ + .id_parents = src,\ + .num_parents = ARRAY_SIZE(src),\ + .mux = &(struct mux_cfg) {\ + .offset = (_offset),\ + .shift = (_shift),\ + .width = (_witdh),\ + .bitrdy = MUX_NO_BIT_RDY,\ + },\ +} + +#define MUX_RDY_CFG(id, src, _offset, _shift, _witdh)[id] = {\ + .id_parents = src,\ + .num_parents = ARRAY_SIZE(src),\ + .mux = &(struct mux_cfg) {\ + .offset = (_offset),\ + .shift = (_shift),\ + .width = (_witdh),\ + .bitrdy = 31,\ + },\ +} + +static const struct parent_cfg parent_mp13[] = { + MUX_CFG(MUX_ADC1, ADC1_src, RCC_ADC12CKSELR, 0, 2), + MUX_CFG(MUX_ADC2, ADC2_src, RCC_ADC12CKSELR, 2, 2), + MUX_RDY_CFG(MUX_AXI, AXI_src, RCC_ASSCKSELR, 0, 3), + MUX_CFG(MUX_CKPER, CKPER_src, RCC_CPERCKSELR, 0, 2), + MUX_CFG(MUX_DCMIPP, DCMIPP_src, RCC_DCMIPPCKSELR, 0, 2), + MUX_CFG(MUX_ETH1, ETH1_src, RCC_ETH12CKSELR, 0, 2), + MUX_CFG(MUX_ETH2, ETH2_src, RCC_ETH12CKSELR, 8, 2), + MUX_CFG(MUX_FDCAN, FDCAN_src, RCC_FDCANCKSELR, 0, 2), + MUX_CFG(MUX_FMC, FMC_src, RCC_FMCCKSELR, 0, 2), + MUX_CFG(MUX_I2C12, I2C12_src, RCC_I2C12CKSELR, 0, 3), + MUX_CFG(MUX_I2C3, I2C3_src, RCC_I2C345CKSELR, 0, 3), + MUX_CFG(MUX_I2C4, I2C4_src, RCC_I2C345CKSELR, 3, 3), + MUX_CFG(MUX_I2C5, I2C5_src, RCC_I2C345CKSELR, 6, 3), + MUX_CFG(MUX_LPTIM1, LPTIM1_src, RCC_LPTIM1CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM2, LPTIM2_src, RCC_LPTIM23CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM3, LPTIM3_src, RCC_LPTIM23CKSELR, 3, 3), + MUX_CFG(MUX_LPTIM45, LPTIM45_src, RCC_LPTIM45CKSELR, 0, 3), + MUX_CFG(MUX_MCO1, MCO1_src, RCC_MCO1CFGR, 0, 3), + MUX_CFG(MUX_MCO2, MCO2_src, RCC_MCO2CFGR, 0, 3), + MUX_RDY_CFG(MUX_MLAHB, MLAHBS_src, RCC_MSSCKSELR, 0, 2), + MUX_RDY_CFG(MUX_MPU, MPU_src, RCC_MPCKSELR, 0, 2), + MUX_RDY_CFG(MUX_PLL12, PLL12_src, RCC_RCK12SELR, 0, 2), + MUX_RDY_CFG(MUX_PLL3, PLL3_src, RCC_RCK3SELR, 0, 2), + MUX_RDY_CFG(MUX_PLL4, PLL4_src, RCC_RCK4SELR, 0, 2), + MUX_CFG(MUX_QSPI, QSPI_src, RCC_QSPICKSELR, 0, 2), + MUX_CFG(MUX_RNG1, RNG1_src, RCC_RNG1CKSELR, 0, 2), + MUX_CFG(MUX_RTC, RTC_src, RCC_BDCR, 16, 2), + MUX_CFG(MUX_SAES, SAES_src, RCC_SAESCKSELR, 0, 2), + MUX_CFG(MUX_SAI1, SAI1_src, RCC_SAI1CKSELR, 0, 3), + MUX_CFG(MUX_SAI2, SAI2_src, RCC_SAI2CKSELR, 0, 3), + MUX_CFG(MUX_SDMMC1, SDMMC1_src, RCC_SDMMC12CKSELR, 0, 3), + MUX_CFG(MUX_SDMMC2, SDMMC2_src, RCC_SDMMC12CKSELR, 3, 3), + MUX_CFG(MUX_SPDIF, SPDIF_src, RCC_SPDIFCKSELR, 0, 2), + MUX_CFG(MUX_SPI1, SPI1_src, RCC_SPI2S1CKSELR, 0, 3), + MUX_CFG(MUX_SPI23, SPI23_src, RCC_SPI2S23CKSELR, 0, 3), + MUX_CFG(MUX_SPI4, SPI4_src, RCC_SPI45CKSELR, 0, 3), + MUX_CFG(MUX_SPI5, SPI5_src, RCC_SPI45CKSELR, 3, 3), + MUX_CFG(MUX_STGEN, STGEN_src, RCC_STGENCKSELR, 0, 2), + MUX_CFG(MUX_UART1, UART1_src, RCC_UART12CKSELR, 0, 3), + MUX_CFG(MUX_UART2, UART2_src, RCC_UART12CKSELR, 3, 3), + MUX_CFG(MUX_UART35, UART35_src, RCC_UART35CKSELR, 0, 3), + MUX_CFG(MUX_UART4, UART4_src, RCC_UART4CKSELR, 0, 3), + MUX_CFG(MUX_UART6, UART6_src, RCC_UART6CKSELR, 0, 3), + MUX_CFG(MUX_UART78, UART78_src, RCC_UART78CKSELR, 0, 3), + MUX_CFG(MUX_USBO, USBO_src, RCC_USBCKSELR, 4, 1), + MUX_CFG(MUX_USBPHY, USBPHY_src, RCC_USBCKSELR, 0, 2), +}; + +/* + * GATE CONFIG + */ + +enum enum_gate_cfg { + GATE_ZERO, /* reserved for no gate */ + GATE_LSE, + GATE_RTCCK, + GATE_LSI, + GATE_HSI, + GATE_CSI, + GATE_HSE, + GATE_LSI_RDY, + GATE_CSI_RDY, + GATE_LSE_RDY, + GATE_HSE_RDY, + GATE_HSI_RDY, + GATE_MCO1, + GATE_MCO2, + GATE_DBGCK, + GATE_TRACECK, + GATE_PLL1, + GATE_PLL1_DIVP, + GATE_PLL1_DIVQ, + GATE_PLL1_DIVR, + GATE_PLL2, + GATE_PLL2_DIVP, + GATE_PLL2_DIVQ, + GATE_PLL2_DIVR, + GATE_PLL3, + GATE_PLL3_DIVP, + GATE_PLL3_DIVQ, + GATE_PLL3_DIVR, + GATE_PLL4, + GATE_PLL4_DIVP, + GATE_PLL4_DIVQ, + GATE_PLL4_DIVR, + GATE_DDRC1, + GATE_DDRC1LP, + GATE_DDRPHYC, + GATE_DDRPHYCLP, + GATE_DDRCAPB, + GATE_DDRCAPBLP, + GATE_AXIDCG, + GATE_DDRPHYCAPB, + GATE_DDRPHYCAPBLP, + GATE_TIM2, + GATE_TIM3, + GATE_TIM4, + GATE_TIM5, + GATE_TIM6, + GATE_TIM7, + GATE_LPTIM1, + GATE_SPI2, + GATE_SPI3, + GATE_USART3, + GATE_UART4, + GATE_UART5, + GATE_UART7, + GATE_UART8, + GATE_I2C1, + GATE_I2C2, + GATE_SPDIF, + GATE_TIM1, + GATE_TIM8, + GATE_SPI1, + GATE_USART6, + GATE_SAI1, + GATE_SAI2, + GATE_DFSDM, + GATE_ADFSDM, + GATE_FDCAN, + GATE_LPTIM2, + GATE_LPTIM3, + GATE_LPTIM4, + GATE_LPTIM5, + GATE_VREF, + GATE_DTS, + GATE_PMBCTRL, + GATE_HDP, + GATE_SYSCFG, + GATE_DCMIPP, + GATE_DDRPERFM, + GATE_IWDG2APB, + GATE_USBPHY, + GATE_STGENRO, + GATE_LTDC, + GATE_RTCAPB, + GATE_TZC, + GATE_ETZPC, + GATE_IWDG1APB, + GATE_BSEC, + GATE_STGENC, + GATE_USART1, + GATE_USART2, + GATE_SPI4, + GATE_SPI5, + GATE_I2C3, + GATE_I2C4, + GATE_I2C5, + GATE_TIM12, + GATE_TIM13, + GATE_TIM14, + GATE_TIM15, + GATE_TIM16, + GATE_TIM17, + GATE_DMA1, + GATE_DMA2, + GATE_DMAMUX1, + GATE_DMA3, + GATE_DMAMUX2, + GATE_ADC1, + GATE_ADC2, + GATE_USBO, + GATE_TSC, + GATE_GPIOA, + GATE_GPIOB, + GATE_GPIOC, + GATE_GPIOD, + GATE_GPIOE, + GATE_GPIOF, + GATE_GPIOG, + GATE_GPIOH, + GATE_GPIOI, + GATE_PKA, + GATE_SAES, + GATE_CRYP1, + GATE_HASH1, + GATE_RNG1, + GATE_BKPSRAM, + GATE_AXIMC, + GATE_MCE, + GATE_ETH1CK, + GATE_ETH1TX, + GATE_ETH1RX, + GATE_ETH1MAC, + GATE_FMC, + GATE_QSPI, + GATE_SDMMC1, + GATE_SDMMC2, + GATE_CRC1, + GATE_USBH, + GATE_ETH2CK, + GATE_ETH2TX, + GATE_ETH2RX, + GATE_ETH2MAC, + GATE_MDMA, + + LAST_GATE +}; + +#define GATE_CFG(id, _offset, _bit_idx, _offset_clr)[id] = {\ + .offset = (_offset),\ + .bit_idx = (_bit_idx),\ + .set_clr = (_offset_clr),\ +} + +static const struct gate_cfg gates_mp13[LAST_GATE] = { + GATE_CFG(GATE_LSE, RCC_BDCR, 0, 0), + GATE_CFG(GATE_RTCCK, RCC_BDCR, 20, 0), + GATE_CFG(GATE_LSI, RCC_RDLSICR, 0, 0), + GATE_CFG(GATE_HSI, RCC_OCENSETR, 0, 1), + GATE_CFG(GATE_CSI, RCC_OCENSETR, 4, 1), + GATE_CFG(GATE_HSE, RCC_OCENSETR, 8, 1), + GATE_CFG(GATE_LSI_RDY, RCC_RDLSICR, 1, 0), + GATE_CFG(GATE_CSI_RDY, RCC_OCRDYR, 4, 0), + GATE_CFG(GATE_LSE_RDY, RCC_BDCR, 2, 0), + GATE_CFG(GATE_HSE_RDY, RCC_OCRDYR, 8, 0), + GATE_CFG(GATE_HSI_RDY, RCC_OCRDYR, 0, 0), + GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 12, 0), + GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 12, 0), + GATE_CFG(GATE_DBGCK, RCC_DBGCFGR, 8, 0), + GATE_CFG(GATE_TRACECK, RCC_DBGCFGR, 9, 0), + GATE_CFG(GATE_PLL1, RCC_PLL1CR, 0, 0), + GATE_CFG(GATE_PLL1_DIVP, RCC_PLL1CR, 4, 0), + GATE_CFG(GATE_PLL1_DIVQ, RCC_PLL1CR, 5, 0), + GATE_CFG(GATE_PLL1_DIVR, RCC_PLL1CR, 6, 0), + GATE_CFG(GATE_PLL2, RCC_PLL2CR, 0, 0), + GATE_CFG(GATE_PLL2_DIVP, RCC_PLL2CR, 4, 0), + GATE_CFG(GATE_PLL2_DIVQ, RCC_PLL2CR, 5, 0), + GATE_CFG(GATE_PLL2_DIVR, RCC_PLL2CR, 6, 0), + GATE_CFG(GATE_PLL3, RCC_PLL3CR, 0, 0), + GATE_CFG(GATE_PLL3_DIVP, RCC_PLL3CR, 4, 0), + GATE_CFG(GATE_PLL3_DIVQ, RCC_PLL3CR, 5, 0), + GATE_CFG(GATE_PLL3_DIVR, RCC_PLL3CR, 6, 0), + GATE_CFG(GATE_PLL4, RCC_PLL4CR, 0, 0), + GATE_CFG(GATE_PLL4_DIVP, RCC_PLL4CR, 4, 0), + GATE_CFG(GATE_PLL4_DIVQ, RCC_PLL4CR, 5, 0), + GATE_CFG(GATE_PLL4_DIVR, RCC_PLL4CR, 6, 0), + GATE_CFG(GATE_DDRC1, RCC_DDRITFCR, 0, 0), + GATE_CFG(GATE_DDRC1LP, RCC_DDRITFCR, 1, 0), + GATE_CFG(GATE_DDRPHYC, RCC_DDRITFCR, 4, 0), + GATE_CFG(GATE_DDRPHYCLP, RCC_DDRITFCR, 5, 0), + GATE_CFG(GATE_DDRCAPB, RCC_DDRITFCR, 6, 0), + GATE_CFG(GATE_DDRCAPBLP, RCC_DDRITFCR, 7, 0), + GATE_CFG(GATE_AXIDCG, RCC_DDRITFCR, 8, 0), + GATE_CFG(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9, 0), + GATE_CFG(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10, 0), + GATE_CFG(GATE_TIM2, RCC_MP_APB1ENSETR, 0, 1), + GATE_CFG(GATE_TIM3, RCC_MP_APB1ENSETR, 1, 1), + GATE_CFG(GATE_TIM4, RCC_MP_APB1ENSETR, 2, 1), + GATE_CFG(GATE_TIM5, RCC_MP_APB1ENSETR, 3, 1), + GATE_CFG(GATE_TIM6, RCC_MP_APB1ENSETR, 4, 1), + GATE_CFG(GATE_TIM7, RCC_MP_APB1ENSETR, 5, 1), + GATE_CFG(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9, 1), + GATE_CFG(GATE_SPI2, RCC_MP_APB1ENSETR, 11, 1), + GATE_CFG(GATE_SPI3, RCC_MP_APB1ENSETR, 12, 1), + GATE_CFG(GATE_USART3, RCC_MP_APB1ENSETR, 15, 1), + GATE_CFG(GATE_UART4, RCC_MP_APB1ENSETR, 16, 1), + GATE_CFG(GATE_UART5, RCC_MP_APB1ENSETR, 17, 1), + GATE_CFG(GATE_UART7, RCC_MP_APB1ENSETR, 18, 1), + GATE_CFG(GATE_UART8, RCC_MP_APB1ENSETR, 19, 1), + GATE_CFG(GATE_I2C1, RCC_MP_APB1ENSETR, 21, 1), + GATE_CFG(GATE_I2C2, RCC_MP_APB1ENSETR, 22, 1), + GATE_CFG(GATE_SPDIF, RCC_MP_APB1ENSETR, 26, 1), + GATE_CFG(GATE_TIM1, RCC_MP_APB2ENSETR, 0, 1), + GATE_CFG(GATE_TIM8, RCC_MP_APB2ENSETR, 1, 1), + GATE_CFG(GATE_SPI1, RCC_MP_APB2ENSETR, 8, 1), + GATE_CFG(GATE_USART6, RCC_MP_APB2ENSETR, 13, 1), + GATE_CFG(GATE_SAI1, RCC_MP_APB2ENSETR, 16, 1), + GATE_CFG(GATE_SAI2, RCC_MP_APB2ENSETR, 17, 1), + GATE_CFG(GATE_DFSDM, RCC_MP_APB2ENSETR, 20, 1), + GATE_CFG(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21, 1), + GATE_CFG(GATE_FDCAN, RCC_MP_APB2ENSETR, 24, 1), + GATE_CFG(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0, 1), + GATE_CFG(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1, 1), + GATE_CFG(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2, 1), + GATE_CFG(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3, 1), + GATE_CFG(GATE_VREF, RCC_MP_APB3ENSETR, 13, 1), + GATE_CFG(GATE_DTS, RCC_MP_APB3ENSETR, 16, 1), + GATE_CFG(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17, 1), + GATE_CFG(GATE_HDP, RCC_MP_APB3ENSETR, 20, 1), + GATE_CFG(GATE_SYSCFG, RCC_MP_S_APB3ENSETR, 0, 1), + GATE_CFG(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1, 1), + GATE_CFG(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8, 1), + GATE_CFG(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15, 1), + GATE_CFG(GATE_USBPHY, RCC_MP_APB4ENSETR, 16, 1), + GATE_CFG(GATE_STGENRO, RCC_MP_APB4ENSETR, 20, 1), + GATE_CFG(GATE_LTDC, RCC_MP_S_APB4ENSETR, 0, 1), + GATE_CFG(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8, 1), + GATE_CFG(GATE_TZC, RCC_MP_APB5ENSETR, 11, 1), + GATE_CFG(GATE_ETZPC, RCC_MP_APB5ENSETR, 13, 1), + GATE_CFG(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15, 1), + GATE_CFG(GATE_BSEC, RCC_MP_APB5ENSETR, 16, 1), + GATE_CFG(GATE_STGENC, RCC_MP_APB5ENSETR, 20, 1), + GATE_CFG(GATE_USART1, RCC_MP_APB6ENSETR, 0, 1), + GATE_CFG(GATE_USART2, RCC_MP_APB6ENSETR, 1, 1), + GATE_CFG(GATE_SPI4, RCC_MP_APB6ENSETR, 2, 1), + GATE_CFG(GATE_SPI5, RCC_MP_APB6ENSETR, 3, 1), + GATE_CFG(GATE_I2C3, RCC_MP_APB6ENSETR, 4, 1), + GATE_CFG(GATE_I2C4, RCC_MP_APB6ENSETR, 5, 1), + GATE_CFG(GATE_I2C5, RCC_MP_APB6ENSETR, 6, 1), + GATE_CFG(GATE_TIM12, RCC_MP_APB6ENSETR, 7, 1), + GATE_CFG(GATE_TIM13, RCC_MP_APB6ENSETR, 8, 1), + GATE_CFG(GATE_TIM14, RCC_MP_APB6ENSETR, 9, 1), + GATE_CFG(GATE_TIM15, RCC_MP_APB6ENSETR, 10, 1), + GATE_CFG(GATE_TIM16, RCC_MP_APB6ENSETR, 11, 1), + GATE_CFG(GATE_TIM17, RCC_MP_APB6ENSETR, 12, 1), + GATE_CFG(GATE_DMA1, RCC_MP_AHB2ENSETR, 0, 1), + GATE_CFG(GATE_DMA2, RCC_MP_AHB2ENSETR, 1, 1), + GATE_CFG(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2, 1), + GATE_CFG(GATE_DMA3, RCC_MP_AHB2ENSETR, 3, 1), + GATE_CFG(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4, 1), + GATE_CFG(GATE_ADC1, RCC_MP_AHB2ENSETR, 5, 1), + GATE_CFG(GATE_ADC2, RCC_MP_AHB2ENSETR, 6, 1), + GATE_CFG(GATE_USBO, RCC_MP_AHB2ENSETR, 8, 1), + GATE_CFG(GATE_TSC, RCC_MP_AHB4ENSETR, 15, 1), + + GATE_CFG(GATE_GPIOA, RCC_MP_S_AHB4ENSETR, 0, 1), + GATE_CFG(GATE_GPIOB, RCC_MP_S_AHB4ENSETR, 1, 1), + GATE_CFG(GATE_GPIOC, RCC_MP_S_AHB4ENSETR, 2, 1), + GATE_CFG(GATE_GPIOD, RCC_MP_S_AHB4ENSETR, 3, 1), + GATE_CFG(GATE_GPIOE, RCC_MP_S_AHB4ENSETR, 4, 1), + GATE_CFG(GATE_GPIOF, RCC_MP_S_AHB4ENSETR, 5, 1), + GATE_CFG(GATE_GPIOG, RCC_MP_S_AHB4ENSETR, 6, 1), + GATE_CFG(GATE_GPIOH, RCC_MP_S_AHB4ENSETR, 7, 1), + GATE_CFG(GATE_GPIOI, RCC_MP_S_AHB4ENSETR, 8, 1), + + GATE_CFG(GATE_PKA, RCC_MP_AHB5ENSETR, 2, 1), + GATE_CFG(GATE_SAES, RCC_MP_AHB5ENSETR, 3, 1), + GATE_CFG(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4, 1), + GATE_CFG(GATE_HASH1, RCC_MP_AHB5ENSETR, 5, 1), + GATE_CFG(GATE_RNG1, RCC_MP_AHB5ENSETR, 6, 1), + GATE_CFG(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8, 1), + GATE_CFG(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16, 1), + GATE_CFG(GATE_MCE, RCC_MP_AHB6ENSETR, 1, 1), + GATE_CFG(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7, 1), + GATE_CFG(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8, 1), + GATE_CFG(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9, 1), + GATE_CFG(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10, 1), + GATE_CFG(GATE_FMC, RCC_MP_AHB6ENSETR, 12, 1), + GATE_CFG(GATE_QSPI, RCC_MP_AHB6ENSETR, 14, 1), + GATE_CFG(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16, 1), + GATE_CFG(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17, 1), + GATE_CFG(GATE_CRC1, RCC_MP_AHB6ENSETR, 20, 1), + GATE_CFG(GATE_USBH, RCC_MP_AHB6ENSETR, 24, 1), + GATE_CFG(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27, 1), + GATE_CFG(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28, 1), + GATE_CFG(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29, 1), + GATE_CFG(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30, 1), + GATE_CFG(GATE_MDMA, RCC_MP_S_AHB6ENSETR, 0, 1), +}; + +/* + * DIV CONFIG + */ + +static const struct clk_div_table axi_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, + { 4, 4 }, { 5, 4 }, { 6, 4 }, { 7, 4 }, + { 0 }, +}; + +static const struct clk_div_table mlahb_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 }, + { 8, 256 }, { 9, 512 }, { 10, 512}, { 11, 512 }, + { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 }, + { 0 }, +}; + +static const struct clk_div_table apb_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, + { 0 }, +}; + +#define DIV_CFG(id, _offset, _shift, _width, _flags, _table, _bitrdy)[id] = {\ + .offset = _offset,\ + .shift = _shift,\ + .width = _width,\ + .flags = _flags,\ + .table = _table,\ + .bitrdy = _bitrdy,\ +} + +static const struct div_cfg dividers_mp13[] = { + DIV_CFG(DIV_PLL1DIVP, RCC_PLL1CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL2DIVP, RCC_PLL2CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL2DIVQ, RCC_PLL2CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL2DIVR, RCC_PLL2CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL3DIVP, RCC_PLL3CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL3DIVQ, RCC_PLL3CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL3DIVR, RCC_PLL3CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL4DIVP, RCC_PLL4CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL4DIVQ, RCC_PLL4CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL4DIVR, RCC_PLL4CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_MPU, RCC_MPCKDIVR, 0, 4, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_AXI, RCC_AXIDIVR, 0, 3, 0, axi_div_table, 31), + DIV_CFG(DIV_MLAHB, RCC_MLAHBDIVR, 0, 4, 0, mlahb_div_table, 31), + DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB5, RCC_APB5DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB6, RCC_APB6DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), + + DIV_CFG(DIV_HSI, RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, CLK_DIVIDER_POWER_OF_TWO, NULL, DIV_NO_BIT_RDY), + + DIV_CFG(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL, DIV_NO_BIT_RDY), +}; + +#define MAX_HSI_HZ 64000000 +#define USB_PHY_48_MHZ 48000000 + +#define TIMEOUT_US_200MS U(200000) +#define TIMEOUT_US_1S U(1000000) + +#define PLLRDY_TIMEOUT TIMEOUT_US_200MS +#define CLKSRC_TIMEOUT TIMEOUT_US_200MS +#define CLKDIV_TIMEOUT TIMEOUT_US_200MS +#define HSIDIV_TIMEOUT TIMEOUT_US_200MS +#define OSCRDY_TIMEOUT TIMEOUT_US_1S + +enum stm32_osc { + OSC_HSI, + OSC_HSE, + OSC_CSI, + OSC_LSI, + OSC_LSE, + OSC_I2SCKIN, + NB_OSCILLATOR +}; + +enum stm32mp1_pll_id { + _PLL1, + _PLL2, + _PLL3, + _PLL4, + _PLL_NB +}; + +enum stm32mp1_plltype { + PLL_800, + PLL_1600, + PLL_2000, + PLL_TYPE_NB +}; + +#define RCC_OFFSET_PLLXCR 0 +#define RCC_OFFSET_PLLXCFGR1 4 +#define RCC_OFFSET_PLLXCFGR2 8 +#define RCC_OFFSET_PLLXFRACR 12 +#define RCC_OFFSET_PLLXCSGR 16 + +struct stm32_clk_pll { + enum stm32mp1_plltype plltype; + uint16_t clk_id; + uint16_t reg_pllxcr; +}; + +struct stm32mp1_pll { + uint8_t refclk_min; + uint8_t refclk_max; +}; + +/* Define characteristic of PLL according type */ +static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { + [PLL_800] = { + .refclk_min = 4, + .refclk_max = 16, + }, + [PLL_1600] = { + .refclk_min = 8, + .refclk_max = 16, + }, + [PLL_2000] = { + .refclk_min = 8, + .refclk_max = 16, + }, +}; + +#if STM32MP_USB_PROGRAMMER +static bool pll4_bootrom; +#endif + +/* RCC clock device driver private */ +static unsigned int refcounts_mp13[CK_LAST]; + +static const struct stm32_clk_pll *clk_st32_pll_data(unsigned int idx); + +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER +static void clk_oscillator_check_bypass(struct stm32_clk_priv *priv, int idx, + bool digbyp, bool bypass) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, idx); + struct stm32_clk_bypass *bypass_data = osc_data->bypass; + uintptr_t address; + + if (bypass_data == NULL) { + return; + } + + address = priv->base + bypass_data->offset; + if ((mmio_read_32(address) & RCC_OCENR_HSEBYP) && + (!(digbyp || bypass))) { + panic(); + } +} +#endif + +static void stm32_enable_oscillator_hse(struct stm32_clk_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE]; + bool digbyp = osci->digbyp; + bool bypass = osci->bypass; + bool css = osci->css; + + if (_clk_stm32_get_rate(priv, _CK_HSE) == 0U) { + return; + } + + clk_oscillator_set_bypass(priv, _CK_HSE, digbyp, bypass); + + _clk_stm32_enable(priv, _CK_HSE); + +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER + clk_oscillator_check_bypass(priv, _CK_HSE, digbyp, bypass); +#endif + + clk_oscillator_set_css(priv, _CK_HSE, css); +} + +static void stm32_enable_oscillator_lse(struct stm32_clk_priv *priv) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, _CK_LSE); + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; + bool digbyp = osci->digbyp; + bool bypass = osci->bypass; + uint8_t drive = osci->drive; + + if (_clk_stm32_get_rate(priv, _CK_LSE) == 0U) { + return; + } + + clk_oscillator_set_bypass(priv, _CK_LSE, digbyp, bypass); + + clk_oscillator_set_drive(priv, _CK_LSE, drive); + + _clk_stm32_gate_enable(priv, osc_data->gate_id); +} + +static int stm32mp1_set_hsidiv(uint8_t hsidiv) +{ + uint64_t timeout; + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t address = rcc_base + RCC_OCRDYR; + + mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, + RCC_HSICFGR_HSIDIV_MASK, + RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); + + timeout = timeout_init_us(HSIDIV_TIMEOUT); + while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", + address, mmio_read_32(address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int stm32mp1_hsidiv(unsigned long hsifreq) +{ + uint8_t hsidiv; + uint32_t hsidivfreq = MAX_HSI_HZ; + + for (hsidiv = 0; hsidiv < 4U; hsidiv++) { + if (hsidivfreq == hsifreq) { + break; + } + + hsidivfreq /= 2U; + } + + if (hsidiv == 4U) { + ERROR("Invalid clk-hsi frequency\n"); + return -EINVAL; + } + + if (hsidiv != 0U) { + return stm32mp1_set_hsidiv(hsidiv); + } + + return 0; +} + +static int stm32_clk_oscillators_lse_set_css(struct stm32_clk_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; + + clk_oscillator_set_css(priv, _CK_LSE, osci->css); + + return 0; +} + +static int stm32mp1_come_back_to_hsi(void) +{ + int ret; + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + + /* Come back to HSI */ + ret = _clk_stm32_set_parent(priv, _CKMPU, _CK_HSI); + if (ret != 0) { + return ret; + } + + ret = _clk_stm32_set_parent(priv, _CKAXI, _CK_HSI); + if (ret != 0) { + return ret; + } + + ret = _clk_stm32_set_parent(priv, _CKMLAHB, _CK_HSI); + if (ret != 0) { + return ret; + } + + return 0; +} + +static int stm32_clk_configure_clk_get_binding_id(struct stm32_clk_priv *priv, uint32_t data) +{ + unsigned long binding_id = ((unsigned long)data & CLK_ID_MASK) >> CLK_ID_SHIFT; + + return clk_get_index(priv, binding_id); +} + +static int stm32_clk_configure_clk(struct stm32_clk_priv *priv, uint32_t data) +{ + int sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT; + int enable = (data & CLK_ON_MASK) >> CLK_ON_SHIFT; + int clk_id; + int ret; + + clk_id = stm32_clk_configure_clk_get_binding_id(priv, data); + if (clk_id < 0) { + return clk_id; + } + + ret = _clk_stm32_set_parent_by_index(priv, clk_id, sel); + if (ret != 0) { + return ret; + } + + if (enable) { + clk_stm32_enable_call_ops(priv, clk_id); + } else { + clk_stm32_disable_call_ops(priv, clk_id); + } + + return 0; +} + +static int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t data) +{ + int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT; + int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT; + + return clk_mux_set_parent(priv, mux, sel); +} + +static int stm32_clk_dividers_configure(struct stm32_clk_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + uint32_t i; + + for (i = 0; i < pdata->nclkdiv; i++) { + int div_id, div_n; + int val; + int ret; + + val = pdata->clkdiv[i] & CMD_DATA_MASK; + div_id = (val & DIV_ID_MASK) >> DIV_ID_SHIFT; + div_n = (val & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT; + + ret = clk_stm32_set_div(priv, div_id, div_n); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +static int stm32_clk_source_configure(struct stm32_clk_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + bool ckper_disabled = false; + int clk_id; + int ret; + uint32_t i; + + for (i = 0; i < pdata->nclksrc; i++) { + uint32_t val = pdata->clksrc[i]; + uint32_t cmd, cmd_data; + + if (val == (uint32_t)CLK_CKPER_DISABLED) { + ckper_disabled = true; + continue; + } + + if (val == (uint32_t)CLK_RTC_DISABLED) { + continue; + } + + cmd = (val & CMD_MASK) >> CMD_SHIFT; + cmd_data = val & ~CMD_MASK; + + switch (cmd) { + case CMD_MUX: + ret = stm32_clk_configure_mux(priv, cmd_data); + break; + + case CMD_CLK: + clk_id = stm32_clk_configure_clk_get_binding_id(priv, cmd_data); + + if (clk_id == _RTCCK) { + if ((_clk_stm32_is_enabled(priv, _RTCCK) == true)) { + continue; + } + } + + ret = stm32_clk_configure_clk(priv, cmd_data); + break; + default: + ret = -EINVAL; + break; + } + + if (ret != 0) { + return ret; + } + } + + /* + * CKPER is source for some peripheral clocks + * (FMC-NAND / QPSI-NOR) and switching source is allowed + * only if previous clock is still ON + * => deactivate CKPER only after switching clock + */ + if (ckper_disabled) { + ret = stm32_clk_configure_mux(priv, CLK_CKPER_DISABLED & CMD_MASK); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +static int stm32_clk_stgen_configure(struct stm32_clk_priv *priv, int id) +{ + unsigned long stgen_freq; + + stgen_freq = _clk_stm32_get_rate(priv, id); + + stm32mp_stgen_config(stgen_freq); + + return 0; +} + +#define CLK_PLL_CFG(_idx, _clk_id, _type, _reg)\ + [(_idx)] = {\ + .clk_id = (_clk_id),\ + .plltype = (_type),\ + .reg_pllxcr = (_reg),\ + } + +static int clk_stm32_pll_compute_cfgr1(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco, + uint32_t *value) +{ + uint32_t divm = vco->div_mn[PLL_CFG_M]; + uint32_t divn = vco->div_mn[PLL_CFG_N]; + unsigned long prate = 0UL; + unsigned long refclk = 0UL; + + prate = _clk_stm32_get_parent_rate(priv, pll->clk_id); + refclk = prate / (divm + 1U); + + if ((refclk < (stm32mp1_pll[pll->plltype].refclk_min * 1000000U)) || + (refclk > (stm32mp1_pll[pll->plltype].refclk_max * 1000000U))) { + return -EINVAL; + } + + *value = 0; + + if ((pll->plltype == PLL_800) && (refclk >= 8000000U)) { + *value = 1U << RCC_PLLNCFGR1_IFRGE_SHIFT; + } + + *value |= (divn << RCC_PLLNCFGR1_DIVN_SHIFT) & RCC_PLLNCFGR1_DIVN_MASK; + *value |= (divm << RCC_PLLNCFGR1_DIVM_SHIFT) & RCC_PLLNCFGR1_DIVM_MASK; + + return 0; +} + +static uint32_t clk_stm32_pll_compute_cfgr2(struct stm32_pll_output *out) +{ + uint32_t value = 0; + + value |= (out->output[PLL_CFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & RCC_PLLNCFGR2_DIVP_MASK; + value |= (out->output[PLL_CFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & RCC_PLLNCFGR2_DIVQ_MASK; + value |= (out->output[PLL_CFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & RCC_PLLNCFGR2_DIVR_MASK; + + return value; +} + +static void clk_stm32_pll_config_vco(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t value = 0; + + if (clk_stm32_pll_compute_cfgr1(priv, pll, vco, &value) != 0) { + ERROR("Invalid Vref clock !\n"); + panic(); + } + + /* Write N / M / IFREGE fields */ + mmio_write_32(pll_base + RCC_OFFSET_PLLXCFGR1, value); + + /* Fractional configuration */ + mmio_write_32(pll_base + RCC_OFFSET_PLLXFRACR, 0); + + /* Frac must be enabled only once its configuration is loaded */ + mmio_write_32(pll_base + RCC_OFFSET_PLLXFRACR, vco->frac << RCC_PLLNFRACR_FRACV_SHIFT); + mmio_setbits_32(pll_base + RCC_OFFSET_PLLXFRACR, RCC_PLLNFRACR_FRACLE); +} + +static void clk_stm32_pll_config_csg(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t mod_per = 0; + uint32_t inc_step = 0; + uint32_t sscg_mode = 0; + uint32_t value = 0; + + if (!vco->csg_enabled) { + return; + } + + mod_per = vco->csg[PLL_CSG_MOD_PER]; + inc_step = vco->csg[PLL_CSG_INC_STEP]; + sscg_mode = vco->csg[PLL_CSG_SSCG_MODE]; + + value |= (mod_per << RCC_PLLNCSGR_MOD_PER_SHIFT) & RCC_PLLNCSGR_MOD_PER_MASK; + value |= (inc_step << RCC_PLLNCSGR_INC_STEP_SHIFT) & RCC_PLLNCSGR_INC_STEP_MASK; + value |= (sscg_mode << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & RCC_PLLNCSGR_SSCG_MODE_MASK; + + mmio_write_32(pll_base + RCC_OFFSET_PLLXCSGR, value); + mmio_setbits_32(pll_base + RCC_OFFSET_PLLXCR, RCC_PLLNCR_SSCG_CTRL); +} + +static void clk_stm32_pll_config_out(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll, + struct stm32_pll_output *out) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t value = 0; + + value = clk_stm32_pll_compute_cfgr2(out); + + mmio_write_32(pll_base + RCC_OFFSET_PLLXCFGR2, value); +} + +static inline struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(int pll_idx) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + struct stm32_clk_platdata *pdata = priv->pdata; + + return &pdata->pll[pll_idx]; +} + +static bool _clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + + return ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLON) != 0U); +} + +static void _clk_stm32_pll_set_on(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + + /* Preserve RCC_PLLNCR_SSCG_CTRL value */ + mmio_clrsetbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN, + RCC_PLLNCR_PLLON); +} + +static void _clk_stm32_pll_set_off(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + + /* Stop all output */ + mmio_clrbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); + + /* Stop PLL */ + mmio_clrbits_32(pll_base, RCC_PLLNCR_PLLON); +} + +static int _clk_stm32_pll_wait_ready_on(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); + + /* Wait PLL lock */ + while ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%d clock start failed @ 0x%x: 0x%x\n", + pll->clk_id, pll->reg_pllxcr, mmio_read_32(pll_base)); + return -EINVAL; + } + } + + return 0; +} + +static int _clk_stm32_pll_wait_ready_off(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); + + /* Wait PLL lock */ + while ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLRDY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%d clock stop failed @ 0x%x: 0x%x\n", + pll->clk_id, pll->reg_pllxcr, mmio_read_32(pll_base)); + return -EINVAL; + } + } + + return 0; +} + +static int _clk_stm32_pll_enable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + if (_clk_stm32_pll_is_enabled(priv, pll)) { + return 0; + } + + /* Preserve RCC_PLLNCR_SSCG_CTRL value */ + _clk_stm32_pll_set_on(priv, pll); + + /* Wait PLL lock */ + return _clk_stm32_pll_wait_ready_on(priv, pll); +} + +static void _clk_stm32_pll_disable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + if (!_clk_stm32_pll_is_enabled(priv, pll)) { + return; + } + + /* Stop all outputs and the PLL */ + _clk_stm32_pll_set_off(priv, pll); + + /* Wait PLL stopped */ + _clk_stm32_pll_wait_ready_off(priv, pll); +} + +static int _clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx, + struct stm32_pll_dt_cfg *pll_conf) +{ + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_idx); + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + int ret = 0; + + /* Configure PLLs source */ + ret = stm32_clk_configure_mux(priv, pll_conf->vco.src); + if (ret) { + return ret; + } + +#if STM32MP_USB_PROGRAMMER + if ((pll_idx == _PLL4) && pll4_bootrom) { + clk_stm32_pll_config_out(priv, pll, &pll_conf->output); + + mmio_setbits_32(pll_base, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); + + return 0; + } +#endif + /* Stop the PLL before */ + _clk_stm32_pll_disable(priv, pll); + + clk_stm32_pll_config_vco(priv, pll, &pll_conf->vco); + clk_stm32_pll_config_out(priv, pll, &pll_conf->output); + clk_stm32_pll_config_csg(priv, pll, &pll_conf->vco); + + ret = _clk_stm32_pll_enable(priv, pll); + if (ret != 0) { + return ret; + } + + mmio_setbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); + + return 0; +} + +static int clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx) +{ + struct stm32_pll_dt_cfg *pll_conf = clk_stm32_pll_get_pdata(pll_idx); + + if (pll_conf->vco.status) { + return _clk_stm32_pll_init(priv, pll_idx, pll_conf); + } + + return 0; +} + +static int stm32_clk_pll_configure(struct stm32_clk_priv *priv) +{ + int err = 0; + + err = clk_stm32_pll_init(priv, _PLL1); + if (err) { + return err; + } + + err = clk_stm32_pll_init(priv, _PLL2); + if (err) { + return err; + } + + err = clk_stm32_pll_init(priv, _PLL3); + if (err) { + return err; + } + + err = clk_stm32_pll_init(priv, _PLL4); + if (err) { + return err; + } + + return 0; +} + +static int stm32_clk_oscillators_wait_lse_ready(struct stm32_clk_priv *priv) +{ + int ret = 0; + + if (_clk_stm32_get_rate(priv, _CK_LSE) != 0U) { + ret = clk_oscillator_wait_ready_on(priv, _CK_LSE); + } + + return ret; +} + +static void stm32_clk_oscillators_enable(struct stm32_clk_priv *priv) +{ + stm32_enable_oscillator_hse(priv); + stm32_enable_oscillator_lse(priv); + _clk_stm32_enable(priv, _CK_LSI); + _clk_stm32_enable(priv, _CK_CSI); +} + +static int stm32_clk_hsidiv_configure(struct stm32_clk_priv *priv) +{ + return stm32mp1_hsidiv(_clk_stm32_get_rate(priv, _CK_HSI)); +} + +#if STM32MP_USB_PROGRAMMER +static bool stm32mp1_clk_is_pll4_used_by_bootrom(struct stm32_clk_priv *priv, int usbphy_p) +{ + /* Don't initialize PLL4, when used by BOOTROM */ + if ((stm32mp_get_boot_itf_selected() == + BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) && + (usbphy_p == _PLL4R)) { + return true; + } + + return false; +} + +static int stm32mp1_clk_check_usb_conflict(struct stm32_clk_priv *priv, int usbphy_p, int usbo_p) +{ + int _usbo_p; + int _usbphy_p; + + if (!pll4_bootrom) { + return 0; + } + + _usbo_p = _clk_stm32_get_parent(priv, _USBO_K); + _usbphy_p = _clk_stm32_get_parent(priv, _USBPHY_K); + + if ((_usbo_p != usbo_p) || (_usbphy_p != usbphy_p)) { + return -FDT_ERR_BADVALUE; + } + + return 0; +} +#endif + +static struct clk_oscillator_data stm32mp13_osc_data[NB_OSCILLATOR] = { + OSCILLATOR(OSC_HSI, _CK_HSI, "clk-hsi", GATE_HSI, GATE_HSI_RDY, + NULL, NULL, NULL), + + OSCILLATOR(OSC_LSI, _CK_LSI, "clk-lsi", GATE_LSI, GATE_LSI_RDY, + NULL, NULL, NULL), + + OSCILLATOR(OSC_CSI, _CK_CSI, "clk-csi", GATE_CSI, GATE_CSI_RDY, + NULL, NULL, NULL), + + OSCILLATOR(OSC_LSE, _CK_LSE, "clk-lse", GATE_LSE, GATE_LSE_RDY, + BYPASS(RCC_BDCR, 1, 3), + CSS(RCC_BDCR, 8), + DRIVE(RCC_BDCR, 4, 2, 2)), + + OSCILLATOR(OSC_HSE, _CK_HSE, "clk-hse", GATE_HSE, GATE_HSE_RDY, + BYPASS(RCC_OCENSETR, 10, 7), + CSS(RCC_OCENSETR, 11), + NULL), + + OSCILLATOR(OSC_I2SCKIN, _I2SCKIN, "i2s_ckin", NO_GATE, NO_GATE, + NULL, NULL, NULL), +}; + +static const char *clk_stm32_get_oscillator_name(enum stm32_osc id) +{ + if (id < NB_OSCILLATOR) { + return stm32mp13_osc_data[id].name; + } + + return NULL; +} + +#define CLK_PLL_CFG(_idx, _clk_id, _type, _reg)\ + [(_idx)] = {\ + .clk_id = (_clk_id),\ + .plltype = (_type),\ + .reg_pllxcr = (_reg),\ + } + +static const struct stm32_clk_pll stm32_mp13_clk_pll[_PLL_NB] = { + CLK_PLL_CFG(_PLL1, _CK_PLL1, PLL_2000, RCC_PLL1CR), + CLK_PLL_CFG(_PLL2, _CK_PLL2, PLL_1600, RCC_PLL2CR), + CLK_PLL_CFG(_PLL3, _CK_PLL3, PLL_800, RCC_PLL3CR), + CLK_PLL_CFG(_PLL4, _CK_PLL4, PLL_800, RCC_PLL4CR), +}; + +static const struct stm32_clk_pll *clk_st32_pll_data(unsigned int idx) +{ + return &stm32_mp13_clk_pll[idx]; +} + +struct stm32_pll_cfg { + int pll_id; +}; + +static unsigned long clk_stm32_pll_recalc_rate(struct stm32_clk_priv *priv, int id, + unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t cfgr1, fracr, divm, divn; + unsigned long fvco; + + cfgr1 = mmio_read_32(pll_base + RCC_OFFSET_PLLXCFGR1); + fracr = mmio_read_32(pll_base + RCC_OFFSET_PLLXFRACR); + + divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; + divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; + + /* + * With FRACV : + * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) + * Without FRACV + * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) + */ + if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { + uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> + RCC_PLLNFRACR_FRACV_SHIFT; + unsigned long long numerator, denominator; + + numerator = (((unsigned long long)divn + 1U) << 13) + fracv; + numerator = prate * numerator; + denominator = ((unsigned long long)divm + 1U) << 13; + fvco = (unsigned long)(numerator / denominator); + } else { + fvco = (unsigned long)(prate * (divn + 1U) / (divm + 1U)); + } + + return fvco; +}; + +static bool clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); + + return _clk_stm32_pll_is_enabled(priv, pll); +} + +static int clk_stm32_pll_enable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); + + return _clk_stm32_pll_enable(priv, pll); +} + +static void clk_stm32_pll_disable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); + + _clk_stm32_pll_disable(priv, pll); +} + +static const struct stm32_clk_ops clk_stm32_pll_ops = { + .recalc_rate = clk_stm32_pll_recalc_rate, + .enable = clk_stm32_pll_enable, + .disable = clk_stm32_pll_disable, + .is_enabled = clk_stm32_pll_is_enabled, +}; + +#define CLK_PLL(idx, _idx, _parent, _gate, _pll_id, _flags)[idx] = {\ + .name = #idx,\ + .binding = _idx,\ + .parent = _parent,\ + .flags = (_flags),\ + .clock_cfg = &(struct stm32_pll_cfg) {\ + .pll_id = _pll_id,\ + },\ + .ops = &clk_stm32_pll_ops,\ +} + +struct clk_stm32_composite_cfg { + int gate_id; + int div_id; +}; + +static unsigned long clk_stm32_composite_recalc_rate(struct stm32_clk_priv *priv, + int idx, unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, idx); + struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; + + return _clk_stm32_divider_recalc(priv, composite_cfg->div_id, prate); +}; + +static bool clk_stm32_composite_gate_is_enabled(struct stm32_clk_priv *priv, int idx) +{ + const struct clk_stm32 *clk = _clk_get(priv, idx); + struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; + + return _clk_stm32_gate_is_enabled(priv, composite_cfg->gate_id); +} + +static int clk_stm32_composite_gate_enable(struct stm32_clk_priv *priv, int idx) +{ + const struct clk_stm32 *clk = _clk_get(priv, idx); + struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; + + return _clk_stm32_gate_enable(priv, composite_cfg->gate_id); +} + +static void clk_stm32_composite_gate_disable(struct stm32_clk_priv *priv, int idx) +{ + const struct clk_stm32 *clk = _clk_get(priv, idx); + struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; + + _clk_stm32_gate_disable(priv, composite_cfg->gate_id); +} + +static const struct stm32_clk_ops clk_stm32_composite_ops = { + .recalc_rate = clk_stm32_composite_recalc_rate, + .is_enabled = clk_stm32_composite_gate_is_enabled, + .enable = clk_stm32_composite_gate_enable, + .disable = clk_stm32_composite_gate_disable, +}; + +#define STM32_COMPOSITE(idx, _binding, _parent, _flags, _gate_id,\ + _div_id)[idx] = {\ + .name = #idx,\ + .binding = (_binding),\ + .parent = (_parent),\ + .flags = (_flags),\ + .clock_cfg = &(struct clk_stm32_composite_cfg) {\ + .gate_id = (_gate_id),\ + .div_id = (_div_id),\ + },\ + .ops = &clk_stm32_composite_ops,\ +} + +static const struct clk_stm32 stm32mp13_clk[CK_LAST] = { + /* ROOT CLOCKS */ + CLK_FIXED_RATE(_CK_OFF, _NO_ID, 0), + CLK_OSC(_CK_HSE, CK_HSE, CLK_IS_ROOT, OSC_HSE), + CLK_OSC(_CK_HSI, CK_HSI, CLK_IS_ROOT, OSC_HSI), + CLK_OSC(_CK_CSI, CK_CSI, CLK_IS_ROOT, OSC_CSI), + CLK_OSC(_CK_LSI, CK_LSI, CLK_IS_ROOT, OSC_LSI), + CLK_OSC(_CK_LSE, CK_LSE, CLK_IS_ROOT, OSC_LSE), + + CLK_OSC_FIXED(_I2SCKIN, _NO_ID, CLK_IS_ROOT, OSC_I2SCKIN), + + CLK_FIXED_RATE(_USB_PHY_48, _NO_ID, USB_PHY_48_MHZ), + + STM32_DIV(_HSE_DIV, _NO_ID, _CK_HSE, 0, DIV_RTC), + + FIXED_FACTOR(_HSE_DIV2, CK_HSE_DIV2, _CK_HSE, 1, 2), + FIXED_FACTOR(_CSI_DIV122, _NO_ID, _CK_CSI, 1, 122), + + CLK_PLL(_CK_PLL1, PLL1, MUX(MUX_PLL12), GATE_PLL1, _PLL1, 0), + CLK_PLL(_CK_PLL2, PLL2, MUX(MUX_PLL12), GATE_PLL2, _PLL2, 0), + CLK_PLL(_CK_PLL3, PLL3, MUX(MUX_PLL3), GATE_PLL3, _PLL3, 0), + CLK_PLL(_CK_PLL4, PLL4, MUX(MUX_PLL4), GATE_PLL4, _PLL4, 0), + + STM32_COMPOSITE(_PLL1P, PLL1_P, _CK_PLL1, CLK_IS_CRITICAL, GATE_PLL1_DIVP, DIV_PLL1DIVP), + STM32_DIV(_PLL1P_DIV, _NO_ID, _CK_PLL1, 0, DIV_MPU), + + STM32_COMPOSITE(_PLL2P, PLL2_P, _CK_PLL2, CLK_IS_CRITICAL, GATE_PLL2_DIVP, DIV_PLL2DIVP), + STM32_COMPOSITE(_PLL2Q, PLL2_Q, _CK_PLL2, 0, GATE_PLL2_DIVQ, DIV_PLL2DIVQ), + STM32_COMPOSITE(_PLL2R, PLL2_R, _CK_PLL2, CLK_IS_CRITICAL, GATE_PLL2_DIVR, DIV_PLL2DIVR), + + STM32_COMPOSITE(_PLL3P, PLL3_P, _CK_PLL3, 0, GATE_PLL3_DIVP, DIV_PLL3DIVP), + STM32_COMPOSITE(_PLL3Q, PLL3_Q, _CK_PLL3, 0, GATE_PLL3_DIVQ, DIV_PLL3DIVQ), + STM32_COMPOSITE(_PLL3R, PLL3_R, _CK_PLL3, 0, GATE_PLL3_DIVR, DIV_PLL3DIVR), + + STM32_COMPOSITE(_PLL4P, PLL4_P, _CK_PLL4, 0, GATE_PLL4_DIVP, DIV_PLL4DIVP), + STM32_COMPOSITE(_PLL4Q, PLL4_Q, _CK_PLL4, 0, GATE_PLL4_DIVQ, DIV_PLL4DIVQ), + STM32_COMPOSITE(_PLL4R, PLL4_R, _CK_PLL4, 0, GATE_PLL4_DIVR, DIV_PLL4DIVR), + + STM32_MUX(_CKMPU, CK_MPU, MUX_MPU, 0), + STM32_DIV(_CKAXI, CK_AXI, MUX(MUX_AXI), 0, DIV_AXI), + STM32_DIV(_CKMLAHB, CK_MLAHB, MUX(MUX_MLAHB), CLK_IS_CRITICAL, DIV_MLAHB), + STM32_MUX(_CKPER, CK_PER, MUX(MUX_CKPER), 0), + + STM32_DIV(_PCLK1, PCLK1, _CKMLAHB, 0, DIV_APB1), + STM32_DIV(_PCLK2, PCLK2, _CKMLAHB, 0, DIV_APB2), + STM32_DIV(_PCLK3, PCLK3, _CKMLAHB, 0, DIV_APB3), + STM32_DIV(_PCLK4, PCLK4, _CKAXI, 0, DIV_APB4), + STM32_DIV(_PCLK5, PCLK5, _CKAXI, 0, DIV_APB5), + STM32_DIV(_PCLK6, PCLK6, _CKMLAHB, 0, DIV_APB6), + + CK_TIMER(_CKTIMG1, CK_TIMG1, _PCLK1, 0, RCC_APB1DIVR, RCC_TIMG1PRER), + CK_TIMER(_CKTIMG2, CK_TIMG2, _PCLK2, 0, RCC_APB2DIVR, RCC_TIMG2PRER), + CK_TIMER(_CKTIMG3, CK_TIMG3, _PCLK6, 0, RCC_APB6DIVR, RCC_TIMG3PRER), + + /* END ROOT CLOCKS */ + + STM32_GATE(_DDRC1, DDRC1, _CKAXI, CLK_IS_CRITICAL, GATE_DDRC1), + STM32_GATE(_DDRC1LP, DDRC1LP, _CKAXI, CLK_IS_CRITICAL, GATE_DDRC1LP), + STM32_GATE(_DDRPHYC, DDRPHYC, _PLL2R, CLK_IS_CRITICAL, GATE_DDRPHYC), + STM32_GATE(_DDRPHYCLP, DDRPHYCLP, _PLL2R, CLK_IS_CRITICAL, GATE_DDRPHYCLP), + STM32_GATE(_DDRCAPB, DDRCAPB, _PCLK4, CLK_IS_CRITICAL, GATE_DDRCAPB), + STM32_GATE(_DDRCAPBLP, DDRCAPBLP, _PCLK4, CLK_IS_CRITICAL, GATE_DDRCAPBLP), + STM32_GATE(_AXIDCG, AXIDCG, _CKAXI, CLK_IS_CRITICAL, GATE_AXIDCG), + STM32_GATE(_DDRPHYCAPB, DDRPHYCAPB, _PCLK4, CLK_IS_CRITICAL, GATE_DDRPHYCAPB), + STM32_GATE(_DDRPHYCAPBLP, DDRPHYCAPBLP, _PCLK4, CLK_IS_CRITICAL, GATE_DDRPHYCAPBLP), + + STM32_GATE(_SYSCFG, SYSCFG, _PCLK3, 0, GATE_SYSCFG), + STM32_GATE(_DDRPERFM, DDRPERFM, _PCLK4, 0, GATE_DDRPERFM), + STM32_GATE(_IWDG2APB, IWDG2, _PCLK4, 0, GATE_IWDG2APB), + STM32_GATE(_USBPHY_K, USBPHY_K, MUX(MUX_USBPHY), 0, GATE_USBPHY), + STM32_GATE(_USBO_K, USBO_K, MUX(MUX_USBO), 0, GATE_USBO), + + STM32_GATE(_RTCAPB, RTCAPB, _PCLK5, CLK_IS_CRITICAL, GATE_RTCAPB), + STM32_GATE(_TZC, TZC, _PCLK5, CLK_IS_CRITICAL, GATE_TZC), + STM32_GATE(_ETZPC, TZPC, _PCLK5, CLK_IS_CRITICAL, GATE_ETZPC), + STM32_GATE(_IWDG1APB, IWDG1, _PCLK5, 0, GATE_IWDG1APB), + STM32_GATE(_BSEC, BSEC, _PCLK5, CLK_IS_CRITICAL, GATE_BSEC), + STM32_GATE(_STGENC, STGEN_K, MUX(MUX_STGEN), CLK_IS_CRITICAL, GATE_STGENC), + + STM32_GATE(_USART1_K, USART1_K, MUX(MUX_UART1), 0, GATE_USART1), + STM32_GATE(_USART2_K, USART2_K, MUX(MUX_UART2), 0, GATE_USART2), + STM32_GATE(_I2C3_K, I2C3_K, MUX(MUX_I2C3), 0, GATE_I2C3), + STM32_GATE(_I2C4_K, I2C4_K, MUX(MUX_I2C4), 0, GATE_I2C4), + STM32_GATE(_I2C5_K, I2C5_K, MUX(MUX_I2C5), 0, GATE_I2C5), + STM32_GATE(_TIM12, TIM12_K, _CKTIMG3, 0, GATE_TIM12), + STM32_GATE(_TIM15, TIM15_K, _CKTIMG3, 0, GATE_TIM15), + + STM32_GATE(_RTCCK, RTC, MUX(MUX_RTC), 0, GATE_RTCCK), + + STM32_GATE(_GPIOA, GPIOA, _CKMLAHB, 0, GATE_GPIOA), + STM32_GATE(_GPIOB, GPIOB, _CKMLAHB, 0, GATE_GPIOB), + STM32_GATE(_GPIOC, GPIOC, _CKMLAHB, 0, GATE_GPIOC), + STM32_GATE(_GPIOD, GPIOD, _CKMLAHB, 0, GATE_GPIOD), + STM32_GATE(_GPIOE, GPIOE, _CKMLAHB, 0, GATE_GPIOE), + STM32_GATE(_GPIOF, GPIOF, _CKMLAHB, 0, GATE_GPIOF), + STM32_GATE(_GPIOG, GPIOG, _CKMLAHB, 0, GATE_GPIOG), + STM32_GATE(_GPIOH, GPIOH, _CKMLAHB, 0, GATE_GPIOH), + STM32_GATE(_GPIOI, GPIOI, _CKMLAHB, 0, GATE_GPIOI), + + STM32_GATE(_PKA, PKA, _CKAXI, 0, GATE_PKA), + STM32_GATE(_SAES_K, SAES_K, MUX(MUX_SAES), 0, GATE_SAES), + STM32_GATE(_CRYP1, CRYP1, _PCLK5, 0, GATE_CRYP1), + STM32_GATE(_HASH1, HASH1, _PCLK5, 0, GATE_HASH1), + + STM32_GATE(_RNG1_K, RNG1_K, MUX(MUX_RNG1), 0, GATE_RNG1), + STM32_GATE(_BKPSRAM, BKPSRAM, _PCLK5, CLK_IS_CRITICAL, GATE_BKPSRAM), + + STM32_GATE(_SDMMC1_K, SDMMC1_K, MUX(MUX_SDMMC1), 0, GATE_SDMMC1), + STM32_GATE(_SDMMC2_K, SDMMC2_K, MUX(MUX_SDMMC2), 0, GATE_SDMMC2), + STM32_GATE(_DBGCK, CK_DBG, _CKAXI, 0, GATE_DBGCK), + +/* TODO: CHECK CLOCK FOR BL2/BL32 AND IF ONLY FOR TEST OR NOT */ + STM32_GATE(_USART3_K, USART3_K, MUX(MUX_UART35), 0, GATE_USART3), + STM32_GATE(_UART4_K, UART4_K, MUX(MUX_UART4), 0, GATE_UART4), + STM32_GATE(_UART5_K, UART5_K, MUX(MUX_UART35), 0, GATE_UART5), + STM32_GATE(_UART7_K, UART7_K, MUX(MUX_UART78), 0, GATE_UART7), + STM32_GATE(_UART8_K, UART8_K, MUX(MUX_UART78), 0, GATE_UART8), + STM32_GATE(_USART6_K, USART6_K, MUX(MUX_UART6), 0, GATE_USART6), + STM32_GATE(_MCE, MCE, _CKAXI, CLK_IS_CRITICAL, GATE_MCE), + STM32_GATE(_FMC_K, FMC_K, MUX(MUX_FMC), 0, GATE_FMC), + STM32_GATE(_QSPI_K, QSPI_K, MUX(MUX_QSPI), 0, GATE_QSPI), + + STM32_COMPOSITE(_MCO1_K, CK_MCO1, MUX(MUX_MCO1), 0, GATE_MCO1, DIV_MCO1), + STM32_COMPOSITE(_MCO2_K, CK_MCO2, MUX(MUX_MCO2), 0, GATE_MCO2, DIV_MCO2), + STM32_COMPOSITE(_TRACECK, CK_TRACE, _CKAXI, 0, GATE_TRACECK, DIV_TRACE), + +#if defined(IMAGE_BL32) + STM32_GATE(_TIM2, TIM2_K, _CKTIMG1, 0, GATE_TIM2), + STM32_GATE(_TIM3, TIM3_K, _CKTIMG1, 0, GATE_TIM3), + STM32_GATE(_TIM4, TIM4_K, _CKTIMG1, 0, GATE_TIM4), + STM32_GATE(_TIM5, TIM5_K, _CKTIMG1, 0, GATE_TIM5), + STM32_GATE(_TIM6, TIM6_K, _CKTIMG1, 0, GATE_TIM6), + STM32_GATE(_TIM7, TIM7_K, _CKTIMG1, 0, GATE_TIM7), + STM32_GATE(_TIM13, TIM13_K, _CKTIMG3, 0, GATE_TIM13), + STM32_GATE(_TIM14, TIM14_K, _CKTIMG3, 0, GATE_TIM14), + STM32_GATE(_LPTIM1_K, LPTIM1_K, MUX(MUX_LPTIM1), 0, GATE_LPTIM1), + STM32_GATE(_SPI2_K, SPI2_K, MUX(MUX_SPI23), 0, GATE_SPI2), + STM32_GATE(_SPI3_K, SPI3_K, MUX(MUX_SPI23), 0, GATE_SPI3), + STM32_GATE(_SPDIF_K, SPDIF_K, MUX(MUX_SPDIF), 0, GATE_SPDIF), + STM32_GATE(_TIM1, TIM1_K, _CKTIMG2, 0, GATE_TIM1), + STM32_GATE(_TIM8, TIM8_K, _CKTIMG2, 0, GATE_TIM8), + STM32_GATE(_TIM16, TIM16_K, _CKTIMG3, 0, GATE_TIM16), + STM32_GATE(_TIM17, TIM17_K, _CKTIMG3, 0, GATE_TIM17), + STM32_GATE(_SPI1_K, SPI1_K, MUX(MUX_SPI1), 0, GATE_SPI1), + STM32_GATE(_SPI4_K, SPI4_K, MUX(MUX_SPI4), 0, GATE_SPI4), + STM32_GATE(_SPI5_K, SPI5_K, MUX(MUX_SPI5), 0, GATE_SPI5), + STM32_GATE(_SAI1_K, SAI1_K, MUX(MUX_SAI1), 0, GATE_SAI1), + STM32_GATE(_SAI2_K, SAI2_K, MUX(MUX_SAI2), 0, GATE_SAI2), + STM32_GATE(_DFSDM, DFSDM_K, MUX(MUX_SAI1), 0, GATE_DFSDM), + STM32_GATE(_FDCAN_K, FDCAN_K, MUX(MUX_FDCAN), 0, GATE_FDCAN), + STM32_GATE(_USBH, USBH, _CKAXI, 0, GATE_USBH), + STM32_GATE(_I2C1_K, I2C1_K, MUX(MUX_I2C12), 0, GATE_I2C1), + STM32_GATE(_I2C2_K, I2C2_K, MUX(MUX_I2C12), 0, GATE_I2C2), + STM32_GATE(_ADFSDM, ADFSDM_K, MUX(MUX_SAI1), 0, GATE_ADFSDM), + STM32_GATE(_LPTIM2_K, LPTIM2_K, MUX(MUX_LPTIM2), 0, GATE_LPTIM2), + STM32_GATE(_LPTIM3_K, LPTIM3_K, MUX(MUX_LPTIM3), 0, GATE_LPTIM3), + STM32_GATE(_LPTIM4_K, LPTIM4_K, MUX(MUX_LPTIM45), 0, GATE_LPTIM4), + STM32_GATE(_LPTIM5_K, LPTIM5_K, MUX(MUX_LPTIM45), 0, GATE_LPTIM5), + STM32_GATE(_VREF, VREF, _PCLK3, 0, GATE_VREF), + STM32_GATE(_DTS, TMPSENS, _PCLK3, 0, GATE_DTS), + STM32_GATE(_PMBCTRL, PMBCTRL, _PCLK3, 0, GATE_HDP), + STM32_GATE(_HDP, HDP, _PCLK3, 0, GATE_PMBCTRL), + STM32_GATE(_STGENRO, STGENRO, _PCLK4, 0, GATE_DCMIPP), + STM32_GATE(_DCMIPP_K, DCMIPP_K, MUX(MUX_DCMIPP), 0, GATE_DCMIPP), + STM32_GATE(_DMAMUX1, DMAMUX1, _CKAXI, 0, GATE_DMAMUX1), + STM32_GATE(_DMAMUX2, DMAMUX2, _CKAXI, 0, GATE_DMAMUX2), + STM32_GATE(_DMA3, DMA3, _CKAXI, 0, GATE_DMAMUX2), + STM32_GATE(_ADC1_K, ADC1_K, MUX(MUX_ADC1), 0, GATE_ADC1), + STM32_GATE(_ADC2_K, ADC2_K, MUX(MUX_ADC2), 0, GATE_ADC2), + STM32_GATE(_TSC, TSC, _CKAXI, 0, GATE_TSC), + STM32_GATE(_AXIMC, AXIMC, _CKAXI, 0, GATE_AXIMC), + STM32_GATE(_CRC1, CRC1, _CKAXI, 0, GATE_ETH1TX), + STM32_GATE(_ETH1CK, ETH1CK_K, MUX(MUX_ETH1), 0, GATE_ETH1CK), + STM32_GATE(_ETH1TX, ETH1TX, _CKAXI, 0, GATE_ETH1TX), + STM32_GATE(_ETH1RX, ETH1RX, _CKAXI, 0, GATE_ETH1RX), + STM32_GATE(_ETH2CK, ETH2CK_K, MUX(MUX_ETH2), 0, GATE_ETH2CK), + STM32_GATE(_ETH2TX, ETH2TX, _CKAXI, 0, GATE_ETH2TX), + STM32_GATE(_ETH2RX, ETH2RX, _CKAXI, 0, GATE_ETH2RX), + STM32_GATE(_ETH2MAC, ETH2MAC, _CKAXI, 0, GATE_ETH2MAC), +#endif +}; + +static struct stm32_pll_dt_cfg mp13_pll[_PLL_NB]; + +static struct stm32_osci_dt_cfg mp13_osci[NB_OSCILLATOR]; + +static uint32_t mp13_clksrc[MUX_MAX]; + +static uint32_t mp13_clkdiv[DIV_MAX]; + +static struct stm32_clk_platdata stm32mp13_clock_pdata = { + .osci = mp13_osci, + .nosci = NB_OSCILLATOR, + .pll = mp13_pll, + .npll = _PLL_NB, + .clksrc = mp13_clksrc, + .nclksrc = MUX_MAX, + .clkdiv = mp13_clkdiv, + .nclkdiv = DIV_MAX, +}; + +static struct stm32_clk_priv stm32mp13_clock_data = { + .base = RCC_BASE, + .num = ARRAY_SIZE(stm32mp13_clk), + .clks = stm32mp13_clk, + .parents = parent_mp13, + .nb_parents = ARRAY_SIZE(parent_mp13), + .gates = gates_mp13, + .nb_gates = ARRAY_SIZE(gates_mp13), + .div = dividers_mp13, + .nb_div = ARRAY_SIZE(dividers_mp13), + .osci_data = stm32mp13_osc_data, + .nb_osci_data = ARRAY_SIZE(stm32mp13_osc_data), + .gate_refcounts = refcounts_mp13, + .pdata = &stm32mp13_clock_pdata, +}; + +static int stm32mp1_init_clock_tree(void) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int ret; + +#if STM32MP_USB_PROGRAMMER + int usbphy_p = _clk_stm32_get_parent(priv, _USBPHY_K); + int usbo_p = _clk_stm32_get_parent(priv, _USBO_K); + + /* Don't initialize PLL4, when used by BOOTROM */ + pll4_bootrom = stm32mp1_clk_is_pll4_used_by_bootrom(priv, usbphy_p); +#endif + + /* + * Switch ON oscillators found in device-tree. + * Note: HSI already ON after BootROM stage. + */ + stm32_clk_oscillators_enable(priv); + + /* Come back to HSI */ + ret = stm32mp1_come_back_to_hsi(); + if (ret != 0) { + return ret; + } + + ret = stm32_clk_hsidiv_configure(priv); + if (ret != 0) { + return ret; + } + + ret = stm32_clk_stgen_configure(priv, _STGENC); + if (ret != 0) { + panic(); + } + + ret = stm32_clk_dividers_configure(priv); + if (ret != 0) { + panic(); + } + + ret = stm32_clk_pll_configure(priv); + if (ret != 0) { + panic(); + } + + /* Wait LSE ready before to use it */ + ret = stm32_clk_oscillators_wait_lse_ready(priv); + if (ret != 0) { + panic(); + } + + /* Configure with expected clock source */ + ret = stm32_clk_source_configure(priv); + if (ret != 0) { + panic(); + } + + /* Configure LSE css after RTC source configuration */ + ret = stm32_clk_oscillators_lse_set_css(priv); + if (ret != 0) { + panic(); + } + +#if STM32MP_USB_PROGRAMMER + ret = stm32mp1_clk_check_usb_conflict(priv, usbphy_p, usbo_p); + if (ret != 0) { + return ret; + } +#endif + /* reconfigure STGEN with DT config */ + ret = stm32_clk_stgen_configure(priv, _STGENC); + if (ret != 0) { + panic(); + } + + /* Software Self-Refresh mode (SSR) during DDR initilialization */ + mmio_clrsetbits_32(priv->base + RCC_DDRITFCR, + RCC_DDRITFCR_DDRCKMOD_MASK, + RCC_DDRITFCR_DDRCKMOD_SSR << + RCC_DDRITFCR_DDRCKMOD_SHIFT); + + return 0; +} + +#define LSEDRV_MEDIUM_HIGH 2 + +static int clk_stm32_parse_oscillator_fdt(void *fdt, int node, const char *name, + struct stm32_osci_dt_cfg *osci) +{ + int subnode = 0; + + /* default value oscillator not found, freq=0 */ + osci->freq = 0; + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar = NULL; + const fdt32_t *cuint = NULL; + int ret = 0; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return ret; + } + + if (strncmp(cchar, name, (size_t)ret) || + fdt_get_status(subnode) == DT_DISABLED) { + continue; + } + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); + if (cuint == NULL) { + return ret; + } + + osci->freq = fdt32_to_cpu(*cuint); + + if (fdt_getprop(fdt, subnode, "st,bypass", NULL) != NULL) { + osci->bypass = true; + } + + if (fdt_getprop(fdt, subnode, "st,digbypass", NULL) != NULL) { + osci->digbyp = true; + } + + if (fdt_getprop(fdt, subnode, "st,css", NULL) != NULL) { + osci->css = true; + } + + osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive", LSEDRV_MEDIUM_HIGH); + + return 0; + } + + return 0; +} + +static int stm32_clk_parse_fdt_all_oscillator(void *fdt, struct stm32_clk_platdata *pdata) +{ + int fdt_err = 0; + uint32_t i = 0; + int node = 0; + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + for (i = 0; i < pdata->nosci; i++) { + const char *name = NULL; + + name = clk_stm32_get_oscillator_name((enum stm32_osc)i); + if (name == NULL) { + continue; + } + + fdt_err = clk_stm32_parse_oscillator_fdt(fdt, node, name, &pdata->osci[i]); + if (fdt_err < 0) { + panic(); + } + } + + return 0; +} + +#define RCC_PLL_NAME_SIZE 12 + +static int clk_stm32_load_vco_config(void *fdt, int subnode, struct stm32_pll_vco *vco) +{ + int err = 0; + + err = fdt_read_uint32_array(fdt, subnode, "divmn", (int)PLL_DIV_MN_NB, vco->div_mn); + if (err != 0) { + return err; + } + + err = fdt_read_uint32_array(fdt, subnode, "csg", (int)PLL_CSG_NB, vco->csg); + + vco->csg_enabled = (err == 0); + + if (err == -FDT_ERR_NOTFOUND) { + err = 0; + } + + if (err != 0) { + return err; + } + + vco->status = RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN | RCC_PLLNCR_PLLON; + + vco->frac = fdt_read_uint32_default(fdt, subnode, "frac", 0); + + vco->src = fdt_read_uint32_default(fdt, subnode, "src", UINT32_MAX); + + return 0; +} + +static int clk_stm32_load_output_config(void *fdt, int subnode, struct stm32_pll_output *output) +{ + int err = 0; + + err = fdt_read_uint32_array(fdt, subnode, "st,pll_div_pqr", (int)PLL_DIV_PQR_NB, + output->output); + if (err != 0) { + return err; + } + + return 0; +} + +static int clk_stm32_parse_pll_fdt(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll) +{ + const fdt32_t *cuint = NULL; + int subnode_pll = 0; + int subnode_vco = 0; + int err = 0; + + cuint = fdt_getprop(fdt, subnode, "st,pll", NULL); + if (!cuint) { + return -FDT_ERR_NOTFOUND; + } + + subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (subnode_pll < 0) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, subnode_pll, "st,pll_vco", NULL); + if (!cuint) { + return -FDT_ERR_NOTFOUND; + } + + subnode_vco = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (subnode_vco < 0) { + return -FDT_ERR_NOTFOUND; + } + + err = clk_stm32_load_vco_config(fdt, subnode_vco, &pll->vco); + if (err != 0) { + return err; + } + + err = clk_stm32_load_output_config(fdt, subnode_pll, &pll->output); + if (err != 0) { + return err; + } + + return 0; +} + +static int stm32_clk_parse_fdt_all_pll(void *fdt, int node, struct stm32_clk_platdata *pdata) +{ + size_t i = 0U; + + for (i = _PLL1; i < pdata->npll; i++) { + struct stm32_pll_dt_cfg *pll = pdata->pll + i; + char name[RCC_PLL_NAME_SIZE]; + int subnode = 0; + int err = 0; + + snprintf(name, sizeof(name), "st,pll@%u", i); + + subnode = fdt_subnode_offset(fdt, node, name); + if (!fdt_check_node(subnode)) { + continue; + } + + err = clk_stm32_parse_pll_fdt(fdt, subnode, pll); + if (err != 0) { + panic(); + } + } + + return 0; +} + +static int stm32_clk_parse_fdt(struct stm32_clk_platdata *pdata) +{ + void *fdt = NULL; + int node; + uint32_t err; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + if (node < 0) { + panic(); + } + + err = stm32_clk_parse_fdt_all_oscillator(fdt, pdata); + if (err != 0) { + return err; + } + + err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata); + if (err != 0) { + return err; + } + + err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clkdiv", pdata->clkdiv, &pdata->nclkdiv); + if (err != 0) { + return err; + } + + err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clksrc", pdata->clksrc, &pdata->nclksrc); + if (err != 0) { + return err; + } + + return 0; +} + +int stm32mp1_clk_init(void) +{ + return 0; +} + +int stm32mp1_clk_probe(void) +{ + uintptr_t base = RCC_BASE; + int ret; + + ret = stm32_clk_parse_fdt(&stm32mp13_clock_pdata); + if (ret != 0) { + return ret; + } + + ret = clk_stm32_init(&stm32mp13_clock_data, base); + if (ret != 0) { + return ret; + } + + ret = stm32mp1_init_clock_tree(); + if (ret != 0) { + return ret; + } + + clk_stm32_enable_critical_clocks(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c b/arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c new file mode 100644 index 0000000..534ee3b --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c @@ -0,0 +1,2376 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_HSI_HZ 64000000 +#define USB_PHY_48_MHZ 48000000 + +#define TIMEOUT_US_200MS U(200000) +#define TIMEOUT_US_1S U(1000000) + +#define PLLRDY_TIMEOUT TIMEOUT_US_200MS +#define CLKSRC_TIMEOUT TIMEOUT_US_200MS +#define CLKDIV_TIMEOUT TIMEOUT_US_200MS +#define HSIDIV_TIMEOUT TIMEOUT_US_200MS +#define OSCRDY_TIMEOUT TIMEOUT_US_1S + +const char *stm32mp_osc_node_label[NB_OSC] = { + [_LSI] = "clk-lsi", + [_LSE] = "clk-lse", + [_HSI] = "clk-hsi", + [_HSE] = "clk-hse", + [_CSI] = "clk-csi", + [_I2S_CKIN] = "i2s_ckin", +}; + +enum stm32mp1_parent_id { +/* Oscillators are defined in enum stm32mp_osc_id */ + +/* Other parent source */ + _HSI_KER = NB_OSC, + _HSE_KER, + _HSE_KER_DIV2, + _HSE_RTC, + _CSI_KER, + _PLL1_P, + _PLL1_Q, + _PLL1_R, + _PLL2_P, + _PLL2_Q, + _PLL2_R, + _PLL3_P, + _PLL3_Q, + _PLL3_R, + _PLL4_P, + _PLL4_Q, + _PLL4_R, + _ACLK, + _PCLK1, + _PCLK2, + _PCLK3, + _PCLK4, + _PCLK5, + _HCLK6, + _HCLK2, + _CK_PER, + _CK_MPU, + _CK_MCU, + _USB_PHY_48, + _PARENT_NB, + _UNKNOWN_ID = 0xff, +}; + +/* Lists only the parent clock we are interested in */ +enum stm32mp1_parent_sel { + _I2C12_SEL, + _I2C35_SEL, + _STGEN_SEL, + _I2C46_SEL, + _SPI6_SEL, + _UART1_SEL, + _RNG1_SEL, + _UART6_SEL, + _UART24_SEL, + _UART35_SEL, + _UART78_SEL, + _SDMMC12_SEL, + _SDMMC3_SEL, + _QSPI_SEL, + _FMC_SEL, + _AXIS_SEL, + _MCUS_SEL, + _USBPHY_SEL, + _USBO_SEL, + _MPU_SEL, + _CKPER_SEL, + _RTC_SEL, + _PARENT_SEL_NB, + _UNKNOWN_SEL = 0xff, +}; + +/* State the parent clock ID straight related to a clock */ +static const uint8_t parent_id_clock_id[_PARENT_NB] = { + [_HSE] = CK_HSE, + [_HSI] = CK_HSI, + [_CSI] = CK_CSI, + [_LSE] = CK_LSE, + [_LSI] = CK_LSI, + [_I2S_CKIN] = _UNKNOWN_ID, + [_USB_PHY_48] = _UNKNOWN_ID, + [_HSI_KER] = CK_HSI, + [_HSE_KER] = CK_HSE, + [_HSE_KER_DIV2] = CK_HSE_DIV2, + [_HSE_RTC] = _UNKNOWN_ID, + [_CSI_KER] = CK_CSI, + [_PLL1_P] = PLL1_P, + [_PLL1_Q] = PLL1_Q, + [_PLL1_R] = PLL1_R, + [_PLL2_P] = PLL2_P, + [_PLL2_Q] = PLL2_Q, + [_PLL2_R] = PLL2_R, + [_PLL3_P] = PLL3_P, + [_PLL3_Q] = PLL3_Q, + [_PLL3_R] = PLL3_R, + [_PLL4_P] = PLL4_P, + [_PLL4_Q] = PLL4_Q, + [_PLL4_R] = PLL4_R, + [_ACLK] = CK_AXI, + [_PCLK1] = CK_AXI, + [_PCLK2] = CK_AXI, + [_PCLK3] = CK_AXI, + [_PCLK4] = CK_AXI, + [_PCLK5] = CK_AXI, + [_CK_PER] = CK_PER, + [_CK_MPU] = CK_MPU, + [_CK_MCU] = CK_MCU, +}; + +static unsigned int clock_id2parent_id(unsigned long id) +{ + unsigned int n; + + for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) { + if (parent_id_clock_id[n] == id) { + return n; + } + } + + return _UNKNOWN_ID; +} + +enum stm32mp1_pll_id { + _PLL1, + _PLL2, + _PLL3, + _PLL4, + _PLL_NB +}; + +enum stm32mp1_div_id { + _DIV_P, + _DIV_Q, + _DIV_R, + _DIV_NB, +}; + +enum stm32mp1_clksrc_id { + CLKSRC_MPU, + CLKSRC_AXI, + CLKSRC_MCU, + CLKSRC_PLL12, + CLKSRC_PLL3, + CLKSRC_PLL4, + CLKSRC_RTC, + CLKSRC_MCO1, + CLKSRC_MCO2, + CLKSRC_NB +}; + +enum stm32mp1_clkdiv_id { + CLKDIV_MPU, + CLKDIV_AXI, + CLKDIV_MCU, + CLKDIV_APB1, + CLKDIV_APB2, + CLKDIV_APB3, + CLKDIV_APB4, + CLKDIV_APB5, + CLKDIV_RTC, + CLKDIV_MCO1, + CLKDIV_MCO2, + CLKDIV_NB +}; + +enum stm32mp1_pllcfg { + PLLCFG_M, + PLLCFG_N, + PLLCFG_P, + PLLCFG_Q, + PLLCFG_R, + PLLCFG_O, + PLLCFG_NB +}; + +enum stm32mp1_pllcsg { + PLLCSG_MOD_PER, + PLLCSG_INC_STEP, + PLLCSG_SSCG_MODE, + PLLCSG_NB +}; + +enum stm32mp1_plltype { + PLL_800, + PLL_1600, + PLL_TYPE_NB +}; + +struct stm32mp1_pll { + uint8_t refclk_min; + uint8_t refclk_max; + uint8_t divn_max; +}; + +struct stm32mp1_clk_gate { + uint16_t offset; + uint8_t bit; + uint8_t index; + uint8_t set_clr; + uint8_t secure; + uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ + uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ +}; + +struct stm32mp1_clk_sel { + uint16_t offset; + uint8_t src; + uint8_t msk; + uint8_t nb_parent; + const uint8_t *parent; +}; + +#define REFCLK_SIZE 4 +struct stm32mp1_clk_pll { + enum stm32mp1_plltype plltype; + uint16_t rckxselr; + uint16_t pllxcfgr1; + uint16_t pllxcfgr2; + uint16_t pllxfracr; + uint16_t pllxcr; + uint16_t pllxcsgr; + enum stm32mp_osc_id refclk[REFCLK_SIZE]; +}; + +/* Clocks with selectable source and non set/clr register access */ +#define _CLK_SELEC(sec, off, b, idx, s) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 0, \ + .secure = (sec), \ + .sel = (s), \ + .fixed = _UNKNOWN_ID, \ + } + +/* Clocks with fixed source and non set/clr register access */ +#define _CLK_FIXED(sec, off, b, idx, f) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 0, \ + .secure = (sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (f), \ + } + +/* Clocks with selectable source and set/clr register access */ +#define _CLK_SC_SELEC(sec, off, b, idx, s) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 1, \ + .secure = (sec), \ + .sel = (s), \ + .fixed = _UNKNOWN_ID, \ + } + +/* Clocks with fixed source and set/clr register access */ +#define _CLK_SC_FIXED(sec, off, b, idx, f) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 1, \ + .secure = (sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (f), \ + } + +#define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ + [_ ## _label ## _SEL] = { \ + .offset = _rcc_selr, \ + .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ + .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \ + (_rcc_selr ## _ ## _label ## SRC_SHIFT), \ + .parent = (_parents), \ + .nb_parent = ARRAY_SIZE(_parents) \ + } + +#define _CLK_PLL(idx, type, off1, off2, off3, \ + off4, off5, off6, \ + p1, p2, p3, p4) \ + [(idx)] = { \ + .plltype = (type), \ + .rckxselr = (off1), \ + .pllxcfgr1 = (off2), \ + .pllxcfgr2 = (off3), \ + .pllxfracr = (off4), \ + .pllxcr = (off5), \ + .pllxcsgr = (off6), \ + .refclk[0] = (p1), \ + .refclk[1] = (p2), \ + .refclk[2] = (p3), \ + .refclk[3] = (p4), \ + } + +#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) + +#define SEC 1 +#define N_S 0 + +static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { + _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), + _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), + _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), + +#if defined(IMAGE_BL32) + _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), +#endif + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), + +#if defined(IMAGE_BL32) + _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), +#endif + _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), + + _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), + + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), + + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), + +#if defined(IMAGE_BL32) + _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), +#endif + + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), + + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), + _CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), + +#if defined(IMAGE_BL2) + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), +#endif + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), +#if defined(IMAGE_BL32) + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), +#endif + + _CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL), + _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), +}; + +static const uint8_t i2c12_parents[] = { + _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER +}; + +static const uint8_t i2c35_parents[] = { + _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER +}; + +static const uint8_t stgen_parents[] = { + _HSI_KER, _HSE_KER +}; + +static const uint8_t i2c46_parents[] = { + _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER +}; + +static const uint8_t spi6_parents[] = { + _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q +}; + +static const uint8_t usart1_parents[] = { + _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER +}; + +static const uint8_t rng1_parents[] = { + _CSI, _PLL4_R, _LSE, _LSI +}; + +static const uint8_t uart6_parents[] = { + _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER +}; + +static const uint8_t uart234578_parents[] = { + _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER +}; + +static const uint8_t sdmmc12_parents[] = { + _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER +}; + +static const uint8_t sdmmc3_parents[] = { + _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER +}; + +static const uint8_t qspi_parents[] = { + _ACLK, _PLL3_R, _PLL4_P, _CK_PER +}; + +static const uint8_t fmc_parents[] = { + _ACLK, _PLL3_R, _PLL4_P, _CK_PER +}; + +static const uint8_t axiss_parents[] = { + _HSI, _HSE, _PLL2_P +}; + +static const uint8_t mcuss_parents[] = { + _HSI, _HSE, _CSI, _PLL3_P +}; + +static const uint8_t usbphy_parents[] = { + _HSE_KER, _PLL4_R, _HSE_KER_DIV2 +}; + +static const uint8_t usbo_parents[] = { + _PLL4_R, _USB_PHY_48 +}; + +static const uint8_t mpu_parents[] = { + _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ +}; + +static const uint8_t per_parents[] = { + _HSI, _HSE, _CSI, +}; + +static const uint8_t rtc_parents[] = { + _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC +}; + +static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), + _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), + _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), + _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), + _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), + _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), + _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), + _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), + _CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents), + _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents), + _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), + _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), + _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), + _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), + _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), + _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), + _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), + _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), + _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents), + _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents), + _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), + _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), +}; + +/* Define characteristic of PLL according type */ +#define DIVN_MIN 24 +static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { + [PLL_800] = { + .refclk_min = 4, + .refclk_max = 16, + .divn_max = 99, + }, + [PLL_1600] = { + .refclk_min = 8, + .refclk_max = 16, + .divn_max = 199, + }, +}; + +/* PLLNCFGR2 register divider by output */ +static const uint8_t pllncfgr2[_DIV_NB] = { + [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, + [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, + [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, +}; + +static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { + _CLK_PLL(_PLL1, PLL_1600, + RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, + RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, + _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL2, PLL_1600, + RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, + RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, + _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL3, PLL_800, + RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, + RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, + _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL4, PLL_800, + RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, + RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, + _HSI, _HSE, _CSI, _I2S_CKIN), +}; + +/* Prescaler table lookups for clock computation */ +/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ +static const uint8_t stm32mp1_mcu_div[16] = { + 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ +#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div +#define stm32mp1_apbx_div stm32mp1_mpu_apbx_div +static const uint8_t stm32mp1_mpu_apbx_div[8] = { + 0, 1, 2, 3, 4, 4, 4, 4 +}; + +/* div = /1 /2 /3 /4 */ +static const uint8_t stm32mp1_axi_div[8] = { + 1, 2, 3, 4, 4, 4, 4, 4 +}; + +static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { + [_HSI] = "HSI", + [_HSE] = "HSE", + [_CSI] = "CSI", + [_LSI] = "LSI", + [_LSE] = "LSE", + [_I2S_CKIN] = "I2S_CKIN", + [_HSI_KER] = "HSI_KER", + [_HSE_KER] = "HSE_KER", + [_HSE_KER_DIV2] = "HSE_KER_DIV2", + [_HSE_RTC] = "HSE_RTC", + [_CSI_KER] = "CSI_KER", + [_PLL1_P] = "PLL1_P", + [_PLL1_Q] = "PLL1_Q", + [_PLL1_R] = "PLL1_R", + [_PLL2_P] = "PLL2_P", + [_PLL2_Q] = "PLL2_Q", + [_PLL2_R] = "PLL2_R", + [_PLL3_P] = "PLL3_P", + [_PLL3_Q] = "PLL3_Q", + [_PLL3_R] = "PLL3_R", + [_PLL4_P] = "PLL4_P", + [_PLL4_Q] = "PLL4_Q", + [_PLL4_R] = "PLL4_R", + [_ACLK] = "ACLK", + [_PCLK1] = "PCLK1", + [_PCLK2] = "PCLK2", + [_PCLK3] = "PCLK3", + [_PCLK4] = "PCLK4", + [_PCLK5] = "PCLK5", + [_HCLK6] = "KCLK6", + [_HCLK2] = "HCLK2", + [_CK_PER] = "CK_PER", + [_CK_MPU] = "CK_MPU", + [_CK_MCU] = "CK_MCU", + [_USB_PHY_48] = "USB_PHY_48", +}; + +/* RCC clock device driver private */ +static unsigned long stm32mp1_osc[NB_OSC]; +static struct spinlock reg_lock; +static unsigned int gate_refcounts[NB_GATES]; +static struct spinlock refcount_lock; + +static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) +{ + return &stm32mp1_clk_gate[idx]; +} + +#if defined(IMAGE_BL32) +static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate) +{ + return gate->secure == N_S; +} +#endif + +static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) +{ + return &stm32mp1_clk_sel[idx]; +} + +static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) +{ + return &stm32mp1_clk_pll[idx]; +} + +static void stm32mp1_clk_lock(struct spinlock *lock) +{ + if (stm32mp_lock_available()) { + /* Assume interrupts are masked */ + spin_lock(lock); + } +} + +static void stm32mp1_clk_unlock(struct spinlock *lock) +{ + if (stm32mp_lock_available()) { + spin_unlock(lock); + } +} + +bool stm32mp1_rcc_is_secure(void) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t mask = RCC_TZCR_TZEN; + + return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; +} + +bool stm32mp1_rcc_is_mckprot(void) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT; + + return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; +} + +void stm32mp1_clk_rcc_regs_lock(void) +{ + stm32mp1_clk_lock(®_lock); +} + +void stm32mp1_clk_rcc_regs_unlock(void) +{ + stm32mp1_clk_unlock(®_lock); +} + +static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) +{ + if (idx >= NB_OSC) { + return 0; + } + + return stm32mp1_osc[idx]; +} + +static int stm32mp1_clk_get_gated_id(unsigned long id) +{ + unsigned int i; + + for (i = 0U; i < NB_GATES; i++) { + if (gate_ref(i)->index == id) { + return i; + } + } + + ERROR("%s: clk id %lu not found\n", __func__, id); + + return -EINVAL; +} + +static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) +{ + return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); +} + +static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) +{ + return (enum stm32mp1_parent_id)(gate_ref(i)->fixed); +} + +static int stm32mp1_clk_get_parent(unsigned long id) +{ + const struct stm32mp1_clk_sel *sel; + uint32_t p_sel; + int i; + enum stm32mp1_parent_id p; + enum stm32mp1_parent_sel s; + uintptr_t rcc_base = stm32mp_rcc_base(); + + /* Few non gateable clock have a static parent ID, find them */ + i = (int)clock_id2parent_id(id); + if (i != _UNKNOWN_ID) { + return i; + } + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + panic(); + } + + p = stm32mp1_clk_get_fixed_parent(i); + if (p < _PARENT_NB) { + return (int)p; + } + + s = stm32mp1_clk_get_sel(i); + if (s == _UNKNOWN_SEL) { + return -EINVAL; + } + if (s >= _PARENT_SEL_NB) { + panic(); + } + + sel = clk_sel_ref(s); + p_sel = (mmio_read_32(rcc_base + sel->offset) & + (sel->msk << sel->src)) >> sel->src; + if (p_sel < sel->nb_parent) { + return (int)sel->parent[p_sel]; + } + + return -EINVAL; +} + +static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) +{ + uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); + uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; + + return stm32mp1_clk_get_fixed(pll->refclk[src]); +} + +/* + * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL + * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) + * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) + * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) + */ +static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) +{ + unsigned long refclk, fvco; + uint32_t cfgr1, fracr, divm, divn; + uintptr_t rcc_base = stm32mp_rcc_base(); + + cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); + fracr = mmio_read_32(rcc_base + pll->pllxfracr); + + divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; + divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; + + refclk = stm32mp1_pll_get_fref(pll); + + /* + * With FRACV : + * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) + * Without FRACV + * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) + */ + if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { + uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> + RCC_PLLNFRACR_FRACV_SHIFT; + unsigned long long numerator, denominator; + + numerator = (((unsigned long long)divn + 1U) << 13) + fracv; + numerator = refclk * numerator; + denominator = ((unsigned long long)divm + 1U) << 13; + fvco = (unsigned long)(numerator / denominator); + } else { + fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); + } + + return fvco; +} + +static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, + enum stm32mp1_div_id div_id) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + unsigned long dfout; + uint32_t cfgr2, divy; + + if (div_id >= _DIV_NB) { + return 0; + } + + cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); + divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; + + dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); + + return dfout; +} + +static unsigned long get_clock_rate(int p) +{ + uint32_t reg, clkdiv; + unsigned long clock = 0; + uintptr_t rcc_base = stm32mp_rcc_base(); + + switch (p) { + case _CK_MPU: + /* MPU sub system */ + reg = mmio_read_32(rcc_base + RCC_MPCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_MPCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_MPCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_MPCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); + break; + case RCC_MPCKSELR_PLL_MPUDIV: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); + + reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); + clkdiv = reg & RCC_MPUDIV_MASK; + clock >>= stm32mp1_mpu_div[clkdiv]; + break; + default: + break; + } + break; + /* AXI sub system */ + case _ACLK: + case _HCLK2: + case _HCLK6: + case _PCLK4: + case _PCLK5: + reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_ASSCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_ASSCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_ASSCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); + break; + default: + break; + } + + /* System clock divider */ + reg = mmio_read_32(rcc_base + RCC_AXIDIVR); + clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; + + switch (p) { + case _PCLK4: + reg = mmio_read_32(rcc_base + RCC_APB4DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK5: + reg = mmio_read_32(rcc_base + RCC_APB5DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + default: + break; + } + break; + /* MCU sub system */ + case _CK_MCU: + case _PCLK1: + case _PCLK2: + case _PCLK3: + reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_MSSCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_MSSCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_MSSCKSELR_CSI: + clock = stm32mp1_clk_get_fixed(_CSI); + break; + case RCC_MSSCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); + break; + default: + break; + } + + /* MCU clock divider */ + reg = mmio_read_32(rcc_base + RCC_MCUDIVR); + clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; + + switch (p) { + case _PCLK1: + reg = mmio_read_32(rcc_base + RCC_APB1DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK2: + reg = mmio_read_32(rcc_base + RCC_APB2DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK3: + reg = mmio_read_32(rcc_base + RCC_APB3DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _CK_MCU: + default: + break; + } + break; + case _CK_PER: + reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_CPERCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_CPERCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_CPERCKSELR_CSI: + clock = stm32mp1_clk_get_fixed(_CSI); + break; + default: + break; + } + break; + case _HSI: + case _HSI_KER: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case _CSI: + case _CSI_KER: + clock = stm32mp1_clk_get_fixed(_CSI); + break; + case _HSE: + case _HSE_KER: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case _HSE_KER_DIV2: + clock = stm32mp1_clk_get_fixed(_HSE) >> 1; + break; + case _HSE_RTC: + clock = stm32mp1_clk_get_fixed(_HSE); + clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U; + break; + case _LSI: + clock = stm32mp1_clk_get_fixed(_LSI); + break; + case _LSE: + clock = stm32mp1_clk_get_fixed(_LSE); + break; + /* PLL */ + case _PLL1_P: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); + break; + case _PLL1_Q: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); + break; + case _PLL1_R: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); + break; + case _PLL2_P: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); + break; + case _PLL2_Q: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); + break; + case _PLL2_R: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); + break; + case _PLL3_P: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); + break; + case _PLL3_Q: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); + break; + case _PLL3_R: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); + break; + case _PLL4_P: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); + break; + case _PLL4_Q: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); + break; + case _PLL4_R: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); + break; + /* Other */ + case _USB_PHY_48: + clock = USB_PHY_48_MHZ; + break; + default: + break; + } + + return clock; +} + +static void __clk_enable(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + VERBOSE("Enable clock %u\n", gate->index); + + if (gate->set_clr != 0U) { + mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); + } else { + mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); + } +} + +static void __clk_disable(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + VERBOSE("Disable clock %u\n", gate->index); + + if (gate->set_clr != 0U) { + mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, + BIT(gate->bit)); + } else { + mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); + } +} + +static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); +} + +/* Oscillators and PLLs are not gated at runtime */ +static bool clock_is_always_on(unsigned long id) +{ + switch (id) { + case CK_HSE: + case CK_CSI: + case CK_LSI: + case CK_LSE: + case CK_HSI: + case CK_HSE_DIV2: + case PLL1_Q: + case PLL1_R: + case PLL2_P: + case PLL2_Q: + case PLL2_R: + case PLL3_P: + case PLL3_Q: + case PLL3_R: + case CK_AXI: + case CK_MPU: + case CK_MCU: + case RTC: + return true; + default: + return false; + } +} + +static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt) +{ + const struct stm32mp1_clk_gate *gate; + int i; + + if (clock_is_always_on(id)) { + return; + } + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + ERROR("Clock %lu can't be enabled\n", id); + panic(); + } + + gate = gate_ref(i); + + if (!with_refcnt) { + __clk_enable(gate); + return; + } + +#if defined(IMAGE_BL32) + if (gate_is_non_secure(gate)) { + /* Enable non-secure clock w/o any refcounting */ + __clk_enable(gate); + return; + } +#endif + + stm32mp1_clk_lock(&refcount_lock); + + if (gate_refcounts[i] == 0U) { + __clk_enable(gate); + } + + gate_refcounts[i]++; + if (gate_refcounts[i] == UINT_MAX) { + ERROR("Clock %lu refcount reached max value\n", id); + panic(); + } + + stm32mp1_clk_unlock(&refcount_lock); +} + +static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt) +{ + const struct stm32mp1_clk_gate *gate; + int i; + + if (clock_is_always_on(id)) { + return; + } + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + ERROR("Clock %lu can't be disabled\n", id); + panic(); + } + + gate = gate_ref(i); + + if (!with_refcnt) { + __clk_disable(gate); + return; + } + +#if defined(IMAGE_BL32) + if (gate_is_non_secure(gate)) { + /* Don't disable non-secure clocks */ + return; + } +#endif + + stm32mp1_clk_lock(&refcount_lock); + + if (gate_refcounts[i] == 0U) { + ERROR("Clock %lu refcount reached 0\n", id); + panic(); + } + gate_refcounts[i]--; + + if (gate_refcounts[i] == 0U) { + __clk_disable(gate); + } + + stm32mp1_clk_unlock(&refcount_lock); +} + +static int stm32mp_clk_enable(unsigned long id) +{ + __stm32mp1_clk_enable(id, true); + + return 0; +} + +static void stm32mp_clk_disable(unsigned long id) +{ + __stm32mp1_clk_disable(id, true); +} + +static bool stm32mp_clk_is_enabled(unsigned long id) +{ + int i; + + if (clock_is_always_on(id)) { + return true; + } + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + panic(); + } + + return __clk_is_enabled(gate_ref(i)); +} + +static unsigned long stm32mp_clk_get_rate(unsigned long id) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + int p = stm32mp1_clk_get_parent(id); + uint32_t prescaler, timpre; + unsigned long parent_rate; + + if (p < 0) { + return 0; + } + + parent_rate = get_clock_rate(p); + + switch (id) { + case TIM2_K: + case TIM3_K: + case TIM4_K: + case TIM5_K: + case TIM6_K: + case TIM7_K: + case TIM12_K: + case TIM13_K: + case TIM14_K: + prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & + RCC_APBXDIV_MASK; + timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & + RCC_TIMGXPRER_TIMGXPRE; + break; + + case TIM1_K: + case TIM8_K: + case TIM15_K: + case TIM16_K: + case TIM17_K: + prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & + RCC_APBXDIV_MASK; + timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & + RCC_TIMGXPRER_TIMGXPRE; + break; + + default: + return parent_rate; + } + + if (prescaler == 0U) { + return parent_rate; + } + + return parent_rate * (timpre + 1U) * 2U; +} + +static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) +{ + uintptr_t address = stm32mp_rcc_base() + offset; + + if (enable) { + mmio_setbits_32(address, mask_on); + } else { + mmio_clrbits_32(address, mask_on); + } +} + +static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) +{ + uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; + uintptr_t address = stm32mp_rcc_base() + offset; + + mmio_write_32(address, mask_on); +} + +static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) +{ + uint64_t timeout; + uint32_t mask_test; + uintptr_t address = stm32mp_rcc_base() + offset; + + if (enable) { + mask_test = mask_rdy; + } else { + mask_test = 0; + } + + timeout = timeout_init_us(OSCRDY_TIMEOUT); + while ((mmio_read_32(address) & mask_rdy) != mask_test) { + if (timeout_elapsed(timeout)) { + ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n", + mask_rdy, address, enable, mmio_read_32(address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) +{ + uint32_t value; + uintptr_t rcc_base = stm32mp_rcc_base(); + + if (digbyp) { + mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); + } + + if (bypass || digbyp) { + mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); + } + + /* + * Warning: not recommended to switch directly from "high drive" + * to "medium low drive", and vice-versa. + */ + value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> + RCC_BDCR_LSEDRV_SHIFT; + + while (value != lsedrv) { + if (value > lsedrv) { + value--; + } else { + value++; + } + + mmio_clrsetbits_32(rcc_base + RCC_BDCR, + RCC_BDCR_LSEDRV_MASK, + value << RCC_BDCR_LSEDRV_SHIFT); + } + + stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); +} + +static void stm32mp1_lse_wait(void) +{ + if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } +} + +static void stm32mp1_lsi_set(bool enable) +{ + stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); + + if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } +} + +static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + if (digbyp) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); + } + + if (bypass || digbyp) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); + } + + stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); + if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } + + if (css) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); + } + +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER + if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) && + (!(digbyp || bypass))) { + panic(); + } +#endif +} + +static void stm32mp1_csi_set(bool enable) +{ + stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); + if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } +} + +static void stm32mp1_hsi_set(bool enable) +{ + stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); + if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } +} + +static int stm32mp1_set_hsidiv(uint8_t hsidiv) +{ + uint64_t timeout; + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t address = rcc_base + RCC_OCRDYR; + + mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, + RCC_HSICFGR_HSIDIV_MASK, + RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); + + timeout = timeout_init_us(HSIDIV_TIMEOUT); + while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", + address, mmio_read_32(address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int stm32mp1_hsidiv(unsigned long hsifreq) +{ + uint8_t hsidiv; + uint32_t hsidivfreq = MAX_HSI_HZ; + + for (hsidiv = 0; hsidiv < 4U; hsidiv++) { + if (hsidivfreq == hsifreq) { + break; + } + + hsidivfreq /= 2U; + } + + if (hsidiv == 4U) { + ERROR("Invalid clk-hsi frequency\n"); + return -1; + } + + if (hsidiv != 0U) { + return stm32mp1_set_hsidiv(hsidiv); + } + + return 0; +} + +static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, + unsigned int clksrc, + uint32_t *pllcfg, int plloff) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t pllxcr = rcc_base + pll->pllxcr; + enum stm32mp1_plltype type = pll->plltype; + uintptr_t clksrc_address = rcc_base + (clksrc >> 4); + unsigned long refclk; + uint32_t ifrge = 0U; + uint32_t src, value, fracv = 0; + void *fdt; + + /* Check PLL output */ + if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { + return false; + } + + /* Check current clksrc */ + src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK; + if (src != (clksrc & RCC_SELR_SRC_MASK)) { + return false; + } + + /* Check Div */ + src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; + + refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / + (pllcfg[PLLCFG_M] + 1U); + + if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || + (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { + return false; + } + + if ((type == PLL_800) && (refclk >= 8000000U)) { + ifrge = 1U; + } + + value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & + RCC_PLLNCFGR1_DIVN_MASK; + value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & + RCC_PLLNCFGR1_DIVM_MASK; + value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & + RCC_PLLNCFGR1_IFRGE_MASK; + if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { + return false; + } + + /* Fractional configuration */ + if (fdt_get_address(&fdt) == 1) { + fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); + } + + value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; + value |= RCC_PLLNFRACR_FRACLE; + if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { + return false; + } + + /* Output config */ + value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & + RCC_PLLNCFGR2_DIVP_MASK; + value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & + RCC_PLLNCFGR2_DIVQ_MASK; + value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & + RCC_PLLNCFGR2_DIVR_MASK; + if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { + return false; + } + + return true; +} + +static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; + + /* Preserve RCC_PLLNCR_SSCG_CTRL value */ + mmio_clrsetbits_32(pllxcr, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN, + RCC_PLLNCR_PLLON); +} + +static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; + uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); + + /* Wait PLL lock */ + while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("PLL%u start failed @ 0x%lx: 0x%x\n", + pll_id, pllxcr, mmio_read_32(pllxcr)); + return -ETIMEDOUT; + } + } + + /* Start the requested output */ + mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); + + return 0; +} + +static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; + uint64_t timeout; + + /* Stop all output */ + mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN); + + /* Stop PLL */ + mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); + + timeout = timeout_init_us(PLLRDY_TIMEOUT); + /* Wait PLL stopped */ + while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("PLL%u stop failed @ 0x%lx: 0x%x\n", + pll_id, pllxcr, mmio_read_32(pllxcr)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, + uint32_t *pllcfg) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t value; + + value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & + RCC_PLLNCFGR2_DIVP_MASK; + value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & + RCC_PLLNCFGR2_DIVQ_MASK; + value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & + RCC_PLLNCFGR2_DIVR_MASK; + mmio_write_32(rcc_base + pll->pllxcfgr2, value); +} + +static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, + uint32_t *pllcfg, uint32_t fracv) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); + enum stm32mp1_plltype type = pll->plltype; + unsigned long refclk; + uint32_t ifrge = 0; + uint32_t src, value; + + src = mmio_read_32(rcc_base + pll->rckxselr) & + RCC_SELR_REFCLK_SRC_MASK; + + refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / + (pllcfg[PLLCFG_M] + 1U); + + if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || + (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { + return -EINVAL; + } + + if ((type == PLL_800) && (refclk >= 8000000U)) { + ifrge = 1U; + } + + value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & + RCC_PLLNCFGR1_DIVN_MASK; + value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & + RCC_PLLNCFGR1_DIVM_MASK; + value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & + RCC_PLLNCFGR1_IFRGE_MASK; + mmio_write_32(rcc_base + pll->pllxcfgr1, value); + + /* Fractional configuration */ + value = 0; + mmio_write_32(rcc_base + pll->pllxfracr, value); + + value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; + mmio_write_32(rcc_base + pll->pllxfracr, value); + + value |= RCC_PLLNFRACR_FRACLE; + mmio_write_32(rcc_base + pll->pllxfracr, value); + + stm32mp1_pll_config_output(pll_id, pllcfg); + + return 0; +} + +static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uint32_t pllxcsg = 0; + + pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & + RCC_PLLNCSGR_MOD_PER_MASK; + + pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) & + RCC_PLLNCSGR_INC_STEP_MASK; + + pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & + RCC_PLLNCSGR_SSCG_MODE_MASK; + + mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); + + mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, + RCC_PLLNCR_SSCG_CTRL); +} + +static int stm32mp1_set_clksrc(unsigned int clksrc) +{ + uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); + uint64_t timeout; + + mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK, + clksrc & RCC_SELR_SRC_MASK); + + timeout = timeout_init_us(CLKSRC_TIMEOUT); + while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc, + clksrc_address, mmio_read_32(clksrc_address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address) +{ + uint64_t timeout; + + mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK, + clkdiv & RCC_DIVR_DIV_MASK); + + timeout = timeout_init_us(CLKDIV_TIMEOUT); + while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n", + clkdiv, address, mmio_read_32(address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv) +{ + uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); + + /* + * Binding clksrc : + * bit15-4 offset + * bit3: disable + * bit2-0: MCOSEL[2:0] + */ + if ((clksrc & 0x8U) != 0U) { + mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON); + } else { + mmio_clrsetbits_32(clksrc_address, + RCC_MCOCFG_MCOSRC_MASK, + clksrc & RCC_MCOCFG_MCOSRC_MASK); + mmio_clrsetbits_32(clksrc_address, + RCC_MCOCFG_MCODIV_MASK, + clkdiv << RCC_MCOCFG_MCODIV_SHIFT); + mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON); + } +} + +static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) +{ + uintptr_t address = stm32mp_rcc_base() + RCC_BDCR; + + if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || + (clksrc != (uint32_t)CLK_RTC_DISABLED)) { + mmio_clrsetbits_32(address, + RCC_BDCR_RTCSRC_MASK, + (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT); + + mmio_setbits_32(address, RCC_BDCR_RTCCKEN); + } + + if (lse_css) { + mmio_setbits_32(address, RCC_BDCR_LSECSSON); + } +} + +static void stm32mp1_pkcs_config(uint32_t pkcs) +{ + uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); + uint32_t value = pkcs & 0xFU; + uint32_t mask = 0xFU; + + if ((pkcs & BIT(31)) != 0U) { + mask <<= 4; + value <<= 4; + } + + mmio_clrsetbits_32(address, mask, value); +} + +static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg, + uint32_t *fracv, uint32_t *csg, + bool *csg_set) +{ + void *fdt; + int ret; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB, + pllcfg); + if (ret < 0) { + return -FDT_ERR_NOTFOUND; + } + + *fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); + + ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB, + csg); + + *csg_set = (ret == 0); + + if (ret == -FDT_ERR_NOTFOUND) { + ret = 0; + } + + return ret; +} + +int stm32mp1_clk_init(void) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t pllfracv[_PLL_NB]; + uint32_t pllcsg[_PLL_NB][PLLCSG_NB]; + unsigned int clksrc[CLKSRC_NB]; + unsigned int clkdiv[CLKDIV_NB]; + unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; + int plloff[_PLL_NB]; + int ret, len; + enum stm32mp1_pll_id i; + bool pllcsg_set[_PLL_NB]; + bool pllcfg_valid[_PLL_NB]; + bool lse_css = false; + bool pll3_preserve = false; + bool pll4_preserve = false; + bool pll4_bootrom = false; + const fdt32_t *pkcs_cell; + void *fdt; + int stgen_p = stm32mp1_clk_get_parent(STGEN_K); + int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K); + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, + clksrc); + if (ret < 0) { + return -FDT_ERR_NOTFOUND; + } + + ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB, + clkdiv); + if (ret < 0) { + return -FDT_ERR_NOTFOUND; + } + + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + char name[12]; + + snprintf(name, sizeof(name), "st,pll@%u", i); + plloff[i] = fdt_rcc_subnode_offset(name); + + pllcfg_valid[i] = fdt_check_node(plloff[i]); + if (!pllcfg_valid[i]) { + continue; + } + + ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i], + &pllfracv[i], pllcsg[i], + &pllcsg_set[i]); + if (ret != 0) { + return ret; + } + } + + stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); + stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); + + /* + * Switch ON oscillator found in device-tree. + * Note: HSI already ON after BootROM stage. + */ + if (stm32mp1_osc[_LSI] != 0U) { + stm32mp1_lsi_set(true); + } + if (stm32mp1_osc[_LSE] != 0U) { + const char *name = stm32mp_osc_node_label[_LSE]; + bool bypass, digbyp; + uint32_t lsedrv; + + bypass = fdt_clk_read_bool(name, "st,bypass"); + digbyp = fdt_clk_read_bool(name, "st,digbypass"); + lse_css = fdt_clk_read_bool(name, "st,css"); + lsedrv = fdt_clk_read_uint32_default(name, "st,drive", + LSEDRV_MEDIUM_HIGH); + stm32mp1_lse_enable(bypass, digbyp, lsedrv); + } + if (stm32mp1_osc[_HSE] != 0U) { + const char *name = stm32mp_osc_node_label[_HSE]; + bool bypass, digbyp, css; + + bypass = fdt_clk_read_bool(name, "st,bypass"); + digbyp = fdt_clk_read_bool(name, "st,digbypass"); + css = fdt_clk_read_bool(name, "st,css"); + stm32mp1_hse_enable(bypass, digbyp, css); + } + /* + * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) + * => switch on CSI even if node is not present in device tree + */ + stm32mp1_csi_set(true); + + /* Come back to HSI */ + ret = stm32mp1_set_clksrc(CLK_MPU_HSI); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clksrc(CLK_AXI_HSI); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clksrc(CLK_MCU_HSI); + if (ret != 0) { + return ret; + } + + if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & + RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { + if (pllcfg_valid[_PLL3]) { + pll3_preserve = + stm32mp1_check_pll_conf(_PLL3, + clksrc[CLKSRC_PLL3], + pllcfg[_PLL3], + plloff[_PLL3]); + } + + if (pllcfg_valid[_PLL4]) { + pll4_preserve = + stm32mp1_check_pll_conf(_PLL4, + clksrc[CLKSRC_PLL4], + pllcfg[_PLL4], + plloff[_PLL4]); + } + } + /* Don't initialize PLL4, when used by BOOTROM */ + if ((stm32mp_get_boot_itf_selected() == + BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) && + ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) { + pll4_bootrom = true; + pll4_preserve = true; + } + + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + if (((i == _PLL3) && pll3_preserve) || + ((i == _PLL4) && pll4_preserve)) { + continue; + } + + ret = stm32mp1_pll_stop(i); + if (ret != 0) { + return ret; + } + } + + /* Configure HSIDIV */ + if (stm32mp1_osc[_HSI] != 0U) { + ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); + if (ret != 0) { + return ret; + } + + stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); + } + + /* Select DIV */ + /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ + mmio_write_32(rcc_base + RCC_MPCKDIVR, + clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR); + if (ret != 0) { + return ret; + } + + /* No ready bit for RTC */ + mmio_write_32(rcc_base + RCC_RTCDIVR, + clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK); + + /* Configure PLLs source */ + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]); + if (ret != 0) { + return ret; + } + + if (!pll3_preserve) { + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]); + if (ret != 0) { + return ret; + } + } + + if (!pll4_preserve) { + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]); + if (ret != 0) { + return ret; + } + } + + /* Configure and start PLLs */ + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + if (((i == _PLL3) && pll3_preserve) || + ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { + continue; + } + + if (!pllcfg_valid[i]) { + continue; + } + + if ((i == _PLL4) && pll4_bootrom) { + /* Set output divider if not done by the Bootrom */ + stm32mp1_pll_config_output(i, pllcfg[i]); + continue; + } + + ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]); + if (ret != 0) { + return ret; + } + + if (pllcsg_set[i]) { + stm32mp1_pll_csg(i, pllcsg[i]); + } + + stm32mp1_pll_start(i); + } + /* Wait and start PLLs ouptut when ready */ + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + if (!pllcfg_valid[i]) { + continue; + } + + ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]); + if (ret != 0) { + return ret; + } + } + /* Wait LSE ready before to use it */ + if (stm32mp1_osc[_LSE] != 0U) { + stm32mp1_lse_wait(); + } + + /* Configure with expected clock source */ + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]); + if (ret != 0) { + return ret; + } + stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); + + /* Configure PKCK */ + pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len); + if (pkcs_cell != NULL) { + bool ckper_disabled = false; + uint32_t j; + uint32_t usbreg_bootrom = 0U; + + if (pll4_bootrom) { + usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR); + } + + for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { + uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); + + if (pkcs == (uint32_t)CLK_CKPER_DISABLED) { + ckper_disabled = true; + continue; + } + stm32mp1_pkcs_config(pkcs); + } + + /* + * CKPER is source for some peripheral clocks + * (FMC-NAND / QPSI-NOR) and switching source is allowed + * only if previous clock is still ON + * => deactivated CKPER only after switching clock + */ + if (ckper_disabled) { + stm32mp1_pkcs_config(CLK_CKPER_DISABLED); + } + + if (pll4_bootrom) { + uint32_t usbreg_value, usbreg_mask; + const struct stm32mp1_clk_sel *sel; + + sel = clk_sel_ref(_USBPHY_SEL); + usbreg_mask = (uint32_t)sel->msk << sel->src; + sel = clk_sel_ref(_USBO_SEL); + usbreg_mask |= (uint32_t)sel->msk << sel->src; + + usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) & + usbreg_mask; + usbreg_bootrom &= usbreg_mask; + if (usbreg_bootrom != usbreg_value) { + VERBOSE("forbidden new USB clk path\n"); + VERBOSE("vs bootrom on USB boot\n"); + return -FDT_ERR_BADVALUE; + } + } + } + + /* Switch OFF HSI if not found in device-tree */ + if (stm32mp1_osc[_HSI] == 0U) { + stm32mp1_hsi_set(false); + } + + stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); + + /* Software Self-Refresh mode (SSR) during DDR initilialization */ + mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, + RCC_DDRITFCR_DDRCKMOD_MASK, + RCC_DDRITFCR_DDRCKMOD_SSR << + RCC_DDRITFCR_DDRCKMOD_SHIFT); + + return 0; +} + +static void stm32mp1_osc_clk_init(const char *name, + enum stm32mp_osc_id index) +{ + uint32_t frequency; + + if (fdt_osc_read_freq(name, &frequency) == 0) { + stm32mp1_osc[index] = frequency; + } +} + +static void stm32mp1_osc_init(void) +{ + enum stm32mp_osc_id i; + + for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { + stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); + } +} + +#ifdef STM32MP_SHARED_RESOURCES +/* + * Get the parent ID of the target parent clock, for tagging as secure + * shared clock dependencies. + */ +static int get_parent_id_parent(unsigned int parent_id) +{ + enum stm32mp1_parent_sel s = _UNKNOWN_SEL; + enum stm32mp1_pll_id pll_id; + uint32_t p_sel; + uintptr_t rcc_base = stm32mp_rcc_base(); + + switch (parent_id) { + case _ACLK: + case _PCLK4: + case _PCLK5: + s = _AXIS_SEL; + break; + case _PLL1_P: + case _PLL1_Q: + case _PLL1_R: + pll_id = _PLL1; + break; + case _PLL2_P: + case _PLL2_Q: + case _PLL2_R: + pll_id = _PLL2; + break; + case _PLL3_P: + case _PLL3_Q: + case _PLL3_R: + pll_id = _PLL3; + break; + case _PLL4_P: + case _PLL4_Q: + case _PLL4_R: + pll_id = _PLL4; + break; + case _PCLK1: + case _PCLK2: + case _HCLK2: + case _HCLK6: + case _CK_PER: + case _CK_MPU: + case _CK_MCU: + case _USB_PHY_48: + /* We do not expect to access these */ + panic(); + break; + default: + /* Other parents have no parent */ + return -1; + } + + if (s != _UNKNOWN_SEL) { + const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); + + p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & + sel->msk; + + if (p_sel < sel->nb_parent) { + return (int)sel->parent[p_sel]; + } + } else { + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + + p_sel = mmio_read_32(rcc_base + pll->rckxselr) & + RCC_SELR_REFCLK_SRC_MASK; + + if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) { + return (int)pll->refclk[p_sel]; + } + } + + VERBOSE("No parent selected for %s\n", + stm32mp1_clk_parent_name[parent_id]); + + return -1; +} + +static void secure_parent_clocks(unsigned long parent_id) +{ + int grandparent_id; + + switch (parent_id) { + case _PLL3_P: + case _PLL3_Q: + case _PLL3_R: + stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); + break; + + /* These clocks are always secure when RCC is secure */ + case _ACLK: + case _HCLK2: + case _HCLK6: + case _PCLK4: + case _PCLK5: + case _PLL1_P: + case _PLL1_Q: + case _PLL1_R: + case _PLL2_P: + case _PLL2_Q: + case _PLL2_R: + case _HSI: + case _HSI_KER: + case _LSI: + case _CSI: + case _CSI_KER: + case _HSE: + case _HSE_KER: + case _HSE_KER_DIV2: + case _HSE_RTC: + case _LSE: + break; + + default: + VERBOSE("Cannot secure parent clock %s\n", + stm32mp1_clk_parent_name[parent_id]); + panic(); + } + + grandparent_id = get_parent_id_parent(parent_id); + if (grandparent_id >= 0) { + secure_parent_clocks(grandparent_id); + } +} + +void stm32mp1_register_clock_parents_secure(unsigned long clock_id) +{ + int parent_id; + + if (!stm32mp1_rcc_is_secure()) { + return; + } + + switch (clock_id) { + case PLL1: + case PLL2: + /* PLL1/PLL2 are always secure: nothing to do */ + break; + case PLL3: + stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); + break; + case PLL4: + ERROR("PLL4 cannot be secured\n"); + panic(); + break; + default: + /* Others are expected gateable clock */ + parent_id = stm32mp1_clk_get_parent(clock_id); + if (parent_id < 0) { + INFO("No parent found for clock %lu\n", clock_id); + } else { + secure_parent_clocks(parent_id); + } + break; + } +} +#endif /* STM32MP_SHARED_RESOURCES */ + +static void sync_earlyboot_clocks_state(void) +{ + unsigned int idx; + const unsigned long secure_enable[] = { + AXIDCG, + BSEC, + DDRC1, DDRC1LP, + DDRC2, DDRC2LP, + DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, + DDRPHYC, DDRPHYCLP, + RTCAPB, + TZC1, TZC2, + TZPC, + STGEN_K, + }; + + for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { + stm32mp_clk_enable(secure_enable[idx]); + } +} + +static const struct clk_ops stm32mp_clk_ops = { + .enable = stm32mp_clk_enable, + .disable = stm32mp_clk_disable, + .is_enabled = stm32mp_clk_is_enabled, + .get_rate = stm32mp_clk_get_rate, + .get_parent = stm32mp1_clk_get_parent, +}; + +int stm32mp1_clk_probe(void) +{ +#if defined(IMAGE_BL32) + if (!fdt_get_rcc_secure_state()) { + mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U); + } +#endif + + stm32mp1_osc_init(); + + sync_earlyboot_clocks_state(); + + clk_register(&stm32mp_clk_ops); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c b/arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c new file mode 100644 index 0000000..80c2f41 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DT_UART_COMPAT "st,stm32h7-uart" +/* + * Get the frequency of an oscillator from its name in device tree. + * @param name: oscillator name + * @param freq: stores the frequency of the oscillator + * @return: 0 on success, and a negative FDT/ERRNO error code on failure. + */ +int fdt_osc_read_freq(const char *name, uint32_t *freq) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return ret; + } + + if ((strncmp(cchar, name, (size_t)ret) == 0) && + (fdt_get_status(subnode) != DT_DISABLED)) { + const fdt32_t *cuint; + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", + &ret); + if (cuint == NULL) { + return ret; + } + + *freq = fdt32_to_cpu(*cuint); + + return 0; + } + } + + /* Oscillator not found, freq=0 */ + *freq = 0; + return 0; +} + +/* + * Check the presence of an oscillator property from its id. + * @param node_label: clock node name + * @param prop_name: property name + * @return: true/false regarding search result. + */ +bool fdt_clk_read_bool(const char *node_label, const char *prop_name) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return false; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return false; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return false; + } + + if (strncmp(cchar, node_label, (size_t)ret) != 0) { + continue; + } + + if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) { + return true; + } + } + + return false; +} + +/* + * Get the value of a oscillator property from its name. + * @param node_label: oscillator name + * @param prop_name: property name + * @param dflt_value: default value + * @return oscillator value on success, default value if property not found. + */ +uint32_t fdt_clk_read_uint32_default(const char *node_label, + const char *prop_name, uint32_t dflt_value) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return dflt_value; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return dflt_value; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return dflt_value; + } + + if (strncmp(cchar, node_label, (size_t)ret) != 0) { + continue; + } + + return fdt_read_uint32_default(fdt, subnode, prop_name, + dflt_value); + } + + return dflt_value; +} + +/* + * Get the RCC node offset from the device tree + * @param fdt: Device tree reference + * @return: Node offset or a negative value on error + */ +static int fdt_get_rcc_node(void *fdt) +{ + static int node; + + if (node <= 0) { + node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + } + + return node; +} + +/* + * Read a series of parameters in rcc-clk section in device tree + * @param prop_name: Name of the RCC property to be read + * @param array: the array to store the property parameters + * @param count: number of parameters to be read + * @return: 0 on succes or a negative value on error + */ +int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count, + uint32_t *array) +{ + int node; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + return fdt_read_uint32_array(fdt, node, prop_name, count, array); +} + +/* + * Get the subnode offset in rcc-clk section from its name in device tree + * @param name: name of the RCC property + * @return: offset on success, and a negative FDT/ERRNO error code on failure. + */ +int fdt_rcc_subnode_offset(const char *name) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + subnode = fdt_subnode_offset(fdt, node, name); + if (subnode <= 0) { + return -FDT_ERR_NOTFOUND; + } + + return subnode; +} + +/* + * Get the pointer to a rcc-clk property from its name. + * @param name: name of the RCC property + * @param lenp: stores the length of the property. + * @return: pointer to the property on success, and NULL value on failure. + */ +const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) +{ + const fdt32_t *cuint; + int node, len; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return NULL; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return NULL; + } + + cuint = fdt_getprop(fdt, node, prop_name, &len); + if (cuint == NULL) { + return NULL; + } + + *lenp = len; + return cuint; +} + +/* + * Get the secure state for rcc node in device tree. + * @return: true if rcc is configured for secure world access, false if not. + */ +bool fdt_get_rcc_secure_state(void) +{ + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return false; + } + + if (fdt_node_offset_by_compatible(fdt, -1, DT_RCC_SEC_CLK_COMPAT) < 0) { + return false; + } + + return true; +} + +/* + * Get the clock ID of the given node in device tree. + * @param node: node offset + * @return: Clock ID on success, and a negative FDT/ERRNO error code on failure. + */ +int fdt_get_clock_id(int node) +{ + const fdt32_t *cuint; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + cuint = fdt_getprop(fdt, node, "clocks", NULL); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + cuint++; + return (int)fdt32_to_cpu(*cuint); +} + +/* + * Get the frequency of the specified UART instance. + * @param instance: UART interface registers base address. + * @return: clock frequency on success, 0 value on failure. + */ +unsigned long fdt_get_uart_clock_freq(uintptr_t instance) +{ + void *fdt; + int node; + int clk_id; + + if (fdt_get_address(&fdt) == 0) { + return 0UL; + } + + /* Check for UART nodes */ + node = dt_match_instance_by_compatible(DT_UART_COMPAT, instance); + if (node < 0) { + return 0UL; + } + + clk_id = fdt_get_clock_id(node); + if (clk_id < 0) { + return 0UL; + } + + return clk_get_rate((unsigned long)clk_id); +} + +/******************************************************************************* + * This function configures and restores the STGEN counter depending on the + * connected clock. + ******************************************************************************/ +void stm32mp_stgen_config(unsigned long rate) +{ + uint32_t cntfid0; + unsigned long long counter; + + cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); + + if (cntfid0 == rate) { + return; + } + + mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + counter = stm32mp_stgen_get_counter() * rate / cntfid0; + + mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter); + mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32)); + mmio_write_32(STGEN_BASE + CNTFID_OFF, rate); + mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + + write_cntfrq_el0(rate); + + /* Need to update timer with new frequency */ + generic_delay_timer_init(); +} + +/******************************************************************************* + * This function returns the STGEN counter value. + ******************************************************************************/ +unsigned long long stm32mp_stgen_get_counter(void) +{ + return (((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | + mmio_read_32(STGEN_BASE + CNTCVL_OFF)); +} + +/******************************************************************************* + * This function restores the STGEN counter value. + * It takes a first input value as a counter backup value to be restored and a + * offset in ms to be added. + ******************************************************************************/ +void stm32mp_stgen_restore_counter(unsigned long long value, + unsigned long long offset_in_ms) +{ + unsigned long long cnt; + + cnt = value + ((offset_in_ms * + mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U); + + mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt); + mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32)); + mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); +} diff --git a/arm-trusted-firmware/drivers/st/crypto/stm32_hash.c b/arm-trusted-firmware/drivers/st/crypto/stm32_hash.c new file mode 100644 index 0000000..6a1d476 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/crypto/stm32_hash.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DT_HASH_COMPAT "st,stm32f756-hash" + +#define HASH_CR 0x00U +#define HASH_DIN 0x04U +#define HASH_STR 0x08U +#define HASH_SR 0x24U +#define HASH_HREG(x) (0x310U + ((x) * 0x04U)) + +/* Control Register */ +#define HASH_CR_INIT BIT(2) +#define HASH_CR_DATATYPE_SHIFT U(4) + +#define HASH_CR_ALGO_SHA1 0x0U +#define HASH_CR_ALGO_MD5 BIT(7) +#define HASH_CR_ALGO_SHA224 BIT(18) +#define HASH_CR_ALGO_SHA256 (BIT(18) | BIT(7)) + +/* Status Flags */ +#define HASH_SR_DCIS BIT(1) +#define HASH_SR_BUSY BIT(3) + +/* STR Register */ +#define HASH_STR_NBLW_MASK GENMASK(4, 0) +#define HASH_STR_DCAL BIT(8) + +#define MD5_DIGEST_SIZE 16U +#define SHA1_DIGEST_SIZE 20U +#define SHA224_DIGEST_SIZE 28U +#define SHA256_DIGEST_SIZE 32U + +#define RESET_TIMEOUT_US_1MS 1000U +#define HASH_TIMEOUT_US 10000U + +enum stm32_hash_data_format { + HASH_DATA_32_BITS, + HASH_DATA_16_BITS, + HASH_DATA_8_BITS, + HASH_DATA_1_BIT +}; + +struct stm32_hash_instance { + uintptr_t base; + unsigned int clock; + size_t digest_size; +}; + +struct stm32_hash_remain { + uint32_t buffer; + size_t length; +}; + +/* Expect a single HASH peripheral */ +static struct stm32_hash_instance stm32_hash; +static struct stm32_hash_remain stm32_remain; + +static uintptr_t hash_base(void) +{ + return stm32_hash.base; +} + +static int hash_wait_busy(void) +{ + uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); + + while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_BUSY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: busy timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int hash_wait_computation(void) +{ + uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); + + while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_DCIS) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: busy timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int hash_write_data(uint32_t data) +{ + int ret; + + ret = hash_wait_busy(); + if (ret != 0) { + return ret; + } + + mmio_write_32(hash_base() + HASH_DIN, data); + + return 0; +} + +static void hash_hw_init(enum stm32_hash_algo_mode mode) +{ + uint32_t reg; + + reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT); + + switch (mode) { + case HASH_MD5SUM: + reg |= HASH_CR_ALGO_MD5; + stm32_hash.digest_size = MD5_DIGEST_SIZE; + break; + case HASH_SHA1: + reg |= HASH_CR_ALGO_SHA1; + stm32_hash.digest_size = SHA1_DIGEST_SIZE; + break; + case HASH_SHA224: + reg |= HASH_CR_ALGO_SHA224; + stm32_hash.digest_size = SHA224_DIGEST_SIZE; + break; + /* Default selected algo is SHA256 */ + case HASH_SHA256: + default: + reg |= HASH_CR_ALGO_SHA256; + stm32_hash.digest_size = SHA256_DIGEST_SIZE; + break; + } + + mmio_write_32(hash_base() + HASH_CR, reg); +} + +static int hash_get_digest(uint8_t *digest) +{ + int ret; + uint32_t i; + uint32_t dsg; + + ret = hash_wait_computation(); + if (ret != 0) { + return ret; + } + + for (i = 0U; i < (stm32_hash.digest_size / sizeof(uint32_t)); i++) { + dsg = __builtin_bswap32(mmio_read_32(hash_base() + + HASH_HREG(i))); + memcpy(digest + (i * sizeof(uint32_t)), &dsg, sizeof(uint32_t)); + } + +#if defined(IMAGE_BL2) + /* + * Clean hardware context as HASH could be used later + * by non-secure software + */ + hash_hw_init(HASH_SHA256); +#endif + return 0; +} + +int stm32_hash_update(const uint8_t *buffer, size_t length) +{ + size_t remain_length = length; + int ret = 0; + + if ((length == 0U) || (buffer == NULL)) { + return 0; + } + + clk_enable(stm32_hash.clock); + + if (stm32_remain.length != 0U) { + uint32_t copysize; + + copysize = MIN((sizeof(uint32_t) - stm32_remain.length), + length); + memcpy(((uint8_t *)&stm32_remain.buffer) + stm32_remain.length, + buffer, copysize); + remain_length -= copysize; + buffer += copysize; + if (stm32_remain.length == sizeof(uint32_t)) { + ret = hash_write_data(stm32_remain.buffer); + if (ret != 0) { + goto exit; + } + + zeromem(&stm32_remain, sizeof(stm32_remain)); + } + } + + while (remain_length / sizeof(uint32_t) != 0U) { + uint32_t tmp_buf; + + memcpy(&tmp_buf, buffer, sizeof(uint32_t)); + ret = hash_write_data(tmp_buf); + if (ret != 0) { + goto exit; + } + + buffer += sizeof(uint32_t); + remain_length -= sizeof(uint32_t); + } + + if (remain_length != 0U) { + assert(stm32_remain.length == 0U); + + memcpy((uint8_t *)&stm32_remain.buffer, buffer, remain_length); + stm32_remain.length = remain_length; + } + +exit: + clk_disable(stm32_hash.clock); + + return ret; +} + +int stm32_hash_final(uint8_t *digest) +{ + int ret; + + clk_enable(stm32_hash.clock); + + if (stm32_remain.length != 0U) { + ret = hash_write_data(stm32_remain.buffer); + if (ret != 0) { + clk_disable(stm32_hash.clock); + return ret; + } + + mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK, + 8U * stm32_remain.length); + zeromem(&stm32_remain, sizeof(stm32_remain)); + } else { + mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK); + } + + mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL); + + ret = hash_get_digest(digest); + + clk_disable(stm32_hash.clock); + + return ret; +} + +int stm32_hash_final_update(const uint8_t *buffer, uint32_t length, + uint8_t *digest) +{ + int ret; + + ret = stm32_hash_update(buffer, length); + if (ret != 0) { + return ret; + } + + return stm32_hash_final(digest); +} + +void stm32_hash_init(enum stm32_hash_algo_mode mode) +{ + clk_enable(stm32_hash.clock); + + hash_hw_init(mode); + + clk_disable(stm32_hash.clock); + + zeromem(&stm32_remain, sizeof(stm32_remain)); +} + +int stm32_hash_register(void) +{ + struct dt_node_info hash_info; + int node; + + for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT); + node != -FDT_ERR_NOTFOUND; + node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) { +#if defined(IMAGE_BL2) + if (hash_info.status != DT_DISABLED) { + break; + } +#else + /* BL32 uses hash if it is assigned only to secure world */ + if (hash_info.status == DT_SECURE) { + stm32mp_register_secure_periph_iomem(hash_info.base); + break; + } +#endif + } + + if (node == -FDT_ERR_NOTFOUND) { + return -ENODEV; + } + + if (hash_info.clock < 0) { + return -EINVAL; + } + + stm32_hash.base = hash_info.base; + stm32_hash.clock = hash_info.clock; + + clk_enable(stm32_hash.clock); + + if (hash_info.reset >= 0) { + uint32_t id = (uint32_t)hash_info.reset; + + if (stm32mp_reset_assert(id, RESET_TIMEOUT_US_1MS) != 0) { + panic(); + } + udelay(20); + if (stm32mp_reset_deassert(id, RESET_TIMEOUT_US_1MS) != 0) { + panic(); + } + } + + clk_disable(stm32_hash.clock); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c new file mode 100644 index 0000000..4719e1e --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c @@ -0,0 +1,764 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DDRCTL_REG(x, y) \ + { \ + .name = #x, \ + .offset = offsetof(struct stm32mp_ddrctl, x), \ + .par_offset = offsetof(struct y, x) \ + } + +#define DDRPHY_REG(x, y) \ + { \ + .name = #x, \ + .offset = offsetof(struct stm32mp_ddrphy, x), \ + .par_offset = offsetof(struct y, x) \ + } + +/* + * PARAMETERS: value get from device tree : + * size / order need to be aligned with binding + * modification NOT ALLOWED !!! + */ +#define DDRCTL_REG_REG_SIZE 25 /* st,ctl-reg */ +#define DDRCTL_REG_TIMING_SIZE 12 /* st,ctl-timing */ +#define DDRCTL_REG_MAP_SIZE 9 /* st,ctl-map */ +#if STM32MP_DDR_DUAL_AXI_PORT +#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */ +#else +#define DDRCTL_REG_PERF_SIZE 11 /* st,ctl-perf */ +#endif + +#if STM32MP_DDR_32BIT_INTERFACE +#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ +#else +#define DDRPHY_REG_REG_SIZE 9 /* st,phy-reg */ +#endif +#define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ + +#define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) +static const struct stm32mp_ddr_reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = { + DDRCTL_REG_REG(mstr), + DDRCTL_REG_REG(mrctrl0), + DDRCTL_REG_REG(mrctrl1), + DDRCTL_REG_REG(derateen), + DDRCTL_REG_REG(derateint), + DDRCTL_REG_REG(pwrctl), + DDRCTL_REG_REG(pwrtmg), + DDRCTL_REG_REG(hwlpctl), + DDRCTL_REG_REG(rfshctl0), + DDRCTL_REG_REG(rfshctl3), + DDRCTL_REG_REG(crcparctl0), + DDRCTL_REG_REG(zqctl0), + DDRCTL_REG_REG(dfitmg0), + DDRCTL_REG_REG(dfitmg1), + DDRCTL_REG_REG(dfilpcfg0), + DDRCTL_REG_REG(dfiupd0), + DDRCTL_REG_REG(dfiupd1), + DDRCTL_REG_REG(dfiupd2), + DDRCTL_REG_REG(dfiphymstr), + DDRCTL_REG_REG(odtmap), + DDRCTL_REG_REG(dbg0), + DDRCTL_REG_REG(dbg1), + DDRCTL_REG_REG(dbgcmd), + DDRCTL_REG_REG(poisoncfg), + DDRCTL_REG_REG(pccfg), +}; + +#define DDRCTL_REG_TIMING(x) DDRCTL_REG(x, stm32mp1_ddrctrl_timing) +static const struct stm32mp_ddr_reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = { + DDRCTL_REG_TIMING(rfshtmg), + DDRCTL_REG_TIMING(dramtmg0), + DDRCTL_REG_TIMING(dramtmg1), + DDRCTL_REG_TIMING(dramtmg2), + DDRCTL_REG_TIMING(dramtmg3), + DDRCTL_REG_TIMING(dramtmg4), + DDRCTL_REG_TIMING(dramtmg5), + DDRCTL_REG_TIMING(dramtmg6), + DDRCTL_REG_TIMING(dramtmg7), + DDRCTL_REG_TIMING(dramtmg8), + DDRCTL_REG_TIMING(dramtmg14), + DDRCTL_REG_TIMING(odtcfg), +}; + +#define DDRCTL_REG_MAP(x) DDRCTL_REG(x, stm32mp1_ddrctrl_map) +static const struct stm32mp_ddr_reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = { + DDRCTL_REG_MAP(addrmap1), + DDRCTL_REG_MAP(addrmap2), + DDRCTL_REG_MAP(addrmap3), + DDRCTL_REG_MAP(addrmap4), + DDRCTL_REG_MAP(addrmap5), + DDRCTL_REG_MAP(addrmap6), + DDRCTL_REG_MAP(addrmap9), + DDRCTL_REG_MAP(addrmap10), + DDRCTL_REG_MAP(addrmap11), +}; + +#define DDRCTL_REG_PERF(x) DDRCTL_REG(x, stm32mp1_ddrctrl_perf) +static const struct stm32mp_ddr_reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = { + DDRCTL_REG_PERF(sched), + DDRCTL_REG_PERF(sched1), + DDRCTL_REG_PERF(perfhpr1), + DDRCTL_REG_PERF(perflpr1), + DDRCTL_REG_PERF(perfwr1), + DDRCTL_REG_PERF(pcfgr_0), + DDRCTL_REG_PERF(pcfgw_0), + DDRCTL_REG_PERF(pcfgqos0_0), + DDRCTL_REG_PERF(pcfgqos1_0), + DDRCTL_REG_PERF(pcfgwqos0_0), + DDRCTL_REG_PERF(pcfgwqos1_0), +#if STM32MP_DDR_DUAL_AXI_PORT + DDRCTL_REG_PERF(pcfgr_1), + DDRCTL_REG_PERF(pcfgw_1), + DDRCTL_REG_PERF(pcfgqos0_1), + DDRCTL_REG_PERF(pcfgqos1_1), + DDRCTL_REG_PERF(pcfgwqos0_1), + DDRCTL_REG_PERF(pcfgwqos1_1), +#endif +}; + +#define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg) +static const struct stm32mp_ddr_reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = { + DDRPHY_REG_REG(pgcr), + DDRPHY_REG_REG(aciocr), + DDRPHY_REG_REG(dxccr), + DDRPHY_REG_REG(dsgcr), + DDRPHY_REG_REG(dcr), + DDRPHY_REG_REG(odtcr), + DDRPHY_REG_REG(zq0cr1), + DDRPHY_REG_REG(dx0gcr), + DDRPHY_REG_REG(dx1gcr), +#if STM32MP_DDR_32BIT_INTERFACE + DDRPHY_REG_REG(dx2gcr), + DDRPHY_REG_REG(dx3gcr), +#endif +}; + +#define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing) +static const struct stm32mp_ddr_reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = { + DDRPHY_REG_TIMING(ptr0), + DDRPHY_REG_TIMING(ptr1), + DDRPHY_REG_TIMING(ptr2), + DDRPHY_REG_TIMING(dtpr0), + DDRPHY_REG_TIMING(dtpr1), + DDRPHY_REG_TIMING(dtpr2), + DDRPHY_REG_TIMING(mr0), + DDRPHY_REG_TIMING(mr1), + DDRPHY_REG_TIMING(mr2), + DDRPHY_REG_TIMING(mr3), +}; + +/* + * REGISTERS ARRAY: used to parse device tree and interactive mode + */ +static const struct stm32mp_ddr_reg_info ddr_registers[REG_TYPE_NB] = { + [REG_REG] = { + .name = "static", + .desc = ddr_reg, + .size = DDRCTL_REG_REG_SIZE, + .base = DDR_BASE + }, + [REG_TIMING] = { + .name = "timing", + .desc = ddr_timing, + .size = DDRCTL_REG_TIMING_SIZE, + .base = DDR_BASE + }, + [REG_PERF] = { + .name = "perf", + .desc = ddr_perf, + .size = DDRCTL_REG_PERF_SIZE, + .base = DDR_BASE + }, + [REG_MAP] = { + .name = "map", + .desc = ddr_map, + .size = DDRCTL_REG_MAP_SIZE, + .base = DDR_BASE + }, + [REGPHY_REG] = { + .name = "static", + .desc = ddrphy_reg, + .size = DDRPHY_REG_REG_SIZE, + .base = DDRPHY_BASE + }, + [REGPHY_TIMING] = { + .name = "timing", + .desc = ddrphy_timing, + .size = DDRPHY_REG_TIMING_SIZE, + .base = DDRPHY_BASE + }, +}; + +static void stm32mp1_ddrphy_idone_wait(struct stm32mp_ddrphy *phy) +{ + uint32_t pgsr; + int error = 0; + uint64_t timeout = timeout_init_us(TIMEOUT_US_1S); + + do { + pgsr = mmio_read_32((uintptr_t)&phy->pgsr); + + VERBOSE(" > [0x%lx] pgsr = 0x%x &\n", + (uintptr_t)&phy->pgsr, pgsr); + + if (timeout_elapsed(timeout)) { + panic(); + } + + if ((pgsr & DDRPHYC_PGSR_DTERR) != 0U) { + VERBOSE("DQS Gate Trainig Error\n"); + error++; + } + + if ((pgsr & DDRPHYC_PGSR_DTIERR) != 0U) { + VERBOSE("DQS Gate Trainig Intermittent Error\n"); + error++; + } + + if ((pgsr & DDRPHYC_PGSR_DFTERR) != 0U) { + VERBOSE("DQS Drift Error\n"); + error++; + } + + if ((pgsr & DDRPHYC_PGSR_RVERR) != 0U) { + VERBOSE("Read Valid Training Error\n"); + error++; + } + + if ((pgsr & DDRPHYC_PGSR_RVEIRR) != 0U) { + VERBOSE("Read Valid Training Intermittent Error\n"); + error++; + } + } while (((pgsr & DDRPHYC_PGSR_IDONE) == 0U) && (error == 0)); + VERBOSE("\n[0x%lx] pgsr = 0x%x\n", + (uintptr_t)&phy->pgsr, pgsr); +} + +static void stm32mp1_ddrphy_init(struct stm32mp_ddrphy *phy, uint32_t pir) +{ + uint32_t pir_init = pir | DDRPHYC_PIR_INIT; + + mmio_write_32((uintptr_t)&phy->pir, pir_init); + VERBOSE("[0x%lx] pir = 0x%x -> 0x%x\n", + (uintptr_t)&phy->pir, pir_init, + mmio_read_32((uintptr_t)&phy->pir)); + + /* Need to wait 10 configuration clock before start polling */ + udelay(10); + + /* Wait DRAM initialization and Gate Training Evaluation complete */ + stm32mp1_ddrphy_idone_wait(phy); +} + +/* Wait quasi dynamic register update */ +static void stm32mp1_wait_operating_mode(struct stm32mp_ddr_priv *priv, uint32_t mode) +{ + uint64_t timeout; + uint32_t stat; + int break_loop = 0; + + timeout = timeout_init_us(TIMEOUT_US_1S); + for ( ; ; ) { + uint32_t operating_mode; + uint32_t selref_type; + + stat = mmio_read_32((uintptr_t)&priv->ctl->stat); + operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK; + selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK; + VERBOSE("[0x%lx] stat = 0x%x\n", + (uintptr_t)&priv->ctl->stat, stat); + if (timeout_elapsed(timeout)) { + panic(); + } + + if (mode == DDRCTRL_STAT_OPERATING_MODE_SR) { + /* + * Self-refresh due to software + * => checking also STAT.selfref_type. + */ + if ((operating_mode == + DDRCTRL_STAT_OPERATING_MODE_SR) && + (selref_type == DDRCTRL_STAT_SELFREF_TYPE_SR)) { + break_loop = 1; + } + } else if (operating_mode == mode) { + break_loop = 1; + } else if ((mode == DDRCTRL_STAT_OPERATING_MODE_NORMAL) && + (operating_mode == DDRCTRL_STAT_OPERATING_MODE_SR) && + (selref_type == DDRCTRL_STAT_SELFREF_TYPE_ASR)) { + /* Normal mode: handle also automatic self refresh */ + break_loop = 1; + } + + if (break_loop == 1) { + break; + } + } + + VERBOSE("[0x%lx] stat = 0x%x\n", + (uintptr_t)&priv->ctl->stat, stat); +} + +/* Mode Register Writes (MRW or MRS) */ +static void stm32mp1_mode_register_write(struct stm32mp_ddr_priv *priv, uint8_t addr, + uint32_t data) +{ + uint32_t mrctrl0; + + VERBOSE("MRS: %d = %x\n", addr, data); + + /* + * 1. Poll MRSTAT.mr_wr_busy until it is '0'. + * This checks that there is no outstanding MR transaction. + * No write should be performed to MRCTRL0 and MRCTRL1 + * if MRSTAT.mr_wr_busy = 1. + */ + while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) & + DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { + ; + } + + /* + * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank + * and (for MRWs) MRCTRL1.mr_data to define the MR transaction. + */ + mrctrl0 = DDRCTRL_MRCTRL0_MR_TYPE_WRITE | + DDRCTRL_MRCTRL0_MR_RANK_ALL | + (((uint32_t)addr << DDRCTRL_MRCTRL0_MR_ADDR_SHIFT) & + DDRCTRL_MRCTRL0_MR_ADDR_MASK); + mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0); + VERBOSE("[0x%lx] mrctrl0 = 0x%x (0x%x)\n", + (uintptr_t)&priv->ctl->mrctrl0, + mmio_read_32((uintptr_t)&priv->ctl->mrctrl0), mrctrl0); + mmio_write_32((uintptr_t)&priv->ctl->mrctrl1, data); + VERBOSE("[0x%lx] mrctrl1 = 0x%x\n", + (uintptr_t)&priv->ctl->mrctrl1, + mmio_read_32((uintptr_t)&priv->ctl->mrctrl1)); + + /* + * 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1. This + * bit is self-clearing, and triggers the MR transaction. + * The uMCTL2 then asserts the MRSTAT.mr_wr_busy while it performs + * the MR transaction to SDRAM, and no further access can be + * initiated until it is deasserted. + */ + mrctrl0 |= DDRCTRL_MRCTRL0_MR_WR; + mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0); + + while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) & + DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { + ; + } + + VERBOSE("[0x%lx] mrctrl0 = 0x%x\n", + (uintptr_t)&priv->ctl->mrctrl0, mrctrl0); +} + +/* Switch DDR3 from DLL-on to DLL-off */ +static void stm32mp1_ddr3_dll_off(struct stm32mp_ddr_priv *priv) +{ + uint32_t mr1 = mmio_read_32((uintptr_t)&priv->phy->mr1); + uint32_t mr2 = mmio_read_32((uintptr_t)&priv->phy->mr2); + uint32_t dbgcam; + + VERBOSE("mr1: 0x%x\n", mr1); + VERBOSE("mr2: 0x%x\n", mr2); + + /* + * 1. Set the DBG1.dis_hif = 1. + * This prevents further reads/writes being received on the HIF. + */ + mmio_setbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); + VERBOSE("[0x%lx] dbg1 = 0x%x\n", + (uintptr_t)&priv->ctl->dbg1, + mmio_read_32((uintptr_t)&priv->ctl->dbg1)); + + /* + * 2. Ensure all commands have been flushed from the uMCTL2 by polling + * DBGCAM.wr_data_pipeline_empty = 1, + * DBGCAM.rd_data_pipeline_empty = 1, + * DBGCAM.dbg_wr_q_depth = 0 , + * DBGCAM.dbg_lpr_q_depth = 0, and + * DBGCAM.dbg_hpr_q_depth = 0. + */ + do { + dbgcam = mmio_read_32((uintptr_t)&priv->ctl->dbgcam); + VERBOSE("[0x%lx] dbgcam = 0x%x\n", + (uintptr_t)&priv->ctl->dbgcam, dbgcam); + } while ((((dbgcam & DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY) == + DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY)) && + ((dbgcam & DDRCTRL_DBGCAM_DBG_Q_DEPTH) == 0U)); + + /* + * 3. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) + * to disable RTT_NOM: + * a. DDR3: Write to MR1[9], MR1[6] and MR1[2] + * b. DDR4: Write to MR1[10:8] + */ + mr1 &= ~(BIT(9) | BIT(6) | BIT(2)); + stm32mp1_mode_register_write(priv, 1, mr1); + + /* + * 4. For DDR4 only: Perform an MRS command + * (using MRCTRL0 and MRCTRL1 registers) to write to MR5[8:6] + * to disable RTT_PARK + */ + + /* + * 5. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) + * to write to MR2[10:9], to disable RTT_WR + * (and therefore disable dynamic ODT). + * This applies for both DDR3 and DDR4. + */ + mr2 &= ~GENMASK(10, 9); + stm32mp1_mode_register_write(priv, 2, mr2); + + /* + * 6. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) + * to disable the DLL. The timing of this MRS is automatically + * handled by the uMCTL2. + * a. DDR3: Write to MR1[0] + * b. DDR4: Write to MR1[0] + */ + mr1 |= BIT(0); + stm32mp1_mode_register_write(priv, 1, mr1); + + /* + * 7. Put the SDRAM into self-refresh mode by setting + * PWRCTL.selfref_sw = 1, and polling STAT.operating_mode to ensure + * the DDRC has entered self-refresh. + */ + mmio_setbits_32((uintptr_t)&priv->ctl->pwrctl, + DDRCTRL_PWRCTL_SELFREF_SW); + VERBOSE("[0x%lx] pwrctl = 0x%x\n", + (uintptr_t)&priv->ctl->pwrctl, + mmio_read_32((uintptr_t)&priv->ctl->pwrctl)); + + /* + * 8. Wait until STAT.operating_mode[1:0]==11 indicating that the + * DWC_ddr_umctl2 core is in self-refresh mode. + * Ensure transition to self-refresh was due to software + * by checking that STAT.selfref_type[1:0]=2. + */ + stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_SR); + + /* + * 9. Set the MSTR.dll_off_mode = 1. + * warning: MSTR.dll_off_mode is a quasi-dynamic type 2 field + */ + stm32mp_ddr_start_sw_done(priv->ctl); + + mmio_setbits_32((uintptr_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE); + VERBOSE("[0x%lx] mstr = 0x%x\n", + (uintptr_t)&priv->ctl->mstr, + mmio_read_32((uintptr_t)&priv->ctl->mstr)); + + stm32mp_ddr_wait_sw_done_ack(priv->ctl); + + /* 10. Change the clock frequency to the desired value. */ + + /* + * 11. Update any registers which may be required to change for the new + * frequency. This includes static and dynamic registers. + * This includes both uMCTL2 registers and PHY registers. + */ + + /* Change Bypass Mode Frequency Range */ + if (clk_get_rate(DDRPHYC) < 100000000U) { + mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr, + DDRPHYC_DLLGCR_BPS200); + } else { + mmio_setbits_32((uintptr_t)&priv->phy->dllgcr, + DDRPHYC_DLLGCR_BPS200); + } + + mmio_setbits_32((uintptr_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS); + + mmio_setbits_32((uintptr_t)&priv->phy->dx0dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); + mmio_setbits_32((uintptr_t)&priv->phy->dx1dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); +#if STM32MP_DDR_32BIT_INTERFACE + mmio_setbits_32((uintptr_t)&priv->phy->dx2dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); + mmio_setbits_32((uintptr_t)&priv->phy->dx3dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); +#endif + + /* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */ + mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl, + DDRCTRL_PWRCTL_SELFREF_SW); + stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); + + /* + * 13. If ZQCTL0.dis_srx_zqcl = 0, the uMCTL2 performs a ZQCL command + * at this point. + */ + + /* + * 14. Perform MRS commands as required to re-program timing registers + * in the SDRAM for the new frequency + * (in particular, CL, CWL and WR may need to be changed). + */ + + /* 15. Write DBG1.dis_hif = 0 to re-enable reads and writes. */ + mmio_clrbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); + VERBOSE("[0x%lx] dbg1 = 0x%x\n", + (uintptr_t)&priv->ctl->dbg1, + mmio_read_32((uintptr_t)&priv->ctl->dbg1)); +} + +static void stm32mp1_refresh_disable(struct stm32mp_ddrctl *ctl) +{ + stm32mp_ddr_start_sw_done(ctl); + /* Quasi-dynamic register update*/ + mmio_setbits_32((uintptr_t)&ctl->rfshctl3, + DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); + mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); + mmio_clrbits_32((uintptr_t)&ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); + stm32mp_ddr_wait_sw_done_ack(ctl); +} + +static void stm32mp1_refresh_restore(struct stm32mp_ddrctl *ctl, + uint32_t rfshctl3, uint32_t pwrctl) +{ + stm32mp_ddr_start_sw_done(ctl); + if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) { + mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, + DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); + } + if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) { + mmio_setbits_32((uintptr_t)&ctl->pwrctl, + DDRCTRL_PWRCTL_POWERDOWN_EN); + } + mmio_setbits_32((uintptr_t)&ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); + stm32mp_ddr_wait_sw_done_ack(ctl); +} + +void stm32mp1_ddr_init(struct stm32mp_ddr_priv *priv, + struct stm32mp_ddr_config *config) +{ + uint32_t pir; + int ret = -EINVAL; + + if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { + ret = stm32mp_board_ddr_power_init(STM32MP_DDR3); + } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) != 0U) { + ret = stm32mp_board_ddr_power_init(STM32MP_LPDDR2); + } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3) != 0U) { + ret = stm32mp_board_ddr_power_init(STM32MP_LPDDR3); + } else { + ERROR("DDR type not supported\n"); + } + + if (ret != 0) { + panic(); + } + + VERBOSE("name = %s\n", config->info.name); + VERBOSE("speed = %u kHz\n", config->info.speed); + VERBOSE("size = 0x%x\n", config->info.size); + + /* DDR INIT SEQUENCE */ + + /* + * 1. Program the DWC_ddr_umctl2 registers + * nota: check DFIMISC.dfi_init_complete = 0 + */ + + /* 1.1 RESETS: presetn, core_ddrc_rstn, aresetn */ + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); + + /* 1.2. start CLOCK */ + if (stm32mp1_ddr_clk_enable(priv, config->info.speed) != 0) { + panic(); + } + + /* 1.3. deassert reset */ + /* De-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST. */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); + /* + * De-assert presetn once the clocks are active + * and stable via DDRCAPBRST bit. + */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); + + /* 1.4. wait 128 cycles to permit initialization of end logic */ + udelay(2); + /* For PCLK = 133MHz => 1 us is enough, 2 to allow lower frequency */ + + /* 1.5. initialize registers ddr_umctl2 */ + /* Stop uMCTL2 before PHY is ready */ + mmio_clrbits_32((uintptr_t)&priv->ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); + VERBOSE("[0x%lx] dfimisc = 0x%x\n", + (uintptr_t)&priv->ctl->dfimisc, + mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); + + stm32mp_ddr_set_reg(priv, REG_REG, &config->c_reg, ddr_registers); + + /* DDR3 = don't set DLLOFF for init mode */ + if ((config->c_reg.mstr & + (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) + == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { + VERBOSE("deactivate DLL OFF in mstr\n"); + mmio_clrbits_32((uintptr_t)&priv->ctl->mstr, + DDRCTRL_MSTR_DLL_OFF_MODE); + VERBOSE("[0x%lx] mstr = 0x%x\n", + (uintptr_t)&priv->ctl->mstr, + mmio_read_32((uintptr_t)&priv->ctl->mstr)); + } + + stm32mp_ddr_set_reg(priv, REG_TIMING, &config->c_timing, ddr_registers); + stm32mp_ddr_set_reg(priv, REG_MAP, &config->c_map, ddr_registers); + + /* Skip CTRL init, SDRAM init is done by PHY PUBL */ + mmio_clrsetbits_32((uintptr_t)&priv->ctl->init0, + DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK, + DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL); + VERBOSE("[0x%lx] init0 = 0x%x\n", + (uintptr_t)&priv->ctl->init0, + mmio_read_32((uintptr_t)&priv->ctl->init0)); + + stm32mp_ddr_set_reg(priv, REG_PERF, &config->c_perf, ddr_registers); + + /* 2. deassert reset signal core_ddrc_rstn, aresetn and presetn */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); + + /* + * 3. start PHY init by accessing relevant PUBL registers + * (DXGCR, DCR, PTR*, MR*, DTPR*) + */ + stm32mp_ddr_set_reg(priv, REGPHY_REG, &config->p_reg, ddr_registers); + stm32mp_ddr_set_reg(priv, REGPHY_TIMING, &config->p_timing, ddr_registers); + + /* DDR3 = don't set DLLOFF for init mode */ + if ((config->c_reg.mstr & + (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) + == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { + VERBOSE("deactivate DLL OFF in mr1\n"); + mmio_clrbits_32((uintptr_t)&priv->phy->mr1, BIT(0)); + VERBOSE("[0x%lx] mr1 = 0x%x\n", + (uintptr_t)&priv->phy->mr1, + mmio_read_32((uintptr_t)&priv->phy->mr1)); + } + + /* + * 4. Monitor PHY init status by polling PUBL register PGSR.IDONE + * Perform DDR PHY DRAM initialization and Gate Training Evaluation + */ + stm32mp1_ddrphy_idone_wait(priv->phy); + + /* + * 5. Indicate to PUBL that controller performs SDRAM initialization + * by setting PIR.INIT and PIR CTLDINIT and pool PGSR.IDONE + * DRAM init is done by PHY, init0.skip_dram.init = 1 + */ + + pir = DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK | DDRPHYC_PIR_ZCAL | + DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_DRAMINIT | DDRPHYC_PIR_ICPC; + + if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { + pir |= DDRPHYC_PIR_DRAMRST; /* Only for DDR3 */ + } + + stm32mp1_ddrphy_init(priv->phy, pir); + + /* + * 6. SET DFIMISC.dfi_init_complete_en to 1 + * Enable quasi-dynamic register programming. + */ + stm32mp_ddr_start_sw_done(priv->ctl); + + mmio_setbits_32((uintptr_t)&priv->ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); + VERBOSE("[0x%lx] dfimisc = 0x%x\n", + (uintptr_t)&priv->ctl->dfimisc, + mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); + + stm32mp_ddr_wait_sw_done_ack(priv->ctl); + + /* + * 7. Wait for DWC_ddr_umctl2 to move to normal operation mode + * by monitoring STAT.operating_mode signal + */ + + /* Wait uMCTL2 ready */ + stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); + + /* Switch to DLL OFF mode */ + if ((config->c_reg.mstr & DDRCTRL_MSTR_DLL_OFF_MODE) != 0U) { + stm32mp1_ddr3_dll_off(priv); + } + + VERBOSE("DDR DQS training : "); + + /* + * 8. Disable Auto refresh and power down by setting + * - RFSHCTL3.dis_au_refresh = 1 + * - PWRCTL.powerdown_en = 0 + * - DFIMISC.dfiinit_complete_en = 0 + */ + stm32mp1_refresh_disable(priv->ctl); + + /* + * 9. Program PUBL PGCR to enable refresh during training + * and rank to train + * not done => keep the programed value in PGCR + */ + + /* + * 10. configure PUBL PIR register to specify which training step + * to run + * RVTRN is executed only on LPDDR2/LPDDR3 + */ + pir = DDRPHYC_PIR_QSTRN; + if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) == 0U) { + pir |= DDRPHYC_PIR_RVTRN; + } + + stm32mp1_ddrphy_init(priv->phy, pir); + + /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ + stm32mp1_ddrphy_idone_wait(priv->phy); + + /* + * 12. set back registers in step 8 to the orginal values if desidered + */ + stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, + config->c_reg.pwrctl); + + stm32mp_ddr_enable_axi_port(priv->ctl); +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c new file mode 100644 index 0000000..e0621b5 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +void ddr_enable_clock(void) +{ + stm32mp1_clk_rcc_regs_lock(); + + mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR, + RCC_DDRITFCR_DDRC1EN | +#if STM32MP_DDR_DUAL_AXI_PORT + RCC_DDRITFCR_DDRC2EN | +#endif + RCC_DDRITFCR_DDRPHYCEN | + RCC_DDRITFCR_DDRPHYCAPBEN | + RCC_DDRITFCR_DDRCAPBEN); + + stm32mp1_clk_rcc_regs_unlock(); +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c new file mode 100644 index 0000000..b510c8f --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct stm32mp_ddr_priv ddr_priv_data; + +int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed) +{ + unsigned long ddrphy_clk, ddr_clk, mem_speed_hz; + + ddr_enable_clock(); + + ddrphy_clk = clk_get_rate(DDRPHYC); + + VERBOSE("DDR: mem_speed (%u kHz), RCC %lu kHz\n", + mem_speed, ddrphy_clk / 1000U); + + mem_speed_hz = mem_speed * 1000U; + + /* Max 10% frequency delta */ + if (ddrphy_clk > mem_speed_hz) { + ddr_clk = ddrphy_clk - mem_speed_hz; + } else { + ddr_clk = mem_speed_hz - ddrphy_clk; + } + if (ddr_clk > (mem_speed_hz / 10)) { + ERROR("DDR expected freq %u kHz, current is %lu kHz\n", + mem_speed, ddrphy_clk / 1000U); + return -1; + } + return 0; +} + +static int stm32mp1_ddr_setup(void) +{ + struct stm32mp_ddr_priv *priv = &ddr_priv_data; + int ret; + struct stm32mp_ddr_config config; + int node; + uint32_t uret; + void *fdt; + + const struct stm32mp_ddr_param param[] = { + CTL_PARAM(reg), + CTL_PARAM(timing), + CTL_PARAM(map), + CTL_PARAM(perf), + PHY_PARAM(reg), + PHY_PARAM(timing), + }; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); + if (node < 0) { + ERROR("%s: Cannot read DDR node in DT\n", __func__); + return -EINVAL; + } + + ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info); + if (ret < 0) { + return ret; + } + + ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config); + if (ret < 0) { + return ret; + } + + /* Disable axidcg clock gating during init */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); + + stm32mp1_ddr_init(priv, &config); + + /* Enable axidcg clock gating */ + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); + + priv->info.size = config.info.size; + + VERBOSE("%s : ram size(%x, %x)\n", __func__, + (uint32_t)priv->info.base, (uint32_t)priv->info.size); + + if (stm32mp_map_ddr_non_cacheable() != 0) { + panic(); + } + + uret = stm32mp_ddr_test_data_bus(); + if (uret != 0U) { + ERROR("DDR data bus test: can't access memory @ 0x%x\n", + uret); + panic(); + } + + uret = stm32mp_ddr_test_addr_bus(config.info.size); + if (uret != 0U) { + ERROR("DDR addr bus test: can't access memory @ 0x%x\n", + uret); + panic(); + } + + uret = stm32mp_ddr_check_size(); + if (uret < config.info.size) { + ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", + uret, config.info.size); + panic(); + } + + if (stm32mp_unmap_ddr() != 0) { + panic(); + } + + return 0; +} + +int stm32mp1_ddr_probe(void) +{ + struct stm32mp_ddr_priv *priv = &ddr_priv_data; + + VERBOSE("STM32MP DDR probe\n"); + + priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base(); + priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base(); + priv->pwr = stm32mp_pwr_base(); + priv->rcc = stm32mp_rcc_base(); + + priv->info.base = STM32MP_DDR_BASE; + priv->info.size = 0; + + return stm32mp1_ddr_setup(); +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c new file mode 100644 index 0000000..6776e3b --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define INVALID_OFFSET 0xFFU + +static uintptr_t get_base_addr(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_base_type base) +{ + if (base == DDRPHY_BASE) { + return (uintptr_t)priv->phy; + } else { + return (uintptr_t)priv->ctl; + } +} + +void stm32mp_ddr_set_reg(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_reg_type type, + const void *param, const struct stm32mp_ddr_reg_info *ddr_registers) +{ + unsigned int i; + unsigned int value; + enum stm32mp_ddr_base_type base = ddr_registers[type].base; + uintptr_t base_addr = get_base_addr(priv, base); + const struct stm32mp_ddr_reg_desc *desc = ddr_registers[type].desc; + + VERBOSE("init %s\n", ddr_registers[type].name); + for (i = 0; i < ddr_registers[type].size; i++) { + uintptr_t ptr = base_addr + desc[i].offset; + + if (desc[i].par_offset == INVALID_OFFSET) { + ERROR("invalid parameter offset for %s", desc[i].name); + panic(); + } else { + value = *((uint32_t *)((uintptr_t)param + + desc[i].par_offset)); + mmio_write_32(ptr, value); + } + } +} + +/* Start quasi dynamic register update */ +void stm32mp_ddr_start_sw_done(struct stm32mp_ddrctl *ctl) +{ + mmio_clrbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); + VERBOSE("[0x%lx] swctl = 0x%x\n", + (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); +} + +/* Wait quasi dynamic register update */ +void stm32mp_ddr_wait_sw_done_ack(struct stm32mp_ddrctl *ctl) +{ + uint64_t timeout; + uint32_t swstat; + + mmio_setbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); + VERBOSE("[0x%lx] swctl = 0x%x\n", + (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); + + timeout = timeout_init_us(TIMEOUT_US_1S); + do { + swstat = mmio_read_32((uintptr_t)&ctl->swstat); + VERBOSE("[0x%lx] swstat = 0x%x ", + (uintptr_t)&ctl->swstat, swstat); + if (timeout_elapsed(timeout)) { + panic(); + } + } while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U); + + VERBOSE("[0x%lx] swstat = 0x%x\n", + (uintptr_t)&ctl->swstat, swstat); +} + +void stm32mp_ddr_enable_axi_port(struct stm32mp_ddrctl *ctl) +{ + /* Enable uMCTL2 AXI port 0 */ + mmio_setbits_32((uintptr_t)&ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); + VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", (uintptr_t)&ctl->pctrl_0, + mmio_read_32((uintptr_t)&ctl->pctrl_0)); + +#if STM32MP_DDR_DUAL_AXI_PORT + /* Enable uMCTL2 AXI port 1 */ + mmio_setbits_32((uintptr_t)&ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); + VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", (uintptr_t)&ctl->pctrl_1, + mmio_read_32((uintptr_t)&ctl->pctrl_1)); +#endif + +} + +int stm32mp_board_ddr_power_init(enum ddr_type ddr_type) +{ + if (dt_pmic_status() > 0) { + return pmic_ddr_power_init(ddr_type); + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c new file mode 100644 index 0000000..6733cc6 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#define DDR_PATTERN 0xAAAAAAAAU +#define DDR_ANTIPATTERN 0x55555555U + +/******************************************************************************* + * This function tests a simple read/write access to the DDR. + * Note that the previous content is restored after test. + * Returns 0 if success, and address value else. + ******************************************************************************/ +uint32_t stm32mp_ddr_test_rw_access(void) +{ + uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE); + + mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); + + if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { + return (uint32_t)STM32MP_DDR_BASE; + } + + mmio_write_32(STM32MP_DDR_BASE, saved_value); + + return 0U; +} + +/******************************************************************************* + * This function tests the DDR data bus wiring. + * This is inspired from the Data Bus Test algorithm written by Michael Barr + * in "Programming Embedded Systems in C and C++" book. + * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ + * File: memtest.c - This source code belongs to Public Domain. + * Returns 0 if success, and address value else. + ******************************************************************************/ +uint32_t stm32mp_ddr_test_data_bus(void) +{ + uint32_t pattern; + + for (pattern = 1U; pattern != 0U; pattern <<= 1U) { + mmio_write_32(STM32MP_DDR_BASE, pattern); + + if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { + return (uint32_t)STM32MP_DDR_BASE; + } + } + + return 0; +} + +/******************************************************************************* + * This function tests the DDR address bus wiring. + * This is inspired from the Data Bus Test algorithm written by Michael Barr + * in "Programming Embedded Systems in C and C++" book. + * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ + * File: memtest.c - This source code belongs to Public Domain. + * size: size in bytes of the DDR memory device. + * Returns 0 if success, and address value else. + ******************************************************************************/ +uint32_t stm32mp_ddr_test_addr_bus(uint64_t size) +{ + uint64_t addressmask = size - 1U; + uint64_t offset; + uint64_t testoffset = 0U; + + /* Write the default pattern at each of the power-of-two offsets. */ + for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; + offset <<= 1U) { + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset, + DDR_PATTERN); + } + + /* Check for address bits stuck high. */ + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, + DDR_ANTIPATTERN); + + for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; + offset <<= 1U) { + if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) != + DDR_PATTERN) { + return (uint32_t)(STM32MP_DDR_BASE + offset); + } + } + + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN); + + /* Check for address bits stuck low or shorted. */ + for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U; + testoffset <<= 1U) { + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, + DDR_ANTIPATTERN); + + if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { + return STM32MP_DDR_BASE; + } + + for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; + offset <<= 1) { + if ((mmio_read_32(STM32MP_DDR_BASE + + (uint32_t)offset) != DDR_PATTERN) && + (offset != testoffset)) { + return (uint32_t)(STM32MP_DDR_BASE + offset); + } + } + + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, + DDR_PATTERN); + } + + return 0U; +} + +/******************************************************************************* + * This function checks the DDR size. It has to be run with Data Cache off. + * This test is run before data have been put in DDR, and is only done for + * cold boot. The DDR data can then be overwritten, and it is not useful to + * restore its content. + * Returns DDR computed size. + ******************************************************************************/ +uint32_t stm32mp_ddr_check_size(void) +{ + uint32_t offset = sizeof(uint32_t); + + mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); + + while (offset < STM32MP_DDR_MAX_SIZE) { + mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); + dsb(); + + if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { + break; + } + + offset <<= 1U; + } + + INFO("Memory size = 0x%x (%u MB)\n", offset, offset / (1024U * 1024U)); + + return offset; +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c new file mode 100644 index 0000000..0804568 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include + +int stm32mp_ddr_dt_get_info(void *fdt, int node, struct stm32mp_ddr_info *info) +{ + int ret; + + ret = fdt_read_uint32(fdt, node, "st,mem-speed", &info->speed); + if (ret < 0) { + VERBOSE("%s: no st,mem-speed\n", __func__); + return -EINVAL; + } + ret = fdt_read_uint32(fdt, node, "st,mem-size", &info->size); + if (ret < 0) { + VERBOSE("%s: no st,mem-size\n", __func__); + return -EINVAL; + } + info->name = fdt_getprop(fdt, node, "st,mem-name", NULL); + if (info->name == NULL) { + VERBOSE("%s: no st,mem-name\n", __func__); + return -EINVAL; + } + + INFO("RAM: %s\n", info->name); + + return 0; +} + +int stm32mp_ddr_dt_get_param(void *fdt, int node, const struct stm32mp_ddr_param *param, + uint32_t param_size, uintptr_t config) +{ + int ret; + uint32_t idx; + + for (idx = 0U; idx < param_size; idx++) { + ret = fdt_read_uint32_array(fdt, node, param[idx].name, param[idx].size, + (void *)(config + param[idx].offset)); + + VERBOSE("%s: %s[0x%x] = %d\n", __func__, param[idx].name, param[idx].size, ret); + if (ret != 0) { + ERROR("%s: Cannot read %s, error=%d\n", __func__, param[idx].name, ret); + return -EINVAL; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/etzpc/etzpc.c b/arm-trusted-firmware/drivers/st/etzpc/etzpc.c new file mode 100644 index 0000000..ff52a22 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/etzpc/etzpc.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Device Tree related definitions */ +#define ETZPC_COMPAT "st,stm32-etzpc" +#define ETZPC_LOCK_MASK 0x1U +#define ETZPC_MODE_SHIFT 8 +#define ETZPC_MODE_MASK GENMASK(1, 0) +#define ETZPC_ID_SHIFT 16 +#define ETZPC_ID_MASK GENMASK(7, 0) + +/* ID Registers */ +#define ETZPC_TZMA0_SIZE 0x000U +#define ETZPC_DECPROT0 0x010U +#define ETZPC_DECPROT_LOCK0 0x030U +#define ETZPC_HWCFGR 0x3F0U +#define ETZPC_VERR 0x3F4U + +/* ID Registers fields */ +#define ETZPC_TZMA0_SIZE_LOCK BIT(31) +#define ETZPC_DECPROT0_MASK GENMASK(1, 0) +#define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0 +#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8 +#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16 +#define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT 24 + +#define DECPROT_SHIFT 1 +#define IDS_PER_DECPROT_REGS 16U +#define IDS_PER_DECPROT_LOCK_REGS 32U + +/* + * etzpc_instance. + * base : register base address set during init given by user + * chunk_size : supported TZMA size steps + * num_tzma: number of TZMA zone read from register at init + * num_ahb_sec : number of securable AHB master zone read from register + * num_per_sec : number of securable AHB & APB Peripherals read from register + * revision : IP revision read from register at init + */ +struct etzpc_instance { + uintptr_t base; + uint8_t chunck_size; + uint8_t num_tzma; + uint8_t num_per_sec; + uint8_t num_ahb_sec; + uint8_t revision; +}; + +/* Only 1 instance of the ETZPC is expected per platform */ +static struct etzpc_instance etzpc_dev; + +/* + * Implementation uses uint8_t to store each securable DECPROT configuration. + * When resuming from deep suspend, the DECPROT configurations are restored. + */ +#define PERIPH_LOCK_BIT BIT(7) +#define PERIPH_ATTR_MASK GENMASK(2, 0) + +#if ENABLE_ASSERTIONS +static bool valid_decprot_id(unsigned int id) +{ + return id < (unsigned int)etzpc_dev.num_per_sec; +} + +static bool valid_tzma_id(unsigned int id) +{ + return id < (unsigned int)etzpc_dev.num_tzma; +} +#endif + +/* + * etzpc_configure_decprot : Load a DECPROT configuration + * decprot_id : ID of the IP + * decprot_attr : Restriction access attribute + */ +void etzpc_configure_decprot(uint32_t decprot_id, + enum etzpc_decprot_attributes decprot_attr) +{ + uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); + uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; + uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK; + + assert(valid_decprot_id(decprot_id)); + + mmio_clrsetbits_32(etzpc_dev.base + ETZPC_DECPROT0 + offset, + (uint32_t)ETZPC_DECPROT0_MASK << shift, + masked_decprot << shift); +} + +/* + * etzpc_get_decprot : Get the DECPROT attribute + * decprot_id : ID of the IP + * return : Attribute of this DECPROT + */ +enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id) +{ + uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); + uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; + uintptr_t base_decprot = etzpc_dev.base + offset; + uint32_t value; + + assert(valid_decprot_id(decprot_id)); + + value = (mmio_read_32(base_decprot + ETZPC_DECPROT0) >> shift) & + ETZPC_DECPROT0_MASK; + + return (enum etzpc_decprot_attributes)value; +} + +/* + * etzpc_lock_decprot : Lock access to the DECPROT attribute + * decprot_id : ID of the IP + */ +void etzpc_lock_decprot(uint32_t decprot_id) +{ + uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); + uint32_t shift = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); + uintptr_t base_decprot = etzpc_dev.base + offset; + + assert(valid_decprot_id(decprot_id)); + + mmio_write_32(base_decprot + ETZPC_DECPROT_LOCK0, shift); +} + +/* + * etzpc_configure_tzma : Configure the target TZMA read only size + * tzma_id : ID of the memory + * tzma_value : read-only size + */ +void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value) +{ + assert(valid_tzma_id(tzma_id)); + + mmio_write_32(etzpc_dev.base + ETZPC_TZMA0_SIZE + + (sizeof(uint32_t) * tzma_id), tzma_value); +} + +/* + * etzpc_get_tzma : Get the target TZMA read only size + * tzma_id : TZMA ID + * return : Size of read only size + */ +uint16_t etzpc_get_tzma(uint32_t tzma_id) +{ + assert(valid_tzma_id(tzma_id)); + + return (uint16_t)mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE + + (sizeof(uint32_t) * tzma_id)); +} + +/* + * etzpc_lock_tzma : Lock the target TZMA + * tzma_id : TZMA ID + */ +void etzpc_lock_tzma(uint32_t tzma_id) +{ + assert(valid_tzma_id(tzma_id)); + + mmio_setbits_32(etzpc_dev.base + ETZPC_TZMA0_SIZE + + (sizeof(uint32_t) * tzma_id), ETZPC_TZMA0_SIZE_LOCK); +} + +/* + * etzpc_get_lock_tzma : Return the lock status of the target TZMA + * tzma_id : TZMA ID + * return : True if TZMA is locked, false otherwise + */ +bool etzpc_get_lock_tzma(uint32_t tzma_id) +{ + uint32_t tzma_size; + + assert(valid_tzma_id(tzma_id)); + + tzma_size = mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE + + (sizeof(uint32_t) * tzma_id)); + + return (tzma_size & ETZPC_TZMA0_SIZE_LOCK) != 0; +} + +/* + * etzpc_get_num_per_sec : Return the DECPROT ID limit value + */ +uint8_t etzpc_get_num_per_sec(void) +{ + return etzpc_dev.num_per_sec; +} + +/* + * etzpc_get_revision : Return the ETZPC IP revision + */ +uint8_t etzpc_get_revision(void) +{ + return etzpc_dev.revision; +} + +/* + * etzpc_get_base_address : Return the ETZPC IP base address + */ +uintptr_t etzpc_get_base_address(void) +{ + return etzpc_dev.base; +} + +/* + * etzpc_init : Initialize the ETZPC driver + * Return 0 on success and a negative errno on failure + */ +int etzpc_init(void) +{ + uint32_t hwcfg; + int node; + struct dt_node_info etzpc_info; + + node = dt_get_node(&etzpc_info, -1, ETZPC_COMPAT); + if (node < 0) { + return -EIO; + } + + /* Check ETZPC is secure only */ + if (etzpc_info.status != DT_SECURE) { + return -EACCES; + } + + etzpc_dev.base = etzpc_info.base; + + hwcfg = mmio_read_32(etzpc_dev.base + ETZPC_HWCFGR); + + etzpc_dev.num_tzma = (uint8_t)(hwcfg >> ETZPC_HWCFGR_NUM_TZMA_SHIFT); + etzpc_dev.num_per_sec = (uint8_t)(hwcfg >> + ETZPC_HWCFGR_NUM_PER_SEC_SHIFT); + etzpc_dev.num_ahb_sec = (uint8_t)(hwcfg >> + ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT); + etzpc_dev.chunck_size = (uint8_t)(hwcfg >> + ETZPC_HWCFGR_CHUNCKS1N4_SHIFT); + + etzpc_dev.revision = mmio_read_8(etzpc_dev.base + ETZPC_VERR); + + VERBOSE("ETZPC version 0x%x", etzpc_dev.revision); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c b/arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c new file mode 100644 index 0000000..9bdc854 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c @@ -0,0 +1,934 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Timeout for device interface reset */ +#define TIMEOUT_US_1_MS 1000U + +/* FMC2 Compatibility */ +#define DT_FMC2_EBI_COMPAT "st,stm32mp1-fmc2-ebi" +#define DT_FMC2_NFC_COMPAT "st,stm32mp1-fmc2-nfc" +#define MAX_CS 2U +#define MAX_BANK 5U + +/* FMC2 Controller Registers */ +#define FMC2_BCR1 0x00U +#define FMC2_PCR 0x80U +#define FMC2_SR 0x84U +#define FMC2_PMEM 0x88U +#define FMC2_PATT 0x8CU +#define FMC2_HECCR 0x94U +#define FMC2_BCHISR 0x254U +#define FMC2_BCHICR 0x258U +#define FMC2_BCHDSR0 0x27CU +#define FMC2_BCHDSR1 0x280U +#define FMC2_BCHDSR2 0x284U +#define FMC2_BCHDSR3 0x288U +#define FMC2_BCHDSR4 0x28CU + +/* FMC2_BCR1 register */ +#define FMC2_BCR1_FMC2EN BIT(31) +/* FMC2_PCR register */ +#define FMC2_PCR_PWAITEN BIT(1) +#define FMC2_PCR_PBKEN BIT(2) +#define FMC2_PCR_PWID_MASK GENMASK_32(5, 4) +#define FMC2_PCR_PWID(x) (((x) << 4) & FMC2_PCR_PWID_MASK) +#define FMC2_PCR_PWID_8 0x0U +#define FMC2_PCR_PWID_16 0x1U +#define FMC2_PCR_ECCEN BIT(6) +#define FMC2_PCR_ECCALG BIT(8) +#define FMC2_PCR_TCLR_MASK GENMASK_32(12, 9) +#define FMC2_PCR_TCLR(x) (((x) << 9) & FMC2_PCR_TCLR_MASK) +#define FMC2_PCR_TCLR_DEFAULT 0xFU +#define FMC2_PCR_TAR_MASK GENMASK_32(16, 13) +#define FMC2_PCR_TAR(x) (((x) << 13) & FMC2_PCR_TAR_MASK) +#define FMC2_PCR_TAR_DEFAULT 0xFU +#define FMC2_PCR_ECCSS_MASK GENMASK_32(19, 17) +#define FMC2_PCR_ECCSS(x) (((x) << 17) & FMC2_PCR_ECCSS_MASK) +#define FMC2_PCR_ECCSS_512 0x1U +#define FMC2_PCR_ECCSS_2048 0x3U +#define FMC2_PCR_BCHECC BIT(24) +#define FMC2_PCR_WEN BIT(25) +/* FMC2_SR register */ +#define FMC2_SR_NWRF BIT(6) +/* FMC2_PMEM register*/ +#define FMC2_PMEM_MEMSET(x) (((x) & GENMASK_32(7, 0)) << 0) +#define FMC2_PMEM_MEMWAIT(x) (((x) & GENMASK_32(7, 0)) << 8) +#define FMC2_PMEM_MEMHOLD(x) (((x) & GENMASK_32(7, 0)) << 16) +#define FMC2_PMEM_MEMHIZ(x) (((x) & GENMASK_32(7, 0)) << 24) +#define FMC2_PMEM_DEFAULT 0x0A0A0A0AU +/* FMC2_PATT register */ +#define FMC2_PATT_ATTSET(x) (((x) & GENMASK_32(7, 0)) << 0) +#define FMC2_PATT_ATTWAIT(x) (((x) & GENMASK_32(7, 0)) << 8) +#define FMC2_PATT_ATTHOLD(x) (((x) & GENMASK_32(7, 0)) << 16) +#define FMC2_PATT_ATTHIZ(x) (((x) & GENMASK_32(7, 0)) << 24) +#define FMC2_PATT_DEFAULT 0x0A0A0A0AU +/* FMC2_BCHISR register */ +#define FMC2_BCHISR_DERF BIT(1) +/* FMC2_BCHICR register */ +#define FMC2_BCHICR_CLEAR_IRQ GENMASK_32(4, 0) +/* FMC2_BCHDSR0 register */ +#define FMC2_BCHDSR0_DUE BIT(0) +#define FMC2_BCHDSR0_DEF BIT(1) +#define FMC2_BCHDSR0_DEN_MASK GENMASK_32(7, 4) +#define FMC2_BCHDSR0_DEN_SHIFT 4U +/* FMC2_BCHDSR1 register */ +#define FMC2_BCHDSR1_EBP1_MASK GENMASK_32(12, 0) +#define FMC2_BCHDSR1_EBP2_MASK GENMASK_32(28, 16) +#define FMC2_BCHDSR1_EBP2_SHIFT 16U +/* FMC2_BCHDSR2 register */ +#define FMC2_BCHDSR2_EBP3_MASK GENMASK_32(12, 0) +#define FMC2_BCHDSR2_EBP4_MASK GENMASK_32(28, 16) +#define FMC2_BCHDSR2_EBP4_SHIFT 16U +/* FMC2_BCHDSR3 register */ +#define FMC2_BCHDSR3_EBP5_MASK GENMASK_32(12, 0) +#define FMC2_BCHDSR3_EBP6_MASK GENMASK_32(28, 16) +#define FMC2_BCHDSR3_EBP6_SHIFT 16U +/* FMC2_BCHDSR4 register */ +#define FMC2_BCHDSR4_EBP7_MASK GENMASK_32(12, 0) +#define FMC2_BCHDSR4_EBP8_MASK GENMASK_32(28, 16) +#define FMC2_BCHDSR4_EBP8_SHIFT 16U + +/* Timings */ +#define FMC2_THIZ 0x01U +#define FMC2_TIO 8000U +#define FMC2_TSYNC 3000U +#define FMC2_PCR_TIMING_MASK GENMASK_32(3, 0) +#define FMC2_PMEM_PATT_TIMING_MASK GENMASK_32(7, 0) + +#define FMC2_BBM_LEN 2U +#define FMC2_MAX_ECC_BYTES 14U +#define TIMEOUT_US_10_MS 10000U +#define FMC2_PSEC_PER_MSEC (1000UL * 1000UL * 1000UL) + +enum stm32_fmc2_ecc { + FMC2_ECC_HAM = 1U, + FMC2_ECC_BCH4 = 4U, + FMC2_ECC_BCH8 = 8U +}; + +struct stm32_fmc2_cs_reg { + uintptr_t data_base; + uintptr_t cmd_base; + uintptr_t addr_base; +}; + +struct stm32_fmc2_nand_timings { + uint8_t tclr; + uint8_t tar; + uint8_t thiz; + uint8_t twait; + uint8_t thold_mem; + uint8_t tset_mem; + uint8_t thold_att; + uint8_t tset_att; +}; + +struct stm32_fmc2_nfc { + uintptr_t reg_base; + struct stm32_fmc2_cs_reg cs[MAX_CS]; + unsigned long clock_id; + unsigned int reset_id; + uint8_t cs_sel; +}; + +static struct stm32_fmc2_nfc stm32_fmc2; + +static uintptr_t fmc2_base(void) +{ + return stm32_fmc2.reg_base; +} + +static void stm32_fmc2_nand_setup_timing(void) +{ + struct stm32_fmc2_nand_timings tims; + unsigned long hclk = clk_get_rate(stm32_fmc2.clock_id); + unsigned long hclkp = FMC2_PSEC_PER_MSEC / (hclk / 1000U); + unsigned long timing, tar, tclr, thiz, twait; + unsigned long tset_mem, tset_att, thold_mem, thold_att; + uint32_t pcr, pmem, patt; + + tar = MAX(hclkp, NAND_TAR_MIN); + timing = div_round_up(tar, hclkp) - 1U; + tims.tar = MIN(timing, (unsigned long)FMC2_PCR_TIMING_MASK); + + tclr = MAX(hclkp, NAND_TCLR_MIN); + timing = div_round_up(tclr, hclkp) - 1U; + tims.tclr = MIN(timing, (unsigned long)FMC2_PCR_TIMING_MASK); + + tims.thiz = FMC2_THIZ; + thiz = (tims.thiz + 1U) * hclkp; + + /* + * tWAIT > tRP + * tWAIT > tWP + * tWAIT > tREA + tIO + */ + twait = MAX(hclkp, NAND_TRP_MIN); + twait = MAX(twait, NAND_TWP_MIN); + twait = MAX(twait, NAND_TREA_MAX + FMC2_TIO); + timing = div_round_up(twait, hclkp); + tims.twait = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + /* + * tSETUP_MEM > tCS - tWAIT + * tSETUP_MEM > tALS - tWAIT + * tSETUP_MEM > tDS - (tWAIT - tHIZ) + */ + tset_mem = hclkp; + if ((twait < NAND_TCS_MIN) && (tset_mem < (NAND_TCS_MIN - twait))) { + tset_mem = NAND_TCS_MIN - twait; + } + if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) && + (tset_mem < (NAND_TDS_MIN - (twait - thiz)))) { + tset_mem = NAND_TDS_MIN - (twait - thiz); + } + timing = div_round_up(tset_mem, hclkp); + tims.tset_mem = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + /* + * tHOLD_MEM > tCH + * tHOLD_MEM > tREH - tSETUP_MEM + * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT) + */ + thold_mem = MAX(hclkp, NAND_TCH_MIN); + if ((tset_mem < NAND_TREH_MIN) && + (thold_mem < (NAND_TREH_MIN - tset_mem))) { + thold_mem = NAND_TREH_MIN - tset_mem; + } + if (((tset_mem + twait) < NAND_TRC_MIN) && + (thold_mem < (NAND_TRC_MIN - (tset_mem + twait)))) { + thold_mem = NAND_TRC_MIN - (tset_mem + twait); + } + if (((tset_mem + twait) < NAND_TWC_MIN) && + (thold_mem < (NAND_TWC_MIN - (tset_mem + twait)))) { + thold_mem = NAND_TWC_MIN - (tset_mem + twait); + } + timing = div_round_up(thold_mem, hclkp); + tims.thold_mem = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + /* + * tSETUP_ATT > tCS - tWAIT + * tSETUP_ATT > tCLS - tWAIT + * tSETUP_ATT > tALS - tWAIT + * tSETUP_ATT > tRHW - tHOLD_MEM + * tSETUP_ATT > tDS - (tWAIT - tHIZ) + */ + tset_att = hclkp; + if ((twait < NAND_TCS_MIN) && (tset_att < (NAND_TCS_MIN - twait))) { + tset_att = NAND_TCS_MIN - twait; + } + if ((thold_mem < NAND_TRHW_MIN) && + (tset_att < (NAND_TRHW_MIN - thold_mem))) { + tset_att = NAND_TRHW_MIN - thold_mem; + } + if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) && + (tset_att < (NAND_TDS_MIN - (twait - thiz)))) { + tset_att = NAND_TDS_MIN - (twait - thiz); + } + timing = div_round_up(tset_att, hclkp); + tims.tset_att = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + /* + * tHOLD_ATT > tALH + * tHOLD_ATT > tCH + * tHOLD_ATT > tCLH + * tHOLD_ATT > tCOH + * tHOLD_ATT > tDH + * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM + * tHOLD_ATT > tADL - tSETUP_MEM + * tHOLD_ATT > tWH - tSETUP_MEM + * tHOLD_ATT > tWHR - tSETUP_MEM + * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT) + * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) + */ + thold_att = MAX(hclkp, NAND_TALH_MIN); + thold_att = MAX(thold_att, NAND_TCH_MIN); + thold_att = MAX(thold_att, NAND_TCLH_MIN); + thold_att = MAX(thold_att, NAND_TCOH_MIN); + thold_att = MAX(thold_att, NAND_TDH_MIN); + if (((NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC) > tset_mem) && + (thold_att < (NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC - tset_mem))) { + thold_att = NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC - tset_mem; + } + if ((tset_mem < NAND_TADL_MIN) && + (thold_att < (NAND_TADL_MIN - tset_mem))) { + thold_att = NAND_TADL_MIN - tset_mem; + } + if ((tset_mem < NAND_TWH_MIN) && + (thold_att < (NAND_TWH_MIN - tset_mem))) { + thold_att = NAND_TWH_MIN - tset_mem; + } + if ((tset_mem < NAND_TWHR_MIN) && + (thold_att < (NAND_TWHR_MIN - tset_mem))) { + thold_att = NAND_TWHR_MIN - tset_mem; + } + if (((tset_att + twait) < NAND_TRC_MIN) && + (thold_att < (NAND_TRC_MIN - (tset_att + twait)))) { + thold_att = NAND_TRC_MIN - (tset_att + twait); + } + if (((tset_att + twait) < NAND_TWC_MIN) && + (thold_att < (NAND_TWC_MIN - (tset_att + twait)))) { + thold_att = NAND_TWC_MIN - (tset_att + twait); + } + timing = div_round_up(thold_att, hclkp); + tims.thold_att = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + VERBOSE("NAND timings: %u - %u - %u - %u - %u - %u - %u - %u\n", + tims.tclr, tims.tar, tims.thiz, tims.twait, + tims.thold_mem, tims.tset_mem, + tims.thold_att, tims.tset_att); + + /* Set tclr/tar timings */ + pcr = mmio_read_32(fmc2_base() + FMC2_PCR); + pcr &= ~FMC2_PCR_TCLR_MASK; + pcr |= FMC2_PCR_TCLR(tims.tclr); + pcr &= ~FMC2_PCR_TAR_MASK; + pcr |= FMC2_PCR_TAR(tims.tar); + + /* Set tset/twait/thold/thiz timings in common bank */ + pmem = FMC2_PMEM_MEMSET(tims.tset_mem); + pmem |= FMC2_PMEM_MEMWAIT(tims.twait); + pmem |= FMC2_PMEM_MEMHOLD(tims.thold_mem); + pmem |= FMC2_PMEM_MEMHIZ(tims.thiz); + + /* Set tset/twait/thold/thiz timings in attribute bank */ + patt = FMC2_PATT_ATTSET(tims.tset_att); + patt |= FMC2_PATT_ATTWAIT(tims.twait); + patt |= FMC2_PATT_ATTHOLD(tims.thold_att); + patt |= FMC2_PATT_ATTHIZ(tims.thiz); + + mmio_write_32(fmc2_base() + FMC2_PCR, pcr); + mmio_write_32(fmc2_base() + FMC2_PMEM, pmem); + mmio_write_32(fmc2_base() + FMC2_PATT, patt); +} + +static void stm32_fmc2_set_buswidth_16(bool set) +{ + mmio_clrsetbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_PWID_MASK, + (set ? FMC2_PCR_PWID(FMC2_PCR_PWID_16) : 0U)); +} + +static void stm32_fmc2_set_ecc(bool enable) +{ + mmio_clrsetbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_ECCEN, + (enable ? FMC2_PCR_ECCEN : 0U)); +} + +static int stm32_fmc2_ham_correct(uint8_t *buffer, uint8_t *eccbuffer, + uint8_t *ecc) +{ + uint8_t xor_ecc_ones; + uint16_t xor_ecc_1b, xor_ecc_2b, xor_ecc_3b; + union { + uint32_t val; + uint8_t bytes[4]; + } xor_ecc; + + /* Page size--------ECC_Code Size + * 256---------------22 bits LSB (ECC_CODE & 0x003FFFFF) + * 512---------------24 bits (ECC_CODE & 0x00FFFFFF) + * 1024--------------26 bits (ECC_CODE & 0x03FFFFFF) + * 2048--------------28 bits (ECC_CODE & 0x0FFFFFFF) + * 4096--------------30 bits (ECC_CODE & 0x3FFFFFFF) + * 8192--------------32 bits (ECC_CODE & 0xFFFFFFFF) + */ + + /* For Page size 512, ECC_Code size 24 bits */ + xor_ecc_1b = ecc[0] ^ eccbuffer[0]; + xor_ecc_2b = ecc[1] ^ eccbuffer[1]; + xor_ecc_3b = ecc[2] ^ eccbuffer[2]; + + xor_ecc.val = 0U; + xor_ecc.bytes[2] = xor_ecc_3b; + xor_ecc.bytes[1] = xor_ecc_2b; + xor_ecc.bytes[0] = xor_ecc_1b; + + if (xor_ecc.val == 0U) { + return 0; /* No Error */ + } + + xor_ecc_ones = __builtin_popcount(xor_ecc.val); + if (xor_ecc_ones < 23U) { + if (xor_ecc_ones == 12U) { + uint16_t bit_address, byte_address; + + /* Correctable ERROR */ + bit_address = ((xor_ecc_1b >> 1) & BIT(0)) | + ((xor_ecc_1b >> 2) & BIT(1)) | + ((xor_ecc_1b >> 3) & BIT(2)); + + byte_address = ((xor_ecc_1b >> 7) & BIT(0)) | + ((xor_ecc_2b) & BIT(1)) | + ((xor_ecc_2b >> 1) & BIT(2)) | + ((xor_ecc_2b >> 2) & BIT(3)) | + ((xor_ecc_2b >> 3) & BIT(4)) | + ((xor_ecc_3b << 4) & BIT(5)) | + ((xor_ecc_3b << 3) & BIT(6)) | + ((xor_ecc_3b << 2) & BIT(7)) | + ((xor_ecc_3b << 1) & BIT(8)); + + /* Correct bit error in the data */ + buffer[byte_address] = + buffer[byte_address] ^ BIT(bit_address); + VERBOSE("Hamming: 1 ECC error corrected\n"); + + return 0; + } + + /* Non Correctable ERROR */ + ERROR("%s: Uncorrectable ECC Errors\n", __func__); + return -1; + } + + /* ECC ERROR */ + ERROR("%s: Hamming correction error\n", __func__); + return -1; +} + + +static int stm32_fmc2_ham_calculate(uint8_t *buffer, uint8_t *ecc) +{ + uint32_t heccr; + uint64_t timeout = timeout_init_us(TIMEOUT_US_10_MS); + + while ((mmio_read_32(fmc2_base() + FMC2_SR) & FMC2_SR_NWRF) == 0U) { + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } + + heccr = mmio_read_32(fmc2_base() + FMC2_HECCR); + + ecc[0] = heccr; + ecc[1] = heccr >> 8; + ecc[2] = heccr >> 16; + + /* Disable ECC */ + stm32_fmc2_set_ecc(false); + + return 0; +} + +static int stm32_fmc2_bch_correct(uint8_t *buffer, unsigned int eccsize) +{ + uint32_t bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4; + uint16_t pos[8]; + int i, den; + uint64_t timeout = timeout_init_us(TIMEOUT_US_10_MS); + + while ((mmio_read_32(fmc2_base() + FMC2_BCHISR) & + FMC2_BCHISR_DERF) == 0U) { + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } + + bchdsr0 = mmio_read_32(fmc2_base() + FMC2_BCHDSR0); + bchdsr1 = mmio_read_32(fmc2_base() + FMC2_BCHDSR1); + bchdsr2 = mmio_read_32(fmc2_base() + FMC2_BCHDSR2); + bchdsr3 = mmio_read_32(fmc2_base() + FMC2_BCHDSR3); + bchdsr4 = mmio_read_32(fmc2_base() + FMC2_BCHDSR4); + + /* Disable ECC */ + stm32_fmc2_set_ecc(false); + + /* No error found */ + if ((bchdsr0 & FMC2_BCHDSR0_DEF) == 0U) { + return 0; + } + + /* Too many errors detected */ + if ((bchdsr0 & FMC2_BCHDSR0_DUE) != 0U) { + return -EBADMSG; + } + + pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK; + pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT; + pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK; + pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT; + pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK; + pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT; + pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK; + pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT; + + den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT; + for (i = 0; i < den; i++) { + if (pos[i] < (eccsize * 8U)) { + uint8_t bitmask = BIT(pos[i] % 8U); + uint32_t offset = pos[i] / 8U; + + *(buffer + offset) ^= bitmask; + } + } + + return 0; +} + +static void stm32_fmc2_hwctl(struct nand_device *nand) +{ + stm32_fmc2_set_ecc(false); + + if (nand->ecc.max_bit_corr != FMC2_ECC_HAM) { + mmio_clrbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_WEN); + mmio_write_32(fmc2_base() + FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ); + } + + stm32_fmc2_set_ecc(true); +} + +static int stm32_fmc2_read_page(struct nand_device *nand, + unsigned int page, uintptr_t buffer) +{ + unsigned int eccsize = nand->ecc.size; + unsigned int eccbytes = nand->ecc.bytes; + unsigned int eccsteps = nand->page_size / eccsize; + uint8_t ecc_corr[FMC2_MAX_ECC_BYTES]; + uint8_t ecc_cal[FMC2_MAX_ECC_BYTES] = {0U}; + uint8_t *p; + unsigned int i; + unsigned int s; + int ret; + + VERBOSE(">%s page %u buffer %lx\n", __func__, page, buffer); + + ret = nand_read_page_cmd(page, 0U, 0U, 0U); + if (ret != 0) { + return ret; + } + + for (s = 0U, i = nand->page_size + FMC2_BBM_LEN, p = (uint8_t *)buffer; + s < eccsteps; + s++, i += eccbytes, p += eccsize) { + stm32_fmc2_hwctl(nand); + + /* Read the NAND page sector (512 bytes) */ + ret = nand_change_read_column_cmd(s * eccsize, (uintptr_t)p, + eccsize); + if (ret != 0) { + return ret; + } + + if (nand->ecc.max_bit_corr == FMC2_ECC_HAM) { + ret = stm32_fmc2_ham_calculate(p, ecc_cal); + if (ret != 0) { + return ret; + } + } + + /* Read the corresponding ECC bytes */ + ret = nand_change_read_column_cmd(i, (uintptr_t)ecc_corr, + eccbytes); + if (ret != 0) { + return ret; + } + + /* Correct the data */ + if (nand->ecc.max_bit_corr == FMC2_ECC_HAM) { + ret = stm32_fmc2_ham_correct(p, ecc_corr, ecc_cal); + } else { + ret = stm32_fmc2_bch_correct(p, eccsize); + } + + if (ret != 0) { + return ret; + } + } + + return 0; +} + +static void stm32_fmc2_read_data(struct nand_device *nand, + uint8_t *buff, unsigned int length, + bool use_bus8) +{ + uintptr_t data_base = stm32_fmc2.cs[stm32_fmc2.cs_sel].data_base; + + if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { + stm32_fmc2_set_buswidth_16(false); + } + + if ((((uintptr_t)buff & BIT(0)) != 0U) && (length != 0U)) { + *buff = mmio_read_8(data_base); + buff += sizeof(uint8_t); + length -= sizeof(uint8_t); + } + + if ((((uintptr_t)buff & GENMASK_32(1, 0)) != 0U) && + (length >= sizeof(uint16_t))) { + *(uint16_t *)buff = mmio_read_16(data_base); + buff += sizeof(uint16_t); + length -= sizeof(uint16_t); + } + + /* 32bit aligned */ + while (length >= sizeof(uint32_t)) { + *(uint32_t *)buff = mmio_read_32(data_base); + buff += sizeof(uint32_t); + length -= sizeof(uint32_t); + } + + /* Read remaining bytes */ + if (length >= sizeof(uint16_t)) { + *(uint16_t *)buff = mmio_read_16(data_base); + buff += sizeof(uint16_t); + length -= sizeof(uint16_t); + } + + if (length != 0U) { + *buff = mmio_read_8(data_base); + } + + if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { + /* Reconfigure bus width to 16-bit */ + stm32_fmc2_set_buswidth_16(true); + } +} + +static void stm32_fmc2_write_data(struct nand_device *nand, + uint8_t *buff, unsigned int length, + bool use_bus8) +{ + uintptr_t data_base = stm32_fmc2.cs[stm32_fmc2.cs_sel].data_base; + + if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { + /* Reconfigure bus width to 8-bit */ + stm32_fmc2_set_buswidth_16(false); + } + + if ((((uintptr_t)buff & BIT(0)) != 0U) && (length != 0U)) { + mmio_write_8(data_base, *buff); + buff += sizeof(uint8_t); + length -= sizeof(uint8_t); + } + + if ((((uintptr_t)buff & GENMASK_32(1, 0)) != 0U) && + (length >= sizeof(uint16_t))) { + mmio_write_16(data_base, *(uint16_t *)buff); + buff += sizeof(uint16_t); + length -= sizeof(uint16_t); + } + + /* 32bits aligned */ + while (length >= sizeof(uint32_t)) { + mmio_write_32(data_base, *(uint32_t *)buff); + buff += sizeof(uint32_t); + length -= sizeof(uint32_t); + } + + /* Read remaining bytes */ + if (length >= sizeof(uint16_t)) { + mmio_write_16(data_base, *(uint16_t *)buff); + buff += sizeof(uint16_t); + length -= sizeof(uint16_t); + } + + if (length != 0U) { + mmio_write_8(data_base, *buff); + } + + if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { + /* Reconfigure bus width to 16-bit */ + stm32_fmc2_set_buswidth_16(true); + } +} + +static void stm32_fmc2_ctrl_init(void) +{ + uint32_t pcr = mmio_read_32(fmc2_base() + FMC2_PCR); + uint32_t bcr1 = mmio_read_32(fmc2_base() + FMC2_BCR1); + + /* Enable wait feature and NAND flash memory bank */ + pcr |= FMC2_PCR_PWAITEN; + pcr |= FMC2_PCR_PBKEN; + + /* Set buswidth to 8 bits mode for identification */ + pcr &= ~FMC2_PCR_PWID_MASK; + + /* ECC logic is disabled */ + pcr &= ~FMC2_PCR_ECCEN; + + /* Default mode */ + pcr &= ~FMC2_PCR_ECCALG; + pcr &= ~FMC2_PCR_BCHECC; + pcr &= ~FMC2_PCR_WEN; + + /* Set default ECC sector size */ + pcr &= ~FMC2_PCR_ECCSS_MASK; + pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048); + + /* Set default TCLR/TAR timings */ + pcr &= ~FMC2_PCR_TCLR_MASK; + pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT); + pcr &= ~FMC2_PCR_TAR_MASK; + pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT); + + /* Enable FMC2 controller */ + bcr1 |= FMC2_BCR1_FMC2EN; + + mmio_write_32(fmc2_base() + FMC2_BCR1, bcr1); + mmio_write_32(fmc2_base() + FMC2_PCR, pcr); + mmio_write_32(fmc2_base() + FMC2_PMEM, FMC2_PMEM_DEFAULT); + mmio_write_32(fmc2_base() + FMC2_PATT, FMC2_PATT_DEFAULT); +} + +static int stm32_fmc2_exec(struct nand_req *req) +{ + int ret = 0; + + switch (req->type & NAND_REQ_MASK) { + case NAND_REQ_CMD: + VERBOSE("Write CMD %x\n", (uint8_t)req->type); + mmio_write_8(stm32_fmc2.cs[stm32_fmc2.cs_sel].cmd_base, + (uint8_t)req->type); + break; + case NAND_REQ_ADDR: + VERBOSE("Write ADDR %x\n", *(req->addr)); + mmio_write_8(stm32_fmc2.cs[stm32_fmc2.cs_sel].addr_base, + *(req->addr)); + break; + case NAND_REQ_DATAIN: + VERBOSE("Read data\n"); + stm32_fmc2_read_data(req->nand, req->addr, req->length, + ((req->type & NAND_REQ_BUS_WIDTH_8) != + 0U)); + break; + case NAND_REQ_DATAOUT: + VERBOSE("Write data\n"); + stm32_fmc2_write_data(req->nand, req->addr, req->length, + ((req->type & NAND_REQ_BUS_WIDTH_8) != + 0U)); + break; + case NAND_REQ_WAIT: + VERBOSE("WAIT Ready\n"); + ret = nand_wait_ready(req->delay_ms); + break; + default: + ret = -EINVAL; + break; + }; + + return ret; +} + +static void stm32_fmc2_setup(struct nand_device *nand) +{ + uint32_t pcr = mmio_read_32(fmc2_base() + FMC2_PCR); + + /* Set buswidth */ + pcr &= ~FMC2_PCR_PWID_MASK; + if (nand->buswidth == NAND_BUS_WIDTH_16) { + pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_16); + } + + if (nand->ecc.mode == NAND_ECC_HW) { + nand->mtd_read_page = stm32_fmc2_read_page; + + pcr &= ~FMC2_PCR_ECCALG; + pcr &= ~FMC2_PCR_BCHECC; + + pcr &= ~FMC2_PCR_ECCSS_MASK; + pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512); + + switch (nand->ecc.max_bit_corr) { + case FMC2_ECC_HAM: + nand->ecc.bytes = 3; + break; + case FMC2_ECC_BCH8: + pcr |= FMC2_PCR_ECCALG; + pcr |= FMC2_PCR_BCHECC; + nand->ecc.bytes = 13; + break; + default: + /* Use FMC2 ECC BCH4 */ + pcr |= FMC2_PCR_ECCALG; + nand->ecc.bytes = 7; + break; + } + + if ((nand->buswidth & NAND_BUS_WIDTH_16) != 0) { + nand->ecc.bytes++; + } + } + + mmio_write_32(stm32_fmc2.reg_base + FMC2_PCR, pcr); +} + +static const struct nand_ctrl_ops ctrl_ops = { + .setup = stm32_fmc2_setup, + .exec = stm32_fmc2_exec +}; + +int stm32_fmc2_init(void) +{ + int fmc_ebi_node; + int fmc_nfc_node; + int fmc_flash_node = 0; + int nchips = 0; + unsigned int i; + void *fdt = NULL; + const fdt32_t *cuint; + struct dt_node_info info; + uintptr_t bank_address[MAX_BANK] = { 0, 0, 0, 0, 0 }; + uint8_t bank_assigned = 0; + uint8_t bank; + int ret; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + fmc_ebi_node = dt_get_node(&info, -1, DT_FMC2_EBI_COMPAT); + if (fmc_ebi_node < 0) { + return fmc_ebi_node; + } + + if (info.status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + stm32_fmc2.reg_base = info.base; + + if ((info.clock < 0) || (info.reset < 0)) { + return -FDT_ERR_BADVALUE; + } + + stm32_fmc2.clock_id = (unsigned long)info.clock; + stm32_fmc2.reset_id = (unsigned int)info.reset; + + cuint = fdt_getprop(fdt, fmc_ebi_node, "ranges", NULL); + if (cuint == NULL) { + return -FDT_ERR_BADVALUE; + } + + for (i = 0U; i < MAX_BANK; i++) { + bank = fdt32_to_cpu(*cuint); + if ((bank >= MAX_BANK) || ((bank_assigned & BIT(bank)) != 0U)) { + return -FDT_ERR_BADVALUE; + } + bank_assigned |= BIT(bank); + bank_address[bank] = fdt32_to_cpu(*(cuint + 2)); + cuint += 4; + } + + /* Pinctrl initialization */ + if (dt_set_pinctrl_config(fmc_ebi_node) != 0) { + return -FDT_ERR_BADVALUE; + } + + /* Parse NFC controller node */ + fmc_nfc_node = fdt_node_offset_by_compatible(fdt, fmc_ebi_node, + DT_FMC2_NFC_COMPAT); + if (fmc_nfc_node < 0) { + return fmc_nfc_node; + } + + if (fdt_get_status(fmc_nfc_node) == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, fmc_nfc_node, "reg", NULL); + if (cuint == NULL) { + return -FDT_ERR_BADVALUE; + } + + for (i = 0U; i < MAX_CS; i++) { + bank = fdt32_to_cpu(*cuint); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].data_base = fdt32_to_cpu(*(cuint + 1)) + + bank_address[bank]; + + bank = fdt32_to_cpu(*(cuint + 3)); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].cmd_base = fdt32_to_cpu(*(cuint + 4)) + + bank_address[bank]; + + bank = fdt32_to_cpu(*(cuint + 6)); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].addr_base = fdt32_to_cpu(*(cuint + 7)) + + bank_address[bank]; + + cuint += 9; + } + + /* Parse flash nodes */ + fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) { + nchips++; + } + + if (nchips != 1) { + WARN("Only one SLC NAND device supported\n"); + return -FDT_ERR_BADVALUE; + } + + fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) { + /* Get chip select */ + cuint = fdt_getprop(fdt, fmc_flash_node, "reg", NULL); + if (cuint == NULL) { + WARN("Chip select not well defined\n"); + return -FDT_ERR_BADVALUE; + } + + stm32_fmc2.cs_sel = fdt32_to_cpu(*cuint); + if (stm32_fmc2.cs_sel >= MAX_CS) { + return -FDT_ERR_BADVALUE; + } + + VERBOSE("NAND CS %i\n", stm32_fmc2.cs_sel); + } + + /* Enable Clock */ + clk_enable(stm32_fmc2.clock_id); + + /* Reset IP */ + ret = stm32mp_reset_assert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { + panic(); + } + ret = stm32mp_reset_deassert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { + panic(); + } + + /* Setup default IP registers */ + stm32_fmc2_ctrl_init(); + + /* Setup default timings */ + stm32_fmc2_nand_setup_timing(); + + /* Init NAND RAW framework */ + nand_raw_ctrl_init(&ctrl_ops); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c b/arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c new file mode 100644 index 0000000..708989f --- /dev/null +++ b/arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DT_GPIO_BANK_SHIFT 12 +#define DT_GPIO_BANK_MASK GENMASK(16, 12) +#define DT_GPIO_PIN_SHIFT 8 +#define DT_GPIO_PIN_MASK GENMASK(11, 8) +#define DT_GPIO_MODE_MASK GENMASK(7, 0) + +static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type, + uint32_t speed, uint32_t pull, uint32_t od, + uint32_t alternate, uint8_t status); + +/******************************************************************************* + * This function gets GPIO bank node in DT. + * Returns node offset if status is okay in DT, else return 0 + ******************************************************************************/ +static int ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) +{ + int pinctrl_subnode; + uint32_t bank_offset = stm32_get_gpio_bank_offset(bank); + + fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { + const fdt32_t *cuint; + + if (fdt_getprop(fdt, pinctrl_subnode, + "gpio-controller", NULL) == NULL) { + continue; + } + + cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); + if (cuint == NULL) { + continue; + } + + if ((fdt32_to_cpu(*cuint) == bank_offset) && + (fdt_get_status(pinctrl_subnode) != DT_DISABLED)) { + return pinctrl_subnode; + } + } + + return 0; +} + +/******************************************************************************* + * This function gets the pin settings from DT information. + * When analyze and parsing is done, set the GPIO registers. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +static int dt_set_gpio_config(void *fdt, int node, uint8_t status) +{ + const fdt32_t *cuint, *slewrate; + int len; + int pinctrl_node; + uint32_t i; + uint32_t speed = GPIO_SPEED_LOW; + uint32_t pull = GPIO_NO_PULL; + + cuint = fdt_getprop(fdt, node, "pinmux", &len); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); + if (pinctrl_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); + if (slewrate != NULL) { + speed = fdt32_to_cpu(*slewrate); + } + + if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { + pull = GPIO_PULL_UP; + } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { + pull = GPIO_PULL_DOWN; + } else { + VERBOSE("No bias configured in node %d\n", node); + } + + for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) { + uint32_t pincfg; + uint32_t bank; + uint32_t pin; + uint32_t mode; + uint32_t alternate = GPIO_ALTERNATE_(0); + uint32_t type; + uint32_t od = GPIO_OD_OUTPUT_LOW; + int bank_node; + int clk; + + pincfg = fdt32_to_cpu(*cuint); + cuint++; + + bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; + + pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; + + mode = pincfg & DT_GPIO_MODE_MASK; + + switch (mode) { + case 0: + mode = GPIO_MODE_INPUT; + break; + case 1 ... 16: + alternate = mode - 1U; + mode = GPIO_MODE_ALTERNATE; + break; + case 17: + mode = GPIO_MODE_ANALOG; + break; + default: + mode = GPIO_MODE_OUTPUT; + break; + } + + if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { + type = GPIO_TYPE_OPEN_DRAIN; + } else { + type = GPIO_TYPE_PUSH_PULL; + } + + if (fdt_getprop(fdt, node, "output-high", NULL) != NULL) { + if (mode == GPIO_MODE_INPUT) { + mode = GPIO_MODE_OUTPUT; + od = GPIO_OD_OUTPUT_HIGH; + } + } + + if (fdt_getprop(fdt, node, "output-low", NULL) != NULL) { + if (mode == GPIO_MODE_INPUT) { + mode = GPIO_MODE_OUTPUT; + od = GPIO_OD_OUTPUT_LOW; + } + } + + bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node); + if (bank_node == 0) { + ERROR("PINCTRL inconsistent in DT\n"); + panic(); + } + + clk = fdt_get_clock_id(bank_node); + if (clk < 0) { + return -FDT_ERR_NOTFOUND; + } + + /* Platform knows the clock: assert it is okay */ + assert((unsigned long)clk == stm32_get_gpio_bank_clock(bank)); + + set_gpio(bank, pin, mode, type, speed, pull, od, alternate, status); + } + + return 0; +} + +/******************************************************************************* + * This function gets the pin settings from DT information. + * When analyze and parsing is done, set the GPIO registers. + * Returns 0 on success and a negative FDT/ERRNO error code on failure. + ******************************************************************************/ +int dt_set_pinctrl_config(int node) +{ + const fdt32_t *cuint; + int lenp; + uint32_t i; + uint8_t status; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + status = fdt_get_status(node); + if (status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + for (i = 0; i < ((uint32_t)lenp / 4U); i++) { + int p_node, p_subnode; + + p_node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (p_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_subnode(p_subnode, fdt, p_node) { + int ret = dt_set_gpio_config(fdt, p_subnode, status); + + if (ret < 0) { + return ret; + } + } + + cuint++; + } + + return 0; +} + +static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type, + uint32_t speed, uint32_t pull, uint32_t od, + uint32_t alternate, uint8_t status) +{ + uintptr_t base = stm32_get_gpio_bank_base(bank); + unsigned long clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + + clk_enable(clock); + + mmio_clrsetbits_32(base + GPIO_MODE_OFFSET, + (uint32_t)GPIO_MODE_MASK << (pin << 1), + mode << (pin << 1)); + + mmio_clrsetbits_32(base + GPIO_TYPE_OFFSET, + (uint32_t)GPIO_TYPE_MASK << pin, + type << pin); + + mmio_clrsetbits_32(base + GPIO_SPEED_OFFSET, + (uint32_t)GPIO_SPEED_MASK << (pin << 1), + speed << (pin << 1)); + + mmio_clrsetbits_32(base + GPIO_PUPD_OFFSET, + (uint32_t)GPIO_PULL_MASK << (pin << 1), + pull << (pin << 1)); + + if (pin < GPIO_ALT_LOWER_LIMIT) { + mmio_clrsetbits_32(base + GPIO_AFRL_OFFSET, + (uint32_t)GPIO_ALTERNATE_MASK << (pin << 2), + alternate << (pin << 2)); + } else { + size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2; + + mmio_clrsetbits_32(base + GPIO_AFRH_OFFSET, + (uint32_t)GPIO_ALTERNATE_MASK << shift, + alternate << shift); + } + + mmio_clrsetbits_32(base + GPIO_OD_OFFSET, + (uint32_t)GPIO_OD_MASK << pin, + od << pin); + + VERBOSE("GPIO %u mode set to 0x%x\n", bank, + mmio_read_32(base + GPIO_MODE_OFFSET)); + VERBOSE("GPIO %u type set to 0x%x\n", bank, + mmio_read_32(base + GPIO_TYPE_OFFSET)); + VERBOSE("GPIO %u speed set to 0x%x\n", bank, + mmio_read_32(base + GPIO_SPEED_OFFSET)); + VERBOSE("GPIO %u mode pull to 0x%x\n", bank, + mmio_read_32(base + GPIO_PUPD_OFFSET)); + VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank, + mmio_read_32(base + GPIO_AFRL_OFFSET)); + VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, + mmio_read_32(base + GPIO_AFRH_OFFSET)); + VERBOSE("GPIO %u output data set to 0x%x\n", bank, + mmio_read_32(base + GPIO_OD_OFFSET)); + + clk_disable(clock); + + if (status == DT_SECURE) { + stm32mp_register_secure_gpio(bank, pin); +#if !IMAGE_BL2 + set_gpio_secure_cfg(bank, pin, true); +#endif + + } else { + stm32mp_register_non_secure_gpio(bank, pin); +#if !IMAGE_BL2 + set_gpio_secure_cfg(bank, pin, false); +#endif + } +} + +void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) +{ + uintptr_t base = stm32_get_gpio_bank_base(bank); + unsigned long clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + + clk_enable(clock); + + if (secure) { + mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } else { + mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } + + clk_disable(clock); +} + +void set_gpio_reset_cfg(uint32_t bank, uint32_t pin) +{ + set_gpio(bank, pin, GPIO_MODE_ANALOG, GPIO_TYPE_PUSH_PULL, + GPIO_SPEED_LOW, GPIO_NO_PULL, GPIO_OD_OUTPUT_LOW, + GPIO_ALTERNATE_(0), DT_DISABLED); + set_gpio_secure_cfg(bank, pin, stm32_gpio_is_secure_at_reset(bank)); +} diff --git a/arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c b/arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c new file mode 100644 index 0000000..bf6c3ee --- /dev/null +++ b/arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c @@ -0,0 +1,982 @@ +/* + * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* STM32 I2C registers offsets */ +#define I2C_CR1 0x00U +#define I2C_CR2 0x04U +#define I2C_OAR1 0x08U +#define I2C_OAR2 0x0CU +#define I2C_TIMINGR 0x10U +#define I2C_TIMEOUTR 0x14U +#define I2C_ISR 0x18U +#define I2C_ICR 0x1CU +#define I2C_PECR 0x20U +#define I2C_RXDR 0x24U +#define I2C_TXDR 0x28U + +#define TIMINGR_CLEAR_MASK 0xF0FFFFFFU + +#define MAX_NBYTE_SIZE 255U + +#define I2C_NSEC_PER_SEC 1000000000L + +/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */ +#define I2C_TIMING 0x10D07DB5 + +static void notif_i2c_timeout(struct i2c_handle_s *hi2c) +{ + hi2c->i2c_err |= I2C_ERROR_TIMEOUT; + hi2c->i2c_mode = I2C_MODE_NONE; + hi2c->i2c_state = I2C_STATE_READY; +} + +/* + * @brief Configure I2C Analog noise filter. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C peripheral. + * @param analog_filter: New state of the Analog filter + * @retval 0 if OK, negative value else + */ +static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, + uint32_t analog_filter) +{ + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return -EBUSY; + } + + hi2c->lock = 1; + + hi2c->i2c_state = I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + + /* Reset I2Cx ANOFF bit */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF); + + /* Set analog filter bit*/ + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter); + + /* Enable the selected I2C peripheral */ + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + + hi2c->i2c_state = I2C_STATE_READY; + + hi2c->lock = 0; + + return 0; +} + +/* + * @brief Get I2C setup information from the device tree and set pinctrl + * configuration. + * @param fdt: Pointer to the device tree + * @param node: I2C node offset + * @param init: Ref to the initialization configuration structure + * @retval 0 if OK, negative value else + */ +int stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init) +{ + const fdt32_t *cuint; + + cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); + if (cuint == NULL) { + init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; + } else { + init->rise_time = fdt32_to_cpu(*cuint); + } + + cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); + if (cuint == NULL) { + init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; + } else { + init->fall_time = fdt32_to_cpu(*cuint); + } + + cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); + if (cuint == NULL) { + init->speed_mode = STM32_I2C_SPEED_DEFAULT; + } else { + switch (fdt32_to_cpu(*cuint)) { + case STANDARD_RATE: + init->speed_mode = I2C_SPEED_STANDARD; + break; + case FAST_RATE: + init->speed_mode = I2C_SPEED_FAST; + break; + case FAST_PLUS_RATE: + init->speed_mode = I2C_SPEED_FAST_PLUS; + break; + default: + init->speed_mode = STM32_I2C_SPEED_DEFAULT; + break; + } + } + + return dt_set_pinctrl_config(node); +} + +/* + * @brief Initialize the I2C device. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param init_data: Initialization configuration structure + * @retval 0 if OK, negative value else + */ +int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data) +{ + int rc = 0; + uint32_t timing = I2C_TIMING; + + if (hi2c == NULL) { + return -ENOENT; + } + + if (hi2c->i2c_state == I2C_STATE_RESET) { + hi2c->lock = 0; + } + + hi2c->i2c_state = I2C_STATE_BUSY; + + clk_enable(hi2c->clock); + + /* Disable the selected I2C peripheral */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + + /* Configure I2Cx: Frequency range */ + mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR, + timing & TIMINGR_CLEAR_MASK); + + /* Disable Own Address1 before set the Own Address1 configuration */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN); + + /* Configure I2Cx: Own Address1 and ack own address1 mode */ + if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) { + mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, + I2C_OAR1_OA1EN | init_data->own_address1); + } else { /* I2C_ADDRESSINGMODE_10BIT */ + mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, + I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | + init_data->own_address1); + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0); + + /* Configure I2Cx: Addressing Master mode */ + if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) { + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10); + } + + /* + * Enable the AUTOEND by default, and enable NACK + * (should be disabled only during Slave process). + */ + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, + I2C_CR2_AUTOEND | I2C_CR2_NACK); + + /* Disable Own Address2 before set the Own Address2 configuration */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE); + + /* Configure I2Cx: Dual mode and Own Address2 */ + mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2, + init_data->dual_address_mode | + init_data->own_address2 | + (init_data->own_address2_masks << 8)); + + /* Configure I2Cx: Generalcall and NoStretch mode */ + mmio_write_32(hi2c->i2c_base_addr + I2C_CR1, + init_data->general_call_mode | + init_data->no_stretch_mode); + + /* Enable the selected I2C peripheral */ + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + + hi2c->i2c_err = I2C_ERROR_NONE; + hi2c->i2c_state = I2C_STATE_READY; + hi2c->i2c_mode = I2C_MODE_NONE; + + rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ? + I2C_ANALOGFILTER_ENABLE : + I2C_ANALOGFILTER_DISABLE); + if (rc != 0) { + ERROR("Cannot initialize I2C analog filter (%d)\n", rc); + clk_disable(hi2c->clock); + return rc; + } + + clk_disable(hi2c->clock); + + return rc; +} + +/* + * @brief I2C Tx data register flush process. + * @param hi2c: I2C handle + * @retval None + */ +static void i2c_flush_txdr(struct i2c_handle_s *hi2c) +{ + /* + * If a pending TXIS flag is set, + * write a dummy data in TXDR to clear it. + */ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) != + 0U) { + mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0); + } + + /* Flush TX register if not empty */ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) == + 0U) { + mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR, + I2C_FLAG_TXE); + } +} + +/* + * @brief This function handles I2C Communication timeout. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param flag: Specifies the I2C flag to check + * @param awaited_value: The awaited bit value for the flag (0 or 1) + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, + uint8_t awaited_value, uint64_t timeout_ref) +{ + for ( ; ; ) { + uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR); + + if (!!(isr & flag) != !!awaited_value) { + return 0; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } +} + +/* + * @brief This function handles Acknowledge failed detection during + * an I2C Communication. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { + return 0; + } + + /* + * Wait until STOP Flag is reset. + * AutoEnd should be initiate after AF. + */ + while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_STOPF) == 0U) { + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); + + i2c_flush_txdr(hi2c); + + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); + + hi2c->i2c_err |= I2C_ERROR_AF; + hi2c->i2c_state = I2C_STATE_READY; + hi2c->i2c_mode = I2C_MODE_NONE; + + hi2c->lock = 0; + + return -EIO; +} + +/* + * @brief This function handles I2C Communication timeout for specific usage + * of TXIS flag. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_TXIS) == 0U) { + if (i2c_ack_failed(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } + + return 0; +} + +/* + * @brief This function handles I2C Communication timeout for specific + * usage of STOP flag. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_STOPF) == 0U) { + if (i2c_ack_failed(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } + + return 0; +} + +/* + * @brief Handles I2Cx communication when starting transfer or during transfer + * (TC or TCR flag are set). + * @param hi2c: I2C handle + * @param dev_addr: Specifies the slave address to be programmed + * @param size: Specifies the number of bytes to be programmed. + * This parameter must be a value between 0 and 255. + * @param i2c_mode: New state of the I2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref I2C_RELOAD_MODE: Enable Reload mode. + * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. + * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. + * @param request: New state of the I2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. + * @arg @ref I2C_GENERATE_STOP: Generate stop condition + * (size should be set to 0). + * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. + * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. + * @retval None + */ +static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t size, uint32_t i2c_mode, + uint32_t request) +{ + uint32_t clr_value, set_value; + + clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | + I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | + (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); + + set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | + (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | + i2c_mode | request; + + mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value); +} + +/* + * @brief Master sends target device address followed by internal memory + * address for write request. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address + * @param mem_add_size: Size of internal memory address + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_request_memory_write(struct i2c_handle_s *hi2c, + uint16_t dev_addr, uint16_t mem_addr, + uint16_t mem_add_size, uint64_t timeout_ref) +{ + i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, + I2C_GENERATE_START_WRITE); + + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { + /* Send Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)(mem_addr & 0x00FFU)); + } else { + /* Send MSB of Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)((mem_addr & 0xFF00U) >> 8)); + + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + return -EIO; + } + + /* Send LSB of Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)(mem_addr & 0x00FFU)); + } + + if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) { + return -EIO; + } + + return 0; +} + +/* + * @brief Master sends target device address followed by internal memory + * address for read request. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address + * @param mem_add_size: Size of internal memory address + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint64_t timeout_ref) +{ + i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, + I2C_GENERATE_START_WRITE); + + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { + /* Send Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)(mem_addr & 0x00FFU)); + } else { + /* Send MSB of Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)((mem_addr & 0xFF00U) >> 8)); + + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + return -EIO; + } + + /* Send LSB of Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)(mem_addr & 0x00FFU)); + } + + if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) { + return -EIO; + } + + return 0; +} +/* + * @brief Generic function to write an amount of data in blocking mode + * (for Memory Mode and Master Mode) + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address (if Memory Mode) + * @param mem_add_size: Size of internal memory address (if Memory Mode) + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @param mode: Communication mode + * @retval 0 if OK, negative value else + */ +static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms, + enum i2c_mode_e mode) +{ + uint64_t timeout_ref; + int rc = -EIO; + uint8_t *p_buff = p_data; + uint32_t xfer_size; + uint32_t xfer_count = size; + + if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { + return -1; + } + + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return -EBUSY; + } + + if ((p_data == NULL) || (size == 0U)) { + return -EINVAL; + } + + clk_enable(hi2c->clock); + + hi2c->lock = 1; + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); + if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { + goto bail; + } + + hi2c->i2c_state = I2C_STATE_BUSY_TX; + hi2c->i2c_mode = mode; + hi2c->i2c_err = I2C_ERROR_NONE; + + timeout_ref = timeout_init_us(timeout_ms * 1000); + + if (mode == I2C_MODE_MEM) { + /* In Memory Mode, Send Slave Address and Memory Address */ + if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, + mem_add_size, timeout_ref) != 0) { + goto bail; + } + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } else { + /* In Master Mode, Send Slave Address */ + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, + I2C_GENERATE_START_WRITE); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, + I2C_GENERATE_START_WRITE); + } + } + + do { + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + goto bail; + } + + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff); + p_buff++; + xfer_count--; + xfer_size--; + + if ((xfer_count != 0U) && (xfer_size == 0U)) { + /* Wait until TCR flag is set */ + if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, + timeout_ref) != 0) { + goto bail; + } + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_RELOAD_MODE, + I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_AUTOEND_MODE, + I2C_NO_STARTSTOP); + } + } + + } while (xfer_count > 0U); + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is reset. + */ + if (i2c_wait_stop(hi2c, timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); + + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); + + hi2c->i2c_state = I2C_STATE_READY; + hi2c->i2c_mode = I2C_MODE_NONE; + + rc = 0; + +bail: + hi2c->lock = 0; + clk_disable(hi2c->clock); + + return rc; +} + +/* + * @brief Write an amount of data in blocking mode to a specific memory + * address. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address + * @param mem_add_size: Size of internal memory address + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms) +{ + return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size, + p_data, size, timeout_ms, I2C_MODE_MEM); +} + +/* + * @brief Transmits in master mode an amount of data in blocking mode. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms) +{ + return i2c_write(hi2c, dev_addr, 0, 0, + p_data, size, timeout_ms, I2C_MODE_MASTER); +} + +/* + * @brief Generic function to read an amount of data in blocking mode + * (for Memory Mode and Master Mode) + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address (if Memory Mode) + * @param mem_add_size: Size of internal memory address (if Memory Mode) + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @param mode: Communication mode + * @retval 0 if OK, negative value else + */ +static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms, + enum i2c_mode_e mode) +{ + uint64_t timeout_ref; + int rc = -EIO; + uint8_t *p_buff = p_data; + uint32_t xfer_count = size; + uint32_t xfer_size; + + if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { + return -1; + } + + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return -EBUSY; + } + + if ((p_data == NULL) || (size == 0U)) { + return -EINVAL; + } + + clk_enable(hi2c->clock); + + hi2c->lock = 1; + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); + if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { + goto bail; + } + + hi2c->i2c_state = I2C_STATE_BUSY_RX; + hi2c->i2c_mode = mode; + hi2c->i2c_err = I2C_ERROR_NONE; + + if (mode == I2C_MODE_MEM) { + /* Send Memory Address */ + if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, + mem_add_size, timeout_ref) != 0) { + goto bail; + } + } + + /* + * Send Slave Address. + * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE + * and generate RESTART. + */ + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, I2C_GENERATE_START_READ); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + } + + do { + if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) { + goto bail; + } + + *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); + p_buff++; + xfer_size--; + xfer_count--; + + if ((xfer_count != 0U) && (xfer_size == 0U)) { + if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, + timeout_ref) != 0) { + goto bail; + } + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_RELOAD_MODE, + I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_AUTOEND_MODE, + I2C_NO_STARTSTOP); + } + } + } while (xfer_count > 0U); + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is reset. + */ + if (i2c_wait_stop(hi2c, timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); + + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); + + hi2c->i2c_state = I2C_STATE_READY; + hi2c->i2c_mode = I2C_MODE_NONE; + + rc = 0; + +bail: + hi2c->lock = 0; + clk_disable(hi2c->clock); + + return rc; +} + +/* + * @brief Read an amount of data in blocking mode from a specific memory + * address. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address + * @param mem_add_size: Size of internal memory address + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms) +{ + return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size, + p_data, size, timeout_ms, I2C_MODE_MEM); +} + +/* + * @brief Receives in master mode an amount of data in blocking mode. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms) +{ + return i2c_read(hi2c, dev_addr, 0, 0, + p_data, size, timeout_ms, I2C_MODE_MASTER); +} + +/* + * @brief Checks if target device is ready for communication. + * @note This function is used with Memory devices + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param trials: Number of trials + * @param timeout_ms: Timeout duration in milliseconds + * @retval True if device is ready, false else + */ +bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, + uint16_t dev_addr, uint32_t trials, + uint32_t timeout_ms) +{ + uint32_t i2c_trials = 0U; + bool rc = false; + + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return rc; + } + + clk_enable(hi2c->clock); + + hi2c->lock = 1; + hi2c->i2c_mode = I2C_MODE_NONE; + + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != + 0U) { + goto bail; + } + + hi2c->i2c_state = I2C_STATE_BUSY; + hi2c->i2c_err = I2C_ERROR_NONE; + + do { + uint64_t timeout_ref; + + /* Generate Start */ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) & + I2C_OAR1_OA1MODE) == 0) { + mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, + (((uint32_t)dev_addr & I2C_CR2_SADD) | + I2C_CR2_START | I2C_CR2_AUTOEND) & + ~I2C_CR2_RD_WRN); + } else { + mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, + (((uint32_t)dev_addr & I2C_CR2_SADD) | + I2C_CR2_START | I2C_CR2_ADD10) & + ~I2C_CR2_RD_WRN); + } + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is set or a NACK flag is set. + */ + timeout_ref = timeout_init_us(timeout_ms * 1000); + do { + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) { + break; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + goto bail; + } + } while (true); + + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_AF) == 0U) { + if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, + timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, + I2C_FLAG_STOPF); + + hi2c->i2c_state = I2C_STATE_READY; + + rc = true; + goto bail; + } + + if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); + + if (i2c_trials == trials) { + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, + I2C_CR2_STOP); + + if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, + timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, + I2C_FLAG_STOPF); + } + + i2c_trials++; + } while (i2c_trials < trials); + + notif_i2c_timeout(hi2c); + +bail: + hi2c->lock = 0; + clk_disable(hi2c->clock); + + return rc; +} + diff --git a/arm-trusted-firmware/drivers/st/io/io_mmc.c b/arm-trusted-firmware/drivers/st/io/io_mmc.c new file mode 100644 index 0000000..2bf88e6 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/io/io_mmc.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* SDMMC device functions */ +static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info); +static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); +static int mmc_block_seek(io_entity_t *entity, int mode, + signed long long offset); +static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int mmc_block_close(io_entity_t *entity); +static int mmc_dev_close(io_dev_info_t *dev_info); +static io_type_t device_type_mmc(void); + +static signed long long seek_offset; +static size_t (*_read_blocks)(int lba, uintptr_t buf, size_t size); + +static const io_dev_connector_t mmc_dev_connector = { + .dev_open = mmc_dev_open +}; + +static const io_dev_funcs_t mmc_dev_funcs = { + .type = device_type_mmc, + .open = mmc_block_open, + .seek = mmc_block_seek, + .size = NULL, + .read = mmc_block_read, + .write = NULL, + .close = mmc_block_close, + .dev_init = mmc_dev_init, + .dev_close = mmc_dev_close, +}; + +static const io_dev_info_t mmc_dev_info = { + .funcs = &mmc_dev_funcs, + .info = 0, +}; + +/* Identify the device type as mmc device */ +static io_type_t device_type_mmc(void) +{ + return IO_TYPE_MMC; +} + +/* Open a connection to the mmc device */ +static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info) +{ + struct io_mmc_dev_spec *device_spec = + (struct io_mmc_dev_spec *)init_params; + + assert(dev_info != NULL); + *dev_info = (io_dev_info_t *)&mmc_dev_info; + + _read_blocks = !device_spec->use_boot_part ? + mmc_read_blocks : mmc_boot_part_read_blocks; + + return 0; +} + +static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) +{ + return 0; +} + +/* Close a connection to the mmc device */ +static int mmc_dev_close(io_dev_info_t *dev_info) +{ + return 0; +} + +/* Open a file on the mmc device */ +static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + seek_offset = 0; + return 0; +} + +/* Seek to a particular file offset on the mmc device */ +static int mmc_block_seek(io_entity_t *entity, int mode, + signed long long offset) +{ + seek_offset = offset; + return 0; +} + +/* Read data from a file on the mmc device */ +static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + uint8_t retries; + + for (retries = 0U; retries < 3U; retries++) { + *length_read = _read_blocks(seek_offset / MMC_BLOCK_SIZE, + buffer, length); + + if (*length_read == length) { + return 0; + } + WARN("%s: length_read = %lu (!= %lu), retry %u\n", __func__, + (unsigned long)*length_read, (unsigned long)length, + retries + 1U); + } + + return -EIO; +} + +/* Close a file on the mmc device */ +static int mmc_block_close(io_entity_t *entity) +{ + return 0; +} + +/* Register the mmc driver with the IO abstraction */ +int register_io_dev_mmc(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&mmc_dev_info); + if (result == 0) { + *dev_con = &mmc_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/st/io/io_stm32image.c b/arm-trusted-firmware/drivers/st/io/io_stm32image.c new file mode 100644 index 0000000..9fa0c50 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/io/io_stm32image.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2018-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 + +static uintptr_t backend_dev_handle; +static uintptr_t backend_image_spec; +static uint32_t *stm32_img; +static uint8_t first_lba_buffer[MAX_LBA_SIZE] __aligned(4); +static struct stm32image_part_info *current_part; + +/* STM32 Image driver functions */ +static int stm32image_dev_open(const uintptr_t init_params, + io_dev_info_t **dev_info); +static int stm32image_partition_open(io_dev_info_t *dev_info, + const uintptr_t spec, io_entity_t *entity); +static int stm32image_partition_size(io_entity_t *entity, size_t *length); +static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read); +static int stm32image_partition_close(io_entity_t *entity); +static int stm32image_dev_init(io_dev_info_t *dev_info, + const uintptr_t init_params); +static int stm32image_dev_close(io_dev_info_t *dev_info); + +/* Identify the device type as a virtual driver */ +static io_type_t device_type_stm32image(void) +{ + return IO_TYPE_STM32IMAGE; +} + +static const io_dev_connector_t stm32image_dev_connector = { + .dev_open = stm32image_dev_open +}; + +static const io_dev_funcs_t stm32image_dev_funcs = { + .type = device_type_stm32image, + .open = stm32image_partition_open, + .size = stm32image_partition_size, + .read = stm32image_partition_read, + .close = stm32image_partition_close, + .dev_init = stm32image_dev_init, + .dev_close = stm32image_dev_close, +}; + +static io_dev_info_t stm32image_dev_info = { + .funcs = &stm32image_dev_funcs, + .info = (uintptr_t)0, +}; + +static struct stm32image_device_info stm32image_dev; + +static int get_part_idx_by_binary_type(uint32_t binary_type) +{ + int i; + + for (i = 0; i < STM32_PART_NUM; i++) { + if (stm32image_dev.part_info[i].binary_type == binary_type) { + return i; + } + } + + return -EINVAL; +} + +/* Open a connection to the STM32IMAGE device */ +static int stm32image_dev_open(const uintptr_t init_params, + io_dev_info_t **dev_info) +{ + int i; + struct stm32image_device_info *device_info = + (struct stm32image_device_info *)init_params; + + assert(dev_info != NULL); + *dev_info = (io_dev_info_t *)&stm32image_dev_info; + + stm32image_dev.device_size = device_info->device_size; + stm32image_dev.lba_size = device_info->lba_size; + + for (i = 0; i < STM32_PART_NUM; i++) { + memcpy(stm32image_dev.part_info[i].name, + device_info->part_info[i].name, MAX_PART_NAME_SIZE); + stm32image_dev.part_info[i].binary_type = + device_info->part_info[i].binary_type; + stm32image_dev.part_info[i].part_offset = + device_info->part_info[i].part_offset; + stm32image_dev.part_info[i].bkp_offset = + device_info->part_info[i].bkp_offset; + } + + return 0; +} + +/* Do some basic package checks */ +static int stm32image_dev_init(io_dev_info_t *dev_info, + const uintptr_t init_params) +{ + int result; + + if ((backend_dev_handle != 0U) || (backend_image_spec != 0U)) { + ERROR("STM32 Image io supports only one session\n"); + return -ENOMEM; + } + + /* Obtain a reference to the image by querying the platform layer */ + result = plat_get_image_source(STM32_IMAGE_ID, &backend_dev_handle, + &backend_image_spec); + if (result != 0) { + ERROR("STM32 image error (%i)\n", result); + return -EINVAL; + } + + return result; +} + +/* Close a connection to the STM32 Image device */ +static int stm32image_dev_close(io_dev_info_t *dev_info) +{ + backend_dev_handle = 0U; + backend_image_spec = 0U; + stm32_img = NULL; + + return 0; +} + +/* Open a partition */ +static int stm32image_partition_open(io_dev_info_t *dev_info, + const uintptr_t spec, io_entity_t *entity) +{ + const struct stm32image_part_info *partition_spec; + int idx; + + assert(entity != NULL); + + partition_spec = (struct stm32image_part_info *)spec; + assert(partition_spec != NULL); + + idx = get_part_idx_by_binary_type(partition_spec->binary_type); + if ((idx < 0) || (idx > STM32_PART_NUM)) { + ERROR("Wrong partition index (%d)\n", idx); + return -EINVAL; + } + + current_part = &stm32image_dev.part_info[idx]; + stm32_img = (uint32_t *)¤t_part->part_offset; + + return 0; +} + +/* Return the size of a partition */ +static int stm32image_partition_size(io_entity_t *entity, size_t *length) +{ + int result; + uintptr_t backend_handle; + size_t bytes_read; + boot_api_image_header_t *header = + (boot_api_image_header_t *)first_lba_buffer; + + assert(entity != NULL); + assert(length != NULL); + + /* Attempt to access the image */ + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + + if (result < 0) { + ERROR("%s: io_open (%i)\n", __func__, result); + return result; + } + + /* Reset magic header value */ + header->magic = 0; + + while (header->magic == 0U) { + result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img); + if (result != 0) { + ERROR("%s: io_seek (%i)\n", __func__, result); + break; + } + + result = io_read(backend_handle, (uintptr_t)header, + MAX_LBA_SIZE, (size_t *)&bytes_read); + if (result != 0) { + if (current_part->bkp_offset == 0U) { + ERROR("%s: io_read (%i)\n", __func__, result); + } + header->magic = 0; + } + + if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) || + (header->binary_type != current_part->binary_type) || + (header->image_length >= stm32image_dev.device_size)) { + VERBOSE("%s: partition %s not found at %x\n", + __func__, current_part->name, *stm32_img); + + if (current_part->bkp_offset == 0U) { + result = -ENOMEM; + break; + } + + /* Header not correct, check next offset for backup */ + *stm32_img += current_part->bkp_offset; + if (*stm32_img > stm32image_dev.device_size) { + /* No backup found, end of device reached */ + WARN("%s : partition %s not found\n", + __func__, current_part->name); + result = -ENOMEM; + break; + } + header->magic = 0; + } + } + + io_close(backend_handle); + + if (result != 0) { + return result; + } + + if (header->image_length < stm32image_dev.lba_size) { + *length = stm32image_dev.lba_size; + } else { + *length = header->image_length; + } + + INFO("STM32 Image size : %lu\n", (unsigned long)*length); + + return 0; +} + +/* Read data from a partition */ +static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + int result = -EINVAL; + uint8_t *local_buffer; + boot_api_image_header_t *header = + (boot_api_image_header_t *)first_lba_buffer; + size_t hdr_sz = sizeof(boot_api_image_header_t); + + assert(entity != NULL); + assert(buffer != 0U); + assert(length_read != NULL); + + local_buffer = (uint8_t *)buffer; + *length_read = 0U; + + while (*length_read == 0U) { + int offset; + int local_length; + uintptr_t backend_handle; + + if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { + /* Check for backup as image is corrupted */ + if (current_part->bkp_offset == 0U) { + result = -ENOMEM; + break; + } + + *stm32_img += current_part->bkp_offset; + if (*stm32_img >= stm32image_dev.device_size) { + /* End of device reached */ + result = -ENOMEM; + break; + } + + local_buffer = (uint8_t *)buffer; + + result = stm32image_partition_size(entity, &length); + if (result != 0) { + break; + } + } + + /* Part of image already loaded with the header */ + memcpy(local_buffer, (uint8_t *)first_lba_buffer + hdr_sz, + MAX_LBA_SIZE - hdr_sz); + local_buffer += MAX_LBA_SIZE - hdr_sz; + offset = MAX_LBA_SIZE; + + /* New image length to be read */ + local_length = round_up(length - ((MAX_LBA_SIZE) - hdr_sz), + stm32image_dev.lba_size); + + if ((header->load_address != 0U) && + (header->load_address != buffer)) { + ERROR("Wrong load address\n"); + panic(); + } + + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + + if (result != 0) { + ERROR("%s: io_open (%i)\n", __func__, result); + break; + } + + result = io_seek(backend_handle, IO_SEEK_SET, + *stm32_img + offset); + + if (result != 0) { + ERROR("%s: io_seek (%i)\n", __func__, result); + *length_read = 0; + io_close(backend_handle); + break; + } + + result = io_read(backend_handle, (uintptr_t)local_buffer, + local_length, length_read); + + /* Adding part of size already read from header */ + *length_read += MAX_LBA_SIZE - hdr_sz; + + if (result != 0) { + ERROR("%s: io_read (%i)\n", __func__, result); + *length_read = 0; + header->magic = 0; + continue; + } + + result = stm32mp_check_header(header, buffer); + if (result != 0) { + ERROR("Header check failed\n"); + *length_read = 0; + header->magic = 0; + } + + result = stm32mp_auth_image(header, buffer); + if (result != 0) { + ERROR("Authentication Failed (%i)\n", result); + return result; + } + + inv_dcache_range(round_up((uintptr_t)(local_buffer + length - hdr_sz), + CACHE_WRITEBACK_GRANULE), *length_read - length + hdr_sz); + + io_close(backend_handle); + } + + return result; +} + +/* Close a partition */ +static int stm32image_partition_close(io_entity_t *entity) +{ + current_part = NULL; + + return 0; +} + +/* Register the stm32image driver with the IO abstraction */ +int register_io_dev_stm32image(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&stm32image_dev_info); + if (result == 0) { + *dev_con = &stm32image_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c b/arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c new file mode 100644 index 0000000..74451d7 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* IWDG registers offsets */ +#define IWDG_KR_OFFSET 0x00U + +/* Registers values */ +#define IWDG_KR_RELOAD_KEY 0xAAAA + +struct stm32_iwdg_instance { + uintptr_t base; + unsigned long clock; + uint8_t flags; + int num_irq; +}; + +static struct stm32_iwdg_instance stm32_iwdg[IWDG_MAX_INSTANCE]; + +static int stm32_iwdg_get_dt_node(struct dt_node_info *info, int offset) +{ + int node; + + node = dt_get_node(info, offset, DT_IWDG_COMPAT); + if (node < 0) { + if (offset == -1) { + VERBOSE("%s: No IDWG found\n", __func__); + } + return -FDT_ERR_NOTFOUND; + } + + return node; +} + +void stm32_iwdg_refresh(void) +{ + uint8_t i; + + for (i = 0U; i < IWDG_MAX_INSTANCE; i++) { + struct stm32_iwdg_instance *iwdg = &stm32_iwdg[i]; + + /* 0x00000000 is not a valid address for IWDG peripherals */ + if (iwdg->base != 0U) { + clk_enable(iwdg->clock); + + mmio_write_32(iwdg->base + IWDG_KR_OFFSET, + IWDG_KR_RELOAD_KEY); + + clk_disable(iwdg->clock); + } + } +} + +int stm32_iwdg_init(void) +{ + int node = -1; + struct dt_node_info dt_info; + void *fdt; + uint32_t __unused count = 0; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + for (node = stm32_iwdg_get_dt_node(&dt_info, node); + node != -FDT_ERR_NOTFOUND; + node = stm32_iwdg_get_dt_node(&dt_info, node)) { + struct stm32_iwdg_instance *iwdg; + uint32_t hw_init; + uint32_t idx; + + count++; + + idx = stm32_iwdg_get_instance(dt_info.base); + iwdg = &stm32_iwdg[idx]; + iwdg->base = dt_info.base; + iwdg->clock = (unsigned long)dt_info.clock; + + /* DT can specify low power cases */ + if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) == + NULL) { + iwdg->flags |= IWDG_DISABLE_ON_STOP; + } + + if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) == + NULL) { + iwdg->flags |= IWDG_DISABLE_ON_STANDBY; + } + + /* Explicit list of supported bit flags */ + hw_init = stm32_iwdg_get_otp_config(idx); + + if ((hw_init & IWDG_HW_ENABLED) != 0) { + if (dt_info.status == DT_DISABLED) { + ERROR("OTP enabled but iwdg%u DT-disabled\n", + idx + 1U); + panic(); + } + iwdg->flags |= IWDG_HW_ENABLED; + } + + if (dt_info.status == DT_DISABLED) { + zeromem((void *)iwdg, + sizeof(struct stm32_iwdg_instance)); + continue; + } + + if ((hw_init & IWDG_DISABLE_ON_STOP) != 0) { + iwdg->flags |= IWDG_DISABLE_ON_STOP; + } + + if ((hw_init & IWDG_DISABLE_ON_STANDBY) != 0) { + iwdg->flags |= IWDG_DISABLE_ON_STANDBY; + } + + VERBOSE("IWDG%u found, %ssecure\n", idx + 1U, + ((dt_info.status & DT_NON_SECURE) != 0) ? + "non-" : ""); + + if ((dt_info.status & DT_NON_SECURE) != 0) { + stm32mp_register_non_secure_periph_iomem(iwdg->base); + } else { + stm32mp_register_secure_periph_iomem(iwdg->base); + } + +#if defined(IMAGE_BL2) + if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) { + return -1; + } +#endif + } + + VERBOSE("%u IWDG instance%s found\n", count, (count > 1U) ? "s" : ""); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c b/arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c new file mode 100644 index 0000000..40641b5 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c @@ -0,0 +1,776 @@ +/* + * Copyright (c) 2018-2022, STMicroelectronics - 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 + +/* Registers offsets */ +#define SDMMC_POWER 0x00U +#define SDMMC_CLKCR 0x04U +#define SDMMC_ARGR 0x08U +#define SDMMC_CMDR 0x0CU +#define SDMMC_RESPCMDR 0x10U +#define SDMMC_RESP1R 0x14U +#define SDMMC_RESP2R 0x18U +#define SDMMC_RESP3R 0x1CU +#define SDMMC_RESP4R 0x20U +#define SDMMC_DTIMER 0x24U +#define SDMMC_DLENR 0x28U +#define SDMMC_DCTRLR 0x2CU +#define SDMMC_DCNTR 0x30U +#define SDMMC_STAR 0x34U +#define SDMMC_ICR 0x38U +#define SDMMC_MASKR 0x3CU +#define SDMMC_ACKTIMER 0x40U +#define SDMMC_IDMACTRLR 0x50U +#define SDMMC_IDMABSIZER 0x54U +#define SDMMC_IDMABASE0R 0x58U +#define SDMMC_IDMABASE1R 0x5CU +#define SDMMC_FIFOR 0x80U + +/* SDMMC power control register */ +#define SDMMC_POWER_PWRCTRL GENMASK(1, 0) +#define SDMMC_POWER_PWRCTRL_PWR_CYCLE BIT(1) +#define SDMMC_POWER_DIRPOL BIT(4) + +/* SDMMC clock control register */ +#define SDMMC_CLKCR_WIDBUS_4 BIT(14) +#define SDMMC_CLKCR_WIDBUS_8 BIT(15) +#define SDMMC_CLKCR_NEGEDGE BIT(16) +#define SDMMC_CLKCR_HWFC_EN BIT(17) +#define SDMMC_CLKCR_SELCLKRX_0 BIT(20) + +/* SDMMC command register */ +#define SDMMC_CMDR_CMDTRANS BIT(6) +#define SDMMC_CMDR_CMDSTOP BIT(7) +#define SDMMC_CMDR_WAITRESP GENMASK(9, 8) +#define SDMMC_CMDR_WAITRESP_SHORT BIT(8) +#define SDMMC_CMDR_WAITRESP_SHORT_NOCRC BIT(9) +#define SDMMC_CMDR_CPSMEN BIT(12) + +/* SDMMC data control register */ +#define SDMMC_DCTRLR_DTEN BIT(0) +#define SDMMC_DCTRLR_DTDIR BIT(1) +#define SDMMC_DCTRLR_DTMODE GENMASK(3, 2) +#define SDMMC_DCTRLR_DBLOCKSIZE GENMASK(7, 4) +#define SDMMC_DCTRLR_DBLOCKSIZE_SHIFT 4 +#define SDMMC_DCTRLR_FIFORST BIT(13) + +#define SDMMC_DCTRLR_CLEAR_MASK (SDMMC_DCTRLR_DTEN | \ + SDMMC_DCTRLR_DTDIR | \ + SDMMC_DCTRLR_DTMODE | \ + SDMMC_DCTRLR_DBLOCKSIZE) + +/* SDMMC status register */ +#define SDMMC_STAR_CCRCFAIL BIT(0) +#define SDMMC_STAR_DCRCFAIL BIT(1) +#define SDMMC_STAR_CTIMEOUT BIT(2) +#define SDMMC_STAR_DTIMEOUT BIT(3) +#define SDMMC_STAR_TXUNDERR BIT(4) +#define SDMMC_STAR_RXOVERR BIT(5) +#define SDMMC_STAR_CMDREND BIT(6) +#define SDMMC_STAR_CMDSENT BIT(7) +#define SDMMC_STAR_DATAEND BIT(8) +#define SDMMC_STAR_DBCKEND BIT(10) +#define SDMMC_STAR_DPSMACT BIT(12) +#define SDMMC_STAR_RXFIFOHF BIT(15) +#define SDMMC_STAR_RXFIFOE BIT(19) +#define SDMMC_STAR_IDMATE BIT(27) +#define SDMMC_STAR_IDMABTC BIT(28) + +/* SDMMC DMA control register */ +#define SDMMC_IDMACTRLR_IDMAEN BIT(0) + +#define SDMMC_STATIC_FLAGS (SDMMC_STAR_CCRCFAIL | \ + SDMMC_STAR_DCRCFAIL | \ + SDMMC_STAR_CTIMEOUT | \ + SDMMC_STAR_DTIMEOUT | \ + SDMMC_STAR_TXUNDERR | \ + SDMMC_STAR_RXOVERR | \ + SDMMC_STAR_CMDREND | \ + SDMMC_STAR_CMDSENT | \ + SDMMC_STAR_DATAEND | \ + SDMMC_STAR_DBCKEND | \ + SDMMC_STAR_IDMATE | \ + SDMMC_STAR_IDMABTC) + +#define TIMEOUT_US_1_MS 1000U +#define TIMEOUT_US_10_MS 10000U +#define TIMEOUT_US_1_S 1000000U + +/* Power cycle delays in ms */ +#define VCC_POWER_OFF_DELAY 2 +#define VCC_POWER_ON_DELAY 2 +#define POWER_CYCLE_DELAY 2 +#define POWER_OFF_DELAY 2 +#define POWER_ON_DELAY 1 + +#ifndef DT_SDMMC2_COMPAT +#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" +#endif + +static void stm32_sdmmc2_init(void); +static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd); +static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd); +static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width); +static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size); +static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size); +static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size); + +static const struct mmc_ops stm32_sdmmc2_ops = { + .init = stm32_sdmmc2_init, + .send_cmd = stm32_sdmmc2_send_cmd, + .set_ios = stm32_sdmmc2_set_ios, + .prepare = stm32_sdmmc2_prepare, + .read = stm32_sdmmc2_read, + .write = stm32_sdmmc2_write, +}; + +static struct stm32_sdmmc2_params sdmmc2_params; + +#pragma weak plat_sdmmc2_use_dma +bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory) +{ + return false; +} + +static void stm32_sdmmc2_init(void) +{ + uint32_t clock_div; + uint32_t freq = STM32MP_MMC_INIT_FREQ; + uintptr_t base = sdmmc2_params.reg_base; + int ret; + + if (sdmmc2_params.max_freq != 0U) { + freq = MIN(sdmmc2_params.max_freq, freq); + } + + if (sdmmc2_params.vmmc_regu != NULL) { + ret = regulator_disable(sdmmc2_params.vmmc_regu); + if (ret < 0) { + panic(); + } + } + + mdelay(VCC_POWER_OFF_DELAY); + + mmio_write_32(base + SDMMC_POWER, + SDMMC_POWER_PWRCTRL_PWR_CYCLE | sdmmc2_params.dirpol); + mdelay(POWER_CYCLE_DELAY); + + if (sdmmc2_params.vmmc_regu != NULL) { + ret = regulator_enable(sdmmc2_params.vmmc_regu); + if (ret < 0) { + panic(); + } + } + + mdelay(VCC_POWER_ON_DELAY); + + mmio_write_32(base + SDMMC_POWER, sdmmc2_params.dirpol); + mdelay(POWER_OFF_DELAY); + + clock_div = div_round_up(sdmmc2_params.clk_rate, freq * 2U); + + mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | + sdmmc2_params.negedge | + sdmmc2_params.pin_ckin); + + mmio_write_32(base + SDMMC_POWER, + SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol); + + mdelay(POWER_ON_DELAY); +} + +static int stm32_sdmmc2_stop_transfer(void) +{ + struct mmc_cmd cmd_stop; + + zeromem(&cmd_stop, sizeof(struct mmc_cmd)); + + cmd_stop.cmd_idx = MMC_CMD(12); + cmd_stop.resp_type = MMC_RESPONSE_R1B; + + return stm32_sdmmc2_send_cmd(&cmd_stop); +} + +static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) +{ + uint64_t timeout; + uint32_t flags_cmd, status; + uint32_t flags_data = 0; + int err = 0; + uintptr_t base = sdmmc2_params.reg_base; + unsigned int cmd_reg, arg_reg; + + if (cmd == NULL) { + return -EINVAL; + } + + flags_cmd = SDMMC_STAR_CTIMEOUT; + arg_reg = cmd->cmd_arg; + + if ((mmio_read_32(base + SDMMC_CMDR) & SDMMC_CMDR_CPSMEN) != 0U) { + mmio_write_32(base + SDMMC_CMDR, 0); + } + + cmd_reg = cmd->cmd_idx | SDMMC_CMDR_CPSMEN; + + if (cmd->resp_type == 0U) { + flags_cmd |= SDMMC_STAR_CMDSENT; + } + + if ((cmd->resp_type & MMC_RSP_48) != 0U) { + if ((cmd->resp_type & MMC_RSP_136) != 0U) { + flags_cmd |= SDMMC_STAR_CMDREND; + cmd_reg |= SDMMC_CMDR_WAITRESP; + } else if ((cmd->resp_type & MMC_RSP_CRC) != 0U) { + flags_cmd |= SDMMC_STAR_CMDREND | SDMMC_STAR_CCRCFAIL; + cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT; + } else { + flags_cmd |= SDMMC_STAR_CMDREND; + cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT_NOCRC; + } + } + + switch (cmd->cmd_idx) { + case MMC_CMD(1): + arg_reg |= OCR_POWERUP; + break; + case MMC_CMD(8): + if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { + cmd_reg |= SDMMC_CMDR_CMDTRANS; + } + break; + case MMC_CMD(12): + cmd_reg |= SDMMC_CMDR_CMDSTOP; + break; + case MMC_CMD(17): + case MMC_CMD(18): + cmd_reg |= SDMMC_CMDR_CMDTRANS; + if (sdmmc2_params.use_dma) { + flags_data |= SDMMC_STAR_DCRCFAIL | + SDMMC_STAR_DTIMEOUT | + SDMMC_STAR_DATAEND | + SDMMC_STAR_RXOVERR | + SDMMC_STAR_IDMATE; + } + break; + case MMC_ACMD(41): + arg_reg |= OCR_3_2_3_3 | OCR_3_3_3_4; + break; + case MMC_ACMD(51): + cmd_reg |= SDMMC_CMDR_CMDTRANS; + if (sdmmc2_params.use_dma) { + flags_data |= SDMMC_STAR_DCRCFAIL | + SDMMC_STAR_DTIMEOUT | + SDMMC_STAR_DATAEND | + SDMMC_STAR_RXOVERR | + SDMMC_STAR_IDMATE | + SDMMC_STAR_DBCKEND; + } + break; + default: + break; + } + + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + + /* + * Clear the SDMMC_DCTRLR if the command does not await data. + * Skip CMD55 as the next command could be data related, and + * the register could have been set in prepare function. + */ + if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) && + (cmd->cmd_idx != MMC_CMD(55))) { + mmio_write_32(base + SDMMC_DCTRLR, 0U); + } + + if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) { + mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); + } + + mmio_write_32(base + SDMMC_ARGR, arg_reg); + + mmio_write_32(base + SDMMC_CMDR, cmd_reg); + + status = mmio_read_32(base + SDMMC_STAR); + + timeout = timeout_init_us(TIMEOUT_US_10_MS); + + while ((status & flags_cmd) == 0U) { + if (timeout_elapsed(timeout)) { + err = -ETIMEDOUT; + ERROR("%s: timeout 10ms (cmd = %u,status = %x)\n", + __func__, cmd->cmd_idx, status); + goto err_exit; + } + + status = mmio_read_32(base + SDMMC_STAR); + } + + if ((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) { + if ((status & SDMMC_STAR_CTIMEOUT) != 0U) { + err = -ETIMEDOUT; + /* + * Those timeouts can occur, and framework will handle + * the retries. CMD8 is expected to return this timeout + * for eMMC + */ + if (!((cmd->cmd_idx == MMC_CMD(1)) || + (cmd->cmd_idx == MMC_CMD(13)) || + ((cmd->cmd_idx == MMC_CMD(8)) && + (cmd->resp_type == MMC_RESPONSE_R7)))) { + ERROR("%s: CTIMEOUT (cmd = %u,status = %x)\n", + __func__, cmd->cmd_idx, status); + } + } else { + err = -EIO; + ERROR("%s: CRCFAIL (cmd = %u,status = %x)\n", + __func__, cmd->cmd_idx, status); + } + + goto err_exit; + } + + if ((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) { + if ((cmd->cmd_idx == MMC_CMD(9)) && + ((cmd_reg & SDMMC_CMDR_WAITRESP) == SDMMC_CMDR_WAITRESP)) { + /* Need to invert response to match CSD structure */ + cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP4R); + cmd->resp_data[1] = mmio_read_32(base + SDMMC_RESP3R); + cmd->resp_data[2] = mmio_read_32(base + SDMMC_RESP2R); + cmd->resp_data[3] = mmio_read_32(base + SDMMC_RESP1R); + } else { + cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP1R); + if ((cmd_reg & SDMMC_CMDR_WAITRESP) == + SDMMC_CMDR_WAITRESP) { + cmd->resp_data[1] = mmio_read_32(base + + SDMMC_RESP2R); + cmd->resp_data[2] = mmio_read_32(base + + SDMMC_RESP3R); + cmd->resp_data[3] = mmio_read_32(base + + SDMMC_RESP4R); + } + } + } + + if (flags_data == 0U) { + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + + return 0; + } + + status = mmio_read_32(base + SDMMC_STAR); + + timeout = timeout_init_us(TIMEOUT_US_10_MS); + + while ((status & flags_data) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: timeout 10ms (cmd = %u,status = %x)\n", + __func__, cmd->cmd_idx, status); + err = -ETIMEDOUT; + goto err_exit; + } + + status = mmio_read_32(base + SDMMC_STAR); + }; + + if ((status & (SDMMC_STAR_DTIMEOUT | SDMMC_STAR_DCRCFAIL | + SDMMC_STAR_TXUNDERR | SDMMC_STAR_RXOVERR | + SDMMC_STAR_IDMATE)) != 0U) { + ERROR("%s: Error flag (cmd = %u,status = %x)\n", __func__, + cmd->cmd_idx, status); + err = -EIO; + } + +err_exit: + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS); + + if ((err != 0) && ((status & SDMMC_STAR_DPSMACT) != 0U)) { + int ret_stop = stm32_sdmmc2_stop_transfer(); + + if (ret_stop != 0) { + return ret_stop; + } + } + + return err; +} + +static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd) +{ + uint8_t retry; + int err; + + assert(cmd != NULL); + + for (retry = 0U; retry < 3U; retry++) { + err = stm32_sdmmc2_send_cmd_req(cmd); + if (err == 0) { + return 0; + } + + if ((cmd->cmd_idx == MMC_CMD(1)) || + (cmd->cmd_idx == MMC_CMD(13))) { + return 0; /* Retry managed by framework */ + } + + /* Command 8 is expected to fail for eMMC */ + if (cmd->cmd_idx != MMC_CMD(8)) { + WARN(" CMD%u, Retry: %u, Error: %d\n", + cmd->cmd_idx, retry + 1U, err); + } + + udelay(10U); + } + + return err; +} + +static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width) +{ + uintptr_t base = sdmmc2_params.reg_base; + uint32_t bus_cfg = 0; + uint32_t clock_div, max_freq, freq; + uint32_t clk_rate = sdmmc2_params.clk_rate; + uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq; + + switch (width) { + case MMC_BUS_WIDTH_1: + break; + case MMC_BUS_WIDTH_4: + bus_cfg |= SDMMC_CLKCR_WIDBUS_4; + break; + case MMC_BUS_WIDTH_8: + bus_cfg |= SDMMC_CLKCR_WIDBUS_8; + break; + default: + panic(); + break; + } + + if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { + if (max_bus_freq >= 52000000U) { + max_freq = STM32MP_EMMC_HIGH_SPEED_MAX_FREQ; + } else { + max_freq = STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ; + } + } else { + if (max_bus_freq >= 50000000U) { + max_freq = STM32MP_SD_HIGH_SPEED_MAX_FREQ; + } else { + max_freq = STM32MP_SD_NORMAL_SPEED_MAX_FREQ; + } + } + + if (sdmmc2_params.max_freq != 0U) { + freq = MIN(sdmmc2_params.max_freq, max_freq); + } else { + freq = max_freq; + } + + clock_div = div_round_up(clk_rate, freq * 2U); + + mmio_write_32(base + SDMMC_CLKCR, + SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg | + sdmmc2_params.negedge | + sdmmc2_params.pin_ckin); + + return 0; +} + +static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size) +{ + struct mmc_cmd cmd; + int ret; + uintptr_t base = sdmmc2_params.reg_base; + uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR; + uint32_t arg_size; + + assert(size != 0U); + + if (size > MMC_BLOCK_SIZE) { + arg_size = MMC_BLOCK_SIZE; + } else { + arg_size = size; + } + + sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf); + + if (sdmmc2_params.use_dma) { + inv_dcache_range(buf, size); + } + + /* Prepare CMD 16*/ + mmio_write_32(base + SDMMC_DTIMER, 0); + + mmio_write_32(base + SDMMC_DLENR, 0); + + mmio_write_32(base + SDMMC_DCTRLR, 0); + + zeromem(&cmd, sizeof(struct mmc_cmd)); + + cmd.cmd_idx = MMC_CMD(16); + cmd.cmd_arg = arg_size; + cmd.resp_type = MMC_RESPONSE_R1; + + ret = stm32_sdmmc2_send_cmd(&cmd); + if (ret != 0) { + ERROR("CMD16 failed\n"); + return ret; + } + + /* Prepare data command */ + mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); + + mmio_write_32(base + SDMMC_DLENR, size); + + if (sdmmc2_params.use_dma) { + mmio_write_32(base + SDMMC_IDMACTRLR, + SDMMC_IDMACTRLR_IDMAEN); + mmio_write_32(base + SDMMC_IDMABASE0R, buf); + + flush_dcache_range(buf, size); + } + + data_ctrl |= __builtin_ctz(arg_size) << SDMMC_DCTRLR_DBLOCKSIZE_SHIFT; + + mmio_clrsetbits_32(base + SDMMC_DCTRLR, + SDMMC_DCTRLR_CLEAR_MASK, + data_ctrl); + + return 0; +} + +static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) +{ + uint32_t error_flags = SDMMC_STAR_RXOVERR | SDMMC_STAR_DCRCFAIL | + SDMMC_STAR_DTIMEOUT; + uint32_t flags = error_flags | SDMMC_STAR_DATAEND; + uint32_t status; + uint32_t *buffer; + uintptr_t base = sdmmc2_params.reg_base; + uintptr_t fifo_reg = base + SDMMC_FIFOR; + uint64_t timeout; + int ret; + + /* Assert buf is 4 bytes aligned */ + assert((buf & GENMASK(1, 0)) == 0U); + + buffer = (uint32_t *)buf; + + if (sdmmc2_params.use_dma) { + inv_dcache_range(buf, size); + + return 0; + } + + if (size <= MMC_BLOCK_SIZE) { + flags |= SDMMC_STAR_DBCKEND; + } + + timeout = timeout_init_us(TIMEOUT_US_1_S); + + do { + status = mmio_read_32(base + SDMMC_STAR); + + if ((status & error_flags) != 0U) { + ERROR("%s: Read error (status = %x)\n", __func__, + status); + mmio_write_32(base + SDMMC_DCTRLR, + SDMMC_DCTRLR_FIFORST); + + mmio_write_32(base + SDMMC_ICR, + SDMMC_STATIC_FLAGS); + + ret = stm32_sdmmc2_stop_transfer(); + if (ret != 0) { + return ret; + } + + return -EIO; + } + + if (timeout_elapsed(timeout)) { + ERROR("%s: timeout 1s (status = %x)\n", + __func__, status); + mmio_write_32(base + SDMMC_ICR, + SDMMC_STATIC_FLAGS); + + ret = stm32_sdmmc2_stop_transfer(); + if (ret != 0) { + return ret; + } + + return -ETIMEDOUT; + } + + if (size < (8U * sizeof(uint32_t))) { + if ((mmio_read_32(base + SDMMC_DCNTR) > 0U) && + ((status & SDMMC_STAR_RXFIFOE) == 0U)) { + *buffer = mmio_read_32(fifo_reg); + buffer++; + } + } else if ((status & SDMMC_STAR_RXFIFOHF) != 0U) { + uint32_t count; + + /* Read data from SDMMC Rx FIFO */ + for (count = 0; count < 8U; count++) { + *buffer = mmio_read_32(fifo_reg); + buffer++; + } + } + } while ((status & flags) == 0U); + + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + + if ((status & SDMMC_STAR_DPSMACT) != 0U) { + WARN("%s: DPSMACT=1, send stop\n", __func__); + return stm32_sdmmc2_stop_transfer(); + } + + return 0; +} + +static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size) +{ + return 0; +} + +static int stm32_sdmmc2_dt_get_config(void) +{ + int sdmmc_node; + void *fdt = NULL; + const fdt32_t *cuint; + struct dt_node_info dt_info; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + if (fdt == NULL) { + return -FDT_ERR_NOTFOUND; + } + + sdmmc_node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, + sdmmc2_params.reg_base); + if (sdmmc_node == -FDT_ERR_NOTFOUND) { + return -FDT_ERR_NOTFOUND; + } + + dt_fill_device_info(&dt_info, sdmmc_node); + if (dt_info.status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + if (dt_set_pinctrl_config(sdmmc_node) != 0) { + return -FDT_ERR_BADVALUE; + } + + sdmmc2_params.clock_id = dt_info.clock; + sdmmc2_params.reset_id = dt_info.reset; + + if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) { + sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0; + } + + if ((fdt_getprop(fdt, sdmmc_node, "st,sig-dir", NULL)) != NULL) { + sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL; + } + + if ((fdt_getprop(fdt, sdmmc_node, "st,neg-edge", NULL)) != NULL) { + sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE; + } + + cuint = fdt_getprop(fdt, sdmmc_node, "bus-width", NULL); + if (cuint != NULL) { + switch (fdt32_to_cpu(*cuint)) { + case 4: + sdmmc2_params.bus_width = MMC_BUS_WIDTH_4; + break; + + case 8: + sdmmc2_params.bus_width = MMC_BUS_WIDTH_8; + break; + + default: + break; + } + } + + cuint = fdt_getprop(fdt, sdmmc_node, "max-frequency", NULL); + if (cuint != NULL) { + sdmmc2_params.max_freq = fdt32_to_cpu(*cuint); + } + + sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc"); + + return 0; +} + +unsigned long long stm32_sdmmc2_mmc_get_device_size(void) +{ + return sdmmc2_params.device_info->device_size; +} + +int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) +{ + int rc; + + assert((params != NULL) && + ((params->reg_base & MMC_BLOCK_MASK) == 0U) && + ((params->bus_width == MMC_BUS_WIDTH_1) || + (params->bus_width == MMC_BUS_WIDTH_4) || + (params->bus_width == MMC_BUS_WIDTH_8))); + + memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params)); + + sdmmc2_params.vmmc_regu = NULL; + + if (stm32_sdmmc2_dt_get_config() != 0) { + ERROR("%s: DT error\n", __func__); + return -ENOMEM; + } + + clk_enable(sdmmc2_params.clock_id); + + rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS); + if (rc != 0) { + panic(); + } + udelay(2); + rc = stm32mp_reset_deassert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS); + if (rc != 0) { + panic(); + } + mdelay(1); + + sdmmc2_params.clk_rate = clk_get_rate(sdmmc2_params.clock_id); + sdmmc2_params.device_info->ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4; + + return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate, + sdmmc2_params.bus_width, sdmmc2_params.flags, + sdmmc2_params.device_info); +} diff --git a/arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c b/arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c new file mode 100644 index 0000000..5b43760 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PMIC_NODE_NOT_FOUND 1 + +static struct i2c_handle_s i2c_handle; +static uint32_t pmic_i2c_addr; + +static int register_pmic(void); + +static int dt_get_pmic_node(void *fdt) +{ + static int node = -FDT_ERR_BADOFFSET; + + if (node == -FDT_ERR_BADOFFSET) { + node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); + } + + return node; +} + +int dt_pmic_status(void) +{ + static int status = -FDT_ERR_BADVALUE; + int node; + void *fdt; + + if (status != -FDT_ERR_BADVALUE) { + return status; + } + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = dt_get_pmic_node(fdt); + if (node <= 0) { + status = -FDT_ERR_NOTFOUND; + + return status; + } + + status = (int)fdt_get_status(node); + + return status; +} + +static bool dt_pmic_is_secure(void) +{ + int status = dt_pmic_status(); + + return (status >= 0) && + (status == DT_SECURE) && + (i2c_handle.dt_status == DT_SECURE); +} + +/* + * Get PMIC and its I2C bus configuration from the device tree. + * Return 0 on success, negative on error, 1 if no PMIC node is defined. + */ +static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, + struct stm32_i2c_init_s *init) +{ + static int i2c_node = -FDT_ERR_NOTFOUND; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + if (i2c_node == -FDT_ERR_NOTFOUND) { + int pmic_node; + const fdt32_t *cuint; + + pmic_node = dt_get_pmic_node(fdt); + if (pmic_node < 0) { + return PMIC_NODE_NOT_FOUND; + } + + cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; + if (pmic_i2c_addr > UINT16_MAX) { + return -FDT_ERR_BADVALUE; + } + + i2c_node = fdt_parent_offset(fdt, pmic_node); + if (i2c_node < 0) { + return -FDT_ERR_NOTFOUND; + } + } + + dt_fill_device_info(i2c_info, i2c_node); + if (i2c_info->base == 0U) { + return -FDT_ERR_NOTFOUND; + } + + return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); +} + +bool initialize_pmic_i2c(void) +{ + int ret; + struct dt_node_info i2c_info; + struct i2c_handle_s *i2c = &i2c_handle; + struct stm32_i2c_init_s i2c_init; + + ret = dt_pmic_i2c_config(&i2c_info, &i2c_init); + if (ret < 0) { + ERROR("I2C configuration failed %d\n", ret); + panic(); + } + + if (ret != 0) { + return false; + } + + /* Initialize PMIC I2C */ + i2c->i2c_base_addr = i2c_info.base; + i2c->dt_status = i2c_info.status; + i2c->clock = i2c_info.clock; + i2c->i2c_state = I2C_STATE_RESET; + i2c_init.own_address1 = pmic_i2c_addr; + i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; + i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; + i2c_init.own_address2 = 0; + i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; + i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; + i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; + i2c_init.analog_filter = 1; + i2c_init.digital_filter_coef = 0; + + ret = stm32_i2c_init(i2c, &i2c_init); + if (ret != 0) { + ERROR("Cannot initialize I2C %x (%d)\n", + i2c->i2c_base_addr, ret); + panic(); + } + + if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1, + I2C_TIMEOUT_BUSY_MS)) { + ERROR("I2C device not ready\n"); + panic(); + } + + stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr); + + return true; +} + +static void register_pmic_shared_peripherals(void) +{ + uintptr_t i2c_base = i2c_handle.i2c_base_addr; + + if (dt_pmic_is_secure()) { + stm32mp_register_secure_periph_iomem(i2c_base); + } else { + if (i2c_base != 0U) { + stm32mp_register_non_secure_periph_iomem(i2c_base); + } + } +} + +void initialize_pmic(void) +{ + if (!initialize_pmic_i2c()) { + VERBOSE("No PMIC\n"); + return; + } + + register_pmic_shared_peripherals(); + + if (register_pmic() < 0) { + panic(); + } + + if (stpmic1_powerctrl_on() < 0) { + panic(); + } + +} + +#if DEBUG +void print_pmic_info_and_debug(void) +{ + unsigned long pmic_version; + + if (stpmic1_get_version(&pmic_version) != 0) { + ERROR("Failed to access PMIC\n"); + panic(); + } + + INFO("PMIC version = 0x%02lx\n", pmic_version); +} +#endif + +int pmic_ddr_power_init(enum ddr_type ddr_type) +{ + int status; + uint16_t buck3_min_mv; + struct rdev *buck2, *buck3, *vref; + struct rdev *ldo3 __unused; + + buck2 = regulator_get_by_name("buck2"); + if (buck2 == NULL) { + return -ENOENT; + } + +#if STM32MP15 + ldo3 = regulator_get_by_name("ldo3"); + if (ldo3 == NULL) { + return -ENOENT; + } +#endif + + vref = regulator_get_by_name("vref_ddr"); + if (vref == NULL) { + return -ENOENT; + } + + switch (ddr_type) { + case STM32MP_DDR3: +#if STM32MP15 + status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE); + if (status != 0) { + return status; + } +#endif + + status = regulator_set_min_voltage(buck2); + if (status != 0) { + return status; + } + + status = regulator_enable(buck2); + if (status != 0) { + return status; + } + + status = regulator_enable(vref); + if (status != 0) { + return status; + } + +#if STM32MP15 + status = regulator_enable(ldo3); + if (status != 0) { + return status; + } +#endif + break; + + case STM32MP_LPDDR2: + case STM32MP_LPDDR3: + /* + * Set LDO3 to 1.8V + * Set LDO3 to bypass mode if BUCK3 = 1.8V + * Set LDO3 to normal mode if BUCK3 != 1.8V + */ + buck3 = regulator_get_by_name("buck3"); + if (buck3 == NULL) { + return -ENOENT; + } + + regulator_get_range(buck3, &buck3_min_mv, NULL); + +#if STM32MP15 + if (buck3_min_mv != 1800) { + status = regulator_set_min_voltage(ldo3); + if (status != 0) { + return status; + } + } else { + status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS); + if (status != 0) { + return status; + } + } +#endif + + status = regulator_set_min_voltage(buck2); + if (status != 0) { + return status; + } + +#if STM32MP15 + status = regulator_enable(ldo3); + if (status != 0) { + return status; + } +#endif + + status = regulator_enable(buck2); + if (status != 0) { + return status; + } + + status = regulator_enable(vref); + if (status != 0) { + return status; + } + break; + + default: + break; + }; + + return 0; +} + +int pmic_voltages_init(void) +{ +#if STM32MP13 + struct rdev *buck1, *buck4; + int status; + + buck1 = regulator_get_by_name("buck1"); + if (buck1 == NULL) { + return -ENOENT; + } + + buck4 = regulator_get_by_name("buck4"); + if (buck4 == NULL) { + return -ENOENT; + } + + status = regulator_set_min_voltage(buck1); + if (status != 0) { + return status; + } + + status = regulator_set_min_voltage(buck4); + if (status != 0) { + return status; + } +#endif + + return 0; +} + +enum { + STPMIC1_BUCK1 = 0, + STPMIC1_BUCK2, + STPMIC1_BUCK3, + STPMIC1_BUCK4, + STPMIC1_LDO1, + STPMIC1_LDO2, + STPMIC1_LDO3, + STPMIC1_LDO4, + STPMIC1_LDO5, + STPMIC1_LDO6, + STPMIC1_VREF_DDR, + STPMIC1_BOOST, + STPMIC1_VBUS_OTG, + STPMIC1_SW_OUT, +}; + +static int pmic_set_state(const struct regul_description *desc, bool enable) +{ + VERBOSE("%s: set state to %d\n", desc->node_name, enable); + + if (enable == STATE_ENABLE) { + return stpmic1_regulator_enable(desc->node_name); + } else { + return stpmic1_regulator_disable(desc->node_name); + } +} + +static int pmic_get_state(const struct regul_description *desc) +{ + VERBOSE("%s: get state\n", desc->node_name); + + return stpmic1_is_regulator_enabled(desc->node_name); +} + +static int pmic_get_voltage(const struct regul_description *desc) +{ + VERBOSE("%s: get volt\n", desc->node_name); + + return stpmic1_regulator_voltage_get(desc->node_name); +} + +static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv) +{ + VERBOSE("%s: get volt\n", desc->node_name); + + return stpmic1_regulator_voltage_set(desc->node_name, mv); +} + +static int pmic_list_voltages(const struct regul_description *desc, + const uint16_t **levels, size_t *count) +{ + VERBOSE("%s: list volt\n", desc->node_name); + + return stpmic1_regulator_levels_mv(desc->node_name, levels, count); +} + +static int pmic_set_flag(const struct regul_description *desc, uint16_t flag) +{ + VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag); + + switch (flag) { + case REGUL_OCP: + return stpmic1_regulator_icc_set(desc->node_name); + + case REGUL_ACTIVE_DISCHARGE: + return stpmic1_active_discharge_mode_set(desc->node_name); + + case REGUL_PULL_DOWN: + return stpmic1_regulator_pull_down_set(desc->node_name); + + case REGUL_MASK_RESET: + return stpmic1_regulator_mask_reset_set(desc->node_name); + + case REGUL_SINK_SOURCE: + return stpmic1_regulator_sink_mode_set(desc->node_name); + + case REGUL_ENABLE_BYPASS: + return stpmic1_regulator_bypass_mode_set(desc->node_name); + + default: + return -EINVAL; + } +} + +static const struct regul_ops pmic_ops = { + .set_state = pmic_set_state, + .get_state = pmic_get_state, + .set_voltage = pmic_set_voltage, + .get_voltage = pmic_get_voltage, + .list_voltages = pmic_list_voltages, + .set_flag = pmic_set_flag, +}; + +#define DEFINE_REGU(name) { \ + .node_name = name, \ + .ops = &pmic_ops, \ + .driver_data = NULL, \ + .enable_ramp_delay = 1000, \ +} + +static const struct regul_description pmic_regs[] = { + [STPMIC1_BUCK1] = DEFINE_REGU("buck1"), + [STPMIC1_BUCK2] = DEFINE_REGU("buck2"), + [STPMIC1_BUCK3] = DEFINE_REGU("buck3"), + [STPMIC1_BUCK4] = DEFINE_REGU("buck4"), + [STPMIC1_LDO1] = DEFINE_REGU("ldo1"), + [STPMIC1_LDO2] = DEFINE_REGU("ldo2"), + [STPMIC1_LDO3] = DEFINE_REGU("ldo3"), + [STPMIC1_LDO4] = DEFINE_REGU("ldo4"), + [STPMIC1_LDO5] = DEFINE_REGU("ldo5"), + [STPMIC1_LDO6] = DEFINE_REGU("ldo6"), + [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"), + [STPMIC1_BOOST] = DEFINE_REGU("boost"), + [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"), + [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"), +}; + +#define NB_REG ARRAY_SIZE(pmic_regs) + +static int register_pmic(void) +{ + void *fdt; + int pmic_node, regulators_node, subnode; + + VERBOSE("Register pmic\n"); + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + pmic_node = dt_get_pmic_node(fdt); + if (pmic_node < 0) { + return pmic_node; + } + + regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); + if (regulators_node < 0) { + return -ENOENT; + } + + fdt_for_each_subnode(subnode, fdt, regulators_node) { + const char *reg_name = fdt_get_name(fdt, subnode, NULL); + const struct regul_description *desc; + unsigned int i; + int ret; + + for (i = 0; i < NB_REG; i++) { + desc = &pmic_regs[i]; + if (strcmp(desc->node_name, reg_name) == 0) { + break; + } + } + assert(i < NB_REG); + + ret = regulator_register(desc, subnode); + if (ret != 0) { + WARN("%s:%d failed to register %s\n", __func__, + __LINE__, reg_name); + return ret; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/pmic/stpmic1.c b/arm-trusted-firmware/drivers/st/pmic/stpmic1.c new file mode 100644 index 0000000..37eb50b --- /dev/null +++ b/arm-trusted-firmware/drivers/st/pmic/stpmic1.c @@ -0,0 +1,937 @@ +/* + * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#define I2C_TIMEOUT_MS 25 + +struct regul_struct { + const char *dt_node_name; + const uint16_t *voltage_table; + uint8_t voltage_table_size; + uint8_t control_reg; + uint8_t enable_mask; + uint8_t low_power_reg; + uint8_t pull_down_reg; + uint8_t pull_down; + uint8_t mask_reset_reg; + uint8_t mask_reset; + uint8_t icc_reg; + uint8_t icc_mask; +}; + +static struct i2c_handle_s *pmic_i2c_handle; +static uint16_t pmic_i2c_addr; +/* + * Special mode corresponds to LDO3 in sink source mode or in bypass mode. + * LDO3 doesn't switch back from special to normal mode. + */ +static bool ldo3_special_mode; + +/* Voltage tables in mV */ +static const uint16_t buck1_voltage_table[] = { + 725, + 725, + 725, + 725, + 725, + 725, + 750, + 775, + 800, + 825, + 850, + 875, + 900, + 925, + 950, + 975, + 1000, + 1025, + 1050, + 1075, + 1100, + 1125, + 1150, + 1175, + 1200, + 1225, + 1250, + 1275, + 1300, + 1325, + 1350, + 1375, + 1400, + 1425, + 1450, + 1475, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, +}; + +static const uint16_t buck2_voltage_table[] = { + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1050, + 1050, + 1100, + 1100, + 1150, + 1150, + 1200, + 1200, + 1250, + 1250, + 1300, + 1300, + 1350, + 1350, + 1400, + 1400, + 1450, + 1450, + 1500, +}; + +static const uint16_t buck3_voltage_table[] = { + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1100, + 1100, + 1100, + 1100, + 1200, + 1200, + 1200, + 1200, + 1300, + 1300, + 1300, + 1300, + 1400, + 1400, + 1400, + 1400, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, +}; + +static const uint16_t buck4_voltage_table[] = { + 600, + 625, + 650, + 675, + 700, + 725, + 750, + 775, + 800, + 825, + 850, + 875, + 900, + 925, + 950, + 975, + 1000, + 1025, + 1050, + 1075, + 1100, + 1125, + 1150, + 1175, + 1200, + 1225, + 1250, + 1275, + 1300, + 1300, + 1350, + 1350, + 1400, + 1400, + 1450, + 1450, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, + 3500, + 3600, + 3700, + 3800, + 3900, +}; + +static const uint16_t ldo1_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo2_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo3_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3300, + 3300, + 3300, + 3300, + 3300, + 3300, +}; + +/* Special mode table is used for sink source OR bypass mode */ +static const uint16_t ldo3_special_mode_table[] = { + 0, +}; + +static const uint16_t ldo5_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, + 3500, + 3600, + 3700, + 3800, + 3900, +}; + +static const uint16_t ldo6_voltage_table[] = { + 900, + 1000, + 1100, + 1200, + 1300, + 1400, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo4_voltage_table[] = { + 3300, +}; + +static const uint16_t vref_ddr_voltage_table[] = { + 3300, +}; + +static const uint16_t fixed_5v_voltage_table[] = { + 5000, +}; + +/* Table of Regulators in PMIC SoC */ +static const struct regul_struct regulators_table[] = { + { + .dt_node_name = "buck1", + .voltage_table = buck1_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), + .control_reg = BUCK1_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = BUCK1_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK1_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK1_MASK_RESET, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BUCK1_ICC_SHIFT, + }, + { + .dt_node_name = "buck2", + .voltage_table = buck2_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), + .control_reg = BUCK2_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = BUCK2_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK2_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK2_MASK_RESET, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BUCK2_ICC_SHIFT, + }, + { + .dt_node_name = "buck3", + .voltage_table = buck3_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), + .control_reg = BUCK3_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = BUCK3_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK3_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK3_MASK_RESET, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BUCK3_ICC_SHIFT, + }, + { + .dt_node_name = "buck4", + .voltage_table = buck4_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), + .control_reg = BUCK4_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = BUCK4_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK4_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK4_MASK_RESET, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BUCK4_ICC_SHIFT, + }, + { + .dt_node_name = "ldo1", + .voltage_table = ldo1_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), + .control_reg = LDO1_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO1_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO1_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO1_ICC_SHIFT, + }, + { + .dt_node_name = "ldo2", + .voltage_table = ldo2_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), + .control_reg = LDO2_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO2_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO2_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO2_ICC_SHIFT, + }, + { + .dt_node_name = "ldo3", + .voltage_table = ldo3_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), + .control_reg = LDO3_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO3_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO3_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO3_ICC_SHIFT, + }, + { + .dt_node_name = "ldo4", + .voltage_table = ldo4_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), + .control_reg = LDO4_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO4_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO4_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO4_ICC_SHIFT, + }, + { + .dt_node_name = "ldo5", + .voltage_table = ldo5_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), + .control_reg = LDO5_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO5_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO5_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO5_ICC_SHIFT, + }, + { + .dt_node_name = "ldo6", + .voltage_table = ldo6_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), + .control_reg = LDO6_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO6_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO6_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO6_ICC_SHIFT, + }, + { + .dt_node_name = "vref_ddr", + .voltage_table = vref_ddr_voltage_table, + .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), + .control_reg = VREF_DDR_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = VREF_DDR_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = VREF_DDR_MASK_RESET, + }, + { + .dt_node_name = "boost", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_mask = BOOST_ENABLED, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BOOST_ICC_SHIFT, + }, + { + .dt_node_name = "pwr_sw1", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_mask = USBSW_OTG_SWITCH_ENABLED, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = PWR_SW1_ICC_SHIFT, + }, + { + .dt_node_name = "pwr_sw2", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_mask = SWIN_SWOUT_ENABLED, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = PWR_SW2_ICC_SHIFT, + }, +}; + +#define MAX_REGUL ARRAY_SIZE(regulators_table) + +static const struct regul_struct *get_regulator_data(const char *name) +{ + uint8_t i; + + for (i = 0 ; i < MAX_REGUL ; i++) { + if (strncmp(name, regulators_table[i].dt_node_name, + strlen(regulators_table[i].dt_node_name)) == 0) { + return ®ulators_table[i]; + } + } + + /* Regulator not found */ + panic(); + return NULL; +} + +static uint8_t voltage_to_index(const char *name, uint16_t millivolts) +{ + const struct regul_struct *regul = get_regulator_data(name); + uint8_t i; + + for (i = 0 ; i < regul->voltage_table_size ; i++) { + if (regul->voltage_table[i] == millivolts) { + return i; + } + } + + /* Voltage not found */ + panic(); + + return 0; +} + +int stpmic1_powerctrl_on(void) +{ + return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID, + PWRCTRL_PIN_VALID); +} + +int stpmic1_switch_off(void) +{ + return stpmic1_register_update(MAIN_CONTROL_REG, 1, + SOFTWARE_SWITCH_OFF_ENABLED); +} + +int stpmic1_regulator_enable(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + return stpmic1_register_update(regul->control_reg, regul->enable_mask, + regul->enable_mask); +} + +int stpmic1_regulator_disable(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + return stpmic1_register_update(regul->control_reg, 0, + regul->enable_mask); +} + +bool stpmic1_is_regulator_enabled(const char *name) +{ + uint8_t val; + const struct regul_struct *regul = get_regulator_data(name); + + if (stpmic1_register_read(regul->control_reg, &val) != 0) { + panic(); + } + + return (val & regul->enable_mask) == regul->enable_mask; +} + +int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) +{ + uint8_t voltage_index = voltage_to_index(name, millivolts); + const struct regul_struct *regul = get_regulator_data(name); + uint8_t mask; + + if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) { + /* + * when the LDO3 is in special mode, we do not change voltage, + * because by setting voltage, the LDO would leaves sink-source + * mode. There is obviously no reason to leave sink-source mode + * at runtime. + */ + return 0; + } + + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { + mask = BUCK_VOLTAGE_MASK; + } else if ((strncmp(name, "ldo", 3) == 0) && + (strncmp(name, "ldo4", 5) != 0)) { + mask = LDO_VOLTAGE_MASK; + } else { + return 0; + } + + return stpmic1_register_update(regul->control_reg, + voltage_index << LDO_BUCK_VOLTAGE_SHIFT, + mask); +} + +int stpmic1_regulator_pull_down_set(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (regul->pull_down_reg != 0) { + return stpmic1_register_update(regul->pull_down_reg, + BIT(regul->pull_down), + LDO_BUCK_PULL_DOWN_MASK << + regul->pull_down); + } + + return 0; +} + +int stpmic1_regulator_mask_reset_set(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (regul->mask_reset_reg == 0U) { + return -EPERM; + } + + return stpmic1_register_update(regul->mask_reset_reg, + BIT(regul->mask_reset), + LDO_BUCK_RESET_MASK << + regul->mask_reset); +} + +int stpmic1_regulator_icc_set(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (regul->mask_reset_reg == 0U) { + return -EPERM; + } + + return stpmic1_register_update(regul->icc_reg, + BIT(regul->icc_mask), + BIT(regul->icc_mask)); +} + +int stpmic1_regulator_sink_mode_set(const char *name) +{ + if (strncmp(name, "ldo3", 5) != 0) { + return -EPERM; + } + + ldo3_special_mode = true; + + /* disable bypass mode, enable sink mode */ + return stpmic1_register_update(LDO3_CONTROL_REG, + LDO3_DDR_SEL << LDO_BUCK_VOLTAGE_SHIFT, + LDO3_BYPASS | LDO_VOLTAGE_MASK); +} + +int stpmic1_regulator_bypass_mode_set(const char *name) +{ + if (strncmp(name, "ldo3", 5) != 0) { + return -EPERM; + } + + ldo3_special_mode = true; + + /* enable bypass mode, disable sink mode */ + return stpmic1_register_update(LDO3_CONTROL_REG, + LDO3_BYPASS, + LDO3_BYPASS | LDO_VOLTAGE_MASK); +} + +int stpmic1_active_discharge_mode_set(const char *name) +{ + if (strncmp(name, "pwr_sw1", 8) == 0) { + return stpmic1_register_update(USB_CONTROL_REG, + VBUS_OTG_DISCHARGE, + VBUS_OTG_DISCHARGE); + } + + if (strncmp(name, "pwr_sw2", 8) == 0) { + return stpmic1_register_update(USB_CONTROL_REG, + SW_OUT_DISCHARGE, + SW_OUT_DISCHARGE); + } + + return -EPERM; +} + +int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, + size_t *levels_count) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) { + *levels_count = ARRAY_SIZE(ldo3_special_mode_table); + *levels = ldo3_special_mode_table; + } else { + *levels_count = regul->voltage_table_size; + *levels = regul->voltage_table; + } + + return 0; +} + +int stpmic1_regulator_voltage_get(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + uint8_t value; + uint8_t mask; + int status; + + if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) { + return 0; + } + + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { + mask = BUCK_VOLTAGE_MASK; + } else if ((strncmp(name, "ldo", 3) == 0) && + (strncmp(name, "ldo4", 5) != 0)) { + mask = LDO_VOLTAGE_MASK; + } else { + return 0; + } + + status = stpmic1_register_read(regul->control_reg, &value); + if (status < 0) { + return status; + } + + value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; + + if (value > regul->voltage_table_size) { + return -ERANGE; + } + + return (int)regul->voltage_table[value]; +} + +int stpmic1_register_read(uint8_t register_id, uint8_t *value) +{ + return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr, + (uint16_t)register_id, + I2C_MEMADD_SIZE_8BIT, value, + 1, I2C_TIMEOUT_MS); +} + +int stpmic1_register_write(uint8_t register_id, uint8_t value) +{ + int status; + + status = stm32_i2c_mem_write(pmic_i2c_handle, pmic_i2c_addr, + (uint16_t)register_id, + I2C_MEMADD_SIZE_8BIT, &value, + 1, I2C_TIMEOUT_MS); + +#if ENABLE_ASSERTIONS + if (status != 0) { + return status; + } + + if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) { + uint8_t readval; + + status = stpmic1_register_read(register_id, &readval); + if (status != 0) { + return status; + } + + if (readval != value) { + return -EIO; + } + } +#endif + + return status; +} + +int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) +{ + int status; + uint8_t val; + + status = stpmic1_register_read(register_id, &val); + if (status != 0) { + return status; + } + + val = (val & ~mask) | (value & mask); + + return stpmic1_register_write(register_id, val); +} + +void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) +{ + pmic_i2c_handle = i2c_handle; + pmic_i2c_addr = i2c_addr; +} + +void stpmic1_dump_regulators(void) +{ + uint32_t i; + + for (i = 0U; i < MAX_REGUL; i++) { + const char *name __unused = regulators_table[i].dt_node_name; + + VERBOSE("PMIC regul %s: %sable, %dmV", + name, + stpmic1_is_regulator_enabled(name) ? "en" : "dis", + stpmic1_regulator_voltage_get(name)); + } +} + +int stpmic1_get_version(unsigned long *version) +{ + uint8_t read_val; + int status; + + status = stpmic1_register_read(VERSION_STATUS_REG, &read_val); + if (status < 0) { + return status; + } + + *version = (unsigned long)read_val; + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/regulator/regulator_core.c b/arm-trusted-firmware/drivers/st/regulator/regulator_core.c new file mode 100644 index 0000000..5cc8329 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/regulator/regulator_core.c @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define MAX_PROPERTY_LEN 64 + +static struct rdev rdev_array[PLAT_NB_RDEVS]; + +#define for_each_rdev(rdev) \ + for (rdev = rdev_array; rdev < (rdev_array + PLAT_NB_RDEVS); rdev++) + +#define for_each_registered_rdev(rdev) \ + for (rdev = rdev_array; \ + (rdev < (rdev_array + PLAT_NB_RDEVS)) && (rdev->desc != NULL); rdev++) + +static void lock_driver(const struct rdev *rdev) +{ + if (rdev->desc->ops->lock != NULL) { + rdev->desc->ops->lock(rdev->desc); + } +} + +static void unlock_driver(const struct rdev *rdev) +{ + if (rdev->desc->ops->unlock != NULL) { + rdev->desc->ops->unlock(rdev->desc); + } +} + +static struct rdev *regulator_get_by_phandle(int32_t phandle) +{ + struct rdev *rdev; + + for_each_registered_rdev(rdev) { + if (rdev->phandle == phandle) { + return rdev; + } + } + + WARN("%s: phandle %d not found\n", __func__, phandle); + return NULL; +} + +/* + * Get a regulator from its node name + * + * @fdt - pointer to device tree memory + * @node_name - name of the node "ldo1" + * Return pointer to rdev if succeed, NULL else. + */ +struct rdev *regulator_get_by_name(const char *node_name) +{ + struct rdev *rdev; + + assert(node_name != NULL); + VERBOSE("get %s\n", node_name); + + for_each_registered_rdev(rdev) { + if (strcmp(rdev->desc->node_name, node_name) == 0) { + return rdev; + } + } + + WARN("%s: %s not found\n", __func__, node_name); + return NULL; +} + +static int32_t get_supply_phandle(const void *fdt, int node, const char *name) +{ + const fdt32_t *cuint; + int len __unused; + int supply_phandle = -FDT_ERR_NOTFOUND; + char prop_name[MAX_PROPERTY_LEN]; + + len = snprintf(prop_name, MAX_PROPERTY_LEN - 1, "%s-supply", name); + assert((len >= 0) && (len < MAX_PROPERTY_LEN - 1)); + + cuint = fdt_getprop(fdt, node, prop_name, NULL); + if (cuint != NULL) { + supply_phandle = fdt32_to_cpu(*cuint); + VERBOSE("%s: supplied by %d\n", name, supply_phandle); + } + + return supply_phandle; +} + +/* + * Get a regulator from a supply name + * + * @fdt - pointer to device tree memory + * @node - offset of the node that contains the supply description + * @name - name of the supply "vdd" for "vdd-supply' + * Return pointer to rdev if succeed, NULL else. + */ +struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name) +{ + const int p = get_supply_phandle(fdt, node, name); + + if (p < 0) { + return NULL; + } + + return regulator_get_by_phandle(p); +} + +static int __regulator_set_state(struct rdev *rdev, bool state) +{ + if (rdev->desc->ops->set_state == NULL) { + return -ENODEV; + } + + return rdev->desc->ops->set_state(rdev->desc, state); +} + +/* + * Enable regulator + * + * @rdev - pointer to rdev struct + * Return 0 if succeed, non 0 else. + */ +int regulator_enable(struct rdev *rdev) +{ + int ret; + + assert(rdev != NULL); + + ret = __regulator_set_state(rdev, STATE_ENABLE); + + udelay(rdev->enable_ramp_delay); + + return ret; +} + +/* + * Disable regulator + * + * @rdev - pointer to rdev struct + * Return 0 if succeed, non 0 else. + */ +int regulator_disable(struct rdev *rdev) +{ + int ret; + + assert(rdev != NULL); + + if (rdev->flags & REGUL_ALWAYS_ON) { + return 0; + } + + ret = __regulator_set_state(rdev, STATE_DISABLE); + + udelay(rdev->enable_ramp_delay); + + return ret; +} + +/* + * Regulator enabled query + * + * @rdev - pointer to rdev struct + * Return 0 if disabled, 1 if enabled, <0 else. + */ +int regulator_is_enabled(const struct rdev *rdev) +{ + int ret; + + assert(rdev != NULL); + + VERBOSE("%s: is en\n", rdev->desc->node_name); + + if (rdev->desc->ops->get_state == NULL) { + return -ENODEV; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->get_state(rdev->desc); + if (ret < 0) { + ERROR("regul %s get state failed: err:%d\n", + rdev->desc->node_name, ret); + } + + unlock_driver(rdev); + + return ret; +} + +/* + * Set regulator voltage + * + * @rdev - pointer to rdev struct + * @mvolt - Target voltage level in millivolt + * Return 0 if succeed, non 0 else. + */ +int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt) +{ + int ret; + + assert(rdev != NULL); + + VERBOSE("%s: set mvolt\n", rdev->desc->node_name); + + if (rdev->desc->ops->set_voltage == NULL) { + return -ENODEV; + } + + if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) { + return -EPERM; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt); + if (ret < 0) { + ERROR("regul %s set volt failed: err:%d\n", + rdev->desc->node_name, ret); + } + + unlock_driver(rdev); + + return ret; +} + +/* + * Set regulator min voltage + * + * @rdev - pointer to rdev struct + * Return 0 if succeed, non 0 else. + */ +int regulator_set_min_voltage(struct rdev *rdev) +{ + return regulator_set_voltage(rdev, rdev->min_mv); +} + +/* + * Get regulator voltage + * + * @rdev - pointer to rdev struct + * Return milli volts if succeed, <0 else. + */ +int regulator_get_voltage(const struct rdev *rdev) +{ + int ret; + + assert(rdev != NULL); + + VERBOSE("%s: get volt\n", rdev->desc->node_name); + + if (rdev->desc->ops->get_voltage == NULL) { + return rdev->min_mv; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->get_voltage(rdev->desc); + if (ret < 0) { + ERROR("regul %s get voltage failed: err:%d\n", + rdev->desc->node_name, ret); + } + + unlock_driver(rdev); + + return ret; +} + +/* + * List regulator voltages + * + * @rdev - pointer to rdev struct + * @levels - out: array of supported millitvolt levels from min to max value + * @count - out: number of possible millivolt values + * Return 0 if succeed, non 0 else. + */ +int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count) +{ + int ret; + size_t n; + + assert(rdev != NULL); + assert(levels != NULL); + assert(count != NULL); + + VERBOSE("%s: list volt\n", rdev->desc->node_name); + + if (rdev->desc->ops->list_voltages == NULL) { + return -ENODEV; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count); + + unlock_driver(rdev); + + if (ret < 0) { + ERROR("regul %s list_voltages failed: err: %d\n", + rdev->desc->node_name, ret); + return ret; + } + + /* + * Reduce the possible values depending on min and max from device-tree + */ + n = *count; + while ((n > 1U) && ((*levels)[n - 1U] > rdev->max_mv)) { + n--; + } + + /* Verify that max val is a valid value */ + if (rdev->max_mv != (*levels)[n - 1]) { + ERROR("regul %s: max value %u is invalid\n", + rdev->desc->node_name, rdev->max_mv); + return -EINVAL; + } + + while ((n > 1U) && ((*levels[0U]) < rdev->min_mv)) { + (*levels)++; + n--; + } + + /* Verify that min is not too high */ + if (n == 0U) { + ERROR("regul %s set min voltage is too high\n", + rdev->desc->node_name); + return -EINVAL; + } + + /* Verify that min val is a valid vlue */ + if (rdev->min_mv != (*levels)[0U]) { + ERROR("regul %s: min value %u is invalid\n", + rdev->desc->node_name, rdev->min_mv); + return -EINVAL; + } + + *count = n; + + VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv); + + return 0; +} + +/* + * Get regulator voltages range + * + * @rdev - pointer to rdev struct + * @min_mv - out: min possible millivolt value + * @max_mv - out: max possible millivolt value + * Return 0 if succeed, non 0 else. + */ +void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv) +{ + assert(rdev != NULL); + + if (min_mv != NULL) { + *min_mv = rdev->min_mv; + } + if (max_mv != NULL) { + *max_mv = rdev->max_mv; + } +} + +/* + * Set regulator flag + * + * @rdev - pointer to rdev struct + * @flag - flag value to set (eg: REGUL_OCP) + * Return 0 if succeed, non 0 else. + */ +int regulator_set_flag(struct rdev *rdev, uint16_t flag) +{ + int ret; + + /* check that only one bit is set on flag */ + if (__builtin_popcount(flag) != 1) { + return -EINVAL; + } + + /* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */ + if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) { + rdev->flags |= flag; + return 0; + } + + if (rdev->desc->ops->set_flag == NULL) { + ERROR("%s can not set any flag\n", rdev->desc->node_name); + return -ENODEV; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->set_flag(rdev->desc, flag); + + unlock_driver(rdev); + + if (ret != 0) { + ERROR("%s: could not set flag %d ret=%d\n", + rdev->desc->node_name, flag, ret); + return ret; + } + + rdev->flags |= flag; + + return 0; +} + +static int parse_properties(const void *fdt, struct rdev *rdev, int node) +{ + int ret; + + if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) { + VERBOSE("%s: set regulator-always-on\n", rdev->desc->node_name); + ret = regulator_set_flag(rdev, REGUL_ALWAYS_ON); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +/* + * Parse the device-tree for a regulator + * + * Read min/max voltage from dt and check its validity + * Read the properties, and call the driver to set flags + * Read power supply phandle + * Read and store low power mode states + * + * @rdev - pointer to rdev struct + * @node - device-tree node offset of the regulator + * Return 0 if disabled, 1 if enabled, <0 else. + */ +static int parse_dt(struct rdev *rdev, int node) +{ + void *fdt; + const fdt32_t *cuint; + const uint16_t *levels; + size_t size; + int ret; + + VERBOSE("%s: parse dt\n", rdev->desc->node_name); + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + rdev->phandle = fdt_get_phandle(fdt, node); + + cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); + if (cuint != NULL) { + uint16_t min_mv; + + min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); + VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv); + if (min_mv <= rdev->max_mv) { + rdev->min_mv = min_mv; + } else { + ERROR("%s: min_mv=%d is too high\n", + rdev->desc->node_name, (int)min_mv); + return -EINVAL; + } + } + + cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); + if (cuint != NULL) { + uint16_t max_mv; + + max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); + VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv); + if (max_mv >= rdev->min_mv) { + rdev->max_mv = max_mv; + } else { + ERROR("%s: max_mv=%d is too low\n", + rdev->desc->node_name, (int)max_mv); + return -EINVAL; + } + } + + /* validate that min and max values can be used */ + ret = regulator_list_voltages(rdev, &levels, &size); + if ((ret != 0) && (ret != -ENODEV)) { + return ret; + } + + ret = parse_properties(fdt, rdev, node); + if (ret != 0) { + return ret; + } + + return 0; +} + +/* + * Register a regulator driver in regulator framework. + * Initialize voltage range from driver description + * + * @desc - pointer to the regulator description + * @node - device-tree node offset of the regulator + * Return 0 if succeed, non 0 else. + */ +int regulator_register(const struct regul_description *desc, int node) +{ + struct rdev *rdev; + + assert(desc != NULL); + + VERBOSE("register %s\n", desc->node_name); + + for_each_rdev(rdev) { + if (rdev->desc == NULL) { + break; + } + } + + if (rdev == rdev_array + PLAT_NB_RDEVS) { + WARN("Not enough place for regulators, PLAT_NB_RDEVS should be increased.\n"); + return -ENOMEM; + } + + rdev->desc = desc; + rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay; + + if (rdev->desc->ops->list_voltages != NULL) { + int ret; + const uint16_t *levels; + size_t count; + + lock_driver(rdev); + + ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count); + + unlock_driver(rdev); + + if (ret < 0) { + ERROR("regul %s set state failed: err:%d\n", + rdev->desc->node_name, ret); + return ret; + } + + rdev->min_mv = levels[0]; + rdev->max_mv = levels[count - 1U]; + } else { + rdev->max_mv = UINT16_MAX; + } + + return parse_dt(rdev, node); +} diff --git a/arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c b/arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c new file mode 100644 index 0000000..f1c224e --- /dev/null +++ b/arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#ifndef PLAT_NB_FIXED_REGS +#error "Missing PLAT_NB_FIXED_REGS" +#endif + +#define FIXED_NAME_LEN 32 + +struct fixed_data { + char name[FIXED_NAME_LEN]; + uint16_t volt; + struct regul_description desc; +}; + +static struct fixed_data data[PLAT_NB_FIXED_REGS]; + +static int fixed_set_state(const struct regul_description *desc, bool state) +{ + return 0; +} + +static int fixed_get_state(const struct regul_description *desc) +{ + return 1; +} + +static struct regul_ops fixed_ops = { + .set_state = fixed_set_state, + .get_state = fixed_get_state, +}; + +int fixed_regulator_register(void) +{ + uint32_t count = 0; + void *fdt; + int node; + + VERBOSE("fixed reg init!\n"); + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_compatible_node(fdt, node, "regulator-fixed") { + int len __unused; + int ret; + struct fixed_data *d = &data[count]; + const char *reg_name; + + reg_name = fdt_get_name(fdt, node, NULL); + + VERBOSE("register fixed reg %s!\n", reg_name); + + len = snprintf(d->name, FIXED_NAME_LEN - 1, "%s", reg_name); + assert((len > 0) && (len < (FIXED_NAME_LEN - 1))); + + d->desc.node_name = d->name; + d->desc.driver_data = d; + d->desc.ops = &fixed_ops; + + ret = regulator_register(&d->desc, node); + if (ret != 0) { + WARN("%s:%d failed to register %s\n", __func__, + __LINE__, reg_name); + return ret; + } + + count++; + assert(count <= PLAT_NB_FIXED_REGS); + + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c b/arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c new file mode 100644 index 0000000..98c8dcf --- /dev/null +++ b/arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +static uint32_t id2reg_offset(unsigned int reset_id) +{ + return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t); +} + +static uint8_t id2reg_bit_pos(unsigned int reset_id) +{ + return (uint8_t)(reset_id & GENMASK(4, 0)); +} + +int stm32mp_reset_assert(uint32_t id, unsigned int to_us) +{ + uint32_t offset = id2reg_offset(id); + uint32_t bitmsk = BIT(id2reg_bit_pos(id)); + uintptr_t rcc_base = stm32mp_rcc_base(); + + mmio_write_32(rcc_base + offset, bitmsk); + + if (to_us != 0U) { + uint64_t timeout_ref = timeout_init_us(to_us); + + while ((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) { + if (timeout_elapsed(timeout_ref)) { + return -ETIMEDOUT; + } + } + } + + return 0; +} + +int stm32mp_reset_deassert(uint32_t id, unsigned int to_us) +{ + uint32_t offset = id2reg_offset(id) + RCC_RSTCLRR_OFFSET; + uint32_t bitmsk = BIT(id2reg_bit_pos(id)); + uintptr_t rcc_base = stm32mp_rcc_base(); + + mmio_write_32(rcc_base + offset, bitmsk); + + if (to_us != 0U) { + uint64_t timeout_ref = timeout_init_us(to_us); + + while ((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) { + if (timeout_elapsed(timeout_ref)) { + return -ETIMEDOUT; + } + } + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/spi/stm32_qspi.c b/arm-trusted-firmware/drivers/st/spi/stm32_qspi.c new file mode 100644 index 0000000..d3c26d9 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/spi/stm32_qspi.c @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Timeout for device interface reset */ +#define TIMEOUT_US_1_MS 1000U + +/* QUADSPI registers */ +#define QSPI_CR 0x00U +#define QSPI_DCR 0x04U +#define QSPI_SR 0x08U +#define QSPI_FCR 0x0CU +#define QSPI_DLR 0x10U +#define QSPI_CCR 0x14U +#define QSPI_AR 0x18U +#define QSPI_ABR 0x1CU +#define QSPI_DR 0x20U +#define QSPI_PSMKR 0x24U +#define QSPI_PSMAR 0x28U +#define QSPI_PIR 0x2CU +#define QSPI_LPTR 0x30U + +/* QUADSPI control register */ +#define QSPI_CR_EN BIT(0) +#define QSPI_CR_ABORT BIT(1) +#define QSPI_CR_DMAEN BIT(2) +#define QSPI_CR_TCEN BIT(3) +#define QSPI_CR_SSHIFT BIT(4) +#define QSPI_CR_DFM BIT(6) +#define QSPI_CR_FSEL BIT(7) +#define QSPI_CR_FTHRES_SHIFT 8U +#define QSPI_CR_TEIE BIT(16) +#define QSPI_CR_TCIE BIT(17) +#define QSPI_CR_FTIE BIT(18) +#define QSPI_CR_SMIE BIT(19) +#define QSPI_CR_TOIE BIT(20) +#define QSPI_CR_APMS BIT(22) +#define QSPI_CR_PMM BIT(23) +#define QSPI_CR_PRESCALER_MASK GENMASK_32(31, 24) +#define QSPI_CR_PRESCALER_SHIFT 24U + +/* QUADSPI device configuration register */ +#define QSPI_DCR_CKMODE BIT(0) +#define QSPI_DCR_CSHT_MASK GENMASK_32(10, 8) +#define QSPI_DCR_CSHT_SHIFT 8U +#define QSPI_DCR_FSIZE_MASK GENMASK_32(20, 16) +#define QSPI_DCR_FSIZE_SHIFT 16U + +/* QUADSPI status register */ +#define QSPI_SR_TEF BIT(0) +#define QSPI_SR_TCF BIT(1) +#define QSPI_SR_FTF BIT(2) +#define QSPI_SR_SMF BIT(3) +#define QSPI_SR_TOF BIT(4) +#define QSPI_SR_BUSY BIT(5) + +/* QUADSPI flag clear register */ +#define QSPI_FCR_CTEF BIT(0) +#define QSPI_FCR_CTCF BIT(1) +#define QSPI_FCR_CSMF BIT(3) +#define QSPI_FCR_CTOF BIT(4) + +/* QUADSPI communication configuration register */ +#define QSPI_CCR_DDRM BIT(31) +#define QSPI_CCR_DHHC BIT(30) +#define QSPI_CCR_SIOO BIT(28) +#define QSPI_CCR_FMODE_SHIFT 26U +#define QSPI_CCR_DMODE_SHIFT 24U +#define QSPI_CCR_DCYC_SHIFT 18U +#define QSPI_CCR_ABSIZE_SHIFT 16U +#define QSPI_CCR_ABMODE_SHIFT 14U +#define QSPI_CCR_ADSIZE_SHIFT 12U +#define QSPI_CCR_ADMODE_SHIFT 10U +#define QSPI_CCR_IMODE_SHIFT 8U +#define QSPI_CCR_IND_WRITE 0U +#define QSPI_CCR_IND_READ 1U +#define QSPI_CCR_MEM_MAP 3U + +#define QSPI_MAX_CHIP 2U + +#define QSPI_FIFO_TIMEOUT_US 30U +#define QSPI_CMD_TIMEOUT_US 1000U +#define QSPI_BUSY_TIMEOUT_US 100U +#define QSPI_ABT_TIMEOUT_US 100U + +#define DT_QSPI_COMPAT "st,stm32f469-qspi" + +#define FREQ_100MHZ 100000000U + +struct stm32_qspi_ctrl { + uintptr_t reg_base; + uintptr_t mm_base; + size_t mm_size; + unsigned long clock_id; + unsigned int reset_id; +}; + +static struct stm32_qspi_ctrl stm32_qspi; + +static uintptr_t qspi_base(void) +{ + return stm32_qspi.reg_base; +} + +static int stm32_qspi_wait_for_not_busy(void) +{ + uint64_t timeout = timeout_init_us(QSPI_BUSY_TIMEOUT_US); + + while ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_BUSY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: busy timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int stm32_qspi_wait_cmd(const struct spi_mem_op *op) +{ + int ret = 0; + uint64_t timeout; + + if (op->data.nbytes == 0U) { + return stm32_qspi_wait_for_not_busy(); + } + + timeout = timeout_init_us(QSPI_CMD_TIMEOUT_US); + while ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_TCF) == 0U) { + if (timeout_elapsed(timeout)) { + ret = -ETIMEDOUT; + break; + } + } + + if (ret == 0) { + if ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_TEF) != 0U) { + ERROR("%s: transfer error\n", __func__); + ret = -EIO; + } + } else { + ERROR("%s: cmd timeout\n", __func__); + } + + /* Clear flags */ + mmio_write_32(qspi_base() + QSPI_FCR, QSPI_FCR_CTCF | QSPI_FCR_CTEF); + + return ret; +} + +static void stm32_qspi_read_fifo(uint8_t *val, uintptr_t addr) +{ + *val = mmio_read_8(addr); +} + +static void stm32_qspi_write_fifo(uint8_t *val, uintptr_t addr) +{ + mmio_write_8(addr, *val); +} + +static int stm32_qspi_poll(const struct spi_mem_op *op) +{ + void (*fifo)(uint8_t *val, uintptr_t addr); + uint32_t len; + uint8_t *buf; + + if (op->data.dir == SPI_MEM_DATA_IN) { + fifo = stm32_qspi_read_fifo; + } else { + fifo = stm32_qspi_write_fifo; + } + + buf = (uint8_t *)op->data.buf; + + for (len = op->data.nbytes; len != 0U; len--) { + uint64_t timeout = timeout_init_us(QSPI_FIFO_TIMEOUT_US); + + while ((mmio_read_32(qspi_base() + QSPI_SR) & + QSPI_SR_FTF) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: fifo timeout\n", __func__); + return -ETIMEDOUT; + } + } + + fifo(buf++, qspi_base() + QSPI_DR); + } + + return 0; +} + +static int stm32_qspi_mm(const struct spi_mem_op *op) +{ + memcpy(op->data.buf, + (void *)(stm32_qspi.mm_base + (size_t)op->addr.val), + op->data.nbytes); + + return 0; +} + +static int stm32_qspi_tx(const struct spi_mem_op *op, uint8_t mode) +{ + if (op->data.nbytes == 0U) { + return 0; + } + + if (mode == QSPI_CCR_MEM_MAP) { + return stm32_qspi_mm(op); + } + + return stm32_qspi_poll(op); +} + +static unsigned int stm32_qspi_get_mode(uint8_t buswidth) +{ + if (buswidth == 4U) { + return 3U; + } + + return buswidth; +} + +static int stm32_qspi_exec_op(const struct spi_mem_op *op) +{ + uint64_t timeout; + uint32_t ccr; + size_t addr_max; + uint8_t mode = QSPI_CCR_IND_WRITE; + int ret; + + VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addr:%" PRIx64 " len:%x\n", + __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, + op->dummy.buswidth, op->data.buswidth, + op->addr.val, op->data.nbytes); + + ret = stm32_qspi_wait_for_not_busy(); + if (ret != 0) { + return ret; + } + + addr_max = op->addr.val + op->data.nbytes + 1U; + + if ((op->data.dir == SPI_MEM_DATA_IN) && (op->data.nbytes != 0U)) { + if ((addr_max < stm32_qspi.mm_size) && + (op->addr.buswidth != 0U)) { + mode = QSPI_CCR_MEM_MAP; + } else { + mode = QSPI_CCR_IND_READ; + } + } + + if (op->data.nbytes != 0U) { + mmio_write_32(qspi_base() + QSPI_DLR, op->data.nbytes - 1U); + } + + ccr = mode << QSPI_CCR_FMODE_SHIFT; + ccr |= op->cmd.opcode; + ccr |= stm32_qspi_get_mode(op->cmd.buswidth) << QSPI_CCR_IMODE_SHIFT; + + if (op->addr.nbytes != 0U) { + ccr |= (op->addr.nbytes - 1U) << QSPI_CCR_ADSIZE_SHIFT; + ccr |= stm32_qspi_get_mode(op->addr.buswidth) << + QSPI_CCR_ADMODE_SHIFT; + } + + if ((op->dummy.buswidth != 0U) && (op->dummy.nbytes != 0U)) { + ccr |= (op->dummy.nbytes * 8U / op->dummy.buswidth) << + QSPI_CCR_DCYC_SHIFT; + } + + if (op->data.nbytes != 0U) { + ccr |= stm32_qspi_get_mode(op->data.buswidth) << + QSPI_CCR_DMODE_SHIFT; + } + + mmio_write_32(qspi_base() + QSPI_CCR, ccr); + + if ((op->addr.nbytes != 0U) && (mode != QSPI_CCR_MEM_MAP)) { + mmio_write_32(qspi_base() + QSPI_AR, op->addr.val); + } + + ret = stm32_qspi_tx(op, mode); + + /* + * Abort in: + * - Error case. + * - Memory mapped read: prefetching must be stopped if we read the last + * byte of device (device size - fifo size). If device size is not + * known then prefetching is always stopped. + */ + if ((ret != 0) || (mode == QSPI_CCR_MEM_MAP)) { + goto abort; + } + + /* Wait end of TX in indirect mode */ + ret = stm32_qspi_wait_cmd(op); + if (ret != 0) { + goto abort; + } + + return 0; + +abort: + mmio_setbits_32(qspi_base() + QSPI_CR, QSPI_CR_ABORT); + + /* Wait clear of abort bit by hardware */ + timeout = timeout_init_us(QSPI_ABT_TIMEOUT_US); + while ((mmio_read_32(qspi_base() + QSPI_CR) & QSPI_CR_ABORT) != 0U) { + if (timeout_elapsed(timeout)) { + ret = -ETIMEDOUT; + break; + } + } + + mmio_write_32(qspi_base() + QSPI_FCR, QSPI_FCR_CTCF); + + if (ret != 0) { + ERROR("%s: exec op error\n", __func__); + } + + return ret; +} + +static int stm32_qspi_claim_bus(unsigned int cs) +{ + uint32_t cr; + + if (cs >= QSPI_MAX_CHIP) { + return -ENODEV; + } + + /* Set chip select and enable the controller */ + cr = QSPI_CR_EN; + if (cs == 1U) { + cr |= QSPI_CR_FSEL; + } + + mmio_clrsetbits_32(qspi_base() + QSPI_CR, QSPI_CR_FSEL, cr); + + return 0; +} + +static void stm32_qspi_release_bus(void) +{ + mmio_clrbits_32(qspi_base() + QSPI_CR, QSPI_CR_EN); +} + +static int stm32_qspi_set_speed(unsigned int hz) +{ + unsigned long qspi_clk = clk_get_rate(stm32_qspi.clock_id); + uint32_t prescaler = UINT8_MAX; + uint32_t csht; + int ret; + + if (qspi_clk == 0U) { + return -EINVAL; + } + + if (hz > 0U) { + prescaler = div_round_up(qspi_clk, hz) - 1U; + if (prescaler > UINT8_MAX) { + prescaler = UINT8_MAX; + } + } + + csht = div_round_up((5U * qspi_clk) / (prescaler + 1U), FREQ_100MHZ); + csht = ((csht - 1U) << QSPI_DCR_CSHT_SHIFT) & QSPI_DCR_CSHT_MASK; + + ret = stm32_qspi_wait_for_not_busy(); + if (ret != 0) { + return ret; + } + + mmio_clrsetbits_32(qspi_base() + QSPI_CR, QSPI_CR_PRESCALER_MASK, + prescaler << QSPI_CR_PRESCALER_SHIFT); + + mmio_clrsetbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CSHT_MASK, csht); + + VERBOSE("%s: speed=%lu\n", __func__, qspi_clk / (prescaler + 1U)); + + return 0; +} + +static int stm32_qspi_set_mode(unsigned int mode) +{ + int ret; + + ret = stm32_qspi_wait_for_not_busy(); + if (ret != 0) { + return ret; + } + + if ((mode & SPI_CS_HIGH) != 0U) { + return -ENODEV; + } + + if (((mode & SPI_CPHA) != 0U) && ((mode & SPI_CPOL) != 0U)) { + mmio_setbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CKMODE); + } else if (((mode & SPI_CPHA) == 0U) && ((mode & SPI_CPOL) == 0U)) { + mmio_clrbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CKMODE); + } else { + return -ENODEV; + } + + VERBOSE("%s: mode=0x%x\n", __func__, mode); + + if ((mode & SPI_RX_QUAD) != 0U) { + VERBOSE("rx: quad\n"); + } else if ((mode & SPI_RX_DUAL) != 0U) { + VERBOSE("rx: dual\n"); + } else { + VERBOSE("rx: single\n"); + } + + if ((mode & SPI_TX_QUAD) != 0U) { + VERBOSE("tx: quad\n"); + } else if ((mode & SPI_TX_DUAL) != 0U) { + VERBOSE("tx: dual\n"); + } else { + VERBOSE("tx: single\n"); + } + + return 0; +} + +static const struct spi_bus_ops stm32_qspi_bus_ops = { + .claim_bus = stm32_qspi_claim_bus, + .release_bus = stm32_qspi_release_bus, + .set_speed = stm32_qspi_set_speed, + .set_mode = stm32_qspi_set_mode, + .exec_op = stm32_qspi_exec_op, +}; + +int stm32_qspi_init(void) +{ + size_t size; + int qspi_node; + struct dt_node_info info; + void *fdt = NULL; + int ret; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + qspi_node = dt_get_node(&info, -1, DT_QSPI_COMPAT); + if (qspi_node < 0) { + ERROR("No QSPI ctrl found\n"); + return -FDT_ERR_NOTFOUND; + } + + if (info.status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + ret = fdt_get_reg_props_by_name(fdt, qspi_node, "qspi", + &stm32_qspi.reg_base, &size); + if (ret != 0) { + return ret; + } + + ret = fdt_get_reg_props_by_name(fdt, qspi_node, "qspi_mm", + &stm32_qspi.mm_base, + &stm32_qspi.mm_size); + if (ret != 0) { + return ret; + } + + if (dt_set_pinctrl_config(qspi_node) != 0) { + return -FDT_ERR_BADVALUE; + } + + if ((info.clock < 0) || (info.reset < 0)) { + return -FDT_ERR_BADVALUE; + } + + stm32_qspi.clock_id = (unsigned long)info.clock; + stm32_qspi.reset_id = (unsigned int)info.reset; + + clk_enable(stm32_qspi.clock_id); + + ret = stm32mp_reset_assert(stm32_qspi.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { + panic(); + } + ret = stm32mp_reset_deassert(stm32_qspi.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { + panic(); + } + + mmio_write_32(qspi_base() + QSPI_CR, QSPI_CR_SSHIFT); + mmio_write_32(qspi_base() + QSPI_DCR, QSPI_DCR_FSIZE_MASK); + + return spi_mem_init_slave(fdt, qspi_node, &stm32_qspi_bus_ops); +}; diff --git a/arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S b/arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S new file mode 100644 index 0000000..e467f09 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +#define USART_TIMEOUT 0x1000 + + /* + * "core" functions are low-level implementations that don't require + * writeable memory and are thus safe to call in BL1 crash context. + */ + .globl console_stm32_core_init + .globl console_stm32_core_putc + .globl console_stm32_core_getc + .globl console_stm32_core_flush + + .globl console_stm32_putc + .globl console_stm32_flush + + + + /* ----------------------------------------------------------------- + * int console_core_init(uintptr_t base_addr, + * unsigned int uart_clk, + * unsigned int baud_rate) + * + * Function to initialize the console without a C Runtime to print + * debug information. This function will be accessed by console_init + * and crash reporting. + * + * In: r0 - console base address + * r1 - Uart clock in Hz + * r2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : r1, r2, r3 + * ----------------------------------------------------------------- + */ +func console_stm32_core_init + /* Check the input base address */ + cmp r0, #0 + beq core_init_fail +#if !defined(IMAGE_BL2) + /* Skip UART initialization if it is already enabled */ + ldr r3, [r0, #USART_CR1] + ands r3, r3, #USART_CR1_UE + bne 1f +#endif /* IMAGE_BL2 */ + /* Check baud rate and uart clock for sanity */ + cmp r1, #0 + beq core_init_fail + cmp r2, #0 + beq core_init_fail + /* Disable UART */ + ldr r3, [r0, #USART_CR1] + bic r3, r3, #USART_CR1_UE + str r3, [r0, #USART_CR1] + /* Configure UART */ + orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN) + str r3, [r0, #USART_CR1] + ldr r3, [r0, #USART_CR2] + bic r3, r3, #USART_CR2_STOP + str r3, [r0, #USART_CR2] + /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ + lsr r3, r2, #1 + add r3, r1, r3 + udiv r3, r3, r2 + cmp r3, #16 + bhi 2f + /* Oversampling 8 */ + /* Divisor = (2 * Uart clock + (baudrate / 2)) / baudrate */ + lsr r3, r2, #1 + add r3, r3, r1, lsl #1 + udiv r3, r3, r2 + and r1, r3, #USART_BRR_DIV_FRACTION + lsr r1, r1, #1 + bic r3, r3, #USART_BRR_DIV_FRACTION + orr r3, r3, r1 + ldr r1, [r0, #USART_CR1] + orr r1, r1, #USART_CR1_OVER8 + str r1, [r0, #USART_CR1] +2: + str r3, [r0, #USART_BRR] + /* Enable UART */ + ldr r3, [r0, #USART_CR1] + orr r3, r3, #USART_CR1_UE + str r3, [r0, #USART_CR1] + /* Check TEACK bit */ + mov r2, #USART_TIMEOUT +teack_loop: + subs r2, r2, #1 + beq core_init_fail + ldr r3, [r0, #USART_ISR] + tst r3, #USART_ISR_TEACK + beq teack_loop +1: + mov r0, #1 + bx lr +core_init_fail: + mov r0, #0 + bx lr +endfunc console_stm32_core_init + + .globl console_stm32_register + + /* ------------------------------------------------------- + * int console_stm32_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new STM32 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: r0 - UART register base address + * r1 - UART clock in Hz + * r2 - Baud rate + * r3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : r0, r1, r2 + * ------------------------------------------------------- + */ +func console_stm32_register + push {r4, lr} + mov r4, r3 + cmp r4, #0 + beq register_fail + str r0, [r4, #CONSOLE_T_BASE] + + bl console_stm32_core_init + cmp r0, #0 + beq register_fail + + mov r0, r4 + pop {r4, lr} + finish_console_register stm32 putc=1, getc=0, flush=1 + +register_fail: + pop {r4, pc} +endfunc console_stm32_register + + /* --------------------------------------------------------------- + * int console_core_putc(int c, uintptr_t base_addr) + * + * Function to output a character over the console. It returns the + * character printed on success or -1 on error. + * + * In : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * --------------------------------------------------------------- + */ +func console_stm32_core_putc + /* Check the input parameter */ + cmp r1, #0 + beq putc_error + + /* Check Transmit Data Register Empty */ +txe_loop: + ldr r2, [r1, #USART_ISR] + tst r2, #USART_ISR_TXE + beq txe_loop + str r0, [r1, #USART_TDR] + /* Check transmit complete flag */ +tc_loop: + ldr r2, [r1, #USART_ISR] + tst r2, #USART_ISR_TC + beq tc_loop + bx lr +putc_error: + mov r0, #-1 + bx lr +endfunc console_stm32_core_putc + + /* ------------------------------------------------------------ + * int console_stm32_putc(int c, console_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In: r0 - character to be printed + * r1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list: r2 + * ------------------------------------------------------------ + */ +func console_stm32_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r1, [r1, #CONSOLE_T_BASE] + b console_stm32_core_putc +endfunc console_stm32_putc + + /* ----------------------------------------------------------- + * int console_core_getc(uintptr_t base_addr) + * + * Function to get a character from the console. + * It returns the character grabbed on success or -1 on error. + * + * In : r0 - console base address + * Out : return -1. + * Clobber list : r0, r1 + * ----------------------------------------------------------- + */ +func console_stm32_core_getc + /* Not supported */ + mov r0, #-1 + bx lr +endfunc console_stm32_core_getc + + /* --------------------------------------------------------------- + * void console_core_flush(uintptr_t base_addr) + * + * Function to force a write of all buffered data that hasn't been + * output. + * + * In : r0 - console base address + * Out : void. + * Clobber list : r0, r1 + * --------------------------------------------------------------- + */ +func console_stm32_core_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + /* Check Transmit Data Register Empty */ +txe_loop_3: + ldr r1, [r0, #USART_ISR] + tst r1, #USART_ISR_TXE + beq txe_loop_3 + bx lr +endfunc console_stm32_core_flush + + /* ------------------------------------------------------ + * void console_stm32_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - pointer to console_t structure + * Out : void. + * Clobber list: r0, r1 + * ------------------------------------------------------ + */ +func console_stm32_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_stm32_core_flush +endfunc console_stm32_flush diff --git a/arm-trusted-firmware/drivers/st/uart/stm32_uart.c b/arm-trusted-firmware/drivers/st/uart/stm32_uart.c new file mode 100644 index 0000000..e2e5405 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/uart/stm32_uart.c @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* UART time-out value */ +#define STM32_UART_TIMEOUT_US 20000U + +/* Mask to clear ALL the configuration registers */ + +#define STM32_UART_CR1_FIELDS \ + (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ + USART_CR1_RE | USART_CR1_OVER8 | USART_CR1_FIFOEN) + +#define STM32_UART_CR2_FIELDS \ + (USART_CR2_SLVEN | USART_CR2_DIS_NSS | USART_CR2_ADDM7 | \ + USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \ + USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \ + USART_CR2_STOP | USART_CR2_LINEN | USART_CR2_SWAP | \ + USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_DATAINV | \ + USART_CR2_MSBFIRST | USART_CR2_ABREN | USART_CR2_ABRMODE | \ + USART_CR2_RTOEN | USART_CR2_ADD) + +#define STM32_UART_CR3_FIELDS \ + (USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | \ + USART_CR3_HDSEL | USART_CR3_NACK | USART_CR3_SCEN | \ + USART_CR3_DMAR | USART_CR3_DMAT | USART_CR3_RTSE | \ + USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \ + USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | \ + USART_CR3_DEP | USART_CR3_SCARCNT | USART_CR3_WUS | \ + USART_CR3_WUFIE | USART_CR3_TXFTIE | USART_CR3_TCBGTIE | \ + USART_CR3_RXFTCFG | USART_CR3_RXFTIE | USART_CR3_TXFTCFG) + +#define STM32_UART_ISR_ERRORS \ + (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE) + +static const uint16_t presc_table[STM32_UART_PRESCALER_NB] = { + 1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U +}; + +/* @brief BRR division operation to set BRR register in 8-bit oversampling + * mode. + * @param clockfreq: UART clock. + * @param baud_rate: Baud rate set by the user. + * @param prescaler: UART prescaler value. + * @retval Division result. + */ +static uint32_t uart_div_sampling8(unsigned long clockfreq, + uint32_t baud_rate, + uint32_t prescaler) +{ + uint32_t scaled_freq = clockfreq / presc_table[prescaler]; + + return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate; + +} + +/* @brief BRR division operation to set BRR register in 16-bit oversampling + * mode. + * @param clockfreq: UART clock. + * @param baud_rate: Baud rate set by the user. + * @param prescaler: UART prescaler value. + * @retval Division result. + */ +static uint32_t uart_div_sampling16(unsigned long clockfreq, + uint32_t baud_rate, + uint32_t prescaler) +{ + uint32_t scaled_freq = clockfreq / presc_table[prescaler]; + + return (scaled_freq + (baud_rate / 2)) / baud_rate; + +} + +/* + * @brief Return the UART clock frequency. + * @param huart: UART handle. + * @retval Frequency value in Hz. + */ +static unsigned long uart_get_clock_freq(struct stm32_uart_handle_s *huart) +{ + return fdt_get_uart_clock_freq((uintptr_t)huart->base); +} + +/* + * @brief Configure the UART peripheral. + * @param huart: UART handle. + * @retval UART status. + */ +static int uart_set_config(struct stm32_uart_handle_s *huart, + const struct stm32_uart_init_s *init) +{ + uint32_t tmpreg; + unsigned long clockfreq; + uint32_t brrtemp; + + /* + * ---------------------- USART CR1 Configuration -------------------- + * Clear M, PCE, PS, TE, RE and OVER8 bits and configure + * the UART word length, parity, mode and oversampling: + * - set the M bits according to init->word_length value, + * - set PCE and PS bits according to init->parity value, + * - set TE and RE bits according to init->mode value, + * - set OVER8 bit according to init->over_sampling value. + */ + tmpreg = init->word_length | + init->parity | + init->mode | + init->over_sampling | + init->fifo_mode; + mmio_clrsetbits_32(huart->base + USART_CR1, STM32_UART_CR1_FIELDS, tmpreg); + + /* + * --------------------- USART CR2 Configuration --------------------- + * Configure the UART Stop Bits: Set STOP[13:12] bits according + * to init->stop_bits value. + */ + mmio_clrsetbits_32(huart->base + USART_CR2, STM32_UART_CR2_FIELDS, + init->stop_bits); + + /* + * --------------------- USART CR3 Configuration --------------------- + * Configure: + * - UART HardWare Flow Control: set CTSE and RTSE bits according + * to init->hw_flow_control value, + * - one-bit sampling method versus three samples' majority rule + * according to init->one_bit_sampling (not applicable to + * LPUART), + * - set TXFTCFG bit according to init->tx_fifo_threshold value, + * - set RXFTCFG bit according to init->rx_fifo_threshold value. + */ + tmpreg = init->hw_flow_control | init->one_bit_sampling; + + if (init->fifo_mode == USART_CR1_FIFOEN) { + tmpreg |= init->tx_fifo_threshold | + init->rx_fifo_threshold; + } + + mmio_clrsetbits_32(huart->base + USART_CR3, STM32_UART_CR3_FIELDS, tmpreg); + + /* + * --------------------- USART PRESC Configuration ------------------- + * Configure UART Clock Prescaler : set PRESCALER according to + * init->prescaler value. + */ + assert(init->prescaler < STM32_UART_PRESCALER_NB); + mmio_clrsetbits_32(huart->base + USART_PRESC, USART_PRESC_PRESCALER, + init->prescaler); + + /*---------------------- USART BRR configuration --------------------*/ + clockfreq = uart_get_clock_freq(huart); + if (clockfreq == 0UL) { + return -ENODEV; + } + + if (init->over_sampling == STM32_UART_OVERSAMPLING_8) { + uint32_t usartdiv = uart_div_sampling8(clockfreq, + init->baud_rate, + init->prescaler); + + brrtemp = (usartdiv & USART_BRR_DIV_MANTISSA) | + ((usartdiv & USART_BRR_DIV_FRACTION) >> 1); + } else { + brrtemp = uart_div_sampling16(clockfreq, + init->baud_rate, + init->prescaler) & + (USART_BRR_DIV_FRACTION | USART_BRR_DIV_MANTISSA); + } + mmio_write_32(huart->base + USART_BRR, brrtemp); + + return 0; +} + +/* + * @brief Handle UART communication timeout. + * @param huart: UART handle. + * @param flag: Specifies the UART flag to check. + * @retval UART status. + */ +static int stm32_uart_wait_flag(struct stm32_uart_handle_s *huart, uint32_t flag) +{ + uint64_t timeout_ref = timeout_init_us(STM32_UART_TIMEOUT_US); + + while ((mmio_read_32(huart->base + USART_ISR) & flag) == 0U) { + if (timeout_elapsed(timeout_ref)) { + return -ETIMEDOUT; + } + } + + return 0; +} + +/* + * @brief Check the UART idle State. + * @param huart: UART handle. + * @retval UART status. + */ +static int stm32_uart_check_idle(struct stm32_uart_handle_s *huart) +{ + int ret; + + /* Check if the transmitter is enabled */ + if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_TE) == USART_CR1_TE) { + ret = stm32_uart_wait_flag(huart, USART_ISR_TEACK); + if (ret != 0) { + return ret; + } + } + + /* Check if the receiver is enabled */ + if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_RE) == USART_CR1_RE) { + ret = stm32_uart_wait_flag(huart, USART_ISR_REACK); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +/* + * @brief Compute RDR register mask depending on word length. + * @param huart: UART handle. + * @retval Mask value. + */ +static unsigned int stm32_uart_rdr_mask(const struct stm32_uart_init_s *init) +{ + unsigned int mask = 0U; + + switch (init->word_length) { + case STM32_UART_WORDLENGTH_9B: + mask = GENMASK(8, 0); + break; + case STM32_UART_WORDLENGTH_8B: + mask = GENMASK(7, 0); + break; + case STM32_UART_WORDLENGTH_7B: + mask = GENMASK(6, 0); + break; + default: + break; /* not reached */ + } + + if (init->parity != STM32_UART_PARITY_NONE) { + mask >>= 1; + } + + return mask; +} + +/* + * @brief Check interrupt and status errors. + * @retval True if error detected, false otherwise. + */ +static bool stm32_uart_error_detected(struct stm32_uart_handle_s *huart) +{ + return (mmio_read_32(huart->base + USART_ISR) & STM32_UART_ISR_ERRORS) != 0U; +} + +/* + * @brief Clear status errors. + */ +static void stm32_uart_error_clear(struct stm32_uart_handle_s *huart) +{ + mmio_write_32(huart->base + USART_ICR, STM32_UART_ISR_ERRORS); +} + +/* + * @brief Stop the UART. + * @param base: UART base address. + */ +void stm32_uart_stop(uintptr_t base) +{ + mmio_clrbits_32(base + USART_CR1, USART_CR1_UE); +} + +/* + * @brief Initialize UART. + * @param huart: UART handle. + * @param base_addr: base address of UART. + * @param init: UART initialization parameter. + * @retval UART status. + */ + +int stm32_uart_init(struct stm32_uart_handle_s *huart, + uintptr_t base_addr, + const struct stm32_uart_init_s *init) +{ + int ret; + + if (huart == NULL || init == NULL || base_addr == 0U) { + return -EINVAL; + } + + huart->base = base_addr; + + /* Disable the peripheral */ + stm32_uart_stop(huart->base); + + /* Computation of UART mask to apply to RDR register */ + huart->rdr_mask = stm32_uart_rdr_mask(init); + + /* Init the peripheral */ + ret = uart_set_config(huart, init); + if (ret != 0) { + return ret; + } + + /* Enable the peripheral */ + mmio_setbits_32(huart->base + USART_CR1, USART_CR1_UE); + + /* TEACK and/or REACK to check */ + return stm32_uart_check_idle(huart); +} + +/* + * @brief Transmit one data in no blocking mode. + * @param huart: UART handle. + * @param c: data to sent. + * @retval UART status. + */ +int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c) +{ + int ret; + + if (huart == NULL) { + return -EINVAL; + } + + ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); + if (ret != 0) { + return ret; + } + + mmio_write_32(huart->base + USART_TDR, c); + if (stm32_uart_error_detected(huart)) { + stm32_uart_error_clear(huart); + return -EFAULT; + } + + return 0; +} + +/* + * @brief Flush TX Transmit fifo + * @param huart: UART handle. + * @retval UART status. + */ +int stm32_uart_flush(struct stm32_uart_handle_s *huart) +{ + int ret; + + if (huart == NULL) { + return -EINVAL; + } + + ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); + if (ret != 0) { + return ret; + } + + return stm32_uart_wait_flag(huart, USART_ISR_TC); +} + +/* + * @brief Receive a data in no blocking mode. + * @retval value if >0 or UART status. + */ +int stm32_uart_getc(struct stm32_uart_handle_s *huart) +{ + uint32_t data; + + if (huart == NULL) { + return -EINVAL; + } + + /* Check if data is available */ + if ((mmio_read_32(huart->base + USART_ISR) & USART_ISR_RXNE) == 0U) { + return -EAGAIN; + } + + data = mmio_read_32(huart->base + USART_RDR) & huart->rdr_mask; + + if (stm32_uart_error_detected(huart)) { + stm32_uart_error_clear(huart); + return -EFAULT; + } + + return (int)data; +} diff --git a/arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c b/arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c new file mode 100644 index 0000000..9a49690 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c @@ -0,0 +1,1091 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#define USB_OTG_MODE_DEVICE 0U +#define USB_OTG_MODE_HOST 1U +#define USB_OTG_MODE_DRD 2U + +#define EP_TYPE_CTRL 0U +#define EP_TYPE_ISOC 1U +#define EP_TYPE_BULK 2U +#define EP_TYPE_INTR 3U + +#define USBD_FIFO_FLUSH_TIMEOUT_US 1000U +#define EP0_FIFO_SIZE 64U + +/* OTG registers offsets */ +#define OTG_GOTGINT 0x004U +#define OTG_GAHBCFG 0x008U +#define OTG_GUSBCFG 0x00CU +#define OTG_GRSTCTL 0x010U +#define OTG_GINTSTS 0x014U +#define OTG_GINTMSK 0x018U +#define OTG_GRXSTSP 0x020U +#define OTG_GLPMCFG 0x054U +#define OTG_DCFG 0x800U +#define OTG_DCTL 0x804U +#define OTG_DSTS 0x808U +#define OTG_DIEPMSK 0x810U +#define OTG_DOEPMSK 0x814U +#define OTG_DAINT 0x818U +#define OTG_DAINTMSK 0x81CU +#define OTG_DIEPEMPMSK 0x834U + +/* Definitions for OTG_DIEPx registers */ +#define OTG_DIEP_BASE 0x900U +#define OTG_DIEP_SIZE 0x20U +#define OTG_DIEPCTL 0x00U +#define OTG_DIEPINT 0x08U +#define OTG_DIEPTSIZ 0x10U +#define OTG_DIEPDMA 0x14U +#define OTG_DTXFSTS 0x18U +#define OTG_DIEP_MAX_NB 9U + +/* Definitions for OTG_DOEPx registers */ +#define OTG_DOEP_BASE 0xB00U +#define OTG_DOEP_SIZE 0x20U +#define OTG_DOEPCTL 0x00U +#define OTG_DOEPINT 0x08U +#define OTG_DOEPTSIZ 0x10U +#define OTG_DOEPDMA 0x14U +#define OTG_D0EP_MAX_NB 9U + +/* Definitions for OTG_DAINT registers */ +#define OTG_DAINT_OUT_MASK GENMASK(31, 16) +#define OTG_DAINT_OUT_SHIFT 16U +#define OTG_DAINT_IN_MASK GENMASK(15, 0) +#define OTG_DAINT_IN_SHIFT 0U + +#define OTG_DAINT_EP0_IN BIT(16) +#define OTG_DAINT_EP0_OUT BIT(0) + +/* Definitions for FIFOs */ +#define OTG_FIFO_BASE 0x1000U +#define OTG_FIFO_SIZE 0x1000U + +/* Bit definitions for OTG_GOTGINT register */ +#define OTG_GOTGINT_SEDET BIT(2) + +/* Bit definitions for OTG_GAHBCFG register */ +#define OTG_GAHBCFG_GINT BIT(0) + +/* Bit definitions for OTG_GUSBCFG register */ +#define OTG_GUSBCFG_TRDT GENMASK(13, 10) +#define OTG_GUSBCFG_TRDT_SHIFT 10U + +#define USBD_HS_TRDT_VALUE 9U + +/* Bit definitions for OTG_GRSTCTL register */ +#define OTG_GRSTCTL_RXFFLSH BIT(4) +#define OTG_GRSTCTL_TXFFLSH BIT(5) +#define OTG_GRSTCTL_TXFNUM_SHIFT 6U + +/* Bit definitions for OTG_GINTSTS register */ +#define OTG_GINTSTS_CMOD BIT(0) +#define OTG_GINTSTS_MMIS BIT(1) +#define OTG_GINTSTS_OTGINT BIT(2) +#define OTG_GINTSTS_SOF BIT(3) +#define OTG_GINTSTS_RXFLVL BIT(4) +#define OTG_GINTSTS_USBSUSP BIT(11) +#define OTG_GINTSTS_USBRST BIT(12) +#define OTG_GINTSTS_ENUMDNE BIT(13) +#define OTG_GINTSTS_IEPINT BIT(18) +#define OTG_GINTSTS_OEPINT BIT(19) +#define OTG_GINTSTS_IISOIXFR BIT(20) +#define OTG_GINTSTS_IPXFR_INCOMPISOOUT BIT(21) +#define OTG_GINTSTS_LPMINT BIT(27) +#define OTG_GINTSTS_SRQINT BIT(30) +#define OTG_GINTSTS_WKUPINT BIT(31) + +/* Bit definitions for OTG_GRXSTSP register */ +#define OTG_GRXSTSP_EPNUM GENMASK(3, 0) +#define OTG_GRXSTSP_BCNT GENMASK(14, 4) +#define OTG_GRXSTSP_BCNT_SHIFT 4U +#define OTG_GRXSTSP_PKTSTS GENMASK(20, 17) +#define OTG_GRXSTSP_PKTSTS_SHIFT 17U + +#define STS_GOUT_NAK 1U +#define STS_DATA_UPDT 2U +#define STS_XFER_COMP 3U +#define STS_SETUP_COMP 4U +#define STS_SETUP_UPDT 6U + +/* Bit definitions for OTG_GLPMCFG register */ +#define OTG_GLPMCFG_BESL GENMASK(5, 2) + +/* Bit definitions for OTG_DCFG register */ +#define OTG_DCFG_DAD GENMASK(10, 4) +#define OTG_DCFG_DAD_SHIFT 4U + +/* Bit definitions for OTG_DCTL register */ +#define OTG_DCTL_RWUSIG BIT(0) +#define OTG_DCTL_SDIS BIT(1) +#define OTG_DCTL_CGINAK BIT(8) + +/* Bit definitions for OTG_DSTS register */ +#define OTG_DSTS_SUSPSTS BIT(0) +#define OTG_DSTS_ENUMSPD_MASK GENMASK(2, 1) +#define OTG_DSTS_FNSOF0 BIT(8) + +#define OTG_DSTS_ENUMSPD(val) ((val) << 1) +#define OTG_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(0U) +#define OTG_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(1U) +#define OTG_DSTS_ENUMSPD_LS_PHY_6MHZ OTG_DSTS_ENUMSPD(2U) +#define OTG_DSTS_ENUMSPD_FS_PHY_48MHZ OTG_DSTS_ENUMSPD(3U) + +/* Bit definitions for OTG_DIEPMSK register */ +#define OTG_DIEPMSK_XFRCM BIT(0) +#define OTG_DIEPMSK_EPDM BIT(1) +#define OTG_DIEPMSK_TOM BIT(3) + +/* Bit definitions for OTG_DOEPMSK register */ +#define OTG_DOEPMSK_XFRCM BIT(0) +#define OTG_DOEPMSK_EPDM BIT(1) +#define OTG_DOEPMSK_STUPM BIT(3) + +/* Bit definitions for OTG_DIEPCTLx registers */ +#define OTG_DIEPCTL_MPSIZ GENMASK(10, 0) +#define OTG_DIEPCTL_STALL BIT(21) +#define OTG_DIEPCTL_CNAK BIT(26) +#define OTG_DIEPCTL_SD0PID_SEVNFRM BIT(28) +#define OTG_DIEPCTL_SODDFRM BIT(29) +#define OTG_DIEPCTL_EPDIS BIT(30) +#define OTG_DIEPCTL_EPENA BIT(31) + +/* Bit definitions for OTG_DIEPINTx registers */ +#define OTG_DIEPINT_XFRC BIT(0) +#define OTG_DIEPINT_EPDISD BIT(1) +#define OTG_DIEPINT_TOC BIT(3) +#define OTG_DIEPINT_ITTXFE BIT(4) +#define OTG_DIEPINT_INEPNE BIT(6) +#define OTG_DIEPINT_TXFE BIT(7) +#define OTG_DIEPINT_TXFE_SHIFT 7U + +#define OTG_DIEPINT_MASK (BIT(13) | BIT(11) | GENMASK(9, 0)) + +/* Bit definitions for OTG_DIEPTSIZx registers */ +#define OTG_DIEPTSIZ_XFRSIZ GENMASK(18, 0) +#define OTG_DIEPTSIZ_PKTCNT GENMASK(28, 19) +#define OTG_DIEPTSIZ_PKTCNT_SHIFT 19U +#define OTG_DIEPTSIZ_MCNT_MASK GENMASK(30, 29) +#define OTG_DIEPTSIZ_MCNT_DATA0 BIT(29) + +#define OTG_DIEPTSIZ_PKTCNT_1 BIT(19) + +/* Bit definitions for OTG_DTXFSTSx registers */ +#define OTG_DTXFSTS_INEPTFSAV GENMASK(15, 0) + +/* Bit definitions for OTG_DOEPCTLx registers */ +#define OTG_DOEPCTL_STALL BIT(21) +#define OTG_DOEPCTL_CNAK BIT(26) +#define OTG_DOEPCTL_SD0PID_SEVNFRM BIT(28) /* other than endpoint 0 */ +#define OTG_DOEPCTL_SD1PID_SODDFRM BIT(29) /* other than endpoint 0 */ +#define OTG_DOEPCTL_EPDIS BIT(30) +#define OTG_DOEPCTL_EPENA BIT(31) + +/* Bit definitions for OTG_DOEPTSIZx registers */ +#define OTG_DOEPTSIZ_XFRSIZ GENMASK(18, 0) +#define OTG_DOEPTSIZ_PKTCNT GENMASK(28, 19) +#define OTG_DOEPTSIZ_RXDPID_STUPCNT GENMASK(30, 29) + +/* Bit definitions for OTG_DOEPINTx registers */ +#define OTG_DOEPINT_XFRC BIT(0) +#define OTG_DOEPINT_STUP BIT(3) +#define OTG_DOEPINT_OTEPDIS BIT(4) + +#define OTG_DOEPINT_MASK (GENMASK(15, 12) | GENMASK(9, 8) | GENMASK(6, 0)) + +#define EP_NB 15U +#define EP_ALL 0x10U + +/* + * Flush TX FIFO. + * handle: PCD handle. + * num: FIFO number. + * This parameter can be a value from 1 to 15 or EP_ALL. + * EP_ALL= 0x10 means Flush all TX FIFOs + * return: USB status. + */ +static enum usb_status usb_dwc2_flush_tx_fifo(void *handle, uint32_t num) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); + + mmio_write_32(usb_base_addr + OTG_GRSTCTL, + OTG_GRSTCTL_TXFFLSH | (uint32_t)(num << OTG_GRSTCTL_TXFNUM_SHIFT)); + + while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & + OTG_GRSTCTL_TXFFLSH) == OTG_GRSTCTL_TXFFLSH) { + if (timeout_elapsed(timeout)) { + return USBD_TIMEOUT; + } + } + + return USBD_OK; +} + +/* + * Flush RX FIFO. + * handle: PCD handle. + * return: USB status. + */ +static enum usb_status usb_dwc2_flush_rx_fifo(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); + + mmio_write_32(usb_base_addr + OTG_GRSTCTL, OTG_GRSTCTL_RXFFLSH); + + while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & + OTG_GRSTCTL_RXFFLSH) == OTG_GRSTCTL_RXFFLSH) { + if (timeout_elapsed(timeout)) { + return USBD_TIMEOUT; + } + } + + return USBD_OK; +} + +/* + * Return the global USB interrupt status. + * handle: PCD handle. + * return: Interrupt register value. + */ +static uint32_t usb_dwc2_read_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_GINTSTS) & + mmio_read_32(usb_base_addr + OTG_GINTMSK); +} + +/* + * Return the USB device OUT endpoints interrupt. + * handle: PCD handle. + * return: Device OUT endpoint interrupts. + */ +static uint32_t usb_dwc2_all_out_ep_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return ((mmio_read_32(usb_base_addr + OTG_DAINT) & + mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & + OTG_DAINT_OUT_MASK) >> OTG_DAINT_OUT_SHIFT; +} + +/* + * Return the USB device IN endpoints interrupt. + * handle: PCD handle. + * return: Device IN endpoint interrupts. + */ +static uint32_t usb_dwc2_all_in_ep_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return ((mmio_read_32(usb_base_addr + OTG_DAINT) & + mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & + OTG_DAINT_IN_MASK) >> OTG_DAINT_IN_SHIFT; +} + +/* + * Return Device OUT EP interrupt register. + * handle: PCD handle. + * epnum: Endpoint number. + * This parameter can be a value from 0 to 15. + * return: Device OUT EP Interrupt register. + */ +static uint32_t usb_dwc2_out_ep_int(void *handle, uint8_t epnum) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_DOEP_BASE + + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT) & + mmio_read_32(usb_base_addr + OTG_DOEPMSK); +} + +/* + * Return Device IN EP interrupt register. + * handle: PCD handle. + * epnum: Endpoint number. + * This parameter can be a value from 0 to 15. + * return: Device IN EP Interrupt register. + */ +static uint32_t usb_dwc2_in_ep_int(void *handle, uint8_t epnum) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t msk; + uint32_t emp; + + msk = mmio_read_32(usb_base_addr + OTG_DIEPMSK); + emp = mmio_read_32(usb_base_addr + OTG_DIEPEMPMSK); + msk |= ((emp >> epnum) << OTG_DIEPINT_TXFE_SHIFT) & OTG_DIEPINT_TXFE; + + return mmio_read_32(usb_base_addr + OTG_DIEP_BASE + + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT) & msk; +} + +/* + * Return USB core mode. + * handle: PCD handle. + * return: Core mode. + * This parameter can be 0 (host) or 1 (device). + */ +static uint32_t usb_dwc2_get_mode(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_GINTSTS) & OTG_GINTSTS_CMOD; +} + +/* + * Activate EP0 for detup transactions. + * handle: PCD handle. + * return: USB status. + */ +static enum usb_status usb_dwc2_activate_setup(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE; + + /* Set the MPS of the IN EP based on the enumeration speed */ + mmio_clrbits_32(reg_offset + OTG_DIEPCTL, OTG_DIEPCTL_MPSIZ); + + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_ENUMSPD_MASK) == + OTG_DSTS_ENUMSPD_LS_PHY_6MHZ) { + mmio_setbits_32(reg_offset + OTG_DIEPCTL, 3U); + } + + mmio_setbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_CGINAK); + + return USBD_OK; +} + +/* + * Prepare the EP0 to start the first control setup. + * handle: Selected device. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep0_out_start(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE + OTG_DIEPTSIZ; + uint32_t reg_value = 0U; + + /* PKTCNT = 1 and XFRSIZ = 24 bytes for endpoint 0 */ + reg_value |= OTG_DIEPTSIZ_PKTCNT_1; + reg_value |= (EP0_FIFO_SIZE & OTG_DIEPTSIZ_XFRSIZ); + reg_value |= OTG_DOEPTSIZ_RXDPID_STUPCNT; + + mmio_write_32(reg_offset, reg_value); + + return USBD_OK; +} + +/* + * Write a packet into the TX FIFO associated with the EP/channel. + * handle: Selected device. + * src: Pointer to source buffer. + * ch_ep_num: Endpoint or host channel number. + * len: Number of bytes to write. + * return: USB status. + */ +static enum usb_status usb_dwc2_write_packet(void *handle, uint8_t *src, + uint8_t ch_ep_num, uint16_t len) +{ + uint32_t reg_offset; + uint32_t count32b = (len + 3U) / 4U; + uint32_t i; + + reg_offset = (uintptr_t)handle + OTG_FIFO_BASE + + (ch_ep_num * OTG_FIFO_SIZE); + + for (i = 0U; i < count32b; i++) { + uint32_t src_copy = 0U; + uint32_t j; + + /* Data written to FIFO need to be 4 bytes aligned */ + for (j = 0U; j < 4U; j++) { + src_copy += (*(src + j)) << (8U * j); + } + + mmio_write_32(reg_offset, src_copy); + src += 4U; + } + + return USBD_OK; +} + +/* + * Read a packet from the RX FIFO associated with the EP/channel. + * handle: Selected device. + * dst: Destination pointer. + * len: Number of bytes to read. + * return: Pointer to destination buffer. + */ +static void *usb_dwc2_read_packet(void *handle, uint8_t *dest, uint16_t len) +{ + uint32_t reg_offset; + uint32_t count32b = (len + 3U) / 4U; + uint32_t i; + + VERBOSE("read packet length %i to 0x%lx\n", len, (uintptr_t)dest); + + reg_offset = (uintptr_t)handle + OTG_FIFO_BASE; + + for (i = 0U; i < count32b; i++) { + *(uint32_t *)dest = mmio_read_32(reg_offset); + dest += 4U; + dsb(); + } + + return (void *)dest; +} + +/* + * Setup and start a transfer over an EP. + * handle: Selected device + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep_start_xfer(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + uint32_t clear_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + (ep->num * OTG_DIEP_SIZE); + clear_value = OTG_DIEPTSIZ_PKTCNT | OTG_DIEPTSIZ_XFRSIZ; + if (ep->xfer_len == 0U) { + reg_value = OTG_DIEPTSIZ_PKTCNT_1; + } else { + /* + * Program the transfer size and packet count + * as follows: + * xfersize = N * maxpacket + short_packet + * pktcnt = N + (short_packet exist ? 1 : 0) + */ + reg_value = (OTG_DIEPTSIZ_PKTCNT & + (((ep->xfer_len + ep->maxpacket - 1U) / + ep->maxpacket) << OTG_DIEPTSIZ_PKTCNT_SHIFT)) + | ep->xfer_len; + + if (ep->type == EP_TYPE_ISOC) { + clear_value |= OTG_DIEPTSIZ_MCNT_MASK; + reg_value |= OTG_DIEPTSIZ_MCNT_DATA0; + } + } + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, clear_value, reg_value); + + if ((ep->type != EP_TYPE_ISOC) && (ep->xfer_len > 0U)) { + /* Enable the TX FIFO empty interrupt for this EP */ + mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(ep->num)); + } + + /* EP enable, IN data in FIFO */ + reg_value = OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA; + + if (ep->type == EP_TYPE_ISOC) { + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { + reg_value |= OTG_DIEPCTL_SODDFRM; + } else { + reg_value |= OTG_DIEPCTL_SD0PID_SEVNFRM; + } + } + + mmio_setbits_32(reg_offset + OTG_DIEPCTL, reg_value); + + if (ep->type == EP_TYPE_ISOC) { + usb_dwc2_write_packet(handle, ep->xfer_buff, ep->num, ep->xfer_len); + } + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + (ep->num * OTG_DOEP_SIZE); + /* + * Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + if (ep->xfer_len == 0U) { + reg_value = ep->maxpacket | OTG_DIEPTSIZ_PKTCNT_1; + } else { + uint16_t pktcnt = (ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket; + + reg_value = (pktcnt << OTG_DIEPTSIZ_PKTCNT_SHIFT) | + (ep->maxpacket * pktcnt); + } + + mmio_clrsetbits_32(reg_offset + OTG_DOEPTSIZ, + OTG_DOEPTSIZ_XFRSIZ & OTG_DOEPTSIZ_PKTCNT, + reg_value); + + /* EP enable */ + reg_value = OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA; + + if (ep->type == EP_TYPE_ISOC) { + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { + reg_value |= OTG_DOEPCTL_SD1PID_SODDFRM; + } else { + reg_value |= OTG_DOEPCTL_SD0PID_SEVNFRM; + } + } + + mmio_setbits_32(reg_offset + OTG_DOEPCTL, reg_value); + } + + return USBD_OK; +} + +/* + * Setup and start a transfer over the EP0. + * handle: Selected device. + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep0_start_xfer(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + + (ep->num * OTG_DIEP_SIZE); + + if (ep->xfer_len == 0U) { + reg_value = OTG_DIEPTSIZ_PKTCNT_1; + } else { + /* + * Program the transfer size and packet count + * as follows: + * xfersize = N * maxpacket + short_packet + * pktcnt = N + (short_packet exist ? 1 : 0) + */ + + if (ep->xfer_len > ep->maxpacket) { + ep->xfer_len = ep->maxpacket; + } + + reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->xfer_len; + } + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, + OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, + reg_value); + + /* Enable the TX FIFO empty interrupt for this EP */ + if (ep->xfer_len > 0U) { + mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, + BIT(ep->num)); + } + + /* EP enable, IN data in FIFO */ + mmio_setbits_32(reg_offset + OTG_DIEPCTL, + OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA); + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + + (ep->num * OTG_DOEP_SIZE); + + /* + * Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + if (ep->xfer_len > 0U) { + ep->xfer_len = ep->maxpacket; + } + + reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->maxpacket; + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, + OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, + reg_value); + + /* EP enable */ + mmio_setbits_32(reg_offset + OTG_DOEPCTL, + OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA); + } + + return USBD_OK; +} + +/* + * Set a stall condition over an EP. + * handle: Selected device. + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep_set_stall(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + + (ep->num * OTG_DIEP_SIZE); + reg_value = mmio_read_32(reg_offset + OTG_DIEPCTL); + + if ((reg_value & OTG_DIEPCTL_EPENA) == 0U) { + reg_value &= ~OTG_DIEPCTL_EPDIS; + } + + reg_value |= OTG_DIEPCTL_STALL; + + mmio_write_32(reg_offset + OTG_DIEPCTL, reg_value); + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + + (ep->num * OTG_DOEP_SIZE); + reg_value = mmio_read_32(reg_offset + OTG_DOEPCTL); + + if ((reg_value & OTG_DOEPCTL_EPENA) == 0U) { + reg_value &= ~OTG_DOEPCTL_EPDIS; + } + + reg_value |= OTG_DOEPCTL_STALL; + + mmio_write_32(reg_offset + OTG_DOEPCTL, reg_value); + } + + return USBD_OK; +} + +/* + * Stop the USB device mode. + * handle: Selected device. + * return: USB status. + */ +static enum usb_status usb_dwc2_stop_device(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t i; + + /* Disable Int */ + mmio_clrbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); + + /* Clear pending interrupts */ + for (i = 0U; i < EP_NB; i++) { + mmio_write_32(usb_base_addr + OTG_DIEP_BASE + (i * OTG_DIEP_SIZE) + OTG_DIEPINT, + OTG_DIEPINT_MASK); + mmio_write_32(usb_base_addr + OTG_DOEP_BASE + (i * OTG_DOEP_SIZE) + OTG_DOEPINT, + OTG_DOEPINT_MASK); + } + + mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); + + /* Clear interrupt masks */ + mmio_write_32(usb_base_addr + OTG_DIEPMSK, 0U); + mmio_write_32(usb_base_addr + OTG_DOEPMSK, 0U); + mmio_write_32(usb_base_addr + OTG_DAINTMSK, 0U); + + /* Flush the FIFO */ + usb_dwc2_flush_rx_fifo(handle); + usb_dwc2_flush_tx_fifo(handle, EP_ALL); + + /* Disconnect the USB device by disabling the pull-up/pull-down */ + mmio_setbits_32((uintptr_t)handle + OTG_DCTL, OTG_DCTL_SDIS); + + return USBD_OK; +} + +/* + * Stop the USB device mode. + * handle: Selected device. + * address: New device address to be assigned. + * This parameter can be a value from 0 to 255. + * return: USB status. + */ +static enum usb_status usb_dwc2_set_address(void *handle, uint8_t address) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + mmio_clrsetbits_32(usb_base_addr + OTG_DCFG, + OTG_DCFG_DAD, + address << OTG_DCFG_DAD_SHIFT); + + return USBD_OK; +} + +/* + * Check FIFO for the next packet to be loaded. + * handle: Selected device. + * epnum : Endpoint number. + * xfer_len: Block length. + * xfer_count: Number of blocks. + * maxpacket: Max packet length. + * xfer_buff: Buffer pointer. + * return: USB status. + */ +static enum usb_status usb_dwc2_write_empty_tx_fifo(void *handle, + uint32_t epnum, + uint32_t xfer_len, + uint32_t *xfer_count, + uint32_t maxpacket, + uint8_t **xfer_buff) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + int32_t len; + uint32_t len32b; + enum usb_status ret; + + len = xfer_len - *xfer_count; + + if ((len > 0) && ((uint32_t)len > maxpacket)) { + len = maxpacket; + } + + len32b = (len + 3U) / 4U; + + reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE); + + while (((mmio_read_32(reg_offset + OTG_DTXFSTS) & + OTG_DTXFSTS_INEPTFSAV) > len32b) && + (*xfer_count < xfer_len) && (xfer_len != 0U)) { + /* Write the FIFO */ + len = xfer_len - *xfer_count; + + if ((len > 0) && ((uint32_t)len > maxpacket)) { + len = maxpacket; + } + + len32b = (len + 3U) / 4U; + + ret = usb_dwc2_write_packet(handle, *xfer_buff, epnum, len); + if (ret != USBD_OK) { + return ret; + } + + *xfer_buff += len; + *xfer_count += len; + } + + if (len <= 0) { + mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); + } + + return USBD_OK; +} + +/* + * Handle PCD interrupt request. + * handle: PCD handle. + * param: Pointer to information updated by the IT handling. + * return: Action to do after IT handling. + */ +static enum usb_action usb_dwc2_it_handler(void *handle, uint32_t *param) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t ep_intr; + uint32_t epint; + uint32_t epnum; + uint32_t temp; + enum usb_status ret; + + if (usb_dwc2_get_mode(handle) != USB_OTG_MODE_DEVICE) { + return USB_NOTHING; + } + + /* Avoid spurious interrupt */ + if (usb_dwc2_read_int(handle) == 0U) { + return USB_NOTHING; + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_MMIS) != 0U) { + /* Incorrect mode, acknowledge the interrupt */ + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_MMIS); + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OEPINT) != 0U) { + uint32_t reg_offset; + + /* Read in the device interrupt bits */ + ep_intr = usb_dwc2_all_out_ep_int(handle); + epnum = 0U; + while ((ep_intr & BIT(0)) != BIT(0)) { + epnum++; + ep_intr >>= 1; + } + + reg_offset = usb_base_addr + OTG_DOEP_BASE + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT; + + epint = usb_dwc2_out_ep_int(handle, epnum); + + if ((epint & OTG_DOEPINT_XFRC) == OTG_DOEPINT_XFRC) { + mmio_write_32(reg_offset, OTG_DOEPINT_XFRC); + *param = epnum; + + return USB_DATA_OUT; + } + + if ((epint & OTG_DOEPINT_STUP) == OTG_DOEPINT_STUP) { + /* Inform that a setup packet is available */ + mmio_write_32(reg_offset, OTG_DOEPINT_STUP); + + return USB_SETUP; + } + + if ((epint & OTG_DOEPINT_OTEPDIS) == OTG_DOEPINT_OTEPDIS) { + mmio_write_32(reg_offset, OTG_DOEPINT_OTEPDIS); + } + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IEPINT) != 0U) { + uint32_t reg_offset; + + /* Read in the device interrupt bits */ + ep_intr = usb_dwc2_all_in_ep_int(handle); + epnum = 0U; + while ((ep_intr & BIT(0)) != BIT(0)) { + epnum++; + ep_intr >>= 1; + } + + reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT; + + epint = usb_dwc2_in_ep_int(handle, epnum); + + if ((epint & OTG_DIEPINT_XFRC) == OTG_DIEPINT_XFRC) { + mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); + mmio_write_32(reg_offset, OTG_DIEPINT_XFRC); + *param = epnum; + + return USB_DATA_IN; + } + + if ((epint & OTG_DIEPINT_TOC) == OTG_DIEPINT_TOC) { + mmio_write_32(reg_offset, OTG_DIEPINT_TOC); + } + + if ((epint & OTG_DIEPINT_ITTXFE) == OTG_DIEPINT_ITTXFE) { + mmio_write_32(reg_offset, OTG_DIEPINT_ITTXFE); + } + + if ((epint & OTG_DIEPINT_INEPNE) == OTG_DIEPINT_INEPNE) { + mmio_write_32(reg_offset, OTG_DIEPINT_INEPNE); + } + + if ((epint & OTG_DIEPINT_EPDISD) == OTG_DIEPINT_EPDISD) { + mmio_write_32(reg_offset, OTG_DIEPINT_EPDISD); + } + + if ((epint & OTG_DIEPINT_TXFE) == OTG_DIEPINT_TXFE) { + *param = epnum; + + return USB_WRITE_EMPTY; + } + } + + /* Handle resume interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_WKUPINT) != 0U) { + INFO("handle USB : Resume\n"); + + /* Clear the remote wake-up signaling */ + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_WKUPINT); + + return USB_RESUME; + } + + /* Handle suspend interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBSUSP) != 0U) { + INFO("handle USB : Suspend int\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBSUSP); + + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & + OTG_DSTS_SUSPSTS) == OTG_DSTS_SUSPSTS) { + return USB_SUSPEND; + } + } + + /* Handle LPM interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_LPMINT) != 0U) { + INFO("handle USB : LPM int enter in suspend\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_LPMINT); + *param = (mmio_read_32(usb_base_addr + OTG_GLPMCFG) & + OTG_GLPMCFG_BESL) >> 2; + + return USB_LPM; + } + + /* Handle reset interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBRST) != 0U) { + INFO("handle USB : Reset\n"); + + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); + + usb_dwc2_flush_tx_fifo(handle, 0U); + + mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); + mmio_setbits_32(usb_base_addr + OTG_DAINTMSK, OTG_DAINT_EP0_IN | OTG_DAINT_EP0_OUT); + + mmio_setbits_32(usb_base_addr + OTG_DOEPMSK, OTG_DOEPMSK_STUPM | + OTG_DOEPMSK_XFRCM | + OTG_DOEPMSK_EPDM); + mmio_setbits_32(usb_base_addr + OTG_DIEPMSK, OTG_DIEPMSK_TOM | + OTG_DIEPMSK_XFRCM | + OTG_DIEPMSK_EPDM); + + /* Set default address to 0 */ + mmio_clrbits_32(usb_base_addr + OTG_DCFG, OTG_DCFG_DAD); + + /* Setup EP0 to receive SETUP packets */ + ret = usb_dwc2_ep0_out_start(handle); + if (ret != USBD_OK) { + return ret; + } + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBRST); + + return USB_RESET; + } + + /* Handle enumeration done interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_ENUMDNE) != 0U) { + ret = usb_dwc2_activate_setup(handle); + if (ret != USBD_OK) { + return ret; + } + + mmio_clrbits_32(usb_base_addr + OTG_GUSBCFG, OTG_GUSBCFG_TRDT); + + mmio_setbits_32(usb_base_addr + OTG_GUSBCFG, + (USBD_HS_TRDT_VALUE << OTG_GUSBCFG_TRDT_SHIFT) & OTG_GUSBCFG_TRDT); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_ENUMDNE); + + return USB_ENUM_DONE; + } + + /* Handle RXQLevel interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_RXFLVL) != 0U) { + mmio_clrbits_32(usb_base_addr + OTG_GINTMSK, + OTG_GINTSTS_RXFLVL); + + temp = mmio_read_32(usb_base_addr + OTG_GRXSTSP); + + *param = temp & OTG_GRXSTSP_EPNUM; + *param |= (temp & OTG_GRXSTSP_BCNT) << (USBD_OUT_COUNT_SHIFT - + OTG_GRXSTSP_BCNT_SHIFT); + + if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == STS_DATA_UPDT) { + if ((temp & OTG_GRXSTSP_BCNT) != 0U) { + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + + return USB_READ_DATA_PACKET; + } + } else if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == + STS_SETUP_UPDT) { + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + + return USB_READ_SETUP_PACKET; + } + + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + } + + /* Handle SOF interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SOF) != 0U) { + INFO("handle USB : SOF\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SOF); + + return USB_SOF; + } + + /* Handle incomplete ISO IN interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IISOIXFR) != 0U) { + INFO("handle USB : ISO IN\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, + OTG_GINTSTS_IISOIXFR); + } + + /* Handle incomplete ISO OUT interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IPXFR_INCOMPISOOUT) != + 0U) { + INFO("handle USB : ISO OUT\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, + OTG_GINTSTS_IPXFR_INCOMPISOOUT); + } + + /* Handle connection event interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SRQINT) != 0U) { + INFO("handle USB : Connect\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SRQINT); + } + + /* Handle disconnection event interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OTGINT) != 0U) { + INFO("handle USB : Disconnect\n"); + + temp = mmio_read_32(usb_base_addr + OTG_GOTGINT); + + if ((temp & OTG_GOTGINT_SEDET) == OTG_GOTGINT_SEDET) { + return USB_DISCONNECT; + } + } + + return USB_NOTHING; +} + +/* + * Start the usb device mode + * usb_core_handle: USB core driver handle. + * return USB status. + */ +static enum usb_status usb_dwc2_start_device(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_SDIS); + mmio_setbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); + + return USBD_OK; +} + +static const struct usb_driver usb_dwc2driver = { + .ep0_out_start = usb_dwc2_ep0_out_start, + .ep_start_xfer = usb_dwc2_ep_start_xfer, + .ep0_start_xfer = usb_dwc2_ep0_start_xfer, + .write_packet = usb_dwc2_write_packet, + .read_packet = usb_dwc2_read_packet, + .ep_set_stall = usb_dwc2_ep_set_stall, + .start_device = usb_dwc2_start_device, + .stop_device = usb_dwc2_stop_device, + .set_address = usb_dwc2_set_address, + .write_empty_tx_fifo = usb_dwc2_write_empty_tx_fifo, + .it_handler = usb_dwc2_it_handler +}; + +/* + * Initialize USB DWC2 driver. + * usb_core_handle: USB core driver handle. + * pcd_handle: PCD handle. + * base_register: USB global register base address. + */ +void stm32mp1_usb_init_driver(struct usb_handle *usb_core_handle, + struct pcd_handle *pcd_handle, + void *base_register) +{ + register_usb_driver(usb_core_handle, pcd_handle, &usb_dwc2driver, + base_register); +} diff --git a/arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c b/arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c new file mode 100644 index 0000000..04f4673 --- /dev/null +++ b/arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c @@ -0,0 +1,432 @@ +/* + * 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 + +#define DWMMC_CTRL (0x00) +#define CTRL_IDMAC_EN (1 << 25) +#define CTRL_DMA_EN (1 << 5) +#define CTRL_INT_EN (1 << 4) +#define CTRL_DMA_RESET (1 << 2) +#define CTRL_FIFO_RESET (1 << 1) +#define CTRL_RESET (1 << 0) +#define CTRL_RESET_ALL (CTRL_DMA_RESET | CTRL_FIFO_RESET | \ + CTRL_RESET) + +#define DWMMC_PWREN (0x04) +#define DWMMC_CLKDIV (0x08) +#define DWMMC_CLKSRC (0x0c) +#define DWMMC_CLKENA (0x10) +#define DWMMC_TMOUT (0x14) +#define DWMMC_CTYPE (0x18) +#define CTYPE_8BIT (1 << 16) +#define CTYPE_4BIT (1) +#define CTYPE_1BIT (0) + +#define DWMMC_BLKSIZ (0x1c) +#define DWMMC_BYTCNT (0x20) +#define DWMMC_INTMASK (0x24) +#define INT_EBE (1 << 15) +#define INT_SBE (1 << 13) +#define INT_HLE (1 << 12) +#define INT_FRUN (1 << 11) +#define INT_DRT (1 << 9) +#define INT_RTO (1 << 8) +#define INT_DCRC (1 << 7) +#define INT_RCRC (1 << 6) +#define INT_RXDR (1 << 5) +#define INT_TXDR (1 << 4) +#define INT_DTO (1 << 3) +#define INT_CMD_DONE (1 << 2) +#define INT_RE (1 << 1) + +#define DWMMC_CMDARG (0x28) +#define DWMMC_CMD (0x2c) +#define CMD_START (U(1) << 31) +#define CMD_USE_HOLD_REG (1 << 29) /* 0 if SDR50/100 */ +#define CMD_UPDATE_CLK_ONLY (1 << 21) +#define CMD_SEND_INIT (1 << 15) +#define CMD_STOP_ABORT_CMD (1 << 14) +#define CMD_WAIT_PRVDATA_COMPLETE (1 << 13) +#define CMD_WRITE (1 << 10) +#define CMD_DATA_TRANS_EXPECT (1 << 9) +#define CMD_CHECK_RESP_CRC (1 << 8) +#define CMD_RESP_LEN (1 << 7) +#define CMD_RESP_EXPECT (1 << 6) +#define CMD(x) (x & 0x3f) + +#define DWMMC_RESP0 (0x30) +#define DWMMC_RESP1 (0x34) +#define DWMMC_RESP2 (0x38) +#define DWMMC_RESP3 (0x3c) +#define DWMMC_RINTSTS (0x44) +#define DWMMC_STATUS (0x48) +#define STATUS_DATA_BUSY (1 << 9) + +#define DWMMC_FIFOTH (0x4c) +#define FIFOTH_TWMARK(x) (x & 0xfff) +#define FIFOTH_RWMARK(x) ((x & 0x1ff) << 16) +#define FIFOTH_DMA_BURST_SIZE(x) ((x & 0x7) << 28) + +#define DWMMC_DEBNCE (0x64) +#define DWMMC_BMOD (0x80) +#define BMOD_ENABLE (1 << 7) +#define BMOD_FB (1 << 1) +#define BMOD_SWRESET (1 << 0) + +#define DWMMC_DBADDR (0x88) +#define DWMMC_IDSTS (0x8c) +#define DWMMC_IDINTEN (0x90) +#define DWMMC_CARDTHRCTL (0x100) +#define CARDTHRCTL_RD_THR(x) ((x & 0xfff) << 16) +#define CARDTHRCTL_RD_THR_EN (1 << 0) + +#define IDMAC_DES0_DIC (1 << 1) +#define IDMAC_DES0_LD (1 << 2) +#define IDMAC_DES0_FS (1 << 3) +#define IDMAC_DES0_CH (1 << 4) +#define IDMAC_DES0_ER (1 << 5) +#define IDMAC_DES0_CES (1 << 30) +#define IDMAC_DES0_OWN (U(1) << 31) +#define IDMAC_DES1_BS1(x) ((x) & 0x1fff) +#define IDMAC_DES2_BS2(x) (((x) & 0x1fff) << 13) + +#define DWMMC_DMA_MAX_BUFFER_SIZE (512 * 8) + +#define DWMMC_8BIT_MODE (1 << 6) + +#define DWMMC_ADDRESS_MASK U(0x0f) + +#define TIMEOUT 100000 + +struct dw_idmac_desc { + unsigned int des0; + unsigned int des1; + unsigned int des2; + unsigned int des3; +}; + +static void dw_init(void); +static int dw_send_cmd(struct mmc_cmd *cmd); +static int dw_set_ios(unsigned int clk, unsigned int width); +static int dw_prepare(int lba, uintptr_t buf, size_t size); +static int dw_read(int lba, uintptr_t buf, size_t size); +static int dw_write(int lba, uintptr_t buf, size_t size); + +static const struct mmc_ops dw_mmc_ops = { + .init = dw_init, + .send_cmd = dw_send_cmd, + .set_ios = dw_set_ios, + .prepare = dw_prepare, + .read = dw_read, + .write = dw_write, +}; + +static dw_mmc_params_t dw_params; + +static void dw_update_clk(void) +{ + unsigned int data; + + mmio_write_32(dw_params.reg_base + DWMMC_CMD, + CMD_WAIT_PRVDATA_COMPLETE | CMD_UPDATE_CLK_ONLY | + CMD_START); + while (1) { + data = mmio_read_32(dw_params.reg_base + DWMMC_CMD); + if ((data & CMD_START) == 0) + break; + data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS); + assert((data & INT_HLE) == 0); + } +} + +static void dw_set_clk(int clk) +{ + unsigned int data; + int div; + + assert(clk > 0); + + for (div = 1; div < 256; div++) { + if ((dw_params.clk_rate / (2 * div)) <= clk) { + break; + } + } + assert(div < 256); + + /* wait until controller is idle */ + do { + data = mmio_read_32(dw_params.reg_base + DWMMC_STATUS); + } while (data & STATUS_DATA_BUSY); + + /* disable clock before change clock rate */ + mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 0); + dw_update_clk(); + + mmio_write_32(dw_params.reg_base + DWMMC_CLKDIV, div); + dw_update_clk(); + + /* enable clock */ + mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 1); + mmio_write_32(dw_params.reg_base + DWMMC_CLKSRC, 0); + dw_update_clk(); +} + +static void dw_init(void) +{ + unsigned int data; + uintptr_t base; + + assert((dw_params.reg_base & MMC_BLOCK_MASK) == 0); + + base = dw_params.reg_base; + mmio_write_32(base + DWMMC_PWREN, 1); + mmio_write_32(base + DWMMC_CTRL, CTRL_RESET_ALL); + do { + data = mmio_read_32(base + DWMMC_CTRL); + } while (data); + + /* enable DMA in CTRL */ + data = CTRL_INT_EN | CTRL_DMA_EN | CTRL_IDMAC_EN; + mmio_write_32(base + DWMMC_CTRL, data); + mmio_write_32(base + DWMMC_RINTSTS, ~0); + mmio_write_32(base + DWMMC_INTMASK, 0); + mmio_write_32(base + DWMMC_TMOUT, ~0); + mmio_write_32(base + DWMMC_IDINTEN, ~0); + mmio_write_32(base + DWMMC_BLKSIZ, MMC_BLOCK_SIZE); + mmio_write_32(base + DWMMC_BYTCNT, 256 * 1024); + mmio_write_32(base + DWMMC_DEBNCE, 0x00ffffff); + mmio_write_32(base + DWMMC_BMOD, BMOD_SWRESET); + do { + data = mmio_read_32(base + DWMMC_BMOD); + } while (data & BMOD_SWRESET); + /* enable DMA in BMOD */ + data |= BMOD_ENABLE | BMOD_FB; + mmio_write_32(base + DWMMC_BMOD, data); + + udelay(100); + dw_set_clk(MMC_BOOT_CLK_RATE); + udelay(100); +} + +static int dw_send_cmd(struct mmc_cmd *cmd) +{ + unsigned int op, data, err_mask; + uintptr_t base; + int timeout; + + assert(cmd); + + base = dw_params.reg_base; + + switch (cmd->cmd_idx) { + case 0: + op = CMD_SEND_INIT; + break; + case 12: + op = CMD_STOP_ABORT_CMD; + break; + case 13: + op = CMD_WAIT_PRVDATA_COMPLETE; + break; + case 8: + if (dw_params.mmc_dev_type == MMC_IS_EMMC) + op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE; + else + op = CMD_WAIT_PRVDATA_COMPLETE; + break; + case 17: + case 18: + op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE; + break; + case 24: + case 25: + op = CMD_WRITE | CMD_DATA_TRANS_EXPECT | + CMD_WAIT_PRVDATA_COMPLETE; + break; + case 51: + op = CMD_DATA_TRANS_EXPECT; + break; + default: + op = 0; + break; + } + op |= CMD_USE_HOLD_REG | CMD_START; + switch (cmd->resp_type) { + case 0: + break; + case MMC_RESPONSE_R2: + op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC | + CMD_RESP_LEN; + break; + case MMC_RESPONSE_R3: + op |= CMD_RESP_EXPECT; + break; + default: + op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC; + break; + } + timeout = TIMEOUT; + do { + data = mmio_read_32(base + DWMMC_STATUS); + if (--timeout <= 0) + panic(); + } while (data & STATUS_DATA_BUSY); + + mmio_write_32(base + DWMMC_RINTSTS, ~0); + mmio_write_32(base + DWMMC_CMDARG, cmd->cmd_arg); + mmio_write_32(base + DWMMC_CMD, op | cmd->cmd_idx); + + err_mask = INT_EBE | INT_HLE | INT_RTO | INT_RCRC | INT_RE | + INT_DCRC | INT_DRT | INT_SBE; + timeout = TIMEOUT; + do { + udelay(500); + data = mmio_read_32(base + DWMMC_RINTSTS); + + if (data & err_mask) + return -EIO; + if (data & INT_DTO) + break; + if (--timeout == 0) { + ERROR("%s, RINTSTS:0x%x\n", __func__, data); + panic(); + } + } while (!(data & INT_CMD_DONE)); + + if (op & CMD_RESP_EXPECT) { + cmd->resp_data[0] = mmio_read_32(base + DWMMC_RESP0); + if (op & CMD_RESP_LEN) { + cmd->resp_data[1] = mmio_read_32(base + DWMMC_RESP1); + cmd->resp_data[2] = mmio_read_32(base + DWMMC_RESP2); + cmd->resp_data[3] = mmio_read_32(base + DWMMC_RESP3); + } + } + return 0; +} + +static int dw_set_ios(unsigned int clk, unsigned int width) +{ + switch (width) { + case MMC_BUS_WIDTH_1: + mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_1BIT); + break; + case MMC_BUS_WIDTH_4: + mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_4BIT); + break; + case MMC_BUS_WIDTH_8: + mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_8BIT); + break; + default: + assert(0); + break; + } + dw_set_clk(clk); + return 0; +} + +static int dw_prepare(int lba, uintptr_t buf, size_t size) +{ + struct dw_idmac_desc *desc; + int desc_cnt, i, last; + uintptr_t base; + + assert(((buf & DWMMC_ADDRESS_MASK) == 0) && + (dw_params.desc_size > 0) && + ((dw_params.reg_base & MMC_BLOCK_MASK) == 0) && + ((dw_params.desc_base & MMC_BLOCK_MASK) == 0) && + ((dw_params.desc_size & MMC_BLOCK_MASK) == 0)); + + flush_dcache_range(buf, size); + + desc_cnt = (size + DWMMC_DMA_MAX_BUFFER_SIZE - 1) / + DWMMC_DMA_MAX_BUFFER_SIZE; + assert(desc_cnt * sizeof(struct dw_idmac_desc) < dw_params.desc_size); + + base = dw_params.reg_base; + desc = (struct dw_idmac_desc *)dw_params.desc_base; + mmio_write_32(base + DWMMC_BYTCNT, size); + + if (size < MMC_BLOCK_SIZE) + mmio_write_32(base + DWMMC_BLKSIZ, size); + else + mmio_write_32(base + DWMMC_BLKSIZ, MMC_BLOCK_SIZE); + + mmio_write_32(base + DWMMC_RINTSTS, ~0); + for (i = 0; i < desc_cnt; i++) { + desc[i].des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | IDMAC_DES0_DIC; + desc[i].des1 = IDMAC_DES1_BS1(DWMMC_DMA_MAX_BUFFER_SIZE); + desc[i].des2 = buf + DWMMC_DMA_MAX_BUFFER_SIZE * i; + desc[i].des3 = dw_params.desc_base + + (sizeof(struct dw_idmac_desc)) * (i + 1); + } + /* first descriptor */ + desc->des0 |= IDMAC_DES0_FS; + /* last descriptor */ + last = desc_cnt - 1; + (desc + last)->des0 |= IDMAC_DES0_LD; + (desc + last)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH); + (desc + last)->des1 = IDMAC_DES1_BS1(size - (last * + DWMMC_DMA_MAX_BUFFER_SIZE)); + /* set next descriptor address as 0 */ + (desc + last)->des3 = 0; + + mmio_write_32(base + DWMMC_DBADDR, dw_params.desc_base); + flush_dcache_range(dw_params.desc_base, + desc_cnt * DWMMC_DMA_MAX_BUFFER_SIZE); + + + return 0; +} + +static int dw_read(int lba, uintptr_t buf, size_t size) +{ + uint32_t data = 0; + int timeout = TIMEOUT; + + do { + data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS); + udelay(50); + } while (!(data & INT_DTO) && timeout-- > 0); + + inv_dcache_range(buf, size); + + return 0; +} + +static int dw_write(int lba, uintptr_t buf, size_t size) +{ + return 0; +} + +void dw_mmc_init(dw_mmc_params_t *params, struct mmc_device_info *info) +{ + assert((params != 0) && + ((params->reg_base & MMC_BLOCK_MASK) == 0) && + ((params->desc_base & MMC_BLOCK_MASK) == 0) && + ((params->desc_size & MMC_BLOCK_MASK) == 0) && + (params->desc_size > 0) && + (params->clk_rate > 0) && + ((params->bus_width == MMC_BUS_WIDTH_1) || + (params->bus_width == MMC_BUS_WIDTH_4) || + (params->bus_width == MMC_BUS_WIDTH_8))); + + memcpy(&dw_params, params, sizeof(dw_mmc_params_t)); + dw_params.mmc_dev_type = info->mmc_dev_type; + mmc_init(&dw_mmc_ops, params->clk_rate, params->bus_width, + params->flags, info); +} diff --git a/arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c b/arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c new file mode 100644 index 0000000..6bed981 --- /dev/null +++ b/arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +static int dwufs_phy_init(ufs_params_t *params) +{ + uintptr_t base; + unsigned int fsm0, fsm1; + unsigned int data; + int result; + + assert((params != NULL) && (params->reg_base != 0)); + + base = params->reg_base; + + /* Unipro VS_MPHY disable */ + ufshc_dme_set(VS_MPHY_DISABLE_OFFSET, 0, VS_MPHY_DISABLE_MPHYDIS); + ufshc_dme_set(PA_HS_SERIES_OFFSET, 0, 2); + /* MPHY CBRATESEL */ + ufshc_dme_set(0x8114, 0, 1); + /* MPHY CBOVRCTRL2 */ + ufshc_dme_set(0x8121, 0, 0x2d); + /* MPHY CBOVRCTRL3 */ + ufshc_dme_set(0x8122, 0, 0x1); + ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1); + + /* MPHY RXOVRCTRL4 rx0 */ + ufshc_dme_set(0x800d, 4, 0x58); + /* MPHY RXOVRCTRL4 rx1 */ + ufshc_dme_set(0x800d, 5, 0x58); + /* MPHY RXOVRCTRL5 rx0 */ + ufshc_dme_set(0x800e, 4, 0xb); + /* MPHY RXOVRCTRL5 rx1 */ + ufshc_dme_set(0x800e, 5, 0xb); + /* MPHY RXSQCONTROL rx0 */ + ufshc_dme_set(0x8009, 4, 0x1); + /* MPHY RXSQCONTROL rx1 */ + ufshc_dme_set(0x8009, 5, 0x1); + ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1); + + ufshc_dme_set(0x8113, 0, 0x1); + ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1); + + ufshc_dme_set(RX_HS_G3_SYNC_LENGTH_CAP_OFFSET, 4, 0x4a); + ufshc_dme_set(RX_HS_G3_SYNC_LENGTH_CAP_OFFSET, 5, 0x4a); + ufshc_dme_set(RX_HS_G2_SYNC_LENGTH_CAP_OFFSET, 4, 0x4a); + ufshc_dme_set(RX_HS_G2_SYNC_LENGTH_CAP_OFFSET, 5, 0x4a); + ufshc_dme_set(RX_MIN_ACTIVATETIME_CAP_OFFSET, 4, 0x7); + ufshc_dme_set(RX_MIN_ACTIVATETIME_CAP_OFFSET, 5, 0x7); + ufshc_dme_set(TX_HIBERN8TIME_CAP_OFFSET, 0, 0x5); + ufshc_dme_set(TX_HIBERN8TIME_CAP_OFFSET, 1, 0x5); + ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1); + + result = ufshc_dme_get(VS_MPHY_DISABLE_OFFSET, 0, &data); + assert((result == 0) && (data == VS_MPHY_DISABLE_MPHYDIS)); + /* enable Unipro VS MPHY */ + ufshc_dme_set(VS_MPHY_DISABLE_OFFSET, 0, 0); + + while (1) { + result = ufshc_dme_get(TX_FSM_STATE_OFFSET, 0, &fsm0); + assert(result == 0); + result = ufshc_dme_get(TX_FSM_STATE_OFFSET, 1, &fsm1); + assert(result == 0); + if ((fsm0 == TX_FSM_STATE_HIBERN8) && + (fsm1 == TX_FSM_STATE_HIBERN8)) + break; + } + + mmio_write_32(base + HCLKDIV, 0xE4); + mmio_clrbits_32(base + AHIT, 0x3FF); + + ufshc_dme_set(PA_LOCAL_TX_LCC_ENABLE_OFFSET, 0, 0); + ufshc_dme_set(VS_MK2_EXTN_SUPPORT_OFFSET, 0, 0); + + result = ufshc_dme_get(VS_MK2_EXTN_SUPPORT_OFFSET, 0, &data); + assert((result == 0) && (data == 0)); + + ufshc_dme_set(DL_AFC0_CREDIT_THRESHOLD_OFFSET, 0, 0); + ufshc_dme_set(DL_TC0_OUT_ACK_THRESHOLD_OFFSET, 0, 0); + ufshc_dme_set(DL_TC0_TX_FC_THRESHOLD_OFFSET, 0, 9); + (void)result; + return 0; +} + +static int dwufs_phy_set_pwr_mode(ufs_params_t *params) +{ + int result; + unsigned int data, tx_lanes, rx_lanes; + uintptr_t base; + unsigned int flags; + + assert((params != NULL) && (params->reg_base != 0)); + + base = params->reg_base; + flags = params->flags; + if ((flags & UFS_FLAGS_VENDOR_SKHYNIX) != 0U) { + NOTICE("ufs: H**** device must set VS_DebugSaveConfigTime 0x10\n"); + /* VS_DebugSaveConfigTime */ + result = ufshc_dme_set(0xd0a0, 0x0, 0x10); + assert(result == 0); + /* sync length */ + result = ufshc_dme_set(0x1556, 0x0, 0x48); + assert(result == 0); + } + + result = ufshc_dme_get(PA_TACTIVATE_OFFSET, 0, &data); + assert(result == 0); + if (data < 7) { + result = ufshc_dme_set(PA_TACTIVATE_OFFSET, 0, 7); + assert(result == 0); + } + result = ufshc_dme_get(PA_CONNECTED_TX_DATA_LANES_OFFSET, 0, &tx_lanes); + assert(result == 0); + result = ufshc_dme_get(PA_CONNECTED_RX_DATA_LANES_OFFSET, 0, &rx_lanes); + assert(result == 0); + + result = ufshc_dme_set(PA_TX_SKIP_OFFSET, 0, 0); + assert(result == 0); + result = ufshc_dme_set(PA_TX_GEAR_OFFSET, 0, 3); + assert(result == 0); + result = ufshc_dme_set(PA_RX_GEAR_OFFSET, 0, 3); + assert(result == 0); + result = ufshc_dme_set(PA_HS_SERIES_OFFSET, 0, 2); + assert(result == 0); + result = ufshc_dme_set(PA_TX_TERMINATION_OFFSET, 0, 1); + assert(result == 0); + result = ufshc_dme_set(PA_RX_TERMINATION_OFFSET, 0, 1); + assert(result == 0); + result = ufshc_dme_set(PA_SCRAMBLING_OFFSET, 0, 0); + assert(result == 0); + result = ufshc_dme_set(PA_ACTIVE_TX_DATA_LANES_OFFSET, 0, tx_lanes); + assert(result == 0); + result = ufshc_dme_set(PA_ACTIVE_RX_DATA_LANES_OFFSET, 0, rx_lanes); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA0_OFFSET, 0, 8191); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA1_OFFSET, 0, 65535); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA2_OFFSET, 0, 32767); + assert(result == 0); + result = ufshc_dme_set(DME_FC0_PROTECTION_TIMEOUT_OFFSET, 0, 8191); + assert(result == 0); + result = ufshc_dme_set(DME_TC0_REPLAY_TIMEOUT_OFFSET, 0, 65535); + assert(result == 0); + result = ufshc_dme_set(DME_AFC0_REQ_TIMEOUT_OFFSET, 0, 32767); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA3_OFFSET, 0, 8191); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA4_OFFSET, 0, 65535); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA5_OFFSET, 0, 32767); + assert(result == 0); + result = ufshc_dme_set(DME_FC1_PROTECTION_TIMEOUT_OFFSET, 0, 8191); + assert(result == 0); + result = ufshc_dme_set(DME_TC1_REPLAY_TIMEOUT_OFFSET, 0, 65535); + assert(result == 0); + result = ufshc_dme_set(DME_AFC1_REQ_TIMEOUT_OFFSET, 0, 32767); + assert(result == 0); + + result = ufshc_dme_set(PA_PWR_MODE_OFFSET, 0, 0x11); + assert(result == 0); + do { + data = mmio_read_32(base + IS); + } while ((data & UFS_INT_UPMS) == 0); + mmio_write_32(base + IS, UFS_INT_UPMS); + data = mmio_read_32(base + HCS); + if ((data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL) + INFO("ufs: change power mode success\n"); + else + WARN("ufs: HCS.UPMCRS error, HCS:0x%x\n", data); + (void)result; + return 0; +} + +static const ufs_ops_t dw_ufs_ops = { + .phy_init = dwufs_phy_init, + .phy_set_pwr_mode = dwufs_phy_set_pwr_mode, +}; + +int dw_ufs_init(dw_ufs_params_t *params) +{ + ufs_params_t ufs_params; + + memset(&ufs_params, 0, sizeof(ufs_params)); + ufs_params.reg_base = params->reg_base; + ufs_params.desc_base = params->desc_base; + ufs_params.desc_size = params->desc_size; + ufs_params.flags = params->flags; + ufs_init(&dw_ufs_ops, &ufs_params); + return 0; +} diff --git a/arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S b/arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S new file mode 100644 index 0000000..0429f87 --- /dev/null +++ b/arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_16550_core_init + .globl console_16550_core_putc + .globl console_16550_core_getc + .globl console_16550_core_flush + + .globl console_16550_putc + .globl console_16550_getc + .globl console_16550_flush + + /* ----------------------------------------------- + * int console_16550_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: r0 - console base address + * r1 - Uart clock in Hz + * r2 - Baud rate + * Out: return 1 on success, 0 on error + * Clobber list : r1, r2, r3 + * ----------------------------------------------- + */ +func console_16550_core_init + /* Check the input base address */ + cmp r0, #0 + beq init_fail + /* Check baud rate and uart clock for sanity */ + cmp r1, #0 + beq init_fail + cmp r2, #0 + beq init_fail + + /* Program the baudrate */ + /* Divisor = Uart clock / (16 * baudrate) */ + lsl r2, r2, #4 + udiv r2, r1, r2 + and r1, r2, #0xff /* w1 = DLL */ + lsr r2, r2, #8 + and r2, r2, #0xff /* w2 = DLLM */ + ldr r3, [r0, #UARTLCR] + orr r3, r3, #UARTLCR_DLAB + str r3, [r0, #UARTLCR] /* enable DLL, DLLM programming */ + str r1, [r0, #UARTDLL] /* program DLL */ + str r2, [r0, #UARTDLLM] /* program DLLM */ + mov r2, #~UARTLCR_DLAB + and r3, r3, r2 + str r3, [r0, #UARTLCR] /* disable DLL, DLLM programming */ + + /* 8n1 */ + mov r3, #3 + str r3, [r0, #UARTLCR] + /* no interrupt */ + mov r3, #0 + str r3, [r0, #UARTIER] +#ifdef TI_16550_MDR_QUIRK + /* UART must be enabled on some platforms via the MDR register */ + str r3, [r0, #UARTMDR1] +#endif /* TI_16550_MDR_QUIRK */ + /* enable fifo, DMA */ + mov r3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN) + str r3, [r0, #UARTFCR] + /* DTR + RTS */ + mov r3, #3 + str r3, [r0, #UARTMCR] + mov r0, #1 + bx lr +init_fail: + mov r0, #0 + bx lr +endfunc console_16550_core_init + + .globl console_16550_register + + /* ------------------------------------------------------- + * int console_16550_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new 16550 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * If r1 (UART clock) is 0, initialisation will be + * skipped, relying on previous code to have done + * this already. r2 is ignored then as well. + * In: r0 - UART register base address + * r1 - UART clock in Hz + * r2 - Baud rate (ignored if r1 is 0) + * r3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : r0, r1, r2 + * ------------------------------------------------------- + */ +func console_16550_register + push {r4, lr} + mov r4, r3 + cmp r4, #0 + beq register_fail + str r0, [r4, #CONSOLE_T_BASE] + + /* A clock rate of zero means to skip the initialisation. */ + cmp r1, #0 + beq register_16550 + + bl console_16550_core_init + cmp r0, #0 + beq register_fail + +register_16550: + mov r0, r4 + pop {r4, lr} + finish_console_register 16550 putc=1, getc=1, flush=1 + +register_fail: + pop {r4, pc} +endfunc console_16550_register + + /* -------------------------------------------------------- + * int console_16550_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +func console_16550_core_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp r0, #0xA + bne 2f + /* Check if the transmit FIFO is full */ +1: ldr r2, [r1, #UARTLSR] + and r2, r2, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp r2, #(UARTLSR_TEMT | UARTLSR_THRE) + bne 1b + mov r2, #0xD /* '\r' */ + str r2, [r1, #UARTTX] + + /* Check if the transmit FIFO is full */ +2: ldr r2, [r1, #UARTLSR] + and r2, r2, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp r2, #(UARTLSR_TEMT | UARTLSR_THRE) + bne 2b + str r0, [r1, #UARTTX] + bx lr +endfunc console_16550_core_putc + + /* -------------------------------------------------------- + * int console_16550_putc(int c, console_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : r0 - character to be printed + * r1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +func console_16550_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r1, [r1, #CONSOLE_T_BASE] + b console_16550_core_putc +endfunc console_16550_putc + + /* --------------------------------------------- + * int console_16550_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : r0 - console base address + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_16550_core_getc +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ +1: ldr r1, [r0, #UARTLSR] + tst r1, #UARTLSR_RDR_BIT + beq no_char + ldr r1, [r0, #UARTRX] + mov r0, r1 + bx lr +no_char: + mov r0, #ERROR_NO_PENDING_CHAR + bx lr +endfunc console_16550_core_getc + + /* --------------------------------------------- + * int console_16550_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : r0 - pointer to console_t stucture + * Out : r0 - character if available, else -1 + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_16550_getc +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_16550_core_getc +endfunc console_16550_getc + + /* --------------------------------------------- + * void console_16550_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - console base address + * Out : void. + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_16550_core_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Loop until the transmit FIFO is empty */ +1: ldr r1, [r0, #UARTLSR] + and r1, r1, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp r1, #(UARTLSR_TEMT | UARTLSR_THRE) + bne 1b + + bx lr +endfunc console_16550_core_flush + + /* --------------------------------------------- + * void console_16550_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - pointer to console_t structure + * Out : void + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_16550_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_16550_core_flush +endfunc console_16550_flush diff --git a/arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S b/arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S new file mode 100644 index 0000000..cb21512 --- /dev/null +++ b/arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_16550_core_init + .globl console_16550_core_putc + .globl console_16550_core_getc + .globl console_16550_core_flush + + .globl console_16550_putc + .globl console_16550_getc + .globl console_16550_flush + + /* ----------------------------------------------- + * int console_16550_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success, 0 on error + * Clobber list : x1, x2, x3 + * ----------------------------------------------- + */ +func console_16550_core_init + /* Check the input base address */ + cbz x0, init_fail + /* Check baud rate and uart clock for sanity */ + cbz w1, init_fail + cbz w2, init_fail + + /* Program the baudrate */ + /* Divisor = Uart clock / (16 * baudrate) */ + lsl w2, w2, #4 + udiv w2, w1, w2 + and w1, w2, #0xff /* w1 = DLL */ + lsr w2, w2, #8 + and w2, w2, #0xff /* w2 = DLLM */ + ldr w3, [x0, #UARTLCR] + orr w3, w3, #UARTLCR_DLAB + str w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */ + str w1, [x0, #UARTDLL] /* program DLL */ + str w2, [x0, #UARTDLLM] /* program DLLM */ + mov w2, #~UARTLCR_DLAB + and w3, w3, w2 + str w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */ + + /* 8n1 */ + mov w3, #3 + str w3, [x0, #UARTLCR] + /* no interrupt */ + mov w3, #0 + str w3, [x0, #UARTIER] +#ifdef TI_16550_MDR_QUIRK + /* UART must be enabled on some platforms via the MDR register */ + str w3, [x0, #UARTMDR1] +#endif /* TI_16550_MDR_QUIRK */ + /* enable fifo, DMA */ + mov w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN) + str w3, [x0, #UARTFCR] + /* DTR + RTS */ + mov w3, #3 + str w3, [x0, #UARTMCR] + mov w0, #1 + ret +init_fail: + mov w0, #0 + ret +endfunc console_16550_core_init + + .globl console_16550_register + + /* ----------------------------------------------- + * int console_16550_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new 16550 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * If w1 (UART clock) is 0, initialisation will be + * skipped, relying on previous code to have done + * this already. w2 is ignored then as well. + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate (ignored if w1 is 0) + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_16550_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + /* A clock rate of zero means to skip the initialisation. */ + cbz w1, register_16550 + + bl console_16550_core_init + cbz x0, register_fail + +register_16550: + mov x0, x6 + mov x30, x7 + finish_console_register 16550 putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_16550_register + + /* -------------------------------------------------------- + * int console_16550_core_putc(int c, uintptr_t base_addr) + * 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 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_16550_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f + /* Check if the transmit FIFO is full */ +1: ldr w2, [x1, #UARTLSR] + and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE) + b.ne 1b + mov w2, #0xD /* '\r' */ + str w2, [x1, #UARTTX] + + /* Check if the transmit FIFO is full */ +2: ldr w2, [x1, #UARTLSR] + and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE) + b.ne 2b + str w0, [x1, #UARTTX] + ret +endfunc console_16550_core_putc + + /* -------------------------------------------------------- + * int console_16550_putc(int c, console_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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_16550_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_BASE] + b console_16550_core_putc +endfunc console_16550_putc + + /* --------------------------------------------- + * int console_16550_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - console base address + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ +1: ldr w1, [x0, #UARTLSR] + tbz w1, #UARTLSR_RDR_BIT, no_char + ldr w0, [x0, #UARTRX] + ret +no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_16550_core_getc + + /* --------------------------------------------- + * int console_16550_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - pointer to console_t stucture + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_getc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_16550_core_getc +endfunc console_16550_getc + + /* --------------------------------------------- + * void console_16550_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Loop until the transmit FIFO is empty */ +1: ldr w1, [x0, #UARTLSR] + and w1, w1, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp w1, #(UARTLSR_TEMT | UARTLSR_THRE) + b.ne 1b + + ret +endfunc console_16550_core_flush + + /* --------------------------------------------- + * void console_16550_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_16550_core_flush +endfunc console_16550_flush diff --git a/arm-trusted-firmware/drivers/ufs/ufs.c b/arm-trusted-firmware/drivers/ufs/ufs.c new file mode 100644 index 0000000..3c27aff --- /dev/null +++ b/arm-trusted-firmware/drivers/ufs/ufs.c @@ -0,0 +1,839 @@ +/* + * Copyright (c) 2017-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 + +#define CDB_ADDR_MASK 127 +#define ALIGN_CDB(x) (((x) + CDB_ADDR_MASK) & ~CDB_ADDR_MASK) +#define ALIGN_8(x) (((x) + 7) & ~7) + +#define UFS_DESC_SIZE 0x400 +#define MAX_UFS_DESC_SIZE 0x8000 /* 32 descriptors */ + +#define MAX_PRDT_SIZE 0x40000 /* 256KB */ + +static ufs_params_t ufs_params; +static int nutrs; /* Number of UTP Transfer Request Slots */ + +int ufshc_send_uic_cmd(uintptr_t base, uic_cmd_t *cmd) +{ + unsigned int data; + + if (base == 0 || cmd == NULL) + return -EINVAL; + + data = mmio_read_32(base + HCS); + if ((data & HCS_UCRDY) == 0) + return -EBUSY; + mmio_write_32(base + IS, ~0); + mmio_write_32(base + UCMDARG1, cmd->arg1); + mmio_write_32(base + UCMDARG2, cmd->arg2); + mmio_write_32(base + UCMDARG3, cmd->arg3); + mmio_write_32(base + UICCMD, cmd->op); + + do { + data = mmio_read_32(base + IS); + } while ((data & UFS_INT_UCCS) == 0); + mmio_write_32(base + IS, UFS_INT_UCCS); + return mmio_read_32(base + UCMDARG2) & CONFIG_RESULT_CODE_MASK; +} + +int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val) +{ + uintptr_t base; + unsigned int data; + int result, retries; + uic_cmd_t cmd; + + assert(ufs_params.reg_base != 0); + + if (val == NULL) + return -EINVAL; + + base = ufs_params.reg_base; + for (retries = 0; retries < 100; retries++) { + data = mmio_read_32(base + HCS); + if ((data & HCS_UCRDY) != 0) + break; + mdelay(1); + } + if (retries >= 100) + return -EBUSY; + + cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx); + cmd.arg2 = 0; + cmd.arg3 = 0; + cmd.op = DME_GET; + for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) { + result = ufshc_send_uic_cmd(base, &cmd); + if (result == 0) + break; + data = mmio_read_32(base + IS); + if (data & UFS_INT_UE) + return -EINVAL; + } + if (retries >= UFS_UIC_COMMAND_RETRIES) + return -EIO; + + *val = mmio_read_32(base + UCMDARG3); + return 0; +} + +int ufshc_dme_set(unsigned int attr, unsigned int idx, unsigned int val) +{ + uintptr_t base; + unsigned int data; + int result, retries; + uic_cmd_t cmd; + + assert((ufs_params.reg_base != 0)); + + base = ufs_params.reg_base; + cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx); + cmd.arg2 = 0; + cmd.arg3 = val; + cmd.op = DME_SET; + + for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) { + result = ufshc_send_uic_cmd(base, &cmd); + if (result == 0) + break; + data = mmio_read_32(base + IS); + if (data & UFS_INT_UE) + return -EINVAL; + } + if (retries >= UFS_UIC_COMMAND_RETRIES) + return -EIO; + + return 0; +} + +static int ufshc_hce_enable(uintptr_t base) +{ + unsigned int data; + int retries; + + /* Enable Host Controller */ + mmio_write_32(base + HCE, HCE_ENABLE); + + /* Wait until basic initialization sequence completed */ + for (retries = 0; retries < HCE_ENABLE_INNER_RETRIES; ++retries) { + data = mmio_read_32(base + HCE); + if (data & HCE_ENABLE) { + break; + } + udelay(HCE_ENABLE_TIMEOUT_US); + } + if (retries >= HCE_ENABLE_INNER_RETRIES) { + return -ETIMEDOUT; + } + + return 0; +} + +static int ufshc_reset(uintptr_t base) +{ + unsigned int data; + int retries, result; + + for (retries = 0; retries < HCE_ENABLE_OUTER_RETRIES; ++retries) { + result = ufshc_hce_enable(base); + if (result == 0) { + break; + } + } + if (retries >= HCE_ENABLE_OUTER_RETRIES) { + return -EIO; + } + + /* Enable Interrupts */ + data = UFS_INT_UCCS | UFS_INT_ULSS | UFS_INT_UE | UFS_INT_UTPES | + UFS_INT_DFES | UFS_INT_HCFES | UFS_INT_SBFES; + mmio_write_32(base + IE, data); + + return 0; +} + +static int ufshc_dme_link_startup(uintptr_t base) +{ + uic_cmd_t cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op = DME_LINKSTARTUP; + return ufshc_send_uic_cmd(base, &cmd); +} + +static int ufshc_link_startup(uintptr_t base) +{ + int data, result; + int retries; + + for (retries = DME_LINKSTARTUP_RETRIES; retries > 0; retries--) { + result = ufshc_dme_link_startup(base); + if (result != 0) { + /* Reset controller before trying again */ + result = ufshc_reset(base); + if (result != 0) { + return result; + } + continue; + } + while ((mmio_read_32(base + HCS) & HCS_DP) == 0) + ; + data = mmio_read_32(base + IS); + if (data & UFS_INT_ULSS) + mmio_write_32(base + IS, UFS_INT_ULSS); + return 0; + } + return -EIO; +} + +/* Check Door Bell register to get an empty slot */ +static int get_empty_slot(int *slot) +{ + unsigned int data; + int i; + + data = mmio_read_32(ufs_params.reg_base + UTRLDBR); + for (i = 0; i < nutrs; i++) { + if ((data & 1) == 0) + break; + data = data >> 1; + } + if (i >= nutrs) + return -EBUSY; + *slot = i; + return 0; +} + +static void get_utrd(utp_utrd_t *utrd) +{ + uintptr_t base; + int slot = 0, result; + utrd_header_t *hd; + + assert(utrd != NULL); + result = get_empty_slot(&slot); + assert(result == 0); + + /* clear utrd */ + memset((void *)utrd, 0, sizeof(utp_utrd_t)); + base = ufs_params.desc_base + (slot * UFS_DESC_SIZE); + /* clear the descriptor */ + memset((void *)base, 0, UFS_DESC_SIZE); + + utrd->header = base; + utrd->task_tag = slot + 1; + /* CDB address should be aligned with 128 bytes */ + utrd->upiu = ALIGN_CDB(utrd->header + sizeof(utrd_header_t)); + utrd->resp_upiu = ALIGN_8(utrd->upiu + sizeof(cmd_upiu_t)); + utrd->size_upiu = utrd->resp_upiu - utrd->upiu; + utrd->size_resp_upiu = ALIGN_8(sizeof(resp_upiu_t)); + utrd->prdt = utrd->resp_upiu + utrd->size_resp_upiu; + + hd = (utrd_header_t *)utrd->header; + hd->ucdba = utrd->upiu & UINT32_MAX; + hd->ucdbau = (utrd->upiu >> 32) & UINT32_MAX; + /* Both RUL and RUO is based on DWORD */ + hd->rul = utrd->size_resp_upiu >> 2; + hd->ruo = utrd->size_upiu >> 2; + (void)result; +} + +/* + * Prepare UTRD, Command UPIU, Response UPIU. + */ +static int ufs_prepare_cmd(utp_utrd_t *utrd, uint8_t op, uint8_t lun, + int lba, uintptr_t buf, size_t length) +{ + utrd_header_t *hd; + cmd_upiu_t *upiu; + prdt_t *prdt; + unsigned int ulba; + unsigned int lba_cnt; + int prdt_size; + + + mmio_write_32(ufs_params.reg_base + UTRLBA, + utrd->header & UINT32_MAX); + mmio_write_32(ufs_params.reg_base + UTRLBAU, + (utrd->upiu >> 32) & UINT32_MAX); + + hd = (utrd_header_t *)utrd->header; + upiu = (cmd_upiu_t *)utrd->upiu; + + hd->i = 1; + hd->ct = CT_UFS_STORAGE; + hd->ocs = OCS_MASK; + + upiu->trans_type = CMD_UPIU; + upiu->task_tag = utrd->task_tag; + upiu->cdb[0] = op; + ulba = (unsigned int)lba; + lba_cnt = (unsigned int)(length >> UFS_BLOCK_SHIFT); + switch (op) { + case CDBCMD_TEST_UNIT_READY: + break; + case CDBCMD_READ_CAPACITY_10: + hd->dd = DD_OUT; + upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S; + upiu->lun = lun; + break; + case CDBCMD_READ_10: + hd->dd = DD_OUT; + upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S; + upiu->lun = lun; + upiu->cdb[1] = RW_WITHOUT_CACHE; + /* set logical block address */ + upiu->cdb[2] = (ulba >> 24) & 0xff; + upiu->cdb[3] = (ulba >> 16) & 0xff; + upiu->cdb[4] = (ulba >> 8) & 0xff; + upiu->cdb[5] = ulba & 0xff; + /* set transfer length */ + upiu->cdb[7] = (lba_cnt >> 8) & 0xff; + upiu->cdb[8] = lba_cnt & 0xff; + break; + case CDBCMD_WRITE_10: + hd->dd = DD_IN; + upiu->flags = UPIU_FLAGS_W | UPIU_FLAGS_ATTR_S; + upiu->lun = lun; + upiu->cdb[1] = RW_WITHOUT_CACHE; + /* set logical block address */ + upiu->cdb[2] = (ulba >> 24) & 0xff; + upiu->cdb[3] = (ulba >> 16) & 0xff; + upiu->cdb[4] = (ulba >> 8) & 0xff; + upiu->cdb[5] = ulba & 0xff; + /* set transfer length */ + upiu->cdb[7] = (lba_cnt >> 8) & 0xff; + upiu->cdb[8] = lba_cnt & 0xff; + break; + default: + assert(0); + break; + } + if (hd->dd == DD_IN) + flush_dcache_range(buf, length); + else if (hd->dd == DD_OUT) + inv_dcache_range(buf, length); + if (length) { + upiu->exp_data_trans_len = htobe32(length); + assert(lba_cnt <= UINT16_MAX); + prdt = (prdt_t *)utrd->prdt; + + prdt_size = 0; + while (length > 0) { + prdt->dba = (unsigned int)(buf & UINT32_MAX); + prdt->dbau = (unsigned int)((buf >> 32) & UINT32_MAX); + /* prdt->dbc counts from 0 */ + if (length > MAX_PRDT_SIZE) { + prdt->dbc = MAX_PRDT_SIZE - 1; + length = length - MAX_PRDT_SIZE; + } else { + prdt->dbc = length - 1; + length = 0; + } + buf += MAX_PRDT_SIZE; + prdt++; + prdt_size += sizeof(prdt_t); + } + utrd->size_prdt = ALIGN_8(prdt_size); + hd->prdtl = utrd->size_prdt >> 2; + hd->prdto = (utrd->size_upiu + utrd->size_resp_upiu) >> 2; + } + + flush_dcache_range((uintptr_t)utrd, sizeof(utp_utrd_t)); + flush_dcache_range((uintptr_t)utrd->header, UFS_DESC_SIZE); + return 0; +} + +static int ufs_prepare_query(utp_utrd_t *utrd, uint8_t op, uint8_t idn, + uint8_t index, uint8_t sel, + uintptr_t buf, size_t length) +{ + utrd_header_t *hd; + query_upiu_t *query_upiu; + + + hd = (utrd_header_t *)utrd->header; + query_upiu = (query_upiu_t *)utrd->upiu; + + mmio_write_32(ufs_params.reg_base + UTRLBA, + utrd->header & UINT32_MAX); + mmio_write_32(ufs_params.reg_base + UTRLBAU, + (utrd->header >> 32) & UINT32_MAX); + + + hd->i = 1; + hd->ct = CT_UFS_STORAGE; + hd->ocs = OCS_MASK; + + query_upiu->trans_type = QUERY_REQUEST_UPIU; + query_upiu->task_tag = utrd->task_tag; + query_upiu->ts.desc.opcode = op; + query_upiu->ts.desc.idn = idn; + query_upiu->ts.desc.index = index; + query_upiu->ts.desc.selector = sel; + switch (op) { + case QUERY_READ_DESC: + query_upiu->query_func = QUERY_FUNC_STD_READ; + query_upiu->ts.desc.length = htobe16(length); + break; + case QUERY_WRITE_DESC: + query_upiu->query_func = QUERY_FUNC_STD_WRITE; + query_upiu->ts.desc.length = htobe16(length); + memcpy((void *)(utrd->upiu + sizeof(query_upiu_t)), + (void *)buf, length); + break; + case QUERY_READ_ATTR: + case QUERY_READ_FLAG: + query_upiu->query_func = QUERY_FUNC_STD_READ; + break; + case QUERY_CLEAR_FLAG: + case QUERY_SET_FLAG: + query_upiu->query_func = QUERY_FUNC_STD_WRITE; + break; + case QUERY_WRITE_ATTR: + query_upiu->query_func = QUERY_FUNC_STD_WRITE; + memcpy((void *)&query_upiu->ts.attr.value, (void *)buf, length); + break; + default: + assert(0); + break; + } + flush_dcache_range((uintptr_t)utrd, sizeof(utp_utrd_t)); + flush_dcache_range((uintptr_t)utrd->header, UFS_DESC_SIZE); + return 0; +} + +static void ufs_prepare_nop_out(utp_utrd_t *utrd) +{ + utrd_header_t *hd; + nop_out_upiu_t *nop_out; + + mmio_write_32(ufs_params.reg_base + UTRLBA, + utrd->header & UINT32_MAX); + mmio_write_32(ufs_params.reg_base + UTRLBAU, + (utrd->header >> 32) & UINT32_MAX); + + hd = (utrd_header_t *)utrd->header; + nop_out = (nop_out_upiu_t *)utrd->upiu; + + hd->i = 1; + hd->ct = CT_UFS_STORAGE; + hd->ocs = OCS_MASK; + + nop_out->trans_type = 0; + nop_out->task_tag = utrd->task_tag; + flush_dcache_range((uintptr_t)utrd, sizeof(utp_utrd_t)); + flush_dcache_range((uintptr_t)utrd->header, UFS_DESC_SIZE); +} + +static void ufs_send_request(int task_tag) +{ + unsigned int data; + int slot; + + slot = task_tag - 1; + /* clear all interrupts */ + mmio_write_32(ufs_params.reg_base + IS, ~0); + + mmio_write_32(ufs_params.reg_base + UTRLRSR, 1); + do { + data = mmio_read_32(ufs_params.reg_base + UTRLRSR); + } while (data == 0); + + data = UTRIACR_IAEN | UTRIACR_CTR | UTRIACR_IACTH(0x1F) | + UTRIACR_IATOVAL(0xFF); + mmio_write_32(ufs_params.reg_base + UTRIACR, data); + /* send request */ + mmio_setbits_32(ufs_params.reg_base + UTRLDBR, 1 << slot); +} + +static int ufs_check_resp(utp_utrd_t *utrd, int trans_type) +{ + utrd_header_t *hd; + resp_upiu_t *resp; + unsigned int data; + int slot; + + hd = (utrd_header_t *)utrd->header; + resp = (resp_upiu_t *)utrd->resp_upiu; + inv_dcache_range((uintptr_t)hd, UFS_DESC_SIZE); + do { + data = mmio_read_32(ufs_params.reg_base + IS); + if ((data & ~(UFS_INT_UCCS | UFS_INT_UTRCS)) != 0) + return -EIO; + } while ((data & UFS_INT_UTRCS) == 0); + slot = utrd->task_tag - 1; + + data = mmio_read_32(ufs_params.reg_base + UTRLDBR); + assert((data & (1 << slot)) == 0); + assert(hd->ocs == OCS_SUCCESS); + assert((resp->trans_type & TRANS_TYPE_CODE_MASK) == trans_type); + (void)resp; + (void)slot; + return 0; +} + +static void ufs_send_cmd(utp_utrd_t *utrd, uint8_t cmd_op, uint8_t lun, int lba, uintptr_t buf, + size_t length) +{ + int result; + + get_utrd(utrd); + + result = ufs_prepare_cmd(utrd, cmd_op, lun, lba, buf, length); + assert(result == 0); + ufs_send_request(utrd->task_tag); + result = ufs_check_resp(utrd, RESPONSE_UPIU); + assert(result == 0); + (void)result; +} + +#ifdef UFS_RESP_DEBUG +static void dump_upiu(utp_utrd_t *utrd) +{ + utrd_header_t *hd; + int i; + + hd = (utrd_header_t *)utrd->header; + INFO("utrd:0x%x, ruo:0x%x, rul:0x%x, ocs:0x%x, UTRLDBR:0x%x\n", + (unsigned int)(uintptr_t)utrd, hd->ruo, hd->rul, hd->ocs, + mmio_read_32(ufs_params.reg_base + UTRLDBR)); + for (i = 0; i < sizeof(utrd_header_t); i += 4) { + INFO("[%lx]:0x%x\n", + (uintptr_t)utrd->header + i, + *(unsigned int *)((uintptr_t)utrd->header + i)); + } + + for (i = 0; i < sizeof(cmd_upiu_t); i += 4) { + INFO("cmd[%lx]:0x%x\n", + utrd->upiu + i, + *(unsigned int *)(utrd->upiu + i)); + } + for (i = 0; i < sizeof(resp_upiu_t); i += 4) { + INFO("resp[%lx]:0x%x\n", + utrd->resp_upiu + i, + *(unsigned int *)(utrd->resp_upiu + i)); + } + for (i = 0; i < sizeof(prdt_t); i += 4) { + INFO("prdt[%lx]:0x%x\n", + utrd->prdt + i, + *(unsigned int *)(utrd->prdt + i)); + } +} +#endif + +static void ufs_verify_init(void) +{ + utp_utrd_t utrd; + int result; + + get_utrd(&utrd); + ufs_prepare_nop_out(&utrd); + ufs_send_request(utrd.task_tag); + result = ufs_check_resp(&utrd, NOP_IN_UPIU); + assert(result == 0); + (void)result; +} + +static void ufs_verify_ready(void) +{ + utp_utrd_t utrd; + ufs_send_cmd(&utrd, CDBCMD_TEST_UNIT_READY, 0, 0, 0, 0); +} + +static void ufs_query(uint8_t op, uint8_t idn, uint8_t index, uint8_t sel, + uintptr_t buf, size_t size) +{ + utp_utrd_t utrd; + query_resp_upiu_t *resp; + int result; + + switch (op) { + case QUERY_READ_FLAG: + case QUERY_READ_ATTR: + case QUERY_READ_DESC: + case QUERY_WRITE_DESC: + case QUERY_WRITE_ATTR: + assert(((buf & 3) == 0) && (size != 0)); + break; + default: + /* Do nothing in default case */ + break; + } + get_utrd(&utrd); + ufs_prepare_query(&utrd, op, idn, index, sel, buf, size); + ufs_send_request(utrd.task_tag); + result = ufs_check_resp(&utrd, QUERY_RESPONSE_UPIU); + assert(result == 0); + resp = (query_resp_upiu_t *)utrd.resp_upiu; +#ifdef UFS_RESP_DEBUG + dump_upiu(&utrd); +#endif + assert(resp->query_resp == QUERY_RESP_SUCCESS); + + switch (op) { + case QUERY_READ_FLAG: + *(uint32_t *)buf = (uint32_t)resp->ts.flag.value; + break; + case QUERY_READ_ATTR: + case QUERY_READ_DESC: + memcpy((void *)buf, + (void *)(utrd.resp_upiu + sizeof(query_resp_upiu_t)), + size); + break; + default: + /* Do nothing in default case */ + break; + } + (void)result; +} + +unsigned int ufs_read_attr(int idn) +{ + unsigned int value; + + ufs_query(QUERY_READ_ATTR, idn, 0, 0, + (uintptr_t)&value, sizeof(value)); + return value; +} + +void ufs_write_attr(int idn, unsigned int value) +{ + ufs_query(QUERY_WRITE_ATTR, idn, 0, 0, + (uintptr_t)&value, sizeof(value)); +} + +unsigned int ufs_read_flag(int idn) +{ + unsigned int value; + + ufs_query(QUERY_READ_FLAG, idn, 0, 0, + (uintptr_t)&value, sizeof(value)); + return value; +} + +void ufs_set_flag(int idn) +{ + ufs_query(QUERY_SET_FLAG, idn, 0, 0, 0, 0); +} + +void ufs_clear_flag(int idn) +{ + ufs_query(QUERY_CLEAR_FLAG, idn, 0, 0, 0, 0); +} + +void ufs_read_desc(int idn, int index, uintptr_t buf, size_t size) +{ + ufs_query(QUERY_READ_DESC, idn, index, 0, buf, size); +} + +void ufs_write_desc(int idn, int index, uintptr_t buf, size_t size) +{ + ufs_query(QUERY_WRITE_DESC, idn, index, 0, buf, size); +} + +static void ufs_read_capacity(int lun, unsigned int *num, unsigned int *size) +{ + utp_utrd_t utrd; + resp_upiu_t *resp; + sense_data_t *sense; + unsigned char data[CACHE_WRITEBACK_GRANULE << 1]; + uintptr_t buf; + int result; + int retry; + + assert((ufs_params.reg_base != 0) && + (ufs_params.desc_base != 0) && + (ufs_params.desc_size >= UFS_DESC_SIZE) && + (num != NULL) && (size != NULL)); + + /* align buf address */ + buf = (uintptr_t)data; + buf = (buf + CACHE_WRITEBACK_GRANULE - 1) & + ~(CACHE_WRITEBACK_GRANULE - 1); + memset((void *)buf, 0, CACHE_WRITEBACK_GRANULE); + flush_dcache_range(buf, CACHE_WRITEBACK_GRANULE); + do { + ufs_send_cmd(&utrd, CDBCMD_READ_CAPACITY_10, lun, 0, + buf, READ_CAPACITY_LENGTH); +#ifdef UFS_RESP_DEBUG + dump_upiu(&utrd); +#endif + resp = (resp_upiu_t *)utrd.resp_upiu; + retry = 0; + sense = &resp->sd.sense; + if (sense->resp_code == SENSE_DATA_VALID) { + if ((sense->sense_key == SENSE_KEY_UNIT_ATTENTION) && + (sense->asc == 0x29) && (sense->ascq == 0)) { + retry = 1; + } + } + inv_dcache_range(buf, CACHE_WRITEBACK_GRANULE); + /* last logical block address */ + *num = be32toh(*(unsigned int *)buf); + if (*num) + *num += 1; + /* logical block length in bytes */ + *size = be32toh(*(unsigned int *)(buf + 4)); + } while (retry); + (void)result; +} + +size_t ufs_read_blocks(int lun, int lba, uintptr_t buf, size_t size) +{ + utp_utrd_t utrd; + resp_upiu_t *resp; + int result; + + assert((ufs_params.reg_base != 0) && + (ufs_params.desc_base != 0) && + (ufs_params.desc_size >= UFS_DESC_SIZE)); + + ufs_send_cmd(&utrd, CDBCMD_READ_10, lun, lba, buf, size); +#ifdef UFS_RESP_DEBUG + dump_upiu(&utrd); +#endif + resp = (resp_upiu_t *)utrd.resp_upiu; + (void)result; + return size - resp->res_trans_cnt; +} + +size_t ufs_write_blocks(int lun, int lba, const uintptr_t buf, size_t size) +{ + utp_utrd_t utrd; + resp_upiu_t *resp; + int result; + + assert((ufs_params.reg_base != 0) && + (ufs_params.desc_base != 0) && + (ufs_params.desc_size >= UFS_DESC_SIZE)); + + ufs_send_cmd(&utrd, CDBCMD_WRITE_10, lun, lba, buf, size); +#ifdef UFS_RESP_DEBUG + dump_upiu(&utrd); +#endif + resp = (resp_upiu_t *)utrd.resp_upiu; + (void)result; + return size - resp->res_trans_cnt; +} + +static void ufs_enum(void) +{ + unsigned int blk_num, blk_size; + int i; + + ufs_verify_init(); + ufs_verify_ready(); + + ufs_set_flag(FLAG_DEVICE_INIT); + mdelay(200); + /* dump available LUNs */ + for (i = 0; i < UFS_MAX_LUNS; i++) { + ufs_read_capacity(i, &blk_num, &blk_size); + if (blk_num && blk_size) { + INFO("UFS LUN%d contains %d blocks with %d-byte size\n", + i, blk_num, blk_size); + } + } +} + +static void ufs_get_device_info(struct ufs_dev_desc *card_data) +{ + uint8_t desc_buf[DESC_DEVICE_MAX_SIZE]; + + ufs_query(QUERY_READ_DESC, DESC_TYPE_DEVICE, 0, 0, + (uintptr_t)desc_buf, DESC_DEVICE_MAX_SIZE); + + /* + * getting vendor (manufacturerID) and Bank Index in big endian + * format + */ + card_data->wmanufacturerid = (uint16_t)((desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8) | + (desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1])); +} + +int ufs_init(const ufs_ops_t *ops, ufs_params_t *params) +{ + int result; + unsigned int data; + uic_cmd_t cmd; + struct ufs_dev_desc card = {0}; + + assert((params != NULL) && + (params->reg_base != 0) && + (params->desc_base != 0) && + (params->desc_size >= UFS_DESC_SIZE)); + + memcpy(&ufs_params, params, sizeof(ufs_params_t)); + + /* 0 means 1 slot */ + nutrs = (mmio_read_32(ufs_params.reg_base + CAP) & CAP_NUTRS_MASK) + 1; + if (nutrs > (ufs_params.desc_size / UFS_DESC_SIZE)) { + nutrs = ufs_params.desc_size / UFS_DESC_SIZE; + } + + + if (ufs_params.flags & UFS_FLAGS_SKIPINIT) { + result = ufshc_dme_get(0x1571, 0, &data); + assert(result == 0); + result = ufshc_dme_get(0x41, 0, &data); + assert(result == 0); + if (data == 1) { + /* prepare to exit hibernate mode */ + memset(&cmd, 0, sizeof(uic_cmd_t)); + cmd.op = DME_HIBERNATE_EXIT; + result = ufshc_send_uic_cmd(ufs_params.reg_base, + &cmd); + assert(result == 0); + data = mmio_read_32(ufs_params.reg_base + UCMDARG2); + assert(data == 0); + do { + data = mmio_read_32(ufs_params.reg_base + IS); + } while ((data & UFS_INT_UHXS) == 0); + mmio_write_32(ufs_params.reg_base + IS, UFS_INT_UHXS); + data = mmio_read_32(ufs_params.reg_base + HCS); + assert((data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL); + } + result = ufshc_dme_get(0x1568, 0, &data); + assert(result == 0); + assert((data > 0) && (data <= 3)); + } else { + assert((ops != NULL) && (ops->phy_init != NULL) && + (ops->phy_set_pwr_mode != NULL)); + + result = ufshc_reset(ufs_params.reg_base); + assert(result == 0); + ops->phy_init(&ufs_params); + result = ufshc_link_startup(ufs_params.reg_base); + assert(result == 0); + + ufs_enum(); + + ufs_get_device_info(&card); + if (card.wmanufacturerid == UFS_VENDOR_SKHYNIX) { + ufs_params.flags |= UFS_FLAGS_VENDOR_SKHYNIX; + } + + ops->phy_set_pwr_mode(&ufs_params); + } + + (void)result; + return 0; +} diff --git a/arm-trusted-firmware/drivers/usb/usb_device.c b/arm-trusted-firmware/drivers/usb/usb_device.c new file mode 100644 index 0000000..701f301 --- /dev/null +++ b/arm-trusted-firmware/drivers/usb/usb_device.c @@ -0,0 +1,845 @@ +/* + * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +/* Define for EP address */ +#define EP_DIR_MASK BIT(7) +#define EP_DIR_IN BIT(7) +#define EP_NUM_MASK GENMASK(3, 0) + +#define EP0_IN (0U | EP_DIR_IN) +#define EP0_OUT 0U + +/* USB address between 1 through 127 = 0x7F mask */ +#define ADDRESS_MASK GENMASK(6, 0) + +/* + * Set a STALL condition over an endpoint + * pdev: USB handle + * ep_addr: endpoint address + * return : status + */ +static enum usb_status usb_core_set_stall(struct usb_handle *pdev, uint8_t ep_addr) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + if ((EP_DIR_MASK & ep_addr) == EP_DIR_IN) { + ep = &hpcd->in_ep[num]; + ep->is_in = true; + } else { + ep = &hpcd->out_ep[num]; + ep->is_in = false; + } + ep->num = num; + + pdev->driver->ep_set_stall(hpcd->instance, ep); + if (num == 0U) { + pdev->driver->ep0_out_start(hpcd->instance); + } + + return USBD_OK; +} + +/* + * usb_core_get_desc + * Handle Get Descriptor requests + * pdev : device instance + * req : usb request + */ +static void usb_core_get_desc(struct usb_handle *pdev, struct usb_setup_req *req) +{ + uint16_t len; + uint8_t *pbuf; + uint8_t desc_type = HIBYTE(req->value); + uint8_t desc_idx = LOBYTE(req->value); + + switch (desc_type) { + case USB_DESC_TYPE_DEVICE: + pbuf = pdev->desc->get_device_desc(&len); + break; + + case USB_DESC_TYPE_CONFIGURATION: + pbuf = pdev->desc->get_config_desc(&len); + break; + + case USB_DESC_TYPE_STRING: + switch (desc_idx) { + case USBD_IDX_LANGID_STR: + pbuf = pdev->desc->get_lang_id_desc(&len); + break; + + case USBD_IDX_MFC_STR: + pbuf = pdev->desc->get_manufacturer_desc(&len); + break; + + case USBD_IDX_PRODUCT_STR: + pbuf = pdev->desc->get_product_desc(&len); + break; + + case USBD_IDX_SERIAL_STR: + pbuf = pdev->desc->get_serial_desc(&len); + break; + + case USBD_IDX_CONFIG_STR: + pbuf = pdev->desc->get_configuration_desc(&len); + break; + + case USBD_IDX_INTERFACE_STR: + pbuf = pdev->desc->get_interface_desc(&len); + break; + + /* For all USER string */ + case USBD_IDX_USER0_STR: + default: + pbuf = pdev->desc->get_usr_desc(desc_idx - USBD_IDX_USER0_STR, &len); + break; + } + break; + + case USB_DESC_TYPE_DEVICE_QUALIFIER: + pbuf = pdev->desc->get_device_qualifier_desc(&len); + break; + + case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: + if (pdev->desc->get_other_speed_config_desc == NULL) { + usb_core_ctl_error(pdev); + return; + } + pbuf = pdev->desc->get_other_speed_config_desc(&len); + break; + + default: + ERROR("Unknown request %i\n", desc_type); + usb_core_ctl_error(pdev); + return; + } + + if ((len != 0U) && (req->length != 0U)) { + len = MIN(len, req->length); + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, pbuf, len); + } +} + +/* + * usb_core_set_config + * Handle Set device configuration request + * pdev : device instance + * req : usb request + */ +static void usb_core_set_config(struct usb_handle *pdev, struct usb_setup_req *req) +{ + static uint8_t cfgidx; + + cfgidx = LOBYTE(req->value); + + if (cfgidx > USBD_MAX_NUM_CONFIGURATION) { + usb_core_ctl_error(pdev); + return; + } + + switch (pdev->dev_state) { + case USBD_STATE_ADDRESSED: + if (cfgidx != 0U) { + pdev->dev_config = cfgidx; + pdev->dev_state = USBD_STATE_CONFIGURED; + if (!pdev->class) { + usb_core_ctl_error(pdev); + return; + } + /* Set configuration and Start the Class */ + if (pdev->class->init(pdev, cfgidx) != 0U) { + usb_core_ctl_error(pdev); + return; + } + } + break; + + case USBD_STATE_CONFIGURED: + if (cfgidx == 0U) { + pdev->dev_state = USBD_STATE_ADDRESSED; + pdev->dev_config = cfgidx; + pdev->class->de_init(pdev, cfgidx); + } else if (cfgidx != pdev->dev_config) { + if (pdev->class == NULL) { + usb_core_ctl_error(pdev); + return; + } + /* Clear old configuration */ + pdev->class->de_init(pdev, pdev->dev_config); + /* Set new configuration */ + pdev->dev_config = cfgidx; + /* Set configuration and start the USB class */ + if (pdev->class->init(pdev, cfgidx) != 0U) { + usb_core_ctl_error(pdev); + return; + } + } + break; + + default: + usb_core_ctl_error(pdev); + return; + } + + /* Send status */ + usb_core_transmit_ep0(pdev, NULL, 0U); +} + +/* + * usb_core_get_status + * Handle Get Status request + * pdev : device instance + * req : usb request + */ +static void usb_core_get_status(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + if ((pdev->dev_state != USBD_STATE_ADDRESSED) && + (pdev->dev_state != USBD_STATE_CONFIGURED)) { + usb_core_ctl_error(pdev); + return; + } + + pdev->dev_config_status = USB_CONFIG_SELF_POWERED; + + if (pdev->dev_remote_wakeup != 0U) { + pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP; + } + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, (uint8_t *)&pdev->dev_config_status, 2U); +} + +/* + * usb_core_set_address + * Set device address + * pdev : device instance + * req : usb request + */ +static void usb_core_set_address(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + uint8_t dev_addr; + + if ((req->index != 0U) || (req->length != 0U)) { + usb_core_ctl_error(pdev); + return; + } + + dev_addr = req->value & ADDRESS_MASK; + if (pdev->dev_state != USBD_STATE_DEFAULT) { + usb_core_ctl_error(pdev); + return; + } + + pdev->dev_address = dev_addr; + pdev->driver->set_address(((struct pcd_handle *)(pdev->data))->instance, dev_addr); + + /* Send status */ + usb_core_transmit_ep0(pdev, NULL, 0U); + + if (dev_addr != 0U) { + pdev->dev_state = USBD_STATE_ADDRESSED; + } else { + pdev->dev_state = USBD_STATE_DEFAULT; + } +} + +/* + * usb_core_dev_req + * Handle standard usb device requests + * pdev : device instance + * req : usb request + * return : status + */ +static enum usb_status usb_core_dev_req(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + VERBOSE("receive request %i\n", req->b_request); + switch (req->b_request) { + case USB_REQ_GET_DESCRIPTOR: + usb_core_get_desc(pdev, req); + break; + + case USB_REQ_SET_CONFIGURATION: + usb_core_set_config(pdev, req); + break; + + case USB_REQ_GET_STATUS: + usb_core_get_status(pdev, req); + break; + + case USB_REQ_SET_ADDRESS: + usb_core_set_address(pdev, req); + break; + + case USB_REQ_GET_CONFIGURATION: + case USB_REQ_SET_FEATURE: + case USB_REQ_CLEAR_FEATURE: + default: + ERROR("NOT SUPPORTED %i\n", req->b_request); + usb_core_ctl_error(pdev); + break; + } + + return USBD_OK; +} + +/* + * usb_core_itf_req + * Handle standard usb interface requests + * pdev : device instance + * req : usb request + * return : status + */ +static enum usb_status usb_core_itf_req(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + if (pdev->dev_state != USBD_STATE_CONFIGURED) { + usb_core_ctl_error(pdev); + return USBD_OK; + } + + if (LOBYTE(req->index) <= USBD_MAX_NUM_INTERFACES) { + pdev->class->setup(pdev, req); + + if (req->length == 0U) { + usb_core_transmit_ep0(pdev, NULL, 0U); + } + } else { + usb_core_ctl_error(pdev); + } + + return USBD_OK; +} + +/* + * usb_core_setup_stage + * Handle the setup stage + * pdev: device instance + * psetup : setup buffer + * return : status + */ +static enum usb_status usb_core_setup_stage(struct usb_handle *pdev, + uint8_t *psetup) +{ + struct usb_setup_req *req = &pdev->request; + + /* Copy setup buffer into req structure */ + req->bm_request = psetup[0]; + req->b_request = psetup[1]; + req->value = psetup[2] + (psetup[3] << 8); + req->index = psetup[4] + (psetup[5] << 8); + req->length = psetup[6] + (psetup[7] << 8); + + pdev->ep0_state = USBD_EP0_SETUP; + pdev->ep0_data_len = pdev->request.length; + + switch (pdev->request.bm_request & USB_REQ_RECIPIENT_MASK) { + case USB_REQ_RECIPIENT_DEVICE: + usb_core_dev_req(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_INTERFACE: + usb_core_itf_req(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + default: + ERROR("receive unsupported request %u", + pdev->request.bm_request & USB_REQ_RECIPIENT_MASK); + usb_core_set_stall(pdev, pdev->request.bm_request & USB_REQ_DIRECTION); + return USBD_FAIL; + } + + return USBD_OK; +} + +/* + * usb_core_data_out + * Handle data OUT stage + * pdev: device instance + * epnum: endpoint index + * pdata: buffer to sent + * return : status + */ +static enum usb_status usb_core_data_out(struct usb_handle *pdev, uint8_t epnum, + uint8_t *pdata) +{ + struct usb_endpoint *pep; + + if (epnum == 0U) { + pep = &pdev->ep_out[0]; + if (pdev->ep0_state == USBD_EP0_DATA_OUT) { + if (pep->rem_length > pep->maxpacket) { + pep->rem_length -= pep->maxpacket; + + usb_core_receive(pdev, 0U, pdata, + MIN(pep->rem_length, + pep->maxpacket)); + } else { + if (pdev->class->ep0_rx_ready && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->ep0_rx_ready(pdev); + } + + usb_core_transmit_ep0(pdev, NULL, 0U); + } + } + } else if (pdev->class->data_out != NULL && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->data_out(pdev, epnum); + } + + return USBD_OK; +} + +/* + * usb_core_data_in + * Handle data in stage + * pdev: device instance + * epnum: endpoint index + * pdata: buffer to fill + * return : status + */ +static enum usb_status usb_core_data_in(struct usb_handle *pdev, uint8_t epnum, + uint8_t *pdata) +{ + if (epnum == 0U) { + struct usb_endpoint *pep = &pdev->ep_in[0]; + + if (pdev->ep0_state == USBD_EP0_DATA_IN) { + if (pep->rem_length > pep->maxpacket) { + pep->rem_length -= pep->maxpacket; + + usb_core_transmit(pdev, 0U, pdata, + pep->rem_length); + + /* Prepare EP for premature end of transfer */ + usb_core_receive(pdev, 0U, NULL, 0U); + } else { + /* Last packet is MPS multiple, send ZLP packet */ + if ((pep->total_length % pep->maxpacket == 0U) && + (pep->total_length >= pep->maxpacket) && + (pep->total_length < pdev->ep0_data_len)) { + usb_core_transmit(pdev, 0U, NULL, 0U); + + pdev->ep0_data_len = 0U; + + /* Prepare endpoint for premature end of transfer */ + usb_core_receive(pdev, 0U, NULL, 0U); + } else { + if (pdev->class->ep0_tx_sent != NULL && + (pdev->dev_state == + USBD_STATE_CONFIGURED)) { + pdev->class->ep0_tx_sent(pdev); + } + /* Start the transfer */ + usb_core_receive_ep0(pdev, NULL, 0U); + } + } + } + } else if ((pdev->class->data_in != NULL) && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->data_in(pdev, epnum); + } + + return USBD_OK; +} + +/* + * usb_core_suspend + * Handle suspend event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_suspend(struct usb_handle *pdev) +{ + INFO("USB Suspend mode\n"); + pdev->dev_old_state = pdev->dev_state; + pdev->dev_state = USBD_STATE_SUSPENDED; + + return USBD_OK; +} + +/* + * usb_core_resume + * Handle resume event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_resume(struct usb_handle *pdev) +{ + INFO("USB Resume\n"); + pdev->dev_state = pdev->dev_old_state; + + return USBD_OK; +} + +/* + * usb_core_sof + * Handle SOF event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_sof(struct usb_handle *pdev) +{ + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + if (pdev->class->sof != NULL) { + pdev->class->sof(pdev); + } + } + + return USBD_OK; +} + +/* + * usb_core_disconnect + * Handle device disconnection event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_disconnect(struct usb_handle *pdev) +{ + /* Free class resources */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->class->de_init(pdev, pdev->dev_config); + + return USBD_OK; +} + +enum usb_status usb_core_handle_it(struct usb_handle *pdev) +{ + uint32_t param = 0U; + uint32_t len = 0U; + struct usbd_ep *ep; + + switch (pdev->driver->it_handler(pdev->data->instance, ¶m)) { + case USB_DATA_OUT: + usb_core_data_out(pdev, param, + pdev->data->out_ep[param].xfer_buff); + break; + + case USB_DATA_IN: + usb_core_data_in(pdev, param, + pdev->data->in_ep[param].xfer_buff); + break; + + case USB_SETUP: + usb_core_setup_stage(pdev, (uint8_t *)pdev->data->setup); + break; + + case USB_ENUM_DONE: + break; + + case USB_READ_DATA_PACKET: + ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK]; + len = (param & USBD_OUT_COUNT_MASK) >> USBD_OUT_COUNT_SHIFT; + pdev->driver->read_packet(pdev->data->instance, + ep->xfer_buff, len); + ep->xfer_buff += len; + ep->xfer_count += len; + break; + + case USB_READ_SETUP_PACKET: + ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK]; + len = (param & USBD_OUT_COUNT_MASK) >> 0x10; + pdev->driver->read_packet(pdev->data->instance, + (uint8_t *)pdev->data->setup, 8); + ep->xfer_count += len; + break; + + case USB_RESET: + pdev->dev_state = USBD_STATE_DEFAULT; + break; + + case USB_RESUME: + if (pdev->data->lpm_state == LPM_L1) { + pdev->data->lpm_state = LPM_L0; + } else { + usb_core_resume(pdev); + } + break; + + case USB_SUSPEND: + usb_core_suspend(pdev); + break; + + case USB_LPM: + if (pdev->data->lpm_state == LPM_L0) { + pdev->data->lpm_state = LPM_L1; + } else { + usb_core_suspend(pdev); + } + break; + + case USB_SOF: + usb_core_sof(pdev); + break; + + case USB_DISCONNECT: + usb_core_disconnect(pdev); + break; + + case USB_WRITE_EMPTY: + pdev->driver->write_empty_tx_fifo(pdev->data->instance, param, + pdev->data->in_ep[param].xfer_len, + (uint32_t *)&pdev->data->in_ep[param].xfer_count, + pdev->data->in_ep[param].maxpacket, + &pdev->data->in_ep[param].xfer_buff); + break; + + case USB_NOTHING: + default: + break; + } + + return USBD_OK; +} + +static void usb_core_start_xfer(struct usb_handle *pdev, + void *handle, + struct usbd_ep *ep) +{ + if (ep->num == 0U) { + pdev->driver->ep0_start_xfer(handle, ep); + } else { + pdev->driver->ep_start_xfer(handle, ep); + } +} + +/* + * usb_core_receive + * Receive an amount of data + * pdev: USB handle + * ep_addr: endpoint address + * buf: pointer to the reception buffer + * len: amount of data to be received + * return : status + */ +enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *buf, uint32_t len) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + ep = &hpcd->out_ep[num]; + + /* Setup and start the Xfer */ + ep->xfer_buff = buf; + ep->xfer_len = len; + ep->xfer_count = 0U; + ep->is_in = false; + ep->num = num; + + usb_core_start_xfer(pdev, hpcd->instance, ep); + + return USBD_OK; +} + +/* + * usb_core_transmit + * Send an amount of data + * pdev: USB handle + * ep_addr: endpoint address + * buf: pointer to the transmission buffer + * len: amount of data to be sent + * return : status + */ +enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *buf, uint32_t len) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + ep = &hpcd->in_ep[num]; + + /* Setup and start the Xfer */ + ep->xfer_buff = buf; + ep->xfer_len = len; + ep->xfer_count = 0U; + ep->is_in = true; + ep->num = num; + + usb_core_start_xfer(pdev, hpcd->instance, ep); + + return USBD_OK; +} + +/* + * usb_core_receive_ep0 + * Receive an amount of data on ep0 + * pdev: USB handle + * buf: pointer to the reception buffer + * len: amount of data to be received + * return : status + */ +enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *buf, + uint32_t len) +{ + /* Prepare the reception of the buffer over EP0 */ + if (len != 0U) { + pdev->ep0_state = USBD_EP0_DATA_OUT; + } else { + pdev->ep0_state = USBD_EP0_STATUS_OUT; + } + + pdev->ep_out[0].total_length = len; + pdev->ep_out[0].rem_length = len; + + /* Start the transfer */ + return usb_core_receive(pdev, 0U, buf, len); +} + +/* + * usb_core_transmit_ep0 + * Send an amount of data on ep0 + * pdev: USB handle + * buf: pointer to the transmission buffer + * len: amount of data to be sent + * return : status + */ +enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *buf, + uint32_t len) +{ + /* Set EP0 State */ + if (len != 0U) { + pdev->ep0_state = USBD_EP0_DATA_IN; + } else { + pdev->ep0_state = USBD_EP0_STATUS_IN; + } + + pdev->ep_in[0].total_length = len; + pdev->ep_in[0].rem_length = len; + + /* Start the transfer */ + return usb_core_transmit(pdev, 0U, buf, len); +} + +/* + * usb_core_ctl_error + * Handle USB low level error + * pdev: device instance + * req: usb request + * return : None + */ + +void usb_core_ctl_error(struct usb_handle *pdev) +{ + ERROR("%s : Send an ERROR\n", __func__); + usb_core_set_stall(pdev, EP0_IN); + usb_core_set_stall(pdev, EP0_OUT); +} + +/* + * usb_core_start + * Start the USB device core. + * pdev: Device Handle + * return : USBD Status + */ +enum usb_status usb_core_start(struct usb_handle *pdev) +{ + /* Start the low level driver */ + pdev->driver->start_device(pdev->data->instance); + + return USBD_OK; +} + +/* + * usb_core_stop + * Stop the USB device core. + * pdev: Device Handle + * return : USBD Status + */ +enum usb_status usb_core_stop(struct usb_handle *pdev) +{ + /* Free class resources */ + pdev->class->de_init(pdev, pdev->dev_config); + + /* Stop the low level driver */ + pdev->driver->stop_device(pdev->data->instance); + + return USBD_OK; +} + +/* + * register_usb_driver + * Stop the USB device core. + * pdev: Device Handle + * pcd_handle: PCD handle + * driver: USB driver + * driver_handle: USB driver handle + * return : USBD Status + */ +enum usb_status register_usb_driver(struct usb_handle *pdev, + struct pcd_handle *pcd_handle, + const struct usb_driver *driver, + void *driver_handle) +{ + uint8_t i; + + assert(pdev != NULL); + assert(pcd_handle != NULL); + assert(driver != NULL); + assert(driver_handle != NULL); + + /* Free class resources */ + pdev->driver = driver; + pdev->data = pcd_handle; + pdev->data->instance = driver_handle; + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->ep0_state = USBD_EP0_IDLE; + + /* Copy endpoint information */ + for (i = 0U; i < USBD_EP_NB; i++) { + pdev->ep_in[i].maxpacket = pdev->data->in_ep[i].maxpacket; + pdev->ep_out[i].maxpacket = pdev->data->out_ep[i].maxpacket; + } + + return USBD_OK; +} + +/* + * register_platform + * Register the USB device core. + * pdev: Device Handle + * plat_call_back: callback + * return : USBD Status + */ +enum usb_status register_platform(struct usb_handle *pdev, + const struct usb_desc *plat_call_back) +{ + assert(pdev != NULL); + assert(plat_call_back != NULL); + + /* Save platform info in class resources */ + pdev->desc = plat_call_back; + + return USBD_OK; +} diff --git a/arm-trusted-firmware/fdts/a5ds.dts b/arm-trusted-firmware/fdts/a5ds.dts new file mode 100644 index 0000000..c6f5be6 --- /dev/null +++ b/arm-trusted-firmware/fdts/a5ds.dts @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "A5DS"; + compatible = "arm,A5DS"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_on = <0x84000003>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "psci"; + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <0>; + next-level-cache = <&L2>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <1>; + next-level-cache = <&L2>; + }; + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <2>; + next-level-cache = <&L2>; + }; + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <3>; + next-level-cache = <&L2>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x7F000000>; + }; + + L2: cache-controller@1C010000 { + compatible = "arm,pl310-cache"; + reg = <0x1C010000 0x1000>; + interrupts = <0 84 4>; + cache-level = <2>; + cache-unified; + arm,data-latency = <1 1 1>; + arm,tag-latency = <1 1 1>; + }; + + refclk7500khz: refclk7500khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <7500000>; + clock-output-names = "apb_pclk"; + }; + + refclk24mhz: refclk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "apb_pclk"; + }; + + smbclk: refclk24mhzx2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "smclk"; + }; + + + rtc@1a220000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x1a220000 0x1000>; + clocks = <&refclk24mhz>; + interrupts = <0 6 0xf04>; + clock-names = "apb_pclk"; + }; + + gic: interrupt-controller@1c001000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x1c001000 0x1000>, + <0x1c000100 0x100>; + interrupts = <1 9 0xf04>; + }; + + serial0: uart@1a200000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a200000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 8 0xf04>; + clocks = <&refclk7500khz>; + clock-names = "apb_pclk"; + }; + + serial1: uart@1a210000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a210000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 9 0xf04>; + clocks = <&refclk7500khz>; + clock-names = "apb_pclk"; + }; + + timer0: timer@1a040000 { + compatible = "arm,armv7-timer-mem"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + reg = <0x1a040000 0x1000>; + clock-frequency = <7500000>; + + frame@1a050000 { + frame-number = <0>; + interrupts = <0 2 0xf04>; + reg = <0x1a050000 0x1000>; + }; + }; + v2m_fixed_3v3: fixed-regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + ethernet@4020000 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <0x40200000 0x10000>; + interrupt-parent = <&gic>; + interrupts = <0 43 0xf04>; + reg-io-width = <4>; + phy-mode = "mii"; + smsc,irq-active-high; + vdd33a-supply = <&v2m_fixed_3v3>; + vddvario-supply = <&v2m_fixed_3v3>; + }; +}; diff --git a/arm-trusted-firmware/fdts/arm_fpga.dts b/arm-trusted-firmware/fdts/arm_fpga.dts new file mode 100644 index 0000000..c0efd09 --- /dev/null +++ b/arm-trusted-firmware/fdts/arm_fpga.dts @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * Devicetree for the Arm Ltd. FPGA platform + * Number and kind of CPU cores differs from image to image, so the + * topology is auto-detected by BL31, and the /cpus node is created and + * populated accordingly at runtime. + */ + +#include + +/dts-v1/; + +/ { + model = "ARM FPGA"; + compatible = "arm,fpga", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &dbg_uart; + }; + + chosen { + stdout-path = "serial0:38400n8"; + bootargs = "console=ttyAMA0,38400n8 earlycon"; + /* Allow to upload a generous 100MB initrd payload. */ + linux,initrd-start = <0x0 0x84000000>; + linux,initrd-end = <0x0 0x8a400000>; + }; + + /* /cpus node will be added by BL31 at runtime. */ + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + /* This node will be removed at runtime on cores without SPE. */ + spe-pmu { + compatible = "arm,statistical-profiling-extension-v1"; + interrupts = ; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x80000000>, + <0x8 0x80000000 0x1 0x80000000>; + }; + + + bus_refclk: refclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + uartclk: baudclock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <10000000>; + clock-output-names = "uartclk"; + }; + + dbg_uart: serial@7ff80000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x7ff80000 0x0 0x00001000>; + interrupts = ; + clocks = <&uartclk>, <&bus_refclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + gic: interrupt-controller@30000000 { + compatible = "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x30000000 0x0 0x00010000>, /* GICD */ + /* The GICR size will be adjusted at runtime to match the cores. */ + <0x0 0x30040000 0x0 0x00020000>; /* GICR for one core */ + interrupts = ; + + its: msi-controller@30040000 { + compatible = "arm,gic-v3-its"; + reg = <0x0 0x30040000 0x0 0x40000>; + #msi-cells = <1>; + msi-controller; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/corstone700.dtsi b/arm-trusted-firmware/fdts/corstone700.dtsi new file mode 100644 index 0000000..2372207 --- /dev/null +++ b/arm-trusted-firmware/fdts/corstone700.dtsi @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/ { + compatible = "arm,Corstone-700"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + chosen { }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0>; + next-level-cache = <&L2_0>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x80000000>; + }; + + gic: interrupt-controller@1c000000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x1c010000 0x1000>, + <0x1c02f000 0x2000>, + <0x1c04f000 0x1000>, + <0x1c06f000 0x2000>; + interrupts = <1 9 0xf08>; + }; + + L2_0: l2-cache0 { + compatible = "cache"; + }; + + refclk100mhz: refclk100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + smbclk: refclk24mhzx2 { + /* Reference 24MHz clock x 2 */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "smclk"; + }; + + uartclk: uartclk { + /* UART clock - 32MHz */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32000000>; + clock-output-names = "uartclk"; + }; + + serial0: uart@1a510000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a510000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 19 4>; + clocks = <&uartclk>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + serial1: uart@1a520000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a520000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 20 4>; + clocks = <&uartclk>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; + }; + + refclk: refclk@1a220000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x1a220000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + frame@1a230000 { + frame-number = <0>; + interrupts = <0 2 0xf04>; + reg = <0x1a230000 0x1000>; + }; + }; + + mbox_es0mhu0: mhu@1b000000 { + compatible = "arm,mhuv2","arm,primecell"; + reg = <0x1b000000 0x1000>, + <0x1b010000 0x1000>; + clocks = <&refclk100mhz>; + clock-names = "apb_pclk"; + interrupts = <0 12 4>; + interrupt-names = "mhu_rx"; + #mbox-cells = <1>; + mbox-name = "arm-es0-mhu0"; + }; + + mbox_es0mhu1: mhu@1b020000 { + compatible = "arm,mhuv2","arm,primecell"; + reg = <0x1b020000 0x1000>, + <0x1b030000 0x1000>; + clocks = <&refclk100mhz>; + clock-names = "apb_pclk"; + interrupts = <0 47 4>; + interrupt-names = "mhu_rx"; + #mbox-cells = <1>; + mbox-name = "arm-es0-mhu1"; + }; + + mbox_semhu1: mhu@1b820000 { + compatible = "arm,mhuv2","arm,primecell"; + reg = <0x1b820000 0x1000>, + <0x1b830000 0x1000>; + clocks = <&refclk100mhz>; + clock-names = "apb_pclk"; + interrupts = <0 45 4>; + interrupt-names = "mhu_rx"; + #mbox-cells = <1>; + mbox-name = "arm-se-mhu1"; + }; + + client { + compatible = "arm,client"; + mboxes = <&mbox_es0mhu0 0>, <&mbox_es0mhu1 0>, <&mbox_semhu1 0>; + mbox-names = "es0mhu0", "es0mhu1", "semhu1"; + }; + + extsys0: extsys@1A010310 { + compatible = "arm,extsys_ctrl"; + reg = <0x1A010310 0x4>, + <0x1A010314 0x4>; + reg-names = "rstreg", "streg"; + }; +}; diff --git a/arm-trusted-firmware/fdts/corstone700_fpga.dts b/arm-trusted-firmware/fdts/corstone700_fpga.dts new file mode 100644 index 0000000..1ac0d4b --- /dev/null +++ b/arm-trusted-firmware/fdts/corstone700_fpga.dts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +#include "corstone700.dtsi" + +/ { + model = "corstone700-fpga"; + + ethernet: eth@40100000 { + compatible = "smsc,lan9115"; + reg = <0x40100000 0x10000>; + phy-mode = "mii"; + interrupt-parent = <&gic>; + interrupts = ; + reg-io-width = <2>; + smsc,irq-push-pull; + }; + + usb: usb@4020000 { + compatible = "nxp,usb-isp1763"; + reg = <0x40200000 0x100000>; + interrupt-parent = <&gic>; + interrupts = ; + }; +}; + +&refclk { + clock-frequency = <32000000>; +}; diff --git a/arm-trusted-firmware/fdts/corstone700_fvp.dts b/arm-trusted-firmware/fdts/corstone700_fvp.dts new file mode 100644 index 0000000..3b1202d --- /dev/null +++ b/arm-trusted-firmware/fdts/corstone700_fvp.dts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +#include "corstone700.dtsi" + +/ { + model = "corstone700-fvp"; + + /* + * Intel StrataFlash J3 NOR flash: 2 x 16-bit interleaved components + * Flash total size: 32 MB + * Allocated flash space: 8 MB + */ + + flash@8500000 { + compatible = "cfi-flash"; + reg = <0x8500000 0x800000>; + bank-width = <4>; + device-width= <2>; + }; + + ethernet: eth@4010000 { + compatible = "smsc,lan91c111"; + reg = <0x40100000 0x10000>; + phy-mode = "mii"; + interrupt-parent = <&gic>; + interrupts = ; + reg-io-width = <2>; + smsc,irq-push-pull; + }; +}; + +&refclk { + clock-frequency = <50000000>; +}; diff --git a/arm-trusted-firmware/fdts/cot_descriptors.dtsi b/arm-trusted-firmware/fdts/cot_descriptors.dtsi new file mode 100644 index 0000000..411bae6 --- /dev/null +++ b/arm-trusted-firmware/fdts/cot_descriptors.dtsi @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +cot { + manifests { + compatible = "arm, cert-descs"; + + trusted_boot_fw_cert: trusted_boot_fw_cert { + root-certificate; + image-id =; + antirollback-counter = <&trusted_nv_counter>; + + tb_fw_hash: tb_fw_hash { + oid = TRUSTED_BOOT_FW_HASH_OID; + }; + tb_fw_config_hash: tb_fw_config_hash { + oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID; + }; + hw_config_hash: hw_config_hash { + oid = HW_CONFIG_HASH_OID; + }; + fw_config_hash: fw_config_hash { + oid = FW_CONFIG_HASH_OID; + }; + }; + + trusted_key_cert: trusted_key_cert { + root-certificate; + image-id = ; + antirollback-counter = <&trusted_nv_counter>; + + trusted_world_pk: trusted_world_pk { + oid = TRUSTED_WORLD_PK_OID; + }; + non_trusted_world_pk: non_trusted_world_pk { + oid = NON_TRUSTED_WORLD_PK_OID; + }; + }; + + scp_fw_key_cert: scp_fw_key_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + + scp_fw_content_pk: scp_fw_content_pk { + oid = SCP_FW_CONTENT_CERT_PK_OID; + }; + }; + + scp_fw_content_cert: scp_fw_content_cert { + image-id = ; + parent = <&scp_fw_key_cert>; + signing-key = <&scp_fw_content_pk>; + antirollback-counter = <&trusted_nv_counter>; + + scp_fw_hash: scp_fw_hash { + oid = SCP_FW_HASH_OID; + }; + }; + + soc_fw_key_cert: soc_fw_key_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + soc_fw_content_pk: soc_fw_content_pk { + oid = SOC_FW_CONTENT_CERT_PK_OID; + }; + }; + + soc_fw_content_cert: soc_fw_content_cert { + image-id = ; + parent = <&soc_fw_key_cert>; + signing-key = <&soc_fw_content_pk>; + antirollback-counter = <&trusted_nv_counter>; + + soc_fw_hash: soc_fw_hash { + oid = SOC_AP_FW_HASH_OID; + }; + soc_fw_config_hash: soc_fw_config_hash { + oid = SOC_FW_CONFIG_HASH_OID; + }; + }; + + trusted_os_fw_key_cert: trusted_os_fw_key_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + + tos_fw_content_pk: tos_fw_content_pk { + oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID; + }; + }; + + trusted_os_fw_content_cert: trusted_os_fw_content_cert { + image-id = ; + parent = <&trusted_os_fw_key_cert>; + signing-key = <&tos_fw_content_pk>; + antirollback-counter = <&trusted_nv_counter>; + + tos_fw_hash: tos_fw_hash { + oid = TRUSTED_OS_FW_HASH_OID; + }; + tos_fw_extra1_hash: tos_fw_extra1_hash { + oid = TRUSTED_OS_FW_EXTRA1_HASH_OID; + }; + tos_fw_extra2_hash: tos_fw_extra2_hash { + oid = TRUSTED_OS_FW_EXTRA2_HASH_OID; + }; + tos_fw_config_hash: tos_fw_config_hash { + oid = TRUSTED_OS_FW_CONFIG_HASH_OID; + }; + }; + + non_trusted_fw_key_cert: non_trusted_fw_key_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&non_trusted_world_pk>; + antirollback-counter = <&non_trusted_nv_counter>; + + nt_fw_content_pk: nt_fw_content_pk { + oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID; + }; + }; + + non_trusted_fw_content_cert: non_trusted_fw_content_cert { + image-id = ; + parent = <&non_trusted_fw_key_cert>; + signing-key = <&nt_fw_content_pk>; + antirollback-counter = <&non_trusted_nv_counter>; + + nt_world_bl_hash: nt_world_bl_hash { + oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID; + }; + nt_fw_config_hash: nt_fw_config_hash { + oid = NON_TRUSTED_FW_CONFIG_HASH_OID; + }; + }; + +#if defined(SPD_spmd) + sip_sp_content_cert: sip_sp_content_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + + sp_pkg1_hash: sp_pkg1_hash { + oid = SP_PKG1_HASH_OID; + }; + sp_pkg2_hash: sp_pkg2_hash { + oid = SP_PKG2_HASH_OID; + }; + sp_pkg3_hash: sp_pkg3_hash { + oid = SP_PKG3_HASH_OID; + }; + sp_pkg4_hash: sp_pkg4_hash { + oid = SP_PKG4_HASH_OID; + }; + sp_pkg5_hash: sp_pkg5_hash { + oid = SP_PKG5_HASH_OID; + }; + sp_pkg6_hash: sp_pkg6_hash { + oid = SP_PKG6_HASH_OID; + }; + sp_pkg7_hash: sp_pkg7_hash { + oid = SP_PKG7_HASH_OID; + }; + sp_pkg8_hash: sp_pkg8_hash { + oid = SP_PKG8_HASH_OID; + }; + }; +#endif + }; + + images { + compatible = "arm, img-descs"; + + hw_config { + image-id = ; + parent = <&trusted_boot_fw_cert>; + hash = <&hw_config_hash>; + }; + + tb_fw_config { + image-id = ; + parent = <&trusted_boot_fw_cert>; + hash = <&tb_fw_config_hash>; + }; + + scp_bl2_image { + image-id = ; + parent = <&scp_fw_content_cert>; + hash = <&scp_fw_hash>; + }; + + bl31_image { + image-id = ; + parent = <&soc_fw_content_cert>; + hash = <&soc_fw_hash>; + }; + + soc_fw_config { + image-id = ; + parent = <&soc_fw_content_cert>; + hash = <&soc_fw_config_hash>; + }; + + bl32_image { + image-id = ; + parent = <&trusted_os_fw_content_cert>; + hash = <&tos_fw_hash>; + }; + + bl32_extra1_image { + image-id = ; + parent = <&trusted_os_fw_content_cert>; + hash = <&tos_fw_extra1_hash>; + }; + + bl32_extra2_image { + image-id = ; + parent = <&trusted_os_fw_content_cert>; + hash = <&tos_fw_extra2_hash>; + }; + + tos_fw_config { + image-id = ; + parent = <&trusted_os_fw_content_cert>; + hash = <&tos_fw_config_hash>; + }; + + bl33_image { + image-id = ; + parent = <&non_trusted_fw_content_cert>; + hash = <&nt_world_bl_hash>; + }; + + nt_fw_config { + image-id = ; + parent = <&non_trusted_fw_content_cert>; + hash = <&nt_fw_config_hash>; + }; + +#if defined(SPD_spmd) + sp_pkg1 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg1_hash>; + }; + + sp_pkg2 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg2_hash>; + }; + + sp_pkg3 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg3_hash>; + }; + + sp_pkg4 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg4_hash>; + }; + + sp_pkg5 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg5_hash>; + }; + + sp_pkg6 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg6_hash>; + }; + + sp_pkg7 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg7_hash>; + }; + + sp_pkg8 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg8_hash>; + }; +#endif + }; +}; + +non_volatile_counters: non_volatile_counters { + compatible = "arm, non-volatile-counter"; + + #address-cells = <1>; + #size-cells = <0>; + + trusted_nv_counter: trusted_nv_counter { + id = ; + oid = TRUSTED_FW_NVCOUNTER_OID; + }; + + non_trusted_nv_counter: non_trusted_nv_counter { + id = ; + oid = NON_TRUSTED_FW_NVCOUNTER_OID; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts b/arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts new file mode 100644 index 0000000..3a921f4 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs */ + +/dts-v1/; + +#define AFF +#define REG_32 + +#include +#include "fvp-defs.dtsi" + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, + <0x0 0x2c000000 0 0x2000>, + <0x0 0x2c010000 0 0x2000>, + <0x0 0x2c02F000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 6 &gic 0 6 4>, + <0 0 7 &gic 0 7 4>, + <0 0 8 &gic 0 8 4>, + <0 0 9 &gic 0 9 4>, + <0 0 10 &gic 0 10 4>, + <0 0 11 &gic 0 11 4>, + <0 0 12 &gic 0 12 4>, + <0 0 13 &gic 0 13 4>, + <0 0 14 &gic 0 14 4>, + <0 0 15 &gic 0 15 4>, + <0 0 16 &gic 0 16 4>, + <0 0 17 &gic 0 17 4>, + <0 0 18 &gic 0 18 4>, + <0 0 19 &gic 0 19 4>, + <0 0 20 &gic 0 20 4>, + <0 0 21 &gic 0 21 4>, + <0 0 22 &gic 0 22 4>, + <0 0 23 &gic 0 23 4>, + <0 0 24 &gic 0 24 4>, + <0 0 25 &gic 0 25 4>, + <0 0 26 &gic 0 26 4>, + <0 0 27 &gic 0 27 4>, + <0 0 28 &gic 0 28 4>, + <0 0 29 &gic 0 29 4>, + <0 0 30 &gic 0 30 4>, + <0 0 31 &gic 0 31 4>, + <0 0 32 &gic 0 32 4>, + <0 0 33 &gic 0 33 4>, + <0 0 34 &gic 0 34 4>, + <0 0 35 &gic 0 35 4>, + <0 0 36 &gic 0 36 4>, + <0 0 37 &gic 0 37 4>, + <0 0 38 &gic 0 38 4>, + <0 0 39 &gic 0 39 4>, + <0 0 40 &gic 0 40 4>, + <0 0 41 &gic 0 41 4>, + <0 0 42 &gic 0 42 4>; + + #include "rtsm_ve-motherboard-aarch32.dtsi" + }; + + panels { + panel@0 { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts b/arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts new file mode 100644 index 0000000..e99719e --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs */ + +/dts-v1/; + +#define AFF + +#include +#include "fvp-defs.dtsi" + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, + <0x0 0x2c000000 0 0x2000>, + <0x0 0x2c010000 0 0x2000>, + <0x0 0x2c02F000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #include "rtsm_ve-motherboard.dtsi" + }; + + panels { + panel@0 { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts new file mode 100644 index 0000000..c5e0424 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs with 1 thread per each */ + +/dts-v1/; + +#define AFF 00 + +#include "fvp-defs.dtsi" +#include "fvp-base-gicv3-psci-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts new file mode 100644 index 0000000..a31c703 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs with 1 thread per each */ + +/dts-v1/; + +#define AFF 00 +#define REG_32 + +#include "fvp-defs.dtsi" +#include "fvp-base-gicv3-psci-aarch32-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi new file mode 100644 index 0000000..85988e9 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, // GICD + <0x0 0x2f100000 0 0x200000>, // GICR + <0x0 0x2c000000 0 0x2000>, // GICC + <0x0 0x2c010000 0 0x2000>, // GICH + <0x0 0x2c02f000 0 0x2000>; // GICV + interrupts = <1 9 4>; + + its: its@2f020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x2f020000 0x0 0x20000>; // GITS + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 0 0 4>, + <0 0 1 &gic 0 0 0 1 4>, + <0 0 2 &gic 0 0 0 2 4>, + <0 0 3 &gic 0 0 0 3 4>, + <0 0 4 &gic 0 0 0 4 4>, + <0 0 5 &gic 0 0 0 5 4>, + <0 0 6 &gic 0 0 0 6 4>, + <0 0 7 &gic 0 0 0 7 4>, + <0 0 8 &gic 0 0 0 8 4>, + <0 0 9 &gic 0 0 0 9 4>, + <0 0 10 &gic 0 0 0 10 4>, + <0 0 11 &gic 0 0 0 11 4>, + <0 0 12 &gic 0 0 0 12 4>, + <0 0 13 &gic 0 0 0 13 4>, + <0 0 14 &gic 0 0 0 14 4>, + <0 0 15 &gic 0 0 0 15 4>, + <0 0 16 &gic 0 0 0 16 4>, + <0 0 17 &gic 0 0 0 17 4>, + <0 0 18 &gic 0 0 0 18 4>, + <0 0 19 &gic 0 0 0 19 4>, + <0 0 20 &gic 0 0 0 20 4>, + <0 0 21 &gic 0 0 0 21 4>, + <0 0 22 &gic 0 0 0 22 4>, + <0 0 23 &gic 0 0 0 23 4>, + <0 0 24 &gic 0 0 0 24 4>, + <0 0 25 &gic 0 0 0 25 4>, + <0 0 26 &gic 0 0 0 26 4>, + <0 0 27 &gic 0 0 0 27 4>, + <0 0 28 &gic 0 0 0 28 4>, + <0 0 29 &gic 0 0 0 29 4>, + <0 0 30 &gic 0 0 0 30 4>, + <0 0 31 &gic 0 0 0 31 4>, + <0 0 32 &gic 0 0 0 32 4>, + <0 0 33 &gic 0 0 0 33 4>, + <0 0 34 &gic 0 0 0 34 4>, + <0 0 35 &gic 0 0 0 35 4>, + <0 0 36 &gic 0 0 0 36 4>, + <0 0 37 &gic 0 0 0 37 4>, + <0 0 38 &gic 0 0 0 38 4>, + <0 0 39 &gic 0 0 0 39 4>, + <0 0 40 &gic 0 0 0 40 4>, + <0 0 41 &gic 0 0 0 41 4>, + <0 0 42 &gic 0 0 0 42 4>; + + #include "rtsm_ve-motherboard-aarch32.dtsi" + }; + + panels { + panel@0 { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts new file mode 100644 index 0000000..971b2e4 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs */ + +/dts-v1/; + +#define REG_32 +#define AFF + +#include "fvp-defs.dtsi" +#include "fvp-base-gicv3-psci-aarch32-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi new file mode 100644 index 0000000..3cb613f --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define LEVEL 0 +#define EDGE 2 +#define SDEI_NORMAL 0x70 +#define HIGHEST_SEC 0 + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + +#if (ENABLE_RME == 1) + chosen { bootargs = "mem=1G console=ttyAMA0 earlycon=pl011,0x1c090000 root=/dev/vda ip=on";}; +#else + chosen {}; +#endif + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + +#if SDEI_IN_FCONF || SEC_INT_DESC_IN_FCONF + firmware { +#if SDEI_IN_FCONF + sdei { + compatible = "arm,sdei-1.0"; + method = "smc"; + private_event_count = <3>; + shared_event_count = <3>; + /* + * Each event descriptor has typically 3 fields: + * 1. Event number + * 2. Interrupt number the event is bound to or + * if event is dynamic, specified as SDEI_DYN_IRQ + * 3. Bit map of event flags + */ + private_events = <1000 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, + <1001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, + <1002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>; + shared_events = <2000 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, + <2001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, + <2002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>; + }; +#endif /* SDEI_IN_FCONF */ + +#if SEC_INT_DESC_IN_FCONF + sec_interrupts { + compatible = "arm,secure_interrupt_desc"; + /* Number of G0 and G1 secure interrupts defined by the platform */ + g0_intr_cnt = <2>; + g1s_intr_cnt = <9>; + /* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. Each interrupt property descriptor has 3 fields: + * 1. Interrupt number + * 2. Interrupt priority + * 3. Type of interrupt (Edge or Level configured) + */ + g0_intr_desc = < 8 SDEI_NORMAL EDGE>, + <14 HIGHEST_SEC EDGE>; + + g1s_intr_desc = < 9 HIGHEST_SEC EDGE>, + <10 HIGHEST_SEC EDGE>, + <11 HIGHEST_SEC EDGE>, + <12 HIGHEST_SEC EDGE>, + <13 HIGHEST_SEC EDGE>, + <15 HIGHEST_SEC EDGE>, + <29 HIGHEST_SEC LEVEL>, + <56 HIGHEST_SEC LEVEL>, + <57 HIGHEST_SEC LEVEL>; + }; +#endif /* SEC_INT_DESC_IN_FCONF */ + }; +#endif /* SDEI_IN_FCONF || SEC_INT_DESC_IN_FCONF */ + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; +#if (ENABLE_RME == 1) + reg = <0x00000000 0x80000000 0 0x7C000000>, + <0x00000008 0x80000000 0 0x80000000>; +#else + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; +#endif + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, // GICD + <0x0 0x2f100000 0 0x200000>, // GICR + <0x0 0x2c000000 0 0x2000>, // GICC + <0x0 0x2c010000 0 0x2000>, // GICH + <0x0 0x2c02f000 0 0x2000>; // GICV + interrupts = <1 9 4>; + + its: its@2f020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x2f020000 0x0 0x20000>; // GITS + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb@0,0 { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #include "rtsm_ve-motherboard.dtsi" + }; + + panels { + panel { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts new file mode 100644 index 0000000..bda4b8d --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* DynamIQ configuration: 1 cluster with up to 8 CPUs with 2 threads per each */ + +/* Set default value if not passed from platform's makefile */ +#ifdef FVP_MAX_PE_PER_CPU +#define PE_PER_CPU FVP_MAX_PE_PER_CPU +#else +#define PE_PER_CPU 2 +#endif + +/dts-v1/; + +#include "fvp-base-gicv3-psci-dynamiq-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi new file mode 100644 index 0000000..42a439f --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +#include "fvp-defs-dynamiq.dtsi" +#include "fvp-base-gicv3-psci-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts new file mode 100644 index 0000000..b693f75 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* DynamIQ configuration: 1 cluster with up to 8 CPUs */ + +/* Set default value if not passed from platform's makefile */ +#ifdef FVP_MAX_PE_PER_CPU +#define PE_PER_CPU FVP_MAX_PE_PER_CPU +#else +#define PE_PER_CPU 1 +#endif + +/dts-v1/; + +#include "fvp-base-gicv3-psci-dynamiq-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts new file mode 100644 index 0000000..eb99472 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs */ + +/dts-v1/; + +#define AFF + +#include "fvp-defs.dtsi" +#include "fvp-base-gicv3-psci-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi b/arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi new file mode 100644 index 0000000..3659cd3 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_DEFS_DYNAMIQ_DTSI +#define FVP_DEFS_DYNAMIQ_DTSI + +/* Set default topology values if not passed from platform's makefile */ +#ifdef FVP_CLUSTER_COUNT +#define CLUSTER_COUNT FVP_CLUSTER_COUNT +#else +#define CLUSTER_COUNT 1 +#endif + +#ifdef FVP_MAX_CPUS_PER_CLUSTER +#define CPUS_PER_CLUSTER FVP_MAX_CPUS_PER_CLUSTER +#else +#define CPUS_PER_CLUSTER 8 +#endif + +#define CONCAT(x, y) x##y +#define CONC(x, y) CONCAT(x, y) + +/* + * n - CPU number + * r - MPID + */ +#define CPU(n, r) \ + CPU##n:cpu@r## { \ + device_type = "cpu"; \ + compatible = "arm,armv8"; \ + reg = <0x0 0x##r>; \ + enable-method = "psci"; \ + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; \ + next-level-cache = <&L2_0>; \ + }; + +#if (PE_PER_CPU == 2) +#define THREAD(n) \ + thread##n { \ + cpu = <&CONC(CPU, __COUNTER__)>; \ + }; + +#define CORE(n) \ + core##n { \ + THREAD(0) \ + THREAD(1) \ + }; + +#else /* PE_PER_CPU == 1 */ +#define CORE(n) \ + core##n { \ + cpu = <&CPU##n>;\ + }; +#endif /* PE_PER_CORE */ + +#if (CPUS_PER_CLUSTER == 1) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + }; + +#elif (CPUS_PER_CLUSTER == 2) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + }; + +#elif (CPUS_PER_CLUSTER == 3) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + }; + +#elif (CPUS_PER_CLUSTER == 4) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + }; + +#elif (CPUS_PER_CLUSTER == 5) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) \ + CPU(4, 400) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) \ + CPU(8, 400) \ + CPU(9, 401) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + CORE(4) \ + }; + +#elif (CPUS_PER_CLUSTER == 6) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) \ + CPU(4, 400) \ + CPU(5, 500) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) \ + CPU(8, 400) \ + CPU(9, 401) \ + CPU(10, 500) \ + CPU(11, 501) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + CORE(4) \ + CORE(5) \ + }; + +#elif (CPUS_PER_CLUSTER == 7) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) \ + CPU(4, 400) \ + CPU(5, 500) \ + CPU(6, 600) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) \ + CPU(8, 400) \ + CPU(9, 401) \ + CPU(10, 500) \ + CPU(11, 501) \ + CPU(12, 600) \ + CPU(13, 601) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + CORE(4) \ + CORE(5) \ + CORE(6) \ + }; + +#else +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) \ + CPU(4, 400) \ + CPU(5, 500) \ + CPU(6, 600) \ + CPU(7, 700) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) \ + CPU(8, 400) \ + CPU(9, 401) \ + CPU(10, 500) \ + CPU(11, 501) \ + CPU(12, 600) \ + CPU(13, 601) \ + CPU(14, 700) \ + CPU(15, 701) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + CORE(4) \ + CORE(5) \ + CORE(6) \ + CORE(7) \ + }; +#endif /* CPUS_PER_CLUSTER */ + +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + }; + +#endif /* FVP_DEFS_DYNAMIQ_DTSI */ diff --git a/arm-trusted-firmware/fdts/fvp-defs.dtsi b/arm-trusted-firmware/fdts/fvp-defs.dtsi new file mode 100644 index 0000000..1ffe65a --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-defs.dtsi @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_DEFS_DTSI +#define FVP_DEFS_DTSI + +/* Set default topology values if not passed from platform's makefile */ +#ifndef CLUSTER_COUNT +#ifdef FVP_CLUSTER_COUNT +#define CLUSTER_COUNT FVP_CLUSTER_COUNT +#else +#define CLUSTER_COUNT 2 +#endif +#endif /* CLUSTER_COUNT */ + +#ifndef CPUS_PER_CLUSTER +#ifdef FVP_MAX_CPUS_PER_CLUSTER +#define CPUS_PER_CLUSTER FVP_MAX_CPUS_PER_CLUSTER +#else +#define CPUS_PER_CLUSTER 4 +#endif +#endif /* CPUS_PER_CLUSTER */ + +/* Get platform's topology */ +#define CPUS_COUNT (CLUSTER_COUNT * CPUS_PER_CLUSTER) + +#define CONCAT(x, y) x##y +#define CONC(x, y) CONCAT(x, y) + +/* CPU's cluster */ +#define CLS(n) (n / CPUS_PER_CLUSTER) + +/* CPU's position in cluster */ +#define POS(n) (n % CPUS_PER_CLUSTER) + +#define ADR(n, c, p) \ + CPU##n:cpu@CONC(c, CONC(p, AFF)) { + +#define PRE \ + device_type = "cpu"; \ + compatible = "arm,armv8"; + +#ifdef REG_32 +/* 32-bit address */ +#define REG(c, p) \ + reg = ; +#else +/* 64-bit address */ +#define REG(c, p) \ + reg = <0x0 CONC(0x, CONC(c, CONC(p, AFF)))>; +#endif /* REG_32 */ + +#define POST \ + enable-method = "psci"; \ + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; \ + next-level-cache = <&L2_0>; \ + }; + +#ifdef REG_32 +#define CPU_0 \ + CPU0:cpu@0 { \ + PRE \ + reg = <0x0>; \ + POST +#else +#define CPU_0 \ + CPU0:cpu@0 { \ + PRE \ + reg = <0x0 0x0>;\ + POST +#endif /* REG_32 */ + +/* + * n - CPU number + */ +#define CPU(n, c, p) \ + ADR(n, c, p) \ + PRE \ + REG(c, p) \ + POST + +/* 2 CPUs */ +#if (CPUS_COUNT > 1) +#if (CLS(1) == 0) +#define c1 +#define p1 1 +#else +#define c1 10 +#define p1 0 +#endif + +#define CPU_1 CPU(1, c1, p1) /* CPU1: 0.1; 1.0 */ + +/* 3 CPUs */ +#if (CPUS_COUNT > 2) +#if (CLS(2) == 0) +#define c2 +#define p2 2 +#elif (CLS(2) == 1) +#define c2 10 +#define p2 0 +#else +#define c2 20 +#define p2 0 +#endif + +#define CPU_2 CPU(2, c2, p2) /* CPU2: 0.2; 1.0; 2.0 */ + +/* 4 CPUs */ +#if (CPUS_COUNT > 3) +#if (CLS(3) == 0) +#define c3 +#elif (CLS(3) == 1) +#define c3 10 +#else +#define c3 30 +#endif + +#if (POS(3) == 0) +#define p3 0 +#elif (POS(3) == 1) +#define p3 1 +#else +#define p3 3 +#endif + +#define CPU_3 CPU(3, c3, p3) /* CPU3: 0.3; 1.0; 1.1; 3.0 */ + +/* 6 CPUs */ +#if (CPUS_COUNT > 4) +#if (CLS(4) == 1) +#define c4 10 +#else +#define c4 20 +#endif + +#if (POS(4) == 0) +#define p4 0 +#else +#define p4 1 +#endif + +#if (CLS(5) == 1) +#define c5 10 +#else +#define c5 20 +#endif + +#if (POS(5) == 1) +#define p5 1 +#else +#define p5 2 +#endif + +#define CPU_4 CPU(4, c4, p4) /* CPU4: 1.0; 1.1; 2.0 */ +#define CPU_5 CPU(5, c5, p5) /* CPU5: 1.1; 1.2; 2.1 */ + +/* 8 CPUs */ +#if (CPUS_COUNT > 6) +#if (CLS(6) == 1) +#define c6 10 +#define p6 2 +#elif (CLS(6) == 2) +#define c6 20 +#define p6 0 +#else +#define c6 30 +#define p6 0 +#endif + +#if (CLS(7) == 1) +#define c7 10 +#define p7 3 +#elif (CLS(7) == 2) +#define c7 20 +#define p7 1 +#else +#define c7 30 +#define p7 1 +#endif + +#define CPU_6 CPU(6, c6, p6) /* CPU6: 1.2; 2.0; 3.0 */ +#define CPU_7 CPU(7, c7, p7) /* CPU7: 1.3; 2.1; 3.1 */ + +/* 9 CPUs */ +#if (CPUS_COUNT > 8) +#if (POS(8) == 0) +#define p8 0 +#else +#define p8 2 +#endif + +#define CPU_8 CPU(8, 20, p8) /* CPU8: 2.0; 2.2 */ + +/* 12 CPUs */ +#if (CPUS_COUNT > 9) +#if (CLS(9) == 2) +#define c9 20 +#define p9 1 +#else +#define c9 30 +#define p9 0 +#endif + +#if (CLS(10) == 2) +#define c10 20 +#define p10 2 +#else +#define c10 30 +#define p10 1 +#endif + +#if (CLS(11) == 2) +#define c11 20 +#define p11 3 +#else +#define c11 30 +#define p11 2 +#endif + +#define CPU_9 CPU(9, c9, p9) /* CPU9: 2.1; 3.0 */ +#define CPU_10 CPU(10, c10, p10) /* CPU10: 2.2; 3.1 */ +#define CPU_11 CPU(11, c11, p11) /* CPU11: 2.3; 3.2 */ + +/* 16 CPUs */ +#if (CPUS_COUNT > 12) +#define CPU_12 CPU(12, 30, 0) /* CPU12: 3.0 */ +#define CPU_13 CPU(13, 30, 1) /* CPU13: 3.1 */ +#define CPU_14 CPU(14, 30, 2) /* CPU14: 3.2 */ +#define CPU_15 CPU(15, 30, 3) /* CPU15: 3.3 */ +#endif /* > 12 */ +#endif /* > 9 */ +#endif /* > 8 */ +#endif /* > 6 */ +#endif /* > 4 */ +#endif /* > 3 */ +#endif /* > 2 */ +#endif /* > 1 */ + +#if (CPUS_COUNT == 1) +#define CPUS \ + CPU_0 + +#elif (CPUS_COUNT == 2) +#define CPUS \ + CPU_0 \ + CPU_1 + +#elif (CPUS_COUNT == 3) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 + +#elif (CPUS_COUNT == 4) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 + +#elif (CPUS_COUNT == 6) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 + +#elif (CPUS_COUNT == 8) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 \ + CPU_6 \ + CPU_7 + +#elif (CPUS_COUNT == 9) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 \ + CPU_6 \ + CPU_7 \ + CPU_8 + +#elif (CPUS_COUNT == 12) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 \ + CPU_6 \ + CPU_7 \ + CPU_8 \ + CPU_9 \ + CPU_10 \ + CPU_11 + +#else +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 \ + CPU_6 \ + CPU_7 \ + CPU_8 \ + CPU_9 \ + CPU_10 \ + CPU_11 \ + CPU_12 \ + CPU_13 \ + CPU_14 \ + CPU_15 +#endif /* CPUS_COUNT */ + +#define CORE(n) \ + core##n { \ + cpu = <&CONC(CPU, __COUNTER__)>; \ + }; + +/* Max 4 CPUs per cluster */ +#if (CPUS_PER_CLUSTER == 1) +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + }; +#elif (CPUS_PER_CLUSTER == 2) +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + }; + +#elif (CPUS_PER_CLUSTER == 3) +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + }; + +#else +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + }; +#endif /* CPUS_PER_CLUSTER */ + +/* Max 4 clusters */ +#if (CLUSTER_COUNT == 1) +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + }; + +#elif (CLUSTER_COUNT == 2) +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + CLUSTER(1) \ + }; + +#elif (CLUSTER_COUNT == 3) +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + CLUSTER(1) \ + CLUSTER(2) \ + }; + +#else +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + CLUSTER(1) \ + CLUSTER(2) \ + CLUSTER(3) \ + }; +#endif /* CLUSTER_COUNT */ + +#endif /* FVP_DEFS_DTSI */ diff --git a/arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts b/arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts new file mode 100644 index 0000000..5a82c46 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: 1 cluster with up to 4 CPUs */ + +/dts-v1/; + +#define AFF +#define CLUSTER_COUNT 1 + +#include +#include "fvp-defs.dtsi" + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Foundation"; + compatible = "arm,fvp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, + <0x0 0x2c000000 0 0x2000>, + <0x0 0x2c010000 0 0x2000>, + <0x0 0x2c02F000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #include "fvp-foundation-motherboard.dtsi" + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts b/arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts new file mode 100644 index 0000000..e1249d4 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: 1 cluster with up to 4 CPUs */ + +/dts-v1/; + +#define AFF +#define CLUSTER_COUNT 1 + +#include +#include "fvp-defs.dtsi" + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Foundation"; + compatible = "arm,fvp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, // GICD + <0x0 0x2f100000 0 0x200000>, // GICR + <0x0 0x2c000000 0 0x2000>, // GICC + <0x0 0x2c010000 0 0x2000>, // GICH + <0x0 0x2c02f000 0 0x2000>; // GICV + interrupts = <1 9 4>; + + its: its@2f020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x2f020000 0x0 0x20000>; // GITS + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #include "fvp-foundation-motherboard.dtsi" + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi b/arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi new file mode 100644 index 0000000..9ee5b64 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + ranges; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <0 15 4>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@10000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_sysctl: sysctl@20000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x020000 0x1000>; + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; + }; + + v2m_serial0: uart@90000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <0 5 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <0 6 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <0 7 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <0 8 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0f0000 0x1000>; + interrupts = <0 0 4>; + clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; + clock-names = "wdogclk", "apb_pclk"; + }; + + v2m_timer01: timer@110000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x110000 0x1000>; + interrupts = <0 2 4>; + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + v2m_timer23: timer@120000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x120000 0x1000>; + interrupts = <0 3 4>; + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + rtc@170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x170000 0x1000>; + interrupts = <0 4 4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + virtio_block@130000 { + compatible = "virtio,mmio"; + reg = <0x130000 0x1000>; + interrupts = <0 0x2a 4>; + }; + }; + + v2m_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + + mcc { + compatible = "arm,vexpress,config-bus", "simple-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + /* + * Not supported in FVP models + * + * reset@0 { + * compatible = "arm,vexpress-reset"; + * arm,vexpress-sysreg,func = <5 0>; + * }; + */ + + muxfpga@0 { + compatible = "arm,vexpress-muxfpga"; + arm,vexpress-sysreg,func = <7 0>; + }; + + /* + * Not used - Superseded by PSCI sys_poweroff + * + * shutdown@0 { + * compatible = "arm,vexpress-shutdown"; + * arm,vexpress-sysreg,func = <8 0>; + * }; + */ + + /* + * Not used - Superseded by PSCI sys_reset + * + * reboot@0 { + * compatible = "arm,vexpress-reboot"; + * arm,vexpress-sysreg,func = <9 0>; + * }; + */ + + dvimode@0 { + compatible = "arm,vexpress-dvimode"; + arm,vexpress-sysreg,func = <11 0>; + }; + }; + }; diff --git a/arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts b/arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts new file mode 100644 index 0000000..9d2d1d5 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "V2P-CA5s"; + compatible = "arm,vexpress,v2p-ca5s", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <0>; + }; + + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x1000000>; + }; + + hdlcd@2a110000 { + compatible = "arm,hdlcd"; + reg = <0x2a110000 0x1000>; + interrupts = <0 85 4>; + clocks = <&oscclk3>; + clock-names = "pxlclk"; + }; + + scu@2c000000 { + compatible = "arm,cortex-a5-scu"; + reg = <0x2c000000 0x58>; + }; + + watchdog@2c000620 { + compatible = "arm,cortex-a5-twd-wdt"; + reg = <0x2c000620 0x20>; + interrupts = <1 14 0x304>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x2c001000 0x1000>, + <0x2c000100 0x100>; + }; + + dcc { + compatible = "arm,vexpress,config-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + oscclk0: osc@0 { + /* CPU and internal AXI reference clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 0>; + freq-range = <50000000 100000000>; + #clock-cells = <0>; + clock-output-names = "oscclk0"; + }; + + oscclk1: osc@1 { + /* Multiplexed AXI master clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <5000000 50000000>; + #clock-cells = <0>; + clock-output-names = "oscclk1"; + }; + + osc@2 { + /* DDR2 */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 2>; + freq-range = <80000000 120000000>; + #clock-cells = <0>; + clock-output-names = "oscclk2"; + }; + + oscclk3: osc@3 { + /* HDLCD */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 3>; + freq-range = <23750000 165000000>; + #clock-cells = <0>; + clock-output-names = "oscclk3"; + }; + + osc@4 { + /* Test chip gate configuration */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 4>; + freq-range = <80000000 80000000>; + #clock-cells = <0>; + clock-output-names = "oscclk4"; + }; + + smbclk: osc@5 { + /* SMB clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 5>; + freq-range = <25000000 60000000>; + #clock-cells = <0>; + clock-output-names = "oscclk5"; + }; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x08000000 0x04000000>, + <1 0 0x14000000 0x04000000>, + <2 0 0x18000000 0x04000000>, + <3 0 0x1c000000 0x04000000>, + <4 0 0x0c000000 0x04000000>, + <5 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 42 &gic 0 42 4>; + + #include "rtsm_ve-motherboard-aarch32.dtsi" + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts b/arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts new file mode 100644 index 0000000..28de91d --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "V2F-1XV7 Cortex-A7x1 SMM"; + compatible = "arm,vexpress,v2f-1xv7", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0 0>; + }; + }; + + memory@0,80000000 { + device_type = "memory"; + reg = <0 0x80000000 0 0x80000000>; /* 2GB @ 2GB */ + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x2c001000 0 0x1000>, + <0 0x2c002000 0 0x1000>, + <0 0x2c004000 0 0x2000>, + <0 0x2c006000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + smbclk: refclk24mhzx2 { + /* Reference 24MHz clock x 2 */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "smclk"; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 42 &gic 0 42 4>; + + #include "rtsm_ve-motherboard-aarch32.dtsi" + }; +}; diff --git a/arm-trusted-firmware/fdts/juno-ethosn.dtsi b/arm-trusted-firmware/fdts/juno-ethosn.dtsi new file mode 100644 index 0000000..e2f3355 --- /dev/null +++ b/arm-trusted-firmware/fdts/juno-ethosn.dtsi @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * For examples of multi-core and multi-device NPU, refer to the examples given in the + * Arm Ethos-N NPU driver stack. + * https://github.com/ARM-software/ethos-n-driver-stack + */ + +/ { + #address-cells = <2>; + #size-cells = <2>; + + ethosn0: ethosn@6f300000 { + compatible = "ethosn"; + reg = <0 0x6f300000 0 0x00100000>; + status = "okay"; + + core0 { + compatible = "ethosn-core"; + status = "okay"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/juno.dts b/arm-trusted-firmware/fdts/juno.dts new file mode 100644 index 0000000..56fe167 --- /dev/null +++ b/arm-trusted-firmware/fdts/juno.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + +}; + +#if ARM_ETHOSN_NPU_DRIVER + #include "juno-ethosn.dtsi" +#endif diff --git a/arm-trusted-firmware/fdts/morello-fvp.dts b/arm-trusted-firmware/fdts/morello-fvp.dts new file mode 100644 index 0000000..55c87bf --- /dev/null +++ b/arm-trusted-firmware/fdts/morello-fvp.dts @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +#include "morello.dtsi" + +/ { + + chosen { + stdout-path = "serial0:115200n8"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + secure-firmware@ff000000 { + reg = <0 0xff000000 0 0x01000000>; + no-map; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + cluster1 { + core0 { + cpu = <&CPU2>; + }; + core1 { + cpu = <&CPU3>; + }; + }; + }; + CPU0: cpu0@0 { + compatible = "arm,armv8"; + reg = <0x0 0x0>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + }; + CPU1: cpu1@100 { + compatible = "arm,armv8"; + reg = <0x0 0x100>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + }; + CPU2: cpu2@10000 { + compatible = "arm,armv8"; + reg = <0x0 0x10000>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + }; + CPU3: cpu3@10100 { + compatible = "arm,armv8"; + reg = <0x0 0x10100>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + }; + }; + + /* The first bank of memory, memory map is actually provided by UEFI. */ + memory@80000000 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "memory"; + /* [0x80000000-0xffffffff] */ + reg = <0x00000000 0x80000000 0x0 0x80000000>; + }; + + memory@8080000000 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "memory"; + /* [0x8080000000-0x83ffffffff] */ + reg = <0x00000080 0x80000000 0x1 0x80000000>; + }; + + virtio_block@1c170000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c170000 0x0 0x200>; + interrupts = ; + }; + + virtio_net@1c180000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c180000 0x0 0x200>; + interrupts = ; + }; + + virtio_rng@1c190000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c190000 0x0 0x200>; + interrupts = ; + }; + + virtio_p9@1c1a0000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c1a0000 0x0 0x200>; + interrupts = ; + }; + + ethernet@1d100000 { + compatible = "smsc,lan91c111"; + reg = <0x0 0x1d100000 0x0 0x10000>; + interrupts = ; + }; + + kmi@1c150000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x0 0x1c150000 0x0 0x1000>; + interrupts = ; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@1c160000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x0 0x1c160000 0x0 0x1000>; + interrupts = ; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + firmware { + scmi { + compatible = "arm,scmi"; + mbox-names = "tx", "rx"; + mboxes = <&mailbox 1 0 &mailbox 1 1>; + shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>; + #address-cells = <1>; + #size-cells = <0>; + + scmi_dvfs: protocol@13 { + reg = <0x13>; + #clock-cells = <1>; + }; + }; + }; + + bp_clock24mhz: clock24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "bp:clock24mhz"; + }; +}; + +&gic { + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x300c0000 0 0x80000>; /* GICR */ + interrupts = ; +}; diff --git a/arm-trusted-firmware/fdts/morello-soc.dts b/arm-trusted-firmware/fdts/morello-soc.dts new file mode 100644 index 0000000..8464634 --- /dev/null +++ b/arm-trusted-firmware/fdts/morello-soc.dts @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +#include "morello.dtsi" + +/ { + + chosen { + stdout-path = "soc_uart0:115200n8"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + secure-firmware@ff000000 { + reg = <0 0xff000000 0 0x01000000>; + no-map; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + cpu0@0 { + compatible = "arm,armv8"; + reg = <0x0 0x0>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + }; + cpu1@100 { + compatible = "arm,armv8"; + reg = <0x0 0x100>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + }; + cpu2@10000 { + compatible = "arm,armv8"; + reg = <0x0 0x10000>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + }; + cpu3@10100 { + compatible = "arm,armv8"; + reg = <0x0 0x10100>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + }; + }; + + /* The first bank of memory, memory map is actually provided by UEFI. */ + memory@80000000 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "memory"; + /* [0x80000000-0xffffffff] */ + reg = <0x00000000 0x80000000 0x0 0x7F000000>; + }; + + memory@8080000000 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "memory"; + /* [0x8080000000-0x83f7ffffff] */ + reg = <0x00000080 0x80000000 0x3 0x78000000>; + }; + + smmu_pcie: iommu@4f400000 { + compatible = "arm,smmu-v3"; + reg = <0 0x4f400000 0 0x40000>; + interrupts = , + , + , + ; + interrupt-names = "eventq", "priq", "cmdq-sync", "gerror"; + msi-parent = <&its2 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + pcie_ctlr: pcie@28c0000000 { + compatible = "pci-host-ecam-generic"; + device_type = "pci"; + reg = <0x28 0xC0000000 0 0x10000000>; + bus-range = <0 255>; + linux,pci-domain = <0>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x00 0x6F000000 0x00 0x00800000>, + <0x02000000 0x00 0x60000000 0x00 0x60000000 0x00 0x0F000000>, + <0x42000000 0x09 0x00000000 0x09 0x00000000 0x1F 0xC0000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 170 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 171 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 172 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_pcie 0 0x10000>; + iommu-map = <0 &smmu_pcie 0 0x10000>; + status = "okay"; + }; + + smmu_ccix: iommu@4f000000 { + compatible = "arm,smmu-v3"; + reg = <0 0x4f000000 0 0x40000>; + interrupts = , + , + , + ; + interrupt-names = "eventq", "priq", "cmdq-sync", "gerror"; + msi-parent = <&its1 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + ccix_pcie_ctlr: pcie@4fc0000000 { + compatible = "pci-host-ecam-generic"; + device_type = "pci"; + reg = <0x4F 0xC0000000 0 0x10000000>; + bus-range = <0 255>; + linux,pci-domain = <1>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x00 0x7F000000 0x00 0x00800000>, + <0x02000000 0x00 0x70000000 0x00 0x70000000 0x00 0x0F000000>, + <0x42000000 0x30 0x00000000 0x30 0x00000000 0x1F 0xC0000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 201 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 202 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 203 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 204 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_ccix 0 0x10000>; + iommu-map = <0 &smmu_ccix 0 0x10000>; + status = "okay"; + }; + + smmu_dp: iommu@2ce00000 { + compatible = "arm,smmu-v3"; + reg = <0 0x2ce00000 0 0x40000>; + interrupts = , + , + ; + interrupt-names = "eventq", "cmdq-sync", "gerror"; + #iommu-cells = <1>; + }; + + dp0: display@2cc00000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "arm,mali-d32"; + reg = <0 0x2cc00000 0 0x20000>; + interrupts = <0 69 4>; + interrupt-names = "DPU"; + clocks = <&dpu_aclk>; + clock-names = "aclk"; + iommus = <&smmu_dp 0>, <&smmu_dp 1>, <&smmu_dp 2>, <&smmu_dp 3>, + <&smmu_dp 8>; + + pl0: pipeline@0 { + reg = <0>; + clocks = <&scmi_clk 1>; + clock-names = "pxclk"; + pl_id = <0>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + dp_pl0_out0: endpoint { + remote-endpoint = <&tda998x_0_input>; + }; + }; + }; + }; + }; + + i2c@1c0f0000 { + compatible = "cdns,i2c-r1p14"; + reg = <0x0 0x1c0f0000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <100000>; + i2c-sda-hold-time-ns = <500>; + interrupts = ; + clocks = <&dpu_aclk>; + + hdmi-transmitter@70 { + compatible = "nxp,tda998x"; + reg = <0x70>; + video-ports = <0x234501>; + port { + tda998x_0_input: endpoint { + remote-endpoint = <&dp_pl0_out0>; + }; + }; + }; + }; + + dpu_aclk: dpu_aclk { + /* 77.1 MHz derived from 24 MHz reference clock */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <350000000>; + clock-output-names = "aclk"; + }; + + firmware { + scmi { + compatible = "arm,scmi"; + mbox-names = "tx", "rx"; + mboxes = <&mailbox 1 0 &mailbox 1 1>; + shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>; + #address-cells = <1>; + #size-cells = <0>; + scmi_dvfs: protocol@13 { + reg = <0x13>; + #clock-cells = <1>; + }; + scmi_clk: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + }; + }; +}; + +&gic { + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x300c0000 0 0x80000>; /* GICR */ + interrupts = ; + + its1: its@30040000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30040000 0x0 0x20000>; + }; + + its2: its@30060000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30060000 0x0 0x20000>; + }; + + its_ccix: its@30080000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30080000 0x0 0x20000>; + }; + + its_pcie: its@300a0000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x300a0000 0x0 0x20000>; + }; +}; diff --git a/arm-trusted-firmware/fdts/morello.dtsi b/arm-trusted-firmware/fdts/morello.dtsi new file mode 100644 index 0000000..f119820 --- /dev/null +++ b/arm-trusted-firmware/fdts/morello.dtsi @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/ { + compatible = "arm,morello"; + + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &soc_uart0; + }; + + gic: interrupt-controller@2c010000 { + compatible = "arm,gic-600", "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + spe-pmu { + compatible = "arm,statistical-profiling-extension-v1"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + mailbox: mhu@45000000 { + compatible = "arm,mhu-doorbell", "arm,primecell"; + reg = <0x0 0x45000000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "mhu_lpri_rx", + "mhu_hpri_rx"; + #mbox-cells = <2>; + mbox-name = "ARM-MHU"; + clocks = <&soc_refclk50mhz>; + clock-names = "apb_pclk"; + }; + + sram: sram@45200000 { + compatible = "mmio-sram"; + reg = <0x0 0x06000000 0x0 0x8000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x06000000 0x8000>; + + cpu_scp_hpri0: scp-shmem@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x80>; + }; + + cpu_scp_hpri1: scp-shmem@80 { + compatible = "arm,scmi-shmem"; + reg = <0x80 0x80>; + }; + }; + + soc_refclk50mhz: refclk50mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "apb_pclk"; + }; + + soc_uartclk: uartclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "uartclk"; + }; + + soc_uart0: uart@2a400000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x2a400000 0x0 0x1000>; + interrupts = ; + clocks = <&soc_uartclk>, <&soc_refclk50mhz>; + clock-names = "uartclk", "apb_pclk"; + status = "okay"; + }; +}; diff --git a/arm-trusted-firmware/fdts/n1sdp-multi-chip.dts b/arm-trusted-firmware/fdts/n1sdp-multi-chip.dts new file mode 100644 index 0000000..8932dfc --- /dev/null +++ b/arm-trusted-firmware/fdts/n1sdp-multi-chip.dts @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) +/* + * Copyright (c) 2019-2020, Arm Limited. + */ + +#include "n1sdp-single-chip.dts" + +/ { + cpus { + cpu4@100000000 { + compatible = "arm,neoverse-n1"; + reg = <0x1 0x0>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu5@100000100 { + compatible = "arm,neoverse-n1"; + reg = <0x1 0x00000100>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu6@100010000 { + compatible = "arm,neoverse-n1"; + reg = <0x1 0x00010000>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu7@100010100 { + compatible = "arm,neoverse-n1"; + reg = <0x1 0x00010100>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <1>; + }; + }; + + /* Remote N1SDP board address is mapped at offset 4TB. + * First DRAM Bank of remote N1SDP board is mapped at 4TB + 2GB. + */ + memory@40080000000 { + device_type = "memory"; + reg = <0x00000400 0x80000000 0x0 0x80000000>, + <0x00000480 0x80000000 0x3 0x80000000>; + numa-node-id = <1>; + }; + + distance-map { + compatible = "numa-distance-map-v1"; + distance-matrix = <0 0 10>, + <0 1 20>, + <1 1 10>; + }; + + smmu_slave_pcie: iommu@4004f400000 { + compatible = "arm,smmu-v3"; + reg = <0x400 0x4f400000 0 0x40000>; + interrupts = , + , + ; + interrupt-names = "eventq", "cmdq-sync", "gerror"; + msi-parent = <&its2_slave 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + pcie_slave_ctlr: pcie@40070000000 { + compatible = "arm,n1sdp-pcie"; + device_type = "pci"; + reg = <0x400 0x70000000 0 0x1200000>; + bus-range = <0 0xff>; + linux,pci-domain = <2>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x400 0x75200000 0x00 0x00010000>, + <0x02000000 0x00 0x71200000 0x400 0x71200000 0x00 0x04000000>, + <0x42000000 0x09 0x00000000 0x409 0x00000000 0x20 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 649 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 650 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 651 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 652 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_slave_pcie 0 0x10000>; + iommu-map = <0 &smmu_slave_pcie 0 0x10000>; + status = "okay"; + }; + +}; + +&gic { + #redistributor-regions = <2>; + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x300c0000 0 0x80000>, /* GICR */ + <0x400 0x300c0000 0 0x80000>; /* GICR */ + + its2_slave: its@40030060000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x400 0x30060000 0x0 0x20000>; + }; + + its_slave_pcie: its@400300a0000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x400 0x300a0000 0x0 0x20000>; + }; +}; diff --git a/arm-trusted-firmware/fdts/n1sdp-single-chip.dts b/arm-trusted-firmware/fdts/n1sdp-single-chip.dts new file mode 100644 index 0000000..3c091ac --- /dev/null +++ b/arm-trusted-firmware/fdts/n1sdp-single-chip.dts @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) +/* + * Copyright (c) 2019-2020, Arm Limited. + */ + +/dts-v1/; + +#include "n1sdp.dtsi" + +/ { + model = "Arm Neoverse N1 System Development Platform"; + compatible = "arm,neoverse-n1-sdp", "arm,neoverse-n1-soc"; + + aliases { + serial0 = &soc_uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + /* This configuration assumes that standard setup with two DIMM modules. + * In the first 2GB of DRAM bank the top 16MB are reserved by firmware as secure memory. + * This configuration assumes 16GB of total DRAM being populated. + */ + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0x0 0x7f000000>, + <0x00000080 0x80000000 0x3 0x80000000>; + numa-node-id = <0>; + }; + + soc_refclk60mhz: refclk60mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <60000000>; + clock-output-names = "iofpga_clk"; + }; + + soc_hdlcdclk: hdlcdclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <23750000>; + clock-output-names = "hdlcdclk"; + }; + + hdlcd: hdlcd@1c050000 { + compatible = "arm,hdlcd"; + reg = <0 0x1c050000 0 0x1000>; + interrupts = ; + clocks = <&soc_hdlcdclk>; + clock-names = "pxlclk"; + + port { + hdlcd0_output: endpoint { + remote-endpoint = <&tda998x_0_input>; + }; + }; + }; + + i2c@1c0f0000 { + compatible = "arm,versatile-i2c"; + reg = <0x0 0x1c0f0000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + i2c-sda-hold-time-ns = <500>; + clocks = <&soc_refclk60mhz>; + + hdmi-transmitter@70 { + compatible = "nxp,tda998x"; + reg = <0x70>; + port { + tda998x_0_input: endpoint { + remote-endpoint = <&hdlcd0_output>; + }; + }; + }; + }; +}; + +&pcie_ctlr { + status = "okay"; +}; + +&ccix_pcie_ctlr { + status = "okay"; +}; + +&soc_uart0 { + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/n1sdp.dtsi b/arm-trusted-firmware/fdts/n1sdp.dtsi new file mode 100644 index 0000000..88f8734 --- /dev/null +++ b/arm-trusted-firmware/fdts/n1sdp.dtsi @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) +/* + * Copyright (c) 2019-2020, Arm Limited. + */ + +#include + +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0@0 { + compatible = "arm,neoverse-n1"; + reg = <0x0 0x0>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu1@100 { + compatible = "arm,neoverse-n1"; + reg = <0x0 0x100>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu2@10000 { + compatible = "arm,neoverse-n1"; + reg = <0x0 0x10000>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu3@10100 { + compatible = "arm,neoverse-n1"; + reg = <0x0 0x10100>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <0>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + spe-pmu { + compatible = "arm,statistical-profiling-extension-v1"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + soc_refclk100mhz: refclk100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + soc_uartclk: uartclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "uartclk"; + }; + + soc { + compatible = "arm,neoverse-n1-soc", "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gic: interrupt-controller@30000000 { + compatible = "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x300c0000 0 0x80000>; /* GICR */ + + interrupts = ; + + its1: its@30040000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30040000 0x0 0x20000>; + }; + + its2: its@30060000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30060000 0x0 0x20000>; + }; + + its_ccix: its@30080000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30080000 0x0 0x20000>; + }; + + its_pcie: its@300a0000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x300a0000 0x0 0x20000>; + }; + }; + + smmu_ccix: iommu@4f000000 { + compatible = "arm,smmu-v3"; + reg = <0 0x4f000000 0 0x40000>; + interrupts = , + , + ; + interrupt-names = "eventq", "cmdq-sync", "gerror"; + msi-parent = <&its1 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + smmu_pcie: iommu@4f400000 { + compatible = "arm,smmu-v3"; + reg = <0 0x4f400000 0 0x40000>; + interrupts = , + , + ; + interrupt-names = "eventq", "cmdq-sync", "gerror"; + msi-parent = <&its2 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + pcie_ctlr: pcie@70000000 { + compatible = "arm,n1sdp-pcie"; + device_type = "pci"; + reg = <0 0x70000000 0 0x1200000>; + bus-range = <0 17>; + linux,pci-domain = <0>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x00 0x75200000 0x00 0x00010000>, + <0x02000000 0x00 0x71200000 0x00 0x71200000 0x00 0x04000000>, + <0x42000000 0x09 0x00000000 0x09 0x00000000 0x20 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 170 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 171 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 172 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_pcie 0 0x10000>; + iommu-map = <0 &smmu_pcie 0 0x10000>; + status = "disabled"; + }; + + ccix_pcie_ctlr: pcie@68000000 { + compatible = "arm,n1sdp-pcie"; + device_type = "pci"; + reg = <0 0x68000000 0 0x1200000>; + bus-range = <0 17>; + linux,pci-domain = <1>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x00 0x6d200000 0x00 0x00010000>, + <0x02000000 0x00 0x69200000 0x00 0x69200000 0x00 0x04000000>, + <0x42000000 0x29 0x00000000 0x29 0x00000000 0x20 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 201 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 202 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 203 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 204 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_ccix 0 0x10000>; + iommu-map = <0 &smmu_ccix 0 0x10000>; + status = "disabled"; + }; + + soc_uart0: serial@2a400000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x2a400000 0x0 0x1000>; + interrupts = ; + clocks = <&soc_uartclk>, <&soc_refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi b/arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi new file mode 100644 index 0000000..7a8af8e --- /dev/null +++ b/arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + #interrupt-cells = <1>; + ranges; + + flash@0,00000000 { + compatible = "arm,vexpress-flash", "cfi-flash"; + reg = <0 0x00000000 0x04000000>, + <4 0x00000000 0x04000000>; + bank-width = <4>; + }; + + vram@2,00000000 { + compatible = "arm,vexpress-vram"; + reg = <2 0x00000000 0x00800000>; + }; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <15>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@10000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_sysctl: sysctl@20000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x020000 0x1000>; + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; + }; + + aaci@40000 { + compatible = "arm,pl041", "arm,primecell"; + reg = <0x040000 0x1000>; + interrupts = <11>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + mmci@50000 { + compatible = "arm,pl180", "arm,primecell"; + reg = <0x050000 0x1000>; + interrupts = <9 10>; + cd-gpios = <&v2m_sysreg 0 0>; + wp-gpios = <&v2m_sysreg 1 0>; + max-frequency = <12000000>; + vmmc-supply = <&v2m_fixed_3v3>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "mclk", "apb_pclk"; + }; + + kmi@60000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x060000 0x1000>; + interrupts = <12>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@70000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x070000 0x1000>; + interrupts = <13>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + v2m_serial0: uart@90000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <5>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <6>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <7>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <8>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0f0000 0x1000>; + interrupts = <0>; + clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; + clock-names = "wdogclk", "apb_pclk"; + }; + + v2m_timer01: timer@110000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x110000 0x1000>; + interrupts = <2>; + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + v2m_timer23: timer@120000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x120000 0x1000>; + interrupts = <3>; + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + rtc@170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x170000 0x1000>; + interrupts = <4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + clcd@1f0000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x1f0000 0x1000>; + interrupts = <14>; + clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; + clock-names = "clcdclk", "apb_pclk"; + mode = "XVGA"; + use_dma = <0>; + framebuffer = <0x18000000 0x00180000>; + }; + + virtio_block@130000 { + compatible = "virtio,mmio"; + reg = <0x130000 0x1000>; + interrupts = <0x2a>; + }; + }; + + v2m_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + mcc { + compatible = "arm,vexpress,config-bus", "simple-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + v2m_oscclk1: osc@1 { + /* CLCD clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <23750000 63500000>; + #clock-cells = <0>; + clock-output-names = "v2m:oscclk1"; + }; + + /* + * Not supported in FVP models + * + * reset@0 { + * compatible = "arm,vexpress-reset"; + * arm,vexpress-sysreg,func = <5 0>; + * }; + */ + + muxfpga@0 { + compatible = "arm,vexpress-muxfpga"; + arm,vexpress-sysreg,func = <7 0>; + }; + + /* + * Not used - Superseded by PSCI sys_poweroff + * + * shutdown@0 { + * compatible = "arm,vexpress-shutdown"; + * arm,vexpress-sysreg,func = <8 0>; + * }; + */ + + /* + * Not used - Superseded by PSCI sys_reset + * + * reboot@0 { + * compatible = "arm,vexpress-reboot"; + * arm,vexpress-sysreg,func = <9 0>; + * }; + */ + + dvimode@0 { + compatible = "arm,vexpress-dvimode"; + arm,vexpress-sysreg,func = <11 0>; + }; + }; + }; diff --git a/arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi b/arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi new file mode 100644 index 0000000..486f8a9 --- /dev/null +++ b/arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + ranges; + + flash@0,00000000 { + compatible = "arm,vexpress-flash", "cfi-flash"; + reg = <0 0x00000000 0x04000000>, + <4 0x00000000 0x04000000>; + bank-width = <4>; + }; + + vram@2,00000000 { + compatible = "arm,vexpress-vram"; + reg = <2 0x00000000 0x00800000>; + }; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <0 15 4>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@10000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_sysctl: sysctl@20000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x020000 0x1000>; + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; + }; + + aaci@40000 { + compatible = "arm,pl041", "arm,primecell"; + reg = <0x040000 0x1000>; + interrupts = <0 11 4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + mmci@50000 { + compatible = "arm,pl180", "arm,primecell"; + reg = <0x050000 0x1000>; + interrupts = <0 9 4 0 10 4>; + cd-gpios = <&v2m_sysreg 0 0>; + wp-gpios = <&v2m_sysreg 1 0>; + max-frequency = <12000000>; + vmmc-supply = <&v2m_fixed_3v3>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "mclk", "apb_pclk"; + }; + + kmi@60000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x060000 0x1000>; + interrupts = <0 12 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@70000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x070000 0x1000>; + interrupts = <0 13 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + v2m_serial0: uart@90000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <0 5 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <0 6 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <0 7 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <0 8 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0f0000 0x1000>; + interrupts = <0 0 4>; + clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; + clock-names = "wdogclk", "apb_pclk"; + }; + + v2m_timer01: timer@110000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x110000 0x1000>; + interrupts = <0 2 4>; + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + v2m_timer23: timer@120000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x120000 0x1000>; + interrupts = <0 3 4>; + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + rtc@170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x170000 0x1000>; + interrupts = <0 4 4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + clcd@1f0000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x1f0000 0x1000>; + interrupts = <0 14 4>; + clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; + clock-names = "clcdclk", "apb_pclk"; + mode = "XVGA"; + use_dma = <0>; + framebuffer = <0x18000000 0x00180000>; + }; + + virtio_block@130000 { + compatible = "virtio,mmio"; + reg = <0x130000 0x1000>; + interrupts = <0 0x2a 4>; + }; + }; + + v2m_fixed_3v3: fixedregulator { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + mcc { + compatible = "arm,vexpress,config-bus", "simple-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + v2m_oscclk1: osc { + /* CLCD clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <23750000 63500000>; + #clock-cells = <0>; + clock-output-names = "v2m:oscclk1"; + }; + + /* + * Not supported in FVP models + * + * reset@0 { + * compatible = "arm,vexpress-reset"; + * arm,vexpress-sysreg,func = <5 0>; + * }; + */ + + muxfpga { + compatible = "arm,vexpress-muxfpga"; + arm,vexpress-sysreg,func = <7 0>; + }; + + /* + * Not used - Superseded by PSCI sys_poweroff + * + * shutdown@0 { + * compatible = "arm,vexpress-shutdown"; + * arm,vexpress-sysreg,func = <8 0>; + * }; + */ + + /* + * Not used - Superseded by PSCI sys_reset + * + * reboot@0 { + * compatible = "arm,vexpress-reboot"; + * arm,vexpress-sysreg,func = <9 0>; + * }; + */ + + dvimode { + compatible = "arm,vexpress-dvimode"; + arm,vexpress-sysreg,func = <11 0>; + }; + }; + }; diff --git a/arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi b/arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi new file mode 100644 index 0000000..41d6e2e --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + */ + +/ { + aliases { +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-property/ mmc0; + /delete-property/ mmc1; +#endif + /delete-property/ ethernet0; + /delete-property/ ethernet1; + }; + + cpus { + cpu@0 { + /delete-property/ operating-points-v2; + }; + }; + + /delete-node/ cpu0-opp-table; + /delete-node/ psci; + + soc { + /delete-node/ sram@30000000; + /delete-node/ timer@40000000; + /delete-node/ timer@40001000; + /delete-node/ timer@40002000; + /delete-node/ timer@40003000; + /delete-node/ timer@40004000; + /delete-node/ timer@40005000; + /delete-node/ timer@40009000; + /delete-node/ spi@4000b000; + /delete-node/ audio-controller@4000b000; + /delete-node/ spi@4000c000; + /delete-node/ audio-controller@4000c000; + /delete-node/ audio-controller@4000d000; + /delete-node/ i2c@40012000; + /delete-node/ i2c@40013000; + /delete-node/ timer@44000000; + /delete-node/ timer@44001000; + /delete-node/ spi@44004000; + /delete-node/ audio-controller@44004000; + /delete-node/ sai@4400a000; + /delete-node/ sai@4400b000; + /delete-node/ dfsdm@4400d000; + /delete-node/ can@4400e000; + /delete-node/ can@4400f000; + /delete-node/ dma-controller@48000000; + /delete-node/ dma-controller@48001000; + /delete-node/ dma-router@48002000; + /delete-node/ adc@48003000; + /delete-node/ adc@48004000; + /delete-node/ dma@48005000; + /delete-node/ dma-router@48006000; +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usb-otg@49000000; +#endif + /delete-node/ spi@4c002000; + /delete-node/ spi@4c003000; + /delete-node/ timer@4c007000; + /delete-node/ timer@4c008000; + /delete-node/ timer@4c009000; + /delete-node/ timer@4c00a000; + /delete-node/ timer@4c00b000; + /delete-node/ timer@4c00c000; + /delete-node/ timer@50021000; + /delete-node/ timer@50022000; + /delete-node/ timer@50023000; + /delete-node/ timer@50024000; + /delete-node/ vrefbuf@50025000; + /delete-node/ thermal@50028000; + /delete-node/ hdp@5002a000; + /delete-node/ dma-controller@58000000; +#if !STM32MP_RAW_NAND + /delete-node/ memory-controller@58002000; +#endif +#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR + /delete-node/ spi@58003000; +#endif +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-node/ mmc@58005000; + /delete-node/ mmc@58007000; +#endif + /delete-node/ crc@58009000; + /delete-node/ stmmac-axi-config; + /delete-node/ eth1@5800a000; +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usbh-ohci@5800c000; + /delete-node/ usbh-ehci@5800d000; +#endif + /delete-node/ eth2@5800e000; + /delete-node/ dcmipp@5a000000; + /delete-node/ display-controller@5a001000; +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usbphyc@5a006000; +#endif + /delete-node/ perf@5a007000; + /delete-node/ rtc@5c004000; + /delete-node/ tamp@5c00a000; + /delete-node/ stgen@5c008000; + + pin-controller@50002000 { +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-node/ sdmmc1-b4-0; + /delete-node/ sdmmc2-b4-0; +#endif + }; + }; + + /* + * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in + * network order (big endian) + */ + + st-io_policies { + fip-handles { + compatible = "st,io-fip-handle"; + fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e"; + bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38"; + bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288"; + bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9"; + bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4"; + hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc"; + tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021"; + nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi b/arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi new file mode 100644 index 0000000..56eb36e --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + */ + +&ddr { + st,mem-name = DDR_MEM_NAME; + st,mem-speed = ; + st,mem-size = ; + + st,ctl-reg = < + DDR_MSTR + DDR_MRCTRL0 + DDR_MRCTRL1 + DDR_DERATEEN + DDR_DERATEINT + DDR_PWRCTL + DDR_PWRTMG + DDR_HWLPCTL + DDR_RFSHCTL0 + DDR_RFSHCTL3 + DDR_CRCPARCTL0 + DDR_ZQCTL0 + DDR_DFITMG0 + DDR_DFITMG1 + DDR_DFILPCFG0 + DDR_DFIUPD0 + DDR_DFIUPD1 + DDR_DFIUPD2 + DDR_DFIPHYMSTR + DDR_ODTMAP + DDR_DBG0 + DDR_DBG1 + DDR_DBGCMD + DDR_POISONCFG + DDR_PCCFG + >; + + st,ctl-timing = < + DDR_RFSHTMG + DDR_DRAMTMG0 + DDR_DRAMTMG1 + DDR_DRAMTMG2 + DDR_DRAMTMG3 + DDR_DRAMTMG4 + DDR_DRAMTMG5 + DDR_DRAMTMG6 + DDR_DRAMTMG7 + DDR_DRAMTMG8 + DDR_DRAMTMG14 + DDR_ODTCFG + >; + + st,ctl-map = < + DDR_ADDRMAP1 + DDR_ADDRMAP2 + DDR_ADDRMAP3 + DDR_ADDRMAP4 + DDR_ADDRMAP5 + DDR_ADDRMAP6 + DDR_ADDRMAP9 + DDR_ADDRMAP10 + DDR_ADDRMAP11 + >; + + st,ctl-perf = < + DDR_SCHED + DDR_SCHED1 + DDR_PERFHPR1 + DDR_PERFLPR1 + DDR_PERFWR1 + DDR_PCFGR_0 + DDR_PCFGW_0 + DDR_PCFGQOS0_0 + DDR_PCFGQOS1_0 + DDR_PCFGWQOS0_0 + DDR_PCFGWQOS1_0 + >; + + st,phy-reg = < + DDR_PGCR + DDR_ACIOCR + DDR_DXCCR + DDR_DSGCR + DDR_DCR + DDR_ODTCR + DDR_ZQ0CR1 + DDR_DX0GCR + DDR_DX1GCR + >; + + st,phy-timing = < + DDR_PTR0 + DDR_PTR1 + DDR_PTR2 + DDR_DTPR0 + DDR_DTPR1 + DDR_DTPR2 + DDR_MR0 + DDR_MR1 + DDR_MR2 + DDR_MR3 + >; +}; + +#undef DDR_MEM_NAME +#undef DDR_MEM_SPEED +#undef DDR_MEM_SIZE +#undef DDR_MSTR +#undef DDR_MRCTRL0 +#undef DDR_MRCTRL1 +#undef DDR_DERATEEN +#undef DDR_DERATEINT +#undef DDR_PWRCTL +#undef DDR_PWRTMG +#undef DDR_HWLPCTL +#undef DDR_RFSHCTL0 +#undef DDR_RFSHCTL3 +#undef DDR_RFSHTMG +#undef DDR_CRCPARCTL0 +#undef DDR_DRAMTMG0 +#undef DDR_DRAMTMG1 +#undef DDR_DRAMTMG2 +#undef DDR_DRAMTMG3 +#undef DDR_DRAMTMG4 +#undef DDR_DRAMTMG5 +#undef DDR_DRAMTMG6 +#undef DDR_DRAMTMG7 +#undef DDR_DRAMTMG8 +#undef DDR_DRAMTMG14 +#undef DDR_ZQCTL0 +#undef DDR_DFITMG0 +#undef DDR_DFITMG1 +#undef DDR_DFILPCFG0 +#undef DDR_DFIUPD0 +#undef DDR_DFIUPD1 +#undef DDR_DFIUPD2 +#undef DDR_DFIPHYMSTR +#undef DDR_ADDRMAP1 +#undef DDR_ADDRMAP2 +#undef DDR_ADDRMAP3 +#undef DDR_ADDRMAP4 +#undef DDR_ADDRMAP5 +#undef DDR_ADDRMAP6 +#undef DDR_ADDRMAP9 +#undef DDR_ADDRMAP10 +#undef DDR_ADDRMAP11 +#undef DDR_ODTCFG +#undef DDR_ODTMAP +#undef DDR_SCHED +#undef DDR_SCHED1 +#undef DDR_PERFHPR1 +#undef DDR_PERFLPR1 +#undef DDR_PERFWR1 +#undef DDR_DBG0 +#undef DDR_DBG1 +#undef DDR_DBGCMD +#undef DDR_POISONCFG +#undef DDR_PCCFG +#undef DDR_PCFGR_0 +#undef DDR_PCFGW_0 +#undef DDR_PCFGQOS0_0 +#undef DDR_PCFGQOS1_0 +#undef DDR_PCFGWQOS0_0 +#undef DDR_PCFGWQOS1_0 +#undef DDR_PGCR +#undef DDR_PTR0 +#undef DDR_PTR1 +#undef DDR_PTR2 +#undef DDR_ACIOCR +#undef DDR_DXCCR +#undef DDR_DSGCR +#undef DDR_DCR +#undef DDR_DTPR0 +#undef DDR_DTPR1 +#undef DDR_DTPR2 +#undef DDR_MR0 +#undef DDR_MR1 +#undef DDR_MR2 +#undef DDR_MR3 +#undef DDR_ODTCR +#undef DDR_ZQ0CR1 +#undef DDR_DX0GCR +#undef DDR_DX1GCR diff --git a/arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi b/arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi new file mode 100644 index 0000000..a5f7989 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * STM32MP135C DISCO BOARD configuration + * 1x DDR3L 4Gb, 16-bit, 533MHz. + * Reference used MT41K256M16TW-107 P from Micron + * + * DDR type / Platform DDR3/3L + * freq 533MHz + * width 16 + * datasheet 1 + * DDR density 4 + * timing mode optimized + * Scheduling/QoS options : type = 6 + * address mapping : RBC + * Tc > + 85C : N + */ +#define DDR_MEM_NAME "DDR3-1066 bin F 1x4Gb 533MHz v1.53" +#define DDR_MEM_SPEED 533000 +#define DDR_MEM_SIZE 0x20000000 + +#define DDR_MSTR 0x00040401 +#define DDR_MRCTRL0 0x00000010 +#define DDR_MRCTRL1 0x00000000 +#define DDR_DERATEEN 0x00000000 +#define DDR_DERATEINT 0x00800000 +#define DDR_PWRCTL 0x00000000 +#define DDR_PWRTMG 0x00400010 +#define DDR_HWLPCTL 0x00000000 +#define DDR_RFSHCTL0 0x00210000 +#define DDR_RFSHCTL3 0x00000000 +#define DDR_RFSHTMG 0x0081008B +#define DDR_CRCPARCTL0 0x00000000 +#define DDR_DRAMTMG0 0x121B2414 +#define DDR_DRAMTMG1 0x000A041B +#define DDR_DRAMTMG2 0x0607080F +#define DDR_DRAMTMG3 0x0050400C +#define DDR_DRAMTMG4 0x07040607 +#define DDR_DRAMTMG5 0x06060403 +#define DDR_DRAMTMG6 0x02020002 +#define DDR_DRAMTMG7 0x00000202 +#define DDR_DRAMTMG8 0x00001005 +#define DDR_DRAMTMG14 0x000000A0 +#define DDR_ZQCTL0 0xC2000040 +#define DDR_DFITMG0 0x02050105 +#define DDR_DFITMG1 0x00000202 +#define DDR_DFILPCFG0 0x07000000 +#define DDR_DFIUPD0 0xC0400003 +#define DDR_DFIUPD1 0x00000000 +#define DDR_DFIUPD2 0x00000000 +#define DDR_DFIPHYMSTR 0x00000000 +#define DDR_ADDRMAP1 0x00080808 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x00000000 +#define DDR_ADDRMAP4 0x00001F1F +#define DDR_ADDRMAP5 0x07070707 +#define DDR_ADDRMAP6 0x0F070707 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 +#define DDR_ODTCFG 0x06000600 +#define DDR_ODTMAP 0x00000001 +#define DDR_SCHED 0x00000F01 +#define DDR_SCHED1 0x00000000 +#define DDR_PERFHPR1 0x00000001 +#define DDR_PERFLPR1 0x04000200 +#define DDR_PERFWR1 0x08000400 +#define DDR_DBG0 0x00000000 +#define DDR_DBG1 0x00000000 +#define DDR_DBGCMD 0x00000000 +#define DDR_POISONCFG 0x00000000 +#define DDR_PCCFG 0x00000010 +#define DDR_PCFGR_0 0x00000000 +#define DDR_PCFGW_0 0x00000000 +#define DDR_PCFGQOS0_0 0x00100009 +#define DDR_PCFGQOS1_0 0x00000020 +#define DDR_PCFGWQOS0_0 0x01100B03 +#define DDR_PCFGWQOS1_0 0x01000200 +#define DDR_PGCR 0x01442E02 +#define DDR_PTR0 0x0022AA5B +#define DDR_PTR1 0x04841104 +#define DDR_PTR2 0x042DA068 +#define DDR_ACIOCR 0x10400812 +#define DDR_DXCCR 0x00000C40 +#define DDR_DSGCR 0xF200011F +#define DDR_DCR 0x0000000B +#define DDR_DTPR0 0x36D477D0 +#define DDR_DTPR1 0x098B00D8 +#define DDR_DTPR2 0x10023600 +#define DDR_MR0 0x00000830 +#define DDR_MR1 0x00000000 +#define DDR_MR2 0x00000208 +#define DDR_MR3 0x00000000 +#define DDR_ODTCR 0x00010000 +#define DDR_ZQ0CR1 0x00000038 +#define DDR_DX0GCR 0x0000CE81 +#define DDR_DX1GCR 0x0000CE81 + +#include "stm32mp13-ddr.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi b/arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi new file mode 100644 index 0000000..dc8ca1b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + */ + +#include +#include + +#include + +#ifndef DDR_SIZE +#error "DDR_SIZE is not defined" +#endif + +#define DDR_NS_BASE STM32MP_DDR_BASE +#define DDR_SEC_SIZE 0x01e00000 +#define DDR_SEC_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SEC_SIZE)) +#define DDR_SHARE_SIZE 0x00200000 +#define DDR_SHARE_BASE (DDR_SEC_BASE - DDR_SHARE_SIZE) +#define DDR_NS_SIZE (DDR_SHARE_BASE - DDR_NS_BASE) + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + hw-config { + load-address = <0x0 STM32MP_HW_CONFIG_BASE>; + max-size = ; + id = ; + }; + + nt_fw { + load-address = <0x0 STM32MP_BL33_BASE>; + max-size = ; + id = ; + }; + + tos_fw { + load-address = <0x0 DDR_SEC_BASE>; + max-size = ; + id = ; + }; + }; + + st-mem-firewall { + compatible = "st,mem-firewall"; + memory-ranges = < + DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR + DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) + DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi new file mode 100644 index 0000000..0ad06a4 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue + */ +#include + +&pinctrl { + i2c4_pins_a: i2c4-0 { + pins { + pinmux = , /* I2C4_SCL */ + ; /* I2C4_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + sdmmc1_b4_pins_a: sdmmc1-b4-0 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + , /* SDMMC1_D3 */ + ; /* SDMMC1_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc2_b4_pins_a: sdmmc2-b4-0 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + }; + + uart4_pins_a: uart4-0 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + usart1_pins_a: usart1-0 { + pins1 { + pinmux = , /* USART1_TX */ + ; /* USART1_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART1_RX */ + ; /* USART1_CTS_NSS */ + bias-pull-up; + }; + }; + + uart8_pins_a: uart8-0 { + pins1 { + pinmux = ; /* UART8_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART8_RX */ + bias-pull-up; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp131.dtsi b/arm-trusted-firmware/fdts/stm32mp131.dtsi new file mode 100644 index 0000000..dff1b33 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp131.dtsi @@ -0,0 +1,621 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <0>; + clocks = <&rcc CK_MPU>; + clock-names = "cpu"; + nvmem-cells = <&part_number_otp>; + nvmem-cell-names = "part_number"; + }; + }; + + nvmem_layout: nvmem_layout@0 { + compatible = "st,stm32-nvmem-layout"; + + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&nand2_otp>, + <&uid_otp>, + <&hw2_otp>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "nand2_otp", + "uid_otp", + "hw2_otp"; + }; + + clocks { + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + }; + + intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, + <0xa0022000 0x2000>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges; + + usart3: serial@4000f000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000f000 0x400>; + interrupts = ; + clocks = <&rcc USART3_K>; + resets = <&rcc USART3_R>; + status = "disabled"; + }; + + uart4: serial@40010000 { + compatible = "st,stm32h7-uart"; + reg = <0x40010000 0x400>; + interrupts = ; + clocks = <&rcc UART4_K>; + resets = <&rcc UART4_R>; + status = "disabled"; + }; + + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; + interrupts = ; + clocks = <&rcc UART5_K>; + resets = <&rcc UART5_R>; + status = "disabled"; + }; + + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; + interrupts = ; + clocks = <&rcc UART7_K>; + resets = <&rcc UART7_R>; + status = "disabled"; + }; + + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; + interrupts = ; + clocks = <&rcc UART8_K>; + resets = <&rcc UART8_R>; + status = "disabled"; + }; + + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; + interrupts = ; + clocks = <&rcc USART6_K>; + resets = <&rcc USART6_R>; + status = "disabled"; + }; + + usbotg_hs: usb-otg@49000000 { + compatible = "st,stm32mp15-hsotg", "snps,dwc2"; + reg = <0x49000000 0x40000>; + clocks = <&rcc USBO_K>; + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; + interrupts = ; + g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <32>; + g-tx-fifo-size = <256 16 16 16 16 16 16 16>; + dr_mode = "otg"; + usb33d-supply = <&usb33>; + status = "disabled"; + }; + + usart1: serial@4c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x4c000000 0x400>; + interrupts = ; + clocks = <&rcc USART1_K>; + resets = <&rcc USART1_R>; + status = "disabled"; + }; + + usart2: serial@4c001000 { + compatible = "st,stm32h7-uart"; + reg = <0x4c001000 0x400>; + interrupts = ; + clocks = <&rcc USART2_K>; + resets = <&rcc USART2_R>; + status = "disabled"; + }; + + i2c3: i2c@4c004000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c004000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 23 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C3_K>; + resets = <&rcc I2C3_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x4>; + i2c-analog-filter; + status = "disabled"; + }; + + i2c4: i2c@4c005000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c005000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C4_K>; + resets = <&rcc I2C4_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x8>; + i2c-analog-filter; + status = "disabled"; + }; + + i2c5: i2c@4c006000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c006000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 25 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C5_K>; + resets = <&rcc I2C5_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x10>; + i2c-analog-filter; + status = "disabled"; + }; + + rcc: rcc@50000000 { + compatible = "st,stm32mp13-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <1>; + #reset-cells = <1>; + interrupts = ; + secure-interrupts = ; + secure-interrupt-names = "wakeup"; + }; + + pwr_regulators: pwr@50001000 { + compatible = "st,stm32mp1,pwr-reg"; + reg = <0x50001000 0x10>; + + reg11: reg11 { + regulator-name = "reg11"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + reg18: reg18 { + regulator-name = "reg18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + usb33: usb33 { + regulator-name = "usb33"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + + exti: interrupt-controller@5000d000 { + compatible = "st,stm32mp13-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000d000 0x400>; + }; + + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + clocks = <&rcc SYSCFG>; + }; + + vrefbuf: vrefbuf@50025000 { + compatible = "st,stm32-vrefbuf"; + reg = <0x50025000 0x8>; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <2500000>; + clocks = <&rcc VREF>; + status = "disabled"; + }; + + hash: hash@54003000 { + compatible = "st,stm32mp13-hash"; + reg = <0x54003000 0x400>; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; + status = "disabled"; + }; + + rng: rng@54004000 { + compatible = "st,stm32mp13-rng"; + reg = <0x54004000 0x400>; + clocks = <&rcc RNG1_K>; + resets = <&rcc RNG1_R>; + status = "disabled"; + }; + + fmc: memory-controller@58002000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "st,stm32mp1-fmc2-ebi"; + reg = <0x58002000 0x1000>; + clocks = <&rcc FMC_K>; + resets = <&rcc FMC_R>; + status = "disabled"; + + ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ + <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ + <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ + <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ + <4 0 0x80000000 0x10000000>; /* NAND */ + + nand-controller@4,0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32mp1-fmc2-nfc"; + reg = <4 0x00000000 0x1000>, + <4 0x08010000 0x1000>, + <4 0x08020000 0x1000>, + <4 0x01000000 0x1000>, + <4 0x09010000 0x1000>, + <4 0x09020000 0x1000>; + interrupts = ; + status = "disabled"; + }; + }; + + qspi: spi@58003000 { + compatible = "st,stm32f469-qspi"; + reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; + interrupts = ; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; + status = "disabled"; + }; + + sdmmc1: mmc@58005000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x20253180>; + reg = <0x58005000 0x1000>, <0x58006000 0x1000>; + clocks = <&rcc SDMMC1_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC1_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + sdmmc2: mmc@58007000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x20253180>; + reg = <0x58007000 0x1000>, <0x58008000 0x1000>; + clocks = <&rcc SDMMC2_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC2_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + crc1: crc@58009000 { + compatible = "st,stm32f7-crc"; + reg = <0x58009000 0x400>; + clocks = <&rcc CRC1>; + }; + + usbh_ohci: usbh-ohci@5800c000 { + compatible = "generic-ohci"; + reg = <0x5800c000 0x1000>; + clocks = <&rcc USBH>; + resets = <&rcc USBH_R>; + interrupts = ; + status = "disabled"; + }; + + usbh_ehci: usbh-ehci@5800d000 { + compatible = "generic-ehci"; + reg = <0x5800d000 0x1000>; + clocks = <&rcc USBH>; + resets = <&rcc USBH_R>; + interrupts = ; + companion = <&usbh_ohci>; + status = "disabled"; + }; + + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + ddr: ddr@5a003000{ + compatible = "st,stm32mp13-ddr"; + reg = <0x5a003000 0x550>, <0x5a004000 0x234>; + clocks = <&rcc AXIDCG>, + <&rcc DDRC1>, + <&rcc DDRPHYC>, + <&rcc DDRCAPB>, + <&rcc DDRPHYCAPB>; + clock-names = "axidcg", + "ddrc1", + "ddrphyc", + "ddrcapb", + "ddrphycapb"; + }; + + usbphyc: usbphyc@5a006000 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "st,stm32mp1-usbphyc"; + reg = <0x5a006000 0x1000>; + clocks = <&rcc USBPHY_K>; + resets = <&rcc USBPHY_R>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; + status = "disabled"; + + usbphyc_port0: usb-phy@0 { + #phy-cells = <0>; + reg = <0>; + }; + + usbphyc_port1: usb-phy@1 { + #phy-cells = <1>; + reg = <1>; + }; + }; + + iwdg1: watchdog@5c003000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5c003000 0x400>; + interrupts = ; + clocks = <&rcc IWDG1>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + bsec: efuse@5c005000 { + compatible = "st,stm32mp15-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + + cfg0_otp: cfg0_otp@0 { + reg = <0x0 0x2>; + }; + part_number_otp: part_number_otp@4 { + reg = <0x4 0x2>; + }; + monotonic_otp: monotonic_otp@10 { + reg = <0x10 0x4>; + }; + nand_otp: cfg9_otp@24 { + reg = <0x24 0x4>; + }; + nand2_otp: cfg10_otp@28 { + reg = <0x28 0x4>; + }; + uid_otp: uid_otp@34 { + reg = <0x34 0xc>; + }; + hw2_otp: hw2_otp@48 { + reg = <0x48 0x4>; + }; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; + pkh_otp: pkh_otp@60 { + reg = <0x60 0x20>; + }; + mac_addr: mac_addr@e4 { + reg = <0xe4 0xc>; + st,non-secure-otp; + }; + }; + + tamp: tamp@5c00a000 { + reg = <0x5c00a000 0x400>; + }; + + /* + * Break node order to solve dependency probe issue between + * pinctrl and exti. + */ + pinctrl: pin-controller@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp135-pinctrl"; + ranges = <0 0x50002000 0x8400>; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; + pins-are-numbered; + + gpioa: gpio@50002000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x0 0x400>; + clocks = <&rcc GPIOA>; + st,bank-name = "GPIOA"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x1000 0x400>; + clocks = <&rcc GPIOB>; + st,bank-name = "GPIOB"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x2000 0x400>; + clocks = <&rcc GPIOC>; + st,bank-name = "GPIOC"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x3000 0x400>; + clocks = <&rcc GPIOD>; + st,bank-name = "GPIOD"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x4000 0x400>; + clocks = <&rcc GPIOE>; + st,bank-name = "GPIOE"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000 0x400>; + clocks = <&rcc GPIOF>; + st,bank-name = "GPIOF"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x6000 0x400>; + clocks = <&rcc GPIOG>; + st,bank-name = "GPIOG"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x7000 0x400>; + clocks = <&rcc GPIOH>; + st,bank-name = "GPIOH"; + ngpios = <15>; + gpio-ranges = <&pinctrl 0 112 15>; + }; + + gpioi: gpio@5000a000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x8000 0x400>; + clocks = <&rcc GPIOI>; + st,bank-name = "GPIOI"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 128 8>; + }; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp133.dtsi b/arm-trusted-firmware/fdts/stm32mp133.dtsi new file mode 100644 index 0000000..8bbcc61 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp133.dtsi @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp131.dtsi" + +/ { + soc { + m_can1: can@4400e000 { + reg = <0x4400e000 0x400>, <0x44011000 0x1400>; + status = "disabled"; + }; + + m_can2: can@4400f000 { + reg = <0x4400f000 0x400>, <0x44011000 0x2800>; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp135.dtsi b/arm-trusted-firmware/fdts/stm32mp135.dtsi new file mode 100644 index 0000000..415bb9b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp135.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp133.dtsi" + +/ { + soc { + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts new file mode 100644 index 0000000..21f8242 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp13-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp135f-dk.dts b/arm-trusted-firmware/fdts/stm32mp135f-dk.dts new file mode 100644 index 0000000..0fa064b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp135f-dk.dts @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include +#include "stm32mp135.dtsi" +#include "stm32mp13xf.dtsi" +#include "stm32mp13-ddr3-1x4Gb-1066-binF.dtsi" +#include "stm32mp13-pinctrl.dtsi" + +/ { + model = "STMicroelectronics STM32MP135F-DK Discovery Board"; + compatible = "st,stm32mp135f-dk", "st,stm32mp135"; + + aliases { + serial0 = &uart4; + serial1 = &usart1; + serial2 = &uart8; + serial3 = &usart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + v3v3_ao: v3v3_ao { + compatible = "regulator-fixed"; + regulator-name = "v3v3_ao"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; +}; + +&bsec { + board_id: board_id@f0 { + reg = <0xf0 0x4>; + st,non-secure-otp; + }; +}; + +&cpu0 { + cpu-supply = <&vddcpu>; +}; + +&hash { + status = "okay"; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "disabled"; + secure-status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + + status = "disabled"; + secure-status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&vin>; + ldo4-supply = <&vin>; + ldo5-supply = <&vin>; + ldo6-supply = <&vin>; + vref_ddr-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&v3v3_ao>; + + vddcpu: buck1 { + regulator-name = "vddcpu"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-over-current-protection; + }; + + vddcore: buck4 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_adc: ldo1 { + regulator-name = "vdd_adc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + v1v8_periph: ldo6 { + regulator-name = "v1v8_periph"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + v3v3_sw: pwr_sw2 { + regulator-name = "v3v3_sw"; + regulator-active-discharge = <1>; + regulator-always-on; + }; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&nvmem_layout { + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&nand2_otp>, + <&uid_otp>, + <&hw2_otp>, + <&pkh_otp>, + <&board_id>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "nand2_otp", + "uid_otp", + "hw2_otp", + "pkh_otp", + "board_id"; +}; + +&pka { + secure-status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MLAHBS_PLL3 + CLK_CKPER_HSE + CLK_RTC_LSE + CLK_SDMMC1_PLL4P + CLK_SDMMC2_PLL4P + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_I2C4_HSI + CLK_USBO_USBPHY + CLK_I2C12_HSI + CLK_UART2_HSI + CLK_UART4_HSI + CLK_SAES_AXI + >; + + st,clkdiv = < + DIV(DIV_AXI, 0) + DIV(DIV_MLAHB, 0) + DIV(DIV_APB1, 1) + DIV(DIV_APB2, 1) + DIV(DIV_APB3, 1) + DIV(DIV_APB4, 1) + DIV(DIV_APB5, 2) + DIV(DIV_APB6, 1) + DIV(DIV_RTC, 0) + >; + + st,pll_vco { + pll1_vco_1300Mhz: pll1-vco-1300Mhz { + src = < CLK_PLL12_HSE >; + divmn = < 2 80 >; + frac = < 0x800 >; + }; + + pll2_vco_1066Mhz: pll2-vco-1066Mhz { + src = < CLK_PLL12_HSE >; + divmn = < 2 65 >; + frac = < 0x1400 >; + }; + + pll3_vco_417_8Mhz: pll2-vco-417_8Mhz { + src = < CLK_PLL3_HSE >; + divmn = < 1 33 >; + frac = < 0x1a04 >; + }; + + pll4_vco_600Mhz: pll2-vco-600Mhz { + src = < CLK_PLL4_HSE >; + divmn = < 1 49 >; + }; + }; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1:st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + + st,pll = < &pll1_cfg1 >; + + pll1_cfg1: pll1_cfg1 { + st,pll_vco = < &pll1_vco_1300Mhz >; + st,pll_div_pqr = < 0 1 1 >; + }; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 266, R = 533 (DDR) */ + pll2:st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + + st,pll = < &pll2_cfg1 >; + + pll2_cfg1: pll2_cfg1 { + st,pll_vco = < &pll2_vco_1066Mhz >; + st,pll_div_pqr = < 1 1 0 >; + }; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 209 */ + pll3:st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + + st,pll = < &pll3_cfg1 >; + + pll3_cfg1: pll3_cfg1 { + st,pll_vco = < &pll3_vco_417_8Mhz >; + st,pll_div_pqr = < 1 16 1 >; + }; + }; + + /* VCO = 600.0 MHz => P = 50, Q = 10, R = 100 */ + pll4:st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + + st,pll = < &pll4_cfg1 >; + + pll4_cfg1: pll4_cfg1 { + st,pll_vco = < &pll4_vco_600Mhz >; + st,pll_div_pqr = < 11 59 5 >; + }; + }; +}; + +&rng { + status = "okay"; +}; + +&saes { + secure-status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; + +&uart8 { + pinctrl-names = "default"; + pinctrl-0 = <&uart8_pins_a>; + status = "disabled"; +}; + +&usart1 { + pinctrl-names = "default"; + pinctrl-0 = <&usart1_pins_a>; + uart-has-rtscts; + status = "disabled"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp13xa.dtsi b/arm-trusted-firmware/fdts/stm32mp13xa.dtsi new file mode 100644 index 0000000..0ef2fce --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13xa.dtsi @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ diff --git a/arm-trusted-firmware/fdts/stm32mp13xc.dtsi b/arm-trusted-firmware/fdts/stm32mp13xc.dtsi new file mode 100644 index 0000000..c03bd43 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13xc.dtsi @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp13xa.dtsi" + +/ { + soc { + cryp: crypto@54002000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + + saes: saes@54005000 { + compatible = "st,stm32-saes"; + reg = <0x54005000 0x400>; + clocks = <&rcc SAES_K>; + resets = <&rcc SAES_R>; + status = "disabled"; + }; + + pka: pka@54006000 { + compatible = "st,stm32-pka64"; + reg = <0x54006000 0x2000>; + clocks = <&rcc PKA>; + resets = <&rcc PKA_R>; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp13xd.dtsi b/arm-trusted-firmware/fdts/stm32mp13xd.dtsi new file mode 100644 index 0000000..0ef2fce --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13xd.dtsi @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ diff --git a/arm-trusted-firmware/fdts/stm32mp13xf.dtsi b/arm-trusted-firmware/fdts/stm32mp13xf.dtsi new file mode 100644 index 0000000..e467d71 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13xf.dtsi @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include "stm32mp13xd.dtsi" + +/ { + soc { + cryp: crypto@54002000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + + saes: saes@54005000 { + compatible = "st,stm32-saes"; + reg = <0x54005000 0x400>; + clocks = <&rcc SAES_K>; + resets = <&rcc SAES_R>; + status = "disabled"; + }; + + pka: pka@54006000 { + compatible = "st,stm32-pka64"; + reg = <0x54006000 0x2000>; + clocks = <&rcc PKA>; + resets = <&rcc PKA_R>; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi b/arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi new file mode 100644 index 0000000..d00e35b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2020-2022 - All Rights Reserved + */ + +/ { +#if !STM32MP_EMMC && !STM32MP_SDMMC + aliases { + /delete-property/ mmc0; + /delete-property/ mmc1; + }; +#endif + + cpus { + /delete-node/ cpu@1; + }; + + /delete-node/ psci; + + soc { + /delete-node/ timer@40006000; + /delete-node/ timer@44006000; +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usb-otg@49000000; +#endif + /delete-node/ pwr_mcu@50001014; + /delete-node/ cryp@54001000; + /delete-node/ rng@54003000; +#if !STM32MP_RAW_NAND + /delete-node/ memory-controller@58002000; +#endif +#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR + /delete-node/ spi@58003000; +#endif +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-node/ mmc@58005000; + /delete-node/ mmc@58007000; +#endif +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usbphyc@5a006000; +#endif + /delete-node/ spi@5c001000; + /delete-node/ rtc@5c004000; + /delete-node/ etzpc@5c007000; + /delete-node/ stgen@5c008000; + /delete-node/ i2c@5c009000; + /delete-node/ tamp@5c00a000; + + pin-controller@50002000 { +#if !STM32MP_RAW_NAND + /delete-node/ fmc-0; +#endif +#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR + /delete-node/ qspi-clk-0; + /delete-node/ qspi-bk1-0; + /delete-node/ qspi-bk2-0; +#endif +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-node/ sdmmc1-b4-0; + /delete-node/ sdmmc1-dir-0; + /delete-node/ sdmmc2-b4-0; + /delete-node/ sdmmc2-b4-1; + /delete-node/ sdmmc2-d47-0; +#endif +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usbotg_hs-0; + /delete-node/ usbotg-fs-dp-dm-0; +#endif + }; + }; + +#if !STM32MP_USE_STM32IMAGE + /* + * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in + * network order (big endian) + */ + + st-io_policies { + fip-handles { + compatible = "st,io-fip-handle"; + fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e"; + bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38"; + bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288"; + bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9"; + bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4"; + hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc"; + tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021"; + nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9"; + }; + }; +#endif /* !STM32MP_USE_STM32IMAGE */ +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi b/arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi new file mode 100644 index 0000000..ca4bb3e --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2020-2021 - All Rights Reserved + */ + +/ { + aliases { + /delete-property/ mmc0; + /delete-property/ mmc1; + }; + + cpus { + /delete-node/ cpu@1; + }; + + /delete-node/ psci; + + soc { + /delete-node/ usb-otg@49000000; + /delete-node/ hash@54002000; + /delete-node/ memory-controller@58002000; + /delete-node/ spi@58003000; + /delete-node/ mmc@58005000; + /delete-node/ mmc@58007000; + /delete-node/ usbphyc@5a006000; + /delete-node/ spi@5c001000; + /delete-node/ stgen@5c008000; + /delete-node/ i2c@5c009000; + + pin-controller@50002000 { + /delete-node/ fmc-0; + /delete-node/ qspi-clk-0; + /delete-node/ qspi-bk1-0; + /delete-node/ qspi-bk2-0; + /delete-node/ sdmmc1-b4-0; + /delete-node/ sdmmc1-dir-0; + /delete-node/ sdmmc2-b4-0; + /delete-node/ sdmmc2-b4-1; + /delete-node/ sdmmc2-d47-0; + /delete-node/ sdmmc2-d47-1; + /delete-node/ sdmmc2-d47-3; + /delete-node/ usbotg_hs-0; + /delete-node/ usbotg-fs-dp-dm-0; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi b/arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi new file mode 100644 index 0000000..d0b3a17 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + */ + +&ddr { + st,mem-name = DDR_MEM_NAME; + st,mem-speed = ; + st,mem-size = ; + + st,ctl-reg = < + DDR_MSTR + DDR_MRCTRL0 + DDR_MRCTRL1 + DDR_DERATEEN + DDR_DERATEINT + DDR_PWRCTL + DDR_PWRTMG + DDR_HWLPCTL + DDR_RFSHCTL0 + DDR_RFSHCTL3 + DDR_CRCPARCTL0 + DDR_ZQCTL0 + DDR_DFITMG0 + DDR_DFITMG1 + DDR_DFILPCFG0 + DDR_DFIUPD0 + DDR_DFIUPD1 + DDR_DFIUPD2 + DDR_DFIPHYMSTR + DDR_ODTMAP + DDR_DBG0 + DDR_DBG1 + DDR_DBGCMD + DDR_POISONCFG + DDR_PCCFG + >; + + st,ctl-timing = < + DDR_RFSHTMG + DDR_DRAMTMG0 + DDR_DRAMTMG1 + DDR_DRAMTMG2 + DDR_DRAMTMG3 + DDR_DRAMTMG4 + DDR_DRAMTMG5 + DDR_DRAMTMG6 + DDR_DRAMTMG7 + DDR_DRAMTMG8 + DDR_DRAMTMG14 + DDR_ODTCFG + >; + + st,ctl-map = < + DDR_ADDRMAP1 + DDR_ADDRMAP2 + DDR_ADDRMAP3 + DDR_ADDRMAP4 + DDR_ADDRMAP5 + DDR_ADDRMAP6 + DDR_ADDRMAP9 + DDR_ADDRMAP10 + DDR_ADDRMAP11 + >; + + st,ctl-perf = < + DDR_SCHED + DDR_SCHED1 + DDR_PERFHPR1 + DDR_PERFLPR1 + DDR_PERFWR1 + DDR_PCFGR_0 + DDR_PCFGW_0 + DDR_PCFGQOS0_0 + DDR_PCFGQOS1_0 + DDR_PCFGWQOS0_0 + DDR_PCFGWQOS1_0 + DDR_PCFGR_1 + DDR_PCFGW_1 + DDR_PCFGQOS0_1 + DDR_PCFGQOS1_1 + DDR_PCFGWQOS0_1 + DDR_PCFGWQOS1_1 + >; + + st,phy-reg = < + DDR_PGCR + DDR_ACIOCR + DDR_DXCCR + DDR_DSGCR + DDR_DCR + DDR_ODTCR + DDR_ZQ0CR1 + DDR_DX0GCR + DDR_DX1GCR + DDR_DX2GCR + DDR_DX3GCR + >; + + st,phy-timing = < + DDR_PTR0 + DDR_PTR1 + DDR_PTR2 + DDR_DTPR0 + DDR_DTPR1 + DDR_DTPR2 + DDR_MR0 + DDR_MR1 + DDR_MR2 + DDR_MR3 + >; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi new file mode 100644 index 0000000..5d1001d --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved + */ + +/* + * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs + * DDR type: DDR3 / DDR3L + * DDR width: 16bits + * DDR density: 4Gb + * System frequency: 533000Khz + * Relaxed Timing Mode: false + * Address mapping type: RBC + * + * Save Date: 2020.02.20, save Time: 18:45:20 + */ + +#define DDR_MEM_NAME "DDR3-DDR3L 16bits 533000kHz" +#define DDR_MEM_SPEED 533000 +#define DDR_MEM_SIZE 0x20000000 + +#define DDR_MSTR 0x00041401 +#define DDR_MRCTRL0 0x00000010 +#define DDR_MRCTRL1 0x00000000 +#define DDR_DERATEEN 0x00000000 +#define DDR_DERATEINT 0x00800000 +#define DDR_PWRCTL 0x00000000 +#define DDR_PWRTMG 0x00400010 +#define DDR_HWLPCTL 0x00000000 +#define DDR_RFSHCTL0 0x00210000 +#define DDR_RFSHCTL3 0x00000000 +#define DDR_RFSHTMG 0x0081008B +#define DDR_CRCPARCTL0 0x00000000 +#define DDR_DRAMTMG0 0x121B2414 +#define DDR_DRAMTMG1 0x000A041C +#define DDR_DRAMTMG2 0x0608090F +#define DDR_DRAMTMG3 0x0050400C +#define DDR_DRAMTMG4 0x08040608 +#define DDR_DRAMTMG5 0x06060403 +#define DDR_DRAMTMG6 0x02020002 +#define DDR_DRAMTMG7 0x00000202 +#define DDR_DRAMTMG8 0x00001005 +#define DDR_DRAMTMG14 0x000000A0 +#define DDR_ZQCTL0 0xC2000040 +#define DDR_DFITMG0 0x02060105 +#define DDR_DFITMG1 0x00000202 +#define DDR_DFILPCFG0 0x07000000 +#define DDR_DFIUPD0 0xC0400003 +#define DDR_DFIUPD1 0x00000000 +#define DDR_DFIUPD2 0x00000000 +#define DDR_DFIPHYMSTR 0x00000000 +#define DDR_ODTCFG 0x06000600 +#define DDR_ODTMAP 0x00000001 +#define DDR_SCHED 0x00000C01 +#define DDR_SCHED1 0x00000000 +#define DDR_PERFHPR1 0x01000001 +#define DDR_PERFLPR1 0x08000200 +#define DDR_PERFWR1 0x08000400 +#define DDR_DBG0 0x00000000 +#define DDR_DBG1 0x00000000 +#define DDR_DBGCMD 0x00000000 +#define DDR_POISONCFG 0x00000000 +#define DDR_PCCFG 0x00000010 +#define DDR_PCFGR_0 0x00010000 +#define DDR_PCFGW_0 0x00000000 +#define DDR_PCFGQOS0_0 0x02100C03 +#define DDR_PCFGQOS1_0 0x00800100 +#define DDR_PCFGWQOS0_0 0x01100C03 +#define DDR_PCFGWQOS1_0 0x01000200 +#define DDR_PCFGR_1 0x00010000 +#define DDR_PCFGW_1 0x00000000 +#define DDR_PCFGQOS0_1 0x02100C03 +#define DDR_PCFGQOS1_1 0x00800040 +#define DDR_PCFGWQOS0_1 0x01100C03 +#define DDR_PCFGWQOS1_1 0x01000200 +#define DDR_ADDRMAP1 0x00070707 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x1F000000 +#define DDR_ADDRMAP4 0x00001F1F +#define DDR_ADDRMAP5 0x06060606 +#define DDR_ADDRMAP6 0x0F060606 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 +#define DDR_PGCR 0x01442E02 +#define DDR_PTR0 0x0022AA5B +#define DDR_PTR1 0x04841104 +#define DDR_PTR2 0x042DA068 +#define DDR_ACIOCR 0x10400812 +#define DDR_DXCCR 0x00000C40 +#define DDR_DSGCR 0xF200011F +#define DDR_DCR 0x0000000B +#define DDR_DTPR0 0x38D488D0 +#define DDR_DTPR1 0x098B00D8 +#define DDR_DTPR2 0x10023600 +#define DDR_MR0 0x00000840 +#define DDR_MR1 0x00000000 +#define DDR_MR2 0x00000208 +#define DDR_MR3 0x00000000 +#define DDR_ODTCR 0x00010000 +#define DDR_ZQ0CR1 0x00000038 +#define DDR_DX0GCR 0x0000CE81 +#define DDR_DX1GCR 0x0000CE81 +#define DDR_DX2GCR 0x0000CE80 +#define DDR_DX3GCR 0x0000CE80 + +#include "stm32mp15-ddr.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi new file mode 100644 index 0000000..6494ceb --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved + */ + +/* + * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs + * DDR type: DDR3 / DDR3L + * DDR width: 32bits + * DDR density: 8Gb + * System frequency: 533000Khz + * Relaxed Timing Mode: false + * Address mapping type: RBC + * + * Save Date: 2020.02.20, save Time: 18:49:33 + */ + +#define DDR_MEM_NAME "DDR3-DDR3L 32bits 533000kHz" +#define DDR_MEM_SPEED 533000 +#define DDR_MEM_SIZE 0x40000000 + +#define DDR_MSTR 0x00040401 +#define DDR_MRCTRL0 0x00000010 +#define DDR_MRCTRL1 0x00000000 +#define DDR_DERATEEN 0x00000000 +#define DDR_DERATEINT 0x00800000 +#define DDR_PWRCTL 0x00000000 +#define DDR_PWRTMG 0x00400010 +#define DDR_HWLPCTL 0x00000000 +#define DDR_RFSHCTL0 0x00210000 +#define DDR_RFSHCTL3 0x00000000 +#define DDR_RFSHTMG 0x0081008B +#define DDR_CRCPARCTL0 0x00000000 +#define DDR_DRAMTMG0 0x121B2414 +#define DDR_DRAMTMG1 0x000A041C +#define DDR_DRAMTMG2 0x0608090F +#define DDR_DRAMTMG3 0x0050400C +#define DDR_DRAMTMG4 0x08040608 +#define DDR_DRAMTMG5 0x06060403 +#define DDR_DRAMTMG6 0x02020002 +#define DDR_DRAMTMG7 0x00000202 +#define DDR_DRAMTMG8 0x00001005 +#define DDR_DRAMTMG14 0x000000A0 +#define DDR_ZQCTL0 0xC2000040 +#define DDR_DFITMG0 0x02060105 +#define DDR_DFITMG1 0x00000202 +#define DDR_DFILPCFG0 0x07000000 +#define DDR_DFIUPD0 0xC0400003 +#define DDR_DFIUPD1 0x00000000 +#define DDR_DFIUPD2 0x00000000 +#define DDR_DFIPHYMSTR 0x00000000 +#define DDR_ODTCFG 0x06000600 +#define DDR_ODTMAP 0x00000001 +#define DDR_SCHED 0x00000C01 +#define DDR_SCHED1 0x00000000 +#define DDR_PERFHPR1 0x01000001 +#define DDR_PERFLPR1 0x08000200 +#define DDR_PERFWR1 0x08000400 +#define DDR_DBG0 0x00000000 +#define DDR_DBG1 0x00000000 +#define DDR_DBGCMD 0x00000000 +#define DDR_POISONCFG 0x00000000 +#define DDR_PCCFG 0x00000010 +#define DDR_PCFGR_0 0x00010000 +#define DDR_PCFGW_0 0x00000000 +#define DDR_PCFGQOS0_0 0x02100C03 +#define DDR_PCFGQOS1_0 0x00800100 +#define DDR_PCFGWQOS0_0 0x01100C03 +#define DDR_PCFGWQOS1_0 0x01000200 +#define DDR_PCFGR_1 0x00010000 +#define DDR_PCFGW_1 0x00000000 +#define DDR_PCFGQOS0_1 0x02100C03 +#define DDR_PCFGQOS1_1 0x00800040 +#define DDR_PCFGWQOS0_1 0x01100C03 +#define DDR_PCFGWQOS1_1 0x01000200 +#define DDR_ADDRMAP1 0x00080808 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x00000000 +#define DDR_ADDRMAP4 0x00001F1F +#define DDR_ADDRMAP5 0x07070707 +#define DDR_ADDRMAP6 0x0F070707 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 +#define DDR_PGCR 0x01442E02 +#define DDR_PTR0 0x0022AA5B +#define DDR_PTR1 0x04841104 +#define DDR_PTR2 0x042DA068 +#define DDR_ACIOCR 0x10400812 +#define DDR_DXCCR 0x00000C40 +#define DDR_DSGCR 0xF200011F +#define DDR_DCR 0x0000000B +#define DDR_DTPR0 0x38D488D0 +#define DDR_DTPR1 0x098B00D8 +#define DDR_DTPR2 0x10023600 +#define DDR_MR0 0x00000840 +#define DDR_MR1 0x00000000 +#define DDR_MR2 0x00000208 +#define DDR_MR3 0x00000000 +#define DDR_ODTCR 0x00010000 +#define DDR_ZQ0CR1 0x00000038 +#define DDR_DX0GCR 0x0000CE81 +#define DDR_DX1GCR 0x0000CE81 +#define DDR_DX2GCR 0x0000CE81 +#define DDR_DX3GCR 0x0000CE81 + +#include "stm32mp15-ddr.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi b/arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi new file mode 100644 index 0000000..8aece28 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#include +#include + +#include + +#ifndef DDR_SIZE +#error "DDR_SIZE is not defined" +#endif + +#define DDR_NS_BASE STM32MP_DDR_BASE +#ifdef AARCH32_SP_OPTEE +/* OP-TEE reserved shared memory: located at DDR top */ +#define DDR_SHARE_SIZE STM32MP_DDR_SHMEM_SIZE +#define DDR_SHARE_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SHARE_SIZE)) +/* OP-TEE secure memory: located right below OP-TEE reserved shared memory */ +#define DDR_SEC_SIZE STM32MP_DDR_S_SIZE +#define DDR_SEC_BASE (DDR_SHARE_BASE - DDR_SEC_SIZE) +#define DDR_NS_SIZE (DDR_SEC_BASE - DDR_NS_BASE) +#else /* !AARCH32_SP_OPTEE */ +#define DDR_NS_SIZE DDR_SIZE +#endif /* AARCH32_SP_OPTEE */ + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + hw-config { + load-address = <0x0 STM32MP_HW_CONFIG_BASE>; + max-size = ; + id = ; + }; + + nt_fw { + load-address = <0x0 STM32MP_BL33_BASE>; + max-size = ; + id = ; + }; + +#ifdef AARCH32_SP_OPTEE + tos_fw { + load-address = <0x0 STM32MP_OPTEE_BASE>; + max-size = ; + id = ; + }; +#else + tos_fw { + load-address = <0x0 STM32MP_BL32_BASE>; + max-size = ; + id = ; + }; + + tos_fw-config { + load-address = <0x0 STM32MP_BL32_DTB_BASE>; + max-size = ; + id = ; + }; +#endif + }; + + st-mem-firewall { + compatible = "st,mem-firewall"; +#ifdef AARCH32_SP_OPTEE + memory-ranges = < + DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR + DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0 + DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>; +#else + memory-ranges = < + DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>; +#endif + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi new file mode 100644 index 0000000..d74dc2b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +#include + +&pinctrl { + fmc_pins_a: fmc-0 { + pins1 { + pinmux = , /* FMC_NOE */ + , /* FMC_NWE */ + , /* FMC_A16_FMC_CLE */ + , /* FMC_A17_FMC_ALE */ + , /* FMC_D0 */ + , /* FMC_D1 */ + , /* FMC_D2 */ + , /* FMC_D3 */ + , /* FMC_D4 */ + , /* FMC_D5 */ + , /* FMC_D6 */ + , /* FMC_D7 */ + ; /* FMC_NE2_FMC_NCE */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* FMC_NWAIT */ + bias-pull-up; + }; + }; + + i2c2_pins_a: i2c2-0 { + pins { + pinmux = , /* I2C2_SCL */ + ; /* I2C2_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + qspi_clk_pins_a: qspi-clk-0 { + pins { + pinmux = ; /* QSPI_CLK */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + }; + + qspi_bk1_pins_a: qspi-bk1-0 { + pins1 { + pinmux = , /* QSPI_BK1_IO0 */ + , /* QSPI_BK1_IO1 */ + , /* QSPI_BK1_IO2 */ + ; /* QSPI_BK1_IO3 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* QSPI_BK1_NCS */ + bias-pull-up; + drive-push-pull; + slew-rate = <1>; + }; + }; + + qspi_bk2_pins_a: qspi-bk2-0 { + pins1 { + pinmux = , /* QSPI_BK2_IO0 */ + , /* QSPI_BK2_IO1 */ + , /* QSPI_BK2_IO2 */ + ; /* QSPI_BK2_IO3 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* QSPI_BK2_NCS */ + bias-pull-up; + drive-push-pull; + slew-rate = <1>; + }; + }; + + sdmmc1_b4_pins_a: sdmmc1-b4-0 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + , /* SDMMC1_D3 */ + ; /* SDMMC1_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc1_dir_pins_a: sdmmc1-dir-0 { + pins1 { + pinmux = , /* SDMMC1_D0DIR */ + , /* SDMMC1_D123DIR */ + ; /* SDMMC1_CDIR */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2{ + pinmux = ; /* SDMMC1_CKIN */ + bias-pull-up; + }; + }; + + sdmmc2_b4_pins_a: sdmmc2-b4-0 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc2_b4_pins_b: sdmmc2-b4-1 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc2_d47_pins_a: sdmmc2-d47-0 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc2_d47_pins_b: sdmmc2-d47-1 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc2_d47_pins_d: sdmmc2-d47-3 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + }; + }; + + uart4_pins_a: uart4-0 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + uart4_pins_b: uart4-1 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + uart7_pins_a: uart7-0 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* UART7_RX */ + , /* UART7_CTS */ + ; /* UART7_RTS */ + bias-disable; + }; + }; + + uart7_pins_b: uart7-1 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART7_RX */ + bias-disable; + }; + }; + + uart7_pins_c: uart7-2 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART7_RX */ + bias-disable; + }; + }; + + uart8_pins_a: uart8-0 { + pins1 { + pinmux = ; /* UART8_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART8_RX */ + bias-disable; + }; + }; + + usart2_pins_a: usart2-0 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart2_pins_b: usart2-1 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart2_pins_c: usart2-2 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart3_pins_a: usart3-0 { + pins1 { + pinmux = ; /* USART3_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART3_RX */ + bias-disable; + }; + }; + + usart3_pins_b: usart3-1 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; + + usart3_pins_c: usart3-2 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; + + usbotg_hs_pins_a: usbotg-hs-0 { + pins { + pinmux = ; /* OTG_ID */ + }; + }; + + usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { + pins { + pinmux = , /* OTG_FS_DM */ + ; /* OTG_FS_DP */ + }; + }; +}; + +&pinctrl_z { + i2c4_pins_a: i2c4-0 { + pins { + pinmux = , /* I2C4_SCL */ + ; /* I2C4_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp151.dtsi b/arm-trusted-firmware/fdts/stm32mp151.dtsi new file mode 100644 index 0000000..454e124 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp151.dtsi @@ -0,0 +1,708 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <0>; + nvmem-cells = <&part_number_otp>; + nvmem-cell-names = "part_number"; + }; + }; + + nvmem_layout: nvmem_layout@0 { + compatible = "st,stm32-nvmem-layout"; + + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&uid_otp>, + <&package_otp>, + <&hw2_otp>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "uid_otp", + "package_otp", + "hw2_otp"; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, + <0xa0022000 0x2000>; + }; + + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges; + + timers12: timer@40006000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40006000 0x400>; + clocks = <&rcc TIM12_K>; + clock-names = "int"; + status = "disabled"; + }; + + usart2: serial@4000e000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000e000 0x400>; + interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART2_K>; + resets = <&rcc USART2_R>; + status = "disabled"; + }; + + usart3: serial@4000f000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000f000 0x400>; + interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART3_K>; + resets = <&rcc USART3_R>; + status = "disabled"; + }; + + uart4: serial@40010000 { + compatible = "st,stm32h7-uart"; + reg = <0x40010000 0x400>; + interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART4_K>; + resets = <&rcc UART4_R>; + wakeup-source; + status = "disabled"; + }; + + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; + interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART5_K>; + resets = <&rcc UART5_R>; + status = "disabled"; + }; + + i2c2: i2c@40013000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x40013000 0x400>; + interrupt-names = "event", "error"; + interrupts = <&exti 22 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C2_K>; + resets = <&rcc I2C2_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x2>; + wakeup-source; + status = "disabled"; + }; + + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; + interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART7_K>; + resets = <&rcc UART7_R>; + status = "disabled"; + }; + + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; + interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART8_K>; + resets = <&rcc UART8_R>; + status = "disabled"; + }; + + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; + interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART6_K>; + resets = <&rcc USART6_R>; + status = "disabled"; + }; + + timers15: timer@44006000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x44006000 0x400>; + clocks = <&rcc TIM15_K>; + clock-names = "int"; + status = "disabled"; + }; + + usbotg_hs: usb-otg@49000000 { + compatible = "st,stm32mp15-hsotg", "snps,dwc2"; + reg = <0x49000000 0x10000>; + clocks = <&rcc USBO_K>; + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; + interrupts-extended = <&exti 44 IRQ_TYPE_LEVEL_HIGH>; + g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <32>; + g-tx-fifo-size = <256 16 16 16 16 16 16 16>; + dr_mode = "otg"; + usb33d-supply = <&usb33>; + status = "disabled"; + }; + + rcc: rcc@50000000 { + compatible = "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <1>; + #reset-cells = <1>; + interrupts = ; + secure-interrupts = ; + secure-interrupt-names = "wakeup"; + }; + + pwr_regulators: pwr@50001000 { + compatible = "st,stm32mp1,pwr-reg"; + reg = <0x50001000 0x10>; + st,tzcr = <&rcc 0x0 0x1>; + + reg11: reg11 { + regulator-name = "reg11"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + reg18: reg18 { + regulator-name = "reg18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + usb33: usb33 { + regulator-name = "usb33"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + + pwr_mcu: pwr_mcu@50001014 { + compatible = "st,stm32mp151-pwr-mcu", "syscon"; + reg = <0x50001014 0x4>; + }; + + pwr_irq: pwr@50001020 { + compatible = "st,stm32mp1-pwr"; + reg = <0x50001020 0x100>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + }; + + exti: interrupt-controller@5000d000 { + compatible = "st,stm32mp1-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000d000 0x400>; + + /* exti_pwr is an extra interrupt controller used for + * EXTI 55 to 60. It's mapped on pwr interrupt + * controller. + */ + exti_pwr: exti-pwr { + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&pwr_irq>; + st,irq-number = <6>; + }; + }; + + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + clocks = <&rcc SYSCFG>; + }; + + hash1: hash@54002000 { + compatible = "st,stm32f756-hash"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; + status = "disabled"; + }; + + rng1: rng@54003000 { + compatible = "st,stm32-rng"; + reg = <0x54003000 0x400>; + clocks = <&rcc RNG1_K>; + resets = <&rcc RNG1_R>; + status = "disabled"; + }; + + fmc: memory-controller@58002000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "st,stm32mp1-fmc2-ebi"; + reg = <0x58002000 0x1000>; + clocks = <&rcc FMC_K>; + resets = <&rcc FMC_R>; + status = "disabled"; + + ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ + <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ + <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ + <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ + <4 0 0x80000000 0x10000000>; /* NAND */ + + nand-controller@4,0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32mp1-fmc2-nfc"; + reg = <4 0x00000000 0x1000>, + <4 0x08010000 0x1000>, + <4 0x08020000 0x1000>, + <4 0x01000000 0x1000>, + <4 0x09010000 0x1000>, + <4 0x09020000 0x1000>; + interrupts = ; + status = "disabled"; + }; + }; + + qspi: spi@58003000 { + compatible = "st,stm32f469-qspi"; + reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; + interrupts = ; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; + status = "disabled"; + }; + + sdmmc1: mmc@58005000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; + reg = <0x58005000 0x1000>, <0x58006000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC1_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC1_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + sdmmc2: mmc@58007000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; + reg = <0x58007000 0x1000>, <0x58008000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC2_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC2_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; + secure-interrupts = ; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + ddr: ddr@5a003000{ + compatible = "st,stm32mp1-ddr"; + reg = <0x5A003000 0x550 0x5A004000 0x234>; + clocks = <&rcc AXIDCG>, + <&rcc DDRC1>, + <&rcc DDRC2>, + <&rcc DDRPHYC>, + <&rcc DDRCAPB>, + <&rcc DDRPHYCAPB>; + clock-names = "axidcg", + "ddrc1", + "ddrc2", + "ddrphyc", + "ddrcapb", + "ddrphycapb"; + status = "okay"; + }; + + usbphyc: usbphyc@5a006000 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "st,stm32mp1-usbphyc"; + reg = <0x5a006000 0x1000>; + clocks = <&rcc USBPHY_K>; + resets = <&rcc USBPHY_R>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; + status = "disabled"; + + usbphyc_port0: usb-phy@0 { + #phy-cells = <0>; + reg = <0>; + }; + + usbphyc_port1: usb-phy@1 { + #phy-cells = <1>; + reg = <1>; + }; + }; + + usart1: serial@5c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x5c000000 0x400>; + interrupts = ; + clocks = <&rcc USART1_K>; + resets = <&rcc USART1_R>; + status = "disabled"; + }; + + spi6: spi@5c001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x5c001000 0x400>; + interrupts = ; + clocks = <&rcc SPI6_K>; + resets = <&rcc SPI6_R>; + status = "disabled"; + }; + + i2c4: i2c@5c002000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x5c002000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C4_K>; + resets = <&rcc I2C4_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x8>; + wakeup-source; + status = "disabled"; + }; + + iwdg1: watchdog@5c003000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5C003000 0x400>; + interrupts = ; + clocks = <&rcc IWDG1>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + rtc: rtc@5c004000 { + compatible = "st,stm32mp1-rtc"; + reg = <0x5c004000 0x400>; + clocks = <&rcc RTCAPB>, <&rcc RTC>; + clock-names = "pclk", "rtc_ck"; + interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + bsec: efuse@5c005000 { + compatible = "st,stm32mp15-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + + cfg0_otp: cfg0_otp@0 { + reg = <0x0 0x1>; + }; + part_number_otp: part_number_otp@4 { + reg = <0x4 0x1>; + }; + monotonic_otp: monotonic_otp@10 { + reg = <0x10 0x4>; + }; + nand_otp: nand_otp@24 { + reg = <0x24 0x4>; + }; + uid_otp: uid_otp@34 { + reg = <0x34 0xc>; + }; + package_otp: package_otp@40 { + reg = <0x40 0x4>; + }; + hw2_otp: hw2_otp@48 { + reg = <0x48 0x4>; + }; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; + mac_addr: mac_addr@e4 { + reg = <0xe4 0x8>; + st,non-secure-otp; + }; + }; + + etzpc: etzpc@5c007000 { + compatible = "st,stm32-etzpc"; + reg = <0x5C007000 0x400>; + clocks = <&rcc TZPC>; + status = "disabled"; + secure-status = "okay"; + }; + + stgen: stgen@5c008000 { + compatible = "st,stm32-stgen"; + reg = <0x5C008000 0x1000>; + }; + + i2c6: i2c@5c009000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x5c009000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 54 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C6_K>; + resets = <&rcc I2C6_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x20>; + wakeup-source; + status = "disabled"; + }; + + tamp: tamp@5c00a000 { + compatible = "st,stm32-tamp", "simple-bus", "syscon", "simple-mfd"; + reg = <0x5c00a000 0x400>; + secure-interrupts = ; + clocks = <&rcc RTCAPB>; + }; + + /* + * Break node order to solve dependency probe issue between + * pinctrl and exti. + */ + pinctrl: pin-controller@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-pinctrl"; + ranges = <0 0x50002000 0xa400>; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; + pins-are-numbered; + + gpioa: gpio@50002000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x0 0x400>; + clocks = <&rcc GPIOA>; + st,bank-name = "GPIOA"; + status = "disabled"; + }; + + gpiob: gpio@50003000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x1000 0x400>; + clocks = <&rcc GPIOB>; + st,bank-name = "GPIOB"; + status = "disabled"; + }; + + gpioc: gpio@50004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x2000 0x400>; + clocks = <&rcc GPIOC>; + st,bank-name = "GPIOC"; + status = "disabled"; + }; + + gpiod: gpio@50005000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x3000 0x400>; + clocks = <&rcc GPIOD>; + st,bank-name = "GPIOD"; + status = "disabled"; + }; + + gpioe: gpio@50006000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x4000 0x400>; + clocks = <&rcc GPIOE>; + st,bank-name = "GPIOE"; + status = "disabled"; + }; + + gpiof: gpio@50007000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000 0x400>; + clocks = <&rcc GPIOF>; + st,bank-name = "GPIOF"; + status = "disabled"; + }; + + gpiog: gpio@50008000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x6000 0x400>; + clocks = <&rcc GPIOG>; + st,bank-name = "GPIOG"; + status = "disabled"; + }; + + gpioh: gpio@50009000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x7000 0x400>; + clocks = <&rcc GPIOH>; + st,bank-name = "GPIOH"; + status = "disabled"; + }; + + gpioi: gpio@5000a000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x8000 0x400>; + clocks = <&rcc GPIOI>; + st,bank-name = "GPIOI"; + status = "disabled"; + }; + + gpioj: gpio@5000b000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x9000 0x400>; + clocks = <&rcc GPIOJ>; + st,bank-name = "GPIOJ"; + status = "disabled"; + }; + + gpiok: gpio@5000c000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0xa000 0x400>; + clocks = <&rcc GPIOK>; + st,bank-name = "GPIOK"; + status = "disabled"; + }; + }; + + pinctrl_z: pin-controller-z@54004000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-z-pinctrl"; + ranges = <0 0x54004000 0x400>; + pins-are-numbered; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; + + gpioz: gpio@54004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0 0x400>; + clocks = <&rcc GPIOZ>; + st,bank-name = "GPIOZ"; + st,bank-ioport = <11>; + status = "disabled"; + }; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp153.dtsi b/arm-trusted-firmware/fdts/stm32mp153.dtsi new file mode 100644 index 0000000..0a0bb8d --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp153.dtsi @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp151.dtsi" + +/ { + cpus { + cpu1: cpu@1 { + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <1>; + clocks = <&rcc CK_MPU>; + clock-names = "cpu"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157.dtsi b/arm-trusted-firmware/fdts/stm32mp157.dtsi new file mode 100644 index 0000000..c834029 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157.dtsi @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp153.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts b/arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts new file mode 100644 index 0000000..b967736 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) Arrow Electronics 2019 - All Rights Reserved + * Author: Botond Kardos + * + * Copyright (C) Linaro Ltd 2019 - All Rights Reserved + * Author: Manivannan Sadhasivam + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include +#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" + +/ { + model = "Arrow Electronics STM32MP157A Avenger96 board"; + compatible = "arrow,stm32mp157a-avenger96", "st,stm32mp157"; + + aliases { + mmc0 = &sdmmc1; + serial0 = &uart4; + serial1 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x40000000>; + }; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + st,main-control-register = <0x04>; + st,vin-control-register = <0xc0>; + st,usb-control-register = <0x30>; + + regulators { + compatible = "st,stpmic1-regulators"; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge = <1>; + }; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_DISABLED + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = <2 80 0 0 0 PQR(1,0,0)>; + frac = <0x800>; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <1 39 3 11 4 PQR(1,1,1)>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; + st,sig-dir; + st,neg-edge; + st,use-ckin; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + status = "okay"; +}; + +&uart4 { + /* On Low speed expansion header */ + label = "LS-UART1"; + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_b>; + status = "okay"; +}; + +&uart7 { + /* On Low speed expansion header */ + label = "LS-UART0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts new file mode 100644 index 0000000..83116d1 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157a-dk1.dts b/arm-trusted-firmware/fdts/stm32mp157a-dk1.dts new file mode 100644 index 0000000..a73bef8 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-dk1.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include "stm32mp15xx-dkx.dtsi" + +/ { + model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; + compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; + + aliases { + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts new file mode 100644 index 0000000..83116d1 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-dk2.dts b/arm-trusted-firmware/fdts/stm32mp157c-dk2.dts new file mode 100644 index 0000000..be8300e --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-dk2.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include "stm32mp15xx-dkx.dtsi" + +/ { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + + aliases { + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; + serial3 = &usart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&cryp1 { + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-ed1.dts b/arm-trusted-firmware/fdts/stm32mp157c-ed1.dts new file mode 100644 index 0000000..44c7016 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-ed1.dts @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include +#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" + +/ { + model = "STMicroelectronics STM32MP157C eval daughter"; + compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xC0000000 0x40000000>; + }; + + aliases { + serial0 = &uart4; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&cpu0 { + cpu-supply = <&vddcore>; +}; + +&cpu1 { + cpu-supply = <&vddcore>; +}; + +&cryp1 { + status = "okay"; +}; + +&hash1 { + status = "okay"; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-always-on; + regulator-over-current-protection; + st,regulator-sink-source; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge = <1>; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + power-off-time-sec = <10>; + status = "okay"; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&nvmem_layout { + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&uid_otp>, + <&package_otp>, + <&hw2_otp>, + <&board_id>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "uid_otp", + "package_otp", + "hw2_otp", + "board_id"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_PLL4P + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = <2 80 0 0 0 PQR(1,0,0)>; + frac = <0x800>; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; + disable-wp; + st,sig-dir; + st,neg-edge; + st,use-ckin; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-ddr50; + status = "okay"; +}; + +&sdmmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; + non-removable; + no-sd; + no-sdio; + st,neg-edge; + bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&vdd>; + mmc-ddr-3_3v; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-ev1.dts b/arm-trusted-firmware/fdts/stm32mp157c-ev1.dts new file mode 100644 index 0000000..02840a2 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-ev1.dts @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +/dts-v1/; + +#include "stm32mp157c-ed1.dts" + +/ { + model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; + compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial1 = &usart3; + }; +}; + +&fmc { + pinctrl-names = "default"; + pinctrl-0 = <&fmc_pins_a>; + status = "okay"; + + nand-controller@4,0 { + status = "okay"; + + nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; + #size-cells = <1>; + }; + }; +}; + +&qspi { + pinctrl-names = "default"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>; + reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash0: mx66l51235l@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&usart3 { + pinctrl-names = "default"; + pinctrl-0 = <&usart3_pins_b>; + uart-has-rtscts; + status = "disabled"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts new file mode 100644 index 0000000..9ee09e9 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts b/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts new file mode 100644 index 0000000..6f67712 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */ +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + * Copyright (C) 2020 Ahmad Fatoum, Pengutronix + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" +#include "stm32mp15xx-osd32.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" + +/ { + model = "Linux Automation MC-1 board"; + compatible = "lxa,stm32mp157c-mc1", "oct,stm32mp15xx-osd32", "st,stm32mp157"; + + aliases { + mmc0 = &sdmmc1; + mmc1 = &sdmmc2; + serial0 = &uart4; + }; + + chosen { + stdout-path = &uart4; + }; + + led-act { + compatible = "gpio-leds"; + + led-green { + label = "mc1:green:act"; + gpios = <&gpioa 13 1>; + linux,default-trigger = "heartbeat"; + }; + }; + + reg_3v3: regulator_3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + vin-supply = <&v3v3>; + }; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + bus-width = <4>; + cd-gpios = <&gpioh 3 1>; + disable-wp; + no-1-8-v; + st,neg-edge; + vmmc-supply = <®_3v3>; + status = "okay"; +}; + +&sdmmc1_b4_pins_a { + /* + * board lacks external pull-ups on SDMMC lines. Class 10 SD refuses to + * work, thus enable internal pull-ups. + */ + pins1 { + /delete-property/ bias-disable; + bias-pull-up; + }; + pins2 { + /delete-property/ bias-disable; + bias-pull-up; + }; +}; + +&sdmmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_b>; + bus-width = <8>; + no-1-8-v; + no-sd; + no-sdio; + non-removable; + st,neg-edge; + vmmc-supply = <®_3v3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts new file mode 100644 index 0000000..9ee09e9 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi b/arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi new file mode 100644 index 0000000..6bed339 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2019, STMicroelectronics. All Rights Reserved. + * Copyright (C) 2021, Grzegorz Szymaszek. + * + * SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) + */ + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include +#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" + +/ { + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&cpu0 { + cpu-supply = <&vddcore>; +}; + +&cpu1 { + cpu-supply = <&vddcore>; +}; + +&cryp1 { + status = "okay"; +}; + +&hash1 { + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&v3v3>; + ldo2-supply = <&vin>; + ldo3-supply = <&vdd_ddr>; + ldo4-supply = <&vin>; + ldo5-supply = <&vin>; + ldo6-supply = <&v3v3>; + vref_ddr-supply = <&vin>; + boost-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge = <1>; + }; + }; + + pmic_watchdog: watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_PLL4P + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = <2 80 0 0 0 PQR(1,0,0)>; + frac = <0x800>; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_d>; + non-removable; + no-sd; + no-sdio; + st,neg-edge; + bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&vdd>; + mmc-ddr-3_3v; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts b/arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts new file mode 100644 index 0000000..03800f9 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019, STMicroelectronics. All Rights Reserved. + * Copyright (C) 2021, Grzegorz Szymaszek. + * + * SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) + */ + +/dts-v1/; + +#include "stm32mp157c-odyssey-som.dtsi" + +/ { + model = "Seeed Studio Odyssey-STM32MP157C Board"; + compatible = "seeed,stm32mp157c-odyssey", + "seeed,stm32mp157c-odyssey-som", "st,stm32mp157"; + + aliases { + serial0 = &uart4; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts new file mode 100644 index 0000000..83116d1 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts new file mode 100644 index 0000000..83116d1 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp15xc.dtsi b/arm-trusted-firmware/fdts/stm32mp15xc.dtsi new file mode 100644 index 0000000..b06a55a --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xc.dtsi @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { + soc { + cryp1: cryp@54001000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54001000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi b/arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi new file mode 100644 index 0000000..2eb3a57 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include +#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" + +/ { + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&cpu0{ + cpu-supply = <&vddcore>; +}; + +&cpu1{ + cpu-supply = <&vddcore>; +}; + +&hash1 { + status = "okay"; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&v3v3>; + ldo2-supply = <&vin>; + ldo3-supply = <&vdd_ddr>; + ldo4-supply = <&vin>; + ldo5-supply = <&vin>; + ldo6-supply = <&v3v3>; + vref_ddr-supply = <&vin>; + boost-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-always-on; + regulator-over-current-protection; + st,regulator-sink-source; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge = <1>; + }; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "okay"; +}; + +&nvmem_layout { + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&uid_otp>, + <&package_otp>, + <&hw2_otp>, + <&board_id>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "uid_otp", + "package_otp", + "hw2_otp", + "board_id"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_PLL4P + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = < 2 80 0 0 0 PQR(1,0,0) >; + frac = < 0x800 >; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "okay"; +}; + +&timers15 { + secure-status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_c>; + status = "disabled"; +}; + +&usart3 { + pinctrl-names = "default"; + pinctrl-0 = <&usart3_pins_c>; + uart-has-rtscts; + status = "disabled"; +}; + +&usbotg_hs { + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + usb-role-switch; + status = "okay"; +}; + +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi b/arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi new file mode 100644 index 0000000..76a2561 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */ +/* + * Copyright (C) 2020 STMicroelectronics - All Rights Reserved + * Copyright (C) 2020 Ahmad Fatoum, Pengutronix + */ + +#include "stm32mp15-pinctrl.dtsi" + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + + regulators { + compatible = "st,stpmic1-regulators"; + + ldo1-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + regulator-active-discharge; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge; + }; + }; + + pmic_watchdog: watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&rng1 { + status = "okay"; +}; + +/* ATF Specific */ +#include + +/ { + aliases { + gpio0 = &gpioa; + gpio1 = &gpiob; + gpio2 = &gpioc; + gpio3 = &gpiod; + gpio4 = &gpioe; + gpio5 = &gpiof; + gpio6 = &gpiog; + gpio7 = &gpioh; + gpio8 = &gpioi; + gpio25 = &gpioz; + i2c3 = &i2c4; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&cpu0{ + cpu-supply = <&vddcore>; +}; + +&cpu1{ + cpu-supply = <&vddcore>; +}; + +&hash1 { + status = "okay"; +}; + +/* CLOCK init */ +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_PLL4P + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = < 2 80 0 0 0 PQR(1,0,0) >; + frac = < 0x800 >; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi new file mode 100644 index 0000000..f1d540a --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 112 16>; + }; + + gpioi: gpio@5000a000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 128 16>; + }; + + gpioj: gpio@5000b000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 144 16>; + }; + + gpiok: gpio@5000c000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 160 8>; + }; +}; + +&pinctrl_z { + st,package = ; + + gpioz: gpio@54004000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl_z 0 400 8>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi new file mode 100644 index 0000000..b58c7e2 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <6>; + gpio-ranges = <&pinctrl 6 86 6>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl 6 102 10>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <2>; + gpio-ranges = <&pinctrl 0 112 2>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi new file mode 100644 index 0000000..11e7e03 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 112 16>; + }; + + gpioi: gpio@5000a000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + st,package = ; + + gpioz: gpio@54004000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl_z 0 400 8>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi new file mode 100644 index 0000000..52806d6 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <6>; + gpio-ranges = <&pinctrl 6 86 6>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl 6 102 10>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <2>; + gpio-ranges = <&pinctrl 0 112 2>; + }; +}; diff --git a/arm-trusted-firmware/fdts/tc.dts b/arm-trusted-firmware/fdts/tc.dts new file mode 100644 index 0000000..7c0e842 --- /dev/null +++ b/arm-trusted-firmware/fdts/tc.dts @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + compatible = "arm,tc"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &soc_uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + core2 { + cpu = <&CPU2>; + }; + core3 { + cpu = <&CPU3>; + }; + core4 { + cpu = <&CPU4>; + }; + core5 { + cpu = <&CPU5>; + }; + core6 { + cpu = <&CPU6>; + }; + core7 { + cpu = <&CPU7>; + }; + }; + }; + + /* + * The timings below are just to demonstrate working cpuidle. + * These values may be inaccurate. + */ + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <300>; + exit-latency-us = <1200>; + min-residency-us = <2000>; + }; + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x1010000>; + local-timer-stop; + entry-latency-us = <400>; + exit-latency-us = <1200>; + min-residency-us = <2500>; + }; + }; + + amus { + amu: amu-0 { + #address-cells = <1>; + #size-cells = <0>; + + mpmm_gear0: counter@0 { + reg = <0>; + + enable-at-el3; + }; + + mpmm_gear1: counter@1 { + reg = <1>; + + enable-at-el3; + }; + + mpmm_gear2: counter@2 { + reg = <2>; + + enable-at-el3; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <406>; + amu = <&amu>; + supports-mpmm; + }; + + CPU1:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x100>; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <406>; + amu = <&amu>; + supports-mpmm; + }; + + CPU2:cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x200>; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <406>; + amu = <&amu>; + supports-mpmm; + }; + + CPU3:cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x300>; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <406>; + amu = <&amu>; + supports-mpmm; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x400>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <912>; + amu = <&amu>; + supports-mpmm; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x500>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <912>; + amu = <&amu>; + supports-mpmm; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x600>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <912>; + amu = <&amu>; + supports-mpmm; + }; + + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x700>; + enable-method = "psci"; + clocks = <&scmi_dvfs 2>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <1024>; + amu = <&amu>; + supports-mpmm; + }; + + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + linux,cma-default; + }; + + optee@0xfce00000 { + reg = <0x00000000 0xfce00000 0 0x00200000>; + no-map; + }; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; + + sram: sram@6000000 { + compatible = "mmio-sram"; + reg = <0x0 0x06000000 0x0 0x8000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x06000000 0x8000>; + + cpu_scp_scmi_mem: scp-shmem@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x80>; + }; + }; + + mbox_db_rx: mhu@45010000 { + compatible = "arm,mhuv2-rx","arm,primecell"; + reg = <0x0 0x45010000 0x0 0x1000>; + clocks = <&soc_refclk100mhz>; + clock-names = "apb_pclk"; + #mbox-cells = <2>; + interrupts = <0 317 4>; + interrupt-names = "mhu_rx"; + mhu-protocol = "doorbell"; + arm,mhuv2-protocols = <0 1>; + }; + + mbox_db_tx: mhu@45000000 { + compatible = "arm,mhuv2-tx","arm,primecell"; + reg = <0x0 0x45000000 0x0 0x1000>; + clocks = <&soc_refclk100mhz>; + clock-names = "apb_pclk"; + #mbox-cells = <2>; + interrupt-names = "mhu_tx"; + mhu-protocol = "doorbell"; + arm,mhuv2-protocols = <0 1>; + }; + + scmi { + compatible = "arm,scmi"; + mbox-names = "tx", "rx"; + mboxes = <&mbox_db_tx 0 0 &mbox_db_rx 0 0 >; + shmem = <&cpu_scp_scmi_mem &cpu_scp_scmi_mem>; + #address-cells = <1>; + #size-cells = <0>; + + scmi_dvfs: protocol@13 { + reg = <0x13>; + #clock-cells = <1>; + }; + + scmi_clk: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + }; + + gic: interrupt-controller@2c010000 { + compatible = "arm,gic-600", "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x30080000 0 0x200000>; /* GICR */ + interrupts = <0x1 0x9 0x4>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <0x1 13 0x8>, + <0x1 14 0x8>, + <0x1 11 0x8>, + <0x1 10 0x8>; + }; + + soc_refclk100mhz: refclk100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + soc_refclk60mhz: refclk60mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <60000000>; + clock-output-names = "iofpga_clk"; + }; + + soc_uartclk: uartclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "uartclk"; + }; + + soc_uart0: uart@7ff80000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x7ff80000 0x0 0x1000>; + interrupts = <0x0 116 0x4>; + clocks = <&soc_uartclk>, <&soc_refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + status = "okay"; + }; + + vencoder { + compatible = "drm,virtual-encoder"; + + port { + vencoder_in: endpoint { + remote-endpoint = <&dp_pl0_out0>; + }; + }; + + display-timings { + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + vactive = <480>; + hfront-porch = <16>; + hback-porch = <48>; + hsync-len = <96>; + vfront-porch = <10>; + vback-porch = <33>; + vsync-len = <2>; + }; + }; + + }; + + hdlcd: hdlcd@7ff60000 { + compatible = "arm,hdlcd"; + reg = <0x0 0x7ff60000 0x0 0x1000>; + interrupts = <0x0 117 0x4>; + clocks = <&fake_hdlcd_clk>; + clock-names = "pxlclk"; + status = "disabled"; + + port { + hdlcd_out: endpoint { + remote-endpoint = <&vencoder_in>; + }; + }; + }; + + fake_hdlcd_clk: fake-hdlcd-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25175000>; + clock-output-names = "pxlclk"; + }; + + ethernet@18000000 { + compatible = "smsc,lan91c111"; + reg = <0x0 0x18000000 0x0 0x10000>; + interrupts = <0 109 4>; + }; + + kmi@1c060000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x0 0x001c060000 0x0 0x1000>; + interrupts = <0 197 4>; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@1c070000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x0 0x001c070000 0x0 0x1000>; + interrupts = <0 103 4>; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + bp_clock24mhz: clock24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "bp:clock24mhz"; + }; + + virtio_block@1c130000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c130000 0x0 0x200>; + interrupts = <0 204 4>; + }; + + sysreg: sysreg@1c010000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x0 0x001c010000 0x0 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + fixed_3v3: v2m-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + mmci@1c050000 { + compatible = "arm,pl180", "arm,primecell"; + reg = <0x0 0x001c050000 0x0 0x1000>; + interrupts = <0 107 0x4>, + <0 108 0x4>; + cd-gpios = <&sysreg 0 0>; + wp-gpios = <&sysreg 1 0>; + bus-width = <8>; + max-frequency = <12000000>; + vmmc-supply = <&fixed_3v3>; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "mclk", "apb_pclk"; + }; + + gpu: gpu@2d000000 { + compatible = "arm,mali-midgard"; + reg = <0x0 0x2d000000 0x0 0x200000>; + interrupts = <0 66 4>, <0 67 4>, <0 65 4>; + interrupt-names = "JOB", "MMU", "GPU"; + clocks = <&soc_refclk100mhz>; + clock-names = "clk_mali"; + operating-points = < + /* KHz uV */ + 50000 820000 + >; + }; + + smmu: smmu@2ce00000 { + #iommu-cells = <1>; + compatible = "arm,smmu-v3"; + reg = <0x0 0x2ce00000 0x0 0x20000>; + status = "okay"; + }; + + dp0: display@2cc00000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "arm,mali-d71"; + reg = <0 0x2cc00000 0 0x20000>; + interrupts = <0 69 4>; + interrupt-names = "DPU"; + clocks = <&scmi_clk 0>; + clock-names = "aclk"; + iommus = <&smmu 0>, <&smmu 1>, <&smmu 2>, <&smmu 3>, + <&smmu 4>, <&smmu 5>, <&smmu 6>, <&smmu 7>, + <&smmu 8>, <&smmu 9>; + pl0: pipeline@0 { + reg = <0>; + clocks = <&scmi_clk 1>; + clock-names = "pxclk"; + pl_id = <0>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + dp_pl0_out0: endpoint { + remote-endpoint = <&vencoder_in>; + }; + }; + }; + }; + + pl1: pipeline@1 { + reg = <1>; + clocks = <&scmi_clk 2>; + clock-names = "pxclk"; + pl_id = <1>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + }; + }; + }; + }; + + ete0 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU0>; + }; + + ete1 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU1>; + }; + + ete2 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU2>; + }; + + ete3 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU3>; + }; + + ete4 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU4>; + }; + + ete5 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU5>; + }; + + ete6 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU6>; + }; + + ete7 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU7>; + }; + + trbe0 { + compatible = "arm,trace-buffer-extension"; + interrupts = <1 2 4>; + }; +}; diff --git a/arm-trusted-firmware/include/arch/aarch32/arch.h b/arm-trusted-firmware/include/arch/aarch32/arch.h new file mode 100644 index 0000000..bdff25b --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/arch.h @@ -0,0 +1,778 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. 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(24) +#define MIDR_VAR_SHIFT U(20) +#define MIDR_VAR_BITS U(4) +#define MIDR_REV_SHIFT U(0) +#define MIDR_REV_BITS U(4) +#define MIDR_PN_MASK U(0xfff) +#define MIDR_PN_SHIFT U(4) + +/******************************************************************************* + * MPIDR macros + ******************************************************************************/ +#define MPIDR_MT_MASK (U(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 U(0xff) +#define MPIDR_AFFLVL_SHIFT U(3) +#define MPIDR_AFF0_SHIFT U(0) +#define MPIDR_AFF1_SHIFT U(8) +#define MPIDR_AFF2_SHIFT U(16) +#define MPIDR_AFF_SHIFT(_n) MPIDR_AFF##_n##_SHIFT +#define MPIDR_AFFINITY_MASK U(0x00ffffff) +#define MPIDR_AFFLVL0 U(0) +#define MPIDR_AFFLVL1 U(1) +#define MPIDR_AFFLVL2 U(2) +#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) U(0) + +#define MPIDR_AFF_ID(mpid, n) \ + (((mpid) >> MPIDR_AFF_SHIFT(n)) & MPIDR_AFFLVL_MASK) + +#define MPID_MASK (MPIDR_MT_MASK |\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT)|\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT)|\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) + +/* + * An invalid MPID. This value can be used by functions that return an MPID to + * indicate an error. + */ +#define INVALID_MPID U(0xFFFFFFFF) + +/* + * The MPIDR_MAX_AFFLVL count starts from 0. Take care to + * add one while using this macro to define array sizes. + */ +#define MPIDR_MAX_AFFLVL U(2) + +/* Data Cache set/way op type defines */ +#define DC_OP_ISW U(0x0) +#define DC_OP_CISW U(0x1) +#if ERRATA_A53_827319 +#define DC_OP_CSW DC_OP_CISW +#else +#define DC_OP_CSW U(0x2) +#endif + +/******************************************************************************* + * Generic timer memory mapped registers & offsets + ******************************************************************************/ +#define CNTCR_OFF U(0x000) +/* Counter Count Value Lower register */ +#define CNTCVL_OFF U(0x008) +/* Counter Count Value Upper register */ +#define CNTCVU_OFF U(0x00C) +#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 CLIDR_FIELD_WIDTH U(3) + +/* CSSELR definitions */ +#define LEVEL_SHIFT U(1) + +/* ID_DFR0_EL1 definitions */ +#define ID_DFR0_COPTRC_SHIFT U(12) +#define ID_DFR0_COPTRC_MASK U(0xf) +#define ID_DFR0_COPTRC_SUPPORTED U(1) +#define ID_DFR0_COPTRC_LENGTH U(4) +#define ID_DFR0_TRACEFILT_SHIFT U(28) +#define ID_DFR0_TRACEFILT_MASK U(0xf) +#define ID_DFR0_TRACEFILT_SUPPORTED U(1) +#define ID_DFR0_TRACEFILT_LENGTH U(4) + +/* ID_DFR1_EL1 definitions */ +#define ID_DFR1_MTPMU_SHIFT U(0) +#define ID_DFR1_MTPMU_MASK U(0xf) +#define ID_DFR1_MTPMU_SUPPORTED U(1) + +/* ID_MMFR4 definitions */ +#define ID_MMFR4_CNP_SHIFT U(12) +#define ID_MMFR4_CNP_LENGTH U(4) +#define ID_MMFR4_CNP_MASK U(0xf) + +#define ID_MMFR4_CCIDX_SHIFT U(24) +#define ID_MMFR4_CCIDX_LENGTH U(4) +#define ID_MMFR4_CCIDX_MASK U(0xf) + +/* ID_PFR0 definitions */ +#define ID_PFR0_AMU_SHIFT U(20) +#define ID_PFR0_AMU_LENGTH U(4) +#define ID_PFR0_AMU_MASK U(0xf) +#define ID_PFR0_AMU_NOT_SUPPORTED U(0x0) +#define ID_PFR0_AMU_V1 U(0x1) +#define ID_PFR0_AMU_V1P1 U(0x2) + +#define ID_PFR0_DIT_SHIFT U(24) +#define ID_PFR0_DIT_LENGTH U(4) +#define ID_PFR0_DIT_MASK U(0xf) +#define ID_PFR0_DIT_SUPPORTED (U(1) << ID_PFR0_DIT_SHIFT) + +/* ID_PFR1 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) +#define ID_PFR1_GENTIMER_SHIFT U(16) +#define ID_PFR1_GENTIMER_MASK U(0xf) +#define ID_PFR1_GIC_SHIFT U(28) +#define ID_PFR1_GIC_MASK U(0xf) +#define ID_PFR1_SEC_SHIFT U(4) +#define ID_PFR1_SEC_MASK U(0xf) +#define ID_PFR1_ELx_ENABLED U(1) + +/* SCTLR definitions */ +#define SCTLR_RES1_DEF ((U(1) << 23) | (U(1) << 22) | (U(1) << 4) | \ + (U(1) << 3)) +#if ARM_ARCH_MAJOR == 7 +#define SCTLR_RES1 SCTLR_RES1_DEF +#else +#define SCTLR_RES1 (SCTLR_RES1_DEF | (U(1) << 11)) +#endif +#define SCTLR_M_BIT (U(1) << 0) +#define SCTLR_A_BIT (U(1) << 1) +#define SCTLR_C_BIT (U(1) << 2) +#define SCTLR_CP15BEN_BIT (U(1) << 5) +#define SCTLR_ITD_BIT (U(1) << 7) +#define SCTLR_Z_BIT (U(1) << 11) +#define SCTLR_I_BIT (U(1) << 12) +#define SCTLR_V_BIT (U(1) << 13) +#define SCTLR_RR_BIT (U(1) << 14) +#define SCTLR_NTWI_BIT (U(1) << 16) +#define SCTLR_NTWE_BIT (U(1) << 18) +#define SCTLR_WXN_BIT (U(1) << 19) +#define SCTLR_UWXN_BIT (U(1) << 20) +#define SCTLR_EE_BIT (U(1) << 25) +#define SCTLR_TRE_BIT (U(1) << 28) +#define SCTLR_AFE_BIT (U(1) << 29) +#define SCTLR_TE_BIT (U(1) << 30) +#define SCTLR_DSSBS_BIT (U(1) << 31) +#define SCTLR_RESET_VAL (SCTLR_RES1 | SCTLR_NTWE_BIT | \ + SCTLR_NTWI_BIT | SCTLR_CP15BEN_BIT) + +/* SDCR definitions */ +#define SDCR_SPD(x) ((x) << 14) +#define SDCR_SPD_LEGACY U(0x0) +#define SDCR_SPD_DISABLE U(0x2) +#define SDCR_SPD_ENABLE U(0x3) +#define SDCR_SCCD_BIT (U(1) << 23) +#define SDCR_TTRF_BIT (U(1) << 19) +#define SDCR_SPME_BIT (U(1) << 17) +#define SDCR_RESET_VAL U(0x0) +#define SDCR_MTPME_BIT (U(1) << 28) + +/* HSCTLR definitions */ +#define HSCTLR_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ + (U(1) << 11) | (U(1) << 4) | (U(1) << 3)) + +#define HSCTLR_M_BIT (U(1) << 0) +#define HSCTLR_A_BIT (U(1) << 1) +#define HSCTLR_C_BIT (U(1) << 2) +#define HSCTLR_CP15BEN_BIT (U(1) << 5) +#define HSCTLR_ITD_BIT (U(1) << 7) +#define HSCTLR_SED_BIT (U(1) << 8) +#define HSCTLR_I_BIT (U(1) << 12) +#define HSCTLR_WXN_BIT (U(1) << 19) +#define HSCTLR_EE_BIT (U(1) << 25) +#define HSCTLR_TE_BIT (U(1) << 30) + +/* CPACR definitions */ +#define CPACR_FPEN(x) ((x) << 20) +#define CPACR_FP_TRAP_PL0 UL(0x1) +#define CPACR_FP_TRAP_ALL UL(0x2) +#define CPACR_FP_TRAP_NONE UL(0x3) + +/* SCR definitions */ +#define SCR_TWE_BIT (UL(1) << 13) +#define SCR_TWI_BIT (UL(1) << 12) +#define SCR_SIF_BIT (UL(1) << 9) +#define SCR_HCE_BIT (UL(1) << 8) +#define SCR_SCD_BIT (UL(1) << 7) +#define SCR_NET_BIT (UL(1) << 6) +#define SCR_AW_BIT (UL(1) << 5) +#define SCR_FW_BIT (UL(1) << 4) +#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(0x33ff) +#define SCR_RESET_VAL U(0x0) + +#define GET_NS_BIT(scr) ((scr) & SCR_NS_BIT) + +/* HCR definitions */ +#define HCR_TGE_BIT (U(1) << 27) +#define HCR_AMO_BIT (U(1) << 5) +#define HCR_IMO_BIT (U(1) << 4) +#define HCR_FMO_BIT (U(1) << 3) +#define HCR_RESET_VAL U(0x0) + +/* CNTHCTL definitions */ +#define CNTHCTL_RESET_VAL U(0x0) +#define PL1PCEN_BIT (U(1) << 1) +#define PL1PCTEN_BIT (U(1) << 0) + +/* CNTKCTL definitions */ +#define PL0PTEN_BIT (U(1) << 9) +#define PL0VTEN_BIT (U(1) << 8) +#define PL0PCTEN_BIT (U(1) << 0) +#define PL0VCTEN_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) + +/* HCPTR definitions */ +#define HCPTR_RES1 ((U(1) << 13) | (U(1) << 12) | U(0x3ff)) +#define TCPAC_BIT (U(1) << 31) +#define TAM_SHIFT U(30) +#define TAM_BIT (U(1) << TAM_SHIFT) +#define TTA_BIT (U(1) << 20) +#define TCP11_BIT (U(1) << 11) +#define TCP10_BIT (U(1) << 10) +#define HCPTR_RESET_VAL HCPTR_RES1 + +/* VTTBR defintions */ +#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) + +/* HDCR definitions */ +#define HDCR_MTPME_BIT (U(1) << 28) +#define HDCR_HLP_BIT (U(1) << 26) +#define HDCR_HPME_BIT (U(1) << 7) +#define HDCR_RESET_VAL U(0x0) + +/* HSTR definitions */ +#define HSTR_RESET_VAL U(0x0) + +/* CNTHP_CTL definitions */ +#define CNTHP_CTL_RESET_VAL U(0x0) + +/* NSACR definitions */ +#define NSASEDIS_BIT (U(1) << 15) +#define NSTRCDIS_BIT (U(1) << 20) +#define NSACR_CP11_BIT (U(1) << 11) +#define NSACR_CP10_BIT (U(1) << 10) +#define NSACR_IMP_DEF_MASK (U(0x7) << 16) +#define NSACR_ENABLE_FP_ACCESS (NSACR_CP11_BIT | NSACR_CP10_BIT) +#define NSACR_RESET_VAL U(0x0) + +/* CPACR definitions */ +#define ASEDIS_BIT (U(1) << 31) +#define TRCDIS_BIT (U(1) << 28) +#define CPACR_CP11_SHIFT U(22) +#define CPACR_CP10_SHIFT U(20) +#define CPACR_ENABLE_FP_ACCESS ((U(0x3) << CPACR_CP11_SHIFT) |\ + (U(0x3) << CPACR_CP10_SHIFT)) +#define CPACR_RESET_VAL U(0x0) + +/* FPEXC definitions */ +#define FPEXC_RES1 ((U(1) << 10) | (U(1) << 9) | (U(1) << 8)) +#define FPEXC_EN_BIT (U(1) << 30) +#define FPEXC_RESET_VAL FPEXC_RES1 + +/* SPSR/CPSR definitions */ +#define SPSR_FIQ_BIT (U(1) << 0) +#define SPSR_IRQ_BIT (U(1) << 1) +#define SPSR_ABT_BIT (U(1) << 2) +#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(0) +#define SPSR_E_BIG U(1) + +#define SPSR_T_SHIFT U(5) +#define SPSR_T_MASK U(0x1) +#define SPSR_T_ARM U(0) +#define SPSR_T_THUMB U(1) + +#define SPSR_MODE_SHIFT U(0) +#define SPSR_MODE_MASK U(0x7) + +#define SPSR_SSBS_BIT BIT_32(23) + +#define DISABLE_ALL_EXCEPTIONS \ + (SPSR_FIQ_BIT | SPSR_IRQ_BIT | SPSR_ABT_BIT) + +#define CPSR_DIT_BIT (U(1) << 21) +/* + * TTBCR definitions + */ +#define TTBCR_EAE_BIT (U(1) << 31) + +#define TTBCR_SH1_NON_SHAREABLE (U(0x0) << 28) +#define TTBCR_SH1_OUTER_SHAREABLE (U(0x2) << 28) +#define TTBCR_SH1_INNER_SHAREABLE (U(0x3) << 28) + +#define TTBCR_RGN1_OUTER_NC (U(0x0) << 26) +#define TTBCR_RGN1_OUTER_WBA (U(0x1) << 26) +#define TTBCR_RGN1_OUTER_WT (U(0x2) << 26) +#define TTBCR_RGN1_OUTER_WBNA (U(0x3) << 26) + +#define TTBCR_RGN1_INNER_NC (U(0x0) << 24) +#define TTBCR_RGN1_INNER_WBA (U(0x1) << 24) +#define TTBCR_RGN1_INNER_WT (U(0x2) << 24) +#define TTBCR_RGN1_INNER_WBNA (U(0x3) << 24) + +#define TTBCR_EPD1_BIT (U(1) << 23) +#define TTBCR_A1_BIT (U(1) << 22) + +#define TTBCR_T1SZ_SHIFT U(16) +#define TTBCR_T1SZ_MASK U(0x7) +#define TTBCR_TxSZ_MIN U(0) +#define TTBCR_TxSZ_MAX U(7) + +#define TTBCR_SH0_NON_SHAREABLE (U(0x0) << 12) +#define TTBCR_SH0_OUTER_SHAREABLE (U(0x2) << 12) +#define TTBCR_SH0_INNER_SHAREABLE (U(0x3) << 12) + +#define TTBCR_RGN0_OUTER_NC (U(0x0) << 10) +#define TTBCR_RGN0_OUTER_WBA (U(0x1) << 10) +#define TTBCR_RGN0_OUTER_WT (U(0x2) << 10) +#define TTBCR_RGN0_OUTER_WBNA (U(0x3) << 10) + +#define TTBCR_RGN0_INNER_NC (U(0x0) << 8) +#define TTBCR_RGN0_INNER_WBA (U(0x1) << 8) +#define TTBCR_RGN0_INNER_WT (U(0x2) << 8) +#define TTBCR_RGN0_INNER_WBNA (U(0x3) << 8) + +#define TTBCR_EPD0_BIT (U(1) << 7) +#define TTBCR_T0SZ_SHIFT U(0) +#define TTBCR_T0SZ_MASK U(0x7) + +/* + * HTCR definitions + */ +#define HTCR_RES1 ((U(1) << 31) | (U(1) << 23)) + +#define HTCR_SH0_NON_SHAREABLE (U(0x0) << 12) +#define HTCR_SH0_OUTER_SHAREABLE (U(0x2) << 12) +#define HTCR_SH0_INNER_SHAREABLE (U(0x3) << 12) + +#define HTCR_RGN0_OUTER_NC (U(0x0) << 10) +#define HTCR_RGN0_OUTER_WBA (U(0x1) << 10) +#define HTCR_RGN0_OUTER_WT (U(0x2) << 10) +#define HTCR_RGN0_OUTER_WBNA (U(0x3) << 10) + +#define HTCR_RGN0_INNER_NC (U(0x0) << 8) +#define HTCR_RGN0_INNER_WBA (U(0x1) << 8) +#define HTCR_RGN0_INNER_WT (U(0x2) << 8) +#define HTCR_RGN0_INNER_WBNA (U(0x3) << 8) + +#define HTCR_T0SZ_SHIFT U(0) +#define HTCR_T0SZ_MASK U(0x7) + +#define MODE_RW_SHIFT U(0x4) +#define MODE_RW_MASK U(0x1) +#define MODE_RW_32 U(0x1) + +#define MODE32_SHIFT U(0) +#define MODE32_MASK U(0x1f) +#define MODE32_usr U(0x10) +#define MODE32_fiq U(0x11) +#define MODE32_irq U(0x12) +#define MODE32_svc U(0x13) +#define MODE32_mon U(0x16) +#define MODE32_abt U(0x17) +#define MODE32_hyp U(0x1a) +#define MODE32_und U(0x1b) +#define MODE32_sys U(0x1f) + +#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) + +#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)) \ +) + +/* + * TTBR definitions + */ +#define TTBR_CNP_BIT ULL(0x1) + +/* + * CTR 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_WIDTH U(4) +#define CTR_DMINLINE_MASK ((U(1) << 4) - U(1)) +#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 */ + +/* PMCR definitions */ +#define PMCR_N_SHIFT U(11) +#define PMCR_N_MASK U(0x1f) +#define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT) +#define PMCR_LP_BIT (U(1) << 7) +#define PMCR_LC_BIT (U(1) << 6) +#define PMCR_DP_BIT (U(1) << 5) +#define PMCR_RESET_VAL U(0x0) + +/******************************************************************************* + * Definitions of register offsets, fields and macros for CPU system + * instructions. + ******************************************************************************/ + +#define TLBI_ADDR_SHIFT U(0) +#define TLBI_ADDR_MASK U(0xFFFFF000) +#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) + +/* Physical timer control register bit fields shifts and masks */ +#define CNTP_CTL_ENABLE_SHIFT 0 +#define CNTP_CTL_IMASK_SHIFT 1 +#define CNTP_CTL_ISTATUS_SHIFT 2 + +#define CNTP_CTL_ENABLE_MASK U(1) +#define CNTP_CTL_IMASK_MASK U(1) +#define CNTP_CTL_ISTATUS_MASK U(1) + +/* MAIR macros */ +#define MAIR0_ATTR_SET(attr, index) ((attr) << ((index) << U(3))) +#define MAIR1_ATTR_SET(attr, index) ((attr) << (((index) - U(3)) << U(3))) + +/* System register defines The format is: coproc, opt1, CRn, CRm, opt2 */ +#define SCR p15, 0, c1, c1, 0 +#define SCTLR p15, 0, c1, c0, 0 +#define ACTLR p15, 0, c1, c0, 1 +#define SDCR p15, 0, c1, c3, 1 +#define MPIDR p15, 0, c0, c0, 5 +#define MIDR p15, 0, c0, c0, 0 +#define HVBAR p15, 4, c12, c0, 0 +#define VBAR p15, 0, c12, c0, 0 +#define MVBAR p15, 0, c12, c0, 1 +#define NSACR p15, 0, c1, c1, 2 +#define CPACR p15, 0, c1, c0, 2 +#define DCCIMVAC p15, 0, c7, c14, 1 +#define DCCMVAC p15, 0, c7, c10, 1 +#define DCIMVAC p15, 0, c7, c6, 1 +#define DCCISW p15, 0, c7, c14, 2 +#define DCCSW p15, 0, c7, c10, 2 +#define DCISW p15, 0, c7, c6, 2 +#define CTR p15, 0, c0, c0, 1 +#define CNTFRQ p15, 0, c14, c0, 0 +#define ID_MMFR4 p15, 0, c0, c2, 6 +#define ID_DFR0 p15, 0, c0, c1, 2 +#define ID_DFR1 p15, 0, c0, c3, 5 +#define ID_PFR0 p15, 0, c0, c1, 0 +#define ID_PFR1 p15, 0, c0, c1, 1 +#define MAIR0 p15, 0, c10, c2, 0 +#define MAIR1 p15, 0, c10, c2, 1 +#define TTBCR p15, 0, c2, c0, 2 +#define TTBR0 p15, 0, c2, c0, 0 +#define TTBR1 p15, 0, c2, c0, 1 +#define TLBIALL p15, 0, c8, c7, 0 +#define TLBIALLH p15, 4, c8, c7, 0 +#define TLBIALLIS p15, 0, c8, c3, 0 +#define TLBIMVA p15, 0, c8, c7, 1 +#define TLBIMVAA p15, 0, c8, c7, 3 +#define TLBIMVAAIS p15, 0, c8, c3, 3 +#define TLBIMVAHIS p15, 4, c8, c3, 1 +#define BPIALLIS p15, 0, c7, c1, 6 +#define BPIALL p15, 0, c7, c5, 6 +#define ICIALLU p15, 0, c7, c5, 0 +#define HSCTLR p15, 4, c1, c0, 0 +#define HCR p15, 4, c1, c1, 0 +#define HCPTR p15, 4, c1, c1, 2 +#define HSTR p15, 4, c1, c1, 3 +#define CNTHCTL p15, 4, c14, c1, 0 +#define CNTKCTL p15, 0, c14, c1, 0 +#define VPIDR p15, 4, c0, c0, 0 +#define VMPIDR p15, 4, c0, c0, 5 +#define ISR p15, 0, c12, c1, 0 +#define CLIDR p15, 1, c0, c0, 1 +#define CSSELR p15, 2, c0, c0, 0 +#define CCSIDR p15, 1, c0, c0, 0 +#define CCSIDR2 p15, 1, c0, c0, 2 +#define HTCR p15, 4, c2, c0, 2 +#define HMAIR0 p15, 4, c10, c2, 0 +#define ATS1CPR p15, 0, c7, c8, 0 +#define ATS1HR p15, 4, c7, c8, 0 +#define DBGOSDLR p14, 0, c1, c3, 4 + +/* Debug register defines. The format is: coproc, opt1, CRn, CRm, opt2 */ +#define HDCR p15, 4, c1, c1, 1 +#define PMCR p15, 0, c9, c12, 0 +#define CNTHP_TVAL p15, 4, c14, c2, 0 +#define CNTHP_CTL p15, 4, c14, c2, 1 + +/* AArch32 coproc registers for 32bit MMU descriptor support */ +#define PRRR p15, 0, c10, c2, 0 +#define NMRR p15, 0, c10, c2, 1 +#define DACR p15, 0, c3, c0, 0 + +/* GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRn, CRm, opt2 */ +#define ICC_IAR1 p15, 0, c12, c12, 0 +#define ICC_IAR0 p15, 0, c12, c8, 0 +#define ICC_EOIR1 p15, 0, c12, c12, 1 +#define ICC_EOIR0 p15, 0, c12, c8, 1 +#define ICC_HPPIR1 p15, 0, c12, c12, 2 +#define ICC_HPPIR0 p15, 0, c12, c8, 2 +#define ICC_BPR1 p15, 0, c12, c12, 3 +#define ICC_BPR0 p15, 0, c12, c8, 3 +#define ICC_DIR p15, 0, c12, c11, 1 +#define ICC_PMR p15, 0, c4, c6, 0 +#define ICC_RPR p15, 0, c12, c11, 3 +#define ICC_CTLR p15, 0, c12, c12, 4 +#define ICC_MCTLR p15, 6, c12, c12, 4 +#define ICC_SRE p15, 0, c12, c12, 5 +#define ICC_HSRE p15, 4, c12, c9, 5 +#define ICC_MSRE p15, 6, c12, c12, 5 +#define ICC_IGRPEN0 p15, 0, c12, c12, 6 +#define ICC_IGRPEN1 p15, 0, c12, c12, 7 +#define ICC_MGRPEN1 p15, 6, c12, c12, 7 + +/* 64 bit system register defines The format is: coproc, opt1, CRm */ +#define TTBR0_64 p15, 0, c2 +#define TTBR1_64 p15, 1, c2 +#define CNTVOFF_64 p15, 4, c14 +#define VTTBR_64 p15, 6, c2 +#define CNTPCT_64 p15, 0, c14 +#define HTTBR_64 p15, 4, c2 +#define CNTHP_CVAL_64 p15, 6, c14 +#define PAR_64 p15, 0, c7 + +/* 64 bit GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRm */ +#define ICC_SGI1R_EL1_64 p15, 0, c12 +#define ICC_ASGI1R_EL1_64 p15, 1, c12 +#define ICC_SGI0R_EL1_64 p15, 2, c12 + +/******************************************************************************* + * Definitions of MAIR encodings for device and normal memory + ******************************************************************************/ +/* + * MAIR encodings for device memory attributes. + */ +#define MAIR_DEV_nGnRnE U(0x0) +#define MAIR_DEV_nGnRE U(0x4) +#define MAIR_DEV_nGRE U(0x8) +#define MAIR_DEV_GRE U(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 U(0x1) +#define MAIR_NORM_WT_TR_RA U(0x2) +#define MAIR_NORM_WT_TR_RWA U(0x3) +#define MAIR_NORM_NC U(0x4) +#define MAIR_NORM_WB_TR_WA U(0x5) +#define MAIR_NORM_WB_TR_RA U(0x6) +#define MAIR_NORM_WB_TR_RWA U(0x7) +#define MAIR_NORM_WT_NTR_NA U(0x8) +#define MAIR_NORM_WT_NTR_WA U(0x9) +#define MAIR_NORM_WT_NTR_RA U(0xa) +#define MAIR_NORM_WT_NTR_RWA U(0xb) +#define MAIR_NORM_WB_NTR_NA U(0xc) +#define MAIR_NORM_WB_NTR_WA U(0xd) +#define MAIR_NORM_WB_NTR_RA U(0xe) +#define MAIR_NORM_WB_NTR_RWA U(0xf) + +#define MAIR_NORM_OUTER_SHIFT U(4) + +#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \ + ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) + +/* PAR fields */ +#define PAR_F_SHIFT U(0) +#define PAR_F_MASK ULL(0x1) +#define PAR_ADDR_SHIFT U(12) +#define PAR_ADDR_MASK (BIT_64(40) - ULL(1)) /* 40-bits-wide page address */ + +/******************************************************************************* + * Definitions for system register interface to AMU for FEAT_AMUv1 + ******************************************************************************/ +#define AMCR p15, 0, c13, c2, 0 +#define AMCFGR p15, 0, c13, c2, 1 +#define AMCGCR p15, 0, c13, c2, 2 +#define AMUSERENR p15, 0, c13, c2, 3 +#define AMCNTENCLR0 p15, 0, c13, c2, 4 +#define AMCNTENSET0 p15, 0, c13, c2, 5 +#define AMCNTENCLR1 p15, 0, c13, c3, 0 +#define AMCNTENSET1 p15, 0, c13, c3, 1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00 p15, 0, c0 +#define AMEVCNTR01 p15, 1, c0 +#define AMEVCNTR02 p15, 2, c0 +#define AMEVCNTR03 p15, 3, c0 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00 p15, 0, c13, c6, 0 +#define AMEVTYPER01 p15, 0, c13, c6, 1 +#define AMEVTYPER02 p15, 0, c13, c6, 2 +#define AMEVTYPER03 p15, 0, c13, c6, 3 + +/* Activity Monitor Group 1 Event Counter Registers */ +#define AMEVCNTR10 p15, 0, c4 +#define AMEVCNTR11 p15, 1, c4 +#define AMEVCNTR12 p15, 2, c4 +#define AMEVCNTR13 p15, 3, c4 +#define AMEVCNTR14 p15, 4, c4 +#define AMEVCNTR15 p15, 5, c4 +#define AMEVCNTR16 p15, 6, c4 +#define AMEVCNTR17 p15, 7, c4 +#define AMEVCNTR18 p15, 0, c5 +#define AMEVCNTR19 p15, 1, c5 +#define AMEVCNTR1A p15, 2, c5 +#define AMEVCNTR1B p15, 3, c5 +#define AMEVCNTR1C p15, 4, c5 +#define AMEVCNTR1D p15, 5, c5 +#define AMEVCNTR1E p15, 6, c5 +#define AMEVCNTR1F p15, 7, c5 + +/* Activity Monitor Group 1 Event Type Registers */ +#define AMEVTYPER10 p15, 0, c13, c14, 0 +#define AMEVTYPER11 p15, 0, c13, c14, 1 +#define AMEVTYPER12 p15, 0, c13, c14, 2 +#define AMEVTYPER13 p15, 0, c13, c14, 3 +#define AMEVTYPER14 p15, 0, c13, c14, 4 +#define AMEVTYPER15 p15, 0, c13, c14, 5 +#define AMEVTYPER16 p15, 0, c13, c14, 6 +#define AMEVTYPER17 p15, 0, c13, c14, 7 +#define AMEVTYPER18 p15, 0, c13, c15, 0 +#define AMEVTYPER19 p15, 0, c13, c15, 1 +#define AMEVTYPER1A p15, 0, c13, c15, 2 +#define AMEVTYPER1B p15, 0, c13, c15, 3 +#define AMEVTYPER1C p15, 0, c13, c15, 4 +#define AMEVTYPER1D p15, 0, c13, c15, 5 +#define AMEVTYPER1E p15, 0, c13, c15, 6 +#define AMEVTYPER1F p15, 0, c13, c15, 7 + +/* AMCNTENSET0 definitions */ +#define AMCNTENSET0_Pn_SHIFT U(0) +#define AMCNTENSET0_Pn_MASK U(0xffff) + +/* AMCNTENSET1 definitions */ +#define AMCNTENSET1_Pn_SHIFT U(0) +#define AMCNTENSET1_Pn_MASK U(0xffff) + +/* AMCNTENCLR0 definitions */ +#define AMCNTENCLR0_Pn_SHIFT U(0) +#define AMCNTENCLR0_Pn_MASK U(0xffff) + +/* AMCNTENCLR1 definitions */ +#define AMCNTENCLR1_Pn_SHIFT U(0) +#define AMCNTENCLR1_Pn_MASK U(0xffff) + +/* AMCR definitions */ +#define AMCR_CG1RZ_SHIFT U(17) +#define AMCR_CG1RZ_BIT (ULL(1) << AMCR_CG1RZ_SHIFT) + +/* AMCFGR definitions */ +#define AMCFGR_NCG_SHIFT U(28) +#define AMCFGR_NCG_MASK U(0xf) +#define AMCFGR_N_SHIFT U(0) +#define AMCFGR_N_MASK U(0xff) + +/* AMCGCR definitions */ +#define AMCGCR_CG0NC_SHIFT U(0) +#define AMCGCR_CG0NC_MASK U(0xff) +#define AMCGCR_CG1NC_SHIFT U(8) +#define AMCGCR_CG1NC_MASK U(0xff) + +/******************************************************************************* + * Definitions for DynamicIQ Shared Unit registers + ******************************************************************************/ +#define CLUSTERPWRDN p15, 0, c15, c3, 6 + +/* CLUSTERPWRDN 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/arm-trusted-firmware/include/arch/aarch32/arch_features.h b/arm-trusted-firmware/include/arch/aarch32/arch_features.h new file mode 100644 index 0000000..ddf0968 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/arch_features.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, 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) +{ + return ((read_id_pfr1() >> ID_PFR1_GENTIMER_SHIFT) & + ID_PFR1_GENTIMER_MASK) != 0U; +} + +static inline bool is_armv8_2_ttcnp_present(void) +{ + return ((read_id_mmfr4() >> ID_MMFR4_CNP_SHIFT) & + ID_MMFR4_CNP_MASK) != 0U; +} + +#endif /* ARCH_FEATURES_H */ diff --git a/arm-trusted-firmware/include/arch/aarch32/arch_helpers.h b/arm-trusted-firmware/include/arch/aarch32/arch_helpers.h new file mode 100644 index 0000000..0330989 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/arch_helpers.h @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2016-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_COPROCR_WRITE_FUNC(_name, coproc, opc1, CRn, CRm, opc2) \ +static inline void write_## _name(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_COPROCR_READ_FUNC(_name, coproc, opc1, CRn, CRm, opc2) \ +static inline u_register_t read_ ## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("mrc "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : "=r" (v));\ + return v; \ +} + +/* + * The undocumented %Q and %R extended asm are used to implemented the below + * 64 bit `mrrc` and `mcrr` instructions. + */ + +#define _DEFINE_COPROCR_WRITE_FUNC_64(_name, coproc, opc1, CRm) \ +static inline void write64_## _name(uint64_t v) \ +{ \ + __asm__ volatile ("mcrr "#coproc","#opc1", %Q0, %R0,"#CRm : : "r" (v));\ +} + +#define _DEFINE_COPROCR_READ_FUNC_64(_name, coproc, opc1, CRm) \ +static inline uint64_t read64_## _name(void) \ +{ uint64_t v; \ + __asm__ volatile ("mrrc "#coproc","#opc1", %Q0, %R0,"#CRm : "=r" (v));\ + return v; \ +} + +#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 _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(const u_register_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v)); \ +} + +/* Define read function for coproc register */ +#define DEFINE_COPROCR_READ_FUNC(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__) + +/* Define write function for coproc register */ +#define DEFINE_COPROCR_WRITE_FUNC(_name, ...) \ + _DEFINE_COPROCR_WRITE_FUNC(_name, __VA_ARGS__) + +/* Define read & write function for coproc register */ +#define DEFINE_COPROCR_RW_FUNCS(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__) \ + _DEFINE_COPROCR_WRITE_FUNC(_name, __VA_ARGS__) + +/* Define 64 bit read function for coproc register */ +#define DEFINE_COPROCR_READ_FUNC_64(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__) + +/* Define 64 bit write function for coproc register */ +#define DEFINE_COPROCR_WRITE_FUNC_64(_name, ...) \ + _DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__) + +/* Define 64 bit read & write function for coproc register */ +#define DEFINE_COPROCR_RW_FUNCS_64(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__) \ + _DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__) + +/* 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) + +/********************************************************************** + * Macros to create inline functions for tlbi operations + *********************************************************************/ + +#define _DEFINE_TLBIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void tlbi##_op(void) \ +{ \ + u_register_t v = 0; \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_BPIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void bpi##_op(void) \ +{ \ + u_register_t v = 0; \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_TLBIOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void tlbi##_op(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +/* Define function for simple TLBI operation */ +#define DEFINE_TLBIOP_FUNC(_op, ...) \ + _DEFINE_TLBIOP_FUNC(_op, __VA_ARGS__) + +/* Define function for TLBI operation with register parameter */ +#define DEFINE_TLBIOP_PARAM_FUNC(_op, ...) \ + _DEFINE_TLBIOP_PARAM_FUNC(_op, __VA_ARGS__) + +/* Define function for simple BPI operation */ +#define DEFINE_BPIOP_FUNC(_op, ...) \ + _DEFINE_BPIOP_FUNC(_op, __VA_ARGS__) + +/********************************************************************** + * Macros to create inline functions for DC operations + *********************************************************************/ +#define _DEFINE_DCOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void dc##_op(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +/* Define function for DC operation with register parameter */ +#define DEFINE_DCOP_PARAM_FUNC(_op, ...) \ + _DEFINE_DCOP_PARAM_FUNC(_op, __VA_ARGS__) + +/********************************************************************** + * 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 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(u_register_t v) \ +{ \ + __asm__ (#_op " " #_type ", %0" : : "r" (v)); \ +} + +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_secure(void); +void disable_mmu_icache_secure(void); + +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) + +/* dmb ld is not valid for armv7/thumb machines */ +#if ARM_ARCH_MAJOR != 7 +DEFINE_SYSOP_TYPE_FUNC(dmb, ld) +#endif + +DEFINE_SYSOP_TYPE_FUNC(dsb, ish) +DEFINE_SYSOP_TYPE_FUNC(dsb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dmb, ish) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishst) +DEFINE_SYSOP_FUNC(isb) + +void __dead2 smc(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3, + uint32_t r4, uint32_t r5, uint32_t r6, uint32_t r7); + +DEFINE_SYSREG_RW_FUNCS(spsr) +DEFINE_SYSREG_RW_FUNCS(cpsr) + +/******************************************************************************* + * System register accessor prototypes + ******************************************************************************/ +DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR) +DEFINE_COPROCR_READ_FUNC(midr, MIDR) +DEFINE_COPROCR_READ_FUNC(id_mmfr4, ID_MMFR4) +DEFINE_COPROCR_READ_FUNC(id_dfr0, ID_DFR0) +DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0) +DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1) +DEFINE_COPROCR_READ_FUNC(isr, ISR) +DEFINE_COPROCR_READ_FUNC(clidr, CLIDR) +DEFINE_COPROCR_READ_FUNC_64(cntpct, CNTPCT_64) + +DEFINE_COPROCR_RW_FUNCS(scr, SCR) +DEFINE_COPROCR_RW_FUNCS(ctr, CTR) +DEFINE_COPROCR_RW_FUNCS(sctlr, SCTLR) +DEFINE_COPROCR_RW_FUNCS(actlr, ACTLR) +DEFINE_COPROCR_RW_FUNCS(hsctlr, HSCTLR) +DEFINE_COPROCR_RW_FUNCS(hcr, HCR) +DEFINE_COPROCR_RW_FUNCS(hcptr, HCPTR) +DEFINE_COPROCR_RW_FUNCS(cntfrq, CNTFRQ) +DEFINE_COPROCR_RW_FUNCS(cnthctl, CNTHCTL) +DEFINE_COPROCR_RW_FUNCS(mair0, MAIR0) +DEFINE_COPROCR_RW_FUNCS(mair1, MAIR1) +DEFINE_COPROCR_RW_FUNCS(hmair0, HMAIR0) +DEFINE_COPROCR_RW_FUNCS(ttbcr, TTBCR) +DEFINE_COPROCR_RW_FUNCS(htcr, HTCR) +DEFINE_COPROCR_RW_FUNCS(ttbr0, TTBR0) +DEFINE_COPROCR_RW_FUNCS_64(ttbr0, TTBR0_64) +DEFINE_COPROCR_RW_FUNCS(ttbr1, TTBR1) +DEFINE_COPROCR_RW_FUNCS_64(httbr, HTTBR_64) +DEFINE_COPROCR_RW_FUNCS(vpidr, VPIDR) +DEFINE_COPROCR_RW_FUNCS(vmpidr, VMPIDR) +DEFINE_COPROCR_RW_FUNCS_64(vttbr, VTTBR_64) +DEFINE_COPROCR_RW_FUNCS_64(ttbr1, TTBR1_64) +DEFINE_COPROCR_RW_FUNCS_64(cntvoff, CNTVOFF_64) +DEFINE_COPROCR_RW_FUNCS(csselr, CSSELR) +DEFINE_COPROCR_RW_FUNCS(hstr, HSTR) +DEFINE_COPROCR_RW_FUNCS(cnthp_ctl_el2, CNTHP_CTL) +DEFINE_COPROCR_RW_FUNCS(cnthp_tval_el2, CNTHP_TVAL) +DEFINE_COPROCR_RW_FUNCS_64(cnthp_cval_el2, CNTHP_CVAL_64) + +#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_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE) +DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE) +DEFINE_COPROCR_RW_FUNCS(icc_sre_el3, ICC_MSRE) +DEFINE_COPROCR_RW_FUNCS(icc_pmr_el1, ICC_PMR) +DEFINE_COPROCR_RW_FUNCS(icc_rpr_el1, ICC_RPR) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el3, ICC_MGRPEN1) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0) +DEFINE_COPROCR_RW_FUNCS(icc_hppir0_el1, ICC_HPPIR0) +DEFINE_COPROCR_RW_FUNCS(icc_hppir1_el1, ICC_HPPIR1) +DEFINE_COPROCR_RW_FUNCS(icc_iar0_el1, ICC_IAR0) +DEFINE_COPROCR_RW_FUNCS(icc_iar1_el1, ICC_IAR1) +DEFINE_COPROCR_RW_FUNCS(icc_eoir0_el1, ICC_EOIR0) +DEFINE_COPROCR_RW_FUNCS(icc_eoir1_el1, ICC_EOIR1) +DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64) +DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64) + +DEFINE_COPROCR_RW_FUNCS(sdcr, SDCR) +DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR) +DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL) +DEFINE_COPROCR_READ_FUNC(pmcr, PMCR) + +/* + * Address translation + */ +DEFINE_COPROCR_WRITE_FUNC(ats1cpr, ATS1CPR) +DEFINE_COPROCR_WRITE_FUNC(ats1hr, ATS1HR) +DEFINE_COPROCR_RW_FUNCS_64(par, PAR_64) + +DEFINE_COPROCR_RW_FUNCS(nsacr, NSACR) + +/* AArch32 coproc registers for 32bit MMU descriptor support */ +DEFINE_COPROCR_RW_FUNCS(prrr, PRRR) +DEFINE_COPROCR_RW_FUNCS(nmrr, NMRR) +DEFINE_COPROCR_RW_FUNCS(dacr, DACR) + +/* Coproc registers for 32bit AMU support */ +DEFINE_COPROCR_READ_FUNC(amcfgr, AMCFGR) +DEFINE_COPROCR_READ_FUNC(amcgcr, AMCGCR) +DEFINE_COPROCR_RW_FUNCS(amcr, AMCR) + +DEFINE_COPROCR_RW_FUNCS(amcntenset0, AMCNTENSET0) +DEFINE_COPROCR_RW_FUNCS(amcntenset1, AMCNTENSET1) +DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0) +DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1) + +/* Coproc registers for 64bit AMU support */ +DEFINE_COPROCR_RW_FUNCS_64(amevcntr00, AMEVCNTR00) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr01, AMEVCNTR01) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr02, AMEVCNTR02) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr03, AMEVCNTR03) + +/* + * TLBI operation prototypes + */ +DEFINE_TLBIOP_FUNC(all, TLBIALL) +DEFINE_TLBIOP_FUNC(allis, TLBIALLIS) +DEFINE_TLBIOP_PARAM_FUNC(mva, TLBIMVA) +DEFINE_TLBIOP_PARAM_FUNC(mvaa, TLBIMVAA) +DEFINE_TLBIOP_PARAM_FUNC(mvaais, TLBIMVAAIS) +DEFINE_TLBIOP_PARAM_FUNC(mvahis, TLBIMVAHIS) + +/* + * BPI operation prototypes. + */ +DEFINE_BPIOP_FUNC(allis, BPIALLIS) + +/* + * DC operation prototypes + */ +DEFINE_DCOP_PARAM_FUNC(civac, DCCIMVAC) +DEFINE_DCOP_PARAM_FUNC(ivac, DCIMVAC) +#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 +DEFINE_DCOP_PARAM_FUNC(cvac, DCCIMVAC) +#else +DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC) +#endif + +/* + * DynamIQ Shared Unit power management + */ +DEFINE_COPROCR_RW_FUNCS(clusterpwrdn, CLUSTERPWRDN) + +/* Previously defined accessor functions with incomplete register names */ +#define dsb() dsbsy() +#define dmb() dmbsy() + +/* dmb ld is not valid for armv7/thumb machines, so alias it to dmb */ +#if ARM_ARCH_MAJOR == 7 +#define dmbld() dmb() +#endif + +#define IS_IN_SECURE() \ + (GET_NS_BIT(read_scr()) == 0) + +#define IS_IN_HYP() (GET_M32(read_cpsr()) == MODE32_hyp) +#define IS_IN_SVC() (GET_M32(read_cpsr()) == MODE32_svc) +#define IS_IN_MON() (GET_M32(read_cpsr()) == MODE32_mon) +#define IS_IN_EL2() IS_IN_HYP() +/* If EL3 is AArch32, then secure PL1 and monitor mode correspond to EL3 */ +#define IS_IN_EL3() \ + ((GET_M32(read_cpsr()) == MODE32_mon) || \ + (IS_IN_SECURE() && (GET_M32(read_cpsr()) != MODE32_usr))) + +static inline unsigned int get_current_el(void) +{ + if (IS_IN_EL3()) { + return 3U; + } else if (IS_IN_EL2()) { + return 2U; + } else { + return 1U; + } +} + +/* Macros for compatibility with AArch64 system registers */ +#define read_mpidr_el1() read_mpidr() + +#define read_scr_el3() read_scr() +#define write_scr_el3(_v) write_scr(_v) + +#define read_hcr_el2() read_hcr() +#define write_hcr_el2(_v) write_hcr(_v) + +#define read_cpacr_el1() read_cpacr() +#define write_cpacr_el1(_v) write_cpacr(_v) + +#define read_cntfrq_el0() read_cntfrq() +#define write_cntfrq_el0(_v) write_cntfrq(_v) +#define read_isr_el1() read_isr() + +#define read_cntpct_el0() read64_cntpct() + +#define read_ctr_el0() read_ctr() + +#define write_icc_sgi0r_el1(_v) write64_icc_sgi0r_el1(_v) + +#define read_daif() read_cpsr() +#define write_daif(flags) write_cpsr(flags) + +#define read_cnthp_cval_el2() read64_cnthp_cval_el2() +#define write_cnthp_cval_el2(v) write64_cnthp_cval_el2(v) + +#define read_amcntenset0_el0() read_amcntenset0() +#define read_amcntenset1_el0() read_amcntenset1() + +/* Helper functions to manipulate CPSR */ +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(); + __asm__ volatile ("cpsie i"); + isb(); +} + +static inline void enable_serror(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsie a"); + isb(); +} + +static inline void enable_fiq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsie f"); + isb(); +} + +static inline void disable_irq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid i"); + isb(); +} + +static inline void disable_serror(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid a"); + isb(); +} + +static inline void disable_fiq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid f"); + isb(); +} + +#endif /* ARCH_HELPERS_H */ diff --git a/arm-trusted-firmware/include/arch/aarch32/asm_macros.S b/arm-trusted-firmware/include/arch/aarch32/asm_macros.S new file mode 100644 index 0000000..483f9fe --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/asm_macros.S @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASM_MACROS_S +#define ASM_MACROS_S + +#include +#include +#include + +/* + * TLBI instruction with type specifier that implements the workaround for + * errata 813419 of Cortex-A57. + */ +#if ERRATA_A57_813419 +#define TLB_INVALIDATE(_reg, _coproc) \ + stcopr _reg, _coproc; \ + dsb ish; \ + stcopr _reg, _coproc +#else +#define TLB_INVALIDATE(_reg, _coproc) \ + stcopr _reg, _coproc +#endif + +#define WORD_SIZE 4 + + /* + * Co processor register accessors + */ + .macro ldcopr reg, coproc, opc1, CRn, CRm, opc2 + mrc \coproc, \opc1, \reg, \CRn, \CRm, \opc2 + .endm + + .macro ldcopr16 reg1, reg2, coproc, opc1, CRm + mrrc \coproc, \opc1, \reg1, \reg2, \CRm + .endm + + .macro stcopr reg, coproc, opc1, CRn, CRm, opc2 + mcr \coproc, \opc1, \reg, \CRn, \CRm, \opc2 + .endm + + .macro stcopr16 reg1, reg2, coproc, opc1, CRm + mcrr \coproc, \opc1, \reg1, \reg2, \CRm + .endm + + /* Cache line size helpers */ + .macro dcache_line_size reg, tmp + ldcopr \tmp, CTR + ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH + mov \reg, #WORD_SIZE + lsl \reg, \reg, \tmp + .endm + + .macro icache_line_size reg, tmp + ldcopr \tmp, CTR + and \tmp, \tmp, #CTR_IMINLINE_MASK + mov \reg, #WORD_SIZE + lsl \reg, \reg, \tmp + .endm + + /* + * Declare the exception vector table, enforcing it is aligned on a + * 32 byte boundary. + */ + .macro vector_base label + .section .vectors, "ax" + .align 5 + \label: + .endm + + /* + * This macro calculates the base address of the current CPU's multi + * processor(MP) stack using the plat_my_core_pos() index, the name of + * the stack storage and the size of each stack. + * Out: r0 = physical address of stack base + * Clobber: r14, r1, r2 + */ + .macro get_my_mp_stack _name, _size + bl plat_my_core_pos + ldr r2, =(\_name + \_size) + mov r1, #\_size + mla r0, r0, r1, r2 + .endm + + /* + * This macro calculates the base address of a uniprocessor(UP) stack + * using the name of the stack storage and the size of the stack + * Out: r0 = physical address of stack base + */ + .macro get_up_stack _name, _size + ldr r0, =(\_name + \_size) + .endm + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* + * Macro for mitigating against speculative execution. + * ARMv7 cores without Virtualization extension do not support the + * eret instruction. + */ + .macro exception_return + movs pc, lr + dsb nsh + isb + .endm + +#else + /* + * 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 + +#if (ARM_ARCH_MAJOR == 7) + /* ARMv7 does not support stl instruction */ + .macro stl _reg, _write_lock + dmb + str \_reg, \_write_lock + dsb + .endm +#endif + + /* + * Helper macro to generate the best mov/movw/movt combinations + * according to the value to be moved. + */ + .macro mov_imm _reg, _val + .if ((\_val) & 0xffff0000) == 0 + mov \_reg, #(\_val) + .else + movw \_reg, #((\_val) & 0xffff) + movt \_reg, #((\_val) >> 16) + .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 + + /* + * Helper macro to OR the bottom 32 bits of `_val` into `_reg_l` + * and the top 32 bits of `_val` into `_reg_h`. If either the bottom + * or top word of `_val` is zero, the corresponding OR operation + * is skipped. + */ + .macro orr64_imm _reg_l, _reg_h, _val + .if (\_val >> 32) + orr \_reg_h, \_reg_h, #(\_val >> 32) + .endif + .if (\_val & 0xffffffff) + orr \_reg_l, \_reg_l, #(\_val & 0xffffffff) + .endif + .endm + + /* + * Helper macro to bitwise-clear bits in `_reg_l` and + * `_reg_h` given a 64 bit immediate `_val`. The set bits + * in the bottom word of `_val` dictate which bits from + * `_reg_l` should be cleared. Similarly, the set bits in + * the top word of `_val` dictate which bits from `_reg_h` + * should be cleared. If either the bottom or top word of + * `_val` is zero, the corresponding BIC operation is skipped. + */ + .macro bic64_imm _reg_l, _reg_h, _val + .if (\_val >> 32) + bic \_reg_h, \_reg_h, #(\_val >> 32) + .endif + .if (\_val & 0xffffffff) + bic \_reg_l, \_reg_l, #(\_val & 0xffffffff) + .endif + .endm + + /* + * Helper macro for carrying out division in software when + * hardware division is not suported. \top holds the dividend + * in the function call and the remainder after + * the function is executed. \bot holds the divisor. \div holds + * the quotient and \temp is a temporary registed used in calcualtion. + * The division algorithm has been obtained from: + * http://www.keil.com/support/man/docs/armasm/armasm_dom1359731155623.htm + */ + .macro softudiv div:req,top:req,bot:req,temp:req + + mov \temp, \bot + cmp \temp, \top, lsr #1 +div1: + movls \temp, \temp, lsl #1 + cmp \temp, \top, lsr #1 + bls div1 + mov \div, #0 + +div2: + cmp \top, \temp + subcs \top, \top,\temp + ADC \div, \div, \div + mov \temp, \temp, lsr #1 + cmp \temp, \bot + bhs div2 + .endm +#endif /* ASM_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch32/assert_macros.S b/arm-trusted-firmware/include/arch/aarch32/assert_macros.S new file mode 100644 index 0000000..ab3a2eb --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/assert_macros.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 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. We assume that the stack is + * initialized prior to invoking 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 ;\ + ldr r0, =.L_assert_filename ;\ + ldr r1, =__LINE__ ;\ + b asm_assert;\ +300: + +#endif /* ASSERT_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch32/console_macros.S b/arm-trusted-firmware/include/arch/aarch32/console_macros.S new file mode 100644 index 0000000..996cb32 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/console_macros.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018-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 r0 and a valid return address in lr. + */ + .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 + ldr r1, =console_\_driver\()_putc + .else + mov r1, #0 + .endif + str r1, [r0, #CONSOLE_T_PUTC] + + .ifne \getc + ldr r1, =console_\_driver\()_getc + .else + mov r1, #0 + .endif + str r1, [r0, #CONSOLE_T_GETC] + + .ifne \flush + ldr r1, =console_\_driver\()_flush + .else + mov r1, #0 + .endif + str r1, [r0, #CONSOLE_T_FLUSH] + + mov r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH) + str r1, [r0, #CONSOLE_T_FLAGS] + b console_register + .endm + +#endif /* CONSOLE_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S b/arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S new file mode 100644 index 0000000..8b6765a --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2016-2022, 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 + +#define PAGE_START_MASK ~(PAGE_SIZE_MASK) + + /* + * Helper macro to initialise EL3 registers we care about. + */ + .macro el3_arch_init_common + /* --------------------------------------------------------------------- + * SCTLR has already been initialised - read current value before + * modifying. + * + * SCTLR.I: Enable the instruction cache. + * + * SCTLR.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. + * --------------------------------------------------------------------- + */ + ldr r1, =(SCTLR_I_BIT | SCTLR_A_BIT) + ldcopr r0, SCTLR + orr r0, r0, r1 + stcopr r0, SCTLR + isb + + /* --------------------------------------------------------------------- + * Initialise SCR, setting all fields rather than relying on the hw. + * + * SCR.SIF: Enabled so that Secure state instruction fetches from + * Non-secure memory are not permitted. + * --------------------------------------------------------------------- + */ + ldr r0, =(SCR_RESET_VAL | SCR_SIF_BIT) + stcopr r0, SCR + + /* ----------------------------------------------------- + * Enable the Asynchronous data abort now that the + * exception vectors have been setup. + * ----------------------------------------------------- + */ + cpsie a + isb + + /* --------------------------------------------------------------------- + * Initialise NSACR, setting all the fields, except for the + * IMPLEMENTATION DEFINED field, rather than relying on the hw. Some + * fields are architecturally UNKNOWN on reset. + * + * NSACR_ENABLE_FP_ACCESS: Represents NSACR.cp11 and NSACR.cp10. The + * cp11 field is ignored, but is set to same value as cp10. The cp10 + * field is set to allow access to Advanced SIMD and floating point + * features from both Security states. + * + * NSACR.NSTRCDIS: When system register trace implemented, Set to one + * so that NS System register accesses to all implemented trace + * registers are disabled. + * When system register trace is not implemented, this bit is RES0 and + * hence set to zero. + * --------------------------------------------------------------------- + */ + ldcopr r0, NSACR + and r0, r0, #NSACR_IMP_DEF_MASK + orr r0, r0, #(NSACR_RESET_VAL | NSACR_ENABLE_FP_ACCESS) + ldcopr r1, ID_DFR0 + ubfx r1, r1, #ID_DFR0_COPTRC_SHIFT, #ID_DFR0_COPTRC_LENGTH + cmp r1, #ID_DFR0_COPTRC_SUPPORTED + bne 1f + orr r0, r0, #NSTRCDIS_BIT +1: + stcopr r0, NSACR + isb + + /* --------------------------------------------------------------------- + * Initialise CPACR, setting all fields rather than relying on hw. Some + * fields are architecturally UNKNOWN on reset. + * + * CPACR.TRCDIS: Trap control for PL0 and PL1 System register accesses + * to trace registers. Set to zero to allow access. + * + * CPACR_ENABLE_FP_ACCESS: Represents CPACR.cp11 and CPACR.cp10. The + * cp11 field is ignored, but is set to same value as cp10. The cp10 + * field is set to allow full access from PL0 and PL1 to floating-point + * and Advanced SIMD features. + * --------------------------------------------------------------------- + */ + ldr r0, =((CPACR_RESET_VAL | CPACR_ENABLE_FP_ACCESS) & ~(TRCDIS_BIT)) + stcopr r0, CPACR + isb + + /* --------------------------------------------------------------------- + * Initialise FPEXC, setting all fields rather than relying on hw. Some + * fields are architecturally UNKNOWN on reset and are set to zero + * except for field(s) listed below. + * + * FPEXC.EN: Enable access to Advanced SIMD and floating point features + * from all exception levels. + * + * __SOFTFP__: Predefined macro exposed by soft-float toolchain. + * ARMv7 and Cortex-A32(ARMv8/aarch32) has both soft-float and + * hard-float variants of toolchain, avoid compiling below code with + * soft-float toolchain as "vmsr" instruction will not be recognized. + * --------------------------------------------------------------------- + */ +#if ((ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_VFP)) && !(__SOFTFP__) + ldr r0, =(FPEXC_RESET_VAL | FPEXC_EN_BIT) + vmsr FPEXC, r0 + isb +#endif + +#if (ARM_ARCH_MAJOR > 7) + /* --------------------------------------------------------------------- + * Initialise SDCR, setting all the fields rather than relying on hw. + * + * SDCR.SPD: Disable AArch32 privileged debug. Debug exceptions from + * Secure EL1 are disabled. + * + * SDCR.SCCD: Set to one so that cycle counting by PMCCNTR 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. + * + * SDCR.TTRF: Set to one so that access to trace filter control + * registers in non-monitor mode generate Monitor trap exception, + * unless the access generates a higher priority exception when + * trace filter control(FEAT_TRF) is implemented. + * When FEAT_TRF is not implemented, this bit is RES0. + * --------------------------------------------------------------------- + */ + ldr r0, =((SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE) | \ + SDCR_SCCD_BIT) & ~SDCR_TTRF_BIT) + ldcopr r1, ID_DFR0 + ubfx r1, r1, #ID_DFR0_TRACEFILT_SHIFT, #ID_DFR0_TRACEFILT_LENGTH + cmp r1, #ID_DFR0_TRACEFILT_SUPPORTED + bne 1f + orr r0, r0, #SDCR_TTRF_BIT +1: + stcopr r0, SDCR + + /* --------------------------------------------------------------------- + * Initialise PMCR, setting all fields rather than relying + * on hw. Some fields are architecturally UNKNOWN on reset. + * + * PMCR.LP: Set to one so that event counter overflow, that + * is recorded in PMOVSCLR[0-30], occurs on the increment + * that changes PMEVCNTR[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. + * This bit is Reserved, UNK/SBZP in ARMv7. + * + * PMCR.LC: Set to one so that cycle counter overflow, that + * is recorded in PMOVSCLR[31], occurs on the increment + * that changes PMCCNTR[63] from 1 to 0. + * This bit is Reserved, UNK/SBZP in ARMv7. + * + * PMCR.DP: Set to one to prohibit cycle counting whilst in Secure mode. + * --------------------------------------------------------------------- + */ + ldr r0, =(PMCR_RESET_VAL | PMCR_DP_BIT | PMCR_LC_BIT | \ + PMCR_LP_BIT) +#else + ldr r0, =(PMCR_RESET_VAL | PMCR_DP_BIT) +#endif + stcopr r0, PMCR + + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL3 + */ + ldcopr r0, ID_PFR0 + and r0, r0, #(ID_PFR0_DIT_MASK << ID_PFR0_DIT_SHIFT) + cmp r0, #ID_PFR0_DIT_SUPPORTED + bne 1f + mrs r0, cpsr + orr r0, r0, #CPSR_DIT_BIT + msr cpsr_cxsf, r0 +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 BL32 (SP_MIN). + * + * 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 the SCTLR register 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 + + /* Make sure we are in Secure Mode */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCR + tst r0, #SCR_NS_BIT + ASM_ASSERT(eq) +#endif + + .if \_init_sctlr + /* ------------------------------------------------------------- + * This is the initialisation of SCTLR and so must ensure that + * all fields are explicitly set rather than relying on hw. Some + * fields reset to an IMPLEMENTATION DEFINED value. + * + * SCTLR.TE: Set to zero so that exceptions to an Exception + * Level executing at PL1 are taken to A32 state. + * + * SCTLR.EE: Set the CPU endianness before doing anything that + * might involve memory reads or writes. Set to zero to select + * Little Endian. + * + * SCTLR.V: Set to zero to select the normal exception vectors + * with base address held in VBAR. + * + * SCTLR.DSSBS: Set to zero to disable speculation store bypass + * safe behaviour upon exception entry to EL3. + * ------------------------------------------------------------- + */ + ldr r0, =(SCTLR_RESET_VAL & ~(SCTLR_TE_BIT | SCTLR_EE_BIT | \ + SCTLR_V_BIT | SCTLR_DSSBS_BIT)) + stcopr r0, SCTLR + isb + .endif /* _init_sctlr */ + + /* Switch to monitor mode */ + cps #MODE32_mon + isb + +#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 + cmp r0, #0 + bxne r0 + .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 r0, =pie_fixup + ldr r1, =PAGE_START_MASK + and r0, r0, r1 + mov_imm r1, \_pie_fixup_size + add r1, r1, r0 + bl fixup_gdt_reloc +#endif /* ENABLE_PIE */ + .endif /* _pie_fixup_size */ + + /* --------------------------------------------------------------------- + * Set the exception vectors (VBAR/MVBAR). + * --------------------------------------------------------------------- + */ + ldr r0, =\_exception_vectors + stcopr r0, VBAR + stcopr r0, MVBAR + 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 + cmp r0, #0 + bne 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 */ + no_ret plat_panic_handler + + 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_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3) + /* ----------------------------------------------------------------- + * Invalidate the RW memory used by the 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. If PIE is enabled however, + * RO sections including the GOT may be modified during + * pie fixup. Therefore, to be on the safe side, invalidate + * the entire image region if PIE is enabled. + * ----------------------------------------------------------------- + */ +#if ENABLE_PIE +#if SEPARATE_CODE_AND_RODATA + ldr r0, =__TEXT_START__ +#else + ldr r0, =__RO_START__ +#endif /* SEPARATE_CODE_AND_RODATA */ +#else + ldr r0, =__RW_START__ +#endif /* ENABLE_PIE */ + ldr r1, =__RW_END__ + sub r1, r1, r0 + bl inv_dcache_range +#if defined(IMAGE_BL2) && SEPARATE_BL2_NOLOAD_REGION + ldr r0, =__BL2_NOLOAD_START__ + ldr r1, =__BL2_NOLOAD_END__ + sub r1, r1, r0 + bl inv_dcache_range +#endif +#endif + + /* + * zeromem uses r12 whereas it is used to save previous BL arg3, + * save it in r7 + */ + mov r7, r12 + ldr r0, =__BSS_START__ + ldr r1, =__BSS_END__ + sub r1, r1, r0 + bl zeromem + +#if USE_COHERENT_MEM + ldr r0, =__COHERENT_RAM_START__ + ldr r1, =__COHERENT_RAM_END_UNALIGNED__ + sub r1, r1, r0 + bl zeromem +#endif + + /* Restore r12 */ + mov r12, r7 + +#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM) + /* ----------------------------------------------------- + * Copy data from ROM to RAM. + * ----------------------------------------------------- + */ + ldr r0, =__DATA_RAM_START__ + ldr r1, =__DATA_ROM_START__ + ldr r2, =__DATA_RAM_END__ + sub r2, r2, r0 + bl memcpy4 +#endif + .endif /* _init_c_runtime */ + + /* --------------------------------------------------------------------- + * 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 + +#endif /* EL3_COMMON_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h b/arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h new file mode 100644 index 0000000..2ce7874 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMCCC_HELPERS_H +#define SMCCC_HELPERS_H + +#include + +/* These are offsets to registers in smc_ctx_t */ +#define SMC_CTX_GPREG_R0 U(0x0) +#define SMC_CTX_GPREG_R1 U(0x4) +#define SMC_CTX_GPREG_R2 U(0x8) +#define SMC_CTX_GPREG_R3 U(0xC) +#define SMC_CTX_GPREG_R4 U(0x10) +#define SMC_CTX_GPREG_R5 U(0x14) +#define SMC_CTX_SP_USR U(0x34) +#define SMC_CTX_SPSR_MON U(0x78) +#define SMC_CTX_SP_MON U(0x7C) +#define SMC_CTX_LR_MON U(0x80) +#define SMC_CTX_SCR U(0x84) +#define SMC_CTX_PMCR U(0x88) +#define SMC_CTX_SIZE U(0x90) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* + * The generic structure to save arguments and callee saved registers during + * an SMC. Also this structure is used to store the result return values after + * the completion of SMC service. + */ +typedef struct smc_ctx { + u_register_t r0; + u_register_t r1; + u_register_t r2; + u_register_t r3; + u_register_t r4; + u_register_t r5; + u_register_t r6; + u_register_t r7; + u_register_t r8; + u_register_t r9; + u_register_t r10; + u_register_t r11; + u_register_t r12; + /* spsr_usr doesn't exist */ + u_register_t sp_usr; + u_register_t lr_usr; + u_register_t spsr_irq; + u_register_t sp_irq; + u_register_t lr_irq; + u_register_t spsr_fiq; + u_register_t sp_fiq; + u_register_t lr_fiq; + u_register_t spsr_svc; + u_register_t sp_svc; + u_register_t lr_svc; + u_register_t spsr_abt; + u_register_t sp_abt; + u_register_t lr_abt; + u_register_t spsr_und; + u_register_t sp_und; + u_register_t lr_und; + u_register_t spsr_mon; + /* + * `sp_mon` will point to the C runtime stack in monitor mode. But prior + * to exit from SMC, this will point to the `smc_ctx_t` so that + * on next entry due to SMC, the `smc_ctx_t` can be easily accessed. + */ + u_register_t sp_mon; + u_register_t lr_mon; + u_register_t scr; + u_register_t pmcr; + /* + * The workaround for CVE-2017-5715 requires storing information in + * the bottom 3 bits of the stack pointer. Add a padding field to + * force the size of the struct to be a multiple of 8. + */ + u_register_t pad; +} smc_ctx_t __aligned(8); + +/* + * Compile time assertions related to the 'smc_context' structure to + * ensure that the assembler and the compiler view of the offsets of + * the structure members is the same. + */ +CASSERT(SMC_CTX_GPREG_R0 == __builtin_offsetof(smc_ctx_t, r0), \ + assert_smc_ctx_greg_r0_offset_mismatch); +CASSERT(SMC_CTX_GPREG_R1 == __builtin_offsetof(smc_ctx_t, r1), \ + assert_smc_ctx_greg_r1_offset_mismatch); +CASSERT(SMC_CTX_GPREG_R2 == __builtin_offsetof(smc_ctx_t, r2), \ + assert_smc_ctx_greg_r2_offset_mismatch); +CASSERT(SMC_CTX_GPREG_R3 == __builtin_offsetof(smc_ctx_t, r3), \ + assert_smc_ctx_greg_r3_offset_mismatch); +CASSERT(SMC_CTX_GPREG_R4 == __builtin_offsetof(smc_ctx_t, r4), \ + assert_smc_ctx_greg_r4_offset_mismatch); +CASSERT(SMC_CTX_SP_USR == __builtin_offsetof(smc_ctx_t, sp_usr), \ + assert_smc_ctx_sp_usr_offset_mismatch); +CASSERT(SMC_CTX_LR_MON == __builtin_offsetof(smc_ctx_t, lr_mon), \ + assert_smc_ctx_lr_mon_offset_mismatch); +CASSERT(SMC_CTX_SPSR_MON == __builtin_offsetof(smc_ctx_t, spsr_mon), \ + assert_smc_ctx_spsr_mon_offset_mismatch); + +CASSERT((sizeof(smc_ctx_t) & 0x7U) == 0U, assert_smc_ctx_not_aligned); +CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch); + +/* Convenience macros to return from SMC handler */ +#define SMC_RET0(_h) { \ + return (uintptr_t)(_h); \ +} +#define SMC_RET1(_h, _r0) { \ + ((smc_ctx_t *)(_h))->r0 = (_r0); \ + SMC_RET0(_h); \ +} +#define SMC_RET2(_h, _r0, _r1) { \ + ((smc_ctx_t *)(_h))->r1 = (_r1); \ + SMC_RET1(_h, (_r0)); \ +} +#define SMC_RET3(_h, _r0, _r1, _r2) { \ + ((smc_ctx_t *)(_h))->r2 = (_r2); \ + SMC_RET2(_h, (_r0), (_r1)); \ +} +#define SMC_RET4(_h, _r0, _r1, _r2, _r3) { \ + ((smc_ctx_t *)(_h))->r3 = (_r3); \ + SMC_RET3(_h, (_r0), (_r1), (_r2)); \ +} +#define SMC_RET5(_h, _r0, _r1, _r2, _r3, _r4) { \ + ((smc_ctx_t *)(_h))->r4 = (_r4); \ + SMC_RET4(_h, (_r0), (_r1), (_r2), (_r3)); \ +} +#define SMC_RET6(_h, _r0, _r1, _r2, _r3, _r4, _r5) { \ + ((smc_ctx_t *)(_h))->r5 = (_r5); \ + SMC_RET5(_h, (_r0), (_r1), (_r2), (_r3), (_r4)); \ +} +#define SMC_RET7(_h, _r0, _r1, _r2, _r3, _r4, _r5, _r6) { \ + ((smc_ctx_t *)(_h))->r6 = (_r6); \ + SMC_RET6(_h, (_r0), (_r1), (_r2), (_r3), (_r4), (_r5)); \ +} +#define SMC_RET8(_h, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) { \ + ((smc_ctx_t *)(_h))->r7 = (_r7); \ + SMC_RET7(_h, (_r0), (_r1), (_r2), (_r3), (_r4), (_r5), (_r6)); \ +} + +/* + * Helper macro to retrieve the SMC parameters from smc_ctx_t. + */ +#define get_smc_params_from_ctx(_hdl, _r1, _r2, _r3, _r4) { \ + _r1 = ((smc_ctx_t *)_hdl)->r1; \ + _r2 = ((smc_ctx_t *)_hdl)->r2; \ + _r3 = ((smc_ctx_t *)_hdl)->r3; \ + _r4 = ((smc_ctx_t *)_hdl)->r4; \ + } + +/* ------------------------------------------------------------------------ + * Helper APIs for setting and retrieving appropriate `smc_ctx_t`. + * These functions need to implemented by the BL including this library. + * ------------------------------------------------------------------------ + */ + +/* Get the pointer to `smc_ctx_t` corresponding to the security state. */ +void *smc_get_ctx(unsigned int security_state); + +/* Set the next `smc_ctx_t` corresponding to the security state. */ +void smc_set_next_ctx(unsigned int security_state); + +/* Get the pointer to next `smc_ctx_t` already set by `smc_set_next_ctx()`. */ +void *smc_get_next_ctx(void); + +#endif /*__ASSEMBLER__*/ + +#endif /* SMCCC_HELPERS_H */ diff --git a/arm-trusted-firmware/include/arch/aarch32/smccc_macros.S b/arm-trusted-firmware/include/arch/aarch32/smccc_macros.S new file mode 100644 index 0000000..ea7835a --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/smccc_macros.S @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SMCCC_MACROS_S +#define SMCCC_MACROS_S + +#include + +/* + * Macro to save the General purpose registers (r0 - r12), the banked + * spsr, lr, sp registers and the `scr` register to the SMC context on entry + * due a SMC call. The `lr` of the current mode (monitor) is expected to be + * already saved. The `sp` must point to the `smc_ctx_t` to save to. + * Additionally, also save the 'pmcr' register as this is updated whilst + * executing in the secure world. + */ + .macro smccc_save_gp_mode_regs + /* Save r0 - r12 in the SMC context */ + stm sp, {r0-r12} + mov r0, sp + add r0, r0, #SMC_CTX_SP_USR + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* Must be in secure state to restore Monitor mode */ + ldcopr r4, SCR + bic r2, r4, #SCR_NS_BIT + stcopr r2, SCR + isb + + cps #MODE32_sys + stm r0!, {sp, lr} + + cps #MODE32_irq + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_fiq + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_svc + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_abt + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_und + mrs r2, spsr + stm r0!, {r2, sp, lr} + + /* lr_mon is already saved by caller */ + cps #MODE32_mon + mrs r2, spsr + stm r0!, {r2} + + stcopr r4, SCR +#else + /* Save the banked registers including the current SPSR and LR */ + mrs r4, sp_usr + mrs r5, lr_usr + mrs r6, spsr_irq + mrs r7, sp_irq + mrs r8, lr_irq + mrs r9, spsr_fiq + mrs r10, sp_fiq + mrs r11, lr_fiq + mrs r12, spsr_svc + stm r0!, {r4-r12} + + mrs r4, sp_svc + mrs r5, lr_svc + mrs r6, spsr_abt + mrs r7, sp_abt + mrs r8, lr_abt + mrs r9, spsr_und + mrs r10, sp_und + mrs r11, lr_und + mrs r12, spsr + stm r0!, {r4-r12} + /* lr_mon is already saved by caller */ + + ldcopr r4, SCR + +#if ARM_ARCH_MAJOR > 7 + /* + * Check if earlier initialization of SDCR.SCCD to 1 + * failed, meaning that ARMv8-PMU is not implemented, + * cycle counting is not disabled and PMCR should be + * saved in Non-secure context. + */ + ldcopr r5, SDCR + tst r5, #SDCR_SCCD_BIT + bne 1f +#endif + /* Secure Cycle Counter is not disabled */ +#endif + ldcopr r5, PMCR + + /* Check caller's security state */ + tst r4, #SCR_NS_BIT + beq 2f + + /* Save PMCR if called from Non-secure state */ + str r5, [sp, #SMC_CTX_PMCR] + + /* Disable cycle counter when event counting is prohibited */ +2: orr r5, r5, #PMCR_DP_BIT + stcopr r5, PMCR + isb +1: str r4, [sp, #SMC_CTX_SCR] + .endm + +/* + * Macro to restore the `smc_ctx_t`, which includes the General purpose + * registers and banked mode registers, and exit from the monitor mode. + * r0 must point to the `smc_ctx_t` to restore from. + */ + .macro monitor_exit + /* + * Save the current sp and restore the smc context + * pointer to sp which will be used for handling the + * next SMC. + */ + str sp, [r0, #SMC_CTX_SP_MON] + mov sp, r0 + + /* + * Restore SCR first so that we access the right banked register + * when the other mode registers are restored. + */ + ldr r1, [r0, #SMC_CTX_SCR] + stcopr r1, SCR + isb + + /* + * Restore PMCR when returning to Non-secure state + */ + tst r1, #SCR_NS_BIT + beq 2f + + /* + * Back to Non-secure state + */ +#if ARM_ARCH_MAJOR > 7 + /* + * Check if earlier initialization SDCR.SCCD to 1 + * failed, meaning that ARMv8-PMU is not implemented and + * PMCR should be restored from Non-secure context. + */ + ldcopr r1, SDCR + tst r1, #SDCR_SCCD_BIT + bne 2f +#endif + /* + * Restore the PMCR register. + */ + ldr r1, [r0, #SMC_CTX_PMCR] + stcopr r1, PMCR +2: + /* Restore the banked registers including the current SPSR */ + add r1, r0, #SMC_CTX_SP_USR + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* Must be in secure state to restore Monitor mode */ + ldcopr r4, SCR + bic r2, r4, #SCR_NS_BIT + stcopr r2, SCR + isb + + cps #MODE32_sys + ldm r1!, {sp, lr} + + cps #MODE32_irq + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_fiq + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_svc + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_abt + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_und + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_mon + ldm r1!, {r2} + msr spsr_fsxc, r2 + + stcopr r4, SCR + isb +#else + ldm r1!, {r4-r12} + msr sp_usr, r4 + msr lr_usr, r5 + msr spsr_irq, r6 + msr sp_irq, r7 + msr lr_irq, r8 + msr spsr_fiq, r9 + msr sp_fiq, r10 + msr lr_fiq, r11 + msr spsr_svc, r12 + + ldm r1!, {r4-r12} + msr sp_svc, r4 + msr lr_svc, r5 + msr spsr_abt, r6 + msr sp_abt, r7 + msr lr_abt, r8 + msr spsr_und, r9 + msr sp_und, r10 + msr lr_und, r11 + /* + * Use the `_fsxc` suffix explicitly to instruct the assembler + * to update all the 32 bits of SPSR. Else, by default, the + * assembler assumes `_fc` suffix which only modifies + * f->[31:24] and c->[7:0] bits of SPSR. + */ + msr spsr_fsxc, r12 +#endif + + /* Restore the LR */ + ldr lr, [r0, #SMC_CTX_LR_MON] + + /* Restore the rest of the general purpose registers */ + ldm r0, {r0-r12} + exception_return + .endm + +#endif /* SMCCC_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch64/arch.h b/arm-trusted-firmware/include/arch/aarch64/arch.h new file mode 100644 index 0000000..55b56d8 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/arch.h @@ -0,0 +1,1265 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, 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_SVE_LENGTH U(4) +#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) +#define ID_AA64PFR0_FEAT_RME_SHIFT U(52) +#define ID_AA64PFR0_FEAT_RME_MASK ULL(0xf) +#define ID_AA64PFR0_FEAT_RME_LENGTH U(4) +#define ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED U(0) +#define ID_AA64PFR0_FEAT_RME_V1 U(1) + +/* 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.TraceVer definitions */ +#define ID_AA64DFR0_TRACEVER_SHIFT U(4) +#define ID_AA64DFR0_TRACEVER_MASK ULL(0xf) +#define ID_AA64DFR0_TRACEVER_SUPPORTED ULL(1) +#define ID_AA64DFR0_TRACEVER_LENGTH U(4) +#define ID_AA64DFR0_TRACEFILT_SHIFT U(40) +#define ID_AA64DFR0_TRACEFILT_MASK U(0xf) +#define ID_AA64DFR0_TRACEFILT_SUPPORTED U(1) +#define ID_AA64DFR0_TRACEFILT_LENGTH U(4) + +/* 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.TraceBuffer definitions */ +#define ID_AA64DFR0_TRACEBUFFER_SHIFT U(44) +#define ID_AA64DFR0_TRACEBUFFER_MASK ULL(0xf) +#define ID_AA64DFR0_TRACEBUFFER_SUPPORTED ULL(1) + +/* 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) + +#define ID_AA64MMFR1_EL1_VHE_SHIFT U(8) +#define ID_AA64MMFR1_EL1_VHE_MASK ULL(0xf) + +#define ID_AA64MMFR1_EL1_HCX_SHIFT U(40) +#define ID_AA64MMFR1_EL1_HCX_MASK ULL(0xf) +#define ID_AA64MMFR1_EL1_HCX_SUPPORTED ULL(0x1) +#define ID_AA64MMFR1_EL1_HCX_NOT_SUPPORTED ULL(0x0) + +/* 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_CCIDX_SHIFT U(20) +#define ID_AA64MMFR2_EL1_CCIDX_MASK ULL(0xf) +#define ID_AA64MMFR2_EL1_CCIDX_LENGTH U(4) + +#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) + +#define ID_AA64PFR1_EL1_SME_SHIFT U(24) +#define ID_AA64PFR1_EL1_SME_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) +#define SCTLR_ENTP2_BIT (ULL(1) << 60) + +/* 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_SHIFT U(44) +#define SCTLR_DSSBS_BIT (ULL(1) << SCTLR_DSSBS_SHIFT) +#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_NSE_SHIFT U(62) +#define SCR_NSE_BIT (ULL(1) << SCR_NSE_SHIFT) +#define SCR_GPF_BIT (UL(1) << 48) +#define SCR_TWEDEL_SHIFT U(30) +#define SCR_TWEDEL_MASK ULL(0xf) +#define SCR_HXEn_BIT (UL(1) << 38) +#define SCR_ENTP2_SHIFT U(41) +#define SCR_ENTP2_BIT (UL(1) << SCR_ENTP2_SHIFT) +#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_EnSCXT_BIT (UL(1) << 25) +#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(0x24000002F8F) +#define SCR_RESET_VAL SCR_RES1_BITS + +/* MDCR_EL3 definitions */ +#define MDCR_EnPMSN_BIT (ULL(1) << 36) +#define MDCR_MPMX_BIT (ULL(1) << 35) +#define MDCR_MCCD_BIT (ULL(1) << 34) +#define MDCR_NSTB(x) ((x) << 24) +#define MDCR_NSTB_EL1 ULL(0x3) +#define MDCR_NSTBE (ULL(1) << 26) +#define MDCR_MTPME_BIT (ULL(1) << 28) +#define MDCR_TDCC_BIT (ULL(1) << 27) +#define MDCR_SCCD_BIT (ULL(1) << 23) +#define MDCR_EPMAD_BIT (ULL(1) << 21) +#define MDCR_EDAD_BIT (ULL(1) << 20) +#define MDCR_TTRF_BIT (ULL(1) << 19) +#define MDCR_STE_BIT (ULL(1) << 18) +#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_E2TB(x) ((x) << 24) +#define MDCR_EL2_E2TB_EL1 U(0x3) +#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_RESET_VAL ULL(0x0) +#define HCR_AMVOFFEN_SHIFT U(51) +#define HCR_AMVOFFEN_BIT (ULL(1) << HCR_AMVOFFEN_SHIFT) +#define HCR_TEA_BIT (ULL(1) << 47) +#define HCR_API_BIT (ULL(1) << 41) +#define HCR_APK_BIT (ULL(1) << 40) +#define HCR_E2H_BIT (ULL(1) << 34) +#define HCR_HCD_BIT (ULL(1) << 29) +#define HCR_TGE_BIT (ULL(1) << 27) +#define HCR_RW_SHIFT U(31) +#define HCR_RW_BIT (ULL(1) << HCR_RW_SHIFT) +#define HCR_TWE_BIT (ULL(1) << 14) +#define HCR_TWI_BIT (ULL(1) << 13) +#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_SHIFT U(30) +#define TAM_BIT (U(1) << TAM_SHIFT) +#define TTA_BIT (U(1) << 20) +#define ESM_BIT (U(1) << 12) +#define TFP_BIT (U(1) << 10) +#define CPTR_EZ_BIT (U(1) << 8) +#define CPTR_EL3_RESET_VAL ((TCPAC_BIT | TAM_BIT | TTA_BIT | TFP_BIT) & \ + ~(CPTR_EZ_BIT | ESM_BIT)) + +/* 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_SHIFT U(30) +#define CPTR_EL2_TAM_BIT (U(1) << CPTR_EL2_TAM_SHIFT) +#define CPTR_EL2_SMEN_MASK ULL(0x3) +#define CPTR_EL2_SMEN_SHIFT U(24) +#define CPTR_EL2_TTA_BIT (U(1) << 20) +#define CPTR_EL2_TSM_BIT (U(1) << 12) +#define CPTR_EL2_TFP_BIT (U(1) << 10) +#define CPTR_EL2_TZ_BIT (U(1) << 8) +#define CPTR_EL2_RESET_VAL CPTR_EL2_RES1 + +/* VTCR_EL2 definitions */ +#define VTCR_RESET_VAL U(0x0) +#define VTCR_EL2_MSA (U(1) << 31) + +/* 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_M_EL2H U(0x9) + +#define SPSR_EL_SHIFT U(2) +#define SPSR_EL_WIDTH U(2) + +#define SPSR_SSBS_SHIFT_AARCH64 U(12) +#define SPSR_SSBS_BIT_AARCH64 (ULL(1) << SPSR_SSBS_SHIFT_AARCH64) +#define SPSR_SSBS_SHIFT_AARCH32 U(23) +#define SPSR_SSBS_BIT_AARCH32 (ULL(1) << SPSR_SSBS_SHIFT_AARCH32) + +#define SPSR_PAN_BIT BIT_64(22) + +#define SPSR_DIT_BIT BIT(24) + +#define SPSR_TCO_BIT_AARCH64 BIT_64(25) + +#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 for system register interface to SME as needed in EL3 + ******************************************************************************/ +#define ID_AA64SMFR0_EL1 S3_0_C0_C4_5 +#define SMCR_EL3 S3_6_C1_C2_6 + +/* ID_AA64SMFR0_EL1 definitions */ +#define ID_AA64SMFR0_EL1_FA64_BIT (UL(1) << 63) + +/* SMCR_ELx definitions */ +#define SMCR_ELX_LEN_SHIFT U(0) +#define SMCR_ELX_LEN_MASK U(0x1ff) +#define SMCR_ELX_FA64_BIT (U(1) << 31) + +/******************************************************************************* + * 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 + +/* AMCNTENSET0_EL0 definitions */ +#define AMCNTENSET0_EL0_Pn_SHIFT U(0) +#define AMCNTENSET0_EL0_Pn_MASK ULL(0xffff) + +/* AMCNTENSET1_EL0 definitions */ +#define AMCNTENSET1_EL0_Pn_SHIFT U(0) +#define AMCNTENSET1_EL0_Pn_MASK ULL(0xffff) + +/* AMCNTENCLR0_EL0 definitions */ +#define AMCNTENCLR0_EL0_Pn_SHIFT U(0) +#define AMCNTENCLR0_EL0_Pn_MASK ULL(0xffff) + +/* AMCNTENCLR1_EL0 definitions */ +#define AMCNTENCLR1_EL0_Pn_SHIFT U(0) +#define AMCNTENCLR1_EL0_Pn_MASK ULL(0xffff) + +/* 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_CG0NC_SHIFT U(0) +#define AMCGCR_EL0_CG0NC_MASK U(0xff) +#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_SHIFT U(17) +#define AMCR_CG1RZ_BIT (ULL(0x1) << AMCR_CG1RZ_SHIFT) + +/* + * 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 + +/******************************************************************************* + * Realm management extension register definitions + ******************************************************************************/ +#define GPCCR_EL3 S3_6_C2_C1_6 +#define GPTBR_EL3 S3_6_C2_C1_4 + +/******************************************************************************* + * 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 + +/******************************************************************************* + * FEAT_HCX - Extended Hypervisor Configuration Register + ******************************************************************************/ +#define HCRX_EL2 S3_4_C1_C2_2 +#define HCRX_EL2_FGTnXS_BIT (UL(1) << 4) +#define HCRX_EL2_FnXS_BIT (UL(1) << 3) +#define HCRX_EL2_EnASR_BIT (UL(1) << 2) +#define HCRX_EL2_EnALS_BIT (UL(1) << 1) +#define HCRX_EL2_EnAS0_BIT (UL(1) << 0) + +/******************************************************************************* + * Definitions for DynamicIQ Shared Unit registers + ******************************************************************************/ +#define CLUSTERECTLR_EL1 S3_0_C15_C3_4 +#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) + +/* CLUSTERECTLR_EL1 register definitions */ +#define DSU_NC_CTRL_BIT BIT(0) +#define DSU_WRITEEVICT_BIT BIT(14) + +/******************************************************************************* + * Definitions for CPU Power/Performance Management registers + ******************************************************************************/ + +#define CPUPPMCR_EL3 S3_6_C15_C2_0 +#define CPUPPMCR_EL3_MPMMPINCTL_SHIFT UINT64_C(0) +#define CPUPPMCR_EL3_MPMMPINCTL_MASK UINT64_C(0x1) + +#define CPUMPMMCR_EL3 S3_6_C15_C2_1 +#define CPUMPMMCR_EL3_MPMM_EN_SHIFT UINT64_C(0) +#define CPUMPMMCR_EL3_MPMM_EN_MASK UINT64_C(0x1) + +#endif /* ARCH_H */ diff --git a/arm-trusted-firmware/include/arch/aarch64/arch_features.h b/arm-trusted-firmware/include/arch/aarch64/arch_features.h new file mode 100644 index 0000000..a260f03 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/arch_features.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2019-2022, 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_1_pan_present(void) +{ + return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_PAN_SHIFT) & + ID_AA64MMFR1_EL1_PAN_MASK) != 0U; +} + +static inline bool is_armv8_1_vhe_present(void) +{ + return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_VHE_SHIFT) & + ID_AA64MMFR1_EL1_VHE_MASK) != 0U; +} + +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_dit_present(void) +{ + return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) & + ID_AA64PFR0_DIT_MASK) == 1U; +} + +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)); +} + +static inline bool is_feat_hcx_present(void) +{ + return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_HCX_SHIFT) & + ID_AA64MMFR1_EL1_HCX_MASK) == ID_AA64MMFR1_EL1_HCX_SUPPORTED); +} + +static inline unsigned int get_armv9_2_feat_rme_support(void) +{ + /* + * Return the RME version, zero if not supported. This function can be + * used as both an integer value for the RME version or compared to zero + * to detect RME presence. + */ + return (unsigned int)(read_id_aa64pfr0_el1() >> + ID_AA64PFR0_FEAT_RME_SHIFT) & ID_AA64PFR0_FEAT_RME_MASK; +} + +#endif /* ARCH_FEATURES_H */ diff --git a/arm-trusted-firmware/include/arch/aarch64/arch_helpers.h b/arm-trusted-firmware/include/arch/aarch64/arch_helpers.h new file mode 100644 index 0000000..7ce86df --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/arch_helpers.h @@ -0,0 +1,671 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. 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 flush_dcache_to_popa_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_mpu_el2(void); +void disable_mmu_icache_el1(void); +void disable_mmu_icache_el3(void); +void disable_mpu_icache_el2(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, osh) +DEFINE_SYSOP_TYPE_FUNC(dsb, nsh) +DEFINE_SYSOP_TYPE_FUNC(dsb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dsb, oshst) +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_SYSREG_RW_FUNCS(vtcr_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(id_aa64smfr0_el1, ID_AA64SMFR0_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(smcr_el3, SMCR_EL3) + +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.4 Data Independent Timing Register */ +DEFINE_RENAME_SYSREG_RW_FUNCS(dit, DIT) + +/* 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) + +/* FEAT_HCX Register */ +DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2) + +/* DynamIQ Shared Unit registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(clusterectlr_el1, CLUSTERECTLR_EL1) + +/* DynamIQ Shared Unit power management */ +DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1) + +/* CPU Power/Performance Management registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(cpuppmcr_el3, CPUPPMCR_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(cpumpmmcr_el3, CPUMPMMCR_EL3) + +/* Armv9.2 RME Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3) + +#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; + } +} + +/* + * TLBIPAALLOS instruction + * (TLB Inivalidate GPT Information by PA, + * All Entries, Outer Shareable) + */ +static inline void tlbipaallos(void) +{ + __asm__("SYS #6,c8,c1,#4"); +} + +/* + * Invalidate TLBs of GPT entries by Physical address, last level. + * + * @pa: the starting address for the range + * of invalidation + * @size: size of the range of invalidation + */ +void gpt_tlbi_by_pa_ll(uint64_t pa, size_t size); + + +/* Previously defined accessor 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/arm-trusted-firmware/include/arch/aarch64/asm_macros.S b/arm-trusted-firmware/include/arch/aarch64/asm_macros.S new file mode 100644 index 0000000..7706cd8 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/asm_macros.S @@ -0,0 +1,231 @@ +/* + * 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 + +/* + * 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/arm-trusted-firmware/include/arch/aarch64/assert_macros.S b/arm-trusted-firmware/include/arch/aarch64/assert_macros.S new file mode 100644 index 0000000..06371c4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/arch/aarch64/console_macros.S b/arm-trusted-firmware/include/arch/aarch64/console_macros.S new file mode 100644 index 0000000..3285d85 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S b/arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S new file mode 100644 index 0000000..7bf4806 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EL2_COMMON_MACROS_S +#define EL2_COMMON_MACROS_S + +#include +#include +#include +#include + +#include + + /* + * Helper macro to initialise system registers at EL2. + */ + .macro el2_arch_init_common + + /* --------------------------------------------------------------------- + * SCTLR_EL2 has already been initialised - read current value before + * modifying. + * + * SCTLR_EL2.I: Enable the instruction cache. + * + * SCTLR_EL2.SA: Enable Stack Alignment check. A SP alignment fault + * exception is generated if a load or store instruction executed at + * EL2 uses the SP as the base address and the SP is not aligned to a + * 16-byte boundary. + * + * SCTLR_EL2.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_el2 + orr x0, x0, x1 + msr sctlr_el2, x0 + isb + + /* --------------------------------------------------------------------- + * Initialise HCR_EL2, 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(). + * + * HCR_EL2.TWE: Set to zero so that execution of WFE instructions at + * EL2, EL1 and EL0 are not trapped to EL2. + * + * HCR_EL2.TWI: Set to zero so that execution of WFI instructions at + * EL2, EL1 and EL0 are not trapped to EL2. + * + * HCR_EL2.HCD: Set to zero to enable HVC calls at EL1 and above, + * from both Security states and both Execution states. + * + * HCR_EL2.TEA: Set to one to route External Aborts and SError + * Interrupts to EL2 when executing at any EL. + * + * HCR_EL2.{API,APK}: For Armv8.3 pointer authentication feature, + * disable traps to EL2 when accessing key registers or using + * pointer authentication instructions from lower ELs. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((HCR_RESET_VAL | HCR_TEA_BIT) \ + & ~(HCR_TWE_BIT | HCR_TWI_BIT | HCR_HCD_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, #(HCR_API_BIT | HCR_APK_BIT) +#endif /* CTX_INCLUDE_PAUTH_REGS */ + msr hcr_el2, x0 + + /* --------------------------------------------------------------------- + * Initialise MDCR_EL2, setting all fields rather than relying on + * hw. Some fields are architecturally UNKNOWN on reset. + * + * MDCR_EL2.TDOSA: Set to zero so that EL2 and EL2 System register + * access to the powerdown debug registers do not trap to EL2. + * + * MDCR_EL2.TDA: Set to zero to allow EL0, EL1 and EL2 access to the + * debug registers, other than those registers that are controlled by + * MDCR_EL2.TDOSA. + * + * MDCR_EL2.TPM: Set to zero so that EL0, EL1, and EL2 System + * register accesses to all Performance Monitors registers do not trap + * to EL2. + * + * MDCR_EL2.HPMD: Set to zero so that event counting by the program- + * mable 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_EL2_RESET_VAL | \ + MDCR_SPD32(MDCR_SPD32_DISABLE)) \ + & ~(MDCR_EL2_HPMD | MDCR_TDOSA_BIT | \ + MDCR_TDA_BIT | MDCR_TPM_BIT)) + + msr mdcr_el2, x0 + + /* --------------------------------------------------------------------- + * Initialise PMCR_EL0 setting all fields rather than relying + * on hw. Some fields are architecturally UNKNOWN on reset. + * + * 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_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_EL2, setting all fields rather than relying on hw. + * All fields are architecturally UNKNOWN on reset. + * + * CPTR_EL2.TCPAC: Set to zero so that any accesses to CPACR_EL1 do + * not trap to EL2. + * + * CPTR_EL2.TTA: Set to zero so that System register accesses to the + * trace registers do not trap to EL2. + * + * CPTR_EL2.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 EL2. + */ + + mov_imm x0, (CPTR_EL2_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT)) + msr cptr_el2, x0 + + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL2 + */ + 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 EL2. 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_EL2, 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_EL2 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 el2_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_EL2 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_EL2.WXN: For the EL2 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_EL2.SA: Set to zero to disable Stack Alignment check. + * + * SCTLR_EL2.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 EL2. + * ------------------------------------------------------------- + */ + mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \ + | SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT)) + msr sctlr_el2, 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_el2, x0 + isb + + /* --------------------------------------------------------------------- + * It is a cold boot. + * Perform any processor specific actions upon reset e.g. cache, TLB + * invalidations etc. + * --------------------------------------------------------------------- + */ + bl reset_handler + + el2_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 el2_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 + 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 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 /* EL2_COMMON_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S b/arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S new file mode 100644 index 0000000..de2b931 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S @@ -0,0 +1,570 @@ +/* + * Copyright (c) 2015-2022, 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 +#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 +#if ENABLE_RME + /* + * TODO: Settting the EEL2 bit to allow EL3 access to secure only registers + * in context management. This will need to be refactored. + */ + orr x0, x0, #SCR_EEL2_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 with FEAT_PMUv3p5 not implemented, setting it to 1 + * doesn't have any effect on them. + * + * MDCR_EL3.MCCD: Set to one so that cycle counting by PMCCNTR_EL0 is + * prohibited in EL3. This bit is RES0 in versions of the + * architecture with FEAT_PMUv3p7 not implemented, 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(). + * + * MDCR_EL3.NSTB, MDCR_EL3.NSTBE: Set to zero so that Trace Buffer + * owning security state is Secure state. If FEAT_TRBE is implemented, + * accesses to Trace Buffer control registers at EL2 and EL1 in any + * security state generates trap exceptions to EL3. + * If FEAT_TRBE is not implemented, these bits are RES0. + * + * MDCR_EL3.TTRF: Set to one so that access to trace filter control + * registers in non-monitor mode generate EL3 trap exception, + * unless the access generates a higher priority exception when trace + * filter control(FEAT_TRF) is implemented. + * When FEAT_TRF is not implemented, this bit is RES0. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((MDCR_EL3_RESET_VAL | MDCR_SDD_BIT | \ + MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT | \ + MDCR_MCCD_BIT) & ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | \ + MDCR_TDA_BIT | MDCR_TPM_BIT | MDCR_NSTB(MDCR_NSTB_EL1) | \ + MDCR_NSTBE | MDCR_TTRF_BIT)) + + mrs x1, id_aa64dfr0_el1 + ubfx x1, x1, #ID_AA64DFR0_TRACEFILT_SHIFT, #ID_AA64DFR0_TRACEFILT_LENGTH + cbz x1, 1f + orr x0, x0, #MDCR_TTRF_BIT +1: + 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 one so that accesses to the trace system + * registers trap to EL3 from all exception levels and security + * states when system register trace is implemented. + * When system register trace is not implemented, this bit is RES0 and + * hence set to zero. + * + * 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. + * + * CPTR_EL3.TAM: Set to one so that Activity Monitor access is + * trapped to EL3 by default. + * + * CPTR_EL3.EZ: Set to zero so that all SVE functionality is trapped + * to EL3 by default. + * + * CPTR_EL3.ESM: Set to zero so that all SME functionality is trapped + * to EL3 by default. + */ + + mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT)) + mrs x1, id_aa64dfr0_el1 + ubfx x1, x1, #ID_AA64DFR0_TRACEVER_SHIFT, #ID_AA64DFR0_TRACEVER_LENGTH + cbz x1, 1f + orr x0, x0, #TTA_BIT +1: + msr cptr_el3, x0 + + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL3. + * First assert that the FEAT_DIT build flag matches the feature id + * register value for DIT. + */ +#if ENABLE_FEAT_DIT +#if ENABLE_ASSERTIONS + mrs x0, id_aa64pfr0_el1 + ubfx x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH + cmp x0, #ID_AA64PFR0_DIT_SUPPORTED + ASM_ASSERT(eq) +#endif /* ENABLE_ASSERTIONS */ + mov x0, #DIT_BIT + msr DIT, x0 +#endif + .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 + +#if !(defined(IMAGE_BL2) && ENABLE_RME) + /* --------------------------------------------------------------------- + * It is a cold boot. + * Perform any processor specific actions upon reset e.g. cache, TLB + * invalidations etc. + * --------------------------------------------------------------------- + */ + bl reset_handler +#endif + + 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) || ENABLE_RME)) + /* ------------------------------------------------------------- + * 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. If PIE is enabled however, + * RO sections including the GOT may be modified during + * pie fixup. Therefore, to be on the safe side, invalidate + * the entire image region if PIE is enabled. + * ------------------------------------------------------------- + */ +#if ENABLE_PIE +#if SEPARATE_CODE_AND_RODATA + adrp x0, __TEXT_START__ + add x0, x0, :lo12:__TEXT_START__ +#else + adrp x0, __RO_START__ + add x0, x0, :lo12:__RO_START__ +#endif /* SEPARATE_CODE_AND_RODATA */ +#else + adrp x0, __RW_START__ + add x0, x0, :lo12:__RW_START__ +#endif /* ENABLE_PIE */ + 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 +#if defined(IMAGE_BL2) && SEPARATE_BL2_NOLOAD_REGION + adrp x0, __BL2_NOLOAD_START__ + add x0, x0, :lo12:__BL2_NOLOAD_START__ + adrp x1, __BL2_NOLOAD_END__ + add x1, x1, :lo12:__BL2_NOLOAD_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/arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h b/arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h new file mode 100644 index 0000000..fac6fd9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/bl1/bl1.h b/arm-trusted-firmware/include/bl1/bl1.h new file mode 100644 index 0000000..21d3ae7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h b/arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h new file mode 100644 index 0000000..db15cdb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/bl2/bl2.h b/arm-trusted-firmware/include/bl2/bl2.h new file mode 100644 index 0000000..73f5ac7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/bl2u/bl2u.h b/arm-trusted-firmware/include/bl2u/bl2u.h new file mode 100644 index 0000000..387eaf8 --- /dev/null +++ b/arm-trusted-firmware/include/bl2u/bl2u.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL2U_H +#define BL2U_H + +void bl2u_main(void); + +#endif /* BL2U_H */ diff --git a/arm-trusted-firmware/include/bl31/bl31.h b/arm-trusted-firmware/include/bl31/bl31.h new file mode 100644 index 0000000..1d58ef9 --- /dev/null +++ b/arm-trusted-firmware/include/bl31/bl31.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013-2021, 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_register_rmm_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/arm-trusted-firmware/include/bl31/ea_handle.h b/arm-trusted-firmware/include/bl31/ea_handle.h new file mode 100644 index 0000000..68f012c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/bl31/ehf.h b/arm-trusted-firmware/include/bl31/ehf.h new file mode 100644 index 0000000..c13d28c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/bl31/interrupt_mgmt.h b/arm-trusted-firmware/include/bl31/interrupt_mgmt.h new file mode 100644 index 0000000..935bf77 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/bl32/payloads/tlk.h b/arm-trusted-firmware/include/bl32/payloads/tlk.h new file mode 100644 index 0000000..290f329 --- /dev/null +++ b/arm-trusted-firmware/include/bl32/payloads/tlk.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TLK_H +#define TLK_H + +#include + +/* + * Generate function IDs for the Trusted OS/Apps + */ +#define TLK_TOS_YIELD_FID(fid) ((fid) | 0x72000000 | (0 << 31)) +#define TLK_TA_YIELD_FID(fid) ((fid) | 0x70000000 | (0 << 31)) + +/* + * Trusted OS specific function IDs + */ +#define TLK_REGISTER_LOGBUF TLK_TOS_YIELD_FID(0x1) +#define TLK_REGISTER_REQBUF TLK_TOS_YIELD_FID(0x2) +#define TLK_SS_REGISTER_HANDLER TLK_TOS_YIELD_FID(0x3) +#define TLK_REGISTER_NS_DRAM_RANGES TLK_TOS_YIELD_FID(0x4) +#define TLK_SET_ROOT_OF_TRUST TLK_TOS_YIELD_FID(0x5) +#define TLK_SET_BL_VERSION TLK_TOS_YIELD_FID(0x6) +#define TLK_LOCK_BL_INTERFACE TLK_TOS_YIELD_FID(0x7) +#define TLK_BL_RPMB_SERVICE TLK_TOS_YIELD_FID(0x8) +#define TLK_RESUME_FID TLK_TOS_YIELD_FID(0x100) +#define TLK_SYSTEM_SUSPEND TLK_TOS_YIELD_FID(0xE001) +#define TLK_SYSTEM_RESUME TLK_TOS_YIELD_FID(0xE002) +#define TLK_IRQ_FIRED TLK_TOS_YIELD_FID(0xE004) + +/* + * SMC function IDs that TLK uses to signal various forms of completions + * to the secure payload dispatcher. + */ +#define TLK_REQUEST_DONE (0x32000001 | (ULL(1) << 31)) +#define TLK_PREEMPTED (0x32000002 | (ULL(1) << 31)) +#define TLK_ENTRY_DONE (0x32000003 | (ULL(1) << 31)) +#define TLK_VA_TRANSLATE (0x32000004 | (ULL(1) << 31)) +#define TLK_SUSPEND_DONE (0x32000005 | (ULL(1) << 31)) +#define TLK_RESUME_DONE (0x32000006 | (ULL(1) << 31)) +#define TLK_IRQ_DONE (0x32000008 | (ULL(1) << 31)) + +/* + * Trusted Application specific function IDs + */ +#define TLK_OPEN_TA_SESSION TLK_TA_YIELD_FID(0x1) +#define TLK_CLOSE_TA_SESSION TLK_TA_YIELD_FID(0x2) +#define TLK_TA_LAUNCH_OP TLK_TA_YIELD_FID(0x3) +#define TLK_TA_SEND_EVENT TLK_TA_YIELD_FID(0x4) + +/* + * Total number of function IDs implemented for services offered to NS clients. + */ +#define TLK_NUM_FID 7 + +/* TLK implementation version numbers */ +#define TLK_VERSION_MAJOR 0x0 /* Major version */ +#define TLK_VERSION_MINOR 0x1 /* Minor version */ + +/* + * Standard Trusted OS Function IDs that fall under Trusted OS call range + * according to SMC calling convention + */ +#define TOS_CALL_COUNT 0xbf00ff00 /* Number of calls implemented */ +#define TOS_UID 0xbf00ff01 /* Implementation UID */ +#define TOS_CALL_VERSION 0xbf00ff03 /* Trusted OS Call Version */ + +#endif /* TLK_H */ diff --git a/arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h b/arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h new file mode 100644 index 0000000..971f661 --- /dev/null +++ b/arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_SP_MIN_H +#define PLATFORM_SP_MIN_H + +#include + +/******************************************************************************* + * Mandatory SP_MIN functions + ******************************************************************************/ +void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); +void sp_min_platform_setup(void); +void sp_min_plat_runtime_setup(void); +void sp_min_plat_arch_setup(void); +entry_point_info_t *sp_min_plat_get_bl33_ep_info(void); +void sp_min_warm_entrypoint(void); + +/* Platforms that enable SP_MIN_WITH_SECURE_FIQ shall implement this api */ +void sp_min_plat_fiq_handler(uint32_t id); + +#endif /* PLATFORM_SP_MIN_H */ diff --git a/arm-trusted-firmware/include/bl32/tsp/platform_tsp.h b/arm-trusted-firmware/include/bl32/tsp/platform_tsp.h new file mode 100644 index 0000000..fe8a2c9 --- /dev/null +++ b/arm-trusted-firmware/include/bl32/tsp/platform_tsp.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_TSP_H +#define PLATFORM_TSP_H + +/******************************************************************************* + * Mandatory TSP functions (only if platform contains a TSP) + ******************************************************************************/ +void tsp_early_platform_setup(void); +void tsp_plat_arch_setup(void); +void tsp_platform_setup(void); + +#endif /* PLATFORM_TSP_H */ diff --git a/arm-trusted-firmware/include/bl32/tsp/tsp.h b/arm-trusted-firmware/include/bl32/tsp/tsp.h new file mode 100644 index 0000000..285bfbe --- /dev/null +++ b/arm-trusted-firmware/include/bl32/tsp/tsp.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TSP_H +#define TSP_H + +/* + * SMC function IDs that TSP uses to signal various forms of completions + * to the secure payload dispatcher. + */ +#define TSP_ENTRY_DONE 0xf2000000 +#define TSP_ON_DONE 0xf2000001 +#define TSP_OFF_DONE 0xf2000002 +#define TSP_SUSPEND_DONE 0xf2000003 +#define TSP_RESUME_DONE 0xf2000004 +#define TSP_PREEMPTED 0xf2000005 +#define TSP_ABORT_DONE 0xf2000007 +#define TSP_SYSTEM_OFF_DONE 0xf2000008 +#define TSP_SYSTEM_RESET_DONE 0xf2000009 + +/* + * Function identifiers to handle S-EL1 interrupt through the synchronous + * handling model. If the TSP was previously interrupted then control has to + * be returned to the TSPD after handling the interrupt else execution can + * remain in the TSP. + */ +#define TSP_HANDLED_S_EL1_INTR 0xf2000006 + +/* SMC function ID that TSP uses to request service from secure monitor */ +#define TSP_GET_ARGS 0xf2001000 + +/* + * Identifiers for various TSP services. Corresponding function IDs (whether + * fast or yielding) are generated by macros defined below + */ +#define TSP_ADD 0x2000 +#define TSP_SUB 0x2001 +#define TSP_MUL 0x2002 +#define TSP_DIV 0x2003 +#define TSP_HANDLE_SEL1_INTR_AND_RETURN 0x2004 +#define TSP_CHECK_DIT 0x2005 + +/* + * Identify a TSP service from function ID filtering the last 16 bits from the + * SMC function ID + */ +#define TSP_BARE_FID(fid) ((fid) & 0xffff) + +/* + * Generate function IDs for TSP services to be used in SMC calls, by + * appropriately setting bit 31 to differentiate yielding and fast SMC calls + */ +#define TSP_YIELD_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000)) +#define TSP_FAST_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000) | (1u << 31)) + +/* SMC function ID to request a previously preempted yielding smc */ +#define TSP_FID_RESUME TSP_YIELD_FID(0x3000) +/* + * SMC function ID to request abortion of a previously preempted yielding SMC. A + * fast SMC is used so that the TSP abort handler does not have to be + * reentrant. + */ +#define TSP_FID_ABORT TSP_FAST_FID(0x3001) + +/* + * Total number of function IDs implemented for services offered to NS clients. + * The function IDs are defined above + */ +#define TSP_NUM_FID 0x5 + +/* TSP implementation version numbers */ +#define TSP_VERSION_MAJOR 0x0 /* Major version */ +#define TSP_VERSION_MINOR 0x1 /* Minor version */ + +/* + * Standard Trusted OS Function IDs that fall under Trusted OS call range + * according to SMC calling convention + */ +#define TOS_CALL_COUNT 0xbf00ff00 /* Number of calls implemented */ +#define TOS_UID 0xbf00ff01 /* Implementation UID */ +/* 0xbf00ff02 is reserved */ +#define TOS_CALL_VERSION 0xbf00ff03 /* Trusted OS Call Version */ + + +#ifndef __ASSEMBLER__ + +#include + + +typedef uint32_t tsp_vector_isn_t; + +typedef struct tsp_vectors { + tsp_vector_isn_t yield_smc_entry; + tsp_vector_isn_t fast_smc_entry; + tsp_vector_isn_t cpu_on_entry; + tsp_vector_isn_t cpu_off_entry; + tsp_vector_isn_t cpu_resume_entry; + tsp_vector_isn_t cpu_suspend_entry; + tsp_vector_isn_t sel1_intr_entry; + tsp_vector_isn_t system_off_entry; + tsp_vector_isn_t system_reset_entry; + tsp_vector_isn_t abort_yield_smc_entry; +} tsp_vectors_t; + +void tsp_setup(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* TSP_H */ diff --git a/arm-trusted-firmware/include/common/asm_macros_common.S b/arm-trusted-firmware/include/common/asm_macros_common.S new file mode 100644 index 0000000..fd0ea81 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/bl_common.h b/arm-trusted-firmware/include/common/bl_common.h new file mode 100644 index 0000000..8cb4990 --- /dev/null +++ b/arm-trusted-firmware/include/common/bl_common.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2013-2021, 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 +#if SEPARATE_NOBITS_REGION +IMPORT_SYM(uintptr_t, __NOBITS_START__, BL_NOBITS_BASE); +IMPORT_SYM(uintptr_t, __NOBITS_END__, BL_NOBITS_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); +#elif defined(IMAGE_RMM) +IMPORT_SYM(uintptr_t, __RMM_END__, RMM_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/arm-trusted-firmware/include/common/bl_common.ld.h b/arm-trusted-firmware/include/common/bl_common.ld.h new file mode 100644 index 0000000..5147e37 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/debug.h b/arm-trusted-firmware/include/common/debug.h new file mode 100644 index 0000000..a7ca0d7 --- /dev/null +++ b/arm-trusted-firmware/include/common/debug.h @@ -0,0 +1,118 @@ +/* + * 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__) +# define ERROR_NL() tf_log_newline(LOG_MARKER_ERROR) +#else +# define ERROR(...) no_tf_log(LOG_MARKER_ERROR __VA_ARGS__) +# define ERROR_NL() +#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_newline(const char log_fmt[2]); +void tf_log_set_max_level(unsigned int log_level); + +#endif /* __ASSEMBLER__ */ +#endif /* DEBUG_H */ diff --git a/arm-trusted-firmware/include/common/desc_image_load.h b/arm-trusted-firmware/include/common/desc_image_load.h new file mode 100644 index 0000000..b044f3e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/ep_info.h b/arm-trusted-firmware/include/common/ep_info.h new file mode 100644 index 0000000..771572c --- /dev/null +++ b/arm-trusted-firmware/include/common/ep_info.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017-2021, 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 REALM EP_REALM +#if ENABLE_RME +#define sec_state_is_valid(s) (((s) == SECURE) || \ + ((s) == NON_SECURE) || \ + ((s) == REALM)) +#else +#define sec_state_is_valid(s) (((s) == SECURE) || ((s) == NON_SECURE)) +#endif + +#define PARAM_EP_SECURITY_MASK EP_SECURITY_MASK + +#define NON_EXECUTABLE EP_NON_EXECUTABLE +#define EXECUTABLE EP_EXECUTABLE + +/* Get/set security state of an 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/arm-trusted-firmware/include/common/fdt_fixup.h b/arm-trusted-firmware/include/common/fdt_fixup.h new file mode 100644 index 0000000..7a590b2 --- /dev/null +++ b/arm-trusted-firmware/include/common/fdt_fixup.h @@ -0,0 +1,21 @@ +/* + * 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 + +#define INVALID_BASE_ADDR ((uintptr_t)~0UL) + +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, uintptr_t gicr_base, + unsigned int gicr_frame_size); + +#endif /* FDT_FIXUP_H */ diff --git a/arm-trusted-firmware/include/common/fdt_wrappers.h b/arm-trusted-firmware/include/common/fdt_wrappers.h new file mode 100644 index 0000000..9c7180c --- /dev/null +++ b/arm-trusted-firmware/include/common/fdt_wrappers.h @@ -0,0 +1,59 @@ +/* + * 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); + +int fdtw_for_each_cpu(const void *fdt, + int (*callback)(const void *dtb, int node, uintptr_t mpidr)); + +static inline uint32_t fdt_blob_size(const void *dtb) +{ + const uint32_t *dtb_header = dtb; + + return fdt32_to_cpu(dtb_header[1]); +} + +#define fdt_for_each_compatible_node(dtb, node, compatible_str) \ +for (node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); \ + node >= 0; \ + node = fdt_node_offset_by_compatible(dtb, node, compatible_str)) + +#endif /* FDT_WRAPPERS_H */ diff --git a/arm-trusted-firmware/include/common/image_decompress.h b/arm-trusted-firmware/include/common/image_decompress.h new file mode 100644 index 0000000..bb35c3b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/interrupt_props.h b/arm-trusted-firmware/include/common/interrupt_props.h new file mode 100644 index 0000000..07bafaa --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/nv_cntr_ids.h b/arm-trusted-firmware/include/common/nv_cntr_ids.h new file mode 100644 index 0000000..a15c431 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/param_header.h b/arm-trusted-firmware/include/common/param_header.h new file mode 100644 index 0000000..4dab4e3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/romlib.h b/arm-trusted-firmware/include/common/romlib.h new file mode 100644 index 0000000..7f53c47 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/runtime_svc.h b/arm-trusted-firmware/include/common/runtime_svc.h new file mode 100644 index 0000000..472a32a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/tbbr/cot_def.h b/arm-trusted-firmware/include/common/tbbr/cot_def.h new file mode 100644 index 0000000..800ad07 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h b/arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h new file mode 100644 index 0000000..e1c8c29 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/common/tf_crc32.h b/arm-trusted-firmware/include/common/tf_crc32.h new file mode 100644 index 0000000..38c56a5 --- /dev/null +++ b/arm-trusted-firmware/include/common/tf_crc32.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TF_CRC32_H +#define TF_CRC32_H + +#include +#include + +/* compute CRC using Arm intrinsic function */ +uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size); + +#endif /* TF_CRC32_H */ diff --git a/arm-trusted-firmware/include/common/uuid.h b/arm-trusted-firmware/include/common/uuid.h new file mode 100644 index 0000000..5651d0d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/allwinner/axp.h b/arm-trusted-firmware/include/drivers/allwinner/axp.h new file mode 100644 index 0000000..8b90c7f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/allwinner/axp.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AXP_H +#define AXP_H + +#include + +#define AXP20X_MODE_REG 0x3e +#define AXP20X_MODE_I2C 0x00 +#define AXP20X_MODE_RSB 0x7c + +#define NA 0xff + +enum { + AXP803_CHIP_ID = 0x41, + AXP805_CHIP_ID = 0x40, +}; + +struct axp_regulator { + const char *dt_name; + uint16_t min_volt; + uint16_t max_volt; + uint16_t step; + unsigned char split; + unsigned char volt_reg; + unsigned char switch_reg; + unsigned char switch_bit; +}; + +extern const uint8_t axp_chip_id; +extern const char *const axp_compatible; +extern const struct axp_regulator axp_regulators[]; + +/* + * Since the PMIC can be connected to multiple bus types, + * low-level read/write functions must be provided by the platform + */ +int axp_read(uint8_t reg); +int axp_write(uint8_t reg, uint8_t val); +int axp_clrsetbits(uint8_t reg, uint8_t clr_mask, uint8_t set_mask); +#define axp_clrbits(reg, clr_mask) axp_clrsetbits(reg, clr_mask, 0) +#define axp_setbits(reg, set_mask) axp_clrsetbits(reg, 0, set_mask) + +int axp_check_id(void); +void axp_power_off(void); + +#if SUNXI_SETUP_REGULATORS == 1 +void axp_setup_regulators(const void *fdt); +#else +static inline void axp_setup_regulators(const void *fdt) +{ +} +#endif + +#endif /* AXP_H */ diff --git a/arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h b/arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h new file mode 100644 index 0000000..3d003ce --- /dev/null +++ b/arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_RSB_H +#define SUNXI_RSB_H + +#include + +int rsb_init_controller(void); +int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq); +int rsb_set_device_mode(uint32_t device_mode); +int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr); + +int rsb_read(uint8_t rt_addr, uint8_t reg_addr); +int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value); + +#endif /* SUNXI_RSB_H */ diff --git a/arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h b/arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h new file mode 100644 index 0000000..52129a6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019, Remi Pommarel + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SHA_DMA_H +#define SHA_DMA_H + +#define SHA256_HASHSZ 32 +#define SHA256_BLOCKSZ 0x40 + +enum ASD_MODE { + ASM_INVAL, + ASM_SHA256, + ASM_SHA224, +}; + +struct asd_ctx { + uint8_t digest[SHA256_HASHSZ]; + uint8_t block[SHA256_BLOCKSZ]; + size_t blocksz; + enum ASD_MODE mode; + uint8_t started; +}; + +static inline void asd_sha_init(struct asd_ctx *ctx, enum ASD_MODE mode) +{ + ctx->started = 0; + ctx->mode = mode; + ctx->blocksz = 0; +} + +void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len); +void asd_sha_finalize(struct asd_ctx *ctx); + +#endif diff --git a/arm-trusted-firmware/include/drivers/amlogic/meson_console.h b/arm-trusted-firmware/include/drivers/amlogic/meson_console.h new file mode 100644 index 0000000..8d52d79 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/amlogic/meson_console.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MESON_CONSOLE_H +#define MESON_CONSOLE_H + +#include + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new meson 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. + * + * NOTE: The clock is actually fixed to 24 MHz. The argument is only there in + * order to make this function future-proof. + */ +int console_meson_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* MESON_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h b/arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h new file mode 100644 index 0000000..d1e93be --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h @@ -0,0 +1,28 @@ +/* + * 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) + +#define IIDR_MODEL_ARM_GIC_600 U(0x0200043b) +#define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b) +#define IIDR_MODEL_ARM_GIC_700 U(0x0400043b) + +#define PIDR_COMPONENT_ARM_DIST U(0x492) +#define PIDR_COMPONENT_ARM_REDIST U(0x493) +#define PIDR_COMPONENT_ARM_ITS U(0x494) + +#endif /* ARM_GICV3_COMMON_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/cci.h b/arm-trusted-firmware/include/drivers/arm/cci.h new file mode 100644 index 0000000..5aea95a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cci.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CCI_H +#define CCI_H + +#include + +/* Slave interface offsets from PERIPHBASE */ +#define SLAVE_IFACE6_OFFSET UL(0x7000) +#define SLAVE_IFACE5_OFFSET UL(0x6000) +#define SLAVE_IFACE4_OFFSET UL(0x5000) +#define SLAVE_IFACE3_OFFSET UL(0x4000) +#define SLAVE_IFACE2_OFFSET UL(0x3000) +#define SLAVE_IFACE1_OFFSET UL(0x2000) +#define SLAVE_IFACE0_OFFSET UL(0x1000) +#define SLAVE_IFACE_OFFSET(index) (SLAVE_IFACE0_OFFSET + \ + (UL(0x1000) * (index))) + +/* Slave interface event and count register offsets from PERIPHBASE */ +#define EVENT_SELECT7_OFFSET UL(0x80000) +#define EVENT_SELECT6_OFFSET UL(0x70000) +#define EVENT_SELECT5_OFFSET UL(0x60000) +#define EVENT_SELECT4_OFFSET UL(0x50000) +#define EVENT_SELECT3_OFFSET UL(0x40000) +#define EVENT_SELECT2_OFFSET UL(0x30000) +#define EVENT_SELECT1_OFFSET UL(0x20000) +#define EVENT_SELECT0_OFFSET UL(0x10000) +#define EVENT_OFFSET(index) (EVENT_SELECT0_OFFSET + \ + (UL(0x10000) * (index))) + +/* Control and ID register offsets */ +#define CTRL_OVERRIDE_REG U(0x0) +#define SECURE_ACCESS_REG U(0x8) +#define STATUS_REG U(0xc) +#define IMPRECISE_ERR_REG U(0x10) +#define PERFMON_CTRL_REG U(0x100) +#define IFACE_MON_CTRL_REG U(0x104) + +/* Component and peripheral ID registers */ +#define PERIPHERAL_ID0 U(0xFE0) +#define PERIPHERAL_ID1 U(0xFE4) +#define PERIPHERAL_ID2 U(0xFE8) +#define PERIPHERAL_ID3 U(0xFEC) +#define PERIPHERAL_ID4 U(0xFD0) +#define PERIPHERAL_ID5 U(0xFD4) +#define PERIPHERAL_ID6 U(0xFD8) +#define PERIPHERAL_ID7 U(0xFDC) + +#define COMPONENT_ID0 U(0xFF0) +#define COMPONENT_ID1 U(0xFF4) +#define COMPONENT_ID2 U(0xFF8) +#define COMPONENT_ID3 U(0xFFC) +#define COMPONENT_ID4 U(0x1000) +#define COMPONENT_ID5 U(0x1004) +#define COMPONENT_ID6 U(0x1008) +#define COMPONENT_ID7 U(0x100C) + +/* Slave interface register offsets */ +#define SNOOP_CTRL_REG U(0x0) +#define SH_OVERRIDE_REG U(0x4) +#define READ_CHNL_QOS_VAL_OVERRIDE_REG U(0x100) +#define WRITE_CHNL_QOS_VAL_OVERRIDE_REG U(0x104) +#define MAX_OT_REG U(0x110) + +/* Snoop Control register bit definitions */ +#define DVM_EN_BIT BIT_32(1) +#define SNOOP_EN_BIT BIT_32(0) +#define SUPPORT_SNOOPS BIT_32(30) +#define SUPPORT_DVM BIT_32(31) + +/* Status register bit definitions */ +#define CHANGE_PENDING_BIT BIT_32(0) + +/* Event and count register offsets */ +#define EVENT_SELECT_REG U(0x0) +#define EVENT_COUNT_REG U(0x4) +#define COUNT_CNTRL_REG U(0x8) +#define COUNT_OVERFLOW_REG U(0xC) + +/* Slave interface monitor registers */ +#define INT_MON_REG_SI0 U(0x90000) +#define INT_MON_REG_SI1 U(0x90004) +#define INT_MON_REG_SI2 U(0x90008) +#define INT_MON_REG_SI3 U(0x9000C) +#define INT_MON_REG_SI4 U(0x90010) +#define INT_MON_REG_SI5 U(0x90014) +#define INT_MON_REG_SI6 U(0x90018) + +/* Master interface monitor registers */ +#define INT_MON_REG_MI0 U(0x90100) +#define INT_MON_REG_MI1 U(0x90104) +#define INT_MON_REG_MI2 U(0x90108) +#define INT_MON_REG_MI3 U(0x9010c) +#define INT_MON_REG_MI4 U(0x90110) +#define INT_MON_REG_MI5 U(0x90114) + +#define SLAVE_IF_UNUSED -1 + +#ifndef __ASSEMBLER__ + +#include + +/* Function declarations */ + +/* + * The ARM CCI driver needs the following: + * 1. Base address of the CCI product + * 2. An array of map between AMBA 4 master ids and ACE/ACE lite slave + * interfaces. + * 3. Size of the array. + * + * SLAVE_IF_UNUSED should be used in the map to represent no AMBA 4 master exists + * for that interface. + */ +void cci_init(uintptr_t base, const int *map, unsigned int num_cci_masters); + +void cci_enable_snoop_dvm_reqs(unsigned int master_id); +void cci_disable_snoop_dvm_reqs(unsigned int master_id); + +#endif /* __ASSEMBLER__ */ +#endif /* CCI_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/ccn.h b/arm-trusted-firmware/include/drivers/arm/ccn.h new file mode 100644 index 0000000..7f73768 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/ccn.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CCN_H +#define CCN_H + +/* + * This macro defines the maximum number of master interfaces that reside on + * Request nodes which the CCN driver can accommodate. The driver APIs to add + * and remove Request nodes from snoop/dvm domains take a bit map of master + * interfaces as inputs. The largest C data type that can be used is a 64-bit + * unsigned integer. Hence the value of 64. The platform will have to ensure + * that the master interfaces are numbered from 0-63. + */ +#define CCN_MAX_RN_MASTERS 64 + +/* + * The following constants define the various run modes that the platform can + * request the CCN driver to place the L3 cache in. These map to the + * programmable P-State values in a HN-F P-state register. + */ +#define CCN_L3_RUN_MODE_NOL3 0x0 /* HNF_PM_NOL3 */ +#define CCN_L3_RUN_MODE_SFONLY 0x1 /* HNF_PM_SFONLY */ +#define CCN_L3_RUN_MODE_HAM 0x2 /* HNF_PM_HALF */ +#define CCN_L3_RUN_MODE_FAM 0x3 /* HNF_PM_FULL */ + +/* part 0 IDs for various CCN variants */ +#define CCN_502_PART0_ID 0x30 +#define CCN_504_PART0_ID 0x26 +#define CCN_505_PART0_ID 0x27 +#define CCN_508_PART0_ID 0x28 +#define CCN_512_PART0_ID 0x29 + +/* + * The following macro takes the value returned from a read of a HN-F P-state + * status register and returns the retention state value. + */ +#define CCN_GET_RETENTION_STATE(pstate) ((pstate >> 4) & 0x3) + +/* + * The following macro takes the value returned from a read of a HN-F P-state + * status register and returns the run state value. + */ +#define CCN_GET_RUN_STATE(pstate) (pstate & 0xf) + +#ifndef __ASSEMBLER__ +#include + +/* + * This structure describes some of the implementation defined attributes of the + * CCN IP. It is used by the platform port to specify these attributes in order + * to initialise the CCN driver. The attributes are described below. + * + * 1. The 'num_masters' field specifies the total number of master interfaces + * resident on Request nodes. + * + * 2. The 'master_to_rn_id_map' field is a ponter to an array in which each + * index corresponds to a master interface and its value corresponds to the + * Request node on which the master interface resides. + * This field is not simply defined as an array of size CCN_MAX_RN_MASTERS. + * In reality, a platform will have much fewer master * interfaces than + * CCN_MAX_RN_MASTERS. With an array of this size, it would also have to + * set the unused entries to a suitable value. Zeroing the array would not + * be enough since 0 is also a valid node id. Hence, such an array is not + * used. + * + * 3. The 'periphbase' field is the base address of the programmer's view of the + * CCN IP. + */ +typedef struct ccn_desc { + unsigned int num_masters; + const unsigned char *master_to_rn_id_map; + uintptr_t periphbase; +} ccn_desc_t; + +/* Enum used to loop through all types of nodes in CCN*/ +typedef enum node_types { + NODE_TYPE_RNF = 0, + NODE_TYPE_RNI, + NODE_TYPE_RND, + NODE_TYPE_HNF, + NODE_TYPE_HNI, + NODE_TYPE_SN, + NUM_NODE_TYPES +} node_types_t; + +void ccn_init(const ccn_desc_t *plat_ccn_desc); +void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map); +void ccn_exit_snoop_dvm_domain(unsigned long long master_iface_map); +void ccn_enter_dvm_domain(unsigned long long master_iface_map); +void ccn_exit_dvm_domain(unsigned long long master_iface_map); +void ccn_set_l3_run_mode(unsigned int mode); +void ccn_program_sys_addrmap(unsigned int sn0_id, + unsigned int sn1_id, + unsigned int sn2_id, + unsigned int top_addr_bit0, + unsigned int top_addr_bit1, + unsigned char three_sn_en); +unsigned int ccn_get_l3_run_mode(void); +int ccn_get_part0_id(uintptr_t periphbase); + +void ccn_write_node_reg(node_types_t node_type, unsigned int node_id, + unsigned int reg_offset, + unsigned long long val); +unsigned long long ccn_read_node_reg(node_types_t node_type, + unsigned int node_id, + unsigned int reg_offset); + +#endif /* __ASSEMBLER__ */ +#endif /* CCN_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h new file mode 100644 index 0000000..2cb8938 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_CRYPTO_BOOT_DEFS_H +#define _CC_CRYPTO_BOOT_DEFS_H + +/*! @file +@brief This file contains SBROM definitions +*/ + +/*! Version counters value. */ +typedef enum { + + CC_SW_VERSION_COUNTER1 = 1, /*!< Counter 1 - trusted version. */ + CC_SW_VERSION_COUNTER2, /*!< Counter 2 - non trusted version. */ + + CC_SW_VERSION_MAX = 0x7FFFFFFF + +} CCSbSwVersionId_t; + +/* HASH boot key definition */ +typedef enum { + CC_SB_HASH_BOOT_KEY_0_128B = 0, /*!< 128-bit truncated SHA256 digest of public key 0. */ + CC_SB_HASH_BOOT_KEY_1_128B = 1, /*!< 128-bit truncated SHA256 digest of public key 1. */ + CC_SB_HASH_BOOT_KEY_256B = 2, /*!< 256-bit SHA256 digest of public key. */ + CC_SB_HASH_BOOT_NOT_USED = 0xFF, + CC_SB_HASH_MAX_NUM = 0x7FFFFFFF, /*!\internal use external 128-bit truncated SHA256 digest */ +} CCSbPubKeyIndexType_t; + + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h new file mode 100644 index 0000000..212a710 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! +@file +@brief This file contains the platform-dependent definitions that are used in the SBROM code. +*/ + +#ifndef _CC_PAL_SB_PLAT_H +#define _CC_PAL_SB_PLAT_H + +#include "cc_pal_types.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! Definition of DMA address type, can be 32 bits or 64 bits according to CryptoCell's HW. */ +typedef uint64_t CCDmaAddr_t; +/*! Definition of CryptoCell address type, can be 32 bits or 64 bits according to platform. */ +typedef uintptr_t CCAddr_t; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h new file mode 100644 index 0000000..8c09b23 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CC_PAL_TYPES_H +#define CC_PAL_TYPES_H + +/*! +@file +@brief This file contains platform-dependent definitions and types. +*/ + +#include "cc_pal_types_plat.h" + +typedef enum { + CC_FALSE = 0, + CC_TRUE = 1 +} CCBool; + +#define CC_SUCCESS 0UL +#define CC_FAIL 1UL + +#define CC_1K_SIZE_IN_BYTES 1024 +#define CC_BITS_IN_BYTE 8 +#define CC_BITS_IN_32BIT_WORD 32 +#define CC_32BIT_WORD_SIZE (sizeof(uint32_t)) + +#define CC_OK CC_SUCCESS + +#define CC_UNUSED_PARAM(prm) ((void)prm) + +#define CC_MAX_UINT32_VAL (0xFFFFFFFF) + +#define CALC_FULL_BYTES(numBits) (((numBits) + (CC_BITS_IN_BYTE - 1))/CC_BITS_IN_BYTE) +#define CALC_FULL_32BIT_WORDS(numBits) (((numBits) + (CC_BITS_IN_32BIT_WORD - 1))/CC_BITS_IN_32BIT_WRD) +#define CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) (((sizeBytes) + CC_32BIT_WORD_SIZE - 1)/CC_32BIT_WORD_SIZE) + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h new file mode 100644 index 0000000..8410024 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! @file +@brief This file contains basic type definitions that are platform-dependent. +*/ +#ifndef _CC_PAL_TYPES_PLAT_H +#define _CC_PAL_TYPES_PLAT_H +/* Host specific types for standard (ISO-C99) compilant platforms */ + +#include +#include + +typedef uint32_t CCStatus; + +#define CCError_t CCStatus +#define CC_INFINITE 0xFFFFFFFF + +#define CEXPORT_C +#define CIMPORT_C + +#endif /*_CC_PAL_TYPES_PLAT_H*/ diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h new file mode 100644 index 0000000..d419218 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_SEC_DEFS_H +#define _CC_SEC_DEFS_H + +/*! +@file +@brief This file contains general hash definitions and types. +*/ + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! The hashblock size in words. */ +#define HASH_BLOCK_SIZE_IN_WORDS 16 +/*! The hash - SHA2 results in words. */ +#define HASH_RESULT_SIZE_IN_WORDS 8 +#define HASH_RESULT_SIZE_IN_BYTES 32 + +/*! Definition for hash result array. */ +typedef uint32_t CCHashResult_t[HASH_RESULT_SIZE_IN_WORDS]; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h new file mode 100644 index 0000000..18104dd --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CRYPTO_DRIVER_H +#define _CRYPTO_DRIVER_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_sb_plat.h" +#include "cc_sec_defs.h" + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ +/*! + * @brief This function gives the functionality of integrated hash + * + * @param[in] hwBaseAddress - CryptoCell base address + * @param[out] hashResult - the HASH result. + * + */ +CCError_t SBROM_CryptoHash(unsigned long hwBaseAddress, CCDmaAddr_t inputDataAddr, uint32_t BlockSize, + CCHashResult_t hashResult); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h new file mode 100644 index 0000000..a70289f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _NVM__H +#define _NVM__H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_crypto_boot_defs.h" +#include "cc_pal_types.h" +#include "cc_sec_defs.h" + +/*------------------------------------ + DEFINES +-------------------------------------*/ + +/** + * @brief This function reads the LCS from the SRAM/NVM + * + * @param[in] hwBaseAddress - CryptoCell base address + * + * @param[in/out] lcs_ptr - pointer to memory to store the LCS + * + * @return CCError_t - On success the value CC_OK is returned, and on failure -a value from NVM_error.h + */ +CCError_t NVM_GetLCS(unsigned long hwBaseAddress, uint32_t *lcs_ptr); + +/** + * @brief The NVM_ReadHASHPubKey function is a NVM interface function - + * The function retrieves the HASH of the device Public key from the SRAM/NVM + * + * @param[in] hwBaseAddress - CryptoCell base address + * + * @param[in] pubKeyIndex - Index of HASH in the OTP + * + * @param[out] PubKeyHASH - the public key HASH. + * + * @param[in] hashSizeInWords - hash size (valid values: 4W, 8W) + * + * @return CCError_t - On success the value CC_OK is returned, and on failure -a value from NVM_error.h + */ + +CCError_t NVM_ReadHASHPubKey(unsigned long hwBaseAddress, CCSbPubKeyIndexType_t pubKeyIndex, CCHashResult_t PubKeyHASH, uint32_t hashSizeInWords); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h new file mode 100644 index 0000000..390d62b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _NVM_OTP_H +#define _NVM_OTP_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_crypto_boot_defs.h" +#include "cc_pal_types.h" + +/*------------------------------------ + DEFINES +-------------------------------------*/ + + + +/** + * @brief The NVM_GetSwVersion function is a NVM interface function - + * The function retrieves the SW version from the SRAM/NVM. + * In case of OTP, we support up to 16 anti-rollback counters (taken from the certificate) + * + * @param[in] hwBaseAddress - CryptoCell base address + * + * @param[in] counterId - relevant only for OTP (valid values: 1,2) + * + * @param[out] swVersion - the minimum SW version + * + * @return CCError_t - On success the value CC_OK is returned, and on failure -a value from NVM_error.h + */ +CCError_t NVM_GetSwVersion(unsigned long hwBaseAddress, CCSbSwVersionId_t counterId, uint32_t *swVersion); + + +/** + * @brief The NVM_SetSwVersion function is a NVM interface function - + * The function writes the SW version into the SRAM/NVM. + * In case of OTP, we support up to 16 anti-rollback counters (taken from the certificate) + * + * @param[in] hwBaseAddress - CryptoCell base address + * + * @param[in] counterId - relevant only for OTP (valid values: 1,2) + * + * @param[in] swVersion - the minimum SW version + * + * @return CCError_t - On success the value CC_OK is returned, and on failure -a value from NVM_error.h + */ +CCError_t NVM_SetSwVersion(unsigned long hwBaseAddress, CCSbSwVersionId_t counterId, uint32_t swVersion); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h new file mode 100644 index 0000000..825214d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RSA_H +#define RSA_H + +/* + * All the includes that are needed for code using this module to + * compile correctly should be #included here. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_types.h" + +/************************ Defines ******************************/ + +/* the modulus size in bits */ +#if (KEY_SIZE == 2048) +#define RSA_MOD_SIZE_IN_BITS 2048UL +#elif (KEY_SIZE == 3072) +#define RSA_MOD_SIZE_IN_BITS 3072UL +#else +#error Unsupported CryptoCell key size requested +#endif + +#define RSA_MOD_SIZE_IN_BYTES (CALC_FULL_BYTES(RSA_MOD_SIZE_IN_BITS)) +#define RSA_MOD_SIZE_IN_WORDS (CALC_FULL_32BIT_WORDS(RSA_MOD_SIZE_IN_BITS)) +#define RSA_MOD_SIZE_IN_256BITS (RSA_MOD_SIZE_IN_WORDS/8) +#define RSA_EXP_SIZE_IN_BITS 17UL +#define RSA_EXP_SIZE_IN_BYTES (CALC_FULL_BYTES(RSA_EXP_SIZE_IN_BITS)) + +/* + * @brief The RSA_CalcNp calculates Np value and saves it into Np_ptr: + * + * + + * @param[in] hwBaseAddress - HW base address. Relevant for HW + * implementation, for SW it is ignored. + * @N_ptr[in] - The pointer to the modulus buffer. + * @Np_ptr[out] - pointer to Np vector buffer. Its size must be >= 160. + */ +void RSA_CalcNp(unsigned long hwBaseAddress, + uint32_t *N_ptr, + uint32_t *Np_ptr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h new file mode 100644 index 0000000..de83546 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SBROM_BSV_API_H +#define _SBROM_BSV_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This file contains all SBROM library APIs and definitions. +*/ +#include "cc_pal_types.h" + +/* Life cycle state definitions */ +#define CC_BSV_CHIP_MANUFACTURE_LCS 0x0 /*!< CM lifecycle value. */ +#define CC_BSV_DEVICE_MANUFACTURE_LCS 0x1 /*!< DM lifecycle value. */ +#define CC_BSV_SECURITY_DISABLED_LCS 0x3 /*!< SD lifecycle value. */ +#define CC_BSV_SECURE_LCS 0x5 /*!< Secure lifecycle value. */ +#define CC_BSV_RMA_LCS 0x7 /*!< RMA lifecycle value. */ + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/*! +@brief This function should be the first ARM TrustZone CryptoCell TEE SBROM library API called. +It verifies the HW product and version numbers. + +@return CC_OK On success. +@return A non-zero value from sbrom_bsv_error.h on failure. +*/ +CCError_t CC_BsvSbromInit( + unsigned long hwBaseAddress /*!< [in] HW registers base address. */ + ); + + +/*! +@brief This function can be used for checking the LCS value, after CC_BsvLcsGetAndInit was called by the Boot ROM. + +@return CC_OK On success. +@return A non-zero value from sbrom_bsv_error.h on failure. +*/ +CCError_t CC_BsvLcsGet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + uint32_t *pLcs /*!< [out] Returned lifecycle state. */ + ); + +/*! +@brief This function retrieves the HW security lifecycle state, performs validity checks, +and additional initializations in case the LCS is RMA (sets the Kce to fixed value). +\note Invalid LCS results in an error returned. +In this case, the customer's code must completely disable the device. + +@return CC_OK On success. +@return A non-zero value from sbrom_bsv_error.h on failure. +*/ +CCError_t CC_BsvLcsGetAndInit( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + uint32_t *pLcs /*!< [out] Returned lifecycle state. */ + ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h new file mode 100644 index 0000000..6db596e --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SECURE_BOOT_BASE_FUNC_H +#define _SECURE_BOOT_BASE_FUNC_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_types.h" +#include "secureboot_gen_defs.h" + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/** + * @brief This function calculates the HASH over the given data and than verify + * RSA signature on that hashed data + * + * @param[in] hwBaseAddr - CryptoCell base address + * @param[in] pData - pointer to the data to be verified + * @param[in] pNParams - a pointer to the public key parameters + * @param[in] pSignature - a pointer to the signature structure + * @param[in] sizeOfData - size of the data to calculate the HASH on (in bytes) + * @param[in] RSAAlg - RSA algorithm to use + * + * @return CCError_t - On success the value CC_OK is returned, + * on failure - a value from BootImagesVerifier_error.h + */ +CCError_t CCSbVerifySignature(unsigned long hwBaseAddress, + uint32_t *pData, + CCSbNParams_t *pNParams, + CCSbSignature_t *pSignature, + uint32_t sizeOfData, + CCSbRsaAlg_t RSAAlg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h new file mode 100644 index 0000000..ed1f283 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SECURE_BOOT_GEN_DEFS_H +#define _SECURE_BOOT_GEN_DEFS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This file contains all of the definitions and structures that are used for the secure boot. +*/ + +#include "cc_pal_sb_plat.h" +#include "cc_sec_defs.h" + + +/* General definitions */ +/***********************/ + +/*RSA definitions*/ +#if (KEY_SIZE == 2048) +#define SB_RSA_MOD_SIZE_IN_WORDS 64 +#elif (KEY_SIZE == 3072) +#define SB_RSA_MOD_SIZE_IN_WORDS 96 +#else +#error Unsupported CryptoCell key size requested +#endif + +#define SB_RSA_HW_PKI_PKA_BARRETT_MOD_TAG_SIZE_IN_WORDS 5 + + +/*! Public key data structure. */ +typedef struct { + uint32_t N[SB_RSA_MOD_SIZE_IN_WORDS]; /*!< N public key, big endian representation. */ + uint32_t Np[SB_RSA_HW_PKI_PKA_BARRETT_MOD_TAG_SIZE_IN_WORDS]; /*!< Np (Barrett n' value). */ +} CCSbNParams_t; + +/*! Signature structure. */ +typedef struct { + uint32_t sig[SB_RSA_MOD_SIZE_IN_WORDS]; /*!< RSA PSS signature. */ +} CCSbSignature_t; + + +/********* Supported algorithms definitions ***********/ + +/*! RSA supported algorithms */ +/* Note: this applies to either 2k or 3k based on CryptoCell SBROM library + * version - it means 2k in version 1 and 3k in version 2 (yes, really). + */ +typedef enum { + RSA_PSS = 0x01, /*!< RSA PSS after hash SHA 256 */ + RSA_PKCS15 = 0x02, /*!< RSA PKX15 */ + RSA_Last = 0x7FFFFFFF +} CCSbRsaAlg_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h new file mode 100644 index 0000000..18fb599 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UTIL_H +#define UTIL_H + +/* + * All the includes that are needed for code using this module to + * compile correctly should be #included here. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ + +/* invers the bytes on a word- used for output from HASH */ +#ifdef BIG__ENDIAN +#define UTIL_INVERSE_UINT32_BYTES(val) (val) +#else +#define UTIL_INVERSE_UINT32_BYTES(val) \ + (((val) >> 24) | (((val) & 0x00FF0000) >> 8) | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) +#endif + +/* invers the bytes on a word - used for input data for HASH */ +#ifdef BIG__ENDIAN +#define UTIL_REVERT_UINT32_BYTES(val) \ + (((val) >> 24) | (((val) & 0x00FF0000) >> 8) | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) +#else +#define UTIL_REVERT_UINT32_BYTES(val) (val) +#endif + + /* ------------------------------------------------------------ + ** + * @brief This function executes a reverse bytes copying from one buffer to another buffer. + * + * @param[in] dst_ptr - The pointer to destination buffer. + * @param[in] src_ptr - The pointer to source buffer. + * @param[in] size - The size in bytes. + * + */ + +void UTIL_ReverseMemCopy(uint8_t *dst_ptr, uint8_t *src_ptr, uint32_t size); + + + /* ------------------------------------------------------------ + ** + * @brief This function executes a reversed byte copy on a specified buffer. + * + * on a 6 byte byffer: + * + * buff[5] <---> buff[0] + * buff[4] <---> buff[1] + * buff[3] <---> buff[2] + * + * @param[in] dst_ptr - The counter buffer. + * @param[in] src_ptr - The counter size in bytes. + * + */ +void UTIL_ReverseBuff(uint8_t *buff_ptr, uint32_t size); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h new file mode 100644 index 0000000..dc49473 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_API_H +#define _BSV_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the Boot Services APIs and definitions. + +@defgroup cc_bsv_api CryptoCell Boot Services APIs and definitions +@{ +@ingroup cc_bsv +*/ + +#include "cc_pal_types.h" +#include "cc_sec_defs.h" +#include "cc_boot_defs.h" + +/* Life cycle state definitions. */ +#define CC_BSV_CHIP_MANUFACTURE_LCS 0x0 /*!< The CM life-cycle state (LCS) value. */ +#define CC_BSV_DEVICE_MANUFACTURE_LCS 0x1 /*!< The DM life-cycle state (LCS) value. */ +#define CC_BSV_SECURE_LCS 0x5 /*!< The Secure life-cycle state (LCS) value. */ +#define CC_BSV_RMA_LCS 0x7 /*!< The RMA life-cycle state (LCS) value. */ +#define CC_BSV_INVALID_LCS 0xff /*!< The invalid life-cycle state (LCS) value. */ + +/*---------------------------- + TYPES +-----------------------------------*/ + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + + +/*! +@brief This function verifies the product and version numbers of the HW, and initializes it. + +\warning This function must be the first CryptoCell-7xx SBROM library API called. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvInit( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); + +/*! +@brief This function retrieves the HW LCS and performs validity checks. + +If the LCS is RMA, it also sets the OTP secret keys to a fixed value. + +@note An error is returned if there is an invalid LCS. If this happens, your code must +completely disable the device. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvGetAndInitLcs( + unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + uint32_t *pLcs /*!< [out] The value of the current LCS. */ + ); + +/*! +@brief This function retrieves the LCS from the NVM manager. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvLcsGet( + unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + uint32_t *pLcs /*!< [out] The value of the current LCS. */ + ); + +/*! +@brief This function reads software revocation counter from OTP memory, according to the provided sw version index. +SW version is stored in NVM counter and represented by ones. Meaning seVersion=5 would be stored as binary 0b11111; +hence: + the maximal of trusted is 32 + the maximal of non-trusted is 224 + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSwVersionGet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCSbSwVersionId_t id, /*!< [in] Enumeration defining the trusted/non-trusted counter to read. */ + uint32_t *swVersion /*!< [out] The value of the requested counter as read from OTP memory. */ + ); + +/*! +@brief This function sets the NVM counter according to swVersionID (trusted/non-trusted). + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSwVersionSet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCSbSwVersionId_t id, /*!< [in] Enumeration defining the trusted/non-trusted counter to read. */ + uint32_t swVersion /*!< [in] New value of the counter to be programmed in OTP memory. */ + ); + +/*! +@brief This function sets the "fatal error" flag in the NVM manager, to disable the use of +any HW keys or security services. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvFatalErrorSet( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); + +/*! +@brief This function retrieves the public key hash from OTP memory, according to the provided index. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvPubKeyHashGet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCSbPubKeyIndexType_t keyIndex, /*!< [in] Enumeration defining the key hash to retrieve: 128-bit HBK0, 128-bit HBK1, or 256-bit HBK. */ + uint32_t *hashedPubKey, /*!< [out] A buffer to contain the public key HASH. */ + uint32_t hashResultSizeWords /*!< [in] The size of the hash in 32-bit words: + - Must be 4 for 128-bit hash. + - Must be 8 for 256bit hash. */ + ); + +/*! +@brief This function permanently sets the RMA LCS for the ICV and the OEM. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvRMAModeEnable( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); + +/*! +@brief This function is called by the ICV code, to disable the OEM code from changing the ICV RMA bit flag. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvICVRMAFlagBitLock( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); + +/*! +@brief This function locks the defined ICV class keys from further usage. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvICVKeyLock( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCBool_t isICVProvisioningKeyLock, /*!< [in] Should the provisioning key be locked. */ + CCBool_t isICVCodeEncKeyLock /*!< [in] Should the encryption key be locked. */ + ); + + +/*! +@brief This function retrieves the value of "secure disable" bit. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSecureDisableGet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCBool_t *isSDEnabled /*!< [out] The value of the SD Enable bit. */ + ); + + +/*! +@brief This function derives the platform key (Kplt) from the Kpicv, and then decrypts the customer key (Kcst) +from the EKcst (burned in the OTP). The decryption is done only in Secure and RMA LCS mode using AES-ECB. +The customer ROM should invoke this function during early boot, prior to running any non-ROM code, only if Kcst exists. +The resulting Kcst is saved in a HW register. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvCustomerKeyDecrypt( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); +#ifdef __cplusplus +} +#endif + +/*! +@brief This function derives the unique SoC_ID for the device, as hashed (Hbk || AES_CMAC (HUK)). + +@note SoC_ID is required to create debug certificates. + +The OEM or ICV must provide a method for a developer to discover the SoC_ID of a target +device without having to first enable debugging. +One suggested implementation is to have the device ROM code compute the SoC_ID and place +it in a specific location in the flash memory, from where it can be accessed by the developer. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSocIDCompute( + unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + CCHashResult_t hashResult /*!< [out] The derived SoC_ID. */ + ); + +#endif /* _BSV_API_H */ + +/** +@} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h new file mode 100644 index 0000000..1e60579 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_CRYPTO_API_H +#define _BSV_CRYPTO_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the cryptographic ROM APIs of the Boot Services. + +@defgroup cc_bsv_crypto_api CryptoCell Boot Services cryptographic ROM APIs +@{ +@ingroup cc_bsv +*/ + +#include "cc_pal_types.h" +#include "cc_sec_defs.h" +#include "cc_address_defs.h" +#include "bsv_crypto_defs.h" + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/*! +@brief This function calculates the SHA-256 digest over contiguous memory +in an integrated operation. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSha256( + unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + uint8_t *pDataIn, /*!< [in] A pointer to the input buffer to be hashed. The buffer must be contiguous. */ + size_t dataSize, /*!< [in] The size of the data to be hashed, in bytes. */ + CCHashResult_t hashBuff /*!< [out] A pointer to a word-aligned 32-byte buffer. */ + ); + + +/*! +@brief This function allows you to calculate SHA256 digest of an image with decryption base on AES-CTR, +with HW or user key. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. (in this case, hashBuff will be returned clean, while the output data should be cleaned by the user). +*/ +CCError_t CC_BsvCryptoImageDecrypt( unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + CCBsvflowMode_t flow, /*!< [in] The supported operations are: HASH, AES to HASH, AES and HASH. */ + CCBsvKeyType_t keyType, /*!< [in] The key type to use: Kce, Kceicv, or user key. */ + uint8_t *pUserKey, /*!< [in] A pointer to the user key buffer in case keyType is CC_BSV_USER_KEY. */ + size_t userKeySize, /*!< [in] The user key size in bytes (128bits) in case keyType is CC_BSV_USER_KEY. */ + uint8_t *pIvBuf, /*!< [in] A pointer to the IV / counter buffer. */ + uint8_t *pInputData, /*!< [in] A pointer to the input data. */ + uint8_t *pOutputData, /*!< [out] A pointer to the output buffer. (optional – should be null in case of hash only). */ + size_t dataSize, /*!< [in] The size of the input data in bytes. MUST be multiple of AES block size. */ + CCHashResult_t hashBuff /*!< [out] A pointer to a word-aligned 32-byte digest output buffer. */ + ); + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h new file mode 100644 index 0000000..406e1ef --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_CRYPTO_ASYM_API_H +#define _BSV_CRYPTO_ASYM_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the cryptographic Asymmetric ROM APIs of the Boot Services. + +@defgroup cc_bsv_crypto_asym_api CryptoCell Boot Services cryptographic Asymmetric ROM APIs +@{ +@ingroup cc_bsv +*/ + +#include "cc_pal_types.h" +#include "cc_pka_hw_plat_defs.h" +#include "cc_sec_defs.h" +#include "bsv_crypto_api.h" + +/*! Defines the workspace size in bytes needed for internal Asymmetric operations. */ +#define BSV_RSA_WORKSPACE_MIN_SIZE (4*BSV_CERT_RSA_KEY_SIZE_IN_BYTES +\ + 2*RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_BYTES) + +/*! Definition for the RSA public modulus array. */ +typedef uint32_t CCBsvNBuff_t[BSV_CERT_RSA_KEY_SIZE_IN_WORDS]; + +/*! Definition for the RSA Barrett mod tag array. */ +typedef uint32_t CCBsvNpBuff_t[RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_BYTES]; + +/*! Definition for the RSA signature array. */ +typedef uint32_t CCBsvSignature_t[BSV_CERT_RSA_KEY_SIZE_IN_WORDS]; + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/*! +@brief This function performs the primitive operation of RSA, meaning exponent and modulus. + outBuff = (pInBuff ^ Exp) mod NBuff. ( Exp = 0x10001 ) + + The function supports 2k and 3K bit size of modulus, based on compile time define. + There are no restriction on pInBuff location, however its size must be equal to BSV_RSA_KEY_SIZE_IN_BYTES and its + value must be smaller than the modulus. + + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvRsaPrimVerify (unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + CCBsvNBuff_t NBuff, /*!< [in] The modulus buffer big endian format. */ + CCBsvNpBuff_t NpBuff, /*!< [in] The barret tag buffer big endian format - optional. */ + uint32_t *pInBuff, /*!< [in] The DataIn buffer to be encrypted. */ + size_t inBuffSize, /*!< [in] The DataIn buffer size in bytes, must be BSV_RSA_KEY_SIZE_IN_BYTES. */ + CCBsvSignature_t pOutBuff, /*!< [out] The encrypted buffer in big endian format. */ + uint32_t *pWorkSpace, /*!< [in] The pointer to user allocated buffer for internal use. */ + size_t workBufferSize /*!< [in] The size in bytes of pWorkSpace, must be at-least BSV_RSA_WORKSPACE_MIN_SIZE. */ +); + + +/*! +@brief This function performs RSA PSS verify. + + The function should support 2k and 3K bit size of modulus, based on compile time define. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvRsaPssVerify (unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + CCBsvNBuff_t NBuff, /*!< [in] The modulus buffer big endian format. */ + CCBsvNpBuff_t NpBuff, /*!< [in] The barret tag buffer big endian format - optional. */ + CCBsvSignature_t signature, /*!< [in] The signature buffer to verify - big endian format. */ + CCHashResult_t hashedData, /*!< [in] The data-in buffer to be verified as sha256 digest. */ + uint32_t *pWorkSpace, /*!< [in] The pointer to user allocated buffer for internal use. */ + size_t workBufferSize, /*!< [in] The size in bytes of pWorkSpace, must be at-least BSV_RSA_WORKSPACE_MIN_SIZE. */ + CCBool_t *pIsVerified /*!< [out] The flag indicates whether the signature is verified or not. + If verified value will be CC_TRUE, otherwise CC_FALSE */ +); + + + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h new file mode 100644 index 0000000..9ea354d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_CRYPTO_DEFS_H +#define _BSV_CRYPTO_DEFS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the definitions of the cryptographic ROM APIs. + +@defgroup cc_bsv_crypto_defs CryptoCell Boot Services cryptographic ROM API definitions +@{ +@ingroup cc_bsv +*/ + +/*! AES supported HW key code table. */ +typedef enum { + + CC_BSV_USER_KEY = 0, /*!< Definition for a user key. */ + CC_BSV_HUK_KEY = 1, /*!< Definition for the HW unique key. */ + CC_BSV_RTL_KEY = 2, /*!< Definition for the RTL key. */ + CC_BSV_SESSION_KEY = 3, /*!< Definition for the Session key. */ + CC_BSV_CE_KEY = 4, /*!< Definition for the Kce. */ + CC_BSV_PLT_KEY = 5, /*!< Definition for the Platform key. */ + CC_BSV_KCST_KEY = 6, /*!< Definition for Kcst. */ + CC_BSV_ICV_PROV_KEY = 0xd, /*!< Definition for the Kpicv. */ + CC_BSV_ICV_CE_KEY = 0xe, /*!< Definition for the Kceicv. */ + CC_BSV_PROV_KEY = 0xf, /*!< Definition for the Kcp. */ + CC_BSV_END_OF_KEY_TYPE = INT32_MAX, /*!< Reserved. */ +}CCBsvKeyType_t; + +/*! AES directions. */ +typedef enum bsvAesDirection { + BSV_AES_DIRECTION_ENCRYPT = 0, /*!< Encrypt.*/ + BSV_AES_DIRECTION_DECRYPT = 1, /*!< Decrypt.*/ + BSV_AES_NUM_OF_ENCRYPT_MODES, /*!< The maximal number of operations. */ + BSV_AES_DIRECTION_RESERVE32B = INT32_MAX /*!< Reserved.*/ +}bsvAesDirection_t; + +/*! Definitions of the cryptographic flow supported as part of the Secure Boot. */ +typedef enum { + CC_BSV_CRYPTO_HASH_MODE = 0, /*!< Hash mode only. */ + CC_BSV_CRYPTO_AES_CTR_AND_HASH_MODE = 1, /*!< Data goes into the AES and Hash engines. */ + CC_BSV_CRYPTO_AES_CTR_TO_HASH_MODE = 2 /*!< Data goes into the AES and from the AES to the Hash engine. */ +}CCBsvflowMode_t; + +/*! CryptoImage HW completion sequence mode */ +typedef enum +{ + BSV_CRYPTO_COMPLETION_NO_WAIT = 0, /*!< The driver waits only before reading the output. */ + BSV_CRYPTO_COMPLETION_WAIT_UPON_END = 1 /*!< The driver waits after each chunk of data. */ +}bsvCryptoCompletionMode_t; + + +/*! AES-CMAC result size, in words. */ +#define CC_BSV_CMAC_RESULT_SIZE_IN_WORDS 4 /* 128b */ +/*! AES-CMAC result size, in bytes. */ +#define CC_BSV_CMAC_RESULT_SIZE_IN_BYTES 16 /* 128b */ +/*! AES-CCM 128bit key size, in bytes. */ +#define CC_BSV_CCM_KEY_SIZE_BYTES 16 +/*! AES-CCM 128bit key size, in words. */ +#define CC_BSV_CCM_KEY_SIZE_WORDS 4 +/*! AES-CCM NONCE size, in bytes. */ +#define CC_BSV_CCM_NONCE_SIZE_BYTES 12 + + +/*! AES-CMAC result buffer. */ +typedef uint32_t CCBsvCmacResult_t[CC_BSV_CMAC_RESULT_SIZE_IN_WORDS]; +/*! AES-CCM key buffer.*/ +typedef uint32_t CCBsvCcmKey_t[CC_BSV_CCM_KEY_SIZE_WORDS]; +/*! AES-CCM nonce buffer.*/ +typedef uint8_t CCBsvCcmNonce_t[CC_BSV_CCM_NONCE_SIZE_BYTES]; +/*! AES-CCM MAC buffer.*/ +typedef uint8_t CCBsvCcmMacRes_t[CC_BSV_CMAC_RESULT_SIZE_IN_BYTES]; + + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h new file mode 100644 index 0000000..4d72e60 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_ERROR_H +#define _BSV_ERROR_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file defines the error code types that are returned from the Boot Services APIs. + +@defgroup cc_bsv_error CryptoCell Boot Services error codes +@{ +@ingroup cc_bsv +*/ + +/*! Defines the base address for Boot Services errors. */ +#define CC_BSV_BASE_ERROR 0x0B000000 +/*! Defines the base address for Boot Services cryptographic errors. */ +#define CC_BSV_CRYPTO_ERROR 0x0C000000 + +/*! Illegal input parameter. */ +#define CC_BSV_ILLEGAL_INPUT_PARAM_ERR (CC_BSV_BASE_ERROR + 0x00000001) +/*! Illegal HUK value. */ +#define CC_BSV_ILLEGAL_HUK_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000002) +/*! Illegal Kcp value. */ +#define CC_BSV_ILLEGAL_KCP_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000003) +/*! Illegal Kce value. */ +#define CC_BSV_ILLEGAL_KCE_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000004) +/*! Illegal Kpicv value. */ +#define CC_BSV_ILLEGAL_KPICV_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000005) +/*! Illegal Kceicv value. */ +#define CC_BSV_ILLEGAL_KCEICV_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000006) +/*! Illegal EKcst value. */ +#define CC_BSV_ILLEGAL_EKCST_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000007) +/*! Hash boot key not programmed in the OTP. */ +#define CC_BSV_HASH_NOT_PROGRAMMED_ERR (CC_BSV_BASE_ERROR + 0x00000008) +/*! Illegal Hash boot key zero count in the OTP. */ +#define CC_BSV_HBK_ZERO_COUNT_ERR (CC_BSV_BASE_ERROR + 0x00000009) +/*! Illegal LCS. */ +#define CC_BSV_ILLEGAL_LCS_ERR (CC_BSV_BASE_ERROR + 0x0000000A) +/*! OTP write compare failure. */ +#define CC_BSV_OTP_WRITE_CMP_FAIL_ERR (CC_BSV_BASE_ERROR + 0x0000000B) +/*! OTP access error */ +#define CC_BSV_OTP_ACCESS_ERR (CC_BSV_BASE_ERROR + 0x0000000C) +/*! Erase key in OTP failed. */ +#define CC_BSV_ERASE_KEY_FAILED_ERR (CC_BSV_BASE_ERROR + 0x0000000D) +/*! Illegal PIDR. */ +#define CC_BSV_ILLEGAL_PIDR_ERR (CC_BSV_BASE_ERROR + 0x0000000E) +/*! Illegal CIDR. */ +#define CC_BSV_ILLEGAL_CIDR_ERR (CC_BSV_BASE_ERROR + 0x0000000F) +/*! Device failed to move to fatal error state. */ +#define CC_BSV_FAILED_TO_SET_FATAL_ERR (CC_BSV_BASE_ERROR + 0x00000010) +/*! Failed to set RMA LCS. */ +#define CC_BSV_FAILED_TO_SET_RMA_ERR (CC_BSV_BASE_ERROR + 0x00000011) +/*! Illegal RMA indication. */ +#define CC_BSV_ILLEGAL_RMA_INDICATION_ERR (CC_BSV_BASE_ERROR + 0x00000012) +/*! Boot Services version is not initialized. */ +#define CC_BSV_VER_IS_NOT_INITIALIZED_ERR (CC_BSV_BASE_ERROR + 0x00000013) +/*! APB secure mode is locked. */ +#define CC_BSV_APB_SECURE_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000014) +/*! APB privilege mode is locked. */ +#define CC_BSV_APB_PRIVILEG_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000015) +/*! Illegal operation. */ +#define CC_BSV_ILLEGAL_OPERATION_ERR (CC_BSV_BASE_ERROR + 0x00000016) +/*! Illegal asset size. */ +#define CC_BSV_ILLEGAL_ASSET_SIZE_ERR (CC_BSV_BASE_ERROR + 0x00000017) +/*! Illegal asset value. */ +#define CC_BSV_ILLEGAL_ASSET_VAL_ERR (CC_BSV_BASE_ERROR + 0x00000018) +/*! Kpicv is locked. */ +#define CC_BSV_KPICV_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000019) +/*! Illegal SW version. */ +#define CC_BSV_ILLEGAL_SW_VERSION_ERR (CC_BSV_BASE_ERROR + 0x0000001A) +/*! AO write operation. */ +#define CC_BSV_AO_WRITE_FAILED_ERR (CC_BSV_BASE_ERROR + 0x0000001B) +/*! Chip state is already initialized. */ +#define CC_BSV_CHIP_INITIALIZED_ERR (CC_BSV_BASE_ERROR + 0x0000001C) +/*! SP is not enabled. */ +#define CC_BSV_SP_NOT_ENABLED_ERR (CC_BSV_BASE_ERROR + 0x0000001D) +/*! Production secure provisioning - header fields. */ +#define CC_BSV_PROD_PKG_HEADER_ERR (CC_BSV_BASE_ERROR + 0x0000001E) +/*! Production secure provisioning - header MAC. */ +#define CC_BSV_PROD_PKG_HEADER_MAC_ERR (CC_BSV_BASE_ERROR + 0x0000001F) +/*! Overrun buffer or size. */ +#define CC_BSV_OVERRUN_ERR (CC_BSV_BASE_ERROR + 0x00000020) +/*! Kceicv is locked. */ +#define CC_BSV_KCEICV_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000021) +/*! Chip indication is CHIP_STATE_ERROR. */ +#define CC_BSV_CHIP_INDICATION_ERR (CC_BSV_BASE_ERROR + 0x00000022) +/*! Device is locked in fatal error state. */ +#define CC_BSV_FATAL_ERR_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000023) +/*! Device has security disable feature enabled. */ +#define CC_BSV_SECURE_DISABLE_ERROR (CC_BSV_BASE_ERROR + 0x00000024) +/*! Device has Kcst in disabled state */ +#define CC_BSV_KCST_DISABLE_ERROR (CC_BSV_BASE_ERROR + 0x00000025) + + +/*! Illegal data-in pointer. */ +#define CC_BSV_CRYPTO_INVALID_DATA_IN_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000001) +/*! Illegal data-out pointer. */ +#define CC_BSV_CRYPTO_INVALID_DATA_OUT_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000002) +/*! Illegal data size. */ +#define CC_BSV_CRYPTO_INVALID_DATA_SIZE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000003) +/*! Illegal key type. */ +#define CC_BSV_CRYPTO_INVALID_KEY_TYPE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000004) +/*! Illegal key size. */ +#define CC_BSV_CRYPTO_INVALID_KEY_SIZE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000005) +/*! Invalid key pointer. */ +#define CC_BSV_CRYPTO_INVALID_KEY_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000006) +/*! Illegal key DMA type. */ +#define CC_BSV_CRYPTO_INVALID_KEY_DMA_TYPE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000007) +/*! Illegal IV pointer. */ +#define CC_BSV_CRYPTO_INVALID_IV_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000008) +/*! Illegal cipher mode. */ +#define CC_BSV_CRYPTO_INVALID_CIPHER_MODE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000009) +/*! Illegal result buffer pointer. */ +#define CC_BSV_CRYPTO_INVALID_RESULT_BUFFER_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000A) +/*! Invalid DMA type. */ +#define CC_BSV_CRYPTO_INVALID_DMA_TYPE_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000B) +/*! Invalid in/out buffers overlapping. */ +#define CC_BSV_CRYPTO_DATA_OUT_DATA_IN_OVERLAP_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000C) +/*! Invalid KDF label size. */ +#define CC_BSV_CRYPTO_ILLEGAL_KDF_LABEL_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000D) +/*! Invalid KDF Context size. */ +#define CC_BSV_CRYPTO_ILLEGAL_KDF_CONTEXT_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000E) +/*! Invalid CCM key. */ +#define CC_BSV_CCM_INVALID_KEY_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000f) +/*! Invalid CCM Nonce. */ +#define CC_BSV_CCM_INVALID_NONCE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000010) +/*! Invalid CCM associated data. */ +#define CC_BSV_CCM_INVALID_ASSOC_DATA_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000011) +/*! Invalid CCM text data. */ +#define CC_BSV_CCM_INVALID_TEXT_DATA_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000012) +/*! Invalid CCM-MAC buffer. */ +#define CC_BSV_CCM_INVALID_MAC_BUF_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000013) +/*! CCM-MAC comparison failed. */ +#define CC_BSV_CCM_TAG_LENGTH_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000014) +/*! CCM-MAC comparison failed. */ +#define CC_BSV_CCM_MAC_INVALID_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000015) +/*! Illegal flow mode. */ +#define CC_BSV_CRYPTO_INVALID_FLOW_MODE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000016) + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + + + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h new file mode 100644 index 0000000..0abc15c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_ADDRESS_DEFS_H +#define _CC_ADDRESS_DEFS_H + +/*! +@file +@brief This file contains general definitions. +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_types.h" + +/************************ Defines ******************************/ + +/** + * Address types within CC + */ +/*! Definition of DMA address type, can be 32 bits or 64 bits according to CryptoCell's HW. */ +typedef uint64_t CCDmaAddr_t; +/*! Definition of CryptoCell address type, can be 32 bits or 64 bits according to platform. */ +typedef uint64_t CCAddr_t; +/*! Definition of CC SRAM address type, can be 32 bits according to CryptoCell's HW. */ +typedef uint32_t CCSramAddr_t; + +/* + * CCSramAddr_t is being cast into pointer type which can be 64 bit. + */ +/*! Definition of MACRO that casts SRAM addresses to pointer types. */ +#define CCSramAddr2Ptr(sramAddr) ((uintptr_t)sramAddr) + +#ifdef __cplusplus +} +#endif + +#endif + +/** + @} + */ + + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h new file mode 100644 index 0000000..4d29a6d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_BOOT_DEFS_H +#define _CC_BOOT_DEFS_H + +/*! + @file + @brief This file contains general definitions of types and enums of Boot APIs. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! Version counters value. */ +typedef enum { + + CC_SW_VERSION_TRUSTED = 0, /*!< Trusted counter. */ + CC_SW_VERSION_NON_TRUSTED, /*!< Non trusted counter. */ + CC_SW_VERSION_MAX = 0x7FFFFFFF /*!< Reserved */ +} CCSbSwVersionId_t; + +/*! The hash boot key definition. */ +typedef enum { + CC_SB_HASH_BOOT_KEY_0_128B = 0, /*!< Hbk0: 128-bit truncated SHA-256 digest of PubKB0. Used by ICV */ + CC_SB_HASH_BOOT_KEY_1_128B = 1, /*!< Hbk1: 128-bit truncated SHA-256 digest of PubKB1. Used by OEM */ + CC_SB_HASH_BOOT_KEY_256B = 2, /*!< Hbk: 256-bit SHA-256 digest of public key. */ + CC_SB_HASH_BOOT_NOT_USED = 0xF, /*!< Hbk is not used. */ + CC_SB_HASH_MAX_NUM = 0x7FFFFFFF, /*!< Reserved. */ +} CCSbPubKeyIndexType_t; + +/*! Chip state. */ +typedef enum { + CHIP_STATE_NOT_INITIALIZED = 0, /*! Chip is not initialized. */ + CHIP_STATE_TEST = 1, /*! Chip is in Production state. */ + CHIP_STATE_PRODUCTION = 2, /*! Chip is in Production state. */ + CHIP_STATE_ERROR = 3, /*! Chip is in Error state. */ +} CCBsvChipState_t; +#ifdef __cplusplus +} +#endif + +#endif /*_CC_BOOT_DEFS_H */ + +/** +@} + */ diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h new file mode 100644 index 0000000..4ab3960 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CC_PAL_TYPES_H +#define CC_PAL_TYPES_H + +/*! +@file +@brief This file contains platform-dependent definitions and types of the PAL layer. + +@defgroup cc_pal_types CryptoCell platform-dependent PAL layer definitions and types +@{ +@ingroup cc_pal + + @{ + @ingroup cc_pal + @} +*/ + +#include "cc_pal_types_plat.h" + +/*! Definition of Boolean type.*/ +typedef enum { + /*! Boolean false.*/ + CC_FALSE = 0, + /*! Boolean true.*/ + CC_TRUE = 1 +} CCBool_t; + +/*! Success. */ +#define CC_SUCCESS 0UL +/*! Failure. */ +#define CC_FAIL 1UL + +/*! Success (OK). */ +#define CC_OK 0 + +/*! This macro handles unused parameters in the code, to avoid compilation warnings. */ +#define CC_UNUSED_PARAM(prm) ((void)prm) + +/*! The maximal uint32 value.*/ +#define CC_MAX_UINT32_VAL (0xFFFFFFFF) + + +/* Minimal and Maximal macros */ +#ifdef min +/*! Definition for minimal calculation. */ +#define CC_MIN(a,b) min( a , b ) +#else +/*! Definition for minimal calculation. */ +#define CC_MIN( a , b ) ( ( (a) < (b) ) ? (a) : (b) ) +#endif + +#ifdef max +/*! Definition for maximal calculation. */ +#define CC_MAX(a,b) max( a , b ) +#else +/*! Definition for maximal calculation.. */ +#define CC_MAX( a , b ) ( ( (a) > (b) ) ? (a) : (b) ) +#endif + +/*! This macro calculates the number of full Bytes from bits, where seven bits are one Byte. */ +#define CALC_FULL_BYTES(numBits) ((numBits)/CC_BITS_IN_BYTE + (((numBits) & (CC_BITS_IN_BYTE-1)) > 0)) +/*! This macro calculates the number of full 32-bit words from bits where 31 bits are one word. */ +#define CALC_FULL_32BIT_WORDS(numBits) ((numBits)/CC_BITS_IN_32BIT_WORD + (((numBits) & (CC_BITS_IN_32BIT_WORD-1)) > 0)) +/*! This macro calculates the number of full 32-bit words from Bytes where three Bytes are one word. */ +#define CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) ((sizeBytes)/CC_32BIT_WORD_SIZE + (((sizeBytes) & (CC_32BIT_WORD_SIZE-1)) > 0)) +/*! This macro calculates the number of full 32-bit words from 64-bits dwords. */ +#define CALC_32BIT_WORDS_FROM_64BIT_DWORD(sizeWords) (sizeWords * CC_32BIT_WORD_IN_64BIT_DWORD) +/*! This macro rounds up bits to 32-bit words. */ +#define ROUNDUP_BITS_TO_32BIT_WORD(numBits) (CALC_FULL_32BIT_WORDS(numBits) * CC_BITS_IN_32BIT_WORD) +/*! This macro rounds up bits to Bytes. */ +#define ROUNDUP_BITS_TO_BYTES(numBits) (CALC_FULL_BYTES(numBits) * CC_BITS_IN_BYTE) +/*! This macro rounds up bytes to 32-bit words. */ +#define ROUNDUP_BYTES_TO_32BIT_WORD(sizeBytes) (CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) * CC_32BIT_WORD_SIZE) +/*! This macro calculates the number Bytes from words. */ +#define CALC_WORDS_TO_BYTES(numwords) ((numwords)*CC_32BIT_WORD_SIZE) +/*! Definition of 1 KB in Bytes. */ +#define CC_1K_SIZE_IN_BYTES 1024 +/*! Definition of number of bits in a Byte. */ +#define CC_BITS_IN_BYTE 8 +/*! Definition of number of bits in a 32-bits word. */ +#define CC_BITS_IN_32BIT_WORD 32 +/*! Definition of number of Bytes in a 32-bits word. */ +#define CC_32BIT_WORD_SIZE 4 +/*! Definition of number of 32-bits words in a 64-bits dword. */ +#define CC_32BIT_WORD_IN_64BIT_DWORD 2 + + +#endif + +/** +@} + */ + + + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h new file mode 100644 index 0000000..9848472 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! @file +@brief This file contains basic type definitions that are platform-dependent. +*/ +#ifndef _CC_PAL_TYPES_PLAT_H +#define _CC_PAL_TYPES_PLAT_H +/* Host specific types for standard (ISO-C99) compilant platforms */ + +#include +#include + +typedef uint32_t CCStatus; + +#define CCError_t CCStatus +#define CC_INFINITE 0xFFFFFFFF + +#define CEXPORT_C +#define CIMPORT_C + +#endif /*_CC_PAL_TYPES_PLAT_H*/ diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h new file mode 100644 index 0000000..1a1bce0 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_PKA_HW_PLAT_DEFS_H +#define _CC_PKA_HW_PLAT_DEFS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#include "cc_pal_types.h" +/*! +@file +@brief Contains the enums and definitions that are used in the PKA code (definitions that are platform dependent). +*/ + +/*! The size of the PKA engine word. */ +#define CC_PKA_WORD_SIZE_IN_BITS 128 + +/*! The maximal supported size of modulus in RSA in bits. */ +#define CC_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 4096 +/*! The maximal supported size of key-generation in RSA in bits. */ +#define CC_RSA_MAX_KEY_GENERATION_HW_SIZE_BITS 4096 + +/*! Secure boot/debug certificate RSA public modulus key size in bits. */ +#if (KEY_SIZE == 3072) + #define BSV_CERT_RSA_KEY_SIZE_IN_BITS 3072 +#else + #define BSV_CERT_RSA_KEY_SIZE_IN_BITS 2048 +#endif +/*! Secure boot/debug certificate RSA public modulus key size in bytes. */ +#define BSV_CERT_RSA_KEY_SIZE_IN_BYTES (BSV_CERT_RSA_KEY_SIZE_IN_BITS/CC_BITS_IN_BYTE) +/*! Secure boot/debug certificate RSA public modulus key size in words. */ +#define BSV_CERT_RSA_KEY_SIZE_IN_WORDS (BSV_CERT_RSA_KEY_SIZE_IN_BITS/CC_BITS_IN_32BIT_WORD) + +/*! The maximal count of extra bits in PKA operations. */ +#define PKA_EXTRA_BITS 8 +/*! The number of memory registers in PKA operations. */ +#define PKA_MAX_COUNT_OF_PHYS_MEM_REGS 32 + +/*! Size of buffer for Barrett modulus tag in words. */ +#define RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS 5 +/*! Size of buffer for Barrett modulus tag in bytes. */ +#define RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_BYTES (RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS*CC_32BIT_WORD_SIZE) + + + +#ifdef __cplusplus +} +#endif + +#endif //_CC_PKA_HW_PLAT_DEFS_H + +/** + @} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h new file mode 100644 index 0000000..8fb698f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_SEC_DEFS_H +#define _CC_SEC_DEFS_H + +/*! +@file +@brief This file contains general definitions and types. +*/ + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_types.h" + +/*! Hashblock size in words. */ +#define HASH_BLOCK_SIZE_IN_WORDS 16 +/*! Hash - SHA2 results in words. */ +#define HASH_RESULT_SIZE_IN_WORDS 8 +/*! Hash - SHA2 results in bytes. */ +#define HASH_RESULT_SIZE_IN_BYTES 32 + +/*! Definition for hash result array. */ +typedef uint32_t CCHashResult_t[HASH_RESULT_SIZE_IN_WORDS]; + +/*! Definition for converting pointer to Host address. */ +#define CONVERT_TO_ADDR(ptr) (unsigned long)ptr + +/*! Definition for converting pointer to SRAM address. */ +#define CONVERT_TO_SRAM_ADDR(ptr) (0xFFFFFFFF & ptr) + +/*! The data size of the signed SW image, in bytes. */ +/*!\internal ContentCertImageRecord_t includes: HS(8W) + 64-b dstAddr(2W) + imgSize(1W) + isCodeEncUsed(1W) */ +#define SW_REC_SIGNED_DATA_SIZE_IN_BYTES 48 + +/*! The data size of the unsigned SW image, in bytes. */ +/*!\internal CCSbSwImgAddData_t includes: 64-b srcAddr(2W)*/ +#define SW_REC_NONE_SIGNED_DATA_SIZE_IN_BYTES 8 + +/*! The additional data size - storage address and length of the unsigned SW image, in words. */ +#define SW_REC_NONE_SIGNED_DATA_SIZE_IN_WORDS SW_REC_NONE_SIGNED_DATA_SIZE_IN_BYTES/CC_32BIT_WORD_SIZE + +/*! The additional data section size, in bytes. */ +#define CC_SB_MAX_SIZE_ADDITIONAL_DATA_BYTES 128 + +/*! Indication of whether or not to load the SW image to memory. */ +#define CC_SW_COMP_NO_MEM_LOAD_INDICATION 0xFFFFFFFFFFFFFFFFUL + +/*! Indication of product version, stored in certificate version field. */ +#define CC_SB_CERT_VERSION_PROJ_PRD 0x713 + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + + + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h new file mode 100644 index 0000000..9398496 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_ROTPK_H +#define _CC_ROTPK_H + +int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, + unsigned int *flags); + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/css/css_mhu.h b/arm-trusted-firmware/include/drivers/arm/css/css_mhu.h new file mode 100644 index 0000000..ff04ae4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/css_mhu.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_MHU_H +#define CSS_MHU_H + +#include + +void mhu_secure_message_start(unsigned int slot_id); +void mhu_secure_message_send(unsigned int slot_id); +uint32_t mhu_secure_message_wait(void); +void mhu_secure_message_end(unsigned int slot_id); + +void mhu_secure_init(void); + +#endif /* CSS_MHU_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h b/arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h new file mode 100644 index 0000000..88302fd --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_MHU_DOORBELL_H +#define CSS_MHU_DOORBELL_H + +#include + +#include + +/* MHUv2 Frame Base Mask */ +#define MHU_V2_FRAME_BASE_MASK UL(~0xFFF) + +/* MHUv2 Control Registers Offsets */ +#define MHU_V2_MSG_NO_CAP_OFFSET UL(0xF80) +#define MHU_V2_ACCESS_REQ_OFFSET UL(0xF88) +#define MHU_V2_ACCESS_READY_OFFSET UL(0xF8C) + +#define SENDER_REG_STAT(_channel) (0x20 * (_channel)) +#define SENDER_REG_SET(_channel) ((0x20 * (_channel)) + 0xC) + +/* Helper macro to ring doorbell */ +#define MHU_RING_DOORBELL(addr, modify_mask, preserve_mask) do { \ + uint32_t db = mmio_read_32(addr) & (preserve_mask); \ + mmio_write_32(addr, db | (modify_mask)); \ + } while (0) + +#define MHU_V2_ACCESS_REQUEST(addr) \ + mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x1) + +#define MHU_V2_CLEAR_REQUEST(addr) \ + mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x0) + +#define MHU_V2_IS_ACCESS_READY(addr) \ + (mmio_read_32((addr) + MHU_V2_ACCESS_READY_OFFSET) & 0x1) + +struct scmi_channel_plat_info; +void mhu_ring_doorbell(struct scmi_channel_plat_info *plat_info); +void mhuv2_ring_doorbell(struct scmi_channel_plat_info *plat_info); + +#endif /* CSS_MHU_DOORBELL_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/css_scp.h b/arm-trusted-firmware/include/drivers/arm/css/css_scp.h new file mode 100644 index 0000000..2b506ea --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/css_scp.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_SCP_H +#define CSS_SCP_H + +#include + +#include + +#include + +/* Forward declarations */ +struct psci_power_state; + +/* API for power management by SCP */ +int css_system_reset2(int is_vendor, int reset_type, u_register_t cookie); +void css_scp_suspend(const struct psci_power_state *target_state); +void css_scp_off(const struct psci_power_state *target_state); +void css_scp_on(u_register_t mpidr); +int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level); +void __dead2 css_scp_sys_shutdown(void); +void __dead2 css_scp_sys_reboot(void); +void __dead2 css_scp_system_off(int state); + +/* API for SCP Boot Image transfer. Return 0 on success, -1 on error */ +int css_scp_boot_image_xfer(void *image, unsigned int image_size); + +/* + * API to wait for SCP to signal till it's ready after booting the transferred + * image. + */ +int css_scp_boot_ready(void); + +#if CSS_LOAD_SCP_IMAGES + +/* + * All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31 + * usually resides except when ARM_BL31_IN_DRAM is + * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into fw_config. + */ +CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2); +CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2); + +CASSERT(SCP_BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2_overflow); +CASSERT(SCP_BL2U_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow); +#endif + +#endif /* CSS_SCP_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/css_scpi.h b/arm-trusted-firmware/include/drivers/arm/css/css_scpi.h new file mode 100644 index 0000000..68fc60a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/css_scpi.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_SCPI_H +#define CSS_SCPI_H + +#include +#include + +/* + * An SCPI command consists of a header and a payload. + * The following structure describes the header. It is 64-bit long. + */ +typedef struct { + /* Command ID */ + uint32_t id : 7; + /* Set ID. Identifies whether this is a standard or extended command. */ + uint32_t set : 1; + /* Sender ID to match a reply. The value is sender specific. */ + uint32_t sender : 8; + /* Size of the payload in bytes (0 - 511) */ + uint32_t size : 9; + uint32_t reserved : 7; + /* + * Status indicating the success of a command. + * See the enum below. + */ + uint32_t status; +} scpi_cmd_t; + +typedef enum { + SCPI_SET_NORMAL = 0, /* Normal SCPI commands */ + SCPI_SET_EXTENDED /* Extended SCPI commands */ +} scpi_set_t; + +enum { + SCP_OK = 0, /* Success */ + SCP_E_PARAM, /* Invalid parameter(s) */ + SCP_E_ALIGN, /* Invalid alignment */ + SCP_E_SIZE, /* Invalid size */ + SCP_E_HANDLER, /* Invalid handler or callback */ + SCP_E_ACCESS, /* Invalid access or permission denied */ + SCP_E_RANGE, /* Value out of range */ + SCP_E_TIMEOUT, /* Time out has ocurred */ + SCP_E_NOMEM, /* Invalid memory area or pointer */ + SCP_E_PWRSTATE, /* Invalid power state */ + SCP_E_SUPPORT, /* Feature not supported or disabled */ + SCPI_E_DEVICE, /* Device error */ + SCPI_E_BUSY, /* Device is busy */ +}; + +typedef uint32_t scpi_status_t; + +typedef enum { + SCPI_CMD_SCP_READY = 0x01, + SCPI_CMD_SET_CSS_POWER_STATE = 0x03, + SCPI_CMD_GET_CSS_POWER_STATE = 0x04, + SCPI_CMD_SYS_POWER_STATE = 0x05 +} scpi_command_t; + +/* + * Macros to parse SCP response to GET_CSS_POWER_STATE command + * + * [3:0] : cluster ID + * [7:4] : cluster state: 0 = on; 3 = off; rest are reserved + * [15:8]: on/off state for individual CPUs in the cluster + * + * Payload is in little-endian + */ +#define CLUSTER_ID(_resp) ((_resp) & 0xf) +#define CLUSTER_POWER_STATE(_resp) (((_resp) >> 4) & 0xf) + +/* Result is a bit mask of CPU on/off states in the cluster */ +#define CPU_POWER_STATE(_resp) (((_resp) >> 8) & 0xff) + +/* + * For GET_CSS_POWER_STATE, SCP returns the power states of every cluster. The + * size of response depends on the number of clusters in the system. The + * SCP-to-AP payload contains 2 bytes per cluster. Make sure the response is + * large enough to contain power states of a given cluster + */ +#define CHECK_RESPONSE(_resp, _clus) \ + (_resp.size >= (((_clus) + 1) * 2)) + +typedef enum { + scpi_power_on = 0, + scpi_power_retention = 1, + scpi_power_off = 3, +} scpi_power_state_t; + +typedef enum { + scpi_system_shutdown = 0, + scpi_system_reboot = 1, + scpi_system_reset = 2 +} scpi_system_state_t; + +int scpi_wait_ready(void); +void scpi_set_css_power_state(unsigned int mpidr, + scpi_power_state_t cpu_state, + scpi_power_state_t cluster_state, + scpi_power_state_t css_state); +int scpi_get_css_power_state(unsigned int mpidr, unsigned int *cpu_state_p, + unsigned int *cluster_state_p); +uint32_t scpi_sys_power_state(scpi_system_state_t system_state); + +#endif /* CSS_SCPI_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/scmi.h b/arm-trusted-firmware/include/drivers/arm/css/scmi.h new file mode 100644 index 0000000..9dd08e5 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/scmi.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCMI_H +#define SCMI_H + +#include +#include + +#include +#include +#include + +/* Supported SCMI Protocol Versions */ +#define SCMI_AP_CORE_PROTO_VER MAKE_SCMI_VERSION(1, 0) +#define SCMI_PWR_DMN_PROTO_VER MAKE_SCMI_VERSION(2, 0) +#define SCMI_SYS_PWR_PROTO_VER MAKE_SCMI_VERSION(1, 0) + +#define GET_SCMI_MAJOR_VER(ver) (((ver) >> 16) & 0xffff) +#define GET_SCMI_MINOR_VER(ver) ((ver) & 0xffff) + +#define MAKE_SCMI_VERSION(maj, min) \ + ((((maj) & 0xffff) << 16) | ((min) & 0xffff)) + +/* + * Check that the driver's version is same or higher than the reported SCMI + * version. We accept lower major version numbers, as all affected protocols + * so far stay backwards compatible. This might need to be revisited in the + * future. + */ +#define is_scmi_version_compatible(drv, scmi) \ + ((GET_SCMI_MAJOR_VER(drv) > GET_SCMI_MAJOR_VER(scmi)) || \ + ((GET_SCMI_MAJOR_VER(drv) == GET_SCMI_MAJOR_VER(scmi)) && \ + (GET_SCMI_MINOR_VER(drv) <= GET_SCMI_MINOR_VER(scmi)))) + +/* SCMI Protocol identifiers */ +#define SCMI_PWR_DMN_PROTO_ID 0x11 +#define SCMI_SYS_PWR_PROTO_ID 0x12 +/* The AP core protocol is a CSS platform-specific extension */ +#define SCMI_AP_CORE_PROTO_ID 0x90 + +/* Mandatory messages IDs for all SCMI protocols */ +#define SCMI_PROTO_VERSION_MSG 0x0 +#define SCMI_PROTO_ATTR_MSG 0x1 +#define SCMI_PROTO_MSG_ATTR_MSG 0x2 + +/* SCMI power domain management protocol message IDs */ +#define SCMI_PWR_STATE_SET_MSG 0x4 +#define SCMI_PWR_STATE_GET_MSG 0x5 + +/* SCMI system power management protocol message IDs */ +#define SCMI_SYS_PWR_STATE_SET_MSG 0x3 +#define SCMI_SYS_PWR_STATE_GET_MSG 0x4 + +/* SCMI AP core protocol message IDs */ +#define SCMI_AP_CORE_RESET_ADDR_SET_MSG 0x3 +#define SCMI_AP_CORE_RESET_ADDR_GET_MSG 0x4 + +/* Helper macros for system power management protocol commands */ + +/* + * Macros to describe the bit-fields of the `attribute` of system power domain + * protocol PROTOCOL_MSG_ATTRIBUTE message. + */ +#define SYS_PWR_ATTR_WARM_RESET_SHIFT 31 +#define SCMI_SYS_PWR_WARM_RESET_SUPPORTED (1U << SYS_PWR_ATTR_WARM_RESET_SHIFT) + +#define SYS_PWR_ATTR_SUSPEND_SHIFT 30 +#define SCMI_SYS_PWR_SUSPEND_SUPPORTED (1 << SYS_PWR_ATTR_SUSPEND_SHIFT) + +/* + * Macros to describe the bit-fields of the `flags` parameter of system power + * domain protocol SYSTEM_POWER_STATE_SET message. + */ +#define SYS_PWR_SET_GRACEFUL_REQ_SHIFT 0 +#define SCMI_SYS_PWR_GRACEFUL_REQ (1 << SYS_PWR_SET_GRACEFUL_REQ_SHIFT) +#define SCMI_SYS_PWR_FORCEFUL_REQ (0 << SYS_PWR_SET_GRACEFUL_REQ_SHIFT) + +/* + * Macros to describe the `system_state` parameter of system power + * domain protocol SYSTEM_POWER_STATE_SET message. + */ +#define SCMI_SYS_PWR_SHUTDOWN 0x0 +#define SCMI_SYS_PWR_COLD_RESET 0x1 +#define SCMI_SYS_PWR_WARM_RESET 0x2 +#define SCMI_SYS_PWR_POWER_UP 0x3 +#define SCMI_SYS_PWR_SUSPEND 0x4 + +/* + * Macros to describe the bit-fields of the `attribute` of AP core protocol + * AP_CORE_RESET_ADDR set/get messages. + */ +#define SCMI_AP_CORE_LOCK_ATTR_SHIFT 0x0 +#define SCMI_AP_CORE_LOCK_ATTR (1U << SCMI_AP_CORE_LOCK_ATTR_SHIFT) + +/* SCMI Error code definitions */ +#define SCMI_E_QUEUED 1 +#define SCMI_E_SUCCESS 0 +#define SCMI_E_NOT_SUPPORTED -1 +#define SCMI_E_INVALID_PARAM -2 +#define SCMI_E_DENIED -3 +#define SCMI_E_NOT_FOUND -4 +#define SCMI_E_OUT_OF_RANGE -5 +#define SCMI_E_BUSY -6 + +/* + * SCMI driver platform information. The details of the doorbell mechanism + * can be found in the SCMI specification. + */ +typedef struct scmi_channel_plat_info { + /* SCMI mailbox memory */ + uintptr_t scmi_mbx_mem; + /* The door bell register address */ + uintptr_t db_reg_addr; + /* The bit mask that need to be preserved when ringing doorbell */ + uint32_t db_preserve_mask; + /* The bit mask that need to be set to ring doorbell */ + uint32_t db_modify_mask; + /* The handler for ringing doorbell */ + void (*ring_doorbell)(struct scmi_channel_plat_info *plat_info); + /* cookie is unused now. But added for future enhancements. */ + void *cookie; +} scmi_channel_plat_info_t; + + +#if HW_ASSISTED_COHERENCY +typedef spinlock_t scmi_lock_t; +#else +typedef bakery_lock_t scmi_lock_t; +#endif + +/* + * Structure to represent an SCMI channel. + */ +typedef struct scmi_channel { + scmi_channel_plat_info_t *info; + /* The lock for channel access */ + scmi_lock_t *lock; + /* Indicate whether the channel is initialized */ + int is_initialized; +} scmi_channel_t; + +/* External Common API */ +void *scmi_init(scmi_channel_t *ch); +int scmi_proto_msg_attr(void *p, uint32_t proto_id, uint32_t command_id, + uint32_t *attr); +int scmi_proto_version(void *p, uint32_t proto_id, uint32_t *version); + +/* + * Power domain protocol commands. Refer to the SCMI specification for more + * details on these commands. + */ +int scmi_pwr_state_set(void *p, uint32_t domain_id, uint32_t scmi_pwr_state); +int scmi_pwr_state_get(void *p, uint32_t domain_id, uint32_t *scmi_pwr_state); + +/* + * System power management protocol commands. Refer SCMI specification for more + * details on these commands. + */ +int scmi_sys_pwr_state_set(void *p, uint32_t flags, uint32_t system_state); +int scmi_sys_pwr_state_get(void *p, uint32_t *system_state); + +/* SCMI AP core configuration protocol commands. */ +int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr); +int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr); + +/* API to get the platform specific SCMI channel information. */ +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id); + +/* API to override default PSCI callbacks for platforms that support SCMI. */ +const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops); + +#endif /* SCMI_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/sds.h b/arm-trusted-firmware/include/drivers/arm/css/sds.h new file mode 100644 index 0000000..db4cbaa --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/sds.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDS_H +#define SDS_H + +/* SDS Structure Identifier defines */ +/* AP CPU INFO defines */ +#define SDS_AP_CPU_INFO_STRUCT_ID 1 +#define SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET 0x0 +#define SDS_AP_CPU_INFO_PRIMARY_CPUID_SIZE 0x4 + +/* ROM Firmware Version defines */ +#define SDS_ROM_VERSION_STRUCT_ID 2 +#define SDS_ROM_VERSION_OFFSET 0x0 +#define SDS_ROM_VERSION_SIZE 0x4 + +/* RAM Firmware version defines */ +#define SDS_RAM_VERSION_STRUCT_ID 3 +#define SDS_RAM_VERSION_OFFSET 0x0 +#define SDS_RAM_VERSION_SIZE 0x4 + +/* Platform Identity defines */ +#define SDS_PLATFORM_IDENTITY_STRUCT_ID 4 +#define SDS_PLATFORM_IDENTITY_ID_OFFSET 0x0 +#define SDS_PLATFORM_IDENTITY_ID_SIZE 0x4 +#define SDS_PLATFORM_IDENTITY_ID_CONFIG_SHIFT 28 +#define SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH 4 +#define SDS_PLATFORM_IDENTITY_ID_CONFIG_MASK \ + ((1 << SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH) - 1) + +#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_OFFSET 0x4 +#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_SIZE 0x4 + +/* Reset Syndrome defines */ +#define SDS_RESET_SYNDROME_STRUCT_ID 5 +#define SDS_RESET_SYNDROME_OFFSET 0 +#define SDS_RESET_SYNDROME_SIZE 4 +#define SDS_RESET_SYNDROME_POW_ON_RESET_BIT (1 << 0) +#define SDS_RESET_SYNDROME_SCP_WD_RESET_BIT (1 << 1) +#define SDS_RESET_SYNDROME_AP_WD_RESET_BIT (1 << 2) +#define SDS_RESET_SYNDROME_SYS_RESET_REQ_BIT (1 << 3) +#define SDS_RESET_SYNDROME_M3_LOCKUP_BIT (1 << 4) + +/* SCP Firmware Feature Availability defines */ +#define SDS_FEATURE_AVAIL_STRUCT_ID 6 +#define SDS_FEATURE_AVAIL_OFFSET 0 +#define SDS_FEATURE_AVAIL_SIZE 4 +#define SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT (1 << 0) +#define SDS_FEATURE_AVAIL_DMC_READY_BIT (1 << 1) +#define SDS_FEATURE_AVAIL_MSG_IF_READY_BIT (1 << 2) + +/* SCP BL2 Image Metadata defines */ +#define SDS_SCP_IMG_STRUCT_ID 9 +#define SDS_SCP_IMG_FLAG_OFFSET 0 +#define SDS_SCP_IMG_FLAG_SIZE 4 +#define SDS_SCP_IMG_VALID_FLAG_BIT (1 << 0) +#define SDS_SCP_IMG_ADDR_OFFSET 4 +#define SDS_SCP_IMG_ADDR_SIZE 4 +#define SDS_SCP_IMG_SIZE_OFFSET 8 +#define SDS_SCP_IMG_SIZE_SIZE 4 + +/* SDS Driver Error Codes */ +#define SDS_OK 0 +#define SDS_ERR_FAIL -1 +#define SDS_ERR_INVALID_PARAMS -2 +#define SDS_ERR_STRUCT_NOT_FOUND -3 +#define SDS_ERR_STRUCT_NOT_FINALIZED -4 + +#ifndef __ASSEMBLER__ +#include +#include + +typedef enum { + SDS_ACCESS_MODE_NON_CACHED, + SDS_ACCESS_MODE_CACHED, +} sds_access_mode_t; + +int sds_init(void); +int sds_struct_exists(unsigned int structure_id); +int sds_struct_read(uint32_t structure_id, unsigned int fld_off, void *data, + size_t size, sds_access_mode_t mode); +int sds_struct_write(uint32_t structure_id, unsigned int fld_off, void *data, + size_t size, sds_access_mode_t mode); +#endif /*__ASSEMBLER__ */ + +#endif /* SDS_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/dcc.h b/arm-trusted-firmware/include/drivers/arm/dcc.h new file mode 100644 index 0000000..1f1fd03 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/dcc.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, Xilinx Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DCC_H +#define DCC_H + +#include +#include + +/* + * Initialize a new dcc console instance and register it with the console + * framework. + */ +int console_dcc_register(void); + +#endif /* DCC */ diff --git a/arm-trusted-firmware/include/drivers/arm/dsu.h b/arm-trusted-firmware/include/drivers/arm/dsu.h new file mode 100644 index 0000000..ad4a1f0 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/dsu.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DSU_H +#define DSU_H + +#include + +#include + +#include + +/******************************************************************************* + * DSU Power Policy Unit registers + ******************************************************************************/ +#define PPU_PWPR U(0x000) +#define PPU_PMER U(0x004) +#define PPU_PWSR U(0x008) +#define PPU_DISR U(0x010) +#define PPU_MISR U(0x014) +#define PPU_STSR U(0x018) +#define PPU_UNLK U(0x01C) +#define PPU_PWCR U(0x020) +#define PPU_PTCR U(0x024) +#define PPU_IMR U(0x030) +#define PPU_AIMR U(0x034) +#define PPU_ISR U(0x038) +#define PPU_AISR U(0x03C) +#define PPU_IESR U(0x040) +#define PPU_OPSR U(0x044) +#define PPU_FUNRR U(0x050) +#define PPU_FULRR U(0x054) +#define PPU_MEMRR U(0x058) +#define PPU_DCDR0 U(0x170) +#define PPU_DCDR1 U(0x174) +#define PPU_IDR0 U(0xFB0) +#define PPU_IDR1 U(0xFB4) +#define PPU_IIDR U(0xFC8) +#define PPU_AIDR U(0xFCC) +#define PPU_PIDR4 U(0xFD0) +#define PPU_PIDR5 U(0xFD4) +#define PPU_PIDR6 U(0xFD8) +#define PPU_PIDR7 U(0xFDC) +#define PPU_PIDR0 U(0xFE0) +#define PPU_PIDR1 U(0xFE4) +#define PPU_PIDR2 U(0xFE8) +#define PPU_PIDR3 U(0xFEC) +#define PPU_CIDR0 U(0xFF0) +#define PPU_CIDR1 U(0xFF4) +#define PPU_CIDR2 U(0xFF8) +#define PPU_CIDR3 U(0xFFC) + +/******************************************************************************* + * PPU_PWPR and PPU_PWSR constants + ******************************************************************************/ +#define OP_DYN_EN_BIT BIT(24) +#define OP_POLICY_MODE_00 U(0x0) +#define OP_POLICY_MODE_01 U(0x1) +#define OP_POLICY_MODE_03 U(0x3) +#define OP_POLICY_MODE_04 U(0x4) +#define OP_POLICY_MODE_05 U(0x5) +#define OP_POLICY_MODE_07 U(0x7) +#define OP_POLICY_MODE_SHIFT U(16) +#define OP_POLICY_MODE_MASK U(0xF) +#define LOCK_EN_BIT BIT(12) +#define PWR_DYN_EN_BIT BIT(8) +#define PWR_POLICY_OFF U(0x0) +#define PWR_POLICY_OFF_EMU U(0x1) +#define PWR_POLICY_MEM_RET U(0x2) +#define PWR_POLICY_MEM_RET__EMU U(0x3) +#define PWR_POLICY_OFF_FUNC_RET U(0x7) +#define PWR_POLICY_ON U(0x8) +#define PWR_POLICY_WARM_RST U(0x9) +#define PWR_POLICY_DBG_RECOV U(0x10) +#define PWR_POLICY_SHIFT U(0) +#define PWR_POLICY_MASK U(0xF) + +/******************************************************************************* + * Helper macros + ******************************************************************************/ +#define PPU_REGION_SIZE U(0x100000) +#define CLUSTER_PPU_BASE(n) ((PPU_REGION_SIZE * n) + U(0x30000)) +#define CORE_PPU_BASE(n) ((PPU_REGION_SIZE * n) + U(0x80000)) + +/******************************************************************************* + * Accessor functions + ******************************************************************************/ +static inline void dsu_ppu_cluster_write_32(uint32_t core_pos, + uint64_t ub_base, uint32_t offset, uint32_t value) +{ + uint64_t base = ub_base + CLUSTER_PPU_BASE(core_pos); + + mmio_write_32(base + offset, value); +} + +static inline uint32_t dsu_ppu_cluster_read_32(uint32_t core_pos, + uint64_t ub_base, uint32_t offset) +{ + uint64_t base = ub_base + CLUSTER_PPU_BASE(core_pos); + + return mmio_read_32(base + offset); +} + +static inline void dsu_ppu_core_write_32(uint32_t core_pos, uint64_t ub_base, + uint32_t offset, uint32_t value) +{ + uint64_t base = ub_base + CORE_PPU_BASE(core_pos); + + mmio_write_32(base + offset, value); +} + +static inline uint32_t dsu_ppu_core_read_32(uint32_t core_pos, uint64_t ub_base, + uint32_t offset) +{ + uint64_t base = ub_base + CORE_PPU_BASE(core_pos); + + return mmio_read_32(base + offset); +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +int dsu_ppu_setup(uint64_t base, uint64_t per_socket_mmio_size, + unsigned int num_cpus_per_socket); +int dsu_ppu_core_power_on(uint32_t socket, uint32_t core, + uint32_t cluster_ppu_pwpr, uint32_t core_ppu_pwpr); +int dsu_ppu_core_power_off(uint32_t socket, uint32_t core, + uint32_t cluster_ppu_pwpr, uint32_t core_ppu_pwpr); + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/ethosn.h b/arm-trusted-firmware/include/drivers/arm/ethosn.h new file mode 100644 index 0000000..9310733 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/ethosn.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ETHOSN_H +#define ETHOSN_H + +#include + +/* Function numbers */ +#define ETHOSN_FNUM_VERSION U(0x50) +#define ETHOSN_FNUM_IS_SEC U(0x51) +#define ETHOSN_FNUM_HARD_RESET U(0x52) +#define ETHOSN_FNUM_SOFT_RESET U(0x53) +/* 0x54-0x5F reserved for future use */ + +/* SMC64 function IDs */ +#define ETHOSN_FID_64(func_num) U(0xC2000000 | func_num) +#define ETHOSN_FID_VERSION_64 ETHOSN_FID_64(ETHOSN_FNUM_VERSION) +#define ETHOSN_FID_IS_SEC_64 ETHOSN_FID_64(ETHOSN_FNUM_IS_SEC) +#define ETHOSN_FID_HARD_RESET_64 ETHOSN_FID_64(ETHOSN_FNUM_HARD_RESET) +#define ETHOSN_FID_SOFT_RESET_64 ETHOSN_FID_64(ETHOSN_FNUM_SOFT_RESET) + +/* SMC32 function IDs */ +#define ETHOSN_FID_32(func_num) U(0x82000000 | func_num) +#define ETHOSN_FID_VERSION_32 ETHOSN_FID_32(ETHOSN_FNUM_VERSION) +#define ETHOSN_FID_IS_SEC_32 ETHOSN_FID_32(ETHOSN_FNUM_IS_SEC) +#define ETHOSN_FID_HARD_RESET_32 ETHOSN_FID_32(ETHOSN_FNUM_HARD_RESET) +#define ETHOSN_FID_SOFT_RESET_32 ETHOSN_FID_32(ETHOSN_FNUM_SOFT_RESET) + +#define ETHOSN_NUM_SMC_CALLS 8 + +/* Macro to identify function calls */ +#define ETHOSN_FID_MASK U(0xFFF0) +#define ETHOSN_FID_VALUE U(0x50) +#define is_ethosn_fid(_fid) (((_fid) & ETHOSN_FID_MASK) == ETHOSN_FID_VALUE) + +/* Service version */ +#define ETHOSN_VERSION_MAJOR U(1) +#define ETHOSN_VERSION_MINOR U(0) + +/* Return codes for function calls */ +#define ETHOSN_SUCCESS 0 +#define ETHOSN_NOT_SUPPORTED -1 +/* -2 Reserved for NOT_REQUIRED */ +/* -3 Reserved for INVALID_PARAMETER */ +#define ETHOSN_FAILURE -4 +#define ETHOSN_UNKNOWN_CORE_ADDRESS -5 + +uintptr_t ethosn_smc_handler(uint32_t smc_fid, + u_register_t core_addr, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); + +#endif /* ETHOSN_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h b/arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h new file mode 100644 index 0000000..39e2516 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_PWRC_H +#define FVP_PWRC_H + +/* FVP Power controller register offset etc */ +#define PPOFFR_OFF U(0x0) +#define PPONR_OFF U(0x4) +#define PCOFFR_OFF U(0x8) +#define PWKUPR_OFF U(0xc) +#define PSYSR_OFF U(0x10) + +#define PWKUPR_WEN BIT_32(31) + +#define PSYSR_AFF_L2 BIT_32(31) +#define PSYSR_AFF_L1 BIT_32(30) +#define PSYSR_AFF_L0 BIT_32(29) +#define PSYSR_WEN BIT_32(28) +#define PSYSR_PC BIT_32(27) +#define PSYSR_PP BIT_32(26) + +#define PSYSR_WK_SHIFT 24 +#define PSYSR_WK_WIDTH 0x2 +#define PSYSR_WK_MASK ((1U << PSYSR_WK_WIDTH) - 1U) +#define PSYSR_WK(x) ((x) >> PSYSR_WK_SHIFT) & PSYSR_WK_MASK + +#define WKUP_COLD U(0x0) +#define WKUP_RESET U(0x1) +#define WKUP_PPONR U(0x2) +#define WKUP_GICREQ U(0x3) + +#define PSYSR_INVALID U(0xffffffff) + +#ifndef __ASSEMBLER__ + +#include + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void fvp_pwrc_write_pcoffr(u_register_t mpidr); +void fvp_pwrc_write_ppoffr(u_register_t mpidr); +void fvp_pwrc_write_pponr(u_register_t mpidr); +void fvp_pwrc_set_wen(u_register_t mpidr); +void fvp_pwrc_clr_wen(u_register_t mpidr); +unsigned int fvp_pwrc_read_psysr(u_register_t mpidr); +unsigned int fvp_pwrc_get_cpu_wkr(u_register_t mpidr); + +#endif /*__ASSEMBLER__*/ + +#endif /* FVP_PWRC_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/gic600_multichip.h b/arm-trusted-firmware/include/drivers/arm/gic600_multichip.h new file mode 100644 index 0000000..bda406b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h b/arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h new file mode 100644 index 0000000..88b87b9 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC600AE_FMU_H +#define GIC600AE_FMU_H + +/******************************************************************************* + * GIC600-AE FMU register offsets and constants + ******************************************************************************/ +#define GICFMU_ERRFR_LO U(0x000) +#define GICFMU_ERRFR_HI U(0x004) +#define GICFMU_ERRCTLR_LO U(0x008) +#define GICFMU_ERRCTLR_HI U(0x00C) +#define GICFMU_ERRSTATUS_LO U(0x010) +#define GICFMU_ERRSTATUS_HI U(0x014) +#define GICFMU_ERRGSR_LO U(0xE00) +#define GICFMU_ERRGSR_HI U(0xE04) +#define GICFMU_KEY U(0xEA0) +#define GICFMU_PINGCTLR U(0xEA4) +#define GICFMU_PINGNOW U(0xEA8) +#define GICFMU_SMEN U(0xEB0) +#define GICFMU_SMINJERR U(0xEB4) +#define GICFMU_PINGMASK_LO U(0xEC0) +#define GICFMU_PINGMASK_HI U(0xEC4) +#define GICFMU_STATUS U(0xF00) +#define GICFMU_ERRIDR U(0xFC8) + +/* ERRCTLR bits */ +#define FMU_ERRCTLR_ED_BIT BIT(0) +#define FMU_ERRCTLR_CE_EN_BIT BIT(1) +#define FMU_ERRCTLR_UI_BIT BIT(2) +#define FMU_ERRCTLR_CI_BIT BIT(3) + +/* SMEN constants */ +#define FMU_SMEN_BLK_SHIFT U(8) +#define FMU_SMEN_SMID_SHIFT U(24) +#define FMU_SMEN_EN_BIT BIT(0) + +/* Error record IDs */ +#define FMU_BLK_GICD U(0) +#define FMU_BLK_SPICOL U(1) +#define FMU_BLK_WAKERQ U(2) +#define FMU_BLK_ITS0 U(4) +#define FMU_BLK_ITS1 U(5) +#define FMU_BLK_ITS2 U(6) +#define FMU_BLK_ITS3 U(7) +#define FMU_BLK_ITS4 U(8) +#define FMU_BLK_ITS5 U(9) +#define FMU_BLK_ITS6 U(10) +#define FMU_BLK_ITS7 U(11) +#define FMU_BLK_PPI0 U(12) +#define FMU_BLK_PPI1 U(13) +#define FMU_BLK_PPI2 U(14) +#define FMU_BLK_PPI3 U(15) +#define FMU_BLK_PPI4 U(16) +#define FMU_BLK_PPI5 U(17) +#define FMU_BLK_PPI6 U(18) +#define FMU_BLK_PPI7 U(19) +#define FMU_BLK_PPI8 U(20) +#define FMU_BLK_PPI9 U(21) +#define FMU_BLK_PPI10 U(22) +#define FMU_BLK_PPI11 U(23) +#define FMU_BLK_PPI12 U(24) +#define FMU_BLK_PPI13 U(25) +#define FMU_BLK_PPI14 U(26) +#define FMU_BLK_PPI15 U(27) +#define FMU_BLK_PPI16 U(28) +#define FMU_BLK_PPI17 U(29) +#define FMU_BLK_PPI18 U(30) +#define FMU_BLK_PPI19 U(31) +#define FMU_BLK_PPI20 U(32) +#define FMU_BLK_PPI21 U(33) +#define FMU_BLK_PPI22 U(34) +#define FMU_BLK_PPI23 U(35) +#define FMU_BLK_PPI24 U(36) +#define FMU_BLK_PPI25 U(37) +#define FMU_BLK_PPI26 U(38) +#define FMU_BLK_PPI27 U(39) +#define FMU_BLK_PPI28 U(40) +#define FMU_BLK_PPI29 U(41) +#define FMU_BLK_PPI30 U(42) +#define FMU_BLK_PPI31 U(43) +#define FMU_BLK_PRESENT_MASK U(0xFFFFFFFFFFF) + +/* Safety Mechamism limit */ +#define FMU_SMID_GICD_MAX U(33) +#define FMU_SMID_PPI_MAX U(12) +#define FMU_SMID_ITS_MAX U(14) +#define FMU_SMID_SPICOL_MAX U(5) +#define FMU_SMID_WAKERQ_MAX U(2) + +/* MBIST Safety Mechanism ID */ +#define GICD_MBIST_REQ_ERROR U(23) +#define GICD_FMU_CLKGATE_ERROR U(33) +#define PPI_MBIST_REQ_ERROR U(10) +#define PPI_FMU_CLKGATE_ERROR U(12) +#define ITS_MBIST_REQ_ERROR U(13) +#define ITS_FMU_CLKGATE_ERROR U(14) + +/* ERRSTATUS bits */ +#define FMU_ERRSTATUS_BLKID_SHIFT U(32) +#define FMU_ERRSTATUS_BLKID_MASK U(0xFF) +#define FMU_ERRSTATUS_V_BIT BIT(30) +#define FMU_ERRSTATUS_UE_BIT BIT(29) +#define FMU_ERRSTATUS_OV_BIT BIT(27) +#define FMU_ERRSTATUS_CE_BITS (BIT(25) | BIT(24)) +#define FMU_ERRSTATUS_CLEAR (FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \ + FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS) +#define FMU_ERRSTATUS_IERR_MASK U(0xFF) +#define FMU_ERRSTATUS_IERR_SHIFT U(8) +#define FMU_ERRSTATUS_SERR_MASK U(0xFF) + +/* PINGCTLR constants */ +#define FMU_PINGCTLR_INTDIFF_SHIFT U(16) +#define FMU_PINGCTLR_TIMEOUTVAL_SHIFT U(4) +#define FMU_PINGCTLR_EN_BIT BIT(0) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/******************************************************************************* + * GIC600 FMU EL3 driver API + ******************************************************************************/ +uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n); +uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n); +uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n); +uint64_t gic_fmu_read_errgsr(uintptr_t base); +uint32_t gic_fmu_read_pingctlr(uintptr_t base); +uint32_t gic_fmu_read_pingnow(uintptr_t base); +uint64_t gic_fmu_read_pingmask(uintptr_t base); +uint32_t gic_fmu_read_status(uintptr_t base); +uint32_t gic_fmu_read_erridr(uintptr_t base); +void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val); +void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val); +void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val); +void gic_fmu_write_pingnow(uintptr_t base, uint32_t val); +void gic_fmu_write_smen(uintptr_t base, uint32_t val); +void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val); +void gic_fmu_write_pingmask(uintptr_t base, uint64_t val); +void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid); + +void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, bool errctlr_ce_en, bool errctlr_ue_en); +void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask, + unsigned int timeout_val, unsigned int interval_diff); +void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid); +int gic600_fmu_probe(uint64_t base, int *probe_data); +int gic600_fmu_ras_handler(uint64_t base, int probe_data); + +#endif /* __ASSEMBLER__ */ + +#endif /* GIC600AE_FMU_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/gic_common.h b/arm-trusted-firmware/include/drivers/arm/gic_common.h new file mode 100644 index 0000000..c385708 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gic_common.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. 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_SAC U(0x24) +#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) + +/* GICD_SAC bit definitions */ +#define SAC_GICTNS BIT(1) +#define SAC_GICPNS BIT(2) + +/******************************************************************************* + * 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/arm-trusted-firmware/include/drivers/arm/gicv2.h b/arm-trusted-firmware/include/drivers/arm/gicv2.h new file mode 100644 index 0000000..b960194 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gicv2.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GICV2_H +#define GICV2_H + +#include +#include + +/******************************************************************************* + * GICv2 miscellaneous definitions + ******************************************************************************/ + +/* Interrupt group definitions */ +#define GICV2_INTR_GROUP0 U(0) +#define GICV2_INTR_GROUP1 U(1) + +/* Interrupt IDs reported by the HPPIR and IAR registers */ +#define PENDING_G1_INTID U(1022) + +/* GICv2 can only target up to 8 PEs */ +#define GICV2_MAX_TARGET_PE U(8) + +/******************************************************************************* + * GICv2 specific Distributor interface register offsets and constants. + ******************************************************************************/ +#define GICD_ITARGETSR U(0x800) +#define GICD_SGIR U(0xF00) +#define GICD_CPENDSGIR U(0xF10) +#define GICD_SPENDSGIR U(0xF20) + +/* + * Some GICv2 implementations violate the specification and have this register + * at a different address. Allow overriding it in platform_def.h as workaround. + */ +#ifndef GICD_PIDR2_GICV2 +#define GICD_PIDR2_GICV2 U(0xFE8) +#endif + +#define ITARGETSR_SHIFT 2 +#define GIC_TARGET_CPU_MASK U(0xff) + +#define CPENDSGIR_SHIFT 2 +#define SPENDSGIR_SHIFT CPENDSGIR_SHIFT + +#define SGIR_TGTLSTFLT_SHIFT 24 +#define SGIR_TGTLSTFLT_MASK U(0x3) +#define SGIR_TGTLST_SHIFT 16 +#define SGIR_TGTLST_MASK U(0xff) +#define SGIR_INTID_MASK ULL(0xf) + +#define SGIR_TGT_SPECIFIC U(0) + +#define GICV2_SGIR_VALUE(tgt_lst_flt, tgt, intid) \ + ((((tgt_lst_flt) & SGIR_TGTLSTFLT_MASK) << SGIR_TGTLSTFLT_SHIFT) | \ + (((tgt) & SGIR_TGTLST_MASK) << SGIR_TGTLST_SHIFT) | \ + ((intid) & SGIR_INTID_MASK)) + +/******************************************************************************* + * GICv2 specific CPU interface register offsets and constants. + ******************************************************************************/ +/* Physical CPU Interface registers */ +#define GICC_CTLR U(0x0) +#define GICC_PMR U(0x4) +#define GICC_BPR U(0x8) +#define GICC_IAR U(0xC) +#define GICC_EOIR U(0x10) +#define GICC_RPR U(0x14) +#define GICC_HPPIR U(0x18) +#define GICC_AHPPIR U(0x28) +#define GICC_IIDR U(0xFC) +#define GICC_DIR U(0x1000) +#define GICC_PRIODROP GICC_EOIR + +/* GICC_CTLR bit definitions */ +#define EOI_MODE_NS BIT_32(10) +#define EOI_MODE_S BIT_32(9) +#define IRQ_BYP_DIS_GRP1 BIT_32(8) +#define FIQ_BYP_DIS_GRP1 BIT_32(7) +#define IRQ_BYP_DIS_GRP0 BIT_32(6) +#define FIQ_BYP_DIS_GRP0 BIT_32(5) +#define CBPR BIT_32(4) +#define FIQ_EN_SHIFT 3 +#define FIQ_EN_BIT BIT_32(FIQ_EN_SHIFT) +#define ACK_CTL BIT_32(2) + +/* GICC_IIDR bit masks and shifts */ +#define GICC_IIDR_PID_SHIFT 20 +#define GICC_IIDR_ARCH_SHIFT 16 +#define GICC_IIDR_REV_SHIFT 12 +#define GICC_IIDR_IMP_SHIFT 0 + +#define GICC_IIDR_PID_MASK U(0xfff) +#define GICC_IIDR_ARCH_MASK U(0xf) +#define GICC_IIDR_REV_MASK U(0xf) +#define GICC_IIDR_IMP_MASK U(0xfff) + +/* HYP view virtual CPU Interface registers */ +#define GICH_CTL U(0x0) +#define GICH_VTR U(0x4) +#define GICH_ELRSR0 U(0x30) +#define GICH_ELRSR1 U(0x34) +#define GICH_APR0 U(0xF0) +#define GICH_LR_BASE U(0x100) + +/* Virtual CPU Interface registers */ +#define GICV_CTL U(0x0) +#define GICV_PRIMASK U(0x4) +#define GICV_BP U(0x8) +#define GICV_INTACK U(0xC) +#define GICV_EOI U(0x10) +#define GICV_RUNNINGPRI U(0x14) +#define GICV_HIGHESTPEND U(0x18) +#define GICV_DEACTIVATE U(0x1000) + +/* GICD_CTLR bit definitions */ +#define CTLR_ENABLE_G1_SHIFT 1 +#define CTLR_ENABLE_G1_MASK U(0x1) +#define CTLR_ENABLE_G1_BIT BIT_32(CTLR_ENABLE_G1_SHIFT) + +/* Interrupt ID mask for HPPIR, AHPPIR, IAR and AIAR CPU Interface registers */ +#define INT_ID_MASK U(0x3ff) + +#ifndef __ASSEMBLER__ + +#include +#include + +#include + +/******************************************************************************* + * This structure describes some of the implementation defined attributes of + * the GICv2 IP. It is used by the platform port to specify these attributes + * in order to initialize the GICv2 driver. The attributes are described + * below. + * + * The 'gicd_base' field contains the base address of the Distributor interface + * programmer's view. + * + * The 'gicc_base' field contains the base address of the CPU Interface + * programmer's view. + * + * The 'target_masks' is a pointer to an array containing 'target_masks_num' + * elements. The GIC driver will populate the array with per-PE target mask to + * use to when targeting interrupts. + * + * 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, 'g0_interrupt_num' is + * ignored. + ******************************************************************************/ +typedef struct gicv2_driver_data { + uintptr_t gicd_base; + uintptr_t gicc_base; + unsigned int *target_masks; + unsigned int target_masks_num; + const interrupt_prop_t *interrupt_props; + unsigned int interrupt_props_num; +} gicv2_driver_data_t; + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +void gicv2_driver_init(const gicv2_driver_data_t *plat_driver_data); +void gicv2_distif_init(void); +void gicv2_pcpu_distif_init(void); +void gicv2_cpuif_enable(void); +void gicv2_cpuif_disable(void); +unsigned int gicv2_is_fiq_enabled(void); +unsigned int gicv2_get_pending_interrupt_type(void); +unsigned int gicv2_get_pending_interrupt_id(void); +unsigned int gicv2_acknowledge_interrupt(void); +void gicv2_end_of_interrupt(unsigned int id); +unsigned int gicv2_get_interrupt_group(unsigned int id); +unsigned int gicv2_get_running_priority(void); +void gicv2_set_pe_target_mask(unsigned int proc_num); +unsigned int gicv2_get_interrupt_active(unsigned int id); +void gicv2_enable_interrupt(unsigned int id); +void gicv2_disable_interrupt(unsigned int id); +void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority); +void gicv2_set_interrupt_type(unsigned int id, unsigned int type); +void gicv2_raise_sgi(int sgi_num, int proc_num); +void gicv2_set_spi_routing(unsigned int id, int proc_num); +void gicv2_set_interrupt_pending(unsigned int id); +void gicv2_clear_interrupt_pending(unsigned int id); +unsigned int gicv2_set_pmr(unsigned int mask); +void gicv2_interrupt_set_cfg(unsigned int id, unsigned int cfg); + +#endif /* __ASSEMBLER__ */ +#endif /* GICV2_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/gicv3.h b/arm-trusted-firmware/include/drivers/arm/gicv3.h new file mode 100644 index 0000000..5efefb6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gicv3.h @@ -0,0 +1,547 @@ +/* + * 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_PIDR0_GICV3 U(0xffe0) +#define GICD_PIDR1_GICV3 U(0xffe4) +#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 + ******************************************************************************/ +#define GICR_V4_PCPUBASE_SHIFT 0x12 +#define GICR_V3_PCPUBASE_SHIFT 0x11 +#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_VLPI_SHIFT 1 + +#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_VLPI_BIT BIT_32(TYPER_VLPI_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) + +#define GITS_TYPER_VSGI BIT_64(39) + +#ifndef __ASSEMBLER__ + +#include +#include + +#include +#include +#include +#include + +static inline uintptr_t gicv3_redist_size(uint64_t typer_val) +{ +#if GIC_ENABLE_V4_EXTN + if ((typer_val & TYPER_VLPI_BIT) != 0U) { + return 1U << GICR_V4_PCPUBASE_SHIFT; + } else { + return 1U << GICR_V3_PCPUBASE_SHIFT; + } +#else + return 1U << GICR_V3_PCPUBASE_SHIFT; +#endif +} + +unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame); + +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/arm-trusted-firmware/include/drivers/arm/nic_400.h b/arm-trusted-firmware/include/drivers/arm/nic_400.h new file mode 100644 index 0000000..bb74982 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/nic_400.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NIC_400_H +#define NIC_400_H + +/* + * Address of slave 'n' security setting in the NIC-400 address region + * control + */ +#define NIC400_ADDR_CTRL_SECURITY_REG(n) (0x8 + (n) * 4) + +#endif /* NIC_400_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/pl011.h b/arm-trusted-firmware/include/drivers/arm/pl011.h new file mode 100644 index 0000000..ebc6643 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/pl011.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PL011_H +#define PL011_H + +#include + +/* PL011 Registers */ +#define UARTDR 0x000 +#define UARTRSR 0x004 +#define UARTECR 0x004 +#define UARTFR 0x018 +#define UARTIMSC 0x038 +#define UARTRIS 0x03C +#define UARTICR 0x044 + +/* PL011 registers (out of the SBSA specification) */ +#if !PL011_GENERIC_UART +#define UARTILPR 0x020 +#define UARTIBRD 0x024 +#define UARTFBRD 0x028 +#define UARTLCR_H 0x02C +#define UARTCR 0x030 +#define UARTIFLS 0x034 +#define UARTMIS 0x040 +#define UARTDMACR 0x048 +#endif /* !PL011_GENERIC_UART */ + +/* Data status bits */ +#define UART_DATA_ERROR_MASK 0x0F00 + +/* Status reg bits */ +#define UART_STATUS_ERROR_MASK 0x0F + +/* Flag reg bits */ +#define PL011_UARTFR_RI (1 << 8) /* Ring indicator */ +#define PL011_UARTFR_TXFE (1 << 7) /* Transmit FIFO empty */ +#define PL011_UARTFR_RXFF (1 << 6) /* Receive FIFO full */ +#define PL011_UARTFR_TXFF (1 << 5) /* Transmit FIFO full */ +#define PL011_UARTFR_RXFE (1 << 4) /* Receive FIFO empty */ +#define PL011_UARTFR_BUSY (1 << 3) /* UART busy */ +#define PL011_UARTFR_DCD (1 << 2) /* Data carrier detect */ +#define PL011_UARTFR_DSR (1 << 1) /* Data set ready */ +#define PL011_UARTFR_CTS (1 << 0) /* Clear to send */ + +#define PL011_UARTFR_TXFF_BIT 5 /* Transmit FIFO full bit in UARTFR register */ +#define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */ +#define PL011_UARTFR_BUSY_BIT 3 /* UART busy bit in UARTFR register */ + +/* Control reg bits */ +#if !PL011_GENERIC_UART +#define PL011_UARTCR_CTSEN (1 << 15) /* CTS hardware flow control enable */ +#define PL011_UARTCR_RTSEN (1 << 14) /* RTS hardware flow control enable */ +#define PL011_UARTCR_RTS (1 << 11) /* Request to send */ +#define PL011_UARTCR_DTR (1 << 10) /* Data transmit ready. */ +#define PL011_UARTCR_RXE (1 << 9) /* Receive enable */ +#define PL011_UARTCR_TXE (1 << 8) /* Transmit enable */ +#define PL011_UARTCR_LBE (1 << 7) /* Loopback enable */ +#define PL011_UARTCR_UARTEN (1 << 0) /* UART Enable */ + +#if !defined(PL011_LINE_CONTROL) +/* FIFO Enabled / No Parity / 8 Data bit / One Stop Bit */ +#define PL011_LINE_CONTROL (PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8) +#endif + +/* Line Control Register Bits */ +#define PL011_UARTLCR_H_SPS (1 << 7) /* Stick parity select */ +#define PL011_UARTLCR_H_WLEN_8 (3 << 5) +#define PL011_UARTLCR_H_WLEN_7 (2 << 5) +#define PL011_UARTLCR_H_WLEN_6 (1 << 5) +#define PL011_UARTLCR_H_WLEN_5 (0 << 5) +#define PL011_UARTLCR_H_FEN (1 << 4) /* FIFOs Enable */ +#define PL011_UARTLCR_H_STP2 (1 << 3) /* Two stop bits select */ +#define PL011_UARTLCR_H_EPS (1 << 2) /* Even parity select */ +#define PL011_UARTLCR_H_PEN (1 << 1) /* Parity Enable */ +#define PL011_UARTLCR_H_BRK (1 << 0) /* Send break */ + +#endif /* !PL011_GENERIC_UART */ + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new PL011 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_pl011_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* PL011_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/pl061_gpio.h b/arm-trusted-firmware/include/drivers/arm/pl061_gpio.h new file mode 100644 index 0000000..68238c9 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/pl061_gpio.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PL061_GPIO_H +#define PL061_GPIO_H + +#include + +void pl061_gpio_register(uintptr_t base_addr, int gpio_dev); +void pl061_gpio_init(void); + +#endif /* PL061_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/sbsa.h b/arm-trusted-firmware/include/drivers/arm/sbsa.h new file mode 100644 index 0000000..9403634 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/sbsa.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SBSA_H +#define SBSA_H + +#include + +/* Register Offsets */ +#define SBSA_WDOG_WCS_OFFSET UL(0x000) +#define SBSA_WDOG_WOR_LOW_OFFSET UL(0x008) +#define SBSA_WDOG_WOR_HIGH_OFFSET UL(0x00C) + +#define SBSA_WDOG_WCS_EN U(0x1) + +#define SBSA_WDOG_WOR_WIDTH UL(48) + +void sbsa_wdog_start(uintptr_t base, uint64_t ms); +void sbsa_wdog_stop(uintptr_t base); + +#endif /* SBSA_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/scu.h b/arm-trusted-firmware/include/drivers/arm/scu.h new file mode 100644 index 0000000..992539f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/scu.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCU_H +#define SCU_H + +#include + +#define SCU_CTRL_REG 0x00 +#define SCU_CFG_REG 0x04 + +#define SCU_ENABLE_BIT (1 << 0) + +void enable_snoop_ctrl_unit(uintptr_t base); +uint32_t read_snoop_ctrl_unit_cfg(uintptr_t base); + +#endif /* SCU_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/smmu_v3.h b/arm-trusted-firmware/include/drivers/arm/smmu_v3.h new file mode 100644 index 0000000..a820a44 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/smmu_v3.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMMU_V3_H +#define SMMU_V3_H + +#include +#include + +/* SMMUv3 register offsets from device base */ +#define SMMU_GBPA U(0x0044) +#define SMMU_S_IDR1 U(0x8004) +#define SMMU_S_INIT U(0x803c) +#define SMMU_S_GBPA U(0x8044) + +/* SMMU_GBPA register fields */ +#define SMMU_GBPA_UPDATE (1UL << 31) +#define SMMU_GBPA_ABORT (1UL << 20) + +/* SMMU_S_IDR1 register fields */ +#define SMMU_S_IDR1_SECURE_IMPL (1UL << 31) + +/* SMMU_S_INIT register fields */ +#define SMMU_S_INIT_INV_ALL (1UL << 0) + +/* SMMU_S_GBPA register fields */ +#define SMMU_S_GBPA_UPDATE (1UL << 31) +#define SMMU_S_GBPA_ABORT (1UL << 20) + +int smmuv3_init(uintptr_t smmu_base); +int smmuv3_security_init(uintptr_t smmu_base); + +#endif /* SMMU_V3_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h b/arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h new file mode 100644 index 0000000..f8769e8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SP804_DELAY_TIMER_H +#define SP804_DELAY_TIMER_H + +#include + +#include + +uint32_t sp804_get_timer_value(void); + +void sp804_timer_ops_init(uintptr_t base_addr, const timer_ops_t *ops); + +#define sp804_timer_init(base_addr, clk_mult, clk_div) \ + do { \ + static const timer_ops_t sp804_timer_ops = { \ + sp804_get_timer_value, \ + (clk_mult), \ + (clk_div) \ + }; \ + sp804_timer_ops_init((base_addr), &sp804_timer_ops); \ + } while (0) + +#endif /* SP804_DELAY_TIMER_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/sp805.h b/arm-trusted-firmware/include/drivers/arm/sp805.h new file mode 100644 index 0000000..b00ede1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/sp805.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SP805_H +#define SP805_H + +#include + +/* SP805 register offset */ +#define SP805_WDOG_LOAD_OFF UL(0x000) +#define SP805_WDOG_CTR_OFF UL(0x008) +#define SP805_WDOG_LOCK_OFF UL(0xc00) + +/* Magic word to unlock the wd registers */ +#define WDOG_UNLOCK_KEY U(0x1ACCE551) + +/* Register field definitions */ +#define SP805_CTR_RESEN (U(1) << 1) +#define SP805_CTR_INTEN (U(1) << 0) + +#ifndef __ASSEMBLER__ + +#include + +/* Public high level API */ + +void sp805_start(uintptr_t base, unsigned int ticks); +void sp805_stop(uintptr_t base); +void sp805_refresh(uintptr_t base, unsigned int ticks); + +#endif /* __ASSEMBLER__ */ + +#endif /* SP805_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/tzc380.h b/arm-trusted-firmware/include/drivers/arm/tzc380.h new file mode 100644 index 0000000..9bd5f21 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc380.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC380_H +#define TZC380_H + +#include +#include + +#define TZC380_CONFIGURATION_OFF U(0x000) +#define ACTION_OFF U(0x004) +#define LOCKDOWN_RANGE_OFF U(0x008) +#define LOCKDOWN_SELECT_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) + +#define SPECULATION_CTRL_OFF U(0x030) +#define SECURITY_INV_EN_OFF U(0x034) + +#define REGION_SETUP_LOW_OFF(n) U(0x100 + (n) * 0x10) +#define REGION_SETUP_HIGH_OFF(n) U(0x104 + (n) * 0x10) +#define REGION_ATTRIBUTES_OFF(n) U(0x108 + (n) * 0x10) + +#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(0xf) + +#define ACTION_RV_SHIFT 0 +#define ACTION_RV_MASK U(0x3) +#define ACTION_RV_LOWOK U(0x0) +#define ACTION_RV_LOWERR U(0x1) +#define ACTION_RV_HIGHOK U(0x2) +#define ACTION_RV_HIGHERR U(0x3) + +/* Speculation is enabled by default. */ +#define SPECULATION_CTRL_WRITE_DISABLE BIT_32(1) +#define SPECULATION_CTRL_READ_DISABLE BIT_32(0) + +#define INT_STATUS_OVERRUN_SHIFT 1 +#define INT_STATUS_OVERRUN_MASK U(0x1) +#define INT_STATUS_STATUS_SHIFT 0 +#define INT_STATUS_STATUS_MASK U(0x1) + +#define INT_CLEAR_CLEAR_SHIFT 0 +#define INT_CLEAR_CLEAR_MASK U(0x1) + +#define TZC380_COMPONENT_ID U(0xb105f00d) +#define TZC380_PERIPH_ID_LOW U(0x001bb380) +#define TZC380_PERIPH_ID_HIGH U(0x00000004) + +#define TZC_SP_NS_W BIT_32(0) +#define TZC_SP_NS_R BIT_32(1) +#define TZC_SP_S_W BIT_32(2) +#define TZC_SP_S_R BIT_32(3) + +#define TZC_ATTR_SP_SHIFT 28 +#define TZC_ATTR_SP_ALL ((TZC_SP_S_W | TZC_SP_S_R | TZC_SP_NS_W | \ + TZC_SP_NS_R) << TZC_ATTR_SP_SHIFT) +#define TZC_ATTR_SP_S_RW ((TZC_SP_S_W | TZC_SP_S_R) << \ + TZC_ATTR_SP_SHIFT) +#define TZC_ATTR_SP_NS_RW ((TZC_SP_NS_W | TZC_SP_NS_R) << \ + TZC_ATTR_SP_SHIFT) + +#define TZC_REGION_SIZE_32K U(0xe) +#define TZC_REGION_SIZE_64K U(0xf) +#define TZC_REGION_SIZE_128K U(0x10) +#define TZC_REGION_SIZE_256K U(0x11) +#define TZC_REGION_SIZE_512K U(0x12) +#define TZC_REGION_SIZE_1M U(0x13) +#define TZC_REGION_SIZE_2M U(0x14) +#define TZC_REGION_SIZE_4M U(0x15) +#define TZC_REGION_SIZE_8M U(0x16) +#define TZC_REGION_SIZE_16M U(0x17) +#define TZC_REGION_SIZE_32M U(0x18) +#define TZC_REGION_SIZE_64M U(0x19) +#define TZC_REGION_SIZE_128M U(0x1a) +#define TZC_REGION_SIZE_256M U(0x1b) +#define TZC_REGION_SIZE_512M U(0x1c) +#define TZC_REGION_SIZE_1G U(0x1d) +#define TZC_REGION_SIZE_2G U(0x1e) +#define TZC_REGION_SIZE_4G U(0x1f) +#define TZC_REGION_SIZE_8G U(0x20) +#define TZC_REGION_SIZE_16G U(0x21) +#define TZC_REGION_SIZE_32G U(0x22) +#define TZC_REGION_SIZE_64G U(0x23) +#define TZC_REGION_SIZE_128G U(0x24) +#define TZC_REGION_SIZE_256G U(0x25) +#define TZC_REGION_SIZE_512G U(0x26) +#define TZC_REGION_SIZE_1T U(0x27) +#define TZC_REGION_SIZE_2T U(0x28) +#define TZC_REGION_SIZE_4T U(0x29) +#define TZC_REGION_SIZE_8T U(0x2a) +#define TZC_REGION_SIZE_16T U(0x2b) +#define TZC_REGION_SIZE_32T U(0x2c) +#define TZC_REGION_SIZE_64T U(0x2d) +#define TZC_REGION_SIZE_128T U(0x2e) +#define TZC_REGION_SIZE_256T U(0x2f) +#define TZC_REGION_SIZE_512T U(0x30) +#define TZC_REGION_SIZE_1P U(0x31) +#define TZC_REGION_SIZE_2P U(0x32) +#define TZC_REGION_SIZE_4P U(0x33) +#define TZC_REGION_SIZE_8P U(0x34) +#define TZC_REGION_SIZE_16P U(0x35) +#define TZC_REGION_SIZE_32P U(0x36) +#define TZC_REGION_SIZE_64P U(0x37) +#define TZC_REGION_SIZE_128P U(0x38) +#define TZC_REGION_SIZE_256P U(0x39) +#define TZC_REGION_SIZE_512P U(0x3a) +#define TZC_REGION_SIZE_1E U(0x3b) +#define TZC_REGION_SIZE_2E U(0x3c) +#define TZC_REGION_SIZE_4E U(0x3d) +#define TZC_REGION_SIZE_8E U(0x3e) +#define TZC_REGION_SIZE_16E U(0x3f) + +#define TZC_SUBREGION_DIS_SHIFT 0x8 +#define TZC_SUBREGION_DIS_MASK U(0xff) +#define TZC_ATTR_SUBREG_DIS(s) (((s) & TZC_SUBREGION_DIS_MASK) \ + << TZC_SUBREGION_DIS_SHIFT) + +#define TZC_REGION_SIZE_SHIFT 0x1 +#define TZC_REGION_SIZE_MASK U(0x7e) +#define TZC_ATTR_REGION_SIZE(s) ((s) << TZC_REGION_SIZE_SHIFT) + +#define TZC_ATTR_REGION_EN_SHIFT 0x0 +#define TZC_ATTR_REGION_EN_MASK U(0x1) + +#define TZC_ATTR_REGION_EN +#define TZC_ATTR_REGION_ENABLE U(0x1) +#define TZC_ATTR_REGION_DISABLE U(0x0) + +#define REGION_MAX 16 + +void tzc380_init(uintptr_t base); +void tzc380_configure_region(uint8_t region, + uintptr_t region_base, + unsigned int attr); +void tzc380_set_action(unsigned int action); +static inline void tzc_init(uintptr_t base) +{ + tzc380_init(base); +} + +static inline void tzc_configure_region(uint8_t region, + uintptr_t region_base, + unsigned int attr) +{ + tzc380_configure_region(region, region_base, attr); +} + +static inline void tzc_set_action(unsigned int action) +{ + tzc380_set_action(action); +} + +#endif /* TZC380_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/tzc400.h b/arm-trusted-firmware/include/drivers/arm/tzc400.h new file mode 100644 index 0000000..765c130 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc400.h @@ -0,0 +1,160 @@ +/* + * 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_update_filters(unsigned int region, unsigned int filters); +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/arm-trusted-firmware/include/drivers/arm/tzc_common.h b/arm-trusted-firmware/include/drivers/arm/tzc_common.h new file mode 100644 index 0000000..e58201c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h b/arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h new file mode 100644 index 0000000..cce074c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_DMC500_H +#define TZC_DMC500_H + +#include +#include + +#define SI_STATUS_OFFSET U(0x000) +#define SI_STATE_CTRL_OFFSET U(0x030) +#define SI_FLUSH_CTRL_OFFSET U(0x034) +#define SI_INT_CONTROL_OFFSET U(0x048) + +#define SI_INT_STATUS_OFFSET U(0x004) +#define SI_TZ_FAIL_ADDRESS_LOW_OFFSET U(0x008) +#define SI_TZ_FAIL_ADDRESS_HIGH_OFFSET U(0x00c) +#define SI_FAIL_CONTROL_OFFSET U(0x010) +#define SI_FAIL_ID_OFFSET U(0x014) +#define SI_INT_CLR_OFFSET U(0x04c) + +/* + * DMC-500 has 2 system interfaces each having a similar set of regs + * to configure each interface. + */ +#define SI0_BASE U(0x0000) +#define SI1_BASE U(0x0200) + +/* Bit positions of SIx_SI_STATUS */ +#define SI_EMPTY_SHIFT 1 +#define SI_STALL_ACK_SHIFT 0 +#define SI_EMPTY_MASK U(0x01) +#define SI_STALL_ACK_MASK U(0x01) + +/* Bit positions of SIx_SI_INT_STATUS */ +#define PMU_REQ_INT_OVERFLOW_STATUS_SHIFT 18 +#define FAILED_ACCESS_INT_OVERFLOW_STATUS_SHIFT 16 +#define PMU_REQ_INT_STATUS_SHIFT 2 +#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_SHIFT 1 +#define FAILED_ACCESS_INT_STATUS_SHIFT 0 +#define PMU_REQ_INT_OVERFLOW_STATUS_MASK U(0x1) +#define FAILED_ACCESS_INT_OVERFLOW_STATUS_MASK U(0x1) +#define PMU_REQ_INT_STATUS_MASK U(0x1) +#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_MASK U(0x1) +#define FAILED_ACCESS_INT_STATUS_MASK U(0x1) + +/* Bit positions of SIx_TZ_FAIL_CONTROL */ +#define DIRECTION_SHIFT 24 +#define NON_SECURE_SHIFT 21 +#define PRIVILEGED_SHIFT 20 +#define FAILED_ACCESS_INT_INFO_RANK_MASKED_SHIFT 3 +#define FAILED_ACCESS_INT_INFO_UNMAPPED_SHIFT 2 +#define FAILED_ACCESS_INT_TZ_FAIL_SHIFT 1 +#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_SHIFT 0 +#define DIRECTION_MASK U(0x1) +#define NON_SECURE_MASK U(0x1) +#define PRIVILEGED_MASK U(0x1) +#define FAILED_ACCESS_INT_INFO_RANK_MASKED_MASK U(0x1) +#define FAILED_ACCESS_INT_INFO_UNMAPPED_MASK U(0x1) +#define FAILED_ACCESS_INT_TZ_FAIL_MASK U(0x1) +#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_MASK U(0x1) + +/* Bit positions of SIx_FAIL_STATUS */ +#define FAIL_ID_VNET_SHIFT 24 +#define FAIL_ID_ID_SHIFT 0 +#define FAIL_ID_VNET_MASK U(0xf) +#define FAIL_ID_ID_MASK U(0xffffff) + +/* Bit positions of SIx_SI_STATE_CONTRL */ +#define SI_STALL_REQ_GO 0x0 +#define SI_STALL_REQ_STALL 0x1 + +/* Bit positions of SIx_SI_FLUSH_CONTROL */ +#define SI_FLUSH_REQ_INACTIVE 0x0 +#define SI_FLUSH_REQ_ACTIVE 0x1 +#define SI_FLUSH_REQ_MASK 0x1 + +/* Bit positions of SIx_SI_INT_CONTROL */ +#define PMU_REQ_INT_EN_SHIFT 2 +#define OVERLAP_DETECT_INT_EN_SHIFT 1 +#define FAILED_ACCESS_INT_EN_SHIFT 0 +#define PMU_REQ_INT_EN_MASK U(0x1) +#define OVERLAP_DETECT_INT_EN_MASK U(0x1) +#define FAILED_ACCESS_INT_EN_MASK U(0x1) +#define PMU_REQ_INT_EN U(0x1) +#define OVERLAP_DETECT_INT_EN U(0x1) +#define FAILED_ACCESS_INT_EN U(0x1) + +/* Bit positions of SIx_SI_INT_CLR */ +#define PMU_REQ_OFLOW_CLR_SHIFT 18 +#define FAILED_ACCESS_OFLOW_CLR_SHIFT 16 +#define PMU_REQ_INT_CLR_SHIFT 2 +#define FAILED_ACCESS_INT_CLR_SHIFT 0 +#define PMU_REQ_OFLOW_CLR_MASK U(0x1) +#define FAILED_ACCESS_OFLOW_CLR_MASK U(0x1) +#define PMU_REQ_INT_CLR_MASK U(0x1) +#define FAILED_ACCESS_INT_CLR_MASK U(0x1) +#define PMU_REQ_OFLOW_CLR U(0x1) +#define FAILED_ACCESS_OFLOW_CLR U(0x1) +#define PMU_REQ_INT_CLR U(0x1) +#define FAILED_ACCESS_INT_CLR U(0x1) + +/* Macro to get the correct base register for a system interface */ +#define IFACE_OFFSET(sys_if) ((sys_if) ? SI1_BASE : SI0_BASE) + +#define MAX_SYS_IF_COUNT U(2) +#define MAX_REGION_VAL 8 + +/* DMC-500 supports striping across a max of 4 DMC instances */ +#define MAX_DMC_COUNT 4 + +/* Consist of part_number_1 and part_number_0 */ +#define DMC500_PERIPHERAL_ID U(0x0450) + +/* Filter enable bits in a TZC */ +#define TZC_DMC500_REGION_ATTR_F_EN_MASK U(0x1) + +/* Length of registers for configuring each region */ +#define TZC_DMC500_REGION_SIZE U(0x018) + +#ifndef __ASSEMBLER__ + +#include + +/* + * Contains the base addresses of all the DMC instances. + */ +typedef struct tzc_dmc500_driver_data { + uintptr_t dmc_base[MAX_DMC_COUNT]; + int dmc_count; + unsigned int sys_if_count; +} tzc_dmc500_driver_data_t; + +void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data); +void tzc_dmc500_configure_region0(unsigned int sec_attr, + unsigned int nsaid_permissions); +void tzc_dmc500_configure_region(unsigned int region_no, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int nsaid_permissions); +void tzc_dmc500_set_action(unsigned int action); +void tzc_dmc500_config_complete(void); +int tzc_dmc500_verify_complete(void); + + +#endif /* __ASSEMBLER__ */ +#endif /* TZC_DMC500_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h b/arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h new file mode 100644 index 0000000..26c444d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_DMC620_H +#define TZC_DMC620_H + +#include + +/* DMC-620 memc register offsets */ +#define DMC620_MEMC_STATUS U(0x0000) +#define DMC620_MEMC_CMD U(0x0008) + +/* Mask value to check the status of memc_cmd register */ +#define DMC620_MEMC_CMD_MASK U(0x00000007) + +/* memc_cmd register's action values */ +#define DMC620_MEMC_CMD_GO U(0x00000003) +#define DMC620_MEMC_CMD_EXECUTE U(0x00000004) + +/* Address offsets of access address next region 0 registers */ +#define DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE U(0x0080) +#define DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE U(0x0084) +#define DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE U(0x0088) +#define DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE U(0x008c) + +/* Length of one block of access address next register region */ +#define DMC620_ACC_ADDR_NEXT_SIZE U(0x0010) + +/* Address offsets of access address next registers */ +#define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no) \ + (DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE + \ + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no) \ + (DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE + \ + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no) \ + (DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE + \ + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no) \ + (DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE + \ + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) + +/* Number of TZC address regions in DMC-620 */ +#define DMC620_ACC_ADDR_COUNT U(8) +/* Width of access address registers */ +#define DMC620_ACC_ADDR_WIDTH U(32) + +/* Peripheral ID registers offsets */ +#define DMC620_PERIPHERAL_ID_0 U(0x1fe0) + +/* Default values in id registers */ +#define DMC620_PERIPHERAL_ID_0_VALUE U(0x00000054) + +/* Secure access region attributes. */ +#define TZC_DMC620_REGION_NS_RD U(0x00000001) +#define TZC_DMC620_REGION_NS_WR U(0x00000002) +#define TZC_DMC620_REGION_NS_RDWR \ + (TZC_DMC620_REGION_NS_RD | TZC_DMC620_REGION_NS_WR) +#define TZC_DMC620_REGION_S_RD U(0x00000004) +#define TZC_DMC620_REGION_S_WR U(0x00000008) +#define TZC_DMC620_REGION_S_RDWR \ + (TZC_DMC620_REGION_S_RD | TZC_DMC620_REGION_S_WR) +#define TZC_DMC620_REGION_S_NS_RDWR \ + (TZC_DMC620_REGION_NS_RDWR | TZC_DMC620_REGION_S_RDWR) + +/* + * Contains pointer to the base addresses of all the DMC-620 instances. + * 'dmc_count' specifies the number of DMC base addresses contained in the + * array pointed to by dmc_base. + */ +typedef struct tzc_dmc620_driver_data { + const uintptr_t *dmc_base; + const unsigned int dmc_count; +} tzc_dmc620_driver_data_t; + +/* + * Contains region base, region top addresses and corresponding attributes + * for configuring TZC access region registers. + */ +typedef struct tzc_dmc620_acc_addr_data { + const unsigned long long region_base; + const unsigned long long region_top; + const unsigned int sec_attr; +} tzc_dmc620_acc_addr_data_t; + +/* + * Contains platform specific data for configuring TZC region base and + * region top address. 'acc_addr_count' specifies the number of + * valid entries in 'plat_acc_addr_data' array. + */ +typedef struct tzc_dmc620_config_data { + const tzc_dmc620_driver_data_t *plat_drv_data; + const tzc_dmc620_acc_addr_data_t *plat_acc_addr_data; + const uint8_t acc_addr_count; +} tzc_dmc620_config_data_t; + +/* Function prototypes */ +void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data); + +#endif /* TZC_DMC620_H */ + diff --git a/arm-trusted-firmware/include/drivers/auth/auth_common.h b/arm-trusted-firmware/include/drivers/auth/auth_common.h new file mode 100644 index 0000000..e6859fd --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/auth/auth_mod.h b/arm-trusted-firmware/include/drivers/auth/auth_mod.h new file mode 100644 index 0000000..94537f6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/auth_mod.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AUTH_MOD_H +#define AUTH_MOD_H + +#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 */ +#if TRUSTED_BOARD_BOOT +void auth_mod_init(void); +#else +static inline void auth_mod_init(void) +{ +} +#endif /* TRUSTED_BOARD_BOOT */ +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 /* AUTH_MOD_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/crypto_mod.h b/arm-trusted-firmware/include/drivers/auth/crypto_mod.h new file mode 100644 index 0000000..73b2b99 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/crypto_mod.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015-2022, 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 +}; + +/* Message digest algorithm */ +enum crypto_md_algo { + CRYPTO_MD_SHA256, + CRYPTO_MD_SHA384, + CRYPTO_MD_SHA512, +}; + +/* Maximum size as per the known stronger hash algorithm i.e.SHA512 */ +#define CRYPTO_MD_MAX_SIZE 64U + +/* + * 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)(enum crypto_md_algo md_alg, void *data_ptr, + unsigned int data_len, + unsigned char output[CRYPTO_MD_MAX_SIZE]); +#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 */ +#if CRYPTO_SUPPORT +void crypto_mod_init(void); +#else +static inline void crypto_mod_init(void) +{ +} +#endif /* CRYPTO_SUPPORT */ + +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(enum crypto_md_algo alg, void *data_ptr, + unsigned int data_len, + unsigned char output[CRYPTO_MD_MAX_SIZE]); +#endif /* MEASURED_BOOT */ + +#if MEASURED_BOOT && TRUSTED_BOARD_BOOT +/* 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 \ + } +#elif TRUSTED_BOARD_BOOT +#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 \ + } +#elif MEASURED_BOOT +#define REGISTER_CRYPTO_LIB(_name, _init, _calc_hash) \ + const crypto_lib_desc_t crypto_lib_desc = { \ + .name = _name, \ + .init = _init, \ + .calc_hash = _calc_hash, \ + } +#endif /* MEASURED_BOOT && TRUSTED_BOARD_BOOT */ + +extern const crypto_lib_desc_t crypto_lib_desc; + +#endif /* CRYPTO_MOD_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/img_parser_mod.h b/arm-trusted-firmware/include/drivers/auth/img_parser_mod.h new file mode 100644 index 0000000..b2fb60e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h b/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h new file mode 100644 index 0000000..a9c2352 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MBEDTLS_COMMON_H +#define MBEDTLS_COMMON_H + +void mbedtls_init(void); + +#endif /* MBEDTLS_COMMON_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h b/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h new file mode 100644 index 0000000..8ad6d7a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* + * Key algorithms currently supported on mbed TLS libraries + */ +#define TF_MBEDTLS_RSA 1 +#define TF_MBEDTLS_ECDSA 2 +#define TF_MBEDTLS_RSA_AND_ECDSA 3 + +#define TF_MBEDTLS_USE_RSA (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA \ + || TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA) +#define TF_MBEDTLS_USE_ECDSA (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA \ + || TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA) + +/* + * Hash algorithms currently supported on mbed TLS libraries + */ +#define TF_MBEDTLS_SHA256 1 +#define TF_MBEDTLS_SHA384 2 +#define TF_MBEDTLS_SHA512 3 + +/* + * Configuration file to build mbed TLS with the required features for + * Trusted Boot + */ + +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +/* Prevent mbed TLS from using snprintf so that it can use tf_snprintf. */ +#define MBEDTLS_PLATFORM_SNPRINTF_ALT + +#define MBEDTLS_PKCS1_V21 + +#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#define MBEDTLS_X509_CHECK_KEY_USAGE +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C + +#define MBEDTLS_BASE64_C +#define MBEDTLS_BIGNUM_C + +#define MBEDTLS_ERROR_C +#define MBEDTLS_MD_C + +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_OID_C + +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C + +#define MBEDTLS_PLATFORM_C + +#if TF_MBEDTLS_USE_ECDSA +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_NO_INTERNAL_RNG +#endif +#if TF_MBEDTLS_USE_RSA +#define MBEDTLS_RSA_C +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT +#endif + +#define MBEDTLS_SHA256_C + +/* + * If either Trusted Boot or Measured Boot require a stronger algorithm than + * SHA-256, pull in SHA-512 support. + */ +#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256) /* TBB hash algo */ +#define MBEDTLS_SHA512_C +#else + /* TBB uses SHA-256, what about measured boot? */ +#if defined(TF_MBEDTLS_TPM_HASH_ALG_ID) && \ + (TF_MBEDTLS_TPM_HASH_ALG_ID != TF_MBEDTLS_SHA256) +#define MBEDTLS_SHA512_C +#endif +#endif + +#define MBEDTLS_VERSION_C + +#define MBEDTLS_X509_USE_C +#define MBEDTLS_X509_CRT_PARSE_C + +#if TF_MBEDTLS_USE_AES_GCM +#define MBEDTLS_AES_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_GCM_C +#endif + +/* MPI / BIGNUM options */ +#define MBEDTLS_MPI_WINDOW_SIZE 2 + +#if TF_MBEDTLS_USE_RSA +#if TF_MBEDTLS_KEY_SIZE <= 2048 +#define MBEDTLS_MPI_MAX_SIZE 256 +#else +#define MBEDTLS_MPI_MAX_SIZE 512 +#endif +#else +#define MBEDTLS_MPI_MAX_SIZE 256 +#endif + +/* Memory buffer allocator options */ +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 8 + +/* + * Prevent the use of 128-bit division which + * creates dependency on external libraries. + */ +#define MBEDTLS_NO_UDBL_DIVISION + +#ifndef __ASSEMBLER__ +/* System headers required to build mbed TLS with the current configuration */ +#include +#include +#endif + +/* + * Determine Mbed TLS heap size + * 13312 = 13*1024 + * 11264 = 11*1024 + * 7168 = 7*1024 + */ +#if TF_MBEDTLS_USE_ECDSA +#define TF_MBEDTLS_HEAP_SIZE U(13312) +#elif TF_MBEDTLS_USE_RSA +#if TF_MBEDTLS_KEY_SIZE <= 2048 +#define TF_MBEDTLS_HEAP_SIZE U(7168) +#else +#define TF_MBEDTLS_HEAP_SIZE U(11264) +#endif +#endif + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h b/arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h new file mode 100644 index 0000000..a51faee --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/brcm/chimp.h b/arm-trusted-firmware/include/drivers/brcm/chimp.h new file mode 100644 index 0000000..02d528b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/chimp.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SR_CHIMP_H +#define SR_CHIMP_H + +#include +#include +#include + +#include + +#define CHIMP_WINDOW_SIZE 0x400000 +#define CHIMP_ERROR_OFFSET 28 +#define CHIMP_ERROR_MASK 0xf0000000 + +#ifndef EMULATION_SETUP +#define CHIMP_HANDSHAKE_TIMEOUT_MS 10000 +#else +/* + * 1hr timeout for test in emulator + * By doing this ChiMP is given a chance to boot + * fully from the QSPI + * (on Palladium this takes upto 50 min depending on QSPI clk) + */ + +#define CHIMP_HANDSHAKE_TIMEOUT_MS 3600000 +#endif + +#define CHIMP_BPE_MODE_ID_PATTERN (0x25000000) +#define CHIMP_BPE_MODE_ID_MASK (0x7f000000) +#define NIC_RESET_RELEASE_TIMEOUT_US (10) + +/* written by M0, used by ChiMP ROM */ +#define SR_IN_SMARTNIC_MODE_BIT 0 +/* written by M0, used by ChiMP ROM */ +#define SR_CHIMP_SECURE_BOOT_BIT 1 +/* cleared by AP, set by ChiMP BC2 code */ +#define SR_FLASH_ACCESS_DONE_BIT 2 + +#ifdef USE_CHIMP +void bcm_chimp_write(uintptr_t addr, uint32_t value); +uint32_t bcm_chimp_read(uintptr_t addr); +uint32_t bcm_chimp_read_ctrl(uint32_t offset); +void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits); +void bcm_chimp_setbits(uintptr_t addr, uint32_t bits); +int bcm_chimp_is_nic_mode(void); +void bcm_chimp_fru_prog_done(bool status); +int bcm_chimp_handshake_done(void); +int bcm_chimp_wait_handshake(void); +/* Fastboot-related*/ +int bcm_chimp_initiate_fastboot(int fastboot_type); +#else +static inline void bcm_chimp_write(uintptr_t addr, uint32_t value) +{ +} +static inline uint32_t bcm_chimp_read(uintptr_t addr) +{ + return 0; +} +static inline uint32_t bcm_chimp_read_ctrl(uint32_t offset) +{ + return 0; +} +static inline void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits) +{ +} +static inline void bcm_chimp_setbits(uintptr_t addr, uint32_t bits) +{ +} +static inline int bcm_chimp_is_nic_mode(void) +{ + return 0; +} +static inline void bcm_chimp_fru_prog_done(bool status) +{ +} +static inline int bcm_chimp_handshake_done(void) +{ + return 0; +} +static inline int bcm_chimp_wait_handshake(void) +{ + return 0; +} +static inline int bcm_chimp_initiate_fastboot(int fastboot_type) +{ + return 0; +} +#endif /* USE_CHIMP */ +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h b/arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h new file mode 100644 index 0000000..9be361f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BNXNVM_DEFS_H +#define BNXNVM_DEFS_H + +#if defined(__GNUC__) + #define PACKED_STRUCT __packed +#else /* non-GCC compiler */ + +#ifndef DOS_DRIVERS + #pragma pack(push) + #pragma pack(1) +#endif + #define PACKED_STRUCT +#endif + +typedef uint32_t u32_t; +typedef uint8_t u8_t; +typedef uint16_t u16_t; + +#define BNXNVM_DEFAULT_BLOCK_SIZE 4096 +#define BNXNVM_UNUSED_BYTE_VALUE 0xff + +#define NV_MAX_BLOCK_SIZE 16384 + +#define BITS_PER_BYTE (8) +#define SIZEOF_IN_BITS(x) (sizeof(x)*BITS_PER_BYTE) + +/************************/ +/* byte-swapping macros */ +/************************/ +#define BYTE_SWAP_16(x) \ + ((((u16_t)(x) & 0xff00) >> 8) | \ + (((u16_t)(x) & 0x00ff) << 8)) +#define BYTE_SWAP_32(x) \ + ((((u32_t)(x) & 0xff000000) >> 24) | \ + (((u32_t)(x) & 0x00ff0000) >> 8) | \ + (((u32_t)(x) & 0x0000ff00) << 8) | \ + (((u32_t)(x) & 0x000000ff) << 24)) + +/* auto-detect integer size */ +#define BYTE_SWAP_INT(x) \ + (SIZEOF_IN_BITS(x) == 16 ? BYTE_SWAP_16(x) : \ + SIZEOF_IN_BITS(x) == 32 ? BYTE_SWAP_32(x) : (x)) + +/********************************/ +/* Architecture-specific macros */ +/********************************/ +#ifdef __BIG_ENDIAN__ /* e.g. Motorola */ + + #define BE_INT16(x) (x) + #define BE_INT32(x) (x) + #define BE_INT(x) (x) + #define LE_INT16(x) BYTE_SWAP_16(x) + #define LE_INT32(x) BYTE_SWAP_32(x) + #define LE_INT(x) BYTE_SWAP_INT(x) + +#else /* Little Endian (e.g. Intel) */ + + #define LE_INT16(x) (x) + #define LE_INT32(x) (x) + #define LE_INT(x) (x) + #define BE_INT16(x) BYTE_SWAP_16(x) + #define BE_INT32(x) BYTE_SWAP_32(x) + #define BE_INT(x) BYTE_SWAP_INT(x) + +#endif + + +enum { + NV_OK = 0, + NV_NOT_NVRAM, + NV_BAD_MB, + NV_BAD_DIR_HEADER, + NV_BAD_DIR_ENTRY, + NV_FW_NOT_FOUND, +}; + +typedef struct { +#define BNXNVM_MASTER_BLOCK_SIG BE_INT32(0x424E5834) /*"BNX4"*/ + /* Signature*/ + u32_t sig; + /* Length of Master Block Header, in bytes [32] */ + u32_t length; + /* Block size, in bytes [4096] */ + u32_t block_size; + /* Byte-offset to Directory Block (translated) */ + u32_t directory_offset; + /* Byte-offset to Block Redirection Table (non-translated) */ + u32_t redirect_offset; + /* Size, in bytes of Reserved Blocks region (at end of NVRAM) */ + u32_t reserved_size; + /* + * Size of NVRAM (in bytes) - may be used to + * override auto-detected size + */ + u32_t nvram_size; + /* CRC-32 (IEEE 802.3 compatible) of the above */ + u32_t chksum; +} PACKED_STRUCT bnxnvm_master_block_header_t; + +typedef struct { +#define BNXNVM_DIRECTORY_BLOCK_SIG BE_INT32(0x44697230) /* "Dir0" */ + /* Signature */ + u32_t sig; + /* Length of Directory Header, in bytes [16] */ + u32_t length; + /* Number of Directory Entries */ + u32_t entries; + /* Length of each Directory Entry, in bytes [24] */ + u32_t entry_length; +} PACKED_STRUCT bnxnvm_directory_block_header_t; + +typedef struct { + /* Directory Entry Type (see enum bnxnvm_directory_type) */ + u16_t type; + /* Instance of this Directory Entry type (0-based) */ + u16_t ordinal; + /* + * Directory Entry Extension flags used to identify + * secondary instances of a type:ordinal combinations + */ + u16_t ext; + /* Directory Entry Attribute flags used to describe the item contents */ + u16_t attr; + /* Item location in NVRAM specified as offset (in bytes) */ + u32_t item_location; + /* + * Length of NVRAM item in bytes + * (including padding - multiple of block size) + */ + u32_t item_length; + /* Length of item data in bytes (excluding padding) */ + u32_t data_length; + /* + * CRC-32 (IEEE 802.3 compatible) of item data + * (excluding padding) (optional) + */ + u32_t data_chksum; +} PACKED_STRUCT bnxnvm_directory_entry_t; + +enum bnxnvm_version_format { + /* US-ASCII string (not necessarily null-terminated) */ + BNX_VERSION_FMT_ASCII = 0, + /* Each field 16-bits, displayed as unpadded decimal (e.g. "1.2.3.4") */ + BNX_VERSION_FMT_DEC = 1, + /* A single hexadecimal value, up to 64-bits (no dots) */ + BNX_VERSION_FMT_HEX = 2, + /* Multiple version values (three 8-bit version fields) */ + BNX_VERSION_FMT_MULTI = 3 +}; + +/* This structure definition must not change: */ +typedef struct { + u16_t flags; /* bit-flags (defaults to 0x0000) */ + u8_t version_format; /* enum bnxnvm_version_format */ + u8_t version_length; /* in bytes */ + u8_t version[16]; /* version value */ + u16_t dir_type; /* enum bnxnvm_directory_type */ + /* size of the entire trailer (to locate end of component data) */ + u16_t trailer_length; +#define BNXNVM_COMPONENT_TRAILER_SIG BE_INT32(0x54726c72) /* "Trlr" */ + u32_t sig; + u32_t chksum; /* CRC-32 of all bytes to this point */ +} PACKED_STRUCT bnxnvm_component_trailer_base_t; + +typedef struct { + /* + * new trailer members (e.g. digital signature) + * go here (insert at top): + */ + u8_t rsa_sig[256]; /* 2048-bit RSA-encrypted SHA-256 hash */ + bnxnvm_component_trailer_base_t base; +} PACKED_STRUCT bnxnvm_component_trailer_t; + +#define BNX_MAX_LEN_DIR_NAME 12 +#define BNX_MAX_LEN_DIR_DESC 50 +/********************************************************* + * NVRAM Directory Entry/Item Types, Names, and Descriptions + * + * If you see a name or description that needs improvement, + * please correct it or raise for discussion. + * When adding a new directory type, it would be appreciated + * if you also updated ../../libs/nvm/bnxt_nvm_str.c. + * DIR_NAME macros may contain up to 12 alpha-numeric + * US-ASCII characters only, camelCase is preferred for clarity. + * DIR_DESC macros may contain up to 50 US-ASCII characters + * providing a verbose description of the directory type. + */ +enum bnxnvm_directory_type { + /* 0x00 Unused directory entry, available for use */ + BNX_DIR_TYPE_UNUSED = 0, +#define BNX_DIR_NAME_UNUSED "unused" +#define BNX_DIR_DESC_UNUSED "Deleted directory entry, available for reuse" + /* 0x01 Package installation log */ + BNX_DIR_TYPE_PKG_LOG = 1, +#define BNX_DIR_NAME_PKG_LOG "pkgLog" +#define BNX_DIR_DESC_PKG_LOG "Package Installation Log" + BNX_DIR_TYPE_CHIMP_PATCH = 3, +#define BNX_DIR_NAME_CHIMP_PATCH "chimpPatch" +#define BNX_DIR_DESC_CHIMP_PATCH "ChiMP Patch Firmware" + /* 0x04 ChiMP firmware: Boot Code phase 1 */ + BNX_DIR_TYPE_BOOTCODE = 4, +#define BNX_DIR_NAME_BOOTCODE "chimpBoot" +#define BNX_DIR_DESC_BOOTCODE "Chip Management Processor Boot Firmware" + /* 0x05 VPD data block */ + BNX_DIR_TYPE_VPD = 5, +#define BNX_DIR_NAME_VPD "VPD" +#define BNX_DIR_DESC_VPD "Vital Product Data" + /* 0x06 Exp ROM MBA */ + BNX_DIR_TYPE_EXP_ROM_MBA = 6, +#define BNX_DIR_NAME_EXP_ROM_MBA "MBA" +#define BNX_DIR_DESC_EXP_ROM_MBA "Multiple Boot Agent Expansion ROM" + BNX_DIR_TYPE_AVS = 7, /* 0x07 AVS FW */ +#define BNX_DIR_NAME_AVS "AVS" +#define BNX_DIR_DESC_AVS "Adaptive Voltage Scaling Firmware" + BNX_DIR_TYPE_PCIE = 8, /* 0x08 PCIE FW */ +#define BNX_DIR_NAME_PCIE "PCIEucode" +#define BNX_DIR_DESC_PCIE "PCIe Microcode" + BNX_DIR_TYPE_PORT_MACRO = 9, /* 0x09 PORT MACRO FW */ +#define BNX_DIR_NAME_PORT_MACRO "portMacro" +#define BNX_DIR_DESC_PORT_MACRO "Port Macro Firmware" + BNX_DIR_TYPE_APE_FW = 10, /* 0x0A APE Firmware */ +#define BNX_DIR_NAME_APE_FW "apeFW" +#define BNX_DIR_DESC_APE_FW "Application Processing Engine Firmware" + /* 0x0B Patch firmware executed by APE ROM */ + BNX_DIR_TYPE_APE_PATCH = 11, +#define BNX_DIR_NAME_APE_PATCH "apePatch" +#define BNX_DIR_DESC_APE_PATCH "APE Patch Firmware" + BNX_DIR_TYPE_KONG_FW = 12, /* 0x0C Kong Firmware */ +#define BNX_DIR_NAME_KONG_FW "kongFW" +#define BNX_DIR_DESC_KONG_FW "Kong Firmware" + /* 0x0D Patch firmware executed by Kong ROM */ + BNX_DIR_TYPE_KONG_PATCH = 13, +#define BNX_DIR_NAME_KONG_PATCH "kongPatch" +#define BNX_DIR_DESC_KONG_PATCH "Kong Patch Firmware" + BNX_DIR_TYPE_BONO_FW = 14, /* 0x0E Bono Firmware */ +#define BNX_DIR_NAME_BONO_FW "bonoFW" +#define BNX_DIR_DESC_BONO_FW "Bono Firmware" + /* 0x0F Patch firmware executed by Bono ROM */ + BNX_DIR_TYPE_BONO_PATCH = 15, +#define BNX_DIR_NAME_BONO_PATCH "bonoPatch" +#define BNX_DIR_DESC_BONO_PATCH "Bono Patch Firmware" + BNX_DIR_TYPE_TANG_FW = 16, /* 0x10 Tang firmware */ +#define BNX_DIR_NAME_TANG_FW "tangFW" +#define BNX_DIR_DESC_TANG_FW "Tang Firmware" + /* 0x11 Patch firmware executed by Tang ROM */ + BNX_DIR_TYPE_TANG_PATCH = 17, +#define BNX_DIR_NAME_TANG_PATCH "tangPatch" +#define BNX_DIR_DESC_TANG_PATCH "Tang Patch Firmware" + /* 0x12 ChiMP firmware: Boot Code phase 2 (loaded by phase 1) */ + BNX_DIR_TYPE_BOOTCODE_2 = 18, +#define BNX_DIR_NAME_BOOTCODE_2 "chimpHWRM" +#define BNX_DIR_DESC_BOOTCODE_2 "ChiMP Hardware Resource Manager Firmware" + BNX_DIR_TYPE_CCM = 19, /* 0x13 CCM ROM binary */ +#define BNX_DIR_NAME_CCM "CCM" +#define BNX_DIR_DESC_CCM "Comprehensive Configuration Management" + /* 0x14 PCI-IDs, PCI-related configuration properties */ + BNX_DIR_TYPE_PCI_CFG = 20, +#define BNX_DIR_NAME_PCI_CFG "pciCFG" +#define BNX_DIR_DESC_PCI_CFG "PCIe Configuration Data" + + BNX_DIR_TYPE_TSCF_UCODE = 21, /* 0x15 TSCF micro-code */ +#define BNX_DIR_NAME_TSCF_UCODE "PHYucode" +#define BNX_DIR_DESC_TSCF_UCODE "Falcon PHY Microcode" + BNX_DIR_TYPE_ISCSI_BOOT = 22, /* 0x16 iSCSI Boot */ +#define BNX_DIR_NAME_ISCSI_BOOT "iSCSIboot" +#define BNX_DIR_DESC_ISCSI_BOOT "iSCSI Boot Software Initiator" + /* 0x18 iSCSI Boot IPV6 - ***DEPRECATED*** */ + BNX_DIR_TYPE_ISCSI_BOOT_IPV6 = 24, + /* 0x19 iSCSI Boot IPV4N6 - ***DEPRECATED*** */ + BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6 = 25, + BNX_DIR_TYPE_ISCSI_BOOT_CFG = 26, /* 0x1a iSCSI Boot CFG v6 */ +#define BNX_DIR_NAME_ISCSI_BOOT_CFG "iSCSIcfg" +#define BNX_DIR_DESC_ISCSI_BOOT_CFG "iSCSI Boot Configuration Data" + BNX_DIR_TYPE_EXT_PHY = 27, /* 0x1b External PHY FW */ +#define BNX_DIR_NAME_EXT_PHY "extPHYfw" +#define BNX_DIR_DESC_EXT_PHY "External PHY Firmware" + BNX_DIR_TYPE_MODULES_PN = 28, /* 0x1c Modules PartNum list */ +#define BNX_DIR_NAME_MODULES_PN "modPartNums" +#define BNX_DIR_DESC_MODULES_PN "Optical Modules Part Number List" + BNX_DIR_TYPE_SHARED_CFG = 40, /* 0x28 shared configuration block */ +#define BNX_DIR_NAME_SHARED_CFG "sharedCFG" +#define BNX_DIR_DESC_SHARED_CFG "Shared Configuration Data" + BNX_DIR_TYPE_PORT_CFG = 41, /* 0x29 port configuration block */ +#define BNX_DIR_NAME_PORT_CFG "portCFG" +#define BNX_DIR_DESC_PORT_CFG "Port Configuration Data" + BNX_DIR_TYPE_FUNC_CFG = 42, /* 0x2A func configuration block */ +#define BNX_DIR_NAME_FUNC_CFG "funcCFG" +#define BNX_DIR_DESC_FUNC_CFG "Function Configuration Data" + + /* Management Firmware (TruManage) related dir entries*/ + /* 0x30 Management firmware configuration (see BMCFG library)*/ + BNX_DIR_TYPE_MGMT_CFG = 48, +#define BNX_DIR_NAME_MGMT_CFG "mgmtCFG" +#define BNX_DIR_DESC_MGMT_CFG "Out-of-band Management Configuration Data" + BNX_DIR_TYPE_MGMT_DATA = 49, /* 0x31 "Opaque Management Data" */ +#define BNX_DIR_NAME_MGMT_DATA "mgmtData" +#define BNX_DIR_DESC_MGMT_DATA "Out-of-band Management Data" + BNX_DIR_TYPE_MGMT_WEB_DATA = 50, /* 0x32 "Web GUI" file data */ +#define BNX_DIR_NAME_MGMT_WEB_DATA "webData" +#define BNX_DIR_DESC_MGMT_WEB_DATA "Out-of-band Management Web Data" + /* 0x33 "Web GUI" file metadata */ + BNX_DIR_TYPE_MGMT_WEB_META = 51, +#define BNX_DIR_NAME_MGMT_WEB_META "webMeta" +#define BNX_DIR_DESC_MGMT_WEB_META "Out-of-band Management Web Metadata" + /* 0x34 Management firmware Event Log (a.k.a. "SEL") */ + BNX_DIR_TYPE_MGMT_EVENT_LOG = 52, +#define BNX_DIR_NAME_MGMT_EVENT_LOG "eventLog" +#define BNX_DIR_DESC_MGMT_EVENT_LOG "Out-of-band Management Event Log" + /* 0x35 Management firmware Audit Log */ + BNX_DIR_TYPE_MGMT_AUDIT_LOG = 53 +#define BNX_DIR_NAME_MGMT_AUDIT_LOG "auditLog" +#define BNX_DIR_DESC_MGMT_AUDIT_LOG "Out-of-band Management Audit Log" + +}; + +/* For backwards compatibility only, may be removed later */ +#define BNX_DIR_TYPE_ISCSI_BOOT_CFG6 BNX_DIR_TYPE_ISCSI_BOOT_CFG + +/* Firmware NVM items of "APE BIN" format are identified with + * the following macro: + */ +#define BNX_DIR_TYPE_IS_APE_BIN_FMT(type)\ + ((type) == BNX_DIR_TYPE_CHIMP_PATCH \ + || (type) == BNX_DIR_TYPE_BOOTCODE \ + || (type) == BNX_DIR_TYPE_BOOTCODE_2 \ + || (type) == BNX_DIR_TYPE_APE_FW \ + || (type) == BNX_DIR_TYPE_APE_PATCH \ + || (type) == BNX_DIR_TYPE_TANG_FW \ + || (type) == BNX_DIR_TYPE_TANG_PATCH \ + || (type) == BNX_DIR_TYPE_KONG_FW \ + || (type) == BNX_DIR_TYPE_KONG_PATCH \ + || (type) == BNX_DIR_TYPE_BONO_FW \ + || (type) == BNX_DIR_TYPE_BONO_PATCH \ + ) + +/* Other (non APE BIN) executable NVM items are identified with + * the following macro: + */ +#define BNX_DIR_TYPE_IS_OTHER_EXEC(type)\ + ((type) == BNX_DIR_TYPE_AVS \ + || (type) == BNX_DIR_TYPE_EXP_ROM_MBA \ + || (type) == BNX_DIR_TYPE_PCIE \ + || (type) == BNX_DIR_TYPE_TSCF_UCODE \ + || (type) == BNX_DIR_TYPE_EXT_PHY \ + || (type) == BNX_DIR_TYPE_CCM \ + || (type) == BNX_DIR_TYPE_ISCSI_BOOT \ + ) + +/* Executable NVM items (e.g. microcode, firmware, software) identified + * with the following macro + */ +#define BNX_DIR_TYPE_IS_EXECUTABLE(type) \ + (BNX_DIR_TYPE_IS_APE_BIN_FMT(type) \ + || BNX_DIR_TYPE_IS_OTHER_EXEC(type)) + +#define BNX_DIR_ORDINAL_FIRST 0 /* Ordinals are 0-based */ + +/* No extension flags for this directory entry */ +#define BNX_DIR_EXT_NONE 0 +/* Directory entry is inactive (not used, not hidden, + * not available for reuse) + */ +#define BNX_DIR_EXT_INACTIVE (1 << 0) +/* Directory content is a temporary staging location for + * updating the primary (non-update) directory entry contents + * (e.g. performing a secure firmware update) + */ +#define BNX_DIR_EXT_UPDATE (1 << 1) + +/* No attribute flags set for this directory entry */ +#define BNX_DIR_ATTR_NONE 0 +/* Directory entry checksum of contents is purposely incorrect */ +#define BNX_DIR_ATTR_NO_CHKSUM (1 << 0) +/* Directory contents are in the form of a property-stream + * (e.g. configuration properties) + */ +#define BNX_DIR_ATTR_PROP_STREAM (1 << 1) +/* Directory content (e.g. iSCSI boot) supports IPv4 */ +#define BNX_DIR_ATTR_IPv4 (1 << 2) +/* Directory content (e.g. iSCSI boot) supports IPv6 */ +#define BNX_DIR_ATTR_IPv6 (1 << 3) +/* Directory content includes standard NVM component trailer + * (bnxnvm_component_trailer_t) + */ +#define BNX_DIR_ATTR_TRAILER (1 << 4) + +/* Index of tab-delimited fields in each package log + * (BNX_DIR_TYPE_PKG_LOG) record (\n-terminated line): + */ +enum bnxnvm_pkglog_field_index { + /* Package installation date/time in ISO-8601 format */ + BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0, + /* Installed package description (from package header) or "N/A" */ + BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1, + /* Installed package version string (from package header) or "N/A" */ + BNX_PKG_LOG_FIELD_IDX_PKG_VERSION = 2, + /* Installed package creation/modification timestamp (ISO-8601) */ + BNX_PKG_LOG_FIELD_IDX_PKG_TIMESTAMP = 3, + /* Installed package checksum in hexadecimal (CRC-32) or "N/A" */ + BNX_PKG_LOG_FIELD_IDX_PKG_CHECKSUM = 4, + /* Total number of packaged items applied in this installation */ + BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS = 5, + /* Hexadecimal bit-mask identifying which items were installed */ + BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK = 6 +}; + +#if !defined(__GNUC__) +#ifndef DOS_DRIVERS + #pragma pack(pop) /* original packing */ +#endif +#endif + +#endif /* Don't add anything after this line */ diff --git a/arm-trusted-firmware/include/drivers/brcm/dmu.h b/arm-trusted-firmware/include/drivers/brcm/dmu.h new file mode 100644 index 0000000..3a57bbd --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/dmu.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DMU_H +#define DMU_H + +/* Clock field should be 2 bits only */ +#define CLKCONFIG_MASK 0x3 + +/* argument */ +struct DmuBlockEnable { + uint32_t sotp:1; + uint32_t pka_rng:1; + uint32_t crypto:1; + uint32_t spl:1; + uint32_t cdru_vgm:1; + uint32_t apbs_s0_idm:1; + uint32_t smau_s0_idm:1; +}; + +/* prototype */ +uint32_t bcm_dmu_block_enable(struct DmuBlockEnable dbe); +uint32_t bcm_dmu_block_disable(struct DmuBlockEnable dbe); +uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel); +uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num); + +#define PLL_FREQ_BYPASS 0x0 +#define PLL_FREQ_FULL 0x1 +#define PLL_FREQ_HALF 0x2 +#define PLL_FREQ_QRTR 0x3 + +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h b/arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h new file mode 100644 index 0000000..67f0602 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_H +#define EMMC_H + +#include + +#include + +#include + +#include "emmc_chal_types.h" +#include "emmc_chal_sd.h" +#include "emmc_csl_sdprot.h" +#include "emmc_csl_sdcmd.h" +#include "emmc_pboot_hal_memory_drv.h" + +/* ------------------------------------------------------------------- */ +#define EXT_CSD_SIZE 512 + +#ifdef PLAT_SD_MAX_READ_LENGTH +#define SD_MAX_READ_LENGTH PLAT_SD_MAX_READ_LENGTH +#ifdef USE_EMMC_LARGE_BLK_TRANSFER_LENGTH +#define SD_MAX_BLK_TRANSFER_LENGTH 0x10000000 +#else +#define SD_MAX_BLK_TRANSFER_LENGTH 0x1000 +#endif +#else +#define SD_MAX_READ_LENGTH EMMC_BLOCK_SIZE +#define SD_MAX_BLK_TRANSFER_LENGTH EMMC_BLOCK_SIZE +#endif + +struct emmc_global_buffer { + union { + uint8_t Ext_CSD_storage[EXT_CSD_SIZE]; + uint8_t tempbuf[SD_MAX_READ_LENGTH]; + } u; +}; + +struct emmc_global_vars { + struct sd_card_data cardData; + struct sd_handle sdHandle; + struct sd_dev sdDevice; + struct sd_card_info sdCard; + unsigned int init_done; +}; + +#define ICFG_SDIO0_CAP0__SLOT_TYPE_R 27 +#define ICFG_SDIO0_CAP0__INT_MODE_R 26 +#define ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R 25 +#define ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R 24 +#define ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R 23 +#define ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R 22 +#define ICFG_SDIO0_CAP0__SUSPEND_RESUME_R 21 +#define ICFG_SDIO0_CAP0__SDMA_R 20 +#define ICFG_SDIO0_CAP0__HIGH_SPEED_R 19 +#define ICFG_SDIO0_CAP0__ADMA2_R 18 +#define ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R 17 +#define ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R 15 +#define ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R 7 +#define ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R 6 +#define ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R 0 +#define ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R 22 +#define ICFG_SDIO0_CAP1__SPI_MODE_R 21 +#define ICFG_SDIO0_CAP1__CLK_MULT_R 13 +#define ICFG_SDIO0_CAP1__RETUNING_MODE_R 11 +#define ICFG_SDIO0_CAP1__TUNE_SDR50_R 10 +#define ICFG_SDIO0_CAP1__TIME_RETUNE_R 6 +#define ICFG_SDIO0_CAP1__DRIVER_D_R 5 +#define ICFG_SDIO0_CAP1__DRIVER_C_R 4 +#define ICFG_SDIO0_CAP1__DRIVER_A_R 3 +#define ICFG_SDIO0_CAP1__DDR50_R 2 +#define ICFG_SDIO0_CAP1__SDR104_R 1 +#define ICFG_SDIO0_CAP1__SDR50_R 0 + +#define SDIO0_CTRL_REGS_BASE_ADDR (SDIO0_EMMCSDXC_SYSADDR) +#define SDIO0_IDM_RESET_CTRL_ADDR (SDIO_IDM0_IDM_RESET_CONTROL) + +#define EMMC_CTRL_REGS_BASE_ADDR SDIO0_CTRL_REGS_BASE_ADDR +#define EMMC_IDM_RESET_CTRL_ADDR SDIO0_IDM_RESET_CTRL_ADDR +#define EMMC_IDM_IO_CTRL_DIRECT_ADDR SDIO_IDM0_IO_CONTROL_DIRECT + +extern struct emmc_global_buffer *emmc_global_buf_ptr; + +extern struct emmc_global_vars *emmc_global_vars_ptr; + +#define EMMC_CARD_DETECT_TIMEOUT_MS 1200 +#define EMMC_CMD_TIMEOUT_MS 200 +#define EMMC_BUSY_CMD_TIMEOUT_MS 200 +#define EMMC_CLOCK_SETTING_TIMEOUT_MS 100 +#define EMMC_WFE_RETRY 40000 +#define EMMC_WFE_RETRY_DELAY_US 10 + +#ifdef EMMC_DEBUG +#define EMMC_TRACE INFO +#else +#define EMMC_TRACE(...) +#endif + +#endif /* EMMC_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h new file mode 100644 index 0000000..c4c2a58 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_API_H +#define EMMC_API_H + +#include "bcm_emmc.h" +#include "emmc_pboot_hal_memory_drv.h" + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +/* + * The erasable unit of the eMMC is the Erase Group + * Erase group is measured in write blocks which + * are the basic writable units of the Device + * EMMC_ERASE_GROUP_SIZE is the number of writeable + * units (each unit is 512 bytes) + */ + +/* Start address (sector) */ +#define EMMC_ERASE_START_BLOCK 0x0 +/* Number of blocks to be erased */ +#define EMMC_ERASE_BLOCK_COUNT 0x1 + +#define EMMC_ERASE_USER_AREA 0 +#define EMMC_ERASE_BOOT_PARTITION1 1 +#define EMMC_ERASE_BOOT_PARTITION2 2 + +/* eMMC partition to be erased */ +#define EMMC_ERASE_PARTITION EMMC_ERASE_USER_AREA +#endif + +uint32_t bcm_emmc_init(bool card_rdy_only); +void emmc_deinit(void); + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition); +#endif + +uint32_t emmc_partition_select(uint32_t partition); +uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr, + size_t storage_size, size_t bytes_to_read); +uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr, + size_t bytes_to_write); +#endif /* EMMC_API_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h new file mode 100644 index 0000000..96c333d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h @@ -0,0 +1,1116 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BRCM_RDB_SD4_EMMC_TOP_H +#define BRCM_RDB_SD4_EMMC_TOP_H + +#define SD4_EMMC_TOP_SYSADDR_OFFSET 0x00000000 +#define SD4_EMMC_TOP_SYSADDR_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_SYSADDR_TYPE uint32_t +#define SD4_EMMC_TOP_SYSADDR_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_SYSADDR_SYSADDR_SHIFT 0 +#define SD4_EMMC_TOP_SYSADDR_SYSADDR_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_BLOCK_OFFSET 0x00000004 +#define SD4_EMMC_TOP_BLOCK_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_BLOCK_TYPE uint32_t +#define SD4_EMMC_TOP_BLOCK_RESERVED_MASK 0x00008000 +#define SD4_EMMC_TOP_BLOCK_BCNT_SHIFT 16 +#define SD4_EMMC_TOP_BLOCK_BCNT_MASK 0xFFFF0000 +#define SD4_EMMC_TOP_BLOCK_HSBS_SHIFT 12 +#define SD4_EMMC_TOP_BLOCK_HSBS_MASK 0x00007000 +#define SD4_EMMC_TOP_BLOCK_TBS_SHIFT 0 +#define SD4_EMMC_TOP_BLOCK_TBS_MASK 0x00000FFF + +#define SD4_EMMC_TOP_ARG_OFFSET 0x00000008 +#define SD4_EMMC_TOP_ARG_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ARG_TYPE uint32_t +#define SD4_EMMC_TOP_ARG_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_ARG_ARG_SHIFT 0 +#define SD4_EMMC_TOP_ARG_ARG_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_CMD_OFFSET 0x0000000C +#define SD4_EMMC_TOP_CMD_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CMD_TYPE uint32_t +#define SD4_EMMC_TOP_CMD_RESERVED_MASK 0xC004FFC0 +#define SD4_EMMC_TOP_CMD_CIDX_SHIFT 24 +#define SD4_EMMC_TOP_CMD_CIDX_MASK 0x3F000000 +#define SD4_EMMC_TOP_CMD_CTYP_SHIFT 22 +#define SD4_EMMC_TOP_CMD_CTYP_MASK 0x00C00000 +#define SD4_EMMC_TOP_CMD_DPS_SHIFT 21 +#define SD4_EMMC_TOP_CMD_DPS_MASK 0x00200000 +#define SD4_EMMC_TOP_CMD_CCHK_EN_SHIFT 20 +#define SD4_EMMC_TOP_CMD_CCHK_EN_MASK 0x00100000 +#define SD4_EMMC_TOP_CMD_CRC_EN_SHIFT 19 +#define SD4_EMMC_TOP_CMD_CRC_EN_MASK 0x00080000 +#define SD4_EMMC_TOP_CMD_RTSEL_SHIFT 16 +#define SD4_EMMC_TOP_CMD_RTSEL_MASK 0x00030000 +#define SD4_EMMC_TOP_CMD_MSBS_SHIFT 5 +#define SD4_EMMC_TOP_CMD_MSBS_MASK 0x00000020 +#define SD4_EMMC_TOP_CMD_DTDS_SHIFT 4 +#define SD4_EMMC_TOP_CMD_DTDS_MASK 0x00000010 +#define SD4_EMMC_TOP_CMD_ACMDEN_SHIFT 2 +#define SD4_EMMC_TOP_CMD_ACMDEN_MASK 0x0000000C +#define SD4_EMMC_TOP_CMD_BCEN_SHIFT 1 +#define SD4_EMMC_TOP_CMD_BCEN_MASK 0x00000002 +#define SD4_EMMC_TOP_CMD_DMA_SHIFT 0 +#define SD4_EMMC_TOP_CMD_DMA_MASK 0x00000001 + +#define SD4_EMMC_TOP_CMD_SD4_OFFSET 0x0000000C +#define SD4_EMMC_TOP_CMD_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CMD_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CMD_SD4_RESERVED_MASK 0xC004FE00 +#define SD4_EMMC_TOP_CMD_SD4_CIDX_SHIFT 24 +#define SD4_EMMC_TOP_CMD_SD4_CIDX_MASK 0x3F000000 +#define SD4_EMMC_TOP_CMD_SD4_CTYP_SHIFT 22 +#define SD4_EMMC_TOP_CMD_SD4_CTYP_MASK 0x00C00000 +#define SD4_EMMC_TOP_CMD_SD4_DPS_SHIFT 21 +#define SD4_EMMC_TOP_CMD_SD4_DPS_MASK 0x00200000 +#define SD4_EMMC_TOP_CMD_SD4_CCHK_EN_SHIFT 20 +#define SD4_EMMC_TOP_CMD_SD4_CCHK_EN_MASK 0x00100000 +#define SD4_EMMC_TOP_CMD_SD4_CRC_EN_SHIFT 19 +#define SD4_EMMC_TOP_CMD_SD4_CRC_EN_MASK 0x00080000 +#define SD4_EMMC_TOP_CMD_SD4_RTSEL_SHIFT 16 +#define SD4_EMMC_TOP_CMD_SD4_RTSEL_MASK 0x00030000 +#define SD4_EMMC_TOP_CMD_SD4_RESPIRQDIS_SHIFT 8 +#define SD4_EMMC_TOP_CMD_SD4_RESPIRQDIS_MASK 0x00000100 +#define SD4_EMMC_TOP_CMD_SD4_RESPERRCHKEN_SHIFT 7 +#define SD4_EMMC_TOP_CMD_SD4_RESPERRCHKEN_MASK 0x00000080 +#define SD4_EMMC_TOP_CMD_SD4_RESPR1R5_SHIFT 6 +#define SD4_EMMC_TOP_CMD_SD4_RESPR1R5_MASK 0x00000040 +#define SD4_EMMC_TOP_CMD_SD4_MSBS_SHIFT 5 +#define SD4_EMMC_TOP_CMD_SD4_MSBS_MASK 0x00000020 +#define SD4_EMMC_TOP_CMD_SD4_DTDS_SHIFT 4 +#define SD4_EMMC_TOP_CMD_SD4_DTDS_MASK 0x00000010 +#define SD4_EMMC_TOP_CMD_SD4_ACMDEN_SHIFT 2 +#define SD4_EMMC_TOP_CMD_SD4_ACMDEN_MASK 0x0000000C +#define SD4_EMMC_TOP_CMD_SD4_BCEN_SHIFT 1 +#define SD4_EMMC_TOP_CMD_SD4_BCEN_MASK 0x00000002 +#define SD4_EMMC_TOP_CMD_SD4_DMA_SHIFT 0 +#define SD4_EMMC_TOP_CMD_SD4_DMA_MASK 0x00000001 + +#define SD4_EMMC_TOP_RESP0_OFFSET 0x00000010 +#define SD4_EMMC_TOP_RESP0_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_RESP0_TYPE uint32_t +#define SD4_EMMC_TOP_RESP0_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_RESP0_RESP0_SHIFT 0 +#define SD4_EMMC_TOP_RESP0_RESP0_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_RESP2_OFFSET 0x00000014 +#define SD4_EMMC_TOP_RESP2_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_RESP2_TYPE uint32_t +#define SD4_EMMC_TOP_RESP2_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_RESP2_RESP2_SHIFT 0 +#define SD4_EMMC_TOP_RESP2_RESP2_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_RESP4_OFFSET 0x00000018 +#define SD4_EMMC_TOP_RESP4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_RESP4_TYPE uint32_t +#define SD4_EMMC_TOP_RESP4_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_RESP4_RESP4_SHIFT 0 +#define SD4_EMMC_TOP_RESP4_RESP4_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_RESP6_OFFSET 0x0000001C +#define SD4_EMMC_TOP_RESP6_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_RESP6_TYPE uint32_t +#define SD4_EMMC_TOP_RESP6_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_RESP6_RESP6_SHIFT 0 +#define SD4_EMMC_TOP_RESP6_RESP6_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_BUFDAT_OFFSET 0x00000020 +#define SD4_EMMC_TOP_BUFDAT_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_BUFDAT_TYPE uint32_t +#define SD4_EMMC_TOP_BUFDAT_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_BUFDAT_BUFDAT_SHIFT 0 +#define SD4_EMMC_TOP_BUFDAT_BUFDAT_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_PSTATE_OFFSET 0x00000024 +#define SD4_EMMC_TOP_PSTATE_DEFAULT 0x1FFC0000 +#define SD4_EMMC_TOP_PSTATE_TYPE uint32_t +#define SD4_EMMC_TOP_PSTATE_RESERVED_MASK 0xE000F0F0 +#define SD4_EMMC_TOP_PSTATE_DLS7_4_SHIFT 25 +#define SD4_EMMC_TOP_PSTATE_DLS7_4_MASK 0x1E000000 +#define SD4_EMMC_TOP_PSTATE_CLSL_SHIFT 24 +#define SD4_EMMC_TOP_PSTATE_CLSL_MASK 0x01000000 +#define SD4_EMMC_TOP_PSTATE_DLS3_0_SHIFT 20 +#define SD4_EMMC_TOP_PSTATE_DLS3_0_MASK 0x00F00000 +#define SD4_EMMC_TOP_PSTATE_WPSL_SHIFT 19 +#define SD4_EMMC_TOP_PSTATE_WPSL_MASK 0x00080000 +#define SD4_EMMC_TOP_PSTATE_CDPL_SHIFT 18 +#define SD4_EMMC_TOP_PSTATE_CDPL_MASK 0x00040000 +#define SD4_EMMC_TOP_PSTATE_CSS_SHIFT 17 +#define SD4_EMMC_TOP_PSTATE_CSS_MASK 0x00020000 +#define SD4_EMMC_TOP_PSTATE_CINS_SHIFT 16 +#define SD4_EMMC_TOP_PSTATE_CINS_MASK 0x00010000 +#define SD4_EMMC_TOP_PSTATE_BREN_SHIFT 11 +#define SD4_EMMC_TOP_PSTATE_BREN_MASK 0x00000800 +#define SD4_EMMC_TOP_PSTATE_BWEN_SHIFT 10 +#define SD4_EMMC_TOP_PSTATE_BWEN_MASK 0x00000400 +#define SD4_EMMC_TOP_PSTATE_RXACT_SHIFT 9 +#define SD4_EMMC_TOP_PSTATE_RXACT_MASK 0x00000200 +#define SD4_EMMC_TOP_PSTATE_WXACT_SHIFT 8 +#define SD4_EMMC_TOP_PSTATE_WXACT_MASK 0x00000100 +#define SD4_EMMC_TOP_PSTATE_RETUNE_REQ_SHIFT 3 +#define SD4_EMMC_TOP_PSTATE_RETUNE_REQ_MASK 0x00000008 +#define SD4_EMMC_TOP_PSTATE_DATACT_SHIFT 2 +#define SD4_EMMC_TOP_PSTATE_DATACT_MASK 0x00000004 +#define SD4_EMMC_TOP_PSTATE_DATINH_SHIFT 1 +#define SD4_EMMC_TOP_PSTATE_DATINH_MASK 0x00000002 +#define SD4_EMMC_TOP_PSTATE_CMDINH_SHIFT 0 +#define SD4_EMMC_TOP_PSTATE_CMDINH_MASK 0x00000001 + +#define SD4_EMMC_TOP_PSTATE_SD4_OFFSET 0x00000024 +#define SD4_EMMC_TOP_PSTATE_SD4_DEFAULT 0x01FC00F0 +#define SD4_EMMC_TOP_PSTATE_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_PSTATE_SD4_RESERVED_MASK 0x1E00F000 +#define SD4_EMMC_TOP_PSTATE_SD4_STBLDET_SHIFT 31 +#define SD4_EMMC_TOP_PSTATE_SD4_STBLDET_MASK 0x80000000 +#define SD4_EMMC_TOP_PSTATE_SD4_LANESYNC_SHIFT 30 +#define SD4_EMMC_TOP_PSTATE_SD4_LANESYNC_MASK 0x40000000 +#define SD4_EMMC_TOP_PSTATE_SD4_INDORMNTSTATE_SHIFT 29 +#define SD4_EMMC_TOP_PSTATE_SD4_INDORMNTSTATE_MASK 0x20000000 +#define SD4_EMMC_TOP_PSTATE_SD4_CLSL_SHIFT 24 +#define SD4_EMMC_TOP_PSTATE_SD4_CLSL_MASK 0x01000000 +#define SD4_EMMC_TOP_PSTATE_SD4_DLS3_0_SHIFT 20 +#define SD4_EMMC_TOP_PSTATE_SD4_DLS3_0_MASK 0x00F00000 +#define SD4_EMMC_TOP_PSTATE_SD4_WPSL_SHIFT 19 +#define SD4_EMMC_TOP_PSTATE_SD4_WPSL_MASK 0x00080000 +#define SD4_EMMC_TOP_PSTATE_SD4_CDPL_SHIFT 18 +#define SD4_EMMC_TOP_PSTATE_SD4_CDPL_MASK 0x00040000 +#define SD4_EMMC_TOP_PSTATE_SD4_CSS_SHIFT 17 +#define SD4_EMMC_TOP_PSTATE_SD4_CSS_MASK 0x00020000 +#define SD4_EMMC_TOP_PSTATE_SD4_CINS_SHIFT 16 +#define SD4_EMMC_TOP_PSTATE_SD4_CINS_MASK 0x00010000 +#define SD4_EMMC_TOP_PSTATE_SD4_BREN_SHIFT 11 +#define SD4_EMMC_TOP_PSTATE_SD4_BREN_MASK 0x00000800 +#define SD4_EMMC_TOP_PSTATE_SD4_BWEN_SHIFT 10 +#define SD4_EMMC_TOP_PSTATE_SD4_BWEN_MASK 0x00000400 +#define SD4_EMMC_TOP_PSTATE_SD4_RXACT_SHIFT 9 +#define SD4_EMMC_TOP_PSTATE_SD4_RXACT_MASK 0x00000200 +#define SD4_EMMC_TOP_PSTATE_SD4_WXACT_SHIFT 8 +#define SD4_EMMC_TOP_PSTATE_SD4_WXACT_MASK 0x00000100 +#define SD4_EMMC_TOP_PSTATE_SD4_DLS7_4_SHIFT 4 +#define SD4_EMMC_TOP_PSTATE_SD4_DLS7_4_MASK 0x000000F0 +#define SD4_EMMC_TOP_PSTATE_SD4_RETUNE_REQ_SHIFT 3 +#define SD4_EMMC_TOP_PSTATE_SD4_RETUNE_REQ_MASK 0x00000008 +#define SD4_EMMC_TOP_PSTATE_SD4_DATACT_SHIFT 2 +#define SD4_EMMC_TOP_PSTATE_SD4_DATACT_MASK 0x00000004 +#define SD4_EMMC_TOP_PSTATE_SD4_DATINH_SHIFT 1 +#define SD4_EMMC_TOP_PSTATE_SD4_DATINH_MASK 0x00000002 +#define SD4_EMMC_TOP_PSTATE_SD4_CMDINH_SHIFT 0 +#define SD4_EMMC_TOP_PSTATE_SD4_CMDINH_MASK 0x00000001 + +#define SD4_EMMC_TOP_CTRL_OFFSET 0x00000028 +#define SD4_EMMC_TOP_CTRL_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CTRL_TYPE uint32_t +#define SD4_EMMC_TOP_CTRL_RESERVED_MASK 0xF800E000 +#define SD4_EMMC_TOP_CTRL_WAKENRMV_SHIFT 26 +#define SD4_EMMC_TOP_CTRL_WAKENRMV_MASK 0x04000000 +#define SD4_EMMC_TOP_CTRL_WAKENINS_SHIFT 25 +#define SD4_EMMC_TOP_CTRL_WAKENINS_MASK 0x02000000 +#define SD4_EMMC_TOP_CTRL_WAKENIRQ_SHIFT 24 +#define SD4_EMMC_TOP_CTRL_WAKENIRQ_MASK 0x01000000 +#define SD4_EMMC_TOP_CTRL_BOOTACK_SHIFT 23 +#define SD4_EMMC_TOP_CTRL_BOOTACK_MASK 0x00800000 +#define SD4_EMMC_TOP_CTRL_ATLBOOTEN_SHIFT 22 +#define SD4_EMMC_TOP_CTRL_ATLBOOTEN_MASK 0x00400000 +#define SD4_EMMC_TOP_CTRL_BOOTEN_SHIFT 21 +#define SD4_EMMC_TOP_CTRL_BOOTEN_MASK 0x00200000 +#define SD4_EMMC_TOP_CTRL_SPIMODE_SHIFT 20 +#define SD4_EMMC_TOP_CTRL_SPIMODE_MASK 0x00100000 +#define SD4_EMMC_TOP_CTRL_BLKIRQ_SHIFT 19 +#define SD4_EMMC_TOP_CTRL_BLKIRQ_MASK 0x00080000 +#define SD4_EMMC_TOP_CTRL_RDWTCRTL_SHIFT 18 +#define SD4_EMMC_TOP_CTRL_RDWTCRTL_MASK 0x00040000 +#define SD4_EMMC_TOP_CTRL_CONTREQ_SHIFT 17 +#define SD4_EMMC_TOP_CTRL_CONTREQ_MASK 0x00020000 +#define SD4_EMMC_TOP_CTRL_BLKSTPREQ_SHIFT 16 +#define SD4_EMMC_TOP_CTRL_BLKSTPREQ_MASK 0x00010000 +#define SD4_EMMC_TOP_CTRL_HRESET_SHIFT 12 +#define SD4_EMMC_TOP_CTRL_HRESET_MASK 0x00001000 +#define SD4_EMMC_TOP_CTRL_SDVSELVDD1_SHIFT 9 +#define SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK 0x00000E00 +#define SD4_EMMC_TOP_CTRL_SDPWR_SHIFT 8 +#define SD4_EMMC_TOP_CTRL_SDPWR_MASK 0x00000100 +#define SD4_EMMC_TOP_CTRL_CDSD_SHIFT 7 +#define SD4_EMMC_TOP_CTRL_CDSD_MASK 0x00000080 +#define SD4_EMMC_TOP_CTRL_CDTL_SHIFT 6 +#define SD4_EMMC_TOP_CTRL_CDTL_MASK 0x00000040 +#define SD4_EMMC_TOP_CTRL_SDB_SHIFT 5 +#define SD4_EMMC_TOP_CTRL_SDB_MASK 0x00000020 +#define SD4_EMMC_TOP_CTRL_DMASEL_SHIFT 3 +#define SD4_EMMC_TOP_CTRL_DMASEL_MASK 0x00000018 +#define SD4_EMMC_TOP_CTRL_HSEN_SHIFT 2 +#define SD4_EMMC_TOP_CTRL_HSEN_MASK 0x00000004 +#define SD4_EMMC_TOP_CTRL_DXTW_SHIFT 1 +#define SD4_EMMC_TOP_CTRL_DXTW_MASK 0x00000002 +#define SD4_EMMC_TOP_CTRL_LEDCTL_SHIFT 0 +#define SD4_EMMC_TOP_CTRL_LEDCTL_MASK 0x00000001 + +#define SD4_EMMC_TOP_CTRL_SD4_OFFSET 0x00000028 +#define SD4_EMMC_TOP_CTRL_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CTRL_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CTRL_SD4_RESERVED_MASK 0xF8F00000 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENRMV_SHIFT 26 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENRMV_MASK 0x04000000 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENINS_SHIFT 25 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENINS_MASK 0x02000000 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENIRQ_SHIFT 24 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENIRQ_MASK 0x01000000 +#define SD4_EMMC_TOP_CTRL_SD4_BLKIRQ_SHIFT 19 +#define SD4_EMMC_TOP_CTRL_SD4_BLKIRQ_MASK 0x00080000 +#define SD4_EMMC_TOP_CTRL_SD4_RDWTCRTL_SHIFT 18 +#define SD4_EMMC_TOP_CTRL_SD4_RDWTCRTL_MASK 0x00040000 +#define SD4_EMMC_TOP_CTRL_SD4_CONTREQ_SHIFT 17 +#define SD4_EMMC_TOP_CTRL_SD4_CONTREQ_MASK 0x00020000 +#define SD4_EMMC_TOP_CTRL_SD4_BLKSTPREQ_SHIFT 16 +#define SD4_EMMC_TOP_CTRL_SD4_BLKSTPREQ_MASK 0x00010000 +#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD2_SHIFT 13 +#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD2_MASK 0x0000E000 +#define SD4_EMMC_TOP_CTRL_SD4_SDPWRVDD2_SHIFT 12 +#define SD4_EMMC_TOP_CTRL_SD4_SDPWRVDD2_MASK 0x00001000 +#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD1_SHIFT 9 +#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD1_MASK 0x00000E00 +#define SD4_EMMC_TOP_CTRL_SD4_SDPWR_SHIFT 8 +#define SD4_EMMC_TOP_CTRL_SD4_SDPWR_MASK 0x00000100 +#define SD4_EMMC_TOP_CTRL_SD4_CDSD_SHIFT 7 +#define SD4_EMMC_TOP_CTRL_SD4_CDSD_MASK 0x00000080 +#define SD4_EMMC_TOP_CTRL_SD4_CDTL_SHIFT 6 +#define SD4_EMMC_TOP_CTRL_SD4_CDTL_MASK 0x00000040 +#define SD4_EMMC_TOP_CTRL_SD4_SDB_SHIFT 5 +#define SD4_EMMC_TOP_CTRL_SD4_SDB_MASK 0x00000020 +#define SD4_EMMC_TOP_CTRL_SD4_DMASEL_SHIFT 3 +#define SD4_EMMC_TOP_CTRL_SD4_DMASEL_MASK 0x00000018 +#define SD4_EMMC_TOP_CTRL_SD4_HSEN_SHIFT 2 +#define SD4_EMMC_TOP_CTRL_SD4_HSEN_MASK 0x00000004 +#define SD4_EMMC_TOP_CTRL_SD4_DXTW_SHIFT 1 +#define SD4_EMMC_TOP_CTRL_SD4_DXTW_MASK 0x00000002 +#define SD4_EMMC_TOP_CTRL_SD4_LEDCTL_SHIFT 0 +#define SD4_EMMC_TOP_CTRL_SD4_LEDCTL_MASK 0x00000001 + +#define SD4_EMMC_TOP_CTRL1_OFFSET 0x0000002C +#define SD4_EMMC_TOP_CTRL1_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CTRL1_TYPE uint32_t +#define SD4_EMMC_TOP_CTRL1_RESERVED_MASK 0xF8F00018 +#define SD4_EMMC_TOP_CTRL1_DATRST_SHIFT 26 +#define SD4_EMMC_TOP_CTRL1_DATRST_MASK 0x04000000 +#define SD4_EMMC_TOP_CTRL1_CMDRST_SHIFT 25 +#define SD4_EMMC_TOP_CTRL1_CMDRST_MASK 0x02000000 +#define SD4_EMMC_TOP_CTRL1_RST_SHIFT 24 +#define SD4_EMMC_TOP_CTRL1_RST_MASK 0x01000000 +#define SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT 16 +#define SD4_EMMC_TOP_CTRL1_DTCNT_MASK 0x000F0000 +#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT 8 +#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK 0x0000FF00 +#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT 6 +#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK 0x000000C0 +#define SD4_EMMC_TOP_CTRL1_CLKGENSEL_SHIFT 5 +#define SD4_EMMC_TOP_CTRL1_CLKGENSEL_MASK 0x00000020 +#define SD4_EMMC_TOP_CTRL1_SDCLKEN_SHIFT 2 +#define SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK 0x00000004 +#define SD4_EMMC_TOP_CTRL1_ICLKSTB_SHIFT 1 +#define SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK 0x00000002 +#define SD4_EMMC_TOP_CTRL1_ICLKEN_SHIFT 0 +#define SD4_EMMC_TOP_CTRL1_ICLKEN_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTR_OFFSET 0x00000030 +#define SD4_EMMC_TOP_INTR_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTR_TYPE uint32_t +#define SD4_EMMC_TOP_INTR_RESERVED_MASK 0xEC000000 +#define SD4_EMMC_TOP_INTR_TRESPERR_SHIFT 28 +#define SD4_EMMC_TOP_INTR_TRESPERR_MASK 0x10000000 +#define SD4_EMMC_TOP_INTR_ADMAERR_SHIFT 25 +#define SD4_EMMC_TOP_INTR_ADMAERR_MASK 0x02000000 +#define SD4_EMMC_TOP_INTR_CMDERROR_SHIFT 24 +#define SD4_EMMC_TOP_INTR_CMDERROR_MASK 0x01000000 +#define SD4_EMMC_TOP_INTR_IERR_SHIFT 23 +#define SD4_EMMC_TOP_INTR_IERR_MASK 0x00800000 +#define SD4_EMMC_TOP_INTR_DEBERR_SHIFT 22 +#define SD4_EMMC_TOP_INTR_DEBERR_MASK 0x00400000 +#define SD4_EMMC_TOP_INTR_DCRCERR_SHIFT 21 +#define SD4_EMMC_TOP_INTR_DCRCERR_MASK 0x00200000 +#define SD4_EMMC_TOP_INTR_DTOERR_SHIFT 20 +#define SD4_EMMC_TOP_INTR_DTOERR_MASK 0x00100000 +#define SD4_EMMC_TOP_INTR_CMDIDXERR_SHIFT 19 +#define SD4_EMMC_TOP_INTR_CMDIDXERR_MASK 0x00080000 +#define SD4_EMMC_TOP_INTR_CEBERR_SHIFT 18 +#define SD4_EMMC_TOP_INTR_CEBERR_MASK 0x00040000 +#define SD4_EMMC_TOP_INTR_CCRCERR_SHIFT 17 +#define SD4_EMMC_TOP_INTR_CCRCERR_MASK 0x00020000 +#define SD4_EMMC_TOP_INTR_CTOERR_SHIFT 16 +#define SD4_EMMC_TOP_INTR_CTOERR_MASK 0x00010000 +#define SD4_EMMC_TOP_INTR_ERRIRQ_SHIFT 15 +#define SD4_EMMC_TOP_INTR_ERRIRQ_MASK 0x00008000 +#define SD4_EMMC_TOP_INTR_BTIRQ_SHIFT 14 +#define SD4_EMMC_TOP_INTR_BTIRQ_MASK 0x00004000 +#define SD4_EMMC_TOP_INTR_BTACKRX_SHIFT 13 +#define SD4_EMMC_TOP_INTR_BTACKRX_MASK 0x00002000 +#define SD4_EMMC_TOP_INTR_RETUNE_EVENT_SHIFT 12 +#define SD4_EMMC_TOP_INTR_RETUNE_EVENT_MASK 0x00001000 +#define SD4_EMMC_TOP_INTR_INT_C_SHIFT 11 +#define SD4_EMMC_TOP_INTR_INT_C_MASK 0x00000800 +#define SD4_EMMC_TOP_INTR_INT_B_SHIFT 10 +#define SD4_EMMC_TOP_INTR_INT_B_MASK 0x00000400 +#define SD4_EMMC_TOP_INTR_INT_A_SHIFT 9 +#define SD4_EMMC_TOP_INTR_INT_A_MASK 0x00000200 +#define SD4_EMMC_TOP_INTR_CRDIRQ_SHIFT 8 +#define SD4_EMMC_TOP_INTR_CRDIRQ_MASK 0x00000100 +#define SD4_EMMC_TOP_INTR_CRDRMV_SHIFT 7 +#define SD4_EMMC_TOP_INTR_CRDRMV_MASK 0x00000080 +#define SD4_EMMC_TOP_INTR_CRDINS_SHIFT 6 +#define SD4_EMMC_TOP_INTR_CRDINS_MASK 0x00000040 +#define SD4_EMMC_TOP_INTR_BRRDY_SHIFT 5 +#define SD4_EMMC_TOP_INTR_BRRDY_MASK 0x00000020 +#define SD4_EMMC_TOP_INTR_BWRDY_SHIFT 4 +#define SD4_EMMC_TOP_INTR_BWRDY_MASK 0x00000010 +#define SD4_EMMC_TOP_INTR_DMAIRQ_SHIFT 3 +#define SD4_EMMC_TOP_INTR_DMAIRQ_MASK 0x00000008 +#define SD4_EMMC_TOP_INTR_BLKENT_SHIFT 2 +#define SD4_EMMC_TOP_INTR_BLKENT_MASK 0x00000004 +#define SD4_EMMC_TOP_INTR_TXDONE_SHIFT 1 +#define SD4_EMMC_TOP_INTR_TXDONE_MASK 0x00000002 +#define SD4_EMMC_TOP_INTR_CMDDONE_SHIFT 0 +#define SD4_EMMC_TOP_INTR_CMDDONE_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTR_SD4_OFFSET 0x00000030 +#define SD4_EMMC_TOP_INTR_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTR_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_INTR_SD4_RESERVED_MASK 0xF0006000 +#define SD4_EMMC_TOP_INTR_SD4_TRESPERR_SHIFT 27 +#define SD4_EMMC_TOP_INTR_SD4_TRESPERR_MASK 0x08000000 +#define SD4_EMMC_TOP_INTR_SD4_TUNEERR_SHIFT 26 +#define SD4_EMMC_TOP_INTR_SD4_TUNEERR_MASK 0x04000000 +#define SD4_EMMC_TOP_INTR_SD4_ADMAERR_SHIFT 25 +#define SD4_EMMC_TOP_INTR_SD4_ADMAERR_MASK 0x02000000 +#define SD4_EMMC_TOP_INTR_SD4_CMDERROR_SHIFT 24 +#define SD4_EMMC_TOP_INTR_SD4_CMDERROR_MASK 0x01000000 +#define SD4_EMMC_TOP_INTR_SD4_IERR_SHIFT 23 +#define SD4_EMMC_TOP_INTR_SD4_IERR_MASK 0x00800000 +#define SD4_EMMC_TOP_INTR_SD4_DEBERR_SHIFT 22 +#define SD4_EMMC_TOP_INTR_SD4_DEBERR_MASK 0x00400000 +#define SD4_EMMC_TOP_INTR_SD4_DCRCERR_SHIFT 21 +#define SD4_EMMC_TOP_INTR_SD4_DCRCERR_MASK 0x00200000 +#define SD4_EMMC_TOP_INTR_SD4_DTOERR_SHIFT 20 +#define SD4_EMMC_TOP_INTR_SD4_DTOERR_MASK 0x00100000 +#define SD4_EMMC_TOP_INTR_SD4_CMDIDXERR_SHIFT 19 +#define SD4_EMMC_TOP_INTR_SD4_CMDIDXERR_MASK 0x00080000 +#define SD4_EMMC_TOP_INTR_SD4_CEBERR_SHIFT 18 +#define SD4_EMMC_TOP_INTR_SD4_CEBERR_MASK 0x00040000 +#define SD4_EMMC_TOP_INTR_SD4_CCRCERR_SHIFT 17 +#define SD4_EMMC_TOP_INTR_SD4_CCRCERR_MASK 0x00020000 +#define SD4_EMMC_TOP_INTR_SD4_CTOERR_SHIFT 16 +#define SD4_EMMC_TOP_INTR_SD4_CTOERR_MASK 0x00010000 +#define SD4_EMMC_TOP_INTR_SD4_ERRIRQ_SHIFT 15 +#define SD4_EMMC_TOP_INTR_SD4_ERRIRQ_MASK 0x00008000 +#define SD4_EMMC_TOP_INTR_SD4_RETUNE_EVENT_SHIFT 12 +#define SD4_EMMC_TOP_INTR_SD4_RETUNE_EVENT_MASK 0x00001000 +#define SD4_EMMC_TOP_INTR_SD4_INT_C_SHIFT 11 +#define SD4_EMMC_TOP_INTR_SD4_INT_C_MASK 0x00000800 +#define SD4_EMMC_TOP_INTR_SD4_INT_B_SHIFT 10 +#define SD4_EMMC_TOP_INTR_SD4_INT_B_MASK 0x00000400 +#define SD4_EMMC_TOP_INTR_SD4_INT_A_SHIFT 9 +#define SD4_EMMC_TOP_INTR_SD4_INT_A_MASK 0x00000200 +#define SD4_EMMC_TOP_INTR_SD4_CRDIRQ_SHIFT 8 +#define SD4_EMMC_TOP_INTR_SD4_CRDIRQ_MASK 0x00000100 +#define SD4_EMMC_TOP_INTR_SD4_CRDRMV_SHIFT 7 +#define SD4_EMMC_TOP_INTR_SD4_CRDRMV_MASK 0x00000080 +#define SD4_EMMC_TOP_INTR_SD4_CRDINS_SHIFT 6 +#define SD4_EMMC_TOP_INTR_SD4_CRDINS_MASK 0x00000040 +#define SD4_EMMC_TOP_INTR_SD4_BRRDY_SHIFT 5 +#define SD4_EMMC_TOP_INTR_SD4_BRRDY_MASK 0x00000020 +#define SD4_EMMC_TOP_INTR_SD4_BWRDY_SHIFT 4 +#define SD4_EMMC_TOP_INTR_SD4_BWRDY_MASK 0x00000010 +#define SD4_EMMC_TOP_INTR_SD4_DMAIRQ_SHIFT 3 +#define SD4_EMMC_TOP_INTR_SD4_DMAIRQ_MASK 0x00000008 +#define SD4_EMMC_TOP_INTR_SD4_BLKENT_SHIFT 2 +#define SD4_EMMC_TOP_INTR_SD4_BLKENT_MASK 0x00000004 +#define SD4_EMMC_TOP_INTR_SD4_TXDONE_SHIFT 1 +#define SD4_EMMC_TOP_INTR_SD4_TXDONE_MASK 0x00000002 +#define SD4_EMMC_TOP_INTR_SD4_CMDDONE_SHIFT 0 +#define SD4_EMMC_TOP_INTR_SD4_CMDDONE_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTREN1_OFFSET 0x00000034 +#define SD4_EMMC_TOP_INTREN1_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTREN1_TYPE uint32_t +#define SD4_EMMC_TOP_INTREN1_RESERVED_MASK 0xEC000000 +#define SD4_EMMC_TOP_INTREN1_TRESPERREN_SHIFT 28 +#define SD4_EMMC_TOP_INTREN1_TRESPERREN_MASK 0x10000000 +#define SD4_EMMC_TOP_INTREN1_ADMAEREN_SHIFT 25 +#define SD4_EMMC_TOP_INTREN1_ADMAEREN_MASK 0x02000000 +#define SD4_EMMC_TOP_INTREN1_CMDERREN_SHIFT 24 +#define SD4_EMMC_TOP_INTREN1_CMDERREN_MASK 0x01000000 +#define SD4_EMMC_TOP_INTREN1_ILIMERREN_SHIFT 23 +#define SD4_EMMC_TOP_INTREN1_ILIMERREN_MASK 0x00800000 +#define SD4_EMMC_TOP_INTREN1_DEBERREN_SHIFT 22 +#define SD4_EMMC_TOP_INTREN1_DEBERREN_MASK 0x00400000 +#define SD4_EMMC_TOP_INTREN1_DCRCERREN_SHIFT 21 +#define SD4_EMMC_TOP_INTREN1_DCRCERREN_MASK 0x00200000 +#define SD4_EMMC_TOP_INTREN1_DTOERREN_SHIFT 20 +#define SD4_EMMC_TOP_INTREN1_DTOERREN_MASK 0x00100000 +#define SD4_EMMC_TOP_INTREN1_CIDXERREN_SHIFT 19 +#define SD4_EMMC_TOP_INTREN1_CIDXERREN_MASK 0x00080000 +#define SD4_EMMC_TOP_INTREN1_CEBERREN_SHIFT 18 +#define SD4_EMMC_TOP_INTREN1_CEBERREN_MASK 0x00040000 +#define SD4_EMMC_TOP_INTREN1_CMDCRCEN_SHIFT 17 +#define SD4_EMMC_TOP_INTREN1_CMDCRCEN_MASK 0x00020000 +#define SD4_EMMC_TOP_INTREN1_CMDTOEN_SHIFT 16 +#define SD4_EMMC_TOP_INTREN1_CMDTOEN_MASK 0x00010000 +#define SD4_EMMC_TOP_INTREN1_FIXZ_SHIFT 15 +#define SD4_EMMC_TOP_INTREN1_FIXZ_MASK 0x00008000 +#define SD4_EMMC_TOP_INTREN1_BTIRQEN_SHIFT 14 +#define SD4_EMMC_TOP_INTREN1_BTIRQEN_MASK 0x00004000 +#define SD4_EMMC_TOP_INTREN1_BTACKRXEN_SHIFT 13 +#define SD4_EMMC_TOP_INTREN1_BTACKRXEN_MASK 0x00002000 +#define SD4_EMMC_TOP_INTREN1_RETUNE_EVENTEN_SHIFT 12 +#define SD4_EMMC_TOP_INTREN1_RETUNE_EVENTEN_MASK 0x00001000 +#define SD4_EMMC_TOP_INTREN1_INT_C_EN_SHIFT 11 +#define SD4_EMMC_TOP_INTREN1_INT_C_EN_MASK 0x00000800 +#define SD4_EMMC_TOP_INTREN1_INT_B_EN_SHIFT 10 +#define SD4_EMMC_TOP_INTREN1_INT_B_EN_MASK 0x00000400 +#define SD4_EMMC_TOP_INTREN1_INT_A_EN_SHIFT 9 +#define SD4_EMMC_TOP_INTREN1_INT_A_EN_MASK 0x00000200 +#define SD4_EMMC_TOP_INTREN1_CIRQEN_SHIFT 8 +#define SD4_EMMC_TOP_INTREN1_CIRQEN_MASK 0x00000100 +#define SD4_EMMC_TOP_INTREN1_CRDRMVEN_SHIFT 7 +#define SD4_EMMC_TOP_INTREN1_CRDRMVEN_MASK 0x00000080 +#define SD4_EMMC_TOP_INTREN1_CRDINSEN_SHIFT 6 +#define SD4_EMMC_TOP_INTREN1_CRDINSEN_MASK 0x00000040 +#define SD4_EMMC_TOP_INTREN1_BUFRREN_SHIFT 5 +#define SD4_EMMC_TOP_INTREN1_BUFRREN_MASK 0x00000020 +#define SD4_EMMC_TOP_INTREN1_BUFWREN_SHIFT 4 +#define SD4_EMMC_TOP_INTREN1_BUFWREN_MASK 0x00000010 +#define SD4_EMMC_TOP_INTREN1_DMAIRQEN_SHIFT 3 +#define SD4_EMMC_TOP_INTREN1_DMAIRQEN_MASK 0x00000008 +#define SD4_EMMC_TOP_INTREN1_BLKEN_SHIFT 2 +#define SD4_EMMC_TOP_INTREN1_BLKEN_MASK 0x00000004 +#define SD4_EMMC_TOP_INTREN1_TXDONEEN_SHIFT 1 +#define SD4_EMMC_TOP_INTREN1_TXDONEEN_MASK 0x00000002 +#define SD4_EMMC_TOP_INTREN1_CMDDONEEN_SHIFT 0 +#define SD4_EMMC_TOP_INTREN1_CMDDONEEN_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTREN1_SD4_OFFSET 0x00000034 +#define SD4_EMMC_TOP_INTREN1_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTREN1_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_INTREN1_SD4_RESERVED_MASK 0x00006000 +#define SD4_EMMC_TOP_INTREN1_SD4_VNDRERREN_SHIFT 28 +#define SD4_EMMC_TOP_INTREN1_SD4_VNDRERREN_MASK 0xF0000000 +#define SD4_EMMC_TOP_INTREN1_SD4_TRESPERREN_SHIFT 27 +#define SD4_EMMC_TOP_INTREN1_SD4_TRESPERREN_MASK 0x08000000 +#define SD4_EMMC_TOP_INTREN1_SD4_TUNEERREN_SHIFT 26 +#define SD4_EMMC_TOP_INTREN1_SD4_TUNEERREN_MASK 0x04000000 +#define SD4_EMMC_TOP_INTREN1_SD4_ADMAEREN_SHIFT 25 +#define SD4_EMMC_TOP_INTREN1_SD4_ADMAEREN_MASK 0x02000000 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDERREN_SHIFT 24 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDERREN_MASK 0x01000000 +#define SD4_EMMC_TOP_INTREN1_SD4_ILIMERREN_SHIFT 23 +#define SD4_EMMC_TOP_INTREN1_SD4_ILIMERREN_MASK 0x00800000 +#define SD4_EMMC_TOP_INTREN1_SD4_DEBERREN_SHIFT 22 +#define SD4_EMMC_TOP_INTREN1_SD4_DEBERREN_MASK 0x00400000 +#define SD4_EMMC_TOP_INTREN1_SD4_DCRCERREN_SHIFT 21 +#define SD4_EMMC_TOP_INTREN1_SD4_DCRCERREN_MASK 0x00200000 +#define SD4_EMMC_TOP_INTREN1_SD4_DTOERREN_SHIFT 20 +#define SD4_EMMC_TOP_INTREN1_SD4_DTOERREN_MASK 0x00100000 +#define SD4_EMMC_TOP_INTREN1_SD4_CIDXERREN_SHIFT 19 +#define SD4_EMMC_TOP_INTREN1_SD4_CIDXERREN_MASK 0x00080000 +#define SD4_EMMC_TOP_INTREN1_SD4_CEBERREN_SHIFT 18 +#define SD4_EMMC_TOP_INTREN1_SD4_CEBERREN_MASK 0x00040000 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDCRCEN_SHIFT 17 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDCRCEN_MASK 0x00020000 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDTOEN_SHIFT 16 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDTOEN_MASK 0x00010000 +#define SD4_EMMC_TOP_INTREN1_SD4_FIXZ_SHIFT 15 +#define SD4_EMMC_TOP_INTREN1_SD4_FIXZ_MASK 0x00008000 +#define SD4_EMMC_TOP_INTREN1_SD4_RETUNE_EVENTEN_SHIFT 12 +#define SD4_EMMC_TOP_INTREN1_SD4_RETUNE_EVENTEN_MASK 0x00001000 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_C_EN_SHIFT 11 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_C_EN_MASK 0x00000800 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_B_EN_SHIFT 10 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_B_EN_MASK 0x00000400 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_A_EN_SHIFT 9 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_A_EN_MASK 0x00000200 +#define SD4_EMMC_TOP_INTREN1_SD4_CIRQEN_SHIFT 8 +#define SD4_EMMC_TOP_INTREN1_SD4_CIRQEN_MASK 0x00000100 +#define SD4_EMMC_TOP_INTREN1_SD4_CRDRMVEN_SHIFT 7 +#define SD4_EMMC_TOP_INTREN1_SD4_CRDRMVEN_MASK 0x00000080 +#define SD4_EMMC_TOP_INTREN1_SD4_CRDINSEN_SHIFT 6 +#define SD4_EMMC_TOP_INTREN1_SD4_CRDINSEN_MASK 0x00000040 +#define SD4_EMMC_TOP_INTREN1_SD4_BUFRREN_SHIFT 5 +#define SD4_EMMC_TOP_INTREN1_SD4_BUFRREN_MASK 0x00000020 +#define SD4_EMMC_TOP_INTREN1_SD4_BUFWREN_SHIFT 4 +#define SD4_EMMC_TOP_INTREN1_SD4_BUFWREN_MASK 0x00000010 +#define SD4_EMMC_TOP_INTREN1_SD4_DMAIRQEN_SHIFT 3 +#define SD4_EMMC_TOP_INTREN1_SD4_DMAIRQEN_MASK 0x00000008 +#define SD4_EMMC_TOP_INTREN1_SD4_BLKEN_SHIFT 2 +#define SD4_EMMC_TOP_INTREN1_SD4_BLKEN_MASK 0x00000004 +#define SD4_EMMC_TOP_INTREN1_SD4_TXDONEEN_SHIFT 1 +#define SD4_EMMC_TOP_INTREN1_SD4_TXDONEEN_MASK 0x00000002 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDDONEEN_SHIFT 0 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDDONEEN_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTREN2_OFFSET 0x00000038 +#define SD4_EMMC_TOP_INTREN2_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTREN2_TYPE uint32_t +#define SD4_EMMC_TOP_INTREN2_RESERVED_MASK 0xEC000000 +#define SD4_EMMC_TOP_INTREN2_TRESPERRSEN_SHIFT 28 +#define SD4_EMMC_TOP_INTREN2_TRESPERRSEN_MASK 0x10000000 +#define SD4_EMMC_TOP_INTREN2_ADMASIGEN_SHIFT 25 +#define SD4_EMMC_TOP_INTREN2_ADMASIGEN_MASK 0x02000000 +#define SD4_EMMC_TOP_INTREN2_CMDSIGEN_SHIFT 24 +#define SD4_EMMC_TOP_INTREN2_CMDSIGEN_MASK 0x01000000 +#define SD4_EMMC_TOP_INTREN2_ILIMSIGEN_SHIFT 23 +#define SD4_EMMC_TOP_INTREN2_ILIMSIGEN_MASK 0x00800000 +#define SD4_EMMC_TOP_INTREN2_DEBSIGEN_SHIFT 22 +#define SD4_EMMC_TOP_INTREN2_DEBSIGEN_MASK 0x00400000 +#define SD4_EMMC_TOP_INTREN2_DCRCSIGEN_SHIFT 21 +#define SD4_EMMC_TOP_INTREN2_DCRCSIGEN_MASK 0x00200000 +#define SD4_EMMC_TOP_INTREN2_DTOSIGEN_SHIFT 20 +#define SD4_EMMC_TOP_INTREN2_DTOSIGEN_MASK 0x00100000 +#define SD4_EMMC_TOP_INTREN2_CIDXSIGEN_SHIFT 19 +#define SD4_EMMC_TOP_INTREN2_CIDXSIGEN_MASK 0x00080000 +#define SD4_EMMC_TOP_INTREN2_CEBSIGEN_SHIFT 18 +#define SD4_EMMC_TOP_INTREN2_CEBSIGEN_MASK 0x00040000 +#define SD4_EMMC_TOP_INTREN2_CMDCRCSIGEN_SHIFT 17 +#define SD4_EMMC_TOP_INTREN2_CMDCRCSIGEN_MASK 0x00020000 +#define SD4_EMMC_TOP_INTREN2_CMDTOSIGEN_SHIFT 16 +#define SD4_EMMC_TOP_INTREN2_CMDTOSIGEN_MASK 0x00010000 +#define SD4_EMMC_TOP_INTREN2_FIXZERO_SHIFT 15 +#define SD4_EMMC_TOP_INTREN2_FIXZERO_MASK 0x00008000 +#define SD4_EMMC_TOP_INTREN2_BTIRQSEN_SHIFT 14 +#define SD4_EMMC_TOP_INTREN2_BTIRQSEN_MASK 0x00004000 +#define SD4_EMMC_TOP_INTREN2_BTACKRXSEN_SHIFT 13 +#define SD4_EMMC_TOP_INTREN2_BTACKRXSEN_MASK 0x00002000 +#define SD4_EMMC_TOP_INTREN2_RETUNE_EVENTSIGEN_SHIFT 12 +#define SD4_EMMC_TOP_INTREN2_RETUNE_EVENTSIGEN_MASK 0x00001000 +#define SD4_EMMC_TOP_INTREN2_INT_C_SIGEN_SHIFT 11 +#define SD4_EMMC_TOP_INTREN2_INT_C_SIGEN_MASK 0x00000800 +#define SD4_EMMC_TOP_INTREN2_INT_B_SIGEN_SHIFT 10 +#define SD4_EMMC_TOP_INTREN2_INT_B_SIGEN_MASK 0x00000400 +#define SD4_EMMC_TOP_INTREN2_INT_A_SIGEN_SHIFT 9 +#define SD4_EMMC_TOP_INTREN2_INT_A_SIGEN_MASK 0x00000200 +#define SD4_EMMC_TOP_INTREN2_CRDIRQEN_SHIFT 8 +#define SD4_EMMC_TOP_INTREN2_CRDIRQEN_MASK 0x00000100 +#define SD4_EMMC_TOP_INTREN2_CRDRVMEN_SHIFT 7 +#define SD4_EMMC_TOP_INTREN2_CRDRVMEN_MASK 0x00000080 +#define SD4_EMMC_TOP_INTREN2_CRDINSEN_SHIFT 6 +#define SD4_EMMC_TOP_INTREN2_CRDINSEN_MASK 0x00000040 +#define SD4_EMMC_TOP_INTREN2_BUFRRDYEN_SHIFT 5 +#define SD4_EMMC_TOP_INTREN2_BUFRRDYEN_MASK 0x00000020 +#define SD4_EMMC_TOP_INTREN2_BUFWRDYEN_SHIFT 4 +#define SD4_EMMC_TOP_INTREN2_BUFWRDYEN_MASK 0x00000010 +#define SD4_EMMC_TOP_INTREN2_DMAIRQEN_SHIFT 3 +#define SD4_EMMC_TOP_INTREN2_DMAIRQEN_MASK 0x00000008 +#define SD4_EMMC_TOP_INTREN2_BLKGAPEN_SHIFT 2 +#define SD4_EMMC_TOP_INTREN2_BLKGAPEN_MASK 0x00000004 +#define SD4_EMMC_TOP_INTREN2_TXDONE_SHIFT 1 +#define SD4_EMMC_TOP_INTREN2_TXDONE_MASK 0x00000002 +#define SD4_EMMC_TOP_INTREN2_CMDDONE_SHIFT 0 +#define SD4_EMMC_TOP_INTREN2_CMDDONE_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTREN2_SD4_OFFSET 0x00000038 +#define SD4_EMMC_TOP_INTREN2_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTREN2_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_INTREN2_SD4_RESERVED_MASK 0xF0006000 +#define SD4_EMMC_TOP_INTREN2_SD4_TRESPERRSEN_SHIFT 27 +#define SD4_EMMC_TOP_INTREN2_SD4_TRESPERRSEN_MASK 0x08000000 +#define SD4_EMMC_TOP_INTREN2_SD4_TUNERRSIGEN_SHIFT 26 +#define SD4_EMMC_TOP_INTREN2_SD4_TUNERRSIGEN_MASK 0x04000000 +#define SD4_EMMC_TOP_INTREN2_SD4_ADMASIGEN_SHIFT 25 +#define SD4_EMMC_TOP_INTREN2_SD4_ADMASIGEN_MASK 0x02000000 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDSIGEN_SHIFT 24 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDSIGEN_MASK 0x01000000 +#define SD4_EMMC_TOP_INTREN2_SD4_ILIMSIGEN_SHIFT 23 +#define SD4_EMMC_TOP_INTREN2_SD4_ILIMSIGEN_MASK 0x00800000 +#define SD4_EMMC_TOP_INTREN2_SD4_DEBSIGEN_SHIFT 22 +#define SD4_EMMC_TOP_INTREN2_SD4_DEBSIGEN_MASK 0x00400000 +#define SD4_EMMC_TOP_INTREN2_SD4_DCRCSIGEN_SHIFT 21 +#define SD4_EMMC_TOP_INTREN2_SD4_DCRCSIGEN_MASK 0x00200000 +#define SD4_EMMC_TOP_INTREN2_SD4_DTOSIGEN_SHIFT 20 +#define SD4_EMMC_TOP_INTREN2_SD4_DTOSIGEN_MASK 0x00100000 +#define SD4_EMMC_TOP_INTREN2_SD4_CIDXSIGEN_SHIFT 19 +#define SD4_EMMC_TOP_INTREN2_SD4_CIDXSIGEN_MASK 0x00080000 +#define SD4_EMMC_TOP_INTREN2_SD4_CEBSIGEN_SHIFT 18 +#define SD4_EMMC_TOP_INTREN2_SD4_CEBSIGEN_MASK 0x00040000 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDCRCSIGEN_SHIFT 17 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDCRCSIGEN_MASK 0x00020000 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDTOSIGEN_SHIFT 16 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDTOSIGEN_MASK 0x00010000 +#define SD4_EMMC_TOP_INTREN2_SD4_FIXZERO_SHIFT 15 +#define SD4_EMMC_TOP_INTREN2_SD4_FIXZERO_MASK 0x00008000 +#define SD4_EMMC_TOP_INTREN2_SD4_RETUNE_EVENTSIGEN_SHIFT 12 +#define SD4_EMMC_TOP_INTREN2_SD4_RETUNE_EVENTSIGEN_MASK 0x00001000 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_C_SIGEN_SHIFT 11 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_C_SIGEN_MASK 0x00000800 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_B_SIGEN_SHIFT 10 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_B_SIGEN_MASK 0x00000400 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_A_SIGEN_SHIFT 9 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_A_SIGEN_MASK 0x00000200 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDIRQEN_SHIFT 8 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDIRQEN_MASK 0x00000100 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDRVMEN_SHIFT 7 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDRVMEN_MASK 0x00000080 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDINSEN_SHIFT 6 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDINSEN_MASK 0x00000040 +#define SD4_EMMC_TOP_INTREN2_SD4_BUFRRDYEN_SHIFT 5 +#define SD4_EMMC_TOP_INTREN2_SD4_BUFRRDYEN_MASK 0x00000020 +#define SD4_EMMC_TOP_INTREN2_SD4_BUFWRDYEN_SHIFT 4 +#define SD4_EMMC_TOP_INTREN2_SD4_BUFWRDYEN_MASK 0x00000010 +#define SD4_EMMC_TOP_INTREN2_SD4_DMAIRQEN_SHIFT 3 +#define SD4_EMMC_TOP_INTREN2_SD4_DMAIRQEN_MASK 0x00000008 +#define SD4_EMMC_TOP_INTREN2_SD4_BLKGAPEN_SHIFT 2 +#define SD4_EMMC_TOP_INTREN2_SD4_BLKGAPEN_MASK 0x00000004 +#define SD4_EMMC_TOP_INTREN2_SD4_TXDONE_SHIFT 1 +#define SD4_EMMC_TOP_INTREN2_SD4_TXDONE_MASK 0x00000002 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDDONE_SHIFT 0 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDDONE_MASK 0x00000001 + +#define SD4_EMMC_TOP_ERRSTAT_OFFSET 0x0000003C +#define SD4_EMMC_TOP_ERRSTAT_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ERRSTAT_TYPE uint32_t +#define SD4_EMMC_TOP_ERRSTAT_RESERVED_MASK 0x3F00FF60 +#define SD4_EMMC_TOP_ERRSTAT_PRESETEN_SHIFT 31 +#define SD4_EMMC_TOP_ERRSTAT_PRESETEN_MASK 0x80000000 +#define SD4_EMMC_TOP_ERRSTAT_ASYNC_INTREN_SHIFT 30 +#define SD4_EMMC_TOP_ERRSTAT_ASYNC_INTREN_MASK 0x40000000 +#define SD4_EMMC_TOP_ERRSTAT_SAMPLECLOCKSEL_SHIFT 23 +#define SD4_EMMC_TOP_ERRSTAT_SAMPLECLOCKSEL_MASK 0x00800000 +#define SD4_EMMC_TOP_ERRSTAT_EXECTUNE_SHIFT 22 +#define SD4_EMMC_TOP_ERRSTAT_EXECTUNE_MASK 0x00400000 +#define SD4_EMMC_TOP_ERRSTAT_DRVSTRESEL_SHIFT 20 +#define SD4_EMMC_TOP_ERRSTAT_DRVSTRESEL_MASK 0x00300000 +#define SD4_EMMC_TOP_ERRSTAT_EN1P8V_SHIFT 19 +#define SD4_EMMC_TOP_ERRSTAT_EN1P8V_MASK 0x00080000 +#define SD4_EMMC_TOP_ERRSTAT_UHSMODESEL_SHIFT 16 +#define SD4_EMMC_TOP_ERRSTAT_UHSMODESEL_MASK 0x00070000 +#define SD4_EMMC_TOP_ERRSTAT_NOCMD_SHIFT 7 +#define SD4_EMMC_TOP_ERRSTAT_NOCMD_MASK 0x00000080 +#define SD4_EMMC_TOP_ERRSTAT_CMDIDXERR_SHIFT 4 +#define SD4_EMMC_TOP_ERRSTAT_CMDIDXERR_MASK 0x00000010 +#define SD4_EMMC_TOP_ERRSTAT_CMDENDERR_SHIFT 3 +#define SD4_EMMC_TOP_ERRSTAT_CMDENDERR_MASK 0x00000008 +#define SD4_EMMC_TOP_ERRSTAT_CMDCRCERR_SHIFT 2 +#define SD4_EMMC_TOP_ERRSTAT_CMDCRCERR_MASK 0x00000004 +#define SD4_EMMC_TOP_ERRSTAT_CMDTOERR_SHIFT 1 +#define SD4_EMMC_TOP_ERRSTAT_CMDTOERR_MASK 0x00000002 +#define SD4_EMMC_TOP_ERRSTAT_CMDNOEXEC_SHIFT 0 +#define SD4_EMMC_TOP_ERRSTAT_CMDNOEXEC_MASK 0x00000001 + +#define SD4_EMMC_TOP_ERRSTAT_SD4_OFFSET 0x0000003C +#define SD4_EMMC_TOP_ERRSTAT_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_ERRSTAT_SD4_RESERVED_MASK 0x0E00FF40 +#define SD4_EMMC_TOP_ERRSTAT_SD4_PRESETEN_SHIFT 31 +#define SD4_EMMC_TOP_ERRSTAT_SD4_PRESETEN_MASK 0x80000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_ASYNC_INTREN_SHIFT 30 +#define SD4_EMMC_TOP_ERRSTAT_SD4_ASYNC_INTREN_MASK 0x40000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_ADDR64_SHIFT 29 +#define SD4_EMMC_TOP_ERRSTAT_SD4_ADDR64_MASK 0x20000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_HOSTVER4_00_SHIFT 28 +#define SD4_EMMC_TOP_ERRSTAT_SD4_HOSTVER4_00_MASK 0x10000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_UHS2INTFEN_SHIFT 24 +#define SD4_EMMC_TOP_ERRSTAT_SD4_UHS2INTFEN_MASK 0x01000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_SAMPLECLOCKSEL_SHIFT 23 +#define SD4_EMMC_TOP_ERRSTAT_SD4_SAMPLECLOCKSEL_MASK 0x00800000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_EXECTUNE_SHIFT 22 +#define SD4_EMMC_TOP_ERRSTAT_SD4_EXECTUNE_MASK 0x00400000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_DRVSTRESEL_SHIFT 20 +#define SD4_EMMC_TOP_ERRSTAT_SD4_DRVSTRESEL_MASK 0x00300000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_EN1P8V_SHIFT 19 +#define SD4_EMMC_TOP_ERRSTAT_SD4_EN1P8V_MASK 0x00080000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_UHSMODESEL_SHIFT 16 +#define SD4_EMMC_TOP_ERRSTAT_SD4_UHSMODESEL_MASK 0x00070000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_NOCMD_SHIFT 7 +#define SD4_EMMC_TOP_ERRSTAT_SD4_NOCMD_MASK 0x00000080 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDRESPERR_SHIFT 5 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDRESPERR_MASK 0x00000020 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDIDXERR_SHIFT 4 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDIDXERR_MASK 0x00000010 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDENDERR_SHIFT 3 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDENDERR_MASK 0x00000008 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDCRCERR_SHIFT 2 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDCRCERR_MASK 0x00000004 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDTOERR_SHIFT 1 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDTOERR_MASK 0x00000002 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDNOEXEC_SHIFT 0 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDNOEXEC_MASK 0x00000001 + +#define SD4_EMMC_TOP_CAPABILITIES1_OFFSET 0x00000040 +#define SD4_EMMC_TOP_CAPABILITIES1_DEFAULT 0x17EFD0B0 +#define SD4_EMMC_TOP_CAPABILITIES1_TYPE uint32_t +#define SD4_EMMC_TOP_CAPABILITIES1_RESERVED_MASK 0x08100040 +#define SD4_EMMC_TOP_CAPABILITIES1_SLOTTYPE_SHIFT 30 +#define SD4_EMMC_TOP_CAPABILITIES1_SLOTTYPE_MASK 0xC0000000 +#define SD4_EMMC_TOP_CAPABILITIES1_ASYNCHIRQ_SHIFT 29 +#define SD4_EMMC_TOP_CAPABILITIES1_ASYNCHIRQ_MASK 0x20000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SYSBUS64_SHIFT 28 +#define SD4_EMMC_TOP_CAPABILITIES1_SYSBUS64_MASK 0x10000000 +#define SD4_EMMC_TOP_CAPABILITIES1_V18_SHIFT 26 +#define SD4_EMMC_TOP_CAPABILITIES1_V18_MASK 0x04000000 +#define SD4_EMMC_TOP_CAPABILITIES1_V3_SHIFT 25 +#define SD4_EMMC_TOP_CAPABILITIES1_V3_MASK 0x02000000 +#define SD4_EMMC_TOP_CAPABILITIES1_V33_SHIFT 24 +#define SD4_EMMC_TOP_CAPABILITIES1_V33_MASK 0x01000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SUPRSM_SHIFT 23 +#define SD4_EMMC_TOP_CAPABILITIES1_SUPRSM_MASK 0x00800000 +#define SD4_EMMC_TOP_CAPABILITIES1_SDMA_SHIFT 22 +#define SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK 0x00400000 +#define SD4_EMMC_TOP_CAPABILITIES1_HSPEED_SHIFT 21 +#define SD4_EMMC_TOP_CAPABILITIES1_HSPEED_MASK 0x00200000 +#define SD4_EMMC_TOP_CAPABILITIES1_ADMA2_SHIFT 19 +#define SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK 0x00080000 +#define SD4_EMMC_TOP_CAPABILITIES1_EXTBUSMED_SHIFT 18 +#define SD4_EMMC_TOP_CAPABILITIES1_EXTBUSMED_MASK 0x00040000 +#define SD4_EMMC_TOP_CAPABILITIES1_MAXBLK_SHIFT 16 +#define SD4_EMMC_TOP_CAPABILITIES1_MAXBLK_MASK 0x00030000 +#define SD4_EMMC_TOP_CAPABILITIES1_BCLK_SHIFT 8 +#define SD4_EMMC_TOP_CAPABILITIES1_BCLK_MASK 0x0000FF00 +#define SD4_EMMC_TOP_CAPABILITIES1_TOUT_SHIFT 7 +#define SD4_EMMC_TOP_CAPABILITIES1_TOUT_MASK 0x00000080 +#define SD4_EMMC_TOP_CAPABILITIES1_TOUTFREQ_SHIFT 0 +#define SD4_EMMC_TOP_CAPABILITIES1_TOUTFREQ_MASK 0x0000003F + +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_OFFSET 0x00000040 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_DEFAULT 0x10E934B4 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_RESERVED_MASK 0x08100040 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SLOTTYPE_SHIFT 30 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SLOTTYPE_MASK 0xC0000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ASYNCHIRQ_SHIFT 29 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ASYNCHIRQ_MASK 0x20000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SYSBUS64_SHIFT 28 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SYSBUS64_MASK 0x10000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V18_SHIFT 26 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V18_MASK 0x04000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V3_SHIFT 25 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V3_MASK 0x02000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V33_SHIFT 24 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V33_MASK 0x01000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SUPRSM_SHIFT 23 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SUPRSM_MASK 0x00800000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SDMA_SHIFT 22 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SDMA_MASK 0x00400000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_HSPEED_SHIFT 21 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_HSPEED_MASK 0x00200000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ADMA2_SHIFT 19 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ADMA2_MASK 0x00080000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_EXTBUSMED_SHIFT 18 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_EXTBUSMED_MASK 0x00040000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_MAXBLK_SHIFT 16 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_MAXBLK_MASK 0x00030000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_BCLK_SHIFT 8 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_BCLK_MASK 0x0000FF00 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUT_SHIFT 7 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUT_MASK 0x00000080 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUTFREQ_SHIFT 0 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUTFREQ_MASK 0x0000003F + +#define SD4_EMMC_TOP_CAPABILITIES2_OFFSET 0x00000044 +#define SD4_EMMC_TOP_CAPABILITIES2_DEFAULT 0x03002177 +#define SD4_EMMC_TOP_CAPABILITIES2_TYPE uint32_t +#define SD4_EMMC_TOP_CAPABILITIES2_RESERVED_MASK 0xFC001088 +#define SD4_EMMC_TOP_CAPABILITIES2_SPIBLOCKMODE_SHIFT 25 +#define SD4_EMMC_TOP_CAPABILITIES2_SPIBLOCKMODE_MASK 0x02000000 +#define SD4_EMMC_TOP_CAPABILITIES2_SPIMODE_CAP_SHIFT 24 +#define SD4_EMMC_TOP_CAPABILITIES2_SPIMODE_CAP_MASK 0x01000000 +#define SD4_EMMC_TOP_CAPABILITIES2_CLOCKMULT_SHIFT 16 +#define SD4_EMMC_TOP_CAPABILITIES2_CLOCKMULT_MASK 0x00FF0000 +#define SD4_EMMC_TOP_CAPABILITIES2_RETUNE_MODE_SHIFT 14 +#define SD4_EMMC_TOP_CAPABILITIES2_RETUNE_MODE_MASK 0x0000C000 +#define SD4_EMMC_TOP_CAPABILITIES2_USETUNE_SDR50_SHIFT 13 +#define SD4_EMMC_TOP_CAPABILITIES2_USETUNE_SDR50_MASK 0x00002000 +#define SD4_EMMC_TOP_CAPABILITIES2_TMRCNT_RETUNE_SHIFT 8 +#define SD4_EMMC_TOP_CAPABILITIES2_TMRCNT_RETUNE_MASK 0x00000F00 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPED_SHIFT 6 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPED_MASK 0x00000040 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEC_SHIFT 5 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEC_MASK 0x00000020 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEA_SHIFT 4 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEA_MASK 0x00000010 +#define SD4_EMMC_TOP_CAPABILITIES2_DDR50_SHIFT 2 +#define SD4_EMMC_TOP_CAPABILITIES2_DDR50_MASK 0x00000004 +#define SD4_EMMC_TOP_CAPABILITIES2_SDR104_SHIFT 1 +#define SD4_EMMC_TOP_CAPABILITIES2_SDR104_MASK 0x00000002 +#define SD4_EMMC_TOP_CAPABILITIES2_SDR50_SHIFT 0 +#define SD4_EMMC_TOP_CAPABILITIES2_SDR50_MASK 0x00000001 + +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_OFFSET 0x00000044 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DEFAULT 0x10000064 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RESERVED_MASK 0xE7001080 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_VDD2_18_SHIFT 28 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_VDD2_18_MASK 0x10000000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_ADMA3_SHIFT 27 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_ADMA3_MASK 0x08000000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_CLOCKMULT_SHIFT 16 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_CLOCKMULT_MASK 0x00FF0000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RETUNE_MODE_SHIFT 14 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RETUNE_MODE_MASK 0x0000C000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_USETUNE_SDR50_SHIFT 13 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_USETUNE_SDR50_MASK 0x00002000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TMRCNT_RETUNE_SHIFT 8 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TMRCNT_RETUNE_MASK 0x00000F00 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPED_SHIFT 6 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPED_MASK 0x00000040 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEC_SHIFT 5 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEC_MASK 0x00000020 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEA_SHIFT 4 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEA_MASK 0x00000010 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_UHS_II_SHIFT 3 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_UHS_II_MASK 0x00000008 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DDR50_SHIFT 2 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DDR50_MASK 0x00000004 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR104_SHIFT 1 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR104_MASK 0x00000002 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR50_SHIFT 0 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR50_MASK 0x00000001 + +#define SD4_EMMC_TOP_MAX_A1_OFFSET 0x00000048 +#define SD4_EMMC_TOP_MAX_A1_DEFAULT 0x00000001 +#define SD4_EMMC_TOP_MAX_A1_TYPE uint32_t +#define SD4_EMMC_TOP_MAX_A1_RESERVED_MASK 0xFF000000 +#define SD4_EMMC_TOP_MAX_A1_MAXA18_SHIFT 16 +#define SD4_EMMC_TOP_MAX_A1_MAXA18_MASK 0x00FF0000 +#define SD4_EMMC_TOP_MAX_A1_MAXA30_SHIFT 8 +#define SD4_EMMC_TOP_MAX_A1_MAXA30_MASK 0x0000FF00 +#define SD4_EMMC_TOP_MAX_A1_MAXA33_SHIFT 0 +#define SD4_EMMC_TOP_MAX_A1_MAXA33_MASK 0x000000FF + +#define SD4_EMMC_TOP_MAX_A2_OFFSET 0x0000004C +#define SD4_EMMC_TOP_MAX_A2_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_MAX_A2_TYPE uint32_t +#define SD4_EMMC_TOP_MAX_A2_RESERVED_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_MAX_A2_SD4_OFFSET 0x0000004C +#define SD4_EMMC_TOP_MAX_A2_SD4_DEFAULT 0x00000001 +#define SD4_EMMC_TOP_MAX_A2_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_MAX_A2_SD4_RESERVED_MASK 0xFFFFFF00 +#define SD4_EMMC_TOP_MAX_A2_SD4_MAXAVDD2_SHIFT 0 +#define SD4_EMMC_TOP_MAX_A2_SD4_MAXAVDD2_MASK 0x000000FF + +#define SD4_EMMC_TOP_CMDENTSTAT_OFFSET 0x00000050 +#define SD4_EMMC_TOP_CMDENTSTAT_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CMDENTSTAT_TYPE uint32_t +#define SD4_EMMC_TOP_CMDENTSTAT_RESERVED_MASK 0x2C00FF60 +#define SD4_EMMC_TOP_CMDENTSTAT_VSES_SHIFT 30 +#define SD4_EMMC_TOP_CMDENTSTAT_VSES_MASK 0xC0000000 +#define SD4_EMMC_TOP_CMDENTSTAT_TRERR_SHIFT 28 +#define SD4_EMMC_TOP_CMDENTSTAT_TRERR_MASK 0x10000000 +#define SD4_EMMC_TOP_CMDENTSTAT_ADMAERR_SHIFT 25 +#define SD4_EMMC_TOP_CMDENTSTAT_ADMAERR_MASK 0x02000000 +#define SD4_EMMC_TOP_CMDENTSTAT_ACMDERR_SHIFT 24 +#define SD4_EMMC_TOP_CMDENTSTAT_ACMDERR_MASK 0x01000000 +#define SD4_EMMC_TOP_CMDENTSTAT_ILERR_SHIFT 23 +#define SD4_EMMC_TOP_CMDENTSTAT_ILERR_MASK 0x00800000 +#define SD4_EMMC_TOP_CMDENTSTAT_DENDERR_SHIFT 22 +#define SD4_EMMC_TOP_CMDENTSTAT_DENDERR_MASK 0x00400000 +#define SD4_EMMC_TOP_CMDENTSTAT_DCRCERR_SHIFT 21 +#define SD4_EMMC_TOP_CMDENTSTAT_DCRCERR_MASK 0x00200000 +#define SD4_EMMC_TOP_CMDENTSTAT_DTOUTERR_SHIFT 20 +#define SD4_EMMC_TOP_CMDENTSTAT_DTOUTERR_MASK 0x00100000 +#define SD4_EMMC_TOP_CMDENTSTAT_CIDXERR_SHIFT 19 +#define SD4_EMMC_TOP_CMDENTSTAT_CIDXERR_MASK 0x00080000 +#define SD4_EMMC_TOP_CMDENTSTAT_CENDERR_SHIFT 18 +#define SD4_EMMC_TOP_CMDENTSTAT_CENDERR_MASK 0x00040000 +#define SD4_EMMC_TOP_CMDENTSTAT_CCRCERR_SHIFT 17 +#define SD4_EMMC_TOP_CMDENTSTAT_CCRCERR_MASK 0x00020000 +#define SD4_EMMC_TOP_CMDENTSTAT_CTOUTERR_SHIFT 16 +#define SD4_EMMC_TOP_CMDENTSTAT_CTOUTERR_MASK 0x00010000 +#define SD4_EMMC_TOP_CMDENTSTAT_NOFRCENT_SHIFT 7 +#define SD4_EMMC_TOP_CMDENTSTAT_NOFRCENT_MASK 0x00000080 +#define SD4_EMMC_TOP_CMDENTSTAT_IDXERR_SHIFT 4 +#define SD4_EMMC_TOP_CMDENTSTAT_IDXERR_MASK 0x00000010 +#define SD4_EMMC_TOP_CMDENTSTAT_EBITERR_SHIFT 3 +#define SD4_EMMC_TOP_CMDENTSTAT_EBITERR_MASK 0x00000008 +#define SD4_EMMC_TOP_CMDENTSTAT_CRCERR_SHIFT 2 +#define SD4_EMMC_TOP_CMDENTSTAT_CRCERR_MASK 0x00000004 +#define SD4_EMMC_TOP_CMDENTSTAT_TOUTERR_SHIFT 1 +#define SD4_EMMC_TOP_CMDENTSTAT_TOUTERR_MASK 0x00000002 +#define SD4_EMMC_TOP_CMDENTSTAT_AUTONOEX_SHIFT 0 +#define SD4_EMMC_TOP_CMDENTSTAT_AUTONOEX_MASK 0x00000001 + +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_OFFSET 0x00000050 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESERVED_MASK 0x0000FF40 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_VSES_SHIFT 28 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_VSES_MASK 0xF0000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TRESPERR_SHIFT 27 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TRESPERR_MASK 0x08000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TUNERR_SHIFT 26 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TUNERR_MASK 0x04000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ADMAERR_SHIFT 25 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ADMAERR_MASK 0x02000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ACMDERR_SHIFT 24 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ACMDERR_MASK 0x01000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ILERR_SHIFT 23 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ILERR_MASK 0x00800000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DENDERR_SHIFT 22 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DENDERR_MASK 0x00400000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DCRCERR_SHIFT 21 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DCRCERR_MASK 0x00200000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DTOUTERR_SHIFT 20 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DTOUTERR_MASK 0x00100000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CIDXERR_SHIFT 19 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CIDXERR_MASK 0x00080000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CENDERR_SHIFT 18 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CENDERR_MASK 0x00040000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CCRCERR_SHIFT 17 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CCRCERR_MASK 0x00020000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CTOUTERR_SHIFT 16 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CTOUTERR_MASK 0x00010000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_NOFRCENT_SHIFT 7 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_NOFRCENT_MASK 0x00000080 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESPERR_SHIFT 5 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESPERR_MASK 0x00000020 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_IDXERR_SHIFT 4 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_IDXERR_MASK 0x00000010 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_EBITERR_SHIFT 3 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_EBITERR_MASK 0x00000008 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CRCERR_SHIFT 2 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CRCERR_MASK 0x00000004 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TOUTERR_SHIFT 1 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TOUTERR_MASK 0x00000002 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_AUTONOEX_SHIFT 0 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_AUTONOEX_MASK 0x00000001 + +#define SD4_EMMC_TOP_ADMAERR_OFFSET 0x00000054 +#define SD4_EMMC_TOP_ADMAERR_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ADMAERR_TYPE uint32_t +#define SD4_EMMC_TOP_ADMAERR_RESERVED_MASK 0xFFFFFFF8 +#define SD4_EMMC_TOP_ADMAERR_ADMALERR_SHIFT 2 +#define SD4_EMMC_TOP_ADMAERR_ADMALERR_MASK 0x00000004 +#define SD4_EMMC_TOP_ADMAERR_ADMAERR_SHIFT 0 +#define SD4_EMMC_TOP_ADMAERR_ADMAERR_MASK 0x00000003 + +#define SD4_EMMC_TOP_ADMAADDR0_OFFSET 0x00000058 +#define SD4_EMMC_TOP_ADMAADDR0_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ADMAADDR0_TYPE uint32_t +#define SD4_EMMC_TOP_ADMAADDR0_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_ADMAADDR0_ADMAADDR0_SHIFT 0 +#define SD4_EMMC_TOP_ADMAADDR0_ADMAADDR0_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_ADMAADDR1_OFFSET 0x0000005C +#define SD4_EMMC_TOP_ADMAADDR1_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ADMAADDR1_TYPE uint32_t +#define SD4_EMMC_TOP_ADMAADDR1_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_ADMAADDR1_ADMAADDR1_SHIFT 0 +#define SD4_EMMC_TOP_ADMAADDR1_ADMAADDR1_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_PRESETVAL1_OFFSET 0x00000060 +#define SD4_EMMC_TOP_PRESETVAL1_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_PRESETVAL1_TYPE uint32_t +#define SD4_EMMC_TOP_PRESETVAL1_RESERVED_MASK 0x38003800 +#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_DFS_SHIFT 30 +#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_DFS_MASK 0xC0000000 +#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_DFS_SHIFT 26 +#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_DFS_MASK 0x04000000 +#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_DFS_SHIFT 16 +#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_DFS_MASK 0x03FF0000 +#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_INIT_SHIFT 14 +#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_INIT_MASK 0x0000C000 +#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_INIT_SHIFT 10 +#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_INIT_MASK 0x00000400 +#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_INIT_SHIFT 0 +#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_INIT_MASK 0x000003FF + +#define SD4_EMMC_TOP_PRESETVAL2_OFFSET 0x00000064 +#define SD4_EMMC_TOP_PRESETVAL2_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_PRESETVAL2_TYPE uint32_t +#define SD4_EMMC_TOP_PRESETVAL2_RESERVED_MASK 0x38003800 +#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_SDR12_SHIFT 30 +#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_SDR12_MASK 0xC0000000 +#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_SDR12_SHIFT 26 +#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_SDR12_MASK 0x04000000 +#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_SDR12_SHIFT 16 +#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_SDR12_MASK 0x03FF0000 +#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_HS_SHIFT 14 +#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_HS_MASK 0x0000C000 +#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_HS_SHIFT 10 +#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_HS_MASK 0x00000400 +#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_HS_SHIFT 0 +#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_HS_MASK 0x000003FF + +#define SD4_EMMC_TOP_PRESETVAL3_OFFSET 0x00000068 +#define SD4_EMMC_TOP_PRESETVAL3_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_PRESETVAL3_TYPE uint32_t +#define SD4_EMMC_TOP_PRESETVAL3_RESERVED_MASK 0x38003800 +#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR50_SHIFT 30 +#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR50_MASK 0xC0000000 +#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR50_SHIFT 26 +#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR50_MASK 0x04000000 +#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR50_SHIFT 16 +#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR50_MASK 0x03FF0000 +#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR25_SHIFT 14 +#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR25_MASK 0x0000C000 +#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR25_SHIFT 10 +#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR25_MASK 0x00000400 +#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR25_SHIFT 0 +#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR25_MASK 0x000003FF + +#define SD4_EMMC_TOP_PRESETVAL4_OFFSET 0x0000006C +#define SD4_EMMC_TOP_PRESETVAL4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_PRESETVAL4_TYPE uint32_t +#define SD4_EMMC_TOP_PRESETVAL4_RESERVED_MASK 0x38003800 +#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_DDR50_SHIFT 30 +#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_DDR50_MASK 0xC0000000 +#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_DDR50_SHIFT 26 +#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_DDR50_MASK 0x04000000 +#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_DDR50_SHIFT 16 +#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_DDR50_MASK 0x03FF0000 +#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_SDR104_SHIFT 14 +#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_SDR104_MASK 0x0000C000 +#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_SDR104_SHIFT 10 +#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_SDR104_MASK 0x00000400 +#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_SDR104_SHIFT 0 +#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_SDR104_MASK 0x000003FF + +#define SD4_EMMC_TOP_BOOTTIMEOUT_OFFSET 0x00000070 +#define SD4_EMMC_TOP_BOOTTIMEOUT_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_BOOTTIMEOUT_TYPE uint32_t +#define SD4_EMMC_TOP_BOOTTIMEOUT_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_BOOTTIMEOUT_BOOTDATATIMEOUTCTRVALUE_SHIFT 0 +#define SD4_EMMC_TOP_BOOTTIMEOUT_BOOTDATATIMEOUTCTRVALUE_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_DBGSEL_OFFSET 0x00000074 +#define SD4_EMMC_TOP_DBGSEL_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_DBGSEL_TYPE uint32_t +#define SD4_EMMC_TOP_DBGSEL_RESERVED_MASK 0xFFFFFFFE +#define SD4_EMMC_TOP_DBGSEL_DBGSEL_SHIFT 0 +#define SD4_EMMC_TOP_DBGSEL_DBGSEL_MASK 0x00000001 + +#define SD4_EMMC_TOP_UHS2_PRESETVAL_OFFSET 0x00000074 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_TYPE uint32_t +#define SD4_EMMC_TOP_UHS2_PRESETVAL_RESERVED_MASK 0xFFFF3800 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_DRVSTRVAL_SHIFT 14 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_DRVSTRVAL_MASK 0x0000C000 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_CLKGENSELVAL_SHIFT 10 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_CLKGENSELVAL_MASK 0x00000400 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_SDCLKFREQSELVAL_SHIFT 0 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_SDCLKFREQSELVAL_MASK 0x000003FF + +#define SD4_EMMC_TOP_HCVERSIRQ_OFFSET 0x000000FC +#define SD4_EMMC_TOP_HCVERSIRQ_DEFAULT 0x10020000 +#define SD4_EMMC_TOP_HCVERSIRQ_TYPE uint32_t +#define SD4_EMMC_TOP_HCVERSIRQ_RESERVED_MASK 0x0000FF00 +#define SD4_EMMC_TOP_HCVERSIRQ_VENDVER_SHIFT 24 +#define SD4_EMMC_TOP_HCVERSIRQ_VENDVER_MASK 0xFF000000 +#define SD4_EMMC_TOP_HCVERSIRQ_SPECVER_SHIFT 16 +#define SD4_EMMC_TOP_HCVERSIRQ_SPECVER_MASK 0x00FF0000 +#define SD4_EMMC_TOP_HCVERSIRQ_SIRQ_SHIFT 0 +#define SD4_EMMC_TOP_HCVERSIRQ_SIRQ_MASK 0x000000FF + +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_OFFSET 0x000000FC +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_DEFAULT 0x01030000 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_RESERVED_MASK 0x0000FF00 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_VENDVER_SHIFT 24 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_VENDVER_MASK 0xFF000000 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SPECVER_SHIFT 16 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SPECVER_MASK 0x00FF0000 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SIRQ_SHIFT 0 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SIRQ_MASK 0x000000FF + +#endif /* BRCM_RDB_SD4_EMMC_TOP_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h new file mode 100644 index 0000000..8d223f9 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CHAL_SD_H +#define CHAL_SD_H + +#include + +#define BASE_CLK_FREQ (200 * 1000 * 1000) +#define INIT_CLK_FREQ (400 * 1000) + +#define SD_ERROR_RECOVERABLE 0 +#define SD_ERROR_NON_RECOVERABLE 1 + +#define SD_OK 0 +#define SD_FAIL (-1) +#define SD_INVALID_HANDLE (-2) +#define SD_CEATA_INIT_ERROR (-3) +#define SD_RESET_ERROR (-4) +#define SD_CARD_INIT_ERROR (-5) +#define SD_INV_DATA_WIDTH (-6) +#define SD_SET_BUS_WIDTH_ERROR (-7) +#define SD_DMA_NOT_SUPPORT (-8) +#define SD_SDIO_READ_ERROR (-9) +#define SD_SDIO_WRITE_ERROR (-10) +#define SD_WRITE_ERROR (-11) +#define SD_READ_ERROR (-12) +#define SD_READ_SIZE_ERROR (-13) +#define SD_RW_ADDRESS_ERROR (-14) +#define SD_XFER_ADDRESS_ERROR (-15) +#define SD_DATA_XFER_ADDR_ERROR (-16) +#define SD_DATA_XFER_ERROR (-17) +#define SD_WRITE_SIZE_ERROR (-18) +#define SD_CMD_STATUS_UPDATE_ERR (-19) +#define SD_CMD12_ERROR (-20) +#define SD_CMD_DATA_ERROR (-21) +#define SD_CMD_TIMEOUT (-22) +#define SD_CMD_NO_RESPONSE (-22) +#define SD_CMD_ABORT_ERROR (-23) +#define SD_CMD_INVALID (-24) +#define SD_CMD_RESUME_ERROR (-25) +#define SD_CMD_ERR_INVALID_RESPONSE (-26) +#define SD_WAIT_TIMEOUT (-27) +#define SD_READ_TIMEOUT (-28) +#define SD_CEATA_REST_ERROR (-29) +#define SD_INIT_CAED_FAILED (-30) +#define SD_ERROR_CLOCK_OFFLIMIT (-31) +#define SD_INV_SLOT (-32) + +#define SD_NOR_INTERRUPTS 0x000000FF +#define SD_ERR_INTERRUPTS 0x03FF0000 +#define SD_CMD_ERROR_INT 0x010F0000 +#define SD_DAT_ERROR_INT 0x02F00000 +#define SD_DAT_TIMEOUT 0x00100000 + +/* Operation modes */ +#define SD_PIO_MODE 0 +#define SD_INT_MODE 1 + +/* Support both ADMA and SDMA (for version 2.0 and above) */ +#define SD_DMA_OFF 0 +#define SD_DMA_SDMA 1 +#define SD_DMA_ADMA 2 + +#define SD_NORMAL_SPEED 0 +#define SD_HIGH_SPEED 1 + +#define SD_XFER_CARD_TO_HOST 3 +#define SD_XFER_HOST_TO_CARD 4 + +#define SD_CARD_DETECT_AUTO 0 +#define SD_CARD_DETECT_SD 1 +#define SD_CARD_DETECT_SDIO 2 +#define SD_CARD_DETECT_MMC 3 +#define SD_CARD_DETECT_CEATA 4 + +#define SD_ABORT_SYNC_MODE 0 +#define SD_ABORT_ASYNC_MODE 1 + +#define SD_CMD_ERROR_FLAGS (0x18F << 16) +#define SD_DATA_ERROR_FLAGS (0x70 << 16) +#define SD_AUTO_CMD12_ERROR_FLAGS (0x9F) + +#define SD_CARD_STATUS_ERROR 0x10000000 +#define SD_CMD_MISSING 0x80000000 +#define SD_ERROR_INT 0x8000 + +#define SD_TRAN_HIGH_SPEED 0x32 +#define SD_CARD_HIGH_CAPACITY 0x40000000 +#define SD_CARD_POWER_UP_STATUS 0x80000000 + +#define SD_HOST_CORE_TIMEOUT 0x0E + +/* SD CARD and Host Controllers bus width */ +#define SD_BUS_DATA_WIDTH_1BIT 0x00 +#define SD_BUS_DATA_WIDTH_4BIT 0x02 +#define SD_BUS_DATA_WIDTH_8BIT 0x20 + +/* dma boundary settings */ +#define SD_DMA_BOUNDARY_4K 0 +#define SD_DMA_BOUNDARY_8K (1 << 12) +#define SD_DMA_BOUNDARY_16K (2 << 12) +#define SD_DMA_BOUNDARY_32K (3 << 12) +#define SD_DMA_BOUNDARY_64K (4 << 12) +#define SD_DMA_BOUNDARY_128K (5 << 12) +#define SD_DMA_BOUNDARY_256K (6 << 12) +#define SD_DMA_BOUNDARY_512K (7 << 12) + +#define SD_CMDR_CMD_NORMAL 0x00000000 +#define SD_CMDR_CMD_SUSPEND 0x00400000 +#define SD_CMDR_CMD_RESUME 0x00800000 +#define SD_CMDR_CMD_ABORT 0x00c00000 + +#define SD_CMDR_RSP_TYPE_NONE 0x0 +#define SD_CMDR_RSP_TYPE_R2 0x1 +#define SD_CMDR_RSP_TYPE_R3_4 0x2 +#define SD_CMDR_RSP_TYPE_R1_5_6 0x2 +#define SD_CMDR_RSP_TYPE_R1b_5b 0x3 +#define SD_CMDR_RSP_TYPE_S 16 + +struct sd_ctrl_info { + uint32_t blkReg; /* current block register cache value */ + uint32_t cmdReg; /* current command register cache value */ + uint32_t argReg; /* current argument register cache value */ + uint32_t cmdIndex; /* current command index */ + uint32_t cmdStatus; /* current command status, cmd/data compelete */ + uint16_t rca; /* relative card address */ + uint32_t ocr; /* operation codition */ + uint32_t eventList; /* events list */ + uint32_t blkGapEnable; + + uint32_t capability; /* controller's capbilities */ + uint32_t maxCurrent; /* maximum current supported */ + uint32_t present; /* if card is inserted or removed */ + uint32_t version; /* SD spec version 1.0 or 2.0 */ + uint32_t vendor; /* vendor number */ + + uintptr_t sdRegBaseAddr; /* sdio control registers */ + uintptr_t hostRegBaseAddr; /* SD Host control registers */ +}; + +struct sd_cfg { + uint32_t mode; /* interrupt or polling */ + uint32_t dma; /* dma enabled or disabled */ + uint32_t retryLimit; /* command retry limit */ + uint32_t speedMode; /* speed mode, 0 standard, 1 high speed */ + uint32_t voltage; /* voltage level */ + uint32_t blockSize; /* access block size (512 for HC card) */ + uint32_t dmaBoundary; /* dma address boundary */ + uint32_t detSignal; /* card det signal src, for test purpose only */ + uint32_t rdWaiting; + uint32_t wakeupOut; + uint32_t wakeupIn; + uint32_t wakeupInt; + uint32_t wfe_retry; + uint32_t gapInt; + uint32_t readWait; + uint32_t led; +}; + +struct sd_dev { + struct sd_cfg cfg; /* SD configuration */ + struct sd_ctrl_info ctrl; /* SD info */ +}; + +int32_t chal_sd_start(CHAL_HANDLE *sdHandle, uint32_t mode, + uint32_t sdBase, uint32_t hostBase); +int32_t chal_sd_config(CHAL_HANDLE *sdHandle, uint32_t speed, + uint32_t retry, uint32_t boundary, + uint32_t blkSize, uint32_t dma); +int32_t chal_sd_stop(void); +int32_t chal_sd_set_dma(CHAL_HANDLE *sdHandle, uint32_t mode); +uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *handle); +int32_t chal_sd_config_bus_width(CHAL_HANDLE *sdHandle, int32_t width); +int32_t chal_sd_send_cmd(CHAL_HANDLE *sdHandle, uint32_t cmdIndex, + uint32_t arg, uint32_t options); +int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sdHandle, uintptr_t address); +int32_t chal_sd_set_clock(CHAL_HANDLE *sdHandle, + uint32_t div_ctrl_setting, uint32_t on); +uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq); +int32_t chal_sd_setup_xfer(CHAL_HANDLE *sdHandle, uint8_t *data, + uint32_t length, int32_t dir); +int32_t chal_sd_write_buffer(CHAL_HANDLE *sdHandle, uint32_t length, + uint8_t *data); +int32_t chal_sd_read_buffer(CHAL_HANDLE *sdHandle, uint32_t length, + uint8_t *data); +int32_t chal_sd_reset_line(CHAL_HANDLE *sdHandle, uint32_t line); +int32_t chal_sd_get_response(CHAL_HANDLE *sdHandle, uint32_t *resp); +int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sdHandle); +int32_t chal_sd_get_irq_status(CHAL_HANDLE *sdHandle); +int32_t chal_sd_clear_irq(CHAL_HANDLE *sdHandle, uint32_t mask); +uint32_t chal_sd_get_present_status(CHAL_HANDLE *sdHandle); +int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sdHandle); +void chal_sd_set_speed(CHAL_HANDLE *sdHandle, uint32_t speed); +int32_t chal_sd_check_cap(CHAL_HANDLE *sdHandle, uint32_t cap); +void chal_sd_set_irq_signal(CHAL_HANDLE *sdHandle, uint32_t mask, + uint32_t state); +void chal_sd_dump_fifo(CHAL_HANDLE *sdHandle); +#endif /* CHAL_SD_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h new file mode 100644 index 0000000..9563273 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef CHAL_TYPES_H +#define CHAL_TYPES_H + +#include + +// +// Generic cHAL handler +// +#ifndef CHAL_HANDLE + typedef void *CHAL_HANDLE; ///< void pointer (32 bits wide) +#endif + +#endif /* _CHAL_TYPES_H_ */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h new file mode 100644 index 0000000..52b8bc8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSL_SD_H +#define CSL_SD_H + +#define SD_CLOCK_BASE 104000000 +#define SD_CLOCK_52MHZ 52000000 +#define SD_CLOCK_26MHZ 26000000 +#define SD_CLOCK_17MHZ 17330000 +#define SD_CLOCK_13MHZ 13000000 +#define SD_CLOCK_10MHZ 10000000 +#define SD_CLOCK_9MHZ 9000000 +#define SD_CLOCK_7MHZ 7000000 +#define SD_CLOCK_5MHZ 5000000 +#define SD_CLOCK_1MHZ 1000000 +#define SD_CLOCK_400KHZ 400000 + +#define SD_DRIVE_STRENGTH_MASK 0x38000000 +#if defined(_BCM213x1_) || defined(_BCM21551_) || defined(_ATHENA_) +#define SD_DRIVE_STRENGTH 0x28000000 +#elif defined(_BCM2153_) +#define SD_DRIVE_STRENGTH 0x38000000 +#else +#define SD_DRIVE_STRENGTH 0x00000000 +#endif + +#define SD_NUM_HOST 2 + +#define SD_CARD_UNLOCK 0 +#define SD_CARD_LOCK 0x4 +#define SD_CARD_CLEAR_PWD 0x2 +#define SD_CARD_SET_PWD 0x1 +#define SD_CARD_ERASE_PWD 0x8 + +#define SD_CARD_LOCK_STATUS 0x02000000 +#define SD_CARD_UNLOCK_STATUS 0x01000000 + +#define SD_CMD_ERROR_FLAGS (0x18F << 16) +#define SD_DATA_ERROR_FLAGS (0x70 << 16) +#define SD_AUTO_CMD12_ERROR_FLAGS (0x9F) +#define SD_CARD_STATUS_ERROR 0x10000000 +#define SD_CMD_MISSING 0x80000000 + +#define SD_TRAN_HIGH_SPEED 0x32 +#define SD_CARD_HIGH_CAPACITY 0x40000000 +#define SD_CARD_POWER_UP_STATUS 0x80000000 + +struct sd_dev_info { + uint32_t mode; /* interrupt or polling */ + uint32_t dma; /* dma enabled or disabled */ + uint32_t voltage; /* voltage level */ + uint32_t slot; /* if the HC is locatd at slot 0 or slot 1 */ + uint32_t version; /* 1.0 or 2.0 */ + uint32_t curSystemAddr; /* system address */ + uint32_t dataWidth; /* data width for the controller */ + uint32_t clock; /* clock rate */ + uint32_t status; /* if device is active on transfer or not */ +}; + +void data_xfer_setup(struct sd_handle *handle, uint8_t *data, + uint32_t length, int dir); +int reset_card(struct sd_handle *handle); +int reset_host_ctrl(struct sd_handle *handle); +int init_card(struct sd_handle *handle, int detection); +int init_mmc_card(struct sd_handle *handle); +int write_buffer(struct sd_handle *handle, uint32_t len, uint8_t *buffer); +int read_buffer(struct sd_handle *handle, uint32_t len, uint8_t *buffer); +int select_blk_sz(struct sd_handle *handle, uint16_t size); +int check_error(struct sd_handle *handle, uint32_t ints); + +int process_data_xfer(struct sd_handle *handle, uint8_t *buffer, + uint32_t addr, uint32_t length, int dir); +int read_block(struct sd_handle *handle, uint8_t *dst, uint32_t addr, + uint32_t len); +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks); +#endif +int write_block(struct sd_handle *handle, uint8_t *src, uint32_t addr, + uint32_t len); +int process_cmd_response(struct sd_handle *handle, uint32_t cmdIndex, + uint32_t rsp0, uint32_t rsp1, uint32_t rsp2, + uint32_t rsp3, struct sd_resp *resp); +int32_t set_config(struct sd_handle *handle, uint32_t speed, + uint32_t retry, uint32_t dma, uint32_t dmaBound, + uint32_t blkSize, uint32_t wfe_retry); + +uint32_t wait_for_event(struct sd_handle *handle, uint32_t mask, + uint32_t retry); +int set_boot_config(struct sd_handle *handle, uint32_t config); + +int mmc_cmd1(struct sd_handle *handle); +#endif /* CSL_SD_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h new file mode 100644 index 0000000..425603f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSL_SD_CMD_H +#define CSL_SD_CMD_H + +#define SD_CMD_OK 0 +#define SD_CMD_ERROR -1 + +#define SD_CMD_ERR_NO_IO_FUNC 5 +#define SD_CMD_ERR_INVALID_PARAMETER 6 +#define SD_CMD_ERR_R1_ILLEGAL_COMMAND 7 +#define SD_CMD_ERR_R1_COM_CRC_ERROR 8 +#define SD_CMD_ERR_R1_FUNC_NUM_ERROR 9 +#define SD_CMD_ERR_R1_ADDRESS_ERROR 10 +#define SD_CMD_ERR_R1_PARAMETER_ERROR 11 +#define SD_CMD_ERR_DATA_ERROR_TOKEN 12 +#define SD_CMD_ERR_DATA_NOT_ACCEPTED 13 +#define SD_CMD7_ARG_RCA_SHIFT 16 + +#define SD_CARD_STATUS_PENDING 0x01 +#define SD_CARD_STATUS_BUFFER_OVERFLOW 0x01 +#define SD_CARD_STATUS_DEVICE_BUSY 0x02 +#define SD_CARD_STATUS_UNSUCCESSFUL 0x03 +#define SD_CARD_STATUS_NOT_IMPLEMENTED 0x04 +#define SD_CARD_STATUS_ACCESS_VIOLATION 0x05 +#define SD_CARD_STATUS_INVALID_HANDLE 0x06 +#define SD_CARD_STATUS_INVALID_PARAMETER 0x07 +#define SD_CARD_STATUS_NO_SUCH_DEVICE 0x08 +#define SD_CARD_STATUS_INVALID_DEVICE_REQUEST 0x09 +#define SD_CARD_STATUS_NO_MEMORY 0x0A +#define SD_CARD_STATUS_BUS_DRIVER_NOT_READY 0x0B +#define SD_CARD_STATUS_DATA_ERROR 0x0C +#define SD_CARD_STATUS_CRC_ERROR 0x0D +#define SD_CARD_STATUS_INSUFFICIENT_RESOURCES 0x0E +#define SD_CARD_STATUS_DEVICE_NOT_CONNECTED 0x10 +#define SD_CARD_STATUS_DEVICE_REMOVED 0x11 +#define SD_CARD_STATUS_DEVICE_NOT_RESPONDING 0x12 +#define SD_CARD_STATUS_CANCELED 0x13 +#define SD_CARD_STATUS_RESPONSE_TIMEOUT 0x14 +#define SD_CARD_STATUS_DATA_TIMEOUT 0x15 +#define SD_CARD_STATUS_DEVICE_RESPONSE_ERROR 0x16 +#define SD_CARD_STATUS_DEVICE_UNSUPPORTED 0x17 + +/* Response structure */ +struct sd_r2_resp { + uint32_t rsp4; /* 127:96 */ + uint32_t rsp3; /* 95:64 */ + uint32_t rsp2; /* 63:32 */ + uint32_t rsp1; /* 31:0 */ +}; + +struct sd_r3_resp { + uint32_t ocr; +}; + +struct sd_r4_resp { + uint8_t cardReady; + uint8_t funcs; + uint8_t memPresent; + uint32_t ocr; +}; + +struct sd_r5_resp { + uint8_t data; +}; + +struct sd_r6_resp { + uint16_t rca; + uint16_t cardStatus; +}; + +struct sd_r7_resp { + uint16_t rca; +}; + +struct sd_resp { + uint8_t r1; + uint32_t cardStatus; + uint32_t rawData[4]; + union { + struct sd_r2_resp r2; + struct sd_r3_resp r3; + struct sd_r4_resp r4; + struct sd_r5_resp r5; + struct sd_r6_resp r6; + struct sd_r7_resp r7; + } data; +}; + +struct sd_card_info { + uint32_t type; /* card type SD, MMC or SDIO */ + uint64_t size; /* card size */ + uint32_t speed; /* card speed */ + uint32_t voltage; /* voltage supported */ + uint32_t mId; /* manufacturer ID */ + uint32_t oId; /* OEM ID */ + uint32_t classes; /* card class */ + uint32_t name1; /* product name part 1 */ + uint32_t name2; /* product name part 2 */ + uint32_t revision; /* revison */ + uint32_t sn; /* serial number */ + uint32_t numIoFuns; /* total I/O function number */ + uint32_t maxRdBlkLen; /* max read block length */ + uint32_t maxWtBlkLen; /* max write block length */ + uint32_t blkMode; /* sdio card block mode support */ + uint32_t f0Cis; /* sdio card block mode support */ + uint32_t f1Cis; /* sdio card block mode support */ + + uint8_t partRead; /* partial block read allowed */ + uint8_t partWrite; /* partial block write allowed */ + uint8_t dsr; /* card DSR */ + uint8_t rdCurMin; /* min current for read */ + uint8_t rdCurMax; /* max current for read */ + uint8_t wtCurMin; /* min current for write */ + uint8_t wtCurMax; /* max current for write */ + uint8_t erase; /* erase enable */ + uint8_t eraseSecSize; /* erase sector size */ + uint8_t proGrpSize; /* write protection group size */ + uint8_t protect; /* permanent write protection or not */ + uint8_t tmpProt; /* temp write protection or not */ + uint8_t wtSpeed; /* write speed relatively to read */ + uint8_t version; /* card version 0:1.0 - 1.01, 1:1.10, 2:2.0 */ + uint8_t eraseState; /* if the data will be 0 or 1 after erase */ + uint8_t bus; /* data with supported */ + uint8_t security; /* security support 0, 2:1.01 3:2.0 */ + uint8_t format; /* file format */ + uint8_t fileGrp; /* file group */ + char pwd[20]; /* password */ +}; + +struct sd_handle { + struct sd_dev *device; + struct sd_card_info *card; +}; + +int sd_cmd0(struct sd_handle *handle); +int sd_cmd1(struct sd_handle *handle, uint32_t initOcr, uint32_t *ocr); +int sd_cmd2(struct sd_handle *handle); +int sd_cmd3(struct sd_handle *handle); +int sd_cmd7(struct sd_handle *handle, uint32_t rca); +int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card); +int sd_cmd13(struct sd_handle *handle, uint32_t *status); +int sd_cmd16(struct sd_handle *handle, uint32_t blockLen); +int sd_cmd17(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer); +int sd_cmd18(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer); +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +int sd_cmd24(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer); +int sd_cmd25(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer); +#endif +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +int sd_cmd35(struct sd_handle *handle, uint32_t start); +int sd_cmd36(struct sd_handle *handle, uint32_t end); +int sd_cmd38(struct sd_handle *handle); +#endif +int mmc_cmd6(struct sd_handle *handle, uint32_t argument); +int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg); + +int send_cmd(struct sd_handle *handle, uint32_t cmdIndex, + uint32_t argument, uint32_t options, struct sd_resp *resp); +#endif /* CSL_SD_CMD_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h new file mode 100644 index 0000000..597e1e0 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSL_SD_PROT_H +#define CSL_SD_PROT_H + +#define SD_CARD_UNKNOWN 0 /* bad type or unrecognized */ +#define SD_CARD_SD 1 /* IO only card */ +#define SD_CARD_SDIO 2 /* memory only card */ +#define SD_CARD_COMBO 3 /* IO and memory combo card */ +#define SD_CARD_MMC 4 /* memory only card */ +#define SD_CARD_CEATA 5 /* IO and memory combo card */ + +#define SD_IO_FIXED_ADDRESS 0 /* fix Address */ +#define SD_IO_INCREMENT_ADDRESS 1 + +#define SD_HIGH_CAPACITY_CARD 0x40000000 + +#define MMC_CMD_IDLE_RESET_ARG 0xF0F0F0F0 + +/* Supported operating voltages are 3.2-3.3 and 3.3-3.4 */ +#define MMC_OCR_OP_VOLT 0x00300000 +/* Enable sector access mode */ +#define MMC_OCR_SECTOR_ACCESS_MODE 0x40000000 + +/* command index */ +#define SD_CMD_GO_IDLE_STATE 0 /* mandatory for SDIO */ +#define SD_CMD_SEND_OPCOND 1 +#define SD_CMD_ALL_SEND_CID 2 +#define SD_CMD_MMC_SET_RCA 3 +#define SD_CMD_MMC_SET_DSR 4 +#define SD_CMD_IO_SEND_OP_COND 5 /* mandatory for SDIO */ +#define SD_ACMD_SET_BUS_WIDTH 6 +#define SD_CMD_SWITCH_FUNC 6 +#define SD_CMD_SELECT_DESELECT_CARD 7 +#define SD_CMD_READ_EXT_CSD 8 +#define SD_CMD_SEND_CSD 9 +#define SD_CMD_SEND_CID 10 +#define SD_CMD_STOP_TRANSMISSION 12 +#define SD_CMD_SEND_STATUS 13 +#define SD_ACMD_SD_STATUS 13 +#define SD_CMD_GO_INACTIVE_STATE 15 +#define SD_CMD_SET_BLOCKLEN 16 +#define SD_CMD_READ_SINGLE_BLOCK 17 +#define SD_CMD_READ_MULTIPLE_BLOCK 18 +#define SD_CMD_WRITE_BLOCK 24 +#define SD_CMD_WRITE_MULTIPLE_BLOCK 25 +#define SD_CMD_PROGRAM_CSD 27 +#define SD_CMD_SET_WRITE_PROT 28 +#define SD_CMD_CLR_WRITE_PROT 29 +#define SD_CMD_SEND_WRITE_PROT 30 +#define SD_CMD_ERASE_WR_BLK_START 32 +#define SD_CMD_ERASE_WR_BLK_END 33 +#define SD_CMD_ERASE_GROUP_START 35 +#define SD_CMD_ERASE_GROUP_END 36 +#define SD_CMD_ERASE 38 +#define SD_CMD_LOCK_UNLOCK 42 +#define SD_CMD_IO_RW_DIRECT 52 /* mandatory for SDIO */ +#define SD_CMD_IO_RW_EXTENDED 53 /* mandatory for SDIO */ +#define SD_CMD_APP_CMD 55 +#define SD_CMD_GEN_CMD 56 +#define SD_CMD_READ_OCR 58 +#define SD_CMD_CRC_ON_OFF 59 /* mandatory for SDIO */ +#define SD_ACMD_SEND_NUM_WR_BLOCKS 22 +#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT 23 +#define SD_ACMD_SD_SEND_OP_COND 41 +#define SD_ACMD_SET_CLR_CARD_DETECT 42 +#define SD_ACMD_SEND_SCR 51 + +/* response parameters */ +#define SD_RSP_NO_NONE 0 +#define SD_RSP_NO_1 1 +#define SD_RSP_NO_2 2 +#define SD_RSP_NO_3 3 +#define SD_RSP_NO_4 4 +#define SD_RSP_NO_5 5 +#define SD_RSP_NO_6 6 + +/* Modified R6 response (to CMD3) */ +#define SD_RSP_MR6_COM_CRC_ERROR 0x8000 +#define SD_RSP_MR6_ILLEGAL_COMMAND 0x4000 +#define SD_RSP_MR6_ERROR 0x2000 + +/* Modified R1 in R4 Response (to CMD5) */ +#define SD_RSP_MR1_SBIT 0x80 +#define SD_RSP_MR1_PARAMETER_ERROR 0x40 +#define SD_RSP_MR1_RFU5 0x20 +#define SD_RSP_MR1_FUNC_NUM_ERROR 0x10 +#define SD_RSP_MR1_COM_CRC_ERROR 0x80 +#define SD_RSP_MR1_ILLEGAL_COMMAND 0x40 +#define SD_RSP_MR1_RFU1 0x20 +#define SD_RSP_MR1_IDLE_STATE 0x01 + +/* R5 response (to CMD52 and CMD53) */ +#define SD_RSP_R5_COM_CRC_ERROR 0x80 +#define SD_RSP_R5_ILLEGAL_COMMAND 0x40 +#define SD_RSP_R5_IO_CURRENTSTATE1 0x20 +#define SD_RSP_R5_IO_CURRENTSTATE0 0x10 +#define SD_RSP_R5_ERROR 0x80 +#define SD_RSP_R5_RFU 0x40 +#define SD_RSP_R5_FUNC_NUM_ERROR 0x20 +#define SD_RSP_R5_OUT_OF_RANGE 0x01 + +/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */ +#define SD_OP_READ 0 /* Read_Write */ +#define SD_OP_WRITE 1 /* Read_Write */ + +#define SD_RW_NORMAL 0 /* no RAW */ +#define SD_RW_RAW 1 /* RAW */ + +#define SD_BYTE_MODE 0 /* Byte Mode */ +#define SD_BLOCK_MODE 1 /* BlockMode */ + +#define SD_FIXED_ADDRESS 0 /* fix Address */ +#define SD_INCREMENT_ADDRESS 1 /* IncrementAddress */ + +#define SD_CMD5_ARG_IO_OCR_MASK 0x00FFFFFF +#define SD_CMD5_ARG_IO_OCR_SHIFT 0 +#define SD_CMD55_ARG_RCA_SHIFT 16 +#define SD_CMD59_ARG_CRC_OPTION_MASK 0x01 +#define SD_CMD59_ARG_CRC_OPTION_SHIFT 0 + +/* SD_CMD_IO_RW_DIRECT Argument */ +#define SdioIoRWDirectArg(rw, raw, func, addr, data) \ + (((rw & 1) << 31) | ((func & 0x7) << 28) | \ + ((raw & 1) << 27) | ((addr & 0x1FFFF) << 9) | \ + (data & 0xFF)) + +/* build SD_CMD_IO_RW_EXTENDED Argument */ +#define SdioIoRWExtArg(rw, blk, func, addr, inc_addr, count) \ + (((rw & 1) << 31) | ((func & 0x7) << 28) | \ + ((blk & 1) << 27) | ((inc_addr & 1) << 26) | \ + ((addr & 0x1FFFF) << 9) | (count & 0x1FF)) + +/* + * The Common I/O area shall be implemented on all SDIO cards and + * is accessed the the host via I/O reads and writes to function 0, + * the registers within the CIA are provided to enable/disable + * the operationo fthe i/o funciton. + */ + +/* cccr_sdio_rev */ +#define SDIO_REV_SDIOID_MASK 0xf0 /* SDIO spec revision number */ +#define SDIO_REV_CCCRID_MASK 0x0f /* CCCR format version number */ + +/* sd_rev */ +#define SDIO_REV_PHY_MASK 0x0f /* SD format version number */ +#define SDIO_FUNC_ENABLE_1 0x02 /* function 1 I/O enable */ +#define SDIO_FUNC_READY_1 0x02 /* function 1 I/O ready */ +#define SDIO_INTR_CTL_FUNC1_EN 0x2 /* interrupt enable for function 1 */ +#define SDIO_INTR_CTL_MASTER_EN 0x1 /* interrupt enable master */ +#define SDIO_INTR_STATUS_FUNC1 0x2 /* interrupt pending for function 1 */ +#define SDIO_IO_ABORT_RESET_ALL 0x08 /* I/O card reset */ +#define SDIO_IO_ABORT_FUNC_MASK 0x07 /* abort selection: function x */ +#define SDIO_BUS_CARD_DETECT_DIS 0x80 /* Card Detect disable */ +#define SDIO_BUS_SPI_CONT_INTR_CAP 0x40 /* support continuous SPI interrupt */ +#define SDIO_BUS_SPI_CONT_INTR_EN 0x20 /* continuous SPI interrupt enable */ +#define SDIO_BUS_DATA_WIDTH_MASK 0x03 /* bus width mask */ +#define SDIO_BUS_DATA_WIDTH_4BIT 0x02 /* bus width 4-bit mode */ +#define SDIO_BUS_DATA_WIDTH_1BIT 0x00 /* bus width 1-bit mode */ + +/* capability */ +#define SDIO_CAP_4BLS 0x80 /* 4-bit support for low speed card */ +#define SDIO_CAP_LSC 0x40 /* low speed card */ +#define SDIO_CAP_E4MI 0x20 /* enable int between block in 4-bit mode */ +#define SDIO_CAP_S4MI 0x10 /* support int between block in 4-bit mode */ +#define SDIO_CAP_SBS 0x08 /* support suspend/resume */ +#define SDIO_CAP_SRW 0x04 /* support read wait */ +#define SDIO_CAP_SMB 0x02 /* support multi-block transfer */ +#define SDIO_CAP_SDC 0x01 /* Support Direct cmd during multi-uint8 transfer */ + +/* CIA FBR1 registers */ +#define SDIO_FUNC1_INFO 0x100 /* basic info for function 1 */ +#define SDIO_FUNC1_EXT 0x101 /* extension of standard I/O device */ +#define SDIO_CIS_FUNC1_BASE_LOW 0x109 /* function 1 cis address bit 0-7 */ +#define SDIO_CIS_FUNC1_BASE_MID 0x10A /* function 1 cis address bit 8-15 */ +#define SDIO_CIS_FUNC1_BASE_HIGH 0x10B /* function 1 cis address bit 16 */ +#define SDIO_CSA_BASE_LOW 0x10C /* CSA base address uint8_t 0 */ +#define SDIO_CSA_BASE_MID 0x10D /* CSA base address uint8_t 1 */ +#define SDIO_CSA_BASE_HIGH 0x10E /* CSA base address uint8_t 2 */ +#define SDIO_CSA_DATA_OFFSET 0x10F /* CSA data register */ +#define SDIO_IO_BLK_SIZE_LOW 0x110 /* I/O block size uint8_t 0 */ +#define SDIO_IO_BLK_SIZE_HIGH 0x111 /* I/O block size uint8_t 1 */ + +/* SD_SDIO_FUNC1_INFO bits */ +#define SDIO_FUNC1_INFO_DIC 0x0f /* device interface code */ +#define SDIO_FUNC1_INFO_CSA 0x40 /* CSA support flag */ +#define SDIO_FUNC1_INFO_CSA_EN 0x80 /* CSA enabled */ + +/* SD_SDIO_FUNC1_EXT bits */ +#define SDIO_FUNC1_EXT_SHP 0x03 /* support high power */ +#define SDIO_FUNC1_EXT_EHP 0x04 /* enable high power */ + +/* devctr */ +/* I/O device interface code */ +#define SDIO_DEVCTR_DEVINTER 0x0f +/* support CSA */ +#define SDIO_DEVCTR_CSA_SUP 0x40 +/* enable CSA */ +#define SDIO_DEVCTR_CSA_EN 0x80 + +/* ext_dev */ +/* supports high-power mask */ +#define SDIO_HIGHPWR_SUPPORT_M 0x3 +/* enable high power */ +#define SDIO_HIGHPWR_EN 0x4 +/* standard power function(up to 200mA */ +#define SDIO_HP_STD 0 +/* need high power to operate */ +#define SDIO_HP_REQUIRED 0x2 +/* can work with standard power, but prefer high power */ +#define SDIO_HP_DESIRED 0x3 + +/* misc define */ +/* macro to calculate fbr register base */ +#define FBR_REG_BASE(n) (n*0x100) +#define SDIO_FUNC_0 0 +#define SDIO_FUNC_1 1 +#define SDIO_FUNC_2 2 +#define SDIO_FUNC_3 3 +#define SDIO_FUNC_4 4 +#define SDIO_FUNC_5 5 +#define SDIO_FUNC_6 6 +#define SDIO_FUNC_7 7 + +/* maximum block size for block mode operation */ +#define SDIO_MAX_BLOCK_SIZE 2048 +/* minimum block size for block mode operation */ +#define SDIO_MIN_BLOCK_SIZE 1 + +/* Card registers: status bit position */ +#define SDIO_STATUS_OUTOFRANGE 31 +#define SDIO_STATUS_COMCRCERROR 23 +#define SDIO_STATUS_ILLEGALCOMMAND 22 +#define SDIO_STATUS_ERROR 19 +#define SDIO_STATUS_IOCURRENTSTATE3 12 +#define SDIO_STATUS_IOCURRENTSTATE2 11 +#define SDIO_STATUS_IOCURRENTSTATE1 10 +#define SDIO_STATUS_IOCURRENTSTATE0 9 +#define SDIO_STATUS_FUN_NUM_ERROR 4 + +#define GET_SDIOCARD_STATUS(x) ((x >> 9) & 0x0f) +#define SDIO_STATUS_STATE_IDLE 0 +#define SDIO_STATUS_STATE_READY 1 +#define SDIO_STATUS_STATE_IDENT 2 +#define SDIO_STATUS_STATE_STBY 3 +#define SDIO_STATUS_STATE_TRAN 4 +#define SDIO_STATUS_STATE_DATA 5 +#define SDIO_STATUS_STATE_RCV 6 +#define SDIO_STATUS_STATE_PRG 7 +#define SDIO_STATUS_STATE_DIS 8 + +/* sprom */ +#define SBSDIO_SPROM_CS 0x10000 /* command and status */ +#define SBSDIO_SPROM_INFO 0x10001 /* info register */ +#define SBSDIO_SPROM_DATA_LOW 0x10002 /* indirect access data uint8_t 0 */ +#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* indirect access data uint8_t 1 */ +#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* indirect access addr uint8_t 0 */ +#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* indirect access addr uint8_t 0 */ +#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu data output */ +#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu enable */ +#define SBSDIO_WATERMARK 0x10008 /* retired in rev 7 */ +#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */ + +#define SBSDIO_SPROM_IDLE 0 +#define SBSDIO_SPROM_WRITE 1 +#define SBSDIO_SPROM_READ 2 +#define SBSDIO_SPROM_WEN 4 +#define SBSDIO_SPROM_WDS 7 +#define SBSDIO_SPROM_DONE 8 + +/* SBSDIO_SPROM_INFO */ +#define SBSDIO_SROM_SZ_MASK 0x03 /* SROM size, 1: 4k, 2: 16k */ +#define SBSDIO_SROM_BLANK 0x04 /* depreciated in corerev 6 */ +#define SBSDIO_SROM_OTP 0x80 /* OTP present */ + +/* SBSDIO_CHIP_CTRL */ +/* or'd with onchip xtal_pu, 1: power on oscillator */ +#define SBSDIO_CHIP_CTRL_XTAL 0x01 + +/* SBSDIO_WATERMARK */ +/* number of bytes minus 1 for sd device to wait before sending data to host */ +#define SBSDIO_WATERMARK_MASK 0x3f + +/* SBSDIO_DEVICE_CTL */ +/* 1: device will assert busy signal when receiving CMD53 */ +#define SBSDIO_DEVCTL_SETBUSY 0x01 +/* 1: assertion of sdio interrupt is synchronous to the sdio clock */ +#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 + +/* function 1 OCP space */ +/* sb offset addr is <= 15 bits, 32k */ +#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF +#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 +/* sdsdio function 1 OCP space has 16/32 bit section */ +#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 + +/* direct(mapped) cis space */ +/* MAPPED common CIS address */ +#define SBSDIO_CIS_BASE_COMMON 0x1000 +/* function 0(common) cis size in bytes */ +#define SBSDIO_CIS_FUNC0_LIMIT 0x020 +/* funciton 1 cis size in bytes */ +#define SBSDIO_CIS_SIZE_LIMIT 0x200 +/* cis offset addr is < 17 bits */ +#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF +/* manfid tuple length, include tuple, link bytes */ +#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 + +/* indirect cis access (in sprom) */ +/* 8 control bytes first, CIS starts from 8th uint8_t */ +#define SBSDIO_SPROM_CIS_OFFSET 0x8 +/* sdio uint8_t mode: maximum length of one data comamnd */ +#define SBSDIO_BYTEMODE_DATALEN_MAX 64 +/* 4317 supports less */ +#define SBSDIO_BYTEMODE_DATALEN_MAX_4317 52 +/* sdio core function one address mask */ +#define SBSDIO_CORE_ADDR_MASK 0x1FFFF + +/* CEATA defines */ +#define CEATA_EXT_CSDBLOCK_SIZE 512 +#define CEATA_FAST_IO 39 +#define CEATA_MULTIPLE_REGISTER_RW 60 +#define CEATA_MULTIPLE_BLOCK_RW 61 + +/* defines CE ATA task file registers */ +#define CEATA_SCT_CNT_EXP_REG 0x02 +#define CEATA_LBA_LOW_EXP_REG 0x03 +#define CEATA_LBA_MID_EXP_REG 0x04 +#define CEATA_LBA_HIGH_EXP_REG 0x05 +#define CEATA_CNTRL_REG 0x06 +#define CEATA_FEATURE_REG 0x09 /* write */ +#define CEATA_ERROR_REG 0x09 /* read */ +#define CEATA_SCT_CNT_REG 0x0A +#define CEATA_LBA_LOW_REG 0x0B +#define CEATA_LBA_MID_REG 0x0C +#define CEATA_LBA_HIGH_REG 0x0D +#define CEATA_DEV_HEAD_REG 0x0E +#define CEATA_STA_REG 0x0F /* read */ +#define CEATA_CMD_REG 0x0F /* write */ + +/* defines CEATA control and status registers for ce ata client driver */ +#define CEATA_SCR_TEMPC_REG 0x80 +#define CEATA_SCR_TEMPMAXP_REG 0x84 +#define CEATA_TEMPMINP_REG 0x88 +#define CEATA_SCR_STATUS_REG 0x8C +#define CEATA_SCR_REALLOCSA_REG 0x90 +#define CEATA_SCR_ERETRACTSA_REG 0x94 +#define CEATA_SCR_CAPABILITIES_REG 0x98 +#define CEATA_SCR_CONTROL_REG 0xC0 + +/* defines for SCR capabilities register bits for ce ata client driver */ +#define CEATA_SCR_CAP_512 0x00000001 +#define CEATA_SCR_CAP_1K 0x00000002 +#define CEATA_SCR_CAP_4K 0x00000004 + +/* defines CE ATA Control reg bits for ce ata client driver */ +#define CEATA_CNTRL_ENABLE_INTR 0x00 +#define CEATA_CNTRL_DISABLE_INTR 0x02 +#define CEATA_CNTRL_SRST 0x04 +#define CEATA_CNTRL_RSRST 0x00 + +/* define CE ATA Status reg bits for ce ata client driver */ +#define CEATA_STA_ERROR_BIT 0x01 +#define CEATA_STA_OVR_BIT 0x02 +#define CEATA_STA_SPT_BIT 0x04 +#define CEATA_STA_DRQ_BIT 0x08 +#define CEATA_STA_DRDY_BIT 0x40 +#define CEATA_STA_BSY_BIT 0x80 + +/* define CE ATA Error reg bits for ce ata client driver */ +#define CEATA_ERROR_ABORTED_BIT 0x04 +#define CEATA_ERROR_IDNF_BIT 0x10 +#define CEATA_ERROR_UNCORRECTABLE_BIT 0x40 +#define CEATA_ERROR_ICRC_BIT 0x80 + +/* define CE ATA Commands for ce ata client driver */ +#define CEATA_CMD_IDENTIFY_DEVICE 0xEC +#define CEATA_CMD_READ_DMA_EXT 0x25 +#define CEATA_CMD_WRITE_DMA_EXT 0x35 +#define CEATA_CMD_STANDBY_IMMEDIATE 0xE0 +#define CEATA_CMD_FLUSH_CACHE_EXT 0xEA + +struct csd_mmc { + uint32_t padding:8; + uint32_t structure:2; + uint32_t csdSpecVer:4; + uint32_t reserved1:2; + uint32_t taac:8; + uint32_t nsac:8; + uint32_t speed:8; + uint32_t classes:12; + uint32_t rdBlkLen:4; + uint32_t rdBlkPartial:1; + uint32_t wrBlkMisalign:1; + uint32_t rdBlkMisalign:1; + uint32_t dsr:1; + uint32_t reserved2:2; + uint32_t size:12; + uint32_t vddRdCurrMin:3; + uint32_t vddRdCurrMax:3; + uint32_t vddWrCurrMin:3; + uint32_t vddWrCurrMax:3; + uint32_t devSizeMulti:3; + uint32_t eraseGrpSize:5; + uint32_t eraseGrpSizeMulti:5; + uint32_t wrProtGroupSize:5; + uint32_t wrProtGroupEnable:1; + uint32_t manuDefEcc:2; + uint32_t wrSpeedFactor:3; + uint32_t wrBlkLen:4; + uint32_t wrBlkPartial:1; + uint32_t reserved5:4; + uint32_t protAppl:1; + uint32_t fileFormatGrp:1; + uint32_t copyFlag:1; + uint32_t permWrProt:1; + uint32_t tmpWrProt:1; + uint32_t fileFormat:2; + uint32_t eccCode:2; +}; + +/* CSD register*/ +union sd_csd { + uint32_t csd[4]; + struct csd_mmc mmc; +}; + +struct sd_card_data { + union sd_csd csd; +}; +#endif /* CSL_SD_PROT_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h new file mode 100644 index 0000000..8e61b51 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PBOOT_HAL_MEMORY_EMMC_DRV_H +#define PBOOT_HAL_MEMORY_EMMC_DRV_H + +#include + +#include "emmc_chal_types.h" +#include "emmc_chal_sd.h" +#include "emmc_csl_sdprot.h" +#include "emmc_csl_sdcmd.h" +#include "emmc_csl_sd.h" +#include "emmc_brcm_rdb_sd4_top.h" + +#define CLK_SDIO_DIV_52MHZ 0x0 +#define SYSCFG_IOCR4_PAD_10MA 0x38000000 + +#define SDCLK_CNT_PER_MS 52000 +#define BOOT_ACK_TIMEOUT (50 * SDCLK_CNT_PER_MS) +#define BOOT_DATA_TIMEOUT (1000 * SDCLK_CNT_PER_MS) + +#define EMMC_BOOT_OK 0 +#define EMMC_BOOT_ERROR 1 +#define EMMC_BOOT_TIMEOUT 2 +#define EMMC_BOOT_INVALIDIMAGE 3 +#define EMMC_BOOT_NO_CARD 4 + +#define EMMC_USER_AREA 0 +#define EMMC_BOOT_PARTITION1 1 +#define EMMC_BOOT_PARTITION2 2 +#define EMMC_USE_CURRENT_PARTITION 3 + +#define EMMC_BOOT_PARTITION_SIZE (128*1024) +#define EMMC_BLOCK_SIZE 512 +#define EMMC_DMA_SIZE (4*1024) + +/* + * EMMC4.3 definitions + * Table 6 EXT_CSD access mode + * Access + * Bits Access Name Operation + * 00 Command Set The command set is changed according to the Cmd Set field of + * the argument + * 01 Set Bits The bits in the pointed uint8_t are set, + * according to the 1 bits in the Value field. + * 10 Clear Bits The bits in the pointed uint8_t are cleared, + * according to the 1 bits in the Value field. + * 11 Write Byte The Value field is written into the pointed uint8_t. + */ + +#define SDIO_HW_EMMC_EXT_CSD_WRITE_BYTE 0X03000000 + +/* Boot bus width1 BOOT_BUS_WIDTH 1 R/W [177] */ +#define SDIO_HW_EMMC_EXT_CSD_BOOT_BUS_WIDTH_OFFSET 0X00B10000 + +/* Boot configuration BOOT_CONFIG 1 R/W [179] */ +#define SDIO_HW_EMMC_EXT_CSD_BOOT_CONFIG_OFFSET 0X00B30000 + +/* Bus width mode BUS_WIDTH 1 WO [183] */ +#define SDIO_HW_EMMC_EXT_CSD_BUS_WIDTH_OFFSET 0X00B70000 + +/* + * Bit 6: BOOT_ACK (non-volatile) + * 0x0 : No boot acknowledge sent (default) + * 0x1 : Boot acknowledge sent during boot operation + * Bit[5:3] : BOOT_PARTITION_ENABLE (non-volatile) + * User selects boot data that will be sent to master + * 0x0 : Device not boot enabled (default) + * 0x1 : Boot partition 1 enabled for boot + * 0x2 : Boot partition 2 enabled for boot + * 0x3-0x6 : Reserved + * 0x7 : User area enabled for boot + * Bit[2:0] : BOOT_PARTITION_ACCESS + * User selects boot partition for read and write operation + * 0x0 : No access to boot partition (default) + * 0x1 : R/W boot partition 1 + * 0x2 : R/W boot partition 2 + * 0x3-0x7 : Reserved + */ + +#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1 0X00000100 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2 0X00000200 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER 0X00000000 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_BOOT1 0X00004800 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_BOOT2 0X00005000 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_USER 0X00007800 + +#define SD_US_DELAY(x) udelay(x) + +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/fru.h b/arm-trusted-firmware/include/drivers/brcm/fru.h new file mode 100644 index 0000000..ee863b4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/fru.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FRU_H +#define FRU_H + +#include +#include + +/* max string length */ +#define FRU_MAX_STR_LEN 32 + +/* max number of DDR channels */ +#define BCM_MAX_NR_DDR 3 + +/* max supported FRU table size */ +#define BCM_MAX_FRU_LEN 512 + +/* FRU table starting offset */ +#define BCM_FRU_TBL_OFFSET 0x300000 + +/* FRU time constants */ +#define MINS_PER_DAY 1440 +#define MINS_PER_HOUR 60 +#define FRU_YEAR_START 1996 +#define FRU_MONTH_START 1 +#define FRU_DAY_START 1 +#define MONTHS_PER_YEAR 12 + +/* + * FRU areas based on the spec + */ +enum fru_area_name { + FRU_AREA_INTERNAL = 0, + FRU_AREA_CHASSIS_INFO, + FRU_AREA_BOARD_INFO, + FRU_AREA_PRODUCT_INFO, + FRU_AREA_MRECORD_INFO, + FRU_MAX_NR_AREAS +}; + +/* + * FRU area information + * + * @use: indicate this area is being used + * @version: format version + * @offset: offset of this area from the beginning of the FRU table + * @len: total length of the area + */ +struct fru_area_info { + bool use; + uint8_t version; + unsigned int offset; + unsigned int len; +}; + +/* + * DDR MCB information + * + * @idx: DDR channel index + * @size_mb: DDR size of this channel in MB + * @ref_id: DDR MCB reference ID + */ +struct ddr_mcb { + unsigned int idx; + unsigned int size_mb; + uint32_t ref_id; +}; + +/* + * DDR information + * + * @ddr_info: array that contains MCB related info for each channel + */ +struct ddr_info { + struct ddr_mcb mcb[BCM_MAX_NR_DDR]; +}; + +/* + * FRU board area information + * + * @lang: Language code + * @mfg_date: Manufacturing date + * @manufacturer: Manufacturer + * @product_name: Product name + * @serial_number: Serial number + * @part_number: Part number + * @file_id: FRU file ID + */ +struct fru_board_info { + unsigned char lang; + unsigned int mfg_date; + unsigned char manufacturer[FRU_MAX_STR_LEN]; + unsigned char product_name[FRU_MAX_STR_LEN]; + unsigned char serial_number[FRU_MAX_STR_LEN]; + unsigned char part_number[FRU_MAX_STR_LEN]; + unsigned char file_id[FRU_MAX_STR_LEN]; +}; + +/* + * FRU manufacture date in human readable format + */ +struct fru_time { + unsigned int min; + unsigned int hour; + unsigned int day; + unsigned int month; + unsigned int year; +}; + +#ifdef USE_FRU +int fru_validate(uint8_t *data, struct fru_area_info *fru_area); +int fru_parse_ddr(uint8_t *data, struct fru_area_info *area, + struct ddr_info *ddr); +int fru_parse_board(uint8_t *data, struct fru_area_info *area, + struct fru_board_info *board); +void fru_format_time(unsigned int min, struct fru_time *tm); +#else +static inline int fru_validate(uint8_t *data, struct fru_area_info *fru_area) +{ + return -1; +} + +static inline int fru_parse_ddr(uint8_t *data, struct fru_area_info *area, + struct ddr_info *ddr) +{ + return -1; +} + +static inline int fru_parse_board(uint8_t *data, struct fru_area_info *area, + struct fru_board_info *board) +{ + return -1; +} + +static inline void fru_format_time(unsigned int min, struct fru_time *tm) +{ +} +#endif /* USE_FRU */ + +#endif /* FRU_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h b/arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h new file mode 100644 index 0000000..24d42e2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_H +#define I2C_H + +#include + +#define I2C_SPEED_100KHz 100000 +#define I2C_SPEED_400KHz 400000 +#define I2C_SPEED_DEFAULT I2C_SPEED_100KHz + +/* + * Function Name: i2c_probe + * + * Description: + * This function probes the I2C bus for the existence of the specified + * device. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_probe(uint32_t bus_id, uint8_t devaddr); + +/* + * Function Name: i2c_init + * + * Description: + * This function initializes the SMBUS. + * + * Parameters: + * bus_id - I2C bus ID + * speed - I2C bus speed in Hz + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_init(uint32_t bus_id, int speed); + +/* + * Function Name: i2c_set_bus_speed + * + * Description: + * This function configures the SMBUS speed + * + * Parameters: + * bus_id - I2C bus ID + * speed - I2C bus speed in Hz + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_set_bus_speed(uint32_t bus_id, uint32_t speed); + +/* + * Function Name: i2c_get_bus_speed + * + * Description: + * This function returns the SMBUS speed. + * + * Parameters: + * bus_id - I2C bus ID + * + * Return: + * Bus speed in Hz, 0 on failure + */ +uint32_t i2c_get_bus_speed(uint32_t bus_id); + +/* + * Function Name: i2c_recv_byte + * + * Description: + * This function reads I2C data from a device without specifying + * a command regsiter. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * value - Data Read + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_recv_byte(uint32_t bus_id, uint8_t devaddr, uint8_t *value); + +/* + * Function Name: i2c_send_byte + * + * Description: + * This function send I2C data to a device without specifying + * a command regsiter. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * value - Data Send + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_send_byte(uint32_t bus_id, uint8_t devaddr, uint8_t value); + +/* + * Function Name: i2c_read + * + * Description: + * This function reads I2C data from a device with a designated + * command register + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * addr - Register Offset + * alen - Address Length, 1 for byte, 2 for word (not supported) + * buffer - Data Buffer + * len - Data Length in bytes + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_read(uint32_t bus_id, + uint8_t devaddr, + uint32_t addr, + int alen, + uint8_t *buffer, + int len); + +/* + * Function Name: i2c_write + * + * Description: + * This function write I2C data to a device with a designated + * command register + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * addr - Register Offset + * alen - Address Length, 1 for byte, 2 for word (not supported) + * buffer - Data Buffer + * len - Data Length in bytes + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_write(uint32_t bus_id, + uint8_t devaddr, + uint32_t addr, + int alen, + uint8_t *buffer, + int len); + + +#endif /* I2C_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h b/arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h new file mode 100644 index 0000000..74ea824 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_REGS +#define I2C_REGS + +/* SMBUS Config register */ +#define SMB_CFG_REG 0x0U + +#define SMB_CFG_RST_MASK 0x80000000U +#define SMB_CFG_RST_SHIFT 31U + +#define SMB_CFG_SMBEN_MASK 0x40000000U +#define SMB_CFG_SMBEN_SHIFT 30U + +#define SMB_CFG_BITBANGEN_MASK 0x20000000U +#define SMB_CFG_BITBANGEN_SHIFT 29U + +#define SMB_CFG_EN_NIC_SMBADDR0_MASK 0x10000000U +#define SMB_CFG_EN_NIC_SMBADDR0_SHIFT 28U + +#define SMB_CFG_PROMISCMODE_MASK 0x08000000U +#define SMB_CFG_PROMISCMODE_SHIFT 27U + +#define SMB_CFG_TSTMPCNTEN_MASK 0x04000000U +#define SMB_CFG_TSTMPCNTEN_SHIFT 26U + +#define SMB_CFG_MSTRRTRYCNT_MASK 0x000F0000U +#define SMB_CFG_MSTRRTRYCNT_SHIFT 16U + +/* SMBUS Timing config register */ +#define SMB_TIMGCFG_REG 0x4U + +#define SMB_TIMGCFG_MODE400_MASK 0x80000000U +#define SMB_TIMGCFG_MODE400_SHIFT 31U + +#define SMB_TIMGCFG_RNDSLVSTR_MASK 0x7F000000U +#define SMB_TIMGCFG_RNDSLVSTR_SHIFT 24U + +#define SMB_TIMGCFG_PERSLVSTR_MASK 0x00FF0000U +#define SMB_TIMGCFG_PERSLVSTR_SHIFT 16U + +#define SMB_TIMGCFG_IDLTIME_MASK 0x0000FF00U +#define SMB_TIMGCFG_IDLTIME_SHIFT 8U + +/* SMBUS Slave address register */ +#define SMB_ADDR_REG 0x8U + +#define SMB_EN_NIC_SMBADDR3_MASK 0x80000000U +#define SMB_EN_NIC_SMBADDR3_SHIFT 31U + +#define SMB_NIC_SMBADDR3_MASK 0x7F000000U +#define SMB_NIC_SMBADDR3_SHIFT 24U + +#define SMB_EN_NIC_SMBADDR2_MASK 0x00800000U +#define SMB_EN_NIC_SMBADDR2_SHIFT 23U + +#define SMB_NIC_SMBADDR2_MASK 0x007F0000U +#define SMB_NIC_SMBADDR2_SHIFT 16U + +#define SMB_EN_NIC_SMBADDR1_MASK 0x00008000U +#define SMB_EN_NIC_SMBADDR1_SHIFT 15U + +#define SMB_NIC_SMBADDR1_MASK 0x00007F00U +#define SMB_NIC_SMBADDR1_SHIFT 8U + +#define SMB_EN_NIC_SMBADDR0_MASK 0x00000080U +#define SMB_EN_NIC_SMBADDR0_SHIFT 7U + +#define SMB_NIC_SMBADDR0_MASK 0x0000007FU +#define SMB_NIC_SMBADDR0_SHIFT 0U + +/* SMBUS Master FIFO control register */ +#define SMB_MSTRFIFOCTL_REG 0xCU + +#define SMB_MSTRRXFIFOFLSH_MASK 0x80000000U +#define SMB_MSTRRXFIFOFLSH_SHIFT 31U + +#define SMB_MSTRTXFIFOFLSH_MASK 0x40000000U +#define SMB_MSTRTXFIFOFLSH_SHIFT 30U + +#define SMB_MSTRRXPKTCNT_MASK 0x007F0000U +#define SMB_MSTRRXPKTCNT_SHIFT 16U + +#define SMB_MSTRRXFIFOTHR_MASK 0x00003F00U +#define SMB_MSTRRXFIFOTHR_SHIFT 8U + +/* SMBUS Slave FIFO control register */ +#define SMB_SLVFIFOCTL_REG 0x10U + +#define SMB_SLVRXFIFOFLSH_MASK 0x80000000U +#define SMB_SLVRXFIFOFLSH_SHIFT 31U + +#define SMB_SLVTXFIFOFLSH_MASK 0x40000000U +#define SMB_SLVTXFIFOFLSH_SHIFT 30U + +#define SMB_SLVRXPKTCNT_MASK 0x007F0000U +#define SMB_SLVRXPKTCNT_SHIFT 16U + +#define SMB_SLVRXFIFOTHR_MASK 0x00003F00U +#define SMB_SLVRXFIFOTHR_SHIFT 8U + +/* SMBUS Bit-bang mode control register */ +#define SMB_BITBANGCTL_REG 0x14U + +#define SMB_SMBCLKIN_MASK 0x80000000U +#define SMB_SMBCLKIN_SHIFT 31U + +#define SMB_SMBCLKOUTEN_MASK 0x40000000U +#define SMB_SMBCLKOUTEN_SHIFT 30U + +#define SMB_SMBDATAIN_MASK 0x20000000U +#define SMB_SMBDATAIN_SHIFT 29U + +#define SMB_SMBDATAOUTEN_MASK 0x10000000U +#define SMB_SMBDATAOUTEN_SHIFT 28U + +/* SMBUS Master command register */ +#define SMB_MSTRCMD_REG 0x30U + +#define SMB_MSTRSTARTBUSYCMD_MASK 0x80000000U +#define SMB_MSTRSTARTBUSYCMD_SHIFT 31U + +#define SMB_MSTRABORT_MASK 0x40000000U +#define SMB_MSTRABORT_SHIFT 30U + +#define SMB_MSTRSTS_MASK 0x0E000000U +#define SMB_MSTRSTS_SHIFT 25U + +#define SMB_MSTRSMBUSPROTO_MASK 0x00001E00U +#define SMB_MSTRSMBUSPROTO_SHIFT 9U + +#define SMB_MSTRPEC_MASK 0x00000100U +#define SMB_MSTRPEC_SHIFT 8U + +#define SMB_MSTRRDBYTECNT_MASK 0x000000FFU +#define SMB_MSTRRDBYTECNT_SHIFT 0U + +/* SMBUS Slave command register */ +#define SMB_SLVCMD_REG 0x34U + +#define SMB_SLVSTARTBUSYCMD_MASK 0x80000000U +#define SMB_SLVSTARTBUSYCMD_SHIFT 31U + +#define SMB_SLVABORT_MASK 0x40000000U +#define SMB_SLVABORT_SHIFT 30U + +#define SMB_SLVSTS_MASK 0x03800000U +#define SMB_SLVSTS_SHIFT 23U + +#define SMB_SLVPEC_MASK 0x00000100U +#define SMB_SLVPEC_SHIFT 8U + +/* SMBUS Event enable register */ +#define SMB_EVTEN_REG 0x38U + +#define SMB_MSTRRXFIFOFULLEN_MASK 0x80000000U +#define SMB_MSTRRXFIFOFULLEN_SHIFT 31U + +#define SMB_MSTRRXFIFOTHRHITEN_MASK 0x40000000U +#define SMB_MSTRRXFIFOTHRHITEN_SHIFT 30U + +#define SMB_MSTRRXEVTEN_MASK 0x20000000U +#define SMB_MSTRRXEVTEN_SHIFT 29U + +#define SMB_MSTRSTARTBUSYEN_MASK 0x10000000U +#define SMB_MSTRSTARTBUSYEN_SHIFT 28U + +#define SMB_MSTRTXUNDEN_MASK 0x08000000U +#define SMB_MSTRTXUNDEN_SHIFT 27U + +#define SMB_SLVRXFIFOFULLEN_MASK 0x04000000U +#define SMB_SLVRXFIFOFULLEN_SHIFT 26U + +#define SMB_SLVRXFIFOTHRHITEN_MASK 0x02000000U +#define SMB_SLVRXFIFOTHRHITEN_SHIFT 25U + +#define SMB_SLVRXEVTEN_MASK 0x01000000U +#define SMB_SLVRXEVTEN_SHIFT 24U + +#define SMB_SLVSTARTBUSYEN_MASK 0x00800000U +#define SMB_SLVSTARTBUSYEN_SHIFT 23U + +#define SMB_SLVTXUNDEN_MASK 0x00400000U +#define SMB_SLVTXUNDEN_SHIFT 22U + +#define SMB_SLVRDEVTEN_MASK 0x00200000U +#define SMB_SLVRDEVTEN_SHIFT 21U + +/* SMBUS Event status register */ +#define SMB_EVTSTS_REG 0x3CU + +#define SMB_MSTRRXFIFOFULLSTS_MASK 0x80000000U +#define SMB_MSTRRXFIFOFULLSTS_SHIFT 31U + +#define SMB_MSTRRXFIFOTHRHITSTS_MASK 0x40000000U +#define SMB_MSTRRXFIFOTHRHITSTS_SHIFT 30U + +#define SMB_MSTRRXEVTSTS_MASK 0x20000000U +#define SMB_MSTRRXEVTSTS_SHIFT 29U + +#define SMB_MSTRSTARTBUSYSTS_MASK 0x10000000U +#define SMB_MSTRSTARTBUSYSTS_SHIFT 28U + +#define SMB_MSTRTXUNDSTS_MASK 0x08000000U +#define SMB_MSTRTXUNDSTS_SHIFT 27U + +#define SMB_SLVRXFIFOFULLSTS_MASK 0x04000000U +#define SMB_SLVRXFIFOFULLSTS_SHIFT 26U + +#define SMB_SLVRXFIFOTHRHITSTS_MASK 0x02000000U +#define SMB_SLVRXFIFOTHRHITSTS_SHIFT 25U + +#define SMB_SLVRXEVTSTS_MASK 0x01000000U +#define SMB_SLVRXEVTSTS_SHIFT 24U + +#define SMB_SLVSTARTBUSYSTS_MASK 0x00800000U +#define SMB_SLVSTARTBUSYSTS_SHIFT 23U + +#define SMB_SLVTXUNDSTS_MASK 0x00400000U +#define SMB_SLVTXUNDSTS_SHIFT 22U + +#define SMB_SLVRDEVTSTS_MASK 0x00200000U +#define SMB_SLVRDEVTSTS_SHIFT 21U + +/* SMBUS Master data write register */ +#define SMB_MSTRDATAWR_REG 0x40U + +#define SMB_MSTRWRSTS_MASK 0x80000000U +#define SMB_MSTRWRSTS_SHIFT 31U + +#define SMB_MSTRWRDATA_MASK 0x000000FFU +#define SMB_MSTRWRDATA_SHIFT 0U + +/* SMBUS Master data read register */ +#define SMB_MSTRDATARD_REG 0x44U + +#define SMB_MSTRRDSTS_MASK 0xC0000000U +#define SMB_MSTRRDSTS_SHIFT 30U + +#define SMB_MSTRRDPECERR_MASK 0x20000000U +#define SMB_MSTRRDPECERR_SHIFT 29U + +#define SMB_MSTRRDDATA_MASK 0x000000FFU +#define SMB_MSTRRDDATA_SHIFT 0U + +/* SMBUS Slave data write register */ +#define SMB_SLVDATAWR_REG 0x48U + +#define SMB_SLVWRSTS_MASK 0x80000000U +#define SMB_SLVWRSTS_SHIFT 31U + +#define SMB_SLVWRDATA_MASK 0x000000FFU +#define SMB_SLVWRDATA_SHIFT 0U + +/* SMBUS Slave data read register */ +#define SMB_SLVDATARD_REG 0x4CU + +#define SMB_SLVRDSTS_MASK 0xC0000000U +#define SMB_SLVRDSTS_SHIFT 30U + +#define SMB_SLVRDERRSTS_MASK 0x30000000U +#define SMB_SLVRDERRSTS_SHIFT 28U + +#define SMB_SLVRDDATA_MASK 0x000000FFU +#define SMB_SLVRDDATA_SHIFT 0U + +#endif /* I2C_REGS */ diff --git a/arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h b/arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h new file mode 100644 index 0000000..be971f6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IPROC_GPIO_H +#define IPROC_GPIO_H + +#ifdef USE_GPIO +void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base, + uintptr_t pinconf_base); +#else +static void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base, + uintptr_t pinconf_base) +{ +} +#endif /* IPROC_GPIO */ + +#endif /* IPROC_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h b/arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h new file mode 100644 index 0000000..b27c7b3 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MDIO_H +#define MDIO_H + +#define CMIC_MIIM_PARAM (PLAT_CMIC_MIIM_BASE + 0x23cU) +#define MDIO_PARAM_MIIM_CYCLE 29U +#define MDIO_PARAM_INTERNAL_SEL 25U +#define MDIO_PARAM_BUSID 22U +#define MDIO_PARAM_BUSID_MASK 0x7U +#define MDIO_PARAM_C45_SEL 21U +#define MDIO_PARAM_PHYID 16U +#define MDIO_PARAM_PHYID_MASK 0x1FU +#define MDIO_PARAM_DATA 0U +#define MDIO_PARAM_DATA_MASK 0xFFFFU +#define CMIC_MIIM_READ_DATA (PLAT_CMIC_MIIM_BASE + 0x240U) +#define MDIO_READ_DATA_MASK 0xffffU +#define CMIC_MIIM_ADDRESS (PLAT_CMIC_MIIM_BASE + 0x244U) +#define CMIC_MIIM_CTRL (PLAT_CMIC_MIIM_BASE + 0x248U) +#define MDIO_CTRL_WRITE_OP 0x1U +#define MDIO_CTRL_READ_OP 0x2U +#define CMIC_MIIM_STAT (PLAT_CMIC_MIIM_BASE + 0x24cU) +#define MDIO_STAT_DONE 1U + +int mdio_write(uint16_t busid, uint16_t phyid, uint32_t reg, uint16_t val); +int mdio_read(uint16_t busid, uint16_t phyid, uint32_t reg); +#endif /* MDIO_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/ocotp.h b/arm-trusted-firmware/include/drivers/brcm/ocotp.h new file mode 100644 index 0000000..830b3e4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/ocotp.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OCOTP_H +#define OCOTP_H + +#include + +struct otpc_map { + /* in words. */ + uint32_t otpc_row_size; + /* 128 bit row / 4 words support. */ + uint16_t data_r_offset[4]; + /* 128 bit row / 4 words support. */ + uint16_t data_w_offset[4]; + int word_size; + int stride; +}; + +int bcm_otpc_init(struct otpc_map *map); +int bcm_otpc_read(unsigned int offset, void *val, uint32_t bytes, + uint32_t ecc_flag); + +#endif /* OCOTP_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/scp.h b/arm-trusted-firmware/include/drivers/brcm/scp.h new file mode 100644 index 0000000..7806314 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/scp.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCP_H +#define SCP_H + +#include + +int download_scp_patch(void *image, unsigned int image_size); + +#endif /* SCP_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/sf.h b/arm-trusted-firmware/include/drivers/brcm/sf.h new file mode 100644 index 0000000..c32cbeb --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/sf.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SF_H +#define SF_H + +#include +#include + +#ifdef SPI_DEBUG +#define SPI_DEBUG(fmt, ...) INFO(fmt, ##__VA_ARGS__) +#else +#define SPI_DEBUG(fmt, ...) +#endif + +#define SPI_FLASH_MAX_ID_LEN 6 + +#define CMD_WRSR 0x01 /* Write status register */ +#define CMD_PAGE_PROGRAM 0x02 +#define CMD_READ_NORMAL 0x03 +#define CMD_RDSR 0x05 +#define CMD_WRITE_ENABLE 0x06 +#define CMD_RDFSR 0x70 +#define CMD_READ_ID 0x9f +#define CMD_ERASE_4K 0x20 +#define CMD_ERASE_64K 0xd8 +#define ERASE_SIZE_64K (64 * 1024) + +/* Common status */ +#define STATUS_WIP BIT(0) + +struct spi_flash { + struct spi_slave *spi; + uint32_t size; + uint32_t page_size; + uint32_t sector_size; + uint32_t erase_size; + uint8_t erase_cmd; + uint8_t read_cmd; + uint8_t write_cmd; + uint8_t flags; +}; + +struct spi_flash_info { + const char *name; + + /* + * This array stores the ID bytes. + * The first three bytes are the JEDIC ID. + * JEDEC ID zero means "no ID" (mostly older chips). + */ + uint8_t id[SPI_FLASH_MAX_ID_LEN]; + uint8_t id_len; + + uint32_t sector_size; + uint32_t n_sectors; + uint16_t page_size; + + uint8_t flags; +}; + +/* Enum list - Full read commands */ +enum spi_read_cmds { + ARRAY_SLOW = BIT(0), + ARRAY_FAST = BIT(1), + DUAL_OUTPUT_FAST = BIT(2), + DUAL_IO_FAST = BIT(3), + QUAD_OUTPUT_FAST = BIT(4), + QUAD_IO_FAST = BIT(5), +}; + +/* sf param flags */ +enum spi_param_flag { + SECT_4K = BIT(0), + SECT_32K = BIT(1), + E_FSR = BIT(2), + SST_BP = BIT(3), + SST_WP = BIT(4), + WR_QPP = BIT(5), +}; + +int spi_flash_cmd_read(const uint8_t *cmd, size_t cmd_len, + void *data, size_t data_len); +int spi_flash_cmd(uint8_t cmd, void *response, size_t len); +int spi_flash_cmd_write(const uint8_t *cmd, size_t cmd_len, + const void *data, size_t data_len); +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/sotp.h b/arm-trusted-firmware/include/drivers/brcm/sotp.h new file mode 100644 index 0000000..a93d687 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/sotp.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOTP_H +#define SOTP_H + +#include +#include + +#include + +#define SOTP_ROW_NO_ECC 0 +#define SOTP_ROW_ECC 1 + +#define SOTP_STATUS_1 (SOTP_REGS_OTP_BASE + 0x001c) +#define SOTP_FAIL_BITS 0x18000000000 +#define SOTP_ECC_ERR_DETECT 0x8000000000000000 + +#define SOTP_REGS_SOTP_CHIP_STATES (SOTP_REGS_OTP_BASE + 0x0028) +#define SOTP_REGS_OTP_WR_LOCK (SOTP_REGS_OTP_BASE + 0x0038) + +#define SOTP_CHIP_STATES_MANU_DEBUG_MASK (1 << 8) +#define SOTP_DEVICE_SECURE_CFG0_OTP_ERASED_MASK (3 << 16) +#define SOTP_REGS_SOTP_CHIP_STATES_OTP_ERASED_MASK (1 << 16) + +#define SOTP_DEVICE_SECURE_CFG0_CID_MASK (3 << 2) +#define SOTP_DEVICE_SECURE_CFG0_AB_MASK (3 << 6) +#define SOTP_DEVICE_SECURE_CFG0_DEV_MASK (3 << 8) + +#define SOTP_BOOT_SOURCE_SHIFT 8 +/* bits 14 and 15 */ +#define SOTP_BOOT_SOURCE_ENABLE_MASK (0xC0 << SOTP_BOOT_SOURCE_SHIFT) +/* bits 8 to 13 */ +#define SOTP_BOOT_SOURCE_BITS0 (0x03 << SOTP_BOOT_SOURCE_SHIFT) +#define SOTP_BOOT_SOURCE_BITS1 (0x0C << SOTP_BOOT_SOURCE_SHIFT) +#define SOTP_BOOT_SOURCE_BITS2 (0x30 << SOTP_BOOT_SOURCE_SHIFT) +#define SOTP_BOOT_SOURCE_MASK (0x3F << SOTP_BOOT_SOURCE_SHIFT) + +#define SOTP_ATF_CFG_ROW_ID SOTP_DEVICE_SECURE_CFG2_ROW +/* bits 28 and 29 */ +#define SOTP_SBL_MASK (3 << 28) +/* bits 30 and 31 */ +#define SOTP_ATF_NVCOUNTER_ENABLE_MASK ((uint64_t)3 << 30) +/* bits 32 and 33 */ +#define SOTP_ATF_WATCHDOG_ENABLE_MASK ((uint64_t)3 << 32) +/* bits 34 and 35 */ +#define SOTP_ATF_PLL_ON ((uint64_t)3 << 34) +/* bits 36 and 37 */ +#define SOTP_ATF_RESET_RETRY ((uint64_t)3 << 36) +/* bits 38 to 40 */ +#define SOTP_ATF_LOG_LEVEL_SHIFT 38 +#define SOTP_ATF_LOG_LEVEL ((uint64_t)7 << SOTP_ATF_LOG_LEVEL_SHIFT) + +#define SOTP_ATF2_CFG_ROW_ID SOTP_DEVICE_SECURE_CFG3_ROW +/* bits 16 and 17 */ +#define SOTP_ROMKEY_MASK (3 << 16) +/* bits 18 and 19 */ +#define SOTP_EC_EN_MASK (3 << 18) + +#define SOTP_ENC_DEV_TYPE_AB_DEV ((uint64_t)0x19999800000) +#define SOTP_ENC_DEV_TYPE_MASK ((uint64_t)0x1ffff800000) + +uint64_t sotp_mem_read(uint32_t offset, uint32_t sotp_add_ecc); +void sotp_mem_write(uint32_t addr, uint32_t sotp_add_ecc, uint64_t wdata); +int sotp_read_key(uint8_t *key, size_t keysize, int start_row, int end_row); +int sotp_key_erased(void); +uint32_t sotp_redundancy_reduction(uint32_t sotp_row_data); +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/spi.h b/arm-trusted-firmware/include/drivers/brcm/spi.h new file mode 100644 index 0000000..9d92d8c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/spi.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPI_H +#define SPI_H + +#include + +#define SPI_XFER_BEGIN (1 << 0) /* Assert CS before transfer */ +#define SPI_XFER_END (1 << 1) /* De-assert CS after transfer */ +#define SPI_XFER_QUAD (1 << 2) + +int spi_init(void); +int spi_claim_bus(void); +void spi_release_bus(void); +int spi_xfer(uint32_t bitlen, const void *dout, void *din, uint32_t flags); + +#endif /* _SPI_H_ */ diff --git a/arm-trusted-firmware/include/drivers/brcm/spi_flash.h b/arm-trusted-firmware/include/drivers/brcm/spi_flash.h new file mode 100644 index 0000000..bbaaa50 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/spi_flash.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPI_FLASH_H +#define SPI_FLASH_H + +#include + +int spi_flash_probe(struct spi_flash *flash); +int spi_flash_erase(struct spi_flash *flash, uint32_t offset, uint32_t len); +int spi_flash_write(struct spi_flash *flash, uint32_t offset, + uint32_t len, void *buf); +int spi_flash_read(struct spi_flash *flash, uint32_t offset, + uint32_t len, void *data); +#endif /* _SPI_FLASH_H_ */ diff --git a/arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h b/arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h new file mode 100644 index 0000000..93dec7b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h @@ -0,0 +1,4809 @@ +/* + * Copyright (c) 2017 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef USBH_XHCI_REGS_H +#define USBH_XHCI_REGS_H + +#include +#include + +#define XHCI_LEN (8096U) + +#define XHC_CPLIVER_OFFSET 0x000U +#define XHC_SPARAMS1_OFFSET 0x004U +#define XHC_SPARAMS2_OFFSET 0x008U +#define XHC_SPARAMS3_OFFSET 0x00cU +#define XHC_CPARAMS1_OFFSET 0x010U +#define XHC_DBOFF_OFFSET 0x014U +#define XHC_RTOFF_OFFSET 0x018U +#define XHC_CPARAMS2_OFFSET 0x01cU +#define XHC_USBCMD_OFFSET 0x020U +#define XHC_USBSTS_OFFSET 0x024U +#define XHC_PAGESIZE_OFFSET 0x028U +#define XHC_DNCTRL_OFFSET 0x034U +#define XHC_CRCRL_OFFSET 0x038U +#define XHC_CRCRH_OFFSET 0x03cU +#define XHC_DCBAAPL_OFFSET 0x050U +#define XHC_DCBAAPH_OFFSET 0x054U +#define XHC_CONFIG_OFFSET 0x058U +#define XHC_PORTSC1_OFFSET 0x420U +#define XHC_PORTPM1_OFFSET 0x424U +#define XHC_PORTLC1_OFFSET 0x428U +#define XHC_PORTSC2_OFFSET 0x430U +#define XHC_PORTPM2_OFFSET 0x434U +#define XHC_PORTLC2_OFFSET 0x43cU +#define XHC_PORTSC3_OFFSET 0x440U +#define XHC_PORTPM3_OFFSET 0x444U +#define XHC_PORTLI3_OFFSET 0x44cU +#define XHC_MFINDEX_OFFSET 0x4a0U +#define XHC_IMAN0_OFFSET 0x4c0U +#define XHC_IMOD0_OFFSET 0x4c4U +#define XHC_ERSTSZ0_OFFSET 0x4c8U +#define XHC_ERSTBAL0_OFFSET 0x4d0U +#define XHC_ERSTBAH0_OFFSET 0x4d4U +#define XHC_ERDPL0_OFFSET 0x4d8U +#define XHC_ERDPH0_OFFSET 0x4dcU +#define XHC_IMAN1_OFFSET 0x4e0U +#define XHC_IMOD1_OFFSET 0x4e4U +#define XHC_ERSTSZ1_OFFSET 0x4e8U +#define XHC_ERSTBAL1_OFFSET 0x4f0U +#define XHC_ERSTBAH1_OFFSET 0x4f4U +#define XHC_ERDPL1_OFFSET 0x4f8U +#define XHC_ERDPH1_OFFSET 0x4fcU +#define XHC_DBLCMD_OFFSET 0x8c0U +#define XHC_DBLDVX1_OFFSET 0x8c4U +#define XHC_DBLDVX2_OFFSET 0x8c8U +#define XHC_DBLDVX3_OFFSET 0x8ccU +#define XHC_DBLDVX4_OFFSET 0x8d0U +#define XHC_DBLDVX5_OFFSET 0x8d4U +#define XHC_DBLDVX6_OFFSET 0x8d8U +#define XHC_DBLDVX7_OFFSET 0x8dcU +#define XHC_DBLDVX8_OFFSET 0x8e0U +#define XHC_DBLDVX9_OFFSET 0x8e4U +#define XHC_DBLDVX10_OFFSET 0x8e8U +#define XHC_DBLDVX11_OFFSET 0x8ecU +#define XHC_DBLDVX12_OFFSET 0x8f0U +#define XHC_DBLDVX13_OFFSET 0x8f4U +#define XHC_DBLDVX14_OFFSET 0x8f8U +#define XHC_DBLDVX15_OFFSET 0x8fcU +#define XHC_DBLDVX16_OFFSET 0x900U +#define XHC_ECHSPT3_OFFSET 0x940U +#define XHC_PNSTR3_OFFSET 0x944U +#define XHC_PSUM3_OFFSET 0x948U +#define XHC_PTSLTYP3_OFFSET 0x94cU +#define XHC_ECHSPT2_OFFSET 0x950U +#define XHC_PNSTR2_OFFSET 0x954U +#define XHC_PSUM2_OFFSET 0x958U +#define XHC_PTSLTYP2_OFFSET 0x95cU +#define XHC_ECHRSVP_OFFSET 0x960U +#define XHC_ECHRSVI_OFFSET 0x968U +#define XHC_ECHRSVM_OFFSET 0xae8U +#define XHC_ECHRSVD_OFFSET 0xaf8U +#define XHC_ECHRSVO_OFFSET 0xb38U +#define XHC_ECHCTT_OFFSET 0xbf0U +#define XHC_CTTMTS0_OFFSET 0xbf8U +#define XHC_CTTMTS1_OFFSET 0xbfcU +#define XHC_ECHBIU_OFFSET 0xc00U +#define XHC_BIUSPC_OFFSET 0xc04U +#define XHC_AXIWRA_OFFSET 0xc08U +#define XHC_AXIRDA_OFFSET 0xc0cU +#define XHC_AXILPM_OFFSET 0xc10U +#define XHC_AXIQOS_OFFSET 0xc14U +#define XHC_ECHCSR_OFFSET 0xc20U +#define XHC_CSRSPC_OFFSET 0xc24U +#define XHC_ECHAIU_OFFSET 0xc30U +#define XHC_AIUDMA_OFFSET 0xc34U +#define XHC_AIUFLA_OFFSET 0xc38U +#define XHC_AIUCFG_OFFSET 0xc3cU +#define XHC_ECHFSC_OFFSET 0xc40U +#define XHC_FSCPOC_OFFSET 0xc54U +#define XHC_FSCGOC_OFFSET 0xc58U +#define XHC_FSCNOC_OFFSET 0xc5cU +#define XHC_FSCAIC_OFFSET 0xc60U +#define XHC_FSCPIC_OFFSET 0xc64U +#define XHC_FSCGIC_OFFSET 0xc68U +#define XHC_FSCNIC_OFFSET 0xc6cU +#define XHC_ECHPRT_OFFSET 0xc70U +#define XHC_PRTHSC_OFFSET 0xc78U +#define XHC_PRTHSR_OFFSET 0xc7cU +#define XHC_ECHRHS_OFFSET 0xc80U +#define XHC_RHSDES_OFFSET 0xc84U +#define XHC_RHSHSC0_OFFSET 0xc90U +#define XHC_RHSHSR0_OFFSET 0xc94U +#define XHC_RHSHSC1_OFFSET 0xc98U +#define XHC_RHSHSR1_OFFSET 0xc9cU +#define XHC_RHSHSC2_OFFSET 0xca0U +#define XHC_RHSHSR2_OFFSET 0xca4U +#define XHC_RHSHSC3_OFFSET 0xca8U +#define XHC_RHSHSR3_OFFSET 0xcacU +#define XHC_ECHSSP_OFFSET 0xcb0U +#define XHC_SSPVER_OFFSET 0xcb4U +#define XHC_SSPMGN_OFFSET 0xcb8U +#define XHC_ECHFSC2_OFFSET 0xcc0U +#define XHC_FSC2POC_OFFSET 0xcd4U +#define XHC_FSC2GOC_OFFSET 0xcd8U +#define XHC_FSC2NOC_OFFSET 0xcdcU +#define XHC_FSC2AIC_OFFSET 0xce0U +#define XHC_FSC2PIC_OFFSET 0xce4U +#define XHC_FSC2GIC_OFFSET 0xce8U +#define XHC_FSC2NIC_OFFSET 0xcecU +#define XHC_ECHPRT2_OFFSET 0xcf0U +#define XHC_PRT2HSC_OFFSET 0xcf8U +#define XHC_PRT2HSR_OFFSET 0xcfcU +#define XHC_ECHRH2_OFFSET 0xd00U +#define XHC_RH2DES_OFFSET 0xd04U +#define XHC_RH2HSC0_OFFSET 0xd10U +#define XHC_RH2HSR0_OFFSET 0xd14U +#define XHC_RH2HSC1_OFFSET 0xd18U +#define XHC_RH2HSR1_OFFSET 0xd1cU +#define XHC_RH2HSC2_OFFSET 0xd20U +#define XHC_RH2HSR2_OFFSET 0xd24U +#define XHC_RH2HSC3_OFFSET 0xd28U +#define XHC_RH2HSR3_OFFSET 0xd2cU +#define XHC_ECHU2P_OFFSET 0xd30U +#define XHC_U2PVER_OFFSET 0xd34U +#define XHC_U2PMGN_OFFSET 0xd38U +#define XHC_ECHRSV2_OFFSET 0xd40U +#define XHC_ECHIRA_OFFSET 0xf90U +#define XHC_IRAADR_OFFSET 0xf98U +#define XHC_IRADAT_OFFSET 0xf9cU +#define XHC_ECHHST_OFFSET 0xfa0U +#define XHC_HSTDBG_OFFSET 0xfa4U +#define XHC_HSTNPL_OFFSET 0xfa8U +#define XHC_HSTNPH_OFFSET 0xfacU +#define XHC_ECHRBV_OFFSET 0xfb0U +#define XHC_RBVPDT_OFFSET 0xfb4U +#define XHC_RBVMGN_OFFSET 0xfbcU + +#define XHC_CPLIVER_BASE 0x000U +#define XHC_CPLIVER__IVH_L 31U +#define XHC_CPLIVER__IVH_R 24U +#define XHC_CPLIVER__IVH_WIDTH 8U +#define XHC_CPLIVER__IVH_RESETVALUE 0x01U +#define XHC_CPLIVER__IVL_L 23U +#define XHC_CPLIVER__IVL_R 16U +#define XHC_CPLIVER__IVL_WIDTH 8U +#define XHC_CPLIVER__IVL_RESETVALUE 0x10U +#define XHC_CPLIVER__reserved_L 15U +#define XHC_CPLIVER__reserved_R 8U +#define XHC_CPLIVER__reserved_WIDTH 8U +#define XHC_CPLIVER__reserved_RESETVALUE 0x00U +#define XHC_CPLIVER__CPL_L 7U +#define XHC_CPLIVER__CPL_R 0U +#define XHC_CPLIVER__CPL_WIDTH 8U +#define XHC_CPLIVER__CPL_RESETVALUE 0x00U +#define XHC_CPLIVER_WIDTH 32U +#define XHC_CPLIVER__WIDTH 32U +#define XHC_CPLIVER_ALL_L 31U +#define XHC_CPLIVER_ALL_R 0U +#define XHC_CPLIVER__ALL_L 31U +#define XHC_CPLIVER__ALL_R 0U +#define XHC_CPLIVER_DATAMASK 0xffffffffU +#define XHC_CPLIVER_RDWRMASK 0x00000000U +#define XHC_CPLIVER_RESETVALUE 0x01100000U + +#define XHC_SPARAMS1_OFFSET 0x004U +#define XHC_SPARAMS1_BASE 0x004U +#define XHC_SPARAMS1__NPTS_L 31U +#define XHC_SPARAMS1__NPTS_R 24U +#define XHC_SPARAMS1__NPTS_WIDTH 8U +#define XHC_SPARAMS1__NPTS_RESETVALUE 0x00U +#define XHC_SPARAMS1__reserved_L 23U +#define XHC_SPARAMS1__reserved_R 19U +#define XHC_SPARAMS1__reserved_WIDTH 5U +#define XHC_SPARAMS1__reserved_RESETVALUE 0x0U +#define XHC_SPARAMS1__MITS_L 18U +#define XHC_SPARAMS1__MITS_R 8U +#define XHC_SPARAMS1__MITS_WIDTH 11U +#define XHC_SPARAMS1__MITS_RESETVALUE 0x1U +#define XHC_SPARAMS1__MSLS_L 7U +#define XHC_SPARAMS1__MSLS_R 0U +#define XHC_SPARAMS1__MSLS_WIDTH 8U +#define XHC_SPARAMS1__MSLS_RESETVALUE 0x00U +#define XHC_SPARAMS1_WIDTH 32U +#define XHC_SPARAMS1__WIDTH 32U +#define XHC_SPARAMS1_ALL_L 31U +#define XHC_SPARAMS1_ALL_R 0U +#define XHC_SPARAMS1__ALL_L 31U +#define XHC_SPARAMS1__ALL_R 0U +#define XHC_SPARAMS1_DATAMASK 0xffffffffU +#define XHC_SPARAMS1_RDWRMASK 0x00000000U +#define XHC_SPARAMS1_RESETVALUE 0x00000100U + +#define XHC_SPARAMS2_OFFSET 0x008U +#define XHC_SPARAMS2_BASE 0x008U +#define XHC_SPARAMS2__MSPBSL_L 31U +#define XHC_SPARAMS2__MSPBSL_R 27U +#define XHC_SPARAMS2__MSPBSL_WIDTH 5U +#define XHC_SPARAMS2__MSPBSL_RESETVALUE 0x0U +#define XHC_SPARAMS2__SPR 26U +#define XHC_SPARAMS2__SPR_L 26U +#define XHC_SPARAMS2__SPR_R 26U +#define XHC_SPARAMS2__SPR_WIDTH 1U +#define XHC_SPARAMS2__SPR_RESETVALUE 0x1U +#define XHC_SPARAMS2__MSPBSH_L 25U +#define XHC_SPARAMS2__MSPBSH_R 21U +#define XHC_SPARAMS2__MSPBSH_WIDTH 5U +#define XHC_SPARAMS2__MSPBSH_RESETVALUE 0x0U +#define XHC_SPARAMS2__reserved_L 20U +#define XHC_SPARAMS2__reserved_R 8U +#define XHC_SPARAMS2__reserved_WIDTH 13U +#define XHC_SPARAMS2__reserved_RESETVALUE 0x0U +#define XHC_SPARAMS2__MERST_L 7U +#define XHC_SPARAMS2__MERST_R 4U +#define XHC_SPARAMS2__MERST_WIDTH 4U +#define XHC_SPARAMS2__MERST_RESETVALUE 0x0U +#define XHC_SPARAMS2__IST_L 3U +#define XHC_SPARAMS2__IST_R 0U +#define XHC_SPARAMS2__IST_WIDTH 4U +#define XHC_SPARAMS2__IST_RESETVALUE 0x0U +#define XHC_SPARAMS2_WIDTH 32U +#define XHC_SPARAMS2__WIDTH 32U +#define XHC_SPARAMS2_ALL_L 31U +#define XHC_SPARAMS2_ALL_R 0U +#define XHC_SPARAMS2__ALL_L 31U +#define XHC_SPARAMS2__ALL_R 0U +#define XHC_SPARAMS2_DATAMASK 0xffffffffU +#define XHC_SPARAMS2_RDWRMASK 0x00000000U +#define XHC_SPARAMS2_RESETVALUE 0x04000000U + +#define XHC_SPARAMS3_OFFSET 0x00cU +#define XHC_SPARAMS3_BASE 0x00cU +#define XHC_SPARAMS3__U2L_L 31U +#define XHC_SPARAMS3__U2L_R 16U +#define XHC_SPARAMS3__U2L_WIDTH 16U +#define XHC_SPARAMS3__U2L_RESETVALUE 0x0000U +#define XHC_SPARAMS3__reserved_L 15U +#define XHC_SPARAMS3__reserved_R 8U +#define XHC_SPARAMS3__reserved_WIDTH 8U +#define XHC_SPARAMS3__reserved_RESETVALUE 0x00U +#define XHC_SPARAMS3__U1L_L 7U +#define XHC_SPARAMS3__U1L_R 0U +#define XHC_SPARAMS3__U1L_WIDTH 8U +#define XHC_SPARAMS3__U1L_RESETVALUE 0x00U +#define XHC_SPARAMS3_WIDTH 32U +#define XHC_SPARAMS3__WIDTH 32U +#define XHC_SPARAMS3_ALL_L 31U +#define XHC_SPARAMS3_ALL_R 0U +#define XHC_SPARAMS3__ALL_L 31U +#define XHC_SPARAMS3__ALL_R 0U +#define XHC_SPARAMS3_DATAMASK 0xffffffffU +#define XHC_SPARAMS3_RDWRMASK 0x00000000U +#define XHC_SPARAMS3_RESETVALUE 0x00000000U + +#define XHC_CPARAMS1_OFFSET 0x010U +#define XHC_CPARAMS1_BASE 0x010U +#define XHC_CPARAMS1__XECP_L 31U +#define XHC_CPARAMS1__XECP_R 16U +#define XHC_CPARAMS1__XECP_WIDTH 16U +#define XHC_CPARAMS1__XECP_RESETVALUE 0x0000U +#define XHC_CPARAMS1__MPSA_L 15U +#define XHC_CPARAMS1__MPSA_R 12U +#define XHC_CPARAMS1__MPSA_WIDTH 4U +#define XHC_CPARAMS1__MPSA_RESETVALUE 0x0U +#define XHC_CPARAMS1__CFC 11U +#define XHC_CPARAMS1__CFC_L 11U +#define XHC_CPARAMS1__CFC_R 11U +#define XHC_CPARAMS1__CFC_WIDTH 1U +#define XHC_CPARAMS1__CFC_RESETVALUE 0x0U +#define XHC_CPARAMS1__SEC 10U +#define XHC_CPARAMS1__SEC_L 10U +#define XHC_CPARAMS1__SEC_R 10U +#define XHC_CPARAMS1__SEC_WIDTH 1U +#define XHC_CPARAMS1__SEC_RESETVALUE 0x0U +#define XHC_CPARAMS1__SPC 9U +#define XHC_CPARAMS1__SPC_L 9U +#define XHC_CPARAMS1__SPC_R 9U +#define XHC_CPARAMS1__SPC_WIDTH 1U +#define XHC_CPARAMS1__SPC_RESETVALUE 0x0U +#define XHC_CPARAMS1__PAE 8U +#define XHC_CPARAMS1__PAE_L 8U +#define XHC_CPARAMS1__PAE_R 8U +#define XHC_CPARAMS1__PAE_WIDTH 1U +#define XHC_CPARAMS1__PAE_RESETVALUE 0x1U +#define XHC_CPARAMS1__NSS 7U +#define XHC_CPARAMS1__NSS_L 7U +#define XHC_CPARAMS1__NSS_R 7U +#define XHC_CPARAMS1__NSS_WIDTH 1U +#define XHC_CPARAMS1__NSS_RESETVALUE 0x0U +#define XHC_CPARAMS1__LTC 6U +#define XHC_CPARAMS1__LTC_L 6U +#define XHC_CPARAMS1__LTC_R 6U +#define XHC_CPARAMS1__LTC_WIDTH 1U +#define XHC_CPARAMS1__LTC_RESETVALUE 0x1U +#define XHC_CPARAMS1__LRC 5U +#define XHC_CPARAMS1__LRC_L 5U +#define XHC_CPARAMS1__LRC_R 5U +#define XHC_CPARAMS1__LRC_WIDTH 1U +#define XHC_CPARAMS1__LRC_RESETVALUE 0x0U +#define XHC_CPARAMS1__PIND 4U +#define XHC_CPARAMS1__PIND_L 4U +#define XHC_CPARAMS1__PIND_R 4U +#define XHC_CPARAMS1__PIND_WIDTH 1U +#define XHC_CPARAMS1__PIND_RESETVALUE 0x0U + +#define XHC_CPARAMS1__PPC_L 3U +#define XHC_CPARAMS1__PPC_R 3U +#define XHC_CPARAMS1__PPC_WIDTH 1U +#define XHC_CPARAMS1__PPC_RESETVALUE 0x0U +#define XHC_CPARAMS1__CSZ 2U +#define XHC_CPARAMS1__CSZ_L 2U +#define XHC_CPARAMS1__CSZ_R 2U +#define XHC_CPARAMS1__CSZ_WIDTH 1U +#define XHC_CPARAMS1__CSZ_RESETVALUE 0x1U +#define XHC_CPARAMS1__BNC 1U +#define XHC_CPARAMS1__BNC_L 1U +#define XHC_CPARAMS1__BNC_R 1U +#define XHC_CPARAMS1__BNC_WIDTH 1U +#define XHC_CPARAMS1__BNC_RESETVALUE 0x0U +#define XHC_CPARAMS1__AC64 0U +#define XHC_CPARAMS1__AC64_L 0U +#define XHC_CPARAMS1__AC64_R 0U +#define XHC_CPARAMS1__AC64_WIDTH 1U +#define XHC_CPARAMS1__AC64_RESETVALUE 0x0U +#define XHC_CPARAMS1_WIDTH 32U +#define XHC_CPARAMS1__WIDTH 32U +#define XHC_CPARAMS1_ALL_L 31U +#define XHC_CPARAMS1_ALL_R 0U +#define XHC_CPARAMS1__ALL_L 31U +#define XHC_CPARAMS1__ALL_R 0U +#define XHC_CPARAMS1_DATAMASK 0xffffffffU +#define XHC_CPARAMS1_RDWRMASK 0x00000000U +#define XHC_CPARAMS1_RESETVALUE 0x00000144U + +#define XHC_DBOFF_OFFSET 0x014U +#define XHC_DBOFF_BASE 0x014U +#define XHC_DBOFF__DBO_L 15U +#define XHC_DBOFF__DBO_R 2U +#define XHC_DBOFF__DBO_WIDTH 14U +#define XHC_DBOFF__DBO_RESETVALUE 0x0U +#define XHC_DBOFF__reserved_L 1U +#define XHC_DBOFF__reserved_R 0U +#define XHC_DBOFF__reserved_WIDTH 2U +#define XHC_DBOFF__reserved_RESETVALUE 0x0U +#define XHC_DBOFF__RESERVED_L 31U +#define XHC_DBOFF__RESERVED_R 16U +#define XHC_DBOFF_WIDTH 16U +#define XHC_DBOFF__WIDTH 16U +#define XHC_DBOFF_ALL_L 15U +#define XHC_DBOFF_ALL_R 0U +#define XHC_DBOFF__ALL_L 15U +#define XHC_DBOFF__ALL_R 0U +#define XHC_DBOFF_DATAMASK 0x0000ffffU +#define XHC_DBOFF_RDWRMASK 0xffff0000U +#define XHC_DBOFF_RESETVALUE 0x0000U + +#define XHC_RTOFF_OFFSET 0x018U +#define XHC_RTOFF_BASE 0x018U +#define XHC_RTOFF__RTO_L 15U +#define XHC_RTOFF__RTO_R 5U +#define XHC_RTOFF__RTO_WIDTH 11U +#define XHC_RTOFF__RTO_RESETVALUE 0x0U +#define XHC_RTOFF__reserved_L 4U +#define XHC_RTOFF__reserved_R 0U +#define XHC_RTOFF__reserved_WIDTH 5U +#define XHC_RTOFF__reserved_RESETVALUE 0x0U +#define XHC_RTOFF__RESERVED_L 31U +#define XHC_RTOFF__RESERVED_R 16U +#define XHC_RTOFF_WIDTH 16U +#define XHC_RTOFF__WIDTH 16U +#define XHC_RTOFF_ALL_L 15U +#define XHC_RTOFF_ALL_R 0U +#define XHC_RTOFF__ALL_L 15U +#define XHC_RTOFF__ALL_R 0U +#define XHC_RTOFF_DATAMASK 0x0000ffffU +#define XHC_RTOFF_RDWRMASK 0xffff0000U +#define XHC_RTOFF_RESETVALUE 0x0000U + +#define XHC_CPARAMS2_OFFSET 0x01cU +#define XHC_CPARAMS2_BASE 0x01cU +#define XHC_CPARAMS2__reserved_L 31U +#define XHC_CPARAMS2__reserved_R 6U +#define XHC_CPARAMS2__reserved_WIDTH 26U +#define XHC_CPARAMS2__reserved_RESETVALUE 0x0U +#define XHC_CPARAMS2__CIC 5U +#define XHC_CPARAMS2__CIC_L 5U +#define XHC_CPARAMS2__CIC_R 5U +#define XHC_CPARAMS2__CIC_WIDTH 1U +#define XHC_CPARAMS2__CIC_RESETVALUE 0x0U +#define XHC_CPARAMS2__LEC 4U +#define XHC_CPARAMS2__LEC_L 4U +#define XHC_CPARAMS2__LEC_R 4U +#define XHC_CPARAMS2__LEC_WIDTH 1U +#define XHC_CPARAMS2__LEC_RESETVALUE 0x0U +#define XHC_CPARAMS2__CTC 3U +#define XHC_CPARAMS2__CTC_L 3U +#define XHC_CPARAMS2__CTC_R 3U +#define XHC_CPARAMS2__CTC_WIDTH 1U +#define XHC_CPARAMS2__CTC_RESETVALUE 0x0U +#define XHC_CPARAMS2__FSC 2U +#define XHC_CPARAMS2__FSC_L 2U +#define XHC_CPARAMS2__FSC_R 2U +#define XHC_CPARAMS2__FSC_WIDTH 1U +#define XHC_CPARAMS2__FSC_RESETVALUE 0x0U +#define XHC_CPARAMS2__CMC 1U +#define XHC_CPARAMS2__CMC_L 1U +#define XHC_CPARAMS2__CMC_R 1U +#define XHC_CPARAMS2__CMC_WIDTH 1U +#define XHC_CPARAMS2__CMC_RESETVALUE 0x0U +#define XHC_CPARAMS2__U3C 0U +#define XHC_CPARAMS2__U3C_L 0U +#define XHC_CPARAMS2__U3C_R 0U +#define XHC_CPARAMS2__U3C_WIDTH 1U +#define XHC_CPARAMS2__U3C_RESETVALUE 0x0U +#define XHC_CPARAMS2_WIDTH 32U +#define XHC_CPARAMS2__WIDTH 32U +#define XHC_CPARAMS2_ALL_L 31U +#define XHC_CPARAMS2_ALL_R 0U +#define XHC_CPARAMS2__ALL_L 31U +#define XHC_CPARAMS2__ALL_R 0U +#define XHC_CPARAMS2_DATAMASK 0xffffffffU +#define XHC_CPARAMS2_RDWRMASK 0x00000000U +#define XHC_CPARAMS2_RESETVALUE 0x00000000U + +#define XHC_USBCMD_OFFSET 0x020U +#define XHC_USBCMD_BASE 0x020U +#define XHC_USBCMD__CME 13U +#define XHC_USBCMD__CME_L 13U +#define XHC_USBCMD__CME_R 13U +#define XHC_USBCMD__CME_WIDTH 1U +#define XHC_USBCMD__CME_RESETVALUE 0x0U +#define XHC_USBCMD__SPE 12U +#define XHC_USBCMD__SPE_L 12U +#define XHC_USBCMD__SPE_R 12U +#define XHC_USBCMD__SPE_WIDTH 1U +#define XHC_USBCMD__SPE_RESETVALUE 0x0U +#define XHC_USBCMD__EU3S 11U +#define XHC_USBCMD__EU3S_L 11U +#define XHC_USBCMD__EU3S_R 11U +#define XHC_USBCMD__EU3S_WIDTH 1U +#define XHC_USBCMD__EU3S_RESETVALUE 0x0U +#define XHC_USBCMD__EWE 10U +#define XHC_USBCMD__EWE_L 10U +#define XHC_USBCMD__EWE_R 10U +#define XHC_USBCMD__EWE_WIDTH 1U +#define XHC_USBCMD__EWE_RESETVALUE 0x0U +#define XHC_USBCMD__CRS 9U +#define XHC_USBCMD__CRS_L 9U +#define XHC_USBCMD__CRS_R 9U +#define XHC_USBCMD__CRS_WIDTH 1U +#define XHC_USBCMD__CRS_RESETVALUE 0x0U +#define XHC_USBCMD__CSS 8U +#define XHC_USBCMD__CSS_L 8U +#define XHC_USBCMD__CSS_R 8U +#define XHC_USBCMD__CSS_WIDTH 1U +#define XHC_USBCMD__CSS_RESETVALUE 0x0U +#define XHC_USBCMD__LRST 7U +#define XHC_USBCMD__LRST_L 7U +#define XHC_USBCMD__LRST_R 7U +#define XHC_USBCMD__LRST_WIDTH 1U +#define XHC_USBCMD__LRST_RESETVALUE 0x0U +#define XHC_USBCMD__reserved_L 6U +#define XHC_USBCMD__reserved_R 4U +#define XHC_USBCMD__reserved_WIDTH 3U +#define XHC_USBCMD__reserved_RESETVALUE 0x0U +#define XHC_USBCMD__HSEE 3U +#define XHC_USBCMD__HSEE_L 3U +#define XHC_USBCMD__HSEE_R 3U +#define XHC_USBCMD__HSEE_WIDTH 1U +#define XHC_USBCMD__HSEE_RESETVALUE 0x0U +#define XHC_USBCMD__INTE 2U +#define XHC_USBCMD__INTE_L 2U +#define XHC_USBCMD__INTE_R 2U +#define XHC_USBCMD__INTE_WIDTH 1U +#define XHC_USBCMD__INTE_RESETVALUE 0x0U +#define XHC_USBCMD__RST 1U +#define XHC_USBCMD__RST_L 1U +#define XHC_USBCMD__RST_R 1U +#define XHC_USBCMD__RST_WIDTH 1U +#define XHC_USBCMD__RST_RESETVALUE 0x0U +#define XHC_USBCMD__RS 0U +#define XHC_USBCMD__RS_L 0U +#define XHC_USBCMD__RS_R 0U +#define XHC_USBCMD__RS_WIDTH 1U +#define XHC_USBCMD__RS_RESETVALUE 0x0U +#define XHC_USBCMD__RESERVED_L 31U +#define XHC_USBCMD__RESERVED_R 14U +#define XHC_USBCMD_WIDTH 14U +#define XHC_USBCMD__WIDTH 14U +#define XHC_USBCMD_ALL_L 13U +#define XHC_USBCMD_ALL_R 0U +#define XHC_USBCMD__ALL_L 13U +#define XHC_USBCMD__ALL_R 0U +#define XHC_USBCMD_DATAMASK 0x00003fffU +#define XHC_USBCMD_RDWRMASK 0xffffc000U +#define XHC_USBCMD_RESETVALUE 0x0000U + +#define XHC_USBSTS_OFFSET 0x024U +#define XHC_USBSTS_BASE 0x024U +#define XHC_USBSTS__CE 12U +#define XHC_USBSTS__CE_L 12U +#define XHC_USBSTS__CE_R 12U +#define XHC_USBSTS__CE_WIDTH 1U +#define XHC_USBSTS__CE_RESETVALUE 0x0U +#define XHC_USBSTS__CNR 11U +#define XHC_USBSTS__CNR_L 11U +#define XHC_USBSTS__CNR_R 11U +#define XHC_USBSTS__CNR_WIDTH 1U +#define XHC_USBSTS__CNR_RESETVALUE 0x1U + +#define XHC_USBSTS__SRE 10U +#define XHC_USBSTS__SRE_L 10U +#define XHC_USBSTS__SRE_R 10U +#define XHC_USBSTS__SRE_WIDTH 1U +#define XHC_USBSTS__SRE_RESETVALUE 0x0U +#define XHC_USBSTS__RSS 9U +#define XHC_USBSTS__RSS_L 9U +#define XHC_USBSTS__RSS_R 9U +#define XHC_USBSTS__RSS_WIDTH 1U +#define XHC_USBSTS__RSS_RESETVALUE 0x0U +#define XHC_USBSTS__SSS 8U +#define XHC_USBSTS__SSS_L 8U +#define XHC_USBSTS__SSS_R 8U +#define XHC_USBSTS__SSS_WIDTH 1U +#define XHC_USBSTS__SSS_RESETVALUE 0x0U +#define XHC_USBSTS__PCD 4U +#define XHC_USBSTS__PCD_L 4U +#define XHC_USBSTS__PCD_R 4U +#define XHC_USBSTS__PCD_WIDTH 1U +#define XHC_USBSTS__PCD_RESETVALUE 0x0U +#define XHC_USBSTS__EINT 3U +#define XHC_USBSTS__EINT_L 3U +#define XHC_USBSTS__EINT_R 3U +#define XHC_USBSTS__EINT_WIDTH 1U +#define XHC_USBSTS__EINT_RESETVALUE 0x0U +#define XHC_USBSTS__HSE 2U +#define XHC_USBSTS__HSE_L 2U +#define XHC_USBSTS__HSE_R 2U +#define XHC_USBSTS__HSE_WIDTH 1U +#define XHC_USBSTS__HSE_RESETVALUE 0x0U +#define XHC_USBSTS__reserved 1U +#define XHC_USBSTS__reserved_L 1U +#define XHC_USBSTS__reserved_R 1U +#define XHC_USBSTS__reserved_WIDTH 1U +#define XHC_USBSTS__reserved_RESETVALUE 0x0U + +#define XHC_USBSTS__CH_L 0U +#define XHC_USBSTS__CH_R 0U +#define XHC_USBSTS__CH_WIDTH 1U +#define XHC_USBSTS__CH_RESETVALUE 0x1U +#define XHC_USBSTS__RESERVED_L 31U +#define XHC_USBSTS__RESERVED_R 13U +#define XHC_USBSTS_WIDTH 13U +#define XHC_USBSTS__WIDTH 13U +#define XHC_USBSTS_ALL_L 12U +#define XHC_USBSTS_ALL_R 0U +#define XHC_USBSTS__ALL_L 12U +#define XHC_USBSTS__ALL_R 0U +#define XHC_USBSTS_DATAMASK 0x00001f1fU +#define XHC_USBSTS_RDWRMASK 0xffffe0e0U +#define XHC_USBSTS_RESETVALUE 0x0801U + +#define XHC_PAGESIZE_OFFSET 0x028U +#define XHC_PAGESIZE_BASE 0x028U +#define XHC_PAGESIZE__reserved_L 31U +#define XHC_PAGESIZE__reserved_R 16U +#define XHC_PAGESIZE__reserved_WIDTH 16U +#define XHC_PAGESIZE__reserved_RESETVALUE 0x0000U +#define XHC_PAGESIZE__PS_L 15U +#define XHC_PAGESIZE__PS_R 0U +#define XHC_PAGESIZE__PS_WIDTH 16U +#define XHC_PAGESIZE__PS_RESETVALUE 0x0000U +#define XHC_PAGESIZE_WIDTH 32U +#define XHC_PAGESIZE__WIDTH 32U +#define XHC_PAGESIZE_ALL_L 31U +#define XHC_PAGESIZE_ALL_R 0U +#define XHC_PAGESIZE__ALL_L 31U +#define XHC_PAGESIZE__ALL_R 0U +#define XHC_PAGESIZE_DATAMASK 0xffffffffU +#define XHC_PAGESIZE_RDWRMASK 0x00000000U +#define XHC_PAGESIZE_RESETVALUE 0x00000000U + +#define XHC_DNCTRL_OFFSET 0x034U +#define XHC_DNCTRL_BASE 0x034U +#define XHC_DNCTRL__reserved_L 31U +#define XHC_DNCTRL__reserved_R 16U +#define XHC_DNCTRL__reserved_WIDTH 16U +#define XHC_DNCTRL__reserved_RESETVALUE 0x0000U +#define XHC_DNCTRL__DNE_L 15U +#define XHC_DNCTRL__DNE_R 0U +#define XHC_DNCTRL__DNE_WIDTH 16U +#define XHC_DNCTRL__DNE_RESETVALUE 0x0000U +#define XHC_DNCTRL_WIDTH 32U +#define XHC_DNCTRL__WIDTH 32U +#define XHC_DNCTRL_ALL_L 31U +#define XHC_DNCTRL_ALL_R 0U +#define XHC_DNCTRL__ALL_L 31U +#define XHC_DNCTRL__ALL_R 0U +#define XHC_DNCTRL_DATAMASK 0xffffffffU +#define XHC_DNCTRL_RDWRMASK 0x00000000U +#define XHC_DNCTRL_RESETVALUE 0x00000000U + +#define XHC_CRCRL_OFFSET 0x038U +#define XHC_CRCRL_BASE 0x038U +#define XHC_CRCRL__CRPL_L 31U +#define XHC_CRCRL__CRPL_R 6U +#define XHC_CRCRL__CRPL_WIDTH 26U +#define XHC_CRCRL__CRPL_RESETVALUE 0x0U +#define XHC_CRCRL__reserved_L 5U +#define XHC_CRCRL__reserved_R 4U +#define XHC_CRCRL__reserved_WIDTH 2U +#define XHC_CRCRL__reserved_RESETVALUE 0x0U +#define XHC_CRCRL__CRR 3U +#define XHC_CRCRL__CRR_L 3U +#define XHC_CRCRL__CRR_R 3U +#define XHC_CRCRL__CRR_WIDTH 1U +#define XHC_CRCRL__CRR_RESETVALUE 0x0U +#define XHC_CRCRL__CA 2U +#define XHC_CRCRL__CA_L 2U +#define XHC_CRCRL__CA_R 2U +#define XHC_CRCRL__CA_WIDTH 1U +#define XHC_CRCRL__CA_RESETVALUE 0x0U +#define XHC_CRCRL__CS 1U +#define XHC_CRCRL__CS_L 1U +#define XHC_CRCRL__CS_R 1U +#define XHC_CRCRL__CS_WIDTH 1U +#define XHC_CRCRL__CS_RESETVALUE 0x0U +#define XHC_CRCRL__RCS 0U +#define XHC_CRCRL__RCS_L 0U +#define XHC_CRCRL__RCS_R 0U +#define XHC_CRCRL__RCS_WIDTH 1U +#define XHC_CRCRL__RCS_RESETVALUE 0x0U +#define XHC_CRCRL_WIDTH 32U +#define XHC_CRCRL__WIDTH 32U +#define XHC_CRCRL_ALL_L 31U +#define XHC_CRCRL_ALL_R 0U +#define XHC_CRCRL__ALL_L 31U +#define XHC_CRCRL__ALL_R 0U +#define XHC_CRCRL_DATAMASK 0xffffffffU +#define XHC_CRCRL_RDWRMASK 0x00000000U +#define XHC_CRCRL_RESETVALUE 0x00000000U + +#define XHC_CRCRH_OFFSET 0x03cU +#define XHC_CRCRH_BASE 0x03cU +#define XHC_CRCRH__CRPH_L 31U +#define XHC_CRCRH__CRPH_R 0U +#define XHC_CRCRH__CRPH_WIDTH 32U +#define XHC_CRCRH__CRPH_RESETVALUE 0x00000000U +#define XHC_CRCRH_WIDTH 32U +#define XHC_CRCRH__WIDTH 32U +#define XHC_CRCRH_ALL_L 31U +#define XHC_CRCRH_ALL_R 0U +#define XHC_CRCRH__ALL_L 31U +#define XHC_CRCRH__ALL_R 0U +#define XHC_CRCRH_DATAMASK 0xffffffffU +#define XHC_CRCRH_RDWRMASK 0x00000000U +#define XHC_CRCRH_RESETVALUE 0x00000000U + +#define XHC_DCBAAPL_OFFSET 0x050U +#define XHC_DCBAAPL_BASE 0x050U +#define XHC_DCBAAPL__DCAL_L 31U +#define XHC_DCBAAPL__DCAL_R 6U +#define XHC_DCBAAPL__DCAL_WIDTH 26U +#define XHC_DCBAAPL__DCAL_RESETVALUE 0x0U + +#define XHC_DCBAAPL__reserved_L 5U +#define XHC_DCBAAPL__reserved_R 0U +#define XHC_DCBAAPL__reserved_WIDTH 6U +#define XHC_DCBAAPL__reserved_RESETVALUE 0x0U +#define XHC_DCBAAPL_WIDTH 32U +#define XHC_DCBAAPL__WIDTH 32U +#define XHC_DCBAAPL_ALL_L 31U +#define XHC_DCBAAPL_ALL_R 0U +#define XHC_DCBAAPL__ALL_L 31U +#define XHC_DCBAAPL__ALL_R 0U +#define XHC_DCBAAPL_DATAMASK 0xffffffffU +#define XHC_DCBAAPL_RDWRMASK 0x00000000U +#define XHC_DCBAAPL_RESETVALUE 0x00000000U + +#define XHC_DCBAAPH_OFFSET 0x054U +#define XHC_DCBAAPH_BASE 0x054U +#define XHC_DCBAAPH__DCAH_L 31U +#define XHC_DCBAAPH__DCAH_R 0U +#define XHC_DCBAAPH__DCAH_WIDTH 32U +#define XHC_DCBAAPH__DCAH_RESETVALUE 0x00000000U +#define XHC_DCBAAPH_WIDTH 32U +#define XHC_DCBAAPH__WIDTH 32U +#define XHC_DCBAAPH_ALL_L 31U +#define XHC_DCBAAPH_ALL_R 0U +#define XHC_DCBAAPH__ALL_L 31U +#define XHC_DCBAAPH__ALL_R 0U +#define XHC_DCBAAPH_DATAMASK 0xffffffffU +#define XHC_DCBAAPH_RDWRMASK 0x00000000U +#define XHC_DCBAAPH_RESETVALUE 0x00000000U + +#define XHC_CONFIG_OFFSET 0x058U +#define XHC_CONFIG_BASE 0x058U +#define XHC_CONFIG__reserved_L 31U +#define XHC_CONFIG__reserved_R 10U +#define XHC_CONFIG__reserved_WIDTH 22U +#define XHC_CONFIG__reserved_RESETVALUE 0x0U +#define XHC_CONFIG__CIE 9U +#define XHC_CONFIG__CIE_L 9U +#define XHC_CONFIG__CIE_R 9U +#define XHC_CONFIG__CIE_WIDTH 1U +#define XHC_CONFIG__CIE_RESETVALUE 0x0U +#define XHC_CONFIG__U3E 8U +#define XHC_CONFIG__U3E_L 8U +#define XHC_CONFIG__U3E_R 8U +#define XHC_CONFIG__U3E_WIDTH 1U +#define XHC_CONFIG__U3E_RESETVALUE 0x0U +#define XHC_CONFIG__MSE_L 7U +#define XHC_CONFIG__MSE_R 0U +#define XHC_CONFIG__MSE_WIDTH 8U +#define XHC_CONFIG__MSE_RESETVALUE 0x00U +#define XHC_CONFIG_WIDTH 32U +#define XHC_CONFIG__WIDTH 32U +#define XHC_CONFIG_ALL_L 31U +#define XHC_CONFIG_ALL_R 0U +#define XHC_CONFIG__ALL_L 31U +#define XHC_CONFIG__ALL_R 0U +#define XHC_CONFIG_DATAMASK 0xffffffffU +#define XHC_CONFIG_RDWRMASK 0x00000000U +#define XHC_CONFIG_RESETVALUE 0x00000000U + +#define XHC_PORTSC1_OFFSET 0x420U +#define XHC_PORTSC1_BASE 0x420U + +#define XHC_PORTSC1__WPR_L 31U +#define XHC_PORTSC1__WPR_R 31U +#define XHC_PORTSC1__WPR_WIDTH 1U +#define XHC_PORTSC1__WPR_RESETVALUE 0x0U + +#define XHC_PORTSC1__DNR_L 30U +#define XHC_PORTSC1__DNR_R 30U +#define XHC_PORTSC1__DNR_WIDTH 1U +#define XHC_PORTSC1__DNR_RESETVALUE 0x0U + +#define XHC_PORTSC1__WOE_L 27U +#define XHC_PORTSC1__WOE_R 27U +#define XHC_PORTSC1__WOE_WIDTH 1U +#define XHC_PORTSC1__WOE_RESETVALUE 0x0U + +#define XHC_PORTSC1__WDE_L 26U +#define XHC_PORTSC1__WDE_R 26U +#define XHC_PORTSC1__WDE_WIDTH 1U +#define XHC_PORTSC1__WDE_RESETVALUE 0x0U + +#define XHC_PORTSC1__WCE_L 25U +#define XHC_PORTSC1__WCE_R 25U +#define XHC_PORTSC1__WCE_WIDTH 1U +#define XHC_PORTSC1__WCE_RESETVALUE 0x0U + +#define XHC_PORTSC1__CAS_L 24U +#define XHC_PORTSC1__CAS_R 24U +#define XHC_PORTSC1__CAS_WIDTH 1U +#define XHC_PORTSC1__CAS_RESETVALUE 0x0U + +#define XHC_PORTSC1__CEC_L 23U +#define XHC_PORTSC1__CEC_R 23U +#define XHC_PORTSC1__CEC_WIDTH 1U +#define XHC_PORTSC1__CEC_RESETVALUE 0x0U + +#define XHC_PORTSC1__PLC_L 22U +#define XHC_PORTSC1__PLC_R 22U +#define XHC_PORTSC1__PLC_WIDTH 1U +#define XHC_PORTSC1__PLC_RESETVALUE 0x0U + +#define XHC_PORTSC1__PRC_L 21U +#define XHC_PORTSC1__PRC_R 21U +#define XHC_PORTSC1__PRC_WIDTH 1U +#define XHC_PORTSC1__PRC_RESETVALUE 0x0U + +#define XHC_PORTSC1__OCC_L 20U +#define XHC_PORTSC1__OCC_R 20U +#define XHC_PORTSC1__OCC_WIDTH 1U +#define XHC_PORTSC1__OCC_RESETVALUE 0x0U + +#define XHC_PORTSC1__WRC_L 19U +#define XHC_PORTSC1__WRC_R 19U +#define XHC_PORTSC1__WRC_WIDTH 1U +#define XHC_PORTSC1__WRC_RESETVALUE 0x0U + +#define XHC_PORTSC1__PEC_L 18U +#define XHC_PORTSC1__PEC_R 18U +#define XHC_PORTSC1__PEC_WIDTH 1U +#define XHC_PORTSC1__PEC_RESETVALUE 0x0U + +#define XHC_PORTSC1__CSC_L 17U +#define XHC_PORTSC1__CSC_R 17U +#define XHC_PORTSC1__CSC_WIDTH 1U +#define XHC_PORTSC1__CSC_RESETVALUE 0x0U + +#define XHC_PORTSC1__LWS_L 16U +#define XHC_PORTSC1__LWS_R 16U +#define XHC_PORTSC1__LWS_WIDTH 1U +#define XHC_PORTSC1__LWS_RESETVALUE 0x0U +#define XHC_PORTSC1__PIC_L 15U +#define XHC_PORTSC1__PIC_R 14U +#define XHC_PORTSC1__PIC_WIDTH 2U +#define XHC_PORTSC1__PIC_RESETVALUE 0x0U +#define XHC_PORTSC1__PS_L 13U +#define XHC_PORTSC1__PS_R 10U +#define XHC_PORTSC1__PS_WIDTH 4U +#define XHC_PORTSC1__PS_RESETVALUE 0x0U + +#define XHC_PORTSC1__PP_L 9U +#define XHC_PORTSC1__PP_R 9U +#define XHC_PORTSC1__PP_WIDTH 1U +#define XHC_PORTSC1__PP_RESETVALUE 0x0U +#define XHC_PORTSC1__PLS_L 8U +#define XHC_PORTSC1__PLS_R 5U +#define XHC_PORTSC1__PLS_WIDTH 4U +#define XHC_PORTSC1__PLS_RESETVALUE 0x5U + +#define XHC_PORTSC1__PRST_L 4U +#define XHC_PORTSC1__PRST_R 4U +#define XHC_PORTSC1__PRST_WIDTH 1U +#define XHC_PORTSC1__PRST_RESETVALUE 0x0U + +#define XHC_PORTSC1__OCA_L 3U +#define XHC_PORTSC1__OCA_R 3U +#define XHC_PORTSC1__OCA_WIDTH 1U +#define XHC_PORTSC1__OCA_RESETVALUE 0x0U +#define XHC_PORTSC1__reserved 2U +#define XHC_PORTSC1__reserved_L 2U +#define XHC_PORTSC1__reserved_R 2U +#define XHC_PORTSC1__reserved_WIDTH 1U +#define XHC_PORTSC1__reserved_RESETVALUE 0x0U + +#define XHC_PORTSC1__PED_L 1U +#define XHC_PORTSC1__PED_R 1U +#define XHC_PORTSC1__PED_WIDTH 1U +#define XHC_PORTSC1__PED_RESETVALUE 0x0U + +#define XHC_PORTSC1__CCS_L 0U +#define XHC_PORTSC1__CCS_R 0U +#define XHC_PORTSC1__CCS_WIDTH 1U +#define XHC_PORTSC1__CCS_RESETVALUE 0x0U +#define XHC_PORTSC1__RESERVED_L 29U +#define XHC_PORTSC1__RESERVED_R 28U +#define XHC_PORTSC1_WIDTH 32U +#define XHC_PORTSC1__WIDTH 32U +#define XHC_PORTSC1_ALL_L 31U +#define XHC_PORTSC1_ALL_R 0U +#define XHC_PORTSC1__ALL_L 31U +#define XHC_PORTSC1__ALL_R 0U +#define XHC_PORTSC1_DATAMASK 0xcfffffffU +#define XHC_PORTSC1_RDWRMASK 0x30000000U +#define XHC_PORTSC1_RESETVALUE 0x000000a0U + +#define XHC_PORTPM1_OFFSET 0x424U +#define XHC_PORTPM1_BASE 0x424U +#define XHC_PORTPM1__reserved_L 31U +#define XHC_PORTPM1__reserved_R 17U +#define XHC_PORTPM1__reserved_WIDTH 15U +#define XHC_PORTPM1__reserved_RESETVALUE 0x0U +#define XHC_PORTPM1__FLA 16U +#define XHC_PORTPM1__FLA_L 16U +#define XHC_PORTPM1__FLA_R 16U +#define XHC_PORTPM1__FLA_WIDTH 1U +#define XHC_PORTPM1__FLA_RESETVALUE 0x0U +#define XHC_PORTPM1__U2T_L 15U +#define XHC_PORTPM1__U2T_R 8U +#define XHC_PORTPM1__U2T_WIDTH 8U +#define XHC_PORTPM1__U2T_RESETVALUE 0x00U +#define XHC_PORTPM1__U1T_L 7U +#define XHC_PORTPM1__U1T_R 0U +#define XHC_PORTPM1__U1T_WIDTH 8U +#define XHC_PORTPM1__U1T_RESETVALUE 0x00U +#define XHC_PORTPM1_WIDTH 32U +#define XHC_PORTPM1__WIDTH 32U +#define XHC_PORTPM1_ALL_L 31U +#define XHC_PORTPM1_ALL_R 0U +#define XHC_PORTPM1__ALL_L 31U +#define XHC_PORTPM1__ALL_R 0U +#define XHC_PORTPM1_DATAMASK 0xffffffffU +#define XHC_PORTPM1_RDWRMASK 0x00000000U +#define XHC_PORTPM1_RESETVALUE 0x00000000U + +#define XHC_PORTLC1_OFFSET 0x428U +#define XHC_PORTLC1_BASE 0x428U +#define XHC_PORTLC1__reserved_L 31U +#define XHC_PORTLC1__reserved_R 0U +#define XHC_PORTLC1__reserved_WIDTH 32U +#define XHC_PORTLC1__reserved_RESETVALUE 0x00000000U +#define XHC_PORTLC1_WIDTH 32U +#define XHC_PORTLC1__WIDTH 32U +#define XHC_PORTLC1_ALL_L 31U +#define XHC_PORTLC1_ALL_R 0U +#define XHC_PORTLC1__ALL_L 31U +#define XHC_PORTLC1__ALL_R 0U +#define XHC_PORTLC1_DATAMASK 0xffffffffU +#define XHC_PORTLC1_RDWRMASK 0x00000000U +#define XHC_PORTLC1_RESETVALUE 0x00000000U + +#define XHC_PORTSC2_OFFSET 0x430U +#define XHC_PORTSC2_BASE 0x430U +#define XHC_PORTSC2__WPR 31U +#define XHC_PORTSC2__WPR_L 31U +#define XHC_PORTSC2__WPR_R 31U +#define XHC_PORTSC2__WPR_WIDTH 1U +#define XHC_PORTSC2__WPR_RESETVALUE 0x0U +#define XHC_PORTSC2__DNR 30U +#define XHC_PORTSC2__DNR_L 30U +#define XHC_PORTSC2__DNR_R 30U +#define XHC_PORTSC2__DNR_WIDTH 1U +#define XHC_PORTSC2__DNR_RESETVALUE 0x0U +#define XHC_PORTSC2__WOE 27U +#define XHC_PORTSC2__WOE_L 27U +#define XHC_PORTSC2__WOE_R 27U +#define XHC_PORTSC2__WOE_WIDTH 1U +#define XHC_PORTSC2__WOE_RESETVALUE 0x0U +#define XHC_PORTSC2__WDE 26U +#define XHC_PORTSC2__WDE_L 26U +#define XHC_PORTSC2__WDE_R 26U +#define XHC_PORTSC2__WDE_WIDTH 1U +#define XHC_PORTSC2__WDE_RESETVALUE 0x0U +#define XHC_PORTSC2__WCE 25U +#define XHC_PORTSC2__WCE_L 25U +#define XHC_PORTSC2__WCE_R 25U +#define XHC_PORTSC2__WCE_WIDTH 1U +#define XHC_PORTSC2__WCE_RESETVALUE 0x0U +#define XHC_PORTSC2__CAS 24U +#define XHC_PORTSC2__CAS_L 24U +#define XHC_PORTSC2__CAS_R 24U +#define XHC_PORTSC2__CAS_WIDTH 1U +#define XHC_PORTSC2__CAS_RESETVALUE 0x0U +#define XHC_PORTSC2__CEC 23U +#define XHC_PORTSC2__CEC_L 23U +#define XHC_PORTSC2__CEC_R 23U +#define XHC_PORTSC2__CEC_WIDTH 1U +#define XHC_PORTSC2__CEC_RESETVALUE 0x0U +#define XHC_PORTSC2__PLC 22U +#define XHC_PORTSC2__PLC_L 22U +#define XHC_PORTSC2__PLC_R 22U +#define XHC_PORTSC2__PLC_WIDTH 1U +#define XHC_PORTSC2__PLC_RESETVALUE 0x0U +#define XHC_PORTSC2__PRC 21U +#define XHC_PORTSC2__PRC_L 21U +#define XHC_PORTSC2__PRC_R 21U +#define XHC_PORTSC2__PRC_WIDTH 1U +#define XHC_PORTSC2__PRC_RESETVALUE 0x0U +#define XHC_PORTSC2__OCC 20U +#define XHC_PORTSC2__OCC_L 20U +#define XHC_PORTSC2__OCC_R 20U +#define XHC_PORTSC2__OCC_WIDTH 1U +#define XHC_PORTSC2__OCC_RESETVALUE 0x0U +#define XHC_PORTSC2__WRC 19U +#define XHC_PORTSC2__WRC_L 19U +#define XHC_PORTSC2__WRC_R 19U +#define XHC_PORTSC2__WRC_WIDTH 1U +#define XHC_PORTSC2__WRC_RESETVALUE 0x0U +#define XHC_PORTSC2__PEC 18U +#define XHC_PORTSC2__PEC_L 18U +#define XHC_PORTSC2__PEC_R 18U +#define XHC_PORTSC2__PEC_WIDTH 1U +#define XHC_PORTSC2__PEC_RESETVALUE 0x0U +#define XHC_PORTSC2__CSC 17U +#define XHC_PORTSC2__CSC_L 17U +#define XHC_PORTSC2__CSC_R 17U +#define XHC_PORTSC2__CSC_WIDTH 1U +#define XHC_PORTSC2__CSC_RESETVALUE 0x0U +#define XHC_PORTSC2__LWS 16U +#define XHC_PORTSC2__LWS_L 16U +#define XHC_PORTSC2__LWS_R 16U +#define XHC_PORTSC2__LWS_WIDTH 1U +#define XHC_PORTSC2__LWS_RESETVALUE 0x0U +#define XHC_PORTSC2__PIC_L 15U +#define XHC_PORTSC2__PIC_R 14U +#define XHC_PORTSC2__PIC_WIDTH 2U +#define XHC_PORTSC2__PIC_RESETVALUE 0x0U +#define XHC_PORTSC2__PS_L 13U +#define XHC_PORTSC2__PS_R 10U +#define XHC_PORTSC2__PS_WIDTH 4U +#define XHC_PORTSC2__PS_RESETVALUE 0x0U +#define XHC_PORTSC2__PP 9U +#define XHC_PORTSC2__PP_L 9U +#define XHC_PORTSC2__PP_R 9U +#define XHC_PORTSC2__PP_WIDTH 1U +#define XHC_PORTSC2__PP_RESETVALUE 0x0U +#define XHC_PORTSC2__PLS_L 8U +#define XHC_PORTSC2__PLS_R 5U +#define XHC_PORTSC2__PLS_WIDTH 4U +#define XHC_PORTSC2__PLS_RESETVALUE 0x5U + +#define XHC_PORTSC2__PRST_L 4U +#define XHC_PORTSC2__PRST_R 4U +#define XHC_PORTSC2__PRST_WIDTH 1U +#define XHC_PORTSC2__PRST_RESETVALUE 0x0U +#define XHC_PORTSC2__OCA 3U +#define XHC_PORTSC2__OCA_L 3U +#define XHC_PORTSC2__OCA_R 3U +#define XHC_PORTSC2__OCA_WIDTH 1U +#define XHC_PORTSC2__OCA_RESETVALUE 0x0U +#define XHC_PORTSC2__reserved 2U +#define XHC_PORTSC2__reserved_L 2U +#define XHC_PORTSC2__reserved_R 2U +#define XHC_PORTSC2__reserved_WIDTH 1U +#define XHC_PORTSC2__reserved_RESETVALUE 0x0U +#define XHC_PORTSC2__PED 1U +#define XHC_PORTSC2__PED_L 1U +#define XHC_PORTSC2__PED_R 1U +#define XHC_PORTSC2__PED_WIDTH 1U +#define XHC_PORTSC2__PED_RESETVALUE 0x0U +#define XHC_PORTSC2__CCS 0U +#define XHC_PORTSC2__CCS_L 0U +#define XHC_PORTSC2__CCS_R 0U +#define XHC_PORTSC2__CCS_WIDTH 1U +#define XHC_PORTSC2__CCS_RESETVALUE 0x0U +#define XHC_PORTSC2__RESERVED_L 29U +#define XHC_PORTSC2__RESERVED_R 28U +#define XHC_PORTSC2_WIDTH 32U +#define XHC_PORTSC2__WIDTH 32U +#define XHC_PORTSC2_ALL_L 31U +#define XHC_PORTSC2_ALL_R 0U +#define XHC_PORTSC2__ALL_L 31U +#define XHC_PORTSC2__ALL_R 0U +#define XHC_PORTSC2_DATAMASK 0xcfffffffU +#define XHC_PORTSC2_RDWRMASK 0x30000000U +#define XHC_PORTSC2_RESETVALUE 0x000000a0U + +#define XHC_PORTPM2_OFFSET 0x434U +#define XHC_PORTPM2_BASE 0x434U +#define XHC_PORTPM2__PTC_L 31U +#define XHC_PORTPM2__PTC_R 28U +#define XHC_PORTPM2__PTC_WIDTH 4U +#define XHC_PORTPM2__PTC_RESETVALUE 0x0U +#define XHC_PORTPM2__reserved_L 27U +#define XHC_PORTPM2__reserved_R 17U +#define XHC_PORTPM2__reserved_WIDTH 11U +#define XHC_PORTPM2__reserved_RESETVALUE 0x0U +#define XHC_PORTPM2__HLE 16U +#define XHC_PORTPM2__HLE_L 16U +#define XHC_PORTPM2__HLE_R 16U +#define XHC_PORTPM2__HLE_WIDTH 1U +#define XHC_PORTPM2__HLE_RESETVALUE 0x0U +#define XHC_PORTPM2__L1DS_L 15U +#define XHC_PORTPM2__L1DS_R 8U +#define XHC_PORTPM2__L1DS_WIDTH 8U +#define XHC_PORTPM2__L1DS_RESETVALUE 0x00U +#define XHC_PORTPM2__BESL_L 7U +#define XHC_PORTPM2__BESL_R 4U +#define XHC_PORTPM2__BESL_WIDTH 4U +#define XHC_PORTPM2__BESL_RESETVALUE 0x0U +#define XHC_PORTPM2__RWE 3U +#define XHC_PORTPM2__RWE_L 3U +#define XHC_PORTPM2__RWE_R 3U +#define XHC_PORTPM2__RWE_WIDTH 1U +#define XHC_PORTPM2__RWE_RESETVALUE 0x0U +#define XHC_PORTPM2__L1S_L 2U +#define XHC_PORTPM2__L1S_R 0U +#define XHC_PORTPM2__L1S_WIDTH 3U +#define XHC_PORTPM2__L1S_RESETVALUE 0x0U +#define XHC_PORTPM2_WIDTH 32U +#define XHC_PORTPM2__WIDTH 32U +#define XHC_PORTPM2_ALL_L 31U +#define XHC_PORTPM2_ALL_R 0U +#define XHC_PORTPM2__ALL_L 31U +#define XHC_PORTPM2__ALL_R 0U +#define XHC_PORTPM2_DATAMASK 0xffffffffU +#define XHC_PORTPM2_RDWRMASK 0x00000000U +#define XHC_PORTPM2_RESETVALUE 0x00000000U + +#define XHC_PORTLC2_OFFSET 0x43cU +#define XHC_PORTLC2_BASE 0x43cU +#define XHC_PORTLC2__reserved_L 31U +#define XHC_PORTLC2__reserved_R 14U +#define XHC_PORTLC2__reserved_WIDTH 18U +#define XHC_PORTLC2__reserved_RESETVALUE 0x0U +#define XHC_PORTLC2__BESLD_L 13U +#define XHC_PORTLC2__BESLD_R 10U +#define XHC_PORTLC2__BESLD_WIDTH 4U +#define XHC_PORTLC2__BESLD_RESETVALUE 0x0U +#define XHC_PORTLC2__L1T_L 9U +#define XHC_PORTLC2__L1T_R 2U +#define XHC_PORTLC2__L1T_WIDTH 8U +#define XHC_PORTLC2__L1T_RESETVALUE 0x00U +#define XHC_PORTLC2__HIRDM_L 1U +#define XHC_PORTLC2__HIRDM_R 0U +#define XHC_PORTLC2__HIRDM_WIDTH 2U +#define XHC_PORTLC2__HIRDM_RESETVALUE 0x0U +#define XHC_PORTLC2_WIDTH 32U +#define XHC_PORTLC2__WIDTH 32U +#define XHC_PORTLC2_ALL_L 31U +#define XHC_PORTLC2_ALL_R 0U +#define XHC_PORTLC2__ALL_L 31U +#define XHC_PORTLC2__ALL_R 0U +#define XHC_PORTLC2_DATAMASK 0xffffffffU +#define XHC_PORTLC2_RDWRMASK 0x00000000U +#define XHC_PORTLC2_RESETVALUE 0x00000000U + +#define XHC_PORTSC3_OFFSET 0x440U +#define XHC_PORTSC3_BASE 0x440U +#define XHC_PORTSC3__WPR 31U +#define XHC_PORTSC3__WPR_L 31U +#define XHC_PORTSC3__WPR_R 31U +#define XHC_PORTSC3__WPR_WIDTH 1U +#define XHC_PORTSC3__WPR_RESETVALUE 0x0U +#define XHC_PORTSC3__DNR 30U +#define XHC_PORTSC3__DNR_L 30U +#define XHC_PORTSC3__DNR_R 30U +#define XHC_PORTSC3__DNR_WIDTH 1U +#define XHC_PORTSC3__DNR_RESETVALUE 0x0U +#define XHC_PORTSC3__WOE 27U +#define XHC_PORTSC3__WOE_L 27U +#define XHC_PORTSC3__WOE_R 27U +#define XHC_PORTSC3__WOE_WIDTH 1U +#define XHC_PORTSC3__WOE_RESETVALUE 0x0U +#define XHC_PORTSC3__WDE 26U +#define XHC_PORTSC3__WDE_L 26U +#define XHC_PORTSC3__WDE_R 26U +#define XHC_PORTSC3__WDE_WIDTH 1U +#define XHC_PORTSC3__WDE_RESETVALUE 0x0U +#define XHC_PORTSC3__WCE 25U +#define XHC_PORTSC3__WCE_L 25U +#define XHC_PORTSC3__WCE_R 25U +#define XHC_PORTSC3__WCE_WIDTH 1U +#define XHC_PORTSC3__WCE_RESETVALUE 0x0U +#define XHC_PORTSC3__CAS 24U +#define XHC_PORTSC3__CAS_L 24U +#define XHC_PORTSC3__CAS_R 24U +#define XHC_PORTSC3__CAS_WIDTH 1U +#define XHC_PORTSC3__CAS_RESETVALUE 0x0U +#define XHC_PORTSC3__CEC 23U +#define XHC_PORTSC3__CEC_L 23U +#define XHC_PORTSC3__CEC_R 23U +#define XHC_PORTSC3__CEC_WIDTH 1U +#define XHC_PORTSC3__CEC_RESETVALUE 0x0U +#define XHC_PORTSC3__PLC 22U +#define XHC_PORTSC3__PLC_L 22U +#define XHC_PORTSC3__PLC_R 22U +#define XHC_PORTSC3__PLC_WIDTH 1U +#define XHC_PORTSC3__PLC_RESETVALUE 0x0U +#define XHC_PORTSC3__PRC 21U +#define XHC_PORTSC3__PRC_L 21U +#define XHC_PORTSC3__PRC_R 21U +#define XHC_PORTSC3__PRC_WIDTH 1U +#define XHC_PORTSC3__PRC_RESETVALUE 0x0U +#define XHC_PORTSC3__OCC 20U +#define XHC_PORTSC3__OCC_L 20U +#define XHC_PORTSC3__OCC_R 20U +#define XHC_PORTSC3__OCC_WIDTH 1U +#define XHC_PORTSC3__OCC_RESETVALUE 0x0U +#define XHC_PORTSC3__WRC 19U +#define XHC_PORTSC3__WRC_L 19U +#define XHC_PORTSC3__WRC_R 19U +#define XHC_PORTSC3__WRC_WIDTH 1U +#define XHC_PORTSC3__WRC_RESETVALUE 0x0U +#define XHC_PORTSC3__PEC 18U +#define XHC_PORTSC3__PEC_L 18U +#define XHC_PORTSC3__PEC_R 18U +#define XHC_PORTSC3__PEC_WIDTH 1U +#define XHC_PORTSC3__PEC_RESETVALUE 0x0U +#define XHC_PORTSC3__CSC 17U +#define XHC_PORTSC3__CSC_L 17U +#define XHC_PORTSC3__CSC_R 17U +#define XHC_PORTSC3__CSC_WIDTH 1U +#define XHC_PORTSC3__CSC_RESETVALUE 0x0U +#define XHC_PORTSC3__LWS 16U +#define XHC_PORTSC3__LWS_L 16U +#define XHC_PORTSC3__LWS_R 16U +#define XHC_PORTSC3__LWS_WIDTH 1U +#define XHC_PORTSC3__LWS_RESETVALUE 0x0U +#define XHC_PORTSC3__PIC_L 15U +#define XHC_PORTSC3__PIC_R 14U +#define XHC_PORTSC3__PIC_WIDTH 2U +#define XHC_PORTSC3__PIC_RESETVALUE 0x0U +#define XHC_PORTSC3__PS_L 13U +#define XHC_PORTSC3__PS_R 10U +#define XHC_PORTSC3__PS_WIDTH 4U +#define XHC_PORTSC3__PS_RESETVALUE 0x0U +#define XHC_PORTSC3__PP 9U +#define XHC_PORTSC3__PP_L 9U +#define XHC_PORTSC3__PP_R 9U +#define XHC_PORTSC3__PP_WIDTH 1U +#define XHC_PORTSC3__PP_RESETVALUE 0x0U +#define XHC_PORTSC3__PLS_L 8U +#define XHC_PORTSC3__PLS_R 5U +#define XHC_PORTSC3__PLS_WIDTH 4U +#define XHC_PORTSC3__PLS_RESETVALUE 0x5U +#define XHC_PORTSC3__PR 4U +#define XHC_PORTSC3__PR_L 4U +#define XHC_PORTSC3__PR_R 4U +#define XHC_PORTSC3__PR_WIDTH 1U +#define XHC_PORTSC3__PR_RESETVALUE 0x0U +#define XHC_PORTSC3__OCA 3U +#define XHC_PORTSC3__OCA_L 3U +#define XHC_PORTSC3__OCA_R 3U +#define XHC_PORTSC3__OCA_WIDTH 1U +#define XHC_PORTSC3__OCA_RESETVALUE 0x0U +#define XHC_PORTSC3__reserved 2U +#define XHC_PORTSC3__reserved_L 2U +#define XHC_PORTSC3__reserved_R 2U +#define XHC_PORTSC3__reserved_WIDTH 1U +#define XHC_PORTSC3__reserved_RESETVALUE 0x0U +#define XHC_PORTSC3__PED 1U +#define XHC_PORTSC3__PED_L 1U +#define XHC_PORTSC3__PED_R 1U +#define XHC_PORTSC3__PED_WIDTH 1U +#define XHC_PORTSC3__PED_RESETVALUE 0x0U +#define XHC_PORTSC3__CCS 0U +#define XHC_PORTSC3__CCS_L 0U +#define XHC_PORTSC3__CCS_R 0U +#define XHC_PORTSC3__CCS_WIDTH 1U +#define XHC_PORTSC3__CCS_RESETVALUE 0x0U +#define XHC_PORTSC3__RESERVED_L 29U +#define XHC_PORTSC3__RESERVED_R 28U +#define XHC_PORTSC3_WIDTH 32U +#define XHC_PORTSC3__WIDTH 32U +#define XHC_PORTSC3_ALL_L 31U +#define XHC_PORTSC3_ALL_R 0U +#define XHC_PORTSC3__ALL_L 31U +#define XHC_PORTSC3__ALL_R 0U +#define XHC_PORTSC3_DATAMASK 0xcfffffffU +#define XHC_PORTSC3_RDWRMASK 0x30000000U +#define XHC_PORTSC3_RESETVALUE 0x000000a0U + +#define XHC_PORTPM3_OFFSET 0x444U +#define XHC_PORTPM3_BASE 0x444U +#define XHC_PORTPM3__PTC_L 31U +#define XHC_PORTPM3__PTC_R 28U +#define XHC_PORTPM3__PTC_WIDTH 4U +#define XHC_PORTPM3__PTC_RESETVALUE 0x0U +#define XHC_PORTPM3__reserved_L 27U +#define XHC_PORTPM3__reserved_R 17U +#define XHC_PORTPM3__reserved_WIDTH 11U +#define XHC_PORTPM3__reserved_RESETVALUE 0x0U +#define XHC_PORTPM3__HLE 16U +#define XHC_PORTPM3__HLE_L 16U +#define XHC_PORTPM3__HLE_R 16U +#define XHC_PORTPM3__HLE_WIDTH 1U +#define XHC_PORTPM3__HLE_RESETVALUE 0x0U +#define XHC_PORTPM3__L1DS_L 15U +#define XHC_PORTPM3__L1DS_R 8U +#define XHC_PORTPM3__L1DS_WIDTH 8U +#define XHC_PORTPM3__L1DS_RESETVALUE 0x00U +#define XHC_PORTPM3__BESL_L 7U +#define XHC_PORTPM3__BESL_R 4U +#define XHC_PORTPM3__BESL_WIDTH 4U +#define XHC_PORTPM3__BESL_RESETVALUE 0x0U +#define XHC_PORTPM3__RWE 3U +#define XHC_PORTPM3__RWE_L 3U +#define XHC_PORTPM3__RWE_R 3U +#define XHC_PORTPM3__RWE_WIDTH 1U +#define XHC_PORTPM3__RWE_RESETVALUE 0x0U +#define XHC_PORTPM3__L1S_L 2U +#define XHC_PORTPM3__L1S_R 0U +#define XHC_PORTPM3__L1S_WIDTH 3U +#define XHC_PORTPM3__L1S_RESETVALUE 0x0U +#define XHC_PORTPM3_WIDTH 32U +#define XHC_PORTPM3__WIDTH 32U +#define XHC_PORTPM3_ALL_L 31U +#define XHC_PORTPM3_ALL_R 0U +#define XHC_PORTPM3__ALL_L 31U +#define XHC_PORTPM3__ALL_R 0U +#define XHC_PORTPM3_DATAMASK 0xffffffffU +#define XHC_PORTPM3_RDWRMASK 0x00000000U +#define XHC_PORTPM3_RESETVALUE 0x00000000U + +#define XHC_PORTLI3_OFFSET 0x44cU +#define XHC_PORTLI3_BASE 0x44cU +#define XHC_PORTLI3__reserved_L 31U +#define XHC_PORTLI3__reserved_R 0U +#define XHC_PORTLI3__reserved_WIDTH 32U +#define XHC_PORTLI3__reserved_RESETVALUE 0x00000000U +#define XHC_PORTLI3_WIDTH 32U +#define XHC_PORTLI3__WIDTH 32U +#define XHC_PORTLI3_ALL_L 31U +#define XHC_PORTLI3_ALL_R 0U +#define XHC_PORTLI3__ALL_L 31U +#define XHC_PORTLI3__ALL_R 0U +#define XHC_PORTLI3_DATAMASK 0xffffffffU +#define XHC_PORTLI3_RDWRMASK 0x00000000U +#define XHC_PORTLI3_RESETVALUE 0x00000000U + +#define XHC_MFINDEX_OFFSET 0x4a0U +#define XHC_MFINDEX_BASE 0x4a0U +#define XHC_MFINDEX__reserved_L 31U +#define XHC_MFINDEX__reserved_R 14U +#define XHC_MFINDEX__reserved_WIDTH 18U +#define XHC_MFINDEX__reserved_RESETVALUE 0x0U +#define XHC_MFINDEX__MFI_L 13U +#define XHC_MFINDEX__MFI_R 0U +#define XHC_MFINDEX__MFI_WIDTH 14U +#define XHC_MFINDEX__MFI_RESETVALUE 0x0U +#define XHC_MFINDEX_WIDTH 32U +#define XHC_MFINDEX__WIDTH 32U +#define XHC_MFINDEX_ALL_L 31U +#define XHC_MFINDEX_ALL_R 0U +#define XHC_MFINDEX__ALL_L 31U +#define XHC_MFINDEX__ALL_R 0U +#define XHC_MFINDEX_DATAMASK 0xffffffffU +#define XHC_MFINDEX_RDWRMASK 0x00000000U +#define XHC_MFINDEX_RESETVALUE 0x00000000U + +#define XHC_IMAN0_OFFSET 0x4c0U +#define XHC_IMAN0_BASE 0x4c0U +#define XHC_IMAN0__reserved_L 31U +#define XHC_IMAN0__reserved_R 2U +#define XHC_IMAN0__reserved_WIDTH 30U +#define XHC_IMAN0__reserved_RESETVALUE 0x0U +#define XHC_IMAN0__IE 1U +#define XHC_IMAN0__IE_L 1U +#define XHC_IMAN0__IE_R 1U +#define XHC_IMAN0__IE_WIDTH 1U +#define XHC_IMAN0__IE_RESETVALUE 0x0U +#define XHC_IMAN0__IP 0U +#define XHC_IMAN0__IP_L 0U +#define XHC_IMAN0__IP_R 0U +#define XHC_IMAN0__IP_WIDTH 1U +#define XHC_IMAN0__IP_RESETVALUE 0x0U +#define XHC_IMAN0_WIDTH 32U +#define XHC_IMAN0__WIDTH 32U +#define XHC_IMAN0_ALL_L 31U +#define XHC_IMAN0_ALL_R 0U +#define XHC_IMAN0__ALL_L 31U +#define XHC_IMAN0__ALL_R 0U +#define XHC_IMAN0_DATAMASK 0xffffffffU +#define XHC_IMAN0_RDWRMASK 0x00000000U +#define XHC_IMAN0_RESETVALUE 0x00000000U + +#define XHC_IMOD0_OFFSET 0x4c4U +#define XHC_IMOD0_BASE 0x4c4U +#define XHC_IMOD0__IMODC_L 31U +#define XHC_IMOD0__IMODC_R 16U +#define XHC_IMOD0__IMODC_WIDTH 16U +#define XHC_IMOD0__IMODC_RESETVALUE 0x0000U +#define XHC_IMOD0__IMODI_L 15U +#define XHC_IMOD0__IMODI_R 0U +#define XHC_IMOD0__IMODI_WIDTH 16U +#define XHC_IMOD0__IMODI_RESETVALUE 0x4000U +#define XHC_IMOD0_WIDTH 32U +#define XHC_IMOD0__WIDTH 32U +#define XHC_IMOD0_ALL_L 31U +#define XHC_IMOD0_ALL_R 0U +#define XHC_IMOD0__ALL_L 31U +#define XHC_IMOD0__ALL_R 0U +#define XHC_IMOD0_DATAMASK 0xffffffffU +#define XHC_IMOD0_RDWRMASK 0x00000000U +#define XHC_IMOD0_RESETVALUE 0x00004000U + +#define XHC_ERSTSZ0_OFFSET 0x4c8U +#define XHC_ERSTSZ0_BASE 0x4c8U +#define XHC_ERSTSZ0__reserved_L 31U +#define XHC_ERSTSZ0__reserved_R 16U +#define XHC_ERSTSZ0__reserved_WIDTH 16U +#define XHC_ERSTSZ0__reserved_RESETVALUE 0x0000U +#define XHC_ERSTSZ0__TSZ_L 15U +#define XHC_ERSTSZ0__TSZ_R 0U +#define XHC_ERSTSZ0__TSZ_WIDTH 16U +#define XHC_ERSTSZ0__TSZ_RESETVALUE 0x0000U +#define XHC_ERSTSZ0_WIDTH 32U +#define XHC_ERSTSZ0__WIDTH 32U +#define XHC_ERSTSZ0_ALL_L 31U +#define XHC_ERSTSZ0_ALL_R 0U +#define XHC_ERSTSZ0__ALL_L 31U +#define XHC_ERSTSZ0__ALL_R 0U +#define XHC_ERSTSZ0_DATAMASK 0xffffffffU +#define XHC_ERSTSZ0_RDWRMASK 0x00000000U +#define XHC_ERSTSZ0_RESETVALUE 0x00000000U + +#define XHC_ERSTBAL0_OFFSET 0x4d0U +#define XHC_ERSTBAL0_BASE 0x4d0U +#define XHC_ERSTBAL0__BAL_L 31U +#define XHC_ERSTBAL0__BAL_R 4U +#define XHC_ERSTBAL0__BAL_WIDTH 28U +#define XHC_ERSTBAL0__BAL_RESETVALUE 0x0000000U +#define XHC_ERSTBAL0__reserved_L 3U +#define XHC_ERSTBAL0__reserved_R 0U +#define XHC_ERSTBAL0__reserved_WIDTH 4U +#define XHC_ERSTBAL0__reserved_RESETVALUE 0x0U +#define XHC_ERSTBAL0_WIDTH 32U +#define XHC_ERSTBAL0__WIDTH 32U +#define XHC_ERSTBAL0_ALL_L 31U +#define XHC_ERSTBAL0_ALL_R 0U +#define XHC_ERSTBAL0__ALL_L 31U +#define XHC_ERSTBAL0__ALL_R 0U +#define XHC_ERSTBAL0_DATAMASK 0xffffffffU +#define XHC_ERSTBAL0_RDWRMASK 0x00000000U +#define XHC_ERSTBAL0_RESETVALUE 0x00000000U + +#define XHC_ERSTBAH0_OFFSET 0x4d4U +#define XHC_ERSTBAH0_BASE 0x4d4U +#define XHC_ERSTBAH0__BAH_L 31U +#define XHC_ERSTBAH0__BAH_R 0U +#define XHC_ERSTBAH0__BAH_WIDTH 32U +#define XHC_ERSTBAH0__BAH_RESETVALUE 0x00000000U +#define XHC_ERSTBAH0_WIDTH 32U +#define XHC_ERSTBAH0__WIDTH 32U +#define XHC_ERSTBAH0_ALL_L 31U +#define XHC_ERSTBAH0_ALL_R 0U +#define XHC_ERSTBAH0__ALL_L 31U +#define XHC_ERSTBAH0__ALL_R 0U +#define XHC_ERSTBAH0_DATAMASK 0xffffffffU +#define XHC_ERSTBAH0_RDWRMASK 0x00000000U +#define XHC_ERSTBAH0_RESETVALUE 0x00000000U + +#define XHC_ERDPL0_OFFSET 0x4d8U +#define XHC_ERDPL0_BASE 0x4d8U +#define XHC_ERDPL0__DPL_L 31U +#define XHC_ERDPL0__DPL_R 4U +#define XHC_ERDPL0__DPL_WIDTH 28U +#define XHC_ERDPL0__DPL_RESETVALUE 0x0000000U +#define XHC_ERDPL0__EHB 3U +#define XHC_ERDPL0__EHB_L 3U +#define XHC_ERDPL0__EHB_R 3U +#define XHC_ERDPL0__EHB_WIDTH 1U +#define XHC_ERDPL0__EHB_RESETVALUE 0x0U +#define XHC_ERDPL0__DESI_L 2U +#define XHC_ERDPL0__DESI_R 0U +#define XHC_ERDPL0__DESI_WIDTH 3U +#define XHC_ERDPL0__DESI_RESETVALUE 0x0U +#define XHC_ERDPL0_WIDTH 32U +#define XHC_ERDPL0__WIDTH 32U +#define XHC_ERDPL0_ALL_L 31U +#define XHC_ERDPL0_ALL_R 0U +#define XHC_ERDPL0__ALL_L 31U +#define XHC_ERDPL0__ALL_R 0U +#define XHC_ERDPL0_DATAMASK 0xffffffffU +#define XHC_ERDPL0_RDWRMASK 0x00000000U +#define XHC_ERDPL0_RESETVALUE 0x00000000U + +#define XHC_ERDPH0_OFFSET 0x4dcU +#define XHC_ERDPH0_BASE 0x4dcU +#define XHC_ERDPH0__DPH_L 31U +#define XHC_ERDPH0__DPH_R 0U +#define XHC_ERDPH0__DPH_WIDTH 32U +#define XHC_ERDPH0__DPH_RESETVALUE 0x00000000U +#define XHC_ERDPH0_WIDTH 32U +#define XHC_ERDPH0__WIDTH 32U +#define XHC_ERDPH0_ALL_L 31U +#define XHC_ERDPH0_ALL_R 0U +#define XHC_ERDPH0__ALL_L 31U +#define XHC_ERDPH0__ALL_R 0U +#define XHC_ERDPH0_DATAMASK 0xffffffffU +#define XHC_ERDPH0_RDWRMASK 0x00000000U +#define XHC_ERDPH0_RESETVALUE 0x00000000U + +#define XHC_IMAN1_OFFSET 0x4e0U +#define XHC_IMAN1_BASE 0x4e0U +#define XHC_IMAN1__reserved_L 31U +#define XHC_IMAN1__reserved_R 2U +#define XHC_IMAN1__reserved_WIDTH 30U +#define XHC_IMAN1__reserved_RESETVALUE 0x0U +#define XHC_IMAN1__IE 1U +#define XHC_IMAN1__IE_L 1U +#define XHC_IMAN1__IE_R 1U +#define XHC_IMAN1__IE_WIDTH 1U +#define XHC_IMAN1__IE_RESETVALUE 0x0U +#define XHC_IMAN1__IP 0U +#define XHC_IMAN1__IP_L 0U +#define XHC_IMAN1__IP_R 0U +#define XHC_IMAN1__IP_WIDTH 1U +#define XHC_IMAN1__IP_RESETVALUE 0x0U +#define XHC_IMAN1_WIDTH 32U +#define XHC_IMAN1__WIDTH 32U +#define XHC_IMAN1_ALL_L 31U +#define XHC_IMAN1_ALL_R 0U +#define XHC_IMAN1__ALL_L 31U +#define XHC_IMAN1__ALL_R 0U +#define XHC_IMAN1_DATAMASK 0xffffffffU +#define XHC_IMAN1_RDWRMASK 0x00000000U +#define XHC_IMAN1_RESETVALUE 0x00000000U + +#define XHC_IMOD1_OFFSET 0x4e4U +#define XHC_IMOD1_BASE 0x4e4U +#define XHC_IMOD1__IMODC_L 31U +#define XHC_IMOD1__IMODC_R 16U +#define XHC_IMOD1__IMODC_WIDTH 16U +#define XHC_IMOD1__IMODC_RESETVALUE 0x0000U +#define XHC_IMOD1__IMODI_L 15U +#define XHC_IMOD1__IMODI_R 0U +#define XHC_IMOD1__IMODI_WIDTH 16U +#define XHC_IMOD1__IMODI_RESETVALUE 0x4000U +#define XHC_IMOD1_WIDTH 32U +#define XHC_IMOD1__WIDTH 32U +#define XHC_IMOD1_ALL_L 31U +#define XHC_IMOD1_ALL_R 0U +#define XHC_IMOD1__ALL_L 31U +#define XHC_IMOD1__ALL_R 0U +#define XHC_IMOD1_DATAMASK 0xffffffffU +#define XHC_IMOD1_RDWRMASK 0x00000000U +#define XHC_IMOD1_RESETVALUE 0x00004000U + +#define XHC_ERSTSZ1_OFFSET 0x4e8U +#define XHC_ERSTSZ1_BASE 0x4e8U +#define XHC_ERSTSZ1__reserved_L 31U +#define XHC_ERSTSZ1__reserved_R 16U +#define XHC_ERSTSZ1__reserved_WIDTH 16U +#define XHC_ERSTSZ1__reserved_RESETVALUE 0x0000U +#define XHC_ERSTSZ1__TSZ_L 15U +#define XHC_ERSTSZ1__TSZ_R 0U +#define XHC_ERSTSZ1__TSZ_WIDTH 16U +#define XHC_ERSTSZ1__TSZ_RESETVALUE 0x0000U +#define XHC_ERSTSZ1_WIDTH 32U +#define XHC_ERSTSZ1__WIDTH 32U +#define XHC_ERSTSZ1_ALL_L 31U +#define XHC_ERSTSZ1_ALL_R 0U +#define XHC_ERSTSZ1__ALL_L 31U +#define XHC_ERSTSZ1__ALL_R 0U +#define XHC_ERSTSZ1_DATAMASK 0xffffffffU +#define XHC_ERSTSZ1_RDWRMASK 0x00000000U +#define XHC_ERSTSZ1_RESETVALUE 0x00000000U + +#define XHC_ERSTBAL1_OFFSET 0x4f0U +#define XHC_ERSTBAL1_BASE 0x4f0U +#define XHC_ERSTBAL1__BAL_L 31U +#define XHC_ERSTBAL1__BAL_R 4U +#define XHC_ERSTBAL1__BAL_WIDTH 28U +#define XHC_ERSTBAL1__BAL_RESETVALUE 0x0000000U +#define XHC_ERSTBAL1__reserved_L 3U +#define XHC_ERSTBAL1__reserved_R 0U +#define XHC_ERSTBAL1__reserved_WIDTH 4U +#define XHC_ERSTBAL1__reserved_RESETVALUE 0x0U +#define XHC_ERSTBAL1_WIDTH 32U +#define XHC_ERSTBAL1__WIDTH 32U +#define XHC_ERSTBAL1_ALL_L 31U +#define XHC_ERSTBAL1_ALL_R 0U +#define XHC_ERSTBAL1__ALL_L 31U +#define XHC_ERSTBAL1__ALL_R 0U +#define XHC_ERSTBAL1_DATAMASK 0xffffffffU +#define XHC_ERSTBAL1_RDWRMASK 0x00000000U +#define XHC_ERSTBAL1_RESETVALUE 0x00000000U + +#define XHC_ERSTBAH1_OFFSET 0x4f4U +#define XHC_ERSTBAH1_BASE 0x4f4U +#define XHC_ERSTBAH1__BAH_L 31U +#define XHC_ERSTBAH1__BAH_R 0U +#define XHC_ERSTBAH1__BAH_WIDTH 32U +#define XHC_ERSTBAH1__BAH_RESETVALUE 0x00000000U +#define XHC_ERSTBAH1_WIDTH 32U +#define XHC_ERSTBAH1__WIDTH 32U +#define XHC_ERSTBAH1_ALL_L 31U +#define XHC_ERSTBAH1_ALL_R 0U +#define XHC_ERSTBAH1__ALL_L 31U +#define XHC_ERSTBAH1__ALL_R 0U +#define XHC_ERSTBAH1_DATAMASK 0xffffffffU +#define XHC_ERSTBAH1_RDWRMASK 0x00000000U +#define XHC_ERSTBAH1_RESETVALUE 0x00000000U + +#define XHC_ERDPL1_OFFSET 0x4f8U +#define XHC_ERDPL1_BASE 0x4f8U +#define XHC_ERDPL1__DPL_L 31U +#define XHC_ERDPL1__DPL_R 4U +#define XHC_ERDPL1__DPL_WIDTH 28U +#define XHC_ERDPL1__DPL_RESETVALUE 0x0000000U +#define XHC_ERDPL1__EHB 3U +#define XHC_ERDPL1__EHB_L 3U +#define XHC_ERDPL1__EHB_R 3U +#define XHC_ERDPL1__EHB_WIDTH 1U +#define XHC_ERDPL1__EHB_RESETVALUE 0x0U +#define XHC_ERDPL1__DESI_L 2U +#define XHC_ERDPL1__DESI_R 0U +#define XHC_ERDPL1__DESI_WIDTH 3U +#define XHC_ERDPL1__DESI_RESETVALUE 0x0U +#define XHC_ERDPL1_WIDTH 32U +#define XHC_ERDPL1__WIDTH 32U +#define XHC_ERDPL1_ALL_L 31U +#define XHC_ERDPL1_ALL_R 0U +#define XHC_ERDPL1__ALL_L 31U +#define XHC_ERDPL1__ALL_R 0U +#define XHC_ERDPL1_DATAMASK 0xffffffffU +#define XHC_ERDPL1_RDWRMASK 0x00000000U +#define XHC_ERDPL1_RESETVALUE 0x00000000U + +#define XHC_ERDPH1_OFFSET 0x4fcU +#define XHC_ERDPH1_BASE 0x4fcU +#define XHC_ERDPH1__DPH_L 31U +#define XHC_ERDPH1__DPH_R 0U +#define XHC_ERDPH1__DPH_WIDTH 32U +#define XHC_ERDPH1__DPH_RESETVALUE 0x00000000U +#define XHC_ERDPH1_WIDTH 32U +#define XHC_ERDPH1__WIDTH 32U +#define XHC_ERDPH1_ALL_L 31U +#define XHC_ERDPH1_ALL_R 0U +#define XHC_ERDPH1__ALL_L 31U +#define XHC_ERDPH1__ALL_R 0U +#define XHC_ERDPH1_DATAMASK 0xffffffffU +#define XHC_ERDPH1_RDWRMASK 0x00000000U +#define XHC_ERDPH1_RESETVALUE 0x00000000U + +#define XHC_DBLCMD_OFFSET 0x8c0U +#define XHC_DBLCMD_BASE 0x8c0U +#define XHC_DBLCMD__SID_L 31U +#define XHC_DBLCMD__SID_R 16U +#define XHC_DBLCMD__SID_WIDTH 16U +#define XHC_DBLCMD__SID_RESETVALUE 0x0000U +#define XHC_DBLCMD__reserved_L 15U +#define XHC_DBLCMD__reserved_R 8U +#define XHC_DBLCMD__reserved_WIDTH 8U +#define XHC_DBLCMD__reserved_RESETVALUE 0x00U +#define XHC_DBLCMD__TGT_L 7U +#define XHC_DBLCMD__TGT_R 0U +#define XHC_DBLCMD__TGT_WIDTH 8U +#define XHC_DBLCMD__TGT_RESETVALUE 0x00U +#define XHC_DBLCMD_WIDTH 32U +#define XHC_DBLCMD__WIDTH 32U +#define XHC_DBLCMD_ALL_L 31U +#define XHC_DBLCMD_ALL_R 0U +#define XHC_DBLCMD__ALL_L 31U +#define XHC_DBLCMD__ALL_R 0U +#define XHC_DBLCMD_DATAMASK 0xffffffffU +#define XHC_DBLCMD_RDWRMASK 0x00000000U +#define XHC_DBLCMD_RESETVALUE 0x00000000U + +#define XHC_DBLDVX1_OFFSET 0x8c4U +#define XHC_DBLDVX1_BASE 0x8c4U +#define XHC_DBLDVX1__SID_L 31U +#define XHC_DBLDVX1__SID_R 16U +#define XHC_DBLDVX1__SID_WIDTH 16U +#define XHC_DBLDVX1__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX1__reserved_L 15U +#define XHC_DBLDVX1__reserved_R 8U +#define XHC_DBLDVX1__reserved_WIDTH 8U +#define XHC_DBLDVX1__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX1__TGT_L 7U +#define XHC_DBLDVX1__TGT_R 0U +#define XHC_DBLDVX1__TGT_WIDTH 8U +#define XHC_DBLDVX1__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX1_WIDTH 32U +#define XHC_DBLDVX1__WIDTH 32U +#define XHC_DBLDVX1_ALL_L 31U +#define XHC_DBLDVX1_ALL_R 0U +#define XHC_DBLDVX1__ALL_L 31U +#define XHC_DBLDVX1__ALL_R 0U +#define XHC_DBLDVX1_DATAMASK 0xffffffffU +#define XHC_DBLDVX1_RDWRMASK 0x00000000U +#define XHC_DBLDVX1_RESETVALUE 0x00000000U + +#define XHC_DBLDVX2_OFFSET 0x8c8U +#define XHC_DBLDVX2_BASE 0x8c8U +#define XHC_DBLDVX2__SID_L 31U +#define XHC_DBLDVX2__SID_R 16U +#define XHC_DBLDVX2__SID_WIDTH 16U +#define XHC_DBLDVX2__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX2__reserved_L 15U +#define XHC_DBLDVX2__reserved_R 8U +#define XHC_DBLDVX2__reserved_WIDTH 8U +#define XHC_DBLDVX2__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX2__TGT_L 7U +#define XHC_DBLDVX2__TGT_R 0U +#define XHC_DBLDVX2__TGT_WIDTH 8U +#define XHC_DBLDVX2__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX2_WIDTH 32U +#define XHC_DBLDVX2__WIDTH 32U +#define XHC_DBLDVX2_ALL_L 31U +#define XHC_DBLDVX2_ALL_R 0U +#define XHC_DBLDVX2__ALL_L 31U +#define XHC_DBLDVX2__ALL_R 0U +#define XHC_DBLDVX2_DATAMASK 0xffffffffU +#define XHC_DBLDVX2_RDWRMASK 0x00000000U +#define XHC_DBLDVX2_RESETVALUE 0x00000000U + +#define XHC_DBLDVX3_OFFSET 0x8ccU +#define XHC_DBLDVX3_BASE 0x8ccU +#define XHC_DBLDVX3__SID_L 31U +#define XHC_DBLDVX3__SID_R 16U +#define XHC_DBLDVX3__SID_WIDTH 16U +#define XHC_DBLDVX3__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX3__reserved_L 15U +#define XHC_DBLDVX3__reserved_R 8U +#define XHC_DBLDVX3__reserved_WIDTH 8U +#define XHC_DBLDVX3__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX3__TGT_L 7U +#define XHC_DBLDVX3__TGT_R 0U +#define XHC_DBLDVX3__TGT_WIDTH 8U +#define XHC_DBLDVX3__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX3_WIDTH 32U +#define XHC_DBLDVX3__WIDTH 32U +#define XHC_DBLDVX3_ALL_L 31U +#define XHC_DBLDVX3_ALL_R 0U +#define XHC_DBLDVX3__ALL_L 31U +#define XHC_DBLDVX3__ALL_R 0U +#define XHC_DBLDVX3_DATAMASK 0xffffffffU +#define XHC_DBLDVX3_RDWRMASK 0x00000000U +#define XHC_DBLDVX3_RESETVALUE 0x00000000U + +#define XHC_DBLDVX4_OFFSET 0x8d0U +#define XHC_DBLDVX4_BASE 0x8d0U +#define XHC_DBLDVX4__SID_L 31U +#define XHC_DBLDVX4__SID_R 16U +#define XHC_DBLDVX4__SID_WIDTH 16U +#define XHC_DBLDVX4__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX4__reserved_L 15U +#define XHC_DBLDVX4__reserved_R 8U +#define XHC_DBLDVX4__reserved_WIDTH 8U +#define XHC_DBLDVX4__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX4__TGT_L 7U +#define XHC_DBLDVX4__TGT_R 0U +#define XHC_DBLDVX4__TGT_WIDTH 8U +#define XHC_DBLDVX4__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX4_WIDTH 32U +#define XHC_DBLDVX4__WIDTH 32U +#define XHC_DBLDVX4_ALL_L 31U +#define XHC_DBLDVX4_ALL_R 0U +#define XHC_DBLDVX4__ALL_L 31U +#define XHC_DBLDVX4__ALL_R 0U +#define XHC_DBLDVX4_DATAMASK 0xffffffffU +#define XHC_DBLDVX4_RDWRMASK 0x00000000U +#define XHC_DBLDVX4_RESETVALUE 0x00000000U + +#define XHC_DBLDVX5_OFFSET 0x8d4U +#define XHC_DBLDVX5_BASE 0x8d4U +#define XHC_DBLDVX5__SID_L 31U +#define XHC_DBLDVX5__SID_R 16U +#define XHC_DBLDVX5__SID_WIDTH 16U +#define XHC_DBLDVX5__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX5__reserved_L 15U +#define XHC_DBLDVX5__reserved_R 8U +#define XHC_DBLDVX5__reserved_WIDTH 8U +#define XHC_DBLDVX5__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX5__TGT_L 7U +#define XHC_DBLDVX5__TGT_R 0U +#define XHC_DBLDVX5__TGT_WIDTH 8U +#define XHC_DBLDVX5__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX5_WIDTH 32U +#define XHC_DBLDVX5__WIDTH 32U +#define XHC_DBLDVX5_ALL_L 31U +#define XHC_DBLDVX5_ALL_R 0U +#define XHC_DBLDVX5__ALL_L 31U +#define XHC_DBLDVX5__ALL_R 0U +#define XHC_DBLDVX5_DATAMASK 0xffffffffU +#define XHC_DBLDVX5_RDWRMASK 0x00000000U +#define XHC_DBLDVX5_RESETVALUE 0x00000000U + +#define XHC_DBLDVX6_OFFSET 0x8d8U +#define XHC_DBLDVX6_BASE 0x8d8U +#define XHC_DBLDVX6__SID_L 31U +#define XHC_DBLDVX6__SID_R 16U +#define XHC_DBLDVX6__SID_WIDTH 16U +#define XHC_DBLDVX6__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX6__reserved_L 15U +#define XHC_DBLDVX6__reserved_R 8U +#define XHC_DBLDVX6__reserved_WIDTH 8U +#define XHC_DBLDVX6__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX6__TGT_L 7U +#define XHC_DBLDVX6__TGT_R 0U +#define XHC_DBLDVX6__TGT_WIDTH 8U +#define XHC_DBLDVX6__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX6_WIDTH 32U +#define XHC_DBLDVX6__WIDTH 32U +#define XHC_DBLDVX6_ALL_L 31U +#define XHC_DBLDVX6_ALL_R 0U +#define XHC_DBLDVX6__ALL_L 31U +#define XHC_DBLDVX6__ALL_R 0U +#define XHC_DBLDVX6_DATAMASK 0xffffffffU +#define XHC_DBLDVX6_RDWRMASK 0x00000000U +#define XHC_DBLDVX6_RESETVALUE 0x00000000U + +#define XHC_DBLDVX7_OFFSET 0x8dcU +#define XHC_DBLDVX7_BASE 0x8dcU +#define XHC_DBLDVX7__SID_L 31U +#define XHC_DBLDVX7__SID_R 16U +#define XHC_DBLDVX7__SID_WIDTH 16U +#define XHC_DBLDVX7__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX7__reserved_L 15U +#define XHC_DBLDVX7__reserved_R 8U +#define XHC_DBLDVX7__reserved_WIDTH 8U +#define XHC_DBLDVX7__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX7__TGT_L 7U +#define XHC_DBLDVX7__TGT_R 0U +#define XHC_DBLDVX7__TGT_WIDTH 8U +#define XHC_DBLDVX7__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX7_WIDTH 32U +#define XHC_DBLDVX7__WIDTH 32U +#define XHC_DBLDVX7_ALL_L 31U +#define XHC_DBLDVX7_ALL_R 0U +#define XHC_DBLDVX7__ALL_L 31U +#define XHC_DBLDVX7__ALL_R 0U +#define XHC_DBLDVX7_DATAMASK 0xffffffffU +#define XHC_DBLDVX7_RDWRMASK 0x00000000U +#define XHC_DBLDVX7_RESETVALUE 0x00000000U + +#define XHC_DBLDVX8_OFFSET 0x8e0U +#define XHC_DBLDVX8_BASE 0x8e0U +#define XHC_DBLDVX8__SID_L 31U +#define XHC_DBLDVX8__SID_R 16U +#define XHC_DBLDVX8__SID_WIDTH 16U +#define XHC_DBLDVX8__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX8__reserved_L 15U +#define XHC_DBLDVX8__reserved_R 8U +#define XHC_DBLDVX8__reserved_WIDTH 8U +#define XHC_DBLDVX8__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX8__TGT_L 7U +#define XHC_DBLDVX8__TGT_R 0U +#define XHC_DBLDVX8__TGT_WIDTH 8U +#define XHC_DBLDVX8__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX8_WIDTH 32U +#define XHC_DBLDVX8__WIDTH 32U +#define XHC_DBLDVX8_ALL_L 31U +#define XHC_DBLDVX8_ALL_R 0U +#define XHC_DBLDVX8__ALL_L 31U +#define XHC_DBLDVX8__ALL_R 0U +#define XHC_DBLDVX8_DATAMASK 0xffffffffU +#define XHC_DBLDVX8_RDWRMASK 0x00000000U +#define XHC_DBLDVX8_RESETVALUE 0x00000000U + +#define XHC_DBLDVX9_OFFSET 0x8e4U +#define XHC_DBLDVX9_BASE 0x8e4U +#define XHC_DBLDVX9__SID_L 31U +#define XHC_DBLDVX9__SID_R 16U +#define XHC_DBLDVX9__SID_WIDTH 16U +#define XHC_DBLDVX9__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX9__reserved_L 15U +#define XHC_DBLDVX9__reserved_R 8U +#define XHC_DBLDVX9__reserved_WIDTH 8U +#define XHC_DBLDVX9__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX9__TGT_L 7U +#define XHC_DBLDVX9__TGT_R 0U +#define XHC_DBLDVX9__TGT_WIDTH 8U +#define XHC_DBLDVX9__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX9_WIDTH 32U +#define XHC_DBLDVX9__WIDTH 32U +#define XHC_DBLDVX9_ALL_L 31U +#define XHC_DBLDVX9_ALL_R 0U +#define XHC_DBLDVX9__ALL_L 31U +#define XHC_DBLDVX9__ALL_R 0U +#define XHC_DBLDVX9_DATAMASK 0xffffffffU +#define XHC_DBLDVX9_RDWRMASK 0x00000000U +#define XHC_DBLDVX9_RESETVALUE 0x00000000U + +#define XHC_DBLDVX10_OFFSET 0x8e8U +#define XHC_DBLDVX10_BASE 0x8e8U +#define XHC_DBLDVX10__SID_L 31U +#define XHC_DBLDVX10__SID_R 16U +#define XHC_DBLDVX10__SID_WIDTH 16U +#define XHC_DBLDVX10__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX10__reserved_L 15U +#define XHC_DBLDVX10__reserved_R 8U +#define XHC_DBLDVX10__reserved_WIDTH 8U +#define XHC_DBLDVX10__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX10__TGT_L 7U +#define XHC_DBLDVX10__TGT_R 0U +#define XHC_DBLDVX10__TGT_WIDTH 8U +#define XHC_DBLDVX10__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX10_WIDTH 32U +#define XHC_DBLDVX10__WIDTH 32U +#define XHC_DBLDVX10_ALL_L 31U +#define XHC_DBLDVX10_ALL_R 0U +#define XHC_DBLDVX10__ALL_L 31U +#define XHC_DBLDVX10__ALL_R 0U +#define XHC_DBLDVX10_DATAMASK 0xffffffffU +#define XHC_DBLDVX10_RDWRMASK 0x00000000U +#define XHC_DBLDVX10_RESETVALUE 0x00000000U + +#define XHC_DBLDVX11_OFFSET 0x8ecU +#define XHC_DBLDVX11_BASE 0x8ecU +#define XHC_DBLDVX11__SID_L 31U +#define XHC_DBLDVX11__SID_R 16U +#define XHC_DBLDVX11__SID_WIDTH 16U +#define XHC_DBLDVX11__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX11__reserved_L 15U +#define XHC_DBLDVX11__reserved_R 8U +#define XHC_DBLDVX11__reserved_WIDTH 8U +#define XHC_DBLDVX11__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX11__TGT_L 7U +#define XHC_DBLDVX11__TGT_R 0U +#define XHC_DBLDVX11__TGT_WIDTH 8U +#define XHC_DBLDVX11__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX11_WIDTH 32U +#define XHC_DBLDVX11__WIDTH 32U +#define XHC_DBLDVX11_ALL_L 31U +#define XHC_DBLDVX11_ALL_R 0U +#define XHC_DBLDVX11__ALL_L 31U +#define XHC_DBLDVX11__ALL_R 0U +#define XHC_DBLDVX11_DATAMASK 0xffffffffU +#define XHC_DBLDVX11_RDWRMASK 0x00000000U +#define XHC_DBLDVX11_RESETVALUE 0x00000000U + +#define XHC_DBLDVX12_OFFSET 0x8f0U +#define XHC_DBLDVX12_BASE 0x8f0U +#define XHC_DBLDVX12__SID_L 31U +#define XHC_DBLDVX12__SID_R 16U +#define XHC_DBLDVX12__SID_WIDTH 16U +#define XHC_DBLDVX12__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX12__reserved_L 15U +#define XHC_DBLDVX12__reserved_R 8U +#define XHC_DBLDVX12__reserved_WIDTH 8U +#define XHC_DBLDVX12__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX12__TGT_L 7U +#define XHC_DBLDVX12__TGT_R 0U +#define XHC_DBLDVX12__TGT_WIDTH 8U +#define XHC_DBLDVX12__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX12_WIDTH 32U +#define XHC_DBLDVX12__WIDTH 32U +#define XHC_DBLDVX12_ALL_L 31U +#define XHC_DBLDVX12_ALL_R 0U +#define XHC_DBLDVX12__ALL_L 31U +#define XHC_DBLDVX12__ALL_R 0U +#define XHC_DBLDVX12_DATAMASK 0xffffffffU +#define XHC_DBLDVX12_RDWRMASK 0x00000000U +#define XHC_DBLDVX12_RESETVALUE 0x00000000U + +#define XHC_DBLDVX13_OFFSET 0x8f4U +#define XHC_DBLDVX13_BASE 0x8f4U +#define XHC_DBLDVX13__SID_L 31U +#define XHC_DBLDVX13__SID_R 16U +#define XHC_DBLDVX13__SID_WIDTH 16U +#define XHC_DBLDVX13__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX13__reserved_L 15U +#define XHC_DBLDVX13__reserved_R 8U +#define XHC_DBLDVX13__reserved_WIDTH 8U +#define XHC_DBLDVX13__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX13__TGT_L 7U +#define XHC_DBLDVX13__TGT_R 0U +#define XHC_DBLDVX13__TGT_WIDTH 8U +#define XHC_DBLDVX13__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX13_WIDTH 32U +#define XHC_DBLDVX13__WIDTH 32U +#define XHC_DBLDVX13_ALL_L 31U +#define XHC_DBLDVX13_ALL_R 0U +#define XHC_DBLDVX13__ALL_L 31U +#define XHC_DBLDVX13__ALL_R 0U +#define XHC_DBLDVX13_DATAMASK 0xffffffffU +#define XHC_DBLDVX13_RDWRMASK 0x00000000U +#define XHC_DBLDVX13_RESETVALUE 0x00000000U + +#define XHC_DBLDVX14_OFFSET 0x8f8U +#define XHC_DBLDVX14_BASE 0x8f8U +#define XHC_DBLDVX14__SID_L 31U +#define XHC_DBLDVX14__SID_R 16U +#define XHC_DBLDVX14__SID_WIDTH 16U +#define XHC_DBLDVX14__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX14__reserved_L 15U +#define XHC_DBLDVX14__reserved_R 8U +#define XHC_DBLDVX14__reserved_WIDTH 8U +#define XHC_DBLDVX14__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX14__TGT_L 7U +#define XHC_DBLDVX14__TGT_R 0U +#define XHC_DBLDVX14__TGT_WIDTH 8U +#define XHC_DBLDVX14__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX14_WIDTH 32U +#define XHC_DBLDVX14__WIDTH 32U +#define XHC_DBLDVX14_ALL_L 31U +#define XHC_DBLDVX14_ALL_R 0U +#define XHC_DBLDVX14__ALL_L 31U +#define XHC_DBLDVX14__ALL_R 0U +#define XHC_DBLDVX14_DATAMASK 0xffffffffU +#define XHC_DBLDVX14_RDWRMASK 0x00000000U +#define XHC_DBLDVX14_RESETVALUE 0x00000000U + +#define XHC_DBLDVX15_OFFSET 0x8fcU +#define XHC_DBLDVX15_BASE 0x8fcU +#define XHC_DBLDVX15__SID_L 31U +#define XHC_DBLDVX15__SID_R 16U +#define XHC_DBLDVX15__SID_WIDTH 16U +#define XHC_DBLDVX15__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX15__reserved_L 15U +#define XHC_DBLDVX15__reserved_R 8U +#define XHC_DBLDVX15__reserved_WIDTH 8U +#define XHC_DBLDVX15__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX15__TGT_L 7U +#define XHC_DBLDVX15__TGT_R 0U +#define XHC_DBLDVX15__TGT_WIDTH 8U +#define XHC_DBLDVX15__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX15_WIDTH 32U +#define XHC_DBLDVX15__WIDTH 32U +#define XHC_DBLDVX15_ALL_L 31U +#define XHC_DBLDVX15_ALL_R 0U +#define XHC_DBLDVX15__ALL_L 31U +#define XHC_DBLDVX15__ALL_R 0U +#define XHC_DBLDVX15_DATAMASK 0xffffffffU +#define XHC_DBLDVX15_RDWRMASK 0x00000000U +#define XHC_DBLDVX15_RESETVALUE 0x00000000U + +#define XHC_DBLDVX16_OFFSET 0x900U +#define XHC_DBLDVX16_BASE 0x900U +#define XHC_DBLDVX16__SID_L 31U +#define XHC_DBLDVX16__SID_R 16U +#define XHC_DBLDVX16__SID_WIDTH 16U +#define XHC_DBLDVX16__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX16__reserved_L 15U +#define XHC_DBLDVX16__reserved_R 8U +#define XHC_DBLDVX16__reserved_WIDTH 8U +#define XHC_DBLDVX16__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX16__TGT_L 7U +#define XHC_DBLDVX16__TGT_R 0U +#define XHC_DBLDVX16__TGT_WIDTH 8U +#define XHC_DBLDVX16__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX16_WIDTH 32U +#define XHC_DBLDVX16__WIDTH 32U +#define XHC_DBLDVX16_ALL_L 31U +#define XHC_DBLDVX16_ALL_R 0U +#define XHC_DBLDVX16__ALL_L 31U +#define XHC_DBLDVX16__ALL_R 0U +#define XHC_DBLDVX16_DATAMASK 0xffffffffU +#define XHC_DBLDVX16_RDWRMASK 0x00000000U +#define XHC_DBLDVX16_RESETVALUE 0x00000000U + +#define XHC_ECHSPT3_OFFSET 0x940U +#define XHC_ECHSPT3_BASE 0x940U +#define XHC_ECHSPT3__RMAJ_L 31U +#define XHC_ECHSPT3__RMAJ_R 24U +#define XHC_ECHSPT3__RMAJ_WIDTH 8U +#define XHC_ECHSPT3__RMAJ_RESETVALUE 0x00U +#define XHC_ECHSPT3__RMIN_L 23U +#define XHC_ECHSPT3__RMIN_R 16U +#define XHC_ECHSPT3__RMIN_WIDTH 8U +#define XHC_ECHSPT3__RMIN_RESETVALUE 0x00U +#define XHC_ECHSPT3__NCP_L 15U +#define XHC_ECHSPT3__NCP_R 8U +#define XHC_ECHSPT3__NCP_WIDTH 8U +#define XHC_ECHSPT3__NCP_RESETVALUE 0x00U +#define XHC_ECHSPT3__CID_L 7U +#define XHC_ECHSPT3__CID_R 0U +#define XHC_ECHSPT3__CID_WIDTH 8U +#define XHC_ECHSPT3__CID_RESETVALUE 0x02U +#define XHC_ECHSPT3_WIDTH 32U +#define XHC_ECHSPT3__WIDTH 32U +#define XHC_ECHSPT3_ALL_L 31U +#define XHC_ECHSPT3_ALL_R 0U +#define XHC_ECHSPT3__ALL_L 31U +#define XHC_ECHSPT3__ALL_R 0U +#define XHC_ECHSPT3_DATAMASK 0xffffffffU +#define XHC_ECHSPT3_RDWRMASK 0x00000000U +#define XHC_ECHSPT3_RESETVALUE 0x00000002U + +#define XHC_PNSTR3_OFFSET 0x944U +#define XHC_PNSTR3_BASE 0x944U +#define XHC_PNSTR3__STR_L 31U +#define XHC_PNSTR3__STR_R 0U +#define XHC_PNSTR3__STR_WIDTH 32U +#define XHC_PNSTR3__STR_RESETVALUE 0x20425355U +#define XHC_PNSTR3_WIDTH 32U +#define XHC_PNSTR3__WIDTH 32U +#define XHC_PNSTR3_ALL_L 31U +#define XHC_PNSTR3_ALL_R 0U +#define XHC_PNSTR3__ALL_L 31U +#define XHC_PNSTR3__ALL_R 0U +#define XHC_PNSTR3_DATAMASK 0xffffffffU +#define XHC_PNSTR3_RDWRMASK 0x00000000U +#define XHC_PNSTR3_RESETVALUE 0x20425355U + +#define XHC_PSUM3_OFFSET 0x948U +#define XHC_PSUM3_BASE 0x948U +#define XHC_PSUM3__PSIC_L 31U +#define XHC_PSUM3__PSIC_R 28U +#define XHC_PSUM3__PSIC_WIDTH 4U +#define XHC_PSUM3__PSIC_RESETVALUE 0x0U +#define XHC_PSUM3__MHD_L 27U +#define XHC_PSUM3__MHD_R 25U +#define XHC_PSUM3__MHD_WIDTH 3U +#define XHC_PSUM3__MHD_RESETVALUE 0x0U +#define XHC_PSUM3__BLC 20U +#define XHC_PSUM3__BLC_L 20U +#define XHC_PSUM3__BLC_R 20U +#define XHC_PSUM3__BLC_WIDTH 1U +#define XHC_PSUM3__BLC_RESETVALUE 0x0U +#define XHC_PSUM3__HLC 19U +#define XHC_PSUM3__HLC_L 19U +#define XHC_PSUM3__HLC_R 19U +#define XHC_PSUM3__HLC_WIDTH 1U +#define XHC_PSUM3__HLC_RESETVALUE 0x1U +#define XHC_PSUM3__IHI 18U +#define XHC_PSUM3__IHI_L 18U +#define XHC_PSUM3__IHI_R 18U +#define XHC_PSUM3__IHI_WIDTH 1U +#define XHC_PSUM3__IHI_RESETVALUE 0x0U +#define XHC_PSUM3__HSO 17U +#define XHC_PSUM3__HSO_L 17U +#define XHC_PSUM3__HSO_R 17U +#define XHC_PSUM3__HSO_WIDTH 1U +#define XHC_PSUM3__HSO_RESETVALUE 0x0U +#define XHC_PSUM3__reserved 16U +#define XHC_PSUM3__reserved_L 16U +#define XHC_PSUM3__reserved_R 16U +#define XHC_PSUM3__reserved_WIDTH 1U +#define XHC_PSUM3__reserved_RESETVALUE 0x0U +#define XHC_PSUM3__CPC_L 15U +#define XHC_PSUM3__CPC_R 8U +#define XHC_PSUM3__CPC_WIDTH 8U +#define XHC_PSUM3__CPC_RESETVALUE 0x00U +#define XHC_PSUM3__CPO_L 7U +#define XHC_PSUM3__CPO_R 0U +#define XHC_PSUM3__CPO_WIDTH 8U +#define XHC_PSUM3__CPO_RESETVALUE 0x00U +#define XHC_PSUM3__RESERVED_L 24U +#define XHC_PSUM3__RESERVED_R 21U +#define XHC_PSUM3_WIDTH 32U +#define XHC_PSUM3__WIDTH 32U +#define XHC_PSUM3_ALL_L 31U +#define XHC_PSUM3_ALL_R 0U +#define XHC_PSUM3__ALL_L 31U +#define XHC_PSUM3__ALL_R 0U +#define XHC_PSUM3_DATAMASK 0xfe1fffffU +#define XHC_PSUM3_RDWRMASK 0x01e00000U +#define XHC_PSUM3_RESETVALUE 0x00080000U + +#define XHC_PTSLTYP3_OFFSET 0x94cU +#define XHC_PTSLTYP3_BASE 0x94cU +#define XHC_PTSLTYP3__reserved_L 31U +#define XHC_PTSLTYP3__reserved_R 5U +#define XHC_PTSLTYP3__reserved_WIDTH 27U +#define XHC_PTSLTYP3__reserved_RESETVALUE 0x0U +#define XHC_PTSLTYP3__PST_L 4U +#define XHC_PTSLTYP3__PST_R 0U +#define XHC_PTSLTYP3__PST_WIDTH 5U +#define XHC_PTSLTYP3__PST_RESETVALUE 0x0U +#define XHC_PTSLTYP3_WIDTH 32U +#define XHC_PTSLTYP3__WIDTH 32U +#define XHC_PTSLTYP3_ALL_L 31U +#define XHC_PTSLTYP3_ALL_R 0U +#define XHC_PTSLTYP3__ALL_L 31U +#define XHC_PTSLTYP3__ALL_R 0U +#define XHC_PTSLTYP3_DATAMASK 0xffffffffU +#define XHC_PTSLTYP3_RDWRMASK 0x00000000U +#define XHC_PTSLTYP3_RESETVALUE 0x00000000U + +#define XHC_ECHSPT2_OFFSET 0x950U +#define XHC_ECHSPT2_BASE 0x950U +#define XHC_ECHSPT2__RMAJ_L 31U +#define XHC_ECHSPT2__RMAJ_R 24U +#define XHC_ECHSPT2__RMAJ_WIDTH 8U +#define XHC_ECHSPT2__RMAJ_RESETVALUE 0x00U +#define XHC_ECHSPT2__RMIN_L 23U +#define XHC_ECHSPT2__RMIN_R 16U +#define XHC_ECHSPT2__RMIN_WIDTH 8U +#define XHC_ECHSPT2__RMIN_RESETVALUE 0x00U +#define XHC_ECHSPT2__NCP_L 15U +#define XHC_ECHSPT2__NCP_R 8U +#define XHC_ECHSPT2__NCP_WIDTH 8U +#define XHC_ECHSPT2__NCP_RESETVALUE 0x00U +#define XHC_ECHSPT2__CID_L 7U +#define XHC_ECHSPT2__CID_R 0U +#define XHC_ECHSPT2__CID_WIDTH 8U +#define XHC_ECHSPT2__CID_RESETVALUE 0x02U +#define XHC_ECHSPT2_WIDTH 32U +#define XHC_ECHSPT2__WIDTH 32U +#define XHC_ECHSPT2_ALL_L 31U +#define XHC_ECHSPT2_ALL_R 0U +#define XHC_ECHSPT2__ALL_L 31U +#define XHC_ECHSPT2__ALL_R 0U +#define XHC_ECHSPT2_DATAMASK 0xffffffffU +#define XHC_ECHSPT2_RDWRMASK 0x00000000U +#define XHC_ECHSPT2_RESETVALUE 0x00000002U + +#define XHC_PNSTR2_OFFSET 0x954U +#define XHC_PNSTR2_BASE 0x954U +#define XHC_PNSTR2__STR_L 31U +#define XHC_PNSTR2__STR_R 0U +#define XHC_PNSTR2__STR_WIDTH 32U +#define XHC_PNSTR2__STR_RESETVALUE 0x20425355U +#define XHC_PNSTR2_WIDTH 32U +#define XHC_PNSTR2__WIDTH 32U +#define XHC_PNSTR2_ALL_L 31U +#define XHC_PNSTR2_ALL_R 0U +#define XHC_PNSTR2__ALL_L 31U +#define XHC_PNSTR2__ALL_R 0U +#define XHC_PNSTR2_DATAMASK 0xffffffffU +#define XHC_PNSTR2_RDWRMASK 0x00000000U +#define XHC_PNSTR2_RESETVALUE 0x20425355U + +#define XHC_PSUM2_OFFSET 0x958U +#define XHC_PSUM2_BASE 0x958U +#define XHC_PSUM2__PSIC_L 31U +#define XHC_PSUM2__PSIC_R 28U +#define XHC_PSUM2__PSIC_WIDTH 4U +#define XHC_PSUM2__PSIC_RESETVALUE 0x0U +#define XHC_PSUM2__MHD_L 27U +#define XHC_PSUM2__MHD_R 25U +#define XHC_PSUM2__MHD_WIDTH 3U +#define XHC_PSUM2__MHD_RESETVALUE 0x0U +#define XHC_PSUM2__BLC 20U +#define XHC_PSUM2__BLC_L 20U +#define XHC_PSUM2__BLC_R 20U +#define XHC_PSUM2__BLC_WIDTH 1U +#define XHC_PSUM2__BLC_RESETVALUE 0x0U +#define XHC_PSUM2__HLC 19U +#define XHC_PSUM2__HLC_L 19U +#define XHC_PSUM2__HLC_R 19U +#define XHC_PSUM2__HLC_WIDTH 1U +#define XHC_PSUM2__HLC_RESETVALUE 0x1U +#define XHC_PSUM2__IHI 18U +#define XHC_PSUM2__IHI_L 18U +#define XHC_PSUM2__IHI_R 18U +#define XHC_PSUM2__IHI_WIDTH 1U +#define XHC_PSUM2__IHI_RESETVALUE 0x0U +#define XHC_PSUM2__HSO 17U +#define XHC_PSUM2__HSO_L 17U +#define XHC_PSUM2__HSO_R 17U +#define XHC_PSUM2__HSO_WIDTH 1U +#define XHC_PSUM2__HSO_RESETVALUE 0x0U +#define XHC_PSUM2__reserved 16U +#define XHC_PSUM2__reserved_L 16U +#define XHC_PSUM2__reserved_R 16U +#define XHC_PSUM2__reserved_WIDTH 1U +#define XHC_PSUM2__reserved_RESETVALUE 0x0U +#define XHC_PSUM2__CPC_L 15U +#define XHC_PSUM2__CPC_R 8U +#define XHC_PSUM2__CPC_WIDTH 8U +#define XHC_PSUM2__CPC_RESETVALUE 0x00U +#define XHC_PSUM2__CPO_L 7U +#define XHC_PSUM2__CPO_R 0U +#define XHC_PSUM2__CPO_WIDTH 8U +#define XHC_PSUM2__CPO_RESETVALUE 0x00U +#define XHC_PSUM2__RESERVED_L 24U +#define XHC_PSUM2__RESERVED_R 21U +#define XHC_PSUM2_WIDTH 32U +#define XHC_PSUM2__WIDTH 32U +#define XHC_PSUM2_ALL_L 31U +#define XHC_PSUM2_ALL_R 0U +#define XHC_PSUM2__ALL_L 31U +#define XHC_PSUM2__ALL_R 0U +#define XHC_PSUM2_DATAMASK 0xfe1fffffU +#define XHC_PSUM2_RDWRMASK 0x01e00000U +#define XHC_PSUM2_RESETVALUE 0x00080000U + +#define XHC_PTSLTYP2_OFFSET 0x95cU +#define XHC_PTSLTYP2_BASE 0x95cU +#define XHC_PTSLTYP2__reserved_L 31U +#define XHC_PTSLTYP2__reserved_R 5U +#define XHC_PTSLTYP2__reserved_WIDTH 27U +#define XHC_PTSLTYP2__reserved_RESETVALUE 0x0U +#define XHC_PTSLTYP2__PST_L 4U +#define XHC_PTSLTYP2__PST_R 0U +#define XHC_PTSLTYP2__PST_WIDTH 5U +#define XHC_PTSLTYP2__PST_RESETVALUE 0x0U +#define XHC_PTSLTYP2_WIDTH 32U +#define XHC_PTSLTYP2__WIDTH 32U +#define XHC_PTSLTYP2_ALL_L 31U +#define XHC_PTSLTYP2_ALL_R 0U +#define XHC_PTSLTYP2__ALL_L 31U +#define XHC_PTSLTYP2__ALL_R 0U +#define XHC_PTSLTYP2_DATAMASK 0xffffffffU +#define XHC_PTSLTYP2_RDWRMASK 0x00000000U +#define XHC_PTSLTYP2_RESETVALUE 0x00000000U + +#define XHC_ECHRSVP_OFFSET 0x960U +#define XHC_ECHRSVP_BASE 0x960U +#define XHC_ECHRSVP__reserved_L 31U +#define XHC_ECHRSVP__reserved_R 16U +#define XHC_ECHRSVP__reserved_WIDTH 16U +#define XHC_ECHRSVP__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVP__NCP_L 15U +#define XHC_ECHRSVP__NCP_R 8U +#define XHC_ECHRSVP__NCP_WIDTH 8U +#define XHC_ECHRSVP__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVP__CID_L 7U +#define XHC_ECHRSVP__CID_R 0U +#define XHC_ECHRSVP__CID_WIDTH 8U +#define XHC_ECHRSVP__CID_RESETVALUE 0xffU +#define XHC_ECHRSVP_WIDTH 32U +#define XHC_ECHRSVP__WIDTH 32U +#define XHC_ECHRSVP_ALL_L 31U +#define XHC_ECHRSVP_ALL_R 0U +#define XHC_ECHRSVP__ALL_L 31U +#define XHC_ECHRSVP__ALL_R 0U +#define XHC_ECHRSVP_DATAMASK 0xffffffffU +#define XHC_ECHRSVP_RDWRMASK 0x00000000U +#define XHC_ECHRSVP_RESETVALUE 0x000000ffU + +#define XHC_ECHRSVI_OFFSET 0x968U +#define XHC_ECHRSVI_BASE 0x968U +#define XHC_ECHRSVI__reserved_L 31U +#define XHC_ECHRSVI__reserved_R 16U +#define XHC_ECHRSVI__reserved_WIDTH 16U +#define XHC_ECHRSVI__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVI__NCP_L 15U +#define XHC_ECHRSVI__NCP_R 8U +#define XHC_ECHRSVI__NCP_WIDTH 8U +#define XHC_ECHRSVI__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVI__CID_L 7U +#define XHC_ECHRSVI__CID_R 0U +#define XHC_ECHRSVI__CID_WIDTH 8U +#define XHC_ECHRSVI__CID_RESETVALUE 0xffU +#define XHC_ECHRSVI_WIDTH 32U +#define XHC_ECHRSVI__WIDTH 32U +#define XHC_ECHRSVI_ALL_L 31U +#define XHC_ECHRSVI_ALL_R 0U +#define XHC_ECHRSVI__ALL_L 31U +#define XHC_ECHRSVI__ALL_R 0U +#define XHC_ECHRSVI_DATAMASK 0xffffffffU +#define XHC_ECHRSVI_RDWRMASK 0x00000000U +#define XHC_ECHRSVI_RESETVALUE 0x000000ffU + +#define XHC_ECHRSVM_OFFSET 0xae8U +#define XHC_ECHRSVM_BASE 0xae8U +#define XHC_ECHRSVM__reserved_L 31U +#define XHC_ECHRSVM__reserved_R 16U +#define XHC_ECHRSVM__reserved_WIDTH 16U +#define XHC_ECHRSVM__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVM__NCP_L 15U +#define XHC_ECHRSVM__NCP_R 8U +#define XHC_ECHRSVM__NCP_WIDTH 8U +#define XHC_ECHRSVM__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVM__CID_L 7U +#define XHC_ECHRSVM__CID_R 0U +#define XHC_ECHRSVM__CID_WIDTH 8U +#define XHC_ECHRSVM__CID_RESETVALUE 0xffU +#define XHC_ECHRSVM_WIDTH 32U +#define XHC_ECHRSVM__WIDTH 32U +#define XHC_ECHRSVM_ALL_L 31U +#define XHC_ECHRSVM_ALL_R 0U +#define XHC_ECHRSVM__ALL_L 31U +#define XHC_ECHRSVM__ALL_R 0U +#define XHC_ECHRSVM_DATAMASK 0xffffffffU +#define XHC_ECHRSVM_RDWRMASK 0x00000000U +#define XHC_ECHRSVM_RESETVALUE 0x000000ffU + +#define XHC_ECHRSVD_OFFSET 0xaf8U +#define XHC_ECHRSVD_BASE 0xaf8U +#define XHC_ECHRSVD__reserved_L 31U +#define XHC_ECHRSVD__reserved_R 16U +#define XHC_ECHRSVD__reserved_WIDTH 16U +#define XHC_ECHRSVD__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVD__NCP_L 15U +#define XHC_ECHRSVD__NCP_R 8U +#define XHC_ECHRSVD__NCP_WIDTH 8U +#define XHC_ECHRSVD__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVD__CID_L 7U +#define XHC_ECHRSVD__CID_R 0U +#define XHC_ECHRSVD__CID_WIDTH 8U +#define XHC_ECHRSVD__CID_RESETVALUE 0xffU +#define XHC_ECHRSVD_WIDTH 32U +#define XHC_ECHRSVD__WIDTH 32U +#define XHC_ECHRSVD_ALL_L 31U +#define XHC_ECHRSVD_ALL_R 0U +#define XHC_ECHRSVD__ALL_L 31U +#define XHC_ECHRSVD__ALL_R 0U +#define XHC_ECHRSVD_DATAMASK 0xffffffffU +#define XHC_ECHRSVD_RDWRMASK 0x00000000U +#define XHC_ECHRSVD_RESETVALUE 0x000000ffU + +#define XHC_ECHRSVO_OFFSET 0xb38U +#define XHC_ECHRSVO_BASE 0xb38U +#define XHC_ECHRSVO__reserved_L 31U +#define XHC_ECHRSVO__reserved_R 16U +#define XHC_ECHRSVO__reserved_WIDTH 16U +#define XHC_ECHRSVO__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVO__NCP_L 15U +#define XHC_ECHRSVO__NCP_R 8U +#define XHC_ECHRSVO__NCP_WIDTH 8U +#define XHC_ECHRSVO__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVO__CID_L 7U +#define XHC_ECHRSVO__CID_R 0U +#define XHC_ECHRSVO__CID_WIDTH 8U +#define XHC_ECHRSVO__CID_RESETVALUE 0xffU +#define XHC_ECHRSVO_WIDTH 32U +#define XHC_ECHRSVO__WIDTH 32U +#define XHC_ECHRSVO_ALL_L 31U +#define XHC_ECHRSVO_ALL_R 0U +#define XHC_ECHRSVO__ALL_L 31U +#define XHC_ECHRSVO__ALL_R 0U +#define XHC_ECHRSVO_DATAMASK 0xffffffffU +#define XHC_ECHRSVO_RDWRMASK 0x00000000U +#define XHC_ECHRSVO_RESETVALUE 0x000000ffU + +#define XHC_ECHCTT_OFFSET 0xbf0U +#define XHC_ECHCTT_BASE 0xbf0U +#define XHC_ECHCTT__reserved_L 31U +#define XHC_ECHCTT__reserved_R 16U +#define XHC_ECHCTT__reserved_WIDTH 16U +#define XHC_ECHCTT__reserved_RESETVALUE 0x0000U +#define XHC_ECHCTT__NCP_L 15U +#define XHC_ECHCTT__NCP_R 8U +#define XHC_ECHCTT__NCP_WIDTH 8U +#define XHC_ECHCTT__NCP_RESETVALUE 0x04U +#define XHC_ECHCTT__CID_L 7U +#define XHC_ECHCTT__CID_R 0U +#define XHC_ECHCTT__CID_WIDTH 8U +#define XHC_ECHCTT__CID_RESETVALUE 0xe0U +#define XHC_ECHCTT_WIDTH 32U +#define XHC_ECHCTT__WIDTH 32U +#define XHC_ECHCTT_ALL_L 31U +#define XHC_ECHCTT_ALL_R 0U +#define XHC_ECHCTT__ALL_L 31U +#define XHC_ECHCTT__ALL_R 0U +#define XHC_ECHCTT_DATAMASK 0xffffffffU +#define XHC_ECHCTT_RDWRMASK 0x00000000U +#define XHC_ECHCTT_RESETVALUE 0x000004e0U + +#define XHC_CTTMTS0_OFFSET 0xbf8U +#define XHC_CTTMTS0_BASE 0xbf8U +#define XHC_CTTMTS0__DCM 31U +#define XHC_CTTMTS0__DCM_L 31U +#define XHC_CTTMTS0__DCM_R 31U +#define XHC_CTTMTS0__DCM_WIDTH 1U +#define XHC_CTTMTS0__DCM_RESETVALUE 0x0U +#define XHC_CTTMTS0__reserved_L 30U +#define XHC_CTTMTS0__reserved_R 10U +#define XHC_CTTMTS0__reserved_WIDTH 21U +#define XHC_CTTMTS0__reserved_RESETVALUE 0x0U +#define XHC_CTTMTS0__SLA_L 9U +#define XHC_CTTMTS0__SLA_R 0U +#define XHC_CTTMTS0__SLA_WIDTH 10U +#define XHC_CTTMTS0__SLA_RESETVALUE 0x0U +#define XHC_CTTMTS0_WIDTH 32U +#define XHC_CTTMTS0__WIDTH 32U +#define XHC_CTTMTS0_ALL_L 31U +#define XHC_CTTMTS0_ALL_R 0U +#define XHC_CTTMTS0__ALL_L 31U +#define XHC_CTTMTS0__ALL_R 0U +#define XHC_CTTMTS0_DATAMASK 0xffffffffU +#define XHC_CTTMTS0_RDWRMASK 0x00000000U +#define XHC_CTTMTS0_RESETVALUE 0x00000000U + +#define XHC_CTTMTS1_OFFSET 0xbfcU +#define XHC_CTTMTS1_BASE 0xbfcU +#define XHC_CTTMTS1__TXF_L 25U +#define XHC_CTTMTS1__TXF_R 16U +#define XHC_CTTMTS1__TXF_WIDTH 10U +#define XHC_CTTMTS1__TXF_RESETVALUE 0x0U +#define XHC_CTTMTS1__reserved_L 15U +#define XHC_CTTMTS1__reserved_R 10U +#define XHC_CTTMTS1__reserved_WIDTH 6U +#define XHC_CTTMTS1__reserved_RESETVALUE 0x0U +#define XHC_CTTMTS1__RXF_L 9U +#define XHC_CTTMTS1__RXF_R 0U +#define XHC_CTTMTS1__RXF_WIDTH 10U +#define XHC_CTTMTS1__RXF_RESETVALUE 0x0U +#define XHC_CTTMTS1__RESERVED_L 31U +#define XHC_CTTMTS1__RESERVED_R 26U +#define XHC_CTTMTS1_WIDTH 26U +#define XHC_CTTMTS1__WIDTH 26U +#define XHC_CTTMTS1_ALL_L 25U +#define XHC_CTTMTS1_ALL_R 0U +#define XHC_CTTMTS1__ALL_L 25U +#define XHC_CTTMTS1__ALL_R 0U +#define XHC_CTTMTS1_DATAMASK 0x03ffffffU +#define XHC_CTTMTS1_RDWRMASK 0xfc000000U +#define XHC_CTTMTS1_RESETVALUE 0x0000000U + +#define XHC_ECHBIU_OFFSET 0xc00U +#define XHC_ECHBIU_BASE 0xc00U +#define XHC_ECHBIU__CLK_L 31U +#define XHC_ECHBIU__CLK_R 21U +#define XHC_ECHBIU__CLK_WIDTH 11U +#define XHC_ECHBIU__CLK_RESETVALUE 0x0U +#define XHC_ECHBIU__reserved_L 20U +#define XHC_ECHBIU__reserved_R 19U +#define XHC_ECHBIU__reserved_WIDTH 2U +#define XHC_ECHBIU__reserved_RESETVALUE 0x0U +#define XHC_ECHBIU__WID_L 18U +#define XHC_ECHBIU__WID_R 16U +#define XHC_ECHBIU__WID_WIDTH 3U +#define XHC_ECHBIU__WID_RESETVALUE 0x0U +#define XHC_ECHBIU__NCP_L 15U +#define XHC_ECHBIU__NCP_R 8U +#define XHC_ECHBIU__NCP_WIDTH 8U +#define XHC_ECHBIU__NCP_RESETVALUE 0x08U +#define XHC_ECHBIU__CID_L 7U +#define XHC_ECHBIU__CID_R 0U +#define XHC_ECHBIU__CID_WIDTH 8U +#define XHC_ECHBIU__CID_RESETVALUE 0xc0U +#define XHC_ECHBIU_WIDTH 32U +#define XHC_ECHBIU__WIDTH 32U +#define XHC_ECHBIU_ALL_L 31U +#define XHC_ECHBIU_ALL_R 0U +#define XHC_ECHBIU__ALL_L 31U +#define XHC_ECHBIU__ALL_R 0U +#define XHC_ECHBIU_DATAMASK 0xffffffffU +#define XHC_ECHBIU_RDWRMASK 0x00000000U +#define XHC_ECHBIU_RESETVALUE 0x000008c0U + +#define XHC_BIUSPC_OFFSET 0xc04U +#define XHC_BIUSPC_BASE 0xc04U +#define XHC_BIUSPC__MAJ_L 31U +#define XHC_BIUSPC__MAJ_R 28U +#define XHC_BIUSPC__MAJ_WIDTH 4U +#define XHC_BIUSPC__MAJ_RESETVALUE 0x0U +#define XHC_BIUSPC__MIN_L 27U +#define XHC_BIUSPC__MIN_R 24U +#define XHC_BIUSPC__MIN_WIDTH 4U +#define XHC_BIUSPC__MIN_RESETVALUE 0x0U +#define XHC_BIUSPC__RLS_L 23U +#define XHC_BIUSPC__RLS_R 20U +#define XHC_BIUSPC__RLS_WIDTH 4U +#define XHC_BIUSPC__RLS_RESETVALUE 0x0U +#define XHC_BIUSPC__reserved_L 19U +#define XHC_BIUSPC__reserved_R 4U +#define XHC_BIUSPC__reserved_WIDTH 16U +#define XHC_BIUSPC__reserved_RESETVALUE 0x0000U +#define XHC_BIUSPC__SPI_L 3U +#define XHC_BIUSPC__SPI_R 2U +#define XHC_BIUSPC__SPI_WIDTH 2U +#define XHC_BIUSPC__SPI_RESETVALUE 0x3U +#define XHC_BIUSPC__TYP_L 1U +#define XHC_BIUSPC__TYP_R 0U +#define XHC_BIUSPC__TYP_WIDTH 2U +#define XHC_BIUSPC__TYP_RESETVALUE 0x0U +#define XHC_BIUSPC_WIDTH 32U +#define XHC_BIUSPC__WIDTH 32U +#define XHC_BIUSPC_ALL_L 31U +#define XHC_BIUSPC_ALL_R 0U +#define XHC_BIUSPC__ALL_L 31U +#define XHC_BIUSPC__ALL_R 0U +#define XHC_BIUSPC_DATAMASK 0xffffffffU +#define XHC_BIUSPC_RDWRMASK 0x00000000U +#define XHC_BIUSPC_RESETVALUE 0x0000000cU + +#define XHC_AXIWRA_OFFSET 0xc08U +#define XHC_AXIWRA_BASE 0xc08U +#define XHC_AXIWRA__WTS_L 31U +#define XHC_AXIWRA__WTS_R 28U +#define XHC_AXIWRA__WTS_WIDTH 4U +#define XHC_AXIWRA__WTS_RESETVALUE 0x2U +#define XHC_AXIWRA__WUA_L 24U +#define XHC_AXIWRA__WUA_R 16U +#define XHC_AXIWRA__WUA_WIDTH 9U +#define XHC_AXIWRA__WUA_RESETVALUE 0x0U +#define XHC_AXIWRA__reserved_L 15U +#define XHC_AXIWRA__reserved_R 10U +#define XHC_AXIWRA__reserved_WIDTH 6U +#define XHC_AXIWRA__reserved_RESETVALUE 0x0U +#define XHC_AXIWRA__BYP 9U +#define XHC_AXIWRA__BYP_L 9U +#define XHC_AXIWRA__BYP_R 9U +#define XHC_AXIWRA__BYP_WIDTH 1U +#define XHC_AXIWRA__BYP_RESETVALUE 0x0U +#define XHC_AXIWRA__WSA_L 8U +#define XHC_AXIWRA__WSA_R 0U +#define XHC_AXIWRA__WSA_WIDTH 9U +#define XHC_AXIWRA__WSA_RESETVALUE 0x0U +#define XHC_AXIWRA__RESERVED_L 27U +#define XHC_AXIWRA__RESERVED_R 25U +#define XHC_AXIWRA_WIDTH 32U +#define XHC_AXIWRA__WIDTH 32U +#define XHC_AXIWRA_ALL_L 31U +#define XHC_AXIWRA_ALL_R 0U +#define XHC_AXIWRA__ALL_L 31U +#define XHC_AXIWRA__ALL_R 0U +#define XHC_AXIWRA_DATAMASK 0xf1ffffffU +#define XHC_AXIWRA_RDWRMASK 0x0e000000U +#define XHC_AXIWRA_RESETVALUE 0x20000000U + +#define XHC_AXIRDA_OFFSET 0xc0cU +#define XHC_AXIRDA_BASE 0xc0cU +#define XHC_AXIRDA__RTS_L 31U +#define XHC_AXIRDA__RTS_R 28U +#define XHC_AXIRDA__RTS_WIDTH 4U +#define XHC_AXIRDA__RTS_RESETVALUE 0x2U +#define XHC_AXIRDA__RFPC 27U +#define XHC_AXIRDA__RFPC_L 27U +#define XHC_AXIRDA__RFPC_R 27U +#define XHC_AXIRDA__RFPC_WIDTH 1U +#define XHC_AXIRDA__RFPC_RESETVALUE 0x0U +#define XHC_AXIRDA__RUA_L 24U +#define XHC_AXIRDA__RUA_R 16U +#define XHC_AXIRDA__RUA_WIDTH 9U +#define XHC_AXIRDA__RUA_RESETVALUE 0x0U +#define XHC_AXIRDA__reserved_L 15U +#define XHC_AXIRDA__reserved_R 9U +#define XHC_AXIRDA__reserved_WIDTH 7U +#define XHC_AXIRDA__reserved_RESETVALUE 0x0U +#define XHC_AXIRDA__RSA_L 8U +#define XHC_AXIRDA__RSA_R 0U +#define XHC_AXIRDA__RSA_WIDTH 9U +#define XHC_AXIRDA__RSA_RESETVALUE 0x0U +#define XHC_AXIRDA__RESERVED_L 26U +#define XHC_AXIRDA__RESERVED_R 25U +#define XHC_AXIRDA_WIDTH 32U +#define XHC_AXIRDA__WIDTH 32U +#define XHC_AXIRDA_ALL_L 31U +#define XHC_AXIRDA_ALL_R 0U +#define XHC_AXIRDA__ALL_L 31U +#define XHC_AXIRDA__ALL_R 0U +#define XHC_AXIRDA_DATAMASK 0xf9ffffffU +#define XHC_AXIRDA_RDWRMASK 0x06000000U +#define XHC_AXIRDA_RESETVALUE 0x20000000U + +#define XHC_AXILPM_OFFSET 0xc10U +#define XHC_AXILPM_BASE 0xc10U +#define XHC_AXILPM__ENB 31U +#define XHC_AXILPM__ENB_L 31U +#define XHC_AXILPM__ENB_R 31U +#define XHC_AXILPM__ENB_WIDTH 1U +#define XHC_AXILPM__ENB_RESETVALUE 0x0U +#define XHC_AXILPM__reserved_L 30U +#define XHC_AXILPM__reserved_R 3U +#define XHC_AXILPM__reserved_WIDTH 28U +#define XHC_AXILPM__reserved_RESETVALUE 0x0000000U +#define XHC_AXILPM__ITT_L 2U +#define XHC_AXILPM__ITT_R 0U +#define XHC_AXILPM__ITT_WIDTH 3U +#define XHC_AXILPM__ITT_RESETVALUE 0x0U +#define XHC_AXILPM_WIDTH 32U +#define XHC_AXILPM__WIDTH 32U +#define XHC_AXILPM_ALL_L 31U +#define XHC_AXILPM_ALL_R 0U +#define XHC_AXILPM__ALL_L 31U +#define XHC_AXILPM__ALL_R 0U +#define XHC_AXILPM_DATAMASK 0xffffffffU +#define XHC_AXILPM_RDWRMASK 0x00000000U +#define XHC_AXILPM_RESETVALUE 0x00000000U + +#define XHC_AXIQOS_OFFSET 0xc14U +#define XHC_AXIQOS_BASE 0xc14U +#define XHC_AXIQOS__WQOS3_L 31U +#define XHC_AXIQOS__WQOS3_R 28U +#define XHC_AXIQOS__WQOS3_WIDTH 4U +#define XHC_AXIQOS__WQOS3_RESETVALUE 0x0U +#define XHC_AXIQOS__WQOS2_L 27U +#define XHC_AXIQOS__WQOS2_R 24U +#define XHC_AXIQOS__WQOS2_WIDTH 4U +#define XHC_AXIQOS__WQOS2_RESETVALUE 0x0U +#define XHC_AXIQOS__WQOS1_L 23U +#define XHC_AXIQOS__WQOS1_R 20U +#define XHC_AXIQOS__WQOS1_WIDTH 4U +#define XHC_AXIQOS__WQOS1_RESETVALUE 0x0U +#define XHC_AXIQOS__WQOS0_L 19U +#define XHC_AXIQOS__WQOS0_R 16U +#define XHC_AXIQOS__WQOS0_WIDTH 4U +#define XHC_AXIQOS__WQOS0_RESETVALUE 0x0U +#define XHC_AXIQOS__RQOS3_L 15U +#define XHC_AXIQOS__RQOS3_R 12U +#define XHC_AXIQOS__RQOS3_WIDTH 4U +#define XHC_AXIQOS__RQOS3_RESETVALUE 0x0U +#define XHC_AXIQOS__RQOS2_L 11U +#define XHC_AXIQOS__RQOS2_R 8U +#define XHC_AXIQOS__RQOS2_WIDTH 4U +#define XHC_AXIQOS__RQOS2_RESETVALUE 0x0U +#define XHC_AXIQOS__RQOS1_L 7U +#define XHC_AXIQOS__RQOS1_R 4U +#define XHC_AXIQOS__RQOS1_WIDTH 4U +#define XHC_AXIQOS__RQOS1_RESETVALUE 0x0U +#define XHC_AXIQOS__RQOS0_L 3U +#define XHC_AXIQOS__RQOS0_R 0U +#define XHC_AXIQOS__RQOS0_WIDTH 4U +#define XHC_AXIQOS__RQOS0_RESETVALUE 0x0U +#define XHC_AXIQOS_WIDTH 32U +#define XHC_AXIQOS__WIDTH 32U +#define XHC_AXIQOS_ALL_L 31U +#define XHC_AXIQOS_ALL_R 0U +#define XHC_AXIQOS__ALL_L 31U +#define XHC_AXIQOS__ALL_R 0U +#define XHC_AXIQOS_DATAMASK 0xffffffffU +#define XHC_AXIQOS_RDWRMASK 0x00000000U +#define XHC_AXIQOS_RESETVALUE 0x00000000U + +#define XHC_ECHCSR_OFFSET 0xc20U +#define XHC_ECHCSR_BASE 0xc20U +#define XHC_ECHCSR__CLK_L 31U +#define XHC_ECHCSR__CLK_R 21U +#define XHC_ECHCSR__CLK_WIDTH 11U +#define XHC_ECHCSR__CLK_RESETVALUE 0x0U +#define XHC_ECHCSR__reserved_L 20U +#define XHC_ECHCSR__reserved_R 19U +#define XHC_ECHCSR__reserved_WIDTH 2U +#define XHC_ECHCSR__reserved_RESETVALUE 0x0U +#define XHC_ECHCSR__WID_L 18U +#define XHC_ECHCSR__WID_R 16U +#define XHC_ECHCSR__WID_WIDTH 3U +#define XHC_ECHCSR__WID_RESETVALUE 0x0U +#define XHC_ECHCSR__NCP_L 15U +#define XHC_ECHCSR__NCP_R 8U +#define XHC_ECHCSR__NCP_WIDTH 8U +#define XHC_ECHCSR__NCP_RESETVALUE 0x04U +#define XHC_ECHCSR__CID_L 7U +#define XHC_ECHCSR__CID_R 0U +#define XHC_ECHCSR__CID_WIDTH 8U +#define XHC_ECHCSR__CID_RESETVALUE 0xc1U +#define XHC_ECHCSR_WIDTH 32U +#define XHC_ECHCSR__WIDTH 32U +#define XHC_ECHCSR_ALL_L 31U +#define XHC_ECHCSR_ALL_R 0U +#define XHC_ECHCSR__ALL_L 31U +#define XHC_ECHCSR__ALL_R 0U +#define XHC_ECHCSR_DATAMASK 0xffffffffU +#define XHC_ECHCSR_RDWRMASK 0x00000000U +#define XHC_ECHCSR_RESETVALUE 0x000004c1U + +#define XHC_CSRSPC_OFFSET 0xc24U +#define XHC_CSRSPC_BASE 0xc24U +#define XHC_CSRSPC__MAJ_L 31U +#define XHC_CSRSPC__MAJ_R 28U +#define XHC_CSRSPC__MAJ_WIDTH 4U +#define XHC_CSRSPC__MAJ_RESETVALUE 0x0U +#define XHC_CSRSPC__MIN_L 27U +#define XHC_CSRSPC__MIN_R 24U +#define XHC_CSRSPC__MIN_WIDTH 4U +#define XHC_CSRSPC__MIN_RESETVALUE 0x0U +#define XHC_CSRSPC__RLS_L 23U +#define XHC_CSRSPC__RLS_R 20U +#define XHC_CSRSPC__RLS_WIDTH 4U +#define XHC_CSRSPC__RLS_RESETVALUE 0x0U +#define XHC_CSRSPC__reserved_L 19U +#define XHC_CSRSPC__reserved_R 3U +#define XHC_CSRSPC__reserved_WIDTH 17U +#define XHC_CSRSPC__reserved_RESETVALUE 0x0U +#define XHC_CSRSPC__ASP 2U +#define XHC_CSRSPC__ASP_L 2U +#define XHC_CSRSPC__ASP_R 2U +#define XHC_CSRSPC__ASP_WIDTH 1U +#define XHC_CSRSPC__ASP_RESETVALUE 0x0U +#define XHC_CSRSPC__TYP_L 1U +#define XHC_CSRSPC__TYP_R 0U +#define XHC_CSRSPC__TYP_WIDTH 2U +#define XHC_CSRSPC__TYP_RESETVALUE 0x0U +#define XHC_CSRSPC_WIDTH 32U +#define XHC_CSRSPC__WIDTH 32U +#define XHC_CSRSPC_ALL_L 31U +#define XHC_CSRSPC_ALL_R 0U +#define XHC_CSRSPC__ALL_L 31U +#define XHC_CSRSPC__ALL_R 0U +#define XHC_CSRSPC_DATAMASK 0xffffffffU +#define XHC_CSRSPC_RDWRMASK 0x00000000U +#define XHC_CSRSPC_RESETVALUE 0x00000000U + +#define XHC_ECHAIU_OFFSET 0xc30U +#define XHC_ECHAIU_BASE 0xc30U +#define XHC_ECHAIU__DMA_L 31U +#define XHC_ECHAIU__DMA_R 30U +#define XHC_ECHAIU__DMA_WIDTH 2U +#define XHC_ECHAIU__DMA_RESETVALUE 0x1U +#define XHC_ECHAIU__PBRS_L 29U +#define XHC_ECHAIU__PBRS_R 28U +#define XHC_ECHAIU__PBRS_WIDTH 2U +#define XHC_ECHAIU__PBRS_RESETVALUE 0x0U +#define XHC_ECHAIU__PBR2_L 27U +#define XHC_ECHAIU__PBR2_R 26U +#define XHC_ECHAIU__PBR2_WIDTH 2U +#define XHC_ECHAIU__PBR2_RESETVALUE 0x0U +#define XHC_ECHAIU__SCHS_L 25U +#define XHC_ECHAIU__SCHS_R 24U +#define XHC_ECHAIU__SCHS_WIDTH 2U +#define XHC_ECHAIU__SCHS_RESETVALUE 0x0U +#define XHC_ECHAIU__SCH2_L 23U +#define XHC_ECHAIU__SCH2_R 22U +#define XHC_ECHAIU__SCH2_WIDTH 2U +#define XHC_ECHAIU__SCH2_RESETVALUE 0x0U +#define XHC_ECHAIU__CHMS_L 21U +#define XHC_ECHAIU__CHMS_R 20U +#define XHC_ECHAIU__CHMS_WIDTH 2U +#define XHC_ECHAIU__CHMS_RESETVALUE 0x3U +#define XHC_ECHAIU__CHM2_L 19U +#define XHC_ECHAIU__CHM2_R 18U +#define XHC_ECHAIU__CHM2_WIDTH 2U +#define XHC_ECHAIU__CHM2_RESETVALUE 0x0U +#define XHC_ECHAIU__reserved_L 17U +#define XHC_ECHAIU__reserved_R 16U +#define XHC_ECHAIU__reserved_WIDTH 2U +#define XHC_ECHAIU__reserved_RESETVALUE 0x0U +#define XHC_ECHAIU__NCP_L 15U +#define XHC_ECHAIU__NCP_R 8U +#define XHC_ECHAIU__NCP_WIDTH 8U +#define XHC_ECHAIU__NCP_RESETVALUE 0x04U +#define XHC_ECHAIU__CID_L 7U +#define XHC_ECHAIU__CID_R 0U +#define XHC_ECHAIU__CID_WIDTH 8U +#define XHC_ECHAIU__CID_RESETVALUE 0xc2U +#define XHC_ECHAIU_WIDTH 32U +#define XHC_ECHAIU__WIDTH 32U +#define XHC_ECHAIU_ALL_L 31U +#define XHC_ECHAIU_ALL_R 0U +#define XHC_ECHAIU__ALL_L 31U +#define XHC_ECHAIU__ALL_R 0U +#define XHC_ECHAIU_DATAMASK 0xffffffffU +#define XHC_ECHAIU_RDWRMASK 0x00000000U +#define XHC_ECHAIU_RESETVALUE 0x403004c2U + +#define XHC_AIUDMA_OFFSET 0xc34U +#define XHC_AIUDMA_BASE 0xc34U +#define XHC_AIUDMA__WRMB_L 31U +#define XHC_AIUDMA__WRMB_R 28U +#define XHC_AIUDMA__WRMB_WIDTH 4U +#define XHC_AIUDMA__WRMB_RESETVALUE 0x0U +#define XHC_AIUDMA__WRD_L 27U +#define XHC_AIUDMA__WRD_R 26U +#define XHC_AIUDMA__WRD_WIDTH 2U +#define XHC_AIUDMA__WRD_RESETVALUE 0x0U +#define XHC_AIUDMA__WED_L 25U +#define XHC_AIUDMA__WED_R 24U +#define XHC_AIUDMA__WED_WIDTH 2U +#define XHC_AIUDMA__WED_RESETVALUE 0x0U +#define XHC_AIUDMA__WMS_L 23U +#define XHC_AIUDMA__WMS_R 22U +#define XHC_AIUDMA__WMS_WIDTH 2U +#define XHC_AIUDMA__WMS_RESETVALUE 0x0U +#define XHC_AIUDMA__WMI_L 21U +#define XHC_AIUDMA__WMI_R 20U +#define XHC_AIUDMA__WMI_WIDTH 2U +#define XHC_AIUDMA__WMI_RESETVALUE 0x0U +#define XHC_AIUDMA__WPF_L 19U +#define XHC_AIUDMA__WPF_R 16U +#define XHC_AIUDMA__WPF_WIDTH 4U +#define XHC_AIUDMA__WPF_RESETVALUE 0x6U +#define XHC_AIUDMA__RRMB_L 15U +#define XHC_AIUDMA__RRMB_R 12U +#define XHC_AIUDMA__RRMB_WIDTH 4U +#define XHC_AIUDMA__RRMB_RESETVALUE 0x0U +#define XHC_AIUDMA__RTD_L 11U +#define XHC_AIUDMA__RTD_R 10U +#define XHC_AIUDMA__RTD_WIDTH 2U +#define XHC_AIUDMA__RTD_RESETVALUE 0x0U +#define XHC_AIUDMA__RTF_L 9U +#define XHC_AIUDMA__RTF_R 8U +#define XHC_AIUDMA__RTF_WIDTH 2U +#define XHC_AIUDMA__RTF_RESETVALUE 0x0U +#define XHC_AIUDMA__RM_S_L 7U +#define XHC_AIUDMA__RM_S_R 6U +#define XHC_AIUDMA__RM_S_WIDTH 2U +#define XHC_AIUDMA__RM_S_RESETVALUE 0x0U +#define XHC_AIUDMA__TFBS_L 5U +#define XHC_AIUDMA__TFBS_R 3U +#define XHC_AIUDMA__TFBS_WIDTH 3U +#define XHC_AIUDMA__TFBS_RESETVALUE 0x0U +#define XHC_AIUDMA__reserved_L 2U +#define XHC_AIUDMA__reserved_R 0U +#define XHC_AIUDMA__reserved_WIDTH 3U +#define XHC_AIUDMA__reserved_RESETVALUE 0x0U +#define XHC_AIUDMA_WIDTH 32U +#define XHC_AIUDMA__WIDTH 32U +#define XHC_AIUDMA_ALL_L 31U +#define XHC_AIUDMA_ALL_R 0U +#define XHC_AIUDMA__ALL_L 31U +#define XHC_AIUDMA__ALL_R 0U +#define XHC_AIUDMA_DATAMASK 0xffffffffU +#define XHC_AIUDMA_RDWRMASK 0x00000000U +#define XHC_AIUDMA_RESETVALUE 0x00060000U + +#define XHC_AIUFLA_OFFSET 0xc38U +#define XHC_AIUFLA_BASE 0xc38U +#define XHC_AIUFLA__ACLK_L 31U +#define XHC_AIUFLA__ACLK_R 23U +#define XHC_AIUFLA__ACLK_WIDTH 9U +#define XHC_AIUFLA__ACLK_RESETVALUE 0x0U +#define XHC_AIUFLA__MFLV_L 22U +#define XHC_AIUFLA__MFLV_R 7U +#define XHC_AIUFLA__MFLV_WIDTH 16U +#define XHC_AIUFLA__MFLV_RESETVALUE 0x0000U +#define XHC_AIUFLA__NFC 6U +#define XHC_AIUFLA__NFC_L 6U +#define XHC_AIUFLA__NFC_R 6U +#define XHC_AIUFLA__NFC_WIDTH 1U +#define XHC_AIUFLA__NFC_RESETVALUE 0x1U +#define XHC_AIUFLA__FLADJ_L 5U +#define XHC_AIUFLA__FLADJ_R 0U +#define XHC_AIUFLA__FLADJ_WIDTH 6U +#define XHC_AIUFLA__FLADJ_RESETVALUE 0x20U +#define XHC_AIUFLA_WIDTH 32U +#define XHC_AIUFLA__WIDTH 32U +#define XHC_AIUFLA_ALL_L 31U +#define XHC_AIUFLA_ALL_R 0U +#define XHC_AIUFLA__ALL_L 31U +#define XHC_AIUFLA__ALL_R 0U +#define XHC_AIUFLA_DATAMASK 0xffffffffU +#define XHC_AIUFLA_RDWRMASK 0x00000000U +#define XHC_AIUFLA_RESETVALUE 0x00000060U + +#define XHC_AIUCFG_OFFSET 0xc3cU +#define XHC_AIUCFG_BASE 0xc3cU +#define XHC_AIUCFG__ISO_L 30U +#define XHC_AIUCFG__ISO_R 28U +#define XHC_AIUCFG__ISO_WIDTH 3U +#define XHC_AIUCFG__ISO_RESETVALUE 0x0U +#define XHC_AIUCFG__EPC_L 26U +#define XHC_AIUCFG__EPC_R 24U +#define XHC_AIUCFG__EPC_WIDTH 3U +#define XHC_AIUCFG__EPC_RESETVALUE 0x5U +#define XHC_AIUCFG__PTQ_L 22U +#define XHC_AIUCFG__PTQ_R 20U +#define XHC_AIUCFG__PTQ_WIDTH 3U +#define XHC_AIUCFG__PTQ_RESETVALUE 0x3U +#define XHC_AIUCFG__NTQ_L 18U +#define XHC_AIUCFG__NTQ_R 16U +#define XHC_AIUCFG__NTQ_WIDTH 3U +#define XHC_AIUCFG__NTQ_RESETVALUE 0x3U +#define XHC_AIUCFG__HID 15U +#define XHC_AIUCFG__HID_L 15U +#define XHC_AIUCFG__HID_R 15U +#define XHC_AIUCFG__HID_WIDTH 1U +#define XHC_AIUCFG__HID_RESETVALUE 0x0U +#define XHC_AIUCFG__EPS_L 14U +#define XHC_AIUCFG__EPS_R 12U +#define XHC_AIUCFG__EPS_WIDTH 3U +#define XHC_AIUCFG__EPS_RESETVALUE 0x0U +#define XHC_AIUCFG__reserved_L 11U +#define XHC_AIUCFG__reserved_R 9U +#define XHC_AIUCFG__reserved_WIDTH 3U +#define XHC_AIUCFG__reserved_RESETVALUE 0x0U +#define XHC_AIUCFG__PEP2_L 8U +#define XHC_AIUCFG__PEP2_R 6U +#define XHC_AIUCFG__PEP2_WIDTH 3U +#define XHC_AIUCFG__PEP2_RESETVALUE 0x4U +#define XHC_AIUCFG__MELADJ_L 5U +#define XHC_AIUCFG__MELADJ_R 0U +#define XHC_AIUCFG__MELADJ_WIDTH 6U +#define XHC_AIUCFG__MELADJ_RESETVALUE 0x0U +#define XHC_AIUCFG__RESERVED_0 31U +#define XHC_AIUCFG__RESERVED_0_L 31U +#define XHC_AIUCFG__RESERVED_0_R 31U +#define XHC_AIUCFG__RESERVED_1 27U +#define XHC_AIUCFG__RESERVED_1_L 27U +#define XHC_AIUCFG__RESERVED_1_R 27U +#define XHC_AIUCFG__RESERVED_2 23U +#define XHC_AIUCFG__RESERVED_2_L 23U +#define XHC_AIUCFG__RESERVED_2_R 23U +#define XHC_AIUCFG__RESERVED_3 19U +#define XHC_AIUCFG__RESERVED_3_L 19U +#define XHC_AIUCFG__RESERVED_3_R 19U +#define XHC_AIUCFG_WIDTH 31U +#define XHC_AIUCFG__WIDTH 31U +#define XHC_AIUCFG_ALL_L 30U +#define XHC_AIUCFG_ALL_R 0U +#define XHC_AIUCFG__ALL_L 30U +#define XHC_AIUCFG__ALL_R 0U +#define XHC_AIUCFG_DATAMASK 0x7777ffffU +#define XHC_AIUCFG_RDWRMASK 0x88880000U +#define XHC_AIUCFG_RESETVALUE 0x05330100U + +#define XHC_ECHFSC_OFFSET 0xc40U +#define XHC_ECHFSC_BASE 0xc40U +#define XHC_ECHFSC__reserved_L 31U +#define XHC_ECHFSC__reserved_R 24U +#define XHC_ECHFSC__reserved_WIDTH 8U +#define XHC_ECHFSC__reserved_RESETVALUE 0x00U +#define XHC_ECHFSC__WRMB_L 23U +#define XHC_ECHFSC__WRMB_R 20U +#define XHC_ECHFSC__WRMB_WIDTH 4U +#define XHC_ECHFSC__WRMB_RESETVALUE 0x0U +#define XHC_ECHFSC__RRMB_L 19U +#define XHC_ECHFSC__RRMB_R 16U +#define XHC_ECHFSC__RRMB_WIDTH 4U +#define XHC_ECHFSC__RRMB_RESETVALUE 0x0U +#define XHC_ECHFSC__NCP_L 15U +#define XHC_ECHFSC__NCP_R 8U +#define XHC_ECHFSC__NCP_WIDTH 8U +#define XHC_ECHFSC__NCP_RESETVALUE 0x50U +#define XHC_ECHFSC__CID_L 7U +#define XHC_ECHFSC__CID_R 0U +#define XHC_ECHFSC__CID_WIDTH 8U +#define XHC_ECHFSC__CID_RESETVALUE 0xc3U +#define XHC_ECHFSC_WIDTH 32U +#define XHC_ECHFSC__WIDTH 32U +#define XHC_ECHFSC_ALL_L 31U +#define XHC_ECHFSC_ALL_R 0U +#define XHC_ECHFSC__ALL_L 31U +#define XHC_ECHFSC__ALL_R 0U +#define XHC_ECHFSC_DATAMASK 0xffffffffU +#define XHC_ECHFSC_RDWRMASK 0x00000000U +#define XHC_ECHFSC_RESETVALUE 0x000050c3U + +#define XHC_FSCPOC_OFFSET 0xc54U +#define XHC_FSCPOC_BASE 0xc54U +#define XHC_FSCPOC__NCS_L 31U +#define XHC_FSCPOC__NCS_R 28U +#define XHC_FSCPOC__NCS_WIDTH 4U +#define XHC_FSCPOC__NCS_RESETVALUE 0x0U +#define XHC_FSCPOC__FSIZ_L 22U +#define XHC_FSCPOC__FSIZ_R 18U +#define XHC_FSCPOC__FSIZ_WIDTH 5U +#define XHC_FSCPOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSCPOC__PSIZ_L 16U +#define XHC_FSCPOC__PSIZ_R 12U +#define XHC_FSCPOC__PSIZ_WIDTH 5U +#define XHC_FSCPOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSCPOC__reserved_L 11U +#define XHC_FSCPOC__reserved_R 5U +#define XHC_FSCPOC__reserved_WIDTH 7U +#define XHC_FSCPOC__reserved_RESETVALUE 0x0U +#define XHC_FSCPOC__TSIZ_L 4U +#define XHC_FSCPOC__TSIZ_R 0U +#define XHC_FSCPOC__TSIZ_WIDTH 5U +#define XHC_FSCPOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCPOC__RESERVED_L 27U +#define XHC_FSCPOC__RESERVED_R 23U +#define XHC_FSCPOC_WIDTH 32U +#define XHC_FSCPOC__WIDTH 32U +#define XHC_FSCPOC_ALL_L 31U +#define XHC_FSCPOC_ALL_R 0U +#define XHC_FSCPOC__ALL_L 31U +#define XHC_FSCPOC__ALL_R 0U +#define XHC_FSCPOC_DATAMASK 0xf07dffffU +#define XHC_FSCPOC_RDWRMASK 0x0f820000U +#define XHC_FSCPOC_RESETVALUE 0x00000000U + +#define XHC_FSCGOC_OFFSET 0xc58U +#define XHC_FSCGOC_BASE 0xc58U +#define XHC_FSCGOC__NCS_L 31U +#define XHC_FSCGOC__NCS_R 28U +#define XHC_FSCGOC__NCS_WIDTH 4U +#define XHC_FSCGOC__NCS_RESETVALUE 0x0U +#define XHC_FSCGOC__FSIZ_L 22U +#define XHC_FSCGOC__FSIZ_R 18U +#define XHC_FSCGOC__FSIZ_WIDTH 5U +#define XHC_FSCGOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSCGOC__PSIZ_L 16U +#define XHC_FSCGOC__PSIZ_R 12U +#define XHC_FSCGOC__PSIZ_WIDTH 5U +#define XHC_FSCGOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSCGOC__reserved_L 11U +#define XHC_FSCGOC__reserved_R 5U +#define XHC_FSCGOC__reserved_WIDTH 7U +#define XHC_FSCGOC__reserved_RESETVALUE 0x0U +#define XHC_FSCGOC__TSIZ_L 4U +#define XHC_FSCGOC__TSIZ_R 0U +#define XHC_FSCGOC__TSIZ_WIDTH 5U +#define XHC_FSCGOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCGOC__RESERVED_L 27U +#define XHC_FSCGOC__RESERVED_R 23U +#define XHC_FSCGOC_WIDTH 32U +#define XHC_FSCGOC__WIDTH 32U +#define XHC_FSCGOC_ALL_L 31U +#define XHC_FSCGOC_ALL_R 0U +#define XHC_FSCGOC__ALL_L 31U +#define XHC_FSCGOC__ALL_R 0U +#define XHC_FSCGOC_DATAMASK 0xf07dffffU +#define XHC_FSCGOC_RDWRMASK 0x0f820000U +#define XHC_FSCGOC_RESETVALUE 0x00000000U + +#define XHC_FSCNOC_OFFSET 0xc5cU +#define XHC_FSCNOC_BASE 0xc5cU +#define XHC_FSCNOC__NCS_L 31U +#define XHC_FSCNOC__NCS_R 28U +#define XHC_FSCNOC__NCS_WIDTH 4U +#define XHC_FSCNOC__NCS_RESETVALUE 0x0U +#define XHC_FSCNOC__FSIZ_L 22U +#define XHC_FSCNOC__FSIZ_R 18U +#define XHC_FSCNOC__FSIZ_WIDTH 5U +#define XHC_FSCNOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSCNOC__PSIZ_L 16U +#define XHC_FSCNOC__PSIZ_R 12U +#define XHC_FSCNOC__PSIZ_WIDTH 5U +#define XHC_FSCNOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSCNOC__reserved_L 11U +#define XHC_FSCNOC__reserved_R 5U +#define XHC_FSCNOC__reserved_WIDTH 7U +#define XHC_FSCNOC__reserved_RESETVALUE 0x0U +#define XHC_FSCNOC__TSIZ_L 4U +#define XHC_FSCNOC__TSIZ_R 0U +#define XHC_FSCNOC__TSIZ_WIDTH 5U +#define XHC_FSCNOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCNOC__RESERVED_L 27U +#define XHC_FSCNOC__RESERVED_R 23U +#define XHC_FSCNOC_WIDTH 32U +#define XHC_FSCNOC__WIDTH 32U +#define XHC_FSCNOC_ALL_L 31U +#define XHC_FSCNOC_ALL_R 0U +#define XHC_FSCNOC__ALL_L 31U +#define XHC_FSCNOC__ALL_R 0U +#define XHC_FSCNOC_DATAMASK 0xf07dffffU +#define XHC_FSCNOC_RDWRMASK 0x0f820000U +#define XHC_FSCNOC_RESETVALUE 0x00000000U + +#define XHC_FSCAIC_OFFSET 0xc60U +#define XHC_FSCAIC_BASE 0xc60U +#define XHC_FSCAIC__FSIZ_L 22U +#define XHC_FSCAIC__FSIZ_R 18U +#define XHC_FSCAIC__FSIZ_WIDTH 5U +#define XHC_FSCAIC__FSIZ_RESETVALUE 0x0U +#define XHC_FSCAIC__PSIZ_L 16U +#define XHC_FSCAIC__PSIZ_R 12U +#define XHC_FSCAIC__PSIZ_WIDTH 5U +#define XHC_FSCAIC__PSIZ_RESETVALUE 0x0U +#define XHC_FSCAIC__reserved_L 11U +#define XHC_FSCAIC__reserved_R 0U +#define XHC_FSCAIC__reserved_WIDTH 12U +#define XHC_FSCAIC__reserved_RESETVALUE 0x000U +#define XHC_FSCAIC__RESERVED_L 31U +#define XHC_FSCAIC__RESERVED_R 23U +#define XHC_FSCAIC_WIDTH 23U +#define XHC_FSCAIC__WIDTH 23U +#define XHC_FSCAIC_ALL_L 22U +#define XHC_FSCAIC_ALL_R 0U +#define XHC_FSCAIC__ALL_L 22U +#define XHC_FSCAIC__ALL_R 0U +#define XHC_FSCAIC_DATAMASK 0x007dffffU +#define XHC_FSCAIC_RDWRMASK 0xff820000U +#define XHC_FSCAIC_RESETVALUE 0x000000U + +#define XHC_FSCPIC_OFFSET 0xc64U +#define XHC_FSCPIC_BASE 0xc64U +#define XHC_FSCPIC__NCS_L 31U +#define XHC_FSCPIC__NCS_R 28U +#define XHC_FSCPIC__NCS_WIDTH 4U +#define XHC_FSCPIC__NCS_RESETVALUE 0x0U +#define XHC_FSCPIC__reserved_L 27U +#define XHC_FSCPIC__reserved_R 5U +#define XHC_FSCPIC__reserved_WIDTH 23U +#define XHC_FSCPIC__reserved_RESETVALUE 0x0U +#define XHC_FSCPIC__TSIZ_L 4U +#define XHC_FSCPIC__TSIZ_R 0U +#define XHC_FSCPIC__TSIZ_WIDTH 5U +#define XHC_FSCPIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCPIC_WIDTH 32U +#define XHC_FSCPIC__WIDTH 32U +#define XHC_FSCPIC_ALL_L 31U +#define XHC_FSCPIC_ALL_R 0U +#define XHC_FSCPIC__ALL_L 31U +#define XHC_FSCPIC__ALL_R 0U +#define XHC_FSCPIC_DATAMASK 0xffffffffU +#define XHC_FSCPIC_RDWRMASK 0x00000000U +#define XHC_FSCPIC_RESETVALUE 0x00000000U + +#define XHC_FSCGIC_OFFSET 0xc68U +#define XHC_FSCGIC_BASE 0xc68U +#define XHC_FSCGIC__NCS_L 31U +#define XHC_FSCGIC__NCS_R 28U +#define XHC_FSCGIC__NCS_WIDTH 4U +#define XHC_FSCGIC__NCS_RESETVALUE 0x0U +#define XHC_FSCGIC__reserved_L 27U +#define XHC_FSCGIC__reserved_R 5U +#define XHC_FSCGIC__reserved_WIDTH 23U +#define XHC_FSCGIC__reserved_RESETVALUE 0x0U +#define XHC_FSCGIC__TSIZ_L 4U +#define XHC_FSCGIC__TSIZ_R 0U +#define XHC_FSCGIC__TSIZ_WIDTH 5U +#define XHC_FSCGIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCGIC_WIDTH 32U +#define XHC_FSCGIC__WIDTH 32U +#define XHC_FSCGIC_ALL_L 31U +#define XHC_FSCGIC_ALL_R 0U +#define XHC_FSCGIC__ALL_L 31U +#define XHC_FSCGIC__ALL_R 0U +#define XHC_FSCGIC_DATAMASK 0xffffffffU +#define XHC_FSCGIC_RDWRMASK 0x00000000U +#define XHC_FSCGIC_RESETVALUE 0x00000000U + +#define XHC_FSCNIC_OFFSET 0xc6cU +#define XHC_FSCNIC_BASE 0xc6cU +#define XHC_FSCNIC__NCS_L 31U +#define XHC_FSCNIC__NCS_R 28U +#define XHC_FSCNIC__NCS_WIDTH 4U +#define XHC_FSCNIC__NCS_RESETVALUE 0x0U +#define XHC_FSCNIC__reserved_L 27U +#define XHC_FSCNIC__reserved_R 5U +#define XHC_FSCNIC__reserved_WIDTH 23U +#define XHC_FSCNIC__reserved_RESETVALUE 0x0U +#define XHC_FSCNIC__TSIZ_L 4U +#define XHC_FSCNIC__TSIZ_R 0U +#define XHC_FSCNIC__TSIZ_WIDTH 5U +#define XHC_FSCNIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCNIC_WIDTH 32U +#define XHC_FSCNIC__WIDTH 32U +#define XHC_FSCNIC_ALL_L 31U +#define XHC_FSCNIC_ALL_R 0U +#define XHC_FSCNIC__ALL_L 31U +#define XHC_FSCNIC__ALL_R 0U +#define XHC_FSCNIC_DATAMASK 0xffffffffU +#define XHC_FSCNIC_RDWRMASK 0x00000000U +#define XHC_FSCNIC_RESETVALUE 0x00000000U + +#define XHC_ECHPRT_OFFSET 0xc70U +#define XHC_ECHPRT_BASE 0xc70U +#define XHC_ECHPRT__TDP 31U +#define XHC_ECHPRT__TDP_L 31U +#define XHC_ECHPRT__TDP_R 31U +#define XHC_ECHPRT__TDP_WIDTH 1U +#define XHC_ECHPRT__TDP_RESETVALUE 0x0U +#define XHC_ECHPRT__RDP 30U +#define XHC_ECHPRT__RDP_L 30U +#define XHC_ECHPRT__RDP_R 30U +#define XHC_ECHPRT__RDP_WIDTH 1U +#define XHC_ECHPRT__RDP_RESETVALUE 0x0U +#define XHC_ECHPRT__reserved_L 29U +#define XHC_ECHPRT__reserved_R 25U +#define XHC_ECHPRT__reserved_WIDTH 5U +#define XHC_ECHPRT__reserved_RESETVALUE 0x0U +#define XHC_ECHPRT__MFT_L 24U +#define XHC_ECHPRT__MFT_R 17U +#define XHC_ECHPRT__MFT_WIDTH 8U +#define XHC_ECHPRT__MFT_RESETVALUE 0x7dU +#define XHC_ECHPRT__HST 16U +#define XHC_ECHPRT__HST_L 16U +#define XHC_ECHPRT__HST_R 16U +#define XHC_ECHPRT__HST_WIDTH 1U +#define XHC_ECHPRT__HST_RESETVALUE 0x0U +#define XHC_ECHPRT__NCP_L 15U +#define XHC_ECHPRT__NCP_R 8U +#define XHC_ECHPRT__NCP_WIDTH 8U +#define XHC_ECHPRT__NCP_RESETVALUE 0x04U +#define XHC_ECHPRT__CID_L 7U +#define XHC_ECHPRT__CID_R 0U +#define XHC_ECHPRT__CID_WIDTH 8U +#define XHC_ECHPRT__CID_RESETVALUE 0xc4U +#define XHC_ECHPRT_WIDTH 32U +#define XHC_ECHPRT__WIDTH 32U +#define XHC_ECHPRT_ALL_L 31U +#define XHC_ECHPRT_ALL_R 0U +#define XHC_ECHPRT__ALL_L 31U +#define XHC_ECHPRT__ALL_R 0U +#define XHC_ECHPRT_DATAMASK 0xffffffffU +#define XHC_ECHPRT_RDWRMASK 0x00000000U +#define XHC_ECHPRT_RESETVALUE 0x00fa04c4U + +#define XHC_PRTHSC_OFFSET 0xc78U +#define XHC_PRTHSC_BASE 0xc78U +#define XHC_PRTHSC__TMR_L 31U +#define XHC_PRTHSC__TMR_R 16U +#define XHC_PRTHSC__TMR_WIDTH 16U +#define XHC_PRTHSC__TMR_RESETVALUE 0x0000U +#define XHC_PRTHSC__RSL_L 7U +#define XHC_PRTHSC__RSL_R 6U +#define XHC_PRTHSC__RSL_WIDTH 2U +#define XHC_PRTHSC__RSL_RESETVALUE 0x0U +#define XHC_PRTHSC__AS_M_L 5U +#define XHC_PRTHSC__AS_M_R 4U +#define XHC_PRTHSC__AS_M_WIDTH 2U +#define XHC_PRTHSC__AS_M_RESETVALUE 0x0U +#define XHC_PRTHSC__CMD_L 3U +#define XHC_PRTHSC__CMD_R 2U +#define XHC_PRTHSC__CMD_WIDTH 2U +#define XHC_PRTHSC__CMD_RESETVALUE 0x0U +#define XHC_PRTHSC__reserved 1U +#define XHC_PRTHSC__reserved_L 1U +#define XHC_PRTHSC__reserved_R 1U +#define XHC_PRTHSC__reserved_WIDTH 1U +#define XHC_PRTHSC__reserved_RESETVALUE 0x0U +#define XHC_PRTHSC__STB 0U +#define XHC_PRTHSC__STB_L 0U +#define XHC_PRTHSC__STB_R 0U +#define XHC_PRTHSC__STB_WIDTH 1U +#define XHC_PRTHSC__STB_RESETVALUE 0x0U +#define XHC_PRTHSC__RESERVED_L 15U +#define XHC_PRTHSC__RESERVED_R 8U +#define XHC_PRTHSC_WIDTH 32U +#define XHC_PRTHSC__WIDTH 32U +#define XHC_PRTHSC_ALL_L 31U +#define XHC_PRTHSC_ALL_R 0U +#define XHC_PRTHSC__ALL_L 31U +#define XHC_PRTHSC__ALL_R 0U +#define XHC_PRTHSC_DATAMASK 0xffff00ffU +#define XHC_PRTHSC_RDWRMASK 0x0000ff00U +#define XHC_PRTHSC_RESETVALUE 0x00000000U + +#define XHC_PRTHSR_OFFSET 0xc7cU +#define XHC_PRTHSR_BASE 0xc7cU +#define XHC_PRTHSR__RDLY_L 31U +#define XHC_PRTHSR__RDLY_R 24U +#define XHC_PRTHSR__RDLY_WIDTH 8U +#define XHC_PRTHSR__RDLY_RESETVALUE 0x00U +#define XHC_PRTHSR__TDPP_L 23U +#define XHC_PRTHSR__TDPP_R 16U +#define XHC_PRTHSR__TDPP_WIDTH 8U +#define XHC_PRTHSR__TDPP_RESETVALUE 0x00U +#define XHC_PRTHSR__RDPP_L 15U +#define XHC_PRTHSR__RDPP_R 8U +#define XHC_PRTHSR__RDPP_WIDTH 8U +#define XHC_PRTHSR__RDPP_RESETVALUE 0x00U +#define XHC_PRTHSR__TRTY_L 7U +#define XHC_PRTHSR__TRTY_R 0U +#define XHC_PRTHSR__TRTY_WIDTH 8U +#define XHC_PRTHSR__TRTY_RESETVALUE 0x00U +#define XHC_PRTHSR_WIDTH 32U +#define XHC_PRTHSR__WIDTH 32U +#define XHC_PRTHSR_ALL_L 31U +#define XHC_PRTHSR_ALL_R 0U +#define XHC_PRTHSR__ALL_L 31U +#define XHC_PRTHSR__ALL_R 0U +#define XHC_PRTHSR_DATAMASK 0xffffffffU +#define XHC_PRTHSR_RDWRMASK 0x00000000U +#define XHC_PRTHSR_RESETVALUE 0x00000000U + +#define XHC_ECHRHS_OFFSET 0xc80U +#define XHC_ECHRHS_BASE 0xc80U +#define XHC_ECHRHS__RPO_L 30U +#define XHC_ECHRHS__RPO_R 24U +#define XHC_ECHRHS__RPO_WIDTH 7U +#define XHC_ECHRHS__RPO_RESETVALUE 0x0U +#define XHC_ECHRHS__reserved_L 23U +#define XHC_ECHRHS__reserved_R 22U +#define XHC_ECHRHS__reserved_WIDTH 2U +#define XHC_ECHRHS__reserved_RESETVALUE 0x0U +#define XHC_ECHRHS__RPN_L 21U +#define XHC_ECHRHS__RPN_R 20U +#define XHC_ECHRHS__RPN_WIDTH 2U +#define XHC_ECHRHS__RPN_RESETVALUE 0x0U +#define XHC_ECHRHS__DNR_L 19U +#define XHC_ECHRHS__DNR_R 16U +#define XHC_ECHRHS__DNR_WIDTH 4U +#define XHC_ECHRHS__DNR_RESETVALUE 0x0U +#define XHC_ECHRHS__NCP_L 15U +#define XHC_ECHRHS__NCP_R 8U +#define XHC_ECHRHS__NCP_WIDTH 8U +#define XHC_ECHRHS__NCP_RESETVALUE 0x0cU +#define XHC_ECHRHS__CID_L 7U +#define XHC_ECHRHS__CID_R 0U +#define XHC_ECHRHS__CID_WIDTH 8U +#define XHC_ECHRHS__CID_RESETVALUE 0xc8U +#define XHC_ECHRHS__RESERVED 31U +#define XHC_ECHRHS__RESERVED_L 31U +#define XHC_ECHRHS__RESERVED_R 31U +#define XHC_ECHRHS_WIDTH 31U +#define XHC_ECHRHS__WIDTH 31U +#define XHC_ECHRHS_ALL_L 30U +#define XHC_ECHRHS_ALL_R 0U +#define XHC_ECHRHS__ALL_L 30U +#define XHC_ECHRHS__ALL_R 0U +#define XHC_ECHRHS_DATAMASK 0x7fffffffU +#define XHC_ECHRHS_RDWRMASK 0x80000000U +#define XHC_ECHRHS_RESETVALUE 0x00000cc8U + +#define XHC_RHSDES_OFFSET 0xc84U +#define XHC_RHSDES_BASE 0xc84U +#define XHC_RHSDES__PIS3_L 31U +#define XHC_RHSDES__PIS3_R 30U +#define XHC_RHSDES__PIS3_WIDTH 2U +#define XHC_RHSDES__PIS3_RESETVALUE 0x0U +#define XHC_RHSDES__HIST3 24U +#define XHC_RHSDES__HIST3_L 24U +#define XHC_RHSDES__HIST3_R 24U +#define XHC_RHSDES__HIST3_WIDTH 1U +#define XHC_RHSDES__HIST3_RESETVALUE 0x0U +#define XHC_RHSDES__PIS2_L 23U +#define XHC_RHSDES__PIS2_R 22U +#define XHC_RHSDES__PIS2_WIDTH 2U +#define XHC_RHSDES__PIS2_RESETVALUE 0x0U +#define XHC_RHSDES__HIST2 16U +#define XHC_RHSDES__HIST2_L 16U +#define XHC_RHSDES__HIST2_R 16U +#define XHC_RHSDES__HIST2_WIDTH 1U +#define XHC_RHSDES__HIST2_RESETVALUE 0x0U +#define XHC_RHSDES__PIS1_L 15U +#define XHC_RHSDES__PIS1_R 14U +#define XHC_RHSDES__PIS1_WIDTH 2U +#define XHC_RHSDES__PIS1_RESETVALUE 0x0U +#define XHC_RHSDES__HIST1 8U +#define XHC_RHSDES__HIST1_L 8U +#define XHC_RHSDES__HIST1_R 8U +#define XHC_RHSDES__HIST1_WIDTH 1U +#define XHC_RHSDES__HIST1_RESETVALUE 0x0U +#define XHC_RHSDES__PIS0_L 7U +#define XHC_RHSDES__PIS0_R 6U +#define XHC_RHSDES__PIS0_WIDTH 2U +#define XHC_RHSDES__PIS0_RESETVALUE 0x0U +#define XHC_RHSDES__reserved_L 5U +#define XHC_RHSDES__reserved_R 1U +#define XHC_RHSDES__reserved_WIDTH 5U +#define XHC_RHSDES__reserved_RESETVALUE 0x0U +#define XHC_RHSDES__HIST0 0U +#define XHC_RHSDES__HIST0_L 0U +#define XHC_RHSDES__HIST0_R 0U +#define XHC_RHSDES__HIST0_WIDTH 1U +#define XHC_RHSDES__HIST0_RESETVALUE 0x0U +#define XHC_RHSDES__RESERVED_0_L 29U +#define XHC_RHSDES__RESERVED_0_R 25U +#define XHC_RHSDES__RESERVED_1_L 21U +#define XHC_RHSDES__RESERVED_1_R 17U +#define XHC_RHSDES__RESERVED_2_L 13U +#define XHC_RHSDES__RESERVED_2_R 9U +#define XHC_RHSDES__RESERVED_L 29U +#define XHC_RHSDES__RESERVED_R 25U +#define XHC_RHSDES_WIDTH 32U +#define XHC_RHSDES__WIDTH 32U +#define XHC_RHSDES_ALL_L 31U +#define XHC_RHSDES_ALL_R 0U +#define XHC_RHSDES__ALL_L 31U +#define XHC_RHSDES__ALL_R 0U +#define XHC_RHSDES_DATAMASK 0xc1c1c1ffU +#define XHC_RHSDES_RDWRMASK 0x3e3e3e00U +#define XHC_RHSDES_RESETVALUE 0x00000000U + +#define XHC_RHSHSC0_OFFSET 0xc90U +#define XHC_RHSHSC0_BASE 0xc90U +#define XHC_RHSHSC0__TMR_L 31U +#define XHC_RHSHSC0__TMR_R 16U +#define XHC_RHSHSC0__TMR_WIDTH 16U +#define XHC_RHSHSC0__TMR_RESETVALUE 0x0000U +#define XHC_RHSHSC0__RSL_L 7U +#define XHC_RHSHSC0__RSL_R 6U +#define XHC_RHSHSC0__RSL_WIDTH 2U +#define XHC_RHSHSC0__RSL_RESETVALUE 0x0U +#define XHC_RHSHSC0__AS_M_L 5U +#define XHC_RHSHSC0__AS_M_R 4U +#define XHC_RHSHSC0__AS_M_WIDTH 2U +#define XHC_RHSHSC0__AS_M_RESETVALUE 0x0U +#define XHC_RHSHSC0__CMD_L 3U +#define XHC_RHSHSC0__CMD_R 2U +#define XHC_RHSHSC0__CMD_WIDTH 2U +#define XHC_RHSHSC0__CMD_RESETVALUE 0x0U +#define XHC_RHSHSC0__reserved 1U +#define XHC_RHSHSC0__reserved_L 1U +#define XHC_RHSHSC0__reserved_R 1U +#define XHC_RHSHSC0__reserved_WIDTH 1U +#define XHC_RHSHSC0__reserved_RESETVALUE 0x0U +#define XHC_RHSHSC0__STB 0U +#define XHC_RHSHSC0__STB_L 0U +#define XHC_RHSHSC0__STB_R 0U +#define XHC_RHSHSC0__STB_WIDTH 1U +#define XHC_RHSHSC0__STB_RESETVALUE 0x0U +#define XHC_RHSHSC0__RESERVED_L 15U +#define XHC_RHSHSC0__RESERVED_R 8U +#define XHC_RHSHSC0_WIDTH 32U +#define XHC_RHSHSC0__WIDTH 32U +#define XHC_RHSHSC0_ALL_L 31U +#define XHC_RHSHSC0_ALL_R 0U +#define XHC_RHSHSC0__ALL_L 31U +#define XHC_RHSHSC0__ALL_R 0U +#define XHC_RHSHSC0_DATAMASK 0xffff00ffU +#define XHC_RHSHSC0_RDWRMASK 0x0000ff00U +#define XHC_RHSHSC0_RESETVALUE 0x00000000U + +#define XHC_RHSHSR0_OFFSET 0xc94U +#define XHC_RHSHSR0_BASE 0xc94U +#define XHC_RHSHSR0__C2U_L 31U +#define XHC_RHSHSR0__C2U_R 24U +#define XHC_RHSHSR0__C2U_WIDTH 8U +#define XHC_RHSHSR0__C2U_RESETVALUE 0x00U +#define XHC_RHSHSR0__C1U_L 23U +#define XHC_RHSHSR0__C1U_R 16U +#define XHC_RHSHSR0__C1U_WIDTH 8U +#define XHC_RHSHSR0__C1U_RESETVALUE 0x00U +#define XHC_RHSHSR0__RCV_L 15U +#define XHC_RHSHSR0__RCV_R 8U +#define XHC_RHSHSR0__RCV_WIDTH 8U +#define XHC_RHSHSR0__RCV_RESETVALUE 0x00U +#define XHC_RHSHSR0__RTY_L 7U +#define XHC_RHSHSR0__RTY_R 0U +#define XHC_RHSHSR0__RTY_WIDTH 8U +#define XHC_RHSHSR0__RTY_RESETVALUE 0x00U +#define XHC_RHSHSR0_WIDTH 32U +#define XHC_RHSHSR0__WIDTH 32U +#define XHC_RHSHSR0_ALL_L 31U +#define XHC_RHSHSR0_ALL_R 0U +#define XHC_RHSHSR0__ALL_L 31U +#define XHC_RHSHSR0__ALL_R 0U +#define XHC_RHSHSR0_DATAMASK 0xffffffffU +#define XHC_RHSHSR0_RDWRMASK 0x00000000U +#define XHC_RHSHSR0_RESETVALUE 0x00000000U + +#define XHC_RHSHSC1_OFFSET 0xc98U +#define XHC_RHSHSC1_BASE 0xc98U +#define XHC_RHSHSC1__TMR_L 31U +#define XHC_RHSHSC1__TMR_R 16U +#define XHC_RHSHSC1__TMR_WIDTH 16U +#define XHC_RHSHSC1__TMR_RESETVALUE 0x0000U +#define XHC_RHSHSC1__RSL_L 7U +#define XHC_RHSHSC1__RSL_R 6U +#define XHC_RHSHSC1__RSL_WIDTH 2U +#define XHC_RHSHSC1__RSL_RESETVALUE 0x0U +#define XHC_RHSHSC1__AS_M_L 5U +#define XHC_RHSHSC1__AS_M_R 4U +#define XHC_RHSHSC1__AS_M_WIDTH 2U +#define XHC_RHSHSC1__AS_M_RESETVALUE 0x0U +#define XHC_RHSHSC1__CMD_L 3U +#define XHC_RHSHSC1__CMD_R 2U +#define XHC_RHSHSC1__CMD_WIDTH 2U +#define XHC_RHSHSC1__CMD_RESETVALUE 0x0U +#define XHC_RHSHSC1__reserved 1U +#define XHC_RHSHSC1__reserved_L 1U +#define XHC_RHSHSC1__reserved_R 1U +#define XHC_RHSHSC1__reserved_WIDTH 1U +#define XHC_RHSHSC1__reserved_RESETVALUE 0x0U +#define XHC_RHSHSC1__STB 0U +#define XHC_RHSHSC1__STB_L 0U +#define XHC_RHSHSC1__STB_R 0U +#define XHC_RHSHSC1__STB_WIDTH 1U +#define XHC_RHSHSC1__STB_RESETVALUE 0x0U +#define XHC_RHSHSC1__RESERVED_L 15U +#define XHC_RHSHSC1__RESERVED_R 8U +#define XHC_RHSHSC1_WIDTH 32U +#define XHC_RHSHSC1__WIDTH 32U +#define XHC_RHSHSC1_ALL_L 31U +#define XHC_RHSHSC1_ALL_R 0U +#define XHC_RHSHSC1__ALL_L 31U +#define XHC_RHSHSC1__ALL_R 0U +#define XHC_RHSHSC1_DATAMASK 0xffff00ffU +#define XHC_RHSHSC1_RDWRMASK 0x0000ff00U +#define XHC_RHSHSC1_RESETVALUE 0x00000000U + +#define XHC_RHSHSR1_OFFSET 0xc9cU +#define XHC_RHSHSR1_BASE 0xc9cU +#define XHC_RHSHSR1__C2U_L 31U +#define XHC_RHSHSR1__C2U_R 24U +#define XHC_RHSHSR1__C2U_WIDTH 8U +#define XHC_RHSHSR1__C2U_RESETVALUE 0x00U +#define XHC_RHSHSR1__C1U_L 23U +#define XHC_RHSHSR1__C1U_R 16U +#define XHC_RHSHSR1__C1U_WIDTH 8U +#define XHC_RHSHSR1__C1U_RESETVALUE 0x00U +#define XHC_RHSHSR1__RCV_L 15U +#define XHC_RHSHSR1__RCV_R 8U +#define XHC_RHSHSR1__RCV_WIDTH 8U +#define XHC_RHSHSR1__RCV_RESETVALUE 0x00U +#define XHC_RHSHSR1__RTY_L 7U +#define XHC_RHSHSR1__RTY_R 0U +#define XHC_RHSHSR1__RTY_WIDTH 8U +#define XHC_RHSHSR1__RTY_RESETVALUE 0x00U +#define XHC_RHSHSR1_WIDTH 32U +#define XHC_RHSHSR1__WIDTH 32U +#define XHC_RHSHSR1_ALL_L 31U +#define XHC_RHSHSR1_ALL_R 0U +#define XHC_RHSHSR1__ALL_L 31U +#define XHC_RHSHSR1__ALL_R 0U +#define XHC_RHSHSR1_DATAMASK 0xffffffffU +#define XHC_RHSHSR1_RDWRMASK 0x00000000U +#define XHC_RHSHSR1_RESETVALUE 0x00000000U + +#define XHC_RHSHSC2_OFFSET 0xca0U +#define XHC_RHSHSC2_BASE 0xca0U +#define XHC_RHSHSC2__TMR_L 31U +#define XHC_RHSHSC2__TMR_R 16U +#define XHC_RHSHSC2__TMR_WIDTH 16U +#define XHC_RHSHSC2__TMR_RESETVALUE 0x0000U +#define XHC_RHSHSC2__RSL_L 7U +#define XHC_RHSHSC2__RSL_R 6U +#define XHC_RHSHSC2__RSL_WIDTH 2U +#define XHC_RHSHSC2__RSL_RESETVALUE 0x0U +#define XHC_RHSHSC2__AS_M_L 5U +#define XHC_RHSHSC2__AS_M_R 4U +#define XHC_RHSHSC2__AS_M_WIDTH 2U +#define XHC_RHSHSC2__AS_M_RESETVALUE 0x0U +#define XHC_RHSHSC2__CMD_L 3U +#define XHC_RHSHSC2__CMD_R 2U +#define XHC_RHSHSC2__CMD_WIDTH 2U +#define XHC_RHSHSC2__CMD_RESETVALUE 0x0U +#define XHC_RHSHSC2__reserved 1U +#define XHC_RHSHSC2__reserved_L 1U +#define XHC_RHSHSC2__reserved_R 1U +#define XHC_RHSHSC2__reserved_WIDTH 1U +#define XHC_RHSHSC2__reserved_RESETVALUE 0x0U +#define XHC_RHSHSC2__STB 0U +#define XHC_RHSHSC2__STB_L 0U +#define XHC_RHSHSC2__STB_R 0U +#define XHC_RHSHSC2__STB_WIDTH 1U +#define XHC_RHSHSC2__STB_RESETVALUE 0x0U +#define XHC_RHSHSC2__RESERVED_L 15U +#define XHC_RHSHSC2__RESERVED_R 8U +#define XHC_RHSHSC2_WIDTH 32U +#define XHC_RHSHSC2__WIDTH 32U +#define XHC_RHSHSC2_ALL_L 31U +#define XHC_RHSHSC2_ALL_R 0U +#define XHC_RHSHSC2__ALL_L 31U +#define XHC_RHSHSC2__ALL_R 0U +#define XHC_RHSHSC2_DATAMASK 0xffff00ffU +#define XHC_RHSHSC2_RDWRMASK 0x0000ff00U +#define XHC_RHSHSC2_RESETVALUE 0x00000000U + +#define XHC_RHSHSR2_OFFSET 0xca4U +#define XHC_RHSHSR2_BASE 0xca4U +#define XHC_RHSHSR2__C2U_L 31U +#define XHC_RHSHSR2__C2U_R 24U +#define XHC_RHSHSR2__C2U_WIDTH 8U +#define XHC_RHSHSR2__C2U_RESETVALUE 0x00U +#define XHC_RHSHSR2__C1U_L 23U +#define XHC_RHSHSR2__C1U_R 16U +#define XHC_RHSHSR2__C1U_WIDTH 8U +#define XHC_RHSHSR2__C1U_RESETVALUE 0x00U +#define XHC_RHSHSR2__RCV_L 15U +#define XHC_RHSHSR2__RCV_R 8U +#define XHC_RHSHSR2__RCV_WIDTH 8U +#define XHC_RHSHSR2__RCV_RESETVALUE 0x00U +#define XHC_RHSHSR2__RTY_L 7U +#define XHC_RHSHSR2__RTY_R 0U +#define XHC_RHSHSR2__RTY_WIDTH 8U +#define XHC_RHSHSR2__RTY_RESETVALUE 0x00U +#define XHC_RHSHSR2_WIDTH 32U +#define XHC_RHSHSR2__WIDTH 32U +#define XHC_RHSHSR2_ALL_L 31U +#define XHC_RHSHSR2_ALL_R 0U +#define XHC_RHSHSR2__ALL_L 31U +#define XHC_RHSHSR2__ALL_R 0U +#define XHC_RHSHSR2_DATAMASK 0xffffffffU +#define XHC_RHSHSR2_RDWRMASK 0x00000000U +#define XHC_RHSHSR2_RESETVALUE 0x00000000U + +#define XHC_RHSHSC3_OFFSET 0xca8U +#define XHC_RHSHSC3_BASE 0xca8U +#define XHC_RHSHSC3__TMR_L 31U +#define XHC_RHSHSC3__TMR_R 16U +#define XHC_RHSHSC3__TMR_WIDTH 16U +#define XHC_RHSHSC3__TMR_RESETVALUE 0x0000U +#define XHC_RHSHSC3__RSL_L 7U +#define XHC_RHSHSC3__RSL_R 6U +#define XHC_RHSHSC3__RSL_WIDTH 2U +#define XHC_RHSHSC3__RSL_RESETVALUE 0x0U +#define XHC_RHSHSC3__AS_M_L 5U +#define XHC_RHSHSC3__AS_M_R 4U +#define XHC_RHSHSC3__AS_M_WIDTH 2U +#define XHC_RHSHSC3__AS_M_RESETVALUE 0x0U +#define XHC_RHSHSC3__CMD_L 3U +#define XHC_RHSHSC3__CMD_R 2U +#define XHC_RHSHSC3__CMD_WIDTH 2U +#define XHC_RHSHSC3__CMD_RESETVALUE 0x0U +#define XHC_RHSHSC3__reserved 1U +#define XHC_RHSHSC3__reserved_L 1U +#define XHC_RHSHSC3__reserved_R 1U +#define XHC_RHSHSC3__reserved_WIDTH 1U +#define XHC_RHSHSC3__reserved_RESETVALUE 0x0U +#define XHC_RHSHSC3__STB 0U +#define XHC_RHSHSC3__STB_L 0U +#define XHC_RHSHSC3__STB_R 0U +#define XHC_RHSHSC3__STB_WIDTH 1U +#define XHC_RHSHSC3__STB_RESETVALUE 0x0U +#define XHC_RHSHSC3__RESERVED_L 15U +#define XHC_RHSHSC3__RESERVED_R 8U +#define XHC_RHSHSC3_WIDTH 32U +#define XHC_RHSHSC3__WIDTH 32U +#define XHC_RHSHSC3_ALL_L 31U +#define XHC_RHSHSC3_ALL_R 0U +#define XHC_RHSHSC3__ALL_L 31U +#define XHC_RHSHSC3__ALL_R 0U +#define XHC_RHSHSC3_DATAMASK 0xffff00ffU +#define XHC_RHSHSC3_RDWRMASK 0x0000ff00U +#define XHC_RHSHSC3_RESETVALUE 0x00000000U + +#define XHC_RHSHSR3_OFFSET 0xcacU +#define XHC_RHSHSR3_BASE 0xcacU +#define XHC_RHSHSR3__C2U_L 31U +#define XHC_RHSHSR3__C2U_R 24U +#define XHC_RHSHSR3__C2U_WIDTH 8U +#define XHC_RHSHSR3__C2U_RESETVALUE 0x00U +#define XHC_RHSHSR3__C1U_L 23U +#define XHC_RHSHSR3__C1U_R 16U +#define XHC_RHSHSR3__C1U_WIDTH 8U +#define XHC_RHSHSR3__C1U_RESETVALUE 0x00U +#define XHC_RHSHSR3__RCV_L 15U +#define XHC_RHSHSR3__RCV_R 8U +#define XHC_RHSHSR3__RCV_WIDTH 8U +#define XHC_RHSHSR3__RCV_RESETVALUE 0x00U +#define XHC_RHSHSR3__RTY_L 7U +#define XHC_RHSHSR3__RTY_R 0U +#define XHC_RHSHSR3__RTY_WIDTH 8U +#define XHC_RHSHSR3__RTY_RESETVALUE 0x00U +#define XHC_RHSHSR3_WIDTH 32U +#define XHC_RHSHSR3__WIDTH 32U +#define XHC_RHSHSR3_ALL_L 31U +#define XHC_RHSHSR3_ALL_R 0U +#define XHC_RHSHSR3__ALL_L 31U +#define XHC_RHSHSR3__ALL_R 0U +#define XHC_RHSHSR3_DATAMASK 0xffffffffU +#define XHC_RHSHSR3_RDWRMASK 0x00000000U +#define XHC_RHSHSR3_RESETVALUE 0x00000000U + +#define XHC_ECHSSP_OFFSET 0xcb0U +#define XHC_ECHSSP_BASE 0xcb0U +#define XHC_ECHSSP__reserved_L 31U +#define XHC_ECHSSP__reserved_R 16U +#define XHC_ECHSSP__reserved_WIDTH 16U +#define XHC_ECHSSP__reserved_RESETVALUE 0x0000U +#define XHC_ECHSSP__NCP_L 15U +#define XHC_ECHSSP__NCP_R 8U +#define XHC_ECHSSP__NCP_WIDTH 8U +#define XHC_ECHSSP__NCP_RESETVALUE 0x04U +#define XHC_ECHSSP__CID_L 7U +#define XHC_ECHSSP__CID_R 0U +#define XHC_ECHSSP__CID_WIDTH 8U +#define XHC_ECHSSP__CID_RESETVALUE 0xc6U +#define XHC_ECHSSP_WIDTH 32U +#define XHC_ECHSSP__WIDTH 32U +#define XHC_ECHSSP_ALL_L 31U +#define XHC_ECHSSP_ALL_R 0U +#define XHC_ECHSSP__ALL_L 31U +#define XHC_ECHSSP__ALL_R 0U +#define XHC_ECHSSP_DATAMASK 0xffffffffU +#define XHC_ECHSSP_RDWRMASK 0x00000000U +#define XHC_ECHSSP_RESETVALUE 0x000004c6U + +#define XHC_SSPVER_OFFSET 0xcb4U +#define XHC_SSPVER_BASE 0xcb4U +#define XHC_SSPVER__MAJ_L 31U +#define XHC_SSPVER__MAJ_R 28U +#define XHC_SSPVER__MAJ_WIDTH 4U +#define XHC_SSPVER__MAJ_RESETVALUE 0x0U +#define XHC_SSPVER__MIN_L 27U +#define XHC_SSPVER__MIN_R 24U +#define XHC_SSPVER__MIN_WIDTH 4U +#define XHC_SSPVER__MIN_RESETVALUE 0x0U +#define XHC_SSPVER__RLS_L 23U +#define XHC_SSPVER__RLS_R 20U +#define XHC_SSPVER__RLS_WIDTH 4U +#define XHC_SSPVER__RLS_RESETVALUE 0x0U +#define XHC_SSPVER__reserved_L 19U +#define XHC_SSPVER__reserved_R 0U +#define XHC_SSPVER__reserved_WIDTH 20U +#define XHC_SSPVER__reserved_RESETVALUE 0x00000U +#define XHC_SSPVER_WIDTH 32U +#define XHC_SSPVER__WIDTH 32U +#define XHC_SSPVER_ALL_L 31U +#define XHC_SSPVER_ALL_R 0U +#define XHC_SSPVER__ALL_L 31U +#define XHC_SSPVER__ALL_R 0U +#define XHC_SSPVER_DATAMASK 0xffffffffU +#define XHC_SSPVER_RDWRMASK 0x00000000U +#define XHC_SSPVER_RESETVALUE 0x00000000U + +#define XHC_SSPMGN_OFFSET 0xcb8U +#define XHC_SSPMGN_BASE 0xcb8U +#define XHC_SSPMGN__MGN_L 31U +#define XHC_SSPMGN__MGN_R 0U +#define XHC_SSPMGN__MGN_WIDTH 32U +#define XHC_SSPMGN__MGN_RESETVALUE 0x4b535040U +#define XHC_SSPMGN_WIDTH 32U +#define XHC_SSPMGN__WIDTH 32U +#define XHC_SSPMGN_ALL_L 31U +#define XHC_SSPMGN_ALL_R 0U +#define XHC_SSPMGN__ALL_L 31U +#define XHC_SSPMGN__ALL_R 0U +#define XHC_SSPMGN_DATAMASK 0xffffffffU +#define XHC_SSPMGN_RDWRMASK 0x00000000U +#define XHC_SSPMGN_RESETVALUE 0x4b535040U + +#define XHC_ECHFSC2_OFFSET 0xcc0U +#define XHC_ECHFSC2_BASE 0xcc0U +#define XHC_ECHFSC2__reserved_L 31U +#define XHC_ECHFSC2__reserved_R 16U +#define XHC_ECHFSC2__reserved_WIDTH 16U +#define XHC_ECHFSC2__reserved_RESETVALUE 0x0000U +#define XHC_ECHFSC2__NCP_L 15U +#define XHC_ECHFSC2__NCP_R 8U +#define XHC_ECHFSC2__NCP_WIDTH 8U +#define XHC_ECHFSC2__NCP_RESETVALUE 0x50U +#define XHC_ECHFSC2__CID_L 7U +#define XHC_ECHFSC2__CID_R 0U +#define XHC_ECHFSC2__CID_WIDTH 8U +#define XHC_ECHFSC2__CID_RESETVALUE 0xc7U +#define XHC_ECHFSC2_WIDTH 32U +#define XHC_ECHFSC2__WIDTH 32U +#define XHC_ECHFSC2_ALL_L 31U +#define XHC_ECHFSC2_ALL_R 0U +#define XHC_ECHFSC2__ALL_L 31U +#define XHC_ECHFSC2__ALL_R 0U +#define XHC_ECHFSC2_DATAMASK 0xffffffffU +#define XHC_ECHFSC2_RDWRMASK 0x00000000U +#define XHC_ECHFSC2_RESETVALUE 0x000050c7U + +#define XHC_FSC2POC_OFFSET 0xcd4U +#define XHC_FSC2POC_BASE 0xcd4U +#define XHC_FSC2POC__NCS_L 31U +#define XHC_FSC2POC__NCS_R 28U +#define XHC_FSC2POC__NCS_WIDTH 4U +#define XHC_FSC2POC__NCS_RESETVALUE 0x0U +#define XHC_FSC2POC__FSIZ_L 22U +#define XHC_FSC2POC__FSIZ_R 18U +#define XHC_FSC2POC__FSIZ_WIDTH 5U +#define XHC_FSC2POC__FSIZ_RESETVALUE 0x0U +#define XHC_FSC2POC__PSIZ_L 16U +#define XHC_FSC2POC__PSIZ_R 12U +#define XHC_FSC2POC__PSIZ_WIDTH 5U +#define XHC_FSC2POC__PSIZ_RESETVALUE 0x0U +#define XHC_FSC2POC__reserved_L 11U +#define XHC_FSC2POC__reserved_R 5U +#define XHC_FSC2POC__reserved_WIDTH 7U +#define XHC_FSC2POC__reserved_RESETVALUE 0x0U +#define XHC_FSC2POC__TSIZ_L 4U +#define XHC_FSC2POC__TSIZ_R 0U +#define XHC_FSC2POC__TSIZ_WIDTH 5U +#define XHC_FSC2POC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2POC__RESERVED_L 27U +#define XHC_FSC2POC__RESERVED_R 23U +#define XHC_FSC2POC_WIDTH 32U +#define XHC_FSC2POC__WIDTH 32U +#define XHC_FSC2POC_ALL_L 31U +#define XHC_FSC2POC_ALL_R 0U +#define XHC_FSC2POC__ALL_L 31U +#define XHC_FSC2POC__ALL_R 0U +#define XHC_FSC2POC_DATAMASK 0xf07dffffU +#define XHC_FSC2POC_RDWRMASK 0x0f820000U +#define XHC_FSC2POC_RESETVALUE 0x00000000U + +#define XHC_FSC2GOC_OFFSET 0xcd8U +#define XHC_FSC2GOC_BASE 0xcd8U +#define XHC_FSC2GOC__NCS_L 31U +#define XHC_FSC2GOC__NCS_R 28U +#define XHC_FSC2GOC__NCS_WIDTH 4U +#define XHC_FSC2GOC__NCS_RESETVALUE 0x0U +#define XHC_FSC2GOC__FSIZ_L 22U +#define XHC_FSC2GOC__FSIZ_R 18U +#define XHC_FSC2GOC__FSIZ_WIDTH 5U +#define XHC_FSC2GOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSC2GOC__PSIZ_L 16U +#define XHC_FSC2GOC__PSIZ_R 12U +#define XHC_FSC2GOC__PSIZ_WIDTH 5U +#define XHC_FSC2GOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSC2GOC__reserved_L 11U +#define XHC_FSC2GOC__reserved_R 5U +#define XHC_FSC2GOC__reserved_WIDTH 7U +#define XHC_FSC2GOC__reserved_RESETVALUE 0x0U +#define XHC_FSC2GOC__TSIZ_L 4U +#define XHC_FSC2GOC__TSIZ_R 0U +#define XHC_FSC2GOC__TSIZ_WIDTH 5U +#define XHC_FSC2GOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2GOC__RESERVED_L 27U +#define XHC_FSC2GOC__RESERVED_R 23U +#define XHC_FSC2GOC_WIDTH 32U +#define XHC_FSC2GOC__WIDTH 32U +#define XHC_FSC2GOC_ALL_L 31U +#define XHC_FSC2GOC_ALL_R 0U +#define XHC_FSC2GOC__ALL_L 31U +#define XHC_FSC2GOC__ALL_R 0U +#define XHC_FSC2GOC_DATAMASK 0xf07dffffU +#define XHC_FSC2GOC_RDWRMASK 0x0f820000U +#define XHC_FSC2GOC_RESETVALUE 0x00000000U + +#define XHC_FSC2NOC_OFFSET 0xcdcU +#define XHC_FSC2NOC_BASE 0xcdcU +#define XHC_FSC2NOC__NCS_L 31U +#define XHC_FSC2NOC__NCS_R 28U +#define XHC_FSC2NOC__NCS_WIDTH 4U +#define XHC_FSC2NOC__NCS_RESETVALUE 0x0U +#define XHC_FSC2NOC__FSIZ_L 22U +#define XHC_FSC2NOC__FSIZ_R 18U +#define XHC_FSC2NOC__FSIZ_WIDTH 5U +#define XHC_FSC2NOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSC2NOC__PSIZ_L 16U +#define XHC_FSC2NOC__PSIZ_R 12U +#define XHC_FSC2NOC__PSIZ_WIDTH 5U +#define XHC_FSC2NOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSC2NOC__reserved_L 11U +#define XHC_FSC2NOC__reserved_R 5U +#define XHC_FSC2NOC__reserved_WIDTH 7U +#define XHC_FSC2NOC__reserved_RESETVALUE 0x0U +#define XHC_FSC2NOC__TSIZ_L 4U +#define XHC_FSC2NOC__TSIZ_R 0U +#define XHC_FSC2NOC__TSIZ_WIDTH 5U +#define XHC_FSC2NOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2NOC__RESERVED_L 27U +#define XHC_FSC2NOC__RESERVED_R 23U +#define XHC_FSC2NOC_WIDTH 32U +#define XHC_FSC2NOC__WIDTH 32U +#define XHC_FSC2NOC_ALL_L 31U +#define XHC_FSC2NOC_ALL_R 0U +#define XHC_FSC2NOC__ALL_L 31U +#define XHC_FSC2NOC__ALL_R 0U +#define XHC_FSC2NOC_DATAMASK 0xf07dffffU +#define XHC_FSC2NOC_RDWRMASK 0x0f820000U +#define XHC_FSC2NOC_RESETVALUE 0x00000000U + +#define XHC_FSC2AIC_OFFSET 0xce0U +#define XHC_FSC2AIC_BASE 0xce0U +#define XHC_FSC2AIC__FSIZ_L 22U +#define XHC_FSC2AIC__FSIZ_R 18U +#define XHC_FSC2AIC__FSIZ_WIDTH 5U +#define XHC_FSC2AIC__FSIZ_RESETVALUE 0x0U +#define XHC_FSC2AIC__PSIZ_L 16U +#define XHC_FSC2AIC__PSIZ_R 12U +#define XHC_FSC2AIC__PSIZ_WIDTH 5U +#define XHC_FSC2AIC__PSIZ_RESETVALUE 0x0U +#define XHC_FSC2AIC__reserved_L 11U +#define XHC_FSC2AIC__reserved_R 0U +#define XHC_FSC2AIC__reserved_WIDTH 12U +#define XHC_FSC2AIC__reserved_RESETVALUE 0x000U +#define XHC_FSC2AIC__RESERVED_L 31U +#define XHC_FSC2AIC__RESERVED_R 23U +#define XHC_FSC2AIC_WIDTH 23U +#define XHC_FSC2AIC__WIDTH 23U +#define XHC_FSC2AIC_ALL_L 22U +#define XHC_FSC2AIC_ALL_R 0U +#define XHC_FSC2AIC__ALL_L 22U +#define XHC_FSC2AIC__ALL_R 0U +#define XHC_FSC2AIC_DATAMASK 0x007dffffU +#define XHC_FSC2AIC_RDWRMASK 0xff820000U +#define XHC_FSC2AIC_RESETVALUE 0x000000U + +#define XHC_FSC2PIC_OFFSET 0xce4U +#define XHC_FSC2PIC_BASE 0xce4U +#define XHC_FSC2PIC__NCS_L 31U +#define XHC_FSC2PIC__NCS_R 28U +#define XHC_FSC2PIC__NCS_WIDTH 4U +#define XHC_FSC2PIC__NCS_RESETVALUE 0x0U +#define XHC_FSC2PIC__reserved_L 27U +#define XHC_FSC2PIC__reserved_R 5U +#define XHC_FSC2PIC__reserved_WIDTH 23U +#define XHC_FSC2PIC__reserved_RESETVALUE 0x0U +#define XHC_FSC2PIC__TSIZ_L 4U +#define XHC_FSC2PIC__TSIZ_R 0U +#define XHC_FSC2PIC__TSIZ_WIDTH 5U +#define XHC_FSC2PIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2PIC_WIDTH 32U +#define XHC_FSC2PIC__WIDTH 32U +#define XHC_FSC2PIC_ALL_L 31U +#define XHC_FSC2PIC_ALL_R 0U +#define XHC_FSC2PIC__ALL_L 31U +#define XHC_FSC2PIC__ALL_R 0U +#define XHC_FSC2PIC_DATAMASK 0xffffffffU +#define XHC_FSC2PIC_RDWRMASK 0x00000000U +#define XHC_FSC2PIC_RESETVALUE 0x00000000U + +#define XHC_FSC2GIC_OFFSET 0xce8U +#define XHC_FSC2GIC_BASE 0xce8U +#define XHC_FSC2GIC__NCS_L 31U +#define XHC_FSC2GIC__NCS_R 28U +#define XHC_FSC2GIC__NCS_WIDTH 4U +#define XHC_FSC2GIC__NCS_RESETVALUE 0x0U +#define XHC_FSC2GIC__reserved_L 27U +#define XHC_FSC2GIC__reserved_R 5U +#define XHC_FSC2GIC__reserved_WIDTH 23U +#define XHC_FSC2GIC__reserved_RESETVALUE 0x0U +#define XHC_FSC2GIC__TSIZ_L 4U +#define XHC_FSC2GIC__TSIZ_R 0U +#define XHC_FSC2GIC__TSIZ_WIDTH 5U +#define XHC_FSC2GIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2GIC_WIDTH 32U +#define XHC_FSC2GIC__WIDTH 32U +#define XHC_FSC2GIC_ALL_L 31U +#define XHC_FSC2GIC_ALL_R 0U +#define XHC_FSC2GIC__ALL_L 31U +#define XHC_FSC2GIC__ALL_R 0U +#define XHC_FSC2GIC_DATAMASK 0xffffffffU +#define XHC_FSC2GIC_RDWRMASK 0x00000000U +#define XHC_FSC2GIC_RESETVALUE 0x00000000U + +#define XHC_FSC2NIC_OFFSET 0xcecU +#define XHC_FSC2NIC_BASE 0xcecU +#define XHC_FSC2NIC__NCS_L 31U +#define XHC_FSC2NIC__NCS_R 28U +#define XHC_FSC2NIC__NCS_WIDTH 4U +#define XHC_FSC2NIC__NCS_RESETVALUE 0x0U +#define XHC_FSC2NIC__reserved_L 27U +#define XHC_FSC2NIC__reserved_R 5U +#define XHC_FSC2NIC__reserved_WIDTH 23U +#define XHC_FSC2NIC__reserved_RESETVALUE 0x0U +#define XHC_FSC2NIC__TSIZ_L 4U +#define XHC_FSC2NIC__TSIZ_R 0U +#define XHC_FSC2NIC__TSIZ_WIDTH 5U +#define XHC_FSC2NIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2NIC_WIDTH 32U +#define XHC_FSC2NIC__WIDTH 32U +#define XHC_FSC2NIC_ALL_L 31U +#define XHC_FSC2NIC_ALL_R 0U +#define XHC_FSC2NIC__ALL_L 31U +#define XHC_FSC2NIC__ALL_R 0U +#define XHC_FSC2NIC_DATAMASK 0xffffffffU +#define XHC_FSC2NIC_RDWRMASK 0x00000000U +#define XHC_FSC2NIC_RESETVALUE 0x00000000U + +#define XHC_ECHPRT2_OFFSET 0xcf0U +#define XHC_ECHPRT2_BASE 0xcf0U +#define XHC_ECHPRT2__HDP 31U +#define XHC_ECHPRT2__HDP_L 31U +#define XHC_ECHPRT2__HDP_R 31U +#define XHC_ECHPRT2__HDP_WIDTH 1U +#define XHC_ECHPRT2__HDP_RESETVALUE 0x0U +#define XHC_ECHPRT2__FDP 30U +#define XHC_ECHPRT2__FDP_L 30U +#define XHC_ECHPRT2__FDP_R 30U +#define XHC_ECHPRT2__FDP_WIDTH 1U +#define XHC_ECHPRT2__FDP_RESETVALUE 0x0U +#define XHC_ECHPRT2__reserved_L 29U +#define XHC_ECHPRT2__reserved_R 17U +#define XHC_ECHPRT2__reserved_WIDTH 13U +#define XHC_ECHPRT2__reserved_RESETVALUE 0x0U +#define XHC_ECHPRT2__HST 16U +#define XHC_ECHPRT2__HST_L 16U +#define XHC_ECHPRT2__HST_R 16U +#define XHC_ECHPRT2__HST_WIDTH 1U +#define XHC_ECHPRT2__HST_RESETVALUE 0x0U +#define XHC_ECHPRT2__NCP_L 15U +#define XHC_ECHPRT2__NCP_R 8U +#define XHC_ECHPRT2__NCP_WIDTH 8U +#define XHC_ECHPRT2__NCP_RESETVALUE 0x04U +#define XHC_ECHPRT2__CID_L 7U +#define XHC_ECHPRT2__CID_R 0U +#define XHC_ECHPRT2__CID_WIDTH 8U +#define XHC_ECHPRT2__CID_RESETVALUE 0xc8U +#define XHC_ECHPRT2_WIDTH 32U +#define XHC_ECHPRT2__WIDTH 32U +#define XHC_ECHPRT2_ALL_L 31U +#define XHC_ECHPRT2_ALL_R 0U +#define XHC_ECHPRT2__ALL_L 31U +#define XHC_ECHPRT2__ALL_R 0U +#define XHC_ECHPRT2_DATAMASK 0xffffffffU +#define XHC_ECHPRT2_RDWRMASK 0x00000000U +#define XHC_ECHPRT2_RESETVALUE 0x000004c8U + +#define XHC_PRT2HSC_OFFSET 0xcf8U +#define XHC_PRT2HSC_BASE 0xcf8U +#define XHC_PRT2HSC__TMR_L 31U +#define XHC_PRT2HSC__TMR_R 16U +#define XHC_PRT2HSC__TMR_WIDTH 16U +#define XHC_PRT2HSC__TMR_RESETVALUE 0x0000U +#define XHC_PRT2HSC__RSL_L 7U +#define XHC_PRT2HSC__RSL_R 6U +#define XHC_PRT2HSC__RSL_WIDTH 2U +#define XHC_PRT2HSC__RSL_RESETVALUE 0x0U +#define XHC_PRT2HSC__AS_M_L 5U +#define XHC_PRT2HSC__AS_M_R 4U +#define XHC_PRT2HSC__AS_M_WIDTH 2U +#define XHC_PRT2HSC__AS_M_RESETVALUE 0x0U +#define XHC_PRT2HSC__CMD_L 3U +#define XHC_PRT2HSC__CMD_R 2U +#define XHC_PRT2HSC__CMD_WIDTH 2U +#define XHC_PRT2HSC__CMD_RESETVALUE 0x0U +#define XHC_PRT2HSC__reserved 1U +#define XHC_PRT2HSC__reserved_L 1U +#define XHC_PRT2HSC__reserved_R 1U +#define XHC_PRT2HSC__reserved_WIDTH 1U +#define XHC_PRT2HSC__reserved_RESETVALUE 0x0U +#define XHC_PRT2HSC__STB 0U +#define XHC_PRT2HSC__STB_L 0U +#define XHC_PRT2HSC__STB_R 0U +#define XHC_PRT2HSC__STB_WIDTH 1U +#define XHC_PRT2HSC__STB_RESETVALUE 0x0U +#define XHC_PRT2HSC__RESERVED_L 15U +#define XHC_PRT2HSC__RESERVED_R 8U +#define XHC_PRT2HSC_WIDTH 32U +#define XHC_PRT2HSC__WIDTH 32U +#define XHC_PRT2HSC_ALL_L 31U +#define XHC_PRT2HSC_ALL_R 0U +#define XHC_PRT2HSC__ALL_L 31U +#define XHC_PRT2HSC__ALL_R 0U +#define XHC_PRT2HSC_DATAMASK 0xffff00ffU +#define XHC_PRT2HSC_RDWRMASK 0x0000ff00U +#define XHC_PRT2HSC_RESETVALUE 0x00000000U + +#define XHC_PRT2HSR_OFFSET 0xcfcU +#define XHC_PRT2HSR_BASE 0xcfcU +#define XHC_PRT2HSR__RNAK_L 31U +#define XHC_PRT2HSR__RNAK_R 24U +#define XHC_PRT2HSR__RNAK_WIDTH 8U +#define XHC_PRT2HSR__RNAK_RESETVALUE 0x00U +#define XHC_PRT2HSR__HSTX_L 23U +#define XHC_PRT2HSR__HSTX_R 16U +#define XHC_PRT2HSR__HSTX_WIDTH 8U +#define XHC_PRT2HSR__HSTX_RESETVALUE 0x00U +#define XHC_PRT2HSR__HSRX_L 15U +#define XHC_PRT2HSR__HSRX_R 8U +#define XHC_PRT2HSR__HSRX_WIDTH 8U +#define XHC_PRT2HSR__HSRX_RESETVALUE 0x00U +#define XHC_PRT2HSR__SPLT_L 7U +#define XHC_PRT2HSR__SPLT_R 0U +#define XHC_PRT2HSR__SPLT_WIDTH 8U +#define XHC_PRT2HSR__SPLT_RESETVALUE 0x00U +#define XHC_PRT2HSR_WIDTH 32U +#define XHC_PRT2HSR__WIDTH 32U +#define XHC_PRT2HSR_ALL_L 31U +#define XHC_PRT2HSR_ALL_R 0U +#define XHC_PRT2HSR__ALL_L 31U +#define XHC_PRT2HSR__ALL_R 0U +#define XHC_PRT2HSR_DATAMASK 0xffffffffU +#define XHC_PRT2HSR_RDWRMASK 0x00000000U +#define XHC_PRT2HSR_RESETVALUE 0x00000000U + +#define XHC_ECHRH2_OFFSET 0xd00U +#define XHC_ECHRH2_BASE 0xd00U +#define XHC_ECHRH2__MTT 31U +#define XHC_ECHRH2__MTT_L 31U +#define XHC_ECHRH2__MTT_R 31U +#define XHC_ECHRH2__MTT_WIDTH 1U +#define XHC_ECHRH2__MTT_RESETVALUE 0x0U +#define XHC_ECHRH2__RPO_L 30U +#define XHC_ECHRH2__RPO_R 24U +#define XHC_ECHRH2__RPO_WIDTH 7U +#define XHC_ECHRH2__RPO_RESETVALUE 0x0U +#define XHC_ECHRH2__reserved_L 23U +#define XHC_ECHRH2__reserved_R 22U +#define XHC_ECHRH2__reserved_WIDTH 2U +#define XHC_ECHRH2__reserved_RESETVALUE 0x0U +#define XHC_ECHRH2__RPN_L 21U +#define XHC_ECHRH2__RPN_R 20U +#define XHC_ECHRH2__RPN_WIDTH 2U +#define XHC_ECHRH2__RPN_RESETVALUE 0x0U +#define XHC_ECHRH2__DNR_L 19U +#define XHC_ECHRH2__DNR_R 16U +#define XHC_ECHRH2__DNR_WIDTH 4U +#define XHC_ECHRH2__DNR_RESETVALUE 0x0U +#define XHC_ECHRH2__NCP_L 15U +#define XHC_ECHRH2__NCP_R 8U +#define XHC_ECHRH2__NCP_WIDTH 8U +#define XHC_ECHRH2__NCP_RESETVALUE 0x0cU +#define XHC_ECHRH2__CID_L 7U +#define XHC_ECHRH2__CID_R 0U +#define XHC_ECHRH2__CID_WIDTH 8U +#define XHC_ECHRH2__CID_RESETVALUE 0xc9U +#define XHC_ECHRH2_WIDTH 32U +#define XHC_ECHRH2__WIDTH 32U +#define XHC_ECHRH2_ALL_L 31U +#define XHC_ECHRH2_ALL_R 0U +#define XHC_ECHRH2__ALL_L 31U +#define XHC_ECHRH2__ALL_R 0U +#define XHC_ECHRH2_DATAMASK 0xffffffffU +#define XHC_ECHRH2_RDWRMASK 0x00000000U +#define XHC_ECHRH2_RESETVALUE 0x00000cc9U + +#define XHC_RH2DES_OFFSET 0xd04U +#define XHC_RH2DES_BASE 0xd04U +#define XHC_RH2DES__PIS3_L 31U +#define XHC_RH2DES__PIS3_R 30U +#define XHC_RH2DES__PIS3_WIDTH 2U +#define XHC_RH2DES__PIS3_RESETVALUE 0x0U +#define XHC_RH2DES__HIST3 24U +#define XHC_RH2DES__HIST3_L 24U +#define XHC_RH2DES__HIST3_R 24U +#define XHC_RH2DES__HIST3_WIDTH 1U +#define XHC_RH2DES__HIST3_RESETVALUE 0x0U +#define XHC_RH2DES__PIS2_L 23U +#define XHC_RH2DES__PIS2_R 22U +#define XHC_RH2DES__PIS2_WIDTH 2U +#define XHC_RH2DES__PIS2_RESETVALUE 0x0U +#define XHC_RH2DES__HIST2 16U +#define XHC_RH2DES__HIST2_L 16U +#define XHC_RH2DES__HIST2_R 16U +#define XHC_RH2DES__HIST2_WIDTH 1U +#define XHC_RH2DES__HIST2_RESETVALUE 0x0U +#define XHC_RH2DES__PIS1_L 15U +#define XHC_RH2DES__PIS1_R 14U +#define XHC_RH2DES__PIS1_WIDTH 2U +#define XHC_RH2DES__PIS1_RESETVALUE 0x0U +#define XHC_RH2DES__HIST1 8U +#define XHC_RH2DES__HIST1_L 8U +#define XHC_RH2DES__HIST1_R 8U +#define XHC_RH2DES__HIST1_WIDTH 1U +#define XHC_RH2DES__HIST1_RESETVALUE 0x0U +#define XHC_RH2DES__PIS0_L 7U +#define XHC_RH2DES__PIS0_R 6U +#define XHC_RH2DES__PIS0_WIDTH 2U +#define XHC_RH2DES__PIS0_RESETVALUE 0x0U +#define XHC_RH2DES__reserved_L 5U +#define XHC_RH2DES__reserved_R 1U +#define XHC_RH2DES__reserved_WIDTH 5U +#define XHC_RH2DES__reserved_RESETVALUE 0x0U +#define XHC_RH2DES__HIST0 0U +#define XHC_RH2DES__HIST0_L 0U +#define XHC_RH2DES__HIST0_R 0U +#define XHC_RH2DES__HIST0_WIDTH 1U +#define XHC_RH2DES__HIST0_RESETVALUE 0x0U +#define XHC_RH2DES__RESERVED_0_L 29U +#define XHC_RH2DES__RESERVED_0_R 25U +#define XHC_RH2DES__RESERVED_1_L 21U +#define XHC_RH2DES__RESERVED_1_R 17U +#define XHC_RH2DES__RESERVED_2_L 13U +#define XHC_RH2DES__RESERVED_2_R 9U +#define XHC_RH2DES__RESERVED_L 29U +#define XHC_RH2DES__RESERVED_R 25U +#define XHC_RH2DES_WIDTH 32U +#define XHC_RH2DES__WIDTH 32U +#define XHC_RH2DES_ALL_L 31U +#define XHC_RH2DES_ALL_R 0U +#define XHC_RH2DES__ALL_L 31U +#define XHC_RH2DES__ALL_R 0U +#define XHC_RH2DES_DATAMASK 0xc1c1c1ffU +#define XHC_RH2DES_RDWRMASK 0x3e3e3e00U +#define XHC_RH2DES_RESETVALUE 0x00000000U + +#define XHC_RH2HSC0_OFFSET 0xd10U +#define XHC_RH2HSC0_BASE 0xd10U +#define XHC_RH2HSC0__TMR_L 31U +#define XHC_RH2HSC0__TMR_R 16U +#define XHC_RH2HSC0__TMR_WIDTH 16U +#define XHC_RH2HSC0__TMR_RESETVALUE 0x0000U +#define XHC_RH2HSC0__RSL_L 7U +#define XHC_RH2HSC0__RSL_R 6U +#define XHC_RH2HSC0__RSL_WIDTH 2U +#define XHC_RH2HSC0__RSL_RESETVALUE 0x0U +#define XHC_RH2HSC0__AS_M_L 5U +#define XHC_RH2HSC0__AS_M_R 4U +#define XHC_RH2HSC0__AS_M_WIDTH 2U +#define XHC_RH2HSC0__AS_M_RESETVALUE 0x0U +#define XHC_RH2HSC0__CMD_L 3U +#define XHC_RH2HSC0__CMD_R 2U +#define XHC_RH2HSC0__CMD_WIDTH 2U +#define XHC_RH2HSC0__CMD_RESETVALUE 0x0U +#define XHC_RH2HSC0__reserved 1U +#define XHC_RH2HSC0__reserved_L 1U +#define XHC_RH2HSC0__reserved_R 1U +#define XHC_RH2HSC0__reserved_WIDTH 1U +#define XHC_RH2HSC0__reserved_RESETVALUE 0x0U +#define XHC_RH2HSC0__STB 0U +#define XHC_RH2HSC0__STB_L 0U +#define XHC_RH2HSC0__STB_R 0U +#define XHC_RH2HSC0__STB_WIDTH 1U +#define XHC_RH2HSC0__STB_RESETVALUE 0x0U +#define XHC_RH2HSC0__RESERVED_L 15U +#define XHC_RH2HSC0__RESERVED_R 8U +#define XHC_RH2HSC0_WIDTH 32U +#define XHC_RH2HSC0__WIDTH 32U +#define XHC_RH2HSC0_ALL_L 31U +#define XHC_RH2HSC0_ALL_R 0U +#define XHC_RH2HSC0__ALL_L 31U +#define XHC_RH2HSC0__ALL_R 0U +#define XHC_RH2HSC0_DATAMASK 0xffff00ffU +#define XHC_RH2HSC0_RDWRMASK 0x0000ff00U +#define XHC_RH2HSC0_RESETVALUE 0x00000000U + +#define XHC_RH2HSR0_OFFSET 0xd14U +#define XHC_RH2HSR0_BASE 0xd14U +#define XHC_RH2HSR0__C2U_L 31U +#define XHC_RH2HSR0__C2U_R 24U +#define XHC_RH2HSR0__C2U_WIDTH 8U +#define XHC_RH2HSR0__C2U_RESETVALUE 0x00U +#define XHC_RH2HSR0__C1U_L 23U +#define XHC_RH2HSR0__C1U_R 16U +#define XHC_RH2HSR0__C1U_WIDTH 8U +#define XHC_RH2HSR0__C1U_RESETVALUE 0x00U +#define XHC_RH2HSR0__reserved_L 15U +#define XHC_RH2HSR0__reserved_R 8U +#define XHC_RH2HSR0__reserved_WIDTH 8U +#define XHC_RH2HSR0__reserved_RESETVALUE 0x00U +#define XHC_RH2HSR0__RTY_L 7U +#define XHC_RH2HSR0__RTY_R 0U +#define XHC_RH2HSR0__RTY_WIDTH 8U +#define XHC_RH2HSR0__RTY_RESETVALUE 0x00U +#define XHC_RH2HSR0_WIDTH 32U +#define XHC_RH2HSR0__WIDTH 32U +#define XHC_RH2HSR0_ALL_L 31U +#define XHC_RH2HSR0_ALL_R 0U +#define XHC_RH2HSR0__ALL_L 31U +#define XHC_RH2HSR0__ALL_R 0U +#define XHC_RH2HSR0_DATAMASK 0xffffffffU +#define XHC_RH2HSR0_RDWRMASK 0x00000000U +#define XHC_RH2HSR0_RESETVALUE 0x00000000U + +#define XHC_RH2HSC1_OFFSET 0xd18U +#define XHC_RH2HSC1_BASE 0xd18U +#define XHC_RH2HSC1__TMR_L 31U +#define XHC_RH2HSC1__TMR_R 16U +#define XHC_RH2HSC1__TMR_WIDTH 16U +#define XHC_RH2HSC1__TMR_RESETVALUE 0x0000U +#define XHC_RH2HSC1__RSL_L 7U +#define XHC_RH2HSC1__RSL_R 6U +#define XHC_RH2HSC1__RSL_WIDTH 2U +#define XHC_RH2HSC1__RSL_RESETVALUE 0x0U +#define XHC_RH2HSC1__AS_M_L 5U +#define XHC_RH2HSC1__AS_M_R 4U +#define XHC_RH2HSC1__AS_M_WIDTH 2U +#define XHC_RH2HSC1__AS_M_RESETVALUE 0x0U +#define XHC_RH2HSC1__CMD_L 3U +#define XHC_RH2HSC1__CMD_R 2U +#define XHC_RH2HSC1__CMD_WIDTH 2U +#define XHC_RH2HSC1__CMD_RESETVALUE 0x0U +#define XHC_RH2HSC1__reserved 1U +#define XHC_RH2HSC1__reserved_L 1U +#define XHC_RH2HSC1__reserved_R 1U +#define XHC_RH2HSC1__reserved_WIDTH 1U +#define XHC_RH2HSC1__reserved_RESETVALUE 0x0U +#define XHC_RH2HSC1__STB 0U +#define XHC_RH2HSC1__STB_L 0U +#define XHC_RH2HSC1__STB_R 0U +#define XHC_RH2HSC1__STB_WIDTH 1U +#define XHC_RH2HSC1__STB_RESETVALUE 0x0U +#define XHC_RH2HSC1__RESERVED_L 15U +#define XHC_RH2HSC1__RESERVED_R 8U +#define XHC_RH2HSC1_WIDTH 32U +#define XHC_RH2HSC1__WIDTH 32U +#define XHC_RH2HSC1_ALL_L 31U +#define XHC_RH2HSC1_ALL_R 0U +#define XHC_RH2HSC1__ALL_L 31U +#define XHC_RH2HSC1__ALL_R 0U +#define XHC_RH2HSC1_DATAMASK 0xffff00ffU +#define XHC_RH2HSC1_RDWRMASK 0x0000ff00U +#define XHC_RH2HSC1_RESETVALUE 0x00000000U + +#define XHC_RH2HSR1_OFFSET 0xd1cU +#define XHC_RH2HSR1_BASE 0xd1cU +#define XHC_RH2HSR1__C2U_L 31U +#define XHC_RH2HSR1__C2U_R 24U +#define XHC_RH2HSR1__C2U_WIDTH 8U +#define XHC_RH2HSR1__C2U_RESETVALUE 0x00U +#define XHC_RH2HSR1__C1U_L 23U +#define XHC_RH2HSR1__C1U_R 16U +#define XHC_RH2HSR1__C1U_WIDTH 8U +#define XHC_RH2HSR1__C1U_RESETVALUE 0x00U +#define XHC_RH2HSR1__reserved_L 15U +#define XHC_RH2HSR1__reserved_R 8U +#define XHC_RH2HSR1__reserved_WIDTH 8U +#define XHC_RH2HSR1__reserved_RESETVALUE 0x00U +#define XHC_RH2HSR1__RTY_L 7U +#define XHC_RH2HSR1__RTY_R 0U +#define XHC_RH2HSR1__RTY_WIDTH 8U +#define XHC_RH2HSR1__RTY_RESETVALUE 0x00U +#define XHC_RH2HSR1_WIDTH 32U +#define XHC_RH2HSR1__WIDTH 32U +#define XHC_RH2HSR1_ALL_L 31U +#define XHC_RH2HSR1_ALL_R 0U +#define XHC_RH2HSR1__ALL_L 31U +#define XHC_RH2HSR1__ALL_R 0U +#define XHC_RH2HSR1_DATAMASK 0xffffffffU +#define XHC_RH2HSR1_RDWRMASK 0x00000000U +#define XHC_RH2HSR1_RESETVALUE 0x00000000U + +#define XHC_RH2HSC2_OFFSET 0xd20U +#define XHC_RH2HSC2_BASE 0xd20U +#define XHC_RH2HSC2__TMR_L 31U +#define XHC_RH2HSC2__TMR_R 16U +#define XHC_RH2HSC2__TMR_WIDTH 16U +#define XHC_RH2HSC2__TMR_RESETVALUE 0x0000U +#define XHC_RH2HSC2__RSL_L 7U +#define XHC_RH2HSC2__RSL_R 6U +#define XHC_RH2HSC2__RSL_WIDTH 2U +#define XHC_RH2HSC2__RSL_RESETVALUE 0x0U +#define XHC_RH2HSC2__AS_M_L 5U +#define XHC_RH2HSC2__AS_M_R 4U +#define XHC_RH2HSC2__AS_M_WIDTH 2U +#define XHC_RH2HSC2__AS_M_RESETVALUE 0x0U +#define XHC_RH2HSC2__CMD_L 3U +#define XHC_RH2HSC2__CMD_R 2U +#define XHC_RH2HSC2__CMD_WIDTH 2U +#define XHC_RH2HSC2__CMD_RESETVALUE 0x0U +#define XHC_RH2HSC2__reserved 1U +#define XHC_RH2HSC2__reserved_L 1U +#define XHC_RH2HSC2__reserved_R 1U +#define XHC_RH2HSC2__reserved_WIDTH 1U +#define XHC_RH2HSC2__reserved_RESETVALUE 0x0U +#define XHC_RH2HSC2__STB 0U +#define XHC_RH2HSC2__STB_L 0U +#define XHC_RH2HSC2__STB_R 0U +#define XHC_RH2HSC2__STB_WIDTH 1U +#define XHC_RH2HSC2__STB_RESETVALUE 0x0U +#define XHC_RH2HSC2__RESERVED_L 15U +#define XHC_RH2HSC2__RESERVED_R 8U +#define XHC_RH2HSC2_WIDTH 32U +#define XHC_RH2HSC2__WIDTH 32U +#define XHC_RH2HSC2_ALL_L 31U +#define XHC_RH2HSC2_ALL_R 0U +#define XHC_RH2HSC2__ALL_L 31U +#define XHC_RH2HSC2__ALL_R 0U +#define XHC_RH2HSC2_DATAMASK 0xffff00ffU +#define XHC_RH2HSC2_RDWRMASK 0x0000ff00U +#define XHC_RH2HSC2_RESETVALUE 0x00000000U + +#define XHC_RH2HSR2_OFFSET 0xd24U +#define XHC_RH2HSR2_BASE 0xd24U +#define XHC_RH2HSR2__C2U_L 31U +#define XHC_RH2HSR2__C2U_R 24U +#define XHC_RH2HSR2__C2U_WIDTH 8U +#define XHC_RH2HSR2__C2U_RESETVALUE 0x00U +#define XHC_RH2HSR2__C1U_L 23U +#define XHC_RH2HSR2__C1U_R 16U +#define XHC_RH2HSR2__C1U_WIDTH 8U +#define XHC_RH2HSR2__C1U_RESETVALUE 0x00U +#define XHC_RH2HSR2__reserved_L 15U +#define XHC_RH2HSR2__reserved_R 8U +#define XHC_RH2HSR2__reserved_WIDTH 8U +#define XHC_RH2HSR2__reserved_RESETVALUE 0x00U +#define XHC_RH2HSR2__RTY_L 7U +#define XHC_RH2HSR2__RTY_R 0U +#define XHC_RH2HSR2__RTY_WIDTH 8U +#define XHC_RH2HSR2__RTY_RESETVALUE 0x00U +#define XHC_RH2HSR2_WIDTH 32U +#define XHC_RH2HSR2__WIDTH 32U +#define XHC_RH2HSR2_ALL_L 31U +#define XHC_RH2HSR2_ALL_R 0U +#define XHC_RH2HSR2__ALL_L 31U +#define XHC_RH2HSR2__ALL_R 0U +#define XHC_RH2HSR2_DATAMASK 0xffffffffU +#define XHC_RH2HSR2_RDWRMASK 0x00000000U +#define XHC_RH2HSR2_RESETVALUE 0x00000000U + +#define XHC_RH2HSC3_OFFSET 0xd28U +#define XHC_RH2HSC3_BASE 0xd28U +#define XHC_RH2HSC3__TMR_L 31U +#define XHC_RH2HSC3__TMR_R 16U +#define XHC_RH2HSC3__TMR_WIDTH 16U +#define XHC_RH2HSC3__TMR_RESETVALUE 0x0000U +#define XHC_RH2HSC3__RSL_L 7U +#define XHC_RH2HSC3__RSL_R 6U +#define XHC_RH2HSC3__RSL_WIDTH 2U +#define XHC_RH2HSC3__RSL_RESETVALUE 0x0U +#define XHC_RH2HSC3__AS_M_L 5U +#define XHC_RH2HSC3__AS_M_R 4U +#define XHC_RH2HSC3__AS_M_WIDTH 2U +#define XHC_RH2HSC3__AS_M_RESETVALUE 0x0U +#define XHC_RH2HSC3__CMD_L 3U +#define XHC_RH2HSC3__CMD_R 2U +#define XHC_RH2HSC3__CMD_WIDTH 2U +#define XHC_RH2HSC3__CMD_RESETVALUE 0x0U +#define XHC_RH2HSC3__reserved 1U +#define XHC_RH2HSC3__reserved_L 1U +#define XHC_RH2HSC3__reserved_R 1U +#define XHC_RH2HSC3__reserved_WIDTH 1U +#define XHC_RH2HSC3__reserved_RESETVALUE 0x0U +#define XHC_RH2HSC3__STB 0U +#define XHC_RH2HSC3__STB_L 0U +#define XHC_RH2HSC3__STB_R 0U +#define XHC_RH2HSC3__STB_WIDTH 1U +#define XHC_RH2HSC3__STB_RESETVALUE 0x0U +#define XHC_RH2HSC3__RESERVED_L 15U +#define XHC_RH2HSC3__RESERVED_R 8U +#define XHC_RH2HSC3_WIDTH 32U +#define XHC_RH2HSC3__WIDTH 32U +#define XHC_RH2HSC3_ALL_L 31U +#define XHC_RH2HSC3_ALL_R 0U +#define XHC_RH2HSC3__ALL_L 31U +#define XHC_RH2HSC3__ALL_R 0U +#define XHC_RH2HSC3_DATAMASK 0xffff00ffU +#define XHC_RH2HSC3_RDWRMASK 0x0000ff00U +#define XHC_RH2HSC3_RESETVALUE 0x00000000U + +#define XHC_RH2HSR3_OFFSET 0xd2cU +#define XHC_RH2HSR3_BASE 0xd2cU +#define XHC_RH2HSR3__C2U_L 31U +#define XHC_RH2HSR3__C2U_R 24U +#define XHC_RH2HSR3__C2U_WIDTH 8U +#define XHC_RH2HSR3__C2U_RESETVALUE 0x00U +#define XHC_RH2HSR3__C1U_L 23U +#define XHC_RH2HSR3__C1U_R 16U +#define XHC_RH2HSR3__C1U_WIDTH 8U +#define XHC_RH2HSR3__C1U_RESETVALUE 0x00U +#define XHC_RH2HSR3__reserved_L 15U +#define XHC_RH2HSR3__reserved_R 8U +#define XHC_RH2HSR3__reserved_WIDTH 8U +#define XHC_RH2HSR3__reserved_RESETVALUE 0x00U +#define XHC_RH2HSR3__RTY_L 7U +#define XHC_RH2HSR3__RTY_R 0U +#define XHC_RH2HSR3__RTY_WIDTH 8U +#define XHC_RH2HSR3__RTY_RESETVALUE 0x00U +#define XHC_RH2HSR3_WIDTH 32U +#define XHC_RH2HSR3__WIDTH 32U +#define XHC_RH2HSR3_ALL_L 31U +#define XHC_RH2HSR3_ALL_R 0U +#define XHC_RH2HSR3__ALL_L 31U +#define XHC_RH2HSR3__ALL_R 0U +#define XHC_RH2HSR3_DATAMASK 0xffffffffU +#define XHC_RH2HSR3_RDWRMASK 0x00000000U +#define XHC_RH2HSR3_RESETVALUE 0x00000000U + +#define XHC_ECHU2P_OFFSET 0xd30U +#define XHC_ECHU2P_BASE 0xd30U +#define XHC_ECHU2P__reserved_L 31U +#define XHC_ECHU2P__reserved_R 16U +#define XHC_ECHU2P__reserved_WIDTH 16U +#define XHC_ECHU2P__reserved_RESETVALUE 0x0000U +#define XHC_ECHU2P__NCP_L 15U +#define XHC_ECHU2P__NCP_R 8U +#define XHC_ECHU2P__NCP_WIDTH 8U +#define XHC_ECHU2P__NCP_RESETVALUE 0x04U +#define XHC_ECHU2P__CID_L 7U +#define XHC_ECHU2P__CID_R 0U +#define XHC_ECHU2P__CID_WIDTH 8U +#define XHC_ECHU2P__CID_RESETVALUE 0xcaU +#define XHC_ECHU2P_WIDTH 32U +#define XHC_ECHU2P__WIDTH 32U +#define XHC_ECHU2P_ALL_L 31U +#define XHC_ECHU2P_ALL_R 0U +#define XHC_ECHU2P__ALL_L 31U +#define XHC_ECHU2P__ALL_R 0U +#define XHC_ECHU2P_DATAMASK 0xffffffffU +#define XHC_ECHU2P_RDWRMASK 0x00000000U +#define XHC_ECHU2P_RESETVALUE 0x000004caU + +#define XHC_U2PVER_OFFSET 0xd34U +#define XHC_U2PVER_BASE 0xd34U +#define XHC_U2PVER__MAJ_L 31U +#define XHC_U2PVER__MAJ_R 28U +#define XHC_U2PVER__MAJ_WIDTH 4U +#define XHC_U2PVER__MAJ_RESETVALUE 0x0U +#define XHC_U2PVER__MIN_L 27U +#define XHC_U2PVER__MIN_R 24U +#define XHC_U2PVER__MIN_WIDTH 4U +#define XHC_U2PVER__MIN_RESETVALUE 0x0U +#define XHC_U2PVER__RLS_L 23U +#define XHC_U2PVER__RLS_R 20U +#define XHC_U2PVER__RLS_WIDTH 4U +#define XHC_U2PVER__RLS_RESETVALUE 0x0U +#define XHC_U2PVER__reserved_L 19U +#define XHC_U2PVER__reserved_R 0U +#define XHC_U2PVER__reserved_WIDTH 20U +#define XHC_U2PVER__reserved_RESETVALUE 0x00000U +#define XHC_U2PVER_WIDTH 32U +#define XHC_U2PVER__WIDTH 32U +#define XHC_U2PVER_ALL_L 31U +#define XHC_U2PVER_ALL_R 0U +#define XHC_U2PVER__ALL_L 31U +#define XHC_U2PVER__ALL_R 0U +#define XHC_U2PVER_DATAMASK 0xffffffffU +#define XHC_U2PVER_RDWRMASK 0x00000000U +#define XHC_U2PVER_RESETVALUE 0x00000000U + +#define XHC_U2PMGN_OFFSET 0xd38U +#define XHC_U2PMGN_BASE 0xd38U +#define XHC_U2PMGN__MGN_L 31U +#define XHC_U2PMGN__MGN_R 0U +#define XHC_U2PMGN__MGN_WIDTH 32U +#define XHC_U2PMGN__MGN_RESETVALUE 0x4b534b4dU +#define XHC_U2PMGN_WIDTH 32U +#define XHC_U2PMGN__WIDTH 32U +#define XHC_U2PMGN_ALL_L 31U +#define XHC_U2PMGN_ALL_R 0U +#define XHC_U2PMGN__ALL_L 31U +#define XHC_U2PMGN__ALL_R 0U +#define XHC_U2PMGN_DATAMASK 0xffffffffU +#define XHC_U2PMGN_RDWRMASK 0x00000000U +#define XHC_U2PMGN_RESETVALUE 0x4b534b4dU + +#define XHC_ECHRSV2_OFFSET 0xd40U +#define XHC_ECHRSV2_BASE 0xd40U +#define XHC_ECHRSV2__reserved_L 31U +#define XHC_ECHRSV2__reserved_R 16U +#define XHC_ECHRSV2__reserved_WIDTH 16U +#define XHC_ECHRSV2__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSV2__NCP_L 15U +#define XHC_ECHRSV2__NCP_R 8U +#define XHC_ECHRSV2__NCP_WIDTH 8U +#define XHC_ECHRSV2__NCP_RESETVALUE 0x00U +#define XHC_ECHRSV2__CID_L 7U +#define XHC_ECHRSV2__CID_R 0U +#define XHC_ECHRSV2__CID_WIDTH 8U +#define XHC_ECHRSV2__CID_RESETVALUE 0xffU +#define XHC_ECHRSV2_WIDTH 32U +#define XHC_ECHRSV2__WIDTH 32U +#define XHC_ECHRSV2_ALL_L 31U +#define XHC_ECHRSV2_ALL_R 0U +#define XHC_ECHRSV2__ALL_L 31U +#define XHC_ECHRSV2__ALL_R 0U +#define XHC_ECHRSV2_DATAMASK 0xffffffffU +#define XHC_ECHRSV2_RDWRMASK 0x00000000U +#define XHC_ECHRSV2_RESETVALUE 0x000000ffU + +#define XHC_ECHIRA_OFFSET 0xf90U +#define XHC_ECHIRA_BASE 0xf90U +#define XHC_ECHIRA__reserved_L 31U +#define XHC_ECHIRA__reserved_R 16U +#define XHC_ECHIRA__reserved_WIDTH 16U +#define XHC_ECHIRA__reserved_RESETVALUE 0x0000U +#define XHC_ECHIRA__NCP_L 15U +#define XHC_ECHIRA__NCP_R 8U +#define XHC_ECHIRA__NCP_WIDTH 8U +#define XHC_ECHIRA__NCP_RESETVALUE 0x04U +#define XHC_ECHIRA__CID_L 7U +#define XHC_ECHIRA__CID_R 0U +#define XHC_ECHIRA__CID_WIDTH 8U +#define XHC_ECHIRA__CID_RESETVALUE 0xfdU +#define XHC_ECHIRA_WIDTH 32U +#define XHC_ECHIRA__WIDTH 32U +#define XHC_ECHIRA_ALL_L 31U +#define XHC_ECHIRA_ALL_R 0U +#define XHC_ECHIRA__ALL_L 31U +#define XHC_ECHIRA__ALL_R 0U +#define XHC_ECHIRA_DATAMASK 0xffffffffU +#define XHC_ECHIRA_RDWRMASK 0x00000000U +#define XHC_ECHIRA_RESETVALUE 0x000004fdU + +#define XHC_IRAADR_OFFSET 0xf98U +#define XHC_IRAADR_BASE 0xf98U +#define XHC_IRAADR__ADR_L 23U +#define XHC_IRAADR__ADR_R 2U +#define XHC_IRAADR__ADR_WIDTH 22U +#define XHC_IRAADR__ADR_RESETVALUE 0x0U +#define XHC_IRAADR__reserved 1U +#define XHC_IRAADR__reserved_L 1U +#define XHC_IRAADR__reserved_R 1U +#define XHC_IRAADR__reserved_WIDTH 1U +#define XHC_IRAADR__reserved_RESETVALUE 0x0U +#define XHC_IRAADR__MOD 0U +#define XHC_IRAADR__MOD_L 0U +#define XHC_IRAADR__MOD_R 0U +#define XHC_IRAADR__MOD_WIDTH 1U +#define XHC_IRAADR__MOD_RESETVALUE 0x0U +#define XHC_IRAADR__RESERVED_L 31U +#define XHC_IRAADR__RESERVED_R 24U +#define XHC_IRAADR_WIDTH 24U +#define XHC_IRAADR__WIDTH 24U +#define XHC_IRAADR_ALL_L 23U +#define XHC_IRAADR_ALL_R 0U +#define XHC_IRAADR__ALL_L 23U +#define XHC_IRAADR__ALL_R 0U +#define XHC_IRAADR_DATAMASK 0x00ffffffU +#define XHC_IRAADR_RDWRMASK 0xff000000U +#define XHC_IRAADR_RESETVALUE 0x000000U + +#define XHC_IRADAT_OFFSET 0xf9cU +#define XHC_IRADAT_BASE 0xf9cU +#define XHC_IRADAT__DAT_L 31U +#define XHC_IRADAT__DAT_R 0U +#define XHC_IRADAT__DAT_WIDTH 32U +#define XHC_IRADAT__DAT_RESETVALUE 0x00000000U +#define XHC_IRADAT_WIDTH 32U +#define XHC_IRADAT__WIDTH 32U +#define XHC_IRADAT_ALL_L 31U +#define XHC_IRADAT_ALL_R 0U +#define XHC_IRADAT__ALL_L 31U +#define XHC_IRADAT__ALL_R 0U +#define XHC_IRADAT_DATAMASK 0xffffffffU +#define XHC_IRADAT_RDWRMASK 0x00000000U +#define XHC_IRADAT_RESETVALUE 0x00000000U + + +#define XHC_ECHHST_OFFSET 0xfa0U +#define XHC_ECHHST_BASE 0xfa0U +#define XHC_ECHHST__CCC 31U +#define XHC_ECHHST__CCC_L 31U +#define XHC_ECHHST__CCC_R 31U +#define XHC_ECHHST__CCC_WIDTH 1U +#define XHC_ECHHST__CCC_RESETVALUE 0x1U +#define XHC_ECHHST__PME 30U +#define XHC_ECHHST__PME_L 30U +#define XHC_ECHHST__PME_R 30U +#define XHC_ECHHST__PME_WIDTH 1U +#define XHC_ECHHST__PME_RESETVALUE 0x0U +#define XHC_ECHHST__AUX_L 29U +#define XHC_ECHHST__AUX_R 24U +#define XHC_ECHHST__AUX_WIDTH 6U +#define XHC_ECHHST__AUX_RESETVALUE 0x0U +#define XHC_ECHHST__IRA 20U +#define XHC_ECHHST__IRA_L 20U +#define XHC_ECHHST__IRA_R 20U +#define XHC_ECHHST__IRA_WIDTH 1U +#define XHC_ECHHST__IRA_RESETVALUE 0x0U +#define XHC_ECHHST__ULS 19U +#define XHC_ECHHST__ULS_L 19U +#define XHC_ECHHST__ULS_R 19U +#define XHC_ECHHST__ULS_WIDTH 1U +#define XHC_ECHHST__ULS_RESETVALUE 0x0U +#define XHC_ECHHST__reserved 18U +#define XHC_ECHHST__reserved_L 18U +#define XHC_ECHHST__reserved_R 18U +#define XHC_ECHHST__reserved_WIDTH 1U +#define XHC_ECHHST__reserved_RESETVALUE 0x0U +#define XHC_ECHHST__TEDA 17U +#define XHC_ECHHST__TEDA_L 17U +#define XHC_ECHHST__TEDA_R 17U +#define XHC_ECHHST__TEDA_WIDTH 1U +#define XHC_ECHHST__TEDA_RESETVALUE 0x0U +#define XHC_ECHHST__FSW 16U +#define XHC_ECHHST__FSW_L 16U +#define XHC_ECHHST__FSW_R 16U +#define XHC_ECHHST__FSW_WIDTH 1U +#define XHC_ECHHST__FSW_RESETVALUE 0x1U +#define XHC_ECHHST__NCP_L 15U +#define XHC_ECHHST__NCP_R 8U +#define XHC_ECHHST__NCP_WIDTH 8U +#define XHC_ECHHST__NCP_RESETVALUE 0x04U +#define XHC_ECHHST__CID_L 7U +#define XHC_ECHHST__CID_R 0U +#define XHC_ECHHST__CID_WIDTH 8U +#define XHC_ECHHST__CID_RESETVALUE 0xfcU +#define XHC_ECHHST__RESERVED_L 23U +#define XHC_ECHHST__RESERVED_R 21U +#define XHC_ECHHST_WIDTH 32U +#define XHC_ECHHST__WIDTH 32U +#define XHC_ECHHST_ALL_L 31U +#define XHC_ECHHST_ALL_R 0U +#define XHC_ECHHST__ALL_L 31U +#define XHC_ECHHST__ALL_R 0U +#define XHC_ECHHST_DATAMASK 0xff1fffffU +#define XHC_ECHHST_RDWRMASK 0x00e00000U +#define XHC_ECHHST_RESETVALUE 0x800104fcU + +#define XHC_HSTDBG_OFFSET 0xfa4U +#define XHC_HSTDBG_BASE 0xfa4U +#define XHC_HSTDBG__ETE 31U +#define XHC_HSTDBG__ETE_L 31U +#define XHC_HSTDBG__ETE_R 31U +#define XHC_HSTDBG__ETE_WIDTH 1U +#define XHC_HSTDBG__ETE_RESETVALUE 0x0U +#define XHC_HSTDBG__reserved_L 30U +#define XHC_HSTDBG__reserved_R 16U +#define XHC_HSTDBG__reserved_WIDTH 15U +#define XHC_HSTDBG__reserved_RESETVALUE 0x0U +#define XHC_HSTDBG__OUTP_L 15U +#define XHC_HSTDBG__OUTP_R 8U +#define XHC_HSTDBG__OUTP_WIDTH 8U +#define XHC_HSTDBG__OUTP_RESETVALUE 0x00U +#define XHC_HSTDBG__INP_L 7U +#define XHC_HSTDBG__INP_R 0U +#define XHC_HSTDBG__INP_WIDTH 8U +#define XHC_HSTDBG__INP_RESETVALUE 0x00U +#define XHC_HSTDBG_WIDTH 32U +#define XHC_HSTDBG__WIDTH 32U +#define XHC_HSTDBG_ALL_L 31U +#define XHC_HSTDBG_ALL_R 0U +#define XHC_HSTDBG__ALL_L 31U +#define XHC_HSTDBG__ALL_R 0U +#define XHC_HSTDBG_DATAMASK 0xffffffffU +#define XHC_HSTDBG_RDWRMASK 0x00000000U +#define XHC_HSTDBG_RESETVALUE 0x00000000U + +#define XHC_HSTNPL_OFFSET 0xfa8U +#define XHC_HSTNPL_BASE 0xfa8U +#define XHC_HSTNPL__NPL_L 31U +#define XHC_HSTNPL__NPL_R 9U +#define XHC_HSTNPL__NPL_WIDTH 23U +#define XHC_HSTNPL__NPL_RESETVALUE 0x0U +#define XHC_HSTNPL__reserved_L 8U +#define XHC_HSTNPL__reserved_R 0U +#define XHC_HSTNPL__reserved_WIDTH 9U +#define XHC_HSTNPL__reserved_RESETVALUE 0x0U +#define XHC_HSTNPL_WIDTH 32U +#define XHC_HSTNPL__WIDTH 32U +#define XHC_HSTNPL_ALL_L 31U +#define XHC_HSTNPL_ALL_R 0U +#define XHC_HSTNPL__ALL_L 31U +#define XHC_HSTNPL__ALL_R 0U +#define XHC_HSTNPL_DATAMASK 0xffffffffU +#define XHC_HSTNPL_RDWRMASK 0x00000000U +#define XHC_HSTNPL_RESETVALUE 0x00000000U + +#define XHC_HSTNPH_OFFSET 0xfacU +#define XHC_HSTNPH_BASE 0xfacU +#define XHC_HSTNPH__NPH_L 31U +#define XHC_HSTNPH__NPH_R 0U +#define XHC_HSTNPH__NPH_WIDTH 32U +#define XHC_HSTNPH__NPH_RESETVALUE 0x00000000U +#define XHC_HSTNPH_WIDTH 32U +#define XHC_HSTNPH__WIDTH 32U +#define XHC_HSTNPH_ALL_L 31U +#define XHC_HSTNPH_ALL_R 0U +#define XHC_HSTNPH__ALL_L 31U +#define XHC_HSTNPH__ALL_R 0U +#define XHC_HSTNPH_DATAMASK 0xffffffffU +#define XHC_HSTNPH_RDWRMASK 0x00000000U +#define XHC_HSTNPH_RESETVALUE 0x00000000U + +#define XHC_ECHRBV_OFFSET 0xfb0U +#define XHC_ECHRBV_BASE 0xfb0U +#define XHC_ECHRBV__MAJ_L 31U +#define XHC_ECHRBV__MAJ_R 28U +#define XHC_ECHRBV__MAJ_WIDTH 4U +#define XHC_ECHRBV__MAJ_RESETVALUE 0x0U +#define XHC_ECHRBV__MIN_L 27U +#define XHC_ECHRBV__MIN_R 24U +#define XHC_ECHRBV__MIN_WIDTH 4U +#define XHC_ECHRBV__MIN_RESETVALUE 0x0U +#define XHC_ECHRBV__RLS_L 23U +#define XHC_ECHRBV__RLS_R 16U +#define XHC_ECHRBV__RLS_WIDTH 8U +#define XHC_ECHRBV__RLS_RESETVALUE 0x00U +#define XHC_ECHRBV__NCP_L 15U +#define XHC_ECHRBV__NCP_R 8U +#define XHC_ECHRBV__NCP_WIDTH 8U +#define XHC_ECHRBV__NCP_RESETVALUE 0x00U +#define XHC_ECHRBV__CID_L 7U +#define XHC_ECHRBV__CID_R 0U +#define XHC_ECHRBV__CID_WIDTH 8U +#define XHC_ECHRBV__CID_RESETVALUE 0xfeU +#define XHC_ECHRBV_WIDTH 32U +#define XHC_ECHRBV__WIDTH 32U +#define XHC_ECHRBV_ALL_L 31U +#define XHC_ECHRBV_ALL_R 0U +#define XHC_ECHRBV__ALL_L 31U +#define XHC_ECHRBV__ALL_R 0U +#define XHC_ECHRBV_DATAMASK 0xffffffffU +#define XHC_ECHRBV_RDWRMASK 0x00000000U +#define XHC_ECHRBV_RESETVALUE 0x000000feU + +#define XHC_RBVPDT_OFFSET 0xfb4U +#define XHC_RBVPDT_BASE 0xfb4U +#define XHC_RBVPDT__VDR_L 31U +#define XHC_RBVPDT__VDR_R 16U +#define XHC_RBVPDT__VDR_WIDTH 16U +#define XHC_RBVPDT__VDR_RESETVALUE 0x0a5cU +#define XHC_RBVPDT__PDT_L 15U +#define XHC_RBVPDT__PDT_R 0U +#define XHC_RBVPDT__PDT_WIDTH 16U +#define XHC_RBVPDT__PDT_RESETVALUE 0x0000U +#define XHC_RBVPDT_WIDTH 32U +#define XHC_RBVPDT__WIDTH 32U +#define XHC_RBVPDT_ALL_L 31U +#define XHC_RBVPDT_ALL_R 0U +#define XHC_RBVPDT__ALL_L 31U +#define XHC_RBVPDT__ALL_R 0U +#define XHC_RBVPDT_DATAMASK 0xffffffffU +#define XHC_RBVPDT_RDWRMASK 0x00000000U +#define XHC_RBVPDT_RESETVALUE 0x0a5c0000U + +#define XHC_RBVMGN_OFFSET 0xfbcU +#define XHC_RBVMGN_BASE 0xfbcU +#define XHC_RBVMGN__MGN_L 31U +#define XHC_RBVMGN__MGN_R 0U +#define XHC_RBVMGN__MGN_WIDTH 32U +#define XHC_RBVMGN__MGN_RESETVALUE 0x52535354U +#define XHC_RBVMGN_WIDTH 32U +#define XHC_RBVMGN__WIDTH 32U +#define XHC_RBVMGN_ALL_L 31U +#define XHC_RBVMGN_ALL_R 0U +#define XHC_RBVMGN__ALL_L 31U +#define XHC_RBVMGN__ALL_R 0U +#define XHC_RBVMGN_DATAMASK 0xffffffffU +#define XHC_RBVMGN_RDWRMASK 0x00000000U +#define XHC_RBVMGN_RESETVALUE 0x52535354U + +/* PORTSC field defines */ +#define XHC_PORTSC__PS_LINK_STATE_U0 0U +#define XHC_PORTSC__PS_LINK_STATE_U1 1U +#define XHC_PORTSC__PS_LINK_STATE_U2 2U +#define XHC_PORTSC__PS_LINK_STATE_U3 3U +#define XHC_PORTSC__PS_LINK_STATE_DISABLED 4U +#define XHC_PORTSC__PS_LINK_STATE_RX_DETECT 5U +#define XHC_PORTSC__PS_LINK_STATE_INACTIVE 6U +#define XHC_PORTSC__PS_LINK_STATE_POLLING 7U +#define XHC_PORTSC__PS_LINK_STATE_RECOVERY 8U +#define XHC_PORTSC__PS_LINK_STATE_HOT_RESET 9U +#define XHC_PORTSC__PS_LINK_STATE_COMPLIANCE 10U +#define XHC_PORTSC__PS_LINK_STATE_TEST 11U +#define XHC_PORTSC__PS_LINK_STATE_RESUME 15U + +#define XHC_PORTSC__PS_SPEED_UNDEFINED 0U +#define XHC_PORTSC__PS_FS 1U +#define XHC_PORTSC__PS_LS 2U +#define XHC_PORTSC__PS_HS 3U +#define XHC_PORTSC__PS_SS 4U + +/* macros and inline functions */ + +/* write 64bit ptr 'p' to destination 'd' with offset 'v' */ +inline void WRITE64_REG_PTRL(uint32_t r, uint32_t *p) +{ + uint32_t *ptr = (uint32_t *) (uint64_t) (XHC_BASE + r); + + *ptr = (uint32_t) ((uint64_t) p & (uint64_t) 0xffffffffU); +} + +inline void WRITE64_REG_PTRH(uint32_t r, uint32_t *p) +{ + uint32_t *ptr = (uint32_t *) (uint64_t) (XHC_BASE + r); + + *ptr = (uint32_t) ((uint64_t) p >> 32U); +} + +#define XHC_REG_RD(addr) mmio_read_32(XHC_BASE + addr) + +#define XHC_REG_WR(addr, val) mmio_write_32(XHC_BASE+addr, val) + +#endif /* USBH_XHCI_REGS_H */ + diff --git a/arm-trusted-firmware/include/drivers/cadence/cdns_uart.h b/arm-trusted-firmware/include/drivers/cadence/cdns_uart.h new file mode 100644 index 0000000..30ca910 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/cadence/cdns_uart.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CDNS_UART_H +#define CDNS_UART_H + +#include + +/* This is very minimalistic and will only work in QEMU. */ + +/* CADENCE Registers */ +#define R_UART_CR 0 +#define R_UART_CR_RXRST (1 << 0) /* RX logic reset */ +#define R_UART_CR_TXRST (1 << 1) /* TX logic reset */ +#define R_UART_CR_RX_EN (1 << 2) /* RX enabled */ +#define R_UART_CR_TX_EN (1 << 4) /* TX enabled */ + +#define R_UART_SR 0x2C +#define UART_SR_INTR_REMPTY_BIT 1 +#define UART_SR_INTR_TFUL_BIT 4 +#define UART_SR_INTR_TEMPTY_BIT 3 + +#define R_UART_TX 0x30 +#define R_UART_RX 0x30 + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new Cadence 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_cdns_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* CDNS_UART_H */ diff --git a/arm-trusted-firmware/include/drivers/cfi/v2m_flash.h b/arm-trusted-firmware/include/drivers/cfi/v2m_flash.h new file mode 100644 index 0000000..6beec50 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/cfi/v2m_flash.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef V2M_FLASH_H +#define V2M_FLASH_H + +#include + +/* First bus cycle */ +#define NOR_CMD_READ_ARRAY 0xFF +#define NOR_CMD_READ_ID_CODE 0x90 +#define NOR_CMD_READ_QUERY 0x98 +#define NOR_CMD_READ_STATUS_REG 0x70 +#define NOR_CMD_CLEAR_STATUS_REG 0x50 +#define NOR_CMD_WRITE_TO_BUFFER 0xE8 +#define NOR_CMD_WORD_PROGRAM 0x40 +#define NOR_CMD_BLOCK_ERASE 0x20 +#define NOR_CMD_LOCK_UNLOCK 0x60 +#define NOR_CMD_BLOCK_ERASE_ACK 0xD0 + +/* Second bus cycle */ +#define NOR_LOCK_BLOCK 0x01 +#define NOR_UNLOCK_BLOCK 0xD0 + +/* Status register bits */ +#define NOR_DWS (1 << 7) +#define NOR_ESS (1 << 6) +#define NOR_ES (1 << 5) +#define NOR_PS (1 << 4) +#define NOR_VPPS (1 << 3) +#define NOR_PSS (1 << 2) +#define NOR_BLS (1 << 1) +#define NOR_BWS (1 << 0) + +/* Public API */ +void nor_send_cmd(uintptr_t base_addr, unsigned long cmd); +int nor_word_program(uintptr_t base_addr, unsigned long data); +int nor_lock(uintptr_t base_addr); +int nor_unlock(uintptr_t base_addr); +int nor_erase(uintptr_t base_addr); + +#endif /* V2M_FLASH_H*/ diff --git a/arm-trusted-firmware/include/drivers/clk.h b/arm-trusted-firmware/include/drivers/clk.h new file mode 100644 index 0000000..a18f41f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/clk.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CLK_H +#define CLK_H + +#include + +struct clk_ops { + int (*enable)(unsigned long id); + void (*disable)(unsigned long id); + unsigned long (*get_rate)(unsigned long id); + int (*get_parent)(unsigned long id); + bool (*is_enabled)(unsigned long id); +}; + +int clk_enable(unsigned long id); +void clk_disable(unsigned long id); +unsigned long clk_get_rate(unsigned long id); +bool clk_is_enabled(unsigned long id); +int clk_get_parent(unsigned long id); + +void clk_register(const struct clk_ops *ops); + +#endif /* CLK_H */ diff --git a/arm-trusted-firmware/include/drivers/console.h b/arm-trusted-firmware/include/drivers/console.h new file mode 100644 index 0000000..99bf960 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/console_assertions.h b/arm-trusted-firmware/include/drivers/console_assertions.h new file mode 100644 index 0000000..00caa31 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h b/arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h new file mode 100644 index 0000000..30b39f1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CBMEM_CONSOLE_H +#define CBMEM_CONSOLE_H + +#include + +#define CONSOLE_T_CBMC_SIZE CONSOLE_T_DRVDATA + +#ifndef __ASSEMBLER__ + +typedef struct { + console_t console; + uint32_t size; +} console_cbmc_t; + +int console_cbmc_register(uintptr_t base, console_cbmc_t *console); + +#endif /* __ASSEMBLER__ */ + +#endif /* CBMEM_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/delay_timer.h b/arm-trusted-firmware/include/drivers/delay_timer.h new file mode 100644 index 0000000..20a5543 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/dw_ufs.h b/arm-trusted-firmware/include/drivers/dw_ufs.h new file mode 100644 index 0000000..13e53f1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/fwu/fwu.h b/arm-trusted-firmware/include/drivers/fwu/fwu.h new file mode 100644 index 0000000..9f18e22 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/fwu/fwu.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FWU_H +#define FWU_H + +#include + +void fwu_init(void); +bool fwu_is_trial_run_state(void); +const struct fwu_metadata *fwu_get_metadata(void); + +#endif /* FWU_H */ diff --git a/arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h b/arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h new file mode 100644 index 0000000..2e88de5 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * FWU metadata information as per the specification section 4.1: + * https://developer.arm.com/documentation/den0118/a/ + * + */ + +#ifndef FWU_METADATA_H +#define FWU_METADATA_H + +#include +#include + +/* Properties of image in a bank */ +struct fwu_image_properties { + + /* UUID of the image in this bank */ + uuid_t img_uuid; + + /* [0]: bit describing the image acceptance status – + * 1 means the image is accepted + * [31:1]: MBZ + */ + uint32_t accepted; + + /* reserved (MBZ) */ + uint32_t reserved; + +} __packed; + +/* Image entry information */ +struct fwu_image_entry { + + /* UUID identifying the image type */ + uuid_t img_type_uuid; + + /* UUID of the storage volume where the image is located */ + uuid_t location_uuid; + + /* Properties of images with img_type_uuid in the different FW banks */ + struct fwu_image_properties img_props[NR_OF_FW_BANKS]; + +} __packed; + +/* + * FWU metadata filled by the updater and consumed by TF-A for + * various purposes as below: + * 1. Get active FW bank. + * 2. Rollback to previous working FW bank. + * 3. Get properties of all images present in all banks. + */ +struct fwu_metadata { + + /* Metadata CRC value */ + uint32_t crc_32; + + /* Metadata version */ + uint32_t version; + + /* Bank index with which device boots */ + uint32_t active_index; + + /* Previous bank index with which device booted successfully */ + uint32_t previous_active_index; + + /* Image entry information */ + struct fwu_image_entry img_entry[NR_OF_IMAGES_IN_FW_BANK]; + +} __packed; + +#endif /* FWU_METADATA_H */ diff --git a/arm-trusted-firmware/include/drivers/generic_delay_timer.h b/arm-trusted-firmware/include/drivers/generic_delay_timer.h new file mode 100644 index 0000000..adba10f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/gpio.h b/arm-trusted-firmware/include/drivers/gpio.h new file mode 100644 index 0000000..9bba993 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/gpio.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016-2021, 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 +#define GPIO_PULL_REPEATER ARM_TF_GPIO_PULL_REPEATER + +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/arm-trusted-firmware/include/drivers/io/io_block.h b/arm-trusted-firmware/include/drivers/io/io_block.h new file mode 100644 index 0000000..c99e8c7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/io/io_driver.h b/arm-trusted-firmware/include/drivers/io/io_driver.h new file mode 100644 index 0000000..d8bb435 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/io/io_dummy.h b/arm-trusted-firmware/include/drivers/io/io_dummy.h new file mode 100644 index 0000000..edfc699 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/io/io_encrypted.h b/arm-trusted-firmware/include/drivers/io/io_encrypted.h new file mode 100644 index 0000000..9dcf061 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/io/io_fip.h b/arm-trusted-firmware/include/drivers/io/io_fip.h new file mode 100644 index 0000000..7e65436 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/io/io_memmap.h b/arm-trusted-firmware/include/drivers/io/io_memmap.h new file mode 100644 index 0000000..87e3466 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/io/io_mtd.h b/arm-trusted-firmware/include/drivers/io/io_mtd.h new file mode 100644 index 0000000..2b5d9b1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_mtd.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2019-2021, 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); + + /* + * Look for an offset to be added to the given offset. + * + * @base: Base address of the area. + * @offset: Offset in bytes to start read operation. + * @extra_offset: [out] Offset to be added to the previous offset. + * Return 0 on success, a negative error code otherwise. + */ + int (*seek)(uintptr_t base, unsigned int offset, size_t *extra_offset); +} io_mtd_ops_t; + +typedef struct io_mtd_dev_spec { + unsigned long long device_size; + unsigned int erase_size; + size_t offset; + 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/arm-trusted-firmware/include/drivers/io/io_semihosting.h b/arm-trusted-firmware/include/drivers/io/io_semihosting.h new file mode 100644 index 0000000..e90ea5c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/io/io_storage.h b/arm-trusted-firmware/include/drivers/io/io_storage.h new file mode 100644 index 0000000..f2d641c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/marvell/addr_map.h b/arm-trusted-firmware/include/drivers/marvell/addr_map.h new file mode 100644 index 0000000..0d219f2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/addr_map.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Address map types for Marvell address translation unit drivers */ + +#ifndef ADDR_MAP_H +#define ADDR_MAP_H + +#include + +struct addr_map_win { + uint64_t base_addr; + uint64_t win_size; + uint32_t target_id; +}; + +#endif /* ADDR_MAP_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/amb_adec.h b/arm-trusted-firmware/include/drivers/marvell/amb_adec.h new file mode 100644 index 0000000..a92db5b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/amb_adec.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AXI to M-Bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs */ + +#ifndef AMB_ADEC_H +#define AMB_ADEC_H + +#include + +enum amb_attribute_ids { + AMB_SPI0_CS0_ID = 0x1E, + AMB_SPI0_CS1_ID = 0x5E, + AMB_SPI0_CS2_ID = 0x9E, + AMB_SPI0_CS3_ID = 0xDE, + AMB_SPI1_CS0_ID = 0x1A, + AMB_SPI1_CS1_ID = 0x5A, + AMB_SPI1_CS2_ID = 0x9A, + AMB_SPI1_CS3_ID = 0xDA, + AMB_DEV_CS0_ID = 0x3E, + AMB_DEV_CS1_ID = 0x3D, + AMB_DEV_CS2_ID = 0x3B, + AMB_DEV_CS3_ID = 0x37, + AMB_BOOT_CS_ID = 0x2f, + AMB_BOOT_ROM_ID = 0x1D, +}; + +#define AMB_MAX_WIN_ID 7 + +int init_amb_adec(uintptr_t base); + +#endif /* AMB_ADEC_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h b/arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h new file mode 100644 index 0000000..4353b83 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef AP807_INIT_CLOCKS_H +#define AP807_INIT_CLOCKS_H + +void ap807_clocks_init(unsigned int freq_option); + +#endif /* AP807_INIT_CLOCKS_H */ + diff --git a/arm-trusted-firmware/include/drivers/marvell/aro.h b/arm-trusted-firmware/include/drivers/marvell/aro.h new file mode 100644 index 0000000..4d1094a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/aro.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ +#ifndef ARO_H +#define ARO_H + +enum hws_freq { + CPU_FREQ_2000, + CPU_FREQ_1800, + CPU_FREQ_1600, + CPU_FREQ_1400, + CPU_FREQ_1300, + CPU_FREQ_1200, + CPU_FREQ_1000, + CPU_FREQ_600, + CPU_FREQ_800, + DDR_FREQ_LAST, + DDR_FREQ_SAR +}; + +#include + +enum cpu_clock_freq_mode { + CPU_2000_DDR_1200_RCLK_1200 = 0x0, + CPU_2000_DDR_1050_RCLK_1050 = 0x1, + CPU_1600_DDR_800_RCLK_800 = 0x4, + CPU_2200_DDR_1200_RCLK_1200 = 0x6, + CPU_1800_DDR_1050_RCLK_1050 = 0x7, + CPU_1600_DDR_900_RCLK_900 = 0x0B, + CPU_1600_DDR_1050_RCLK_1050 = 0x0D, + CPU_1600_DDR_1200_RCLK_1200 = 0x0D, + CPU_1600_DDR_900_RCLK_900_2 = 0x0E, + CPU_1000_DDR_650_RCLK_650 = 0x13, + CPU_1300_DDR_800_RCLK_800 = 0x14, + CPU_1300_DDR_650_RCLK_650 = 0x17, + CPU_1200_DDR_800_RCLK_800 = 0x19, + CPU_1400_DDR_800_RCLK_800 = 0x1a, + CPU_600_DDR_800_RCLK_800 = 0x1B, + CPU_800_DDR_800_RCLK_800 = 0x1C, + CPU_1000_DDR_800_RCLK_800 = 0x1D, + CPU_DDR_RCLK_INVALID +}; + +int init_aro(void); + +#endif /* ARO_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/cache_llc.h b/arm-trusted-firmware/include/drivers/marvell/cache_llc.h new file mode 100644 index 0000000..72111b3 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/cache_llc.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018-2020 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* LLC driver is the Last Level Cache (L3C) driver + * for Marvell SoCs in AP806, AP807, and AP810 + */ + +#ifndef CACHE_LLC_H +#define CACHE_LLC_H + +#define LLC_CTRL(ap) (MVEBU_LLC_BASE(ap) + 0x100) +#define LLC_SECURE_CTRL(ap) (MVEBU_LLC_BASE(ap) + 0x10C) +#define LLC_SYNC(ap) (MVEBU_LLC_BASE(ap) + 0x700) +#define LLC_BANKED_MNT_AHR(ap) (MVEBU_LLC_BASE(ap) + 0x724) +#define LLC_INV_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x77C) +#define LLC_BLK_ALOC(ap) (MVEBU_LLC_BASE(ap) + 0x78c) +#define LLC_CLEAN_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x7BC) +#define LLC_CLEAN_INV_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x7FC) +#define LLC_TCN_LOCK(ap, tc) (MVEBU_LLC_BASE(ap) + 0x920 + 4 * (tc)) + +#define MASTER_LLC_CTRL LLC_CTRL(MVEBU_AP0) +#define MASTER_LLC_INV_WAY LLC_INV_WAY(MVEBU_AP0) +#define MASTER_LLC_TC0_LOCK LLC_TCN_LOCK(MVEBU_AP0, 0) + +#define LLC_CTRL_EN 1 +#define LLC_EXCLUSIVE_EN 0x100 +#define LLC_ALL_WAYS_MASK 0xFFFFFFFF + +/* AP806/AP807 - 1MB 8-ways LLC */ +#define LLC_WAYS 8 +#define LLC_WAY_MASK ((1 << LLC_WAYS) - 1) +#define LLC_SIZE (1024 * 1024) +#define LLC_WAY_SIZE (LLC_SIZE / LLC_WAYS) +#define LLC_TC_NUM 15 + +#define LLC_BLK_ALOC_WAY_ID(way) ((way) & 0x1f) +#define LLC_BLK_ALOC_WAY_DATA_DSBL (0x0 << 6) +#define LLC_BLK_ALOC_WAY_DATA_CLR (0x1 << 6) +#define LLC_BLK_ALOC_WAY_DATA_SET (0x3 << 6) +#define LLC_BLK_ALOC_BASE_ADDR(addr) ((addr) & ~(LLC_WAY_SIZE - 1)) + +#ifndef __ASSEMBLER__ +void llc_cache_sync(int ap_index); +void llc_flush_all(int ap_index); +void llc_clean_all(int ap_index); +void llc_inv_all(int ap_index); +void llc_disable(int ap_index); +void llc_enable(int ap_index, int excl_mode); +int llc_is_exclusive(int ap_index); +void llc_runtime_enable(int ap_index); +#if LLC_SRAM +int llc_sram_enable(int ap_index, int size); +void llc_sram_disable(int ap_index); +int llc_sram_test(int ap_index, int size, char *msg); +#endif /* LLC_SRAM */ +#endif /* __ASSEMBLER__ */ + +#endif /* CACHE_LLC_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/ccu.h b/arm-trusted-firmware/include/drivers/marvell/ccu.h new file mode 100644 index 0000000..f8f0adf --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/ccu.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* CCU unit device driver for Marvell AP807, AP807 and AP810 SoCs */ + +#ifndef CCU_H +#define CCU_H + +#ifndef __ASSEMBLER__ +#include +#endif + +/* CCU registers definitions */ +#define CCU_WIN_CR_OFFSET(ap, win) (MVEBU_CCU_BASE(ap) + 0x0 + \ + (0x10 * win)) +#define CCU_TARGET_ID_OFFSET (8) +#define CCU_TARGET_ID_MASK (0x7F) + +#define CCU_WIN_SCR_OFFSET(ap, win) (MVEBU_CCU_BASE(ap) + 0x4 + \ + (0x10 * win)) +#define CCU_WIN_ENA_WRITE_SECURE (0x1) +#define CCU_WIN_ENA_READ_SECURE (0x2) + +#define CCU_WIN_ALR_OFFSET(ap, win) (MVEBU_CCU_BASE(ap) + 0x8 + \ + (0x10 * win)) +#define CCU_WIN_AHR_OFFSET(ap, win) (MVEBU_CCU_BASE(ap) + 0xC + \ + (0x10 * win)) + +#define CCU_WIN_GCR_OFFSET(ap) (MVEBU_CCU_BASE(ap) + 0xD0) +#define CCU_GCR_TARGET_OFFSET (8) +#define CCU_GCR_TARGET_MASK (0xFF) + +#define CCU_SRAM_WIN_CR CCU_WIN_CR_OFFSET(MVEBU_AP0, 1) + +#ifndef __ASSEMBLER__ +int init_ccu(int); +void ccu_win_check(struct addr_map_win *win); +void ccu_enable_win(int ap_index, struct addr_map_win *win, uint32_t win_id); +void ccu_temp_win_insert(int ap_index, struct addr_map_win *win, int size); +void ccu_temp_win_remove(int ap_index, struct addr_map_win *win, int size); +void ccu_dram_win_config(int ap_index, struct addr_map_win *win); +void ccu_dram_target_set(int ap_index, uint32_t target); +void ccu_save_win_all(int ap_id); +void ccu_restore_win_all(int ap_id); +int ccu_is_win_enabled(int ap_index, uint32_t win_id); +void errata_wa_init(void); +#endif + +#endif /* CCU_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/gwin.h b/arm-trusted-firmware/include/drivers/marvell/gwin.h new file mode 100644 index 0000000..1b874a7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/gwin.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* GWIN unit device driver for Marvell AP810 SoC */ + +#ifndef GWIN_H +#define GWIN_H + +#include + +int init_gwin(int ap_index); +void gwin_temp_win_insert(int ap_index, struct addr_map_win *win, int size); +void gwin_temp_win_remove(int ap_index, struct addr_map_win *win, int size); + +#endif /* GWIN_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/i2c.h b/arm-trusted-firmware/include/drivers/marvell/i2c.h new file mode 100644 index 0000000..06c5114 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/i2c.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef I2C_H +#define I2C_H + + +void i2c_init(void); + +int i2c_read(uint8_t chip, + unsigned int addr, int alen, uint8_t *buffer, int len); + +int i2c_write(uint8_t chip, + unsigned int addr, int alen, uint8_t *buffer, int len); + +#endif /* I2C_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/io_win.h b/arm-trusted-firmware/include/drivers/marvell/io_win.h new file mode 100644 index 0000000..7438d6b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/io_win.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* IO Window unit device driver for Marvell AP807, AP807 and AP810 SoCs */ + +#ifndef IO_WIN_H +#define IO_WIN_H + +#include + +int init_io_win(int ap_index); +void iow_temp_win_insert(int ap_index, struct addr_map_win *win, int size); +void iow_temp_win_remove(int ap_index, struct addr_map_win *win, int size); +void iow_save_win_all(int ap_id); +void iow_restore_win_all(int ap_id); + +#endif /* IO_WIN_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/iob.h b/arm-trusted-firmware/include/drivers/marvell/iob.h new file mode 100644 index 0000000..9b5e515 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/iob.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* IOW unit device driver for Marvell CP110 and CP115 SoCs */ + +#ifndef IOB_H +#define IOB_H + +#include + +enum target_ids_iob { + INTERNAL_TID = 0x0, + MCI0_TID = 0x1, + PEX1_TID = 0x2, + PEX2_TID = 0x3, + PEX0_TID = 0x4, + NAND_TID = 0x5, + RUNIT_TID = 0x6, + MCI1_TID = 0x7, + IOB_MAX_TID +}; + +int init_iob(uintptr_t base); +void iob_cfg_space_update(int ap_idx, int cp_idx, + uintptr_t base, uintptr_t new_base); + +#endif /* IOB_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/mci.h b/arm-trusted-firmware/include/drivers/marvell/mci.h new file mode 100644 index 0000000..af5d620 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/mci.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* MCI bus driver for Marvell ARMADA 8K and 8K+ SoCs */ + +#ifndef MCI_H +#define MCI_H + +int mci_link_tune(int mci_index); +void mci_turn_link_down(void); +void mci_turn_link_on(void); +int mci_get_link_status(void); + +#endif /* MCI_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h b/arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h new file mode 100644 index 0000000..5b0e75f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AP8xx Marvell SoC driver */ + +#ifndef AP_SETUP_H +#define AP_SETUP_H + +void ap_init(void); +void ap_ble_init(void); +int ap_get_count(void); +void update_cp110_default_win(int cp_id); + +#endif /* AP_SETUP_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h b/arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h new file mode 100644 index 0000000..4a69257 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* CP110 Marvell SoC driver */ + +#ifndef CP110_SETUP_H +#define CP110_SETUP_H + +#include + +#include + +#define MVEBU_DEVICE_ID_REG (MVEBU_CP_DFX_OFFSET + 0x40) +#define MVEBU_DEVICE_ID_OFFSET (0) +#define MVEBU_DEVICE_ID_MASK (0xffff << MVEBU_DEVICE_ID_OFFSET) +#define MVEBU_DEVICE_REV_OFFSET (16) +#define MVEBU_DEVICE_REV_MASK (0xf << MVEBU_DEVICE_REV_OFFSET) +#define MVEBU_70X0_DEV_ID (0x7040) +#define MVEBU_70X0_CP115_DEV_ID (0x7045) +#define MVEBU_3900_DEV_ID (0x6025) +#define MVEBU_80X0_DEV_ID (0x8040) +#define MVEBU_80X0_CP115_DEV_ID (0x8045) +#define MVEBU_CN9130_DEV_ID (0x7025) +#define MVEBU_CP110_SA_DEV_ID (0x110) +#define MVEBU_CP110_REF_ID_A1 1 +#define MVEBU_CP110_REF_ID_A2 2 +#define MAX_STREAM_ID_PER_CP (0x10) +#define STREAM_ID_BASE (0x40) + +#define MVEBU_SECUREBOOT_CTRL_REG (MVEBU_RFU_BASE + 0x4730) +#define MVEBU_SECUREBOOT_EN_MASK BIT(0) + +static inline uint32_t cp110_device_id_get(uintptr_t base) +{ + /* Returns: + * - MVEBU_70X0_DEV_ID for A70X0 family + * - MVEBU_80X0_DEV_ID for A80X0 family + * - MVEBU_CP110_SA_DEV_ID for CP that connected stand alone + */ + return (mmio_read_32(base + MVEBU_DEVICE_ID_REG) >> + MVEBU_DEVICE_ID_OFFSET) & + MVEBU_DEVICE_ID_MASK; +} + +static inline uint32_t cp110_rev_id_get(uintptr_t base) +{ + return (mmio_read_32(base + MVEBU_DEVICE_ID_REG) & + MVEBU_DEVICE_REV_MASK) >> + MVEBU_DEVICE_REV_OFFSET; +} + +static inline uint32_t is_secure(void) +{ + return !!(mmio_read_32(MVEBU_SECUREBOOT_CTRL_REG) & + MVEBU_SECUREBOOT_EN_MASK); +} + +void cp110_init(uintptr_t cp110_base, uint32_t stream_id); +void cp110_ble_init(uintptr_t cp110_base); +void cp110_amb_init(uintptr_t base); + +#endif /* CP110_SETUP_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/thermal.h b/arm-trusted-firmware/include/drivers/marvell/thermal.h new file mode 100644 index 0000000..48376a7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/thermal.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Driver for thermal unit located in Marvell ARMADA 8K and compatible SoCs */ + +#ifndef THERMAL_H +#define THERMAL_H + +struct tsen_config { + /* thermal temperature parameters */ + int tsen_offset; + int tsen_gain; + int tsen_divisor; + /* thermal data */ + int tsen_ready; + void *regs_base; + /* thermal functionality */ + int (*ptr_tsen_probe)(struct tsen_config *cfg); + int (*ptr_tsen_read)(struct tsen_config *cfg, int *temp); +}; + +/* Thermal driver APIs */ +int marvell_thermal_init(struct tsen_config *tsen_cfg); +int marvell_thermal_read(struct tsen_config *tsen_cfg, int *temp); +struct tsen_config *marvell_thermal_config_get(void); + +#endif /* THERMAL_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h b/arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h new file mode 100644 index 0000000..ce673a1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef A3700_CONSOLE_H +#define A3700_CONSOLE_H + +#include +#include + +/* MVEBU UART Registers */ +#define UART_RX_REG 0x00 +#define UART_TX_REG 0x04 +#define UART_CTRL_REG 0x08 +#define UART_STATUS_REG 0x0c +#define UART_BAUD_REG 0x10 +#define UART_POSSR_REG 0x14 + +/* FIFO Control Register bits */ +#define UARTFCR_FIFOMD_16450 (0 << 6) +#define UARTFCR_FIFOMD_16550 (1 << 6) +#define UARTFCR_RXTRIG_1 (0 << 6) +#define UARTFCR_RXTRIG_4 (1 << 6) +#define UARTFCR_RXTRIG_8 (2 << 6) +#define UARTFCR_RXTRIG_16 (3 << 6) +#define UARTFCR_TXTRIG_1 (0 << 4) +#define UARTFCR_TXTRIG_4 (1 << 4) +#define UARTFCR_TXTRIG_8 (2 << 4) +#define UARTFCR_TXTRIG_16 (3 << 4) +#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */ +#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */ +#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */ +#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */ + +/* Line Control Register bits */ +#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */ +#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */ +#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */ +#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */ +#define UARTLCR_PAR (1 << 3) /* Parity */ +#define UARTLCR_STOP (1 << 2) /* Stop Bit */ +#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */ +#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */ +#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */ +#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */ + +/* Line Status Register bits */ +#define UARTLSR_TXFIFOFULL (1 << 11) /* Tx Fifo Full */ +#define UARTLSR_TXEMPTY (1 << 6) /* Tx Empty */ +#define UARTLSR_RXRDY (1 << 4) /* Rx Ready */ + +/* UART Control Register bits */ +#define UART_CTRL_RXFIFO_RESET (1 << 14) +#define UART_CTRL_TXFIFO_RESET (1 << 15) + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new a3700 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_a3700_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* A3700_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h b/arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h new file mode 100644 index 0000000..0a19f8a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EVENT_LOG_H +#define EVENT_LOG_H + +#include + +#include +#include +#include + +/* + * Set Event Log debug level to one of: + * + * LOG_LEVEL_ERROR + * LOG_LEVEL_INFO + * LOG_LEVEL_WARNING + * LOG_LEVEL_VERBOSE + */ +#if EVENT_LOG_LEVEL == LOG_LEVEL_ERROR +#define LOG_EVENT ERROR +#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE +#define LOG_EVENT NOTICE +#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING +#define LOG_EVENT WARN +#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO +#define LOG_EVENT INFO +#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE +#define LOG_EVENT VERBOSE +#else +#error "Not supported EVENT_LOG_LEVEL" +#endif + +/* Number of hashing algorithms supported */ +#define HASH_ALG_COUNT 1U + +#define EVLOG_INVALID_ID UINT32_MAX + +#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) + +/* + * Each event log entry has some metadata (i.e. a string) that identifies + * what is measured.These macros define these strings. + * Note that these strings follow the standardization recommendations + * defined in the Arm Server Base Security Guide (a.k.a. SBSG, Arm DEN 0086), + * where applicable. They should not be changed in the code. + * Where the SBSG does not make recommendations, we are free to choose any + * naming convention. + * The key thing is to choose meaningful strings so that when the TPM event + * log is used in attestation, the different components can be identified. + */ +#define EVLOG_BL2_STRING "BL_2" +#define EVLOG_BL31_STRING "SECURE_RT_EL3" +#if defined(SPD_opteed) +#define EVLOG_BL32_STRING "SECURE_RT_EL1_OPTEE" +#elif defined(SPD_tspd) +#define EVLOG_BL32_STRING "SECURE_RT_EL1_TSPD" +#elif defined(SPD_tlkd) +#define EVLOG_BL32_STRING "SECURE_RT_EL1_TLKD" +#elif defined(SPD_trusty) +#define EVLOG_BL32_STRING "SECURE_RT_EL1_TRUSTY" +#else +#define EVLOG_BL32_STRING "SECURE_RT_EL1_UNKNOWN" +#endif +#define EVLOG_BL32_EXTRA1_STRING "SECURE_RT_EL1_OPTEE_EXTRA1" +#define EVLOG_BL32_EXTRA2_STRING "SECURE_RT_EL1_OPTEE_EXTRA2" +#define EVLOG_BL33_STRING "BL_33" +#define EVLOG_FW_CONFIG_STRING "FW_CONFIG" +#define EVLOG_HW_CONFIG_STRING "HW_CONFIG" +#define EVLOG_NT_FW_CONFIG_STRING "NT_FW_CONFIG" +#define EVLOG_SCP_BL2_STRING "SYS_CTRL_2" +#define EVLOG_SOC_FW_CONFIG_STRING "SOC_FW_CONFIG" +#define EVLOG_STM32_STRING "STM32" +#define EVLOG_TB_FW_CONFIG_STRING "TB_FW_CONFIG" +#define EVLOG_TOS_FW_CONFIG_STRING "TOS_FW_CONFIG" +#define EVLOG_RMM_STRING "RMM" + +typedef struct { + unsigned int id; + const char *name; + unsigned int pcr; +} event_log_metadata_t; + +#define ID_EVENT_SIZE (sizeof(id_event_headers_t) + \ + (sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \ + sizeof(id_event_struct_data_t)) + +#define LOC_EVENT_SIZE (sizeof(event2_header_t) + \ + sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \ + sizeof(event2_data_t) + \ + sizeof(startup_locality_event_t)) + +#define LOG_MIN_SIZE (ID_EVENT_SIZE + LOC_EVENT_SIZE) + +#define EVENT2_HDR_SIZE (sizeof(event2_header_t) + \ + sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \ + sizeof(event2_data_t)) + +/* Functions' declarations */ +void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish); +void event_log_write_header(void); +void dump_event_log(uint8_t *log_addr, size_t log_size); +const event_log_metadata_t *plat_event_log_get_metadata(void); +int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size, + uint32_t data_id); +size_t event_log_get_cur_size(uint8_t *event_log_start); + +#endif /* EVENT_LOG_H */ diff --git a/arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h b/arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h new file mode 100644 index 0000000..ab27a08 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TCG_H +#define TCG_H + +#include + +#define TCG_ID_EVENT_SIGNATURE_03 "Spec ID Event03" +#define TCG_STARTUP_LOCALITY_SIGNATURE "StartupLocality" + +#define TCG_SPEC_VERSION_MAJOR_TPM2 2 +#define TCG_SPEC_VERSION_MINOR_TPM2 0 +#define TCG_SPEC_ERRATA_TPM2 2 + +/* + * Event types + * Ref. Table 9 Events + * TCG PC Client Platform Firmware Profile Specification. + */ +#define EV_PREBOOT_CERT U(0x00000000) +#define EV_POST_CODE U(0x00000001) +#define EV_UNUSED U(0x00000002) +#define EV_NO_ACTION U(0x00000003) +#define EV_SEPARATOR U(0x00000004) +#define EV_ACTION U(0x00000005) +#define EV_EVENT_TAG U(0x00000006) +#define EV_S_CRTM_CONTENTS U(0x00000007) +#define EV_S_CRTM_VERSION U(0x00000008) +#define EV_CPU_MICROCODE U(0x00000009) +#define EV_PLATFORM_CONFIG_FLAGS U(0x0000000A) +#define EV_TABLE_OF_DEVICES U(0x0000000B) +#define EV_COMPACT_HASH U(0x0000000C) +#define EV_IPL U(0x0000000D) +#define EV_IPL_PARTITION_DATA U(0x0000000E) +#define EV_NONHOST_CODE U(0x0000000F) +#define EV_NONHOST_CONFIG U(0x00000010) +#define EV_NONHOST_INFO U(0x00000011) +#define EV_OMIT_BOOT_DEVICE_EVENTS U(0x00000012) +#define EV_EFI_EVENT_BASE U(0x80000000) +#define EV_EFI_VARIABLE_DRIVER_CONFIG U(0x80000001) +#define EV_EFI_VARIABLE_BOOT U(0x80000002) +#define EV_EFI_BOOT_SERVICES_APPLICATION U(0x80000003) +#define EV_EFI_BOOT_SERVICES_DRIVER U(0x80000004) +#define EV_EFI_RUNTIME_SERVICES_DRIVER U(0x80000005) +#define EV_EFI_GPT_EVENT U(0x80000006) +#define EV_EFI_ACTION U(0x80000007) +#define EV_EFI_PLATFORM_FIRMWARE_BLOB U(0x80000008) +#define EV_EFI_HANDOFF_TABLES U(0x80000009) +#define EV_EFI_HCRTM_EVENT U(0x80000010) +#define EV_EFI_VARIABLE_AUTHORITY U(0x800000E0) + +/* + * TPM_ALG_ID constants. + * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants + * Trusted Platform Module Library. Part 2: Structures + */ +#define TPM_ALG_SHA256 0x000B +#define TPM_ALG_SHA384 0x000C +#define TPM_ALG_SHA512 0x000D + +/* TCG Platform Type */ +#define PLATFORM_CLASS_CLIENT 0 +#define PLATFORM_CLASS_SERVER 1 + +/* SHA digest sizes in bytes */ +#define SHA1_DIGEST_SIZE 20 +#define SHA256_DIGEST_SIZE 32 +#define SHA384_DIGEST_SIZE 48 +#define SHA512_DIGEST_SIZE 64 + +enum { + /* + * SRTM, BIOS, Host Platform Extensions, Embedded + * Option ROMs and PI Drivers + */ + PCR_0 = 0, + /* Host Platform Configuration */ + PCR_1, + /* UEFI driver and application Code */ + PCR_2, + /* UEFI driver and application Configuration and Data */ + PCR_3, + /* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */ + PCR_4, + /* + * Boot Manager Code Configuration and Data (for use + * by the Boot Manager Code) and GPT/Partition Table + */ + PCR_5, + /* Host Platform Manufacturer Specific */ + PCR_6, + /* Secure Boot Policy */ + PCR_7, + /* 8-15: Defined for use by the Static OS */ + PCR_8, + /* Debug */ + PCR_16 = 16 +}; + +#pragma pack(push, 1) + +/* + * PCR Event Header + * TCG EFI Protocol Specification + * 5.3 Event Log Header + */ +typedef struct { + /* PCRIndex: + * The PCR Index to which this event is extended + */ + uint32_t pcr_index; + + /* EventType: + * SHALL be an EV_NO_ACTION event + */ + uint32_t event_type; + + /* SHALL be 20 Bytes of 0x00 */ + uint8_t digest[SHA1_DIGEST_SIZE]; + + /* The size of the event */ + uint32_t event_size; + + /* SHALL be a TCG_EfiSpecIdEvent */ + uint8_t event[]; /* [event_data_size] */ +} tcg_pcr_event_t; + +/* + * Log Header Entry Data + * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize + * TCG PC Client Platform Firmware Profile 9.4.5.1 + */ +typedef struct { + /* Algorithm ID (hashAlg) of the Hash used by BIOS */ + uint16_t algorithm_id; + + /* The size of the digest produced by the implemented Hash algorithm */ + uint16_t digest_size; +} id_event_algorithm_size_t; + +/* + * TCG_EfiSpecIdEvent structure + * Ref. Table 15 TCG_EfiSpecIdEvent + * TCG PC Client Platform Firmware Profile 9.4.5.1 + */ +typedef struct { + /* + * The NUL-terminated ASCII string "Spec ID Event03". + * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44, + * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}. + */ + uint8_t signature[16]; + + /* + * The value for the Platform Class. + * The enumeration is defined in the TCG ACPI Specification Client + * Common Header. + */ + uint32_t platform_class; + + /* + * The PC Client Platform Profile Specification minor version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x00. + */ + uint8_t spec_version_minor; + + /* + * The PC Client Platform Profile Specification major version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x02. + */ + uint8_t spec_version_major; + + /* + * The PC Client Platform Profile Specification errata version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x02. + */ + uint8_t spec_errata; + + /* + * Specifies the size of the UINTN fields used in various data + * structures used in this specification. + * 0x01 indicates UINT32 and 0x02 indicates UINT64. + */ + uint8_t uintn_size; + + /* + * The number of Hash algorithms in the digestSizes field. + * This field MUST be set to a value of 0x01 or greater. + */ + uint32_t number_of_algorithms; + + /* + * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId + * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2 + * structure, the first of which is a Hash algorithmID and the second + * is the size of the respective digest. + */ + id_event_algorithm_size_t digest_size[]; /* number_of_algorithms */ +} id_event_struct_header_t; + +typedef struct { + /* + * Size in bytes of the VendorInfo field. + * Maximum value MUST be FFh bytes. + */ + uint8_t vendor_info_size; + + /* + * Provided for use by Platform Firmware implementer. The value might + * be used, for example, to provide more detailed information about the + * specific BIOS such as BIOS revision numbers, etc. The values within + * this field are not standardized and are implementer-specific. + * Platform-specific or -unique information MUST NOT be provided in + * this field. + * + */ + uint8_t vendor_info[]; /* [vendorInfoSize] */ +} id_event_struct_data_t; + +typedef struct { + id_event_struct_header_t struct_header; + id_event_struct_data_t struct_data; +} id_event_struct_t; + +typedef struct { + tcg_pcr_event_t header; + id_event_struct_header_t struct_header; +} id_event_headers_t; + +/* TPMT_HA Structure */ +typedef struct { + /* Selector of the hash contained in the digest that implies + * the size of the digest + */ + uint16_t algorithm_id; /* AlgorithmId */ + + /* Digest, depends on AlgorithmId */ + uint8_t digest[]; /* Digest[] */ +} tpmt_ha; + +/* + * TPML_DIGEST_VALUES Structure + */ +typedef struct { + /* The number of digests in the list */ + uint32_t count; /* Count */ + + /* The list of tagged digests, as sent to the TPM as part of a + * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command + */ + tpmt_ha digests[]; /* Digests[Count] */ +} tpml_digest_values; + +/* + * TCG_PCR_EVENT2 header + */ +typedef struct { + /* The PCR Index to which this event was extended */ + uint32_t pcr_index; /* PCRIndex */ + + /* Type of event */ + uint32_t event_type; /* EventType */ + + /* Digests: + * A counted list of tagged digests, which contain the digest of + * the event data (or external data) for all active PCR banks + */ + tpml_digest_values digests; /* Digests */ +} event2_header_t; + +typedef struct event2_data { + /* The size of the event data */ + uint32_t event_size; /* EventSize */ + + /* The data of the event */ + uint8_t event[]; /* Event[EventSize] */ +} event2_data_t; + +/* + * Startup Locality Event + * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3 + */ +typedef struct { + /* + * The NUL-terminated ASCII string "StartupLocality" SHALL be + * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63 + * 0x61 0x6C 0x69 0x74 0x79 0x00} + */ + uint8_t signature[16]; + + /* The Locality Indicator which sent the TPM2_Startup command */ + uint8_t startup_locality; +} startup_locality_event_t; + +#pragma pack(pop) + +#endif /* TCG_H */ diff --git a/arm-trusted-firmware/include/drivers/mentor/mi2cv.h b/arm-trusted-firmware/include/drivers/mentor/mi2cv.h new file mode 100644 index 0000000..85b733b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/mentor/mi2cv.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * Copyright (C) 2018 Icenowy Zheng + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* This driver provides support for Mentor Graphics MI2CV IP core */ + +#ifndef MI2CV_H +#define MI2CV_H + +#include + +/* + * Initialization, must be called once on start up, may be called + * repeatedly to change the speed and slave addresses. + */ +void i2c_init(void *i2c_base); + +/* + * Read/Write interface: + * chip: I2C chip address, range 0..127 + * addr: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Where to read/write the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int i2c_read(uint8_t chip, + unsigned int addr, int alen, uint8_t *buffer, int len); + +int i2c_write(uint8_t chip, + unsigned int addr, int alen, uint8_t *buffer, int len); + +#endif /* MI2CV_H */ diff --git a/arm-trusted-firmware/include/drivers/mmc.h b/arm-trusted-firmware/include/drivers/mmc.h new file mode 100644 index 0000000..834a80f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/mmc.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021, 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_PART_SWITCH_TIME 199 +#define CMD_EXTCSD_SEC_CNT 212 + +#define EXT_CSD_PART_CONFIG_ACC_MASK GENMASK(2, 0) +#define PART_CFG_BOOT_PARTITION1_ENABLE (U(1) << 3) +#define PART_CFG_BOOT_PARTITION1_ACCESS (U(1) << 0) +#define PART_CFG_BOOT_PART_EN_MASK GENMASK(5, 3) +#define PART_CFG_BOOT_PART_EN_SHIFT 3 +#define PART_CFG_CURRENT_BOOT_PARTITION(x) (((x) & PART_CFG_BOOT_PART_EN_MASK) >> \ + PART_CFG_BOOT_PART_EN_SHIFT) + +/* 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); +size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, 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/arm-trusted-firmware/include/drivers/nand.h b/arm-trusted-firmware/include/drivers/nand.h new file mode 100644 index 0000000..1b78ad4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nand.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_NAND_H +#define DRIVERS_NAND_H + +#include +#include + +#include + +#define PSEC_TO_MSEC(x) div_round_up((x), 1000000000ULL) + +struct ecc { + unsigned int mode; /* ECC mode NAND_ECC_MODE_{NONE|HW|ONDIE} */ + unsigned int size; /* Data byte per ECC step */ + unsigned int bytes; /* ECC bytes per step */ + unsigned int max_bit_corr; /* Max correctible bits per ECC steps */ +}; + +struct nand_device { + unsigned int block_size; + unsigned int page_size; + unsigned long long size; + unsigned int nb_planes; + unsigned int buswidth; + struct ecc ecc; + int (*mtd_block_is_bad)(unsigned int block); + int (*mtd_read_page)(struct nand_device *nand, unsigned int page, + uintptr_t buffer); +}; + +/* + * Read bytes from NAND device + * + * @offset: Byte offset to read from in device + * @buffer: [out] Bytes read from device + * @length: Number of bytes to read + * @length_read: [out] Number of bytes read from device + * Return: 0 on success, a negative errno on failure + */ +int nand_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read); + +/* + * Look for an extra offset to be added in case of bad blocks + * + * @base: Base address of the area + * @offset: Byte offset to read from in device + * @extra_offset: [out] Extra offset to be added if bad blocks are found + * Return: 0 on success, a negative errno on failure + */ +int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset); + +/* + * Get NAND device instance + * + * Return: NAND device instance reference + */ +struct nand_device *get_nand_device(void); + +#endif /* DRIVERS_NAND_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h b/arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h new file mode 100644 index 0000000..ae56d3b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h @@ -0,0 +1,155 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CSF_HDR_H +#define CSF_HDR_H + +#include "caam.h" +#include "hash.h" +#include "rsa.h" + +/* Barker code size in bytes */ +#define CSF_BARKER_LEN 4 /* barker code length in ESBC uboot client */ + /* header */ + +#ifdef CSF_HDR_CH3 +struct csf_hdr { + uint8_t barker[CSF_BARKER_LEN]; /* 0x00 Barker code */ + uint32_t srk_tbl_off; /* 0x04 SRK Table Offset */ + + struct { + uint8_t num_srk; /* 0x08 No. of keys */ + uint8_t srk_sel; /* Key no. to be used */ + uint8_t reserve; /* 0x0a rseerved */ + } len_kr; + uint8_t ie_flag; + + uint32_t uid_flag; + + uint32_t psign; /* 0x10 signature offset */ + uint32_t sign_len; /* 0x14 length of signature */ + + union { + struct { + uint32_t sg_table_offset; /* 0x18 SG Table Offset */ + uint32_t sg_entries; /* 0x1c no of entries in SG */ + } sg_isbc; + uint64_t img_addr; /* 64 bit pointer to ESBC Image */ + }; + + union { + struct { + uint32_t img_size; /* ESBC client img size in bytes */ + uint32_t ie_key_sel; + } img; + uint64_t entry_point; /* 0x20-0x24 ESBC entry point */ + }; + + uint32_t fsl_uid_0; /* 0x28 Freescale unique id 0 */ + uint32_t fsl_uid_1; /* 0x2c Freescale unique id 1 */ + uint32_t oem_uid_0; /* 0x30 OEM unique id 0 */ + uint32_t oem_uid_1; /* 0x34 OEM unique id 1 */ + uint32_t oem_uid_2; /* 0x38 OEM unique id 2 */ + uint32_t oem_uid_3; /* 0x3c OEM unique id 3 */ + uint32_t oem_uid_4; /* 0x40 OEM unique id 4 */ + + uint32_t reserved[3]; /* 0x44 - 0x4f */ +}; + +/* Srk table and key revocation check */ +#define UNREVOCABLE_KEY 8 +#define REVOC_KEY_ALIGN 7 +#define MAX_KEY_ENTRIES 8 + +#else + +/* CSF header for Chassis 2 */ +struct csf_hdr { + uint8_t barker[CSF_BARKER_LEN]; /* barker code */ + union { + uint32_t pkey; /* public key offset */ + uint32_t srk_tbl_off; + }; + + union { + uint32_t key_len; /* pub key length in bytes */ + struct { + uint32_t srk_table_flag:8; + uint32_t srk_sel:8; + uint32_t num_srk:16; + } len_kr; + }; + + uint32_t psign; /* signature offset */ + uint32_t sign_len; /* length of the signature in bytes */ + + /* SG Table used by ISBC header */ + union { + struct { + uint32_t sg_table_offset; /* 0x14 SG Table Offset */ + uint32_t sg_entries; /* no of entries in SG table */ + } sg_isbc; + struct { + uint32_t reserved1; /* Reserved field */ + uint32_t img_size; /* ESBC img size in bytes */ + } img; + }; + + uint32_t entry_point; /* ESBC client entry point */ + uint32_t reserved2; /* Scatter gather flag */ + uint32_t uid_flag; + uint32_t fsl_uid_0; + uint32_t oem_uid_0; + uint32_t reserved3[2]; + uint32_t fsl_uid_1; + uint32_t oem_uid_1; + + /* The entries below aren't present in ISBC header */ + uint64_t img_addr; /* 64 bit pointer to ESBC Image */ + uint32_t ie_flag; + uint32_t ie_key_sel; +}; + +/* Srk table and key revocation check */ +#define UNREVOCABLE_KEY 4 +#define REVOC_KEY_ALIGN 3 +#define MAX_KEY_ENTRIES 4 + +#endif + +struct srk_table { + uint32_t key_len; + uint8_t pkey[2 * RSA_4K_KEY_SZ_BYTES]; +}; + +/* + * This struct contains the following fields + * length of the segment + * Destination Target ID + * source address + * destination address + */ +struct sg_table { + uint32_t len; /* Length of Image */ + uint32_t res1; + union { + uint64_t src_addr; /* SRC Address of Image */ + struct { + uint32_t src_addr; + uint32_t dst_addr; + } img; + }; +}; + +int validate_esbc_header(void *img_hdr, void **img_key, uint32_t *key_len, + void **img_sign, uint32_t *sign_len, + enum sig_alg *algo); + +int calc_img_hash(struct csf_hdr *hdr, void *img_addr, uint32_t img_size, + uint8_t *img_hash, uint32_t *hash_len); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/console/plat_console.h b/arm-trusted-firmware/include/drivers/nxp/console/plat_console.h new file mode 100644 index 0000000..8b1b23a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/console/plat_console.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_CONSOLE_H +#define PLAT_CONSOLE_H + +#include +#include + +#if (NXP_CONSOLE == NS16550) +/* + * NXP specific UART - 16550 configuration + * + * Initialize a NXP 16550 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. + * When |clock| has a value of 0, the UART will *not* be initialised. This + * means the UART should already be enabled and the baudrate and clock setup + * should have been done already, either by platform specific code or by + * previous firmware stages. The |baud| parameter will be ignored in this + * case as well. + */ +int nxp_console_16550_register(uintptr_t baseaddr, uint32_t clock, + uint32_t baud, console_t *console); +#endif +/* + * Function to initialize platform's console + * and register with console framework + */ +void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div, + uint32_t baud); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h new file mode 100644 index 0000000..6cc1f3d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CAAM_H +#define CAAM_H + +#include "caam_io.h" +#include "sec_jr_driver.h" + + +/* Job ring 3 is reserved for usage by sec firmware */ +#define DEFAULT_JR 3 + +#if defined(CONFIG_CHASSIS_3_2) || defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_2) +#define CAAM_JR0_OFFSET 0x10000 +#define CAAM_JR1_OFFSET 0x20000 +#define CAAM_JR2_OFFSET 0x30000 +#define CAAM_JR3_OFFSET 0x40000 +#endif + +enum sig_alg { + RSA, + ECC +}; + +/* This function does basic SEC Initialization */ +int sec_init(uintptr_t nxp_caam_addr); +int config_sec_block(void); +uintptr_t get_caam_addr(void); + +/* This function is used to submit jobs to JR */ +int run_descriptor_jr(struct job_descriptor *desc); + +/* This function is used to instatiate the HW RNG is already not instantiated */ +int hw_rng_instantiate(void); + +/* This function is used to return random bytes of byte_len from HW RNG */ +int get_rand_bytes_hw(uint8_t *bytes, int byte_len); + +/* This function is used to set the hw unique key from HW CAAM */ +int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size); + +/* This function is used to fetch random number from + * CAAM of length either of 4 bytes or 8 bytes depending + * rngWidth value. + */ +unsigned long long get_random(int rngWidth); + +#endif /* CAAM_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h new file mode 100644 index 0000000..b68f836 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CAAM_IO_H +#define CAAM_IO_H + +#include +#include + +typedef unsigned long long phys_addr_t; +typedef unsigned long long phys_size_t; + +/* Return higher 32 bits of physical address */ +#define PHYS_ADDR_HI(phys_addr) \ + (uint32_t)(((uint64_t)phys_addr) >> 32) + +/* Return lower 32 bits of physical address */ +#define PHYS_ADDR_LO(phys_addr) \ + (uint32_t)(((uint64_t)phys_addr) & 0xFFFFFFFF) + +#ifdef NXP_SEC_BE +#define sec_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#define sec_in64(addr) ( \ + ((uint64_t)sec_in32((uintptr_t)(addr)) << 32) | \ + (sec_in32(((uintptr_t)(addr)) + 4))) +#define sec_out64(addr, val) ({ \ + sec_out32(((uintptr_t)(addr)), (uint32_t)((val) >> 32)); \ + sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)(val)); }) +#elif defined(NXP_SEC_LE) +#define sec_in32(a) mmio_read_32((uintptr_t)(a)) +#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#define sec_in64(addr) ( \ + ((uint64_t)sec_in32((uintptr_t)(addr) + 4) << 32) | \ + (sec_in32((uintptr_t)(addr)))) +#define sec_out64(addr, val) ({ \ + sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)((val) >> 32)); \ + sec_out32(((uintptr_t)(addr)), (uint32_t)(val)); }) +#else +#error Please define CCSR SEC register endianness +#endif + +static inline void *ptov(phys_addr_t *ptr) +{ + return (void *)ptr; +} + +static inline phys_addr_t *vtop(void *ptr) +{ + return (phys_addr_t *)ptr; +} +#endif /* CAAM_IO_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h new file mode 100644 index 0000000..9136dca --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h @@ -0,0 +1,85 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __HASH_H__ +#define __HASH_H__ + +#include + +/* List of hash algorithms */ +enum hash_algo { + SHA1 = 0, + SHA256 +}; + +/* number of bytes in the SHA256-256 digest */ +#define SHA256_DIGEST_SIZE 32 + +/* + * number of words in the digest - Digest is kept internally + * as 8 32-bit words + */ +#define _SHA256_DIGEST_LENGTH 8 + +/* + * block length - A block, treated as a sequence of + * 32-bit words + */ +#define SHA256_BLOCK_LENGTH 16 + +/* number of bytes in the block */ +#define SHA256_DATA_SIZE 64 + +#define MAX_SG 12 + +struct sg_entry { +#if defined(NXP_SEC_LE) + uint32_t addr_lo; /* Memory Address - lo */ + uint32_t addr_hi; /* Memory Address of start of buffer - hi */ +#else + uint32_t addr_hi; /* Memory Address of start of buffer - hi */ + uint32_t addr_lo; /* Memory Address - lo */ +#endif + + uint32_t len_flag; /* Length of the data in the frame */ +#define SG_ENTRY_LENGTH_MASK 0x3FFFFFFF +#define SG_ENTRY_EXTENSION_BIT 0x80000000 +#define SG_ENTRY_FINAL_BIT 0x40000000 + uint32_t bpid_offset; +#define SG_ENTRY_BPID_MASK 0x00FF0000 +#define SG_ENTRY_BPID_SHIFT 16 +#define SG_ENTRY_OFFSET_MASK 0x00001FFF +#define SG_ENTRY_OFFSET_SHIFT 0 +}; + +/* + * SHA256-256 context + * contain the following fields + * State + * count low + * count high + * block data buffer + * index to the buffer + */ +struct hash_ctx { + struct sg_entry sg_tbl[MAX_SG]; + uint32_t hash_desc[64]; + uint8_t hash[SHA256_DIGEST_SIZE]; + uint32_t sg_num; + uint32_t len; + uint8_t *data; + enum hash_algo algo; + bool active; +}; + +int hash_init(enum hash_algo algo, void **ctx); +int hash_update(enum hash_algo algo, void *context, void *data_ptr, + unsigned int data_len); +int hash_final(enum hash_algo algo, void *context, void *hash_ptr, + unsigned int hash_len); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h new file mode 100644 index 0000000..efef228 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __JOBDESC_H +#define __JOBDESC_H + +#include + +#define DESC_LEN_MASK 0x7f +#define DESC_START_SHIFT 16 + +#define KEY_BLOB_SIZE 32 +#define MAC_SIZE 16 + +#define KEY_IDNFR_SZ_BYTES 16 +#define CLASS_SHIFT 25 +#define CLASS_2 (0x02 << CLASS_SHIFT) + +#define CMD_SHIFT 27 +#define CMD_OPERATION (U(0x10) << CMD_SHIFT) + +#define OP_TYPE_SHIFT 24 +#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT) + +/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */ +#define OP_PCLID_SHIFT 16 +#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT) + +#define BLOB_PROTO_INFO 0x00000002 + +uint32_t desc_length(uint32_t *desc); + +int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle, + uint32_t *add_inp, uint32_t add_ip_len, + uint8_t *out_data, uint32_t len); + +int cnstr_rng_instantiate_jobdesc(uint32_t *desc); + +/* Construct descriptor to generate hw key blob */ +int cnstr_hw_encap_blob_jobdesc(uint32_t *desc, + uint8_t *key_idnfr, uint32_t key_sz, + uint32_t key_class, uint8_t *plain_txt, + uint32_t in_sz, uint8_t *enc_blob, + uint32_t out_sz, uint32_t operation); + +void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz, + uint8_t *digest); + +void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, + struct pk_in_params *pkin, uint8_t *out, + uint32_t out_siz); +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h new file mode 100644 index 0000000..1b3c447 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h @@ -0,0 +1,205 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _JR_DRIVER_CONFIG_H_ +#define _JR_DRIVER_CONFIG_H_ + +/* Helper defines */ + + /* Define used for setting a flag on */ +#define ON 1 + /* Define used for setting a flag off */ +#define OFF 0 + + /* SEC is configured to start work in polling mode, */ +#define SEC_STARTUP_POLLING_MODE 0 +/* + * SEC is configured to start work in interrupt mode, + * when configured for NAPI notification style. + */ +#define SEC_STARTUP_INTERRUPT_MODE 1 + +/* + * SEC driver will use ONLY interrupts to receive notifications + * for processed packets from SEC engine hardware. + */ +#define SEC_NOTIFICATION_TYPE_IRQ 1 +/* + * SEC driver will use ONLY polling to receive notifications + * for processed packets from SEC engine hardware. + */ +#define SEC_NOTIFICATION_TYPE_POLL 2 + +/* + * Determines how SEC user space driver will receive notifications + * for processed packets from SEC engine. + * Valid values are: #SEC_NOTIFICATION_TYPE_POLL, #SEC_NOTIFICATION_TYPE_IRQ + */ +#define SEC_NOTIFICATION_TYPE SEC_NOTIFICATION_TYPE_POLL + + /* Maximum number of job rings supported by SEC hardware */ +#define MAX_SEC_JOB_RINGS 1 + +/* + * Size of cryptographic context that is used directly in communicating + * with SEC device. + * SEC device works only with physical addresses. This is the maximum size + * for a SEC descriptor ( = 64 words). + */ + +#define SEC_CRYPTO_DESCRIPTOR_SIZE 256 + +/* + * Size of job descriptor submitted to SEC device for each packet to be + * processed. + * Job descriptor contains 3 DMA address pointers: + * - to shared descriptor, to input buffer and to output buffer. + * The job descriptor contains other SEC specific commands as well: + * - HEADER command, SEQ IN PTR command SEQ OUT PTR command and opaque + * data, each measuring 4 bytes. + * Job descriptor size, depending on physical address representation: + * - 32 bit - size is 28 bytes - cacheline-aligned size is 64 bytes + * - 36 bit - size is 40 bytes - cacheline-aligned size is 64 bytes + * @note: Job descriptor must be cacheline-aligned to ensure efficient memory + * access. + * @note: If other format is used for job descriptor, then the size must be + * revised. + */ + +#define SEC_JOB_DESCRIPTOR_SIZE 64 + +/* + * Size of one entry in the input ring of a job ring. + * Input ring contains pointers to job descriptors. + * The memory used for an input ring and output ring must be physically + * contiguous. + */ + +#define SEC_JOB_INPUT_RING_ENTRY_SIZE sizeof(phys_addr_t) + +/* + * Size of one entry in the output ring of a job ring. + * Output ring entry is a pointer to a job descriptor followed by a 4 byte + * status word. + * The memory used for an input ring and output ring must be physically + * contiguous. + * @note If desired to use also the optional SEQ OUT indication in output + * ring entries, then 4 more bytes must be added to the size. + */ + +#define SEC_JOB_OUTPUT_RING_ENTRY_SIZE (SEC_JOB_INPUT_RING_ENTRY_SIZE + 4) + + /* DMA memory required for an input ring of a job ring. */ +#define SEC_DMA_MEM_INPUT_RING_SIZE \ + ((SEC_JOB_INPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE)) + +/* + * DMA memory required for an output ring of a job ring. + * Required extra 4 byte for status word per each entry. + */ +#define SEC_DMA_MEM_OUTPUT_RING_SIZE \ + ((SEC_JOB_OUTPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE)) + + /* DMA memory required for descriptors of a job ring. */ +#define SEC_DMA_MEM_DESCRIPTORS \ + ((SEC_CRYPTO_DESCRIPTOR_SIZE)*(SEC_JOB_RING_SIZE)) + + /* DMA memory required for a job ring, including both input output rings. */ +#define SEC_DMA_MEM_JOB_RING_SIZE \ + ((SEC_DMA_MEM_INPUT_RING_SIZE) + \ + (SEC_DMA_MEM_OUTPUT_RING_SIZE)) + +/* + * When calling sec_init() UA will provide an area of virtual memory + * of size #SEC_DMA_MEMORY_SIZE to be used internally by the driver + * to allocate data (like SEC descriptors) that needs to be passed to + * SEC device in physical addressing and later on retrieved from SEC device. + * At initialization the UA provides specialized ptov/vtop functions/macros to + * translate addresses allocated from this memory area. + */ +#define SEC_DMA_MEMORY_SIZE \ + ((SEC_DMA_MEM_JOB_RING_SIZE) * (MAX_SEC_JOB_RINGS)) + +/* + * SEC DEVICE related configuration. + + * Enable/Disable logging support at compile time. + * Valid values: + * ON - enable logging + * OFF - disable logging + * The messages are logged at stdout. + */ + +#define SEC_DRIVER_LOGGING OFF + +/* + * Configure logging level at compile time. + * Valid values: + * SEC_DRIVER_LOG_ERROR - log only errors + * SEC_DRIVER_LOG_INFO - log errors and info messages + * SEC_DRIVER_LOG_DEBUG - log errors, info and debug messages + */ + +#define SEC_DRIVER_LOGGING_LEVEL SEC_DRIVER_LOG_DEBUG + +/* + * SEC JOB RING related configuration. + + * Configure the size of the JOB RING. + * The maximum size of the ring is hardware limited to 1024. + * However the number of packets in flight in a time interval of + * 1ms can be calculated + * from the traffic rate (Mbps) and packet size. + * Here it was considered a packet size of 40 bytes. + * @note Round up to nearest power of 2 for optimized update + * of producer/consumer indexes of each job ring + * \todo Should set to 750, according to the calculation above, but + * the JR size must be power of 2, thus the next closest value must + * be chosen (i.e. 512 since 1024 is not available) + * For firmware choose this to be 16 + */ + +#define SEC_JOB_RING_SIZE 16 + +/* + * Interrupt coalescing related configuration. + * NOTE: SEC hardware enabled interrupt + * coalescing is not supported on SEC version 3.1! + * SEC version 4.4 has support for interrupt + * coalescing. + */ + +#if SEC_NOTIFICATION_TYPE != SEC_NOTIFICATION_TYPE_POLL + +#define SEC_INT_COALESCING_ENABLE ON +/* + * Interrupt Coalescing Descriptor Count Threshold. + * While interrupt coalescing is enabled (ICEN=1), this value determines + * how many Descriptors are completed before raising an interrupt. + * Valid values for this field are from 0 to 255. + * Note that a value of 1 functionally defeats the advantages of interrupt + * coalescing since the threshold value is reached each time that a + * Job Descriptor is completed. A value of 0 is treated in the same + * manner as a value of 1. + * + */ +#define SEC_INTERRUPT_COALESCING_DESCRIPTOR_COUNT_THRESH 10 + +/* + * Interrupt Coalescing Timer Threshold. + * While interrupt coalescing is enabled (ICEN=1), this value determines the + * maximum amount of time after processing a Descriptor before raising an + * interrupt. + * The threshold value is represented in units equal to 64 CAAM interface + * clocks. Valid values for this field are from 1 to 65535. + * A value of 0 results in behavior identical to that when interrupt + * coalescing is disabled. + */ +#define SEC_INTERRUPT_COALESCING_TIMER_THRESH 100 +#endif /* SEC_NOTIFICATION_TYPE_POLL */ + +#endif /* _JR_DRIVER_CONFIG_H_ */ diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h new file mode 100644 index 0000000..dd9ecdc --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _RSA_H__ +#define _RSA_H__ + +/* RSA key size defines */ +#define RSA_4K_KEY_SZ 4096 +#define RSA_4K_KEY_SZ_BYTES (RSA_4K_KEY_SZ/8) +#define RSA_2K_KEY_SZ 2048 +#define RSA_2K_KEY_SZ_BYTES (RSA_2K_KEY_SZ/8) +#define RSA_1K_KEY_SZ 1024 +#define RSA_1K_KEY_SZ_BYTES (RSA_1K_KEY_SZ/8) + +#define SHA256_BYTES (256/8) + +struct pk_in_params { + uint8_t *e; + uint32_t e_siz; + uint8_t *n; + uint32_t n_siz; + uint8_t *a; + uint32_t a_siz; + uint8_t *b; + uint32_t b_siz; +}; + +struct rsa_context { + struct pk_in_params pkin; +}; + +int rsa_verify_signature(void *hash_ptr, unsigned int hash_len, + void *sig_ptr, unsigned int sig_len, + void *pk_ptr, unsigned int pk_len); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h new file mode 100644 index 0000000..9800793 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h @@ -0,0 +1,503 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _SEC_HW_SPECIFIC_H_ +#define _SEC_HW_SPECIFIC_H_ + +#include "caam.h" +#include "sec_jr_driver.h" + + /* DEFINES AND MACROS */ + +/* Used to retry resetting a job ring in SEC hardware. */ +#define SEC_TIMEOUT 100000 + +/* + * Offset to the registers of a job ring. + *Is different for each job ring. + */ +#define CHAN_BASE(jr) ((phys_addr_t)(jr)->register_base_addr) + +#define unlikely(x) __builtin_expect(!!(x), 0) + +#define SEC_JOB_RING_IS_FULL(pi, ci, ring_max_size, ring_threshold) \ + ((((pi) + 1 + ((ring_max_size) - (ring_threshold))) & \ + (ring_max_size - 1)) == ((ci))) + +#define SEC_CIRCULAR_COUNTER(x, max) (((x) + 1) & (max - 1)) + + /* Struct representing various job ring registers */ +struct jobring_regs { +#ifdef NXP_SEC_BE + unsigned int irba_h; + unsigned int irba_l; +#else + unsigned int irba_l; + unsigned int irba_h; +#endif + unsigned int rsvd1; + unsigned int irs; + unsigned int rsvd2; + unsigned int irsa; + unsigned int rsvd3; + unsigned int irja; +#ifdef NXP_SEC_BE + unsigned int orba_h; + unsigned int orba_l; +#else + unsigned int orba_l; + unsigned int orba_h; +#endif + unsigned int rsvd4; + unsigned int ors; + unsigned int rsvd5; + unsigned int orjr; + unsigned int rsvd6; + unsigned int orsf; + unsigned int rsvd7; + unsigned int jrsta; + unsigned int rsvd8; + unsigned int jrint; + unsigned int jrcfg0; + unsigned int jrcfg1; + unsigned int rsvd9; + unsigned int irri; + unsigned int rsvd10; + unsigned int orwi; + unsigned int rsvd11; + unsigned int jrcr; +}; + + /* Offsets representing common SEC Registers */ +#define SEC_REG_MCFGR_OFFSET 0x0004 +#define SEC_REG_SCFGR_OFFSET 0x000C +#define SEC_REG_JR0ICIDR_MS_OFFSET 0x0010 +#define SEC_REG_JR0ICIDR_LS_OFFSET 0x0014 +#define SEC_REG_JR1ICIDR_MS_OFFSET 0x0018 +#define SEC_REG_JR1ICIDR_LS_OFFSET 0x001C +#define SEC_REG_JR2ICIDR_MS_OFFSET 0x0020 +#define SEC_REG_JR2ICIDR_LS_OFFSET 0x0024 +#define SEC_REG_JR3ICIDR_MS_OFFSET 0x0028 +#define SEC_REG_JR3ICIDR_LS_OFFSET 0x002C +#define SEC_REG_JRSTARTR_OFFSET 0x005C +#define SEC_REG_CTPR_MS_OFFSET 0x0FA8 + + /* Offsets representing various RNG registers */ +#define RNG_REG_RTMCTL_OFFSET 0x0600 +#define RNG_REG_RTSDCTL_OFFSET 0x0610 +#define RNG_REG_RTFRQMIN_OFFSET 0x0618 +#define RNG_REG_RTFRQMAX_OFFSET 0x061C +#define RNG_REG_RDSTA_OFFSET 0x06C0 +#define ALG_AAI_SH_SHIFT 4 + + /* SEC Registers Bitmasks */ +#define MCFGR_PS_SHIFT 16 +#define MCFGR_AWCACHE_SHIFT 8 +#define MCFGR_AWCACHE_MASK (0xF << MCFGR_AWCACHE_SHIFT) +#define MCFGR_ARCACHE_SHIFT 12 +#define MCFGR_ARCACHE_MASK (0xF << MCFGR_ARCACHE_SHIFT) + +#define SCFGR_RNGSH0 0x00000200 +#define SCFGR_VIRT_EN 0x00008000 + +#define JRICID_MS_LICID 0x80000000 +#define JRICID_MS_LAMTD 0x00020000 +#define JRICID_MS_AMTDT 0x00010000 +#define JRICID_MS_TZ 0x00008000 +#define JRICID_LS_SDID_MASK 0x00000FFF +#define JRICID_LS_NSEQID_MASK 0x0FFF0000 +#define JRICID_LS_NSEQID_SHIFT 16 +#define JRICID_LS_SEQID_MASK 0x00000FFF + +#define JRSTARTR_STARTJR0 0x00000001 +#define JRSTARTR_STARTJR1 0x00000002 +#define JRSTARTR_STARTJR2 0x00000004 +#define JRSTARTR_STARTJR3 0x00000008 + +#define CTPR_VIRT_EN_POR 0x00000002 +#define CTPR_VIRT_EN_INC 0x00000001 + + /* RNG RDSTA bitmask */ +#define RNG_STATE0_HANDLE_INSTANTIATED 0x00000001 +#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */ + /* use von Neumann data in both entropy shifter and statistical checker */ +#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC 0 + /* use raw data in both entropy shifter and statistical checker */ +#define RTMCTL_SAMP_MODE_RAW_ES_SC 1 + /* use von Neumann data in entropy shifter, raw data in statistical checker */ +#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_RAW_SC 2 + /* invalid combination */ +#define RTMCTL_SAMP_MODE_INVALID 3 +#define RTSDCTL_ENT_DLY_MIN 3200 +#define RTSDCTL_ENT_DLY_MAX 12800 +#define RTSDCTL_ENT_DLY_SHIFT 16 +#define RTSDCTL_ENT_DLY_MASK (U(0xffff) << RTSDCTL_ENT_DLY_SHIFT) +#define RTFRQMAX_DISABLE (1 << 20) + + /* Constants for error handling on job ring */ +#define JR_REG_JRINT_ERR_TYPE_SHIFT 8 +#define JR_REG_JRINT_ERR_ORWI_SHIFT 16 +#define JR_REG_JRINIT_JRE_SHIFT 1 + +#define JRINT_JRE (1 << JR_REG_JRINIT_JRE_SHIFT) +#define JRINT_ERR_WRITE_STATUS (1 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_BAD_INPUT_BASE (3 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_BAD_OUTPUT_BASE (4 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_WRITE_2_IRBA (5 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_WRITE_2_ORBA (6 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_RES_B4_HALT (7 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_REM_TOO_MANY (8 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_ADD_TOO_MANY (9 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_HALT_MASK 0x0C +#define JRINT_ERR_HALT_INPROGRESS 0x04 +#define JRINT_ERR_HALT_COMPLETE 0x08 + +#define JR_REG_JRCR_VAL_RESET 0x00000001 + +#define JR_REG_JRCFG_LO_ICTT_SHIFT 0x10 +#define JR_REG_JRCFG_LO_ICDCT_SHIFT 0x08 +#define JR_REG_JRCFG_LO_ICEN_EN 0x02 +#define JR_REG_JRCFG_LO_IMSK_EN 0x01 + + /* Constants for Descriptor Processing errors */ +#define SEC_HW_ERR_SSRC_NO_SRC 0x00 +#define SEC_HW_ERR_SSRC_CCB_ERR 0x02 +#define SEC_HW_ERR_SSRC_JMP_HALT_U 0x03 +#define SEC_HW_ERR_SSRC_DECO 0x04 +#define SEC_HW_ERR_SSRC_JR 0x06 +#define SEC_HW_ERR_SSRC_JMP_HALT_COND 0x07 + +#define SEC_HW_ERR_DECO_HFN_THRESHOLD 0xF1 +#define SEC_HW_ERR_CCB_ICV_CHECK_FAIL 0x0A + + /* Macros for extracting error codes for the job ring */ + +#define JR_REG_JRINT_ERR_TYPE_EXTRACT(value) \ + ((value) & 0x00000F00) + +#define JR_REG_JRINT_ERR_ORWI_EXTRACT(value) \ + (((value) & 0x3FFF0000) >> \ + JR_REG_JRINT_ERR_ORWI_SHIFT) + +#define JR_REG_JRINT_JRE_EXTRACT(value) \ + ((value) & JRINT_JRE) + + /* Macros for manipulating JR registers */ +typedef struct { +#ifdef NXP_SEC_BE + uint32_t high; + uint32_t low; +#else + uint32_t low; + uint32_t high; +#endif +} ptr_addr_t; + +#if defined(CONFIG_PHYS_64BIT) +#define sec_read_addr(a) sec_in64((a)) +#define sec_write_addr(a, v) sec_out64((a), (v)) +#else +#define sec_read_addr(a) sec_in32((a)) +#define sec_write_addr(a, v) sec_out32((a), (v)) +#endif + +#define JR_REG(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET) +#define JR_REG_LO(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET_LO) + +#define GET_JR_REG(name, jr) (sec_in32(JR_REG(name, (jr)))) +#define GET_JR_REG_LO(name, jr) (sec_in32(JR_REG_LO(name, (jr)))) + +#define SET_JR_REG(name, jr, val) \ + (sec_out32(JR_REG(name, (jr)), (val))) + +#define SET_JR_REG_LO(name, jr, val) \ + (sec_out32(JR_REG_LO(name, (jr)), (val))) + + /* STRUCTURES AND OTHER TYPEDEFS */ + /* Lists the possible states for a job ring. */ +typedef enum sec_job_ring_state_e { + SEC_JOB_RING_STATE_STARTED, /* Job ring is initialized */ + SEC_JOB_RING_STATE_RESET, /* Job ring reset is in progres */ +} sec_job_ring_state_t; + +struct sec_job_ring_t { + /* + * Consumer index for job ring (jobs array). + * @note: cidx and pidx are accessed from + * different threads. + * Place the cidx and pidx inside the structure + * so that they lay on different cachelines, to + * avoid false sharing between threads when the + * threads run on different cores! + */ + uint32_t cidx; + + /* Producer index for job ring (jobs array) */ + uint32_t pidx; + + /* Ring of input descriptors. Size of array is power of 2 to allow + * fast update of producer/consumer indexes with bitwise operations. + */ + phys_addr_t *input_ring; + + /* Ring of output descriptors. */ + struct sec_outring_entry *output_ring; + + /* The file descriptor used for polling for interrupts notifications */ + uint32_t irq_fd; + + /* Model used by SEC Driver to receive notifications from SEC. + * Can be either of the three: + * #SEC_NOTIFICATION_TYPE_IRQ or + * #SEC_NOTIFICATION_TYPE_POLL + */ + uint32_t jr_mode; + /* Base address for SEC's register memory for this job ring. */ + void *register_base_addr; + /* notifies if coelescing is enabled for the job ring */ + uint8_t coalescing_en; + /* The state of this job ring */ + sec_job_ring_state_t jr_state; +}; + + /* Forward structure declaration */ +typedef struct sec_job_ring_t sec_job_ring_t; + +struct sec_outring_entry { + phys_addr_t desc; /* Pointer to completed descriptor */ + uint32_t status; /* Status for completed descriptor */ +} __packed; + + /* Lists the states possible for the SEC user space driver. */ +typedef enum sec_driver_state_e { + SEC_DRIVER_STATE_IDLE, /*< Driver not initialized */ + SEC_DRIVER_STATE_STARTED, /*< Driver initialized and */ + SEC_DRIVER_STATE_RELEASE, /*< Driver release is in progress */ +} sec_driver_state_t; + + /* Union describing the possible error codes that */ + /* can be set in the descriptor status word */ + +union hw_error_code { + uint32_t error; + union { + struct { + uint32_t ssrc:4; + uint32_t ssed_val:28; + } __packed value; + struct { + uint32_t ssrc:4; + uint32_t res:28; + } __packed no_status_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t cha_id:4; + uint32_t err_id:4; + } __packed ccb_status_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t offset:8; + } __packed jmp_halt_user_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t desc_err:8; + } __packed deco_src; + struct { + uint32_t ssrc:4; + uint32_t res:17; + uint32_t naddr:3; + uint32_t desc_err:8; + } __packed jr_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t cond:8; + } __packed jmp_halt_cond_src; + } __packed error_desc; +} __packed; + + /* FUNCTION PROTOTYPES */ + +/* + * @brief Initialize a job ring/channel in SEC device. + * Write configuration register/s to properly initialize a job ring. + * + * @param [in] job_ring The job ring + * + * @retval 0 for success + * @retval other for error + */ +int hw_reset_job_ring(sec_job_ring_t *job_ring); + +/* + * @brief Reset a job ring/channel in SEC device. + * Write configuration register/s to reset a job ring. + * + * @param [in] job_ring The job ring + * + * @retval 0 for success + * @retval -1 in case job ring reset failed + */ +int hw_shutdown_job_ring(sec_job_ring_t *job_ring); + +/* + * @brief Handle a job ring/channel error in SEC device. + * Identify the error type and clear error bits if required. + * + * @param [in] job_ring The job ring + * @param [in] sec_error_code error code as first read from SEC engine + */ + +void hw_handle_job_ring_error(sec_job_ring_t *job_ring, + uint32_t sec_error_code); +/* + * @brief Handle a job ring error in the device. + * Identify the error type and printout a explanatory + * messages. + * + * @param [in] job_ring The job ring + * + */ + +int hw_job_ring_error(sec_job_ring_t *job_ring); + +/* @brief Set interrupt coalescing parameters on the Job Ring. + * @param [in] job_ring The job ring + * @param [in] irq_coalesing_timer + * Interrupt coalescing timer threshold. + * This value determines the maximum + * amount of time after processing a descriptor + * before raising an interrupt. + * @param [in] irq_coalescing_count + * Interrupt coalescing count threshold. + * This value determines how many descriptors + * are completed before raising an interrupt. + */ + +int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count); + +/* @brief Enable interrupt coalescing on a job ring + * @param [in] job_ring The job ring + */ + +int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring); + +/* + * @brief Disable interrupt coalescing on a job ring + * @param [in] job_ring The job ring + */ + +int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring); + +/* + * @brief Poll the HW for already processed jobs in the JR + * and notify the available jobs to UA. + * + * @param [in] job_ring The job ring to poll. + * @param [in] limit The maximum number of jobs to notify. + * If set to negative value, all available + * jobs are notified. + * + * @retval >=0 for No of jobs notified to UA. + * @retval -1 for error + */ + +int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit); + +/* @brief Poll the HW for already processed jobs in the JR + * and silently discard the available jobs or notify them to UA + * with indicated error code. + + * @param [in,out] job_ring The job ring to poll. + * @param [in] do_notify Can be #TRUE or #FALSE. + * Indicates if descriptors to be discarded + * or notified to UA with given error_code. + * @param [in] error_code The detailed SEC error code. + * @param [out] notified_descs Number of notified descriptors. + * Can be NULL if do_notify is #FALSE + */ +void hw_flush_job_ring(struct sec_job_ring_t *job_ring, + uint32_t do_notify, + uint32_t error_code, uint32_t *notified_descs); + +/* + * @brief Flush job rings of any processed descs. + * The processed descs are silently dropped, + * WITHOUT being notified to UA. + */ +void flush_job_rings(void); + +/* + * @brief Handle desc that generated error in SEC engine. + * Identify the exact type of error and handle the error. + * Depending on the error type, the job ring could be reset. + * All descs that are submitted for processing on this job ring + * are notified to User Application with error status and detailed error code. + + * @param [in] job_ring Job ring + * @param [in] sec_error_code Error code read from job ring's Channel + * Status Register + * @param [out] notified_descs Number of notified descs. Can be NULL if + * do_notify is #FALSE + * @param [out] do_driver_shutdown If set to #TRUE, then UA is returned code + * #SEC_PROCESSING_ERROR + * which is indication that UA must call + * sec_release() after this. + */ +void sec_handle_desc_error(struct sec_job_ring_t *job_ring, + uint32_t sec_error_code, + uint32_t *notified_descs, + uint32_t *do_driver_shutdown); + +/* + * @brief Release the software and hardware resources tied to a job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int shutdown_job_ring(struct sec_job_ring_t *job_ring); + +/* + * @brief Enable irqs on associated job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int jr_enable_irqs(struct sec_job_ring_t *job_ring); + +/* + * @brief Disable irqs on associated job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int jr_disable_irqs(struct sec_job_ring_t *job_ring); + + /* + * IRJA - Input Ring Jobs Added Register shows + * how many new jobs were added to the Input Ring. + */ +static inline void hw_enqueue_desc_on_job_ring(struct jobring_regs *regs, + int num) +{ + sec_out32(®s->irja, num); +} + +#endif /* _SEC_HW_SPECIFIC_H_ */ diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h new file mode 100644 index 0000000..57e0fa0 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h @@ -0,0 +1,178 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _JR_DRIVER_H_ +#define _JR_DRIVER_H_ + +#include "jr_driver_config.h" + +/* The maximum size of a SEC descriptor, in WORDs (32 bits). */ +#define MAX_DESC_SIZE_WORDS 64 + +#define CAAM_TIMEOUT 200000 /* ms */ + +/* Return codes for JR user space driver APIs */ +typedef enum sec_return_code_e { + SEC_SUCCESS = 0, + SEC_INVALID_INPUT_PARAM, + SEC_OUT_OF_MEMORY, + SEC_DESCRIPTOR_IN_FLIGHT, + SEC_LAST_DESCRIPTOR_IN_FLIGHT, + SEC_PROCESSING_ERROR, + SEC_DESC_PROCESSING_ERROR, + SEC_JR_IS_FULL, + SEC_DRIVER_RELEASE_IN_PROGRESS, + SEC_DRIVER_ALREADY_INITIALIZED, + SEC_DRIVER_NOT_INITIALIZED, + SEC_JOB_RING_RESET_IN_PROGRESS, + SEC_RESET_ENGINE_FAILED, + SEC_ENABLE_IRQS_FAILED, + SEC_DISABLE_IRQS_FAILED, + SEC_RETURN_CODE_MAX_VALUE, +} sec_return_code_t; + +/* STRUCTURES AND OTHER TYPEDEFS */ + +/* + * @brief Function called by JR User Space driver to notify every processed + * descriptor. + * + * Callback provided by the User Application. + * Callback is invoked by JR User Space driver for each descriptor processed by + * SEC + * @param [in] status Status word indicating processing result for + * this descriptor. + * @param [in] arg Opaque data passed by User Application + * It is opaque from JR driver's point of view. + * @param [in] job_ring The job ring handle on which the processed + * descriptor word was enqueued + */ +typedef void (*user_callback) (uint32_t *desc, uint32_t status, + void *arg, void *job_ring); + +/* + * Structure encompassing a job descriptor which is to be processed + * by SEC. User should also initialise this structure with the callback + * function pointer which will be called by driver after recieving proccessed + * descriptor from SEC. User data is also passed in this data structure which + * will be sent as an argument to the user callback function. + */ +struct job_descriptor { + uint32_t desc[MAX_DESC_SIZE_WORDS]; + void *arg; + user_callback callback; +}; + +/* + * @brief Initialize the JR User Space driver. + * This function will handle initialization of sec library + * along with registering platform specific callbacks, + * as well as local data initialization. + * Call once during application startup. + * @note Global SEC initialization is done in SEC kernel driver. + * @note The hardware IDs of the initialized Job Rings are opaque to the UA. + * The exact Job Rings used by this library are decided between SEC user + * space driver and SEC kernel driver. A static partitioning of Job Rings is + * assumed, configured in DTS(device tree specification) file. + * @param [in] platform_cb Registering the platform specific + * callbacks with driver + * @retval ::0 for successful execution + * @retval ::-1 failure + */ +int sec_jr_lib_init(void); + +/* + * @brief Initialize the software and hardware resources tied to a job ring. + * @param [in] jr_mode; Model to be used by SEC Driver to receive + * notifications from SEC. Can be either + * SEC_NOTIFICATION_TYPE_IRQ or + * SEC_NOTIFICATION_TYPE_POLL + * @param [in] irq_coalescing_timer This value determines the maximum + * amount of time after processing a + * descriptor before raising an interrupt. + * @param [in] irq_coalescing_count This value determines how many + * descriptors are completed before + * raising an interrupt. + * @param [in] reg_base_addr The job ring base address register + * @param [in] irq_id The job ring interrupt identification number. + * @retval job_ring_handle for successful job ring configuration + * @retval NULL on error + */ +void *init_job_ring(uint8_t jr_mode, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count, + void *reg_base_addr, uint32_t irq_id); + +/* + * @brief Release the resources used by the JR User Space driver. + * Reset and release SEC's job rings indicated by the User Application at + * init_job_ring() and free any memory allocated internally. + * Call once during application tear down. + * @note In case there are any descriptors in-flight (descriptors received by + * JR driver for processing and for which no response was yet provided to UA), + * the descriptors are discarded without any notifications to User Application. + * @retval ::0 is returned for a successful execution + * @retval ::-1 is returned if JR driver release is in progress + */ +int sec_release(void); + +/* + * @brief Submit a descriptor for SEC processing. + * This function creates a "job" which is meant to instruct SEC HW + * to perform the processing on the input buffer. The "job" is enqueued + * in the Job Ring associated. The function will return after the "job" + * enqueue is finished. The function will not wait for SEC to + * start or/and finish the "job" processing. + * After the processing is finished the SEC HW writes the processing result + * to the provided output buffer. + * The Caller must poll JR driver using jr_dequeue() + * to receive notifications of the processing completion + * status. The notifications are received by caller by means of callback + * (see ::user_callback). + * @param [in] job_ring_handle The handle of the job ring on which + * descriptor is to be enqueued + * @param [in] job_descriptor The job descriptor structure of type + * struct job_descriptor. This structure + * should be filled with job descriptor along + * with callback function to be called after + * processing of descriptor and some + * opaque data passed to be passed to the + * callback function + * + * @retval ::0 is returned for successful execution + * @retval ::-1 is returned if there is some enqueue failure + */ +int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr); + +/* + * @brief Polls for available descriptors processed by SEC on a specific + * Job Ring + * This function polls the SEC Job Rings and delivers processed descriptors + * Each processed descriptor has a user_callback registered. + * This user_callback is invoked for each processed descriptor. + * The polling is stopped when "limit" descriptors are notified or when + * there are no more descriptors to notify. + * @note The dequeue_jr() API cannot be called from within a user_callback + * function + * @param [in] job_ring_handle The Job Ring handle. + * @param [in] limit This value represents the maximum number + * of processed descriptors that can be + * notified API call on this Job Ring. + * Note that fewer descriptors may be notified + * if enough processed descriptors are not + * available. + * If limit has a negative value, then all + * ready descriptors will be notified. + * + * @retval :: >=0 is returned where retval is the total + * Number of descriptors notified + * during this function call. + * @retval :: -1 is returned in case of some error + */ +int dequeue_jr(void *job_ring_handle, int32_t limit); + +#endif /* _JR_DRIVER_H_ */ diff --git a/arm-trusted-firmware/include/drivers/nxp/csu/csu.h b/arm-trusted-firmware/include/drivers/nxp/csu/csu.h new file mode 100644 index 0000000..83f1834 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/csu/csu.h @@ -0,0 +1,42 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CSU_H +#define CSU_H + +#define CSU_SEC_ACCESS_REG_OFFSET (0x0021CU) +/* Bit mask */ +#define TZASC_BYPASS_MUX_DISABLE (0x4U) + +/* Macros defining access permissions to configure + * the regions controlled by Central Security Unit. + */ +enum csu_cslx_access { + CSU_NS_SUP_R = (0x8U), + CSU_NS_SUP_W = (0x80U), + CSU_NS_SUP_RW = (0x88U), + CSU_NS_USER_R = (0x4U), + CSU_NS_USER_W = (0x40U), + CSU_NS_USER_RW = (0x44U), + CSU_S_SUP_R = (0x2U), + CSU_S_SUP_W = (0x20U), + CSU_S_SUP_RW = (0x22U), + CSU_S_USER_R = (0x1U), + CSU_S_USER_W = (0x10U), + CSU_S_USER_RW = (0x11U), + CSU_ALL_RW = (0xffU), +}; + +struct csu_ns_dev_st { + uintptr_t ind; + uint32_t val; +}; + +void enable_layerscape_ns_access(struct csu_ns_dev_st *csu_ns_dev, + uint32_t num, uintptr_t nxp_csu_addr); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h new file mode 100644 index 0000000..cf29b12 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h @@ -0,0 +1,103 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DCFG_H +#define DCFG_H + +#include + +#if defined(CONFIG_CHASSIS_2) +#include +#elif defined(CONFIG_CHASSIS_3_2) || defined(CONFIG_CHASSIS_3) +#include +#endif + +#ifdef NXP_GUR_BE +#define gur_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define gur_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_GUR_LE) +#define gur_in32(a) mmio_read_32((uintptr_t)(a)) +#define gur_out32(a, v) mmio_write_32((uintptr_t)(a), v) +#else +#error Please define CCSR GUR register endianness +#endif + +typedef struct { + union { + uint32_t val; + struct { + uint32_t min_ver:4; + uint32_t maj_ver:4; +#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2) + uint32_t personality:6; + uint32_t rsv1:2; +#elif defined(CONFIG_CHASSIS_2) + uint32_t personality:8; + +#endif +#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2) + uint32_t dev_id:6; + uint32_t rsv2:2; + uint32_t family:4; +#elif defined(CONFIG_CHASSIS_2) + uint32_t dev_id:12; +#endif + uint32_t mfr_id; + } __packed bf; + struct { + uint32_t maj_min:8; + uint32_t version; /* SoC version without major and minor info */ + } __packed bf_ver; + } __packed svr_reg; + bool sec_enabled; + bool is_populated; +} soc_info_t; + +typedef struct { + bool is_populated; + uint8_t ocram_present; + uint8_t ddrc1_present; +#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2) + uint8_t ddrc2_present; +#endif +} devdisr5_info_t; + +typedef struct { + uint32_t porsr1; + uintptr_t g_nxp_dcfg_addr; + unsigned long nxp_sysclk_freq; + unsigned long nxp_ddrclk_freq; + unsigned int nxp_plat_clk_divider; +} dcfg_init_info_t; + + +struct sysinfo { + unsigned long freq_platform; + unsigned long freq_ddr_pll0; + unsigned long freq_ddr_pll1; +}; + +int get_clocks(struct sysinfo *sys); + +/* Read the PORSR1 register */ +uint32_t read_reg_porsr1(void); + +/******************************************************************************* + * Returns true if secur eboot is enabled on board + * mode = 0 (development mode - sb_en = 1) + * mode = 1 (production mode - ITS = 1) + ******************************************************************************/ +bool check_boot_mode_secure(uint32_t *mode); + +const soc_info_t *get_soc_info(); +const devdisr5_info_t *get_devdisr5_info(); + +void dcfg_init(dcfg_init_info_t *dcfg_init_data); +bool is_sec_enabled(void); + +void error_handler(int error_code); +#endif /* DCFG_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h new file mode 100644 index 0000000..882ba5a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h @@ -0,0 +1,85 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DCFG_LSCH2_H +#define DCFG_LSCH2_H + +/* dcfg block register offsets and bitfields */ +#define DCFG_PORSR1_OFFSET 0x00 +#define DCFG_DEVDISR1_OFFSET 0x070 +#define DCFG_DEVDISR2_OFFSET 0x074 +#define DCFG_DEVDISR3_OFFSET 0x078 +#define DCFG_DEVDISR4_OFFSET 0x07C +#define DCFG_DEVDISR5_OFFSET 0x080 +#define DCFG_COREDISR_OFFSET 0x094 +#define RCWSR0_OFFSET 0x100 +#define RCWSR5_OFFSET 0x118 +#define DCFG_BOOTLOCPTRL_OFFSET 0x400 +#define DCFG_BOOTLOCPTRH_OFFSET 0x404 +#define DCFG_COREDISABLEDSR_OFFSET 0x990 +#define DCFG_SCRATCH4_OFFSET 0x20C +#define DCFG_SVR_OFFSET 0x0A4 +#define DCFG_BRR_OFFSET 0x0E4 + +#define DCFG_RSTCR_OFFSET 0x0B0 +#define RSTCR_RESET_REQ 0x2 + +#define DCFG_RSTRQSR1_OFFSET 0x0C8 +#define DCFG_RSTRQMR1_OFFSET 0x0C0 + +/* PORSR1 bit mask */ +#define PORSR1_RCW_MASK 0xff800000 +#define PORSR1_RCW_SHIFT 23 + +/* DCFG DCSR Macros */ +#define DCFG_DCSR_PORCR1_OFFSET 0x0 + +#define SVR_MFR_ID_MASK 0xF0000000 +#define SVR_MFR_ID_SHIFT 28 +#define SVR_DEV_ID_MASK 0xFFF0000 +#define SVR_DEV_ID_SHIFT 16 +#define SVR_PERSONALITY_MASK 0xFF00 +#define SVR_PERSONALITY_SHIFT 8 +#define SVR_SEC_MASK 0x100 +#define SVR_SEC_SHIFT 8 +#define SVR_MAJ_VER_MASK 0xF0 +#define SVR_MAJ_VER_SHIFT 4 +#define SVR_MIN_VER_MASK 0xF +#define SVR_MINOR_VER_0 0x00 +#define SVR_MINOR_VER_1 0x01 + +#define DISR5_DDRC1_MASK 0x1 +#define DISR5_OCRAM_MASK 0x40 + +/* DCFG regsiters bit masks */ +#define RCWSR0_SYS_PLL_RAT_SHIFT 25 +#define RCWSR0_SYS_PLL_RAT_MASK 0x1f +#define RCWSR0_MEM_PLL_RAT_SHIFT 16 +#define RCWSR0_MEM_PLL_RAT_MASK 0x3f +#define RCWSR0_MEM2_PLL_RAT_SHIFT 18 +#define RCWSR0_MEM2_PLL_RAT_MASK 0x3f + +#define RCWSR_SB_EN_OFFSET RCWSR5_OFFSET +#define RCWSR_SBEN_MASK 0x1 +#define RCWSR_SBEN_SHIFT 21 + +/* RCW SRC NAND */ +#define RCW_SRC_NAND_MASK (0x100) +#define RCW_SRC_NAND_VAL (0x100) +#define NAND_RESERVED_MASK (0xFC) +#define NAND_RESERVED_1 (0x0) +#define NAND_RESERVED_2 (0x80) + +/* RCW SRC NOR */ +#define RCW_SRC_NOR_MASK (0x1F0) +#define NOR_8B_VAL (0x10) +#define NOR_16B_VAL (0x20) +#define SD_VAL (0x40) +#define QSPI_VAL1 (0x44) +#define QSPI_VAL2 (0x45) + +#endif /* DCFG_LSCH2_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h new file mode 100644 index 0000000..cde86fe --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h @@ -0,0 +1,80 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DCFG_LSCH3_H +#define DCFG_LSCH3_H + +/* dcfg block register offsets and bitfields */ +#define DCFG_PORSR1_OFFSET 0x00 + +#define DCFG_DEVDISR1_OFFSET 0x70 +#define DCFG_DEVDISR1_SEC (1 << 22) + +#define DCFG_DEVDISR2_OFFSET 0x74 + +#define DCFG_DEVDISR3_OFFSET 0x78 +#define DCFG_DEVDISR3_QBMAIN (1 << 12) + +#define DCFG_DEVDISR4_OFFSET 0x7C +#define DCFG_DEVDISR4_SPI_QSPI (1 << 4 | 1 << 5) + +#define DCFG_DEVDISR5_OFFSET 0x80 +#define DISR5_DDRC1_MASK 0x1 +#define DISR5_DDRC2_MASK 0x2 +#define DISR5_OCRAM_MASK 0x1000 +#define DEVDISR5_MASK_ALL_MEM 0x00001003 +#define DEVDISR5_MASK_DDR 0x00000003 +#define DEVDISR5_MASK_DBG 0x00000400 + +#define DCFG_DEVDISR6_OFFSET 0x84 +//#define DEVDISR6_MASK 0x00000001 + +#define DCFG_COREDISR_OFFSET 0x94 + +#define DCFG_SVR_OFFSET 0x0A4 +#define SVR_MFR_ID_MASK 0xF0000000 +#define SVR_MFR_ID_SHIFT 28 +#define SVR_FAMILY_MASK 0xF000000 +#define SVR_FAMILY_SHIFT 24 +#define SVR_DEV_ID_MASK 0x3F0000 +#define SVR_DEV_ID_SHIFT 16 +#define SVR_PERSONALITY_MASK 0x3E00 +#define SVR_PERSONALITY_SHIFT 9 +#define SVR_SEC_MASK 0x100 +#define SVR_SEC_SHIFT 8 +#define SVR_MAJ_VER_MASK 0xF0 +#define SVR_MAJ_VER_SHIFT 4 +#define SVR_MIN_VER_MASK 0xF + +#define RCWSR0_OFFSET 0x100 +#define RCWSR0_SYS_PLL_RAT_SHIFT 2 +#define RCWSR0_SYS_PLL_RAT_MASK 0x1f +#define RCWSR0_MEM_PLL_RAT_SHIFT 10 +#define RCWSR0_MEM_PLL_RAT_MASK 0x3f +#define RCWSR0_MEM2_PLL_RAT_SHIFT 18 +#define RCWSR0_MEM2_PLL_RAT_MASK 0x3f + +#define RCWSR5_OFFSET 0x110 +#define RCWSR9_OFFSET 0x120 +#define RCWSR_SB_EN_OFFSET RCWSR9_OFFSET +#define RCWSR_SBEN_MASK 0x1 +#define RCWSR_SBEN_SHIFT 10 + +#define RCW_SR27_OFFSET 0x168 +/* DCFG register to dump error code */ +#define DCFG_SCRATCH4_OFFSET 0x20C +#define DCFG_SCRATCHRW5_OFFSET 0x210 +#define DCFG_SCRATCHRW6_OFFSET 0x214 +#define DCFG_SCRATCHRW7_OFFSET 0x218 +#define DCFG_BOOTLOCPTRL_OFFSET 0x400 +#define DCFG_BOOTLOCPTRH_OFFSET 0x404 +#define DCFG_COREDISABLEDSR_OFFSET 0x990 + +/* Reset module bit field */ +#define RSTCR_RESET_REQ 0x2 + +#endif /* DCFG_LSCH3_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h b/arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h new file mode 100644 index 0000000..8067de1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h @@ -0,0 +1,65 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SCFG_H +#define SCFG_H + +#ifdef CONFIG_CHASSIS_2 + +/* SCFG register offsets */ +#define SCFG_CORE0_SFT_RST_OFFSET 0x0130 +#define SCFG_SNPCNFGCR_OFFSET 0x01A4 +#define SCFG_CORESRENCR_OFFSET 0x0204 +#define SCFG_RVBAR0_0_OFFSET 0x0220 +#define SCFG_RVBAR0_1_OFFSET 0x0224 +#define SCFG_COREBCR_OFFSET 0x0680 +#define SCFG_RETREQCR_OFFSET 0x0424 + +#define SCFG_COREPMCR_OFFSET 0x042C +#define COREPMCR_WFIL2 0x1 + +#define SCFG_GIC400_ADDR_ALIGN_OFFSET 0x0188 +#define SCFG_BOOTLOCPTRH_OFFSET 0x0600 +#define SCFG_BOOTLOCPTRL_OFFSET 0x0604 +#define SCFG_SCRATCHRW2_OFFSET 0x0608 +#define SCFG_SCRATCHRW3_OFFSET 0x060C + +/* SCFG bit fields */ +#define SCFG_SNPCNFGCR_SECRDSNP 0x80000000 +#define SCFG_SNPCNFGCR_SECWRSNP 0x40000000 + +/* GIC Address Align Register */ +#define SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK 0x80000000 +#define SCFG_GIC400_ADDR_ALIGN_4KMODE_EN 0x80000000 +#define SCFG_GIC400_ADDR_ALIGN_4KMODE_DIS 0x0 + +#endif /* CONFIG_CHASSIS_2 */ + +#ifndef __ASSEMBLER__ +#include +#include + +#ifdef NXP_SCFG_BE +#define scfg_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define scfg_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#define scfg_setbits32(a, v) mmio_setbits_32((uintptr_t)(a), v) +#define scfg_clrbits32(a, v) mmio_clrbits_32((uintptr_t)(a), v) +#define scfg_clrsetbits32(a, clear, set) \ + mmio_clrsetbits_32((uintptr_t)(a), clear, set) +#elif defined(NXP_SCFG_LE) +#define scfg_in32(a) mmio_read_32((uintptr_t)(a)) +#define scfg_out32(a, v) mmio_write_32((uintptr_t)(a), v) +#define scfg_setbits32(a, v) mmio_setbits_32((uintptr_t)(a), v) +#define scfg_clrbits32(a, v) mmio_clrbits_32((uintptr_t)(a), v) +#define scfg_clrsetbits32(a, clear, set) \ + mmio_clrsetbits_32((uintptr_t)(a), clear, set) +#else +#error Please define CCSR SCFG register endianness +#endif +#endif /* __ASSEMBLER__ */ + +#endif /* SCFG_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h b/arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h new file mode 100644 index 0000000..0ef2870 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h @@ -0,0 +1,151 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_H +#define DDR_H + +#include "ddr_io.h" +#include "dimm.h" +#include "immap.h" + +#ifndef DDRC_NUM_CS +#define DDRC_NUM_CS 4 +#endif + +/* + * This is irrespective of what is the number of DDR controller, + * number of DIMM used. This is set to maximum + * Max controllers = 2 + * Max num of DIMM per controlle = 2 + * MAX NUM CS = 4 + * Not to be changed. + */ +#define MAX_DDRC_NUM 2 +#define MAX_DIMM_NUM 2 +#define MAX_CS_NUM 4 + +#include "opts.h" +#include "regs.h" +#include "utility.h" + +#ifdef DDR_DEBUG +#define debug(...) INFO(__VA_ARGS__) +#else +#define debug(...) VERBOSE(__VA_ARGS__) +#endif + +#ifndef DDRC_NUM_DIMM +#define DDRC_NUM_DIMM 1 +#endif + +#define CONFIG_CS_PER_SLOT \ + (DDRC_NUM_CS / DDRC_NUM_DIMM) + +/* Record of register values computed */ +struct ddr_cfg_regs { + struct { + unsigned int bnds; + unsigned int config; + unsigned int config_2; + } cs[MAX_CS_NUM]; + unsigned int dec[10]; + unsigned int timing_cfg[10]; + unsigned int sdram_cfg[3]; + unsigned int sdram_mode[16]; + unsigned int md_cntl; + unsigned int interval; + unsigned int data_init; + unsigned int clk_cntl; + unsigned int init_addr; + unsigned int init_ext_addr; + unsigned int zq_cntl; + unsigned int wrlvl_cntl[3]; + unsigned int ddr_sr_cntr; + unsigned int sdram_rcw[6]; + unsigned int dq_map[4]; + unsigned int eor; + unsigned int cdr[2]; + unsigned int err_disable; + unsigned int err_int_en; + unsigned int tx_cfg[4]; + unsigned int debug[64]; +}; + +struct ddr_conf { + int dimm_in_use[MAX_DIMM_NUM]; + int cs_in_use; /* bitmask, bit 0 for cs0, bit 1 for cs1, etc. */ + int cs_on_dimm[MAX_DIMM_NUM]; /* bitmask */ + unsigned long long cs_base_addr[MAX_CS_NUM]; + unsigned long long cs_size[MAX_CS_NUM]; + unsigned long long base_addr; + unsigned long long total_mem; +}; + +struct ddr_info { + unsigned long clk; + unsigned long long mem_base; + unsigned int num_ctlrs; + unsigned int dimm_on_ctlr; + struct dimm_params dimm; + struct memctl_opt opt; + struct ddr_conf conf; + struct ddr_cfg_regs ddr_reg; + struct ccsr_ddr *ddr[MAX_DDRC_NUM]; + uint16_t *phy[MAX_DDRC_NUM]; + int *spd_addr; + unsigned int ip_rev; + uintptr_t phy_gen2_fw_img_buf; + void *img_loadr; + int warm_boot_flag; +}; + +struct rc_timing { + unsigned int speed_bin; + unsigned int clk_adj; + unsigned int wrlvl; +}; + +struct board_timing { + unsigned int rc; + struct rc_timing const *p; + unsigned int add1; + unsigned int add2; +}; + +enum warm_boot { + DDR_COLD_BOOT = 0, + DDR_WARM_BOOT = 1, + DDR_WRM_BOOT_NT_SUPPORTED = -1, +}; + +int disable_unused_ddrc(struct ddr_info *priv, int mask, + uintptr_t nxp_ccn_hn_f0_addr); +int ddr_board_options(struct ddr_info *priv); +int compute_ddrc(const unsigned long clk, + const struct memctl_opt *popts, + const struct ddr_conf *conf, + struct ddr_cfg_regs *ddr, + const struct dimm_params *dimm_params, + const unsigned int ip_rev); +int compute_ddr_phy(struct ddr_info *priv); +int ddrc_set_regs(const unsigned long clk, + const struct ddr_cfg_regs *regs, + const struct ccsr_ddr *ddr, + int twopass); +int cal_board_params(struct ddr_info *priv, + const struct board_timing *dimm, + int len); +/* return bit mask of used DIMM(s) */ +int ddr_get_ddr_params(struct dimm_params *pdimm, struct ddr_conf *conf); +long long dram_init(struct ddr_info *priv +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , uintptr_t nxp_ccn_hn_f0_addr +#endif + ); +long long board_static_ddr(struct ddr_info *info); + +#endif /* DDR_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h b/arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h new file mode 100644 index 0000000..fbd7e97 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_IO_H +#define DDR_IO_H + +#include + +#include + +#define min(a, b) (((a) > (b)) ? (b) : (a)) + +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +/* macro for memory barrier */ +#define mb() asm volatile("dsb sy" : : : "memory") + +#ifdef NXP_DDR_BE +#define ddr_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define ddr_out32(a, v) mmio_write_32((uintptr_t)(a),\ + bswap32(v)) +#elif defined(NXP_DDR_LE) +#define ddr_in32(a) mmio_read_32((uintptr_t)(a)) +#define ddr_out32(a, v) mmio_write_32((uintptr_t)(a), v) +#else +#error Please define CCSR DDR register endianness +#endif + +#define ddr_setbits32(a, v) ddr_out32((a), ddr_in32(a) | (v)) +#define ddr_clrbits32(a, v) ddr_out32((a), ddr_in32(a) & ~(v)) +#define ddr_clrsetbits32(a, c, s) ddr_out32((a), (ddr_in32(a) & ~(c)) \ + | (s)) + +#endif /* DDR_IO_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h b/arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h new file mode 100644 index 0000000..fcae179 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h @@ -0,0 +1,330 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DIMM_H +#define DIMM_H + +#define SPD_MEMTYPE_DDR4 0x0C + +#define DDR4_SPD_MODULETYPE_MASK 0x0f +#define DDR4_SPD_MODULETYPE_EXT 0x00 +#define DDR4_SPD_RDIMM 0x01 +#define DDR4_SPD_UDIMM 0x02 +#define DDR4_SPD_SO_DIMM 0x03 +#define DDR4_SPD_LRDIMM 0x04 +#define DDR4_SPD_MINI_RDIMM 0x05 +#define DDR4_SPD_MINI_UDIMM 0x06 +#define DDR4_SPD_72B_SO_RDIMM 0x08 +#define DDR4_SPD_72B_SO_UDIMM 0x09 +#define DDR4_SPD_16B_SO_DIMM 0x0c +#define DDR4_SPD_32B_SO_DIMM 0x0d + +#define SPD_SPA0_ADDRESS 0x36 +#define SPD_SPA1_ADDRESS 0x37 + +#define spd_to_ps(mtb, ftb) \ + ((mtb) * pdimm->mtb_ps + ((ftb) * pdimm->ftb_10th_ps) / 10) + +#ifdef DDR_DEBUG +#define dump_spd(spd, len) { \ + register int i; \ + register unsigned char *buf = (void *)(spd); \ + \ + for (i = 0; i < (len); i++) { \ + print_uint(i); \ + puts("\t: 0x"); \ + print_hex(buf[i]); \ + puts("\n"); \ + } \ +} +#else +#define dump_spd(spd, len) {} +#endif + +/* From JEEC Standard No. 21-C release 23A */ +struct ddr4_spd { + /* General Section: Bytes 0-127 */ + unsigned char info_size_crc; /* 0 # bytes */ + unsigned char spd_rev; /* 1 Total # bytes of SPD */ + unsigned char mem_type; /* 2 Key Byte / mem type */ + unsigned char module_type; /* 3 Key Byte / Module Type */ + unsigned char density_banks; /* 4 Density and Banks */ + unsigned char addressing; /* 5 Addressing */ + unsigned char package_type; /* 6 Package type */ + unsigned char opt_feature; /* 7 Optional features */ + unsigned char thermal_ref; /* 8 Thermal and refresh */ + unsigned char oth_opt_features; /* 9 Other optional features */ + unsigned char res_10; /* 10 Reserved */ + unsigned char module_vdd; /* 11 Module nominal voltage */ + unsigned char organization; /* 12 Module Organization */ + unsigned char bus_width; /* 13 Module Memory Bus Width */ + unsigned char therm_sensor; /* 14 Module Thermal Sensor */ + unsigned char ext_type; /* 15 Extended module type */ + unsigned char res_16; + unsigned char timebases; /* 17 MTb and FTB */ + unsigned char tck_min; /* 18 tCKAVGmin */ + unsigned char tck_max; /* 19 TCKAVGmax */ + unsigned char caslat_b1; /* 20 CAS latencies, 1st byte */ + unsigned char caslat_b2; /* 21 CAS latencies, 2nd byte */ + unsigned char caslat_b3; /* 22 CAS latencies, 3rd byte */ + unsigned char caslat_b4; /* 23 CAS latencies, 4th byte */ + unsigned char taa_min; /* 24 Min CAS Latency Time */ + unsigned char trcd_min; /* 25 Min RAS# to CAS# Delay Time */ + unsigned char trp_min; /* 26 Min Row Precharge Delay Time */ + unsigned char tras_trc_ext; /* 27 Upper Nibbles for tRAS and tRC */ + unsigned char tras_min_lsb; /* 28 tRASmin, lsb */ + unsigned char trc_min_lsb; /* 29 tRCmin, lsb */ + unsigned char trfc1_min_lsb; /* 30 Min Refresh Recovery Delay Time */ + unsigned char trfc1_min_msb; /* 31 Min Refresh Recovery Delay Time */ + unsigned char trfc2_min_lsb; /* 32 Min Refresh Recovery Delay Time */ + unsigned char trfc2_min_msb; /* 33 Min Refresh Recovery Delay Time */ + unsigned char trfc4_min_lsb; /* 34 Min Refresh Recovery Delay Time */ + unsigned char trfc4_min_msb; /* 35 Min Refresh Recovery Delay Time */ + unsigned char tfaw_msb; /* 36 Upper Nibble for tFAW */ + unsigned char tfaw_min; /* 37 tFAW, lsb */ + unsigned char trrds_min; /* 38 tRRD_Smin, MTB */ + unsigned char trrdl_min; /* 39 tRRD_Lmin, MTB */ + unsigned char tccdl_min; /* 40 tCCS_Lmin, MTB */ + unsigned char res_41[60-41]; /* 41 Rserved */ + unsigned char mapping[78-60]; /* 60~77 Connector to SDRAM bit map */ + unsigned char res_78[117-78]; /* 78~116, Reserved */ + signed char fine_tccdl_min; /* 117 Fine offset for tCCD_Lmin */ + signed char fine_trrdl_min; /* 118 Fine offset for tRRD_Lmin */ + signed char fine_trrds_min; /* 119 Fine offset for tRRD_Smin */ + signed char fine_trc_min; /* 120 Fine offset for tRCmin */ + signed char fine_trp_min; /* 121 Fine offset for tRPmin */ + signed char fine_trcd_min; /* 122 Fine offset for tRCDmin */ + signed char fine_taa_min; /* 123 Fine offset for tAAmin */ + signed char fine_tck_max; /* 124 Fine offset for tCKAVGmax */ + signed char fine_tck_min; /* 125 Fine offset for tCKAVGmin */ + /* CRC: Bytes 126-127 */ + unsigned char crc[2]; /* 126-127 SPD CRC */ + + /* Module-Specific Section: Bytes 128-255 */ + union { + struct { + /* 128 (Unbuffered) Module Nominal Height */ + unsigned char mod_height; + /* 129 (Unbuffered) Module Maximum Thickness */ + unsigned char mod_thickness; + /* 130 (Unbuffered) Reference Raw Card Used */ + unsigned char ref_raw_card; + /* 131 (Unbuffered) Address Mapping from + * Edge Connector to DRAM + */ + unsigned char addr_mapping; + /* 132~253 (Unbuffered) Reserved */ + unsigned char res_132[254-132]; + /* 254~255 CRC */ + unsigned char crc[2]; + } unbuffered; + struct { + /* 128 (Registered) Module Nominal Height */ + unsigned char mod_height; + /* 129 (Registered) Module Maximum Thickness */ + unsigned char mod_thickness; + /* 130 (Registered) Reference Raw Card Used */ + unsigned char ref_raw_card; + /* 131 DIMM Module Attributes */ + unsigned char modu_attr; + /* 132 RDIMM Thermal Heat Spreader Solution */ + unsigned char thermal; + /* 133 Register Manufacturer ID Code, LSB */ + unsigned char reg_id_lo; + /* 134 Register Manufacturer ID Code, MSB */ + unsigned char reg_id_hi; + /* 135 Register Revision Number */ + unsigned char reg_rev; + /* 136 Address mapping from register to DRAM */ + unsigned char reg_map; + unsigned char ca_stren; + unsigned char clk_stren; + /* 139~253 Reserved */ + unsigned char res_139[254-139]; + /* 254~255 CRC */ + unsigned char crc[2]; + } registered; + struct { + /* 128 (Loadreduced) Module Nominal Height */ + unsigned char mod_height; + /* 129 (Loadreduced) Module Maximum Thickness */ + unsigned char mod_thickness; + /* 130 (Loadreduced) Reference Raw Card Used */ + unsigned char ref_raw_card; + /* 131 DIMM Module Attributes */ + unsigned char modu_attr; + /* 132 RDIMM Thermal Heat Spreader Solution */ + unsigned char thermal; + /* 133 Register Manufacturer ID Code, LSB */ + unsigned char reg_id_lo; + /* 134 Register Manufacturer ID Code, MSB */ + unsigned char reg_id_hi; + /* 135 Register Revision Number */ + unsigned char reg_rev; + /* 136 Address mapping from register to DRAM */ + unsigned char reg_map; + /* 137 Register Output Drive Strength for CMD/Add*/ + unsigned char reg_drv; + /* 138 Register Output Drive Strength for CK */ + unsigned char reg_drv_ck; + /* 139 Data Buffer Revision Number */ + unsigned char data_buf_rev; + /* 140 DRAM VrefDQ for Package Rank 0 */ + unsigned char vrefqe_r0; + /* 141 DRAM VrefDQ for Package Rank 1 */ + unsigned char vrefqe_r1; + /* 142 DRAM VrefDQ for Package Rank 2 */ + unsigned char vrefqe_r2; + /* 143 DRAM VrefDQ for Package Rank 3 */ + unsigned char vrefqe_r3; + /* 144 Data Buffer VrefDQ for DRAM Interface */ + unsigned char data_intf; + /* + * 145 Data Buffer MDQ Drive Strength and RTT + * for data rate <= 1866 + */ + unsigned char data_drv_1866; + /* + * 146 Data Buffer MDQ Drive Strength and RTT + * for 1866 < data rate <= 2400 + */ + unsigned char data_drv_2400; + /* + * 147 Data Buffer MDQ Drive Strength and RTT + * for 2400 < data rate <= 3200 + */ + unsigned char data_drv_3200; + /* 148 DRAM Drive Strength */ + unsigned char dram_drv; + /* + * 149 DRAM ODT (RTT_WR, RTT_NOM) + * for data rate <= 1866 + */ + unsigned char dram_odt_1866; + /* + * 150 DRAM ODT (RTT_WR, RTT_NOM) + * for 1866 < data rate <= 2400 + */ + unsigned char dram_odt_2400; + /* + * 151 DRAM ODT (RTT_WR, RTT_NOM) + * for 2400 < data rate <= 3200 + */ + unsigned char dram_odt_3200; + /* + * 152 DRAM ODT (RTT_PARK) + * for data rate <= 1866 + */ + unsigned char dram_odt_park_1866; + /* + * 153 DRAM ODT (RTT_PARK) + * for 1866 < data rate <= 2400 + */ + unsigned char dram_odt_park_2400; + /* + * 154 DRAM ODT (RTT_PARK) + * for 2400 < data rate <= 3200 + */ + unsigned char dram_odt_park_3200; + unsigned char res_155[254-155]; /* Reserved */ + /* 254~255 CRC */ + unsigned char crc[2]; + } loadreduced; + unsigned char uc[128]; /* 128-255 Module-Specific Section */ + } mod_section; + + unsigned char res_256[320-256]; /* 256~319 Reserved */ + + /* Module supplier's data: Byte 320~383 */ + unsigned char mmid_lsb; /* 320 Module MfgID Code LSB */ + unsigned char mmid_msb; /* 321 Module MfgID Code MSB */ + unsigned char mloc; /* 322 Mfg Location */ + unsigned char mdate[2]; /* 323~324 Mfg Date */ + unsigned char sernum[4]; /* 325~328 Module Serial Number */ + unsigned char mpart[20]; /* 329~348 Mfg's Module Part Number */ + unsigned char mrev; /* 349 Module Revision Code */ + unsigned char dmid_lsb; /* 350 DRAM MfgID Code LSB */ + unsigned char dmid_msb; /* 351 DRAM MfgID Code MSB */ + unsigned char stepping; /* 352 DRAM stepping */ + unsigned char msd[29]; /* 353~381 Mfg's Specific Data */ + unsigned char res_382[2]; /* 382~383 Reserved */ +}; + +/* Parameters for a DDR dimm computed from the SPD */ +struct dimm_params { + /* DIMM organization parameters */ + char mpart[19]; /* guaranteed null terminated */ + + unsigned int n_ranks; + unsigned int die_density; + unsigned long long rank_density; + unsigned long long capacity; + unsigned int primary_sdram_width; + unsigned int ec_sdram_width; + unsigned int rdimm; + unsigned int package_3ds; /* number of dies in 3DS */ + unsigned int device_width; /* x4, x8, x16 components */ + unsigned int rc; + + /* SDRAM device parameters */ + unsigned int n_row_addr; + unsigned int n_col_addr; + unsigned int edc_config; /* 0 = none, 1 = parity, 2 = ECC */ + unsigned int bank_addr_bits; + unsigned int bank_group_bits; + unsigned int burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */ + + /* mirrored DIMMs */ + unsigned int mirrored_dimm; /* only for ddr3 */ + + /* DIMM timing parameters */ + + int mtb_ps; /* medium timebase ps */ + int ftb_10th_ps; /* fine timebase, in 1/10 ps */ + int taa_ps; /* minimum CAS latency time */ + int tfaw_ps; /* four active window delay */ + + /* + * SDRAM clock periods + * The range for these are 1000-10000 so a short should be sufficient + */ + int tckmin_x_ps; + int tckmax_ps; + + /* SPD-defined CAS latencies */ + unsigned int caslat_x; + + /* basic timing parameters */ + int trcd_ps; + int trp_ps; + int tras_ps; + + int trfc1_ps; + int trfc2_ps; + int trfc4_ps; + int trrds_ps; + int trrdl_ps; + int tccdl_ps; + int trfc_slr_ps; + + int trc_ps; /* maximum = 254 ns + .75 ns = 254750 ps */ + int twr_ps; /* 15ns for all speed bins */ + + unsigned int refresh_rate_ps; + unsigned int extended_op_srt; + + /* RDIMM */ + unsigned char rcw[16]; /* Register Control Word 0-15 */ + unsigned int dq_mapping[18]; + unsigned int dq_mapping_ors; +}; + +int read_spd(unsigned char chip, void *buf, int len); +int crc16(unsigned char *ptr, int count); +int cal_dimm_params(const struct ddr4_spd *spd, struct dimm_params *pdimm); + +#endif /* DIMM_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h b/arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h new file mode 100644 index 0000000..31db552 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h @@ -0,0 +1,173 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_MMDC_H +#define FSL_MMDC_H + +/* PHY Write Leveling Configuration and Error Status Register (MPWLGCR) */ +#define MPWLGCR_HW_WL_EN (1 << 0) + +/* PHY Pre-defined Compare and CA delay-line Configuration (MPPDCMPR2) */ +#define MPPDCMPR2_MPR_COMPARE_EN (1 << 0) + + +/* MMDC PHY Read DQS gating control register 0 (MPDGCTRL0) */ +#define AUTO_RD_DQS_GATING_CALIBRATION_EN (1 << 28) + +/* MMDC PHY Read Delay HW Calibration Control Register (MPRDDLHWCTL) */ +#define MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN (1 << 4) + +/* MMDC Core Power Saving Control and Status Register (MMDC_MAPSR) */ +#define MMDC_MAPSR_PWR_SAV_CTRL_STAT 0x00001067 + +/* MMDC Core Refresh Control Register (MMDC_MDREF) */ +#define MDREF_START_REFRESH (1 << 0) + +/* MMDC Core Special Command Register (MDSCR) */ +#define CMD_ADDR_MSB_MR_OP(x) (x << 24) +#define CMD_ADDR_LSB_MR_ADDR(x) (x << 16) +#define MDSCR_DISABLE_CFG_REQ (0 << 15) +#define MDSCR_ENABLE_CON_REQ (1 << 15) +#define MDSCR_CON_ACK (1 << 14) +#define MDSCR_WL_EN (1 << 9) +#define CMD_NORMAL (0 << 4) +#define CMD_PRECHARGE (1 << 4) +#define CMD_AUTO_REFRESH (2 << 4) +#define CMD_LOAD_MODE_REG (3 << 4) +#define CMD_ZQ_CALIBRATION (4 << 4) +#define CMD_PRECHARGE_BANK_OPEN (5 << 4) +#define CMD_MRR (6 << 4) +#define CMD_BANK_ADDR_0 0x0 +#define CMD_BANK_ADDR_1 0x1 +#define CMD_BANK_ADDR_2 0x2 +#define CMD_BANK_ADDR_3 0x3 +#define CMD_BANK_ADDR_4 0x4 +#define CMD_BANK_ADDR_5 0x5 +#define CMD_BANK_ADDR_6 0x6 +#define CMD_BANK_ADDR_7 0x7 + +/* MMDC Core Control Register (MDCTL) */ +#define MDCTL_SDE0 (U(1) << 31) +#define MDCTL_SDE1 (1 << 30) + +/* MMDC PHY ZQ HW control register (MMDC_MPZQHWCTRL) */ +#define MPZQHWCTRL_ZQ_HW_FORCE (1 << 16) + +/* MMDC PHY Measure Unit Register (MMDC_MPMUR0) */ +#define MMDC_MPMUR0_FRC_MSR (1 << 11) + +/* MMDC PHY Read delay-lines Configuration Register (MMDC_MPRDDLCTL) */ +/* default 64 for a quarter cycle delay */ +#define MMDC_MPRDDLCTL_DEFAULT_DELAY 0x40404040 + +/* MMDC Registers */ +struct mmdc_regs { + unsigned int mdctl; + unsigned int mdpdc; + unsigned int mdotc; + unsigned int mdcfg0; + unsigned int mdcfg1; + unsigned int mdcfg2; + unsigned int mdmisc; + unsigned int mdscr; + unsigned int mdref; + unsigned int res1[2]; + unsigned int mdrwd; + unsigned int mdor; + unsigned int mdmrr; + unsigned int mdcfg3lp; + unsigned int mdmr4; + unsigned int mdasp; + unsigned int res2[239]; + unsigned int maarcr; + unsigned int mapsr; + unsigned int maexidr0; + unsigned int maexidr1; + unsigned int madpcr0; + unsigned int madpcr1; + unsigned int madpsr0; + unsigned int madpsr1; + unsigned int madpsr2; + unsigned int madpsr3; + unsigned int madpsr4; + unsigned int madpsr5; + unsigned int masbs0; + unsigned int masbs1; + unsigned int res3[2]; + unsigned int magenp; + unsigned int res4[239]; + unsigned int mpzqhwctrl; + unsigned int mpzqswctrl; + unsigned int mpwlgcr; + unsigned int mpwldectrl0; + unsigned int mpwldectrl1; + unsigned int mpwldlst; + unsigned int mpodtctrl; + unsigned int mprddqby0dl; + unsigned int mprddqby1dl; + unsigned int mprddqby2dl; + unsigned int mprddqby3dl; + unsigned int mpwrdqby0dl; + unsigned int mpwrdqby1dl; + unsigned int mpwrdqby2dl; + unsigned int mpwrdqby3dl; + unsigned int mpdgctrl0; + unsigned int mpdgctrl1; + unsigned int mpdgdlst0; + unsigned int mprddlctl; + unsigned int mprddlst; + unsigned int mpwrdlctl; + unsigned int mpwrdlst; + unsigned int mpsdctrl; + unsigned int mpzqlp2ctl; + unsigned int mprddlhwctl; + unsigned int mpwrdlhwctl; + unsigned int mprddlhwst0; + unsigned int mprddlhwst1; + unsigned int mpwrdlhwst0; + unsigned int mpwrdlhwst1; + unsigned int mpwlhwerr; + unsigned int mpdghwst0; + unsigned int mpdghwst1; + unsigned int mpdghwst2; + unsigned int mpdghwst3; + unsigned int mppdcmpr1; + unsigned int mppdcmpr2; + unsigned int mpswdar0; + unsigned int mpswdrdr0; + unsigned int mpswdrdr1; + unsigned int mpswdrdr2; + unsigned int mpswdrdr3; + unsigned int mpswdrdr4; + unsigned int mpswdrdr5; + unsigned int mpswdrdr6; + unsigned int mpswdrdr7; + unsigned int mpmur0; + unsigned int mpwrcadl; + unsigned int mpdccr; +}; + +struct fsl_mmdc_info { + unsigned int mdctl; + unsigned int mdpdc; + unsigned int mdotc; + unsigned int mdcfg0; + unsigned int mdcfg1; + unsigned int mdcfg2; + unsigned int mdmisc; + unsigned int mdref; + unsigned int mdrwd; + unsigned int mdor; + unsigned int mdasp; + unsigned int mpodtctrl; + unsigned int mpzqhwctrl; + unsigned int mprddlctl; +}; + +void mmdc_init(const struct fsl_mmdc_info *priv, uintptr_t nxp_ddr_addr); + +#endif /* FSL_MMDC_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/immap.h b/arm-trusted-firmware/include/drivers/nxp/ddr/immap.h new file mode 100644 index 0000000..83b4de6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/immap.h @@ -0,0 +1,125 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_IMMAP_H +#define DDR_IMMAP_H + +#define DDR_DBUS_64 0 +#define DDR_DBUS_32 1 +#define DDR_DBUS_16 2 + +/* + * DDRC register file for DDRC 5.0 and above + */ +struct ccsr_ddr { + struct { + unsigned int a; /* 0x0, 0x8, 0x10, 0x18 */ + unsigned int res; /* 0x4, 0xc, 0x14, 0x1c */ + } bnds[4]; + unsigned char res_20[0x40 - 0x20]; + unsigned int dec[10]; /* 0x40 */ + unsigned char res_68[0x80 - 0x68]; + unsigned int csn_cfg[4]; /* 0x80, 0x84, 0x88, 0x8c */ + unsigned char res_90[48]; + unsigned int csn_cfg_2[4]; /* 0xc0, 0xc4, 0xc8, 0xcc */ + unsigned char res_d0[48]; + unsigned int timing_cfg_3; /* SDRAM Timing Configuration 3 */ + unsigned int timing_cfg_0; /* SDRAM Timing Configuration 0 */ + unsigned int timing_cfg_1; /* SDRAM Timing Configuration 1 */ + unsigned int timing_cfg_2; /* SDRAM Timing Configuration 2 */ + unsigned int sdram_cfg; /* SDRAM Control Configuration */ + unsigned int sdram_cfg_2; /* SDRAM Control Configuration 2 */ + unsigned int sdram_mode; /* SDRAM Mode Configuration */ + unsigned int sdram_mode_2; /* SDRAM Mode Configuration 2 */ + unsigned int sdram_md_cntl; /* SDRAM Mode Control */ + unsigned int sdram_interval; /* SDRAM Interval Configuration */ + unsigned int sdram_data_init; /* SDRAM Data initialization */ + unsigned char res_12c[4]; + unsigned int sdram_clk_cntl; /* SDRAM Clock Control */ + unsigned char res_134[20]; + unsigned int init_addr; /* training init addr */ + unsigned int init_ext_addr; /* training init extended addr */ + unsigned char res_150[16]; + unsigned int timing_cfg_4; /* SDRAM Timing Configuration 4 */ + unsigned int timing_cfg_5; /* SDRAM Timing Configuration 5 */ + unsigned int timing_cfg_6; /* SDRAM Timing Configuration 6 */ + unsigned int timing_cfg_7; /* SDRAM Timing Configuration 7 */ + unsigned int zq_cntl; /* ZQ calibration control*/ + unsigned int wrlvl_cntl; /* write leveling control*/ + unsigned char reg_178[4]; + unsigned int ddr_sr_cntr; /* self refresh counter */ + unsigned int ddr_sdram_rcw_1; /* Control Words 1 */ + unsigned int ddr_sdram_rcw_2; /* Control Words 2 */ + unsigned char reg_188[8]; + unsigned int ddr_wrlvl_cntl_2; /* write leveling control 2 */ + unsigned int ddr_wrlvl_cntl_3; /* write leveling control 3 */ + unsigned char res_198[0x1a0-0x198]; + unsigned int ddr_sdram_rcw_3; + unsigned int ddr_sdram_rcw_4; + unsigned int ddr_sdram_rcw_5; + unsigned int ddr_sdram_rcw_6; + unsigned char res_1b0[0x200-0x1b0]; + unsigned int sdram_mode_3; /* SDRAM Mode Configuration 3 */ + unsigned int sdram_mode_4; /* SDRAM Mode Configuration 4 */ + unsigned int sdram_mode_5; /* SDRAM Mode Configuration 5 */ + unsigned int sdram_mode_6; /* SDRAM Mode Configuration 6 */ + unsigned int sdram_mode_7; /* SDRAM Mode Configuration 7 */ + unsigned int sdram_mode_8; /* SDRAM Mode Configuration 8 */ + unsigned char res_218[0x220-0x218]; + unsigned int sdram_mode_9; /* SDRAM Mode Configuration 9 */ + unsigned int sdram_mode_10; /* SDRAM Mode Configuration 10 */ + unsigned int sdram_mode_11; /* SDRAM Mode Configuration 11 */ + unsigned int sdram_mode_12; /* SDRAM Mode Configuration 12 */ + unsigned int sdram_mode_13; /* SDRAM Mode Configuration 13 */ + unsigned int sdram_mode_14; /* SDRAM Mode Configuration 14 */ + unsigned int sdram_mode_15; /* SDRAM Mode Configuration 15 */ + unsigned int sdram_mode_16; /* SDRAM Mode Configuration 16 */ + unsigned char res_240[0x250-0x240]; + unsigned int timing_cfg_8; /* SDRAM Timing Configuration 8 */ + unsigned int timing_cfg_9; /* SDRAM Timing Configuration 9 */ + unsigned int timing_cfg_10; /* SDRAM Timing COnfigurtion 10 */ + unsigned char res_258[0x260-0x25c]; + unsigned int sdram_cfg_3; + unsigned char res_264[0x270-0x264]; + unsigned int sdram_md_cntl_2; + unsigned char res_274[0x400-0x274]; + unsigned int dq_map[4]; + unsigned char res_410[0x800-0x410]; + unsigned int tx_cfg[4]; + unsigned char res_810[0xb20-0x810]; + unsigned int ddr_dsr1; /* Debug Status 1 */ + unsigned int ddr_dsr2; /* Debug Status 2 */ + unsigned int ddr_cdr1; /* Control Driver 1 */ + unsigned int ddr_cdr2; /* Control Driver 2 */ + unsigned char res_b30[200]; + unsigned int ip_rev1; /* IP Block Revision 1 */ + unsigned int ip_rev2; /* IP Block Revision 2 */ + unsigned int eor; /* Enhanced Optimization Register */ + unsigned char res_c04[252]; + unsigned int mtcr; /* Memory Test Control Register */ + unsigned char res_d04[28]; + unsigned int mtp[10]; /* Memory Test Patterns */ + unsigned char res_d48[184]; + unsigned int data_err_inject_hi; /* Data Path Err Injection Mask Hi*/ + unsigned int data_err_inject_lo;/* Data Path Err Injection Mask Lo*/ + unsigned int ecc_err_inject; /* Data Path Err Injection Mask ECC */ + unsigned char res_e0c[20]; + unsigned int capture_data_hi; /* Data Path Read Capture High */ + unsigned int capture_data_lo; /* Data Path Read Capture Low */ + unsigned int capture_ecc; /* Data Path Read Capture ECC */ + unsigned char res_e2c[20]; + unsigned int err_detect; /* Error Detect */ + unsigned int err_disable; /* Error Disable */ + unsigned int err_int_en; + unsigned int capture_attributes; /* Error Attrs Capture */ + unsigned int capture_address; /* Error Addr Capture */ + unsigned int capture_ext_address; /* Error Extended Addr Capture */ + unsigned int err_sbe; /* Single-Bit ECC Error Management */ + unsigned char res_e5c[164]; + unsigned int debug[64]; /* debug_1 to debug_64 */ +}; +#endif /* DDR_IMMAP_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/opts.h b/arm-trusted-firmware/include/drivers/nxp/ddr/opts.h new file mode 100644 index 0000000..f32891b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/opts.h @@ -0,0 +1,119 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_OPTS_H +#define DDR_OPTS_H + +#define SDRAM_TYPE_DDR4 5 /* sdram_cfg register */ + +#define DDR_BC4 4 /* burst chop */ +#define DDR_OTF 6 /* on-the-fly BC4 and BL8 */ +#define DDR_BL8 8 /* burst length 8 */ + +#define DDR4_RTT_OFF 0 +#define DDR4_RTT_60_OHM 1 /* RZQ/4 */ +#define DDR4_RTT_120_OHM 2 /* RZQ/2 */ +#define DDR4_RTT_40_OHM 3 /* RZQ/6 */ +#define DDR4_RTT_240_OHM 4 /* RZQ/1 */ +#define DDR4_RTT_48_OHM 5 /* RZQ/5 */ +#define DDR4_RTT_80_OHM 6 /* RZQ/3 */ +#define DDR4_RTT_34_OHM 7 /* RZQ/7 */ +#define DDR4_RTT_WR_OFF 0 +#define DDR4_RTT_WR_120_OHM 1 +#define DDR4_RTT_WR_240_OHM 2 +#define DDR4_RTT_WR_HZ 3 +#define DDR4_RTT_WR_80_OHM 4 +#define DDR_ODT_NEVER 0x0 +#define DDR_ODT_CS 0x1 +#define DDR_ODT_ALL_OTHER_CS 0x2 +#define DDR_ODT_OTHER_DIMM 0x3 +#define DDR_ODT_ALL 0x4 +#define DDR_ODT_SAME_DIMM 0x5 +#define DDR_ODT_CS_AND_OTHER_DIMM 0x6 +#define DDR_ODT_OTHER_CS_ONSAMEDIMM 0x7 +#define DDR_BA_INTLV_CS01 0x40 +#define DDR_BA_INTLV_CS0123 0x64 +#define DDR_BA_NONE 0 +#define DDR_256B_INTLV 0x8 + +struct memctl_opt { + int rdimm; + unsigned int dbw_cap_shift; + struct local_opts_s { + unsigned int auto_precharge; + unsigned int odt_rd_cfg; + unsigned int odt_wr_cfg; + unsigned int odt_rtt_norm; + unsigned int odt_rtt_wr; + } cs_odt[DDRC_NUM_CS]; + int ctlr_intlv; + unsigned int ctlr_intlv_mode; + unsigned int ba_intlv; + int addr_hash; + int ecc_mode; + int ctlr_init_ecc; + int self_refresh_in_sleep; + int self_refresh_irq_en; + int dynamic_power; + /* memory data width 0 = 64-bit, 1 = 32-bit, 2 = 16-bit */ + unsigned int data_bus_dimm; + unsigned int data_bus_used; /* on individual board */ + unsigned int burst_length; /* BC4, OTF and BL8 */ + int otf_burst_chop_en; + int mirrored_dimm; + int quad_rank_present; + int output_driver_impedance; + int ap_en; + int x4_en; + + int caslat_override; + unsigned int caslat_override_value; + int addt_lat_override; + unsigned int addt_lat_override_value; + + unsigned int clk_adj; + unsigned int cpo_sample; + unsigned int wr_data_delay; + + unsigned int cswl_override; + unsigned int wrlvl_override; + unsigned int wrlvl_sample; + unsigned int wrlvl_start; + unsigned int wrlvl_ctl_2; + unsigned int wrlvl_ctl_3; + + int half_strength_drive_en; + int twot_en; + int threet_en; + unsigned int bstopre; + unsigned int tfaw_ps; + + int rtt_override; + unsigned int rtt_override_value; + unsigned int rtt_wr_override_value; + unsigned int rtt_park; + + int auto_self_refresh_en; + unsigned int sr_it; + unsigned int ddr_cdr1; + unsigned int ddr_cdr2; + + unsigned int trwt_override; + unsigned int trwt; + unsigned int twrt; + unsigned int trrt; + unsigned int twwt; + + unsigned int vref_phy; + unsigned int vref_dimm; + unsigned int odt; + unsigned int phy_tx_impedance; + unsigned int phy_atx_impedance; + unsigned int skip2d; +}; + +#endif /* DDR_OPTS_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/regs.h b/arm-trusted-firmware/include/drivers/nxp/ddr/regs.h new file mode 100644 index 0000000..e85fd8f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/regs.h @@ -0,0 +1,109 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_REG_H +#define DDR_REG_H + +#define SDRAM_CS_CONFIG_EN 0x80000000 + +/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration + */ +#define SDRAM_CFG_MEM_EN 0x80000000 +#define SDRAM_CFG_SREN 0x40000000 +#define SDRAM_CFG_ECC_EN 0x20000000 +#define SDRAM_CFG_RD_EN 0x10000000 +#define SDRAM_CFG_SDRAM_TYPE_MASK 0x07000000 +#define SDRAM_CFG_SDRAM_TYPE_SHIFT 24 +#define SDRAM_CFG_DYN_PWR 0x00200000 +#define SDRAM_CFG_DBW_MASK 0x00180000 +#define SDRAM_CFG_DBW_SHIFT 19 +#define SDRAM_CFG_32_BW 0x00080000 +#define SDRAM_CFG_16_BW 0x00100000 +#define SDRAM_CFG_8_BW 0x00180000 +#define SDRAM_CFG_8_BE 0x00040000 +#define SDRAM_CFG_2T_EN 0x00008000 +#define SDRAM_CFG_MEM_HLT 0x00000002 +#define SDRAM_CFG_BI 0x00000001 + +#define SDRAM_CFG2_FRC_SR 0x80000000 +#define SDRAM_CFG2_FRC_SR_CLEAR ~(SDRAM_CFG2_FRC_SR) +#define SDRAM_CFG2_D_INIT 0x00000010 +#define SDRAM_CFG2_AP_EN 0x00000020 +#define SDRAM_CFG2_ODT_ONLY_READ 2 + +#define SDRAM_CFG3_DDRC_RST 0x80000000 + +#define SDRAM_INTERVAL_REFINT 0xFFFF0000 +#define SDRAM_INTERVAL_REFINT_CLEAR ~(SDRAM_INTERVAL_REFINT) +#define SDRAM_INTERVAL_BSTOPRE 0x3FFF + +/* DDR_MD_CNTL */ +#define MD_CNTL_MD_EN 0x80000000 +#define MD_CNTL_CS_SEL(x) (((x) & 0x7) << 28) +#define MD_CNTL_MD_SEL(x) (((x) & 0xf) << 24) +#define MD_CNTL_CKE(x) (((x) & 0x3) << 20) + +/* DDR_CDR1 */ +#define DDR_CDR1_DHC_EN 0x80000000 +#define DDR_CDR1_ODT_SHIFT 17 +#define DDR_CDR1_ODT_MASK 0x6 +#define DDR_CDR2_ODT_MASK 0x1 +#define DDR_CDR1_ODT(x) ((x & DDR_CDR1_ODT_MASK) << DDR_CDR1_ODT_SHIFT) +#define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK) +#define DDR_CDR2_VREF_OVRD(x) (0x00008080 | ((((x) - 37) & 0x3F) << 8)) +#define DDR_CDR2_VREF_TRAIN_EN 0x00000080 +#define DDR_CDR2_VREF_RANGE_2 0x00000040 +#define DDR_CDR_ODT_OFF 0x0 +#define DDR_CDR_ODT_100ohm 0x1 +#define DDR_CDR_ODT_120OHM 0x2 +#define DDR_CDR_ODT_80ohm 0x3 +#define DDR_CDR_ODT_60ohm 0x4 +#define DDR_CDR_ODT_40ohm 0x5 +#define DDR_CDR_ODT_50ohm 0x6 +#define DDR_CDR_ODT_30ohm 0x7 + + +/* DDR ERR_DISABLE */ +#define DDR_ERR_DISABLE_APED (1 << 8) /* Address parity error disable */ +#define DDR_ERR_DISABLE_SBED (1 << 2) /* Address parity error disable */ +#define DDR_ERR_DISABLE_MBED (1 << 3) /* Address parity error disable */ + +/* Mode Registers */ +#define DDR_MR5_CA_PARITY_LAT_4_CLK 0x1 /* for DDR4-1600/1866/2133 */ +#define DDR_MR5_CA_PARITY_LAT_5_CLK 0x2 /* for DDR4-2400 */ + +/* DDR DSR2 register */ +#define DDR_DSR_2_PHY_INIT_CMPLT 0x4 + +/* SDRAM TIMING_CFG_10 register */ +#define DDR_TIMING_CFG_10_T_STAB 0x7FFF + +/* DEBUG 2 register */ +#define DDR_DBG_2_MEM_IDLE 0x00000002 + +/* DEBUG 26 register */ +#define DDR_DEBUG_26_BIT_6 (0x1 << 6) +#define DDR_DEBUG_26_BIT_7 (0x1 << 7) +#define DDR_DEBUG_26_BIT_12 (0x1 << 12) +#define DDR_DEBUG_26_BIT_13 (0x1 << 13) +#define DDR_DEBUG_26_BIT_14 (0x1 << 14) +#define DDR_DEBUG_26_BIT_15 (0x1 << 15) +#define DDR_DEBUG_26_BIT_16 (0x1 << 16) +#define DDR_DEBUG_26_BIT_17 (0x1 << 17) +#define DDR_DEBUG_26_BIT_18 (0x1 << 18) +#define DDR_DEBUG_26_BIT_19 (0x1 << 19) +#define DDR_DEBUG_26_BIT_24 (0x1 << 24) +#define DDR_DEBUG_26_BIT_25 (0x1 << 25) + +#define DDR_DEBUG_26_BIT_24_CLEAR ~(DDR_DEBUG_26_BIT_24) + +/* DEBUG_29 register */ +#define DDR_TX_BD_DIS (1 << 10) /* Transmit Bit Deskew Disable */ + +#define DDR_INIT_ADDR_EXT_UIA (1 << 31) + +#endif /* DDR_REG_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/utility.h b/arm-trusted-firmware/include/drivers/nxp/ddr/utility.h new file mode 100644 index 0000000..2e22ad5 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/utility.h @@ -0,0 +1,24 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef UTILITY_H +#define UTILITY_H + +#include + +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) +#define CCN_HN_F_SAM_CTL 0x8 +#define CCN_HN_F_REGION_SIZE 0x10000 +#endif + +unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num); +unsigned int get_memory_clk_ps(unsigned long clk); +unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos); +unsigned int get_ddrc_version(const struct ccsr_ddr *ddr); +void print_ddr_info(struct ccsr_ddr *ddr); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h b/arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h new file mode 100644 index 0000000..d0ffc86 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2020-2021 NXP + */ + +/** + * @Flash info + * + */ +#ifndef FLASH_INFO_H +#define FLASH_INFO_H + +#define SZ_16M_BYTES 0x1000000U + +/* Start of "if defined(CONFIG_MT25QU512A)" */ +#if defined(CONFIG_MT25QU512A) +#define F_SECTOR_64K 0x10000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x4000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_64K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif + +/* End of "if defined(CONFIG_MT25QU512A)" */ + +/* Start of "if defined(CONFIG_MX25U25645G)" */ +#elif defined(CONFIG_MX25U25645G) +#define F_SECTOR_64K 0x10000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x2000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_64K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif + +/* End of "if defined(CONFIG_MX25U25645G)" */ + +/* Start of "if defined(CONFIG_MX25U51245G)" */ +#elif defined(CONFIG_MX25U51245G) +#define F_SECTOR_64K 0x10000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x4000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_64K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif + +/* End of "if defined(CONFIG_MX25U51245G)" */ + +/* Start of "if defined(CONFIG_MT35XU512A)" */ +#elif defined(CONFIG_MT35XU512A) +#define F_SECTOR_128K 0x20000U +#define F_SECTOR_32K 0x8000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x4000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_128K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif +/* If Warm boot is enabled for the platform, + * count of arm instruction N-OP(s) to mark + * the completion of write operation to flash; + * varies from one flash to other. + */ +#ifdef NXP_WARM_BOOT +#define FLASH_WR_COMP_WAIT_BY_NOP_COUNT 0x20000 +#endif + +/* End of "if defined(CONFIG_MT35XU512A)" */ + +/* Start of #elif defined(CONFIG_MT35XU02G) */ +#elif defined(CONFIG_MT35XU02G) +#define F_SECTOR_128K 0x20000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x10000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_128K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif + +#endif /* End of #elif defined(CONFIG_MT35XU02G) */ + +#endif /* FLASH_INFO_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h b/arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h new file mode 100644 index 0000000..d0de543 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h @@ -0,0 +1,122 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +/*! + * @file fspi_api.h + * @brief This file contains the FlexSPI/FSPI API to communicate + * to attached Slave device. + * @addtogroup FSPI_API + * @{ + */ + +#ifndef FSPI_API_H +#define FSPI_API_H + +#if DEBUG_FLEXSPI +#define SZ_57M 0x3900000u +#endif + +/*! + * Basic set of APIs. + */ + +/*! + * @details AHB read/IP Read, decision to be internal to API + * Minimum Read size = 1Byte + * @param[in] src_off source offset from where data to read from flash + * @param[out] des Destination location where data needs to be copied + * @param[in] len length in Bytes,where 1-word=4-bytes/32-bits + * + * @return XSPI_SUCCESS or error code + */ +int xspi_read(uint32_t src_off, uint32_t *des, uint32_t len); +/*! + * @details Sector erase, Minimum size + * 256KB(0x40000)/128KB(0x20000)/64K(0x10000)/4K(0x1000) + * depending upon flash, Calls xspi_wren() internally + * @param[out] erase_offset Destination erase location on flash which + * has to be erased, needs to be multiple of 0x40000/0x20000/0x10000 + * @param[in] erase_len length in bytes in Hex like 0x100000 for 1MB, minimum + * erase size is 1 sector(0x40000/0x20000/0x10000) + * + * @return XSPI_SUCCESS or error code + */ +int xspi_sector_erase(uint32_t erase_offset, uint32_t erase_len); +/*! + * @details IP write, For writing data to flash, calls xspi_wren() internally. + * Single/multiple page write can start @any offset, but performance will be low + * due to ERRATA + * @param[out] dst_off Destination location on flash where data needs to + * be written + * @param[in] src source offset from where data to be read + * @param[in] len length in bytes,where 1-word=4-bytes/32-bits + * + * @return XSPI_SUCCESS or error code + */ +int xspi_write(uint32_t dst_off, void *src, uint32_t len); +/*! + * @details fspi_init, Init function. + * @param[in] uint32_t base_reg_addr + * @param[in] uint32_t flash_start_addr + * + * @return XSPI_SUCCESS or error code + */ +int fspi_init(uint32_t base_reg_addr, uint32_t flash_start_addr); +/*! + * @details is_flash_busy, Check if any erase or write or lock is + * pending on flash/slave + * @param[in] void + * + * @return TRUE/FLASE + */ +bool is_flash_busy(void); + +/*! + * Advanced set of APIs. + */ + +/*! + * @details Write enable, to be used by advance users only. + * Step 1 for sending write commands to flash. + * @param[in] dst_off destination offset where data will be written + * + * @return XSPI_SUCCESS or error code + */ +int xspi_wren(uint32_t dst_off); +/*! + * @details AHB read, meaning direct memory mapped access to flash, + * Minimum Read size = 1Byte + * @param[in] src_off source offset from where data to read from flash, + * needs to be word aligned + * @param[out] des Destination location where data needs to be copied + * @param[in] len length in Bytes,where 1-word=4-bytes/32-bits + * + * @return XSPI_SUCCESS or error code + */ +int xspi_ahb_read(uint32_t src_off, uint32_t *des, uint32_t len); +/*! + * @details IP read, READ via RX buffer from flash, minimum READ size = 1Byte + * @param[in] src_off source offset from where data to be read from flash + * @param[out] des Destination location where data needs to be copied + * @param[in] len length in Bytes,where 1-word=4-bytes/32-bits + * + * @return XSPI_SUCCESS or error code + */ +int xspi_ip_read(uint32_t src_off, uint32_t *des, uint32_t len); +/*! + * @details CHIP erase, Erase complete chip in one go + * + * @return XSPI_SUCCESS or error code + */ +int xspi_bulk_erase(void); + +/*! + * Add test cases to confirm flash read/erase/write functionality. + */ +void fspi_test(uint32_t fspi_test_addr, uint32_t size, int extra); +#endif /* FSPI_API_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h b/arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h new file mode 100644 index 0000000..18b31eb --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h @@ -0,0 +1,28 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* error codes */ +#ifndef XSPI_ERROR_CODES_H +#define XSPI_ERROR_CODES_H + +#include + +typedef enum { + XSPI_SUCCESS = 0, + XSPI_READ_FAIL = ELAST + 1, + XSPI_ERASE_FAIL, + XSPI_IP_READ_FAIL, + XSPI_AHB_READ_FAIL, + XSPI_IP_WRITE_FAIL, + XSPI_AHB_WRITE_FAIL, + XSPI_BLOCK_TIMEOUT, + XSPI_UNALIGN_ADDR, + XSPI_UNALIGN_SIZE, +} XSPI_STATUS_CODES; +#undef ELAST +#define ELAST XSPI_STATUS_CODES.XSPI_UNALIGN_SIZE +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h b/arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h new file mode 100644 index 0000000..ff34744 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h @@ -0,0 +1,72 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_GICV2_H +#define PLAT_GICV2_H + +#include + + /* register offsets */ +#define GICD_CTLR_OFFSET 0x0 +#define GICD_CPENDSGIR3_OFFSET 0xF1C +#define GICD_SPENDSGIR3_OFFSET 0xF2C +#define GICD_SGIR_OFFSET 0xF00 +#define GICD_IGROUPR0_OFFSET 0x080 +#define GICD_TYPER_OFFSET 0x0004 +#define GICD_ISENABLER0_OFFSET 0x0100 +#define GICD_ICENABLER0_OFFSET 0x0180 +#define GICD_IPRIORITYR3_OFFSET 0x040C +#define GICD_ISENABLERn_OFFSET 0x0100 +#define GICD_ISACTIVER0_OFFSET 0x300 + +#define GICC_CTLR_OFFSET 0x0 +#define GICC_PMR_OFFSET 0x0004 +#define GICC_IAR_OFFSET 0x000C +#define GICC_DIR_OFFSET 0x1000 +#define GICC_EOIR_OFFSET 0x0010 + + /* bitfield masks */ +#define GICC_CTLR_EN_GRP0 0x1 +#define GICC_CTLR_EN_GRP1 0x2 +#define GICC_CTLR_EOImodeS_MASK 0x200 +#define GICC_CTLR_DIS_BYPASS 0x60 +#define GICC_CTLR_CBPR_MASK 0x10 +#define GICC_CTLR_FIQ_EN_MASK 0x8 +#define GICC_CTLR_ACKCTL_MASK 0x4 +#define GICC_PMR_FILTER 0xFF + +#define GICD_CTLR_EN_GRP0 0x1 +#define GICD_CTLR_EN_GRP1 0x2 +#define GICD_IGROUP0_SGI15 0x8000 +#define GICD_ISENABLE0_SGI15 0x8000 +#define GICD_ICENABLE0_SGI15 0x8000 +#define GICD_ISACTIVER0_SGI15 0x8000 +#define GICD_CPENDSGIR_CLR_MASK 0xFF000000 +#define GICD_IPRIORITY_SGI15_MASK 0xFF000000 +#define GICD_SPENDSGIR3_SGI15_MASK 0xFF000000 +#define GICD_SPENDSGIR3_SGI15_OFFSET 0x18 + +#ifndef __ASSEMBLER__ + +/* GIC common API's */ +void plat_ls_gic_driver_init(const uintptr_t nxp_gicd_addr, + const uintptr_t nxp_gicc_addr, + uint8_t plat_core_count, + interrupt_prop_t *ls_interrupt_props, + uint8_t ls_interrupt_prop_count, + uint32_t *target_mask_array); +void plat_ls_gic_init(void); +void plat_ls_gic_cpuif_enable(void); +void plat_ls_gic_cpuif_disable(void); +void plat_ls_gic_redistif_on(void); +void plat_ls_gic_redistif_off(void); +void plat_gic_pcpu_init(void); +/* GIC utility functions */ +void get_gic_offset(uint32_t *gicc_base, uint32_t *gicd_base); +#endif + +#endif /* PLAT_GICV2_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h b/arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h new file mode 100644 index 0000000..0c0d0fc --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h @@ -0,0 +1,121 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_GICV3_H +#define PLAT_GICV3_H + +#include + + /* offset between redistributors */ +#define GIC_RD_OFFSET 0x00020000 + /* offset between SGI's */ +#define GIC_SGI_OFFSET 0x00020000 + /* offset from rd base to sgi base */ +#define GIC_RD_2_SGI_OFFSET 0x00010000 + + /* register offsets */ +#define GICD_CTLR_OFFSET 0x0 +#define GICD_CLR_SPI_SR 0x58 +#define GICD_IGROUPR_2 0x88 +#define GICD_ISENABLER_1 0x104 +#define GICD_ICENABLER_1 0x184 +#define GICD_ISENABLER_2 0x108 +#define GICD_ICENABLER_2 0x188 +#define GICD_ISENABLER_3 0x10c +#define GICD_ICENABLER_3 0x18c +#define GICD_ICPENDR_2 0x288 +#define GICD_ICACTIVER_2 0x388 +#define GICD_IPRIORITYR_22 0x458 +#define GICD_ICFGR_5 0xC14 +#define GICD_IGRPMODR_2 0xD08 + +#define GICD_IROUTER60_OFFSET 0x61e0 +#define GICD_IROUTER76_OFFSET 0x6260 +#define GICD_IROUTER89_OFFSET 0x62C8 +#define GICD_IROUTER112_OFFSET 0x6380 +#define GICD_IROUTER113_OFFSET 0x6388 + +#define GICR_ICENABLER0_OFFSET 0x180 +#define GICR_CTLR_OFFSET 0x0 +#define GICR_IGROUPR0_OFFSET 0x80 +#define GICR_IGRPMODR0_OFFSET 0xD00 +#define GICR_IPRIORITYR3_OFFSET 0x40C +#define GICR_ICPENDR0_OFFSET 0x280 +#define GICR_ISENABLER0_OFFSET 0x100 +#define GICR_TYPER_OFFSET 0x8 +#define GICR_WAKER_OFFSET 0x14 +#define GICR_ICACTIVER0_OFFSET 0x380 +#define GICR_ICFGR0_OFFSET 0xC00 + + /* bitfield masks */ +#define GICD_CTLR_EN_GRP_MASK 0x7 +#define GICD_CTLR_EN_GRP_1NS 0x2 +#define GICD_CTLR_EN_GRP_1S 0x4 +#define GICD_CTLR_EN_GRP_0 0x1 +#define GICD_CTLR_ARE_S_MASK 0x10 +#define GICD_CTLR_RWP 0x80000000 + +#define GICR_ICENABLER0_SGI15 0x00008000 +#define GICR_CTLR_RWP 0x8 +#define GICR_CTLR_DPG0_MASK 0x2000000 +#define GICR_IGROUPR0_SGI15 0x00008000 +#define GICR_IGRPMODR0_SGI15 0x00008000 +#define GICR_ISENABLER0_SGI15 0x00008000 +#define GICR_IPRIORITYR3_SGI15_MASK 0xFF000000 +#define GICR_ICPENDR0_SGI15 0x8000 + +#define GIC_SPI_89_MASK 0x02000000 +#define GIC_SPI89_PRIORITY_MASK 0xFF00 +#define GIC_IRM_SPI89 0x80000000 + +#define GICD_IROUTER_VALUE 0x100 +#define GICD_ISENABLER_1_VALUE 0x10000000 +#define GICD_ISENABLER_2_VALUE 0x100 +#define GICD_ISENABLER_3_VALUE 0x20100 +#define GICR_WAKER_SLEEP_BIT 0x2 +#define GICR_WAKER_ASLEEP (1 << 2 | 1 << 1) + +#define ICC_SRE_EL3_SRE 0x1 +#define ICC_IGRPEN0_EL1_EN 0x1 +#define ICC_CTLR_EL3_CBPR_EL1S 0x1 +#define ICC_CTLR_EL3_RM 0x20 +#define ICC_CTLR_EL3_EOIMODE_EL3 0x4 +#define ICC_CTLR_EL3_PMHE 0x40 +#define ICC_PMR_EL1_P_FILTER 0xFF +#define ICC_IAR0_EL1_SGI15 0xF +#define ICC_SGI0R_EL1_INTID 0x0F000000 +#define ICC_IAR0_INTID_SPI_89 0x59 + +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_PMR_EL1 S3_0_C4_C6_0 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 + +#ifndef __ASSEMBLER__ + +/* GIC common API's */ +typedef unsigned int (*my_core_pos_fn)(void); + +void plat_ls_gic_driver_init(const uintptr_t nxp_gicd_addr, + const uintptr_t nxp_gicr_addr, + uint8_t plat_core_count, + interrupt_prop_t *ls_interrupt_props, + uint8_t ls_interrupt_prop_count, + uintptr_t *target_mask_array, + mpidr_hash_fn mpidr_to_core_pos); +//void plat_ls_gic_driver_init(void); +void plat_ls_gic_init(void); +void plat_ls_gic_cpuif_enable(void); +void plat_ls_gic_cpuif_disable(void); +void plat_ls_gic_redistif_on(void); +void plat_ls_gic_redistif_off(void); +void plat_gic_pcpu_init(void); +#endif + +#endif /* PLAT_GICV3_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h b/arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h new file mode 100644 index 0000000..df75840 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h @@ -0,0 +1,53 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_GPIO_H +#define PLAT_GPIO_H + +#include +#include + +/* GPIO Register offset */ +#define GPIO_SEL_MASK 0x7F +#define GPIO_BIT_MASK 0x1F +#define GPDIR_REG_OFFSET 0x0 +#define GPDAT_REG_OFFSET 0x8 + +#define GPIO_ID_BASE_ADDR_SHIFT 5U +#define GPIO_BITS_PER_BASE_REG 32U + +#define GPIO_0 0 +#define GPIO_1 1 +#define GPIO_2 2 +#define GPIO_3 3 + +#define GPIO_SUCCESS 0x0 +#define GPIO_FAILURE 0x1 + +#ifdef NXP_GPIO_BE +#define gpio_read32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define gpio_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_GPIO_LE) +#define gpio_read32(a) mmio_read_32((uintptr_t)(a)) +#define gpio_write32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define GPIO register endianness +#endif + +typedef struct { + uintptr_t gpio1_base_addr; + uintptr_t gpio2_base_addr; + uintptr_t gpio3_base_addr; + uintptr_t gpio4_base_addr; +} gpio_init_info_t; + +void gpio_init(gpio_init_info_t *gpio_init_data); +uint32_t *select_gpio_n_bitnum(uint32_t povdd_gpio, uint32_t *bit_num); +int clr_gpio_bit(uint32_t *gpio_base_addr, uint32_t bit_num); +int set_gpio_bit(uint32_t *gpio_base_addr, uint32_t bit_num); + +#endif /* PLAT_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h b/arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h new file mode 100644 index 0000000..85e6eb4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h @@ -0,0 +1,52 @@ +/* + * Copyright 2016-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#ifndef I2C_H +#define I2C_H + +#include + +#define I2C_TIMEOUT 1000 /* ms */ + +#define I2C_FD_CONSERV 0x7e +#define I2C_CR_DIS (1 << 7) +#define I2C_CR_EN (0 << 7) +#define I2C_CR_MA (1 << 5) +#define I2C_CR_TX (1 << 4) +#define I2C_CR_TX_NAK (1 << 3) +#define I2C_CR_RSTA (1 << 2) +#define I2C_SR_BB (1 << 5) +#define I2C_SR_IDLE (0 << 5) +#define I2C_SR_AL (1 << 4) +#define I2C_SR_IF (1 << 1) +#define I2C_SR_RX_NAK (1 << 0) +#define I2C_SR_RST (I2C_SR_AL | I2C_SR_IF) + +#define I2C_GLITCH_EN 0x8 + +#define i2c_in(a) mmio_read_8((uintptr_t)(a)) +#define i2c_out(a, v) mmio_write_8((uintptr_t)(a), (v)) + +struct ls_i2c { + unsigned char ad; /* I2c Bus Address Register */ + unsigned char fd; /* I2c Bus Frequency Dividor Register */ + unsigned char cr; /* I2c Bus Control Register */ + unsigned char sr; /* I2c Bus Status Register */ + unsigned char dr; /* I2C Bus Data I/O Register */ + unsigned char ic; /* I2C Bus Interrupt Config Register */ + unsigned char dbg; /* I2C Bus Debug Register */ +}; + +void i2c_init(uintptr_t nxp_i2c_addr); +int i2c_read(unsigned char chip, int addr, int alen, + unsigned char *buf, int len); +int i2c_write(unsigned char chip, int addr, int alen, + const unsigned char *buf, int len); +int i2c_probe_chip(unsigned char chip); + +#endif /* I2C_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h b/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h new file mode 100644 index 0000000..dbcd762 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h @@ -0,0 +1,19 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IFC_NAND_H +#define IFC_NAND_H + +#define NXP_IFC_SRAM_BUFFER_SIZE UL(0x100000) /* 1M */ + +int ifc_nand_init(uintptr_t *block_dev_spec, + uintptr_t ifc_region_addr, + uintptr_t ifc_register_addr, + size_t ifc_sram_size, + uintptr_t ifc_nand_blk_offset, + size_t ifc_nand_blk_size); + +#endif /*IFC_NAND_H*/ diff --git a/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h b/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h new file mode 100644 index 0000000..ee14460 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h @@ -0,0 +1,14 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef IFC_NOR_H +#define IFC_NOR_H + + +int ifc_nor_init(uintptr_t flash_addr, size_t flash_size); + +#endif /*IFC_NOR_H*/ diff --git a/arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h b/arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h new file mode 100644 index 0000000..777089c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h @@ -0,0 +1,19 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef LS_INTERCONNECT_H +#define LS_INTERCONNECT_H + +#if (INTERCONNECT == CCI400) +#define CCI_TERMINATE_BARRIER_TX 0x8 +#endif + +/* Interconnect CCI/CCN functions */ +void plat_ls_interconnect_enter_coherency(unsigned int num_clusters); +void plat_ls_interconnect_exit_coherency(void); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h b/arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h new file mode 100644 index 0000000..28199e8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h @@ -0,0 +1,75 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PMU_H +#define PMU_H + +/* PMU Registers' OFFSET */ +#define PMU_PCPW20SR_OFFSET 0x830 +#define PMU_CLL2FLUSHSETR_OFFSET 0x1110 +#define PMU_CLSL2FLUSHCLRR_OFFSET 0x1114 +#define PMU_CLL2FLUSHSR_OFFSET 0x1118 +#define PMU_POWMGTCSR_VAL (1 << 20) + +/* PMU Registers */ +#define CORE_TIMEBASE_ENBL_OFFSET 0x8A0 +#define CLUST_TIMER_BASE_ENBL_OFFSET 0x18A0 + +#define PMU_IDLE_CLUSTER_MASK 0x2 +#define PMU_FLUSH_CLUSTER_MASK 0x2 +#define PMU_IDLE_CORE_MASK 0xfe + +/* pmu register offsets and bitmaps */ +#define PMU_POWMGTDCR0_OFFSET 0xC20 +#define PMU_POWMGTCSR_OFFSET 0x4000 +#define PMU_CLAINACTSETR_OFFSET 0x1100 +#define PMU_CLAINACTCLRR_OFFSET 0x1104 +#define PMU_CLSINACTSETR_OFFSET 0x1108 +#define PMU_CLSINACTCLRR_OFFSET 0x110C +#define PMU_CLL2FLUSHSETR_OFFSET 0x1110 +#define PMU_CLL2FLUSHCLRR_OFFSET 0x1114 +#define PMU_IPPDEXPCR0_OFFSET 0x4040 +#define PMU_IPPDEXPCR1_OFFSET 0x4044 +#define PMU_IPPDEXPCR2_OFFSET 0x4048 +#define PMU_IPPDEXPCR3_OFFSET 0x404C +#define PMU_IPPDEXPCR4_OFFSET 0x4050 +#define PMU_IPPDEXPCR5_OFFSET 0x4054 +#define PMU_IPPDEXPCR6_OFFSET 0x4058 +#define PMU_IPSTPCR0_OFFSET 0x4120 +#define PMU_IPSTPCR1_OFFSET 0x4124 +#define PMU_IPSTPCR2_OFFSET 0x4128 +#define PMU_IPSTPCR3_OFFSET 0x412C +#define PMU_IPSTPCR4_OFFSET 0x4130 +#define PMU_IPSTPCR5_OFFSET 0x4134 +#define PMU_IPSTPCR6_OFFSET 0x4138 +#define PMU_IPSTPACKSR0_OFFSET 0x4140 +#define PMU_IPSTPACKSR1_OFFSET 0x4144 +#define PMU_IPSTPACKSR2_OFFSET 0x4148 +#define PMU_IPSTPACKSR3_OFFSET 0x414C +#define PMU_IPSTPACKSR4_OFFSET 0x4150 +#define PMU_IPSTPACKSR5_OFFSET 0x4154 +#define PMU_IPSTPACKSR6_OFFSET 0x4158 + +#define CLAINACT_DISABLE_ACP 0xFF +#define CLSINACT_DISABLE_SKY 0xFF +#define POWMGTDCR_STP_OV_EN 0x1 +#define POWMGTCSR_LPM20_REQ 0x00100000 + +/* Used by PMU */ +#define DEVDISR1_MASK 0x024F3504 +#define DEVDISR2_MASK 0x0003FFFF +#define DEVDISR3_MASK 0x0000303F +#define DEVDISR4_MASK 0x0000FFFF +#define DEVDISR5_MASK 0x00F07603 +#define DEVDISR6_MASK 0x00000001 + +#ifndef __ASSEMBLER__ +void enable_timer_base_to_cluster(uintptr_t nxp_pmu_addr); +void enable_core_tb(uintptr_t nxp_pmu_addr); +#endif /* __ASSEMBLER__ */ + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h b/arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h new file mode 100644 index 0000000..db11c3b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h @@ -0,0 +1,30 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef QSPI_H +#define QSPI_H + +#include +#include + +#define CHS_QSPI_MCR 0x01550000 +#define CHS_QSPI_64LE 0xC + +#ifdef NXP_QSPI_BE +#define qspi_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define qspi_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_QSPI_LE) +#define qspi_in32(a) mmio_read_32((uintptr_t)(a)) +#define qspi_out32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define CCSR QSPI register endianness +#endif + +int qspi_io_setup(uintptr_t nxp_qspi_flash_addr, + size_t nxp_qspi_flash_size, + uintptr_t fip_offset); +#endif /* __QSPI_H__ */ diff --git a/arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h b/arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h new file mode 100644 index 0000000..32b41f1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2015, 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SD_MMC_H +#define SD_MMC_H + +#include + +/* operating freq */ +#define CARD_IDENTIFICATION_FREQ 400000 +#define SD_SS_25MHZ 20000000 +#define SD_HS_50MHZ 40000000 +#define MMC_SS_20MHZ 15000000 +#define MMC_HS_26MHZ 20000000 +#define MMC_HS_52MHZ 40000000 + +/* Need to check this value ? */ +#define MAX_PLATFORM_CLOCK 800000000 + +/* eSDHC system control register defines */ +#define ESDHC_SYSCTL_DTOCV(t) (((t) & 0xF) << 16) +#define ESDHC_SYSCTL_SDCLKFS(f) (((f) & 0xFF) << 8) +#define ESDHC_SYSCTL_DVS(d) (((d) & 0xF) << 4) +#define ESDHC_SYSCTL_SDCLKEN (0x00000008) +#define ESDHC_SYSCTL_RSTA (0x01000000) + +/* Data timeout counter value. SDHC_CLK x 227 */ +#define TIMEOUT_COUNTER_SDCLK_2_27 0xE +#define ESDHC_SYSCTL_INITA 0x08000000 + +/* eSDHC interrupt status enable register defines */ +#define ESDHC_IRQSTATEN_CINS 0x00000040 +#define ESDHC_IRQSTATEN_BWR 0x00000010 + +/* eSDHC interrupt status register defines */ +#define ESDHC_IRQSTAT_DMAE (0x10000000) +#define ESDHC_IRQSTAT_AC12E (0x01000000) +#define ESDHC_IRQSTAT_DEBE (0x00400000) +#define ESDHC_IRQSTAT_DCE (0x00200000) +#define ESDHC_IRQSTAT_DTOE (0x00100000) +#define ESDHC_IRQSTAT_CIE (0x00080000) +#define ESDHC_IRQSTAT_CEBE (0x00040000) +#define ESDHC_IRQSTAT_CCE (0x00020000) +#define ESDHC_IRQSTAT_CTOE (0x00010000) +#define ESDHC_IRQSTAT_CINT (0x00000100) +#define ESDHC_IRQSTAT_CRM (0x00000080) +#define ESDHC_IRQSTAT_CINS (0x00000040) +#define ESDHC_IRQSTAT_BRR (0x00000020) +#define ESDHC_IRQSTAT_BWR (0x00000010) +#define ESDHC_IRQSTAT_DINT (0x00000008) +#define ESDHC_IRQSTAT_BGE (0x00000004) +#define ESDHC_IRQSTAT_TC (0x00000002) +#define ESDHC_IRQSTAT_CC (0x00000001) +#define ESDHC_IRQSTAT_CMD_ERR (ESDHC_IRQSTAT_CIE |\ + ESDHC_IRQSTAT_CEBE |\ + ESDHC_IRQSTAT_CCE) +#define ESDHC_IRQSTAT_DATA_ERR (ESDHC_IRQSTAT_DEBE |\ + ESDHC_IRQSTAT_DCE |\ + ESDHC_IRQSTAT_DTOE) +#define ESDHC_IRQSTAT_CLEAR_ALL (0xFFFFFFFF) + +/* eSDHC present state register defines */ +#define ESDHC_PRSSTAT_CLSL 0x00800000 +#define ESDHC_PRSSTAT_WPSPL 0x00080000 +#define ESDHC_PRSSTAT_CDPL 0x00040000 +#define ESDHC_PRSSTAT_CINS 0x00010000 +#define ESDHC_PRSSTAT_BREN 0x00000800 +#define ESDHC_PRSSTAT_BWEN 0x00000400 +#define ESDHC_PRSSTAT_RTA 0x00000200 +#define ESDHC_PRSSTAT_WTA 0x00000100 +#define ESDHC_PRSSTAT_SDOFF 0x00000080 +#define ESDHC_PRSSTAT_PEROFF 0x00000040 +#define ESDHC_PRSSTAT_HCKOFF 0x00000020 +#define ESDHC_PRSSTAT_IPGOFF 0x00000010 +#define ESDHC_PRSSTAT_DLA 0x00000004 +#define ESDHC_PRSSTAT_CDIHB 0x00000002 +#define ESDHC_PRSSTAT_CIHB 0x00000001 + +/* eSDHC protocol control register defines */ +#define ESDHC_PROCTL_EMODE_LE 0x00000020 +#define ESDHC_PROCTL_DTW_1BIT 0x00000000 +#define ESDHC_PROCTL_DTW_4BIT 0x00000002 +#define ESDHC_PROCTL_DTW_8BIT 0x00000004 + +/* Watermark Level Register (WML) */ +#define ESDHC_WML_RD_WML(w) ((w) & 0x7F) +#define ESDHC_WML_WR_WML(w) (((w) & 0x7F) << 16) +#define ESDHC_WML_RD_BRST(w) (((w) & 0xF) << 8) +#define ESDHC_WML_WR_BRST(w) (((w) & 0xF) << 24) +#define ESDHC_WML_WR_BRST_MASK (0x0F000000) +#define ESDHC_WML_RD_BRST_MASK (0x00000F00) +#define ESDHC_WML_RD_WML_MASK (0x0000007F) +#define ESDHC_WML_WR_WML_MASK (0x007F0000) +#define WML_512_BYTES (0x0) +#define BURST_128_BYTES (0x0) + +/* eSDHC control register define */ +#define ESDHC_DCR_SNOOP 0x00000040 + +/* ESDHC Block attributes register */ +#define ESDHC_BLKATTR_BLKCNT(c) (((c) & 0xffff) << 16) +#define ESDHC_BLKATTR_BLKSZE(s) ((s) & 0xfff) + +/* Transfer Type Register */ +#define ESDHC_XFERTYP_CMD(c) (((c) & 0x3F) << 24) +#define ESDHC_XFERTYP_CMDTYP_NORMAL (0x0) +#define ESDHC_XFERTYP_CMDTYP_SUSPEND (0x00400000) +#define ESDHC_XFERTYP_CMDTYP_RESUME (0x00800000) +#define ESDHC_XFERTYP_CMDTYP_ABORT (0x00C00000) +#define ESDHC_XFERTYP_DPSEL (0x00200000) +#define ESDHC_XFERTYP_CICEN (0x00100000) +#define ESDHC_XFERTYP_CCCEN (0x00080000) +#define ESDHC_XFERTYP_RSPTYP_NONE (0x0) +#define ESDHC_XFERTYP_RSPTYP_136 (0x00010000) +#define ESDHC_XFERTYP_RSPTYP_48 (0x00020000) +#define ESDHC_XFERTYP_RSPTYP_48_BUSY (0x00030000) +#define ESDHC_XFERTYP_MSBSEL (0x00000020) +#define ESDHC_XFERTYP_DTDSEL (0x00000010) +#define ESDHC_XFERTYP_AC12EN (0x00000004) +#define ESDHC_XFERTYP_BCEN (0x00000002) +#define ESDHC_XFERTYP_DMAEN (0x00000001) + +#define MMC_VDD_HIGH_VOLTAGE 0x00000100 + +/* command index */ +#define CMD0 0 +#define CMD1 1 +#define CMD2 2 +#define CMD3 3 +#define CMD5 5 +#define CMD6 6 +#define CMD7 7 +#define CMD8 8 +#define CMD9 9 +#define CMD12 12 +#define CMD13 13 +#define CMD14 14 +#define CMD16 16 +#define CMD17 17 +#define CMD18 18 +#define CMD19 19 +#define CMD24 24 +#define CMD41 41 +#define CMD42 42 +#define CMD51 51 +#define CMD55 55 +#define CMD56 56 +#define ACMD6 CMD6 +#define ACMD13 CMD13 +#define ACMD41 CMD41 +#define ACMD42 CMD42 +#define ACMD51 CMD51 + +/* commands abbreviations */ +#define CMD_GO_IDLE_STATE CMD0 +#define CMD_MMC_SEND_OP_COND CMD1 +#define CMD_ALL_SEND_CID CMD2 +#define CMD_SEND_RELATIVE_ADDR CMD3 +#define CMD_SET_DSR CMD4 +#define CMD_SWITCH_FUNC CMD6 +#define CMD_SELECT_CARD CMD7 +#define CMD_DESELECT_CARD CMD7 +#define CMD_SEND_IF_COND CMD8 +#define CMD_MMC_SEND_EXT_CSD CMD8 +#define CMD_SEND_CSD CMD9 +#define CMD_SEND_CID CMD10 +#define CMD_STOP_TRANSMISSION CMD12 +#define CMD_SEND_STATUS CMD13 +#define CMD_BUS_TEST_R CMD14 +#define CMD_GO_INACTIVE_STATE CMD15 +#define CMD_SET_BLOCKLEN CMD16 +#define CMD_READ_SINGLE_BLOCK CMD17 +#define CMD_READ_MULTIPLE_BLOCK CMD18 +#define CMD_WRITE_SINGLE_BLOCK CMD24 +#define CMD_BUS_TEST_W CMD19 +#define CMD_APP_CMD CMD55 +#define CMD_GEN_CMD CMD56 +#define CMD_SET_BUS_WIDTH ACMD6 +#define CMD_SD_STATUS ACMD13 +#define CMD_SD_SEND_OP_COND ACMD41 +#define CMD_SET_CLR_CARD_DETECT ACMD42 +#define CMD_SEND_SCR ACMD51 + +/* MMC card spec version */ +#define MMC_CARD_VERSION_1_2 0 +#define MMC_CARD_VERSION_1_4 1 +#define MMC_CARD_VERSION_2_X 2 +#define MMC_CARD_VERSION_3_X 3 +#define MMC_CARD_VERSION_4_X 4 + +/* SD Card Spec Version */ +/* May need to add version 3 here? */ +#define SD_CARD_VERSION_1_0 0 +#define SD_CARD_VERSION_1_10 1 +#define SD_CARD_VERSION_2_0 2 + +/* card types */ +#define MMC_CARD 0 +#define SD_CARD 1 +#define NOT_SD_CARD MMC_CARD + +/* Card rca */ +#define SD_MMC_CARD_RCA 0x1 +#define BLOCK_LEN_512 512 + +/* card state */ +#define STATE_IDLE 0 +#define STATE_READY 1 +#define STATE_IDENT 2 +#define STATE_STBY 3 +#define STATE_TRAN 4 +#define STATE_DATA 5 +#define STATE_RCV 6 +#define STATE_PRG 7 +#define STATE_DIS 8 + +/* Card OCR register */ +/* VDD voltage window 1,65 to 1.95 */ +#define MMC_OCR_VDD_165_195 0x00000080 +/* VDD voltage window 2.7-2.8 */ +#define MMC_OCR_VDD_FF8 0x00FF8000 +#define MMC_OCR_CCS 0x40000000/* Card Capacity */ +#define MMC_OCR_BUSY 0x80000000/* busy bit */ +#define SD_OCR_HCS 0x40000000/* High capacity host */ +#define MMC_OCR_SECTOR_MODE 0x40000000/* Access Mode as Sector */ + +/* mmc Switch function */ +#define SET_EXT_CSD_HS_TIMING 0x03B90100/* set High speed */ + +/* check supports switching or not */ +#define SD_SWITCH_FUNC_CHECK_MODE 0x00FFFFF1 +#define SD_SWITCH_FUNC_SWITCH_MODE 0x80FFFFF1/* switch */ +#define SD_SWITCH_FUNC_HIGH_SPEED 0x02/* HIGH SPEED FUNC */ +#define SWITCH_ERROR 0x00000080 + +/* errors in sending commands */ +#define RESP_TIMEOUT 0x1 +#define COMMAND_ERROR 0x2 +/* error in response */ +#define R1_ERROR (1 << 19) +#define R1_CURRENT_STATE(x) (((x) & 0x00001E00) >> 9) + +/* Host Controller Capabilities */ +#define ESDHC_HOSTCAPBLT_DMAS (0x00400000) + + +/* SD/MMC memory map */ +struct esdhc_regs { + uint32_t dsaddr; /* dma system address */ + uint32_t blkattr; /* Block attributes */ + uint32_t cmdarg; /* Command argument */ + uint32_t xfertyp; /* Command transfer type */ + uint32_t cmdrsp[4]; /* Command response0,1,2,3 */ + uint32_t datport; /* Data buffer access port */ + uint32_t prsstat; /* Present state */ + uint32_t proctl; /* Protocol control */ + uint32_t sysctl; /* System control */ + uint32_t irqstat; /* Interrupt status */ + uint32_t irqstaten; /* Interrupt status enable */ + uint32_t irqsigen; /* Interrupt signal enable */ + uint32_t autoc12err; /* Auto CMD12 status */ + uint32_t hostcapblt; /* Host controller capabilities */ + uint32_t wml; /* Watermark level */ + uint32_t res1[2]; + uint32_t fevt; /* Force event */ + uint32_t res2; + uint32_t adsaddrl; + uint32_t adsaddrh; + uint32_t res3[39]; + uint32_t hostver; /* Host controller version */ + uint32_t res4; + uint32_t dmaerr; /* DMA error address */ + uint32_t dmaerrh; /* DMA error address high */ + uint32_t dmaerrattr; /* DMA error atrribute */ + uint32_t res5; + uint32_t hostcapblt2;/* Host controller capabilities2 */ + uint32_t res6[2]; + uint32_t tcr; /* Tuning control */ + uint32_t res7[7]; + uint32_t dirctrl; /* Direction control */ + uint32_t ccr; /* Clock control */ + uint32_t res8[177]; + uint32_t ctl; /* Control register */ +}; + +/* SD/MMC card attributes */ +struct card_attributes { + uint32_t type; /* sd or mmc card */ + uint32_t version; /* version */ + uint32_t block_len; /* block length */ + uint32_t bus_freq; /* sdhc bus frequency */ + uint16_t rca; /* relative card address */ + uint8_t is_high_capacity; /* high capacity */ +}; + +struct mmc { + struct esdhc_regs *esdhc_regs; + struct card_attributes card; + + uint32_t block_len; + uint32_t voltages_caps; /* supported voltaes */ + uint32_t dma_support; /* DMA support */ +}; + +enum cntrl_num { + SDHC1 = 0, + SDHC2 +}; + +int sd_emmc_init(uintptr_t *block_dev_spec, + uintptr_t nxp_esdhc_addr, + size_t nxp_sd_block_offset, + size_t nxp_sd_block_size, + bool card_detect); + +int esdhc_emmc_init(struct mmc *mmc, bool card_detect); +int esdhc_read(struct mmc *mmc, uint32_t src_offset, uintptr_t dst, + size_t size); +int esdhc_write(struct mmc *mmc, uintptr_t src, uint32_t dst_offset, + size_t size); + +#ifdef NXP_ESDHC_BE +#define esdhc_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define esdhc_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_ESDHC_LE) +#define esdhc_in32(a) mmio_read_32((uintptr_t)(a)) +#define esdhc_out32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define CCSR ESDHC register endianness +#endif + +#endif /*SD_MMC_H*/ diff --git a/arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h b/arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h new file mode 100644 index 0000000..4455383 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h @@ -0,0 +1,86 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SNVS_H +#define SNVS_H + + +#ifndef __ASSEMBLER__ + +#include +#include + +#include + +struct snvs_regs { + uint32_t reserved1; + uint32_t hp_com; /* 0x04 SNVS_HP Command Register */ + uint32_t reserved2[3]; + uint32_t hp_stat; /* 0x14 SNVS_HP Status Register */ +}; + +#ifdef NXP_SNVS_BE +#define snvs_read32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define snvs_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32((v))) +#elif defined(NXP_SNVS_LE) +#define snvs_read32(a) mmio_read_32((uintptr_t)(a)) +#define snvs_write32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define CCSR SNVS register endianness +#endif + +void snvs_init(uintptr_t nxp_snvs_addr); +uint32_t get_snvs_state(void); +void transition_snvs_non_secure(void); +void transition_snvs_soft_fail(void); +uint32_t transition_snvs_trusted(void); +uint32_t transition_snvs_secure(void); + +uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos); +void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val); + +void snvs_disable_zeroize_lp_gpr(void); + +#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB) +uint32_t snvs_read_app_data(void); +uint32_t snvs_read_app_data_bit(uint32_t bit_pos); +void snvs_clear_app_data(void); +void snvs_write_app_data_bit(uint32_t bit_pos); +#endif + +#endif /* __ASSEMBLER__ */ + +/* SSM_ST field in SNVS status reg */ +#define HPSTS_CHECK_SSM_ST 0x900 /* SNVS is in check state */ +#define HPSTS_NON_SECURE_SSM_ST 0xb00 /* SNVS is in non secure state */ +#define HPSTS_TRUST_SSM_ST 0xd00 /* SNVS is in trusted state */ +#define HPSTS_SECURE_SSM_ST 0xf00 /* SNVS is in secure state */ +#define HPSTS_SOFT_FAIL_SSM_ST 0x300 /* SNVS is in soft fail state */ +#define HPSTS_MASK_SSM_ST 0xf00 /* SSM_ST field mask in SNVS reg */ + +/* SNVS register bits */ +#define HPCOM_SW_SV 0x100 /* Security Violation bit */ +#define HPCOM_SW_FSV 0x200 /* Fatal Security Violation bit */ +#define HPCOM_SSM_ST 0x1 /* SSM_ST field in SNVS command reg */ +#define HPCOM_SSM_ST_DIS 0x2 /* Disable Secure to Trusted State */ +#define HPCOM_SSM_SFNS_DIS 0x4 /* Disable Soft Fail to Non-Secure */ + +#define NXP_LP_GPR0_OFFSET 0x90 +#define NXP_LPCR_OFFSET 0x38 +#define NXP_GPR_Z_DIS_BIT 24 + +#ifdef NXP_COINED_BB + +#ifndef NXP_APP_DATA_LP_GPR_OFFSET +#define NXP_APP_DATA_LP_GPR_OFFSET NXP_LP_GPR0_OFFSET +#endif + +#define NXP_LPGPR_ZEROTH_BIT 0 + +#endif /* NXP_COINED_BB */ + +#endif /* SNVS_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h b/arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h new file mode 100644 index 0000000..e015318 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h @@ -0,0 +1,83 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#if !defined(FUSE_PROV_H) && defined(POLICY_FUSE_PROVISION) +#define FUSE_PROV_H + +#include +#include + +#define MASK_NONE U(0xFFFFFFFF) +#define ERROR_WRITE U(0xA) +#define ERROR_ALREADY_BLOWN U(0xB) + +/* Flag bit shifts */ +#define FLAG_POVDD_SHIFT U(0) +#define FLAG_SYSCFG_SHIFT U(1) +#define FLAG_SRKH_SHIFT U(2) +#define FLAG_MC_SHIFT U(3) +#define FLAG_DCV0_SHIFT U(4) +#define FLAG_DCV1_SHIFT U(5) +#define FLAG_DRV0_SHIFT U(6) +#define FLAG_DRV1_SHIFT U(7) +#define FLAG_OUID0_SHIFT U(8) +#define FLAG_OUID1_SHIFT U(9) +#define FLAG_OUID2_SHIFT U(10) +#define FLAG_OUID3_SHIFT U(11) +#define FLAG_OUID4_SHIFT U(12) +#define FLAG_DBG_LVL_SHIFT U(13) +#define FLAG_OTPMK_SHIFT U(16) +#define FLAG_OUID_MASK U(0x1F) +#define FLAG_DEBUG_MASK U(0xF) +#define FLAG_OTPMK_MASK U(0xF) + +/* OTPMK flag values */ +#define PROG_OTPMK_MIN U(0x0) +#define PROG_OTPMK_RANDOM U(0x1) +#define PROG_OTPMK_USER U(0x2) +#define PROG_OTPMK_RANDOM_MIN U(0x5) +#define PROG_OTPMK_USER_MIN U(0x6) +#define PROG_NO_OTPMK U(0x8) + +#define OTPMK_MIM_BITS_MASK U(0xF0000000) + +/* System configuration bit shifts */ +#define SCB_WP_SHIFT U(0) +#define SCB_ITS_SHIFT U(2) +#define SCB_NSEC_SHIFT U(4) +#define SCB_ZD_SHIFT U(5) +#define SCB_K0_SHIFT U(15) +#define SCB_K1_SHIFT U(14) +#define SCB_K2_SHIFT U(13) +#define SCB_K3_SHIFT U(12) +#define SCB_K4_SHIFT U(11) +#define SCB_K5_SHIFT U(10) +#define SCB_K6_SHIFT U(9) +#define SCB_FR0_SHIFT U(30) +#define SCB_FR1_SHIFT U(31) + +/* Fuse Header Structure */ +struct fuse_hdr_t { + uint8_t barker[4]; /* 0x00 Barker code */ + uint32_t flags; /* 0x04 Script flags */ + uint32_t povdd_gpio; /* 0x08 GPIO for POVDD */ + uint32_t otpmk[8]; /* 0x0C-0x2B OTPMK */ + uint32_t srkh[8]; /* 0x2C-0x4B SRKH */ + uint32_t oem_uid[5]; /* 0x4C-0x5F OEM unique id's */ + uint32_t dcv[2]; /* 0x60-0x67 Debug Challenge */ + uint32_t drv[2]; /* 0x68-0x6F Debug Response */ + uint32_t ospr1; /* 0x70 OSPR1 */ + uint32_t sc; /* 0x74 OSPR0 (System Configuration) */ + uint32_t reserved[2]; /* 0x78-0x7F Reserved */ +}; + +/* Function to do fuse provisioning */ +int provision_fuses(unsigned long long fuse_scr_addr, + bool en_povdd_status); + +#define EFUSE_POWERUP_DELAY_mSec U(25) +#endif /* FUSE_PROV_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h b/arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h new file mode 100644 index 0000000..2cb4c7d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h @@ -0,0 +1,100 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SFP_H +#define SFP_H + +#include +#include + +/* SFP Configuration Register Offsets */ +#define SFP_INGR_OFFSET U(0x20) +#define SFP_SVHESR_OFFSET U(0x24) +#define SFP_SFPCR_OFFSET U(0x28) +#define SFP_VER_OFFSET U(0x38) + +/* SFP Hamming register masks for OTPMK and DRV */ +#define SFP_SVHESR_DRV_MASK U(0x7F) +#define SFP_SVHESR_OTPMK_MASK U(0x7FC00) + +/* SFP commands */ +#define SFP_INGR_READFB_CMD U(0x1) +#define SFP_INGR_PROGFB_CMD U(0x2) +#define SFP_INGR_ERROR_MASK U(0x100) + +/* SFPCR Masks */ +#define SFP_SFPCR_WD U(0x80000000) +#define SFP_SFPCR_WDL U(0x40000000) + +/* SFPCR Masks */ +#define SFP_SFPCR_WD U(0x80000000) +#define SFP_SFPCR_WDL U(0x40000000) + +#define SFP_FUSE_REGS_OFFSET U(0x200) + +#ifdef NXP_SFP_VER_3_4 +#define OSPR0_SC_MASK U(0xC000FE35) +#elif defined(NXP_SFP_VER_3_2) +#define OSPR0_SC_MASK U(0x0000E035) +#endif + +#if defined(NXP_SFP_VER_3_4) +#define OSPR_KEY_REVOC_SHIFT U(9) +#define OSPR_KEY_REVOC_MASK U(0x0000fe00) +#elif defined(NXP_SFP_VER_3_2) +#define OSPR_KEY_REVOC_SHIFT U(13) +#define OSPR_KEY_REVOC_MASK U(0x0000e000) +#endif /* NXP_SFP_VER_3_4 */ + +#define OSPR1_MC_MASK U(0xFFFF0000) +#define OSPR1_DBG_LVL_MASK U(0x00000007) + +#define OSPR_ITS_MASK U(0x00000004) +#define OSPR_WP_MASK U(0x00000001) + +#define MAX_OEM_UID U(5) +#define SRK_HASH_SIZE U(32) + +/* SFP CCSR Register Map */ +struct sfp_ccsr_regs_t { + uint32_t ospr; /* 0x200 OSPR0 */ + uint32_t ospr1; /* 0x204 OSPR1 */ + uint32_t dcv[2]; /* 0x208 Debug Challenge Value */ + uint32_t drv[2]; /* 0x210 Debug Response Value */ + uint32_t fswpr; /* 0x218 FSL Section Write Protect */ + uint32_t fsl_uid[2]; /* 0x21c FSL UID 0 */ + uint32_t isbcr; /* 0x224 ISBC Configuration */ + uint32_t fsspr[3]; /* 0x228 FSL Scratch Pad */ + uint32_t otpmk[8]; /* 0x234 OTPMK */ + uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)]; + /* 0x254 Super Root Key Hash */ + uint32_t oem_uid[MAX_OEM_UID]; /* 0x274 OEM UID 0 */ +}; + +uintptr_t get_sfp_addr(void); +void sfp_init(uintptr_t nxp_sfp_addr); +uint32_t *get_sfp_srk_hash(void); +int sfp_check_its(void); +int sfp_check_oem_wp(void); +uint32_t get_key_revoc(void); +void set_sfp_wr_disable(void); +int sfp_program_fuses(void); + +uint32_t sfp_read_oem_uid(uint8_t oem_uid); +uint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val); + +#ifdef NXP_SFP_BE +#define sfp_read32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define sfp_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_SFP_LE) +#define sfp_read32(a) mmio_read_32((uintptr_t)(a)) +#define sfp_write32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define CCSR SFP register endianness +#endif + +#endif/* SFP_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h b/arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h new file mode 100644 index 0000000..7be7a27 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h @@ -0,0 +1,40 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SFP_ERROR_CODES_H +#define SFP_ERROR_CODES_H + + /* Error codes */ +#define ERROR_FUSE_BARKER 0x1 +#define ERROR_READFB_CMD 0x2 +#define ERROR_PROGFB_CMD 0x3 +#define ERROR_SRKH_ALREADY_BLOWN 0x4 +#define ERROR_SRKH_WRITE 0x5 +#define ERROR_OEMUID_ALREADY_BLOWN 0x6 +#define ERROR_OEMUID_WRITE 0x7 +#define ERROR_DCV_ALREADY_BLOWN 0x8 +#define ERROR_DCV_WRITE 0x9 +#define ERROR_DRV_ALREADY_BLOWN 0xa +#define ERROR_DRV_HAMMING_ERROR 0xb +#define ERROR_DRV_WRITE 0x18 +#define ERROR_OTPMK_ALREADY_BLOWN 0xc +#define ERROR_OTPMK_HAMMING_ERROR 0xd +#define ERROR_OTPMK_USER_MIN 0xe +#define ERROR_OSPR1_ALREADY_BLOWN 0xf +#define ERROR_OSPR1_WRITE 0x10 +#define ERROR_SC_ALREADY_BLOWN 0x11 +#define ERROR_SC_WRITE 0x12 +#define ERROR_POVDD_GPIO_FAIL 0x13 +#define ERROR_GPIO_SET_FAIL 0x14 +#define ERROR_GPIO_RESET_FAIL 0x15 +#define ERROR_OTPMK_SEC_DISABLED 0x16 +#define ERROR_OTPMK_SEC_ERROR 0x17 +#define ERROR_OTPMK_WRITE 0x19 +#define PLAT_ERROR_ENABLE_POVDD 0x20 +#define PLAT_ERROR_DISABLE_POVDD 0x21 + +#endif /* SFP_ERROR_CODES_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h b/arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h new file mode 100644 index 0000000..d64c33b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef NXP_SMMU_H +#define NXP_SMMU_H + +#define SMMU_SCR0 (0x0) +#define SMMU_NSCR0 (0x400) + +#define SCR0_CLIENTPD_MASK 0x00000001 +#define SCR0_USFCFG_MASK 0x00000400 + +static inline void bypass_smmu(uintptr_t smmu_base_addr) +{ + uint32_t val; + + val = (mmio_read_32(smmu_base_addr + SMMU_SCR0) | SCR0_CLIENTPD_MASK) & + ~(SCR0_USFCFG_MASK); + mmio_write_32((smmu_base_addr + SMMU_SCR0), val); + + val = (mmio_read_32(smmu_base_addr + SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & + ~(SCR0_USFCFG_MASK); + mmio_write_32((smmu_base_addr + SMMU_NSCR0), val); +} + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h b/arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h new file mode 100644 index 0000000..280e5b2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h @@ -0,0 +1,35 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +# +#ifndef NXP_TIMER_H +#define NXP_TIMER_H + + /* System Counter Offset and Bit Mask */ +#define SYS_COUNTER_CNTCR_OFFSET 0x0 +#define SYS_COUNTER_CNTCR_EN 0x00000001 +#define CNTCR_EN_MASK 0x1 + +#ifndef __ASSEMBLER__ +uint64_t get_timer_val(uint64_t start); + +#ifdef IMAGE_BL31 +void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base, + uint8_t ls_config_cntacr, + uint8_t plat_ls_ns_timer_frame_id); +void enable_init_timer(void); +#endif + +/* + * Initialise the nxp on-chip free rolling usec counter as the delay + * timer. + */ +void delay_timer_init(uintptr_t nxp_timer_addr); +void ls_bl31_timer_init(uintptr_t nxp_timer_addr); +#endif /* __ASSEMBLER__ */ + +#endif /* NXP_TIMER_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h b/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h new file mode 100644 index 0000000..08d2148 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h @@ -0,0 +1,47 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if !defined(PLAT_TZC380_H) && defined(IMAGE_BL2) +#define PLAT_TZC380_H + +#include + +/* Number of DRAM regions to be configured + * for the platform can be over-written. + * + * Array tzc400_reg_list too, needs be over-written + * if there is any changes to default DRAM region + * configuration. + */ +#ifndef MAX_NUM_TZC_REGION +/* 3 regions: + * Region 0(default), + * Region 1 (DRAM0, Secure Memory), + * Region 2 (DRAM0, Shared memory) + */ +#define MAX_NUM_TZC_REGION 3 +#define DEFAULT_TZASC_CONFIG 1 +#endif + +struct tzc380_reg { + unsigned int secure; + unsigned int enabled; + uint64_t addr; + uint64_t size; + unsigned int sub_mask; +}; + +void mem_access_setup(uintptr_t base, uint32_t total_regions, + struct tzc380_reg *tzc380_reg_list); + +int populate_tzc380_reg_list(struct tzc380_reg *tzc380_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz); + +#endif /* PLAT_TZC380_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h b/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h new file mode 100644 index 0000000..1b8e3a4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h @@ -0,0 +1,55 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#if !defined(PLAT_TZC400_H) && defined(IMAGE_BL2) +#define PLAT_TZC400_H + +#include + +/* Structure to configure TZC Regions' boundaries and attributes. */ +struct tzc400_reg { + uint8_t reg_filter_en; + unsigned long long start_addr; + unsigned long long end_addr; + unsigned int sec_attr; + unsigned int nsaid_permissions; +}; + +#define TZC_REGION_NS_NONE 0x00000000U + +/* NXP Platforms do not support NS Access ID (NSAID) based non-secure access. + * Supports only non secure through generic NS ACCESS ID + */ +#define TZC_NS_ACCESS_ID 0xFFFFFFFFU + +/* Number of DRAM regions to be configured + * for the platform can be over-written. + * + * Array tzc400_reg_list too, needs be over-written + * if there is any changes to default DRAM region + * configuration. + */ +#ifndef MAX_NUM_TZC_REGION +/* 3 regions: + * Region 0(default), + * Region 1 (DRAM0, Secure Memory), + * Region 2 (DRAM0, Shared memory) + */ +#define MAX_NUM_TZC_REGION NUM_DRAM_REGIONS + 3 +#define DEFAULT_TZASC_CONFIG 1 +#endif + +void mem_access_setup(uintptr_t base, uint32_t total_regions, + struct tzc400_reg *tzc400_reg_list); +int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz); + +#endif /* PLAT_TZC400_H */ diff --git a/arm-trusted-firmware/include/drivers/partition/efi.h b/arm-trusted-firmware/include/drivers/partition/efi.h new file mode 100644 index 0000000..e463f96 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/partition/efi.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Linaro Limited + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DRIVERS_PARTITION_EFI_H +#define DRIVERS_PARTITION_EFI_H + +#include + +#include + +#define EFI_NAMELEN 36 + +static inline int guidcmp(const void *g1, const void *g2) +{ + return memcmp(g1, g2, sizeof(struct efi_guid)); +} + +static inline void *guidcpy(void *dst, const void *src) +{ + return memcpy(dst, src, sizeof(struct efi_guid)); +} + +#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ + { (a) & 0xffffffff, \ + (b) & 0xffff, \ + (c) & 0xffff, \ + { (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) } } + +#define NULL_GUID \ + EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + +#endif /* DRIVERS_PARTITION_EFI_H */ diff --git a/arm-trusted-firmware/include/drivers/partition/gpt.h b/arm-trusted-firmware/include/drivers/partition/gpt.h new file mode 100644 index 0000000..c2a229e --- /dev/null +++ b/arm-trusted-firmware/include/drivers/partition/gpt.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPT_H +#define GPT_H + +#include +#include +#include + +#define PARTITION_TYPE_GPT 0xee +#define GPT_HEADER_OFFSET PLAT_PARTITION_BLOCK_SIZE +#define GPT_ENTRY_OFFSET (GPT_HEADER_OFFSET + \ + PLAT_PARTITION_BLOCK_SIZE) + +#define GPT_SIGNATURE "EFI PART" + +typedef struct gpt_entry { + struct efi_guid type_uuid; + struct efi_guid unique_uuid; + unsigned long long first_lba; + unsigned long long last_lba; + unsigned long long attr; + unsigned short name[EFI_NAMELEN]; +} gpt_entry_t; + +typedef struct gpt_header { + unsigned char signature[8]; + unsigned int revision; + unsigned int size; + unsigned int header_crc; + unsigned int reserved; + unsigned long long current_lba; + unsigned long long backup_lba; + unsigned long long first_lba; + unsigned long long last_lba; + struct efi_guid disk_uuid; + /* starting LBA of array of partition entries */ + unsigned long long part_lba; + /* number of partition entries in array */ + unsigned int list_num; + /* size of a single partition entry (usually 128) */ + unsigned int part_size; + unsigned int part_crc; +} gpt_header_t; + +int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry); + +#endif /* GPT_H */ diff --git a/arm-trusted-firmware/include/drivers/partition/mbr.h b/arm-trusted-firmware/include/drivers/partition/mbr.h new file mode 100644 index 0000000..1452c02 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/partition/mbr.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MBR_H +#define MBR_H + +#define MBR_OFFSET 0 + +#define MBR_PRIMARY_ENTRY_OFFSET 0x1be +#define MBR_PRIMARY_ENTRY_SIZE 0x10 +#define MBR_PRIMARY_ENTRY_NUMBER 4 +#define MBR_CHS_ADDRESS_LEN 3 + +#define MBR_SIGNATURE_FIRST 0x55 +#define MBR_SIGNATURE_SECOND 0xAA + +typedef struct mbr_entry { + unsigned char status; + unsigned char first_sector[MBR_CHS_ADDRESS_LEN]; + unsigned char type; + unsigned char last_sector[MBR_CHS_ADDRESS_LEN]; + unsigned int first_lba; + unsigned int sector_nums; +} mbr_entry_t; + +#endif /* MBR_H */ diff --git a/arm-trusted-firmware/include/drivers/partition/partition.h b/arm-trusted-firmware/include/drivers/partition/partition.h new file mode 100644 index 0000000..b292ec7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/partition/partition.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PARTITION_H +#define PARTITION_H + +#include + +#include +#include +#include + +#if !PLAT_PARTITION_MAX_ENTRIES +# define PLAT_PARTITION_MAX_ENTRIES 128 +#endif /* PLAT_PARTITION_MAX_ENTRIES */ + +CASSERT(PLAT_PARTITION_MAX_ENTRIES <= 128, assert_plat_partition_max_entries); + +#if !PLAT_PARTITION_BLOCK_SIZE +# define PLAT_PARTITION_BLOCK_SIZE 512 +#endif /* PLAT_PARTITION_BLOCK_SIZE */ + +CASSERT((PLAT_PARTITION_BLOCK_SIZE == 512) || + (PLAT_PARTITION_BLOCK_SIZE == 4096), + assert_plat_partition_block_size); + +#define LEGACY_PARTITION_BLOCK_SIZE 512 + +typedef struct partition_entry { + uint64_t start; + uint64_t length; + char name[EFI_NAMELEN]; + struct efi_guid part_guid; +} partition_entry_t; + +typedef struct partition_entry_list { + partition_entry_t list[PLAT_PARTITION_MAX_ENTRIES]; + int entry_count; +} partition_entry_list_t; + +int load_partition_table(unsigned int image_id); +const partition_entry_t *get_partition_entry(const char *name); +const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid); +const partition_entry_list_t *get_partition_entry_list(void); +void partition_init(unsigned int image_id); + +#endif /* PARTITION_H */ diff --git a/arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h b/arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h new file mode 100644 index 0000000..6de8fc7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef __TRNG_IP_76_H__ +#define __TRNG_IP_76_H__ + +#include +#include + +int32_t eip76_rng_read_rand_buf(void *data, bool wait); +int32_t eip76_rng_probe(uintptr_t base_addr); +int32_t eip76_rng_get_random(uint8_t *data, uint32_t len); + +#endif /* __TRNG_IP_76_H__ */ diff --git a/arm-trusted-firmware/include/drivers/raw_nand.h b/arm-trusted-firmware/include/drivers/raw_nand.h new file mode 100644 index 0000000..7152300 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/raw_nand.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_RAW_NAND_H +#define DRIVERS_RAW_NAND_H + +#include +#include + +#include + +/* NAND ONFI default value mode 0 in picosecond */ +#define NAND_TADL_MIN 400000UL +#define NAND_TALH_MIN 20000UL +#define NAND_TALS_MIN 50000UL +#define NAND_TAR_MIN 25000UL +#define NAND_TCCS_MIN 500000UL +#define NAND_TCEA_MIN 100000UL +#define NAND_TCEH_MIN 20000UL +#define NAND_TCH_MIN 20000UL +#define NAND_TCHZ_MAX 100000UL +#define NAND_TCLH_MIN 20000UL +#define NAND_TCLR_MIN 20000UL +#define NAND_TCLS_MIN 50000UL +#define NAND_TCOH_MIN 0UL +#define NAND_TCS_MIN 70000UL +#define NAND_TDH_MIN 20000UL +#define NAND_TDS_MIN 40000UL +#define NAND_TFEAT_MAX 1000000UL +#define NAND_TIR_MIN 10000UL +#define NAND_TITC_MIN 1000000UL +#define NAND_TR_MAX 200000000UL +#define NAND_TRC_MIN 100000UL +#define NAND_TREA_MAX 40000UL +#define NAND_TREH_MIN 30000UL +#define NAND_TRHOH_MIN 0UL +#define NAND_TRHW_MIN 200000UL +#define NAND_TRHZ_MAX 200000UL +#define NAND_TRLOH_MIN 0UL +#define NAND_TRP_MIN 50000UL +#define NAND_TRR_MIN 40000UL +#define NAND_TRST_MAX 250000000000ULL +#define NAND_TWB_MAX 200000UL +#define NAND_TWC_MIN 100000UL +#define NAND_TWH_MIN 30000UL +#define NAND_TWHR_MIN 120000UL +#define NAND_TWP_MIN 50000UL +#define NAND_TWW_MIN 100000UL + +/* NAND request types */ +#define NAND_REQ_CMD 0x0000U +#define NAND_REQ_ADDR 0x1000U +#define NAND_REQ_DATAIN 0x2000U +#define NAND_REQ_DATAOUT 0x3000U +#define NAND_REQ_WAIT 0x4000U +#define NAND_REQ_MASK GENMASK(14, 12) +#define NAND_REQ_BUS_WIDTH_8 BIT(15) + +#define PARAM_PAGE_SIZE 256 + +/* NAND ONFI commands */ +#define NAND_CMD_READ_1ST 0x00U +#define NAND_CMD_CHANGE_1ST 0x05U +#define NAND_CMD_READID_SIG_ADDR 0x20U +#define NAND_CMD_READ_2ND 0x30U +#define NAND_CMD_STATUS 0x70U +#define NAND_CMD_READID 0x90U +#define NAND_CMD_CHANGE_2ND 0xE0U +#define NAND_CMD_READ_PARAM_PAGE 0xECU +#define NAND_CMD_RESET 0xFFU + +#define ONFI_REV_21 BIT(3) +#define ONFI_FEAT_BUS_WIDTH_16 BIT(0) +#define ONFI_FEAT_EXTENDED_PARAM BIT(7) + +/* NAND ECC type */ +#define NAND_ECC_NONE U(0) +#define NAND_ECC_HW U(1) +#define NAND_ECC_ONDIE U(2) + +/* NAND bus width */ +#define NAND_BUS_WIDTH_8 U(0) +#define NAND_BUS_WIDTH_16 U(1) + +struct nand_req { + struct nand_device *nand; + uint16_t type; + uint8_t *addr; + unsigned int length; + unsigned int delay_ms; + unsigned int inst_delay; +}; + +struct nand_param_page { + /* Rev information and feature block */ + uint32_t page_sig; + uint16_t rev; + uint16_t features; + uint16_t opt_cmd; + uint8_t jtg; + uint8_t train_cmd; + uint16_t ext_param_length; + uint8_t nb_param_pages; + uint8_t reserved1[17]; + /* Manufacturer information */ + uint8_t manufacturer[12]; + uint8_t model[20]; + uint8_t manufacturer_id; + uint16_t data_code; + uint8_t reserved2[13]; + /* Memory organization */ + uint32_t bytes_per_page; + uint16_t spare_per_page; + uint32_t bytes_per_partial; + uint16_t spare_per_partial; + uint32_t num_pages_per_blk; + uint32_t num_blk_in_lun; + uint8_t num_lun; + uint8_t num_addr_cycles; + uint8_t bit_per_cell; + uint16_t max_bb_per_lun; + uint16_t blk_endur; + uint8_t valid_blk_begin; + uint16_t blk_enbur_valid; + uint8_t nb_prog_page; + uint8_t partial_prog_attr; + uint8_t nb_ecc_bits; + uint8_t plane_addr; + uint8_t mplanes_ops; + uint8_t ez_nand; + uint8_t reserved3[12]; + /* Electrical parameters */ + uint8_t io_pin_cap_max; + uint16_t sdr_timing_mode; + uint16_t sdr_prog_cache_timing; + uint16_t tprog; + uint16_t tbers; + uint16_t tr; + uint16_t tccs; + uint8_t nvddr_timing_mode; + uint8_t nvddr2_timing_mode; + uint8_t nvddr_features; + uint16_t clk_input_cap_typ; + uint16_t io_pin_cap_typ; + uint16_t input_pin_cap_typ; + uint8_t input_pin_cap_max; + uint8_t drv_strength_support; + uint16_t tr_max; + uint16_t tadl; + uint16_t tr_typ; + uint8_t reserved4[6]; + /* Vendor block */ + uint16_t vendor_revision; + uint8_t vendor[88]; + uint16_t crc16; +} __packed; + +struct nand_ctrl_ops { + int (*exec)(struct nand_req *req); + void (*setup)(struct nand_device *nand); +}; + +struct rawnand_device { + struct nand_device *nand_dev; + const struct nand_ctrl_ops *ops; +}; + +int nand_raw_init(unsigned long long *size, unsigned int *erase_size); +int nand_wait_ready(unsigned int delay_ms); +int nand_read_page_cmd(unsigned int page, unsigned int offset, + uintptr_t buffer, unsigned int len); +int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer, + unsigned int len); +void nand_raw_ctrl_init(const struct nand_ctrl_ops *ops); + +/* + * Platform can implement this to override default raw NAND instance + * configuration. + * + * @device: target raw NAND instance. + * Return 0 on success, negative value otherwise. + */ +int plat_get_raw_nand_data(struct rawnand_device *device); + +#endif /* DRIVERS_RAW_NAND_H */ diff --git a/arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h b/arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h new file mode 100644 index 0000000..7d5b5d3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h b/arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h new file mode 100644 index 0000000..7bb3ee2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI3_GPIO_H +#define RPI3_GPIO_H + +#include +#include + +void rpi3_gpio_init(void); +int rpi3_gpio_get_select(int gpio); +void rpi3_gpio_set_select(int gpio, int fsel); + +#define RPI3_GPIO_GPFSEL(n) ((n) * U(0x04)) +#define RPI3_GPIO_GPSET(n) (((n) * U(0x04)) + U(0x1C)) +#define RPI3_GPIO_GPCLR(n) (((n) * U(0x04)) + U(0x28)) +#define RPI3_GPIO_GPLEV(n) (((n) * U(0x04)) + U(0x34)) +#define RPI3_GPIO_GPPUD U(0x94) +#define RPI3_GPIO_GPPUDCLK(n) (((n) * U(0x04)) + U(0x98)) + +#define RPI3_GPIO_FUNC_INPUT U(0) +#define RPI3_GPIO_FUNC_OUTPUT U(1) +#define RPI3_GPIO_FUNC_ALT0 U(4) +#define RPI3_GPIO_FUNC_ALT1 U(5) +#define RPI3_GPIO_FUNC_ALT2 U(6) +#define RPI3_GPIO_FUNC_ALT3 U(7) +#define RPI3_GPIO_FUNC_ALT4 U(3) +#define RPI3_GPIO_FUNC_ALT5 U(2) + +#endif /* RPI3_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h b/arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h new file mode 100644 index 0000000..c107440 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI3_MBOX_H +#define RPI3_MBOX_H + +#include + +/* This struct must be aligned to 16 bytes */ +typedef struct __packed __aligned(16) rpi3_mbox_request { + uint32_t size; /* Buffer size in bytes */ + uint32_t code; /* Request/response code */ + uint32_t tags[0]; +} rpi3_mbox_request_t; + +#define RPI3_MBOX_BUFFER_SIZE U(256) + +/* Constants to perform a request/check the status of a request. */ +#define RPI3_MBOX_PROCESS_REQUEST U(0x00000000) +#define RPI3_MBOX_REQUEST_SUCCESSFUL U(0x80000000) +#define RPI3_MBOX_REQUEST_ERROR U(0x80000001) + +/* Command constants */ +#define RPI3_TAG_HARDWARE_GET_BOARD_REVISION U(0x00010002) +#define RPI3_TAG_END U(0x00000000) + +#define RPI3_TAG_REQUEST U(0x00000000) +#define RPI3_TAG_IS_RESPONSE U(0x80000000) /* Set if response */ +#define RPI3_TAG_RESPONSE_LENGTH_MASK U(0x7FFFFFFF) + +#define RPI3_CHANNEL_ARM_TO_VC U(0x8) +#define RPI3_CHANNEL_MASK U(0xF) + +void rpi3_vc_mailbox_request_send(rpi3_mbox_request_t *req, int req_size); + +#endif diff --git a/arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h b/arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h new file mode 100644 index 0000000..ea5a677 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI3_RNG_H +#define RPI3_RNG_H + +void rpi3_rng_read(void *buf, size_t len); + +#endif diff --git a/arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h b/arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h new file mode 100644 index 0000000..1653240 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI3_SDHOST_H +#define RPI3_SDHOST_H + +#include +#include +#include + +struct rpi3_sdhost_params { + uintptr_t reg_base; + uint32_t clk_rate; + uint32_t bus_width; + uint32_t flags; + uint32_t current_cmd; + uint8_t cmdbusy; + uint8_t mmc_app_cmd; + uint32_t ns_per_fifo_word; + + uint32_t sdcard_rca; + uint32_t gpio48_pinselect[6]; +}; + +void rpi3_sdhost_init(struct rpi3_sdhost_params *params, + struct mmc_device_info *mmc_dev_info); +void rpi3_sdhost_stop(void); + +/* Registers */ +#define HC_COMMAND 0x00 /* Command and flags */ +#define HC_ARGUMENT 0x04 +#define HC_TIMEOUTCOUNTER 0x08 +#define HC_CLOCKDIVISOR 0x0c +#define HC_RESPONSE_0 0x10 +#define HC_RESPONSE_1 0x14 +#define HC_RESPONSE_2 0x18 +#define HC_RESPONSE_3 0x1c +#define HC_HOSTSTATUS 0x20 +#define HC_POWER 0x30 +#define HC_DEBUG 0x34 +#define HC_HOSTCONFIG 0x38 +#define HC_BLOCKSIZE 0x3c +#define HC_DATAPORT 0x40 +#define HC_BLOCKCOUNT 0x50 + +/* Flags for HC_COMMAND register */ +#define HC_CMD_ENABLE 0x8000 +#define HC_CMD_FAILED 0x4000 +#define HC_CMD_BUSY 0x0800 +#define HC_CMD_RESPONSE_NONE 0x0400 +#define HC_CMD_RESPONSE_LONG 0x0200 +#define HC_CMD_WRITE 0x0080 +#define HC_CMD_READ 0x0040 +#define HC_CMD_COMMAND_MASK 0x003f + +#define HC_CLOCKDIVISOR_MAXVAL 0x07ff +#define HC_CLOCKDIVISOR_PREFERVAL 0x027b +#define HC_CLOCKDIVISOR_SLOWVAL 0x0148 +#define HC_CLOCKDIVISOR_STOPVAL 0x01fb + +/* Flags for HC_HOSTSTATUS register */ +#define HC_HSTST_HAVEDATA 0x0001 +#define HC_HSTST_ERROR_FIFO 0x0008 +#define HC_HSTST_ERROR_CRC7 0x0010 +#define HC_HSTST_ERROR_CRC16 0x0020 +#define HC_HSTST_TIMEOUT_CMD 0x0040 +#define HC_HSTST_TIMEOUT_DATA 0x0080 +#define HC_HSTST_INT_BLOCK 0x0200 +#define HC_HSTST_INT_BUSY 0x0400 + +#define HC_HSTST_RESET 0xffff + +#define HC_HSTST_MASK_ERROR_DATA (HC_HSTST_ERROR_FIFO | \ + HC_HSTST_ERROR_CRC7 | \ + HC_HSTST_ERROR_CRC16 | \ + HC_HSTST_TIMEOUT_DATA) + +#define HC_HSTST_MASK_ERROR_ALL (HC_HSTST_MASK_ERROR_DATA | \ + HC_HSTST_TIMEOUT_CMD) + +/* Flags for HC_HOSTCONFIG register */ +#define HC_HSTCF_INTBUS_WIDE 0x0002 +#define HC_HSTCF_EXTBUS_4BIT 0x0004 +#define HC_HSTCF_SLOW_CARD 0x0008 +#define HC_HSTCF_INT_DATA 0x0010 +#define HC_HSTCF_INT_BLOCK 0x0100 +#define HC_HSTCF_INT_BUSY 0x0400 + +/* Flags for HC_DEBUG register */ +#define HC_DBG_FIFO_THRESH_WRITE_SHIFT 9 +#define HC_DBG_FIFO_THRESH_READ_SHIFT 14 +#define HC_DBG_FIFO_THRESH_MASK 0x001f +#define HC_DBG_FSM_MASK 0xf +#define HC_DBG_FSM_IDENTMODE 0x0 +#define HC_DBG_FSM_DATAMODE 0x1 +#define HC_DBG_FSM_READDATA 0x2 +#define HC_DBG_FSM_WRITEDATA 0x3 +#define HC_DBG_FSM_READWAIT 0x4 +#define HC_DBG_FSM_READCRC 0x5 +#define HC_DBG_FSM_WRITECRC 0x6 +#define HC_DBG_FSM_WRITEWAIT1 0x7 +#define HC_DBG_FSM_POWERDOWN 0x8 +#define HC_DBG_FSM_POWERUP 0x9 +#define HC_DBG_FSM_WRITESTART1 0xa +#define HC_DBG_FSM_WRITESTART2 0xb +#define HC_DBG_FSM_GENPULSES 0xc +#define HC_DBG_FSM_WRITEWAIT2 0xd +#define HC_DBG_FSM_STARTPOWDOWN 0xf +#define HC_DBG_FORCE_DATA_MODE 0x40000 + +/* Settings */ +#define HC_FIFO_SIZE 16 +#define HC_FIFO_THRESH_READ 4 +#define HC_FIFO_THRESH_WRITE 4 + +#define HC_TIMEOUT_DEFAULT 0x00f00000 +#define HC_TIMEOUT_IDLE 0x00a00000 + +#endif /* RPI3_SDHOST_H */ diff --git a/arm-trusted-firmware/include/drivers/scmi-msg.h b/arm-trusted-firmware/include/drivers/scmi-msg.h new file mode 100644 index 0000000..a9a99cf --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/scmi.h b/arm-trusted-firmware/include/drivers/scmi.h new file mode 100644 index 0000000..ac5dc38 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/drivers/spi_mem.h b/arm-trusted-firmware/include/drivers/spi_mem.h new file mode 100644 index 0000000..d1953ac --- /dev/null +++ b/arm-trusted-firmware/include/drivers/spi_mem.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_SPI_MEM_H +#define DRIVERS_SPI_MEM_H + +#include +#include +#include + +#define SPI_MEM_BUSWIDTH_1_LINE 1U +#define SPI_MEM_BUSWIDTH_2_LINE 2U +#define SPI_MEM_BUSWIDTH_4_LINE 4U + +/* + * enum spi_mem_data_dir - Describes the direction of a SPI memory data + * transfer from the controller perspective. + * @SPI_MEM_DATA_IN: data coming from the SPI memory. + * @SPI_MEM_DATA_OUT: data sent to the SPI memory. + */ +enum spi_mem_data_dir { + SPI_MEM_DATA_IN, + SPI_MEM_DATA_OUT, +}; + +/* + * struct spi_mem_op - Describes a SPI memory operation. + * + * @cmd.buswidth: Number of IO lines used to transmit the command. + * @cmd.opcode: Operation opcode. + * @addr.nbytes: Number of address bytes to send. Can be zero if the operation + * does not need to send an address. + * @addr.buswidth: Number of IO lines used to transmit the address. + * @addr.val: Address value. This value is always sent MSB first on the bus. + * Note that only @addr.nbytes are taken into account in this + * address value, so users should make sure the value fits in the + * assigned number of bytes. + * @dummy.nbytes: Number of dummy bytes to send after an opcode or address. Can + * be zero if the operation does not require dummy bytes. + * @dummy.buswidth: Number of IO lines used to transmit the dummy bytes. + * @data.buswidth: Number of IO lines used to send/receive the data. + * @data.dir: Direction of the transfer. + * @data.nbytes: Number of data bytes to transfer. + * @data.buf: Input or output data buffer depending on data::dir. + */ +struct spi_mem_op { + struct { + uint8_t buswidth; + uint8_t opcode; + } cmd; + + struct { + uint8_t nbytes; + uint8_t buswidth; + uint64_t val; + } addr; + + struct { + uint8_t nbytes; + uint8_t buswidth; + } dummy; + + struct { + uint8_t buswidth; + enum spi_mem_data_dir dir; + unsigned int nbytes; + void *buf; + } data; +}; + +/* SPI mode flags */ +#define SPI_CPHA BIT(0) /* clock phase */ +#define SPI_CPOL BIT(1) /* clock polarity */ +#define SPI_CS_HIGH BIT(2) /* CS active high */ +#define SPI_LSB_FIRST BIT(3) /* per-word bits-on-wire */ +#define SPI_3WIRE BIT(4) /* SI/SO signals shared */ +#define SPI_PREAMBLE BIT(5) /* Skip preamble bytes */ +#define SPI_TX_DUAL BIT(6) /* transmit with 2 wires */ +#define SPI_TX_QUAD BIT(7) /* transmit with 4 wires */ +#define SPI_RX_DUAL BIT(8) /* receive with 2 wires */ +#define SPI_RX_QUAD BIT(9) /* receive with 4 wires */ + +struct spi_bus_ops { + /* + * Claim the bus and prepare it for communication. + * + * @cs: The chip select. + * Returns: 0 if the bus was claimed successfully, or a negative value + * if it wasn't. + */ + int (*claim_bus)(unsigned int cs); + + /* + * Release the SPI bus. + */ + void (*release_bus)(void); + + /* + * Set transfer speed. + * + * @hz: The transfer speed in Hertz. + * Returns: 0 on success, a negative error code otherwise. + */ + int (*set_speed)(unsigned int hz); + + /* + * Set the SPI mode/flags. + * + * @mode: Requested SPI mode (SPI_... flags). + * Returns: 0 on success, a negative error code otherwise. + */ + int (*set_mode)(unsigned int mode); + + /* + * Execute a SPI memory operation. + * + * @op: The memory operation to execute. + * Returns: 0 on success, a negative error code otherwise. + */ + int (*exec_op)(const struct spi_mem_op *op); +}; + +int spi_mem_exec_op(const struct spi_mem_op *op); +int spi_mem_init_slave(void *fdt, int bus_node, + const struct spi_bus_ops *ops); + +#endif /* DRIVERS_SPI_MEM_H */ diff --git a/arm-trusted-firmware/include/drivers/spi_nand.h b/arm-trusted-firmware/include/drivers/spi_nand.h new file mode 100644 index 0000000..40e2063 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/spi_nand.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_SPI_NAND_H +#define DRIVERS_SPI_NAND_H + +#include +#include + +#define SPI_NAND_OP_GET_FEATURE 0x0FU +#define SPI_NAND_OP_SET_FEATURE 0x1FU +#define SPI_NAND_OP_READ_ID 0x9FU +#define SPI_NAND_OP_LOAD_PAGE 0x13U +#define SPI_NAND_OP_RESET 0xFFU +#define SPI_NAND_OP_READ_FROM_CACHE 0x03U +#define SPI_NAND_OP_READ_FROM_CACHE_2X 0x3BU +#define SPI_NAND_OP_READ_FROM_CACHE_4X 0x6BU + +/* Configuration register */ +#define SPI_NAND_REG_CFG 0xB0U +#define SPI_NAND_CFG_ECC_EN BIT(4) +#define SPI_NAND_CFG_QE BIT(0) + +/* Status register */ +#define SPI_NAND_REG_STATUS 0xC0U +#define SPI_NAND_STATUS_BUSY BIT(0) +#define SPI_NAND_STATUS_ECC_UNCOR BIT(5) + +struct spinand_device { + struct nand_device *nand_dev; + struct spi_mem_op spi_read_cache_op; + uint8_t cfg_cache; /* Cached value of SPI NAND device register CFG */ +}; + +int spi_nand_init(unsigned long long *size, unsigned int *erase_size); + +/* + * Platform can implement this to override default SPI-NAND instance + * configuration. + * + * @device: target SPI-NAND instance. + * Return 0 on success, negative value otherwise. + */ +int plat_get_spi_nand_data(struct spinand_device *device); + +#endif /* DRIVERS_SPI_NAND_H */ diff --git a/arm-trusted-firmware/include/drivers/spi_nor.h b/arm-trusted-firmware/include/drivers/spi_nor.h new file mode 100644 index 0000000..72cfe5b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/spi_nor.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_SPI_NOR_H +#define DRIVERS_SPI_NOR_H + +#include + +/* OPCODE */ +#define SPI_NOR_OP_WREN 0x06U /* Write enable */ +#define SPI_NOR_OP_WRSR 0x01U /* Write status register 1 byte */ +#define SPI_NOR_OP_READ_ID 0x9FU /* Read JEDEC ID */ +#define SPI_NOR_OP_READ_CR 0x35U /* Read configuration register */ +#define SPI_NOR_OP_READ_SR 0x05U /* Read status register */ +#define SPI_NOR_OP_READ_FSR 0x70U /* Read flag status register */ +#define SPINOR_OP_RDEAR 0xC8U /* Read Extended Address Register */ +#define SPINOR_OP_WREAR 0xC5U /* Write Extended Address Register */ + +/* Used for Spansion flashes only. */ +#define SPINOR_OP_BRWR 0x17U /* Bank register write */ +#define SPINOR_OP_BRRD 0x16U /* Bank register read */ + +#define SPI_NOR_OP_READ 0x03U /* Read data bytes (low frequency) */ +#define SPI_NOR_OP_READ_FAST 0x0BU /* Read data bytes (high frequency) */ +#define SPI_NOR_OP_READ_1_1_2 0x3BU /* Read data bytes (Dual Output SPI) */ +#define SPI_NOR_OP_READ_1_2_2 0xBBU /* Read data bytes (Dual I/O SPI) */ +#define SPI_NOR_OP_READ_1_1_4 0x6BU /* Read data bytes (Quad Output SPI) */ +#define SPI_NOR_OP_READ_1_4_4 0xEBU /* Read data bytes (Quad I/O SPI) */ + +/* Flags for NOR specific configuration */ +#define SPI_NOR_USE_FSR BIT(0) +#define SPI_NOR_USE_BANK BIT(1) + +struct nor_device { + struct spi_mem_op read_op; + uint32_t size; + uint32_t flags; + uint8_t selected_bank; + uint8_t bank_write_cmd; + uint8_t bank_read_cmd; +}; + +int spi_nor_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read); +int spi_nor_init(unsigned long long *device_size, unsigned int *erase_size); + +/* + * Platform can implement this to override default NOR instance configuration. + * + * @device: target NOR instance. + * Return 0 on success, negative value otherwise. + */ +int plat_get_nor_data(struct nor_device *device); + +#endif /* DRIVERS_SPI_NOR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/bsec.h b/arm-trusted-firmware/include/drivers/st/bsec.h new file mode 100644 index 0000000..60dcf3c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/bsec.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BSEC_H +#define BSEC_H + +#include +#include + +#include + +/* + * IP configuration + */ +#define BSEC_OTP_MASK GENMASK(4, 0) +#define BSEC_OTP_BANK_SHIFT 5 +#define BSEC_TIMEOUT_VALUE 0xFFFF + +/* + * Return status + */ +#define BSEC_OK 0U +#define BSEC_ERROR 0xFFFFFFFFU +#define BSEC_DISTURBED 0xFFFFFFFEU +#define BSEC_INVALID_PARAM 0xFFFFFFFCU +#define BSEC_PROG_FAIL 0xFFFFFFFBU +#define BSEC_LOCK_FAIL 0xFFFFFFFAU +#define BSEC_TIMEOUT 0xFFFFFFF9U +#define BSEC_RETRY 0xFFFFFFF8U +#define BSEC_NOT_SUPPORTED 0xFFFFFFF7U +#define BSEC_WRITE_LOCKED 0xFFFFFFF6U +#define BSEC_ERROR_INVALID_FVR 0xFFFFFFF5U + +/* + * OTP MODE + */ +#define BSEC_MODE_OPEN1 0x00U +#define BSEC_MODE_SECURED 0x01U +#define BSEC_MODE_OPEN2 0x02U +#define BSEC_MODE_INVALID 0x04U + +/* + * OTP Lock services definition. + * Value must corresponding to the bit number in the register. + * Special case: (bit number << 1) for BSEC3. + */ +#define BSEC_LOCK_UPPER_OTP 0x00 +#define BSEC_LOCK_GWLOCK 0x01 +#define BSEC_LOCK_DEBUG 0x02 +#define BSEC_LOCK_PROGRAM 0x03 +#define BSEC_LOCK_KVLOCK 0x04 + +/* + * Values for struct bsec_config::freq + */ +#define FREQ_10_20_MHZ 0x0 +#define FREQ_20_30_MHZ 0x1 +#define FREQ_30_45_MHZ 0x2 +#define FREQ_45_67_MHZ 0x3 + +/* + * Device info structure, providing device-specific functions and a means of + * adding driver-specific state. + */ +struct bsec_config { + uint8_t den_lock; /* + * Debug enable sticky lock + * 1 debug enable is locked until next reset + */ + + /* BSEC2 only */ + uint8_t tread; /* SAFMEM Reading current level default 0 */ + uint8_t pulse_width; /* SAFMEM Programming pulse width default 1 */ + uint8_t freq; /* + * SAFMEM CLOCK see freq value define + * default FREQ_45_67_MHZ + */ + uint8_t power; /* Power up SAFMEM. 1 power up, 0 power off */ + uint8_t prog_lock; /* + * Programming Sticky lock + * 1 programming is locked until next reset + */ + uint8_t upper_otp_lock; /* + * Shadowing of upper OTP sticky lock + * 1 shadowing of upper OTP is locked + * until next reset + */ +}; + +uint32_t bsec_probe(void); +uint32_t bsec_get_base(void); + +uint32_t bsec_set_config(struct bsec_config *cfg); +uint32_t bsec_get_config(struct bsec_config *cfg); + +uint32_t bsec_shadow_register(uint32_t otp); +uint32_t bsec_read_otp(uint32_t *val, uint32_t otp); +uint32_t bsec_write_otp(uint32_t val, uint32_t otp); +uint32_t bsec_program_otp(uint32_t val, uint32_t otp); +uint32_t bsec_permanent_lock_otp(uint32_t otp); + +void bsec_write_debug_conf(uint32_t val); +uint32_t bsec_read_debug_conf(void); + +void bsec_write_scratch(uint32_t val); +uint32_t bsec_read_scratch(void); + +uint32_t bsec_get_status(void); +uint32_t bsec_get_hw_conf(void); +uint32_t bsec_get_version(void); +uint32_t bsec_get_id(void); +uint32_t bsec_get_magic_id(void); + +uint32_t bsec_set_sr_lock(uint32_t otp); +uint32_t bsec_read_sr_lock(uint32_t otp, bool *value); +uint32_t bsec_set_sw_lock(uint32_t otp); +uint32_t bsec_read_sw_lock(uint32_t otp, bool *value); +uint32_t bsec_set_sp_lock(uint32_t otp); +uint32_t bsec_read_sp_lock(uint32_t otp, bool *value); +uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value); +uint32_t bsec_otp_lock(uint32_t service); + +uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word); +uint32_t bsec_check_nsec_access_rights(uint32_t otp); + +#endif /* BSEC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/bsec2_reg.h b/arm-trusted-firmware/include/drivers/st/bsec2_reg.h new file mode 100644 index 0000000..f895020 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/bsec2_reg.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BSEC2_REG_H +#define BSEC2_REG_H + +#include + +/* IP configuration */ +#define ADDR_LOWER_OTP_PERLOCK_SHIFT 0x03 +#define DATA_LOWER_OTP_PERLOCK_BIT 0x03U /* 2 significants bits are used */ +#define DATA_LOWER_OTP_PERLOCK_MASK GENMASK(2, 0) +#define ADDR_UPPER_OTP_PERLOCK_SHIFT 0x04 +#define DATA_UPPER_OTP_PERLOCK_BIT 0x01U /* 1 significants bits are used */ +#define DATA_UPPER_OTP_PERLOCK_MASK GENMASK(3, 0) + +/* BSEC REGISTER OFFSET (base relative) */ +#define BSEC_OTP_CONF_OFF U(0x000) +#define BSEC_OTP_CTRL_OFF U(0x004) +#define BSEC_OTP_WRDATA_OFF U(0x008) +#define BSEC_OTP_STATUS_OFF U(0x00C) +#define BSEC_OTP_LOCK_OFF U(0x010) +#define BSEC_DEN_OFF U(0x014) +#define BSEC_DISTURBED_OFF U(0x01C) +#define BSEC_DISTURBED1_OFF U(0x020) +#define BSEC_DISTURBED2_OFF U(0x024) +#define BSEC_ERROR_OFF U(0x034) +#define BSEC_ERROR1_OFF U(0x038) +#define BSEC_ERROR2_OFF U(0x03C) +#define BSEC_WRLOCK_OFF U(0x04C) /* Safmem permanent lock */ +#define BSEC_WRLOCK1_OFF U(0x050) +#define BSEC_WRLOCK2_OFF U(0x054) +#define BSEC_SPLOCK_OFF U(0x064) /* Program safmem sticky lock */ +#define BSEC_SPLOCK1_OFF U(0x068) +#define BSEC_SPLOCK2_OFF U(0x06C) +#define BSEC_SWLOCK_OFF U(0x07C) /* Write in OTP sticky lock */ +#define BSEC_SWLOCK1_OFF U(0x080) +#define BSEC_SWLOCK2_OFF U(0x084) +#define BSEC_SRLOCK_OFF U(0x094) /* Shadowing sticky lock */ +#define BSEC_SRLOCK1_OFF U(0x098) +#define BSEC_SRLOCK2_OFF U(0x09C) +#define BSEC_JTAG_IN_OFF U(0x0AC) +#define BSEC_JTAG_OUT_OFF U(0x0B0) +#define BSEC_SCRATCH_OFF U(0x0B4) +#define BSEC_OTP_DATA_OFF U(0x200) +#define BSEC_IPHW_CFG_OFF U(0xFF0) +#define BSEC_IPVR_OFF U(0xFF4) +#define BSEC_IP_ID_OFF U(0xFF8) +#define BSEC_IP_MAGIC_ID_OFF U(0xFFC) + +#define BSEC_WRLOCK(n) (BSEC_WRLOCK_OFF + U(0x04) * (n)) +#define BSEC_SPLOCK(n) (BSEC_SPLOCK_OFF + U(0x04) * (n)) +#define BSEC_SWLOCK(n) (BSEC_SWLOCK_OFF + U(0x04) * (n)) +#define BSEC_SRLOCK(n) (BSEC_SRLOCK_OFF + U(0x04) * (n)) + +/* BSEC_CONFIGURATION Register */ +#define BSEC_CONF_POWER_UP_MASK BIT(0) +#define BSEC_CONF_POWER_UP_SHIFT 0 +#define BSEC_CONF_FRQ_MASK GENMASK(2, 1) +#define BSEC_CONF_FRQ_SHIFT 1 +#define BSEC_CONF_PRG_WIDTH_MASK GENMASK(6, 3) +#define BSEC_CONF_PRG_WIDTH_SHIFT 3 +#define BSEC_CONF_TREAD_MASK GENMASK(8, 7) +#define BSEC_CONF_TREAD_SHIFT 7 + +/* BSEC_CONTROL Register */ +#define BSEC_READ 0U +#define BSEC_WRITE BIT(8) +#define BSEC_LOCK BIT(9) + +/* BSEC_OTP_LOCK register */ +#define UPPER_OTP_LOCK_MASK BIT(0) +#define UPPER_OTP_LOCK_SHIFT 0 +#define DENREG_LOCK_MASK BIT(2) +#define DENREG_LOCK_SHIFT 2 +#define GPLOCK_LOCK_MASK BIT(4) +#define GPLOCK_LOCK_SHIFT 4 + +/* BSEC_OTP_STATUS Register */ +#define BSEC_MODE_STATUS_MASK GENMASK(2, 0) +#define BSEC_MODE_SECURE_MASK BIT(0) +#define BSEC_MODE_FULLDBG_MASK BIT(1) +#define BSEC_MODE_INVALID_MASK BIT(2) +#define BSEC_MODE_BUSY_MASK BIT(3) +#define BSEC_MODE_PROGFAIL_MASK BIT(4) +#define BSEC_MODE_PWR_MASK BIT(5) +#define BSEC_MODE_BIST1_LOCK_MASK BIT(6) +#define BSEC_MODE_BIST2_LOCK_MASK BIT(7) + +/* BSEC_DENABLE Register */ +#define BSEC_HDPEN BIT(4) +#define BSEC_SPIDEN BIT(5) +#define BSEC_SPINDEN BIT(6) +#define BSEC_DBGSWGEN BIT(10) +#define BSEC_DEN_ALL_MSK GENMASK(10, 0) + +/* BSEC_FENABLE Register */ +#define BSEC_FEN_ALL_MSK GENMASK(14, 0) + +/* BSEC_IPVR Register */ +#define BSEC_IPVR_MSK GENMASK(7, 0) + +#endif /* BSEC2_REG_H */ diff --git a/arm-trusted-firmware/include/drivers/st/etzpc.h b/arm-trusted-firmware/include/drivers/st/etzpc.h new file mode 100644 index 0000000..4cd2b4e --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/etzpc.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_ST_ETZPC_H +#define DRIVERS_ST_ETZPC_H + +#include +#include + +/* Define security level for each peripheral (DECPROT) */ +enum etzpc_decprot_attributes { + ETZPC_DECPROT_S_RW = 0, + ETZPC_DECPROT_NS_R_S_W = 1, + ETZPC_DECPROT_MCU_ISOLATION = 2, + ETZPC_DECPROT_NS_RW = 3, + ETZPC_DECPROT_MAX = 4, +}; + +void etzpc_configure_decprot(uint32_t decprot_id, + enum etzpc_decprot_attributes decprot_attr); +enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id); +void etzpc_lock_decprot(uint32_t decprot_id); + +void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value); +uint16_t etzpc_get_tzma(uint32_t tzma_id); +void etzpc_lock_tzma(uint32_t tzma_id); +bool etzpc_get_lock_tzma(uint32_t tzma_id); + +uint8_t etzpc_get_num_per_sec(void); +uint8_t etzpc_get_revision(void); +uintptr_t etzpc_get_base_address(void); + +int etzpc_init(void); + +#endif /* DRIVERS_ST_ETZPC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/io_mmc.h b/arm-trusted-firmware/include/drivers/st/io_mmc.h new file mode 100644 index 0000000..6179e89 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/io_mmc.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MMC_H +#define IO_MMC_H + +#include + +struct io_mmc_dev_spec { + bool use_boot_part; +}; + +int register_io_dev_mmc(const io_dev_connector_t **dev_con); + +#endif /* IO_MMC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/io_stm32image.h b/arm-trusted-firmware/include/drivers/st/io_stm32image.h new file mode 100644 index 0000000..f9fa363 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/io_stm32image.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_STM32IMAGE_H +#define IO_STM32IMAGE_H + +#include +#include + +#define MAX_LBA_SIZE 512 +#define MAX_PART_NAME_SIZE (EFI_NAMELEN + 1) +#define STM32_PART_NUM (PLAT_PARTITION_MAX_ENTRIES - STM32_TF_A_COPIES) + +struct stm32image_part_info { + char name[MAX_PART_NAME_SIZE]; + uint32_t binary_type; + uintptr_t part_offset; + uint32_t bkp_offset; +}; + +struct stm32image_device_info { + struct stm32image_part_info part_info[STM32_PART_NUM]; + unsigned long long device_size; + uint32_t lba_size; +}; + +int register_io_dev_stm32image(const io_dev_connector_t **dev_con); + +#endif /* IO_STM32IMAGE_H */ diff --git a/arm-trusted-firmware/include/drivers/st/regulator.h b/arm-trusted-firmware/include/drivers/st/regulator.h new file mode 100644 index 0000000..bf583e2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/regulator.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef REGULATOR_H +#define REGULATOR_H + +#include + +#ifndef PLAT_NB_RDEVS +#error "Missing PLAT_NB_RDEVS" +#endif + +/* + * Consumer interface + */ + +/* regulator-always-on : regulator should never be disabled */ +#define REGUL_ALWAYS_ON BIT(0) +/* + * regulator-boot-on: + * It's expected that this regulator was left on by the bootloader. + * The core shouldn't prevent it from being turned off later. + * The regulator is needed to exit from suspend so it is turned on during suspend entry. + */ +#define REGUL_BOOT_ON BIT(1) +/* regulator-over-current-protection: Enable over current protection. */ +#define REGUL_OCP BIT(2) +/* regulator-active-discharge: enable active discharge. */ +#define REGUL_ACTIVE_DISCHARGE BIT(3) +/* regulator-pull-down: Enable pull down resistor when the regulator is disabled. */ +#define REGUL_PULL_DOWN BIT(4) +/* + * st,mask-reset: set mask reset for the regulator, meaning that the regulator + * setting is maintained during pmic reset. + */ +#define REGUL_MASK_RESET BIT(5) +/* st,regulator-sink-source: set the regulator in sink source mode */ +#define REGUL_SINK_SOURCE BIT(6) +/* st,regulator-bypass: set the regulator in bypass mode */ +#define REGUL_ENABLE_BYPASS BIT(7) + +struct rdev *regulator_get_by_name(const char *node_name); + +struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name); + +int regulator_enable(struct rdev *rdev); +int regulator_disable(struct rdev *rdev); +int regulator_is_enabled(const struct rdev *rdev); + +int regulator_set_voltage(struct rdev *rdev, uint16_t volt); +int regulator_set_min_voltage(struct rdev *rdev); +int regulator_get_voltage(const struct rdev *rdev); + +int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count); +void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv); +int regulator_set_flag(struct rdev *rdev, uint16_t flag); + +/* + * Driver Interface + */ + +/* set_state() arguments */ +#define STATE_DISABLE false +#define STATE_ENABLE true + +struct regul_description { + const char *node_name; + const struct regul_ops *ops; + const void *driver_data; + const char *supply_name; + const uint32_t enable_ramp_delay; +}; + +struct regul_ops { + int (*set_state)(const struct regul_description *desc, bool state); + int (*get_state)(const struct regul_description *desc); + int (*set_voltage)(const struct regul_description *desc, uint16_t mv); + int (*get_voltage)(const struct regul_description *desc); + int (*list_voltages)(const struct regul_description *desc, + const uint16_t **levels, size_t *count); + int (*set_flag)(const struct regul_description *desc, uint16_t flag); + void (*lock)(const struct regul_description *desc); + void (*unlock)(const struct regul_description *desc); +}; + +int regulator_register(const struct regul_description *desc, int node); + +/* + * Internal regulator structure + * The structure is internal to the core, and the content should not be used + * by a consumer nor a driver. + */ +struct rdev { + const struct regul_description *desc; + + int32_t phandle; + + uint16_t min_mv; + uint16_t max_mv; + + uint16_t flags; + + uint32_t enable_ramp_delay; +}; + +#endif /* REGULATOR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/regulator_fixed.h b/arm-trusted-firmware/include/drivers/st/regulator_fixed.h new file mode 100644 index 0000000..b981262 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/regulator_fixed.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REGULATOR_FIXED_H +#define REGULATOR_FIXED_H + +int fixed_regulator_register(void); + +#endif /* REGULATOR_FIXED_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_console.h b/arm-trusted-firmware/include/drivers/st/stm32_console.h new file mode 100644 index 0000000..8d9187d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_console.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_CONSOLE_H +#define STM32_CONSOLE_H + +#include + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new STM32 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_stm32_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* STM32_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h b/arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h new file mode 100644 index 0000000..81d5b9d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32_FMC2_NAND_H +#define STM32_FMC2_NAND_H + +int stm32_fmc2_init(void); + +#endif /* STM32_FMC2_NAND_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_gpio.h b/arm-trusted-firmware/include/drivers/st/stm32_gpio.h new file mode 100644 index 0000000..eeef9da --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_gpio.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_GPIO_H +#define STM32_GPIO_H + +#include + +#define GPIO_MODE_OFFSET U(0x00) +#define GPIO_TYPE_OFFSET U(0x04) +#define GPIO_SPEED_OFFSET U(0x08) +#define GPIO_PUPD_OFFSET U(0x0C) +#define GPIO_OD_OFFSET U(0x14) +#define GPIO_BSRR_OFFSET U(0x18) +#define GPIO_AFRL_OFFSET U(0x20) +#define GPIO_AFRH_OFFSET U(0x24) +#define GPIO_SECR_OFFSET U(0x30) + +#define GPIO_ALT_LOWER_LIMIT U(0x08) + +#define GPIO_PIN_(_x) U(_x) +#define GPIO_PIN_MAX GPIO_PIN_(15) + +#define GPIO_ALTERNATE_(_x) U(_x) +#define GPIO_ALTERNATE_MASK U(0x0F) + +#define GPIO_MODE_INPUT U(0x00) +#define GPIO_MODE_OUTPUT U(0x01) +#define GPIO_MODE_ALTERNATE U(0x02) +#define GPIO_MODE_ANALOG U(0x03) +#define GPIO_MODE_MASK U(0x03) + +#define GPIO_TYPE_PUSH_PULL U(0x00) +#define GPIO_TYPE_OPEN_DRAIN U(0x01) +#define GPIO_TYPE_MASK U(0x01) + +#define GPIO_SPEED_LOW U(0x00) +#define GPIO_SPEED_MEDIUM U(0x01) +#define GPIO_SPEED_HIGH U(0x02) +#define GPIO_SPEED_VERY_HIGH U(0x03) +#define GPIO_SPEED_MASK U(0x03) + +#define GPIO_NO_PULL U(0x00) +#define GPIO_PULL_UP U(0x01) +#define GPIO_PULL_DOWN U(0x02) +#define GPIO_PULL_MASK U(0x03) + +#define GPIO_OD_OUTPUT_LOW U(0x00) +#define GPIO_OD_OUTPUT_HIGH U(0x01) +#define GPIO_OD_MASK U(0x01) + +#ifndef __ASSEMBLER__ +#include + +int dt_set_pinctrl_config(int node); +void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure); +void set_gpio_reset_cfg(uint32_t bank, uint32_t pin); +#endif /*__ASSEMBLER__*/ + +#endif /* STM32_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_hash.h b/arm-trusted-firmware/include/drivers/st/stm32_hash.h new file mode 100644 index 0000000..df04730 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_hash.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_HASH_H +#define STM32_HASH_H + +enum stm32_hash_algo_mode { + HASH_MD5SUM, + HASH_SHA1, + HASH_SHA224, + HASH_SHA256 +}; + +int stm32_hash_update(const uint8_t *buffer, size_t length); +int stm32_hash_final(uint8_t *digest); +int stm32_hash_final_update(const uint8_t *buffer, uint32_t buf_length, + uint8_t *digest); +void stm32_hash_init(enum stm32_hash_algo_mode mode); +int stm32_hash_register(void); + +#endif /* STM32_HASH_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_i2c.h b/arm-trusted-firmware/include/drivers/st/stm32_i2c.h new file mode 100644 index 0000000..170d4cf --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_i2c.h @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_I2C_H +#define STM32_I2C_H + +#include + +#include + +/* Bit definition for I2C_CR1 register */ +#define I2C_CR1_PE BIT(0) +#define I2C_CR1_TXIE BIT(1) +#define I2C_CR1_RXIE BIT(2) +#define I2C_CR1_ADDRIE BIT(3) +#define I2C_CR1_NACKIE BIT(4) +#define I2C_CR1_STOPIE BIT(5) +#define I2C_CR1_TCIE BIT(6) +#define I2C_CR1_ERRIE BIT(7) +#define I2C_CR1_DNF GENMASK(11, 8) +#define I2C_CR1_ANFOFF BIT(12) +#define I2C_CR1_SWRST BIT(13) +#define I2C_CR1_TXDMAEN BIT(14) +#define I2C_CR1_RXDMAEN BIT(15) +#define I2C_CR1_SBC BIT(16) +#define I2C_CR1_NOSTRETCH BIT(17) +#define I2C_CR1_WUPEN BIT(18) +#define I2C_CR1_GCEN BIT(19) +#define I2C_CR1_SMBHEN BIT(22) +#define I2C_CR1_SMBDEN BIT(21) +#define I2C_CR1_ALERTEN BIT(22) +#define I2C_CR1_PECEN BIT(23) + +/* Bit definition for I2C_CR2 register */ +#define I2C_CR2_SADD GENMASK(9, 0) +#define I2C_CR2_RD_WRN BIT(10) +#define I2C_CR2_RD_WRN_OFFSET 10U +#define I2C_CR2_ADD10 BIT(11) +#define I2C_CR2_HEAD10R BIT(12) +#define I2C_CR2_START BIT(13) +#define I2C_CR2_STOP BIT(14) +#define I2C_CR2_NACK BIT(15) +#define I2C_CR2_NBYTES GENMASK(23, 16) +#define I2C_CR2_NBYTES_OFFSET 16U +#define I2C_CR2_RELOAD BIT(24) +#define I2C_CR2_AUTOEND BIT(25) +#define I2C_CR2_PECBYTE BIT(26) + +/* Bit definition for I2C_OAR1 register */ +#define I2C_OAR1_OA1 GENMASK(9, 0) +#define I2C_OAR1_OA1MODE BIT(10) +#define I2C_OAR1_OA1EN BIT(15) + +/* Bit definition for I2C_OAR2 register */ +#define I2C_OAR2_OA2 GENMASK(7, 1) +#define I2C_OAR2_OA2MSK GENMASK(10, 8) +#define I2C_OAR2_OA2NOMASK 0 +#define I2C_OAR2_OA2MASK01 BIT(8) +#define I2C_OAR2_OA2MASK02 BIT(9) +#define I2C_OAR2_OA2MASK03 GENMASK(9, 8) +#define I2C_OAR2_OA2MASK04 BIT(10) +#define I2C_OAR2_OA2MASK05 (BIT(8) | BIT(10)) +#define I2C_OAR2_OA2MASK06 (BIT(9) | BIT(10)) +#define I2C_OAR2_OA2MASK07 GENMASK(10, 8) +#define I2C_OAR2_OA2EN BIT(15) + +/* Bit definition for I2C_TIMINGR register */ +#define I2C_TIMINGR_SCLL GENMASK(7, 0) +#define I2C_TIMINGR_SCLH GENMASK(15, 8) +#define I2C_TIMINGR_SDADEL GENMASK(19, 16) +#define I2C_TIMINGR_SCLDEL GENMASK(23, 20) +#define I2C_TIMINGR_PRESC GENMASK(31, 28) + +/* Bit definition for I2C_TIMEOUTR register */ +#define I2C_TIMEOUTR_TIMEOUTA GENMASK(11, 0) +#define I2C_TIMEOUTR_TIDLE BIT(12) +#define I2C_TIMEOUTR_TIMOUTEN BIT(15) +#define I2C_TIMEOUTR_TIMEOUTB GENMASK(27, 16) +#define I2C_TIMEOUTR_TEXTEN BIT(31) + +/* Bit definition for I2C_ISR register */ +#define I2C_ISR_TXE BIT(0) +#define I2C_ISR_TXIS BIT(1) +#define I2C_ISR_RXNE BIT(2) +#define I2C_ISR_ADDR BIT(3) +#define I2C_ISR_NACKF BIT(4) +#define I2C_ISR_STOPF BIT(5) +#define I2C_ISR_TC BIT(6) +#define I2C_ISR_TCR BIT(7) +#define I2C_ISR_BERR BIT(8) +#define I2C_ISR_ARLO BIT(9) +#define I2C_ISR_OVR BIT(10) +#define I2C_ISR_PECERR BIT(11) +#define I2C_ISR_TIMEOUT BIT(12) +#define I2C_ISR_ALERT BIT(13) +#define I2C_ISR_BUSY BIT(15) +#define I2C_ISR_DIR BIT(16) +#define I2C_ISR_ADDCODE GENMASK(23, 17) + +/* Bit definition for I2C_ICR register */ +#define I2C_ICR_ADDRCF BIT(3) +#define I2C_ICR_NACKCF BIT(4) +#define I2C_ICR_STOPCF BIT(5) +#define I2C_ICR_BERRCF BIT(8) +#define I2C_ICR_ARLOCF BIT(9) +#define I2C_ICR_OVRCF BIT(10) +#define I2C_ICR_PECCF BIT(11) +#define I2C_ICR_TIMOUTCF BIT(12) +#define I2C_ICR_ALERTCF BIT(13) + +enum i2c_speed_e { + I2C_SPEED_STANDARD, /* 100 kHz */ + I2C_SPEED_FAST, /* 400 kHz */ + I2C_SPEED_FAST_PLUS, /* 1 MHz */ +}; + +#define STANDARD_RATE 100000 +#define FAST_RATE 400000 +#define FAST_PLUS_RATE 1000000 + +struct stm32_i2c_init_s { + uint32_t own_address1; /* + * Specifies the first device own + * address. This parameter can be a + * 7-bit or 10-bit address. + */ + + uint32_t addressing_mode; /* + * Specifies if 7-bit or 10-bit + * addressing mode is selected. + * This parameter can be a value of + * @ref I2C_ADDRESSING_MODE. + */ + + uint32_t dual_address_mode; /* + * Specifies if dual addressing mode is + * selected. + * This parameter can be a value of @ref + * I2C_DUAL_ADDRESSING_MODE. + */ + + uint32_t own_address2; /* + * Specifies the second device own + * address if dual addressing mode is + * selected. This parameter can be a + * 7-bit address. + */ + + uint32_t own_address2_masks; /* + * Specifies the acknowledge mask + * address second device own address + * if dual addressing mode is selected + * This parameter can be a value of @ref + * I2C_OWN_ADDRESS2_MASKS. + */ + + uint32_t general_call_mode; /* + * Specifies if general call mode is + * selected. + * This parameter can be a value of @ref + * I2C_GENERAL_CALL_ADDRESSING_MODE. + */ + + uint32_t no_stretch_mode; /* + * Specifies if nostretch mode is + * selected. + * This parameter can be a value of @ref + * I2C_NOSTRETCH_MODE. + */ + + uint32_t rise_time; /* + * Specifies the SCL clock pin rising + * time in nanoseconds. + */ + + uint32_t fall_time; /* + * Specifies the SCL clock pin falling + * time in nanoseconds. + */ + + enum i2c_speed_e speed_mode; /* + * Specifies the I2C clock source + * frequency mode. + * This parameter can be a value of @ref + * i2c_speed_mode_e. + */ + + int analog_filter; /* + * Specifies if the I2C analog noise + * filter is selected. + * This parameter can be 0 (filter + * off), all other values mean filter + * on. + */ + + uint8_t digital_filter_coef; /* + * Specifies the I2C digital noise + * filter coefficient. + * This parameter can be a value + * between 0 and + * STM32_I2C_DIGITAL_FILTER_MAX. + */ +}; + +enum i2c_state_e { + I2C_STATE_RESET = 0x00U, /* Not yet initialized */ + I2C_STATE_READY = 0x20U, /* Ready for use */ + I2C_STATE_BUSY = 0x24U, /* Internal process ongoing */ + I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission ongoing */ + I2C_STATE_BUSY_RX = 0x22U, /* Data Reception ongoing */ +}; + +enum i2c_mode_e { + I2C_MODE_NONE = 0x00U, /* No active communication */ + I2C_MODE_MASTER = 0x10U, /* Communication in Master Mode */ + I2C_MODE_SLAVE = 0x20U, /* Communication in Slave Mode */ + I2C_MODE_MEM = 0x40U /* Communication in Memory Mode */ + +}; + +#define I2C_ERROR_NONE 0x00000000U /* No error */ +#define I2C_ERROR_BERR 0x00000001U /* BERR error */ +#define I2C_ERROR_ARLO 0x00000002U /* ARLO error */ +#define I2C_ERROR_AF 0x00000004U /* ACKF error */ +#define I2C_ERROR_OVR 0x00000008U /* OVR error */ +#define I2C_ERROR_DMA 0x00000010U /* DMA transfer error */ +#define I2C_ERROR_TIMEOUT 0x00000020U /* Timeout error */ +#define I2C_ERROR_SIZE 0x00000040U /* Size Management error */ + +struct i2c_handle_s { + uint32_t i2c_base_addr; /* Registers base address */ + unsigned int dt_status; /* DT nsec/sec status */ + unsigned int clock; /* Clock reference */ + uint8_t lock; /* Locking object */ + enum i2c_state_e i2c_state; /* Communication state */ + enum i2c_mode_e i2c_mode; /* Communication mode */ + uint32_t i2c_err; /* Error code */ +}; + +#define I2C_ADDRESSINGMODE_7BIT 0x00000001U +#define I2C_ADDRESSINGMODE_10BIT 0x00000002U + +#define I2C_DUALADDRESS_DISABLE 0x00000000U +#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN + +#define I2C_GENERALCALL_DISABLE 0x00000000U +#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN + +#define I2C_NOSTRETCH_DISABLE 0x00000000U +#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH + +#define I2C_MEMADD_SIZE_8BIT 0x00000001U +#define I2C_MEMADD_SIZE_16BIT 0x00000002U + +#define I2C_RELOAD_MODE I2C_CR2_RELOAD +#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND +#define I2C_SOFTEND_MODE 0x00000000U + +#define I2C_NO_STARTSTOP 0x00000000U +#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP) +#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \ + I2C_CR2_RD_WRN) +#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) + +#define I2C_FLAG_TXE I2C_ISR_TXE +#define I2C_FLAG_TXIS I2C_ISR_TXIS +#define I2C_FLAG_RXNE I2C_ISR_RXNE +#define I2C_FLAG_ADDR I2C_ISR_ADDR +#define I2C_FLAG_AF I2C_ISR_NACKF +#define I2C_FLAG_STOPF I2C_ISR_STOPF +#define I2C_FLAG_TC I2C_ISR_TC +#define I2C_FLAG_TCR I2C_ISR_TCR +#define I2C_FLAG_BERR I2C_ISR_BERR +#define I2C_FLAG_ARLO I2C_ISR_ARLO +#define I2C_FLAG_OVR I2C_ISR_OVR +#define I2C_FLAG_PECERR I2C_ISR_PECERR +#define I2C_FLAG_TIMEOUT I2C_ISR_TIMEOUT +#define I2C_FLAG_ALERT I2C_ISR_ALERT +#define I2C_FLAG_BUSY I2C_ISR_BUSY +#define I2C_FLAG_DIR I2C_ISR_DIR + +#define I2C_RESET_CR2 (I2C_CR2_SADD | I2C_CR2_HEAD10R | \ + I2C_CR2_NBYTES | I2C_CR2_RELOAD | \ + I2C_CR2_RD_WRN) + +#define I2C_TIMEOUT_BUSY_MS 25U + +#define I2C_ANALOGFILTER_ENABLE 0x00000000U +#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF + +/* STM32 specific defines */ +#define STM32_I2C_RISE_TIME_DEFAULT 25 /* ns */ +#define STM32_I2C_FALL_TIME_DEFAULT 10 /* ns */ +#define STM32_I2C_SPEED_DEFAULT I2C_SPEED_STANDARD +#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ +#define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ +#define STM32_I2C_DIGITAL_FILTER_MAX 16 + +int stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init); +int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data); +int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms); +int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms); +int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms); +int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms); +bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint32_t trials, uint32_t timeout_ms); + +#endif /* STM32_I2C_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_iwdg.h b/arm-trusted-firmware/include/drivers/st/stm32_iwdg.h new file mode 100644 index 0000000..bad2524 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_iwdg.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_IWDG_H +#define STM32_IWDG_H + +#include + +#define IWDG_HW_ENABLED BIT(0) +#define IWDG_DISABLE_ON_STOP BIT(1) +#define IWDG_DISABLE_ON_STANDBY BIT(2) + +int stm32_iwdg_init(void); +void stm32_iwdg_refresh(void); + +#endif /* STM32_IWDG_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_qspi.h b/arm-trusted-firmware/include/drivers/st/stm32_qspi.h new file mode 100644 index 0000000..f47fca4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_qspi.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32_QSPI_H +#define STM32_QSPI_H + +int stm32_qspi_init(void); + +#endif /* STM32_QSPI_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h b/arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h new file mode 100644 index 0000000..c83f625 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_SDMMC2_H +#define STM32_SDMMC2_H + +#include + +#include +#include + +struct stm32_sdmmc2_params { + uintptr_t reg_base; + unsigned int clk_rate; + unsigned int bus_width; + unsigned int flags; + struct mmc_device_info *device_info; + unsigned int pin_ckin; + unsigned int negedge; + unsigned int dirpol; + unsigned int clock_id; + unsigned int reset_id; + unsigned int max_freq; + bool use_dma; + struct rdev *vmmc_regu; +}; + +unsigned long long stm32_sdmmc2_mmc_get_device_size(void); +int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params); +bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory); + +#endif /* STM32_SDMMC2_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_uart.h b/arm-trusted-firmware/include/drivers/st/stm32_uart.h new file mode 100644 index 0000000..212968f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_uart.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_UART_H +#define STM32_UART_H + +/* UART word length */ +#define STM32_UART_WORDLENGTH_7B USART_CR1_M1 +#define STM32_UART_WORDLENGTH_8B 0x00000000U +#define STM32_UART_WORDLENGTH_9B USART_CR1_M0 + +/* UART number of stop bits */ +#define STM32_UART_STOPBITS_0_5 USART_CR2_STOP_0 +#define STM32_UART_STOPBITS_1 0x00000000U +#define STM32_UART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) +#define STM32_UART_STOPBITS_2 USART_CR2_STOP_1 + +/* UART parity */ +#define STM32_UART_PARITY_NONE 0x00000000U +#define STM32_UART_PARITY_EVEN USART_CR1_PCE +#define STM32_UART_PARITY_ODD (USART_CR1_PCE | USART_CR1_PS) + +/* UART transfer mode */ +#define STM32_UART_MODE_RX USART_CR1_RE +#define STM32_UART_MODE_TX USART_CR1_TE +#define STM32_UART_MODE_TX_RX (USART_CR1_TE | USART_CR1_RE) + +/* UART hardware flow control */ +#define STM32_UART_HWCONTROL_NONE 0x00000000U +#define STM32_UART_HWCONTROL_RTS USART_CR3_RTSE +#define STM32_UART_HWCONTROL_CTS USART_CR3_CTSE +#define STM32_UART_HWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE) + +/* UART over sampling */ +#define STM32_UART_OVERSAMPLING_16 0x00000000U +#define STM32_UART_OVERSAMPLING_8 USART_CR1_OVER8 + +/* UART prescaler */ +#define STM32_UART_PRESCALER_DIV1 0x00000000U +#define STM32_UART_PRESCALER_DIV2 0x00000001U +#define STM32_UART_PRESCALER_DIV4 0x00000002U +#define STM32_UART_PRESCALER_DIV6 0x00000003U +#define STM32_UART_PRESCALER_DIV8 0x00000004U +#define STM32_UART_PRESCALER_DIV10 0x00000005U +#define STM32_UART_PRESCALER_DIV12 0x00000006U +#define STM32_UART_PRESCALER_DIV16 0x00000007U +#define STM32_UART_PRESCALER_DIV32 0x00000008U +#define STM32_UART_PRESCALER_DIV64 0x00000009U +#define STM32_UART_PRESCALER_DIV128 0x0000000AU +#define STM32_UART_PRESCALER_DIV256 0x0000000BU +#define STM32_UART_PRESCALER_NB 0x0000000CU + +/* UART fifo mode */ +#define STM32_UART_FIFOMODE_EN USART_CR1_FIFOEN +#define STM32_UART_FIFOMODE_DIS 0x00000000U + +/* UART TXFIFO threshold level */ +#define STM32_UART_TXFIFO_THRESHOLD_1EIGHTHFULL 0x00000000U +#define STM32_UART_TXFIFO_THRESHOLD_1QUARTERFUL USART_CR3_TXFTCFG_0 +#define STM32_UART_TXFIFO_THRESHOLD_HALFFULL USART_CR3_TXFTCFG_1 +#define STM32_UART_TXFIFO_THRESHOLD_3QUARTERSFULL (USART_CR3_TXFTCFG_0 | USART_CR3_TXFTCFG_1) +#define STM32_UART_TXFIFO_THRESHOLD_7EIGHTHFULL USART_CR3_TXFTCFG_2 +#define STM32_UART_TXFIFO_THRESHOLD_EMPTY (USART_CR3_TXFTCFG_2 | USART_CR3_TXFTCFG_0) + +/* UART RXFIFO threshold level */ +#define STM32_UART_RXFIFO_THRESHOLD_1EIGHTHFULL 0x00000000U +#define STM32_UART_RXFIFO_THRESHOLD_1QUARTERFULL USART_CR3_RXFTCFG_0 +#define STM32_UART_RXFIFO_THRESHOLD_HALFFULL USART_CR3_RXFTCFG_1 +#define STM32_UART_RXFIFO_THRESHOLD_3QUARTERSFULL (USART_CR3_RXFTCFG_0 | USART_CR3_RXFTCFG_1) +#define STM32_UART_RXFIFO_THRESHOLD_7EIGHTHFULL USART_CR3_RXFTCFG_2 +#define STM32_UART_RXFIFO_THRESHOLD_FULL (USART_CR3_RXFTCFG_2 | USART_CR3_RXFTCFG_0) + +struct stm32_uart_init_s { + uint32_t baud_rate; /* + * Configures the UART communication + * baud rate. + */ + + uint32_t word_length; /* + * Specifies the number of data bits + * transmitted or received in a frame. + * This parameter can be a value of + * @ref STM32_UART_WORDLENGTH_*. + */ + + uint32_t stop_bits; /* + * Specifies the number of stop bits + * transmitted. This parameter can be + * a value of @ref STM32_UART_STOPBITS_*. + */ + + uint32_t parity; /* + * Specifies the parity mode. + * This parameter can be a value of + * @ref STM32_UART_PARITY_*. + */ + + uint32_t mode; /* + * Specifies whether the receive or + * transmit mode is enabled or + * disabled. This parameter can be a + * value of @ref @ref STM32_UART_MODE_*. + */ + + uint32_t hw_flow_control; /* + * Specifies whether the hardware flow + * control mode is enabled or + * disabled. This parameter can be a + * value of @ref STM32_UARTHWCONTROL_*. + */ + + uint32_t over_sampling; /* + * Specifies whether the over sampling + * 8 is enabled or disabled. + * This parameter can be a value of + * @ref STM32_UART_OVERSAMPLING_*. + */ + + uint32_t one_bit_sampling; /* + * Specifies whether a single sample + * or three samples' majority vote is + * selected. This parameter can be 0 + * or USART_CR3_ONEBIT. + */ + + uint32_t prescaler; /* + * Specifies the prescaler value used + * to divide the UART clock source. + * This parameter can be a value of + * @ref STM32_UART_PRESCALER_*. + */ + + uint32_t fifo_mode; /* + * Specifies if the FIFO mode will be + * used. This parameter can be a value + * of @ref STM32_UART_FIFOMODE_*. + */ + + uint32_t tx_fifo_threshold; /* + * Specifies the TXFIFO threshold + * level. This parameter can be a + * value of @ref + * STM32_UART_TXFIFO_THRESHOLD_*. + */ + + uint32_t rx_fifo_threshold; /* + * Specifies the RXFIFO threshold + * level. This parameter can be a + * value of @ref + * STM32_UART_RXFIFO_THRESHOLD_*. + */ +}; + +struct stm32_uart_handle_s { + uint32_t base; + uint32_t rdr_mask; +}; + +int stm32_uart_init(struct stm32_uart_handle_s *huart, + uintptr_t base_addr, + const struct stm32_uart_init_s *init); +void stm32_uart_stop(uintptr_t base_addr); +int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c); +int stm32_uart_flush(struct stm32_uart_handle_s *huart); +int stm32_uart_getc(struct stm32_uart_handle_s *huart); + +#endif /* STM32_UART_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h b/arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h new file mode 100644 index 0000000..14b296c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_UART_REGS_H +#define STM32_UART_REGS_H + +#include + +#define USART_CR1 U(0x00) +#define USART_CR2 U(0x04) +#define USART_CR3 U(0x08) +#define USART_BRR U(0x0C) +#define USART_GTPR U(0x10) +#define USART_RTOR U(0x14) +#define USART_RQR U(0x18) +#define USART_ISR U(0x1C) +#define USART_ICR U(0x20) +#define USART_RDR U(0x24) +#define USART_TDR U(0x28) +#define USART_PRESC U(0x2C) + +/* USART_CR1 register fields */ +#define USART_CR1_UE BIT(0) +#define USART_CR1_UESM BIT(1) +#define USART_CR1_RE BIT(2) +#define USART_CR1_TE BIT(3) +#define USART_CR1_IDLEIE BIT(4) +#define USART_CR1_RXNEIE BIT(5) +#define USART_CR1_TCIE BIT(6) +#define USART_CR1_TXEIE BIT(7) +#define USART_CR1_PEIE BIT(8) +#define USART_CR1_PS BIT(9) +#define USART_CR1_PCE BIT(10) +#define USART_CR1_WAKE BIT(11) +#define USART_CR1_M (BIT(28) | BIT(12)) +#define USART_CR1_M0 BIT(12) +#define USART_CR1_MME BIT(13) +#define USART_CR1_CMIE BIT(14) +#define USART_CR1_OVER8 BIT(15) +#define USART_CR1_DEDT GENMASK(20, 16) +#define USART_CR1_DEDT_0 BIT(16) +#define USART_CR1_DEDT_1 BIT(17) +#define USART_CR1_DEDT_2 BIT(18) +#define USART_CR1_DEDT_3 BIT(19) +#define USART_CR1_DEDT_4 BIT(20) +#define USART_CR1_DEAT GENMASK(25, 21) +#define USART_CR1_DEAT_0 BIT(21) +#define USART_CR1_DEAT_1 BIT(22) +#define USART_CR1_DEAT_2 BIT(23) +#define USART_CR1_DEAT_3 BIT(24) +#define USART_CR1_DEAT_4 BIT(25) +#define USART_CR1_RTOIE BIT(26) +#define USART_CR1_EOBIE BIT(27) +#define USART_CR1_M1 BIT(28) +#define USART_CR1_FIFOEN BIT(29) +#define USART_CR1_TXFEIE BIT(30) +#define USART_CR1_RXFFIE BIT(31) + +/* USART_CR2 register fields */ +#define USART_CR2_SLVEN BIT(0) +#define USART_CR2_DIS_NSS BIT(3) +#define USART_CR2_ADDM7 BIT(4) +#define USART_CR2_LBDL BIT(5) +#define USART_CR2_LBDIE BIT(6) +#define USART_CR2_LBCL BIT(8) +#define USART_CR2_CPHA BIT(9) +#define USART_CR2_CPOL BIT(10) +#define USART_CR2_CLKEN BIT(11) +#define USART_CR2_STOP GENMASK(13, 12) +#define USART_CR2_STOP_0 BIT(12) +#define USART_CR2_STOP_1 BIT(13) +#define USART_CR2_LINEN BIT(14) +#define USART_CR2_SWAP BIT(15) +#define USART_CR2_RXINV BIT(16) +#define USART_CR2_TXINV BIT(17) +#define USART_CR2_DATAINV BIT(18) +#define USART_CR2_MSBFIRST BIT(19) +#define USART_CR2_ABREN BIT(20) +#define USART_CR2_ABRMODE GENMASK(22, 21) +#define USART_CR2_ABRMODE_0 BIT(21) +#define USART_CR2_ABRMODE_1 BIT(22) +#define USART_CR2_RTOEN BIT(23) +#define USART_CR2_ADD GENMASK(31, 24) + +/* USART_CR3 register fields */ +#define USART_CR3_EIE BIT(0) +#define USART_CR3_IREN BIT(1) +#define USART_CR3_IRLP BIT(2) +#define USART_CR3_HDSEL BIT(3) +#define USART_CR3_NACK BIT(4) +#define USART_CR3_SCEN BIT(5) +#define USART_CR3_DMAR BIT(6) +#define USART_CR3_DMAT BIT(7) +#define USART_CR3_RTSE BIT(8) +#define USART_CR3_CTSE BIT(9) +#define USART_CR3_CTSIE BIT(10) +#define USART_CR3_ONEBIT BIT(11) +#define USART_CR3_OVRDIS BIT(12) +#define USART_CR3_DDRE BIT(13) +#define USART_CR3_DEM BIT(14) +#define USART_CR3_DEP BIT(15) +#define USART_CR3_SCARCNT GENMASK(19, 17) +#define USART_CR3_SCARCNT_0 BIT(17) +#define USART_CR3_SCARCNT_1 BIT(18) +#define USART_CR3_SCARCNT_2 BIT(19) +#define USART_CR3_WUS GENMASK(21, 20) +#define USART_CR3_WUS_0 BIT(20) +#define USART_CR3_WUS_1 BIT(21) +#define USART_CR3_WUFIE BIT(22) +#define USART_CR3_TXFTIE BIT(23) +#define USART_CR3_TCBGTIE BIT(24) +#define USART_CR3_RXFTCFG GENMASK(27, 25) +#define USART_CR3_RXFTCFG_0 BIT(25) +#define USART_CR3_RXFTCFG_1 BIT(26) +#define USART_CR3_RXFTCFG_2 BIT(27) +#define USART_CR3_RXFTIE BIT(28) +#define USART_CR3_TXFTCFG GENMASK(31, 29) +#define USART_CR3_TXFTCFG_0 BIT(29) +#define USART_CR3_TXFTCFG_1 BIT(30) +#define USART_CR3_TXFTCFG_2 BIT(31) + +/* USART_BRR register fields */ +#define USART_BRR_DIV_FRACTION GENMASK(3, 0) +#define USART_BRR_DIV_MANTISSA GENMASK(15, 4) + +/* USART_GTPR register fields */ +#define USART_GTPR_PSC GENMASK(7, 0) +#define USART_GTPR_GT GENMASK(15, 8) + +/* USART_RTOR register fields */ +#define USART_RTOR_RTO GENMASK(23, 0) +#define USART_RTOR_BLEN GENMASK(31, 24) + +/* USART_RQR register fields */ +#define USART_RQR_ABRRQ BIT(0) +#define USART_RQR_SBKRQ BIT(1) +#define USART_RQR_MMRQ BIT(2) +#define USART_RQR_RXFRQ BIT(3) +#define USART_RQR_TXFRQ BIT(4) + +/* USART_ISR register fields */ +#define USART_ISR_PE BIT(0) +#define USART_ISR_FE BIT(1) +#define USART_ISR_NE BIT(2) +#define USART_ISR_ORE BIT(3) +#define USART_ISR_IDLE BIT(4) +#define USART_ISR_RXNE BIT(5) +#define USART_ISR_TC BIT(6) +#define USART_ISR_TXE BIT(7) +#define USART_ISR_LBDF BIT(8) +#define USART_ISR_CTSIF BIT(9) +#define USART_ISR_CTS BIT(10) +#define USART_ISR_RTOF BIT(11) +#define USART_ISR_EOBF BIT(12) +#define USART_ISR_UDR BIT(13) +#define USART_ISR_ABRE BIT(14) +#define USART_ISR_ABRF BIT(15) +#define USART_ISR_BUSY BIT(16) +#define USART_ISR_CMF BIT(17) +#define USART_ISR_SBKF BIT(18) +#define USART_ISR_RWU BIT(19) +#define USART_ISR_WUF BIT(20) +#define USART_ISR_TEACK BIT(21) +#define USART_ISR_REACK BIT(22) +#define USART_ISR_TXFE BIT(23) +#define USART_ISR_RXFF BIT(24) +#define USART_ISR_TCBGT BIT(25) +#define USART_ISR_RXFT BIT(26) +#define USART_ISR_TXFT BIT(27) + +/* USART_ICR register fields */ +#define USART_ICR_PECF BIT(0) +#define USART_ICR_FECF BIT(1) +#define USART_ICR_NCF BIT(2) +#define USART_ICR_ORECF BIT(3) +#define USART_ICR_IDLECF BIT(4) +#define USART_ICR_TCCF BIT(6) +#define USART_ICR_TCBGT BIT(7) +#define USART_ICR_LBDCF BIT(8) +#define USART_ICR_CTSCF BIT(9) +#define USART_ICR_RTOCF BIT(11) +#define USART_ICR_EOBCF BIT(12) +#define USART_ICR_UDRCF BIT(13) +#define USART_ICR_CMCF BIT(17) +#define USART_ICR_WUCF BIT(20) + +/* USART_RDR register fields */ +#define USART_RDR_RDR GENMASK(8, 0) + +/* USART_TDR register fields */ +#define USART_TDR_TDR GENMASK(8, 0) + +/* USART_PRESC register fields */ +#define USART_PRESC_PRESCALER GENMASK(3, 0) + +#endif /* STM32_UART_REGS_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h b/arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h new file mode 100644 index 0000000..1451c9a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h @@ -0,0 +1,1878 @@ +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP13_RCC_H +#define STM32MP13_RCC_H + +#include + +#define RCC_SECCFGR U(0X0) +#define RCC_MP_SREQSETR U(0X100) +#define RCC_MP_SREQCLRR U(0X104) +#define RCC_MP_APRSTCR U(0X108) +#define RCC_MP_APRSTSR U(0X10C) +#define RCC_PWRLPDLYCR U(0X110) +#define RCC_MP_GRSTCSETR U(0X114) +#define RCC_BR_RSTSCLRR U(0X118) +#define RCC_MP_RSTSSETR U(0X11C) +#define RCC_MP_RSTSCLRR U(0X120) +#define RCC_MP_IWDGFZSETR U(0X124) +#define RCC_MP_IWDGFZCLRR U(0X128) +#define RCC_MP_CIER U(0X200) +#define RCC_MP_CIFR U(0X204) +#define RCC_BDCR U(0X400) +#define RCC_RDLSICR U(0X404) +#define RCC_OCENSETR U(0X420) +#define RCC_OCENCLRR U(0X424) +#define RCC_OCRDYR U(0X428) +#define RCC_HSICFGR U(0X440) +#define RCC_CSICFGR U(0X444) +#define RCC_MCO1CFGR U(0X460) +#define RCC_MCO2CFGR U(0X464) +#define RCC_DBGCFGR U(0X468) +#define RCC_RCK12SELR U(0X480) +#define RCC_RCK3SELR U(0X484) +#define RCC_RCK4SELR U(0X488) +#define RCC_PLL1CR U(0X4A0) +#define RCC_PLL1CFGR1 U(0X4A4) +#define RCC_PLL1CFGR2 U(0X4A8) +#define RCC_PLL1FRACR U(0X4AC) +#define RCC_PLL1CSGR U(0X4B0) +#define RCC_PLL2CR U(0X4D0) +#define RCC_PLL2CFGR1 U(0X4D4) +#define RCC_PLL2CFGR2 U(0X4D8) +#define RCC_PLL2FRACR U(0X4DC) +#define RCC_PLL2CSGR U(0X4E0) +#define RCC_PLL3CR U(0X500) +#define RCC_PLL3CFGR1 U(0X504) +#define RCC_PLL3CFGR2 U(0X508) +#define RCC_PLL3FRACR U(0X50C) +#define RCC_PLL3CSGR U(0X510) +#define RCC_PLL4CR U(0X520) +#define RCC_PLL4CFGR1 U(0X524) +#define RCC_PLL4CFGR2 U(0X528) +#define RCC_PLL4FRACR U(0X52C) +#define RCC_PLL4CSGR U(0X530) +#define RCC_MPCKSELR U(0X540) +#define RCC_ASSCKSELR U(0X544) +#define RCC_MSSCKSELR U(0X548) +#define RCC_CPERCKSELR U(0X54C) +#define RCC_RTCDIVR U(0X560) +#define RCC_MPCKDIVR U(0X564) +#define RCC_AXIDIVR U(0X568) +#define RCC_MLAHBDIVR U(0X56C) +#define RCC_APB1DIVR U(0X570) +#define RCC_APB2DIVR U(0X574) +#define RCC_APB3DIVR U(0X578) +#define RCC_APB4DIVR U(0X57C) +#define RCC_APB5DIVR U(0X580) +#define RCC_APB6DIVR U(0X584) +#define RCC_TIMG1PRER U(0X5A0) +#define RCC_TIMG2PRER U(0X5A4) +#define RCC_TIMG3PRER U(0X5A8) +#define RCC_DDRITFCR U(0X5C0) +#define RCC_I2C12CKSELR U(0X600) +#define RCC_I2C345CKSELR U(0X604) +#define RCC_SPI2S1CKSELR U(0X608) +#define RCC_SPI2S23CKSELR U(0X60C) +#define RCC_SPI45CKSELR U(0X610) +#define RCC_UART12CKSELR U(0X614) +#define RCC_UART35CKSELR U(0X618) +#define RCC_UART4CKSELR U(0X61C) +#define RCC_UART6CKSELR U(0X620) +#define RCC_UART78CKSELR U(0X624) +#define RCC_LPTIM1CKSELR U(0X628) +#define RCC_LPTIM23CKSELR U(0X62C) +#define RCC_LPTIM45CKSELR U(0X630) +#define RCC_SAI1CKSELR U(0X634) +#define RCC_SAI2CKSELR U(0X638) +#define RCC_FDCANCKSELR U(0X63C) +#define RCC_SPDIFCKSELR U(0X640) +#define RCC_ADC12CKSELR U(0X644) +#define RCC_SDMMC12CKSELR U(0X648) +#define RCC_ETH12CKSELR U(0X64C) +#define RCC_USBCKSELR U(0X650) +#define RCC_QSPICKSELR U(0X654) +#define RCC_FMCCKSELR U(0X658) +#define RCC_RNG1CKSELR U(0X65C) +#define RCC_STGENCKSELR U(0X660) +#define RCC_DCMIPPCKSELR U(0X664) +#define RCC_SAESCKSELR U(0X668) +#define RCC_APB1RSTSETR U(0X6A0) +#define RCC_APB1RSTCLRR U(0X6A4) +#define RCC_APB2RSTSETR U(0X6A8) +#define RCC_APB2RSTCLRR U(0X6AC) +#define RCC_APB3RSTSETR U(0X6B0) +#define RCC_APB3RSTCLRR U(0X6B4) +#define RCC_APB4RSTSETR U(0X6B8) +#define RCC_APB4RSTCLRR U(0X6BC) +#define RCC_APB5RSTSETR U(0X6C0) +#define RCC_APB5RSTCLRR U(0X6C4) +#define RCC_APB6RSTSETR U(0X6C8) +#define RCC_APB6RSTCLRR U(0X6CC) +#define RCC_AHB2RSTSETR U(0X6D0) +#define RCC_AHB2RSTCLRR U(0X6D4) +#define RCC_AHB4RSTSETR U(0X6E0) +#define RCC_AHB4RSTCLRR U(0X6E4) +#define RCC_AHB5RSTSETR U(0X6E8) +#define RCC_AHB5RSTCLRR U(0X6EC) +#define RCC_AHB6RSTSETR U(0X6F0) +#define RCC_AHB6RSTCLRR U(0X6F4) +#define RCC_MP_APB1ENSETR U(0X700) +#define RCC_MP_APB1ENCLRR U(0X704) +#define RCC_MP_APB2ENSETR U(0X708) +#define RCC_MP_APB2ENCLRR U(0X70C) +#define RCC_MP_APB3ENSETR U(0X710) +#define RCC_MP_APB3ENCLRR U(0X714) +#define RCC_MP_S_APB3ENSETR U(0X718) +#define RCC_MP_S_APB3ENCLRR U(0X71C) +#define RCC_MP_NS_APB3ENSETR U(0X720) +#define RCC_MP_NS_APB3ENCLRR U(0X724) +#define RCC_MP_APB4ENSETR U(0X728) +#define RCC_MP_APB4ENCLRR U(0X72C) +#define RCC_MP_S_APB4ENSETR U(0X730) +#define RCC_MP_S_APB4ENCLRR U(0X734) +#define RCC_MP_NS_APB4ENSETR U(0X738) +#define RCC_MP_NS_APB4ENCLRR U(0X73C) +#define RCC_MP_APB5ENSETR U(0X740) +#define RCC_MP_APB5ENCLRR U(0X744) +#define RCC_MP_APB6ENSETR U(0X748) +#define RCC_MP_APB6ENCLRR U(0X74C) +#define RCC_MP_AHB2ENSETR U(0X750) +#define RCC_MP_AHB2ENCLRR U(0X754) +#define RCC_MP_AHB4ENSETR U(0X760) +#define RCC_MP_AHB4ENCLRR U(0X764) +#define RCC_MP_S_AHB4ENSETR U(0X768) +#define RCC_MP_S_AHB4ENCLRR U(0X76C) +#define RCC_MP_NS_AHB4ENSETR U(0X770) +#define RCC_MP_NS_AHB4ENCLRR U(0X774) +#define RCC_MP_AHB5ENSETR U(0X778) +#define RCC_MP_AHB5ENCLRR U(0X77C) +#define RCC_MP_AHB6ENSETR U(0X780) +#define RCC_MP_AHB6ENCLRR U(0X784) +#define RCC_MP_S_AHB6ENSETR U(0X788) +#define RCC_MP_S_AHB6ENCLRR U(0X78C) +#define RCC_MP_NS_AHB6ENSETR U(0X790) +#define RCC_MP_NS_AHB6ENCLRR U(0X794) +#define RCC_MP_APB1LPENSETR U(0X800) +#define RCC_MP_APB1LPENCLRR U(0X804) +#define RCC_MP_APB2LPENSETR U(0X808) +#define RCC_MP_APB2LPENCLRR U(0X80C) +#define RCC_MP_APB3LPENSETR U(0X810) +#define RCC_MP_APB3LPENCLRR U(0X814) +#define RCC_MP_S_APB3LPENSETR U(0X818) +#define RCC_MP_S_APB3LPENCLRR U(0X81C) +#define RCC_MP_NS_APB3LPENSETR U(0X820) +#define RCC_MP_NS_APB3LPENCLRR U(0X824) +#define RCC_MP_APB4LPENSETR U(0X828) +#define RCC_MP_APB4LPENCLRR U(0X82C) +#define RCC_MP_S_APB4LPENSETR U(0X830) +#define RCC_MP_S_APB4LPENCLRR U(0X834) +#define RCC_MP_NS_APB4LPENSETR U(0X838) +#define RCC_MP_NS_APB4LPENCLRR U(0X83C) +#define RCC_MP_APB5LPENSETR U(0X840) +#define RCC_MP_APB5LPENCLRR U(0X844) +#define RCC_MP_APB6LPENSETR U(0X848) +#define RCC_MP_APB6LPENCLRR U(0X84C) +#define RCC_MP_AHB2LPENSETR U(0X850) +#define RCC_MP_AHB2LPENCLRR U(0X854) +#define RCC_MP_AHB4LPENSETR U(0X858) +#define RCC_MP_AHB4LPENCLRR U(0X85C) +#define RCC_MP_S_AHB4LPENSETR U(0X868) +#define RCC_MP_S_AHB4LPENCLRR U(0X86C) +#define RCC_MP_NS_AHB4LPENSETR U(0X870) +#define RCC_MP_NS_AHB4LPENCLRR U(0X874) +#define RCC_MP_AHB5LPENSETR U(0X878) +#define RCC_MP_AHB5LPENCLRR U(0X87C) +#define RCC_MP_AHB6LPENSETR U(0X880) +#define RCC_MP_AHB6LPENCLRR U(0X884) +#define RCC_MP_S_AHB6LPENSETR U(0X888) +#define RCC_MP_S_AHB6LPENCLRR U(0X88C) +#define RCC_MP_NS_AHB6LPENSETR U(0X890) +#define RCC_MP_NS_AHB6LPENCLRR U(0X894) +#define RCC_MP_S_AXIMLPENSETR U(0X898) +#define RCC_MP_S_AXIMLPENCLRR U(0X89C) +#define RCC_MP_NS_AXIMLPENSETR U(0X8A0) +#define RCC_MP_NS_AXIMLPENCLRR U(0X8A4) +#define RCC_MP_MLAHBLPENSETR U(0X8A8) +#define RCC_MP_MLAHBLPENCLRR U(0X8AC) +#define RCC_APB3SECSR U(0X8C0) +#define RCC_APB4SECSR U(0X8C4) +#define RCC_APB5SECSR U(0X8C8) +#define RCC_APB6SECSR U(0X8CC) +#define RCC_AHB2SECSR U(0X8D0) +#define RCC_AHB4SECSR U(0X8D4) +#define RCC_AHB5SECSR U(0X8D8) +#define RCC_AHB6SECSR U(0X8DC) +#define RCC_VERR U(0XFF4) +#define RCC_IDR U(0XFF8) +#define RCC_SIDR U(0XFFC) + +/* RCC_SECCFGR register fields */ +#define RCC_SECCFGR_HSISEC BIT(0) +#define RCC_SECCFGR_CSISEC BIT(1) +#define RCC_SECCFGR_HSESEC BIT(2) +#define RCC_SECCFGR_LSISEC BIT(3) +#define RCC_SECCFGR_LSESEC BIT(4) +#define RCC_SECCFGR_PLL12SEC BIT(8) +#define RCC_SECCFGR_PLL3SEC BIT(9) +#define RCC_SECCFGR_PLL4SEC BIT(10) +#define RCC_SECCFGR_MPUSEC BIT(11) +#define RCC_SECCFGR_AXISEC BIT(12) +#define RCC_SECCFGR_MLAHBSEC BIT(13) +#define RCC_SECCFGR_APB3DIVSEC BIT(16) +#define RCC_SECCFGR_APB4DIVSEC BIT(17) +#define RCC_SECCFGR_APB5DIVSEC BIT(18) +#define RCC_SECCFGR_APB6DIVSEC BIT(19) +#define RCC_SECCFGR_TIMG3SEC BIT(20) +#define RCC_SECCFGR_CPERSEC BIT(21) +#define RCC_SECCFGR_MCO1SEC BIT(22) +#define RCC_SECCFGR_MCO2SEC BIT(23) +#define RCC_SECCFGR_STPSEC BIT(24) +#define RCC_SECCFGR_RSTSEC BIT(25) +#define RCC_SECCFGR_PWRSEC BIT(31) + +/* RCC_MP_SREQSETR register fields */ +#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) + +/* RCC_MP_SREQCLRR register fields */ +#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) + +/* RCC_MP_APRSTCR register fields */ +#define RCC_MP_APRSTCR_RDCTLEN BIT(0) +#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) +#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 + +/* RCC_MP_APRSTSR register fields */ +#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) +#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 + +/* RCC_PWRLPDLYCR register fields */ +#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 + +/* RCC_MP_GRSTCSETR register fields */ +#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) + +/* RCC_BR_RSTSCLRR register fields */ +#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) +#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) +#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) +#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_BR_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) + +/* RCC_MP_RSTSSETR register fields */ +#define RCC_MP_RSTSSETR_PORRSTF BIT(0) +#define RCC_MP_RSTSSETR_BORRSTF BIT(1) +#define RCC_MP_RSTSSETR_PADRSTF BIT(2) +#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) +#define RCC_MP_RSTSSETR_VCPURSTF BIT(5) +#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSSETR_STP2RSTF BIT(10) +#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSSETR_SPARE BIT(15) + +/* RCC_MP_RSTSCLRR register fields */ +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STP2RSTF BIT(10) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSCLRR_SPARE BIT(15) + +/* RCC_MP_IWDGFZSETR register fields */ +#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) + +/* RCC_MP_IWDGFZCLRR register fields */ +#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) + +/* RCC_MP_CIER register fields */ +#define RCC_MP_CIER_LSIRDYIE BIT(0) +#define RCC_MP_CIER_LSERDYIE BIT(1) +#define RCC_MP_CIER_HSIRDYIE BIT(2) +#define RCC_MP_CIER_HSERDYIE BIT(3) +#define RCC_MP_CIER_CSIRDYIE BIT(4) +#define RCC_MP_CIER_PLL1DYIE BIT(8) +#define RCC_MP_CIER_PLL2DYIE BIT(9) +#define RCC_MP_CIER_PLL3DYIE BIT(10) +#define RCC_MP_CIER_PLL4DYIE BIT(11) +#define RCC_MP_CIER_LSECSSIE BIT(16) +#define RCC_MP_CIER_WKUPIE BIT(20) + +/* RCC_MP_CIFR register fields */ +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) +#define RCC_MP_CIFR_LSECSSF BIT(16) +#define RCC_MP_CIFR_WKUPF BIT(20) + +/* RCC_BDCR register fields */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_LSECSSD BIT(9) +#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) +#define RCC_BDCR_RTCSRC_SHIFT 16 +#define RCC_BDCR_RTCCKEN BIT(20) +#define RCC_BDCR_VSWRST BIT(31) + +#define RCC_BDCR_LSEBYP_BIT 1 +#define RCC_BDCR_LSERDY_BIT 2 +#define RCC_BDCR_DIGBYP_BIT 3 +#define RCC_BDCR_LSECSSON_BIT 8 + +#define RCC_BDCR_LSEDRV_WIDTH 2 + +/* RCC_RDLSICR register fields */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) +#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) +#define RCC_RDLSICR_MRD_SHIFT 16 +#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) +#define RCC_RDLSICR_EADLY_SHIFT 24 +#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) +#define RCC_RDLSICR_SPARE_SHIFT 27 + +#define RCC_RDLSICR_LSIRDY_BIT 1 + +/* RCC_OCENSETR register fields */ +#define RCC_OCENSETR_HSION BIT(0) +#define RCC_OCENSETR_HSIKERON BIT(1) +#define RCC_OCENSETR_CSION BIT(4) +#define RCC_OCENSETR_CSIKERON BIT(5) +#define RCC_OCENSETR_DIGBYP BIT(7) +#define RCC_OCENSETR_HSEON BIT(8) +#define RCC_OCENSETR_HSEKERON BIT(9) +#define RCC_OCENSETR_HSEBYP BIT(10) +#define RCC_OCENSETR_HSECSSON BIT(11) + +#define RCC_OCENR_DIGBYP_BIT 7 +#define RCC_OCENR_HSEBYP_BIT 10 +#define RCC_OCENR_HSECSSON_BIT 11 + +/* RCC_OCENCLRR register fields */ +#define RCC_OCENCLRR_HSION BIT(0) +#define RCC_OCENCLRR_HSIKERON BIT(1) +#define RCC_OCENCLRR_CSION BIT(4) +#define RCC_OCENCLRR_CSIKERON BIT(5) +#define RCC_OCENCLRR_DIGBYP BIT(7) +#define RCC_OCENCLRR_HSEON BIT(8) +#define RCC_OCENCLRR_HSEKERON BIT(9) +#define RCC_OCENCLRR_HSEBYP BIT(10) + +/* RCC_OCRDYR register fields */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) +#define RCC_OCRDYR_MPUCKRDY BIT(23) +#define RCC_OCRDYR_AXICKRDY BIT(24) + +#define RCC_OCRDYR_HSIRDY_BIT 0 +#define RCC_OCRDYR_HSIDIVRDY_BIT 2 +#define RCC_OCRDYR_CSIRDY_BIT 4 +#define RCC_OCRDYR_HSERDY_BIT 8 + +/* RCC_HSICFGR register fields */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) +#define RCC_HSICFGR_HSIDIV_SHIFT 0 +#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16) +#define RCC_HSICFGR_HSICAL_SHIFT 16 + +/* RCC_CSICFGR register fields */ +#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) +#define RCC_CSICFGR_CSICAL_SHIFT 16 + +/* RCC_MCO1CFGR register fields */ +#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) +#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 +#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) +#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 +#define RCC_MCO1CFGR_MCO1ON BIT(12) + +/* RCC_MCO2CFGR register fields */ +#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) +#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 +#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) +#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 +#define RCC_MCO2CFGR_MCO2ON BIT(12) + +/* RCC_DBGCFGR register fields */ +#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) +#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 +#define RCC_DBGCFGR_DBGCKEN BIT(8) +#define RCC_DBGCFGR_TRACECKEN BIT(9) +#define RCC_DBGCFGR_DBGRST BIT(12) + +/* RCC_RCK12SELR register fields */ +#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) +#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 +#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) + +/* RCC_RCK3SELR register fields */ +#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) +#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 +#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) + +/* RCC_RCK4SELR register fields */ +#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) +#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 +#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) + +/* RCC_PLL1CR register fields */ +#define RCC_PLL1CR_PLLON BIT(0) +#define RCC_PLL1CR_PLL1RDY BIT(1) +#define RCC_PLL1CR_SSCG_CTRL BIT(2) +#define RCC_PLL1CR_DIVPEN BIT(4) +#define RCC_PLL1CR_DIVQEN BIT(5) +#define RCC_PLL1CR_DIVREN BIT(6) + +/* RCC_PLL1CFGR1 register fields */ +#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL1CFGR1_DIVN_SHIFT 0 +#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) +#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 + +/* RCC_PLL1CFGR2 register fields */ +#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL1CFGR2_DIVP_SHIFT 0 +#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL1CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL1FRACR register fields */ +#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL1FRACR_FRACV_SHIFT 3 +#define RCC_PLL1FRACR_FRACLE BIT(16) + +/* RCC_PLL1CSGR register fields */ +#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL1CSGR_SSCG_MODE BIT(15) +#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL2CR register fields */ +#define RCC_PLL2CR_PLLON BIT(0) +#define RCC_PLL2CR_PLL2RDY BIT(1) +#define RCC_PLL2CR_SSCG_CTRL BIT(2) +#define RCC_PLL2CR_DIVPEN BIT(4) +#define RCC_PLL2CR_DIVQEN BIT(5) +#define RCC_PLL2CR_DIVREN BIT(6) + +/* RCC_PLL2CFGR1 register fields */ +#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL2CFGR1_DIVN_SHIFT 0 +#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) +#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 + +/* RCC_PLL2CFGR2 register fields */ +#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL2CFGR2_DIVP_SHIFT 0 +#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL2CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL2FRACR register fields */ +#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL2FRACR_FRACV_SHIFT 3 +#define RCC_PLL2FRACR_FRACLE BIT(16) + +/* RCC_PLL2CSGR register fields */ +#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL2CSGR_SSCG_MODE BIT(15) +#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL3CR register fields */ +#define RCC_PLL3CR_PLLON BIT(0) +#define RCC_PLL3CR_PLL3RDY BIT(1) +#define RCC_PLL3CR_SSCG_CTRL BIT(2) +#define RCC_PLL3CR_DIVPEN BIT(4) +#define RCC_PLL3CR_DIVQEN BIT(5) +#define RCC_PLL3CR_DIVREN BIT(6) + +/* RCC_PLL3CFGR1 register fields */ +#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL3CFGR1_DIVN_SHIFT 0 +#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) +#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 +#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL3CFGR2 register fields */ +#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL3CFGR2_DIVP_SHIFT 0 +#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL3CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL3FRACR register fields */ +#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL3FRACR_FRACV_SHIFT 3 +#define RCC_PLL3FRACR_FRACLE BIT(16) + +/* RCC_PLL3CSGR register fields */ +#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL3CSGR_SSCG_MODE BIT(15) +#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL4CR register fields */ +#define RCC_PLL4CR_PLLON BIT(0) +#define RCC_PLL4CR_PLL4RDY BIT(1) +#define RCC_PLL4CR_SSCG_CTRL BIT(2) +#define RCC_PLL4CR_DIVPEN BIT(4) +#define RCC_PLL4CR_DIVQEN BIT(5) +#define RCC_PLL4CR_DIVREN BIT(6) + +/* RCC_PLL4CFGR1 register fields */ +#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL4CFGR1_DIVN_SHIFT 0 +#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) +#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 +#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL4CFGR2 register fields */ +#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL4CFGR2_DIVP_SHIFT 0 +#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL4CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL4FRACR register fields */ +#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL4FRACR_FRACV_SHIFT 3 +#define RCC_PLL4FRACR_FRACLE BIT(16) + +/* RCC_PLL4CSGR register fields */ +#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL4CSGR_SSCG_MODE BIT(15) +#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 + +/* RCC_MPCKSELR register fields */ +#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) +#define RCC_MPCKSELR_MPUSRC_SHIFT 0 +#define RCC_MPCKSELR_MPUSRCRDY BIT(31) + +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 +#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_MLAHBSSRC_MASK GENMASK(1, 0) +#define RCC_MSSCKSELR_MLAHBSSRC_SHIFT 0 +#define RCC_MSSCKSELR_MLAHBSSRCRDY BIT(31) + +/* RCC_CPERCKSELR register fields */ +#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) +#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 + +/* RCC_RTCDIVR register fields */ +#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) +#define RCC_RTCDIVR_RTCDIV_SHIFT 0 + +/* RCC_MPCKDIVR register fields */ +#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(3, 0) +#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 +#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) + +/* RCC_AXIDIVR register fields */ +#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIVR_AXIDIV_SHIFT 0 +#define RCC_AXIDIVR_AXIDIVRDY BIT(31) + +/* RCC_MLAHBDIVR register fields */ +#define RCC_MLAHBDIVR_MLAHBDIV_MASK GENMASK(3, 0) +#define RCC_MLAHBDIVR_MLAHBDIV_SHIFT 0 +#define RCC_MLAHBDIVR_MLAHBDIVRDY BIT(31) + +/* RCC_APB1DIVR register fields */ +#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) +#define RCC_APB1DIVR_APB1DIV_SHIFT 0 +#define RCC_APB1DIVR_APB1DIVRDY BIT(31) + +/* RCC_APB2DIVR register fields */ +#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) +#define RCC_APB2DIVR_APB2DIV_SHIFT 0 +#define RCC_APB2DIVR_APB2DIVRDY BIT(31) + +/* RCC_APB3DIVR register fields */ +#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) +#define RCC_APB3DIVR_APB3DIV_SHIFT 0 +#define RCC_APB3DIVR_APB3DIVRDY BIT(31) + +/* RCC_APB4DIVR register fields */ +#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) +#define RCC_APB4DIVR_APB4DIV_SHIFT 0 +#define RCC_APB4DIVR_APB4DIVRDY BIT(31) + +/* RCC_APB5DIVR register fields */ +#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) +#define RCC_APB5DIVR_APB5DIV_SHIFT 0 +#define RCC_APB5DIVR_APB5DIVRDY BIT(31) + +/* RCC_APB6DIVR register fields */ +#define RCC_APB6DIVR_APB6DIV_MASK GENMASK(2, 0) +#define RCC_APB6DIVR_APB6DIV_SHIFT 0 +#define RCC_APB6DIVR_APB6DIVRDY BIT(31) + +/* RCC_TIMG1PRER register fields */ +#define RCC_TIMG1PRER_TIMG1PRE BIT(0) +#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) + +/* RCC_TIMG2PRER register fields */ +#define RCC_TIMG2PRER_TIMG2PRE BIT(0) +#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) + +/* RCC_TIMG3PRER register fields */ +#define RCC_TIMG3PRER_TIMG3PRE BIT(0) +#define RCC_TIMG3PRER_TIMG3PRERDY BIT(31) + +/* RCC_DDRITFCR register fields */ +#define RCC_DDRITFCR_DDRC1EN BIT(0) +#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +#define RCC_DDRITFCR_AXIDCGEN BIT(8) +#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) +#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 +#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +#define RCC_DDRITFCR_DDRCORERST BIT(16) +#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +#define RCC_DDRITFCR_DPHYRST BIT(18) +#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_GSKPMOD BIT(23) +#define RCC_DDRITFCR_GSKPCTRL BIT(24) +#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) +#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 +#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) +#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C345CKSELR register fields */ +#define RCC_I2C345CKSELR_I2C3SRC_MASK GENMASK(2, 0) +#define RCC_I2C345CKSELR_I2C3SRC_SHIFT 0 +#define RCC_I2C345CKSELR_I2C4SRC_MASK GENMASK(5, 3) +#define RCC_I2C345CKSELR_I2C4SRC_SHIFT 3 +#define RCC_I2C345CKSELR_I2C5SRC_MASK GENMASK(8, 6) +#define RCC_I2C345CKSELR_I2C5SRC_SHIFT 6 + +/* RCC_SPI2S1CKSELR register fields */ +#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 + +/* RCC_SPI2S23CKSELR register fields */ +#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 + +/* RCC_SPI45CKSELR register fields */ +#define RCC_SPI45CKSELR_SPI4SRC_MASK GENMASK(2, 0) +#define RCC_SPI45CKSELR_SPI4SRC_SHIFT 0 +#define RCC_SPI45CKSELR_SPI5SRC_MASK GENMASK(5, 3) +#define RCC_SPI45CKSELR_SPI5SRC_SHIFT 3 + +/* RCC_UART12CKSELR register fields */ +#define RCC_UART12CKSELR_UART1SRC_MASK GENMASK(2, 0) +#define RCC_UART12CKSELR_UART1SRC_SHIFT 0 +#define RCC_UART12CKSELR_UART2SRC_MASK GENMASK(5, 3) +#define RCC_UART12CKSELR_UART2SRC_SHIFT 3 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART4CKSELR register fields */ +#define RCC_UART4CKSELR_UART4SRC_MASK GENMASK(2, 0) +#define RCC_UART4CKSELR_UART4SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_LPTIM1CKSELR register fields */ +#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 + +/* RCC_LPTIM23CKSELR register fields */ +#define RCC_LPTIM23CKSELR_LPTIM2SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM23CKSELR_LPTIM2SRC_SHIFT 0 +#define RCC_LPTIM23CKSELR_LPTIM3SRC_MASK GENMASK(5, 3) +#define RCC_LPTIM23CKSELR_LPTIM3SRC_SHIFT 3 + +/* RCC_LPTIM45CKSELR register fields */ +#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 + +/* RCC_SAI1CKSELR register fields */ +#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) +#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 + +/* RCC_SAI2CKSELR register fields */ +#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) +#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 + +/* RCC_FDCANCKSELR register fields */ +#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) +#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 + +/* RCC_SPDIFCKSELR register fields */ +#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) +#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 + +/* RCC_ADC12CKSELR register fields */ +#define RCC_ADC12CKSELR_ADC1SRC_MASK GENMASK(1, 0) +#define RCC_ADC12CKSELR_ADC1SRC_SHIFT 0 +#define RCC_ADC12CKSELR_ADC2SRC_MASK GENMASK(3, 2) +#define RCC_ADC12CKSELR_ADC2SRC_SHIFT 2 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC1SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC1SRC_SHIFT 0 +#define RCC_SDMMC12CKSELR_SDMMC2SRC_MASK GENMASK(5, 3) +#define RCC_SDMMC12CKSELR_SDMMC2SRC_SHIFT 3 + +/* RCC_ETH12CKSELR register fields */ +#define RCC_ETH12CKSELR_ETH1SRC_MASK GENMASK(1, 0) +#define RCC_ETH12CKSELR_ETH1SRC_SHIFT 0 +#define RCC_ETH12CKSELR_ETH1PTPDIV_MASK GENMASK(7, 4) +#define RCC_ETH12CKSELR_ETH1PTPDIV_SHIFT 4 +#define RCC_ETH12CKSELR_ETH2SRC_MASK GENMASK(9, 8) +#define RCC_ETH12CKSELR_ETH2SRC_SHIFT 8 +#define RCC_ETH12CKSELR_ETH2PTPDIV_MASK GENMASK(15, 12) +#define RCC_ETH12CKSELR_ETH2PTPDIV_SHIFT 12 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 +#define RCC_USBCKSELR_USBOSRC BIT(4) + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_DCMIPPCKSELR register fields */ +#define RCC_DCMIPPCKSELR_DCMIPPSRC_MASK GENMASK(1, 0) +#define RCC_DCMIPPCKSELR_DCMIPPSRC_SHIFT 0 + +/* RCC_SAESCKSELR register fields */ +#define RCC_SAESCKSELR_SAESSRC_MASK GENMASK(1, 0) +#define RCC_SAESCKSELR_SAESSRC_SHIFT 0 + +/* RCC_APB1RSTSETR register fields */ +#define RCC_APB1RSTSETR_TIM2RST BIT(0) +#define RCC_APB1RSTSETR_TIM3RST BIT(1) +#define RCC_APB1RSTSETR_TIM4RST BIT(2) +#define RCC_APB1RSTSETR_TIM5RST BIT(3) +#define RCC_APB1RSTSETR_TIM6RST BIT(4) +#define RCC_APB1RSTSETR_TIM7RST BIT(5) +#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) +#define RCC_APB1RSTSETR_SPI2RST BIT(11) +#define RCC_APB1RSTSETR_SPI3RST BIT(12) +#define RCC_APB1RSTSETR_USART3RST BIT(15) +#define RCC_APB1RSTSETR_UART4RST BIT(16) +#define RCC_APB1RSTSETR_UART5RST BIT(17) +#define RCC_APB1RSTSETR_UART7RST BIT(18) +#define RCC_APB1RSTSETR_UART8RST BIT(19) +#define RCC_APB1RSTSETR_I2C1RST BIT(21) +#define RCC_APB1RSTSETR_I2C2RST BIT(22) +#define RCC_APB1RSTSETR_SPDIFRST BIT(26) + +/* RCC_APB1RSTCLRR register fields */ +#define RCC_APB1RSTCLRR_TIM2RST BIT(0) +#define RCC_APB1RSTCLRR_TIM3RST BIT(1) +#define RCC_APB1RSTCLRR_TIM4RST BIT(2) +#define RCC_APB1RSTCLRR_TIM5RST BIT(3) +#define RCC_APB1RSTCLRR_TIM6RST BIT(4) +#define RCC_APB1RSTCLRR_TIM7RST BIT(5) +#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) +#define RCC_APB1RSTCLRR_SPI2RST BIT(11) +#define RCC_APB1RSTCLRR_SPI3RST BIT(12) +#define RCC_APB1RSTCLRR_USART3RST BIT(15) +#define RCC_APB1RSTCLRR_UART4RST BIT(16) +#define RCC_APB1RSTCLRR_UART5RST BIT(17) +#define RCC_APB1RSTCLRR_UART7RST BIT(18) +#define RCC_APB1RSTCLRR_UART8RST BIT(19) +#define RCC_APB1RSTCLRR_I2C1RST BIT(21) +#define RCC_APB1RSTCLRR_I2C2RST BIT(22) +#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) + +/* RCC_APB2RSTSETR register fields */ +#define RCC_APB2RSTSETR_TIM1RST BIT(0) +#define RCC_APB2RSTSETR_TIM8RST BIT(1) +#define RCC_APB2RSTSETR_SPI1RST BIT(8) +#define RCC_APB2RSTSETR_USART6RST BIT(13) +#define RCC_APB2RSTSETR_SAI1RST BIT(16) +#define RCC_APB2RSTSETR_SAI2RST BIT(17) +#define RCC_APB2RSTSETR_DFSDMRST BIT(20) +#define RCC_APB2RSTSETR_FDCANRST BIT(24) + +/* RCC_APB2RSTCLRR register fields */ +#define RCC_APB2RSTCLRR_TIM1RST BIT(0) +#define RCC_APB2RSTCLRR_TIM8RST BIT(1) +#define RCC_APB2RSTCLRR_SPI1RST BIT(8) +#define RCC_APB2RSTCLRR_USART6RST BIT(13) +#define RCC_APB2RSTCLRR_SAI1RST BIT(16) +#define RCC_APB2RSTCLRR_SAI2RST BIT(17) +#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) +#define RCC_APB2RSTCLRR_FDCANRST BIT(24) + +/* RCC_APB3RSTSETR register fields */ +#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) +#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) +#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) +#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) +#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) +#define RCC_APB3RSTSETR_VREFRST BIT(13) +#define RCC_APB3RSTSETR_DTSRST BIT(16) +#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) + +/* RCC_APB3RSTCLRR register fields */ +#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) +#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) +#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) +#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) +#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) +#define RCC_APB3RSTCLRR_VREFRST BIT(13) +#define RCC_APB3RSTCLRR_DTSRST BIT(16) +#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) + +/* RCC_APB4RSTSETR register fields */ +#define RCC_APB4RSTSETR_LTDCRST BIT(0) +#define RCC_APB4RSTSETR_DCMIPPRST BIT(1) +#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTSETR_USBPHYRST BIT(16) + +/* RCC_APB4RSTCLRR register fields */ +#define RCC_APB4RSTCLRR_LTDCRST BIT(0) +#define RCC_APB4RSTCLRR_DCMIPPRST BIT(1) +#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) + +/* RCC_APB5RSTSETR register fields */ +#define RCC_APB5RSTSETR_STGENRST BIT(20) + +/* RCC_APB5RSTCLRR register fields */ +#define RCC_APB5RSTCLRR_STGENRST BIT(20) + +/* RCC_APB6RSTSETR register fields */ +#define RCC_APB6RSTSETR_USART1RST BIT(0) +#define RCC_APB6RSTSETR_USART2RST BIT(1) +#define RCC_APB6RSTSETR_SPI4RST BIT(2) +#define RCC_APB6RSTSETR_SPI5RST BIT(3) +#define RCC_APB6RSTSETR_I2C3RST BIT(4) +#define RCC_APB6RSTSETR_I2C4RST BIT(5) +#define RCC_APB6RSTSETR_I2C5RST BIT(6) +#define RCC_APB6RSTSETR_TIM12RST BIT(7) +#define RCC_APB6RSTSETR_TIM13RST BIT(8) +#define RCC_APB6RSTSETR_TIM14RST BIT(9) +#define RCC_APB6RSTSETR_TIM15RST BIT(10) +#define RCC_APB6RSTSETR_TIM16RST BIT(11) +#define RCC_APB6RSTSETR_TIM17RST BIT(12) + +/* RCC_APB6RSTCLRR register fields */ +#define RCC_APB6RSTCLRR_USART1RST BIT(0) +#define RCC_APB6RSTCLRR_USART2RST BIT(1) +#define RCC_APB6RSTCLRR_SPI4RST BIT(2) +#define RCC_APB6RSTCLRR_SPI5RST BIT(3) +#define RCC_APB6RSTCLRR_I2C3RST BIT(4) +#define RCC_APB6RSTCLRR_I2C4RST BIT(5) +#define RCC_APB6RSTCLRR_I2C5RST BIT(6) +#define RCC_APB6RSTCLRR_TIM12RST BIT(7) +#define RCC_APB6RSTCLRR_TIM13RST BIT(8) +#define RCC_APB6RSTCLRR_TIM14RST BIT(9) +#define RCC_APB6RSTCLRR_TIM15RST BIT(10) +#define RCC_APB6RSTCLRR_TIM16RST BIT(11) +#define RCC_APB6RSTCLRR_TIM17RST BIT(12) + +/* RCC_AHB2RSTSETR register fields */ +#define RCC_AHB2RSTSETR_DMA1RST BIT(0) +#define RCC_AHB2RSTSETR_DMA2RST BIT(1) +#define RCC_AHB2RSTSETR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTSETR_DMA3RST BIT(3) +#define RCC_AHB2RSTSETR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTSETR_ADC1RST BIT(5) +#define RCC_AHB2RSTSETR_ADC2RST BIT(6) +#define RCC_AHB2RSTSETR_USBORST BIT(8) + +/* RCC_AHB2RSTCLRR register fields */ +#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) +#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) +#define RCC_AHB2RSTCLRR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTCLRR_DMA3RST BIT(3) +#define RCC_AHB2RSTCLRR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTCLRR_ADC1RST BIT(5) +#define RCC_AHB2RSTCLRR_ADC2RST BIT(6) +#define RCC_AHB2RSTCLRR_USBORST BIT(8) + +/* RCC_AHB4RSTSETR register fields */ +#define RCC_AHB4RSTSETR_GPIOARST BIT(0) +#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) +#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) +#define RCC_AHB4RSTSETR_GPIODRST BIT(3) +#define RCC_AHB4RSTSETR_GPIOERST BIT(4) +#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) +#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) +#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) +#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) +#define RCC_AHB4RSTSETR_TSCRST BIT(15) + +/* RCC_AHB4RSTCLRR register fields */ +#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) +#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) +#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) +#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) +#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) +#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) +#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) +#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) +#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) +#define RCC_AHB4RSTCLRR_TSCRST BIT(15) + +/* RCC_AHB5RSTSETR register fields */ +#define RCC_AHB5RSTSETR_PKARST BIT(2) +#define RCC_AHB5RSTSETR_SAESRST BIT(3) +#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + +/* RCC_AHB5RSTCLRR register fields */ +#define RCC_AHB5RSTCLRR_PKARST BIT(2) +#define RCC_AHB5RSTCLRR_SAESRST BIT(3) +#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) +#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) +#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) +#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) + +/* RCC_AHB6RSTSETR register fields */ +#define RCC_AHB6RSTSETR_MDMARST BIT(0) +#define RCC_AHB6RSTSETR_MCERST BIT(1) +#define RCC_AHB6RSTSETR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTSETR_FMCRST BIT(12) +#define RCC_AHB6RSTSETR_QSPIRST BIT(14) +#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTSETR_CRC1RST BIT(20) +#define RCC_AHB6RSTSETR_USBHRST BIT(24) +#define RCC_AHB6RSTSETR_ETH2MACRST BIT(30) + +/* RCC_AHB6RSTCLRR register fields */ +#define RCC_AHB6RSTCLRR_MDMARST BIT(0) +#define RCC_AHB6RSTCLRR_MCERST BIT(1) +#define RCC_AHB6RSTCLRR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTCLRR_FMCRST BIT(12) +#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) +#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) +#define RCC_AHB6RSTCLRR_USBHRST BIT(24) +#define RCC_AHB6RSTCLRR_ETH2MACRST BIT(30) + +/* RCC_MP_APB1ENSETR register fields */ +#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MP_APB1ENSETR_USART3EN BIT(15) +#define RCC_MP_APB1ENSETR_UART4EN BIT(16) +#define RCC_MP_APB1ENSETR_UART5EN BIT(17) +#define RCC_MP_APB1ENSETR_UART7EN BIT(18) +#define RCC_MP_APB1ENSETR_UART8EN BIT(19) +#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) + +/* RCC_MP_APB1ENCLRR register fields */ +#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) + +/* RCC_MP_APB2ENSETR register fields */ +#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MP_APB2ENSETR_USART6EN BIT(13) +#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MP_APB2ENCLRR register fields */ +#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MP_APB3ENSETR register fields */ +#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENSETR_VREFEN BIT(13) +#define RCC_MP_APB3ENSETR_DTSEN BIT(16) +#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MP_APB3ENCLRR register fields */ +#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MP_APB3ENCLRR_DTSEN BIT(16) +#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MP_S_APB3ENSETR register fields */ +#define RCC_MP_S_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_S_APB3ENCLRR register fields */ +#define RCC_MP_S_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENSETR register fields */ +#define RCC_MP_NS_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENCLRR register fields */ +#define RCC_MP_NS_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_APB4ENSETR register fields */ +#define RCC_MP_APB4ENSETR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MP_APB4ENCLRR register fields */ +#define RCC_MP_APB4ENCLRR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MP_S_APB4ENSETR register fields */ +#define RCC_MP_S_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_S_APB4ENCLRR register fields */ +#define RCC_MP_S_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENSETR register fields */ +#define RCC_MP_NS_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENCLRR register fields */ +#define RCC_MP_NS_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_APB5ENSETR register fields */ +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENSETR_TZCEN BIT(11) +#define RCC_MP_APB5ENSETR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENSETR_BSECEN BIT(16) +#define RCC_MP_APB5ENSETR_STGENCEN BIT(20) + +/* RCC_MP_APB5ENCLRR register fields */ +#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENCLRR_TZCEN BIT(11) +#define RCC_MP_APB5ENCLRR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MP_APB5ENCLRR_STGENCEN BIT(20) + +/* RCC_MP_APB6ENSETR register fields */ +#define RCC_MP_APB6ENSETR_USART1EN BIT(0) +#define RCC_MP_APB6ENSETR_USART2EN BIT(1) +#define RCC_MP_APB6ENSETR_SPI4EN BIT(2) +#define RCC_MP_APB6ENSETR_SPI5EN BIT(3) +#define RCC_MP_APB6ENSETR_I2C3EN BIT(4) +#define RCC_MP_APB6ENSETR_I2C4EN BIT(5) +#define RCC_MP_APB6ENSETR_I2C5EN BIT(6) +#define RCC_MP_APB6ENSETR_TIM12EN BIT(7) +#define RCC_MP_APB6ENSETR_TIM13EN BIT(8) +#define RCC_MP_APB6ENSETR_TIM14EN BIT(9) +#define RCC_MP_APB6ENSETR_TIM15EN BIT(10) +#define RCC_MP_APB6ENSETR_TIM16EN BIT(11) +#define RCC_MP_APB6ENSETR_TIM17EN BIT(12) + +/* RCC_MP_APB6ENCLRR register fields */ +#define RCC_MP_APB6ENCLRR_USART1EN BIT(0) +#define RCC_MP_APB6ENCLRR_USART2EN BIT(1) +#define RCC_MP_APB6ENCLRR_SPI4EN BIT(2) +#define RCC_MP_APB6ENCLRR_SPI5EN BIT(3) +#define RCC_MP_APB6ENCLRR_I2C3EN BIT(4) +#define RCC_MP_APB6ENCLRR_I2C4EN BIT(5) +#define RCC_MP_APB6ENCLRR_I2C5EN BIT(6) +#define RCC_MP_APB6ENCLRR_TIM12EN BIT(7) +#define RCC_MP_APB6ENCLRR_TIM13EN BIT(8) +#define RCC_MP_APB6ENCLRR_TIM14EN BIT(9) +#define RCC_MP_APB6ENCLRR_TIM15EN BIT(10) +#define RCC_MP_APB6ENCLRR_TIM16EN BIT(11) +#define RCC_MP_APB6ENCLRR_TIM17EN BIT(12) + +/* RCC_MP_AHB2ENSETR register fields */ +#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENSETR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENSETR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENSETR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENSETR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENSETR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) + +/* RCC_MP_AHB2ENCLRR register fields */ +#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENCLRR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENCLRR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENCLRR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENCLRR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENCLRR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) + +/* RCC_MP_AHB4ENSETR register fields */ +#define RCC_MP_AHB4ENSETR_TSCEN BIT(15) + +/* RCC_MP_AHB4ENCLRR register fields */ +#define RCC_MP_AHB4ENCLRR_TSCEN BIT(15) + +/* RCC_MP_S_AHB4ENSETR register fields */ +#define RCC_MP_S_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_S_AHB4ENCLRR register fields */ +#define RCC_MP_S_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENSETR register fields */ +#define RCC_MP_NS_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENCLRR register fields */ +#define RCC_MP_NS_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_AHB5ENSETR register fields */ +#define RCC_MP_AHB5ENSETR_PKAEN BIT(2) +#define RCC_MP_AHB5ENSETR_SAESEN BIT(3) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) + +/* RCC_MP_AHB5ENCLRR register fields */ +#define RCC_MP_AHB5ENCLRR_PKAEN BIT(2) +#define RCC_MP_AHB5ENCLRR_SAESEN BIT(3) +#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) + +/* RCC_MP_AHB6ENSETR register fields */ +#define RCC_MP_AHB6ENSETR_MCEEN BIT(1) +#define RCC_MP_AHB6ENSETR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENSETR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENSETR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENSETR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) +#define RCC_MP_AHB6ENSETR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENSETR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENSETR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENSETR_ETH2MACEN BIT(30) + +/* RCC_MP_AHB6ENCLRR register fields */ +#define RCC_MP_AHB6ENCLRR_MCEEN BIT(1) +#define RCC_MP_AHB6ENCLRR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENCLRR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENCLRR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENCLRR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) +#define RCC_MP_AHB6ENCLRR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENCLRR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENCLRR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENCLRR_ETH2MACEN BIT(30) + +/* RCC_MP_S_AHB6ENSETR register fields */ +#define RCC_MP_S_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_S_AHB6ENCLRR register fields */ +#define RCC_MP_S_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENSETR register fields */ +#define RCC_MP_NS_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENCLRR register fields */ +#define RCC_MP_NS_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_APB1LPENSETR register fields */ +#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB1LPENCLRR register fields */ +#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB2LPENSETR register fields */ +#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MP_APB2LPENCLRR register fields */ +#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MP_APB3LPENSETR register fields */ +#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENSETR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_APB3LPENCLRR register fields */ +#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENCLRR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_S_APB3LPENSETR register fields */ +#define RCC_MP_S_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_S_APB3LPENCLRR register fields */ +#define RCC_MP_S_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENSETR register fields */ +#define RCC_MP_NS_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENCLRR register fields */ +#define RCC_MP_NS_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_APB4LPENSETR register fields */ +#define RCC_MP_APB4LPENSETR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB4LPENCLRR register fields */ +#define RCC_MP_APB4LPENCLRR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MP_S_APB4LPENSETR register fields */ +#define RCC_MP_S_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_S_APB4LPENCLRR register fields */ +#define RCC_MP_S_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENSETR register fields */ +#define RCC_MP_NS_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENCLRR register fields */ +#define RCC_MP_NS_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_APB5LPENSETR register fields */ +#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENSETR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENSETR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENSETR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENSETR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB5LPENCLRR register fields */ +#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENCLRR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENCLRR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENCLRR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENCLRR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB6LPENSETR register fields */ +#define RCC_MP_APB6LPENSETR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENSETR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENSETR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENSETR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENSETR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENSETR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENSETR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENSETR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENSETR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENSETR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENSETR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENSETR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENSETR_TIM17LPEN BIT(12) + +/* RCC_MP_APB6LPENCLRR register fields */ +#define RCC_MP_APB6LPENCLRR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENCLRR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENCLRR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENCLRR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENCLRR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENCLRR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENCLRR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENCLRR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENCLRR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENCLRR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENCLRR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENCLRR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENCLRR_TIM17LPEN BIT(12) + +/* RCC_MP_AHB2LPENSETR register fields */ +#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENSETR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENSETR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENSETR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENSETR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENSETR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) + +/* RCC_MP_AHB2LPENCLRR register fields */ +#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENCLRR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENCLRR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENCLRR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENCLRR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENCLRR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) + +/* RCC_MP_AHB4LPENSETR register fields */ +#define RCC_MP_AHB4LPENSETR_TSCLPEN BIT(15) + +/* RCC_MP_AHB4LPENCLRR register fields */ +#define RCC_MP_AHB4LPENCLRR_TSCLPEN BIT(15) + +/* RCC_MP_S_AHB4LPENSETR register fields */ +#define RCC_MP_S_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_S_AHB4LPENCLRR register fields */ +#define RCC_MP_S_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENSETR register fields */ +#define RCC_MP_NS_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENCLRR register fields */ +#define RCC_MP_NS_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_AHB5LPENSETR register fields */ +#define RCC_MP_AHB5LPENSETR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENSETR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB5LPENCLRR register fields */ +#define RCC_MP_AHB5LPENCLRR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENCLRR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB6LPENSETR register fields */ +#define RCC_MP_AHB6LPENSETR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENSETR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENSETR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENSETR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENSETR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENSETR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENSETR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENSETR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENSETR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENSETR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENSETR_ETH2STPEN BIT(31) + +/* RCC_MP_AHB6LPENCLRR register fields */ +#define RCC_MP_AHB6LPENCLRR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENCLRR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENCLRR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENCLRR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENCLRR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENCLRR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENCLRR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENCLRR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENCLRR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENCLRR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENCLRR_ETH2STPEN BIT(31) + +/* RCC_MP_S_AHB6LPENSETR register fields */ +#define RCC_MP_S_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_S_AHB6LPENCLRR register fields */ +#define RCC_MP_S_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENSETR register fields */ +#define RCC_MP_NS_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENCLRR register fields */ +#define RCC_MP_NS_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_S_AXIMLPENSETR register fields */ +#define RCC_MP_S_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_S_AXIMLPENCLRR register fields */ +#define RCC_MP_S_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENSETR register fields */ +#define RCC_MP_NS_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENCLRR register fields */ +#define RCC_MP_NS_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_MLAHBLPENSETR register fields */ +#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENSETR_SRAM3LPEN BIT(2) + +/* RCC_MP_MLAHBLPENCLRR register fields */ +#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENCLRR_SRAM3LPEN BIT(2) + +/* RCC_APB3SECSR register fields */ +#define RCC_APB3SECSR_LPTIM2SECF BIT(0) +#define RCC_APB3SECSR_LPTIM3SECF BIT(1) +#define RCC_APB3SECSR_VREFSECF BIT(13) + +/* RCC_APB4SECSR register fields */ +#define RCC_APB4SECSR_DCMIPPSECF BIT(1) +#define RCC_APB4SECSR_USBPHYSECF BIT(16) + +/* RCC_APB5SECSR register fields */ +#define RCC_APB5SECSR_RTCSECF BIT(8) +#define RCC_APB5SECSR_TZCSECF BIT(11) +#define RCC_APB5SECSR_ETZPCSECF BIT(13) +#define RCC_APB5SECSR_IWDG1SECF BIT(15) +#define RCC_APB5SECSR_BSECSECF BIT(16) +#define RCC_APB5SECSR_STGENCSECF_MASK GENMASK(21, 20) +#define RCC_APB5SECSR_STGENCSECF_SHIFT 20 + +/* RCC_APB6SECSR register fields */ +#define RCC_APB6SECSR_USART1SECF BIT(0) +#define RCC_APB6SECSR_USART2SECF BIT(1) +#define RCC_APB6SECSR_SPI4SECF BIT(2) +#define RCC_APB6SECSR_SPI5SECF BIT(3) +#define RCC_APB6SECSR_I2C3SECF BIT(4) +#define RCC_APB6SECSR_I2C4SECF BIT(5) +#define RCC_APB6SECSR_I2C5SECF BIT(6) +#define RCC_APB6SECSR_TIM12SECF BIT(7) +#define RCC_APB6SECSR_TIM13SECF BIT(8) +#define RCC_APB6SECSR_TIM14SECF BIT(9) +#define RCC_APB6SECSR_TIM15SECF BIT(10) +#define RCC_APB6SECSR_TIM16SECF BIT(11) +#define RCC_APB6SECSR_TIM17SECF BIT(12) + +/* RCC_AHB2SECSR register fields */ +#define RCC_AHB2SECSR_DMA3SECF BIT(3) +#define RCC_AHB2SECSR_DMAMUX2SECF BIT(4) +#define RCC_AHB2SECSR_ADC1SECF BIT(5) +#define RCC_AHB2SECSR_ADC2SECF BIT(6) +#define RCC_AHB2SECSR_USBOSECF BIT(8) + +/* RCC_AHB4SECSR register fields */ +#define RCC_AHB4SECSR_TSCSECF BIT(15) + +/* RCC_AHB5SECSR register fields */ +#define RCC_AHB5SECSR_PKASECF BIT(2) +#define RCC_AHB5SECSR_SAESSECF BIT(3) +#define RCC_AHB5SECSR_CRYP1SECF BIT(4) +#define RCC_AHB5SECSR_HASH1SECF BIT(5) +#define RCC_AHB5SECSR_RNG1SECF BIT(6) +#define RCC_AHB5SECSR_BKPSRAMSECF BIT(8) + +/* RCC_AHB6SECSR register fields */ +#define RCC_AHB6SECSR_MCESECF BIT(1) +#define RCC_AHB6SECSR_ETH1SECF_MASK GENMASK(11, 7) +#define RCC_AHB6SECSR_ETH1SECF_SHIFT 7 +#define RCC_AHB6SECSR_FMCSECF BIT(12) +#define RCC_AHB6SECSR_QSPISECF BIT(14) +#define RCC_AHB6SECSR_SDMMC1SECF BIT(16) +#define RCC_AHB6SECSR_SDMMC2SECF BIT(17) +#define RCC_AHB6SECSR_ETH2SECF_MASK GENMASK(31, 27) +#define RCC_AHB6SECSR_ETH2SECF_SHIFT 27 + +/* RCC_VERR register fields */ +#define RCC_VERR_MINREV_MASK GENMASK(3, 0) +#define RCC_VERR_MINREV_SHIFT 0 +#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) +#define RCC_VERR_MAJREV_SHIFT 4 + +/* RCC_IDR register fields */ +#define RCC_IDR_ID_MASK GENMASK(31, 0) +#define RCC_IDR_ID_SHIFT 0 + +/* RCC_SIDR register fields */ +#define RCC_SIDR_SID_MASK GENMASK(31, 0) +#define RCC_SIDR_SID_SHIFT 0 + +/* Used for all RCC_PLLCR registers */ +#define RCC_PLLNCR_PLLON BIT(0) +#define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) +#define RCC_PLLNCR_DIVPEN BIT(4) +#define RCC_PLLNCR_DIVQEN BIT(5) +#define RCC_PLLNCR_DIVREN BIT(6) +#define RCC_PLLNCR_DIVEN_SHIFT 4 + +/* Used for all RCC_PLLCFGR1 registers */ +#define RCC_PLLNCFGR1_DIVM_SHIFT 16 +#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) +#define RCC_PLLNCFGR1_DIVN_SHIFT 0 +#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) + +/* Only for PLL3 and PLL4 */ +#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 +#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) + +/* Used for all RCC_PLLCFGR2 registers */ +#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVP_SHIFT 0 +#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 +#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLLNCFGR2_DIVR_SHIFT 16 +#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) + +/* Used for all RCC_PLLFRACR registers */ +#define RCC_PLLNFRACR_FRACV_SHIFT 3 +#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLLNFRACR_FRACLE BIT(16) + +/* Used for all RCC_PLLCSGR registers */ +#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 +#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 +#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 +#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) + +/* Used for most of RCC_SELR registers */ +#define RCC_SELR_SRC_MASK GENMASK(2, 0) +#define RCC_SELR_REFCLK_SRC_MASK GENMASK(1, 0) +#define RCC_SELR_SRCRDY BIT(31) + +/* Values of RCC_MPCKSELR register */ +#define RCC_MPCKSELR_HSI 0x00000000 +#define RCC_MPCKSELR_HSE 0x00000001 +#define RCC_MPCKSELR_PLL 0x00000002 +#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 + +/* Values of RCC_ASSCKSELR register */ +#define RCC_ASSCKSELR_HSI 0x00000000 +#define RCC_ASSCKSELR_HSE 0x00000001 +#define RCC_ASSCKSELR_PLL 0x00000002 + +/* Values of RCC_MSSCKSELR register */ +#define RCC_MSSCKSELR_HSI 0x00000000 +#define RCC_MSSCKSELR_HSE 0x00000001 +#define RCC_MSSCKSELR_CSI 0x00000002 +#define RCC_MSSCKSELR_PLL 0x00000003 + +/* Values of RCC_CPERCKSELR register */ +#define RCC_CPERCKSELR_HSI 0x00000000 +#define RCC_CPERCKSELR_CSI 0x00000001 +#define RCC_CPERCKSELR_HSE 0x00000002 + +/* Used for most of DIVR register: max div for RTC */ +#define RCC_DIVR_DIV_MASK GENMASK(5, 0) +#define RCC_DIVR_DIVRDY BIT(31) + +/* Masks for specific DIVR registers */ +#define RCC_APBXDIV_MASK GENMASK(2, 0) +#define RCC_MPUDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIV_MASK GENMASK(2, 0) +#define RCC_MLAHBDIV_MASK GENMASK(3, 0) + +/* Used for TIMER Prescaler */ +#define RCC_TIMGXPRER_TIMGXPRE BIT(0) + +/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ +#define RCC_MP_ENCLRR_OFFSET U(4) + +/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ +#define RCC_RSTCLRR_OFFSET U(4) + +/* RCC_OCENSETR register fields */ +#define RCC_OCENR_HSION BIT(0) +#define RCC_OCENR_HSIKERON BIT(1) +#define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_CSIKERON BIT(5) +#define RCC_OCENR_DIGBYP BIT(7) +#define RCC_OCENR_HSEON BIT(8) +#define RCC_OCENR_HSEKERON BIT(9) +#define RCC_OCENR_HSEBYP BIT(10) +#define RCC_OCENR_HSECSSON BIT(11) + +#define RCC_OCENR_DIGBYP_BIT 7 +#define RCC_OCENR_HSEBYP_BIT 10 +#define RCC_OCENR_HSECSSON_BIT 11 + +/* Used for RCC_MCO related operations */ +#define RCC_MCOCFG_MCOON BIT(12) +#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) +#define RCC_MCOCFG_MCODIV_SHIFT 4 +#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) + +#define RCC_UART4CKSELR_HSI 0x00000002 + +#define RCC_CPERCKSELR_PERSRC_MASK GENMASK(1, 0) +#define RCC_CPERCKSELR_PERSRC_SHIFT 0 + +#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) +#define RCC_USBCKSELR_USBOSRC_SHIFT 4 + +#define RCC_DDRITFCR_DDRCKMOD_SSR 0 +#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) +#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) + +#define RCC_DDRITFCR_DDRC2EN BIT(0) +#define RCC_DDRITFCR_DDRC2LPEN BIT(1) + +#define RCC_MP_CIFR_MASK U(0x110F1F) +#define RCC_OFFSET_MASK GENMASK(11, 0) + +#endif /* STM32MP1_RCC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h b/arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h new file mode 100644 index 0000000..ddc0397 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h @@ -0,0 +1,2328 @@ +/* + * Copyright (c) 2015-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_RCC_H +#define STM32MP1_RCC_H + +#include + +#define RCC_TZCR U(0x00) +#define RCC_OCENSETR U(0x0C) +#define RCC_OCENCLRR U(0x10) +#define RCC_HSICFGR U(0x18) +#define RCC_CSICFGR U(0x1C) +#define RCC_MPCKSELR U(0x20) +#define RCC_ASSCKSELR U(0x24) +#define RCC_RCK12SELR U(0x28) +#define RCC_MPCKDIVR U(0x2C) +#define RCC_AXIDIVR U(0x30) +#define RCC_APB4DIVR U(0x3C) +#define RCC_APB5DIVR U(0x40) +#define RCC_RTCDIVR U(0x44) +#define RCC_MSSCKSELR U(0x48) +#define RCC_PLL1CR U(0x80) +#define RCC_PLL1CFGR1 U(0x84) +#define RCC_PLL1CFGR2 U(0x88) +#define RCC_PLL1FRACR U(0x8C) +#define RCC_PLL1CSGR U(0x90) +#define RCC_PLL2CR U(0x94) +#define RCC_PLL2CFGR1 U(0x98) +#define RCC_PLL2CFGR2 U(0x9C) +#define RCC_PLL2FRACR U(0xA0) +#define RCC_PLL2CSGR U(0xA4) +#define RCC_I2C46CKSELR U(0xC0) +#define RCC_SPI6CKSELR U(0xC4) +#define RCC_UART1CKSELR U(0xC8) +#define RCC_RNG1CKSELR U(0xCC) +#define RCC_CPERCKSELR U(0xD0) +#define RCC_STGENCKSELR U(0xD4) +#define RCC_DDRITFCR U(0xD8) +#define RCC_MP_BOOTCR U(0x100) +#define RCC_MP_SREQSETR U(0x104) +#define RCC_MP_SREQCLRR U(0x108) +#define RCC_MP_GCR U(0x10C) +#define RCC_MP_APRSTCR U(0x110) +#define RCC_MP_APRSTSR U(0x114) +#define RCC_BDCR U(0x140) +#define RCC_RDLSICR U(0x144) +#define RCC_APB4RSTSETR U(0x180) +#define RCC_APB4RSTCLRR U(0x184) +#define RCC_APB5RSTSETR U(0x188) +#define RCC_APB5RSTCLRR U(0x18C) +#define RCC_AHB5RSTSETR U(0x190) +#define RCC_AHB5RSTCLRR U(0x194) +#define RCC_AHB6RSTSETR U(0x198) +#define RCC_AHB6RSTCLRR U(0x19C) +#define RCC_TZAHB6RSTSETR U(0x1A0) +#define RCC_TZAHB6RSTCLRR U(0x1A4) +#define RCC_MP_APB4ENSETR U(0x200) +#define RCC_MP_APB4ENCLRR U(0x204) +#define RCC_MP_APB5ENSETR U(0x208) +#define RCC_MP_APB5ENCLRR U(0x20C) +#define RCC_MP_AHB5ENSETR U(0x210) +#define RCC_MP_AHB5ENCLRR U(0x214) +#define RCC_MP_AHB6ENSETR U(0x218) +#define RCC_MP_AHB6ENCLRR U(0x21C) +#define RCC_MP_TZAHB6ENSETR U(0x220) +#define RCC_MP_TZAHB6ENCLRR U(0x224) +#define RCC_MC_APB4ENSETR U(0x280) +#define RCC_MC_APB4ENCLRR U(0x284) +#define RCC_MC_APB5ENSETR U(0x288) +#define RCC_MC_APB5ENCLRR U(0x28C) +#define RCC_MC_AHB5ENSETR U(0x290) +#define RCC_MC_AHB5ENCLRR U(0x294) +#define RCC_MC_AHB6ENSETR U(0x298) +#define RCC_MC_AHB6ENCLRR U(0x29C) +#define RCC_MP_APB4LPENSETR U(0x300) +#define RCC_MP_APB4LPENCLRR U(0x304) +#define RCC_MP_APB5LPENSETR U(0x308) +#define RCC_MP_APB5LPENCLRR U(0x30C) +#define RCC_MP_AHB5LPENSETR U(0x310) +#define RCC_MP_AHB5LPENCLRR U(0x314) +#define RCC_MP_AHB6LPENSETR U(0x318) +#define RCC_MP_AHB6LPENCLRR U(0x31C) +#define RCC_MP_TZAHB6LPENSETR U(0x320) +#define RCC_MP_TZAHB6LPENCLRR U(0x324) +#define RCC_MC_APB4LPENSETR U(0x380) +#define RCC_MC_APB4LPENCLRR U(0x384) +#define RCC_MC_APB5LPENSETR U(0x388) +#define RCC_MC_APB5LPENCLRR U(0x38C) +#define RCC_MC_AHB5LPENSETR U(0x390) +#define RCC_MC_AHB5LPENCLRR U(0x394) +#define RCC_MC_AHB6LPENSETR U(0x398) +#define RCC_MC_AHB6LPENCLRR U(0x39C) +#define RCC_BR_RSTSCLRR U(0x400) +#define RCC_MP_GRSTCSETR U(0x404) +#define RCC_MP_RSTSCLRR U(0x408) +#define RCC_MP_IWDGFZSETR U(0x40C) +#define RCC_MP_IWDGFZCLRR U(0x410) +#define RCC_MP_CIER U(0x414) +#define RCC_MP_CIFR U(0x418) +#define RCC_PWRLPDLYCR U(0x41C) +#define RCC_MP_RSTSSETR U(0x420) +#define RCC_MCO1CFGR U(0x800) +#define RCC_MCO2CFGR U(0x804) +#define RCC_OCRDYR U(0x808) +#define RCC_DBGCFGR U(0x80C) +#define RCC_RCK3SELR U(0x820) +#define RCC_RCK4SELR U(0x824) +#define RCC_TIMG1PRER U(0x828) +#define RCC_TIMG2PRER U(0x82C) +#define RCC_MCUDIVR U(0x830) +#define RCC_APB1DIVR U(0x834) +#define RCC_APB2DIVR U(0x838) +#define RCC_APB3DIVR U(0x83C) +#define RCC_PLL3CR U(0x880) +#define RCC_PLL3CFGR1 U(0x884) +#define RCC_PLL3CFGR2 U(0x888) +#define RCC_PLL3FRACR U(0x88C) +#define RCC_PLL3CSGR U(0x890) +#define RCC_PLL4CR U(0x894) +#define RCC_PLL4CFGR1 U(0x898) +#define RCC_PLL4CFGR2 U(0x89C) +#define RCC_PLL4FRACR U(0x8A0) +#define RCC_PLL4CSGR U(0x8A4) +#define RCC_I2C12CKSELR U(0x8C0) +#define RCC_I2C35CKSELR U(0x8C4) +#define RCC_SAI1CKSELR U(0x8C8) +#define RCC_SAI2CKSELR U(0x8CC) +#define RCC_SAI3CKSELR U(0x8D0) +#define RCC_SAI4CKSELR U(0x8D4) +#define RCC_SPI2S1CKSELR U(0x8D8) +#define RCC_SPI2S23CKSELR U(0x8DC) +#define RCC_SPI45CKSELR U(0x8E0) +#define RCC_UART6CKSELR U(0x8E4) +#define RCC_UART24CKSELR U(0x8E8) +#define RCC_UART35CKSELR U(0x8EC) +#define RCC_UART78CKSELR U(0x8F0) +#define RCC_SDMMC12CKSELR U(0x8F4) +#define RCC_SDMMC3CKSELR U(0x8F8) +#define RCC_ETHCKSELR U(0x8FC) +#define RCC_QSPICKSELR U(0x900) +#define RCC_FMCCKSELR U(0x904) +#define RCC_FDCANCKSELR U(0x90C) +#define RCC_SPDIFCKSELR U(0x914) +#define RCC_CECCKSELR U(0x918) +#define RCC_USBCKSELR U(0x91C) +#define RCC_RNG2CKSELR U(0x920) +#define RCC_DSICKSELR U(0x924) +#define RCC_ADCCKSELR U(0x928) +#define RCC_LPTIM45CKSELR U(0x92C) +#define RCC_LPTIM23CKSELR U(0x930) +#define RCC_LPTIM1CKSELR U(0x934) +#define RCC_APB1RSTSETR U(0x980) +#define RCC_APB1RSTCLRR U(0x984) +#define RCC_APB2RSTSETR U(0x988) +#define RCC_APB2RSTCLRR U(0x98C) +#define RCC_APB3RSTSETR U(0x990) +#define RCC_APB3RSTCLRR U(0x994) +#define RCC_AHB2RSTSETR U(0x998) +#define RCC_AHB2RSTCLRR U(0x99C) +#define RCC_AHB3RSTSETR U(0x9A0) +#define RCC_AHB3RSTCLRR U(0x9A4) +#define RCC_AHB4RSTSETR U(0x9A8) +#define RCC_AHB4RSTCLRR U(0x9AC) +#define RCC_MP_APB1ENSETR U(0xA00) +#define RCC_MP_APB1ENCLRR U(0xA04) +#define RCC_MP_APB2ENSETR U(0xA08) +#define RCC_MP_APB2ENCLRR U(0xA0C) +#define RCC_MP_APB3ENSETR U(0xA10) +#define RCC_MP_APB3ENCLRR U(0xA14) +#define RCC_MP_AHB2ENSETR U(0xA18) +#define RCC_MP_AHB2ENCLRR U(0xA1C) +#define RCC_MP_AHB3ENSETR U(0xA20) +#define RCC_MP_AHB3ENCLRR U(0xA24) +#define RCC_MP_AHB4ENSETR U(0xA28) +#define RCC_MP_AHB4ENCLRR U(0xA2C) +#define RCC_MP_MLAHBENSETR U(0xA38) +#define RCC_MP_MLAHBENCLRR U(0xA3C) +#define RCC_MC_APB1ENSETR U(0xA80) +#define RCC_MC_APB1ENCLRR U(0xA84) +#define RCC_MC_APB2ENSETR U(0xA88) +#define RCC_MC_APB2ENCLRR U(0xA8C) +#define RCC_MC_APB3ENSETR U(0xA90) +#define RCC_MC_APB3ENCLRR U(0xA94) +#define RCC_MC_AHB2ENSETR U(0xA98) +#define RCC_MC_AHB2ENCLRR U(0xA9C) +#define RCC_MC_AHB3ENSETR U(0xAA0) +#define RCC_MC_AHB3ENCLRR U(0xAA4) +#define RCC_MC_AHB4ENSETR U(0xAA8) +#define RCC_MC_AHB4ENCLRR U(0xAAC) +#define RCC_MC_AXIMENSETR U(0xAB0) +#define RCC_MC_AXIMENCLRR U(0xAB4) +#define RCC_MC_MLAHBENSETR U(0xAB8) +#define RCC_MC_MLAHBENCLRR U(0xABC) +#define RCC_MP_APB1LPENSETR U(0xB00) +#define RCC_MP_APB1LPENCLRR U(0xB04) +#define RCC_MP_APB2LPENSETR U(0xB08) +#define RCC_MP_APB2LPENCLRR U(0xB0C) +#define RCC_MP_APB3LPENSETR U(0xB10) +#define RCC_MP_APB3LPENCLRR U(0xB14) +#define RCC_MP_AHB2LPENSETR U(0xB18) +#define RCC_MP_AHB2LPENCLRR U(0xB1C) +#define RCC_MP_AHB3LPENSETR U(0xB20) +#define RCC_MP_AHB3LPENCLRR U(0xB24) +#define RCC_MP_AHB4LPENSETR U(0xB28) +#define RCC_MP_AHB4LPENCLRR U(0xB2C) +#define RCC_MP_AXIMLPENSETR U(0xB30) +#define RCC_MP_AXIMLPENCLRR U(0xB34) +#define RCC_MP_MLAHBLPENSETR U(0xB38) +#define RCC_MP_MLAHBLPENCLRR U(0xB3C) +#define RCC_MC_APB1LPENSETR U(0xB80) +#define RCC_MC_APB1LPENCLRR U(0xB84) +#define RCC_MC_APB2LPENSETR U(0xB88) +#define RCC_MC_APB2LPENCLRR U(0xB8C) +#define RCC_MC_APB3LPENSETR U(0xB90) +#define RCC_MC_APB3LPENCLRR U(0xB94) +#define RCC_MC_AHB2LPENSETR U(0xB98) +#define RCC_MC_AHB2LPENCLRR U(0xB9C) +#define RCC_MC_AHB3LPENSETR U(0xBA0) +#define RCC_MC_AHB3LPENCLRR U(0xBA4) +#define RCC_MC_AHB4LPENSETR U(0xBA8) +#define RCC_MC_AHB4LPENCLRR U(0xBAC) +#define RCC_MC_AXIMLPENSETR U(0xBB0) +#define RCC_MC_AXIMLPENCLRR U(0xBB4) +#define RCC_MC_MLAHBLPENSETR U(0xBB8) +#define RCC_MC_MLAHBLPENCLRR U(0xBBC) +#define RCC_MC_RSTSCLRR U(0xC00) +#define RCC_MC_CIER U(0xC14) +#define RCC_MC_CIFR U(0xC18) +#define RCC_VERR U(0xFF4) +#define RCC_IDR U(0xFF8) +#define RCC_SIDR U(0xFFC) + +/* RCC_TZCR register fields */ +#define RCC_TZCR_TZEN BIT(0) +#define RCC_TZCR_MCKPROT BIT(1) + +/* RCC_OCENSETR register fields */ +#define RCC_OCENSETR_HSION BIT(0) +#define RCC_OCENSETR_HSIKERON BIT(1) +#define RCC_OCENSETR_CSION BIT(4) +#define RCC_OCENSETR_CSIKERON BIT(5) +#define RCC_OCENSETR_DIGBYP BIT(7) +#define RCC_OCENSETR_HSEON BIT(8) +#define RCC_OCENSETR_HSEKERON BIT(9) +#define RCC_OCENSETR_HSEBYP BIT(10) +#define RCC_OCENSETR_HSECSSON BIT(11) + +/* RCC_OCENCLRR register fields */ +#define RCC_OCENCLRR_HSION BIT(0) +#define RCC_OCENCLRR_HSIKERON BIT(1) +#define RCC_OCENCLRR_CSION BIT(4) +#define RCC_OCENCLRR_CSIKERON BIT(5) +#define RCC_OCENCLRR_DIGBYP BIT(7) +#define RCC_OCENCLRR_HSEON BIT(8) +#define RCC_OCENCLRR_HSEKERON BIT(9) +#define RCC_OCENCLRR_HSEBYP BIT(10) + +/* RCC_HSICFGR register fields */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) +#define RCC_HSICFGR_HSIDIV_SHIFT 0 +#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSICAL_MASK GENMASK(24, 16) +#define RCC_HSICFGR_HSICAL_SHIFT 16 +#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK(27, 25) + +/* RCC_CSICFGR register fields */ +#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) +#define RCC_CSICFGR_CSICAL_SHIFT 16 + +/* RCC_MPCKSELR register fields */ +#define RCC_MPCKSELR_HSI 0x00000000 +#define RCC_MPCKSELR_HSE 0x00000001 +#define RCC_MPCKSELR_PLL 0x00000002 +#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 +#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) +#define RCC_MPCKSELR_MPUSRC_SHIFT 0 +#define RCC_MPCKSELR_MPUSRCRDY BIT(31) + +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_HSI 0x00000000 +#define RCC_ASSCKSELR_HSE 0x00000001 +#define RCC_ASSCKSELR_PLL 0x00000002 +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 +#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) + +/* RCC_RCK12SELR register fields */ +#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) +#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 +#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) + +/* RCC_MPCKDIVR register fields */ +#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(2, 0) +#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 +#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) + +/* RCC_AXIDIVR register fields */ +#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIVR_AXIDIV_SHIFT 0 +#define RCC_AXIDIVR_AXIDIVRDY BIT(31) + +/* RCC_APB4DIVR register fields */ +#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) +#define RCC_APB4DIVR_APB4DIV_SHIFT 0 +#define RCC_APB4DIVR_APB4DIVRDY BIT(31) + +/* RCC_APB5DIVR register fields */ +#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) +#define RCC_APB5DIVR_APB5DIV_SHIFT 0 +#define RCC_APB5DIVR_APB5DIVRDY BIT(31) + +/* RCC_RTCDIVR register fields */ +#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) +#define RCC_RTCDIVR_RTCDIV_SHIFT 0 + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_HSI 0x00000000 +#define RCC_MSSCKSELR_HSE 0x00000001 +#define RCC_MSSCKSELR_CSI 0x00000002 +#define RCC_MSSCKSELR_PLL 0x00000003 +#define RCC_MSSCKSELR_MCUSSRC_MASK GENMASK(1, 0) +#define RCC_MSSCKSELR_MCUSSRC_SHIFT 0 +#define RCC_MSSCKSELR_MCUSSRCRDY BIT(31) + +/* RCC_PLL1CR register fields */ +#define RCC_PLL1CR_PLLON BIT(0) +#define RCC_PLL1CR_PLL1RDY BIT(1) +#define RCC_PLL1CR_SSCG_CTRL BIT(2) +#define RCC_PLL1CR_DIVPEN BIT(4) +#define RCC_PLL1CR_DIVQEN BIT(5) +#define RCC_PLL1CR_DIVREN BIT(6) + +/* RCC_PLL1CFGR1 register fields */ +#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL1CFGR1_DIVN_SHIFT 0 +#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) +#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 + +/* RCC_PLL1CFGR2 register fields */ +#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL1CFGR2_DIVP_SHIFT 0 +#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL1CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL1FRACR register fields */ +#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL1FRACR_FRACV_SHIFT 3 +#define RCC_PLL1FRACR_FRACLE BIT(16) + +/* RCC_PLL1CSGR register fields */ +#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL1CSGR_SSCG_MODE BIT(15) +#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL2CR register fields */ +#define RCC_PLL2CR_PLLON BIT(0) +#define RCC_PLL2CR_PLL2RDY BIT(1) +#define RCC_PLL2CR_SSCG_CTRL BIT(2) +#define RCC_PLL2CR_DIVPEN BIT(4) +#define RCC_PLL2CR_DIVQEN BIT(5) +#define RCC_PLL2CR_DIVREN BIT(6) + +/* RCC_PLL2CFGR1 register fields */ +#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL2CFGR1_DIVN_SHIFT 0 +#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) +#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 + +/* RCC_PLL2CFGR2 register fields */ +#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL2CFGR2_DIVP_SHIFT 0 +#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL2CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL2FRACR register fields */ +#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL2FRACR_FRACV_SHIFT 3 +#define RCC_PLL2FRACR_FRACLE BIT(16) + +/* RCC_PLL2CSGR register fields */ +#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL2CSGR_SSCG_MODE BIT(15) +#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 + +/* RCC_I2C46CKSELR register fields */ +#define RCC_I2C46CKSELR_I2C46SRC_MASK GENMASK(2, 0) +#define RCC_I2C46CKSELR_I2C46SRC_SHIFT 0 + +/* RCC_SPI6CKSELR register fields */ +#define RCC_SPI6CKSELR_SPI6SRC_MASK GENMASK(2, 0) +#define RCC_SPI6CKSELR_SPI6SRC_SHIFT 0 + +/* RCC_UART1CKSELR register fields */ +#define RCC_UART1CKSELR_UART1SRC_MASK GENMASK(2, 0) +#define RCC_UART1CKSELR_UART1SRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_CPERCKSELR register fields */ +#define RCC_CPERCKSELR_HSI 0x00000000 +#define RCC_CPERCKSELR_CSI 0x00000001 +#define RCC_CPERCKSELR_HSE 0x00000002 +#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) +#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_DDRITFCR register fields */ +#define RCC_DDRITFCR_DDRC1EN BIT(0) +#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +#define RCC_DDRITFCR_DDRC2EN BIT(2) +#define RCC_DDRITFCR_DDRC2LPEN BIT(3) +#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +#define RCC_DDRITFCR_AXIDCGEN BIT(8) +#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) +#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 +#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +#define RCC_DDRITFCR_DDRCORERST BIT(16) +#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +#define RCC_DDRITFCR_DPHYRST BIT(18) +#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_DDRCKMOD_SSR 0 +#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) +#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) +#define RCC_DDRITFCR_GSKPMOD BIT(23) +#define RCC_DDRITFCR_GSKPCTRL BIT(24) +#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) +#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 +#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) +#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 + +/* RCC_MP_BOOTCR register fields */ +#define RCC_MP_BOOTCR_MCU_BEN BIT(0) +#define RCC_MP_BOOTCR_MPU_BEN BIT(1) + +/* RCC_MP_SREQSETR register fields */ +#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) +#define RCC_MP_SREQSETR_STPREQ_P1 BIT(1) + +/* RCC_MP_SREQCLRR register fields */ +#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) +#define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) + +/* RCC_MP_GCR register fields */ +#define RCC_MP_GCR_BOOT_MCU BIT(0) + +/* RCC_MP_APRSTCR register fields */ +#define RCC_MP_APRSTCR_RDCTLEN BIT(0) +#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) +#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 + +/* RCC_MP_APRSTSR register fields */ +#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) +#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 + +/* RCC_BDCR register fields */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_LSECSSD BIT(9) +#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) +#define RCC_BDCR_RTCSRC_SHIFT 16 +#define RCC_BDCR_RTCCKEN BIT(20) +#define RCC_BDCR_VSWRST BIT(31) + +/* RCC_RDLSICR register fields */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) +#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) +#define RCC_RDLSICR_MRD_SHIFT 16 +#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) +#define RCC_RDLSICR_EADLY_SHIFT 24 +#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) +#define RCC_RDLSICR_SPARE_SHIFT 27 + +/* RCC_APB4RSTSETR register fields */ +#define RCC_APB4RSTSETR_LTDCRST BIT(0) +#define RCC_APB4RSTSETR_DSIRST BIT(4) +#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTSETR_USBPHYRST BIT(16) + +/* RCC_APB4RSTCLRR register fields */ +#define RCC_APB4RSTCLRR_LTDCRST BIT(0) +#define RCC_APB4RSTCLRR_DSIRST BIT(4) +#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) + +/* RCC_APB5RSTSETR register fields */ +#define RCC_APB5RSTSETR_SPI6RST BIT(0) +#define RCC_APB5RSTSETR_I2C4RST BIT(2) +#define RCC_APB5RSTSETR_I2C6RST BIT(3) +#define RCC_APB5RSTSETR_USART1RST BIT(4) +#define RCC_APB5RSTSETR_STGENRST BIT(20) + +/* RCC_APB5RSTCLRR register fields */ +#define RCC_APB5RSTCLRR_SPI6RST BIT(0) +#define RCC_APB5RSTCLRR_I2C4RST BIT(2) +#define RCC_APB5RSTCLRR_I2C6RST BIT(3) +#define RCC_APB5RSTCLRR_USART1RST BIT(4) +#define RCC_APB5RSTCLRR_STGENRST BIT(20) + +/* RCC_AHB5RSTSETR register fields */ +#define RCC_AHB5RSTSETR_GPIOZRST BIT(0) +#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + +/* RCC_AHB5RSTCLRR register fields */ +#define RCC_AHB5RSTCLRR_GPIOZRST BIT(0) +#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) +#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) +#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) +#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) + +/* RCC_AHB6RSTSETR register fields */ +#define RCC_AHB6RSTSETR_GPURST BIT(5) +#define RCC_AHB6RSTSETR_ETHMACRST BIT(10) +#define RCC_AHB6RSTSETR_FMCRST BIT(12) +#define RCC_AHB6RSTSETR_QSPIRST BIT(14) +#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTSETR_CRC1RST BIT(20) +#define RCC_AHB6RSTSETR_USBHRST BIT(24) + +/* RCC_AHB6RSTCLRR register fields */ +#define RCC_AHB6RSTCLRR_ETHMACRST BIT(10) +#define RCC_AHB6RSTCLRR_FMCRST BIT(12) +#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) +#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) +#define RCC_AHB6RSTCLRR_USBHRST BIT(24) + +/* RCC_TZAHB6RSTSETR register fields */ +#define RCC_TZAHB6RSTSETR_MDMARST BIT(0) + +/* RCC_TZAHB6RSTCLRR register fields */ +#define RCC_TZAHB6RSTCLRR_MDMARST BIT(0) + +/* RCC_MP_APB4ENSETR register fields */ +#define RCC_MP_APB4ENSETR_LTDCEN BIT(0) +#define RCC_MP_APB4ENSETR_DSIEN BIT(4) +#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MP_APB4ENCLRR register fields */ +#define RCC_MP_APB4ENCLRR_LTDCEN BIT(0) +#define RCC_MP_APB4ENCLRR_DSIEN BIT(4) +#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MP_APB5ENSETR register fields */ +#define RCC_MP_APB5ENSETR_SPI6EN BIT(0) +#define RCC_MP_APB5ENSETR_I2C4EN BIT(2) +#define RCC_MP_APB5ENSETR_I2C6EN BIT(3) +#define RCC_MP_APB5ENSETR_USART1EN BIT(4) +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENSETR_TZC1EN BIT(11) +#define RCC_MP_APB5ENSETR_TZC2EN BIT(12) +#define RCC_MP_APB5ENSETR_TZPCEN BIT(13) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENSETR_BSECEN BIT(16) +#define RCC_MP_APB5ENSETR_STGENEN BIT(20) + +/* RCC_MP_APB5ENCLRR register fields */ +#define RCC_MP_APB5ENCLRR_SPI6EN BIT(0) +#define RCC_MP_APB5ENCLRR_I2C4EN BIT(2) +#define RCC_MP_APB5ENCLRR_I2C6EN BIT(3) +#define RCC_MP_APB5ENCLRR_USART1EN BIT(4) +#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENCLRR_TZC1EN BIT(11) +#define RCC_MP_APB5ENCLRR_TZC2EN BIT(12) +#define RCC_MP_APB5ENCLRR_TZPCEN BIT(13) +#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MP_APB5ENCLRR_STGENEN BIT(20) + +/* RCC_MP_AHB5ENSETR register fields */ +#define RCC_MP_AHB5ENSETR_GPIOZEN BIT(0) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) + +/* RCC_MP_AHB5ENCLRR register fields */ +#define RCC_MP_AHB5ENCLRR_GPIOZEN BIT(0) +#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) + +/* RCC_MP_AHB6ENSETR register fields */ +#define RCC_MP_AHB6ENSETR_MDMAEN BIT(0) +#define RCC_MP_AHB6ENSETR_GPUEN BIT(5) +#define RCC_MP_AHB6ENSETR_ETHCKEN BIT(7) +#define RCC_MP_AHB6ENSETR_ETHTXEN BIT(8) +#define RCC_MP_AHB6ENSETR_ETHRXEN BIT(9) +#define RCC_MP_AHB6ENSETR_ETHMACEN BIT(10) +#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) + +/* RCC_MP_AHB6ENCLRR register fields */ +#define RCC_MP_AHB6ENCLRR_MDMAEN BIT(0) +#define RCC_MP_AHB6ENCLRR_GPUEN BIT(5) +#define RCC_MP_AHB6ENCLRR_ETHCKEN BIT(7) +#define RCC_MP_AHB6ENCLRR_ETHTXEN BIT(8) +#define RCC_MP_AHB6ENCLRR_ETHRXEN BIT(9) +#define RCC_MP_AHB6ENCLRR_ETHMACEN BIT(10) +#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) + +/* RCC_MP_TZAHB6ENSETR register fields */ +#define RCC_MP_TZAHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_TZAHB6ENCLRR register fields */ +#define RCC_MP_TZAHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MC_APB4ENSETR register fields */ +#define RCC_MC_APB4ENSETR_LTDCEN BIT(0) +#define RCC_MC_APB4ENSETR_DSIEN BIT(4) +#define RCC_MC_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MC_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MC_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MC_APB4ENCLRR register fields */ +#define RCC_MC_APB4ENCLRR_LTDCEN BIT(0) +#define RCC_MC_APB4ENCLRR_DSIEN BIT(4) +#define RCC_MC_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MC_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MC_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MC_APB5ENSETR register fields */ +#define RCC_MC_APB5ENSETR_SPI6EN BIT(0) +#define RCC_MC_APB5ENSETR_I2C4EN BIT(2) +#define RCC_MC_APB5ENSETR_I2C6EN BIT(3) +#define RCC_MC_APB5ENSETR_USART1EN BIT(4) +#define RCC_MC_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MC_APB5ENSETR_TZC1EN BIT(11) +#define RCC_MC_APB5ENSETR_TZC2EN BIT(12) +#define RCC_MC_APB5ENSETR_TZPCEN BIT(13) +#define RCC_MC_APB5ENSETR_BSECEN BIT(16) +#define RCC_MC_APB5ENSETR_STGENEN BIT(20) + +/* RCC_MC_APB5ENCLRR register fields */ +#define RCC_MC_APB5ENCLRR_SPI6EN BIT(0) +#define RCC_MC_APB5ENCLRR_I2C4EN BIT(2) +#define RCC_MC_APB5ENCLRR_I2C6EN BIT(3) +#define RCC_MC_APB5ENCLRR_USART1EN BIT(4) +#define RCC_MC_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MC_APB5ENCLRR_TZC1EN BIT(11) +#define RCC_MC_APB5ENCLRR_TZC2EN BIT(12) +#define RCC_MC_APB5ENCLRR_TZPCEN BIT(13) +#define RCC_MC_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MC_APB5ENCLRR_STGENEN BIT(20) + +/* RCC_MC_AHB5ENSETR register fields */ +#define RCC_MC_AHB5ENSETR_GPIOZEN BIT(0) +#define RCC_MC_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MC_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MC_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MC_AHB5ENSETR_BKPSRAMEN BIT(8) + +/* RCC_MC_AHB5ENCLRR register fields */ +#define RCC_MC_AHB5ENCLRR_GPIOZEN BIT(0) +#define RCC_MC_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MC_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MC_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MC_AHB5ENCLRR_BKPSRAMEN BIT(8) + +/* RCC_MC_AHB6ENSETR register fields */ +#define RCC_MC_AHB6ENSETR_MDMAEN BIT(0) +#define RCC_MC_AHB6ENSETR_GPUEN BIT(5) +#define RCC_MC_AHB6ENSETR_ETHCKEN BIT(7) +#define RCC_MC_AHB6ENSETR_ETHTXEN BIT(8) +#define RCC_MC_AHB6ENSETR_ETHRXEN BIT(9) +#define RCC_MC_AHB6ENSETR_ETHMACEN BIT(10) +#define RCC_MC_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MC_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MC_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MC_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MC_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MC_AHB6ENSETR_USBHEN BIT(24) + +/* RCC_MC_AHB6ENCLRR register fields */ +#define RCC_MC_AHB6ENCLRR_MDMAEN BIT(0) +#define RCC_MC_AHB6ENCLRR_GPUEN BIT(5) +#define RCC_MC_AHB6ENCLRR_ETHCKEN BIT(7) +#define RCC_MC_AHB6ENCLRR_ETHTXEN BIT(8) +#define RCC_MC_AHB6ENCLRR_ETHRXEN BIT(9) +#define RCC_MC_AHB6ENCLRR_ETHMACEN BIT(10) +#define RCC_MC_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MC_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MC_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MC_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MC_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MC_AHB6ENCLRR_USBHEN BIT(24) + +/* RCC_MP_APB4LPENSETR register fields */ +#define RCC_MP_APB4LPENSETR_LTDCLPEN BIT(0) +#define RCC_MP_APB4LPENSETR_DSILPEN BIT(4) +#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB4LPENCLRR register fields */ +#define RCC_MP_APB4LPENCLRR_LTDCLPEN BIT(0) +#define RCC_MP_APB4LPENCLRR_DSILPEN BIT(4) +#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB5LPENSETR register fields */ +#define RCC_MP_APB5LPENSETR_SPI6LPEN BIT(0) +#define RCC_MP_APB5LPENSETR_I2C4LPEN BIT(2) +#define RCC_MP_APB5LPENSETR_I2C6LPEN BIT(3) +#define RCC_MP_APB5LPENSETR_USART1LPEN BIT(4) +#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENSETR_TZC1LPEN BIT(11) +#define RCC_MP_APB5LPENSETR_TZC2LPEN BIT(12) +#define RCC_MP_APB5LPENSETR_TZPCLPEN BIT(13) +#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENSETR_STGENLPEN BIT(20) +#define RCC_MP_APB5LPENSETR_STGENSTPEN BIT(21) + +/* RCC_MP_APB5LPENCLRR register fields */ +#define RCC_MP_APB5LPENCLRR_SPI6LPEN BIT(0) +#define RCC_MP_APB5LPENCLRR_I2C4LPEN BIT(2) +#define RCC_MP_APB5LPENCLRR_I2C6LPEN BIT(3) +#define RCC_MP_APB5LPENCLRR_USART1LPEN BIT(4) +#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENCLRR_TZC1LPEN BIT(11) +#define RCC_MP_APB5LPENCLRR_TZC2LPEN BIT(12) +#define RCC_MP_APB5LPENCLRR_TZPCLPEN BIT(13) +#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENCLRR_STGENLPEN BIT(20) +#define RCC_MP_APB5LPENCLRR_STGENSTPEN BIT(21) + +/* RCC_MP_AHB5LPENSETR register fields */ +#define RCC_MP_AHB5LPENSETR_GPIOZLPEN BIT(0) +#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB5LPENCLRR register fields */ +#define RCC_MP_AHB5LPENCLRR_GPIOZLPEN BIT(0) +#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB6LPENSETR register fields */ +#define RCC_MP_AHB6LPENSETR_MDMALPEN BIT(0) +#define RCC_MP_AHB6LPENSETR_GPULPEN BIT(5) +#define RCC_MP_AHB6LPENSETR_ETHCKLPEN BIT(7) +#define RCC_MP_AHB6LPENSETR_ETHTXLPEN BIT(8) +#define RCC_MP_AHB6LPENSETR_ETHRXLPEN BIT(9) +#define RCC_MP_AHB6LPENSETR_ETHMACLPEN BIT(10) +#define RCC_MP_AHB6LPENSETR_ETHSTPEN BIT(11) +#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) + +/* RCC_MP_AHB6LPENCLRR register fields */ +#define RCC_MP_AHB6LPENCLRR_MDMALPEN BIT(0) +#define RCC_MP_AHB6LPENCLRR_GPULPEN BIT(5) +#define RCC_MP_AHB6LPENCLRR_ETHCKLPEN BIT(7) +#define RCC_MP_AHB6LPENCLRR_ETHTXLPEN BIT(8) +#define RCC_MP_AHB6LPENCLRR_ETHRXLPEN BIT(9) +#define RCC_MP_AHB6LPENCLRR_ETHMACLPEN BIT(10) +#define RCC_MP_AHB6LPENCLRR_ETHSTPEN BIT(11) +#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) + +/* RCC_MP_TZAHB6LPENSETR register fields */ +#define RCC_MP_TZAHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_TZAHB6LPENCLRR register fields */ +#define RCC_MP_TZAHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MC_APB4LPENSETR register fields */ +#define RCC_MC_APB4LPENSETR_LTDCLPEN BIT(0) +#define RCC_MC_APB4LPENSETR_DSILPEN BIT(4) +#define RCC_MC_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MC_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MC_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MC_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MC_APB4LPENCLRR register fields */ +#define RCC_MC_APB4LPENCLRR_LTDCLPEN BIT(0) +#define RCC_MC_APB4LPENCLRR_DSILPEN BIT(4) +#define RCC_MC_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MC_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MC_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MC_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MC_APB5LPENSETR register fields */ +#define RCC_MC_APB5LPENSETR_SPI6LPEN BIT(0) +#define RCC_MC_APB5LPENSETR_I2C4LPEN BIT(2) +#define RCC_MC_APB5LPENSETR_I2C6LPEN BIT(3) +#define RCC_MC_APB5LPENSETR_USART1LPEN BIT(4) +#define RCC_MC_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MC_APB5LPENSETR_TZC1LPEN BIT(11) +#define RCC_MC_APB5LPENSETR_TZC2LPEN BIT(12) +#define RCC_MC_APB5LPENSETR_TZPCLPEN BIT(13) +#define RCC_MC_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MC_APB5LPENSETR_STGENLPEN BIT(20) +#define RCC_MC_APB5LPENSETR_STGENSTPEN BIT(21) + +/* RCC_MC_APB5LPENCLRR register fields */ +#define RCC_MC_APB5LPENCLRR_SPI6LPEN BIT(0) +#define RCC_MC_APB5LPENCLRR_I2C4LPEN BIT(2) +#define RCC_MC_APB5LPENCLRR_I2C6LPEN BIT(3) +#define RCC_MC_APB5LPENCLRR_USART1LPEN BIT(4) +#define RCC_MC_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MC_APB5LPENCLRR_TZC1LPEN BIT(11) +#define RCC_MC_APB5LPENCLRR_TZC2LPEN BIT(12) +#define RCC_MC_APB5LPENCLRR_TZPCLPEN BIT(13) +#define RCC_MC_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MC_APB5LPENCLRR_STGENLPEN BIT(20) +#define RCC_MC_APB5LPENCLRR_STGENSTPEN BIT(21) + +/* RCC_MC_AHB5LPENSETR register fields */ +#define RCC_MC_AHB5LPENSETR_GPIOZLPEN BIT(0) +#define RCC_MC_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MC_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MC_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MC_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MC_AHB5LPENCLRR register fields */ +#define RCC_MC_AHB5LPENCLRR_GPIOZLPEN BIT(0) +#define RCC_MC_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MC_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MC_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MC_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MC_AHB6LPENSETR register fields */ +#define RCC_MC_AHB6LPENSETR_MDMALPEN BIT(0) +#define RCC_MC_AHB6LPENSETR_GPULPEN BIT(5) +#define RCC_MC_AHB6LPENSETR_ETHCKLPEN BIT(7) +#define RCC_MC_AHB6LPENSETR_ETHTXLPEN BIT(8) +#define RCC_MC_AHB6LPENSETR_ETHRXLPEN BIT(9) +#define RCC_MC_AHB6LPENSETR_ETHMACLPEN BIT(10) +#define RCC_MC_AHB6LPENSETR_ETHSTPEN BIT(11) +#define RCC_MC_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MC_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MC_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MC_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MC_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MC_AHB6LPENSETR_USBHLPEN BIT(24) + +/* RCC_MC_AHB6LPENCLRR register fields */ +#define RCC_MC_AHB6LPENCLRR_MDMALPEN BIT(0) +#define RCC_MC_AHB6LPENCLRR_GPULPEN BIT(5) +#define RCC_MC_AHB6LPENCLRR_ETHCKLPEN BIT(7) +#define RCC_MC_AHB6LPENCLRR_ETHTXLPEN BIT(8) +#define RCC_MC_AHB6LPENCLRR_ETHRXLPEN BIT(9) +#define RCC_MC_AHB6LPENCLRR_ETHMACLPEN BIT(10) +#define RCC_MC_AHB6LPENCLRR_ETHSTPEN BIT(11) +#define RCC_MC_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MC_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MC_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MC_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MC_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MC_AHB6LPENCLRR_USBHLPEN BIT(24) + +/* RCC_BR_RSTSCLRR register fields */ +#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) +#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) +#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) +#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_BR_RSTSCLRR_MCSYSRSTF BIT(7) +#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_BR_RSTSCLRR_MPUP1RSTF BIT(14) + +/* RCC_MP_GRSTCSETR register fields */ +#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MCURST BIT(1) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) +#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5) + +/* RCC_MP_RSTSCLRR register fields */ +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_MCSYSRSTF BIT(7) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSCLRR_MPUP1RSTF BIT(14) +#define RCC_MP_RSTSCLRR_SPARE BIT(15) + +/* RCC_MP_IWDGFZSETR register fields */ +#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) + +/* RCC_MP_IWDGFZCLRR register fields */ +#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) + +/* RCC_MP_CIER register fields */ +#define RCC_MP_CIER_LSIRDYIE BIT(0) +#define RCC_MP_CIER_LSERDYIE BIT(1) +#define RCC_MP_CIER_HSIRDYIE BIT(2) +#define RCC_MP_CIER_HSERDYIE BIT(3) +#define RCC_MP_CIER_CSIRDYIE BIT(4) +#define RCC_MP_CIER_PLL1DYIE BIT(8) +#define RCC_MP_CIER_PLL2DYIE BIT(9) +#define RCC_MP_CIER_PLL3DYIE BIT(10) +#define RCC_MP_CIER_PLL4DYIE BIT(11) +#define RCC_MP_CIER_LSECSSIE BIT(16) +#define RCC_MP_CIER_WKUPIE BIT(20) + +/* RCC_MP_CIFR register fields */ +#define RCC_MP_CIFR_MASK U(0x110F1F) +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) +#define RCC_MP_CIFR_LSECSSF BIT(16) +#define RCC_MP_CIFR_WKUPF BIT(20) + +/* RCC_PWRLPDLYCR register fields */ +#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 +#define RCC_PWRLPDLYCR_MCTMPSKP BIT(24) + +/* RCC_MP_RSTSSETR register fields */ +#define RCC_MP_RSTSSETR_PORRSTF BIT(0) +#define RCC_MP_RSTSSETR_BORRSTF BIT(1) +#define RCC_MP_RSTSSETR_PADRSTF BIT(2) +#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) +#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSSETR_MCSYSRSTF BIT(7) +#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSSETR_MPUP1RSTF BIT(14) +#define RCC_MP_RSTSSETR_SPARE BIT(15) + +/* RCC_MCO1CFGR register fields */ +#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) +#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 +#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) +#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 +#define RCC_MCO1CFGR_MCO1ON BIT(12) + +/* RCC_MCO2CFGR register fields */ +#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) +#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 +#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) +#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 +#define RCC_MCO2CFGR_MCO2ON BIT(12) + +/* RCC_OCRDYR register fields */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) +#define RCC_OCRDYR_MPUCKRDY BIT(23) +#define RCC_OCRDYR_AXICKRDY BIT(24) +#define RCC_OCRDYR_CKREST BIT(25) + +/* RCC_DBGCFGR register fields */ +#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) +#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 +#define RCC_DBGCFGR_DBGCKEN BIT(8) +#define RCC_DBGCFGR_TRACECKEN BIT(9) +#define RCC_DBGCFGR_DBGRST BIT(12) + +/* RCC_RCK3SELR register fields */ +#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) +#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 +#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) + +/* RCC_RCK4SELR register fields */ +#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) +#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 +#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) + +/* RCC_TIMG1PRER register fields */ +#define RCC_TIMG1PRER_TIMG1PRE BIT(0) +#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) + +/* RCC_TIMG2PRER register fields */ +#define RCC_TIMG2PRER_TIMG2PRE BIT(0) +#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) + +/* RCC_MCUDIVR register fields */ +#define RCC_MCUDIVR_MCUDIV_MASK GENMASK(3, 0) +#define RCC_MCUDIVR_MCUDIV_SHIFT 0 +#define RCC_MCUDIVR_MCUDIVRDY BIT(31) + +/* RCC_APB1DIVR register fields */ +#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) +#define RCC_APB1DIVR_APB1DIV_SHIFT 0 +#define RCC_APB1DIVR_APB1DIVRDY BIT(31) + +/* RCC_APB2DIVR register fields */ +#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) +#define RCC_APB2DIVR_APB2DIV_SHIFT 0 +#define RCC_APB2DIVR_APB2DIVRDY BIT(31) + +/* RCC_APB3DIVR register fields */ +#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) +#define RCC_APB3DIVR_APB3DIV_SHIFT 0 +#define RCC_APB3DIVR_APB3DIVRDY BIT(31) + +/* RCC_PLL3CR register fields */ +#define RCC_PLL3CR_PLLON BIT(0) +#define RCC_PLL3CR_PLL3RDY BIT(1) +#define RCC_PLL3CR_SSCG_CTRL BIT(2) +#define RCC_PLL3CR_DIVPEN BIT(4) +#define RCC_PLL3CR_DIVQEN BIT(5) +#define RCC_PLL3CR_DIVREN BIT(6) + +/* RCC_PLL3CFGR1 register fields */ +#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL3CFGR1_DIVN_SHIFT 0 +#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) +#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 +#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL3CFGR2 register fields */ +#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL3CFGR2_DIVP_SHIFT 0 +#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL3CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL3FRACR register fields */ +#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL3FRACR_FRACV_SHIFT 3 +#define RCC_PLL3FRACR_FRACLE BIT(16) + +/* RCC_PLL3CSGR register fields */ +#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL3CSGR_SSCG_MODE BIT(15) +#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL4CR register fields */ +#define RCC_PLL4CR_PLLON BIT(0) +#define RCC_PLL4CR_PLL4RDY BIT(1) +#define RCC_PLL4CR_SSCG_CTRL BIT(2) +#define RCC_PLL4CR_DIVPEN BIT(4) +#define RCC_PLL4CR_DIVQEN BIT(5) +#define RCC_PLL4CR_DIVREN BIT(6) + +/* RCC_PLL4CFGR1 register fields */ +#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL4CFGR1_DIVN_SHIFT 0 +#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) +#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 +#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL4CFGR2 register fields */ +#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL4CFGR2_DIVP_SHIFT 0 +#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL4CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL4FRACR register fields */ +#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL4FRACR_FRACV_SHIFT 3 +#define RCC_PLL4FRACR_FRACLE BIT(16) + +/* RCC_PLL4CSGR register fields */ +#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL4CSGR_SSCG_MODE BIT(15) +#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C35CKSELR register fields */ +#define RCC_I2C35CKSELR_I2C35SRC_MASK GENMASK(2, 0) +#define RCC_I2C35CKSELR_I2C35SRC_SHIFT 0 + +/* RCC_SAI1CKSELR register fields */ +#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) +#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 + +/* RCC_SAI2CKSELR register fields */ +#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) +#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 + +/* RCC_SAI3CKSELR register fields */ +#define RCC_SAI3CKSELR_SAI3SRC_MASK GENMASK(2, 0) +#define RCC_SAI3CKSELR_SAI3SRC_SHIFT 0 + +/* RCC_SAI4CKSELR register fields */ +#define RCC_SAI4CKSELR_SAI4SRC_MASK GENMASK(2, 0) +#define RCC_SAI4CKSELR_SAI4SRC_SHIFT 0 + +/* RCC_SPI2S1CKSELR register fields */ +#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 + +/* RCC_SPI2S23CKSELR register fields */ +#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 + +/* RCC_SPI45CKSELR register fields */ +#define RCC_SPI45CKSELR_SPI45SRC_MASK GENMASK(2, 0) +#define RCC_SPI45CKSELR_SPI45SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART24CKSELR register fields */ +#define RCC_UART24CKSELR_HSI 0x00000002 +#define RCC_UART24CKSELR_UART24SRC_MASK GENMASK(2, 0) +#define RCC_UART24CKSELR_UART24SRC_SHIFT 0 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC12SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC12SRC_SHIFT 0 + +/* RCC_SDMMC3CKSELR register fields */ +#define RCC_SDMMC3CKSELR_SDMMC3SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC3CKSELR_SDMMC3SRC_SHIFT 0 + +/* RCC_ETHCKSELR register fields */ +#define RCC_ETHCKSELR_ETHSRC_MASK GENMASK(1, 0) +#define RCC_ETHCKSELR_ETHSRC_SHIFT 0 +#define RCC_ETHCKSELR_ETHPTPDIV_MASK GENMASK(7, 4) +#define RCC_ETHCKSELR_ETHPTPDIV_SHIFT 4 + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_FDCANCKSELR register fields */ +#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) +#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 + +/* RCC_SPDIFCKSELR register fields */ +#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) +#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 + +/* RCC_CECCKSELR register fields */ +#define RCC_CECCKSELR_CECSRC_MASK GENMASK(1, 0) +#define RCC_CECCKSELR_CECSRC_SHIFT 0 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 +#define RCC_USBCKSELR_USBOSRC BIT(4) +#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) +#define RCC_USBCKSELR_USBOSRC_SHIFT 4 + +/* RCC_RNG2CKSELR register fields */ +#define RCC_RNG2CKSELR_RNG2SRC_MASK GENMASK(1, 0) +#define RCC_RNG2CKSELR_RNG2SRC_SHIFT 0 + +/* RCC_DSICKSELR register fields */ +#define RCC_DSICKSELR_DSISRC BIT(0) + +/* RCC_ADCCKSELR register fields */ +#define RCC_ADCCKSELR_ADCSRC_MASK GENMASK(1, 0) +#define RCC_ADCCKSELR_ADCSRC_SHIFT 0 + +/* RCC_LPTIM45CKSELR register fields */ +#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 + +/* RCC_LPTIM23CKSELR register fields */ +#define RCC_LPTIM23CKSELR_LPTIM23SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM23CKSELR_LPTIM23SRC_SHIFT 0 + +/* RCC_LPTIM1CKSELR register fields */ +#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 + +/* RCC_APB1RSTSETR register fields */ +#define RCC_APB1RSTSETR_TIM2RST BIT(0) +#define RCC_APB1RSTSETR_TIM3RST BIT(1) +#define RCC_APB1RSTSETR_TIM4RST BIT(2) +#define RCC_APB1RSTSETR_TIM5RST BIT(3) +#define RCC_APB1RSTSETR_TIM6RST BIT(4) +#define RCC_APB1RSTSETR_TIM7RST BIT(5) +#define RCC_APB1RSTSETR_TIM12RST BIT(6) +#define RCC_APB1RSTSETR_TIM13RST BIT(7) +#define RCC_APB1RSTSETR_TIM14RST BIT(8) +#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) +#define RCC_APB1RSTSETR_SPI2RST BIT(11) +#define RCC_APB1RSTSETR_SPI3RST BIT(12) +#define RCC_APB1RSTSETR_USART2RST BIT(14) +#define RCC_APB1RSTSETR_USART3RST BIT(15) +#define RCC_APB1RSTSETR_UART4RST BIT(16) +#define RCC_APB1RSTSETR_UART5RST BIT(17) +#define RCC_APB1RSTSETR_UART7RST BIT(18) +#define RCC_APB1RSTSETR_UART8RST BIT(19) +#define RCC_APB1RSTSETR_I2C1RST BIT(21) +#define RCC_APB1RSTSETR_I2C2RST BIT(22) +#define RCC_APB1RSTSETR_I2C3RST BIT(23) +#define RCC_APB1RSTSETR_I2C5RST BIT(24) +#define RCC_APB1RSTSETR_SPDIFRST BIT(26) +#define RCC_APB1RSTSETR_CECRST BIT(27) +#define RCC_APB1RSTSETR_DAC12RST BIT(29) +#define RCC_APB1RSTSETR_MDIOSRST BIT(31) + +/* RCC_APB1RSTCLRR register fields */ +#define RCC_APB1RSTCLRR_TIM2RST BIT(0) +#define RCC_APB1RSTCLRR_TIM3RST BIT(1) +#define RCC_APB1RSTCLRR_TIM4RST BIT(2) +#define RCC_APB1RSTCLRR_TIM5RST BIT(3) +#define RCC_APB1RSTCLRR_TIM6RST BIT(4) +#define RCC_APB1RSTCLRR_TIM7RST BIT(5) +#define RCC_APB1RSTCLRR_TIM12RST BIT(6) +#define RCC_APB1RSTCLRR_TIM13RST BIT(7) +#define RCC_APB1RSTCLRR_TIM14RST BIT(8) +#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) +#define RCC_APB1RSTCLRR_SPI2RST BIT(11) +#define RCC_APB1RSTCLRR_SPI3RST BIT(12) +#define RCC_APB1RSTCLRR_USART2RST BIT(14) +#define RCC_APB1RSTCLRR_USART3RST BIT(15) +#define RCC_APB1RSTCLRR_UART4RST BIT(16) +#define RCC_APB1RSTCLRR_UART5RST BIT(17) +#define RCC_APB1RSTCLRR_UART7RST BIT(18) +#define RCC_APB1RSTCLRR_UART8RST BIT(19) +#define RCC_APB1RSTCLRR_I2C1RST BIT(21) +#define RCC_APB1RSTCLRR_I2C2RST BIT(22) +#define RCC_APB1RSTCLRR_I2C3RST BIT(23) +#define RCC_APB1RSTCLRR_I2C5RST BIT(24) +#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) +#define RCC_APB1RSTCLRR_CECRST BIT(27) +#define RCC_APB1RSTCLRR_DAC12RST BIT(29) +#define RCC_APB1RSTCLRR_MDIOSRST BIT(31) + +/* RCC_APB2RSTSETR register fields */ +#define RCC_APB2RSTSETR_TIM1RST BIT(0) +#define RCC_APB2RSTSETR_TIM8RST BIT(1) +#define RCC_APB2RSTSETR_TIM15RST BIT(2) +#define RCC_APB2RSTSETR_TIM16RST BIT(3) +#define RCC_APB2RSTSETR_TIM17RST BIT(4) +#define RCC_APB2RSTSETR_SPI1RST BIT(8) +#define RCC_APB2RSTSETR_SPI4RST BIT(9) +#define RCC_APB2RSTSETR_SPI5RST BIT(10) +#define RCC_APB2RSTSETR_USART6RST BIT(13) +#define RCC_APB2RSTSETR_SAI1RST BIT(16) +#define RCC_APB2RSTSETR_SAI2RST BIT(17) +#define RCC_APB2RSTSETR_SAI3RST BIT(18) +#define RCC_APB2RSTSETR_DFSDMRST BIT(20) +#define RCC_APB2RSTSETR_FDCANRST BIT(24) + +/* RCC_APB2RSTCLRR register fields */ +#define RCC_APB2RSTCLRR_TIM1RST BIT(0) +#define RCC_APB2RSTCLRR_TIM8RST BIT(1) +#define RCC_APB2RSTCLRR_TIM15RST BIT(2) +#define RCC_APB2RSTCLRR_TIM16RST BIT(3) +#define RCC_APB2RSTCLRR_TIM17RST BIT(4) +#define RCC_APB2RSTCLRR_SPI1RST BIT(8) +#define RCC_APB2RSTCLRR_SPI4RST BIT(9) +#define RCC_APB2RSTCLRR_SPI5RST BIT(10) +#define RCC_APB2RSTCLRR_USART6RST BIT(13) +#define RCC_APB2RSTCLRR_SAI1RST BIT(16) +#define RCC_APB2RSTCLRR_SAI2RST BIT(17) +#define RCC_APB2RSTCLRR_SAI3RST BIT(18) +#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) +#define RCC_APB2RSTCLRR_FDCANRST BIT(24) + +/* RCC_APB3RSTSETR register fields */ +#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) +#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) +#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) +#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) +#define RCC_APB3RSTSETR_SAI4RST BIT(8) +#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) +#define RCC_APB3RSTSETR_VREFRST BIT(13) +#define RCC_APB3RSTSETR_TMPSENSRST BIT(16) +#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) + +/* RCC_APB3RSTCLRR register fields */ +#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) +#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) +#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) +#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) +#define RCC_APB3RSTCLRR_SAI4RST BIT(8) +#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) +#define RCC_APB3RSTCLRR_VREFRST BIT(13) +#define RCC_APB3RSTCLRR_TMPSENSRST BIT(16) +#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) + +/* RCC_AHB2RSTSETR register fields */ +#define RCC_AHB2RSTSETR_DMA1RST BIT(0) +#define RCC_AHB2RSTSETR_DMA2RST BIT(1) +#define RCC_AHB2RSTSETR_DMAMUXRST BIT(2) +#define RCC_AHB2RSTSETR_ADC12RST BIT(5) +#define RCC_AHB2RSTSETR_USBORST BIT(8) +#define RCC_AHB2RSTSETR_SDMMC3RST BIT(16) + +/* RCC_AHB2RSTCLRR register fields */ +#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) +#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) +#define RCC_AHB2RSTCLRR_DMAMUXRST BIT(2) +#define RCC_AHB2RSTCLRR_ADC12RST BIT(5) +#define RCC_AHB2RSTCLRR_USBORST BIT(8) +#define RCC_AHB2RSTCLRR_SDMMC3RST BIT(16) + +/* RCC_AHB3RSTSETR register fields */ +#define RCC_AHB3RSTSETR_DCMIRST BIT(0) +#define RCC_AHB3RSTSETR_CRYP2RST BIT(4) +#define RCC_AHB3RSTSETR_HASH2RST BIT(5) +#define RCC_AHB3RSTSETR_RNG2RST BIT(6) +#define RCC_AHB3RSTSETR_CRC2RST BIT(7) +#define RCC_AHB3RSTSETR_HSEMRST BIT(11) +#define RCC_AHB3RSTSETR_IPCCRST BIT(12) + +/* RCC_AHB3RSTCLRR register fields */ +#define RCC_AHB3RSTCLRR_DCMIRST BIT(0) +#define RCC_AHB3RSTCLRR_CRYP2RST BIT(4) +#define RCC_AHB3RSTCLRR_HASH2RST BIT(5) +#define RCC_AHB3RSTCLRR_RNG2RST BIT(6) +#define RCC_AHB3RSTCLRR_CRC2RST BIT(7) +#define RCC_AHB3RSTCLRR_HSEMRST BIT(11) +#define RCC_AHB3RSTCLRR_IPCCRST BIT(12) + +/* RCC_AHB4RSTSETR register fields */ +#define RCC_AHB4RSTSETR_GPIOARST BIT(0) +#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) +#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) +#define RCC_AHB4RSTSETR_GPIODRST BIT(3) +#define RCC_AHB4RSTSETR_GPIOERST BIT(4) +#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) +#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) +#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) +#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) +#define RCC_AHB4RSTSETR_GPIOJRST BIT(9) +#define RCC_AHB4RSTSETR_GPIOKRST BIT(10) + +/* RCC_AHB4RSTCLRR register fields */ +#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) +#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) +#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) +#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) +#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) +#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) +#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) +#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) +#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) +#define RCC_AHB4RSTCLRR_GPIOJRST BIT(9) +#define RCC_AHB4RSTCLRR_GPIOKRST BIT(10) + +/* RCC_MP_APB1ENSETR register fields */ +#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MP_APB1ENSETR_TIM12EN BIT(6) +#define RCC_MP_APB1ENSETR_TIM13EN BIT(7) +#define RCC_MP_APB1ENSETR_TIM14EN BIT(8) +#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MP_APB1ENSETR_USART2EN BIT(14) +#define RCC_MP_APB1ENSETR_USART3EN BIT(15) +#define RCC_MP_APB1ENSETR_UART4EN BIT(16) +#define RCC_MP_APB1ENSETR_UART5EN BIT(17) +#define RCC_MP_APB1ENSETR_UART7EN BIT(18) +#define RCC_MP_APB1ENSETR_UART8EN BIT(19) +#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MP_APB1ENSETR_I2C3EN BIT(23) +#define RCC_MP_APB1ENSETR_I2C5EN BIT(24) +#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) +#define RCC_MP_APB1ENSETR_CECEN BIT(27) +#define RCC_MP_APB1ENSETR_DAC12EN BIT(29) +#define RCC_MP_APB1ENSETR_MDIOSEN BIT(31) + +/* RCC_MP_APB1ENCLRR register fields */ +#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MP_APB1ENCLRR_TIM12EN BIT(6) +#define RCC_MP_APB1ENCLRR_TIM13EN BIT(7) +#define RCC_MP_APB1ENCLRR_TIM14EN BIT(8) +#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MP_APB1ENCLRR_USART2EN BIT(14) +#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MP_APB1ENCLRR_I2C3EN BIT(23) +#define RCC_MP_APB1ENCLRR_I2C5EN BIT(24) +#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) +#define RCC_MP_APB1ENCLRR_CECEN BIT(27) +#define RCC_MP_APB1ENCLRR_DAC12EN BIT(29) +#define RCC_MP_APB1ENCLRR_MDIOSEN BIT(31) + +/* RCC_MP_APB2ENSETR register fields */ +#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MP_APB2ENSETR_TIM15EN BIT(2) +#define RCC_MP_APB2ENSETR_TIM16EN BIT(3) +#define RCC_MP_APB2ENSETR_TIM17EN BIT(4) +#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MP_APB2ENSETR_SPI4EN BIT(9) +#define RCC_MP_APB2ENSETR_SPI5EN BIT(10) +#define RCC_MP_APB2ENSETR_USART6EN BIT(13) +#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MP_APB2ENSETR_SAI3EN BIT(18) +#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MP_APB2ENCLRR register fields */ +#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MP_APB2ENCLRR_TIM15EN BIT(2) +#define RCC_MP_APB2ENCLRR_TIM16EN BIT(3) +#define RCC_MP_APB2ENCLRR_TIM17EN BIT(4) +#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MP_APB2ENCLRR_SPI4EN BIT(9) +#define RCC_MP_APB2ENCLRR_SPI5EN BIT(10) +#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MP_APB2ENCLRR_SAI3EN BIT(18) +#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MP_APB3ENSETR register fields */ +#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENSETR_SAI4EN BIT(8) +#define RCC_MP_APB3ENSETR_SYSCFGEN BIT(11) +#define RCC_MP_APB3ENSETR_VREFEN BIT(13) +#define RCC_MP_APB3ENSETR_TMPSENSEN BIT(16) +#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MP_APB3ENCLRR register fields */ +#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENCLRR_SAI4EN BIT(8) +#define RCC_MP_APB3ENCLRR_SYSCFGEN BIT(11) +#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MP_APB3ENCLRR_TMPSENSEN BIT(16) +#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MP_AHB2ENSETR register fields */ +#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENSETR_DMAMUXEN BIT(2) +#define RCC_MP_AHB2ENSETR_ADC12EN BIT(5) +#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) +#define RCC_MP_AHB2ENSETR_SDMMC3EN BIT(16) + +/* RCC_MP_AHB2ENCLRR register fields */ +#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENCLRR_DMAMUXEN BIT(2) +#define RCC_MP_AHB2ENCLRR_ADC12EN BIT(5) +#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) +#define RCC_MP_AHB2ENCLRR_SDMMC3EN BIT(16) + +/* RCC_MP_AHB3ENSETR register fields */ +#define RCC_MP_AHB3ENSETR_DCMIEN BIT(0) +#define RCC_MP_AHB3ENSETR_CRYP2EN BIT(4) +#define RCC_MP_AHB3ENSETR_HASH2EN BIT(5) +#define RCC_MP_AHB3ENSETR_RNG2EN BIT(6) +#define RCC_MP_AHB3ENSETR_CRC2EN BIT(7) +#define RCC_MP_AHB3ENSETR_HSEMEN BIT(11) +#define RCC_MP_AHB3ENSETR_IPCCEN BIT(12) + +/* RCC_MP_AHB3ENCLRR register fields */ +#define RCC_MP_AHB3ENCLRR_DCMIEN BIT(0) +#define RCC_MP_AHB3ENCLRR_CRYP2EN BIT(4) +#define RCC_MP_AHB3ENCLRR_HASH2EN BIT(5) +#define RCC_MP_AHB3ENCLRR_RNG2EN BIT(6) +#define RCC_MP_AHB3ENCLRR_CRC2EN BIT(7) +#define RCC_MP_AHB3ENCLRR_HSEMEN BIT(11) +#define RCC_MP_AHB3ENCLRR_IPCCEN BIT(12) + +/* RCC_MP_AHB4ENSETR register fields */ +#define RCC_MP_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_AHB4ENSETR_GPIOIEN BIT(8) +#define RCC_MP_AHB4ENSETR_GPIOJEN BIT(9) +#define RCC_MP_AHB4ENSETR_GPIOKEN BIT(10) + +/* RCC_MP_AHB4ENCLRR register fields */ +#define RCC_MP_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_AHB4ENCLRR_GPIOIEN BIT(8) +#define RCC_MP_AHB4ENCLRR_GPIOJEN BIT(9) +#define RCC_MP_AHB4ENCLRR_GPIOKEN BIT(10) + +/* RCC_MP_MLAHBENSETR register fields */ +#define RCC_MP_MLAHBENSETR_RETRAMEN BIT(4) + +/* RCC_MP_MLAHBENCLRR register fields */ +#define RCC_MP_MLAHBENCLRR_RETRAMEN BIT(4) + +/* RCC_MC_APB1ENSETR register fields */ +#define RCC_MC_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MC_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MC_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MC_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MC_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MC_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MC_APB1ENSETR_TIM12EN BIT(6) +#define RCC_MC_APB1ENSETR_TIM13EN BIT(7) +#define RCC_MC_APB1ENSETR_TIM14EN BIT(8) +#define RCC_MC_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MC_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MC_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MC_APB1ENSETR_USART2EN BIT(14) +#define RCC_MC_APB1ENSETR_USART3EN BIT(15) +#define RCC_MC_APB1ENSETR_UART4EN BIT(16) +#define RCC_MC_APB1ENSETR_UART5EN BIT(17) +#define RCC_MC_APB1ENSETR_UART7EN BIT(18) +#define RCC_MC_APB1ENSETR_UART8EN BIT(19) +#define RCC_MC_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MC_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MC_APB1ENSETR_I2C3EN BIT(23) +#define RCC_MC_APB1ENSETR_I2C5EN BIT(24) +#define RCC_MC_APB1ENSETR_SPDIFEN BIT(26) +#define RCC_MC_APB1ENSETR_CECEN BIT(27) +#define RCC_MC_APB1ENSETR_WWDG1EN BIT(28) +#define RCC_MC_APB1ENSETR_DAC12EN BIT(29) +#define RCC_MC_APB1ENSETR_MDIOSEN BIT(31) + +/* RCC_MC_APB1ENCLRR register fields */ +#define RCC_MC_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MC_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MC_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MC_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MC_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MC_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MC_APB1ENCLRR_TIM12EN BIT(6) +#define RCC_MC_APB1ENCLRR_TIM13EN BIT(7) +#define RCC_MC_APB1ENCLRR_TIM14EN BIT(8) +#define RCC_MC_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MC_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MC_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MC_APB1ENCLRR_USART2EN BIT(14) +#define RCC_MC_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MC_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MC_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MC_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MC_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MC_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MC_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MC_APB1ENCLRR_I2C3EN BIT(23) +#define RCC_MC_APB1ENCLRR_I2C5EN BIT(24) +#define RCC_MC_APB1ENCLRR_SPDIFEN BIT(26) +#define RCC_MC_APB1ENCLRR_CECEN BIT(27) +#define RCC_MC_APB1ENCLRR_DAC12EN BIT(29) +#define RCC_MC_APB1ENCLRR_MDIOSEN BIT(31) + +/* RCC_MC_APB2ENSETR register fields */ +#define RCC_MC_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MC_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MC_APB2ENSETR_TIM15EN BIT(2) +#define RCC_MC_APB2ENSETR_TIM16EN BIT(3) +#define RCC_MC_APB2ENSETR_TIM17EN BIT(4) +#define RCC_MC_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MC_APB2ENSETR_SPI4EN BIT(9) +#define RCC_MC_APB2ENSETR_SPI5EN BIT(10) +#define RCC_MC_APB2ENSETR_USART6EN BIT(13) +#define RCC_MC_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MC_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MC_APB2ENSETR_SAI3EN BIT(18) +#define RCC_MC_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MC_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MC_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MC_APB2ENCLRR register fields */ +#define RCC_MC_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MC_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MC_APB2ENCLRR_TIM15EN BIT(2) +#define RCC_MC_APB2ENCLRR_TIM16EN BIT(3) +#define RCC_MC_APB2ENCLRR_TIM17EN BIT(4) +#define RCC_MC_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MC_APB2ENCLRR_SPI4EN BIT(9) +#define RCC_MC_APB2ENCLRR_SPI5EN BIT(10) +#define RCC_MC_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MC_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MC_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MC_APB2ENCLRR_SAI3EN BIT(18) +#define RCC_MC_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MC_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MC_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MC_APB3ENSETR register fields */ +#define RCC_MC_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MC_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MC_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MC_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MC_APB3ENSETR_SAI4EN BIT(8) +#define RCC_MC_APB3ENSETR_SYSCFGEN BIT(11) +#define RCC_MC_APB3ENSETR_VREFEN BIT(13) +#define RCC_MC_APB3ENSETR_TMPSENSEN BIT(16) +#define RCC_MC_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MC_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MC_APB3ENCLRR register fields */ +#define RCC_MC_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MC_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MC_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MC_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MC_APB3ENCLRR_SAI4EN BIT(8) +#define RCC_MC_APB3ENCLRR_SYSCFGEN BIT(11) +#define RCC_MC_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MC_APB3ENCLRR_TMPSENSEN BIT(16) +#define RCC_MC_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MC_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MC_AHB2ENSETR register fields */ +#define RCC_MC_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MC_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MC_AHB2ENSETR_DMAMUXEN BIT(2) +#define RCC_MC_AHB2ENSETR_ADC12EN BIT(5) +#define RCC_MC_AHB2ENSETR_USBOEN BIT(8) +#define RCC_MC_AHB2ENSETR_SDMMC3EN BIT(16) + +/* RCC_MC_AHB2ENCLRR register fields */ +#define RCC_MC_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MC_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MC_AHB2ENCLRR_DMAMUXEN BIT(2) +#define RCC_MC_AHB2ENCLRR_ADC12EN BIT(5) +#define RCC_MC_AHB2ENCLRR_USBOEN BIT(8) +#define RCC_MC_AHB2ENCLRR_SDMMC3EN BIT(16) + +/* RCC_MC_AHB3ENSETR register fields */ +#define RCC_MC_AHB3ENSETR_DCMIEN BIT(0) +#define RCC_MC_AHB3ENSETR_CRYP2EN BIT(4) +#define RCC_MC_AHB3ENSETR_HASH2EN BIT(5) +#define RCC_MC_AHB3ENSETR_RNG2EN BIT(6) +#define RCC_MC_AHB3ENSETR_CRC2EN BIT(7) +#define RCC_MC_AHB3ENSETR_HSEMEN BIT(11) +#define RCC_MC_AHB3ENSETR_IPCCEN BIT(12) + +/* RCC_MC_AHB3ENCLRR register fields */ +#define RCC_MC_AHB3ENCLRR_DCMIEN BIT(0) +#define RCC_MC_AHB3ENCLRR_CRYP2EN BIT(4) +#define RCC_MC_AHB3ENCLRR_HASH2EN BIT(5) +#define RCC_MC_AHB3ENCLRR_RNG2EN BIT(6) +#define RCC_MC_AHB3ENCLRR_CRC2EN BIT(7) +#define RCC_MC_AHB3ENCLRR_HSEMEN BIT(11) +#define RCC_MC_AHB3ENCLRR_IPCCEN BIT(12) + +/* RCC_MC_AHB4ENSETR register fields */ +#define RCC_MC_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MC_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MC_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MC_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MC_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MC_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MC_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MC_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MC_AHB4ENSETR_GPIOIEN BIT(8) +#define RCC_MC_AHB4ENSETR_GPIOJEN BIT(9) +#define RCC_MC_AHB4ENSETR_GPIOKEN BIT(10) + +/* RCC_MC_AHB4ENCLRR register fields */ +#define RCC_MC_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MC_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MC_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MC_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MC_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MC_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MC_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MC_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MC_AHB4ENCLRR_GPIOIEN BIT(8) +#define RCC_MC_AHB4ENCLRR_GPIOJEN BIT(9) +#define RCC_MC_AHB4ENCLRR_GPIOKEN BIT(10) + +/* RCC_MC_AXIMENSETR register fields */ +#define RCC_MC_AXIMENSETR_SYSRAMEN BIT(0) + +/* RCC_MC_AXIMENCLRR register fields */ +#define RCC_MC_AXIMENCLRR_SYSRAMEN BIT(0) + +/* RCC_MC_MLAHBENSETR register fields */ +#define RCC_MC_MLAHBENSETR_RETRAMEN BIT(4) + +/* RCC_MC_MLAHBENCLRR register fields */ +#define RCC_MC_MLAHBENCLRR_RETRAMEN BIT(4) + +/* RCC_MP_APB1LPENSETR register fields */ +#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENSETR_TIM12LPEN BIT(6) +#define RCC_MP_APB1LPENSETR_TIM13LPEN BIT(7) +#define RCC_MP_APB1LPENSETR_TIM14LPEN BIT(8) +#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENSETR_USART2LPEN BIT(14) +#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENSETR_I2C3LPEN BIT(23) +#define RCC_MP_APB1LPENSETR_I2C5LPEN BIT(24) +#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) +#define RCC_MP_APB1LPENSETR_CECLPEN BIT(27) +#define RCC_MP_APB1LPENSETR_DAC12LPEN BIT(29) +#define RCC_MP_APB1LPENSETR_MDIOSLPEN BIT(31) + +/* RCC_MP_APB1LPENCLRR register fields */ +#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENCLRR_TIM12LPEN BIT(6) +#define RCC_MP_APB1LPENCLRR_TIM13LPEN BIT(7) +#define RCC_MP_APB1LPENCLRR_TIM14LPEN BIT(8) +#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENCLRR_USART2LPEN BIT(14) +#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENCLRR_I2C3LPEN BIT(23) +#define RCC_MP_APB1LPENCLRR_I2C5LPEN BIT(24) +#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) +#define RCC_MP_APB1LPENCLRR_CECLPEN BIT(27) +#define RCC_MP_APB1LPENCLRR_DAC12LPEN BIT(29) +#define RCC_MP_APB1LPENCLRR_MDIOSLPEN BIT(31) + +/* RCC_MP_APB2LPENSETR register fields */ +#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENSETR_TIM15LPEN BIT(2) +#define RCC_MP_APB2LPENSETR_TIM16LPEN BIT(3) +#define RCC_MP_APB2LPENSETR_TIM17LPEN BIT(4) +#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENSETR_SPI4LPEN BIT(9) +#define RCC_MP_APB2LPENSETR_SPI5LPEN BIT(10) +#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENSETR_SAI3LPEN BIT(18) +#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MP_APB2LPENCLRR register fields */ +#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENCLRR_TIM15LPEN BIT(2) +#define RCC_MP_APB2LPENCLRR_TIM16LPEN BIT(3) +#define RCC_MP_APB2LPENCLRR_TIM17LPEN BIT(4) +#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENCLRR_SPI4LPEN BIT(9) +#define RCC_MP_APB2LPENCLRR_SPI5LPEN BIT(10) +#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENCLRR_SAI3LPEN BIT(18) +#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MP_APB3LPENSETR register fields */ +#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENSETR_SAI4LPEN BIT(8) +#define RCC_MP_APB3LPENSETR_SYSCFGLPEN BIT(11) +#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENSETR_TMPSENSLPEN BIT(16) +#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_APB3LPENCLRR register fields */ +#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENCLRR_SAI4LPEN BIT(8) +#define RCC_MP_APB3LPENCLRR_SYSCFGLPEN BIT(11) +#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENCLRR_TMPSENSLPEN BIT(16) +#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_AHB2LPENSETR register fields */ +#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENSETR_DMAMUXLPEN BIT(2) +#define RCC_MP_AHB2LPENSETR_ADC12LPEN BIT(5) +#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) +#define RCC_MP_AHB2LPENSETR_SDMMC3LPEN BIT(16) + +/* RCC_MP_AHB2LPENCLRR register fields */ +#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENCLRR_DMAMUXLPEN BIT(2) +#define RCC_MP_AHB2LPENCLRR_ADC12LPEN BIT(5) +#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) +#define RCC_MP_AHB2LPENCLRR_SDMMC3LPEN BIT(16) + +/* RCC_MP_AHB3LPENSETR register fields */ +#define RCC_MP_AHB3LPENSETR_DCMILPEN BIT(0) +#define RCC_MP_AHB3LPENSETR_CRYP2LPEN BIT(4) +#define RCC_MP_AHB3LPENSETR_HASH2LPEN BIT(5) +#define RCC_MP_AHB3LPENSETR_RNG2LPEN BIT(6) +#define RCC_MP_AHB3LPENSETR_CRC2LPEN BIT(7) +#define RCC_MP_AHB3LPENSETR_HSEMLPEN BIT(11) +#define RCC_MP_AHB3LPENSETR_IPCCLPEN BIT(12) + +/* RCC_MP_AHB3LPENCLRR register fields */ +#define RCC_MP_AHB3LPENCLRR_DCMILPEN BIT(0) +#define RCC_MP_AHB3LPENCLRR_CRYP2LPEN BIT(4) +#define RCC_MP_AHB3LPENCLRR_HASH2LPEN BIT(5) +#define RCC_MP_AHB3LPENCLRR_RNG2LPEN BIT(6) +#define RCC_MP_AHB3LPENCLRR_CRC2LPEN BIT(7) +#define RCC_MP_AHB3LPENCLRR_HSEMLPEN BIT(11) +#define RCC_MP_AHB3LPENCLRR_IPCCLPEN BIT(12) + +/* RCC_MP_AHB4LPENSETR register fields */ +#define RCC_MP_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_AHB4LPENSETR_GPIOILPEN BIT(8) +#define RCC_MP_AHB4LPENSETR_GPIOJLPEN BIT(9) +#define RCC_MP_AHB4LPENSETR_GPIOKLPEN BIT(10) + +/* RCC_MP_AHB4LPENCLRR register fields */ +#define RCC_MP_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_AHB4LPENCLRR_GPIOILPEN BIT(8) +#define RCC_MP_AHB4LPENCLRR_GPIOJLPEN BIT(9) +#define RCC_MP_AHB4LPENCLRR_GPIOKLPEN BIT(10) + +/* RCC_MP_AXIMLPENSETR register fields */ +#define RCC_MP_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_AXIMLPENCLRR register fields */ +#define RCC_MP_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_MLAHBLPENSETR register fields */ +#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENSETR_SRAM34LPEN BIT(2) +#define RCC_MP_MLAHBLPENSETR_RETRAMLPEN BIT(4) + +/* RCC_MP_MLAHBLPENCLRR register fields */ +#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENCLRR_SRAM34LPEN BIT(2) +#define RCC_MP_MLAHBLPENCLRR_RETRAMLPEN BIT(4) + +/* RCC_MC_APB1LPENSETR register fields */ +#define RCC_MC_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MC_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MC_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MC_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MC_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MC_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MC_APB1LPENSETR_TIM12LPEN BIT(6) +#define RCC_MC_APB1LPENSETR_TIM13LPEN BIT(7) +#define RCC_MC_APB1LPENSETR_TIM14LPEN BIT(8) +#define RCC_MC_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MC_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MC_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MC_APB1LPENSETR_USART2LPEN BIT(14) +#define RCC_MC_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MC_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MC_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MC_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MC_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MC_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MC_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MC_APB1LPENSETR_I2C3LPEN BIT(23) +#define RCC_MC_APB1LPENSETR_I2C5LPEN BIT(24) +#define RCC_MC_APB1LPENSETR_SPDIFLPEN BIT(26) +#define RCC_MC_APB1LPENSETR_CECLPEN BIT(27) +#define RCC_MC_APB1LPENSETR_WWDG1LPEN BIT(28) +#define RCC_MC_APB1LPENSETR_DAC12LPEN BIT(29) +#define RCC_MC_APB1LPENSETR_MDIOSLPEN BIT(31) + +/* RCC_MC_APB1LPENCLRR register fields */ +#define RCC_MC_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MC_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MC_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MC_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MC_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MC_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MC_APB1LPENCLRR_TIM12LPEN BIT(6) +#define RCC_MC_APB1LPENCLRR_TIM13LPEN BIT(7) +#define RCC_MC_APB1LPENCLRR_TIM14LPEN BIT(8) +#define RCC_MC_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MC_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MC_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MC_APB1LPENCLRR_USART2LPEN BIT(14) +#define RCC_MC_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MC_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MC_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MC_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MC_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MC_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MC_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MC_APB1LPENCLRR_I2C3LPEN BIT(23) +#define RCC_MC_APB1LPENCLRR_I2C5LPEN BIT(24) +#define RCC_MC_APB1LPENCLRR_SPDIFLPEN BIT(26) +#define RCC_MC_APB1LPENCLRR_CECLPEN BIT(27) +#define RCC_MC_APB1LPENCLRR_WWDG1LPEN BIT(28) +#define RCC_MC_APB1LPENCLRR_DAC12LPEN BIT(29) +#define RCC_MC_APB1LPENCLRR_MDIOSLPEN BIT(31) + +/* RCC_MC_APB2LPENSETR register fields */ +#define RCC_MC_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MC_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MC_APB2LPENSETR_TIM15LPEN BIT(2) +#define RCC_MC_APB2LPENSETR_TIM16LPEN BIT(3) +#define RCC_MC_APB2LPENSETR_TIM17LPEN BIT(4) +#define RCC_MC_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MC_APB2LPENSETR_SPI4LPEN BIT(9) +#define RCC_MC_APB2LPENSETR_SPI5LPEN BIT(10) +#define RCC_MC_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MC_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MC_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MC_APB2LPENSETR_SAI3LPEN BIT(18) +#define RCC_MC_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MC_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MC_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MC_APB2LPENCLRR register fields */ +#define RCC_MC_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MC_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MC_APB2LPENCLRR_TIM15LPEN BIT(2) +#define RCC_MC_APB2LPENCLRR_TIM16LPEN BIT(3) +#define RCC_MC_APB2LPENCLRR_TIM17LPEN BIT(4) +#define RCC_MC_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MC_APB2LPENCLRR_SPI4LPEN BIT(9) +#define RCC_MC_APB2LPENCLRR_SPI5LPEN BIT(10) +#define RCC_MC_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MC_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MC_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MC_APB2LPENCLRR_SAI3LPEN BIT(18) +#define RCC_MC_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MC_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MC_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MC_APB3LPENSETR register fields */ +#define RCC_MC_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MC_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MC_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MC_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MC_APB3LPENSETR_SAI4LPEN BIT(8) +#define RCC_MC_APB3LPENSETR_SYSCFGLPEN BIT(11) +#define RCC_MC_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MC_APB3LPENSETR_TMPSENSLPEN BIT(16) +#define RCC_MC_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MC_APB3LPENCLRR register fields */ +#define RCC_MC_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MC_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MC_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MC_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MC_APB3LPENCLRR_SAI4LPEN BIT(8) +#define RCC_MC_APB3LPENCLRR_SYSCFGLPEN BIT(11) +#define RCC_MC_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MC_APB3LPENCLRR_TMPSENSLPEN BIT(16) +#define RCC_MC_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MC_AHB2LPENSETR register fields */ +#define RCC_MC_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MC_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MC_AHB2LPENSETR_DMAMUXLPEN BIT(2) +#define RCC_MC_AHB2LPENSETR_ADC12LPEN BIT(5) +#define RCC_MC_AHB2LPENSETR_USBOLPEN BIT(8) +#define RCC_MC_AHB2LPENSETR_SDMMC3LPEN BIT(16) + +/* RCC_MC_AHB2LPENCLRR register fields */ +#define RCC_MC_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MC_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MC_AHB2LPENCLRR_DMAMUXLPEN BIT(2) +#define RCC_MC_AHB2LPENCLRR_ADC12LPEN BIT(5) +#define RCC_MC_AHB2LPENCLRR_USBOLPEN BIT(8) +#define RCC_MC_AHB2LPENCLRR_SDMMC3LPEN BIT(16) + +/* RCC_MC_AHB3LPENSETR register fields */ +#define RCC_MC_AHB3LPENSETR_DCMILPEN BIT(0) +#define RCC_MC_AHB3LPENSETR_CRYP2LPEN BIT(4) +#define RCC_MC_AHB3LPENSETR_HASH2LPEN BIT(5) +#define RCC_MC_AHB3LPENSETR_RNG2LPEN BIT(6) +#define RCC_MC_AHB3LPENSETR_CRC2LPEN BIT(7) +#define RCC_MC_AHB3LPENSETR_HSEMLPEN BIT(11) +#define RCC_MC_AHB3LPENSETR_IPCCLPEN BIT(12) + +/* RCC_MC_AHB3LPENCLRR register fields */ +#define RCC_MC_AHB3LPENCLRR_DCMILPEN BIT(0) +#define RCC_MC_AHB3LPENCLRR_CRYP2LPEN BIT(4) +#define RCC_MC_AHB3LPENCLRR_HASH2LPEN BIT(5) +#define RCC_MC_AHB3LPENCLRR_RNG2LPEN BIT(6) +#define RCC_MC_AHB3LPENCLRR_CRC2LPEN BIT(7) +#define RCC_MC_AHB3LPENCLRR_HSEMLPEN BIT(11) +#define RCC_MC_AHB3LPENCLRR_IPCCLPEN BIT(12) + +/* RCC_MC_AHB4LPENSETR register fields */ +#define RCC_MC_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MC_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MC_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MC_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MC_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MC_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MC_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MC_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MC_AHB4LPENSETR_GPIOILPEN BIT(8) +#define RCC_MC_AHB4LPENSETR_GPIOJLPEN BIT(9) +#define RCC_MC_AHB4LPENSETR_GPIOKLPEN BIT(10) + +/* RCC_MC_AHB4LPENCLRR register fields */ +#define RCC_MC_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MC_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MC_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MC_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MC_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MC_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MC_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MC_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MC_AHB4LPENCLRR_GPIOILPEN BIT(8) +#define RCC_MC_AHB4LPENCLRR_GPIOJLPEN BIT(9) +#define RCC_MC_AHB4LPENCLRR_GPIOKLPEN BIT(10) + +/* RCC_MC_AXIMLPENSETR register fields */ +#define RCC_MC_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MC_AXIMLPENCLRR register fields */ +#define RCC_MC_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MC_MLAHBLPENSETR register fields */ +#define RCC_MC_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MC_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MC_MLAHBLPENSETR_SRAM34LPEN BIT(2) +#define RCC_MC_MLAHBLPENSETR_RETRAMLPEN BIT(4) + +/* RCC_MC_MLAHBLPENCLRR register fields */ +#define RCC_MC_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MC_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MC_MLAHBLPENCLRR_SRAM34LPEN BIT(2) +#define RCC_MC_MLAHBLPENCLRR_RETRAMLPEN BIT(4) + +/* RCC_MC_RSTSCLRR register fields */ +#define RCC_MC_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MC_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MC_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MC_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MC_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MC_RSTSCLRR_MCURSTF BIT(5) +#define RCC_MC_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MC_RSTSCLRR_MCSYSRSTF BIT(7) +#define RCC_MC_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MC_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MC_RSTSCLRR_WWDG1RSTF BIT(10) + +/* RCC_MC_CIER register fields */ +#define RCC_MC_CIER_LSIRDYIE BIT(0) +#define RCC_MC_CIER_LSERDYIE BIT(1) +#define RCC_MC_CIER_HSIRDYIE BIT(2) +#define RCC_MC_CIER_HSERDYIE BIT(3) +#define RCC_MC_CIER_CSIRDYIE BIT(4) +#define RCC_MC_CIER_PLL1DYIE BIT(8) +#define RCC_MC_CIER_PLL2DYIE BIT(9) +#define RCC_MC_CIER_PLL3DYIE BIT(10) +#define RCC_MC_CIER_PLL4DYIE BIT(11) +#define RCC_MC_CIER_LSECSSIE BIT(16) +#define RCC_MC_CIER_WKUPIE BIT(20) + +/* RCC_MC_CIFR register fields */ +#define RCC_MC_CIFR_LSIRDYF BIT(0) +#define RCC_MC_CIFR_LSERDYF BIT(1) +#define RCC_MC_CIFR_HSIRDYF BIT(2) +#define RCC_MC_CIFR_HSERDYF BIT(3) +#define RCC_MC_CIFR_CSIRDYF BIT(4) +#define RCC_MC_CIFR_PLL1DYF BIT(8) +#define RCC_MC_CIFR_PLL2DYF BIT(9) +#define RCC_MC_CIFR_PLL3DYF BIT(10) +#define RCC_MC_CIFR_PLL4DYF BIT(11) +#define RCC_MC_CIFR_LSECSSF BIT(16) +#define RCC_MC_CIFR_WKUPF BIT(20) + +/* RCC_VERR register fields */ +#define RCC_VERR_MINREV_MASK GENMASK(3, 0) +#define RCC_VERR_MINREV_SHIFT 0 +#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) +#define RCC_VERR_MAJREV_SHIFT 4 + +/* Used for RCC_OCENSETR and RCC_OCENCLRR registers */ +#define RCC_OCENR_HSION BIT(0) +#define RCC_OCENR_HSIKERON BIT(1) +#define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_CSIKERON BIT(5) +#define RCC_OCENR_DIGBYP BIT(7) +#define RCC_OCENR_HSEON BIT(8) +#define RCC_OCENR_HSEKERON BIT(9) +#define RCC_OCENR_HSEBYP BIT(10) +#define RCC_OCENR_HSECSSON BIT(11) + +/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ +#define RCC_MP_ENCLRR_OFFSET U(4) + +/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ +#define RCC_RSTCLRR_OFFSET U(4) + +/* Used for most of DIVR register: max div for RTC */ +#define RCC_DIVR_DIV_MASK GENMASK(5, 0) +#define RCC_DIVR_DIVRDY BIT(31) + +/* Masks for specific DIVR registers */ +#define RCC_APBXDIV_MASK GENMASK(2, 0) +#define RCC_MPUDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIV_MASK GENMASK(2, 0) +#define RCC_MCUDIV_MASK GENMASK(3, 0) + +/* Used for most of RCC_SELR registers */ +#define RCC_SELR_SRC_MASK GENMASK(2, 0) +#define RCC_SELR_REFCLK_SRC_MASK GENMASK(1, 0) +#define RCC_SELR_SRCRDY BIT(31) + +/* Used for all RCC_PLLCR registers */ +#define RCC_PLLNCR_PLLON BIT(0) +#define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) +#define RCC_PLLNCR_DIVPEN BIT(4) +#define RCC_PLLNCR_DIVQEN BIT(5) +#define RCC_PLLNCR_DIVREN BIT(6) +#define RCC_PLLNCR_DIVEN_SHIFT 4 + +/* Used for all RCC_PLLCFGR1 registers */ +#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) +#define RCC_PLLNCFGR1_DIVM_SHIFT 16 +#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLLNCFGR1_DIVN_SHIFT 0 + +/* Only for PLL3 and PLL4 */ +#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 + +/* Used for all RCC_PLLCFGR2 registers */ +#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVP_SHIFT 0 +#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 +#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLLNCFGR2_DIVR_SHIFT 16 + +/* Used for all RCC_PLLFRACR registers */ +#define RCC_PLLNFRACR_FRACV_SHIFT 3 +#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLLNFRACR_FRACLE BIT(16) + +/* Used for all RCC_PLLCSGR registers */ +#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 +#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 +#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 +#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) + +/* Used for TIMER Prescaler */ +#define RCC_TIMGXPRER_TIMGXPRE BIT(0) + +/* Used for RCC_MCO related operations */ +#define RCC_MCOCFG_MCOON BIT(12) +#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) +#define RCC_MCOCFG_MCODIV_SHIFT 4 +#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) + +#endif /* STM32MP1_RCC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h new file mode 100644 index 0000000..e2395bc --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_CLK_H +#define STM32MP1_CLK_H + +#include + +enum stm32mp_osc_id { + _HSI, + _HSE, + _CSI, + _LSI, + _LSE, + _I2S_CKIN, + NB_OSC, + _UNKNOWN_OSC_ID = 0xFF +}; + +extern const char *stm32mp_osc_node_label[NB_OSC]; + +int stm32mp1_clk_probe(void); +int stm32mp1_clk_init(void); + +bool stm32mp1_rcc_is_secure(void); +bool stm32mp1_rcc_is_mckprot(void); + +/* SMP protection on RCC registers access */ +void stm32mp1_clk_rcc_regs_lock(void); +void stm32mp1_clk_rcc_regs_unlock(void); + +#ifdef STM32MP_SHARED_RESOURCES +void stm32mp1_register_clock_parents_secure(unsigned long id); +#endif +#endif /* STM32MP1_CLK_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h new file mode 100644 index 0000000..df71f35 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32MP1_DDR_H +#define STM32MP1_DDR_H + +#include +#include + +#include + +struct stm32mp1_ddrctrl_reg { + uint32_t mstr; + uint32_t mrctrl0; + uint32_t mrctrl1; + uint32_t derateen; + uint32_t derateint; + uint32_t pwrctl; + uint32_t pwrtmg; + uint32_t hwlpctl; + uint32_t rfshctl0; + uint32_t rfshctl3; + uint32_t crcparctl0; + uint32_t zqctl0; + uint32_t dfitmg0; + uint32_t dfitmg1; + uint32_t dfilpcfg0; + uint32_t dfiupd0; + uint32_t dfiupd1; + uint32_t dfiupd2; + uint32_t dfiphymstr; + uint32_t odtmap; + uint32_t dbg0; + uint32_t dbg1; + uint32_t dbgcmd; + uint32_t poisoncfg; + uint32_t pccfg; +}; + +struct stm32mp1_ddrctrl_timing { + uint32_t rfshtmg; + uint32_t dramtmg0; + uint32_t dramtmg1; + uint32_t dramtmg2; + uint32_t dramtmg3; + uint32_t dramtmg4; + uint32_t dramtmg5; + uint32_t dramtmg6; + uint32_t dramtmg7; + uint32_t dramtmg8; + uint32_t dramtmg14; + uint32_t odtcfg; +}; + +struct stm32mp1_ddrctrl_map { + uint32_t addrmap1; + uint32_t addrmap2; + uint32_t addrmap3; + uint32_t addrmap4; + uint32_t addrmap5; + uint32_t addrmap6; + uint32_t addrmap9; + uint32_t addrmap10; + uint32_t addrmap11; +}; + +struct stm32mp1_ddrctrl_perf { + uint32_t sched; + uint32_t sched1; + uint32_t perfhpr1; + uint32_t perflpr1; + uint32_t perfwr1; + uint32_t pcfgr_0; + uint32_t pcfgw_0; + uint32_t pcfgqos0_0; + uint32_t pcfgqos1_0; + uint32_t pcfgwqos0_0; + uint32_t pcfgwqos1_0; +#if STM32MP_DDR_DUAL_AXI_PORT + uint32_t pcfgr_1; + uint32_t pcfgw_1; + uint32_t pcfgqos0_1; + uint32_t pcfgqos1_1; + uint32_t pcfgwqos0_1; + uint32_t pcfgwqos1_1; +#endif +}; + +struct stm32mp1_ddrphy_reg { + uint32_t pgcr; + uint32_t aciocr; + uint32_t dxccr; + uint32_t dsgcr; + uint32_t dcr; + uint32_t odtcr; + uint32_t zq0cr1; + uint32_t dx0gcr; + uint32_t dx1gcr; +#if STM32MP_DDR_32BIT_INTERFACE + uint32_t dx2gcr; + uint32_t dx3gcr; +#endif +}; + +struct stm32mp1_ddrphy_timing { + uint32_t ptr0; + uint32_t ptr1; + uint32_t ptr2; + uint32_t dtpr0; + uint32_t dtpr1; + uint32_t dtpr2; + uint32_t mr0; + uint32_t mr1; + uint32_t mr2; + uint32_t mr3; +}; + +struct stm32mp_ddr_config { + struct stm32mp_ddr_info info; + struct stm32mp1_ddrctrl_reg c_reg; + struct stm32mp1_ddrctrl_timing c_timing; + struct stm32mp1_ddrctrl_map c_map; + struct stm32mp1_ddrctrl_perf c_perf; + struct stm32mp1_ddrphy_reg p_reg; + struct stm32mp1_ddrphy_timing p_timing; +}; + +int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed); +void stm32mp1_ddr_init(struct stm32mp_ddr_priv *priv, struct stm32mp_ddr_config *config); + +#endif /* STM32MP1_DDR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h new file mode 100644 index 0000000..38f2415 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_DDR_HELPERS_H +#define STM32MP1_DDR_HELPERS_H + +void ddr_enable_clock(void); + +#endif /* STM32MP1_DDR_HELPERS_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h new file mode 100644 index 0000000..2fbe1c8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32MP1_DDR_REGS_H +#define STM32MP1_DDR_REGS_H + +#include +#include + +/* DDR Physical Interface Control (DDRPHYC) registers*/ +struct stm32mp_ddrphy { + uint32_t ridr; /* 0x00 R Revision Identification */ + uint32_t pir; /* 0x04 R/W PHY Initialization */ + uint32_t pgcr; /* 0x08 R/W PHY General Configuration */ + uint32_t pgsr; /* 0x0C PHY General Status */ + uint32_t dllgcr; /* 0x10 R/W DLL General Control */ + uint32_t acdllcr; /* 0x14 R/W AC DLL Control */ + uint32_t ptr0; /* 0x18 R/W PHY Timing 0 */ + uint32_t ptr1; /* 0x1C R/W PHY Timing 1 */ + uint32_t ptr2; /* 0x20 R/W PHY Timing 2 */ + uint32_t aciocr; /* 0x24 AC I/O Configuration */ + uint32_t dxccr; /* 0x28 DATX8 Common Configuration */ + uint32_t dsgcr; /* 0x2C DDR System General Configuration */ + uint32_t dcr; /* 0x30 DRAM Configuration */ + uint32_t dtpr0; /* 0x34 DRAM Timing Parameters0 */ + uint32_t dtpr1; /* 0x38 DRAM Timing Parameters1 */ + uint32_t dtpr2; /* 0x3C DRAM Timing Parameters2 */ + uint32_t mr0; /* 0x40 Mode 0 */ + uint32_t mr1; /* 0x44 Mode 1 */ + uint32_t mr2; /* 0x48 Mode 2 */ + uint32_t mr3; /* 0x4C Mode 3 */ + uint32_t odtcr; /* 0x50 ODT Configuration */ + uint32_t dtar; /* 0x54 data training address */ + uint32_t dtdr0; /* 0x58 */ + uint32_t dtdr1; /* 0x5c */ + uint8_t res1[0x0c0 - 0x060]; /* 0x60 */ + uint32_t dcuar; /* 0xc0 Address */ + uint32_t dcudr; /* 0xc4 DCU Data */ + uint32_t dcurr; /* 0xc8 DCU Run */ + uint32_t dculr; /* 0xcc DCU Loop */ + uint32_t dcugcr; /* 0xd0 DCU General Configuration */ + uint32_t dcutpr; /* 0xd4 DCU Timing Parameters */ + uint32_t dcusr0; /* 0xd8 DCU Status 0 */ + uint32_t dcusr1; /* 0xdc DCU Status 1 */ + uint8_t res2[0x100 - 0xe0]; /* 0xe0 */ + uint32_t bistrr; /* 0x100 BIST Run */ + uint32_t bistmskr0; /* 0x104 BIST Mask 0 */ + uint32_t bistmskr1; /* 0x108 BIST Mask 0 */ + uint32_t bistwcr; /* 0x10c BIST Word Count */ + uint32_t bistlsr; /* 0x110 BIST LFSR Seed */ + uint32_t bistar0; /* 0x114 BIST Address 0 */ + uint32_t bistar1; /* 0x118 BIST Address 1 */ + uint32_t bistar2; /* 0x11c BIST Address 2 */ + uint32_t bistupdr; /* 0x120 BIST User Data Pattern */ + uint32_t bistgsr; /* 0x124 BIST General Status */ + uint32_t bistwer; /* 0x128 BIST Word Error */ + uint32_t bistber0; /* 0x12c BIST Bit Error 0 */ + uint32_t bistber1; /* 0x130 BIST Bit Error 1 */ + uint32_t bistber2; /* 0x134 BIST Bit Error 2 */ + uint32_t bistwcsr; /* 0x138 BIST Word Count Status */ + uint32_t bistfwr0; /* 0x13c BIST Fail Word 0 */ + uint32_t bistfwr1; /* 0x140 BIST Fail Word 1 */ + uint8_t res3[0x178 - 0x144]; /* 0x144 */ + uint32_t gpr0; /* 0x178 General Purpose 0 (GPR0) */ + uint32_t gpr1; /* 0x17C General Purpose 1 (GPR1) */ + uint32_t zq0cr0; /* 0x180 zq 0 control 0 */ + uint32_t zq0cr1; /* 0x184 zq 0 control 1 */ + uint32_t zq0sr0; /* 0x188 zq 0 status 0 */ + uint32_t zq0sr1; /* 0x18C zq 0 status 1 */ + uint8_t res4[0x1C0 - 0x190]; /* 0x190 */ + uint32_t dx0gcr; /* 0x1c0 Byte lane 0 General Configuration */ + uint32_t dx0gsr0; /* 0x1c4 Byte lane 0 General Status 0 */ + uint32_t dx0gsr1; /* 0x1c8 Byte lane 0 General Status 1 */ + uint32_t dx0dllcr; /* 0x1cc Byte lane 0 DLL Control */ + uint32_t dx0dqtr; /* 0x1d0 Byte lane 0 DQ Timing */ + uint32_t dx0dqstr; /* 0x1d4 Byte lane 0 DQS Timing */ + uint8_t res5[0x200 - 0x1d8]; /* 0x1d8 */ + uint32_t dx1gcr; /* 0x200 Byte lane 1 General Configuration */ + uint32_t dx1gsr0; /* 0x204 Byte lane 1 General Status 0 */ + uint32_t dx1gsr1; /* 0x208 Byte lane 1 General Status 1 */ + uint32_t dx1dllcr; /* 0x20c Byte lane 1 DLL Control */ + uint32_t dx1dqtr; /* 0x210 Byte lane 1 DQ Timing */ + uint32_t dx1dqstr; /* 0x214 Byte lane 1 QS Timing */ + uint8_t res6[0x240 - 0x218]; /* 0x218 */ +#if STM32MP_DDR_32BIT_INTERFACE + uint32_t dx2gcr; /* 0x240 Byte lane 2 General Configuration */ + uint32_t dx2gsr0; /* 0x244 Byte lane 2 General Status 0 */ + uint32_t dx2gsr1; /* 0x248 Byte lane 2 General Status 1 */ + uint32_t dx2dllcr; /* 0x24c Byte lane 2 DLL Control */ + uint32_t dx2dqtr; /* 0x250 Byte lane 2 DQ Timing */ + uint32_t dx2dqstr; /* 0x254 Byte lane 2 QS Timing */ + uint8_t res7[0x280 - 0x258]; /* 0x258 */ + uint32_t dx3gcr; /* 0x280 Byte lane 3 General Configuration */ + uint32_t dx3gsr0; /* 0x284 Byte lane 3 General Status 0 */ + uint32_t dx3gsr1; /* 0x288 Byte lane 3 General Status 1 */ + uint32_t dx3dllcr; /* 0x28c Byte lane 3 DLL Control */ + uint32_t dx3dqtr; /* 0x290 Byte lane 3 DQ Timing */ + uint32_t dx3dqstr; /* 0x294 Byte lane 3 QS Timing */ +#endif +} __packed; + +/* DDR PHY registers offsets */ +#define DDRPHYC_PIR 0x004 +#define DDRPHYC_PGCR 0x008 +#define DDRPHYC_PGSR 0x00C +#define DDRPHYC_DLLGCR 0x010 +#define DDRPHYC_ACDLLCR 0x014 +#define DDRPHYC_PTR0 0x018 +#define DDRPHYC_ACIOCR 0x024 +#define DDRPHYC_DXCCR 0x028 +#define DDRPHYC_DSGCR 0x02C +#define DDRPHYC_ZQ0CR0 0x180 +#define DDRPHYC_DX0GCR 0x1C0 +#define DDRPHYC_DX0DLLCR 0x1CC +#define DDRPHYC_DX1GCR 0x200 +#define DDRPHYC_DX1DLLCR 0x20C +#if STM32MP_DDR_32BIT_INTERFACE +#define DDRPHYC_DX2GCR 0x240 +#define DDRPHYC_DX2DLLCR 0x24C +#define DDRPHYC_DX3GCR 0x280 +#define DDRPHYC_DX3DLLCR 0x28C +#endif + +/* DDR PHY Register fields */ +#define DDRPHYC_PIR_INIT BIT(0) +#define DDRPHYC_PIR_DLLSRST BIT(1) +#define DDRPHYC_PIR_DLLLOCK BIT(2) +#define DDRPHYC_PIR_ZCAL BIT(3) +#define DDRPHYC_PIR_ITMSRST BIT(4) +#define DDRPHYC_PIR_DRAMRST BIT(5) +#define DDRPHYC_PIR_DRAMINIT BIT(6) +#define DDRPHYC_PIR_QSTRN BIT(7) +#define DDRPHYC_PIR_RVTRN BIT(8) +#define DDRPHYC_PIR_ICPC BIT(16) +#define DDRPHYC_PIR_ZCALBYP BIT(30) +#define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) + +#define DDRPHYC_PGCR_DFTCMP BIT(2) +#define DDRPHYC_PGCR_PDDISDX BIT(24) +#define DDRPHYC_PGCR_RFSHDT_MASK GENMASK(28, 25) + +#define DDRPHYC_PGSR_IDONE BIT(0) +#define DDRPHYC_PGSR_DTERR BIT(5) +#define DDRPHYC_PGSR_DTIERR BIT(6) +#define DDRPHYC_PGSR_DFTERR BIT(7) +#define DDRPHYC_PGSR_RVERR BIT(8) +#define DDRPHYC_PGSR_RVEIRR BIT(9) + +#define DDRPHYC_DLLGCR_BPS200 BIT(23) + +#define DDRPHYC_ACDLLCR_DLLSRST BIT(30) +#define DDRPHYC_ACDLLCR_DLLDIS BIT(31) + +#define DDRPHYC_PTR0_TDLLSRST_OFFSET 0 +#define DDRPHYC_PTR0_TDLLSRST_MASK GENMASK(5, 0) +#define DDRPHYC_PTR0_TDLLLOCK_OFFSET 6 +#define DDRPHYC_PTR0_TDLLLOCK_MASK GENMASK(17, 6) +#define DDRPHYC_PTR0_TITMSRST_OFFSET 18 +#define DDRPHYC_PTR0_TITMSRST_MASK GENMASK(21, 18) + +#define DDRPHYC_ACIOCR_ACPDD BIT(3) +#define DDRPHYC_ACIOCR_ACPDR BIT(4) +#define DDRPHYC_ACIOCR_CKPDD_MASK GENMASK(10, 8) +#define DDRPHYC_ACIOCR_CKPDD_0 BIT(8) +#define DDRPHYC_ACIOCR_CKPDR_MASK GENMASK(13, 11) +#define DDRPHYC_ACIOCR_CKPDR_0 BIT(11) +#define DDRPHYC_ACIOCR_CSPDD_MASK GENMASK(21, 18) +#define DDRPHYC_ACIOCR_CSPDD_0 BIT(18) +#define DDRPHYC_ACIOCR_RSTPDD BIT(27) +#define DDRPHYC_ACIOCR_RSTPDR BIT(28) + +#define DDRPHYC_DXCCR_DXPDD BIT(2) +#define DDRPHYC_DXCCR_DXPDR BIT(3) + +#define DDRPHYC_DSGCR_CKEPDD_MASK GENMASK(19, 16) +#define DDRPHYC_DSGCR_CKEPDD_0 BIT(16) +#define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK(23, 20) +#define DDRPHYC_DSGCR_ODTPDD_0 BIT(20) +#define DDRPHYC_DSGCR_NL2PD BIT(24) + +#define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK(27, 0) +#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 +#define DDRPHYC_ZQ0CRN_ZDEN BIT(28) +#define DDRPHYC_ZQ0CRN_ZQPD BIT(31) + +#define DDRPHYC_DXNGCR_DXEN BIT(0) + +#define DDRPHYC_DXNDLLCR_DLLSRST BIT(30) +#define DDRPHYC_DXNDLLCR_DLLDIS BIT(31) +#define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14) +#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14 + +#endif /* STM32MP1_DDR_REGS_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h new file mode 100644 index 0000000..e17df44 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_PWR_H +#define STM32MP1_PWR_H + +#include + +#define PWR_CR1 U(0x00) +#define PWR_CR2 U(0x08) +#define PWR_CR3 U(0x0C) +#define PWR_MPUCR U(0x10) +#define PWR_WKUPCR U(0x20) +#define PWR_MPUWKUPENR U(0x28) + +#define PWR_CR1_LPDS BIT(0) +#define PWR_CR1_LPCFG BIT(1) +#define PWR_CR1_LVDS BIT(2) +#define PWR_CR1_DBP BIT(8) + +#define PWR_CR3_DDRSREN BIT(10) +#define PWR_CR3_DDRSRDIS BIT(11) +#define PWR_CR3_DDRRETEN BIT(12) + +#define PWR_MPUCR_PDDS BIT(0) +#define PWR_MPUCR_CSTDBYDIS BIT(3) +#define PWR_MPUCR_CSSF BIT(9) + +#endif /* STM32MP1_PWR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h new file mode 100644 index 0000000..38360e7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_RAM_H +#define STM32MP1_RAM_H + +int stm32mp1_ddr_probe(void); + +#endif /* STM32MP1_RAM_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h new file mode 100644 index 0000000..d794225 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if STM32MP13 +#include "stm32mp13_rcc.h" +#endif +#if STM32MP15 +#include "stm32mp15_rcc.h" +#endif diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h new file mode 100644 index 0000000..06a34cb --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_USB_H +#define STM32MP1_USB_H + +#include + +void stm32mp1_usb_init_driver(struct usb_handle *usb_core_handle, + struct pcd_handle *pcd_handle, + void *base_register); + +#endif /* STM32MP1_USB_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h b/arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h new file mode 100644 index 0000000..61286b2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_CLKFUNC_H +#define STM32MP_CLKFUNC_H + +#include + +#include + +#include + +int fdt_osc_read_freq(const char *name, uint32_t *freq); +bool fdt_clk_read_bool(const char *node_label, const char *prop_name); +uint32_t fdt_clk_read_uint32_default(const char *node_label, + const char *prop_name, + uint32_t dflt_value); + +int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count, + uint32_t *array); +int fdt_rcc_subnode_offset(const char *name); +const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp); +bool fdt_get_rcc_secure_state(void); + +int fdt_get_clock_id(int node); +unsigned long fdt_get_uart_clock_freq(uintptr_t instance); + +void stm32mp_stgen_config(unsigned long rate); +void stm32mp_stgen_restore_counter(unsigned long long value, + unsigned long long offset_in_ms); +unsigned long long stm32mp_stgen_get_counter(void); + +#endif /* STM32MP_CLKFUNC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h b/arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h new file mode 100644 index 0000000..1efca42 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32MP_DDR_H +#define STM32MP_DDR_H + +#include + +enum stm32mp_ddr_base_type { + DDR_BASE, + DDRPHY_BASE, + NONE_BASE +}; + +enum stm32mp_ddr_reg_type { + REG_REG, + REG_TIMING, + REG_PERF, + REG_MAP, + REGPHY_REG, + REGPHY_TIMING, + REG_TYPE_NB +}; + +struct stm32mp_ddr_reg_desc { + const char *name; + uint16_t offset; /* Offset for base address */ + uint8_t par_offset; /* Offset for parameter array */ +}; + +struct stm32mp_ddr_reg_info { + const char *name; + const struct stm32mp_ddr_reg_desc *desc; + uint8_t size; + enum stm32mp_ddr_base_type base; +}; + +struct stm32mp_ddr_size { + uint64_t base; + uint64_t size; +}; + +struct stm32mp_ddr_priv { + struct stm32mp_ddr_size info; + struct stm32mp_ddrctl *ctl; + struct stm32mp_ddrphy *phy; + uintptr_t pwr; + uintptr_t rcc; +}; + +struct stm32mp_ddr_info { + const char *name; + uint32_t speed; /* in kHZ */ + uint32_t size; /* Memory size in byte = col * row * width */ +}; + +#define TIMEOUT_US_1S 1000000U + +void stm32mp_ddr_set_reg(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_reg_type type, + const void *param, const struct stm32mp_ddr_reg_info *ddr_registers); +void stm32mp_ddr_start_sw_done(struct stm32mp_ddrctl *ctl); +void stm32mp_ddr_wait_sw_done_ack(struct stm32mp_ddrctl *ctl); +void stm32mp_ddr_enable_axi_port(struct stm32mp_ddrctl *ctl); +int stm32mp_board_ddr_power_init(enum ddr_type ddr_type); + +#endif /* STM32MP_DDR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h b/arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h new file mode 100644 index 0000000..34e522a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_DDR_TEST_H +#define STM32MP_DDR_TEST_H + +#include + +uint32_t stm32mp_ddr_test_rw_access(void); +uint32_t stm32mp_ddr_test_data_bus(void); +uint32_t stm32mp_ddr_test_addr_bus(uint64_t size); +uint32_t stm32mp_ddr_check_size(void); + +#endif /* STM32MP_DDR_TEST_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h b/arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h new file mode 100644 index 0000000..79de86b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32MP_DDRCTRL_REGS_H +#define STM32MP_DDRCTRL_REGS_H + +#include +#include + +#include + +/* DDR Controller (DDRCTRL) registers */ +struct stm32mp_ddrctl { + uint32_t mstr ; /* 0x0 Master */ + uint32_t stat; /* 0x4 Operating Mode Status */ + uint8_t reserved008[0x10 - 0x8]; + uint32_t mrctrl0; /* 0x10 Control 0 */ + uint32_t mrctrl1; /* 0x14 Control 1 */ + uint32_t mrstat; /* 0x18 Status */ + uint32_t mrctrl2; /* 0x1c Control 2 */ + uint32_t derateen; /* 0x20 Temperature Derate Enable */ + uint32_t derateint; /* 0x24 Temperature Derate Interval */ + uint32_t reserved028; + uint32_t deratectl; /* 0x2c Temperature Derate Control */ + uint32_t pwrctl; /* 0x30 Low Power Control */ + uint32_t pwrtmg; /* 0x34 Low Power Timing */ + uint32_t hwlpctl; /* 0x38 Hardware Low Power Control */ + uint8_t reserved03c[0x50 - 0x3c]; + uint32_t rfshctl0; /* 0x50 Refresh Control 0 */ + uint32_t rfshctl1; /* 0x54 Refresh Control 1 */ + uint32_t reserved058; /* 0x58 Refresh Control 2 */ + uint32_t reserved05C; + uint32_t rfshctl3; /* 0x60 Refresh Control 0 */ + uint32_t rfshtmg; /* 0x64 Refresh Timing */ + uint32_t rfshtmg1; /* 0x68 Refresh Timing 1 */ + uint8_t reserved06c[0xc0 - 0x6c]; + uint32_t crcparctl0; /* 0xc0 CRC Parity Control0 */ + uint32_t crcparctl1; /* 0xc4 CRC Parity Control1 */ + uint32_t reserved0c8; /* 0xc8 CRC Parity Control2 */ + uint32_t crcparstat; /* 0xcc CRC Parity Status */ + uint32_t init0; /* 0xd0 SDRAM Initialization 0 */ + uint32_t init1; /* 0xd4 SDRAM Initialization 1 */ + uint32_t init2; /* 0xd8 SDRAM Initialization 2 */ + uint32_t init3; /* 0xdc SDRAM Initialization 3 */ + uint32_t init4; /* 0xe0 SDRAM Initialization 4 */ + uint32_t init5; /* 0xe4 SDRAM Initialization 5 */ + uint32_t init6; /* 0xe8 SDRAM Initialization 6 */ + uint32_t init7; /* 0xec SDRAM Initialization 7 */ + uint32_t dimmctl; /* 0xf0 DIMM Control */ + uint32_t rankctl; /* 0xf4 Rank Control */ + uint8_t reserved0f4[0x100 - 0xf8]; + uint32_t dramtmg0; /* 0x100 SDRAM Timing 0 */ + uint32_t dramtmg1; /* 0x104 SDRAM Timing 1 */ + uint32_t dramtmg2; /* 0x108 SDRAM Timing 2 */ + uint32_t dramtmg3; /* 0x10c SDRAM Timing 3 */ + uint32_t dramtmg4; /* 0x110 SDRAM Timing 4 */ + uint32_t dramtmg5; /* 0x114 SDRAM Timing 5 */ + uint32_t dramtmg6; /* 0x118 SDRAM Timing 6 */ + uint32_t dramtmg7; /* 0x11c SDRAM Timing 7 */ + uint32_t dramtmg8; /* 0x120 SDRAM Timing 8 */ + uint32_t dramtmg9; /* 0x124 SDRAM Timing 9 */ + uint32_t dramtmg10; /* 0x128 SDRAM Timing 10 */ + uint32_t dramtmg11; /* 0x12c SDRAM Timing 11 */ + uint32_t dramtmg12; /* 0x130 SDRAM Timing 12 */ + uint32_t dramtmg13; /* 0x134 SDRAM Timing 13 */ + uint32_t dramtmg14; /* 0x138 SDRAM Timing 14 */ + uint32_t dramtmg15; /* 0x13c SDRAM Timing 15 */ + uint8_t reserved140[0x180 - 0x140]; + uint32_t zqctl0; /* 0x180 ZQ Control 0 */ + uint32_t zqctl1; /* 0x184 ZQ Control 1 */ + uint32_t zqctl2; /* 0x188 ZQ Control 2 */ + uint32_t zqstat; /* 0x18c ZQ Status */ + uint32_t dfitmg0; /* 0x190 DFI Timing 0 */ + uint32_t dfitmg1; /* 0x194 DFI Timing 1 */ + uint32_t dfilpcfg0; /* 0x198 DFI Low Power Configuration 0 */ + uint32_t dfilpcfg1; /* 0x19c DFI Low Power Configuration 1 */ + uint32_t dfiupd0; /* 0x1a0 DFI Update 0 */ + uint32_t dfiupd1; /* 0x1a4 DFI Update 1 */ + uint32_t dfiupd2; /* 0x1a8 DFI Update 2 */ + uint32_t reserved1ac; + uint32_t dfimisc; /* 0x1b0 DFI Miscellaneous Control */ + uint32_t dfitmg2; /* 0x1b4 DFI Timing 2 */ + uint32_t dfitmg3; /* 0x1b8 DFI Timing 3 */ + uint32_t dfistat; /* 0x1bc DFI Status */ + uint32_t dbictl; /* 0x1c0 DM/DBI Control */ + uint32_t dfiphymstr; /* 0x1c4 DFI PHY Master interface */ + uint8_t reserved1c8[0x200 - 0x1c8]; + uint32_t addrmap0; /* 0x200 Address Map 0 */ + uint32_t addrmap1; /* 0x204 Address Map 1 */ + uint32_t addrmap2; /* 0x208 Address Map 2 */ + uint32_t addrmap3; /* 0x20c Address Map 3 */ + uint32_t addrmap4; /* 0x210 Address Map 4 */ + uint32_t addrmap5; /* 0x214 Address Map 5 */ + uint32_t addrmap6; /* 0x218 Address Map 6 */ + uint32_t addrmap7; /* 0x21c Address Map 7 */ + uint32_t addrmap8; /* 0x220 Address Map 8 */ + uint32_t addrmap9; /* 0x224 Address Map 9 */ + uint32_t addrmap10; /* 0x228 Address Map 10 */ + uint32_t addrmap11; /* 0x22C Address Map 11 */ + uint8_t reserved230[0x240 - 0x230]; + uint32_t odtcfg; /* 0x240 ODT Configuration */ + uint32_t odtmap; /* 0x244 ODT/Rank Map */ + uint8_t reserved248[0x250 - 0x248]; + uint32_t sched; /* 0x250 Scheduler Control */ + uint32_t sched1; /* 0x254 Scheduler Control 1 */ + uint32_t reserved258; + uint32_t perfhpr1; /* 0x25c High Priority Read CAM 1 */ + uint32_t reserved260; + uint32_t perflpr1; /* 0x264 Low Priority Read CAM 1 */ + uint32_t reserved268; + uint32_t perfwr1; /* 0x26c Write CAM 1 */ + uint8_t reserved27c[0x300 - 0x270]; + uint32_t dbg0; /* 0x300 Debug 0 */ + uint32_t dbg1; /* 0x304 Debug 1 */ + uint32_t dbgcam; /* 0x308 CAM Debug */ + uint32_t dbgcmd; /* 0x30c Command Debug */ + uint32_t dbgstat; /* 0x310 Status Debug */ + uint8_t reserved314[0x320 - 0x314]; + uint32_t swctl; /* 0x320 Software Programming Control Enable */ + uint32_t swstat; /* 0x324 Software Programming Control Status */ + uint8_t reserved328[0x36c - 0x328]; + uint32_t poisoncfg; /* 0x36c AXI Poison Configuration Register */ + uint32_t poisonstat; /* 0x370 AXI Poison Status Register */ + uint8_t reserved374[0x3f0 - 0x374]; + uint32_t deratestat; /* 0x3f0 Temperature Derate Status */ + uint8_t reserved3f4[0x3fc - 0x3f4]; + + /* Multi Port registers */ + uint32_t pstat; /* 0x3fc Port Status */ + uint32_t pccfg; /* 0x400 Port Common Configuration */ + + /* PORT 0 */ + uint32_t pcfgr_0; /* 0x404 Configuration Read */ + uint32_t pcfgw_0; /* 0x408 Configuration Write */ + uint8_t reserved40c[0x490 - 0x40c]; + uint32_t pctrl_0; /* 0x490 Port Control Register */ + uint32_t pcfgqos0_0; /* 0x494 Read QoS Configuration 0 */ + uint32_t pcfgqos1_0; /* 0x498 Read QoS Configuration 1 */ + uint32_t pcfgwqos0_0; /* 0x49c Write QoS Configuration 0 */ + uint32_t pcfgwqos1_0; /* 0x4a0 Write QoS Configuration 1 */ + uint8_t reserved4a4[0x4b4 - 0x4a4]; + +#if STM32MP_DDR_DUAL_AXI_PORT + /* PORT 1 */ + uint32_t pcfgr_1; /* 0x4b4 Configuration Read */ + uint32_t pcfgw_1; /* 0x4b8 Configuration Write */ + uint8_t reserved4bc[0x540 - 0x4bc]; + uint32_t pctrl_1; /* 0x540 Port 2 Control Register */ + uint32_t pcfgqos0_1; /* 0x544 Read QoS Configuration 0 */ + uint32_t pcfgqos1_1; /* 0x548 Read QoS Configuration 1 */ + uint32_t pcfgwqos0_1; /* 0x54c Write QoS Configuration 0 */ + uint32_t pcfgwqos1_1; /* 0x550 Write QoS Configuration 1 */ +#endif + + uint8_t reserved554[0xff0 - 0x554]; + uint32_t umctl2_ver_number; /* 0xff0 UMCTL2 Version Number */ +} __packed; + +/* DDR Controller registers offsets */ +#define DDRCTRL_MSTR 0x000 +#define DDRCTRL_STAT 0x004 +#define DDRCTRL_MRCTRL0 0x010 +#define DDRCTRL_MRSTAT 0x018 +#define DDRCTRL_PWRCTL 0x030 +#define DDRCTRL_PWRTMG 0x034 +#define DDRCTRL_HWLPCTL 0x038 +#define DDRCTRL_RFSHCTL3 0x060 +#define DDRCTRL_RFSHTMG 0x064 +#define DDRCTRL_INIT0 0x0D0 +#define DDRCTRL_DFIMISC 0x1B0 +#define DDRCTRL_DBG1 0x304 +#define DDRCTRL_DBGCAM 0x308 +#define DDRCTRL_DBGCMD 0x30C +#define DDRCTRL_DBGSTAT 0x310 +#define DDRCTRL_SWCTL 0x320 +#define DDRCTRL_SWSTAT 0x324 +#define DDRCTRL_PSTAT 0x3FC +#define DDRCTRL_PCTRL_0 0x490 +#if STM32MP_DDR_DUAL_AXI_PORT +#define DDRCTRL_PCTRL_1 0x540 +#endif + +/* DDR Controller Register fields */ +#define DDRCTRL_MSTR_DDR3 BIT(0) +#define DDRCTRL_MSTR_LPDDR2 BIT(2) +#define DDRCTRL_MSTR_LPDDR3 BIT(3) +#define DDRCTRL_MSTR_DDR4 BIT(4) +#define DDRCTRL_MSTR_LPDDR4 BIT(5) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK GENMASK(13, 12) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL 0 +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF BIT(12) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER BIT(13) +#define DDRCTRL_MSTR_DLL_OFF_MODE BIT(15) + +#define DDRCTRL_STAT_OPERATING_MODE_MASK GENMASK(2, 0) +#define DDRCTRL_STAT_OPERATING_MODE_NORMAL BIT(0) +#define DDRCTRL_STAT_OPERATING_MODE_SR (BIT(0) | BIT(1)) +#define DDRCTRL_STAT_SELFREF_TYPE_MASK GENMASK(5, 4) +#define DDRCTRL_STAT_SELFREF_TYPE_ASR (BIT(4) | BIT(5)) +#define DDRCTRL_STAT_SELFREF_TYPE_SR BIT(5) + +#define DDRCTRL_MRCTRL0_MR_TYPE_WRITE U(0) +/* Only one rank supported */ +#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4 +#define DDRCTRL_MRCTRL0_MR_RANK_ALL \ + BIT(DDRCTRL_MRCTRL0_MR_RANK_SHIFT) +#define DDRCTRL_MRCTRL0_MR_ADDR_SHIFT 12 +#define DDRCTRL_MRCTRL0_MR_ADDR_MASK GENMASK(15, 12) +#define DDRCTRL_MRCTRL0_MR_WR BIT(31) + +#define DDRCTRL_MRSTAT_MR_WR_BUSY BIT(0) + +#define DDRCTRL_PWRCTL_SELFREF_EN BIT(0) +#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1) +#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3) +#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5) + +#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(23, 16) +#define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16) + +#define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0) +#define DDRCTRL_RFSHCTL3_REFRESH_UPDATE_LEVEL BIT(1) + +#define DDRCTRL_HWLPCTL_HW_LP_EN BIT(0) + +#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK GENMASK(27, 16) +#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16 + +#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK GENMASK(31, 30) +#define DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL BIT(30) + +#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0) +#define DDRCTRL_DFIMISC_DFI_INIT_START BIT(5) + +#define DDRCTRL_DFISTAT_DFI_INIT_COMPLETE BIT(0) + +#define DDRCTRL_DBG1_DIS_HIF BIT(1) + +#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY BIT(29) +#define DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY BIT(28) +#define DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY BIT(26) +#define DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH GENMASK(12, 8) +#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK(4, 0) +#define DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY \ + (DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY | \ + DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY) +#define DDRCTRL_DBGCAM_DBG_Q_DEPTH \ + (DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \ + DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH | \ + DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH) + +#define DDRCTRL_DBGCMD_RANK0_REFRESH BIT(0) + +#define DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY BIT(0) + +#define DDRCTRL_SWCTL_SW_DONE BIT(0) + +#define DDRCTRL_SWSTAT_SW_DONE_ACK BIT(0) + +#define DDRCTRL_PCTRL_N_PORT_EN BIT(0) + +#endif /* STM32MP_DDRCTRL_REGS_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h b/arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h new file mode 100644 index 0000000..303c571 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_PMIC_H +#define STM32MP_PMIC_H + +#include + +#include + +/* + * dt_pmic_status - Check PMIC status from device tree + * + * Returns the status of the PMIC (secure, non-secure), or a negative value on + * error + */ +int dt_pmic_status(void); + +/* + * initialize_pmic_i2c - Initialize I2C for the PMIC control + * + * Returns true if PMIC is available, false if not found, panics on errors + */ +bool initialize_pmic_i2c(void); + +/* + * initialize_pmic - Main PMIC initialization function, called at platform init + * + * Panics on errors + */ +void initialize_pmic(void); + +#if DEBUG +void print_pmic_info_and_debug(void); +#else +static inline void print_pmic_info_and_debug(void) +{ +} +#endif + +/* + * pmic_ddr_power_init - Initialize regulators required for DDR + * + * Returns 0 on success, and negative values on errors + */ +int pmic_ddr_power_init(enum ddr_type ddr_type); + +/* + * pmic_voltages_init - Update voltages for platform init + * + * Returns 0 on success, and negative values on errors + */ +int pmic_voltages_init(void); + +#endif /* STM32MP_PMIC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_ram.h b/arm-trusted-firmware/include/drivers/st/stm32mp_ram.h new file mode 100644 index 0000000..6e1e21d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_ram.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef STM32MP_RAM_H +#define STM32MP_RAM_H + +#include + +#include + +#define PARAM(x, y) \ + { \ + .name = x, \ + .offset = offsetof(struct stm32mp_ddr_config, y), \ + .size = sizeof(config.y) / sizeof(uint32_t), \ + } + +#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) +#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) + +struct stm32mp_ddr_param { + const char *name; /* Name in DT */ + const uint32_t offset; /* Offset in config struct */ + const uint32_t size; /* Size of parameters */ +}; + +int stm32mp_ddr_dt_get_info(void *fdt, int node, struct stm32mp_ddr_info *info); +int stm32mp_ddr_dt_get_param(void *fdt, int node, const struct stm32mp_ddr_param *param, + uint32_t param_size, uintptr_t config); + +#endif /* STM32MP_RAM_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_reset.h b/arm-trusted-firmware/include/drivers/st/stm32mp_reset.h new file mode 100644 index 0000000..8444805 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_reset.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_RESET_H +#define STM32MP_RESET_H + +#include + +/* + * Assert target reset, if @to_us non null, wait until reset is asserted + * + * @reset_id: Reset controller ID + * @to_us: Timeout in microsecond, or 0 if not waiting + * Return 0 on success and -ETIMEDOUT if waiting and timeout expired + */ +int stm32mp_reset_assert(uint32_t reset_id, unsigned int to_us); + +/* + * Enable reset control for target resource + * + * @reset_id: Reset controller ID + */ +static inline void stm32mp_reset_set(uint32_t reset_id) +{ + (void)stm32mp_reset_assert(reset_id, 0U); +} + +/* + * Deassert target reset, if @to_us non null, wait until reset is deasserted + * + * @reset_id: Reset controller ID + * @to_us: Timeout in microsecond, or 0 if not waiting + * Return 0 on success and -ETIMEDOUT if waiting and timeout expired + */ +int stm32mp_reset_deassert(uint32_t reset_id, unsigned int to_us); + +/* + * Release reset control for target resource + * + * @reset_id: Reset controller ID + */ +static inline void stm32mp_reset_release(uint32_t reset_id) +{ + (void)stm32mp_reset_deassert(reset_id, 0U); +} + +#endif /* STM32MP_RESET_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stpmic1.h b/arm-trusted-firmware/include/drivers/st/stpmic1.h new file mode 100644 index 0000000..2dfc7f8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stpmic1.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STPMIC1_H +#define STPMIC1_H + +#include +#include + +#define TURN_ON_REG 0x1U +#define TURN_OFF_REG 0x2U +#define ICC_LDO_TURN_OFF_REG 0x3U +#define ICC_BUCK_TURN_OFF_REG 0x4U +#define RESET_STATUS_REG 0x5U +#define VERSION_STATUS_REG 0x6U +#define MAIN_CONTROL_REG 0x10U +#define PADS_PULL_REG 0x11U +#define BUCK_PULL_DOWN_REG 0x12U +#define LDO14_PULL_DOWN_REG 0x13U +#define LDO56_PULL_DOWN_REG 0x14U +#define VIN_CONTROL_REG 0x15U +#define PONKEY_TIMER_REG 0x16U +#define MASK_RANK_BUCK_REG 0x17U +#define MASK_RESET_BUCK_REG 0x18U +#define MASK_RANK_LDO_REG 0x19U +#define MASK_RESET_LDO_REG 0x1AU +#define WATCHDOG_CONTROL_REG 0x1BU +#define WATCHDOG_TIMER_REG 0x1CU +#define BUCK_ICC_TURNOFF_REG 0x1DU +#define LDO_ICC_TURNOFF_REG 0x1EU +#define BUCK_APM_CONTROL_REG 0x1FU +#define BUCK1_CONTROL_REG 0x20U +#define BUCK2_CONTROL_REG 0x21U +#define BUCK3_CONTROL_REG 0x22U +#define BUCK4_CONTROL_REG 0x23U +#define VREF_DDR_CONTROL_REG 0x24U +#define LDO1_CONTROL_REG 0x25U +#define LDO2_CONTROL_REG 0x26U +#define LDO3_CONTROL_REG 0x27U +#define LDO4_CONTROL_REG 0x28U +#define LDO5_CONTROL_REG 0x29U +#define LDO6_CONTROL_REG 0x2AU +#define BUCK1_PWRCTRL_REG 0x30U +#define BUCK2_PWRCTRL_REG 0x31U +#define BUCK3_PWRCTRL_REG 0x32U +#define BUCK4_PWRCTRL_REG 0x33U +#define VREF_DDR_PWRCTRL_REG 0x34U +#define LDO1_PWRCTRL_REG 0x35U +#define LDO2_PWRCTRL_REG 0x36U +#define LDO3_PWRCTRL_REG 0x37U +#define LDO4_PWRCTRL_REG 0x38U +#define LDO5_PWRCTRL_REG 0x39U +#define LDO6_PWRCTRL_REG 0x3AU +#define FREQUENCY_SPREADING_REG 0x3BU +#define USB_CONTROL_REG 0x40U +#define ITLATCH1_REG 0x50U +#define ITLATCH2_REG 0x51U +#define ITLATCH3_REG 0x52U +#define ITLATCH4_REG 0x53U +#define ITSETLATCH1_REG 0x60U +#define ITSETLATCH2_REG 0x61U +#define ITSETLATCH3_REG 0x62U +#define ITSETLATCH4_REG 0x63U +#define ITCLEARLATCH1_REG 0x70U +#define ITCLEARLATCH2_REG 0x71U +#define ITCLEARLATCH3_REG 0x72U +#define ITCLEARLATCH4_REG 0x73U +#define ITMASK1_REG 0x80U +#define ITMASK2_REG 0x81U +#define ITMASK3_REG 0x82U +#define ITMASK4_REG 0x83U +#define ITSETMASK1_REG 0x90U +#define ITSETMASK2_REG 0x91U +#define ITSETMASK3_REG 0x92U +#define ITSETMASK4_REG 0x93U +#define ITCLEARMASK1_REG 0xA0U +#define ITCLEARMASK2_REG 0xA1U +#define ITCLEARMASK3_REG 0xA2U +#define ITCLEARMASK4_REG 0xA3U +#define ITSOURCE1_REG 0xB0U +#define ITSOURCE2_REG 0xB1U +#define ITSOURCE3_REG 0xB2U +#define ITSOURCE4_REG 0xB3U + +/* Registers masks */ +#define LDO_VOLTAGE_MASK GENMASK(6, 2) +#define BUCK_VOLTAGE_MASK GENMASK(7, 2) +#define LDO_BUCK_VOLTAGE_SHIFT 2 +#define LDO_BUCK_ENABLE_MASK BIT(0) +#define LDO_BUCK_HPLP_ENABLE_MASK BIT(1) +#define LDO_BUCK_HPLP_SHIFT 1 +#define LDO_BUCK_RANK_MASK BIT(0) +#define LDO_BUCK_RESET_MASK BIT(0) +#define LDO_BUCK_PULL_DOWN_MASK GENMASK(1, 0) + +/* Pull down register */ +#define BUCK1_PULL_DOWN_SHIFT 0 +#define BUCK2_PULL_DOWN_SHIFT 2 +#define BUCK3_PULL_DOWN_SHIFT 4 +#define BUCK4_PULL_DOWN_SHIFT 6 +#define VREF_DDR_PULL_DOWN_SHIFT 4 + +/* ICC register */ +#define BUCK1_ICC_SHIFT 0 +#define BUCK2_ICC_SHIFT 1 +#define BUCK3_ICC_SHIFT 2 +#define BUCK4_ICC_SHIFT 3 +#define PWR_SW1_ICC_SHIFT 4 +#define PWR_SW2_ICC_SHIFT 5 +#define BOOST_ICC_SHIFT 6 + +#define LDO1_ICC_SHIFT 0 +#define LDO2_ICC_SHIFT 1 +#define LDO3_ICC_SHIFT 2 +#define LDO4_ICC_SHIFT 3 +#define LDO5_ICC_SHIFT 4 +#define LDO6_ICC_SHIFT 5 + +/* Buck Mask reset register */ +#define BUCK1_MASK_RESET 0 +#define BUCK2_MASK_RESET 1 +#define BUCK3_MASK_RESET 2 +#define BUCK4_MASK_RESET 3 + +/* LDO Mask reset register */ +#define LDO1_MASK_RESET 0 +#define LDO2_MASK_RESET 1 +#define LDO3_MASK_RESET 2 +#define LDO4_MASK_RESET 3 +#define LDO5_MASK_RESET 4 +#define LDO6_MASK_RESET 5 +#define VREF_DDR_MASK_RESET 6 + +/* LDO3 Special modes */ +#define LDO3_BYPASS BIT(7) +#define LDO3_DDR_SEL 31U + +/* Main PMIC Control Register (MAIN_CONTROL_REG) */ +#define ICC_EVENT_ENABLED BIT(4) +#define PWRCTRL_POLARITY_HIGH BIT(3) +#define PWRCTRL_PIN_VALID BIT(2) +#define RESTART_REQUEST_ENABLED BIT(1) +#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0) + +/* Main PMIC PADS Control Register (PADS_PULL_REG) */ +#define WAKEUP_DETECTOR_DISABLED BIT(4) +#define PWRCTRL_PD_ACTIVE BIT(3) +#define PWRCTRL_PU_ACTIVE BIT(2) +#define WAKEUP_PD_ACTIVE BIT(1) +#define PONKEY_PU_ACTIVE BIT(0) + +/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ +#define SWIN_DETECTOR_ENABLED BIT(7) +#define SWOUT_DETECTOR_ENABLED BIT(6) +#define VINLOW_HYST_MASK GENMASK(1, 0) +#define VINLOW_HYST_SHIFT 4 +#define VINLOW_THRESHOLD_MASK GENMASK(2, 0) +#define VINLOW_THRESHOLD_SHIFT 1 +#define VINLOW_ENABLED BIT(0) +#define VINLOW_CTRL_REG_MASK GENMASK(7, 0) + +/* USB Control Register */ +#define BOOST_OVP_DISABLED BIT(7) +#define VBUS_OTG_DETECTION_DISABLED BIT(6) +#define SW_OUT_DISCHARGE BIT(5) +#define VBUS_OTG_DISCHARGE BIT(4) +#define OCP_LIMIT_HIGH BIT(3) +#define SWIN_SWOUT_ENABLED BIT(2) +#define USBSW_OTG_SWITCH_ENABLED BIT(1) +#define BOOST_ENABLED BIT(0) + +int stpmic1_powerctrl_on(void); +int stpmic1_switch_off(void); +int stpmic1_register_read(uint8_t register_id, uint8_t *value); +int stpmic1_register_write(uint8_t register_id, uint8_t value); +int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); +int stpmic1_regulator_enable(const char *name); +int stpmic1_regulator_disable(const char *name); +bool stpmic1_is_regulator_enabled(const char *name); +int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); +int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, + size_t *levels_count); +int stpmic1_regulator_voltage_get(const char *name); +int stpmic1_regulator_pull_down_set(const char *name); +int stpmic1_regulator_mask_reset_set(const char *name); +int stpmic1_regulator_icc_set(const char *name); +int stpmic1_regulator_sink_mode_set(const char *name); +int stpmic1_regulator_bypass_mode_set(const char *name); +int stpmic1_active_discharge_mode_set(const char *name); +void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); + +int stpmic1_get_version(unsigned long *version); +void stpmic1_dump_regulators(void); + +#endif /* STPMIC1_H */ diff --git a/arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h b/arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h new file mode 100644 index 0000000..2004355 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DW_MMC_H +#define DW_MMC_H + +#include + +typedef struct dw_mmc_params { + uintptr_t reg_base; + uintptr_t desc_base; + size_t desc_size; + int clk_rate; + int bus_width; + unsigned int flags; + enum mmc_device_type mmc_dev_type; +} dw_mmc_params_t; + +void dw_mmc_init(dw_mmc_params_t *params, struct mmc_device_info *info); + +#endif /* DW_MMC_H */ diff --git a/arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h b/arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h new file mode 100644 index 0000000..bddd997 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UART_16550_H +#define UART_16550_H + +#include + +/* UART16550 Registers */ +#define UARTTX 0x0 +#define UARTRX 0x0 +#define UARTDLL 0x0 +#define UARTIER 0x4 +#define UARTDLLM 0x4 +#define UARTIIR 0x8 +#define UARTFCR 0x8 +#define UARTLCR 0xc +#define UARTMCR 0x10 +#define UARTLSR 0x14 +#define UARTMSR 0x18 +#define UARTSPR 0x1c +#define UARTCSR 0x20 +/* Some instances have MDR1 defined as well */ +#define UARTMDR1 0x20 +#define UARTRXFIFOCFG 0x24 +#define UARTMIE 0x28 +#define UARTVNDR 0x2c +#define UARTASR 0x3c + +/* FIFO Control Register bits */ +#define UARTFCR_FIFOMD_16450 (0 << 6) +#define UARTFCR_FIFOMD_16550 (1 << 6) +#define UARTFCR_RXTRIG_1 (0 << 6) +#define UARTFCR_RXTRIG_4 (1 << 6) +#define UARTFCR_RXTRIG_8 (2 << 6) +#define UARTFCR_RXTRIG_16 (3 << 6) +#define UARTFCR_TXTRIG_1 (0 << 4) +#define UARTFCR_TXTRIG_4 (1 << 4) +#define UARTFCR_TXTRIG_8 (2 << 4) +#define UARTFCR_TXTRIG_16 (3 << 4) +#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */ +#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */ +#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */ +#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */ + +/* Line Control Register bits */ +#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */ +#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */ +#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */ +#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */ +#define UARTLCR_PAR (1 << 3) /* Parity */ +#define UARTLCR_STOP (1 << 2) /* Stop Bit */ +#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */ +#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */ +#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */ +#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */ + +/* Line Status Register bits */ +#define UARTLSR_RXFIFOEMT (1 << 9) /* Rx Fifo Empty */ +#define UARTLSR_TXFIFOFULL (1 << 8) /* Tx Fifo Full */ +#define UARTLSR_RXFIFOERR (1 << 7) /* Rx Fifo Error */ +#define UARTLSR_TEMT (1 << 6) /* Tx Shift Register Empty */ +#define UARTLSR_THRE (1 << 5) /* Tx Holding Register Empty */ +#define UARTLSR_BRK (1 << 4) /* Break Condition Detected */ +#define UARTLSR_FERR (1 << 3) /* Framing Error */ +#define UARTLSR_PERR (1 << 3) /* Parity Error */ +#define UARTLSR_OVRF (1 << 2) /* Rx Overrun Error */ +#define UARTLSR_RDR_BIT (0) /* Rx Data Ready Bit */ +#define UARTLSR_RDR (1 << UARTLSR_RDR_BIT) /* Rx Data Ready */ + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new 16550 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. + * When |clock| has a value of 0, the UART will *not* be initialised. This + * means the UART should already be enabled and the baudrate and clock setup + * should have been done already, either by platform specific code or by + * previous firmware stages. The |baud| parameter will be ignored in this + * case as well. + */ +int console_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* UART_16550_H */ diff --git a/arm-trusted-firmware/include/drivers/ufs.h b/arm-trusted-firmware/include/drivers/ufs.h new file mode 100644 index 0000000..c074e85 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/ufs.h @@ -0,0 +1,559 @@ +/* + * 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 + +/* maximum number of retries for a general UIC command */ +#define UFS_UIC_COMMAND_RETRIES 3 + +/* maximum number of link-startup retries */ +#define DME_LINKSTARTUP_RETRIES 10 + +#define HCE_ENABLE_OUTER_RETRIES 3 +#define HCE_ENABLE_INNER_RETRIES 50 +#define HCE_ENABLE_TIMEOUT_US 100 + +/** + * 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/arm-trusted-firmware/include/drivers/usb_device.h b/arm-trusted-firmware/include/drivers/usb_device.h new file mode 100644 index 0000000..8fdb6ae --- /dev/null +++ b/arm-trusted-firmware/include/drivers/usb_device.h @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef USB_DEVICE_H +#define USB_DEVICE_H + +#include + +#include + +#define USBD_MAX_NUM_INTERFACES 1U +#define USBD_MAX_NUM_CONFIGURATION 1U + +#define USB_LEN_DEV_QUALIFIER_DESC 0x0AU +#define USB_LEN_DEV_DESC 0x12U +#define USB_LEN_CFG_DESC 0x09U +#define USB_LEN_IF_DESC 0x09U +#define USB_LEN_EP_DESC 0x07U +#define USB_LEN_OTG_DESC 0x03U +#define USB_LEN_LANGID_STR_DESC 0x04U +#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09U + +#define USBD_IDX_LANGID_STR 0x00U +#define USBD_IDX_MFC_STR 0x01U +#define USBD_IDX_PRODUCT_STR 0x02U +#define USBD_IDX_SERIAL_STR 0x03U +#define USBD_IDX_CONFIG_STR 0x04U +#define USBD_IDX_INTERFACE_STR 0x05U +#define USBD_IDX_USER0_STR 0x06U + +#define USB_REQ_TYPE_STANDARD 0x00U +#define USB_REQ_TYPE_CLASS 0x20U +#define USB_REQ_TYPE_VENDOR 0x40U +#define USB_REQ_TYPE_MASK 0x60U + +#define USB_REQ_RECIPIENT_DEVICE 0x00U +#define USB_REQ_RECIPIENT_INTERFACE 0x01U +#define USB_REQ_RECIPIENT_ENDPOINT 0x02U +#define USB_REQ_RECIPIENT_MASK 0x1FU + +#define USB_REQ_DIRECTION 0x80U + +#define USB_REQ_GET_STATUS 0x00U +#define USB_REQ_CLEAR_FEATURE 0x01U +#define USB_REQ_SET_FEATURE 0x03U +#define USB_REQ_SET_ADDRESS 0x05U +#define USB_REQ_GET_DESCRIPTOR 0x06U +#define USB_REQ_SET_DESCRIPTOR 0x07U +#define USB_REQ_GET_CONFIGURATION 0x08U +#define USB_REQ_SET_CONFIGURATION 0x09U +#define USB_REQ_GET_INTERFACE 0x0AU +#define USB_REQ_SET_INTERFACE 0x0BU +#define USB_REQ_SYNCH_FRAME 0x0CU + +#define USB_DESC_TYPE_DEVICE 0x01U +#define USB_DESC_TYPE_CONFIGURATION 0x02U +#define USB_DESC_TYPE_STRING 0x03U +#define USB_DESC_TYPE_INTERFACE 0x04U +#define USB_DESC_TYPE_ENDPOINT 0x05U +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U +#define USB_DESC_TYPE_BOS 0x0FU + +#define USB_CONFIG_REMOTE_WAKEUP 2U +#define USB_CONFIG_SELF_POWERED 1U + +#define USB_MAX_EP0_SIZE 64U + +/* Device Status */ +#define USBD_STATE_DEFAULT 1U +#define USBD_STATE_ADDRESSED 2U +#define USBD_STATE_CONFIGURED 3U +#define USBD_STATE_SUSPENDED 4U + +/* EP0 State */ +#define USBD_EP0_IDLE 0U +#define USBD_EP0_SETUP 1U +#define USBD_EP0_DATA_IN 2U +#define USBD_EP0_DATA_OUT 3U +#define USBD_EP0_STATUS_IN 4U +#define USBD_EP0_STATUS_OUT 5U +#define USBD_EP0_STALL 6U + +#define USBD_EP_TYPE_CTRL 0U +#define USBD_EP_TYPE_ISOC 1U +#define USBD_EP_TYPE_BULK 2U +#define USBD_EP_TYPE_INTR 3U + +#define USBD_OUT_EPNUM_MASK GENMASK(15, 0) +#define USBD_OUT_COUNT_MASK GENMASK(31, 16) +#define USBD_OUT_COUNT_SHIFT 16U + +/* Number of EP supported, allow to reduce footprint: default max = 15 */ +#ifndef CONFIG_USBD_EP_NB +#define USBD_EP_NB 15U +#else +#define USBD_EP_NB CONFIG_USBD_EP_NB +#endif + +#define LOBYTE(x) ((uint8_t)((x) & 0x00FF)) +#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00) >> 8)) + +struct usb_setup_req { + uint8_t bm_request; + uint8_t b_request; + uint16_t value; + uint16_t index; + uint16_t length; +}; + +struct usb_handle; + +struct usb_class { + uint8_t (*init)(struct usb_handle *pdev, uint8_t cfgidx); + uint8_t (*de_init)(struct usb_handle *pdev, uint8_t cfgidx); + /* Control Endpoints */ + uint8_t (*setup)(struct usb_handle *pdev, struct usb_setup_req *req); + uint8_t (*ep0_tx_sent)(struct usb_handle *pdev); + uint8_t (*ep0_rx_ready)(struct usb_handle *pdev); + /* Class Specific Endpoints */ + uint8_t (*data_in)(struct usb_handle *pdev, uint8_t epnum); + uint8_t (*data_out)(struct usb_handle *pdev, uint8_t epnum); + uint8_t (*sof)(struct usb_handle *pdev); + uint8_t (*iso_in_incomplete)(struct usb_handle *pdev, uint8_t epnum); + uint8_t (*iso_out_incomplete)(struct usb_handle *pdev, uint8_t epnum); +}; + +/* Following USB Device status */ +enum usb_status { + USBD_OK = 0U, + USBD_BUSY, + USBD_FAIL, + USBD_TIMEOUT +}; + +/* Action to do after IT handling */ +enum usb_action { + USB_NOTHING = 0U, + USB_DATA_OUT, + USB_DATA_IN, + USB_SETUP, + USB_ENUM_DONE, + USB_READ_DATA_PACKET, + USB_READ_SETUP_PACKET, + USB_RESET, + USB_RESUME, + USB_SUSPEND, + USB_LPM, + USB_SOF, + USB_DISCONNECT, + USB_WRITE_EMPTY +}; + +/* USB Device descriptors structure */ +struct usb_desc { + uint8_t *(*get_device_desc)(uint16_t *length); + uint8_t *(*get_lang_id_desc)(uint16_t *length); + uint8_t *(*get_manufacturer_desc)(uint16_t *length); + uint8_t *(*get_product_desc)(uint16_t *length); + uint8_t *(*get_serial_desc)(uint16_t *length); + uint8_t *(*get_configuration_desc)(uint16_t *length); + uint8_t *(*get_interface_desc)(uint16_t *length); + uint8_t *(*get_usr_desc)(uint8_t index, uint16_t *length); + uint8_t *(*get_config_desc)(uint16_t *length); + uint8_t *(*get_device_qualifier_desc)(uint16_t *length); + /* optional: high speed capable device operating at its other speed */ + uint8_t *(*get_other_speed_config_desc)(uint16_t *length); +}; + +/* USB Device handle structure */ +struct usb_endpoint { + uint32_t status; + uint32_t total_length; + uint32_t rem_length; + uint32_t maxpacket; +}; + +/* + * EndPoint descriptor + * num : Endpoint number, between 0 and 15 (limited by USBD_EP_NB) + * is_in: Endpoint direction + * type : Endpoint type + * maxpacket: Endpoint Max packet size: between 0 and 64KB + * xfer_buff: Pointer to transfer buffer + * xfer_len: Current transfer lengt + * hxfer_count: Partial transfer length in case of multi packet transfer + */ +struct usbd_ep { + uint8_t num; + bool is_in; + uint8_t type; + uint32_t maxpacket; + uint8_t *xfer_buff; + uint32_t xfer_len; + uint32_t xfer_count; +}; + +enum pcd_lpm_state { + LPM_L0 = 0x00U, /* on */ + LPM_L1 = 0x01U, /* LPM L1 sleep */ + LPM_L2 = 0x02U, /* suspend */ + LPM_L3 = 0x03U, /* off */ +}; + +/* USB Device descriptors structure */ +struct usb_driver { + enum usb_status (*ep0_out_start)(void *handle); + enum usb_status (*ep_start_xfer)(void *handle, struct usbd_ep *ep); + enum usb_status (*ep0_start_xfer)(void *handle, struct usbd_ep *ep); + enum usb_status (*write_packet)(void *handle, uint8_t *src, + uint8_t ch_ep_num, uint16_t len); + void *(*read_packet)(void *handle, uint8_t *dest, uint16_t len); + enum usb_status (*ep_set_stall)(void *handle, struct usbd_ep *ep); + enum usb_status (*start_device)(void *handle); + enum usb_status (*stop_device)(void *handle); + enum usb_status (*set_address)(void *handle, uint8_t address); + enum usb_status (*write_empty_tx_fifo)(void *handle, + uint32_t epnum, uint32_t xfer_len, + uint32_t *xfer_count, + uint32_t maxpacket, + uint8_t **xfer_buff); + enum usb_action (*it_handler)(void *handle, uint32_t *param); +}; + +/* USB Peripheral Controller Drivers */ +struct pcd_handle { + void *instance; /* Register base address */ + struct usbd_ep in_ep[USBD_EP_NB]; /* IN endpoint parameters */ + struct usbd_ep out_ep[USBD_EP_NB]; /* OUT endpoint parameters */ + uint32_t setup[12]; /* Setup packet buffer */ + enum pcd_lpm_state lpm_state; /* LPM State */ +}; + +/* USB Device handle structure */ +struct usb_handle { + uint8_t id; + uint32_t dev_config; + uint32_t dev_config_status; + struct usb_endpoint ep_in[USBD_EP_NB]; + struct usb_endpoint ep_out[USBD_EP_NB]; + uint32_t ep0_state; + uint32_t ep0_data_len; + uint8_t dev_state; + uint8_t dev_old_state; + uint8_t dev_address; + uint32_t dev_remote_wakeup; + struct usb_setup_req request; + const struct usb_desc *desc; + struct usb_class *class; + void *class_data; + void *user_data; + struct pcd_handle *data; + const struct usb_driver *driver; +}; + +enum usb_status usb_core_handle_it(struct usb_handle *pdev); +enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *p_buf, uint32_t len); +enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *p_buf, uint32_t len); +enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *p_buf, + uint32_t len); +enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *p_buf, + uint32_t len); +void usb_core_ctl_error(struct usb_handle *pdev); +enum usb_status usb_core_start(struct usb_handle *pdev); +enum usb_status usb_core_stop(struct usb_handle *pdev); +enum usb_status register_usb_driver(struct usb_handle *pdev, + struct pcd_handle *pcd_handle, + const struct usb_driver *driver, + void *driver_handle); +enum usb_status register_platform(struct usb_handle *pdev, + const struct usb_desc *plat_call_back); + +#endif /* USB_DEVICE_H */ diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h new file mode 100644 index 0000000..0d25ded --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018-2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#if STM32MP13 +#include "stm32mp13-clks.h" +#endif +#if STM32MP15 +#include "stm32mp15-clks.h" +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h new file mode 100644 index 0000000..d02ddcd --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2017-2022, STMicroelectronics - All Rights Reserved + */ + +#if STM32MP13 +#include "stm32mp13-clksrc.h" +#endif +#if STM32MP15 +#include "stm32mp15-clksrc.h" +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h new file mode 100644 index 0000000..1d5bb78 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP13_CLKS_H_ +#define _DT_BINDINGS_STM32MP13_CLKS_H_ + +/* OSCILLATOR clocks */ +#define CK_HSE 0 +#define CK_CSI 1 +#define CK_LSI 2 +#define CK_LSE 3 +#define CK_HSI 4 +#define CK_HSE_DIV2 5 + +/* PLL */ +#define PLL1 6 +#define PLL2 7 +#define PLL3 8 +#define PLL4 9 + +/* ODF */ +#define PLL1_P 10 +#define PLL1_Q 11 +#define PLL1_R 12 +#define PLL2_P 13 +#define PLL2_Q 14 +#define PLL2_R 15 +#define PLL3_P 16 +#define PLL3_Q 17 +#define PLL3_R 18 +#define PLL4_P 19 +#define PLL4_Q 20 +#define PLL4_R 21 + +#define PCLK1 22 +#define PCLK2 23 +#define PCLK3 24 +#define PCLK4 25 +#define PCLK5 26 +#define PCLK6 27 + +/* SYSTEM CLOCK */ +#define CK_PER 28 +#define CK_MPU 29 +#define CK_AXI 30 +#define CK_MLAHB 31 + +/* BASE TIMER */ +#define CK_TIMG1 32 +#define CK_TIMG2 33 +#define CK_TIMG3 34 + +/* AUX */ +#define RTC 35 + +/* TRACE & DEBUG clocks */ +#define CK_DBG 36 +#define CK_TRACE 37 + +/* MCO clocks */ +#define CK_MCO1 38 +#define CK_MCO2 39 + +/* IP clocks */ +#define SYSCFG 40 +#define VREF 41 +#define TMPSENS 42 +#define PMBCTRL 43 +#define HDP 44 +#define IWDG2 45 +#define STGENRO 46 +#define USART1 47 +#define RTCAPB 48 +#define TZC 49 +#define TZPC 50 +#define IWDG1 51 +#define BSEC 52 +#define DMA1 53 +#define DMA2 54 +#define DMAMUX1 55 +#define DMAMUX2 56 +#define GPIOA 57 +#define GPIOB 58 +#define GPIOC 59 +#define GPIOD 60 +#define GPIOE 61 +#define GPIOF 62 +#define GPIOG 63 +#define GPIOH 64 +#define GPIOI 65 +#define CRYP1 66 +#define HASH1 67 +#define BKPSRAM 68 +#define MDMA 69 +#define CRC1 70 +#define USBH 71 +#define DMA3 72 +#define TSC 73 +#define PKA 74 +#define AXIMC 75 +#define MCE 76 +#define ETH1TX 77 +#define ETH2TX 78 +#define ETH1RX 79 +#define ETH2RX 80 +#define ETH1MAC 81 +#define ETH2MAC 82 +#define ETH1STP 83 +#define ETH2STP 84 + +/* IP clocks with parents */ +#define SDMMC1_K 85 +#define SDMMC2_K 86 +#define ADC1_K 87 +#define ADC2_K 88 +#define FMC_K 89 +#define QSPI_K 90 +#define RNG1_K 91 +#define USBPHY_K 92 +#define STGEN_K 93 +#define SPDIF_K 94 +#define SPI1_K 95 +#define SPI2_K 96 +#define SPI3_K 97 +#define SPI4_K 98 +#define SPI5_K 99 +#define I2C1_K 100 +#define I2C2_K 101 +#define I2C3_K 102 +#define I2C4_K 103 +#define I2C5_K 104 +#define TIM2_K 105 +#define TIM3_K 106 +#define TIM4_K 107 +#define TIM5_K 108 +#define TIM6_K 109 +#define TIM7_K 110 +#define TIM12_K 111 +#define TIM13_K 112 +#define TIM14_K 113 +#define TIM1_K 114 +#define TIM8_K 115 +#define TIM15_K 116 +#define TIM16_K 117 +#define TIM17_K 118 +#define LPTIM1_K 119 +#define LPTIM2_K 120 +#define LPTIM3_K 121 +#define LPTIM4_K 122 +#define LPTIM5_K 123 +#define USART1_K 124 +#define USART2_K 125 +#define USART3_K 126 +#define UART4_K 127 +#define UART5_K 128 +#define USART6_K 129 +#define UART7_K 130 +#define UART8_K 131 +#define DFSDM_K 132 +#define FDCAN_K 133 +#define SAI1_K 134 +#define SAI2_K 135 +#define ADFSDM_K 136 +#define USBO_K 137 +#define LTDC_PX 138 +#define ETH1CK_K 139 +#define ETH1PTP_K 140 +#define ETH2CK_K 141 +#define ETH2PTP_K 142 +#define DCMIPP_K 143 +#define SAES_K 144 +#define DTS_K 145 + +/* DDR */ +#define DDRC1 146 +#define DDRC1LP 147 +#define DDRC2 148 +#define DDRC2LP 149 +#define DDRPHYC 150 +#define DDRPHYCLP 151 +#define DDRCAPB 152 +#define DDRCAPBLP 153 +#define AXIDCG 154 +#define DDRPHYCAPB 155 +#define DDRPHYCAPBLP 156 +#define DDRPERFM 157 + +#define ADC1 158 +#define ADC2 159 +#define SAI1 160 +#define SAI2 161 + +#define STM32MP1_LAST_CLK 162 + +/* SCMI clock identifiers */ +#define CK_SCMI0_HSE 0 +#define CK_SCMI0_HSI 1 +#define CK_SCMI0_CSI 2 +#define CK_SCMI0_LSE 3 +#define CK_SCMI0_LSI 4 +#define CK_SCMI0_HSE_DIV2 5 +#define CK_SCMI0_PLL2_Q 6 +#define CK_SCMI0_PLL2_R 7 +#define CK_SCMI0_PLL3_P 8 +#define CK_SCMI0_PLL3_Q 9 +#define CK_SCMI0_PLL3_R 10 +#define CK_SCMI0_PLL4_P 11 +#define CK_SCMI0_PLL4_Q 12 +#define CK_SCMI0_PLL4_R 13 +#define CK_SCMI0_MPU 14 +#define CK_SCMI0_AXI 15 +#define CK_SCMI0_MLAHB 16 +#define CK_SCMI0_CKPER 17 +#define CK_SCMI0_PCLK1 18 +#define CK_SCMI0_PCLK2 19 +#define CK_SCMI0_PCLK3 20 +#define CK_SCMI0_PCLK4 21 +#define CK_SCMI0_PCLK5 22 +#define CK_SCMI0_PCLK6 23 +#define CK_SCMI0_CKTIMG1 24 +#define CK_SCMI0_CKTIMG2 25 +#define CK_SCMI0_CKTIMG3 26 +#define CK_SCMI0_RTC 27 +#define CK_SCMI0_RTCAPB 28 +#define CK_SCMI0_BSEC 29 + +#endif /* _DT_BINDINGS_STM32MP13_CLKS_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h new file mode 100644 index 0000000..0d54ab9 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ +#define _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ + +#define CMD_DIV 0 +#define CMD_MUX 1 +#define CMD_CLK 2 +#define CMD_RESERVED1 3 + +#define CMD_SHIFT 26 +#define CMD_MASK 0xFC000000 +#define CMD_DATA_MASK 0x03FFFFFF + +#define DIV_ID_SHIFT 8 +#define DIV_ID_MASK 0x0000FF00 + +#define DIV_DIVN_SHIFT 0 +#define DIV_DIVN_MASK 0x000000FF + +#define MUX_ID_SHIFT 4 +#define MUX_ID_MASK 0x00000FF0 + +#define MUX_SEL_SHIFT 0 +#define MUX_SEL_MASK 0x0000000F + +#define CLK_ID_MASK GENMASK_32(19, 11) +#define CLK_ID_SHIFT 11 +#define CLK_ON_MASK 0x00000400 +#define CLK_ON_SHIFT 10 +#define CLK_DIV_MASK GENMASK_32(9, 4) +#define CLK_DIV_SHIFT 4 +#define CLK_SEL_MASK GENMASK_32(3, 0) +#define CLK_SEL_SHIFT 0 + +#define DIV_PLL1DIVP 0 +#define DIV_PLL2DIVP 1 +#define DIV_PLL2DIVQ 2 +#define DIV_PLL2DIVR 3 +#define DIV_PLL3DIVP 4 +#define DIV_PLL3DIVQ 5 +#define DIV_PLL3DIVR 6 +#define DIV_PLL4DIVP 7 +#define DIV_PLL4DIVQ 8 +#define DIV_PLL4DIVR 9 +#define DIV_MPU 10 +#define DIV_AXI 11 +#define DIV_MLAHB 12 +#define DIV_APB1 13 +#define DIV_APB2 14 +#define DIV_APB3 15 +#define DIV_APB4 16 +#define DIV_APB5 17 +#define DIV_APB6 18 +#define DIV_RTC 19 +#define DIV_MCO1 20 +#define DIV_MCO2 21 +#define DIV_HSI 22 +#define DIV_TRACE 23 +#define DIV_ETH1PTP 24 +#define DIV_ETH2PTP 25 +#define DIV_MAX 26 + +#define DIV(div_id, div) ((CMD_DIV << CMD_SHIFT) |\ + ((div_id) << DIV_ID_SHIFT |\ + (div))) + +#define CLKSRC(mux_id, sel) ((CMD_MUX << CMD_SHIFT) |\ + ((mux_id) << MUX_ID_SHIFT |\ + (sel))) + +/* MCO output is enable */ +#define MCO_SRC(mco_id, sel) ((CMD_CLK << CMD_SHIFT) |\ + (((mco_id) << CLK_ID_SHIFT) |\ + (sel)) | CLK_ON_MASK) + +#define MCO_DISABLED(mco_id) ((CMD_CLK << CMD_SHIFT) |\ + ((mco_id) << CLK_ID_SHIFT)) + +/* CLK output is enable */ +#define CLK_SRC(clk_id, sel) ((CMD_CLK << CMD_SHIFT) |\ + (((clk_id) << CLK_ID_SHIFT) |\ + (sel)) | CLK_ON_MASK) + +#define CLK_DISABLED(clk_id) ((CMD_CLK << CMD_SHIFT) |\ + ((clk_id) << CLK_ID_SHIFT)) + +#define MUX_MPU 0 +#define MUX_AXI 1 +#define MUX_MLAHB 2 +#define MUX_PLL12 3 +#define MUX_PLL3 4 +#define MUX_PLL4 5 +#define MUX_RTC 6 +#define MUX_MCO1 7 +#define MUX_MCO2 8 +#define MUX_CKPER 9 +#define MUX_KERNEL_BEGIN 10 +#define MUX_ADC1 10 +#define MUX_ADC2 11 +#define MUX_DCMIPP 12 +#define MUX_ETH1 13 +#define MUX_ETH2 14 +#define MUX_FDCAN 15 +#define MUX_FMC 16 +#define MUX_I2C12 17 +#define MUX_I2C3 18 +#define MUX_I2C4 19 +#define MUX_I2C5 20 +#define MUX_LPTIM1 21 +#define MUX_LPTIM2 22 +#define MUX_LPTIM3 23 +#define MUX_LPTIM45 24 +#define MUX_QSPI 25 +#define MUX_RNG1 26 +#define MUX_SAES 27 +#define MUX_SAI1 28 +#define MUX_SAI2 29 +#define MUX_SDMMC1 30 +#define MUX_SDMMC2 31 +#define MUX_SPDIF 32 +#define MUX_SPI1 33 +#define MUX_SPI23 34 +#define MUX_SPI4 35 +#define MUX_SPI5 36 +#define MUX_STGEN 37 +#define MUX_UART1 38 +#define MUX_UART2 39 +#define MUX_UART35 40 +#define MUX_UART4 41 +#define MUX_UART6 42 +#define MUX_UART78 43 +#define MUX_USBO 44 +#define MUX_USBPHY 45 +#define MUX_MAX 46 + +#define CLK_MPU_HSI CLKSRC(MUX_MPU, 0) +#define CLK_MPU_HSE CLKSRC(MUX_MPU, 1) +#define CLK_MPU_PLL1P CLKSRC(MUX_MPU, 2) +#define CLK_MPU_PLL1P_DIV CLKSRC(MUX_MPU, 3) + +#define CLK_AXI_HSI CLKSRC(MUX_AXI, 0) +#define CLK_AXI_HSE CLKSRC(MUX_AXI, 1) +#define CLK_AXI_PLL2P CLKSRC(MUX_AXI, 2) + +#define CLK_MLAHBS_HSI CLKSRC(MUX_MLAHB, 0) +#define CLK_MLAHBS_HSE CLKSRC(MUX_MLAHB, 1) +#define CLK_MLAHBS_CSI CLKSRC(MUX_MLAHB, 2) +#define CLK_MLAHBS_PLL3 CLKSRC(MUX_MLAHB, 3) + +#define CLK_PLL12_HSI CLKSRC(MUX_PLL12, 0) +#define CLK_PLL12_HSE CLKSRC(MUX_PLL12, 1) + +#define CLK_PLL3_HSI CLKSRC(MUX_PLL3, 0) +#define CLK_PLL3_HSE CLKSRC(MUX_PLL3, 1) +#define CLK_PLL3_CSI CLKSRC(MUX_PLL3, 2) + +#define CLK_PLL4_HSI CLKSRC(MUX_PLL4, 0) +#define CLK_PLL4_HSE CLKSRC(MUX_PLL4, 1) +#define CLK_PLL4_CSI CLKSRC(MUX_PLL4, 2) + +#define CLK_RTC_DISABLED CLK_DISABLED(RTC) +#define CLK_RTC_LSE CLK_SRC(RTC, 1) +#define CLK_RTC_LSI CLK_SRC(RTC, 2) +#define CLK_RTC_HSE CLK_SRC(RTC, 3) + +#define CLK_MCO1_HSI CLK_SRC(CK_MCO1, 0) +#define CLK_MCO1_HSE CLK_SRC(CK_MCO1, 1) +#define CLK_MCO1_CSI CLK_SRC(CK_MCO1, 2) +#define CLK_MCO1_LSI CLK_SRC(CK_MCO1, 3) +#define CLK_MCO1_LSE CLK_SRC(CK_MCO1, 4) +#define CLK_MCO1_DISABLED CLK_DISABLED(CK_MCO1) + +#define CLK_MCO2_MPU CLK_SRC(CK_MCO2, 0) +#define CLK_MCO2_AXI CLK_SRC(CK_MCO2, 1) +#define CLK_MCO2_MLAHB CLK_SRC(CK_MCO2, 2) +#define CLK_MCO2_PLL4 CLK_SRC(CK_MCO2, 3) +#define CLK_MCO2_HSE CLK_SRC(CK_MCO2, 4) +#define CLK_MCO2_HSI CLK_SRC(CK_MCO2, 5) +#define CLK_MCO2_DISABLED CLK_DISABLED(CK_MCO2) + +#define CLK_CKPER_HSI CLKSRC(MUX_CKPER, 0) +#define CLK_CKPER_CSI CLKSRC(MUX_CKPER, 1) +#define CLK_CKPER_HSE CLKSRC(MUX_CKPER, 2) +#define CLK_CKPER_DISABLED CLKSRC(MUX_CKPER, 3) + +#define CLK_I2C12_PCLK1 CLKSRC(MUX_I2C12, 0) +#define CLK_I2C12_PLL4R CLKSRC(MUX_I2C12, 1) +#define CLK_I2C12_HSI CLKSRC(MUX_I2C12, 2) +#define CLK_I2C12_CSI CLKSRC(MUX_I2C12, 3) + +#define CLK_I2C3_PCLK6 CLKSRC(MUX_I2C3, 0) +#define CLK_I2C3_PLL4R CLKSRC(MUX_I2C3, 1) +#define CLK_I2C3_HSI CLKSRC(MUX_I2C3, 2) +#define CLK_I2C3_CSI CLKSRC(MUX_I2C3, 3) + +#define CLK_I2C4_PCLK6 CLKSRC(MUX_I2C4, 0) +#define CLK_I2C4_PLL4R CLKSRC(MUX_I2C4, 1) +#define CLK_I2C4_HSI CLKSRC(MUX_I2C4, 2) +#define CLK_I2C4_CSI CLKSRC(MUX_I2C4, 3) + +#define CLK_I2C5_PCLK6 CLKSRC(MUX_I2C5, 0) +#define CLK_I2C5_PLL4R CLKSRC(MUX_I2C5, 1) +#define CLK_I2C5_HSI CLKSRC(MUX_I2C5, 2) +#define CLK_I2C5_CSI CLKSRC(MUX_I2C5, 3) + +#define CLK_SPI1_PLL4P CLKSRC(MUX_SPI1, 0) +#define CLK_SPI1_PLL3Q CLKSRC(MUX_SPI1, 1) +#define CLK_SPI1_I2SCKIN CLKSRC(MUX_SPI1, 2) +#define CLK_SPI1_CKPER CLKSRC(MUX_SPI1, 3) +#define CLK_SPI1_PLL3R CLKSRC(MUX_SPI1, 4) + +#define CLK_SPI23_PLL4P CLKSRC(MUX_SPI23, 0) +#define CLK_SPI23_PLL3Q CLKSRC(MUX_SPI23, 1) +#define CLK_SPI23_I2SCKIN CLKSRC(MUX_SPI23, 2) +#define CLK_SPI23_CKPER CLKSRC(MUX_SPI23, 3) +#define CLK_SPI23_PLL3R CLKSRC(MUX_SPI23, 4) + +#define CLK_SPI4_PCLK6 CLKSRC(MUX_SPI4, 0) +#define CLK_SPI4_PLL4Q CLKSRC(MUX_SPI4, 1) +#define CLK_SPI4_HSI CLKSRC(MUX_SPI4, 2) +#define CLK_SPI4_CSI CLKSRC(MUX_SPI4, 3) +#define CLK_SPI4_HSE CLKSRC(MUX_SPI4, 4) +#define CLK_SPI4_I2SCKIN CLKSRC(MUX_SPI4, 5) + +#define CLK_SPI5_PCLK6 CLKSRC(MUX_SPI5, 0) +#define CLK_SPI5_PLL4Q CLKSRC(MUX_SPI5, 1) +#define CLK_SPI5_HSI CLKSRC(MUX_SPI5, 2) +#define CLK_SPI5_CSI CLKSRC(MUX_SPI5, 3) +#define CLK_SPI5_HSE CLKSRC(MUX_SPI5, 4) + +#define CLK_UART1_PCLK6 CLKSRC(MUX_UART1, 0) +#define CLK_UART1_PLL3Q CLKSRC(MUX_UART1, 1) +#define CLK_UART1_HSI CLKSRC(MUX_UART1, 2) +#define CLK_UART1_CSI CLKSRC(MUX_UART1, 3) +#define CLK_UART1_PLL4Q CLKSRC(MUX_UART1, 4) +#define CLK_UART1_HSE CLKSRC(MUX_UART1, 5) + +#define CLK_UART2_PCLK6 CLKSRC(MUX_UART2, 0) +#define CLK_UART2_PLL3Q CLKSRC(MUX_UART2, 1) +#define CLK_UART2_HSI CLKSRC(MUX_UART2, 2) +#define CLK_UART2_CSI CLKSRC(MUX_UART2, 3) +#define CLK_UART2_PLL4Q CLKSRC(MUX_UART2, 4) +#define CLK_UART2_HSE CLKSRC(MUX_UART2, 5) + +#define CLK_UART35_PCLK1 CLKSRC(MUX_UART35, 0) +#define CLK_UART35_PLL4Q CLKSRC(MUX_UART35, 1) +#define CLK_UART35_HSI CLKSRC(MUX_UART35, 2) +#define CLK_UART35_CSI CLKSRC(MUX_UART35, 3) +#define CLK_UART35_HSE CLKSRC(MUX_UART35, 4) + +#define CLK_UART4_PCLK1 CLKSRC(MUX_UART4, 0) +#define CLK_UART4_PLL4Q CLKSRC(MUX_UART4, 1) +#define CLK_UART4_HSI CLKSRC(MUX_UART4, 2) +#define CLK_UART4_CSI CLKSRC(MUX_UART4, 3) +#define CLK_UART4_HSE CLKSRC(MUX_UART4, 4) + +#define CLK_UART6_PCLK2 CLKSRC(MUX_UART6, 0) +#define CLK_UART6_PLL4Q CLKSRC(MUX_UART6, 1) +#define CLK_UART6_HSI CLKSRC(MUX_UART6, 2) +#define CLK_UART6_CSI CLKSRC(MUX_UART6, 3) +#define CLK_UART6_HSE CLKSRC(MUX_UART6, 4) + +#define CLK_UART78_PCLK1 CLKSRC(MUX_UART78, 0) +#define CLK_UART78_PLL4Q CLKSRC(MUX_UART78, 1) +#define CLK_UART78_HSI CLKSRC(MUX_UART78, 2) +#define CLK_UART78_CSI CLKSRC(MUX_UART78, 3) +#define CLK_UART78_HSE CLKSRC(MUX_UART78, 4) + +#define CLK_LPTIM1_PCLK1 CLKSRC(MUX_LPTIM1, 0) +#define CLK_LPTIM1_PLL4P CLKSRC(MUX_LPTIM1, 1) +#define CLK_LPTIM1_PLL3Q CLKSRC(MUX_LPTIM1, 2) +#define CLK_LPTIM1_LSE CLKSRC(MUX_LPTIM1, 3) +#define CLK_LPTIM1_LSI CLKSRC(MUX_LPTIM1, 4) +#define CLK_LPTIM1_CKPER CLKSRC(MUX_LPTIM1, 5) + +#define CLK_LPTIM2_PCLK3 CLKSRC(MUX_LPTIM2, 0) +#define CLK_LPTIM2_PLL4Q CLKSRC(MUX_LPTIM2, 1) +#define CLK_LPTIM2_CKPER CLKSRC(MUX_LPTIM2, 2) +#define CLK_LPTIM2_LSE CLKSRC(MUX_LPTIM2, 3) +#define CLK_LPTIM2_LSI CLKSRC(MUX_LPTIM2, 4) + +#define CLK_LPTIM3_PCLK3 CLKSRC(MUX_LPTIM3, 0) +#define CLK_LPTIM3_PLL4Q CLKSRC(MUX_LPTIM3, 1) +#define CLK_LPTIM3_CKPER CLKSRC(MUX_LPTIM3, 2) +#define CLK_LPTIM3_LSE CLKSRC(MUX_LPTIM3, 3) +#define CLK_LPTIM3_LSI CLKSRC(MUX_LPTIM3, 4) + +#define CLK_LPTIM45_PCLK3 CLKSRC(MUX_LPTIM45, 0) +#define CLK_LPTIM45_PLL4P CLKSRC(MUX_LPTIM45, 1) +#define CLK_LPTIM45_PLL3Q CLKSRC(MUX_LPTIM45, 2) +#define CLK_LPTIM45_LSE CLKSRC(MUX_LPTIM45, 3) +#define CLK_LPTIM45_LSI CLKSRC(MUX_LPTIM45, 4) +#define CLK_LPTIM45_CKPER CLKSRC(MUX_LPTIM45, 5) + +#define CLK_SAI1_PLL4Q CLKSRC(MUX_SAI1, 0) +#define CLK_SAI1_PLL3Q CLKSRC(MUX_SAI1, 1) +#define CLK_SAI1_I2SCKIN CLKSRC(MUX_SAI1, 2) +#define CLK_SAI1_CKPER CLKSRC(MUX_SAI1, 3) +#define CLK_SAI1_PLL3R CLKSRC(MUX_SAI1, 4) + +#define CLK_SAI2_PLL4Q CLKSRC(MUX_SAI2, 0) +#define CLK_SAI2_PLL3Q CLKSRC(MUX_SAI2, 1) +#define CLK_SAI2_I2SCKIN CLKSRC(MUX_SAI2, 2) +#define CLK_SAI2_CKPER CLKSRC(MUX_SAI2, 3) +#define CLK_SAI2_SPDIF CLKSRC(MUX_SAI2, 4) +#define CLK_SAI2_PLL3R CLKSRC(MUX_SAI2, 5) + +#define CLK_FDCAN_HSE CLKSRC(MUX_FDCAN, 0) +#define CLK_FDCAN_PLL3Q CLKSRC(MUX_FDCAN, 1) +#define CLK_FDCAN_PLL4Q CLKSRC(MUX_FDCAN, 2) +#define CLK_FDCAN_PLL4R CLKSRC(MUX_FDCAN, 3) + +#define CLK_SPDIF_PLL4P CLKSRC(MUX_SPDIF, 0) +#define CLK_SPDIF_PLL3Q CLKSRC(MUX_SPDIF, 1) +#define CLK_SPDIF_HSI CLKSRC(MUX_SPDIF, 2) + +#define CLK_ADC1_PLL4R CLKSRC(MUX_ADC1, 0) +#define CLK_ADC1_CKPER CLKSRC(MUX_ADC1, 1) +#define CLK_ADC1_PLL3Q CLKSRC(MUX_ADC1, 2) + +#define CLK_ADC2_PLL4R CLKSRC(MUX_ADC2, 0) +#define CLK_ADC2_CKPER CLKSRC(MUX_ADC2, 1) +#define CLK_ADC2_PLL3Q CLKSRC(MUX_ADC2, 2) + +#define CLK_SDMMC1_HCLK6 CLKSRC(MUX_SDMMC1, 0) +#define CLK_SDMMC1_PLL3R CLKSRC(MUX_SDMMC1, 1) +#define CLK_SDMMC1_PLL4P CLKSRC(MUX_SDMMC1, 2) +#define CLK_SDMMC1_HSI CLKSRC(MUX_SDMMC1, 3) + +#define CLK_SDMMC2_HCLK6 CLKSRC(MUX_SDMMC2, 0) +#define CLK_SDMMC2_PLL3R CLKSRC(MUX_SDMMC2, 1) +#define CLK_SDMMC2_PLL4P CLKSRC(MUX_SDMMC2, 2) +#define CLK_SDMMC2_HSI CLKSRC(MUX_SDMMC2, 3) + +#define CLK_ETH1_PLL4P CLKSRC(MUX_ETH1, 0) +#define CLK_ETH1_PLL3Q CLKSRC(MUX_ETH1, 1) + +#define CLK_ETH2_PLL4P CLKSRC(MUX_ETH2, 0) +#define CLK_ETH2_PLL3Q CLKSRC(MUX_ETH2, 1) + +#define CLK_USBPHY_HSE CLKSRC(MUX_USBPHY, 0) +#define CLK_USBPHY_PLL4R CLKSRC(MUX_USBPHY, 1) +#define CLK_USBPHY_HSE_DIV2 CLKSRC(MUX_USBPHY, 2) + +#define CLK_USBO_PLL4R CLKSRC(MUX_USBO, 0) +#define CLK_USBO_USBPHY CLKSRC(MUX_USBO, 1) + +#define CLK_QSPI_ACLK CLKSRC(MUX_QSPI, 0) +#define CLK_QSPI_PLL3R CLKSRC(MUX_QSPI, 1) +#define CLK_QSPI_PLL4P CLKSRC(MUX_QSPI, 2) +#define CLK_QSPI_CKPER CLKSRC(MUX_QSPI, 3) + +#define CLK_FMC_ACLK CLKSRC(MUX_FMC, 0) +#define CLK_FMC_PLL3R CLKSRC(MUX_FMC, 1) +#define CLK_FMC_PLL4P CLKSRC(MUX_FMC, 2) +#define CLK_FMC_CKPER CLKSRC(MUX_FMC, 3) + +#define CLK_RNG1_CSI CLKSRC(MUX_RNG1, 0) +#define CLK_RNG1_PLL4R CLKSRC(MUX_RNG1, 1) +/* WARNING: POSITION 2 OF RNG1 MUX IS RESERVED */ +#define CLK_RNG1_LSI CLKSRC(MUX_RNG1, 3) + +#define CLK_STGEN_HSI CLKSRC(MUX_STGEN, 0) +#define CLK_STGEN_HSE CLKSRC(MUX_STGEN, 1) + +#define CLK_DCMIPP_ACLK CLKSRC(MUX_DCMIPP, 0) +#define CLK_DCMIPP_PLL2Q CLKSRC(MUX_DCMIPP, 1) +#define CLK_DCMIPP_PLL4P CLKSRC(MUX_DCMIPP, 2) +#define CLK_DCMIPP_CKPER CLKSRC(MUX_DCMIPP, 3) + +#define CLK_SAES_AXI CLKSRC(MUX_SAES, 0) +#define CLK_SAES_CKPER CLKSRC(MUX_SAES, 1) +#define CLK_SAES_PLL4R CLKSRC(MUX_SAES, 2) +#define CLK_SAES_LSI CLKSRC(MUX_SAES, 3) + +/* PLL output is enable when x=1, with x=p,q or r */ +#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2)) + +/* define for st,pll /csg */ +#define SSCG_MODE_CENTER_SPREAD 0 +#define SSCG_MODE_DOWN_SPREAD 1 + +/* define for st,drive */ +#define LSEDRV_LOWEST 0 +#define LSEDRV_MEDIUM_LOW 1 +#define LSEDRV_MEDIUM_HIGH 2 +#define LSEDRV_HIGHEST 3 + +#endif /* _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h new file mode 100644 index 0000000..bef1368 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018-2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_ +#define _DT_BINDINGS_STM32MP1_CLKS_H_ + +/* OSCILLATOR clocks */ +#define CK_HSE 0 +#define CK_CSI 1 +#define CK_LSI 2 +#define CK_LSE 3 +#define CK_HSI 4 +#define CK_HSE_DIV2 5 + +/* Bus clocks */ +#define TIM2 6 +#define TIM3 7 +#define TIM4 8 +#define TIM5 9 +#define TIM6 10 +#define TIM7 11 +#define TIM12 12 +#define TIM13 13 +#define TIM14 14 +#define LPTIM1 15 +#define SPI2 16 +#define SPI3 17 +#define USART2 18 +#define USART3 19 +#define UART4 20 +#define UART5 21 +#define UART7 22 +#define UART8 23 +#define I2C1 24 +#define I2C2 25 +#define I2C3 26 +#define I2C5 27 +#define SPDIF 28 +#define CEC 29 +#define DAC12 30 +#define MDIO 31 +#define TIM1 32 +#define TIM8 33 +#define TIM15 34 +#define TIM16 35 +#define TIM17 36 +#define SPI1 37 +#define SPI4 38 +#define SPI5 39 +#define USART6 40 +#define SAI1 41 +#define SAI2 42 +#define SAI3 43 +#define DFSDM 44 +#define FDCAN 45 +#define LPTIM2 46 +#define LPTIM3 47 +#define LPTIM4 48 +#define LPTIM5 49 +#define SAI4 50 +#define SYSCFG 51 +#define VREF 52 +#define TMPSENS 53 +#define PMBCTRL 54 +#define HDP 55 +#define LTDC 56 +#define DSI 57 +#define IWDG2 58 +#define USBPHY 59 +#define STGENRO 60 +#define SPI6 61 +#define I2C4 62 +#define I2C6 63 +#define USART1 64 +#define RTCAPB 65 +#define TZC1 66 +#define TZPC 67 +#define IWDG1 68 +#define BSEC 69 +#define STGEN 70 +#define DMA1 71 +#define DMA2 72 +#define DMAMUX 73 +#define ADC12 74 +#define USBO 75 +#define SDMMC3 76 +#define DCMI 77 +#define CRYP2 78 +#define HASH2 79 +#define RNG2 80 +#define CRC2 81 +#define HSEM 82 +#define IPCC 83 +#define GPIOA 84 +#define GPIOB 85 +#define GPIOC 86 +#define GPIOD 87 +#define GPIOE 88 +#define GPIOF 89 +#define GPIOG 90 +#define GPIOH 91 +#define GPIOI 92 +#define GPIOJ 93 +#define GPIOK 94 +#define GPIOZ 95 +#define CRYP1 96 +#define HASH1 97 +#define RNG1 98 +#define BKPSRAM 99 +#define MDMA 100 +#define GPU 101 +#define ETHCK 102 +#define ETHTX 103 +#define ETHRX 104 +#define ETHMAC 105 +#define FMC 106 +#define QSPI 107 +#define SDMMC1 108 +#define SDMMC2 109 +#define CRC1 110 +#define USBH 111 +#define ETHSTP 112 +#define TZC2 113 + +/* Kernel clocks */ +#define SDMMC1_K 118 +#define SDMMC2_K 119 +#define SDMMC3_K 120 +#define FMC_K 121 +#define QSPI_K 122 +#define ETHCK_K 123 +#define RNG1_K 124 +#define RNG2_K 125 +#define GPU_K 126 +#define USBPHY_K 127 +#define STGEN_K 128 +#define SPDIF_K 129 +#define SPI1_K 130 +#define SPI2_K 131 +#define SPI3_K 132 +#define SPI4_K 133 +#define SPI5_K 134 +#define SPI6_K 135 +#define CEC_K 136 +#define I2C1_K 137 +#define I2C2_K 138 +#define I2C3_K 139 +#define I2C4_K 140 +#define I2C5_K 141 +#define I2C6_K 142 +#define LPTIM1_K 143 +#define LPTIM2_K 144 +#define LPTIM3_K 145 +#define LPTIM4_K 146 +#define LPTIM5_K 147 +#define USART1_K 148 +#define USART2_K 149 +#define USART3_K 150 +#define UART4_K 151 +#define UART5_K 152 +#define USART6_K 153 +#define UART7_K 154 +#define UART8_K 155 +#define DFSDM_K 156 +#define FDCAN_K 157 +#define SAI1_K 158 +#define SAI2_K 159 +#define SAI3_K 160 +#define SAI4_K 161 +#define ADC12_K 162 +#define DSI_K 163 +#define DSI_PX 164 +#define ADFSDM_K 165 +#define USBO_K 166 +#define LTDC_PX 167 +#define DAC12_K 168 +#define ETHPTP_K 169 + +/* PLL */ +#define PLL1 176 +#define PLL2 177 +#define PLL3 178 +#define PLL4 179 + +/* ODF */ +#define PLL1_P 180 +#define PLL1_Q 181 +#define PLL1_R 182 +#define PLL2_P 183 +#define PLL2_Q 184 +#define PLL2_R 185 +#define PLL3_P 186 +#define PLL3_Q 187 +#define PLL3_R 188 +#define PLL4_P 189 +#define PLL4_Q 190 +#define PLL4_R 191 + +/* AUX */ +#define RTC 192 + +/* MCLK */ +#define CK_PER 193 +#define CK_MPU 194 +#define CK_AXI 195 +#define CK_MCU 196 + +/* Time base */ +#define TIM2_K 197 +#define TIM3_K 198 +#define TIM4_K 199 +#define TIM5_K 200 +#define TIM6_K 201 +#define TIM7_K 202 +#define TIM12_K 203 +#define TIM13_K 204 +#define TIM14_K 205 +#define TIM1_K 206 +#define TIM8_K 207 +#define TIM15_K 208 +#define TIM16_K 209 +#define TIM17_K 210 + +/* MCO clocks */ +#define CK_MCO1 211 +#define CK_MCO2 212 + +/* TRACE & DEBUG clocks */ +#define CK_DBG 214 +#define CK_TRACE 215 + +/* DDR */ +#define DDRC1 220 +#define DDRC1LP 221 +#define DDRC2 222 +#define DDRC2LP 223 +#define DDRPHYC 224 +#define DDRPHYCLP 225 +#define DDRCAPB 226 +#define DDRCAPBLP 227 +#define AXIDCG 228 +#define DDRPHYCAPB 229 +#define DDRPHYCAPBLP 230 +#define DDRPERFM 231 + +#define STM32MP1_LAST_CLK 232 + +/* SCMI clock identifiers */ +#define CK_SCMI0_HSE 0 +#define CK_SCMI0_HSI 1 +#define CK_SCMI0_CSI 2 +#define CK_SCMI0_LSE 3 +#define CK_SCMI0_LSI 4 +#define CK_SCMI0_PLL2_Q 5 +#define CK_SCMI0_PLL2_R 6 +#define CK_SCMI0_MPU 7 +#define CK_SCMI0_AXI 8 +#define CK_SCMI0_BSEC 9 +#define CK_SCMI0_CRYP1 10 +#define CK_SCMI0_GPIOZ 11 +#define CK_SCMI0_HASH1 12 +#define CK_SCMI0_I2C4 13 +#define CK_SCMI0_I2C6 14 +#define CK_SCMI0_IWDG1 15 +#define CK_SCMI0_RNG1 16 +#define CK_SCMI0_RTC 17 +#define CK_SCMI0_RTCAPB 18 +#define CK_SCMI0_SPI6 19 +#define CK_SCMI0_USART1 20 + +#define CK_SCMI1_PLL3_Q 0 +#define CK_SCMI1_PLL3_R 1 +#define CK_SCMI1_MCU 2 + +#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h new file mode 100644 index 0000000..3a3792d --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2017-2022, STMicroelectronics - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_CLOCK_STM32MP15_CLKSRC_H_ +#define _DT_BINDINGS_CLOCK_STM32MP15_CLKSRC_H_ + +/* PLL output is enable when x=1, with x=p,q or r */ +#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2)) + +/* st,clksrc: mandatory clock source */ +#define CLK_MPU_HSI 0x00000200 +#define CLK_MPU_HSE 0x00000201 +#define CLK_MPU_PLL1P 0x00000202 +#define CLK_MPU_PLL1P_DIV 0x00000203 + +#define CLK_AXI_HSI 0x00000240 +#define CLK_AXI_HSE 0x00000241 +#define CLK_AXI_PLL2P 0x00000242 + +#define CLK_MCU_HSI 0x00000480 +#define CLK_MCU_HSE 0x00000481 +#define CLK_MCU_CSI 0x00000482 +#define CLK_MCU_PLL3P 0x00000483 + +#define CLK_PLL12_HSI 0x00000280 +#define CLK_PLL12_HSE 0x00000281 + +#define CLK_PLL3_HSI 0x00008200 +#define CLK_PLL3_HSE 0x00008201 +#define CLK_PLL3_CSI 0x00008202 + +#define CLK_PLL4_HSI 0x00008240 +#define CLK_PLL4_HSE 0x00008241 +#define CLK_PLL4_CSI 0x00008242 +#define CLK_PLL4_I2SCKIN 0x00008243 + +#define CLK_RTC_DISABLED 0x00001400 +#define CLK_RTC_LSE 0x00001401 +#define CLK_RTC_LSI 0x00001402 +#define CLK_RTC_HSE 0x00001403 + +#define CLK_MCO1_HSI 0x00008000 +#define CLK_MCO1_HSE 0x00008001 +#define CLK_MCO1_CSI 0x00008002 +#define CLK_MCO1_LSI 0x00008003 +#define CLK_MCO1_LSE 0x00008004 +#define CLK_MCO1_DISABLED 0x0000800F + +#define CLK_MCO2_MPU 0x00008040 +#define CLK_MCO2_AXI 0x00008041 +#define CLK_MCO2_MCU 0x00008042 +#define CLK_MCO2_PLL4P 0x00008043 +#define CLK_MCO2_HSE 0x00008044 +#define CLK_MCO2_HSI 0x00008045 +#define CLK_MCO2_DISABLED 0x0000804F + +/* st,pkcs: peripheral kernel clock source */ + +#define CLK_I2C12_PCLK1 0x00008C00 +#define CLK_I2C12_PLL4R 0x00008C01 +#define CLK_I2C12_HSI 0x00008C02 +#define CLK_I2C12_CSI 0x00008C03 +#define CLK_I2C12_DISABLED 0x00008C07 + +#define CLK_I2C35_PCLK1 0x00008C40 +#define CLK_I2C35_PLL4R 0x00008C41 +#define CLK_I2C35_HSI 0x00008C42 +#define CLK_I2C35_CSI 0x00008C43 +#define CLK_I2C35_DISABLED 0x00008C47 + +#define CLK_I2C46_PCLK5 0x00000C00 +#define CLK_I2C46_PLL3Q 0x00000C01 +#define CLK_I2C46_HSI 0x00000C02 +#define CLK_I2C46_CSI 0x00000C03 +#define CLK_I2C46_DISABLED 0x00000C07 + +#define CLK_SAI1_PLL4Q 0x00008C80 +#define CLK_SAI1_PLL3Q 0x00008C81 +#define CLK_SAI1_I2SCKIN 0x00008C82 +#define CLK_SAI1_CKPER 0x00008C83 +#define CLK_SAI1_PLL3R 0x00008C84 +#define CLK_SAI1_DISABLED 0x00008C87 + +#define CLK_SAI2_PLL4Q 0x00008CC0 +#define CLK_SAI2_PLL3Q 0x00008CC1 +#define CLK_SAI2_I2SCKIN 0x00008CC2 +#define CLK_SAI2_CKPER 0x00008CC3 +#define CLK_SAI2_SPDIF 0x00008CC4 +#define CLK_SAI2_PLL3R 0x00008CC5 +#define CLK_SAI2_DISABLED 0x00008CC7 + +#define CLK_SAI3_PLL4Q 0x00008D00 +#define CLK_SAI3_PLL3Q 0x00008D01 +#define CLK_SAI3_I2SCKIN 0x00008D02 +#define CLK_SAI3_CKPER 0x00008D03 +#define CLK_SAI3_PLL3R 0x00008D04 +#define CLK_SAI3_DISABLED 0x00008D07 + +#define CLK_SAI4_PLL4Q 0x00008D40 +#define CLK_SAI4_PLL3Q 0x00008D41 +#define CLK_SAI4_I2SCKIN 0x00008D42 +#define CLK_SAI4_CKPER 0x00008D43 +#define CLK_SAI4_PLL3R 0x00008D44 +#define CLK_SAI4_DISABLED 0x00008D47 + +#define CLK_SPI2S1_PLL4P 0x00008D80 +#define CLK_SPI2S1_PLL3Q 0x00008D81 +#define CLK_SPI2S1_I2SCKIN 0x00008D82 +#define CLK_SPI2S1_CKPER 0x00008D83 +#define CLK_SPI2S1_PLL3R 0x00008D84 +#define CLK_SPI2S1_DISABLED 0x00008D87 + +#define CLK_SPI2S23_PLL4P 0x00008DC0 +#define CLK_SPI2S23_PLL3Q 0x00008DC1 +#define CLK_SPI2S23_I2SCKIN 0x00008DC2 +#define CLK_SPI2S23_CKPER 0x00008DC3 +#define CLK_SPI2S23_PLL3R 0x00008DC4 +#define CLK_SPI2S23_DISABLED 0x00008DC7 + +#define CLK_SPI45_PCLK2 0x00008E00 +#define CLK_SPI45_PLL4Q 0x00008E01 +#define CLK_SPI45_HSI 0x00008E02 +#define CLK_SPI45_CSI 0x00008E03 +#define CLK_SPI45_HSE 0x00008E04 +#define CLK_SPI45_DISABLED 0x00008E07 + +#define CLK_SPI6_PCLK5 0x00000C40 +#define CLK_SPI6_PLL4Q 0x00000C41 +#define CLK_SPI6_HSI 0x00000C42 +#define CLK_SPI6_CSI 0x00000C43 +#define CLK_SPI6_HSE 0x00000C44 +#define CLK_SPI6_PLL3Q 0x00000C45 +#define CLK_SPI6_DISABLED 0x00000C47 + +#define CLK_UART6_PCLK2 0x00008E40 +#define CLK_UART6_PLL4Q 0x00008E41 +#define CLK_UART6_HSI 0x00008E42 +#define CLK_UART6_CSI 0x00008E43 +#define CLK_UART6_HSE 0x00008E44 +#define CLK_UART6_DISABLED 0x00008E47 + +#define CLK_UART24_PCLK1 0x00008E80 +#define CLK_UART24_PLL4Q 0x00008E81 +#define CLK_UART24_HSI 0x00008E82 +#define CLK_UART24_CSI 0x00008E83 +#define CLK_UART24_HSE 0x00008E84 +#define CLK_UART24_DISABLED 0x00008E87 + +#define CLK_UART35_PCLK1 0x00008EC0 +#define CLK_UART35_PLL4Q 0x00008EC1 +#define CLK_UART35_HSI 0x00008EC2 +#define CLK_UART35_CSI 0x00008EC3 +#define CLK_UART35_HSE 0x00008EC4 +#define CLK_UART35_DISABLED 0x00008EC7 + +#define CLK_UART78_PCLK1 0x00008F00 +#define CLK_UART78_PLL4Q 0x00008F01 +#define CLK_UART78_HSI 0x00008F02 +#define CLK_UART78_CSI 0x00008F03 +#define CLK_UART78_HSE 0x00008F04 +#define CLK_UART78_DISABLED 0x00008F07 + +#define CLK_UART1_PCLK5 0x00000C80 +#define CLK_UART1_PLL3Q 0x00000C81 +#define CLK_UART1_HSI 0x00000C82 +#define CLK_UART1_CSI 0x00000C83 +#define CLK_UART1_PLL4Q 0x00000C84 +#define CLK_UART1_HSE 0x00000C85 +#define CLK_UART1_DISABLED 0x00000C87 + +#define CLK_SDMMC12_HCLK6 0x00008F40 +#define CLK_SDMMC12_PLL3R 0x00008F41 +#define CLK_SDMMC12_PLL4P 0x00008F42 +#define CLK_SDMMC12_HSI 0x00008F43 +#define CLK_SDMMC12_DISABLED 0x00008F47 + +#define CLK_SDMMC3_HCLK2 0x00008F80 +#define CLK_SDMMC3_PLL3R 0x00008F81 +#define CLK_SDMMC3_PLL4P 0x00008F82 +#define CLK_SDMMC3_HSI 0x00008F83 +#define CLK_SDMMC3_DISABLED 0x00008F87 + +#define CLK_ETH_PLL4P 0x00008FC0 +#define CLK_ETH_PLL3Q 0x00008FC1 +#define CLK_ETH_DISABLED 0x00008FC3 + +#define CLK_QSPI_ACLK 0x00009000 +#define CLK_QSPI_PLL3R 0x00009001 +#define CLK_QSPI_PLL4P 0x00009002 +#define CLK_QSPI_CKPER 0x00009003 + +#define CLK_FMC_ACLK 0x00009040 +#define CLK_FMC_PLL3R 0x00009041 +#define CLK_FMC_PLL4P 0x00009042 +#define CLK_FMC_CKPER 0x00009043 + +#define CLK_FDCAN_HSE 0x000090C0 +#define CLK_FDCAN_PLL3Q 0x000090C1 +#define CLK_FDCAN_PLL4Q 0x000090C2 +#define CLK_FDCAN_PLL4R 0x000090C3 + +#define CLK_SPDIF_PLL4P 0x00009140 +#define CLK_SPDIF_PLL3Q 0x00009141 +#define CLK_SPDIF_HSI 0x00009142 +#define CLK_SPDIF_DISABLED 0x00009143 + +#define CLK_CEC_LSE 0x00009180 +#define CLK_CEC_LSI 0x00009181 +#define CLK_CEC_CSI_DIV122 0x00009182 +#define CLK_CEC_DISABLED 0x00009183 + +#define CLK_USBPHY_HSE 0x000091C0 +#define CLK_USBPHY_PLL4R 0x000091C1 +#define CLK_USBPHY_HSE_DIV2 0x000091C2 +#define CLK_USBPHY_DISABLED 0x000091C3 + +#define CLK_USBO_PLL4R 0x800091C0 +#define CLK_USBO_USBPHY 0x800091C1 + +#define CLK_RNG1_CSI 0x00000CC0 +#define CLK_RNG1_PLL4R 0x00000CC1 +#define CLK_RNG1_LSE 0x00000CC2 +#define CLK_RNG1_LSI 0x00000CC3 + +#define CLK_RNG2_CSI 0x00009200 +#define CLK_RNG2_PLL4R 0x00009201 +#define CLK_RNG2_LSE 0x00009202 +#define CLK_RNG2_LSI 0x00009203 + +#define CLK_CKPER_HSI 0x00000D00 +#define CLK_CKPER_CSI 0x00000D01 +#define CLK_CKPER_HSE 0x00000D02 +#define CLK_CKPER_DISABLED 0x00000D03 + +#define CLK_STGEN_HSI 0x00000D40 +#define CLK_STGEN_HSE 0x00000D41 +#define CLK_STGEN_DISABLED 0x00000D43 + +#define CLK_DSI_DSIPLL 0x00009240 +#define CLK_DSI_PLL4P 0x00009241 + +#define CLK_ADC_PLL4R 0x00009280 +#define CLK_ADC_CKPER 0x00009281 +#define CLK_ADC_PLL3Q 0x00009282 +#define CLK_ADC_DISABLED 0x00009283 + +#define CLK_LPTIM45_PCLK3 0x000092C0 +#define CLK_LPTIM45_PLL4P 0x000092C1 +#define CLK_LPTIM45_PLL3Q 0x000092C2 +#define CLK_LPTIM45_LSE 0x000092C3 +#define CLK_LPTIM45_LSI 0x000092C4 +#define CLK_LPTIM45_CKPER 0x000092C5 +#define CLK_LPTIM45_DISABLED 0x000092C7 + +#define CLK_LPTIM23_PCLK3 0x00009300 +#define CLK_LPTIM23_PLL4Q 0x00009301 +#define CLK_LPTIM23_CKPER 0x00009302 +#define CLK_LPTIM23_LSE 0x00009303 +#define CLK_LPTIM23_LSI 0x00009304 +#define CLK_LPTIM23_DISABLED 0x00009307 + +#define CLK_LPTIM1_PCLK1 0x00009340 +#define CLK_LPTIM1_PLL4P 0x00009341 +#define CLK_LPTIM1_PLL3Q 0x00009342 +#define CLK_LPTIM1_LSE 0x00009343 +#define CLK_LPTIM1_LSI 0x00009344 +#define CLK_LPTIM1_CKPER 0x00009345 +#define CLK_LPTIM1_DISABLED 0x00009347 + +/* define for st,pll /csg */ +#define SSCG_MODE_CENTER_SPREAD 0 +#define SSCG_MODE_DOWN_SPREAD 1 + +/* define for st,drive */ +#define LSEDRV_LOWEST 0 +#define LSEDRV_MEDIUM_LOW 1 +#define LSEDRV_MEDIUM_HIGH 2 +#define LSEDRV_HIGHEST 3 + +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h b/arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h new file mode 100644 index 0000000..803cd9c --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * This header provides constants for the ARM GIC. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H + +#include + +/* interrupt specifier cell 0 */ + +#define GIC_SPI 0 +#define GIC_PPI 1 + +/* + * Interrupt specifier cell 2. + * The flags in irq.h are valid, plus those below. + */ +#define GIC_CPU_MASK_RAW(x) ((x) << 8) +#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) + +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h b/arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h new file mode 100644 index 0000000..94e7f95 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * This header provides constants for most IRQ bindings. + * + * Most IRQ bindings include a flags cell as part of the IRQ specifier. + * In most cases, the format of the flags cell uses the standard values + * defined in this header. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H + +#define IRQ_TYPE_NONE 0 +#define IRQ_TYPE_EDGE_RISING 1 +#define IRQ_TYPE_EDGE_FALLING 2 +#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) +#define IRQ_TYPE_LEVEL_HIGH 4 +#define IRQ_TYPE_LEVEL_LOW 8 + +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h b/arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h new file mode 100644 index 0000000..1bc2c40 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved + * Author: Torgue Alexandre for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32_PINFUNC_H +#define _DT_BINDINGS_STM32_PINFUNC_H + +/* define PIN modes */ +#define GPIO 0x0 +#define AF0 0x1 +#define AF1 0x2 +#define AF2 0x3 +#define AF3 0x4 +#define AF4 0x5 +#define AF5 0x6 +#define AF6 0x7 +#define AF7 0x8 +#define AF8 0x9 +#define AF9 0xa +#define AF10 0xb +#define AF11 0xc +#define AF12 0xd +#define AF13 0xe +#define AF14 0xf +#define AF15 0x10 +#define ANALOG 0x11 +#define RSVD 0x12 + +/* define Pins number*/ +#define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) + +#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode)) + +/* package information */ +#define STM32MP_PKG_AA 0x1 +#define STM32MP_PKG_AB 0x2 +#define STM32MP_PKG_AC 0x4 +#define STM32MP_PKG_AD 0x8 + +#endif /* _DT_BINDINGS_STM32_PINFUNC_H */ diff --git a/arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h new file mode 100644 index 0000000..d40b1a2 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2020-2022, STMicroelectronics - All Rights Reserved + */ + +#if STM32MP13 +#include "stm32mp13-resets.h" +#endif +#if STM32MP15 +#include "stm32mp15-resets.h" +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h new file mode 100644 index 0000000..8a0f80e --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP13_RESET_H_ +#define _DT_BINDINGS_STM32MP13_RESET_H_ + +#define TIM2_R 13568 +#define TIM3_R 13569 +#define TIM4_R 13570 +#define TIM5_R 13571 +#define TIM6_R 13572 +#define TIM7_R 13573 +#define LPTIM1_R 13577 +#define SPI2_R 13579 +#define SPI3_R 13580 +#define USART3_R 13583 +#define UART4_R 13584 +#define UART5_R 13585 +#define UART7_R 13586 +#define UART8_R 13587 +#define I2C1_R 13589 +#define I2C2_R 13590 +#define SPDIF_R 13594 +#define TIM1_R 13632 +#define TIM8_R 13633 +#define SPI1_R 13640 +#define USART6_R 13645 +#define SAI1_R 13648 +#define SAI2_R 13649 +#define DFSDM_R 13652 +#define FDCAN_R 13656 +#define LPTIM2_R 13696 +#define LPTIM3_R 13697 +#define LPTIM4_R 13698 +#define LPTIM5_R 13699 +#define SYSCFG_R 13707 +#define VREF_R 13709 +#define DTS_R 13712 +#define PMBCTRL_R 13713 +#define LTDC_R 13760 +#define DCMIPP_R 13761 +#define DDRPERFM_R 13768 +#define USBPHY_R 13776 +#define STGEN_R 13844 +#define USART1_R 13888 +#define USART2_R 13889 +#define SPI4_R 13890 +#define SPI5_R 13891 +#define I2C3_R 13892 +#define I2C4_R 13893 +#define I2C5_R 13894 +#define TIM12_R 13895 +#define TIM13_R 13896 +#define TIM14_R 13897 +#define TIM15_R 13898 +#define TIM16_R 13899 +#define TIM17_R 13900 +#define DMA1_R 13952 +#define DMA2_R 13953 +#define DMAMUX1_R 13954 +#define DMA3_R 13955 +#define DMAMUX2_R 13956 +#define ADC1_R 13957 +#define ADC2_R 13958 +#define USBO_R 13960 +#define GPIOA_R 14080 +#define GPIOB_R 14081 +#define GPIOC_R 14082 +#define GPIOD_R 14083 +#define GPIOE_R 14084 +#define GPIOF_R 14085 +#define GPIOG_R 14086 +#define GPIOH_R 14087 +#define GPIOI_R 14088 +#define TSC_R 14095 +#define PKA_R 14146 +#define SAES_R 14147 +#define CRYP1_R 14148 +#define HASH1_R 14149 +#define RNG1_R 14150 +#define AXIMC_R 14160 +#define MDMA_R 14208 +#define MCE_R 14209 +#define ETH1MAC_R 14218 +#define FMC_R 14220 +#define QSPI_R 14222 +#define SDMMC1_R 14224 +#define SDMMC2_R 14225 +#define CRC1_R 14228 +#define USBH_R 14232 +#define ETH2MAC_R 14238 + +#endif /* _DT_BINDINGS_STM32MP13_RESET_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h new file mode 100644 index 0000000..2b34864 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018-2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP15_RESET_H_ +#define _DT_BINDINGS_STM32MP15_RESET_H_ + +#define MCU_HOLD_BOOT_R 2144 +#define LTDC_R 3072 +#define DSI_R 3076 +#define DDRPERFM_R 3080 +#define USBPHY_R 3088 +#define SPI6_R 3136 +#define I2C4_R 3138 +#define I2C6_R 3139 +#define USART1_R 3140 +#define STGEN_R 3156 +#define GPIOZ_R 3200 +#define CRYP1_R 3204 +#define HASH1_R 3205 +#define RNG1_R 3206 +#define AXIM_R 3216 +#define GPU_R 3269 +#define ETHMAC_R 3274 +#define FMC_R 3276 +#define QSPI_R 3278 +#define SDMMC1_R 3280 +#define SDMMC2_R 3281 +#define CRC1_R 3284 +#define USBH_R 3288 +#define MDMA_R 3328 +#define MCU_R 8225 +#define TIM2_R 19456 +#define TIM3_R 19457 +#define TIM4_R 19458 +#define TIM5_R 19459 +#define TIM6_R 19460 +#define TIM7_R 19461 +#define TIM12_R 16462 +#define TIM13_R 16463 +#define TIM14_R 16464 +#define LPTIM1_R 19465 +#define SPI2_R 19467 +#define SPI3_R 19468 +#define USART2_R 19470 +#define USART3_R 19471 +#define UART4_R 19472 +#define UART5_R 19473 +#define UART7_R 19474 +#define UART8_R 19475 +#define I2C1_R 19477 +#define I2C2_R 19478 +#define I2C3_R 19479 +#define I2C5_R 19480 +#define SPDIF_R 19482 +#define CEC_R 19483 +#define DAC12_R 19485 +#define MDIO_R 19847 +#define TIM1_R 19520 +#define TIM8_R 19521 +#define TIM15_R 19522 +#define TIM16_R 19523 +#define TIM17_R 19524 +#define SPI1_R 19528 +#define SPI4_R 19529 +#define SPI5_R 19530 +#define USART6_R 19533 +#define SAI1_R 19536 +#define SAI2_R 19537 +#define SAI3_R 19538 +#define DFSDM_R 19540 +#define FDCAN_R 19544 +#define LPTIM2_R 19584 +#define LPTIM3_R 19585 +#define LPTIM4_R 19586 +#define LPTIM5_R 19587 +#define SAI4_R 19592 +#define SYSCFG_R 19595 +#define VREF_R 19597 +#define TMPSENS_R 19600 +#define PMBCTRL_R 19601 +#define DMA1_R 19648 +#define DMA2_R 19649 +#define DMAMUX_R 19650 +#define ADC12_R 19653 +#define USBO_R 19656 +#define SDMMC3_R 19664 +#define CAMITF_R 19712 +#define CRYP2_R 19716 +#define HASH2_R 19717 +#define RNG2_R 19718 +#define CRC2_R 19719 +#define HSEM_R 19723 +#define MBOX_R 19724 +#define GPIOA_R 19776 +#define GPIOB_R 19777 +#define GPIOC_R 19778 +#define GPIOD_R 19779 +#define GPIOE_R 19780 +#define GPIOF_R 19781 +#define GPIOG_R 19782 +#define GPIOH_R 19783 +#define GPIOI_R 19784 +#define GPIOJ_R 19785 +#define GPIOK_R 19786 + +/* SCMI reset domain identifiers */ +#define RST_SCMI0_SPI6 0 +#define RST_SCMI0_I2C4 1 +#define RST_SCMI0_I2C6 2 +#define RST_SCMI0_USART1 3 +#define RST_SCMI0_STGEN 4 +#define RST_SCMI0_GPIOZ 5 +#define RST_SCMI0_CRYP1 6 +#define RST_SCMI0_HASH1 7 +#define RST_SCMI0_RNG1 8 +#define RST_SCMI0_MDMA 9 +#define RST_SCMI0_MCU 10 +#define RST_SCMI0_MCU_HOLD_BOOT 11 + +#endif /* _DT_BINDINGS_STM32MP15_RESET_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h b/arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h new file mode 100644 index 0000000..3f9fb3b --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef _DT_BINDINGS_STM32_ETZPC_H +#define _DT_BINDINGS_STM32_ETZPC_H + +/* DECPROT modes */ +#define DECPROT_S_RW 0x0 +#define DECPROT_NS_R_S_W 0x1 +#define DECPROT_MCU_ISOLATION 0x2 +#define DECPROT_NS_RW 0x3 + +/* DECPROT lock */ +#define DECPROT_UNLOCK 0x0 +#define DECPROT_LOCK 0x1 + +#endif /* _DT_BINDINGS_STM32_ETZPC_H */ diff --git a/arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h b/arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h new file mode 100644 index 0000000..1cb2326 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + * + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_STM32MP13_TZC400_H +#define _DT_BINDINGS_STM32MP13_TZC400_H + +#include + +#define STM32MP1_TZC_A7_ID U(0) +#define STM32MP1_TZC_LCD_ID U(3) +#define STM32MP1_TZC_MDMA_ID U(5) +#define STM32MP1_TZC_DMA_ID U(6) +#define STM32MP1_TZC_USB_HOST_ID U(7) +#define STM32MP1_TZC_USB_OTG_ID U(8) +#define STM32MP1_TZC_SDMMC_ID U(9) +#define STM32MP1_TZC_ETH_ID U(10) +#define STM32MP1_TZC_DCMIPP_ID U(11) +#define STM32MP1_TZC_DAP_ID U(15) + +#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \ + (TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DCMIPP_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)) + +#endif /* _DT_BINDINGS_STM32MP13_TZC400_H */ diff --git a/arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h b/arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h new file mode 100644 index 0000000..54cd902 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_STM32MP15_TZC400_H +#define _DT_BINDINGS_STM32MP15_TZC400_H + +#include + +#define STM32MP1_TZC_A7_ID U(0) +#define STM32MP1_TZC_M4_ID U(1) +#define STM32MP1_TZC_LCD_ID U(3) +#define STM32MP1_TZC_GPU_ID U(4) +#define STM32MP1_TZC_MDMA_ID U(5) +#define STM32MP1_TZC_DMA_ID U(6) +#define STM32MP1_TZC_USB_HOST_ID U(7) +#define STM32MP1_TZC_USB_OTG_ID U(8) +#define STM32MP1_TZC_SDMMC_ID U(9) +#define STM32MP1_TZC_ETH_ID U(10) +#define STM32MP1_TZC_DAP_ID U(15) + +#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \ + (TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)) + +#endif /* _DT_BINDINGS_STM32MP15_TZC400_H */ diff --git a/arm-trusted-firmware/include/export/README b/arm-trusted-firmware/include/export/README new file mode 100644 index 0000000..2de8d6b --- /dev/null +++ b/arm-trusted-firmware/include/export/README @@ -0,0 +1,33 @@ +All headers under include/export/ are export headers that are intended for +inclusion in third-party code which needs to interact with TF-A data structures +or interfaces. They must follow these special rules: + +- Header guards should start with ARM_TRUSTED_FIRMWARE_ to reduce clash risk. + +- All definitions should be sufficiently namespaced (e.g. with BL_ or TF_) to + make name clashes with third-party code unlikely. + +- They must not #include any headers except other export headers, and those + includes must use relative paths with "../double_quotes.h" notation. + +- They must not rely on any type definitions other that types defined + in the ISO C standard (i.e. uint64_t is fine, but not u_register_t). They + should still not #include . Instead, wrapper headers including + export headers need to ensure that they #include earlier in their + include order. + +- They must not rely on any macro definitions other than those which are + pre-defined by all common compilers (e.g. __ASSEMBLER__ or __aarch64__). + +- They must only contain macro, type and structure definitions, no prototypes. + +- They should avoid using integer types with architecture-dependent widths + (e.g. long, uintptr_t, pointer types) where possible. (Some existing export + headers are violating this for now.) + +- Their names should always end in "_exp.h". + +- Normal TF-A code should never include export headers directly. Instead, it + should include a wrapper header that ensures the export header is included in + the right manner. (The wrapper header for include/export/x/y/z_exp.h should + normally be placed at include/x/y/z.h.) diff --git a/arm-trusted-firmware/include/export/common/bl_common_exp.h b/arm-trusted-firmware/include/export/common/bl_common_exp.h new file mode 100644 index 0000000..8f09017 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/export/common/ep_info_exp.h b/arm-trusted-firmware/include/export/common/ep_info_exp.h new file mode 100644 index 0000000..a5bd10a --- /dev/null +++ b/arm-trusted-firmware/include/export/common/ep_info_exp.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021, 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. Bit 0 and + * bit 5 are used to determine the security + * state of the image as follows: + * + * --------------------------------- + * Bit 5 | Bit 0 | Security state + * --------------------------------- + * 0 0 EP_SECURE + * 0 1 EP_NON_SECURE + * 1 1 EP_REALM + */ +#define EP_SECURITY_MASK UL(0x21) +#define EP_SECURITY_SHIFT UL(0) +#define EP_SECURE UL(0x0) +#define EP_NON_SECURE UL(0x1) +#define EP_REALM UL(0x21) + +/* 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/arm-trusted-firmware/include/export/common/param_header_exp.h b/arm-trusted-firmware/include/export/common/param_header_exp.h new file mode 100644 index 0000000..15bb6f2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h b/arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h new file mode 100644 index 0000000..98544c0 --- /dev/null +++ b/arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2019-2021, 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) + +/* + * Primary FWU metadata image ID + */ +#define FWU_METADATA_IMAGE_ID U(32) + +/* + * Backup FWU metadata image ID + */ +#define BKUP_FWU_METADATA_IMAGE_ID U(33) + +/* Realm Monitor Manager (RMM) */ +#define RMM_IMAGE_ID U(34) + +/* Max Images */ +#define MAX_IMAGE_IDS U(35) + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */ diff --git a/arm-trusted-firmware/include/export/drivers/gpio_exp.h b/arm-trusted-firmware/include/export/drivers/gpio_exp.h new file mode 100644 index 0000000..e4112a9 --- /dev/null +++ b/arm-trusted-firmware/include/export/drivers/gpio_exp.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#define ARM_TF_GPIO_DIR_OUT 0 +#define ARM_TF_GPIO_DIR_IN 1 + +#define ARM_TF_GPIO_LEVEL_LOW 0 +#define ARM_TF_GPIO_LEVEL_HIGH 1 + +#define ARM_TF_GPIO_PULL_NONE 0 +#define ARM_TF_GPIO_PULL_UP 1 +#define ARM_TF_GPIO_PULL_DOWN 2 +#define ARM_TF_GPIO_PULL_REPEATER 3 + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H */ diff --git a/arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h b/arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h new file mode 100644 index 0000000..7391dec --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/export/lib/utils_def_exp.h b/arm-trusted-firmware/include/export/lib/utils_def_exp.h new file mode 100644 index 0000000..d4a4a85 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h b/arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h new file mode 100644 index 0000000..d650030 --- /dev/null +++ b/arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../../lib/bl_aux_params/bl_aux_params_exp.h" + +/* param type */ +enum bl_aux_mtk_param_type { + BL_AUX_PARAM_MTK_RESET_GPIO = BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST, +}; + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H */ diff --git a/arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h b/arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h new file mode 100644 index 0000000..ccc9cd9 --- /dev/null +++ b/arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../../lib/bl_aux_params/bl_aux_params_exp.h" + +/* param type */ +enum bl_aux_rk_param_type { + BL_AUX_PARAM_RK_RESET_GPIO = BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST, + BL_AUX_PARAM_RK_POWEROFF_GPIO, + BL_AUX_PARAM_RK_SUSPEND_GPIO, + BL_AUX_PARAM_RK_SUSPEND_APIO, +}; + +struct bl_aux_rk_apio_info { + uint8_t apio1 : 1; + uint8_t apio2 : 1; + uint8_t apio3 : 1; + uint8_t apio4 : 1; + uint8_t apio5 : 1; +}; + +struct bl_aux_param_rk_apio { + struct bl_aux_param_header h; + struct bl_aux_rk_apio_info apio; +}; + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H */ diff --git a/arm-trusted-firmware/include/lib/bakery_lock.h b/arm-trusted-firmware/include/lib/bakery_lock.h new file mode 100644 index 0000000..1fece01 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h b/arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h new file mode 100644 index 0000000..f6ce802 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/cassert.h b/arm-trusted-firmware/include/lib/cassert.h new file mode 100644 index 0000000..bbfdfdb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/coreboot.h b/arm-trusted-firmware/include/lib/coreboot.h new file mode 100644 index 0000000..0aa6579 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h b/arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h new file mode 100644 index 0000000..1d40cec --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AEM_GENERIC_H +#define AEM_GENERIC_H + +#include + +/* BASE AEM midr for revision 0 */ +#define BASE_AEM_MIDR U(0x410FD0F0) + +#endif /* AEM_GENERIC_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h new file mode 100644 index 0000000..abacdba --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A12_H +#define CORTEX_A12_H + +#include + +/******************************************************************************* + * Cortex-A12 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A12_MIDR U(0x410FC0D0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A12_ACTLR_SMP_BIT (U(1) << 6) + +#endif /* CORTEX_A12_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h new file mode 100644 index 0000000..9526a9c --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A15_H +#define CORTEX_A15_H + +#include + +/******************************************************************************* + * Auxiliary Control Register 2 specific definitions. + ******************************************************************************/ +#define CORTEX_A15_ACTLR2 p15, 1, c15, c0, 4 + +#define CORTEX_A15_ACTLR2_INV_DCC_BIT (U(1) << 0) + +/******************************************************************************* + * Cortex-A15 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A15_MIDR U(0x410FC0F0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A15_ACTLR_INV_BTB_BIT (U(1) << 0) +#define CORTEX_A15_ACTLR_SMP_BIT (U(1) << 6) + +#endif /* CORTEX_A15_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h new file mode 100644 index 0000000..89a8eb6 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A17_H +#define CORTEX_A17_H + +#include + +/******************************************************************************* + * Cortex-A17 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A17_MIDR U(0x410FC0E0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A17_ACTLR_SMP_BIT (U(1) << 6) + +/******************************************************************************* + * Implementation defined register specific definitions. + ******************************************************************************/ +#define CORTEX_A17_IMP_DEF_REG1 p15, 0, c15, c0, 1 + +#endif /* CORTEX_A17_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h new file mode 100644 index 0000000..6ddd533 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A32_H +#define CORTEX_A32_H + +#include + +/* Cortex-A32 Main ID register for revision 0 */ +#define CORTEX_A32_MIDR U(0x410FD010) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + * CPUECTLR_EL1 is an implementation-specific register. + ******************************************************************************/ +#define CORTEX_A32_CPUECTLR_EL1 p15, 1, c15 +#define CORTEX_A32_CPUECTLR_SMPEN_BIT (ULL(1) << 6) + +#endif /* CORTEX_A32_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h new file mode 100644 index 0000000..76703b7 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A5_H +#define CORTEX_A5_H + +#include + +/******************************************************************************* + * Cortex-A8 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A5_MIDR U(0x410FC050) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A5_ACTLR_SMP_BIT (U(1) << 6) + +#endif /* CORTEX_A5_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h new file mode 100644 index 0000000..8dd0192 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A53_H +#define CORTEX_A53_H + +#include + +/* Cortex-A53 midr for revision 0 */ +#define CORTEX_A53_MIDR U(0x410FD030) + +/* Retention timer tick definitions */ +#define RETENTION_ENTRY_TICKS_2 U(0x1) +#define RETENTION_ENTRY_TICKS_8 U(0x2) +#define RETENTION_ENTRY_TICKS_32 U(0x3) +#define RETENTION_ENTRY_TICKS_64 U(0x4) +#define RETENTION_ENTRY_TICKS_128 U(0x5) +#define RETENTION_ENTRY_TICKS_256 U(0x6) +#define RETENTION_ENTRY_TICKS_512 U(0x7) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_ECTLR p15, 1, c15 + +#define CORTEX_A53_ECTLR_SMP_BIT (U(1) << 6) + +#define CORTEX_A53_ECTLR_CPU_RET_CTRL_SHIFT U(0) +#define CORTEX_A53_ECTLR_CPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A53_ECTLR_CPU_RET_CTRL_SHIFT) + +#define CORTEX_A53_ECTLR_FPU_RET_CTRL_SHIFT U(3) +#define CORTEX_A53_ECTLR_FPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A53_ECTLR_FPU_RET_CTRL_SHIFT) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_MERRSR p15, 2, c15 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_CPUACTLR p15, 0, c15 + +#define CORTEX_A53_CPUACTLR_ENDCCASCI_SHIFT U(44) +#define CORTEX_A53_CPUACTLR_ENDCCASCI (ULL(1) << CORTEX_A53_CPUACTLR_ENDCCASCI_SHIFT) +#define CORTEX_A53_CPUACTLR_DTAH_SHIFT U(24) +#define CORTEX_A53_CPUACTLR_DTAH (ULL(1) << CORTEX_A53_CPUACTLR_DTAH_SHIFT) + +/******************************************************************************* + * L2 Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2ACTLR p15, 1, c15, c0, 0 + +#define CORTEX_A53_L2ACTLR_ENABLE_UNIQUECLEAN (U(1) << 14) +#define CORTEX_A53_L2ACTLR_DISABLE_CLEAN_PUSH (U(1) << 3) + +/******************************************************************************* + * L2 Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2ECTLR p15, 1, c9, c0, 3 + +#define CORTEX_A53_L2ECTLR_RET_CTRL_SHIFT U(0) +#define CORTEX_A53_L2ECTLR_RET_CTRL_MASK (U(0x7) << L2ECTLR_RET_CTRL_SHIFT) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2MERRSR p15, 3, c15 + +#endif /* CORTEX_A53_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h new file mode 100644 index 0000000..ffabd61 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A57_H +#define CORTEX_A57_H + +#include + +/* Cortex-A57 midr for revision 0 */ +#define CORTEX_A57_MIDR U(0x410FD070) + +/* Retention timer tick definitions */ +#define RETENTION_ENTRY_TICKS_2 U(0x1) +#define RETENTION_ENTRY_TICKS_8 U(0x2) +#define RETENTION_ENTRY_TICKS_32 U(0x3) +#define RETENTION_ENTRY_TICKS_64 U(0x4) +#define RETENTION_ENTRY_TICKS_128 U(0x5) +#define RETENTION_ENTRY_TICKS_256 U(0x6) +#define RETENTION_ENTRY_TICKS_512 U(0x7) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_ECTLR p15, 1, c15 + +#define CORTEX_A57_ECTLR_SMP_BIT (ULL(1) << 6) +#define CORTEX_A57_ECTLR_DIS_TWD_ACC_PFTCH_BIT (ULL(1) << 38) +#define CORTEX_A57_ECTLR_L2_IPFTCH_DIST_MASK (ULL(0x3) << 35) +#define CORTEX_A57_ECTLR_L2_DPFTCH_DIST_MASK (ULL(0x3) << 32) + +#define CORTEX_A57_ECTLR_CPU_RET_CTRL_SHIFT U(0) +#define CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A57_ECTLR_CPU_RET_CTRL_SHIFT) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_CPUMERRSR p15, 2, c15 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_CPUACTLR p15, 0, c15 + +#define CORTEX_A57_CPUACTLR_DIS_LOAD_PASS_DMB (ULL(1) << 59) +#define CORTEX_A57_CPUACTLR_DIS_DMB_NULLIFICATION (ULL(1) << 58) +#define CORTEX_A57_CPUACTLR_DIS_LOAD_PASS_STORE (ULL(1) << 55) +#define CORTEX_A57_CPUACTLR_GRE_NGRE_AS_NGNRE (ULL(1) << 54) +#define CORTEX_A57_CPUACTLR_DIS_OVERREAD (ULL(1) << 52) +#define CORTEX_A57_CPUACTLR_NO_ALLOC_WBWA (ULL(1) << 49) +#define CORTEX_A57_CPUACTLR_DCC_AS_DCCI (ULL(1) << 44) +#define CORTEX_A57_CPUACTLR_FORCE_FPSCR_FLUSH (ULL(1) << 38) +#define CORTEX_A57_CPUACTLR_DIS_INSTR_PREFETCH (ULL(1) << 32) +#define CORTEX_A57_CPUACTLR_DIS_STREAMING (ULL(3) << 27) +#define CORTEX_A57_CPUACTLR_DIS_L1_STREAMING (ULL(3) << 25) +#define CORTEX_A57_CPUACTLR_DIS_INDIRECT_PREDICTOR (ULL(1) << 4) + +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2CTLR p15, 1, c9, c0, 2 + +#define CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT U(0) +#define CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT U(6) + +#define CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES U(0x2) +#define CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES U(0x2) + +/******************************************************************************* + * L2 Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2ECTLR p15, 1, c9, c0, 3 + +#define CORTEX_A57_L2ECTLR_RET_CTRL_SHIFT U(0) +#define CORTEX_A57_L2ECTLR_RET_CTRL_MASK (U(0x7) << CORTEX_A57_L2ECTLR_RET_CTRL_SHIFT) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2MERRSR p15, 3, c15 + +#endif /* CORTEX_A57_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h new file mode 100644 index 0000000..730fdb5 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A7_H +#define CORTEX_A7_H + +#include + +/******************************************************************************* + * Cortex-A7 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A7_MIDR U(0x410FC070) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A7_ACTLR_SMP_BIT (U(1) << 6) + +#endif /* CORTEX_A7_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h new file mode 100644 index 0000000..4b1af61 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A72_H +#define CORTEX_A72_H + +#include + +/* Cortex-A72 midr for revision 0 */ +#define CORTEX_A72_MIDR U(0x410FD080) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_ECTLR p15, 1, c15 + +#define CORTEX_A72_ECTLR_SMP_BIT (ULL(1) << 6) +#define CORTEX_A72_ECTLR_DIS_TWD_ACC_PFTCH_BIT (ULL(1) << 38) +#define CORTEX_A72_ECTLR_L2_IPFTCH_DIST_MASK (ULL(0x3) << 35) +#define CORTEX_A72_ECTLR_L2_DPFTCH_DIST_MASK (ULL(0x3) << 32) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_MERRSR p15, 2, c15 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_CPUACTLR p15, 0, c15 + +#define CORTEX_A72_CPUACTLR_DISABLE_L1_DCACHE_HW_PFTCH (ULL(1) << 56) +#define CORTEX_A72_CPUACTLR_DIS_LOAD_PASS_STORE (ULL(1) << 55) +#define CORTEX_A72_CPUACTLR_NO_ALLOC_WBWA (ULL(1) << 49) +#define CORTEX_A72_CPUACTLR_DCC_AS_DCCI (ULL(1) << 44) +#define CORTEX_A72_CPUACTLR_DIS_INSTR_PREFETCH (ULL(1) << 32) + +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2CTLR p15, 1, c9, c0, 2 + +#define CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT U(0) +#define CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT U(6) + +#define CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES U(0x2) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES U(0x1) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_3_CYCLES U(0x2) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2MERRSR p15, 3, c15 + +#endif /* CORTEX_A72_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h new file mode 100644 index 0000000..a8c978a --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A9_H +#define CORTEX_A9_H + +#include + +/******************************************************************************* + * Cortex-A9 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A9_MIDR U(0x410FC090) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A9_ACTLR_SMP_BIT (U(1) << 6) +#define CORTEX_A9_ACTLR_FLZW_BIT (U(1) << 3) + +/******************************************************************************* + * CPU Power Control Register + ******************************************************************************/ +#define PCR p15, 0, c15, c0, 0 + +#ifndef __ASSEMBLER__ +#include +DEFINE_COPROCR_RW_FUNCS(pcr, PCR) +#endif + +#endif /* CORTEX_A9_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S b/arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S new file mode 100644 index 0000000..a5ae6a4 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CPU_MACROS_S +#define CPU_MACROS_S + +#include +#include + +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3) +#define IMAGE_AT_EL3 +#endif + +#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 + +/* Word size for 32-bit CPUs */ +#define CPU_WORD_SIZE 4 + +/* + * Whether errata status needs reporting. Errata status is printed in debug + * builds for both BL1 and BL32 images. + */ +#if (defined(IMAGE_BL1) || defined(IMAGE_BL32)) && DEBUG +# define REPORT_ERRATA 1 +#else +# define REPORT_ERRATA 0 +#endif + + + .equ CPU_MIDR_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 + +#ifndef IMAGE_AT_EL3 + .equ CPU_RESET_FUNC_SIZE, 0 +#endif + +/* The power down core and cluster is needed only in BL32 */ +#ifndef IMAGE_BL32 + .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 BL32 requires mutual exclusion and printed flag. */ +#if !(REPORT_ERRATA && defined(IMAGE_BL32)) + .equ CPU_ERRATA_LOCK_SIZE, 0 + .equ CPU_ERRATA_PRINTED_SIZE, 0 +#endif + + +/* + * Define the offsets to the fields in cpu_ops structure. + * Every offset is defined based on the offset and size of the previous + * field. + */ + .equ CPU_MIDR, 0 + .equ CPU_RESET_FUNC, CPU_MIDR + CPU_MIDR_SIZE + .equ CPU_PWR_DWN_OPS, CPU_RESET_FUNC + CPU_RESET_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_OPS_SIZE, CPU_ERRATA_PRINTED + CPU_ERRATA_PRINTED_SIZE + + /* + * Write given expressions as words + * + * _count: + * Write at least _count words. If the given number of expressions + * is less than _count, repeat the last expression to fill _count + * 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 + .word \_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 + * _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 _name:req, _midr:req, _resetfunc:req, \ + _power_down_ops:vararg + .section cpu_ops, "a" + .align 2 + .type cpu_ops_\_name, %object + .word \_midr +#if defined(IMAGE_AT_EL3) + .word \_resetfunc +#endif +#ifdef IMAGE_BL32 + /* 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. + */ + .word \_name\()_errata_report + +#ifdef IMAGE_BL32 + /* Pointers to errata lock and reported flag */ + .word \_name\()_errata_lock + .word \_name\()_errata_reported +#endif +#endif + .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=r4 + /* Stash a string with errata ID */ + .pushsection .rodata + \_cpu\()_errata_\_id\()_str: + .asciz "\_id" + .popsection + + /* Check whether errata applies */ + mov r0, \_rev_var + 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. + */ + cmp r0, #0 + movne r0, #ERRATA_MISSING + .endif + ldr r1, =\_cpu\()_cpu_str + ldr r2, =\_cpu\()_errata_\_id\()_str + bl errata_print_msg + .endm +#endif + /* + * 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: r0-r1 + */ + .macro jump_if_cpu_midr _cpu_midr, _label + ldcopr r0, MIDR + ubfx r0, r0, #MIDR_PN_SHIFT, #12 + ldr r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + cmp r0, r1 + beq \_label + .endm + +#endif /* CPU_MACROS_S */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h b/arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h new file mode 100644 index 0000000..6bb30a2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AEM_GENERIC_H +#define AEM_GENERIC_H + +#include + +/* BASE AEM midr for revision 0 */ +#define BASE_AEM_MIDR U(0x410FD0F0) + +/* Foundation AEM midr for revision 0 */ +#define FOUNDATION_AEM_MIDR U(0x410FD000) + +#endif /* AEM_GENERIC_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h new file mode 100644 index 0000000..5421478 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A35_H +#define CORTEX_A35_H + +#include + +/* Cortex-A35 Main ID register for revision 0 */ +#define CORTEX_A35_MIDR U(0x410FD040) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + * CPUECTLR_EL1 is an implementation-specific register. + ******************************************************************************/ +#define CORTEX_A35_CPUECTLR_EL1 S3_1_C15_C2_1 +#define CORTEX_A35_CPUECTLR_SMPEN_BIT (ULL(1) << 6) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A35_CPUACTLR_EL1 S3_1_C15_C2_0 + +#define CORTEX_A35_CPUACTLR_EL1_ENDCCASCI (ULL(1) << 44) + +#endif /* CORTEX_A35_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h new file mode 100644 index 0000000..2b8db14 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A510_H +#define CORTEX_A510_H + +#define CORTEX_A510_MIDR U(0x410FD460) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_A510_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_SHIFT U(19) +#define CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_DISABLE U(1) +#define CORTEX_A510_CPUECTLR_EL1_RSCTL_SHIFT U(23) +#define CORTEX_A510_CPUECTLR_EL1_NTCTL_SHIFT U(46) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_A510_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A510_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +/******************************************************************************* + * Complex auxiliary control register specific definitions + ******************************************************************************/ +#define CORTEX_A510_CMPXACTLR_EL1 S3_0_C15_C1_3 + +/******************************************************************************* + * Auxiliary control register specific definitions + ******************************************************************************/ +#define CORTEX_A510_CPUACTLR_EL1 S3_0_C15_C1_0 + +#endif /* CORTEX_A510_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h new file mode 100644 index 0000000..54e646c --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A53_H +#define CORTEX_A53_H + +#include + +/* Cortex-A53 midr for revision 0 */ +#define CORTEX_A53_MIDR U(0x410FD030) + +/* Retention timer tick definitions */ +#define RETENTION_ENTRY_TICKS_2 U(0x1) +#define RETENTION_ENTRY_TICKS_8 U(0x2) +#define RETENTION_ENTRY_TICKS_32 U(0x3) +#define RETENTION_ENTRY_TICKS_64 U(0x4) +#define RETENTION_ENTRY_TICKS_128 U(0x5) +#define RETENTION_ENTRY_TICKS_256 U(0x6) +#define RETENTION_ENTRY_TICKS_512 U(0x7) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_ECTLR_EL1 S3_1_C15_C2_1 + +#define CORTEX_A53_ECTLR_SMP_BIT (ULL(1) << 6) + +#define CORTEX_A53_ECTLR_CPU_RET_CTRL_SHIFT U(0) +#define CORTEX_A53_ECTLR_CPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A53_ECTLR_CPU_RET_CTRL_SHIFT) + +#define CORTEX_A53_ECTLR_FPU_RET_CTRL_SHIFT U(3) +#define CORTEX_A53_ECTLR_FPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A53_ECTLR_FPU_RET_CTRL_SHIFT) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_MERRSR_EL1 S3_1_C15_C2_2 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_CPUACTLR_EL1 S3_1_C15_C2_0 + +#define CORTEX_A53_CPUACTLR_EL1_ENDCCASCI_SHIFT U(44) +#define CORTEX_A53_CPUACTLR_EL1_ENDCCASCI (ULL(1) << CORTEX_A53_CPUACTLR_EL1_ENDCCASCI_SHIFT) +#define CORTEX_A53_CPUACTLR_EL1_RADIS_SHIFT U(27) +#define CORTEX_A53_CPUACTLR_EL1_RADIS (ULL(3) << CORTEX_A53_CPUACTLR_EL1_RADIS_SHIFT) +#define CORTEX_A53_CPUACTLR_EL1_L1RADIS_SHIFT U(25) +#define CORTEX_A53_CPUACTLR_EL1_L1RADIS (ULL(3) << CORTEX_A53_CPUACTLR_EL1_L1RADIS_SHIFT) +#define CORTEX_A53_CPUACTLR_EL1_DTAH_SHIFT U(24) +#define CORTEX_A53_CPUACTLR_EL1_DTAH (ULL(1) << CORTEX_A53_CPUACTLR_EL1_DTAH_SHIFT) +#define CORTEX_A53_CPUACTLR_EL1_L1PCTL_SHIFT U(13) +#define CORTEX_A53_CPUACTLR_EL1_L1PCTL (ULL(7) << CORTEX_A53_CPUACTLR_EL1_L1PCTL_SHIFT) + +/******************************************************************************* + * L2 Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2ACTLR_EL1 S3_1_C15_C0_0 + +#define CORTEX_A53_L2ACTLR_ENABLE_UNIQUECLEAN (U(1) << 14) +#define CORTEX_A53_L2ACTLR_DISABLE_CLEAN_PUSH (U(1) << 3) +/******************************************************************************* + * L2 Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2ECTLR_EL1 S3_1_C11_C0_3 + +#define CORTEX_A53_L2ECTLR_RET_CTRL_SHIFT U(0) +#define CORTEX_A53_L2ECTLR_RET_CTRL_MASK (U(0x7) << L2ECTLR_RET_CTRL_SHIFT) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2MERRSR_EL1 S3_1_C15_C2_3 + +/******************************************************************************* + * Helper function to access a53_cpuectlr_el1 register on Cortex-A53 CPUs + ******************************************************************************/ +#ifndef __ASSEMBLER__ +DEFINE_RENAME_SYSREG_RW_FUNCS(a53_cpuectlr_el1, CORTEX_A53_ECTLR_EL1) +#endif /* __ASSEMBLER__ */ + +#endif /* CORTEX_A53_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h new file mode 100644 index 0000000..60ed957 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h new file mode 100644 index 0000000..dc40e31 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A57_H +#define CORTEX_A57_H + +#include + +/* Cortex-A57 midr for revision 0 */ +#define CORTEX_A57_MIDR U(0x410FD070) + +/* Retention timer tick definitions */ +#define RETENTION_ENTRY_TICKS_2 U(0x1) +#define RETENTION_ENTRY_TICKS_8 U(0x2) +#define RETENTION_ENTRY_TICKS_32 U(0x3) +#define RETENTION_ENTRY_TICKS_64 U(0x4) +#define RETENTION_ENTRY_TICKS_128 U(0x5) +#define RETENTION_ENTRY_TICKS_256 U(0x6) +#define RETENTION_ENTRY_TICKS_512 U(0x7) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_ECTLR_EL1 S3_1_C15_C2_1 + +#define CORTEX_A57_ECTLR_SMP_BIT (ULL(1) << 6) +#define CORTEX_A57_ECTLR_DIS_TWD_ACC_PFTCH_BIT (ULL(1) << 38) +#define CORTEX_A57_ECTLR_L2_IPFTCH_DIST_MASK (ULL(0x3) << 35) +#define CORTEX_A57_ECTLR_L2_DPFTCH_DIST_MASK (ULL(0x3) << 32) + +#define CORTEX_A57_ECTLR_CPU_RET_CTRL_SHIFT U(0) +#define CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A57_ECTLR_CPU_RET_CTRL_SHIFT) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_MERRSR_EL1 S3_1_C15_C2_2 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_CPUACTLR_EL1 S3_1_C15_C2_0 + +#define CORTEX_A57_CPUACTLR_EL1_DIS_LOAD_PASS_DMB (ULL(1) << 59) +#define CORTEX_A57_CPUACTLR_EL1_DIS_DMB_NULLIFICATION (ULL(1) << 58) +#define CORTEX_A57_CPUACTLR_EL1_DIS_LOAD_PASS_STORE (ULL(1) << 55) +#define CORTEX_A57_CPUACTLR_EL1_GRE_NGRE_AS_NGNRE (ULL(1) << 54) +#define CORTEX_A57_CPUACTLR_EL1_DIS_OVERREAD (ULL(1) << 52) +#define CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA (ULL(1) << 49) +#define CORTEX_A57_CPUACTLR_EL1_DCC_AS_DCCI (ULL(1) << 44) +#define CORTEX_A57_CPUACTLR_EL1_FORCE_FPSCR_FLUSH (ULL(1) << 38) +#define CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH (ULL(1) << 32) +#define CORTEX_A57_CPUACTLR_EL1_DIS_STREAMING (ULL(3) << 27) +#define CORTEX_A57_CPUACTLR_EL1_EN_NC_LOAD_FWD (ULL(1) << 24) +#define CORTEX_A57_CPUACTLR_EL1_DIS_L1_STREAMING (ULL(3) << 25) +#define CORTEX_A57_CPUACTLR_EL1_DIS_INDIRECT_PREDICTOR (ULL(1) << 4) + +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2CTLR_EL1 S3_1_C11_C0_2 + +#define CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT U(0) +#define CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT U(6) + +#define CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES U(0x2) +#define CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES U(0x2) + +#define CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT (U(1) << 21) + +/******************************************************************************* + * L2 Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2ECTLR_EL1 S3_1_C11_C0_3 + +#define CORTEX_A57_L2ECTLR_RET_CTRL_SHIFT U(0) +#define CORTEX_A57_L2ECTLR_RET_CTRL_MASK (U(0x7) << CORTEX_A57_L2ECTLR_RET_CTRL_SHIFT) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2MERRSR_EL1 S3_1_C15_C2_3 + +#endif /* CORTEX_A57_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h new file mode 100644 index 0000000..0df34c9 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A65_H +#define CORTEX_A65_H + +#include + +#define CORTEX_A65_MIDR U(0x410FD060) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_A65_ECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions + ******************************************************************************/ +#define CORTEX_A65_CPUACTLR_EL1 S3_0_C15_C1_0 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ + +#define CORTEX_A65_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A65_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0) + +#endif /* CORTEX_A65_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h new file mode 100644 index 0000000..bd4a881 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A65AE_H +#define CORTEX_A65AE_H + +#include + +#define CORTEX_A65AE_MIDR U(0x410FD430) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_A65AE_ECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions + ******************************************************************************/ +#define CORTEX_A65AE_CPUACTLR_EL1 S3_0_C15_C1_0 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ + +#define CORTEX_A65AE_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A65AE_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0) + +#endif /* CORTEX_A65AE_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h new file mode 100644 index 0000000..09614ee --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A710_H +#define CORTEX_A710_H + +#define CORTEX_A710_MIDR U(0x410FD470) + +/* Cortex-A710 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A710_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_A710_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_A710_CPUECTLR_EL1_PFSTIDIS_BIT (ULL(1) << 8) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_A710_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A710_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A710_CPUACTLR_EL1 S3_0_C15_C1_0 +#define CORTEX_A710_CPUACTLR_EL1_BIT_46 (ULL(1) << 46) +#define CORTEX_A710_CPUACTLR_EL1_BIT_22 (ULL(1) << 22) + +/******************************************************************************* + * CPU Auxiliary Control register 2 specific definitions. + ******************************************************************************/ +#define CORTEX_A710_CPUACTLR2_EL1 S3_0_C15_C1_1 + +/******************************************************************************* + * CPU Auxiliary Control register 5 specific definitions. + ******************************************************************************/ +#define CORTEX_A710_CPUACTLR5_EL1 S3_0_C15_C8_0 +#define CORTEX_A710_CPUACTLR5_EL1_BIT_13 (ULL(1) << 13) +#define CORTEX_A710_CPUACTLR5_EL1_BIT_44 (ULL(1) << 44) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A710_CPUECTLR2_EL1 S3_0_C15_C1_5 +#define CORTEX_A710_CPUECTLR2_EL1_PF_MODE_CNSRV ULL(9) +#define CPUECTLR2_EL1_PF_MODE_LSB U(11) +#define CPUECTLR2_EL1_PF_MODE_WIDTH U(4) + +#endif /* CORTEX_A710_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h new file mode 100644 index 0000000..1777645 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A72_H +#define CORTEX_A72_H + +#include + +/* Cortex-A72 midr for revision 0 */ +#define CORTEX_A72_MIDR U(0x410FD080) + +/* Cortex-A72 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A72_BHB_LOOP_COUNT U(8) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_ECTLR_EL1 S3_1_C15_C2_1 + +#define CORTEX_A72_ECTLR_SMP_BIT (ULL(1) << 6) +#define CORTEX_A72_ECTLR_DIS_TWD_ACC_PFTCH_BIT (ULL(1) << 38) +#define CORTEX_A72_ECTLR_L2_IPFTCH_DIST_MASK (ULL(0x3) << 35) +#define CORTEX_A72_ECTLR_L2_DPFTCH_DIST_MASK (ULL(0x3) << 32) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_MERRSR_EL1 S3_1_C15_C2_2 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_CPUACTLR_EL1 S3_1_C15_C2_0 + +#define CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH (ULL(1) << 56) +#define CORTEX_A72_CPUACTLR_EL1_DIS_LOAD_PASS_STORE (ULL(1) << 55) +#define CORTEX_A72_CPUACTLR_EL1_NO_ALLOC_WBWA (ULL(1) << 49) +#define CORTEX_A72_CPUACTLR_EL1_DCC_AS_DCCI (ULL(1) << 44) +#define CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH (ULL(1) << 32) + +/******************************************************************************* + * L2 Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2ACTLR_EL1 S3_1_C15_C0_0 + +#define CORTEX_A72_L2ACTLR_FORCE_TAG_BANK_CLK_ACTIVE (ULL(1) << 28) +#define CORTEX_A72_L2ACTLR_FORCE_L2_LOGIC_CLK_ACTIVE (ULL(1) << 27) +#define CORTEX_A72_L2ACTLR_FORCE_L2_GIC_TIMER_RCG_CLK_ACTIVE (ULL(1) << 26) +#define CORTEX_A72_L2ACTLR_ENABLE_UNIQUE_CLEAN (ULL(1) << 14) +#define CORTEX_A72_L2ACTLR_DISABLE_DSB_WITH_NO_DVM_SYNC (ULL(1) << 11) +#define CORTEX_A72_L2ACTLR_DISABLE_DVM_CMO_BROADCAST (ULL(1) << 8) +#define CORTEX_A72_L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT (ULL(1) << 7) +#define CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI (ULL(1) << 6) + +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2CTLR_EL1 S3_1_C11_C0_2 + +#define CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT U(0) +#define CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT U(5) +#define CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT U(6) +#define CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT U(9) + +#define CORTEX_A72_L2_DATA_RAM_LATENCY_MASK U(0x7) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_MASK U(0x7) +#define CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES U(0x2) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES U(0x1) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_3_CYCLES U(0x2) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2MERRSR_EL1 S3_1_C15_C2_3 + +#endif /* CORTEX_A72_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h new file mode 100644 index 0000000..271a333 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A73_H +#define CORTEX_A73_H + +#include + +/* Cortex-A73 midr for revision 0 */ +#define CORTEX_A73_MIDR U(0x410FD090) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A73_CPUECTLR_EL1 S3_1_C15_C2_1 /* Instruction def. */ + +#define CORTEX_A73_CPUECTLR_SMP_BIT (ULL(1) << 6) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A73_L2MERRSR_EL1 S3_1_C15_C2_3 /* Instruction def. */ + +/******************************************************************************* + * CPU implementation defined register specific definitions. + ******************************************************************************/ +#define CORTEX_A73_IMP_DEF_REG1 S3_0_C15_C0_0 + +#define CORTEX_A73_IMP_DEF_REG1_DISABLE_LOAD_PASS_STORE (ULL(1) << 3) + +#define CORTEX_A73_DIAGNOSTIC_REGISTER S3_0_C15_C0_1 + +#define CORTEX_A73_IMP_DEF_REG2 S3_0_C15_C0_2 + +/******************************************************************************* + * Helper function to access a73_cpuectlr_el1 register on Cortex-A73 CPUs + ******************************************************************************/ +#ifndef __ASSEMBLER__ +DEFINE_RENAME_SYSREG_RW_FUNCS(a73_cpuectlr_el1, CORTEX_A73_CPUECTLR_EL1) +#endif /* __ASSEMBLER__ */ + +#endif /* CORTEX_A73_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h new file mode 100644 index 0000000..e5ca1ba --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A75_H +#define CORTEX_A75_H + +#include + +/* Cortex-A75 MIDR */ +#define CORTEX_A75_MIDR U(0x410fd0a0) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A75_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A75_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A75_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define CORTEX_A75_CPUACTLR_EL1_DISABLE_LOAD_PASS_STORE (ULL(1) << 35) + +/* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */ +#define CORTEX_A75_CORE_PWRDN_EN_MASK U(0x1) + +#define CORTEX_A75_ACTLR_AMEN_BIT (ULL(1) << 4) + +/* + * The Cortex-A75 core implements five counters, 0-4. Events 0, 1, 2, are + * fixed and are enabled (Group 0). Events 3 and 4 (Group 1) are + * programmable by programming the appropriate Event count bits in + * CPUAMEVTYPER register and are disabled by default. Platforms may + * enable this with suitable programming. + */ +#define CORTEX_A75_AMU_NR_COUNTERS U(5) +#define CORTEX_A75_AMU_GROUP0_MASK U(0x7) +#define CORTEX_A75_AMU_GROUP1_MASK (U(0) << 3) + +#ifndef __ASSEMBLER__ +#include + +uint64_t cortex_a75_amu_cnt_read(int idx); +void cortex_a75_amu_cnt_write(int idx, uint64_t val); +unsigned int cortex_a75_amu_read_cpuamcntenset_el0(void); +unsigned int cortex_a75_amu_read_cpuamcntenclr_el0(void); +void cortex_a75_amu_write_cpuamcntenset_el0(unsigned int mask); +void cortex_a75_amu_write_cpuamcntenclr_el0(unsigned int mask); +#endif /* __ASSEMBLER__ */ + +#endif /* CORTEX_A75_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h new file mode 100644 index 0000000..0c8b29e --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A76_H +#define CORTEX_A76_H + +#include + +/* Cortex-A76 MIDR for revision 0 */ +#define CORTEX_A76_MIDR U(0x410fd0b0) + +/* Cortex-A76 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A76_BHB_LOOP_COUNT U(24) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A76_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A76_CPUECTLR_EL1 S3_0_C15_C1_4 + +#define CORTEX_A76_CPUECTLR_EL1_WS_THR_L2 (ULL(3) << 24) +#define CORTEX_A76_CPUECTLR_EL1_BIT_51 (ULL(1) << 51) + +/******************************************************************************* + * Definitions for CORTEX_A76_CPUECTLR_EL1 register related to Write-streaming. + ******************************************************************************/ +#define WS_THR_L2_256B (U(0) << 24) +#define WS_THR_L2_4KB (U(1) << 24) +#define WS_THR_L2_8KB (U(2) << 24) +#define WS_THR_L2_DISABLE (U(3) << 24) + +#define WS_THR_L3_768B (U(0) << 22) +#define WS_THR_L3_16KB (U(1) << 22) +#define WS_THR_L3_32KB (U(2) << 22) +#define WS_THR_L3_DISABLE (U(3) << 22) + +#define WS_THR_L4_16KB (U(0) << 20) +#define WS_THR_L4_64KB (U(1) << 20) +#define WS_THR_L4_128KB (U(2) << 20) +#define WS_THR_L4_DISABLE (U(3) << 20) + +#define WS_THR_DRAM_64KB (U(0) << 18) +/* 1MB, for memory designated as outer-allocate.*/ +#define WS_THR_DRAM_ALLOC_1MB (U(1) << 18) +/* 1MB, allocating irrespective of outer-allocation designation. */ +#define WS_THR_DRAM_1MB (U(2) << 18) +#define WS_THR_DRAM_DISABLE (U(3) << 18) + +#define WS_THR_DISABLE_ALL (WS_THR_L2_DISABLE | WS_THR_L3_DISABLE | WS_THR_L4_DISABLE | \ + WS_THR_DRAM_DISABLE) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A76_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define CORTEX_A76_CPUACTLR_EL1_DISABLE_STATIC_PREDICTION (ULL(1) << 6) + +#define CORTEX_A76_CPUACTLR_EL1_BIT_13 (ULL(1) << 13) + +#define CORTEX_A76_CPUACTLR2_EL1 S3_0_C15_C1_1 + +#define CORTEX_A76_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2) + +#define CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE (ULL(1) << 16) + +#define CORTEX_A76_CPUACTLR3_EL1 S3_0_C15_C1_2 + +#define CORTEX_A76_CPUACTLR3_EL1_BIT_10 (ULL(1) << 10) + + +/* Definitions of register field mask in CORTEX_A76_CPUPWRCTLR_EL1 */ +#define CORTEX_A76_CORE_PWRDN_EN_MASK U(0x1) + +#endif /* CORTEX_A76_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h new file mode 100644 index 0000000..0d30f70 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A76AE_H +#define CORTEX_A76AE_H + +#include + +/* Cortex-A76AE MIDR for revision 0 */ +#define CORTEX_A76AE_MIDR U(0x410FD0E0) + +/* Cortex-A76 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A76AE_BHB_LOOP_COUNT U(24) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A76AE_CPUPWRCTLR_EL1 S3_0_C15_C2_7 + +/* Definitions of register field mask in CORTEX_A76AE_CPUPWRCTLR_EL1 */ +#define CORTEX_A76AE_CORE_PWRDN_EN_MASK U(0x1) + +#define CORTEX_A76AE_CPUECTLR_EL1 S3_0_C15_C1_4 + +#endif /* CORTEX_A76AE_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h new file mode 100644 index 0000000..4a87168 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A77_H +#define CORTEX_A77_H + +#include + +/* Cortex-A77 MIDR */ +#define CORTEX_A77_MIDR U(0x410FD0D0) + +/* Cortex-A77 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A77_BHB_LOOP_COUNT U(24) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A77_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_A77_CPUECTLR_EL1_BIT_8 (ULL(1) << 8) + +/******************************************************************************* + * CPU Power Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A77_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A77_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A77_ACTLR2_EL1 S3_0_C15_C1_1 +#define CORTEX_A77_ACTLR2_EL1_BIT_2 (ULL(1) << 2) + +#define CORTEX_A77_CPUPSELR_EL3 S3_6_C15_C8_0 +#define CORTEX_A77_CPUPCR_EL3 S3_6_C15_C8_1 +#define CORTEX_A77_CPUPOR_EL3 S3_6_C15_C8_2 +#define CORTEX_A77_CPUPMR_EL3 S3_6_C15_C8_3 +#define CORTEX_A77_CPUPOR2_EL3 S3_6_C15_C8_4 +#define CORTEX_A77_CPUPMR2_EL3 S3_6_C15_C8_5 + +#endif /* CORTEX_A77_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h new file mode 100644 index 0000000..31da99e --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A78_H +#define CORTEX_A78_H + +#include + +#define CORTEX_A78_MIDR U(0x410FD410) + +/* Cortex-A78 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A78_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A78_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_A78_CPUECTLR_EL1_BIT_8 (ULL(1) << 8) +#define CORTEX_A78_CPUECTLR_EL1_PF_MODE_CNSRV ULL(3) +#define CPUECTLR_EL1_PF_MODE_LSB U(6) +#define CPUECTLR_EL1_PF_MODE_WIDTH U(2) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_A78_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT U(1) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A78_ACTLR_TAM_BIT (ULL(1) << 30) + +#define CORTEX_A78_ACTLR2_EL1 S3_0_C15_C1_1 +#define CORTEX_A78_ACTLR2_EL1_BIT_0 (ULL(1) << 0) +#define CORTEX_A78_ACTLR2_EL1_BIT_1 (ULL(1) << 1) +#define CORTEX_A78_ACTLR2_EL1_BIT_2 (ULL(1) << 2) +#define CORTEX_A78_ACTLR2_EL1_BIT_40 (ULL(1) << 40) + +/******************************************************************************* + * CPU Activity Monitor Unit register specific definitions. + ******************************************************************************/ +#define CPUAMCNTENCLR0_EL0 S3_3_C15_C2_4 +#define CPUAMCNTENSET0_EL0 S3_3_C15_C2_5 +#define CPUAMCNTENCLR1_EL0 S3_3_C15_C3_0 +#define CPUAMCNTENSET1_EL0 S3_3_C15_C3_1 + +#define CORTEX_A78_AMU_GROUP0_MASK U(0xF) +#define CORTEX_A78_AMU_GROUP1_MASK U(0x7) + +#endif /* CORTEX_A78_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h new file mode 100644 index 0000000..09f82df --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A78_AE_H +#define CORTEX_A78_AE_H + +#include + +#define CORTEX_A78_AE_MIDR U(0x410FD420) + +/* Cortex-A78AE loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A78_AE_BHB_LOOP_COUNT U(32) + +#define CORTEX_A78_AE_ACTLR_CLUSTERPMUEN_BIT (ULL(1) << 12) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A78_AE_CPUECTLR_EL1 CORTEX_A78_CPUECTLR_EL1 +#define CORTEX_A78_AE_CPUECTLR_EL1_BIT_8 CORTEX_A78_CPUECTLR_EL1_BIT_8 + +/******************************************************************************* + * CPU Auxiliary Control register 2 specific definitions. + ******************************************************************************/ +#define CORTEX_A78_AE_ACTLR2_EL1 CORTEX_A78_ACTLR2_EL1 +#define CORTEX_A78_AE_ACTLR2_EL1_BIT_0 CORTEX_A78_ACTLR2_EL1_BIT_0 +#define CORTEX_A78_AE_ACTLR2_EL1_BIT_40 CORTEX_A78_ACTLR2_EL1_BIT_40 + +#endif /* CORTEX_A78_AE_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h new file mode 100644 index 0000000..34c964f --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A78C_H +#define CORTEX_A78C_H + + +#define CORTEX_A78C_MIDR U(0x410FD4B1) + +#define CORTEX_A78C_ACTLR_CLUSTERPMUEN_BIT (ULL(1) << 12) + +/* Cortex-A76 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A78C_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A78C_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_A78C_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A78C_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT U(1) + +#endif /* CORTEX_A78C_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h new file mode 100644 index 0000000..82022e9 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_HAYES_H +#define CORTEX_HAYES_H + +#define CORTEX_HAYES_MIDR U(0x410FD800) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_HAYES_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_HAYES_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_HAYES_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* CORTEX_HAYES_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h new file mode 100644 index 0000000..8b59fd9 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_HUNTER_H +#define CORTEX_HUNTER_H + +#define CORTEX_HUNTER_MIDR U(0x410FD810) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_HUNTER_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_HUNTER_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_HUNTER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* CORTEX_HUNTER_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h new file mode 100644 index 0000000..4e0dc86 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_MAKALU_H +#define CORTEX_MAKALU_H + +#define CORTEX_MAKALU_MIDR U(0x410FD4D0) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_MAKALU_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_MAKALU_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_MAKALU_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* CORTEX_MAKALU_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h new file mode 100644 index 0000000..a0d788e --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_MAKALU_ELP_ARM_H +#define CORTEX_MAKALU_ELP_ARM_H + +#define CORTEX_MAKALU_ELP_ARM_MIDR U(0x410FD4E0) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_MAKALU_ELP_ARM_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* CORTEX_MAKALU_ELP_ARM_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h new file mode 100644 index 0000000..62530e2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_X2_H +#define CORTEX_X2_H + +#define CORTEX_X2_MIDR U(0x410FD480) + +/* Cortex-X2 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_X2_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_X2_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_X2_CPUECTLR_EL1_PFSTIDIS_BIT (ULL(1) << 8) + +/******************************************************************************* + * CPU Extended Control register 2 specific definitions + ******************************************************************************/ +#define CORTEX_X2_CPUECTLR2_EL1 S3_0_C15_C1_5 + +#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_SHIFT U(11) +#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_WIDTH U(4) +#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_CNSRV ULL(0x9) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_X2_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_X2_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +/******************************************************************************* + * CPU Auxiliary Control Register 5 definitions + ******************************************************************************/ +#define CORTEX_X2_CPUACTLR5_EL1 S3_0_C15_C8_0 +#define CORTEX_X2_CPUACTLR5_EL1_BIT_17 (ULL(1) << 17) + +/******************************************************************************* + * CPU Implementation Specific Selected Instruction registers + ******************************************************************************/ +#define CORTEX_X2_IMP_CPUPSELR_EL3 S3_6_C15_C8_0 +#define CORTEX_X2_IMP_CPUPCR_EL3 S3_6_C15_C8_1 +#define CORTEX_X2_IMP_CPUPOR_EL3 S3_6_C15_C8_2 +#define CORTEX_X2_IMP_CPUPMR_EL3 S3_6_C15_C8_3 + +#endif /* CORTEX_X2_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S b/arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S new file mode 100644 index 0000000..92e65ae --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2014-2022, 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 +#define CPU_NO_EXTRA3_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_EXTRA3_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_EXTRA3_FUNC, CPU_EXTRA2_FUNC + CPU_EXTRA2_FUNC_SIZE + .equ CPU_E_HANDLER_FUNC, CPU_EXTRA3_FUNC + CPU_EXTRA3_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. + * _extra3: + * 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-2022-23960 needs to be applied or not. + * _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, _extra3: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 \_extra3 + .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, 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, 0, \_e_handler, \_power_down_ops + .endm + + .macro declare_cpu_ops_wa _name:req, _midr:req, \ + _resetfunc:req, _extra1:req, _extra2:req, \ + _extra3:req, _power_down_ops:vararg + declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ + \_extra1, \_extra2, \_extra3, 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/arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h new file mode 100644 index 0000000..463f890 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CPUAMU_H +#define CPUAMU_H + +/******************************************************************************* + * CPU Activity Monitor Unit register specific definitions. + ******************************************************************************/ +#define CPUAMCNTENCLR_EL0 S3_3_C15_C9_7 +#define CPUAMCNTENSET_EL0 S3_3_C15_C9_6 +#define CPUAMCFGR_EL0 S3_3_C15_C10_6 +#define CPUAMUSERENR_EL0 S3_3_C15_C10_7 + +/* Activity Monitor Event Counter Registers */ +#define CPUAMEVCNTR0_EL0 S3_3_C15_C9_0 +#define CPUAMEVCNTR1_EL0 S3_3_C15_C9_1 +#define CPUAMEVCNTR2_EL0 S3_3_C15_C9_2 +#define CPUAMEVCNTR3_EL0 S3_3_C15_C9_3 +#define CPUAMEVCNTR4_EL0 S3_3_C15_C9_4 + +/* Activity Monitor Event Type Registers */ +#define CPUAMEVTYPER0_EL0 S3_3_C15_C10_0 +#define CPUAMEVTYPER1_EL0 S3_3_C15_C10_1 +#define CPUAMEVTYPER2_EL0 S3_3_C15_C10_2 +#define CPUAMEVTYPER3_EL0 S3_3_C15_C10_3 +#define CPUAMEVTYPER4_EL0 S3_3_C15_C10_4 + +#ifndef __ASSEMBLER__ +#include + +uint64_t cpuamu_cnt_read(unsigned int idx); +void cpuamu_cnt_write(unsigned int idx, uint64_t val); +unsigned int cpuamu_read_cpuamcntenset_el0(void); +unsigned int cpuamu_read_cpuamcntenclr_el0(void); +void cpuamu_write_cpuamcntenset_el0(unsigned int mask); +void cpuamu_write_cpuamcntenclr_el0(unsigned int mask); + +int midr_match(unsigned int cpu_midr); +void cpuamu_context_save(unsigned int nr_counters); +void cpuamu_context_restore(unsigned int nr_counters); + +#endif /* __ASSEMBLER__ */ + +#endif /* CPUAMU_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/denver.h b/arm-trusted-firmware/include/lib/cpus/aarch64/denver.h new file mode 100644 index 0000000..826ab8f --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/denver.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DENVER_H +#define DENVER_H + +/* MIDR values for Denver */ +#define DENVER_MIDR_PN0 U(0x4E0F0000) +#define DENVER_MIDR_PN1 U(0x4E0F0010) +#define DENVER_MIDR_PN2 U(0x4E0F0020) +#define DENVER_MIDR_PN3 U(0x4E0F0030) +#define DENVER_MIDR_PN4 U(0x4E0F0040) +#define DENVER_MIDR_PN5 U(0x4E0F0050) +#define DENVER_MIDR_PN6 U(0x4E0F0060) +#define DENVER_MIDR_PN7 U(0x4E0F0070) +#define DENVER_MIDR_PN8 U(0x4E0F0080) +#define DENVER_MIDR_PN9 U(0x4E0F0090) + +/* Implementer code in the MIDR register */ +#define DENVER_IMPL U(0x4E) + +/* CPU state ids - implementation defined */ +#define DENVER_CPU_STATE_POWER_DOWN U(0x3) + +/* Speculative store buffering */ +#define DENVER_CPU_DIS_SSB_EL3 (U(1) << 11) +#define DENVER_PN4_CPU_DIS_SSB_EL3 (U(1) << 18) + +/* Speculative memory disambiguation */ +#define DENVER_CPU_DIS_MD_EL3 (U(1) << 9) +#define DENVER_PN4_CPU_DIS_MD_EL3 (U(1) << 17) + +/* Core power management states */ +#define DENVER_CPU_PMSTATE_C1 U(0x1) +#define DENVER_CPU_PMSTATE_C6 U(0x6) +#define DENVER_CPU_PMSTATE_C7 U(0x7) +#define DENVER_CPU_PMSTATE_MASK U(0xF) + +/* ACTRL_ELx bits to enable dual execution*/ +#define DENVER_CPU_ENABLE_DUAL_EXEC_EL2 (ULL(1) << 9) +#define DENVER_CPU_ENABLE_DUAL_EXEC_EL3 (ULL(1) << 9) +#define DENVER_CPU_ENABLE_DUAL_EXEC_EL1 (U(1) << 4) + +/* + * ACTLR_EL3 bit to enable counting of events in the + * NVIDIA specific Performance Monitors extension. + */ +#define DENVER_CPU_ENABLE_SPME (U(1) << 6) + +#ifndef __ASSEMBLER__ + +/* Disable Dynamic Code Optimisation */ +void denver_disable_dco(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* DENVER_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h b/arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h new file mode 100644 index 0000000..0969acf --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/cpus/aarch64/generic.h b/arm-trusted-firmware/include/lib/cpus/aarch64/generic.h new file mode 100644 index 0000000..53df587 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/generic.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserverd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AARCH64_GENERIC_H +#define AARCH64_GENERIC_H + +#include + +/* + * 0x0 value on the MIDR implementer value is reserved for software use, + * so use an MIDR value of 0 for a default CPU library. + */ +#define AARCH64_GENERIC_MIDR U(0) + +#endif /* AARCH64_GENERIC_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h new file mode 100644 index 0000000..230ed66 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_DEMETER_H +#define NEOVERSE_DEMETER_H + +#define NEOVERSE_DEMETER_MIDR U(0x410FD4F0) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define NEOVERSE_DEMETER_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define NEOVERSE_DEMETER_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* NEOVERSE_DEMETER_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h new file mode 100644 index 0000000..96b4661 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_E1_H +#define NEOVERSE_E1_H + +#include + +#define NEOVERSE_E1_MIDR U(0x410FD4A0) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_E1_ECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_E1_CPUACTLR_EL1 S3_0_C15_C1_0 + +/******************************************************************************* + * CPU Power Control register specific definitions. + ******************************************************************************/ + +#define NEOVERSE_E1_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_E1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0) + +#endif /* NEOVERSE_E1_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h new file mode 100644 index 0000000..b6b8d8d --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_N1_H +#define NEOVERSE_N1_H + +#include + +/* Neoverse N1 MIDR for revision 0 */ +#define NEOVERSE_N1_MIDR U(0x410fd0c0) + +/* Neoverse N1 loop count for CVE-2022-23960 mitigation */ +#define NEOVERSE_N1_BHB_LOOP_COUNT U(24) + +/* Exception Syndrome register EC code for IC Trap */ +#define NEOVERSE_N1_EC_IC_TRAP U(0x1f) + +/******************************************************************************* + * CPU Power Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N1_CPUPWRCTLR_EL1 S3_0_C15_C2_7 + +/* Definitions of register field mask in NEOVERSE_N1_CPUPWRCTLR_EL1 */ +#define NEOVERSE_N1_CORE_PWRDN_EN_MASK U(0x1) + +#define NEOVERSE_N1_ACTLR_AMEN_BIT (U(1) << 4) + +#define NEOVERSE_N1_AMU_NR_COUNTERS U(5) +#define NEOVERSE_N1_AMU_GROUP0_MASK U(0x1f) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N1_CPUECTLR_EL1 S3_0_C15_C1_4 + +#define NEOVERSE_N1_WS_THR_L2_MASK (ULL(3) << 24) +#define NEOVERSE_N1_CPUECTLR_EL1_MM_TLBPF_DIS_BIT (ULL(1) << 51) +#define NEOVERSE_N1_CPUECTLR_EL1_EXTLLC_BIT (ULL(1) << 0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N1_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define NEOVERSE_N1_CPUACTLR_EL1_BIT_6 (ULL(1) << 6) +#define NEOVERSE_N1_CPUACTLR_EL1_BIT_13 (ULL(1) << 13) + +#define NEOVERSE_N1_CPUACTLR2_EL1 S3_0_C15_C1_1 + +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_0 (ULL(1) << 0) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_11 (ULL(1) << 11) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_15 (ULL(1) << 15) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_16 (ULL(1) << 16) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_59 (ULL(1) << 59) + +#define NEOVERSE_N1_CPUACTLR3_EL1 S3_0_C15_C1_2 + +#define NEOVERSE_N1_CPUACTLR3_EL1_BIT_10 (ULL(1) << 10) + +/* 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 /* NEOVERSE_N1_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h new file mode 100644 index 0000000..0452b39 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_N2_H +#define NEOVERSE_N2_H + +/* Neoverse N2 ID register for revision r0p0 */ +#define NEOVERSE_N2_MIDR U(0x410FD490) + +/* Neoverse N2 loop count for CVE-2022-23960 mitigation */ +#define NEOVERSE_N2_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Power control register + ******************************************************************************/ +#define NEOVERSE_N2_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_N2_CORE_PWRDN_EN_BIT (ULL(1) << 0) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUECTLR_EL1 S3_0_C15_C1_4 +#define NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT (ULL(1) << 0) +#define NEOVERSE_N2_CPUECTLR_EL1_PFSTIDIS_BIT (ULL(1) << 8) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUACTLR_EL1 S3_0_C15_C1_0 +#define NEOVERSE_N2_CPUACTLR_EL1_BIT_46 (ULL(1) << 46) +#define NEOVERSE_N2_CPUACTLR_EL1_BIT_22 (ULL(1) << 22) + +/******************************************************************************* + * CPU Auxiliary Control register 2 specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUACTLR2_EL1 S3_0_C15_C1_1 +#define NEOVERSE_N2_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2) + +/******************************************************************************* + * CPU Auxiliary Control register 5 specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUACTLR5_EL1 S3_0_C15_C8_0 +#define NEOVERSE_N2_CPUACTLR5_EL1_BIT_44 (ULL(1) << 44) +#define NEOVERSE_N2_CPUACTLR5_EL1_BIT_13 (ULL(1) << 13) +#define NEOVERSE_N2_CPUACTLR5_EL1_BIT_17 (ULL(1) << 17) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUECTLR2_EL1 S3_0_C15_C1_5 +#define NEOVERSE_N2_CPUECTLR2_EL1_PF_MODE_CNSRV ULL(9) +#define CPUECTLR2_EL1_PF_MODE_LSB U(11) +#define CPUECTLR2_EL1_PF_MODE_WIDTH U(4) + +#endif /* NEOVERSE_N2_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h new file mode 100644 index 0000000..7cb91cd --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_N_COMMON_H +#define NEOVERSE_N_COMMON_H + +/****************************************************************************** + * Neoverse Nx CPU Configuration register definitions + *****************************************************************************/ +#define CPUCFR_EL1 S3_0_C15_C0_0 + +/* SCU bit of CPU Configuration Register, EL1 */ +#define SCU_SHIFT U(2) + +#endif /* NEOVERSE_N_COMMON_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h new file mode 100644 index 0000000..0a8b1d1 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_POSEIDON_H +#define NEOVERSE_POSEIDON_H + + +#define NEOVERSE_POSEIDON_MIDR U(0x410FD830) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_POSEIDON_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define NEOVERSE_POSEIDON_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_POSEIDON_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* NEOVERSE_POSEIDON_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h new file mode 100644 index 0000000..a904c04 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_V1_H +#define NEOVERSE_V1_H + +#define NEOVERSE_V1_MIDR U(0x410FD400) + +/* Neoverse V1 loop count for CVE-2022-23960 mitigation */ +#define NEOVERSE_V1_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_V1_CPUECTLR_EL1 S3_0_C15_C1_4 +#define NEOVERSE_V1_CPUECTLR_EL1_BIT_8 (ULL(1) << 8) +#define NEOVERSE_V1_CPUECTLR_EL1_BIT_53 (ULL(1) << 53) +#define NEOVERSE_V1_CPUECTLR_EL1_PF_MODE_CNSRV ULL(3) +#define CPUECTLR_EL1_PF_MODE_LSB U(6) +#define CPUECTLR_EL1_PF_MODE_WIDTH U(2) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define NEOVERSE_V1_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_V1_ACTLR2_EL1 S3_0_C15_C1_1 +#define NEOVERSE_V1_ACTLR2_EL1_BIT_2 (ULL(1) << 2) +#define NEOVERSE_V1_ACTLR2_EL1_BIT_28 (ULL(1) << 28) + +#endif /* NEOVERSE_V1_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h b/arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h new file mode 100644 index 0000000..14da170 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QEMU_MAX_H +#define QEMU_MAX_H + +#include + +/* + * QEMU MAX midr for revision 0 + * 00 - Reserved for software use + * 0 - Variant + * F - Architectural features identified in ID_* registers + * 051 - 'Q', in a 12-bit field. + * 0 - Revision + */ +#define QEMU_MAX_MIDR U(0x000F0510) + +#endif /* QEMU_MAX_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h b/arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h new file mode 100644 index 0000000..978661f --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RAINIER_H +#define RAINIER_H + +#include + +/* RAINIER MIDR for revision 0 */ +#define RAINIER_MIDR U(0x3f0f4120) + +/* Exception Syndrome register EC code for IC Trap */ +#define RAINIER_EC_IC_TRAP U(0x1f) + +/******************************************************************************* + * CPU Power Control register specific definitions. + ******************************************************************************/ +#define RAINIER_CPUPWRCTLR_EL1 S3_0_C15_C2_7 + +/* Definitions of register field mask in RAINIER_CPUPWRCTLR_EL1 */ +#define RAINIER_CORE_PWRDN_EN_MASK U(0x1) + +#define RAINIER_ACTLR_AMEN_BIT (U(1) << 4) + +#define RAINIER_AMU_NR_COUNTERS U(5) +#define RAINIER_AMU_GROUP0_MASK U(0x1f) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define RAINIER_CPUECTLR_EL1 S3_0_C15_C1_4 + +#define RAINIER_WS_THR_L2_MASK (ULL(3) << 24) +#define RAINIER_CPUECTLR_EL1_MM_TLBPF_DIS_BIT (ULL(1) << 51) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define RAINIER_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define RAINIER_CPUACTLR_EL1_BIT_6 (ULL(1) << 6) +#define RAINIER_CPUACTLR_EL1_BIT_13 (ULL(1) << 13) + +#define RAINIER_CPUACTLR2_EL1 S3_0_C15_C1_1 + +#define RAINIER_CPUACTLR2_EL1_BIT_0 (ULL(1) << 0) +#define RAINIER_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2) +#define RAINIER_CPUACTLR2_EL1_BIT_11 (ULL(1) << 11) +#define RAINIER_CPUACTLR2_EL1_BIT_15 (ULL(1) << 15) +#define RAINIER_CPUACTLR2_EL1_BIT_16 (ULL(1) << 16) +#define RAINIER_CPUACTLR2_EL1_BIT_59 (ULL(1) << 59) + +#define RAINIER_CPUACTLR3_EL1 S3_0_C15_C1_2 + +#define RAINIER_CPUACTLR3_EL1_BIT_10 (ULL(1) << 10) + +/* 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 /* RAINIER_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/errata_report.h b/arm-trusted-firmware/include/lib/cpus/errata_report.h new file mode 100644 index 0000000..efdedf0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h b/arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h new file mode 100644 index 0000000..940fc65 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h b/arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h new file mode 100644 index 0000000..e37db37 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h b/arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h new file mode 100644 index 0000000..35b3fd8 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WA_CVE_2022_23960_H +#define WA_CVE_2022_23960_H + +int check_smccc_arch_wa3_applies(void); + +#endif /* WA_CVE_2022_23960_H */ diff --git a/arm-trusted-firmware/include/lib/debugfs.h b/arm-trusted-firmware/include/lib/debugfs.h new file mode 100644 index 0000000..8ed237a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h b/arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h new file mode 100644 index 0000000..5604c8e --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016-2020, 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 'regs' + * structure at their correct offsets. + ******************************************************************************/ +#define CTX_REGS_OFFSET U(0x0) +#define CTX_GPREG_R0 U(0x0) +#define CTX_GPREG_R1 U(0x4) +#define CTX_GPREG_R2 U(0x8) +#define CTX_GPREG_R3 U(0xC) +#define CTX_LR U(0x10) +#define CTX_SCR U(0x14) +#define CTX_SPSR U(0x18) +#define CTX_NS_SCTLR U(0x1C) +#define CTX_REGS_END U(0x20) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* + * Common constants to help define the 'cpu_context' structure and its + * members below. + */ +#define WORD_SHIFT U(2) +#define DEFINE_REG_STRUCT(name, num_regs) \ + typedef struct name { \ + uint32_t ctx_regs[num_regs]; \ + } __aligned(8) name##_t + +/* Constants to determine the size of individual context structures */ +#define CTX_REG_ALL (CTX_REGS_END >> WORD_SHIFT) + +DEFINE_REG_STRUCT(regs, CTX_REG_ALL); + +#undef CTX_REG_ALL + +#define read_ctx_reg(ctx, offset) ((ctx)->ctx_regs[offset >> WORD_SHIFT]) +#define write_ctx_reg(ctx, offset, val) (((ctx)->ctx_regs[offset >> WORD_SHIFT]) \ + = val) +typedef struct cpu_context { + regs_t regs_ctx; +} cpu_context_t; + +/* Macros to access members of the 'cpu_context_t' structure */ +#define get_regs_ctx(h) (&((cpu_context_t *) h)->regs_ctx) + +/* + * 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_REGS_OFFSET == __builtin_offsetof(cpu_context_t, regs_ctx), \ + assert_core_context_regs_offset_mismatch); + +#endif /* __ASSEMBLER__ */ + +#endif /* CONTEXT_H */ diff --git a/arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h b/arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h new file mode 100644 index 0000000..512d196 --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h @@ -0,0 +1,526 @@ +/* + * 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_CPTR_EL3 U(0x38) +#define CTX_ZCR_EL3 U(0x40) +#define CTX_EL3STATE_END U(0x50) /* 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_HDFGRTR_EL2 U(0x160) +#define CTX_HAFGRTR_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) + +// Register for FEAT_HCX +#define CTX_HCRX_EL2 U(0x1e8) + +/* 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 the next lower EL in a given security state 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. + */ +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/arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h b/arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h new file mode 100644 index 0000000..2090687 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h b/arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h new file mode 100644 index 0000000..2c7b619 --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2014-2021, 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) + +#if ENABLE_RME +/* Size of cpu_context array */ +#define CPU_DATA_CONTEXT_NUM 3 +/* Offset of cpu_ops_ptr, size 8 bytes */ +#define CPU_DATA_CPU_OPS_PTR 0x18 +#else /* ENABLE_RME */ +#define CPU_DATA_CONTEXT_NUM 2 +#define CPU_DATA_CPU_OPS_PTR 0x10 +#endif /* ENABLE_RME */ + +#if ENABLE_PAUTH +/* 8-bytes aligned offset of apiakey[2], size 16 bytes */ +#define CPU_DATA_APIAKEY_OFFSET (0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \ + + CPU_DATA_CPU_OPS_PTR) +#define CPU_DATA_CRASH_BUF_OFFSET (0x10 + CPU_DATA_APIAKEY_OFFSET) +#else /* ENABLE_PAUTH */ +#define CPU_DATA_CRASH_BUF_OFFSET (0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \ + + CPU_DATA_CPU_OPS_PTR) +#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 + +#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 + +typedef enum context_pas { + CPU_CONTEXT_SECURE = 0, + CPU_CONTEXT_NS, +#if ENABLE_RME + CPU_CONTEXT_REALM, +#endif + CPU_CONTEXT_NUM +} context_pas_t; + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ + +/******************************************************************************* + * Cache of frequently used per-cpu data: + * Pointers to non-secure, realm, 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 + * + * 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[CPU_DATA_CONTEXT_NUM]; +#endif /* __aarch64__ */ + 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]; + +#ifdef __aarch64__ +CASSERT(CPU_DATA_CONTEXT_NUM == CPU_CONTEXT_NUM, + assert_cpu_data_context_num_mismatch); +#endif + +#if ENABLE_PAUTH +CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof + (cpu_data_t, apiakey), + assert_cpu_data_pauth_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 + +/* + * Returns the index of the cpu_context array for the given security state. + * All accesses to cpu_context should be through this helper to make sure + * an access is not out-of-bounds. The function assumes security_state is + * valid. + */ +static inline context_pas_t get_cpu_context_index(uint32_t security_state) +{ + if (security_state == SECURE) { + return CPU_CONTEXT_SECURE; + } else { +#if ENABLE_RME + if (security_state == NON_SECURE) { + return CPU_CONTEXT_NS; + } else { + assert(security_state == REALM); + return CPU_CONTEXT_REALM; + } +#else + assert(security_state == NON_SECURE); + return CPU_CONTEXT_NS; +#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/arm-trusted-firmware/include/lib/el3_runtime/pubsub.h b/arm-trusted-firmware/include/lib/el3_runtime/pubsub.h new file mode 100644 index 0000000..64fe5cc --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h b/arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h new file mode 100644 index 0000000..5012082 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/extensions/amu.h b/arm-trusted-firmware/include/lib/extensions/amu.h new file mode 100644 index 0000000..6452f7e --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/amu.h @@ -0,0 +1,47 @@ +/* + * 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 + +#if __aarch64__ +void amu_enable(bool el2_unused, cpu_context_t *ctx); +#else +void amu_enable(bool el2_unused); +#endif + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* + * AMU data for a single core. + */ +struct amu_core { + uint16_t enable; /* Mask of auxiliary counters to enable */ +}; + +/* + * Topological platform data specific to the AMU. + */ +struct amu_topology { + struct amu_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */ +}; + +#if !ENABLE_AMU_FCONF +/* + * Retrieve the platform's AMU topology. A `NULL` return value is treated as a + * non-fatal error, in which case no auxiliary counters will be enabled. + */ +const struct amu_topology *plat_amu_topology(void); +#endif /* ENABLE_AMU_FCONF */ +#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */ + +#endif /* AMU_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/mpam.h b/arm-trusted-firmware/include/lib/extensions/mpam.h new file mode 100644 index 0000000..414adcb --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/mpam.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MPAM_H +#define MPAM_H + +#include + +void mpam_enable(bool el2_unused); + +#endif /* MPAM_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/pauth.h b/arm-trusted-firmware/include/lib/extensions/pauth.h new file mode 100644 index 0000000..2e780de --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/extensions/ras.h b/arm-trusted-firmware/include/lib/extensions/ras.h new file mode 100644 index 0000000..793ab9f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/extensions/ras_arch.h b/arm-trusted-firmware/include/lib/extensions/ras_arch.h new file mode 100644 index 0000000..8d9e474 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/ras_arch.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, 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))) +#define ERR_MISC2(n) (0x30ULL + (64ULL * (n))) +#define ERR_MISC3(n) (0x38ULL + (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 U(8) +#define ERR_CTLR_RCFI_MASK ULL(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/arm-trusted-firmware/include/lib/extensions/sme.h b/arm-trusted-firmware/include/lib/extensions/sme.h new file mode 100644 index 0000000..893f9f2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/sme.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SME_H +#define SME_H + +#include + +#include + +/* + * Maximum value of LEN field in SMCR_ELx. This is different than the maximum + * supported value which is platform dependent. In the first version of SME the + * LEN field is limited to 4 bits but will be expanded in future iterations. + * To support different versions, the code that discovers the supported vector + * lengths will write the max value into SMCR_ELx then read it back to see how + * many bits are implemented. + */ +#define SME_SMCR_LEN_MAX U(0x1FF) + +void sme_enable(cpu_context_t *context); +void sme_disable(cpu_context_t *context); + +#endif /* SME_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/spe.h b/arm-trusted-firmware/include/lib/extensions/spe.h new file mode 100644 index 0000000..d4b925f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/extensions/sve.h b/arm-trusted-firmware/include/lib/extensions/sve.h new file mode 100644 index 0000000..4b66cdb --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/sve.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SVE_H +#define SVE_H + +#include + +void sve_enable(cpu_context_t *context); +void sve_disable(cpu_context_t *context); + +#endif /* SVE_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h b/arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h new file mode 100644 index 0000000..74470fe --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYS_REG_TRACE_H +#define SYS_REG_TRACE_H + +#include + +#if __aarch64__ +void sys_reg_trace_enable(cpu_context_t *context); +#else +void sys_reg_trace_enable(void); +#endif /* __aarch64__ */ + +#endif /* SYS_REG_TRACE_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/trbe.h b/arm-trusted-firmware/include/lib/extensions/trbe.h new file mode 100644 index 0000000..1753ab6 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/trbe.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRBE_H +#define TRBE_H + +void trbe_enable(void); + +#endif /* TRBE_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/trf.h b/arm-trusted-firmware/include/lib/extensions/trf.h new file mode 100644 index 0000000..18f17f3 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/trf.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRF_H +#define TRF_H + +void trf_enable(void); + +#endif /* TRF_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/twed.h b/arm-trusted-firmware/include/lib/extensions/twed.h new file mode 100644 index 0000000..eac4aa3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/fconf/fconf.h b/arm-trusted-firmware/include/lib/fconf/fconf.h new file mode 100644 index 0000000..917e053 --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_H +#define FCONF_H + +#include + +/* Public API */ +#define FCONF_GET_PROPERTY(a, b, c) a##__##b##_getter(c) + +/* + * This macro takes three arguments: + * config: Configuration identifier + * name: property namespace + * callback: populate() function + */ +#define FCONF_REGISTER_POPULATOR(config, name, callback) \ + __attribute__((used, section(".fconf_populator"))) \ + const struct fconf_populator (name##__populator) = { \ + .config_type = (#config), \ + .info = (#name), \ + .populate = (callback) \ + }; + +/* + * Populator callback + * + * This structure are used by the fconf_populate function and should only be + * defined by the FCONF_REGISTER_POPULATOR macro. + */ +struct fconf_populator { + /* Description of the data loaded by the callback */ + const char *config_type; + const char *info; + + /* Callback used by fconf_populate function with a provided config dtb. + * Return 0 on success, err_code < 0 otherwise. + */ + int (*populate)(uintptr_t config); +}; + +/* This function supports to load tb_fw_config and fw_config dtb */ +int fconf_load_config(unsigned int image_id); + +/* Top level populate function + * + * This function takes a configuration dtb and calls all the registered + * populator callback with it. + * + * Panic on error. + */ +void fconf_populate(const char *config_type, uintptr_t config); + +/* FCONF specific getter */ +#define fconf__dtb_getter(prop) fconf_dtb_info.prop + +/* Structure used to locally keep a reference to the config dtb. */ +struct fconf_dtb_info_t { + uintptr_t base_addr; + size_t size; +}; + +extern struct fconf_dtb_info_t fconf_dtb_info; + +#endif /* FCONF_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h b/arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h new file mode 100644 index 0000000..2faee73 --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_AMU_GETTER_H +#define FCONF_AMU_GETTER_H + +#include + +#define amu__config_getter(id) fconf_amu_config.id + +struct fconf_amu_config { + const struct amu_topology *topology; +}; + +extern struct fconf_amu_config fconf_amu_config; + +#endif /* FCONF_AMU_GETTER_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h b/arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h new file mode 100644 index 0000000..ff51c6c --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_DYN_CFG_GETTER_H +#define FCONF_DYN_CFG_GETTER_H + +#include + +#define FCONF_INVALID_IDX 0xFFFFFFFFU + +/* Dynamic configuration related getter */ +#define dyn_cfg__dtb_getter(id) dyn_cfg_dtb_info_getter(id) + +struct dyn_cfg_dtb_info_t { + uintptr_t config_addr; + uint32_t config_max_size; + unsigned int config_id; +}; + +unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id); +struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id); +int fconf_populate_dtb_registry(uintptr_t config); + +/* Set config information in global DTB array */ +void set_config_info(uintptr_t config_addr, uint32_t config_max_size, + unsigned int config_id); + +#endif /* FCONF_DYN_CFG_GETTER_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h b/arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h new file mode 100644 index 0000000..50d991a --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_MPMM_GETTER_H +#define FCONF_MPMM_GETTER_H + +#include + +#define mpmm__config_getter(id) fconf_mpmm_config.id + +struct fconf_mpmm_config { + const struct mpmm_topology *topology; +}; + +extern struct fconf_mpmm_config fconf_mpmm_config; + +#endif /* FCONF_MPMM_GETTER_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h b/arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h new file mode 100644 index 0000000..db98b68 --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_TBBR_GETTER_H +#define FCONF_TBBR_GETTER_H + +#include + +#include + +/* TBBR related getter */ +#define tbbr__cot_getter(id) __extension__ ({ \ + assert((id) < cot_desc_size); \ + cot_desc_ptr[id]; \ +}) + +#define tbbr__dyn_config_getter(id) tbbr_dyn_config.id + +struct tbbr_dyn_config_t { + uint32_t disable_auth; + void *mbedtls_heap_addr; + size_t mbedtls_heap_size; +}; + +extern struct tbbr_dyn_config_t tbbr_dyn_config; + +int fconf_populate_tbbr_dyn_config(uintptr_t config); + +#endif /* FCONF_TBBR_GETTER_H */ diff --git a/arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h b/arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h new file mode 100644 index 0000000..94a88b0 --- /dev/null +++ b/arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPT_RME_H +#define GPT_RME_H + +#include + +#include + +/******************************************************************************/ +/* GPT helper macros and definitions */ +/******************************************************************************/ + +/* + * Structure for specifying a mapping range and it's properties. This should not + * be manually initialized, using the MAP_GPT_REGION_x macros is recommended as + * to avoid potential incompatibilities in the future. + */ +typedef struct pas_region { + uintptr_t base_pa; /* Base address for PAS. */ + size_t size; /* Size of the PAS. */ + unsigned int attrs; /* PAS GPI and entry type. */ +} pas_region_t; + +/* GPT GPI definitions */ +#define GPT_GPI_NO_ACCESS U(0x0) +#define GPT_GPI_SECURE U(0x8) +#define GPT_GPI_NS U(0x9) +#define GPT_GPI_ROOT U(0xA) +#define GPT_GPI_REALM U(0xB) +#define GPT_GPI_ANY U(0xF) +#define GPT_GPI_VAL_MASK UL(0xF) + +#define GPT_NSE_SECURE U(0b00) +#define GPT_NSE_ROOT U(0b01) +#define GPT_NSE_NS U(0b10) +#define GPT_NSE_REALM U(0b11) + +#define GPT_NSE_SHIFT U(62) + +/* PAS attribute GPI definitions. */ +#define GPT_PAS_ATTR_GPI_SHIFT U(0) +#define GPT_PAS_ATTR_GPI_MASK U(0xF) +#define GPT_PAS_ATTR_GPI(_attrs) (((_attrs) \ + >> GPT_PAS_ATTR_GPI_SHIFT) \ + & GPT_PAS_ATTR_GPI_MASK) + +/* PAS attribute mapping type definitions */ +#define GPT_PAS_ATTR_MAP_TYPE_BLOCK U(0x0) +#define GPT_PAS_ATTR_MAP_TYPE_GRANULE U(0x1) +#define GPT_PAS_ATTR_MAP_TYPE_SHIFT U(4) +#define GPT_PAS_ATTR_MAP_TYPE_MASK U(0x1) +#define GPT_PAS_ATTR_MAP_TYPE(_attrs) (((_attrs) \ + >> GPT_PAS_ATTR_MAP_TYPE_SHIFT) \ + & GPT_PAS_ATTR_MAP_TYPE_MASK) + +/* + * Macro to initialize the attributes field in the pas_region_t structure. + * [31:5] Reserved + * [4] Mapping type (GPT_PAS_ATTR_MAP_TYPE_x definitions) + * [3:0] PAS GPI type (GPT_GPI_x definitions) + */ +#define GPT_PAS_ATTR(_type, _gpi) \ + ((((_type) & GPT_PAS_ATTR_MAP_TYPE_MASK) \ + << GPT_PAS_ATTR_MAP_TYPE_SHIFT) | \ + (((_gpi) & GPT_PAS_ATTR_GPI_MASK) \ + << GPT_PAS_ATTR_GPI_SHIFT)) + +/* + * Macro to create a GPT entry for this PAS range as a block descriptor. If this + * region does not fit the requirements for a block descriptor then GPT + * initialization will fail. + */ +#define GPT_MAP_REGION_BLOCK(_pa, _sz, _gpi) \ + { \ + .base_pa = (_pa), \ + .size = (_sz), \ + .attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_BLOCK, (_gpi)), \ + } + +/* + * Macro to create a GPT entry for this PAS range as a table descriptor. If this + * region does not fit the requirements for a table descriptor then GPT + * initialization will fail. + */ +#define GPT_MAP_REGION_GRANULE(_pa, _sz, _gpi) \ + { \ + .base_pa = (_pa), \ + .size = (_sz), \ + .attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_GRANULE, (_gpi)), \ + } + +/******************************************************************************/ +/* GPT register field definitions */ +/******************************************************************************/ + +/* + * Least significant address bits protected by each entry in level 0 GPT. This + * field is read-only. + */ +#define GPCCR_L0GPTSZ_SHIFT U(20) +#define GPCCR_L0GPTSZ_MASK U(0xF) + +typedef enum { + GPCCR_L0GPTSZ_30BITS = U(0x0), + GPCCR_L0GPTSZ_34BITS = U(0x4), + GPCCR_L0GPTSZ_36BITS = U(0x6), + GPCCR_L0GPTSZ_39BITS = U(0x9) +} gpccr_l0gptsz_e; + +/* Granule protection check priority bit definitions */ +#define GPCCR_GPCP_SHIFT U(17) +#define GPCCR_GPCP_BIT (ULL(1) << GPCCR_EL3_GPCP_SHIFT) + +/* Granule protection check bit definitions */ +#define GPCCR_GPC_SHIFT U(16) +#define GPCCR_GPC_BIT (ULL(1) << GPCCR_GPC_SHIFT) + +/* Physical granule size bit definitions */ +#define GPCCR_PGS_SHIFT U(14) +#define GPCCR_PGS_MASK U(0x3) +#define SET_GPCCR_PGS(x) (((x) & GPCCR_PGS_MASK) << GPCCR_PGS_SHIFT) + +typedef enum { + GPCCR_PGS_4K = U(0x0), + GPCCR_PGS_64K = U(0x1), + GPCCR_PGS_16K = U(0x2) +} gpccr_pgs_e; + +/* GPT fetch shareability attribute bit definitions */ +#define GPCCR_SH_SHIFT U(12) +#define GPCCR_SH_MASK U(0x3) +#define SET_GPCCR_SH(x) (((x) & GPCCR_SH_MASK) << GPCCR_SH_SHIFT) + +typedef enum { + GPCCR_SH_NS = U(0x0), + GPCCR_SH_OS = U(0x2), + GPCCR_SH_IS = U(0x3) +} gpccr_sh_e; + +/* GPT fetch outer cacheability attribute bit definitions */ +#define GPCCR_ORGN_SHIFT U(10) +#define GPCCR_ORGN_MASK U(0x3) +#define SET_GPCCR_ORGN(x) (((x) & GPCCR_ORGN_MASK) << GPCCR_ORGN_SHIFT) + +typedef enum { + GPCCR_ORGN_NC = U(0x0), + GPCCR_ORGN_WB_RA_WA = U(0x1), + GPCCR_ORGN_WT_RA_NWA = U(0x2), + GPCCR_ORGN_WB_RA_NWA = U(0x3) +} gpccr_orgn_e; + +/* GPT fetch inner cacheability attribute bit definitions */ +#define GPCCR_IRGN_SHIFT U(8) +#define GPCCR_IRGN_MASK U(0x3) +#define SET_GPCCR_IRGN(x) (((x) & GPCCR_IRGN_MASK) << GPCCR_IRGN_SHIFT) + +typedef enum { + GPCCR_IRGN_NC = U(0x0), + GPCCR_IRGN_WB_RA_WA = U(0x1), + GPCCR_IRGN_WT_RA_NWA = U(0x2), + GPCCR_IRGN_WB_RA_NWA = U(0x3) +} gpccr_irgn_e; + +/* Protected physical address size bit definitions */ +#define GPCCR_PPS_SHIFT U(0) +#define GPCCR_PPS_MASK U(0x7) +#define SET_GPCCR_PPS(x) (((x) & GPCCR_PPS_MASK) << GPCCR_PPS_SHIFT) + +typedef enum { + GPCCR_PPS_4GB = U(0x0), + GPCCR_PPS_64GB = U(0x1), + GPCCR_PPS_1TB = U(0x2), + GPCCR_PPS_4TB = U(0x3), + GPCCR_PPS_16TB = U(0x4), + GPCCR_PPS_256TB = U(0x5), + GPCCR_PPS_4PB = U(0x6) +} gpccr_pps_e; + +/* Base Address for the GPT bit definitions */ +#define GPTBR_BADDR_SHIFT U(0) +#define GPTBR_BADDR_VAL_SHIFT U(12) +#define GPTBR_BADDR_MASK ULL(0xffffffffff) + +/******************************************************************************/ +/* GPT public APIs */ +/******************************************************************************/ + +/* + * Public API that initializes the entire protected space to GPT_GPI_ANY using + * the L0 tables (block descriptors). Ideally, this function is invoked prior + * to DDR discovery and initialization. The MMU must be initialized before + * calling this function. + * + * Parameters + * pps PPS value to use for table generation + * l0_mem_base Base address of L0 tables in memory. + * l0_mem_size Total size of memory available for L0 tables. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_l0_tables(gpccr_pps_e pps, + uintptr_t l0_mem_base, + size_t l0_mem_size); + +/* + * Public API that carves out PAS regions from the L0 tables and builds any L1 + * tables that are needed. This function ideally is run after DDR discovery and + * initialization. The L0 tables must have already been initialized to GPI_ANY + * when this function is called. + * + * Parameters + * pgs PGS value to use for table generation. + * l1_mem_base Base address of memory used for L1 tables. + * l1_mem_size Total size of memory available for L1 tables. + * *pas_regions Pointer to PAS regions structure array. + * pas_count Total number of PAS regions. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, + uintptr_t l1_mem_base, + size_t l1_mem_size, + pas_region_t *pas_regions, + unsigned int pas_count); + +/* + * Public API to initialize the runtime gpt_config structure based on the values + * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization + * typically happens in a bootloader stage prior to setting up the EL3 runtime + * environment for the granule transition service so this function detects the + * initialization from a previous stage. Granule protection checks must be + * enabled already or this function will return an error. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_runtime_init(void); + +/* + * Public API to enable granule protection checks once the tables have all been + * initialized. This function is called at first initialization and then again + * later during warm boots of CPU cores. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_enable(void); + +/* + * Public API to disable granule protection checks. + */ +void gpt_disable(void); + +/* + * This function is the core of the granule transition service. When a granule + * transition request occurs it is routed to this function where the request is + * validated then fulfilled if possible. + * + * TODO: implement support for transitioning multiple granules at once. + * + * Parameters + * base: Base address of the region to transition, must be aligned to granule + * size. + * size: Size of region to transition, must be aligned to granule size. + * src_sec_state: Security state of the originating SMC invoking the API. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_delegate_pas(uint64_t base, size_t size, unsigned int src_sec_state); +int gpt_undelegate_pas(uint64_t base, size_t size, unsigned int src_sec_state); + +#endif /* GPT_RME_H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/endian_.h b/arm-trusted-firmware/include/lib/libc/aarch32/endian_.h new file mode 100644 index 0000000..0cf2c75 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/endian_.h @@ -0,0 +1,146 @@ +/*- + * 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 */ + +#ifdef __ARMEB__ +#define _BYTE_ORDER _BIG_ENDIAN +#else +#define _BYTE_ORDER _LITTLE_ENDIAN +#endif /* __ARMEB__ */ + +#if __BSD_VISIBLE +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER +#endif + +#ifdef __ARMEB__ +#define _QUAD_HIGHWORD 0 +#define _QUAD_LOWWORD 1 +#define __ntohl(x) ((uint32_t)(x)) +#define __ntohs(x) ((uint16_t)(x)) +#define __htonl(x) ((uint32_t)(x)) +#define __htons(x) ((uint16_t)(x)) +#else +#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)) +#endif /* __ARMEB__ */ + +static __inline uint64_t +__bswap64(uint64_t _x) +{ + + return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) | + ((_x >> 8) & 0xff000000) | ((_x << 8) & ((uint64_t)0xff << 32)) | + ((_x << 24) & ((uint64_t)0xff << 40)) | + ((_x << 40) & ((uint64_t)0xff << 48)) | ((_x << 56))); +} + +static __inline uint32_t +__bswap32_var(uint32_t v) +{ + uint32_t t1; + + __asm __volatile("eor %1, %0, %0, ror #16\n" + "bic %1, %1, #0x00ff0000\n" + "mov %0, %0, ror #8\n" + "eor %0, %0, %1, lsr #8\n" + : "+r" (v), "=r" (t1)); + + return (v); +} + +static __inline uint16_t +__bswap16_var(uint16_t v) +{ + uint32_t ret = v & 0xffff; + + __asm __volatile( + "mov %0, %0, ror #8\n" + "orr %0, %0, %0, lsr #16\n" + "bic %0, %0, %0, lsl #16" + : "+r" (ret)); + + 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(x) : \ + __bswap16_var(x))) + +#define __bswap32(x) \ + ((uint32_t)(__builtin_constant_p(x) ? \ + __bswap32_constant(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/arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h b/arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h new file mode 100644 index 0000000..11d2d35 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h @@ -0,0 +1,21 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef INTTYPES__H +#define INTTYPES__H + +#define PRId64 "lld" /* int64_t */ +#define PRIi64 "lli" /* int64_t */ +#define PRIo64 "llo" /* int64_t */ +#define PRIu64 "llu" /* uint64_t */ +#define PRIx64 "llx" /* uint64_t */ +#define PRIX64 "llX" /* uint64_t */ + +#endif /* INTTYPES__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/limits_.h b/arm-trusted-firmware/include/lib/libc/aarch32/limits_.h new file mode 100644 index 0000000..26cec17 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/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 0x7FFFFFFFL +#define LONG_MIN (-LONG_MAX - 1L) +#define ULONG_MAX 0xFFFFFFFFUL +#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL +#define LLONG_MIN (-LLONG_MAX - 1LL) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL + +#define __LONG_BIT 32 +#define __WORD_BIT 32 diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h b/arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h new file mode 100644 index 0000000..36dc20b --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/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 int size_t; +#define SIZET_ +#endif + +#endif /* STDDEF__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h b/arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h new file mode 100644 index 0000000..dafe142 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h @@ -0,0 +1,28 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDINT__H +#define STDINT__H + +#define INT64_MAX LLONG_MAX +#define INT64_MIN LLONG_MIN +#define UINT64_MAX ULLONG_MAX + +#define INT64_C(x) x ## LL +#define UINT64_C(x) x ## ULL + +typedef long long int64_t; +typedef unsigned long long uint64_t; +typedef long long int64_least_t; +typedef unsigned long long uint64_least_t; +typedef long long int64_fast_t; +typedef unsigned long long uint64_fast_t; + +#endif diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h b/arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h new file mode 100644 index 0000000..5e49425 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/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 int ssize_t; +#define SSIZET_ +#endif + +#endif /* STDIO__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/endian_.h b/arm-trusted-firmware/include/lib/libc/aarch64/endian_.h new file mode 100644 index 0000000..7c79fd4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h b/arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h new file mode 100644 index 0000000..197d627 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h @@ -0,0 +1,21 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef INTTYPES__H +#define INTTYPES__H + +#define PRId64 "ld" /* int64_t */ +#define PRIi64 "li" /* int64_t */ +#define PRIo64 "lo" /* int64_t */ +#define PRIu64 "lu" /* uint64_t */ +#define PRIx64 "lx" /* uint64_t */ +#define PRIX64 "lX" /* uint64_t */ + +#endif /* INTTYPES__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/limits_.h b/arm-trusted-firmware/include/lib/libc/aarch64/limits_.h new file mode 100644 index 0000000..e36cfe7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h b/arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h new file mode 100644 index 0000000..f880a17 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h b/arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h new file mode 100644 index 0000000..6ecc606 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h b/arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h new file mode 100644 index 0000000..56e9f1b --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h @@ -0,0 +1,31 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDINT__H +#define STDINT__H + +#define INT64_MAX LONG_MAX +#define INT64_MIN LONG_MIN +#define UINT64_MAX ULONG_MAX + +#define INT64_C(x) x ## L +#define UINT64_C(x) x ## UL + +typedef long int64_t; +typedef unsigned long uint64_t; +typedef long int64_least_t; +typedef unsigned long uint64_least_t; +typedef long int64_fast_t; +typedef unsigned long uint64_fast_t; + +typedef __int128 int128_t; +typedef unsigned __int128 uint128_t; + +#endif diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h b/arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h new file mode 100644 index 0000000..afaeadc --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/arm_acle.h b/arm-trusted-firmware/include/lib/libc/arm_acle.h new file mode 100644 index 0000000..eb08552 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/arm_acle.h @@ -0,0 +1,24 @@ +/* + * 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 __crc32b __builtin_arm_crc32b +# define __crc32w __builtin_arm_crc32w +#else +# define __crc32b __builtin_aarch64_crc32b +# define __crc32w __builtin_aarch64_crc32w +#endif + +#endif /* ARM_ACLE_H */ diff --git a/arm-trusted-firmware/include/lib/libc/assert.h b/arm-trusted-firmware/include/lib/libc/assert.h new file mode 100644 index 0000000..486bbc2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/cdefs.h b/arm-trusted-firmware/include/lib/libc/cdefs.h new file mode 100644 index 0000000..0d00722 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/endian.h b/arm-trusted-firmware/include/lib/libc/endian.h new file mode 100644 index 0000000..4100f57 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/errno.h b/arm-trusted-firmware/include/lib/libc/errno.h new file mode 100644 index 0000000..029912f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/inttypes.h b/arm-trusted-firmware/include/lib/libc/inttypes.h new file mode 100644 index 0000000..0f9e8c6 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/inttypes.h @@ -0,0 +1,47 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef INTTYPES_H +#define INTTYPES_H + +#include +#include + +#define PRId8 "d" /* int8_t */ +#define PRId16 "d" /* int16_t */ +#define PRId32 "d" /* int32_t */ +#define PRIdPTR "d" /* intptr_t */ + +#define PRIi8 "i" /* int8_t */ +#define PRIi16 "i" /* int16_t */ +#define PRIi32 "i" /* int32_t */ +#define PRIiPTR "i" /* intptr_t */ + +#define PRIo8 "o" /* int8_t */ +#define PRIo16 "o" /* int16_t */ +#define PRIo32 "o" /* int32_t */ +#define PRIoPTR "o" /* intptr_t */ + +#define PRIu8 "u" /* uint8_t */ +#define PRIu16 "u" /* uint16_t */ +#define PRIu32 "u" /* uint32_t */ +#define PRIuPTR "u" /* uintptr_t */ + +#define PRIx8 "x" /* uint8_t */ +#define PRIx16 "x" /* uint16_t */ +#define PRIx32 "x" /* uint32_t */ +#define PRIxPTR "x" /* uintptr_t */ + +#define PRIX8 "X" /* uint8_t */ +#define PRIX16 "X" /* uint16_t */ +#define PRIX32 "X" /* uint32_t */ +#define PRIXPTR "X" /* uintptr_t */ + +#endif diff --git a/arm-trusted-firmware/include/lib/libc/limits.h b/arm-trusted-firmware/include/lib/libc/limits.h new file mode 100644 index 0000000..41bb658 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/setjmp.h b/arm-trusted-firmware/include/lib/libc/setjmp.h new file mode 100644 index 0000000..be8e2c0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/stdarg.h b/arm-trusted-firmware/include/lib/libc/stdarg.h new file mode 100644 index 0000000..e260b9b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/stdbool.h b/arm-trusted-firmware/include/lib/libc/stdbool.h new file mode 100644 index 0000000..b58334c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/stddef.h b/arm-trusted-firmware/include/lib/libc/stddef.h new file mode 100644 index 0000000..58a519e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/stdint.h b/arm-trusted-firmware/include/lib/libc/stdint.h new file mode 100644 index 0000000..e96a25c --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/stdint.h @@ -0,0 +1,122 @@ +/* + * 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 +#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 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 UINT8_C(x) x +#define UINT16_C(x) x +#define UINT32_C(x) x ## U + +#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 unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +typedef signed char int8_least_t; +typedef short int16_least_t; +typedef int int32_least_t; + +typedef unsigned char uint8_least_t; +typedef unsigned short uint16_least_t; +typedef unsigned int uint32_least_t; + +typedef int int8_fast_t; +typedef int int16_fast_t; +typedef int int32_fast_t; + +typedef unsigned int uint8_fast_t; +typedef unsigned int uint16_fast_t; +typedef unsigned int uint32_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; + +#endif /* STDINT_H */ diff --git a/arm-trusted-firmware/include/lib/libc/stdio.h b/arm-trusted-firmware/include/lib/libc/stdio.h new file mode 100644 index 0000000..ba13683 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/stdlib.h b/arm-trusted-firmware/include/lib/libc/stdlib.h new file mode 100644 index 0000000..4641e56 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/string.h b/arm-trusted-firmware/include/lib/libc/string.h new file mode 100644 index 0000000..9894483 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libc/time.h b/arm-trusted-firmware/include/lib/libc/time.h new file mode 100644 index 0000000..c1c95e5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/libfdt/fdt.h b/arm-trusted-firmware/include/lib/libfdt/fdt.h new file mode 100644 index 0000000..eb9edb7 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libfdt/fdt.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef FDT_H +#define FDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + */ + +#ifndef __ASSEMBLER__ + +struct fdt_header { + fdt32_t magic; /* magic word FDT_MAGIC */ + fdt32_t totalsize; /* total size of DT block */ + fdt32_t off_dt_struct; /* offset to structure */ + fdt32_t off_dt_strings; /* offset to strings */ + fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ + fdt32_t version; /* format version */ + fdt32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + fdt32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + fdt32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + fdt32_t size_dt_struct; /* size of the structure block */ +}; + +struct fdt_reserve_entry { + fdt64_t address; + fdt64_t size; +}; + +struct fdt_node_header { + fdt32_t tag; + char name[0]; +}; + +struct fdt_property { + fdt32_t tag; + fdt32_t len; + fdt32_t nameoff; + char data[0]; +}; + +#endif /* !__ASSEMBLER__*/ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(fdt32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, + size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(fdt32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) + +#endif /* FDT_H */ diff --git a/arm-trusted-firmware/include/lib/libfdt/libfdt.h b/arm-trusted-firmware/include/lib/libfdt/libfdt.h new file mode 100644 index 0000000..544d3ef --- /dev/null +++ b/arm-trusted-firmware/include/lib/libfdt/libfdt.h @@ -0,0 +1,2080 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_H +#define LIBFDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define FDT_FIRST_SUPPORTED_VERSION 0x02 +#define FDT_LAST_SUPPORTED_VERSION 0x11 + +/* Error codes: informative error codes */ +#define FDT_ERR_NOTFOUND 1 + /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ +#define FDT_ERR_EXISTS 2 + /* FDT_ERR_EXISTS: Attempted to create a node or property which + * already exists */ +#define FDT_ERR_NOSPACE 3 + /* FDT_ERR_NOSPACE: Operation needed to expand the device + * tree, but its buffer did not have sufficient space to + * contain the expanded tree. Use fdt_open_into() to move the + * device tree to a buffer with more space. */ + +/* Error codes: codes for bad parameters */ +#define FDT_ERR_BADOFFSET 4 + /* FDT_ERR_BADOFFSET: Function was passed a structure block + * offset which is out-of-bounds, or which points to an + * unsuitable part of the structure for the operation. */ +#define FDT_ERR_BADPATH 5 + /* FDT_ERR_BADPATH: Function was passed a badly formatted path + * (e.g. missing a leading / for a function which requires an + * absolute path) */ +#define FDT_ERR_BADPHANDLE 6 + /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. + * This can be caused either by an invalid phandle property + * length, or the phandle value was either 0 or -1, which are + * not permitted. */ +#define FDT_ERR_BADSTATE 7 + /* FDT_ERR_BADSTATE: Function was passed an incomplete device + * tree created by the sequential-write functions, which is + * not sufficiently complete for the requested operation. */ + +/* Error codes: codes for bad device tree blobs */ +#define FDT_ERR_TRUNCATED 8 + /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly + * terminated (overflows, goes outside allowed bounds, or + * isn't properly terminated). */ +#define FDT_ERR_BADMAGIC 9 + /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a + * device tree at all - it is missing the flattened device + * tree magic number. */ +#define FDT_ERR_BADVERSION 10 + /* FDT_ERR_BADVERSION: Given device tree has a version which + * can't be handled by the requested operation. For + * read-write functions, this may mean that fdt_open_into() is + * required to convert the tree to the expected version. */ +#define FDT_ERR_BADSTRUCTURE 11 + /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt + * structure block or other serious error (e.g. misnested + * nodes, or subnodes preceding properties). */ +#define FDT_ERR_BADLAYOUT 12 + /* FDT_ERR_BADLAYOUT: For read-write functions, the given + * device tree has it's sub-blocks in an order that the + * function can't handle (memory reserve map, then structure, + * then strings). Use fdt_open_into() to reorganize the tree + * into a form suitable for the read-write operations. */ + +/* "Can't happen" error indicating a bug in libfdt */ +#define FDT_ERR_INTERNAL 13 + /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. + * Should never be returned, if it is, it indicates a bug in + * libfdt itself. */ + +/* Errors in device tree content */ +#define FDT_ERR_BADNCELLS 14 + /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells + * or similar property with a bad format or value */ + +#define FDT_ERR_BADVALUE 15 + /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected + * value. For example: a property expected to contain a string list + * is not NUL-terminated within the length of its value. */ + +#define FDT_ERR_BADOVERLAY 16 + /* FDT_ERR_BADOVERLAY: The device tree overlay, while + * correctly structured, cannot be applied due to some + * unexpected or missing value, property or node. */ + +#define FDT_ERR_NOPHANDLES 17 + /* FDT_ERR_NOPHANDLES: The device tree doesn't have any + * phandle available anymore without causing an overflow */ + +#define FDT_ERR_BADFLAGS 18 + /* FDT_ERR_BADFLAGS: The function was passed a flags field that + * contains invalid flags or an invalid combination of flags. */ + +#define FDT_ERR_MAX 18 + +/* constants */ +#define FDT_MAX_PHANDLE 0xfffffffe + /* Valid values for phandles range from 1 to 2^32-2. */ + +/**********************************************************************/ +/* Low-level functions (you probably don't need these) */ +/**********************************************************************/ + +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); +#endif +static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) +{ + return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); +} + +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); + +/* + * Alignment helpers: + * These helpers access words from a device tree blob. They're + * built to work even with unaligned pointers on platforms (ike + * ARM) that don't like unaligned loads and stores + */ + +static inline uint32_t fdt32_ld(const fdt32_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; +} + +static inline void fdt32_st(void *property, uint32_t value) +{ + uint8_t *bp = (uint8_t *)property; + + bp[0] = value >> 24; + bp[1] = (value >> 16) & 0xff; + bp[2] = (value >> 8) & 0xff; + bp[3] = value & 0xff; +} + +static inline uint64_t fdt64_ld(const fdt64_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint64_t)bp[0] << 56) + | ((uint64_t)bp[1] << 48) + | ((uint64_t)bp[2] << 40) + | ((uint64_t)bp[3] << 32) + | ((uint64_t)bp[4] << 24) + | ((uint64_t)bp[5] << 16) + | ((uint64_t)bp[6] << 8) + | bp[7]; +} + +static inline void fdt64_st(void *property, uint64_t value) +{ + uint8_t *bp = (uint8_t *)property; + + bp[0] = value >> 56; + bp[1] = (value >> 48) & 0xff; + bp[2] = (value >> 40) & 0xff; + bp[3] = (value >> 32) & 0xff; + bp[4] = (value >> 24) & 0xff; + bp[5] = (value >> 16) & 0xff; + bp[6] = (value >> 8) & 0xff; + bp[7] = value & 0xff; +} + +/**********************************************************************/ +/* Traversal functions */ +/**********************************************************************/ + +int fdt_next_node(const void *fdt, int offset, int *depth); + +/** + * fdt_first_subnode() - get offset of first direct subnode + * + * @fdt: FDT blob + * @offset: Offset of node to check + * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none + */ +int fdt_first_subnode(const void *fdt, int offset); + +/** + * fdt_next_subnode() - get offset of next direct subnode + * + * After first calling fdt_first_subnode(), call this function repeatedly to + * get direct subnodes of a parent node. + * + * @fdt: FDT blob + * @offset: Offset of previous subnode + * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more + * subnodes + */ +int fdt_next_subnode(const void *fdt, int offset); + +/** + * fdt_for_each_subnode - iterate over all subnodes of a parent + * + * @node: child node (int, lvalue) + * @fdt: FDT blob (const void *) + * @parent: parent node (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_subnode(node, fdt, parent) { + * Use node + * ... + * } + * + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and @node is used as + * iterator in the loop. The parent variable be constant or even a + * literal. + * + */ +#define fdt_for_each_subnode(node, fdt, parent) \ + for (node = fdt_first_subnode(fdt, parent); \ + node >= 0; \ + node = fdt_next_subnode(fdt, node)) + +/**********************************************************************/ +/* General functions */ +/**********************************************************************/ +#define fdt_get_header(fdt, field) \ + (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) + +#define fdt_set_hdr_(name) \ + static inline void fdt_set_##name(void *fdt, uint32_t val) \ + { \ + struct fdt_header *fdth = (struct fdt_header *)fdt; \ + fdth->name = cpu_to_fdt32(val); \ + } +fdt_set_hdr_(magic); +fdt_set_hdr_(totalsize); +fdt_set_hdr_(off_dt_struct); +fdt_set_hdr_(off_dt_strings); +fdt_set_hdr_(off_mem_rsvmap); +fdt_set_hdr_(version); +fdt_set_hdr_(last_comp_version); +fdt_set_hdr_(boot_cpuid_phys); +fdt_set_hdr_(size_dt_strings); +fdt_set_hdr_(size_dt_struct); +#undef fdt_set_hdr_ + +/** + * fdt_header_size - return the size of the tree's header + * @fdt: pointer to a flattened device tree + */ +size_t fdt_header_size(const void *fdt); + +/** + * fdt_header_size_ - internal function which takes a version number + */ +size_t fdt_header_size_(uint32_t version); + +/** + * fdt_check_header - sanity check a device tree header + + * @fdt: pointer to data which might be a flattened device tree + * + * fdt_check_header() checks that the given buffer contains what + * appears to be a flattened device tree, and that the header contains + * valid information (to the extent that can be determined from the + * header alone). + * + * returns: + * 0, if the buffer appears to contain a valid device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings, as above + */ +int fdt_check_header(const void *fdt); + +/** + * fdt_move - move a device tree around in memory + * @fdt: pointer to the device tree to move + * @buf: pointer to memory where the device is to be moved + * @bufsize: size of the memory space at buf + * + * fdt_move() relocates, if possible, the device tree blob located at + * fdt to the buffer at buf of size bufsize. The buffer may overlap + * with the existing device tree blob at fdt. Therefore, + * fdt_move(fdt, fdt, fdt_totalsize(fdt)) + * should always succeed. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_move(const void *fdt, void *buf, int bufsize); + +/**********************************************************************/ +/* Read-only functions */ +/**********************************************************************/ + +int fdt_check_full(const void *fdt, size_t bufsize); + +/** + * fdt_get_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * @lenp: optional pointer to return the string's length + * + * fdt_get_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt, and optionally also + * returns the string's length in *lenp. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds, or doesn't point to a valid string + */ +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); + +/** + * fdt_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * + * fdt_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds, or doesn't point to a valid string + */ +const char *fdt_string(const void *fdt, int stroffset); + +/** + * fdt_find_max_phandle - find and return the highest phandle in a tree + * @fdt: pointer to the device tree blob + * @phandle: return location for the highest phandle value found in the tree + * + * fdt_find_max_phandle() finds the highest phandle value in the given device + * tree. The value returned in @phandle is only valid if the function returns + * success. + * + * returns: + * 0 on success or a negative error code on failure + */ +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); + +/** + * fdt_get_max_phandle - retrieves the highest phandle in a tree + * @fdt: pointer to the device tree blob + * + * fdt_get_max_phandle retrieves the highest phandle in the given + * device tree. This will ignore badly formatted phandles, or phandles + * with a value of 0 or -1. + * + * This function is deprecated in favour of fdt_find_max_phandle(). + * + * returns: + * the highest phandle on success + * 0, if no phandle was found in the device tree + * -1, if an error occurred + */ +static inline uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t phandle; + int err; + + err = fdt_find_max_phandle(fdt, &phandle); + if (err < 0) + return (uint32_t)-1; + + return phandle; +} + +/** + * fdt_generate_phandle - return a new, unused phandle for a device tree blob + * @fdt: pointer to the device tree blob + * @phandle: return location for the new phandle + * + * Walks the device tree blob and looks for the highest phandle value. On + * success, the new, unused phandle value (one higher than the previously + * highest phandle value in the device tree blob) will be returned in the + * @phandle parameter. + * + * Returns: + * 0 on success or a negative error-code on failure + */ +int fdt_generate_phandle(const void *fdt, uint32_t *phandle); + +/** + * fdt_num_mem_rsv - retrieve the number of memory reserve map entries + * @fdt: pointer to the device tree blob + * + * Returns the number of entries in the device tree blob's memory + * reservation map. This does not include the terminating 0,0 entry + * or any other (0,0) entries reserved for expansion. + * + * returns: + * the number of entries + */ +int fdt_num_mem_rsv(const void *fdt); + +/** + * fdt_get_mem_rsv - retrieve one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: pointers to 64-bit variables + * + * On success, *address and *size will contain the address and size of + * the n-th reserve map entry from the device tree blob, in + * native-endian format. + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); + +/** + * fdt_subnode_offset_namelen - find a subnode based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_subnode_offset(), but only examine the first + * namelen characters of name for matching the subnode name. This is + * useful for finding subnodes based on a portion of a larger string, + * such as a full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, + const char *name, int namelen); +#endif +/** + * fdt_subnode_offset - find a subnode of a given node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_subnode_offset() finds a subnode of the node at structure block + * offset parentoffset with the given name. name may include a unit + * address, in which case fdt_subnode_offset() will find the subnode + * with that unit address, or the unit address may be omitted, in + * which case fdt_subnode_offset() will find an arbitrary subnode + * whose name excluding unit address matches the given name. + * + * returns: + * structure block offset of the requested subnode (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); + +/** + * fdt_path_offset_namelen - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * @namelen: number of characters of path to consider + * + * Identical to fdt_path_offset(), but only consider the first namelen + * characters of path as the path name. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); +#endif + +/** + * fdt_path_offset - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * + * fdt_path_offset() finds a node of a given path in the device tree. + * Each path component may omit the unit address portion, but the + * results of this are undefined if any such path component is + * ambiguous (that is if there are multiple nodes at the relevant + * level matching the given component, differentiated only by unit + * address). + * + * returns: + * structure block offset of the node with the requested path (>=0), on + * success + * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid + * -FDT_ERR_NOTFOUND, if the requested node does not exist + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_path_offset(const void *fdt, const char *path); + +/** + * fdt_get_name - retrieve the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the starting node + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_name() retrieves the name (including unit address) of the + * device tree node at structure block offset nodeoffset. If lenp is + * non-NULL, the length of this name is also returned, in the integer + * pointed to by lenp. + * + * returns: + * pointer to the node's name, on success + * If lenp is non-NULL, *lenp contains the length of that name + * (>=0) + * NULL, on error + * if lenp is non-NULL *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); + +/** + * fdt_first_property_offset - find the offset of a node's first property + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * + * fdt_first_property_offset() finds the first property of the node at + * the given structure block offset. + * + * returns: + * structure block offset of the property (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested node has no properties + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_first_property_offset(const void *fdt, int nodeoffset); + +/** + * fdt_next_property_offset - step through a node's properties + * @fdt: pointer to the device tree blob + * @offset: structure block offset of a property + * + * fdt_next_property_offset() finds the property immediately after the + * one at the given structure block offset. This will be a property + * of the same node as the given property. + * + * returns: + * structure block offset of the next property (>=0), on success + * -FDT_ERR_NOTFOUND, if the given property is the last in its node + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_next_property_offset(const void *fdt, int offset); + +/** + * fdt_for_each_property_offset - iterate over all properties of a node + * + * @property_offset: property offset (int, lvalue) + * @fdt: FDT blob (const void *) + * @node: node offset (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_property_offset(property, fdt, node) { + * Use property + * ... + * } + * + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and property is used as + * iterator in the loop. The node variable can be constant or even a + * literal. + */ +#define fdt_for_each_property_offset(property, fdt, node) \ + for (property = fdt_first_property_offset(fdt, node); \ + property >= 0; \ + property = fdt_next_property_offset(fdt, property)) + +/** + * fdt_get_property_by_offset - retrieve the property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to retrieve + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property_by_offset() retrieves a pointer to the + * fdt_property structure within the device tree blob at the given + * offset. If lenp is non-NULL, the length of the property value is + * also returned, in the integer pointed to by lenp. + * + * Note that this code only works on device tree versions >= 16. fdt_getprop() + * works on all versions. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp); + +/** + * fdt_get_property_namelen - find a property based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_get_property(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int nodeoffset, + const char *name, + int namelen, int *lenp); +#endif + +/** + * fdt_get_property - find a given property in a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property() retrieves a pointer to the fdt_property + * structure within the device tree blob corresponding to the property + * named 'name' of the node at offset nodeoffset. If lenp is + * non-NULL, the length of the property value is also returned, in the + * integer pointed to by lenp. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, + const char *name, + int *lenp) +{ + return (struct fdt_property *)(uintptr_t) + fdt_get_property(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_getprop_by_offset - retrieve the value of a property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to read + * @namep: pointer to a string variable (will be overwritten) or NULL + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop_by_offset() retrieves a pointer to the value of the + * property at structure block offset 'offset' (this will be a pointer + * to within the device blob itself, not a copy of the value). If + * lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. If namep is non-NULL, + * the property's namne will also be returned in the char * pointed to + * by namep (this will be a pointer to within the device tree's string + * block, not a new copy of the name). + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * if namep is non-NULL *namep contiains a pointer to the property + * name. + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp); +#endif + +/** + * fdt_getprop_namelen - get property value based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_getprop(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp); +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, + const char *name, int namelen, + int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, + namelen, lenp); +} +#endif + +/** + * fdt_getprop - retrieve the value of a given property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop() retrieves a pointer to the value of the property + * named 'name' of the node at offset nodeoffset (this will be a + * pointer to within the device blob itself, not a copy of the value). + * If lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline void *fdt_getprop_w(void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_get_phandle - retrieve the phandle of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the node + * + * fdt_get_phandle() retrieves the phandle of the device tree node at + * structure block offset nodeoffset. + * + * returns: + * the phandle of the node at nodeoffset, on success (!= 0, != -1) + * 0, if the node has no phandle, or another error occurs + */ +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); + +/** + * fdt_get_alias_namelen - get alias based on substring + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_alias(), but only examine the first namelen + * characters of name for matching the alias name. + */ +#ifndef SWIG /* Not available in Python */ +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen); +#endif + +/** + * fdt_get_alias - retrieve the path referenced by a given alias + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * + * fdt_get_alias() retrieves the value of a given alias. That is, the + * value of the property named 'name' in the node /aliases. + * + * returns: + * a pointer to the expansion of the alias named 'name', if it exists + * NULL, if the given alias or the /aliases node does not exist + */ +const char *fdt_get_alias(const void *fdt, const char *name); + +/** + * fdt_get_path - determine the full path of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose path to find + * @buf: character buffer to contain the returned path (will be overwritten) + * @buflen: size of the character buffer at buf + * + * fdt_get_path() computes the full path of the node at offset + * nodeoffset, and records that path in the buffer at buf. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * 0, on success + * buf contains the absolute path of the node at + * nodeoffset, as a NUL-terminated string. + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) + * characters and will not fit in the given buffer. + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); + +/** + * fdt_supernode_atdepth_offset - find a specific ancestor of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * @supernodedepth: depth of the ancestor to find + * @nodedepth: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_supernode_atdepth_offset() finds an ancestor of the given node + * at a specific depth from the root (where the root itself has depth + * 0, its immediate subnodes depth 1 and so forth). So + * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); + * will always return 0, the offset of the root node. If the node at + * nodeoffset has depth D, then: + * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); + * will return nodeoffset itself. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * structure block offset of the node at node offset's ancestor + * of depth supernodedepth (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of + * nodeoffset + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth); + +/** + * fdt_node_depth - find the depth of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_node_depth() finds the depth of a given node. The root node + * has depth 0, its immediate subnodes depth 1 and so forth. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * depth of the node at nodeoffset (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_depth(const void *fdt, int nodeoffset); + +/** + * fdt_parent_offset - find the parent of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_parent_offset() locates the parent node of a given node (that + * is, it finds the offset of the node which contains the node at + * nodeoffset as a subnode). + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset, *twice*. + * + * returns: + * structure block offset of the parent of the node at nodeoffset + * (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_parent_offset(const void *fdt, int nodeoffset); + +/** + * fdt_node_offset_by_prop_value - find nodes with a given property value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @propname: property name to check + * @propval: property value to search for + * @proplen: length of the value in propval + * + * fdt_node_offset_by_prop_value() returns the offset of the first + * node after startoffset, which has a property named propname whose + * value is of length proplen and has value equal to propval; or if + * startoffset is -1, the very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, + * propval, proplen); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, + * propval, proplen); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen); + +/** + * fdt_node_offset_by_phandle - find the node with a given phandle + * @fdt: pointer to the device tree blob + * @phandle: phandle value + * + * fdt_node_offset_by_phandle() returns the offset of the node + * which has the given phandle value. If there is more than one node + * in the tree with the given phandle (an invalid tree), results are + * undefined. + * + * returns: + * structure block offset of the located node (>= 0), on success + * -FDT_ERR_NOTFOUND, no node with that phandle exists + * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); + +/** + * fdt_node_check_compatible: check a node's compatible property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @compatible: string to match against + * + * + * fdt_node_check_compatible() returns 0 if the given node contains a + * 'compatible' property with the given string as one of its elements, + * it returns non-zero otherwise, or on error. + * + * returns: + * 0, if the node has a 'compatible' property listing the given string + * 1, if the node has a 'compatible' property, but it does not list + * the given string + * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property + * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible); + +/** + * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @compatible: 'compatible' string to match against + * + * fdt_node_offset_by_compatible() returns the offset of the first + * node after startoffset, which has a 'compatible' property which + * lists the given compatible string; or if startoffset is -1, the + * very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible); + +/** + * fdt_stringlist_contains - check a string list property for a string + * @strlist: Property containing a list of strings to check + * @listlen: Length of property + * @str: String to search for + * + * This is a utility function provided for convenience. The list contains + * one or more strings, each terminated by \0, as is found in a device tree + * "compatible" property. + * + * @return: 1 if the string is found in the list, 0 not found, or invalid list + */ +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); + +/** + * fdt_stringlist_count - count the number of strings in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @return: + * the number of strings in the given property + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); + +/** + * fdt_stringlist_search - find a string in a string list and return its index + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @string: string to look up in the string list + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @return: + * the index of the string in the list of strings + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist or does not contain + * the given string + */ +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string); + +/** + * fdt_stringlist_get() - obtain the string at a given index in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @index: index of the string to return + * @lenp: return location for the string length or an error code on failure + * + * Note that this will successfully extract strings from properties with + * non-NUL-terminated values. For example on small-valued cell properties + * this function will return the empty string. + * + * If non-NULL, the length of the string (on success) or a negative error-code + * (on failure) will be stored in the integer pointer to by lenp. + * + * @return: + * A pointer to the string at the given index in the string list or NULL on + * failure. On success the length of the string will be stored in the memory + * location pointed to by the lenp parameter, if non-NULL. On failure one of + * the following negative error codes will be returned in the lenp parameter + * (if non-NULL): + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int index, + int *lenp); + +/**********************************************************************/ +/* Read-only functions (addressing related) */ +/**********************************************************************/ + +/** + * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells + * + * This is the maximum value for #address-cells, #size-cells and + * similar properties that will be processed by libfdt. IEE1275 + * requires that OF implementations handle values up to 4. + * Implementations may support larger values, but in practice higher + * values aren't used. + */ +#define FDT_MAX_NCELLS 4 + +/** + * fdt_address_cells - retrieve address size for a bus represented in the tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address size for + * + * When the node has a valid #address-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_address_cells(const void *fdt, int nodeoffset); + +/** + * fdt_size_cells - retrieve address range size for a bus represented in the + * tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address range size for + * + * When the node has a valid #size-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 1, if the node has no #size-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #size-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_size_cells(const void *fdt, int nodeoffset); + + +/**********************************************************************/ +/* Write-in-place functions */ +/**********************************************************************/ + +/** + * fdt_setprop_inplace_namelen_partial - change a property's value, + * but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @namelen: number of characters of name to consider + * @idx: index of the property to change in the array + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * Identical to fdt_setprop_inplace(), but modifies the given property + * starting from the given index, and using only the first characters + * of the name. It is useful when you want to manipulate only one value of + * an array and you have a string that doesn't end with \0. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len); +#endif + +/** + * fdt_setprop_inplace - change a property's value, but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * fdt_setprop_inplace() replaces the value of a given property with + * the data in val, of length len. This function cannot change the + * size of a property, and so will only work if len is equal to the + * current length of the property. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if len is not equal to the property's current length + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len); +#endif + +/** + * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to replace the property with + * + * fdt_setprop_inplace_u32() replaces the value of a given property + * with the 32-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 4. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to replace the property with + * + * fdt_setprop_inplace_u64() replaces the value of a given property + * with the 64-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 8. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell property + * + * This is an alternative name for fdt_setprop_inplace_u32() + */ +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_nop_property - replace a property with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_nop_property() will replace a given property's representation + * in the blob with FDT_NOP tags, effectively removing it from the + * tree. + * + * This function will alter only the bytes in the blob which contain + * the property, and will not alter or move any other part of the + * tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_property(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_nop_node - replace a node (subtree) with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_nop_node() will replace a given node's representation in the + * blob, including all its subnodes, if any, with FDT_NOP tags, + * effectively removing it from the tree. + * + * This function will alter only the bytes in the blob which contain + * the node and its properties and subnodes, and will not alter or + * move any other part of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_node(void *fdt, int nodeoffset); + +/**********************************************************************/ +/* Sequential write functions */ +/**********************************************************************/ + +/* fdt_create_with_flags flags */ +#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1 + /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property + * names in the fdt. This can result in faster creation times, but + * a larger fdt. */ + +#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP) + +/** + * fdt_create_with_flags - begin creation of a new fdt + * @fdt: pointer to memory allocated where fdt will be created + * @bufsize: size of the memory space at fdt + * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0. + * + * fdt_create_with_flags() begins the process of creating a new fdt with + * the sequential write interface. + * + * fdt creation process must end with fdt_finished() to produce a valid fdt. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + * -FDT_ERR_BADFLAGS, flags is not valid + */ +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); + +/** + * fdt_create - begin creation of a new fdt + * @fdt: pointer to memory allocated where fdt will be created + * @bufsize: size of the memory space at fdt + * + * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + */ +int fdt_create(void *buf, int bufsize); + +int fdt_resize(void *fdt, void *buf, int bufsize); +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); +int fdt_finish_reservemap(void *fdt); +int fdt_begin_node(void *fdt, const char *name); +int fdt_property(void *fdt, const char *name, const void *val, int len); +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} +static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} + +#ifndef SWIG /* Not available in Python */ +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ + return fdt_property_u32(fdt, name, val); +} +#endif + +/** + * fdt_property_placeholder - add a new property and return a ptr to its value + * + * @fdt: pointer to the device tree blob + * @name: name of property to add + * @len: length of property value in bytes + * @valp: returns a pointer to where where the value should be placed + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_NOSPACE, standard meanings + */ +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); + +#define fdt_property_string(fdt, name, str) \ + fdt_property(fdt, name, str, strlen(str)+1) +int fdt_end_node(void *fdt); +int fdt_finish(void *fdt); + +/**********************************************************************/ +/* Read-write functions */ +/**********************************************************************/ + +int fdt_create_empty_tree(void *buf, int bufsize); +int fdt_open_into(const void *fdt, void *buf, int bufsize); +int fdt_pack(void *fdt); + +/** + * fdt_add_mem_rsv - add one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: 64-bit values (native endian) + * + * Adds a reserve map entry to the given blob reserving a region at + * address address of length size. + * + * This function will insert data into the reserve map and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new reservation entry + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); + +/** + * fdt_del_mem_rsv - remove a memory reserve map entry + * @fdt: pointer to the device tree blob + * @n: entry to remove + * + * fdt_del_mem_rsv() removes the n-th memory reserve map entry from + * the blob. + * + * This function will delete data from the reservation table and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there + * are less than n+1 reserve map entries) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_mem_rsv(void *fdt, int n); + +/** + * fdt_set_name - change the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * @name: name to give the node + * + * fdt_set_name() replaces the name (including unit address, if any) + * of the given node with the given string. NOTE: this function can't + * efficiently check if the new name is unique amongst the given + * node's siblings; results are undefined if this function is invoked + * with a name equal to one of the given node's siblings. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob + * to contain the new name + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_set_name(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_setprop - create or change a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to set the property value to + * @len: length of the property value + * + * fdt_setprop() sets the value of the named property in the given + * node to the given value and length, creating the property if it + * does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_setprop_placeholder - allocate space for a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @len: length of the property value + * @prop_data: return pointer to property data + * + * fdt_setprop_placeholer() allocates the named property in the given node. + * If the property exists it is resized. In either case a pointer to the + * property data is returned. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data); + +/** + * fdt_setprop_u32 - set a property to a 32-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value for the property (native endian) + * + * fdt_setprop_u32() sets the value of the named property in the given + * node to the given 32-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_u64 - set a property to a 64-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value for the property (native endian) + * + * fdt_setprop_u64() sets the value of the named property in the given + * node to the given 64-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, + uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_cell - set a property to a single cell value + * + * This is an alternative name for fdt_setprop_u32() + */ +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + return fdt_setprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_setprop_string - set a property to a string value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value for the property + * + * fdt_setprop_string() sets the value of the named property in the + * given node to the given string value (using the length of the + * string to determine the new length of the property), or creates a + * new property with that value if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_string(fdt, nodeoffset, name, str) \ + fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + + +/** + * fdt_setprop_empty - set a property to an empty value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * + * fdt_setprop_empty() sets the value of the named property in the + * given node to an empty (zero length) value, or creates a new empty + * property if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_empty(fdt, nodeoffset, name) \ + fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) + +/** + * fdt_appendprop - append to or create a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to append to + * @val: pointer to data to append to the property value + * @len: length of the data to append to the property value + * + * fdt_appendprop() appends the value to the named property in the + * given node, creating the property if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_appendprop_u32 - append a 32-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u32() appends the given 32-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_u64 - append a 64-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u64() appends the given 64-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_cell - append a single cell value to a property + * + * This is an alternative name for fdt_appendprop_u32() + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_appendprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_appendprop_string - append a string to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value to append to the property + * + * fdt_appendprop_string() appends the given string to the value of + * the named property in the given node, or creates a new property + * with that value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ + fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/** + * fdt_appendprop_addrrange - append a address range property + * @fdt: pointer to the device tree blob + * @parent: offset of the parent node + * @nodeoffset: offset of the node to add a property at + * @name: name of property + * @addr: start address of a given range + * @size: size of a given range + * + * fdt_appendprop_addrrange() appends an address range value (start + * address and size) to the value of the named property in the given + * node, or creates a new property with that value if it does not + * already exist. + * If "name" is not specified, a default "reg" is used. + * Cell sizes are determined by parent's #address-cells and #size-cells. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain a new property + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size); + +/** + * fdt_delprop - delete a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_del_property() will delete the given property. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_delprop(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_add_subnode_namelen - creates a new node based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_add_subnode(), but use only the first namelen + * characters of name as the name of the new node. This is useful for + * creating subnodes based on a portion of a larger string, such as a + * full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen); +#endif + +/** + * fdt_add_subnode - creates a new node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_add_subnode() creates a new node as a subnode of the node at + * structure block offset parentoffset, with the given name (which + * should include the unit address, if any). + * + * This function will insert data into the blob, and will therefore + * change the offsets of some existing nodes. + + * returns: + * structure block offset of the created nodeequested subnode (>=0), on + * success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of + * the given name + * -FDT_ERR_NOSPACE, if there is insufficient free space in the + * blob to contain the new node + * -FDT_ERR_NOSPACE + * -FDT_ERR_BADLAYOUT + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_add_subnode(void *fdt, int parentoffset, const char *name); + +/** + * fdt_del_node - delete a node (subtree) + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_del_node() will remove the given node, including all its + * subnodes if any, from the blob. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_node(void *fdt, int nodeoffset); + +/** + * fdt_overlay_apply - Applies a DT overlay on a base DT + * @fdt: pointer to the base device tree blob + * @fdto: pointer to the device tree overlay blob + * + * fdt_overlay_apply() will apply the given device tree overlay on the + * given base device tree. + * + * Expect the base device tree to be modified, even if the function + * returns an error. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there's not enough space in the base device tree + * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or + * properties in the base DT + * -FDT_ERR_BADPHANDLE, + * -FDT_ERR_BADOVERLAY, + * -FDT_ERR_NOPHANDLES, + * -FDT_ERR_INTERNAL, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADOFFSET, + * -FDT_ERR_BADPATH, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_overlay_apply(void *fdt, void *fdto); + +/**********************************************************************/ +/* Debugging / informational functions */ +/**********************************************************************/ + +const char *fdt_strerror(int errval); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBFDT_H */ diff --git a/arm-trusted-firmware/include/lib/libfdt/libfdt_env.h b/arm-trusted-firmware/include/lib/libfdt/libfdt_env.h new file mode 100644 index 0000000..73b6d40 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libfdt/libfdt_env.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_ENV_H +#define LIBFDT_ENV_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef __CHECKER__ +#define FDT_FORCE __attribute__((force)) +#define FDT_BITWISE __attribute__((bitwise)) +#else +#define FDT_FORCE +#define FDT_BITWISE +#endif + +typedef uint16_t FDT_BITWISE fdt16_t; +typedef uint32_t FDT_BITWISE fdt32_t; +typedef uint64_t FDT_BITWISE fdt64_t; + +#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) +#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) +#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ + (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) +#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ + (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ + (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ + (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) + +static inline uint16_t fdt16_to_cpu(fdt16_t x) +{ + return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); +} +static inline fdt16_t cpu_to_fdt16(uint16_t x) +{ + return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); +} + +static inline uint32_t fdt32_to_cpu(fdt32_t x) +{ + return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); +} +static inline fdt32_t cpu_to_fdt32(uint32_t x) +{ + return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); +} + +static inline uint64_t fdt64_to_cpu(fdt64_t x) +{ + return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); +} +static inline fdt64_t cpu_to_fdt64(uint64_t x) +{ + return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); +} +#undef CPU_TO_FDT64 +#undef CPU_TO_FDT32 +#undef CPU_TO_FDT16 +#undef EXTRACT_BYTE + +#ifdef __APPLE__ +#include + +/* strnlen() is not available on Mac OS < 10.7 */ +# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ + MAC_OS_X_VERSION_10_7) + +#define strnlen fdt_strnlen + +/* + * fdt_strnlen: returns the length of a string or max_count - which ever is + * smallest. + * Input 1 string: the string whose size is to be determined + * Input 2 max_count: the maximum value returned by this function + * Output: length of the string or max_count (the smallest of the two) + */ +static inline size_t fdt_strnlen(const char *string, size_t max_count) +{ + const char *p = memchr(string, 0, max_count); + return p ? p - string : max_count; +} + +#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < + MAC_OS_X_VERSION_10_7) */ + +#endif /* __APPLE__ */ + +#endif /* LIBFDT_ENV_H */ diff --git a/arm-trusted-firmware/include/lib/mmio.h b/arm-trusted-firmware/include/lib/mmio.h new file mode 100644 index 0000000..3242a7c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/mpmm/mpmm.h b/arm-trusted-firmware/include/lib/mpmm/mpmm.h new file mode 100644 index 0000000..955c530 --- /dev/null +++ b/arm-trusted-firmware/include/lib/mpmm/mpmm.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MPMM_H +#define MPMM_H + +#include + +#include + +/* + * Enable the Maximum Power Mitigation Mechanism. + * + * This function will enable MPMM for the current core. The AMU counters + * representing the MPMM gears must have been configured and enabled prior to + * calling this function. + */ +void mpmm_enable(void); + +/* + * MPMM core data. + * + * This structure represents per-core data retrieved from the hardware + * configuration device tree. + */ +struct mpmm_core { + /* + * Whether MPMM is supported. + * + * Cores with support for MPMM offer one or more auxiliary AMU counters + * representing MPMM gears. + */ + bool supported; +}; + +/* + * MPMM topology. + * + * This topology structure describes the system-wide representation of the + * information retrieved from the hardware configuration device tree. + */ +struct mpmm_topology { + struct mpmm_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */ +}; + +#if !ENABLE_MPMM_FCONF +/* + * Retrieve the platform's MPMM topology. A `NULL` return value is treated as a + * non-fatal error, in which case MPMM will not be enabled for any core. + */ +const struct mpmm_topology *plat_mpmm_topology(void); +#endif /* ENABLE_MPMM_FCONF */ + +#endif /* MPMM_H */ diff --git a/arm-trusted-firmware/include/lib/object_pool.h b/arm-trusted-firmware/include/lib/object_pool.h new file mode 100644 index 0000000..66e8c47 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/optee_utils.h b/arm-trusted-firmware/include/lib/optee_utils.h new file mode 100644 index 0000000..06378eb --- /dev/null +++ b/arm-trusted-firmware/include/lib/optee_utils.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OPTEE_UTILS_H +#define OPTEE_UTILS_H + +#include + +#include + +bool optee_header_is_valid(uintptr_t header_base); + +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/arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S b/arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S new file mode 100644 index 0000000..1dbb408 --- /dev/null +++ b/arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMF_ASM_MACROS_S +#define PMF_ASM_MACROS_S + +#define PMF_TS_SIZE 8 + + /* + * This macro calculates the address of the per-cpu timestamp + * for the given service name and local timestamp id. + * Clobbers: r0 - r4 + */ + .macro pmf_calc_timestamp_addr _name, _tid + mov r4, lr + bl plat_my_core_pos + mov lr, r4 + ldr r1, =__PERCPU_TIMESTAMP_SIZE__ + mov r2, #(\_tid * PMF_TS_SIZE) + mla r0, r0, r1, r2 + ldr r1, =pmf_ts_mem_\_name + add r0, r0, r1 + .endm + +#endif /* PMF_ASM_MACROS_S */ diff --git a/arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S b/arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S new file mode 100644 index 0000000..5f3e6b7 --- /dev/null +++ b/arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMF_ASM_MACROS_S +#define PMF_ASM_MACROS_S + +#define PMF_TS_SIZE 8 + + /* + * This macro calculates the address of the per-cpu timestamp + * for the given service name and local timestamp id. + * Clobbers: x0 - x9 + */ + .macro pmf_calc_timestamp_addr _name, _tid + mov x9, x30 + bl plat_my_core_pos + mov x30, x9 + adr x2, __PMF_PERCPU_TIMESTAMP_END__ + adr x1, __PMF_TIMESTAMP_START__ + sub x1, x2, x1 + mov x2, #(\_tid * PMF_TS_SIZE) + madd x0, x0, x1, x2 + adr x1, pmf_ts_mem_\_name + add x0, x0, x1 + .endm + +#endif /* PMF_ASM_MACROS_S */ diff --git a/arm-trusted-firmware/include/lib/pmf/pmf.h b/arm-trusted-firmware/include/lib/pmf/pmf.h new file mode 100644 index 0000000..fa990d2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/pmf/pmf.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMF_H +#define PMF_H + +#include +#include +#include + +/* + * Constants used for/by PMF services. + */ +#define PMF_ARM_TIF_IMPL_ID UL(0x41) +#define PMF_TID_SHIFT 0 +#define PMF_TID_MASK (UL(0xFF) << PMF_TID_SHIFT) +#define PMF_SVC_ID_SHIFT 10 +#define PMF_SVC_ID_MASK (UL(0x3F) << PMF_SVC_ID_SHIFT) +#define PMF_IMPL_ID_SHIFT 24 +#define PMF_IMPL_ID_MASK (UL(0xFF) << PMF_IMPL_ID_SHIFT) + +/* + * Flags passed to PMF_REGISTER_SERVICE + */ +#define PMF_STORE_ENABLE (1 << 0) +#define PMF_DUMP_ENABLE (1 << 1) + +/* + * Flags passed to PMF_GET_TIMESTAMP_XXX + * and PMF_CAPTURE_TIMESTAMP + */ +#define PMF_CACHE_MAINT (U(1) << 0) +#define PMF_NO_CACHE_MAINT U(0) + +/* + * Defines for PMF SMC function ids. + */ +#define PMF_SMC_GET_TIMESTAMP_32 U(0x82000010) +#define PMF_SMC_GET_TIMESTAMP_64 U(0xC2000010) +#define PMF_NUM_SMC_CALLS 2 + +/* + * The macros below are used to identify + * PMF calls from the SMC function ID. + */ +#define PMF_FID_MASK U(0xffe0) +#define PMF_FID_VALUE U(0) +#define is_pmf_fid(_fid) (((_fid) & PMF_FID_MASK) == PMF_FID_VALUE) + +/* Following are the supported PMF service IDs */ +#define PMF_PSCI_STAT_SVC_ID 0 +#define PMF_RT_INSTR_SVC_ID 1 + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +/* PMF common functions */ +int pmf_get_timestamp_smc(unsigned int tid, + u_register_t mpidr, + unsigned int flags, + unsigned long long *ts_value); +int pmf_setup(void); +uintptr_t pmf_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, + u_register_t flags); + +#endif /* PMF_H */ diff --git a/arm-trusted-firmware/include/lib/pmf/pmf_helpers.h b/arm-trusted-firmware/include/lib/pmf/pmf_helpers.h new file mode 100644 index 0000000..b49c6da --- /dev/null +++ b/arm-trusted-firmware/include/lib/pmf/pmf_helpers.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMF_HELPERS_H +#define PMF_HELPERS_H + +#include +#include +#include + +#include +#include +#include + +/* + * Prototype for PMF service functions. + */ +typedef int (*pmf_svc_init_t)(void); +typedef unsigned long long (*pmf_svc_get_ts_t)(unsigned int tid, + u_register_t mpidr, + unsigned int flags); + +/* + * This is the definition of PMF service desc. + */ +typedef struct pmf_svc_desc { + /* Structure version information */ + param_header_t h; + + /* Name of the PMF service */ + const char *name; + + /* PMF service config: Implementer id, Service id and total id*/ + unsigned int svc_config; + + /* PMF service initialization handler */ + pmf_svc_init_t init; + + /* PMF service time-stamp retrieval handler */ + pmf_svc_get_ts_t get_ts; +} pmf_svc_desc_t; + +#if ENABLE_PMF +/* + * Convenience macros for capturing time-stamp. + */ +#define PMF_DECLARE_CAPTURE_TIMESTAMP(_name) \ + void pmf_capture_timestamp_with_cache_maint_ ## _name( \ + unsigned int tid, \ + unsigned long long ts); \ + void pmf_capture_timestamp_ ## _name( \ + unsigned int tid, \ + unsigned long long ts); + +#define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags) \ + do { \ + unsigned long long ts = read_cntpct_el0(); \ + if (((_flags) & PMF_CACHE_MAINT) != 0U) \ + pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), ts);\ + else \ + pmf_capture_timestamp_ ## _name((_tid), ts); \ + } while (0) + +#define PMF_CAPTURE_AND_GET_TIMESTAMP(_name, _tid, _flags, _tsval) \ + do { \ + (_tsval) = read_cntpct_el0(); \ + CASSERT(sizeof(_tsval) == sizeof(unsigned long long), invalid_tsval_size);\ + if (((_flags) & PMF_CACHE_MAINT) != 0U) \ + pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_tsval));\ + else \ + pmf_capture_timestamp_ ## _name((_tid), (_tsval));\ + } while (0) + +#define PMF_WRITE_TIMESTAMP(_name, _tid, _flags, _wrval) \ + do { \ + CASSERT(sizeof(_wrval) == sizeof(unsigned long long), invalid_wrval_size);\ + if (((_flags) & PMF_CACHE_MAINT) != 0U) \ + pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_wrval));\ + else \ + pmf_capture_timestamp_ ## _name((_tid), (_wrval));\ + } while (0) + +/* + * Convenience macros for retrieving time-stamp. + */ +#define PMF_DECLARE_GET_TIMESTAMP(_name) \ + unsigned long long pmf_get_timestamp_by_index_ ## _name(\ + unsigned int tid, \ + unsigned int cpuid, \ + unsigned int flags); \ + unsigned long long pmf_get_timestamp_by_mpidr_ ## _name(\ + unsigned int tid, \ + u_register_t mpidr, \ + unsigned int flags); + +#define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval)\ + _tsval = pmf_get_timestamp_by_mpidr_ ## _name(_tid, _mpidr, _flags) + +#define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval)\ + _tsval = pmf_get_timestamp_by_index_ ## _name(_tid, _cpuid, _flags) + +/* Convenience macros to register a PMF service.*/ +/* + * This macro is used to register a PMF Service. It allocates PMF memory + * and defines default service-specific PMF functions. + */ +#define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) \ + PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _totalid) \ + PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags) \ + PMF_DEFINE_GET_TIMESTAMP(_name) + +/* + * This macro is used to register a PMF service, including an + * SMC interface to that service. + */ +#define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags)\ + PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) \ + PMF_DEFINE_SERVICE_DESC(_name, PMF_ARM_TIF_IMPL_ID, \ + _svcid, _totalid, NULL, \ + pmf_get_timestamp_by_mpidr_ ## _name) + +/* + * This macro is used to register a PMF service that has an SMC interface + * but provides its own service-specific PMF functions. + */ +#define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid, \ + _init, _getts) \ + PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid, \ + _init, _getts) + +#else + +#define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) +#define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags) +#define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid, \ + _init, _getts) +#define PMF_DECLARE_CAPTURE_TIMESTAMP(_name) +#define PMF_DECLARE_GET_TIMESTAMP(_name) +#define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags) +#define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval) +#define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval) + +#endif /* ENABLE_PMF */ + +/* + * Convenience macro to allocate memory for a PMF service. + * + * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. + */ +#define PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _total_id) \ + extern unsigned long long pmf_ts_mem_ ## _name[_total_id]; \ + unsigned long long pmf_ts_mem_ ## _name[_total_id] \ + __aligned(CACHE_WRITEBACK_GRANULE) \ + __section("pmf_timestamp_array") \ + __used; + +/* + * Convenience macro to validate tid index for the given TS array. + */ +#define PMF_VALIDATE_TID(_name, _tid) \ + assert((_tid & PMF_TID_MASK) < (ARRAY_SIZE(pmf_ts_mem_ ## _name))) + +/* + * Convenience macros for capturing time-stamp. + * + * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. + */ +#define PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags) \ + void pmf_capture_timestamp_ ## _name( \ + unsigned int tid, \ + unsigned long long ts) \ + { \ + CASSERT(_flags != 0, select_proper_config); \ + PMF_VALIDATE_TID(_name, (uint64_t)tid); \ + uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ + if (((_flags) & PMF_STORE_ENABLE) != 0) \ + __pmf_store_timestamp(base_addr, \ + (uint64_t)tid, ts); \ + if (((_flags) & PMF_DUMP_ENABLE) != 0) \ + __pmf_dump_timestamp((uint64_t)tid, ts); \ + } \ + void pmf_capture_timestamp_with_cache_maint_ ## _name( \ + unsigned int tid, \ + unsigned long long ts) \ + { \ + CASSERT(_flags != 0, select_proper_config); \ + PMF_VALIDATE_TID(_name, (uint64_t)tid); \ + uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ + if (((_flags) & PMF_STORE_ENABLE) != 0) \ + __pmf_store_timestamp_with_cache_maint( \ + base_addr, (uint64_t)tid, ts); \ + if (((_flags) & PMF_DUMP_ENABLE) != 0) \ + __pmf_dump_timestamp((uint64_t)tid, ts); \ + } + +/* + * Convenience macros for retrieving time-stamp. + * + * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. + */ +#define PMF_DEFINE_GET_TIMESTAMP(_name) \ + unsigned long long pmf_get_timestamp_by_index_ ## _name( \ + unsigned int tid, unsigned int cpuid, unsigned int flags)\ + { \ + PMF_VALIDATE_TID(_name, tid); \ + uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ + return __pmf_get_timestamp(base_addr, tid, cpuid, flags);\ + } \ + unsigned long long pmf_get_timestamp_by_mpidr_ ## _name( \ + unsigned int tid, u_register_t mpidr, unsigned int flags)\ + { \ + PMF_VALIDATE_TID(_name, tid); \ + uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ + return __pmf_get_timestamp(base_addr, tid, \ + plat_core_pos_by_mpidr(mpidr), flags); \ + } + +/* + * Convenience macro to register a PMF service. + * This is needed for services that require SMC handling. + */ +#define PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid, \ + _init, _getts_by_mpidr) \ + static const pmf_svc_desc_t __pmf_desc_ ## _name \ + __section("pmf_svc_descs") __used = { \ + .h.type = PARAM_EP, \ + .h.version = VERSION_1, \ + .h.size = sizeof(pmf_svc_desc_t), \ + .h.attr = 0, \ + .name = #_name, \ + .svc_config = ((((_implid) << PMF_IMPL_ID_SHIFT) & \ + PMF_IMPL_ID_MASK) | \ + (((_svcid) << PMF_SVC_ID_SHIFT) & \ + PMF_SVC_ID_MASK) | \ + (((_totalid) << PMF_TID_SHIFT) & \ + PMF_TID_MASK)), \ + .init = _init, \ + .get_ts = _getts_by_mpidr \ + }; + +/* PMF internal functions */ +void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts); +void __pmf_store_timestamp(uintptr_t base_addr, + unsigned int tid, + unsigned long long ts); +void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr, + unsigned int tid, + unsigned long long ts); +unsigned long long __pmf_get_timestamp(uintptr_t base_addr, + unsigned int tid, + unsigned int cpuid, + unsigned int flags); +#endif /* PMF_HELPERS_H */ diff --git a/arm-trusted-firmware/include/lib/psci/psci.h b/arm-trusted-firmware/include/lib/psci/psci.h new file mode 100644 index 0000000..b56e98b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/psci/psci_lib.h b/arm-trusted-firmware/include/lib/psci/psci_lib.h new file mode 100644 index 0000000..1ac45ad --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/runtime_instr.h b/arm-trusted-firmware/include/lib/runtime_instr.h new file mode 100644 index 0000000..303f27e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/semihosting.h b/arm-trusted-firmware/include/lib/semihosting.h new file mode 100644 index 0000000..24b030c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/smccc.h b/arm-trusted-firmware/include/lib/smccc.h new file mode 100644 index 0000000..1a39f24 --- /dev/null +++ b/arm-trusted-firmware/include/lib/smccc.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2016-2021, 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) + +/******************************************************************************* + * SMCCC_ARCH_SOC_ID SoC version & revision bit definition + ******************************************************************************/ +#define SOC_ID_JEP_106_BANK_IDX_MASK GENMASK_32(30, 24) +#define SOC_ID_JEP_106_BANK_IDX_SHIFT U(24) +#define SOC_ID_JEP_106_ID_CODE_MASK GENMASK_32(23, 16) +#define SOC_ID_JEP_106_ID_CODE_SHIFT U(16) +#define SOC_ID_IMPL_DEF_MASK GENMASK_32(15, 0) +#define SOC_ID_IMPL_DEF_SHIFT U(0) +#define SOC_ID_SET_JEP_106(bkid, mfid) ((((bkid) << SOC_ID_JEP_106_BANK_IDX_SHIFT) & \ + SOC_ID_JEP_106_BANK_IDX_MASK) | \ + (((mfid) << SOC_ID_JEP_106_ID_CODE_SHIFT) & \ + SOC_ID_JEP_106_ID_CODE_MASK)) + +#define SOC_ID_REV_MASK GENMASK_32(30, 0) +#define SOC_ID_REV_SHIFT U(0) + +/******************************************************************************* + * 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 + * + * Bit 5 and bit 0 of the flag are used to + * determine the source security state as + * follows: + * --------------------------------- + * Bit 5 | Bit 0 | Security state + * --------------------------------- + * 0 0 SMC_FROM_SECURE + * 0 1 SMC_FROM_NON_SECURE + * 1 1 SMC_FROM_REALM + */ + +#define SMC_FROM_SECURE (U(0) << 0) +#define SMC_FROM_NON_SECURE (U(1) << 0) +#define SMC_FROM_REALM U(0x21) +#define SMC_FROM_MASK U(0x21) + +#ifndef __ASSEMBLER__ + +#include + +#include + +#if ENABLE_RME +#define is_caller_non_secure(_f) (((_f) & SMC_FROM_MASK) \ + == SMC_FROM_NON_SECURE) +#define is_caller_secure(_f) (((_f) & SMC_FROM_MASK) \ + == SMC_FROM_SECURE) +#define is_caller_realm(_f) (((_f) & SMC_FROM_MASK) \ + == SMC_FROM_REALM) +#define caller_sec_state(_f) ((_f) & SMC_FROM_MASK) +#else /* ENABLE_RME */ +#define is_caller_non_secure(_f) (((_f) & SMC_FROM_NON_SECURE) != U(0)) +#define is_caller_secure(_f) (!is_caller_non_secure(_f)) +#endif /* ENABLE_RME */ + +/* 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/arm-trusted-firmware/include/lib/spinlock.h b/arm-trusted-firmware/include/lib/spinlock.h new file mode 100644 index 0000000..0bf3ee0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/utils.h b/arm-trusted-firmware/include/lib/utils.h new file mode 100644 index 0000000..17ee936 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/utils_def.h b/arm-trusted-firmware/include/lib/utils_def.h new file mode 100644 index 0000000..7a7012d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h b/arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h new file mode 100644 index 0000000..252b92c --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_MPU_H +#define XLAT_MPU_H + +#ifndef __ASSEMBLER__ + +#include + +#define XLAT_TABLES_LIB_V2 1 + +void enable_mpu_el2(unsigned int flags); +void enable_mpu_direct_el2(unsigned int flags); + +/* + * Function to wipe clean and disable all MPU regions. This function expects + * that the MPU has already been turned off, and caching concerns addressed, + * but it nevertheless also explicitly turns off the MPU. + */ +void clear_all_mpu_regions(void); + +#endif /* __ASSEMBLER__ */ +#endif /* XLAT_MPU_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h b/arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h new file mode 100644 index 0000000..30eb5e9 --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_AARCH32_H +#define XLAT_TABLES_AARCH32_H + +#include +#include +#include + +#if !defined(PAGE_SIZE) +#error "PAGE_SIZE is not defined." +#endif + +/* + * In AArch32 state, the MMU only supports 4KB page granularity, which means + * that the first translation table level is either 1 or 2. Both of them are + * allowed to have block and table descriptors. See section G4.5.6 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 +#error "Invalid granule size. AArch32 supports 4KB pages only." +#endif + +#define MIN_LVL_BLOCK_DESC U(1) + +#define XLAT_TABLE_LEVEL_MIN U(1) + +/* + * Define the architectural limits of the virtual address space in AArch32 + * state. + * + * TTBCR.TxSZ is calculated as 32 minus the width of said address space. The + * value of TTBCR.TxSZ must be in the range 0 to 7 [1], which means that the + * virtual address space width must be in the range 32 to 25 bits. + * + * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information, Section G4.6.5 + */ +#define MIN_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(32) - TTBCR_TxSZ_MAX)) +#define MAX_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(32) - TTBCR_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 1 supports virtual address spaces of widths 32 to 31 bits; + * - level 2 from 30 to 25. + * + * Wider or narrower address spaces are not supported. As a result, level 3 + * cannot be used as the initial lookup level with 4 KB granularity. + * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information, Section G4.6.5 + * + * For example, for a 31-bit address space (i.e. virt_addr_space_size == + * 1 << 31), TTBCR.TxSZ will be programmed to (32 - 31) = 1. According to Table + * G4-5 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) << L1_XLAT_ADDRESS_SHIFT)) ? \ + U(1) : U(2)) + +#endif /* XLAT_TABLES_AARCH32_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h b/arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h new file mode 100644 index 0000000..3014c8f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h new file mode 100644 index 0000000..269afd2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h new file mode 100644 index 0000000..a156969 --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014-2021, 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) + +/* Memory type for EL3 regions */ +#if ENABLE_RME +#error FEAT_RME requires version 2 of the Translation Tables Library +#else +#define EL3_PAS MT_SECURE +#endif + +/* + * 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/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h new file mode 100644 index 0000000..0ce0cac --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h new file mode 100644 index 0000000..90768db --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h new file mode 100644 index 0000000..2d0949b --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017-2021, 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 EL3_S1_NSE (U(0x1) << 9) +#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/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h new file mode 100644 index 0000000..69ad027 --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2017-2021, 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) + +/* Physical address space (SECURE/NS/Root/Realm) */ +#define MT_PAS_SHIFT U(4) +#define MT_PAS_MASK (U(3) << MT_PAS_SHIFT) +#define MT_PAS(_attr) ((_attr) & MT_PAS_MASK) + +/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */ +#define MT_EXECUTE_SHIFT U(6) +/* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */ +#define MT_USER_SHIFT U(7) + +/* Shareability attribute for the memory region */ +#define MT_SHAREABILITY_SHIFT U(8) +#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_PAS_SHIFT) +#define MT_NS (U(1) << MT_PAS_SHIFT) +#define MT_ROOT (U(2) << MT_PAS_SHIFT) +#define MT_REALM (U(3) << MT_PAS_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 + +/* Memory type for EL3 regions. With RME, EL3 is in ROOT PAS */ +#if ENABLE_RME +#define EL3_PAS MT_ROOT +#else +#define EL3_PAS MT_SECURE +#endif /* ENABLE_RME */ + +/* + * 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/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h new file mode 100644 index 0000000..62f853d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/lib/zlib/tf_gunzip.h b/arm-trusted-firmware/include/lib/zlib/tf_gunzip.h new file mode 100644 index 0000000..741ba50 --- /dev/null +++ b/arm-trusted-firmware/include/lib/zlib/tf_gunzip.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TF_GUNZIP_H +#define TF_GUNZIP_H + +#include +#include + +int gunzip(uintptr_t *in_buf, size_t in_len, uintptr_t *out_buf, + size_t out_len, uintptr_t work_buf, size_t work_len); + +#endif /* TF_GUNZIP_H */ diff --git a/arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h b/arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h new file mode 100644 index 0000000..1963bf0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h b/arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h new file mode 100644 index 0000000..cb11dac --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef V2M_DEF_H +#define V2M_DEF_H + +#include + +/* Base address of all V2M */ +#ifdef PLAT_V2M_OFFSET +#define V2M_OFFSET PLAT_V2M_OFFSET +#else +#define V2M_OFFSET UL(0) +#endif + +/* 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 (V2M_OFFSET + UL(0x08000000)) +#define V2M_FLASH0_SIZE UL(0x04000000) +#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */ + +#define V2M_IOFPGA_BASE (V2M_OFFSET + UL(0x1c000000)) +#define V2M_IOFPGA_SIZE UL(0x03000000) + +/* PL011 UART related constants */ +#define V2M_IOFPGA_UART0_BASE (V2M_OFFSET + UL(0x1c090000)) +#define V2M_IOFPGA_UART1_BASE (V2M_OFFSET + UL(0x1c0a0000)) +#define V2M_IOFPGA_UART2_BASE (V2M_OFFSET + UL(0x1c0b0000)) +#define V2M_IOFPGA_UART3_BASE (V2M_OFFSET + 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 (V2M_OFFSET + UL(0x1C110000)) +#define V2M_SP804_TIMER1_BASE (V2M_OFFSET + UL(0x1C120000)) + +/* SP810 controller */ +#define V2M_SP810_BASE (V2M_OFFSET + 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/arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h b/arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h new file mode 100644 index 0000000..0b41e67 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_BL1_H +#define FVP_R_BL1_H + +void bl1_load_bl33(void); +void bl1_transfer_bl33(void); + +#endif /* FVP_R_BL1_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S b/arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S new file mode 100644 index 0000000..d47e4e0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S b/arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S new file mode 100644 index 0000000..07f7cd3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/arm_config.h b/arm-trusted-firmware/include/plat/arm/common/arm_config.h new file mode 100644 index 0000000..c2b28df --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/arm_def.h b/arm-trusted-firmware/include/plat/arm/common/arm_def.h new file mode 100644 index 0000000..2af8c11 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_def.h @@ -0,0 +1,737 @@ +/* + * Copyright (c) 2015-2022, 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 + +#ifdef PLAT_ARM_TRUSTED_SRAM_BASE +#define ARM_TRUSTED_SRAM_BASE PLAT_ARM_TRUSTED_SRAM_BASE +#else +#define ARM_TRUSTED_SRAM_BASE UL(0x04000000) +#endif /* PLAT_ARM_TRUSTED_SRAM_BASE */ + +#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 (or 64MB if RME is enabled) of DRAM1 is configured as + * follows: + * - SCP TZC DRAM: If present, DRAM reserved for SCP use + * - L1 GPT DRAM: Reserved for L1 GPT if RME is enabled + * - REALM DRAM: Reserved for Realm world if RME is enabled + * - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use + * + * RME enabled(64MB) RME not enabled(16MB) + * -------------------- ------------------- + * | | | | + * | AP TZC (~28MB) | | AP TZC (~14MB) | + * -------------------- ------------------- + * | | | | + * | REALM (32MB) | | EL3 TZC (2MB) | + * -------------------- ------------------- + * | | | | + * | EL3 TZC (3MB) | | SCP TZC | + * -------------------- 0xFFFF_FFFF------------------- + * | L1 GPT + SCP TZC | + * | (~1MB) | + * 0xFFFF_FFFF -------------------- + */ +#if ENABLE_RME +#define ARM_TZC_DRAM1_SIZE UL(0x04000000) /* 64MB */ +/* + * Define a 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. 3MB region is reserved if RME is enabled, 2MB otherwise. + */ +#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00300000) /* 3MB */ +#define ARM_L1_GPT_SIZE UL(0x00100000) /* 1MB */ +#define ARM_REALM_SIZE UL(0x02000000) /* 32MB */ +#else +#define ARM_TZC_DRAM1_SIZE UL(0x01000000) /* 16MB */ +#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00200000) /* 2MB */ +#define ARM_L1_GPT_SIZE UL(0) +#define ARM_REALM_SIZE UL(0) +#endif /* ENABLE_RME */ + +#define ARM_SCP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + (ARM_SCP_TZC_DRAM1_SIZE + \ + ARM_L1_GPT_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) +#if ENABLE_RME +#define ARM_L1_GPT_ADDR_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + ARM_L1_GPT_SIZE) +#define ARM_L1_GPT_END (ARM_L1_GPT_ADDR_BASE + \ + ARM_L1_GPT_SIZE - 1U) + +#define ARM_REALM_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + (ARM_SCP_TZC_DRAM1_SIZE + \ + ARM_EL3_TZC_DRAM1_SIZE + \ + ARM_REALM_SIZE + \ + ARM_L1_GPT_SIZE)) +#define ARM_REALM_END (ARM_REALM_BASE + ARM_REALM_SIZE - 1U) +#endif /* ENABLE_RME */ + +#define ARM_EL3_TZC_DRAM1_BASE (ARM_SCP_TZC_DRAM1_BASE - \ + ARM_EL3_TZC_DRAM1_SIZE) +#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 + \ + ARM_REALM_SIZE + \ + ARM_L1_GPT_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) +#ifdef PLAT_ARM_DRAM1_BASE +#define ARM_DRAM1_BASE PLAT_ARM_DRAM1_BASE +#else +#define ARM_DRAM1_BASE ULL(0x80000000) +#endif /* PLAT_ARM_DRAM1_BASE */ + +#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 | EL3_PAS) + +#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 | EL3_PAS) + +#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 + +#if ENABLE_RME +#define ARM_MAP_RMM_DRAM MAP_REGION_FLAT( \ + PLAT_ARM_RMM_BASE, \ + PLAT_ARM_RMM_SIZE, \ + MT_MEMORY | MT_RW | MT_REALM) + + +#define ARM_MAP_GPT_L1_DRAM MAP_REGION_FLAT( \ + ARM_L1_GPT_ADDR_BASE, \ + ARM_L1_GPT_SIZE, \ + MT_MEMORY | MT_RW | EL3_PAS) + +#endif /* ENABLE_RME */ + +/* + * 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 | EL3_PAS) + +/* + * 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 | EL3_PAS), \ + MAP_REGION_FLAT( \ + BL_RO_DATA_BASE, \ + BL_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | EL3_PAS) +#else +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | EL3_PAS) +#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 | EL3_PAS) +#endif +#if USE_ROMLIB +#define ARM_MAP_ROMLIB_CODE MAP_REGION_FLAT( \ + ROMLIB_RO_BASE, \ + ROMLIB_RO_LIMIT - ROMLIB_RO_BASE,\ + MT_CODE | EL3_PAS) + +#define ARM_MAP_ROMLIB_DATA MAP_REGION_FLAT( \ + ROMLIB_RW_BASE, \ + ROMLIB_RW_END - ROMLIB_RW_BASE,\ + MT_MEMORY | MT_RW | EL3_PAS) +#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 | EL3_PAS) +/* + * Map L0_GPT with read and write permissions + */ +#if ENABLE_RME +#define ARM_MAP_L0_GPT_REGION MAP_REGION_FLAT(ARM_L0_GPT_ADDR_BASE, \ + ARM_L0_GPT_SIZE, \ + MT_MEMORY | MT_RW | MT_ROOT) +#endif + +/* + * 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 7 + +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) + +/* Memory mapped Generic timer interfaces */ +#ifdef PLAT_ARM_SYS_CNTCTL_BASE +#define ARM_SYS_CNTCTL_BASE PLAT_ARM_SYS_CNTCTL_BASE +#else +#define ARM_SYS_CNTCTL_BASE UL(0x2a430000) +#endif + +#ifdef PLAT_ARM_SYS_CNTREAD_BASE +#define ARM_SYS_CNTREAD_BASE PLAT_ARM_SYS_CNTREAD_BASE +#else +#define ARM_SYS_CNTREAD_BASE UL(0x2a800000) +#endif + +#ifdef PLAT_ARM_SYS_TIMCTL_BASE +#define ARM_SYS_TIMCTL_BASE PLAT_ARM_SYS_TIMCTL_BASE +#else +#define ARM_SYS_TIMCTL_BASE UL(0x2a810000) +#endif + +#ifdef PLAT_ARM_SYS_CNT_BASE_S +#define ARM_SYS_CNT_BASE_S PLAT_ARM_SYS_CNT_BASE_S +#else +#define ARM_SYS_CNT_BASE_S UL(0x2a820000) +#endif + +#ifdef PLAT_ARM_SYS_CNT_BASE_NS +#define ARM_SYS_CNT_BASE_NS PLAT_ARM_SYS_CNT_BASE_NS +#else +#define ARM_SYS_CNT_BASE_NS UL(0x2a830000) +#endif + +#define ARM_CONSOLE_BAUDRATE 115200 + +/* Trusted Watchdog constants */ +#ifdef PLAT_ARM_SP805_TWDG_BASE +#define ARM_SP805_TWDG_BASE PLAT_ARM_SP805_TWDG_BASE +#else +#define ARM_SP805_TWDG_BASE UL(0x2a490000) +#endif +#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)) + +#if ENABLE_RME +/* + * Store the L0 GPT on Trusted SRAM next to firmware + * configuration memory, 4KB aligned. + */ +#define ARM_L0_GPT_SIZE (PAGE_SIZE) +#define ARM_L0_GPT_ADDR_BASE (ARM_FW_CONFIGS_LIMIT) +#define ARM_L0_GPT_LIMIT (ARM_L0_GPT_ADDR_BASE + ARM_L0_GPT_SIZE) +#else +#define ARM_L0_GPT_SIZE U(0) +#endif + +/******************************************************************************* + * 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 +#ifdef PLAT_BL1_RO_LIMIT +#define BL1_RO_LIMIT PLAT_BL1_RO_LIMIT +#else +#define BL1_RO_LIMIT (PLAT_ARM_TRUSTED_ROM_BASE \ + + (PLAT_ARM_TRUSTED_ROM_SIZE - \ + PLAT_ARM_MAX_ROMLIB_RO_SIZE)) +#endif + +/* + * 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 + +/****************************************************************************** + * RMM specific defines + *****************************************************************************/ +#if ENABLE_RME +#define RMM_BASE (ARM_REALM_BASE) +#define RMM_LIMIT (RMM_BASE + ARM_REALM_SIZE) +#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 +/* Ensure Position Independent support (PIE) is enabled for this config.*/ +# if !ENABLE_PIE +# error "BL32 must be a PIE if RESET_TO_SP_MIN=1." +#endif +/* + * Since this is PIE, we can define BL32_BASE to 0x0 since this macro is solely + * used for building BL32 and not used for loading BL32. + */ +# define BL32_BASE 0x0 +# define BL32_LIMIT PLAT_ARM_MAX_BL32_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/arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h b/arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h new file mode 100644 index 0000000..ff00fe7 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018-2021, 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); + +#endif /* ARM_DYN_CFG_HELPERS_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h b/arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h new file mode 100644 index 0000000..8fd8c7a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h b/arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h new file mode 100644 index 0000000..02ee66c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h b/arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h new file mode 100644 index 0000000..4fee41b --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_PAS_DEF_H +#define ARM_PAS_DEF_H + +#include +#include + +/***************************************************************************** + * PAS regions used to initialize the Granule Protection Table (GPT) + ****************************************************************************/ + +/* + * The PA space is initially mapped in the GPT as follows: + * + * ============================================================================ + * Base Addr| Size |L? GPT|PAS |Content |Comment + * ============================================================================ + * 0GB | 1GB |L0 GPT|ANY |TBROM (EL3 code) |Fixed mapping + * | | | |TSRAM (EL3 data) | + * | | | |IO (incl.UARTs & GIC) | + * ---------------------------------------------------------------------------- + * 1GB | 1GB |L0 GPT|ANY |IO |Fixed mapping + * ---------------------------------------------------------------------------- + * 2GB | 1GB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip + * ---------------------------------------------------------------------------- + * 3GB |1GB-64MB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip + * ---------------------------------------------------------------------------- + * 4GB-64MB |64MB-32MB | | | | + * | -4MB |L1 GPT|SECURE|DRAM TZC |Use T.Descrip + * ---------------------------------------------------------------------------- + * 4GB-32MB | | | | | + * -3MB-1MB |32MB |L1 GPT|REALM |RMM |Use T.Descrip + * ---------------------------------------------------------------------------- + * 4GB-3MB | | | | | + * -1MB |3MB |L1 GPT|ROOT |EL3 DRAM data |Use T.Descrip + * ---------------------------------------------------------------------------- + * 4GB-1MB |1MB |L1 GPT|ROOT |DRAM (L1 GPTs, SCP TZC) |Fixed mapping + * ============================================================================ + * + * - 4KB of L0 GPT reside in TSRAM, on top of the CONFIG section. + * - ~1MB of L1 GPTs reside at the top of DRAM1 (TZC area). + * - The first 1GB region has GPT_GPI_ANY and, therefore, is not protected by + * the GPT. + * - The DRAM TZC area is split into three regions: the L1 GPT region and + * 3MB of region below that are defined as GPT_GPI_ROOT, 32MB Realm region + * below that is defined as GPT_GPI_REALM and the rest of it is defined as + * GPT_GPI_SECURE. + */ + +/* TODO: This might not be the best way to map the PAS */ + +/* Device memory 0 to 2GB */ +#define ARM_PAS_1_BASE (U(0)) +#define ARM_PAS_1_SIZE ((ULL(1)<<31)) /* 2GB */ + +/* NS memory 2GB to (end - 64MB) */ +#define ARM_PAS_2_BASE (ARM_PAS_1_BASE + ARM_PAS_1_SIZE) +#define ARM_PAS_2_SIZE (ARM_NS_DRAM1_SIZE) + +/* Secure TZC region */ +#define ARM_PAS_3_BASE (ARM_AP_TZC_DRAM1_BASE) +#define ARM_PAS_3_SIZE (ARM_AP_TZC_DRAM1_SIZE) + +#define ARM_PAS_GPI_ANY MAP_GPT_REGION(ARM_PAS_1_BASE, \ + ARM_PAS_1_SIZE, \ + GPT_GPI_ANY) +#define ARM_PAS_KERNEL GPT_MAP_REGION_GRANULE(ARM_PAS_2_BASE, \ + ARM_PAS_2_SIZE, \ + GPT_GPI_NS) + +#define ARM_PAS_SECURE GPT_MAP_REGION_GRANULE(ARM_PAS_3_BASE, \ + ARM_PAS_3_SIZE, \ + GPT_GPI_SECURE) + +#define ARM_PAS_REALM GPT_MAP_REGION_GRANULE(ARM_REALM_BASE, \ + ARM_REALM_SIZE, \ + GPT_GPI_REALM) + +#define ARM_PAS_EL3_DRAM GPT_MAP_REGION_GRANULE(ARM_EL3_TZC_DRAM1_BASE, \ + ARM_EL3_TZC_DRAM1_SIZE, \ + GPT_GPI_ROOT) + +#define ARM_PAS_GPTS GPT_MAP_REGION_GRANULE(ARM_L1_GPT_ADDR_BASE, \ + ARM_L1_GPT_SIZE, \ + GPT_GPI_ROOT) + +/* GPT Configuration options */ +#define PLATFORM_L0GPTSZ GPCCR_L0GPTSZ_30BITS + +#endif /* ARM_PAS_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S b/arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S new file mode 100644 index 0000000..717f65e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h b/arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h new file mode 100644 index 0000000..2eeed95 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h b/arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h new file mode 100644 index 0000000..c43583d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S b/arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S new file mode 100644 index 0000000..6dcea0b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h b/arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h new file mode 100644 index 0000000..aa628df --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h b/arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h new file mode 100644 index 0000000..fcdc31f --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h @@ -0,0 +1,38 @@ +/* + * 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[idx].addr; \ +}) + +#define ETHOSN_STATUS_DISABLED U(0) +#define ETHOSN_STATUS_ENABLED U(1) + +#define ETHOSN_CORE_NUM_MAX U(64) + +struct ethosn_core_t { + uint64_t addr; +}; + +struct ethosn_config_t { + uint32_t num_cores; + struct ethosn_core_t core[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/arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h b/arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h new file mode 100644 index 0000000..80a6000 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h b/arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h new file mode 100644 index 0000000..e0a97a6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h b/arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h new file mode 100644 index 0000000..5d6b594 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/common/plat_arm.h b/arm-trusted-firmware/include/plat/arm/common/plat_arm.h new file mode 100644 index 0000000..9618700 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/plat_arm.h @@ -0,0 +1,361 @@ +/* + * 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 + ARM_L1_GPT_SIZE,\ + 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} + +#elif ENABLE_RME +#define ARM_TZC_REGIONS_DEF \ + {ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END, TZC_REGION_S_RDWR, 0},\ + {ARM_EL3_TZC_DRAM1_BASE, ARM_L1_GPT_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_REALM_BASE, ARM_REALM_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} + +#else +#define ARM_TZC_REGIONS_DEF \ + {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END + ARM_L1_GPT_SIZE,\ + 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, + uintptr_t *dev_handle, uintptr_t *image_spec); +void arm_set_fip_addr(uint32_t active_fw_bank_idx); + +/* 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 +int arm_set_tos_fw_info(uintptr_t log_addr, size_t log_size); +int arm_set_nt_fw_info( +/* + * 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); +int arm_set_tb_fw_info(uintptr_t log_addr, size_t log_size); +int arm_get_tb_fw_info(uint64_t *log_addr, size_t *log_size); +#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/arm-trusted-firmware/include/plat/arm/common/smccc_def.h b/arm-trusted-firmware/include/plat/arm/common/smccc_def.h new file mode 100644 index 0000000..0f4e573 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/smccc_def.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020-2021, 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) + +#endif /* SMCCC_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S b/arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S new file mode 100644 index 0000000..85a7044 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/css/common/css_def.h b/arm-trusted-firmware/include/plat/arm/css/common/css_def.h new file mode 100644 index 0000000..dde174c --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/css/common/css_def.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2015-2021, 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 SPNIDEN_INT_CLR_SHIFT 4 +#define SPNIDEN_SEL_SET_SHIFT 5 +#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/arm-trusted-firmware/include/plat/arm/css/common/css_pm.h b/arm-trusted-firmware/include/plat/arm/css/common/css_pm.h new file mode 100644 index 0000000..e5357f5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h b/arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h new file mode 100644 index 0000000..469928d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h b/arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h new file mode 100644 index 0000000..b4b6ba8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/brcm/common/bcm_console.h b/arm-trusted-firmware/include/plat/brcm/common/bcm_console.h new file mode 100644 index 0000000..7b653d8 --- /dev/null +++ b/arm-trusted-firmware/include/plat/brcm/common/bcm_console.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BCM_CONSOLE_H +#define BCM_CONSOLE_H + +void bcm_console_boot_init(void); +void bcm_console_boot_end(void); +void bcm_console_runtime_init(void); +void bcm_console_runtime_end(void); + +#endif /* BCM_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h b/arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h new file mode 100644 index 0000000..ea4b169 --- /dev/null +++ b/arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BCM_ELOG_H +#define BCM_ELOG_H + +#ifndef __ASSEMBLER__ + +#include + +#if defined(BCM_ELOG) && (defined(IMAGE_BL2) || defined(IMAGE_BL31)) +int bcm_elog_init(void *base, uint32_t size, unsigned int level); +void bcm_elog_exit(void); +int bcm_elog_copy_log(void *dst, uint32_t max_size); +void bcm_elog(const char *fmt, ...); +#else +static inline int bcm_elog_init(void *base, uint32_t size, + unsigned int level) +{ + return 0; +} +static inline void bcm_elog_exit(void) +{ +} +static inline int bcm_elog_copy_log(void *dst, uint32_t max_size) +{ + return 0; +} +static inline void bcm_elog(const char *fmt, ...) +{ +} +#endif /* BCM_ELOG */ + +#endif /* __ASSEMBLER__ */ +#endif /* BCM_ELOG_H */ diff --git a/arm-trusted-firmware/include/plat/brcm/common/brcm_def.h b/arm-trusted-firmware/include/plat/brcm/common/brcm_def.h new file mode 100644 index 0000000..c9137bc --- /dev/null +++ b/arm-trusted-firmware/include/plat/brcm/common/brcm_def.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BRCM_DEF_H +#define BRCM_DEF_H + +#include +#include +#include +#include +#include + +#include + +#define PLAT_PHY_ADDR_SPACE_SIZE BIT_64(32) +#define PLAT_VIRT_ADDR_SPACE_SIZE BIT_64(32) + +#define BL11_DAUTH_ID 0x796C51ab +#define BL11_DAUTH_BASE BL11_RW_BASE + +/* We keep a table at the end of ROM for function pointers */ +#define ROM_TABLE_SIZE 32 +#define BL1_ROM_TABLE (BL1_RO_LIMIT - ROM_TABLE_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 BRCM_TZC_DRAM1_SIZE ULL(0x01000000) + +#define BRCM_SCP_TZC_DRAM1_BASE (BRCM_DRAM1_BASE + \ + BRCM_DRAM1_SIZE - \ + BRCM_SCP_TZC_DRAM1_SIZE) +#define BRCM_SCP_TZC_DRAM1_SIZE PLAT_BRCM_SCP_TZC_DRAM1_SIZE + +#define BRCM_AP_TZC_DRAM1_BASE (BRCM_DRAM1_BASE + \ + BRCM_DRAM1_SIZE - \ + BRCM_TZC_DRAM1_SIZE) +#define BRCM_AP_TZC_DRAM1_SIZE (BRCM_TZC_DRAM1_SIZE - \ + BRCM_SCP_TZC_DRAM1_SIZE) + +#define BRCM_NS_DRAM1_BASE BRCM_DRAM1_BASE +#define BRCM_NS_DRAM1_SIZE (BRCM_DRAM1_SIZE - \ + BRCM_TZC_DRAM1_SIZE) + +#ifdef BRCM_SHARED_DRAM_BASE +#define BRCM_NS_SHARED_DRAM_BASE BRCM_SHARED_DRAM_BASE +#define BRCM_NS_SHARED_DRAM_SIZE BRCM_SHARED_DRAM_SIZE +#endif + +#define BRCM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + BRCM_SHARED_RAM_BASE, \ + BRCM_SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define BRCM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + BRCM_NS_DRAM1_BASE, \ + BRCM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#ifdef BRCM_SHARED_DRAM_BASE +#define BRCM_MAP_NS_SHARED_DRAM MAP_REGION_FLAT( \ + BRCM_NS_SHARED_DRAM_BASE, \ + BRCM_NS_SHARED_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) +#endif + +#ifdef BRCM_EXT_SRAM_BASE +#define BRCM_MAP_EXT_SRAM MAP_REGION_FLAT( \ + BRCM_EXT_SRAM_BASE, \ + BRCM_EXT_SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#define BRCM_MAP_NAND_RO MAP_REGION_FLAT(NAND_BASE_ADDR,\ + NAND_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define BRCM_MAP_QSPI_RO MAP_REGION_FLAT(QSPI_BASE_ADDR,\ + QSPI_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define HSLS_REGION MAP_REGION_FLAT(HSLS_BASE_ADDR, \ + HSLS_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define CCN_REGION MAP_REGION_FLAT(PLAT_BRCM_CCN_BASE, \ + CCN_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define GIC500_REGION MAP_REGION_FLAT(GIC500_BASE, \ + GIC500_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#ifdef PERIPH0_BASE +#define PERIPH0_REGION MAP_REGION_FLAT(PERIPH0_BASE, \ + PERIPH0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#ifdef PERIPH1_BASE +#define PERIPH1_REGION MAP_REGION_FLAT(PERIPH1_BASE, \ + PERIPH1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#ifdef PERIPH2_BASE +#define PERIPH2_REGION MAP_REGION_FLAT(PERIPH2_BASE, \ + PERIPH2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#if BRCM_BL31_IN_DRAM +#if IMAGE_BL2 +#define BRCM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \ + BL31_BASE, \ + PLAT_BRCM_MAX_BL31_SIZE,\ + MT_DEVICE | MT_RW | MT_SECURE) +#else +#define BRCM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \ + BL31_BASE, \ + PLAT_BRCM_MAX_BL31_SIZE,\ + MT_MEMORY | MT_RW | MT_SECURE) +#endif +#endif + +#if defined(USB_BASE) && defined(DRIVER_USB_ENABLE) +#define USB_REGION MAP_REGION_FLAT( \ + USB_BASE, \ + USB_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#ifdef USE_CRMU_SRAM +#define CRMU_SRAM_REGION MAP_REGION_FLAT( \ + CRMU_SRAM_BASE, \ + CRMU_SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif +/* + * The number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#if USE_COHERENT_MEM +#define BRCM_BL_REGIONS 3 +#else +#define BRCM_BL_REGIONS 2 +#endif + +#endif /* BRCM_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h b/arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h new file mode 100644 index 0000000..66ed2cb --- /dev/null +++ b/arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_BRCM_H +#define PLAT_BRCM_H + +#include + +#include +#include +#include + +#include + +struct image_info; + +/* Global variables */ +extern const mmap_region_t plat_brcm_mmap[]; + +uint32_t brcm_get_spsr_for_bl32_entry(void); +uint32_t brcm_get_spsr_for_bl33_entry(void); +const mmap_region_t *plat_brcm_get_mmap(void); +int bcm_bl2_handle_scp_bl2(struct image_info *image_info); +unsigned int plat_brcm_calc_core_pos(u_register_t mpidr); +void plat_brcm_gic_driver_init(void); +void plat_brcm_gic_init(void); +void plat_brcm_gic_cpuif_enable(void); +void plat_brcm_gic_cpuif_disable(void); +void plat_brcm_gic_pcpu_init(void); +void plat_brcm_gic_redistif_on(void); +void plat_brcm_gic_redistif_off(void); +void plat_brcm_interconnect_init(void); +void plat_brcm_interconnect_enter_coherency(void); +void plat_brcm_interconnect_exit_coherency(void); +void plat_brcm_io_setup(void); +void plat_brcm_process_flags(uint16_t plat_toc_flags); + +#endif /* PLAT_BRCM_H */ diff --git a/arm-trusted-firmware/include/plat/common/common_def.h b/arm-trusted-firmware/include/plat/common/common_def.h new file mode 100644 index 0000000..1d3ac15 --- /dev/null +++ b/arm-trusted-firmware/include/plat/common/common_def.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015-2022, 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 + +#define SZ_32 U(0x00000020) +#define SZ_64 U(0x00000040) +#define SZ_128 U(0x00000080) +#define SZ_256 U(0x00000100) +#define SZ_512 U(0x00000200) + +#define SZ_1K U(0x00000400) +#define SZ_2K U(0x00000800) +#define SZ_4K U(0x00001000) +#define SZ_8K U(0x00002000) +#define SZ_16K U(0x00004000) +#define SZ_32K U(0x00008000) +#define SZ_64K U(0x00010000) +#define SZ_128K U(0x00020000) +#define SZ_256K U(0x00040000) +#define SZ_512K U(0x00080000) + +#define SZ_1M U(0x00100000) +#define SZ_2M U(0x00200000) +#define SZ_4M U(0x00400000) +#define SZ_8M U(0x00800000) +#define SZ_16M U(0x01000000) +#define SZ_32M U(0x02000000) +#define SZ_64M U(0x04000000) +#define SZ_128M U(0x08000000) +#define SZ_256M U(0x10000000) +#define SZ_512M U(0x20000000) + +#define SZ_1G U(0x40000000) +#define SZ_2G U(0x80000000) + +/****************************************************************************** + * 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 */ + +#if MEASURED_BOOT +/* + * Start critical data Ids from 2^32/2 reserving Ids from 0 to (2^32/2 - 1) + * for Images, It is a critical data Id base for all platforms. + */ +#define CRITICAL_DATA_ID_BASE U(0x80000000) +#endif /* MEASURED_BOOT */ + +#endif /* COMMON_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/common/plat_trng.h b/arm-trusted-firmware/include/plat/common/plat_trng.h new file mode 100644 index 0000000..a9f73b6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/plat/common/platform.h b/arm-trusted-firmware/include/plat/common/platform.h new file mode 100644 index 0000000..7664509 --- /dev/null +++ b/arm-trusted-firmware/include/plat/common/platform.h @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2013-2022, 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 +#include + +/******************************************************************************* + * 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); + +#if MEASURED_BOOT +int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data); +int plat_mboot_measure_critical_data(unsigned int critical_data_id, + const void *base, + size_t size); +#else +static inline int plat_mboot_measure_image(unsigned int image_id __unused, + image_info_t *image_data __unused) +{ + return 0; +} +static inline int plat_mboot_measure_critical_data( + unsigned int critical_data_id __unused, + const void *base __unused, + size_t size __unused) +{ + return 0; +} +#endif /* MEASURED_BOOT */ + +/******************************************************************************* + * 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_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags); +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 +void bl1_plat_mboot_init(void); +void bl1_plat_mboot_finish(void); +#else +static inline void bl1_plat_mboot_init(void) +{ +} +static inline void bl1_plat_mboot_finish(void) +{ +} +#endif /* MEASURED_BOOT */ + +/******************************************************************************* + * 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 +void bl2_plat_mboot_init(void); +void bl2_plat_mboot_finish(void); +#else +static inline void bl2_plat_mboot_init(void) +{ +} +static inline void bl2_plat_mboot_finish(void) +{ +} +#endif /* MEASURED_BOOT */ + +/******************************************************************************* + * 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); + +/******************************************************************************* + * Mandatory BL31 functions when ENABLE_RME=1 + ******************************************************************************/ +int plat_get_cca_attest_token(uintptr_t buf, size_t *len, + uintptr_t hash, size_t hash_size); +int plat_get_cca_realm_attest_key(uintptr_t buf, size_t *len, + unsigned int type); + +/******************************************************************************* + * 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); + +/******************************************************************************* + * FWU platform specific functions + ******************************************************************************/ +int plat_fwu_set_metadata_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +void plat_fwu_set_images_source(const struct fwu_metadata *metadata); +uint32_t plat_fwu_get_boot_idx(void); + +#endif /* PLATFORM_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h new file mode 100644 index 0000000..c6953fb --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef ARMADA_COMMON_H +#define ARMADA_COMMON_H + +#include + +#include + +int marvell_get_io_dec_win_conf(struct dec_win_config **win, uint32_t *size); + +#endif /* ARMADA_COMMON_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h new file mode 100644 index 0000000..bc3e04f --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef BOARD_MARVELL_DEF_H +#define BOARD_MARVELL_DEF_H + +/* + * Required platform porting definitions common to all ARM + * development platforms + */ + +/* Size of cacheable stacks */ +#if IMAGE_BL1 +#if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +#else +# define PLATFORM_STACK_SIZE 0x440 +#endif +#elif IMAGE_BL2 +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif IMAGE_BL31 +# define PLATFORM_STACK_SIZE 0x400 +#elif IMAGE_BL32 +# define PLATFORM_STACK_SIZE 0x440 +#endif + +/* + * PLAT_MARVELL_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if IMAGE_BLE +# define PLAT_MARVELL_MMAP_ENTRIES 3 +#endif +#if IMAGE_BL1 +# if TRUSTED_BOARD_BOOT +# define PLAT_MARVELL_MMAP_ENTRIES 7 +# else +# define PLAT_MARVELL_MMAP_ENTRIES 6 +# endif /* TRUSTED_BOARD_BOOT */ +#endif +#if IMAGE_BL2 +# define PLAT_MARVELL_MMAP_ENTRIES 8 +#endif +#if IMAGE_BL31 +#define PLAT_MARVELL_MMAP_ENTRIES 5 +#endif + +/* + * Platform specific page table and MMU setup constants + */ +#if IMAGE_BL1 +#define MAX_XLAT_TABLES 4 +#elif IMAGE_BLE +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL2 +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL31 +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL32 +# define MAX_XLAT_TABLES 4 +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +#endif /* BOARD_MARVELL_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h new file mode 100644 index 0000000..1394c05 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_DEF_H +#define MARVELL_DEF_H + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions common to all MARVELL standard platforms + **************************************************************************** + */ +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define MARVELL_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define PLAT_MARVELL_NORTHB_COUNT 1 + +#define PLAT_MARVELL_CLUSTER_COUNT 1 + +#define MARVELL_CACHE_WRITEBACK_SHIFT 6 + +/* + * Macros mapping the MPIDR Affinity levels to MARVELL Platform Power levels. + * The power levels have a 1:1 mapping with the MPIDR affinity levels. + */ +#define MARVELL_PWR_LVL0 MPIDR_AFFLVL0 +#define MARVELL_PWR_LVL1 MPIDR_AFFLVL1 +#define MARVELL_PWR_LVL2 MPIDR_AFFLVL2 + +/* + * Macros for local power states in Marvell platforms encoded by State-ID field + * within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define MARVELL_LOCAL_STATE_RUN 0 +/* Local power state for retention. Valid only for CPU power domains */ +#define MARVELL_LOCAL_STATE_RET 1 +/* Local power state for OFF/power-down. + * Valid for CPU and cluster power domains + */ +#define MARVELL_LOCAL_STATE_OFF 2 + +/* This leaves a gap between end of DRAM and start of ROM block */ +#define MARVELL_TRUSTED_DRAM_SIZE 0x80000 /* 512 KB */ + +/* The first 4KB of Trusted SRAM are used as shared memory */ +#define MARVELL_SHARED_RAM_BASE PLAT_MARVELL_ATF_BASE +#define MARVELL_SHARED_RAM_SIZE 0x00001000 /* 4 KB */ + +/* The remaining Trusted SRAM is used to load the BL images */ +#define MARVELL_BL_RAM_BASE (MARVELL_SHARED_RAM_BASE + \ + MARVELL_SHARED_RAM_SIZE) +#define MARVELL_BL_RAM_SIZE (MARVELL_TRUSTED_DRAM_SIZE - \ + MARVELL_SHARED_RAM_SIZE) + +#define MARVELL_DRAM_BASE ULL(0x0) +#define MARVELL_DRAM_SIZE ULL(0x20000000) +#define MARVELL_DRAM_END (MARVELL_DRAM_BASE + \ + MARVELL_DRAM_SIZE - 1) + +#define MARVELL_IRQ_SEC_PHY_TIMER 29 + +#define MARVELL_IRQ_SEC_SGI_0 8 +#define MARVELL_IRQ_SEC_SGI_1 9 +#define MARVELL_IRQ_SEC_SGI_2 10 +#define MARVELL_IRQ_SEC_SGI_3 11 +#define MARVELL_IRQ_SEC_SGI_4 12 +#define MARVELL_IRQ_SEC_SGI_5 13 +#define MARVELL_IRQ_SEC_SGI_6 14 +#define MARVELL_IRQ_SEC_SGI_7 15 + +#define MARVELL_MAP_SHARED_RAM MAP_REGION_FLAT( \ + MARVELL_SHARED_RAM_BASE, \ + MARVELL_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MARVELL_MAP_DRAM MAP_REGION_FLAT( \ + MARVELL_DRAM_BASE, \ + MARVELL_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* + * The number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#if USE_COHERENT_MEM +#define MARVELL_BL_REGIONS 3 +#else +#define MARVELL_BL_REGIONS 2 +#endif + +#define MAX_MMAP_REGIONS (PLAT_MARVELL_MMAP_ENTRIES + \ + MARVELL_BL_REGIONS) + +#define MARVELL_CONSOLE_BAUDRATE 115200 + +/**************************************************************************** + * Required platform porting definitions common to all MARVELL std. platforms + **************************************************************************** + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * 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 MARVELL_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 MARVELL_LOCAL_STATE_OFF + + +#define PLATFORM_CORE_COUNT PLAT_MARVELL_CLUSTER_CORE_COUNT + +/* + * 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 (1 << MARVELL_CACHE_WRITEBACK_SHIFT) + + +/***************************************************************************** + * 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_MARVELL_TRUSTED_ROM_BASE +#define BL1_RO_LIMIT (PLAT_MARVELL_TRUSTED_ROM_BASE \ + + PLAT_MARVELL_TRUSTED_ROM_SIZE) +/* + * Put BL1 RW at the top of the Trusted SRAM. + */ +#define BL1_RW_BASE (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE - \ + PLAT_MARVELL_MAX_BL1_RW_SIZE) +#define BL1_RW_LIMIT (MARVELL_BL_RAM_BASE + MARVELL_BL_RAM_SIZE) + +/***************************************************************************** + * BL2 specific defines. + ***************************************************************************** + */ +/* + * Put BL2 just below BL31. + */ +#define BL2_BASE (BL31_BASE - PLAT_MARVELL_MAX_BL2_SIZE) +#define BL2_LIMIT BL31_BASE + +/***************************************************************************** + * BL31 specific defines. + ***************************************************************************** + */ +/* + * Put BL31 at the top of the Trusted SRAM. + */ +#define BL31_BASE (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE - \ + PLAT_MARVEL_MAX_BL31_SIZE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE +#define BL31_LIMIT (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE) + +/***************************************************************************** + * BL32 specific defines. + ***************************************************************************** + */ +#define BL32_BASE PLAT_MARVELL_TRUSTED_RAM_BASE +#define BL32_LIMIT (BL32_BASE + PLAT_MARVELL_TRUSTED_RAM_SIZE) + +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ + +#endif /* MARVELL_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h new file mode 100644 index 0000000..cb31481 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLAT_MARVELL_H +#define PLAT_MARVELL_H + +#include + +#include +#include +#include +#include + +/* + * Extern declarations common to Marvell standard platforms + */ +extern const mmap_region_t plat_marvell_mmap[]; + +#define MARVELL_CASSERT_MMAP \ + CASSERT((ARRAY_SIZE(plat_marvell_mmap) + MARVELL_BL_REGIONS) \ + <= MAX_MMAP_REGIONS, \ + assert_max_mmap_regions) + +/* + * Utility functions common to Marvell standard platforms + */ +void marvell_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, + uintptr_t coh_limit +#endif +); + +/* Console utility functions */ +void marvell_console_boot_init(void); +void marvell_console_boot_end(void); +void marvell_console_runtime_init(void); +void marvell_console_runtime_end(void); + +/* IO storage utility functions */ +void marvell_io_setup(void); + +/* Systimer utility function */ +void marvell_configure_sys_timer(void); + +/* Topology utility function */ +int marvell_check_mpidr(u_register_t mpidr); + +/* BL1 utility functions */ +void marvell_bl1_early_platform_setup(void); +void marvell_bl1_platform_setup(void); +void marvell_bl1_plat_arch_setup(void); + +/* BL2 utility functions */ +void marvell_bl2_early_platform_setup(meminfo_t *mem_layout); +void marvell_bl2_platform_setup(void); +void marvell_bl2_plat_arch_setup(void); +uint32_t marvell_get_spsr_for_bl32_entry(void); +uint32_t marvell_get_spsr_for_bl33_entry(void); + +/* BL31 utility functions */ +void marvell_bl31_early_platform_setup(void *from_bl2, + uintptr_t soc_fw_config, + uintptr_t hw_config, + void *plat_params_from_bl2); +void marvell_bl31_platform_setup(void); +void marvell_bl31_plat_runtime_setup(void); +void marvell_bl31_plat_arch_setup(void); + +/* FIP TOC validity check */ +int marvell_io_is_toc_valid(void); + +/* + * PSCI functionality + */ +void marvell_psci_arch_init(int idx); +void plat_marvell_system_reset(void); + +/* + * Optional functions required in Marvell standard platforms + */ +void plat_marvell_io_setup(void); +int plat_marvell_get_alt_image_source( + unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +unsigned int plat_marvell_calc_core_pos(u_register_t mpidr); + +void plat_marvell_interconnect_init(void); +void plat_marvell_interconnect_enter_coherency(void); + +const mmap_region_t *plat_marvell_get_mmap(void); + +uint32_t get_ref_clk(void); + +#endif /* PLAT_MARVELL_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h new file mode 100644 index 0000000..709d009 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef ARMADA_COMMON_H +#define ARMADA_COMMON_H + +#include +#include +#include +#include + +/* + * This struct supports skip image request + * detection_method: the method used to detect the request "signal". + * info: + * GPIO: + * detection_method: HIGH (pressed button), LOW (unpressed button), + * num (button mpp number). + * i2c: + * i2c_addr: the address of the i2c chosen. + * i2d_reg: the i2c register chosen. + * test: + * choose the DIE you picked the button in (AP or CP). + * in case of CP(cp_index = 0 if CP0, cp_index = 1 if CP1) + */ +struct skip_image { + enum { + GPIO, + I2C, + USER_DEFINED + } detection_method; + + struct { + struct { + int num; + enum { + HIGH, + LOW + } button_state; + + } gpio; + + struct { + int i2c_addr; + int i2c_reg; + } i2c; + + struct { + enum { + CP, + AP + } cp_ap; + int cp_index; + } test; + } info; +}; + +/* + * This struct supports SoC power off method + * type: the method used to power off the SoC + * cfg: + * PMIC_GPIO: + * pin_count: current GPIO pin number used for toggling the signal for + * notifying external PMIC + * info: holds the GPIOs information, CP GPIO should be used and + * all GPIOs should be within same GPIO config. register + * step_count: current step number to toggle the GPIO for PMIC + * seq: GPIO toggling values in sequence, each bit represents a GPIO. + * For example, bit0 represents first GPIO used for toggling + * the GPIO the last step is used to trigger the power off + * signal + * delay_ms: transition interval for the GPIO setting to take effect + * in unit of ms + */ +/* Max GPIO number used to notify PMIC to power off the SoC */ +#define PMIC_GPIO_MAX_NUMBER 8 +/* Max GPIO toggling steps in sequence to power off the SoC */ +#define PMIC_GPIO_MAX_TOGGLE_STEP 8 + +enum gpio_output_state { + GPIO_LOW = 0, + GPIO_HIGH +}; + +typedef struct gpio_info { + int cp_index; + int gpio_index; +} gpio_info_t; + +struct power_off_method { + enum { + PMIC_GPIO, + } type; + + struct { + struct { + int pin_count; + struct gpio_info info[PMIC_GPIO_MAX_NUMBER]; + int step_count; + uint32_t seq[PMIC_GPIO_MAX_TOGGLE_STEP]; + int delay_ms; + } gpio; + } cfg; +}; + +int marvell_gpio_config(void); +uint32_t marvell_get_io_win_gcr_target(int ap_idx); +uint32_t marvell_get_ccu_gcr_target(int ap_idx); + + +/* + * The functions below are defined as Weak and may be overridden + * in specific Marvell standard platform + */ +int marvell_get_amb_memory_map(struct addr_map_win **win, + uint32_t *size, uintptr_t base); +int marvell_get_io_win_memory_map(int ap_idx, struct addr_map_win **win, + uint32_t *size); +int marvell_get_iob_memory_map(struct addr_map_win **win, + uint32_t *size, uintptr_t base); +int marvell_get_ccu_memory_map(int ap_idx, struct addr_map_win **win, + uint32_t *size); +int system_power_off(void); + +#endif /* ARMADA_COMMON_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h new file mode 100644 index 0000000..7e90f5f --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef BOARD_MARVELL_DEF_H +#define BOARD_MARVELL_DEF_H + +/* + * Required platform porting definitions common to all ARM + * development platforms + */ + +/* Size of cacheable stacks */ +#if IMAGE_BL1 +#if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +#else +# define PLATFORM_STACK_SIZE 0x440 +#endif +#elif IMAGE_BL2 +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif IMAGE_BL31 +# define PLATFORM_STACK_SIZE 0x400 +#elif IMAGE_BL32 +# define PLATFORM_STACK_SIZE 0x440 +#endif + +/* + * PLAT_MARVELL_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if IMAGE_BLE +# define PLAT_MARVELL_MMAP_ENTRIES 3 +#endif +#if IMAGE_BL1 +# if TRUSTED_BOARD_BOOT +# define PLAT_MARVELL_MMAP_ENTRIES 7 +# else +# define PLAT_MARVELL_MMAP_ENTRIES 6 +# endif /* TRUSTED_BOARD_BOOT */ +#endif +#if IMAGE_BL2 +# define PLAT_MARVELL_MMAP_ENTRIES 8 +#endif +#if IMAGE_BL31 +#define PLAT_MARVELL_MMAP_ENTRIES 5 +#endif + +/* + * Platform specific page table and MMU setup constants + */ +#if IMAGE_BL1 +#define MAX_XLAT_TABLES 4 +#elif IMAGE_BLE +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL2 +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL31 +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL32 +# define MAX_XLAT_TABLES 4 +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +#endif /* BOARD_MARVELL_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h new file mode 100644 index 0000000..ff1d4a3 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef EFUSE_DEF_H +#define EFUSE_DEF_H + +#include + +#define MVEBU_AP_EFUSE_SRV_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x8) +#define EFUSE_SRV_CTRL_LD_SELECT_OFFS 6 +#define EFUSE_SRV_CTRL_LD_SELECT_MASK (1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS) + +#define MVEBU_AP_LD_EFUSE_BASE (MVEBU_AP_GEN_MGMT_BASE + 0xF00) +/* Bits [31:0] - 32 data bits total */ +#define MVEBU_AP_LDX_31_0_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE) +/* Bits [62:32] - 31 data bits total 32nd bit is parity for bits [62:0]*/ +#define MVEBU_AP_LDX_62_32_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x4) +/* Bits [94:63] - 32 data bits total */ +#define MVEBU_AP_LDX_94_63_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x8) +/* Bits [125:95] - 31 data bits total, 32nd bit is parity for bits [125:63] */ +#define MVEBU_AP_LDX_125_95_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0xC) +/* Bits [157:126] - 32 data bits total */ +#define MVEBU_AP_LDX_126_157_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x10) +/* Bits [188:158] - 31 data bits total, 32nd bit is parity for bits [188:126] */ +#define MVEBU_AP_LDX_188_158_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x14) +/* Bits [220:189] - 32 data bits total */ +#define MVEBU_AP_LDX_220_189_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x18) + +#endif /* EFUSE_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h new file mode 100644 index 0000000..1245b88 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_DEF_H +#define MARVELL_DEF_H + +#include + +#include +#include +#include +#include + +/****************************************************************************** + * Definitions common to all MARVELL standard platforms + *****************************************************************************/ + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define MARVELL_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + + +#define MARVELL_CACHE_WRITEBACK_SHIFT 6 + +/* + * Macros mapping the MPIDR Affinity levels to MARVELL Platform Power levels. + * The power levels have a 1:1 mapping with the MPIDR affinity levels. + */ +#define MARVELL_PWR_LVL0 MPIDR_AFFLVL0 +#define MARVELL_PWR_LVL1 MPIDR_AFFLVL1 +#define MARVELL_PWR_LVL2 MPIDR_AFFLVL2 + +/* + * Macros for local power states in Marvell platforms encoded by + * State-ID field within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define MARVELL_LOCAL_STATE_RUN 0 +/* Local power state for retention. Valid only for CPU power domains */ +#define MARVELL_LOCAL_STATE_RET 1 +/* + * Local power state for OFF/power-down. Valid for CPU + * and cluster power domains + */ +#define MARVELL_LOCAL_STATE_OFF 2 + +/* This leaves a gap between end of DRAM and start of ROM block */ +#define MARVELL_TRUSTED_DRAM_SIZE 0x80000 /* 512 KB */ + +/* The first 4KB of Trusted SRAM are used as shared memory */ +#define MARVELL_SHARED_RAM_BASE PLAT_MARVELL_ATF_BASE +#define MARVELL_SHARED_RAM_SIZE 0x00001000 /* 4 KB */ + +/* The remaining Trusted SRAM is used to load the BL images */ +#define MARVELL_BL_RAM_BASE (MARVELL_SHARED_RAM_BASE + \ + MARVELL_SHARED_RAM_SIZE) +#define MARVELL_BL_RAM_SIZE (MARVELL_TRUSTED_DRAM_SIZE - \ + MARVELL_SHARED_RAM_SIZE) +/* Non-shared DRAM */ +#define MARVELL_DRAM_BASE ULL(0x0) +#define MARVELL_DRAM_SIZE ULL(0x80000000) +#define MARVELL_DRAM_END (MARVELL_DRAM_BASE + \ + MARVELL_DRAM_SIZE - 1) + +#define MARVELL_IRQ_PIC0 28 +#define MARVELL_IRQ_SEC_PHY_TIMER 29 + +#define MARVELL_IRQ_SEC_SGI_0 8 +#define MARVELL_IRQ_SEC_SGI_1 9 +#define MARVELL_IRQ_SEC_SGI_2 10 +#define MARVELL_IRQ_SEC_SGI_3 11 +#define MARVELL_IRQ_SEC_SGI_4 12 +#define MARVELL_IRQ_SEC_SGI_5 13 +#define MARVELL_IRQ_SEC_SGI_6 14 +#define MARVELL_IRQ_SEC_SGI_7 15 + +#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 MARVELL_OPTEE_PAGEABLE_LOAD_BASE \ + (PLAT_MARVELL_TRUSTED_RAM_BASE + \ + PLAT_MARVELL_TRUSTED_RAM_SIZE - \ + MARVELL_OPTEE_PAGEABLE_LOAD_SIZE) +#define MARVELL_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 +#define MARVELL_OPTEE_PAGEABLE_LOAD_MEM \ + MAP_REGION_FLAT( \ + MARVELL_OPTEE_PAGEABLE_LOAD_BASE, \ + MARVELL_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 MARVELL_MAP_OPTEE_CORE_MEM MAP_REGION_FLAT( \ + BL32_BASE, \ + BL32_LIMIT - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* SPD_opteed */ + +#define MARVELL_MAP_SECURE_RAM MAP_REGION_FLAT( \ + MARVELL_SHARED_RAM_BASE, \ + MARVELL_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MARVELL_MAP_DRAM MAP_REGION_FLAT( \ + MARVELL_DRAM_BASE, \ + MARVELL_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* + * The number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#if USE_COHERENT_MEM +#define MARVELL_BL_REGIONS 3 +#else +#define MARVELL_BL_REGIONS 2 +#endif + +#define MAX_MMAP_REGIONS (PLAT_MARVELL_MMAP_ENTRIES + \ + MARVELL_BL_REGIONS) + +#define MARVELL_CONSOLE_BAUDRATE 115200 + +/****************************************************************************** + * Required platform porting definitions common to all MARVELL std. platforms + *****************************************************************************/ + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * 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 MARVELL_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 MARVELL_LOCAL_STATE_OFF + + +#define PLATFORM_CORE_COUNT PLAT_MARVELL_CORE_COUNT +#define PLAT_NUM_PWR_DOMAINS (PLAT_MARVELL_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +/* + * 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 (1 << MARVELL_CACHE_WRITEBACK_SHIFT) + + +/******************************************************************************* + * 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_MARVELL_TRUSTED_ROM_BASE +#define BL1_RO_LIMIT (PLAT_MARVELL_TRUSTED_ROM_BASE \ + + PLAT_MARVELL_TRUSTED_ROM_SIZE) +/* + * Put BL1 RW at the top of the Trusted SRAM. + */ +#define BL1_RW_BASE (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE - \ + PLAT_MARVELL_MAX_BL1_RW_SIZE) +#define BL1_RW_LIMIT (MARVELL_BL_RAM_BASE + MARVELL_BL_RAM_SIZE) + +/******************************************************************************* + * BLE specific defines. + ******************************************************************************/ +#define BLE_BASE PLAT_MARVELL_SRAM_BASE +#define BLE_LIMIT PLAT_MARVELL_SRAM_END + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ +/* + * Put BL2 just below BL31. + */ +#define BL2_BASE (BL31_BASE - PLAT_MARVELL_MAX_BL2_SIZE) +#define BL2_LIMIT BL31_BASE + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted SRAM. + */ +#define BL31_BASE (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE - \ + PLAT_MARVEL_MAX_BL31_SIZE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE +#define BL31_LIMIT (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE) + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#define BL32_BASE PLAT_MARVELL_TRUSTED_RAM_BASE +#define BL32_LIMIT (BL32_BASE + PLAT_MARVELL_TRUSTED_RAM_SIZE) + +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ + +#endif /* MARVELL_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h new file mode 100644 index 0000000..5d805a7 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLAT_MARVELL_H +#define PLAT_MARVELL_H + +#include + +#include +#include +#include +#include + +/* + * Extern declarations common to Marvell standard platforms + */ +extern const mmap_region_t plat_marvell_mmap[]; + +#define MARVELL_CASSERT_MMAP \ + CASSERT((ARRAY_SIZE(plat_marvell_mmap) + MARVELL_BL_REGIONS) \ + <= MAX_MMAP_REGIONS, \ + assert_max_mmap_regions) + +struct marvell_bl31_params { + 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; +}; + +/* + * Utility functions common to Marvell standard platforms + */ +void marvell_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, + uintptr_t coh_limit +#endif +); + +/* Console utility functions */ +void marvell_console_boot_init(void); +void marvell_console_boot_end(void); +void marvell_console_runtime_init(void); +void marvell_console_runtime_end(void); + +/* IO storage utility functions */ +void marvell_io_setup(void); + +/* Systimer utility function */ +void marvell_configure_sys_timer(void); + +/* Topology utility function */ +int marvell_check_mpidr(u_register_t mpidr); + +/* BLE utility functions */ +int ble_plat_setup(int *skip); +void plat_marvell_dram_update_topology(void); +void ble_plat_pcie_ep_setup(void); +struct pci_hw_cfg *plat_get_pcie_hw_data(void); + +/* BL1 utility functions */ +void marvell_bl1_early_platform_setup(void); +void marvell_bl1_platform_setup(void); +void marvell_bl1_plat_arch_setup(void); + +/* BL2 utility functions */ +void marvell_bl2_early_platform_setup(meminfo_t *mem_layout); +void marvell_bl2_platform_setup(void); +void marvell_bl2_plat_arch_setup(void); +uint32_t marvell_get_spsr_for_bl32_entry(void); +uint32_t marvell_get_spsr_for_bl33_entry(void); + +/* BL31 utility functions */ +void marvell_bl31_early_platform_setup(void *from_bl2, + uintptr_t soc_fw_config, + uintptr_t hw_config, + void *plat_params_from_bl2); +void marvell_bl31_platform_setup(void); +void marvell_bl31_plat_runtime_setup(void); +void marvell_bl31_plat_arch_setup(void); + +/* Power management config to power off the SoC */ +void *plat_marvell_get_pm_cfg(void); + +/* Check if MSS AP CM3 firmware contains PM support */ +_Bool is_pm_fw_running(void); + +/* Bootrom image recovery utility functions */ +void *plat_marvell_get_skip_image_data(void); + +/* FIP TOC validity check */ +int marvell_io_is_toc_valid(void); + +/* + * PSCI functionality + */ +void marvell_psci_arch_init(int ap_idx); +void plat_marvell_system_reset(void); + +/* + * Miscellaneous platform SMC routines + */ +#ifdef MVEBU_PMU_IRQ_WA +void mvebu_pmu_interrupt_enable(void); +void mvebu_pmu_interrupt_disable(void); +#endif + +/* + * Optional functions required in Marvell standard platforms + */ +void plat_marvell_io_setup(void); +int plat_marvell_get_alt_image_source( + unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +unsigned int plat_marvell_calc_core_pos(u_register_t mpidr); + +const mmap_region_t *plat_marvell_get_mmap(void); +void marvell_ble_prepare_exit(void); +void marvell_exit_bootrom(uintptr_t base); + +int plat_marvell_early_cpu_powerdown(void); +int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info); + +#endif /* PLAT_MARVELL_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h new file mode 100644 index 0000000..a954914 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLAT_PM_TRACE_H +#define PLAT_PM_TRACE_H + +/* + * PM Trace is for Debug purpose only!!! + * It should not be enabled during System Run time + */ +#undef PM_TRACE_ENABLE + + +/* trace entry time */ +struct pm_trace_entry { + /* trace entry time stamp */ + unsigned int timestamp; + + /* trace info + * [16-31] - API Trace Id + * [00-15] - API Step Id + */ + unsigned int trace_info; +}; + +struct pm_trace_ctrl { + /* trace pointer - points to next free entry in trace cyclic queue */ + unsigned int trace_pointer; + + /* trace count - number of entries in the queue, clear upon read */ + unsigned int trace_count; +}; + +/* trace size definition */ +#define AP_MSS_ATF_CORE_INFO_SIZE (256) +#define AP_MSS_ATF_CORE_ENTRY_SIZE (8) +#define AP_MSS_ATF_TRACE_SIZE_MASK (0xFF) + +/* trace address definition */ +#define AP_MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110) + +#define AP_MSS_ATF_CORE_0_CTRL_BASE (MVEBU_REGS_BASE_MASK + 0x520140) +#define AP_MSS_ATF_CORE_1_CTRL_BASE (MVEBU_REGS_BASE_MASK + 0x520150) +#define AP_MSS_ATF_CORE_2_CTRL_BASE (MVEBU_REGS_BASE_MASK + 0x520160) +#define AP_MSS_ATF_CORE_3_CTRL_BASE (MVEBU_REGS_BASE_MASK + 0x520170) +#define AP_MSS_ATF_CORE_CTRL_BASE (AP_MSS_ATF_CORE_0_CTRL_BASE) + +#define AP_MSS_ATF_CORE_0_INFO_BASE (MVEBU_REGS_BASE_MASK + 0x5201C0) +#define AP_MSS_ATF_CORE_0_INFO_TRACE (MVEBU_REGS_BASE_MASK + 0x5201C4) +#define AP_MSS_ATF_CORE_1_INFO_BASE (MVEBU_REGS_BASE_MASK + 0x5209C0) +#define AP_MSS_ATF_CORE_1_INFO_TRACE (MVEBU_REGS_BASE_MASK + 0x5209C4) +#define AP_MSS_ATF_CORE_2_INFO_BASE (MVEBU_REGS_BASE_MASK + 0x5211C0) +#define AP_MSS_ATF_CORE_2_INFO_TRACE (MVEBU_REGS_BASE_MASK + 0x5211C4) +#define AP_MSS_ATF_CORE_3_INFO_BASE (MVEBU_REGS_BASE_MASK + 0x5219C0) +#define AP_MSS_ATF_CORE_3_INFO_TRACE (MVEBU_REGS_BASE_MASK + 0x5219C4) +#define AP_MSS_ATF_CORE_INFO_BASE (AP_MSS_ATF_CORE_0_INFO_BASE) + +/* trace info definition */ +#define TRACE_PWR_DOMAIN_OFF (0x10000) +#define TRACE_PWR_DOMAIN_SUSPEND (0x20000) +#define TRACE_PWR_DOMAIN_SUSPEND_FINISH (0x30000) +#define TRACE_PWR_DOMAIN_ON (0x40000) +#define TRACE_PWR_DOMAIN_ON_FINISH (0x50000) + +#define TRACE_PWR_DOMAIN_ON_MASK (0xFF) + +#ifdef PM_TRACE_ENABLE + +/* trace API definition */ +void pm_core_0_trace(unsigned int trace); +void pm_core_1_trace(unsigned int trace); +void pm_core_2_trace(unsigned int trace); +void pm_core_3_trace(unsigned int trace); + +typedef void (*core_trace_func)(unsigned int); + +extern core_trace_func funcTbl[PLATFORM_CORE_COUNT]; + +#define PM_TRACE(trace) funcTbl[plat_my_core_pos()](trace) + +#else + +#define PM_TRACE(trace) + +#endif + +/******************************************************************************* + * pm_trace_add + * + * DESCRIPTION: Add PM trace + ****************************************************************************** + */ +void pm_trace_add(unsigned int trace, unsigned int core); + +#endif /* PLAT_PM_TRACE_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S b/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S new file mode 100644 index 0000000..b0a909b --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#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_MARVELL_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MARVELL_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_MARVELL_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MARVELL_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/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S b/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S new file mode 100644 index 0000000..bfe2d41 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_MACROS_S +#define MARVELL_MACROS_S + +#include +#include +#include +#include +#include + +/* + * These Macros are required by ATF + */ + +.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", "" + +#ifdef USE_CCI +/* Applicable only to GICv3 with SRE enabled */ +icc_regs: + .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", "" +#endif +/* Registers common to both GICv2 and GICv3 */ +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + /* --------------------------------------------- + * 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 marvell_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 + +#ifdef USE_CCI + /* 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 +#endif + 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 + bl asm_print_hex + + 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 + + +.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 +#ifdef USE_CCI + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_MARVELL_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MARVELL_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_MARVELL_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MARVELL_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 +#endif + .endm + + +#endif /* MARVELL_MACROS_S */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h b/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h new file mode 100644 index 0000000..78b5331 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_PLAT_PRIV_H +#define MARVELL_PLAT_PRIV_H + +#include + +/***************************************************************************** + * Function and variable prototypes + ***************************************************************************** + */ +void plat_delay_timer_init(void); + +uint64_t mvebu_get_dram_size(uint64_t ap_base_addr); + +/* + * GIC operation, mandatory functions required in Marvell standard platforms + */ +void plat_marvell_gic_driver_init(void); +void plat_marvell_gic_init(void); +void plat_marvell_gic_cpuif_enable(void); +void plat_marvell_gic_cpuif_disable(void); +void plat_marvell_gic_pcpu_init(void); +void plat_marvell_gic_irq_save(void); +void plat_marvell_gic_irq_restore(void); +void plat_marvell_gic_irq_pcpu_save(void); +void plat_marvell_gic_irq_pcpu_restore(void); + +#endif /* MARVELL_PLAT_PRIV_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h b/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h new file mode 100644 index 0000000..8f16607 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_PM_H +#define MARVELL_PM_H + +#define MVEBU_MAILBOX_MAGIC_NUM PLAT_MARVELL_MAILBOX_MAGIC_NUM +#define MVEBU_MAILBOX_SUSPEND_STATE 0xb007de7c + +/* Mailbox entry indexes */ +/* Magic number for validity check */ +#define MBOX_IDX_MAGIC 0 +/* Recovery from suspend entry point */ +#define MBOX_IDX_SEC_ADDR 1 +/* Suspend state magic number */ +#define MBOX_IDX_SUSPEND_MAGIC 2 +/* Recovery jump address for ROM bypass */ +#define MBOX_IDX_ROM_EXIT_ADDR 3 +/* BLE execution start counter value */ +#define MBOX_IDX_START_CNT 4 + +#endif /* MARVELL_PM_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h b/arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h new file mode 100644 index 0000000..35a0200 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_H +#define MVEBU_H + +/* Use this functions only when printf is allowed */ +#define debug_enter() VERBOSE("----> Enter %s\n", __func__) +#define debug_exit() VERBOSE("<---- Exit %s\n", __func__) + +/* Macro for testing alignment. Positive if number is NOT aligned */ +#define IS_NOT_ALIGN(number, align) ((number) & ((align) - 1)) + +/* Macro for alignment up. For example, ALIGN_UP(0x0330, 0x20) = 0x0340 */ +#define ALIGN_UP(number, align) (((number) & ((align) - 1)) ? \ + (((number) + (align)) & ~((align)-1)) : (number)) + +/* Macro for testing whether a number is a power of 2. Positive if so */ +#define IS_POWER_OF_2(number) ((number) != 0 && \ + (((number) & ((number) - 1)) == 0)) + +/* + * Macro for ronding up to next power of 2 + * it is done by count leading 0 (clz assembly opcode) and see msb set bit. + * then you can shift it left and get number which power of 2 + * Note: this Macro is for 32 bit number + */ +#define ROUND_UP_TO_POW_OF_2(number) (1 << \ + (32 - __builtin_clz((number) - 1))) + +#define _1MB_ (1024ULL * 1024ULL) +#define _1GB_ (_1MB_ * 1024ULL) +#define _2GB_ (2 * _1GB_) + +#endif /* MVEBU_H */ diff --git a/arm-trusted-firmware/include/services/arm_arch_svc.h b/arm-trusted-firmware/include/services/arm_arch_svc.h new file mode 100644 index 0000000..42f62f5 --- /dev/null +++ b/arm-trusted-firmware/include/services/arm_arch_svc.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018-2022, 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_ARCH_WORKAROUND_3 U(0x80003FFF) + +#define ARM_ARCH_SVC_CALL_COUNT U(0x8000ff00) +#define ARM_ARCH_SVC_UID U(0x8000ff01) +#define ARM_ARCH_SVC_VERSION U(0x8000ff03) + +#define ARM_ARCH_SVC_COUNT U(7) + +#define ARM_ARCH_SVC_VERSION_MAJOR U(0) +#define ARM_ARCH_SVC_VERSION_MINOR U(1) + +#define SMCCC_GET_SOC_VERSION U(0) +#define SMCCC_GET_SOC_REVISION U(1) + +#endif /* ARM_ARCH_SVC_H */ diff --git a/arm-trusted-firmware/include/services/ffa_svc.h b/arm-trusted-firmware/include/services/ffa_svc.h new file mode 100644 index 0000000..9a7c489 --- /dev/null +++ b/arm-trusted-firmware/include/services/ffa_svc.h @@ -0,0 +1,212 @@ +/* + * 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(0x87) +#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(1) +#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) /* Legacy FF-A v1.0 */ +#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) /* Legacy FF-A v1.0 */ +#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_NORMAL_WORLD_RESUME U(0x7C) + +/* FF-A v1.1 */ +#define FFA_FNUM_NOTIFICATION_BITMAP_CREATE U(0x7D) +#define FFA_FNUM_NOTIFICATION_BITMAP_DESTROY U(0x7E) +#define FFA_FNUM_NOTIFICATION_BIND U(0x7F) +#define FFA_FNUM_NOTIFICATION_UNBIND U(0x80) +#define FFA_FNUM_NOTIFICATION_SET U(0x81) +#define FFA_FNUM_NOTIFICATION_GET U(0x82) +#define FFA_FNUM_NOTIFICATION_INFO_GET U(0x83) +#define FFA_FNUM_RX_ACQUIRE U(0x84) +#define FFA_FNUM_SPM_ID_GET U(0x85) +#define FFA_FNUM_MSG_SEND2 U(0x86) +#define FFA_FNUM_SECONDARY_EP_REGISTER U(0x87) + +/* 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_SEND2 FFA_FID(SMC_32, FFA_FNUM_MSG_SEND2) +#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) +#define FFA_NOTIFICATION_BITMAP_CREATE \ + FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BITMAP_CREATE) +#define FFA_NOTIFICATION_BITMAP_DESTROY \ + FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BITMAP_DESTROY) +#define FFA_NOTIFICATION_BIND FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BIND) +#define FFA_NOTIFICATION_UNBIND FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_UNBIND) +#define FFA_NOTIFICATION_SET FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_SET) +#define FFA_NOTIFICATION_GET FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_GET) +#define FFA_NOTIFICATION_INFO_GET \ + FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_INFO_GET) +#define FFA_SPM_ID_GET FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET) +#define FFA_NORMAL_WORLD_RESUME FFA_FID(SMC_32, FFA_FNUM_NORMAL_WORLD_RESUME) + +/* 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) +#define FFA_NOTIFICATION_INFO_GET_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET) + +/* + * 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/arm-trusted-firmware/include/services/pci_svc.h b/arm-trusted-firmware/include/services/pci_svc.h new file mode 100644 index 0000000..664a742 --- /dev/null +++ b/arm-trusted-firmware/include/services/pci_svc.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PCI_SVC_H +#define PCI_SVC_H + +#include + +/* SMCCC PCI platform functions */ +#define SMC_PCI_VERSION U(0x84000130) +#define SMC_PCI_FEATURES U(0x84000131) +#define SMC_PCI_READ U(0x84000132) +#define SMC_PCI_WRITE U(0x84000133) +#define SMC_PCI_SEG_INFO U(0x84000134) + +#define is_pci_fid(_fid) (((_fid) >= SMC_PCI_VERSION) && \ + ((_fid) <= SMC_PCI_SEG_INFO)) + +uint64_t pci_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); + +#define PCI_ADDR_FUN(dev) ((dev) & U(0x7)) +#define PCI_ADDR_DEV(dev) (((dev) >> U(3)) & U(0x001F)) +#define PCI_ADDR_BUS(dev) (((dev) >> U(8)) & U(0x00FF)) +#define PCI_ADDR_SEG(dev) (((dev) >> U(16)) & U(0xFFFF)) +#define PCI_OFFSET_MASK U(0xFFF) +typedef union { + struct { + uint16_t minor; + uint16_t major; + } __packed; + uint32_t val; +} pcie_version; + +/* + * platforms are responsible for providing implementations of these + * three functions in a manner which conforms to the Arm PCI Configuration + * Space Access Firmware Interface (DEN0115) and the PCIe specification's + * sections on PCI configuration access. See the rpi4_pci_svc.c example. + */ +uint32_t pci_read_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t *val); +uint32_t pci_write_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t val); +uint32_t pci_get_bus_for_seg(uint32_t seg, uint32_t *bus_range, uint32_t *nseg); + +/* Return codes for Arm PCI Config Space Access Firmware SMC calls */ +#define SMC_PCI_CALL_SUCCESS U(0) +#define SMC_PCI_CALL_NOT_SUPPORTED -1 +#define SMC_PCI_CALL_INVAL_PARAM -2 +#define SMC_PCI_CALL_NOT_IMPL -3 + +#define SMC_PCI_SZ_8BIT U(1) +#define SMC_PCI_SZ_16BIT U(2) +#define SMC_PCI_SZ_32BIT U(4) + +#endif /* PCI_SVC_H */ diff --git a/arm-trusted-firmware/include/services/rmmd_svc.h b/arm-trusted-firmware/include/services/rmmd_svc.h new file mode 100644 index 0000000..2fbdddd --- /dev/null +++ b/arm-trusted-firmware/include/services/rmmd_svc.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RMMD_SVC_H +#define RMMD_SVC_H + +#include +#include + +/* Construct RMM fastcall std FID from function number */ +#define RMM_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)) + +/* The macros below are used to identify RMI calls from the SMC function ID */ +#define RMI_FNUM_MIN_VALUE U(0x150) +#define RMI_FNUM_MAX_VALUE U(0x18F) + +#define is_rmi_fid(fid) __extension__ ({ \ + __typeof__(fid) _fid = (fid); \ + ((GET_SMC_NUM(_fid) >= RMI_FNUM_MIN_VALUE) && \ + (GET_SMC_NUM(_fid) <= RMI_FNUM_MAX_VALUE) && \ + (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST) && \ + (GET_SMC_CC(_fid) == SMC_64) && \ + (GET_SMC_OEN(_fid) == OEN_STD_START) && \ + ((_fid & 0x00FE0000) == 0U)); }) + +/* + * RMI_FNUM_REQ_COMPLETE is the only function in the RMI rnage that originates + * from the Realm world and is handled by the RMMD. The RMI functions are + * always invoked by the Normal world, forwarded by RMMD and handled by the + * RMM + */ +#define RMI_FNUM_REQ_COMPLETE U(0x18F) +#define RMMD_RMI_REQ_COMPLETE RMM_FID(SMC_64, RMI_FNUM_REQ_COMPLETE) + +/* The SMC in the range 0x8400 0190 - 0x8400 01AF are reserved for RSIs.*/ + +/* + * EL3 - RMM SMCs used for requesting RMMD services. These SMCs originate in Realm + * world and return to Realm world. + * + * These are allocated from 0x8400 01B0 - 0x8400 01CF in the RMM Service range. + */ +#define RMMD_EL3_FNUM_MIN_VALUE U(0x1B0) +#define RMMD_EL3_FNUM_MAX_VALUE U(0x1CF) + +/* The macros below are used to identify GTSI calls from the SMC function ID */ +#define is_rmmd_el3_fid(fid) __extension__ ({ \ + __typeof__(fid) _fid = (fid); \ + ((GET_SMC_NUM(_fid) >= RMMD_EL3_FNUM_MIN_VALUE) &&\ + (GET_SMC_NUM(_fid) <= RMMD_EL3_FNUM_MAX_VALUE) &&\ + (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST) && \ + (GET_SMC_CC(_fid) == SMC_64) && \ + (GET_SMC_OEN(_fid) == OEN_STD_START) && \ + ((_fid & 0x00FE0000) == 0U)); }) + +/* RMMD Service Function NUmbers */ +#define GTSI_DELEGATE U(0x1B0) +#define GTSI_UNDELEGATE U(0x1B1) +#define ATTEST_GET_REALM_KEY U(0x1B2) +#define ATTEST_GET_PLAT_TOKEN U(0x1B3) + +#define RMMD_GTSI_DELEGATE RMM_FID(SMC_64, GTSI_DELEGATE) +#define RMMD_GTSI_UNDELEGATE RMM_FID(SMC_64, GTSI_UNDELEGATE) + +/* Return error codes from RMM-EL3 SMCs */ +#define RMMD_OK 0 +#define RMMD_ERR_BAD_ADDR -2 +#define RMMD_ERR_BAD_PAS -3 +#define RMMD_ERR_NOMEM -4 +#define RMMD_ERR_INVAL -5 +#define RMMD_ERR_UNK -6 + +/* + * Retrieve Platform token from EL3. + * The arguments to this SMC are : + * arg0 - Function ID. + * arg1 - Platform attestation token buffer Physical address. (The challenge + * object is passed in this buffer.) + * arg2 - Platform attestation token buffer size (in bytes). + * arg3 - Challenge object size (in bytes). It has be one of the defined SHA hash + * sizes. + * The return arguments are : + * ret0 - Status / error. + * ret1 - Size of the platform token if successful. + */ +#define RMMD_ATTEST_GET_PLAT_TOKEN RMM_FID(SMC_64, ATTEST_GET_PLAT_TOKEN) + +/* Acceptable SHA sizes for Challenge object */ +#define SHA256_DIGEST_SIZE 32U +#define SHA384_DIGEST_SIZE 48U +#define SHA512_DIGEST_SIZE 64U + +/* + * Retrieve Realm attestation key from EL3. Only P-384 ECC curve key is + * supported. The arguments to this SMC are : + * arg0 - Function ID. + * arg1 - Realm attestation key buffer Physical address. + * arg2 - Realm attestation key buffer size (in bytes). + * arg3 - The type of the elliptic curve to which the requested + * attestation key belongs to. The value should be one of the + * defined curve types. + * The return arguments are : + * ret0 - Status / error. + * ret1 - Size of the realm attestation key if successful. + */ +#define RMMD_ATTEST_GET_REALM_KEY RMM_FID(SMC_64, ATTEST_GET_REALM_KEY) + +/* ECC Curve types for attest key generation */ +#define ATTEST_KEY_CURVE_ECC_SECP384R1 0 + + +#ifndef __ASSEMBLER__ +#include + +int rmmd_setup(void); +uint64_t rmmd_rmi_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags); + +uint64_t rmmd_rmm_el3_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 /* RMMD_SVC_H */ diff --git a/arm-trusted-firmware/include/services/sdei.h b/arm-trusted-firmware/include/services/sdei.h new file mode 100644 index 0000000..063ed6f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/services/sdei_flags.h b/arm-trusted-firmware/include/services/sdei_flags.h new file mode 100644 index 0000000..d1308f8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/services/spm_core_manifest.h b/arm-trusted-firmware/include/services/spm_core_manifest.h new file mode 100644 index 0000000..453b21c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/services/spm_mm_partition.h b/arm-trusted-firmware/include/services/spm_mm_partition.h new file mode 100644 index 0000000..ad5ceef --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/services/spm_mm_svc.h b/arm-trusted-firmware/include/services/spm_mm_svc.h new file mode 100644 index 0000000..3148beb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/services/spmd_svc.h b/arm-trusted-firmware/include/services/spmd_svc.h new file mode 100644 index 0000000..1e7e6aa --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/services/std_svc.h b/arm-trusted-firmware/include/services/std_svc.h new file mode 100644 index 0000000..b0614fb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/services/trng_svc.h b/arm-trusted-firmware/include/services/trng_svc.h new file mode 100644 index 0000000..ed4d557 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/services/trp/platform_trp.h b/arm-trusted-firmware/include/services/trp/platform_trp.h new file mode 100644 index 0000000..b34da85 --- /dev/null +++ b/arm-trusted-firmware/include/services/trp/platform_trp.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_TRP_H +#define PLATFORM_TRP_H + +/******************************************************************************* + * Mandatory TRP functions (only if platform contains a TRP) + ******************************************************************************/ +void trp_early_platform_setup(void); + +#endif /* PLATFORM_TRP_H */ diff --git a/arm-trusted-firmware/include/tools_share/dualroot_oid.h b/arm-trusted-firmware/include/tools_share/dualroot_oid.h new file mode 100644 index 0000000..3e88a6d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/tools_share/firmware_encrypted.h b/arm-trusted-firmware/include/tools_share/firmware_encrypted.h new file mode 100644 index 0000000..7ca634f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/tools_share/firmware_image_package.h b/arm-trusted-firmware/include/tools_share/firmware_image_package.h new file mode 100644 index 0000000..bd5b14b --- /dev/null +++ b/arm-trusted-firmware/include/tools_share/firmware_image_package.h @@ -0,0 +1,104 @@ +/* + * 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} } +#define UUID_REALM_MONITOR_MGMT_FIRMWARE \ + {{0x6c, 0x07, 0x62, 0xa6}, {0x12, 0xf2}, {0x4b, 0x56}, 0x92, 0xcb, {0xba, 0x8f, 0x63, 0x36, 0x06, 0xd9} } +/* 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/arm-trusted-firmware/include/tools_share/sptool.h b/arm-trusted-firmware/include/tools_share/sptool.h new file mode 100644 index 0000000..53668e0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/tools_share/tbbr_oid.h b/arm-trusted-firmware/include/tools_share/tbbr_oid.h new file mode 100644 index 0000000..52b43ab --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/include/tools_share/uuid.h b/arm-trusted-firmware/include/tools_share/uuid.h new file mode 100644 index 0000000..2ced3a3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c b/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c new file mode 100644 index 0000000..ea8e2bb --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Form ABI specifications: + * int __aeabi_idiv(int numerator, int denominator); + * unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator); + * + * typedef struct { int quot; int rem; } idiv_return; + * typedef struct { unsigned quot; unsigned rem; } uidiv_return; + * + * __value_in_regs idiv_return __aeabi_idivmod(int numerator, + * int *denominator); + * __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator, + * unsigned denominator); + */ + +/* struct qr - stores quotient/remainder to handle divmod EABI interfaces. */ +struct qr { + unsigned int q; /* computed quotient */ + unsigned int r; /* computed remainder */ + unsigned int q_n; /* specifies if quotient shall be negative */ + unsigned int r_n; /* specifies if remainder shall be negative */ +}; + +static void uint_div_qr(unsigned int numerator, unsigned int denominator, + struct qr *qr); + +/* returns in R0 and R1 by tail calling an asm function */ +unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator); + +unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator); + +/* returns in R0 and R1 by tail calling an asm function */ +signed int __aeabi_idivmod(signed int numerator, signed int denominator); + +signed int __aeabi_idiv(signed int numerator, signed int denominator); + +/* + * __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator) + * Numerator and Denominator are received in R0 and R1. + * Where __ste_idivmod_ret_t is returned in R0 and R1. + * + * __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator, + * unsigned denominator) + * Numerator and Denominator are received in R0 and R1. + * Where __ste_uidivmod_ret_t is returned in R0 and R1. + */ +#ifdef __GNUC__ +signed int ret_idivmod_values(signed int quotient, signed int remainder); +unsigned int ret_uidivmod_values(unsigned int quotient, unsigned int remainder); +#else +#error "Compiler not supported" +#endif + +static void division_qr(unsigned int n, unsigned int p, struct qr *qr) +{ + unsigned int i = 1, q = 0; + + if (p == 0) { + qr->r = 0xFFFFFFFF; /* division by 0 */ + return; + } + + while ((p >> 31) == 0) { + i = i << 1; /* count the max division steps */ + p = p << 1; /* increase p until it has maximum size*/ + } + + while (i > 0) { + q = q << 1; /* write bit in q at index (size-1) */ + if (n >= p) { + n -= p; + q++; + } + p = p >> 1; /* decrease p */ + i = i >> 1; /* decrease remaining size in q */ + } + qr->r = n; + qr->q = q; +} + +static void uint_div_qr(unsigned int numerator, unsigned int denominator, + struct qr *qr) +{ + division_qr(numerator, denominator, qr); + + /* negate quotient and/or remainder according to requester */ + if (qr->q_n) + qr->q = -qr->q; + if (qr->r_n) + qr->r = -qr->r; +} + +unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return qr.q; +} + +unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return ret_uidivmod_values(qr.q, qr.r); +} + +signed int __aeabi_idiv(signed int numerator, signed int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return qr.q; +} + +signed int __aeabi_idivmod(signed int numerator, signed int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return ret_idivmod_values(qr.q, qr.r); +} diff --git a/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S b/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S new file mode 100644 index 0000000..6915dcd --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * EABI wrappers from the udivmod and idivmod functions + */ + + .globl ret_uidivmod_values + .globl ret_idivmod_values + +/* + * signed ret_idivmod_values(signed quot, signed rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +func ret_idivmod_values + bx lr +endfunc ret_idivmod_values + +/* + * unsigned ret_uidivmod_values(unsigned quot, unsigned rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +func ret_uidivmod_values + bx lr +endfunc ret_uidivmod_values diff --git a/arm-trusted-firmware/lib/aarch32/armclang_printf.S b/arm-trusted-firmware/lib/aarch32/armclang_printf.S new file mode 100644 index 0000000..2b87bf7 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/armclang_printf.S @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018, 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 +__1printf: +__2printf: + b printf +endfunc __0printf diff --git a/arm-trusted-firmware/lib/aarch32/cache_helpers.S b/arm-trusted-firmware/lib/aarch32/cache_helpers.S new file mode 100644 index 0000000..13d1872 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/cache_helpers.S @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2016-2021, 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, coproc, opc1, CRn, CRm, opc2 + /* Exit early if size is zero */ + cmp r1, #0 + beq exit_loop_\op + dcache_line_size r2, r3 + add r1, r0, r1 + sub r3, r2, #1 + bic r0, r0, r3 +loop_\op: + stcopr r0, \coproc, \opc1, \CRn, \CRm, \opc2 + add r0, r0, r2 + cmp r0, r1 + blo loop_\op + dsb sy +exit_loop_\op: + bx lr +.endm + + /* ------------------------------------------ + * Clean+Invalidate from base address till + * size. 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +func flush_dcache_range + do_dcache_maintenance_by_mva cimvac, DCCIMVAC +endfunc flush_dcache_range + + /* ------------------------------------------ + * Clean from base address till size. + * 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +func clean_dcache_range + do_dcache_maintenance_by_mva cmvac, DCCMVAC +endfunc clean_dcache_range + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +func inv_dcache_range + do_dcache_maintenance_by_mva imvac, DCIMVAC +endfunc inv_dcache_range + + /* ---------------------------------------------------------------- + * Data cache operations by set/way to the level specified + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * r1: The cache level to begin operation from + * r2: clidr_el1 + * r3: The last cache level to operate on + * and will carry out the operation on each data cache from level 0 + * to the level in r3 in sequence + * + * The dcsw_op macro sets up the r2 and r3 parameters based on + * clidr_el1 cache information before invoking the main function + * ---------------------------------------------------------------- + */ + + .macro dcsw_op shift, fw, ls + ldcopr r2, CLIDR + ubfx r3, r2, \shift, \fw + lsl r3, r3, \ls + mov r1, #0 + b do_dcsw_op + .endm + +func do_dcsw_op + push {r4-r12, lr} + ldcopr r8, ID_MMFR4 // stash FEAT_CCIDX identifier in r8 + ubfx r8, r8, #ID_MMFR4_CCIDX_SHIFT, #ID_MMFR4_CCIDX_LENGTH + adr r11, dcsw_loop_table // compute cache op based on the operation type + add r6, r11, r0, lsl #3 // cache op is 2x32-bit instructions +loop1: + add r10, r1, r1, LSR #1 // Work out 3x current cache level + mov r12, r2, LSR r10 // extract cache type bits from clidr + and r12, r12, #7 // mask the bits for current cache only + cmp r12, #2 // see what cache we have at this level + blo level_done // no cache or only instruction cache at this level + + stcopr r1, CSSELR // select current cache level in csselr + isb // isb to sych the new cssr&csidr + ldcopr r12, CCSIDR // read the new ccsidr + and r10, r12, #7 // extract the length of the cache lines + add r10, r10, #4 // add 4 (r10 = line length offset) + + cmp r8, #0 // check for FEAT_CCIDX for Associativity + beq 1f + ubfx r4, r12, #3, #21 // r4 = associativity CCSIDR[23:3] + b 2f +1: + ubfx r4, r12, #3, #10 // r4 = associativity CCSIDR[12:3] +2: + clz r5, r4 // r5 = the bit position of the way size increment + mov r9, r4 // r9 working copy of the aligned max way number + +loop2: + cmp r8, #0 // check for FEAT_CCIDX for NumSets + beq 3f + ldcopr r12, CCSIDR2 // FEAT_CCIDX numsets is in CCSIDR2 + ubfx r7, r12, #0, #24 // r7 = numsets CCSIDR2[23:0] + b loop3 +3: + ubfx r7, r12, #13, #15 // r7 = numsets CCSIDR[27:13] +loop3: + orr r0, r1, r9, LSL r5 // factor in the way number and cache level into r0 + orr r0, r0, r7, LSL r10 // factor in the set number + + blx r6 + subs r7, r7, #1 // decrement the set number + bhs loop3 + subs r9, r9, #1 // decrement the way number + bhs loop2 +level_done: + add r1, r1, #2 // increment the cache number + cmp r3, r1 + // Ensure completion of previous cache maintenance instruction. Note + // this also mitigates erratum 814220 on Cortex-A7 + dsb sy + bhi loop1 + + mov r6, #0 + stcopr r6, CSSELR //select cache level 0 in csselr + dsb sy + isb + pop {r4-r12, pc} + +dcsw_loop_table: + stcopr r0, DCISW + bx lr + stcopr r0, DCCISW + bx lr + stcopr r0, DCCSW + bx lr + +endfunc do_dcsw_op + + /* --------------------------------------------------------------- + * Data cache operations by set/way till PoU. + * + * The function requires : + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_louis + dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT +endfunc dcsw_op_louis + + /* --------------------------------------------------------------- + * Data cache operations by set/way till PoC. + * + * The function requires : + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * --------------------------------------------------------------- + */ +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 + ldcopr r2, CLIDR + mov r3, \level + sub r1, r3, #2 + b do_dcsw_op + .endm + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 1 cache + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * 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: + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * 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: + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level3 + dcsw_op_level #(3 << LEVEL_SHIFT) +endfunc dcsw_op_level3 diff --git a/arm-trusted-firmware/lib/aarch32/misc_helpers.S b/arm-trusted-firmware/lib/aarch32/misc_helpers.S new file mode 100644 index 0000000..59e15bd --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/misc_helpers.S @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl smc + .globl zeromem + .globl zero_normalmem + .globl memcpy4 + .globl disable_mmu_icache_secure + .globl disable_mmu_secure + .globl fixup_gdt_reloc + +#define PAGE_START_MASK ~(PAGE_SIZE_MASK) + +func smc + /* + * For AArch32 only r0-r3 will be in the registers; + * rest r4-r6 will be pushed on to the stack. So here, we'll + * have to load them from the stack to registers r4-r6 explicitly. + * Clobbers: r4-r6 + */ + ldm sp, {r4, r5, r6} + smc #0 +endfunc smc + +/* ----------------------------------------------------------------------- + * void zeromem(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. + * + * ----------------------------------------------------------------------- + */ +func zeromem + /* + * Readable names for registers + * + * Registers r0, r1 and r2 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 r0 /* Start address and then current address */ + length .req r1 /* Length in bytes of the region to zero out */ + /* + * Reusing the r1 register as length is only used at the beginning of + * the function. + */ + stop_address .req r1 /* Address past the last zeroed byte */ + zeroreg1 .req r2 /* Source register filled with 0 */ + zeroreg2 .req r3 /* Source register filled with 0 */ + tmp .req r12 /* Temporary scratch register */ + + mov zeroreg1, #0 + + /* stop_address is the address past the last to zero */ + add stop_address, cursor, length + + /* + * Length cannot be used anymore as it shares the same register with + * stop_address. + */ + .unreq length + + /* + * If the start address is already aligned to 8 bytes, skip this loop. + */ + tst cursor, #(8-1) + beq .Lzeromem_8bytes_aligned + + /* Calculate the next address aligned to 8 bytes */ + orr tmp, cursor, #(8-1) + adds tmp, tmp, #1 + /* If it overflows, fallback to byte per byte zeroing */ + beq .Lzeromem_1byte_aligned + /* If the next aligned address is after the stop address, fall back */ + cmp tmp, stop_address + bhs .Lzeromem_1byte_aligned + + /* zero byte per byte */ +1: + strb zeroreg1, [cursor], #1 + cmp cursor, tmp + bne 1b + + /* zero 8 bytes at a time */ +.Lzeromem_8bytes_aligned: + + /* Calculate the last 8 bytes aligned address. */ + bic tmp, stop_address, #(8-1) + + cmp cursor, tmp + bhs 2f + + mov zeroreg2, #0 +1: + stmia cursor!, {zeroreg1, zeroreg2} + cmp cursor, tmp + blo 1b +2: + + /* zero byte per byte */ +.Lzeromem_1byte_aligned: + cmp cursor, stop_address + beq 2f +1: + strb zeroreg1, [cursor], #1 + cmp cursor, stop_address + bne 1b +2: + bx lr + + .unreq cursor + /* + * length is already unreq'ed to reuse the register for another + * variable. + */ + .unreq stop_address + .unreq zeroreg1 + .unreq zeroreg2 + .unreq tmp +endfunc zeromem + +/* + * AArch32 does not have special ways of zeroing normal memory as AArch64 does + * using the DC ZVA instruction, so we just alias zero_normalmem to zeromem. + */ +.equ zero_normalmem, zeromem + +/* -------------------------------------------------------------------------- + * void memcpy4(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 4-byte aligned. + * -------------------------------------------------------------------------- + */ +func memcpy4 +#if ENABLE_ASSERTIONS + orr r3, r0, r1 + tst r3, #0x3 + ASM_ASSERT(eq) +#endif +/* copy 4 bytes at a time */ +m_loop4: + cmp r2, #4 + blo m_loop1 + ldr r3, [r1], #4 + str r3, [r0], #4 + subs r2, r2, #4 + bne m_loop4 + bx lr + +/* copy byte per byte */ +m_loop1: + ldrb r3, [r1], #1 + strb r3, [r0], #1 + subs r2, r2, #1 + bne m_loop1 + bx lr +endfunc memcpy4 + +/* --------------------------------------------------------------------------- + * Disable the MMU in Secure State + * --------------------------------------------------------------------------- + */ + +func disable_mmu_secure + mov r1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mmu: +#if ERRATA_A9_794073 + stcopr r0, BPIALL + dsb +#endif + ldcopr r0, SCTLR + bic r0, r0, r1 + stcopr r0, SCTLR + isb // ensure MMU is off + dsb sy + bx lr +endfunc disable_mmu_secure + + +func disable_mmu_icache_secure + ldr r1, =(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mmu +endfunc disable_mmu_icache_secure + +/* --------------------------------------------------------------------------- + * Helper to fixup Global Descriptor table (GDT) and dynamic relocations + * (.rel.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). + * r0 - the start of the fixup region + * r1 - the limit of the fixup region + * These addresses have to be 4KB page aligned. + * --------------------------------------------------------------------------- + */ + +/* Relocation codes */ +#define R_ARM_RELATIVE 23 + +func fixup_gdt_reloc + mov r6, r0 + mov r7, r1 + +#if ENABLE_ASSERTIONS + /* Test if the limits are 4K aligned */ + orr r0, r0, r1 + mov r1, #(PAGE_SIZE_MASK) + tst r0, r1 + ASM_ASSERT(eq) +#endif + /* + * Calculate the offset based on return address in lr. + * Assume that this function is called within a page at the start of + * fixup region. + */ + ldr r1, =PAGE_START_MASK + and r2, lr, r1 + subs r0, r2, r6 /* Diff(S) = Current Address - Compiled Address */ + beq 3f /* Diff(S) = 0. No relocation needed */ + + ldr r1, =__GOT_START__ + add r1, r1, r0 + ldr r2, =__GOT_END__ + add r2, r2, r0 + + /* + * GOT is an array of 32_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 r3, [r1] + + /* Skip adding offset if address is < lower limit */ + cmp r3, r6 + blo 2f + + /* Skip adding offset if address is > upper limit */ + cmp r3, r7 + bhi 2f + add r3, r3, r0 + str r3, [r1] + +2: add r1, r1, #4 + cmp r1, r2 + blo 1b + + /* Starting dynamic relocations. Use ldr to get RELA_START and END */ +3: ldr r1, =__RELA_START__ + add r1, r1, r0 + ldr r2, =__RELA_END__ + add r2, r2, r0 + + /* + * According to ELF-32 specification, the RELA data structure is as + * follows: + * typedef struct { + * Elf32_Addr r_offset; + * Elf32_Xword r_info; + * } Elf32_Rela; + * + * r_offset is address of reference + * r_info is symbol index and type of relocation (in this case + * code 23 which corresponds to R_ARM_RELATIVE). + * + * Size of Elf32_Rela structure is 8 bytes. + */ + + /* Skip R_ARM_NONE entry with code 0 */ +1: ldr r3, [r1, #4] + ands r3, r3, #0xff + beq 2f + +#if ENABLE_ASSERTIONS + /* Assert that the relocation type is R_ARM_RELATIVE */ + cmp r3, #R_ARM_RELATIVE + ASM_ASSERT(eq) +#endif + ldr r3, [r1] /* r_offset */ + add r3, r0, r3 /* Diff(S) + r_offset */ + ldr r4, [r3] + + /* Skip adding offset if address is < lower limit */ + cmp r4, r6 + blo 2f + + /* Skip adding offset if address is > upper limit */ + cmp r4, r7 + bhi 2f + + add r4, r0, r4 + str r4, [r3] + +2: add r1, r1, #8 + cmp r1, r2 + blo 1b + bx lr +endfunc fixup_gdt_reloc diff --git a/arm-trusted-firmware/lib/aarch64/armclang_printf.S b/arm-trusted-firmware/lib/aarch64/armclang_printf.S new file mode 100644 index 0000000..52a6976 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/aarch64/cache_helpers.S b/arm-trusted-firmware/lib/aarch64/cache_helpers.S new file mode 100644 index 0000000..6faf545 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch64/cache_helpers.S @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl flush_dcache_range + .globl flush_dcache_to_popa_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 + + + /* + * On implementations with FEAT_MTE2, + * Root firmware must issue DC_CIGDPAPA instead of DC_CIPAPA , + * in order to additionally clean and invalidate Allocation Tags + * associated with the affected locations. + * + * ------------------------------------------ + * Clean+Invalidate by PA to POPA + * from base address till size. + * 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +func flush_dcache_to_popa_range + /* Exit early if size is zero */ + cbz x1, exit_loop_dc_cipapa + dcache_line_size x2, x3 + sub x3, x2, #1 + bic x0, x0, x3 + add x1, x1, x0 +loop_dc_cipapa: + sys #6, c7, c14, #1, x0 /* DC CIPAPA, */ + add x0, x0, x2 + cmp x0, x1 + b.lo loop_dc_cipapa + dsb osh +exit_loop_dc_cipapa: + ret +endfunc flush_dcache_to_popa_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 + mrs x12, ID_AA64MMFR2_EL1 // stash FEAT_CCIDX identifier in x12 + ubfx x12, x12, #ID_AA64MMFR2_EL1_CCIDX_SHIFT, #ID_AA64MMFR2_EL1_CCIDX_LENGTH + 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) + + cbz x12, 1f // check for FEAT_CCIDX for Associativity + ubfx x4, x1, #3, #21 // x4 = associativity CCSIDR_EL1[23:3] + b 2f +1: + ubfx x4, x1, #3, #10 // x4 = associativity CCSIDR_EL1[12:3] +2: + 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 + + cbz x12, 3f // check for FEAT_CCIDX for NumSets + ubfx x6, x1, #32, #24 // x6 (w6) = numsets CCSIDR_EL1[55:32] + // ISA will not allow x->w ubfx + b 4f +3: + ubfx w6, w1, #13, #15 // w6 = numsets CCSIDR_EL1[27:13] +4: + 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/arm-trusted-firmware/lib/aarch64/misc_helpers.S b/arm-trusted-firmware/lib/aarch64/misc_helpers.S new file mode 100644 index 0000000..e8110b0 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch64/misc_helpers.S @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2013-2022, 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 gpt_tlbi_by_pa_ll + + .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 || ENABLE_RME)) + 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.hi 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.hi 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 + +/* + * TODO: Currently only supports size of 4KB, + * support other sizes as well. + */ +func gpt_tlbi_by_pa_ll +#if ENABLE_ASSERTIONS + cmp x1, #PAGE_SIZE_4KB + ASM_ASSERT(eq) + tst x0, #(PAGE_SIZE_MASK) + ASM_ASSERT(eq) +#endif + lsr x0, x0, #FOUR_KB_SHIFT /* 4KB size encoding is zero */ + sys #6, c8, c4, #7, x0 /* TLBI RPALOS, */ + dsb sy + ret +endfunc gpt_tlbi_by_pa_ll diff --git a/arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c b/arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c new file mode 100644 index 0000000..7f357b7 --- /dev/null +++ b/arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + +#include +#include +#include + +void bl_aux_params_parse(u_register_t head, + bl_aux_param_handler_t handler) +{ + struct bl_aux_param_header *p; + + for (p = (void *)head; p; p = (void *)(uintptr_t)p->next) { + if (handler && handler(p)) + continue; + + switch (p->type) { +#if COREBOOT + case BL_AUX_PARAM_COREBOOT_TABLE: + coreboot_table_setup((void *)(uintptr_t) + ((struct bl_aux_param_uint64 *)p)->value); + break; +#endif + default: + ERROR("Ignoring unknown BL aux parameter: 0x%" PRIx64, + p->type); + break; + } + } +} diff --git a/arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT b/arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT new file mode 100644 index 0000000..a17dc12 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S b/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S new file mode 100644 index 0000000..038ae5d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S b/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S new file mode 100644 index 0000000..be343b6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h b/arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h new file mode 100644 index 0000000..29d9f88 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c b/arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c new file mode 100644 index 0000000..db3c6fd --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c b/arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c new file mode 100644 index 0000000..b8eebcb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c b/arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c new file mode 100644 index 0000000..0d4df67 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h b/arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h new file mode 100644 index 0000000..7995ddb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h b/arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h new file mode 100644 index 0000000..80a7c41 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h b/arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h new file mode 100644 index 0000000..fc81fb7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h b/arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h new file mode 100644 index 0000000..660385e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c b/arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c new file mode 100644 index 0000000..67b2a76 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c b/arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c new file mode 100644 index 0000000..5e8a62f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c b/arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c new file mode 100644 index 0000000..44544ff --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c b/arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c new file mode 100644 index 0000000..0c8b4ff --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/compiler-rt/compiler-rt.mk b/arm-trusted-firmware/lib/compiler-rt/compiler-rt.mk new file mode 100644 index 0000000..40c669f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/coreboot/coreboot.mk b/arm-trusted-firmware/lib/coreboot/coreboot.mk new file mode 100644 index 0000000..4201823 --- /dev/null +++ b/arm-trusted-firmware/lib/coreboot/coreboot.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +COREBOOT := 0 +$(eval $(call assert_boolean,COREBOOT)) +$(eval $(call add_define,COREBOOT)) + +ifeq (${COREBOOT},1) + +ifneq (${ARCH},aarch64) +$(error "coreboot only supports Trusted Firmware on AArch64.") +endif + +BL31_SOURCES += $(addprefix lib/coreboot/, \ + coreboot_table.c) + +BL31_SOURCES += drivers/coreboot/cbmem_console/${ARCH}/cbmem_console.S + +endif # COREBOOT diff --git a/arm-trusted-firmware/lib/coreboot/coreboot_table.c b/arm-trusted-firmware/lib/coreboot/coreboot_table.c new file mode 100644 index 0000000..fb31ef1 --- /dev/null +++ b/arm-trusted-firmware/lib/coreboot/coreboot_table.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +/* + * Structures describing coreboot's in-memory descriptor tables. See + * /src/commonlib/include/commonlib/coreboot_tables.h for + * canonical implementation. + */ + +typedef struct { + char signature[4]; + uint32_t header_bytes; + uint32_t header_checksum; + uint32_t table_bytes; + uint32_t table_checksum; + uint32_t table_entries; +} cb_header_t; + +typedef enum { + CB_TAG_MEMORY = 0x1, + CB_TAG_SERIAL = 0xf, + CB_TAG_CBMEM_CONSOLE = 0x17, +} cb_tag_t; + +typedef struct { + uint32_t tag; + uint32_t size; + union { + coreboot_memrange_t memranges[COREBOOT_MAX_MEMRANGES]; + coreboot_serial_t serial; + uint64_t uint64; + }; +} cb_entry_t; + +coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES]; +coreboot_serial_t coreboot_serial; + +/* + * The coreboot table is parsed before the MMU is enabled (i.e. with strongly + * ordered memory), so we cannot make unaligned accesses. The table entries + * immediately follow one another without padding, so nothing after the header + * is guaranteed to be naturally aligned. Therefore, we need to define safety + * functions that can read unaligned integers. + */ +static uint32_t read_le32(uint32_t *p) +{ + uintptr_t addr = (uintptr_t)p; + return mmio_read_8(addr) | + mmio_read_8(addr + 1) << 8 | + mmio_read_8(addr + 2) << 16 | + mmio_read_8(addr + 3) << 24; +} +static uint64_t read_le64(uint64_t *p) +{ + return read_le32((void *)p) | (uint64_t)read_le32((void *)p + 4) << 32; +} + +static void expand_and_mmap(uintptr_t baseaddr, size_t size) +{ + uintptr_t pageaddr = round_down(baseaddr, PAGE_SIZE); + size_t expanded = round_up(baseaddr - pageaddr + size, PAGE_SIZE); + mmap_add_region(pageaddr, pageaddr, expanded, + MT_MEMORY | MT_RW | MT_NS | MT_EXECUTE_NEVER); +} + +static void setup_cbmem_console(uintptr_t baseaddr) +{ + static console_cbmc_t console; + assert(!console.console.base); /* should only have one CBMEM console */ + + /* CBMEM console structure stores its size in first header field. */ + uint32_t size = *(uint32_t *)baseaddr; + expand_and_mmap(baseaddr, size); + console_cbmc_register(baseaddr, &console); + console_set_scope(&console.console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | + CONSOLE_FLAG_CRASH); +} + +coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size) +{ + int i; + + for (i = 0; i < COREBOOT_MAX_MEMRANGES; i++) { + coreboot_memrange_t *range = &coreboot_memranges[i]; + + if (range->type == CB_MEM_NONE) + break; /* end of table reached */ + if ((start >= range->start) && + (start - range->start < range->size) && + (size <= range->size - (start - range->start))) { + return range->type; + } + } + + return CB_MEM_NONE; +} + +void coreboot_table_setup(void *base) +{ + cb_header_t *header = base; + void *ptr; + int i; + + if (strncmp(header->signature, "LBIO", 4)) { + ERROR("coreboot table signature corrupt!\n"); + return; + } + + ptr = base + header->header_bytes; + for (i = 0; i < header->table_entries; i++) { + size_t size; + cb_entry_t *entry = ptr; + + if (ptr - base >= header->header_bytes + header->table_bytes) { + ERROR("coreboot table exceeds its bounds!\n"); + break; + } + + switch (read_le32(&entry->tag)) { + case CB_TAG_MEMORY: + size = read_le32(&entry->size) - + offsetof(cb_entry_t, memranges); + if (size > sizeof(coreboot_memranges)) { + ERROR("Need to truncate coreboot memranges!\n"); + size = sizeof(coreboot_memranges); + } + memcpy(&coreboot_memranges, &entry->memranges, size); + break; + case CB_TAG_SERIAL: + memcpy(&coreboot_serial, &entry->serial, + sizeof(coreboot_serial)); + break; + case CB_TAG_CBMEM_CONSOLE: + setup_cbmem_console(read_le64(&entry->uint64)); + break; + default: + /* There are many tags TF doesn't need to care about. */ + break; + } + + ptr += read_le32(&entry->size); + } +} diff --git a/arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S b/arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S new file mode 100644 index 0000000..7bd586a --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +func aem_generic_core_pwr_dwn + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + /* --------------------------------------------- + * Flush L1 cache to PoU. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + b dcsw_op_louis +endfunc aem_generic_core_pwr_dwn + + +func aem_generic_cluster_pwr_dwn + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + /* --------------------------------------------- + * Flush L1 and L2 caches to PoC. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + b dcsw_op_all +endfunc aem_generic_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for AEM. Must follow AAPCS. + */ +func aem_generic_errata_report + bx lr +endfunc aem_generic_errata_report +#endif + +/* cpu_ops for Base AEM FVP */ +declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \ + aem_generic_core_pwr_dwn, \ + aem_generic_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S new file mode 100644 index 0000000..5300fe0 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a12_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A12_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a12_disable_smp + +func cortex_a12_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A12_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a12_enable_smp + +func cortex_a12_reset_func + b cortex_a12_enable_smp +endfunc cortex_a12_reset_func + +func cortex_a12_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a12_disable_smp +endfunc cortex_a12_core_pwr_dwn + +func cortex_a12_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a12_disable_smp +endfunc cortex_a12_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A12. Must follow AAPCS. + */ +func cortex_a12_errata_report + bx lr +endfunc cortex_a12_errata_report +#endif + +declare_cpu_ops cortex_a12, CORTEX_A12_MIDR, \ + cortex_a12_reset_func, \ + cortex_a12_core_pwr_dwn, \ + cortex_a12_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S new file mode 100644 index 0000000..ab136ad --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * Cortex-A15 support LPAE and Virtualization Extensions. + * Don't care if confiugration uses or not LPAE and VE. + * Therefore, where we don't check ARCH_IS_ARMV7_WITH_LPAE/VE + */ + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a15_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A15_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb +#if ERRATA_A15_816470 + /* + * Invalidate any TLB address + */ + mov r0, #0 + stcopr r0, TLBIMVA +#endif + dsb sy + bx lr +endfunc cortex_a15_disable_smp + +func cortex_a15_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A15_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a15_enable_smp + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A15 Errata #816470. + * This applies only to revision >= r3p0 of Cortex A15. + * ---------------------------------------------------- + */ +func check_errata_816470 + /* + * Even though this is only needed for revision >= r3p0, it is always + * applied because of the low cost of the workaround. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_816470 + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A15 Errata #827671. + * This applies only to revision >= r3p0 of Cortex A15. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * ---------------------------------------------------- + */ +func errata_a15_827671_wa + /* + * Compare r0 against revision r3p0 + */ + mov r2, lr + bl check_errata_827671 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr r0, CORTEX_A15_ACTLR2 + orr r0, #CORTEX_A15_ACTLR2_INV_DCC_BIT + stcopr r0, CORTEX_A15_ACTLR2 + isb +1: + bx r2 +endfunc errata_a15_827671_wa + +func check_errata_827671 + mov r1, #0x30 + b cpu_rev_var_hs +endfunc check_errata_827671 + +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A15. Must follow AAPCS. + */ +func cortex_a15_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A15_816470, cortex_a15, 816470 + report_errata ERRATA_A15_827671, cortex_a15, 827671 + report_errata WORKAROUND_CVE_2017_5715, cortex_a15, cve_2017_5715 + + pop {r12, lr} + bx lr +endfunc cortex_a15_errata_report +#endif + +func cortex_a15_reset_func + mov r5, lr + bl cpu_get_rev_var + +#if ERRATA_A15_827671 + bl errata_a15_827671_wa +#endif + +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldcopr r0, ACTLR + orr r0, #CORTEX_A15_ACTLR_INV_BTB_BIT + stcopr r0, ACTLR + ldr r0, =workaround_icache_inv_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif + + mov lr, r5 + b cortex_a15_enable_smp +endfunc cortex_a15_reset_func + +func cortex_a15_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a15_disable_smp +endfunc cortex_a15_core_pwr_dwn + +func cortex_a15_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a15_disable_smp +endfunc cortex_a15_cluster_pwr_dwn + +declare_cpu_ops cortex_a15, CORTEX_A15_MIDR, \ + cortex_a15_reset_func, \ + cortex_a15_core_pwr_dwn, \ + cortex_a15_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S new file mode 100644 index 0000000..b8abd33 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a17_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A17_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a17_disable_smp + +func cortex_a17_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A17_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a17_enable_smp + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A17 Errata #852421. + * This applies only to revision <= r1p2 of Cortex A17. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * ---------------------------------------------------- + */ +func errata_a17_852421_wa + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_852421 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr r0, CORTEX_A17_IMP_DEF_REG1 + orr r0, r0, #(1<<24) + stcopr r0, CORTEX_A17_IMP_DEF_REG1 +1: + bx r2 +endfunc errata_a17_852421_wa + +func check_errata_852421 + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_852421 + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A17 Errata #852423. + * This applies only to revision <= r1p2 of Cortex A17. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * ---------------------------------------------------- + */ +func errata_a17_852423_wa + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_852423 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr r0, CORTEX_A17_IMP_DEF_REG1 + orr r0, r0, #(1<<12) + stcopr r0, CORTEX_A17_IMP_DEF_REG1 +1: + bx r2 +endfunc errata_a17_852423_wa + +func check_errata_852423 + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_852423 + +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A17. Must follow AAPCS. + */ +func cortex_a17_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A17_852421, cortex_a17, 852421 + report_errata ERRATA_A17_852423, cortex_a17, 852423 + report_errata WORKAROUND_CVE_2017_5715, cortex_a17, cve_2017_5715 + + pop {r12, lr} + bx lr +endfunc cortex_a17_errata_report +#endif + +func cortex_a17_reset_func + mov r5, lr + bl cpu_get_rev_var + mov r4, r0 + +#if ERRATA_A17_852421 + mov r0, r4 + bl errata_a17_852421_wa +#endif + +#if ERRATA_A17_852423 + mov r0, r4 + bl errata_a17_852423_wa +#endif + +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldr r0, =workaround_bpiall_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif + + mov lr, r5 + b cortex_a17_enable_smp +endfunc cortex_a17_reset_func + +func cortex_a17_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a17_disable_smp +endfunc cortex_a17_core_pwr_dwn + +func cortex_a17_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a17_disable_smp +endfunc cortex_a17_cluster_pwr_dwn + +declare_cpu_ops cortex_a17, CORTEX_A17_MIDR, \ + cortex_a17_reset_func, \ + cortex_a17_core_pwr_dwn, \ + cortex_a17_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S new file mode 100644 index 0000000..c262276 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + + /* --------------------------------------------- + * Disable intra-cluster coherency + * Clobbers: r0-r1 + * --------------------------------------------- + */ +func cortex_a32_disable_smp + ldcopr16 r0, r1, CORTEX_A32_CPUECTLR_EL1 + bic r0, r0, #CORTEX_A32_CPUECTLR_SMPEN_BIT + stcopr16 r0, r1, CORTEX_A32_CPUECTLR_EL1 + isb + dsb sy + bx lr +endfunc cortex_a32_disable_smp + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A32. + * Clobbers: r0-r1 + * ------------------------------------------------- + */ +func cortex_a32_reset_func + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + ldcopr16 r0, r1, CORTEX_A32_CPUECTLR_EL1 + orr r0, r0, #CORTEX_A32_CPUECTLR_SMPEN_BIT + stcopr16 r0, r1, CORTEX_A32_CPUECTLR_EL1 + isb + bx lr +endfunc cortex_a32_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A32. + * Clobbers: r0-r3 + * ---------------------------------------------------- + */ +func cortex_a32_core_pwr_dwn + /* r12 is pushed to meet the 8 byte stack alignment requirement */ + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a32_disable_smp +endfunc cortex_a32_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A32. + * Clobbers: r0-r3 + * ------------------------------------------------------- + */ +func cortex_a32_cluster_pwr_dwn + /* r12 is pushed to meet the 8 byte stack alignment requirement */ + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Flush L1 cache. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 cache. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a32_disable_smp +endfunc cortex_a32_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A32. Must follow AAPCS. + */ +func cortex_a32_errata_report + bx lr +endfunc cortex_a32_errata_report +#endif + +declare_cpu_ops cortex_a32, CORTEX_A32_MIDR, \ + cortex_a32_reset_func, \ + cortex_a32_core_pwr_dwn, \ + cortex_a32_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S new file mode 100644 index 0000000..8abb66f --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a5_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A5_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a5_disable_smp + +func cortex_a5_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A5_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a5_enable_smp + +func cortex_a5_reset_func + b cortex_a5_enable_smp +endfunc cortex_a5_reset_func + +func cortex_a5_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a5_disable_smp +endfunc cortex_a5_core_pwr_dwn + +func cortex_a5_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a5_disable_smp +endfunc cortex_a5_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A5. Must follow AAPCS. + */ +func cortex_a5_errata_report + bx lr +endfunc cortex_a5_errata_report +#endif + +declare_cpu_ops cortex_a5, CORTEX_A5_MIDR, \ + cortex_a5_reset_func, \ + cortex_a5_core_pwr_dwn, \ + cortex_a5_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S new file mode 100644 index 0000000..6e3ff81 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#if A53_DISABLE_NON_TEMPORAL_HINT +#undef ERRATA_A53_836870 +#define ERRATA_A53_836870 1 +#endif + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a53_disable_smp + ldcopr16 r0, r1, CORTEX_A53_ECTLR + bic64_imm r0, r1, CORTEX_A53_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A53_ECTLR + isb + dsb sy + bx lr +endfunc cortex_a53_disable_smp + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #819472. + * This applies only to revision <= r0p1 of Cortex A53. + * --------------------------------------------------- + */ +func check_errata_819472 + /* + * Even though this is only needed for revision <= r0p1, it + * is always applied due to limitations of the current + * errata framework. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_819472 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #824069. + * This applies only to revision <= r0p2 of Cortex A53. + * --------------------------------------------------- + */ +func check_errata_824069 + /* + * Even though this is only needed for revision <= r0p2, it + * is always applied due to limitations of the current + * errata framework. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_824069 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #826319. + * This applies only to revision <= r0p2 of Cortex A53. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * -------------------------------------------------- + */ +func errata_a53_826319_wa + /* + * Compare r0 against revision r0p2 + */ + mov r2, lr + bl check_errata_826319 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr r0, CORTEX_A53_L2ACTLR + bic r0, #CORTEX_A53_L2ACTLR_ENABLE_UNIQUECLEAN + orr r0, #CORTEX_A53_L2ACTLR_DISABLE_CLEAN_PUSH + stcopr r0, CORTEX_A53_L2ACTLR +1: + bx lr +endfunc errata_a53_826319_wa + +func check_errata_826319 + mov r1, #0x02 + b cpu_rev_var_ls +endfunc check_errata_826319 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #827319. + * This applies only to revision <= r0p2 of Cortex A53. + * --------------------------------------------------- + */ +func check_errata_827319 + /* + * Even though this is only needed for revision <= r0p2, it + * is always applied due to limitations of the current + * errata framework. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_827319 + + /* --------------------------------------------------------------------- + * Disable the cache non-temporal hint. + * + * This ignores the Transient allocation hint in the MAIR and treats + * allocations the same as non-transient allocation types. As a result, + * the LDNP and STNP instructions in AArch64 behave the same as the + * equivalent LDP and STP instructions. + * + * This is relevant only for revisions <= r0p3 of Cortex-A53. + * From r0p4 and onwards, the bit to disable the hint is enabled by + * default at reset. + * + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------------------------- + */ +func a53_disable_non_temporal_hint + /* + * Compare r0 against revision r0p3 + */ + mov r2, lr + bl check_errata_disable_non_temporal_hint + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A53_CPUACTLR + orr64_imm r0, r1, CORTEX_A53_CPUACTLR_DTAH + stcopr16 r0, r1, CORTEX_A53_CPUACTLR +1: + bx lr +endfunc a53_disable_non_temporal_hint + +func check_errata_disable_non_temporal_hint + mov r1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_disable_non_temporal_hint + + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #855873. + * + * This applies only to revisions >= r0p3 of Cortex A53. + * Earlier revisions of the core are affected as well, but don't + * have the chicken bit in the CPUACTLR register. It is expected that + * the rich OS takes care of that, especially as the workaround is + * shared with other erratas in those revisions of the CPU. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * -------------------------------------------------- + */ +func errata_a53_855873_wa + /* + * Compare r0 against revision r0p3 and higher + */ + mov r2, lr + bl check_errata_855873 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A53_CPUACTLR + orr64_imm r0, r1, CORTEX_A53_CPUACTLR_ENDCCASCI + stcopr16 r0, r1, CORTEX_A53_CPUACTLR +1: + bx lr +endfunc errata_a53_855873_wa + +func check_errata_855873 + mov r1, #0x03 + b cpu_rev_var_hs +endfunc check_errata_855873 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A53. + * Shall clobber: r0-r6 + * ------------------------------------------------- + */ +func cortex_a53_reset_func + mov r5, lr + bl cpu_get_rev_var + mov r4, r0 + +#if ERRATA_A53_826319 + mov r0, r4 + bl errata_a53_826319_wa +#endif + +#if ERRATA_A53_836870 + mov r0, r4 + bl a53_disable_non_temporal_hint +#endif + +#if ERRATA_A53_855873 + mov r0, r4 + bl errata_a53_855873_wa +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + ldcopr16 r0, r1, CORTEX_A53_ECTLR + orr64_imm r0, r1, CORTEX_A53_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A53_ECTLR + isb + bx r5 +endfunc cortex_a53_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A53. + * ---------------------------------------------------- + */ +func cortex_a53_core_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a53_disable_smp +endfunc cortex_a53_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A53. + * Clobbers: r0-r3 + * ------------------------------------------------------- + */ +func cortex_a53_cluster_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a53_disable_smp +endfunc cortex_a53_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A53. Must follow AAPCS. + */ +func cortex_a53_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A53_819472, cortex_a53, 819472 + report_errata ERRATA_A53_824069, cortex_a53, 824069 + report_errata ERRATA_A53_826319, cortex_a53, 826319 + report_errata ERRATA_A53_827319, cortex_a53, 827319 + report_errata ERRATA_A53_836870, cortex_a53, disable_non_temporal_hint + report_errata ERRATA_A53_855873, cortex_a53, 855873 + + pop {r12, lr} + bx lr +endfunc cortex_a53_errata_report +#endif + +declare_cpu_ops cortex_a53, CORTEX_A53_MIDR, \ + cortex_a53_reset_func, \ + cortex_a53_core_pwr_dwn, \ + cortex_a53_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S new file mode 100644 index 0000000..2e97abb --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable intra-cluster coherency + * Clobbers: r0-r1 + * --------------------------------------------- + */ +func cortex_a57_disable_smp + ldcopr16 r0, r1, CORTEX_A57_ECTLR + bic64_imm r0, r1, CORTEX_A57_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A57_ECTLR + bx lr +endfunc cortex_a57_disable_smp + + /* --------------------------------------------- + * Disable all types of L2 prefetches. + * Clobbers: r0-r2 + * --------------------------------------------- + */ +func cortex_a57_disable_l2_prefetch + ldcopr16 r0, r1, CORTEX_A57_ECTLR + orr64_imm r0, r1, CORTEX_A57_ECTLR_DIS_TWD_ACC_PFTCH_BIT + bic64_imm r0, r1, (CORTEX_A57_ECTLR_L2_IPFTCH_DIST_MASK | \ + CORTEX_A57_ECTLR_L2_DPFTCH_DIST_MASK) + stcopr16 r0, r1, CORTEX_A57_ECTLR + isb + dsb ish + bx lr +endfunc cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func cortex_a57_disable_ext_debug + mov r0, #1 + stcopr r0, DBGOSDLR + isb +#if ERRATA_A57_817169 + /* + * Invalidate any TLB address + */ + mov r0, #0 + stcopr r0, TLBIMVA +#endif + dsb sy + bx lr +endfunc cortex_a57_disable_ext_debug + + /* -------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #806969. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * -------------------------------------------------- + */ +func errata_a57_806969_wa + /* + * Compare r0 against revision r0p0 + */ + mov r2, lr + bl check_errata_806969 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_NO_ALLOC_WBWA + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_806969_wa + +func check_errata_806969 + mov r1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_806969 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #813419. + * This applies only to revision r0p0 of Cortex A57. + * --------------------------------------------------- + */ +func check_errata_813419 + /* + * Even though this is only needed for revision r0p0, it + * is always applied due to limitations of the current + * errata framework. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_813419 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #813420. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_813420_wa + /* + * Compare r0 against revision r0p0 + */ + mov r2, lr + bl check_errata_813420 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DCC_AS_DCCI + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_813420_wa + +func check_errata_813420 + mov r1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_813420 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #814670. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_814670_wa + /* + * Compare r0 against revision r0p0 + */ + mov r2, lr + bl check_errata_814670 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_DMB_NULLIFICATION + stcopr16 r0, r1, CORTEX_A57_CPUACTLR + isb +1: + bx r2 +endfunc errata_a57_814670_wa + +func check_errata_814670 + mov r1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_814670 + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #817169. + * This applies only to revision <= r0p1 of Cortex A57. + * ---------------------------------------------------- + */ +func check_errata_817169 + /* + * Even though this is only needed for revision <= r0p1, it + * is always applied because of the low cost of the workaround. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_817169 + + /* -------------------------------------------------------------------- + * Disable the over-read from the LDNP instruction. + * + * This applies to all revisions <= r1p2. The performance degradation + * observed with LDNP/STNP has been fixed on r1p3 and onwards. + * + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------------------------- + */ +func a57_disable_ldnp_overread + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_disable_ldnp_overread + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_OVERREAD + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc a57_disable_ldnp_overread + +func check_errata_disable_ldnp_overread + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_disable_ldnp_overread + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #826974. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_826974_wa + /* + * Compare r0 against revision r1p1 + */ + mov r2, lr + bl check_errata_826974 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_LOAD_PASS_DMB + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_826974_wa + +func check_errata_826974 + mov r1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826974 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #826977. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_826977_wa + /* + * Compare r0 against revision r1p1 + */ + mov r2, lr + bl check_errata_826977 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_GRE_NGRE_AS_NGNRE + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_826977_wa + +func check_errata_826977 + mov r1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826977 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #828024. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_828024_wa + /* + * Compare r0 against revision r1p1 + */ + mov r2, lr + bl check_errata_828024 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + /* + * Setting the relevant bits in CORTEX_A57_CPUACTLR has to be done in 2 + * instructions here because the resulting bitmask doesn't fit in a + * 16-bit value so it cannot be encoded in a single instruction. + */ + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_NO_ALLOC_WBWA + orr64_imm r0, r1, (CORTEX_A57_CPUACTLR_DIS_L1_STREAMING | CORTEX_A57_CPUACTLR_DIS_STREAMING) + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_828024_wa + +func check_errata_828024 + mov r1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_828024 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #829520. + * This applies only to revision <= r1p2 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_829520_wa + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_829520 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_INDIRECT_PREDICTOR + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_829520_wa + +func check_errata_829520 + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_829520 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #833471. + * This applies only to revision <= r1p2 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_833471_wa + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_833471 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r1, r1, CORTEX_A57_CPUACTLR_FORCE_FPSCR_FLUSH + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_833471_wa + +func check_errata_833471 + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_833471 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #859972. + * This applies only to revision <= r1p3 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_859972_wa + mov r2, lr + bl check_errata_859972 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r1, r1, CORTEX_A57_CPUACTLR_DIS_INSTR_PREFETCH + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_859972_wa + +func check_errata_859972 + mov r1, #0x13 + b cpu_rev_var_ls +endfunc check_errata_859972 + +func check_errata_cve_2017_5715 + mov r0, #ERRATA_MISSING + bx lr +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2018_3639 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A57. + * Shall clobber: r0-r6 + * ------------------------------------------------- + */ +func cortex_a57_reset_func + mov r5, lr + bl cpu_get_rev_var + mov r4, r0 + +#if ERRATA_A57_806969 + mov r0, r4 + bl errata_a57_806969_wa +#endif + +#if ERRATA_A57_813420 + mov r0, r4 + bl errata_a57_813420_wa +#endif + +#if ERRATA_A57_814670 + mov r0, r4 + bl errata_a57_814670_wa +#endif + +#if A57_DISABLE_NON_TEMPORAL_HINT + mov r0, r4 + bl a57_disable_ldnp_overread +#endif + +#if ERRATA_A57_826974 + mov r0, r4 + bl errata_a57_826974_wa +#endif + +#if ERRATA_A57_826977 + mov r0, r4 + bl errata_a57_826977_wa +#endif + +#if ERRATA_A57_828024 + mov r0, r4 + bl errata_a57_828024_wa +#endif + +#if ERRATA_A57_829520 + mov r0, r4 + bl errata_a57_829520_wa +#endif + +#if ERRATA_A57_833471 + mov r0, r4 + bl errata_a57_833471_wa +#endif + +#if ERRATA_A57_859972 + mov r0, r4 + bl errata_a57_859972_wa +#endif + +#if WORKAROUND_CVE_2018_3639 + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_LOAD_PASS_STORE + stcopr16 r0, r1, CORTEX_A57_CPUACTLR + isb + dsb sy +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + ldcopr16 r0, r1, CORTEX_A57_ECTLR + orr64_imm r0, r1, CORTEX_A57_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A57_ECTLR + isb + bx r5 +endfunc cortex_a57_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A57. + * ---------------------------------------------------- + */ +func cortex_a57_core_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a57_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a57_disable_ext_debug +endfunc cortex_a57_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A57. + * Clobbers: r0-r3 + * ------------------------------------------------------- + */ +func cortex_a57_cluster_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a57_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a57_disable_ext_debug +endfunc cortex_a57_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A57. Must follow AAPCS. + */ +func cortex_a57_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A57_806969, cortex_a57, 806969 + report_errata ERRATA_A57_813419, cortex_a57, 813419 + report_errata ERRATA_A57_813420, cortex_a57, 813420 + report_errata ERRATA_A57_814670, cortex_a57, 814670 + report_errata ERRATA_A57_817169, cortex_a57, 817169 + report_errata A57_DISABLE_NON_TEMPORAL_HINT, cortex_a57, \ + disable_ldnp_overread + report_errata ERRATA_A57_826974, cortex_a57, 826974 + report_errata ERRATA_A57_826977, cortex_a57, 826977 + report_errata ERRATA_A57_828024, cortex_a57, 828024 + report_errata ERRATA_A57_829520, cortex_a57, 829520 + report_errata ERRATA_A57_833471, cortex_a57, 833471 + report_errata ERRATA_A57_859972, cortex_a57, 859972 + report_errata WORKAROUND_CVE_2017_5715, cortex_a57, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a57, cve_2018_3639 + + pop {r12, lr} + bx lr +endfunc cortex_a57_errata_report +#endif + +declare_cpu_ops cortex_a57, CORTEX_A57_MIDR, \ + cortex_a57_reset_func, \ + cortex_a57_core_pwr_dwn, \ + cortex_a57_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S new file mode 100644 index 0000000..4d4bb77 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a7_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A7_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a7_disable_smp + +func cortex_a7_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A7_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a7_enable_smp + +func cortex_a7_reset_func + b cortex_a7_enable_smp +endfunc cortex_a7_reset_func + +func cortex_a7_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a7_disable_smp +endfunc cortex_a7_core_pwr_dwn + +func cortex_a7_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a7_disable_smp +endfunc cortex_a7_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A7. Must follow AAPCS. + */ +func cortex_a7_errata_report + bx lr +endfunc cortex_a7_errata_report +#endif + +declare_cpu_ops cortex_a7, CORTEX_A7_MIDR, \ + cortex_a7_reset_func, \ + cortex_a7_core_pwr_dwn, \ + cortex_a7_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S new file mode 100644 index 0000000..ff2b0e6 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable all types of L2 prefetches. + * --------------------------------------------- + */ +func cortex_a72_disable_l2_prefetch + ldcopr16 r0, r1, CORTEX_A72_ECTLR + orr64_imm r0, r1, CORTEX_A72_ECTLR_DIS_TWD_ACC_PFTCH_BIT + bic64_imm r0, r1, (CORTEX_A72_ECTLR_L2_IPFTCH_DIST_MASK | \ + CORTEX_A72_ECTLR_L2_DPFTCH_DIST_MASK) + stcopr16 r0, r1, CORTEX_A72_ECTLR + isb + bx lr +endfunc cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ +func cortex_a72_disable_hw_prefetcher + ldcopr16 r0, r1, CORTEX_A72_CPUACTLR + orr64_imm r0, r1, CORTEX_A72_CPUACTLR_DISABLE_L1_DCACHE_HW_PFTCH + stcopr16 r0, r1, CORTEX_A72_CPUACTLR + isb + dsb ish + bx lr +endfunc cortex_a72_disable_hw_prefetcher + + /* --------------------------------------------- + * Disable intra-cluster coherency + * Clobbers: r0-r1 + * --------------------------------------------- + */ +func cortex_a72_disable_smp + ldcopr16 r0, r1, CORTEX_A72_ECTLR + bic64_imm r0, r1, CORTEX_A72_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A72_ECTLR + bx lr +endfunc cortex_a72_disable_smp + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func cortex_a72_disable_ext_debug + mov r0, #1 + stcopr r0, DBGOSDLR + isb + dsb sy + bx lr +endfunc cortex_a72_disable_ext_debug + + /* --------------------------------------------------- + * Errata Workaround for Cortex A72 Errata #859971. + * This applies only to revision <= r0p3 of Cortex A72. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a72_859971_wa + mov r2,lr + bl check_errata_859971 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A72_CPUACTLR + orr64_imm r1, r1, CORTEX_A72_CPUACTLR_DIS_INSTR_PREFETCH + stcopr16 r0, r1, CORTEX_A72_CPUACTLR +1: + bx lr +endfunc errata_a72_859971_wa + +func check_errata_859971 + mov r1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_859971 + +func check_errata_cve_2017_5715 + mov r0, #ERRATA_MISSING + bx lr +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2018_3639 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A72. + * ------------------------------------------------- + */ +func cortex_a72_reset_func + mov r5, lr + bl cpu_get_rev_var + mov r4, r0 + +#if ERRATA_A72_859971 + mov r0, r4 + bl errata_a72_859971_wa +#endif + +#if WORKAROUND_CVE_2018_3639 + ldcopr16 r0, r1, CORTEX_A72_CPUACTLR + orr64_imm r0, r1, CORTEX_A72_CPUACTLR_DIS_LOAD_PASS_STORE + stcopr16 r0, r1, CORTEX_A72_CPUACTLR + isb + dsb sy +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + ldcopr16 r0, r1, CORTEX_A72_ECTLR + orr64_imm r0, r1, CORTEX_A72_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A72_ECTLR + isb + bx r5 +endfunc cortex_a72_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A72. + * ---------------------------------------------------- + */ +func cortex_a72_core_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ + bl cortex_a72_disable_hw_prefetcher + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a72_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a72_disable_ext_debug +endfunc cortex_a72_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A72. + * ------------------------------------------------------- + */ +func cortex_a72_cluster_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ + bl cortex_a72_disable_hw_prefetcher + +#if !SKIP_A72_L1_FLUSH_PWR_DWN + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 +#endif + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* ------------------------------------------------- + * Flush the L2 caches. + * ------------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a72_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a72_disable_ext_debug +endfunc cortex_a72_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A72. Must follow AAPCS. + */ +func cortex_a72_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A72_859971, cortex_a72, 859971 + report_errata WORKAROUND_CVE_2017_5715, cortex_a72, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a72, cve_2018_3639 + + pop {r12, lr} + bx lr +endfunc cortex_a72_errata_report +#endif + +declare_cpu_ops cortex_a72, CORTEX_A72_MIDR, \ + cortex_a72_reset_func, \ + cortex_a72_core_pwr_dwn, \ + cortex_a72_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S new file mode 100644 index 0000000..7200343 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a9_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A9_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a9_disable_smp + +func cortex_a9_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A9_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a9_enable_smp + +func check_errata_a9_794073 +#if ERRATA_A9_794073 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A9. Must follow AAPCS. + */ +func cortex_a9_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, cortex_a9, cve_2017_5715 + report_errata ERRATA_A9_794073, cortex_a9, a9_79407 + + pop {r12, lr} + bx lr +endfunc cortex_a9_errata_report +#endif + +func cortex_a9_reset_func +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldr r0, =workaround_bpiall_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif + b cortex_a9_enable_smp +endfunc cortex_a9_reset_func + +func cortex_a9_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a9_disable_smp +endfunc cortex_a9_core_pwr_dwn + +func cortex_a9_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a9_disable_smp +endfunc cortex_a9_cluster_pwr_dwn + +declare_cpu_ops cortex_a9, CORTEX_A9_MIDR, \ + cortex_a9_reset_func, \ + cortex_a9_core_pwr_dwn, \ + cortex_a9_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S b/arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S new file mode 100644 index 0000000..6ed800c --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (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. The reset handler is invoked very early + * in the boot sequence and it is assumed that we can clobber r0 - r10 + * without the need to follow AAPCS. + * Clobbers: r0 - r10 + */ + .globl reset_handler +func reset_handler + mov r8, lr + + /* The plat_reset_handler can clobber r0 - r7 */ + bl plat_reset_handler + + /* Get the matching cpu_ops pointer (clobbers: r0 - r5) */ + bl get_cpu_ops_ptr + +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif + + /* Get the cpu_ops reset handler */ + ldr r1, [r0, #CPU_RESET_FUNC] + cmp r1, #0 + mov lr, r8 + bxne r1 + bx lr +endfunc reset_handler + +#endif + +#ifdef IMAGE_BL32 /* The power down core and cluster is needed only in BL32 */ + /* + * 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 r2, #(CPU_MAX_PWR_DWN_OPS - 1) + cmp r0, r2 + movhi r0, r2 + + push {r0, lr} + bl _cpu_data + pop {r2, lr} + + ldr r0, [r0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif + + /* Get the appropriate power down handler */ + mov r1, #CPU_PWR_DWN_OPS + add r1, r1, r2, lsl #2 + ldr r1, [r0, r1] +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif + bx r1 +endfunc prepare_cpu_pwr_dwn + + /* + * Initializes the cpu_ops_ptr if not already initialized + * in cpu_data. This must only be called after the data cache + * is enabled. AAPCS is followed. + */ + .globl init_cpu_ops +func init_cpu_ops + push {r4 - r6, lr} + bl _cpu_data + mov r6, r0 + ldr r1, [r0, #CPU_DATA_CPU_OPS_PTR] + cmp r1, #0 + bne 1f + bl get_cpu_ops_ptr +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif + str r0, [r6, #CPU_DATA_CPU_OPS_PTR]! +1: + pop {r4 - r6, pc} +endfunc init_cpu_ops + +#endif /* IMAGE_BL32 */ + + /* + * The below function returns the cpu_ops structure matching the + * midr of the core. It reads the MIDR and finds the matching + * entry in cpu_ops entries. Only the implementation and part number + * are used to match the entries. + * Return : + * r0 - The matching cpu_ops pointer on Success + * r0 - 0 on failure. + * Clobbers: r0 - r5 + */ + .globl get_cpu_ops_ptr +func get_cpu_ops_ptr + /* Get the cpu_ops start and end locations */ + ldr r4, =(__CPU_OPS_START__ + CPU_MIDR) + ldr r5, =(__CPU_OPS_END__ + CPU_MIDR) + + /* Initialize the return parameter */ + mov r0, #0 + + /* Read the MIDR_EL1 */ + ldcopr r2, MIDR + ldr r3, =CPU_IMPL_PN_MASK + + /* Retain only the implementation and part number using mask */ + and r2, r2, r3 +1: + /* Check if we have reached end of list */ + cmp r4, r5 + bhs error_exit + + /* load the midr from the cpu_ops */ + ldr r1, [r4], #CPU_OPS_SIZE + and r1, r1, r3 + + /* Check if midr matches to midr of this core */ + cmp r1, r2 + bne 1b + + /* Subtract the increment and offset to get the cpu-ops pointer */ + sub r0, r4, #(CPU_OPS_SIZE + CPU_MIDR) +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif +error_exit: + bx lr +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 + ldcopr r1, MIDR + + /* + * Extract the variant[23:20] and revision[3:0] from r1 and pack it in + * r0[0:7] as variant[7:4] and revision[3:0]: + * + * First extract r1[23:16] to r0[7:0] and zero fill the rest. Then + * extract r1[3:0] into r0[3:0] retaining other bits. + */ + ubfx r0, r1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) + bfi r0, r1, #MIDR_REV_SHIFT, #MIDR_REV_BITS + bx lr +endfunc cpu_get_rev_var + +/* + * Compare the CPU's revision-variant (r0) with a given value (r1), for errata + * application purposes. If the revision-variant is less than or same as a given + * value, indicates that errata applies; otherwise not. + */ + .globl cpu_rev_var_ls +func cpu_rev_var_ls + cmp r0, r1 + movls r0, #ERRATA_APPLIES + movhi r0, #ERRATA_NOT_APPLIES + bx lr +endfunc cpu_rev_var_ls + +/* + * Compare the CPU's revision-variant (r0) with a given value (r1), for errata + * application purposes. If the revision-variant is higher than or same as a + * given value, indicates that errata applies; otherwise not. + */ + .globl cpu_rev_var_hs +func cpu_rev_var_hs + cmp r0, r1 + movge r0, #ERRATA_APPLIES + movlt r0, #ERRATA_NOT_APPLIES + bx lr +endfunc cpu_rev_var_hs + +#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 + /* r12 is pushed only for the sake of 8-byte stack alignment */ + push {r4, r5, r12, lr} +#ifdef IMAGE_BL1 + /* + * BL1 doesn't have per-CPU data. So retrieve the CPU operations + * directly. + */ + bl get_cpu_ops_ptr + ldr r0, [r0, #CPU_ERRATA_FUNC] + cmp r0, #0 + blxne r0 +#else + /* + * Retrieve pointer to cpu_ops, and further, the errata printing + * function. If it's non-NULL, jump to the function in turn. + */ + bl _cpu_data +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif + ldr r1, [r0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif + ldr r0, [r1, #CPU_ERRATA_FUNC] + cmp r0, #0 + beq 1f + + mov r4, r0 + + /* + * 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 r0, [r1, #CPU_ERRATA_LOCK] + ldr r1, [r1, #CPU_ERRATA_PRINTED] + bl errata_needs_reporting + cmp r0, #0 + blxne r4 +1: +#endif + pop {r4, r5, r12, pc} +endfunc print_errata_status +#endif diff --git a/arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S b/arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S new file mode 100644 index 0000000..6291e43 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +func aem_generic_core_pwr_dwn + /* --------------------------------------------- + * Disable the Data Cache. + * --------------------------------------------- + */ + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + + /* --------------------------------------------- + * AEM model supports L3 caches in which case L2 + * will be private per core caches and flush + * from L1 to L2 is not sufficient. + * --------------------------------------------- + */ + mrs x1, clidr_el1 + + /* --------------------------------------------- + * Check if L3 cache is implemented. + * --------------------------------------------- + */ + tst x1, ((1 << CLIDR_FIELD_WIDTH) - 1) << CTYPE_SHIFT(3) + + /* --------------------------------------------- + * There is no L3 cache, flush L1 to L2 only. + * --------------------------------------------- + */ + mov x0, #DCCISW + b.eq dcsw_op_level1 + + mov x18, x30 + + /* --------------------------------------------- + * Flush L1 cache to L2. + * --------------------------------------------- + */ + bl dcsw_op_level1 + mov x30, x18 + + /* --------------------------------------------- + * Flush L2 cache to L3. + * --------------------------------------------- + */ + mov x0, #DCCISW + b dcsw_op_level2 +endfunc aem_generic_core_pwr_dwn + +func aem_generic_cluster_pwr_dwn + /* --------------------------------------------- + * Disable the Data Cache. + * --------------------------------------------- + */ + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + + /* --------------------------------------------- + * Flush all caches to PoC. + * --------------------------------------------- + */ + mov x0, #DCCISW + b dcsw_op_all +endfunc aem_generic_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for AEM. Must follow AAPCS. + */ +func aem_generic_errata_report + ret +endfunc aem_generic_errata_report +#endif + + /* --------------------------------------------- + * This function provides cpu 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.aem_generic_regs, "aS" +aem_generic_regs: /* The ascii list of register names to be reported */ + .asciz "" /* no registers to report */ + +func aem_generic_cpu_reg_dump + adr x6, aem_generic_regs + ret +endfunc aem_generic_cpu_reg_dump + + +/* cpu_ops for Base AEM FVP */ +declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \ + aem_generic_core_pwr_dwn, \ + aem_generic_cluster_pwr_dwn + +/* cpu_ops for Foundation FVP */ +declare_cpu_ops aem_generic, FOUNDATION_AEM_MIDR, CPU_NO_RESET_FUNC, \ + aem_generic_core_pwr_dwn, \ + aem_generic_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S new file mode 100644 index 0000000..be3c652 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func cortex_a35_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a35_disable_dcache + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a35_disable_smp + mrs x0, CORTEX_A35_CPUECTLR_EL1 + bic x0, x0, #CORTEX_A35_CPUECTLR_SMPEN_BIT + msr CORTEX_A35_CPUECTLR_EL1, x0 + isb + dsb sy + ret +endfunc cortex_a35_disable_smp + + /* --------------------------------------------------- + * Errata Workaround for Cortex A35 Errata #855472. + * This applies to revisions r0p0 of Cortex A35. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a35_855472_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_855472 + cbz x0, 1f + mrs x1, CORTEX_A35_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A35_CPUACTLR_EL1_ENDCCASCI + msr CORTEX_A35_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a35_855472_wa + +func check_errata_855472 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_855472 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A35. + * Clobbers: x0 + * ------------------------------------------------- + */ +func cortex_a35_reset_func + mov x19, x30 + bl cpu_get_rev_var + +#if ERRATA_A35_855472 + bl errata_a35_855472_wa +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + mrs x0, CORTEX_A35_CPUECTLR_EL1 + orr x0, x0, #CORTEX_A35_CPUECTLR_SMPEN_BIT + msr CORTEX_A35_CPUECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a35_reset_func + +func cortex_a35_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a35_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a35_disable_smp +endfunc cortex_a35_core_pwr_dwn + +func cortex_a35_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a35_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a35_disable_smp +endfunc cortex_a35_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A35. Must follow AAPCS. + */ +func cortex_a35_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A35_855472, cortex_a35, 855472 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a35_errata_report +#endif + + + /* --------------------------------------------- + * This function provides cortex_a35 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_a35_regs, "aS" +cortex_a35_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a35_cpu_reg_dump + adr x6, cortex_a35_regs + mrs x8, CORTEX_A35_CPUECTLR_EL1 + ret +endfunc cortex_a35_cpu_reg_dump + +declare_cpu_ops cortex_a35, CORTEX_A35_MIDR, \ + cortex_a35_reset_func, \ + cortex_a35_core_pwr_dwn, \ + cortex_a35_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S new file mode 100644 index 0000000..34e1082 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2022, ARM Limited. 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-A510 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex-A510 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #1922240. + * This applies only to revision r0p0 (fixed in r0p1) + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_1922240_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1922240 + cbz x0, 1f + + /* Apply the workaround by setting IMP_CMPXACTLR_EL1[11:10] = 0b11. */ + mrs x0, CORTEX_A510_CMPXACTLR_EL1 + mov x1, #3 + bfi x0, x1, #10, #2 + msr CORTEX_A510_CMPXACTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_1922240_wa + +func check_errata_1922240 + /* Applies to r0p0 only */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_1922240 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2288014. + * This applies only to revisions r0p0, r0p1, r0p2, + * r0p3 and r1p0. (fixed in r1p1) + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2288014_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2288014 + cbz x0, 1f + + /* Apply the workaround by setting IMP_CPUACTLR_EL1[18] = 0b1. */ + mrs x0, CORTEX_A510_CPUACTLR_EL1 + mov x1, #1 + bfi x0, x1, #18, #1 + msr CORTEX_A510_CPUACTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_2288014_wa + +func check_errata_2288014 + /* Applies to r1p0 and below */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_2288014 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2042739. + * This applies only to revisions r0p0, r0p1 and r0p2. + * (fixed in r0p3) + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2042739_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2042739 + cbz x0, 1f + + /* Apply the workaround by disabling ReadPreferUnique. */ + mrs x0, CORTEX_A510_CPUECTLR_EL1 + mov x1, #CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_DISABLE + bfi x0, x1, #CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_SHIFT, #1 + msr CORTEX_A510_CPUECTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_2042739_wa + +func check_errata_2042739 + /* Applies to revisions r0p0 - r0p2 */ + mov x1, #0x02 + b cpu_rev_var_ls +endfunc check_errata_2042739 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2041909. + * This applies only to revision r0p2 and it is fixed in + * r0p3. The issue is also present in r0p0 and r0p1 but + * there is no workaround in those revisions. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x2, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2041909_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2041909 + cbz x0, 1f + + /* Apply workaround */ + mov x0, xzr + msr S3_6_C15_C4_0, x0 + isb + + mov x0, #0x8500000 + msr S3_6_C15_C4_2, x0 + + mov x0, #0x1F700000 + movk x0, #0x8, lsl #32 + msr S3_6_C15_C4_3, x0 + + mov x0, #0x3F1 + movk x0, #0x110, lsl #16 + msr S3_6_C15_C4_1, x0 + isb + +1: + ret x17 +endfunc errata_cortex_a510_2041909_wa + +func check_errata_2041909 + /* Applies only to revision r0p2 */ + mov x1, #0x02 + mov x2, #0x02 + b cpu_rev_var_range +endfunc check_errata_2041909 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2250311. + * This applies only to revisions r0p0, r0p1, r0p2, + * r0p3 and r1p0, and is fixed in r1p1. + * This workaround is not a typical errata fix. MPMM + * is disabled here, but this conflicts with the BL31 + * MPMM support. So in addition to simply disabling + * the feature, a flag is set in the MPMM library + * indicating that it should not be enabled even if + * ENABLE_MPMM=1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2250311_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2250311 + cbz x0, 1f + + /* Disable MPMM */ + mrs x0, CPUMPMMCR_EL3 + bfm x0, xzr, #0, #0 /* bfc instruction does not work in GCC */ + msr CPUMPMMCR_EL3, x0 + +#if ENABLE_MPMM && IMAGE_BL31 + /* If ENABLE_MPMM is set, tell the runtime lib to skip enabling it. */ + bl mpmm_errata_disable +#endif + +1: + ret x17 +endfunc errata_cortex_a510_2250311_wa + +func check_errata_2250311 + /* Applies to r1p0 and lower */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_2250311 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2218950. + * This applies only to revisions r0p0, r0p1, r0p2, + * r0p3 and r1p0, and is fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2218950_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2218950 + cbz x0, 1f + + /* Source register for BFI */ + mov x1, #1 + + /* Set bit 18 in CPUACTLR_EL1 */ + mrs x0, CORTEX_A510_CPUACTLR_EL1 + bfi x0, x1, #18, #1 + msr CORTEX_A510_CPUACTLR_EL1, x0 + + /* Set bit 25 in CMPXACTLR_EL1 */ + mrs x0, CORTEX_A510_CMPXACTLR_EL1 + bfi x0, x1, #25, #1 + msr CORTEX_A510_CMPXACTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_2218950_wa + +func check_errata_2218950 + /* Applies to r1p0 and lower */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_2218950 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2172148. + * This applies only to revisions r0p0, r0p1, r0p2, + * r0p3 and r1p0, and is fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2172148_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2172148 + cbz x0, 1f + + /* + * Force L2 allocation of transient lines by setting + * CPUECTLR_EL1.RSCTL=0b01 and CPUECTLR_EL1.NTCTL=0b01. + */ + mrs x0, CORTEX_A510_CPUECTLR_EL1 + mov x1, #1 + bfi x0, x1, #CORTEX_A510_CPUECTLR_EL1_RSCTL_SHIFT, #2 + bfi x0, x1, #CORTEX_A510_CPUECTLR_EL1_NTCTL_SHIFT, #2 + msr CORTEX_A510_CPUECTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_2172148_wa + +func check_errata_2172148 + /* Applies to r1p0 and lower */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_2172148 + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_a510_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_A510_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A510_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A510_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a510_core_pwr_dwn + + /* + * Errata printing function for Cortex-A510. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_a510_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A510_1922240, cortex_a510, 1922240 + report_errata ERRATA_A510_2288014, cortex_a510, 2288014 + report_errata ERRATA_A510_2042739, cortex_a510, 2042739 + report_errata ERRATA_A510_2041909, cortex_a510, 2041909 + report_errata ERRATA_A510_2250311, cortex_a510, 2250311 + report_errata ERRATA_A510_2218950, cortex_a510, 2218950 + report_errata ERRATA_A510_2172148, cortex_a510, 2172148 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a510_errata_report +#endif + +func cortex_a510_reset_func + mov x19, x30 + + /* Disable speculative loads */ + msr SSBS, xzr + isb + + /* Get the CPU revision and stash it in x18. */ + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A510_1922240 + mov x0, x18 + bl errata_cortex_a510_1922240_wa +#endif + +#if ERRATA_A510_2288014 + mov x0, x18 + bl errata_cortex_a510_2288014_wa +#endif + +#if ERRATA_A510_2042739 + mov x0, x18 + bl errata_cortex_a510_2042739_wa +#endif + +#if ERRATA_A510_2041909 + mov x0, x18 + bl errata_cortex_a510_2041909_wa +#endif + +#if ERRATA_A510_2250311 + mov x0, x18 + bl errata_cortex_a510_2250311_wa +#endif + +#if ERRATA_A510_2218950 + mov x0, x18 + bl errata_cortex_a510_2218950_wa +#endif + +#if ERRATA_A510_2172148 + mov x0, x18 + bl errata_cortex_a510_2172148_wa +#endif + + ret x19 +endfunc cortex_a510_reset_func + + /* --------------------------------------------- + * This function provides Cortex-A510 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_a510_regs, "aS" +cortex_a510_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a510_cpu_reg_dump + adr x6, cortex_a510_regs + mrs x8, CORTEX_A510_CPUECTLR_EL1 + ret +endfunc cortex_a510_cpu_reg_dump + +declare_cpu_ops cortex_a510, CORTEX_A510_MIDR, \ + cortex_a510_reset_func, \ + cortex_a510_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S new file mode 100644 index 0000000..df11d86 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S @@ -0,0 +1,409 @@ +/* + * 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 + +#if A53_DISABLE_NON_TEMPORAL_HINT +#undef ERRATA_A53_836870 +#define ERRATA_A53_836870 1 +#endif + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func cortex_a53_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a53_disable_dcache + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a53_disable_smp + mrs x0, CORTEX_A53_ECTLR_EL1 + bic x0, x0, #CORTEX_A53_ECTLR_SMP_BIT + msr CORTEX_A53_ECTLR_EL1, x0 + isb + dsb sy + ret +endfunc cortex_a53_disable_smp + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #819472. + * This applies only to revision <= r0p1 of Cortex A53. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * --------------------------------------------------- + */ +func check_errata_819472 +#if ERRATA_A53_819472 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x01 + b cpu_rev_var_ls +#endif +endfunc check_errata_819472 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #824069. + * This applies only to revision <= r0p2 of Cortex A53. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * --------------------------------------------------- + */ +func check_errata_824069 +#if ERRATA_A53_824069 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x02 + b cpu_rev_var_ls +#endif +endfunc check_errata_824069 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #826319. + * This applies only to revision <= r0p2 of Cortex A53. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a53_826319_wa + /* + * Compare x0 against revision r0p2 + */ + mov x17, x30 + bl check_errata_826319 + cbz x0, 1f + mrs x1, CORTEX_A53_L2ACTLR_EL1 + bic x1, x1, #CORTEX_A53_L2ACTLR_ENABLE_UNIQUECLEAN + orr x1, x1, #CORTEX_A53_L2ACTLR_DISABLE_CLEAN_PUSH + msr CORTEX_A53_L2ACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a53_826319_wa + +func check_errata_826319 + mov x1, #0x02 + b cpu_rev_var_ls +endfunc check_errata_826319 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #827319. + * This applies only to revision <= r0p2 of Cortex A53. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * --------------------------------------------------- + */ +func check_errata_827319 +#if ERRATA_A53_827319 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x02 + b cpu_rev_var_ls +#endif +endfunc check_errata_827319 + + /* --------------------------------------------------------------------- + * Disable the cache non-temporal hint. + * + * This ignores the Transient allocation hint in the MAIR and treats + * allocations the same as non-transient allocation types. As a result, + * the LDNP and STNP instructions in AArch64 behave the same as the + * equivalent LDP and STP instructions. + * + * This is relevant only for revisions <= r0p3 of Cortex-A53. + * From r0p4 and onwards, the bit to disable the hint is enabled by + * default at reset. + * + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func a53_disable_non_temporal_hint + /* + * Compare x0 against revision r0p3 + */ + mov x17, x30 + bl check_errata_disable_non_temporal_hint + cbz x0, 1f + mrs x1, CORTEX_A53_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A53_CPUACTLR_EL1_DTAH + msr CORTEX_A53_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc a53_disable_non_temporal_hint + +func check_errata_disable_non_temporal_hint + mov x1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_disable_non_temporal_hint + + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #855873. + * + * This applies only to revisions >= r0p3 of Cortex A53. + * Earlier revisions of the core are affected as well, but don't + * have the chicken bit in the CPUACTLR register. It is expected that + * the rich OS takes care of that, especially as the workaround is + * shared with other erratas in those revisions of the CPU. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a53_855873_wa + /* + * Compare x0 against revision r0p3 and higher + */ + mov x17, x30 + bl check_errata_855873 + cbz x0, 1f + + mrs x1, CORTEX_A53_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A53_CPUACTLR_EL1_ENDCCASCI + msr CORTEX_A53_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a53_855873_wa + +func check_errata_855873 + mov x1, #0x03 + b cpu_rev_var_hs +endfunc check_errata_855873 + +/* + * Errata workaround for Cortex A53 Errata #835769. + * This applies to revisions <= r0p4 of Cortex A53. + * This workaround is statically enabled at build time. + */ +func check_errata_835769 + cmp x0, #0x04 + b.hi errata_not_applies + /* + * Fix potentially available for revisions r0p2, r0p3 and r0p4. + * If r0p2, r0p3 or r0p4; check for fix in REVIDR, else exit. + */ + cmp x0, #0x01 + mov x0, #ERRATA_APPLIES + b.ls exit_check_errata_835769 + /* Load REVIDR. */ + mrs x1, revidr_el1 + /* If REVIDR[7] is set (fix exists) set ERRATA_NOT_APPLIES, else exit. */ + tbz x1, #7, exit_check_errata_835769 +errata_not_applies: + mov x0, #ERRATA_NOT_APPLIES +exit_check_errata_835769: + ret +endfunc check_errata_835769 + +/* + * Errata workaround for Cortex A53 Errata #843419. + * This applies to revisions <= r0p4 of Cortex A53. + * This workaround is statically enabled at build time. + */ +func check_errata_843419 + mov x1, #ERRATA_APPLIES + mov x2, #ERRATA_NOT_APPLIES + cmp x0, #0x04 + csel x0, x1, x2, ls + /* + * Fix potentially available for revision r0p4. + * If r0p4 check for fix in REVIDR, else exit. + */ + b.ne exit_check_errata_843419 + /* Load REVIDR. */ + mrs x3, revidr_el1 + /* If REVIDR[8] is set (fix exists) set ERRATA_NOT_APPLIES, else exit. */ + tbz x3, #8, exit_check_errata_843419 + mov x0, x2 +exit_check_errata_843419: + ret +endfunc check_errata_843419 + + /* -------------------------------------------------- + * Errata workaround for Cortex A53 Errata #1530924. + * This applies to all revisions of Cortex A53. + * -------------------------------------------------- + */ +func check_errata_1530924 +#if ERRATA_A53_1530924 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_1530924 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A53. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a53_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + + +#if ERRATA_A53_826319 + mov x0, x18 + bl errata_a53_826319_wa +#endif + +#if ERRATA_A53_836870 + mov x0, x18 + bl a53_disable_non_temporal_hint +#endif + +#if ERRATA_A53_855873 + mov x0, x18 + bl errata_a53_855873_wa +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + mrs x0, CORTEX_A53_ECTLR_EL1 + orr x0, x0, #CORTEX_A53_ECTLR_SMP_BIT + msr CORTEX_A53_ECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a53_reset_func + +func cortex_a53_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a53_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a53_disable_smp +endfunc cortex_a53_core_pwr_dwn + +func cortex_a53_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a53_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a53_disable_smp +endfunc cortex_a53_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A53. Must follow AAPCS. + */ +func cortex_a53_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A53_819472, cortex_a53, 819472 + report_errata ERRATA_A53_824069, cortex_a53, 824069 + report_errata ERRATA_A53_826319, cortex_a53, 826319 + report_errata ERRATA_A53_827319, cortex_a53, 827319 + report_errata ERRATA_A53_835769, cortex_a53, 835769 + report_errata ERRATA_A53_836870, cortex_a53, disable_non_temporal_hint + report_errata ERRATA_A53_843419, cortex_a53, 843419 + report_errata ERRATA_A53_855873, cortex_a53, 855873 + report_errata ERRATA_A53_1530924, cortex_a53, 1530924 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a53_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a53 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_a53_regs, "aS" +cortex_a53_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", \ + "cpuactlr_el1", "" + +func cortex_a53_cpu_reg_dump + adr x6, cortex_a53_regs + mrs x8, CORTEX_A53_ECTLR_EL1 + mrs x9, CORTEX_A53_MERRSR_EL1 + mrs x10, CORTEX_A53_L2MERRSR_EL1 + mrs x11, CORTEX_A53_CPUACTLR_EL1 + ret +endfunc cortex_a53_cpu_reg_dump + +declare_cpu_ops cortex_a53, CORTEX_A53_MIDR, \ + cortex_a53_reset_func, \ + cortex_a53_core_pwr_dwn, \ + cortex_a53_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S new file mode 100644 index 0000000..7838304 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S new file mode 100644 index 0000000..3766ec7 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2014-2022, 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 + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func cortex_a57_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a57_disable_dcache + + /* --------------------------------------------- + * Disable all types of L2 prefetches. + * --------------------------------------------- + */ +func cortex_a57_disable_l2_prefetch + mrs x0, CORTEX_A57_ECTLR_EL1 + orr x0, x0, #CORTEX_A57_ECTLR_DIS_TWD_ACC_PFTCH_BIT + mov x1, #CORTEX_A57_ECTLR_L2_IPFTCH_DIST_MASK + orr x1, x1, #CORTEX_A57_ECTLR_L2_DPFTCH_DIST_MASK + bic x0, x0, x1 + msr CORTEX_A57_ECTLR_EL1, x0 + isb + dsb ish + ret +endfunc cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a57_disable_smp + mrs x0, CORTEX_A57_ECTLR_EL1 + bic x0, x0, #CORTEX_A57_ECTLR_SMP_BIT + msr CORTEX_A57_ECTLR_EL1, x0 + ret +endfunc cortex_a57_disable_smp + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func cortex_a57_disable_ext_debug + mov x0, #1 + msr osdlr_el1, x0 + isb +#if ERRATA_A57_817169 + /* + * Invalidate any TLB address + */ + mov x0, #0 + tlbi vae3, x0 +#endif + dsb sy + ret +endfunc cortex_a57_disable_ext_debug + + /* -------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #806969. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a57_806969_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_806969 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_806969_wa + +func check_errata_806969 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_806969 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #813419. + * This applies only to revision r0p0 of Cortex A57. + * --------------------------------------------------- + */ +func check_errata_813419 + /* + * Even though this is only needed for revision r0p0, it + * is always applied due to limitations of the current + * errata framework. + */ + mov x0, #ERRATA_APPLIES + ret +endfunc check_errata_813419 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #813420. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_813420_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_813420 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DCC_AS_DCCI + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_813420_wa + +func check_errata_813420 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_813420 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #814670. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_814670_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_814670 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_DMB_NULLIFICATION + msr CORTEX_A57_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a57_814670_wa + +func check_errata_814670 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_814670 + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #817169. + * This applies only to revision <= r0p1 of Cortex A57. + * ---------------------------------------------------- + */ +func check_errata_817169 + /* + * Even though this is only needed for revision <= r0p1, it + * is always applied because of the low cost of the workaround. + */ + mov x0, #ERRATA_APPLIES + ret +endfunc check_errata_817169 + + /* -------------------------------------------------------------------- + * Disable the over-read from the LDNP instruction. + * + * This applies to all revisions <= r1p2. The performance degradation + * observed with LDNP/STNP has been fixed on r1p3 and onwards. + * + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func a57_disable_ldnp_overread + /* + * Compare x0 against revision r1p2 + */ + mov x17, x30 + bl check_errata_disable_ldnp_overread + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_OVERREAD + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc a57_disable_ldnp_overread + +func check_errata_disable_ldnp_overread + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_disable_ldnp_overread + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #826974. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_826974_wa + /* + * Compare x0 against revision r1p1 + */ + mov x17, x30 + bl check_errata_826974 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_LOAD_PASS_DMB + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_826974_wa + +func check_errata_826974 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826974 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #826977. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_826977_wa + /* + * Compare x0 against revision r1p1 + */ + mov x17, x30 + bl check_errata_826977 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_GRE_NGRE_AS_NGNRE + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_826977_wa + +func check_errata_826977 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826977 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #828024. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_828024_wa + /* + * Compare x0 against revision r1p1 + */ + mov x17, x30 + bl check_errata_828024 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + /* + * Setting the relevant bits in CPUACTLR_EL1 has to be done in 2 + * instructions here because the resulting bitmask doesn't fit in a + * 16-bit value so it cannot be encoded in a single instruction. + */ + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA + orr x1, x1, #(CORTEX_A57_CPUACTLR_EL1_DIS_L1_STREAMING | \ + CORTEX_A57_CPUACTLR_EL1_DIS_STREAMING) + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_828024_wa + +func check_errata_828024 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_828024 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #829520. + * This applies only to revision <= r1p2 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_829520_wa + /* + * Compare x0 against revision r1p2 + */ + mov x17, x30 + bl check_errata_829520 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_INDIRECT_PREDICTOR + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_829520_wa + +func check_errata_829520 + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_829520 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #833471. + * This applies only to revision <= r1p2 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_833471_wa + /* + * Compare x0 against revision r1p2 + */ + mov x17, x30 + bl check_errata_833471 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_FORCE_FPSCR_FLUSH + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_833471_wa + +func check_errata_833471 + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_833471 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #859972. + * This applies only to revision <= r1p3 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: + * -------------------------------------------------- + */ +func errata_a57_859972_wa + mov x17, x30 + bl check_errata_859972 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_859972_wa + +func check_errata_859972 + mov x1, #0x13 + b cpu_rev_var_ls +endfunc check_errata_859972 + +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + + /* -------------------------------------------------- + * Errata workaround for Cortex A57 Errata #1319537. + * This applies to all revisions of Cortex A57. + * -------------------------------------------------- + */ +func check_errata_1319537 +#if ERRATA_A57_1319537 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_1319537 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A57. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a57_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A57_806969 + mov x0, x18 + bl errata_a57_806969_wa +#endif + +#if ERRATA_A57_813420 + mov x0, x18 + bl errata_a57_813420_wa +#endif + +#if ERRATA_A57_814670 + mov x0, x18 + bl errata_a57_814670_wa +#endif + +#if A57_DISABLE_NON_TEMPORAL_HINT + mov x0, x18 + bl a57_disable_ldnp_overread +#endif + +#if ERRATA_A57_826974 + mov x0, x18 + bl errata_a57_826974_wa +#endif + +#if ERRATA_A57_826977 + mov x0, x18 + bl errata_a57_826977_wa +#endif + +#if ERRATA_A57_828024 + mov x0, x18 + bl errata_a57_828024_wa +#endif + +#if ERRATA_A57_829520 + mov x0, x18 + bl errata_a57_829520_wa +#endif + +#if ERRATA_A57_833471 + mov x0, x18 + bl errata_a57_833471_wa +#endif + +#if ERRATA_A57_859972 + mov x0, x18 + bl errata_a57_859972_wa +#endif + +#if IMAGE_BL31 && ( WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 ) + /* --------------------------------------------------------------- + * Override vector table & enable existing workaround if either of + * the build flags are enabled + * --------------------------------------------------------------- + */ + adr x0, wa_cve_2017_5715_mmu_vbar + msr vbar_el3, x0 + /* isb will be performed before returning from this function */ +#endif + +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A57_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A57_CPUACTLR_EL1_DIS_LOAD_PASS_STORE + msr CORTEX_A57_CPUACTLR_EL1, x0 + isb + dsb sy +#endif + +#if A57_ENABLE_NONCACHEABLE_LOAD_FWD + /* --------------------------------------------- + * Enable higher performance non-cacheable load + * forwarding + * --------------------------------------------- + */ + mrs x0, CORTEX_A57_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A57_CPUACTLR_EL1_EN_NC_LOAD_FWD + msr CORTEX_A57_CPUACTLR_EL1, x0 +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + mrs x0, CORTEX_A57_ECTLR_EL1 + orr x0, x0, #CORTEX_A57_ECTLR_SMP_BIT + msr CORTEX_A57_ECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a57_reset_func + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + +func check_smccc_arch_workaround_3 + mov x0, #ERRATA_APPLIES + ret +endfunc check_smccc_arch_workaround_3 + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A57. + * ---------------------------------------------------- + */ +func cortex_a57_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a57_disable_dcache + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a57_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a57_disable_ext_debug +endfunc cortex_a57_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A57. + * ------------------------------------------------------- + */ +func cortex_a57_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a57_disable_dcache + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a57_disable_l2_prefetch + +#if !SKIP_A57_L1_FLUSH_PWR_DWN + /* ------------------------------------------------- + * Flush the L1 caches. + * ------------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 +#endif + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* ------------------------------------------------- + * Flush the L2 caches. + * ------------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a57_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a57_disable_ext_debug +endfunc cortex_a57_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A57. Must follow AAPCS. + */ +func cortex_a57_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A57_806969, cortex_a57, 806969 + report_errata ERRATA_A57_813419, cortex_a57, 813419 + report_errata ERRATA_A57_813420, cortex_a57, 813420 + report_errata ERRATA_A57_814670, cortex_a57, 814670 + report_errata ERRATA_A57_817169, cortex_a57, 817169 + report_errata A57_DISABLE_NON_TEMPORAL_HINT, cortex_a57, \ + disable_ldnp_overread + report_errata ERRATA_A57_826974, cortex_a57, 826974 + report_errata ERRATA_A57_826977, cortex_a57, 826977 + report_errata ERRATA_A57_828024, cortex_a57, 828024 + report_errata ERRATA_A57_829520, cortex_a57, 829520 + report_errata ERRATA_A57_833471, cortex_a57, 833471 + report_errata ERRATA_A57_859972, cortex_a57, 859972 + report_errata ERRATA_A57_1319537, cortex_a57, 1319537 + report_errata WORKAROUND_CVE_2017_5715, cortex_a57, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a57, cve_2018_3639 + report_errata WORKAROUND_CVE_2022_23960, cortex_a57, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a57_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a57 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_a57_regs, "aS" +cortex_a57_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", "" + +func cortex_a57_cpu_reg_dump + adr x6, cortex_a57_regs + mrs x8, CORTEX_A57_ECTLR_EL1 + mrs x9, CORTEX_A57_MERRSR_EL1 + mrs x10, CORTEX_A57_L2MERRSR_EL1 + ret +endfunc cortex_a57_cpu_reg_dump + +declare_cpu_ops_wa cortex_a57, CORTEX_A57_MIDR, \ + cortex_a57_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + check_smccc_arch_workaround_3, \ + cortex_a57_core_pwr_dwn, \ + cortex_a57_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S new file mode 100644 index 0000000..666324c --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if !HW_ASSISTED_COHERENCY +#error "Cortex-A65 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS +#error "Cortex-A65 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +/* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A65. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a65_reset_func + mov x19, x30 + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + ret x19 +endfunc cortex_a65_reset_func + +func cortex_a65_cpu_pwr_dwn + mrs x0, CORTEX_A65_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A65_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A65_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a65_cpu_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A65. Must follow AAPCS. + */ +func cortex_a65_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_DSU_936184, cortex_a65, dsu_936184 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a65_errata_report +#endif + +.section .rodata.cortex_a65_regs, "aS" +cortex_a65_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a65_cpu_reg_dump + adr x6, cortex_a65_regs + mrs x8, CORTEX_A65_ECTLR_EL1 + ret +endfunc cortex_a65_cpu_reg_dump + +declare_cpu_ops cortex_a65, CORTEX_A65_MIDR, \ + cortex_a65_reset_func, \ + cortex_a65_cpu_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S new file mode 100644 index 0000000..ac6583e --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if !HW_ASSISTED_COHERENCY +#error "Cortex-A65AE must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS +#error "Cortex-A65AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +/* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A65. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a65ae_reset_func + mov x19, x30 + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + ret x19 +endfunc cortex_a65ae_reset_func + +func cortex_a65ae_cpu_pwr_dwn + mrs x0, CORTEX_A65AE_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A65AE_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A65AE_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a65ae_cpu_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A65AE. Must follow AAPCS. + */ +func cortex_a65ae_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_DSU_936184, cortex_a65ae, dsu_936184 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a65ae_errata_report +#endif + +.section .rodata.cortex_a65ae_regs, "aS" +cortex_a65ae_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a65ae_cpu_reg_dump + adr x6, cortex_a65ae_regs + mrs x8, CORTEX_A65AE_ECTLR_EL1 + ret +endfunc cortex_a65ae_cpu_reg_dump + +declare_cpu_ops cortex_a65ae, CORTEX_A65AE_MIDR, \ + cortex_a65ae_reset_func, \ + cortex_a65ae_cpu_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S new file mode 100644 index 0000000..aea62ae --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex A710 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex A710 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A710_BHB_LOOP_COUNT, cortex_a710 +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 1987031. + * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710. It is still + * open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a710_1987031_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_1987031 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0,=0x6 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xF3A08002 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFF0F7FE + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000001003ff + msr S3_6_c15_c8_1,x0 + ldr x0,=0x7 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xBF200000 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0000 + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000001003f3 + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_a710_1987031_wa + +func check_errata_1987031 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1987031 + +/* -------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2081180. + * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710. + * It is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a710_2081180_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2081180 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0,=0x3 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xF3A08002 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFF0F7FE + msr S3_6_c15_c8_3,x0 + ldr x0,=0x10002001003FF + msr S3_6_c15_c8_1,x0 + ldr x0,=0x4 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xBF200000 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0000 + msr S3_6_c15_c8_3,x0 + ldr x0,=0x10002001003F3 + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_a710_2081180_wa + +func check_errata_2081180 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2081180 + +/* --------------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2055002. + * This applies to revision r1p0, r2p0 of Cortex-A710 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func errata_a710_2055002_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2055002 + cbz x0, 1f + mrs x1, CORTEX_A710_CPUACTLR_EL1 + orr x1, x1, CORTEX_A710_CPUACTLR_EL1_BIT_46 + msr CORTEX_A710_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a710_2055002_wa + +func check_errata_2055002 + /* Applies to r1p0, r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2055002 + +/* ------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2017096. + * This applies to revisions r0p0, r1p0 and r2p0 of Cortex-A710. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ------------------------------------------------------------- + */ +func errata_a710_2017096_wa + /* Compare x0 against revision r0p0 to r2p0 */ + mov x17, x30 + bl check_errata_2017096 + cbz x0, 1f + mrs x1, CORTEX_A710_CPUECTLR_EL1 + orr x1, x1, CORTEX_A710_CPUECTLR_EL1_PFSTIDIS_BIT + msr CORTEX_A710_CPUECTLR_EL1, x1 + +1: + ret x17 +endfunc errata_a710_2017096_wa + +func check_errata_2017096 + /* Applies to r0p0, r1p0, r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2017096 + + +/* --------------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2083908. + * This applies to revision r2p0 of Cortex-A710 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func errata_a710_2083908_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2083908 + cbz x0, 1f + mrs x1, CORTEX_A710_CPUACTLR5_EL1 + orr x1, x1, CORTEX_A710_CPUACTLR5_EL1_BIT_13 + msr CORTEX_A710_CPUACTLR5_EL1, x1 +1: + ret x17 +endfunc errata_a710_2083908_wa + +func check_errata_2083908 + /* Applies to r2p0 */ + mov x1, #CPU_REV(2, 0) + mov x2, #CPU_REV(2, 0) + b cpu_rev_var_range +endfunc check_errata_2083908 + +/* --------------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2058056. + * This applies to revisions r0p0, r1p0 and r2p0 of Cortex-A710 and is still + * open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func errata_a710_2058056_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2058056 + cbz x0, 1f + mrs x1, CORTEX_A710_CPUECTLR2_EL1 + mov x0, #CORTEX_A710_CPUECTLR2_EL1_PF_MODE_CNSRV + bfi x1, x0, #CPUECTLR2_EL1_PF_MODE_LSB, #CPUECTLR2_EL1_PF_MODE_WIDTH + msr CORTEX_A710_CPUECTLR2_EL1, x1 +1: + ret x17 +endfunc errata_a710_2058056_wa + +func check_errata_2058056 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2058056 + +/* -------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2267065. + * This applies to revisions r0p0, r1p0 and r2p0. + * It is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_a710_2267065_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2267065 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, CORTEX_A710_CPUACTLR_EL1 + orr x1, x1, CORTEX_A710_CPUACTLR_EL1_BIT_22 + msr CORTEX_A710_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a710_2267065_wa + +func check_errata_2267065 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2267065 + +/* --------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2136059. + * This applies to revision r0p0, r1p0 and r2p0. + * It is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------- + */ +func errata_a710_2136059_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2136059 + cbz x0, 1f + + /* Apply the workaround */ + mrs x1, CORTEX_A710_CPUACTLR5_EL1 + orr x1, x1, CORTEX_A710_CPUACTLR5_EL1_BIT_44 + msr CORTEX_A710_CPUACTLR5_EL1, x1 + +1: + ret x17 +endfunc errata_a710_2136059_wa + +func check_errata_2136059 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2136059 + +/* --------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2282622. + * This applies to revision r0p0, r1p0 and r2p0. + * It is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * --------------------------------------------------------------- + */ +func errata_a710_2282622_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2282622 + cbz x0, 1f + + /* Apply the workaround */ + mrs x1, CORTEX_A710_CPUACTLR2_EL1 + orr x1, x1, BIT(0) + msr CORTEX_A710_CPUACTLR2_EL1, x1 + +1: + ret x17 +endfunc errata_a710_2282622_wa + +func check_errata_2282622 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2282622 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_a710_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_A710_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A710_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A710_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a710_core_pwr_dwn + +#if REPORT_ERRATA + /* + * Errata printing function for Cortex-A710. Must follow AAPCS. + */ +func cortex_a710_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A710_1987031, cortex_a710, 1987031 + report_errata ERRATA_A710_2081180, cortex_a710, 2081180 + report_errata ERRATA_A710_2055002, cortex_a710, 2055002 + report_errata ERRATA_A710_2017096, cortex_a710, 2017096 + report_errata ERRATA_A710_2083908, cortex_a710, 2083908 + report_errata ERRATA_A710_2058056, cortex_a710, 2058056 + report_errata ERRATA_A710_2267065, cortex_a710, 2267065 + report_errata ERRATA_A710_2136059, cortex_a710, 2136059 + report_errata ERRATA_A710_2282622, cortex_a710, 2282622 + report_errata WORKAROUND_CVE_2022_23960, cortex_a710, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a710_errata_report +#endif + +func cortex_a710_reset_func + mov x19, x30 + + /* Disable speculative loads */ + msr SSBS, xzr + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A710_1987031 + mov x0, x18 + bl errata_a710_1987031_wa +#endif + +#if ERRATA_A710_2081180 + mov x0, x18 + bl errata_a710_2081180_wa +#endif + +#if ERRATA_A710_2055002 + mov x0, x18 + bl errata_a710_2055002_wa +#endif + +#if ERRATA_A710_2017096 + mov x0, x18 + bl errata_a710_2017096_wa +#endif + +#if ERRATA_A710_2083908 + mov x0, x18 + bl errata_a710_2083908_wa +#endif + +#if ERRATA_A710_2058056 + mov x0, x18 + bl errata_a710_2058056_wa +#endif + +#if ERRATA_A710_2267065 + mov x0, x18 + bl errata_a710_2267065_wa +#endif + +#if ERRATA_A710_2136059 + mov x0, x18 + bl errata_a710_2136059_wa +#endif + +#if ERRATA_A710_2282622 + mov x0, x18 + bl errata_a710_2282622_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A710 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a710 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_a710_reset_func + + /* --------------------------------------------- + * This function provides Cortex-A710 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_a710_regs, "aS" +cortex_a710_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a710_cpu_reg_dump + adr x6, cortex_a710_regs + mrs x8, CORTEX_A710_CPUECTLR_EL1 + ret +endfunc cortex_a710_cpu_reg_dump + +declare_cpu_ops cortex_a710, CORTEX_A710_MIDR, \ + cortex_a710_reset_func, \ + cortex_a710_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S new file mode 100644 index 0000000..de2d36e --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A72_BHB_LOOP_COUNT, cortex_a72 +#endif /* WORKAROUND_CVE_2022_23960 */ + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func cortex_a72_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a72_disable_dcache + + /* --------------------------------------------- + * Disable all types of L2 prefetches. + * --------------------------------------------- + */ +func cortex_a72_disable_l2_prefetch + mrs x0, CORTEX_A72_ECTLR_EL1 + orr x0, x0, #CORTEX_A72_ECTLR_DIS_TWD_ACC_PFTCH_BIT + mov x1, #CORTEX_A72_ECTLR_L2_IPFTCH_DIST_MASK + orr x1, x1, #CORTEX_A72_ECTLR_L2_DPFTCH_DIST_MASK + bic x0, x0, x1 + msr CORTEX_A72_ECTLR_EL1, x0 + isb + ret +endfunc cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ +func cortex_a72_disable_hw_prefetcher + mrs x0, CORTEX_A72_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH + msr CORTEX_A72_CPUACTLR_EL1, x0 + isb + dsb ish + ret +endfunc cortex_a72_disable_hw_prefetcher + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a72_disable_smp + mrs x0, CORTEX_A72_ECTLR_EL1 + bic x0, x0, #CORTEX_A72_ECTLR_SMP_BIT + msr CORTEX_A72_ECTLR_EL1, x0 + ret +endfunc cortex_a72_disable_smp + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func cortex_a72_disable_ext_debug + mov x0, #1 + msr osdlr_el1, x0 + isb + dsb sy + ret +endfunc cortex_a72_disable_ext_debug + + /* -------------------------------------------------- + * Errata Workaround for Cortex A72 Errata #859971. + * This applies only to revision <= r0p3 of Cortex A72. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: + * -------------------------------------------------- + */ +func errata_a72_859971_wa + mov x17,x30 + bl check_errata_859971 + cbz x0, 1f + mrs x1, CORTEX_A72_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH + msr CORTEX_A72_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a72_859971_wa + +func check_errata_859971 + mov x1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_859971 + +func check_errata_cve_2017_5715 + cpu_check_csv2 x0, 1f +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + + /* -------------------------------------------------- + * Errata workaround for Cortex A72 Errata #1319367. + * This applies to all revisions of Cortex A72. + * -------------------------------------------------- + */ +func check_errata_1319367 +#if ERRATA_A72_1319367 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_1319367 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + +func check_smccc_arch_workaround_3 + cpu_check_csv2 x0, 1f + mov x0, #ERRATA_APPLIES + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_smccc_arch_workaround_3 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A72. + * ------------------------------------------------- + */ +func cortex_a72_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A72_859971 + mov x0, x18 + bl errata_a72_859971_wa +#endif + +#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) + cpu_check_csv2 x0, 1f + adr x0, wa_cve_2017_5715_mmu_vbar + msr vbar_el3, x0 + /* isb will be performed before returning from this function */ + + /* Skip CVE_2022_23960 mitigation if cve_2017_5715 mitigation applied */ + b 2f +1: +#if WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A72 generic vectors are overridden to apply the + * mitigation on exception entry from lower ELs for revisions >= r1p0 + * which has CSV2 implemented. + */ + adr x0, wa_cve_vbar_cortex_a72 + msr vbar_el3, x0 + + /* isb will be performed before returning from this function */ +#endif /* WORKAROUND_CVE_2022_23960 */ +2: +#endif /* IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */ + +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A72_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A72_CPUACTLR_EL1_DIS_LOAD_PASS_STORE + msr CORTEX_A72_CPUACTLR_EL1, x0 + isb + dsb sy +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + mrs x0, CORTEX_A72_ECTLR_EL1 + orr x0, x0, #CORTEX_A72_ECTLR_SMP_BIT + msr CORTEX_A72_ECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a72_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A72. + * ---------------------------------------------------- + */ +func cortex_a72_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a72_disable_dcache + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ + bl cortex_a72_disable_hw_prefetcher + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a72_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a72_disable_ext_debug +endfunc cortex_a72_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A72. + * ------------------------------------------------------- + */ +func cortex_a72_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a72_disable_dcache + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ + bl cortex_a72_disable_hw_prefetcher + +#if !SKIP_A72_L1_FLUSH_PWR_DWN + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 +#endif + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* ------------------------------------------------- + * Flush the L2 caches. + * ------------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a72_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a72_disable_ext_debug +endfunc cortex_a72_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A72. Must follow AAPCS. + */ +func cortex_a72_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A72_859971, cortex_a72, 859971 + report_errata ERRATA_A72_1319367, cortex_a72, 1319367 + report_errata WORKAROUND_CVE_2017_5715, cortex_a72, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a72, cve_2018_3639 + report_errata WORKAROUND_CVE_2022_23960, cortex_a72, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a72_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a72 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_a72_regs, "aS" +cortex_a72_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", "" + +func cortex_a72_cpu_reg_dump + adr x6, cortex_a72_regs + mrs x8, CORTEX_A72_ECTLR_EL1 + mrs x9, CORTEX_A72_MERRSR_EL1 + mrs x10, CORTEX_A72_L2MERRSR_EL1 + ret +endfunc cortex_a72_cpu_reg_dump + +declare_cpu_ops_wa cortex_a72, CORTEX_A72_MIDR, \ + cortex_a72_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + check_smccc_arch_workaround_3, \ + cortex_a72_core_pwr_dwn, \ + cortex_a72_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S new file mode 100644 index 0000000..edcd1f5 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable L1 data cache + * --------------------------------------------- + */ +func cortex_a73_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a73_disable_dcache + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a73_disable_smp + mrs x0, CORTEX_A73_CPUECTLR_EL1 + bic x0, x0, #CORTEX_A73_CPUECTLR_SMP_BIT + msr CORTEX_A73_CPUECTLR_EL1, x0 + isb + dsb sy + ret +endfunc cortex_a73_disable_smp + + /* --------------------------------------------------- + * Errata Workaround for Cortex A73 Errata #852427. + * This applies only to revision r0p0 of Cortex A73. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a73_852427_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_852427 + cbz x0, 1f + mrs x1, CORTEX_A73_DIAGNOSTIC_REGISTER + orr x1, x1, #(1 << 12) + msr CORTEX_A73_DIAGNOSTIC_REGISTER, x1 + isb +1: + ret x17 +endfunc errata_a73_852427_wa + +func check_errata_852427 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_852427 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A73 Errata #855423. + * This applies only to revision <= r0p1 of Cortex A73. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a73_855423_wa + /* + * Compare x0 against revision r0p1 + */ + mov x17, x30 + bl check_errata_855423 + cbz x0, 1f + mrs x1, CORTEX_A73_IMP_DEF_REG2 + orr x1, x1, #(1 << 7) + msr CORTEX_A73_IMP_DEF_REG2, x1 + isb +1: + ret x17 +endfunc errata_a73_855423_wa + +func check_errata_855423 + mov x1, #0x01 + b cpu_rev_var_ls +endfunc check_errata_855423 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A73. + * ------------------------------------------------- + */ + +func cortex_a73_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A73_852427 + mov x0, x18 + bl errata_a73_852427_wa +#endif + +#if ERRATA_A73_855423 + mov x0, x18 + bl errata_a73_855423_wa +#endif + +#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) + cpu_check_csv2 x0, 1f + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb + /* Skip installing vector table again for CVE_2022_23960 */ + b 2f +1: +#if WORKAROUND_CVE_2022_23960 + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb +#endif +2: +#endif /* IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */ + +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A73_IMP_DEF_REG1 + orr x0, x0, #CORTEX_A73_IMP_DEF_REG1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A73_IMP_DEF_REG1, x0 + isb +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * Clobbers : x0 + * --------------------------------------------- + */ + mrs x0, CORTEX_A73_CPUECTLR_EL1 + orr x0, x0, #CORTEX_A73_CPUECTLR_SMP_BIT + msr CORTEX_A73_CPUECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a73_reset_func + +func cortex_a73_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a73_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a73_disable_smp +endfunc cortex_a73_core_pwr_dwn + +func cortex_a73_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a73_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a73_disable_smp +endfunc cortex_a73_cluster_pwr_dwn + +func check_errata_cve_2017_5715 + cpu_check_csv2 x0, 1f +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 + cpu_check_csv2 x0, 1f + mov x0, #ERRATA_APPLIES + ret + 1: +# if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +# else + mov x0, #ERRATA_MISSING +# endif /* WORKAROUND_CVE_2022_23960 */ + ret +#endif /* WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 */ + mov x0, #ERRATA_MISSING + ret +endfunc check_errata_cve_2022_23960 + +func check_smccc_arch_workaround_3 + mov x0, #ERRATA_APPLIES + ret +endfunc check_smccc_arch_workaround_3 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A75. Must follow AAPCS. + */ +func cortex_a73_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A73_852427, cortex_a73, 852427 + report_errata ERRATA_A73_855423, cortex_a73, 855423 + report_errata WORKAROUND_CVE_2017_5715, cortex_a73, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a73, cve_2018_3639 + report_errata WORKAROUND_CVE_2022_23960, cortex_a73, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a73_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a73 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_a73_regs, "aS" +cortex_a73_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "l2merrsr_el1", "" + +func cortex_a73_cpu_reg_dump + adr x6, cortex_a73_regs + mrs x8, CORTEX_A73_CPUECTLR_EL1 + mrs x9, CORTEX_A73_L2MERRSR_EL1 + ret +endfunc cortex_a73_cpu_reg_dump + +declare_cpu_ops_wa cortex_a73, CORTEX_A73_MIDR, \ + cortex_a73_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + check_smccc_arch_workaround_3, \ + cortex_a73_core_pwr_dwn, \ + cortex_a73_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S new file mode 100644 index 0000000..d561be4 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A75 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + + /* -------------------------------------------------- + * Errata Workaround for Cortex A75 Errata #764081. + * This applies only to revision r0p0 of Cortex A75. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a75_764081_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_764081 + cbz x0, 1f + mrs x1, sctlr_el3 + orr x1, x1 ,#SCTLR_IESB_BIT + msr sctlr_el3, x1 + isb +1: + ret x17 +endfunc errata_a75_764081_wa + +func check_errata_764081 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_764081 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A75 Errata #790748. + * This applies only to revision r0p0 of Cortex A75. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a75_790748_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_790748 + cbz x0, 1f + mrs x1, CORTEX_A75_CPUACTLR_EL1 + orr x1, x1 ,#(1 << 13) + msr CORTEX_A75_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a75_790748_wa + +func check_errata_790748 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_790748 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A75. + * ------------------------------------------------- + */ +func cortex_a75_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A75_764081 + mov x0, x18 + bl errata_a75_764081_wa +#endif + +#if ERRATA_A75_790748 + mov x0, x18 + bl errata_a75_790748_wa +#endif + +#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) + cpu_check_csv2 x0, 1f + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb + /* Skip installing vector table again for CVE_2022_23960 */ + b 2f +1: +#if WORKAROUND_CVE_2022_23960 + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb +#endif +2: +#endif /* IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */ + +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A75_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A75_CPUACTLR_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A75_CPUACTLR_EL1, x0 + isb +#endif + +#if ERRATA_DSU_798953 + bl errata_dsu_798953_wa +#endif + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT + msr actlr_el3, x0 + isb + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT + msr actlr_el2, x0 + isb + + /* Enable group0 counters */ + mov x0, #CORTEX_A75_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 + isb + + /* Enable group1 counters */ + mov x0, #CORTEX_A75_AMU_GROUP1_MASK + msr CPUAMCNTENSET_EL0, x0 + isb +#endif + ret x19 +endfunc cortex_a75_reset_func + +func check_errata_cve_2017_5715 + cpu_check_csv2 x0, 1f +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 + cpu_check_csv2 x0, 1f + mov x0, #ERRATA_APPLIES + ret +1: +# if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +# else + mov x0, #ERRATA_MISSING +# endif /* WORKAROUND_CVE_2022_23960 */ + ret +#endif /* WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 */ + mov x0, #ERRATA_MISSING + ret +endfunc check_errata_cve_2022_23960 + +func check_smccc_arch_workaround_3 + mov x0, #ERRATA_APPLIES + ret +endfunc check_smccc_arch_workaround_3 + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a75_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A75_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A75_CORE_PWRDN_EN_MASK + msr CORTEX_A75_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a75_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A75. Must follow AAPCS. + */ +func cortex_a75_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A75_764081, cortex_a75, 764081 + report_errata ERRATA_A75_790748, cortex_a75, 790748 + report_errata WORKAROUND_CVE_2017_5715, cortex_a75, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a75, cve_2018_3639 + report_errata ERRATA_DSU_798953, cortex_a75, dsu_798953 + report_errata ERRATA_DSU_936184, cortex_a75, dsu_936184 + report_errata WORKAROUND_CVE_2022_23960, cortex_a75, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a75_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a75 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_a75_regs, "aS" +cortex_a75_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a75_cpu_reg_dump + adr x6, cortex_a75_regs + mrs x8, CORTEX_A75_CPUECTLR_EL1 + ret +endfunc cortex_a75_cpu_reg_dump + +declare_cpu_ops_wa cortex_a75, CORTEX_A75_MIDR, \ + cortex_a75_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + check_smccc_arch_workaround_3, \ + cortex_a75_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c new file mode 100644 index 0000000..bd2c697 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static void *cortex_a75_context_save(const void *arg) +{ + if (midr_match(CORTEX_A75_MIDR) != 0) + cpuamu_context_save(CORTEX_A75_AMU_NR_COUNTERS); + + return (void *)0; +} + +static void *cortex_a75_context_restore(const void *arg) +{ + if (midr_match(CORTEX_A75_MIDR) != 0) + cpuamu_context_restore(CORTEX_A75_AMU_NR_COUNTERS); + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_a75_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, cortex_a75_context_restore); diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S new file mode 100644 index 0000000..50bd8cd --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S @@ -0,0 +1,812 @@ +/* + * 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 "wa_cve_2022_23960_bhb.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A76 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex-A76 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#define ESR_EL3_A64_SMC0 0x5e000000 +#define ESR_EL3_A32_SMC0 0x4e000000 + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + /* + * This macro applies the mitigation for CVE-2018-3639. + * It implements a fast path where `SMCCC_ARCH_WORKAROUND_2` + * SMC calls from a lower EL running in AArch32 or AArch64 + * will go through the fast and return early. + * + * The macro saves x2-x3 to the context. In the fast path + * x0-x3 registers do not need to be restored as the calling + * context will have saved them. The macro also saves + * x29-x30 to the context in the sync_exception path. + */ + .macro apply_cve_2018_3639_wa _is_sync_exception _esr_el3_val + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + .if \_is_sync_exception + stp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + mov_imm w2, \_esr_el3_val + bl apply_cve_2018_3639_sync_wa + ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + .endif + /* + * Always enable v4 mitigation during EL3 execution. This is not + * required for the fast path above because it does not perform any + * memory loads. + */ + mrs x2, CORTEX_A76_CPUACTLR2_EL1 + orr x2, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x2 + isb + + /* + * The caller may have passed arguments to EL3 via x2-x3. + * Restore these registers from the context before jumping to the + * main runtime vector table entry. + */ + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + .endm +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 || WORKAROUND_CVE_2022_23960 +vector_base cortex_a76_wa_cve_vbar + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_sp_el0 + b sync_exception_sp_el0 +end_vector_entry cortex_a76_sync_exception_sp_el0 + +vector_entry cortex_a76_irq_sp_el0 + b irq_sp_el0 +end_vector_entry cortex_a76_irq_sp_el0 + +vector_entry cortex_a76_fiq_sp_el0 + b fiq_sp_el0 +end_vector_entry cortex_a76_fiq_sp_el0 + +vector_entry cortex_a76_serror_sp_el0 + b serror_sp_el0 +end_vector_entry cortex_a76_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_sp_elx + b sync_exception_sp_elx +end_vector_entry cortex_a76_sync_exception_sp_elx + +vector_entry cortex_a76_irq_sp_elx + b irq_sp_elx +end_vector_entry cortex_a76_irq_sp_elx + +vector_entry cortex_a76_fiq_sp_elx + b fiq_sp_elx +end_vector_entry cortex_a76_fiq_sp_elx + +vector_entry cortex_a76_serror_sp_elx + b serror_sp_elx +end_vector_entry cortex_a76_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_aarch64 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A64_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b sync_exception_aarch64 +end_vector_entry cortex_a76_sync_exception_aarch64 + +vector_entry cortex_a76_irq_aarch64 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b irq_aarch64 +end_vector_entry cortex_a76_irq_aarch64 + +vector_entry cortex_a76_fiq_aarch64 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b fiq_aarch64 +end_vector_entry cortex_a76_fiq_aarch64 + +vector_entry cortex_a76_serror_aarch64 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b serror_aarch64 +end_vector_entry cortex_a76_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_aarch32 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A32_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b sync_exception_aarch32 +end_vector_entry cortex_a76_sync_exception_aarch32 + +vector_entry cortex_a76_irq_aarch32 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b irq_aarch32 +end_vector_entry cortex_a76_irq_aarch32 + +vector_entry cortex_a76_fiq_aarch32 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b fiq_aarch32 +end_vector_entry cortex_a76_fiq_aarch32 + +vector_entry cortex_a76_serror_aarch32 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b serror_aarch32 +end_vector_entry cortex_a76_serror_aarch32 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 || WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + /* + * ----------------------------------------------------------------- + * This function applies the mitigation for CVE-2018-3639 + * specifically for sync exceptions. It implements a fast path + * where `SMCCC_ARCH_WORKAROUND_2` SMC calls from a lower EL + * running in AArch64 will go through the fast and return early. + * + * In the fast path x0-x3 registers do not need to be restored as the + * calling context will have saved them. + * + * Caller must pass value of esr_el3 to compare via x2. + * Save and restore these registers outside of this function from the + * context before jumping to the main runtime vector table entry. + * + * Shall clobber: x0-x3, x30 + * ----------------------------------------------------------------- + */ +func apply_cve_2018_3639_sync_wa + /* + * Ensure SMC is coming from A64/A32 state on #0 + * with W0 = SMCCC_ARCH_WORKAROUND_2 + * + * This sequence evaluates as: + * (W0==SMCCC_ARCH_WORKAROUND_2) ? (ESR_EL3==SMC#0) : (NE) + * allowing use of a single branch operation + * X2 populated outside this function with the SMC FID. + */ + orr w3, wzr, #SMCCC_ARCH_WORKAROUND_2 + cmp x0, x3 + mrs x3, esr_el3 + + ccmp w2, w3, #0, eq + /* + * Static predictor will predict a fall-through, optimizing + * the `SMCCC_ARCH_WORKAROUND_2` fast path. + */ + bne 1f + + /* + * The sequence below implements the `SMCCC_ARCH_WORKAROUND_2` + * fast path. + */ + cmp x1, xzr /* enable/disable check */ + + /* + * When the calling context wants mitigation disabled, + * we program the mitigation disable function in the + * CPU context, which gets invoked on subsequent exits from + * EL3 via the `el3_exit` function. Otherwise NULL is + * programmed in the CPU context, which results in caller's + * inheriting the EL3 mitigation state (enabled) on subsequent + * `el3_exit`. + */ + mov x0, xzr + adr x1, cortex_a76_disable_wa_cve_2018_3639 + csel x1, x1, x0, eq + str x1, [sp, #CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_DISABLE] + + mrs x2, CORTEX_A76_CPUACTLR2_EL1 + orr x1, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + bic x3, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + csel x3, x3, x1, eq + msr CORTEX_A76_CPUACTLR2_EL1, x3 + ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + /* + * `SMCCC_ARCH_WORKAROUND_2`fast path return to lower EL. + */ + exception_return /* exception_return contains ISB */ +1: + ret +endfunc apply_cve_2018_3639_sync_wa +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */ + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1073348. + * This applies only to revision <= r1p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1073348_wa + /* + * Compare x0 against revision r1p0 + */ + mov x17, x30 + bl check_errata_1073348 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUACTLR_EL1 + orr x1, x1 ,#CORTEX_A76_CPUACTLR_EL1_DISABLE_STATIC_PREDICTION + msr CORTEX_A76_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1073348_wa + +func check_errata_1073348 + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1073348 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1130799. + * This applies only to revision <= r2p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1130799_wa + /* + * Compare x0 against revision r2p0 + */ + mov x17, x30 + bl check_errata_1130799 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUACTLR2_EL1 + orr x1, x1 ,#(1 << 59) + msr CORTEX_A76_CPUACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1130799_wa + +func check_errata_1130799 + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1130799 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1220197. + * This applies only to revision <= r2p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1220197_wa +/* + * Compare x0 against revision r2p0 + */ + mov x17, x30 + bl check_errata_1220197 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUECTLR_EL1 + orr x1, x1, #CORTEX_A76_CPUECTLR_EL1_WS_THR_L2 + msr CORTEX_A76_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1220197_wa + +func check_errata_1220197 + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1220197 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1257314. + * This applies only to revision <= r3p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1257314_wa + /* + * Compare x0 against revision r3p0 + */ + mov x17, x30 + bl check_errata_1257314 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUACTLR3_EL1 + orr x1, x1, CORTEX_A76_CPUACTLR3_EL1_BIT_10 + msr CORTEX_A76_CPUACTLR3_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1257314_wa + +func check_errata_1257314 + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1257314 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1262888. + * This applies only to revision <= r3p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1262888_wa + /* + * Compare x0 against revision r3p0 + */ + mov x17, x30 + bl check_errata_1262888 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUECTLR_EL1 + orr x1, x1, CORTEX_A76_CPUECTLR_EL1_BIT_51 + msr CORTEX_A76_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1262888_wa + +func check_errata_1262888 + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1262888 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1286807. + * This applies only to revision <= r3p0 of Cortex A76. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * --------------------------------------------------- + */ +func check_errata_1286807 +#if ERRATA_A76_1286807 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x30 + b cpu_rev_var_ls +#endif +endfunc check_errata_1286807 + + /* -------------------------------------------------- + * Errata workaround for Cortex A76 Errata #1791580. + * This applies to revisions <= r4p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1791580_wa + /* Compare x0 against revision r4p0 */ + mov x17, x30 + bl check_errata_1791580 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUACTLR2_EL1 + orr x1, x1, CORTEX_A76_CPUACTLR2_EL1_BIT_2 + msr CORTEX_A76_CPUACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1791580_wa + +func check_errata_1791580 + /* Applies to everything <=r4p0. */ + mov x1, #0x40 + b cpu_rev_var_ls +endfunc check_errata_1791580 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1262606, + * #1275112, and #1868343. #1262606 and #1275112 + * apply to revisions <= r3p0 and #1868343 applies to + * revisions <= r4p0. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ + +func errata_a76_1262606_1275112_1868343_wa + mov x17, x30 + +/* Check for <= r3p0 cases and branch if check passes. */ +#if ERRATA_A76_1262606 || ERRATA_A76_1275112 + bl check_errata_1262606 + cbnz x0, 1f +#endif + +/* Check for <= r4p0 cases and branch if check fails. */ +#if ERRATA_A76_1868343 + bl check_errata_1868343 + cbz x0, 2f +#endif +1: + mrs x1, CORTEX_A76_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A76_CPUACTLR_EL1_BIT_13 + msr CORTEX_A76_CPUACTLR_EL1, x1 + isb +2: + ret x17 +endfunc errata_a76_1262606_1275112_1868343_wa + +func check_errata_1262606 + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1262606 + +func check_errata_1275112 + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1275112 + +func check_errata_1868343 + mov x1, #0x40 + b cpu_rev_var_ls +endfunc check_errata_1868343 + +/* -------------------------------------------------- + * Errata Workaround for A76 Erratum 1946160. + * This applies to revisions r3p0 - r4p1 of A76. + * It also exists in r0p0 - r2p0 but there is no fix + * in those revisions. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1946160_wa + /* Compare x0 against revisions r3p0 - r4p1 */ + mov x17, x30 + bl check_errata_1946160 + cbz x0, 1f + + mov x0, #3 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3900002 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #4 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #5 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + isb +1: + ret x17 +endfunc errata_a76_1946160_wa + +func check_errata_1946160 + /* Applies to revisions r3p0 - r4p1. */ + mov x1, #0x30 + mov x2, #0x41 + b cpu_rev_var_range +endfunc check_errata_1946160 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + +func cortex_a76_disable_wa_cve_2018_3639 + mrs x0, CORTEX_A76_CPUACTLR2_EL1 + bic x0, x0, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x0 + isb + ret +endfunc cortex_a76_disable_wa_cve_2018_3639 + + /* -------------------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1165522. + * This applies only to revisions <= r3p0 of Cortex A76. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * -------------------------------------------------------------- + */ +func check_errata_1165522 +#if ERRATA_A76_1165522 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x30 + b cpu_rev_var_ls +#endif +endfunc check_errata_1165522 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif /* WORKAROUND_CVE_2022_23960 */ + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A76. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a76_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A76_1073348 + mov x0, x18 + bl errata_a76_1073348_wa +#endif + +#if ERRATA_A76_1130799 + mov x0, x18 + bl errata_a76_1130799_wa +#endif + +#if ERRATA_A76_1220197 + mov x0, x18 + bl errata_a76_1220197_wa +#endif + +#if ERRATA_A76_1257314 + mov x0, x18 + bl errata_a76_1257314_wa +#endif + +#if ERRATA_A76_1262606 || ERRATA_A76_1275112 || ERRATA_A76_1868343 + mov x0, x18 + bl errata_a76_1262606_1275112_1868343_wa +#endif + +#if ERRATA_A76_1262888 + mov x0, x18 + bl errata_a76_1262888_wa +#endif + +#if ERRATA_A76_1791580 + mov x0, x18 + bl errata_a76_1791580_wa +#endif + +#if ERRATA_A76_1946160 + mov x0, x18 + bl errata_a76_1946160_wa +#endif + +#if WORKAROUND_CVE_2018_3639 + /* If the PE implements SSBS, we don't need the dynamic workaround */ + mrs x0, id_aa64pfr1_el1 + lsr x0, x0, #ID_AA64PFR1_EL1_SSBS_SHIFT + and x0, x0, #ID_AA64PFR1_EL1_SSBS_MASK +#if !DYNAMIC_WORKAROUND_CVE_2018_3639 && ENABLE_ASSERTIONS + cmp x0, 0 + ASM_ASSERT(ne) +#endif +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + cbnz x0, 1f + mrs x0, CORTEX_A76_CPUACTLR2_EL1 + orr x0, x0, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x0 + isb + +#ifdef IMAGE_BL31 + /* + * The Cortex-A76 generic vectors are overwritten to use the vectors + * defined above. This is required in order to apply mitigation + * against CVE-2018-3639 on exception entry from lower ELs. + * If the below vector table is used, skip overriding it again for + * CVE_2022_23960 as both use the same vbar. + */ + adr x0, cortex_a76_wa_cve_vbar + msr vbar_el3, x0 + isb + b 2f +#endif /* IMAGE_BL31 */ + +1: +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */ +#endif /* WORKAROUND_CVE_2018_3639 */ + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A76 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. This will be bypassed + * if DYNAMIC_WORKAROUND_CVE_2018_3639 has overridden the vectors. + */ + adr x0, cortex_a76_wa_cve_vbar + msr vbar_el3, x0 + isb +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ +2: + +#if ERRATA_DSU_798953 + bl errata_dsu_798953_wa +#endif + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + ret x19 +endfunc cortex_a76_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a76_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A76_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A76_CORE_PWRDN_EN_MASK + msr CORTEX_A76_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a76_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A76. Must follow AAPCS. + */ +func cortex_a76_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A76_1073348, cortex_a76, 1073348 + report_errata ERRATA_A76_1130799, cortex_a76, 1130799 + report_errata ERRATA_A76_1220197, cortex_a76, 1220197 + report_errata ERRATA_A76_1257314, cortex_a76, 1257314 + report_errata ERRATA_A76_1262606, cortex_a76, 1262606 + report_errata ERRATA_A76_1262888, cortex_a76, 1262888 + report_errata ERRATA_A76_1275112, cortex_a76, 1275112 + report_errata ERRATA_A76_1286807, cortex_a76, 1286807 + report_errata ERRATA_A76_1791580, cortex_a76, 1791580 + report_errata ERRATA_A76_1165522, cortex_a76, 1165522 + report_errata ERRATA_A76_1868343, cortex_a76, 1868343 + report_errata ERRATA_A76_1946160, cortex_a76, 1946160 + report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639 + report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953 + report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184 + report_errata WORKAROUND_CVE_2022_23960, cortex_a76, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a76_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a76 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_a76_regs, "aS" +cortex_a76_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a76_cpu_reg_dump + adr x6, cortex_a76_regs + mrs x8, CORTEX_A76_CPUECTLR_EL1 + ret +endfunc cortex_a76_cpu_reg_dump + +declare_cpu_ops_wa cortex_a76, CORTEX_A76_MIDR, \ + cortex_a76_reset_func, \ + CPU_NO_EXTRA1_FUNC, \ + cortex_a76_disable_wa_cve_2018_3639, \ + CPU_NO_EXTRA3_FUNC, \ + cortex_a76_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S new file mode 100644 index 0000000..5c19548 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A76AE must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex-A76AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A76AE_BHB_LOOP_COUNT, cortex_a76ae +#endif /* WORKAROUND_CVE_2022_23960 */ + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif /* WORKAROUND_CVE_2022_23960 */ + ret +endfunc check_errata_cve_2022_23960 + + /* -------------------------------------------- + * The CPU Ops reset function for Cortex-A76AE. + * Shall clobber: x0-x19 + * -------------------------------------------- + */ +func cortex_a76ae_reset_func +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A76ae generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a76ae + msr vbar_el3, x0 + isb +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + ret +endfunc cortex_a76ae_reset_func + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_a76ae_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_A76AE_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A76AE_CORE_PWRDN_EN_MASK + msr CORTEX_A76AE_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a76ae_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A76AE. Must follow AAPCS. + */ +func cortex_a76ae_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2022_23960, cortex_a76ae, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a76ae_errata_report +#endif /* REPORT_ERRATA */ + + /* --------------------------------------------- + * This function provides cortex_a76ae 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_a76ae_regs, "aS" +cortex_a76ae_regs: /* The ASCII list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a76ae_cpu_reg_dump + adr x6, cortex_a76ae_regs + mrs x8, CORTEX_A76AE_CPUECTLR_EL1 + ret +endfunc cortex_a76ae_cpu_reg_dump + +declare_cpu_ops cortex_a76ae, CORTEX_A76AE_MIDR, cortex_a76ae_reset_func, \ + cortex_a76ae_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S new file mode 100644 index 0000000..e7365e2 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A77 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex-A77 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A77_BHB_LOOP_COUNT, cortex_a77 +#endif /* WORKAROUND_CVE_2022_23960 */ + + /* -------------------------------------------------- + * Errata Workaround for Cortex A77 Errata #1508412. + * This applies only to revision <= r1p0 of Cortex A77. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a77_1508412_wa + /* + * Compare x0 against revision r1p0 + */ + mov x17, x30 + bl check_errata_1508412 + cbz x0, 3f + /* + * Compare x0 against revision r0p0 + */ + bl check_errata_1508412_0 + cbz x0, 1f + ldr x0, =0x0 + msr CORTEX_A77_CPUPSELR_EL3, x0 + ldr x0, =0x00E8400000 + msr CORTEX_A77_CPUPOR_EL3, x0 + ldr x0, =0x00FFE00000 + msr CORTEX_A77_CPUPMR_EL3, x0 + ldr x0, =0x4004003FF + msr CORTEX_A77_CPUPCR_EL3, x0 + ldr x0, =0x1 + msr CORTEX_A77_CPUPSELR_EL3, x0 + ldr x0, =0x00E8C00040 + msr CORTEX_A77_CPUPOR_EL3, x0 + ldr x0, =0x00FFE00040 + msr CORTEX_A77_CPUPMR_EL3, x0 + b 2f +1: + ldr x0, =0x0 + msr CORTEX_A77_CPUPSELR_EL3, x0 + ldr x0, =0x00E8400000 + msr CORTEX_A77_CPUPOR_EL3, x0 + ldr x0, =0x00FF600000 + msr CORTEX_A77_CPUPMR_EL3, x0 + ldr x0, =0x00E8E00080 + msr CORTEX_A77_CPUPOR2_EL3, x0 + ldr x0, =0x00FFE000C0 + msr CORTEX_A77_CPUPMR2_EL3, x0 +2: + ldr x0, =0x04004003FF + msr CORTEX_A77_CPUPCR_EL3, x0 + isb +3: + ret x17 +endfunc errata_a77_1508412_wa + +func check_errata_1508412 + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1508412 + +func check_errata_1508412_0 + mov x1, #0x0 + b cpu_rev_var_ls +endfunc check_errata_1508412_0 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A77 Errata #1925769. + * This applies to revision <= r1p1 of Cortex A77. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a77_1925769_wa + /* Compare x0 against revision <= r1p1 */ + mov x17, x30 + bl check_errata_1925769 + cbz x0, 1f + + /* Set bit 8 in ECTLR_EL1 */ + mrs x1, CORTEX_A77_CPUECTLR_EL1 + orr x1, x1, #CORTEX_A77_CPUECTLR_EL1_BIT_8 + msr CORTEX_A77_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a77_1925769_wa + +func check_errata_1925769 + /* Applies to everything <= r1p1 */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1925769 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A77 Errata #1946167. + * This applies to revision <= r1p1 of Cortex A77. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a77_1946167_wa + /* Compare x0 against revision <= r1p1 */ + mov x17, x30 + bl check_errata_1946167 + cbz x0, 1f + + ldr x0,=0x4 + msr CORTEX_A77_CPUPSELR_EL3,x0 + ldr x0,=0x10E3900002 + msr CORTEX_A77_CPUPOR_EL3,x0 + ldr x0,=0x10FFF00083 + msr CORTEX_A77_CPUPMR_EL3,x0 + ldr x0,=0x2001003FF + msr CORTEX_A77_CPUPCR_EL3,x0 + + ldr x0,=0x5 + msr CORTEX_A77_CPUPSELR_EL3,x0 + ldr x0,=0x10E3800082 + msr CORTEX_A77_CPUPOR_EL3,x0 + ldr x0,=0x10FFF00083 + msr CORTEX_A77_CPUPMR_EL3,x0 + ldr x0,=0x2001003FF + msr CORTEX_A77_CPUPCR_EL3,x0 + + ldr x0,=0x6 + msr CORTEX_A77_CPUPSELR_EL3,x0 + ldr x0,=0x10E3800200 + msr CORTEX_A77_CPUPOR_EL3,x0 + ldr x0,=0x10FFF003E0 + msr CORTEX_A77_CPUPMR_EL3,x0 + ldr x0,=0x2001003FF + msr CORTEX_A77_CPUPCR_EL3,x0 + + isb +1: + ret x17 +endfunc errata_a77_1946167_wa + +func check_errata_1946167 + /* Applies to everything <= r1p1 */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1946167 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A77 Errata #1791578. + * This applies to revisions r0p0, r1p0, and r1p1 and is still open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a77_1791578_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1791578 + cbz x0, 1f + + /* Set bit 2 in ACTLR2_EL1 */ + mrs x1, CORTEX_A77_ACTLR2_EL1 + orr x1, x1, #CORTEX_A77_ACTLR2_EL1_BIT_2 + msr CORTEX_A77_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a77_1791578_wa + +func check_errata_1791578 + /* Applies to r0p0, r1p0, and r1p1 right now */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1791578 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A77. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a77_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A77_1508412 + mov x0, x18 + bl errata_a77_1508412_wa +#endif + +#if ERRATA_A77_1925769 + mov x0, x18 + bl errata_a77_1925769_wa +#endif + +#if ERRATA_A77_1946167 + mov x0, x18 + bl errata_a77_1946167_wa +#endif + +#if ERRATA_A77_1791578 + mov x0, x18 + bl errata_a77_1791578_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A77 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a77 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_a77_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a77_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A77_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A77_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A77_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a77_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A77. Must follow AAPCS. + */ +func cortex_a77_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A77_1508412, cortex_a77, 1508412 + report_errata ERRATA_A77_1925769, cortex_a77, 1925769 + report_errata ERRATA_A77_1946167, cortex_a77, 1946167 + report_errata ERRATA_A77_1791578, cortex_a77, 1791578 + report_errata WORKAROUND_CVE_2022_23960, cortex_a77, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a77_errata_report +#endif + + + /* --------------------------------------------- + * This function provides Cortex-A77 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_a77_regs, "aS" +cortex_a77_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a77_cpu_reg_dump + adr x6, cortex_a77_regs + mrs x8, CORTEX_A77_CPUECTLR_EL1 + ret +endfunc cortex_a77_cpu_reg_dump + +declare_cpu_ops cortex_a77, CORTEX_A77_MIDR, \ + cortex_a77_reset_func, \ + cortex_a77_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S new file mode 100644 index 0000000..1a6f848 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "cortex_a78 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A78_BHB_LOOP_COUNT, cortex_a78 +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for A78 Erratum 1688305. + * This applies to revision r0p0 and r1p0 of A78. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1688305_wa + /* Compare x0 against revision r1p0 */ + mov x17, x30 + bl check_errata_1688305 + cbz x0, 1f + mrs x1, CORTEX_A78_ACTLR2_EL1 + orr x1, x1, #CORTEX_A78_ACTLR2_EL1_BIT_1 + msr CORTEX_A78_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a78_1688305_wa + +func check_errata_1688305 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1688305 + +/* -------------------------------------------------- + * Errata Workaround for Cortex A78 Errata #1941498. + * This applies to revisions r0p0, r1p0, and r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1941498_wa + /* Compare x0 against revision <= r1p1 */ + mov x17, x30 + bl check_errata_1941498 + cbz x0, 1f + + /* Set bit 8 in ECTLR_EL1 */ + mrs x1, CORTEX_A78_CPUECTLR_EL1 + orr x1, x1, #CORTEX_A78_CPUECTLR_EL1_BIT_8 + msr CORTEX_A78_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a78_1941498_wa + +func check_errata_1941498 + /* Check for revision <= r1p1, might need to be updated later. */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1941498 + +/* -------------------------------------------------- + * Errata Workaround for A78 Erratum 1951500. + * This applies to revisions r1p0 and r1p1 of A78. + * The issue also exists in r0p0 but there is no fix + * in that revision. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1951500_wa + /* Compare x0 against revisions r1p0 - r1p1 */ + mov x17, x30 + bl check_errata_1951500 + cbz x0, 1f + + msr S3_6_c15_c8_0, xzr + ldr x0, =0x10E3900002 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + mov x0, #1 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + mov x0, #2 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + isb +1: + ret x17 +endfunc errata_a78_1951500_wa + +func check_errata_1951500 + /* Applies to revisions r1p0 and r1p1. */ + mov x1, #CPU_REV(1, 0) + mov x2, #CPU_REV(1, 1) + b cpu_rev_var_range +endfunc check_errata_1951500 + +/* -------------------------------------------------- + * Errata Workaround for Cortex A78 Errata #1821534. + * This applies to revisions r0p0 and r1p0. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1821534_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_1821534 + cbz x0, 1f + + /* Set bit 2 in ACTLR2_EL1 */ + mrs x1, CORTEX_A78_ACTLR2_EL1 + orr x1, x1, #CORTEX_A78_ACTLR2_EL1_BIT_2 + msr CORTEX_A78_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a78_1821534_wa + +func check_errata_1821534 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1821534 + +/* -------------------------------------------------- + * Errata Workaround for Cortex A78 Errata 1952683. + * This applies to revision r0p0. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1952683_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_1952683 + cbz x0, 1f + + ldr x0,=0x5 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xEEE10A10 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0FFF + msr S3_6_c15_c8_3,x0 + ldr x0,=0x0010F000 + msr S3_6_c15_c8_4,x0 + ldr x0,=0x0010F000 + msr S3_6_c15_c8_5,x0 + ldr x0,=0x40000080023ff + msr S3_6_c15_c8_1,x0 + ldr x0,=0x6 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xEE640F34 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0FFF + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000080023ff + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_a78_1952683_wa + +func check_errata_1952683 + /* Applies to r0p0 only */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_1952683 + +/* -------------------------------------------------- + * Errata Workaround for Cortex A78 Errata 2132060. + * This applies to revisions r0p0, r1p0, r1p1, and r1p2. + * It is still open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_a78_2132060_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2132060 + cbz x0, 1f + + /* Apply the workaround. */ + mrs x1, CORTEX_A78_CPUECTLR_EL1 + mov x0, #CORTEX_A78_CPUECTLR_EL1_PF_MODE_CNSRV + bfi x1, x0, #CPUECTLR_EL1_PF_MODE_LSB, #CPUECTLR_EL1_PF_MODE_WIDTH + msr CORTEX_A78_CPUECTLR_EL1, x1 +1: + ret x17 +endfunc errata_a78_2132060_wa + +func check_errata_2132060 + /* Applies to r0p0, r0p1, r1p1, and r1p2 */ + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_2132060 + +/* -------------------------------------------------------------------- + * Errata Workaround for A78 Erratum 2242635. + * This applies to revisions r1p0, r1p1, and r1p2 of the Cortex A78 + * processor and is still open. + * The issue also exists in r0p0 but there is no fix in that revision. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------------------------- + */ +func errata_a78_2242635_wa + /* Compare x0 against revisions r1p0 - r1p2 */ + mov x17, x30 + bl check_errata_2242635 + cbz x0, 1f + + ldr x0, =0x5 + msr S3_6_c15_c8_0, x0 /* CPUPSELR_EL3 */ + ldr x0, =0x10F600E000 + msr S3_6_c15_c8_2, x0 /* CPUPOR_EL3 */ + ldr x0, =0x10FF80E000 + msr S3_6_c15_c8_3, x0 /* CPUPMR_EL3 */ + ldr x0, =0x80000000003FF + msr S3_6_c15_c8_1, x0 /* CPUPCR_EL3 */ + + isb +1: + ret x17 +endfunc errata_a78_2242635_wa + +func check_errata_2242635 + /* Applies to revisions r1p0 through r1p2. */ + mov x1, #CPU_REV(1, 0) + mov x2, #CPU_REV(1, 2) + b cpu_rev_var_range +endfunc check_errata_2242635 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A78 + * ------------------------------------------------- + */ +func cortex_a78_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A78_1688305 + mov x0, x18 + bl errata_a78_1688305_wa +#endif + +#if ERRATA_A78_1941498 + mov x0, x18 + bl errata_a78_1941498_wa +#endif + +#if ERRATA_A78_1951500 + mov x0, x18 + bl errata_a78_1951500_wa +#endif + +#if ERRATA_A78_1821534 + mov x0, x18 + bl errata_a78_1821534_wa +#endif + +#if ERRATA_A78_1952683 + mov x0, x18 + bl errata_a78_1952683_wa +#endif + +#if ERRATA_A78_2132060 + mov x0, x18 + bl errata_a78_2132060_wa +#endif + +#if ERRATA_A78_2242635 + mov x0, x18 + bl errata_a78_2242635_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + bic x0, x0, #CORTEX_A78_ACTLR_TAM_BIT + msr actlr_el3, x0 + + /* Make sure accesses from non-secure EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + bic x0, x0, #CORTEX_A78_ACTLR_TAM_BIT + msr actlr_el2, x0 + + /* Enable group0 counters */ + mov x0, #CORTEX_A78_AMU_GROUP0_MASK + msr CPUAMCNTENSET0_EL0, x0 + + /* Enable group1 counters */ + mov x0, #CORTEX_A78_AMU_GROUP1_MASK + msr CPUAMCNTENSET1_EL0, x0 +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A78 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a78 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_a78_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a78_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A78_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT + msr CORTEX_A78_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a78_core_pwr_dwn + + /* + * Errata printing function for cortex_a78. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_a78_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A78_1688305, cortex_a78, 1688305 + report_errata ERRATA_A78_1941498, cortex_a78, 1941498 + report_errata ERRATA_A78_1951500, cortex_a78, 1951500 + report_errata ERRATA_A78_1821534, cortex_a78, 1821534 + report_errata ERRATA_A78_1952683, cortex_a78, 1952683 + report_errata ERRATA_A78_2132060, cortex_a78, 2132060 + report_errata ERRATA_A78_2242635, cortex_a78, 2242635 + report_errata WORKAROUND_CVE_2022_23960, cortex_a78, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a78_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a78 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_a78_regs, "aS" +cortex_a78_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a78_cpu_reg_dump + adr x6, cortex_a78_regs + mrs x8, CORTEX_A78_CPUECTLR_EL1 + ret +endfunc cortex_a78_cpu_reg_dump + +declare_cpu_ops cortex_a78, CORTEX_A78_MIDR, \ + cortex_a78_reset_func, \ + cortex_a78_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S new file mode 100644 index 0000000..8ca9f7d --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "cortex_a78_ae must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A78_AE_BHB_LOOP_COUNT, cortex_a78_ae +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 1941500. + * This applies to revisions r0p0 and r0p1 of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_ae_1941500_wa + /* Compare x0 against revisions r0p0 - r0p1 */ + mov x17, x30 + bl check_errata_1941500 + cbz x0, 1f + + /* Set bit 8 in ECTLR_EL1 */ + mrs x0, CORTEX_A78_AE_CPUECTLR_EL1 + bic x0, x0, #CORTEX_A78_AE_CPUECTLR_EL1_BIT_8 + msr CORTEX_A78_AE_CPUECTLR_EL1, x0 + isb +1: + ret x17 +endfunc errata_a78_ae_1941500_wa + +func check_errata_1941500 + /* Applies to revisions r0p0 and r0p1. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 1) + b cpu_rev_var_range +endfunc check_errata_1941500 + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 1951502. + * This applies to revisions r0p0 and r0p1 of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_ae_1951502_wa + /* Compare x0 against revisions r0p0 - r0p1 */ + mov x17, x30 + bl check_errata_1951502 + cbz x0, 1f + + msr S3_6_c15_c8_0, xzr + ldr x0, =0x10E3900002 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + mov x0, #1 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + mov x0, #2 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + isb +1: + ret x17 +endfunc errata_a78_ae_1951502_wa + +func check_errata_1951502 + /* Applies to revisions r0p0 and r0p1. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 1) + b cpu_rev_var_range +endfunc check_errata_1951502 + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 2376748. + * This applies to revisions r0p0 and r0p1 of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_ae_2376748_wa + /* Compare x0 against revisions r0p0 - r0p1 */ + mov x17, x30 + bl check_errata_2376748 + cbz x0, 1f + + /* ------------------------------------------------------- + * Set CPUACTLR2_EL1[0] to 1 to force PLDW/PFRM ST to + * behave like PLD/PRFM LD and not cause invalidations to + * other PE caches. There might be a small performance + * degradation to this workaround for certain workloads + * that share data. + * ------------------------------------------------------- + */ + mrs x0, CORTEX_A78_AE_ACTLR2_EL1 + orr x0, x0, #CORTEX_A78_AE_ACTLR2_EL1_BIT_0 + msr CORTEX_A78_AE_ACTLR2_EL1, x0 + isb +1: + ret x17 +endfunc errata_a78_ae_2376748_wa + +func check_errata_2376748 + /* Applies to revisions r0p0 and r0p1. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 1) + b cpu_rev_var_range +endfunc check_errata_2376748 + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 2395408. + * This applies to revisions r0p0 and r0p1 of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_ae_2395408_wa + /* Compare x0 against revisions r0p0 - r0p1 */ + mov x17, x30 + bl check_errata_2395408 + cbz x0, 1f + + /* -------------------------------------------------------- + * Disable folding of demand requests into older prefetches + * with L2 miss requests outstanding by setting the + * CPUACTLR2_EL1[40] to 1. + * -------------------------------------------------------- + */ + mrs x0, CORTEX_A78_AE_ACTLR2_EL1 + orr x0, x0, #CORTEX_A78_AE_ACTLR2_EL1_BIT_40 + msr CORTEX_A78_AE_ACTLR2_EL1, x0 + isb +1: + ret x17 +endfunc errata_a78_ae_2395408_wa + +func check_errata_2395408 + /* Applies to revisions r0p0 and r0p1. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 1) + b cpu_rev_var_range +endfunc check_errata_2395408 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A78-AE + * ------------------------------------------------- + */ +func cortex_a78_ae_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A78_AE_1941500 + mov x0, x18 + bl errata_a78_ae_1941500_wa +#endif + +#if ERRATA_A78_AE_1951502 + mov x0, x18 + bl errata_a78_ae_1951502_wa +#endif + +#if ERRATA_A78_AE_2376748 + mov x0, x18 + bl errata_a78_ae_2376748_wa +#endif + +#if ERRATA_A78_AE_2395408 + mov x0, x18 + bl errata_a78_ae_2395408_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A78AE generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a78_ae + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_a78_ae_reset_func + + /* ------------------------------------------------------- + * HW will do the cache maintenance while powering down + * ------------------------------------------------------- + */ +func cortex_a78_ae_core_pwr_dwn + /* ------------------------------------------------------- + * Enable CPU power down bit in power control register + * ------------------------------------------------------- + */ + mrs x0, CORTEX_A78_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT + msr CORTEX_A78_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a78_ae_core_pwr_dwn + + /* + * Errata printing function for cortex_a78_ae. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_a78_ae_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A78_AE_1941500, cortex_a78_ae, 1941500 + report_errata ERRATA_A78_AE_1951502, cortex_a78_ae, 1951502 + report_errata ERRATA_A78_AE_2376748, cortex_a78_ae, 2376748 + report_errata ERRATA_A78_AE_2395408, cortex_a78_ae, 2395408 + report_errata WORKAROUND_CVE_2022_23960, cortex_a78_ae, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a78_ae_errata_report +#endif + + /* ------------------------------------------------------- + * This function provides cortex_a78_ae 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_a78_ae_regs, "aS" +cortex_a78_ae_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a78_ae_cpu_reg_dump + adr x6, cortex_a78_ae_regs + mrs x8, CORTEX_A78_CPUECTLR_EL1 + ret +endfunc cortex_a78_ae_cpu_reg_dump + +declare_cpu_ops cortex_a78_ae, CORTEX_A78_AE_MIDR, \ + cortex_a78_ae_reset_func, \ + cortex_a78_ae_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S new file mode 100644 index 0000000..0712109 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "cortex_a78c must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A78C_BHB_LOOP_COUNT, cortex_a78c +#endif /* WORKAROUND_CVE_2022_23960 */ + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A78C + * ------------------------------------------------- + */ +func cortex_a78c_reset_func +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A78c generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a78c + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + isb + ret +endfunc cortex_a78c_reset_func + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_a78c_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_A78C_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A78C_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT + msr CORTEX_A78C_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a78c_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A78C. Must follow AAPCS. + */ +func cortex_a78c_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2022_23960, cortex_a78c, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a78c_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a78c 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_a78c_regs, "aS" +cortex_a78c_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a78c_cpu_reg_dump + adr x6, cortex_a78c_regs + mrs x8, CORTEX_A78C_CPUECTLR_EL1 + ret +endfunc cortex_a78c_cpu_reg_dump + +declare_cpu_ops cortex_a78c, CORTEX_A78C_MIDR, \ + cortex_a78c_reset_func, \ + cortex_a78c_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S new file mode 100644 index 0000000..445a691 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. 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 Hayes must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex Hayes supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_hayes_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_HAYES_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_HAYES_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_HAYES_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_hayes_core_pwr_dwn + + /* + * Errata printing function for Cortex Hayes. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_hayes_errata_report + ret +endfunc cortex_hayes_errata_report +#endif + +func cortex_hayes_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc cortex_hayes_reset_func + + /* --------------------------------------------- + * This function provides Cortex Hayes 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_hayes_regs, "aS" +cortex_hayes_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_hayes_cpu_reg_dump + adr x6, cortex_hayes_regs + mrs x8, CORTEX_HAYES_CPUECTLR_EL1 + ret +endfunc cortex_hayes_cpu_reg_dump + +declare_cpu_ops cortex_hayes, CORTEX_HAYES_MIDR, \ + cortex_hayes_reset_func, \ + cortex_hayes_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S new file mode 100644 index 0000000..2ab4296 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. 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 Hunter must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex Hunter supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +func cortex_hunter_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc cortex_hunter_reset_func + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_hunter_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_HUNTER_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_HUNTER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_HUNTER_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_hunter_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Hunter. Must follow AAPCS. + */ +func cortex_hunter_errata_report + ret +endfunc cortex_hunter_errata_report +#endif + + /* --------------------------------------------- + * This function provides Cortex Hunter-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_hunter_regs, "aS" +cortex_hunter_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_hunter_cpu_reg_dump + adr x6, cortex_hunter_regs + mrs x8, CORTEX_HUNTER_CPUECTLR_EL1 + ret +endfunc cortex_hunter_cpu_reg_dump + +declare_cpu_ops cortex_hunter, CORTEX_HUNTER_MIDR, \ + cortex_hunter_reset_func, \ + cortex_hunter_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S new file mode 100644 index 0000000..98c7d6d --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. 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 Makalu must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex Makalu supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +func cortex_makalu_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc cortex_makalu_reset_func + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_makalu_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_MAKALU_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_MAKALU_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_MAKALU_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_makalu_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Makalu. Must follow AAPCS. + */ +func cortex_makalu_errata_report + ret +endfunc cortex_makalu_errata_report +#endif + + /* --------------------------------------------- + * This function provides Cortex Makalu-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_makalu_regs, "aS" +cortex_makalu_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_makalu_cpu_reg_dump + adr x6, cortex_makalu_regs + mrs x8, CORTEX_MAKALU_CPUECTLR_EL1 + ret +endfunc cortex_makalu_cpu_reg_dump + +declare_cpu_ops cortex_makalu, CORTEX_MAKALU_MIDR, \ + cortex_makalu_reset_func, \ + cortex_makalu_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S new file mode 100644 index 0000000..fbbf205 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. 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 Makalu ELP must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex Makalu ELP supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_makalu_elp_arm_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_makalu_elp_arm_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Makalu ELP. Must follow AAPCS. + */ +func cortex_makalu_elp_arm_errata_report + ret +endfunc cortex_makalu_elp_arm_errata_report +#endif + +func cortex_makalu_elp_arm_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc cortex_makalu_elp_arm_reset_func + + /* --------------------------------------------- + * This function provides Cortex Makalu ELP- + * 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_makalu_elp_arm_regs, "aS" +cortex_makalu_elp_arm_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_makalu_elp_arm_cpu_reg_dump + adr x6, cortex_makalu_elp_arm_regs + mrs x8, CORTEX_MAKALU_ELP_ARM_CPUECTLR_EL1 + ret +endfunc cortex_makalu_elp_arm_cpu_reg_dump + +declare_cpu_ops cortex_makalu_elp_arm, CORTEX_MAKALU_ELP_ARM_MIDR, \ + cortex_makalu_elp_arm_reset_func, \ + cortex_makalu_elp_arm_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S new file mode 100644 index 0000000..9586a5b --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex X2 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex X2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_X2_BHB_LOOP_COUNT, cortex_x2 +#endif /* WORKAROUND_CVE_2022_23960 */ + + /* -------------------------------------------------- + * Errata Workaround for Cortex X2 Errata #2002765. + * This applies to revisions r0p0, r1p0, and r2p0 and + * is open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_x2_2002765_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2002765 + cbz x0, 1f + + ldr x0, =0x6 + msr S3_6_C15_C8_0, x0 /* CPUPSELR_EL3 */ + ldr x0, =0xF3A08002 + msr S3_6_C15_C8_2, x0 /* CPUPOR_EL3 */ + ldr x0, =0xFFF0F7FE + msr S3_6_C15_C8_3, x0 /* CPUPMR_EL3 */ + ldr x0, =0x40000001003ff + msr S3_6_C15_C8_1, x0 /* CPUPCR_EL3 */ + isb + +1: + ret x17 +endfunc errata_cortex_x2_2002765_wa + +func check_errata_2002765 + /* Applies to r0p0 - r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2002765 + + /* -------------------------------------------------- + * Errata Workaround for Cortex X2 Errata #2058056. + * This applies to revisions r0p0, r1p0, and r2p0 and + * is open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_x2_2058056_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2058056 + cbz x0, 1f + + mrs x1, CORTEX_X2_CPUECTLR2_EL1 + mov x0, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_CNSRV + bfi x1, x0, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_SHIFT, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_WIDTH + msr CORTEX_X2_CPUECTLR2_EL1, x1 + +1: + ret x17 +endfunc errata_cortex_x2_2058056_wa + +func check_errata_2058056 + /* Applies to r0p0 - r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2058056 + + /* -------------------------------------------------- + * Errata Workaround for Cortex X2 Errata #2083908. + * This applies to revision r2p0 and is open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x2, x17 + * -------------------------------------------------- + */ +func errata_cortex_x2_2083908_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2083908 + cbz x0, 1f + + /* Apply the workaround by setting bit 13 in CPUACTLR5_EL1. */ + mrs x1, CORTEX_X2_CPUACTLR5_EL1 + orr x1, x1, #BIT(13) + msr CORTEX_X2_CPUACTLR5_EL1, x1 + +1: + ret x17 +endfunc errata_cortex_x2_2083908_wa + +func check_errata_2083908 + /* Applies to r2p0 */ + mov x1, #0x20 + mov x2, #0x20 + b cpu_rev_var_range +endfunc check_errata_2083908 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-X2 Errata 2017096. + * This applies only to revisions r0p0, r1p0 and r2p0 + * and is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_x2_2017096_wa + /* Compare x0 against revision r0p0 to r2p0 */ + mov x17, x30 + bl check_errata_2017096 + cbz x0, 1f + mrs x1, CORTEX_X2_CPUECTLR_EL1 + orr x1, x1, CORTEX_X2_CPUECTLR_EL1_PFSTIDIS_BIT + msr CORTEX_X2_CPUECTLR_EL1, x1 + +1: + ret x17 +endfunc errata_x2_2017096_wa + +func check_errata_2017096 + /* Applies to r0p0, r1p0, r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2017096 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-X2 Errata 2081180. + * This applies to revision r0p0, r1p0 and r2p0 + * and is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_x2_2081180_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2081180 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0, =0x3 + msr CORTEX_X2_IMP_CPUPSELR_EL3, x0 + ldr x0, =0xF3A08002 + msr CORTEX_X2_IMP_CPUPOR_EL3, x0 + ldr x0, =0xFFF0F7FE + msr CORTEX_X2_IMP_CPUPMR_EL3, x0 + ldr x0, =0x10002001003FF + msr CORTEX_X2_IMP_CPUPCR_EL3, x0 + ldr x0, =0x4 + msr CORTEX_X2_IMP_CPUPSELR_EL3, x0 + ldr x0, =0xBF200000 + msr CORTEX_X2_IMP_CPUPOR_EL3, x0 + ldr x0, =0xFFEF0000 + msr CORTEX_X2_IMP_CPUPMR_EL3, x0 + ldr x0, =0x10002001003F3 + msr CORTEX_X2_IMP_CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_x2_2081180_wa + +func check_errata_2081180 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2081180 + + /* -------------------------------------------------- + * Errata Workaround for Cortex X2 Errata 2216384. + * This applies to revisions r0p0, r1p0, and r2p0 + * and is fixed in r2p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_x2_2216384_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2216384 + cbz x0, 1f + + mrs x1, CORTEX_X2_CPUACTLR5_EL1 + orr x1, x1, CORTEX_X2_CPUACTLR5_EL1_BIT_17 + msr CORTEX_X2_CPUACTLR5_EL1, x1 + + /* Apply instruction patching sequence */ + ldr x0, =0x5 + msr CORTEX_X2_IMP_CPUPSELR_EL3, x0 + ldr x0, =0x10F600E000 + msr CORTEX_X2_IMP_CPUPOR_EL3, x0 + ldr x0, =0x10FF80E000 + msr CORTEX_X2_IMP_CPUPMR_EL3, x0 + ldr x0, =0x80000000003FF + msr CORTEX_X2_IMP_CPUPCR_EL3, x0 + isb + +1: + ret x17 +endfunc errata_x2_2216384_wa + +func check_errata_2216384 + /* Applies to r0p0 - r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2216384 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_x2_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_X2_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_X2_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_X2_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_x2_core_pwr_dwn + + /* + * Errata printing function for Cortex X2. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_x2_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_X2_2002765, cortex_x2, 2002765 + report_errata ERRATA_X2_2058056, cortex_x2, 2058056 + report_errata ERRATA_X2_2083908, cortex_x2, 2083908 + report_errata ERRATA_X2_2017096, cortex_x2, 2017096 + report_errata ERRATA_X2_2081180, cortex_x2, 2081180 + report_errata ERRATA_X2_2216384, cortex_x2, 2216384 + report_errata WORKAROUND_CVE_2022_23960, cortex_x2, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_x2_errata_report +#endif + +func cortex_x2_reset_func + mov x19, x30 + + /* Disable speculative loads */ + msr SSBS, xzr + isb + + /* Get the CPU revision and stash it in x18. */ + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_X2_2002765 + mov x0, x18 + bl errata_cortex_x2_2002765_wa +#endif + +#if ERRATA_X2_2058056 + mov x0, x18 + bl errata_cortex_x2_2058056_wa +#endif + +#if ERRATA_X2_2083908 + mov x0, x18 + bl errata_cortex_x2_2083908_wa +#endif + +#if ERRATA_X2_2017096 + mov x0, x18 + bl errata_x2_2017096_wa +#endif + +#if ERRATA_X2_2081180 + mov x0, x18 + bl errata_x2_2081180_wa +#endif + +#if ERRATA_X2_2216384 + mov x0, x18 + bl errata_x2_2216384_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-X2 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_x2 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_x2_reset_func + + /* --------------------------------------------- + * This function provides Cortex X2 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_x2_regs, "aS" +cortex_x2_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_x2_cpu_reg_dump + adr x6, cortex_x2_regs + mrs x8, CORTEX_X2_CPUECTLR_EL1 + ret +endfunc cortex_x2_cpu_reg_dump + +declare_cpu_ops cortex_x2, CORTEX_X2_MIDR, \ + cortex_x2_reset_func, \ + cortex_x2_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S b/arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S new file mode 100644 index 0000000..2385627 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2014-2022, 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 reserved 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, #CPU_NO_EXTRA1_FUNC + 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 + +/* + * int check_smccc_arch_wa3_applies(void); + * + * This function checks whether SMCCC_ARCH_WORKAROUND_3 is enabled to mitigate + * CVE-2022-23960 for this CPU. It returns: + * - ERRATA_APPLIES when SMCCC_ARCH_WORKAROUND_3 can be invoked to mitigate + * the CVE. + * - ERRATA_NOT_APPLIES when SMCCC_ARCH_WORKAROUND_3 should not be invoked to + * mitigate the CVE. + * + * NOTE: Must be called only after cpu_ops have been initialized + * in per-CPU data. + */ + .globl check_smccc_arch_wa3_applies +func check_smccc_arch_wa3_applies + 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_EXTRA3_FUNC] + /* + * If the reserved function pointer is NULL, this CPU + * is unaffected by CVE-2022-23960 so bail out. + */ + cmp x0, #CPU_NO_EXTRA3_FUNC + beq 1f + br x0 +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_smccc_arch_wa3_applies diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c b/arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c new file mode 100644 index 0000000..3a2fa81 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define CPUAMU_NR_COUNTERS 5U + +struct cpuamu_ctx { + uint64_t cnts[CPUAMU_NR_COUNTERS]; + unsigned int mask; +}; + +static struct cpuamu_ctx cpuamu_ctxs[PLATFORM_CORE_COUNT]; + +int midr_match(unsigned int cpu_midr) +{ + unsigned int midr, midr_mask; + + midr = (unsigned int)read_midr(); + midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | + (MIDR_PN_MASK << MIDR_PN_SHIFT); + return ((midr & midr_mask) == (cpu_midr & midr_mask)); +} + +void cpuamu_context_save(unsigned int nr_counters) +{ + struct cpuamu_ctx *ctx = &cpuamu_ctxs[plat_my_core_pos()]; + unsigned int i; + + assert(nr_counters <= CPUAMU_NR_COUNTERS); + + /* Save counter configuration */ + ctx->mask = cpuamu_read_cpuamcntenset_el0(); + + /* Disable counters */ + cpuamu_write_cpuamcntenclr_el0(ctx->mask); + isb(); + + /* Save counters */ + for (i = 0; i < nr_counters; i++) + ctx->cnts[i] = cpuamu_cnt_read(i); +} + +void cpuamu_context_restore(unsigned int nr_counters) +{ + struct cpuamu_ctx *ctx = &cpuamu_ctxs[plat_my_core_pos()]; + unsigned int i; + + assert(nr_counters <= CPUAMU_NR_COUNTERS); + + /* + * Disable counters. They were enabled early in the + * CPU reset function. + */ + cpuamu_write_cpuamcntenclr_el0(ctx->mask); + isb(); + + /* Restore counters */ + for (i = 0; i < nr_counters; i++) + cpuamu_cnt_write(i, ctx->cnts[i]); + isb(); + + /* Restore counter configuration */ + cpuamu_write_cpuamcntenset_el0(ctx->mask); +} diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S b/arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S new file mode 100644 index 0000000..5a77fc7 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl cpuamu_cnt_read + .globl cpuamu_cnt_write + .globl cpuamu_read_cpuamcntenset_el0 + .globl cpuamu_read_cpuamcntenclr_el0 + .globl cpuamu_write_cpuamcntenset_el0 + .globl cpuamu_write_cpuamcntenclr_el0 + +/* + * uint64_t cpuamu_cnt_read(unsigned int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `x0`. + */ +func cpuamu_cnt_read + adr x1, 1f + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read CPUAMEVCNTR0_EL0 + read CPUAMEVCNTR1_EL0 + read CPUAMEVCNTR2_EL0 + read CPUAMEVCNTR3_EL0 + read CPUAMEVCNTR4_EL0 +endfunc cpuamu_cnt_read + +/* + * void cpuamu_cnt_write(unsigned int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + */ +func cpuamu_cnt_write + adr x2, 1f + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write CPUAMEVCNTR0_EL0 + write CPUAMEVCNTR1_EL0 + write CPUAMEVCNTR2_EL0 + write CPUAMEVCNTR3_EL0 + write CPUAMEVCNTR4_EL0 +endfunc cpuamu_cnt_write + +/* + * unsigned int cpuamu_read_cpuamcntenset_el0(void); + * + * Read the `CPUAMCNTENSET_EL0` CPU register and return + * it in `x0`. + */ +func cpuamu_read_cpuamcntenset_el0 + mrs x0, CPUAMCNTENSET_EL0 + ret +endfunc cpuamu_read_cpuamcntenset_el0 + +/* + * unsigned int cpuamu_read_cpuamcntenclr_el0(void); + * + * Read the `CPUAMCNTENCLR_EL0` CPU register and return + * it in `x0`. + */ +func cpuamu_read_cpuamcntenclr_el0 + mrs x0, CPUAMCNTENCLR_EL0 + ret +endfunc cpuamu_read_cpuamcntenclr_el0 + +/* + * void cpuamu_write_cpuamcntenset_el0(unsigned int mask); + * + * Write `mask` to the `CPUAMCNTENSET_EL0` CPU register. + */ +func cpuamu_write_cpuamcntenset_el0 + msr CPUAMCNTENSET_EL0, x0 + ret +endfunc cpuamu_write_cpuamcntenset_el0 + +/* + * void cpuamu_write_cpuamcntenclr_el0(unsigned int mask); + * + * Write `mask` to the `CPUAMCNTENCLR_EL0` CPU register. + */ +func cpuamu_write_cpuamcntenclr_el0 + msr CPUAMCNTENCLR_EL0, x0 + ret +endfunc cpuamu_write_cpuamcntenclr_el0 diff --git a/arm-trusted-firmware/lib/cpus/aarch64/denver.S b/arm-trusted-firmware/lib/cpus/aarch64/denver.S new file mode 100644 index 0000000..3c54a6f --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/denver.S @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + + /* ------------------------------------------------- + * CVE-2017-5715 mitigation + * + * Flush the indirect branch predictor and RSB on + * entry to EL3 by issuing a newly added instruction + * for Denver CPUs. + * + * To achieve this without performing any branch + * instruction, a per-cpu vbar is installed which + * executes the workaround and then branches off to + * the corresponding vector entry in the main vector + * table. + * ------------------------------------------------- + */ +vector_base workaround_bpflush_runtime_exceptions + + .macro apply_workaround + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + + /* Disable cycle counter when event counting is prohibited */ + mrs x1, pmcr_el0 + orr x0, x1, #PMCR_EL0_DP_BIT + msr pmcr_el0, x0 + isb + + /* ------------------------------------------------- + * A new write-only system register where a write of + * 1 to bit 0 will cause the indirect branch predictor + * and RSB to be flushed. + * + * A write of 0 to bit 0 will be ignored. A write of + * 1 to any other bit will cause an MCA. + * ------------------------------------------------- + */ + mov x0, #1 + msr s3_0_c15_c0_6, x0 + isb + + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + .endm + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry workaround_bpflush_sync_exception_sp_el0 + b sync_exception_sp_el0 +end_vector_entry workaround_bpflush_sync_exception_sp_el0 + +vector_entry workaround_bpflush_irq_sp_el0 + b irq_sp_el0 +end_vector_entry workaround_bpflush_irq_sp_el0 + +vector_entry workaround_bpflush_fiq_sp_el0 + b fiq_sp_el0 +end_vector_entry workaround_bpflush_fiq_sp_el0 + +vector_entry workaround_bpflush_serror_sp_el0 + b serror_sp_el0 +end_vector_entry workaround_bpflush_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry workaround_bpflush_sync_exception_sp_elx + b sync_exception_sp_elx +end_vector_entry workaround_bpflush_sync_exception_sp_elx + +vector_entry workaround_bpflush_irq_sp_elx + b irq_sp_elx +end_vector_entry workaround_bpflush_irq_sp_elx + +vector_entry workaround_bpflush_fiq_sp_elx + b fiq_sp_elx +end_vector_entry workaround_bpflush_fiq_sp_elx + +vector_entry workaround_bpflush_serror_sp_elx + b serror_sp_elx +end_vector_entry workaround_bpflush_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry workaround_bpflush_sync_exception_aarch64 + apply_workaround + b sync_exception_aarch64 +end_vector_entry workaround_bpflush_sync_exception_aarch64 + +vector_entry workaround_bpflush_irq_aarch64 + apply_workaround + b irq_aarch64 +end_vector_entry workaround_bpflush_irq_aarch64 + +vector_entry workaround_bpflush_fiq_aarch64 + apply_workaround + b fiq_aarch64 +end_vector_entry workaround_bpflush_fiq_aarch64 + +vector_entry workaround_bpflush_serror_aarch64 + apply_workaround + b serror_aarch64 +end_vector_entry workaround_bpflush_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry workaround_bpflush_sync_exception_aarch32 + apply_workaround + b sync_exception_aarch32 +end_vector_entry workaround_bpflush_sync_exception_aarch32 + +vector_entry workaround_bpflush_irq_aarch32 + apply_workaround + b irq_aarch32 +end_vector_entry workaround_bpflush_irq_aarch32 + +vector_entry workaround_bpflush_fiq_aarch32 + apply_workaround + b fiq_aarch32 +end_vector_entry workaround_bpflush_fiq_aarch32 + +vector_entry workaround_bpflush_serror_aarch32 + apply_workaround + b serror_aarch32 +end_vector_entry workaround_bpflush_serror_aarch32 + + .global denver_disable_dco + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func denver_disable_ext_debug + mov x0, #1 + msr osdlr_el1, x0 + isb + dsb sy + ret +endfunc denver_disable_ext_debug + + /* ---------------------------------------------------- + * Enable dynamic code optimizer (DCO) + * ---------------------------------------------------- + */ +func denver_enable_dco + /* DCO is not supported on PN5 and later */ + mrs x1, midr_el1 + mov_imm x2, DENVER_MIDR_PN4 + cmp x1, x2 + b.hi 1f + + mov x18, x30 + bl plat_my_core_pos + mov x1, #1 + lsl x1, x1, x0 + msr s3_0_c15_c0_2, x1 + mov x30, x18 +1: ret +endfunc denver_enable_dco + + /* ---------------------------------------------------- + * Disable dynamic code optimizer (DCO) + * ---------------------------------------------------- + */ +func denver_disable_dco + /* DCO is not supported on PN5 and later */ + mrs x1, midr_el1 + mov_imm x2, DENVER_MIDR_PN4 + cmp x1, x2 + b.hi 2f + + /* turn off background work */ + mov x18, x30 + bl plat_my_core_pos + mov x1, #1 + lsl x1, x1, x0 + lsl x2, x1, #16 + msr s3_0_c15_c0_2, x2 + isb + + /* wait till the background work turns off */ +1: mrs x2, s3_0_c15_c0_2 + lsr x2, x2, #32 + and w2, w2, 0xFFFF + and x2, x2, x1 + cbnz x2, 1b + + mov x30, x18 +2: ret +endfunc denver_disable_dco + +func check_errata_cve_2017_5715 + mov x0, #ERRATA_MISSING +#if WORKAROUND_CVE_2017_5715 + /* + * Check if the CPU supports the special instruction + * required to flush the indirect branch predictor and + * RSB. Support for this operation can be determined by + * comparing bits 19:16 of ID_AFR0_EL1 with 0b0001. + */ + mrs x1, id_afr0_el1 + mov x2, #0x10000 + and x1, x1, x2 + cbz x1, 1f + mov x0, #ERRATA_APPLIES +1: +#endif + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + + /* ------------------------------------------------- + * The CPU Ops reset function for Denver. + * ------------------------------------------------- + */ +func denver_reset_func + + mov x19, x30 + +#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715 + /* + * Check if the CPU supports the special instruction + * required to flush the indirect branch predictor and + * RSB. Support for this operation can be determined by + * comparing bits 19:16 of ID_AFR0_EL1 with 0b0001. + */ + mrs x0, id_afr0_el1 + mov x1, #0x10000 + and x0, x0, x1 + cmp x0, #0 + adr x1, workaround_bpflush_runtime_exceptions + mrs x2, vbar_el3 + csel x0, x1, x2, ne + msr vbar_el3, x0 +#endif + +#if WORKAROUND_CVE_2018_3639 + /* + * Denver CPUs with DENVER_MIDR_PN3 or earlier, use different + * bits in the ACTLR_EL3 register to disable speculative + * store buffer and memory disambiguation. + */ + mrs x0, midr_el1 + mov_imm x1, DENVER_MIDR_PN4 + cmp x0, x1 + mrs x0, actlr_el3 + mov x1, #(DENVER_CPU_DIS_MD_EL3 | DENVER_CPU_DIS_SSB_EL3) + mov x2, #(DENVER_PN4_CPU_DIS_MD_EL3 | DENVER_PN4_CPU_DIS_SSB_EL3) + csel x3, x1, x2, ne + orr x0, x0, x3 + msr actlr_el3, x0 + isb + dsb sy +#endif + + /* ---------------------------------------------------- + * Reset ACTLR.PMSTATE to C1 state + * ---------------------------------------------------- + */ + mrs x0, actlr_el1 + bic x0, x0, #DENVER_CPU_PMSTATE_MASK + orr x0, x0, #DENVER_CPU_PMSTATE_C1 + msr actlr_el1, x0 + + /* ---------------------------------------------------- + * Enable dynamic code optimizer (DCO) + * ---------------------------------------------------- + */ + bl denver_enable_dco + + ret x19 +endfunc denver_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Denver. + * ---------------------------------------------------- + */ +func denver_core_pwr_dwn + + mov x19, x30 + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + bl denver_disable_ext_debug + + ret x19 +endfunc denver_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Denver. + * ------------------------------------------------------- + */ +func denver_cluster_pwr_dwn + ret +endfunc denver_cluster_pwr_dwn + +#if REPORT_ERRATA + /* + * Errata printing function for Denver. Must follow AAPCS. + */ +func denver_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, denver, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, denver, cve_2018_3639 + + ldp x8, x30, [sp], #16 + ret +endfunc denver_errata_report +#endif + + /* --------------------------------------------- + * This function provides Denver 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.denver_regs, "aS" +denver_regs: /* The ascii list of register names to be reported */ + .asciz "actlr_el1", "" + +func denver_cpu_reg_dump + adr x6, denver_regs + mrs x8, ACTLR_EL1 + ret +endfunc denver_cpu_reg_dump + +/* macro to declare cpu_ops for Denver SKUs */ +.macro denver_cpu_ops_wa midr + declare_cpu_ops_wa denver, \midr, \ + denver_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + CPU_NO_EXTRA3_FUNC, \ + denver_core_pwr_dwn, \ + denver_cluster_pwr_dwn +.endm + +denver_cpu_ops_wa DENVER_MIDR_PN0 +denver_cpu_ops_wa DENVER_MIDR_PN1 +denver_cpu_ops_wa DENVER_MIDR_PN2 +denver_cpu_ops_wa DENVER_MIDR_PN3 +denver_cpu_ops_wa DENVER_MIDR_PN4 +denver_cpu_ops_wa DENVER_MIDR_PN5 +denver_cpu_ops_wa DENVER_MIDR_PN6 +denver_cpu_ops_wa DENVER_MIDR_PN7 +denver_cpu_ops_wa DENVER_MIDR_PN8 +denver_cpu_ops_wa DENVER_MIDR_PN9 diff --git a/arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S b/arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S new file mode 100644 index 0000000..da052d5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/cpus/aarch64/generic.S b/arm-trusted-firmware/lib/cpus/aarch64/generic.S new file mode 100644 index 0000000..ef1f048 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/generic.S @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func generic_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc generic_disable_dcache + +func generic_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl generic_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + ret x18 +endfunc generic_core_pwr_dwn + +func generic_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl generic_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + ret x18 + +endfunc generic_cluster_pwr_dwn + +/* --------------------------------------------- + * Unimplemented functions. + * --------------------------------------------- + */ +.equ generic_errata_report, 0 +.equ generic_cpu_reg_dump, 0 +.equ generic_reset_func, 0 + +declare_cpu_ops generic, AARCH64_GENERIC_MIDR, \ + generic_reset_func, \ + generic_core_pwr_dwn, \ + generic_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S new file mode 100644 index 0000000..f43c18b --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse Demeter must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse Demeter supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func neoverse_demeter_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, NEOVERSE_DEMETER_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_DEMETER_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_demeter_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Neoverse Demeter. Must follow AAPCS. + */ +func neoverse_demeter_errata_report + ret +endfunc neoverse_demeter_errata_report +#endif + +func neoverse_demeter_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc neoverse_demeter_reset_func + + /* --------------------------------------------- + * This function provides Neoverse Demeter- + * 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.neoverse_demeter_regs, "aS" +neoverse_demeter_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_demeter_cpu_reg_dump + adr x6, neoverse_demeter_regs + mrs x8, NEOVERSE_DEMETER_CPUECTLR_EL1 + ret +endfunc neoverse_demeter_cpu_reg_dump + +declare_cpu_ops neoverse_demeter, NEOVERSE_DEMETER_MIDR, \ + neoverse_demeter_reset_func, \ + neoverse_demeter_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S new file mode 100644 index 0000000..96b63cf --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse E1 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse-E1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* ------------------------------------------------- + * The CPU Ops reset function for Neoverse-E1. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func neoverse_e1_reset_func + mov x19, x30 + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + ret x19 +endfunc neoverse_e1_reset_func + +func neoverse_e1_cpu_pwr_dwn + mrs x0, NEOVERSE_E1_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_E1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_E1_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_e1_cpu_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Neoverse N1. Must follow AAPCS. + */ +func neoverse_e1_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_DSU_936184, neoverse_e1, dsu_936184 + + ldp x8, x30, [sp], #16 + ret +endfunc neoverse_e1_errata_report +#endif + + +.section .rodata.neoverse_e1_regs, "aS" +neoverse_e1_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_e1_cpu_reg_dump + adr x6, neoverse_e1_regs + mrs x8, NEOVERSE_E1_ECTLR_EL1 + ret +endfunc neoverse_e1_cpu_reg_dump + +declare_cpu_ops neoverse_e1, NEOVERSE_E1_MIDR, \ + neoverse_e1_reset_func, \ + neoverse_e1_cpu_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S new file mode 100644 index 0000000..b75b0c1 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S @@ -0,0 +1,714 @@ +/* + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse N1 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse-N1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + .global neoverse_n1_errata_ic_trap_handler + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table NEOVERSE_N1_BHB_LOOP_COUNT, neoverse_n1 +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Erratum 1043202. + * This applies to revision r0p0 and r1p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1043202_wa + /* Compare x0 against revision r1p0 */ + mov x17, x30 + bl check_errata_1043202 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0, =0x0 + msr CPUPSELR_EL3, x0 + ldr x0, =0xF3BF8F2F + msr CPUPOR_EL3, x0 + ldr x0, =0xFFFFFFFF + msr CPUPMR_EL3, x0 + ldr x0, =0x800200071 + msr CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_n1_1043202_wa + +func check_errata_1043202 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1043202 + +/* -------------------------------------------------- + * Disable speculative loads if Neoverse N1 supports + * SSBS. + * + * Shall clobber: x0. + * -------------------------------------------------- + */ +func neoverse_n1_disable_speculative_loads + /* Check if the PE implements SSBS */ + mrs x0, id_aa64pfr1_el1 + tst x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT) + b.eq 1f + + /* Disable speculative loads */ + msr SSBS, xzr + +1: + ret +endfunc neoverse_n1_disable_speculative_loads + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1073348 + * This applies to revision r0p0 and r1p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1073348_wa + /* Compare x0 against revision r1p0 */ + mov x17, x30 + bl check_errata_1073348 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR_EL1_BIT_6 + msr NEOVERSE_N1_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1073348_wa + +func check_errata_1073348 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1073348 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1130799 + * This applies to revision <=r2p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1130799_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_1130799 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR2_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR2_EL1_BIT_59 + msr NEOVERSE_N1_CPUACTLR2_EL1, x1 +1: + ret x17 +endfunc errata_n1_1130799_wa + +func check_errata_1130799 + /* Applies to <=r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1130799 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1165347 + * This applies to revision <=r2p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1165347_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_1165347 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR2_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR2_EL1_BIT_0 + orr x1, x1, NEOVERSE_N1_CPUACTLR2_EL1_BIT_15 + msr NEOVERSE_N1_CPUACTLR2_EL1, x1 +1: + ret x17 +endfunc errata_n1_1165347_wa + +func check_errata_1165347 + /* Applies to <=r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1165347 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1207823 + * This applies to revision <=r2p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1207823_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_1207823 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR2_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR2_EL1_BIT_11 + msr NEOVERSE_N1_CPUACTLR2_EL1, x1 +1: + ret x17 +endfunc errata_n1_1207823_wa + +func check_errata_1207823 + /* Applies to <=r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1207823 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1220197 + * This applies to revision <=r2p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1220197_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_1220197 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUECTLR_EL1 + orr x1, x1, NEOVERSE_N1_WS_THR_L2_MASK + msr NEOVERSE_N1_CPUECTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1220197_wa + +func check_errata_1220197 + /* Applies to <=r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1220197 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1257314 + * This applies to revision <=r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1257314_wa + /* Compare x0 against revision r3p0 */ + mov x17, x30 + bl check_errata_1257314 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR3_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR3_EL1_BIT_10 + msr NEOVERSE_N1_CPUACTLR3_EL1, x1 +1: + ret x17 +endfunc errata_n1_1257314_wa + +func check_errata_1257314 + /* Applies to <=r3p0 */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1257314 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1262606 + * This applies to revision <=r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1262606_wa + /* Compare x0 against revision r3p0 */ + mov x17, x30 + bl check_errata_1262606 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR_EL1_BIT_13 + msr NEOVERSE_N1_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1262606_wa + +func check_errata_1262606 + /* Applies to <=r3p0 */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1262606 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1262888 + * This applies to revision <=r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1262888_wa + /* Compare x0 against revision r3p0 */ + mov x17, x30 + bl check_errata_1262888 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUECTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUECTLR_EL1_MM_TLBPF_DIS_BIT + msr NEOVERSE_N1_CPUECTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1262888_wa + +func check_errata_1262888 + /* Applies to <=r3p0 */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1262888 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1275112 + * This applies to revision <=r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1275112_wa + /* Compare x0 against revision r3p0 */ + mov x17, x30 + bl check_errata_1275112 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR_EL1_BIT_13 + msr NEOVERSE_N1_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1275112_wa + +func check_errata_1275112 + /* Applies to <=r3p0 */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1275112 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Erratum 1315703. + * This applies to revision <= r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1315703_wa + /* Compare x0 against revision r3p1 */ + mov x17, x30 + bl check_errata_1315703 + cbz x0, 1f + + mrs x0, NEOVERSE_N1_CPUACTLR2_EL1 + orr x0, x0, #NEOVERSE_N1_CPUACTLR2_EL1_BIT_16 + msr NEOVERSE_N1_CPUACTLR2_EL1, x0 + +1: + ret x17 +endfunc errata_n1_1315703_wa + +func check_errata_1315703 + /* Applies to everything <= r3p0. */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1315703 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Erratum 1542419. + * This applies to revisions r3p0 - r4p0 of Neoverse N1 + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1542419_wa + /* Compare x0 against revision r3p0 and r4p0 */ + mov x17, x30 + bl check_errata_1542419 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0, =0x0 + msr CPUPSELR_EL3, x0 + ldr x0, =0xEE670D35 + msr CPUPOR_EL3, x0 + ldr x0, =0xFFFF0FFF + msr CPUPMR_EL3, x0 + ldr x0, =0x08000020007D + msr CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_n1_1542419_wa + +func check_errata_1542419 + /* Applies to everything r3p0 - r4p0. */ + mov x1, #0x30 + mov x2, #0x40 + b cpu_rev_var_range +endfunc check_errata_1542419 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1868343. + * This applies to revision <= r4p0 of Neoverse N1. + * This workaround is the same as the workaround for + * errata 1262606 and 1275112 but applies to a wider + * revision range. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1868343_wa + /* + * Compare x0 against revision r4p0 + */ + mov x17, x30 + bl check_errata_1868343 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR_EL1_BIT_13 + msr NEOVERSE_N1_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_n1_1868343_wa + +func check_errata_1868343 + /* Applies to everything <= r4p0 */ + mov x1, #0x40 + b cpu_rev_var_ls +endfunc check_errata_1868343 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1946160. + * This applies to revisions r3p0, r3p1, r4p0, and + * r4p1 of Neoverse N1. It also exists in r0p0, r1p0, + * and r2p0 but there is no fix in these revisions. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1946160_wa + /* + * Compare x0 against r3p0 - r4p1 + */ + mov x17, x30 + bl check_errata_1946160 + cbz x0, 1f + + mov x0, #3 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3900002 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #4 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #5 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + isb +1: + ret x17 +endfunc errata_n1_1946160_wa + +func check_errata_1946160 + /* Applies to r3p0 - r4p1. */ + mov x1, #0x30 + mov x2, #0x41 + b cpu_rev_var_range +endfunc check_errata_1946160 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + +func neoverse_n1_reset_func + mov x19, x30 + + bl neoverse_n1_disable_speculative_loads + + /* Forces all cacheable atomic instructions to be near */ + mrs x0, NEOVERSE_N1_CPUACTLR2_EL1 + orr x0, x0, #NEOVERSE_N1_CPUACTLR2_EL1_BIT_2 + msr NEOVERSE_N1_CPUACTLR2_EL1, x0 + isb + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_N1_1043202 + mov x0, x18 + bl errata_n1_1043202_wa +#endif + +#if ERRATA_N1_1073348 + mov x0, x18 + bl errata_n1_1073348_wa +#endif + +#if ERRATA_N1_1130799 + mov x0, x18 + bl errata_n1_1130799_wa +#endif + +#if ERRATA_N1_1165347 + mov x0, x18 + bl errata_n1_1165347_wa +#endif + +#if ERRATA_N1_1207823 + mov x0, x18 + bl errata_n1_1207823_wa +#endif + +#if ERRATA_N1_1220197 + mov x0, x18 + bl errata_n1_1220197_wa +#endif + +#if ERRATA_N1_1257314 + mov x0, x18 + bl errata_n1_1257314_wa +#endif + +#if ERRATA_N1_1262606 + mov x0, x18 + bl errata_n1_1262606_wa +#endif + +#if ERRATA_N1_1262888 + mov x0, x18 + bl errata_n1_1262888_wa +#endif + +#if ERRATA_N1_1275112 + mov x0, x18 + bl errata_n1_1275112_wa +#endif + +#if ERRATA_N1_1315703 + mov x0, x18 + bl errata_n1_1315703_wa +#endif + +#if ERRATA_N1_1542419 + mov x0, x18 + bl errata_n1_1542419_wa +#endif + +#if ERRATA_N1_1868343 + mov x0, x18 + bl errata_n1_1868343_wa +#endif + +#if ERRATA_N1_1946160 + mov x0, x18 + bl errata_n1_1946160_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #NEOVERSE_N1_ACTLR_AMEN_BIT + msr actlr_el3, x0 + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #NEOVERSE_N1_ACTLR_AMEN_BIT + msr actlr_el2, x0 + + /* Enable group0 counters */ + mov x0, #NEOVERSE_N1_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 +#endif + +#if NEOVERSE_Nx_EXTERNAL_LLC + /* Some system may have External LLC, core needs to be made aware */ + mrs x0, NEOVERSE_N1_CPUECTLR_EL1 + orr x0, x0, NEOVERSE_N1_CPUECTLR_EL1_EXTLLC_BIT + msr NEOVERSE_N1_CPUECTLR_EL1, x0 +#endif + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Neoverse-N1 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_neoverse_n1 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc neoverse_n1_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func neoverse_n1_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, NEOVERSE_N1_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_N1_CORE_PWRDN_EN_MASK + msr NEOVERSE_N1_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_n1_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Neoverse N1. Must follow AAPCS. + */ +func neoverse_n1_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_N1_1043202, neoverse_n1, 1043202 + report_errata ERRATA_N1_1073348, neoverse_n1, 1073348 + report_errata ERRATA_N1_1130799, neoverse_n1, 1130799 + report_errata ERRATA_N1_1165347, neoverse_n1, 1165347 + report_errata ERRATA_N1_1207823, neoverse_n1, 1207823 + report_errata ERRATA_N1_1220197, neoverse_n1, 1220197 + report_errata ERRATA_N1_1257314, neoverse_n1, 1257314 + report_errata ERRATA_N1_1262606, neoverse_n1, 1262606 + report_errata ERRATA_N1_1262888, neoverse_n1, 1262888 + report_errata ERRATA_N1_1275112, neoverse_n1, 1275112 + report_errata ERRATA_N1_1315703, neoverse_n1, 1315703 + report_errata ERRATA_N1_1542419, neoverse_n1, 1542419 + report_errata ERRATA_N1_1868343, neoverse_n1, 1868343 + report_errata ERRATA_N1_1946160, neoverse_n1, 1946160 + report_errata ERRATA_DSU_936184, neoverse_n1, dsu_936184 + report_errata WORKAROUND_CVE_2022_23960, neoverse_n1, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc neoverse_n1_errata_report +#endif + +/* + * Handle trap of EL0 IC IVAU instructions to EL3 by executing a TLB + * inner-shareable invalidation to an arbitrary address followed by a DSB. + * + * x1: Exception Syndrome + */ +func neoverse_n1_errata_ic_trap_handler + cmp x1, #NEOVERSE_N1_EC_IC_TRAP + b.ne 1f + tlbi vae3is, xzr + dsb sy + + # Skip the IC instruction itself + mrs x3, elr_el3 + add x3, x3, #4 + msr elr_el3, x3 + + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +#if IMAGE_BL31 && RAS_EXTENSION + /* + * Issue Error Synchronization Barrier to synchronize SErrors before + * exiting EL3. We're running with EAs unmasked, so any synchronized + * errors would be taken immediately; therefore no need to inspect + * DISR_EL1 register. + */ + esb +#endif + exception_return +1: + ret +endfunc neoverse_n1_errata_ic_trap_handler + + /* --------------------------------------------- + * This function provides neoverse_n1 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.neoverse_n1_regs, "aS" +neoverse_n1_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_n1_cpu_reg_dump + adr x6, neoverse_n1_regs + mrs x8, NEOVERSE_N1_CPUECTLR_EL1 + ret +endfunc neoverse_n1_cpu_reg_dump + +declare_cpu_ops_eh neoverse_n1, NEOVERSE_N1_MIDR, \ + neoverse_n1_reset_func, \ + neoverse_n1_errata_ic_trap_handler, \ + neoverse_n1_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c new file mode 100644 index 0000000..b1b7bb8 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static void *neoverse_n1_context_save(const void *arg) +{ + if (midr_match(NEOVERSE_N1_MIDR) != 0) + cpuamu_context_save(NEOVERSE_N1_AMU_NR_COUNTERS); + + return (void *)0; +} + +static void *neoverse_n1_context_restore(const void *arg) +{ + if (midr_match(NEOVERSE_N1_MIDR) != 0) + cpuamu_context_restore(NEOVERSE_N1_AMU_NR_COUNTERS); + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, neoverse_n1_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, neoverse_n1_context_restore); diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S new file mode 100644 index 0000000..b93f2a6 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse N2 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse-N2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table NEOVERSE_N2_BHB_LOOP_COUNT, neoverse_n2 +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2002655. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n2_2002655_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2002655 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0,=0x6 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xF3A08002 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFF0F7FE + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000001003ff + msr S3_6_c15_c8_1,x0 + ldr x0,=0x7 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xBF200000 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0000 + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000001003f3 + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_n2_2002655_wa + +func check_errata_2002655 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2002655 + +/* --------------------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2067956. + * This applies to revision r0p0 of Neoverse N2 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------- + */ +func errata_n2_2067956_wa + /* Compare x0 against revision r0p0 */ + mov x17, x30 + bl check_errata_2067956 + cbz x0, 1f + mrs x1, NEOVERSE_N2_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR_EL1_BIT_46 + msr NEOVERSE_N2_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n2_2067956_wa + +func check_errata_2067956 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2067956 + +/* --------------------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2025414. + * This applies to revision r0p0 of Neoverse N2 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------- + */ +func errata_n2_2025414_wa + /* Compare x0 against revision r0p0 */ + mov x17, x30 + bl check_errata_2025414 + cbz x0, 1f + mrs x1, NEOVERSE_N2_CPUECTLR_EL1 + orr x1, x1, NEOVERSE_N2_CPUECTLR_EL1_PFSTIDIS_BIT + msr NEOVERSE_N2_CPUECTLR_EL1, x1 + +1: + ret x17 +endfunc errata_n2_2025414_wa + +func check_errata_2025414 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2025414 + +/* --------------------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2189731. + * This applies to revision r0p0 of Neoverse N2 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------- + */ +func errata_n2_2189731_wa + /* Compare x0 against revision r0p0 */ + mov x17, x30 + bl check_errata_2189731 + cbz x0, 1f + mrs x1, NEOVERSE_N2_CPUACTLR5_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR5_EL1_BIT_44 + msr NEOVERSE_N2_CPUACTLR5_EL1, x1 + +1: + ret x17 +endfunc errata_n2_2189731_wa + +func check_errata_2189731 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2189731 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2138956. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n2_2138956_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2138956 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0,=0x3 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xF3A08002 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFF0F7FE + msr S3_6_c15_c8_3,x0 + ldr x0,=0x10002001003FF + msr S3_6_c15_c8_1,x0 + ldr x0,=0x4 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xBF200000 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0000 + msr S3_6_c15_c8_3,x0 + ldr x0,=0x10002001003F3 + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_n2_2138956_wa + +func check_errata_2138956 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2138956 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2242415. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2242415_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2242415 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR_EL1_BIT_22 + msr NEOVERSE_N2_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n2_2242415_wa + +func check_errata_2242415 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2242415 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2138953. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2138953_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2138953 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUECTLR2_EL1 + mov x0, #NEOVERSE_N2_CPUECTLR2_EL1_PF_MODE_CNSRV + bfi x1, x0, #CPUECTLR2_EL1_PF_MODE_LSB, #CPUECTLR2_EL1_PF_MODE_WIDTH + msr NEOVERSE_N2_CPUECTLR2_EL1, x1 +1: + ret x17 +endfunc errata_n2_2138953_wa + +func check_errata_2138953 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2138953 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2138958. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2138958_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2138958 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUACTLR5_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR5_EL1_BIT_13 + msr NEOVERSE_N2_CPUACTLR5_EL1, x1 +1: + ret x17 +endfunc errata_n2_2138958_wa + +func check_errata_2138958 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2138958 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2242400. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2242400_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2242400 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUACTLR5_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR5_EL1_BIT_17 + msr NEOVERSE_N2_CPUACTLR5_EL1, x1 + ldr x0, =0x2 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10F600E000 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FF80E000 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x80000000003FF + msr S3_6_c15_c8_1, x0 + isb +1: + ret x17 +endfunc errata_n2_2242400_wa + +func check_errata_2242400 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2242400 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2280757. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2280757_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2280757 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR_EL1_BIT_22 + msr NEOVERSE_N2_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n2_2280757_wa + +func check_errata_2280757 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2280757 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------- + * The CPU Ops reset function for Neoverse N2. + * ------------------------------------------- + */ +func neoverse_n2_reset_func + mov x19, x30 + + /* Check if the PE implements SSBS */ + mrs x0, id_aa64pfr1_el1 + tst x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT) + b.eq 1f + + /* Disable speculative loads */ + msr SSBS, xzr +1: + /* Force all cacheable atomic instructions to be near */ + mrs x0, NEOVERSE_N2_CPUACTLR2_EL1 + orr x0, x0, #NEOVERSE_N2_CPUACTLR2_EL1_BIT_2 + msr NEOVERSE_N2_CPUACTLR2_EL1, x0 + +#if ERRATA_N2_2067956 + mov x0, x18 + bl errata_n2_2067956_wa +#endif + +#if ERRATA_N2_2025414 + mov x0, x18 + bl errata_n2_2025414_wa +#endif + +#if ERRATA_N2_2189731 + mov x0, x18 + bl errata_n2_2189731_wa +#endif + + +#if ERRATA_N2_2138956 + mov x0, x18 + bl errata_n2_2138956_wa +#endif + +#if ERRATA_N2_2138953 + mov x0, x18 + bl errata_n2_2138953_wa +#endif + +#if ERRATA_N2_2242415 + mov x0, x18 + bl errata_n2_2242415_wa +#endif + +#if ERRATA_N2_2138958 + mov x0, x18 + bl errata_n2_2138958_wa +#endif + +#if ERRATA_N2_2242400 + mov x0, x18 + bl errata_n2_2242400_wa +#endif + +#if ERRATA_N2_2280757 + mov x0, x18 + bl errata_n2_2280757_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, cptr_el3 + orr x0, x0, #TAM_BIT + msr cptr_el3, x0 + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, cptr_el2 + orr x0, x0, #TAM_BIT + msr cptr_el2, x0 + + /* No need to enable the counters as this would be done at el3 exit */ +#endif + +#if NEOVERSE_Nx_EXTERNAL_LLC + /* Some systems may have External LLC, core needs to be made aware */ + mrs x0, NEOVERSE_N2_CPUECTLR_EL1 + orr x0, x0, NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT + msr NEOVERSE_N2_CPUECTLR_EL1, x0 +#endif + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_N2_2002655 + mov x0, x18 + bl errata_n2_2002655_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Neoverse-N2 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_neoverse_n2 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc neoverse_n2_reset_func + +func neoverse_n2_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * No need to do cache maintenance here. + * --------------------------------------------------- + */ + mrs x0, NEOVERSE_N2_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_N2_CORE_PWRDN_EN_BIT + msr NEOVERSE_N2_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_n2_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Neoverse N2 cores. Must follow AAPCS. + */ +func neoverse_n2_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_N2_2002655, neoverse_n2, 2002655 + report_errata ERRATA_N2_2067956, neoverse_n2, 2067956 + report_errata ERRATA_N2_2025414, neoverse_n2, 2025414 + report_errata ERRATA_N2_2189731, neoverse_n2, 2189731 + report_errata ERRATA_N2_2138956, neoverse_n2, 2138956 + report_errata ERRATA_N2_2138953, neoverse_n2, 2138953 + report_errata ERRATA_N2_2242415, neoverse_n2, 2242415 + report_errata ERRATA_N2_2138958, neoverse_n2, 2138958 + report_errata ERRATA_N2_2242400, neoverse_n2, 2242400 + report_errata ERRATA_N2_2280757, neoverse_n2, 2280757 + report_errata WORKAROUND_CVE_2022_23960, neoverse_n2, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc neoverse_n2_errata_report +#endif + + /* --------------------------------------------- + * This function provides Neoverse N2 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.neoverse_n2_regs, "aS" +neoverse_n2_regs: /* The ASCII list of register names to be reported */ + .asciz "cpupwrctlr_el1", "" + +func neoverse_n2_cpu_reg_dump + adr x6, neoverse_n2_regs + mrs x8, NEOVERSE_N2_CPUPWRCTLR_EL1 + ret +endfunc neoverse_n2_cpu_reg_dump + +declare_cpu_ops neoverse_n2, NEOVERSE_N2_MIDR, \ + neoverse_n2_reset_func, \ + neoverse_n2_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S new file mode 100644 index 0000000..b816342 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .global is_scu_present_in_dsu + +/* + * Check if the SCU L3 Unit is present on the DSU + * 1-> SCU present + * 0-> SCU not present + * + * This function is implemented as weak on dsu_helpers.S and must be + * overwritten for Neoverse Nx cores. + */ + +func is_scu_present_in_dsu + mrs x0, CPUCFR_EL1 + ubfx x0, x0, #SCU_SHIFT, #1 + eor x0, x0, #1 + ret +endfunc is_scu_present_in_dsu diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S new file mode 100644 index 0000000..43a93aa --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse Poseidon must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse Poseidon supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func neoverse_poseidon_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, NEOVERSE_POSEIDON_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_POSEIDON_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_POSEIDON_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_poseidon_core_pwr_dwn + +#if REPORT_ERRATA + /* + * Errata printing function for Neoverse Poseidon. Must follow AAPCS. + */ +func neoverse_poseidon_errata_report + ret +endfunc neoverse_poseidon_errata_report +#endif + +func neoverse_poseidon_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc neoverse_poseidon_reset_func + + /* --------------------------------------------- + * This function provides Neoverse-Poseidon 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.neoverse_poseidon_regs, "aS" +neoverse_poseidon_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_poseidon_cpu_reg_dump + adr x6, neoverse_poseidon_regs + mrs x8, NEOVERSE_POSEIDON_CPUECTLR_EL1 + ret +endfunc neoverse_poseidon_cpu_reg_dump + +declare_cpu_ops neoverse_poseidon, NEOVERSE_POSEIDON_MIDR, \ + neoverse_poseidon_reset_func, \ + neoverse_poseidon_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S new file mode 100644 index 0000000..6adb3a8 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse V1 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse-V1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table NEOVERSE_V1_BHB_LOOP_COUNT, neoverse_v1 +#endif /* WORKAROUND_CVE_2022_23960 */ + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1774420. + * This applies to revisions r0p0 and r1p0, fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1774420_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1774420 + cbz x0, 1f + + /* Set bit 53 in CPUECTLR_EL1 */ + mrs x1, NEOVERSE_V1_CPUECTLR_EL1 + orr x1, x1, #NEOVERSE_V1_CPUECTLR_EL1_BIT_53 + msr NEOVERSE_V1_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_neoverse_v1_1774420_wa + +func check_errata_1774420 + /* Applies to r0p0 and r1p0. */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1774420 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1791573. + * This applies to revisions r0p0 and r1p0, fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1791573_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1791573 + cbz x0, 1f + + /* Set bit 2 in ACTLR2_EL1 */ + mrs x1, NEOVERSE_V1_ACTLR2_EL1 + orr x1, x1, #NEOVERSE_V1_ACTLR2_EL1_BIT_2 + msr NEOVERSE_V1_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_neoverse_v1_1791573_wa + +func check_errata_1791573 + /* Applies to r0p0 and r1p0. */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1791573 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1852267. + * This applies to revisions r0p0 and r1p0, fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1852267_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1852267 + cbz x0, 1f + + /* Set bit 28 in ACTLR2_EL1 */ + mrs x1, NEOVERSE_V1_ACTLR2_EL1 + orr x1, x1, #NEOVERSE_V1_ACTLR2_EL1_BIT_28 + msr NEOVERSE_V1_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_neoverse_v1_1852267_wa + +func check_errata_1852267 + /* Applies to r0p0 and r1p0. */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1852267 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1925756. + * This applies to revisions <= r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1925756_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1925756 + cbz x0, 1f + + /* Set bit 8 in CPUECTLR_EL1 */ + mrs x1, NEOVERSE_V1_CPUECTLR_EL1 + orr x1, x1, #NEOVERSE_V1_CPUECTLR_EL1_BIT_8 + msr NEOVERSE_V1_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_neoverse_v1_1925756_wa + +func check_errata_1925756 + /* Applies to <= r1p1. */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1925756 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Erratum #1940577 + * This applies to revisions r1p0 - r1p1 and is open. + * It also exists in r0p0 but there is no fix in that + * revision. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1940577_wa + /* Compare x0 against revisions r1p0 - r1p1 */ + mov x17, x30 + bl check_errata_1940577 + cbz x0, 1f + + mov x0, #0 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3900002 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #1 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #2 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + isb +1: + ret x17 +endfunc errata_neoverse_v1_1940577_wa + +func check_errata_1940577 + /* Applies to revisions r1p0 - r1p1. */ + mov x1, #0x10 + mov x2, #0x11 + b cpu_rev_var_range +endfunc check_errata_1940577 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1966096 + * This applies to revisions r1p0 - r1p1 and is open. + * It also exists in r0p0 but there is no workaround + * for that revision. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1966096_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1966096 + cbz x0, 1f + + /* Apply the workaround. */ + mov x0, #0x3 + msr S3_6_C15_C8_0, x0 + ldr x0, =0xEE010F12 + msr S3_6_C15_C8_2, x0 + ldr x0, =0xFFFF0FFF + msr S3_6_C15_C8_3, x0 + ldr x0, =0x80000000003FF + msr S3_6_C15_C8_1, x0 + isb + +1: + ret x17 +endfunc errata_neoverse_v1_1966096_wa + +func check_errata_1966096 + mov x1, #0x10 + mov x2, #0x11 + b cpu_rev_var_range +endfunc check_errata_1966096 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #2139242. + * This applies to revisions r0p0, r1p0, and r1p1, it + * is still open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_2139242_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2139242 + cbz x0, 1f + + /* Apply the workaround. */ + mov x0, #0x3 + msr S3_6_C15_C8_0, x0 + ldr x0, =0xEE720F14 + msr S3_6_C15_C8_2, x0 + ldr x0, =0xFFFF0FDF + msr S3_6_C15_C8_3, x0 + ldr x0, =0x40000005003FF + msr S3_6_C15_C8_1, x0 + isb + +1: + ret x17 +endfunc errata_neoverse_v1_2139242_wa + +func check_errata_2139242 + /* Applies to r0p0, r1p0, r1p1 */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_2139242 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #2108267. + * This applies to revisions r0p0, r1p0, and r1p1, it + * is still open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_2108267_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2108267 + cbz x0, 1f + + /* Apply the workaround. */ + mrs x1, NEOVERSE_V1_CPUECTLR_EL1 + mov x0, #NEOVERSE_V1_CPUECTLR_EL1_PF_MODE_CNSRV + bfi x1, x0, #CPUECTLR_EL1_PF_MODE_LSB, #CPUECTLR_EL1_PF_MODE_WIDTH + msr NEOVERSE_V1_CPUECTLR_EL1, x1 +1: + ret x17 +endfunc errata_neoverse_v1_2108267_wa + +func check_errata_2108267 + /* Applies to r0p0, r1p0, r1p1 */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_2108267 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #2216392. + * This applies to revisions r1p0 and r1p1 and is + * still open. + * This issue is also present in r0p0 but there is no + * workaround in that revision. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_2216392_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2216392 + cbz x0, 1f + + ldr x0, =0x5 + msr S3_6_c15_c8_0, x0 /* CPUPSELR_EL3 */ + ldr x0, =0x10F600E000 + msr S3_6_c15_c8_2, x0 /* CPUPOR_EL3 */ + ldr x0, =0x10FF80E000 + msr S3_6_c15_c8_3, x0 /* CPUPMR_EL3 */ + ldr x0, =0x80000000003FF + msr S3_6_c15_c8_1, x0 /* CPUPCR_EL3 */ + + isb +1: + ret x17 +endfunc errata_neoverse_v1_2216392_wa + +func check_errata_2216392 + /* Applies to revisions r1p0 and r1p1. */ + mov x1, #CPU_REV(1, 0) + mov x2, #CPU_REV(1, 1) + b cpu_rev_var_range +endfunc check_errata_2216392 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func neoverse_v1_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, NEOVERSE_V1_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_V1_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_v1_core_pwr_dwn + + /* + * Errata printing function for Neoverse V1. Must follow AAPCS. + */ +#if REPORT_ERRATA +func neoverse_v1_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_V1_1774420, neoverse_v1, 1774420 + report_errata ERRATA_V1_1791573, neoverse_v1, 1791573 + report_errata ERRATA_V1_1852267, neoverse_v1, 1852267 + report_errata ERRATA_V1_1925756, neoverse_v1, 1925756 + report_errata ERRATA_V1_1940577, neoverse_v1, 1940577 + report_errata ERRATA_V1_1966096, neoverse_v1, 1966096 + report_errata ERRATA_V1_2139242, neoverse_v1, 2139242 + report_errata ERRATA_V1_2108267, neoverse_v1, 2108267 + report_errata ERRATA_V1_2216392, neoverse_v1, 2216392 + report_errata WORKAROUND_CVE_2022_23960, neoverse_v1, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc neoverse_v1_errata_report +#endif + +func neoverse_v1_reset_func + mov x19, x30 + + /* Disable speculative loads */ + msr SSBS, xzr + isb + +#if ERRATA_V1_1774420 + mov x0, x18 + bl errata_neoverse_v1_1774420_wa +#endif + +#if ERRATA_V1_1791573 + mov x0, x18 + bl errata_neoverse_v1_1791573_wa +#endif + +#if ERRATA_V1_1852267 + mov x0, x18 + bl errata_neoverse_v1_1852267_wa +#endif + +#if ERRATA_V1_1925756 + mov x0, x18 + bl errata_neoverse_v1_1925756_wa +#endif + +#if ERRATA_V1_1940577 + mov x0, x18 + bl errata_neoverse_v1_1940577_wa +#endif + +#if ERRATA_V1_1966096 + mov x0, x18 + bl errata_neoverse_v1_1966096_wa +#endif + +#if ERRATA_V1_2139242 + mov x0, x18 + bl errata_neoverse_v1_2139242_wa +#endif + +#if ERRATA_V1_2108267 + mov x0, x18 + bl errata_neoverse_v1_2108267_wa +#endif + +#if ERRATA_V1_2216392 + mov x0, x18 + bl errata_neoverse_v1_2216392_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Neoverse-V1 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_neoverse_v1 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc neoverse_v1_reset_func + + /* --------------------------------------------- + * This function provides Neoverse-V1 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.neoverse_v1_regs, "aS" +neoverse_v1_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_v1_cpu_reg_dump + adr x6, neoverse_v1_regs + mrs x8, NEOVERSE_V1_CPUECTLR_EL1 + ret +endfunc neoverse_v1_cpu_reg_dump + +declare_cpu_ops neoverse_v1, NEOVERSE_V1_MIDR, \ + neoverse_v1_reset_func, \ + neoverse_v1_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S b/arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S new file mode 100644 index 0000000..8948fda --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +func qemu_max_core_pwr_dwn + /* --------------------------------------------- + * Disable the Data Cache. + * --------------------------------------------- + */ + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + + /* --------------------------------------------- + * Flush L1 cache to L2. + * --------------------------------------------- + */ + mov x18, lr + mov x0, #DCCISW + bl dcsw_op_level1 + mov lr, x18 + ret +endfunc qemu_max_core_pwr_dwn + +func qemu_max_cluster_pwr_dwn + /* --------------------------------------------- + * Disable the Data Cache. + * --------------------------------------------- + */ + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + + /* --------------------------------------------- + * Flush all caches to PoC. + * --------------------------------------------- + */ + mov x0, #DCCISW + b dcsw_op_all +endfunc qemu_max_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for QEMU "max". Must follow AAPCS. + */ +func qemu_max_errata_report + ret +endfunc qemu_max_errata_report +#endif + + /* --------------------------------------------- + * This function provides cpu 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.qemu_max_regs, "aS" +qemu_max_regs: /* The ascii list of register names to be reported */ + .asciz "" /* no registers to report */ + +func qemu_max_cpu_reg_dump + adr x6, qemu_max_regs + ret +endfunc qemu_max_cpu_reg_dump + + +/* cpu_ops for QEMU MAX */ +declare_cpu_ops qemu_max, QEMU_MAX_MIDR, CPU_NO_RESET_FUNC, \ + qemu_max_core_pwr_dwn, \ + qemu_max_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/rainier.S b/arm-trusted-firmware/lib/cpus/aarch64/rainier.S new file mode 100644 index 0000000..584ab97 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/rainier.S @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Rainier CPU must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Rainier CPU supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +/* -------------------------------------------------- + * Disable speculative loads if Rainier supports + * SSBS. + * + * Shall clobber: x0. + * -------------------------------------------------- + */ +func rainier_disable_speculative_loads + /* Check if the PE implements SSBS */ + mrs x0, id_aa64pfr1_el1 + tst x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT) + b.eq 1f + + /* Disable speculative loads */ + msr SSBS, xzr + +1: + ret +endfunc rainier_disable_speculative_loads + + /* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1868343. + * This applies to revision <= r4p0 of Neoverse N1. + * This workaround is the same as the workaround for + * errata 1262606 and 1275112 but applies to a wider + * revision range. + * Rainier R0P0 is based on Neoverse N1 R4P0 so the + * workaround checks for r0p0 version of Rainier CPU. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1 & x17 + * -------------------------------------------------- + */ +func errata_n1_1868343_wa + /* + * Compare x0 against revision r4p0 + */ + mov x17, x30 + bl check_errata_1868343 + cbz x0, 1f + mrs x1, RAINIER_CPUACTLR_EL1 + orr x1, x1, RAINIER_CPUACTLR_EL1_BIT_13 + msr RAINIER_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_n1_1868343_wa + +func check_errata_1868343 + /* Applies to r0p0 of Rainier CPU */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_1868343 + +func rainier_reset_func + mov x19, x30 + + bl rainier_disable_speculative_loads + + /* Forces all cacheable atomic instructions to be near */ + mrs x0, RAINIER_CPUACTLR2_EL1 + orr x0, x0, #RAINIER_CPUACTLR2_EL1_BIT_2 + msr RAINIER_CPUACTLR2_EL1, x0 + isb + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_N1_1868343 + mov x0, x18 + bl errata_n1_1868343_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #RAINIER_ACTLR_AMEN_BIT + msr actlr_el3, x0 + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #RAINIER_ACTLR_AMEN_BIT + msr actlr_el2, x0 + + /* Enable group0 counters */ + mov x0, #RAINIER_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 +#endif + + isb + ret x19 +endfunc rainier_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func rainier_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, RAINIER_CPUPWRCTLR_EL1 + orr x0, x0, #RAINIER_CORE_PWRDN_EN_MASK + msr RAINIER_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc rainier_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Rainier. Must follow AAPCS. + */ +func rainier_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_N1_1868343, rainier, 1868343 + + ldp x8, x30, [sp], #16 + ret +endfunc rainier_errata_report +#endif + + /* --------------------------------------------- + * This function provides Rainier 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.rainier_regs, "aS" +rainier_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func rainier_cpu_reg_dump + adr x6, rainier_regs + mrs x8, RAINIER_CPUECTLR_EL1 + ret +endfunc rainier_cpu_reg_dump + +declare_cpu_ops rainier, RAINIER_MIDR, \ + rainier_reset_func, \ + rainier_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S new file mode 100644 index 0000000..0222818 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl wa_cve_2017_5715_bpiall_vbar + +#define EMIT_BPIALL 0xee070fd5 +#define EMIT_SMC 0xe1600070 +#define ESR_EL3_A64_SMC0 0x5e000000 + + .macro apply_cve_2017_5715_wa _from_vector + /* + * Save register state to enable a call to AArch32 S-EL1 and return + * Identify the original calling vector in w2 (==_from_vector) + * Use w3-w6 for additional register state preservation while in S-EL1 + */ + + /* Save GP regs */ + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6] + stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8] + stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10] + stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12] + stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14] + stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16] + stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18] + stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20] + stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22] + stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24] + stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26] + stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + + /* Identify the original exception vector */ + mov w2, \_from_vector + + /* Preserve 32-bit system registers in GP registers through the workaround */ + mrs x3, esr_el3 + mrs x4, spsr_el3 + mrs x5, scr_el3 + mrs x6, sctlr_el1 + + /* + * Preserve LR and ELR_EL3 registers in the GP regs context. + * Temporarily use the CTX_GPREG_SP_EL0 slot to preserve ELR_EL3 + * through the workaround. This is OK because at this point the + * current state for this context's SP_EL0 is in the live system + * register, which is unmodified by the workaround. + */ + mrs x7, elr_el3 + stp x30, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* + * Load system registers for entry to S-EL1. + */ + + /* Mask all interrupts and set AArch32 Supervisor mode */ + movz w8, SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, SPSR_AIF_MASK) + + /* Switch EL3 exception vectors while the workaround is executing. */ + adr x9, wa_cve_2017_5715_bpiall_ret_vbar + + /* Setup SCTLR_EL1 with MMU off and I$ on */ + ldr x10, stub_sel1_sctlr + + /* Land at the S-EL1 workaround stub */ + adr x11, aarch32_stub + + /* + * Setting SCR_EL3 to all zeroes means that the NS, RW + * and SMD bits are configured as expected. + */ + msr scr_el3, xzr + msr spsr_el3, x8 + msr vbar_el3, x9 + msr sctlr_el1, x10 + msr elr_el3, x11 + + eret + .endm + + /* --------------------------------------------------------------------- + * This vector table is used at runtime to enter the workaround at + * AArch32 S-EL1 for Sync/IRQ/FIQ/SError exceptions. If the workaround + * is not enabled, the existing runtime exception vector table is used. + * --------------------------------------------------------------------- + */ +vector_base wa_cve_2017_5715_bpiall_vbar + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_sync_exception_sp_el0 + b sync_exception_sp_el0 + nop /* to force 8 byte alignment for the following stub */ + + /* + * Since each vector table entry is 128 bytes, we can store the + * stub context in the unused space to minimize memory footprint. + */ +stub_sel1_sctlr: + .quad SCTLR_AARCH32_EL1_RES1 | SCTLR_I_BIT + +aarch32_stub: + .word EMIT_BPIALL + .word EMIT_SMC + +end_vector_entry bpiall_sync_exception_sp_el0 + +vector_entry bpiall_irq_sp_el0 + b irq_sp_el0 +end_vector_entry bpiall_irq_sp_el0 + +vector_entry bpiall_fiq_sp_el0 + b fiq_sp_el0 +end_vector_entry bpiall_fiq_sp_el0 + +vector_entry bpiall_serror_sp_el0 + b serror_sp_el0 +end_vector_entry bpiall_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_sync_exception_sp_elx + b sync_exception_sp_elx +end_vector_entry bpiall_sync_exception_sp_elx + +vector_entry bpiall_irq_sp_elx + b irq_sp_elx +end_vector_entry bpiall_irq_sp_elx + +vector_entry bpiall_fiq_sp_elx + b fiq_sp_elx +end_vector_entry bpiall_fiq_sp_elx + +vector_entry bpiall_serror_sp_elx + b serror_sp_elx +end_vector_entry bpiall_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_sync_exception_aarch64 + apply_cve_2017_5715_wa 1 +end_vector_entry bpiall_sync_exception_aarch64 + +vector_entry bpiall_irq_aarch64 + apply_cve_2017_5715_wa 2 +end_vector_entry bpiall_irq_aarch64 + +vector_entry bpiall_fiq_aarch64 + apply_cve_2017_5715_wa 4 +end_vector_entry bpiall_fiq_aarch64 + +vector_entry bpiall_serror_aarch64 + apply_cve_2017_5715_wa 8 +end_vector_entry bpiall_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_sync_exception_aarch32 + apply_cve_2017_5715_wa 1 +end_vector_entry bpiall_sync_exception_aarch32 + +vector_entry bpiall_irq_aarch32 + apply_cve_2017_5715_wa 2 +end_vector_entry bpiall_irq_aarch32 + +vector_entry bpiall_fiq_aarch32 + apply_cve_2017_5715_wa 4 +end_vector_entry bpiall_fiq_aarch32 + +vector_entry bpiall_serror_aarch32 + apply_cve_2017_5715_wa 8 +end_vector_entry bpiall_serror_aarch32 + + /* --------------------------------------------------------------------- + * This vector table is used while the workaround is executing. It + * installs a simple SMC handler to allow the Sync/IRQ/FIQ/SError + * workaround stubs to enter EL3 from S-EL1. It restores the previous + * EL3 state before proceeding with the normal runtime exception vector. + * --------------------------------------------------------------------- + */ +vector_base wa_cve_2017_5715_bpiall_ret_vbar + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 (UNUSED) + * --------------------------------------------------------------------- + */ +vector_entry bpiall_ret_sync_exception_sp_el0 + b report_unhandled_exception +end_vector_entry bpiall_ret_sync_exception_sp_el0 + +vector_entry bpiall_ret_irq_sp_el0 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_irq_sp_el0 + +vector_entry bpiall_ret_fiq_sp_el0 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_fiq_sp_el0 + +vector_entry bpiall_ret_serror_sp_el0 + b report_unhandled_exception +end_vector_entry bpiall_ret_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 (UNUSED) + * --------------------------------------------------------------------- + */ +vector_entry bpiall_ret_sync_exception_sp_elx + b report_unhandled_exception +end_vector_entry bpiall_ret_sync_exception_sp_elx + +vector_entry bpiall_ret_irq_sp_elx + b report_unhandled_interrupt +end_vector_entry bpiall_ret_irq_sp_elx + +vector_entry bpiall_ret_fiq_sp_elx + b report_unhandled_interrupt +end_vector_entry bpiall_ret_fiq_sp_elx + +vector_entry bpiall_ret_serror_sp_elx + b report_unhandled_exception +end_vector_entry bpiall_ret_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 (UNUSED) + * --------------------------------------------------------------------- + */ +vector_entry bpiall_ret_sync_exception_aarch64 + b report_unhandled_exception +end_vector_entry bpiall_ret_sync_exception_aarch64 + +vector_entry bpiall_ret_irq_aarch64 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_irq_aarch64 + +vector_entry bpiall_ret_fiq_aarch64 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_fiq_aarch64 + +vector_entry bpiall_ret_serror_aarch64 + b report_unhandled_exception +end_vector_entry bpiall_ret_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_ret_sync_exception_aarch32 + /* + * w2 indicates which SEL1 stub was run and thus which original vector was used + * w3-w6 contain saved system register state (esr_el3 in w3) + * Restore LR and ELR_EL3 register state from the GP regs context + */ + ldp x30, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* Apply the restored system register state */ + msr esr_el3, x3 + msr spsr_el3, x4 + msr scr_el3, x5 + msr sctlr_el1, x6 + msr elr_el3, x7 + + /* + * Workaround is complete, so swap VBAR_EL3 to point + * to workaround entry table in preparation for subsequent + * Sync/IRQ/FIQ/SError exceptions. + */ + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + + /* + * Restore all GP regs except x2 and x3 (esr). The value in x2 + * indicates the type of the original exception. + */ + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + ldp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6] + ldp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8] + ldp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10] + ldp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12] + ldp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14] + ldp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16] + ldp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18] + ldp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20] + ldp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22] + ldp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24] + ldp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26] + ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + + /* Fast path Sync exceptions. Static predictor will fall through. */ + tbz w2, #0, workaround_not_sync + + /* + * Check if SMC is coming from A64 state on #0 + * with W0 = SMCCC_ARCH_WORKAROUND_1 or W0 = SMCCC_ARCH_WORKAROUND_3 + * + * This sequence evaluates as: + * (W0==SMCCC_ARCH_WORKAROUND_1) || (W0==SMCCC_ARCH_WORKAROUND_3) ? + * (ESR_EL3==SMC#0) : (NE) + * allowing use of a single branch operation + */ + orr w2, wzr, #SMCCC_ARCH_WORKAROUND_1 + cmp w0, w2 + orr w2, wzr, #SMCCC_ARCH_WORKAROUND_3 + ccmp w0, w2, #4, ne + mov_imm w2, ESR_EL3_A64_SMC0 + ccmp w3, w2, #0, eq + /* Static predictor will predict a fall through */ + bne 1f + eret +1: + /* restore x2 and x3 and continue sync exception handling */ + b bpiall_ret_sync_exception_aarch32_tail +end_vector_entry bpiall_ret_sync_exception_aarch32 + +vector_entry bpiall_ret_irq_aarch32 + b report_unhandled_interrupt + + /* + * Post-workaround fan-out for non-sync exceptions + */ +workaround_not_sync: + tbnz w2, #3, bpiall_ret_serror + tbnz w2, #2, bpiall_ret_fiq + /* IRQ */ + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + b irq_aarch64 + +bpiall_ret_fiq: + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + b fiq_aarch64 + +bpiall_ret_serror: + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + b serror_aarch64 +end_vector_entry bpiall_ret_irq_aarch32 + +vector_entry bpiall_ret_fiq_aarch32 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_fiq_aarch32 + +vector_entry bpiall_ret_serror_aarch32 + b report_unhandled_exception +end_vector_entry bpiall_ret_serror_aarch32 + + /* + * Part of bpiall_ret_sync_exception_aarch32 to save vector space + */ +func bpiall_ret_sync_exception_aarch32_tail + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + b sync_exception_aarch64 +endfunc bpiall_ret_sync_exception_aarch32_tail diff --git a/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S new file mode 100644 index 0000000..ed0a549 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl wa_cve_2017_5715_mmu_vbar + +#define ESR_EL3_A64_SMC0 0x5e000000 +#define ESR_EL3_A32_SMC0 0x4e000000 + +vector_base wa_cve_2017_5715_mmu_vbar + + .macro apply_cve_2017_5715_wa _is_sync_exception _esr_el3_val + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + mrs x1, sctlr_el3 + /* Disable MMU */ + bic x1, x1, #SCTLR_M_BIT + msr sctlr_el3, x1 + isb + /* Enable MMU */ + orr x1, x1, #SCTLR_M_BIT + msr sctlr_el3, x1 + /* + * Defer ISB to avoid synchronizing twice in case we hit + * the workaround SMC call which will implicitly synchronize + * because of the ERET instruction. + */ + + /* + * Ensure SMC is coming from A64/A32 state on #0 + * with W0 = SMCCC_ARCH_WORKAROUND_1 or W0 = SMCCC_ARCH_WORKAROUND_3 + * + * This sequence evaluates as: + * (W0==SMCCC_ARCH_WORKAROUND_1) || (W0==SMCCC_ARCH_WORKAROUND_3) ? + * (ESR_EL3==SMC#0) : (NE) + * allowing use of a single branch operation + */ + .if \_is_sync_exception + orr w1, wzr, #SMCCC_ARCH_WORKAROUND_1 + cmp w0, w1 + orr w1, wzr, #SMCCC_ARCH_WORKAROUND_3 + ccmp w0, w1, #4, ne + mrs x0, esr_el3 + mov_imm w1, \_esr_el3_val + ccmp w0, w1, #0, eq + /* Static predictor will predict a fall through */ + bne 1f + exception_return +1: + .endif + + /* + * Synchronize now to enable the MMU. This is required + * to ensure the load pair below reads the data stored earlier. + */ + isb + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + .endm + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry mmu_sync_exception_sp_el0 + b sync_exception_sp_el0 +end_vector_entry mmu_sync_exception_sp_el0 + +vector_entry mmu_irq_sp_el0 + b irq_sp_el0 +end_vector_entry mmu_irq_sp_el0 + +vector_entry mmu_fiq_sp_el0 + b fiq_sp_el0 +end_vector_entry mmu_fiq_sp_el0 + +vector_entry mmu_serror_sp_el0 + b serror_sp_el0 +end_vector_entry mmu_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry mmu_sync_exception_sp_elx + b sync_exception_sp_elx +end_vector_entry mmu_sync_exception_sp_elx + +vector_entry mmu_irq_sp_elx + b irq_sp_elx +end_vector_entry mmu_irq_sp_elx + +vector_entry mmu_fiq_sp_elx + b fiq_sp_elx +end_vector_entry mmu_fiq_sp_elx + +vector_entry mmu_serror_sp_elx + b serror_sp_elx +end_vector_entry mmu_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry mmu_sync_exception_aarch64 + apply_cve_2017_5715_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A64_SMC0 + b sync_exception_aarch64 +end_vector_entry mmu_sync_exception_aarch64 + +vector_entry mmu_irq_aarch64 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b irq_aarch64 +end_vector_entry mmu_irq_aarch64 + +vector_entry mmu_fiq_aarch64 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b fiq_aarch64 +end_vector_entry mmu_fiq_aarch64 + +vector_entry mmu_serror_aarch64 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b serror_aarch64 +end_vector_entry mmu_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry mmu_sync_exception_aarch32 + apply_cve_2017_5715_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A32_SMC0 + b sync_exception_aarch32 +end_vector_entry mmu_sync_exception_aarch32 + +vector_entry mmu_irq_aarch32 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b irq_aarch32 +end_vector_entry mmu_irq_aarch32 + +vector_entry mmu_fiq_aarch32 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b fiq_aarch32 +end_vector_entry mmu_fiq_aarch32 + +vector_entry mmu_serror_aarch32 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b serror_aarch32 +end_vector_entry mmu_serror_aarch32 diff --git a/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S new file mode 100644 index 0000000..e0e41cc --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#if WORKAROUND_CVE_2022_23960 + /* + * This macro applies the mitigation for CVE-2022-23960. + * The macro saves x2-x3 to the CPU context. + * SP should point to the CPU context. + */ + .macro apply_cve_2022_23960_bhb_wa _bhb_loop_count + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + + /* CVE-BHB-NUM loop count */ + mov x2, \_bhb_loop_count + +1: + /* b pc+4 part of the workaround */ + b 2f +2: + subs x2, x2, #1 + bne 1b + dsb sy + isb + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + .endm +#endif /* WORKAROUND_CVE_2022_23960 */ diff --git a/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S new file mode 100644 index 0000000..220fa11 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "wa_cve_2022_23960_bhb.S" + + /* + * This macro is used to isolate the vector table for relevant CPUs + * used in the mitigation for CVE_2022_23960. + */ + .macro wa_cve_2022_23960_bhb_vector_table _bhb_loop_count, _cpu + + .globl wa_cve_vbar_\_cpu + +vector_base wa_cve_vbar_\_cpu + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry bhb_sync_exception_sp_el0_\_cpu + b sync_exception_sp_el0 +end_vector_entry bhb_sync_exception_sp_el0_\_cpu + +vector_entry bhb_irq_sp_el0_\_cpu + b irq_sp_el0 +end_vector_entry bhb_irq_sp_el0_\_cpu + +vector_entry bhb_fiq_sp_el0_\_cpu + b fiq_sp_el0 +end_vector_entry bhb_fiq_sp_el0_\_cpu + +vector_entry bhb_serror_sp_el0_\_cpu + b serror_sp_el0 +end_vector_entry bhb_serror_sp_el0_\_cpu + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry bhb_sync_exception_sp_elx_\_cpu + b sync_exception_sp_elx +end_vector_entry bhb_sync_exception_sp_elx_\_cpu + +vector_entry bhb_irq_sp_elx_\_cpu + b irq_sp_elx +end_vector_entry bhb_irq_sp_elx_\_cpu + +vector_entry bhb_fiq_sp_elx_\_cpu + b fiq_sp_elx +end_vector_entry bhb_fiq_sp_elx_\_cpu + +vector_entry bhb_serror_sp_elx_\_cpu + b serror_sp_elx +end_vector_entry bhb_serror_sp_elx_\_cpu + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry bhb_sync_exception_aarch64_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b sync_exception_aarch64 +end_vector_entry bhb_sync_exception_aarch64_\_cpu + +vector_entry bhb_irq_aarch64_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b irq_aarch64 +end_vector_entry bhb_irq_aarch64_\_cpu + +vector_entry bhb_fiq_aarch64_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b fiq_aarch64 +end_vector_entry bhb_fiq_aarch64_\_cpu + +vector_entry bhb_serror_aarch64_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b serror_aarch64 +end_vector_entry bhb_serror_aarch64_\_cpu + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry bhb_sync_exception_aarch32_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b sync_exception_aarch32 +end_vector_entry bhb_sync_exception_aarch32_\_cpu + +vector_entry bhb_irq_aarch32_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b irq_aarch32 +end_vector_entry bhb_irq_aarch32_\_cpu + +vector_entry bhb_fiq_aarch32_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b fiq_aarch32 +end_vector_entry bhb_fiq_aarch32_\_cpu + +vector_entry bhb_serror_aarch32_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b serror_aarch32 +end_vector_entry bhb_serror_aarch32_\_cpu + .endm diff --git a/arm-trusted-firmware/lib/cpus/cpu-ops.mk b/arm-trusted-firmware/lib/cpus/cpu-ops.mk new file mode 100644 index 0000000..8840f8e --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/cpu-ops.mk @@ -0,0 +1,1100 @@ +# +# Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2022, 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 +WORKAROUND_CVE_2022_23960 ?=1 + +# 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)) + +# Process WORKAROUND_CVE_2022_23960 flag +$(eval $(call assert_boolean,WORKAROUND_CVE_2022_23960)) +$(eval $(call add_define,WORKAROUND_CVE_2022_23960)) + +$(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 1791578 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r1p1, it is still open. +ERRATA_A77_1791578 ?=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 erratum 1821534 workaround during reset. This erratum applies +# to revisions r0p0 and r1p0 of the A78 cpu. +ERRATA_A78_1821534 ?=0 + +# Flag to apply erratum 1952683 workaround during reset. This erratum applies +# to revision r0p0 of the A78 cpu and was fixed in the revision r1p0. +ERRATA_A78_1952683 ?=0 + +# Flag to apply erratum 2132060 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, r1p1, and r1p2 of the A78 cpu. It is still open. +ERRATA_A78_2132060 ?=0 + +# Flag to apply erratum 2242635 workaround during reset. This erratum applies +# to revisions r1p0, r1p1, and r1p2 of the A78 cpu and is open. The issue is +# present in r0p0 as well but there is no workaround for that revision. +ERRATA_A78_2242635 ?=0 + +# Flag to apply erratum 1941500 workaround during reset. This erratum applies +# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open. +ERRATA_A78_AE_1941500 ?=0 + +# Flag to apply erratum 1951502 workaround during reset. This erratum applies +# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open. +ERRATA_A78_AE_1951502 ?=0 + +# Flag to apply erratum 2376748 workaround during reset. This erratum applies +# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open. +ERRATA_A78_AE_2376748 ?=0 + +# Flag to apply erratum 2395408 workaround during reset. This erratum applies +# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open. +ERRATA_A78_AE_2395408 ?=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 erratum 2002655 workaround during reset. This erratum applies +# to revisions r0p0 of the Neoverse-N2 cpu, it is still open. +ERRATA_N2_2002655 ?=0 + +# Flag to apply erratum 1774420 workaround during reset. This erratum applies +# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1. +ERRATA_V1_1774420 ?=0 + +# Flag to apply erratum 1791573 workaround during reset. This erratum applies +# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1. +ERRATA_V1_1791573 ?=0 + +# Flag to apply erratum 1852267 workaround during reset. This erratum applies +# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1. +ERRATA_V1_1852267 ?=0 + +# Flag to apply erratum 1925756 workaround during reset. This needs to be +# enabled for r0p0, r1p0, and r1p1 of the Neoverse V1 core, it is still open. +ERRATA_V1_1925756 ?=0 + +# Flag to apply erratum 1940577 workaround during reset. This erratum applies +# to revisions r1p0 and r1p1 of the Neoverse V1 cpu. +ERRATA_V1_1940577 ?=0 + +# Flag to apply erratum 1966096 workaround during reset. This erratum applies +# to revisions r1p0 and r1p1 of the Neoverse V1 CPU and is open. This issue +# exists in r0p0 as well but there is no workaround for that revision. +ERRATA_V1_1966096 ?=0 + +# Flag to apply erratum 2139242 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r1p1 of the Neoverse V1 cpu and is still open. +ERRATA_V1_2139242 ?=0 + +# Flag to apply erratum 2108267 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r1p1 of the Neoverse V1 cpu and is still open. +ERRATA_V1_2108267 ?=0 + +# Flag to apply erratum 2216392 workaround during reset. This erratum applies +# to revisions r1p0 and r1p1 of the Neoverse V1 cpu and is still open. This +# issue exists in r0p0 as well but there is no workaround for that revision. +ERRATA_V1_2216392 ?=0 + +# Flag to apply erratum 1987031 workaround during reset. This erratum applies +# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_1987031 ?=0 + +# Flag to apply erratum 2081180 workaround during reset. This erratum applies +# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2081180 ?=0 + +# Flag to apply erratum 2083908 workaround during reset. This erratum applies +# to revision r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2083908 ?=0 + +# Flag to apply erratum 2058056 workaround during reset. This erratum applies +# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2058056 ?=0 + +# Flag to apply erratum 2055002 workaround during reset. This erratum applies +# to revision r1p0, r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2055002 ?=0 + +# Flag to apply erratum 2017096 workaround during reset. This erratum applies +# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2017096 ?=0 + +# Flag to apply erratum 2267065 workaround during reset. This erratum applies +# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1. +ERRATA_A710_2267065 ?=0 + +# Flag to apply erratum 2136059 workaround during reset. This erratum applies +# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1. +ERRATA_A710_2136059 ?=0 + +# Flag to apply erratum 2282622 workaround during reset. This erratum applies +# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1. +ERRATA_A710_2282622 ?=0 + +# Flag to apply erratum 2067956 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2067956 ?=0 + +# Flag to apply erratum 2025414 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2025414 ?=0 + +# Flag to apply erratum 2189731 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2189731 ?=0 + +# Flag to apply erratum 2138956 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2138956 ?=0 + +# Flag to apply erratum 2138953 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2138953 ?=0 + +# Flag to apply erratum 2242415 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2242415 ?=0 + +# Flag to apply erratum 2138958 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2138958 ?=0 + +# Flag to apply erratum 2242400 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2242400 ?=0 + +# Flag to apply erratum 2280757 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2280757 ?=0 + +# Flag to apply erratum 2002765 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r2p0 of the Cortex-X2 cpu and is still open. +ERRATA_X2_2002765 ?=0 + +# Flag to apply erratum 2058056 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r2p0 of the Cortex-X2 cpu and is still open. +ERRATA_X2_2058056 ?=0 + +# Flag to apply erratum 2083908 workaround during reset. This erratum applies +# to revision r2p0 of the Cortex-X2 cpu and is still open. +ERRATA_X2_2083908 ?=0 + +# Flag to apply erratum 2017096 workaround during reset. This erratum applies +# only to revisions r0p0, r1p0 and r2p0 of the Cortex-X2 cpu, it is fixed in +# r2p1. +ERRATA_X2_2017096 ?=0 + +# Flag to apply erratum 2081180 workaround during reset. This erratum applies +# only to revisions r0p0, r1p0 and r2p0 of the Cortex-X2 cpu, it is fixed in +# r2p1. +ERRATA_X2_2081180 ?=0 + +# Flag to apply erratum 2216384 workaround during reset. This erratum applies +# only to revisions r0p0, r1p0 and r2p0 of the Cortex-X2 cpu, it is fixed in +# r2p1. +ERRATA_X2_2216384 ?=0 + +# Flag to apply erratum 1922240 workaround during reset. This erratum applies +# to revision r0p0 of the Cortex-A510 cpu and is fixed in r0p1. +ERRATA_A510_1922240 ?=0 + +# Flag to apply erratum 2288014 workaround during reset. This erratum applies +# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0 of the Cortex-A510 cpu and is +# fixed in r1p1. +ERRATA_A510_2288014 ?=0 + +# Flag to apply erratum 2042739 workaround during reset. This erratum applies +# to revisions r0p0, r0p1 and r0p2 of the Cortex-A510 cpu and is fixed in r0p3. +ERRATA_A510_2042739 ?=0 + +# Flag to apply erratum 2041909 workaround during reset. This erratum applies +# to revision r0p2 of the Cortex-A510 cpu and is fixed in r0p3. The issue is +# present in r0p0 and r0p1 but there is no workaround for those revisions. +ERRATA_A510_2041909 ?=0 + +# Flag to apply erratum 2250311 workaround during reset. This erratum applies +# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1. +ERRATA_A510_2250311 ?=0 + +# Flag to apply erratum 2218950 workaround during reset. This erratum applies +# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1. +ERRATA_A510_2218950 ?=0 + +# Flag to apply erratum 2172148 workaround during reset. This erratum applies +# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1. +ERRATA_A510_2172148 ?=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_A77_1791578 flag +$(eval $(call assert_boolean,ERRATA_A77_1791578)) +$(eval $(call add_define,ERRATA_A77_1791578)) + +# 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_A78_1821534 flag +$(eval $(call assert_boolean,ERRATA_A78_1821534)) +$(eval $(call add_define,ERRATA_A78_1821534)) + +# Process ERRATA_A78_1952683 flag +$(eval $(call assert_boolean,ERRATA_A78_1952683)) +$(eval $(call add_define,ERRATA_A78_1952683)) + +# Process ERRATA_A78_2132060 flag +$(eval $(call assert_boolean,ERRATA_A78_2132060)) +$(eval $(call add_define,ERRATA_A78_2132060)) + +# Process ERRATA_A78_2242635 flag +$(eval $(call assert_boolean,ERRATA_A78_2242635)) +$(eval $(call add_define,ERRATA_A78_2242635)) + +# Process ERRATA_A78_AE_1941500 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_1941500)) +$(eval $(call add_define,ERRATA_A78_AE_1941500)) + +# Process ERRATA_A78_AE_1951502 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_1951502)) +$(eval $(call add_define,ERRATA_A78_AE_1951502)) + +# Process ERRATA_A78_AE_2376748 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_2376748)) +$(eval $(call add_define,ERRATA_A78_AE_2376748)) + +# Process ERRATA_A78_AE_2395408 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_2395408)) +$(eval $(call add_define,ERRATA_A78_AE_2395408)) + +# 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_N2_2002655 flag +$(eval $(call assert_boolean,ERRATA_N2_2002655)) +$(eval $(call add_define,ERRATA_N2_2002655)) + +# Process ERRATA_V1_1774420 flag +$(eval $(call assert_boolean,ERRATA_V1_1774420)) +$(eval $(call add_define,ERRATA_V1_1774420)) + +# Process ERRATA_V1_1791573 flag +$(eval $(call assert_boolean,ERRATA_V1_1791573)) +$(eval $(call add_define,ERRATA_V1_1791573)) + +# Process ERRATA_V1_1852267 flag +$(eval $(call assert_boolean,ERRATA_V1_1852267)) +$(eval $(call add_define,ERRATA_V1_1852267)) + +# Process ERRATA_V1_1925756 flag +$(eval $(call assert_boolean,ERRATA_V1_1925756)) +$(eval $(call add_define,ERRATA_V1_1925756)) + +# Process ERRATA_V1_1940577 flag +$(eval $(call assert_boolean,ERRATA_V1_1940577)) +$(eval $(call add_define,ERRATA_V1_1940577)) + +# Process ERRATA_V1_1966096 flag +$(eval $(call assert_boolean,ERRATA_V1_1966096)) +$(eval $(call add_define,ERRATA_V1_1966096)) + +# Process ERRATA_V1_2139242 flag +$(eval $(call assert_boolean,ERRATA_V1_2139242)) +$(eval $(call add_define,ERRATA_V1_2139242)) + +# Process ERRATA_V1_2108267 flag +$(eval $(call assert_boolean,ERRATA_V1_2108267)) +$(eval $(call add_define,ERRATA_V1_2108267)) + +# Process ERRATA_V1_2216392 flag +$(eval $(call assert_boolean,ERRATA_V1_2216392)) +$(eval $(call add_define,ERRATA_V1_2216392)) + +# Process ERRATA_A710_1987031 flag +$(eval $(call assert_boolean,ERRATA_A710_1987031)) +$(eval $(call add_define,ERRATA_A710_1987031)) + +# Process ERRATA_A710_2081180 flag +$(eval $(call assert_boolean,ERRATA_A710_2081180)) +$(eval $(call add_define,ERRATA_A710_2081180)) + +# Process ERRATA_A710_2083908 flag +$(eval $(call assert_boolean,ERRATA_A710_2083908)) +$(eval $(call add_define,ERRATA_A710_2083908)) + +# Process ERRATA_A710_2058056 flag +$(eval $(call assert_boolean,ERRATA_A710_2058056)) +$(eval $(call add_define,ERRATA_A710_2058056)) + +# Process ERRATA_A710_2055002 flag +$(eval $(call assert_boolean,ERRATA_A710_2055002)) +$(eval $(call add_define,ERRATA_A710_2055002)) + +# Process ERRATA_A710_2017096 flag +$(eval $(call assert_boolean,ERRATA_A710_2017096)) +$(eval $(call add_define,ERRATA_A710_2017096)) + +# Process ERRATA_A710_2267065 flag +$(eval $(call assert_boolean,ERRATA_A710_2267065)) +$(eval $(call add_define,ERRATA_A710_2267065)) + +# Process ERRATA_A710_2136059 flag +$(eval $(call assert_boolean,ERRATA_A710_2136059)) +$(eval $(call add_define,ERRATA_A710_2136059)) + +# Process ERRATA_A710_2282622 flag +$(eval $(call assert_boolean,ERRATA_A710_2282622)) +$(eval $(call add_define,ERRATA_A710_2282622)) + +# Process ERRATA_N2_2067956 flag +$(eval $(call assert_boolean,ERRATA_N2_2067956)) +$(eval $(call add_define,ERRATA_N2_2067956)) + +# Process ERRATA_N2_2025414 flag +$(eval $(call assert_boolean,ERRATA_N2_2025414)) +$(eval $(call add_define,ERRATA_N2_2025414)) + +# Process ERRATA_N2_2189731 flag +$(eval $(call assert_boolean,ERRATA_N2_2189731)) +$(eval $(call add_define,ERRATA_N2_2189731)) + +# Process ERRATA_N2_2138956 flag +$(eval $(call assert_boolean,ERRATA_N2_2138956)) +$(eval $(call add_define,ERRATA_N2_2138956)) + +# Process ERRATA_N2_2138953 flag +$(eval $(call assert_boolean,ERRATA_N2_2138953)) +$(eval $(call add_define,ERRATA_N2_2138953)) + +# Process ERRATA_N2_2242415 flag +$(eval $(call assert_boolean,ERRATA_N2_2242415)) +$(eval $(call add_define,ERRATA_N2_2242415)) + +# Process ERRATA_N2_2138958 flag +$(eval $(call assert_boolean,ERRATA_N2_2138958)) +$(eval $(call add_define,ERRATA_N2_2138958)) + +# Process ERRATA_N2_2242400 flag +$(eval $(call assert_boolean,ERRATA_N2_2242400)) +$(eval $(call add_define,ERRATA_N2_2242400)) + +# Process ERRATA_N2_2280757 flag +$(eval $(call assert_boolean,ERRATA_N2_2280757)) +$(eval $(call add_define,ERRATA_N2_2280757)) + +# Process ERRATA_X2_2002765 flag +$(eval $(call assert_boolean,ERRATA_X2_2002765)) +$(eval $(call add_define,ERRATA_X2_2002765)) + +# Process ERRATA_X2_2058056 flag +$(eval $(call assert_boolean,ERRATA_X2_2058056)) +$(eval $(call add_define,ERRATA_X2_2058056)) + +# Process ERRATA_X2_2083908 flag +$(eval $(call assert_boolean,ERRATA_X2_2083908)) +$(eval $(call add_define,ERRATA_X2_2083908)) + +# Process ERRATA_X2_2017096 flag +$(eval $(call assert_boolean,ERRATA_X2_2017096)) +$(eval $(call add_define,ERRATA_X2_2017096)) + +# Process ERRATA_X2_2081180 flag +$(eval $(call assert_boolean,ERRATA_X2_2081180)) +$(eval $(call add_define,ERRATA_X2_2081180)) + +# Process ERRATA_X2_2216384 flag +$(eval $(call assert_boolean,ERRATA_X2_2216384)) +$(eval $(call add_define,ERRATA_X2_2216384)) + +# Process ERRATA_A510_1922240 flag +$(eval $(call assert_boolean,ERRATA_A510_1922240)) +$(eval $(call add_define,ERRATA_A510_1922240)) + +# Process ERRATA_A510_2288014 flag +$(eval $(call assert_boolean,ERRATA_A510_2288014)) +$(eval $(call add_define,ERRATA_A510_2288014)) + +# Process ERRATA_A510_2042739 flag +$(eval $(call assert_boolean,ERRATA_A510_2042739)) +$(eval $(call add_define,ERRATA_A510_2042739)) + +# Process ERRATA_A510_2041909 flag +$(eval $(call assert_boolean,ERRATA_A510_2041909)) +$(eval $(call add_define,ERRATA_A510_2041909)) + +# Process ERRATA_A510_2250311 flag +$(eval $(call assert_boolean,ERRATA_A510_2250311)) +$(eval $(call add_define,ERRATA_A510_2250311)) + +# Process ERRATA_A510_2218950 flag +$(eval $(call assert_boolean,ERRATA_A510_2218950)) +$(eval $(call add_define,ERRATA_A510_2218950)) + +# Process ERRATA_A510_2172148 flag +$(eval $(call assert_boolean,ERRATA_A510_2172148)) +$(eval $(call add_define,ERRATA_A510_2172148)) + +# 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/arm-trusted-firmware/lib/cpus/errata_report.c b/arm-trusted-firmware/lib/cpus/errata_report.c new file mode 100644 index 0000000..93b2744 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/errata_report.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2021, 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(__aarch64__) && 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/arm-trusted-firmware/lib/debugfs/blobs.h b/arm-trusted-firmware/lib/debugfs/blobs.h new file mode 100644 index 0000000..54ca9f7 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/blobs.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "dev.h" + +static const dirtab_t blobtab[] = { + {"ctl", DEV_ROOT_QBLOBCTL, 0, O_READ}, + {"fip.bin", DEV_ROOT_QBLOBCTL + 1, 0x100000, O_READ, (void *)0x8000000} +}; diff --git a/arm-trusted-firmware/lib/debugfs/debugfs.mk b/arm-trusted-firmware/lib/debugfs/debugfs.mk new file mode 100644 index 0000000..138fc72 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/debugfs.mk @@ -0,0 +1,13 @@ +# +# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +DEBUGFS_SRCS := $(addprefix lib/debugfs/, \ + dev.c \ + devc.c \ + devroot.c \ + devfip.c) + +DEBUGFS_SRCS += lib/debugfs/debugfs_smc.c diff --git a/arm-trusted-firmware/lib/debugfs/debugfs_smc.c b/arm-trusted-firmware/lib/debugfs/debugfs_smc.c new file mode 100644 index 0000000..400c166 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/debugfs_smc.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAX_PATH_LEN 256 + +#define MOUNT 0 +#define CREATE 1 +#define OPEN 2 +#define CLOSE 3 +#define READ 4 +#define WRITE 5 +#define SEEK 6 +#define BIND 7 +#define STAT 8 +#define INIT 10 +#define VERSION 11 + +/* This is the virtual address to which we map the NS shared buffer */ +#define DEBUGFS_SHARED_BUF_VIRT ((void *)0x81000000U) + +static union debugfs_parms { + struct { + char fname[MAX_PATH_LEN]; + } open; + + struct { + char srv[MAX_PATH_LEN]; + char where[MAX_PATH_LEN]; + char spec[MAX_PATH_LEN]; + } mount; + + struct { + char path[MAX_PATH_LEN]; + dir_t dir; + } stat; + + struct { + char oldpath[MAX_PATH_LEN]; + char newpath[MAX_PATH_LEN]; + } bind; +} parms; + +/* debugfs_access_lock protects shared buffer and internal */ +/* FS functions from concurrent acccesses. */ +static spinlock_t debugfs_access_lock; + +static bool debugfs_initialized; + +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, + u_register_t flags) +{ + int64_t smc_ret = DEBUGFS_E_INVALID_PARAMS, smc_resp = 0; + int ret; + + /* Allow calls from non-secure only */ + if (is_caller_secure(flags)) { + SMC_RET1(handle, DEBUGFS_E_DENIED); + } + + /* Expect a SiP service fast call */ + if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || + (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { + SMC_RET1(handle, SMC_UNK); + } + + /* Truncate parameters if 32b SMC convention call */ + if (GET_SMC_CC(smc_fid) == SMC_32) { + arg2 &= 0xffffffff; + arg3 &= 0xffffffff; + arg4 &= 0xffffffff; + } + + spin_lock(&debugfs_access_lock); + + if (debugfs_initialized == true) { + /* Copy NS shared buffer to internal secure location */ + memcpy(&parms, (void *)DEBUGFS_SHARED_BUF_VIRT, + sizeof(union debugfs_parms)); + } + + switch (cmd) { + case INIT: + if (debugfs_initialized == false) { + /* TODO: check PA validity e.g. whether */ + /* it is an NS region. */ + ret = mmap_add_dynamic_region(arg2, + (uintptr_t)DEBUGFS_SHARED_BUF_VIRT, + PAGE_SIZE_4KB, + MT_MEMORY | MT_RW | MT_NS); + if (ret == 0) { + debugfs_initialized = true; + smc_ret = SMC_OK; + smc_resp = 0; + } + } + break; + + case VERSION: + smc_ret = SMC_OK; + smc_resp = DEBUGFS_VERSION; + break; + + case MOUNT: + ret = mount(parms.mount.srv, + parms.mount.where, + parms.mount.spec); + if (ret == 0) { + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + case OPEN: + ret = open(parms.open.fname, arg2); + if (ret >= 0) { + smc_ret = SMC_OK; + smc_resp = ret; + } + break; + + case CLOSE: + ret = close(arg2); + if (ret == 0) { + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + case READ: + ret = read(arg2, DEBUGFS_SHARED_BUF_VIRT, arg3); + if (ret >= 0) { + smc_ret = SMC_OK; + smc_resp = ret; + } + break; + + case SEEK: + ret = seek(arg2, arg3, arg4); + if (ret == 0) { + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + case BIND: + ret = bind(parms.bind.oldpath, parms.bind.newpath); + if (ret == 0) { + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + case STAT: + ret = stat(parms.stat.path, &parms.stat.dir); + if (ret == 0) { + memcpy((void *)DEBUGFS_SHARED_BUF_VIRT, &parms, + sizeof(union debugfs_parms)); + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + /* Not implemented */ + case CREATE: + /* Intentional fall-through */ + + /* Not implemented */ + case WRITE: + /* Intentional fall-through */ + + default: + smc_ret = SMC_UNK; + smc_resp = 0; + } + + spin_unlock(&debugfs_access_lock); + + SMC_RET2(handle, smc_ret, smc_resp); + + /* Not reached */ + return smc_ret; +} + +int debugfs_smc_setup(void) +{ + debugfs_initialized = false; + debugfs_access_lock.lock = 0; + + return 0; +} diff --git a/arm-trusted-firmware/lib/debugfs/dev.c b/arm-trusted-firmware/lib/debugfs/dev.c new file mode 100644 index 0000000..2fc1d40 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/dev.c @@ -0,0 +1,853 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "dev.h" + +#define NR_MOUNT_POINTS 4 + +struct mount_point { + chan_t *new; + chan_t *old; +}; + +/* This array contains all the available channels of the filesystem. + * A file descriptor is the index of a specific channel in this array. + */ +static chan_t fdset[NR_CHANS]; + +/* This array contains all the available mount points of the filesystem. */ +static struct mount_point mount_points[NR_MOUNT_POINTS]; + +/* This variable stores the channel associated to the root directory. */ +static chan_t slash_channel; + +/* This function creates a channel from a device index and registers + * it to fdset. + */ +static chan_t *create_new_channel(unsigned char index) +{ + chan_t *channel = NULL; + int i; + + for (i = 0; i < NR_CHANS; i++) { + if (fdset[i].index == NODEV) { + channel = &fdset[i]; + channel->index = index; + break; + } + } + + return channel; +} + +/******************************************************************************* + * This function returns a pointer to an existing channel in fdset from a file + * descriptor. + ******************************************************************************/ +static chan_t *fd_to_channel(int fd) +{ + if ((fd < 0) || (fd >= NR_CHANS) || (fdset[fd].index == NODEV)) { + return NULL; + } + + return &fdset[fd]; +} + +/******************************************************************************* + * This function returns a file descriptor from a channel. + * The caller must be sure that the channel is registered in fdset. + ******************************************************************************/ +static int channel_to_fd(chan_t *channel) +{ + return (channel == NULL) ? -1 : (channel - fdset); +} + +/******************************************************************************* + * This function checks the validity of a mode. + ******************************************************************************/ +static bool is_valid_mode(int mode) +{ + if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR))) { + return false; + } + if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR))) { + return false; + } + if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE))) { + return false; + } + + return true; +} + +/******************************************************************************* + * This function extracts the next part of the given path contained and puts it + * in token. It returns a pointer to the remainder of the path. + ******************************************************************************/ +static const char *next(const char *path, char *token) +{ + int index; + const char *cursor; + + while (*path == '/') { + ++path; + } + + index = 0; + cursor = path; + if (*path != '\0') { + while (*cursor != '/' && *cursor != '\0') { + if (index == NAMELEN) { + return NULL; + } + token[index++] = *cursor++; + } + } + token[index] = '\0'; + + return cursor; +} + +/******************************************************************************* + * This function returns the driver index in devtab of the driver + * identified by id. + ******************************************************************************/ +static int get_device_index(int id) +{ + int index; + dev_t * const *dp; + + for (index = 0, dp = devtab; *dp && (*dp)->id != id; ++dp) { + index++; + } + + if (*dp == NULL) { + return -1; + } + + return index; +} + +/******************************************************************************* + * This function clears a given channel fields + ******************************************************************************/ +static void channel_clear(chan_t *channel) +{ + channel->offset = 0; + channel->qid = 0; + channel->index = NODEV; + channel->dev = 0; + channel->mode = 0; +} + +/******************************************************************************* + * This function closes the channel pointed to by c. + ******************************************************************************/ +void channel_close(chan_t *channel) +{ + if (channel != NULL) { + channel_clear(channel); + } +} + +/******************************************************************************* + * This function copies data from src to dst after applying the offset of the + * channel c. nbytes bytes are expected to be copied unless the data goes over + * dst + len. + * It returns the actual number of bytes that were copied. + ******************************************************************************/ +int buf_to_channel(chan_t *channel, void *dst, void *src, int nbytes, long len) +{ + const char *addr = src; + + if ((channel == NULL) || (dst == NULL) || (src == NULL)) { + return 0; + } + + if (channel->offset >= len) { + return 0; + } + + if ((channel->offset + nbytes) > len) { + nbytes = len - channel->offset; + } + + memcpy(dst, addr + channel->offset, nbytes); + + channel->offset += nbytes; + + return nbytes; +} + +/******************************************************************************* + * This function checks whether a channel (identified by its device index and + * qid) is registered as a mount point. + * Returns a pointer to the channel it is mounted to when found, NULL otherwise. + ******************************************************************************/ +static chan_t *mount_point_to_channel(int index, qid_t qid) +{ + chan_t *channel; + struct mount_point *mp; + + for (mp = mount_points; mp < &mount_points[NR_MOUNT_POINTS]; mp++) { + channel = mp->new; + if (channel == NULL) { + continue; + } + + if ((channel->index == index) && (channel->qid == qid)) { + return mp->old; + } + } + + return NULL; +} + +/******************************************************************************* + * This function calls the attach function of the driver identified by id. + ******************************************************************************/ +chan_t *attach(int id, int dev) +{ + /* Get the devtab index for the driver identified by id */ + int index = get_device_index(id); + + if (index < 0) { + return NULL; + } + + return devtab[index]->attach(id, dev); +} + +/******************************************************************************* + * This function is the default implementation of the driver attach function. + * It creates a new channel and returns a pointer to it. + ******************************************************************************/ +chan_t *devattach(int id, int dev) +{ + chan_t *channel; + int index; + + index = get_device_index(id); + if (index < 0) { + return NULL; + } + + channel = create_new_channel(index); + if (channel == NULL) { + return NULL; + } + + channel->dev = dev; + channel->qid = CHDIR; + + return channel; +} + +/******************************************************************************* + * This function returns a channel given a path. + * It goes through the filesystem, from the root namespace ('/') or from a + * device namespace ('#'), switching channel on mount points. + ******************************************************************************/ +chan_t *path_to_channel(const char *path, int mode) +{ + int i, n; + const char *path_next; + chan_t *mnt, *channel; + char elem[NAMELEN]; + + if (path == NULL) { + return NULL; + } + + switch (path[0]) { + case '/': + channel = clone(&slash_channel, NULL); + path_next = path; + break; + case '#': + path_next = next(path + 1, elem); + if (path_next == NULL) { + goto noent; + } + + n = 0; + for (i = 1; (elem[i] >= '0') && (elem[i] <= '9'); i++) { + n += elem[i] - '0'; + } + + if (elem[i] != '\0') { + goto noent; + } + + channel = attach(elem[0], n); + break; + default: + return NULL; + } + + if (channel == NULL) { + return NULL; + } + + for (path_next = next(path_next, elem); *elem; + path_next = next(path_next, elem)) { + if ((channel->qid & CHDIR) == 0) { + goto notfound; + } + + if (devtab[channel->index]->walk(channel, elem) < 0) { + channel_close(channel); + goto notfound; + } + + mnt = mount_point_to_channel(channel->index, channel->qid); + if (mnt != NULL) { + clone(mnt, channel); + } + } + + if (path_next == NULL) { + goto notfound; + } + + /* TODO: check mode */ + return channel; + +notfound: + channel_close(channel); +noent: + return NULL; +} + +/******************************************************************************* + * This function calls the clone function of the driver associated to the + * channel c. + ******************************************************************************/ +chan_t *clone(chan_t *c, chan_t *nc) +{ + if (c->index == NODEV) { + return NULL; + } + + return devtab[c->index]->clone(c, nc); +} + +/******************************************************************************* + * This function is the default implementation of the driver clone function. + * It creates a new channel and returns a pointer to it. + * It clones channel into new_channel. + ******************************************************************************/ +chan_t *devclone(chan_t *channel, chan_t *new_channel) +{ + if (channel == NULL) { + return NULL; + } + + if (new_channel == NULL) { + new_channel = create_new_channel(channel->index); + if (new_channel == NULL) { + return NULL; + } + } + + new_channel->qid = channel->qid; + new_channel->dev = channel->dev; + new_channel->mode = channel->mode; + new_channel->offset = channel->offset; + new_channel->index = channel->index; + + return new_channel; +} + +/******************************************************************************* + * This function is the default implementation of the driver walk function. + * It goes through all the elements of tab using the gen function until a match + * is found with name. + * If a match is found, it copies the qid of the new directory. + ******************************************************************************/ +int devwalk(chan_t *channel, const char *name, const dirtab_t *tab, + int ntab, devgen_t *gen) +{ + int i; + dir_t dir; + + if ((channel == NULL) || (name == NULL) || (gen == NULL)) { + return -1; + } + + if ((name[0] == '.') && (name[1] == '\0')) { + return 1; + } + + for (i = 0; ; i++) { + switch ((*gen)(channel, tab, ntab, i, &dir)) { + case 0: + /* Intentional fall-through */ + case -1: + return -1; + case 1: + if (strncmp(name, dir.name, NAMELEN) != 0) { + continue; + } + channel->qid = dir.qid; + return 1; + } + } +} + +/******************************************************************************* + * This is a helper function which exposes the content of a directory, element + * by element. It is meant to be called until the end of the directory is + * reached or an error occurs. + * It returns -1 on error, 0 on end of directory and 1 when a new file is found. + ******************************************************************************/ +int dirread(chan_t *channel, dir_t *dir, const dirtab_t *tab, + int ntab, devgen_t *gen) +{ + int i, ret; + + if ((channel == NULL) || (dir == NULL) || (gen == NULL)) { + return -1; + } + + i = channel->offset/sizeof(dir_t); + ret = (*gen)(channel, tab, ntab, i, dir); + if (ret == 1) { + channel->offset += sizeof(dir_t); + } + + return ret; +} + +/******************************************************************************* + * This function sets the elements of dir. + ******************************************************************************/ +void make_dir_entry(chan_t *channel, dir_t *dir, + const char *name, long length, qid_t qid, unsigned int mode) +{ + if ((channel == NULL) || (dir == NULL) || (name == NULL)) { + return; + } + + strlcpy(dir->name, name, sizeof(dir->name)); + dir->length = length; + dir->qid = qid; + dir->mode = mode; + + if ((qid & CHDIR) != 0) { + dir->mode |= O_DIR; + } + + dir->index = channel->index; + dir->dev = channel->dev; +} + +/******************************************************************************* + * This function is the default implementation of the internal driver gen + * function. + * It copies and formats the information of the nth element of tab into dir. + ******************************************************************************/ +int devgen(chan_t *channel, const dirtab_t *tab, int ntab, int n, dir_t *dir) +{ + const dirtab_t *dp; + + if ((channel == NULL) || (dir == NULL) || (tab == NULL) || + (n >= ntab)) { + return 0; + } + + dp = &tab[n]; + make_dir_entry(channel, dir, dp->name, dp->length, dp->qid, dp->perm); + return 1; +} + +/******************************************************************************* + * This function returns a file descriptor identifying the channel associated to + * the given path. + ******************************************************************************/ +int open(const char *path, int mode) +{ + chan_t *channel; + + if (path == NULL) { + return -1; + } + + if (is_valid_mode(mode) == false) { + return -1; + } + + channel = path_to_channel(path, mode); + + return channel_to_fd(channel); +} + +/******************************************************************************* + * This function closes the channel identified by the file descriptor fd. + ******************************************************************************/ +int close(int fd) +{ + chan_t *channel; + + channel = fd_to_channel(fd); + if (channel == NULL) { + return -1; + } + + channel_close(channel); + return 0; +} + +/******************************************************************************* + * This function is the default implementation of the driver stat function. + * It goes through all the elements of tab using the gen function until a match + * is found with file. + * If a match is found, dir contains the information file. + ******************************************************************************/ +int devstat(chan_t *dirc, const char *file, dir_t *dir, + const dirtab_t *tab, int ntab, devgen_t *gen) +{ + int i, r = 0; + chan_t *c, *mnt; + + if ((dirc == NULL) || (dir == NULL) || (gen == NULL)) { + return -1; + } + + c = path_to_channel(file, O_STAT); + if (c == NULL) { + return -1; + } + + for (i = 0; ; i++) { + switch ((*gen)(dirc, tab, ntab, i, dir)) { + case 0: + /* Intentional fall-through */ + case -1: + r = -1; + goto leave; + case 1: + mnt = mount_point_to_channel(dir->index, dir->qid); + if (mnt != NULL) { + dir->qid = mnt->qid; + dir->index = mnt->index; + } + + if ((dir->qid != c->qid) || (dir->index != c->index)) { + continue; + } + + goto leave; + } + } + +leave: + channel_close(c); + return r; +} + +/******************************************************************************* + * This function calls the stat function of the driver associated to the parent + * directory of the file in path. + * The result is stored in dir. + ******************************************************************************/ +int stat(const char *path, dir_t *dir) +{ + int r; + size_t len; + chan_t *channel; + char *p, dirname[PATHLEN]; + + if ((path == NULL) || (dir == NULL)) { + return -1; + } + + len = strlen(path); + if ((len + 1) > sizeof(dirname)) { + return -1; + } + + memcpy(dirname, path, len); + for (p = dirname + len; p > dirname; --p) { + if (*p != '/') { + break; + } + } + + p = memrchr(dirname, '/', p - dirname); + if (p == NULL) { + return -1; + } + + dirname[p - dirname + 1] = '\0'; + + channel = path_to_channel(dirname, O_STAT); + if (channel == NULL) { + return -1; + } + + r = devtab[channel->index]->stat(channel, path, dir); + channel_close(channel); + + return r; +} + +/******************************************************************************* + * This function calls the read function of the driver associated to fd. + * It fills buf with at most n bytes. + * It returns the number of bytes that were actually read. + ******************************************************************************/ +int read(int fd, void *buf, int n) +{ + chan_t *channel; + + if (buf == NULL) { + return -1; + } + + channel = fd_to_channel(fd); + if (channel == NULL) { + return -1; + } + + if (((channel->qid & CHDIR) != 0) && (n < sizeof(dir_t))) { + return -1; + } + + return devtab[channel->index]->read(channel, buf, n); +} + +/******************************************************************************* + * This function calls the write function of the driver associated to fd. + * It writes at most n bytes of buf. + * It returns the number of bytes that were actually written. + ******************************************************************************/ +int write(int fd, void *buf, int n) +{ + chan_t *channel; + + if (buf == NULL) { + return -1; + } + + channel = fd_to_channel(fd); + if (channel == NULL) { + return -1; + } + + if ((channel->qid & CHDIR) != 0) { + return -1; + } + + return devtab[channel->index]->write(channel, buf, n); +} + +/******************************************************************************* + * This function calls the seek function of the driver associated to fd. + * It applies the offset off according to the strategy whence. + ******************************************************************************/ +int seek(int fd, long off, int whence) +{ + chan_t *channel; + + channel = fd_to_channel(fd); + if (channel == NULL) { + return -1; + } + + if ((channel->qid & CHDIR) != 0) { + return -1; + } + + return devtab[channel->index]->seek(channel, off, whence); +} + +/******************************************************************************* + * This function is the default error implementation of the driver mount + * function. + ******************************************************************************/ +chan_t *deverrmount(chan_t *channel, const char *spec) +{ + return NULL; +} + +/******************************************************************************* + * This function is the default error implementation of the driver write + * function. + ******************************************************************************/ +int deverrwrite(chan_t *channel, void *buf, int n) +{ + return -1; +} + +/******************************************************************************* + * This function is the default error implementation of the driver seek + * function. + ******************************************************************************/ +int deverrseek(chan_t *channel, long off, int whence) +{ + return -1; +} + +/******************************************************************************* + * This function is the default implementation of the driver seek function. + * It applies the offset off according to the strategy whence to the channel c. + ******************************************************************************/ +int devseek(chan_t *channel, long off, int whence) +{ + switch (whence) { + case KSEEK_SET: + channel->offset = off; + break; + case KSEEK_CUR: + channel->offset += off; + break; + case KSEEK_END: + /* Not implemented */ + return -1; + } + + return 0; +} + +/******************************************************************************* + * This function registers the channel associated to the path new as a mount + * point for the channel c. + ******************************************************************************/ +static int add_mount_point(chan_t *channel, const char *new) +{ + int i; + chan_t *cn; + struct mount_point *mp; + + if (new == NULL) { + goto err0; + } + + cn = path_to_channel(new, O_READ); + if (cn == NULL) { + goto err0; + } + + if ((cn->qid & CHDIR) == 0) { + goto err1; + } + + for (i = NR_MOUNT_POINTS - 1; i >= 0; i--) { + mp = &mount_points[i]; + if (mp->new == NULL) { + break; + } + } + + if (i < 0) { + goto err1; + } + + mp->new = cn; + mp->old = channel; + + return 0; + +err1: + channel_close(cn); +err0: + return -1; +} + +/******************************************************************************* + * This function registers the path new as a mount point for the path old. + ******************************************************************************/ +int bind(const char *old, const char *new) +{ + chan_t *channel; + + channel = path_to_channel(old, O_BIND); + if (channel == NULL) { + return -1; + } + + if (add_mount_point(channel, new) < 0) { + channel_close(channel); + return -1; + } + + return 0; +} + +/******************************************************************************* + * This function calls the mount function of the driver associated to the path + * srv. + * It mounts the path srv on the path where. + ******************************************************************************/ +int mount(const char *srv, const char *where, const char *spec) +{ + chan_t *channel, *mount_point_chan; + int ret; + + channel = path_to_channel(srv, O_RDWR); + if (channel == NULL) { + goto err0; + } + + mount_point_chan = devtab[channel->index]->mount(channel, spec); + if (mount_point_chan == NULL) { + goto err1; + } + + ret = add_mount_point(mount_point_chan, where); + if (ret < 0) { + goto err2; + } + + channel_close(channel); + + return 0; + +err2: + channel_close(mount_point_chan); +err1: + channel_close(channel); +err0: + return -1; +} + +/******************************************************************************* + * This function initializes the device environment. + * It creates the '/' channel. + * It links the device drivers to the physical drivers. + ******************************************************************************/ +void debugfs_init(void) +{ + chan_t *channel, *cloned_channel; + + for (channel = fdset; channel < &fdset[NR_CHANS]; channel++) { + channel_clear(channel); + } + + channel = devattach('/', 0); + if (channel == NULL) { + panic(); + } + + cloned_channel = clone(channel, &slash_channel); + if (cloned_channel == NULL) { + panic(); + } + + channel_close(channel); + devlink(); +} + +__dead2 void devpanic(const char *cause) +{ + panic(); +} diff --git a/arm-trusted-firmware/lib/debugfs/dev.h b/arm-trusted-firmware/lib/debugfs/dev.h new file mode 100644 index 0000000..c142651 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/dev.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEV_H +#define DEV_H + +#include +#include +#include + +/* FIXME: need configurability */ +#define NR_CHANS 10 +#define NR_CONSS 1 +#define NR_BINDS 4 +#define NR_FILES 18 + +#define NODEV 255 +#define CHDIR (1 << 15) + +#define SYNCDEV 0 +#define SYNCALL 1 + +typedef struct dev dev_t; +typedef struct chan chan_t; +typedef struct dirtab dirtab_t; +typedef int devgen_t(chan_t *, const dirtab_t *, int, int, dir_t *); +typedef struct attr attr_t; + +enum { + DEV_ROOT_QROOT, + DEV_ROOT_QDEV, + DEV_ROOT_QFIP, + DEV_ROOT_QBLOBS, + DEV_ROOT_QBLOBCTL, + DEV_ROOT_QPSCI +}; + +/******************************************************************************* + * This structure contains the necessary information to represent a directory + * of the filesystem. + ******************************************************************************/ +struct dirtab { + char name[NAMELEN]; + qid_t qid; + long length; + unsigned char perm; + void *data; +}; + +/******************************************************************************* + * This structure defines the interface of device drivers. + * Each driver must implement a subset of those functions. + * It is possible to redirect to default implementations defined in dev.c. + ******************************************************************************/ +/* FIXME: comments for the callbacks */ +struct dev { + char id; + int (*stat)(chan_t *c, const char *file, dir_t *dir); + int (*walk)(chan_t *c, const char *name); + int (*read)(chan_t *c, void *buf, int n); + int (*write)(chan_t *c, void *buf, int n); + int (*seek)(chan_t *c, long off, int whence); + chan_t *(*clone)(chan_t *c, chan_t *nc); + chan_t *(*attach)(int id, int dev); + chan_t *(*mount)(chan_t *c, const char *spec); +}; + +/******************************************************************************* + * This structure defines the channel structure. + * A channel is a handle on an element of the filesystem. + ******************************************************************************/ +struct chan { + long offset; + qid_t qid; + unsigned char index; /* device index in devtab */ + unsigned char dev; + unsigned char mode; +}; + +/******************************************************************************* + * This structure defines an abstract argument passed to physical drivers from + * the configuration file. + ******************************************************************************/ +struct attr { + char *key; + char *value; +}; + +chan_t *path_to_channel(const char *path, int mode); +chan_t *clone(chan_t *c, chan_t *nc); +chan_t *attach(int id, int dev); +void channel_close(chan_t *c); +int buf_to_channel(chan_t *c, void *dst, void *src, int nbytes, long len); +int dirread(chan_t *c, dir_t *dir, const dirtab_t *tab, + int ntab, devgen_t *gen); +void make_dir_entry(chan_t *c, dir_t *dir, const char *name, long length, + qid_t qid, unsigned int mode); +void devlink(void); + +chan_t *devattach(int id, int dev); +int devseek(chan_t *c, long off, int whence); +chan_t *devclone(chan_t *c, chan_t *nc); +int devgen(chan_t *c, const dirtab_t *tab, int ntab, int n, dir_t *dir); +int devwalk(chan_t *c, const char *name, const dirtab_t *tab, int ntab, + devgen_t *gen); +int devstat(chan_t *dirc, const char *file, dir_t *dir, + const dirtab_t *tab, int ntab, devgen_t *gen); + +chan_t *deverrmount(chan_t *c, const char *spec); +int deverrwrite(chan_t *c, void *buf, int n); +int deverrseek(chan_t *c, long off, int whence); + +extern dev_t *const devtab[]; + +void __dead2 devpanic(const char *cause); + +#endif /* DEV_H */ diff --git a/arm-trusted-firmware/lib/debugfs/devc.c b/arm-trusted-firmware/lib/debugfs/devc.c new file mode 100644 index 0000000..1099a85 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/devc.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +typedef struct dev dev_t; + +extern dev_t rootdevtab; +extern dev_t fipdevtab; + +dev_t *const devtab[] = { + &rootdevtab, + &fipdevtab, + 0 +}; + +void devlink(void) +{ +} diff --git a/arm-trusted-firmware/lib/debugfs/devfip.c b/arm-trusted-firmware/lib/debugfs/devfip.c new file mode 100644 index 0000000..85e6403 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/devfip.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dev.h" + +#define NR_FIPS 1 +#define STOC_HEADER (sizeof(fip_toc_header_t)) +#define STOC_ENTRY (sizeof(fip_toc_entry_t)) + +struct fipfile { + chan_t *c; + long offset[NR_FILES]; + long size[NR_FILES]; +}; + +struct fip_entry { + uuid_t uuid; + long long offset_address; + long long size; + long long flags; +}; + +struct uuidnames { + const char name[NAMELEN]; + const uuid_t uuid; +}; + +/******************************************************************************* + * This array links the FIP file names to their UUID. + * The elements are ordered according to the image number stored in + * tbbr_img_def.h, starting at index 1. + * + * TODO: this name to uuid binding will preferably be done using + * the coming Property Access Layer / Firmware CONFiguration feature. + ******************************************************************************/ +static const struct uuidnames uuidnames[] = { + {"", { {0}, {0}, {0}, 0, 0, {0} } }, + {"bl2.bin", UUID_TRUSTED_BOOT_FIRMWARE_BL2}, + {"scp-bl2.bin", UUID_SCP_FIRMWARE_SCP_BL2}, + {"bl31.bin", UUID_EL3_RUNTIME_FIRMWARE_BL31}, + {"bl32.bin", UUID_SECURE_PAYLOAD_BL32}, + {"bl33.bin", UUID_NON_TRUSTED_FIRMWARE_BL33}, + {"tb-fw.crt", UUID_TRUSTED_BOOT_FW_CERT}, + {"trstd-k.crt", UUID_TRUSTED_KEY_CERT}, + {"scp-fw-k.crt", UUID_SCP_FW_KEY_CERT}, + {"soc-fw-k.crt", UUID_SOC_FW_KEY_CERT}, + {"tos-fw-k.crt", UUID_TRUSTED_OS_FW_KEY_CERT}, + {"nt-fw-k.crt", UUID_NON_TRUSTED_FW_KEY_CERT}, + {"scp-fw-c.crt", UUID_SCP_FW_CONTENT_CERT}, + {"soc-fw-c.crt", UUID_SOC_FW_CONTENT_CERT}, + {"tos-fw-c.crt", UUID_TRUSTED_OS_FW_CONTENT_CERT}, + {"nt-fw-c.crt", UUID_NON_TRUSTED_FW_CONTENT_CERT}, + { }, + {"fwu.crt", UUID_TRUSTED_FWU_CERT}, + {"scp-bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U}, + {"bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_BL2U}, + {"ns-bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U}, + {"bl32-xtr1.bin", UUID_SECURE_PAYLOAD_BL32_EXTRA1}, + {"bl32-xtr2.bin", UUID_SECURE_PAYLOAD_BL32_EXTRA2}, + {"hw.cfg", UUID_HW_CONFIG}, + {"tb-fw.cfg", UUID_TB_FW_CONFIG}, + {"soc-fw.cfg", UUID_SOC_FW_CONFIG}, + {"tos-fw.cfg", UUID_TOS_FW_CONFIG}, + {"nt-fw.cfg", UUID_NT_FW_CONFIG}, + {"fw.cfg", UUID_FW_CONFIG}, + {"rot-k.crt", UUID_ROT_KEY_CERT}, + {"nt-k.crt", UUID_NON_TRUSTED_WORLD_KEY_CERT}, + {"sip-sp.crt", UUID_SIP_SECURE_PARTITION_CONTENT_CERT}, + {"plat-sp.crt", UUID_PLAT_SECURE_PARTITION_CONTENT_CERT} +}; + +/******************************************************************************* + * This array contains all the available FIP files. + ******************************************************************************/ +static struct fipfile archives[NR_FIPS]; + +/******************************************************************************* + * This variable stores the current number of registered FIP files. + ******************************************************************************/ +static int nfips; + +/******************************************************************************* + * This function parses the ToC of the FIP. + ******************************************************************************/ +static int get_entry(chan_t *c, struct fip_entry *entry) +{ + int n; + + n = devtab[c->index]->read(c, entry, sizeof(struct fip_entry)); + if (n <= 0) { + return n; + } + + if (n != sizeof(struct fip_entry)) { + return -1; + } + + if (entry->size == 0) { + return 0; + } + + return 1; +} + +/******************************************************************************* + * This function exposes the FIP images as files. + ******************************************************************************/ +static int fipgen(chan_t *c, const dirtab_t *tab, int ntab, int n, dir_t *dir) +{ + int i, r; + long off; + chan_t nc; + struct fip_entry entry; + struct fipfile *fip; + static const char unk[] = "unknown"; + + if (c->dev >= nfips) { + panic(); + } + + if (clone(archives[c->dev].c, &nc) == NULL) { + panic(); + } + + fip = &archives[nc.dev]; + + off = STOC_HEADER; + for (i = 0; i <= n; i++) { + if (fip->offset[i] == -1) { + return 0; + } + + if (devtab[nc.index]->seek(&nc, off, KSEEK_SET) < 0) { + return -1; + } + + r = get_entry(&nc, &entry); + if (r <= 0) { + return r; + } + + off += sizeof(entry); + } + + for (i = 1; i < NELEM(uuidnames); i++) { + if (memcmp(&uuidnames[i].uuid, + &entry.uuid, sizeof(uuid_t)) == 0) { + break; + } + } + + if (i < NELEM(uuidnames)) { + make_dir_entry(c, dir, uuidnames[i].name, + entry.size, n, O_READ); + } else { + // TODO: set name depending on uuid node value + make_dir_entry(c, dir, unk, entry.size, n, O_READ); + } + + return 1; +} + +static int fipwalk(chan_t *c, const char *name) +{ + return devwalk(c, name, NULL, 0, fipgen); +} + +static int fipstat(chan_t *c, const char *file, dir_t *dir) +{ + return devstat(c, file, dir, NULL, 0, fipgen); +} + +/******************************************************************************* + * This function copies at most n bytes of the FIP image referred by c into + * buf. + ******************************************************************************/ +static int fipread(chan_t *c, void *buf, int n) +{ + long off; + chan_t cs; + struct fipfile *fip; + long size; + + /* Only makes sense when using debug language */ + assert(c->qid != CHDIR); + + if ((c->dev >= nfips) || ((c->qid & CHDIR) != 0)) { + panic(); + } + + fip = &archives[c->dev]; + + if ((c->qid >= NR_FILES) || (fip->offset[c->qid] < 0)) { + panic(); + } + + if (clone(fip->c, &cs) == NULL) { + panic(); + } + + size = fip->size[c->qid]; + if (c->offset >= size) { + return 0; + } + + if (n < 0) { + return -1; + } + + if (n > (size - c->offset)) { + n = size - c->offset; + } + + off = fip->offset[c->qid] + c->offset; + if (devtab[cs.index]->seek(&cs, off, KSEEK_SET) < 0) { + return -1; + } + + n = devtab[cs.index]->read(&cs, buf, n); + if (n > 0) { + c->offset += n; + } + + return n; +} + +/******************************************************************************* + * This function parses the FIP spec and registers its images in order to + * expose them as files in the driver namespace. + * It acts as an initialization function for the FIP driver. + * It returns a pointer to the newly created channel. + ******************************************************************************/ +static chan_t *fipmount(chan_t *c, const char *spec) +{ + int r, n, t; + chan_t *cspec; + uint32_t hname; + struct fip_entry entry; + struct fipfile *fip; + dir_t dir; + + if (nfips == NR_FIPS) { + return NULL; + } + + fip = &archives[nfips]; + + for (n = 0; n < NR_FILES; n++) { + fip->offset[n] = -1; + } + + cspec = path_to_channel(spec, O_READ); + if (cspec == NULL) { + return NULL; + } + + fip->c = cspec; + + r = devtab[cspec->index]->read(cspec, &hname, sizeof(hname)); + if (r < 0) { + goto err; + } + + if ((r != sizeof(hname)) || (hname != TOC_HEADER_NAME)) { + goto err; + } + + if (stat(spec, &dir) < 0) { + goto err; + } + + t = cspec->index; + if (devtab[t]->seek(cspec, STOC_HEADER, KSEEK_SET) < 0) { + goto err; + } + + for (n = 0; n < NR_FILES; n++) { + switch (get_entry(cspec, &entry)) { + case 0: + return attach('F', nfips++); + case -1: + goto err; + default: + if ((entry.offset_address + entry.size) > dir.length) { + goto err; + } + + fip->offset[n] = entry.offset_address; + fip->size[n] = entry.size; + break; + } + } + +err: + channel_close(cspec); + return NULL; +} + +const dev_t fipdevtab = { + .id = 'F', + .stat = fipstat, + .clone = devclone, + .attach = devattach, + .walk = fipwalk, + .read = fipread, + .write = deverrwrite, + .mount = fipmount, + .seek = devseek +}; + diff --git a/arm-trusted-firmware/lib/debugfs/devroot.c b/arm-trusted-firmware/lib/debugfs/devroot.c new file mode 100644 index 0000000..9dd6c92 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/devroot.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "blobs.h" +#include "dev.h" + +/******************************************************************************* + * This array contains the directories available from the root directory. + ******************************************************************************/ +static const dirtab_t dirtab[] = { + {"dev", CHDIR | DEV_ROOT_QDEV, 0, O_READ}, + {"blobs", CHDIR | DEV_ROOT_QBLOBS, 0, O_READ}, + {"fip", CHDIR | DEV_ROOT_QFIP, 0, O_READ} +}; + +static const dirtab_t devfstab[] = { +}; + +/******************************************************************************* + * This function exposes the elements of the root directory. + * It also exposes the content of the dev and blobs directories. + ******************************************************************************/ +static int rootgen(chan_t *channel, const dirtab_t *tab, int ntab, + int n, dir_t *dir) +{ + switch (channel->qid & ~CHDIR) { + case DEV_ROOT_QROOT: + tab = dirtab; + ntab = NELEM(dirtab); + break; + case DEV_ROOT_QDEV: + tab = devfstab; + ntab = NELEM(devfstab); + break; + case DEV_ROOT_QBLOBS: + tab = blobtab; + ntab = NELEM(blobtab); + break; + default: + return 0; + } + + return devgen(channel, tab, ntab, n, dir); +} + +static int rootwalk(chan_t *channel, const char *name) +{ + return devwalk(channel, name, NULL, 0, rootgen); +} + +/******************************************************************************* + * This function copies at most n bytes from the element referred by c into buf. + ******************************************************************************/ +static int rootread(chan_t *channel, void *buf, int size) +{ + const dirtab_t *dp; + dir_t *dir; + + if ((channel->qid & CHDIR) != 0) { + if (size < sizeof(dir_t)) { + return -1; + } + + dir = buf; + return dirread(channel, dir, NULL, 0, rootgen); + } + + /* Only makes sense when using debug language */ + assert(channel->qid != DEV_ROOT_QBLOBCTL); + + dp = &blobtab[channel->qid - DEV_ROOT_QBLOBCTL]; + return buf_to_channel(channel, buf, dp->data, size, dp->length); +} + +static int rootstat(chan_t *channel, const char *file, dir_t *dir) +{ + return devstat(channel, file, dir, NULL, 0, rootgen); +} + +const dev_t rootdevtab = { + .id = '/', + .stat = rootstat, + .clone = devclone, + .attach = devattach, + .walk = rootwalk, + .read = rootread, + .write = deverrwrite, + .mount = deverrmount, + .seek = devseek +}; diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c b/arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c new file mode 100644 index 0000000..3ef378c --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2016-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 + +/******************************************************************************* + * Context management library initialisation routine. This library is used by + * runtime services to share pointers to 'cpu_context' structures for the secure + * and non-secure states. Management of the structures and their associated + * memory is not done by the context management library e.g. the PSCI service + * manages the cpu context used for entry from and exit to the non-secure state. + * The Secure payload manages the context(s) corresponding to the secure state. + * It also uses this library to get access to the non-secure + * state cpu context pointers. + ******************************************************************************/ +void cm_init(void) +{ + /* + * The context management library has only global data to initialize, but + * that will be done when the BSS is zeroed out + */ +} + +/******************************************************************************* + * The following function initializes the cpu_context 'ctx' for + * first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + * + * The security state to initialize is determined by the SECURE attribute + * of the entry_point_info. + * + * The EE and ST attributes are used to configure the endianness and secure + * timer availability for the new execution context. + * + * To prepare the register state for entry call cm_prepare_el3_exit() and + * el3_exit(). For Secure-EL1 cm_prepare_el3_exit() is equivalent to + * cm_el1_sysregs_context_restore(). + ******************************************************************************/ +void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) +{ + unsigned int security_state; + uint32_t scr, sctlr; + regs_t *reg_ctx; + + assert(ctx != NULL); + + security_state = GET_SECURITY_STATE(ep->h.attr); + + /* Clear any residual register values from the context */ + zeromem(ctx, sizeof(*ctx)); + + reg_ctx = get_regs_ctx(ctx); + + /* + * Base the context SCR on the current value, adjust for entry point + * specific requirements + */ + scr = read_scr(); + scr &= ~(SCR_NS_BIT | SCR_HCE_BIT); + + if (security_state != SECURE) + scr |= SCR_NS_BIT; + + if (security_state != SECURE) { + /* + * Set up SCTLR for the Non-secure context. + * + * SCTLR.EE: Endianness is taken from the entrypoint attributes. + * + * SCTLR.M, SCTLR.C and SCTLR.I: These fields must be zero (as + * required by PSCI specification) + * + * Set remaining SCTLR fields to their architecturally defined + * values. Some fields reset to an IMPLEMENTATION DEFINED value: + * + * SCTLR.TE: Set to zero so that exceptions to an Exception + * Level executing at PL1 are taken to A32 state. + * + * SCTLR.V: Set to zero to select the normal exception vectors + * with base address held in VBAR. + */ + assert(((ep->spsr >> SPSR_E_SHIFT) & SPSR_E_MASK) == + (EP_GET_EE(ep->h.attr) >> EP_EE_SHIFT)); + + sctlr = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0U; + sctlr |= (SCTLR_RESET_VAL & ~(SCTLR_TE_BIT | SCTLR_V_BIT)); + write_ctx_reg(reg_ctx, CTX_NS_SCTLR, sctlr); + } + + /* + * The target exception level is based on the spsr mode requested. If + * execution is requested to hyp mode, HVC is enabled via SCR.HCE. + */ + if (GET_M32(ep->spsr) == MODE32_hyp) + scr |= SCR_HCE_BIT; + + /* + * Store the initialised values for SCTLR and SCR in the cpu_context. + * The Hyp mode registers are not part of the saved context and are + * set-up in cm_prepare_el3_exit(). + */ + write_ctx_reg(reg_ctx, CTX_SCR, scr); + write_ctx_reg(reg_ctx, CTX_LR, ep->pc); + write_ctx_reg(reg_ctx, CTX_SPSR, ep->spsr); + + /* + * Store the r0-r3 value from the entrypoint into the context + * Use memcpy as we are in control of the layout of the structures + */ + memcpy((void *)reg_ctx, (void *)&ep->args, sizeof(aapcs32_params_t)); +} + +/******************************************************************************* + * Enable architecture extensions on first entry to Non-secure world. + * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise + * it is zero. + ******************************************************************************/ +static void enable_extensions_nonsecure(bool el2_unused) +{ +#if IMAGE_BL32 +#if ENABLE_AMU + amu_enable(el2_unused); +#endif + +#if ENABLE_SYS_REG_TRACE_FOR_NS + sys_reg_trace_enable(); +#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */ + +#if ENABLE_TRF_FOR_NS + trf_enable(); +#endif /* ENABLE_TRF_FOR_NS */ +#endif +} + +/******************************************************************************* + * The following function initializes the cpu_context for a CPU specified by + * its `cpu_idx` for first use, and sets the initial entrypoint state as + * specified by the entry_point_info structure. + ******************************************************************************/ +void cm_init_context_by_index(unsigned int cpu_idx, + const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr)); + cm_setup_context(ctx, ep); +} + +/******************************************************************************* + * The following function initializes the cpu_context for the current CPU + * for first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + ******************************************************************************/ +void cm_init_my_context(const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context(GET_SECURITY_STATE(ep->h.attr)); + cm_setup_context(ctx, ep); +} + +/******************************************************************************* + * Prepare the CPU system registers for first entry into secure or normal world + * + * If execution is requested to hyp mode, HSCTLR is initialized + * If execution is requested to non-secure PL1, and the CPU supports + * HYP mode then HYP mode is disabled by configuring all necessary HYP mode + * registers. + ******************************************************************************/ +void cm_prepare_el3_exit(uint32_t security_state) +{ + uint32_t hsctlr, scr; + cpu_context_t *ctx = cm_get_context(security_state); + bool el2_unused = false; + + assert(ctx != NULL); + + if (security_state == NON_SECURE) { + scr = read_ctx_reg(get_regs_ctx(ctx), CTX_SCR); + if ((scr & SCR_HCE_BIT) != 0U) { + /* Use SCTLR value to initialize HSCTLR */ + hsctlr = read_ctx_reg(get_regs_ctx(ctx), + CTX_NS_SCTLR); + hsctlr |= HSCTLR_RES1; + /* Temporarily set the NS bit to access HSCTLR */ + write_scr(read_scr() | SCR_NS_BIT); + /* + * Make sure the write to SCR is complete so that + * we can access HSCTLR + */ + isb(); + write_hsctlr(hsctlr); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); + } else if ((read_id_pfr1() & + (ID_PFR1_VIRTEXT_MASK << ID_PFR1_VIRTEXT_SHIFT)) != 0U) { + el2_unused = true; + + /* + * Set the NS bit to access NS copies of certain banked + * registers + */ + write_scr(read_scr() | SCR_NS_BIT); + isb(); + + /* + * Hyp / PL2 present but unused, need to disable safely. + * HSCTLR can be ignored in this case. + * + * Set HCR to its architectural reset value so that + * Non-secure operations do not trap to Hyp mode. + */ + write_hcr(HCR_RESET_VAL); + + /* + * Set HCPTR to its architectural reset value so that + * Non-secure access from EL1 or EL0 to trace and to + * Advanced SIMD and floating point functionality does + * not trap to Hyp mode. + */ + write_hcptr(HCPTR_RESET_VAL); + + /* + * Initialise CNTHCTL. All fields are architecturally + * UNKNOWN on reset and are set to zero except for + * field(s) listed below. + * + * CNTHCTL.PL1PCEN: Disable traps to Hyp mode of + * Non-secure EL0 and EL1 accessed to the physical + * timer registers. + * + * CNTHCTL.PL1PCTEN: Disable traps to Hyp mode of + * Non-secure EL0 and EL1 accessed to the physical + * counter registers. + */ + write_cnthctl(CNTHCTL_RESET_VAL | + PL1PCEN_BIT | PL1PCTEN_BIT); + + /* + * Initialise CNTVOFF to zero as it resets to an + * IMPLEMENTATION DEFINED value. + */ + write64_cntvoff(0); + + /* + * Set VPIDR and VMPIDR to match MIDR_EL1 and MPIDR + * respectively. + */ + write_vpidr(read_midr()); + write_vmpidr(read_mpidr()); + + /* + * Initialise VTTBR, setting all fields rather than + * relying on the hw. Some fields are architecturally + * UNKNOWN at reset. + * + * VTTBR.VMID: Set to zero which is the architecturally + * defined reset value. Even though EL1&0 stage 2 + * address translation is disabled, cache maintenance + * operations depend on the VMID. + * + * VTTBR.BADDR: Set to zero as EL1&0 stage 2 address + * translation is disabled. + */ + write64_vttbr(VTTBR_RESET_VAL & + ~((VTTBR_VMID_MASK << VTTBR_VMID_SHIFT) + | (VTTBR_BADDR_MASK << VTTBR_BADDR_SHIFT))); + + /* + * Initialise HDCR, setting all the fields rather than + * relying on hw. + * + * HDCR.HPMN: Set to value of PMCR.N which is the + * architecturally-defined reset value. + * + * HDCR.HLP: Set to one so that event counter + * overflow, that is recorded in PMOVSCLR[0-30], + * occurs on the increment that changes + * PMEVCNTR[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. + * This bit is Reserved, UNK/SBZP in ARMv7. + * + * HDCR.HPME: Set to zero to disable EL2 Event + * counters. + */ +#if (ARM_ARCH_MAJOR > 7) + write_hdcr((HDCR_RESET_VAL | HDCR_HLP_BIT | + ((read_pmcr() & PMCR_N_BITS) >> + PMCR_N_SHIFT)) & ~HDCR_HPME_BIT); +#else + write_hdcr((HDCR_RESET_VAL | + ((read_pmcr() & PMCR_N_BITS) >> + PMCR_N_SHIFT)) & ~HDCR_HPME_BIT); +#endif + /* + * Set HSTR to its architectural reset value so that + * access to system registers in the cproc=1111 + * encoding space do not trap to Hyp mode. + */ + write_hstr(HSTR_RESET_VAL); + /* + * Set CNTHP_CTL to its architectural reset value to + * disable the EL2 physical timer and prevent timer + * interrupts. Some fields are architecturally UNKNOWN + * on reset and are set to zero. + */ + write_cnthp_ctl(CNTHP_CTL_RESET_VAL); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); + } + enable_extensions_nonsecure(el2_unused); + } +} diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S b/arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S new file mode 100644 index 0000000..bdad2c1 --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl _cpu_data + .globl _cpu_data_by_index + +/* ----------------------------------------------------------------- + * cpu_data_t *_cpu_data(void) + * + * Return the cpu_data structure for the current CPU. + * ----------------------------------------------------------------- + */ +func _cpu_data + /* r12 is pushed to meet the 8 byte stack alignment requirement */ + push {r12, lr} + bl plat_my_core_pos + pop {r12, lr} + b _cpu_data_by_index +endfunc _cpu_data + +/* ----------------------------------------------------------------- + * cpu_data_t *_cpu_data_by_index(uint32_t cpu_index) + * + * Return the cpu_data structure for the CPU with given linear index + * + * This can be called without a valid stack. + * clobbers: r0, r1 + * ----------------------------------------------------------------- + */ +func _cpu_data_by_index + mov_imm r1, CPU_DATA_SIZE + mul r0, r0, r1 + ldr r1, =percpu_data + add r0, r0, r1 + bx lr +endfunc _cpu_data_by_index diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch64/context.S b/arm-trusted-firmware/lib/el3_runtime/aarch64/context.S new file mode 100644 index 0000000..c1c0612 --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch64/context.S @@ -0,0 +1,1014 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#if CTX_INCLUDE_EL2_REGS + .global el2_sysregs_context_save + .global el2_sysregs_context_restore +#endif + + .global el1_sysregs_context_save + .global el1_sysregs_context_restore +#if CTX_INCLUDE_FPREGS + .global fpregs_context_save + .global fpregs_context_restore +#endif + .global prepare_el3_entry + .global restore_gp_pmcr_pauth_regs + .global save_and_update_ptw_el1_sys_regs + .global el3_exit + +#if CTX_INCLUDE_EL2_REGS + +/* ----------------------------------------------------- + * The following function strictly follows the AArch64 + * PCS to use x9-x16 (temporary caller-saved registers) + * to save EL2 system register context. It assumes that + * 'x0' is pointing to a 'el2_sys_regs' structure where + * the register context will be saved. + * + * The following registers are not added. + * AMEVCNTVOFF0_EL2 + * AMEVCNTVOFF1_EL2 + * ICH_AP0R_EL2 + * ICH_AP1R_EL2 + * ICH_LR_EL2 + * ----------------------------------------------------- + */ +func el2_sysregs_context_save + mrs x9, actlr_el2 + mrs x10, afsr0_el2 + stp x9, x10, [x0, #CTX_ACTLR_EL2] + + mrs x11, afsr1_el2 + mrs x12, amair_el2 + stp x11, x12, [x0, #CTX_AFSR1_EL2] + + mrs x13, cnthctl_el2 + mrs x14, cntvoff_el2 + stp x13, x14, [x0, #CTX_CNTHCTL_EL2] + + mrs x15, cptr_el2 + str x15, [x0, #CTX_CPTR_EL2] + +#if CTX_INCLUDE_AARCH32_REGS + mrs x16, dbgvcr32_el2 + str x16, [x0, #CTX_DBGVCR32_EL2] +#endif + + mrs x9, elr_el2 + mrs x10, esr_el2 + stp x9, x10, [x0, #CTX_ELR_EL2] + + mrs x11, far_el2 + mrs x12, hacr_el2 + stp x11, x12, [x0, #CTX_FAR_EL2] + + mrs x13, hcr_el2 + mrs x14, hpfar_el2 + stp x13, x14, [x0, #CTX_HCR_EL2] + + mrs x15, hstr_el2 + mrs x16, ICC_SRE_EL2 + stp x15, x16, [x0, #CTX_HSTR_EL2] + + mrs x9, ICH_HCR_EL2 + mrs x10, ICH_VMCR_EL2 + stp x9, x10, [x0, #CTX_ICH_HCR_EL2] + + mrs x11, mair_el2 + mrs x12, mdcr_el2 + stp x11, x12, [x0, #CTX_MAIR_EL2] + +#if ENABLE_SPE_FOR_LOWER_ELS + mrs x13, PMSCR_EL2 + str x13, [x0, #CTX_PMSCR_EL2] +#endif + mrs x14, sctlr_el2 + str x14, [x0, #CTX_SCTLR_EL2] + + mrs x15, spsr_el2 + mrs x16, sp_el2 + stp x15, x16, [x0, #CTX_SPSR_EL2] + + mrs x9, tcr_el2 + mrs x10, tpidr_el2 + stp x9, x10, [x0, #CTX_TCR_EL2] + + mrs x11, ttbr0_el2 + mrs x12, vbar_el2 + stp x11, x12, [x0, #CTX_TTBR0_EL2] + + mrs x13, vmpidr_el2 + mrs x14, vpidr_el2 + stp x13, x14, [x0, #CTX_VMPIDR_EL2] + + mrs x15, vtcr_el2 + mrs x16, vttbr_el2 + stp x15, x16, [x0, #CTX_VTCR_EL2] + +#if CTX_INCLUDE_MTE_REGS + mrs x9, TFSR_EL2 + str x9, [x0, #CTX_TFSR_EL2] +#endif + +#if ENABLE_MPAM_FOR_LOWER_ELS + mrs x10, MPAM2_EL2 + str x10, [x0, #CTX_MPAM2_EL2] + + mrs x11, MPAMHCR_EL2 + mrs x12, MPAMVPM0_EL2 + stp x11, x12, [x0, #CTX_MPAMHCR_EL2] + + mrs x13, MPAMVPM1_EL2 + mrs x14, MPAMVPM2_EL2 + stp x13, x14, [x0, #CTX_MPAMVPM1_EL2] + + mrs x15, MPAMVPM3_EL2 + mrs x16, MPAMVPM4_EL2 + stp x15, x16, [x0, #CTX_MPAMVPM3_EL2] + + mrs x9, MPAMVPM5_EL2 + mrs x10, MPAMVPM6_EL2 + stp x9, x10, [x0, #CTX_MPAMVPM5_EL2] + + mrs x11, MPAMVPM7_EL2 + mrs x12, MPAMVPMV_EL2 + stp x11, x12, [x0, #CTX_MPAMVPM7_EL2] +#endif + +#if ENABLE_FEAT_FGT + mrs x13, HDFGRTR_EL2 +#if ENABLE_FEAT_AMUv1 + mrs x14, HAFGRTR_EL2 + stp x13, x14, [x0, #CTX_HDFGRTR_EL2] +#else + str x13, [x0, #CTX_HDFGRTR_EL2] +#endif + mrs x15, HDFGWTR_EL2 + mrs x16, HFGITR_EL2 + stp x15, x16, [x0, #CTX_HDFGWTR_EL2] + + mrs x9, HFGRTR_EL2 + mrs x10, HFGWTR_EL2 + stp x9, x10, [x0, #CTX_HFGRTR_EL2] +#endif + +#if ENABLE_FEAT_ECV + mrs x11, CNTPOFF_EL2 + str x11, [x0, #CTX_CNTPOFF_EL2] +#endif + +#if ARM_ARCH_AT_LEAST(8, 4) + mrs x12, contextidr_el2 + str x12, [x0, #CTX_CONTEXTIDR_EL2] + +#if CTX_INCLUDE_AARCH32_REGS + mrs x13, sder32_el2 + str x13, [x0, #CTX_SDER32_EL2] +#endif + mrs x14, ttbr1_el2 + mrs x15, vdisr_el2 + stp x14, x15, [x0, #CTX_TTBR1_EL2] + +#if CTX_INCLUDE_NEVE_REGS + mrs x16, vncr_el2 + str x16, [x0, #CTX_VNCR_EL2] +#endif + + mrs x9, vsesr_el2 + mrs x10, vstcr_el2 + stp x9, x10, [x0, #CTX_VSESR_EL2] + + mrs x11, vsttbr_el2 + mrs x12, TRFCR_EL2 + stp x11, x12, [x0, #CTX_VSTTBR_EL2] +#endif + +#if ARM_ARCH_AT_LEAST(8, 5) + mrs x13, scxtnum_el2 + str x13, [x0, #CTX_SCXTNUM_EL2] +#endif + +#if ENABLE_FEAT_HCX + mrs x14, hcrx_el2 + str x14, [x0, #CTX_HCRX_EL2] +#endif + + ret +endfunc el2_sysregs_context_save + + +/* ----------------------------------------------------- + * The following function strictly follows the AArch64 + * PCS to use x9-x16 (temporary caller-saved registers) + * to restore EL2 system register context. It assumes + * that 'x0' is pointing to a 'el2_sys_regs' structure + * from where the register context will be restored + + * The following registers are not restored + * AMEVCNTVOFF0_EL2 + * AMEVCNTVOFF1_EL2 + * ICH_AP0R_EL2 + * ICH_AP1R_EL2 + * ICH_LR_EL2 + * ----------------------------------------------------- + */ +func el2_sysregs_context_restore + ldp x9, x10, [x0, #CTX_ACTLR_EL2] + msr actlr_el2, x9 + msr afsr0_el2, x10 + + ldp x11, x12, [x0, #CTX_AFSR1_EL2] + msr afsr1_el2, x11 + msr amair_el2, x12 + + ldp x13, x14, [x0, #CTX_CNTHCTL_EL2] + msr cnthctl_el2, x13 + msr cntvoff_el2, x14 + + ldr x15, [x0, #CTX_CPTR_EL2] + msr cptr_el2, x15 + +#if CTX_INCLUDE_AARCH32_REGS + ldr x16, [x0, #CTX_DBGVCR32_EL2] + msr dbgvcr32_el2, x16 +#endif + + ldp x9, x10, [x0, #CTX_ELR_EL2] + msr elr_el2, x9 + msr esr_el2, x10 + + ldp x11, x12, [x0, #CTX_FAR_EL2] + msr far_el2, x11 + msr hacr_el2, x12 + + ldp x13, x14, [x0, #CTX_HCR_EL2] + msr hcr_el2, x13 + msr hpfar_el2, x14 + + ldp x15, x16, [x0, #CTX_HSTR_EL2] + msr hstr_el2, x15 + msr ICC_SRE_EL2, x16 + + ldp x9, x10, [x0, #CTX_ICH_HCR_EL2] + msr ICH_HCR_EL2, x9 + msr ICH_VMCR_EL2, x10 + + ldp x11, x12, [x0, #CTX_MAIR_EL2] + msr mair_el2, x11 + msr mdcr_el2, x12 + +#if ENABLE_SPE_FOR_LOWER_ELS + ldr x13, [x0, #CTX_PMSCR_EL2] + msr PMSCR_EL2, x13 +#endif + ldr x14, [x0, #CTX_SCTLR_EL2] + msr sctlr_el2, x14 + + ldp x15, x16, [x0, #CTX_SPSR_EL2] + msr spsr_el2, x15 + msr sp_el2, x16 + + ldp x9, x10, [x0, #CTX_TCR_EL2] + msr tcr_el2, x9 + msr tpidr_el2, x10 + + ldp x11, x12, [x0, #CTX_TTBR0_EL2] + msr ttbr0_el2, x11 + msr vbar_el2, x12 + + ldp x13, x14, [x0, #CTX_VMPIDR_EL2] + msr vmpidr_el2, x13 + msr vpidr_el2, x14 + + ldp x15, x16, [x0, #CTX_VTCR_EL2] + msr vtcr_el2, x15 + msr vttbr_el2, x16 + +#if CTX_INCLUDE_MTE_REGS + ldr x9, [x0, #CTX_TFSR_EL2] + msr TFSR_EL2, x9 +#endif + +#if ENABLE_MPAM_FOR_LOWER_ELS + ldr x10, [x0, #CTX_MPAM2_EL2] + msr MPAM2_EL2, x10 + + ldp x11, x12, [x0, #CTX_MPAMHCR_EL2] + msr MPAMHCR_EL2, x11 + msr MPAMVPM0_EL2, x12 + + ldp x13, x14, [x0, #CTX_MPAMVPM1_EL2] + msr MPAMVPM1_EL2, x13 + msr MPAMVPM2_EL2, x14 + + ldp x15, x16, [x0, #CTX_MPAMVPM3_EL2] + msr MPAMVPM3_EL2, x15 + msr MPAMVPM4_EL2, x16 + + ldp x9, x10, [x0, #CTX_MPAMVPM5_EL2] + msr MPAMVPM5_EL2, x9 + msr MPAMVPM6_EL2, x10 + + ldp x11, x12, [x0, #CTX_MPAMVPM7_EL2] + msr MPAMVPM7_EL2, x11 + msr MPAMVPMV_EL2, x12 +#endif + +#if ENABLE_FEAT_FGT +#if ENABLE_FEAT_AMUv1 + ldp x13, x14, [x0, #CTX_HDFGRTR_EL2] + msr HAFGRTR_EL2, x14 +#else + ldr x13, [x0, #CTX_HDFGRTR_EL2] +#endif + msr HDFGRTR_EL2, x13 + + ldp x15, x16, [x0, #CTX_HDFGWTR_EL2] + msr HDFGWTR_EL2, x15 + msr HFGITR_EL2, x16 + + ldp x9, x10, [x0, #CTX_HFGRTR_EL2] + msr HFGRTR_EL2, x9 + msr HFGWTR_EL2, x10 +#endif + +#if ENABLE_FEAT_ECV + ldr x11, [x0, #CTX_CNTPOFF_EL2] + msr CNTPOFF_EL2, x11 +#endif + +#if ARM_ARCH_AT_LEAST(8, 4) + ldr x12, [x0, #CTX_CONTEXTIDR_EL2] + msr contextidr_el2, x12 + +#if CTX_INCLUDE_AARCH32_REGS + ldr x13, [x0, #CTX_SDER32_EL2] + msr sder32_el2, x13 +#endif + ldp x14, x15, [x0, #CTX_TTBR1_EL2] + msr ttbr1_el2, x14 + msr vdisr_el2, x15 + +#if CTX_INCLUDE_NEVE_REGS + ldr x16, [x0, #CTX_VNCR_EL2] + msr vncr_el2, x16 +#endif + + ldp x9, x10, [x0, #CTX_VSESR_EL2] + msr vsesr_el2, x9 + msr vstcr_el2, x10 + + ldp x11, x12, [x0, #CTX_VSTTBR_EL2] + msr vsttbr_el2, x11 + msr TRFCR_EL2, x12 +#endif + +#if ARM_ARCH_AT_LEAST(8, 5) + ldr x13, [x0, #CTX_SCXTNUM_EL2] + msr scxtnum_el2, x13 +#endif + +#if ENABLE_FEAT_HCX + ldr x14, [x0, #CTX_HCRX_EL2] + msr hcrx_el2, x14 +#endif + + ret +endfunc el2_sysregs_context_restore + +#endif /* CTX_INCLUDE_EL2_REGS */ + +/* ------------------------------------------------------------------ + * The following function strictly follows the AArch64 PCS to use + * x9-x17 (temporary caller-saved registers) to save EL1 system + * register context. It assumes that 'x0' is pointing to a + * 'el1_sys_regs' structure where the register context will be saved. + * ------------------------------------------------------------------ + */ +func el1_sysregs_context_save + + mrs x9, spsr_el1 + mrs x10, elr_el1 + stp x9, x10, [x0, #CTX_SPSR_EL1] + +#if !ERRATA_SPECULATIVE_AT + mrs x15, sctlr_el1 + mrs x16, tcr_el1 + stp x15, x16, [x0, #CTX_SCTLR_EL1] +#endif + + mrs x17, cpacr_el1 + mrs x9, csselr_el1 + stp x17, x9, [x0, #CTX_CPACR_EL1] + + mrs x10, sp_el1 + mrs x11, esr_el1 + stp x10, x11, [x0, #CTX_SP_EL1] + + mrs x12, ttbr0_el1 + mrs x13, ttbr1_el1 + stp x12, x13, [x0, #CTX_TTBR0_EL1] + + mrs x14, mair_el1 + mrs x15, amair_el1 + stp x14, x15, [x0, #CTX_MAIR_EL1] + + mrs x16, actlr_el1 + mrs x17, tpidr_el1 + stp x16, x17, [x0, #CTX_ACTLR_EL1] + + mrs x9, tpidr_el0 + mrs x10, tpidrro_el0 + stp x9, x10, [x0, #CTX_TPIDR_EL0] + + mrs x13, par_el1 + mrs x14, far_el1 + stp x13, x14, [x0, #CTX_PAR_EL1] + + mrs x15, afsr0_el1 + mrs x16, afsr1_el1 + stp x15, x16, [x0, #CTX_AFSR0_EL1] + + mrs x17, contextidr_el1 + mrs x9, vbar_el1 + stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] + + /* Save AArch32 system registers if the build has instructed so */ +#if CTX_INCLUDE_AARCH32_REGS + mrs x11, spsr_abt + mrs x12, spsr_und + stp x11, x12, [x0, #CTX_SPSR_ABT] + + mrs x13, spsr_irq + mrs x14, spsr_fiq + stp x13, x14, [x0, #CTX_SPSR_IRQ] + + mrs x15, dacr32_el2 + mrs x16, ifsr32_el2 + stp x15, x16, [x0, #CTX_DACR32_EL2] +#endif + + /* Save NS timer registers if the build has instructed so */ +#if NS_TIMER_SWITCH + mrs x10, cntp_ctl_el0 + mrs x11, cntp_cval_el0 + stp x10, x11, [x0, #CTX_CNTP_CTL_EL0] + + mrs x12, cntv_ctl_el0 + mrs x13, cntv_cval_el0 + stp x12, x13, [x0, #CTX_CNTV_CTL_EL0] + + mrs x14, cntkctl_el1 + str x14, [x0, #CTX_CNTKCTL_EL1] +#endif + + /* Save MTE system registers if the build has instructed so */ +#if CTX_INCLUDE_MTE_REGS + mrs x15, TFSRE0_EL1 + mrs x16, TFSR_EL1 + stp x15, x16, [x0, #CTX_TFSRE0_EL1] + + mrs x9, RGSR_EL1 + mrs x10, GCR_EL1 + stp x9, x10, [x0, #CTX_RGSR_EL1] +#endif + + ret +endfunc el1_sysregs_context_save + +/* ------------------------------------------------------------------ + * The following function strictly follows the AArch64 PCS to use + * x9-x17 (temporary caller-saved registers) to restore EL1 system + * register context. It assumes that 'x0' is pointing to a + * 'el1_sys_regs' structure from where the register context will be + * restored + * ------------------------------------------------------------------ + */ +func el1_sysregs_context_restore + + ldp x9, x10, [x0, #CTX_SPSR_EL1] + msr spsr_el1, x9 + msr elr_el1, x10 + +#if !ERRATA_SPECULATIVE_AT + ldp x15, x16, [x0, #CTX_SCTLR_EL1] + msr sctlr_el1, x15 + msr tcr_el1, x16 +#endif + + ldp x17, x9, [x0, #CTX_CPACR_EL1] + msr cpacr_el1, x17 + msr csselr_el1, x9 + + ldp x10, x11, [x0, #CTX_SP_EL1] + msr sp_el1, x10 + msr esr_el1, x11 + + ldp x12, x13, [x0, #CTX_TTBR0_EL1] + msr ttbr0_el1, x12 + msr ttbr1_el1, x13 + + ldp x14, x15, [x0, #CTX_MAIR_EL1] + msr mair_el1, x14 + msr amair_el1, x15 + + ldp x16, x17, [x0, #CTX_ACTLR_EL1] + msr actlr_el1, x16 + msr tpidr_el1, x17 + + ldp x9, x10, [x0, #CTX_TPIDR_EL0] + msr tpidr_el0, x9 + msr tpidrro_el0, x10 + + ldp x13, x14, [x0, #CTX_PAR_EL1] + msr par_el1, x13 + msr far_el1, x14 + + ldp x15, x16, [x0, #CTX_AFSR0_EL1] + msr afsr0_el1, x15 + msr afsr1_el1, x16 + + ldp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] + msr contextidr_el1, x17 + msr vbar_el1, x9 + + /* Restore AArch32 system registers if the build has instructed so */ +#if CTX_INCLUDE_AARCH32_REGS + ldp x11, x12, [x0, #CTX_SPSR_ABT] + msr spsr_abt, x11 + msr spsr_und, x12 + + ldp x13, x14, [x0, #CTX_SPSR_IRQ] + msr spsr_irq, x13 + msr spsr_fiq, x14 + + ldp x15, x16, [x0, #CTX_DACR32_EL2] + msr dacr32_el2, x15 + msr ifsr32_el2, x16 +#endif + /* Restore NS timer registers if the build has instructed so */ +#if NS_TIMER_SWITCH + ldp x10, x11, [x0, #CTX_CNTP_CTL_EL0] + msr cntp_ctl_el0, x10 + msr cntp_cval_el0, x11 + + ldp x12, x13, [x0, #CTX_CNTV_CTL_EL0] + msr cntv_ctl_el0, x12 + msr cntv_cval_el0, x13 + + ldr x14, [x0, #CTX_CNTKCTL_EL1] + msr cntkctl_el1, x14 +#endif + /* Restore MTE system registers if the build has instructed so */ +#if CTX_INCLUDE_MTE_REGS + ldp x11, x12, [x0, #CTX_TFSRE0_EL1] + msr TFSRE0_EL1, x11 + msr TFSR_EL1, x12 + + ldp x13, x14, [x0, #CTX_RGSR_EL1] + msr RGSR_EL1, x13 + msr GCR_EL1, x14 +#endif + + /* No explict ISB required here as ERET covers it */ + ret +endfunc el1_sysregs_context_restore + +/* ------------------------------------------------------------------ + * The following function follows the aapcs_64 strictly to use + * x9-x17 (temporary caller-saved registers according to AArch64 PCS) + * to save floating point register context. It assumes that 'x0' is + * pointing to a 'fp_regs' structure where the register context will + * be saved. + * + * Access to VFP registers will trap if CPTR_EL3.TFP is set. + * However currently we don't use VFP registers nor set traps in + * Trusted Firmware, and assume it's cleared. + * + * TODO: Revisit when VFP is used in secure world + * ------------------------------------------------------------------ + */ +#if CTX_INCLUDE_FPREGS +func fpregs_context_save + stp q0, q1, [x0, #CTX_FP_Q0] + stp q2, q3, [x0, #CTX_FP_Q2] + stp q4, q5, [x0, #CTX_FP_Q4] + stp q6, q7, [x0, #CTX_FP_Q6] + stp q8, q9, [x0, #CTX_FP_Q8] + stp q10, q11, [x0, #CTX_FP_Q10] + stp q12, q13, [x0, #CTX_FP_Q12] + stp q14, q15, [x0, #CTX_FP_Q14] + stp q16, q17, [x0, #CTX_FP_Q16] + stp q18, q19, [x0, #CTX_FP_Q18] + stp q20, q21, [x0, #CTX_FP_Q20] + stp q22, q23, [x0, #CTX_FP_Q22] + stp q24, q25, [x0, #CTX_FP_Q24] + stp q26, q27, [x0, #CTX_FP_Q26] + stp q28, q29, [x0, #CTX_FP_Q28] + stp q30, q31, [x0, #CTX_FP_Q30] + + mrs x9, fpsr + str x9, [x0, #CTX_FP_FPSR] + + mrs x10, fpcr + str x10, [x0, #CTX_FP_FPCR] + +#if CTX_INCLUDE_AARCH32_REGS + mrs x11, fpexc32_el2 + str x11, [x0, #CTX_FP_FPEXC32_EL2] +#endif + ret +endfunc fpregs_context_save + +/* ------------------------------------------------------------------ + * The following function follows the aapcs_64 strictly to use x9-x17 + * (temporary caller-saved registers according to AArch64 PCS) to + * restore floating point register context. It assumes that 'x0' is + * pointing to a 'fp_regs' structure from where the register context + * will be restored. + * + * Access to VFP registers will trap if CPTR_EL3.TFP is set. + * However currently we don't use VFP registers nor set traps in + * Trusted Firmware, and assume it's cleared. + * + * TODO: Revisit when VFP is used in secure world + * ------------------------------------------------------------------ + */ +func fpregs_context_restore + ldp q0, q1, [x0, #CTX_FP_Q0] + ldp q2, q3, [x0, #CTX_FP_Q2] + ldp q4, q5, [x0, #CTX_FP_Q4] + ldp q6, q7, [x0, #CTX_FP_Q6] + ldp q8, q9, [x0, #CTX_FP_Q8] + ldp q10, q11, [x0, #CTX_FP_Q10] + ldp q12, q13, [x0, #CTX_FP_Q12] + ldp q14, q15, [x0, #CTX_FP_Q14] + ldp q16, q17, [x0, #CTX_FP_Q16] + ldp q18, q19, [x0, #CTX_FP_Q18] + ldp q20, q21, [x0, #CTX_FP_Q20] + ldp q22, q23, [x0, #CTX_FP_Q22] + ldp q24, q25, [x0, #CTX_FP_Q24] + ldp q26, q27, [x0, #CTX_FP_Q26] + ldp q28, q29, [x0, #CTX_FP_Q28] + ldp q30, q31, [x0, #CTX_FP_Q30] + + ldr x9, [x0, #CTX_FP_FPSR] + msr fpsr, x9 + + ldr x10, [x0, #CTX_FP_FPCR] + msr fpcr, x10 + +#if CTX_INCLUDE_AARCH32_REGS + ldr x11, [x0, #CTX_FP_FPEXC32_EL2] + msr fpexc32_el2, x11 +#endif + /* + * No explict ISB required here as ERET to + * switch to secure EL1 or non-secure world + * covers it + */ + + ret +endfunc fpregs_context_restore +#endif /* CTX_INCLUDE_FPREGS */ + + /* + * Set the PSTATE bits not set when the exception was taken as + * described in the AArch64.TakeException() pseudocode function + * in ARM DDI 0487F.c page J1-7635 to a default value. + */ + .macro set_unset_pstate_bits + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL3 + */ +#if ENABLE_FEAT_DIT + mov x8, #DIT_BIT + msr DIT, x8 +#endif /* ENABLE_FEAT_DIT */ + .endm /* set_unset_pstate_bits */ + +/* ------------------------------------------------------------------ + * The following macro is used to save and restore all the general + * purpose and ARMv8.3-PAuth (if enabled) registers. + * It also checks if Secure Cycle Counter is not disabled in MDCR_EL3 + * when ARMv8.5-PMU is implemented, and if called from Non-secure + * state saves PMCR_EL0 and disables Cycle Counter. + * + * Ideally we would only save and restore the callee saved registers + * when a world switch occurs but that type of implementation is more + * complex. So currently we will always save and restore these + * registers on entry and exit of EL3. + * clobbers: x18 + * ------------------------------------------------------------------ + */ + .macro save_gp_pmcr_pauth_regs + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6] + stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8] + stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10] + stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12] + stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14] + stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16] + stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18] + stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20] + stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22] + stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24] + stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26] + stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + mrs x18, sp_el0 + str x18, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0] + + /* ---------------------------------------------------------- + * Check if earlier initialization MDCR_EL3.SCCD/MCCD to 1 + * failed, meaning that FEAT_PMUv3p5/7 is not implemented and + * PMCR_EL0 should be saved in non-secure context. + * ---------------------------------------------------------- + */ + mov_imm x10, (MDCR_SCCD_BIT | MDCR_MCCD_BIT) + mrs x9, mdcr_el3 + tst x9, x10 + bne 1f + + /* Secure Cycle Counter is not disabled */ + mrs x9, pmcr_el0 + + /* Check caller's security state */ + mrs x10, scr_el3 + tst x10, #SCR_NS_BIT + beq 2f + + /* Save PMCR_EL0 if called from Non-secure state */ + str x9, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0] + + /* Disable cycle counter when event counting is prohibited */ +2: orr x9, x9, #PMCR_EL0_DP_BIT + msr pmcr_el0, x9 + isb +1: +#if CTX_INCLUDE_PAUTH_REGS + /* ---------------------------------------------------------- + * Save the ARMv8.3-PAuth keys as they are not banked + * by exception level + * ---------------------------------------------------------- + */ + add x19, sp, #CTX_PAUTH_REGS_OFFSET + + mrs x20, APIAKeyLo_EL1 /* x21:x20 = APIAKey */ + mrs x21, APIAKeyHi_EL1 + mrs x22, APIBKeyLo_EL1 /* x23:x22 = APIBKey */ + mrs x23, APIBKeyHi_EL1 + mrs x24, APDAKeyLo_EL1 /* x25:x24 = APDAKey */ + mrs x25, APDAKeyHi_EL1 + mrs x26, APDBKeyLo_EL1 /* x27:x26 = APDBKey */ + mrs x27, APDBKeyHi_EL1 + mrs x28, APGAKeyLo_EL1 /* x29:x28 = APGAKey */ + mrs x29, APGAKeyHi_EL1 + + stp x20, x21, [x19, #CTX_PACIAKEY_LO] + stp x22, x23, [x19, #CTX_PACIBKEY_LO] + stp x24, x25, [x19, #CTX_PACDAKEY_LO] + stp x26, x27, [x19, #CTX_PACDBKEY_LO] + stp x28, x29, [x19, #CTX_PACGAKEY_LO] +#endif /* CTX_INCLUDE_PAUTH_REGS */ + .endm /* save_gp_pmcr_pauth_regs */ + +/* ----------------------------------------------------------------- + * This function saves the context and sets the PSTATE to a known + * state, preparing entry to el3. + * Save all the general purpose and ARMv8.3-PAuth (if enabled) + * registers. + * Then set any of the PSTATE bits that are not set by hardware + * according to the Aarch64.TakeException pseudocode in the Arm + * Architecture Reference Manual to a default value for EL3. + * clobbers: x17 + * ----------------------------------------------------------------- + */ +func prepare_el3_entry + save_gp_pmcr_pauth_regs + /* + * Set the PSTATE bits not described in the Aarch64.TakeException + * pseudocode to their default values. + */ + set_unset_pstate_bits + ret +endfunc prepare_el3_entry + +/* ------------------------------------------------------------------ + * This function restores ARMv8.3-PAuth (if enabled) and all general + * purpose registers except x30 from the CPU context. + * x30 register must be explicitly restored by the caller. + * ------------------------------------------------------------------ + */ +func restore_gp_pmcr_pauth_regs +#if CTX_INCLUDE_PAUTH_REGS + /* Restore the ARMv8.3 PAuth keys */ + add x10, sp, #CTX_PAUTH_REGS_OFFSET + + ldp x0, x1, [x10, #CTX_PACIAKEY_LO] /* x1:x0 = APIAKey */ + ldp x2, x3, [x10, #CTX_PACIBKEY_LO] /* x3:x2 = APIBKey */ + ldp x4, x5, [x10, #CTX_PACDAKEY_LO] /* x5:x4 = APDAKey */ + ldp x6, x7, [x10, #CTX_PACDBKEY_LO] /* x7:x6 = APDBKey */ + ldp x8, x9, [x10, #CTX_PACGAKEY_LO] /* x9:x8 = APGAKey */ + + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + msr APIBKeyLo_EL1, x2 + msr APIBKeyHi_EL1, x3 + msr APDAKeyLo_EL1, x4 + msr APDAKeyHi_EL1, x5 + msr APDBKeyLo_EL1, x6 + msr APDBKeyHi_EL1, x7 + msr APGAKeyLo_EL1, x8 + msr APGAKeyHi_EL1, x9 +#endif /* CTX_INCLUDE_PAUTH_REGS */ + + /* ---------------------------------------------------------- + * Restore PMCR_EL0 when returning to Non-secure state if + * Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented. + * ---------------------------------------------------------- + */ + mrs x0, scr_el3 + tst x0, #SCR_NS_BIT + beq 2f + + /* ---------------------------------------------------------- + * Back to Non-secure state. + * Check if earlier initialization MDCR_EL3.SCCD/MCCD to 1 + * failed, meaning that FEAT_PMUv3p5/7 is not implemented and + * PMCR_EL0 should be restored from non-secure context. + * ---------------------------------------------------------- + */ + mov_imm x1, (MDCR_SCCD_BIT | MDCR_MCCD_BIT) + mrs x0, mdcr_el3 + tst x0, x1 + bne 2f + ldr x0, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0] + msr pmcr_el0, x0 +2: + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + ldp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6] + ldp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8] + ldp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10] + ldp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12] + ldp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14] + ldp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16] + ldp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18] + ldp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20] + ldp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22] + ldp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24] + ldp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26] + ldr x28, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0] + msr sp_el0, x28 + ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + ret +endfunc restore_gp_pmcr_pauth_regs + +/* + * In case of ERRATA_SPECULATIVE_AT, save SCTLR_EL1 and TCR_EL1 + * registers and update EL1 registers to disable stage1 and stage2 + * page table walk + */ +func save_and_update_ptw_el1_sys_regs + /* ---------------------------------------------------------- + * Save only sctlr_el1 and tcr_el1 registers + * ---------------------------------------------------------- + */ + mrs x29, sctlr_el1 + str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1)] + mrs x29, tcr_el1 + str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_TCR_EL1)] + + /* ------------------------------------------------------------ + * Must follow below order in order to disable page table + * walk for lower ELs (EL1 and EL0). First step ensures that + * page table walk is disabled for stage1 and second step + * ensures that page table walker should use TCR_EL1.EPDx + * bits to perform address translation. ISB ensures that CPU + * does these 2 steps in order. + * + * 1. Update TCR_EL1.EPDx bits to disable page table walk by + * stage1. + * 2. Enable MMU bit to avoid identity mapping via stage2 + * and force TCR_EL1.EPDx to be used by the page table + * walker. + * ------------------------------------------------------------ + */ + orr x29, x29, #(TCR_EPD0_BIT) + orr x29, x29, #(TCR_EPD1_BIT) + msr tcr_el1, x29 + isb + mrs x29, sctlr_el1 + orr x29, x29, #SCTLR_M_BIT + msr sctlr_el1, x29 + isb + + ret +endfunc save_and_update_ptw_el1_sys_regs + +/* ------------------------------------------------------------------ + * This routine assumes that the SP_EL3 is pointing to a valid + * context structure from where the gp regs and other special + * registers can be retrieved. + * ------------------------------------------------------------------ + */ +func el3_exit +#if ENABLE_ASSERTIONS + /* el3_exit assumes SP_EL0 on entry */ + mrs x17, spsel + cmp x17, #MODE_SP_EL0 + ASM_ASSERT(eq) +#endif + + /* ---------------------------------------------------------- + * Save the current SP_EL0 i.e. the EL3 runtime stack which + * will be used for handling the next SMC. + * Then switch to SP_EL3. + * ---------------------------------------------------------- + */ + mov x17, sp + msr spsel, #MODE_SP_ELX + str x17, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + + /* ---------------------------------------------------------- + * Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET + * ---------------------------------------------------------- + */ + ldr x18, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + ldp x16, x17, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + msr scr_el3, x18 + msr spsr_el3, x16 + msr elr_el3, x17 + +#if IMAGE_BL31 + /* ---------------------------------------------------------- + * Restore CPTR_EL3. + * ZCR is only restored if SVE is supported and enabled. + * Synchronization is required before zcr_el3 is addressed. + * ---------------------------------------------------------- + */ + ldp x19, x20, [sp, #CTX_EL3STATE_OFFSET + CTX_CPTR_EL3] + msr cptr_el3, x19 + + ands x19, x19, #CPTR_EZ_BIT + beq sve_not_enabled + + isb + msr S3_6_C1_C2_0, x20 /* zcr_el3 */ +sve_not_enabled: +#endif + +#if IMAGE_BL31 && DYNAMIC_WORKAROUND_CVE_2018_3639 + /* ---------------------------------------------------------- + * Restore mitigation state as it was on entry to EL3 + * ---------------------------------------------------------- + */ + ldr x17, [sp, #CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_DISABLE] + cbz x17, 1f + blr x17 +1: +#endif + restore_ptw_el1_sys_regs + + /* ---------------------------------------------------------- + * Restore general purpose (including x30), PMCR_EL0 and + * ARMv8.3-PAuth registers. + * Exit EL3 via ERET to a lower exception level. + * ---------------------------------------------------------- + */ + bl restore_gp_pmcr_pauth_regs + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +#if IMAGE_BL31 && RAS_EXTENSION + /* ---------------------------------------------------------- + * Issue Error Synchronization Barrier to synchronize SErrors + * before exiting EL3. We're running with EAs unmasked, so + * any synchronized errors would be taken immediately; + * therefore no need to inspect DISR_EL1 register. + * ---------------------------------------------------------- + */ + esb +#else + dsb sy +#endif +#ifdef IMAGE_BL31 + str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3] +#endif + exception_return + +endfunc el3_exit diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c b/arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c new file mode 100644 index 0000000..c69dc95 --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c @@ -0,0 +1,878 @@ +/* + * Copyright (c) 2013-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 +#include +#include +#include +#include +#include +#include +#include +#include + +static void manage_extensions_secure(cpu_context_t *ctx); + +/******************************************************************************* + * Context management library initialisation routine. This library is used by + * runtime services to share pointers to 'cpu_context' structures for the secure + * and non-secure states. Management of the structures and their associated + * memory is not done by the context management library e.g. the PSCI service + * manages the cpu context used for entry from and exit to the non-secure state. + * The Secure payload dispatcher service manages the context(s) corresponding to + * the secure state. It also uses this library to get access to the non-secure + * state cpu context pointers. + * Lastly, this library provides the api to make SP_EL3 point to the cpu context + * which will used for programming an entry into a lower EL. The same context + * will used to save state upon exception entry from that EL. + ******************************************************************************/ +void __init cm_init(void) +{ + /* + * The context management library has only global data to intialize, but + * that will be done when the BSS is zeroed out + */ +} + +/******************************************************************************* + * The following function initializes the cpu_context 'ctx' for + * first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + * + * The security state to initialize is determined by the SECURE attribute + * of the entry_point_info. + * + * The EE and ST attributes are used to configure the endianness and secure + * timer availability for the new execution context. + * + * To prepare the register state for entry call cm_prepare_el3_exit() and + * el3_exit(). For Secure-EL1 cm_prepare_el3_exit() is equivalent to + * cm_el1_sysregs_context_restore(). + ******************************************************************************/ +void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) +{ + unsigned int security_state; + u_register_t scr_el3; + el3_state_t *state; + gp_regs_t *gp_regs; + u_register_t sctlr_elx, actlr_elx; + + assert(ctx != NULL); + + security_state = GET_SECURITY_STATE(ep->h.attr); + + /* Clear any residual register values from the context */ + zeromem(ctx, sizeof(*ctx)); + + /* + * SCR_EL3 was initialised during reset sequence in macro + * el3_arch_init_common. This code modifies the SCR_EL3 fields that + * affect the next EL. + * + * The following fields are initially set to zero and then updated to + * the required value depending on the state of the SPSR_EL3 and the + * Security state and entrypoint attributes of the next EL. + */ + scr_el3 = read_scr(); + scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT | + SCR_ST_BIT | SCR_HCE_BIT); + +#if ENABLE_RME + /* When RME support is enabled, clear the NSE bit as well. */ + scr_el3 &= ~SCR_NSE_BIT; +#endif /* ENABLE_RME */ + + /* + * SCR_NS: Set the security state of the next EL. + */ + if (security_state == NON_SECURE) { + scr_el3 |= SCR_NS_BIT; + } + +#if ENABLE_RME + /* Check for realm state if RME support enabled. */ + if (security_state == REALM) { + scr_el3 |= SCR_NS_BIT | SCR_NSE_BIT | SCR_EnSCXT_BIT; + } +#endif /* ENABLE_RME */ + + /* + * SCR_EL3.RW: Set the execution state, AArch32 or AArch64, for next + * Exception level as specified by SPSR. + */ + if (GET_RW(ep->spsr) == MODE_RW_64) { + scr_el3 |= SCR_RW_BIT; + } + /* + * SCR_EL3.ST: Traps Secure EL1 accesses to the Counter-timer Physical + * Secure timer registers to EL3, from AArch64 state only, if specified + * by the entrypoint attributes. + */ + if (EP_GET_ST(ep->h.attr) != 0U) { + scr_el3 |= SCR_ST_BIT; + } + + /* + * If FEAT_HCX is enabled, enable access to HCRX_EL2 by setting + * SCR_EL3.HXEn. + */ +#if ENABLE_FEAT_HCX + scr_el3 |= SCR_HXEn_BIT; +#endif + +#if RAS_TRAP_LOWER_EL_ERR_ACCESS + /* + * SCR_EL3.TERR: Trap Error record accesses. Accesses to the RAS ERR + * and RAS ERX registers from EL1 and EL2 are trapped to EL3. + */ + scr_el3 |= SCR_TERR_BIT; +#endif + +#if !HANDLE_EA_EL3_FIRST + /* + * SCR_EL3.EA: Do not route External Abort and SError Interrupt External + * to EL3 when executing at a lower EL. When executing at EL3, External + * Aborts are taken to EL3. + */ + scr_el3 &= ~SCR_EA_BIT; +#endif + +#if FAULT_INJECTION_SUPPORT + /* Enable fault injection from lower ELs */ + scr_el3 |= SCR_FIEN_BIT; +#endif + +#if !CTX_INCLUDE_PAUTH_REGS + /* + * If the pointer authentication registers aren't saved during world + * switches the value of the registers can be leaked from the Secure to + * the Non-secure world. To prevent this, rather than enabling pointer + * authentication everywhere, we only enable it in the Non-secure world. + * + * If the Secure world wants to use pointer authentication, + * CTX_INCLUDE_PAUTH_REGS must be set to 1. + */ + if (security_state == NON_SECURE) { + scr_el3 |= SCR_API_BIT | SCR_APK_BIT; + } +#endif /* !CTX_INCLUDE_PAUTH_REGS */ + +#if !CTX_INCLUDE_MTE_REGS || ENABLE_ASSERTIONS + /* Get Memory Tagging Extension support level */ + unsigned int mte = get_armv8_5_mte_support(); +#endif + /* + * Enable MTE support. Support is enabled unilaterally for the normal + * world, and only for the secure world when CTX_INCLUDE_MTE_REGS is + * set. + */ +#if CTX_INCLUDE_MTE_REGS + assert((mte == MTE_IMPLEMENTED_ELX) || (mte == MTE_IMPLEMENTED_ASY)); + scr_el3 |= SCR_ATA_BIT; +#else + /* + * When MTE is only implemented at EL0, it can be enabled + * across both worlds as no MTE registers are used. + */ + if ((mte == MTE_IMPLEMENTED_EL0) || + /* + * When MTE is implemented at all ELs, it can be only enabled + * in Non-Secure world without register saving. + */ + (((mte == MTE_IMPLEMENTED_ELX) || (mte == MTE_IMPLEMENTED_ASY)) && + (security_state == NON_SECURE))) { + scr_el3 |= SCR_ATA_BIT; + } +#endif /* CTX_INCLUDE_MTE_REGS */ + +#ifdef IMAGE_BL31 + /* + * SCR_EL3.IRQ, SCR_EL3.FIQ: Enable the physical FIQ and IRQ routing as + * indicated by the interrupt routing model for BL31. + * + * TODO: The interrupt routing model code is not updated for REALM + * state. Use the default values of IRQ = FIQ = 0 for REALM security + * state for now. + */ + if (security_state != REALM) { + scr_el3 |= get_scr_el3_from_routing_model(security_state); + } +#endif + + /* Save the initialized value of CPTR_EL3 register */ + write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, read_cptr_el3()); + if (security_state == SECURE) { + manage_extensions_secure(ctx); + } + + /* + * SCR_EL3.HCE: Enable HVC instructions if next execution state is + * AArch64 and next EL is EL2, or if next execution state is AArch32 and + * next mode is Hyp. + * SCR_EL3.FGTEn: Enable Fine Grained Virtualization Traps under the + * same conditions as HVC instructions and when the processor supports + * ARMv8.6-FGT. + * SCR_EL3.ECVEn: Enable Enhanced Counter Virtualization (ECV) + * CNTPOFF_EL2 register under the same conditions as HVC instructions + * and when the processor supports ECV. + */ + if (((GET_RW(ep->spsr) == MODE_RW_64) && (GET_EL(ep->spsr) == MODE_EL2)) + || ((GET_RW(ep->spsr) != MODE_RW_64) + && (GET_M32(ep->spsr) == MODE32_hyp))) { + scr_el3 |= SCR_HCE_BIT; + + if (is_armv8_6_fgt_present()) { + scr_el3 |= SCR_FGTEN_BIT; + } + + if (get_armv8_6_ecv_support() + == ID_AA64MMFR0_EL1_ECV_SELF_SYNCH) { + scr_el3 |= SCR_ECVEN_BIT; + } + } + + /* Enable S-EL2 if the next EL is EL2 and security state is secure */ + if ((security_state == SECURE) && (GET_EL(ep->spsr) == MODE_EL2)) { + if (GET_RW(ep->spsr) != MODE_RW_64) { + ERROR("S-EL2 can not be used in AArch32."); + panic(); + } + + scr_el3 |= SCR_EEL2_BIT; + } + + /* + * FEAT_AMUv1p1 virtual offset registers are only accessible from EL3 + * and EL2, when clear, this bit traps accesses from EL2 so we set it + * to 1 when EL2 is present. + */ + if (is_armv8_6_feat_amuv1p1_present() && + (el_implemented(2) != EL_IMPL_NONE)) { + scr_el3 |= SCR_AMVOFFEN_BIT; + } + + /* + * Initialise SCTLR_EL1 to the reset value corresponding to the target + * execution state setting all fields rather than relying of the hw. + * Some fields have architecturally UNKNOWN reset values and these are + * set to zero. + * + * SCTLR.EE: Endianness is taken from the entrypoint attributes. + * + * SCTLR.M, SCTLR.C and SCTLR.I: These fields must be zero (as + * required by PSCI specification) + */ + sctlr_elx = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0U; + if (GET_RW(ep->spsr) == MODE_RW_64) { + sctlr_elx |= SCTLR_EL1_RES1; + } else { + /* + * If the target execution state is AArch32 then the following + * fields need to be set. + * + * SCTRL_EL1.nTWE: Set to one so that EL0 execution of WFE + * instructions are not trapped to EL1. + * + * SCTLR_EL1.nTWI: Set to one so that EL0 execution of WFI + * instructions are not trapped to EL1. + * + * SCTLR_EL1.CP15BEN: Set to one to enable EL0 execution of the + * CP15DMB, CP15DSB, and CP15ISB instructions. + */ + sctlr_elx |= SCTLR_AARCH32_EL1_RES1 | SCTLR_CP15BEN_BIT + | SCTLR_NTWI_BIT | SCTLR_NTWE_BIT; + } + +#if ERRATA_A75_764081 + /* + * If workaround of errata 764081 for Cortex-A75 is used then set + * SCTLR_EL1.IESB to enable Implicit Error Synchronization Barrier. + */ + sctlr_elx |= SCTLR_IESB_BIT; +#endif + + /* Enable WFE trap delay in SCR_EL3 if supported and configured */ + if (is_armv8_6_twed_present()) { + uint32_t delay = plat_arm_set_twedel_scr_el3(); + + if (delay != TWED_DISABLED) { + /* Make sure delay value fits */ + assert((delay & ~SCR_TWEDEL_MASK) == 0U); + + /* Set delay in SCR_EL3 */ + scr_el3 &= ~(SCR_TWEDEL_MASK << SCR_TWEDEL_SHIFT); + scr_el3 |= ((delay & SCR_TWEDEL_MASK) + << SCR_TWEDEL_SHIFT); + + /* Enable WFE delay */ + scr_el3 |= SCR_TWEDEn_BIT; + } + } + + /* + * Store the initialised SCTLR_EL1 value in the cpu_context - SCTLR_EL2 + * and other EL2 registers are set up by cm_prepare_el3_exit() as they + * are not part of the stored cpu_context. + */ + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx); + + /* + * Base the context ACTLR_EL1 on the current value, as it is + * implementation defined. The context restore process will write + * the value from the context to the actual register and can cause + * problems for processor cores that don't expect certain bits to + * be zero. + */ + actlr_elx = read_actlr_el1(); + write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx)); + + /* + * Populate EL3 state so that we've the right context + * before doing ERET + */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); + write_ctx_reg(state, CTX_ELR_EL3, ep->pc); + write_ctx_reg(state, CTX_SPSR_EL3, ep->spsr); + + /* + * Store the X0-X7 value from the entrypoint into the context + * Use memcpy as we are in control of the layout of the structures + */ + gp_regs = get_gpregs_ctx(ctx); + memcpy(gp_regs, (void *)&ep->args, sizeof(aapcs64_params_t)); +} + +/******************************************************************************* + * Enable architecture extensions on first entry to Non-secure world. + * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise + * it is zero. + ******************************************************************************/ +static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx) +{ +#if IMAGE_BL31 +#if ENABLE_SPE_FOR_LOWER_ELS + spe_enable(el2_unused); +#endif + +#if ENABLE_AMU + amu_enable(el2_unused, ctx); +#endif + +#if ENABLE_SME_FOR_NS + /* Enable SME, SVE, and FPU/SIMD for non-secure world. */ + sme_enable(ctx); +#elif ENABLE_SVE_FOR_NS + /* Enable SVE and FPU/SIMD for non-secure world. */ + sve_enable(ctx); +#endif + +#if ENABLE_MPAM_FOR_LOWER_ELS + mpam_enable(el2_unused); +#endif + +#if ENABLE_TRBE_FOR_NS + trbe_enable(); +#endif /* ENABLE_TRBE_FOR_NS */ + +#if ENABLE_SYS_REG_TRACE_FOR_NS + sys_reg_trace_enable(ctx); +#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */ + +#if ENABLE_TRF_FOR_NS + trf_enable(); +#endif /* ENABLE_TRF_FOR_NS */ +#endif +} + +/******************************************************************************* + * Enable architecture extensions on first entry to Secure world. + ******************************************************************************/ +static void manage_extensions_secure(cpu_context_t *ctx) +{ +#if IMAGE_BL31 + #if ENABLE_SME_FOR_NS + #if ENABLE_SME_FOR_SWD + /* + * Enable SME, SVE, FPU/SIMD in secure context, secure manager must + * ensure SME, SVE, and FPU/SIMD context properly managed. + */ + sme_enable(ctx); + #else /* ENABLE_SME_FOR_SWD */ + /* + * Disable SME, SVE, FPU/SIMD in secure context so non-secure world can + * safely use the associated registers. + */ + sme_disable(ctx); + #endif /* ENABLE_SME_FOR_SWD */ + #elif ENABLE_SVE_FOR_NS + #if ENABLE_SVE_FOR_SWD + /* + * Enable SVE and FPU in secure context, secure manager must ensure that + * the SVE and FPU register contexts are properly managed. + */ + sve_enable(ctx); + #else /* ENABLE_SVE_FOR_SWD */ + /* + * Disable SVE and FPU in secure context so non-secure world can safely + * use them. + */ + sve_disable(ctx); + #endif /* ENABLE_SVE_FOR_SWD */ + #endif /* ENABLE_SVE_FOR_NS */ +#endif /* IMAGE_BL31 */ +} + +/******************************************************************************* + * The following function initializes the cpu_context for a CPU specified by + * its `cpu_idx` for first use, and sets the initial entrypoint state as + * specified by the entry_point_info structure. + ******************************************************************************/ +void cm_init_context_by_index(unsigned int cpu_idx, + const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr)); + cm_setup_context(ctx, ep); +} + +/******************************************************************************* + * The following function initializes the cpu_context for the current CPU + * for first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + ******************************************************************************/ +void cm_init_my_context(const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context(GET_SECURITY_STATE(ep->h.attr)); + cm_setup_context(ctx, ep); +} + +/******************************************************************************* + * Prepare the CPU system registers for first entry into realm, secure, or + * normal world. + * + * If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized + * If execution is requested to non-secure EL1 or svc mode, and the CPU supports + * EL2 then EL2 is disabled by configuring all necessary EL2 registers. + * For all entries, the EL1 registers are initialized from the cpu_context + ******************************************************************************/ +void cm_prepare_el3_exit(uint32_t security_state) +{ + u_register_t sctlr_elx, scr_el3, mdcr_el2; + cpu_context_t *ctx = cm_get_context(security_state); + bool el2_unused = false; + uint64_t hcr_el2 = 0U; + + assert(ctx != NULL); + + if (security_state == NON_SECURE) { + scr_el3 = read_ctx_reg(get_el3state_ctx(ctx), + CTX_SCR_EL3); + if ((scr_el3 & SCR_HCE_BIT) != 0U) { + /* Use SCTLR_EL1.EE value to initialise sctlr_el2 */ + sctlr_elx = read_ctx_reg(get_el1_sysregs_ctx(ctx), + CTX_SCTLR_EL1); + sctlr_elx &= SCTLR_EE_BIT; + sctlr_elx |= SCTLR_EL2_RES1; +#if ERRATA_A75_764081 + /* + * If workaround of errata 764081 for Cortex-A75 is used + * then set SCTLR_EL2.IESB to enable Implicit Error + * Synchronization Barrier. + */ + sctlr_elx |= SCTLR_IESB_BIT; +#endif + write_sctlr_el2(sctlr_elx); + } else if (el_implemented(2) != EL_IMPL_NONE) { + el2_unused = true; + + /* + * EL2 present but unused, need to disable safely. + * SCTLR_EL2 can be ignored in this case. + * + * Set EL2 register width appropriately: Set HCR_EL2 + * field to match SCR_EL3.RW. + */ + if ((scr_el3 & SCR_RW_BIT) != 0U) + hcr_el2 |= HCR_RW_BIT; + + /* + * For Armv8.3 pointer authentication feature, disable + * traps to EL2 when accessing key registers or using + * pointer authentication instructions from lower ELs. + */ + hcr_el2 |= (HCR_API_BIT | HCR_APK_BIT); + + write_hcr_el2(hcr_el2); + + /* + * Initialise CPTR_EL2 setting all fields rather than + * relying on the hw. All fields have architecturally + * UNKNOWN reset values. + * + * CPTR_EL2.TCPAC: Set to zero so that Non-secure EL1 + * accesses to the CPACR_EL1 or CPACR from both + * Execution states do not trap to EL2. + * + * CPTR_EL2.TTA: Set to zero so that Non-secure System + * register accesses to the trace registers from both + * Execution states do not trap to EL2. + * If PE trace unit System registers are not implemented + * then this bit is reserved, and must be set to zero. + * + * CPTR_EL2.TFP: Set to zero so that Non-secure accesses + * to SIMD and floating-point functionality from both + * Execution states do not trap to EL2. + */ + write_cptr_el2(CPTR_EL2_RESET_VAL & + ~(CPTR_EL2_TCPAC_BIT | CPTR_EL2_TTA_BIT + | CPTR_EL2_TFP_BIT)); + + /* + * Initialise CNTHCTL_EL2. All fields are + * architecturally UNKNOWN on reset and are set to zero + * except for field(s) listed below. + * + * CNTHCTL_EL2.EL1PTEN: Set to one to disable traps to + * Hyp mode of Non-secure EL0 and EL1 accesses to the + * physical timer registers. + * + * CNTHCTL_EL2.EL1PCTEN: Set to one to disable traps to + * Hyp mode of Non-secure EL0 and EL1 accesses to the + * physical counter registers. + */ + write_cnthctl_el2(CNTHCTL_RESET_VAL | + EL1PCEN_BIT | EL1PCTEN_BIT); + + /* + * Initialise CNTVOFF_EL2 to zero as it resets to an + * architecturally UNKNOWN value. + */ + write_cntvoff_el2(0); + + /* + * Set VPIDR_EL2 and VMPIDR_EL2 to match MIDR_EL1 and + * MPIDR_EL1 respectively. + */ + write_vpidr_el2(read_midr_el1()); + write_vmpidr_el2(read_mpidr_el1()); + + /* + * Initialise VTTBR_EL2. All fields are architecturally + * UNKNOWN on reset. + * + * VTTBR_EL2.VMID: Set to zero. Even though EL1&0 stage + * 2 address translation is disabled, cache maintenance + * operations depend on the VMID. + * + * VTTBR_EL2.BADDR: Set to zero as EL1&0 stage 2 address + * translation is disabled. + */ + write_vttbr_el2(VTTBR_RESET_VAL & + ~((VTTBR_VMID_MASK << VTTBR_VMID_SHIFT) + | (VTTBR_BADDR_MASK << VTTBR_BADDR_SHIFT))); + + /* + * Initialise MDCR_EL2, setting all fields rather than + * relying on hw. Some fields are architecturally + * UNKNOWN on reset. + * + * MDCR_EL2.HLP: 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. + * + * MDCR_EL2.TTRF: Set to zero so that access to Trace + * Filter Control register TRFCR_EL1 at EL1 is not + * trapped to EL2. This bit is RES0 in versions of + * the architecture earlier than ARMv8.4. + * + * MDCR_EL2.HPMD: Set to one so that event counting is + * prohibited at EL2. This bit is RES0 in versions of + * the architecture earlier than ARMv8.1, setting it + * to 1 doesn't have any effect on them. + * + * MDCR_EL2.TPMS: Set to zero so that accesses to + * Statistical Profiling control registers from EL1 + * do not trap to EL2. This bit is RES0 when SPE is + * not implemented. + * + * MDCR_EL2.TDRA: Set to zero so that Non-secure EL0 and + * EL1 System register accesses to the Debug ROM + * registers are not trapped to EL2. + * + * MDCR_EL2.TDOSA: Set to zero so that Non-secure EL1 + * System register accesses to the powerdown debug + * registers are not trapped to EL2. + * + * MDCR_EL2.TDA: Set to zero so that System register + * accesses to the debug registers do not trap to EL2. + * + * MDCR_EL2.TDE: Set to zero so that debug exceptions + * are not routed to EL2. + * + * MDCR_EL2.HPME: Set to zero to disable EL2 Performance + * Monitors. + * + * MDCR_EL2.TPM: Set to zero so that Non-secure EL0 and + * EL1 accesses to all Performance Monitors registers + * are not trapped to EL2. + * + * MDCR_EL2.TPMCR: Set to zero so that Non-secure EL0 + * and EL1 accesses to the PMCR_EL0 or PMCR are not + * trapped to EL2. + * + * MDCR_EL2.HPMN: Set to value of PMCR_EL0.N which is the + * architecturally-defined reset value. + * + * MDCR_EL2.E2TB: Set to zero so that the trace Buffer + * owning exception level is NS-EL1 and, tracing is + * prohibited at NS-EL2. These bits are RES0 when + * FEAT_TRBE is not implemented. + */ + mdcr_el2 = ((MDCR_EL2_RESET_VAL | MDCR_EL2_HLP | + MDCR_EL2_HPMD) | + ((read_pmcr_el0() & PMCR_EL0_N_BITS) + >> PMCR_EL0_N_SHIFT)) & + ~(MDCR_EL2_TTRF | MDCR_EL2_TPMS | + MDCR_EL2_TDRA_BIT | MDCR_EL2_TDOSA_BIT | + MDCR_EL2_TDA_BIT | MDCR_EL2_TDE_BIT | + MDCR_EL2_HPME_BIT | MDCR_EL2_TPM_BIT | + MDCR_EL2_TPMCR_BIT | + MDCR_EL2_E2TB(MDCR_EL2_E2TB_EL1)); + + write_mdcr_el2(mdcr_el2); + + /* + * Initialise HSTR_EL2. All fields are architecturally + * UNKNOWN on reset. + * + * HSTR_EL2.T: Set all these fields to zero so that + * Non-secure EL0 or EL1 accesses to System registers + * do not trap to EL2. + */ + write_hstr_el2(HSTR_EL2_RESET_VAL & ~(HSTR_EL2_T_MASK)); + /* + * Initialise CNTHP_CTL_EL2. All fields are + * architecturally UNKNOWN on reset. + * + * CNTHP_CTL_EL2:ENABLE: Set to zero to disable the EL2 + * physical timer and prevent timer interrupts. + */ + write_cnthp_ctl_el2(CNTHP_CTL_RESET_VAL & + ~(CNTHP_CTL_ENABLE_BIT)); + } + manage_extensions_nonsecure(el2_unused, ctx); + } + + cm_el1_sysregs_context_restore(security_state); + cm_set_next_eret_context(security_state); +} + +#if CTX_INCLUDE_EL2_REGS +/******************************************************************************* + * Save EL2 sysreg context + ******************************************************************************/ +void cm_el2_sysregs_context_save(uint32_t security_state) +{ + u_register_t scr_el3 = read_scr(); + + /* + * Always save the non-secure and realm EL2 context, only save the + * S-EL2 context if S-EL2 is enabled. + */ + if ((security_state != SECURE) || + ((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) { + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + el2_sysregs_context_save(get_el2_sysregs_ctx(ctx)); + } +} + +/******************************************************************************* + * Restore EL2 sysreg context + ******************************************************************************/ +void cm_el2_sysregs_context_restore(uint32_t security_state) +{ + u_register_t scr_el3 = read_scr(); + + /* + * Always restore the non-secure and realm EL2 context, only restore the + * S-EL2 context if S-EL2 is enabled. + */ + if ((security_state != SECURE) || + ((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) { + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + el2_sysregs_context_restore(get_el2_sysregs_ctx(ctx)); + } +} +#endif /* CTX_INCLUDE_EL2_REGS */ + +/******************************************************************************* + * The next four functions are used by runtime services to save and restore + * EL1 context on the 'cpu_context' structure for the specified security + * state. + ******************************************************************************/ +void cm_el1_sysregs_context_save(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + el1_sysregs_context_save(get_el1_sysregs_ctx(ctx)); + +#if IMAGE_BL31 + if (security_state == SECURE) + PUBLISH_EVENT(cm_exited_secure_world); + else + PUBLISH_EVENT(cm_exited_normal_world); +#endif +} + +void cm_el1_sysregs_context_restore(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + el1_sysregs_context_restore(get_el1_sysregs_ctx(ctx)); + +#if IMAGE_BL31 + if (security_state == SECURE) + PUBLISH_EVENT(cm_entering_secure_world); + else + PUBLISH_EVENT(cm_entering_normal_world); +#endif +} + +/******************************************************************************* + * This function populates ELR_EL3 member of 'cpu_context' pertaining to the + * given security state with the given entrypoint + ******************************************************************************/ +void cm_set_elr_el3(uint32_t security_state, uintptr_t entrypoint) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_ELR_EL3, entrypoint); +} + +/******************************************************************************* + * This function populates ELR_EL3 and SPSR_EL3 members of 'cpu_context' + * pertaining to the given security state + ******************************************************************************/ +void cm_set_elr_spsr_el3(uint32_t security_state, + uintptr_t entrypoint, uint32_t spsr) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_ELR_EL3, entrypoint); + write_ctx_reg(state, CTX_SPSR_EL3, spsr); +} + +/******************************************************************************* + * This function updates a single bit in the SCR_EL3 member of the 'cpu_context' + * pertaining to the given security state using the value and bit position + * specified in the parameters. It preserves all other bits. + ******************************************************************************/ +void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value) +{ + cpu_context_t *ctx; + el3_state_t *state; + u_register_t scr_el3; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + /* Ensure that the bit position is a valid one */ + assert(((1UL << bit_pos) & SCR_VALID_BIT_MASK) != 0U); + + /* Ensure that the 'value' is only a bit wide */ + assert(value <= 1U); + + /* + * Get the SCR_EL3 value from the cpu context, clear the desired bit + * and set it to its new value. + */ + state = get_el3state_ctx(ctx); + scr_el3 = read_ctx_reg(state, CTX_SCR_EL3); + scr_el3 &= ~(1UL << bit_pos); + scr_el3 |= (u_register_t)value << bit_pos; + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); +} + +/******************************************************************************* + * This function retrieves SCR_EL3 member of 'cpu_context' pertaining to the + * given security state. + ******************************************************************************/ +u_register_t cm_get_scr_el3(uint32_t security_state) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + return read_ctx_reg(state, CTX_SCR_EL3); +} + +/******************************************************************************* + * 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 + ******************************************************************************/ +void cm_set_next_eret_context(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + cm_set_next_context(ctx); +} diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S b/arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S new file mode 100644 index 0000000..2392d6b --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +.globl init_cpu_data_ptr +.globl _cpu_data_by_index + +/* ----------------------------------------------------------------- + * void init_cpu_data_ptr(void) + * + * Initialise the TPIDR_EL3 register to refer to the cpu_data_t + * for the calling CPU. This must be called before cm_get_cpu_data() + * + * This can be called without a valid stack. It assumes that + * plat_my_core_pos() does not clobber register x10. + * clobbers: x0, x1, x10 + * ----------------------------------------------------------------- + */ +func init_cpu_data_ptr + mov x10, x30 + bl plat_my_core_pos + bl _cpu_data_by_index + msr tpidr_el3, x0 + ret x10 +endfunc init_cpu_data_ptr + +/* ----------------------------------------------------------------- + * cpu_data_t *_cpu_data_by_index(uint32_t cpu_index) + * + * Return the cpu_data structure for the CPU with given linear index + * + * This can be called without a valid stack. + * clobbers: x0, x1 + * ----------------------------------------------------------------- + */ +func _cpu_data_by_index + mov_imm x1, CPU_DATA_SIZE + mul x0, x0, x1 + adrp x1, percpu_data + add x1, x1, :lo12:percpu_data + add x0, x0, x1 + ret +endfunc _cpu_data_by_index diff --git a/arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c b/arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c new file mode 100644 index 0000000..13d464c --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* The per_cpu_ptr_cache_t space allocation */ +cpu_data_t percpu_data[PLATFORM_CORE_COUNT]; diff --git a/arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c b/arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c new file mode 100644 index 0000000..57b1158 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "../amu_private.h" +#include +#include +#include +#include +#include + +#include + +struct amu_ctx { + uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS]; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS]; +#endif + + uint16_t group0_enable; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint16_t group1_enable; +#endif +}; + +static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT]; + +CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS, + amu_ctx_group0_enable_cannot_represent_all_group0_counters); + +#if ENABLE_AMU_AUXILIARY_COUNTERS +CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS, + amu_ctx_group1_enable_cannot_represent_all_group1_counters); +#endif + +static inline __unused uint32_t read_id_pfr0_amu(void) +{ + return (read_id_pfr0() >> ID_PFR0_AMU_SHIFT) & + ID_PFR0_AMU_MASK; +} + +static inline __unused void write_hcptr_tam(uint32_t value) +{ + write_hcptr((read_hcptr() & ~TAM_BIT) | + ((value << TAM_SHIFT) & TAM_BIT)); +} + +static inline __unused void write_amcr_cg1rz(uint32_t value) +{ + write_amcr((read_amcr() & ~AMCR_CG1RZ_BIT) | + ((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT)); +} + +static inline __unused uint32_t read_amcfgr_ncg(void) +{ + return (read_amcfgr() >> AMCFGR_NCG_SHIFT) & + AMCFGR_NCG_MASK; +} + +static inline __unused uint32_t read_amcgcr_cg0nc(void) +{ + return (read_amcgcr() >> AMCGCR_CG0NC_SHIFT) & + AMCGCR_CG0NC_MASK; +} + +static inline __unused uint32_t read_amcgcr_cg1nc(void) +{ + return (read_amcgcr() >> AMCGCR_CG1NC_SHIFT) & + AMCGCR_CG1NC_MASK; +} + +static inline __unused uint32_t read_amcntenset0_px(void) +{ + return (read_amcntenset0() >> AMCNTENSET0_Pn_SHIFT) & + AMCNTENSET0_Pn_MASK; +} + +static inline __unused uint32_t read_amcntenset1_px(void) +{ + return (read_amcntenset1() >> AMCNTENSET1_Pn_SHIFT) & + AMCNTENSET1_Pn_MASK; +} + +static inline __unused void write_amcntenset0_px(uint32_t px) +{ + uint32_t value = read_amcntenset0(); + + value &= ~AMCNTENSET0_Pn_MASK; + value |= (px << AMCNTENSET0_Pn_SHIFT) & + AMCNTENSET0_Pn_MASK; + + write_amcntenset0(value); +} + +static inline __unused void write_amcntenset1_px(uint32_t px) +{ + uint32_t value = read_amcntenset1(); + + value &= ~AMCNTENSET1_Pn_MASK; + value |= (px << AMCNTENSET1_Pn_SHIFT) & + AMCNTENSET1_Pn_MASK; + + write_amcntenset1(value); +} + +static inline __unused void write_amcntenclr0_px(uint32_t px) +{ + uint32_t value = read_amcntenclr0(); + + value &= ~AMCNTENCLR0_Pn_MASK; + value |= (px << AMCNTENCLR0_Pn_SHIFT) & AMCNTENCLR0_Pn_MASK; + + write_amcntenclr0(value); +} + +static inline __unused void write_amcntenclr1_px(uint32_t px) +{ + uint32_t value = read_amcntenclr1(); + + value &= ~AMCNTENCLR1_Pn_MASK; + value |= (px << AMCNTENCLR1_Pn_SHIFT) & AMCNTENCLR1_Pn_MASK; + + write_amcntenclr1(value); +} + +static __unused bool amu_supported(void) +{ + return read_id_pfr0_amu() >= ID_PFR0_AMU_V1; +} + +#if ENABLE_AMU_AUXILIARY_COUNTERS +static __unused bool amu_group1_supported(void) +{ + return read_amcfgr_ncg() > 0U; +} +#endif + +/* + * Enable counters. This function is meant to be invoked by the context + * management library before exiting from EL3. + */ +void amu_enable(bool el2_unused) +{ + uint32_t id_pfr0_amu; /* AMU version */ + + uint32_t amcfgr_ncg; /* Number of counter groups */ + uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ + + uint32_t amcntenset0_px = 0x0; /* Group 0 enable mask */ + uint32_t amcntenset1_px = 0x0; /* Group 1 enable mask */ + + id_pfr0_amu = read_id_pfr0_amu(); + if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { + /* + * If the AMU is unsupported, nothing needs to be done. + */ + + return; + } + + if (el2_unused) { + /* + * HCPTR.TAM: Set to zero so any accesses to the Activity + * Monitor registers do not trap to EL2. + */ + write_hcptr_tam(0U); + } + + /* + * Retrieve the number of architected counters. All of these counters + * are enabled by default. + */ + + amcgcr_cg0nc = read_amcgcr_cg0nc(); + amcntenset0_px = (UINT32_C(1) << (amcgcr_cg0nc)) - 1U; + + assert(amcgcr_cg0nc <= AMU_AMCGCR_CG0NC_MAX); + + /* + * The platform may opt to enable specific auxiliary counters. This can + * be done via the common FCONF getter, or via the platform-implemented + * function. + */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + const struct amu_topology *topology; + +#if ENABLE_AMU_FCONF + topology = FCONF_GET_PROPERTY(amu, config, topology); +#else + topology = plat_amu_topology(); +#endif /* ENABLE_AMU_FCONF */ + + if (topology != NULL) { + unsigned int core_pos = plat_my_core_pos(); + + amcntenset1_el0_px = topology->cores[core_pos].enable; + } else { + ERROR("AMU: failed to generate AMU topology\n"); + } +#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */ + + /* + * Enable the requested counters. + */ + + write_amcntenset0_px(amcntenset0_px); + + amcfgr_ncg = read_amcfgr_ncg(); + if (amcfgr_ncg > 0U) { + write_amcntenset1_px(amcntenset1_px); + +#if !ENABLE_AMU_AUXILIARY_COUNTERS + VERBOSE("AMU: auxiliary counters detected but support is disabled\n"); +#endif + } + + /* Initialize FEAT_AMUv1p1 features if present. */ + if (id_pfr0_amu < ID_PFR0_AMU_V1P1) { + return; + } + +#if AMU_RESTRICT_COUNTERS + /* + * FEAT_AMUv1p1 adds a register field to restrict access to group 1 + * counters at all but the highest implemented EL. This is controlled + * with the AMU_RESTRICT_COUNTERS compile time flag, when set, system + * register reads at lower ELs return zero. Reads from the memory + * mapped view are unaffected. + */ + VERBOSE("AMU group 1 counter access restricted.\n"); + write_amcr_cg1rz(1U); +#else + write_amcr_cg1rz(0U); +#endif +} + +/* Read the group 0 counter identified by the given `idx`. */ +static uint64_t amu_group0_cnt_read(unsigned int idx) +{ + assert(amu_supported()); + assert(idx < read_amcgcr_cg0nc()); + + return amu_group0_cnt_read_internal(idx); +} + +/* Write the group 0 counter identified by the given `idx` with `val` */ +static void amu_group0_cnt_write(unsigned int idx, uint64_t val) +{ + assert(amu_supported()); + assert(idx < read_amcgcr_cg0nc()); + + amu_group0_cnt_write_internal(idx, val); + isb(); +} + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* Read the group 1 counter identified by the given `idx` */ +static uint64_t amu_group1_cnt_read(unsigned int idx) +{ + assert(amu_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_cg1nc()); + + return amu_group1_cnt_read_internal(idx); +} + +/* Write the group 1 counter identified by the given `idx` with `val` */ +static void amu_group1_cnt_write(unsigned int idx, uint64_t val) +{ + assert(amu_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_cg1nc()); + + amu_group1_cnt_write_internal(idx, val); + isb(); +} +#endif + +static void *amu_context_save(const void *arg) +{ + uint32_t i; + + unsigned int core_pos; + struct amu_ctx *ctx; + + uint32_t id_pfr0_amu; /* AMU version */ + uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint32_t amcfgr_ncg; /* Number of counter groups */ + uint32_t amcgcr_cg1nc; /* Number of group 1 counters */ +#endif + + id_pfr0_amu = read_id_pfr0_amu(); + if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { + return (void *)0; + } + + core_pos = plat_my_core_pos(); + ctx = &amu_ctxs_[core_pos]; + + amcgcr_cg0nc = read_amcgcr_cg0nc(); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + amcfgr_ncg = read_amcfgr_ncg(); + amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U; +#endif + + /* + * Disable all AMU counters. + */ + + ctx->group0_enable = read_amcntenset0_px(); + write_amcntenclr0_px(ctx->group0_enable); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + if (amcfgr_ncg > 0U) { + ctx->group1_enable = read_amcntenset1_px(); + write_amcntenclr1_px(ctx->group1_enable); + } +#endif + + /* + * Save the counters to the local context. + */ + + isb(); /* Ensure counters have been stopped */ + + for (i = 0U; i < amcgcr_cg0nc; i++) { + ctx->group0_cnts[i] = amu_group0_cnt_read(i); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U; i < amcgcr_cg1nc; i++) { + ctx->group1_cnts[i] = amu_group1_cnt_read(i); + } +#endif + + return (void *)0; +} + +static void *amu_context_restore(const void *arg) +{ + uint32_t i; + + unsigned int core_pos; + struct amu_ctx *ctx; + + uint32_t id_pfr0_amu; /* AMU version */ + + uint32_t amcfgr_ncg; /* Number of counter groups */ + uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint32_t amcgcr_cg1nc; /* Number of group 1 counters */ +#endif + + id_pfr0_amu = read_id_pfr0_amu(); + if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { + return (void *)0; + } + + core_pos = plat_my_core_pos(); + ctx = &amu_ctxs_[core_pos]; + + amcfgr_ncg = read_amcfgr_ncg(); + amcgcr_cg0nc = read_amcgcr_cg0nc(); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U; +#endif + + /* + * Sanity check that all counters were disabled when the context was + * previously saved. + */ + + assert(read_amcntenset0_px() == 0U); + + if (amcfgr_ncg > 0U) { + assert(read_amcntenset1_px() == 0U); + } + + /* + * Restore the counter values from the local context. + */ + + for (i = 0U; i < amcgcr_cg0nc; i++) { + amu_group0_cnt_write(i, ctx->group0_cnts[i]); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U; i < amcgcr_cg1nc; i++) { + amu_group1_cnt_write(i, ctx->group1_cnts[i]); + } +#endif + + /* + * Re-enable counters that were disabled during context save. + */ + + write_amcntenset0_px(ctx->group0_enable); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + if (amcfgr_ncg > 0U) { + write_amcntenset1_px(ctx->group1_enable); + } +#endif + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore); diff --git a/arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S b/arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S new file mode 100644 index 0000000..8ac7678 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl amu_group0_cnt_read_internal + .globl amu_group0_cnt_write_internal + .globl amu_group1_cnt_read_internal + .globl amu_group1_cnt_write_internal + .globl amu_group1_set_evtype_internal + +/* + * uint64_t amu_group0_cnt_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `r0` and `r1`. + */ +func amu_group0_cnt_read_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 3] */ + mov r1, r0 + lsr r1, r1, #2 + cmp r1, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of ldcopr16/bx lr instruction pair + * in the table below. + */ + adr r1, 1f + lsl r0, r0, #3 /* each ldcopr16/bx lr sequence is 8 bytes */ + add r1, r1, r0 + bx r1 +1: + ldcopr16 r0, r1, AMEVCNTR00 /* index 0 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR01 /* index 1 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR02 /* index 2 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR03 /* index 3 */ + bx lr +endfunc amu_group0_cnt_read_internal + +/* + * void amu_group0_cnt_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + * `idx` is passed in `r0` and `val` is passed in `r2` and `r3`. + * `r1` is used as a scratch register. + */ +func amu_group0_cnt_write_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 3] */ + mov r1, r0 + lsr r1, r1, #2 + cmp r1, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of stcopr16/bx lr instruction pair + * in the table below. + */ + adr r1, 1f + lsl r0, r0, #3 /* each stcopr16/bx lr sequence is 8 bytes */ + add r1, r1, r0 + bx r1 + +1: + stcopr16 r2, r3, AMEVCNTR00 /* index 0 */ + bx lr + stcopr16 r2, r3, AMEVCNTR01 /* index 1 */ + bx lr + stcopr16 r2, r3, AMEVCNTR02 /* index 2 */ + bx lr + stcopr16 r2, r3, AMEVCNTR03 /* index 3 */ + bx lr +endfunc amu_group0_cnt_write_internal + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* + * uint64_t amu_group1_cnt_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `r0` and `r1`. + */ +func amu_group1_cnt_read_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 15] */ + mov r1, r0 + lsr r1, r1, #4 + cmp r1, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of ldcopr16/bx lr instruction pair + * in the table below. + */ + adr r1, 1f + lsl r0, r0, #3 /* each ldcopr16/bx lr sequence is 8 bytes */ + add r1, r1, r0 + bx r1 + +1: + ldcopr16 r0, r1, AMEVCNTR10 /* index 0 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR11 /* index 1 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR12 /* index 2 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR13 /* index 3 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR14 /* index 4 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR15 /* index 5 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR16 /* index 6 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR17 /* index 7 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR18 /* index 8 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR19 /* index 9 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1A /* index 10 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1B /* index 11 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1C /* index 12 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1D /* index 13 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1E /* index 14 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1F /* index 15 */ + bx lr +endfunc amu_group1_cnt_read_internal + +/* + * void amu_group1_cnt_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + * `idx` is passed in `r0` and `val` is passed in `r2` and `r3`. + * `r1` is used as a scratch register. + */ +func amu_group1_cnt_write_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 15] */ + mov r1, r0 + lsr r1, r1, #4 + cmp r1, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of ldcopr16/bx lr instruction pair + * in the table below. + */ + adr r1, 1f + lsl r0, r0, #3 /* each stcopr16/bx lr sequence is 8 bytes */ + add r1, r1, r0 + bx r1 + +1: + stcopr16 r2, r3, AMEVCNTR10 /* index 0 */ + bx lr + stcopr16 r2, r3, AMEVCNTR11 /* index 1 */ + bx lr + stcopr16 r2, r3, AMEVCNTR12 /* index 2 */ + bx lr + stcopr16 r2, r3, AMEVCNTR13 /* index 3 */ + bx lr + stcopr16 r2, r3, AMEVCNTR14 /* index 4 */ + bx lr + stcopr16 r2, r3, AMEVCNTR15 /* index 5 */ + bx lr + stcopr16 r2, r3, AMEVCNTR16 /* index 6 */ + bx lr + stcopr16 r2, r3, AMEVCNTR17 /* index 7 */ + bx lr + stcopr16 r2, r3, AMEVCNTR18 /* index 8 */ + bx lr + stcopr16 r2, r3, AMEVCNTR19 /* index 9 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1A /* index 10 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1B /* index 11 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1C /* index 12 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1D /* index 13 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1E /* index 14 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1F /* index 15 */ + bx lr +endfunc amu_group1_cnt_write_internal + +/* + * void amu_group1_set_evtype_internal(int idx, unsigned int val); + * + * Program the AMU event type register indexed by `idx` + * with the value `val`. + */ +func amu_group1_set_evtype_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 15] */ + mov r2, r0 + lsr r2, r2, #4 + cmp r2, #0 + ASM_ASSERT(eq) + + /* val should be between [0, 65535] */ + mov r2, r1 + lsr r2, r2, #16 + cmp r2, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of stcopr/bx lr instruction pair + * in the table below. + */ + adr r2, 1f + lsl r0, r0, #3 /* each stcopr/bx lr sequence is 8 bytes */ + add r2, r2, r0 + bx r2 + +1: + stcopr r1, AMEVTYPER10 /* index 0 */ + bx lr + stcopr r1, AMEVTYPER11 /* index 1 */ + bx lr + stcopr r1, AMEVTYPER12 /* index 2 */ + bx lr + stcopr r1, AMEVTYPER13 /* index 3 */ + bx lr + stcopr r1, AMEVTYPER14 /* index 4 */ + bx lr + stcopr r1, AMEVTYPER15 /* index 5 */ + bx lr + stcopr r1, AMEVTYPER16 /* index 6 */ + bx lr + stcopr r1, AMEVTYPER17 /* index 7 */ + bx lr + stcopr r1, AMEVTYPER18 /* index 8 */ + bx lr + stcopr r1, AMEVTYPER19 /* index 9 */ + bx lr + stcopr r1, AMEVTYPER1A /* index 10 */ + bx lr + stcopr r1, AMEVTYPER1B /* index 11 */ + bx lr + stcopr r1, AMEVTYPER1C /* index 12 */ + bx lr + stcopr r1, AMEVTYPER1D /* index 13 */ + bx lr + stcopr r1, AMEVTYPER1E /* index 14 */ + bx lr + stcopr r1, AMEVTYPER1F /* index 15 */ + bx lr +endfunc amu_group1_set_evtype_internal +#endif diff --git a/arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c b/arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c new file mode 100644 index 0000000..d329c3d --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include "../amu_private.h" +#include +#include +#include +#include +#include +#include + +#include + +#if ENABLE_AMU_FCONF +# include +# include +#endif + +#if ENABLE_MPMM +# include +#endif + +struct amu_ctx { + uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS]; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS]; +#endif + + /* Architected event counter 1 does not have an offset register */ + uint64_t group0_voffsets[AMU_GROUP0_MAX_COUNTERS - 1U]; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t group1_voffsets[AMU_GROUP1_MAX_COUNTERS]; +#endif + + uint16_t group0_enable; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint16_t group1_enable; +#endif +}; + +static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT]; + +CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS, + amu_ctx_group0_enable_cannot_represent_all_group0_counters); + +#if ENABLE_AMU_AUXILIARY_COUNTERS +CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS, + amu_ctx_group1_enable_cannot_represent_all_group1_counters); +#endif + +static inline __unused uint64_t read_id_aa64pfr0_el1_amu(void) +{ + return (read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) & + ID_AA64PFR0_AMU_MASK; +} + +static inline __unused uint64_t read_hcr_el2_amvoffen(void) +{ + return (read_hcr_el2() & HCR_AMVOFFEN_BIT) >> + HCR_AMVOFFEN_SHIFT; +} + +static inline __unused void write_cptr_el2_tam(uint64_t value) +{ + write_cptr_el2((read_cptr_el2() & ~CPTR_EL2_TAM_BIT) | + ((value << CPTR_EL2_TAM_SHIFT) & CPTR_EL2_TAM_BIT)); +} + +static inline __unused void write_cptr_el3_tam(cpu_context_t *ctx, uint64_t tam) +{ + uint64_t value = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3); + + value &= ~TAM_BIT; + value |= (tam << TAM_SHIFT) & TAM_BIT; + + write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, value); +} + +static inline __unused void write_hcr_el2_amvoffen(uint64_t value) +{ + write_hcr_el2((read_hcr_el2() & ~HCR_AMVOFFEN_BIT) | + ((value << HCR_AMVOFFEN_SHIFT) & HCR_AMVOFFEN_BIT)); +} + +static inline __unused void write_amcr_el0_cg1rz(uint64_t value) +{ + write_amcr_el0((read_amcr_el0() & ~AMCR_CG1RZ_BIT) | + ((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT)); +} + +static inline __unused uint64_t read_amcfgr_el0_ncg(void) +{ + return (read_amcfgr_el0() >> AMCFGR_EL0_NCG_SHIFT) & + AMCFGR_EL0_NCG_MASK; +} + +static inline __unused uint64_t read_amcgcr_el0_cg0nc(void) +{ + return (read_amcgcr_el0() >> AMCGCR_EL0_CG0NC_SHIFT) & + AMCGCR_EL0_CG0NC_MASK; +} + +static inline __unused uint64_t read_amcg1idr_el0_voff(void) +{ + return (read_amcg1idr_el0() >> AMCG1IDR_VOFF_SHIFT) & + AMCG1IDR_VOFF_MASK; +} + +static inline __unused uint64_t read_amcgcr_el0_cg1nc(void) +{ + return (read_amcgcr_el0() >> AMCGCR_EL0_CG1NC_SHIFT) & + AMCGCR_EL0_CG1NC_MASK; +} + +static inline __unused uint64_t read_amcntenset0_el0_px(void) +{ + return (read_amcntenset0_el0() >> AMCNTENSET0_EL0_Pn_SHIFT) & + AMCNTENSET0_EL0_Pn_MASK; +} + +static inline __unused uint64_t read_amcntenset1_el0_px(void) +{ + return (read_amcntenset1_el0() >> AMCNTENSET1_EL0_Pn_SHIFT) & + AMCNTENSET1_EL0_Pn_MASK; +} + +static inline __unused void write_amcntenset0_el0_px(uint64_t px) +{ + uint64_t value = read_amcntenset0_el0(); + + value &= ~AMCNTENSET0_EL0_Pn_MASK; + value |= (px << AMCNTENSET0_EL0_Pn_SHIFT) & AMCNTENSET0_EL0_Pn_MASK; + + write_amcntenset0_el0(value); +} + +static inline __unused void write_amcntenset1_el0_px(uint64_t px) +{ + uint64_t value = read_amcntenset1_el0(); + + value &= ~AMCNTENSET1_EL0_Pn_MASK; + value |= (px << AMCNTENSET1_EL0_Pn_SHIFT) & AMCNTENSET1_EL0_Pn_MASK; + + write_amcntenset1_el0(value); +} + +static inline __unused void write_amcntenclr0_el0_px(uint64_t px) +{ + uint64_t value = read_amcntenclr0_el0(); + + value &= ~AMCNTENCLR0_EL0_Pn_MASK; + value |= (px << AMCNTENCLR0_EL0_Pn_SHIFT) & AMCNTENCLR0_EL0_Pn_MASK; + + write_amcntenclr0_el0(value); +} + +static inline __unused void write_amcntenclr1_el0_px(uint64_t px) +{ + uint64_t value = read_amcntenclr1_el0(); + + value &= ~AMCNTENCLR1_EL0_Pn_MASK; + value |= (px << AMCNTENCLR1_EL0_Pn_SHIFT) & AMCNTENCLR1_EL0_Pn_MASK; + + write_amcntenclr1_el0(value); +} + +static __unused bool amu_supported(void) +{ + return read_id_aa64pfr0_el1_amu() >= ID_AA64PFR0_AMU_V1; +} + +static __unused bool amu_v1p1_supported(void) +{ + return read_id_aa64pfr0_el1_amu() >= ID_AA64PFR0_AMU_V1P1; +} + +#if ENABLE_AMU_AUXILIARY_COUNTERS +static __unused bool amu_group1_supported(void) +{ + return read_amcfgr_el0_ncg() > 0U; +} +#endif + +/* + * Enable counters. This function is meant to be invoked by the context + * management library before exiting from EL3. + */ +void amu_enable(bool el2_unused, cpu_context_t *ctx) +{ + uint64_t id_aa64pfr0_el1_amu; /* AMU version */ + + uint64_t amcfgr_el0_ncg; /* Number of counter groups */ + uint64_t amcgcr_el0_cg0nc; /* Number of group 0 counters */ + + uint64_t amcntenset0_el0_px = 0x0; /* Group 0 enable mask */ + uint64_t amcntenset1_el0_px = 0x0; /* Group 1 enable mask */ + + id_aa64pfr0_el1_amu = read_id_aa64pfr0_el1_amu(); + if (id_aa64pfr0_el1_amu == ID_AA64PFR0_AMU_NOT_SUPPORTED) { + /* + * If the AMU is unsupported, nothing needs to be done. + */ + + return; + } + + if (el2_unused) { + /* + * CPTR_EL2.TAM: Set to zero so any accesses to the Activity + * Monitor registers do not trap to EL2. + */ + write_cptr_el2_tam(0U); + } + + /* + * Retrieve and update the CPTR_EL3 value from the context mentioned + * in 'ctx'. Set CPTR_EL3.TAM to zero so that any accesses to + * the Activity Monitor registers do not trap to EL3. + */ + write_cptr_el3_tam(ctx, 0U); + + /* + * Retrieve the number of architected counters. All of these counters + * are enabled by default. + */ + + amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc(); + amcntenset0_el0_px = (UINT64_C(1) << (amcgcr_el0_cg0nc)) - 1U; + + assert(amcgcr_el0_cg0nc <= AMU_AMCGCR_CG0NC_MAX); + + /* + * The platform may opt to enable specific auxiliary counters. This can + * be done via the common FCONF getter, or via the platform-implemented + * function. + */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + const struct amu_topology *topology; + +#if ENABLE_AMU_FCONF + topology = FCONF_GET_PROPERTY(amu, config, topology); +#else + topology = plat_amu_topology(); +#endif /* ENABLE_AMU_FCONF */ + + if (topology != NULL) { + unsigned int core_pos = plat_my_core_pos(); + + amcntenset1_el0_px = topology->cores[core_pos].enable; + } else { + ERROR("AMU: failed to generate AMU topology\n"); + } +#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */ + + /* + * Enable the requested counters. + */ + + write_amcntenset0_el0_px(amcntenset0_el0_px); + + amcfgr_el0_ncg = read_amcfgr_el0_ncg(); + if (amcfgr_el0_ncg > 0U) { + write_amcntenset1_el0_px(amcntenset1_el0_px); + +#if !ENABLE_AMU_AUXILIARY_COUNTERS + VERBOSE("AMU: auxiliary counters detected but support is disabled\n"); +#endif + } + + /* Initialize FEAT_AMUv1p1 features if present. */ + if (id_aa64pfr0_el1_amu >= ID_AA64PFR0_AMU_V1P1) { + if (el2_unused) { + /* + * Make sure virtual offsets are disabled if EL2 not + * used. + */ + write_hcr_el2_amvoffen(0U); + } + +#if AMU_RESTRICT_COUNTERS + /* + * FEAT_AMUv1p1 adds a register field to restrict access to + * group 1 counters at all but the highest implemented EL. This + * is controlled with the `AMU_RESTRICT_COUNTERS` compile time + * flag, when set, system register reads at lower ELs return + * zero. Reads from the memory mapped view are unaffected. + */ + VERBOSE("AMU group 1 counter access restricted.\n"); + write_amcr_el0_cg1rz(1U); +#else + write_amcr_el0_cg1rz(0U); +#endif + } + +#if ENABLE_MPMM + mpmm_enable(); +#endif +} + +/* Read the group 0 counter identified by the given `idx`. */ +static uint64_t amu_group0_cnt_read(unsigned int idx) +{ + assert(amu_supported()); + assert(idx < read_amcgcr_el0_cg0nc()); + + return amu_group0_cnt_read_internal(idx); +} + +/* Write the group 0 counter identified by the given `idx` with `val` */ +static void amu_group0_cnt_write(unsigned int idx, uint64_t val) +{ + assert(amu_supported()); + assert(idx < read_amcgcr_el0_cg0nc()); + + amu_group0_cnt_write_internal(idx, val); + isb(); +} + +/* + * Unlike with auxiliary counters, we cannot detect at runtime whether an + * architected counter supports a virtual offset. These are instead fixed + * according to FEAT_AMUv1p1, but this switch will need to be updated if later + * revisions of FEAT_AMU add additional architected counters. + */ +static bool amu_group0_voffset_supported(uint64_t idx) +{ + switch (idx) { + case 0U: + case 2U: + case 3U: + return true; + + case 1U: + return false; + + default: + ERROR("AMU: can't set up virtual offset for unknown " + "architected counter %" PRIu64 "!\n", idx); + + panic(); + } +} + +/* + * Read the group 0 offset register for a given index. Index must be 0, 2, + * or 3, the register for 1 does not exist. + * + * Using this function requires FEAT_AMUv1p1 support. + */ +static uint64_t amu_group0_voffset_read(unsigned int idx) +{ + assert(amu_v1p1_supported()); + assert(idx < read_amcgcr_el0_cg0nc()); + assert(idx != 1U); + + return amu_group0_voffset_read_internal(idx); +} + +/* + * Write the group 0 offset register for a given index. Index must be 0, 2, or + * 3, the register for 1 does not exist. + * + * Using this function requires FEAT_AMUv1p1 support. + */ +static void amu_group0_voffset_write(unsigned int idx, uint64_t val) +{ + assert(amu_v1p1_supported()); + assert(idx < read_amcgcr_el0_cg0nc()); + assert(idx != 1U); + + amu_group0_voffset_write_internal(idx, val); + isb(); +} + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* Read the group 1 counter identified by the given `idx` */ +static uint64_t amu_group1_cnt_read(unsigned int idx) +{ + assert(amu_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_el0_cg1nc()); + + return amu_group1_cnt_read_internal(idx); +} + +/* Write the group 1 counter identified by the given `idx` with `val` */ +static void amu_group1_cnt_write(unsigned int idx, uint64_t val) +{ + assert(amu_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_el0_cg1nc()); + + amu_group1_cnt_write_internal(idx, val); + isb(); +} + +/* + * Read the group 1 offset register for a given index. + * + * Using this function requires FEAT_AMUv1p1 support. + */ +static uint64_t amu_group1_voffset_read(unsigned int idx) +{ + assert(amu_v1p1_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_el0_cg1nc()); + assert((read_amcg1idr_el0_voff() & (UINT64_C(1) << idx)) != 0U); + + return amu_group1_voffset_read_internal(idx); +} + +/* + * Write the group 1 offset register for a given index. + * + * Using this function requires FEAT_AMUv1p1 support. + */ +static void amu_group1_voffset_write(unsigned int idx, uint64_t val) +{ + assert(amu_v1p1_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_el0_cg1nc()); + assert((read_amcg1idr_el0_voff() & (UINT64_C(1) << idx)) != 0U); + + amu_group1_voffset_write_internal(idx, val); + isb(); +} +#endif + +static void *amu_context_save(const void *arg) +{ + uint64_t i, j; + + unsigned int core_pos; + struct amu_ctx *ctx; + + uint64_t id_aa64pfr0_el1_amu; /* AMU version */ + uint64_t hcr_el2_amvoffen; /* AMU virtual offsets enabled */ + uint64_t amcgcr_el0_cg0nc; /* Number of group 0 counters */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t amcg1idr_el0_voff; /* Auxiliary counters with virtual offsets */ + uint64_t amcfgr_el0_ncg; /* Number of counter groups */ + uint64_t amcgcr_el0_cg1nc; /* Number of group 1 counters */ +#endif + + id_aa64pfr0_el1_amu = read_id_aa64pfr0_el1_amu(); + if (id_aa64pfr0_el1_amu == ID_AA64PFR0_AMU_NOT_SUPPORTED) { + return (void *)0; + } + + core_pos = plat_my_core_pos(); + ctx = &amu_ctxs_[core_pos]; + + amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc(); + hcr_el2_amvoffen = (id_aa64pfr0_el1_amu >= ID_AA64PFR0_AMU_V1P1) ? + read_hcr_el2_amvoffen() : 0U; + +#if ENABLE_AMU_AUXILIARY_COUNTERS + amcfgr_el0_ncg = read_amcfgr_el0_ncg(); + amcgcr_el0_cg1nc = (amcfgr_el0_ncg > 0U) ? read_amcgcr_el0_cg1nc() : 0U; + amcg1idr_el0_voff = (hcr_el2_amvoffen != 0U) ? read_amcg1idr_el0_voff() : 0U; +#endif + + /* + * Disable all AMU counters. + */ + + ctx->group0_enable = read_amcntenset0_el0_px(); + write_amcntenclr0_el0_px(ctx->group0_enable); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + if (amcfgr_el0_ncg > 0U) { + ctx->group1_enable = read_amcntenset1_el0_px(); + write_amcntenclr1_el0_px(ctx->group1_enable); + } +#endif + + /* + * Save the counters to the local context. + */ + + isb(); /* Ensure counters have been stopped */ + + for (i = 0U; i < amcgcr_el0_cg0nc; i++) { + ctx->group0_cnts[i] = amu_group0_cnt_read(i); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U; i < amcgcr_el0_cg1nc; i++) { + ctx->group1_cnts[i] = amu_group1_cnt_read(i); + } +#endif + + /* + * Save virtual offsets for counters that offer them. + */ + + if (hcr_el2_amvoffen != 0U) { + for (i = 0U, j = 0U; i < amcgcr_el0_cg0nc; i++) { + if (!amu_group0_voffset_supported(i)) { + continue; /* No virtual offset */ + } + + ctx->group0_voffsets[j++] = amu_group0_voffset_read(i); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U, j = 0U; i < amcgcr_el0_cg1nc; i++) { + if ((amcg1idr_el0_voff >> i) & 1U) { + continue; /* No virtual offset */ + } + + ctx->group1_voffsets[j++] = amu_group1_voffset_read(i); + } +#endif + } + + return (void *)0; +} + +static void *amu_context_restore(const void *arg) +{ + uint64_t i, j; + + unsigned int core_pos; + struct amu_ctx *ctx; + + uint64_t id_aa64pfr0_el1_amu; /* AMU version */ + + uint64_t hcr_el2_amvoffen; /* AMU virtual offsets enabled */ + + uint64_t amcfgr_el0_ncg; /* Number of counter groups */ + uint64_t amcgcr_el0_cg0nc; /* Number of group 0 counters */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t amcgcr_el0_cg1nc; /* Number of group 1 counters */ + uint64_t amcg1idr_el0_voff; /* Auxiliary counters with virtual offsets */ +#endif + + id_aa64pfr0_el1_amu = read_id_aa64pfr0_el1_amu(); + if (id_aa64pfr0_el1_amu == ID_AA64PFR0_AMU_NOT_SUPPORTED) { + return (void *)0; + } + + core_pos = plat_my_core_pos(); + ctx = &amu_ctxs_[core_pos]; + + amcfgr_el0_ncg = read_amcfgr_el0_ncg(); + amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc(); + + hcr_el2_amvoffen = (id_aa64pfr0_el1_amu >= ID_AA64PFR0_AMU_V1P1) ? + read_hcr_el2_amvoffen() : 0U; + +#if ENABLE_AMU_AUXILIARY_COUNTERS + amcgcr_el0_cg1nc = (amcfgr_el0_ncg > 0U) ? read_amcgcr_el0_cg1nc() : 0U; + amcg1idr_el0_voff = (hcr_el2_amvoffen != 0U) ? read_amcg1idr_el0_voff() : 0U; +#endif + + /* + * Sanity check that all counters were disabled when the context was + * previously saved. + */ + + assert(read_amcntenset0_el0_px() == 0U); + + if (amcfgr_el0_ncg > 0U) { + assert(read_amcntenset1_el0_px() == 0U); + } + + /* + * Restore the counter values from the local context. + */ + + for (i = 0U; i < amcgcr_el0_cg0nc; i++) { + amu_group0_cnt_write(i, ctx->group0_cnts[i]); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U; i < amcgcr_el0_cg1nc; i++) { + amu_group1_cnt_write(i, ctx->group1_cnts[i]); + } +#endif + + /* + * Restore virtual offsets for counters that offer them. + */ + + if (hcr_el2_amvoffen != 0U) { + for (i = 0U, j = 0U; i < amcgcr_el0_cg0nc; i++) { + if (!amu_group0_voffset_supported(i)) { + continue; /* No virtual offset */ + } + + amu_group0_voffset_write(i, ctx->group0_voffsets[j++]); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U, j = 0U; i < amcgcr_el0_cg1nc; i++) { + if ((amcg1idr_el0_voff >> i) & 1U) { + continue; /* No virtual offset */ + } + + amu_group1_voffset_write(i, ctx->group1_voffsets[j++]); + } +#endif + } + + /* + * Re-enable counters that were disabled during context save. + */ + + write_amcntenset0_el0_px(ctx->group0_enable); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + if (amcfgr_el0_ncg > 0) { + write_amcntenset1_el0_px(ctx->group1_enable); + } +#endif + +#if ENABLE_MPMM + mpmm_enable(); +#endif + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore); diff --git a/arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S b/arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S new file mode 100644 index 0000000..0f6d799 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl amu_group0_cnt_read_internal + .globl amu_group0_cnt_write_internal + .globl amu_group1_cnt_read_internal + .globl amu_group1_cnt_write_internal + .globl amu_group1_set_evtype_internal + + /* FEAT_AMUv1p1 virtualisation offset register functions */ + .globl amu_group0_voffset_read_internal + .globl amu_group0_voffset_write_internal + .globl amu_group1_voffset_read_internal + .globl amu_group1_voffset_write_internal + +/* + * uint64_t amu_group0_cnt_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `x0`. + */ +func amu_group0_cnt_read_internal + adr x1, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~3 + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read AMEVCNTR00_EL0 /* index 0 */ + read AMEVCNTR01_EL0 /* index 1 */ + read AMEVCNTR02_EL0 /* index 2 */ + read AMEVCNTR03_EL0 /* index 3 */ +endfunc amu_group0_cnt_read_internal + +/* + * void amu_group0_cnt_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + */ +func amu_group0_cnt_write_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~3 + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVCNTR00_EL0 /* index 0 */ + write AMEVCNTR01_EL0 /* index 1 */ + write AMEVCNTR02_EL0 /* index 2 */ + write AMEVCNTR03_EL0 /* index 3 */ +endfunc amu_group0_cnt_write_internal + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* + * uint64_t amu_group1_cnt_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `x0`. + */ +func amu_group1_cnt_read_internal + adr x1, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read AMEVCNTR10_EL0 /* index 0 */ + read AMEVCNTR11_EL0 /* index 1 */ + read AMEVCNTR12_EL0 /* index 2 */ + read AMEVCNTR13_EL0 /* index 3 */ + read AMEVCNTR14_EL0 /* index 4 */ + read AMEVCNTR15_EL0 /* index 5 */ + read AMEVCNTR16_EL0 /* index 6 */ + read AMEVCNTR17_EL0 /* index 7 */ + read AMEVCNTR18_EL0 /* index 8 */ + read AMEVCNTR19_EL0 /* index 9 */ + read AMEVCNTR1A_EL0 /* index 10 */ + read AMEVCNTR1B_EL0 /* index 11 */ + read AMEVCNTR1C_EL0 /* index 12 */ + read AMEVCNTR1D_EL0 /* index 13 */ + read AMEVCNTR1E_EL0 /* index 14 */ + read AMEVCNTR1F_EL0 /* index 15 */ +endfunc amu_group1_cnt_read_internal + +/* + * void amu_group1_cnt_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + */ +func amu_group1_cnt_write_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVCNTR10_EL0 /* index 0 */ + write AMEVCNTR11_EL0 /* index 1 */ + write AMEVCNTR12_EL0 /* index 2 */ + write AMEVCNTR13_EL0 /* index 3 */ + write AMEVCNTR14_EL0 /* index 4 */ + write AMEVCNTR15_EL0 /* index 5 */ + write AMEVCNTR16_EL0 /* index 6 */ + write AMEVCNTR17_EL0 /* index 7 */ + write AMEVCNTR18_EL0 /* index 8 */ + write AMEVCNTR19_EL0 /* index 9 */ + write AMEVCNTR1A_EL0 /* index 10 */ + write AMEVCNTR1B_EL0 /* index 11 */ + write AMEVCNTR1C_EL0 /* index 12 */ + write AMEVCNTR1D_EL0 /* index 13 */ + write AMEVCNTR1E_EL0 /* index 14 */ + write AMEVCNTR1F_EL0 /* index 15 */ +endfunc amu_group1_cnt_write_internal + +/* + * void amu_group1_set_evtype_internal(int idx, unsigned int val); + * + * Program the AMU event type register indexed by `idx` + * with the value `val`. + */ +func amu_group1_set_evtype_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) + + /* val should be between [0, 65535] */ + tst x1, #~0xFFFF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of msr/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVTYPER10_EL0 /* index 0 */ + write AMEVTYPER11_EL0 /* index 1 */ + write AMEVTYPER12_EL0 /* index 2 */ + write AMEVTYPER13_EL0 /* index 3 */ + write AMEVTYPER14_EL0 /* index 4 */ + write AMEVTYPER15_EL0 /* index 5 */ + write AMEVTYPER16_EL0 /* index 6 */ + write AMEVTYPER17_EL0 /* index 7 */ + write AMEVTYPER18_EL0 /* index 8 */ + write AMEVTYPER19_EL0 /* index 9 */ + write AMEVTYPER1A_EL0 /* index 10 */ + write AMEVTYPER1B_EL0 /* index 11 */ + write AMEVTYPER1C_EL0 /* index 12 */ + write AMEVTYPER1D_EL0 /* index 13 */ + write AMEVTYPER1E_EL0 /* index 14 */ + write AMEVTYPER1F_EL0 /* index 15 */ +endfunc amu_group1_set_evtype_internal +#endif + +/* + * Accessor functions for virtual offset registers added with FEAT_AMUv1p1 + */ + +/* + * uint64_t amu_group0_voffset_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU virtual offset register + * and return it in `x0`. + */ +func amu_group0_voffset_read_internal + adr x1, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~3 + ASM_ASSERT(eq) + /* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */ + cmp x0, #1 + ASM_ASSERT(ne) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read AMEVCNTVOFF00_EL2 /* index 0 */ + .skip 8 /* AMEVCNTVOFF01_EL2 does not exist */ +#if ENABLE_BTI + .skip 4 +#endif + read AMEVCNTVOFF02_EL2 /* index 2 */ + read AMEVCNTVOFF03_EL2 /* index 3 */ +endfunc amu_group0_voffset_read_internal + +/* + * void amu_group0_voffset_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU virtual offset register. + */ +func amu_group0_voffset_write_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~3 + ASM_ASSERT(eq) + /* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */ + cmp x0, #1 + ASM_ASSERT(ne) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVCNTVOFF00_EL2 /* index 0 */ + .skip 8 /* AMEVCNTVOFF01_EL2 does not exist */ +#if ENABLE_BTI + .skip 4 +#endif + write AMEVCNTVOFF02_EL2 /* index 2 */ + write AMEVCNTVOFF03_EL2 /* index 3 */ +endfunc amu_group0_voffset_write_internal + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* + * uint64_t amu_group1_voffset_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU virtual offset register + * and return it in `x0`. + */ +func amu_group1_voffset_read_internal + adr x1, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read AMEVCNTVOFF10_EL2 /* index 0 */ + read AMEVCNTVOFF11_EL2 /* index 1 */ + read AMEVCNTVOFF12_EL2 /* index 2 */ + read AMEVCNTVOFF13_EL2 /* index 3 */ + read AMEVCNTVOFF14_EL2 /* index 4 */ + read AMEVCNTVOFF15_EL2 /* index 5 */ + read AMEVCNTVOFF16_EL2 /* index 6 */ + read AMEVCNTVOFF17_EL2 /* index 7 */ + read AMEVCNTVOFF18_EL2 /* index 8 */ + read AMEVCNTVOFF19_EL2 /* index 9 */ + read AMEVCNTVOFF1A_EL2 /* index 10 */ + read AMEVCNTVOFF1B_EL2 /* index 11 */ + read AMEVCNTVOFF1C_EL2 /* index 12 */ + read AMEVCNTVOFF1D_EL2 /* index 13 */ + read AMEVCNTVOFF1E_EL2 /* index 14 */ + read AMEVCNTVOFF1F_EL2 /* index 15 */ +endfunc amu_group1_voffset_read_internal + +/* + * void amu_group1_voffset_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU virtual offset register. + */ +func amu_group1_voffset_write_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVCNTVOFF10_EL2 /* index 0 */ + write AMEVCNTVOFF11_EL2 /* index 1 */ + write AMEVCNTVOFF12_EL2 /* index 2 */ + write AMEVCNTVOFF13_EL2 /* index 3 */ + write AMEVCNTVOFF14_EL2 /* index 4 */ + write AMEVCNTVOFF15_EL2 /* index 5 */ + write AMEVCNTVOFF16_EL2 /* index 6 */ + write AMEVCNTVOFF17_EL2 /* index 7 */ + write AMEVCNTVOFF18_EL2 /* index 8 */ + write AMEVCNTVOFF19_EL2 /* index 9 */ + write AMEVCNTVOFF1A_EL2 /* index 10 */ + write AMEVCNTVOFF1B_EL2 /* index 11 */ + write AMEVCNTVOFF1C_EL2 /* index 12 */ + write AMEVCNTVOFF1D_EL2 /* index 13 */ + write AMEVCNTVOFF1E_EL2 /* index 14 */ + write AMEVCNTVOFF1F_EL2 /* index 15 */ +endfunc amu_group1_voffset_write_internal +#endif diff --git a/arm-trusted-firmware/lib/extensions/amu/amu.mk b/arm-trusted-firmware/lib/extensions/amu/amu.mk new file mode 100644 index 0000000..0d203cb --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/amu.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/fconf/fconf.mk + +AMU_SOURCES := lib/extensions/amu/${ARCH}/amu.c \ + lib/extensions/amu/${ARCH}/amu_helpers.S + +ifneq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) + ifeq (${ENABLE_AMU},0) + $(error AMU auxiliary counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`) requires AMU support (`ENABLE_AMU`)) + endif +endif + +ifneq (${ENABLE_AMU_FCONF},0) + ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) + $(error AMU FCONF support (`ENABLE_AMU_FCONF`) is not necessary when auxiliary counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`) is disabled) + endif + + AMU_SOURCES += ${FCONF_AMU_SOURCES} +endif diff --git a/arm-trusted-firmware/lib/extensions/amu/amu_private.h b/arm-trusted-firmware/lib/extensions/amu/amu_private.h new file mode 100644 index 0000000..eb7ff0e --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/amu_private.h @@ -0,0 +1,38 @@ +/* + * 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 + +#include +#include +#include + +#include + +#define AMU_GROUP0_MAX_COUNTERS U(16) +#define AMU_GROUP1_MAX_COUNTERS U(16) + +#define AMU_AMCGCR_CG0NC_MAX U(16) + +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/arm-trusted-firmware/lib/extensions/mpam/mpam.c b/arm-trusted-firmware/lib/extensions/mpam/mpam.c new file mode 100644 index 0000000..65601dd --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/mpam/mpam.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +void mpam_enable(bool el2_unused) +{ + /* Check if MPAM is implemented */ + if (get_mpam_version() == 0U) { + return; + } + + /* + * Enable MPAM, and disable trapping to EL3 when lower ELs access their + * own MPAM registers. + */ + write_mpam3_el3(MPAM3_EL3_MPAMEN_BIT); + + /* + * If EL2 is implemented but unused, disable trapping to EL2 when lower + * ELs access their own MPAM registers. + * If EL2 is implemented and used, enable trapping to EL2. + */ + if (el2_unused) { + write_mpam2_el2(0ULL); + + if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) { + write_mpamhcr_el2(0ULL); + } + } else { + write_mpam2_el2(MPAM2_EL2_TRAPMPAM0EL1 | + MPAM2_EL2_TRAPMPAM1EL1); + + if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) { + write_mpamhcr_el2(MPAMHCR_EL2_TRAP_MPAMIDR_EL1); + } + } +} diff --git a/arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S b/arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S new file mode 100644 index 0000000..834cee3 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .global mtpmu_disable + +/* ------------------------------------------------------------- + * The functions in this file are called at entrypoint, before + * the CPU has decided whether this is a cold or a warm boot. + * Therefore there are no stack yet to rely on for a C function + * call. + * ------------------------------------------------------------- + */ + +/* + * bool mtpmu_supported(void) + * + * Return a boolean indicating whether FEAT_MTPMU is supported or not. + * + * Trash registers: r0. + */ +func mtpmu_supported + ldcopr r0, ID_DFR1 + and r0, r0, #(ID_DFR1_MTPMU_MASK >> ID_DFR1_MTPMU_SHIFT) + cmp r0, #ID_DFR1_MTPMU_SUPPORTED + mov r0, #0 + addeq r0, r0, #1 + bx lr +endfunc mtpmu_supported + +/* + * bool el_implemented(unsigned int el) + * + * Return a boolean indicating if the specified EL (2 or 3) is implemented. + * + * Trash registers: r0 + */ +func el_implemented + cmp r0, #3 + ldcopr r0, ID_PFR1 + lsreq r0, r0, #ID_PFR1_SEC_SHIFT + lsrne r0, r0, #ID_PFR1_VIRTEXT_SHIFT + /* + * ID_PFR1_VIRTEXT_MASK is the same as ID_PFR1_SEC_MASK + * so use any one of them + */ + and r0, r0, #ID_PFR1_VIRTEXT_MASK + cmp r0, #ID_PFR1_ELx_ENABLED + mov r0, #0 + addeq r0, r0, #1 + bx lr +endfunc el_implemented + +/* + * void mtpmu_disable(void) + * + * Disable mtpmu feature if supported. + * + * Trash register: r0, r1, r2 + */ +func mtpmu_disable + mov r2, lr + bl mtpmu_supported + cmp r0, #0 + bxeq r2 /* FEAT_MTPMU not supported */ + + /* FEAT_MTMPU Supported */ + mov r0, #3 + bl el_implemented + cmp r0, #0 + beq 1f + + /* EL3 implemented */ + ldcopr r0, SDCR + ldr r1, =SDCR_MTPME_BIT + bic r0, r0, r1 + stcopr r0, SDCR + + /* + * If EL3 is implemented, HDCR.MTPME is implemented as Res0 and + * FEAT_MTPMU is controlled only from EL3, so no need to perform + * any operations for EL2. + */ + isb + bx r2 +1: + /* EL3 not implemented */ + mov r0, #2 + bl el_implemented + cmp r0, #0 + bxeq r2 /* No EL2 or EL3 implemented */ + + /* EL2 implemented */ + ldcopr r0, HDCR + ldr r1, =HDCR_MTPME_BIT + orr r0, r0, r1 + stcopr r0, HDCR + isb + bx r2 +endfunc mtpmu_disable diff --git a/arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S b/arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S new file mode 100644 index 0000000..0a1d57b --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .global mtpmu_disable + +/* ------------------------------------------------------------- + * The functions in this file are called at entrypoint, before + * the CPU has decided whether this is a cold or a warm boot. + * Therefore there are no stack yet to rely on for a C function + * call. + * ------------------------------------------------------------- + */ + +/* + * bool mtpmu_supported(void) + * + * Return a boolean indicating whether FEAT_MTPMU is supported or not. + * + * Trash registers: x0, x1 + */ +func mtpmu_supported + mrs x0, id_aa64dfr0_el1 + mov_imm x1, ID_AA64DFR0_MTPMU_MASK + and x0, x1, x0, LSR #ID_AA64DFR0_MTPMU_SHIFT + cmp x0, ID_AA64DFR0_MTPMU_SUPPORTED + cset x0, eq + ret +endfunc mtpmu_supported + +/* + * bool el_implemented(unsigned int el_shift) + * + * Return a boolean indicating if the specified EL is implemented. + * The EL is represented as the bitmask shift on id_aa64pfr0_el1 register. + * + * Trash registers: x0, x1 + */ +func el_implemented + mrs x1, id_aa64pfr0_el1 + lsr x1, x1, x0 + cmp x1, #ID_AA64PFR0_ELX_MASK + cset x0, eq + ret +endfunc el_implemented + +/* + * void mtpmu_disable(void) + * + * Disable mtpmu feature if supported. + * + * Trash register: x0, x1, x30 + */ +func mtpmu_disable + mov x10, x30 + bl mtpmu_supported + cbz x0, exit_disable + + /* FEAT_MTMPU Supported */ + mov_imm x0, ID_AA64PFR0_EL3_SHIFT + bl el_implemented + cbz x0, 1f + + /* EL3 implemented */ + mrs x0, mdcr_el3 + mov_imm x1, MDCR_MTPME_BIT + bic x0, x0, x1 + msr mdcr_el3, x0 + + /* + * If EL3 is implemented, MDCR_EL2.MTPME is implemented as Res0 and + * FEAT_MTPMU is controlled only from EL3, so no need to perform + * any operations for EL2. + */ + isb +exit_disable: + ret x10 +1: + /* EL3 not implemented */ + mov_imm x0, ID_AA64PFR0_EL2_SHIFT + bl el_implemented + cbz x0, exit_disable + + /* EL2 implemented */ + mrs x0, mdcr_el2 + mov_imm x1, MDCR_EL2_MTPME + bic x0, x0, x1 + msr mdcr_el2, x0 + isb + ret x10 +endfunc mtpmu_disable diff --git a/arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S b/arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S new file mode 100644 index 0000000..d483c7d --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .global pauth_init_enable_el1 + .global pauth_disable_el1 + .global pauth_init_enable_el3 + .global pauth_disable_el3 + .globl pauth_load_bl31_apiakey + .globl pauth_load_bl1_apiakey_enable + +/* ------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication in EL1 + * ------------------------------------------------------------- + */ +func pauth_init_enable_el1 + stp x29, x30, [sp, #-16]! + + /* Initialize platform key */ + bl plat_init_apkey + + /* Program instruction key A used by the Trusted Firmware */ + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + + /* Enable pointer authentication */ + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_EnIA_BIT + +#if ENABLE_BTI + /* Enable PAC branch type compatibility */ + bic x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT) +#endif + msr sctlr_el1, x0 + isb + + ldp x29, x30, [sp], #16 + ret +endfunc pauth_init_enable_el1 + +/* ------------------------------------------------------------- + * Disable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_disable_el1 + mrs x0, sctlr_el1 + bic x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el1, x0 + isb + ret +endfunc pauth_disable_el1 + +/* ------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_init_enable_el3 + stp x29, x30, [sp, #-16]! + + /* Initialize platform key */ + bl plat_init_apkey + + /* Program instruction key A used by the Trusted Firmware */ + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + + /* Enable pointer authentication */ + mrs x0, sctlr_el3 + orr x0, x0, #SCTLR_EnIA_BIT + +#if ENABLE_BTI + /* Enable PAC branch type compatibility */ + bic x0, x0, #SCTLR_BT_BIT +#endif + msr sctlr_el3, x0 + isb + + ldp x29, x30, [sp], #16 + ret +endfunc pauth_init_enable_el3 + +/* ------------------------------------------------------------- + * Disable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_disable_el3 + mrs x0, sctlr_el3 + bic x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el3, x0 + isb + ret +endfunc pauth_disable_el3 + +/* ------------------------------------------------------------- + * The following functions strictly follow the AArch64 PCS + * to use x9-x17 (temporary caller-saved registers) to load + * the APIAKey_EL1 and enable pointer authentication. + * ------------------------------------------------------------- + */ +func pauth_load_bl31_apiakey + /* tpidr_el3 contains the address of cpu_data structure */ + mrs x9, tpidr_el3 + + /* Load apiakey from cpu_data */ + ldp x10, x11, [x9, #CPU_DATA_APIAKEY_OFFSET] + + /* Program instruction key A */ + msr APIAKeyLo_EL1, x10 + msr APIAKeyHi_EL1, x11 + isb + ret +endfunc pauth_load_bl31_apiakey + +func pauth_load_bl1_apiakey_enable + /* Load instruction key A used by the Trusted Firmware */ + adrp x9, bl1_apiakey + add x9, x9, :lo12:bl1_apiakey + ldp x10, x11, [x9] + + /* Program instruction key A */ + msr APIAKeyLo_EL1, x10 + msr APIAKeyHi_EL1, x11 + + /* Enable pointer authentication */ + mrs x9, sctlr_el3 + orr x9, x9, #SCTLR_EnIA_BIT + +#if ENABLE_BTI + /* Enable PAC branch type compatibility */ + bic x9, x9, #SCTLR_BT_BIT +#endif + msr sctlr_el3, x9 + isb + ret +endfunc pauth_load_bl1_apiakey_enable diff --git a/arm-trusted-firmware/lib/extensions/ras/ras_common.c b/arm-trusted-firmware/lib/extensions/ras/ras_common.c new file mode 100644 index 0000000..73fad54 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/ras/ras_common.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2018-2021, 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 + +#ifndef PLAT_RAS_PRI +# error Platform must define RAS priority value +#endif + +/* + * Function to convert architecturally-defined primary error code SERR, + * bits[7:0] from ERRSTATUS to its corresponding error string. + */ +const char *ras_serr_to_str(unsigned int serr) +{ + const char *str[ERROR_STATUS_NUM_SERR] = { + "No error", + "IMPLEMENTATION DEFINED error", + "Data value from (non-associative) internal memory", + "IMPLEMENTATION DEFINED pin", + "Assertion failure", + "Error detected on internal data path", + "Data value from associative memory", + "Address/control value from associative memory", + "Data value from a TLB", + "Address/control value from a TLB", + "Data value from producer", + "Address/control value from producer", + "Data value from (non-associative) external memory", + "Illegal address (software fault)", + "Illegal access (software fault)", + "Illegal state (software fault)", + "Internal data register", + "Internal control register", + "Error response from slave", + "External timeout", + "Internal timeout", + "Deferred error from slave not supported at master" + }; + + /* + * All other values are reserved. Reserved values might be defined + * in a future version of the architecture + */ + if (serr >= ERROR_STATUS_NUM_SERR) + return "unknown SERR"; + + return str[serr]; +} + +/* Handler that receives External Aborts on RAS-capable systems */ +int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ + unsigned int i, n_handled = 0; + int probe_data, ret; + struct err_record_info *info; + + const struct err_handler_data err_data = { + .version = ERR_HANDLER_VERSION, + .ea_reason = ea_reason, + .interrupt = 0, + .syndrome = (uint32_t) syndrome, + .flags = flags, + .cookie = cookie, + .handle = handle + }; + + for_each_err_record_info(i, info) { + assert(info->probe != NULL); + assert(info->handler != NULL); + + /* Continue probing until the record group signals no error */ + while (true) { + if (info->probe(info, &probe_data) == 0) + break; + + /* Handle error */ + ret = info->handler(info, probe_data, &err_data); + if (ret != 0) + return ret; + + n_handled++; + } + } + + return (n_handled != 0U) ? 1 : 0; +} + +#if EL3_EXCEPTION_HANDLING + +#ifndef PLAT_RAS_PRI +# error Platform must define RAS priority value +#endif + + +#if ENABLE_ASSERTIONS +static void assert_interrupts_sorted(void) +{ + unsigned int i, last; + struct ras_interrupt *start = ras_interrupt_mappings.intrs; + + if (ras_interrupt_mappings.num_intrs == 0UL) + return; + + last = start[0].intr_number; + for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) { + assert(start[i].intr_number > last); + last = start[i].intr_number; + } +} +#endif + +/* + * Given an RAS interrupt number, locate the registered handler and call it. If + * no handler was found for the interrupt number, this function panics. + */ +static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags, + void *handle, void *cookie) +{ + struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs; + struct ras_interrupt *selected = NULL; + int probe_data = 0; + int start, end, mid, ret __unused; + + const struct err_handler_data err_data = { + .version = ERR_HANDLER_VERSION, + .interrupt = intr_raw, + .flags = flags, + .cookie = cookie, + .handle = handle + }; + + assert(ras_interrupt_mappings.num_intrs > 0UL); + + start = 0; + end = (int)ras_interrupt_mappings.num_intrs - 1; + while (start <= end) { + mid = ((end + start) / 2); + if (intr_raw == ras_inrs[mid].intr_number) { + selected = &ras_inrs[mid]; + break; + } else if (intr_raw < ras_inrs[mid].intr_number) { + /* Move left */ + end = mid - 1; + } else { + /* Move right */ + start = mid + 1; + } + } + + if (selected == NULL) { + ERROR("RAS interrupt %u has no handler!\n", intr_raw); + panic(); + } + + if (selected->err_record->probe != NULL) { + ret = selected->err_record->probe(selected->err_record, &probe_data); + assert(ret != 0); + } + + /* Call error handler for the record group */ + assert(selected->err_record->handler != NULL); + (void) selected->err_record->handler(selected->err_record, probe_data, + &err_data); + + return 0; +} +#endif + +void __init ras_init(void) +{ +#if EL3_EXCEPTION_HANDLING + +#if ENABLE_ASSERTIONS + /* Check RAS interrupts are sorted */ + assert_interrupts_sorted(); +#endif + + /* Register RAS priority handler */ + ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler); + +#endif /* EL3_EXCEPTION_HANDLING */ +} diff --git a/arm-trusted-firmware/lib/extensions/ras/std_err_record.c b/arm-trusted-firmware/lib/extensions/ras/std_err_record.c new file mode 100644 index 0000000..c03fbbe --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/ras/std_err_record.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* + * Probe for error in memory-mapped registers containing error records + * implemented Standard Error Record format. Upon detecting an error, set probe + * data to the index of the record in error, and return 1; otherwise, return 0. + */ +int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data) +{ + unsigned int num_records, num_group_regs, i; + uint64_t gsr; + + assert(base != 0UL); + + /* Only 4K supported for now */ + assert(size_num_k == STD_ERR_NODE_SIZE_NUM_K); + + num_records = (unsigned int) + (mmio_read_32(ERR_DEVID(base, size_num_k)) & ERR_DEVID_MASK); + + /* A group register shows error status for 2^6 error records */ + num_group_regs = (num_records >> 6U) + 1U; + + /* Iterate through group registers to find a record in error */ + for (i = 0; i < num_group_regs; i++) { + gsr = mmio_read_64(ERR_GSR(base, size_num_k, i)); + if (gsr == 0ULL) + continue; + + /* Return the index of the record in error */ + if (probe_data != NULL) + *probe_data = (((int) (i << 6U)) + __builtin_ctzll(gsr)); + + return 1; + } + + return 0; +} + +/* + * Probe for error in System Registers where error records are implemented in + * Standard Error Record format. Upon detecting an error, set probe data to the + * index of the record in error, and return 1; otherwise, return 0. + */ +int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data) +{ + unsigned int i; + uint64_t status; + unsigned int max_idx __unused = + ((unsigned int) read_erridr_el1()) & ERRIDR_MASK; + + assert(idx_start < max_idx); + assert(check_u32_overflow(idx_start, num_idx) == 0); + assert((idx_start + num_idx - 1U) < max_idx); + + for (i = 0; i < num_idx; i++) { + /* Select the error record */ + ser_sys_select_record(idx_start + i); + + /* Retrieve status register from the error record */ + status = read_erxstatus_el1(); + + /* Check for valid field in status */ + if (ERR_STATUS_GET_FIELD(status, V) != 0U) { + if (probe_data != NULL) + *probe_data = (int) i; + return 1; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/lib/extensions/sme/sme.c b/arm-trusted-firmware/lib/extensions/sme/sme.c new file mode 100644 index 0000000..1c2b984 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/sme/sme.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +static bool feat_sme_supported(void) +{ + uint64_t features; + + features = read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_SME_SHIFT; + return (features & ID_AA64PFR1_EL1_SME_MASK) != 0U; +} + +static bool feat_sme_fa64_supported(void) +{ + uint64_t features; + + features = read_id_aa64smfr0_el1(); + return (features & ID_AA64SMFR0_EL1_FA64_BIT) != 0U; +} + +void sme_enable(cpu_context_t *context) +{ + u_register_t reg; + u_register_t cptr_el3; + el3_state_t *state; + + /* Make sure SME is implemented in hardware before continuing. */ + if (!feat_sme_supported()) { + return; + } + + /* Get the context state. */ + state = get_el3state_ctx(context); + + /* Enable SME in CPTR_EL3. */ + reg = read_ctx_reg(state, CTX_CPTR_EL3); + reg |= ESM_BIT; + write_ctx_reg(state, CTX_CPTR_EL3, reg); + + /* Set the ENTP2 bit in SCR_EL3 to enable access to TPIDR2_EL0. */ + reg = read_ctx_reg(state, CTX_SCR_EL3); + reg |= SCR_ENTP2_BIT; + write_ctx_reg(state, CTX_SCR_EL3, reg); + + /* Set CPTR_EL3.ESM bit so we can write SMCR_EL3 without trapping. */ + cptr_el3 = read_cptr_el3(); + write_cptr_el3(cptr_el3 | ESM_BIT); + + /* + * Set the max LEN value and FA64 bit. This register is set up globally + * to be the least restrictive, then lower ELs can restrict as needed + * using SMCR_EL2 and SMCR_EL1. + */ + reg = SMCR_ELX_LEN_MASK; + if (feat_sme_fa64_supported()) { + VERBOSE("[SME] FA64 enabled\n"); + reg |= SMCR_ELX_FA64_BIT; + } + write_smcr_el3(reg); + + /* Reset CPTR_EL3 value. */ + write_cptr_el3(cptr_el3); + + /* Enable SVE/FPU in addition to SME. */ + sve_enable(context); +} + +void sme_disable(cpu_context_t *context) +{ + u_register_t reg; + el3_state_t *state; + + /* Make sure SME is implemented in hardware before continuing. */ + if (!feat_sme_supported()) { + return; + } + + /* Get the context state. */ + state = get_el3state_ctx(context); + + /* Disable SME, SVE, and FPU since they all share registers. */ + reg = read_ctx_reg(state, CTX_CPTR_EL3); + reg &= ~ESM_BIT; /* Trap SME */ + reg &= ~CPTR_EZ_BIT; /* Trap SVE */ + reg |= TFP_BIT; /* Trap FPU/SIMD */ + write_ctx_reg(state, CTX_CPTR_EL3, reg); + + /* Disable access to TPIDR2_EL0. */ + reg = read_ctx_reg(state, CTX_SCR_EL3); + reg &= ~SCR_ENTP2_BIT; + write_ctx_reg(state, CTX_SCR_EL3, reg); +} diff --git a/arm-trusted-firmware/lib/extensions/spe/spe.c b/arm-trusted-firmware/lib/extensions/spe/spe.c new file mode 100644 index 0000000..d747efc --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/spe/spe.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +static inline void psb_csync(void) +{ + /* + * The assembler does not yet understand the psb csync mnemonic + * so use the equivalent hint instruction. + */ + __asm__ volatile("hint #17"); +} + +bool spe_supported(void) +{ + uint64_t features; + + features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT; + return (features & ID_AA64DFR0_PMS_MASK) > 0ULL; +} + +void spe_enable(bool el2_unused) +{ + uint64_t v; + + if (!spe_supported()) + return; + + if (el2_unused) { + /* + * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical + * profiling controls to EL2. + * + * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure + * state. Accesses to profiling buffer controls at + * Non-secure EL1 are not trapped to EL2. + */ + v = read_mdcr_el2(); + v &= ~MDCR_EL2_TPMS; + v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1); + write_mdcr_el2(v); + } + + /* + * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state + * and disabled in secure state. Accesses to SPE registers at + * S-EL1 generate trap exceptions to EL3. + * + * MDCR_EL3.EnPMSN (ARM v8.7): Do not trap access to PMSNEVFR_EL1 + * register at NS-EL1 or NS-EL2 to EL3 if FEAT_SPEv1p2 is implemented. + * Setting this bit to 1 doesn't have any effect on it when + * FEAT_SPEv1p2 not implemented. + */ + v = read_mdcr_el3(); + v |= MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT; + write_mdcr_el3(v); +} + +void spe_disable(void) +{ + uint64_t v; + + if (!spe_supported()) + return; + + /* Drain buffered data */ + psb_csync(); + dsbnsh(); + + /* Disable profiling buffer */ + v = read_pmblimitr_el1(); + v &= ~(1ULL << 0); + write_pmblimitr_el1(v); + isb(); +} + +static void *spe_drain_buffers_hook(const void *arg) +{ + if (!spe_supported()) + return (void *)-1; + + /* Drain buffered data */ + psb_csync(); + dsbnsh(); + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook); diff --git a/arm-trusted-firmware/lib/extensions/sve/sve.c b/arm-trusted-firmware/lib/extensions/sve/sve.c new file mode 100644 index 0000000..aa8904b --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/sve/sve.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* + * Converts SVE vector size restriction in bytes to LEN according to ZCR_EL3 documentation. + * VECTOR_SIZE = (LEN+1) * 128 + */ +#define CONVERT_SVE_LENGTH(x) (((x / 128) - 1)) + +static bool sve_supported(void) +{ + uint64_t features; + + features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT; + return (features & ID_AA64PFR0_SVE_MASK) == 1U; +} + +void sve_enable(cpu_context_t *context) +{ + u_register_t cptr_el3; + + if (!sve_supported()) { + return; + } + + cptr_el3 = read_ctx_reg(get_el3state_ctx(context), CTX_CPTR_EL3); + + /* Enable access to SVE functionality for all ELs. */ + cptr_el3 = (cptr_el3 | CPTR_EZ_BIT) & ~(TFP_BIT); + write_ctx_reg(get_el3state_ctx(context), CTX_CPTR_EL3, cptr_el3); + + /* Restrict maximum SVE vector length (SVE_VECTOR_LENGTH+1) * 128. */ + write_ctx_reg(get_el3state_ctx(context), CTX_ZCR_EL3, + (ZCR_EL3_LEN_MASK & CONVERT_SVE_LENGTH(512))); +} + +void sve_disable(cpu_context_t *context) +{ + u_register_t reg; + el3_state_t *state; + + /* Make sure SME is implemented in hardware before continuing. */ + if (!sve_supported()) { + return; + } + + /* Get the context state. */ + state = get_el3state_ctx(context); + + /* Disable SVE and FPU since they share registers. */ + reg = read_ctx_reg(state, CTX_CPTR_EL3); + reg &= ~CPTR_EZ_BIT; /* Trap SVE */ + reg |= TFP_BIT; /* Trap FPU/SIMD */ + write_ctx_reg(state, CTX_CPTR_EL3, reg); +} diff --git a/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c b/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c new file mode 100644 index 0000000..89b8029 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bool sys_reg_trace_supported(void) +{ + uint32_t features; + + features = read_id_dfr0() >> ID_DFR0_COPTRC_SHIFT; + return ((features & ID_DFR0_COPTRC_MASK) == + ID_DFR0_COPTRC_SUPPORTED); +} + +void sys_reg_trace_enable(void) +{ + uint32_t val; + + if (sys_reg_trace_supported()) { + /* + * NSACR.NSTRCDIS = b0 + * enable NS system register access to implemented trace + * registers. + */ + val = read_nsacr(); + val &= ~NSTRCDIS_BIT; + write_nsacr(val); + } +} diff --git a/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c b/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c new file mode 100644 index 0000000..960d698 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bool sys_reg_trace_supported(void) +{ + uint64_t features; + + features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEVER_SHIFT; + return ((features & ID_AA64DFR0_TRACEVER_MASK) == + ID_AA64DFR0_TRACEVER_SUPPORTED); +} + +void sys_reg_trace_enable(cpu_context_t *ctx) +{ + uint64_t val; + + if (sys_reg_trace_supported()) { + /* Retrieve CPTR_EL3 value from the given context 'ctx', + * and update CPTR_EL3.TTA bit to 0. + * This function is called while switching context to NS to + * allow system trace register access to NS-EL2 and NS-EL1 + * when NS-EL2 is implemented but not used. + */ + val = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3); + val &= ~TTA_BIT; + write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, val); + } +} diff --git a/arm-trusted-firmware/lib/extensions/trbe/trbe.c b/arm-trusted-firmware/lib/extensions/trbe/trbe.c new file mode 100644 index 0000000..9f754d5 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/trbe/trbe.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static void tsb_csync(void) +{ + /* + * The assembler does not yet understand the tsb csync mnemonic + * so use the equivalent hint instruction. + */ + __asm__ volatile("hint #18"); +} + +static bool trbe_supported(void) +{ + uint64_t features; + + features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT; + return ((features & ID_AA64DFR0_TRACEBUFFER_MASK) == + ID_AA64DFR0_TRACEBUFFER_SUPPORTED); +} + +void trbe_enable(void) +{ + uint64_t val; + + if (trbe_supported()) { + /* + * MDCR_EL3.NSTB = 0b11 + * Allow access of trace buffer control registers from NS-EL1 + * and NS-EL2, tracing is prohibited in Secure and Realm state + * (if implemented). + */ + val = read_mdcr_el3(); + val |= MDCR_NSTB(MDCR_NSTB_EL1); + write_mdcr_el3(val); + } +} + +static void *trbe_drain_trace_buffers_hook(const void *arg __unused) +{ + if (trbe_supported()) { + /* + * Before switching from normal world to secure world + * the trace buffers need to be drained out to memory. This is + * required to avoid an invalid memory access when TTBR is switched + * for entry to S-EL1. + */ + tsb_csync(); + dsbnsh(); + } + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(cm_entering_secure_world, trbe_drain_trace_buffers_hook); diff --git a/arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c b/arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c new file mode 100644 index 0000000..834092d --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bool trf_supported(void) +{ + uint32_t features; + + features = read_id_dfr0() >> ID_DFR0_TRACEFILT_SHIFT; + return ((features & ID_DFR0_TRACEFILT_MASK) == + ID_DFR0_TRACEFILT_SUPPORTED); +} + +void trf_enable(void) +{ + uint32_t val; + + if (trf_supported()) { + /* + * Allow access of trace filter control registers from + * non-monitor mode + */ + val = read_sdcr(); + val &= ~SDCR_TTRF_BIT; + write_sdcr(val); + } +} diff --git a/arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c b/arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c new file mode 100644 index 0000000..1da5dce --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bool trf_supported(void) +{ + uint64_t features; + + features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT; + return ((features & ID_AA64DFR0_TRACEFILT_MASK) == + ID_AA64DFR0_TRACEFILT_SUPPORTED); +} + +void trf_enable(void) +{ + uint64_t val; + + if (trf_supported()) { + /* + * MDCR_EL3.TTRF = b0 + * Allow access of trace filter control registers from NS-EL2 + * and NS-EL1 when NS-EL2 is implemented but not used + */ + val = read_mdcr_el3(); + val &= ~MDCR_TTRF_BIT; + write_mdcr_el3(val); + } +} diff --git a/arm-trusted-firmware/lib/fconf/fconf.c b/arm-trusted-firmware/lib/fconf/fconf.c new file mode 100644 index 0000000..b1d6eaa --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +int fconf_load_config(unsigned int image_id) +{ + int err; + const struct dyn_cfg_dtb_info_t *config_info; + + assert((image_id == FW_CONFIG_ID) || (image_id == TB_FW_CONFIG_ID)); + + image_info_t config_image_info = { + .h.type = (uint8_t)PARAM_IMAGE_BINARY, + .h.version = (uint8_t)VERSION_2, + .h.size = (uint16_t)sizeof(image_info_t), + .h.attr = 0 + }; + + config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_id); + assert(config_info != NULL); + + config_image_info.image_base = config_info->config_addr; + config_image_info.image_max_size = config_info->config_max_size; + + VERBOSE("FCONF: Loading config with image ID: %u\n", image_id); + err = load_auth_image(image_id, &config_image_info); + if (err != 0) { + VERBOSE("Failed to load config %u\n", image_id); + return err; + } + + INFO("FCONF: Config file with image ID:%u loaded at address = 0x%lx\n", + image_id, config_image_info.image_base); + + return 0; +} + +void fconf_populate(const char *config_type, uintptr_t config) +{ + assert(config != 0UL); + + /* Check if the pointer to DTB is correct */ + if (fdt_check_header((void *)config) != 0) { + ERROR("FCONF: Invalid DTB file passed for %s\n", config_type); + panic(); + } + + INFO("FCONF: Reading %s firmware configuration file from: 0x%lx\n", config_type, config); + + /* Go through all registered populate functions */ + IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_START__, start); + IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_END__, end); + const struct fconf_populator *populator; + + for (populator = start; populator != end; populator++) { + assert((populator->info != NULL) && (populator->populate != NULL)); + + if (strcmp(populator->config_type, config_type) == 0) { + INFO("FCONF: Reading firmware configuration information for: %s\n", populator->info); + if (populator->populate(config) != 0) { + /* TODO: handle property miss */ + panic(); + } + } + } +} diff --git a/arm-trusted-firmware/lib/fconf/fconf.mk b/arm-trusted-firmware/lib/fconf/fconf.mk new file mode 100644 index 0000000..fb88910 --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2019-2021, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +FCONF_SOURCES := lib/fconf/fconf.c +FCONF_SOURCES += ${FDT_WRAPPERS_SOURCES} + +FCONF_DYN_SOURCES := lib/fconf/fconf_dyn_cfg_getter.c +FCONF_DYN_SOURCES += ${FDT_WRAPPERS_SOURCES} + +FCONF_AMU_SOURCES := lib/fconf/fconf_amu_getter.c +FCONF_AMU_SOURCES += ${FDT_WRAPPERS_SOURCES} + +FCONF_MPMM_SOURCES := lib/fconf/fconf_mpmm_getter.c +FCONF_MPMM_SOURCES += ${FDT_WRAPPERS_SOURCES} diff --git a/arm-trusted-firmware/lib/fconf/fconf_amu_getter.c b/arm-trusted-firmware/lib/fconf/fconf_amu_getter.c new file mode 100644 index 0000000..eff309c --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_amu_getter.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +struct fconf_amu_config fconf_amu_config; +static struct amu_topology fconf_amu_topology_; + +/* + * Populate the core-specific AMU structure with information retrieved from a + * device tree. + * + * Returns `0` on success, or a negative integer representing an error code. + */ +static int fconf_populate_amu_cpu_amu(const void *fdt, int parent, + struct amu_core *amu) +{ + int ret = 0; + int node = 0; + + fdt_for_each_subnode(node, fdt, parent) { + const char *name; + const char *value; + int len; + + uintptr_t idx = 0U; + + name = fdt_get_name(fdt, node, &len); + if (strncmp(name, "counter@", 8) != 0) { + continue; + } + + ret = fdt_get_reg_props_by_index(fdt, node, 0, &idx, NULL); + if (ret < 0) { + break; + } + + value = fdt_getprop(fdt, node, "enable-at-el3", &len); + if ((value == NULL) && (len != -FDT_ERR_NOTFOUND)) { + break; + } + + if (len != -FDT_ERR_NOTFOUND) { + amu->enable |= (1 << idx); + } + } + + if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { + return node; + } + + return ret; +} + +/* + * Within a `cpu` node, attempt to dereference the `amu` property, and populate + * the AMU information for the core. + * + * Returns `0` on success, or a negative integer representing an error code. + */ +static int fconf_populate_amu_cpu(const void *fdt, int node, uintptr_t mpidr) +{ + int ret; + int idx; + + uint32_t amu_phandle; + struct amu_core *amu; + + ret = fdt_read_uint32(fdt, node, "amu", &amu_phandle); + if (ret < 0) { + if (ret == -FDT_ERR_NOTFOUND) { + ret = 0; + } + + return ret; + } + + node = fdt_node_offset_by_phandle(fdt, amu_phandle); + if (node < 0) { + return node; + } + + idx = plat_core_pos_by_mpidr(mpidr); + if (idx < 0) { + return -FDT_ERR_BADVALUE; + } + + amu = &fconf_amu_topology_.cores[idx]; + + return fconf_populate_amu_cpu_amu(fdt, node, amu); +} + +/* + * Populates the global `amu_topology` structure based on what's described by + * the hardware configuration device tree blob. + * + * The device tree is expected to provide an `amu` property for each `cpu` node, + * like so: + * + * cpu@0 { + * amu = <&cpu0_amu>; + * }; + * + * amus { + * cpu0_amu: amu-0 { + * counters { + * #address-cells = <2>; + * #size-cells = <0>; + * + * counter@x,y { + * reg = ; // Group x, counter y + * }; + * }; + * }; + * }; + */ +static int fconf_populate_amu(uintptr_t config) +{ + int ret = fdtw_for_each_cpu( + (const void *)config, fconf_populate_amu_cpu); + if (ret == 0) { + fconf_amu_config.topology = &fconf_amu_topology_; + } else { + ERROR("FCONF: failed to parse AMU information: %d\n", ret); + } + + return ret; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, amu, fconf_populate_amu); diff --git a/arm-trusted-firmware/lib/fconf/fconf_cot_getter.c b/arm-trusted-firmware/lib/fconf/fconf_cot_getter.c new file mode 100644 index 0000000..ae59d8c --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_cot_getter.c @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include MBEDTLS_CONFIG_FILE +#include +#include +#include +#include + +#include + +/* static structures used during authentication process */ +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + +/* pointers to an array of CoT descriptors */ +static const auth_img_desc_t *cot_desc[MAX_NUMBER_IDS]; +/* array of CoT descriptors */ +static auth_img_desc_t auth_img_descs[MAX_NUMBER_IDS]; + +/* array of authentication methods structures */ +static auth_method_desc_t auth_methods[MAX_NUMBER_IDS * AUTH_METHOD_NUM]; +static OBJECT_POOL_ARRAY(auth_methods_pool, auth_methods); + +/* array of authentication params structures */ +static auth_param_desc_t auth_params[MAX_NUMBER_IDS * COT_MAX_VERIFIED_PARAMS]; +static OBJECT_POOL_ARRAY(auth_params_pool, auth_params); + +/* array of authentication param type structures */ +static auth_param_type_desc_t auth_param_type_descs[MAX_NUMBER_IDS]; +static OBJECT_POOL_ARRAY(auth_param_type_descs_pool, auth_param_type_descs); + +/* + * array of OIDs + * Object IDs are used to search hash, pk, counter values in certificate. + * As per binding we have below 2 combinations: + * 1. Certificates are validated using nv-cntr and pk + * 2. Raw images are authenticated using hash + * Hence in worst case, there are maximum 2 OIDs per image/certificate + */ +static unsigned char oids[(MAX_NUMBER_IDS * 2)][MAX_OID_NAME_LEN]; +static OBJECT_POOL_ARRAY(oid_pool, oids); + +/* An array of auth buffer which holds hashes and pk + * ToDo: Size decided with the current number of images and + * certificates which are available in CoT. Size of these buffers bound to + * increase in the future on the addition of images/certificates. + */ +static unsigned char hash_auth_bufs[20][HASH_DER_LEN]; +static OBJECT_POOL_ARRAY(hash_auth_buf_pool, hash_auth_bufs); +static unsigned char pk_auth_bufs[12][PK_DER_LEN]; +static OBJECT_POOL_ARRAY(pk_auth_buf_pool, pk_auth_bufs); + +/******************************************************************************* + * update_parent_auth_data() - Update authentication data structure + * @auth_desc[in]: Pointer to the auth image descriptor + * @type_desc[in]: Pointer to authentication parameter + * @auth_buf_size[in]: Buffer size to hold pk or hash + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int update_parent_auth_data(const auth_img_desc_t *auth_desc, + auth_param_type_desc_t *type_desc, + unsigned int auth_buf_size) +{ + unsigned int i; + auth_param_desc_t *auth_data = &auth_desc->authenticated_data[0]; + unsigned char *auth_buf; + + for (i = 0U; i < COT_MAX_VERIFIED_PARAMS; i++) { + if (auth_data[i].type_desc == type_desc) { + return 0; + } + if (auth_data[i].type_desc == NULL) { + break; + } + } + + if (auth_buf_size == HASH_DER_LEN) { + auth_buf = pool_alloc(&hash_auth_buf_pool); + } else if (auth_buf_size == PK_DER_LEN) { + auth_buf = pool_alloc(&pk_auth_buf_pool); + } else { + return -1; + } + + if (i < COT_MAX_VERIFIED_PARAMS) { + auth_data[i].type_desc = type_desc; + auth_data[i].data.ptr = auth_buf; + auth_data[i].data.len = auth_buf_size; + } else { + ERROR("Out of authentication data array\n"); + return -1; + } + + return 0; +} + +/******************************************************************************* + * get_auth_param_type_desc() - Get pointer of authentication parameter + * @img_id[in]: Image Id + * @type_desc[out]: Pointer to authentication parameter + * @buf_size[out]: Buffer size which hold hash/pk + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int get_auth_param_type_desc(unsigned int img_id, + auth_param_type_desc_t **type_desc, + unsigned int *buf_size) +{ + auth_method_desc_t *img_auth_method = NULL; + img_type_t type = auth_img_descs[img_id].img_type; + + if (type == IMG_CERT) { + img_auth_method = + &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_SIG]; + *type_desc = img_auth_method->param.sig.pk; + *buf_size = PK_DER_LEN; + } else if (type == IMG_RAW) { + img_auth_method = + &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_HASH]; + *type_desc = img_auth_method->param.hash.hash; + *buf_size = HASH_DER_LEN; + } else { + return -1; + } + + return 0; +} + +/******************************************************************************* + * set_auth_method() - Update global auth image descriptors with authentication + * method data + * @auth_method_type[in]: Type of authentication method + * @oid[in]: Object Idetifier for pk/hash search + * @auth_method[in]: Pointer to authentication method to set + ******************************************************************************/ +static void set_auth_method(auth_method_type_t auth_method_type, char *oid, + auth_method_desc_t *auth_method) +{ + auth_param_type_t auth_param_type = AUTH_PARAM_NONE; + auth_param_type_desc_t *auth_param_type_desc; + + assert(auth_method != NULL); + + auth_param_type_desc = pool_alloc(&auth_param_type_descs_pool); + auth_method->type = auth_method_type; + + if (auth_method_type == AUTH_METHOD_SIG) { + auth_param_type = AUTH_PARAM_PUB_KEY; + auth_method->param.sig.sig = &sig; + auth_method->param.sig.alg = &sig_alg; + auth_method->param.sig.data = &raw_data; + auth_method->param.sig.pk = auth_param_type_desc; + } else if (auth_method_type == AUTH_METHOD_HASH) { + auth_param_type = AUTH_PARAM_HASH; + auth_method->param.hash.data = &raw_data; + auth_method->param.hash.hash = auth_param_type_desc; + } else if (auth_method_type == AUTH_METHOD_NV_CTR) { + auth_param_type = AUTH_PARAM_NV_CTR; + auth_method->param.nv_ctr.cert_nv_ctr = auth_param_type_desc; + auth_method->param.nv_ctr.plat_nv_ctr = auth_param_type_desc; + } + + auth_param_type_desc->type = auth_param_type; + auth_param_type_desc->cookie = (void *)oid; +} + +/******************************************************************************* + * get_oid() - get object identifier from device tree + * @dtb[in]: Pointer to the device tree blob in memory + * @node[in]: Offset of the node + * @prop[in]: Property to read from the given node + * @oid[out]: Object Indentifier of key/hash/nv-counter in certificate + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int get_oid(const void *dtb, int node, const char *prop, char **oid) +{ + uint32_t phandle; + int rc; + + rc = fdt_read_uint32(dtb, node, prop, &phandle); + if (rc < 0) { + return rc; + } + + node = fdt_node_offset_by_phandle(dtb, phandle); + if (node < 0) { + return node; + } + + *oid = pool_alloc(&oid_pool); + rc = fdtw_read_string(dtb, node, "oid", *oid, MAX_OID_NAME_LEN); + + return rc; +} + +/******************************************************************************* + * populate_and_set_auth_methods() - Populate auth method parameters from + * device tree and set authentication method + * structure. + * @dtb[in]: Pointer to the device tree blob in memory + * @node[in]: Offset of the node + * @img_id[in]: Image identifier + * @type[in]: Type of image + * @root_certificate[in]:Root certificate (authenticated by ROTPK) + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int populate_and_set_auth_methods(const void *dtb, int node, + unsigned int img_id, img_type_t type, + bool root_certificate) +{ + auth_method_type_t auth_method_type = AUTH_METHOD_NONE; + int rc; + char *oid = NULL; + + auth_method_desc_t *auth_method = pool_alloc_n(&auth_methods_pool, + AUTH_METHOD_NUM); + + /* + * This is as per binding document where certificates are + * verified by signature and images are verified by hash. + */ + if (type == IMG_CERT) { + if (root_certificate) { + oid = NULL; + } else { + rc = get_oid(dtb, node, "signing-key", &oid); + if (rc < 0) { + ERROR("FCONF: Can't read %s property\n", + "signing-key"); + return rc; + } + } + auth_method_type = AUTH_METHOD_SIG; + } else if (type == IMG_RAW) { + rc = get_oid(dtb, node, "hash", &oid); + if (rc < 0) { + ERROR("FCONF: Can't read %s property\n", + "hash"); + return rc; + } + auth_method_type = AUTH_METHOD_HASH; + } else { + return -1; + } + + set_auth_method(auth_method_type, oid, + &auth_method[auth_method_type]); + + /* Retrieve the optional property */ + rc = get_oid(dtb, node, "antirollback-counter", &oid); + if (rc == 0) { + auth_method_type = AUTH_METHOD_NV_CTR; + set_auth_method(auth_method_type, oid, + &auth_method[auth_method_type]); + } + + auth_img_descs[img_id].img_auth_methods = &auth_method[0]; + + return 0; +} + +/******************************************************************************* + * get_parent_img_id() - Get parent image id for given child node + * @dtb[in]: Pointer to the device tree blob in memory + * @node[in]: Offset of the child node + * @parent_img_id[out]: Image id of parent + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int get_parent_img_id(const void *dtb, int node, + unsigned int *parent_img_id) +{ + uint32_t phandle; + int err; + + err = fdt_read_uint32(dtb, node, "parent", &phandle); + if (err < 0) { + ERROR("FCONF: Could not read %s property in node\n", + "parent"); + return err; + } + + node = fdt_node_offset_by_phandle(dtb, phandle); + if (node < 0) { + ERROR("FCONF: Failed to locate node using its phandle\n"); + return node; + } + + err = fdt_read_uint32(dtb, node, "image-id", parent_img_id); + if (err < 0) { + ERROR("FCONF: Could not read %s property in node\n", + "image-id"); + } + + return err; +} + +/******************************************************************************* + * set_desc_data() - Update data in descriptor's structure + * @dtb[in]: Pointer to the device tree blob in memory + * @node[in]: Offset of the node + * @type[in]: Type of image (RAW/CERT) + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int set_desc_data(const void *dtb, int node, img_type_t type) +{ + int rc; + bool root_certificate = false; + unsigned int img_id, parent_img_id; + + rc = fdt_read_uint32(dtb, node, "image-id", &img_id); + if (rc < 0) { + ERROR("FCONF: Can't find property %s in node\n", + "image-id"); + return rc; + } + + if (fdt_getprop(dtb, node, "root-certificate", + NULL) != NULL) { + root_certificate = true; + } + + if (!root_certificate) { + rc = get_parent_img_id(dtb, node, &parent_img_id); + if (rc < 0) { + return rc; + } + auth_img_descs[img_id].parent = &auth_img_descs[parent_img_id]; + } + + auth_img_descs[img_id].img_id = img_id; + auth_img_descs[img_id].img_type = type; + + rc = populate_and_set_auth_methods(dtb, node, img_id, type, + root_certificate); + if (rc < 0) { + return rc; + } + + if (type == IMG_CERT) { + auth_param_desc_t *auth_param = + pool_alloc_n(&auth_params_pool, + COT_MAX_VERIFIED_PARAMS); + auth_img_descs[img_id].authenticated_data = &auth_param[0]; + } + + cot_desc[img_id] = &auth_img_descs[img_id]; + + return rc; +} + +/******************************************************************************* + * populate_manifest_descs() - Populate CoT descriptors and update global + * certificate structures + * @dtb[in]: Pointer to the device tree blob in memory + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int populate_manifest_descs(const void *dtb) +{ + int node, child; + int rc; + + /* + * Assert the node offset points to "arm, cert-descs" + * compatible property + */ + const char *compatible_str = "arm, cert-descs"; + + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find %s compatible in node\n", + compatible_str); + return node; + } + + fdt_for_each_subnode(child, dtb, node) { + rc = set_desc_data(dtb, child, IMG_CERT); + if (rc < 0) { + return rc; + } + } + + return 0; +} + +/******************************************************************************* + * populate_image_descs() - Populate CoT descriptors and update global + * image descriptor structures. + * @dtb[in]: Pointer to the device tree blob in memory + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int populate_image_descs(const void *dtb) +{ + int node, child; + int rc; + + /* + * Assert the node offset points to "arm, img-descs" + * compatible property + */ + const char *compatible_str = "arm, img-descs"; + + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find %s compatible in node\n", + compatible_str); + return node; + } + + fdt_for_each_subnode(child, dtb, node) { + rc = set_desc_data(dtb, child, IMG_RAW); + if (rc < 0) { + return rc; + } + } + + return 0; +} + +/******************************************************************************* + * fconf_populate_cot_descs() - Populate CoT descriptors and update global + * structures + * @config[in]: Pointer to the device tree blob in memory + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int fconf_populate_cot_descs(uintptr_t config) +{ + auth_param_type_desc_t *type_desc = NULL; + unsigned int auth_buf_size = 0U; + int rc; + + /* As libfdt uses void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* populate manifest descs information */ + rc = populate_manifest_descs(dtb); + if (rc < 0) { + ERROR("FCONF: population of %s descs failed %d\n", + "manifest", rc); + return rc; + } + + /* populate image descs information */ + rc = populate_image_descs(dtb); + if (rc < 0) { + ERROR("FCONF: population of %s descs failed %d\n", + "images", rc); + return rc; + } + + /* update parent's authentication data */ + for (unsigned int i = 0U; i < MAX_NUMBER_IDS; i++) { + if (auth_img_descs[i].parent != NULL) { + rc = get_auth_param_type_desc(i, + &type_desc, + &auth_buf_size); + if (rc < 0) { + ERROR("FCONF: failed to get auth data %d\n", + rc); + return rc; + } + + rc = update_parent_auth_data(auth_img_descs[i].parent, + type_desc, + auth_buf_size); + if (rc < 0) { + ERROR("FCONF: auth data update failed %d\n", + rc); + return rc; + } + } + } + + return rc; +} + +FCONF_REGISTER_POPULATOR(TB_FW, cot_desc, fconf_populate_cot_descs); +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c b/arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c new file mode 100644 index 0000000..34623fb --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NT_FW and HW configs */ +#define MAX_DTB_INFO U(6) +/* + * Compile time assert if FW_CONFIG_ID is 0 which is more + * unlikely as 0 is a valid image ID for FIP as per the current + * code but still to avoid code breakage in case of unlikely + * event when image IDs get changed. + */ +CASSERT(FW_CONFIG_ID != U(0), assert_invalid_fw_config_id); + +static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO]; +static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos); + +/* + * This function is used to alloc memory for config information from + * global pool and set the configuration information. + */ +void set_config_info(uintptr_t config_addr, uint32_t config_max_size, + unsigned int config_id) +{ + struct dyn_cfg_dtb_info_t *dtb_info; + + dtb_info = pool_alloc(&dtb_info_pool); + dtb_info->config_addr = config_addr; + dtb_info->config_max_size = config_max_size; + dtb_info->config_id = config_id; +} + +/* Get index of the config_id image */ +unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id) +{ + unsigned int index; + + /* Positions index to the proper config-id */ + for (index = 0U; index < MAX_DTB_INFO; index++) { + if (dtb_infos[index].config_id == config_id) { + return index; + } + } + + return FCONF_INVALID_IDX; +} + +struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id) +{ + /* Positions index to the proper config-id */ + unsigned int index = dyn_cfg_dtb_info_get_index(config_id); + + if (index < MAX_DTB_INFO) { + return &dtb_infos[index]; + } + + WARN("FCONF: Invalid config id %u\n", config_id); + + return NULL; +} + +int fconf_populate_dtb_registry(uintptr_t config) +{ + int rc; + int node, child; + + /* As libfdt use void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* + * In case of BL1, fw_config dtb information is already + * populated in global dtb_infos array by 'set_fw_config_info' + * function, Below check is present to avoid re-population of + * fw_config information. + * + * Other BLs, satisfy below check and populate fw_config information + * in global dtb_infos array. + */ + if (dtb_infos[0].config_id == 0U) { + uint32_t config_max_size = fdt_totalsize(dtb); + set_config_info(config, config_max_size, FW_CONFIG_ID); + } + + /* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */ + const char *compatible_str = "fconf,dyn_cfg-dtb_registry"; + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); + return node; + } + + fdt_for_each_subnode(child, dtb, node) { + uint32_t config_max_size, config_id; + uintptr_t config_addr; + uint64_t val64; + + /* Read configuration dtb information */ + rc = fdt_read_uint64(dtb, child, "load-address", &val64); + if (rc < 0) { + ERROR("FCONF: Incomplete configuration property in dtb-registry.\n"); + return rc; + } + config_addr = (uintptr_t)val64; + + rc = fdt_read_uint32(dtb, child, "max-size", &config_max_size); + if (rc < 0) { + ERROR("FCONF: Incomplete configuration property in dtb-registry.\n"); + return rc; + } + + rc = fdt_read_uint32(dtb, child, "id", &config_id); + if (rc < 0) { + ERROR("FCONF: Incomplete configuration property in dtb-registry.\n"); + return rc; + } + + VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n"); + VERBOSE("\tload-address = %lx\n", config_addr); + VERBOSE("\tmax-size = 0x%x\n", config_max_size); + VERBOSE("\tconfig-id = %u\n", config_id); + + set_config_info(config_addr, config_max_size, config_id); + } + + if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) { + ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node); + return child; + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(FW_CONFIG, dyn_cfg, fconf_populate_dtb_registry); diff --git a/arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c b/arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c new file mode 100644 index 0000000..02a566d --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +struct fconf_mpmm_config fconf_mpmm_config; +static struct mpmm_topology fconf_mpmm_topology; + +/* + * Within a `cpu` node, determine support for MPMM via the `supports-mpmm` + * property. + * + * Returns `0` on success, or a negative integer representing an error code. + */ +static int fconf_populate_mpmm_cpu(const void *fdt, int off, uintptr_t mpidr) +{ + int ret, len; + + int core_pos; + struct mpmm_core *core; + + core_pos = plat_core_pos_by_mpidr(mpidr); + if (core_pos < 0) { + return -FDT_ERR_BADVALUE; + } + + core = &fconf_mpmm_topology.cores[core_pos]; + + fdt_getprop(fdt, off, "supports-mpmm", &len); + if (len >= 0) { + core->supported = true; + ret = 0; + } else { + core->supported = false; + ret = len; + } + + return ret; +} + +/* + * Populates the global `fconf_mpmm_config` structure based on what's described + * by the hardware configuration device tree blob. + * + * The device tree is expected to provide a `supports-mpmm` property for each + * `cpu` node, like so: + * + * cpu@0 { + * supports-mpmm; + * }; + * + * This property indicates whether the core implements MPMM, as we cannot detect + * support for it dynamically. + */ +static int fconf_populate_mpmm(uintptr_t config) +{ + int ret = fdtw_for_each_cpu( + (const void *)config, fconf_populate_mpmm_cpu); + if (ret == 0) { + fconf_mpmm_config.topology = &fconf_mpmm_topology; + } else { + ERROR("FCONF: failed to configure MPMM: %d\n", ret); + } + + return ret; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, mpmm, fconf_populate_mpmm); diff --git a/arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c b/arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c new file mode 100644 index 0000000..6f043e6 --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include +#include + +struct tbbr_dyn_config_t tbbr_dyn_config; + +int fconf_populate_tbbr_dyn_config(uintptr_t config) +{ + int err; + int node; + uint64_t val64; + uint32_t val32; + + /* As libfdt use void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* Assert the node offset point to "arm,tb_fw" compatible property */ + const char *compatible_str = "arm,tb_fw"; + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find `%s` compatible in dtb\n", + compatible_str); + return node; + } + + /* Locate the disable_auth cell and read the value */ + err = fdt_read_uint32(dtb, node, "disable_auth", + &tbbr_dyn_config.disable_auth); + if (err < 0) { + WARN("FCONF: Read %s failed for `%s`\n", + "cell", "disable_auth"); + return err; + } + + /* Check if the value is boolean */ + if ((tbbr_dyn_config.disable_auth != 0U) && + (tbbr_dyn_config.disable_auth != 1U)) { + WARN("Invalid value for `%s` cell %d\n", + "disable_auth", tbbr_dyn_config.disable_auth); + return -1; + } + +#if defined(DYN_DISABLE_AUTH) + if (tbbr_dyn_config.disable_auth == 1) + dyn_disable_auth(); +#endif + + /* Retrieve the Mbed TLS heap details from the DTB */ + err = fdt_read_uint64(dtb, node, "mbedtls_heap_addr", &val64); + if (err < 0) { + ERROR("FCONF: Read %s failed for `%s`\n", + "cell", "mbedtls_heap_addr"); + return err; + } + tbbr_dyn_config.mbedtls_heap_addr = (void *)(uintptr_t)val64; + + err = fdt_read_uint32(dtb, node, "mbedtls_heap_size", &val32); + if (err < 0) { + ERROR("FCONF: Read %s failed for `%s`\n", + "cell", "mbedtls_heap_size"); + return err; + } + tbbr_dyn_config.mbedtls_heap_size = val32; + + VERBOSE("%s%s%s %d\n", "FCONF: `tbbr.", "disable_auth", + "` cell found with value =", tbbr_dyn_config.disable_auth); + VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr", + "` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr); + VERBOSE("%s%s%s %zu\n", "FCONF: `tbbr.", "mbedtls_heap_size", + "` cell found with value =", tbbr_dyn_config.mbedtls_heap_size); + + return 0; +} + +FCONF_REGISTER_POPULATOR(TB_FW, tbbr, fconf_populate_tbbr_dyn_config); diff --git a/arm-trusted-firmware/lib/gpt_rme/gpt_rme.c b/arm-trusted-firmware/lib/gpt_rme/gpt_rme.c new file mode 100644 index 0000000..d6fbc04 --- /dev/null +++ b/arm-trusted-firmware/lib/gpt_rme/gpt_rme.c @@ -0,0 +1,1255 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "gpt_rme_private.h" +#include +#include +#include +#include + +#if !ENABLE_RME +#error "ENABLE_RME must be enabled to use the GPT library." +#endif + +/* + * Lookup T from PPS + * + * PPS Size T + * 0b000 4GB 32 + * 0b001 64GB 36 + * 0b010 1TB 40 + * 0b011 4TB 42 + * 0b100 16TB 44 + * 0b101 256TB 48 + * 0b110 4PB 52 + * + * See section 15.1.27 of the RME specification. + */ +static const gpt_t_val_e gpt_t_lookup[] = {PPS_4GB_T, PPS_64GB_T, + PPS_1TB_T, PPS_4TB_T, + PPS_16TB_T, PPS_256TB_T, + PPS_4PB_T}; + +/* + * Lookup P from PGS + * + * PGS Size P + * 0b00 4KB 12 + * 0b10 16KB 14 + * 0b01 64KB 16 + * + * Note that pgs=0b10 is 16KB and pgs=0b01 is 64KB, this is not a typo. + * + * See section 15.1.27 of the RME specification. + */ +static const gpt_p_val_e gpt_p_lookup[] = {PGS_4KB_P, PGS_64KB_P, PGS_16KB_P}; + +/* + * This structure contains GPT configuration data. + */ +typedef struct { + uintptr_t plat_gpt_l0_base; + gpccr_pps_e pps; + gpt_t_val_e t; + gpccr_pgs_e pgs; + gpt_p_val_e p; +} gpt_config_t; + +static gpt_config_t gpt_config; + +/* These variables are used during initialization of the L1 tables. */ +static unsigned int gpt_next_l1_tbl_idx; +static uintptr_t gpt_l1_tbl; + +/* + * This function checks to see if a GPI value is valid. + * + * These are valid GPI values. + * GPT_GPI_NO_ACCESS U(0x0) + * GPT_GPI_SECURE U(0x8) + * GPT_GPI_NS U(0x9) + * GPT_GPI_ROOT U(0xA) + * GPT_GPI_REALM U(0xB) + * GPT_GPI_ANY U(0xF) + * + * Parameters + * gpi GPI to check for validity. + * + * Return + * true for a valid GPI, false for an invalid one. + */ +static bool gpt_is_gpi_valid(unsigned int gpi) +{ + if ((gpi == GPT_GPI_NO_ACCESS) || (gpi == GPT_GPI_ANY) || + ((gpi >= GPT_GPI_SECURE) && (gpi <= GPT_GPI_REALM))) { + return true; + } + return false; +} + +/* + * This function checks to see if two PAS regions overlap. + * + * Parameters + * base_1: base address of first PAS + * size_1: size of first PAS + * base_2: base address of second PAS + * size_2: size of second PAS + * + * Return + * True if PAS regions overlap, false if they do not. + */ +static bool gpt_check_pas_overlap(uintptr_t base_1, size_t size_1, + uintptr_t base_2, size_t size_2) +{ + if (((base_1 + size_1) > base_2) && ((base_2 + size_2) > base_1)) { + return true; + } + return false; +} + +/* + * This helper function checks to see if a PAS region from index 0 to + * (pas_idx - 1) occupies the L0 region at index l0_idx in the L0 table. + * + * Parameters + * l0_idx: Index of the L0 entry to check + * pas_regions: PAS region array + * pas_idx: Upper bound of the PAS array index. + * + * Return + * True if a PAS region occupies the L0 region in question, false if not. + */ +static bool gpt_does_previous_pas_exist_here(unsigned int l0_idx, + pas_region_t *pas_regions, + unsigned int pas_idx) +{ + /* Iterate over PAS regions up to pas_idx. */ + for (unsigned int i = 0U; i < pas_idx; i++) { + if (gpt_check_pas_overlap((GPT_L0GPTSZ_ACTUAL_SIZE * l0_idx), + GPT_L0GPTSZ_ACTUAL_SIZE, + pas_regions[i].base_pa, pas_regions[i].size)) { + return true; + } + } + return false; +} + +/* + * This function iterates over all of the PAS regions and checks them to ensure + * proper alignment of base and size, that the GPI is valid, and that no regions + * overlap. As a part of the overlap checks, this function checks existing L0 + * mappings against the new PAS regions in the event that gpt_init_pas_l1_tables + * is called multiple times to place L1 tables in different areas of memory. It + * also counts the number of L1 tables needed and returns it on success. + * + * Parameters + * *pas_regions Pointer to array of PAS region structures. + * pas_region_cnt Total number of PAS regions in the array. + * + * Return + * Negative Linux error code in the event of a failure, number of L1 regions + * required when successful. + */ +static int gpt_validate_pas_mappings(pas_region_t *pas_regions, + unsigned int pas_region_cnt) +{ + unsigned int idx; + unsigned int l1_cnt = 0U; + unsigned int pas_l1_cnt; + uint64_t *l0_desc = (uint64_t *)gpt_config.plat_gpt_l0_base; + + assert(pas_regions != NULL); + assert(pas_region_cnt != 0U); + + for (idx = 0U; idx < pas_region_cnt; idx++) { + /* Check for arithmetic overflow in region. */ + if ((ULONG_MAX - pas_regions[idx].base_pa) < + pas_regions[idx].size) { + ERROR("[GPT] Address overflow in PAS[%u]!\n", idx); + return -EOVERFLOW; + } + + /* Initial checks for PAS validity. */ + if (((pas_regions[idx].base_pa + pas_regions[idx].size) > + GPT_PPS_ACTUAL_SIZE(gpt_config.t)) || + !gpt_is_gpi_valid(GPT_PAS_ATTR_GPI(pas_regions[idx].attrs))) { + ERROR("[GPT] PAS[%u] is invalid!\n", idx); + return -EFAULT; + } + + /* + * Make sure this PAS does not overlap with another one. We + * start from idx + 1 instead of 0 since prior PAS mappings will + * have already checked themselves against this one. + */ + for (unsigned int i = idx + 1; i < pas_region_cnt; i++) { + if (gpt_check_pas_overlap(pas_regions[idx].base_pa, + pas_regions[idx].size, + pas_regions[i].base_pa, + pas_regions[i].size)) { + ERROR("[GPT] PAS[%u] overlaps with PAS[%u]\n", + i, idx); + return -EFAULT; + } + } + + /* + * Since this function can be called multiple times with + * separate L1 tables we need to check the existing L0 mapping + * to see if this PAS would fall into one that has already been + * initialized. + */ + for (unsigned int i = GPT_L0_IDX(pas_regions[idx].base_pa); + i <= GPT_L0_IDX(pas_regions[idx].base_pa + pas_regions[idx].size - 1); + i++) { + if ((GPT_L0_TYPE(l0_desc[i]) == GPT_L0_TYPE_BLK_DESC) && + (GPT_L0_BLKD_GPI(l0_desc[i]) == GPT_GPI_ANY)) { + /* This descriptor is unused so continue. */ + continue; + } + + /* + * This descriptor has been initialized in a previous + * call to this function so cannot be initialized again. + */ + ERROR("[GPT] PAS[%u] overlaps with previous L0[%d]!\n", + idx, i); + return -EFAULT; + } + + /* Check for block mapping (L0) type. */ + if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) == + GPT_PAS_ATTR_MAP_TYPE_BLOCK) { + /* Make sure base and size are block-aligned. */ + if (!GPT_IS_L0_ALIGNED(pas_regions[idx].base_pa) || + !GPT_IS_L0_ALIGNED(pas_regions[idx].size)) { + ERROR("[GPT] PAS[%u] is not block-aligned!\n", + idx); + return -EFAULT; + } + + continue; + } + + /* Check for granule mapping (L1) type. */ + if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) == + GPT_PAS_ATTR_MAP_TYPE_GRANULE) { + /* Make sure base and size are granule-aligned. */ + if (!GPT_IS_L1_ALIGNED(gpt_config.p, pas_regions[idx].base_pa) || + !GPT_IS_L1_ALIGNED(gpt_config.p, pas_regions[idx].size)) { + ERROR("[GPT] PAS[%u] is not granule-aligned!\n", + idx); + return -EFAULT; + } + + /* Find how many L1 tables this PAS occupies. */ + pas_l1_cnt = (GPT_L0_IDX(pas_regions[idx].base_pa + + pas_regions[idx].size - 1) - + GPT_L0_IDX(pas_regions[idx].base_pa) + 1); + + /* + * This creates a situation where, if multiple PAS + * regions occupy the same table descriptor, we can get + * an artificially high total L1 table count. The way we + * handle this is by checking each PAS against those + * before it in the array, and if they both occupy the + * same PAS we subtract from pas_l1_cnt and only the + * first PAS in the array gets to count it. + */ + + /* + * If L1 count is greater than 1 we know the start and + * end PAs are in different L0 regions so we must check + * both for overlap against other PAS. + */ + if (pas_l1_cnt > 1) { + if (gpt_does_previous_pas_exist_here( + GPT_L0_IDX(pas_regions[idx].base_pa + + pas_regions[idx].size - 1), + pas_regions, idx)) { + pas_l1_cnt = pas_l1_cnt - 1; + } + } + + if (gpt_does_previous_pas_exist_here( + GPT_L0_IDX(pas_regions[idx].base_pa), + pas_regions, idx)) { + pas_l1_cnt = pas_l1_cnt - 1; + } + + l1_cnt += pas_l1_cnt; + continue; + } + + /* If execution reaches this point, mapping type is invalid. */ + ERROR("[GPT] PAS[%u] has invalid mapping type 0x%x.\n", idx, + GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs)); + return -EINVAL; + } + + return l1_cnt; +} + +/* + * This function validates L0 initialization parameters. + * + * Parameters + * l0_mem_base Base address of memory used for L0 tables. + * l1_mem_size Size of memory available for L0 tables. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +static int gpt_validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base, + size_t l0_mem_size) +{ + size_t l0_alignment; + + /* + * Make sure PPS is valid and then store it since macros need this value + * to work. + */ + if (pps > GPT_PPS_MAX) { + ERROR("[GPT] Invalid PPS: 0x%x\n", pps); + return -EINVAL; + } + gpt_config.pps = pps; + gpt_config.t = gpt_t_lookup[pps]; + + /* Alignment must be the greater of 4k or l0 table size. */ + l0_alignment = PAGE_SIZE_4KB; + if (l0_alignment < GPT_L0_TABLE_SIZE(gpt_config.t)) { + l0_alignment = GPT_L0_TABLE_SIZE(gpt_config.t); + } + + /* Check base address. */ + if ((l0_mem_base == 0U) || ((l0_mem_base & (l0_alignment - 1)) != 0U)) { + ERROR("[GPT] Invalid L0 base address: 0x%lx\n", l0_mem_base); + return -EFAULT; + } + + /* Check size. */ + if (l0_mem_size < GPT_L0_TABLE_SIZE(gpt_config.t)) { + ERROR("[GPT] Inadequate L0 memory: need 0x%lx, have 0x%lx)\n", + GPT_L0_TABLE_SIZE(gpt_config.t), + l0_mem_size); + return -ENOMEM; + } + + return 0; +} + +/* + * In the event that L1 tables are needed, this function validates + * the L1 table generation parameters. + * + * Parameters + * l1_mem_base Base address of memory used for L1 table allocation. + * l1_mem_size Total size of memory available for L1 tables. + * l1_gpt_cnt Number of L1 tables needed. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +static int gpt_validate_l1_params(uintptr_t l1_mem_base, size_t l1_mem_size, + unsigned int l1_gpt_cnt) +{ + size_t l1_gpt_mem_sz; + + /* Check if the granularity is supported */ + if (!xlat_arch_is_granule_size_supported( + GPT_PGS_ACTUAL_SIZE(gpt_config.p))) { + return -EPERM; + } + + /* Make sure L1 tables are aligned to their size. */ + if ((l1_mem_base & (GPT_L1_TABLE_SIZE(gpt_config.p) - 1)) != 0U) { + ERROR("[GPT] Unaligned L1 GPT base address: 0x%lx\n", + l1_mem_base); + return -EFAULT; + } + + /* Get total memory needed for L1 tables. */ + l1_gpt_mem_sz = l1_gpt_cnt * GPT_L1_TABLE_SIZE(gpt_config.p); + + /* Check for overflow. */ + if ((l1_gpt_mem_sz / GPT_L1_TABLE_SIZE(gpt_config.p)) != l1_gpt_cnt) { + ERROR("[GPT] Overflow calculating L1 memory size.\n"); + return -ENOMEM; + } + + /* Make sure enough space was supplied. */ + if (l1_mem_size < l1_gpt_mem_sz) { + ERROR("[GPT] Inadequate memory for L1 GPTs. "); + ERROR(" Expected 0x%lx bytes. Got 0x%lx bytes\n", + l1_gpt_mem_sz, l1_mem_size); + return -ENOMEM; + } + + VERBOSE("[GPT] Requested 0x%lx bytes for L1 GPTs.\n", l1_gpt_mem_sz); + return 0; +} + +/* + * This function initializes L0 block descriptors (regions that cannot be + * transitioned at the granule level) according to the provided PAS. + * + * Parameters + * *pas Pointer to the structure defining the PAS region to + * initialize. + */ +static void gpt_generate_l0_blk_desc(pas_region_t *pas) +{ + uint64_t gpt_desc; + unsigned int end_idx; + unsigned int idx; + uint64_t *l0_gpt_arr; + + assert(gpt_config.plat_gpt_l0_base != 0U); + assert(pas != NULL); + + /* + * Checking of PAS parameters has already been done in + * gpt_validate_pas_mappings so no need to check the same things again. + */ + + l0_gpt_arr = (uint64_t *)gpt_config.plat_gpt_l0_base; + + /* Create the GPT Block descriptor for this PAS region */ + gpt_desc = GPT_L0_BLK_DESC(GPT_PAS_ATTR_GPI(pas->attrs)); + + /* Start index of this region in L0 GPTs */ + idx = GPT_L0_IDX(pas->base_pa); + + /* + * Determine number of L0 GPT descriptors covered by + * this PAS region and use the count to populate these + * descriptors. + */ + end_idx = GPT_L0_IDX(pas->base_pa + pas->size); + + /* Generate the needed block descriptors. */ + for (; idx < end_idx; idx++) { + l0_gpt_arr[idx] = gpt_desc; + VERBOSE("[GPT] L0 entry (BLOCK) index %u [%p]: GPI = 0x%" PRIx64 " (0x%" PRIx64 ")\n", + idx, &l0_gpt_arr[idx], + (gpt_desc >> GPT_L0_BLK_DESC_GPI_SHIFT) & + GPT_L0_BLK_DESC_GPI_MASK, l0_gpt_arr[idx]); + } +} + +/* + * Helper function to determine if the end physical address lies in the same L0 + * region as the current physical address. If true, the end physical address is + * returned else, the start address of the next region is returned. + * + * Parameters + * cur_pa Physical address of the current PA in the loop through + * the range. + * end_pa Physical address of the end PA in a PAS range. + * + * Return + * The PA of the end of the current range. + */ +static uintptr_t gpt_get_l1_end_pa(uintptr_t cur_pa, uintptr_t end_pa) +{ + uintptr_t cur_idx; + uintptr_t end_idx; + + cur_idx = GPT_L0_IDX(cur_pa); + end_idx = GPT_L0_IDX(end_pa); + + assert(cur_idx <= end_idx); + + if (cur_idx == end_idx) { + return end_pa; + } + + return (cur_idx + 1U) << GPT_L0_IDX_SHIFT; +} + +/* + * Helper function to fill out GPI entries in a single L1 table. This function + * fills out entire L1 descriptors at a time to save memory writes. + * + * Parameters + * gpi GPI to set this range to + * l1 Pointer to L1 table to fill out + * first Address of first granule in range. + * last Address of last granule in range (inclusive). + */ +static void gpt_fill_l1_tbl(uint64_t gpi, uint64_t *l1, uintptr_t first, + uintptr_t last) +{ + uint64_t gpi_field = GPT_BUILD_L1_DESC(gpi); + uint64_t gpi_mask = 0xFFFFFFFFFFFFFFFF; + + assert(first <= last); + assert((first & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) == 0U); + assert((last & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) == 0U); + assert(GPT_L0_IDX(first) == GPT_L0_IDX(last)); + assert(l1 != NULL); + + /* Shift the mask if we're starting in the middle of an L1 entry. */ + gpi_mask = gpi_mask << (GPT_L1_GPI_IDX(gpt_config.p, first) << 2); + + /* Fill out each L1 entry for this region. */ + for (unsigned int i = GPT_L1_IDX(gpt_config.p, first); + i <= GPT_L1_IDX(gpt_config.p, last); i++) { + /* Account for stopping in the middle of an L1 entry. */ + if (i == GPT_L1_IDX(gpt_config.p, last)) { + gpi_mask &= (gpi_mask >> ((15 - + GPT_L1_GPI_IDX(gpt_config.p, last)) << 2)); + } + + /* Write GPI values. */ + assert((l1[i] & gpi_mask) == + (GPT_BUILD_L1_DESC(GPT_GPI_ANY) & gpi_mask)); + l1[i] = (l1[i] & ~gpi_mask) | (gpi_mask & gpi_field); + + /* Reset mask. */ + gpi_mask = 0xFFFFFFFFFFFFFFFF; + } +} + +/* + * This function finds the next available unused L1 table and initializes all + * granules descriptor entries to GPI_ANY. This ensures that there are no chunks + * of GPI_NO_ACCESS (0b0000) memory floating around in the system in the + * event that a PAS region stops midway through an L1 table, thus guaranteeing + * that all memory not explicitly assigned is GPI_ANY. This function does not + * check for overflow conditions, that should be done by the caller. + * + * Return + * Pointer to the next available L1 table. + */ +static uint64_t *gpt_get_new_l1_tbl(void) +{ + /* Retrieve the next L1 table. */ + uint64_t *l1 = (uint64_t *)((uint64_t)(gpt_l1_tbl) + + (GPT_L1_TABLE_SIZE(gpt_config.p) * + gpt_next_l1_tbl_idx)); + + /* Increment L1 counter. */ + gpt_next_l1_tbl_idx++; + + /* Initialize all GPIs to GPT_GPI_ANY */ + for (unsigned int i = 0U; i < GPT_L1_ENTRY_COUNT(gpt_config.p); i++) { + l1[i] = GPT_BUILD_L1_DESC(GPT_GPI_ANY); + } + + return l1; +} + +/* + * When L1 tables are needed, this function creates the necessary L0 table + * descriptors and fills out the L1 table entries according to the supplied + * PAS range. + * + * Parameters + * *pas Pointer to the structure defining the PAS region. + */ +static void gpt_generate_l0_tbl_desc(pas_region_t *pas) +{ + uintptr_t end_pa; + uintptr_t cur_pa; + uintptr_t last_gran_pa; + uint64_t *l0_gpt_base; + uint64_t *l1_gpt_arr; + unsigned int l0_idx; + + assert(gpt_config.plat_gpt_l0_base != 0U); + assert(pas != NULL); + + /* + * Checking of PAS parameters has already been done in + * gpt_validate_pas_mappings so no need to check the same things again. + */ + + end_pa = pas->base_pa + pas->size; + l0_gpt_base = (uint64_t *)gpt_config.plat_gpt_l0_base; + + /* We start working from the granule at base PA */ + cur_pa = pas->base_pa; + + /* Iterate over each L0 region in this memory range. */ + for (l0_idx = GPT_L0_IDX(pas->base_pa); + l0_idx <= GPT_L0_IDX(end_pa - 1U); + l0_idx++) { + + /* + * See if the L0 entry is already a table descriptor or if we + * need to create one. + */ + if (GPT_L0_TYPE(l0_gpt_base[l0_idx]) == GPT_L0_TYPE_TBL_DESC) { + /* Get the L1 array from the L0 entry. */ + l1_gpt_arr = GPT_L0_TBLD_ADDR(l0_gpt_base[l0_idx]); + } else { + /* Get a new L1 table from the L1 memory space. */ + l1_gpt_arr = gpt_get_new_l1_tbl(); + + /* Fill out the L0 descriptor and flush it. */ + l0_gpt_base[l0_idx] = GPT_L0_TBL_DESC(l1_gpt_arr); + } + + VERBOSE("[GPT] L0 entry (TABLE) index %u [%p] ==> L1 Addr 0x%llx (0x%" PRIx64 ")\n", + l0_idx, &l0_gpt_base[l0_idx], + (unsigned long long)(l1_gpt_arr), + l0_gpt_base[l0_idx]); + + /* + * Determine the PA of the last granule in this L0 descriptor. + */ + last_gran_pa = gpt_get_l1_end_pa(cur_pa, end_pa) - + GPT_PGS_ACTUAL_SIZE(gpt_config.p); + + /* + * Fill up L1 GPT entries between these two addresses. This + * function needs the addresses of the first granule and last + * granule in the range. + */ + gpt_fill_l1_tbl(GPT_PAS_ATTR_GPI(pas->attrs), l1_gpt_arr, + cur_pa, last_gran_pa); + + /* Advance cur_pa to first granule in next L0 region. */ + cur_pa = gpt_get_l1_end_pa(cur_pa, end_pa); + } +} + +/* + * This function flushes a range of L0 descriptors used by a given PAS region + * array. There is a chance that some unmodified L0 descriptors would be flushed + * in the case that there are "holes" in an array of PAS regions but overall + * this should be faster than individually flushing each modified L0 descriptor + * as they are created. + * + * Parameters + * *pas Pointer to an array of PAS regions. + * pas_count Number of entries in the PAS array. + */ +static void flush_l0_for_pas_array(pas_region_t *pas, unsigned int pas_count) +{ + unsigned int idx; + unsigned int start_idx; + unsigned int end_idx; + uint64_t *l0 = (uint64_t *)gpt_config.plat_gpt_l0_base; + + assert(pas != NULL); + assert(pas_count > 0); + + /* Initial start and end values. */ + start_idx = GPT_L0_IDX(pas[0].base_pa); + end_idx = GPT_L0_IDX(pas[0].base_pa + pas[0].size - 1); + + /* Find lowest and highest L0 indices used in this PAS array. */ + for (idx = 1; idx < pas_count; idx++) { + if (GPT_L0_IDX(pas[idx].base_pa) < start_idx) { + start_idx = GPT_L0_IDX(pas[idx].base_pa); + } + if (GPT_L0_IDX(pas[idx].base_pa + pas[idx].size - 1) > end_idx) { + end_idx = GPT_L0_IDX(pas[idx].base_pa + pas[idx].size - 1); + } + } + + /* + * Flush all covered L0 descriptors, add 1 because we need to include + * the end index value. + */ + flush_dcache_range((uintptr_t)&l0[start_idx], + ((end_idx + 1) - start_idx) * sizeof(uint64_t)); +} + +/* + * Public API to enable granule protection checks once the tables have all been + * initialized. This function is called at first initialization and then again + * later during warm boots of CPU cores. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_enable(void) +{ + u_register_t gpccr_el3; + + /* + * Granule tables must be initialised before enabling + * granule protection. + */ + if (gpt_config.plat_gpt_l0_base == 0U) { + ERROR("[GPT] Tables have not been initialized!\n"); + return -EPERM; + } + + /* Invalidate any stale TLB entries */ + tlbipaallos(); + dsb(); + + /* Write the base address of the L0 tables into GPTBR */ + write_gptbr_el3(((gpt_config.plat_gpt_l0_base >> GPTBR_BADDR_VAL_SHIFT) + >> GPTBR_BADDR_SHIFT) & GPTBR_BADDR_MASK); + + /* GPCCR_EL3.PPS */ + gpccr_el3 = SET_GPCCR_PPS(gpt_config.pps); + + /* GPCCR_EL3.PGS */ + gpccr_el3 |= SET_GPCCR_PGS(gpt_config.pgs); + + /* + * Since EL3 maps the L1 region as Inner shareable, use the same + * shareability attribute for GPC as well so that + * GPC fetches are visible to PEs + */ + gpccr_el3 |= SET_GPCCR_SH(GPCCR_SH_IS); + + /* Outer and Inner cacheability set to Normal memory, WB, RA, WA. */ + gpccr_el3 |= SET_GPCCR_ORGN(GPCCR_ORGN_WB_RA_WA); + gpccr_el3 |= SET_GPCCR_IRGN(GPCCR_IRGN_WB_RA_WA); + + /* Enable GPT */ + gpccr_el3 |= GPCCR_GPC_BIT; + + /* TODO: Configure GPCCR_EL3_GPCP for Fault control. */ + write_gpccr_el3(gpccr_el3); + isb(); + tlbipaallos(); + dsb(); + isb(); + + return 0; +} + +/* + * Public API to disable granule protection checks. + */ +void gpt_disable(void) +{ + u_register_t gpccr_el3 = read_gpccr_el3(); + + write_gpccr_el3(gpccr_el3 & ~GPCCR_GPC_BIT); + dsbsy(); + isb(); +} + +/* + * Public API that initializes the entire protected space to GPT_GPI_ANY using + * the L0 tables (block descriptors). Ideally, this function is invoked prior + * to DDR discovery and initialization. The MMU must be initialized before + * calling this function. + * + * Parameters + * pps PPS value to use for table generation + * l0_mem_base Base address of L0 tables in memory. + * l0_mem_size Total size of memory available for L0 tables. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_l0_tables(unsigned int pps, uintptr_t l0_mem_base, + size_t l0_mem_size) +{ + int ret; + uint64_t gpt_desc; + + /* Ensure that MMU and Data caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + + /* Validate other parameters. */ + ret = gpt_validate_l0_params(pps, l0_mem_base, l0_mem_size); + if (ret != 0) { + return ret; + } + + /* Create the descriptor to initialize L0 entries with. */ + gpt_desc = GPT_L0_BLK_DESC(GPT_GPI_ANY); + + /* Iterate through all L0 entries */ + for (unsigned int i = 0U; i < GPT_L0_REGION_COUNT(gpt_config.t); i++) { + ((uint64_t *)l0_mem_base)[i] = gpt_desc; + } + + /* Flush updated L0 tables to memory. */ + flush_dcache_range((uintptr_t)l0_mem_base, + (size_t)GPT_L0_TABLE_SIZE(gpt_config.t)); + + /* Stash the L0 base address once initial setup is complete. */ + gpt_config.plat_gpt_l0_base = l0_mem_base; + + return 0; +} + +/* + * Public API that carves out PAS regions from the L0 tables and builds any L1 + * tables that are needed. This function ideally is run after DDR discovery and + * initialization. The L0 tables must have already been initialized to GPI_ANY + * when this function is called. + * + * This function can be called multiple times with different L1 memory ranges + * and PAS regions if it is desirable to place L1 tables in different locations + * in memory. (ex: you have multiple DDR banks and want to place the L1 tables + * in the DDR bank that they control) + * + * Parameters + * pgs PGS value to use for table generation. + * l1_mem_base Base address of memory used for L1 tables. + * l1_mem_size Total size of memory available for L1 tables. + * *pas_regions Pointer to PAS regions structure array. + * pas_count Total number of PAS regions. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base, + size_t l1_mem_size, pas_region_t *pas_regions, + unsigned int pas_count) +{ + int ret; + int l1_gpt_cnt; + + /* Ensure that MMU and Data caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + + /* PGS is needed for gpt_validate_pas_mappings so check it now. */ + if (pgs > GPT_PGS_MAX) { + ERROR("[GPT] Invalid PGS: 0x%x\n", pgs); + return -EINVAL; + } + gpt_config.pgs = pgs; + gpt_config.p = gpt_p_lookup[pgs]; + + /* Make sure L0 tables have been initialized. */ + if (gpt_config.plat_gpt_l0_base == 0U) { + ERROR("[GPT] L0 tables must be initialized first!\n"); + return -EPERM; + } + + /* Check if L1 GPTs are required and how many. */ + l1_gpt_cnt = gpt_validate_pas_mappings(pas_regions, pas_count); + if (l1_gpt_cnt < 0) { + return l1_gpt_cnt; + } + + VERBOSE("[GPT] %u L1 GPTs requested.\n", l1_gpt_cnt); + + /* If L1 tables are needed then validate the L1 parameters. */ + if (l1_gpt_cnt > 0) { + ret = gpt_validate_l1_params(l1_mem_base, l1_mem_size, + l1_gpt_cnt); + if (ret != 0) { + return ret; + } + + /* Set up parameters for L1 table generation. */ + gpt_l1_tbl = l1_mem_base; + gpt_next_l1_tbl_idx = 0U; + } + + INFO("[GPT] Boot Configuration\n"); + INFO(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t); + INFO(" PGS/P: 0x%x/%u\n", gpt_config.pgs, gpt_config.p); + INFO(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL); + INFO(" PAS count: 0x%x\n", pas_count); + INFO(" L0 base: 0x%lx\n", gpt_config.plat_gpt_l0_base); + + /* Generate the tables in memory. */ + for (unsigned int idx = 0U; idx < pas_count; idx++) { + INFO("[GPT] PAS[%u]: base 0x%lx, size 0x%lx, GPI 0x%x, type 0x%x\n", + idx, pas_regions[idx].base_pa, pas_regions[idx].size, + GPT_PAS_ATTR_GPI(pas_regions[idx].attrs), + GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs)); + + /* Check if a block or table descriptor is required */ + if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) == + GPT_PAS_ATTR_MAP_TYPE_BLOCK) { + gpt_generate_l0_blk_desc(&pas_regions[idx]); + + } else { + gpt_generate_l0_tbl_desc(&pas_regions[idx]); + } + } + + /* Flush modified L0 tables. */ + flush_l0_for_pas_array(pas_regions, pas_count); + + /* Flush L1 tables if needed. */ + if (l1_gpt_cnt > 0) { + flush_dcache_range(l1_mem_base, + GPT_L1_TABLE_SIZE(gpt_config.p) * + l1_gpt_cnt); + } + + /* Make sure that all the entries are written to the memory. */ + dsbishst(); + tlbipaallos(); + dsb(); + isb(); + + return 0; +} + +/* + * Public API to initialize the runtime gpt_config structure based on the values + * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization + * typically happens in a bootloader stage prior to setting up the EL3 runtime + * environment for the granule transition service so this function detects the + * initialization from a previous stage. Granule protection checks must be + * enabled already or this function will return an error. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_runtime_init(void) +{ + u_register_t reg; + + /* Ensure that MMU and Data caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + + /* Ensure GPC are already enabled. */ + if ((read_gpccr_el3() & GPCCR_GPC_BIT) == 0U) { + ERROR("[GPT] Granule protection checks are not enabled!\n"); + return -EPERM; + } + + /* + * Read the L0 table address from GPTBR, we don't need the L1 base + * address since those are included in the L0 tables as needed. + */ + reg = read_gptbr_el3(); + gpt_config.plat_gpt_l0_base = ((reg >> GPTBR_BADDR_SHIFT) & + GPTBR_BADDR_MASK) << + GPTBR_BADDR_VAL_SHIFT; + + /* Read GPCCR to get PGS and PPS values. */ + reg = read_gpccr_el3(); + gpt_config.pps = (reg >> GPCCR_PPS_SHIFT) & GPCCR_PPS_MASK; + gpt_config.t = gpt_t_lookup[gpt_config.pps]; + gpt_config.pgs = (reg >> GPCCR_PGS_SHIFT) & GPCCR_PGS_MASK; + gpt_config.p = gpt_p_lookup[gpt_config.pgs]; + + VERBOSE("[GPT] Runtime Configuration\n"); + VERBOSE(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t); + VERBOSE(" PGS/P: 0x%x/%u\n", gpt_config.pgs, gpt_config.p); + VERBOSE(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL); + VERBOSE(" L0 base: 0x%lx\n", gpt_config.plat_gpt_l0_base); + + return 0; +} + +/* + * The L1 descriptors are protected by a spinlock to ensure that multiple + * CPUs do not attempt to change the descriptors at once. In the future it + * would be better to have separate spinlocks for each L1 descriptor. + */ +static spinlock_t gpt_lock; + +/* + * A helper to write the value (target_pas << gpi_shift) to the index of + * the gpt_l1_addr + */ +static inline void write_gpt(uint64_t *gpt_l1_desc, uint64_t *gpt_l1_addr, + unsigned int gpi_shift, unsigned int idx, + unsigned int target_pas) +{ + *gpt_l1_desc &= ~(GPT_L1_GRAN_DESC_GPI_MASK << gpi_shift); + *gpt_l1_desc |= ((uint64_t)target_pas << gpi_shift); + gpt_l1_addr[idx] = *gpt_l1_desc; +} + +/* + * Helper to retrieve the gpt_l1_* information from the base address + * returned in gpi_info + */ +static int get_gpi_params(uint64_t base, gpi_info_t *gpi_info) +{ + uint64_t gpt_l0_desc, *gpt_l0_base; + + gpt_l0_base = (uint64_t *)gpt_config.plat_gpt_l0_base; + gpt_l0_desc = gpt_l0_base[GPT_L0_IDX(base)]; + if (GPT_L0_TYPE(gpt_l0_desc) != GPT_L0_TYPE_TBL_DESC) { + VERBOSE("[GPT] Granule is not covered by a table descriptor!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + return -EINVAL; + } + + /* Get the table index and GPI shift from PA. */ + gpi_info->gpt_l1_addr = GPT_L0_TBLD_ADDR(gpt_l0_desc); + gpi_info->idx = GPT_L1_IDX(gpt_config.p, base); + gpi_info->gpi_shift = GPT_L1_GPI_IDX(gpt_config.p, base) << 2; + + gpi_info->gpt_l1_desc = (gpi_info->gpt_l1_addr)[gpi_info->idx]; + gpi_info->gpi = (gpi_info->gpt_l1_desc >> gpi_info->gpi_shift) & + GPT_L1_GRAN_DESC_GPI_MASK; + return 0; +} + +/* + * This function is the granule transition delegate service. When a granule + * transition request occurs it is routed to this function to have the request, + * if valid, fulfilled following A1.1.1 Delegate of RME supplement + * + * TODO: implement support for transitioning multiple granules at once. + * + * Parameters + * base Base address of the region to transition, must be + * aligned to granule size. + * size Size of region to transition, must be aligned to granule + * size. + * src_sec_state Security state of the caller. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_delegate_pas(uint64_t base, size_t size, unsigned int src_sec_state) +{ + gpi_info_t gpi_info; + uint64_t nse; + int res; + unsigned int target_pas; + + /* Ensure that the tables have been set up before taking requests. */ + assert(gpt_config.plat_gpt_l0_base != 0UL); + + /* Ensure that caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL); + + /* Delegate request can only come from REALM or SECURE */ + assert(src_sec_state == SMC_FROM_REALM || + src_sec_state == SMC_FROM_SECURE); + + /* See if this is a single or a range of granule transition. */ + if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) { + return -EINVAL; + } + + /* Check that base and size are valid */ + if ((ULONG_MAX - base) < size) { + VERBOSE("[GPT] Transition request address overflow!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + VERBOSE(" Size=0x%lx\n", size); + return -EINVAL; + } + + /* Make sure base and size are valid. */ + if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) || + ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) || + (size == 0UL) || + ((base + size) >= GPT_PPS_ACTUAL_SIZE(gpt_config.t))) { + VERBOSE("[GPT] Invalid granule transition address range!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + VERBOSE(" Size=0x%lx\n", size); + return -EINVAL; + } + + target_pas = GPT_GPI_REALM; + if (src_sec_state == SMC_FROM_SECURE) { + target_pas = GPT_GPI_SECURE; + } + + /* + * Access to L1 tables is controlled by a global lock to ensure + * that no more than one CPU is allowed to make changes at any + * given time. + */ + spin_lock(&gpt_lock); + res = get_gpi_params(base, &gpi_info); + if (res != 0) { + spin_unlock(&gpt_lock); + return res; + } + + /* Check that the current address is in NS state */ + if (gpi_info.gpi != GPT_GPI_NS) { + VERBOSE("[GPT] Only Granule in NS state can be delegated.\n"); + VERBOSE(" Caller: %u, Current GPI: %u\n", src_sec_state, + gpi_info.gpi); + spin_unlock(&gpt_lock); + return -EINVAL; + } + + if (src_sec_state == SMC_FROM_SECURE) { + nse = (uint64_t)GPT_NSE_SECURE << GPT_NSE_SHIFT; + } else { + nse = (uint64_t)GPT_NSE_REALM << GPT_NSE_SHIFT; + } + + /* + * In order to maintain mutual distrust between Realm and Secure + * states, remove any data speculatively fetched into the target + * physical address space. Issue DC CIPAPA over address range + */ + flush_dcache_to_popa_range(nse | base, + GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + + write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr, + gpi_info.gpi_shift, gpi_info.idx, target_pas); + dsboshst(); + + gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + dsbosh(); + + nse = (uint64_t)GPT_NSE_NS << GPT_NSE_SHIFT; + + flush_dcache_to_popa_range(nse | base, + GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + + /* Unlock access to the L1 tables. */ + spin_unlock(&gpt_lock); + + /* + * The isb() will be done as part of context + * synchronization when returning to lower EL + */ + VERBOSE("[GPT] Granule 0x%" PRIx64 ", GPI 0x%x->0x%x\n", + base, gpi_info.gpi, target_pas); + + return 0; +} + +/* + * This function is the granule transition undelegate service. When a granule + * transition request occurs it is routed to this function where the request is + * validated then fulfilled if possible. + * + * TODO: implement support for transitioning multiple granules at once. + * + * Parameters + * base Base address of the region to transition, must be + * aligned to granule size. + * size Size of region to transition, must be aligned to granule + * size. + * src_sec_state Security state of the caller. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_undelegate_pas(uint64_t base, size_t size, unsigned int src_sec_state) +{ + gpi_info_t gpi_info; + uint64_t nse; + int res; + + /* Ensure that the tables have been set up before taking requests. */ + assert(gpt_config.plat_gpt_l0_base != 0UL); + + /* Ensure that MMU and caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL); + + /* Delegate request can only come from REALM or SECURE */ + assert(src_sec_state == SMC_FROM_REALM || + src_sec_state == SMC_FROM_SECURE); + + /* See if this is a single or a range of granule transition. */ + if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) { + return -EINVAL; + } + + /* Check that base and size are valid */ + if ((ULONG_MAX - base) < size) { + VERBOSE("[GPT] Transition request address overflow!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + VERBOSE(" Size=0x%lx\n", size); + return -EINVAL; + } + + /* Make sure base and size are valid. */ + if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) || + ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) || + (size == 0UL) || + ((base + size) >= GPT_PPS_ACTUAL_SIZE(gpt_config.t))) { + VERBOSE("[GPT] Invalid granule transition address range!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + VERBOSE(" Size=0x%lx\n", size); + return -EINVAL; + } + + /* + * Access to L1 tables is controlled by a global lock to ensure + * that no more than one CPU is allowed to make changes at any + * given time. + */ + spin_lock(&gpt_lock); + + res = get_gpi_params(base, &gpi_info); + if (res != 0) { + spin_unlock(&gpt_lock); + return res; + } + + /* Check that the current address is in the delegated state */ + if ((src_sec_state == SMC_FROM_REALM && + gpi_info.gpi != GPT_GPI_REALM) || + (src_sec_state == SMC_FROM_SECURE && + gpi_info.gpi != GPT_GPI_SECURE)) { + VERBOSE("[GPT] Only Granule in REALM or SECURE state can be undelegated.\n"); + VERBOSE(" Caller: %u, Current GPI: %u\n", src_sec_state, + gpi_info.gpi); + spin_unlock(&gpt_lock); + return -EINVAL; + } + + + /* In order to maintain mutual distrust between Realm and Secure + * states, remove access now, in order to guarantee that writes + * to the currently-accessible physical address space will not + * later become observable. + */ + write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr, + gpi_info.gpi_shift, gpi_info.idx, GPT_GPI_NO_ACCESS); + dsboshst(); + + gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + dsbosh(); + + if (src_sec_state == SMC_FROM_SECURE) { + nse = (uint64_t)GPT_NSE_SECURE << GPT_NSE_SHIFT; + } else { + nse = (uint64_t)GPT_NSE_REALM << GPT_NSE_SHIFT; + } + + /* Ensure that the scrubbed data has made it past the PoPA */ + flush_dcache_to_popa_range(nse | base, + GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + + /* + * Remove any data loaded speculatively + * in NS space from before the scrubbing + */ + nse = (uint64_t)GPT_NSE_NS << GPT_NSE_SHIFT; + + flush_dcache_to_popa_range(nse | base, + GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + + /* Clear existing GPI encoding and transition granule. */ + write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr, + gpi_info.gpi_shift, gpi_info.idx, GPT_GPI_NS); + dsboshst(); + + /* Ensure that all agents observe the new NS configuration */ + gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + dsbosh(); + + /* Unlock access to the L1 tables. */ + spin_unlock(&gpt_lock); + + /* + * The isb() will be done as part of context + * synchronization when returning to lower EL + */ + VERBOSE("[GPT] Granule 0x%" PRIx64 ", GPI 0x%x->0x%x\n", + base, gpi_info.gpi, GPT_GPI_NS); + + return 0; +} diff --git a/arm-trusted-firmware/lib/gpt_rme/gpt_rme.mk b/arm-trusted-firmware/lib/gpt_rme/gpt_rme.mk new file mode 100644 index 0000000..60176f4 --- /dev/null +++ b/arm-trusted-firmware/lib/gpt_rme/gpt_rme.mk @@ -0,0 +1,8 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +GPT_LIB_SRCS := $(addprefix lib/gpt_rme/, \ + gpt_rme.c) diff --git a/arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h b/arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h new file mode 100644 index 0000000..3c817f3 --- /dev/null +++ b/arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPT_RME_PRIVATE_H +#define GPT_RME_PRIVATE_H + +#include +#include +#include + +/******************************************************************************/ +/* GPT descriptor definitions */ +/******************************************************************************/ + +/* GPT level 0 descriptor bit definitions. */ +#define GPT_L0_TYPE_MASK UL(0xF) +#define GPT_L0_TYPE_SHIFT U(0) + +/* For now, we don't support contiguous descriptors, only table and block. */ +#define GPT_L0_TYPE_TBL_DESC UL(0x3) +#define GPT_L0_TYPE_BLK_DESC UL(0x1) + +#define GPT_L0_TBL_DESC_L1ADDR_MASK UL(0xFFFFFFFFFF) +#define GPT_L0_TBL_DESC_L1ADDR_SHIFT U(12) + +#define GPT_L0_BLK_DESC_GPI_MASK UL(0xF) +#define GPT_L0_BLK_DESC_GPI_SHIFT U(4) + +/* GPT level 1 descriptor bit definitions */ +#define GPT_L1_GRAN_DESC_GPI_MASK UL(0xF) + +/* + * This macro fills out every GPI entry in a granules descriptor to the same + * value. + */ +#define GPT_BUILD_L1_DESC(_gpi) (((uint64_t)(_gpi) << 4*0) | \ + ((uint64_t)(_gpi) << 4*1) | \ + ((uint64_t)(_gpi) << 4*2) | \ + ((uint64_t)(_gpi) << 4*3) | \ + ((uint64_t)(_gpi) << 4*4) | \ + ((uint64_t)(_gpi) << 4*5) | \ + ((uint64_t)(_gpi) << 4*6) | \ + ((uint64_t)(_gpi) << 4*7) | \ + ((uint64_t)(_gpi) << 4*8) | \ + ((uint64_t)(_gpi) << 4*9) | \ + ((uint64_t)(_gpi) << 4*10) | \ + ((uint64_t)(_gpi) << 4*11) | \ + ((uint64_t)(_gpi) << 4*12) | \ + ((uint64_t)(_gpi) << 4*13) | \ + ((uint64_t)(_gpi) << 4*14) | \ + ((uint64_t)(_gpi) << 4*15)) + +/******************************************************************************/ +/* GPT platform configuration */ +/******************************************************************************/ + +/* This value comes from GPCCR_EL3 so no externally supplied definition. */ +#define GPT_L0GPTSZ ((unsigned int)((read_gpccr_el3() >> \ + GPCCR_L0GPTSZ_SHIFT) & GPCCR_L0GPTSZ_MASK)) + +/* The "S" value is directly related to L0GPTSZ */ +#define GPT_S_VAL (GPT_L0GPTSZ + 30U) + +/* + * Map PPS values to T values. + * + * PPS Size T + * 0b000 4GB 32 + * 0b001 64GB 36 + * 0b010 1TB 40 + * 0b011 4TB 42 + * 0b100 16TB 44 + * 0b101 256TB 48 + * 0b110 4PB 52 + * + * See section 15.1.27 of the RME specification. + */ +typedef enum { + PPS_4GB_T = 32U, + PPS_64GB_T = 36U, + PPS_1TB_T = 40U, + PPS_4TB_T = 42U, + PPS_16TB_T = 44U, + PPS_256TB_T = 48U, + PPS_4PB_T = 52U +} gpt_t_val_e; + +/* + * Map PGS values to P values. + * + * PGS Size P + * 0b00 4KB 12 + * 0b10 16KB 14 + * 0b01 64KB 16 + * + * Note that pgs=0b10 is 16KB and pgs=0b01 is 64KB, this is not a typo. + * + * See section 15.1.27 of the RME specification. + */ +typedef enum { + PGS_4KB_P = 12U, + PGS_16KB_P = 14U, + PGS_64KB_P = 16U +} gpt_p_val_e; + +/* + * Internal structure to retrieve the values from get_gpi_info(); + */ +typedef struct gpi_info { + uint64_t gpt_l1_desc; + uint64_t *gpt_l1_addr; + unsigned int idx; + unsigned int gpi_shift; + unsigned int gpi; +} gpi_info_t; + +/* Max valid value for PGS. */ +#define GPT_PGS_MAX (2U) + +/* Max valid value for PPS. */ +#define GPT_PPS_MAX (6U) + +/******************************************************************************/ +/* L0 address attribute macros */ +/******************************************************************************/ + +/* + * Width of the L0 index field. + * + * If S is greater than or equal to T then there is a single L0 region covering + * the entire protected space so there is no L0 index, so the width (and the + * derivative mask value) are both zero. If we don't specifically handle this + * special case we'll get a negative width value which does not make sense and + * would cause problems. + */ +#define GPT_L0_IDX_WIDTH(_t) (((_t) > GPT_S_VAL) ? \ + ((_t) - GPT_S_VAL) : (0U)) + +/* Bit shift for the L0 index field in a PA. */ +#define GPT_L0_IDX_SHIFT (GPT_S_VAL) + +/* + * Mask for the L0 index field, must be shifted. + * + * The value 0x3FFFFF is 22 bits wide which is the maximum possible width of the + * L0 index within a physical address. This is calculated by + * ((t_max - 1) - s_min + 1) where t_max is 52 for 4PB, the largest PPS, and + * s_min is 30 for 1GB, the smallest L0GPTSZ. + */ +#define GPT_L0_IDX_MASK(_t) (0x3FFFFFUL >> (22U - \ + (GPT_L0_IDX_WIDTH(_t)))) + +/* Total number of L0 regions. */ +#define GPT_L0_REGION_COUNT(_t) ((GPT_L0_IDX_MASK(_t)) + 1U) + +/* Total size of each GPT L0 region in bytes. */ +#define GPT_L0_REGION_SIZE (1UL << (GPT_L0_IDX_SHIFT)) + +/* Total size in bytes of the whole L0 table. */ +#define GPT_L0_TABLE_SIZE(_t) ((GPT_L0_REGION_COUNT(_t)) << 3U) + +/******************************************************************************/ +/* L1 address attribute macros */ +/******************************************************************************/ + +/* + * Width of the L1 index field. + * + * This field does not have a special case to handle widths less than zero like + * the L0 index field above since all valid combinations of PGS (p) and L0GPTSZ + * (s) will result in a positive width value. + */ +#define GPT_L1_IDX_WIDTH(_p) ((GPT_S_VAL - 1U) - ((_p) + 3U)) + +/* Bit shift for the L1 index field. */ +#define GPT_L1_IDX_SHIFT(_p) ((_p) + 4U) + +/* + * Mask for the L1 index field, must be shifted. + * + * The value 0x7FFFFF is 23 bits wide and is the maximum possible width of the + * L1 index within a physical address. It is calculated by + * ((s_max - 1) - (p_min + 4) + 1) where s_max is 39 for 512gb, the largest + * L0GPTSZ, and p_min is 12 for 4KB granules, the smallest PGS. + */ +#define GPT_L1_IDX_MASK(_p) (0x7FFFFFUL >> (23U - \ + (GPT_L1_IDX_WIDTH(_p)))) + +/* Bit shift for the index of the L1 GPI in a PA. */ +#define GPT_L1_GPI_IDX_SHIFT(_p) (_p) + +/* Mask for the index of the L1 GPI in a PA. */ +#define GPT_L1_GPI_IDX_MASK (0xF) + +/* Total number of entries in each L1 table. */ +#define GPT_L1_ENTRY_COUNT(_p) ((GPT_L1_IDX_MASK(_p)) + 1U) + +/* Total size in bytes of each L1 table. */ +#define GPT_L1_TABLE_SIZE(_p) ((GPT_L1_ENTRY_COUNT(_p)) << 3U) + +/******************************************************************************/ +/* General helper macros */ +/******************************************************************************/ + +/* Protected space actual size in bytes. */ +#define GPT_PPS_ACTUAL_SIZE(_t) (1UL << (_t)) + +/* Granule actual size in bytes. */ +#define GPT_PGS_ACTUAL_SIZE(_p) (1UL << (_p)) + +/* L0 GPT region size in bytes. */ +#define GPT_L0GPTSZ_ACTUAL_SIZE (1UL << GPT_S_VAL) + +/* Get the index of the L0 entry from a physical address. */ +#define GPT_L0_IDX(_pa) ((_pa) >> GPT_L0_IDX_SHIFT) + +/* + * This definition is used to determine if a physical address lies on an L0 + * region boundary. + */ +#define GPT_IS_L0_ALIGNED(_pa) (((_pa) & (GPT_L0_REGION_SIZE - U(1))) == U(0)) + +/* Get the type field from an L0 descriptor. */ +#define GPT_L0_TYPE(_desc) (((_desc) >> GPT_L0_TYPE_SHIFT) & \ + GPT_L0_TYPE_MASK) + +/* Create an L0 block descriptor. */ +#define GPT_L0_BLK_DESC(_gpi) (GPT_L0_TYPE_BLK_DESC | \ + (((_gpi) & GPT_L0_BLK_DESC_GPI_MASK) << \ + GPT_L0_BLK_DESC_GPI_SHIFT)) + +/* Create an L0 table descriptor with an L1 table address. */ +#define GPT_L0_TBL_DESC(_pa) (GPT_L0_TYPE_TBL_DESC | ((uint64_t)(_pa) & \ + (GPT_L0_TBL_DESC_L1ADDR_MASK << \ + GPT_L0_TBL_DESC_L1ADDR_SHIFT))) + +/* Get the GPI from an L0 block descriptor. */ +#define GPT_L0_BLKD_GPI(_desc) (((_desc) >> GPT_L0_BLK_DESC_GPI_SHIFT) & \ + GPT_L0_BLK_DESC_GPI_MASK) + +/* Get the L1 address from an L0 table descriptor. */ +#define GPT_L0_TBLD_ADDR(_desc) ((uint64_t *)(((_desc) & \ + (GPT_L0_TBL_DESC_L1ADDR_MASK << \ + GPT_L0_TBL_DESC_L1ADDR_SHIFT)))) + +/* Get the index into the L1 table from a physical address. */ +#define GPT_L1_IDX(_p, _pa) (((_pa) >> GPT_L1_IDX_SHIFT(_p)) & \ + GPT_L1_IDX_MASK(_p)) + +/* Get the index of the GPI within an L1 table entry from a physical address. */ +#define GPT_L1_GPI_IDX(_p, _pa) (((_pa) >> GPT_L1_GPI_IDX_SHIFT(_p)) & \ + GPT_L1_GPI_IDX_MASK) + +/* Determine if an address is granule-aligned. */ +#define GPT_IS_L1_ALIGNED(_p, _pa) (((_pa) & (GPT_PGS_ACTUAL_SIZE(_p) - U(1))) \ + == U(0)) + +#endif /* GPT_RME_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/libc/aarch32/memset.S b/arm-trusted-firmware/lib/libc/aarch32/memset.S new file mode 100644 index 0000000..880ba83 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/aarch32/memset.S @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .syntax unified + .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 + mov r12, r0 /* keep r0 */ + tst r0, #3 + beq aligned /* 4-bytes aligned */ + + /* Unaligned 'dst' */ +unaligned: + subs r2, r2, #1 + strbhs r1, [r12], #1 + bxls lr /* return if 0 */ + tst r12, #3 + bne unaligned /* continue while unaligned */ + + /* 4-bytes aligned */ +aligned:bfi r1, r1, #8, #8 /* propagate 'val' */ + bfi r1, r1, #16, #16 + + mov r3, r1 + + cmp r2, #16 + blo less_16 /* < 16 */ + + push {r4, lr} + mov r4, r1 + mov lr, r1 + +write_32: + subs r2, r2, #32 + stmiahs r12!, {r1, r3, r4, lr} + stmiahs r12!, {r1, r3, r4, lr} + bhi write_32 /* write 32 bytes in a loop */ + popeq {r4, pc} /* return if 0 */ + lsls r2, r2, #28 /* C = r2[4]; N = r2[3]; Z = r2[3:0] */ + stmiacs r12!, {r1, r3, r4, lr} /* write 16 bytes */ + popeq {r4, pc} /* return if 16 */ + stmiami r12!, {r1, r3} /* write 8 bytes */ + lsls r2, r2, #2 /* C = r2[2]; N = r2[1]; Z = r2[1:0] */ + strcs r1, [r12], #4 /* write 4 bytes */ + popeq {r4, pc} /* return if 8 or 4 */ + strhmi r1, [r12], #2 /* write 2 bytes */ + lsls r2, r2, #1 /* N = Z = r2[0] */ + strbmi r1, [r12] /* write 1 byte */ + pop {r4, pc} + +less_16:lsls r2, r2, #29 /* C = r2[3]; N = r2[2]; Z = r2[2:0] */ + stmiacs r12!, {r1, r3} /* write 8 bytes */ + bxeq lr /* return if 8 */ + strmi r1, [r12], #4 /* write 4 bytes */ + lsls r2, r2, #2 /* C = r2[1]; N = Z = r2[0] */ + strhcs r1, [r12], #2 /* write 2 bytes */ + strbmi r1, [r12] /* write 1 byte */ + bx lr + +endfunc memset diff --git a/arm-trusted-firmware/lib/libc/aarch64/memset.S b/arm-trusted-firmware/lib/libc/aarch64/memset.S new file mode 100644 index 0000000..0543704 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/aarch64/setjmp.S b/arm-trusted-firmware/lib/libc/aarch64/setjmp.S new file mode 100644 index 0000000..9d9eb49 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/abort.c b/arm-trusted-firmware/lib/libc/abort.c new file mode 100644 index 0000000..432b1d0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/assert.c b/arm-trusted-firmware/lib/libc/assert.c new file mode 100644 index 0000000..c199de6 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/assert.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013-2022, 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:%u:%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:%u\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/arm-trusted-firmware/lib/libc/exit.c b/arm-trusted-firmware/lib/libc/exit.c new file mode 100644 index 0000000..f4ffe27 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/libc.mk b/arm-trusted-firmware/lib/libc/libc.mk new file mode 100644 index 0000000..b75d09c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/libc_asm.mk b/arm-trusted-firmware/lib/libc/libc_asm.mk new file mode 100644 index 0000000..2f27265 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/memchr.c b/arm-trusted-firmware/lib/libc/memchr.c new file mode 100644 index 0000000..8cbb715 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/memcmp.c b/arm-trusted-firmware/lib/libc/memcmp.c new file mode 100644 index 0000000..cd5f0df --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/memcpy.c b/arm-trusted-firmware/lib/libc/memcpy.c new file mode 100644 index 0000000..158df9b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/memmove.c b/arm-trusted-firmware/lib/libc/memmove.c new file mode 100644 index 0000000..63acf26 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/memrchr.c b/arm-trusted-firmware/lib/libc/memrchr.c new file mode 100644 index 0000000..01caef3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/memset.c b/arm-trusted-firmware/lib/libc/memset.c new file mode 100644 index 0000000..17f798c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/printf.c b/arm-trusted-firmware/lib/libc/printf.c new file mode 100644 index 0000000..45e153e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/putchar.c b/arm-trusted-firmware/lib/libc/putchar.c new file mode 100644 index 0000000..037e28a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/puts.c b/arm-trusted-firmware/lib/libc/puts.c new file mode 100644 index 0000000..2a0ca11 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/snprintf.c b/arm-trusted-firmware/lib/libc/snprintf.c new file mode 100644 index 0000000..675d243 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/snprintf.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#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'; + + if (radix < 10) { + ERROR("snprintf: unsupported radix '%u'.", radix); + plat_panic_handler(); + assert(0); /* Unreachable */ + } + + 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; + for (i = padn - width; i > 0; i--) { + CHECK_AND_PUT_CHAR(*s, n, *chars_printed, padc); + } + for (i = width; i > 0; i--) { + CHECK_AND_PUT_CHAR(*s, n, *chars_printed, num_buf[i - 1]); + } + for (i = width + padn; i < 0; i++) { + CHECK_AND_PUT_CHAR(*s, n, *chars_printed, padc); + } +} + +/******************************************************************* + * 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/arm-trusted-firmware/lib/libc/strchr.c b/arm-trusted-firmware/lib/libc/strchr.c new file mode 100644 index 0000000..d94bb9e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strcmp.c b/arm-trusted-firmware/lib/libc/strcmp.c new file mode 100644 index 0000000..b742f9b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strlcat.c b/arm-trusted-firmware/lib/libc/strlcat.c new file mode 100644 index 0000000..e60c863 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strlcpy.c b/arm-trusted-firmware/lib/libc/strlcpy.c new file mode 100644 index 0000000..c4f39bb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strlen.c b/arm-trusted-firmware/lib/libc/strlen.c new file mode 100644 index 0000000..3c27630 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strncmp.c b/arm-trusted-firmware/lib/libc/strncmp.c new file mode 100644 index 0000000..ce9e5ed --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strnlen.c b/arm-trusted-firmware/lib/libc/strnlen.c new file mode 100644 index 0000000..b944e95 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strrchr.c b/arm-trusted-firmware/lib/libc/strrchr.c new file mode 100644 index 0000000..cd435ff --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strtok.c b/arm-trusted-firmware/lib/libc/strtok.c new file mode 100644 index 0000000..7e1a4d2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strtol.c b/arm-trusted-firmware/lib/libc/strtol.c new file mode 100644 index 0000000..deb862c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strtoll.c b/arm-trusted-firmware/lib/libc/strtoll.c new file mode 100644 index 0000000..4e101e8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strtoul.c b/arm-trusted-firmware/lib/libc/strtoul.c new file mode 100644 index 0000000..b42fb14 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libc/strtoull.c b/arm-trusted-firmware/lib/libc/strtoull.c new file mode 100644 index 0000000..2e65a43 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/libfdt/fdt.c b/arm-trusted-firmware/lib/libfdt/fdt.c new file mode 100644 index 0000000..6cf2fa0 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +/* + * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks + * that the given buffer contains what appears to be a flattened + * device tree with sane information in its header. + */ +int32_t fdt_ro_probe_(const void *fdt) +{ + uint32_t totalsize = fdt_totalsize(fdt); + + if (can_assume(VALID_DTB)) + return totalsize; + + if (fdt_magic(fdt) == FDT_MAGIC) { + /* Complete tree */ + if (!can_assume(LATEST)) { + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + /* Unfinished sequential-write blob */ + if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0) + return -FDT_ERR_BADSTATE; + } else { + return -FDT_ERR_BADMAGIC; + } + + if (totalsize < INT32_MAX) + return totalsize; + else + return -FDT_ERR_TRUNCATED; +} + +static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) +{ + return (off >= hdrsize) && (off <= totalsize); +} + +static int check_block_(uint32_t hdrsize, uint32_t totalsize, + uint32_t base, uint32_t size) +{ + if (!check_off_(hdrsize, totalsize, base)) + return 0; /* block start out of bounds */ + if ((base + size) < base) + return 0; /* overflow */ + if (!check_off_(hdrsize, totalsize, base + size)) + return 0; /* block end out of bounds */ + return 1; +} + +size_t fdt_header_size_(uint32_t version) +{ + if (version <= 1) + return FDT_V1_SIZE; + else if (version <= 2) + return FDT_V2_SIZE; + else if (version <= 3) + return FDT_V3_SIZE; + else if (version <= 16) + return FDT_V16_SIZE; + else + return FDT_V17_SIZE; +} + +size_t fdt_header_size(const void *fdt) +{ + return can_assume(LATEST) ? FDT_V17_SIZE : + fdt_header_size_(fdt_version(fdt)); +} + +int fdt_check_header(const void *fdt) +{ + size_t hdrsize; + + if (fdt_magic(fdt) != FDT_MAGIC) + return -FDT_ERR_BADMAGIC; + if (!can_assume(LATEST)) { + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + || (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION)) + return -FDT_ERR_BADVERSION; + if (fdt_version(fdt) < fdt_last_comp_version(fdt)) + return -FDT_ERR_BADVERSION; + } + hdrsize = fdt_header_size(fdt); + if (!can_assume(VALID_DTB)) { + + if ((fdt_totalsize(fdt) < hdrsize) + || (fdt_totalsize(fdt) > INT_MAX)) + return -FDT_ERR_TRUNCATED; + + /* Bounds check memrsv block */ + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_mem_rsvmap(fdt))) + return -FDT_ERR_TRUNCATED; + } + + if (!can_assume(VALID_DTB)) { + /* Bounds check structure block */ + if (!can_assume(LATEST) && fdt_version(fdt) < 17) { + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } else { + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } + + /* Bounds check strings block */ + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_strings(fdt), + fdt_size_dt_strings(fdt))) + return -FDT_ERR_TRUNCATED; + } + + return 0; +} + +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) +{ + unsigned int uoffset = offset; + unsigned int absoffset = offset + fdt_off_dt_struct(fdt); + + if (offset < 0) + return NULL; + + if (!can_assume(VALID_INPUT)) + if ((absoffset < uoffset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; + + if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) + if (((uoffset + len) < uoffset) + || ((offset + len) > fdt_size_dt_struct(fdt))) + return NULL; + + return fdt_offset_ptr_(fdt, offset); +} + +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) +{ + const fdt32_t *tagp, *lenp; + uint32_t tag; + int offset = startoffset; + const char *p; + + *nextoffset = -FDT_ERR_TRUNCATED; + tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); + if (!can_assume(VALID_DTB) && !tagp) + return FDT_END; /* premature end */ + tag = fdt32_to_cpu(*tagp); + offset += FDT_TAGSIZE; + + *nextoffset = -FDT_ERR_BADSTRUCTURE; + switch (tag) { + case FDT_BEGIN_NODE: + /* skip name */ + do { + p = fdt_offset_ptr(fdt, offset++, 1); + } while (p && (*p != '\0')); + if (!can_assume(VALID_DTB) && !p) + return FDT_END; /* premature end */ + break; + + case FDT_PROP: + lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); + if (!can_assume(VALID_DTB) && !lenp) + return FDT_END; /* premature end */ + /* skip-name offset, length and value */ + offset += sizeof(struct fdt_property) - FDT_TAGSIZE + + fdt32_to_cpu(*lenp); + if (!can_assume(LATEST) && + fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && + ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) + offset += 4; + break; + + case FDT_END: + case FDT_END_NODE: + case FDT_NOP: + break; + + default: + return FDT_END; + } + + if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) + return FDT_END; /* premature end */ + + *nextoffset = FDT_TAGALIGN(offset); + return tag; +} + +int fdt_check_node_offset_(const void *fdt, int offset) +{ + if (!can_assume(VALID_INPUT) + && ((offset < 0) || (offset % FDT_TAGSIZE))) + return -FDT_ERR_BADOFFSET; + + if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int fdt_check_prop_offset_(const void *fdt, int offset) +{ + if (!can_assume(VALID_INPUT) + && ((offset < 0) || (offset % FDT_TAGSIZE))) + return -FDT_ERR_BADOFFSET; + + if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int fdt_next_node(const void *fdt, int offset, int *depth) +{ + int nextoffset = 0; + uint32_t tag; + + if (offset >= 0) + if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0) + return nextoffset; + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_PROP: + case FDT_NOP: + break; + + case FDT_BEGIN_NODE: + if (depth) + (*depth)++; + break; + + case FDT_END_NODE: + if (depth && ((--(*depth)) < 0)) + return nextoffset; + break; + + case FDT_END: + if ((nextoffset >= 0) + || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) + return -FDT_ERR_NOTFOUND; + else + return nextoffset; + } + } while (tag != FDT_BEGIN_NODE); + + return offset; +} + +int fdt_first_subnode(const void *fdt, int offset) +{ + int depth = 0; + + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth != 1) + return -FDT_ERR_NOTFOUND; + + return offset; +} + +int fdt_next_subnode(const void *fdt, int offset) +{ + int depth = 1; + + /* + * With respect to the parent, the depth of the next subnode will be + * the same as the last. + */ + do { + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth < 1) + return -FDT_ERR_NOTFOUND; + } while (depth > 1); + + return offset; +} + +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) +{ + int len = strlen(s) + 1; + const char *last = strtab + tabsize - len; + const char *p; + + for (p = strtab; p <= last; p++) + if (memcmp(p, s, len) == 0) + return p; + return NULL; +} + +int fdt_move(const void *fdt, void *buf, int bufsize) +{ + if (!can_assume(VALID_INPUT) && bufsize < 0) + return -FDT_ERR_NOSPACE; + + FDT_RO_PROBE(fdt); + + if (fdt_totalsize(fdt) > (unsigned int)bufsize) + return -FDT_ERR_NOSPACE; + + memmove(buf, fdt, fdt_totalsize(fdt)); + return 0; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_addresses.c b/arm-trusted-firmware/lib/libfdt/fdt_addresses.c new file mode 100644 index 0000000..9a82cd0 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_addresses.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2014 David Gibson + * Copyright (C) 2018 embedded brains GmbH + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_cells(const void *fdt, int nodeoffset, const char *name) +{ + const fdt32_t *c; + uint32_t val; + int len; + + c = fdt_getprop(fdt, nodeoffset, name, &len); + if (!c) + return len; + + if (len != sizeof(*c)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*c); + if (val > FDT_MAX_NCELLS) + return -FDT_ERR_BADNCELLS; + + return (int)val; +} + +int fdt_address_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == 0) + return -FDT_ERR_BADNCELLS; + if (val == -FDT_ERR_NOTFOUND) + return 2; + return val; +} + +int fdt_size_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#size-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 1; + return val; +} + +/* This function assumes that [address|size]_cells is 1 or 2 */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size) +{ + int addr_cells, size_cells, ret; + uint8_t data[sizeof(fdt64_t) * 2], *prop; + + ret = fdt_address_cells(fdt, parent); + if (ret < 0) + return ret; + addr_cells = ret; + + ret = fdt_size_cells(fdt, parent); + if (ret < 0) + return ret; + size_cells = ret; + + /* check validity of address */ + prop = data; + if (addr_cells == 1) { + if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)addr); + } else if (addr_cells == 2) { + fdt64_st(prop, addr); + } else { + return -FDT_ERR_BADNCELLS; + } + + /* check validity of size */ + prop += addr_cells * sizeof(fdt32_t); + if (size_cells == 1) { + if (size > UINT32_MAX) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)size); + } else if (size_cells == 2) { + fdt64_st(prop, size); + } else { + return -FDT_ERR_BADNCELLS; + } + + return fdt_appendprop(fdt, nodeoffset, name, data, + (addr_cells + size_cells) * sizeof(fdt32_t)); +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c b/arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c new file mode 100644 index 0000000..49d54d4 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2012 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_create_empty_tree(void *buf, int bufsize) +{ + int err; + + err = fdt_create(buf, bufsize); + if (err) + return err; + + err = fdt_finish_reservemap(buf); + if (err) + return err; + + err = fdt_begin_node(buf, ""); + if (err) + return err; + + err = fdt_end_node(buf); + if (err) + return err; + + err = fdt_finish(buf); + if (err) + return err; + + return fdt_open_into(buf, buf, bufsize); +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_overlay.c b/arm-trusted-firmware/lib/libfdt/fdt_overlay.c new file mode 100644 index 0000000..d217e79 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_overlay.c @@ -0,0 +1,882 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2016 Free Electrons + * Copyright (C) 2016 NextThing Co. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +/** + * overlay_get_target_phandle - retrieves the target phandle of a fragment + * @fdto: pointer to the device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * + * overlay_get_target_phandle() retrieves the target phandle of an + * overlay fragment when that fragment uses a phandle (target + * property) instead of a path (target-path property). + * + * returns: + * the phandle pointed by the target property + * 0, if the phandle was not found + * -1, if the phandle was malformed + */ +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) +{ + const fdt32_t *val; + int len; + + val = fdt_getprop(fdto, fragment, "target", &len); + if (!val) + return 0; + + if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) + return (uint32_t)-1; + + return fdt32_to_cpu(*val); +} + +/** + * overlay_get_target - retrieves the offset of a fragment's target + * @fdt: Base device tree blob + * @fdto: Device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL) + * + * overlay_get_target() retrieves the target offset in the base + * device tree of a fragment, no matter how the actual targeting is + * done (through a phandle or a path) + * + * returns: + * the targeted node offset in the base device tree + * Negative error code on error + */ +static int overlay_get_target(const void *fdt, const void *fdto, + int fragment, char const **pathp) +{ + uint32_t phandle; + const char *path = NULL; + int path_len = 0, ret; + + /* Try first to do a phandle based lookup */ + phandle = overlay_get_target_phandle(fdto, fragment); + if (phandle == (uint32_t)-1) + return -FDT_ERR_BADPHANDLE; + + /* no phandle, try path */ + if (!phandle) { + /* And then a path based lookup */ + path = fdt_getprop(fdto, fragment, "target-path", &path_len); + if (path) + ret = fdt_path_offset(fdt, path); + else + ret = path_len; + } else + ret = fdt_node_offset_by_phandle(fdt, phandle); + + /* + * If we haven't found either a target or a + * target-path property in a node that contains a + * __overlay__ subnode (we wouldn't be called + * otherwise), consider it a improperly written + * overlay + */ + if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) + ret = -FDT_ERR_BADOVERLAY; + + /* return on error */ + if (ret < 0) + return ret; + + /* return pointer to path (if available) */ + if (pathp) + *pathp = path ? path : NULL; + + return ret; +} + +/** + * overlay_phandle_add_offset - Increases a phandle by an offset + * @fdt: Base device tree blob + * @node: Device tree overlay blob + * @name: Name of the property to modify (phandle or linux,phandle) + * @delta: offset to apply + * + * overlay_phandle_add_offset() increments a node phandle by a given + * offset. + * + * returns: + * 0 on success. + * Negative error code on error + */ +static int overlay_phandle_add_offset(void *fdt, int node, + const char *name, uint32_t delta) +{ + const fdt32_t *val; + uint32_t adj_val; + int len; + + val = fdt_getprop(fdt, node, name, &len); + if (!val) + return len; + + if (len != sizeof(*val)) + return -FDT_ERR_BADPHANDLE; + + adj_val = fdt32_to_cpu(*val); + if ((adj_val + delta) < adj_val) + return -FDT_ERR_NOPHANDLES; + + adj_val += delta; + if (adj_val == (uint32_t)-1) + return -FDT_ERR_NOPHANDLES; + + return fdt_setprop_inplace_u32(fdt, node, name, adj_val); +} + +/** + * overlay_adjust_node_phandles - Offsets the phandles of a node + * @fdto: Device tree overlay blob + * @node: Offset of the node we want to adjust + * @delta: Offset to shift the phandles of + * + * overlay_adjust_node_phandles() adds a constant to all the phandles + * of a given node. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_node_phandles(void *fdto, int node, + uint32_t delta) +{ + int child; + int ret; + + ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + fdt_for_each_subnode(child, fdto, node) { + ret = overlay_adjust_node_phandles(fdto, child, delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_adjust_local_phandles() adds a constant to all the + * phandles of an overlay. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) +{ + /* + * Start adjusting the phandles from the overlay root + */ + return overlay_adjust_node_phandles(fdto, 0, delta); +} + +/** + * overlay_update_local_node_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @tree_node: Node offset of the node to operate on + * @fixup_node: Node offset of the matching local fixups node + * @delta: Offset to shift the phandles of + * + * overlay_update_local_nodes_references() update the phandles + * pointing to a node within the device tree overlay by adding a + * constant delta. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_node_references(void *fdto, + int tree_node, + int fixup_node, + uint32_t delta) +{ + int fixup_prop; + int fixup_child; + int ret; + + fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { + const fdt32_t *fixup_val; + const char *tree_val; + const char *name; + int fixup_len; + int tree_len; + int i; + + fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, + &name, &fixup_len); + if (!fixup_val) + return fixup_len; + + if (fixup_len % sizeof(uint32_t)) + return -FDT_ERR_BADOVERLAY; + fixup_len /= sizeof(uint32_t); + + tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); + if (!tree_val) { + if (tree_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + + return tree_len; + } + + for (i = 0; i < fixup_len; i++) { + fdt32_t adj_val; + uint32_t poffset; + + poffset = fdt32_to_cpu(fixup_val[i]); + + /* + * phandles to fixup can be unaligned. + * + * Use a memcpy for the architectures that do + * not support unaligned accesses. + */ + memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); + + adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); + + ret = fdt_setprop_inplace_namelen_partial(fdto, + tree_node, + name, + strlen(name), + poffset, + &adj_val, + sizeof(adj_val)); + if (ret == -FDT_ERR_NOSPACE) + return -FDT_ERR_BADOVERLAY; + + if (ret) + return ret; + } + } + + fdt_for_each_subnode(fixup_child, fdto, fixup_node) { + const char *fixup_child_name = fdt_get_name(fdto, fixup_child, + NULL); + int tree_child; + + tree_child = fdt_subnode_offset(fdto, tree_node, + fixup_child_name); + if (tree_child == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (tree_child < 0) + return tree_child; + + ret = overlay_update_local_node_references(fdto, + tree_child, + fixup_child, + delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_update_local_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_update_local_references() update all the phandles pointing + * to a node within the device tree overlay by adding a constant + * delta to not conflict with the base overlay. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_references(void *fdto, uint32_t delta) +{ + int fixups; + + fixups = fdt_path_offset(fdto, "/__local_fixups__"); + if (fixups < 0) { + /* There's no local phandles to adjust, bail out */ + if (fixups == -FDT_ERR_NOTFOUND) + return 0; + + return fixups; + } + + /* + * Update our local references from the root of the tree + */ + return overlay_update_local_node_references(fdto, 0, fixups, + delta); +} + +/** + * overlay_fixup_one_phandle - Set an overlay phandle to the base one + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * @symbols_off: Node offset of the symbols node in the base device tree + * @path: Path to a node holding a phandle in the overlay + * @path_len: number of path characters to consider + * @name: Name of the property holding the phandle reference in the overlay + * @name_len: number of name characters to consider + * @poffset: Offset within the overlay property where the phandle is stored + * @label: Label of the node referenced by the phandle + * + * overlay_fixup_one_phandle() resolves an overlay phandle pointing to + * a node in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_one_phandle(void *fdt, void *fdto, + int symbols_off, + const char *path, uint32_t path_len, + const char *name, uint32_t name_len, + int poffset, const char *label) +{ + const char *symbol_path; + uint32_t phandle; + fdt32_t phandle_prop; + int symbol_off, fixup_off; + int prop_len; + + if (symbols_off < 0) + return symbols_off; + + symbol_path = fdt_getprop(fdt, symbols_off, label, + &prop_len); + if (!symbol_path) + return prop_len; + + symbol_off = fdt_path_offset(fdt, symbol_path); + if (symbol_off < 0) + return symbol_off; + + phandle = fdt_get_phandle(fdt, symbol_off); + if (!phandle) + return -FDT_ERR_NOTFOUND; + + fixup_off = fdt_path_offset_namelen(fdto, path, path_len); + if (fixup_off == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (fixup_off < 0) + return fixup_off; + + phandle_prop = cpu_to_fdt32(phandle); + return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, + name, name_len, poffset, + &phandle_prop, + sizeof(phandle_prop)); +}; + +/** + * overlay_fixup_phandle - Set an overlay phandle to the base one + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * @symbols_off: Node offset of the symbols node in the base device tree + * @property: Property offset in the overlay holding the list of fixups + * + * overlay_fixup_phandle() resolves all the overlay phandles pointed + * to in a __fixups__ property, and updates them to match the phandles + * in use in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, + int property) +{ + const char *value; + const char *label; + int len; + + value = fdt_getprop_by_offset(fdto, property, + &label, &len); + if (!value) { + if (len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + + return len; + } + + do { + const char *path, *name, *fixup_end; + const char *fixup_str = value; + uint32_t path_len, name_len; + uint32_t fixup_len; + char *sep, *endptr; + int poffset, ret; + + fixup_end = memchr(value, '\0', len); + if (!fixup_end) + return -FDT_ERR_BADOVERLAY; + fixup_len = fixup_end - fixup_str; + + len -= fixup_len + 1; + value += fixup_len + 1; + + path = fixup_str; + sep = memchr(fixup_str, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + path_len = sep - path; + if (path_len == (fixup_len - 1)) + return -FDT_ERR_BADOVERLAY; + + fixup_len -= path_len + 1; + name = sep + 1; + sep = memchr(name, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + name_len = sep - name; + if (!name_len) + return -FDT_ERR_BADOVERLAY; + + poffset = strtoul(sep + 1, &endptr, 10); + if ((*endptr != '\0') || (endptr <= (sep + 1))) + return -FDT_ERR_BADOVERLAY; + + ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, + path, path_len, name, name_len, + poffset, label); + if (ret) + return ret; + } while (len > 0); + + return 0; +} + +/** + * overlay_fixup_phandles - Resolve the overlay phandles to the base + * device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_fixup_phandles() resolves all the overlay phandles pointing + * to nodes in the base device tree. + * + * This is one of the steps of the device tree overlay application + * process, when you want all the phandles in the overlay to point to + * the actual base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandles(void *fdt, void *fdto) +{ + int fixups_off, symbols_off; + int property; + + /* We can have overlays without any fixups */ + fixups_off = fdt_path_offset(fdto, "/__fixups__"); + if (fixups_off == -FDT_ERR_NOTFOUND) + return 0; /* nothing to do */ + if (fixups_off < 0) + return fixups_off; + + /* And base DTs without symbols */ + symbols_off = fdt_path_offset(fdt, "/__symbols__"); + if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) + return symbols_off; + + fdt_for_each_property_offset(property, fdto, fixups_off) { + int ret; + + ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_apply_node - Merges a node into the base device tree + * @fdt: Base Device Tree blob + * @target: Node offset in the base device tree to apply the fragment to + * @fdto: Device tree overlay blob + * @node: Node offset in the overlay holding the changes to merge + * + * overlay_apply_node() merges a node into a target base device tree + * node pointed. + * + * This is part of the final step in the device tree overlay + * application process, when all the phandles have been adjusted and + * resolved and you just have to merge overlay into the base device + * tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_apply_node(void *fdt, int target, + void *fdto, int node) +{ + int property; + int subnode; + + fdt_for_each_property_offset(property, fdto, node) { + const char *name; + const void *prop; + int prop_len; + int ret; + + prop = fdt_getprop_by_offset(fdto, property, &name, + &prop_len); + if (prop_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + if (prop_len < 0) + return prop_len; + + ret = fdt_setprop(fdt, target, name, prop, prop_len); + if (ret) + return ret; + } + + fdt_for_each_subnode(subnode, fdto, node) { + const char *name = fdt_get_name(fdto, subnode, NULL); + int nnode; + int ret; + + nnode = fdt_add_subnode(fdt, target, name); + if (nnode == -FDT_ERR_EXISTS) { + nnode = fdt_subnode_offset(fdt, target, name); + if (nnode == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + } + + if (nnode < 0) + return nnode; + + ret = overlay_apply_node(fdt, nnode, fdto, subnode); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_merge - Merge an overlay into its base device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_merge() merges an overlay into its base device tree. + * + * This is the next to last step in the device tree overlay application + * process, when all the phandles have been adjusted and resolved and + * you just have to merge overlay into the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_merge(void *fdt, void *fdto) +{ + int fragment; + + fdt_for_each_subnode(fragment, fdto, 0) { + int overlay; + int target; + int ret; + + /* + * Each fragments will have an __overlay__ node. If + * they don't, it's not supposed to be merged + */ + overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (overlay == -FDT_ERR_NOTFOUND) + continue; + + if (overlay < 0) + return overlay; + + target = overlay_get_target(fdt, fdto, fragment, NULL); + if (target < 0) + return target; + + ret = overlay_apply_node(fdt, target, fdto, overlay); + if (ret) + return ret; + } + + return 0; +} + +static int get_path_len(const void *fdt, int nodeoffset) +{ + int len = 0, namelen; + const char *name; + + FDT_RO_PROBE(fdt); + + for (;;) { + name = fdt_get_name(fdt, nodeoffset, &namelen); + if (!name) + return namelen; + + /* root? we're done */ + if (namelen == 0) + break; + + nodeoffset = fdt_parent_offset(fdt, nodeoffset); + if (nodeoffset < 0) + return nodeoffset; + len += namelen + 1; + } + + /* in case of root pretend it's "/" */ + if (len == 0) + len++; + return len; +} + +/** + * overlay_symbol_update - Update the symbols of base tree after a merge + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_symbol_update() updates the symbols of the base tree with the + * symbols of the applied overlay + * + * This is the last step in the device tree overlay application + * process, allowing the reference of overlay symbols by subsequent + * overlay operations. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_symbol_update(void *fdt, void *fdto) +{ + int root_sym, ov_sym, prop, path_len, fragment, target; + int len, frag_name_len, ret, rel_path_len; + const char *s, *e; + const char *path; + const char *name; + const char *frag_name; + const char *rel_path; + const char *target_path; + char *buf; + void *p; + + ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); + + /* if no overlay symbols exist no problem */ + if (ov_sym < 0) + return 0; + + root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); + + /* it no root symbols exist we should create them */ + if (root_sym == -FDT_ERR_NOTFOUND) + root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); + + /* any error is fatal now */ + if (root_sym < 0) + return root_sym; + + /* iterate over each overlay symbol */ + fdt_for_each_property_offset(prop, fdto, ov_sym) { + path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); + if (!path) + return path_len; + + /* verify it's a string property (terminated by a single \0) */ + if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) + return -FDT_ERR_BADVALUE; + + /* keep end marker to avoid strlen() */ + e = path + path_len; + + if (*path != '/') + return -FDT_ERR_BADVALUE; + + /* get fragment name first */ + s = strchr(path + 1, '/'); + if (!s) { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } + + frag_name = path + 1; + frag_name_len = s - path - 1; + + /* verify format; safe since "s" lies in \0 terminated prop */ + len = sizeof("/__overlay__/") - 1; + if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { + /* //__overlay__/ */ + rel_path = s + len; + rel_path_len = e - rel_path - 1; + } else if ((e - s) == len + && (memcmp(s, "/__overlay__", len - 1) == 0)) { + /* //__overlay__ */ + rel_path = ""; + rel_path_len = 0; + } else { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } + + /* find the fragment index in which the symbol lies */ + ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, + frag_name_len); + /* not found? */ + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + fragment = ret; + + /* an __overlay__ subnode must exist */ + ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + + /* get the target of the fragment */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + + /* if we have a target path use */ + if (!target_path) { + ret = get_path_len(fdt, target); + if (ret < 0) + return ret; + len = ret; + } else { + len = strlen(target_path); + } + + ret = fdt_setprop_placeholder(fdt, root_sym, name, + len + (len > 1) + rel_path_len + 1, &p); + if (ret < 0) + return ret; + + if (!target_path) { + /* again in case setprop_placeholder changed it */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + } + + buf = p; + if (len > 1) { /* target is not root */ + if (!target_path) { + ret = fdt_get_path(fdt, target, buf, len + 1); + if (ret < 0) + return ret; + } else + memcpy(buf, target_path, len + 1); + + } else + len--; + + buf[len] = '/'; + memcpy(buf + len + 1, rel_path, rel_path_len); + buf[len + 1 + rel_path_len] = '\0'; + } + + return 0; +} + +int fdt_overlay_apply(void *fdt, void *fdto) +{ + uint32_t delta; + int ret; + + FDT_RO_PROBE(fdt); + FDT_RO_PROBE(fdto); + + ret = fdt_find_max_phandle(fdt, &delta); + if (ret) + goto err; + + ret = overlay_adjust_local_phandles(fdto, delta); + if (ret) + goto err; + + ret = overlay_update_local_references(fdto, delta); + if (ret) + goto err; + + ret = overlay_fixup_phandles(fdt, fdto); + if (ret) + goto err; + + ret = overlay_merge(fdt, fdto); + if (ret) + goto err; + + ret = overlay_symbol_update(fdt, fdto); + if (ret) + goto err; + + /* + * The overlay has been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + return 0; + +err: + /* + * The overlay might have been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + /* + * The base device tree might have been damaged, erase its + * magic. + */ + fdt_set_magic(fdt, ~0); + + return ret; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_ro.c b/arm-trusted-firmware/lib/libfdt/fdt_ro.c new file mode 100644 index 0000000..91cc6fe --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_ro.c @@ -0,0 +1,859 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_nodename_eq_(const void *fdt, int offset, + const char *s, int len) +{ + int olen; + const char *p = fdt_get_name(fdt, offset, &olen); + + if (!p || olen < len) + /* short match */ + return 0; + + if (memcmp(p, s, len) != 0) + return 0; + + if (p[len] == '\0') + return 1; + else if (!memchr(s, '@', len) && (p[len] == '@')) + return 1; + else + return 0; +} + +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) +{ + int32_t totalsize; + uint32_t absoffset; + size_t len; + int err; + const char *s, *n; + + if (can_assume(VALID_INPUT)) { + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + + if (lenp) + *lenp = strlen(s); + return s; + } + totalsize = fdt_ro_probe_(fdt); + err = totalsize; + if (totalsize < 0) + goto fail; + + err = -FDT_ERR_BADOFFSET; + absoffset = stroffset + fdt_off_dt_strings(fdt); + if (absoffset >= (unsigned)totalsize) + goto fail; + len = totalsize - absoffset; + + if (fdt_magic(fdt) == FDT_MAGIC) { + if (stroffset < 0) + goto fail; + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { + if ((unsigned)stroffset >= fdt_size_dt_strings(fdt)) + goto fail; + if ((fdt_size_dt_strings(fdt) - stroffset) < len) + len = fdt_size_dt_strings(fdt) - stroffset; + } + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + unsigned int sw_stroffset = -stroffset; + + if ((stroffset >= 0) || + (sw_stroffset > fdt_size_dt_strings(fdt))) + goto fail; + if (sw_stroffset < len) + len = sw_stroffset; + } else { + err = -FDT_ERR_INTERNAL; + goto fail; + } + + s = (const char *)fdt + absoffset; + n = memchr(s, '\0', len); + if (!n) { + /* missing terminating NULL */ + err = -FDT_ERR_TRUNCATED; + goto fail; + } + + if (lenp) + *lenp = n - s; + return s; + +fail: + if (lenp) + *lenp = err; + return NULL; +} + +const char *fdt_string(const void *fdt, int stroffset) +{ + return fdt_get_string(fdt, stroffset, NULL); +} + +static int fdt_string_eq_(const void *fdt, int stroffset, + const char *s, int len) +{ + int slen; + const char *p = fdt_get_string(fdt, stroffset, &slen); + + return p && (slen == len) && (memcmp(p, s, len) == 0); +} + +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max = 0; + int offset = -1; + + while (true) { + uint32_t value; + + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + return offset; + } + + value = fdt_get_phandle(fdt, offset); + + if (value > max) + max = value; + } + + if (phandle) + *phandle = max; + + return 0; +} + +int fdt_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max; + int err; + + err = fdt_find_max_phandle(fdt, &max); + if (err < 0) + return err; + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + +static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) +{ + unsigned int offset = n * sizeof(struct fdt_reserve_entry); + unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset; + + if (!can_assume(VALID_INPUT)) { + if (absoffset < fdt_off_mem_rsvmap(fdt)) + return NULL; + if (absoffset > fdt_totalsize(fdt) - + sizeof(struct fdt_reserve_entry)) + return NULL; + } + return fdt_mem_rsv_(fdt, n); +} + +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) +{ + const struct fdt_reserve_entry *re; + + FDT_RO_PROBE(fdt); + re = fdt_mem_rsv(fdt, n); + if (!can_assume(VALID_INPUT) && !re) + return -FDT_ERR_BADOFFSET; + + *address = fdt64_ld(&re->address); + *size = fdt64_ld(&re->size); + return 0; +} + +int fdt_num_mem_rsv(const void *fdt) +{ + int i; + const struct fdt_reserve_entry *re; + + for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { + if (fdt64_ld(&re->size) == 0) + return i; + } + return -FDT_ERR_TRUNCATED; +} + +static int nextprop_(const void *fdt, int offset) +{ + uint32_t tag; + int nextoffset; + + do { + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_END: + if (nextoffset >= 0) + return -FDT_ERR_BADSTRUCTURE; + else + return nextoffset; + + case FDT_PROP: + return offset; + } + offset = nextoffset; + } while (tag == FDT_NOP); + + return -FDT_ERR_NOTFOUND; +} + +int fdt_subnode_offset_namelen(const void *fdt, int offset, + const char *name, int namelen) +{ + int depth; + + FDT_RO_PROBE(fdt); + + for (depth = 0; + (offset >= 0) && (depth >= 0); + offset = fdt_next_node(fdt, offset, &depth)) + if ((depth == 1) + && fdt_nodename_eq_(fdt, offset, name, namelen)) + return offset; + + if (depth < 0) + return -FDT_ERR_NOTFOUND; + return offset; /* error */ +} + +int fdt_subnode_offset(const void *fdt, int parentoffset, + const char *name) +{ + return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) +{ + const char *end = path + namelen; + const char *p = path; + int offset = 0; + + FDT_RO_PROBE(fdt); + + /* see if we have an alias */ + if (*path != '/') { + const char *q = memchr(path, '/', end - p); + + if (!q) + q = end; + + p = fdt_get_alias_namelen(fdt, p, q - p); + if (!p) + return -FDT_ERR_BADPATH; + offset = fdt_path_offset(fdt, p); + + p = q; + } + + while (p < end) { + const char *q; + + while (*p == '/') { + p++; + if (p == end) + return offset; + } + q = memchr(p, '/', end - p); + if (! q) + q = end; + + offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); + if (offset < 0) + return offset; + + p = q; + } + + return offset; +} + +int fdt_path_offset(const void *fdt, const char *path) +{ + return fdt_path_offset_namelen(fdt, path, strlen(path)); +} + +const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) +{ + const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); + const char *nameptr; + int err; + + if (((err = fdt_ro_probe_(fdt)) < 0) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) + goto fail; + + nameptr = nh->name; + + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { + /* + * For old FDT versions, match the naming conventions of V16: + * give only the leaf name (after all /). The actual tree + * contents are loosely checked. + */ + const char *leaf; + leaf = strrchr(nameptr, '/'); + if (leaf == NULL) { + err = -FDT_ERR_BADSTRUCTURE; + goto fail; + } + nameptr = leaf+1; + } + + if (len) + *len = strlen(nameptr); + + return nameptr; + + fail: + if (len) + *len = err; + return NULL; +} + +int fdt_first_property_offset(const void *fdt, int nodeoffset) +{ + int offset; + + if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) + return offset; + + return nextprop_(fdt, offset); +} + +int fdt_next_property_offset(const void *fdt, int offset) +{ + if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) + return offset; + + return nextprop_(fdt, offset); +} + +static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, + int offset, + int *lenp) +{ + int err; + const struct fdt_property *prop; + + if (!can_assume(VALID_INPUT) && + (err = fdt_check_prop_offset_(fdt, offset)) < 0) { + if (lenp) + *lenp = err; + return NULL; + } + + prop = fdt_offset_ptr_(fdt, offset); + + if (lenp) + *lenp = fdt32_ld(&prop->len); + + return prop; +} + +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp) +{ + /* Prior to version 16, properties may need realignment + * and this API does not work. fdt_getprop_*() will, however. */ + + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { + if (lenp) + *lenp = -FDT_ERR_BADVERSION; + return NULL; + } + + return fdt_get_property_by_offset_(fdt, offset, lenp); +} + +static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, + int offset, + const char *name, + int namelen, + int *lenp, + int *poffset) +{ + for (offset = fdt_first_property_offset(fdt, offset); + (offset >= 0); + (offset = fdt_next_property_offset(fdt, offset))) { + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!can_assume(LIBFDT_FLAWLESS) && !prop) { + offset = -FDT_ERR_INTERNAL; + break; + } + if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), + name, namelen)) { + if (poffset) + *poffset = offset; + return prop; + } + } + + if (lenp) + *lenp = offset; + return NULL; +} + + +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int offset, + const char *name, + int namelen, int *lenp) +{ + /* Prior to version 16, properties may need realignment + * and this API does not work. fdt_getprop_*() will, however. */ + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { + if (lenp) + *lenp = -FDT_ERR_BADVERSION; + return NULL; + } + + return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp, + NULL); +} + + +const struct fdt_property *fdt_get_property(const void *fdt, + int nodeoffset, + const char *name, int *lenp) +{ + return fdt_get_property_namelen(fdt, nodeoffset, name, + strlen(name), lenp); +} + +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp) +{ + int poffset; + const struct fdt_property *prop; + + prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp, + &poffset); + if (!prop) + return NULL; + + /* Handle realignment */ + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) + return prop->data + 4; + return prop->data; +} + +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!prop) + return NULL; + if (namep) { + const char *name; + int namelen; + + if (!can_assume(VALID_INPUT)) { + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), + &namelen); + if (!name) { + if (lenp) + *lenp = namelen; + return NULL; + } + *namep = name; + } else { + *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); + } + } + + /* Handle realignment */ + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) + return prop->data + 4; + return prop->data; +} + +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); +} + +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) +{ + const fdt32_t *php; + int len; + + /* FIXME: This is a bit sub-optimal, since we potentially scan + * over all the properties twice. */ + php = fdt_getprop(fdt, nodeoffset, "phandle", &len); + if (!php || (len != sizeof(*php))) { + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); + if (!php || (len != sizeof(*php))) + return 0; + } + + return fdt32_ld(php); +} + +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen) +{ + int aliasoffset; + + aliasoffset = fdt_path_offset(fdt, "/aliases"); + if (aliasoffset < 0) + return NULL; + + return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); +} + +const char *fdt_get_alias(const void *fdt, const char *name) +{ + return fdt_get_alias_namelen(fdt, name, strlen(name)); +} + +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) +{ + int pdepth = 0, p = 0; + int offset, depth, namelen; + const char *name; + + FDT_RO_PROBE(fdt); + + if (buflen < 2) + return -FDT_ERR_NOSPACE; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + while (pdepth > depth) { + do { + p--; + } while (buf[p-1] != '/'); + pdepth--; + } + + if (pdepth >= depth) { + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { + memcpy(buf + p, name, namelen); + p += namelen; + buf[p++] = '/'; + pdepth++; + } + } + + if (offset == nodeoffset) { + if (pdepth < (depth + 1)) + return -FDT_ERR_NOSPACE; + + if (p > 1) /* special case so that root path is "/", not "" */ + p--; + buf[p] = '\0'; + return 0; + } + } + + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + + return offset; /* error from fdt_next_node() */ +} + +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth) +{ + int offset, depth; + int supernodeoffset = -FDT_ERR_INTERNAL; + + FDT_RO_PROBE(fdt); + + if (supernodedepth < 0) + return -FDT_ERR_NOTFOUND; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth == supernodedepth) + supernodeoffset = offset; + + if (offset == nodeoffset) { + if (nodedepth) + *nodedepth = depth; + + if (supernodedepth > depth) + return -FDT_ERR_NOTFOUND; + else + return supernodeoffset; + } + } + + if (!can_assume(VALID_INPUT)) { + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_depth(const void *fdt, int nodeoffset) +{ + int nodedepth; + int err; + + err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); + if (err) + return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err : + -FDT_ERR_INTERNAL; + return nodedepth; +} + +int fdt_parent_offset(const void *fdt, int nodeoffset) +{ + int nodedepth = fdt_node_depth(fdt, nodeoffset); + + if (nodedepth < 0) + return nodedepth; + return fdt_supernode_atdepth_offset(fdt, nodeoffset, + nodedepth - 1, NULL); +} + +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen) +{ + int offset; + const void *val; + int len; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_getprop(), then if that didn't + * find what we want, we scan over them again making our way + * to the next node. Still it's the easiest to implement + * approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + val = fdt_getprop(fdt, offset, propname, &len); + if (val && (len == proplen) + && (memcmp(val, propval, len) == 0)) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) +{ + int offset; + + if ((phandle == 0) || (phandle == ~0U)) + return -FDT_ERR_BADPHANDLE; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we + * potentially scan each property of a node in + * fdt_get_phandle(), then if that didn't find what + * we want, we scan over them again making our way to the next + * node. Still it's the easiest to implement approach; + * performance can come later. */ + for (offset = fdt_next_node(fdt, -1, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + if (fdt_get_phandle(fdt, offset) == phandle) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) +{ + int len = strlen(str); + const char *p; + + while (listlen >= len) { + if (memcmp(str, strlist, len+1) == 0) + return 1; + p = memchr(strlist, '\0', listlen); + if (!p) + return 0; /* malformed strlist.. */ + listlen -= (p-strlist) + 1; + strlist = p + 1; + } + return 0; +} + +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) +{ + const char *list, *end; + int length, count = 0; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + list += length; + count++; + } + + return count; +} + +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) +{ + int length, len, idx = 0; + const char *list, *end; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + len = strlen(string) + 1; + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; + } + + return -FDT_ERR_NOTFOUND; +} + +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) +{ + const char *list, *end; + int length; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; + + return NULL; + } + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) { + if (lenp) + *lenp = -FDT_ERR_BADVALUE; + + return NULL; + } + + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; + } + + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; + + return NULL; +} + +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible) +{ + const void *prop; + int len; + + prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); + if (!prop) + return len; + + return !fdt_stringlist_contains(prop, len, compatible); +} + +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible) +{ + int offset, err; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_node_check_compatible(), then if + * that didn't find what we want, we scan over them again + * making our way to the next node. Still it's the easiest to + * implement approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + err = fdt_node_check_compatible(fdt, offset, compatible); + if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) + return err; + else if (err == 0) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_rw.c b/arm-trusted-firmware/lib/libfdt/fdt_rw.c new file mode 100644 index 0000000..68887b9 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_rw.c @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_blocks_misordered_(const void *fdt, + int mem_rsv_size, int struct_size) +{ + return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) + || (fdt_off_dt_struct(fdt) < + (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) + || (fdt_off_dt_strings(fdt) < + (fdt_off_dt_struct(fdt) + struct_size)) + || (fdt_totalsize(fdt) < + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); +} + +static int fdt_rw_probe_(void *fdt) +{ + if (can_assume(VALID_DTB)) + return 0; + FDT_RO_PROBE(fdt); + + if (!can_assume(LATEST) && fdt_version(fdt) < 17) + return -FDT_ERR_BADVERSION; + if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_BADLAYOUT; + if (!can_assume(LATEST) && fdt_version(fdt) > 17) + fdt_set_version(fdt, 17); + + return 0; +} + +#define FDT_RW_PROBE(fdt) \ + { \ + int err_; \ + if ((err_ = fdt_rw_probe_(fdt)) != 0) \ + return err_; \ + } + +static inline unsigned int fdt_data_size_(void *fdt) +{ + return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); +} + +static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) +{ + char *p = splicepoint; + unsigned int dsize = fdt_data_size_(fdt); + size_t soff = p - (char *)fdt; + + if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) + return -FDT_ERR_BADOFFSET; + if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen)) + return -FDT_ERR_BADOFFSET; + if (dsize - oldlen + newlen > fdt_totalsize(fdt)) + return -FDT_ERR_NOSPACE; + memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen)); + return 0; +} + +static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p, + int oldn, int newn) +{ + int delta = (newn - oldn) * sizeof(*p); + int err; + err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + if (err) + return err; + fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int fdt_splice_struct_(void *fdt, void *p, + int oldlen, int newlen) +{ + int delta = newlen - oldlen; + int err; + + if ((err = fdt_splice_(fdt, p, oldlen, newlen))) + return err; + + fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int newlen = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen); +} + +static int fdt_splice_string_(void *fdt, int newlen) +{ + void *p = (char *)fdt + + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + int err; + + if ((err = fdt_splice_(fdt, p, 0, newlen))) + return err; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); + return 0; +} + +/** + * fdt_find_add_string_() - Find or allocate a string + * + * @fdt: pointer to the device tree to check/adjust + * @s: string to find/add + * @allocated: Set to 0 if the string was found, 1 if not found and so + * allocated. Ignored if can_assume(NO_ROLLBACK) + * @return offset of string in the string table (whether found or added) + */ +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) +{ + char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); + const char *p; + char *new; + int len = strlen(s) + 1; + int err; + + if (!can_assume(NO_ROLLBACK)) + *allocated = 0; + + p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); + if (p) + /* found it */ + return (p - strtab); + + new = strtab + fdt_size_dt_strings(fdt); + err = fdt_splice_string_(fdt, len); + if (err) + return err; + + if (!can_assume(NO_ROLLBACK)) + *allocated = 1; + + memcpy(new, s, len); + return (new - strtab); +} + +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) +{ + struct fdt_reserve_entry *re; + int err; + + FDT_RW_PROBE(fdt); + + re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); + err = fdt_splice_mem_rsv_(fdt, re, 0, 1); + if (err) + return err; + + re->address = cpu_to_fdt64(address); + re->size = cpu_to_fdt64(size); + return 0; +} + +int fdt_del_mem_rsv(void *fdt, int n) +{ + struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); + + FDT_RW_PROBE(fdt); + + if (n >= fdt_num_mem_rsv(fdt)) + return -FDT_ERR_NOTFOUND; + + return fdt_splice_mem_rsv_(fdt, re, 1, 0); +} + +static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int oldlen; + int err; + + *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (!*prop) + return oldlen; + + if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(len)))) + return err; + + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int proplen; + int nextoffset; + int namestroff; + int err; + int allocated; + + if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) + return nextoffset; + + namestroff = fdt_find_add_string_(fdt, name, &allocated); + if (namestroff < 0) + return namestroff; + + *prop = fdt_offset_ptr_w_(fdt, nextoffset); + proplen = sizeof(**prop) + FDT_TAGALIGN(len); + + err = fdt_splice_struct_(fdt, *prop, 0, proplen); + if (err) { + /* Delete the string if we failed to add it */ + if (!can_assume(NO_ROLLBACK) && allocated) + fdt_del_last_string_(fdt, name); + return err; + } + + (*prop)->tag = cpu_to_fdt32(FDT_PROP); + (*prop)->nameoff = cpu_to_fdt32(namestroff); + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +int fdt_set_name(void *fdt, int nodeoffset, const char *name) +{ + char *namep; + int oldlen, newlen; + int err; + + FDT_RW_PROBE(fdt); + + namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); + if (!namep) + return oldlen; + + newlen = strlen(name); + + err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1), + FDT_TAGALIGN(newlen+1)); + if (err) + return err; + + memcpy(namep, name, newlen+1); + return 0; +} + +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data) +{ + struct fdt_property *prop; + int err; + + FDT_RW_PROBE(fdt); + + err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); + if (err == -FDT_ERR_NOTFOUND) + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + + *prop_data = prop->data; + return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + void *prop_data; + int err; + + err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); + if (err) + return err; + + if (len) + memcpy(prop_data, val, len); + return 0; +} + +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err, oldlen, newlen; + + FDT_RW_PROBE(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (prop) { + newlen = len + oldlen; + err = fdt_splice_struct_(fdt, prop->data, + FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(newlen)); + if (err) + return err; + prop->len = cpu_to_fdt32(newlen); + memcpy(prop->data + oldlen, val, len); + } else { + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + memcpy(prop->data, val, len); + } + return 0; +} + +int fdt_delprop(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len, proplen; + + FDT_RW_PROBE(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + proplen = sizeof(*prop) + FDT_TAGALIGN(len); + return fdt_splice_struct_(fdt, prop, proplen, 0); +} + +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen) +{ + struct fdt_node_header *nh; + int offset, nextoffset; + int nodelen; + int err; + uint32_t tag; + fdt32_t *endtag; + + FDT_RW_PROBE(fdt); + + offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); + if (offset >= 0) + return -FDT_ERR_EXISTS; + else if (offset != -FDT_ERR_NOTFOUND) + return offset; + + /* Try to place the new node after the parent's properties */ + fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); + + nh = fdt_offset_ptr_w_(fdt, offset); + nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; + + err = fdt_splice_struct_(fdt, nh, 0, nodelen); + if (err) + return err; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); + memcpy(nh->name, name, namelen); + endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); + *endtag = cpu_to_fdt32(FDT_END_NODE); + + return offset; +} + +int fdt_add_subnode(void *fdt, int parentoffset, const char *name) +{ + return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_del_node(void *fdt, int nodeoffset) +{ + int endoffset; + + FDT_RW_PROBE(fdt); + + endoffset = fdt_node_end_offset_(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset), + endoffset - nodeoffset, 0); +} + +static void fdt_packblocks_(const char *old, char *new, + int mem_rsv_size, int struct_size) +{ + int mem_rsv_off, struct_off, strings_off; + + mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); + struct_off = mem_rsv_off + mem_rsv_size; + strings_off = struct_off + struct_size; + + memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); + fdt_set_off_mem_rsvmap(new, mem_rsv_off); + + memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); + fdt_set_off_dt_struct(new, struct_off); + fdt_set_size_dt_struct(new, struct_size); + + memmove(new + strings_off, old + fdt_off_dt_strings(old), + fdt_size_dt_strings(old)); + fdt_set_off_dt_strings(new, strings_off); + fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); +} + +int fdt_open_into(const void *fdt, void *buf, int bufsize) +{ + int err; + int mem_rsv_size, struct_size; + int newsize; + const char *fdtstart = fdt; + const char *fdtend = fdtstart + fdt_totalsize(fdt); + char *tmp; + + FDT_RO_PROBE(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { + struct_size = fdt_size_dt_struct(fdt); + } else { + struct_size = 0; + while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) + ; + if (struct_size < 0) + return struct_size; + } + + if (can_assume(LIBFDT_ORDER) || + !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { + /* no further work necessary */ + err = fdt_move(fdt, buf, bufsize); + if (err) + return err; + fdt_set_version(buf, 17); + fdt_set_size_dt_struct(buf, struct_size); + fdt_set_totalsize(buf, bufsize); + return 0; + } + + /* Need to reorder */ + newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + + struct_size + fdt_size_dt_strings(fdt); + + if (bufsize < newsize) + return -FDT_ERR_NOSPACE; + + /* First attempt to build converted tree at beginning of buffer */ + tmp = buf; + /* But if that overlaps with the old tree... */ + if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { + /* Try right after the old tree instead */ + tmp = (char *)(uintptr_t)fdtend; + if ((tmp + newsize) > ((char *)buf + bufsize)) + return -FDT_ERR_NOSPACE; + } + + fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size); + memmove(buf, tmp, newsize); + + fdt_set_magic(buf, FDT_MAGIC); + fdt_set_totalsize(buf, bufsize); + fdt_set_version(buf, 17); + fdt_set_last_comp_version(buf, 16); + fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); + + return 0; +} + +int fdt_pack(void *fdt) +{ + int mem_rsv_size; + + FDT_RW_PROBE(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_set_totalsize(fdt, fdt_data_size_(fdt)); + + return 0; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_strerror.c b/arm-trusted-firmware/lib/libfdt/fdt_strerror.c new file mode 100644 index 0000000..b435693 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_strerror.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +struct fdt_errtabent { + const char *str; +}; + +#define FDT_ERRTABENT(val) \ + [(val)] = { .str = #val, } + +static struct fdt_errtabent fdt_errtable[] = { + FDT_ERRTABENT(FDT_ERR_NOTFOUND), + FDT_ERRTABENT(FDT_ERR_EXISTS), + FDT_ERRTABENT(FDT_ERR_NOSPACE), + + FDT_ERRTABENT(FDT_ERR_BADOFFSET), + FDT_ERRTABENT(FDT_ERR_BADPATH), + FDT_ERRTABENT(FDT_ERR_BADPHANDLE), + FDT_ERRTABENT(FDT_ERR_BADSTATE), + + FDT_ERRTABENT(FDT_ERR_TRUNCATED), + FDT_ERRTABENT(FDT_ERR_BADMAGIC), + FDT_ERRTABENT(FDT_ERR_BADVERSION), + FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), + FDT_ERRTABENT(FDT_ERR_BADLAYOUT), + FDT_ERRTABENT(FDT_ERR_INTERNAL), + FDT_ERRTABENT(FDT_ERR_BADNCELLS), + FDT_ERRTABENT(FDT_ERR_BADVALUE), + FDT_ERRTABENT(FDT_ERR_BADOVERLAY), + FDT_ERRTABENT(FDT_ERR_NOPHANDLES), + FDT_ERRTABENT(FDT_ERR_BADFLAGS), +}; +#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))) + +const char *fdt_strerror(int errval) +{ + if (errval > 0) + return ""; + else if (errval == 0) + return ""; + else if (-errval < FDT_ERRTABSIZE) { + const char *s = fdt_errtable[-errval].str; + + if (s) + return s; + } + + return ""; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_sw.c b/arm-trusted-firmware/lib/libfdt/fdt_sw.c new file mode 100644 index 0000000..68b543c --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_sw.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_sw_probe_(void *fdt) +{ + if (!can_assume(VALID_INPUT)) { + if (fdt_magic(fdt) == FDT_MAGIC) + return -FDT_ERR_BADSTATE; + else if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + } + + return 0; +} + +#define FDT_SW_PROBE(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_(fdt)) != 0) \ + return err; \ + } + +/* 'memrsv' state: Initial state after fdt_create() + * + * Allowed functions: + * fdt_add_reservemap_entry() + * fdt_finish_reservemap() [moves to 'struct' state] + */ +static int fdt_sw_probe_memrsv_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_MEMRSV(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ + return err; \ + } + +/* 'struct' state: Enter this state after fdt_finish_reservemap() + * + * Allowed functions: + * fdt_begin_node() + * fdt_end_node() + * fdt_property*() + * fdt_finish() [moves to 'complete' state] + */ +static int fdt_sw_probe_struct_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (!can_assume(VALID_INPUT) && + fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_STRUCT(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ + return err; \ + } + +static inline uint32_t sw_flags(void *fdt) +{ + /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ + return fdt_last_comp_version(fdt); +} + +/* 'complete' state: Enter this state after fdt_finish() + * + * Allowed functions: none + */ + +static void *fdt_grab_space_(void *fdt, size_t len) +{ + unsigned int offset = fdt_size_dt_struct(fdt); + unsigned int spaceleft; + + spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) + - fdt_size_dt_strings(fdt); + + if ((offset + len < offset) || (offset + len > spaceleft)) + return NULL; + + fdt_set_size_dt_struct(fdt, offset + len); + return fdt_offset_ptr_w_(fdt, offset); +} + +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) +{ + const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry)); + void *fdt = buf; + + if (bufsize < hdrsize) + return -FDT_ERR_NOSPACE; + + if (flags & ~FDT_CREATE_FLAGS_ALL) + return -FDT_ERR_BADFLAGS; + + memset(buf, 0, bufsize); + + /* + * magic and last_comp_version keep intermediate state during the fdt + * creation process, which is replaced with the proper FDT format by + * fdt_finish(). + * + * flags should be accessed with sw_flags(). + */ + fdt_set_magic(fdt, FDT_SW_MAGIC); + fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, flags); + + fdt_set_totalsize(fdt, bufsize); + + fdt_set_off_mem_rsvmap(fdt, hdrsize); + fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); + fdt_set_off_dt_strings(fdt, 0); + + return 0; +} + +int fdt_create(void *buf, int bufsize) +{ + return fdt_create_with_flags(buf, bufsize, 0); +} + +int fdt_resize(void *fdt, void *buf, int bufsize) +{ + size_t headsize, tailsize; + char *oldtail, *newtail; + + FDT_SW_PROBE(fdt); + + if (bufsize < 0) + return -FDT_ERR_NOSPACE; + + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + tailsize = fdt_size_dt_strings(fdt); + + if (!can_assume(VALID_DTB) && + headsize + tailsize > fdt_totalsize(fdt)) + return -FDT_ERR_INTERNAL; + + if ((headsize + tailsize) > (unsigned)bufsize) + return -FDT_ERR_NOSPACE; + + oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; + newtail = (char *)buf + bufsize - tailsize; + + /* Two cases to avoid clobbering data if the old and new + * buffers partially overlap */ + if (buf <= fdt) { + memmove(buf, fdt, headsize); + memmove(newtail, oldtail, tailsize); + } else { + memmove(newtail, oldtail, tailsize); + memmove(buf, fdt, headsize); + } + + fdt_set_totalsize(buf, bufsize); + if (fdt_off_dt_strings(buf)) + fdt_set_off_dt_strings(buf, bufsize); + + return 0; +} + +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) +{ + struct fdt_reserve_entry *re; + int offset; + + FDT_SW_PROBE_MEMRSV(fdt); + + offset = fdt_off_dt_struct(fdt); + if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) + return -FDT_ERR_NOSPACE; + + re = (struct fdt_reserve_entry *)((char *)fdt + offset); + re->address = cpu_to_fdt64(addr); + re->size = cpu_to_fdt64(size); + + fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); + + return 0; +} + +int fdt_finish_reservemap(void *fdt) +{ + int err = fdt_add_reservemap_entry(fdt, 0, 0); + + if (err) + return err; + + fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); + return 0; +} + +int fdt_begin_node(void *fdt, const char *name) +{ + struct fdt_node_header *nh; + int namelen; + + FDT_SW_PROBE_STRUCT(fdt); + + namelen = strlen(name) + 1; + nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); + if (! nh) + return -FDT_ERR_NOSPACE; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memcpy(nh->name, name, namelen); + return 0; +} + +int fdt_end_node(void *fdt) +{ + fdt32_t *en; + + FDT_SW_PROBE_STRUCT(fdt); + + en = fdt_grab_space_(fdt, FDT_TAGSIZE); + if (! en) + return -FDT_ERR_NOSPACE; + + *en = cpu_to_fdt32(FDT_END_NODE); + return 0; +} + +static int fdt_add_string_(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + unsigned int strtabsize = fdt_size_dt_strings(fdt); + unsigned int len = strlen(s) + 1; + unsigned int struct_top, offset; + + offset = strtabsize + len; + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + if (fdt_totalsize(fdt) - offset < struct_top) + return 0; /* no more room :( */ + + memcpy(strtab - offset, s, len); + fdt_set_size_dt_strings(fdt, strtabsize + len); + return -offset; +} + +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, strtabsize - len); +} + +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + int strtabsize = fdt_size_dt_strings(fdt); + const char *p; + + *allocated = 0; + + p = fdt_find_string_(strtab - strtabsize, strtabsize, s); + if (p) + return p - strtab; + + *allocated = 1; + + return fdt_add_string_(fdt, s); +} + +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) +{ + struct fdt_property *prop; + int nameoff; + int allocated; + + FDT_SW_PROBE_STRUCT(fdt); + + /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ + if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { + allocated = 1; + nameoff = fdt_add_string_(fdt, name); + } else { + nameoff = fdt_find_add_string_(fdt, name, &allocated); + } + if (nameoff == 0) + return -FDT_ERR_NOSPACE; + + prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); + if (! prop) { + if (allocated) + fdt_del_last_string_(fdt, name); + return -FDT_ERR_NOSPACE; + } + + prop->tag = cpu_to_fdt32(FDT_PROP); + prop->nameoff = cpu_to_fdt32(nameoff); + prop->len = cpu_to_fdt32(len); + *valp = prop->data; + return 0; +} + +int fdt_property(void *fdt, const char *name, const void *val, int len) +{ + void *ptr; + int ret; + + ret = fdt_property_placeholder(fdt, name, len, &ptr); + if (ret) + return ret; + memcpy(ptr, val, len); + return 0; +} + +int fdt_finish(void *fdt) +{ + char *p = (char *)fdt; + fdt32_t *end; + int oldstroffset, newstroffset; + uint32_t tag; + int offset, nextoffset; + + FDT_SW_PROBE_STRUCT(fdt); + + /* Add terminator */ + end = fdt_grab_space_(fdt, sizeof(*end)); + if (! end) + return -FDT_ERR_NOSPACE; + *end = cpu_to_fdt32(FDT_END); + + /* Relocate the string table */ + oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); + newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); + fdt_set_off_dt_strings(fdt, newstroffset); + + /* Walk the structure, correcting string offsets */ + offset = 0; + while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { + if (tag == FDT_PROP) { + struct fdt_property *prop = + fdt_offset_ptr_w_(fdt, offset); + int nameoff; + + nameoff = fdt32_to_cpu(prop->nameoff); + nameoff += fdt_size_dt_strings(fdt); + prop->nameoff = cpu_to_fdt32(nameoff); + } + offset = nextoffset; + } + if (nextoffset < 0) + return nextoffset; + + /* Finally, adjust the header */ + fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); + + /* And fix up fields that were keeping intermediate state. */ + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_magic(fdt, FDT_MAGIC); + + return 0; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_wip.c b/arm-trusted-firmware/lib/libfdt/fdt_wip.c new file mode 100644 index 0000000..c2d7566 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_wip.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len) +{ + void *propval; + int proplen; + + propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, + &proplen); + if (!propval) + return proplen; + + if ((unsigned)proplen < (len + idx)) + return -FDT_ERR_NOSPACE; + + memcpy((char *)propval + idx, val, len); + return 0; +} + +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + const void *propval; + int proplen; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + if (!propval) + return proplen; + + if (proplen != len) + return -FDT_ERR_NOSPACE; + + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, + strlen(name), 0, + val, len); +} + +static void fdt_nop_region_(void *start, int len) +{ + fdt32_t *p; + + for (p = start; (char *)p < ((char *)start + len); p++) + *p = cpu_to_fdt32(FDT_NOP); +} + +int fdt_nop_property(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len; + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + fdt_nop_region_(prop, len + sizeof(*prop)); + + return 0; +} + +int fdt_node_end_offset_(void *fdt, int offset) +{ + int depth = 0; + + while ((offset >= 0) && (depth >= 0)) + offset = fdt_next_node(fdt, offset, &depth); + + return offset; +} + +int fdt_nop_node(void *fdt, int nodeoffset) +{ + int endoffset; + + endoffset = fdt_node_end_offset_(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0), + endoffset - nodeoffset); + return 0; +} diff --git a/arm-trusted-firmware/lib/libfdt/libfdt.mk b/arm-trusted-firmware/lib/libfdt/libfdt.mk new file mode 100644 index 0000000..1cbbd78 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/libfdt.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +LIBFDT_SRCS := $(addprefix lib/libfdt/, \ + fdt.c \ + fdt_addresses.c \ + fdt_empty_tree.c \ + fdt_ro.c \ + fdt_rw.c \ + fdt_strerror.c \ + fdt_sw.c \ + fdt_wip.c) \ + +INCLUDES += -Iinclude/lib/libfdt + +$(eval $(call MAKE_LIB,fdt)) diff --git a/arm-trusted-firmware/lib/libfdt/libfdt_internal.h b/arm-trusted-firmware/lib/libfdt/libfdt_internal.h new file mode 100644 index 0000000..d4e0bd4 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/libfdt_internal.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_INTERNAL_H +#define LIBFDT_INTERNAL_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include + +#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) + +int32_t fdt_ro_probe_(const void *fdt); +#define FDT_RO_PROBE(fdt) \ + { \ + int32_t totalsize_; \ + if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ + return totalsize_; \ + } + +int fdt_check_node_offset_(const void *fdt, int offset); +int fdt_check_prop_offset_(const void *fdt, int offset); +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); +int fdt_node_end_offset_(void *fdt, int nodeoffset); + +static inline const void *fdt_offset_ptr_(const void *fdt, int offset) +{ + return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; +} + +static inline void *fdt_offset_ptr_w_(void *fdt, int offset) +{ + return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); +} + +static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n) +{ + const struct fdt_reserve_entry *rsv_table = + (const struct fdt_reserve_entry *) + ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); + + return rsv_table + n; +} +static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) +{ + return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); +} + +#define FDT_SW_MAGIC (~FDT_MAGIC) + +/**********************************************************************/ +/* Checking controls */ +/**********************************************************************/ + +#ifndef FDT_ASSUME_MASK +#define FDT_ASSUME_MASK 0 +#endif + +/* + * Defines assumptions which can be enabled. Each of these can be enabled + * individually. For maximum safety, don't enable any assumptions! + * + * For minimal code size and no safety, use ASSUME_PERFECT at your own risk. + * You should have another method of validating the device tree, such as a + * signature or hash check before using libfdt. + * + * For situations where security is not a concern it may be safe to enable + * ASSUME_SANE. + */ +enum { + /* + * This does essentially no checks. Only the latest device-tree + * version is correctly handled. Inconsistencies or errors in the device + * tree may cause undefined behaviour or crashes. Invalid parameters + * passed to libfdt may do the same. + * + * If an error occurs when modifying the tree it may leave the tree in + * an intermediate (but valid) state. As an example, adding a property + * where there is insufficient space may result in the property name + * being added to the string table even though the property itself is + * not added to the struct section. + * + * Only use this if you have a fully validated device tree with + * the latest supported version and wish to minimise code size. + */ + ASSUME_PERFECT = 0xff, + + /* + * This assumes that the device tree is sane. i.e. header metadata + * and basic hierarchy are correct. + * + * With this assumption enabled, normal device trees produced by libfdt + * and the compiler should be handled safely. Malicious device trees and + * complete garbage may cause libfdt to behave badly or crash. Truncated + * device trees (e.g. those only partially loaded) can also cause + * problems. + * + * Note: Only checks that relate exclusively to the device tree itself + * (not the parameters passed to libfdt) are disabled by this + * assumption. This includes checking headers, tags and the like. + */ + ASSUME_VALID_DTB = 1 << 0, + + /* + * This builds on ASSUME_VALID_DTB and further assumes that libfdt + * functions are called with valid parameters, i.e. not trigger + * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any + * extensive checking of parameters and the device tree, making various + * assumptions about correctness. + * + * It doesn't make sense to enable this assumption unless + * ASSUME_VALID_DTB is also enabled. + */ + ASSUME_VALID_INPUT = 1 << 1, + + /* + * This disables checks for device-tree version and removes all code + * which handles older versions. + * + * Only enable this if you know you have a device tree with the latest + * version. + */ + ASSUME_LATEST = 1 << 2, + + /* + * This assumes that it is OK for a failed addition to the device tree, + * due to lack of space or some other problem, to skip any rollback + * steps (such as dropping the property name from the string table). + * This is safe to enable in most circumstances, even though it may + * leave the tree in a sub-optimal state. + */ + ASSUME_NO_ROLLBACK = 1 << 3, + + /* + * This assumes that the device tree components appear in a 'convenient' + * order, i.e. the memory reservation block first, then the structure + * block and finally the string block. + * + * This order is not specified by the device-tree specification, + * but is expected by libfdt. The device-tree compiler always created + * device trees with this order. + * + * This assumption disables a check in fdt_open_into() and removes the + * ability to fix the problem there. This is safe if you know that the + * device tree is correctly ordered. See fdt_blocks_misordered_(). + */ + ASSUME_LIBFDT_ORDER = 1 << 4, + + /* + * This assumes that libfdt itself does not have any internal bugs. It + * drops certain checks that should never be needed unless libfdt has an + * undiscovered bug. + * + * This can generally be considered safe to enable. + */ + ASSUME_LIBFDT_FLAWLESS = 1 << 5, +}; + +/** + * can_assume_() - check if a particular assumption is enabled + * + * @mask: Mask to check (ASSUME_...) + * @return true if that assumption is enabled, else false + */ +static inline bool can_assume_(int mask) +{ + return FDT_ASSUME_MASK & mask; +} + +/** helper macros for checking assumptions */ +#define can_assume(_assume) can_assume_(ASSUME_ ## _assume) + +#endif /* LIBFDT_INTERNAL_H */ diff --git a/arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c b/arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c new file mode 100644 index 0000000..748eedd --- /dev/null +++ b/arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +/* + * Functions in this file implement Bakery Algorithm for mutual exclusion with the + * bakery lock data structures in coherent memory. + * + * ARM architecture offers a family of exclusive access instructions to + * efficiently implement mutual exclusion with hardware support. However, as + * well as depending on external hardware, the these instructions have defined + * behavior only on certain memory types (cacheable and Normal memory in + * particular; see ARMv8 Architecture Reference Manual section B2.10). Use cases + * in trusted firmware are such that mutual exclusion implementation cannot + * expect that accesses to the lock have the specific type required by the + * architecture for these primitives to function (for example, not all + * contenders may have address translation enabled). + * + * This implementation does not use mutual exclusion primitives. It expects + * memory regions where the locks reside to be fully ordered and coherent + * (either by disabling address translation, or by assigning proper attributes + * when translation is enabled). + * + * Note that the ARM architecture guarantees single-copy atomicity for aligned + * accesses regardless of status of address translation. + */ + +#define assert_bakery_entry_valid(_entry, _bakery) do { \ + assert((_bakery) != NULL); \ + assert((_entry) < BAKERY_LOCK_MAX_CPUS); \ +} while (false) + +/* Obtain a ticket for a given CPU */ +static unsigned int bakery_get_ticket(bakery_lock_t *bakery, unsigned int me) +{ + unsigned int my_ticket, their_ticket; + unsigned int they; + + /* Prevent recursive acquisition */ + assert(bakery_ticket_number(bakery->lock_data[me]) == 0U); + + /* + * Flag that we're busy getting our ticket. All CPUs are iterated in the + * order of their ordinal position to decide the maximum ticket value + * observed so far. Our priority is set to be greater than the maximum + * observed priority + * + * Note that it's possible that more than one contender gets the same + * ticket value. That's OK as the lock is acquired based on the priority + * value, not the ticket value alone. + */ + my_ticket = 0U; + bakery->lock_data[me] = make_bakery_data(CHOOSING_TICKET, my_ticket); + for (they = 0U; they < BAKERY_LOCK_MAX_CPUS; they++) { + their_ticket = bakery_ticket_number(bakery->lock_data[they]); + if (their_ticket > my_ticket) + my_ticket = their_ticket; + } + + /* + * Compute ticket; then signal to other contenders waiting for us to + * finish calculating our ticket value that we're done + */ + ++my_ticket; + bakery->lock_data[me] = make_bakery_data(CHOSEN_TICKET, my_ticket); + + return my_ticket; +} + + +/* + * Acquire bakery lock + * + * Contending CPUs need first obtain a non-zero ticket and then calculate + * priority value. A contending CPU iterate over all other CPUs in the platform, + * which may be contending for the same lock, in the order of their ordinal + * position (CPU0, CPU1 and so on). A non-contending CPU will have its ticket + * (and priority) value as 0. The contending CPU compares its priority with that + * of others'. The CPU with the highest priority (lowest numerical value) + * acquires the lock + */ +void bakery_lock_get(bakery_lock_t *bakery) +{ + unsigned int they, me; + unsigned int my_ticket, my_prio, their_ticket; + unsigned int their_bakery_data; + + me = plat_my_core_pos(); + + assert_bakery_entry_valid(me, bakery); + + /* Get a ticket */ + my_ticket = bakery_get_ticket(bakery, me); + + /* + * Now that we got our ticket, compute our priority value, then compare + * with that of others, and proceed to acquire the lock + */ + my_prio = bakery_get_priority(my_ticket, me); + for (they = 0U; they < BAKERY_LOCK_MAX_CPUS; they++) { + if (me == they) + continue; + + /* Wait for the contender to get their ticket */ + do { + their_bakery_data = bakery->lock_data[they]; + } while (bakery_is_choosing(their_bakery_data)); + + /* + * If the other party is a contender, they'll have non-zero + * (valid) ticket value. If they do, compare priorities + */ + their_ticket = bakery_ticket_number(their_bakery_data); + if ((their_ticket != 0U) && + (bakery_get_priority(their_ticket, they) < my_prio)) { + /* + * They have higher priority (lower value). Wait for + * their ticket value to change (either release the lock + * to have it dropped to 0; or drop and probably content + * again for the same lock to have an even higher value) + */ + do { + wfe(); + } while (their_ticket == + bakery_ticket_number(bakery->lock_data[they])); + } + } + + /* + * Lock acquired. Ensure that any reads and writes from a shared + * resource in the critical section read/write values after the lock is + * acquired. + */ + dmbish(); +} + + +/* Release the lock and signal contenders */ +void bakery_lock_release(bakery_lock_t *bakery) +{ + unsigned int me = plat_my_core_pos(); + + assert_bakery_entry_valid(me, bakery); + assert(bakery_ticket_number(bakery->lock_data[me]) != 0U); + + /* + * Ensure that other observers see any stores in the critical section + * before releasing the lock. Also ensure all loads in the critical + * section are complete before releasing the lock. Release the lock by + * resetting ticket. Then signal other waiting contenders. + */ + dmbish(); + bakery->lock_data[me] = 0U; + + /* Required to ensure ordering of the following sev */ + dsb(); + sev(); +} diff --git a/arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c b/arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c new file mode 100644 index 0000000..7d35dea --- /dev/null +++ b/arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2015-2020, 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 + +/* + * Functions in this file implement Bakery Algorithm for mutual exclusion with the + * bakery lock data structures in cacheable and Normal memory. + * + * ARM architecture offers a family of exclusive access instructions to + * efficiently implement mutual exclusion with hardware support. However, as + * well as depending on external hardware, these instructions have defined + * behavior only on certain memory types (cacheable and Normal memory in + * particular; see ARMv8 Architecture Reference Manual section B2.10). Use cases + * in trusted firmware are such that mutual exclusion implementation cannot + * expect that accesses to the lock have the specific type required by the + * architecture for these primitives to function (for example, not all + * contenders may have address translation enabled). + * + * This implementation does not use mutual exclusion primitives. It expects + * memory regions where the locks reside to be cacheable and Normal. + * + * Note that the ARM architecture guarantees single-copy atomicity for aligned + * accesses regardless of status of address translation. + */ + +#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE +/* + * Verify that the platform defined value for the per-cpu space for bakery locks is + * a multiple of the cache line size, to prevent multiple CPUs writing to the same + * bakery lock cache line + * + * Using this value, if provided, rather than the linker generated value results in + * more efficient code + */ +CASSERT((PLAT_PERCPU_BAKERY_LOCK_SIZE & (CACHE_WRITEBACK_GRANULE - 1)) == 0, \ + PLAT_PERCPU_BAKERY_LOCK_SIZE_not_cacheline_multiple); +#define PERCPU_BAKERY_LOCK_SIZE (PLAT_PERCPU_BAKERY_LOCK_SIZE) +#else +/* + * Use the linker defined symbol which has evaluated the size reqiurement. + * This is not as efficient as using a platform defined constant + */ +IMPORT_SYM(uintptr_t, __PERCPU_BAKERY_LOCK_START__, BAKERY_LOCK_START); +IMPORT_SYM(uintptr_t, __PERCPU_BAKERY_LOCK_END__, BAKERY_LOCK_END); +#define PERCPU_BAKERY_LOCK_SIZE (BAKERY_LOCK_END - BAKERY_LOCK_START) +#endif + +static inline bakery_lock_t *get_bakery_info(unsigned int cpu_ix, + bakery_lock_t *lock) +{ + return (bakery_info_t *)((uintptr_t)lock + + cpu_ix * PERCPU_BAKERY_LOCK_SIZE); +} + +static inline void write_cache_op(uintptr_t addr, bool cached) +{ + if (cached) + dccvac(addr); + else + dcivac(addr); + + dsbish(); +} + +static inline void read_cache_op(uintptr_t addr, bool cached) +{ + if (cached) + dccivac(addr); + + dmbish(); +} + +/* Helper function to check if the lock is acquired */ +static inline bool is_lock_acquired(const bakery_info_t *my_bakery_info, + bool is_cached) +{ + /* + * Even though lock data is updated only by the owning cpu and + * appropriate cache maintenance operations are performed, + * if the previous update was done when the cpu was not participating + * in coherency, then there is a chance that cache maintenance + * operations were not propagated to all the caches in the system. + * Hence do a `read_cache_op()` prior to read. + */ + read_cache_op((uintptr_t)my_bakery_info, is_cached); + return bakery_ticket_number(my_bakery_info->lock_data) != 0U; +} + +static unsigned int bakery_get_ticket(bakery_lock_t *lock, + unsigned int me, bool is_cached) +{ + unsigned int my_ticket, their_ticket; + unsigned int they; + bakery_info_t *my_bakery_info, *their_bakery_info; + + /* + * Obtain a reference to the bakery information for this cpu and ensure + * it is not NULL. + */ + my_bakery_info = get_bakery_info(me, lock); + assert(my_bakery_info != NULL); + + /* Prevent recursive acquisition.*/ + assert(!is_lock_acquired(my_bakery_info, is_cached)); + + /* + * Tell other contenders that we are through the bakery doorway i.e. + * going to allocate a ticket for this cpu. + */ + my_ticket = 0U; + my_bakery_info->lock_data = make_bakery_data(CHOOSING_TICKET, my_ticket); + + write_cache_op((uintptr_t)my_bakery_info, is_cached); + + /* + * Iterate through the bakery information of each contender to allocate + * the highest ticket number for this cpu. + */ + for (they = 0U; they < BAKERY_LOCK_MAX_CPUS; they++) { + if (me == they) + continue; + + /* + * Get a reference to the other contender's bakery info and + * ensure that a stale copy is not read. + */ + their_bakery_info = get_bakery_info(they, lock); + assert(their_bakery_info != NULL); + + read_cache_op((uintptr_t)their_bakery_info, is_cached); + + /* + * Update this cpu's ticket number if a higher ticket number is + * seen + */ + their_ticket = bakery_ticket_number(their_bakery_info->lock_data); + if (their_ticket > my_ticket) + my_ticket = their_ticket; + } + + /* + * Compute ticket; then signal to other contenders waiting for us to + * finish calculating our ticket value that we're done + */ + ++my_ticket; + my_bakery_info->lock_data = make_bakery_data(CHOSEN_TICKET, my_ticket); + + write_cache_op((uintptr_t)my_bakery_info, is_cached); + + return my_ticket; +} + +void bakery_lock_get(bakery_lock_t *lock) +{ + unsigned int they, me; + unsigned int my_ticket, my_prio, their_ticket; + bakery_info_t *their_bakery_info; + unsigned int their_bakery_data; + bool is_cached; + + me = plat_my_core_pos(); + is_cached = is_dcache_enabled(); + + /* Get a ticket */ + my_ticket = bakery_get_ticket(lock, me, is_cached); + + /* + * Now that we got our ticket, compute our priority value, then compare + * with that of others, and proceed to acquire the lock + */ + my_prio = bakery_get_priority(my_ticket, me); + for (they = 0U; they < BAKERY_LOCK_MAX_CPUS; they++) { + if (me == they) + continue; + + /* + * Get a reference to the other contender's bakery info and + * ensure that a stale copy is not read. + */ + their_bakery_info = get_bakery_info(they, lock); + assert(their_bakery_info != NULL); + + /* Wait for the contender to get their ticket */ + do { + read_cache_op((uintptr_t)their_bakery_info, is_cached); + their_bakery_data = their_bakery_info->lock_data; + } while (bakery_is_choosing(their_bakery_data)); + + /* + * If the other party is a contender, they'll have non-zero + * (valid) ticket value. If they do, compare priorities + */ + their_ticket = bakery_ticket_number(their_bakery_data); + if (their_ticket && (bakery_get_priority(their_ticket, they) < my_prio)) { + /* + * They have higher priority (lower value). Wait for + * their ticket value to change (either release the lock + * to have it dropped to 0; or drop and probably content + * again for the same lock to have an even higher value) + */ + do { + wfe(); + read_cache_op((uintptr_t)their_bakery_info, is_cached); + } while (their_ticket + == bakery_ticket_number(their_bakery_info->lock_data)); + } + } + + /* + * Lock acquired. Ensure that any reads and writes from a shared + * resource in the critical section read/write values after the lock is + * acquired. + */ + dmbish(); +} + +void bakery_lock_release(bakery_lock_t *lock) +{ + bakery_info_t *my_bakery_info; + bool is_cached = is_dcache_enabled(); + + my_bakery_info = get_bakery_info(plat_my_core_pos(), lock); + + assert(is_lock_acquired(my_bakery_info, is_cached)); + + /* + * Ensure that other observers see any stores in the critical section + * before releasing the lock. Also ensure all loads in the critical + * section are complete before releasing the lock. Release the lock by + * resetting ticket. Then signal other waiting contenders. + */ + dmbish(); + my_bakery_info->lock_data = 0U; + write_cache_op((uintptr_t)my_bakery_info, is_cached); + + /* This sev is ordered by the dsbish in write_cahce_op */ + sev(); +} diff --git a/arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S b/arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S new file mode 100644 index 0000000..9492cc0 --- /dev/null +++ b/arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl spin_lock + .globl spin_unlock + +#if ARM_ARCH_AT_LEAST(8, 0) +/* + * According to the ARMv8-A Architecture Reference Manual, "when the global + * monitor for a PE changes from Exclusive Access state to Open Access state, + * an event is generated.". This applies to both AArch32 and AArch64 modes of + * ARMv8-A. As a result, no explicit SEV with unlock is required. + */ +#define COND_SEV() +#else +#define COND_SEV() sev +#endif + +func spin_lock + mov r2, #1 +1: + ldrex r1, [r0] + cmp r1, #0 + wfene + strexeq r1, r2, [r0] + cmpeq r1, #0 + bne 1b + dmb + bx lr +endfunc spin_lock + + +func spin_unlock + mov r1, #0 + stl r1, [r0] + COND_SEV() + bx lr +endfunc spin_unlock diff --git a/arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S b/arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S new file mode 100644 index 0000000..e941b8a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/mpmm/mpmm.c b/arm-trusted-firmware/lib/mpmm/mpmm.c new file mode 100644 index 0000000..dc61cf6 --- /dev/null +++ b/arm-trusted-firmware/lib/mpmm/mpmm.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#if ENABLE_MPMM_FCONF +# include +# include +#endif + +static uint64_t read_cpuppmcr_el3_mpmmpinctl(void) +{ + return (read_cpuppmcr_el3() >> CPUPPMCR_EL3_MPMMPINCTL_SHIFT) & + CPUPPMCR_EL3_MPMMPINCTL_MASK; +} + +static void write_cpumpmmcr_el3_mpmm_en(uint64_t mpmm_en) +{ + uint64_t value = read_cpumpmmcr_el3(); + + value &= ~(CPUMPMMCR_EL3_MPMM_EN_MASK << CPUMPMMCR_EL3_MPMM_EN_SHIFT); + value |= (mpmm_en & CPUMPMMCR_EL3_MPMM_EN_MASK) << + CPUMPMMCR_EL3_MPMM_EN_SHIFT; + + write_cpumpmmcr_el3(value); +} + +static bool mpmm_supported(void) +{ + bool supported = false; + const struct mpmm_topology *topology; + +#if ENABLE_MPMM_FCONF + topology = FCONF_GET_PROPERTY(mpmm, config, topology); +#else + topology = plat_mpmm_topology(); +#endif /* ENABLE_MPMM_FCONF */ + + /* + * For the current core firstly try to find out if the platform + * configuration has claimed support for MPMM, then make sure that MPMM + * is controllable through the system registers. + */ + + if (topology != NULL) { + unsigned int core_pos = plat_my_core_pos(); + + supported = topology->cores[core_pos].supported && + (read_cpuppmcr_el3_mpmmpinctl() == 0U); + } else { + ERROR("MPMM: failed to generate MPMM topology\n"); + } + + return supported; +} + +/* Defaults to false */ +static bool mpmm_disable_for_errata; + +void mpmm_enable(void) +{ + if (mpmm_supported()) { + if (mpmm_disable_for_errata) { + WARN("MPMM: disabled by errata workaround\n"); + return; + } + write_cpumpmmcr_el3_mpmm_en(1U); + } +} + +/* + * This function is called from assembly code very early in BL31 so it must be + * small and simple. + */ +void mpmm_errata_disable(void) +{ + mpmm_disable_for_errata = true; +} diff --git a/arm-trusted-firmware/lib/mpmm/mpmm.mk b/arm-trusted-firmware/lib/mpmm/mpmm.mk new file mode 100644 index 0000000..826f925 --- /dev/null +++ b/arm-trusted-firmware/lib/mpmm/mpmm.mk @@ -0,0 +1,29 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/extensions/amu/amu.mk +include lib/fconf/fconf.mk + +ifneq (${ENABLE_MPMM},0) + ifneq ($(ARCH),aarch64) + $(error MPMM support (`ENABLE_MPMM`) can only be enabled in AArch64 images (`ARCH`)) + endif + + ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) # For MPMM gear AMU counters + $(error MPMM support (`ENABLE_MPM`) requires auxiliary AMU counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`)) + endif +endif + +MPMM_SOURCES := lib/mpmm/mpmm.c +MPMM_SOURCES += ${AMU_SOURCES} + +ifneq (${ENABLE_MPMM_FCONF},0) + ifeq (${ENABLE_MPMM},0) + $(error MPMM FCONF support (`ENABLE_MPMM_FCONF`) requires MPMM support (`ENABLE_MPMM`)) + endif + + MPMM_SOURCES += ${FCONF_MPMM_SOURCES} +endif diff --git a/arm-trusted-firmware/lib/optee/optee_utils.c b/arm-trusted-firmware/lib/optee/optee_utils.c new file mode 100644 index 0000000..72979cd --- /dev/null +++ b/arm-trusted-firmware/lib/optee/optee_utils.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * load_addr_hi and load_addr_lo: image load address. + * image_id: 0 - pager, 1 - paged + * size: image size in bytes. + */ +typedef struct optee_image { + uint32_t load_addr_hi; + uint32_t load_addr_lo; + uint32_t image_id; + uint32_t size; +} optee_image_t; + +#define OPTEE_PAGER_IMAGE_ID 0 +#define OPTEE_PAGED_IMAGE_ID 1 + +#define OPTEE_MAX_NUM_IMAGES 2u + +#define TEE_MAGIC_NUM_OPTEE 0x4554504f +/* + * magic: header magic number. + * version: OPTEE header version: + * 1 - not supported + * 2 - supported + * arch: OPTEE os architecture type: 0 - AARCH32, 1 - AARCH64. + * flags: unused currently. + * nb_images: number of images. + */ +typedef struct optee_header { + uint32_t magic; + uint8_t version; + uint8_t arch; + uint16_t flags; + uint32_t nb_images; + optee_image_t optee_image_list[]; +} optee_header_t; + +/******************************************************************************* + * Check if it is a valid tee header + * Return true if valid + * Return false if invalid + ******************************************************************************/ +static bool tee_validate_header(optee_header_t *header) +{ + if ((header->magic == TEE_MAGIC_NUM_OPTEE) && + (header->version == 2u) && + (header->nb_images > 0u) && + (header->nb_images <= OPTEE_MAX_NUM_IMAGES)) { + return true; + } + + return false; +} + +bool optee_header_is_valid(uintptr_t header_base) +{ + return tee_validate_header((optee_header_t *)header_base); +} + +/******************************************************************************* + * Parse the OPTEE image + * Return 0 on success or a negative error code otherwise. + ******************************************************************************/ +static int parse_optee_image(image_info_t *image_info, + optee_image_t *image) +{ + uintptr_t init_load_addr, free_end, requested_end; + size_t init_size; + + init_load_addr = ((uint64_t)image->load_addr_hi << 32) | + image->load_addr_lo; + init_size = image->size; + + /* + * image->load_addr_hi & image->load_addr_lo set to UINT32_MAX indicate + * loader decided address; take our pre-mapped area for current image + * since arm-tf could not allocate memory dynamically + */ + if ((image->load_addr_hi == UINT32_MAX) && + (image->load_addr_lo == UINT32_MAX)) { + init_load_addr = image_info->image_base; + } + + /* Check that the default end address doesn't overflow */ + if (check_uptr_overflow(image_info->image_base, + image_info->image_max_size - 1)) + return -1; + free_end = image_info->image_base + (image_info->image_max_size - 1); + + /* Check that the image end address doesn't overflow */ + if (check_uptr_overflow(init_load_addr, init_size - 1)) + return -1; + requested_end = init_load_addr + (init_size - 1); + /* + * Check that the requested RAM location is within reserved + * space for OPTEE. + */ + if (!((init_load_addr >= image_info->image_base) && + (requested_end <= free_end))) { + WARN("The load address in optee header %p - %p is not in reserved area: %p - %p.\n", + (void *)init_load_addr, + (void *)(init_load_addr + init_size), + (void *)image_info->image_base, + (void *)(image_info->image_base + + image_info->image_max_size)); + return -1; + } + + /* + * Remove the skip attr from image_info, the image will be loaded. + * The default attr in image_info is "IMAGE_ATTRIB_SKIP_LOADING", which + * mean the image will not be loaded. Here, we parse the header image to + * know that the extra image need to be loaded, so remove the skip attr. + */ + image_info->h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; + + /* Update image base and size of image_info */ + image_info->image_base = init_load_addr; + image_info->image_size = init_size; + + return 0; +} + +/******************************************************************************* + * Parse the OPTEE header + * Return 0 on success or a negative error code otherwise. + ******************************************************************************/ +int parse_optee_header(entry_point_info_t *header_ep, + image_info_t *pager_image_info, + image_info_t *paged_image_info) + +{ + optee_header_t *header; + uint32_t num; + int ret; + + assert(header_ep); + header = (optee_header_t *)header_ep->pc; + assert(header); + + /* Print the OPTEE header information */ + INFO("OPTEE ep=0x%x\n", (unsigned int)header_ep->pc); + INFO("OPTEE header info:\n"); + INFO(" magic=0x%x\n", header->magic); + INFO(" version=0x%x\n", header->version); + INFO(" arch=0x%x\n", header->arch); + INFO(" flags=0x%x\n", header->flags); + INFO(" nb_images=0x%x\n", header->nb_images); + + /* + * OPTEE image has 3 types: + * + * 1. Plain OPTEE bin without header. + * Original bin without header, return directly, + * BL32_EXTRA1_IMAGE_ID and BL32_EXTRA2_IMAGE_ID will be skipped. + * + * 2. OPTEE bin with header bin, but no paging. + * Header available and nb_images = 1, remove skip attr for + * BL32_EXTRA1_IMAGE_ID. BL32_EXTRA1_IMAGE_ID will be loaded, + * and BL32_EXTRA2_IMAGE_ID be skipped. + * + * 3. OPTEE image with paging support. + * Header available and nb_images = 2, there are 3 bins: header, + * pager and pageable. Remove skip attr for BL32_EXTRA1_IMAGE_ID + * and BL32_EXTRA2_IMAGE_ID to load pager and paged bin. + */ + if (!tee_validate_header(header)) { + INFO("Invalid OPTEE header, set legacy mode.\n"); +#ifdef __aarch64__ + header_ep->args.arg0 = MODE_RW_64; +#else + header_ep->args.arg0 = MODE_RW_32; +#endif + return 0; + } + + /* Parse OPTEE image */ + for (num = 0U; num < header->nb_images; num++) { + if (header->optee_image_list[num].image_id == + OPTEE_PAGER_IMAGE_ID) { + ret = parse_optee_image(pager_image_info, + &header->optee_image_list[num]); + } else if (header->optee_image_list[num].image_id == + OPTEE_PAGED_IMAGE_ID) { + ret = parse_optee_image(paged_image_info, + &header->optee_image_list[num]); + } else { + ERROR("Parse optee image failed.\n"); + return -1; + } + + if (ret != 0) + return -1; + } + + /* + * Update "pc" value which should comes from pager image. After the + * header image is parsed, it will be unuseful, and the actual + * execution image after BL31 is pager image. + */ + header_ep->pc = pager_image_info->image_base; + + /* + * The paged load address and size are populated in + * header image arguments so that can be read by the + * BL32 SPD. + */ + header_ep->args.arg1 = paged_image_info->image_base; + header_ep->args.arg2 = paged_image_info->image_size; + + /* Set OPTEE runtime arch - aarch32/aarch64 */ + if (header->arch == 0) { + header_ep->args.arg0 = MODE_RW_32; + } else { +#ifdef __aarch64__ + header_ep->args.arg0 = MODE_RW_64; +#else + ERROR("Cannot boot an AArch64 OP-TEE\n"); + return -1; +#endif + } + + return 0; +} diff --git a/arm-trusted-firmware/lib/pmf/pmf_main.c b/arm-trusted-firmware/lib/pmf/pmf_main.c new file mode 100644 index 0000000..131a055 --- /dev/null +++ b/arm-trusted-firmware/lib/pmf/pmf_main.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * The 'pmf_svc_descs' array holds the PMF service descriptors exported by + * services by placing them in the 'pmf_svc_descs' linker section. + * The 'pmf_svc_descs_indices' array holds the index of a descriptor in the + * 'pmf_svc_descs' array. The TIF[15:10] bits in the time-stamp id are used + * to get an index into the 'pmf_svc_descs_indices' array. This gives the + * index of the descriptor in the 'pmf_svc_descs' array which contains the + * service function pointers. + ******************************************************************************/ + +IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_START__, PMF_SVC_DESCS_START); +IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_END__, PMF_SVC_DESCS_END); +IMPORT_SYM(uintptr_t, __PMF_PERCPU_TIMESTAMP_END__, PMF_PERCPU_TIMESTAMP_END); +IMPORT_SYM(uintptr_t, __PMF_TIMESTAMP_START__, PMF_TIMESTAMP_ARRAY_START); + +#define PMF_PERCPU_TIMESTAMP_SIZE (PMF_PERCPU_TIMESTAMP_END - PMF_TIMESTAMP_ARRAY_START) + +#define PMF_SVC_DESCS_MAX 10 + +/* + * This is used to traverse through registered PMF services. + */ +static pmf_svc_desc_t *pmf_svc_descs; + +/* + * This array is used to store registered PMF services in sorted order. + */ +static int pmf_svc_descs_indices[PMF_SVC_DESCS_MAX]; + +/* + * This is used to track total number of successfully registered PMF services. + */ +static int pmf_num_services; + +/* + * This is the main PMF function that initialize registered + * PMF services and also sort them in ascending order. + */ +int pmf_setup(void) +{ + int rc, ii, jj = 0; + int pmf_svc_descs_num, temp_val; + + /* If no PMF services are registered then simply bail out */ + pmf_svc_descs_num = (PMF_SVC_DESCS_END - PMF_SVC_DESCS_START)/ + sizeof(pmf_svc_desc_t); + if (pmf_svc_descs_num == 0) + return 0; + + assert(pmf_svc_descs_num < PMF_SVC_DESCS_MAX); + + pmf_svc_descs = (pmf_svc_desc_t *) PMF_SVC_DESCS_START; + for (ii = 0; ii < pmf_svc_descs_num; ii++) { + + assert(pmf_svc_descs[ii].get_ts != NULL); + + /* + * Call the initialization routine for this + * PMF service, if it is defined. + */ + if (pmf_svc_descs[ii].init != NULL) { + rc = pmf_svc_descs[ii].init(); + if (rc != 0) { + WARN("Could not initialize PMF" + "service %s - skipping \n", + pmf_svc_descs[ii].name); + continue; + } + } + + /* Update the pmf_svc_descs_indices array */ + pmf_svc_descs_indices[jj++] = ii; + } + + pmf_num_services = jj; + + /* + * Sort the successfully registered PMF services + * according to service ID + */ + for (ii = 1; ii < pmf_num_services; ii++) { + for (jj = 0; jj < (pmf_num_services - ii); jj++) { + if ((pmf_svc_descs[jj].svc_config & PMF_SVC_ID_MASK) > + (pmf_svc_descs[jj + 1].svc_config & + PMF_SVC_ID_MASK)) { + temp_val = pmf_svc_descs_indices[jj]; + pmf_svc_descs_indices[jj] = + pmf_svc_descs_indices[jj+1]; + pmf_svc_descs_indices[jj+1] = temp_val; + } + } + } + + return 0; +} + +/* + * This function implements binary search to find registered + * PMF service based on Service ID provided in `tid` argument. + */ +static pmf_svc_desc_t *get_service(unsigned int tid) +{ + int low = 0; + int mid; + int high = pmf_num_services; + unsigned int svc_id = tid & PMF_SVC_ID_MASK; + int index; + unsigned int desc_svc_id; + + if (pmf_num_services == 0) + return NULL; + + assert(pmf_svc_descs != NULL); + + do { + mid = (low + high) / 2; + index = pmf_svc_descs_indices[mid]; + + desc_svc_id = pmf_svc_descs[index].svc_config & PMF_SVC_ID_MASK; + if (svc_id < desc_svc_id) + high = mid - 1; + if (svc_id > desc_svc_id) + low = mid + 1; + } while ((svc_id != desc_svc_id) && (low <= high)); + + /* + * Make sure the Service found supports the tid range. + */ + if ((svc_id == desc_svc_id) && ((tid & PMF_TID_MASK) < + (pmf_svc_descs[index].svc_config & PMF_TID_MASK))) + return (pmf_svc_desc_t *)&pmf_svc_descs[index]; + + return NULL; +} + +/* + * This function gets the time-stamp value for the PMF services + * registered for SMC interface based on `tid` and `mpidr`. + */ +int pmf_get_timestamp_smc(unsigned int tid, + u_register_t mpidr, + unsigned int flags, + unsigned long long *ts_value) +{ + pmf_svc_desc_t *svc_desc; + assert(ts_value != NULL); + + /* Search for registered service. */ + svc_desc = get_service(tid); + + if ((svc_desc == NULL) || (plat_core_pos_by_mpidr(mpidr) < 0)) { + *ts_value = 0; + return -EINVAL; + } else { + /* Call the service time-stamp handler. */ + *ts_value = svc_desc->get_ts(tid, mpidr, flags); + return 0; + } +} + +/* + * This function can be used to dump `ts` value for given `tid`. + * Assumption is that the console is already initialized. + */ +void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts) +{ + printf("PMF:cpu %u tid %u ts %llu\n", + plat_my_core_pos(), tid, ts); +} + +/* + * This function calculate the address identified by + * `base_addr`, `tid` and `cpuid`. + */ +static inline uintptr_t calc_ts_addr(uintptr_t base_addr, + unsigned int tid, + unsigned int cpuid) +{ + assert(cpuid < PLATFORM_CORE_COUNT); + assert(base_addr >= PMF_TIMESTAMP_ARRAY_START); + assert(base_addr < ((PMF_TIMESTAMP_ARRAY_START + + PMF_PERCPU_TIMESTAMP_SIZE) - ((tid & PMF_TID_MASK) * + sizeof(unsigned long long)))); + + base_addr += ((cpuid * PMF_PERCPU_TIMESTAMP_SIZE) + + ((tid & PMF_TID_MASK) * sizeof(unsigned long long))); + + return base_addr; +} + +/* + * This function stores the `ts` value to the storage identified by + * `base_addr`, `tid` and current cpu id. + * Note: The timestamp addresses are cache line aligned per cpu + * and only the owning CPU would ever write into it. + */ +void __pmf_store_timestamp(uintptr_t base_addr, + unsigned int tid, + unsigned long long ts) +{ + unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr, + tid, plat_my_core_pos()); + *ts_addr = ts; +} + +/* + * This is the cached version of `pmf_store_my_timestamp` + * Note: The timestamp addresses are cache line aligned per cpu + * and only the owning CPU would ever write into it. + */ +void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr, + unsigned int tid, + unsigned long long ts) +{ + unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr, + tid, plat_my_core_pos()); + *ts_addr = ts; + flush_dcache_range((uintptr_t)ts_addr, sizeof(unsigned long long)); +} + +/* + * This function retrieves the `ts` value from the storage identified by + * `base_addr`, `tid` and `cpuid`. + * Note: The timestamp addresses are cache line aligned per cpu. + */ +unsigned long long __pmf_get_timestamp(uintptr_t base_addr, + unsigned int tid, + unsigned int cpuid, + unsigned int flags) +{ + assert(cpuid < PLATFORM_CORE_COUNT); + unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr, + tid, cpuid); + + if ((flags & PMF_CACHE_MAINT) != 0U) + inv_dcache_range((uintptr_t)ts_addr, sizeof(unsigned long long)); + + return *ts_addr; +} diff --git a/arm-trusted-firmware/lib/pmf/pmf_smc.c b/arm-trusted-firmware/lib/pmf/pmf_smc.c new file mode 100644 index 0000000..6d79502 --- /dev/null +++ b/arm-trusted-firmware/lib/pmf/pmf_smc.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* + * This function is responsible for handling all PMF SMC calls. + */ +uintptr_t pmf_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, + u_register_t flags) +{ + int rc; + unsigned long long ts_value; + + if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { + + x1 = (uint32_t)x1; + x2 = (uint32_t)x2; + x3 = (uint32_t)x3; + + if (smc_fid == PMF_SMC_GET_TIMESTAMP_32) { + /* + * Return error code and the captured + * time-stamp to the caller. + * x0 --> error code. + * x1 - x2 --> time-stamp value. + */ + rc = pmf_get_timestamp_smc((unsigned int)x1, x2, + (unsigned int)x3, &ts_value); + SMC_RET3(handle, rc, (uint32_t)ts_value, + (uint32_t)(ts_value >> 32)); + } + } else { + if (smc_fid == PMF_SMC_GET_TIMESTAMP_64) { + /* + * Return error code and the captured + * time-stamp to the caller. + * x0 --> error code. + * x1 --> time-stamp value. + */ + rc = pmf_get_timestamp_smc((unsigned int)x1, x2, + (unsigned int)x3, &ts_value); + SMC_RET2(handle, rc, ts_value); + } + } + + WARN("Unimplemented PMF Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S b/arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S new file mode 100644 index 0000000..5cc192e --- /dev/null +++ b/arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl psci_do_pwrdown_cache_maintenance + .globl psci_do_pwrup_cache_maintenance + .globl psci_power_down_wfi + +/* ----------------------------------------------------------------------- + * void psci_do_pwrdown_cache_maintenance(unsigned int power level); + * + * This function performs cache maintenance for the specified power + * level. The levels of cache affected are determined by the power + * level which is passed as the argument i.e. level 0 results + * in a flush of the L1 cache. Both the L1 and L2 caches are flushed + * for a higher power level. + * + * Additionally, this function also ensures that stack memory is correctly + * flushed out to avoid coherency issues due to a change in its memory + * attributes after the data cache is disabled. + * ----------------------------------------------------------------------- + */ +func psci_do_pwrdown_cache_maintenance + push {r4, lr} + + /* ---------------------------------------------- + * Turn OFF cache and do stack maintenance + * prior to cpu operations . This sequence is + * different from AArch64 because in AArch32 the + * assembler routines for cpu operations utilize + * the stack whereas in AArch64 it doesn't. + * ---------------------------------------------- + */ + mov r4, r0 + bl do_stack_maintenance + + /* --------------------------------------------- + * Invoke CPU-specifc power down operations for + * the appropriate level + * --------------------------------------------- + */ + mov r0, r4 + pop {r4, lr} + b prepare_cpu_pwr_dwn +endfunc psci_do_pwrdown_cache_maintenance + + +/* ----------------------------------------------------------------------- + * void psci_do_pwrup_cache_maintenance(void); + * + * This function performs cache maintenance after this cpu is powered up. + * Currently, this involves managing the used stack memory before turning + * on the data cache. + * ----------------------------------------------------------------------- + */ +func psci_do_pwrup_cache_maintenance + /* r12 is pushed to meet the 8 byte stack alignment requirement */ + push {r12, lr} + + /* --------------------------------------------- + * Ensure any inflight stack writes have made it + * to main memory. + * --------------------------------------------- + */ + dmb st + + /* --------------------------------------------- + * Calculate and store the size of the used + * stack memory in r1. Calculate and store the + * stack base address in r0. + * --------------------------------------------- + */ + bl plat_get_my_stack + mov r1, sp + sub r1, r0, r1 + mov r0, sp + bl inv_dcache_range + + /* --------------------------------------------- + * Enable the data cache. + * --------------------------------------------- + */ + ldcopr r0, SCTLR + orr r0, r0, #SCTLR_C_BIT + stcopr r0, SCTLR + isb + + pop {r12, pc} +endfunc psci_do_pwrup_cache_maintenance + + /* --------------------------------------------- + * void do_stack_maintenance(void) + * Do stack maintenance by flushing the used + * stack to the main memory and invalidating the + * remainder. + * --------------------------------------------- + */ +func do_stack_maintenance + push {r4, lr} + bl plat_get_my_stack + + /* Turn off the D-cache */ + ldcopr r1, SCTLR + bic r1, #SCTLR_C_BIT + stcopr r1, SCTLR + isb + + /* --------------------------------------------- + * Calculate and store the size of the used + * stack memory in r1. + * --------------------------------------------- + */ + mov r4, r0 + mov r1, sp + sub r1, r0, r1 + mov r0, sp + bl flush_dcache_range + + /* --------------------------------------------- + * Calculate and store the size of the unused + * stack memory in r1. Calculate and store the + * stack base address in r0. + * --------------------------------------------- + */ + sub r0, r4, #PLATFORM_STACK_SIZE + sub r1, sp, r0 + bl inv_dcache_range + + pop {r4, pc} +endfunc do_stack_maintenance + +/* ----------------------------------------------------------------------- + * This function is called to indicate to the power controller that it + * is safe to power down this cpu. It should not exit the wfi and will + * be released from reset upon power up. + * ----------------------------------------------------------------------- + */ +func psci_power_down_wfi + dsb sy // ensure write buffer empty + wfi + no_ret plat_panic_handler +endfunc psci_power_down_wfi diff --git a/arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S b/arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S new file mode 100644 index 0000000..add968a --- /dev/null +++ b/arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl psci_do_pwrdown_cache_maintenance + .globl psci_do_pwrup_cache_maintenance + .globl psci_power_down_wfi + +/* ----------------------------------------------------------------------- + * void psci_do_pwrdown_cache_maintenance(unsigned int power level); + * + * This function performs cache maintenance for the specified power + * level. The levels of cache affected are determined by the power + * level which is passed as the argument i.e. level 0 results + * in a flush of the L1 cache. Both the L1 and L2 caches are flushed + * for a higher power level. + * + * Additionally, this function also ensures that stack memory is correctly + * flushed out to avoid coherency issues due to a change in its memory + * attributes after the data cache is disabled. + * ----------------------------------------------------------------------- + */ +func psci_do_pwrdown_cache_maintenance + stp x29, x30, [sp,#-16]! + stp x19, x20, [sp,#-16]! + + /* --------------------------------------------- + * Invoke CPU-specific power down operations for + * the appropriate level + * --------------------------------------------- + */ + bl prepare_cpu_pwr_dwn + + /* --------------------------------------------- + * Do stack maintenance by flushing the used + * stack to the main memory and invalidating the + * remainder. + * --------------------------------------------- + */ + bl plat_get_my_stack + + /* --------------------------------------------- + * Calculate and store the size of the used + * stack memory in x1. + * --------------------------------------------- + */ + mov x19, x0 + mov x1, sp + sub x1, x0, x1 + mov x0, sp + bl flush_dcache_range + + /* --------------------------------------------- + * Calculate and store the size of the unused + * stack memory in x1. Calculate and store the + * stack base address in x0. + * --------------------------------------------- + */ + sub x0, x19, #PLATFORM_STACK_SIZE + sub x1, sp, x0 + bl inv_dcache_range + + ldp x19, x20, [sp], #16 + ldp x29, x30, [sp], #16 + ret +endfunc psci_do_pwrdown_cache_maintenance + + +/* ----------------------------------------------------------------------- + * void psci_do_pwrup_cache_maintenance(void); + * + * This function performs cache maintenance after this cpu is powered up. + * Currently, this involves managing the used stack memory before turning + * on the data cache. + * ----------------------------------------------------------------------- + */ +func psci_do_pwrup_cache_maintenance + stp x29, x30, [sp,#-16]! + + /* --------------------------------------------- + * Ensure any inflight stack writes have made it + * to main memory. + * --------------------------------------------- + */ + dmb st + + /* --------------------------------------------- + * Calculate and store the size of the used + * stack memory in x1. Calculate and store the + * stack base address in x0. + * --------------------------------------------- + */ + bl plat_get_my_stack + mov x1, sp + sub x1, x0, x1 + mov x0, sp + bl inv_dcache_range + + /* --------------------------------------------- + * Enable the data cache. + * --------------------------------------------- + */ + mrs x0, sctlr_el3 + orr x0, x0, #SCTLR_C_BIT + msr sctlr_el3, x0 + isb + + ldp x29, x30, [sp], #16 + ret +endfunc psci_do_pwrup_cache_maintenance + +/* ----------------------------------------------------------------------- + * void psci_power_down_wfi(void); + * This function is called to indicate to the power controller that it + * is safe to power down this cpu. It should not exit the wfi and will + * be released from reset upon power up. + * ----------------------------------------------------------------------- + */ +func psci_power_down_wfi + dsb sy // ensure write buffer empty + wfi + no_ret plat_panic_handler +endfunc psci_power_down_wfi diff --git a/arm-trusted-firmware/lib/psci/psci_common.c b/arm-trusted-firmware/lib/psci/psci_common.c new file mode 100644 index 0000000..b4a6897 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_common.c @@ -0,0 +1,1027 @@ +/* + * Copyright (c) 2013-2022, 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 "psci_private.h" + +/* + * SPD power management operations, expected to be supplied by the registered + * SPD on successful SP initialization + */ +const spd_pm_ops_t *psci_spd_pm; + +/* + * PSCI requested local power state map. This array is used to store the local + * power states requested by a CPU for power levels from level 1 to + * PLAT_MAX_PWR_LVL. It does not store the requested local power state for power + * level 0 (PSCI_CPU_PWR_LVL) as the requested and the target power state for a + * CPU are the same. + * + * During state coordination, the platform is passed an array containing the + * local states requested for a particular non cpu power domain by each cpu + * within the domain. + * + * TODO: Dense packing of the requested states will cause cache thrashing + * when multiple power domains write to it. If we allocate the requested + * states at each power level in a cache-line aligned per-domain memory, + * the cache thrashing can be avoided. + */ +static plat_local_state_t + psci_req_local_pwr_states[PLAT_MAX_PWR_LVL][PLATFORM_CORE_COUNT]; + +unsigned int psci_plat_core_count; + +/******************************************************************************* + * Arrays that hold the platform's power domain tree information for state + * management of power domains. + * Each node in the array 'psci_non_cpu_pd_nodes' corresponds to a power domain + * which is an ancestor of a CPU power domain. + * Each node in the array 'psci_cpu_pd_nodes' corresponds to a cpu power domain + ******************************************************************************/ +non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS] +#if USE_COHERENT_MEM +__section("tzfw_coherent_mem") +#endif +; + +/* Lock for PSCI state coordination */ +DEFINE_PSCI_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]); + +cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Pointer to functions exported by the platform to complete power mgmt. ops + ******************************************************************************/ +const plat_psci_ops_t *psci_plat_pm_ops; + +/****************************************************************************** + * Check that the maximum power level supported by the platform makes sense + *****************************************************************************/ +CASSERT((PLAT_MAX_PWR_LVL <= PSCI_MAX_PWR_LVL) && + (PLAT_MAX_PWR_LVL >= PSCI_CPU_PWR_LVL), + assert_platform_max_pwrlvl_check); + +/* + * The plat_local_state used by the platform is one of these types: RUN, + * RETENTION and OFF. The platform can define further sub-states for each type + * apart from RUN. This categorization is done to verify the sanity of the + * psci_power_state passed by the platform and to print debug information. The + * categorization is done on the basis of the following conditions: + * + * 1. If (plat_local_state == 0) then the category is STATE_TYPE_RUN. + * + * 2. If (0 < plat_local_state <= PLAT_MAX_RET_STATE), then the category is + * STATE_TYPE_RETN. + * + * 3. If (plat_local_state > PLAT_MAX_RET_STATE), then the category is + * STATE_TYPE_OFF. + */ +typedef enum plat_local_state_type { + STATE_TYPE_RUN = 0, + STATE_TYPE_RETN, + STATE_TYPE_OFF +} plat_local_state_type_t; + +/* Function used to categorize plat_local_state. */ +static plat_local_state_type_t find_local_state_type(plat_local_state_t state) +{ + if (state != 0U) { + if (state > PLAT_MAX_RET_STATE) { + return STATE_TYPE_OFF; + } else { + return STATE_TYPE_RETN; + } + } else { + return STATE_TYPE_RUN; + } +} + +/****************************************************************************** + * Check that the maximum retention level supported by the platform is less + * than the maximum off level. + *****************************************************************************/ +CASSERT(PLAT_MAX_RET_STATE < PLAT_MAX_OFF_STATE, + assert_platform_max_off_and_retn_state_check); + +/****************************************************************************** + * This function ensures that the power state parameter in a CPU_SUSPEND request + * is valid. If so, it returns the requested states for each power level. + *****************************************************************************/ +int psci_validate_power_state(unsigned int power_state, + psci_power_state_t *state_info) +{ + /* Check SBZ bits in power state are zero */ + if (psci_check_power_state(power_state) != 0U) + return PSCI_E_INVALID_PARAMS; + + assert(psci_plat_pm_ops->validate_power_state != NULL); + + /* Validate the power_state using platform pm_ops */ + return psci_plat_pm_ops->validate_power_state(power_state, state_info); +} + +/****************************************************************************** + * This function retrieves the `psci_power_state_t` for system suspend from + * the platform. + *****************************************************************************/ +void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info) +{ + /* + * Assert that the required pm_ops hook is implemented to ensure that + * the capability detected during psci_setup() is valid. + */ + assert(psci_plat_pm_ops->get_sys_suspend_power_state != NULL); + + /* + * Query the platform for the power_state required for system suspend + */ + psci_plat_pm_ops->get_sys_suspend_power_state(state_info); +} + +/******************************************************************************* + * This function verifies that the all the other cores in the system have been + * turned OFF and the current CPU is the last running CPU in the system. + * Returns 1 (true) if the current CPU is the last ON CPU or 0 (false) + * otherwise. + ******************************************************************************/ +unsigned int psci_is_last_on_cpu(void) +{ + unsigned int cpu_idx, my_idx = plat_my_core_pos(); + + for (cpu_idx = 0; cpu_idx < psci_plat_core_count; + cpu_idx++) { + if (cpu_idx == my_idx) { + assert(psci_get_aff_info_state() == AFF_STATE_ON); + continue; + } + + if (psci_get_aff_info_state_by_idx(cpu_idx) != AFF_STATE_OFF) + return 0; + } + + return 1; +} + +/******************************************************************************* + * Routine to return the maximum power level to traverse to after a cpu has + * been physically powered up. It is expected to be called immediately after + * reset from assembler code. + ******************************************************************************/ +static unsigned int get_power_on_target_pwrlvl(void) +{ + unsigned int pwrlvl; + + /* + * Assume that this cpu was suspended and retrieve its target power + * level. If it is invalid then it could only have been turned off + * earlier. PLAT_MAX_PWR_LVL will be the highest power level a + * cpu can be turned off to. + */ + pwrlvl = psci_get_suspend_pwrlvl(); + if (pwrlvl == PSCI_INVALID_PWR_LVL) + pwrlvl = PLAT_MAX_PWR_LVL; + assert(pwrlvl < PSCI_INVALID_PWR_LVL); + return pwrlvl; +} + +/****************************************************************************** + * Helper function to update the requested local power state array. This array + * does not store the requested state for the CPU power level. Hence an + * assertion is added to prevent us from accessing the CPU power level. + *****************************************************************************/ +static void psci_set_req_local_pwr_state(unsigned int pwrlvl, + unsigned int cpu_idx, + plat_local_state_t req_pwr_state) +{ + assert(pwrlvl > PSCI_CPU_PWR_LVL); + if ((pwrlvl > PSCI_CPU_PWR_LVL) && (pwrlvl <= PLAT_MAX_PWR_LVL) && + (cpu_idx < psci_plat_core_count)) { + psci_req_local_pwr_states[pwrlvl - 1U][cpu_idx] = req_pwr_state; + } +} + +/****************************************************************************** + * This function initializes the psci_req_local_pwr_states. + *****************************************************************************/ +void __init psci_init_req_local_pwr_states(void) +{ + /* Initialize the requested state of all non CPU power domains as OFF */ + unsigned int pwrlvl; + unsigned int core; + + for (pwrlvl = 0U; pwrlvl < PLAT_MAX_PWR_LVL; pwrlvl++) { + for (core = 0; core < psci_plat_core_count; core++) { + psci_req_local_pwr_states[pwrlvl][core] = + PLAT_MAX_OFF_STATE; + } + } +} + +/****************************************************************************** + * Helper function to return a reference to an array containing the local power + * states requested by each cpu for a power domain at 'pwrlvl'. The size of the + * array will be the number of cpu power domains of which this power domain is + * an ancestor. These requested states will be used to determine a suitable + * target state for this power domain during psci state coordination. An + * assertion is added to prevent us from accessing the CPU power level. + *****************************************************************************/ +static plat_local_state_t *psci_get_req_local_pwr_states(unsigned int pwrlvl, + unsigned int cpu_idx) +{ + assert(pwrlvl > PSCI_CPU_PWR_LVL); + + if ((pwrlvl > PSCI_CPU_PWR_LVL) && (pwrlvl <= PLAT_MAX_PWR_LVL) && + (cpu_idx < psci_plat_core_count)) { + return &psci_req_local_pwr_states[pwrlvl - 1U][cpu_idx]; + } else + return NULL; +} + +/* + * psci_non_cpu_pd_nodes can be placed either in normal memory or coherent + * memory. + * + * With !USE_COHERENT_MEM, psci_non_cpu_pd_nodes is placed in normal memory, + * it's accessed by both cached and non-cached participants. To serve the common + * minimum, perform a cache flush before read and after write so that non-cached + * participants operate on latest data in main memory. + * + * When USE_COHERENT_MEM is used, psci_non_cpu_pd_nodes is placed in coherent + * memory. With HW_ASSISTED_COHERENCY, all PSCI participants are cache-coherent. + * In both cases, no cache operations are required. + */ + +/* + * Retrieve local state of non-CPU power domain node from a non-cached CPU, + * after any required cache maintenance operation. + */ +static plat_local_state_t get_non_cpu_pd_node_local_state( + unsigned int parent_idx) +{ +#if !(USE_COHERENT_MEM || HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + flush_dcache_range( + (uintptr_t) &psci_non_cpu_pd_nodes[parent_idx], + sizeof(psci_non_cpu_pd_nodes[parent_idx])); +#endif + return psci_non_cpu_pd_nodes[parent_idx].local_state; +} + +/* + * Update local state of non-CPU power domain node from a cached CPU; perform + * any required cache maintenance operation afterwards. + */ +static void set_non_cpu_pd_node_local_state(unsigned int parent_idx, + plat_local_state_t state) +{ + psci_non_cpu_pd_nodes[parent_idx].local_state = state; +#if !(USE_COHERENT_MEM || HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + flush_dcache_range( + (uintptr_t) &psci_non_cpu_pd_nodes[parent_idx], + sizeof(psci_non_cpu_pd_nodes[parent_idx])); +#endif +} + +/****************************************************************************** + * Helper function to return the current local power state of each power domain + * from the current cpu power domain to its ancestor at the 'end_pwrlvl'. This + * function will be called after a cpu is powered on to find the local state + * each power domain has emerged from. + *****************************************************************************/ +void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, + psci_power_state_t *target_state) +{ + unsigned int parent_idx, lvl; + plat_local_state_t *pd_state = target_state->pwr_domain_state; + + pd_state[PSCI_CPU_PWR_LVL] = psci_get_cpu_local_state(); + parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node; + + /* Copy the local power state from node to state_info */ + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + pd_state[lvl] = get_non_cpu_pd_node_local_state(parent_idx); + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + + /* Set the the higher levels to RUN */ + for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) + target_state->pwr_domain_state[lvl] = PSCI_LOCAL_STATE_RUN; +} + +/****************************************************************************** + * Helper function to set the target local power state that each power domain + * from the current cpu power domain to its ancestor at the 'end_pwrlvl' will + * enter. This function will be called after coordination of requested power + * states has been done for each power level. + *****************************************************************************/ +static void psci_set_target_local_pwr_states(unsigned int end_pwrlvl, + const psci_power_state_t *target_state) +{ + unsigned int parent_idx, lvl; + const plat_local_state_t *pd_state = target_state->pwr_domain_state; + + psci_set_cpu_local_state(pd_state[PSCI_CPU_PWR_LVL]); + + /* + * Need to flush as local_state might be accessed with Data Cache + * disabled during power on + */ + psci_flush_cpu_data(psci_svc_cpu_data.local_state); + + parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node; + + /* Copy the local_state from state_info */ + for (lvl = 1U; lvl <= end_pwrlvl; lvl++) { + set_non_cpu_pd_node_local_state(parent_idx, pd_state[lvl]); + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } +} + + +/******************************************************************************* + * PSCI helper function to get the parent nodes corresponding to a cpu_index. + ******************************************************************************/ +void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx, + unsigned int end_lvl, + unsigned int *node_index) +{ + unsigned int parent_node = psci_cpu_pd_nodes[cpu_idx].parent_node; + unsigned int i; + unsigned int *node = node_index; + + for (i = PSCI_CPU_PWR_LVL + 1U; i <= end_lvl; i++) { + *node = parent_node; + node++; + parent_node = psci_non_cpu_pd_nodes[parent_node].parent_node; + } +} + +/****************************************************************************** + * This function is invoked post CPU power up and initialization. It sets the + * affinity info state, target power state and requested power state for the + * current CPU and all its ancestor power domains to RUN. + *****************************************************************************/ +void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl) +{ + unsigned int parent_idx, cpu_idx = plat_my_core_pos(), lvl; + parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node; + + /* Reset the local_state to RUN for the non cpu power domains. */ + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + set_non_cpu_pd_node_local_state(parent_idx, + PSCI_LOCAL_STATE_RUN); + psci_set_req_local_pwr_state(lvl, + cpu_idx, + PSCI_LOCAL_STATE_RUN); + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + + /* Set the affinity info state to ON */ + psci_set_aff_info_state(AFF_STATE_ON); + + psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN); + psci_flush_cpu_data(psci_svc_cpu_data); +} + +/****************************************************************************** + * This function is passed the local power states requested for each power + * domain (state_info) between the current CPU domain and its ancestors until + * the target power level (end_pwrlvl). It updates the array of requested power + * states with this information. + * + * Then, for each level (apart from the CPU level) until the 'end_pwrlvl', it + * retrieves the states requested by all the cpus of which the power domain at + * that level is an ancestor. It passes this information to the platform to + * coordinate and return the target power state. If the target state for a level + * is RUN then subsequent levels are not considered. At the CPU level, state + * coordination is not required. Hence, the requested and the target states are + * the same. + * + * The 'state_info' is updated with the target state for each level between the + * CPU and the 'end_pwrlvl' and returned to the caller. + * + * This function will only be invoked with data cache enabled and while + * powering down a core. + *****************************************************************************/ +void psci_do_state_coordination(unsigned int end_pwrlvl, + psci_power_state_t *state_info) +{ + unsigned int lvl, parent_idx, cpu_idx = plat_my_core_pos(); + unsigned int start_idx; + unsigned int ncpus; + plat_local_state_t target_state, *req_states; + + assert(end_pwrlvl <= PLAT_MAX_PWR_LVL); + parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node; + + /* For level 0, the requested state will be equivalent + to target state */ + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + + /* First update the requested power state */ + psci_set_req_local_pwr_state(lvl, cpu_idx, + state_info->pwr_domain_state[lvl]); + + /* Get the requested power states for this power level */ + start_idx = psci_non_cpu_pd_nodes[parent_idx].cpu_start_idx; + req_states = psci_get_req_local_pwr_states(lvl, start_idx); + + /* + * Let the platform coordinate amongst the requested states at + * this power level and return the target local power state. + */ + ncpus = psci_non_cpu_pd_nodes[parent_idx].ncpus; + target_state = plat_get_target_pwr_state(lvl, + req_states, + ncpus); + + state_info->pwr_domain_state[lvl] = target_state; + + /* Break early if the negotiated target power state is RUN */ + if (is_local_state_run(state_info->pwr_domain_state[lvl]) != 0) + break; + + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + + /* + * This is for cases when we break out of the above loop early because + * the target power state is RUN at a power level < end_pwlvl. + * We update the requested power state from state_info and then + * set the target state as RUN. + */ + for (lvl = lvl + 1U; lvl <= end_pwrlvl; lvl++) { + psci_set_req_local_pwr_state(lvl, cpu_idx, + state_info->pwr_domain_state[lvl]); + state_info->pwr_domain_state[lvl] = PSCI_LOCAL_STATE_RUN; + + } + + /* Update the target state in the power domain nodes */ + psci_set_target_local_pwr_states(end_pwrlvl, state_info); +} + +/****************************************************************************** + * This function validates a suspend request by making sure that if a standby + * state is requested then no power level is turned off and the highest power + * level is placed in a standby/retention state. + * + * It also ensures that the state level X will enter is not shallower than the + * state level X + 1 will enter. + * + * This validation will be enabled only for DEBUG builds as the platform is + * expected to perform these validations as well. + *****************************************************************************/ +int psci_validate_suspend_req(const psci_power_state_t *state_info, + unsigned int is_power_down_state) +{ + unsigned int max_off_lvl, target_lvl, max_retn_lvl; + plat_local_state_t state; + plat_local_state_type_t req_state_type, deepest_state_type; + int i; + + /* Find the target suspend power level */ + target_lvl = psci_find_target_suspend_lvl(state_info); + if (target_lvl == PSCI_INVALID_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* All power domain levels are in a RUN state to begin with */ + deepest_state_type = STATE_TYPE_RUN; + + for (i = (int) target_lvl; i >= (int) PSCI_CPU_PWR_LVL; i--) { + state = state_info->pwr_domain_state[i]; + req_state_type = find_local_state_type(state); + + /* + * While traversing from the highest power level to the lowest, + * the state requested for lower levels has to be the same or + * deeper i.e. equal to or greater than the state at the higher + * levels. If this condition is true, then the requested state + * becomes the deepest state encountered so far. + */ + if (req_state_type < deepest_state_type) + return PSCI_E_INVALID_PARAMS; + deepest_state_type = req_state_type; + } + + /* Find the highest off power level */ + max_off_lvl = psci_find_max_off_lvl(state_info); + + /* The target_lvl is either equal to the max_off_lvl or max_retn_lvl */ + max_retn_lvl = PSCI_INVALID_PWR_LVL; + if (target_lvl != max_off_lvl) + max_retn_lvl = target_lvl; + + /* + * If this is not a request for a power down state then max off level + * has to be invalid and max retention level has to be a valid power + * level. + */ + if ((is_power_down_state == 0U) && + ((max_off_lvl != PSCI_INVALID_PWR_LVL) || + (max_retn_lvl == PSCI_INVALID_PWR_LVL))) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +/****************************************************************************** + * This function finds the highest power level which will be powered down + * amongst all the power levels specified in the 'state_info' structure + *****************************************************************************/ +unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info) +{ + int i; + + for (i = (int) PLAT_MAX_PWR_LVL; i >= (int) PSCI_CPU_PWR_LVL; i--) { + if (is_local_state_off(state_info->pwr_domain_state[i]) != 0) + return (unsigned int) i; + } + + return PSCI_INVALID_PWR_LVL; +} + +/****************************************************************************** + * This functions finds the level of the highest power domain which will be + * placed in a low power state during a suspend operation. + *****************************************************************************/ +unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info) +{ + int i; + + for (i = (int) PLAT_MAX_PWR_LVL; i >= (int) PSCI_CPU_PWR_LVL; i--) { + if (is_local_state_run(state_info->pwr_domain_state[i]) == 0) + return (unsigned int) i; + } + + return PSCI_INVALID_PWR_LVL; +} + +/******************************************************************************* + * This function is passed the highest level in the topology tree that the + * operation should be applied to and a list of node indexes. It picks up locks + * from the node index list in order of increasing power domain level in the + * range specified. + ******************************************************************************/ +void psci_acquire_pwr_domain_locks(unsigned int end_pwrlvl, + const unsigned int *parent_nodes) +{ + unsigned int parent_idx; + unsigned int level; + + /* No locking required for level 0. Hence start locking from level 1 */ + for (level = PSCI_CPU_PWR_LVL + 1U; level <= end_pwrlvl; level++) { + parent_idx = parent_nodes[level - 1U]; + psci_lock_get(&psci_non_cpu_pd_nodes[parent_idx]); + } +} + +/******************************************************************************* + * This function is passed the highest level in the topology tree that the + * operation should be applied to and a list of node indexes. It releases the + * locks in order of decreasing power domain level in the range specified. + ******************************************************************************/ +void psci_release_pwr_domain_locks(unsigned int end_pwrlvl, + const unsigned int *parent_nodes) +{ + unsigned int parent_idx; + unsigned int level; + + /* Unlock top down. No unlocking required for level 0. */ + for (level = end_pwrlvl; level >= (PSCI_CPU_PWR_LVL + 1U); level--) { + parent_idx = parent_nodes[level - 1U]; + psci_lock_release(&psci_non_cpu_pd_nodes[parent_idx]); + } + + flush_dcache_range((uint64_t)psci_non_cpu_pd_nodes, + sizeof(non_cpu_pd_node_t) * PLATFORM_CORE_COUNT); +} + +/******************************************************************************* + * Simple routine to determine whether a mpidr is valid or not. + ******************************************************************************/ +int psci_validate_mpidr(u_register_t mpidr) +{ + if (plat_core_pos_by_mpidr(mpidr) < 0) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * This function determines the full entrypoint information for the requested + * PSCI entrypoint on power on/resume and returns it. + ******************************************************************************/ +#ifdef __aarch64__ +static int psci_get_ns_ep_info(entry_point_info_t *ep, + uintptr_t entrypoint, + u_register_t context_id) +{ + u_register_t ep_attr, sctlr; + unsigned int daif, ee, mode; + u_register_t ns_scr_el3 = read_scr_el3(); + u_register_t ns_sctlr_el1 = read_sctlr_el1(); + + sctlr = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? + read_sctlr_el2() : ns_sctlr_el1; + ee = 0; + + ep_attr = NON_SECURE | EP_ST_DISABLE; + if ((sctlr & SCTLR_EE_BIT) != 0U) { + ep_attr |= EP_EE_BIG; + ee = 1; + } + SET_PARAM_HEAD(ep, PARAM_EP, VERSION_1, ep_attr); + + ep->pc = entrypoint; + zeromem(&ep->args, sizeof(ep->args)); + ep->args.arg0 = context_id; + + /* + * Figure out whether the cpu enters the non-secure address space + * in aarch32 or aarch64 + */ + if ((ns_scr_el3 & SCR_RW_BIT) != 0U) { + + /* + * Check whether a Thumb entry point has been provided for an + * aarch64 EL + */ + if ((entrypoint & 0x1UL) != 0UL) + return PSCI_E_INVALID_ADDRESS; + + mode = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? MODE_EL2 : MODE_EL1; + + ep->spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } else { + + mode = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? + MODE32_hyp : MODE32_svc; + + /* + * TODO: Choose async. exception bits if HYP mode is not + * implemented according to the values of SCR.{AW, FW} bits + */ + daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT; + + ep->spsr = SPSR_MODE32((uint64_t)mode, entrypoint & 0x1, ee, + daif); + } + + return PSCI_E_SUCCESS; +} +#else /* !__aarch64__ */ +static int psci_get_ns_ep_info(entry_point_info_t *ep, + uintptr_t entrypoint, + u_register_t context_id) +{ + u_register_t ep_attr; + unsigned int aif, ee, mode; + u_register_t scr = read_scr(); + u_register_t ns_sctlr, sctlr; + + /* Switch to non secure state */ + write_scr(scr | SCR_NS_BIT); + isb(); + ns_sctlr = read_sctlr(); + + sctlr = scr & SCR_HCE_BIT ? read_hsctlr() : ns_sctlr; + + /* Return to original state */ + write_scr(scr); + isb(); + ee = 0; + + ep_attr = NON_SECURE | EP_ST_DISABLE; + if (sctlr & SCTLR_EE_BIT) { + ep_attr |= EP_EE_BIG; + ee = 1; + } + SET_PARAM_HEAD(ep, PARAM_EP, VERSION_1, ep_attr); + + ep->pc = entrypoint; + zeromem(&ep->args, sizeof(ep->args)); + ep->args.arg0 = context_id; + + mode = scr & SCR_HCE_BIT ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Choose async. exception bits if HYP mode is not + * implemented according to the values of SCR.{AW, FW} bits + */ + aif = SPSR_ABT_BIT | SPSR_IRQ_BIT | SPSR_FIQ_BIT; + + ep->spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, aif); + + return PSCI_E_SUCCESS; +} + +#endif /* __aarch64__ */ + +/******************************************************************************* + * This function validates the entrypoint with the platform layer if the + * appropriate pm_ops hook is exported by the platform and returns the + * 'entry_point_info'. + ******************************************************************************/ +int psci_validate_entry_point(entry_point_info_t *ep, + uintptr_t entrypoint, + u_register_t context_id) +{ + int rc; + + /* Validate the entrypoint using platform psci_ops */ + if (psci_plat_pm_ops->validate_ns_entrypoint != NULL) { + rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_ADDRESS; + } + + /* + * Verify and derive the re-entry information for + * the non-secure world from the non-secure state from + * where this call originated. + */ + rc = psci_get_ns_ep_info(ep, entrypoint, context_id); + return rc; +} + +/******************************************************************************* + * Generic handler which is called when a cpu is physically powered on. It + * traverses the node information and finds the highest power level powered + * off and performs generic, architectural, platform setup and state management + * to power on that power level and power levels below it. + * e.g. For a cpu that's been powered on, it will call the platform specific + * code to enable the gic cpu interface and for a cluster it will enable + * coherency at the interconnect level in addition to gic cpu interface. + ******************************************************************************/ +void psci_warmboot_entrypoint(void) +{ + unsigned int end_pwrlvl; + unsigned int cpu_idx = plat_my_core_pos(); + unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; + psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} }; + + /* + * Verify that we have been explicitly turned ON or resumed from + * suspend. + */ + if (psci_get_aff_info_state() == AFF_STATE_OFF) { + ERROR("Unexpected affinity info state.\n"); + panic(); + } + + /* + * Get the maximum power domain level to traverse to after this cpu + * has been physically powered up. + */ + end_pwrlvl = get_power_on_target_pwrlvl(); + + /* Get the parent nodes */ + psci_get_parent_pwr_domain_nodes(cpu_idx, end_pwrlvl, parent_nodes); + + /* + * This function acquires the lock corresponding to each power level so + * that by the time all locks are taken, the system topology is snapshot + * and state management can be done safely. + */ + psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); + + psci_get_target_local_pwr_states(end_pwrlvl, &state_info); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_stop(&state_info); +#endif + + /* + * This CPU could be resuming from suspend or it could have just been + * turned on. To distinguish between these 2 cases, we examine the + * affinity state of the CPU: + * - If the affinity state is ON_PENDING then it has just been + * turned on. + * - Else it is resuming from suspend. + * + * Depending on the type of warm reset identified, choose the right set + * of power management handler and perform the generic, architecture + * and platform specific handling. + */ + if (psci_get_aff_info_state() == AFF_STATE_ON_PENDING) + psci_cpu_on_finish(cpu_idx, &state_info); + else + psci_cpu_suspend_finish(cpu_idx, &state_info); + + /* + * Set the requested and target state of this CPU and all the higher + * power domains which are ancestors of this CPU to run. + */ + psci_set_pwr_domains_to_run(end_pwrlvl); + +#if ENABLE_PSCI_STAT + /* + * Update PSCI stats. + * Caches are off when writing stats data on the power down path. + * Since caches are now enabled, it's necessary to do cache + * maintenance before reading that same data. + */ + psci_stats_update_pwr_up(end_pwrlvl, &state_info); +#endif + + /* + * This loop releases the lock corresponding to each power level + * in the reverse order to which they were acquired. + */ + psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); +} + +/******************************************************************************* + * This function initializes the set of hooks that PSCI invokes as part of power + * management operation. The power management hooks are expected to be provided + * by the SPD, after it finishes all its initialization + ******************************************************************************/ +void psci_register_spd_pm_hook(const spd_pm_ops_t *pm) +{ + assert(pm != NULL); + psci_spd_pm = pm; + + if (pm->svc_migrate != NULL) + psci_caps |= define_psci_cap(PSCI_MIG_AARCH64); + + if (pm->svc_migrate_info != NULL) + psci_caps |= define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) + | define_psci_cap(PSCI_MIG_INFO_TYPE); +} + +/******************************************************************************* + * This function invokes the migrate info hook in the spd_pm_ops. It performs + * the necessary return value validation. If the Secure Payload is UP and + * migrate capable, it returns the mpidr of the CPU on which the Secure payload + * is resident through the mpidr parameter. Else the value of the parameter on + * return is undefined. + ******************************************************************************/ +int psci_spd_migrate_info(u_register_t *mpidr) +{ + int rc; + + if ((psci_spd_pm == NULL) || (psci_spd_pm->svc_migrate_info == NULL)) + return PSCI_E_NOT_SUPPORTED; + + rc = psci_spd_pm->svc_migrate_info(mpidr); + + assert((rc == PSCI_TOS_UP_MIG_CAP) || (rc == PSCI_TOS_NOT_UP_MIG_CAP) || + (rc == PSCI_TOS_NOT_PRESENT_MP) || (rc == PSCI_E_NOT_SUPPORTED)); + + return rc; +} + + +/******************************************************************************* + * This function prints the state of all power domains present in the + * system + ******************************************************************************/ +void psci_print_power_domain_map(void) +{ +#if LOG_LEVEL >= LOG_LEVEL_INFO + unsigned int idx; + plat_local_state_t state; + plat_local_state_type_t state_type; + + /* This array maps to the PSCI_STATE_X definitions in psci.h */ + static const char * const psci_state_type_str[] = { + "ON", + "RETENTION", + "OFF", + }; + + INFO("PSCI Power Domain Map:\n"); + for (idx = 0; idx < (PSCI_NUM_PWR_DOMAINS - psci_plat_core_count); + idx++) { + state_type = find_local_state_type( + psci_non_cpu_pd_nodes[idx].local_state); + INFO(" Domain Node : Level %u, parent_node %u," + " State %s (0x%x)\n", + psci_non_cpu_pd_nodes[idx].level, + psci_non_cpu_pd_nodes[idx].parent_node, + psci_state_type_str[state_type], + psci_non_cpu_pd_nodes[idx].local_state); + } + + for (idx = 0; idx < psci_plat_core_count; idx++) { + state = psci_get_cpu_local_state_by_idx(idx); + state_type = find_local_state_type(state); + INFO(" CPU Node : MPID 0x%llx, parent_node %u," + " State %s (0x%x)\n", + (unsigned long long)psci_cpu_pd_nodes[idx].mpidr, + psci_cpu_pd_nodes[idx].parent_node, + psci_state_type_str[state_type], + psci_get_cpu_local_state_by_idx(idx)); + } +#endif +} + +/****************************************************************************** + * Return whether any secondaries were powered up with CPU_ON call. A CPU that + * have ever been powered up would have set its MPDIR value to something other + * than PSCI_INVALID_MPIDR. Note that MPDIR isn't reset back to + * PSCI_INVALID_MPIDR when a CPU is powered down later, so the return value is + * meaningful only when called on the primary CPU during early boot. + *****************************************************************************/ +int psci_secondaries_brought_up(void) +{ + unsigned int idx, n_valid = 0U; + + for (idx = 0U; idx < ARRAY_SIZE(psci_cpu_pd_nodes); idx++) { + if (psci_cpu_pd_nodes[idx].mpidr != PSCI_INVALID_MPIDR) + n_valid++; + } + + assert(n_valid > 0U); + + return (n_valid > 1U) ? 1 : 0; +} + +/******************************************************************************* + * Initiate power down sequence, by calling power down operations registered for + * this CPU. + ******************************************************************************/ +void psci_do_pwrdown_sequence(unsigned int power_level) +{ +#if HW_ASSISTED_COHERENCY + /* + * With hardware-assisted coherency, the CPU drivers only initiate the + * power down sequence, without performing cache-maintenance operations + * in software. Data caches enabled both before and after this call. + */ + prepare_cpu_pwr_dwn(power_level); +#else + /* + * Without hardware-assisted coherency, the CPU drivers disable data + * caches, then perform cache-maintenance operations in software. + * + * This also calls prepare_cpu_pwr_dwn() to initiate power down + * sequence, but that function will return with data caches disabled. + * We must ensure that the stack memory is flushed out to memory before + * we start popping from it again. + */ + psci_do_pwrdown_cache_maintenance(power_level); +#endif +} + +/******************************************************************************* + * This function invokes the callback 'stop_func()' with the 'mpidr' of each + * online PE. Caller can pass suitable method to stop a remote core. + * + * 'wait_ms' is the timeout value in milliseconds for the other cores to + * transition to power down state. Passing '0' makes it non-blocking. + * + * The function returns 'PSCI_E_DENIED' if some cores failed to stop within the + * given timeout. + ******************************************************************************/ +int psci_stop_other_cores(unsigned int wait_ms, + void (*stop_func)(u_register_t mpidr)) +{ + unsigned int idx, this_cpu_idx; + + this_cpu_idx = plat_my_core_pos(); + + /* Invoke stop_func for each core */ + for (idx = 0U; idx < psci_plat_core_count; idx++) { + /* skip current CPU */ + if (idx == this_cpu_idx) { + continue; + } + + /* Check if the CPU is ON */ + if (psci_get_aff_info_state_by_idx(idx) == AFF_STATE_ON) { + (*stop_func)(psci_cpu_pd_nodes[idx].mpidr); + } + } + + /* Need to wait for other cores to shutdown */ + if (wait_ms != 0U) { + while ((wait_ms-- != 0U) && (psci_is_last_on_cpu() != 0U)) { + mdelay(1U); + } + + if (psci_is_last_on_cpu() != 0U) { + WARN("Failed to stop all cores!\n"); + psci_print_power_domain_map(); + return PSCI_E_DENIED; + } + } + + return PSCI_E_SUCCESS; +} diff --git a/arm-trusted-firmware/lib/psci/psci_lib.mk b/arm-trusted-firmware/lib/psci/psci_lib.mk new file mode 100644 index 0000000..1d4aac4 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_lib.mk @@ -0,0 +1,35 @@ +# +# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PSCI_LIB_SOURCES := lib/el3_runtime/cpu_data_array.c \ + lib/el3_runtime/${ARCH}/cpu_data.S \ + lib/el3_runtime/${ARCH}/context_mgmt.c \ + lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c \ + lib/locks/exclusive/${ARCH}/spinlock.S \ + lib/psci/psci_off.c \ + lib/psci/psci_on.c \ + lib/psci/psci_suspend.c \ + lib/psci/psci_common.c \ + lib/psci/psci_main.c \ + lib/psci/psci_setup.c \ + lib/psci/psci_system_off.c \ + lib/psci/psci_mem_protect.c \ + lib/psci/${ARCH}/psci_helpers.S + +ifeq (${ARCH}, aarch64) +PSCI_LIB_SOURCES += lib/el3_runtime/aarch64/context.S +endif + +ifeq (${USE_COHERENT_MEM}, 1) +PSCI_LIB_SOURCES += lib/locks/bakery/bakery_lock_coherent.c +else +PSCI_LIB_SOURCES += lib/locks/bakery/bakery_lock_normal.c +endif + +ifeq (${ENABLE_PSCI_STAT}, 1) +PSCI_LIB_SOURCES += lib/psci/psci_stat.c +endif diff --git a/arm-trusted-firmware/lib/psci/psci_main.c b/arm-trusted-firmware/lib/psci/psci_main.c new file mode 100644 index 0000000..52a8b8a --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_main.c @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "psci_private.h" + +/******************************************************************************* + * PSCI frontend api for servicing SMCs. Described in the PSCI spec. + ******************************************************************************/ +int psci_cpu_on(u_register_t target_cpu, + uintptr_t entrypoint, + u_register_t context_id) + +{ + int rc; + entry_point_info_t ep; + + /* Determine if the cpu exists of not */ + rc = psci_validate_mpidr(target_cpu); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + /* Validate the entry point and get the entry_point_info */ + rc = psci_validate_entry_point(&ep, entrypoint, context_id); + if (rc != PSCI_E_SUCCESS) + return rc; + + /* + * To turn this cpu on, specify which power + * levels need to be turned on + */ + return psci_cpu_on_start(target_cpu, &ep); +} + +unsigned int psci_version(void) +{ + return PSCI_MAJOR_VER | PSCI_MINOR_VER; +} + +int psci_cpu_suspend(unsigned int power_state, + uintptr_t entrypoint, + u_register_t context_id) +{ + int rc; + unsigned int target_pwrlvl, is_power_down_state; + entry_point_info_t ep; + psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} }; + plat_local_state_t cpu_pd_state; + + /* Validate the power_state parameter */ + rc = psci_validate_power_state(power_state, &state_info); + if (rc != PSCI_E_SUCCESS) { + assert(rc == PSCI_E_INVALID_PARAMS); + return rc; + } + + /* + * Get the value of the state type bit from the power state parameter. + */ + is_power_down_state = psci_get_pstate_type(power_state); + + /* Sanity check the requested suspend levels */ + assert(psci_validate_suspend_req(&state_info, is_power_down_state) + == PSCI_E_SUCCESS); + + target_pwrlvl = psci_find_target_suspend_lvl(&state_info); + if (target_pwrlvl == PSCI_INVALID_PWR_LVL) { + ERROR("Invalid target power level for suspend operation\n"); + panic(); + } + + /* Fast path for CPU standby.*/ + if (is_cpu_standby_req(is_power_down_state, target_pwrlvl)) { + if (psci_plat_pm_ops->cpu_standby == NULL) + return PSCI_E_INVALID_PARAMS; + + /* + * Set the state of the CPU power domain to the platform + * specific retention state and enter the standby state. + */ + cpu_pd_state = state_info.pwr_domain_state[PSCI_CPU_PWR_LVL]; + psci_set_cpu_local_state(cpu_pd_state); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_start(&state_info); +#endif + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + psci_plat_pm_ops->cpu_standby(cpu_pd_state); + + /* Upon exit from standby, set the state back to RUN. */ + psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_stop(&state_info); + + /* Update PSCI stats */ + psci_stats_update_pwr_up(PSCI_CPU_PWR_LVL, &state_info); +#endif + + return PSCI_E_SUCCESS; + } + + /* + * If a power down state has been requested, we need to verify entry + * point and program entry information. + */ + if (is_power_down_state != 0U) { + rc = psci_validate_entry_point(&ep, entrypoint, context_id); + if (rc != PSCI_E_SUCCESS) + return rc; + } + + /* + * Do what is needed to enter the power down state. Upon success, + * enter the final wfi which will power down this CPU. This function + * might return if the power down was abandoned for any reason, e.g. + * arrival of an interrupt + */ + psci_cpu_suspend_start(&ep, + target_pwrlvl, + &state_info, + is_power_down_state); + + return PSCI_E_SUCCESS; +} + + +int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id) +{ + int rc; + psci_power_state_t state_info; + entry_point_info_t ep; + + /* Check if the current CPU is the last ON CPU in the system */ + if (psci_is_last_on_cpu() == 0U) + return PSCI_E_DENIED; + + /* Validate the entry point and get the entry_point_info */ + rc = psci_validate_entry_point(&ep, entrypoint, context_id); + if (rc != PSCI_E_SUCCESS) + return rc; + + /* Query the psci_power_state for system suspend */ + psci_query_sys_suspend_pwrstate(&state_info); + + /* + * Check if platform allows suspend to Highest power level + * (System level) + */ + if (psci_find_target_suspend_lvl(&state_info) < PLAT_MAX_PWR_LVL) + return PSCI_E_DENIED; + + /* Ensure that the psci_power_state makes sense */ + assert(psci_validate_suspend_req(&state_info, PSTATE_TYPE_POWERDOWN) + == PSCI_E_SUCCESS); + assert(is_local_state_off( + state_info.pwr_domain_state[PLAT_MAX_PWR_LVL]) != 0); + + /* + * Do what is needed to enter the system suspend state. This function + * might return if the power down was abandoned for any reason, e.g. + * arrival of an interrupt + */ + psci_cpu_suspend_start(&ep, + PLAT_MAX_PWR_LVL, + &state_info, + PSTATE_TYPE_POWERDOWN); + + return PSCI_E_SUCCESS; +} + +int psci_cpu_off(void) +{ + int rc; + unsigned int target_pwrlvl = PLAT_MAX_PWR_LVL; + + /* + * Do what is needed to power off this CPU and possible higher power + * levels if it able to do so. Upon success, enter the final wfi + * which will power down this CPU. + */ + rc = psci_do_cpu_off(target_pwrlvl); + + /* + * The only error cpu_off can return is E_DENIED. So check if that's + * indeed the case. + */ + assert(rc == PSCI_E_DENIED); + + return rc; +} + +int psci_affinity_info(u_register_t target_affinity, + unsigned int lowest_affinity_level) +{ + int ret; + unsigned int target_idx; + + /* We dont support level higher than PSCI_CPU_PWR_LVL */ + if (lowest_affinity_level > PSCI_CPU_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Calculate the cpu index of the target */ + ret = plat_core_pos_by_mpidr(target_affinity); + if (ret == -1) { + return PSCI_E_INVALID_PARAMS; + } + target_idx = (unsigned int)ret; + + /* + * Generic management: + * Perform cache maintanence ahead of reading the target CPU state to + * ensure that the data is not stale. + * There is a theoretical edge case where the cache may contain stale + * data for the target CPU data - this can occur under the following + * conditions: + * - the target CPU is in another cluster from the current + * - the target CPU was the last CPU to shutdown on its cluster + * - the cluster was removed from coherency as part of the CPU shutdown + * + * In this case the cache maintenace that was performed as part of the + * target CPUs shutdown was not seen by the current CPU's cluster. And + * so the cache may contain stale data for the target CPU. + */ + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + + return psci_get_aff_info_state_by_idx(target_idx); +} + +int psci_migrate(u_register_t target_cpu) +{ + int rc; + u_register_t resident_cpu_mpidr; + + rc = psci_spd_migrate_info(&resident_cpu_mpidr); + if (rc != PSCI_TOS_UP_MIG_CAP) + return (rc == PSCI_TOS_NOT_UP_MIG_CAP) ? + PSCI_E_DENIED : PSCI_E_NOT_SUPPORTED; + + /* + * Migrate should only be invoked on the CPU where + * the Secure OS is resident. + */ + if (resident_cpu_mpidr != read_mpidr_el1()) + return PSCI_E_NOT_PRESENT; + + /* Check the validity of the specified target cpu */ + rc = psci_validate_mpidr(target_cpu); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + assert((psci_spd_pm != NULL) && (psci_spd_pm->svc_migrate != NULL)); + + rc = psci_spd_pm->svc_migrate(read_mpidr_el1(), target_cpu); + assert((rc == PSCI_E_SUCCESS) || (rc == PSCI_E_INTERN_FAIL)); + + return rc; +} + +int psci_migrate_info_type(void) +{ + u_register_t resident_cpu_mpidr; + + return psci_spd_migrate_info(&resident_cpu_mpidr); +} + +u_register_t psci_migrate_info_up_cpu(void) +{ + u_register_t resident_cpu_mpidr; + int rc; + + /* + * Return value of this depends upon what + * psci_spd_migrate_info() returns. + */ + rc = psci_spd_migrate_info(&resident_cpu_mpidr); + if ((rc != PSCI_TOS_NOT_UP_MIG_CAP) && (rc != PSCI_TOS_UP_MIG_CAP)) + return (u_register_t)(register_t) PSCI_E_INVALID_PARAMS; + + return resident_cpu_mpidr; +} + +int psci_node_hw_state(u_register_t target_cpu, + unsigned int power_level) +{ + int rc; + + /* Validate target_cpu */ + rc = psci_validate_mpidr(target_cpu); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + /* Validate power_level against PLAT_MAX_PWR_LVL */ + if (power_level > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* + * Dispatch this call to platform to query power controller, and pass on + * to the caller what it returns + */ + assert(psci_plat_pm_ops->get_node_hw_state != NULL); + rc = psci_plat_pm_ops->get_node_hw_state(target_cpu, power_level); + assert(((rc >= HW_ON) && (rc <= HW_STANDBY)) + || (rc == PSCI_E_NOT_SUPPORTED) + || (rc == PSCI_E_INVALID_PARAMS)); + return rc; +} + +int psci_features(unsigned int psci_fid) +{ + unsigned int local_caps = psci_caps; + + if (psci_fid == SMCCC_VERSION) + return PSCI_E_SUCCESS; + + /* Check if it is a 64 bit function */ + if (((psci_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64) + local_caps &= PSCI_CAP_64BIT_MASK; + + /* Check for invalid fid */ + if (!(is_std_svc_call(psci_fid) && is_valid_fast_smc(psci_fid) + && is_psci_fid(psci_fid))) + return PSCI_E_NOT_SUPPORTED; + + + /* Check if the psci fid is supported or not */ + if ((local_caps & define_psci_cap(psci_fid)) == 0U) + return PSCI_E_NOT_SUPPORTED; + + /* Format the feature flags */ + if ((psci_fid == PSCI_CPU_SUSPEND_AARCH32) || + (psci_fid == PSCI_CPU_SUSPEND_AARCH64)) { + /* + * The trusted firmware does not support OS Initiated Mode. + */ + unsigned int ret = ((FF_PSTATE << FF_PSTATE_SHIFT) | + (((FF_SUPPORTS_OS_INIT_MODE == 1U) ? 0U : 1U) + << FF_MODE_SUPPORT_SHIFT)); + return (int) ret; + } + + /* Return 0 for all other fid's */ + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * PSCI top level handler for servicing SMCs. + ******************************************************************************/ +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) +{ + u_register_t ret; + + if (is_caller_secure(flags)) + return (u_register_t)SMC_UNK; + + /* Check the fid against the capabilities */ + if ((psci_caps & define_psci_cap(smc_fid)) == 0U) + return (u_register_t)SMC_UNK; + + if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { + /* 32-bit PSCI function, clear top parameter bits */ + + uint32_t r1 = (uint32_t)x1; + uint32_t r2 = (uint32_t)x2; + uint32_t r3 = (uint32_t)x3; + + switch (smc_fid) { + case PSCI_VERSION: + ret = (u_register_t)psci_version(); + break; + + case PSCI_CPU_OFF: + ret = (u_register_t)psci_cpu_off(); + break; + + case PSCI_CPU_SUSPEND_AARCH32: + ret = (u_register_t)psci_cpu_suspend(r1, r2, r3); + break; + + case PSCI_CPU_ON_AARCH32: + ret = (u_register_t)psci_cpu_on(r1, r2, r3); + break; + + case PSCI_AFFINITY_INFO_AARCH32: + ret = (u_register_t)psci_affinity_info(r1, r2); + break; + + case PSCI_MIG_AARCH32: + ret = (u_register_t)psci_migrate(r1); + break; + + case PSCI_MIG_INFO_TYPE: + ret = (u_register_t)psci_migrate_info_type(); + break; + + case PSCI_MIG_INFO_UP_CPU_AARCH32: + ret = psci_migrate_info_up_cpu(); + break; + + case PSCI_NODE_HW_STATE_AARCH32: + ret = (u_register_t)psci_node_hw_state(r1, r2); + break; + + case PSCI_SYSTEM_SUSPEND_AARCH32: + ret = (u_register_t)psci_system_suspend(r1, r2); + break; + + case PSCI_SYSTEM_OFF: + psci_system_off(); + /* We should never return from psci_system_off() */ + break; + + case PSCI_SYSTEM_RESET: + psci_system_reset(); + /* We should never return from psci_system_reset() */ + break; + + case PSCI_FEATURES: + ret = (u_register_t)psci_features(r1); + break; + +#if ENABLE_PSCI_STAT + case PSCI_STAT_RESIDENCY_AARCH32: + ret = psci_stat_residency(r1, r2); + break; + + case PSCI_STAT_COUNT_AARCH32: + ret = psci_stat_count(r1, r2); + break; +#endif + case PSCI_MEM_PROTECT: + ret = psci_mem_protect(r1); + break; + + case PSCI_MEM_CHK_RANGE_AARCH32: + ret = psci_mem_chk_range(r1, r2); + break; + + case PSCI_SYSTEM_RESET2_AARCH32: + /* We should never return from psci_system_reset2() */ + ret = psci_system_reset2(r1, r2); + break; + + default: + WARN("Unimplemented PSCI Call: 0x%x\n", smc_fid); + ret = (u_register_t)SMC_UNK; + break; + } + } else { + /* 64-bit PSCI function */ + + switch (smc_fid) { + case PSCI_CPU_SUSPEND_AARCH64: + ret = (u_register_t) + psci_cpu_suspend((unsigned int)x1, x2, x3); + break; + + case PSCI_CPU_ON_AARCH64: + ret = (u_register_t)psci_cpu_on(x1, x2, x3); + break; + + case PSCI_AFFINITY_INFO_AARCH64: + ret = (u_register_t) + psci_affinity_info(x1, (unsigned int)x2); + break; + + case PSCI_MIG_AARCH64: + ret = (u_register_t)psci_migrate(x1); + break; + + case PSCI_MIG_INFO_UP_CPU_AARCH64: + ret = psci_migrate_info_up_cpu(); + break; + + case PSCI_NODE_HW_STATE_AARCH64: + ret = (u_register_t)psci_node_hw_state( + x1, (unsigned int) x2); + break; + + case PSCI_SYSTEM_SUSPEND_AARCH64: + ret = (u_register_t)psci_system_suspend(x1, x2); + break; + +#if ENABLE_PSCI_STAT + case PSCI_STAT_RESIDENCY_AARCH64: + ret = psci_stat_residency(x1, (unsigned int) x2); + break; + + case PSCI_STAT_COUNT_AARCH64: + ret = psci_stat_count(x1, (unsigned int) x2); + break; +#endif + + case PSCI_MEM_CHK_RANGE_AARCH64: + ret = psci_mem_chk_range(x1, x2); + break; + + case PSCI_SYSTEM_RESET2_AARCH64: + /* We should never return from psci_system_reset2() */ + ret = psci_system_reset2((uint32_t) x1, x2); + break; + + default: + WARN("Unimplemented PSCI Call: 0x%x\n", smc_fid); + ret = (u_register_t)SMC_UNK; + break; + } + } + + return ret; +} diff --git a/arm-trusted-firmware/lib/psci/psci_mem_protect.c b/arm-trusted-firmware/lib/psci/psci_mem_protect.c new file mode 100644 index 0000000..481051f --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_mem_protect.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include "psci_private.h" + +u_register_t psci_mem_protect(unsigned int enable) +{ + int val; + + assert(psci_plat_pm_ops->read_mem_protect != NULL); + assert(psci_plat_pm_ops->write_mem_protect != NULL); + + if (psci_plat_pm_ops->read_mem_protect(&val) < 0) + return (u_register_t) PSCI_E_NOT_SUPPORTED; + if (psci_plat_pm_ops->write_mem_protect(enable) < 0) + return (u_register_t) PSCI_E_NOT_SUPPORTED; + + return (val != 0) ? 1U : 0U; +} + +u_register_t psci_mem_chk_range(uintptr_t base, u_register_t length) +{ + int ret; + + assert(psci_plat_pm_ops->mem_protect_chk != NULL); + + if ((length == 0U) || check_uptr_overflow(base, length - 1U)) + return (u_register_t) PSCI_E_DENIED; + + ret = psci_plat_pm_ops->mem_protect_chk(base, length); + return (ret < 0) ? + (u_register_t) PSCI_E_DENIED : (u_register_t) PSCI_E_SUCCESS; +} diff --git a/arm-trusted-firmware/lib/psci/psci_off.c b/arm-trusted-firmware/lib/psci/psci_off.c new file mode 100644 index 0000000..5447045 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_off.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "psci_private.h" + +/****************************************************************************** + * Construct the psci_power_state to request power OFF at all power levels. + ******************************************************************************/ +static void psci_set_power_off_state(psci_power_state_t *state_info) +{ + unsigned int lvl; + + for (lvl = PSCI_CPU_PWR_LVL; lvl <= PLAT_MAX_PWR_LVL; lvl++) + state_info->pwr_domain_state[lvl] = PLAT_MAX_OFF_STATE; +} + +/****************************************************************************** + * Top level handler which is called when a cpu wants to power itself down. + * It's assumed that along with turning the cpu power domain off, power + * domains at higher levels will be turned off as far as possible. It finds + * the highest level where a domain has to be powered off by traversing the + * node information and then performs generic, architectural, platform setup + * and state management required to turn OFF that power domain and domains + * below it. e.g. For a cpu that's to be powered OFF, it could mean programming + * the power controller whereas for a cluster that's to be powered off, it will + * call the platform specific code which will disable coherency at the + * interconnect level if the cpu is the last in the cluster and also the + * program the power controller. + ******************************************************************************/ +int psci_do_cpu_off(unsigned int end_pwrlvl) +{ + int rc = PSCI_E_SUCCESS; + unsigned int idx = plat_my_core_pos(); + psci_power_state_t state_info; + unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; + + /* + * This function must only be called on platforms where the + * CPU_OFF platform hooks have been implemented. + */ + assert(psci_plat_pm_ops->pwr_domain_off != NULL); + + /* Construct the psci_power_state for CPU_OFF */ + psci_set_power_off_state(&state_info); + + /* + * Get the parent nodes here, this is important to do before we + * initiate the power down sequence as after that point the core may + * have exited coherency and its cache may be disabled, any access to + * shared memory after that (such as the parent node lookup in + * psci_cpu_pd_nodes) can cause coherency issues on some platforms. + */ + psci_get_parent_pwr_domain_nodes(idx, end_pwrlvl, parent_nodes); + + /* + * This function acquires the lock corresponding to each power + * level so that by the time all locks are taken, the system topology + * is snapshot and state management can be done safely. + */ + psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); + + /* + * Call the cpu off handler registered by the Secure Payload Dispatcher + * to let it do any bookkeeping. Assume that the SPD always reports an + * E_DENIED error if SP refuse to power down + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_off != NULL)) { + rc = psci_spd_pm->svc_off(0); + if (rc != 0) + goto exit; + } + + /* + * This function is passed the requested state info and + * it returns the negotiated state info for each power level upto + * the end level specified. + */ + psci_do_state_coordination(end_pwrlvl, &state_info); + +#if ENABLE_PSCI_STAT + /* Update the last cpu for each level till end_pwrlvl */ + psci_stats_update_pwr_down(end_pwrlvl, &state_info); +#endif + +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Flush cache line so that even if CPU power down happens + * the timestamp update is reflected in memory. + */ + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_CFLUSH, + PMF_CACHE_MAINT); +#endif + + /* + * Arch. management. Initiate power down sequence. + */ + psci_do_pwrdown_sequence(psci_find_max_off_lvl(&state_info)); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_CFLUSH, + PMF_NO_CACHE_MAINT); +#endif + + /* + * Plat. management: Perform platform specific actions to turn this + * cpu off e.g. exit cpu coherency, program the power controller etc. + */ + psci_plat_pm_ops->pwr_domain_off(&state_info); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_start(&state_info); +#endif + +exit: + /* + * Release the locks corresponding to each power level in the + * reverse order to which they were acquired. + */ + psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); + + /* + * Check if all actions needed to safely power down this cpu have + * successfully completed. + */ + if (rc == PSCI_E_SUCCESS) { + /* + * Set the affinity info state to OFF. When caches are disabled, + * this writes directly to main memory, so cache maintenance is + * required to ensure that later cached reads of aff_info_state + * return AFF_STATE_OFF. A dsbish() ensures ordering of the + * update to the affinity info state prior to cache line + * invalidation. + */ + psci_flush_cpu_data(psci_svc_cpu_data.aff_info_state); + psci_set_aff_info_state(AFF_STATE_OFF); + psci_dsbish(); + psci_inv_cpu_data(psci_svc_cpu_data.aff_info_state); + +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Update the timestamp with cache off. We assume this + * timestamp can only be read from the current CPU and the + * timestamp cache line will be flushed before return to + * normal world on wakeup. + */ + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi != NULL) { + /* This function must not return */ + psci_plat_pm_ops->pwr_domain_pwr_down_wfi(&state_info); + } else { + /* + * Enter a wfi loop which will allow the power + * controller to physically power down this cpu. + */ + psci_power_down_wfi(); + } + } + + return rc; +} diff --git a/arm-trusted-firmware/lib/psci/psci_on.c b/arm-trusted-firmware/lib/psci/psci_on.c new file mode 100644 index 0000000..dd48e10 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_on.c @@ -0,0 +1,233 @@ +/* + * 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 "psci_private.h" + +/* + * Helper functions for the CPU level spinlocks + */ +static inline void psci_spin_lock_cpu(unsigned int idx) +{ + spin_lock(&psci_cpu_pd_nodes[idx].cpu_lock); +} + +static inline void psci_spin_unlock_cpu(unsigned int idx) +{ + spin_unlock(&psci_cpu_pd_nodes[idx].cpu_lock); +} + +/******************************************************************************* + * This function checks whether a cpu which has been requested to be turned on + * is OFF to begin with. + ******************************************************************************/ +static int cpu_on_validate_state(aff_info_state_t aff_state) +{ + if (aff_state == AFF_STATE_ON) + return PSCI_E_ALREADY_ON; + + if (aff_state == AFF_STATE_ON_PENDING) + return PSCI_E_ON_PENDING; + + assert(aff_state == AFF_STATE_OFF); + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Generic handler which is called to physically power on a cpu identified by + * its mpidr. It performs the generic, architectural, platform setup and state + * management to power on the target cpu e.g. it will ensure that + * enough information is stashed for it to resume execution in the non-secure + * security state. + * + * The state of all the relevant power domains are changed after calling the + * platform handler as it can return error. + ******************************************************************************/ +int psci_cpu_on_start(u_register_t target_cpu, + const entry_point_info_t *ep) +{ + int rc; + aff_info_state_t target_aff_state; + int ret = plat_core_pos_by_mpidr(target_cpu); + unsigned int target_idx = (unsigned int)ret; + + /* Calling function must supply valid input arguments */ + assert(ret >= 0); + assert(ep != NULL); + + + /* + * This function must only be called on platforms where the + * CPU_ON platform hooks have been implemented. + */ + assert((psci_plat_pm_ops->pwr_domain_on != NULL) && + (psci_plat_pm_ops->pwr_domain_on_finish != NULL)); + + /* Protect against multiple CPUs trying to turn ON the same target CPU */ + psci_spin_lock_cpu(target_idx); + + /* + * Generic management: Ensure that the cpu is off to be + * turned on. + * Perform cache maintanence ahead of reading the target CPU state to + * ensure that the data is not stale. + * There is a theoretical edge case where the cache may contain stale + * data for the target CPU data - this can occur under the following + * conditions: + * - the target CPU is in another cluster from the current + * - the target CPU was the last CPU to shutdown on its cluster + * - the cluster was removed from coherency as part of the CPU shutdown + * + * In this case the cache maintenace that was performed as part of the + * target CPUs shutdown was not seen by the current CPU's cluster. And + * so the cache may contain stale data for the target CPU. + */ + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + rc = cpu_on_validate_state(psci_get_aff_info_state_by_idx(target_idx)); + if (rc != PSCI_E_SUCCESS) + goto exit; + + /* + * Call the cpu on handler registered by the Secure Payload Dispatcher + * to let it do any bookeeping. If the handler encounters an error, it's + * expected to assert within + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_on != NULL)) + psci_spd_pm->svc_on(target_cpu); + + /* + * Set the Affinity info state of the target cpu to ON_PENDING. + * Flush aff_info_state as it will be accessed with caches + * turned OFF. + */ + psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_ON_PENDING); + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + + /* + * The cache line invalidation by the target CPU after setting the + * state to OFF (see psci_do_cpu_off()), could cause the update to + * aff_info_state to be invalidated. Retry the update if the target + * CPU aff_info_state is not ON_PENDING. + */ + target_aff_state = psci_get_aff_info_state_by_idx(target_idx); + if (target_aff_state != AFF_STATE_ON_PENDING) { + assert(target_aff_state == AFF_STATE_OFF); + psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_ON_PENDING); + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + + assert(psci_get_aff_info_state_by_idx(target_idx) == + AFF_STATE_ON_PENDING); + } + + /* + * Perform generic, architecture and platform specific handling. + */ + /* + * Plat. management: Give the platform the current state + * of the target cpu to allow it to perform the necessary + * steps to power on. + */ + rc = psci_plat_pm_ops->pwr_domain_on(target_cpu); + assert((rc == PSCI_E_SUCCESS) || (rc == PSCI_E_INTERN_FAIL)); + + if (rc == PSCI_E_SUCCESS) + /* Store the re-entry information for the non-secure world. */ + cm_init_context_by_index(target_idx, ep); + else { + /* Restore the state on error. */ + psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_OFF); + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + } + +exit: + psci_spin_unlock_cpu(target_idx); + return rc; +} + +/******************************************************************************* + * The following function finish an earlier power on request. They + * are called by the common finisher routine in psci_common.c. The `state_info` + * is the psci_power_state from which this CPU has woken up from. + ******************************************************************************/ +void psci_cpu_on_finish(unsigned int cpu_idx, const psci_power_state_t *state_info) +{ + /* + * Plat. management: Perform the platform specific actions + * for this cpu e.g. enabling the gic or zeroing the mailbox + * register. The actual state of this cpu has already been + * changed. + */ + psci_plat_pm_ops->pwr_domain_on_finish(state_info); + +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + /* + * Arch. management: Enable data cache and manage stack memory + */ + psci_do_pwrup_cache_maintenance(); +#endif + + /* + * Plat. management: Perform any platform specific actions which + * can only be done with the cpu and the cluster guaranteed to + * be coherent. + */ + if (psci_plat_pm_ops->pwr_domain_on_finish_late != NULL) + psci_plat_pm_ops->pwr_domain_on_finish_late(state_info); + + /* + * All the platform specific actions for turning this cpu + * on have completed. Perform enough arch.initialization + * to run in the non-secure address space. + */ + psci_arch_setup(); + + /* + * Lock the CPU spin lock to make sure that the context initialization + * is done. Since the lock is only used in this function to create + * a synchronization point with cpu_on_start(), it can be released + * immediately. + */ + psci_spin_lock_cpu(cpu_idx); + psci_spin_unlock_cpu(cpu_idx); + + /* Ensure we have been explicitly woken up by another cpu */ + assert(psci_get_aff_info_state() == AFF_STATE_ON_PENDING); + + /* + * Call the cpu on finish handler registered by the Secure Payload + * Dispatcher to let it do any bookeeping. If the handler encounters an + * error, it's expected to assert within + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_on_finish != NULL)) + psci_spd_pm->svc_on_finish(0); + + PUBLISH_EVENT(psci_cpu_on_finish); + + /* Populate the mpidr field within the cpu node array */ + /* This needs to be done only once */ + psci_cpu_pd_nodes[cpu_idx].mpidr = read_mpidr() & MPIDR_AFFINITY_MASK; + + /* + * Generic management: Now we just need to retrieve the + * information that we had stashed away during the cpu_on + * call to set this cpu on its way. + */ + cm_prepare_el3_exit(NON_SECURE); +} diff --git a/arm-trusted-firmware/lib/psci/psci_private.h b/arm-trusted-firmware/lib/psci/psci_private.h new file mode 100644 index 0000000..72bd6bd --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_private.h @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PSCI_PRIVATE_H +#define PSCI_PRIVATE_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * The PSCI capability which are provided by the generic code but does not + * depend on the platform or spd capabilities. + */ +#define PSCI_GENERIC_CAP \ + (define_psci_cap(PSCI_VERSION) | \ + define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \ + define_psci_cap(PSCI_FEATURES)) + +/* + * The PSCI capabilities mask for 64 bit functions. + */ +#define PSCI_CAP_64BIT_MASK \ + (define_psci_cap(PSCI_CPU_SUSPEND_AARCH64) | \ + define_psci_cap(PSCI_CPU_ON_AARCH64) | \ + define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \ + define_psci_cap(PSCI_MIG_AARCH64) | \ + define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) | \ + define_psci_cap(PSCI_NODE_HW_STATE_AARCH64) | \ + define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64) | \ + define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64) | \ + define_psci_cap(PSCI_STAT_COUNT_AARCH64) | \ + define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64) | \ + define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64)) + +/* Internally PSCI uses a uint16_t for various cpu indexes so + * define a limit to number of CPUs that can be initialised. + */ +#define PSCI_MAX_CPUS_INDEX 0xFFFFU + +/* + * Helper functions to get/set the fields of PSCI per-cpu data. + */ +static inline void psci_set_aff_info_state(aff_info_state_t aff_state) +{ + set_cpu_data(psci_svc_cpu_data.aff_info_state, aff_state); +} + +static inline aff_info_state_t psci_get_aff_info_state(void) +{ + return get_cpu_data(psci_svc_cpu_data.aff_info_state); +} + +static inline aff_info_state_t psci_get_aff_info_state_by_idx(unsigned int idx) +{ + return get_cpu_data_by_index(idx, + psci_svc_cpu_data.aff_info_state); +} + +static inline void psci_set_aff_info_state_by_idx(unsigned int idx, + aff_info_state_t aff_state) +{ + set_cpu_data_by_index(idx, + psci_svc_cpu_data.aff_info_state, aff_state); +} + +static inline unsigned int psci_get_suspend_pwrlvl(void) +{ + return get_cpu_data(psci_svc_cpu_data.target_pwrlvl); +} + +static inline void psci_set_suspend_pwrlvl(unsigned int target_lvl) +{ + set_cpu_data(psci_svc_cpu_data.target_pwrlvl, target_lvl); +} + +static inline void psci_set_cpu_local_state(plat_local_state_t state) +{ + set_cpu_data(psci_svc_cpu_data.local_state, state); +} + +static inline plat_local_state_t psci_get_cpu_local_state(void) +{ + return get_cpu_data(psci_svc_cpu_data.local_state); +} + +static inline plat_local_state_t psci_get_cpu_local_state_by_idx( + unsigned int idx) +{ + return get_cpu_data_by_index(idx, + psci_svc_cpu_data.local_state); +} + +/* Helper function to identify a CPU standby request in PSCI Suspend call */ +static inline bool is_cpu_standby_req(unsigned int is_power_down_state, + unsigned int retn_lvl) +{ + return (is_power_down_state == 0U) && (retn_lvl == 0U); +} + +/******************************************************************************* + * The following two data structures implement the power domain tree. The tree + * is used to track the state of all the nodes i.e. power domain instances + * described by the platform. The tree consists of nodes that describe CPU power + * domains i.e. leaf nodes and all other power domains which are parents of a + * CPU power domain i.e. non-leaf nodes. + ******************************************************************************/ +typedef struct non_cpu_pwr_domain_node { + /* + * Index of the first CPU power domain node level 0 which has this node + * as its parent. + */ + unsigned int cpu_start_idx; + + /* + * Number of CPU power domains which are siblings of the domain indexed + * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx + * -> cpu_start_idx + ncpus' have this node as their parent. + */ + unsigned int ncpus; + + /* + * Index of the parent power domain node. + * TODO: Figure out whether to whether using pointer is more efficient. + */ + unsigned int parent_node; + + plat_local_state_t local_state; + + unsigned char level; + + /* For indexing the psci_lock array*/ + uint16_t lock_index; +} non_cpu_pd_node_t; + +typedef struct cpu_pwr_domain_node { + u_register_t mpidr; + + /* + * Index of the parent power domain node. + * TODO: Figure out whether to whether using pointer is more efficient. + */ + unsigned int parent_node; + + /* + * A CPU power domain does not require state coordination like its + * parent power domains. Hence this node does not include a bakery + * lock. A spinlock is required by the CPU_ON handler to prevent a race + * when multiple CPUs try to turn ON the same target CPU. + */ + spinlock_t cpu_lock; +} cpu_pd_node_t; + +/******************************************************************************* + * The following are helpers and declarations of locks. + ******************************************************************************/ +#if HW_ASSISTED_COHERENCY +/* + * On systems where participant CPUs are cache-coherent, we can use spinlocks + * instead of bakery locks. + */ +#define DEFINE_PSCI_LOCK(_name) spinlock_t _name +#define DECLARE_PSCI_LOCK(_name) extern DEFINE_PSCI_LOCK(_name) + +/* One lock is required per non-CPU power domain node */ +DECLARE_PSCI_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]); + +/* + * On systems with hardware-assisted coherency, make PSCI cache operations NOP, + * as PSCI participants are cache-coherent, and there's no need for explicit + * cache maintenance operations or barriers to coordinate their state. + */ +static inline void psci_flush_dcache_range(uintptr_t __unused addr, + size_t __unused size) +{ + /* Empty */ +} + +#define psci_flush_cpu_data(member) +#define psci_inv_cpu_data(member) + +static inline void psci_dsbish(void) +{ + /* Empty */ +} + +static inline void psci_lock_get(non_cpu_pd_node_t *non_cpu_pd_node) +{ + spin_lock(&psci_locks[non_cpu_pd_node->lock_index]); +} + +static inline void psci_lock_release(non_cpu_pd_node_t *non_cpu_pd_node) +{ + spin_unlock(&psci_locks[non_cpu_pd_node->lock_index]); +} + +#else /* if HW_ASSISTED_COHERENCY == 0 */ +/* + * Use bakery locks for state coordination as not all PSCI participants are + * cache coherent. + */ +#define DEFINE_PSCI_LOCK(_name) DEFINE_BAKERY_LOCK(_name) +#define DECLARE_PSCI_LOCK(_name) DECLARE_BAKERY_LOCK(_name) + +/* One lock is required per non-CPU power domain node */ +DECLARE_PSCI_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]); + +/* + * If not all PSCI participants are cache-coherent, perform cache maintenance + * and issue barriers wherever required to coordinate state. + */ +static inline void psci_flush_dcache_range(uintptr_t addr, size_t size) +{ + flush_dcache_range(addr, size); +} + +#define psci_flush_cpu_data(member) flush_cpu_data(member) +#define psci_inv_cpu_data(member) inv_cpu_data(member) + +static inline void psci_dsbish(void) +{ + dsbish(); +} + +static inline void psci_lock_get(non_cpu_pd_node_t *non_cpu_pd_node) +{ + bakery_lock_get(&psci_locks[non_cpu_pd_node->lock_index]); +} + +static inline void psci_lock_release(non_cpu_pd_node_t *non_cpu_pd_node) +{ + bakery_lock_release(&psci_locks[non_cpu_pd_node->lock_index]); +} + +#endif /* HW_ASSISTED_COHERENCY */ + +static inline void psci_lock_init(non_cpu_pd_node_t *non_cpu_pd_node, + uint16_t idx) +{ + non_cpu_pd_node[idx].lock_index = idx; +} + +/******************************************************************************* + * Data prototypes + ******************************************************************************/ +extern const plat_psci_ops_t *psci_plat_pm_ops; +extern non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS]; +extern cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT]; +extern unsigned int psci_caps; +extern unsigned int psci_plat_core_count; + +/******************************************************************************* + * SPD's power management hooks registered with PSCI + ******************************************************************************/ +extern const spd_pm_ops_t *psci_spd_pm; + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +/* Private exported functions from psci_common.c */ +int psci_validate_power_state(unsigned int power_state, + psci_power_state_t *state_info); +void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info); +int psci_validate_mpidr(u_register_t mpidr); +void psci_init_req_local_pwr_states(void); +void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, + psci_power_state_t *target_state); +int psci_validate_entry_point(entry_point_info_t *ep, + uintptr_t entrypoint, u_register_t context_id); +void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx, + unsigned int end_lvl, + unsigned int *node_index); +void psci_do_state_coordination(unsigned int end_pwrlvl, + psci_power_state_t *state_info); +void psci_acquire_pwr_domain_locks(unsigned int end_pwrlvl, + const unsigned int *parent_nodes); +void psci_release_pwr_domain_locks(unsigned int end_pwrlvl, + const unsigned int *parent_nodes); +int psci_validate_suspend_req(const psci_power_state_t *state_info, + unsigned int is_power_down_state); +unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info); +unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info); +void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl); +void psci_print_power_domain_map(void); +unsigned int psci_is_last_on_cpu(void); +int psci_spd_migrate_info(u_register_t *mpidr); +void psci_do_pwrdown_sequence(unsigned int power_level); + +/* + * CPU power down is directly called only when HW_ASSISTED_COHERENCY is + * available. Otherwise, this needs post-call stack maintenance, which is + * handled in assembly. + */ +void prepare_cpu_pwr_dwn(unsigned int power_level); + +/* Private exported functions from psci_on.c */ +int psci_cpu_on_start(u_register_t target_cpu, + const entry_point_info_t *ep); + +void psci_cpu_on_finish(unsigned int cpu_idx, const psci_power_state_t *state_info); + +/* Private exported functions from psci_off.c */ +int psci_do_cpu_off(unsigned int end_pwrlvl); + +/* Private exported functions from psci_suspend.c */ +void psci_cpu_suspend_start(const entry_point_info_t *ep, + unsigned int end_pwrlvl, + psci_power_state_t *state_info, + unsigned int is_power_down_state); + +void psci_cpu_suspend_finish(unsigned int cpu_idx, const psci_power_state_t *state_info); + +/* Private exported functions from psci_helpers.S */ +void psci_do_pwrdown_cache_maintenance(unsigned int pwr_level); +void psci_do_pwrup_cache_maintenance(void); + +/* Private exported functions from psci_system_off.c */ +void __dead2 psci_system_off(void); +void __dead2 psci_system_reset(void); +u_register_t psci_system_reset2(uint32_t reset_type, u_register_t cookie); + +/* Private exported functions from psci_stat.c */ +void psci_stats_update_pwr_down(unsigned int end_pwrlvl, + const psci_power_state_t *state_info); +void psci_stats_update_pwr_up(unsigned int end_pwrlvl, + const psci_power_state_t *state_info); +u_register_t psci_stat_residency(u_register_t target_cpu, + unsigned int power_state); +u_register_t psci_stat_count(u_register_t target_cpu, + unsigned int power_state); + +/* Private exported functions from psci_mem_protect.c */ +u_register_t psci_mem_protect(unsigned int enable); +u_register_t psci_mem_chk_range(uintptr_t base, u_register_t length); + +#endif /* PSCI_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/psci/psci_setup.c b/arm-trusted-firmware/lib/psci/psci_setup.c new file mode 100644 index 0000000..3cb4f7e --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_setup.c @@ -0,0 +1,315 @@ +/* + * 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 "psci_private.h" + +/* + * Check that PLATFORM_CORE_COUNT fits into the number of cores + * that can be represented by PSCI_MAX_CPUS_INDEX. + */ +CASSERT(PLATFORM_CORE_COUNT <= (PSCI_MAX_CPUS_INDEX + 1U), assert_psci_cores_overflow); + +/******************************************************************************* + * Per cpu non-secure contexts used to program the architectural state prior + * return to the normal world. + * TODO: Use the memory allocator to set aside memory for the contexts instead + * of relying on platform defined constants. + ******************************************************************************/ +static cpu_context_t psci_ns_context[PLATFORM_CORE_COUNT]; + +/****************************************************************************** + * Define the psci capability variable. + *****************************************************************************/ +unsigned int psci_caps; + +/******************************************************************************* + * Function which initializes the 'psci_non_cpu_pd_nodes' or the + * 'psci_cpu_pd_nodes' corresponding to the power level. + ******************************************************************************/ +static void __init psci_init_pwr_domain_node(uint16_t node_idx, + unsigned int parent_idx, + unsigned char level) +{ + if (level > PSCI_CPU_PWR_LVL) { + assert(node_idx < PSCI_NUM_NON_CPU_PWR_DOMAINS); + + psci_non_cpu_pd_nodes[node_idx].level = level; + psci_lock_init(psci_non_cpu_pd_nodes, node_idx); + psci_non_cpu_pd_nodes[node_idx].parent_node = parent_idx; + psci_non_cpu_pd_nodes[node_idx].local_state = + PLAT_MAX_OFF_STATE; + } else { + psci_cpu_data_t *svc_cpu_data; + + assert(node_idx < PLATFORM_CORE_COUNT); + + psci_cpu_pd_nodes[node_idx].parent_node = parent_idx; + + /* Initialize with an invalid mpidr */ + psci_cpu_pd_nodes[node_idx].mpidr = PSCI_INVALID_MPIDR; + + svc_cpu_data = + &(_cpu_data_by_index(node_idx)->psci_svc_cpu_data); + + /* Set the Affinity Info for the cores as OFF */ + svc_cpu_data->aff_info_state = AFF_STATE_OFF; + + /* Invalidate the suspend level for the cpu */ + svc_cpu_data->target_pwrlvl = PSCI_INVALID_PWR_LVL; + + /* Set the power state to OFF state */ + svc_cpu_data->local_state = PLAT_MAX_OFF_STATE; + + psci_flush_dcache_range((uintptr_t)svc_cpu_data, + sizeof(*svc_cpu_data)); + + cm_set_context_by_index(node_idx, + (void *) &psci_ns_context[node_idx], + NON_SECURE); + } +} + +/******************************************************************************* + * This functions updates cpu_start_idx and ncpus field for each of the node in + * psci_non_cpu_pd_nodes[]. It does so by comparing the parent nodes of each of + * the CPUs and check whether they match with the parent of the previous + * CPU. The basic assumption for this work is that children of the same parent + * are allocated adjacent indices. The platform should ensure this though proper + * mapping of the CPUs to indices via plat_core_pos_by_mpidr() and + * plat_my_core_pos() APIs. + *******************************************************************************/ +static void __init psci_update_pwrlvl_limits(void) +{ + unsigned int cpu_idx; + int j; + unsigned int nodes_idx[PLAT_MAX_PWR_LVL] = {0}; + unsigned int temp_index[PLAT_MAX_PWR_LVL]; + + for (cpu_idx = 0; cpu_idx < psci_plat_core_count; cpu_idx++) { + psci_get_parent_pwr_domain_nodes(cpu_idx, + PLAT_MAX_PWR_LVL, + temp_index); + for (j = (int)PLAT_MAX_PWR_LVL - 1; j >= 0; j--) { + if (temp_index[j] != nodes_idx[j]) { + nodes_idx[j] = temp_index[j]; + psci_non_cpu_pd_nodes[nodes_idx[j]].cpu_start_idx + = cpu_idx; + } + psci_non_cpu_pd_nodes[nodes_idx[j]].ncpus++; + } + } +} + +/******************************************************************************* + * Core routine to populate the power domain tree. The tree descriptor passed by + * the platform is populated breadth-first and the first entry in the map + * informs the number of root power domains. The parent nodes of the root nodes + * will point to an invalid entry(-1). + ******************************************************************************/ +static unsigned int __init populate_power_domain_tree(const unsigned char + *topology) +{ + unsigned int i, j = 0U, num_nodes_at_lvl = 1U, num_nodes_at_next_lvl; + unsigned int node_index = 0U, num_children; + unsigned int parent_node_index = 0U; + int level = (int)PLAT_MAX_PWR_LVL; + + /* + * For each level the inputs are: + * - number of nodes at this level in plat_array i.e. num_nodes_at_level + * This is the sum of values of nodes at the parent level. + * - Index of first entry at this level in the plat_array i.e. + * parent_node_index. + * - Index of first free entry in psci_non_cpu_pd_nodes[] or + * psci_cpu_pd_nodes[] i.e. node_index depending upon the level. + */ + while (level >= (int) PSCI_CPU_PWR_LVL) { + num_nodes_at_next_lvl = 0U; + /* + * For each entry (parent node) at this level in the plat_array: + * - Find the number of children + * - Allocate a node in a power domain array for each child + * - Set the parent of the child to the parent_node_index - 1 + * - Increment parent_node_index to point to the next parent + * - Accumulate the number of children at next level. + */ + for (i = 0U; i < num_nodes_at_lvl; i++) { + assert(parent_node_index <= + PSCI_NUM_NON_CPU_PWR_DOMAINS); + num_children = topology[parent_node_index]; + + for (j = node_index; + j < (node_index + num_children); j++) + psci_init_pwr_domain_node((uint16_t)j, + parent_node_index - 1U, + (unsigned char)level); + + node_index = j; + num_nodes_at_next_lvl += num_children; + parent_node_index++; + } + + num_nodes_at_lvl = num_nodes_at_next_lvl; + level--; + + /* Reset the index for the cpu power domain array */ + if (level == (int) PSCI_CPU_PWR_LVL) + node_index = 0; + } + + /* Validate the sanity of array exported by the platform */ + assert(j <= PLATFORM_CORE_COUNT); + return j; +} + +/******************************************************************************* + * This function does the architectural setup and takes the warm boot + * entry-point `mailbox_ep` as an argument. The function also initializes the + * power domain topology tree by querying the platform. The power domain nodes + * higher than the CPU are populated in the array psci_non_cpu_pd_nodes[] and + * the CPU power domains are populated in psci_cpu_pd_nodes[]. The platform + * exports its static topology map through the + * populate_power_domain_topology_tree() API. The algorithm populates the + * psci_non_cpu_pd_nodes and psci_cpu_pd_nodes iteratively by using this + * topology map. On a platform that implements two clusters of 2 cpus each, + * and supporting 3 domain levels, the populated psci_non_cpu_pd_nodes would + * look like this: + * + * --------------------------------------------------- + * | system node | cluster 0 node | cluster 1 node | + * --------------------------------------------------- + * + * And populated psci_cpu_pd_nodes would look like this : + * <- cpus cluster0 -><- cpus cluster1 -> + * ------------------------------------------------ + * | CPU 0 | CPU 1 | CPU 2 | CPU 3 | + * ------------------------------------------------ + ******************************************************************************/ +int __init psci_setup(const psci_lib_args_t *lib_args) +{ + const unsigned char *topology_tree; + + assert(VERIFY_PSCI_LIB_ARGS_V1(lib_args)); + + /* Do the Architectural initialization */ + psci_arch_setup(); + + /* Query the topology map from the platform */ + topology_tree = plat_get_power_domain_tree_desc(); + + /* Populate the power domain arrays using the platform topology map */ + psci_plat_core_count = populate_power_domain_tree(topology_tree); + + /* Update the CPU limits for each node in psci_non_cpu_pd_nodes */ + psci_update_pwrlvl_limits(); + + /* Populate the mpidr field of cpu node for this CPU */ + psci_cpu_pd_nodes[plat_my_core_pos()].mpidr = + read_mpidr() & MPIDR_AFFINITY_MASK; + + psci_init_req_local_pwr_states(); + + /* + * Set the requested and target state of this CPU and all the higher + * power domain levels for this CPU to run. + */ + psci_set_pwr_domains_to_run(PLAT_MAX_PWR_LVL); + + (void) plat_setup_psci_ops((uintptr_t)lib_args->mailbox_ep, + &psci_plat_pm_ops); + assert(psci_plat_pm_ops != NULL); + + /* + * Flush `psci_plat_pm_ops` as it will be accessed by secondary CPUs + * during warm boot, possibly before data cache is enabled. + */ + psci_flush_dcache_range((uintptr_t)&psci_plat_pm_ops, + sizeof(psci_plat_pm_ops)); + + /* Initialize the psci capability */ + psci_caps = PSCI_GENERIC_CAP; + + if (psci_plat_pm_ops->pwr_domain_off != NULL) + psci_caps |= define_psci_cap(PSCI_CPU_OFF); + if ((psci_plat_pm_ops->pwr_domain_on != NULL) && + (psci_plat_pm_ops->pwr_domain_on_finish != NULL)) + psci_caps |= define_psci_cap(PSCI_CPU_ON_AARCH64); + if ((psci_plat_pm_ops->pwr_domain_suspend != NULL) && + (psci_plat_pm_ops->pwr_domain_suspend_finish != NULL)) { + if (psci_plat_pm_ops->validate_power_state != NULL) + psci_caps |= define_psci_cap(PSCI_CPU_SUSPEND_AARCH64); + if (psci_plat_pm_ops->get_sys_suspend_power_state != NULL) + psci_caps |= define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64); + } + if (psci_plat_pm_ops->system_off != NULL) + psci_caps |= define_psci_cap(PSCI_SYSTEM_OFF); + if (psci_plat_pm_ops->system_reset != NULL) + psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET); + if (psci_plat_pm_ops->get_node_hw_state != NULL) + psci_caps |= define_psci_cap(PSCI_NODE_HW_STATE_AARCH64); + if ((psci_plat_pm_ops->read_mem_protect != NULL) && + (psci_plat_pm_ops->write_mem_protect != NULL)) + psci_caps |= define_psci_cap(PSCI_MEM_PROTECT); + if (psci_plat_pm_ops->mem_protect_chk != NULL) + psci_caps |= define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64); + if (psci_plat_pm_ops->system_reset2 != NULL) + psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64); + +#if ENABLE_PSCI_STAT + psci_caps |= define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64); + psci_caps |= define_psci_cap(PSCI_STAT_COUNT_AARCH64); +#endif + + return 0; +} + +/******************************************************************************* + * This duplicates what the primary cpu did after a cold boot in BL1. The same + * needs to be done when a cpu is hotplugged in. This function could also over- + * ride any EL3 setup done by BL1 as this code resides in rw memory. + ******************************************************************************/ +void psci_arch_setup(void) +{ +#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER) + /* Program the counter frequency */ + write_cntfrq_el0(plat_get_syscnt_freq2()); +#endif + + /* Initialize the cpu_ops pointer. */ + init_cpu_ops(); + + /* Having initialized cpu_ops, we can now print errata status */ + print_errata_status(); + +#if ENABLE_PAUTH + /* Store APIAKey_EL1 key */ + set_cpu_data(apiakey[0], read_apiakeylo_el1()); + set_cpu_data(apiakey[1], read_apiakeyhi_el1()); +#endif /* ENABLE_PAUTH */ +} + +/****************************************************************************** + * PSCI Library interface to initialize the cpu context for the next non + * secure image during cold boot. The relevant registers in the cpu context + * need to be retrieved and programmed on return from this interface. + *****************************************************************************/ +void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info) +{ + assert(GET_SECURITY_STATE(next_image_info->h.attr) == NON_SECURE); + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(NON_SECURE); +} diff --git a/arm-trusted-firmware/lib/psci/psci_stat.c b/arm-trusted-firmware/lib/psci/psci_stat.c new file mode 100644 index 0000000..ecef95a --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_stat.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#include "psci_private.h" + +#ifndef PLAT_MAX_PWR_LVL_STATES +#define PLAT_MAX_PWR_LVL_STATES 2U +#endif + +/* Following structure is used for PSCI STAT */ +typedef struct psci_stat { + u_register_t residency; + u_register_t count; +} psci_stat_t; + +/* + * Following is used to keep track of the last cpu + * that goes to power down in non cpu power domains. + */ +static int last_cpu_in_non_cpu_pd[PSCI_NUM_NON_CPU_PWR_DOMAINS] = { + [0 ... PSCI_NUM_NON_CPU_PWR_DOMAINS - 1U] = -1}; + +/* + * Following are used to store PSCI STAT values for + * CPU and non CPU power domains. + */ +static psci_stat_t psci_cpu_stat[PLATFORM_CORE_COUNT] + [PLAT_MAX_PWR_LVL_STATES]; +static psci_stat_t psci_non_cpu_stat[PSCI_NUM_NON_CPU_PWR_DOMAINS] + [PLAT_MAX_PWR_LVL_STATES]; + +/* + * This functions returns the index into the `psci_stat_t` array given the + * local power state and power domain level. If the platform implements the + * `get_pwr_lvl_state_idx` pm hook, then that will be used to return the index. + */ +static int get_stat_idx(plat_local_state_t local_state, unsigned int pwr_lvl) +{ + int idx; + + if (psci_plat_pm_ops->get_pwr_lvl_state_idx == NULL) { + assert(PLAT_MAX_PWR_LVL_STATES == 2U); + if (is_local_state_retn(local_state) != 0) + return 0; + + assert(is_local_state_off(local_state) != 0); + return 1; + } + + idx = psci_plat_pm_ops->get_pwr_lvl_state_idx(local_state, pwr_lvl); + assert((idx >= 0) && (idx < (int) PLAT_MAX_PWR_LVL_STATES)); + return idx; +} + +/******************************************************************************* + * This function is passed the target local power states for each power + * domain (state_info) between the current CPU domain and its ancestors until + * the target power level (end_pwrlvl). + * + * Then, for each level (apart from the CPU level) until the 'end_pwrlvl', it + * updates the `last_cpu_in_non_cpu_pd[]` with last power down cpu id. + * + * This function will only be invoked with data cache enabled and while + * powering down a core. + ******************************************************************************/ +void psci_stats_update_pwr_down(unsigned int end_pwrlvl, + const psci_power_state_t *state_info) +{ + unsigned int lvl, parent_idx; + unsigned int cpu_idx = plat_my_core_pos(); + + assert(end_pwrlvl <= PLAT_MAX_PWR_LVL); + assert(state_info != NULL); + + parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node; + + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + + /* Break early if the target power state is RUN */ + if (is_local_state_run(state_info->pwr_domain_state[lvl]) != 0) + break; + + /* + * The power domain is entering a low power state, so this is + * the last CPU for this power domain + */ + last_cpu_in_non_cpu_pd[parent_idx] = (int)cpu_idx; + + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + +} + +/******************************************************************************* + * This function updates the PSCI STATS(residency time and count) for CPU + * and NON-CPU power domains. + * It is called with caches enabled and locks acquired(for NON-CPU domain) + ******************************************************************************/ +void psci_stats_update_pwr_up(unsigned int end_pwrlvl, + const psci_power_state_t *state_info) +{ + unsigned int lvl, parent_idx; + unsigned int cpu_idx = plat_my_core_pos(); + int stat_idx; + plat_local_state_t local_state; + u_register_t residency; + + assert(end_pwrlvl <= PLAT_MAX_PWR_LVL); + assert(state_info != NULL); + + /* Get the index into the stats array */ + local_state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL]; + stat_idx = get_stat_idx(local_state, PSCI_CPU_PWR_LVL); + + /* Call into platform interface to calculate residency. */ + residency = plat_psci_stat_get_residency(PSCI_CPU_PWR_LVL, + state_info, cpu_idx); + + /* Update CPU stats. */ + psci_cpu_stat[cpu_idx][stat_idx].residency += residency; + psci_cpu_stat[cpu_idx][stat_idx].count++; + + /* + * Check what power domains above CPU were off + * prior to this CPU powering on. + */ + parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node; + /* Return early if this is the first power up. */ + if (last_cpu_in_non_cpu_pd[parent_idx] == -1) + return; + + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + local_state = state_info->pwr_domain_state[lvl]; + if (is_local_state_run(local_state) != 0) { + /* Break early */ + break; + } + + assert(last_cpu_in_non_cpu_pd[parent_idx] != -1); + + /* Call into platform interface to calculate residency. */ + residency = plat_psci_stat_get_residency(lvl, state_info, + (unsigned int)last_cpu_in_non_cpu_pd[parent_idx]); + + /* Initialize back to reset value */ + last_cpu_in_non_cpu_pd[parent_idx] = -1; + + /* Get the index into the stats array */ + stat_idx = get_stat_idx(local_state, lvl); + + /* Update non cpu stats */ + psci_non_cpu_stat[parent_idx][stat_idx].residency += residency; + psci_non_cpu_stat[parent_idx][stat_idx].count++; + + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + +} + +/******************************************************************************* + * This function returns the appropriate count and residency time of the + * local state for the highest power level expressed in the `power_state` + * for the node represented by `target_cpu`. + ******************************************************************************/ +static int psci_get_stat(u_register_t target_cpu, unsigned int power_state, + psci_stat_t *psci_stat) +{ + int rc; + unsigned int pwrlvl, lvl, parent_idx, target_idx; + int stat_idx; + psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} }; + plat_local_state_t local_state; + + /* Validate the target_cpu parameter and determine the cpu index */ + target_idx = (unsigned int) plat_core_pos_by_mpidr(target_cpu); + if (target_idx == (unsigned int) -1) + return PSCI_E_INVALID_PARAMS; + + /* Validate the power_state parameter */ + if (psci_plat_pm_ops->translate_power_state_by_mpidr == NULL) + rc = psci_validate_power_state(power_state, &state_info); + else + rc = psci_plat_pm_ops->translate_power_state_by_mpidr( + target_cpu, power_state, &state_info); + + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + /* Find the highest power level */ + pwrlvl = psci_find_target_suspend_lvl(&state_info); + if (pwrlvl == PSCI_INVALID_PWR_LVL) { + ERROR("Invalid target power level for PSCI statistics operation\n"); + panic(); + } + + /* Get the index into the stats array */ + local_state = state_info.pwr_domain_state[pwrlvl]; + stat_idx = get_stat_idx(local_state, pwrlvl); + + if (pwrlvl > PSCI_CPU_PWR_LVL) { + /* Get the power domain index */ + parent_idx = SPECULATION_SAFE_VALUE(psci_cpu_pd_nodes[target_idx].parent_node); + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl < pwrlvl; lvl++) + parent_idx = SPECULATION_SAFE_VALUE(psci_non_cpu_pd_nodes[parent_idx].parent_node); + + /* Get the non cpu power domain stats */ + *psci_stat = psci_non_cpu_stat[parent_idx][stat_idx]; + } else { + /* Get the cpu power domain stats */ + *psci_stat = psci_cpu_stat[target_idx][stat_idx]; + } + + return PSCI_E_SUCCESS; +} + +/* This is the top level function for PSCI_STAT_RESIDENCY SMC. */ +u_register_t psci_stat_residency(u_register_t target_cpu, + unsigned int power_state) +{ + psci_stat_t psci_stat; + int rc = psci_get_stat(target_cpu, power_state, &psci_stat); + + if (rc == PSCI_E_SUCCESS) + return psci_stat.residency; + else + return 0; +} + +/* This is the top level function for PSCI_STAT_COUNT SMC. */ +u_register_t psci_stat_count(u_register_t target_cpu, + unsigned int power_state) +{ + psci_stat_t psci_stat; + int rc = psci_get_stat(target_cpu, power_state, &psci_stat); + + if (rc == PSCI_E_SUCCESS) + return psci_stat.count; + else + return 0; +} diff --git a/arm-trusted-firmware/lib/psci/psci_suspend.c b/arm-trusted-firmware/lib/psci/psci_suspend.c new file mode 100644 index 0000000..da9f328 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_suspend.c @@ -0,0 +1,335 @@ +/* + * 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 + +#include "psci_private.h" + +/******************************************************************************* + * This function does generic and platform specific operations after a wake-up + * from standby/retention states at multiple power levels. + ******************************************************************************/ +static void psci_suspend_to_standby_finisher(unsigned int cpu_idx, + unsigned int end_pwrlvl) +{ + unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; + psci_power_state_t state_info; + + /* Get the parent nodes */ + psci_get_parent_pwr_domain_nodes(cpu_idx, end_pwrlvl, parent_nodes); + + psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); + + /* + * Find out which retention states this CPU has exited from until the + * 'end_pwrlvl'. The exit retention state could be deeper than the entry + * state as a result of state coordination amongst other CPUs post wfi. + */ + psci_get_target_local_pwr_states(end_pwrlvl, &state_info); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_stop(&state_info); + psci_stats_update_pwr_up(end_pwrlvl, &state_info); +#endif + + /* + * Plat. management: Allow the platform to do operations + * on waking up from retention. + */ + psci_plat_pm_ops->pwr_domain_suspend_finish(&state_info); + + /* + * Set the requested and target state of this CPU and all the higher + * power domain levels for this CPU to run. + */ + psci_set_pwr_domains_to_run(end_pwrlvl); + + psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); +} + +/******************************************************************************* + * This function does generic and platform specific suspend to power down + * operations. + ******************************************************************************/ +static void psci_suspend_to_pwrdown_start(unsigned int end_pwrlvl, + const entry_point_info_t *ep, + const psci_power_state_t *state_info) +{ + unsigned int max_off_lvl = psci_find_max_off_lvl(state_info); + + PUBLISH_EVENT(psci_suspend_pwrdown_start); + + /* Save PSCI target power level for the suspend finisher handler */ + psci_set_suspend_pwrlvl(end_pwrlvl); + + /* + * Flush the target power level as it might be accessed on power up with + * Data cache disabled. + */ + psci_flush_cpu_data(psci_svc_cpu_data.target_pwrlvl); + + /* + * Call the cpu suspend handler registered by the Secure Payload + * Dispatcher to let it do any book-keeping. If the handler encounters an + * error, it's expected to assert within + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_suspend != NULL)) + psci_spd_pm->svc_suspend(max_off_lvl); + +#if !HW_ASSISTED_COHERENCY + /* + * Plat. management: Allow the platform to perform any early + * actions required to power down the CPU. This might be useful for + * HW_ASSISTED_COHERENCY = 0 platforms that can safely perform these + * actions with data caches enabled. + */ + if (psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early != NULL) + psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early(state_info); +#endif + + /* + * Store the re-entry information for the non-secure world. + */ + cm_init_my_context(ep); + +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Flush cache line so that even if CPU power down happens + * the timestamp update is reflected in memory. + */ + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_CFLUSH, + PMF_CACHE_MAINT); +#endif + + /* + * Arch. management. Initiate power down sequence. + * TODO : Introduce a mechanism to query the cache level to flush + * and the cpu-ops power down to perform from the platform. + */ + psci_do_pwrdown_sequence(max_off_lvl); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_CFLUSH, + PMF_NO_CACHE_MAINT); +#endif +} + +/******************************************************************************* + * Top level handler which is called when a cpu wants to suspend its execution. + * It is assumed that along with suspending the cpu power domain, power domains + * at higher levels until the target power level will be suspended as well. It + * coordinates with the platform to negotiate the target state for each of + * the power domain level till the target power domain level. It then performs + * generic, architectural, platform setup and state management required to + * suspend that power domain level and power domain levels below it. + * e.g. For a cpu that's to be suspended, it could mean programming the + * power controller whereas for a cluster that's to be suspended, it will call + * the platform specific code which will disable coherency at the interconnect + * level if the cpu is the last in the cluster and also the program the power + * controller. + * + * All the required parameter checks are performed at the beginning and after + * the state transition has been done, no further error is expected and it is + * not possible to undo any of the actions taken beyond that point. + ******************************************************************************/ +void psci_cpu_suspend_start(const entry_point_info_t *ep, + unsigned int end_pwrlvl, + psci_power_state_t *state_info, + unsigned int is_power_down_state) +{ + int skip_wfi = 0; + unsigned int idx = plat_my_core_pos(); + unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; + + /* + * This function must only be called on platforms where the + * CPU_SUSPEND platform hooks have been implemented. + */ + assert((psci_plat_pm_ops->pwr_domain_suspend != NULL) && + (psci_plat_pm_ops->pwr_domain_suspend_finish != NULL)); + + /* Get the parent nodes */ + psci_get_parent_pwr_domain_nodes(idx, end_pwrlvl, parent_nodes); + + /* + * This function acquires the lock corresponding to each power + * level so that by the time all locks are taken, the system topology + * is snapshot and state management can be done safely. + */ + psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); + + /* + * We check if there are any pending interrupts after the delay + * introduced by lock contention to increase the chances of early + * detection that a wake-up interrupt has fired. + */ + if (read_isr_el1() != 0U) { + skip_wfi = 1; + goto exit; + } + + /* + * This function is passed the requested state info and + * it returns the negotiated state info for each power level upto + * the end level specified. + */ + psci_do_state_coordination(end_pwrlvl, state_info); + +#if ENABLE_PSCI_STAT + /* Update the last cpu for each level till end_pwrlvl */ + psci_stats_update_pwr_down(end_pwrlvl, state_info); +#endif + + if (is_power_down_state != 0U) + psci_suspend_to_pwrdown_start(end_pwrlvl, ep, state_info); + + /* + * Plat. management: Allow the platform to perform the + * necessary actions to turn off this cpu e.g. set the + * platform defined mailbox with the psci entrypoint, + * program the power controller etc. + */ + psci_plat_pm_ops->pwr_domain_suspend(state_info); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_start(state_info); +#endif + +exit: + /* + * Release the locks corresponding to each power level in the + * reverse order to which they were acquired. + */ + psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); + + if (skip_wfi == 1) + return; + + if (is_power_down_state != 0U) { +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Update the timestamp with cache off. We assume this + * timestamp can only be read from the current CPU and the + * timestamp cache line will be flushed before return to + * normal world on wakeup. + */ + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + /* The function calls below must not return */ + if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi != NULL) + psci_plat_pm_ops->pwr_domain_pwr_down_wfi(state_info); + else + psci_power_down_wfi(); + } + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + /* + * We will reach here if only retention/standby states have been + * requested at multiple power levels. This means that the cpu + * context will be preserved. + */ + wfi(); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + /* + * After we wake up from context retaining suspend, call the + * context retaining suspend finisher. + */ + psci_suspend_to_standby_finisher(idx, end_pwrlvl); +} + +/******************************************************************************* + * The following functions finish an earlier suspend request. They + * are called by the common finisher routine in psci_common.c. The `state_info` + * is the psci_power_state from which this CPU has woken up from. + ******************************************************************************/ +void psci_cpu_suspend_finish(unsigned int cpu_idx, const psci_power_state_t *state_info) +{ + unsigned int counter_freq; + unsigned int max_off_lvl; + + /* Ensure we have been woken up from a suspended state */ + assert((psci_get_aff_info_state() == AFF_STATE_ON) && + (is_local_state_off( + state_info->pwr_domain_state[PSCI_CPU_PWR_LVL]) != 0)); + + /* + * Plat. management: Perform the platform specific actions + * before we change the state of the cpu e.g. enabling the + * gic or zeroing the mailbox register. If anything goes + * wrong then assert as there is no way to recover from this + * situation. + */ + psci_plat_pm_ops->pwr_domain_suspend_finish(state_info); + +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + /* Arch. management: Enable the data cache, stack memory maintenance. */ + psci_do_pwrup_cache_maintenance(); +#endif + + /* Re-init the cntfrq_el0 register */ + counter_freq = plat_get_syscnt_freq2(); + write_cntfrq_el0(counter_freq); + +#if ENABLE_PAUTH + /* Store APIAKey_EL1 key */ + set_cpu_data(apiakey[0], read_apiakeylo_el1()); + set_cpu_data(apiakey[1], read_apiakeyhi_el1()); +#endif /* ENABLE_PAUTH */ + + /* + * Call the cpu suspend finish handler registered by the Secure Payload + * Dispatcher to let it do any bookeeping. If the handler encounters an + * error, it's expected to assert within + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_suspend_finish != NULL)) { + max_off_lvl = psci_find_max_off_lvl(state_info); + assert(max_off_lvl != PSCI_INVALID_PWR_LVL); + psci_spd_pm->svc_suspend_finish(max_off_lvl); + } + + /* Invalidate the suspend level for the cpu */ + psci_set_suspend_pwrlvl(PSCI_INVALID_PWR_LVL); + + PUBLISH_EVENT(psci_suspend_pwrdown_finish); + + /* + * Generic management: Now we just need to retrieve the + * information that we had stashed away during the suspend + * call to set this cpu on its way. + */ + cm_prepare_el3_exit(NON_SECURE); +} diff --git a/arm-trusted-firmware/lib/psci/psci_system_off.c b/arm-trusted-firmware/lib/psci/psci_system_off.c new file mode 100644 index 0000000..002392c --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_system_off.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include "psci_private.h" + +void __dead2 psci_system_off(void) +{ + psci_print_power_domain_map(); + + assert(psci_plat_pm_ops->system_off != NULL); + + /* Notify the Secure Payload Dispatcher */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_system_off != NULL)) { + psci_spd_pm->svc_system_off(); + } + + console_flush(); + + /* Call the platform specific hook */ + psci_plat_pm_ops->system_off(); + + /* This function does not return. We should never get here */ +} + +void __dead2 psci_system_reset(void) +{ + psci_print_power_domain_map(); + + assert(psci_plat_pm_ops->system_reset != NULL); + + /* Notify the Secure Payload Dispatcher */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_system_reset != NULL)) { + psci_spd_pm->svc_system_reset(); + } + + console_flush(); + + /* Call the platform specific hook */ + psci_plat_pm_ops->system_reset(); + + /* This function does not return. We should never get here */ +} + +u_register_t psci_system_reset2(uint32_t reset_type, u_register_t cookie) +{ + unsigned int is_vendor; + + psci_print_power_domain_map(); + + assert(psci_plat_pm_ops->system_reset2 != NULL); + + is_vendor = (reset_type >> PSCI_RESET2_TYPE_VENDOR_SHIFT) & 1U; + if (is_vendor == 0U) { + /* + * Only WARM_RESET is allowed for architectural type resets. + */ + if (reset_type != PSCI_RESET2_SYSTEM_WARM_RESET) + return (u_register_t) PSCI_E_INVALID_PARAMS; + if ((psci_plat_pm_ops->write_mem_protect != NULL) && + (psci_plat_pm_ops->write_mem_protect(0) < 0)) { + return (u_register_t) PSCI_E_NOT_SUPPORTED; + } + } + + /* Notify the Secure Payload Dispatcher */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_system_reset != NULL)) { + psci_spd_pm->svc_system_reset(); + } + console_flush(); + + return (u_register_t) + psci_plat_pm_ops->system_reset2((int) is_vendor, reset_type, + cookie); +} diff --git a/arm-trusted-firmware/lib/romlib/Makefile b/arm-trusted-firmware/lib/romlib/Makefile new file mode 100644 index 0000000..2ff480b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh b/arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh new file mode 100755 index 0000000..1e3f73a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/init.s b/arm-trusted-firmware/lib/romlib/init.s new file mode 100644 index 0000000..7d97e4d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/jmptbl.i b/arm-trusted-firmware/lib/romlib/jmptbl.i new file mode 100644 index 0000000..33710f5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/romlib.ld.S b/arm-trusted-firmware/lib/romlib/romlib.ld.S new file mode 100644 index 0000000..2aac4ad --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/romlib_generator.py b/arm-trusted-firmware/lib/romlib/romlib_generator.py new file mode 100755 index 0000000..0682dd4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S new file mode 100644 index 0000000..a0f8456 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S new file mode 100644 index 0000000..d96ee94 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S new file mode 100644 index 0000000..a9b5f18 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S new file mode 100644 index 0000000..a9f0375 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S new file mode 100644 index 0000000..d306512 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S new file mode 100644 index 0000000..72b8ce5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/templates/wrapper.S b/arm-trusted-firmware/lib/romlib/templates/wrapper.S new file mode 100644 index 0000000..734a68a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S b/arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S new file mode 100644 index 0000000..ba9b11c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S b/arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S new file mode 100644 index 0000000..aced3d1 --- /dev/null +++ b/arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl semihosting_call + +func semihosting_call + svc #0x123456 + bx lr +endfunc semihosting_call diff --git a/arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S b/arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S new file mode 100644 index 0000000..97d2bca --- /dev/null +++ b/arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl semihosting_call + +func semihosting_call + hlt #0xf000 + ret +endfunc semihosting_call diff --git a/arm-trusted-firmware/lib/semihosting/semihosting.c b/arm-trusted-firmware/lib/semihosting/semihosting.c new file mode 100644 index 0000000..e0845c1 --- /dev/null +++ b/arm-trusted-firmware/lib/semihosting/semihosting.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#ifndef SEMIHOSTING_SUPPORTED +#define SEMIHOSTING_SUPPORTED 1 +#endif + +long semihosting_call(unsigned long operation, uintptr_t system_block_address); + +typedef struct { + const char *file_name; + unsigned long mode; + size_t name_length; +} smh_file_open_block_t; + +typedef struct { + long handle; + uintptr_t buffer; + size_t length; +} smh_file_read_write_block_t; + +typedef struct { + long handle; + ssize_t location; +} smh_file_seek_block_t; + +typedef struct { + char *command_line; + size_t command_length; +} smh_system_block_t; + +long semihosting_connection_supported(void) +{ + return SEMIHOSTING_SUPPORTED; +} + +long semihosting_file_open(const char *file_name, size_t mode) +{ + smh_file_open_block_t open_block; + + open_block.file_name = file_name; + open_block.mode = mode; + open_block.name_length = strlen(file_name); + + return semihosting_call(SEMIHOSTING_SYS_OPEN, (uintptr_t)&open_block); +} + +long semihosting_file_seek(long file_handle, ssize_t offset) +{ + smh_file_seek_block_t seek_block; + long result; + + seek_block.handle = file_handle; + seek_block.location = offset; + + result = semihosting_call(SEMIHOSTING_SYS_SEEK, (uintptr_t)&seek_block); + + if (result != 0) { + result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0); + } + + return result; +} + +long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer) +{ + smh_file_read_write_block_t read_block; + long result = -EINVAL; + + if ((length == NULL) || (buffer == (uintptr_t)NULL)) { + return result; + } + + read_block.handle = file_handle; + read_block.buffer = buffer; + read_block.length = *length; + + result = semihosting_call(SEMIHOSTING_SYS_READ, (uintptr_t)&read_block); + + if (result == *length) { + return -EINVAL; + } else if (result < *length) { + *length -= result; + return 0; + } else { + return result; + } +} + +long semihosting_file_write(long file_handle, size_t *length, + const uintptr_t buffer) +{ + smh_file_read_write_block_t write_block; + long result = -EINVAL; + + if ((length == NULL) || (buffer == (uintptr_t)NULL)) { + return -EINVAL; + } + + write_block.handle = file_handle; + write_block.buffer = (uintptr_t)buffer; /* cast away const */ + write_block.length = *length; + + result = semihosting_call(SEMIHOSTING_SYS_WRITE, + (uintptr_t)&write_block); + + *length = result; + + return (result == 0) ? 0 : -EINVAL; +} + +long semihosting_file_close(long file_handle) +{ + return semihosting_call(SEMIHOSTING_SYS_CLOSE, (uintptr_t)&file_handle); +} + +long semihosting_file_length(long file_handle) +{ + return semihosting_call(SEMIHOSTING_SYS_FLEN, (uintptr_t)&file_handle); +} + +char semihosting_read_char(void) +{ + return semihosting_call(SEMIHOSTING_SYS_READC, 0); +} + +void semihosting_write_char(char character) +{ + semihosting_call(SEMIHOSTING_SYS_WRITEC, (uintptr_t)&character); +} + +void semihosting_write_string(char *string) +{ + semihosting_call(SEMIHOSTING_SYS_WRITE0, (uintptr_t)string); +} + +long semihosting_system(char *command_line) +{ + smh_system_block_t system_block; + + system_block.command_line = command_line; + system_block.command_length = strlen(command_line); + + return semihosting_call(SEMIHOSTING_SYS_SYSTEM, + (uintptr_t)&system_block); +} + +long semihosting_get_flen(const char *file_name) +{ + long file_handle; + long length; + + assert(semihosting_connection_supported() != 0); + + file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB); + if (file_handle == -1) { + return file_handle; + } + + /* Find the length of the file */ + length = semihosting_file_length(file_handle); + + return (semihosting_file_close(file_handle) != 0) ? -1 : length; +} + +long semihosting_download_file(const char *file_name, + size_t buf_size, + uintptr_t buf) +{ + long ret = -EINVAL; + size_t length; + long file_handle; + + /* Null pointer check */ + if (buf == 0U) { + return ret; + } + + assert(semihosting_connection_supported() != 0); + + file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB); + if (file_handle == -1) { + return ret; + } + + /* Find the actual length of the file */ + length = semihosting_file_length(file_handle); + if (length == (size_t)(-1)) { + goto semihosting_fail; + } + + /* Signal error if we do not have enough space for the file */ + if (length > buf_size) { + goto semihosting_fail; + } + + /* + * A successful read will return 0 in which case we pass back + * the actual number of bytes read. Else we pass a negative + * value indicating an error. + */ + ret = semihosting_file_read(file_handle, &length, buf); + if (ret != 0) { + goto semihosting_fail; + } else { + ret = (long)length; + } + +semihosting_fail: + semihosting_file_close(file_handle); + return ret; +} + +void semihosting_exit(uint32_t reason, uint32_t subcode) +{ +#ifdef __aarch64__ + uint64_t parameters[] = {reason, subcode}; + + (void)semihosting_call(SEMIHOSTING_SYS_EXIT, (uintptr_t)¶meters); +#else + /* The subcode is not supported on AArch32. */ + (void)semihosting_call(SEMIHOSTING_SYS_EXIT, reason); +#endif +} diff --git a/arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S b/arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S new file mode 100644 index 0000000..19b7525 --- /dev/null +++ b/arm-trusted-firmware/lib/stack_protector/aarch32/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 r4 as it is callee-saved */ + mov r4, lr + bl plat_get_stack_protector_canary + + /* Update the canary with the returned value */ + ldr r1, =__stack_chk_guard + str r0, [r1] + bx r4 +endfunc update_stack_protector_canary + + diff --git a/arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S b/arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S new file mode 100644 index 0000000..c2245d3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/stack_protector/stack_protector.c b/arm-trusted-firmware/lib/stack_protector/stack_protector.c new file mode 100644 index 0000000..3ff74fc --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/stack_protector/stack_protector.mk b/arm-trusted-firmware/lib/stack_protector/stack_protector.mk new file mode 100644 index 0000000..b5aba15 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/utils/mem_region.c b/arm-trusted-firmware/lib/utils/mem_region.c new file mode 100644 index 0000000..fec086b --- /dev/null +++ b/arm-trusted-firmware/lib/utils/mem_region.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/* + * All the regions defined in mem_region_t must have the following properties + * + * - Any contiguous regions must be merged into a single entry. + * - The number of bytes of each region must be greater than zero. + * - The calculation of the highest address within the region (base + nbytes-1) + * doesn't produce an overflow. + * + * These conditions must be fulfilled by the caller and they aren't checked + * at runtime. + */ + +/* + * zero_normalmem all the regions defined in tbl. + * It assumes that MMU is enabled and the memory is Normal memory. + * tbl must be a valid pointer to a memory mem_region_t array, + * nregions is the size of the array. + */ +void clear_mem_regions(mem_region_t *tbl, size_t nregions) +{ + size_t i; + + assert(tbl != NULL); + assert(nregions > 0U); + + for (i = 0; i < nregions; i++) { + assert(tbl->nbytes > 0); + assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); + zero_normalmem((void *) (tbl->base), tbl->nbytes); + tbl++; + } +} + +#if defined(PLAT_XLAT_TABLES_DYNAMIC) +/* + * zero_normalmem all the regions defined in regions. + * It assumes that MMU is enabled and the memory is Normal memory. + * regions must be a valid pointer to a memory mem_region_t array, + * nregions is the size of the array. va is the virtual address + * where we want to map the physical pages that are going to + * be cleared, and chunk is the amount of memory mapped and + * cleared in every iteration. + */ +void clear_map_dyn_mem_regions(struct mem_region *regions, + size_t nregions, + uintptr_t va, + size_t chunk) +{ + uintptr_t begin; + int r; + size_t size; + const unsigned int attr = MT_MEMORY | MT_RW | MT_NS; + + assert(regions != NULL); + assert(nregions != 0U); + assert(chunk != 0U); + + for (unsigned int i = 0U; i < nregions; i++) { + begin = regions[i].base; + size = regions[i].nbytes; + if (((begin & (chunk-1U)) != 0U) || + ((size & (chunk-1U)) != 0U)) { + INFO("PSCI: Not correctly aligned region\n"); + panic(); + } + + while (size > 0U) { + r = mmap_add_dynamic_region(begin, va, chunk, attr); + if (r != 0) { + INFO("PSCI: %s failed with %d\n", + "mmap_add_dynamic_region", r); + panic(); + } + + zero_normalmem((void *)va, chunk); + + r = mmap_remove_dynamic_region(va, chunk); + if (r != 0) { + INFO("PSCI: %s failed with %d\n", + "mmap_remove_dynamic_region", r); + panic(); + } + + begin += chunk; + size -= chunk; + } + } +} +#endif + +/* + * This function checks that a region (addr + nbytes-1) of memory is totally + * covered by one of the regions defined in tbl. + * tbl must be a valid pointer to a memory mem_region_t array, nregions + * is the size of the array and the region described by addr and nbytes must + * not generate an overflow. + * Returns: + * -1 means that the region is not covered by any of the regions + * described in tbl. + * 0 the region (addr + nbytes-1) is covered by one of the regions described + * in tbl + */ +int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions, + uintptr_t addr, size_t nbytes) +{ + uintptr_t region_start, region_end, start, end; + size_t i; + + assert(tbl != NULL); + assert(nbytes != 0U); + assert(!check_uptr_overflow(addr, nbytes-1)); + + region_start = addr; + region_end = addr + (nbytes - 1U); + for (i = 0U; i < nregions; i++) { + assert(tbl->nbytes > 0); + assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); + start = tbl->base; + end = start + (tbl->nbytes - 1); + if ((region_start >= start) && (region_end <= end)) { + return 0; + } + tbl++; + } + + return -1; +} diff --git a/arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S b/arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S new file mode 100644 index 0000000..3791f2d --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .global enable_mpu_direct_el2 + + /* void enable_mmu_direct_el2(unsigned int flags) */ +func enable_mpu_direct_el2 +#if ENABLE_ASSERTIONS + mrs x1, sctlr_el2 + tst x1, #SCTLR_M_BIT + ASM_ASSERT(eq) +#endif + mov x7, x0 + adrp x0, mmu_cfg_params + add x0, x0, :lo12:mmu_cfg_params + + /* (MAIRs are already set up) */ + + /* TCR */ + ldr x2, [x0, #(MMU_CFG_TCR << 3)] + msr tcr_el2, x2 + + /* + * 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_el2 + 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_el2, x4 + isb + + ret +endfunc enable_mpu_direct_el2 diff --git a/arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c b/arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c new file mode 100644 index 0000000..5068eb8 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "../xlat_mpu_private.h" +#include +#include +#include +#include +#include + +#include + +#warning "xlat_mpu library is currently experimental and its API may change in future." + +#if ENABLE_ASSERTIONS +/* + * 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_mpu_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 { + assert(xlat_arch_current_el() >= 2U); + return (read_sctlr_el2() & SCTLR_M_BIT) != 0U; + } +} + +bool is_dcache_enabled(void) +{ + unsigned int el = get_current_el(); + + if (el == 1U) { + return (read_sctlr_el1() & SCTLR_C_BIT) != 0U; + } else { /* must be EL2 */ + return (read_sctlr_el2() & SCTLR_C_BIT) != 0U; + } +} + +unsigned int xlat_arch_current_el(void) +{ + unsigned int el = (unsigned int)GET_EL(read_CurrentEl()); + + assert(el > 0U); + + return el; +} + diff --git a/arm-trusted-firmware/lib/xlat_mpu/ro_xlat_mpu.mk b/arm-trusted-firmware/lib/xlat_mpu/ro_xlat_mpu.mk new file mode 100644 index 0000000..23f1d46 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/ro_xlat_mpu.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2021, 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) + $(error "The xlat_mpu library does not currently support AArch32.") +endif diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu.mk b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu.mk new file mode 100644 index 0000000..041b91c --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +XLAT_MPU_LIB_V1_SRCS := $(addprefix lib/xlat_mpu/, \ + ${ARCH}/enable_mpu.S \ + ${ARCH}/xlat_mpu_arch.c \ + xlat_mpu_context.c \ + xlat_mpu_core.c \ + xlat_mpu_utils.c) + +XLAT_MPU_LIB_V1 := 1 +$(eval $(call add_define,XLAT_MPU_LIB_V1)) + +ifeq (${ALLOW_XLAT_MPU}, 1) + include lib/xlat_mpu_v2/ro_xlat_mpu.mk +endif diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c new file mode 100644 index 0000000..28c463b --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "lib/xlat_mpu/xlat_mpu.h" +#include +#include +#include "xlat_mpu_private.h" + +#include +#include + +#warning "xlat_mpu library is currently experimental and its API may change in future." + + +/* + * 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(const mmap_region_t *mm) +{ + mmap_add_ctx(&tf_xlat_ctx, mm); +} + +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 { + assert(current_el == 2U); + tf_xlat_ctx.xlat_regime = EL2_REGIME; + } + /* Note: If EL3 is supported in future v8-R64, add EL3 assignment */ + 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); +} + +void enable_mpu_el2(unsigned int flags) +{ + /* EL2 is strictly MPU on v8-R64, so no need for setup_mpu_cfg() */ + enable_mpu_direct_el2(flags); +} diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c new file mode 100644 index 0000000..6b4b0c2 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 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 "xlat_mpu_private.h" + +#include +#include + +#warning "xlat_mpu library is currently experimental and its API may change in future." + + +/* 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); + } +} + + + +/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */ +uint64_t prbar_attr_value(uint32_t attr) +{ + uint64_t retValue = UL(0); + uint64_t extract; /* temp var holding bit extracted from attr */ + + /* Extract and stuff SH: */ + extract = (uint64_t) ((attr >> MT_SHAREABILITY_SHIFT) + & MT_SHAREABILITY_MASK); + retValue |= (extract << PRBAR_SH_SHIFT); + + /* Extract and stuff AP: */ + extract = (uint64_t) ((attr >> MT_PERM_SHIFT) & MT_PERM_MASK); + if (extract == 0U) { + retValue |= (UL(2) << PRBAR_AP_SHIFT); + } else /* extract == 1 */ { + retValue |= (UL(0) << PRBAR_AP_SHIFT); + } + + /* Extract and stuff XN: */ + extract = (uint64_t) ((attr >> MT_EXECUTE_SHIFT) & MT_EXECUTE_MASK); + retValue |= (extract << PRBAR_XN_SHIFT); + /* However, also don't execute in peripheral space: */ + extract = (uint64_t) ((attr >> MT_TYPE_SHIFT) & MT_TYPE_MASK); + if (extract == 0U) { + retValue |= (UL(1) << PRBAR_XN_SHIFT); + } + return retValue; +} + +/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */ +uint64_t prlar_attr_value(uint32_t attr) +{ + uint64_t retValue = UL(0); + uint64_t extract; /* temp var holding bit extracted from attr */ + + /* Extract and stuff AttrIndx: */ + extract = (uint64_t) ((attr >> MT_TYPE_SHIFT) + & MT_TYPE_MASK); + switch (extract) { + case UL(0): + retValue |= (UL(1) << PRLAR_ATTR_SHIFT); + break; + case UL(2): + /* 0, so OR in nothing */ + break; + case UL(3): + retValue |= (UL(2) << PRLAR_ATTR_SHIFT); + break; + default: + retValue |= (extract << PRLAR_ATTR_SHIFT); + break; + } + + /* Stuff EN: */ + retValue |= (UL(1) << PRLAR_EN_SHIFT); + + /* Force NS to 0 (Secure); v8-R64 only supports Secure: */ + extract = ~(1U << PRLAR_NS_SHIFT); + retValue &= extract; + + return retValue; +} + +/* + * Function that writes an MPU "translation" into the MPU registers. If not + * possible (e.g., if no more MPU regions available) boot is aborted. + */ +static void mpu_map_region(mmap_region_t *mm) +{ + uint64_t prenr_el2_value = 0UL; + uint64_t prbar_attrs = 0UL; + uint64_t prlar_attrs = 0UL; + int region_to_use = 0; + + /* If all MPU regions in use, then abort boot: */ + prenr_el2_value = read_prenr_el2(); + assert(prenr_el2_value != 0xffffffff); + + /* Find and select first-available MPU region (PRENR has an enable bit + * for each MPU region, 1 for in-use or 0 for unused): + */ + for (region_to_use = 0; region_to_use < N_MPU_REGIONS; + region_to_use++) { + if (((prenr_el2_value >> region_to_use) & 1) == 0) { + break; + } + } + write_prselr_el2((uint64_t) (region_to_use)); + isb(); + + /* Set base and limit addresses: */ + write_prbar_el2(mm->base_pa & PRBAR_PRLAR_ADDR_MASK); + write_prlar_el2((mm->base_pa + mm->size - 1UL) + & PRBAR_PRLAR_ADDR_MASK); + dsbsy(); + isb(); + + /* Set attributes: */ + prbar_attrs = prbar_attr_value(mm->attr); + write_prbar_el2(read_prbar_el2() | prbar_attrs); + prlar_attrs = prlar_attr_value(mm->attr); + write_prlar_el2(read_prlar_el2() | prlar_attrs); + dsbsy(); + isb(); + + /* Mark this MPU region as used: */ + prenr_el2_value |= (1 << region_to_use); + write_prenr_el2(prenr_el2_value); + isb(); +} + +/* + * 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; + + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + if (base_pa != base_va) { + return -EINVAL; /* MPU does not perform address translation */ + } + if ((base_pa % 64ULL) != 0ULL) { + return -EINVAL; /* MPU requires 64-byte alignment */ + } + /* Check for overflows */ + if ((base_pa > end_pa) || (base_va > end_va)) { + 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 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; + } +} + +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++; + } +} + +void __init init_xlat_tables_ctx(xlat_ctx_t *ctx) +{ + uint64_t mair = UL(0); + + assert(ctx != NULL); + assert(!ctx->initialized); + assert((ctx->xlat_regime == EL2_REGIME) || + (ctx->xlat_regime == EL1_EL0_REGIME)); + /* Note: Add EL3_REGIME if EL3 is supported in future v8-R64 cores. */ + assert(!is_mpu_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; + + /* Also mark all MPU regions as invalid in the MPU hardware itself: */ + write_prenr_el2(0); + /* Sufficient for current, max-32-region implementations. */ + dsbsy(); + isb(); + while (mm->size != 0U) { + if (read_prenr_el2() == ALL_MPU_EL2_REGIONS_USED) { + ERROR("Not enough MPU regions 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(); + } else { +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)mm->base_va, + mm->size); +#endif + mpu_map_region(mm); + } + mm++; + } + + ctx->initialized = true; + + xlat_tables_print(ctx); + + /* 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); + write_mair_el2(mair); + dsbsy(); + isb(); +} + +/* + * Function to wipe clean and disable all MPU regions. This function expects + * that the MPU has already been turned off, and caching concerns addressed, + * but it nevertheless also explicitly turns off the MPU. + */ +void clear_all_mpu_regions(void) +{ + uint64_t sctlr_el2_value = 0UL; + uint64_t region_n = 0UL; + + /* + * MPU should already be disabled, but explicitly disable it + * nevertheless: + */ + sctlr_el2_value = read_sctlr_el2() & ~(1UL); + write_sctlr_el2(sctlr_el2_value); + + /* Disable all regions: */ + write_prenr_el2(0UL); + + /* Sequence through all regions, zeroing them out and turning off: */ + for (region_n = 0UL; region_n < N_MPU_REGIONS; region_n++) { + write_prselr_el2(region_n); + isb(); + write_prbar_el2((uint64_t) 0); + write_prlar_el2((uint64_t) 0); + dsbsy(); + isb(); + } +} diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h new file mode 100644 index 0000000..e0e479d --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_MPU_PRIVATE_H +#define XLAT_MPU_PRIVATE_H + +#include + +#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. + */ + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */ +uint64_t prbar_attr_value(uint32_t attr); +/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */ +uint64_t prlar_attr_value(uint32_t attr); +/* Calculates the attr value for a given PRBAR and PRLAR entry value: */ +uint32_t region_attr(uint64_t prbar_attr, uint64_t prlar_attr); + +#define PRBAR_PRLAR_ADDR_MASK UL(0xffffffffffc0) + /* mask for PRBAR & PRLAR MPU-region field */ +/* MPU region attribute bit fields: */ +#define PRBAR_SH_SHIFT UL(4) +#define PRBAR_SH_MASK UL(0x3) +#define PRBAR_AP_SHIFT UL(2) +#define PRBAR_AP_MASK UL(0x3) +#define PRBAR_XN_SHIFT UL(1) +#define PRBAR_XN_MASK UL(0x3) +#define PRLAR_NS_SHIFT UL(4) +#define PRLAR_NS_MASK UL(0x3) +#define PRBAR_ATTR_SHIFT UL(0) +#define PRBAR_ATTR_MASK UL(0x3f) +#define PRLAR_ATTR_SHIFT UL(1) +#define PRLAR_ATTR_MASK UL(0x7) +#define PRLAR_EN_SHIFT UL(0) +#define PRLAR_EN_MASK UL(0x1) +/* Aspects of the source attributes not defined elsewhere: */ +#define MT_PERM_MASK UL(0x1) +#define MT_SEC_MASK UL(0x1) +#define MT_EXECUTE_MASK UL(0x3) +#define MT_TYPE_SHIFT UL(0) + +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); + +/* 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); + +/* + * Returns true if the MMU of the translation regime managed by the given + * xlat_ctx_t is enabled, false otherwise. + */ +bool is_mpu_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_MPU_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c new file mode 100644 index 0000000..5400875 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "xlat_mpu_private.h" + +#include +#include + +#warning "xlat_mpu library is currently experimental and its API may change in future." + + +void xlat_mmap_print(__unused const mmap_region_t *mmap) +{ + /* Empty */ +} + +#if LOG_LEVEL < LOG_LEVEL_VERBOSE + +void xlat_tables_print(__unused xlat_ctx_t *ctx) +{ + /* Empty */ +} + +#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */ + +static void xlat_tables_print_internal(__unused xlat_ctx_t *ctx) +{ + int region_to_use = 0; + uintptr_t region_base; + size_t region_size; + uint64_t prenr_el2_value = 0U; + + /* + * 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. + */ + + /* + * TODO: Remove this WARN() and comment when these API calls are more + * completely implemented and tested! + */ + WARN("%s in this early version of xlat_mpu library may not produce reliable results!", + __func__); + + /* + * Sequence through all regions and print those in-use (PRENR has an + * enable bit for each MPU region, 1 for in-use or 0 for unused): + */ + prenr_el2_value = read_prenr_el2(); + for (region_to_use = 0; region_to_use < N_MPU_REGIONS; + region_to_use++) { + if (((prenr_el2_value >> region_to_use) & 1U) == 0U) { + continue; + } + region_base = read_prbar_el2() & PRBAR_PRLAR_ADDR_MASK; + region_size = read_prlar_el2() & PRBAR_PRLAR_ADDR_MASK; + printf("Address: 0x%llx, size: 0x%llx ", + (long long) region_base, + (long long) region_size); + } +} + +void xlat_tables_print(__unused xlat_ctx_t *ctx) +{ + xlat_tables_print_internal(ctx); +} + +#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */ diff --git a/arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c b/arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c new file mode 100644 index 0000000..7cd509d --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2016-2017, Linaro Limited. All rights reserved. + * Copyright (c) 2014-2020, Arm Limited. All rights reserved. + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "../xlat_tables_private.h" + +#ifdef ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +#error "ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING flag is set. \ +This module is to be used when LPAE is not supported" +#endif + +CASSERT(PLAT_VIRT_ADDR_SPACE_SIZE == (1ULL << 32), invalid_vaddr_space_size); +CASSERT(PLAT_PHY_ADDR_SPACE_SIZE == (1ULL << 32), invalid_paddr_space_size); + +#define MMU32B_UNSET_DESC ~0UL +#define MMU32B_INVALID_DESC 0UL + +#define MT_UNKNOWN ~0U + +/* + * MMU related values + */ + +/* Sharable */ +#define MMU32B_TTB_S (1U << 1) + +/* Not Outer Sharable */ +#define MMU32B_TTB_NOS (1U << 5) + +/* Normal memory, Inner Non-cacheable */ +#define MMU32B_TTB_IRGN_NC 0U + +/* Normal memory, Inner Write-Back Write-Allocate Cacheable */ +#define MMU32B_TTB_IRGN_WBWA (1U << 6) + +/* Normal memory, Inner Write-Through Cacheable */ +#define MMU32B_TTB_IRGN_WT 1U + +/* Normal memory, Inner Write-Back no Write-Allocate Cacheable */ +#define MMU32B_TTB_IRGN_WB (1U | (1U << 6)) + +/* Normal memory, Outer Write-Back Write-Allocate Cacheable */ +#define MMU32B_TTB_RNG_WBWA (1U << 3) + +#define MMU32B_DEFAULT_ATTRS \ + (MMU32B_TTB_S | MMU32B_TTB_NOS | \ + MMU32B_TTB_IRGN_WBWA | MMU32B_TTB_RNG_WBWA) + +/* armv7 memory mapping attributes: section mapping */ +#define SECTION_SECURE (0U << 19) +#define SECTION_NOTSECURE (1U << 19) +#define SECTION_SHARED (1U << 16) +#define SECTION_NOTGLOBAL (1U << 17) +#define SECTION_ACCESS_FLAG (1U << 10) +#define SECTION_UNPRIV (1U << 11) +#define SECTION_RO (1U << 15) +#define SECTION_TEX(tex) ((((tex) >> 2) << 12) | \ + ((((tex) >> 1) & 0x1) << 3) | \ + (((tex) & 0x1) << 2)) +#define SECTION_DEVICE SECTION_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SECTION_NORMAL SECTION_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SECTION_NORMAL_CACHED \ + SECTION_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX) + +#define SECTION_XN (1U << 4) +#define SECTION_PXN (1U << 0) +#define SECTION_SECTION (2U << 0) + +#define SECTION_PT_NOTSECURE (1U << 3) +#define SECTION_PT_PT (1U << 0) + +#define SMALL_PAGE_SMALL_PAGE (1U << 1) +#define SMALL_PAGE_SHARED (1U << 10) +#define SMALL_PAGE_NOTGLOBAL (1U << 11) +#define SMALL_PAGE_TEX(tex) ((((tex) >> 2) << 6) | \ + ((((tex) >> 1) & 0x1) << 3) | \ + (((tex) & 0x1) << 2)) +#define SMALL_PAGE_DEVICE \ + SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SMALL_PAGE_NORMAL \ + SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SMALL_PAGE_NORMAL_CACHED \ + SMALL_PAGE_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX) +#define SMALL_PAGE_ACCESS_FLAG (1U << 4) +#define SMALL_PAGE_UNPRIV (1U << 5) +#define SMALL_PAGE_RO (1U << 9) +#define SMALL_PAGE_XN (1U << 0) + +/* The TEX, C and B bits concatenated */ +#define MMU32B_ATTR_DEVICE_INDEX 0U +#define MMU32B_ATTR_IWBWA_OWBWA_INDEX 1U + +#define MMU32B_PRRR_IDX(idx, tr, nos) (((tr) << (2 * (idx))) | \ + ((uint32_t)(nos) << ((idx) + 24))) +#define MMU32B_NMRR_IDX(idx, ir, or) (((ir) << (2 * (idx))) | \ + ((uint32_t)(or) << (2 * (idx) + 16))) +#define MMU32B_PRRR_DS0 (1U << 16) +#define MMU32B_PRRR_DS1 (1U << 17) +#define MMU32B_PRRR_NS0 (1U << 18) +#define MMU32B_PRRR_NS1 (1U << 19) + +#define DACR_DOMAIN(num, perm) ((perm) << ((num) * 2)) +#define DACR_DOMAIN_PERM_NO_ACCESS 0U +#define DACR_DOMAIN_PERM_CLIENT 1U +#define DACR_DOMAIN_PERM_MANAGER 3U + +#define NUM_1MB_IN_4GB (1UL << 12) +#define NUM_4K_IN_1MB (1UL << 8) + +#define ONE_MB_SHIFT 20 + +/* mmu 32b integration */ +#define MMU32B_L1_TABLE_SIZE (NUM_1MB_IN_4GB * 4) +#define MMU32B_L2_TABLE_SIZE (NUM_4K_IN_1MB * 4) +#define MMU32B_L1_TABLE_ALIGN (1U << 14) +#define MMU32B_L2_TABLE_ALIGN (1U << 10) + +static unsigned int next_xlat; +static unsigned long long xlat_max_pa; +static uintptr_t xlat_max_va; + +static uint32_t mmu_l1_base[NUM_1MB_IN_4GB] + __aligned(MMU32B_L1_TABLE_ALIGN) __attribute__((section("xlat_table"))); + +static uint32_t mmu_l2_base[MAX_XLAT_TABLES][NUM_4K_IN_1MB] + __aligned(MMU32B_L2_TABLE_ALIGN) __attribute__((section("xlat_table"))); + +/* + * Array of all memory regions stored in order of ascending base address. + * The list is terminated by the first entry with size == 0. + */ +static mmap_region_t mmap[MAX_MMAP_REGIONS + 1]; + +void print_mmap(void) +{ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + mmap_region_t *mm = mmap; + + printf("init xlat - l1:%p l2:%p (%d)\n", + (void *)mmu_l1_base, (void *)mmu_l2_base, MAX_XLAT_TABLES); + printf("mmap:\n"); + while (mm->size) { + printf(" VA:%p PA:0x%llx size:0x%zx attr:0x%x\n", + (void *)mm->base_va, mm->base_pa, + mm->size, mm->attr); + ++mm; + }; + printf("\n"); +#endif +} + +void mmap_add(const mmap_region_t *mm) +{ + const mmap_region_t *mm_cursor = mm; + + while ((mm_cursor->size != 0U) || (mm_cursor->attr != 0U)) { + mmap_add_region(mm_cursor->base_pa, mm_cursor->base_va, + mm_cursor->size, mm_cursor->attr); + mm_cursor++; + } +} + +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr) +{ + mmap_region_t *mm = mmap; + const mmap_region_t *mm_last = mm + ARRAY_SIZE(mmap) - 1U; + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + assert(IS_PAGE_ALIGNED(base_pa)); + assert(IS_PAGE_ALIGNED(base_va)); + assert(IS_PAGE_ALIGNED(size)); + + if (size == 0U) { + return; + } + + assert(base_pa < end_pa); /* Check for overflows */ + assert(base_va < end_va); + + assert((base_va + (uintptr_t)size - (uintptr_t)1) <= + (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert((base_pa + (unsigned long long)size - 1ULL) <= + (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + +#if ENABLE_ASSERTIONS + + /* Check for PAs and VAs overlaps with all other regions */ + for (mm = mmap; mm->size; ++mm) { + + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + + /* + * Check if one of the regions is completely inside the other + * one. + */ + bool fully_overlapped_va = + ((base_va >= mm->base_va) && (end_va <= mm_end_va)) || + ((mm->base_va >= base_va) && (mm_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. + */ + if (fully_overlapped_va) { + assert((mm->base_va - mm->base_pa) == + (base_va - base_pa)); + assert((base_va != mm->base_va) || (size != mm->size)); + } 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_end_pa = + mm->base_pa + mm->size - 1; + + bool separated_pa = (end_pa < mm->base_pa) || + (base_pa > mm_end_pa); + bool separated_va = (end_va < mm->base_va) || + (base_va > mm_end_va); + + assert(separated_va && separated_pa); + } + } + + mm = mmap; /* Restore pointer to the start of the array */ + +#endif /* ENABLE_ASSERTIONS */ + + /* Find correct place in mmap to insert new region */ + while ((mm->base_va < base_va) && (mm->size != 0U)) { + ++mm; + } + + /* + * If a section is contained inside another one with the same base + * address, it must be placed after the one it is contained in: + * + * 1st |-----------------------| + * 2nd |------------| + * 3rd |------| + * + * This is required for mmap_region_attr() to get the attributes of the + * small region correctly. + */ + while ((mm->base_va == base_va) && (mm->size > size)) { + ++mm; + } + + /* Make room for new region by moving other regions up by one place */ + (void)memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm); + + /* Check we haven't lost the empty sentinal from the end of the array */ + assert(mm_last->size == 0U); + + mm->base_pa = base_pa; + mm->base_va = base_va; + mm->size = size; + mm->attr = attr; + + if (end_pa > xlat_max_pa) { + xlat_max_pa = end_pa; + } + if (end_va > xlat_max_va) { + xlat_max_va = end_va; + } +} + +/* map all memory as shared/global/domain0/no-usr access */ +static uint32_t mmap_desc(unsigned attr, unsigned int addr_pa, + unsigned int level) +{ + uint32_t desc; + + switch (level) { + case 1U: + assert((addr_pa & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U); + + desc = SECTION_SECTION | SECTION_SHARED; + + desc |= (attr & MT_NS) != 0U ? SECTION_NOTSECURE : 0U; + + desc |= SECTION_ACCESS_FLAG; + desc |= (attr & MT_RW) != 0U ? 0U : SECTION_RO; + + desc |= (attr & MT_MEMORY) != 0U ? + SECTION_NORMAL_CACHED : SECTION_DEVICE; + + if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) { + desc |= SECTION_XN; + } + break; + case 2U: + assert((addr_pa & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U); + + desc = SMALL_PAGE_SMALL_PAGE | SMALL_PAGE_SHARED; + + desc |= SMALL_PAGE_ACCESS_FLAG; + desc |= (attr & MT_RW) != 0U ? 0U : SMALL_PAGE_RO; + + desc |= (attr & MT_MEMORY) != 0U ? + SMALL_PAGE_NORMAL_CACHED : SMALL_PAGE_DEVICE; + + if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) { + desc |= SMALL_PAGE_XN; + } + break; + default: + panic(); + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only the non-lpae level 2 tables */ + if (level == 2U) { + printf(attr & MT_MEMORY ? "MEM" : "dev"); + printf(attr & MT_RW ? "-rw" : "-RO"); + printf(attr & MT_NS ? "-NS" : "-S"); + } +#endif + return desc | addr_pa; +} + +static unsigned int mmap_region_attr(const mmap_region_t *mm, uintptr_t base_va, + size_t size, unsigned int *attr) +{ + /* Don't assume that the area is contained in the first region */ + unsigned int ret = MT_UNKNOWN; + + /* + * Get attributes from last (innermost) region that contains the + * requested area. Don't stop as soon as one region doesn't contain it + * because there may be other internal regions that contain this area: + * + * |-----------------------------1-----------------------------| + * |----2----| |-------3-------| |----5----| + * |--4--| + * + * |---| <- Area we want the attributes of. + * + * In this example, the area is contained in regions 1, 3 and 4 but not + * in region 2. The loop shouldn't stop at region 2 as inner regions + * have priority over outer regions, it should stop at region 5. + */ + for ( ; ; ++mm) { + + if (mm->size == 0U) { + return ret; /* Reached end of list */ + } + + if (mm->base_va > (base_va + size - 1U)) { + return ret; /* Next region is after area so end */ + } + + if ((mm->base_va + mm->size - 1U) < base_va) { + continue; /* Next region has already been overtaken */ + } + + if ((ret == 0U) && (mm->attr == *attr)) { + continue; /* Region doesn't override attribs so skip */ + } + + if ((mm->base_va > base_va) || + ((mm->base_va + mm->size - 1U) < + (base_va + size - 1U))) { + return MT_UNKNOWN; /* Region doesn't fully cover area */ + } + + *attr = mm->attr; + ret = 0U; + } +} + +static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm, + unsigned int base_va, + uint32_t *table, + unsigned int level) +{ + unsigned int level_size_shift = (level == 1U) ? + ONE_MB_SHIFT : FOUR_KB_SHIFT; + unsigned int level_size = 1U << level_size_shift; + unsigned int level_index_mask = (level == 1U) ? + (NUM_1MB_IN_4GB - 1) << ONE_MB_SHIFT : + (NUM_4K_IN_1MB - 1) << FOUR_KB_SHIFT; + + assert((level == 1U) || (level == 2U)); + + VERBOSE("init xlat table at %p (level%1u)\n", (void *)table, level); + + do { + uint32_t desc = MMU32B_UNSET_DESC; + + if (mm->base_va + mm->size <= base_va) { + /* Area now after the region so skip it */ + ++mm; + continue; + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only non-lpae level 2 tables content */ + if (level == 2U) { + printf(" 0x%lx %x " + 6 - 2 * level, + base_va, level_size); + } +#endif + if (mm->base_va >= base_va + level_size) { + /* Next region is after area so nothing to map yet */ + desc = MMU32B_INVALID_DESC; + } else if ((mm->base_va <= base_va) && + (mm->base_va + mm->size) >= + (base_va + level_size)) { + /* Next region covers all of area */ + unsigned int attr = mm->attr; + unsigned int r = mmap_region_attr(mm, base_va, + level_size, &attr); + + if (r == 0U) { + desc = mmap_desc(attr, + base_va - mm->base_va + mm->base_pa, + level); + } + } + + if (desc == MMU32B_UNSET_DESC) { + uintptr_t xlat_table; + + /* + * Area not covered by a region so need finer table + * Reuse next level table if any (assert attrib matching). + * Otherwise allocate a xlat table. + */ + if (*table) { + assert((*table & 3) == SECTION_PT_PT); + assert(((*table & SECTION_PT_NOTSECURE) == 0U) + == ((mm->attr & MT_NS) == 0U)); + + xlat_table = (*table) & + ~(MMU32B_L1_TABLE_ALIGN - 1); + desc = *table; + } else { + xlat_table = (uintptr_t)mmu_l2_base + + next_xlat * MMU32B_L2_TABLE_SIZE; + next_xlat++; + assert(next_xlat <= MAX_XLAT_TABLES); + (void)memset((char *)xlat_table, 0, + MMU32B_L2_TABLE_SIZE); + + desc = xlat_table | SECTION_PT_PT; + desc |= (mm->attr & MT_NS) != 0U ? + SECTION_PT_NOTSECURE : 0; + } + /* Recurse to fill in new table */ + mm = init_xlation_table_inner(mm, base_va, + (uint32_t *)xlat_table, + level + 1); + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only non-lpae level 2 tables content */ + if (level == 2U) { + printf("\n"); + } +#endif + *table++ = desc; + base_va += level_size; + } while ((mm->size != 0U) && ((base_va & level_index_mask) != 0U)); + + return mm; +} + +void init_xlat_tables(void) +{ + print_mmap(); + + assert(((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U); + assert(((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U); + + (void)memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE); + + init_xlation_table_inner(mmap, 0, (uint32_t *)mmu_l1_base, 1); + + VERBOSE("init xlat - max_va=%p, max_pa=%llx\n", + (void *)xlat_max_va, xlat_max_pa); + assert(xlat_max_pa <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1)); +} + +/******************************************************************************* + * Function for enabling the MMU in Secure PL1, assuming that the + * page-tables have already been created. + ******************************************************************************/ +void enable_mmu_svc_mon(unsigned int flags) +{ + unsigned int prrr; + unsigned int nmrr; + unsigned int sctlr; + + assert(IS_IN_SECURE()); + assert((read_sctlr() & SCTLR_M_BIT) == 0U); + + /* Enable Access flag (simplified access permissions) and TEX remap */ + write_sctlr(read_sctlr() | SCTLR_AFE_BIT | SCTLR_TRE_BIT); + + prrr = MMU32B_PRRR_IDX(MMU32B_ATTR_DEVICE_INDEX, 1, 0) \ + | MMU32B_PRRR_IDX(MMU32B_ATTR_IWBWA_OWBWA_INDEX, 2, 1); + nmrr = MMU32B_NMRR_IDX(MMU32B_ATTR_DEVICE_INDEX, 0, 0) \ + | MMU32B_NMRR_IDX(MMU32B_ATTR_IWBWA_OWBWA_INDEX, 1, 1); + + prrr |= MMU32B_PRRR_NS1 | MMU32B_PRRR_DS1; + + write_prrr(prrr); + write_nmrr(nmrr); + + /* Program Domain access control register: domain 0 only */ + write_dacr(DACR_DOMAIN(0, DACR_DOMAIN_PERM_CLIENT)); + + /* Invalidate TLBs at the current exception level */ + tlbiall(); + + /* set MMU base xlat table entry (use only TTBR0) */ + write_ttbr0((uint32_t)mmu_l1_base | MMU32B_DEFAULT_ATTRS); + write_ttbr1(0U); + + /* + * 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(); + isb(); + + sctlr = read_sctlr(); + sctlr |= SCTLR_M_BIT; +#ifdef ARMV7_SUPPORTS_VIRTUALIZATION + sctlr |= SCTLR_WXN_BIT; +#endif + + if ((flags & DISABLE_DCACHE) != 0U) { + sctlr &= ~SCTLR_C_BIT; + } else { + sctlr |= SCTLR_C_BIT; + } + + write_sctlr(sctlr); + + /* Ensure the MMU enable takes effect immediately */ + isb(); +} diff --git a/arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c b/arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c new file mode 100644 index 0000000..4b01b9b --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "../xlat_tables_private.h" + +#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING) +#error ARMv7 target does not support LPAE MMU descriptors +#endif + +#define XLAT_TABLE_LEVEL_BASE \ + GET_XLAT_TABLE_LEVEL_BASE(PLAT_VIRT_ADDR_SPACE_SIZE) + +#define NUM_BASE_LEVEL_ENTRIES \ + GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) + +static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES] + __aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t)); + +#if ENABLE_ASSERTIONS +static unsigned long long get_max_supported_pa(void) +{ + /* Physical address space size for long descriptor format. */ + return (1ULL << 40) - 1ULL; +} +#endif /* ENABLE_ASSERTIONS */ + +unsigned int xlat_arch_current_el(void) +{ + /* + * If EL3 is in AArch32 mode, all secure PL1 modes (Monitor, System, + * SVC, Abort, UND, IRQ and FIQ modes) execute at EL3. + */ + return 3U; +} + +uint64_t xlat_arch_get_xn_desc(unsigned int el __unused) +{ + return UPPER_ATTRS(XN); +} + +void init_xlat_tables(void) +{ + unsigned long long max_pa; + uintptr_t max_va; + + assert(PLAT_VIRT_ADDR_SPACE_SIZE >= MIN_VIRT_ADDR_SPACE_SIZE); + assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE); + assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE)); + + print_mmap(); + init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE, + &max_va, &max_pa); + + assert(max_va <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert(max_pa <= (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + assert((PLAT_PHY_ADDR_SPACE_SIZE - 1U) <= get_max_supported_pa()); +} + +void enable_mmu_svc_mon(unsigned int flags) +{ + unsigned int mair0, ttbcr, sctlr; + uint64_t ttbr0; + + assert(IS_IN_SECURE()); + assert((read_sctlr() & SCTLR_M_BIT) == 0U); + + /* Set attributes in the right indices of the MAIR */ + mair0 = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); + mair0 |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, + ATTR_IWBWA_OWBWA_NTR_INDEX); + mair0 |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE, + ATTR_NON_CACHEABLE_INDEX); + write_mair0(mair0); + + /* Invalidate TLBs at the current exception level */ + tlbiall(); + + /* + * Set TTBCR bits as well. Set TTBR0 table properties. Disable TTBR1. + */ + int t0sz = 32 - __builtin_ctzll(PLAT_VIRT_ADDR_SPACE_SIZE); + + if ((flags & XLAT_TABLE_NC) != 0U) { + /* Inner & outer non-cacheable non-shareable. */ + ttbcr = TTBCR_EAE_BIT | + TTBCR_SH0_NON_SHAREABLE | TTBCR_RGN0_OUTER_NC | + TTBCR_RGN0_INNER_NC | (uint32_t) t0sz; + } else { + /* Inner & outer WBWA & shareable. */ + ttbcr = TTBCR_EAE_BIT | + TTBCR_SH0_INNER_SHAREABLE | TTBCR_RGN0_OUTER_WBA | + TTBCR_RGN0_INNER_WBA | (uint32_t) t0sz; + } + ttbcr |= TTBCR_EPD1_BIT; + write_ttbcr(ttbcr); + + /* Set TTBR0 bits as well */ + ttbr0 = (uintptr_t) base_xlation_table; + write64_ttbr0(ttbr0); + write64_ttbr1(0U); + + /* + * Ensure all translation table writes have drained + * into memory, the TLB invalidation is complete, + * and translation register writes are committed + * before enabling the MMU + */ + dsbish(); + isb(); + + sctlr = read_sctlr(); + sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT; + + if ((flags & DISABLE_DCACHE) != 0U) + sctlr &= ~SCTLR_C_BIT; + else + sctlr |= SCTLR_C_BIT; + + write_sctlr(sctlr); + + /* Ensure the MMU enable takes effect immediately */ + isb(); +} + +void enable_mmu_direct_svc_mon(unsigned int flags) +{ + enable_mmu_svc_mon(flags); +} diff --git a/arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c b/arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c new file mode 100644 index 0000000..dc167e3 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2014-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 "../xlat_tables_private.h" + +#define XLAT_TABLE_LEVEL_BASE \ + GET_XLAT_TABLE_LEVEL_BASE(PLAT_VIRT_ADDR_SPACE_SIZE) + +#define NUM_BASE_LEVEL_ENTRIES \ + GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) + +static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES] + __aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t)); + +static unsigned long long tcr_ps_bits; + +static unsigned long long calc_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 +}; + +static unsigned long long 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 + */ +static 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 */ + +unsigned int xlat_arch_current_el(void) +{ + unsigned int el = (unsigned int)GET_EL(read_CurrentEl()); + + assert(el > 0U); + + return el; +} + +uint64_t xlat_arch_get_xn_desc(unsigned int el) +{ + if (el == 3U) { + return UPPER_ATTRS(XN); + } else { + assert(el == 1U); + return UPPER_ATTRS(PXN); + } +} + +void init_xlat_tables(void) +{ + unsigned long long max_pa; + uintptr_t max_va; + + assert(PLAT_VIRT_ADDR_SPACE_SIZE >= + (xlat_get_min_virt_addr_space_size() - 1U)); + assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE); + assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE)); + + print_mmap(); + init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE, + &max_va, &max_pa); + + assert(max_va <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert(max_pa <= (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + assert((PLAT_PHY_ADDR_SPACE_SIZE - 1U) <= get_max_supported_pa()); + + tcr_ps_bits = calc_physical_addr_size_bits(max_pa); +} + +/******************************************************************************* + * Macro generating the code for the function enabling the MMU in the given + * exception level, assuming that the pagetables have already been created. + * + * _el: Exception level at which the function will run + * _tcr_extra: Extra bits to set in the TCR register. This mask will + * be OR'ed with the default TCR value. + * _tlbi_fct: Function to invalidate the TLBs at the current + * exception level + ******************************************************************************/ +#define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct) \ + void enable_mmu_el##_el(unsigned int flags) \ + { \ + uint64_t mair, tcr, ttbr; \ + uint32_t sctlr; \ + \ + assert(IS_IN_EL(_el)); \ + assert((read_sctlr_el##_el() & SCTLR_M_BIT) == 0U); \ + \ + /* 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); \ + write_mair_el##_el(mair); \ + \ + /* Invalidate TLBs at the current exception level */ \ + _tlbi_fct(); \ + \ + /* Set TCR bits as well. */ \ + /* Set T0SZ to (64 - width of virtual address space) */ \ + int t0sz = 64 - __builtin_ctzll(PLAT_VIRT_ADDR_SPACE_SIZE);\ + \ + 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 | \ + ((uint64_t)t0sz << TCR_T0SZ_SHIFT); \ + } else { \ + /* Inner & outer WBWA & shareable. */ \ + tcr = TCR_SH_INNER_SHAREABLE | \ + TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA | \ + ((uint64_t)t0sz << TCR_T0SZ_SHIFT); \ + } \ + tcr |= _tcr_extra; \ + write_tcr_el##_el(tcr); \ + \ + /* Set TTBR bits as well */ \ + ttbr = (uint64_t) base_xlation_table; \ + write_ttbr0_el##_el(ttbr); \ + \ + /* Ensure all translation table writes have drained */ \ + /* into memory, the TLB invalidation is complete, */ \ + /* and translation register writes are committed */ \ + /* before enabling the MMU */ \ + dsbish(); \ + isb(); \ + \ + sctlr = read_sctlr_el##_el(); \ + sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT; \ + \ + if ((flags & DISABLE_DCACHE) != 0U) \ + sctlr &= ~SCTLR_C_BIT; \ + else \ + sctlr |= SCTLR_C_BIT; \ + \ + write_sctlr_el##_el(sctlr); \ + \ + /* Ensure the MMU enable takes effect immediately */ \ + isb(); \ + } \ + \ + void enable_mmu_direct_el##_el(unsigned int flags) \ + { \ + enable_mmu_el##_el(flags); \ + } + +/* Define EL1 and EL3 variants of the function enabling the MMU */ +DEFINE_ENABLE_MMU_EL(1, + /* + * TCR_EL1.EPD1: Disable translation table walk for addresses + * that are translated using TTBR1_EL1. + */ + TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT), + tlbivmalle1) +DEFINE_ENABLE_MMU_EL(3, + TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT), + tlbialle3) diff --git a/arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c b/arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c new file mode 100644 index 0000000..23fe3f0 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2016-2018, 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" + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +#define LVL0_SPACER "" +#define LVL1_SPACER " " +#define LVL2_SPACER " " +#define LVL3_SPACER " " +#define get_level_spacer(level) \ + (((level) == U(0)) ? LVL0_SPACER : \ + (((level) == U(1)) ? LVL1_SPACER : \ + (((level) == U(2)) ? LVL2_SPACER : LVL3_SPACER))) +#define debug_print(...) printf(__VA_ARGS__) +#else +#define debug_print(...) ((void)0) +#endif + +#define UNSET_DESC ~0ULL +#define MT_UNKNOWN ~0U + +static uint64_t xlat_tables[MAX_XLAT_TABLES][XLAT_TABLE_ENTRIES] + __aligned(XLAT_TABLE_SIZE) __section("xlat_table"); + +static unsigned int next_xlat; +static unsigned long long xlat_max_pa; +static uintptr_t xlat_max_va; + +static uint64_t execute_never_mask; +static uint64_t ap1_mask; + +/* + * Array of all memory regions stored in order of ascending base address. + * The list is terminated by the first entry with size == 0. + */ +static mmap_region_t mmap[MAX_MMAP_REGIONS + 1]; + + +void print_mmap(void) +{ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + debug_print("mmap:\n"); + mmap_region_t *mm = mmap; + while (mm->size != 0U) { + debug_print(" VA:%p PA:0x%llx size:0x%zx attr:0x%x\n", + (void *)mm->base_va, mm->base_pa, + mm->size, mm->attr); + ++mm; + }; + debug_print("\n"); +#endif +} + +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr) +{ + mmap_region_t *mm = mmap; + const mmap_region_t *mm_last = mm + ARRAY_SIZE(mmap) - 1U; + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + assert(IS_PAGE_ALIGNED(base_pa)); + assert(IS_PAGE_ALIGNED(base_va)); + assert(IS_PAGE_ALIGNED(size)); + + if (size == 0U) + return; + + assert(base_pa < end_pa); /* Check for overflows */ + assert(base_va < end_va); + + assert((base_va + (uintptr_t)size - (uintptr_t)1) <= + (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert((base_pa + (unsigned long long)size - 1ULL) <= + (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + +#if ENABLE_ASSERTIONS + + /* Check for PAs and VAs overlaps with all other regions */ + for (mm = mmap; mm->size; ++mm) { + + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + + /* + * Check if one of the regions is completely inside the other + * one. + */ + bool fully_overlapped_va = + ((base_va >= mm->base_va) && (end_va <= mm_end_va)) || + ((mm->base_va >= base_va) && (mm_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. + */ + if (fully_overlapped_va) { + assert((mm->base_va - mm->base_pa) == + (base_va - base_pa)); + assert((base_va != mm->base_va) || (size != mm->size)); + } 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_end_pa = + mm->base_pa + mm->size - 1; + + bool separated_pa = (end_pa < mm->base_pa) || + (base_pa > mm_end_pa); + bool separated_va = (end_va < mm->base_va) || + (base_va > mm_end_va); + + assert(separated_va && separated_pa); + } + } + + mm = mmap; /* Restore pointer to the start of the array */ + +#endif /* ENABLE_ASSERTIONS */ + + /* Find correct place in mmap to insert new region */ + while ((mm->base_va < base_va) && (mm->size != 0U)) + ++mm; + + /* + * If a section is contained inside another one with the same base + * address, it must be placed after the one it is contained in: + * + * 1st |-----------------------| + * 2nd |------------| + * 3rd |------| + * + * This is required for mmap_region_attr() to get the attributes of the + * small region correctly. + */ + while ((mm->base_va == base_va) && (mm->size > size)) + ++mm; + + /* Make room for new region by moving other regions up by one place */ + (void)memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm); + + /* Check we haven't lost the empty sentinal from the end of the array */ + assert(mm_last->size == 0U); + + mm->base_pa = base_pa; + mm->base_va = base_va; + mm->size = size; + mm->attr = attr; + + if (end_pa > xlat_max_pa) + xlat_max_pa = end_pa; + if (end_va > xlat_max_va) + xlat_max_va = end_va; +} + +void mmap_add(const mmap_region_t *mm) +{ + const mmap_region_t *mm_cursor = mm; + + while ((mm_cursor->size != 0U) || (mm_cursor->attr != 0U)) { + mmap_add_region(mm_cursor->base_pa, mm_cursor->base_va, + mm_cursor->size, mm_cursor->attr); + mm_cursor++; + } +} + +static uint64_t mmap_desc(unsigned int attr, unsigned long long addr_pa, + unsigned int level) +{ + uint64_t desc; + int mem_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; + desc |= ((attr & MT_NS) != 0U) ? LOWER_ATTRS(NS) : 0U; + desc |= ((attr & MT_RW) != 0U) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); + /* + * Always set the access flag, as this library assumes access flag + * faults aren't managed. + */ + desc |= LOWER_ATTRS(ACCESS_FLAG); + desc |= ap1_mask; + + /* + * Deduce shareability domain and executability of the memory region + * from the memory 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 |= execute_never_mask; + + } 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. + */ + if (((attr & MT_RW) != 0U) || ((attr & MT_EXECUTE_NEVER) != 0U)) { + desc |= execute_never_mask; + } + + if (mem_type == MT_MEMORY) { + desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); + } else { + assert(mem_type == MT_NON_CACHEABLE); + desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH); + } + } + + debug_print((mem_type == MT_MEMORY) ? "MEM" : + ((mem_type == MT_NON_CACHEABLE) ? "NC" : "DEV")); + debug_print(((attr & MT_RW) != 0U) ? "-RW" : "-RO"); + debug_print(((attr & MT_NS) != 0U) ? "-NS" : "-S"); + debug_print(((attr & MT_EXECUTE_NEVER) != 0U) ? "-XN" : "-EXEC"); + return desc; +} + +/* + * Look for the innermost region that contains the area at `base_va` with size + * `size`. Populate *attr with the attributes of this region. + * + * On success, this function returns 0. + * If there are partial overlaps (meaning that a smaller size is needed) or if + * the region can't be found in the given area, it returns MT_UNKNOWN. In this + * case the value pointed by attr should be ignored by the caller. + */ +static unsigned int mmap_region_attr(const mmap_region_t *mm, uintptr_t base_va, + size_t size, unsigned int *attr) +{ + /* Don't assume that the area is contained in the first region */ + unsigned int ret = MT_UNKNOWN; + + /* + * Get attributes from last (innermost) region that contains the + * requested area. Don't stop as soon as one region doesn't contain it + * because there may be other internal regions that contain this area: + * + * |-----------------------------1-----------------------------| + * |----2----| |-------3-------| |----5----| + * |--4--| + * + * |---| <- Area we want the attributes of. + * + * In this example, the area is contained in regions 1, 3 and 4 but not + * in region 2. The loop shouldn't stop at region 2 as inner regions + * have priority over outer regions, it should stop at region 5. + */ + for ( ; ; ++mm) { + + if (mm->size == 0U) + return ret; /* Reached end of list */ + + if (mm->base_va > (base_va + size - 1U)) + return ret; /* Next region is after area so end */ + + if ((mm->base_va + mm->size - 1U) < base_va) + continue; /* Next region has already been overtaken */ + + if ((ret == 0U) && (mm->attr == *attr)) + continue; /* Region doesn't override attribs so skip */ + + if ((mm->base_va > base_va) || + ((mm->base_va + mm->size - 1U) < (base_va + size - 1U))) + return MT_UNKNOWN; /* Region doesn't fully cover area */ + + *attr = mm->attr; + ret = 0U; + } + return ret; +} + +static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm, + uintptr_t base_va, + uint64_t *table, + unsigned int level) +{ + assert((level >= XLAT_TABLE_LEVEL_MIN) && + (level <= XLAT_TABLE_LEVEL_MAX)); + + unsigned int level_size_shift = + L0_XLAT_ADDRESS_SHIFT - level * XLAT_TABLE_ENTRIES_SHIFT; + u_register_t level_size = (u_register_t)1 << level_size_shift; + u_register_t level_index_mask = + ((u_register_t)XLAT_TABLE_ENTRIES_MASK) << level_size_shift; + + debug_print("New xlat table:\n"); + + do { + uint64_t desc = UNSET_DESC; + + if (mm->size == 0U) { + /* Done mapping regions; finish zeroing the table */ + desc = INVALID_DESC; + } else if ((mm->base_va + mm->size - 1U) < base_va) { + /* This area is after the region so get next region */ + ++mm; + continue; + } + + debug_print("%s VA:%p size:0x%llx ", get_level_spacer(level), + (void *)base_va, (unsigned long long)level_size); + + if (mm->base_va > (base_va + level_size - 1U)) { + /* Next region is after this area. Nothing to map yet */ + desc = INVALID_DESC; + /* Make sure that the current level allows block descriptors */ + } else if (level >= XLAT_BLOCK_LEVEL_MIN) { + /* + * Try to get attributes of this area. It will fail if + * there are partially overlapping regions. On success, + * it will return the innermost region's attributes. + */ + unsigned int attr; + unsigned int r = mmap_region_attr(mm, base_va, + level_size, &attr); + + if (r == 0U) { + desc = mmap_desc(attr, + base_va - mm->base_va + mm->base_pa, + level); + } + } + + if (desc == UNSET_DESC) { + /* Area not covered by a region so need finer table */ + uint64_t *new_table = xlat_tables[next_xlat]; + + next_xlat++; + assert(next_xlat <= MAX_XLAT_TABLES); + desc = TABLE_DESC | (uintptr_t)new_table; + + /* Recurse to fill in new table */ + mm = init_xlation_table_inner(mm, base_va, + new_table, level + 1U); + } + + debug_print("\n"); + + *table++ = desc; + base_va += level_size; + } while ((base_va & level_index_mask) && + ((base_va - 1U) < (PLAT_VIRT_ADDR_SPACE_SIZE - 1U))); + + return mm; +} + +void init_xlation_table(uintptr_t base_va, uint64_t *table, + unsigned int level, uintptr_t *max_va, + unsigned long long *max_pa) +{ + unsigned int el = xlat_arch_current_el(); + + execute_never_mask = xlat_arch_get_xn_desc(el); + + if (el == 3U) { + ap1_mask = LOWER_ATTRS(AP_ONE_VA_RANGE_RES1); + } else { + assert(el == 1U); + ap1_mask = 0ULL; + } + + init_xlation_table_inner(mmap, base_va, table, level); + *max_va = xlat_max_va; + *max_pa = xlat_max_pa; +} diff --git a/arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h b/arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h new file mode 100644 index 0000000..82bc70c --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016-2018, 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 HW_ASSISTED_COHERENCY +#error xlat tables v2 must be used with HW_ASSISTED_COHERENCY +#endif + +CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(PLAT_PHY_ADDR_SPACE_SIZE), + assert_valid_phy_addr_space_size); + +/* Alias to retain compatibility with the old #define name */ +#define XLAT_BLOCK_LEVEL_MIN MIN_LVL_BLOCK_DESC + +void print_mmap(void); + +/* Returns the current Exception Level. The returned EL must be 1 or higher. */ +unsigned int xlat_arch_current_el(void); + +/* + * Returns the bit mask that has to be ORed to the rest of a translation table + * descriptor so that execution of code is prohibited at the given Exception + * Level. + */ +uint64_t xlat_arch_get_xn_desc(unsigned int el); + +void init_xlation_table(uintptr_t base_va, uint64_t *table, + unsigned int level, uintptr_t *max_va, + unsigned long long *max_pa); + +#endif /* XLAT_TABLES_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S b/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S new file mode 100644 index 0000000..f2fff36 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .global enable_mmu_direct_svc_mon + .global enable_mmu_direct_hyp + + /* void enable_mmu_direct_svc_mon(unsigned int flags) */ +func enable_mmu_direct_svc_mon + /* Assert that MMU is turned off */ +#if ENABLE_ASSERTIONS + ldcopr r1, SCTLR + tst r1, #SCTLR_M_BIT + ASM_ASSERT(eq) +#endif + + /* Invalidate TLB entries */ + TLB_INVALIDATE(r0, TLBIALL) + + mov r3, r0 + ldr r0, =mmu_cfg_params + + /* MAIR0. Only the lower 32 bits are used. */ + ldr r1, [r0, #(MMU_CFG_MAIR << 3)] + stcopr r1, MAIR0 + + /* TTBCR. Only the lower 32 bits are used. */ + ldr r2, [r0, #(MMU_CFG_TCR << 3)] + stcopr r2, TTBCR + + /* TTBR0 */ + ldr r1, [r0, #(MMU_CFG_TTBR0 << 3)] + ldr r2, [r0, #((MMU_CFG_TTBR0 << 3) + 4)] + stcopr16 r1, r2, TTBR0_64 + + /* TTBR1 is unused right now; set it to 0. */ + mov r1, #0 + mov r2, #0 + stcopr16 r1, r2, TTBR1_64 + + /* + * 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 + + /* Enable enable MMU by honoring flags */ + ldcopr r1, SCTLR + ldr r2, =(SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT) + orr r1, r1, r2 + + /* Clear C bit if requested */ + tst r3, #DISABLE_DCACHE + bicne r1, r1, #SCTLR_C_BIT + + stcopr r1, SCTLR + isb + + bx lr +endfunc enable_mmu_direct_svc_mon + + + /* void enable_mmu_direct_hyp(unsigned int flags) */ +func enable_mmu_direct_hyp + /* Assert that MMU is turned off */ +#if ENABLE_ASSERTIONS + ldcopr r1, HSCTLR + tst r1, #HSCTLR_M_BIT + ASM_ASSERT(eq) +#endif + + /* Invalidate TLB entries */ + TLB_INVALIDATE(r0, TLBIALL) + + mov r3, r0 + ldr r0, =mmu_cfg_params + + /* HMAIR0 */ + ldr r1, [r0, #(MMU_CFG_MAIR << 3)] + stcopr r1, HMAIR0 + + /* HTCR */ + ldr r2, [r0, #(MMU_CFG_TCR << 3)] + stcopr r2, HTCR + + /* HTTBR */ + ldr r1, [r0, #(MMU_CFG_TTBR0 << 3)] + ldr r2, [r0, #((MMU_CFG_TTBR0 << 3) + 4)] + stcopr16 r1, r2, HTTBR_64 + + /* + * 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 + + /* Enable enable MMU by honoring flags */ + ldcopr r1, HSCTLR + ldr r2, =(HSCTLR_WXN_BIT | HSCTLR_C_BIT | HSCTLR_M_BIT) + orr r1, r1, r2 + + /* Clear C bit if requested */ + tst r3, #DISABLE_DCACHE + bicne r1, r1, #HSCTLR_C_BIT + + stcopr r1, HSCTLR + isb + + bx lr +endfunc enable_mmu_direct_hyp diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c new file mode 100644 index 0000000..a1a44af --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2017-2021, 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" + +#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING) +#error ARMv7 target does not support LPAE MMU descriptors +#endif + +/* + * Returns true if the provided granule size is supported, false otherwise. + */ +bool xlat_arch_is_granule_size_supported(size_t size) +{ + /* + * The library uses the long descriptor translation table format, which + * supports 4 KiB pages only. + */ + return size == PAGE_SIZE_4KB; +} + +size_t xlat_arch_get_max_supported_granule_size(void) +{ + return PAGE_SIZE_4KB; +} + +/* + * Determine the physical address space encoded in the 'attr' parameter. + * + * The physical address will fall into one of two spaces; secure or + * nonsecure. + */ +uint32_t xlat_arch_get_pas(uint32_t attr) +{ + uint32_t pas = MT_PAS(attr); + + if (pas == MT_NS) { + return LOWER_ATTRS(NS); + } else { /* MT_SECURE */ + return 0U; + } +} + +#if ENABLE_ASSERTIONS +unsigned long long xlat_arch_get_max_supported_pa(void) +{ + /* Physical address space size for long descriptor format. */ + return (1ULL << 40) - 1ULL; +} + +/* + * Return minimum virtual address space size supported by the architecture + */ +uintptr_t xlat_get_min_virt_addr_space_size(void) +{ + return MIN_VIRT_ADDR_SPACE_SIZE; +} +#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() & SCTLR_M_BIT) != 0U; + } else { + assert(ctx->xlat_regime == EL2_REGIME); + assert(xlat_arch_current_el() == 2U); + return (read_hsctlr() & HSCTLR_M_BIT) != 0U; + } +} + +bool is_dcache_enabled(void) +{ + if (IS_IN_EL2()) { + return (read_hsctlr() & HSCTLR_C_BIT) != 0U; + } else { + return (read_sctlr() & SCTLR_C_BIT) != 0U; + } +} + +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime) +{ + if (xlat_regime == EL1_EL0_REGIME) { + return UPPER_ATTRS(XN) | UPPER_ATTRS(PXN); + } else { + assert(xlat_regime == EL2_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(); + + if (xlat_regime == EL1_EL0_REGIME) { + tlbimvaais(TLBI_ADDR(va)); + } else { + assert(xlat_regime == EL2_REGIME); + tlbimvahis(TLBI_ADDR(va)); + } +} + +void xlat_arch_tlbi_va_sync(void) +{ + /* Invalidate all entries from branch predictors. */ + bpiallis(); + + /* + * 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) +{ + if (IS_IN_HYP()) { + return 2U; + } else { + assert(IS_IN_SVC() || IS_IN_MON()); + /* + * If EL3 is in AArch32 mode, all secure PL1 modes (Monitor, + * System, SVC, Abort, UND, IRQ and FIQ modes) execute at EL3. + * + * The PL1&0 translation regime in AArch32 behaves like the + * EL1&0 regime in AArch64 except for the XN bits, but we set + * and unset them at the same time, so there's no difference in + * practice. + */ + return 1U; + } +} + +/******************************************************************************* + * Function for enabling the MMU in PL1 or PL2, assuming that the page tables + * have already been created. + ******************************************************************************/ +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, __unused int xlat_regime) +{ + uint64_t mair, ttbr0; + uint32_t ttbcr; + + /* Set attributes in the right indices of the MAIR */ + mair = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); + mair |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, + ATTR_IWBWA_OWBWA_NTR_INDEX); + mair |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE, + ATTR_NON_CACHEABLE_INDEX); + + /* + * Configure the control register for stage 1 of the PL1&0 or EL2 + * translation regimes. + */ + + /* Use the Long-descriptor translation table format. */ + ttbcr = TTBCR_EAE_BIT; + + if (xlat_regime == EL1_EL0_REGIME) { + assert(IS_IN_SVC() || IS_IN_MON()); + /* + * Disable translation table walk for addresses that are + * translated using TTBR1. Therefore, only TTBR0 is used. + */ + ttbcr |= TTBCR_EPD1_BIT; + } else { + assert(xlat_regime == EL2_REGIME); + assert(IS_IN_HYP()); + + /* + * Set HTCR bits as well. Set HTTBR table properties + * as Inner & outer WBWA & shareable. + */ + ttbcr |= HTCR_RES1 | + HTCR_SH0_INNER_SHAREABLE | HTCR_RGN0_OUTER_WBA | + HTCR_RGN0_INNER_WBA; + } + + /* + * Limit the input address ranges and memory region sizes translated + * using TTBR0 to the given virtual address space size, if smaller than + * 32 bits. + */ + if (max_va != UINT32_MAX) { + uintptr_t virtual_addr_space_size = max_va + 1U; + + assert(virtual_addr_space_size >= + xlat_get_min_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, UINT32_MAX]. + */ + int t0sz = 32 - __builtin_ctzll(virtual_addr_space_size); + + ttbcr |= (uint32_t) t0sz; + } + + /* + * Set the cacheability and shareability attributes for memory + * associated with translation table walks using TTBR0. + */ + if ((flags & XLAT_TABLE_NC) != 0U) { + /* Inner & outer non-cacheable non-shareable. */ + ttbcr |= TTBCR_SH0_NON_SHAREABLE | TTBCR_RGN0_OUTER_NC | + TTBCR_RGN0_INNER_NC; + } else { + /* Inner & outer WBWA & shareable. */ + ttbcr |= TTBCR_SH0_INNER_SHAREABLE | TTBCR_RGN0_OUTER_WBA | + TTBCR_RGN0_INNER_WBA; + } + + /* Set TTBR0 bits as well */ + ttbr0 = (uint64_t)(uintptr_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; + } + + /* Now populate MMU configuration */ + params[MMU_CFG_MAIR] = mair; + params[MMU_CFG_TCR] = (uint64_t) ttbcr; + params[MMU_CFG_TTBR0] = ttbr0; +} diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S b/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S new file mode 100644 index 0000000..9f075e4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c new file mode 100644 index 0000000..719110a --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2017-2021, 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; + } +} + +/* + * Determine the physical address space encoded in the 'attr' parameter. + * + * The physical address will fall into one of four spaces; secure, + * nonsecure, root, or realm if RME is enabled, or one of two spaces; + * secure and nonsecure otherwise. + */ +uint32_t xlat_arch_get_pas(uint32_t attr) +{ + uint32_t pas = MT_PAS(attr); + + switch (pas) { +#if ENABLE_RME + /* TTD.NSE = 1 and TTD.NS = 1 for Realm PAS */ + case MT_REALM: + return LOWER_ATTRS(EL3_S1_NSE | NS); + /* TTD.NSE = 1 and TTD.NS = 0 for Root PAS */ + case MT_ROOT: + return LOWER_ATTRS(EL3_S1_NSE); +#endif + case MT_NS: + return LOWER_ATTRS(NS); + default: /* MT_SECURE */ + return 0U; + } +} + +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/arm-trusted-firmware/lib/xlat_tables_v2/ro_xlat_tables.mk b/arm-trusted-firmware/lib/xlat_tables_v2/ro_xlat_tables.mk new file mode 100644 index 0000000..7991e1a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables.mk b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables.mk new file mode 100644 index 0000000..bcc3e68 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c new file mode 100644 index 0000000..95dae88 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c new file mode 100644 index 0000000..de57184 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c @@ -0,0 +1,1244 @@ +/* + * Copyright (c) 2017-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 "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); + + /* Determine the physical address space this region belongs to. */ + desc |= xlat_arch_get_pas(attr); + + /* + * Deduce other fields of the descriptor based on the MT_RW memory + * region attributes. + */ + 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/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h new file mode 100644 index 0000000..42c9a43 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2021, 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]; + +/* Determine the physical address space encoded in the 'attr' parameter. */ +uint32_t xlat_arch_get_pas(uint32_t attr); + +/* + * 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/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c new file mode 100644 index 0000000..38a375e --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c @@ -0,0 +1,592 @@ +/* + * Copyright (c) 2017-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 "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"); + } + +#if ENABLE_RME + switch (desc & LOWER_ATTRS(EL3_S1_NSE | NS)) { + case 0ULL: + printf("-S"); + break; + case LOWER_ATTRS(NS): + printf("-NS"); + break; + case LOWER_ATTRS(EL3_S1_NSE): + printf("-RT"); + break; + default: /* LOWER_ATTRS(EL3_S1_NSE | NS) */ + printf("-RL"); + } +#else + printf(((LOWER_ATTRS(NS) & desc) != 0ULL) ? "-NS" : "-S"); +#endif + +#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%" PRIx64 " 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/arm-trusted-firmware/lib/zlib/adler32.c b/arm-trusted-firmware/lib/zlib/adler32.c new file mode 100644 index 0000000..d0be438 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/adler32.c @@ -0,0 +1,186 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + +#define BASE 65521U /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32_z(adler, buf, len) + uLong adler; + const Bytef *buf; + z_size_t len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/arm-trusted-firmware/lib/zlib/crc32.c b/arm-trusted-firmware/lib/zlib/crc32.c new file mode 100644 index 0000000..9580440 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +/* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif +#ifdef BYFOUR + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, z_size_t)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, z_size_t)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local z_crc_t FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const z_crc_t FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + z_crc_t c; + int n, k; + z_crc_t poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (z_crc_t)1 << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (z_crc_t)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = ZSWAP32(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = ZSWAP32(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const z_crc_t FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const z_crc_t FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const z_crc_t FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const z_crc_t FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32_z(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + z_crc_t endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + return crc32_z(crc, buf, len); +} + +#ifdef BYFOUR + +/* + This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit + integer pointer type. This violates the strict aliasing rule, where a + compiler can assume, for optimization purposes, that two pointers to + fundamentally different types won't ever point to the same memory. This can + manifest as a problem only if one of the pointers is written to. This code + only reads from those pointers. So long as this code remains isolated in + this compilation unit, there won't be a problem. For this reason, this code + should not be copied and pasted into a compilation unit in which other code + writes to the buffer that is passed to these routines. + */ + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = (z_crc_t)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *buf4++; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = ZSWAP32((z_crc_t)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(ZSWAP32(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/arm-trusted-firmware/lib/zlib/crc32.h b/arm-trusted-firmware/lib/zlib/crc32.h new file mode 100644 index 0000000..9e0c778 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const z_crc_t FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/arm-trusted-firmware/lib/zlib/inffast.c b/arm-trusted-firmware/lib/zlib/inffast.c new file mode 100644 index 0000000..0dbd1db --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inffast.c @@ -0,0 +1,323 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - 5); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + *out++ = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = window; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } while (len > 2); + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/arm-trusted-firmware/lib/zlib/inffast.h b/arm-trusted-firmware/lib/zlib/inffast.h new file mode 100644 index 0000000..e5c1aa4 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/arm-trusted-firmware/lib/zlib/inffixed.h b/arm-trusted-firmware/lib/zlib/inffixed.h new file mode 100644 index 0000000..d628327 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/arm-trusted-firmware/lib/zlib/inflate.c b/arm-trusted-firmware/lib/zlib/inflate.c new file mode 100644 index 0000000..ac333e8 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inflate.c @@ -0,0 +1,1561 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); + +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, end, copy) +z_streamp strm; +const Bytef *end; +unsigned copy; +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +const unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/arm-trusted-firmware/lib/zlib/inflate.h b/arm-trusted-firmware/lib/zlib/inflate.h new file mode 100644 index 0000000..a46cce6 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inflate.h @@ -0,0 +1,125 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD = 16180, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ +struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/arm-trusted-firmware/lib/zlib/inftrees.c b/arm-trusted-firmware/lib/zlib/inftrees.c new file mode 100644 index 0000000..2ea08fc --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inftrees.c @@ -0,0 +1,304 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + unsigned match; /* use base and extra for symbol >= match */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + match = 20; + break; + case LENS: + base = lbase; + extra = lext; + match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/arm-trusted-firmware/lib/zlib/inftrees.h b/arm-trusted-firmware/lib/zlib/inftrees.h new file mode 100644 index 0000000..baa53a0 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/arm-trusted-firmware/lib/zlib/tf_gunzip.c b/arm-trusted-firmware/lib/zlib/tf_gunzip.c new file mode 100644 index 0000000..3ac80bc --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/tf_gunzip.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "zutil.h" + +/* + * memory allocated by malloc() is supposed to be aligned for any built-in type + */ +#define ZALLOC_ALIGNMENT sizeof(void *) + +static uintptr_t zalloc_start; +static uintptr_t zalloc_end; +static uintptr_t zalloc_current; + +static void * ZLIB_INTERNAL zcalloc(void *opaque, unsigned int items, + unsigned int size) +{ + uintptr_t p, p_end; + + size *= items; + + p = round_up(zalloc_current, ZALLOC_ALIGNMENT); + p_end = p + size; + + if (p_end > zalloc_end) + return NULL; + + memset((void *)p, 0, size); + + zalloc_current = p_end; + + return (void *)p; +} + +static void ZLIB_INTERNAL zfree(void *opaque, void *ptr) +{ +} + +/* + * gunzip - decompress gzip data + * @in_buf: source of compressed input. Upon exit, the end of input. + * @in_len: length of in_buf + * @out_buf: destination of decompressed output. Upon exit, the end of output. + * @out_len: length of out_buf + * @work_buf: workspace + * @work_len: length of workspace + */ +int gunzip(uintptr_t *in_buf, size_t in_len, uintptr_t *out_buf, + size_t out_len, uintptr_t work_buf, size_t work_len) +{ + z_stream stream; + int zret, ret; + + zalloc_start = work_buf; + zalloc_end = work_buf + work_len; + zalloc_current = zalloc_start; + + stream.next_in = (typeof(stream.next_in))*in_buf; + stream.avail_in = in_len; + stream.next_out = (typeof(stream.next_out))*out_buf; + stream.avail_out = out_len; + stream.zalloc = zcalloc; + stream.zfree = zfree; + stream.opaque = (voidpf)0; + + zret = inflateInit(&stream); + if (zret != Z_OK) { + ERROR("zlib: inflate init failed (ret = %d)\n", zret); + return (zret == Z_MEM_ERROR) ? -ENOMEM : -EIO; + } + + zret = inflate(&stream, Z_NO_FLUSH); + if (zret == Z_STREAM_END) { + ret = 0; + } else { + if (stream.msg) + ERROR("%s\n", stream.msg); + ERROR("zlib: inflate failed (ret = %d)\n", zret); + ret = (zret == Z_MEM_ERROR) ? -ENOMEM : -EIO; + } + + VERBOSE("zlib: %lu byte input\n", stream.total_in); + VERBOSE("zlib: %lu byte output\n", stream.total_out); + + *in_buf = (uintptr_t)stream.next_in; + *out_buf = (uintptr_t)stream.next_out; + + inflateEnd(&stream); + + return ret; +} + +/* Wrapper function to calculate CRC + * @crc: previous accumulated CRC + * @buf: buffer base address + * @size: size of the buffer + * + * Return calculated CRC32 value + */ +uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size) +{ + return (uint32_t)crc32((unsigned long)crc, buf, size); +} diff --git a/arm-trusted-firmware/lib/zlib/zconf.h b/arm-trusted-firmware/lib/zlib/zconf.h new file mode 100644 index 0000000..5e1d68a --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/arm-trusted-firmware/lib/zlib/zlib.h b/arm-trusted-firmware/lib/zlib/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/arm-trusted-firmware/lib/zlib/zlib.mk b/arm-trusted-firmware/lib/zlib/zlib.mk new file mode 100644 index 0000000..98d4efa --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zlib.mk @@ -0,0 +1,25 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ZLIB_PATH := lib/zlib + +# Imported from zlib 1.2.11 (do not modify them) +ZLIB_SOURCES := $(addprefix $(ZLIB_PATH)/, \ + adler32.c \ + crc32.c \ + inffast.c \ + inflate.c \ + inftrees.c \ + zutil.c) + +# Implemented for TF +ZLIB_SOURCES += $(addprefix $(ZLIB_PATH)/, \ + tf_gunzip.c) + +INCLUDES += -Iinclude/lib/zlib + +# REVISIT: the following flags need not be given globally +TF_CFLAGS += -DZ_SOLO -DDEF_WBITS=31 diff --git a/arm-trusted-firmware/lib/zlib/zutil.c b/arm-trusted-firmware/lib/zlib/zutil.c new file mode 100644 index 0000000..a76c6b0 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zutil.c @@ -0,0 +1,325 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2017 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif + +z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef ZLIB_DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef ZLIB_DEBUG +#include +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf; + ulg bsize = (ulg)items*size; + + (void)opaque; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + + (void)opaque; + + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + (void)opaque; + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + (void)opaque; + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + (void)opaque; + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + (void)opaque; + free(ptr); +} + +#endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/arm-trusted-firmware/lib/zlib/zutil.h b/arm-trusted-firmware/lib/zlib/zutil.h new file mode 100644 index 0000000..b079ea6 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zutil.h @@ -0,0 +1,271 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 1 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 2 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 7 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef __acorn +# define OS_CODE 13 +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 3 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef ZLIB_DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/arm-trusted-firmware/license.rst b/arm-trusted-firmware/license.rst new file mode 100644 index 0000000..3ec3b74 --- /dev/null +++ b/arm-trusted-firmware/license.rst @@ -0,0 +1 @@ +See docs/license.rst diff --git a/arm-trusted-firmware/licenses/LICENSE.MIT b/arm-trusted-firmware/licenses/LICENSE.MIT new file mode 100644 index 0000000..8aa2645 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/make_helpers/armv7-a-cpus.mk b/arm-trusted-firmware/make_helpers/armv7-a-cpus.mk new file mode 100644 index 0000000..eec85cc --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/make_helpers/build_env.mk b/arm-trusted-firmware/make_helpers/build_env.mk new file mode 100644 index 0000000..83093bd --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/make_helpers/build_macros.mk b/arm-trusted-firmware/make_helpers/build_macros.mk new file mode 100644 index 0000000..12aaee6 --- /dev/null +++ b/arm-trusted-firmware/make_helpers/build_macros.mk @@ -0,0 +1,614 @@ +# +# Copyright (c) 2015-2021, 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 +define IMG_LINKERFILE + ${BUILD_DIR}/$(1).ld +endef + +# IMG_MAPFILE defines the output file describing the memory map corresponding +# to a BL stage +# $(1) = BL stage +define IMG_MAPFILE + ${BUILD_DIR}/$(1).map +endef + +# IMG_ELF defines the elf file corresponding to a BL stage +# $(1) = BL stage +define IMG_ELF + ${BUILD_DIR}/$(1).elf +endef + +# IMG_DUMP defines the symbols dump file corresponding to a BL stage +# $(1) = BL stage +define IMG_DUMP + ${BUILD_DIR}/$(1).dump +endef + +# IMG_BIN defines the default image file corresponding to a BL stage +# $(1) = BL stage +define IMG_BIN + ${BUILD_PLAT}/$(1).bin +endef + +# IMG_ENC_BIN defines the default encrypted image file corresponding to a +# BL stage +# $(1) = BL stage +define IMG_ENC_BIN + ${BUILD_PLAT}/$(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 +define MAKE_C + +$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) +$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3))) +$(eval BL_CFLAGS := $($(call uppercase,$(3))_CFLAGS)) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(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 +define MAKE_S + +$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) +$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3))) +$(eval BL_ASFLAGS := $($(call uppercase,$(3))_ASFLAGS)) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(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 +define MAKE_LD + +$(eval DEP := $(1).d) +$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3))) + +$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(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 +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 +# $(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}/$(1)) + $(eval BL_SOURCES := $($(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 := $($(call uppercase,$(1))_LINKERFILE)) + $(eval BL_LIBS := $($(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 : ${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. +${1}_dirs: | ${OBJ_DIRS} + +$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1))) +$(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE),$(1))) +$(eval BL_LDFLAGS := $($(call uppercase,$(1))_LDFLAGS)) + +ifeq ($(USE_ROMLIB),1) +$(ELF): romlib.bin +endif + +$(ELF): $(OBJS) $(LINKERFILE) | $(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=${1}_entrypoint \ + --predefine="-D__LINKER__=$(__LINKER__)" \ + --predefine="-DTF_CFLAGS=$(TF_CFLAGS)" \ + --map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/${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: $(1) +ifeq ($(DISABLE_BIN_GENERATION),1) +$(1): $(ELF) $(DUMP) +else +$(1): $(BIN) $(DUMP) +endif + +all: $(1) + +ifeq ($(4),1) +$(call ENCRYPT_FW,$(BIN),$(ENC_BIN)) +$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \ + $(ENC_BIN))) +else +$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,$(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/arm-trusted-firmware/make_helpers/cygwin.mk b/arm-trusted-firmware/make_helpers/cygwin.mk new file mode 100644 index 0000000..04a963f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/make_helpers/defaults.mk b/arm-trusted-firmware/make_helpers/defaults.mk new file mode 100644 index 0000000..910ffdf --- /dev/null +++ b/arm-trusted-firmware/make_helpers/defaults.mk @@ -0,0 +1,418 @@ +# +# Copyright (c) 2016-2022, 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 + +# Only use SP packages if SP layout JSON is defined +BL2_ENABLE_SP_LOAD := 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 + +# Enable the Maximum Power Mitigation Mechanism on supporting cores. +ENABLE_MPMM := 0 + +# Enable MPMM configuration via FCONF. +ENABLE_MPMM_FCONF := 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 Realm Management Extension (FEAT_RME) +ENABLE_RME := 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 + +# Flag to enable access to the HCRX_EL2 register by setting SCR_EL3.HXEn. +ENABLE_FEAT_HCX := 0 + +# Flag to enable access to the HAFGRTR_EL2 register +ENABLE_FEAT_AMUv1 := 0 + +# Flag to enable access to the HDFGRTR_EL2 register +ENABLE_FEAT_FGT := 0 + +# Flag to enable access to the CNTPOFF_EL2 register +ENABLE_FEAT_ECV := 0 + +# Flag to enable use of the DIT feature. +ENABLE_FEAT_DIT := 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 + +# SMCCC PCI support +SMC_PCI_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 + +# Put BL2 NOLOAD sections (.bss, stacks, page tables) in a separate memory +# region, platform Makefile is free to override this value. +SEPARATE_BL2_NOLOAD_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 +ENABLE_AMU_AUXILIARY_COUNTERS := 0 +ENABLE_AMU_FCONF := 0 +AMU_RESTRICT_COUNTERS := 0 + +# Enable SVE for non-secure world by default +ENABLE_SVE_FOR_NS := 1 +# SVE is only supported on AArch64 so disable it on AArch32. +ifeq (${ARCH},aarch32) + override ENABLE_SVE_FOR_NS := 0 +endif +ENABLE_SVE_FOR_SWD := 0 + +# SME defaults to disabled +ENABLE_SME_FOR_NS := 0 +ENABLE_SME_FOR_SWD := 0 + +# If SME is enabled then force SVE off +ifeq (${ENABLE_SME_FOR_NS},1) + override ENABLE_SVE_FOR_NS := 0 + override ENABLE_SVE_FOR_SWD := 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 + +# Build option to define number of firmware banks, used in firmware update +# metadata structure. +NR_OF_FW_BANKS := 2 + +# Build option to define number of images in firmware bank, used in firmware +# update metadata structure. +NR_OF_IMAGES_IN_FW_BANK := 1 + +# Disable Firmware update support by default +PSA_FWU_SUPPORT := 0 + +# By default, disable access of trace buffer control registers from NS +# lower ELs i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused +# if FEAT_TRBE is implemented. +# Note FEAT_TRBE is only supported on AArch64 - therefore do not enable in +# AArch32. +ifneq (${ARCH},aarch32) + ENABLE_TRBE_FOR_NS := 0 +else + override ENABLE_TRBE_FOR_NS := 0 +endif + +# By default, disable access of trace system registers from NS lower +# ELs i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused if +# system register trace is implemented. +ENABLE_SYS_REG_TRACE_FOR_NS := 0 + +# By default, disable trace filter control registers access to NS +# lower ELs, i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused +# if FEAT_TRF is implemented. +ENABLE_TRF_FOR_NS := 0 diff --git a/arm-trusted-firmware/make_helpers/msys.mk b/arm-trusted-firmware/make_helpers/msys.mk new file mode 100644 index 0000000..7e60d57 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/make_helpers/plat_helpers.mk b/arm-trusted-firmware/make_helpers/plat_helpers.mk new file mode 100644 index 0000000..a7ae9a2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/make_helpers/tbbr/tbbr_tools.mk b/arm-trusted-firmware/make_helpers/tbbr/tbbr_tools.mk new file mode 100644 index 0000000..0a280b4 --- /dev/null +++ b/arm-trusted-firmware/make_helpers/tbbr/tbbr_tools.mk @@ -0,0 +1,115 @@ +# +# 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_BL2: indicates whether BL2 is needed by the platform +# 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 (${NEED_BL2},yes) +ifeq (${BL2_AT_EL3}, 0) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) +endif +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/arm-trusted-firmware/make_helpers/unix.mk b/arm-trusted-firmware/make_helpers/unix.mk new file mode 100644 index 0000000..545ddfd --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/make_helpers/windows.mk b/arm-trusted-firmware/make_helpers/windows.mk new file mode 100644 index 0000000..26ea88e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/package-lock.json b/arm-trusted-firmware/package-lock.json new file mode 100644 index 0000000..469c5f5 --- /dev/null +++ b/arm-trusted-firmware/package-lock.json @@ -0,0 +1,7330 @@ +{ + "name": "trusted-firmware-a", + "version": "2.6.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "trusted-firmware-a", + "version": "2.6.0", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "devDependencies": { + "@commitlint/cli": "^16.1.0", + "@commitlint/config-conventional": "^16.0.0", + "@commitlint/cz-commitlint": "^16.1.0", + "commitizen": "^4.2.4", + "conventional-changelog-tf-a": "file:tools/conventional-changelog-tf-a", + "husky": "^7.0.4", + "js-yaml": "^4.1.0", + "standard-version": "^9.3.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@commitlint/cli": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-16.1.0.tgz", + "integrity": "sha512-x5L1knvA3isRWBRVQx+Q6D45pA9139a2aZQYpxkljMG0dj4UHZkCnsYWpnGalxPxASI7nrI0KedKfS2YeQ55cQ==", + "dev": true, + "dependencies": { + "@commitlint/format": "^16.0.0", + "@commitlint/lint": "^16.0.0", + "@commitlint/load": "^16.1.0", + "@commitlint/read": "^16.0.0", + "@commitlint/types": "^16.0.0", + "lodash": "^4.17.19", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-16.0.0.tgz", + "integrity": "sha512-mN7J8KlKFn0kROd+q9PB01sfDx/8K/R25yITspL1No8PB4oj9M1p77xWjP80hPydqZG9OvQq+anXK3ZWeR7s3g==", + "dev": true, + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.3.1" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-16.1.0.tgz", + "integrity": "sha512-2cHeZPNTuf1JWbMqyA46MkExor5HMSgv8JrdmzEakUbJHUreh35/wN00FJf57qGs134exQW2thiSQ1IJUsVx2Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "ajv": "^6.12.6" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/cz-commitlint": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cz-commitlint/-/cz-commitlint-16.1.0.tgz", + "integrity": "sha512-TThglfXEBW8TZ99dvaeto1c6hU25ONqL9qkENle2+1OFI64NgbICjLsJq7SVzJd4Jn/yZDp4xNqoV53WJPJ9aA==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^16.0.0", + "@commitlint/load": "^16.1.0", + "@commitlint/types": "^16.0.0", + "chalk": "^4.1.0", + "lodash": "^4.17.21", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "commitizen": "^4.0.3", + "inquirer": "^8.0.0" + } + }, + "node_modules/@commitlint/ensure": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-16.0.0.tgz", + "integrity": "sha512-WdMySU8DCTaq3JPf0tZFCKIUhqxaL54mjduNhu8v4D2AMUVIIQKYMGyvXn94k8begeW6iJkTf9cXBArayskE7Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-16.0.0.tgz", + "integrity": "sha512-8edcCibmBb386x5JTHSPHINwA5L0xPkHQFY8TAuDEt5QyRZY/o5DF8OPHSa5Hx2xJvGaxxuIz4UtAT6IiRDYkw==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/format": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-16.0.0.tgz", + "integrity": "sha512-9yp5NCquXL1jVMKL0ZkRwJf/UHdebvCcMvICuZV00NQGYSAL89O398nhqrqxlbjBhM5EZVq0VGcV5+7r3D4zAA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-16.0.0.tgz", + "integrity": "sha512-gmAQcwIGC/R/Lp0CEb2b5bfGC7MT5rPe09N8kOGjO/NcdNmfFSZMquwrvNJsq9hnAP0skRdHIsqwlkENkN4Lag==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "semver": "7.3.5" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/lint": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-16.0.0.tgz", + "integrity": "sha512-HNl15bRC0h+pLzbMzQC3tM0j1aESXsLYhElqKnXcf5mnCBkBkHzu6WwJW8rZbfxX+YwJmNljN62cPhmdBo8x0A==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^16.0.0", + "@commitlint/parse": "^16.0.0", + "@commitlint/rules": "^16.0.0", + "@commitlint/types": "^16.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/load": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-16.1.0.tgz", + "integrity": "sha512-MtlEhKjP8jAF85jjX4mw8DUUwCxKsCgAc865hhpnwxjrfBcmGP7Up2AFE/M3ZMGDmSl1X1TMybQk/zohj8Cqdg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^16.1.0", + "@commitlint/execute-rule": "^16.0.0", + "@commitlint/resolve-extends": "^16.1.0", + "@commitlint/types": "^16.0.0", + "chalk": "^4.0.0", + "cosmiconfig": "^7.0.0", + "cosmiconfig-typescript-loader": "^1.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "typescript": "^4.4.3" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/message": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-16.0.0.tgz", + "integrity": "sha512-CmK2074SH1Ws6kFMEKOKH/7hMekGVbOD6vb4alCOo2+33ZSLUIX8iNkDYyrw38Jwg6yWUhLjyQLUxREeV+QIUA==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/parse": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-16.0.0.tgz", + "integrity": "sha512-F9EjFlMw4MYgBEqoRrWZZKQBzdiJzPBI0qFDFqwUvfQsMmXEREZ242T4R5bFwLINWaALFLHEIa/FXEPa6QxCag==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "conventional-changelog-angular": "^5.0.11", + "conventional-commits-parser": "^3.2.2" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/read": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-16.0.0.tgz", + "integrity": "sha512-H4T2zsfmYQK9B+JtoQaCXWBHUhgIJyOzWZjSfuIV9Ce69/OgHoffNpLZPF2lX6yKuDrS1SQFhI/kUCjVc/e4ew==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^16.0.0", + "@commitlint/types": "^16.0.0", + "fs-extra": "^10.0.0", + "git-raw-commits": "^2.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-16.1.0.tgz", + "integrity": "sha512-8182s6AFoUFX6+FT1PgQDt15nO2ogdR/EN8SYVAdhNXw1rLz8kT5saB/ICw567GuRAUgFTUMGCXy3ctMOXPEDg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^16.1.0", + "@commitlint/types": "^16.0.0", + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/rules": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-16.0.0.tgz", + "integrity": "sha512-AOl0y2SBTdJ1bvIv8nwHvQKRT/jC1xb09C5VZwzHoT8sE8F54KDeEzPCwHQFgUcWdGLyS10kkOTAH2MyA8EIlg==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^16.0.0", + "@commitlint/message": "^16.0.0", + "@commitlint/to-lines": "^16.0.0", + "@commitlint/types": "^16.0.0", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-16.0.0.tgz", + "integrity": "sha512-iN/qU38TCKU7uKOg6RXLpD49wNiuI0TqMqybHbjefUeP/Jmzxa8ishryj0uLyVdrAl1ZjGeD1ukXGMTtvqz8iA==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/top-level": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-16.0.0.tgz", + "integrity": "sha512-/Jt6NLxyFkpjL5O0jxurZPCHURZAm7cQCqikgPCwqPAH0TLgwqdHjnYipl8J+AGnAMGDip4FNLoYrtgIpZGBYw==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-16.0.0.tgz", + "integrity": "sha512-+0FvYOAS39bJ4aKjnYn/7FD4DfWkmQ6G/06I4F0Gvu4KS5twirEg8mIcLhmeRDOOKn4Tp8PwpLwBiSA6npEMQA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz", + "integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==", + "dev": true, + "peer": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", + "dev": true + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/cachedir": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.2.0.tgz", + "integrity": "sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "peer": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commitizen": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.4.tgz", + "integrity": "sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==", + "dev": true, + "dependencies": { + "cachedir": "2.2.0", + "cz-conventional-changelog": "3.2.0", + "dedent": "0.7.0", + "detect-indent": "6.0.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "8.1.0", + "glob": "7.1.4", + "inquirer": "6.5.2", + "is-utf8": "^0.2.1", + "lodash": "^4.17.20", + "minimist": "1.2.5", + "strip-bom": "4.0.0", + "strip-json-comments": "3.0.1" + }, + "bin": { + "commitizen": "bin/commitizen", + "cz": "bin/git-cz", + "git-cz": "bin/git-cz" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/commitizen/node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/commitizen/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "node_modules/commitizen/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/commitizen/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commitizen/node_modules/cz-conventional-changelog": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz", + "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" + } + }, + "node_modules/commitizen/node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/commitizen/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/commitizen/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/commitizen/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "node_modules/commitizen/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/commitizen/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/commitizen/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/commitizen/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/conventional-changelog": { + "version": "3.1.24", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", + "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", + "dev": true, + "dependencies": { + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", + "conventional-changelog-preset-loader": "^2.3.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-atom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-codemirror": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-config-spec": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", + "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", + "dev": true + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", + "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-core": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", + "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "dev": true, + "dependencies": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-core/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/conventional-changelog-core/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/conventional-changelog-core/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/conventional-changelog-ember": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-eslint": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-express": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-jquery": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-jshint": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-preset-loader": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-tf-a": { + "resolved": "tools/conventional-changelog-tf-a", + "link": true + }, + "node_modules/conventional-changelog-writer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz", + "integrity": "sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==", + "dev": true, + "dependencies": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.6", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/conventional-commit-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", + "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", + "dev": true + }, + "node_modules/conventional-commits-filter": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", + "dev": true, + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commits-parser": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz", + "integrity": "sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==", + "dev": true, + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-recommended-bump": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", + "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "dev": true, + "dependencies": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.3.4", + "conventional-commits-filter": "^2.0.7", + "conventional-commits-parser": "^3.2.0", + "git-raw-commits": "^2.0.8", + "git-semver-tags": "^4.1.1", + "meow": "^8.0.0", + "q": "^1.5.1" + }, + "bin": { + "conventional-recommended-bump": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.4.tgz", + "integrity": "sha512-ulv2dvwurP/MZAIthXm69bO7EzzIUThZ6RJ1qXhdlXM6to3F+IKBL/17EnhYSG52A5N1KcAUu66vSG/3/77KrA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7", + "ts-node": "^10.4.0" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "typescript": ">=3" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "peer": true, + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-indent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", + "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotgitignore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", + "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotgitignore/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-node-modules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.2.tgz", + "integrity": "sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug==", + "dev": true, + "dependencies": { + "findup-sync": "^4.0.0", + "merge": "^2.1.0" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "dependencies": { + "null-check": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-pkg-repo": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, + "dependencies": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "get-pkg-repo": "src/cli.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-pkg-repo/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/get-pkg-repo/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/get-pkg-repo/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/get-pkg-repo/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/get-pkg-repo/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", + "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", + "dev": true, + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "dependencies": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/git-semver-tags": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "dev": true, + "dependencies": { + "meow": "^8.0.0", + "semver": "^6.0.0" + }, + "bin": { + "git-semver-tags": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-semver-tags/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", + "dev": true, + "dependencies": { + "ini": "^1.3.2" + } + }, + "node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/husky": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", + "dev": true + }, + "node_modules/lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/longest": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", + "integrity": "sha1-eB4YMpaqlPbU2RbcM10NF676I/g=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "peer": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "peer": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "peer": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "~2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/standard-version": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", + "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "conventional-changelog": "3.1.24", + "conventional-changelog-config-spec": "2.1.0", + "conventional-changelog-conventionalcommits": "4.6.1", + "conventional-recommended-bump": "6.1.0", + "detect-indent": "^6.0.0", + "detect-newline": "^3.1.0", + "dotgitignore": "^2.1.0", + "figures": "^3.1.0", + "find-up": "^5.0.0", + "fs-access": "^1.0.1", + "git-semver-tags": "^4.0.0", + "semver": "^7.1.1", + "stringify-package": "^1.0.1", + "yargs": "^16.0.0" + }, + "bin": { + "standard-version": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/standard-version/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/standard-version/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/standard-version/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stringify-package": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", + "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", + "dev": true + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-node": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", + "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true, + "peer": true + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", + "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "peer": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", + "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "tools/conventional-changelog-tf-a": { + "version": "2.6.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.6.1", + "execa": "^5.1.1", + "lodash": "^4.17.21", + "q": "^1.5.1" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@commitlint/cli": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-16.1.0.tgz", + "integrity": "sha512-x5L1knvA3isRWBRVQx+Q6D45pA9139a2aZQYpxkljMG0dj4UHZkCnsYWpnGalxPxASI7nrI0KedKfS2YeQ55cQ==", + "dev": true, + "requires": { + "@commitlint/format": "^16.0.0", + "@commitlint/lint": "^16.0.0", + "@commitlint/load": "^16.1.0", + "@commitlint/read": "^16.0.0", + "@commitlint/types": "^16.0.0", + "lodash": "^4.17.19", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + } + }, + "@commitlint/config-conventional": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-16.0.0.tgz", + "integrity": "sha512-mN7J8KlKFn0kROd+q9PB01sfDx/8K/R25yITspL1No8PB4oj9M1p77xWjP80hPydqZG9OvQq+anXK3ZWeR7s3g==", + "dev": true, + "requires": { + "conventional-changelog-conventionalcommits": "^4.3.1" + } + }, + "@commitlint/config-validator": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-16.1.0.tgz", + "integrity": "sha512-2cHeZPNTuf1JWbMqyA46MkExor5HMSgv8JrdmzEakUbJHUreh35/wN00FJf57qGs134exQW2thiSQ1IJUsVx2Q==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "ajv": "^6.12.6" + } + }, + "@commitlint/cz-commitlint": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cz-commitlint/-/cz-commitlint-16.1.0.tgz", + "integrity": "sha512-TThglfXEBW8TZ99dvaeto1c6hU25ONqL9qkENle2+1OFI64NgbICjLsJq7SVzJd4Jn/yZDp4xNqoV53WJPJ9aA==", + "dev": true, + "requires": { + "@commitlint/ensure": "^16.0.0", + "@commitlint/load": "^16.1.0", + "@commitlint/types": "^16.0.0", + "chalk": "^4.1.0", + "lodash": "^4.17.21", + "word-wrap": "^1.2.3" + } + }, + "@commitlint/ensure": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-16.0.0.tgz", + "integrity": "sha512-WdMySU8DCTaq3JPf0tZFCKIUhqxaL54mjduNhu8v4D2AMUVIIQKYMGyvXn94k8begeW6iJkTf9cXBArayskE7Q==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "lodash": "^4.17.19" + } + }, + "@commitlint/execute-rule": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-16.0.0.tgz", + "integrity": "sha512-8edcCibmBb386x5JTHSPHINwA5L0xPkHQFY8TAuDEt5QyRZY/o5DF8OPHSa5Hx2xJvGaxxuIz4UtAT6IiRDYkw==", + "dev": true + }, + "@commitlint/format": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-16.0.0.tgz", + "integrity": "sha512-9yp5NCquXL1jVMKL0ZkRwJf/UHdebvCcMvICuZV00NQGYSAL89O398nhqrqxlbjBhM5EZVq0VGcV5+7r3D4zAA==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@commitlint/is-ignored": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-16.0.0.tgz", + "integrity": "sha512-gmAQcwIGC/R/Lp0CEb2b5bfGC7MT5rPe09N8kOGjO/NcdNmfFSZMquwrvNJsq9hnAP0skRdHIsqwlkENkN4Lag==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "semver": "7.3.5" + } + }, + "@commitlint/lint": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-16.0.0.tgz", + "integrity": "sha512-HNl15bRC0h+pLzbMzQC3tM0j1aESXsLYhElqKnXcf5mnCBkBkHzu6WwJW8rZbfxX+YwJmNljN62cPhmdBo8x0A==", + "dev": true, + "requires": { + "@commitlint/is-ignored": "^16.0.0", + "@commitlint/parse": "^16.0.0", + "@commitlint/rules": "^16.0.0", + "@commitlint/types": "^16.0.0" + } + }, + "@commitlint/load": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-16.1.0.tgz", + "integrity": "sha512-MtlEhKjP8jAF85jjX4mw8DUUwCxKsCgAc865hhpnwxjrfBcmGP7Up2AFE/M3ZMGDmSl1X1TMybQk/zohj8Cqdg==", + "dev": true, + "requires": { + "@commitlint/config-validator": "^16.1.0", + "@commitlint/execute-rule": "^16.0.0", + "@commitlint/resolve-extends": "^16.1.0", + "@commitlint/types": "^16.0.0", + "chalk": "^4.0.0", + "cosmiconfig": "^7.0.0", + "cosmiconfig-typescript-loader": "^1.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "typescript": "^4.4.3" + } + }, + "@commitlint/message": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-16.0.0.tgz", + "integrity": "sha512-CmK2074SH1Ws6kFMEKOKH/7hMekGVbOD6vb4alCOo2+33ZSLUIX8iNkDYyrw38Jwg6yWUhLjyQLUxREeV+QIUA==", + "dev": true + }, + "@commitlint/parse": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-16.0.0.tgz", + "integrity": "sha512-F9EjFlMw4MYgBEqoRrWZZKQBzdiJzPBI0qFDFqwUvfQsMmXEREZ242T4R5bFwLINWaALFLHEIa/FXEPa6QxCag==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "conventional-changelog-angular": "^5.0.11", + "conventional-commits-parser": "^3.2.2" + } + }, + "@commitlint/read": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-16.0.0.tgz", + "integrity": "sha512-H4T2zsfmYQK9B+JtoQaCXWBHUhgIJyOzWZjSfuIV9Ce69/OgHoffNpLZPF2lX6yKuDrS1SQFhI/kUCjVc/e4ew==", + "dev": true, + "requires": { + "@commitlint/top-level": "^16.0.0", + "@commitlint/types": "^16.0.0", + "fs-extra": "^10.0.0", + "git-raw-commits": "^2.0.0" + } + }, + "@commitlint/resolve-extends": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-16.1.0.tgz", + "integrity": "sha512-8182s6AFoUFX6+FT1PgQDt15nO2ogdR/EN8SYVAdhNXw1rLz8kT5saB/ICw567GuRAUgFTUMGCXy3ctMOXPEDg==", + "dev": true, + "requires": { + "@commitlint/config-validator": "^16.1.0", + "@commitlint/types": "^16.0.0", + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + } + }, + "@commitlint/rules": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-16.0.0.tgz", + "integrity": "sha512-AOl0y2SBTdJ1bvIv8nwHvQKRT/jC1xb09C5VZwzHoT8sE8F54KDeEzPCwHQFgUcWdGLyS10kkOTAH2MyA8EIlg==", + "dev": true, + "requires": { + "@commitlint/ensure": "^16.0.0", + "@commitlint/message": "^16.0.0", + "@commitlint/to-lines": "^16.0.0", + "@commitlint/types": "^16.0.0", + "execa": "^5.0.0" + } + }, + "@commitlint/to-lines": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-16.0.0.tgz", + "integrity": "sha512-iN/qU38TCKU7uKOg6RXLpD49wNiuI0TqMqybHbjefUeP/Jmzxa8ishryj0uLyVdrAl1ZjGeD1ukXGMTtvqz8iA==", + "dev": true + }, + "@commitlint/top-level": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-16.0.0.tgz", + "integrity": "sha512-/Jt6NLxyFkpjL5O0jxurZPCHURZAm7cQCqikgPCwqPAH0TLgwqdHjnYipl8J+AGnAMGDip4FNLoYrtgIpZGBYw==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "@commitlint/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-16.0.0.tgz", + "integrity": "sha512-+0FvYOAS39bJ4aKjnYn/7FD4DfWkmQ6G/06I4F0Gvu4KS5twirEg8mIcLhmeRDOOKn4Tp8PwpLwBiSA6npEMQA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, + "@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true + }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "@types/node": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz", + "integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==", + "dev": true, + "peer": true + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "peer": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "peer": true + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "peer": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "peer": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "peer": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "cachedir": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.2.0.tgz", + "integrity": "sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "peer": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "peer": true + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "peer": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true, + "peer": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commitizen": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.4.tgz", + "integrity": "sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==", + "dev": true, + "requires": { + "cachedir": "2.2.0", + "cz-conventional-changelog": "3.2.0", + "dedent": "0.7.0", + "detect-indent": "6.0.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "8.1.0", + "glob": "7.1.4", + "inquirer": "6.5.2", + "is-utf8": "^0.2.1", + "lodash": "^4.17.20", + "minimist": "1.2.5", + "strip-bom": "4.0.0", + "strip-json-comments": "3.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "cz-conventional-changelog": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz", + "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==", + "dev": true, + "requires": { + "@commitlint/load": ">6.1.1", + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "conventional-changelog": { + "version": "3.1.24", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", + "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", + "dev": true, + "requires": { + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", + "conventional-changelog-preset-loader": "^2.3.4" + } + }, + "conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + } + }, + "conventional-changelog-atom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-codemirror": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-config-spec": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", + "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", + "dev": true + }, + "conventional-changelog-conventionalcommits": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", + "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + } + }, + "conventional-changelog-core": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", + "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "dev": true, + "requires": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "dependencies": { + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + } + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "conventional-changelog-ember": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-eslint": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-express": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-jquery": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-jshint": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + } + }, + "conventional-changelog-preset-loader": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "dev": true + }, + "conventional-changelog-tf-a": { + "version": "file:tools/conventional-changelog-tf-a", + "requires": { + "conventional-changelog-conventionalcommits": "^4.6.1", + "execa": "^5.1.1", + "lodash": "^4.17.21", + "q": "^1.5.1" + } + }, + "conventional-changelog-writer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz", + "integrity": "sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==", + "dev": true, + "requires": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.6", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "conventional-commit-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", + "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", + "dev": true + }, + "conventional-commits-filter": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", + "dev": true, + "requires": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + } + }, + "conventional-commits-parser": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz", + "integrity": "sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==", + "dev": true, + "requires": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + } + }, + "conventional-recommended-bump": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", + "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "dev": true, + "requires": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.3.4", + "conventional-commits-filter": "^2.0.7", + "conventional-commits-parser": "^3.2.0", + "git-raw-commits": "^2.0.8", + "git-semver-tags": "^4.1.1", + "meow": "^8.0.0", + "q": "^1.5.1" + } + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cosmiconfig-typescript-loader": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.4.tgz", + "integrity": "sha512-ulv2dvwurP/MZAIthXm69bO7EzzIUThZ6RJ1qXhdlXM6to3F+IKBL/17EnhYSG52A5N1KcAUu66vSG/3/77KrA==", + "dev": true, + "requires": { + "cosmiconfig": "^7", + "ts-node": "^10.4.0" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "peer": true, + "requires": { + "clone": "^1.0.2" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-indent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", + "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", + "dev": true + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotgitignore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", + "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "minimatch": "^3.0.4" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-node-modules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.2.tgz", + "integrity": "sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug==", + "dev": true, + "requires": { + "findup-sync": "^4.0.0", + "merge": "^2.1.0" + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "^1.0.0" + } + }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-pkg-repo": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, + "requires": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "git-raw-commits": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", + "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", + "dev": true, + "requires": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + } + }, + "git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "requires": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + } + }, + "git-semver-tags": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "dev": true, + "requires": { + "meow": "^8.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", + "dev": true, + "requires": { + "ini": "^1.3.2" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "husky": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "peer": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", + "dev": true, + "peer": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "peer": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, + "requires": { + "text-extensions": "^1.0.0" + } + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "peer": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", + "dev": true + }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "peer": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "longest": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", + "integrity": "sha1-eB4YMpaqlPbU2RbcM10NF676I/g=", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true + }, + "meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + } + }, + "merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "peer": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "peer": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "requires": { + "global-dirs": "^0.1.1" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "peer": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "peer": true, + "requires": { + "tslib": "~2.1.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "requires": { + "readable-stream": "^3.0.0" + } + }, + "standard-version": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", + "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "conventional-changelog": "3.1.24", + "conventional-changelog-config-spec": "2.1.0", + "conventional-changelog-conventionalcommits": "4.6.1", + "conventional-recommended-bump": "6.1.0", + "detect-indent": "^6.0.0", + "detect-newline": "^3.1.0", + "dotgitignore": "^2.1.0", + "figures": "^3.1.0", + "find-up": "^5.0.0", + "fs-access": "^1.0.1", + "git-semver-tags": "^4.0.0", + "semver": "^7.1.1", + "stringify-package": "^1.0.1", + "yargs": "^16.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "stringify-package": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", + "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true + }, + "ts-node": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", + "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true, + "peer": true + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true + }, + "uglify-js": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", + "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", + "dev": true, + "optional": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "peer": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yargs": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", + "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/arm-trusted-firmware/package.json b/arm-trusted-firmware/package.json new file mode 100644 index 0000000..e5cd924 --- /dev/null +++ b/arm-trusted-firmware/package.json @@ -0,0 +1,23 @@ +{ + "name": "trusted-firmware-a", + "version": "2.6.0", + "license": "BSD-3-Clause", + "private": true, + "scripts": { + "postinstall": "husky install", + "release": "standard-version" + }, + "engines": { + "node": ">=16.0.0" + }, + "devDependencies": { + "@commitlint/cli": "^16.1.0", + "@commitlint/config-conventional": "^16.0.0", + "@commitlint/cz-commitlint": "^16.1.0", + "commitizen": "^4.2.4", + "conventional-changelog-tf-a": "file:tools/conventional-changelog-tf-a", + "husky": "^7.0.4", + "js-yaml": "^4.1.0", + "standard-version": "^9.3.2" + } +} diff --git a/arm-trusted-firmware/plat/allwinner/common/allwinner-common.mk b/arm-trusted-firmware/plat/allwinner/common/allwinner-common.mk new file mode 100644 index 0000000..34fdaf6 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/allwinner-common.mk @@ -0,0 +1,96 @@ +# +# Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk +include lib/libfdt/libfdt.mk +include drivers/arm/gic/v2/gicv2.mk + +AW_PLAT := plat/allwinner + +PLAT_INCLUDES := -Iinclude/plat/arm/common/aarch64 \ + -I${AW_PLAT}/common/include \ + -I${AW_PLAT}/${PLAT}/include + +PLAT_BL_COMMON_SOURCES := drivers/ti/uart/${ARCH}/16550_console.S \ + ${XLAT_TABLES_LIB_SRCS} \ + ${AW_PLAT}/common/plat_helpers.S \ + ${AW_PLAT}/common/sunxi_common.c + +BL31_SOURCES += drivers/allwinner/axp/common.c \ + ${GICV2_SOURCES} \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/${ARCH}/cortex_a53.S \ + plat/common/plat_gicv2.c \ + plat/common/plat_psci_common.c \ + ${AW_PLAT}/common/sunxi_bl31_setup.c \ + ${AW_PLAT}/common/sunxi_pm.c \ + ${AW_PLAT}/${PLAT}/sunxi_power.c \ + ${AW_PLAT}/common/sunxi_security.c \ + ${AW_PLAT}/common/sunxi_topology.c + +# By default, attempt to use SCPI to the ARISC management processor. If SCPI +# is not enabled or SCP firmware is not loaded, fall back to a simpler native +# implementation that does not support CPU or system suspend. +# +# If SCP firmware will always be present (or absent), the unused implementation +# can be compiled out. +SUNXI_PSCI_USE_NATIVE ?= 1 +SUNXI_PSCI_USE_SCPI ?= 1 + +$(eval $(call assert_boolean,SUNXI_PSCI_USE_NATIVE)) +$(eval $(call assert_boolean,SUNXI_PSCI_USE_SCPI)) +$(eval $(call add_define,SUNXI_PSCI_USE_NATIVE)) +$(eval $(call add_define,SUNXI_PSCI_USE_SCPI)) + +ifeq (${SUNXI_PSCI_USE_NATIVE}${SUNXI_PSCI_USE_SCPI},00) +$(error "At least one of SCPI or native PSCI ops must be enabled") +endif + +ifeq (${SUNXI_PSCI_USE_NATIVE},1) +BL31_SOURCES += ${AW_PLAT}/common/sunxi_cpu_ops.c \ + ${AW_PLAT}/common/sunxi_native_pm.c +endif + +ifeq (${SUNXI_PSCI_USE_SCPI},1) +BL31_SOURCES += drivers/allwinner/sunxi_msgbox.c \ + drivers/arm/css/scpi/css_scpi.c \ + ${AW_PLAT}/common/sunxi_scpi_pm.c +endif + +SUNXI_SETUP_REGULATORS ?= 1 +$(eval $(call assert_boolean,SUNXI_SETUP_REGULATORS)) +$(eval $(call add_define,SUNXI_SETUP_REGULATORS)) + +# The bootloader is guaranteed to only run on CPU 0 by the boot ROM. +COLD_BOOT_SINGLE_CPU := 1 + +# Do not enable SPE (not supported on ARM v8.0). +ENABLE_SPE_FOR_LOWER_ELS := 0 + +# Do not enable SVE (not supported on ARM v8.0). +ENABLE_SVE_FOR_NS := 0 + +# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4. +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 + +# The traditional U-Boot load address is 160MB into DRAM. +PRELOADED_BL33_BASE ?= 0x4a000000 + +# The reset vector can be changed for each CPU. +PROGRAMMABLE_RESET_ADDRESS := 1 + +# Allow mapping read-only data as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL +RESET_TO_BL31 := 1 + +# This platform is single-cluster and does not require coherency setup. +WARMBOOT_ENABLE_DCACHE_EARLY := 1 diff --git a/arm-trusted-firmware/plat/allwinner/common/arisc_off.S b/arm-trusted-firmware/plat/allwinner/common/arisc_off.S new file mode 100644 index 0000000..ed10832 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/arisc_off.S @@ -0,0 +1,115 @@ +# turn_off_core.S +# +# Copyright (c) 2018, Andre Przywara +# SPDX-License-Identifier: BSD-3-Clause +# +# OpenRISC assembly to turn off an ARM core on an Allwinner SoC from +# the arisc management controller. +# Generate a binary representation with: +# $ or1k-elf-as -c -o turn_off_core.o turn_off_core.S +# $ or1k-elf-objcopy -O binary --reverse-bytes=4 turn_off_core.o \ +# turn_off_core.bin +# The encoded instructions go into an array defined in +# plat/allwinner/sun50i_*/include/core_off_arisc.h, to be handed off to +# the arisc processor. +# +# This routine is meant to be called directly from arisc reset (put the +# start address in the reset vector), to be actually triggered by that +# very ARM core to be turned off. +# It expects the core number presented as a mask in the upper half of +# r3, so to be patched in the lower 16 bits of the first instruction, +# overwriting the 0 in this code here. +# The code will do the following: +# - Read the C_CPU_STATUS register, which contains the status of the WFI +# lines of each of the four A53 cores. +# - Loop until the core in question reaches WFI. +# - Using that mask, activate the core output clamps by setting the +# respective core bit in CPUX_PWROFF_GATING_REG (0x1f01500). +# Note that the clamp for core 0 covers more than just the core, activating +# it hangs the whole system. So we skip this step for core 0. +# - Using the negated mask, assert the core's reset line by clearing the +# respective bit in C_RST_CTRL (0x1f01c30). +# - Finally turn off the core's power switch by writing 0xff to the +# respective CPUx_PWR_SWITCH_REG (0x1f01540 ff.) +# - Assert the arisc's own reset to end execution. +# This also signals other arisc users that the chip is free again. +# So in C this would look like: +# while (!(readl(0x1700030) & (1U << core_nr))) +# ; +# if (core_nr != 0) +# writel(readl(0x1f01500) | (1U << core_nr), 0x1f01500); +# writel(readl(0x1f01c30) & ~(1U << core_nr), 0x1f01c30); +# writel(0xff, 0x1f01540 + (core_nr * 4)); +# (using A64/H5 addresses) + +.text +_start: + l.movhi r3, 0 # FIXUP! with core mask + l.movhi r0, 0 # clear r0 + l.movhi r13, 0x170 # r13: CPU_CFG_BASE=0x01700000 +wait_wfi: + l.lwz r5, 0x30(r13) # load C_CPU_STATUS + l.and r5, r5, r3 # mask requested core + l.sfeq r5, r0 # is it not yet in WFI? + l.bf wait_wfi # try again + + l.srli r6, r3, 16 # move mask to lower 16 bits + l.sfeqi r6, 1 # core 0 is special + l.bf 1f # don't touch the bit for core 0 + l.movhi r13, 0x1f0 # address of R_CPUCFG (delay) + l.lwz r5, 0x1500(r13) # core output clamps + l.or r5, r5, r6 # set bit to ... + l.sw 0x1500(r13), r5 # ... activate for our core + +1: l.lwz r5, 0x1c30(r13) # CPU power-on reset + l.xori r6, r6, -1 # negate core mask + l.and r5, r5, r6 # clear bit to ... + l.sw 0x1c30(r13), r5 # ... assert for our core + + l.ff1 r6, r3 # get core number from high mask + l.addi r6, r6, -17 # convert to 0-3 + l.slli r6, r6, 2 # r5: core number*4 (0-12) + l.add r6, r6, r13 # add to base address + l.ori r5, r0, 0xff # 0xff means all switches off + l.sw 0x1540(r6), r5 # core power switch registers + +reset: l.sw 0x1c00(r13),r0 # pull down our own reset line + + l.j reset # just in case .... + l.nop 0x0 # (delay slot) + +# same as above, but with the MMIO addresses matching the H6 SoC +_start_h6: + l.movhi r3, 0 # FIXUP! with core mask + l.movhi r0, 0 # clear r0 + l.movhi r13, 0x901 # r13: CPU_CFG_BASE=0x09010000 +1: + l.lwz r5, 0x80(r13) # load C_CPU_STATUS + l.and r5, r5, r3 # mask requested core + l.sfeq r5, r0 # is it not yet in WFI? + l.bf 1b # try again + + l.srli r6, r3, 16 # move mask to lower 16 bits(ds) + l.sfeqi r6, 1 # core 0 is special + l.bf 1f # don't touch the bit for core 0 + l.movhi r13, 0x700 # address of R_CPUCFG (ds) + l.lwz r5, 0x0444(r13) # core output clamps + l.or r5, r5, r6 # set bit to ... + l.sw 0x0444(r13), r5 # ... activate for our core + +1: l.lwz r5, 0x0440(r13) # CPU power-on reset + l.xori r6, r6, -1 # negate core mask + l.and r5, r5, r6 # clear bit to ... + l.sw 0x0440(r13), r5 # ... assert for our core + + l.ff1 r6, r3 # get core number from high mask + l.addi r6, r6, -17 # convert to 0-3 + l.slli r6, r6, 2 # r5: core number*4 (0-12) + l.add r6, r6, r13 # add to base address + l.ori r5, r0, 0xff # 0xff means all switches off + l.sw 0x0450(r6), r5 # core power switch registers + +1: l.sw 0x0400(r13),r0 # pull down our own reset line + + l.j 1b # just in case ... + l.nop 0x0 # (delay slot) diff --git a/arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h b/arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h new file mode 100644 index 0000000..d03f2d1 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 Icenowy Zheng + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ +/* This driver provides I2C support for Allwinner sunXi SoCs */ + +#ifndef MENTOR_I2C_PLAT_H +#define MENTOR_I2C_PLAT_H + +#define CONFIG_SYS_TCLK 24000000 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_SYS_I2C_SLAVE 0 + +#define I2C_INTERRUPT_CLEAR_INVERTED + +struct mentor_i2c_regs { + uint32_t slave_address; + uint32_t xtnd_slave_addr; + uint32_t data; + uint32_t control; + uint32_t status; + uint32_t baudrate; + uint32_t soft_reset; +}; + +#endif /* MENTOR_I2C_PLAT_H */ diff --git a/arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S b/arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S new file mode 100644 index 0000000..77f183d --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x17, SUNXI_GICC_BASE + mov_imm x16, SUNXI_GICD_BASE + arm_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/allwinner/common/include/platform_def.h b/arm-trusted-firmware/plat/allwinner/common/include/platform_def.h new file mode 100644 index 0000000..49951e0 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/platform_def.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#include + +#ifdef SUNXI_BL31_IN_DRAM + +#define BL31_BASE SUNXI_DRAM_BASE +#define BL31_LIMIT (SUNXI_DRAM_BASE + 0x40000) + +#define MAX_XLAT_TABLES 4 +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +#define SUNXI_BL33_VIRT_BASE PRELOADED_BL33_BASE + +#else /* !SUNXI_BL31_IN_DRAM */ + +#define BL31_BASE (SUNXI_SRAM_A2_BASE + \ + SUNXI_SRAM_A2_BL31_OFFSET) +#define BL31_LIMIT (SUNXI_SRAM_A2_BASE + \ + SUNXI_SRAM_A2_SIZE - SUNXI_SCP_SIZE) + +/* Overwrite U-Boot SPL, but reserve the first page for the SPL header. */ +#define BL31_NOBITS_BASE (SUNXI_SRAM_A1_BASE + 0x1000) +#define BL31_NOBITS_LIMIT (SUNXI_SRAM_A1_BASE + SUNXI_SRAM_A1_SIZE) + +#define MAX_XLAT_TABLES 1 +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 28) + +#define SUNXI_BL33_VIRT_BASE SUNXI_DRAM_VIRT_BASE + +/* The SCP firmware is allocated the last 16KiB of SRAM A2. */ +#define SUNXI_SCP_BASE BL31_LIMIT +#define SUNXI_SCP_SIZE 0x4000 + +#endif /* SUNXI_BL31_IN_DRAM */ + +/* How much DRAM to map (to map BL33, for fetching the DTB from U-Boot) */ +#define SUNXI_DRAM_MAP_SIZE (64U << 20) + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define MAX_STATIC_MMAP_REGIONS 3 +#define MAX_MMAP_REGIONS (5 + MAX_STATIC_MMAP_REGIONS) + +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE \ + (SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE - 0x200) + +#define PLAT_MAX_PWR_LVL_STATES U(2) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_NUM_PWR_DOMAINS (U(1) + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) + +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT) + +#ifndef SPD_none +#ifndef BL32_BASE +#define BL32_BASE SUNXI_DRAM_BASE +#endif +#endif + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h b/arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h new file mode 100644 index 0000000..ec50887 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_DEF_H +#define SUNXI_DEF_H + +/* Clock configuration */ +#define SUNXI_OSC24M_CLK_IN_HZ 24000000 + +/* UART configuration */ +#define SUNXI_UART0_BAUDRATE 115200 +#define SUNXI_UART0_CLK_IN_HZ SUNXI_OSC24M_CLK_IN_HZ + +#define SUNXI_SOC_A64 0x1689 +#define SUNXI_SOC_H5 0x1718 +#define SUNXI_SOC_H6 0x1728 +#define SUNXI_SOC_H616 0x1823 +#define SUNXI_SOC_R329 0x1851 + +#endif /* SUNXI_DEF_H */ diff --git a/arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h b/arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h new file mode 100644 index 0000000..6cf4670 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_PRIVATE_H +#define SUNXI_PRIVATE_H + +#include + +void sunxi_configure_mmu_el3(int flags); + +void sunxi_cpu_on(u_register_t mpidr); +void sunxi_cpu_power_off_others(void); +void sunxi_cpu_power_off_self(void); +void sunxi_power_down(void); + +#if SUNXI_PSCI_USE_NATIVE +void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops); +#else +static inline void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops) +{ +} +#endif +#if SUNXI_PSCI_USE_SCPI +int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops); +#else +static inline int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops) +{ + return -1; +} +#endif +int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint); + +int sunxi_pmic_setup(uint16_t socid, const void *fdt); +void sunxi_security_setup(void); + +uint16_t sunxi_read_soc_id(void); +void sunxi_set_gpio_out(char port, int pin, bool level_high); +int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb); +void sunxi_execute_arisc_code(uint32_t *code, size_t size, uint16_t param); + +#ifdef SUNXI_BL31_IN_DRAM +void sunxi_prepare_dtb(void *fdt); +#else +static inline void sunxi_prepare_dtb(void *fdt) +{ +} +#endif + +#endif /* SUNXI_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/allwinner/common/plat_helpers.S b/arm-trusted-firmware/plat/allwinner/common/plat_helpers.S new file mode 100644 index 0000000..b00c7ae --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/plat_helpers.S @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_my_core_pos + .globl platform_mem_init + .globl plat_report_exception + +func plat_crash_console_init + mov_imm x0, SUNXI_UART0_BASE + mov_imm x1, SUNXI_UART0_CLK_IN_HZ + mov_imm x2, SUNXI_UART0_BAUDRATE + b console_16550_core_init +endfunc plat_crash_console_init + +func plat_crash_console_putc + mov_imm x1, SUNXI_UART0_BASE + b console_16550_core_putc +endfunc plat_crash_console_putc + +func plat_crash_console_flush + ret +endfunc plat_crash_console_flush + +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CLUSTER_MASK + and x0, x0, #MPIDR_CPU_MASK + add x0, x0, x1, LSR #6 + ret +endfunc plat_my_core_pos + +func platform_mem_init + ret +endfunc platform_mem_init + +func plat_report_exception + ret +endfunc plat_report_exception diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c new file mode 100644 index 0000000..14049e8 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2017-2018, 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 + +#include +#include +#include + + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +static console_t console; + +static const gicv2_driver_data_t sunxi_gic_data = { + .gicd_base = SUNXI_GICD_BASE, + .gicc_base = SUNXI_GICC_BASE, +}; + +/* + * Try to find a DTB loaded in memory by previous stages. + * + * At the moment we implement a heuristic to find the DTB attached to U-Boot: + * U-Boot appends its DTB to the end of the image. Assuming that BL33 is + * U-Boot, try to find the size of the U-Boot image to learn the DTB address. + * The generic ARMv8 U-Boot image contains the load address and its size + * as u64 variables at the beginning of the image. There might be padding + * or other headers before that data, so scan the first 2KB after the BL33 + * entry point to find the load address, which should be followed by the + * size. Adding those together gives us the address of the DTB. + */ +static void *sunxi_find_dtb(void) +{ + uint64_t *u_boot_base; + int i; + + u_boot_base = (void *)SUNXI_BL33_VIRT_BASE; + + for (i = 0; i < 2048 / sizeof(uint64_t); i++) { + uint32_t *dtb_base; + + if (u_boot_base[i] != PRELOADED_BL33_BASE) + continue; + + /* Does the suspected U-Boot size look anyhow reasonable? */ + if (u_boot_base[i + 1] >= 256 * 1024 * 1024) + continue; + + /* end of the image: base address + size */ + dtb_base = (void *)((char *)u_boot_base + u_boot_base[i + 1]); + + if (fdt_check_header(dtb_base) != 0) + continue; + + return dtb_base; + } + + return NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* Initialize the debug console as soon as possible */ + console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ, + SUNXI_UART0_BAUDRATE, &console); + +#ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; +#endif + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = PRELOADED_BL33_BASE; + bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +void bl31_plat_arch_setup(void) +{ + sunxi_configure_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + const char *soc_name; + uint16_t soc_id = sunxi_read_soc_id(); + void *fdt; + + switch (soc_id) { + case SUNXI_SOC_A64: + soc_name = "A64/H64/R18"; + break; + case SUNXI_SOC_H5: + soc_name = "H5"; + break; + case SUNXI_SOC_H6: + soc_name = "H6"; + break; + case SUNXI_SOC_H616: + soc_name = "H616"; + break; + case SUNXI_SOC_R329: + soc_name = "R329"; + break; + default: + soc_name = "unknown"; + break; + } + NOTICE("BL31: Detected Allwinner %s SoC (%04x)\n", soc_name, soc_id); + + generic_delay_timer_init(); + + fdt = sunxi_find_dtb(); + if (fdt) { + const char *model; + int length; + + model = fdt_getprop(fdt, 0, "model", &length); + NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt, + model ?: "unknown"); + } else { + NOTICE("BL31: No DTB found.\n"); + } + + /* Configure the interrupt controller */ + gicv2_driver_init(&sunxi_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + sunxi_security_setup(); + + /* + * On the A64 U-Boot's SPL sets the bus clocks to some conservative + * values, to work around FEL mode instabilities with SRAM C accesses. + * FEL mode is gone when we reach ATF, so bring the AHB1 bus + * (the "main" bus) clock frequency back to the recommended 200MHz, + * for improved performance. + */ + if (soc_id == SUNXI_SOC_A64) + mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x00003180); + + /* + * U-Boot or the kernel don't setup AHB2, which leaves it at the + * AHB1 frequency (200 MHz, see above). However Allwinner recommends + * 300 MHz, for improved Ethernet and USB performance. Switch the + * clock to use "PLL_PERIPH0 / 2". + */ + if (soc_id == SUNXI_SOC_A64 || soc_id == SUNXI_SOC_H5) + mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0x1); + + sunxi_pmic_setup(soc_id, fdt); + + sunxi_prepare_dtb(fdt); + + INFO("BL31: Platform setup done\n"); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + assert(sec_state_is_valid(type) != 0); + + if (type == NON_SECURE) + return &bl33_image_ep_info; + + if ((type == SECURE) && bl32_image_ep_info.pc) + return &bl32_image_ep_info; + + return NULL; +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_common.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_common.c new file mode 100644 index 0000000..82410b1 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_common.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + +static const mmap_region_t sunxi_mmap[MAX_STATIC_MMAP_REGIONS + 1] = { + MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), + MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), + MAP_REGION(PRELOADED_BL33_BASE, SUNXI_BL33_VIRT_BASE, + SUNXI_DRAM_MAP_SIZE, MT_RW_DATA | MT_NS), + {}, +}; + +unsigned int plat_get_syscnt_freq2(void) +{ + return SUNXI_OSC24M_CLK_IN_HZ; +} + +void sunxi_configure_mmu_el3(int flags) +{ + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + mmap_add_region(BL_CODE_END, BL_CODE_END, + BL_END - BL_CODE_END, + MT_RW_DATA | MT_SECURE); +#if SEPARATE_CODE_AND_RODATA + mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, + BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE); +#endif +#if SEPARATE_NOBITS_REGION + mmap_add_region(BL_NOBITS_BASE, BL_NOBITS_BASE, + BL_NOBITS_END - BL_NOBITS_BASE, + MT_RW_DATA | MT_SECURE); +#endif +#if USE_COHERENT_MEM + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER); +#endif + + mmap_add(sunxi_mmap); + init_xlat_tables(); + + enable_mmu_el3(0); +} + +#define SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24) +uint16_t sunxi_read_soc_id(void) +{ + uint32_t reg = mmio_read_32(SRAM_VER_REG); + + /* Set bit 15 to prepare for the SOCID read. */ + mmio_write_32(SRAM_VER_REG, reg | BIT(15)); + + reg = mmio_read_32(SRAM_VER_REG); + + /* deactivate the SOCID access again */ + mmio_write_32(SRAM_VER_REG, reg & ~BIT(15)); + + return reg >> 16; +} + +/* + * Configure a given pin to the GPIO-OUT function and sets its level. + * The port is given as a capital letter, the pin is the number within + * this port group. + * So to set pin PC7 to high, use: sunxi_set_gpio_out('C', 7, true); + */ +void sunxi_set_gpio_out(char port, int pin, bool level_high) +{ + uintptr_t port_base; + + if (port < 'A' || port > 'L') + return; + if (port == 'L') + port_base = SUNXI_R_PIO_BASE; + else + port_base = SUNXI_PIO_BASE + (port - 'A') * 0x24; + + /* Set the new level first before configuring the pin. */ + if (level_high) + mmio_setbits_32(port_base + 0x10, BIT(pin)); + else + mmio_clrbits_32(port_base + 0x10, BIT(pin)); + + /* configure pin as GPIO out (4(3) bits per pin, 1: GPIO out */ + mmio_clrsetbits_32(port_base + (pin / 8) * 4, + 0x7 << ((pin % 8) * 4), + 0x1 << ((pin % 8) * 4)); +} + +int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb) +{ + uint32_t pin_func = 0x77; + uint32_t device_bit; + unsigned int reset_offset = 0xb0; + + switch (socid) { + case SUNXI_SOC_H5: + if (use_rsb) + return -ENODEV; + pin_func = 0x22; + device_bit = BIT(6); + break; + case SUNXI_SOC_H6: + case SUNXI_SOC_H616: + pin_func = use_rsb ? 0x22 : 0x33; + device_bit = BIT(16); + reset_offset = use_rsb ? 0x1bc : 0x19c; + break; + case SUNXI_SOC_A64: + pin_func = use_rsb ? 0x22 : 0x33; + device_bit = use_rsb ? BIT(3) : BIT(6); + break; + default: + INFO("R_I2C/RSB on Allwinner 0x%x SoC not supported\n", socid); + return -ENODEV; + } + + /* un-gate R_PIO clock */ + if (socid != SUNXI_SOC_H6 && socid != SUNXI_SOC_H616) + mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, BIT(0)); + + /* switch pins PL0 and PL1 to the desired function */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x00, 0xffU, pin_func); + + /* level 2 drive strength */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x14, 0x0fU, 0xaU); + + /* set both pins to pull-up */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x1c, 0x0fU, 0x5U); + + /* un-gate clock */ + if (socid != SUNXI_SOC_H6 && socid != SUNXI_SOC_H616) + mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit); + else + mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, BIT(0)); + + /* assert, then de-assert reset of I2C/RSB controller */ + mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); + mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); + + return 0; +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c new file mode 100644 index 0000000..46e7090 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017-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 + +static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core) +{ + if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff) + return; + + VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core); + + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff); +} + +static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core) +{ + if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0) + return; + + VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core); + + /* Power enable sequence from original Allwinner sources */ + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe); + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8); + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0); + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80); + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00); + udelay(1); +} + +/* We can't turn ourself off like this, but it works for other cores. */ +static void sunxi_cpu_off(u_register_t mpidr) +{ + unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core); + + /* Deassert DBGPWRDUP */ + mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); + /* Activate the core output clamps, but not for core 0. */ + if (core != 0) + mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); + /* Assert CPU power-on reset */ + mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Remove power from the CPU */ + sunxi_cpu_disable_power(cluster, core); +} + +void sunxi_cpu_on(u_register_t mpidr) +{ + unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core); + + /* Assert CPU core reset */ + mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); + /* Assert CPU power-on reset */ + mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Set CPU to start in AArch64 mode */ + mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster), + BIT(SUNXI_AA64nAA32_OFFSET + core)); + /* Apply power to the CPU */ + sunxi_cpu_enable_power(cluster, core); + /* Release the core output clamps */ + mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); + /* Deassert CPU power-on reset */ + mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Deassert CPU core reset */ + mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); + /* Assert DBGPWRDUP */ + mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); +} + +void sunxi_cpu_power_off_others(void) +{ + u_register_t self = read_mpidr(); + unsigned int cluster; + unsigned int core; + + for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; ++cluster) { + for (core = 0; core < PLATFORM_MAX_CPUS_PER_CLUSTER; ++core) { + u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) | + (core << MPIDR_AFF0_SHIFT) | + BIT(31); + if (mpidr != self) + sunxi_cpu_off(mpidr); + } + } +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c new file mode 100644 index 0000000..148f50e --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010) +#define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014) +#define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018) + +static int sunxi_pwr_domain_on(u_register_t mpidr) +{ + sunxi_cpu_on(mpidr); + + return PSCI_E_SUCCESS; +} + +static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) +{ + gicv2_cpuif_disable(); + + sunxi_cpu_power_off_self(); +} + +static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void __dead2 sunxi_system_off(void) +{ + gicv2_cpuif_disable(); + + /* Attempt to power down the board (may not return) */ + sunxi_power_down(); + + /* Turn off all CPUs */ + sunxi_cpu_power_off_others(); + sunxi_cpu_power_off_self(); + psci_power_down_wfi(); +} + +static void __dead2 sunxi_system_reset(void) +{ + gicv2_cpuif_disable(); + + /* Reset the whole system when the watchdog times out */ + mmio_write_32(SUNXI_WDOG0_CFG_REG, 1); + /* Enable the watchdog with the shortest timeout (0.5 seconds) */ + mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1); + /* Wait for twice the watchdog timeout before panicking */ + mdelay(1000); + + ERROR("PSCI: System reset failed\n"); + panic(); +} + +static const plat_psci_ops_t sunxi_native_psci_ops = { + .pwr_domain_on = sunxi_pwr_domain_on, + .pwr_domain_off = sunxi_pwr_domain_off, + .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, + .system_off = sunxi_system_off, + .system_reset = sunxi_system_reset, + .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, +}; + +void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &sunxi_native_psci_ops; +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c new file mode 100644 index 0000000..eb1b7e7 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#include +#include + +int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint) +{ + /* The non-secure entry point must be in DRAM */ + if (ns_entrypoint < SUNXI_DRAM_BASE) { + return PSCI_E_INVALID_ADDRESS; + } + + return PSCI_E_SUCCESS; +} + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + assert(psci_ops); + + /* Program all CPU entry points. */ + for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; ++cpu) { + mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu), + sec_entrypoint & 0xffffffff); + mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu), + sec_entrypoint >> 32); + } + + if (sunxi_set_scpi_psci_ops(psci_ops) == 0) { + INFO("PSCI: Suspend is available via SCPI\n"); + } else { + INFO("PSCI: Suspend is unavailable\n"); + sunxi_set_native_psci_ops(psci_ops); + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c new file mode 100644 index 0000000..eb37daa --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * The addresses for the SCP exception vectors are defined in the or1k + * architecture specification. + */ +#define OR1K_VEC_FIRST 0x01 +#define OR1K_VEC_LAST 0x0e +#define OR1K_VEC_ADDR(n) (0x100 * (n)) + +/* + * This magic value is the little-endian representation of the or1k + * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the + * first instruction in the SCP firmware. + */ +#define SCP_FIRMWARE_MAGIC 0xb4400012 + +#define CPU_PWR_LVL MPIDR_AFFLVL0 +#define CLUSTER_PWR_LVL MPIDR_AFFLVL1 +#define SYSTEM_PWR_LVL MPIDR_AFFLVL2 + +#define CPU_PWR_STATE(state) \ + ((state)->pwr_domain_state[CPU_PWR_LVL]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[CLUSTER_PWR_LVL]) +#define SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[SYSTEM_PWR_LVL]) + +static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state) +{ + if (is_local_state_run(psci_state)) { + return scpi_power_on; + } + if (is_local_state_retn(psci_state)) { + return scpi_power_retention; + } + return scpi_power_off; +} + +static void sunxi_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr = read_scr_el3(); + + assert(is_local_state_retn(cpu_state)); + + write_scr_el3(scr | SCR_IRQ_BIT); + wfi(); + write_scr_el3(scr); +} + +static int sunxi_pwr_domain_on(u_register_t mpidr) +{ + scpi_set_css_power_state(mpidr, + scpi_power_on, + scpi_power_on, + scpi_power_on); + + return PSCI_E_SUCCESS; +} + +static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) +{ + plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state); + plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state); + plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state); + + if (is_local_state_off(cpu_pwr_state)) { + gicv2_cpuif_disable(); + } + + scpi_set_css_power_state(read_mpidr(), + scpi_map_state(cpu_pwr_state), + scpi_map_state(cluster_pwr_state), + scpi_map_state(system_pwr_state)); +} + +static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { + gicv2_distif_init(); + } + if (is_local_state_off(CPU_PWR_STATE(target_state))) { + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + } +} + +static void __dead2 sunxi_system_off(void) +{ + uint32_t ret; + + gicv2_cpuif_disable(); + + /* Send the power down request to the SCP. */ + ret = scpi_sys_power_state(scpi_system_shutdown); + if (ret != SCP_OK) { + ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret); + } + + psci_power_down_wfi(); +} + +static void __dead2 sunxi_system_reset(void) +{ + uint32_t ret; + + gicv2_cpuif_disable(); + + /* Send the system reset request to the SCP. */ + ret = scpi_sys_power_state(scpi_system_reboot); + if (ret != SCP_OK) { + ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret); + } + + psci_power_down_wfi(); +} + +static int sunxi_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int power_level = psci_get_pstate_pwrlvl(power_state); + unsigned int type = psci_get_pstate_type(power_state); + + assert(req_state != NULL); + + if (power_level > PLAT_MAX_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + + if (type == PSTATE_TYPE_STANDBY) { + /* Only one retention power state is supported. */ + if (psci_get_pstate_id(power_state) > 0) { + return PSCI_E_INVALID_PARAMS; + } + /* The SoC cannot be suspended without losing state */ + if (power_level == SYSTEM_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + for (unsigned int i = 0; i <= power_level; ++i) { + req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; + } + } else { + /* Only one off power state is supported. */ + if (psci_get_pstate_id(power_state) > 0) { + return PSCI_E_INVALID_PARAMS; + } + for (unsigned int i = 0; i <= power_level; ++i) { + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } + } + /* Higher power domain levels should all remain running */ + for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i) { + req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN; + } + + return PSCI_E_SUCCESS; +} + +static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + assert(req_state != NULL); + + for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) { + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } +} + +static const plat_psci_ops_t sunxi_scpi_psci_ops = { + .cpu_standby = sunxi_cpu_standby, + .pwr_domain_on = sunxi_pwr_domain_on, + .pwr_domain_off = sunxi_pwr_domain_off, + .pwr_domain_suspend = sunxi_pwr_domain_off, + .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, + .pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish, + .system_off = sunxi_system_off, + .system_reset = sunxi_system_reset, + .validate_power_state = sunxi_validate_power_state, + .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, + .get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state, +}; + +int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &sunxi_scpi_psci_ops; + + /* Check for a valid SCP firmware. */ + if (mmio_read_32(SUNXI_SCP_BASE) != SCP_FIRMWARE_MAGIC) { + return -1; + } + + /* Program SCP exception vectors to the firmware entrypoint. */ + for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) { + uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i); + uint32_t offset = SUNXI_SCP_BASE - vector; + + mmio_write_32(vector, offset >> 2); + } + + /* Take the SCP out of reset. */ + mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0)); + + /* Wait for the SCP firmware to boot. */ + return scpi_wait_ready(); +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_security.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_security.c new file mode 100644 index 0000000..98b91c3 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_security.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#define DMA_SEC_REG 0x20 + +/* + * Setup the peripherals to be accessible by non-secure world. + * This will not work for the Secure Peripherals Controller (SPC) unless + * a fuse it burnt (seems to be an erratum), but we do it nevertheless, + * to allow booting on boards using secure boot. + */ +void sunxi_security_setup(void) +{ + int i; + + INFO("Configuring SPC Controller\n"); + /* SPC setup: set all devices to non-secure */ + for (i = 0; i < SUNXI_SPC_NUM_PORTS; i++) + mmio_write_32(SUNXI_SPC_DECPORT_SET_REG(i), 0xffffffff); + + /* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */ + mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7); + + /* Set R_PRCM bus clocks to non-secure */ + mmio_write_32(SUNXI_R_PRCM_SEC_SWITCH_REG, 0x1); + + /* Set all DMA channels (16 max.) to non-secure */ + mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff); +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c new file mode 100644 index 0000000..45be1e0 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +static const unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = { + /* One root node for the SoC */ + 1, + /* One node for each cluster */ + PLATFORM_CLUSTER_COUNT, + /* One set of CPUs per cluster */ + PLATFORM_MAX_CPUS_PER_CLUSTER, +}; + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + if (MPIDR_AFFLVL3_VAL(mpidr) > 0 || + MPIDR_AFFLVL2_VAL(mpidr) > 0 || + cluster >= PLATFORM_CLUSTER_COUNT || + core >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core; +} + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h new file mode 100644 index 0000000..ae436ca --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint32_t arisc_core_off[] = { + 0x18600000, /* l.movhi r3, */ + 0x18000000, /* l.movhi r0, 0x0 */ + 0x19a00170, /* l.movhi r13, 0x170 */ + 0x84ad0030, /* l.lwz r5, 0x30(r13) */ + 0xe0a51803, /* l.and r5, r5, r3 */ + 0xe4050000, /* l.sfeq r5, r0 */ + 0x13fffffd, /* l.bf -12 */ + + 0xb8c30050, /* l.srli r6, r3, 16 */ + 0xbc060001, /* l.sfeqi r6, 1 */ + 0x10000005, /* l.bf +20 */ + 0x19a001f0, /* l.movhi r13, 0x1f0 */ + 0x84ad1500, /* l.lwz r5, 0x1500(r13) */ + 0xe0a53004, /* l.or r5, r5, r6 */ + 0xd44d2d00, /* l.sw 0x1500(r13), r5 */ + + 0x84ad1c30, /* l.lwz r5, 0x1c30(r13) */ + 0xacc6ffff, /* l.xori r6, r6, -1 */ + 0xe0a53003, /* l.and r5, r5, r6 */ + 0xd46d2c30, /* l.sw 0x1c30(r13), r5 */ + + 0xe0c3000f, /* l.ff1 r6, r3 */ + 0x9cc6ffef, /* l.addi r6, r6, -17 */ + 0xb8c60002, /* l.slli r6, r6, 2 */ + 0xe0c66800, /* l.add r6, r6, r13 */ + 0xa8a000ff, /* l.ori r5, r0, 0xff */ + 0xd4462d40, /* l.sw 0x1540(r6), r5 */ + + 0xd46d0400, /* l.sw 0x1c00(r13), r0 */ + 0x03ffffff, /* l.j -1 */ + 0x15000000, /* l.nop */ +}; diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h new file mode 100644 index 0000000..2a24886 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CCU_H +#define SUNXI_CCU_H + +#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x02f0) + +#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x01d0) + +#endif /* SUNXI_CCU_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h new file mode 100644 index 0000000..aed3585 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CPUCFG_H +#define SUNXI_CPUCFG_H + +#include + +/* c = cluster, n = core */ +#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 16) +#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0004 + (c) * 16) +#define SUNXI_CPUCFG_CACHE_CFG_REG0 (SUNXI_CPUCFG_BASE + 0x0008) +#define SUNXI_CPUCFG_CACHE_CFG_REG1 (SUNXI_CPUCFG_BASE + 0x000c) +#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x0020) +#define SUNXI_CPUCFG_GLB_CTRL_REG (SUNXI_CPUCFG_BASE + 0x0028) +#define SUNXI_CPUCFG_CPU_STS_REG(c) (SUNXI_CPUCFG_BASE + 0x0030 + (c) * 4) +#define SUNXI_CPUCFG_L2_STS_REG (SUNXI_CPUCFG_BASE + 0x003c) +#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0080 + (c) * 4) +#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x00a0 + (n) * 8) +#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x00a4 + (n) * 8) + +#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_PRCM_BASE + 0x0140 + \ + (c) * 16 + (n) * 4) +#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_PRCM_BASE + 0x0100 + (c) * 4) +#define SUNXI_R_CPUCFG_CPUS_RST_REG (SUNXI_R_CPUCFG_BASE + 0x0000) +#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0030 + (c) * 4) +#define SUNXI_R_CPUCFG_SYS_RST_REG (SUNXI_R_CPUCFG_BASE + 0x0140) +#define SUNXI_R_CPUCFG_SS_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01a0) +#define SUNXI_R_CPUCFG_CPU_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a4) +#define SUNXI_R_CPUCFG_SS_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a8) +#define SUNXI_R_CPUCFG_HP_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01ac) + +#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0 +#define SUNXI_AA64nAA32_OFFSET 24 + +#endif /* SUNXI_CPUCFG_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h new file mode 100644 index 0000000..6d10921 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_MMAP_H +#define SUNXI_MMAP_H + +/* Memory regions */ +#define SUNXI_ROM_BASE 0x00000000 +#define SUNXI_ROM_SIZE 0x00010000 +#define SUNXI_SRAM_BASE 0x00010000 +#define SUNXI_SRAM_SIZE 0x00044000 +#define SUNXI_SRAM_A1_BASE 0x00010000 +#define SUNXI_SRAM_A1_SIZE 0x00008000 +#define SUNXI_SRAM_A2_BASE 0x00040000 +#define SUNXI_SRAM_A2_BL31_OFFSET 0x00004000 +#define SUNXI_SRAM_A2_SIZE 0x00014000 +#define SUNXI_SRAM_C_BASE 0x00018000 +#define SUNXI_SRAM_C_SIZE 0x0001c000 +#define SUNXI_DEV_BASE 0x01000000 +#define SUNXI_DEV_SIZE 0x01000000 +#define SUNXI_DRAM_BASE 0x40000000 +#define SUNXI_DRAM_VIRT_BASE 0x02000000 + +/* Memory-mapped devices */ +#define SUNXI_CPU_MBIST_BASE 0x01502000 +#define SUNXI_CPUCFG_BASE 0x01700000 +#define SUNXI_SYSCON_BASE 0x01c00000 +#define SUNXI_DMA_BASE 0x01c02000 +#define SUNXI_KEYMEM_BASE 0x01c0b000 +#define SUNXI_SMHC0_BASE 0x01c0f000 +#define SUNXI_SMHC1_BASE 0x01c10000 +#define SUNXI_SMHC2_BASE 0x01c11000 +#define SUNXI_SID_BASE 0x01c14000 +#define SUNXI_MSGBOX_BASE 0x01c17000 +#define SUNXI_SPINLOCK_BASE 0x01c18000 +#define SUNXI_CCU_BASE 0x01c20000 +#define SUNXI_PIO_BASE 0x01c20800 +#define SUNXI_TIMER_BASE 0x01c20c00 +#define SUNXI_WDOG_BASE 0x01c20ca0 +#define SUNXI_SPC_BASE 0x01c23400 +#define SUNXI_THS_BASE 0x01c25000 +#define SUNXI_UART0_BASE 0x01c28000 +#define SUNXI_UART1_BASE 0x01c28400 +#define SUNXI_UART2_BASE 0x01c28800 +#define SUNXI_UART3_BASE 0x01c28c00 +#define SUNXI_I2C0_BASE 0x01c2ac00 +#define SUNXI_I2C1_BASE 0x01c2b000 +#define SUNXI_I2C2_BASE 0x01c2b400 +#define SUNXI_DRAMCOM_BASE 0x01c62000 +#define SUNXI_DRAMCTL_BASE 0x01c63000 +#define SUNXI_DRAMPHY_BASE 0x01c65000 +#define SUNXI_SPI0_BASE 0x01c68000 +#define SUNXI_SPI1_BASE 0x01c69000 +#define SUNXI_SCU_BASE 0x01c80000 +#define SUNXI_GICD_BASE 0x01c81000 +#define SUNXI_GICC_BASE 0x01c82000 +#define SUNXI_RTC_BASE 0x01f00000 +#define SUNXI_R_TIMER_BASE 0x01f00800 +#define SUNXI_R_INTC_BASE 0x01f00c00 +#define SUNXI_R_WDOG_BASE 0x01f01000 +#define SUNXI_R_PRCM_BASE 0x01f01400 +#define SUNXI_R_TWD_BASE 0x01f01800 +#define SUNXI_R_CPUCFG_BASE 0x01f01c00 +#define SUNXI_R_CIR_BASE 0x01f02000 +#define SUNXI_R_I2C_BASE 0x01f02400 +#define SUNXI_R_UART_BASE 0x01f02800 +#define SUNXI_R_PIO_BASE 0x01f02c00 +#define SUNXI_R_RSB_BASE 0x01f03400 +#define SUNXI_R_PWM_BASE 0x01f03800 + +#endif /* SUNXI_MMAP_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h new file mode 100644 index 0000000..5ba7e18 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_SPC_H +#define SUNXI_SPC_H + +#define SUNXI_SPC_NUM_PORTS 6 + +#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x0c * (p)) +#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x0c * (p)) +#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x000c + 0x0c * (p)) + +#endif /* SUNXI_SPC_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_a64/platform.mk b/arm-trusted-firmware/plat/allwinner/sun50i_a64/platform.mk new file mode 100644 index 0000000..e3c7c52 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_a64/platform.mk @@ -0,0 +1,17 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# The differences between the platform are covered by the include files. +include plat/allwinner/common/allwinner-common.mk + +BL31_SOURCES += drivers/allwinner/axp/axp803.c \ + drivers/allwinner/sunxi_rsb.c + +FDT_ASSUME_MASK := "(ASSUME_LATEST | ASSUME_NO_ROLLBACK | ASSUME_LIBFDT_ORDER)" +$(eval $(call add_define,FDT_ASSUME_MASK)) + +# Put NOBITS memory in SRAM A1, overwriting U-Boot's SPL. +SEPARATE_NOBITS_REGION := 1 diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c b/arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c new file mode 100644 index 0000000..a35b9dd --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018, Icenowy Zheng + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +static enum pmic_type { + UNKNOWN, + GENERIC_H5, + GENERIC_A64, + REF_DESIGN_H5, /* regulators controlled by GPIO pins on port L */ + AXP803_RSB, /* PMIC connected via RSB on most A64 boards */ +} pmic; + +#define AXP803_HW_ADDR 0x3a3 +#define AXP803_RT_ADDR 0x2d + +/* + * On boards without a proper PMIC we struggle to turn off the system properly. + * Try to turn off as much off the system as we can, to reduce power + * consumption. This should be entered with only one core running and SMP + * disabled. + * This function only cares about peripherals. + */ +static void sunxi_turn_off_soc(uint16_t socid) +{ + int i; + + /** Turn off most peripherals, most importantly DRAM users. **/ + /* Keep DRAM controller running for now. */ + mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, ~BIT_32(14)); + mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, ~BIT_32(14)); + /* Contains msgbox (bit 21) and spinlock (bit 22) */ + mmio_write_32(SUNXI_CCU_BASE + 0x2c4, 0); + mmio_write_32(SUNXI_CCU_BASE + 0x64, 0); + mmio_write_32(SUNXI_CCU_BASE + 0x2c8, 0); + /* Keep PIO controller running for now. */ + mmio_clrbits_32(SUNXI_CCU_BASE + 0x68, ~(BIT_32(5))); + mmio_write_32(SUNXI_CCU_BASE + 0x2d0, 0); + /* Contains UART0 (bit 16) */ + mmio_write_32(SUNXI_CCU_BASE + 0x2d8, 0); + mmio_write_32(SUNXI_CCU_BASE + 0x6c, 0); + mmio_write_32(SUNXI_CCU_BASE + 0x70, 0); + + /** Turn off DRAM controller. **/ + mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, BIT_32(14)); + mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, BIT_32(14)); + + /** Migrate CPU and bus clocks away from the PLLs. **/ + /* AHB1: use OSC24M/1, APB1 = AHB1 / 2 */ + mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x1000); + /* APB2: use OSC24M */ + mmio_write_32(SUNXI_CCU_BASE + 0x58, 0x1000000); + /* AHB2: use AHB1 clock */ + mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0); + /* CPU: use OSC24M */ + mmio_write_32(SUNXI_CCU_BASE + 0x50, 0x10000); + + /** Turn off PLLs. **/ + for (i = 0; i < 6; i++) + mmio_clrbits_32(SUNXI_CCU_BASE + i * 8, BIT(31)); + switch (socid) { + case SUNXI_SOC_H5: + mmio_clrbits_32(SUNXI_CCU_BASE + 0x44, BIT(31)); + break; + case SUNXI_SOC_A64: + mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c, BIT(31)); + mmio_clrbits_32(SUNXI_CCU_BASE + 0x4c, BIT(31)); + break; + } +} + +static int rsb_init(void) +{ + int ret; + + ret = rsb_init_controller(); + if (ret) + return ret; + + /* Switch to the recommended 3 MHz bus clock. */ + ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); + if (ret) + return ret; + + /* Initiate an I2C transaction to switch the PMIC to RSB mode. */ + ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8); + if (ret) + return ret; + + /* Associate the 8-bit runtime address with the 12-bit bus address. */ + ret = rsb_assign_runtime_address(AXP803_HW_ADDR, + AXP803_RT_ADDR); + if (ret) + return ret; + + return axp_check_id(); +} + +int axp_read(uint8_t reg) +{ + return rsb_read(AXP803_RT_ADDR, reg); +} + +int axp_write(uint8_t reg, uint8_t val) +{ + return rsb_write(AXP803_RT_ADDR, reg, val); +} + +int sunxi_pmic_setup(uint16_t socid, const void *fdt) +{ + int ret; + + switch (socid) { + case SUNXI_SOC_H5: + NOTICE("PMIC: Assuming H5 reference regulator design\n"); + + pmic = REF_DESIGN_H5; + + break; + case SUNXI_SOC_A64: + pmic = GENERIC_A64; + + INFO("PMIC: Probing AXP803 on RSB\n"); + + ret = sunxi_init_platform_r_twi(socid, true); + if (ret) + return ret; + + ret = rsb_init(); + if (ret) + return ret; + + pmic = AXP803_RSB; + axp_setup_regulators(fdt); + + /* Switch the PMIC back to I2C mode. */ + ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C); + if (ret) + return ret; + + break; + default: + return -ENODEV; + } + return 0; +} + +void sunxi_power_down(void) +{ + switch (pmic) { + case GENERIC_H5: + /* Turn off as many peripherals and clocks as we can. */ + sunxi_turn_off_soc(SUNXI_SOC_H5); + /* Turn off the pin controller now. */ + mmio_write_32(SUNXI_CCU_BASE + 0x68, 0); + break; + case GENERIC_A64: + /* Turn off as many peripherals and clocks as we can. */ + sunxi_turn_off_soc(SUNXI_SOC_A64); + /* Turn off the pin controller now. */ + mmio_write_32(SUNXI_CCU_BASE + 0x68, 0); + break; + case REF_DESIGN_H5: + sunxi_turn_off_soc(SUNXI_SOC_H5); + + /* + * Switch PL pins to power off the board: + * - PL5 (VCC_IO) -> high + * - PL8 (PWR-STB = CPU power supply) -> low + * - PL9 (PWR-DRAM) ->low + * - PL10 (power LED) -> low + * Note: Clearing PL8 will reset the board, so keep it up. + */ + sunxi_set_gpio_out('L', 5, 1); + sunxi_set_gpio_out('L', 9, 0); + sunxi_set_gpio_out('L', 10, 0); + + /* Turn off pin controller now. */ + mmio_write_32(SUNXI_CCU_BASE + 0x68, 0); + + break; + case AXP803_RSB: + /* (Re-)init RSB in case the rich OS has disabled it. */ + sunxi_init_platform_r_twi(SUNXI_SOC_A64, true); + rsb_init(); + axp_power_off(); + break; + default: + break; + } + +} + +/* This lock synchronises access to the arisc management processor. */ +static DEFINE_BAKERY_LOCK(arisc_lock); + +/* + * If we are supposed to turn ourself off, tell the arisc SCP to do that + * work for us. Without any SCPI provider running there, we place some + * OpenRISC code into SRAM, put the address of that into the reset vector + * and release the arisc reset line. The SCP will wait for the core to enter + * WFI, then execute that code and pull the line up again. + * The code expects the core mask to be patched into the first instruction. + */ +void sunxi_cpu_power_off_self(void) +{ + u_register_t mpidr = read_mpidr(); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE + 0x100; + uint32_t *code = arisc_core_off; + + do { + bakery_lock_get(&arisc_lock); + /* Wait until the arisc is in reset state. */ + if (!(mmio_read_32(SUNXI_R_CPUCFG_BASE) & BIT(0))) + break; + + bakery_lock_release(&arisc_lock); + } while (1); + + /* Patch up the code to feed in an input parameter. */ + code[0] = (code[0] & ~0xffff) | BIT_32(core); + clean_dcache_range((uintptr_t)code, sizeof(arisc_core_off)); + + /* + * The OpenRISC unconditional branch has opcode 0, the branch offset + * is in the lower 26 bits, containing the distance to the target, + * in instruction granularity (32 bits). + */ + mmio_write_32(arisc_reset_vec, ((uintptr_t)code - arisc_reset_vec) / 4); + + /* De-assert the arisc reset line to let it run. */ + mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0)); + + /* + * We release the lock here, although the arisc is still busy. + * But as long as it runs, the reset line is high, so other users + * won't leave the loop above. + * Once it has finished, the code is supposed to clear the reset line, + * to signal this to other users. + */ + bakery_lock_release(&arisc_lock); +} diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h new file mode 100644 index 0000000..85fbb90 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CCU_H +#define SUNXI_CCU_H + +#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00) + +#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290) + +#endif /* SUNXI_CCU_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h new file mode 100644 index 0000000..5bfda5d --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CPUCFG_H +#define SUNXI_CPUCFG_H + +#include + +/* c = cluster, n = core */ +#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10) +#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10) +#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_CPUCFG_BASE + 0x0024) +#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x00c0) + +#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4) +#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8) +#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8) + +#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4) +#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4) +#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \ + (c) * 0x10 + (n) * 4) + +#define SUNXI_CPUIDLE_EN_REG (SUNXI_R_CPUCFG_BASE + 0x0100) +#define SUNXI_CORE_CLOSE_REG (SUNXI_R_CPUCFG_BASE + 0x0104) +#define SUNXI_PWR_SW_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0140) +#define SUNXI_CONFIG_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0144) + +#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0 +#define SUNXI_AA64nAA32_OFFSET 24 + +#endif /* SUNXI_CPUCFG_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h new file mode 100644 index 0000000..58216d8 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_MMAP_H +#define SUNXI_MMAP_H + +/* Memory regions */ +#define SUNXI_ROM_BASE 0x00000000 +#define SUNXI_ROM_SIZE 0x00010000 +#define SUNXI_SRAM_BASE 0x00020000 +#define SUNXI_SRAM_SIZE 0x000f8000 +#define SUNXI_SRAM_A1_BASE 0x00020000 +#define SUNXI_SRAM_A1_SIZE 0x00008000 +#define SUNXI_SRAM_A2_BASE 0x00100000 +#define SUNXI_SRAM_A2_BL31_OFFSET 0x00004000 +#define SUNXI_SRAM_A2_SIZE 0x00018000 +#define SUNXI_SRAM_C_BASE 0x00028000 +#define SUNXI_SRAM_C_SIZE 0x0001e000 +#define SUNXI_DEV_BASE 0x01000000 +#define SUNXI_DEV_SIZE 0x09000000 +#define SUNXI_DRAM_BASE 0x40000000 +#define SUNXI_DRAM_VIRT_BASE 0x0a000000 + +/* Memory-mapped devices */ +#define SUNXI_SYSCON_BASE 0x03000000 +#define SUNXI_CPUCFG_BASE 0x09010000 +#define SUNXI_SID_BASE 0x03006000 +#define SUNXI_DMA_BASE 0x03002000 +#define SUNXI_MSGBOX_BASE 0x03003000 +#define SUNXI_CCU_BASE 0x03001000 +#define SUNXI_PIO_BASE 0x0300b000 +#define SUNXI_SPC_BASE 0x03008000 +#define SUNXI_TIMER_BASE 0x03009000 +#define SUNXI_WDOG_BASE 0x030090a0 +#define SUNXI_THS_BASE 0x05070400 +#define SUNXI_UART0_BASE 0x05000000 +#define SUNXI_UART1_BASE 0x05000400 +#define SUNXI_UART2_BASE 0x05000800 +#define SUNXI_UART3_BASE 0x05000c00 +#define SUNXI_I2C0_BASE 0x05002000 +#define SUNXI_I2C1_BASE 0x05002400 +#define SUNXI_I2C2_BASE 0x05002800 +#define SUNXI_I2C3_BASE 0x05002c00 +#define SUNXI_SPI0_BASE 0x05010000 +#define SUNXI_SPI1_BASE 0x05011000 +#define SUNXI_SCU_BASE 0x03020000 +#define SUNXI_GICD_BASE 0x03021000 +#define SUNXI_GICC_BASE 0x03022000 +#define SUNXI_R_TIMER_BASE 0x07020000 +#define SUNXI_R_INTC_BASE 0x07021000 +#define SUNXI_R_WDOG_BASE 0x07020400 +#define SUNXI_R_PRCM_BASE 0x07010000 +#define SUNXI_R_TWD_BASE 0x07020800 +#define SUNXI_R_CPUCFG_BASE 0x07000400 +#define SUNXI_R_I2C_BASE 0x07081400 +#define SUNXI_R_RSB_BASE 0x07083000 +#define SUNXI_R_UART_BASE 0x07080000 +#define SUNXI_R_PIO_BASE 0x07022000 + +#endif /* SUNXI_MMAP_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h new file mode 100644 index 0000000..0f5965b --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_SPC_H +#define SUNXI_SPC_H + +#define SUNXI_SPC_NUM_PORTS 14 + +#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p)) +#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p)) +#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p)) + +#endif /* SUNXI_SPC_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h6/platform.mk b/arm-trusted-firmware/plat/allwinner/sun50i_h6/platform.mk new file mode 100644 index 0000000..e13e8cb --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h6/platform.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# The differences between the platform are covered by the include files. +include plat/allwinner/common/allwinner-common.mk + +BL31_SOURCES += drivers/allwinner/axp/axp805.c \ + drivers/allwinner/sunxi_rsb.c + +# Put NOBITS memory in SRAM A1, overwriting U-Boot's SPL. +SEPARATE_NOBITS_REGION := 1 diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c b/arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c new file mode 100644 index 0000000..d298e6b --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018, Icenowy Zheng + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define AXP805_HW_ADDR 0x745 +#define AXP805_RT_ADDR 0x3a + +static enum pmic_type { + UNKNOWN, + AXP805, +} pmic; + +int axp_read(uint8_t reg) +{ + return rsb_read(AXP805_RT_ADDR, reg); +} + +int axp_write(uint8_t reg, uint8_t val) +{ + return rsb_write(AXP805_RT_ADDR, reg, val); +} + +static int rsb_init(void) +{ + int ret; + + ret = rsb_init_controller(); + if (ret) + return ret; + + /* Switch to the recommended 3 MHz bus clock. */ + ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); + if (ret) + return ret; + + /* Initiate an I2C transaction to switch the PMIC to RSB mode. */ + ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8); + if (ret) + return ret; + + /* Associate the 8-bit runtime address with the 12-bit bus address. */ + ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR); + if (ret) + return ret; + + return axp_check_id(); +} + +int sunxi_pmic_setup(uint16_t socid, const void *fdt) +{ + int ret; + + INFO("PMIC: Probing AXP805 on RSB\n"); + + ret = sunxi_init_platform_r_twi(socid, true); + if (ret) + return ret; + + ret = rsb_init(); + if (ret) + return ret; + + /* Switch the AXP805 to master/single-PMIC mode. */ + ret = axp_write(0xff, 0x0); + if (ret) + return ret; + + pmic = AXP805; + axp_setup_regulators(fdt); + + /* Switch the PMIC back to I2C mode. */ + ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C); + if (ret) + return ret; + + return 0; +} + +void sunxi_power_down(void) +{ + switch (pmic) { + case AXP805: + /* (Re-)init RSB in case the rich OS has disabled it. */ + sunxi_init_platform_r_twi(SUNXI_SOC_H6, true); + rsb_init(); + axp_power_off(); + break; + default: + break; + } +} + +void sunxi_cpu_power_off_self(void) +{ + u_register_t mpidr = read_mpidr(); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + /* Enable the CPUIDLE hardware (only really needs to be done once). */ + mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000); + mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001); + + /* Trigger power off for this core. */ + mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core)); +} diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h new file mode 100644 index 0000000..85fbb90 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CCU_H +#define SUNXI_CCU_H + +#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00) + +#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290) + +#endif /* SUNXI_CCU_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h new file mode 100644 index 0000000..dab663b --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CPUCFG_H +#define SUNXI_CPUCFG_H + +#include + +/* c = cluster, n = core */ +#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10) +#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10) +#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_CPUCFG_BASE + 0x0024) +#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x00c0) + +#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4) +#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8) +#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8) + +#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4) +#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4) +#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \ + (c) * 0x10 + (n) * 4) + +#define SUNXI_CPUIDLE_EN_REG (SUNXI_R_CPUCFG_BASE + 0x0100) +#define SUNXI_CORE_CLOSE_REG (SUNXI_R_CPUCFG_BASE + 0x0104) +#define SUNXI_PWR_SW_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0140) +#define SUNXI_CONFIG_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0144) + +#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0 +#define SUNXI_AA64nAA32_OFFSET 24 + +#endif /* SUNXI_CPUCFG_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h new file mode 100644 index 0000000..3b4f4a0 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_MMAP_H +#define SUNXI_MMAP_H + +/* Memory regions */ +#define SUNXI_ROM_BASE 0x00000000 +#define SUNXI_ROM_SIZE 0x00010000 +#define SUNXI_SRAM_BASE 0x00020000 +#define SUNXI_SRAM_SIZE 0x00038000 +#define SUNXI_SRAM_A1_BASE 0x00020000 +#define SUNXI_SRAM_A1_SIZE 0x00008000 +#define SUNXI_SRAM_C_BASE 0x00028000 +#define SUNXI_SRAM_C_SIZE 0x00030000 +#define SUNXI_DEV_BASE 0x01000000 +#define SUNXI_DEV_SIZE 0x09000000 +#define SUNXI_DRAM_BASE 0x40000000 +#define SUNXI_DRAM_VIRT_BASE SUNXI_DRAM_BASE + +/* Memory-mapped devices */ +#define SUNXI_SYSCON_BASE 0x03000000 +#define SUNXI_CCU_BASE 0x03001000 +#define SUNXI_DMA_BASE 0x03002000 +#define SUNXI_SID_BASE 0x03006000 +#define SUNXI_SPC_BASE 0x03008000 +#define SUNXI_WDOG_BASE 0x030090a0 +#define SUNXI_PIO_BASE 0x0300b000 +#define SUNXI_GICD_BASE 0x03021000 +#define SUNXI_GICC_BASE 0x03022000 +#define SUNXI_UART0_BASE 0x05000000 +#define SUNXI_SPI0_BASE 0x05010000 +#define SUNXI_R_CPUCFG_BASE 0x07000400 +#define SUNXI_R_PRCM_BASE 0x07010000 +//#define SUNXI_R_WDOG_BASE 0x07020400 +#define SUNXI_R_WDOG_BASE SUNXI_WDOG_BASE +#define SUNXI_R_PIO_BASE 0x07022000 +#define SUNXI_R_UART_BASE 0x07080000 +#define SUNXI_R_I2C_BASE 0x07081400 +#define SUNXI_R_RSB_BASE 0x07083000 +#define SUNXI_CPUCFG_BASE 0x09010000 + +#endif /* SUNXI_MMAP_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h new file mode 100644 index 0000000..0f5965b --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_SPC_H +#define SUNXI_SPC_H + +#define SUNXI_SPC_NUM_PORTS 14 + +#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p)) +#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p)) +#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p)) + +#endif /* SUNXI_SPC_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/platform.mk b/arm-trusted-firmware/plat/allwinner/sun50i_h616/platform.mk new file mode 100644 index 0000000..fc09af7 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/platform.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2017-2020, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Without a management processor there is no SCPI support. +SUNXI_PSCI_USE_SCPI := 0 +SUNXI_PSCI_USE_NATIVE := 1 + +# The differences between the platforms are covered by the include files. +include plat/allwinner/common/allwinner-common.mk + +# the above could be overwritten on the command line +ifeq (${SUNXI_PSCI_USE_SCPI}, 1) + $(error "H616 does not support SCPI PSCI ops") +endif + +BL31_SOURCES += drivers/allwinner/axp/axp805.c \ + drivers/allwinner/sunxi_rsb.c \ + common/fdt_fixup.c \ + ${AW_PLAT}/${PLAT}/prepare_dtb.c + +$(eval $(call add_define,SUNXI_BL31_IN_DRAM)) diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c b/arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c new file mode 100644 index 0000000..e94b0b4 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +void sunxi_prepare_dtb(void *fdt) +{ + int ret; + + if (fdt == NULL || fdt_check_header(fdt) != 0) { + return; + } + ret = fdt_open_into(fdt, fdt, 0x100000); + if (ret < 0) { + ERROR("Preparing devicetree at %p: error %d\n", fdt, ret); + return; + } + + /* Reserve memory used by Trusted Firmware. */ + if (fdt_add_reserved_memory(fdt, "tf-a@40000000", BL31_BASE, + BL31_LIMIT - BL31_BASE)) { + WARN("Failed to add reserved memory nodes to DT.\n"); + return; + } + + ret = fdt_pack(fdt); + if (ret < 0) { + ERROR("Failed to pack devicetree at %p: error %d\n", + fdt, ret); + } else { + clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt)); + INFO("Changed devicetree to reserve BL31 memory.\n"); + } +} diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c b/arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c new file mode 100644 index 0000000..dd6ebba --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017-2020, ARM Limited. All rights reserved. + * Copyright (c) 2018, Icenowy Zheng + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define AXP305_I2C_ADDR 0x36 +#define AXP305_HW_ADDR 0x745 +#define AXP305_RT_ADDR 0x3a + +static enum pmic_type { + UNKNOWN, + AXP305, +} pmic; + +int axp_read(uint8_t reg) +{ + return rsb_read(AXP305_RT_ADDR, reg); +} + +int axp_write(uint8_t reg, uint8_t val) +{ + return rsb_write(AXP305_RT_ADDR, reg, val); +} + +static int rsb_init(void) +{ + int ret; + + ret = rsb_init_controller(); + if (ret) + return ret; + + /* Switch to the recommended 3 MHz bus clock. */ + ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); + if (ret) + return ret; + + /* Initiate an I2C transaction to switch the PMIC to RSB mode. */ + ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8); + if (ret) + return ret; + + /* Associate the 8-bit runtime address with the 12-bit bus address. */ + ret = rsb_assign_runtime_address(AXP305_HW_ADDR, AXP305_RT_ADDR); + if (ret) + return ret; + + return axp_check_id(); +} + +int sunxi_pmic_setup(uint16_t socid, const void *fdt) +{ + int ret; + + INFO("PMIC: Probing AXP305 on RSB\n"); + + ret = sunxi_init_platform_r_twi(socid, true); + if (ret) { + INFO("Could not init platform bus: %d\n", ret); + return ret; + } + + ret = rsb_init(); + if (ret) { + INFO("Could not init RSB: %d\n", ret); + return ret; + } + + pmic = AXP305; + axp_setup_regulators(fdt); + + /* Switch the PMIC back to I2C mode. */ + ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C); + if (ret) + return ret; + + return 0; +} + +void sunxi_power_down(void) +{ + switch (pmic) { + case AXP305: + /* Re-initialise after rich OS might have used it. */ + sunxi_init_platform_r_twi(SUNXI_SOC_H616, true); + rsb_init(); + axp_power_off(); + break; + default: + break; + } +} + +void sunxi_cpu_power_off_self(void) +{ + u_register_t mpidr = read_mpidr(); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + /* Enable the CPUIDLE hardware (only really needs to be done once). */ + mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000); + mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001); + + /* Trigger power off for this core. */ + mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core)); +} diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h new file mode 100644 index 0000000..0e6b543 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Sipeed + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CCU_H +#define SUNXI_CCU_H + +#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00) + +#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290) + +#endif /* SUNXI_CCU_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h new file mode 100644 index 0000000..9478f32 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 Sipeed + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_CPUCFG_H +#define SUNXI_CPUCFG_H + +#include + +/* c = cluster, n = core */ +#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_C0_CPUXCFG_BASE + 0x0010) +#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_C0_CPUXCFG_BASE + 0x0014) +#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_C0_CPUXCFG_BASE + 0x0024) +#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_C0_CPUXCFG_BASE + 0x00c0) + +#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_C0_CPUXCFG_BASE + 0x0000) +#define SUNXI_CPUCFG_GEN_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0000) +#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8) +#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8) + +#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4) +#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4) +#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \ + (c) * 0x10 + (n) * 4) + +#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_GEN_CTRL_REG0 +#define SUNXI_AA64nAA32_OFFSET 4 + +#endif /* SUNXI_CPUCFG_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h new file mode 100644 index 0000000..a4469b5 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_MMAP_H +#define SUNXI_MMAP_H + +/* Memory regions */ +#define SUNXI_ROM_BASE 0x00000000 +#define SUNXI_ROM_SIZE 0x00010000 +/* + * In fact all SRAM from 0x100000 is SRAM A2. However as it's too big for + * firmware, and the user manual gives a tip on a 2*64K/27*64K partition, + * only use the first 2*64K for firmwares now, with the SPL using the first + * 64K and BL3-1 using the second one. + * + * Only the used 2*64K SRAM is defined here, to prevent a gaint translation + * table to be generated. + */ +#define SUNXI_SRAM_BASE 0x00100000 +#define SUNXI_SRAM_SIZE 0x00020000 +#define SUNXI_SRAM_A1_BASE 0x00100000 +#define SUNXI_SRAM_A1_SIZE 0x00010000 +#define SUNXI_SRAM_A2_BASE 0x00110000 +#define SUNXI_SRAM_A2_BL31_OFFSET 0x00000000 +#define SUNXI_SRAM_A2_SIZE 0x00010000 +#define SUNXI_DEV_BASE 0x01000000 +#define SUNXI_DEV_SIZE 0x09000000 +#define SUNXI_DRAM_BASE 0x40000000 +#define SUNXI_DRAM_VIRT_BASE 0x0a000000 + +/* Memory-mapped devices */ +#define SUNXI_WDOG_BASE 0x020000a0 +#define SUNXI_R_WDOG_BASE SUNXI_WDOG_BASE +#define SUNXI_PIO_BASE 0x02000400 +#define SUNXI_SPC_BASE 0x02000800 +#define SUNXI_CCU_BASE 0x02001000 +#define SUNXI_UART0_BASE 0x02500000 +#define SUNXI_SYSCON_BASE 0x03000000 +#define SUNXI_DMA_BASE 0x03002000 +#define SUNXI_SID_BASE 0x03006000 +#define SUNXI_GICD_BASE 0x03021000 +#define SUNXI_GICC_BASE 0x03022000 +#define SUNXI_SPI0_BASE 0x04025000 +#define SUNXI_R_CPUCFG_BASE 0x07000400 +#define SUNXI_R_PRCM_BASE 0x07010000 +#define SUNXI_R_PIO_BASE 0x07022000 +#define SUNXI_R_UART_BASE 0x07080000 +#define SUNXI_R_I2C_BASE 0x07081400 +#define SUNXI_CPUCFG_BASE 0x08100000 +#define SUNXI_C0_CPUXCFG_BASE 0x09010000 + +#endif /* SUNXI_MMAP_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h new file mode 100644 index 0000000..2c87bca --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021 Sipeed + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_SPC_H +#define SUNXI_SPC_H + +/* Get by REing stock ATF and checking initialization loop boundary */ +#define SUNXI_SPC_NUM_PORTS 11 + +#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p)) +#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p)) +#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p)) + +#endif /* SUNXI_SPC_H */ diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_r329/platform.mk b/arm-trusted-firmware/plat/allwinner/sun50i_r329/platform.mk new file mode 100644 index 0000000..05d7cde --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_r329/platform.mk @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Sipeed +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Without a management processor there is no SCPI support. +SUNXI_PSCI_USE_SCPI := 0 +SUNXI_PSCI_USE_NATIVE := 1 + +# The differences between the platforms are covered by the include files. +include plat/allwinner/common/allwinner-common.mk + +# the above could be overwritten on the command line +ifeq (${SUNXI_PSCI_USE_SCPI}, 1) + $(error "R329 does not support SCPI PSCI ops") +endif + +# Put NOBITS memory in the first 64K of SRAM A2, overwriting U-Boot's SPL. +SEPARATE_NOBITS_REGION := 1 diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c b/arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c new file mode 100644 index 0000000..96a24d5 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Sipeed + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +int sunxi_pmic_setup(uint16_t socid, const void *fdt) +{ + /* Currently known hardware has no PMIC */ + + return 0; +} + +void sunxi_power_down(void) +{ +} + +void sunxi_cpu_power_off_self(void) +{ + /* TODO: It's still unknown whether CPUIDLE exists on R329 */ +} diff --git a/arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c b/arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c new file mode 100644 index 0000000..8cc9d69 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; +static image_info_t bl30_image_info; +static image_info_t bl301_image_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc != 0U) + return next_image_info; + + return NULL; +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +struct axg_bl31_param { + 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; + image_info_t *scp_image_info[]; +}; + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct axg_bl31_param *from_bl2; + + /* Initialize the console to provide early debug support */ + aml_console_init(); + + from_bl2 = (struct axg_bl31_param *)arg0; + + /* Check params passed from BL2 are not NULL. */ + assert(from_bl2 != NULL); + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + + /* + * Copy BL32 and BL33 entry point information. It is stored in Secure + * RAM, in BL2's address space. + */ + bl32_image_ep_info = *from_bl2->bl32_ep_info; + bl33_image_ep_info = *from_bl2->bl33_ep_info; + +#if AML_USE_ATOS + /* + * BL2 is unconditionally setting 0 (OPTEE_AARCH64) in arg0 even when + * the BL32 image is 32bit (OPTEE_AARCH32). This is causing the boot to + * hang when ATOS (32bit Amlogic BL32 binary-only TEE OS) is used. + * + * Hardcode to OPTEE_AARCH32 / MODE_RW_32. + */ + bl32_image_ep_info.args.arg0 = MODE_RW_32; +#endif + + if (bl33_image_ep_info.pc == 0U) { + ERROR("BL31: BL33 entrypoint not obtained from BL2\n"); + panic(); + } + + bl30_image_info = *from_bl2->scp_image_info[0]; + bl301_image_info = *from_bl2->scp_image_info[1]; +} + +void bl31_plat_arch_setup(void) +{ + aml_setup_page_tables(); + + enable_mmu_el3(0); +} + +static inline bool axg_scp_ready(void) +{ + return AML_AO_RTI_SCP_IS_READY(mmio_read_32(AML_AO_RTI_SCP_STAT)); +} + +static inline void axg_scp_boot(void) +{ + aml_scpi_upload_scp_fw(bl30_image_info.image_base, + bl30_image_info.image_size, 0); + aml_scpi_upload_scp_fw(bl301_image_info.image_base, + bl301_image_info.image_size, 1); + while (!axg_scp_ready()) + ; +} + +/******************************************************************************* + * GICv2 driver setup information + ******************************************************************************/ +static const interrupt_prop_t axg_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) +}; + +static const gicv2_driver_data_t axg_gic_data = { + .gicd_base = AML_GICD_BASE, + .gicc_base = AML_GICC_BASE, + .interrupt_props = axg_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(axg_interrupt_props) +}; + +void bl31_platform_setup(void) +{ + aml_mhu_secure_init(); + + gicv2_driver_init(&axg_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + axg_scp_boot(); +} diff --git a/arm-trusted-firmware/plat/amlogic/axg/axg_common.c b/arm-trusted-firmware/plat/amlogic/axg/axg_common.c new file mode 100644 index 0000000..870daf4 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/axg/axg_common.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Platform memory map regions + ******************************************************************************/ +#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \ + AML_NSDRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_NS_SHARE_MEM MAP_REGION_FLAT(AML_NS_SHARE_MEM_BASE, \ + AML_NS_SHARE_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_SEC_SHARE_MEM MAP_REGION_FLAT(AML_SEC_SHARE_MEM_BASE, \ + AML_SEC_SHARE_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \ + AML_SEC_DEVICE0_SIZE, \ + MT_DEVICE | MT_RW) + +#define MAP_GIC_DEVICE MAP_REGION_FLAT(AML_GIC_DEVICE_BASE, \ + AML_GIC_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \ + AML_SEC_DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \ + AML_SEC_DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \ + AML_TZRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +static const mmap_region_t axg_mmap[] = { + MAP_NSDRAM0, + MAP_NS_SHARE_MEM, + MAP_SEC_SHARE_MEM, + MAP_SEC_DEVICE0, + MAP_GIC_DEVICE, + MAP_SEC_DEVICE1, + MAP_SEC_DEVICE2, + MAP_TZRAM, + {0} +}; + +/******************************************************************************* + * Per-image regions + ******************************************************************************/ +#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \ + BL31_END - BL31_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE) + +#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \ + BL_RO_DATA_END - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) + +#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/******************************************************************************* + * Function that sets up the translation tables. + ******************************************************************************/ +void aml_setup_page_tables(void) +{ +#if IMAGE_BL31 + const mmap_region_t axg_bl_mmap[] = { + MAP_BL31, + MAP_BL_CODE, + MAP_BL_RO_DATA, +#if USE_COHERENT_MEM + MAP_BL_COHERENT, +#endif + {0} + }; +#endif + + mmap_add(axg_bl_mmap); + + mmap_add(axg_mmap); + + init_xlat_tables(); +} + +/******************************************************************************* + * Function that returns the system counter frequency + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + mmio_clrbits_32(AML_SYS_CPU_CFG7, PLAT_SYS_CPU_CFG7); + mmio_clrbits_32(AML_AO_TIMESTAMP_CNTL, PLAT_AO_TIMESTAMP_CNTL); + + return AML_OSC24M_CLK_IN_HZ; +} diff --git a/arm-trusted-firmware/plat/amlogic/axg/axg_def.h b/arm-trusted-firmware/plat/amlogic/axg/axg_def.h new file mode 100644 index 0000000..d90681a --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/axg/axg_def.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AXG_DEF_H +#define AXG_DEF_H + +#include + +/******************************************************************************* + * System oscillator + ******************************************************************************/ +#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */ + +/******************************************************************************* + * Memory regions + ******************************************************************************/ +#define AML_NS_SHARE_MEM_BASE UL(0x05000000) +#define AML_NS_SHARE_MEM_SIZE UL(0x00100000) + +#define AML_SEC_SHARE_MEM_BASE UL(0x05200000) +#define AML_SEC_SHARE_MEM_SIZE UL(0x00100000) + +#define AML_GIC_DEVICE_BASE UL(0xFFC00000) +#define AML_GIC_DEVICE_SIZE UL(0x00008000) + +#define AML_NSDRAM0_BASE UL(0x01000000) +#define AML_NSDRAM0_SIZE UL(0x0F000000) + +#define BL31_BASE UL(0x05100000) +#define BL31_SIZE UL(0x00100000) +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +/* Shared memory used for SMC services */ +#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000) +#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000) + +#define AML_SEC_DEVICE0_BASE UL(0xFFD00000) +#define AML_SEC_DEVICE0_SIZE UL(0x00026000) + +#define AML_SEC_DEVICE1_BASE UL(0xFF800000) +#define AML_SEC_DEVICE1_SIZE UL(0x0000A000) + +#define AML_SEC_DEVICE2_BASE UL(0xFF620000) +#define AML_SEC_DEVICE2_SIZE UL(0x00028000) + +#define AML_TZRAM_BASE UL(0xFFFC0000) +#define AML_TZRAM_SIZE UL(0x00020000) + +/* Mailboxes */ +#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xFFFD3800) +#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xFFFD3A00) +#define AML_PSCI_MAILBOX_BASE UL(0xFFFD3F00) + +/******************************************************************************* + * GIC-400 and interrupt handling related constants + ******************************************************************************/ +#define AML_GICD_BASE UL(0xFFC01000) +#define AML_GICC_BASE UL(0xFFC02000) + +#define IRQ_SEC_PHY_TIMER 29 + +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 +#define IRQ_SEC_SGI_8 16 + +/******************************************************************************* + * UART definitions + ******************************************************************************/ +#define AML_UART0_AO_BASE UL(0xFF803000) +#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ +#define AML_UART_BAUDRATE U(115200) + +/******************************************************************************* + * Memory-mapped I/O Registers + ******************************************************************************/ +#define AML_AO_TIMESTAMP_CNTL UL(0xFF8000B4) + +#define AML_SYS_CPU_CFG7 UL(0xFF634664) + +#define AML_AO_RTI_STATUS_REG3 UL(0xFF80001C) +#define AML_AO_RTI_SCP_STAT UL(0xFF80023C) +#define AML_AO_RTI_SCP_READY_OFF U(0x14) +#define AML_A0_RTI_SCP_READY_MASK U(3) +#define AML_AO_RTI_SCP_IS_READY(v) \ + ((((v) >> AML_AO_RTI_SCP_READY_OFF) & \ + AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK) + +#define AML_HIU_MAILBOX_SET_0 UL(0xFF63C404) +#define AML_HIU_MAILBOX_STAT_0 UL(0xFF63C408) +#define AML_HIU_MAILBOX_CLR_0 UL(0xFF63C40C) +#define AML_HIU_MAILBOX_SET_3 UL(0xFF63C428) +#define AML_HIU_MAILBOX_STAT_3 UL(0xFF63C42C) +#define AML_HIU_MAILBOX_CLR_3 UL(0xFF63C430) + +#define AML_SHA_DMA_BASE UL(0xFF63E000) +#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08) +#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x28) + +/******************************************************************************* + * System Monitor Call IDs and arguments + ******************************************************************************/ +#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020) +#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021) + +#define AML_SM_EFUSE_READ U(0x82000030) +#define AML_SM_EFUSE_USER_MAX U(0x82000033) + +#define AML_SM_JTAG_ON U(0x82000040) +#define AML_SM_JTAG_OFF U(0x82000041) +#define AML_SM_GET_CHIP_ID U(0x82000044) + +#define AML_JTAG_STATE_ON U(0) +#define AML_JTAG_STATE_OFF U(1) + +#define AML_JTAG_M3_AO U(0) +#define AML_JTAG_M3_EE U(1) +#define AML_JTAG_A53_AO U(2) +#define AML_JTAG_A53_EE U(3) + +#endif /* AXG_DEF_H */ diff --git a/arm-trusted-firmware/plat/amlogic/axg/axg_pm.c b/arm-trusted-firmware/plat/amlogic/axg/axg_pm.c new file mode 100644 index 0000000..e67f263 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/axg/axg_pm.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 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 "aml_private.h" + +#define SCPI_POWER_ON 0 +#define SCPI_POWER_RETENTION 1 +#define SCPI_POWER_OFF 3 + +#define SCPI_SYSTEM_SHUTDOWN 0 +#define SCPI_SYSTEM_REBOOT 1 + +static uintptr_t axg_sec_entrypoint; + +static void axg_pm_set_reset_addr(u_register_t mpidr, uint64_t value) +{ + unsigned int core = plat_calc_core_pos(mpidr); + uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4); + + mmio_write_64(cpu_mailbox_addr, value); +} + +static void axg_pm_reset(u_register_t mpidr, uint32_t value) +{ + unsigned int core = plat_calc_core_pos(mpidr); + uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8; + + mmio_write_32(cpu_mailbox_addr, value); +} + +static void __dead2 axg_system_reset(void) +{ + u_register_t mpidr = read_mpidr_el1(); + int ret; + + INFO("BL31: PSCI_SYSTEM_RESET\n"); + + ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT); + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret); + panic(); + } + + axg_pm_reset(mpidr, 0); + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n"); + panic(); +} + +static void __dead2 axg_system_off(void) +{ + u_register_t mpidr = read_mpidr_el1(); + int ret; + + INFO("BL31: PSCI_SYSTEM_OFF\n"); + + ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN); + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret); + panic(); + } + + axg_pm_set_reset_addr(mpidr, 0); + axg_pm_reset(mpidr, 0); + + dmbsy(); + wfi(); + + ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n"); + panic(); +} + +static int32_t axg_pwr_domain_on(u_register_t mpidr) +{ + axg_pm_set_reset_addr(mpidr, axg_sec_entrypoint); + aml_scpi_set_css_power_state(mpidr, + SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON); + dmbsy(); + sev(); + + return PSCI_E_SUCCESS; +} + +static void axg_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + axg_pm_set_reset_addr(read_mpidr_el1(), 0); +} + +static void axg_pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + uint32_t system_state = SCPI_POWER_ON; + uint32_t cluster_state = SCPI_POWER_ON; + + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + axg_pm_reset(mpidr, -1); + + gicv2_cpuif_disable(); + + if (target_state->pwr_domain_state[MPIDR_AFFLVL2] == + PLAT_LOCAL_STATE_OFF) + system_state = SCPI_POWER_OFF; + + if (target_state->pwr_domain_state[MPIDR_AFFLVL1] == + PLAT_LOCAL_STATE_OFF) + cluster_state = SCPI_POWER_OFF; + + + aml_scpi_set_css_power_state(mpidr, + SCPI_POWER_OFF, cluster_state, + system_state); +} + +static void __dead2 axg_pwr_domain_pwr_down_wfi(const psci_power_state_t + *target_state) +{ + dsbsy(); + axg_pm_reset(read_mpidr_el1(), 0); + + for (;;) + wfi(); +} + +/******************************************************************************* + * Platform handlers and setup function. + ******************************************************************************/ +static const plat_psci_ops_t axg_ops = { + .pwr_domain_on = axg_pwr_domain_on, + .pwr_domain_on_finish = axg_pwr_domain_on_finish, + .pwr_domain_off = axg_pwr_domain_off, + .pwr_domain_pwr_down_wfi = axg_pwr_domain_pwr_down_wfi, + .system_off = axg_system_off, + .system_reset = axg_system_reset +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + axg_sec_entrypoint = sec_entrypoint; + *psci_ops = &axg_ops; + return 0; +} diff --git a/arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h b/arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h new file mode 100644 index 0000000..c97687e --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include "../axg_def.h" + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE UL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define AML_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define PLAT_SYS_CPU_CFG7 (U(1) << 25) +#define PLAT_AO_TIMESTAMP_CNTL U(0x1ff) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* Local power state for power-down. Valid for CPU and cluster power domains. */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* Memory-related defines */ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS 16 +#define MAX_XLAT_TABLES 8 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/amlogic/axg/platform.mk b/arm-trusted-firmware/plat/amlogic/axg/platform.mk new file mode 100644 index 0000000..3560b0c --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/axg/platform.mk @@ -0,0 +1,95 @@ +# +# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk + +AML_PLAT := plat/amlogic +AML_PLAT_SOC := ${AML_PLAT}/${PLAT} +AML_PLAT_COMMON := ${AML_PLAT}/common + +DOIMAGEPATH ?= tools/amlogic +DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage + +PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \ + -I${AML_PLAT_SOC}/include \ + -I${AML_PLAT_COMMON}/include + +GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + drivers/amlogic/console/aarch64/meson_console.S \ + ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \ + ${AML_PLAT_SOC}/${PLAT}_pm.c \ + ${AML_PLAT_SOC}/${PLAT}_common.c \ + ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \ + ${AML_PLAT_COMMON}/aml_efuse.c \ + ${AML_PLAT_COMMON}/aml_mhu.c \ + ${AML_PLAT_COMMON}/aml_scpi.c \ + ${AML_PLAT_COMMON}/aml_sip_svc.c \ + ${AML_PLAT_COMMON}/aml_thermal.c \ + ${AML_PLAT_COMMON}/aml_topology.c \ + ${AML_PLAT_COMMON}/aml_console.c \ + drivers/amlogic/crypto/sha_dma.c \ + ${XLAT_TABLES_LIB_SRCS} \ + ${GIC_SOURCES} + +# Tune compiler for Cortex-A53 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a53 +endif + +# Build config flags +# ------------------ + +# Enable all errata workarounds for Cortex-A53 +ERRATA_A53_855873 := 1 +ERRATA_A53_819472 := 1 +ERRATA_A53_824069 := 1 +ERRATA_A53_827319 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +AML_USE_ATOS := 0 +$(eval $(call assert_boolean,AML_USE_ATOS)) +$(eval $(call add_define,AML_USE_ATOS)) + +# Verify build config +# ------------------- + +ifneq (${RESET_TO_BL31}, 0) + $(error Error: ${PLAT} needs RESET_TO_BL31=0) +endif + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on ${PLAT}) +endif + +all: ${BUILD_PLAT}/bl31.img +distclean realclean clean: cleanimage + +cleanimage: + ${Q}${MAKE} -C ${DOIMAGEPATH} clean + +${DOIMAGETOOL}: + ${Q}${MAKE} -C ${DOIMAGEPATH} + +${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL} + ${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img + diff --git a/arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S b/arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S new file mode 100644 index 0000000..159c7d1 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_crash_console_flush + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl platform_mem_init + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_reset_handler + .globl plat_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void); + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_calc_core_pos(u_register_t mpidr); + * ----------------------------------------------------- + */ +func plat_calc_core_pos + and x0, x0, #MPIDR_CPU_MASK + ret +endfunc plat_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary(void); + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #AML_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------- + * void platform_mem_init(void); + * --------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, AML_UART0_AO_BASE + mov_imm x1, AML_UART0_AO_CLK_IN_HZ + mov_imm x2, AML_UART_BAUDRATE + b console_meson_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, AML_UART0_AO_BASE + b console_meson_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, AML_UART0_AO_BASE + b console_meson_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * void plat_reset_handler(void); + * --------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/amlogic/common/aml_console.c b/arm-trusted-firmware/plat/amlogic/common/aml_console.c new file mode 100644 index 0000000..e21d707 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aml_console.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019, Carlo Caione + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/******************************************************************************* + * Function that sets up the console + ******************************************************************************/ +static console_t aml_console; + +void aml_console_init(void) +{ + int rc = console_meson_register(AML_UART0_AO_BASE, + AML_UART0_AO_CLK_IN_HZ, + AML_UART_BAUDRATE, + &aml_console); + if (rc == 0) { + /* + * The crash console doesn't use the multi console API, it uses + * the core console functions directly. It is safe to call panic + * and let it print debug information. + */ + panic(); + } + + console_set_scope(&aml_console, + CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME); +} diff --git a/arm-trusted-firmware/plat/amlogic/common/aml_efuse.c b/arm-trusted-firmware/plat/amlogic/common/aml_efuse.c new file mode 100644 index 0000000..00884eb --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aml_efuse.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "aml_private.h" + +#define EFUSE_BASE 0x140 +#define EFUSE_SIZE 0xC0 + +uint64_t aml_efuse_read(void *dst, uint32_t offset, uint32_t size) +{ + if ((uint64_t)(offset + size) > (uint64_t)EFUSE_SIZE) + return 0; + + return aml_scpi_efuse_read(dst, offset + EFUSE_BASE, size); +} + +uint64_t aml_efuse_user_max(void) +{ + return EFUSE_SIZE; +} diff --git a/arm-trusted-firmware/plat/amlogic/common/aml_mhu.c b/arm-trusted-firmware/plat/amlogic/common/aml_mhu.c new file mode 100644 index 0000000..001686a --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aml_mhu.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static DEFINE_BAKERY_LOCK(mhu_lock); + +void aml_mhu_secure_message_start(void) +{ + bakery_lock_get(&mhu_lock); + + while (mmio_read_32(AML_HIU_MAILBOX_STAT_3) != 0) + ; +} + +void aml_mhu_secure_message_send(uint32_t msg) +{ + mmio_write_32(AML_HIU_MAILBOX_SET_3, msg); + + while (mmio_read_32(AML_HIU_MAILBOX_STAT_3) != 0) + ; +} + +uint32_t aml_mhu_secure_message_wait(void) +{ + uint32_t val; + + do { + val = mmio_read_32(AML_HIU_MAILBOX_STAT_0); + } while (val == 0); + + return val; +} + +void aml_mhu_secure_message_end(void) +{ + mmio_write_32(AML_HIU_MAILBOX_CLR_0, 0xFFFFFFFF); + + bakery_lock_release(&mhu_lock); +} + +void aml_mhu_secure_init(void) +{ + bakery_lock_init(&mhu_lock); + + mmio_write_32(AML_HIU_MAILBOX_CLR_3, 0xFFFFFFFF); +} diff --git a/arm-trusted-firmware/plat/amlogic/common/aml_scpi.c b/arm-trusted-firmware/plat/amlogic/common/aml_scpi.c new file mode 100644 index 0000000..c8a6772 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aml_scpi.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +#define SIZE_SHIFT 20 +#define SIZE_MASK 0x1FF +#define SIZE_FWBLK 0x200UL + +/* + * Note: The Amlogic SCP firmware uses the legacy SCPI protocol. + */ +#define SCPI_CMD_SET_CSS_POWER_STATE 0x04 +#define SCPI_CMD_SET_SYS_POWER_STATE 0x08 + +#define SCPI_CMD_JTAG_SET_STATE 0xC0 +#define SCPI_CMD_EFUSE_READ 0xC2 +#define SCPI_CMD_CHIP_ID 0xC6 + +#define SCPI_CMD_COPY_FW 0xd4 +#define SCPI_CMD_SET_FW_ADDR 0xd3 +#define SCPI_CMD_FW_SIZE 0xd2 + +static inline uint32_t aml_scpi_cmd(uint32_t command, uint32_t size) +{ + return command | (size << SIZE_SHIFT); +} + +static void aml_scpi_secure_message_send(uint32_t command, uint32_t size) +{ + aml_mhu_secure_message_send(aml_scpi_cmd(command, size)); +} + +static uint32_t aml_scpi_secure_message_receive(void **message_out, size_t *size_out) +{ + uint32_t response = aml_mhu_secure_message_wait(); + + size_t size = (response >> SIZE_SHIFT) & SIZE_MASK; + + response &= ~(SIZE_MASK << SIZE_SHIFT); + + if (size_out != NULL) + *size_out = size; + + if (message_out != NULL) + *message_out = (void *)AML_MHU_SECURE_SCP_TO_AP_PAYLOAD; + + return response; +} + +void aml_scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state, + uint32_t cluster_state, uint32_t css_state) +{ + uint32_t state = (mpidr & 0x0F) | /* CPU ID */ + ((mpidr & 0xF00) >> 4) | /* Cluster ID */ + (cpu_state << 8) | + (cluster_state << 12) | + (css_state << 16); + + aml_mhu_secure_message_start(); + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, state); + aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_SET_CSS_POWER_STATE, 4)); + aml_mhu_secure_message_wait(); + aml_mhu_secure_message_end(); +} + +uint32_t aml_scpi_sys_power_state(uint64_t system_state) +{ + uint32_t *response; + size_t size; + + aml_mhu_secure_message_start(); + mmio_write_8(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, system_state); + aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_SET_SYS_POWER_STATE, 1)); + aml_scpi_secure_message_receive((void *)&response, &size); + aml_mhu_secure_message_end(); + + return *response; +} + +void aml_scpi_jtag_set_state(uint32_t state, uint8_t select) +{ + assert(state <= AML_JTAG_STATE_OFF); + + if (select > AML_JTAG_A53_EE) { + WARN("BL31: Invalid JTAG select (0x%x).\n", select); + return; + } + + aml_mhu_secure_message_start(); + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, + (state << 8) | (uint32_t)select); + aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_JTAG_SET_STATE, 4)); + aml_mhu_secure_message_wait(); + aml_mhu_secure_message_end(); +} + +uint32_t aml_scpi_efuse_read(void *dst, uint32_t base, uint32_t size) +{ + uint32_t *response; + size_t resp_size; + + if (size > 0x1FC) + return 0; + + aml_mhu_secure_message_start(); + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, base); + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 4, size); + aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_EFUSE_READ, 8)); + aml_scpi_secure_message_receive((void *)&response, &resp_size); + aml_mhu_secure_message_end(); + + /* + * response[0] is the size of the response message. + * response[1 ... N] are the contents. + */ + if (*response != 0) + memcpy(dst, response + 1, *response); + + return *response; +} + +void aml_scpi_unknown_thermal(uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3) +{ + aml_mhu_secure_message_start(); + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x0, arg0); + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x4, arg1); + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x8, arg2); + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0xC, arg3); + aml_mhu_secure_message_send(aml_scpi_cmd(0xC3, 16)); + aml_mhu_secure_message_wait(); + aml_mhu_secure_message_end(); +} + +uint32_t aml_scpi_get_chip_id(uint8_t *obuff, uint32_t osize) +{ + uint32_t *response; + size_t resp_size; + + if ((osize != 16) && (osize != 12)) + return 0; + + aml_mhu_secure_message_start(); + aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_CHIP_ID, osize)); + aml_scpi_secure_message_receive((void *)&response, &resp_size); + aml_mhu_secure_message_end(); + + if (!((resp_size == 16) && (osize == 16)) && + !((resp_size == 0) && (osize == 12))) + return 0; + + memcpy((void *)obuff, (const void *)response, osize); + + return osize; +} + +static inline void aml_scpi_copy_scp_data(uint8_t *data, size_t len) +{ + void *dst = (void *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD; + size_t sz; + + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, len); + aml_scpi_secure_message_send(SCPI_CMD_FW_SIZE, len); + aml_mhu_secure_message_wait(); + + for (sz = 0; sz < len; sz += SIZE_FWBLK) { + memcpy(dst, data + sz, MIN(SIZE_FWBLK, len - sz)); + aml_mhu_secure_message_send(SCPI_CMD_COPY_FW); + } +} + +static inline void aml_scpi_set_scp_addr(uint64_t addr, size_t len) +{ + volatile uint64_t *dst = (uint64_t *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD; + + /* + * It is ok as AML_MHU_SECURE_AP_TO_SCP_PAYLOAD is mapped as + * non cachable + */ + *dst = addr; + aml_scpi_secure_message_send(SCPI_CMD_SET_FW_ADDR, sizeof(addr)); + aml_mhu_secure_message_wait(); + + mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, len); + aml_scpi_secure_message_send(SCPI_CMD_FW_SIZE, len); + aml_mhu_secure_message_wait(); +} + +static inline void aml_scpi_send_fw_hash(uint8_t hash[], size_t len) +{ + void *dst = (void *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD; + + memcpy(dst, hash, len); + aml_mhu_secure_message_send(0xd0); + aml_mhu_secure_message_send(0xd1); + aml_mhu_secure_message_send(0xd5); + aml_mhu_secure_message_end(); +} + +/** + * Upload a FW to SCP. + * + * @param addr: firmware data address + * @param size: size of firmware + * @param send: If set, actually copy the firmware in SCP memory otherwise only + * send the firmware address. + */ +void aml_scpi_upload_scp_fw(uintptr_t addr, size_t size, int send) +{ + struct asd_ctx ctx; + + asd_sha_init(&ctx, ASM_SHA256); + asd_sha_update(&ctx, (void *)addr, size); + asd_sha_finalize(&ctx); + + aml_mhu_secure_message_start(); + if (send == 0) + aml_scpi_set_scp_addr(addr, size); + else + aml_scpi_copy_scp_data((void *)addr, size); + + aml_scpi_send_fw_hash(ctx.digest, sizeof(ctx.digest)); +} diff --git a/arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c b/arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c new file mode 100644 index 0000000..ab4c015 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +struct aml_cpu_info { + uint32_t version; + uint8_t chip_id[16]; +}; + +static int aml_sip_get_chip_id(uint64_t version) +{ + struct aml_cpu_info *info = (void *)AML_SHARE_MEM_OUTPUT_BASE; + uint32_t size; + + if (version > 2) + return -1; + + memset(info, 0, sizeof(struct aml_cpu_info)); + + if (version == 2) { + info->version = 2; + size = 16; + } else { + info->version = 1; + size = 12; + } + + if (aml_scpi_get_chip_id(info->chip_id, size) == 0) + return -1; + + return 0; +} + +/******************************************************************************* + * This function is responsible for handling all SiP calls + ******************************************************************************/ +static uintptr_t aml_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 AML_SM_GET_SHARE_MEM_INPUT_BASE: + SMC_RET1(handle, AML_SHARE_MEM_INPUT_BASE); + + case AML_SM_GET_SHARE_MEM_OUTPUT_BASE: + SMC_RET1(handle, AML_SHARE_MEM_OUTPUT_BASE); + + case AML_SM_EFUSE_READ: + { + void *dst = (void *)AML_SHARE_MEM_OUTPUT_BASE; + uint64_t ret = aml_efuse_read(dst, (uint32_t)x1, x2); + + SMC_RET1(handle, ret); + } + case AML_SM_EFUSE_USER_MAX: + SMC_RET1(handle, aml_efuse_user_max()); + + case AML_SM_JTAG_ON: + aml_scpi_jtag_set_state(AML_JTAG_STATE_ON, x1); + SMC_RET1(handle, 0); + + case AML_SM_JTAG_OFF: + aml_scpi_jtag_set_state(AML_JTAG_STATE_OFF, x1); + SMC_RET1(handle, 0); + + case AML_SM_GET_CHIP_ID: + SMC_RET1(handle, aml_sip_get_chip_id(x1)); + + default: + ERROR("BL31: Unhandled SIP SMC: 0x%08x\n", smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +DECLARE_RT_SVC( + aml_sip_handler, + + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + aml_sip_handler +); diff --git a/arm-trusted-firmware/plat/amlogic/common/aml_thermal.c b/arm-trusted-firmware/plat/amlogic/common/aml_thermal.c new file mode 100644 index 0000000..53ed103 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aml_thermal.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "aml_private.h" + +static int32_t modules_initialized = -1; + +/******************************************************************************* + * Unknown commands related to something thermal-related + ******************************************************************************/ +void aml_thermal_unknown(void) +{ + uint16_t ret; + + if (modules_initialized == -1) { + aml_scpi_efuse_read(&ret, 0, 2); + modules_initialized = ret; + } + + aml_scpi_unknown_thermal(10, 2, /* thermal */ + 13, 1); /* thermalver */ +} diff --git a/arm-trusted-firmware/plat/amlogic/common/aml_topology.c b/arm-trusted-firmware/plat/amlogic/common/aml_topology.c new file mode 100644 index 0000000..0a04c11 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aml_topology.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "aml_private.h" + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first node */ + PLATFORM_CLUSTER0_CORE_COUNT +}; + +/******************************************************************************* + * This function returns the ARM default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) + return -1; + + return plat_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/amlogic/common/include/aml_private.h b/arm-trusted-firmware/plat/amlogic/common/include/aml_private.h new file mode 100644 index 0000000..724f382 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/include/aml_private.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AML_PRIVATE_H +#define AML_PRIVATE_H + +#include +#include + +/* Utility functions */ +unsigned int plat_calc_core_pos(u_register_t mpidr); +void aml_console_init(void); +void aml_setup_page_tables(void); + +/* MHU functions */ +void aml_mhu_secure_message_start(void); +void aml_mhu_secure_message_send(uint32_t msg); +uint32_t aml_mhu_secure_message_wait(void); +void aml_mhu_secure_message_end(void); +void aml_mhu_secure_init(void); + +/* SCPI functions */ +void aml_scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state, + uint32_t cluster_state, uint32_t css_state); +uint32_t aml_scpi_sys_power_state(uint64_t system_state); +void aml_scpi_jtag_set_state(uint32_t state, uint8_t select); +uint32_t aml_scpi_efuse_read(void *dst, uint32_t base, uint32_t size); +void aml_scpi_unknown_thermal(uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3); +void aml_scpi_upload_scp_fw(uintptr_t addr, size_t size, int send); +uint32_t aml_scpi_get_chip_id(uint8_t *obuff, uint32_t osize); + +/* Peripherals */ +void aml_thermal_unknown(void); +uint64_t aml_efuse_read(void *dst, uint32_t offset, uint32_t size); +uint64_t aml_efuse_user_max(void); + +#endif /* AML_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S b/arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S new file mode 100644 index 0000000..d620fcf --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include + +.section .rodata.gic_reg_name, "aS" + +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + + /* GICC registers */ + + mov_imm x17, AML_GICC_BASE + + adr x6, gicc_regs + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] + bl str_in_crash_buf_print + + /* GICD registers */ + + mov_imm x16, AML_GICD_BASE + + 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 + bl asm_print_hex + + 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 /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c b/arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c new file mode 100644 index 0000000..77057a1 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; +static image_info_t bl30_image_info; +static image_info_t bl301_image_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc != 0U) + return next_image_info; + + return NULL; +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +struct g12a_bl31_param { + 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; + image_info_t *scp_image_info[]; +}; + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct g12a_bl31_param *from_bl2; + + /* Initialize the console to provide early debug support */ + aml_console_init(); + + from_bl2 = (struct g12a_bl31_param *)arg0; + + /* Check params passed from BL2 are not NULL. */ + assert(from_bl2 != NULL); + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + + /* + * Copy BL32 and BL33 entry point information. It is stored in Secure + * RAM, in BL2's address space. + */ + bl32_image_ep_info = *from_bl2->bl32_ep_info; + bl33_image_ep_info = *from_bl2->bl33_ep_info; + + if (bl33_image_ep_info.pc == 0U) { + ERROR("BL31: BL33 entrypoint not obtained from BL2\n"); + panic(); + } + + bl30_image_info = *from_bl2->scp_image_info[0]; + bl301_image_info = *from_bl2->scp_image_info[1]; +} + +void bl31_plat_arch_setup(void) +{ + aml_setup_page_tables(); + + enable_mmu_el3(0); +} + +/******************************************************************************* + * GICv2 driver setup information + ******************************************************************************/ +static const interrupt_prop_t g12a_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) +}; + +static const gicv2_driver_data_t g12a_gic_data = { + .gicd_base = AML_GICD_BASE, + .gicc_base = AML_GICC_BASE, + .interrupt_props = g12a_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g12a_interrupt_props) +}; + +void bl31_platform_setup(void) +{ + aml_mhu_secure_init(); + + gicv2_driver_init(&g12a_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} diff --git a/arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c b/arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c new file mode 100644 index 0000000..e74ed04 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Platform memory map regions + ******************************************************************************/ +#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \ + AML_NSDRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_NS_SHARE_MEM MAP_REGION_FLAT(AML_NS_SHARE_MEM_BASE, \ + AML_NS_SHARE_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_SEC_SHARE_MEM MAP_REGION_FLAT(AML_SEC_SHARE_MEM_BASE, \ + AML_SEC_SHARE_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \ + AML_SEC_DEVICE0_SIZE, \ + MT_DEVICE | MT_RW) + +#define MAP_HDCP_RX MAP_REGION_FLAT(AML_HDCP_RX_BASE, \ + AML_HDCP_RX_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_HDCP_TX MAP_REGION_FLAT(AML_HDCP_TX_BASE, \ + AML_HDCP_TX_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_GIC_DEVICE MAP_REGION_FLAT(AML_GIC_DEVICE_BASE, \ + AML_GIC_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \ + AML_SEC_DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \ + AML_SEC_DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \ + AML_TZRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +static const mmap_region_t g12a_mmap[] = { + MAP_NSDRAM0, + MAP_NS_SHARE_MEM, + MAP_SEC_SHARE_MEM, + MAP_SEC_DEVICE0, + MAP_HDCP_RX, + MAP_HDCP_TX, + MAP_GIC_DEVICE, + MAP_SEC_DEVICE1, + MAP_SEC_DEVICE2, + MAP_TZRAM, + {0} +}; + +/******************************************************************************* + * Per-image regions + ******************************************************************************/ +#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \ + BL31_END - BL31_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE) + +#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \ + BL_RO_DATA_END - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) + +#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/******************************************************************************* + * Function that sets up the translation tables. + ******************************************************************************/ +void aml_setup_page_tables(void) +{ +#if IMAGE_BL31 + const mmap_region_t g12a_bl_mmap[] = { + MAP_BL31, + MAP_BL_CODE, + MAP_BL_RO_DATA, +#if USE_COHERENT_MEM + MAP_BL_COHERENT, +#endif + {0} + }; +#endif + + mmap_add(g12a_bl_mmap); + + mmap_add(g12a_mmap); + + init_xlat_tables(); +} + +/******************************************************************************* + * Function that returns the system counter frequency + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + mmio_clrbits_32(AML_SYS_CPU_CFG7, ~0xFDFFFFFF); + mmio_clrbits_32(AML_AO_TIMESTAMP_CNTL, ~0xFFFFFE00); + + return AML_OSC24M_CLK_IN_HZ; +} diff --git a/arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h b/arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h new file mode 100644 index 0000000..d032815 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef G12A_DEF_H +#define G12A_DEF_H + +#include + +/******************************************************************************* + * System oscillator + ******************************************************************************/ +#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */ + +/******************************************************************************* + * Memory regions + ******************************************************************************/ +#define AML_HDCP_RX_BASE UL(0xFFE0D000) +#define AML_HDCP_RX_SIZE UL(0x00002000) + +#define AML_HDCP_TX_BASE UL(0xFFE01000) +#define AML_HDCP_TX_SIZE UL(0x00001000) + +#define AML_NS_SHARE_MEM_BASE UL(0x05000000) +#define AML_NS_SHARE_MEM_SIZE UL(0x00100000) + +#define AML_SEC_SHARE_MEM_BASE UL(0x05200000) +#define AML_SEC_SHARE_MEM_SIZE UL(0x00100000) + +#define AML_GIC_DEVICE_BASE UL(0xFFC00000) +#define AML_GIC_DEVICE_SIZE UL(0x00008000) + +#define AML_NSDRAM0_BASE UL(0x01000000) +#define AML_NSDRAM0_SIZE UL(0x0F000000) + +#define BL31_BASE UL(0x05100000) +#define BL31_SIZE UL(0x00100000) +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +/* Shared memory used for SMC services */ +#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000) +#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000) + +#define AML_SEC_DEVICE0_BASE UL(0xFFD00000) +#define AML_SEC_DEVICE0_SIZE UL(0x00026000) + +#define AML_SEC_DEVICE1_BASE UL(0xFF800000) +#define AML_SEC_DEVICE1_SIZE UL(0x0000A000) + +#define AML_TZRAM_BASE UL(0xFFFA0000) +#define AML_TZRAM_SIZE UL(0x00048000) + +/* Mailboxes */ +#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xFFFE7800) +#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xFFFE7A00) +#define AML_PSCI_MAILBOX_BASE UL(0xFFFE7F00) + +#define AML_SEC_DEVICE2_BASE UL(0xFF620000) +#define AML_SEC_DEVICE2_SIZE UL(0x00028000) + +/******************************************************************************* + * GIC-400 and interrupt handling related constants + ******************************************************************************/ +#define AML_GICD_BASE UL(0xFFC01000) +#define AML_GICC_BASE UL(0xFFC02000) + +#define IRQ_SEC_PHY_TIMER 29 + +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 +#define IRQ_SEC_SGI_8 16 + +/******************************************************************************* + * UART definitions + ******************************************************************************/ +#define AML_UART0_AO_BASE UL(0xFF803000) +#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ +#define AML_UART_BAUDRATE U(115200) + +/******************************************************************************* + * Memory-mapped I/O Registers + ******************************************************************************/ +#define AML_AO_TIMESTAMP_CNTL UL(0xFF8000B4) + +#define AML_SYS_CPU_CFG7 UL(0xFF634664) + +#define AML_AO_RTI_STATUS_REG3 UL(0xFF80001C) +#define AML_AO_RTI_SCP_STAT UL(0xFF80023C) +#define AML_AO_RTI_SCP_READY_OFF U(0x14) +#define AML_A0_RTI_SCP_READY_MASK U(3) +#define AML_AO_RTI_SCP_IS_READY(v) \ + ((((v) >> AML_AO_RTI_SCP_READY_OFF) & \ + AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK) + +#define AML_HIU_MAILBOX_SET_0 UL(0xFF63C404) +#define AML_HIU_MAILBOX_STAT_0 UL(0xFF63C408) +#define AML_HIU_MAILBOX_CLR_0 UL(0xFF63C40C) +#define AML_HIU_MAILBOX_SET_3 UL(0xFF63C428) +#define AML_HIU_MAILBOX_STAT_3 UL(0xFF63C42C) +#define AML_HIU_MAILBOX_CLR_3 UL(0xFF63C430) + +#define AML_SHA_DMA_BASE UL(0xFF63E000) +#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08) +#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x28) + +/******************************************************************************* + * System Monitor Call IDs and arguments + ******************************************************************************/ +#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020) +#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021) + +#define AML_SM_EFUSE_READ U(0x82000030) +#define AML_SM_EFUSE_USER_MAX U(0x82000033) + +#define AML_SM_JTAG_ON U(0x82000040) +#define AML_SM_JTAG_OFF U(0x82000041) +#define AML_SM_GET_CHIP_ID U(0x82000044) + +#define AML_JTAG_STATE_ON U(0) +#define AML_JTAG_STATE_OFF U(1) + +#define AML_JTAG_M3_AO U(0) +#define AML_JTAG_M3_EE U(1) +#define AML_JTAG_A53_AO U(2) +#define AML_JTAG_A53_EE U(3) + +#endif /* G12A_DEF_H */ diff --git a/arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c b/arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c new file mode 100644 index 0000000..c9fe3e9 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +#define SCPI_POWER_ON 0 +#define SCPI_POWER_RETENTION 1 +#define SCPI_POWER_OFF 3 + +#define SCPI_SYSTEM_SHUTDOWN 0 +#define SCPI_SYSTEM_REBOOT 1 + +static uintptr_t g12a_sec_entrypoint; +static volatile uint32_t g12a_cpu0_go; + +static void g12a_pm_set_reset_addr(u_register_t mpidr, uint64_t value) +{ + unsigned int core = plat_calc_core_pos(mpidr); + uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4); + + mmio_write_64(cpu_mailbox_addr, value); +} + +static void g12a_pm_reset(u_register_t mpidr) +{ + unsigned int core = plat_calc_core_pos(mpidr); + uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8; + + mmio_write_32(cpu_mailbox_addr, 0); +} + +static void __dead2 g12a_system_reset(void) +{ + INFO("BL31: PSCI_SYSTEM_RESET\n"); + + u_register_t mpidr = read_mpidr_el1(); + uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3); + int ret; + + NOTICE("BL31: Reboot reason: 0x%x\n", status); + + status &= 0xFFFF0FF0; + + console_flush(); + + mmio_write_32(AML_AO_RTI_STATUS_REG3, status); + + ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT); + + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret); + panic(); + } + + g12a_pm_reset(mpidr); + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n"); + panic(); +} + +static void __dead2 g12a_system_off(void) +{ + INFO("BL31: PSCI_SYSTEM_OFF\n"); + + u_register_t mpidr = read_mpidr_el1(); + int ret; + + ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN); + + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret); + panic(); + } + + g12a_pm_set_reset_addr(mpidr, 0); + g12a_pm_reset(mpidr); + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n"); + panic(); +} + +static int32_t g12a_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core = plat_calc_core_pos(mpidr); + + /* CPU0 can't be turned OFF */ + if (core == AML_PRIMARY_CPU) { + VERBOSE("BL31: Releasing CPU0 from wait loop...\n"); + + g12a_cpu0_go = 1; + flush_dcache_range((uintptr_t)&g12a_cpu0_go, + sizeof(g12a_cpu0_go)); + dsb(); + isb(); + + sev(); + + return PSCI_E_SUCCESS; + } + + g12a_pm_set_reset_addr(mpidr, g12a_sec_entrypoint); + aml_scpi_set_css_power_state(mpidr, + SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON); + dmbsy(); + sev(); + + return PSCI_E_SUCCESS; +} + +static void g12a_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + unsigned int core = plat_calc_core_pos(read_mpidr_el1()); + + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + if (core == AML_PRIMARY_CPU) { + g12a_cpu0_go = 0; + flush_dcache_range((uintptr_t)&g12a_cpu0_go, + sizeof(g12a_cpu0_go)); + dsb(); + isb(); + } + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void g12a_pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = plat_calc_core_pos(mpidr); + + gicv2_cpuif_disable(); + + /* CPU0 can't be turned OFF */ + if (core == AML_PRIMARY_CPU) + return; + + aml_scpi_set_css_power_state(mpidr, + SCPI_POWER_OFF, SCPI_POWER_ON, + SCPI_POWER_ON); +} + +static void __dead2 g12a_pwr_domain_pwr_down_wfi(const psci_power_state_t + *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = plat_calc_core_pos(mpidr); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == AML_PRIMARY_CPU) { + VERBOSE("BL31: CPU0 entering wait loop...\n"); + + while (g12a_cpu0_go == 0) + wfe(); + + VERBOSE("BL31: CPU0 resumed.\n"); + + /* + * Because setting CPU0's warm reset entrypoint through PSCI + * mailbox and/or mmio mapped RVBAR (0xda834650) does not seem + * to work, jump to it manually. + * In order to avoid an assert, MMU has to be disabled. + */ + disable_mmu_el3(); + ((void(*)(void))g12a_sec_entrypoint)(); + } + + dsbsy(); + g12a_pm_set_reset_addr(mpidr, 0); + g12a_pm_reset(mpidr); + + for (;;) + wfi(); +} + +/******************************************************************************* + * Platform handlers and setup function. + ******************************************************************************/ +static const plat_psci_ops_t g12a_ops = { + .pwr_domain_on = g12a_pwr_domain_on, + .pwr_domain_on_finish = g12a_pwr_domain_on_finish, + .pwr_domain_off = g12a_pwr_domain_off, + .pwr_domain_pwr_down_wfi = g12a_pwr_domain_pwr_down_wfi, + .system_off = g12a_system_off, + .system_reset = g12a_system_reset +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + g12a_sec_entrypoint = sec_entrypoint; + *psci_ops = &g12a_ops; + g12a_cpu0_go = 0; + return 0; +} diff --git a/arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h b/arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h new file mode 100644 index 0000000..23d816d --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include "../g12a_def.h" + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE UL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define AML_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* Local power state for power-down. Valid for CPU and cluster power domains. */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* Memory-related defines */ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS 16 +#define MAX_XLAT_TABLES 8 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/amlogic/g12a/platform.mk b/arm-trusted-firmware/plat/amlogic/g12a/platform.mk new file mode 100644 index 0000000..b0c91b0 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/g12a/platform.mk @@ -0,0 +1,91 @@ +# +# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk + +AML_PLAT := plat/amlogic +AML_PLAT_SOC := ${AML_PLAT}/${PLAT} +AML_PLAT_COMMON := ${AML_PLAT}/common + +DOIMAGEPATH ?= tools/amlogic +DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage + +PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \ + -I${AML_PLAT_SOC}/include \ + -I${AML_PLAT_COMMON}/include + +GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + drivers/amlogic/console/aarch64/meson_console.S \ + ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \ + ${AML_PLAT_SOC}/${PLAT}_pm.c \ + ${AML_PLAT_SOC}/${PLAT}_common.c \ + ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \ + ${AML_PLAT_COMMON}/aml_efuse.c \ + ${AML_PLAT_COMMON}/aml_mhu.c \ + ${AML_PLAT_COMMON}/aml_scpi.c \ + ${AML_PLAT_COMMON}/aml_sip_svc.c \ + ${AML_PLAT_COMMON}/aml_thermal.c \ + ${AML_PLAT_COMMON}/aml_topology.c \ + ${AML_PLAT_COMMON}/aml_console.c \ + drivers/amlogic/crypto/sha_dma.c \ + ${XLAT_TABLES_LIB_SRCS} \ + ${GIC_SOURCES} + +# Tune compiler for Cortex-A53 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a53 +endif + +# Build config flags +# ------------------ + +# Enable all errata workarounds for Cortex-A53 +ERRATA_A53_855873 := 1 +ERRATA_A53_819472 := 1 +ERRATA_A53_824069 := 1 +ERRATA_A53_827319 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Verify build config +# ------------------- + +ifneq (${RESET_TO_BL31}, 0) + $(error Error: ${PLAT} needs RESET_TO_BL31=0) +endif + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on ${PLAT}) +endif + +all: ${BUILD_PLAT}/bl31.img +distclean realclean clean: cleanimage + +cleanimage: + ${Q}${MAKE} -C ${DOIMAGEPATH} clean + +${DOIMAGETOOL}: + ${Q}${MAKE} -C ${DOIMAGEPATH} + +${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL} + ${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img + diff --git a/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c new file mode 100644 index 0000000..cc7a1c4 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(type == NON_SECURE); + + next_image_info = &bl33_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc != 0U) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +struct gxbb_bl31_param { + 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; +}; + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct gxbb_bl31_param *from_bl2; + + /* Initialize the console to provide early debug support */ + aml_console_init(); + + /* + * In debug builds, we pass a special value in 'arg1' to verify platform + * parameters from BL2 to BL31. In release builds it's not used. + */ + assert(arg1 == AML_BL31_PLAT_PARAM_VAL); + + /* Check that params passed from BL2 are not NULL. */ + from_bl2 = (struct gxbb_bl31_param *) arg0; + + /* Check params passed from BL2 are not NULL. */ + assert(from_bl2 != NULL); + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + + /* + * Copy BL33 entry point information. It is stored in Secure RAM, in + * BL2's address space. + */ + bl33_image_ep_info = *from_bl2->bl33_ep_info; + + if (bl33_image_ep_info.pc == 0U) { + ERROR("BL31: BL33 entrypoint not obtained from BL2\n"); + panic(); + } +} + +void bl31_plat_arch_setup(void) +{ + aml_setup_page_tables(); + + enable_mmu_el3(0); +} + +/******************************************************************************* + * GICv2 driver setup information + ******************************************************************************/ +static const interrupt_prop_t gxbb_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +static const gicv2_driver_data_t gxbb_gic_data = { + .gicd_base = AML_GICD_BASE, + .gicc_base = AML_GICC_BASE, + .interrupt_props = gxbb_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(gxbb_interrupt_props), +}; + +void bl31_platform_setup(void) +{ + aml_mhu_secure_init(); + + gicv2_driver_init(&gxbb_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + aml_thermal_unknown(); +} diff --git a/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c new file mode 100644 index 0000000..260a347 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Platform memory map regions + ******************************************************************************/ +#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \ + AML_NSDRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_NSDRAM1 MAP_REGION_FLAT(AML_NSDRAM1_BASE, \ + AML_NSDRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \ + AML_SEC_DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \ + AML_SEC_DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \ + AML_TZRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \ + AML_SEC_DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE3 MAP_REGION_FLAT(AML_SEC_DEVICE3_BASE, \ + AML_SEC_DEVICE3_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +static const mmap_region_t gxbb_mmap[] = { + MAP_NSDRAM0, + MAP_NSDRAM1, + MAP_SEC_DEVICE0, + MAP_SEC_DEVICE1, + MAP_TZRAM, + MAP_SEC_DEVICE2, + MAP_SEC_DEVICE3, + {0} +}; + +/******************************************************************************* + * Per-image regions + ******************************************************************************/ +#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \ + BL31_END - BL31_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE) + +#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \ + BL_RO_DATA_END - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) + +#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/******************************************************************************* + * Function that sets up the translation tables. + ******************************************************************************/ +void aml_setup_page_tables(void) +{ +#if IMAGE_BL31 + const mmap_region_t gxbb_bl_mmap[] = { + MAP_BL31, + MAP_BL_CODE, + MAP_BL_RO_DATA, +#if USE_COHERENT_MEM + MAP_BL_COHERENT, +#endif + {0} + }; +#endif + + mmap_add(gxbb_bl_mmap); + + mmap_add(gxbb_mmap); + + init_xlat_tables(); +} + +/******************************************************************************* + * Function that returns the system counter frequency + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + uint32_t val; + + val = mmio_read_32(AML_SYS_CPU_CFG7); + val &= 0xFDFFFFFF; + mmio_write_32(AML_SYS_CPU_CFG7, val); + + val = mmio_read_32(AML_AO_TIMESTAMP_CNTL); + val &= 0xFFFFFE00; + mmio_write_32(AML_AO_TIMESTAMP_CNTL, val); + + return AML_OSC24M_CLK_IN_HZ; +} diff --git a/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h new file mode 100644 index 0000000..fa5e4fa --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GXBB_DEF_H +#define GXBB_DEF_H + +#include + +/******************************************************************************* + * System oscillator + ******************************************************************************/ +#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */ + +/******************************************************************************* + * Memory regions + ******************************************************************************/ +#define AML_NSDRAM0_BASE UL(0x01000000) +#define AML_NSDRAM0_SIZE UL(0x0F000000) + +#define AML_NSDRAM1_BASE UL(0x10000000) +#define AML_NSDRAM1_SIZE UL(0x00100000) + +#define BL31_BASE UL(0x10100000) +#define BL31_SIZE UL(0x000C0000) +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +/* Shared memory used for SMC services */ +#define AML_SHARE_MEM_INPUT_BASE UL(0x100FE000) +#define AML_SHARE_MEM_OUTPUT_BASE UL(0x100FF000) + +#define AML_SEC_DEVICE0_BASE UL(0xC0000000) +#define AML_SEC_DEVICE0_SIZE UL(0x09000000) + +#define AML_SEC_DEVICE1_BASE UL(0xD0040000) +#define AML_SEC_DEVICE1_SIZE UL(0x00008000) + +#define AML_TZRAM_BASE UL(0xD9000000) +#define AML_TZRAM_SIZE UL(0x00014000) +/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */ + +/* Mailboxes */ +#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xD9013800) +#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xD9013A00) +#define AML_PSCI_MAILBOX_BASE UL(0xD9013F00) + +#define AML_TZROM_BASE UL(0xD9040000) +#define AML_TZROM_SIZE UL(0x00010000) + +#define AML_SEC_DEVICE2_BASE UL(0xDA000000) +#define AML_SEC_DEVICE2_SIZE UL(0x00200000) + +#define AML_SEC_DEVICE3_BASE UL(0xDA800000) +#define AML_SEC_DEVICE3_SIZE UL(0x00200000) + +/******************************************************************************* + * GIC-400 and interrupt handling related constants + ******************************************************************************/ +#define AML_GICD_BASE UL(0xC4301000) +#define AML_GICC_BASE UL(0xC4302000) + +#define IRQ_SEC_PHY_TIMER 29 + +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 + +/******************************************************************************* + * UART definitions + ******************************************************************************/ +#define AML_UART0_AO_BASE UL(0xC81004C0) +#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ +#define AML_UART_BAUDRATE U(115200) + +/******************************************************************************* + * Memory-mapped I/O Registers + ******************************************************************************/ +#define AML_AO_TIMESTAMP_CNTL UL(0xC81000B4) + +#define AML_SYS_CPU_CFG7 UL(0xC8834664) + +#define AML_AO_RTI_STATUS_REG3 UL(0xDA10001C) + +#define AML_HIU_MAILBOX_SET_0 UL(0xDA83C404) +#define AML_HIU_MAILBOX_STAT_0 UL(0xDA83C408) +#define AML_HIU_MAILBOX_CLR_0 UL(0xDA83C40C) +#define AML_HIU_MAILBOX_SET_3 UL(0xDA83C428) +#define AML_HIU_MAILBOX_STAT_3 UL(0xDA83C42C) +#define AML_HIU_MAILBOX_CLR_3 UL(0xDA83C430) + +#define AML_SHA_DMA_BASE UL(0xC883E000) +#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08) +#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18) + +/******************************************************************************* + * System Monitor Call IDs and arguments + ******************************************************************************/ +#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020) +#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021) + +#define AML_SM_EFUSE_READ U(0x82000030) +#define AML_SM_EFUSE_USER_MAX U(0x82000033) + +#define AML_SM_JTAG_ON U(0x82000040) +#define AML_SM_JTAG_OFF U(0x82000041) +#define AML_SM_GET_CHIP_ID U(0x82000044) + +#define AML_JTAG_STATE_ON U(0) +#define AML_JTAG_STATE_OFF U(1) + +#define AML_JTAG_M3_AO U(0) +#define AML_JTAG_M3_EE U(1) +#define AML_JTAG_A53_AO U(2) +#define AML_JTAG_A53_EE U(3) + +#endif /* GXBB_DEF_H */ diff --git a/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c new file mode 100644 index 0000000..48bff7b --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +#define SCPI_POWER_ON 0 +#define SCPI_POWER_RETENTION 1 +#define SCPI_POWER_OFF 3 + +#define SCPI_SYSTEM_SHUTDOWN 0 +#define SCPI_SYSTEM_REBOOT 1 + +static uintptr_t gxbb_sec_entrypoint; +static volatile uint32_t gxbb_cpu0_go; + +static void gxbb_program_mailbox(u_register_t mpidr, uint64_t value) +{ + unsigned int core = plat_calc_core_pos(mpidr); + uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4); + + mmio_write_64(cpu_mailbox_addr, value); + flush_dcache_range(cpu_mailbox_addr, sizeof(uint64_t)); +} + +static void __dead2 gxbb_system_reset(void) +{ + INFO("BL31: PSCI_SYSTEM_RESET\n"); + + uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3); + + NOTICE("BL31: Reboot reason: 0x%x\n", status); + + status &= 0xFFFF0FF0; + + console_flush(); + + mmio_write_32(AML_AO_RTI_STATUS_REG3, status); + + int ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT); + + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %u\n", ret); + panic(); + } + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n"); + panic(); +} + +static void __dead2 gxbb_system_off(void) +{ + INFO("BL31: PSCI_SYSTEM_OFF\n"); + + unsigned int ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN); + + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %u\n", ret); + panic(); + } + + gxbb_program_mailbox(read_mpidr_el1(), 0); + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n"); + panic(); +} + +static int32_t gxbb_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core = plat_calc_core_pos(mpidr); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == AML_PRIMARY_CPU) { + VERBOSE("BL31: Releasing CPU0 from wait loop...\n"); + + gxbb_cpu0_go = 1; + flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go)); + dsb(); + isb(); + + sev(); + + return PSCI_E_SUCCESS; + } + + gxbb_program_mailbox(mpidr, gxbb_sec_entrypoint); + aml_scpi_set_css_power_state(mpidr, + SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON); + dmbsy(); + sev(); + + return PSCI_E_SUCCESS; +} + +static void gxbb_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + unsigned int core = plat_calc_core_pos(read_mpidr_el1()); + + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + if (core == AML_PRIMARY_CPU) { + gxbb_cpu0_go = 0; + flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go)); + dsb(); + isb(); + } + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void gxbb_pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = plat_calc_core_pos(mpidr); + uintptr_t addr = AML_PSCI_MAILBOX_BASE + 8 + (core << 4); + + mmio_write_32(addr, 0xFFFFFFFF); + flush_dcache_range(addr, sizeof(uint32_t)); + + gicv2_cpuif_disable(); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == AML_PRIMARY_CPU) + return; + + aml_scpi_set_css_power_state(mpidr, + SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON); +} + +static void __dead2 gxbb_pwr_domain_pwr_down_wfi(const psci_power_state_t + *target_state) +{ + unsigned int core = plat_calc_core_pos(read_mpidr_el1()); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == AML_PRIMARY_CPU) { + VERBOSE("BL31: CPU0 entering wait loop...\n"); + + while (gxbb_cpu0_go == 0) + wfe(); + + VERBOSE("BL31: CPU0 resumed.\n"); + + write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT); + } + + dsbsy(); + + for (;;) + wfi(); +} + +/******************************************************************************* + * Platform handlers and setup function. + ******************************************************************************/ +static const plat_psci_ops_t gxbb_ops = { + .pwr_domain_on = gxbb_pwr_domain_on, + .pwr_domain_on_finish = gxbb_pwr_domain_on_finish, + .pwr_domain_off = gxbb_pwr_domain_off, + .pwr_domain_pwr_down_wfi = gxbb_pwr_domain_pwr_down_wfi, + .system_off = gxbb_system_off, + .system_reset = gxbb_system_reset, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + gxbb_sec_entrypoint = sec_entrypoint; + *psci_ops = &gxbb_ops; + gxbb_cpu0_go = 0; + return 0; +} diff --git a/arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h b/arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h new file mode 100644 index 0000000..a5cbe78 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include "../gxbb_def.h" + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define AML_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978) + +#define PLATFORM_STACK_SIZE UL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define AML_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* Local power state for power-down. Valid for CPU and cluster power domains. */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* Memory-related defines */ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS 12 +#define MAX_XLAT_TABLES 5 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/amlogic/gxbb/platform.mk b/arm-trusted-firmware/plat/amlogic/gxbb/platform.mk new file mode 100644 index 0000000..62384d2 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxbb/platform.mk @@ -0,0 +1,75 @@ +# +# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk + +AML_PLAT := plat/amlogic +AML_PLAT_SOC := ${AML_PLAT}/${PLAT} +AML_PLAT_COMMON := ${AML_PLAT}/common + +PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \ + -I${AML_PLAT_SOC}/include \ + -I${AML_PLAT_COMMON}/include + +GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + drivers/amlogic/console/aarch64/meson_console.S \ + ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \ + ${AML_PLAT_SOC}/${PLAT}_pm.c \ + ${AML_PLAT_SOC}/${PLAT}_common.c \ + ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \ + ${AML_PLAT_COMMON}/aml_efuse.c \ + ${AML_PLAT_COMMON}/aml_mhu.c \ + ${AML_PLAT_COMMON}/aml_scpi.c \ + ${AML_PLAT_COMMON}/aml_sip_svc.c \ + ${AML_PLAT_COMMON}/aml_thermal.c \ + ${AML_PLAT_COMMON}/aml_topology.c \ + ${AML_PLAT_COMMON}/aml_console.c \ + ${XLAT_TABLES_LIB_SRCS} \ + ${GIC_SOURCES} + +# Tune compiler for Cortex-A53 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a53 +endif + +# Build config flags +# ------------------ + +# Enable all errata workarounds for Cortex-A53 +ERRATA_A53_826319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Verify build config +# ------------------- + +ifneq (${RESET_TO_BL31}, 0) + $(error Error: ${PLAT} needs RESET_TO_BL31=0) +endif + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on ${PLAT}) +endif diff --git a/arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c b/arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c new file mode 100644 index 0000000..f581dd1 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl33_image_ep_info; +static image_info_t bl30_image_info; +static image_info_t bl301_image_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(type == NON_SECURE); + + next_image_info = &bl33_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc != 0U) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +struct gxl_bl31_param { + 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; + image_info_t *scp_image_info[]; +}; + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct gxl_bl31_param *from_bl2; + + /* Initialize the console to provide early debug support */ + aml_console_init(); + + /* Check that params passed from BL2 are not NULL. */ + from_bl2 = (struct gxl_bl31_param *) arg0; + + /* Check params passed from BL2 are not NULL. */ + assert(from_bl2 != NULL); + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + + /* + * Copy BL33 entry point information. It is stored in Secure RAM, in + * BL2's address space. + */ + bl33_image_ep_info = *from_bl2->bl33_ep_info; + + if (bl33_image_ep_info.pc == 0U) { + ERROR("BL31: BL33 entrypoint not obtained from BL2\n"); + panic(); + } + + bl30_image_info = *from_bl2->scp_image_info[0]; + bl301_image_info = *from_bl2->scp_image_info[1]; +} + +void bl31_plat_arch_setup(void) +{ + aml_setup_page_tables(); + + enable_mmu_el3(0); +} + +static inline bool gxl_scp_ready(void) +{ + return AML_AO_RTI_SCP_IS_READY(mmio_read_32(AML_AO_RTI_SCP_STAT)); +} + +static inline void gxl_scp_boot(void) +{ + aml_scpi_upload_scp_fw(bl30_image_info.image_base, + bl30_image_info.image_size, 0); + aml_scpi_upload_scp_fw(bl301_image_info.image_base, + bl301_image_info.image_size, 1); + while (!gxl_scp_ready()) + ; +} + +/******************************************************************************* + * GICv2 driver setup information + ******************************************************************************/ +static const interrupt_prop_t gxl_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +static const gicv2_driver_data_t gxl_gic_data = { + .gicd_base = AML_GICD_BASE, + .gicc_base = AML_GICC_BASE, + .interrupt_props = gxl_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(gxl_interrupt_props), +}; + +void bl31_platform_setup(void) +{ + aml_mhu_secure_init(); + + gicv2_driver_init(&gxl_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + gxl_scp_boot(); + + aml_thermal_unknown(); +} diff --git a/arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c b/arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c new file mode 100644 index 0000000..e1d7bfb --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Platform memory map regions + ******************************************************************************/ +#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \ + AML_NSDRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_NSDRAM1 MAP_REGION_FLAT(AML_NSDRAM1_BASE, \ + AML_NSDRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \ + AML_SEC_DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \ + AML_SEC_DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \ + AML_TZRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \ + AML_SEC_DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE3 MAP_REGION_FLAT(AML_SEC_DEVICE3_BASE, \ + AML_SEC_DEVICE3_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +static const mmap_region_t gxl_mmap[] = { + MAP_NSDRAM0, + MAP_NSDRAM1, + MAP_SEC_DEVICE0, + MAP_SEC_DEVICE1, + MAP_TZRAM, + MAP_SEC_DEVICE2, + MAP_SEC_DEVICE3, + {0} +}; + +/******************************************************************************* + * Per-image regions + ******************************************************************************/ +#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \ + BL31_END - BL31_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE) + +#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \ + BL_RO_DATA_END - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) + +#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/******************************************************************************* + * Function that sets up the translation tables. + ******************************************************************************/ +void aml_setup_page_tables(void) +{ +#if IMAGE_BL31 + const mmap_region_t gxl_bl_mmap[] = { + MAP_BL31, + MAP_BL_CODE, + MAP_BL_RO_DATA, +#if USE_COHERENT_MEM + MAP_BL_COHERENT, +#endif + {0} + }; +#endif + + mmap_add(gxl_bl_mmap); + + mmap_add(gxl_mmap); + + init_xlat_tables(); +} + +/******************************************************************************* + * Function that returns the system counter frequency + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + uint32_t val; + + val = mmio_read_32(AML_SYS_CPU_CFG7); + val &= 0xFDFFFFFF; + mmio_write_32(AML_SYS_CPU_CFG7, val); + + val = mmio_read_32(AML_AO_TIMESTAMP_CNTL); + val &= 0xFFFFFE00; + mmio_write_32(AML_AO_TIMESTAMP_CNTL, val); + + return AML_OSC24M_CLK_IN_HZ; +} diff --git a/arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h b/arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h new file mode 100644 index 0000000..f30eb28 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GXL_DEF_H +#define GXL_DEF_H + +#include + +/******************************************************************************* + * System oscillator + ******************************************************************************/ +#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */ + +/******************************************************************************* + * Memory regions + ******************************************************************************/ +#define AML_NSDRAM0_BASE UL(0x01000000) +#define AML_NSDRAM0_SIZE UL(0x0F000000) + +#define AML_NSDRAM1_BASE UL(0x10000000) +#define AML_NSDRAM1_SIZE UL(0x00100000) + +#define BL31_BASE UL(0x05100000) +#define BL31_SIZE UL(0x000C0000) +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +/* Shared memory used for SMC services */ +#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000) +#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000) + +#define AML_SEC_DEVICE0_BASE UL(0xC0000000) +#define AML_SEC_DEVICE0_SIZE UL(0x09000000) + +#define AML_SEC_DEVICE1_BASE UL(0xD0040000) +#define AML_SEC_DEVICE1_SIZE UL(0x00008000) + +#define AML_TZRAM_BASE UL(0xD9000000) +#define AML_TZRAM_SIZE UL(0x00014000) +/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */ + +/* Mailboxes */ +#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xD9013800) +#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xD9013A00) +#define AML_PSCI_MAILBOX_BASE UL(0xD9013F00) + +// * [ 1K] 0xD901_3800 - 0xD901_3BFF Secure Mailbox (3) +// * [ 1K] 0xD901_3400 - 0xD901_37FF High Mailbox (2) * +// * [ 1K] 0xD901_3000 - 0xD901_33FF High Mailbox (1) * + +#define AML_TZROM_BASE UL(0xD9040000) +#define AML_TZROM_SIZE UL(0x00010000) + +#define AML_SEC_DEVICE2_BASE UL(0xDA000000) +#define AML_SEC_DEVICE2_SIZE UL(0x00200000) + +#define AML_SEC_DEVICE3_BASE UL(0xDA800000) +#define AML_SEC_DEVICE3_SIZE UL(0x00200000) + +/******************************************************************************* + * GIC-400 and interrupt handling related constants + ******************************************************************************/ +#define AML_GICD_BASE UL(0xC4301000) +#define AML_GICC_BASE UL(0xC4302000) + +#define IRQ_SEC_PHY_TIMER 29 + +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 + +/******************************************************************************* + * UART definitions + ******************************************************************************/ +#define AML_UART0_AO_BASE UL(0xC81004C0) +#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ +#define AML_UART_BAUDRATE U(115200) + +/******************************************************************************* + * Memory-mapped I/O Registers + ******************************************************************************/ +#define AML_AO_TIMESTAMP_CNTL UL(0xC81000B4) + +#define AML_SYS_CPU_CFG7 UL(0xC8834664) + +#define AML_AO_RTI_STATUS_REG3 UL(0xDA10001C) +#define AML_AO_RTI_SCP_STAT UL(0xDA10023C) +#define AML_AO_RTI_SCP_READY_OFF U(0x14) +#define AML_A0_RTI_SCP_READY_MASK U(3) +#define AML_AO_RTI_SCP_IS_READY(v) \ + ((((v) >> AML_AO_RTI_SCP_READY_OFF) & \ + AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK) + +#define AML_HIU_MAILBOX_SET_0 UL(0xDA83C404) +#define AML_HIU_MAILBOX_STAT_0 UL(0xDA83C408) +#define AML_HIU_MAILBOX_CLR_0 UL(0xDA83C40C) +#define AML_HIU_MAILBOX_SET_3 UL(0xDA83C428) +#define AML_HIU_MAILBOX_STAT_3 UL(0xDA83C42C) +#define AML_HIU_MAILBOX_CLR_3 UL(0xDA83C430) + +#define AML_SHA_DMA_BASE UL(0xC883E000) +#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08) +#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18) + +/******************************************************************************* + * System Monitor Call IDs and arguments + ******************************************************************************/ +#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020) +#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021) + +#define AML_SM_EFUSE_READ U(0x82000030) +#define AML_SM_EFUSE_USER_MAX U(0x82000033) + +#define AML_SM_JTAG_ON U(0x82000040) +#define AML_SM_JTAG_OFF U(0x82000041) +#define AML_SM_GET_CHIP_ID U(0x82000044) + +#define AML_JTAG_STATE_ON U(0) +#define AML_JTAG_STATE_OFF U(1) + +#define AML_JTAG_M3_AO U(0) +#define AML_JTAG_M3_EE U(1) +#define AML_JTAG_A53_AO U(2) +#define AML_JTAG_A53_EE U(3) + +#endif /* GXL_DEF_H */ diff --git a/arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c b/arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c new file mode 100644 index 0000000..433140b --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_private.h" + +#define SCPI_POWER_ON 0 +#define SCPI_POWER_RETENTION 1 +#define SCPI_POWER_OFF 3 + +#define SCPI_SYSTEM_SHUTDOWN 0 +#define SCPI_SYSTEM_REBOOT 1 + +static uintptr_t gxl_sec_entrypoint; +static volatile uint32_t gxl_cpu0_go; + +static void gxl_pm_set_reset_addr(u_register_t mpidr, uint64_t value) +{ + unsigned int core = plat_calc_core_pos(mpidr); + uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4); + + mmio_write_64(cpu_mailbox_addr, value); +} + +static void gxl_pm_reset(u_register_t mpidr) +{ + unsigned int core = plat_calc_core_pos(mpidr); + uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8; + + mmio_write_32(cpu_mailbox_addr, 0); +} + +static void __dead2 gxl_system_reset(void) +{ + INFO("BL31: PSCI_SYSTEM_RESET\n"); + + u_register_t mpidr = read_mpidr_el1(); + uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3); + int ret; + + NOTICE("BL31: Reboot reason: 0x%x\n", status); + + status &= 0xFFFF0FF0; + + console_flush(); + + mmio_write_32(AML_AO_RTI_STATUS_REG3, status); + + ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT); + + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret); + panic(); + } + + gxl_pm_reset(mpidr); + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n"); + panic(); +} + +static void __dead2 gxl_system_off(void) +{ + INFO("BL31: PSCI_SYSTEM_OFF\n"); + + u_register_t mpidr = read_mpidr_el1(); + int ret; + + ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN); + + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret); + panic(); + } + + gxl_pm_set_reset_addr(mpidr, 0); + gxl_pm_reset(mpidr); + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n"); + panic(); +} + +static int32_t gxl_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core = plat_calc_core_pos(mpidr); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == AML_PRIMARY_CPU) { + VERBOSE("BL31: Releasing CPU0 from wait loop...\n"); + + gxl_cpu0_go = 1; + flush_dcache_range((uintptr_t)&gxl_cpu0_go, + sizeof(gxl_cpu0_go)); + dsb(); + isb(); + + sev(); + + return PSCI_E_SUCCESS; + } + + gxl_pm_set_reset_addr(mpidr, gxl_sec_entrypoint); + aml_scpi_set_css_power_state(mpidr, + SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON); + dmbsy(); + sev(); + + return PSCI_E_SUCCESS; +} + +static void gxl_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + unsigned int core = plat_calc_core_pos(read_mpidr_el1()); + + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + if (core == AML_PRIMARY_CPU) { + gxl_cpu0_go = 0; + flush_dcache_range((uintptr_t)&gxl_cpu0_go, + sizeof(gxl_cpu0_go)); + dsb(); + isb(); + } + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void gxl_pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = plat_calc_core_pos(mpidr); + + gicv2_cpuif_disable(); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == AML_PRIMARY_CPU) + return; + + aml_scpi_set_css_power_state(mpidr, + SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON); +} + +static void __dead2 gxl_pwr_domain_pwr_down_wfi(const psci_power_state_t + *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = plat_calc_core_pos(mpidr); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == AML_PRIMARY_CPU) { + VERBOSE("BL31: CPU0 entering wait loop...\n"); + + while (gxl_cpu0_go == 0) + wfe(); + + VERBOSE("BL31: CPU0 resumed.\n"); + + /* + * Because setting CPU0's warm reset entrypoint through PSCI + * mailbox and/or mmio mapped RVBAR (0xda834650) does not seem + * to work, jump to it manually. + * In order to avoid an assert, mmu has to be disabled. + */ + disable_mmu_el3(); + ((void(*)(void))gxl_sec_entrypoint)(); + } + + dsbsy(); + gxl_pm_set_reset_addr(mpidr, 0); + gxl_pm_reset(mpidr); + + for (;;) + wfi(); +} + +/******************************************************************************* + * Platform handlers and setup function. + ******************************************************************************/ +static const plat_psci_ops_t gxl_ops = { + .pwr_domain_on = gxl_pwr_domain_on, + .pwr_domain_on_finish = gxl_pwr_domain_on_finish, + .pwr_domain_off = gxl_pwr_domain_off, + .pwr_domain_pwr_down_wfi = gxl_pwr_domain_pwr_down_wfi, + .system_off = gxl_system_off, + .system_reset = gxl_system_reset, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + gxl_sec_entrypoint = sec_entrypoint; + *psci_ops = &gxl_ops; + gxl_cpu0_go = 0; + return 0; +} diff --git a/arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h b/arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h new file mode 100644 index 0000000..ec64d68 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include "../gxl_def.h" + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE UL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define AML_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* Local power state for power-down. Valid for CPU and cluster power domains. */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* Memory-related defines */ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS 12 +#define MAX_XLAT_TABLES 6 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/amlogic/gxl/platform.mk b/arm-trusted-firmware/plat/amlogic/gxl/platform.mk new file mode 100644 index 0000000..641d177 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/gxl/platform.mk @@ -0,0 +1,91 @@ +# +# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk + +AML_PLAT := plat/amlogic +AML_PLAT_SOC := ${AML_PLAT}/${PLAT} +AML_PLAT_COMMON := ${AML_PLAT}/common + +DOIMAGEPATH ?= tools/amlogic +DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage + +PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \ + -I${AML_PLAT_SOC}/include \ + -I${AML_PLAT_COMMON}/include + +GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + drivers/amlogic/console/aarch64/meson_console.S \ + ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \ + ${AML_PLAT_SOC}/${PLAT}_pm.c \ + ${AML_PLAT_SOC}/${PLAT}_common.c \ + ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \ + ${AML_PLAT_COMMON}/aml_efuse.c \ + ${AML_PLAT_COMMON}/aml_mhu.c \ + ${AML_PLAT_COMMON}/aml_scpi.c \ + ${AML_PLAT_COMMON}/aml_sip_svc.c \ + ${AML_PLAT_COMMON}/aml_thermal.c \ + ${AML_PLAT_COMMON}/aml_topology.c \ + ${AML_PLAT_COMMON}/aml_console.c \ + drivers/amlogic/crypto/sha_dma.c \ + ${XLAT_TABLES_LIB_SRCS} \ + ${GIC_SOURCES} + +# Tune compiler for Cortex-A53 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a53 +endif + +# Build config flags +# ------------------ + +# Enable all errata workarounds for Cortex-A53 +ERRATA_A53_855873 := 1 +ERRATA_A53_819472 := 1 +ERRATA_A53_824069 := 1 +ERRATA_A53_827319 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Verify build config +# ------------------- + +ifneq (${RESET_TO_BL31}, 0) + $(error Error: ${PLAT} needs RESET_TO_BL31=0) +endif + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on ${PLAT}) +endif + +all: ${BUILD_PLAT}/bl31.img +distclean realclean clean: cleanimage + +cleanimage: + ${Q}${MAKE} -C ${DOIMAGEPATH} clean + +${DOIMAGETOOL}: + ${Q}${MAKE} -C ${DOIMAGEPATH} + +${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL} + ${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img + diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c new file mode 100644 index 0000000..629c928 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); +} + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c new file mode 100644 index 0000000..1979c50 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c new file mode 100644 index 0000000..a4a0cff --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#define MAP_PERIPHBASE MAP_REGION_FLAT(PERIPHBASE,\ + PERIPH_SIZE,\ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_A5_PERIPHERALS MAP_REGION_FLAT(A5_PERIPHERALS_BASE,\ + A5_PERIPHERALS_SIZE,\ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MAP_PERIPHBASE, + MAP_A5_PERIPHERALS, + MAP_BOOT_RW, + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MAP_PERIPHBASE, + MAP_A5_PERIPHERALS, + MAP_BOOT_RW, + ARM_MAP_NS_DRAM1, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MAP_PERIPHBASE, + MAP_A5_PERIPHERALS, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +unsigned int plat_get_syscnt_freq2(void) +{ + return A5DS_TIMER_BASE_FREQUENCY; +} diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c new file mode 100644 index 0000000..feb9fdf --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * a5ds error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c new file mode 100644 index 0000000..7774002 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int a5ds_pwr_domain_on(u_register_t mpidr) +{ + unsigned int pos = plat_core_pos_by_mpidr(mpidr); + uint64_t *hold_base = (uint64_t *)A5DS_HOLD_BASE; + + hold_base[pos] = A5DS_HOLD_STATE_GO; + dsbish(); + sev(); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void a5ds_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* TODO: This setup is needed only after a cold boot*/ + gicv2_pcpu_distif_init(); + + /* Enable the gic cpu interface */ + gicv2_cpuif_enable(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + * a5ds only has always-on power domain and there is no power control present. + ******************************************************************************/ +void a5ds_pwr_domain_off(const psci_power_state_t *target_state) +{ + ERROR("CPU_OFF not supported on this platform\n"); + assert(false); + panic(); +} + +/******************************************************************************* + * Export the platform handlers via a5ds_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t a5ds_psci_pm_ops = { + /* dummy struct */ + .validate_ns_entrypoint = NULL, + .pwr_domain_on = a5ds_pwr_domain_on, + .pwr_domain_on_finish = a5ds_pwr_domain_on_finish, + .pwr_domain_off = a5ds_pwr_domain_off +}; + +int __init plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *mailbox = (void *)A5DS_TRUSTED_MAILBOX_BASE; + *mailbox = sec_entrypoint; + + *psci_ops = &a5ds_psci_pm_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h new file mode 100644 index 0000000..f577249 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef A5DS_PRIVATE_H +#define A5DS_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void a5ds_config_setup(void); + +#endif /* A5DS_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c new file mode 100644 index 0000000..5593ae0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * The platform currently does not have any security setup. + */ +} diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c new file mode 100644 index 0000000..94fa71f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* The A5DS power domain tree descriptor */ +static const unsigned char a5ds_power_domain_tree_desc[] = { + 1, + /* No of children for the root node */ + A5DS_CLUSTER_COUNT, + /* No of children for the first cluster node */ + A5DS_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the topology according to A5DS_CLUSTER_COUNT. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return a5ds_power_domain_tree_desc; +} + +/******************************************************************************* + * Get core position using mpidr + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= A5DS_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= A5DS_MAX_CPUS_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); + +} diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S b/arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S new file mode 100644 index 0000000..ed7ad9c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Calculate address of our hold entry */ + bl plat_my_core_pos + lsl r0, r0, #A5DS_HOLD_ENTRY_SHIFT + mov_imm r2, A5DS_HOLD_BASE + /* Clear the value stored in the hold address for the specific core */ + mov_imm r3, A5DS_HOLD_STATE_WAIT + str r3, [r2, r0] + dmb ish + + /* Wait until we have a go */ +poll_mailbox: + ldr r1, [r2, r0] + cmp r1, #A5DS_HOLD_STATE_WAIT + beq 1f + mov_imm r0, A5DS_TRUSTED_MAILBOX_BASE + ldr r1, [r0] + bx r1 +1: + wfe + b poll_mailbox +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov r0, #0 + bx lr + +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =MPIDR_AFFINITY_MASK + and r0, r1 + cmp r0, #0 + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * Loads MPIDR in r0 and calls plat_arm_calc_core_pos + * --------------------------------------------------------------------- + */ +func plat_my_core_pos + ldcopr r0, MPIDR + b plat_arm_calc_core_pos + +endfunc plat_my_core_pos + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on A5DS. + * + * (ClusterId * A5DS_MAX_CPUS_PER_CLUSTER * A5DS_MAX_PE_PER_CPU) + + * (CPUId * A5DS_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * A5DS_MAX_CPUS_PER_CLUSTER + CPUId) * A5DS_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov r3, r0 + + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation + */ + tst r0, #MPIDR_MT_MASK + lsleq r3, r0, #MPIDR_AFFINITY_BITS + + /* Extract individual affinity fields from MPIDR */ + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov r3, #A5DS_MAX_CPUS_PER_CLUSTER + mla r1, r2, r3, r1 + mov r3, #A5DS_MAX_PE_PER_CPU + mla r0, r1, r3, r0 + + bx lr +endfunc plat_arm_calc_core_pos diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts b/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts new file mode 100644 index 0000000..b9ff8bf --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x2001300>; + max-size = <0x200>; + id = ; + }; + + hw-config { + load-address = <0x0 0x83000000>; + max-size = <0x01000000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts new file mode 100644 index 0000000..c66186f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h new file mode 100644 index 0000000..9f3df1e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include + +/* Memory location options for TSP */ +#define ARM_DRAM_ID 2 + +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE UL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1) + +#define SRAM_BASE 0x2000000 +#define SRAM_SIZE 0x200000 + +/* The first 4KB of NS DRAM1 are used as shared memory */ +#define A5DS_SHARED_RAM_BASE SRAM_BASE +#define A5DS_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ + +/* The next 252 kB of NS DRAM is used to load the BL images */ +#define ARM_BL_RAM_BASE (A5DS_SHARED_RAM_BASE + \ + A5DS_SHARED_RAM_SIZE) +#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \ + A5DS_SHARED_RAM_SIZE) + +#define PERIPHBASE 0x1a000000 +#define PERIPH_SIZE 0x00240000 +#define A5_PERIPHERALS_BASE 0x1c000000 +#define A5_PERIPHERALS_SIZE 0x10000 + +#define ARM_CACHE_WRITEBACK_SHIFT 5 + +#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_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define A5DS_IRQ_TZ_WDOG 56 +#define A5DS_IRQ_SEC_SYS_TIMER 57 + +/* Default cluster count for A5DS */ +#define A5DS_CLUSTER_COUNT U(1) + +/* Default number of CPUs per cluster on A5DS */ +#define A5DS_MAX_CPUS_PER_CLUSTER U(4) + +/* Default number of threads per CPU on A5DS */ +#define A5DS_MAX_PE_PER_CPU U(1) + +#define A5DS_CORE_COUNT U(4) + +#define A5DS_PRIMARY_CPU 0x0 + +#define BOOT_BASE ARM_DRAM1_BASE +#define BOOT_SIZE UL(0x2800000) + +#define ARM_NS_DRAM1_BASE (ARM_DRAM1_BASE + BOOT_SIZE) +/* + * The last 2MB is meant to be NOLOAD and will not be zero + * initialized. + */ +#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + BOOT_SIZE - \ + 0x00200000) + +#define MAP_BOOT_RW MAP_REGION_FLAT( \ + BOOT_BASE, \ + BOOT_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + A5DS_SHARED_RAM_BASE, \ + A5DS_SHARED_RAM_SIZE, \ + MT_MEMORY | 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_SRAM MAP_REGION_FLAT( \ + SRAM_BASE, \ + SRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* + * 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_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) + +#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 + +/* + * 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 A5DS_TIMER_BASE_FREQUENCY UL(7500000) + +#define ARM_CONSOLE_BAUDRATE 115200 + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * 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 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +/* + * 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) + +/* + * 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 0x00000000 +#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE +/* + * Put BL1 RW at the top of the memory allocated for BL images in NS DRAM. + */ +#define BL1_RW_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + (PLAT_ARM_MAX_BL1_RW_SIZE)) +#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \ + (ARM_BL_RAM_SIZE)) +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ + +/* + * Put BL2 just below BL1. + */ +#define BL2_BASE (BL1_RW_BASE - A5DS_MAX_BL2_SIZE) +#define BL2_LIMIT BL1_RW_BASE + +/* Put BL32 below BL2 in NS DRAM.*/ +#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 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) + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT A5DS_CORE_COUNT +#define PLAT_NUM_PWR_DOMAINS (A5DS_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + U(1) + +#define PLAT_MAX_PWR_LVL 2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ + +#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */ + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x10000 /* 64KB */ + +#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000) + +/* + * Load address of BL33 for this platform port + */ +#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000)) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 6 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000 + +/* + * A5DS_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#define A5DS_MAX_BL2_SIZE 0x11000 + +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current SP_MIN PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL32_SIZE 0x3B000 +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +#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 BOOT_BASE +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE) + +#define PLAT_ARM_NVM_BASE BOOT_BASE +#define PLAT_ARM_NVM_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE 0x1A200000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ UL(7500000) + +#define PLAT_ARM_RUN_UART_BASE 0x1A210000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ UL(7500000) + +#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 A5DS_TIMER_BASE_FREQUENCY UL(7500000) + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID 1 + +/* Mailbox base address */ +#define A5DS_TRUSTED_MAILBOX_BASE A5DS_SHARED_RAM_BASE +#define A5DS_TRUSTED_MAILBOX_SIZE (8 + A5DS_HOLD_SIZE) +#define A5DS_HOLD_BASE (A5DS_TRUSTED_MAILBOX_BASE + 8) +#define A5DS_HOLD_SIZE (PLATFORM_CORE_COUNT * \ + A5DS_HOLD_ENTRY_SIZE) +#define A5DS_HOLD_ENTRY_SHIFT 3 +#define A5DS_HOLD_ENTRY_SIZE (1 << A5DS_HOLD_ENTRY_SHIFT) +#define A5DS_HOLD_STATE_WAIT 0 +#define A5DS_HOLD_STATE_GO 1 + +/* Snoop Control Unit base address */ +#define A5DS_SCU_BASE 0x1C000000 + +/* + * GIC related constants to cater for GICv2 + */ +#define PLAT_ARM_GICD_BASE 0x1C001000 +#define PLAT_ARM_GICC_BASE 0x1C000100 + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(A5DS_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(A5DS_IRQ_SEC_SYS_TIMER,\ + GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/platform.mk b/arm-trusted-firmware/plat/arm/board/a5ds/platform.mk new file mode 100644 index 0000000..4f87306 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/platform.mk @@ -0,0 +1,111 @@ +# +# Copyright (c) 2019-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Firmware Configuration Framework sources +include common/fdt_wrappers.mk +include lib/fconf/fconf.mk + +BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} +BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} + +# Add `libfdt` and Arm common helpers required for Dynamic Config +include lib/libfdt/libfdt.mk + +DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \ + plat/arm/common/arm_dyn_cfg_helpers.c + +DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES} + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +A5DS_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +A5DS_SECURITY_SOURCES := plat/arm/board/a5ds/a5ds_security.c + +PLAT_INCLUDES := -Iplat/arm/board/a5ds/include + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/arm/board/a5ds/a5ds_common.c \ + plat/arm/common/${ARCH}/arm_helpers.S \ + plat/arm/common/arm_common.c \ + plat/arm/common/arm_console.c \ + plat/arm/board/common/${ARCH}/board_arm_helpers.S + +A5DS_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S + +BL1_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + drivers/cfi/v2m/v2m_flash.c \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/board/a5ds/a5ds_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + plat/arm/board/a5ds/${ARCH}/a5ds_helpers.S \ + plat/arm/board/a5ds/a5ds_bl1_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + ${A5DS_CPU_LIBS} \ + ${DYN_CFG_SOURCES} + +BL2_SOURCES += lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/board/a5ds/a5ds_bl2_setup.c \ + plat/arm/common/arm_bl2_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/board/a5ds/a5ds_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \ + plat/arm/common/arm_image_load.c \ + common/desc_image_load.c \ + ${DYN_CFG_SOURCES} \ + ${A5DS_SECURITY_SOURCES} + +# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env) +ifdef UNIX_MK + +FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb + +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) + +$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \ + fdts/$(notdir ${FVP_HW_CONFIG_DTS}))) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG})) + +FDT_SOURCES += plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \ + plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \ + ${FVP_HW_CONFIG_DTS} +endif + +NEED_BL32 := yes + +MULTI_CONSOLE_API := 1 + +PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch32/nonlpae_tables.c + +# Use translation tables library v1 when using Cortex-A5 +ARM_XLAT_TABLES_LIB_V1 := 1 +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) + +$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG)) diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c b/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c new file mode 100644 index 0000000..a951dc7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* enable snoop control unit */ + enable_snoop_ctrl_unit(A5DS_SCU_BASE); +} + +/* + * A5DS will only have one always-on power domain and there + * is no power control present. + */ +void plat_arm_pwrc_setup(void) +{ +} + diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk b/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk new file mode 100644 index 0000000..4b0c97d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2019, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to A5DS platform +BL32_SOURCES += drivers/arm/scu/scu.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + plat/arm/board/a5ds/aarch32/a5ds_helpers.S \ + plat/arm/board/a5ds/a5ds_pm.c \ + plat/arm/board/a5ds/a5ds_topology.c \ + plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c \ + plat/arm/common/sp_min/arm_sp_min_setup.c \ + plat/common/aarch32/platform_mp_stack.S \ + plat/common/plat_psci_common.c \ + ${A5DS_CPU_LIBS} \ + ${A5DS_GIC_SOURCES} \ + ${A5DS_SECURITY_SOURCES} diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S new file mode 100644 index 0000000..20120c9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "../fpga_private.h" + +#include + + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl platform_mem_init + .globl plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_fpga_calc_core_pos + +/* ----------------------------------------------------------------------- + * Indicate a cold boot for every CPU - warm boot is unsupported for the + * holding pen PSCI implementation. + * ----------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + +/* ----------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * ----------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + + /* + * Wait for the primary processor to initialise the .BSS segment + * to avoid a race condition that would erase fpga_valid_mpids + * if it is populated before the C runtime is ready. + * + * We cannot use the current spin-lock implementation until the + * runtime is up and we should not rely on sevl/wfe instructions as + * it is optional whether they are implemented or not, so we use + * a global variable as lock and wait for the primary processor to + * finish the C runtime bring-up. + */ + + ldr w0, =C_RUNTIME_READY_KEY + adrp x1, secondary_core_spinlock + add x1, x1, :lo12:secondary_core_spinlock +1: + wfe + ldr w2, [x1] + cmp w2, w0 + b.ne 1b + /* Prevent reordering of the store into fpga_valid_mpids below */ + dmb ish + + mov x10, x30 + bl plat_my_core_pos + mov x30, x10 + + adrp x4, fpga_valid_mpids + add x4, x4, :lo12:fpga_valid_mpids + mov x5, #VALID_MPID + strb w5, [x4, x0] + + /* + * Poll the CPU's hold entry until it indicates to jump + * to the entrypoint address. + */ + + adrp x1, hold_base + add x1, x1, :lo12:hold_base +poll_hold_entry: + ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT] + cmp x3, #PLAT_FPGA_HOLD_STATE_GO + b.ne 1f + + adrp x2, fpga_sec_entrypoint + add x2, x2, :lo12:fpga_sec_entrypoint + ldr x3, [x2] + br x3 +1: + wfe + b poll_hold_entry + +endfunc plat_secondary_cold_boot_setup + +/* ----------------------------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary cpu + * ----------------------------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #FPGA_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + +func platform_mem_init + ret +endfunc platform_mem_init + +func plat_my_core_pos + ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)) + mrs x0, mpidr_el1 + and x0, x0, x1 + b plat_fpga_calc_core_pos + +endfunc plat_my_core_pos + +/* ----------------------------------------------------------------------- + * unsigned int plat_fpga_calc_core_pos (uint32_t mpid) + * Clobber registers: x0 to x5 + * ----------------------------------------------------------------------- + */ +func plat_fpga_calc_core_pos + /* + * Check for MT bit in MPIDR, which may be either value for images + * running on the FPGA. + * + * If not set, shift MPIDR to left to make it look as if in a + * multi-threaded implementation. + * + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + mov x4, #FPGA_MAX_CPUS_PER_CLUSTER + mov x5, #FPGA_MAX_PE_PER_CPU + + /* Compute linear position */ + madd x1, x2, x4, x1 + madd x0, x1, x5, x0 + + ret +endfunc plat_fpga_calc_core_pos + +func plat_crash_console_init + mov_imm x0, PLAT_FPGA_CRASH_UART_BASE + b console_pl011_core_init +endfunc plat_crash_console_init + +func plat_crash_console_putc + mov_imm x1, PLAT_FPGA_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + +func plat_crash_console_flush + mov_imm x0, PLAT_FPGA_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S new file mode 100644 index 0000000..d8254e5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Linker script for the Arm Ltd. FPGA boards to generate an ELF file that + * contains the ROM trampoline, BL31 and the DTB. + * + * This allows to pass just one file to the uploader tool, and automatically + * provides the correct load addresses. + */ + +#include + +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) + +INPUT(./rom_trampoline.o) +INPUT(./kernel_trampoline.o) + +TARGET(binary) +INPUT(./bl31.bin) +INPUT(./fdts/arm_fpga.dtb) + +ENTRY(_start) + +SECTIONS +{ + .rom (0x0): { + *rom_trampoline.o(.text*) + KEEP(*(.rom)) + } + + .bl31 (BL31_BASE): { + ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned"); + *bl31.bin + } + + .dtb (FPGA_PRELOADED_DTB_BASE): { + ASSERT(. == ALIGN(8), "DTB address is not 8-byte aligned"); + *arm_fpga.dtb + } + + .kern_tramp (PRELOADED_BL33_BASE): { + *kernel_trampoline.o(.text*) + KEEP(*(.kern_tramp)) + } + + /DISCARD/ : { *(stacks) } + /DISCARD/ : { *(.debug_*) } + /DISCARD/ : { *(.note*) } + /DISCARD/ : { *(.comment*) } +} diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c new file mode 100644 index 0000000..e1b3abb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c @@ -0,0 +1,402 @@ +/* + * Copyright (c) 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 "fpga_private.h" +#include +#include + +static entry_point_info_t bl33_image_ep_info; +static unsigned int system_freq; +volatile uint32_t secondary_core_spinlock; + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return 0ULL; +#endif +} + +uint32_t fpga_get_spsr_for_bl33_entry(void) +{ + return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* Add this core to the VALID mpids list */ + fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID; + + /* + * Notify the secondary CPUs that the C runtime is ready + * so they can announce themselves. + */ + secondary_core_spinlock = C_RUNTIME_READY_KEY; + dsbish(); + sev(); + + fpga_console_init(); + + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + /* Set x0-x3 for the primary CPU as expected by the kernel */ + bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE; + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = 0U; + bl33_image_ep_info.args.arg3 = 0U; +} + +void bl31_plat_arch_setup(void) +{ +} + +void bl31_platform_setup(void) +{ + /* Write frequency to CNTCRL and initialize timer */ + generic_delay_timer_init(); + + /* + * Before doing anything else, wait for some time to ensure that + * the secondary CPUs have populated the fpga_valid_mpids array. + * As the number of secondary cores is unknown and can even be 0, + * it is not possible to rely on any signal from them, so use a + * delay instead. + */ + mdelay(5); + + /* + * On the event of a cold reset issued by, for instance, a reset pin + * assertion, we cannot guarantee memory to be initialized to zero. + * In such scenario, if the secondary cores reached + * plat_secondary_cold_boot_setup before the primary one initialized + * .BSS, we could end up having a race condition if the spinlock + * was not cleared before. + * + * Similarly, if there were a reset before the spinlock had been + * cleared, the secondary cores would find the lock opened before + * .BSS is cleared, causing another race condition. + * + * So clean the spinlock as soon as we think it is safe to reduce the + * chances of any race condition on a reset. + */ + secondary_core_spinlock = 0UL; + + /* Initialize the GIC driver, cpu and distributor interfaces */ + plat_fpga_gic_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + next_image_info = &bl33_image_ep_info; + + /* Only expecting BL33: the kernel will run in EL2NS */ + assert(type == NON_SECURE); + + /* None of the images can have 0x0 as the entrypoint */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/* + * Even though we sell the FPGA UART as an SBSA variant, it is actually + * a full fledged PL011. So the baudrate divider registers exist. + */ +#ifndef UARTIBRD +#define UARTIBRD 0x024 +#define UARTFBRD 0x028 +#endif + +/* Round an integer to the closest multiple of a value. */ +static unsigned int round_multiple(unsigned int x, unsigned int multiple) +{ + if (multiple < 2) { + return x; + } + + return ((x + (multiple / 2 - 1)) / multiple) * multiple; +} + +#define PL011_FRAC_SHIFT 6 +#define FPGA_DEFAULT_BAUDRATE 38400 +#define PL011_OVERSAMPLING 16 +static unsigned int pl011_freq_from_divider(unsigned int divider) +{ + unsigned int freq; + + freq = divider * FPGA_DEFAULT_BAUDRATE * PL011_OVERSAMPLING; + + return freq >> PL011_FRAC_SHIFT; +} + +/* + * The FPGAs run most peripherals from one main clock, among them the CPUs, + * the arch timer, and the UART baud base clock. + * The SCP knows this frequency and programs the UART clock divider for a + * 38400 bps baudrate. Recalculate the base input clock from there. + */ +static unsigned int fpga_get_system_frequency(void) +{ + const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; + int node, err; + + /* + * If the arch timer DT node has an explicit clock-frequency property + * set, use that, to allow people overriding auto-detection. + */ + node = fdt_node_offset_by_compatible(fdt, 0, "arm,armv8-timer"); + if (node >= 0) { + uint32_t freq; + + err = fdt_read_uint32(fdt, node, "clock-frequency", &freq); + if (err >= 0) { + return freq; + } + } + + node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011"); + if (node >= 0) { + uintptr_t pl011_base; + unsigned int divider; + + err = fdt_get_reg_props_by_index(fdt, node, 0, + &pl011_base, NULL); + if (err >= 0) { + divider = mmio_read_32(pl011_base + UARTIBRD); + divider <<= PL011_FRAC_SHIFT; + divider += mmio_read_32(pl011_base + UARTFBRD); + + /* + * The result won't be exact, due to rounding errors, + * but the input frequency was a multiple of 250 KHz. + */ + return round_multiple(pl011_freq_from_divider(divider), + 250000); + } else { + WARN("Cannot read PL011 MMIO base\n"); + } + } else { + WARN("No PL011 DT node\n"); + } + + /* No PL011 DT node or calculation failed. */ + return FPGA_DEFAULT_TIMER_FREQUENCY; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + if (system_freq == 0U) { + system_freq = fpga_get_system_frequency(); + } + + return system_freq; +} + +static void fpga_dtb_update_clock(void *fdt, unsigned int freq) +{ + uint32_t freq_dtb = fdt32_to_cpu(freq); + uint32_t phandle; + int node, err; + + node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011"); + if (node < 0) { + WARN("%s(): No PL011 DT node found\n", __func__); + + return; + } + + err = fdt_read_uint32(fdt, node, "clocks", &phandle); + if (err != 0) { + WARN("Cannot find clocks property\n"); + + return; + } + + node = fdt_node_offset_by_phandle(fdt, phandle); + if (node < 0) { + WARN("Cannot get phandle\n"); + + return; + } + + err = fdt_setprop_inplace(fdt, node, + "clock-frequency", + &freq_dtb, + sizeof(freq_dtb)); + if (err < 0) { + WARN("Could not update DT baud clock frequency\n"); + + return; + } +} + +#define CMDLINE_SIGNATURE "CMD:" + +static int fpga_dtb_set_commandline(void *fdt, const char *cmdline) +{ + int chosen; + const char *eol; + char nul = 0; + int slen, err; + + chosen = fdt_add_subnode(fdt, 0, "chosen"); + if (chosen == -FDT_ERR_EXISTS) { + chosen = fdt_path_offset(fdt, "/chosen"); + } + + if (chosen < 0) { + return chosen; + } + + /* + * There is most likely an EOL at the end of the + * command line, make sure we terminate the line there. + * We can't replace the EOL with a NUL byte in the + * source, as this is in read-only memory. So we first + * create the property without any termination, then + * append a single NUL byte. + */ + eol = strchr(cmdline, '\n'); + if (eol == NULL) { + eol = strchr(cmdline, 0); + } + /* Skip the signature and omit the EOL/NUL byte. */ + slen = eol - (cmdline + strlen(CMDLINE_SIGNATURE)); + /* + * Let's limit the size of the property, just in case + * we find the signature by accident. The Linux kernel + * limits to 4096 characters at most (in fact 2048 for + * arm64), so that sounds like a reasonable number. + */ + if (slen > 4095) { + slen = 4095; + } + + err = fdt_setprop(fdt, chosen, "bootargs", + cmdline + strlen(CMDLINE_SIGNATURE), slen); + if (err != 0) { + return err; + } + + return fdt_appendprop(fdt, chosen, "bootargs", &nul, 1); +} + +static void fpga_prepare_dtb(void) +{ + void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; + const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE; + int err; + + err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE); + if (err < 0) { + ERROR("cannot open devicetree at %p: %d\n", fdt, err); + panic(); + } + + /* Reserve memory used by Trusted Firmware. */ + if (fdt_add_reserved_memory(fdt, "tf-a@80000000", BL31_BASE, + BL31_LIMIT - BL31_BASE)) { + WARN("Failed to add reserved memory node to DT\n"); + } + + /* Check for the command line signature. */ + if (!strncmp(cmdline, CMDLINE_SIGNATURE, strlen(CMDLINE_SIGNATURE))) { + err = fpga_dtb_set_commandline(fdt, cmdline); + if (err == 0) { + INFO("using command line at 0x%x\n", + FPGA_PRELOADED_CMD_LINE); + } else { + ERROR("failed to put command line into DTB: %d\n", err); + } + } + + if (err < 0) { + ERROR("Error %d extending Device Tree\n", err); + panic(); + } + + err = fdt_add_cpus_node(fdt, FPGA_MAX_PE_PER_CPU, + FPGA_MAX_CPUS_PER_CLUSTER, + FPGA_MAX_CLUSTER_COUNT); + + if (err == -EEXIST) { + WARN("Not overwriting already existing /cpus node in DTB\n"); + } else { + if (err < 0) { + ERROR("Error %d creating the /cpus DT node\n", err); + panic(); + } else { + unsigned int nr_cores = fpga_get_nr_gic_cores(); + + INFO("Adjusting GICR DT region to cover %u cores\n", + nr_cores); + err = fdt_adjust_gic_redist(fdt, nr_cores, + fpga_get_redist_base(), + fpga_get_redist_size()); + if (err < 0) { + ERROR("Error %d fixing up GIC DT node\n", err); + } + } + } + + fpga_dtb_update_clock(fdt, system_freq); + + /* Check whether we support the SPE PMU. Remove the DT node if not. */ + if (!spe_supported()) { + int node = fdt_node_offset_by_compatible(fdt, 0, + "arm,statistical-profiling-extension-v1"); + + if (node >= 0) { + fdt_del_node(fdt, node); + } + } + + /* Check whether we have an ITS. Remove the DT node if not. */ + if (!fpga_has_its()) { + int node = fdt_node_offset_by_compatible(fdt, 0, + "arm,gic-v3-its"); + + if (node >= 0) { + fdt_del_node(fdt, node); + } + } + + err = fdt_pack(fdt); + if (err < 0) { + ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err); + } + + clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt)); +} + +void bl31_plat_runtime_setup(void) +{ + fpga_prepare_dtb(); +} + +void bl31_plat_enable_mmu(uint32_t flags) +{ + /* TODO: determine if MMU needs to be enabled */ +} diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c new file mode 100644 index 0000000..8c1da62 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include + +static console_t console; + +void fpga_console_init(void) +{ + const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; + uintptr_t base_addr = PLAT_FPGA_CRASH_UART_BASE; + int node; + + /* + * Try to read the UART base address from the DT, by chasing the + * stdout-path property of the chosen node. + * If this does not work, use the crash console address as a fallback. + */ + node = fdt_get_stdout_node_offset(fdt); + if (node >= 0) { + fdt_get_reg_props_by_index(fdt, node, 0, &base_addr, NULL); + } + + (void)console_pl011_register(base_addr, 0, 0, &console); + + console_set_scope(&console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME); +} diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h new file mode 100644 index 0000000..2884ea6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#ifndef FPGA_DEF_H +#define FPGA_DEF_H + +/* + * These are set to large values to account for images describing systems with + * larger cluster configurations. + * + * For cases where the number of clusters, cores or threads is smaller than a + * maximum value below, this does not affect the PSCI functionality as any PEs + * that are present will still be indexed appropriately regardless of any empty + * entries in the array used to represent the topology. + */ + +#define FPGA_MAX_CLUSTER_COUNT 4 +#define FPGA_MAX_CPUS_PER_CLUSTER 8 +#define FPGA_MAX_PE_PER_CPU 4 + +#define FPGA_PRIMARY_CPU 0x0 +/******************************************************************************* + * FPGA image memory map related constants + ******************************************************************************/ + +/* + * UART base address, just for the crash console, as a fallback. + * The actual console UART address is taken from the DT. + */ +#define PLAT_FPGA_CRASH_UART_BASE 0x7ff80000 + +#define FPGA_DEFAULT_TIMER_FREQUENCY 10000000 + +#endif diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c new file mode 100644 index 0000000..e06a9da --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static const interrupt_prop_t fpga_interrupt_props[] = { + PLATFORM_G1S_PROPS(INTR_GROUP1S), + PLATFORM_G0_PROPS(INTR_GROUP0) +}; + +static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT]; +static int nr_itses; + +static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +static gicv3_driver_data_t fpga_gicv3_driver_data = { + .interrupt_props = fpga_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = fpga_rdistif_base_addrs, + .mpidr_to_core_pos = fpga_mpidr_to_core_pos +}; + +void plat_fpga_gic_init(void) +{ + const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE; + uintptr_t gicr_base = 0U; + uint32_t iidr; + int node, ret; + + node = fdt_node_offset_by_compatible(fdt, 0, "arm,gic-v3"); + if (node < 0) { + WARN("No \"arm,gic-v3\" compatible node found in DT, no GIC support.\n"); + return; + } + + /* TODO: Assuming only empty "ranges;" properties up the bus path. */ + ret = fdt_get_reg_props_by_index(fdt, node, 0, + &fpga_gicv3_driver_data.gicd_base, NULL); + if (ret < 0) { + WARN("Could not read GIC distributor address from DT.\n"); + return; + } + + iidr = mmio_read_32(fpga_gicv3_driver_data.gicd_base + GICD_IIDR); + if (((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) || + ((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)) { + unsigned int frame_id; + + /* + * According to the GIC TRMs, if there are any ITSes, they + * start four 64K pages after the distributor. After all + * the ITSes then follow the redistributors. + */ + gicr_base = fpga_gicv3_driver_data.gicd_base + (4U << 16); + + do { + uint64_t its_typer; + + /* Each GIC component can be identified by its ID. */ + frame_id = gicv3_get_component_partnum(gicr_base); + + if (frame_id == PIDR_COMPONENT_ARM_REDIST) { + INFO("Found %d ITSes, redistributors start at 0x%llx\n", + nr_itses, (unsigned long long)gicr_base); + break; + } + + if (frame_id != PIDR_COMPONENT_ARM_ITS) { + WARN("GICv3: found unexpected frame 0x%x\n", + frame_id); + gicr_base = 0U; + break; + } + + /* + * Found an ITS, now work out if it supports virtual + * SGIs (for direct guest injection). If yes, each + * ITS occupies four 64K pages, otherwise just two. + */ + its_typer = mmio_read_64(gicr_base + GITS_TYPER); + if ((its_typer & GITS_TYPER_VSGI) != 0U) { + gicr_base += 4U << 16; + } else { + gicr_base += 2U << 16; + } + nr_itses++; + } while (true); + } + + /* + * If this is not a GIC-600 or -700, or the autodetection above failed, + * use the base address from the device tree. + */ + if (gicr_base == 0U) { + ret = fdt_get_reg_props_by_index(fdt, node, 1, + &fpga_gicv3_driver_data.gicr_base, + NULL); + if (ret < 0) { + WARN("Could not read GIC redistributor address from DT.\n"); + return; + } + } else { + fpga_gicv3_driver_data.gicr_base = gicr_base; + } + + gicv3_driver_init(&fpga_gicv3_driver_data); + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void fpga_pwr_gic_on_finish(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void fpga_pwr_gic_off(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); + gicv3_rdistif_off(plat_my_core_pos()); +} + +unsigned int fpga_get_nr_gic_cores(void) +{ + return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base); +} + +uintptr_t fpga_get_redist_size(void) +{ + uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base + + GICR_TYPER); + + return gicv3_redist_size(typer_val); +} + +uintptr_t fpga_get_redist_base(void) +{ + return fpga_gicv3_driver_data.gicr_base; +} + +bool fpga_has_its(void) +{ + return nr_itses > 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c new file mode 100644 index 0000000..a306a23 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "fpga_private.h" +#include + +/* + * This is a basic PSCI implementation that allows secondary CPUs to be + * released from their initial state and continue to the warm boot entrypoint. + * + * The secondary CPUs are placed in a holding pen and released by calls + * to fpga_pwr_domain_on(mpidr), which updates the hold entry for the CPU + * specified by the mpidr argument - the (polling) target CPU will then branch + * to the BL31 warm boot sequence at the entrypoint address. + * + * Additionally, the secondary CPUs are kept in a low-power wfe() state + * (placed there at the end of each poll) and woken when necessary through + * calls to sev() in fpga_pwr_domain_on(mpidr), once the hold state for the + * relevant CPU has been updated. + * + * Hotplug is currently implemented using a wfi-loop, which removes the + * dependencies on any power controllers or other mechanism that is specific + * to the running system as specified by the FPGA image. + */ + +uint64_t hold_base[PLATFORM_CORE_COUNT]; +uintptr_t fpga_sec_entrypoint; + +/* + * Calls to the CPU specified by the mpidr will set its hold entry to a value + * indicating that it should stop polling and branch off to the warm entrypoint. + */ +static int fpga_pwr_domain_on(u_register_t mpidr) +{ + int pos = plat_core_pos_by_mpidr(mpidr); + unsigned long current_mpidr = read_mpidr_el1(); + + if (pos < 0) { + panic(); + } + + if (mpidr == current_mpidr) { + return PSCI_E_ALREADY_ON; + } + hold_base[pos] = PLAT_FPGA_HOLD_STATE_GO; + flush_dcache_range((uintptr_t)&hold_base[pos], sizeof(uint64_t)); + sev(); /* Wake any CPUs from wfe */ + + return PSCI_E_SUCCESS; +} + +void fpga_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + fpga_pwr_gic_on_finish(); +} + +static void fpga_pwr_domain_off(const psci_power_state_t *target_state) +{ + fpga_pwr_gic_off(); + + while (1) { + wfi(); + } +} + +static void fpga_cpu_standby(plat_local_state_t cpu_state) +{ + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + u_register_t scr = read_scr_el3(); + write_scr_el3(scr|SCR_IRQ_BIT); + dsb(); + wfi(); + write_scr_el3(scr); +} + +plat_psci_ops_t plat_fpga_psci_pm_ops = { + .pwr_domain_on = fpga_pwr_domain_on, + .pwr_domain_on_finish = fpga_pwr_domain_on_finish, + .pwr_domain_off = fpga_pwr_domain_off, + .cpu_standby = fpga_cpu_standby +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + fpga_sec_entrypoint = sec_entrypoint; + flush_dcache_range((uint64_t)&fpga_sec_entrypoint, + sizeof(fpga_sec_entrypoint)); + *psci_ops = &plat_fpga_psci_pm_ops; + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h new file mode 100644 index 0000000..84d651c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FPGA_PRIVATE_H +#define FPGA_PRIVATE_H + +#include "../fpga_def.h" +#include + +#define C_RUNTIME_READY_KEY (0xaa55aa55) +#define VALID_MPID (1U) +#define FPGA_MAX_DTB_SIZE 0x10000 + +#ifndef __ASSEMBLER__ + +extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT]; + +void fpga_console_init(void); + +void plat_fpga_gic_init(void); +void fpga_pwr_gic_on_finish(void); +void fpga_pwr_gic_off(void); +unsigned int plat_fpga_calc_core_pos(uint32_t mpid); +unsigned int fpga_get_nr_gic_cores(void); +uintptr_t fpga_get_redist_size(void); +uintptr_t fpga_get_redist_base(void); +bool fpga_has_its(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* FPGA_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c new file mode 100644 index 0000000..7fead86 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "fpga_private.h" +#include +#include + +unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2]; +unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT]; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + * + * This description of the power domain topology is aligned with the CPU + * indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos() + * APIs. + * + * A description of the topology tree can be found at + * https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design + */ + + if (fpga_power_domain_tree_desc[0] == 0U) { + /* + * As fpga_power_domain_tree_desc[0] == 0, assume that the + * Power Domain Topology Tree has not been initialized, so + * perform the initialization here. + */ + + fpga_power_domain_tree_desc[0] = 1U; + fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT; + + for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) { + fpga_power_domain_tree_desc[2 + i] = + (FPGA_MAX_CPUS_PER_CLUSTER * + FPGA_MAX_PE_PER_CPU); + } + } + + return fpga_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int core_pos; + + mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)); + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + + if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) || + (MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) || + (MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) { + ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr); + panic(); + } + + /* Calculate the core position, based on the maximum topology. */ + core_pos = plat_fpga_calc_core_pos(mpidr); + + /* Check whether this core is actually present. */ + if (fpga_valid_mpids[core_pos] != VALID_MPID) { + return -1; + } + + return core_pos; +} diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S new file mode 100644 index 0000000..44cddeb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +.macro plat_crash_print_regs +.endm + +#endif diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h new file mode 100644 index 0000000..2350d87 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include "../fpga_def.h" + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" + +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE UL(0x800) + +#define CACHE_WRITEBACK_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +#define PLATFORM_CORE_COUNT \ + (FPGA_MAX_CLUSTER_COUNT * \ + FPGA_MAX_CPUS_PER_CLUSTER * \ + FPGA_MAX_PE_PER_CPU) + +#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1) + +#if !ENABLE_PIE +#define BL31_BASE UL(0x80000000) +#define BL31_LIMIT UL(0x80070000) +#else +#define BL31_BASE UL(0x0) +#define BL31_LIMIT UL(0x01000000) +#endif + +#define PLAT_SDEI_NORMAL_PRI 0x70 + +#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 PLATFORM_G1S_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 PLATFORM_G0_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 PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +#define PLAT_FPGA_HOLD_ENTRY_SHIFT 3 +#define PLAT_FPGA_HOLD_STATE_WAIT 0 +#define PLAT_FPGA_HOLD_STATE_GO 1 + +#endif diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S new file mode 100644 index 0000000..f4c08ef --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * The traditional arm64 Linux kernel load address is 512KiB from the + * beginning of DRAM, caused by this having been the default value of the + * kernel's CONFIG_TEXT_OFFSET Kconfig value. + * However kernel version 5.8 changed the default offset (into a 2MB page) + * to 0, so TF-A's default assumption is no longer true. Fortunately the + * kernel got more relaxed about this offset at the same time, so it + * tolerates the wrong offset, but issues a warning: + * [Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader! + * + * We cannot easily change the load address offset in TF-A to be 2MiB, because + * this would break older kernels - and they are not as forgiving in this + * respect. + * + * But we can allow users to load the kernel at the right offset, and + * offer this trampoline here to transition to this new load address. + * Any older kernels, or newer kernels misloaded, will overwrite this code + * here, so it does no harm in this case. + */ + +#include +#include + +.text +.global _tramp_start + +_tramp_start: + adr x4, _tramp_start + orr x4, x4, #0x1fffff + add x4, x4, #1 /* align up to 2MB */ + br x4 diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/platform.mk b/arm-trusted-firmware/plat/arm/board/arm_fpga/platform.mk new file mode 100644 index 0000000..084532c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/platform.mk @@ -0,0 +1,130 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk +include lib/libfdt/libfdt.mk + +RESET_TO_BL31 := 1 +ifeq (${RESET_TO_BL31}, 0) +$(error "This is a BL31-only port; RESET_TO_BL31 must be enabled") +endif + +ifeq (${ENABLE_PIE}, 1) +override SEPARATE_CODE_AND_RODATA := 1 +endif + +CTX_INCLUDE_AARCH32_REGS := 0 +ifeq (${CTX_INCLUDE_AARCH32_REGS}, 1) +$(error "This is an AArch64-only port; CTX_INCLUDE_AARCH32_REGS must be disabled") +endif + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +$(error "TRUSTED_BOARD_BOOT must be disabled") +endif + +PRELOADED_BL33_BASE := 0x80080000 + +FPGA_PRELOADED_DTB_BASE := 0x80070000 +$(eval $(call add_define,FPGA_PRELOADED_DTB_BASE)) + +FPGA_PRELOADED_CMD_LINE := 0x1000 +$(eval $(call add_define,FPGA_PRELOADED_CMD_LINE)) + +ENABLE_AMU := 1 + +# Treating this as a memory-constrained port for now +USE_COHERENT_MEM := 0 + +# This can be overridden depending on CPU(s) used in the FPGA image +HW_ASSISTED_COHERENCY := 1 + +PL011_GENERIC_UART := 1 + +SUPPORT_UNKNOWN_MPID ?= 1 + +FPGA_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +# select a different set of CPU files, depending on whether we compile for +# hardware assisted coherency cores or not +ifeq (${HW_ASSISTED_COHERENCY}, 0) +# Cores used without DSU + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/cortex_a73.S +else +# AArch64-only cores + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a76.S \ + lib/cpus/aarch64/cortex_a76ae.S \ + lib/cpus/aarch64/cortex_a77.S \ + lib/cpus/aarch64/cortex_a78.S \ + lib/cpus/aarch64/neoverse_n_common.S \ + lib/cpus/aarch64/neoverse_n1.S \ + lib/cpus/aarch64/neoverse_n2.S \ + lib/cpus/aarch64/neoverse_e1.S \ + lib/cpus/aarch64/neoverse_v1.S \ + lib/cpus/aarch64/cortex_a78_ae.S \ + lib/cpus/aarch64/cortex_a65.S \ + lib/cpus/aarch64/cortex_a65ae.S \ + lib/cpus/aarch64/cortex_a510.S \ + lib/cpus/aarch64/cortex_a710.S \ + lib/cpus/aarch64/cortex_makalu.S \ + lib/cpus/aarch64/cortex_makalu_elp_arm.S \ + lib/cpus/aarch64/cortex_a78c.S + +# AArch64/AArch32 cores + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a75.S +endif + +ifeq (${SUPPORT_UNKNOWN_MPID}, 1) +# Add support for unknown/invalid MPIDs (aarch64 only) +$(eval $(call add_define,SUPPORT_UNKNOWN_MPID)) + FPGA_CPU_LIBS += lib/cpus/aarch64/generic.S +endif + +# Allow detection of GIC-600 +GICV3_SUPPORT_GIC600 := 1 + +GIC_ENABLE_V4_EXTN := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +FPGA_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/board/arm_fpga/fpga_gicv3.c + +FDT_SOURCES := fdts/arm_fpga.dts + +PLAT_INCLUDES := -Iplat/arm/board/arm_fpga/include + +PLAT_BL_COMMON_SOURCES := plat/arm/board/arm_fpga/${ARCH}/fpga_helpers.S + +BL31_SOURCES += common/fdt_fixup.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/common/plat_psci_common.c \ + plat/arm/board/arm_fpga/fpga_pm.c \ + plat/arm/board/arm_fpga/fpga_topology.c \ + plat/arm/board/arm_fpga/fpga_console.c \ + plat/arm/board/arm_fpga/fpga_bl31_setup.c \ + ${FPGA_CPU_LIBS} \ + ${FPGA_GIC_SOURCES} + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,bl31)) +$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/kernel_trampoline.S,bl31)) +$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,bl31)) + +bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/kernel_trampoline.o ${BUILD_PLAT}/build_axf.ld + $(ECHO) " LD $@" + $(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -s -n -o ${BUILD_PLAT}/bl31.axf + +all: bl31.axf diff --git a/arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S new file mode 100644 index 0000000..cd66c79 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * The Arm Ltd. FPGA images start execution at address 0x0, which is + * mapped at an (emulated) ROM image. The payload uploader can write to + * this memory, but write access by the CPU cores is prohibited. + * + * Provide a simple trampoline to start BL31 execution at the actual + * load address. We put the DTB address in x0, so any code in DRAM could + * make use of that information (not yet used in BL31 right now). + */ + +#include +#include + +.text +.global _start + +_start: + mov_imm x1, BL31_BASE /* beginning of DRAM */ + mov_imm x0, FPGA_PRELOADED_DTB_BASE + br x1 diff --git a/arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S b/arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S new file mode 100644 index 0000000..8c63693 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_report_exception + + + /* ------------------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On FVP platform, it updates the LEDs + * to indicate where we are. + * SYS_LED[0] - 0x0 + * SYS_LED[2:1] - 0x0 + * SYS_LED[7:3] - Exception Mode. + * Clobbers: r0-r1 + * ------------------------------------------------------- + */ +func plat_report_exception + lsl r0, r0, #V2M_SYS_LED_EC_SHIFT + ldr r1, =V2M_SYSREGS_BASE + add r1, r1, #V2M_SYS_LED + str r0, [r1] + bx lr +endfunc plat_report_exception diff --git a/arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S b/arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S new file mode 100644 index 0000000..cde6b00 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_report_exception + + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On FVP platform, it updates the LEDs + * to indicate where we are + * --------------------------------------------- + */ +func plat_report_exception + mrs x1, CurrentEl + lsr x1, x1, #MODE_EL_SHIFT + lsl x1, x1, #V2M_SYS_LED_EL_SHIFT + lsl x0, x0, #V2M_SYS_LED_EC_SHIFT + mov x2, #(SECURE << V2M_SYS_LED_SS_SHIFT) + orr x0, x0, x2 + orr x0, x0, x1 + mov x1, #V2M_SYSREGS_BASE + add x1, x1, #V2M_SYS_LED + str w0, [x1] + ret +endfunc plat_report_exception diff --git a/arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c new file mode 100644 index 0000000..66cc3e9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2015-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 defined(ARM_COT_tbbr) +#include +#elif defined(ARM_COT_dualroot) +#include +#endif + +#if !ARM_CRYPTOCELL_INTEG +#if !ARM_ROTPK_LOCATION_ID + #error "ARM_ROTPK_LOCATION_ID not defined" +#endif +#endif + +#if COT_DESC_IN_DTB && defined(IMAGE_BL2) +uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS]; +#else +uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS] = { + TFW_NVCTR_BASE, + NTFW_CTR_BASE +}; +#endif + + +/* Weak definition may be overridden in specific platform */ +#pragma weak plat_get_nv_ctr +#pragma weak plat_set_nv_ctr + +extern unsigned char arm_rotpk_header[], arm_rotpk_hash_end[]; + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) || ARM_CRYPTOCELL_INTEG +static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN]; +#endif + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) +/* + * Return the ROTPK hash stored in dedicated registers. + */ +int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + uint8_t *dst; + uint32_t *src, tmp; + unsigned int words, i; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + /* Copy the DER header */ + + memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); + dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; + + words = ARM_ROTPK_HASH_LEN >> 2; + + src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + /* Words are read in little endian */ + *dst++ = (uint8_t)(tmp & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + } + + *key_ptr = (void *)rotpk_hash_der; + *key_len = (unsigned int)sizeof(rotpk_hash_der); + *flags = ROTPK_IS_HASH; + return 0; +} +#endif + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \ + (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) +/* + * Return development ROTPK hash generated from ROT_KEY. + */ +int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = arm_rotpk_header; + *key_len = arm_rotpk_hash_end - arm_rotpk_header; + *flags = ROTPK_IS_HASH; + return 0; +} +#endif + +#if ARM_CRYPTOCELL_INTEG +/* + * Return ROTPK hash from CryptoCell. + */ +int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + unsigned char *dst; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + /* Copy the DER header */ + memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); + dst = &rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; + *key_ptr = rotpk_hash_der; + *key_len = sizeof(rotpk_hash_der); + return cc_get_rotpk_hash(dst, ARM_ROTPK_HASH_LEN, flags); +} +#endif + +/* + * Wrapper function for most Arm platforms to get ROTPK hash. + */ +static int get_rotpk_info(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ +#if ARM_CRYPTOCELL_INTEG + return arm_get_rotpk_info_cc(key_ptr, key_len, flags); +#else + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \ + (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) + return arm_get_rotpk_info_dev(key_ptr, key_len, flags); +#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + return arm_get_rotpk_info_regs(key_ptr, key_len, flags); +#else + return 1; +#endif +#endif /* ARM_CRYPTOCELL_INTEG */ +} + +#if defined(ARM_COT_tbbr) + +int arm_get_rotpk_info(void *cookie __unused, void **key_ptr, + unsigned int *key_len, unsigned int *flags) +{ + return get_rotpk_info(key_ptr, key_len, flags); +} + +#elif defined(ARM_COT_dualroot) + +int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + /* + * Return the right root of trust key hash based on the cookie value: + * - NULL means the primary ROTPK. + * - Otherwise, interpret cookie as the OID of the certificate + * extension containing the key. + */ + if (cookie == NULL) { + return get_rotpk_info(key_ptr, key_len, flags); + } else if (strcmp(cookie, PROT_PK_OID) == 0) { + extern unsigned char arm_protpk_hash[]; + extern unsigned char arm_protpk_hash_end[]; + *key_ptr = arm_protpk_hash; + *key_len = arm_protpk_hash_end - arm_protpk_hash; + *flags = ROTPK_IS_HASH; + return 0; + } else { + /* Invalid key ID. */ + return 1; + } +} +#endif + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * will contain the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + const char *oid; + uint32_t *nv_ctr_addr; + + assert(cookie != NULL); + assert(nv_ctr != NULL); + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr, + TRUSTED_NV_CTR_ID); + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr, + NON_TRUSTED_NV_CTR_ID); + } else { + return 1; + } + + *nv_ctr = (unsigned int)(*nv_ctr_addr); + + return 0; +} + +/* + * Store a new non-volatile counter value. By default on ARM development + * platforms, the non-volatile counters are RO and cannot be modified. We expect + * the values in the certificates to always match the RO values so that this + * function is never called. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} diff --git a/arm-trusted-firmware/plat/arm/board/common/board_common.mk b/arm-trusted-firmware/plat/arm/board/common/board_common.mk new file mode 100644 index 0000000..5cdf1bf --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/board_common.mk @@ -0,0 +1,91 @@ +# +# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_BL_COMMON_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/arm/board/common/${ARCH}/board_arm_helpers.S + +BL1_SOURCES += drivers/cfi/v2m/v2m_flash.c + +BL2_SOURCES += drivers/cfi/v2m/v2m_flash.c + +ifneq (${TRUSTED_BOARD_BOOT},0) +ifneq (${ARM_CRYPTOCELL_INTEG}, 1) +# ROTPK hash location +ifeq (${ARM_ROTPK_LOCATION}, regs) + ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID +else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa) + CRYPTO_ALG=rsa + ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID + ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin +$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"')) +$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH) +$(warning Development keys support for FVP is deprecated. Use `regs` \ +option instead) +else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa) + CRYPTO_ALG=ec + ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID + ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin +$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"')) +$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH) +$(warning Development keys support for FVP is deprecated. Use `regs` \ +option instead) +else +$(error "Unsupported ARM_ROTPK_LOCATION value") +endif + +$(eval $(call add_define,ARM_ROTPK_LOCATION_ID)) + +# Force generation of the new hash if ROT_KEY is specified +ifdef ROT_KEY + HASH_PREREQUISITES = $(ROT_KEY) FORCE +else + HASH_PREREQUISITES = $(ROT_KEY) +endif + +$(ARM_ROTPK_HASH) : $(HASH_PREREQUISITES) +ifndef ROT_KEY + $(error Cannot generate hash: no ROT_KEY defined) +endif + openssl ${CRYPTO_ALG} -in $< -pubout -outform DER | openssl dgst \ + -sha256 -binary > $@ + +# Certificate NV-Counters. Use values corresponding to tied off values in +# ARM development platforms +TFW_NVCTR_VAL ?= 31 +NTFW_NVCTR_VAL ?= 223 +else +# Certificate NV-Counters when CryptoCell is integrated. For development +# platforms we set the counter to first valid value. +TFW_NVCTR_VAL ?= 0 +NTFW_NVCTR_VAL ?= 0 +endif +BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c \ + plat/arm/board/common/rotpk/arm_dev_rotpk.S +BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c \ + plat/arm/board/common/rotpk/arm_dev_rotpk.S + +# Allows platform code to provide implementation variants depending on the +# selected chain of trust. +$(eval $(call add_define,ARM_COT_${COT})) + +ifeq (${COT},dualroot) +# Platform Root of Trust key files. +ARM_PROT_KEY := plat/arm/board/common/protpk/arm_protprivk_rsa.pem +ARM_PROTPK_HASH := plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin + +# Provide the private key to cert_create tool. It needs it to sign the images. +PROT_KEY := ${ARM_PROT_KEY} + +$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"')) + +BL1_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S +BL2_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S + +$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH) +$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH) +endif + +endif diff --git a/arm-trusted-firmware/plat/arm/board/common/protpk/README b/arm-trusted-firmware/plat/arm/board/common/protpk/README new file mode 100644 index 0000000..3aca180 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/protpk/README @@ -0,0 +1,14 @@ +This directory contains some development keys to be used as the platform +root-of-trust key. + +* arm_protprivk_rsa.pem is a 2K RSA private key in PEM format. It has been + generated using the openssl command line tool: + + openssl genrsa 2048 > arm_protprivk_rsa.pem + +* arm_protpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key + associated with the above private key. It has been generated using the openssl + command line tool: + + openssl rsa -in arm_protprivk_rsa.pem -pubout -outform DER | \ + openssl dgst -sha256 -binary > arm_protpk_rsa_sha256.bin diff --git a/arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S new file mode 100644 index 0000000..2688cbb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global arm_protpk_hash + .global arm_protpk_hash_end + + .section .rodata.arm_protpk_hash, "a" + +arm_protpk_hash: + /* DER header. */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* Key hash. */ + .incbin ARM_PROTPK_HASH +arm_protpk_hash_end: diff --git a/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin new file mode 100644 index 0000000..587da66 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin @@ -0,0 +1 @@ +œó6{W*…`Ÿtíve×·§è£ €¾PžÆK{9 \ No newline at end of file diff --git a/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem new file mode 100644 index 0000000..eeaad9e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAzR0h/Z4Up17wfuRlYrUWseGDmlGKpl1PflGiYbyVmI7PwTTp +y/T77EiljGp52suLWntHsc0lee50pW16DU2c5bVfmyofau3GjJ1Yqw5XFAahr6eM +/0mkN8utrevvcRT9CP07D+zdhb/WlRUAnedqr/AUHU8BXS+Bxe8P0Z0Z7+DKjYZp +thzXxsjKM02BFFzNwyVrlyBFDkW/53A4M+dpmuWDjAGCJH88W/u0LdmLcii11IzD +/Ofz8Jxc/ZhqL+9FFK4qU+AJp8yXAnACSB46DlNltJrode0y5tmPhtS37ZF7EFb8 +UZWwZVgtuQyuyz9RYUS6jtiGuq6s8GlRwjTe7wIDAQABAoIBAFoWIYeyln+sQxR4 +W88umfkmgxaUGcFX2kIwuJEUst9+WeERzF24C62LeqphWYOvQlVLMAH3iC41fSXr +H2AYZoC9WHBd386nAD1iHj+C3Nv+zaTIgjTdszKOUonAxjl0bm40SmyELAdCaoyv +3MV9jm4Xk74LpR24b9bvWJNH3MxttH9hiYS+n0IzeTXDfO8GrNvHh92zx+jo8yMm +Khhu+TDC9jA2pHpJcF/0EXxYMhwYiQT16nnHb+xMgS4JpalQhvVK01s4VYGHRoFk +K6xh4TIS336LDLyalrGsPlfNfEdx+DimShDIfBUx9Jp3Pp11TUQUz4rhIHB9WdfG +b6bV4wECgYEA+cgPS2TQ7XQ1RJq1S7OGePtBXvnoH226KwGS6Fey8838tLxbblim +MU+EOYs3O66V6U2YpzmIakXo8030k8thY+jKbZl3l0m/hMuPOG66hfE5i7dYsiP4 +atok5wFiNeNYYjHMEayzk53MhG8EOh36msAO7ohKmenONUBA7pk6yTkCgYEA0jhk +HPshwi+wKkx+JLTnuoEgx40tkRgSF2xBqKssMTasaQmX8qG+w9CEs0R8nZCI70Vc +tXSFcidjdkHUVE2WsygIFuS1tbsAnpaxtn3E6rjie30X/Z280+TV0HjR0EMETmwl +ShC5lZ0oP3LpEZfjbR5qs2kFW4MOxA7tjQVaMWcCgYEA5ZbVMBifzdMl70RA5i9C +qEtSQAl3KgRCvar5rKSHsX+iC0Kiy9+iCusq/3WONEZ6NvMDIJpKYFyYDaOW7o5f +m2TrRChu+1lnN5mfsGBfBCTBH0JMvZlAin6ussLb0eqBX+ijyY8zlLjTttsQSJcr +tThZwTj3UVfOGbZQuL+RgEkCgYBXO3U3nXI9vUIx2zoBC1yZRNoQVGITMlTXiWGZ +lyYoadKTZ5q44Sti4BUguounaoGYIEU/OtHhM70PJnPwY53kS/lHXrKUbbvtEwU9 +f+UFraC1s4wP/rOLjgq3jlsqO5T+4dt7Z4NLNUKtSYazeT6zWgrW1f6WIcUv0C38 +9bqegwKBgFCK3Oa5ibL5sPaPQ/1UfdeW4JVuu6A4JhHS7r+cVLsmcrvE1Qv7Wcvw +B5aqXeqLu2dtIN8/f++3tzccs9LXKY/fh72D4TVjfrqOSSZoGTH9l4U5NXbqWM3I +skkAYb2bMST/d1qSyYesgXVNAlaQHRh3vEz8x853nJ3v9OFj8/rW +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S new file mode 100644 index 0000000..06e2a06 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* corstone1000 platform provides custom values for the macros defined in + * arm_def.h , so only platform_def.h needs to be included + */ +#if !defined(TARGET_PLATFORM_FVP) && !defined(TARGET_PLATFORM_FPGA) +#include "plat/arm/common/arm_def.h" +#else +#include +#endif + + .global arm_rotpk_header + .global arm_rotpk_header_end + .section .rodata.arm_rotpk_hash, "a" + +arm_rotpk_header: + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 +arm_rotpk_header_len: + +#ifdef ARM_ROTPK_HASH + .global arm_rotpk_hash_end + .incbin ARM_ROTPK_HASH +arm_rotpk_hash_end: +#endif + +.if ARM_ROTPK_HEADER_LEN != arm_rotpk_header_len - arm_rotpk_header +.error "Invalid ROTPK header length." +.endif diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der new file mode 100644 index 0000000..2547877 Binary files /dev/null and b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der differ diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin new file mode 100644 index 0000000..c5e123a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin @@ -0,0 +1 @@ +.@¿nù»˜1q = ýÑÌiJ˜ë‹ ° †Nl \ No newline at end of file diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der new file mode 100644 index 0000000..661f899 Binary files /dev/null and b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der differ diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin new file mode 100644 index 0000000..7653f7e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin @@ -0,0 +1 @@ +°ó‚ —Ø:7zrGì2sé’2âIYö^‹JJFØ"šÚ \ No newline at end of file diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem new file mode 100644 index 0000000..fb328e3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINSaX6nvzS3teiBJA7WlTLRKJOajpy29o2cArLbUXoZBoAoGCCqGSM49 +AwEHoUQDQgAEm+ZIvTQ44aKk83DhVLsvsFpKDP/Ch9vA+4Hp+fmVfX6gDH8K1OBi +SpRf7FJ9RGPIn2H6xst+a1OtLMWUDRqGkQ== +-----END EC PRIVATE KEY----- diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem new file mode 100644 index 0000000..71410ec --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLLGDVjWPUB3l+ +xxaWvU0kTqyG5rdx48VUC+cUHL0pGsE/erYCqqs2xNk2aWziZcObsb89qFYmy/0E +AbqsPlQyynleu7IF6gZY8nS64fSHwBkKH2YHd4SDoRzv/yhZ58NofSYgQ+tWY/M5 +MdgrUam8T9D23pXcX1vB7ZBv7CiRfhfteJD0YKfEx09Q7V0TOiErcMVhewghZTrN +glaMekesieilSEgx2R1G5YWGmKDlwKZqvQfkkldhB499Wk3Krja5VgQQ8my+9jts +gD6+DqNNx9R+p0nU8tK8zzCo53SPZN+8XEdozEBM+IPMy0A1BGDKs6QXnwPKHVr6 +0a8hVxDTAgMBAAECggEAfwsc8ewbhDW4TwIGqfNtDUr0rtYN13VpqohW0ki2L8G/ +HQaKUViO/wxQFqoNn/OqQO0AfHmKhXAAokTCiXngBHJ/OjF7vB7+IRhazZEE6u2/ +uoivr/OYNQbFpXyTqsQ1eFzpPju6KKcPK7BzT4Mc89ek/vloFAi8w6LdMl8lbvOg +LBWqX+5A+UQoenPUTvYM4U22YNcEAWubkpsYAmViiWiac+a+uPRk39aKyfOedDNu ++ty9MtCwekivoUTfP/1+O+jFlDnPMJUOEkBmcBqxseYYAHu7blBpdHxYpAItC2pv +YwJJSvsE+HLBLPk177Jahg7sOUqcP0F/X+T65yuvIQKBgQDxdjXdJT5K8j7rG2fv +2bvF2H1GPaHaTYRk0EGI2Ql6Nn+ddfeCE6gaT7aPPgg87wAhNu93coFuYHw0p/sc +ZkXMJ+BmlstPV555cWXmwcxZLsni0fOXrt4YxwWkZwmh74m0NVM/cSFw56PU0oj1 +yDNeq3fgmsJocmuNTe1eG9qA7QKBgQDXaAGrNA5Xel5mqqMYTHHQWI6l2uzdNtt7 +eDn3K9+Eh3ywTqrwP845MAjKDU2Lq61I6t2H89dEifHq823VIcLCHd9BF04MrAH7 +qDPzrmPP2iB9g+YFmGBKe+K0HFE1t1KrTlo9VV6ZAC6RJNLAgwD4kvfIVYNkCGwe ++hoZBdhgvwKBgBrOsPQ4ak4PzwRzKnrqhXpVqrLdrNZ7vLMkm+IBlpfG7SwiKLR8 +UjF5oB8PGAML1cvaOYPdZplGhQOjkrF4eU9NLhC1tSS96Y46FMIlyfYsx6UzAgRZ +GbdOgUXbWqpr2bH0KaXlfXz3eqzqIuKGs41TJB//jo3iBibN/AhytzORAoGAeGov +5KDpE4XYl9Pz8HVremjG9Xh4yQENmOwQm1fvT4rd7UFM1ZkVk2qCv1DIdLe32vdQ +d9ucDzh+ADWsxGRnF1TTpPN+Mh9FzISu5h4qtdreJsxBHgecbIbsqHrb+wdMM29N +itPaWfV8Eq9fETcqp8qgsWD8XkNHDdoKFMrrtskCgYAoSt/Je1D3ZE/3HEjez7bq +fenS3J6KG2SEn2PNFn+R0R5vBo4DaV/cQysKh44GD2+sh0QDyh6nuWJufyhPzROP +DU6DCLbwNePj/yaGuzi36oLt6bBgfPWCiJY7jIdK8DmTLW25m7fRtCC5pxZlSzgl +KBf7R6cbaTvaFe05Y2FJXA== +-----END PRIVATE KEY----- diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c new file mode 100644 index 0000000..3ee396c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + .ep_info.args.arg3 = ARM_BL31_PLAT_PARAM_VAL, + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + + .next_handoff_image_id = BL32_IMAGE_ID, + }, + + /* Fill BL32 related information */ + { + .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.args.arg0 = CORSTONE1000_TOS_FW_CONFIG_BASE, + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* Fill TOS_FW_CONFIG related information */ + { + .image_id = TOS_FW_CONFIG_ID, + .image_info.image_base = CORSTONE1000_TOS_FW_CONFIG_BASE, + .image_info.image_max_size = CORSTONE1000_TOS_FW_CONFIG_LIMIT - \ + CORSTONE1000_TOS_FW_CONFIG_BASE, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), + .ep_info.pc = BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL33_BASE, + .image_info.image_max_size = BL33_LIMIT - BL33_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c new file mode 100644 index 0000000..376799f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * corstone1000 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S new file mode 100644 index 0000000..cbe27c3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On corstone1000, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, Not yet supported. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current CPU is the primary + * CPU. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #CORSTONE1000_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c new file mode 100644 index 0000000..a96baae --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ + +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + ARM_MAP_NS_SHARED_RAM, + ARM_MAP_NS_DRAM1, + CORSTONE1000_MAP_DEVICE, + CORSTONE1000_EXTERNAL_FLASH, + {0} +}; + +static void set_fip_image_source(void) +{ + const struct plat_io_policy *policy; + /* + * metadata for firmware update is written at 0x0000 offset of the flash. + * PLAT_ARM_BOOT_BANK_FLAG contains the boot bank that TF-M is booted. + * As per firmware update spec, at a given point of time, only one bank is active. + * This means, TF-A should boot from the same bank as TF-M. + */ + volatile uint32_t *boot_bank_flag = (uint32_t *)(PLAT_ARM_BOOT_BANK_FLAG); + if (*boot_bank_flag > 1) { + VERBOSE("Boot_bank is set higher than possible values"); + } + + VERBOSE("Boot bank flag = %u.\n\r", *boot_bank_flag); + + policy = FCONF_GET_PROPERTY(arm, io_policies, FIP_IMAGE_ID); + + assert(policy != NULL); + assert(policy->image_spec != 0UL); + + io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec; + + if ((*boot_bank_flag) == 0) { + VERBOSE("Booting from bank 0: fip offset = 0x%lx\n\r", + PLAT_ARM_FIP_BASE_BANK0); + spec->offset = PLAT_ARM_FIP_BASE_BANK0; + } else { + VERBOSE("Booting from bank 1: fip offset = 0x%lx\n\r", + PLAT_ARM_FIP_BASE_BANK1); + spec->offset = PLAT_ARM_FIP_BASE_BANK1; + } +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); + /* + * Identify the start address of the FIP by reading the boot + * index flag from the flash. + */ + set_fip_image_source(); +} + +/* corstone1000 only has one always-on power domain and there + * is no power control present + */ +void __init plat_arm_pwrc_setup(void) +{ +} + +unsigned int plat_get_syscnt_freq2(void) +{ + /* Returning the Generic Timer Frequency */ + return SYS_COUNTER_FREQ_IN_TICKS; +} + + +/* + * Helper function to initialize ARM interconnect driver. + */ +void plat_arm_interconnect_init(void) +{ +} + +/* + * Helper function to place current master into coherency + */ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/* + * Helper function to remove current master from coherency + */ +void plat_arm_interconnect_exit_coherency(void) +{ +} + +/* + * This function is invoked during Mbed TLS library initialisation to get a heap + * The function simply returns the default allocated heap. + */ + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c new file mode 100644 index 0000000..98dea79 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ + +static void __dead2 corstone1000_system_reset(void) +{ + + uint32_t volatile * const watchdog_ctrl_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_CTRL_REG; + uint32_t volatile * const watchdog_val_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_VAL_REG; + + *(watchdog_val_reg) = SECURE_WATCHDOG_COUNTDOWN_VAL; + *watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE; + while (1) { + wfi(); + } +} + +plat_psci_ops_t plat_arm_psci_pm_ops = { + .system_reset = corstone1000_system_reset, + .validate_ns_entrypoint = NULL +}; + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + ops = &plat_arm_psci_pm_ops; + return ops; +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c new file mode 100644 index 0000000..c88201b --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c new file mode 100644 index 0000000..393235e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +static uint32_t plat_generate_random_number(void) +{ + uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U); + uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U); + uint64_t cntpct = read_cntpct_el0(); + + /* Generate 32-bit pattern: saving the 2 least significant bytes + * in random_lo and random_hi + */ + uint16_t random_lo = (uint16_t)( + (((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct + ); + + uint16_t random_hi = (uint16_t)( + (((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct + ); + + return (((uint32_t)random_hi) << 16) | random_lo; +} + +u_register_t plat_get_stack_protector_canary(void) +{ + return plat_generate_random_number(); /* a 32-bit pattern returned */ +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c new file mode 100644 index 0000000..5351896 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* The corstone1000 power domain tree descriptor */ +static unsigned char corstone1000_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT + + 2]; +/******************************************************************************* + * This function dynamically constructs the topology according to + * CLUSTER_COUNT and returns it. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + corstone1000_power_domain_tree_desc[0] = 1; + corstone1000_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT; + + for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++) + corstone1000_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT; + + return corstone1000_power_domain_tree_desc; +} + +/****************************************************************************** + * This function implements a part of the critical interface between the PSCI + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is + * returned in case the MPIDR is invalid. + *****************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return plat_arm_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c new file mode 100644 index 0000000..cec7332 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * The function returns 0 on success. Any other value is treated as error by the + * Trusted Board Boot. The function also reports extra information related + * to the ROTPK in the flags parameter: ROTPK_IS_HASH, ROTPK_NOT_DEPLOYED. + * + * Refer to the TF-A porting-guide document for more details. + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} + +/* + * STUB overriding the non-volatile counter reading. + * NV counters are not implemented at this stage of development. + * Return: 0 = success + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = CORSTONE1000_FW_NVCTR_VAL; + return 0; +} + +/* + * STUB overriding the non-volatile counter updating. + * NV counters are not implemented at this stage of development. + * Return: 0 = success + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts b/arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts new file mode 100644 index 0000000..8e49ab8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + /* + * BL32 image details needed by SPMC + * + * Note: + * binary_size: size of BL32 + TOS_FW_CONFIG + */ + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0x2002000>; + entrypoint = <0x0 0x2002000>; + binary_size = <0xae000>; + }; + +}; diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h new file mode 100644 index 0000000..2523d72 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#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) + +/* PL011 UART related constants */ +#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ +#undef V2M_IOFPGA_UART0_CLK_IN_HZ +#endif + +#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ +#undef V2M_IOFPGA_UART1_CLK_IN_HZ +#endif + +#define V2M_IOFPGA_UART0_CLK_IN_HZ 50000000 +#define V2M_IOFPGA_UART1_CLK_IN_HZ 50000000 + +/* Core/Cluster/Thread counts for corstone1000 */ +#define CORSTONE1000_CLUSTER_COUNT U(1) +#define CORSTONE1000_MAX_CPUS_PER_CLUSTER U(4) +#define CORSTONE1000_MAX_PE_PER_CPU U(1) +#define CORSTONE1000_PRIMARY_CPU U(0) + +#define PLAT_ARM_CLUSTER_COUNT CORSTONE1000_CLUSTER_COUNT + +#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \ + CORSTONE1000_MAX_CPUS_PER_CLUSTER * \ + CORSTONE1000_MAX_PE_PER_CPU) + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE 0x1a510000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ +#define PLAT_ARM_RUN_UART_BASE 0x1a520000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ +#define ARM_CONSOLE_BAUDRATE 115200 +#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 + +/* Memory related constants */ + +/* SRAM (CVM) memory layout + * + * + * + * partition size: sizeof(meminfo_t) = 16 bytes + * + * content: memory info area used by the next BL + * + * + * + * partition size: 4080 bytes + * + * + * + * partition size: 4 KB + * + * content: + * + * Area where BL2 copies the images descriptors + * + * = + * + * partition size: 688 KB + * + * content: + * + * BL32 (optee-os) + * + * = 0x20ae000 + * + * partition size: 8 KB + * + * content: + * + * BL32 config (TOS_FW_CONFIG) + * + * + * + * partition size: 140 KB + * + * content: + * + * BL31 + * + * + * + * partition size: 4 KB + * + * content: + * + * MCUBOOT data needed to verify TF-A BL2 + * + * + * + * partition size: 176 KB + * + * content: + * + * BL2 + * + * = + 1 MB + * + * partition size: 512 KB + * + * content: + * + * BL33 (u-boot) + */ + +/* DDR memory */ +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE (SZ_2G) /* 2GB*/ +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1) + +/* DRAM1 and DRAM2 are the same for corstone1000 */ +#define ARM_DRAM2_BASE ARM_DRAM1_BASE +#define ARM_DRAM2_SIZE ARM_DRAM1_SIZE +#define ARM_DRAM2_END ARM_DRAM1_END + +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +#define ARM_NS_DRAM1_SIZE ARM_DRAM1_SIZE +#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE +\ + ARM_NS_DRAM1_SIZE - 1) + +/* The first 8 KB of Trusted SRAM are used as shared memory */ +#define ARM_TRUSTED_SRAM_BASE UL(0x02000000) +#define ARM_SHARED_RAM_SIZE (SZ_8K) /* 8 KB */ +#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE + +/* The remaining Trusted SRAM is used to load the BL images */ +#define TOTAL_SRAM_SIZE (SZ_4M) /* 4 MB */ + +/* Last 512KB of CVM is allocated for shared RAM + * as an example openAMP */ +#define ARM_NS_SHARED_RAM_SIZE (512 * SZ_1K) + +#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SRAM_SIZE - \ + ARM_NS_SHARED_RAM_SIZE - \ + ARM_SHARED_RAM_SIZE) + +#define PLAT_ARM_MAX_BL2_SIZE (180 * SZ_1K) /* 180 KB */ + +#define PLAT_ARM_MAX_BL31_SIZE (140 * SZ_1K) /* 140 KB */ + +#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) + +#define BL2_SIGNATURE_SIZE (SZ_4K) /* 4 KB */ + +#define BL2_SIGNATURE_BASE (BL2_LIMIT - \ + PLAT_ARM_MAX_BL2_SIZE) +#define BL2_BASE (BL2_LIMIT - \ + PLAT_ARM_MAX_BL2_SIZE + \ + BL2_SIGNATURE_SIZE) +#define BL2_LIMIT (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE) + +#define BL31_BASE (BL2_SIGNATURE_BASE - \ + PLAT_ARM_MAX_BL31_SIZE) +#define BL31_LIMIT BL2_SIGNATURE_BASE + +#define CORSTONE1000_TOS_FW_CONFIG_BASE (BL31_BASE - \ + CORSTONE1000_TOS_FW_CONFIG_SIZE) +#define CORSTONE1000_TOS_FW_CONFIG_SIZE (SZ_8K) /* 8 KB */ +#define CORSTONE1000_TOS_FW_CONFIG_LIMIT BL31_BASE + +#define BL32_BASE ARM_BL_RAM_BASE +#define PLAT_ARM_MAX_BL32_SIZE (CORSTONE1000_TOS_FW_CONFIG_BASE - \ + BL32_BASE) + +#define BL32_LIMIT (BL32_BASE + \ + PLAT_ARM_MAX_BL32_SIZE) + +/* SPD_spmd settings */ + +#define PLAT_ARM_SPMC_BASE BL32_BASE +#define PLAT_ARM_SPMC_SIZE PLAT_ARM_MAX_BL32_SIZE + +/* NS memory */ + +/* The last 512KB of the SRAM is allocated as shared memory */ +#define ARM_NS_SHARED_RAM_BASE (ARM_TRUSTED_SRAM_BASE + TOTAL_SRAM_SIZE - \ + (PLAT_ARM_MAX_BL31_SIZE + \ + PLAT_ARM_MAX_BL32_SIZE)) + +#define BL33_BASE ARM_DRAM1_BASE +#define PLAT_ARM_MAX_BL33_SIZE (12 * SZ_1M) /* 12 MB*/ +#define BL33_LIMIT (ARM_DRAM1_BASE + PLAT_ARM_MAX_BL33_SIZE) + +/* end of the definition of SRAM memory layout */ + +/* NOR Flash */ + +#define PLAT_ARM_BOOT_BANK_FLAG UL(0x08002000) +#define PLAT_ARM_FIP_BASE_BANK0 UL(0x081EF000) +#define PLAT_ARM_FIP_BASE_BANK1 UL(0x0916F000) +#define PLAT_ARM_FIP_MAX_SIZE UL(0x1ff000) /* 1.996 MB */ + +#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE +#define PLAT_ARM_NVM_SIZE (SZ_32M) /* 32 MB */ + +#define PLAT_ARM_FLASH_IMAGE_BASE PLAT_ARM_FIP_BASE_BANK0 +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE PLAT_ARM_FIP_MAX_SIZE + +/* + * 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) +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * Define FW_CONFIG area base and limit. Leave enough space for BL2 meminfo. + * FW_CONFIG is intended to host the device tree. Currently, This area is not + * used because corstone1000 platform doesn't use a device tree at TF-A level. + */ +#define ARM_FW_CONFIG_BASE (ARM_SHARED_RAM_BASE \ + + sizeof(meminfo_t)) +#define ARM_FW_CONFIG_LIMIT (ARM_SHARED_RAM_BASE \ + + (ARM_SHARED_RAM_SIZE >> 1)) + +/* + * 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_BL_RAM_BASE + +/* + * 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 3 +#define PLAT_ARM_MMAP_ENTRIES 8 +#define MAX_XLAT_TABLES 5 +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) +#define MAX_IO_DEVICES 2 +#define MAX_IO_HANDLES 3 +#define MAX_IO_BLOCK_DEVICES 1 + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x1C010000 +#define PLAT_ARM_GICC_BASE 0x1C02F000 + +/* MHUv2 Secure Channel receiver and sender */ +#define PLAT_SDK700_MHU0_SEND 0x1B800000 +#define PLAT_SDK700_MHU0_RECV 0x1B810000 + +/* Timer/watchdog related constants */ +#define ARM_SYS_CNTCTL_BASE UL(0x1a200000) +#define ARM_SYS_CNTREAD_BASE UL(0x1a210000) +#define ARM_SYS_TIMCTL_BASE UL(0x1a220000) + +#define SECURE_WATCHDOG_ADDR_CTRL_REG 0x1A320000 +#define SECURE_WATCHDOG_ADDR_VAL_REG 0x1A320008 +#define SECURE_WATCHDOG_MASK_ENABLE 0x01 +#define SECURE_WATCHDOG_COUNTDOWN_VAL 0x1000 + +#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */ + +#define CORSTONE1000_IRQ_TZ_WDOG 32 +#define CORSTONE1000_IRQ_SEC_SYS_TIMER 34 + +#define PLAT_MAX_PWR_LVL 2 +/* + * 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 + +/* + * 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) + +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * 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 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +#define PLATFORM_STACK_SIZE UL(0x440) + +#define CORSTONE1000_EXTERNAL_FLASH MAP_REGION_FLAT( \ + PLAT_ARM_NVM_BASE, \ + PLAT_ARM_NVM_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + ARM_SHARED_RAM_BASE, \ + ARM_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \ + ARM_NS_SHARED_RAM_BASE, \ + ARM_NS_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#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_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) +#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 + +/* + * Map the region for the optional device tree configuration with read and + * write permissions + */ +#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT( \ + ARM_FW_CONFIG_BASE, \ + (ARM_FW_CONFIG_LIMIT- \ + ARM_FW_CONFIG_BASE), \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define CORSTONE1000_DEVICE_BASE (0x1A000000) +#define CORSTONE1000_DEVICE_SIZE (0x26000000) +#define CORSTONE1000_MAP_DEVICE MAP_REGION_FLAT( \ + CORSTONE1000_DEVICE_BASE, \ + CORSTONE1000_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#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_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(CORSTONE1000_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CORSTONE1000_IRQ_SEC_SYS_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S new file mode 100644 index 0000000..9334201 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + css_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/platform.mk b/arm-trusted-firmware/plat/arm/board/corstone1000/platform.mk new file mode 100644 index 0000000..d891691 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/platform.mk @@ -0,0 +1,83 @@ +# +# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Making sure the corstone1000 platform type is specified +ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),) + $(error TARGET_PLATFORM must be fpga or fvp) +endif + +CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a35.S + +PLAT_INCLUDES := -Iplat/arm/board/corstone1000/common/include \ + -Iplat/arm/board/corstone1000/include \ + -Iinclude/plat/arm/common \ + -Iinclude/plat/arm/css/common/aarch64 + + +CORSTONE1000_FW_NVCTR_VAL := 255 +TFW_NVCTR_VAL := ${CORSTONE1000_FW_NVCTR_VAL} +NTFW_NVCTR_VAL := ${CORSTONE1000_FW_NVCTR_VAL} + +override NEED_BL1 := no + +override NEED_BL2 := yes +FIP_BL2_ARGS := tb-fw + +override NEED_BL2U := no +override NEED_BL31 := yes +NEED_BL32 := yes +override NEED_BL33 := yes + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +CORSTONE1000_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + + +BL2_SOURCES += plat/arm/board/corstone1000/common/corstone1000_security.c \ + plat/arm/board/corstone1000/common/corstone1000_err.c \ + plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c \ + lib/utils/mem_region.c \ + plat/arm/board/corstone1000/common/corstone1000_helpers.S \ + plat/arm/board/corstone1000/common/corstone1000_plat.c \ + plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c \ + ${CORSTONE1000_CPU_LIBS} \ + + +BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/corstone1000/common/corstone1000_helpers.S \ + plat/arm/board/corstone1000/common/corstone1000_topology.c \ + plat/arm/board/corstone1000/common/corstone1000_security.c \ + plat/arm/board/corstone1000/common/corstone1000_plat.c \ + plat/arm/board/corstone1000/common/corstone1000_pm.c \ + ${CORSTONE1000_CPU_LIBS} \ + ${CORSTONE1000_GIC_SOURCES} + +ifneq (${ENABLE_STACK_PROTECTOR},0) + ifneq (${ENABLE_STACK_PROTECTOR},none) + CORSTONE1000_SECURITY_SOURCES := plat/arm/board/corstone1000/common/corstone1000_stack_protector.c + BL2_SOURCES += ${CORSTONE1000_SECURITY_SOURCES} + BL31_SOURCES += ${CORSTONE1000_SECURITY_SOURCES} + endif +endif + +FDT_SOURCES += plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts +CORSTONE1000_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/corstone1000_spmc_manifest.dtb + +# Add the SPMC manifest to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${CORSTONE1000_TOS_FW_CONFIG},--tos-fw-config,${CORSTONE1000_TOS_FW_CONFIG})) + +# Adding TARGET_PLATFORM as a GCC define (-D option) +$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM}))) + +# Adding CORSTONE1000_FW_NVCTR_VAL as a GCC define (-D option) +$(eval $(call add_define,CORSTONE1000_FW_NVCTR_VAL)) + +include plat/arm/common/arm_common.mk +include plat/arm/board/common/board_common.mk diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S new file mode 100644 index 0000000..c713f4f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On Corstone700, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, Not yet supported. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov r0, #0 + bx lr +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current CPU is the primary + * CPU. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =MPIDR_AFFINITY_MASK + and r0, r1 + cmp r0, #0 + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on Corstone700. + * + * (ClusterId * MAX_CPUS_PER_CLUSTER * MAX_PE_PER_CPU) + + * (CPUId * MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * MAX_CPUS_PER_CLUSTER + CPUId) * MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov r3, r0 + + /* Extract individual affinity fields from MPIDR */ + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov r3, #CORSTONE700_MAX_CPUS_PER_CLUSTER + mla r1, r2, r3, r1 + mov r3, #CORSTONE700_MAX_PE_PER_CPU + mla r0, r1, r3, r0 + + bx lr +endfunc plat_arm_calc_core_pos diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c new file mode 100644 index 0000000..629f076 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ + +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + ARM_MAP_NS_SHARED_RAM, + ARM_MAP_NS_DRAM1, + CORSTONE700_MAP_DEVICE, + {0} +}; + +/* Corstone700 only has one always-on power domain and there + * is no power control present + */ +void __init plat_arm_pwrc_setup(void) +{ + mhu_secure_init(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + /* Returning the Generic Timer Frequency */ + return SYS_COUNTER_FREQ_IN_TICKS; +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c new file mode 100644 index 0000000..4884ea5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t plat_arm_psci_pm_ops = { + /* dummy struct */ + .validate_ns_entrypoint = NULL +}; + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return ops; +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c new file mode 100644 index 0000000..39b2fc9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c new file mode 100644 index 0000000..6fd09da --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +static uint32_t plat_generate_random_number(void) +{ + uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U); + uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U); + uint64_t cntpct = read_cntpct_el0(); + + /* Generate 32-bit pattern: saving the 2 least significant bytes + * in random_lo and random_hi + */ + uint16_t random_lo = (uint16_t)( + (((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct + ); + + uint16_t random_hi = (uint16_t)( + (((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct + ); + + return (((uint32_t)random_hi) << 16) | random_lo; +} + +u_register_t plat_get_stack_protector_canary(void) +{ + return plat_generate_random_number(); /* a 32-bit pattern is returned */ +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c new file mode 100644 index 0000000..904f5ab --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* The Corstone700 power domain tree descriptor */ +static unsigned char corstone700_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT + + 2]; +/******************************************************************************* + * This function dynamically constructs the topology according to + * CLUSTER_COUNT and returns it. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + corstone700_power_domain_tree_desc[0] = 1; + corstone700_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT; + + for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++) + corstone700_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT; + + return corstone700_power_domain_tree_desc; +} + +/****************************************************************************** + * This function implements a part of the critical interface between the PSCI + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is + * returned in case the MPIDR is invalid. + *****************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return plat_arm_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c new file mode 100644 index 0000000..2231d11 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "mhu.h" +#include +#include + +ARM_INSTANTIATE_LOCK; + +#pragma weak plat_arm_pwrc_setup + +/* + * Slot 31 is reserved because the MHU hardware uses this register bit to + * indicate a non-secure access attempt. The total number of available slots is + * therefore 31 [30:0]. + */ +#define MHU_MAX_SLOT_ID 30 + +void mhu_secure_message_start(uintptr_t address, unsigned int slot_id) +{ + unsigned int intr_stat_check; + uint64_t timeout_cnt; + volatile uint8_t expiration; + + assert(slot_id <= MHU_MAX_SLOT_ID); + arm_lock_get(); + + /* + * Make sure any previous command has finished + * and polling timeout not expired + */ + + timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT); + + do { + intr_stat_check = (mmio_read_32(address + CPU_INTR_S_STAT) & + (1 << slot_id)); + + expiration = timeout_elapsed(timeout_cnt); + + } while ((intr_stat_check != 0U) && (expiration == 0U)); + + /* + * Note: No risk of timer overflows while waiting + * for the timeout expiration. + * According to Armv8 TRM: System counter roll-over + * time of not less than 40 years + */ +} + +void mhu_secure_message_send(uintptr_t address, + unsigned int slot_id, + unsigned int message) +{ + unsigned char access_ready; + uint64_t timeout_cnt; + volatile uint8_t expiration; + + assert(slot_id <= MHU_MAX_SLOT_ID); + assert((mmio_read_32(address + CPU_INTR_S_STAT) & + (1 << slot_id)) == 0U); + + MHU_V2_ACCESS_REQUEST(address); + + timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT); + + do { + access_ready = MHU_V2_IS_ACCESS_READY(address); + expiration = timeout_elapsed(timeout_cnt); + + } while ((access_ready == 0U) && (expiration == 0U)); + + /* + * Note: No risk of timer overflows while waiting + * for the timeout expiration. + * According to Armv8 TRM: System counter roll-over + * time of not less than 40 years + */ + + mmio_write_32(address + CPU_INTR_S_SET, message); +} + +void mhu_secure_message_end(uintptr_t address, unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + /* + * Clear any response we got by writing one in the relevant slot bit to + * the CLEAR register + */ + MHU_V2_CLEAR_REQUEST(address); + + arm_lock_release(); +} + +void __init mhu_secure_init(void) +{ + arm_lock_init(); + + /* + * The STAT register resets to zero. Ensure it is in the expected state, + * as a stale or garbage value would make us think it's a message we've + * already sent. + */ + + assert(mmio_read_32(PLAT_SDK700_MHU0_SEND + CPU_INTR_S_STAT) == 0); +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h b/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h new file mode 100644 index 0000000..3808746 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MHU_H +#define MHU_H + +#define MHU_POLL_INTR_STAT_TIMEOUT 50000 /*timeout value in us*/ + +/* CPU MHU secure channel registers */ +#define CPU_INTR_S_STAT 0x00 +#define CPU_INTR_S_SET 0x0C + +/* MHUv2 Control Registers Offsets */ +#define MHU_V2_MSG_CFG_OFFSET 0xF80 +#define MHU_V2_ACCESS_REQ_OFFSET 0xF88 +#define MHU_V2_ACCESS_READY_OFFSET 0xF8C + +#define MHU_V2_ACCESS_REQUEST(addr) \ + mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x1) + +#define MHU_V2_CLEAR_REQUEST(addr) \ + mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x0) + +#define MHU_V2_IS_ACCESS_READY(addr) \ + (mmio_read_32((addr) + MHU_V2_ACCESS_READY_OFFSET) & 0x1) + +void mhu_secure_message_start(uintptr_t address, unsigned int slot_id); +void mhu_secure_message_send(uintptr_t address, + unsigned int slot_id, + unsigned int message); +void mhu_secure_message_end(uintptr_t address, unsigned int slot_id); +void mhu_secure_init(void); + +#endif /* MHU_H */ diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h new file mode 100644 index 0000000..57b0551 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include + +/* PL011 UART related constants */ +#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ +#undef V2M_IOFPGA_UART0_CLK_IN_HZ +#endif + +#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ +#undef V2M_IOFPGA_UART1_CLK_IN_HZ +#endif + +#define V2M_IOFPGA_UART0_CLK_IN_HZ 32000000 +#define V2M_IOFPGA_UART1_CLK_IN_HZ 32000000 + +/* Core/Cluster/Thread counts for Corstone700 */ +#define CORSTONE700_CLUSTER_COUNT U(1) +#define CORSTONE700_MAX_CPUS_PER_CLUSTER U(4) +#define CORSTONE700_MAX_PE_PER_CPU U(1) + +#define PLAT_ARM_CLUSTER_COUNT CORSTONE700_CLUSTER_COUNT + +#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \ + CORSTONE700_MAX_CPUS_PER_CLUSTER * \ + CORSTONE700_MAX_PE_PER_CPU) + + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE 0x1a510000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ +#define PLAT_ARM_RUN_UART_BASE 0x1a520000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ +#define ARM_CONSOLE_BAUDRATE 115200 +#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 + +/* Memory related constants */ +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE UL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1) +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +#define ARM_NS_DRAM1_SIZE ARM_DRAM1_SIZE +#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \ + ARM_NS_DRAM1_SIZE - 1) +#define ARM_TRUSTED_SRAM_BASE UL(0x02000000) +#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE +#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00040000 /* 256 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) + +#define ARM_NS_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE + UL(0x00100000) +#define ARM_NS_SHARED_RAM_SIZE 0x00300000 + +/* + * 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_BL_RAM_BASE + PAGE_SIZE) +#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + +/* + * 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) +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * To enable FW_CONFIG to be loaded by BL1, define the corresponding base + * and limit. Leave enough space for 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 / 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)) + +/* + * 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 3 +#define PLAT_ARM_MMAP_ENTRIES 8 +#define MAX_XLAT_TABLES 5 +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x1C010000 +#define PLAT_ARM_GICC_BASE 0x1C02F000 + +/* MHUv2 Secure Channel receiver and sender */ +#define PLAT_SDK700_MHU0_SEND 0x1B800000 +#define PLAT_SDK700_MHU0_RECV 0x1B810000 + +/* Timer/watchdog related constants */ +#define ARM_SYS_CNTCTL_BASE UL(0x1a200000) +#define ARM_SYS_CNTREAD_BASE UL(0x1a210000) +#define ARM_SYS_TIMCTL_BASE UL(0x1a220000) + +#ifdef TARGET_PLATFORM_FVP +#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */ +#else +#define SYS_COUNTER_FREQ_IN_TICKS UL(32000000) /* 32MHz */ +#endif + +#define CORSTONE700_IRQ_TZ_WDOG 32 +#define CORSTONE700_IRQ_SEC_SYS_TIMER 34 + +#define PLAT_MAX_PWR_LVL 2 +/* + * 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 + +/* + * 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) + +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * 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 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +#define PLATFORM_STACK_SIZE UL(0x440) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + ARM_SHARED_RAM_BASE, \ + ARM_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \ + ARM_NS_SHARED_RAM_BASE, \ + ARM_NS_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#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_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) +#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 + +/* + * 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) + +#define CORSTONE700_DEVICE_BASE (0x1A000000) +#define CORSTONE700_DEVICE_SIZE (0x26000000) +#define CORSTONE700_MAP_DEVICE MAP_REGION_FLAT( \ + CORSTONE700_DEVICE_BASE,\ + CORSTONE700_DEVICE_SIZE,\ + MT_DEVICE | MT_RW | MT_SECURE) + +#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_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(CORSTONE700_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CORSTONE700_IRQ_SEC_SYS_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/platform.mk b/arm-trusted-firmware/plat/arm/board/corstone700/platform.mk new file mode 100644 index 0000000..9a8d38c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/platform.mk @@ -0,0 +1,63 @@ +# +# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Making sure the corstone700 platform type is specified +ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),) + $(error TARGET_PLATFORM must be fpga or fvp) +endif + +CORSTONE700_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S + +BL32_SOURCES += plat/arm/common/aarch32/arm_helpers.S \ + plat/arm/common/arm_console.c \ + plat/arm/common/arm_common.c \ + lib/xlat_tables/aarch32/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + ${CORSTONE700_CPU_LIBS} \ + plat/arm/board/corstone700/common/drivers/mhu/mhu.c + +PLAT_INCLUDES := -Iplat/arm/board/corstone700/common/include \ + -Iinclude/plat/arm/common \ + -Iplat/arm/board/corstone700/common/drivers/mhu + +NEED_BL32 := yes + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +CORSTONE700_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +# BL1/BL2 Image not a part of the capsule Image for Corstone700 +override NEED_BL1 := no +override NEED_BL2 := no +override NEED_BL2U := no +override NEED_BL33 := yes + +#TFA for Corstone700 starts from BL32 +override RESET_TO_SP_MIN := 1 + +#Device tree +CORSTONE700_HW_CONFIG_DTS := fdts/corstone700_${TARGET_PLATFORM}.dts +CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/fdts/corstone700_${TARGET_PLATFORM}.dtb +FDT_SOURCES += ${CORSTONE700_HW_CONFIG_DTS} +$(eval CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(CORSTONE700_HW_CONFIG_DTS))) + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${CORSTONE700_HW_CONFIG},--hw-config,${CORSTONE700_HW_CONFIG})) + +# Check for Linux kernel as a BL33 image by default +$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33)) + ifndef ARM_PRELOADED_DTB_BASE + $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.") + endif + $(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) + +# Adding TARGET_PLATFORM as a GCC define (-D option) +$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM}))) + +include plat/arm/board/common/board_common.mk diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c b/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c new file mode 100644 index 0000000..2fc0e0d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk new file mode 100644 index 0000000..75dc0f1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to FVP platform +BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/corstone700/common/corstone700_helpers.S \ + plat/arm/board/corstone700/common/corstone700_topology.c \ + plat/arm/board/corstone700/common/corstone700_security.c \ + plat/arm/board/corstone700/common/corstone700_plat.c \ + plat/arm/board/corstone700/common/corstone700_pm.c \ + plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c \ + ${CORSTONE700_GIC_SOURCES} + +ifneq (${ENABLE_STACK_PROTECTOR},0) + ifneq (${ENABLE_STACK_PROTECTOR},none) + BL32_SOURCES += plat/arm/board/corstone700/common/corstone700_stack_protector.c + endif +endif + +include plat/arm/common/sp_min/arm_sp_min.mk diff --git a/arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S new file mode 100644 index 0000000..9985c1d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* --------------------------------------------------------------------- + * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC + * WakeRequest signal" then it is a warm boot. + * --------------------------------------------------------------------- + */ + ldcopr r2, MPIDR + ldr r1, =PWRC_BASE + str r2, [r1, #PSYSR_OFF] + ldr r2, [r1, #PSYSR_OFF] + ubfx r2, r2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH + cmp r2, #WKUP_PPONR + beq warm_reset + cmp r2, #WKUP_GICREQ + beq warm_reset + + /* Cold reset */ + mov r0, #0 + bx lr + +warm_reset: + /* --------------------------------------------------------------------- + * A mailbox is maintained in the trusted SRAM. It is flushed out of the + * caches after every update using normal memory so it is safe to read + * it here with SO attributes. + * --------------------------------------------------------------------- + */ + ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr r0, [r0] + cmp r0, #0 + beq _panic + bx lr + + /* --------------------------------------------------------------------- + * The power controller indicates this is a warm reset but the mailbox + * is empty. This should never happen! + * --------------------------------------------------------------------- + */ +_panic: + b _panic +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =MPIDR_AFFINITY_MASK + and r0, r1 + cmp r0, #FVP_PRIMARY_CPU + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) + + * (CPUId * FVP_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov r3, r0 + + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation + */ + tst r0, #MPIDR_MT_MASK + lsleq r3, r0, #MPIDR_AFFINITY_BITS + + /* Extract individual affinity fields from MPIDR */ + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov r3, #FVP_MAX_CPUS_PER_CLUSTER + mla r1, r2, r3, r1 + mov r3, #FVP_MAX_PE_PER_CPU + mla r0, r1, r3, r0 + + bx lr +endfunc plat_arm_calc_core_pos diff --git a/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S new file mode 100644 index 0000000..8efc238 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +#ifndef EL3_PAYLOAD_BASE + /* --------------------------------------------- + * Power down this cpu. + * TODO: Do we need to worry about powering the + * cluster down as well here. That will need + * locks which we won't have unless an elf- + * loader zeroes out the zi section. + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + mov_imm x1, PWRC_BASE + str w0, [x1, #PPOFFR_OFF] + + /* --------------------------------------------- + * There is no sane reason to come out of this + * wfi so panic if we do. This cpu will be pow- + * ered on and reset by the cpu_on pm api + * --------------------------------------------- + */ + dsb sy + wfi + no_ret plat_panic_handler +#else + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + + /* Wait until the entrypoint gets populated */ +poll_mailbox: + ldr x1, [x0] + cbz x1, 1f + br x1 +1: + wfe + b poll_mailbox +#endif /* EL3_PAYLOAD_BASE */ +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* --------------------------------------------------------------------- + * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC + * WakeRequest signal" then it is a warm boot. + * --------------------------------------------------------------------- + */ + mrs x2, mpidr_el1 + mov_imm x1, PWRC_BASE + str w2, [x1, #PSYSR_OFF] + ldr w2, [x1, #PSYSR_OFF] + ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH + cmp w2, #WKUP_PPONR + beq warm_reset + cmp w2, #WKUP_GICREQ + beq warm_reset + + /* Cold reset */ + mov x0, #0 + ret + +warm_reset: + /* --------------------------------------------------------------------- + * A mailbox is maintained in the trusted SRAM. It is flushed out of the + * caches after every update using normal memory so it is safe to read + * it here with SO attributes. + * --------------------------------------------------------------------- + */ + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr x0, [x0] + cbz x0, _panic_handler + ret + + /* --------------------------------------------------------------------- + * The power controller indicates this is a warm reset but the mailbox + * is empty. This should never happen! + * --------------------------------------------------------------------- + */ +_panic_handler: + no_ret plat_panic_handler +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #FVP_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) + + * (CPUId * FVP_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation. + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #FVP_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x5, #FVP_MAX_PE_PER_CPU + madd x0, x1, x5, x0 + ret +endfunc plat_arm_calc_core_pos diff --git a/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c b/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c new file mode 100644 index 0000000..759f6d0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +struct ras_interrupt fvp_ras_interrupts[] = { +}; + +struct err_record_info fvp_err_records[] = { +}; + +REGISTER_ERR_RECORD_INFO(fvp_err_records); +REGISTER_RAS_INTERRUPTS(fvp_ras_interrupts); diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c new file mode 100644 index 0000000..45e3b7e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +struct gicv3_config_t gicv3_config; +struct hw_topology_t soc_topology; +struct uart_serial_config_t uart_serial_config; +struct cpu_timer_t cpu_timer; + +#define ILLEGAL_ADDR ULL(~0) + +int fconf_populate_gicv3_config(uintptr_t config) +{ + int err; + int node; + uintptr_t addr; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* + * Find the offset of the node containing "arm,gic-v3" compatible property. + * Populating fconf strucutures dynamically is not supported for legacy + * systems which use GICv2 IP. Simply skip extracting GIC properties. + */ + node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3"); + if (node < 0) { + WARN("FCONF: Unable to locate node with arm,gic-v3 compatible property\n"); + return 0; + } + /* The GICv3 DT binding holds at least two address/size pairs, + * the first describing the distributor, the second the redistributors. + * See: bindings/interrupt-controller/arm,gic-v3.yaml + */ + err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL); + if (err < 0) { + ERROR("FCONF: Failed to read GICD reg property of GIC node\n"); + return err; + } + gicv3_config.gicd_base = addr; + + err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL); + if (err < 0) { + ERROR("FCONF: Failed to read GICR reg property of GIC node\n"); + } else { + gicv3_config.gicr_base = addr; + } + + return err; +} + +int fconf_populate_topology(uintptr_t config) +{ + int err, node, cluster_node, core_node, thread_node; + uint32_t cluster_count = 0, max_cpu_per_cluster = 0, total_cpu_count = 0; + uint32_t max_pwr_lvl = 0; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* Find the offset of the node containing "arm,psci-1.0" compatible property */ + node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,psci-1.0"); + if (node < 0) { + ERROR("FCONF: Unable to locate node with arm,psci-1.0 compatible property\n"); + return node; + } + + err = fdt_read_uint32(hw_config_dtb, node, "max-pwr-lvl", &max_pwr_lvl); + if (err < 0) { + /* + * Some legacy FVP dts may not have this property. Assign the default + * value. + */ + WARN("FCONF: Could not locate max-pwr-lvl property\n"); + max_pwr_lvl = 2; + } + + assert(max_pwr_lvl <= MPIDR_AFFLVL2); + + /* Find the offset of the "cpus" node */ + node = fdt_path_offset(hw_config_dtb, "/cpus"); + if (node < 0) { + ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpus"); + return node; + } + + /* A typical cpu-map node in a device tree is shown here for reference + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + + cluster1 { + core0 { + cpu = <&CPU2>; + }; + core1 { + cpu = <&CPU3>; + }; + }; + }; + */ + + /* Locate the cpu-map child node */ + node = fdt_subnode_offset(hw_config_dtb, node, "cpu-map"); + if (node < 0) { + ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpu-map"); + return node; + } + + uint32_t cpus_per_cluster[PLAT_ARM_CLUSTER_COUNT] = {0}; + + /* Iterate through cluster nodes */ + fdt_for_each_subnode(cluster_node, hw_config_dtb, node) { + assert(cluster_count < PLAT_ARM_CLUSTER_COUNT); + + /* Iterate through core nodes */ + fdt_for_each_subnode(core_node, hw_config_dtb, cluster_node) { + /* core nodes may have child nodes i.e., "thread" nodes */ + if (fdt_first_subnode(hw_config_dtb, core_node) < 0) { + cpus_per_cluster[cluster_count]++; + } else { + /* Multi-threaded CPU description is found in dtb */ + fdt_for_each_subnode(thread_node, hw_config_dtb, core_node) { + cpus_per_cluster[cluster_count]++; + } + + /* Since in some dtbs, core nodes may not have thread node, + * no need to error if even one child node is not found. + */ + } + } + + /* Ensure every cluster node has at least 1 child node */ + if (cpus_per_cluster[cluster_count] < 1U) { + ERROR("FCONF: Unable to locate the core node in cluster %d\n", cluster_count); + return -1; + } + + VERBOSE("CLUSTER ID: %d cpu-count: %d\n", cluster_count, + cpus_per_cluster[cluster_count]); + + /* Find the maximum number of cpus in any cluster */ + max_cpu_per_cluster = MAX(max_cpu_per_cluster, cpus_per_cluster[cluster_count]); + total_cpu_count += cpus_per_cluster[cluster_count]; + cluster_count++; + } + + + /* At least one cluster node is expected in hardware configuration dtb */ + if (cluster_count < 1U) { + ERROR("FCONF: Unable to locate the cluster node in cpu-map node\n"); + return -1; + } + + soc_topology.plat_max_pwr_level = max_pwr_lvl; + soc_topology.plat_cluster_count = cluster_count; + soc_topology.cluster_cpu_count = max_cpu_per_cluster; + soc_topology.plat_cpu_count = total_cpu_count; + + return 0; +} + +int fconf_populate_uart_config(uintptr_t config) +{ + int uart_node, node, err; + uintptr_t addr; + const char *path; + uint32_t phandle; + uint64_t translated_addr; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* + * uart child node is indirectly referenced through its path which is + * specified in the `serial1` property of the "aliases" node. + * Note that TF-A boot console is mapped to serial0 while runtime + * console is mapped to serial1. + */ + + path = fdt_get_alias(hw_config_dtb, "serial1"); + if (path == NULL) { + ERROR("FCONF: Could not read serial1 property in aliases node\n"); + return -1; + } + + /* Find the offset of the uart serial node */ + uart_node = fdt_path_offset(hw_config_dtb, path); + if (uart_node < 0) { + ERROR("FCONF: Failed to locate uart serial node using its path\n"); + return -1; + } + + /* uart serial node has its offset and size of address in reg property */ + err = fdt_get_reg_props_by_index(hw_config_dtb, uart_node, 0, &addr, + NULL); + if (err < 0) { + ERROR("FCONF: Failed to read reg property of '%s' node\n", + "uart serial"); + return err; + } + VERBOSE("FCONF: UART node address: %lx\n", addr); + + /* + * Perform address translation of local device address to CPU address + * domain. + */ + translated_addr = fdtw_translate_address(hw_config_dtb, + uart_node, (uint64_t)addr); + if (translated_addr == ILLEGAL_ADDR) { + ERROR("FCONF: failed to translate UART node base address"); + return -1; + } + + uart_serial_config.uart_base = translated_addr; + + VERBOSE("FCONF: UART serial device base address: %" PRIx64 "\n", + uart_serial_config.uart_base); + + /* + * The phandle of the DT node which captures the clock info of uart + * serial node is specified in the "clocks" property. + */ + err = fdt_read_uint32(hw_config_dtb, uart_node, "clocks", &phandle); + if (err < 0) { + ERROR("FCONF: Could not read clocks property in uart serial node\n"); + return err; + } + + node = fdt_node_offset_by_phandle(hw_config_dtb, phandle); + if (node < 0) { + ERROR("FCONF: Failed to locate clk node using its path\n"); + return node; + } + + /* + * Retrieve clock frequency. We assume clock provider generates a fixed + * clock. + */ + err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency", + &uart_serial_config.uart_clk); + if (err < 0) { + ERROR("FCONF: Could not read clock-frequency property in clk node\n"); + return err; + } + + VERBOSE("FCONF: UART serial device clk frequency: %x\n", + uart_serial_config.uart_clk); + + return 0; +} + +int fconf_populate_cpu_timer(uintptr_t config) +{ + int err, node; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + /* Find the node offset point to "arm,armv8-timer" compatible property, + * a per-core architected timer attached to a GIC to deliver its per-processor + * interrupts via PPIs */ + node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,armv8-timer"); + if (node < 0) { + ERROR("FCONF: Unrecognized hardware configuration dtb (%d)\n", node); + return node; + } + + /* Locate the cell holding the clock-frequency, an optional field */ + err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency", &cpu_timer.clock_freq); + if (err < 0) { + WARN("FCONF failed to read clock-frequency property\n"); + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config); +FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology); +FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config); +FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer); diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c b/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c new file mode 100644 index 0000000..e258015 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#include + +struct event_log_config_t event_log_config; + +int fconf_populate_event_log_config(uintptr_t config) +{ + int err; + int node; + + /* Necessary to work with libfdt APIs */ + const void *dtb = (const void *)config; + + /* + * Find the offset of the node containing "arm,tpm_event_log" + * compatible property + */ + const char *compatible_str = "arm,tpm_event_log"; + + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find '%s' compatible in dtb\n", + compatible_str); + return node; + } + + /* Retrieve Event Log details from the DTB */ +#ifdef SPD_opteed + err = fdtw_read_cells(dtb, node, "tpm_event_log_sm_addr", 2, + &event_log_config.tpm_event_log_sm_addr); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'tpm_event_log_sm_addr'\n"); + return err; + } +#endif + err = fdtw_read_cells(dtb, node, + "tpm_event_log_addr", 2, &event_log_config.tpm_event_log_addr); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'tpm_event_log_addr'\n"); + return err; + } + + err = fdtw_read_cells(dtb, node, + "tpm_event_log_size", 1, &event_log_config.tpm_event_log_size); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'tpm_event_log_size'\n"); + } + + return err; +} + +FCONF_REGISTER_POPULATOR(NT_CONFIG, event_log_config, + fconf_populate_event_log_config); diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi b/arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi new file mode 100644 index 0000000..47af672 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* TPM Event Log Config */ +event_log: tpm_event_log { + compatible = "arm,tpm_event_log"; + tpm_event_log_addr = <0x0 0x0>; + tpm_event_log_size = <0x0>; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts new file mode 100644 index 0000000..c26b519 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x1800>; + id = ; + }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x01000000>; + id = ; + }; + + /* + * Load SoC and TOS firmware configs at the base of + * non shared SRAM. The runtime checks ensure we don't + * overlap BL2, BL31 or BL32. The NT firmware config + * is loaded at base of DRAM. + */ + soc_fw-config { + load-address = <0x0 0x04001300>; + max-size = <0x200>; + id = ; + }; + +/* If required, SPD should enable loading of trusted OS fw config */ +#if defined(SPD_tspd) || defined(SPD_spmd) + tos_fw-config { + load-address = <0x0 0x04001500>; + max-size = <0xB00>; + id = ; + }; +#endif + + nt_fw-config { + load-address = <0x0 0x80000000>; + max-size = <0x200>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts new file mode 100644 index 0000000..8f32b98 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { +#if MEASURED_BOOT +#include "event_log.dtsi" +#endif +}; + +#if MEASURED_BOOT && defined(SPD_opteed) +&event_log { + tpm_event_log_sm_addr = <0x0 0x0>; +}; +#endif diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts new file mode 100644 index 0000000..7ab980b --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts new file mode 100644 index 0000000..21a6073 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +#define AFF 00 + +#include "fvp-defs.dtsi" +#undef POST +#define POST \ + }; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0x6000000>; + entrypoint = <0x0 0x6000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "cactus-primary"; + load_address = <0x7000000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + vm2 { + is_ffa_partition; + debug_name = "cactus-secondary"; + load_address = <0x7100000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + vm3 { + is_ffa_partition; + debug_name = "cactus-tertiary"; + load_address = <0x7200000>; + vcpu_count = <1>; + mem_size = <1048576>; + }; + vm4 { + is_ffa_partition; + debug_name = "ivy"; + load_address = <0x7600000>; + vcpu_count = <1>; + mem_size = <1048576>; + }; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU_0 + + /* + * SPMC (Hafnium) requires secondary core nodes are declared + * in descending order. + */ + CPU_7 + CPU_6 + CPU_5 + CPU_4 + CPU_3 + CPU_2 + CPU_1 + }; + + memory@6000000 { + device_type = "memory"; + reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */ + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts new file mode 100644 index 0000000..041dade --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +#define AFF 00 + +#include "fvp-defs.dtsi" +#undef POST +#define POST \ + }; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0x6000000>; + entrypoint = <0x0 0x6000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "op-tee"; + load_address = <0x6280000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU_0 + + /* + * SPMC (Hafnium) requires secondary core nodes are declared + * in descending order. + */ + CPU_7 + CPU_6 + CPU_5 + CPU_4 + CPU_3 + CPU_2 + CPU_1 + }; + + memory@6000000 { + device_type = "memory"; + reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */ + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts new file mode 100644 index 0000000..cf4ef2d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2020-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; + + /* + * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in + * network order (big endian) + */ + +#if ARM_IO_IN_DTB + arm-io_policies { + fip-handles { + compatible = "arm,io-fip-handle"; + scp_bl2_uuid = "9766fd3d-89be-e849-ae5d-78a140608213"; + bl31_uuid = "47d4086d-4cfe-9846-9b95-2950cbbd5a00"; + bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38"; + bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288"; + bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9"; + bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4"; + hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc"; + soc_fw_cfg_uuid = "9979814b-0376-fb46-8c8e-8d267f7859e0"; + tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021"; + nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9"; + t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c"; + scp_fw_key_uuid = "024221a1-f860-e411-8d9b-f33c0e15a014"; + soc_fw_key_uuid = "8ab8becc-f960-e411-9ad0-eb4822d8dcf8"; + tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04"; + nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859"; + scp_fw_content_cert_uuid = "44be6f04-5e63-e411-b28b-73d8eaae9656"; + soc_fw_content_cert_uuid = "e2b20c20-5e63-e411-9ce8-abccf92bb666"; + tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d"; + nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7"; + sp_content_cert_uuid = "776dfd44-8697-4c3b-91eb-c13e025a2a6f"; + }; + }; +#endif /* ARM_IO_IN_DTB */ + + secure-partitions { + compatible = "arm,sp"; + +#ifdef ARM_BL2_SP_LIST_DTS + #include __XSTRING(ARM_BL2_SP_LIST_DTS) +#else +#ifdef OPTEE_SP_FW_CONFIG + op-tee { + uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b"; + load-address = <0x6280000>; + }; +#else + cactus-primary { + uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb"; + load-address = <0x7000000>; + owner = "SiP"; + }; + + cactus-secondary { + uuid = "d1582309-f023-47b9-827c-4464f5578fc8"; + load-address = <0x7100000>; + owner = "Plat"; + }; + + cactus-tertiary { + uuid = "79b55c73-1d8c-44b9-8593-61e1770ad8d2"; + load-address = <0x7200000>; + owner = "Plat"; + }; + + ivy { + uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7"; + load-address = <0x7600000>; + owner = "Plat"; + }; +#endif +#endif /* ARM_BL2_SP_LIST_DTS */ + }; + +#if COT_DESC_IN_DTB + #include "cot_descriptors.dtsi" +#endif + +#if MEASURED_BOOT + #include "event_log.dtsi" +#endif + +}; + +#if COT_DESC_IN_DTB + +#include "../fvp_def.h" + +&trusted_nv_counter { + reg = ; +}; + +&non_trusted_nv_counter { + reg = ; +}; +#endif diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts new file mode 100644 index 0000000..7bed6cb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { +#if MEASURED_BOOT +#include "event_log.dtsi" +#endif +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts new file mode 100644 index 0000000..b803340 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP) + * that has additional optional properties defined. + * + */ + +/dts-v1/; + +/ { + compatible = "arm,ffa-manifest-1.0"; + + /* Properties */ + description = "op-tee"; + ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */ + uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>; + id = <1>; + execution-ctx-count = <8>; + exception-level = <2>; /* S-EL1 */ + execution-state = <0>; /* AARCH64 */ + load-address = <0x6280000>; + entrypoint-offset = <0x1000>; + xlat-granule = <0>; /* 4KiB */ + boot-order = <0>; + messaging-method = <0x3>; /* Direct request/response supported. */ + managed-exit; + run-time-model = <1>; /* SP pre-emptible. */ + + /* Boot protocol */ + gp-register-num = <0x0>; + + device-regions { + compatible = "arm,ffa-manifest-device-regions"; + + uart1 { + base-address = <0x00000000 0x1c0a0000>; + pages-count = <1>; + attributes = <0x3>; /* read-write */ + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c new file mode 100644 index 0000000..5468555 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* Event Log data */ +static uint8_t event_log[PLAT_ARM_EVENT_LOG_MAX_SIZE]; + +/* FVP table with platform specific image IDs, names and PCRs */ +const event_log_metadata_t fvp_event_log_metadata[] = { + { FW_CONFIG_ID, EVLOG_FW_CONFIG_STRING, PCR_0 }, + { TB_FW_CONFIG_ID, EVLOG_TB_FW_CONFIG_STRING, PCR_0 }, + { BL2_IMAGE_ID, EVLOG_BL2_STRING, PCR_0 }, + + { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */ +}; + +void bl1_plat_mboot_init(void) +{ + event_log_init(event_log, event_log + sizeof(event_log)); + event_log_write_header(); +} + +void bl1_plat_mboot_finish(void) +{ + size_t event_log_cur_size; + + event_log_cur_size = event_log_get_cur_size(event_log); + int rc = arm_set_tb_fw_info((uintptr_t)event_log, + event_log_cur_size); + if (rc != 0) { + /* + * It is a fatal error because on FVP platform, BL2 software + * assumes that a valid Event Log buffer exist and it will use + * same Event Log buffer to append image measurements. + */ + panic(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c new file mode 100644 index 0000000..59fc0f3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013-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 "fvp_private.h" + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + /* + * Enable coherency in Interconnect for the primary CPU's cluster. + */ + fvp_interconnect_enable(); +} + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); + + /* On FVP RevC, initialize SMMUv3 */ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) + smmuv3_security_init(PLAT_FVP_SMMUV3_BASE); +} + +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) +{ + uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR); + + /* Clear the NV flags register. */ + mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR), + nv_flags); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (true) + wfi(); +} + +/******************************************************************************* + * The following function checks if Firmware update is needed by checking error + * reported in NV flag. + ******************************************************************************/ +bool plat_arm_bl1_fwu_needed(void) +{ + int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR); + + /* if image load/authentication failed */ + return ((nv_flags == -EAUTH) || (nv_flags == -ENOENT)); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c new file mode 100644 index 0000000..7def56a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "fvp_private.h" + +void bl2_el3_early_platform_setup(u_register_t arg0 __unused, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) +{ + arm_bl2_el3_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + /* + * Enable coherency in Interconnect for the primary CPU's cluster. + */ + fvp_interconnect_enable(); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c new file mode 100644 index 0000000..1f38278 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +/* Event Log data */ +static uint64_t event_log_base; + +/* FVP table with platform specific image IDs, names and PCRs */ +const event_log_metadata_t fvp_event_log_metadata[] = { + { BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 }, + { BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 }, + { BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 }, + { BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 }, + { BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 }, + { HW_CONFIG_ID, EVLOG_HW_CONFIG_STRING, PCR_0 }, + { NT_FW_CONFIG_ID, EVLOG_NT_FW_CONFIG_STRING, PCR_0 }, + { SCP_BL2_IMAGE_ID, EVLOG_SCP_BL2_STRING, PCR_0 }, + { SOC_FW_CONFIG_ID, EVLOG_SOC_FW_CONFIG_STRING, PCR_0 }, + { TOS_FW_CONFIG_ID, EVLOG_TOS_FW_CONFIG_STRING, PCR_0 }, + { RMM_IMAGE_ID, EVLOG_RMM_STRING, PCR_0}, + + { CRITICAL_DATA_ID, EVLOG_CRITICAL_DATA_STRING, PCR_1 }, + + { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */ +}; + +void bl2_plat_mboot_init(void) +{ + uint8_t *event_log_start; + uint8_t *event_log_finish; + size_t bl1_event_log_size; + int rc; + + rc = arm_get_tb_fw_info(&event_log_base, &bl1_event_log_size); + if (rc != 0) { + ERROR("%s(): Unable to get Event Log info from TB_FW_CONFIG\n", + __func__); + /* + * It is a fatal error because on FVP platform, BL2 software + * assumes that a valid Event Log buffer exist and it will use + * same Event Log buffer to append image measurements. + */ + panic(); + } + + /* + * BL1 and BL2 share the same Event Log buffer and that BL2 will + * append its measurements after BL1's + */ + event_log_start = (uint8_t *)((uintptr_t)event_log_base + + bl1_event_log_size); + event_log_finish = (uint8_t *)((uintptr_t)event_log_base + + PLAT_ARM_EVENT_LOG_MAX_SIZE); + + event_log_init((uint8_t *)event_log_start, event_log_finish); +} + +int plat_mboot_measure_critical_data(unsigned int critical_data_id, + const void *base, size_t size) +{ + /* + * It is very unlikely that the critical data size would be + * bigger than 2^32 bytes + */ + assert(size < UINT32_MAX); + assert(base != NULL); + + /* Calculate image hash and record data in Event Log */ + int err = event_log_measure_and_record((uintptr_t)base, (uint32_t)size, + critical_data_id); + if (err != 0) { + ERROR("%s%s critical data (%i)\n", + "Failed to ", "record", err); + return err; + } + + return 0; +} + +#if TRUSTED_BOARD_BOOT +static int fvp_populate_critical_data(struct fvp_critical_data *critical_data) +{ + char *nv_ctr_oids[MAX_NV_CTR_IDS] = { + [TRUSTED_NV_CTR_ID] = TRUSTED_FW_NVCOUNTER_OID, + [NON_TRUSTED_NV_CTR_ID] = NON_TRUSTED_FW_NVCOUNTER_OID, + }; + + for (int i = 0; i < MAX_NV_CTR_IDS; i++) { + int rc = plat_get_nv_ctr(nv_ctr_oids[i], + &critical_data->nv_ctr[i]); + if (rc != 0) { + return rc; + } + } + + return 0; +} +#endif /* TRUSTED_BOARD_BOOT */ + +static int fvp_populate_and_measure_critical_data(void) +{ + int rc = 0; + +/* + * FVP platform only measures 'platform NV-counter' and hence its + * measurement makes sense during Trusted-Boot flow only. + */ +#if TRUSTED_BOARD_BOOT + struct fvp_critical_data populate_critical_data; + + rc = fvp_populate_critical_data(&populate_critical_data); + if (rc == 0) { + rc = plat_mboot_measure_critical_data(CRITICAL_DATA_ID, + &populate_critical_data, + sizeof(populate_critical_data)); + } +#endif /* TRUSTED_BOARD_BOOT */ + + return rc; +} + +void bl2_plat_mboot_finish(void) +{ + int rc; + + /* Event Log address in Non-Secure memory */ + uintptr_t ns_log_addr; + + /* Event Log filled size */ + size_t event_log_cur_size; + + rc = fvp_populate_and_measure_critical_data(); + if (rc != 0) { + panic(); + } + + event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base); + + rc = arm_set_nt_fw_info( +#ifdef SPD_opteed + (uintptr_t)event_log_base, +#endif + event_log_cur_size, &ns_log_addr); + if (rc != 0) { + ERROR("%s(): Unable to update %s_FW_CONFIG\n", + __func__, "NT"); + /* + * It is a fatal error because on FVP secure world software + * assumes that a valid event log exists and will use it to + * record the measurements into the fTPM. + * Note: In FVP platform, OP-TEE uses nt_fw_config to get the + * secure Event Log buffer address. + */ + panic(); + } + + /* Copy Event Log to Non-secure memory */ + (void)memcpy((void *)ns_log_addr, (const void *)event_log_base, + event_log_cur_size); + + /* Ensure that the Event Log is visible in Non-secure memory */ + flush_dcache_range(ns_log_addr, event_log_cur_size); + +#if defined(SPD_tspd) || defined(SPD_spmd) + /* Set Event Log data in TOS_FW_CONFIG */ + rc = arm_set_tos_fw_info((uintptr_t)event_log_base, + event_log_cur_size); + if (rc != 0) { + ERROR("%s(): Unable to update %s_FW_CONFIG\n", + __func__, "TOS"); + panic(); + } +#endif /* defined(SPD_tspd) || defined(SPD_spmd) */ + + dump_event_log((uint8_t *)event_log_base, event_log_cur_size); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c new file mode 100644 index 0000000..5a17a0d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fvp_private.h" + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); +} + +/******************************************************************************* + * This function returns the list of executable images + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + struct bl_params *arm_bl_params; + + arm_bl_params = arm_get_next_bl_params(); + +#if __aarch64__ && !BL2_AT_EL3 + const struct dyn_cfg_dtb_info_t *fw_config_info; + bl_mem_params_node_t *param_node; + uintptr_t fw_config_base = 0U; + entry_point_info_t *ep_info; + + /* Get BL31 image node */ + param_node = get_bl_mem_params_node(BL31_IMAGE_ID); + assert(param_node != NULL); + + /* get fw_config load address */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + assert(fw_config_info != NULL); + + fw_config_base = fw_config_info->config_addr; + assert(fw_config_base != 0U); + + /* + * Get the entry point info of BL31 image and override + * arg1 of entry point info with fw_config base address + */ + ep_info = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; +#endif /* __aarch64__ && !BL2_AT_EL3 */ + + return arm_bl_params; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c new file mode 100644 index 0000000..fd73767 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "fvp_private.h" + +void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info) +{ + arm_bl2u_early_platform_setup(mem_layout, plat_info); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c new file mode 100644 index 0000000..a94a4f4 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fvp_private.h" + +void __init bl31_early_platform_setup2(u_register_t arg0, + u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + +#if !RESET_TO_BL31 && !BL2_AT_EL3 + const struct dyn_cfg_dtb_info_t *soc_fw_config_info; + + INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1); + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", arg1); + + soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID); + if (soc_fw_config_info != NULL) { + arg1 = soc_fw_config_info->config_addr; + } +#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 */ + + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize the correct interconnect for this cluster during cold + * boot. No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * FVP PSCI code will enable coherency for other clusters. + */ + fvp_interconnect_enable(); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); + + /* On FVP RevC, initialize SMMUv3 */ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) + smmuv3_init(PLAT_FVP_SMMUV3_BASE); +} + +void __init bl31_plat_arch_setup(void) +{ + arm_bl31_plat_arch_setup(); + + /* + * For RESET_TO_BL31 systems, BL31 is the first bootloader to run. + * So there is no BL2 to load the HW_CONFIG dtb into memory before + * control is passed to BL31. + */ +#if !RESET_TO_BL31 && !BL2_AT_EL3 + /* HW_CONFIG was also loaded by BL2 */ + const struct dyn_cfg_dtb_info_t *hw_config_info; + + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + + fconf_populate("HW_CONFIG", hw_config_info->config_addr); +#endif +} + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + +#if !RESET_TO_BL31 && !BL2_AT_EL3 + /* Get the frequency through FCONF API for HW_CONFIG */ + counter_base_frequency = FCONF_GET_PROPERTY(hw_config, cpu_timer, clock_freq); + if (counter_base_frequency > 0U) { + return counter_base_frequency; + } +#endif + + /* Read the frequency from Frequency modes table */ + counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF); + + /* The first entry of the frequency modes table must not be 0 */ + if (counter_base_frequency == 0U) { + panic(); + } + + return counter_base_frequency; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c new file mode 100644 index 0000000..d8d19de --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2013-2022, 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 +#if SPM_MM +#include +#endif + +#include +#include +#include + +#include "fvp_private.h" + +/* Defines for GIC Driver build time selection */ +#define FVP_GICV2 1 +#define FVP_GICV3 2 + +/******************************************************************************* + * arm_config holds the characteristics of the differences between the three FVP + * platforms (Base, A53_A57 & Foundation). It will be populated during cold boot + * at each boot stage by the primary before enabling the MMU (to allow + * interconnect configuration) & used thereafter. Each BL will have its own copy + * to allow independent operation. + ******************************************************************************/ +arm_config_t arm_config; + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#if FVP_GICR_REGION_PROTECTION +#define MAP_GICD_MEM MAP_REGION_FLAT(BASE_GICD_BASE, \ + BASE_GICD_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* Map all core's redistributor memory as read-only. After boots up, + * per-core map its redistributor memory as read-write */ +#define MAP_GICR_MEM MAP_REGION_FLAT(BASE_GICR_BASE, \ + (BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\ + MT_DEVICE | MT_RO | MT_SECURE) +#endif /* FVP_GICR_REGION_PROTECTION */ + +/* + * Need to be mapped with write permissions in order to set a new non-volatile + * counter value. + */ +#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ + DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Table of memory regions for various BL stages to map using the MMU. + * This doesn't include Trusted SRAM as setup_page_tables() already takes care + * of mapping it. + */ +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RO, + V2M_MAP_IOFPGA, + MAP_DEVICE0, +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + MAP_DEVICE1, +#endif +#if TRUSTED_BOARD_BOOT + /* To access the Root of Trust Public Key registers. */ + MAP_DEVICE2, + /* Map DRAM to authenticate NS_BL2U image. */ + ARM_MAP_NS_DRAM1, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RW, + V2M_MAP_IOFPGA, + MAP_DEVICE0, +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + MAP_DEVICE1, +#endif + ARM_MAP_NS_DRAM1, +#ifdef __aarch64__ + ARM_MAP_DRAM2, +#endif +#if defined(SPD_spmd) + ARM_MAP_TRUSTED_DRAM, +#endif +#if ENABLE_RME + ARM_MAP_RMM_DRAM, + ARM_MAP_GPT_L1_DRAM, +#endif /* ENABLE_RME */ +#ifdef SPD_tspd + ARM_MAP_TSP_SEC_MEM, +#endif +#if TRUSTED_BOARD_BOOT + /* To access the Root of Trust Public Key registers. */ + MAP_DEVICE2, +#endif /* TRUSTED_BOARD_BOOT */ + +#if CRYPTO_SUPPORT && !BL2_AT_EL3 + /* + * To access shared the Mbed TLS heap while booting the + * system with Crypto support + */ + ARM_MAP_BL1_RW, +#endif /* CRYPTO_SUPPORT && !BL2_AT_EL3 */ +#if SPM_MM + ARM_SP_IMAGE_MMAP, +#endif +#if ARM_BL31_IN_DRAM + ARM_MAP_BL31_SEC_DRAM, +#endif +#ifdef SPD_opteed + ARM_MAP_OPTEE_CORE_MEM, + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2U +const mmap_region_t plat_arm_mmap[] = { + MAP_DEVICE0, + V2M_MAP_IOFPGA, + {0} +}; +#endif +#ifdef IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, +#if USE_DEBUGFS + /* Required by devfip, can be removed if devfip is not used */ + V2M_MAP_FLASH0_RW, +#endif /* USE_DEBUGFS */ + ARM_MAP_EL3_TZC_DRAM, + V2M_MAP_IOFPGA, + MAP_DEVICE0, +#if FVP_GICR_REGION_PROTECTION + MAP_GICD_MEM, + MAP_GICR_MEM, +#else + MAP_DEVICE1, +#endif /* FVP_GICR_REGION_PROTECTION */ + ARM_V2M_MAP_MEM_PROTECT, +#if SPM_MM + ARM_SPM_BUF_EL3_MMAP, +#endif + /* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */ + ARM_DTB_DRAM_NS, +#if ENABLE_RME + ARM_MAP_GPT_L1_DRAM, +#endif + {0} +}; + +#if defined(IMAGE_BL31) && SPM_MM +const mmap_region_t plat_arm_secure_partition_mmap[] = { + V2M_MAP_IOFPGA_EL0, /* for the UART */ + MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE | MT_USER), + ARM_SP_IMAGE_MMAP, + ARM_SP_IMAGE_NS_BUF_MMAP, + ARM_SP_IMAGE_RW_MMAP, + ARM_SPM_BUF_EL0_MMAP, + {0} +}; +#endif +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { +#ifndef __aarch64__ + ARM_MAP_SHARED_RAM, + ARM_V2M_MAP_MEM_PROTECT, +#endif + V2M_MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, + /* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */ + ARM_DTB_DRAM_NS, + {0} +}; +#endif + +#ifdef IMAGE_RMM +const mmap_region_t plat_arm_mmap[] = { + V2M_MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +#if FVP_INTERCONNECT_DRIVER != FVP_CCN +static const int fvp_cci400_map[] = { + PLAT_FVP_CCI400_CLUS0_SL_PORT, + PLAT_FVP_CCI400_CLUS1_SL_PORT, +}; + +static const int fvp_cci5xx_map[] = { + PLAT_FVP_CCI5XX_CLUS0_SL_PORT, + PLAT_FVP_CCI5XX_CLUS1_SL_PORT, +}; + +static unsigned int get_interconnect_master(void) +{ + unsigned int master; + u_register_t mpidr; + + mpidr = read_mpidr_el1(); + master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ? + MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr); + + assert(master < FVP_CLUSTER_COUNT); + return master; +} +#endif + +#if defined(IMAGE_BL31) && SPM_MM +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static spm_mm_mp_info_t sp_mp_info[] = { + [0] = {0x80000000, 0}, + [1] = {0x80000001, 0}, + [2] = {0x80000002, 0}, + [3] = {0x80000003, 0}, + [4] = {0x80000100, 0}, + [5] = {0x80000101, 0}, + [6] = {0x80000102, 0}, + [7] = {0x80000103, 0}, +}; + +const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = ARM_SP_IMAGE_BASE, + .sp_mem_limit = ARM_SP_IMAGE_LIMIT, + .sp_image_base = ARM_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = ARM_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = &sp_mp_info[0], +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} +#endif + +/******************************************************************************* + * A single boot loader stack is expected to work on both the Foundation FVP + * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The + * SYS_ID register provides a mechanism for detecting the differences between + * these platforms. This information is stored in a per-BL array to allow the + * code to take the correct path.Per BL platform configuration. + ******************************************************************************/ +void __init fvp_config_setup(void) +{ + unsigned int rev, hbi, bld, arch, sys_id; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK; + hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK; + bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK; + arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; + + if (arch != ARCH_MODEL) { + ERROR("This firmware is for FVP models\n"); + panic(); + } + + /* + * The build field in the SYS_ID tells which variant of the GIC + * memory is implemented by the model. + */ + switch (bld) { + case BLD_GIC_VE_MMAP: + ERROR("Legacy Versatile Express memory map for GIC peripheral" + " is not supported\n"); + panic(); + break; + case BLD_GIC_A53A57_MMAP: + break; + default: + ERROR("Unsupported board build %x\n", bld); + panic(); + } + + /* + * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010 + * for the Foundation FVP. + */ + switch (hbi) { + case HBI_FOUNDATION_FVP: + arm_config.flags = 0; + + /* + * Check for supported revisions of Foundation FVP + * Allow future revisions to run but emit warning diagnostic + */ + switch (rev) { + case REV_FOUNDATION_FVP_V2_0: + case REV_FOUNDATION_FVP_V2_1: + case REV_FOUNDATION_FVP_v9_1: + case REV_FOUNDATION_FVP_v9_6: + break; + default: + WARN("Unrecognized Foundation FVP revision %x\n", rev); + break; + } + break; + case HBI_BASE_FVP: + arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC); + + /* + * Check for supported revisions + * Allow future revisions to run but emit warning diagnostic + */ + switch (rev) { + case REV_BASE_FVP_V0: + arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400; + break; + case REV_BASE_FVP_REVC: + arm_config.flags |= (ARM_CONFIG_FVP_HAS_SMMUV3 | + ARM_CONFIG_FVP_HAS_CCI5XX); + break; + default: + WARN("Unrecognized Base FVP revision %x\n", rev); + break; + } + break; + default: + ERROR("Unsupported board HBI number 0x%x\n", hbi); + panic(); + } + + /* + * We assume that the presence of MT bit, and therefore shifted + * affinities, is uniform across the platform: either all CPUs, or no + * CPUs implement it. + */ + if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) + arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF; +} + + +void __init fvp_interconnect_init(void) +{ +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) { + ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported"); + panic(); + } + + plat_arm_interconnect_init(); +#else + uintptr_t cci_base = 0U; + const int *cci_map = NULL; + unsigned int map_size = 0U; + + /* Initialize the right interconnect */ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) { + cci_base = PLAT_FVP_CCI5XX_BASE; + cci_map = fvp_cci5xx_map; + map_size = ARRAY_SIZE(fvp_cci5xx_map); + } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) { + cci_base = PLAT_FVP_CCI400_BASE; + cci_map = fvp_cci400_map; + map_size = ARRAY_SIZE(fvp_cci400_map); + } else { + return; + } + + assert(cci_base != 0U); + assert(cci_map != NULL); + cci_init(cci_base, cci_map, map_size); +#endif +} + +void fvp_interconnect_enable(void) +{ +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + plat_arm_interconnect_enter_coherency(); +#else + unsigned int master; + + if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { + master = get_interconnect_master(); + cci_enable_snoop_dvm_reqs(master); + } +#endif +} + +void fvp_interconnect_disable(void) +{ +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + plat_arm_interconnect_exit_coherency(); +#else + unsigned int master; + + if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { + master = get_interconnect_master(); + cci_disable_snoop_dvm_reqs(master); + } +#endif +} + +#if CRYPTO_SUPPORT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif /* CRYPTO_SUPPORT */ + +void fvp_timer_init(void) +{ +#if USE_SP804_TIMER + /* Enable the clock override for SP804 timer 0, which means that no + * clock dividers are applied and the raw (35MHz) clock will be used. + */ + mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(V2M_SP804_TIMER0_BASE, + SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); +#else + generic_delay_timer_init(); + + /* Enable System level generic timer */ + mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0U) | CNTCR_EN); +#endif /* USE_SP804_TIMER */ +} + +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC + * feature is availabile for platform. + * @fid: SMCCC function id + * + * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and + * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} + +/* Get SOC version */ +int32_t plat_get_soc_version(void) +{ + return (int32_t) + (SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE, + ARM_SOC_IDENTIFICATION_CODE) | + (FVP_SOC_ID & SOC_ID_IMPL_DEF_MASK)); +} + +/* Get SOC revision */ +int32_t plat_get_soc_revision(void) +{ + unsigned int sys_id; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) & + V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c new file mode 100644 index 0000000..6a403d9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +extern event_log_metadata_t fvp_event_log_metadata[]; + +const event_log_metadata_t *plat_event_log_get_metadata(void) +{ + return fvp_event_log_metadata; +} + +int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data) +{ + /* Calculate image hash and record data in Event Log */ + int err = event_log_measure_and_record(image_data->image_base, + image_data->image_size, + image_id); + if (err != 0) { + ERROR("%s%s image id %u (%i)\n", + "Failed to ", "record", image_id, err); + return err; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c new file mode 100644 index 0000000..1a6cd42 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include + +static console_t fvp_runtime_console; + +/* Initialize the runtime console */ +void arm_console_runtime_init(void) +{ + uintptr_t uart_base; + uint32_t uart_clk; + + /* + * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and + * BL2_AT_EL3 systems. + */ +#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3 + uart_base = PLAT_ARM_RUN_UART_BASE; + uart_clk = PLAT_ARM_RUN_UART_CLK_IN_HZ; +#else + uart_base = FCONF_GET_PROPERTY(hw_config, uart_serial_config, + uart_base); + uart_clk = FCONF_GET_PROPERTY(hw_config, uart_serial_config, + uart_clk); +#endif + + int rc = console_pl011_register(uart_base, uart_clk, + ARM_CONSOLE_BAUDRATE, + &fvp_runtime_console); + + if (rc == 0) { + panic(); + } + + console_set_scope(&fvp_runtime_console, CONSOLE_FLAG_RUNTIME); +} + +void arm_console_runtime_end(void) +{ + console_flush(); + (void)console_unregister(&fvp_runtime_console); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h b/arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h new file mode 100644 index 0000000..831eb35 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_DEF_H +#define FVP_DEF_H + +#include + +#ifndef FVP_CLUSTER_COUNT +#error "FVP_CLUSTER_COUNT is not set in makefile" +#endif + +#ifndef FVP_MAX_CPUS_PER_CLUSTER +#error "FVP_MAX_CPUS_PER_CLUSTER is not set in makefile" +#endif + +#ifndef FVP_MAX_PE_PER_CPU +#error "FVP_MAX_PE_PER_CPU is not set in makefile" +#endif + +#define FVP_PRIMARY_CPU 0x0 + +/* Defines for the Interconnect build selection */ +#define FVP_CCI 1 +#define FVP_CCN 2 + +/****************************************************************************** + * Definition of platform soc id + *****************************************************************************/ +#define FVP_SOC_ID 0 + +/******************************************************************************* + * FVP memory map related constants + ******************************************************************************/ + +#define FLASH1_BASE UL(0x0c000000) +#define FLASH1_SIZE UL(0x04000000) + +#define PSRAM_BASE UL(0x14000000) +#define PSRAM_SIZE UL(0x04000000) + +#define VRAM_BASE UL(0x18000000) +#define VRAM_SIZE UL(0x02000000) + +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE UL(0x20000000) +#define DEVICE0_SIZE UL(0x0c200000) + +/* + * In case of FVP models with CCN, the CCN register space overlaps into + * the NSRAM area. + */ +#if FVP_INTERCONNECT_DRIVER == FVP_CCN +#define DEVICE1_BASE UL(0x2e000000) +#define DEVICE1_SIZE UL(0x1A00000) +#else +#define DEVICE1_BASE BASE_GICD_BASE + +#if GIC_ENABLE_V4_EXTN +/* GICv4 mapping: GICD + CORE_COUNT * 256KB */ +#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \ + (PLATFORM_CORE_COUNT * 0x40000)) +#else +/* GICv2 and GICv3 mapping: GICD + CORE_COUNT * 128KB */ +#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \ + (PLATFORM_CORE_COUNT * 0x20000)) +#endif /* GIC_ENABLE_V4_EXTN */ + +#define NSRAM_BASE UL(0x2e000000) +#define NSRAM_SIZE UL(0x10000) +#endif +/* Devices in the second GB */ +#define DEVICE2_BASE UL(0x7fe00000) +#define DEVICE2_SIZE UL(0x00200000) + +#define PCIE_EXP_BASE UL(0x40000000) +#define TZRNG_BASE UL(0x7fe60000) + +/* Non-volatile counters */ +#define TRUSTED_NVCTR_BASE UL(0x7fe70000) +#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000)) +#define TFW_NVCTR_SIZE UL(4) +#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004)) +#define NTFW_CTR_SIZE UL(4) + +/* Keys */ +#define SOC_KEYS_BASE UL(0x7fe80000) +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000)) +#define TZ_PUB_KEY_HASH_SIZE UL(32) +#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020)) +#define HU_KEY_SIZE UL(16) +#define END_KEY_BASE (SOC_KEYS_BASE + UL(0x0044)) +#define END_KEY_SIZE UL(32) + +/* Constants to distinguish FVP type */ +#define HBI_BASE_FVP U(0x020) +#define REV_BASE_FVP_V0 U(0x0) +#define REV_BASE_FVP_REVC U(0x2) + +#define HBI_FOUNDATION_FVP U(0x010) +#define REV_FOUNDATION_FVP_V2_0 U(0x0) +#define REV_FOUNDATION_FVP_V2_1 U(0x1) +#define REV_FOUNDATION_FVP_v9_1 U(0x2) +#define REV_FOUNDATION_FVP_v9_6 U(0x3) + +#define BLD_GIC_VE_MMAP U(0x0) +#define BLD_GIC_A53A57_MMAP U(0x1) + +#define ARCH_MODEL U(0x1) + +/* FVP Power controller base address*/ +#define PWRC_BASE UL(0x1c100000) + +/* FVP SP804 timer frequency is 35 MHz*/ +#define SP804_TIMER_CLKMULT 1 +#define SP804_TIMER_CLKDIV 35 + +/* SP810 controller. FVP specific flags */ +#define FVP_SP810_CTRL_TIM0_OV BIT_32(16) +#define FVP_SP810_CTRL_TIM1_OV BIT_32(18) +#define FVP_SP810_CTRL_TIM2_OV BIT_32(20) +#define FVP_SP810_CTRL_TIM3_OV BIT_32(22) + +/******************************************************************************* + * GIC & interrupt handling related constants + ******************************************************************************/ +/* VE compatible GIC memory map */ +#define VE_GICD_BASE UL(0x2c001000) +#define VE_GICC_BASE UL(0x2c002000) +#define VE_GICH_BASE UL(0x2c004000) +#define VE_GICV_BASE UL(0x2c006000) + +/* Base FVP compatible GIC memory map */ +#define BASE_GICD_BASE UL(0x2f000000) +#define BASE_GICD_SIZE UL(0x10000) +#define BASE_GICR_BASE UL(0x2f100000) + +#if GIC_ENABLE_V4_EXTN +/* GICv4 redistributor size: 256KB */ +#define BASE_GICR_SIZE UL(0x40000) +#else +#define BASE_GICR_SIZE UL(0x20000) +#endif /* GIC_ENABLE_V4_EXTN */ + +#define BASE_GICC_BASE UL(0x2c000000) +#define BASE_GICH_BASE UL(0x2c010000) +#define BASE_GICV_BASE UL(0x2c02f000) + +#define FVP_IRQ_TZ_WDOG 56 +#define FVP_IRQ_SEC_SYS_TIMER 57 + +/******************************************************************************* + * TrustZone address space controller related constants + ******************************************************************************/ + +/* NSAIDs used by devices in TZC filter 0 on FVP */ +#define FVP_NSAID_DEFAULT 0 +#define FVP_NSAID_PCI 1 +#define FVP_NSAID_VIRTIO 8 /* from FVP v5.6 onwards */ +#define FVP_NSAID_AP 9 /* Application Processors */ +#define FVP_NSAID_VIRTIO_OLD 15 /* until FVP v5.5 */ + +/* NSAIDs used by devices in TZC filter 2 on FVP */ +#define FVP_NSAID_HDLCD0 2 +#define FVP_NSAID_CLCD 7 + +/******************************************************************************* + * Memprotect definitions + ******************************************************************************/ +/* PSCI memory protect definitions: + * This variable is stored in a non-secure flash because some ARM reference + * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT + * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions. + */ +#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \ + V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +#endif /* FVP_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c new file mode 100644 index 0000000..1f9f0dd --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +/* + * FVP error handler + */ +__dead2 void plat_arm_error_handler(int err) +{ + /* Propagate the err code in the NV-flags register */ + mmio_write_32(V2M_SYS_NVFLAGS_ADDR, (uint32_t)err); + + console_flush(); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + for (;;) + wfi(); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c new file mode 100644 index 0000000..8f3e7b7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c @@ -0,0 +1,173 @@ +/* + * 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 + +#if FVP_GICR_REGION_PROTECTION +/* To indicate GICR region of the core initialized as Read-Write */ +static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false}; +#endif /* FVP_GICR_REGION_PROTECTION */ + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +/* Default GICR base address to be used for GICR probe. */ +static uint64_t fvp_gicr_base_addrs[2] = { 0U }; + +/* List of zero terminated GICR frame addresses which CPUs will probe */ +static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs; + +#if !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \ + (defined(__aarch64__) && defined(IMAGE_BL31)))) +static const interrupt_prop_t fvp_interrupt_props[] = { + PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) +}; +#endif + +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr) +{ + u_register_t temp_mpidr = mpidr; + + temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return plat_arm_calc_core_pos(temp_mpidr); +} + + +static gicv3_driver_data_t fvp_gic_data = { + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = fvp_rdistif_base_addrs, + .mpidr_to_core_pos = fvp_gicv3_mpidr_hash +}; + +/****************************************************************************** + * This function gets called per core to make its redistributor frame rw + *****************************************************************************/ +static void fvp_gicv3_make_rdistrif_rw(void) +{ +#if FVP_GICR_REGION_PROTECTION + unsigned int core_pos = plat_my_core_pos(); + + /* Make the redistributor frame RW if it is not done previously */ + if (fvp_gicr_rw_region_init[core_pos] != true) { + int ret = xlat_change_mem_attributes(BASE_GICR_BASE + + (core_pos * BASE_GICR_SIZE), + BASE_GICR_SIZE, + MT_EXECUTE_NEVER | + MT_DEVICE | MT_RW | + MT_SECURE); + + if (ret != 0) { + ERROR("Failed to make redistributor frame \ + read write = %d\n", ret); + panic(); + } else { + fvp_gicr_rw_region_init[core_pos] = true; + } + } +#else + return; +#endif /* FVP_GICR_REGION_PROTECTION */ +} + +void plat_arm_gic_driver_init(void) +{ + fvp_gicv3_make_rdistrif_rw(); + /* + * Get GICD and GICR base addressed through FCONF APIs. + * FCONF is not supported in BL32 for FVP. + */ +#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ + (defined(__aarch64__) && defined(IMAGE_BL31)) + fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config, + gicv3_config, + gicd_base); + fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config, + gicr_base); +#if SEC_INT_DESC_IN_FCONF + fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config, + sec_intr_prop, descriptor); + fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config, + sec_intr_prop, count); +#else + fvp_gic_data.interrupt_props = fvp_interrupt_props; + fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); +#endif +#else + fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE; + fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE; + fvp_gic_data.interrupt_props = fvp_interrupt_props; + fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); +#endif + + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ + +#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ + (defined(__aarch64__) && defined(IMAGE_BL31)) + gicv3_driver_init(&fvp_gic_data); + if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) { + ERROR("No GICR base frame found for Primary CPU\n"); + panic(); + } +#endif +} + +/****************************************************************************** + * Function to iterate over all GICR frames and discover the corresponding + * per-cpu redistributor frame as well as initialize the corresponding + * interface in GICv3. + *****************************************************************************/ +void plat_arm_gic_pcpu_init(void) +{ + int result; + const uint64_t *plat_gicr_frames = fvp_gicr_frames; + + fvp_gicv3_make_rdistrif_rw(); + + do { + result = gicv3_rdistif_probe(*plat_gicr_frames); + + /* If the probe is successful, no need to proceed further */ + if (result == 0) + break; + + plat_gicr_frames++; + } while (*plat_gicr_frames != 0U); + + if (result == -1) { + ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); + panic(); + } + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c new file mode 100644 index 0000000..4eef51c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c @@ -0,0 +1,174 @@ +/* + * 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 + +/* Semihosting filenames */ +#define BL2_IMAGE_NAME "bl2.bin" +#define BL31_IMAGE_NAME "bl31.bin" +#define BL32_IMAGE_NAME "bl32.bin" +#define BL33_IMAGE_NAME "bl33.bin" +#define TB_FW_CONFIG_NAME "fvp_tb_fw_config.dtb" +#define SOC_FW_CONFIG_NAME "fvp_soc_fw_config.dtb" +#define TOS_FW_CONFIG_NAME "fvp_tsp_fw_config.dtb" +#define NT_FW_CONFIG_NAME "fvp_nt_fw_config.dtb" +#define FW_CONFIG_NAME "fvp_fw_config.dtb" +#define HW_CONFIG_NAME "hw_config.dtb" + +#if TRUSTED_BOARD_BOOT +#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt" +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt" +#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt" +#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt" +#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt" +#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt" +#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt" +#endif /* TRUSTED_BOARD_BOOT */ + +/* IO devices */ +static const io_dev_connector_t *sh_dev_con; +static uintptr_t sh_dev_handle; + +static const io_file_spec_t sh_file_spec[] = { + [BL2_IMAGE_ID] = { + .path = BL2_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL31_IMAGE_ID] = { + .path = BL31_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL32_IMAGE_ID] = { + .path = BL32_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL33_IMAGE_ID] = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [TB_FW_CONFIG_ID] = { + .path = TB_FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [SOC_FW_CONFIG_ID] = { + .path = SOC_FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [TOS_FW_CONFIG_ID] = { + .path = TOS_FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [NT_FW_CONFIG_ID] = { + .path = NT_FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [FW_CONFIG_ID] = { + .path = FW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, + [HW_CONFIG_ID] = { + .path = HW_CONFIG_NAME, + .mode = FOPEN_MODE_RB + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + .path = TRUSTED_BOOT_FW_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_KEY_CERT_ID] = { + .path = TRUSTED_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [SOC_FW_KEY_CERT_ID] = { + .path = SOC_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + .path = TOS_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + .path = NT_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [SOC_FW_CONTENT_CERT_ID] = { + .path = SOC_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + .path = TOS_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + .path = NT_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + + +static int open_semihosting(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if the file exists on semi-hosting.*/ + result = io_dev_init(sh_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(sh_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Semi-hosting IO\n"); + io_close(local_image_handle); + } + } + return result; +} + +void plat_arm_io_setup(void) +{ + int io_result; + + io_result = arm_io_setup(); + if (io_result < 0) { + panic(); + } + + /* Register the additional IO devices on this platform */ + io_result = register_io_dev_sh(&sh_dev_con); + if (io_result < 0) { + panic(); + } + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle); + if (io_result < 0) { + panic(); + } +} + +/* + * FVP provides semihosting as an alternative to load images + */ +int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]); + if (result == 0) { + *dev_handle = sh_dev_handle; + *image_spec = (uintptr_t)&sh_file_spec[image_id]; + } + + return result; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c new file mode 100644 index 0000000..5463f33 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* Using hardcoded token values for AEM FVP */ +static uint8_t platform_token[] = { + 0xD2, 0x84, 0x40, 0xA0, 0x59, 0x08, 0xB1, 0xD9, + 0x61, 0xA8, 0xA9, 0x0A, 0x58, 0x40, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x3A, 0x00, + 0x01, 0x24, 0xFA, 0x58, 0x40, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x3A, 0x00, 0x01, + 0x25, 0x00, 0x58, 0x41, 0x01, 0x0B, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x12, 0x78, 0x1C, + 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x61, + 0x72, 0x6D, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x43, + 0x43, 0x41, 0x2D, 0x53, 0x53, 0x44, 0x2F, 0x31, + 0x2E, 0x30, 0x2E, 0x30, 0x0B, 0x58, 0x19, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0x3A, 0x00, 0x01, 0x24, 0xF7, 0x78, 0x1C, 0x68, + 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x61, 0x72, + 0x6D, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x43, 0x43, + 0x41, 0x2D, 0x53, 0x53, 0x44, 0x2F, 0x31, 0x2E, + 0x30, 0x2E, 0x30, 0x3A, 0x00, 0x01, 0x25, 0x01, + 0x78, 0x18, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, + 0x2F, 0x2F, 0x63, 0x63, 0x61, 0x5F, 0x76, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2E, 0x6F, + 0x72, 0x67, 0x3A, 0x00, 0x01, 0x24, 0xF9, 0x19, + 0x30, 0x00, 0x3A, 0x00, 0x01, 0x24, 0xFD, 0x8D, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0x58, 0x40, 0xD3, 0x8A, 0x41, 0xA6, 0xC1, 0x29, + 0x98, 0x18, 0xB5, 0x16, 0x9C, 0x21, 0x78, 0xB7, + 0x92, 0xF8, 0x26, 0x82, 0x76, 0x2F, 0x26, 0x45, + 0x21, 0x6D, 0x0C, 0x21, 0x06, 0xF4, 0xB5, 0xE3, + 0xA8, 0x07, 0xD1, 0xD6, 0x8C, 0x73, 0xA5, 0xC8, + 0x16, 0xD8, 0x30, 0x68, 0xC0, 0xA4, 0x77, 0xE2, + 0x1E, 0xD2, 0x17, 0x86, 0xC3, 0x68, 0x82, 0xDD, + 0x21, 0x1B, 0xA3, 0xE2, 0xC7, 0xF7, 0x06, 0x33, + 0xB0, 0x3A +}; + +int plat_get_cca_attest_token(uintptr_t buf, size_t *len, + uintptr_t hash, size_t hash_size) +{ + (void)hash; + (void)hash_size; + + if (*len < sizeof(platform_token)) { + return -EINVAL; + } + + (void)memcpy((void *)buf, platform_token, sizeof(platform_token)); + *len = sizeof(platform_token); + + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c new file mode 100644 index 0000000..6b9d618 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2013-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 "fvp_private.h" +#include "../drivers/arm/gic/v3/gicv3_private.h" + + +#if ARM_RECOM_STATE_ID_ENC +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +const unsigned int arm_pm_idle_states[] = { + /* State-id - 0x01 */ + arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RET, + ARM_PWR_LVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF, + ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF, + ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x222 */ + arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF, + ARM_LOCAL_STATE_OFF, ARM_PWR_LVL2, PSTATE_TYPE_POWERDOWN), + 0, +}; +#endif + +/******************************************************************************* + * Function which implements the common FVP specific operations to power down a + * cluster in response to a CPU_OFF or CPU_SUSPEND request. + ******************************************************************************/ +static void fvp_cluster_pwrdwn_common(void) +{ + uint64_t mpidr = read_mpidr_el1(); + +#if ENABLE_SPE_FOR_LOWER_ELS + /* + * On power down we need to disable statistical profiling extensions + * before exiting coherency. + */ + spe_disable(); +#endif + + /* Disable coherency if this cluster is to be turned off */ + fvp_interconnect_disable(); + +#if HW_ASSISTED_COHERENCY + uint32_t reg; + + /* + * If we have determined this core to be the last man standing and we + * intend to power down the cluster proactively, we provide a hint to + * the power controller that cluster power is not required when all + * cores are powered down. + * Note that this is only an advisory to power controller and is supported + * by SoCs with DynamIQ Shared Units only. + */ + reg = read_clusterpwrdn(); + + /* Clear and set bit 0 : Cluster power not required */ + reg &= ~DSU_CLUSTER_PWR_MASK; + reg |= DSU_CLUSTER_PWR_OFF; + write_clusterpwrdn(reg); +#endif + + /* Program the power controller to turn the cluster off */ + fvp_pwrc_write_pcoffr(mpidr); +} + +/* + * Empty implementation of these hooks avoid setting the GICR_WAKER.Sleep bit + * on ARM GICv3 implementations on FVP. This is required, because FVP does not + * support SYSTEM_SUSPEND and it is `faked` in firmware. Hence, for wake up + * from `fake` system suspend the GIC must not be powered off. + */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) +{} + +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) +{} + +static void fvp_power_domain_on_finish_common(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* Get the mpidr for this cpu */ + mpidr = read_mpidr_el1(); + + /* Perform the common cluster specific operations */ + if (target_state->pwr_domain_state[ARM_PWR_LVL1] == + ARM_LOCAL_STATE_OFF) { + /* + * This CPU might have woken up whilst the cluster was + * attempting to power down. In this case the FVP power + * controller will have a pending cluster power off request + * which needs to be cleared by writing to the PPONR register. + * This prevents the power controller from interpreting a + * subsequent entry of this cpu into a simple wfi as a power + * down request. + */ + fvp_pwrc_write_pponr(mpidr); + + /* Enable coherency if this cluster was off */ + fvp_interconnect_enable(); + } + /* Perform the common system specific operations */ + if (target_state->pwr_domain_state[ARM_PWR_LVL2] == + ARM_LOCAL_STATE_OFF) + arm_system_pwr_domain_resume(); + + /* + * Clear PWKUPR.WEN bit to ensure interrupts do not interfere + * with a cpu power down unless the bit is set again + */ + fvp_pwrc_clr_wen(mpidr); +} + +/******************************************************************************* + * FVP handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void fvp_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr = read_scr_el3(); + + assert(cpu_state == ARM_LOCAL_STATE_RET); + + /* + * Enable the Non-secure interrupt to wake the CPU. + * In GICv3 affinity routing mode, the Non-secure Group 1 interrupts + * use Physical FIQ at EL3 whereas in GICv2, Physical IRQ is used. + * Enabling both the bits works for both GICv2 mode and GICv3 affinity + * routing mode. + */ + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + isb(); + + /* + * Enter standby state. + * dsb is good practice before using wfi to enter low power states. + */ + dsb(); + wfi(); + + /* + * Restore SCR_EL3 to the original value, synchronisation of SCR_EL3 + * is done by eret in el3_exit() to save some execution cycles. + */ + write_scr_el3(scr); +} + +/******************************************************************************* + * FVP handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int fvp_pwr_domain_on(u_register_t mpidr) +{ + int rc = PSCI_E_SUCCESS; + unsigned int psysr; + + /* + * Ensure that we do not cancel an inflight power off request for the + * target cpu. That would leave it in a zombie wfi. Wait for it to power + * off and then program the power controller to turn that CPU on. + */ + do { + psysr = fvp_pwrc_read_psysr(mpidr); + } while ((psysr & PSYSR_AFF_L0) != 0U); + + fvp_pwrc_write_pponr(mpidr); + return rc; +} + +/******************************************************************************* + * FVP handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void fvp_pwr_domain_off(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* + * If execution reaches this stage then this power domain will be + * suspended. Perform at least the cpu specific actions followed + * by the cluster specific operations if applicable. + */ + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_arm_gic_cpuif_disable(); + + /* Turn redistributor off */ + plat_arm_gic_redistif_off(); + + /* Program the power controller to power off this cpu. */ + fvp_pwrc_write_ppoffr(read_mpidr_el1()); + + if (target_state->pwr_domain_state[ARM_PWR_LVL1] == + ARM_LOCAL_STATE_OFF) + fvp_cluster_pwrdwn_common(); + +} + +/******************************************************************************* + * FVP handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void fvp_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + + /* + * FVP has retention only at cpu level. Just return + * as nothing is to be done for retention. + */ + if (target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_RET) + return; + + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* Get the mpidr for this cpu */ + mpidr = read_mpidr_el1(); + + /* Program the power controller to enable wakeup interrupts. */ + fvp_pwrc_set_wen(mpidr); + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_arm_gic_cpuif_disable(); + + /* + * The Redistributor is not powered off as it can potentially prevent + * wake up events reaching the CPUIF and/or might lead to losing + * register context. + */ + + /* Perform the common cluster specific operations */ + if (target_state->pwr_domain_state[ARM_PWR_LVL1] == + ARM_LOCAL_STATE_OFF) + fvp_cluster_pwrdwn_common(); + + /* Perform the common system specific operations */ + if (target_state->pwr_domain_state[ARM_PWR_LVL2] == + ARM_LOCAL_STATE_OFF) + arm_system_pwr_domain_save(); + + /* Program the power controller to power off this cpu. */ + fvp_pwrc_write_ppoffr(read_mpidr_el1()); +} + +/******************************************************************************* + * FVP handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +static void fvp_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + fvp_power_domain_on_finish_common(target_state); + +} + +/******************************************************************************* + * FVP handler called when a power domain has just been powered on and the cpu + * and its cluster are fully participating in coherent transaction on the + * interconnect. Data cache must be enabled for CPU at this point. + ******************************************************************************/ +static void fvp_pwr_domain_on_finish_late(const psci_power_state_t *target_state) +{ + /* Program GIC per-cpu distributor or re-distributor interface */ + plat_arm_gic_pcpu_init(); + + /* Enable GIC CPU interface */ + plat_arm_gic_cpuif_enable(); +} + +/******************************************************************************* + * FVP handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ******************************************************************************/ +static void fvp_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + /* + * Nothing to be done on waking up from retention from CPU level. + */ + if (target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_RET) + return; + + fvp_power_domain_on_finish_common(target_state); + + /* Enable GIC CPU interface */ + plat_arm_gic_cpuif_enable(); +} + +/******************************************************************************* + * FVP handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 fvp_system_off(void) +{ + /* Write the System Configuration Control Register */ + mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL, + V2M_CFGCTRL_START | + V2M_CFGCTRL_RW | + V2M_CFGCTRL_FUNC(V2M_FUNC_SHUTDOWN)); + wfi(); + ERROR("FVP System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 fvp_system_reset(void) +{ + /* Write the System Configuration Control Register */ + mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL, + V2M_CFGCTRL_START | + V2M_CFGCTRL_RW | + V2M_CFGCTRL_FUNC(V2M_FUNC_REBOOT)); + wfi(); + ERROR("FVP System Reset: operation not handled.\n"); + panic(); +} + +static int fvp_node_hw_state(u_register_t target_cpu, + unsigned int power_level) +{ + unsigned int psysr; + int ret; + + /* + * The format of 'power_level' is implementation-defined, but 0 must + * mean a CPU. We also allow 1 to denote the cluster + */ + if ((power_level != ARM_PWR_LVL0) && (power_level != ARM_PWR_LVL1)) + return PSCI_E_INVALID_PARAMS; + + /* + * Read the status of the given MPDIR from FVP power controller. The + * power controller only gives us on/off status, so map that to expected + * return values of the PSCI call + */ + psysr = fvp_pwrc_read_psysr(target_cpu); + if (psysr == PSYSR_INVALID) + return PSCI_E_INVALID_PARAMS; + + if (power_level == ARM_PWR_LVL0) { + ret = ((psysr & PSYSR_AFF_L0) != 0U) ? HW_ON : HW_OFF; + } else { + /* power_level == ARM_PWR_LVL1 */ + ret = ((psysr & PSYSR_AFF_L1) != 0U) ? HW_ON : HW_OFF; + } + + return ret; +} + +/* + * The FVP doesn't truly support power management at SYSTEM power domain. The + * SYSTEM_SUSPEND will be down-graded to the cluster level within the platform + * layer. The `fake` SYSTEM_SUSPEND allows us to validate some of the driver + * save and restore sequences on FVP. + */ +#if !ARM_BL31_IN_DRAM +static void fvp_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF; +} +#endif + +/******************************************************************************* + * Handler to filter PSCI requests. + ******************************************************************************/ +/* + * The system power domain suspend is only supported only via + * PSCI SYSTEM_SUSPEND API. PSCI CPU_SUSPEND request to system power domain + * will be downgraded to the lower level. + */ +static int fvp_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int rc; + rc = arm_validate_power_state(power_state, req_state); + + /* + * Ensure that the system power domain level is never suspended + * via PSCI CPU SUSPEND API. Currently system suspend is only + * supported via PSCI SYSTEM SUSPEND API. + */ + req_state->pwr_domain_state[ARM_PWR_LVL2] = ARM_LOCAL_STATE_RUN; + return rc; +} + +/* + * Custom `translate_power_state_by_mpidr` handler for FVP. Unlike in the + * `fvp_validate_power_state`, we do not downgrade the system power + * domain level request in `power_state` as it will be used to query the + * PSCI_STAT_COUNT/RESIDENCY at the system power domain level. + */ +static int fvp_translate_power_state_by_mpidr(u_register_t mpidr, + unsigned int power_state, + psci_power_state_t *output_state) +{ + return arm_validate_power_state(power_state, output_state); +} + +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t plat_arm_psci_pm_ops = { + .cpu_standby = fvp_cpu_standby, + .pwr_domain_on = fvp_pwr_domain_on, + .pwr_domain_off = fvp_pwr_domain_off, + .pwr_domain_suspend = fvp_pwr_domain_suspend, + .pwr_domain_on_finish = fvp_pwr_domain_on_finish, + .pwr_domain_on_finish_late = fvp_pwr_domain_on_finish_late, + .pwr_domain_suspend_finish = fvp_pwr_domain_suspend_finish, + .system_off = fvp_system_off, + .system_reset = fvp_system_reset, + .validate_power_state = fvp_validate_power_state, + .validate_ns_entrypoint = arm_validate_psci_entrypoint, + .translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr, + .get_node_hw_state = fvp_node_hw_state, +#if !ARM_BL31_IN_DRAM + /* + * The TrustZone Controller is set up during the warmboot sequence after + * resuming the CPU from a SYSTEM_SUSPEND. If BL31 is located in SRAM + * this is not a problem but, if it is in TZC-secured DRAM, it tries to + * reconfigure the same memory it is running on, causing an exception. + */ + .get_sys_suspend_power_state = fvp_get_sys_suspend_power_state, +#endif + .mem_protect_chk = arm_psci_mem_protect_chk, + .read_mem_protect = arm_psci_read_mem_protect, + .write_mem_protect = arm_nor_psci_write_mem_protect, +}; + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return ops; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h b/arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h new file mode 100644 index 0000000..3590370 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_PRIVATE_H +#define FVP_PRIVATE_H + +#include + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void fvp_config_setup(void); + +void fvp_interconnect_init(void); +void fvp_interconnect_enable(void); +void fvp_interconnect_disable(void); +void fvp_timer_init(void); +void tsp_early_platform_setup(void); + +#endif /* FVP_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c new file mode 100644 index 0000000..b32f557 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +static uint8_t sample_attest_priv_key[] = { + 0x20, 0x11, 0xC7, 0xF0, 0x3C, 0xEE, 0x43, 0x25, 0x17, 0x6E, + 0x52, 0x4F, 0x03, 0x3C, 0x0C, 0xE1, 0xE2, 0x1A, 0x76, 0xE6, + 0xC1, 0xA4, 0xF0, 0xB8, 0x39, 0xAA, 0x1D, 0xF6, 0x1E, 0x0E, + 0x8A, 0x5C, 0x8A, 0x05, 0x74, 0x0F, 0x9B, 0x69, 0xEF, 0xA7, + 0xEB, 0x1A, 0x41, 0x85, 0xBD, 0x11, 0x7F, 0x68 +}; + +int plat_get_cca_realm_attest_key(uintptr_t buf, size_t *len, unsigned int type) +{ + assert(type == ATTEST_KEY_CURVE_ECC_SECP384R1); + + if (*len < sizeof(sample_attest_priv_key)) { + return -EINVAL; + } + + (void)memcpy((void *)buf, sample_attest_priv_key, + sizeof(sample_attest_priv_key)); + *len = sizeof(sample_attest_priv_key); + + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c new file mode 100644 index 0000000..573d92e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * The Base FVP has a TrustZone address space controller, the Foundation + * FVP does not. Trying to program the device on the foundation FVP will + * cause an abort. + * + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ + + const arm_tzc_regions_info_t fvp_tzc_regions[] = { + ARM_TZC_REGIONS_DEF, +#if !SPM_MM && !ENABLE_RME + {FVP_DRAM3_BASE, FVP_DRAM3_END, + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, + {FVP_DRAM4_BASE, FVP_DRAM4_END, + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, + {FVP_DRAM5_BASE, FVP_DRAM5_END, + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, + {FVP_DRAM6_BASE, FVP_DRAM6_END, + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, +#endif + {0} + }; + + if ((get_arm_config()->flags & ARM_CONFIG_HAS_TZC) != 0U) + arm_tzc400_setup(PLAT_ARM_TZC_BASE, fvp_tzc_regions); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c new file mode 100644 index 0000000..e940a12 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * Ideally, a random number should be returned instead of the + * combination of a timer's value and a compile-time constant. As the + * FVP does not have any random number generator, this is better than + * nothing but not necessarily really secure. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} + diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c new file mode 100644 index 0000000..80cfbd5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c @@ -0,0 +1,123 @@ +/* + * 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 + +/* The FVP power domain tree descriptor */ +static unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 2]; + + +CASSERT(((FVP_CLUSTER_COUNT > 0) && (FVP_CLUSTER_COUNT <= 256)), + assert_invalid_fvp_cluster_count); + +/******************************************************************************* + * This function dynamically constructs the topology according to cpu-map node + * in HW_CONFIG dtb and returns it. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + uint32_t cluster_count, cpus_per_cluster; + + /* + * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and + * BL2_AT_EL3 systems. + */ +#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3 + cluster_count = FVP_CLUSTER_COUNT; + cpus_per_cluster = FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU; +#else + cluster_count = FCONF_GET_PROPERTY(hw_config, topology, plat_cluster_count); + cpus_per_cluster = FCONF_GET_PROPERTY(hw_config, topology, cluster_cpu_count); + /* Several FVP Models use the same blanket dts. Ex: FVP_Base_Cortex-A65x4 + * and FVP_Base_Cortex-A65AEx8 both use same dts but have different number of + * CPUs in the cluster, as reflected by build flags FVP_MAX_CPUS_PER_CLUSTER. + * Take the minimum of two to ensure PSCI functions do not exceed the size of + * the PSCI data structures allocated at build time. + */ + cpus_per_cluster = MIN(cpus_per_cluster, + (uint32_t)(FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU)); + +#endif + + assert(cluster_count > 0U); + assert(cpus_per_cluster > 0U); + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + fvp_power_domain_tree_desc[0] = 1; + fvp_power_domain_tree_desc[1] = (unsigned char)cluster_count; + + for (i = 0; i < cluster_count; i++) + fvp_power_domain_tree_desc[i + 2] = (unsigned char)cpus_per_cluster; + + return fvp_power_domain_tree_desc; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return FVP_MAX_CPUS_PER_CLUSTER; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int clus_id, cpu_id, thread_id; + + /* Validate affinity fields */ + if ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) { + thread_id = MPIDR_AFFLVL0_VAL(mpidr); + cpu_id = MPIDR_AFFLVL1_VAL(mpidr); + clus_id = MPIDR_AFFLVL2_VAL(mpidr); + } else { + thread_id = 0; + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + clus_id = MPIDR_AFFLVL1_VAL(mpidr); + } + + if (clus_id >= FVP_CLUSTER_COUNT) + return -1; + if (cpu_id >= FVP_MAX_CPUS_PER_CLUSTER) + return -1; + if (thread_id >= FVP_MAX_PE_PER_CPU) + return -1; + + if (fvp_pwrc_read_psysr(mpidr) == PSYSR_INVALID) + return -1; + + /* + * Core position calculation for FVP platform depends on the MT bit in + * MPIDR. This function cannot assume that the supplied MPIDR has the MT + * bit set even if the implementation has. For example, PSCI clients + * might supply MPIDR values without the MT bit set. Therefore, we + * inject the current PE's MT bit so as to get the calculation correct. + * This of course assumes that none or all CPUs on the platform has MT + * bit set. + */ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return (int) plat_arm_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c new file mode 100644 index 0000000..1ea37f7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c @@ -0,0 +1,71 @@ +/* + * 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 + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} + +/* + * Store a new non-volatile counter value. + * + * On some FVP versions, the non-volatile counters are read-only so this + * function will always fail. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + const char *oid; + uintptr_t nv_ctr_addr; + + assert(cookie != NULL); + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + TRUSTED_NV_CTR_ID); + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + NON_TRUSTED_NV_CTR_ID); + } else { + return 1; + } + + mmio_write_32(nv_ctr_addr, nv_ctr); + + /* + * If the FVP models a locked counter then its value cannot be updated + * and the above write operation has been silently ignored. + */ + return (mmio_read_32(nv_ctr_addr) == nv_ctr) ? 0 : 1; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h new file mode 100644 index 0000000..ca85f7a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_HW_CONFIG_GETTER_H +#define FCONF_HW_CONFIG_GETTER_H + +#include + +/* Hardware Config related getter */ +#define hw_config__gicv3_config_getter(prop) gicv3_config.prop +#define hw_config__topology_getter(prop) soc_topology.prop +#define hw_config__uart_serial_config_getter(prop) uart_serial_config.prop +#define hw_config__cpu_timer_getter(prop) cpu_timer.prop + +struct gicv3_config_t { + uint64_t gicd_base; + uint64_t gicr_base; +}; + +struct hw_topology_t { + uint32_t plat_cluster_count; + uint32_t cluster_cpu_count; + uint32_t plat_cpu_count; + uint32_t plat_max_pwr_level; +}; + +struct uart_serial_config_t { + uint64_t uart_base; + uint32_t uart_clk; +}; + +struct cpu_timer_t { + uint32_t clock_freq; +}; + +int fconf_populate_gicv3_config(uintptr_t config); +int fconf_populate_topology(uintptr_t config); +int fconf_populate_uart_config(uintptr_t config); +int fconf_populate_cpu_timer(uintptr_t config); + +extern struct gicv3_config_t gicv3_config; +extern struct hw_topology_t soc_topology; +extern struct uart_serial_config_t uart_serial_config; +extern struct cpu_timer_t cpu_timer; +#endif /* FCONF_HW_CONFIG_GETTER_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h b/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h new file mode 100644 index 0000000..0824c35 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_NT_CONFIG_GETTER_H +#define FCONF_NT_CONFIG_GETTER_H + +#include + +/* NT Firmware Config related getter */ +#define nt_config__event_log_config_getter(prop) event_log.prop + +struct event_log_config_t { +#ifdef SPD_opteed + void *tpm_event_log_sm_addr; +#endif + void *tpm_event_log_addr; + size_t tpm_event_log_size; +}; + +int fconf_populate_event_log_config(uintptr_t config); + +extern struct event_log_config_t event_log_config; + +#endif /* FCONF_NT_CONFIG_GETTER_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h b/arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h new file mode 100644 index 0000000..3010d21 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define EVLOG_CRITICAL_DATA_STRING "CRITICAL DATA" + +#define CRITICAL_DATA_ID CRITICAL_DATA_ID_BASE + +struct fvp_critical_data { + + /* platform NV counters */ + unsigned int nv_ctr[MAX_NV_CTR_IDS]; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S b/arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S new file mode 100644 index 0000000..7c8bf06 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_LD_S +#define PLAT_LD_S + +#include + +#if RECLAIM_INIT_CODE +#include +#endif /* RECLAIM_INIT_CODE */ + +#endif /* PLAT_LD_S */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S new file mode 100644 index 0000000..57f5924 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_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 plat_crash_print_regs + /* + * Detect if we're using the base memory map or + * the legacy VE memory map + */ + mov_imm x0, (V2M_SYSREGS_BASE + V2M_SYS_ID) + ldr w16, [x0] + /* Extract BLD (12th - 15th bits) from the SYS_ID */ + ubfx x16, x16, #V2M_SYS_ID_BLD_SHIFT, #4 + /* Check if VE mmap */ + cmp w16, #BLD_GIC_VE_MMAP + b.eq use_ve_mmap + /* Assume Base Cortex mmap */ + mov_imm x17, BASE_GICC_BASE + mov_imm x16, BASE_GICD_BASE + b print_gic_regs +use_ve_mmap: + mov_imm x17, VE_GICC_BASE + mov_imm x16, VE_GICD_BASE +print_gic_regs: + arm_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h new file mode 100644 index 0000000..5e5ddce --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include + +#include "../fvp_def.h" + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT (U(FVP_CLUSTER_COUNT) * \ + U(FVP_MAX_CPUS_PER_CLUSTER) * \ + U(FVP_MAX_PE_PER_CPU)) + +#define PLAT_NUM_PWR_DOMAINS (U(FVP_CLUSTER_COUNT) + \ + PLATFORM_CORE_COUNT + U(1)) + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ +#define PLAT_ARM_CLUSTER_COUNT U(FVP_CLUSTER_COUNT) + +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */ + +#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x00000000) +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */ + +#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x06000000) +#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */ + +#if ENABLE_RME +#define PLAT_ARM_RMM_BASE (RMM_BASE) +#define PLAT_ARM_RMM_SIZE (RMM_LIMIT - RMM_BASE) +#endif + +/* + * Max size of SPMC is 2MB for fvp. With SPMD enabled this value corresponds to + * max size of BL32 image. + */ +#if defined(SPD_spmd) +#define PLAT_ARM_SPMC_BASE PLAT_ARM_TRUSTED_DRAM_BASE +#define PLAT_ARM_SPMC_SIZE UL(0x200000) /* 2 MB */ +#endif + +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +/* No SCP in FVP */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x0) + +#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) /* 36-bit range */ +#define PLAT_ARM_DRAM2_SIZE ULL(0x780000000) /* 30 GB */ + +#define FVP_DRAM3_BASE ULL(0x8800000000) /* 40-bit range */ +#define FVP_DRAM3_SIZE ULL(0x7800000000) /* 480 GB */ +#define FVP_DRAM3_END (FVP_DRAM3_BASE + FVP_DRAM3_SIZE - 1U) + +#define FVP_DRAM4_BASE ULL(0x88000000000) /* 44-bit range */ +#define FVP_DRAM4_SIZE ULL(0x78000000000) /* 7.5 TB */ +#define FVP_DRAM4_END (FVP_DRAM4_BASE + FVP_DRAM4_SIZE - 1U) + +#define FVP_DRAM5_BASE ULL(0x880000000000) /* 48-bit range */ +#define FVP_DRAM5_SIZE ULL(0x780000000000) /* 120 TB */ +#define FVP_DRAM5_END (FVP_DRAM5_BASE + FVP_DRAM5_SIZE - 1U) + +#define FVP_DRAM6_BASE ULL(0x8800000000000) /* 52-bit range */ +#define FVP_DRAM6_SIZE ULL(0x7800000000000) /* 1920 TB */ +#define FVP_DRAM6_END (FVP_DRAM6_BASE + FVP_DRAM6_SIZE - 1U) + +/* Range of kernel DTB load address */ +#define FVP_DTB_DRAM_MAP_START ULL(0x82000000) +#define FVP_DTB_DRAM_MAP_SIZE ULL(0x02000000) /* 32 MB */ + +#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \ + FVP_DTB_DRAM_MAP_START, \ + FVP_DTB_DRAM_MAP_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) +/* + * Load address of BL33 for this platform port + */ +#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + UL(0x8000000)) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL31) +# if SPM_MM +# define PLAT_ARM_MMAP_ENTRIES 10 +# if ENABLE_RME +# define MAX_XLAT_TABLES 11 +# else +# define MAX_XLAT_TABLES 9 +# endif +# define PLAT_SP_IMAGE_MMAP_REGIONS 30 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10 +# else +# define PLAT_ARM_MMAP_ENTRIES 9 +# if USE_DEBUGFS +# if ENABLE_RME +# define MAX_XLAT_TABLES 10 +# else +# define MAX_XLAT_TABLES 8 +# endif +# else +# if ENABLE_RME +# define MAX_XLAT_TABLES 9 +# else +# define MAX_XLAT_TABLES 7 +# endif +# endif +# endif +#elif defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 9 +# define MAX_XLAT_TABLES 6 +#elif !USE_ROMLIB +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 5 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000) + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000) +#define FVP_BL2_ROMLIB_OPTIMIZATION UL(0x5000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0) +#define FVP_BL2_ROMLIB_OPTIMIZATION UL(0) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT && COT_DESC_IN_DTB +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1E000) - FVP_BL2_ROMLIB_OPTIMIZATION) +#elif CRYPTO_SUPPORT +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - FVP_BL2_ROMLIB_OPTIMIZATION) +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION) +#endif + +#if RESET_TO_BL31 +/* Size of Trusted SRAM - the first 4KB of shared memory - GPT L0 Tables */ +#define PLAT_ARM_MAX_BL31_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE - \ + ARM_L0_GPT_SIZE) +#else +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL31_SIZE (UL(0x3D000) - ARM_L0_GPT_SIZE) +#endif /* RESET_TO_BL31 */ + +#ifndef __aarch64__ +#if RESET_TO_SP_MIN +/* Size of Trusted SRAM - the first 4KB of shared memory */ +#define PLAT_ARM_MAX_BL32_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE) +#else +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current SP_MIN PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +# define PLAT_ARM_MAX_BL32_SIZE UL(0x3B000) +#endif /* RESET_TO_SP_MIN */ +#endif + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if CRYPTO_SUPPORT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x500) +# endif /* CRYPTO_SUPPORT */ +#elif defined(IMAGE_BL2) +# if CRYPTO_SUPPORT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x600) +# endif /* CRYPTO_SUPPORT */ +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE UL(0x400) +#elif defined(IMAGE_BL31) +# define PLATFORM_STACK_SIZE UL(0x800) +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE UL(0x440) +#elif defined(IMAGE_RMM) +# define PLATFORM_STACK_SIZE UL(0x440) +#endif + +#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) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_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_UART2_BASE +#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ + +#define PLAT_ARM_TRP_UART_BASE V2M_IOFPGA_UART3_BASE +#define PLAT_ARM_TRP_UART_CLK_IN_HZ V2M_IOFPGA_UART3_CLK_IN_HZ + +#define PLAT_FVP_SMMUV3_BASE UL(0x2b400000) + +/* CCI related constants */ +#define PLAT_FVP_CCI400_BASE UL(0x2c090000) +#define PLAT_FVP_CCI400_CLUS0_SL_PORT 3 +#define PLAT_FVP_CCI400_CLUS1_SL_PORT 4 + +/* CCI-500/CCI-550 on Base platform */ +#define PLAT_FVP_CCI5XX_BASE UL(0x2a000000) +#define PLAT_FVP_CCI5XX_CLUS0_SL_PORT 5 +#define PLAT_FVP_CCI5XX_CLUS1_SL_PORT 6 + +/* CCN related constants. Only CCN 502 is currently supported */ +#define PLAT_ARM_CCN_BASE UL(0x2e000000) +#define PLAT_ARM_CLUSTER_TO_CCN_ID_MAP 1, 5, 7, 11 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +/* Mailbox base address */ +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE + + +/* TrustZone controller related constants + * + * Currently only filters 0 and 2 are connected on Base FVP. + * Filter 0 : CPU clusters (no access to DRAM by default) + * Filter 1 : not connected + * Filter 2 : LCDs (access to VRAM allowed by default) + * Filter 3 : not connected + * Programming unconnected filters will have no effect at the + * moment. These filter could, however, be connected in future. + * So care should be taken not to configure the unused filters. + * + * Allow only non-secure access to all DRAM to supported devices. + * Give access to the CPUs and Virtio. Some devices + * would normally use the default ID so allow that too. + */ +#define PLAT_ARM_TZC_BASE UL(0x2a4a0000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) | \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_PCI) | \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) | \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO) | \ + TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD)) + +/* + * GIC related constants to cater for both GICv2 and GICv3 instances of an + * FVP. They could be overridden at runtime in case the FVP implements the + * legacy VE memory map. + */ +#define PLAT_ARM_GICD_BASE BASE_GICD_BASE +#define PLAT_ARM_GICR_BASE BASE_GICR_BASE +#define PLAT_ARM_GICC_BASE BASE_GICC_BASE + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(FVP_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(FVP_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#if SDEI_IN_FCONF +#define PLAT_SDEI_DP_EVENT_MAX_CNT ARM_SDEI_DP_EVENT_MAX_CNT +#define PLAT_SDEI_DS_EVENT_MAX_CNT ARM_SDEI_DS_EVENT_MAX_CNT +#else +#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS +#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS +#endif + +#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) + +#define PLAT_SP_PRI PLAT_RAS_PRI + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* + * Maximum size of Event Log buffer used in Measured Boot Event Log driver + */ +#define PLAT_ARM_EVENT_LOG_MAX_SIZE UL(0x400) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i b/arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i new file mode 100644 index 0000000..b72bdab --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i @@ -0,0 +1,61 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Platform specific romlib functions can be added or included here. +# The index in the output file will be generated cumulatively in the same +# order as it is given in this file. +# Output file can be found at: $BUILD_DIR/jmptbl.i +# +# Format: +# lib function [patch] +# Example: +# rom rom_lib_init +# fdt fdt_getprop_namelen patch + +rom rom_lib_init +fdt fdt_getprop +fdt fdt_get_property +fdt fdt_getprop_namelen +fdt fdt_setprop_inplace +fdt fdt_check_header +fdt fdt_node_offset_by_compatible +fdt fdt_setprop_inplace_namelen_partial +fdt fdt_first_subnode +fdt fdt_next_subnode +fdt fdt_path_offset +fdt fdt_path_offset_namelen +fdt fdt_subnode_offset +fdt fdt_address_cells +fdt fdt_size_cells +fdt fdt_parent_offset +fdt fdt_stringlist_search +fdt fdt_get_alias_namelen +fdt fdt_get_name +fdt fdt_get_alias +fdt fdt_node_offset_by_phandle +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/arm-trusted-firmware/plat/arm/board/fvp/platform.mk b/arm-trusted-firmware/plat/arm/board/fvp/platform.mk new file mode 100644 index 0000000..c9f5551 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/platform.mk @@ -0,0 +1,401 @@ +# +# Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +# Use the GICv3 driver on the FVP by default +FVP_USE_GIC_DRIVER := FVP_GICV3 + +# Default cluster count for FVP +FVP_CLUSTER_COUNT := 2 + +# Default number of CPUs per cluster on FVP +FVP_MAX_CPUS_PER_CLUSTER := 4 + +# Default number of threads per CPU on FVP +FVP_MAX_PE_PER_CPU := 1 + +# Disable redistributor frame of inactive/fused CPU cores by marking it as read +# only; enable redistributor frames of all CPU cores by default. +FVP_GICR_REGION_PROTECTION := 0 + +FVP_DT_PREFIX := fvp-base-gicv3-psci + +# The FVP platform depends on this macro to build with correct GIC driver. +$(eval $(call add_define,FVP_USE_GIC_DRIVER)) + +# Pass FVP_CLUSTER_COUNT to the build system. +$(eval $(call add_define,FVP_CLUSTER_COUNT)) + +# Pass FVP_MAX_CPUS_PER_CLUSTER to the build system. +$(eval $(call add_define,FVP_MAX_CPUS_PER_CLUSTER)) + +# Pass FVP_MAX_PE_PER_CPU to the build system. +$(eval $(call add_define,FVP_MAX_PE_PER_CPU)) + +# Pass FVP_GICR_REGION_PROTECTION to the build system. +$(eval $(call add_define,FVP_GICR_REGION_PROTECTION)) + +# Sanity check the cluster count and if FVP_CLUSTER_COUNT <= 2, +# choose the CCI driver , else the CCN driver +ifeq ($(FVP_CLUSTER_COUNT), 0) +$(error "Incorrect cluster count specified for FVP port") +else ifeq ($(FVP_CLUSTER_COUNT),$(filter $(FVP_CLUSTER_COUNT),1 2)) +FVP_INTERCONNECT_DRIVER := FVP_CCI +else +FVP_INTERCONNECT_DRIVER := FVP_CCN +endif + +$(eval $(call add_define,FVP_INTERCONNECT_DRIVER)) + +# Choose the GIC sources depending upon the how the FVP will be invoked +ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3) + +# The GIC model (GIC-600 or GIC-500) will be detected at runtime +GICV3_SUPPORT_GIC600 := 1 +GICV3_OVERRIDE_DISTIF_PWR_OPS := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +FVP_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c + + ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31} ${RESET_TO_SP_MIN}),) + FVP_GIC_SOURCES += plat/arm/board/fvp/fvp_gicv3.c + endif + +else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2) + +# No GICv4 extension +GIC_ENABLE_V4_EXTN := 0 +$(eval $(call add_define,GIC_ENABLE_V4_EXTN)) + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +FVP_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +FVP_DT_PREFIX := fvp-base-gicv2-psci +else +$(error "Incorrect GIC driver chosen on FVP port") +endif + +ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCI) +FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c +else ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCN) +FVP_INTERCONNECT_SOURCES := drivers/arm/ccn/ccn.c \ + plat/arm/common/arm_ccn.c +else +$(error "Incorrect CCN driver chosen on FVP port") +endif + +FVP_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \ + plat/arm/board/fvp/fvp_security.c \ + plat/arm/common/arm_tzc400.c + + +PLAT_INCLUDES := -Iplat/arm/board/fvp/include + + +PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp/fvp_common.c + +FVP_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +ifeq (${ARCH}, aarch64) + +# select a different set of CPU files, depending on whether we compile for +# hardware assisted coherency cores or not +ifeq (${HW_ASSISTED_COHERENCY}, 0) +# Cores used without DSU + FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/cortex_a73.S +else +# Cores used with DSU only + ifeq (${CTX_INCLUDE_AARCH32_REGS}, 0) + # AArch64-only cores + FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a76.S \ + lib/cpus/aarch64/cortex_a76ae.S \ + lib/cpus/aarch64/cortex_a77.S \ + lib/cpus/aarch64/cortex_a78.S \ + lib/cpus/aarch64/neoverse_n_common.S \ + lib/cpus/aarch64/neoverse_n1.S \ + lib/cpus/aarch64/neoverse_n2.S \ + lib/cpus/aarch64/neoverse_e1.S \ + lib/cpus/aarch64/neoverse_v1.S \ + lib/cpus/aarch64/neoverse_demeter.S \ + lib/cpus/aarch64/cortex_a78_ae.S \ + lib/cpus/aarch64/cortex_a510.S \ + lib/cpus/aarch64/cortex_a710.S \ + lib/cpus/aarch64/cortex_makalu.S \ + lib/cpus/aarch64/cortex_makalu_elp_arm.S \ + lib/cpus/aarch64/cortex_a65.S \ + lib/cpus/aarch64/cortex_a65ae.S \ + lib/cpus/aarch64/cortex_a78c.S \ + lib/cpus/aarch64/cortex_hayes.S \ + lib/cpus/aarch64/cortex_hunter.S \ + lib/cpus/aarch64/cortex_x2.S \ + lib/cpus/aarch64/neoverse_poseidon.S + endif + # AArch64/AArch32 cores + FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a75.S +endif + +else +FVP_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S +endif + +BL1_SOURCES += drivers/arm/smmu/smmu_v3.c \ + drivers/arm/sp805/sp805.c \ + drivers/delay_timer/delay_timer.c \ + drivers/io/io_semihosting.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/arm/board/fvp/${ARCH}/fvp_helpers.S \ + plat/arm/board/fvp/fvp_bl1_setup.c \ + plat/arm/board/fvp/fvp_err.c \ + plat/arm/board/fvp/fvp_io_storage.c \ + ${FVP_CPU_LIBS} \ + ${FVP_INTERCONNECT_SOURCES} + +ifeq (${USE_SP804_TIMER},1) +BL1_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +else +BL1_SOURCES += drivers/delay_timer/generic_delay_timer.c +endif + + +BL2_SOURCES += drivers/arm/sp805/sp805.c \ + drivers/io/io_semihosting.c \ + lib/utils/mem_region.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/arm/board/fvp/fvp_bl2_setup.c \ + plat/arm/board/fvp/fvp_err.c \ + plat/arm/board/fvp/fvp_io_storage.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${FVP_SECURITY_SOURCES} + + +ifeq (${COT_DESC_IN_DTB},1) +BL2_SOURCES += plat/arm/common/fconf/fconf_nv_cntr_getter.c +endif + +ifeq (${ENABLE_RME},1) +BL2_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S +BL31_SOURCES += plat/arm/board/fvp/fvp_plat_attest_token.c \ + plat/arm/board/fvp/fvp_realm_attest_key.c +endif + +ifeq (${BL2_AT_EL3},1) +BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \ + plat/arm/board/fvp/fvp_bl2_el3_setup.c \ + ${FVP_CPU_LIBS} \ + ${FVP_INTERCONNECT_SOURCES} +endif + +ifeq (${USE_SP804_TIMER},1) +BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +endif + +BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \ + ${FVP_SECURITY_SOURCES} + +ifeq (${USE_SP804_TIMER},1) +BL2U_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +endif + +BL31_SOURCES += drivers/arm/fvp/fvp_pwrc.c \ + drivers/arm/smmu/smmu_v3.c \ + drivers/delay_timer/delay_timer.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/fvp/fvp_bl31_setup.c \ + plat/arm/board/fvp/fvp_console.c \ + plat/arm/board/fvp/fvp_pm.c \ + plat/arm/board/fvp/fvp_topology.c \ + plat/arm/board/fvp/aarch64/fvp_helpers.S \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${FVP_CPU_LIBS} \ + ${FVP_GIC_SOURCES} \ + ${FVP_INTERCONNECT_SOURCES} \ + ${FVP_SECURITY_SOURCES} + +# Support for fconf in BL31 +# Added separately from the above list for better readability +ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),) +BL31_SOURCES += lib/fconf/fconf.c \ + lib/fconf/fconf_dyn_cfg_getter.c \ + plat/arm/board/fvp/fconf/fconf_hw_config_getter.c + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +ifeq (${SEC_INT_DESC_IN_FCONF},1) +BL31_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c +endif + +endif + +ifeq (${USE_SP804_TIMER},1) +BL31_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +else +BL31_SOURCES += drivers/delay_timer/generic_delay_timer.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env) +ifdef UNIX_MK +FVP_HW_CONFIG_DTS := fdts/${FVP_DT_PREFIX}.dts +FDT_SOURCES += $(addprefix plat/arm/board/fvp/fdts/, \ + ${PLAT}_fw_config.dts \ + ${PLAT}_tb_fw_config.dts \ + ${PLAT}_soc_fw_config.dts \ + ${PLAT}_nt_fw_config.dts \ + ) + +FVP_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb +FVP_SOC_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_soc_fw_config.dtb +FVP_NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +ifeq (${SPD},tspd) +FDT_SOURCES += plat/arm/board/fvp/fdts/${PLAT}_tsp_fw_config.dts +FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tsp_fw_config.dtb + +# Add the TOS_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config,${FVP_TOS_FW_CONFIG})) +endif + +ifeq (${SPD},spmd) + +ifeq ($(ARM_SPMC_MANIFEST_DTS),) +ARM_SPMC_MANIFEST_DTS := plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts +endif + +FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS} +FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb + +# Add the TOS_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config,${FVP_TOS_FW_CONFIG})) +endif + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config,${FVP_FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config,${FVP_TB_FW_CONFIG})) +# Add the SOC_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_SOC_FW_CONFIG},--soc-fw-config,${FVP_SOC_FW_CONFIG})) +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_NT_FW_CONFIG},--nt-fw-config,${FVP_NT_FW_CONFIG})) + +FDT_SOURCES += ${FVP_HW_CONFIG_DTS} +$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(FVP_HW_CONFIG_DTS))) + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG})) +endif + +# Enable Activity Monitor Unit extensions by default +ENABLE_AMU := 1 + +# Enable dynamic mitigation support by default +DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 + +ifeq (${ENABLE_AMU},1) +BL31_SOURCES += lib/cpus/aarch64/cpuamu.c \ + lib/cpus/aarch64/cpuamu_helpers.S + +ifeq (${HW_ASSISTED_COHERENCY}, 1) +BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \ + lib/cpus/aarch64/neoverse_n1_pubsub.c +endif +endif + +ifeq (${RAS_EXTENSION},1) +BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ras.c +endif + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c +endif + +ifeq (${ARCH},aarch32) + NEED_BL32 := yes +endif + +# Enable the dynamic translation tables library. +ifeq (${ARCH},aarch32) + ifeq (${RESET_TO_SP_MIN},1) + BL32_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +else # AArch64 + ifeq (${RESET_TO_BL31},1) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif + ifeq (${SPD},trusty) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +endif + +ifeq (${ENABLE_RME},1) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC +endif + +ifeq (${ALLOW_RO_XLAT_TABLES}, 1) + ifeq (${ARCH},aarch32) + BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + else # AArch64 + BL31_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + ifeq (${SPD},tspd) + BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + endif + endif +endif + +ifeq (${USE_DEBUGFS},1) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC +endif + +# Add support for platform supplied linker script for BL31 build +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +ifneq (${BL2_AT_EL3}, 0) + override BL1_SOURCES = +endif + +include plat/arm/board/common/board_common.mk +include plat/arm/common/arm_common.mk + +ifeq (${MEASURED_BOOT},1) +BL1_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \ + plat/arm/board/fvp/fvp_bl1_measured_boot.c +BL2_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \ + plat/arm/board/fvp/fvp_bl2_measured_boot.c +endif + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c +BL2_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c + +# FVP being a development platform, enable capability to disable Authentication +# dynamically if TRUSTED_BOARD_BOOT is set. +DYN_DISABLE_AUTH := 1 +endif + +# enable trace buffer control registers access to NS by default +ENABLE_TRBE_FOR_NS := 1 + +# enable trace system registers access to NS by default +ENABLE_SYS_REG_TRACE_FOR_NS := 1 + +# enable trace filter control registers access to NS by default +ENABLE_TRF_FOR_NS := 1 diff --git a/arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c new file mode 100644 index 0000000..763b42a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include "../fvp_private.h" + +uintptr_t hw_config_dtb; + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize the correct interconnect for this cluster during cold + * boot. No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * FVP PSCI code will enable coherency for other clusters. + */ + fvp_interconnect_enable(); + + hw_config_dtb = arg2; +} + +void sp_min_plat_arch_setup(void) +{ + arm_sp_min_plat_arch_setup(); + + /* + * For RESET_TO_SP_MIN systems, SP_MIN(BL32) is the first bootloader + * to run. So there is no BL2 to load the HW_CONFIG dtb into memory + * before control is passed to SP_MIN. + * Also, BL2 skips loading HW_CONFIG dtb for BL2_AT_EL3 builds. + */ +#if !RESET_TO_SP_MIN && !BL2_AT_EL3 + assert(hw_config_dtb != 0U); + + INFO("SP_MIN FCONF: HW_CONFIG address = %p\n", (void *)hw_config_dtb); + fconf_populate("HW_CONFIG", hw_config_dtb); +#endif +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/arm-trusted-firmware/plat/arm/board/fvp/sp_min/sp_min-fvp.mk new file mode 100644 index 0000000..0d8cca5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/sp_min/sp_min-fvp.mk @@ -0,0 +1,38 @@ +# +# Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +# SP_MIN source files specific to FVP platform +BL32_SOURCES += drivers/arm/fvp/fvp_pwrc.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/fvp/aarch32/fvp_helpers.S \ + plat/arm/board/fvp/fvp_pm.c \ + plat/arm/board/fvp/fvp_console.c \ + plat/arm/board/fvp/fvp_topology.c \ + plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${FVP_CPU_LIBS} \ + ${FVP_GIC_SOURCES} \ + ${FVP_INTERCONNECT_SOURCES} \ + ${FVP_SECURITY_SOURCES} + +# Support for fconf in SP_MIN(BL32) +# Added separately from the above list for better readability +ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_SP_MIN}),) +BL32_SOURCES += lib/fconf/fconf.c \ + plat/arm/board/fvp/fconf/fconf_hw_config_getter.c + +BL32_SOURCES += ${FDT_WRAPPERS_SOURCES} + +ifeq (${SEC_INT_DESC_IN_FCONF},1) +BL32_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c +endif + +endif + +include plat/arm/common/sp_min/arm_sp_min.mk diff --git a/arm-trusted-firmware/plat/arm/board/fvp/trp/trp-fvp.mk b/arm-trusted-firmware/plat/arm/board/fvp/trp/trp-fvp.mk new file mode 100644 index 0000000..a450541 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/trp/trp-fvp.mk @@ -0,0 +1,12 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# TRP source files specific to FVP platform + +RMM_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S + +include plat/arm/common/trp/arm_trp.mk + diff --git a/arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c new file mode 100644 index 0000000..3c8a963 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "../fvp_private.h" + +void tsp_early_platform_setup(void) +{ + arm_tsp_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/tsp/tsp-fvp.mk b/arm-trusted-firmware/plat/arm/board/fvp/tsp/tsp-fvp.mk new file mode 100644 index 0000000..ab3f225 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/tsp/tsp-fvp.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# TSP source files specific to FVP platform +BL32_SOURCES += drivers/arm/fvp/fvp_pwrc.c \ + plat/arm/board/fvp/aarch64/fvp_helpers.S \ + plat/arm/board/fvp/fvp_topology.c \ + plat/arm/board/fvp/tsp/fvp_tsp_setup.c \ + ${FVP_GIC_SOURCES} + +include plat/arm/common/tsp/arm_tsp.mk diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c new file mode 100644 index 0000000..ae6af6c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../../../../bl1/bl1_private.h" +#include + +#include + +/******************************************************************************* + * Function that does the first bit of architectural setup that affects + * execution in the non-secure address space. + ******************************************************************************/ +void bl1_arch_setup(void) +{ + /* v8-R64 does not include SCRs. */ +} + +/******************************************************************************* + * Set the Secure EL1 required architectural state + ******************************************************************************/ +void bl1_arch_next_el_setup(void) +{ + u_register_t next_sctlr; + + /* Use the same endianness than the current BL */ + next_sctlr = (read_sctlr_el2() & SCTLR_EE_BIT); + + /* Set SCTLR Secure EL1 */ + next_sctlr |= SCTLR_EL1_RES1; + + write_sctlr_el1(next_sctlr); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S new file mode 100644 index 0000000..15f4c43 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl bl1_entrypoint + .globl bl1_run_next_image + + + /* ----------------------------------------------------- + * bl1_entrypoint() is the entry point into the trusted + * firmware code when a cpu is released from warm or + * cold reset. + * ----------------------------------------------------- + */ + +func bl1_entrypoint + /* --------------------------------------------------------------------- + * If the reset address is programmable then bl1_entrypoint() is + * executed only on the cold boot path. Therefore, we can skip the warm + * boot mailbox mechanism. + * --------------------------------------------------------------------- + */ + el2_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=bl1_exceptions \ + _pie_fixup_size=0 + + /* -------------------------------------------------------------------- + * Perform BL1 setup + * -------------------------------------------------------------------- + */ + bl bl1_setup + + /* -------------------------------------------------------------------- + * Initialize platform and jump to our c-entry point + * for this type of reset. + * -------------------------------------------------------------------- + */ + bl bl1_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler +endfunc bl1_entrypoint + +func bl1_run_next_image + mov x20,x0 + + /* --------------------------------------------- + * MPU needs to be disabled because both BL1 and BL33 execute + * in EL2, and therefore share the same address space. + * BL33 will initialize the address space according to its + * own requirement. + * --------------------------------------------- + */ + bl disable_mpu_icache_el2 + + /* --------------------------------------------- + * Wipe clean and disable all MPU regions. This function expects + * that the MPU has already been turned off, and caching concerns + * addressed, but it also explicitly turns off the MPU. + * --------------------------------------------- + */ + bl clear_all_mpu_regions + + /* -------------------------------------------------- + * Do the transition to next boot image. + * -------------------------------------------------- + */ + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el2, x0 + msr spsr_el2, 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 bl1_run_next_image diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S new file mode 100644 index 0000000..43c2e01 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * File contains an EL2 equivalent of the EL3 vector table from: + * .../bl1/aarch64/bl1_exceptions.S + * ----------------------------------------------------------------------------- + */ + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL1. + * ----------------------------------------------------------------------------- + */ + .globl bl1_exceptions + +vector_base bl1_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 + /* The current v8-R64 implementation does not support conduit calls */ + b el2_panic +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 + + +unexpected_sync_exception: + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + + /* ----------------------------------------------------- + * Save Secure/Normal world context and jump to + * BL1 SMC handler. + * ----------------------------------------------------- + */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c new file mode 100644 index 0000000..841a176 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "../../../../bl1/bl1_private.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +void cm_prepare_el2_exit(void); + +void bl1_run_next_image(const struct entry_point_info *bl_ep_info); + +/******************************************************************************* + * Function to perform late architectural and platform specific initialization. + * It also queries the platform to load and run next BL image. Only called + * by the primary cpu after a cold boot. + ******************************************************************************/ +void bl1_transfer_bl33(void) +{ + unsigned int image_id; + + /* Get the image id of next image to load and run. */ + image_id = bl1_plat_get_next_image_id(); + +#if !ARM_DISABLE_TRUSTED_WDOG + /* Disable watchdog before leaving BL1 */ + plat_arm_secure_wdt_stop(); +#endif + + bl1_run_next_image(&bl1_plat_get_image_desc(image_id)->ep_info); +} + +/******************************************************************************* + * This function locates and loads the BL33 raw binary image in the trusted SRAM. + * Called by the primary cpu after a cold boot. + * TODO: Add support for alternative image load mechanism e.g using virtio/elf + * loader etc. + ******************************************************************************/ +void bl1_load_bl33(void) +{ + image_desc_t *desc; + image_info_t *info; + int err; + + /* Get the image descriptor */ + desc = bl1_plat_get_image_desc(BL33_IMAGE_ID); + assert(desc != NULL); + + /* Get the image info */ + info = &desc->image_info; + INFO("BL1: Loading BL33\n"); + + err = bl1_plat_handle_pre_image_load(BL33_IMAGE_ID); + if (err != 0) { + ERROR("Failure in pre image load handling of BL33 (%d)\n", err); + plat_error_handler(err); + } + + err = load_auth_image(BL33_IMAGE_ID, info); + if (err != 0) { + ERROR("Failed to load BL33 firmware.\n"); + plat_error_handler(err); + } + + /* Allow platform to handle image information. */ + err = bl1_plat_handle_post_image_load(BL33_IMAGE_ID); + if (err != 0) { + ERROR("Failure in post image load handling of BL33 (%d)\n", err); + plat_error_handler(err); + } + + NOTICE("BL1: Booting BL33\n"); +} + +/******************************************************************************* + * Helper utility to calculate the BL2 memory layout taking into consideration + * the BL1 RW data assuming that it is at the top of the memory layout. + ******************************************************************************/ +void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout, + meminfo_t *bl2_mem_layout) +{ + assert(bl1_mem_layout != NULL); + assert(bl2_mem_layout != NULL); + + /* + * Remove BL1 RW data from the scope of memory visible to BL2. + * This is assuming BL1 RW data is at the top of bl1_mem_layout. + */ + assert(bl1_mem_layout->total_base < BL1_RW_BASE); + bl2_mem_layout->total_base = bl1_mem_layout->total_base; + bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base; + + flush_dcache_range((uintptr_t)bl2_mem_layout, sizeof(meminfo_t)); +} + +/******************************************************************************* + * This function prepares for entry to BL33 + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + unsigned int mode = MODE_EL1; + image_desc_t *desc; + entry_point_info_t *next_bl_ep; + +#if CTX_INCLUDE_AARCH32_REGS + /* + * Ensure that the build flag to save AArch32 system registers in CPU + * context is not set for AArch64-only platforms. + */ + if (el_implemented(1) == EL_IMPL_A64ONLY) { + ERROR("EL1 supports AArch64-only. Please set build flag %s", + "CTX_INCLUDE_AARCH32_REGS = 0\n"); + panic(); + } +#endif + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + assert(desc != NULL); + + /* Get the entry point info. */ + next_bl_ep = &desc->ep_info; + + /* FVP-R is only secure */ + assert(GET_SECURITY_STATE(next_bl_ep->h.attr) == SECURE); + + /* Prepare the SPSR for the next BL image. */ + next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode, + (uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + + /* Allow platform to make change */ + bl1_plat_set_ep_info(image_id, next_bl_ep); + + /* Prepare context for the next EL */ + cm_prepare_el2_exit(); + + /* Indicate that image is in execution state. */ + desc->state = IMAGE_STATE_EXECUTED; + + print_entry_point_info(next_bl_ep); +} + +/******************************************************************************* + * Setup function for BL1. + ******************************************************************************/ +void bl1_setup(void) +{ + /* Perform early platform-specific setup */ + bl1_early_platform_setup(); + + /* Perform late platform-specific setup */ + bl1_plat_arch_setup(); +} + +/******************************************************************************* + * Function to perform late architectural and platform specific initialization. + * It also queries the platform to load and run next BL image. Only called + * by the primary cpu after a cold boot. + ******************************************************************************/ +void bl1_main(void) +{ + unsigned int image_id; + + /* Announce our arrival */ + NOTICE(FIRMWARE_WELCOME_STR); + NOTICE("BL1: %s\n", version_string); + NOTICE("BL1: %s\n", build_message); + + INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE, (void *)BL1_RAM_LIMIT); + + print_errata_status(); + +#if ENABLE_ASSERTIONS + u_register_t val; + /* + * Ensure that MMU/Caches and coherency are turned on + */ + val = read_sctlr_el2(); + + assert((val & SCTLR_M_BIT) != 0U); + assert((val & SCTLR_C_BIT) != 0U); + assert((val & SCTLR_I_BIT) != 0U); + /* + * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the + * provided platform value + */ + val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK; + /* + * If CWG is zero, then no CWG information is available but we can + * at least check the platform value is less than the architectural + * maximum. + */ + if (val != 0) { + assert(SIZE_FROM_LOG2_WORDS(val) == CACHE_WRITEBACK_GRANULE); + } else { + assert(MAX_CACHE_LINE_SIZE >= CACHE_WRITEBACK_GRANULE); + } +#endif /* ENABLE_ASSERTIONS */ + + /* Perform remaining generic architectural setup from ELmax */ + bl1_arch_setup(); + +#if TRUSTED_BOARD_BOOT + /* Initialize authentication module */ + auth_mod_init(); +#endif /* TRUSTED_BOARD_BOOT */ + + /* Perform platform setup in BL1. */ + bl1_platform_setup(); + + /* Get the image id of next image to load and run. */ + image_id = bl1_plat_get_next_image_id(); + + /* + * We currently interpret any image id other than + * BL2_IMAGE_ID as the start of firmware update. + */ + if (image_id == BL33_IMAGE_ID) { + bl1_load_bl33(); + } else { + NOTICE("BL1-FWU: *******FWU Process Started*******\n"); + } + + bl1_prepare_next_image(image_id); + + console_flush(); + + bl1_transfer_bl33(); +} + +/******************************************************************************* + * Function called just before handing over to the next BL to inform the user + * about the boot progress. In debug mode, also print details about the BL + * image's execution context. + ******************************************************************************/ +void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info) +{ + NOTICE("BL1: Booting BL31\n"); + print_entry_point_info(bl_ep_info); +} + +#if SPIN_ON_BL1_EXIT +void print_debug_loop_message(void) +{ + NOTICE("BL1: Debug loop, spinning forever\n"); + NOTICE("BL1: Please connect the debugger to continue\n"); +} +#endif + diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c new file mode 100644 index 0000000..68872c1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Use the xlat_tables_v2 data structures: */ +#define XLAT_TABLES_LIB_V2 1 + +#include + +#include +#include +#include +#include +#include +#include + +#include "fvp_r_private.h" +#include +#include +#include +#include +#include + +#define MAP_BL1_TOTAL MAP_REGION_FLAT( \ + bl1_tzram_layout.total_base, \ + bl1_tzram_layout.total_size, \ + 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 MAP_BL1_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL1_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE), \ + MAP_REGION_FLAT( \ + BL1_RO_DATA_BASE, \ + BL1_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) +#else +#define MAP_BL1_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL1_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE) +#endif + +/* Data structure which holds the extents of the trusted SRAM for BL1*/ +static meminfo_t bl1_tzram_layout; + +struct meminfo *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +void arm_bl1_early_platform_setup(void) +{ + +#if !ARM_DISABLE_TRUSTED_WDOG + /* Enable watchdog */ + plat_arm_secure_wdt_start(); +#endif + + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = ARM_BL_RAM_BASE; + bl1_tzram_layout.total_size = ARM_BL_RAM_SIZE; +} + +/* Boolean variable to hold condition whether firmware update needed or not */ +static bool is_fwu_needed; + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + /* + * Enable coherency in Interconnect for the primary CPU's cluster. + */ + fvp_interconnect_enable(); +} + +void arm_bl1_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_BL1_TOTAL, + MAP_BL1_RO, +#if USE_ROMLIB + ARM_MAP_ROMLIB_CODE, + ARM_MAP_ROMLIB_DATA, +#endif +#if ARM_CRYPTOCELL_INTEG + ARM_MAP_BL_COHERENT_RAM, +#endif + /* DRAM1_region: */ + MAP_REGION_FLAT( \ + PLAT_ARM_DRAM1_BASE, \ + PLAT_ARM_DRAM1_SIZE, \ + MT_MEMORY | MT_SECURE | MT_EXECUTE \ + | MT_RW | MT_NON_CACHEABLE), + /* NULL terminator: */ + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + enable_mpu_el2(0); + + arm_setup_romlib(); +} + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} + +/* + * Perform the platform specific architecture setup shared between + * ARM standard platforms. + */ +void arm_bl1_platform_setup(void) +{ + uint32_t fw_config_max_size; + + /* Initialise the IO layer and register platform IO devices */ + plat_arm_io_setup(); + + /* Check if we need FWU before further processing */ + is_fwu_needed = plat_arm_bl1_fwu_needed(); + if (is_fwu_needed) { + ERROR("Skip platform setup as FWU detected\n"); + return; + } + + /* Set global DTB info for fixed fw_config information */ + fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE; + set_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size, FW_CONFIG_ID); + + assert(bl1_plat_get_image_desc(BL33_IMAGE_ID) != NULL); + + /* + * Allow access to the System counter timer module and program + * counter frequency for non secure images during FWU + */ +#ifdef ARM_SYS_TIMCTL_BASE + arm_configure_sys_timer(); +#endif +#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER) + write_cntfrq_el0(plat_get_syscnt_freq2()); +#endif +} + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); + + /* Initialize System level generic or SP804 timer */ + fvp_timer_init(); +} + +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) +{ + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (true) { + wfi(); + } +} + +unsigned int bl1_plat_get_next_image_id(void) +{ + return is_fwu_needed ? NS_BL1U_IMAGE_ID : BL33_IMAGE_ID; +} + +/* + * Returns BL33 image details. + */ +struct image_desc *bl1_plat_get_image_desc(unsigned int image_id) +{ + static image_desc_t bl33_img_desc = BL33_IMAGE_DESC; + + return &bl33_img_desc; +} + +/* + * This function populates the default arguments to BL33. + * The BL33 memory layout structure is allocated and the + * calculated layout is populated in arg1 to BL33. + */ +int bl1_plat_handle_post_image_load(unsigned int image_id) +{ + meminfo_t *bl33_secram_layout; + meminfo_t *bl1_secram_layout; + image_desc_t *image_desc; + entry_point_info_t *ep_info; + + if (image_id != BL33_IMAGE_ID) { + return 0; + } + /* Get the image descriptor */ + image_desc = bl1_plat_get_image_desc(BL33_IMAGE_ID); + assert(image_desc != NULL); + + /* Get the entry point info */ + ep_info = &image_desc->ep_info; + + /* Find out how much free trusted ram remains after BL1 load */ + bl1_secram_layout = bl1_plat_sec_mem_layout(); + + /* + * Create a new layout of memory for BL33 as seen by BL1 i.e. + * tell it the amount of total and free memory available. + * This layout is created at the first free address visible + * to BL33. BL33 will read the memory layout before using its + * memory for other purposes. + */ + bl33_secram_layout = (meminfo_t *) bl1_secram_layout->total_base; + + bl1_calc_bl2_mem_layout(bl1_secram_layout, bl33_secram_layout); + + ep_info->args.arg1 = (uintptr_t)bl33_secram_layout; + + VERBOSE("BL1: BL3 memory layout address = %p\n", + (void *) bl33_secram_layout); + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c new file mode 100644 index 0000000..edcf658 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* This uses xlat_mpu, but tables are set up using V2 mmap_region_t */ +#define XLAT_TABLES_LIB_V2 1 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fvp_r_private.h" +#include +#include +#include +#include + + +/* Defines for GIC Driver build time selection */ +#define FVP_R_GICV3 2 + +/******************************************************************************* + * arm_config holds the characteristics of the differences between the FVP_R + * platforms. It will be populated during cold boot at each boot stage by the + * primary before enabling the MPU (to allow interconnect configuration) & + * used thereafter. Each BL will have its own copy to allow independent + * operation. + ******************************************************************************/ +arm_config_t arm_config; + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Need to be mapped with write permissions in order to set a new non-volatile + * counter value. + */ +#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ + DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Table of memory regions for various BL stages to map using the MPU. + * This doesn't include Trusted SRAM as setup_page_tables() already takes care + * of mapping it. + * + * The flash needs to be mapped as writable in order to erase the FIP's Table of + * Contents in case of unrecoverable error (see plat_error_handler()). + */ +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RW, + V2M_MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, +#if TRUSTED_BOARD_BOOT + /* To access the Root of Trust Public Key registers. */ + MAP_DEVICE2, +#endif + {0} +}; +#endif + +ARM_CASSERT_MMAP + +static const int fvp_cci400_map[] = { + PLAT_FVP_R_CCI400_CLUS0_SL_PORT, + PLAT_FVP_R_CCI400_CLUS1_SL_PORT, +}; + +static const int fvp_cci5xx_map[] = { + PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT, + PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT, +}; + +static unsigned int get_interconnect_master(void) +{ + unsigned int master; + u_register_t mpidr; + + mpidr = read_mpidr_el1(); + master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ? + MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr); + + assert(master < FVP_R_CLUSTER_COUNT); + return master; +} + +/******************************************************************************* + * Initialize the platform config for future decision making + ******************************************************************************/ +void __init fvp_config_setup(void) +{ + unsigned int rev, hbi, bld, arch, sys_id; + + arm_config.flags |= ARM_CONFIG_BASE_MMAP; + sys_id = mmio_read_32(V2M_FVP_R_SYSREGS_BASE + V2M_SYS_ID); + rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK; + hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK; + bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK; + arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; + + if (arch != ARCH_MODEL) { + ERROR("This firmware is for FVP_R models\n"); + panic(); + } + + /* + * The build field in the SYS_ID tells which variant of the GIC + * memory is implemented by the model. + */ + switch (bld) { + case BLD_GIC_VE_MMAP: + ERROR("Legacy Versatile Express memory map for GIC %s", + "peripheral is not supported\n"); + panic(); + break; + case BLD_GIC_A53A57_MMAP: + break; + default: + ERROR("Unsupported board build %x\n", bld); + panic(); + } + + /* + * The hbi field in the SYS_ID is 0x020 for the Base FVP_R & 0x010 + * for the Foundation FVP_R. + */ + switch (hbi) { + case HBI_FOUNDATION_FVP_R: + arm_config.flags = 0; + + /* + * Check for supported revisions of Foundation FVP_R + * Allow future revisions to run but emit warning diagnostic + */ + switch (rev) { + case REV_FOUNDATION_FVP_R_V2_0: + case REV_FOUNDATION_FVP_R_V2_1: + case REV_FOUNDATION_FVP_R_v9_1: + case REV_FOUNDATION_FVP_R_v9_6: + break; + default: + WARN("Unrecognized Foundation FVP_R revision %x\n", rev); + break; + } + break; + case HBI_BASE_FVP_R: + arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC); + + /* + * Check for supported revisions + * Allow future revisions to run but emit warning diagnostic + */ + switch (rev) { + case REV_BASE_FVP_R_V0: + arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400; + break; + default: + WARN("Unrecognized Base FVP_R revision %x\n", rev); + break; + } + break; + default: + ERROR("Unsupported board HBI number 0x%x\n", hbi); + panic(); + } + + /* + * We assume that the presence of MT bit, and therefore shifted + * affinities, is uniform across the platform: either all CPUs, or no + * CPUs implement it. + */ + if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) { + arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF; + } +} + + +void __init fvp_interconnect_init(void) +{ + uintptr_t cci_base = 0U; + const int *cci_map = NULL; + unsigned int map_size = 0U; + + /* Initialize the right interconnect */ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) { + cci_base = PLAT_FVP_R_CCI5XX_BASE; + cci_map = fvp_cci5xx_map; + map_size = ARRAY_SIZE(fvp_cci5xx_map); + } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) { + cci_base = PLAT_FVP_R_CCI400_BASE; + cci_map = fvp_cci400_map; + map_size = ARRAY_SIZE(fvp_cci400_map); + } else { + return; + } + + assert(cci_base != 0U); + assert(cci_map != NULL); + cci_init(cci_base, cci_map, map_size); +} + +void fvp_interconnect_enable(void) +{ + unsigned int master; + + if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { + master = get_interconnect_master(); + cci_enable_snoop_dvm_reqs(master); + } +} + +void fvp_interconnect_disable(void) +{ + unsigned int master; + + if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) { + master = get_interconnect_master(); + cci_disable_snoop_dvm_reqs(master); + } +} + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void fvp_timer_init(void) +{ +#if USE_SP804_TIMER + /* Enable the clock override for SP804 timer 0, which means that no + * clock dividers are applied and the raw (35MHz) clock will be used. + */ + mmio_write_32(V2M_SP810_BASE, FVP_R_SP810_CTRL_TIM0_OV); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(V2M_SP804_TIMER0_BASE, + SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); +#else + generic_delay_timer_init(); + + /* Enable System level generic timer */ + mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0U) | CNTCR_EN); +#endif /* USE_SP804_TIMER */ +} + +/* Get SOC version */ +int32_t plat_get_soc_version(void) +{ + return (int32_t) + ((ARM_SOC_IDENTIFICATION_CODE << ARM_SOC_IDENTIFICATION_SHIFT) + | (ARM_SOC_CONTINUATION_CODE << ARM_SOC_CONTINUATION_SHIFT) + | FVP_R_SOC_ID); +} + +/* Get SOC revision */ +int32_t plat_get_soc_revision(void) +{ + unsigned int sys_id; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + return (int32_t)((sys_id >> V2M_SYS_ID_REV_SHIFT) & + V2M_SYS_ID_REV_MASK); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c new file mode 100644 index 0000000..d172d2d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/************************************************************ + * For R-class everything is in secure world. + * Prepare the CPU system registers for first entry into EL1 + ************************************************************/ +void cm_prepare_el2_exit(void) +{ + uint64_t hcr_el2 = 0U; + + /* + * The use of ARMv8.3 pointer authentication (PAuth) is governed + * by fields in HCR_EL2, which trigger a 'trap to EL2' if not + * enabled. This register initialized at boot up, update PAuth + * bits. + * + * HCR_API_BIT: Set to one to disable traps to EL2 if lower ELs + * access PAuth registers + * + * HCR_APK_BIT: Set to one to disable traps to EL2 if lower ELs + * access PAuth instructions + */ + hcr_el2 = read_hcr_el2(); + write_hcr_el2(hcr_el2 | HCR_API_BIT | HCR_APK_BIT); + + /* + * Initialise CNTHCTL_EL2. All fields are architecturally UNKNOWN + * on reset and are set to zero except for field(s) listed below. + * + * CNTHCTL_EL2.EL1PCEN: Set to one to disable traps to EL2 + * if lower ELs accesses to the physical timer registers. + * + * CNTHCTL_EL2.EL1PCTEN: Set to one to disable traps to EL2 + * if lower ELs access to the physical counter registers. + */ + write_cnthctl_el2(CNTHCTL_RESET_VAL | EL1PCEN_BIT | EL1PCTEN_BIT); + + /* + * On Armv8-R, the EL1&0 memory system architecture is configurable + * as a VMSA or PMSA. All the fields architecturally UNKNOWN on reset + * and are set to zero except for field listed below. + * + * VCTR_EL2.MSA: Set to one to ensure the VMSA is enabled so that + * rich OS can boot. + */ + write_vtcr_el2(VTCR_RESET_VAL | VTCR_EL2_MSA); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S new file mode 100644 index 0000000..88f0a29 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl el2_panic + + /*********************************************************** + * The common implementation of do_panic for all BL stages + ***********************************************************/ + +.section .rodata.panic_str, "aS" + panic_msg: .asciz "PANIC at PC : 0x" + +/* + * el2_panic will be redefined by the + * crash reporting mechanism (if enabled) + */ +el2_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 + + bl plat_crash_console_flush + +_panic_handler: + /* Pass to plat_panic_handler the address from where el2_panic was + * called, not the address of the call from el2_panic. + */ + mov x30, x6 + b plat_panic_handler diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h new file mode 100644 index 0000000..eda39cf --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_DEF_H +#define FVP_R_DEF_H + +#include + +/****************************************************************************** + * FVP-R topology constants + *****************************************************************************/ +#define FVP_R_CLUSTER_COUNT 2 +#define FVP_R_MAX_CPUS_PER_CLUSTER 4 +#define FVP_R_MAX_PE_PER_CPU 1 +#define FVP_R_PRIMARY_CPU 0x0 + +/****************************************************************************** + * Definition of platform soc id + *****************************************************************************/ +#define FVP_R_SOC_ID 0 + +/******************************************************************************* + * FVP_R memory map related constants + ******************************************************************************/ + +#define FLASH1_BASE UL(0x8c000000) +#define FLASH1_SIZE UL(0x04000000) + +#define PSRAM_BASE UL(0x94000000) +#define PSRAM_SIZE UL(0x04000000) + +#define VRAM_BASE UL(0x98000000) +#define VRAM_SIZE UL(0x02000000) + +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE UL(0xa0000000) +#define DEVICE0_SIZE UL(0x0c200000) + +/* + * In case of FVP_R models with CCN, the CCN register space overlaps into + * the NSRAM area. + */ +#define DEVICE1_BASE UL(0xae000000) +#define DEVICE1_SIZE UL(0x1A00000) + +#define NSRAM_BASE UL(0xae000000) +#define NSRAM_SIZE UL(0x10000) +/* Devices in the second GB */ +#define DEVICE2_BASE UL(0xffe00000) +#define DEVICE2_SIZE UL(0x00200000) + +#define PCIE_EXP_BASE UL(0xc0000000) +#define TZRNG_BASE UL(0x7fe60000) + +/* Non-volatile counters */ +#define TRUSTED_NVCTR_BASE UL(0xffe70000) +#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000)) +#define TFW_NVCTR_SIZE UL(4) +#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004)) +#define NTFW_CTR_SIZE UL(4) + +/* Keys */ +#define SOC_KEYS_BASE UL(0xffe80000) +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000)) +#define TZ_PUB_KEY_HASH_SIZE UL(32) +#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020)) +#define HU_KEY_SIZE UL(16) +#define END_KEY_BASE (SOC_KEYS_BASE + UL(0x0044)) +#define END_KEY_SIZE UL(32) + +/* Constants to distinguish FVP_R type */ +#define HBI_BASE_FVP_R U(0x020) +#define REV_BASE_FVP_R_V0 U(0x0) +#define REV_BASE_FVP_R_REVC U(0x2) + +#define HBI_FOUNDATION_FVP_R U(0x010) +#define REV_FOUNDATION_FVP_R_V2_0 U(0x0) +#define REV_FOUNDATION_FVP_R_V2_1 U(0x1) +#define REV_FOUNDATION_FVP_R_v9_1 U(0x2) +#define REV_FOUNDATION_FVP_R_v9_6 U(0x3) + +#define BLD_GIC_VE_MMAP U(0x0) +#define BLD_GIC_A53A57_MMAP U(0x1) + +#define ARCH_MODEL U(0x1) + +/* FVP_R Power controller base address*/ +#define PWRC_BASE UL(0x1c100000) + +/* FVP_R SP804 timer frequency is 35 MHz*/ +#define SP804_TIMER_CLKMULT 1 +#define SP804_TIMER_CLKDIV 35 + +/* SP810 controller. FVP_R specific flags */ +#define FVP_R_SP810_CTRL_TIM0_OV BIT_32(16) +#define FVP_R_SP810_CTRL_TIM1_OV BIT_32(18) +#define FVP_R_SP810_CTRL_TIM2_OV BIT_32(20) +#define FVP_R_SP810_CTRL_TIM3_OV BIT_32(22) + +#endif /* FVP_R_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c new file mode 100644 index 0000000..7ee752b --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +/* + * FVP_R error handler + */ +__dead2 void plat_arm_error_handler(int err) +{ + int ret; + + switch (err) { + case -ENOENT: + case -EAUTH: + /* Image load or authentication error. Erase the ToC */ + INFO("Erasing FIP ToC from flash...\n"); + (void)nor_unlock(PLAT_ARM_FLASH_IMAGE_BASE); + ret = nor_word_program(PLAT_ARM_FLASH_IMAGE_BASE, 0); + if (ret != 0) { + ERROR("Cannot erase ToC\n"); + } else { + INFO("Done\n"); + } + break; + default: + /* Unexpected error */ + break; + } + + (void)console_flush(); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S new file mode 100644 index 0000000..ba85777 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* --------------------------------------------- + * Power down this cpu. + * TODO: Do we need to worry about powering the + * cluster down as well here? That will need + * locks which we won't have unless an elf- + * loader zeroes out the zi section. + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + mov_imm x1, PWRC_BASE + str w0, [x1, #PPOFFR_OFF] + + /* --------------------------------------------- + * There is no sane reason to come out of this + * wfi so panic if we do. This cpu will be pow- + * ered on and reset by the cpu_on pm api + * --------------------------------------------- + */ + dsb sy + wfi + no_ret plat_panic_handler +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP_R, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* --------------------------------------------------------------------- + * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC + * WakeRequest signal" then it is a warm boot. + * --------------------------------------------------------------------- + */ + mrs x2, mpidr_el1 + mov_imm x1, PWRC_BASE + str w2, [x1, #PSYSR_OFF] + ldr w2, [x1, #PSYSR_OFF] + ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH + cmp w2, #WKUP_PPONR + beq warm_reset + cmp w2, #WKUP_GICREQ + beq warm_reset + + /* Cold reset */ + mov x0, #0 + ret + +warm_reset: + /* --------------------------------------------------------------------- + * A mailbox is maintained in the trusted SRAM. It is flushed out of the + * caches after every update using normal memory so it is safe to read + * it here with SO attributes. + * --------------------------------------------------------------------- + */ + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr x0, [x0] + cbz x0, _panic_handler + ret + + /* --------------------------------------------------------------------- + * The power controller indicates this is a warm reset but the mailbox + * is empty. This should never happen! + * --------------------------------------------------------------------- + */ +_panic_handler: + no_ret plat_panic_handler +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #FVP_R_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c new file mode 100644 index 0000000..3b44828 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Semihosting filenames */ +#define BL33_IMAGE_NAME "bl33.bin" + +#if TRUSTED_BOARD_BOOT +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt" +#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt" +#endif /* TRUSTED_BOARD_BOOT */ + +/* IO devices */ +static const io_dev_connector_t *sh_dev_con; +static uintptr_t sh_dev_handle; + +static const io_file_spec_t sh_file_spec[] = { + [BL33_IMAGE_ID] = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_KEY_CERT_ID] = { + .path = TRUSTED_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + .path = NT_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + .path = NT_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + + +static int open_semihosting(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if the file exists on semi-hosting.*/ + result = io_dev_init(sh_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(sh_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Semi-hosting IO\n"); + io_close(local_image_handle); + } + } + return result; +} + +void plat_arm_io_setup(void) +{ + int io_result; + + io_result = arm_io_setup(); + if (io_result < 0) { + panic(); + } + + /* Register the additional IO devices on this platform */ + io_result = register_io_dev_sh(&sh_dev_con); + if (io_result < 0) { + panic(); + } + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle); + if (io_result < 0) { + panic(); + } +} + +/* + * FVP_R provides semihosting as an alternative to load images + */ +int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]); + + if (result == 0) { + *dev_handle = sh_dev_handle; + *image_spec = (uintptr_t)&sh_file_spec[image_id]; + } + + return result; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S new file mode 100644 index 0000000..67ad164 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl disable_mpu_el2 + .globl disable_mpu_icache_el2 + +/* --------------------------------------------------------------------------- + * Disable the MPU at EL2. + * --------------------------------------------------------------------------- + */ + +func disable_mpu_el2 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mpu_el2: + mrs x0, sctlr_el2 + bic x0, x0, x1 + msr sctlr_el2, x0 + isb /* ensure MMU is off */ + dsb sy + ret +endfunc disable_mpu_el2 + + +func disable_mpu_icache_el2 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mpu_el2 +endfunc disable_mpu_icache_el2 diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h new file mode 100644 index 0000000..48f6e89 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_PRIVATE_H +#define FVP_R_PRIVATE_H + +#include + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void fvp_config_setup(void); + +void fvp_interconnect_init(void); +void fvp_interconnect_enable(void); +void fvp_interconnect_disable(void); +void fvp_timer_init(void); + +#endif /* FVP_R_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c new file mode 100644 index 0000000..69b6312 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#define RANDOM_CANARY_VALUE ((u_register_t) 8092347823957523895ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * Ideally, a random number should be returned instead of the + * combination of a timer's value and a compile-time constant. As the + * FVP_R does not have any random number generator, this is better than + * nothing but not necessarily really secure. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} + diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c new file mode 100644 index 0000000..de0b28f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} + +/* + * Store a new non-volatile counter value. + * + * On some FVP_R versions, the non-volatile counters are read-only so this + * function will always fail. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + const char *oid; + uintptr_t nv_ctr_addr; + + assert(cookie != NULL); + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + TRUSTED_NV_CTR_ID); + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr, + NON_TRUSTED_NV_CTR_ID); + } else { + return 1; + } + + mmio_write_32(nv_ctr_addr, nv_ctr); + + /* + * If the FVP_R models a locked counter then its value cannot be updated + * and the above write operation has been silently ignored. + */ + return (mmio_read_32(nv_ctr_addr) == nv_ctr) ? 0 : 1; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h b/arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h new file mode 100644 index 0000000..92bf484 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_ARCH_HELPERS_H +#define FVP_R_ARCH_HELPERS_H + +#include + +/******************************************************************************* + * MPU register definitions + ******************************************************************************/ +#define MPUIR_EL2 S3_4_C0_C0_4 +#define PRBAR_EL2 S3_4_C6_C8_0 +#define PRLAR_EL2 S3_4_C6_C8_1 +#define PRSELR_EL2 S3_4_C6_C2_1 +#define PRENR_EL2 S3_4_C6_C1_1 + +/* v8-R64 MPU registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(mpuir_el2, MPUIR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(prenr_el2, PRENR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(prselr_el2, PRSELR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(prbar_el2, PRBAR_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(prlar_el2, PRLAR_EL2) + +#endif /* FVP_R_ARCH_HELPERS_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h new file mode 100644 index 0000000..ea3a258 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_PLATFORM_DEF_H +#define FVP_R_PLATFORM_DEF_H + +#define PLAT_V2M_OFFSET 0x80000000 + +#define BL33_IMAGE_DESC { \ + .image_id = BL33_IMAGE_ID, \ + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, \ + VERSION_2, image_info_t, 0), \ + .image_info.image_base = PLAT_ARM_DRAM1_BASE + 0x1000, \ + .image_info.image_max_size = UL(0x3ffff000), \ + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, \ + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),\ + .ep_info.pc = PLAT_ARM_DRAM1_BASE + 0x1000, \ + .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), \ +} + +#include "../fvp_r_def.h" +#include +#include +#include + +/* These are referenced by arm_def.h #included next, so #define first. */ +#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x80000000) +#define PLAT_ARM_TRUSTED_SRAM_BASE UL(0x84000000) +#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x86000000) +#define PLAT_ARM_DRAM1_BASE ULL(0x0) +#define PLAT_ARM_DRAM2_BASE ULL(0x080000000) + +#define PLAT_HW_CONFIG_DTB_BASE ULL(0x12000000) +#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000) +#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000) +#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000) +#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000) +#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000) +#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000) + +#include +#include + + +/* Required to create plat_regions: */ +#define MIN_LVL_BLOCK_DESC U(1) + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT (U(FVP_R_CLUSTER_COUNT) * \ + U(FVP_R_MAX_CPUS_PER_CLUSTER) * \ + U(FVP_R_MAX_PE_PER_CPU)) + +#define PLAT_NUM_PWR_DOMAINS (U(FVP_R_CLUSTER_COUNT) + \ + PLATFORM_CORE_COUNT + U(1)) + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ +#define PLAT_ARM_CLUSTER_COUNT U(FVP_R_CLUSTER_COUNT) +#define PLAT_ARM_DRAM1_SIZE ULL(0x7fffffff) +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */ +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */ +#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */ + +/* These two are defined thus in arm_def.h, but doesn't seem to see it... */ +#define PLAT_BL1_RO_LIMIT (BL1_RO_BASE \ + + PLAT_ARM_TRUSTED_ROM_SIZE) + +#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000) +#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000) +#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000) +#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000) +#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000) +#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000) + +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +/* No SCP in FVP_R */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x0) + +#define PLAT_ARM_DRAM2_SIZE UL(0x80000000) + +#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000) + +#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \ + PLAT_HW_CONFIG_DTB_BASE, \ + PLAT_HW_CONFIG_DTB_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + +#define V2M_FVP_R_SYSREGS_BASE UL(0x9c010000) + +/* + * Load address of BL33 for this platform port, + * U-Boot specifically must be loaded at a 4K aligned address. + */ +#define PLAT_ARM_NS_IMAGE_BASE (PLAT_ARM_DRAM1_BASE + 0x1000) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if !USE_ROMLIB +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 5 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif +# define N_MPU_REGIONS 16 /* number of MPU regions */ +# define ALL_MPU_EL2_REGIONS_USED 0xffffffff + /* this is the PRENR_EL2 value if all MPU regions are in use */ + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000) + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000) +#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0x6000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0) +#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +#if COT_DESC_IN_DTB +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1E000) - FVP_R_BL2_ROMLIB_OPTIMIZATION) +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - FVP_R_BL2_ROMLIB_OPTIMIZATION) +#endif +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - FVP_R_BL2_ROMLIB_OPTIMIZATION) +#endif + +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000) + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x500) +# endif +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +/* + * These nominally reserve the last block of flash for PSCI MEM PROTECT flag, + * but no PSCI in FVP_R platform, so reserve nothing: + */ +#define PLAT_ARM_FLASH_IMAGE_BASE (PLAT_ARM_DRAM1_BASE + UL(0x40000000)) +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (PLAT_ARM_DRAM1_SIZE - UL(0x40000000)) + +#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE +#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_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_UART2_BASE +#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ + +/* CCI related constants */ +#define PLAT_FVP_R_CCI400_BASE UL(0xac090000) +#define PLAT_FVP_R_CCI400_CLUS0_SL_PORT 3 +#define PLAT_FVP_R_CCI400_CLUS1_SL_PORT 4 + +/* CCI-500/CCI-550 on Base platform */ +#define PLAT_FVP_R_CCI5XX_BASE UL(0xaa000000) +#define PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT 5 +#define PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT 6 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +/* Mailbox base address */ +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE + + +/* TrustZone controller related constants + * + * Currently only filters 0 and 2 are connected on Base FVP_R. + * Filter 0 : CPU clusters (no access to DRAM by default) + * Filter 1 : not connected + * Filter 2 : LCDs (access to VRAM allowed by default) + * Filter 3 : not connected + * Programming unconnected filters will have no effect at the + * moment. These filter could, however, be connected in future. + * So care should be taken not to configure the unused filters. + * + * Allow only non-secure access to all DRAM to supported devices. + * Give access to the CPUs and Virtio. Some devices + * would normally use the default ID so allow that too. + */ +#define PLAT_ARM_TZC_BASE UL(0xaa4a0000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_DEFAULT) | \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_PCI) | \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_AP) | \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO) | \ + TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO_OLD)) + +/* + * GIC related constants to cater for both GICv2 and GICv3 instances of an + * FVP_R. They could be overridden at runtime in case the FVP_R implements the + * legacy VE memory map. + */ +#define PLAT_ARM_GICD_BASE BASE_GICD_BASE +#define PLAT_ARM_GICR_BASE BASE_GICR_BASE +#define PLAT_ARM_GICC_BASE BASE_GICC_BASE + +#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) + +#define PLAT_SP_PRI PLAT_RAS_PRI + +/* + * Physical and virtual address space limits for MPU in AARCH64 & AARCH32 modes + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) + +#define ARM_SOC_CONTINUATION_SHIFT U(24) +#define ARM_SOC_IDENTIFICATION_SHIFT U(16) + +#endif /* FVP_R_PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_r/platform.mk b/arm-trusted-firmware/plat/arm/board/fvp_r/platform.mk new file mode 100644 index 0000000..93b5cf2 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/platform.mk @@ -0,0 +1,99 @@ +# +# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Only aarch64 ARCH supported for FVP_R +ARCH := aarch64 + +# Override to exclude BL2, BL2U, BL31, and BL33 for FVP_R +override NEED_BL2 := no +override NEED_BL2U := no +override NEED_BL31 := no +NEED_BL32 := no + +override CTX_INCLUDE_AARCH32_REGS := 0 + +# Use MPU-based memory management: +XLAT_MPU_LIB_V1 := 1 + +# FVP R will not have more than 2 clusters so just use CCI interconnect +FVP_R_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c + + +include plat/arm/board/common/board_common.mk +include plat/arm/common/arm_common.mk + +PLAT_INCLUDES := -Iplat/arm/board/fvp_r/include + +FVP_R_BL_COMMON_SOURCES := plat/arm/board/fvp_r/fvp_r_common.c \ + plat/arm/board/fvp_r/fvp_r_context_mgmt.c \ + plat/arm/board/fvp_r/fvp_r_debug.S \ + plat/arm/board/fvp_r/fvp_r_err.c \ + plat/arm/board/fvp_r/fvp_r_helpers.S \ + plat/arm/board/fvp_r/fvp_r_misc_helpers.S + +FVP_R_BL1_SOURCES := plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c \ + plat/arm/board/fvp_r/fvp_r_bl1_setup.c \ + plat/arm/board/fvp_r/fvp_r_io_storage.c \ + plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S \ + plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S \ + plat/arm/board/fvp_r/fvp_r_bl1_main.c + +FVP_R_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +FVP_R_DYNC_CFG_SOURCES := common/fdt_wrappers.c \ + plat/arm/common/arm_dyn_cfg.c + +ifeq (${TRUSTED_BOARD_BOOT},1) +FVP_R_AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + lib/fconf/fconf_tbbr_getter.c \ + plat/common/tbbr/plat_tbbr.c \ + drivers/auth/tbbr/tbbr_cot_bl1_r64.c \ + drivers/auth/tbbr/tbbr_cot_common.c \ + plat/arm/board/common/board_arm_trusted_boot.c \ + plat/arm/board/common/rotpk/arm_dev_rotpk.S \ + plat/arm/board/fvp_r/fvp_r_trusted_boot.c + +FVP_R_BL1_SOURCES += ${MBEDTLS_SOURCES} \ + ${FVP_R_AUTH_SOURCES} +endif + +ifeq (${USE_SP804_TIMER},1) +FVP_R_BL_COMMON_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +else +FVP_R_BL_COMMON_SOURCES += drivers/delay_timer/generic_delay_timer.c +endif + +# Enable Activity Monitor Unit extensions by default +ENABLE_AMU := 1 + +ifneq (${ENABLE_STACK_PROTECTOR},0) +FVP_R_BL_COMMON_SOURCES += plat/arm/board/fvp_r/fvp_r_stack_protector.c +endif + +override BL1_SOURCES := drivers/arm/sp805/sp805.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/delay_timer/delay_timer.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + drivers/io/io_semihosting.c \ + lib/cpus/aarch64/cpu_helpers.S \ + lib/fconf/fconf_dyn_cfg_getter.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + plat/common/plat_bl1_common.c \ + plat/common/aarch64/platform_up_stack.S \ + ${FVP_R_BL1_SOURCES} \ + ${FVP_R_BL_COMMON_SOURCES} \ + ${FVP_R_CPU_LIBS} \ + ${FVP_R_DYNC_CFG_SOURCES} \ + ${FVP_R_INTERCONNECT_SOURCES} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S new file mode 100644 index 0000000..78f6c68 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov r0, #0 + bx lr + +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Currently configured for a sigle CPU + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mov r0, #1 + bx lr +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts new file mode 100644 index 0000000..6e5691b --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x80001300>; + max-size = <0x200>; + id = ; + }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x01000000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts new file mode 100644 index 0000000..c66186f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c new file mode 100644 index 0000000..736cf42 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); +} + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c new file mode 100644 index 0000000..4ccae27 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "fvp_ve_private.h" + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); + + /* Initialize the platform config for future decision making */ + fvp_ve_config_setup(); +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); + +#if USE_SP804_TIMER + /* + * Enable the clock override for SP804 timer 0, which means that no + * clock dividers are applied and the raw (35 MHz) clock will be used + */ + mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(V2M_SP804_TIMER0_BASE, + SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); +#else + generic_delay_timer_init(); +#endif /* USE_SP804_TIMER */ +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c new file mode 100644 index 0000000..768dad5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH1_RW, + V2M_MAP_IOFPGA, + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH1_RW, + V2M_MAP_IOFPGA, + ARM_MAP_NS_DRAM1, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + MAP_DEVICE0, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +void __init fvp_ve_config_setup(void) +{ + unsigned int sys_id, arch; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; + + if (arch != ARCH_MODEL_VE) { + ERROR("This firmware is for FVP VE models\n"); + panic(); + } +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return FVP_VE_TIMER_BASE_FREQUENCY; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h new file mode 100644 index 0000000..98de5f6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_VE_DEF_H +#define FVP_VE_DEF_H + +#include + +/* Default cluster count for FVP VE */ +#define FVP_VE_CLUSTER_COUNT U(1) + +/* Default number of CPUs per cluster on FVP VE */ +#define FVP_VE_MAX_CPUS_PER_CLUSTER U(1) + +/* Default number of threads per CPU on FVP VE */ +#define FVP_VE_MAX_PE_PER_CPU U(1) + +#define FVP_VE_CORE_COUNT U(1) + +#define FVP_VE_PRIMARY_CPU 0x0 + +/******************************************************************************* + * FVP memory map related constants + ******************************************************************************/ + +#define FLASH1_BASE 0x0c000000 +#define FLASH1_SIZE 0x04000000 + +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE 0x20000000 +#define DEVICE0_SIZE 0x0c200000 + +#define NSRAM_BASE 0x2e000000 +#define NSRAM_SIZE 0x10000 + +#define PCIE_EXP_BASE 0x40000000 +#define TZRNG_BASE 0x7fe60000 + +#define ARCH_MODEL_VE 0x5 + +/* FVP Power controller base address*/ +#define PWRC_BASE UL(0x1c100000) + +/* FVP SP804 timer frequency is 35 MHz*/ +#define SP804_TIMER_CLKMULT 1 +#define SP804_TIMER_CLKDIV 35 + +/* SP810 controller. FVP specific flags */ +#define FVP_SP810_CTRL_TIM0_OV (1 << 16) +#define FVP_SP810_CTRL_TIM1_OV (1 << 18) +#define FVP_SP810_CTRL_TIM2_OV (1 << 20) +#define FVP_SP810_CTRL_TIM3_OV (1 << 22) + +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ +/* VE compatible GIC memory map */ +#define VE_GICD_BASE 0x2c001000 +#ifdef ARM_CORTEX_A5 +#define VE_GICC_BASE 0x2c000100 +#else +#define VE_GICC_BASE 0x2c002000 +#endif +#define VE_GICH_BASE 0x2c004000 +#define VE_GICV_BASE 0x2c006000 + +#define FVP_VE_IRQ_TZ_WDOG 56 +#define FVP_VE_IRQ_SEC_SYS_TIMER 57 + +#define V2M_FLASH1_BASE UL(0x0C000000) +#define V2M_FLASH1_SIZE UL(0x04000000) + +#define V2M_MAP_FLASH1_RW MAP_REGION_FLAT(V2M_FLASH1_BASE,\ + V2M_FLASH1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define V2M_MAP_FLASH1_RO MAP_REGION_FLAT(V2M_FLASH1_BASE,\ + V2M_FLASH1_SIZE, \ + MT_RO_DATA | MT_SECURE) + +#endif /* FVP_VE_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c new file mode 100644 index 0000000..8d35688 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * FVP VE error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c new file mode 100644 index 0000000..a4d627b --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2019, Arm Limited. All rights reserved. +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#include +#include + +/******************************************************************************* + * Export the platform handlers via fvp_ve_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t fvp_ve_psci_pm_ops = { + /* dummy struct */ + .validate_ns_entrypoint = NULL, +}; + +int __init plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &fvp_ve_psci_pm_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h new file mode 100644 index 0000000..5d396bc --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_VE_PRIVATE_H +#define FVP_VE_PRIVATE_H + +#include + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void fvp_ve_config_setup(void); + +#endif /* FVP_VE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c new file mode 100644 index 0000000..24465cb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * The Base FVP has a TrustZone address space controller, the Foundation + * FVP does not. Trying to program the device on the foundation FVP will + * cause an abort. + * + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ + + return; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c new file mode 100644 index 0000000..51cc9da --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* The FVP VE power domain tree descriptor */ +static const unsigned char fvp_ve_power_domain_tree_desc[] = { + 1, + /* No of children for the root node */ + FVP_VE_CLUSTER_COUNT, + /* No of children for the first cluster node */ + FVP_VE_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the topology according to FVP_VE_CLUSTER_COUNT. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return fvp_ve_power_domain_tree_desc; +} + +/******************************************************************************* + * Currently FVP VE has only been tested with one core, therefore 0 is returned. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h new file mode 100644 index 0000000..bd8ef6a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include + +#include "../fvp_ve_def.h" + +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* Memory location options for TSP */ +#define ARM_DRAM_ID 2 + +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE UL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1) + +#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 - 1) + +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +/* + * The last 2MB is meant to be NOLOAD and will not be zero + * initialized. + */ +#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + 0x00200000) + + +/* The first 4KB of NS DRAM1 are used as shared memory */ +#define FVP_VE_SHARED_RAM_BASE ARM_NS_DRAM1_BASE +#define FVP_VE_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ + +/* The next 252 kB of NS DRAM is used to load the BL images */ +#define ARM_BL_RAM_BASE (FVP_VE_SHARED_RAM_BASE + \ + FVP_VE_SHARED_RAM_SIZE) +#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \ + FVP_VE_SHARED_RAM_SIZE) + + +#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_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + FVP_VE_SHARED_RAM_BASE, \ + FVP_VE_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_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) + +#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 + +/* + * 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 FVP_VE_TIMER_BASE_FREQUENCY UL(24000000) +#define ARM_SYS_CNTREAD_BASE UL(0x2a800000) +#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(0x1C0F0000) +#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) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * 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 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +/* + * 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)) + +/* + * 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 0x00000000 +#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE +/* + * Put BL1 RW at the top of the memory allocated for BL images in NS DRAM. + */ +#define BL1_RW_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + (PLAT_ARM_MAX_BL1_RW_SIZE)) +#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \ + (ARM_BL_RAM_SIZE)) + + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ + +/* + * Put BL2 just below BL1. + */ +#define BL2_BASE (BL1_RW_BASE - FVP_VE_MAX_BL2_SIZE) +#define BL2_LIMIT BL1_RW_BASE + + +/* Put BL32 below BL2 in NS DRAM.*/ +#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 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) + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT FVP_VE_CLUSTER_COUNT +#define PLAT_NUM_PWR_DOMAINS ((FVP_VE_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + U(1)) + +#define PLAT_MAX_PWR_LVL 2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ + +#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */ + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x04000000 /* 64 MB */ + +#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000) + +/* + * Load address of BL33 for this platform port + */ +#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000)) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 6 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000 + +/* + * FVP_VE_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#define FVP_VE_MAX_BL2_SIZE 0x11000 + +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current SP_MIN PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL32_SIZE 0x3B000 +/* + + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +#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_FLASH1_BASE +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (V2M_FLASH1_SIZE - V2M_FLASH_BLOCK_SIZE) + +#define PLAT_ARM_NVM_BASE V2M_FLASH1_BASE +#define PLAT_ARM_NVM_SIZE (V2M_FLASH1_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_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 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID 1 + +/* Mailbox base address */ +#define FVP_VE_TRUSTED_MAILBOX_BASE FVP_VE_SHARED_RAM_BASE + +/* + * GIC related constants to cater for GICv2 + */ +#define PLAT_ARM_GICD_BASE VE_GICD_BASE +#define PLAT_ARM_GICC_BASE VE_GICC_BASE + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(FVP_VE_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(FVP_VE_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +#endif /* PLATFORM_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/platform.mk b/arm-trusted-firmware/plat/arm/board/fvp_ve/platform.mk new file mode 100644 index 0000000..f7eace8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/platform.mk @@ -0,0 +1,139 @@ +# +# Copyright (c) 2019-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +ifdef ARM_CORTEX_A5 +# Use the SP804 timer instead of the generic one +USE_SP804_TIMER := 1 +BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +endif + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +FVP_VE_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +FVP_VE_SECURITY_SOURCES := plat/arm/board/fvp_ve/fvp_ve_security.c + +PLAT_INCLUDES := -Iplat/arm/board/fvp_ve/include + +PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp_ve/fvp_ve_common.c \ + plat/arm/common/${ARCH}/arm_helpers.S \ + plat/arm/common/arm_common.c \ + plat/arm/common/arm_console.c \ + drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/arm/board/common/${ARCH}/board_arm_helpers.S + +ifdef ARM_CORTEX_A5 +FVP_VE_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S +else +FVP_VE_CPU_LIBS := lib/cpus/aarch32/cortex_a7.S +endif + +BL1_SOURCES += drivers/arm/sp805/sp805.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/board/fvp_ve/fvp_ve_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + drivers/cfi/v2m/v2m_flash.c \ + plat/arm/board/fvp_ve/${ARCH}/fvp_ve_helpers.S \ + plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + ${FVP_VE_CPU_LIBS} \ + ${DYN_CFG_SOURCES} + +BL2_SOURCES += plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl2_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/board/fvp_ve/fvp_ve_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c \ + plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \ + plat/arm/common/arm_image_load.c \ + common/desc_image_load.c \ + ${DYN_CFG_SOURCES} \ + ${FVP_VE_SECURITY_SOURCES} + +# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env) +ifdef UNIX_MK + +FDT_SOURCES += plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts \ + plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts + +FVP_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb +FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config,${FVP_FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config,${FVP_TB_FW_CONFIG})) + +FDT_SOURCES += ${FVP_HW_CONFIG_DTS} +$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \ + fdts/$(notdir ${FVP_HW_CONFIG_DTS}))) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG})) +endif + +NEED_BL32 := yes + +# Modification of arm_common.mk + +# Process ARM_DISABLE_TRUSTED_WDOG flag +# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set +ARM_DISABLE_TRUSTED_WDOG := 0 +ifeq (${SPIN_ON_BL1_EXIT}, 1) +ARM_DISABLE_TRUSTED_WDOG := 1 +endif +$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG)) + +# Use translation tables library v1 if using Cortex-A5 +ifdef ARM_CORTEX_A5 +ARM_XLAT_TABLES_LIB_V1 := 1 +else +ARM_XLAT_TABLES_LIB_V1 := 0 +endif +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) + +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) + # Only use nonlpae version of xlatv1 otherwise use xlat v2 + PLAT_BL_COMMON_SOURCES += lib/xlat_tables/${ARCH}/nonlpae_tables.c +else + include lib/xlat_tables_v2/xlat_tables.mk + PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} +endif + +# Firmware Configuration Framework sources +include lib/fconf/fconf.mk + +BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} +BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} + +# Add `libfdt` and Arm common helpers required for Dynamic Config +include lib/libfdt/libfdt.mk + +DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \ + plat/arm/common/arm_dyn_cfg_helpers.c + +DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c new file mode 100644 index 0000000..e6a1bbe --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk b/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk new file mode 100644 index 0000000..4ca810d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to FVP platform +BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S \ + drivers/arm/fvp/fvp_pwrc.c \ + plat/arm/board/fvp_ve/fvp_ve_pm.c \ + plat/arm/board/fvp_ve/fvp_ve_topology.c \ + plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + plat/arm/common/sp_min/arm_sp_min_setup.c \ + plat/common/aarch32/platform_mp_stack.S \ + plat/common/plat_psci_common.c \ + ${FVP_VE_CPU_LIBS} \ + ${FVP_VE_GIC_SOURCES} \ + ${FVP_VE_SECURITY_SOURCES} diff --git a/arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S b/arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S new file mode 100644 index 0000000..8f9561c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + .globl plat_reset_handler + .globl plat_arm_calc_core_pos + +#define JUNO_REVISION(rev) REV_JUNO_R##rev +#define JUNO_HANDLER(rev) plat_reset_handler_juno_r##rev +#define JUMP_TO_HANDLER_IF_JUNO_R(revision) \ + jump_to_handler JUNO_REVISION(revision), JUNO_HANDLER(revision) + + /* -------------------------------------------------------------------- + * Helper macro to jump to the given handler if the board revision + * matches. + * Expects the Juno board revision in x0. + * -------------------------------------------------------------------- + */ + .macro jump_to_handler _revision, _handler + cmp r0, #\_revision + beq \_handler + .endm + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R0. + * + * Juno R0 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A57 processor cluster. + * + * This handler does the following: + * - Implement workaround for defect id 831273 by enabling an event + * stream every 65536 cycles. + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(0) + /* -------------------------------------------------------------------- + * Enable the event stream every 65536 cycles + * -------------------------------------------------------------------- + */ + mov r0, #(0xf << EVNTI_SHIFT) + orr r0, r0, #EVNTEN_BIT + stcopr r0, CNTKCTL + + /* -------------------------------------------------------------------- + * Nothing else to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A53_MIDR, 1f + + /* -------------------------------------------------------------------- + * Cortex-A57 specific settings + * -------------------------------------------------------------------- + */ + mov r0, #((CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT)) + stcopr r0, CORTEX_A57_L2CTLR +1: + isb + bx lr +endfunc JUNO_HANDLER(0) + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R1. + * + * Juno R1 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A57 processor cluster. + * + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * + * Note that: + * - The default value for the L2 Tag RAM latency for Cortex-A57 is + * suitable. + * - Defect #831273 doesn't affect Juno R1. + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(1) + /* -------------------------------------------------------------------- + * Nothing to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A57_MIDR, A57 + bx lr + +A57: + /* -------------------------------------------------------------------- + * Cortex-A57 specific settings + * -------------------------------------------------------------------- + */ + mov r0, #(CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) + stcopr r0, CORTEX_A57_L2CTLR + isb + bx lr +endfunc JUNO_HANDLER(1) + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R2. + * + * Juno R2 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A72 processor cluster. + * + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72 + * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72 + * + * Note that: + * - Defect #831273 doesn't affect Juno R2. + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(2) + /* -------------------------------------------------------------------- + * Nothing to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A72_MIDR, A72 + bx lr + +A72: + /* -------------------------------------------------------------------- + * Cortex-A72 specific settings + * -------------------------------------------------------------------- + */ + mov r0, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES << CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT)) + stcopr r0, CORTEX_A72_L2CTLR + isb + bx lr +endfunc JUNO_HANDLER(2) + + /* -------------------------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the Juno board revision and call the appropriate reset + * handler. + * -------------------------------------------------------------------- + */ +func plat_reset_handler + /* Read the V2M SYS_ID register */ + ldr r0, =(V2M_SYSREGS_BASE + V2M_SYS_ID) + ldr r1, [r0] + /* Extract board revision from the SYS_ID */ + ubfx r0, r1, #V2M_SYS_ID_REV_SHIFT, #4 + + JUMP_TO_HANDLER_IF_JUNO_R(0) + JUMP_TO_HANDLER_IF_JUNO_R(1) + JUMP_TO_HANDLER_IF_JUNO_R(2) + + /* Board revision is not supported */ + no_ret plat_panic_handler + +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * ----------------------------------------------------- + */ +func plat_arm_calc_core_pos + b css_calc_core_pos_swap_cluster +endfunc plat_arm_calc_core_pos diff --git a/arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S b/arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S new file mode 100644 index 0000000..c94fa3e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + .globl plat_reset_handler + .globl plat_arm_calc_core_pos +#if JUNO_AARCH32_EL3_RUNTIME + .globl plat_get_my_entrypoint + .globl juno_reset_to_aarch32_state +#endif + +#define JUNO_REVISION(rev) REV_JUNO_R##rev +#define JUNO_HANDLER(rev) plat_reset_handler_juno_r##rev +#define JUMP_TO_HANDLER_IF_JUNO_R(revision) \ + jump_to_handler JUNO_REVISION(revision), JUNO_HANDLER(revision) + + /* -------------------------------------------------------------------- + * Helper macro to jump to the given handler if the board revision + * matches. + * Expects the Juno board revision in x0. + * -------------------------------------------------------------------- + */ + .macro jump_to_handler _revision, _handler + cmp x0, #\_revision + b.eq \_handler + .endm + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R0. + * + * Juno R0 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A57 processor cluster. + * + * This handler does the following: + * - Implement workaround for defect id 831273 by enabling an event + * stream every 65536 cycles. + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(0) + /* -------------------------------------------------------------------- + * Enable the event stream every 65536 cycles + * -------------------------------------------------------------------- + */ + mov x0, #(0xf << EVNTI_SHIFT) + orr x0, x0, #EVNTEN_BIT + msr CNTKCTL_EL1, x0 + + /* -------------------------------------------------------------------- + * Nothing else to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A53_MIDR, 1f + + /* -------------------------------------------------------------------- + * Cortex-A57 specific settings + * -------------------------------------------------------------------- + */ + mov x0, #((CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT)) + msr CORTEX_A57_L2CTLR_EL1, x0 +1: + isb + ret +endfunc JUNO_HANDLER(0) + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R1. + * + * Juno R1 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A57 processor cluster. + * + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * + * Note that: + * - The default value for the L2 Tag RAM latency for Cortex-A57 is + * suitable. + * - Defect #831273 doesn't affect Juno R1. + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(1) + /* -------------------------------------------------------------------- + * Nothing to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A57_MIDR, A57 + ret + +A57: + /* -------------------------------------------------------------------- + * Cortex-A57 specific settings + * -------------------------------------------------------------------- + */ + mov x0, #(CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) + msr CORTEX_A57_L2CTLR_EL1, x0 + isb + ret +endfunc JUNO_HANDLER(1) + + /* -------------------------------------------------------------------- + * Platform reset handler for Juno R2. + * + * Juno R2 has the following topology: + * - Quad core Cortex-A53 processor cluster; + * - Dual core Cortex-A72 processor cluster. + * + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72 + * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72 + * + * Note that: + * - Defect #831273 doesn't affect Juno R2. + * -------------------------------------------------------------------- + */ +func JUNO_HANDLER(2) + /* -------------------------------------------------------------------- + * Nothing to do on Cortex-A53. + * -------------------------------------------------------------------- + */ + jump_if_cpu_midr CORTEX_A72_MIDR, A72 + ret + +A72: + /* -------------------------------------------------------------------- + * Cortex-A72 specific settings + * -------------------------------------------------------------------- + */ + mov x0, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES << CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT)) + msr CORTEX_A57_L2CTLR_EL1, x0 + isb + ret +endfunc JUNO_HANDLER(2) + + /* -------------------------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the Juno board revision and call the appropriate reset + * handler. + * -------------------------------------------------------------------- + */ +func plat_reset_handler + /* Read the V2M SYS_ID register */ + mov_imm x0, (V2M_SYSREGS_BASE + V2M_SYS_ID) + ldr w1, [x0] + /* Extract board revision from the SYS_ID */ + ubfx x0, x1, #V2M_SYS_ID_REV_SHIFT, #4 + + JUMP_TO_HANDLER_IF_JUNO_R(0) + JUMP_TO_HANDLER_IF_JUNO_R(1) + JUMP_TO_HANDLER_IF_JUNO_R(2) + + /* Board revision is not supported */ + no_ret plat_panic_handler + +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * void juno_do_reset_to_aarch32_state(void); + * + * Request warm reset to AArch32 mode. + * ----------------------------------------------------- + */ +func juno_do_reset_to_aarch32_state + mov x0, #RMR_EL3_RR_BIT + dsb sy + msr rmr_el3, x0 + isb + wfi + b plat_panic_handler +endfunc juno_do_reset_to_aarch32_state + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * ----------------------------------------------------- + */ +func plat_arm_calc_core_pos + b css_calc_core_pos_swap_cluster +endfunc plat_arm_calc_core_pos + +#if JUNO_AARCH32_EL3_RUNTIME + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. On JUNO platform, this distinction is based on the contents of + * the Trusted Mailbox. It is initialised to zero by the SCP before the + * AP cores are released from reset. Therefore, a zero mailbox means + * it's a cold reset. If it is a warm boot then a request to reset to + * AArch32 state is issued. This is the only way to reset to AArch32 + * in EL3 on Juno. A trampoline located at the high vector address + * has already been prepared by BL1. + * + * This functions returns the contents of the mailbox, i.e.: + * - 0 for a cold boot; + * - request warm reset in AArch32 state for warm boot case; + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr x0, [x0] + cbz x0, return + b juno_do_reset_to_aarch32_state +return: + ret +endfunc plat_get_my_entrypoint + +/* + * Emit a "movw r0, #imm16" which moves the lower + * 16 bits of `_val` into r0. + */ +.macro emit_movw _reg_d, _val + mov_imm \_reg_d, (0xe3000000 | \ + ((\_val & 0xfff) | \ + ((\_val & 0xf000) << 4))) +.endm + +/* + * Emit a "movt r0, #imm16" which moves the upper + * 16 bits of `_val` into r0. + */ +.macro emit_movt _reg_d, _val + mov_imm \_reg_d, (0xe3400000 | \ + (((\_val & 0x0fff0000) >> 16) | \ + ((\_val & 0xf0000000) >> 12))) +.endm + +/* + * This function writes the trampoline code at HI-VEC (0xFFFF0000) + * address which loads r0 with the entrypoint address for + * BL32 (a.k.a SP_MIN) when EL3 is in AArch32 mode. A warm reset + * to AArch32 mode is then requested by writing into RMR_EL3. + */ +func juno_reset_to_aarch32_state + /* + * Invalidate all caches before the warm reset to AArch32 state. + * This is required on the Juno AArch32 boot flow because the L2 + * unified cache may contain code and data from when the processor + * was still executing in AArch64 state. This code only runs on + * the primary core, all other cores are powered down. + */ + mov x0, #DCISW + bl dcsw_op_all + + emit_movw w0, BL32_BASE + emit_movt w1, BL32_BASE + /* opcode "bx r0" to branch using r0 in AArch32 mode */ + mov_imm w2, 0xe12fff10 + + /* Write the above opcodes at HI-VECTOR location */ + mov_imm x3, HI_VECTOR_BASE + str w0, [x3], #4 + str w1, [x3], #4 + str w2, [x3] + + b juno_do_reset_to_aarch32_state +endfunc juno_reset_to_aarch32_state + +#endif /* JUNO_AARCH32_EL3_RUNTIME */ diff --git a/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts b/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts new file mode 100644 index 0000000..4b88efe --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x8000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts new file mode 100644 index 0000000..80cfa3e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + /* Disable authentication for development */ + disable_auth = <0x0>; + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S new file mode 100644 index 0000000..ec94a4f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + css_print_gic_regs + print_cci_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h new file mode 100644 index 0000000..d61ba5d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "../juno_def.h" + +/* Required platform porting definitions */ +/* Juno supports system power domain */ +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 +#define PLAT_NUM_PWR_DOMAINS (ARM_SYSTEM_COUNT + \ + JUNO_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLATFORM_CORE_COUNT (JUNO_CLUSTER0_CORE_COUNT + \ + JUNO_CLUSTER1_CORE_COUNT) + +/* Cryptocell HW Base address */ +#define PLAT_CRYPTOCELL_BASE UL(0x60050000) + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ +#define PLAT_ARM_CLUSTER_COUNT JUNO_CLUSTER_COUNT + +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */ + +/* Use the bypass address */ +#define PLAT_ARM_TRUSTED_ROM_BASE (V2M_FLASH0_BASE + \ + BL1_ROM_BYPASS_OFFSET) + +#define NSRAM_BASE UL(0x2e000000) +#define NSRAM_SIZE UL(0x00008000) /* 32KB */ + +#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000) + +/* Range of kernel DTB load address */ +#define JUNO_DTB_DRAM_MAP_START ULL(0x82000000) +#define JUNO_DTB_DRAM_MAP_SIZE ULL(0x00008000) /* 32KB */ + +#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \ + JUNO_DTB_DRAM_MAP_START, \ + JUNO_DTB_DRAM_MAP_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000) +#define JUNO_BL2_ROMLIB_OPTIMIZATION UL(0x8000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0) +#define JUNO_BL2_ROMLIB_OPTIMIZATION UL(0) +#endif + +/* + * Actual ROM size on Juno is 64 KB, but TBB currently requires at least 80 KB + * in debug mode. We can test TBB on Juno bypassing the ROM and using 128 KB of + * flash + */ + +#if TRUSTED_BOARD_BOOT +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00020000) +#else +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00010000) +#endif /* TRUSTED_BOARD_BOOT */ + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#ifdef IMAGE_BL1 +# define PLAT_ARM_MMAP_ENTRIES 7 +# define MAX_XLAT_TABLES 4 +#endif + +#ifdef IMAGE_BL2 +#ifdef SPD_opteed +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 5 +#else +# define PLAT_ARM_MMAP_ENTRIES 10 +# define MAX_XLAT_TABLES 4 +#endif +#endif + +#ifdef IMAGE_BL2U +# define PLAT_ARM_MMAP_ENTRIES 5 +# define MAX_XLAT_TABLES 3 +#endif + +#ifdef IMAGE_BL31 +# define PLAT_ARM_MMAP_ENTRIES 7 +# define MAX_XLAT_TABLES 5 +#endif + +#ifdef IMAGE_BL32 +# define PLAT_ARM_MMAP_ENTRIES 6 +# define MAX_XLAT_TABLES 4 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000) +#else +# define PLAT_ARM_MAX_BL1_RW_SIZE UL(0x6000) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1F000) - JUNO_BL2_ROMLIB_OPTIMIZATION) +#elif TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION) +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION) +#endif +#else +# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - JUNO_BL2_ROMLIB_OPTIMIZATION) +#endif + +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW. SCP_BL2 image is loaded into the space BL31 -> BL2_BASE. + * Hence the BL31 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE. + */ +#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000) + +#if JUNO_AARCH32_EL3_RUNTIME +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current BL32 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW. SCP_BL2 image is loaded into the space BL32 -> BL2_BASE. + * Hence the BL32 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE. + */ +#define PLAT_ARM_MAX_BL32_SIZE UL(0x3D000) +#endif + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x440) +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x400) +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE UL(0x400) +#elif defined(IMAGE_BL31) +# if PLAT_XLAT_TABLES_DYNAMIC +# define PLATFORM_STACK_SIZE UL(0x800) +# else +# define PLATFORM_STACK_SIZE UL(0x400) +# endif +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE UL(0x440) +#endif + +/* + * Since free SRAM space is scant, enable the ASSERTION message size + * optimization by fixing the PLAT_LOG_LEVEL_ASSERT to LOG_LEVEL_INFO (40). + */ +#define PLAT_LOG_LEVEL_ASSERT 40 + +/* CCI related constants */ +#define PLAT_ARM_CCI_BASE UL(0x2c090000) +#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4 +#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 3 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +/* TZC related constants */ +#define PLAT_ARM_TZC_BASE UL(0x2a4a0000) +#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CCI400) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_PCIE) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD0) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD1) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_USB) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_DMA330) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_THINLINKS) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_AP) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_GPU) | \ + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CORESIGHT)) + +/* TZC related constants */ +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT_ALL + +/* + * Required ARM CSS based platform porting definitions + */ + +/* GIC related constants (no GICR in GIC-400) */ +#define PLAT_ARM_GICD_BASE UL(0x2c010000) +#define PLAT_ARM_GICC_BASE UL(0x2c02f000) +#define PLAT_ARM_GICH_BASE UL(0x2c04f000) +#define PLAT_ARM_GICV_BASE UL(0x2c06f000) + +/* MHU related constants */ +#define PLAT_CSS_MHU_BASE UL(0x2b1f0000) + +/* + * Base address of the first memory region used for communication between AP + * and SCP. Used by the BOM and SCPI protocols. + */ +#if !CSS_USE_SCMI_SDS_DRIVER +/* + * Note that this is located at the same address as SCP_BOOT_CFG_ADDR, which + * means the SCP/AP configuration data gets overwritten when the AP initiates + * communication with the SCP. The configuration data is expected to be a + * 32-bit word on all CSS platforms. On Juno, part of this configuration is + * which CPU is the primary, according to the shift and mask definitions below. + */ +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE (ARM_TRUSTED_SRAM_BASE + UL(0x80)) +#define PLAT_CSS_PRIMARY_CPU_SHIFT 8 +#define PLAT_CSS_PRIMARY_CPU_BIT_WIDTH 4 +#endif + +/* + * SCP_BL2 uses up whatever remaining space is available as it is loaded before + * anything else in this memory region and is handed over to the SCP before + * BL31 is loaded over the top. + */ +#define PLAT_CSS_MAX_SCP_BL2_SIZE \ + ((SCP_BL2_LIMIT - ARM_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK) + +#define PLAT_CSS_MAX_SCP_BL2U_SIZE PLAT_CSS_MAX_SCP_BL2_SIZE + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + CSS_G1S_IRQ_PROPS(grp), \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(JUNO_IRQ_DMA_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_HDLCD0_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_HDLCD1_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_USB_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_THIN_LINKS_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_SEC_I2C, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_GPU_SMMU_1, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(JUNO_IRQ_ETR_SMMU, GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +/* + * Required ARM CSS SoC based platform porting definitions + */ + +/* CSS SoC NIC-400 Global Programmers View (GPV) */ +#define PLAT_SOC_CSS_NIC400_BASE UL(0x2a000000) + +#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS +#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/juno/jmptbl.i b/arm-trusted-firmware/plat/arm/board/juno/jmptbl.i new file mode 100644 index 0000000..393a648 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/jmptbl.i @@ -0,0 +1,60 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Platform specific romlib functions can be added or included here. +# The index in the output file will be generated cumulatively in the same +# order as it is given in this file. +# Output file can be found at: $BUILD_DIR/jmptbl.i +# +# Format: +# lib function [patch] +# Example: +# rom rom_lib_init +# fdt fdt_getprop_namelen patch + +rom rom_lib_init +fdt fdt_getprop +fdt fdt_get_property +fdt fdt_getprop_namelen +fdt fdt_setprop_inplace +fdt fdt_check_header +fdt fdt_node_offset_by_compatible +fdt fdt_setprop_inplace_namelen_partial +fdt fdt_first_subnode +fdt fdt_next_subnode +fdt fdt_parent_offset +fdt fdt_stringlist_search +fdt fdt_get_alias_namelen +fdt fdt_path_offset +fdt fdt_path_offset_namelen +fdt fdt_address_cells +fdt fdt_size_cells +fdt fdt_get_name +fdt fdt_get_alias +fdt fdt_node_offset_by_phandle +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/arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c new file mode 100644 index 0000000..a9d5cc3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c @@ -0,0 +1,122 @@ +/* + * 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 + +void juno_reset_to_aarch32_state(void); + +static int is_watchdog_reset(void) +{ +#if !CSS_USE_SCMI_SDS_DRIVER + #define RESET_REASON_WDOG_RESET (0x2) + const uint32_t *reset_flags_ptr = (const uint32_t *)SSC_GPRETN; + + if ((*reset_flags_ptr & RESET_REASON_WDOG_RESET) != 0) + return 1; + + return 0; +#else + int ret; + uint32_t scp_reset_synd_flags; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SCP SDS initialization failed\n"); + panic(); + } + + ret = sds_struct_read(SDS_RESET_SYNDROME_STRUCT_ID, + SDS_RESET_SYNDROME_OFFSET, + &scp_reset_synd_flags, + SDS_RESET_SYNDROME_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Getting reset reason from SDS failed\n"); + panic(); + } + + /* Check if the WATCHDOG_RESET_BIT is set in the reset syndrome */ + if (scp_reset_synd_flags & SDS_RESET_SYNDROME_AP_WD_RESET_BIT) + return 1; + + return 0; +#endif +} + +/******************************************************************************* + * The following function checks if Firmware update is needed, + * by checking if TOC in FIP image is valid or watchdog reset happened. + ******************************************************************************/ +bool plat_arm_bl1_fwu_needed(void) +{ + int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR); + + /* Check if TOC is invalid or watchdog reset happened. */ + return (!arm_io_is_toc_valid() || (((nv_flags == -EAUTH) || + (nv_flags == -ENOENT)) && is_watchdog_reset())); +} + +/******************************************************************************* + * On JUNO update the arg2 with address of SCP_BL2U image info. + ******************************************************************************/ +void bl1_plat_set_ep_info(unsigned int image_id, + entry_point_info_t *ep_info) +{ + if (image_id == BL2U_IMAGE_ID) { + image_desc_t *image_desc = bl1_plat_get_image_desc(SCP_BL2U_IMAGE_ID); + ep_info->args.arg2 = (unsigned long)&image_desc->image_info; + } +} + +/******************************************************************************* + * On Juno clear SYS_NVFLAGS and wait for watchdog reset. + ******************************************************************************/ +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) +{ + uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR); + + /* Clear the NV flags register. */ + mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR), + nv_flags); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + while (true) + wfi(); +} + +#if JUNO_AARCH32_EL3_RUNTIME +void bl1_plat_prepare_exit(entry_point_info_t *ep_info) +{ +#if !ARM_DISABLE_TRUSTED_WDOG + /* Disable watchdog before leaving BL1 */ + sp805_stop(ARM_SP805_TWDG_BASE); +#endif + + juno_reset_to_aarch32_state(); +} +#endif /* JUNO_AARCH32_EL3_RUNTIME */ + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c new file mode 100644 index 0000000..849acd6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016-2017,2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include + +#if JUNO_AARCH32_EL3_RUNTIME +/******************************************************************************* + * This function changes the spsr for BL32 image to bypass + * the check in BL1 AArch64 exception handler. This is needed in the aarch32 + * boot flow as the core comes up in aarch64 and to enter the BL32 image a warm + * reset in aarch32 state is required. + ******************************************************************************/ +int arm_bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = arm_bl2_handle_post_image_load(image_id); + + if (!err && (image_id == BL32_IMAGE_ID)) { + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + assert(bl_mem_params); + bl_mem_params->ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } + + return err; +} + +#else + +/******************************************************************************* + * This function returns the list of executable images + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + struct bl_params *arm_bl_params = arm_get_next_bl_params(); + +#if __aarch64__ + const struct dyn_cfg_dtb_info_t *fw_config_info; + bl_mem_params_node_t *param_node; + uintptr_t fw_config_base = 0U; + entry_point_info_t *ep_info; + + /* Get BL31 image node */ + param_node = get_bl_mem_params_node(BL31_IMAGE_ID); + assert(param_node != NULL); + + /* Get fw_config load address */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + assert(fw_config_info != NULL); + + fw_config_base = fw_config_info->config_addr; + assert(fw_config_base != 0U); + + /* + * Get the entry point info of BL31 image and override + * arg1 of entry point info with fw_config base address + */ + ep_info = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; +#endif /* __aarch64__ */ + + return arm_bl_params; +} +#endif /* JUNO_AARCH32_EL3_RUNTIME */ diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c new file mode 100644 index 0000000..7a0a6d9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +void __init bl31_early_platform_setup2(u_register_t arg0, + u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + const struct dyn_cfg_dtb_info_t *soc_fw_config_info; + + INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1); + + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", arg1); + + soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID); + if (soc_fw_config_info != NULL) { + arg1 = soc_fw_config_info->config_addr; + } + + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * Platform specific PSCI code will enable coherency for other + * clusters. + */ + plat_arm_interconnect_enter_coherency(); +} + +void __init bl31_plat_arch_setup(void) +{ + arm_bl31_plat_arch_setup(); + + /* HW_CONFIG was also loaded by BL2 */ + const struct dyn_cfg_dtb_info_t *hw_config_info; + + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + + fconf_populate("HW_CONFIG", hw_config_info->config_addr); +} diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_common.c b/arm-trusted-firmware/plat/arm/board/juno/juno_common.c new file mode 100644 index 0000000..038f604 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_common.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +/* + * Table of memory regions for different BL stages to map using the MMU. + * This doesn't include Trusted SRAM as setup_page_tables() already takes care + * of mapping it. + */ +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RW, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, +#if TRUSTED_BOARD_BOOT + /* Map DRAM to authenticate NS_BL2U image. */ + ARM_MAP_NS_DRAM1, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RW, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, + ARM_MAP_NS_DRAM1, +#ifdef __aarch64__ + ARM_MAP_DRAM2, +#endif +#ifdef SPD_tspd + ARM_MAP_TSP_SEC_MEM, +#endif +#ifdef SPD_opteed + ARM_MAP_OPTEE_CORE_MEM, + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2U +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + CSS_MAP_DEVICE, + CSS_MAP_SCP_BL2U, + V2M_MAP_IOFPGA, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif +#ifdef IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + SOC_CSS_MAP_DEVICE, + ARM_DTB_DRAM_NS, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { +#ifndef __aarch64__ + ARM_MAP_SHARED_RAM, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif +#endif + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC + * feature is availabile for platform. + * @fid: SMCCC function id + * + * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and + * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} + +/* Get SOC version */ +int32_t plat_get_soc_version(void) +{ + return (int32_t) + (SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE, + ARM_SOC_IDENTIFICATION_CODE) | + (JUNO_SOC_ID & SOC_ID_IMPL_DEF_MASK)); +} + +/* Get SOC revision */ +int32_t plat_get_soc_revision(void) +{ + unsigned int sys_id; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) & + V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK); +} diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_def.h b/arm-trusted-firmware/plat/arm/board/juno/juno_def.h new file mode 100644 index 0000000..ddf99dc --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_def.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef JUNO_DEF_H +#define JUNO_DEF_H + +#include + +/****************************************************************************** + * Definition of platform soc id + *****************************************************************************/ +#define JUNO_SOC_ID 1 + +/******************************************************************************* + * Juno memory map related constants + ******************************************************************************/ + +/* Board revisions */ +#define REV_JUNO_R0 U(0x1) /* Rev B */ +#define REV_JUNO_R1 U(0x2) /* Rev C */ +#define REV_JUNO_R2 U(0x3) /* Rev D */ + +/* Bypass offset from start of NOR flash */ +#define BL1_ROM_BYPASS_OFFSET UL(0x03EC0000) + +#define EMMC_BASE UL(0x0c000000) +#define EMMC_SIZE UL(0x04000000) + +#define PSRAM_BASE UL(0x14000000) +#define PSRAM_SIZE UL(0x02000000) + +#define JUNO_SSC_VER_PART_NUM U(0x030) + +/******************************************************************************* + * Juno topology related constants + ******************************************************************************/ +#define JUNO_CLUSTER_COUNT U(2) +#define JUNO_CLUSTER0_CORE_COUNT U(2) +#define JUNO_CLUSTER1_CORE_COUNT U(4) + +/******************************************************************************* + * TZC-400 related constants + ******************************************************************************/ +#define TZC400_NSAID_CCI400 0 /* Note: Same as default NSAID!! */ +#define TZC400_NSAID_PCIE 1 +#define TZC400_NSAID_HDLCD0 2 +#define TZC400_NSAID_HDLCD1 3 +#define TZC400_NSAID_USB 4 +#define TZC400_NSAID_DMA330 5 +#define TZC400_NSAID_THINLINKS 6 +#define TZC400_NSAID_AP 9 +#define TZC400_NSAID_GPU 10 +#define TZC400_NSAID_SCP 11 +#define TZC400_NSAID_CORESIGHT 12 + +/******************************************************************************* + * TRNG related constants + ******************************************************************************/ +#define TRNG_BASE UL(0x7FE60000) +#define TRNG_NOUTPUTS 4 +#define TRNG_STATUS UL(0x10) +#define TRNG_INTMASK UL(0x14) +#define TRNG_CONFIG UL(0x18) +#define TRNG_CONTROL UL(0x1C) +#define TRNG_NBYTES 16 /* Number of bytes generated per round. */ + +/******************************************************************************* + * MMU-401 related constants + ******************************************************************************/ +#define MMU401_SSD_OFFSET UL(0x4000) +#define MMU401_DMA330_BASE UL(0x7fb00000) + +/******************************************************************************* + * Interrupt handling constants + ******************************************************************************/ +#define JUNO_IRQ_DMA_SMMU 126 +#define JUNO_IRQ_HDLCD0_SMMU 128 +#define JUNO_IRQ_HDLCD1_SMMU 130 +#define JUNO_IRQ_USB_SMMU 132 +#define JUNO_IRQ_THIN_LINKS_SMMU 134 +#define JUNO_IRQ_SEC_I2C 137 +#define JUNO_IRQ_GPU_SMMU_1 73 +#define JUNO_IRQ_ETR_SMMU 75 + +/******************************************************************************* + * Memprotect definitions + ******************************************************************************/ +/* PSCI memory protect definitions: + * This variable is stored in a non-secure flash because some ARM reference + * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT + * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions. + */ +#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \ + V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +#endif /* JUNO_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_err.c b/arm-trusted-firmware/plat/arm/board/juno/juno_err.c new file mode 100644 index 0000000..02d751e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_err.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* + * Juno error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + /* Propagate the err code in the NV-flags register */ + mmio_write_32(V2M_SYS_NVFLAGS_ADDR, (uint32_t)err); + + /* Setup the watchdog to reset the system as soon as possible */ + sp805_refresh(ARM_SP805_TWDG_BASE, 1U); + + for (;;) + wfi(); +} diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_pm.c b/arm-trusted-firmware/plat/arm/board/juno/juno_pm.c new file mode 100644 index 0000000..cc80651 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_pm.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ +#if CSS_USE_SCMI_SDS_DRIVER + return css_scmi_override_pm_ops(ops); +#else + return ops; +#endif /* CSS_USE_SCMI_SDS_DRIVER */ +} diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_security.c b/arm-trusted-firmware/plat/arm/board/juno/juno_security.c new file mode 100644 index 0000000..654a7f1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_security.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "juno_tzmp1_def.h" + +#ifdef JUNO_TZMP1 +/* + * Protect buffer for VPU/GPU/DPU memory usage with hardware protection + * enabled. Propose 224MB video output, 96 MB video input and 32MB video + * private. + * + * Ind Memory Range Caption S_ATTR NS_ATTR + * 1 0x080000000 - 0x0E7FFFFFF ARM_NS_DRAM1 NONE RDWR | MEDIA_RW + * 2 0x0E8000000 - 0x0F5FFFFFF JUNO_MEDIA_TZC_PROT_DRAM1 NONE MEDIA_RW | AP_WR + * 3 0x0F6000000 - 0x0FBFFFFFF JUNO_VPU_TZC_PROT_DRAM1 RDWR VPU_PROT_RW + * 4 0x0FC000000 - 0x0FDFFFFFF JUNO_VPU_TZC_PRIV_DRAM1 RDWR VPU_PRIV_RW + * 5 0x0FE000000 - 0x0FEFFFFFF JUNO_AP_TZC_SHARE_DRAM1 NONE RDWR | MEDIA_RW + * 6 0x0FF000000 - 0x0FFFFFFFF ARM_AP_TZC_DRAM1 RDWR NONE + * 7 0x880000000 - 0x9FFFFFFFF ARM_DRAM2 NONE RDWR | MEDIA_RW + * + * Memory regions are neighbored to save limited TZC regions. Calculation + * started from ARM_TZC_SHARE_DRAM1 since it is known and fixed for both + * protected-enabled and protected-disabled settings. + * + * Video private buffer aheads of ARM_TZC_SHARE_DRAM1 + */ + +static const arm_tzc_regions_info_t juno_tzmp1_tzc_regions[] = { + {ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END, TZC_REGION_S_RDWR, 0}, + {JUNO_NS_DRAM1_PT1_BASE, JUNO_NS_DRAM1_PT1_END, + TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS}, + {JUNO_MEDIA_TZC_PROT_DRAM1_BASE, JUNO_MEDIA_TZC_PROT_DRAM1_END, + TZC_REGION_S_NONE, JUNO_MEDIA_TZC_PROT_ACCESS}, + {JUNO_VPU_TZC_PROT_DRAM1_BASE, JUNO_VPU_TZC_PROT_DRAM1_END, + TZC_REGION_S_RDWR, JUNO_VPU_TZC_PROT_ACCESS}, + {JUNO_VPU_TZC_PRIV_DRAM1_BASE, JUNO_VPU_TZC_PRIV_DRAM1_END, + TZC_REGION_S_RDWR, JUNO_VPU_TZC_PRIV_ACCESS}, + {JUNO_AP_TZC_SHARE_DRAM1_BASE, JUNO_AP_TZC_SHARE_DRAM1_END, + TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS}, + {ARM_DRAM2_BASE, ARM_DRAM2_END, + TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS}, + {}, +}; + +/******************************************************************************* + * Program dp650 to configure NSAID value for protected mode. + ******************************************************************************/ +static void init_dp650(void) +{ + mmio_write_32(DP650_BASE + DP650_PROT_NSAID_OFFSET, + DP650_PROT_NSAID_CONFIG); +} + +/******************************************************************************* + * Program v550 to configure NSAID value for protected mode. + ******************************************************************************/ +static void init_v550(void) +{ + /* + * bits[31:28] is for PRIVATE, + * bits[27:24] is for OUTBUF, + * bits[23:20] is for PROTECTED. + */ + mmio_write_32(V550_BASE + V550_PROTCTRL_OFFSET, V550_PROTCTRL_CONFIG); +} + +#endif /* JUNO_TZMP1 */ + +/******************************************************************************* + * Set up the MMU-401 SSD tables. The power-on configuration has all stream IDs + * assigned to Non-Secure except some for the DMA-330. Assign those back to the + * Non-Secure world as well, otherwise EL1 may end up erroneously generating + * (untranslated) Secure transactions if it turns the SMMU on. + ******************************************************************************/ +static void init_mmu401(void) +{ + uint32_t reg = mmio_read_32(MMU401_DMA330_BASE + MMU401_SSD_OFFSET); + reg |= 0x1FF; + mmio_write_32(MMU401_DMA330_BASE + MMU401_SSD_OFFSET, reg); +} + +/******************************************************************************* + * Program CSS-NIC400 to allow non-secure access to some CSS regions. + ******************************************************************************/ +static void css_init_nic400(void) +{ + /* Note: This is the NIC-400 device on the CSS */ + mmio_write_32(PLAT_SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(CSS_NIC400_SLAVE_BOOTSECURE), + ~0); +} + +/******************************************************************************* + * Initialize debug configuration. + ******************************************************************************/ +static void init_debug_cfg(void) +{ +#if !DEBUG + /* Set internal drive selection for SPIDEN. */ + mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_SET, + 1U << SPIDEN_SEL_SET_SHIFT); + + /* Drive SPIDEN LOW to disable invasive debug of secure state. */ + mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_CLR, + 1U << SPIDEN_INT_CLR_SHIFT); + + /* Set internal drive selection for SPNIDEN. */ + mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_SET, + 1U << SPNIDEN_SEL_SET_SHIFT); + + /* Drive SPNIDEN LOW to disable non-invasive debug of secure state. */ + mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_CLR, + 1U << SPNIDEN_INT_CLR_SHIFT); +#endif +} + +/******************************************************************************* + * Initialize the secure environment. + ******************************************************************************/ +void plat_arm_security_setup(void) +{ + /* Initialize debug configuration */ + init_debug_cfg(); + /* Initialize the TrustZone Controller */ +#ifdef JUNO_TZMP1 + arm_tzc400_setup(PLAT_ARM_TZC_BASE, juno_tzmp1_tzc_regions); + INFO("TZC protected shared memory base address for TZMP usecase: %p\n", + (void *)JUNO_AP_TZC_SHARE_DRAM1_BASE); + INFO("TZC protected shared memory end address for TZMP usecase: %p\n", + (void *)JUNO_AP_TZC_SHARE_DRAM1_END); +#else + arm_tzc400_setup(PLAT_ARM_TZC_BASE, NULL); +#endif + /* Do ARM CSS internal NIC setup */ + css_init_nic400(); + /* Do ARM CSS SoC security setup */ + soc_css_security_setup(); + /* Initialize the SMMU SSD tables */ + init_mmu401(); +#ifdef JUNO_TZMP1 + init_dp650(); + init_v550(); +#endif +} + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c b/arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c new file mode 100644 index 0000000..3924af8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +u_register_t plat_get_stack_protector_canary(void) +{ + uint64_t entropy; + + if (!plat_get_entropy(&entropy)) { + ERROR("Not enough entropy to initialize canary value\n"); + panic(); + } + + if (sizeof(entropy) == sizeof(u_register_t)) { + return entropy; + } + + return (entropy & 0xffffffffULL) ^ (entropy >> 32); +} diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_topology.c b/arm-trusted-firmware/plat/arm/board/juno/juno_topology.c new file mode 100644 index 0000000..075f512 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_topology.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#if CSS_USE_SCMI_SDS_DRIVER +static scmi_channel_plat_info_t juno_scmi_plat_info = { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell, +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + return &juno_scmi_plat_info; +} + +#endif +/* + * On Juno, the system power level is the highest power level. + * The first entry in the power domain descriptor specifies the + * number of system power domains i.e. 1. + */ +#define JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_SYSTEM_COUNT + +/* + * The Juno power domain tree descriptor. The cluster power domains + * are arranged so that when the PSCI generic code creates the power + * domain tree, the indices of the CPU power domain nodes it allocates + * match the linear indices returned by plat_core_pos_by_mpidr() + * i.e. CLUSTER1 CPUs are allocated indices from 0 to 3 and the higher + * indices for CLUSTER0 CPUs. + */ +static const unsigned char juno_power_domain_tree_desc[] = { + /* No of root nodes */ + JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL, + /* No of children for the root node */ + JUNO_CLUSTER_COUNT, + /* No of children for the first cluster node */ + JUNO_CLUSTER1_CORE_COUNT, + /* No of children for the second cluster node */ + JUNO_CLUSTER0_CORE_COUNT +}; + +/******************************************************************************* + * This function returns the Juno topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return juno_power_domain_tree_desc; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return (((mpidr & (u_register_t) 0x100) != 0U) ? + JUNO_CLUSTER1_CORE_COUNT : JUNO_CLUSTER0_CORE_COUNT); +} + +/* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + */ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 2, 3, 4, 5, 0, 1 }; diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_trng.c b/arm-trusted-firmware/plat/arm/board/juno/juno_trng.c new file mode 100644 index 0000000..09552a6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_trng.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017-2018, 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 + +#define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */ +#define NRETRIES 5 + +/* initialised to false */ +static bool juno_trng_initialized; + +static bool output_valid(void) +{ + int i; + + for (i = 0; i < NRETRIES; i++) { + uint32_t val; + + val = mmio_read_32(TRNG_BASE + TRNG_STATUS); + if (val & 1U) + return true; + } + return false; /* No output data available. */ +} + +DEFINE_SVC_UUID2(_plat_trng_uuid, + 0x23523c58, 0x7448, 0x4083, 0x9d, 0x16, + 0xe3, 0xfa, 0xb9, 0xf1, 0x73, 0xbc +); +uuid_t plat_trng_uuid; + +static uint32_t crc_value = ~0U; + +/* + * Uses the Trusted Entropy Source peripheral on Juno to return 8 bytes of + * entropy. Returns 'true' when done successfully, 'false' otherwise. + */ +bool plat_get_entropy(uint64_t *out) +{ + uint64_t ret; + + assert(out); + assert(!check_uptr_overflow((uintptr_t)out, sizeof(*out))); + + if (!juno_trng_initialized) { + /* Disable interrupt mode. */ + mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0); + /* Program TRNG to sample for `NSAMPLE_CLOCKS`. */ + mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS); + /* Abort any potentially pending sampling. */ + mmio_write_32(TRNG_BASE + TRNG_CONTROL, 2); + /* Reset TRNG outputs. */ + mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); + + juno_trng_initialized = true; + } + + if (!output_valid()) { + /* Start TRNG. */ + mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); + + if (!output_valid()) + return false; + } + + /* CRC each two 32-bit registers together, combine the pairs */ + crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 0)); + crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 4)); + ret = (uint64_t)crc_value << 32; + + crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 8)); + crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 12)); + *out = ret | crc_value; + + /* Acknowledge current cycle, clear output registers. */ + mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); + /* Trigger next TRNG cycle. */ + mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); + + return true; +} + +void plat_entropy_setup(void) +{ + uint64_t dummy; + + plat_trng_uuid = _plat_trng_uuid; + + /* Initialise the entropy source and trigger RNG generation */ + plat_get_entropy(&dummy); +} diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c new file mode 100644 index 0000000..25a7470 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + +static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN]; + +extern unsigned char arm_rotpk_header[]; + +/* + * Return the ROTPK hash stored in the registers of Juno board. + */ +static int juno_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + uint8_t *dst; + uint32_t *src, tmp; + unsigned int words, i; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + /* Copy the DER header */ + memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); + dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; + + + /* + * Append the hash from Trusted Root-Key Storage registers. The hash has + * not been written linearly into the registers, so we have to do a bit + * of byte swapping: + * + * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C + * +---------------------------------------------------------------+ + * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 | + * +---------------------------------------------------------------+ + * | ... ... | | ... ... | + * | +--------------------+ | +-------+ + * | | | | + * +----------------------------+ +----------------------------+ + * | | | | + * +-------+ | +--------------------+ | + * | | | | + * v v v v + * +---------------------------------------------------------------+ + * | | | + * +---------------------------------------------------------------+ + * 0 15 16 31 + * + * Additionally, we have to access the registers in 32-bit words + */ + words = ARM_ROTPK_HASH_LEN >> 3; + + /* Swap bytes 0-15 (first four registers) */ + src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + /* Words are read in little endian */ + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } + + /* Swap bytes 16-31 (last four registers) */ + src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + ARM_ROTPK_HASH_LEN / 2); + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } + + *key_ptr = (void *)rotpk_hash_der; + *key_len = (unsigned int)sizeof(rotpk_hash_der); + *flags = ROTPK_IS_HASH; + return 0; +} + +#endif + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ +#if ARM_CRYPTOCELL_INTEG + return arm_get_rotpk_info_cc(key_ptr, key_len, flags); +#else + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \ + (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) + return arm_get_rotpk_info_dev(key_ptr, key_len, flags); +#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + return juno_get_rotpk_info_regs(key_ptr, key_len, flags); +#else + return 1; +#endif + +#endif /* ARM_CRYPTOCELL_INTEG */ +} diff --git a/arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h b/arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h new file mode 100644 index 0000000..4186d02 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef JUNO_TZMP1_DEF_H +#define JUNO_TZMP1_DEF_H + +/* + * Public memory regions for both protected and non-protected mode + * + * OPTEE shared memory 0xFEE00000 - 0xFEFFFFFF + */ +#define JUNO_AP_TZC_SHARE_DRAM1_SIZE ULL(0x02000000) +#define JUNO_AP_TZC_SHARE_DRAM1_BASE (ARM_AP_TZC_DRAM1_BASE - \ + JUNO_AP_TZC_SHARE_DRAM1_SIZE) +#define JUNO_AP_TZC_SHARE_DRAM1_END (ARM_AP_TZC_DRAM1_BASE - 1) + +/* ARM_MEDIA_FEATURES for MEDIA GPU Protect Mode Test */ +#define JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE 8 /* GPU/DPU protected, VPU outbuf */ +#define JUNO_TZC400_NSAID_FPGA_VIDEO_PROTECTED 7 /* VPU protected */ +#define JUNO_TZC400_NSAID_FPGA_VIDEO_PRIVATE 10 /* VPU private (firmware) */ + +#define JUNO_VPU_TZC_PRIV_DRAM1_SIZE ULL(0x02000000) +#define JUNO_VPU_TZC_PRIV_DRAM1_BASE (JUNO_AP_TZC_SHARE_DRAM1_BASE - \ + JUNO_VPU_TZC_PRIV_DRAM1_SIZE) +#define JUNO_VPU_TZC_PRIV_DRAM1_END (JUNO_AP_TZC_SHARE_DRAM1_BASE - 1) + +/* Video input protected buffer follows upper item */ +#define JUNO_VPU_TZC_PROT_DRAM1_SIZE ULL(0x06000000) +#define JUNO_VPU_TZC_PROT_DRAM1_BASE (JUNO_VPU_TZC_PRIV_DRAM1_BASE - \ + JUNO_VPU_TZC_PROT_DRAM1_SIZE) +#define JUNO_VPU_TZC_PROT_DRAM1_END (JUNO_VPU_TZC_PRIV_DRAM1_BASE - 1) + +/* Video, graphics and display shares same NSAID and same protected buffer */ +#define JUNO_MEDIA_TZC_PROT_DRAM1_SIZE ULL(0x0e000000) +#define JUNO_MEDIA_TZC_PROT_DRAM1_BASE (JUNO_VPU_TZC_PROT_DRAM1_BASE - \ + JUNO_MEDIA_TZC_PROT_DRAM1_SIZE) +#define JUNO_MEDIA_TZC_PROT_DRAM1_END (JUNO_VPU_TZC_PROT_DRAM1_BASE - 1) + +/* Rest of DRAM1 are Non-Secure public buffer */ +#define JUNO_NS_DRAM1_PT1_BASE ARM_DRAM1_BASE +#define JUNO_NS_DRAM1_PT1_END (JUNO_MEDIA_TZC_PROT_DRAM1_BASE - 1) +#define JUNO_NS_DRAM1_PT1_SIZE (JUNO_NS_DRAM1_PT1_END - \ + JUNO_NS_DRAM1_PT1_BASE + 1) + +/* TZC filter flags */ +#define JUNO_MEDIA_TZC_NS_DEV_ACCESS (PLAT_ARM_TZC_NS_DEV_ACCESS | \ + TZC_REGION_ACCESS_RD(JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE)) + +/* VPU / GPU /DPU protected access */ +#define JUNO_MEDIA_TZC_PROT_ACCESS \ + (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE) | \ + TZC_REGION_ACCESS_WR(TZC400_NSAID_AP)) + +#define JUNO_VPU_TZC_PROT_ACCESS \ + (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_VIDEO_PROTECTED)) + +#define JUNO_VPU_TZC_PRIV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_VIDEO_PRIVATE)) + +/******************************************************************************* + * Mali-DP650 related constants + ******************************************************************************/ +/* Base address of DP650 */ +#define DP650_BASE 0x6f200000 +/* offset to PROT_NSAID register */ +#define DP650_PROT_NSAID_OFFSET 0x10004 +/* config to PROT_NSAID register */ +#define DP650_PROT_NSAID_CONFIG 0x08008888 + +/******************************************************************************* + * Mali-V550 related constants + ******************************************************************************/ +/* Base address of V550 */ +#define V550_BASE 0x6f030000 +/* offset to PROTCTRL register */ +#define V550_PROTCTRL_OFFSET 0x0040 +/* config to PROTCTRL register */ +#define V550_PROTCTRL_CONFIG 0xa8700000 + +#endif /* JUNO_TZMP1_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/juno/platform.mk b/arm-trusted-firmware/plat/arm/board/juno/platform.mk new file mode 100644 index 0000000..2c84eb3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/platform.mk @@ -0,0 +1,201 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +JUNO_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +JUNO_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \ + plat/arm/common/arm_cci.c + +JUNO_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \ + plat/arm/board/juno/juno_security.c \ + plat/arm/board/juno/juno_trng.c \ + plat/arm/common/arm_tzc400.c + +ifneq (${ENABLE_STACK_PROTECTOR}, 0) +JUNO_SECURITY_SOURCES += plat/arm/board/juno/juno_stack_protector.c +endif + +# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the +# SCP during power management operations and for SCP RAM Firmware transfer. +CSS_USE_SCMI_SDS_DRIVER := 1 + +PLAT_INCLUDES := -Iplat/arm/board/juno/include + +PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/${ARCH}/juno_helpers.S \ + plat/arm/board/juno/juno_common.c + +# Flag to enable support for AArch32 state on JUNO +JUNO_AARCH32_EL3_RUNTIME := 0 +$(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME)) +$(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME)) + +# Flag to enable support for TZMP1 on JUNO +JUNO_TZMP1 := 0 +$(eval $(call assert_boolean,JUNO_TZMP1)) +ifeq (${JUNO_TZMP1}, 1) +$(eval $(call add_define,JUNO_TZMP1)) +endif + +TRNG_SUPPORT := 1 + +ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1) +# Include BL32 in FIP +NEED_BL32 := yes +# BL31 is not required +override BL31_SOURCES = + +# The BL32 needs to be built separately invoking the AARCH32 compiler and +# be specifed via `BL32` build option. + ifneq (${ARCH}, aarch32) + override BL32_SOURCES = + endif +endif + +ifeq (${ARCH},aarch64) +BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + plat/arm/board/juno/juno_err.c \ + plat/arm/board/juno/juno_bl1_setup.c \ + drivers/arm/sp805/sp805.c \ + ${JUNO_INTERCONNECT_SOURCES} \ + ${JUNO_SECURITY_SOURCES} + +BL2_SOURCES += drivers/arm/sp805/sp805.c \ + lib/utils/mem_region.c \ + plat/arm/board/juno/juno_err.c \ + plat/arm/board/juno/juno_bl2_setup.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${JUNO_SECURITY_SOURCES} + +BL2U_SOURCES += ${JUNO_SECURITY_SOURCES} + +BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/utils/mem_region.c \ + lib/fconf/fconf.c \ + lib/fconf/fconf_dyn_cfg_getter.c \ + plat/arm/board/juno/juno_bl31_setup.c \ + plat/arm/board/juno/juno_pm.c \ + plat/arm/board/juno/juno_topology.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + ${JUNO_GIC_SOURCES} \ + ${JUNO_INTERCONNECT_SOURCES} \ + ${JUNO_SECURITY_SOURCES} + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +ifeq (${CSS_USE_SCMI_SDS_DRIVER},1) +BL1_SOURCES += drivers/arm/css/sds/sds.c +endif + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += plat/arm/board/juno/juno_trusted_boot.c +BL2_SOURCES += plat/arm/board/juno/juno_trusted_boot.c +endif + +endif + +ifneq (${RESET_TO_BL31},0) + $(error "Using BL31 as the reset vector is not supported on ${PLAT} platform. \ + Please set RESET_TO_BL31 to 0.") +endif + +ifeq ($(USE_ROMLIB),1) +all : bl1_romlib.bin +endif + +bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin romlib.bin + @echo "Building combined BL1 and ROMLIB binary for Juno $@" + ./lib/romlib/gen_combined_bl1_romlib.sh -o bl1_romlib.bin $(BUILD_PLAT) + +# Errata workarounds for Cortex-A53: +ERRATA_A53_819472 := 1 +ERRATA_A53_824069 := 1 +ERRATA_A53_826319 := 1 +ERRATA_A53_827319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +# Errata workarounds for Cortex-A57: +ERRATA_A57_806969 := 0 +ERRATA_A57_813419 := 1 +ERRATA_A57_813420 := 1 +ERRATA_A57_814670 := 1 +ERRATA_A57_817169 := 1 +ERRATA_A57_826974 := 1 +ERRATA_A57_826977 := 1 +ERRATA_A57_828024 := 1 +ERRATA_A57_829520 := 1 +ERRATA_A57_833471 := 1 +ERRATA_A57_859972 := 0 + +# Errata workarounds for Cortex-A72: +ERRATA_A72_859971 := 0 + +# Enable option to skip L1 data cache flush during the Cortex-A57 cluster +# power down sequence +SKIP_A57_L1_FLUSH_PWR_DWN := 1 + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +# Enable the dynamic translation tables library. +ifeq (${ARCH},aarch32) + ifeq (${RESET_TO_SP_MIN},1) + BL32_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +else + ifeq (${RESET_TO_BL31},1) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +endif + +ifeq (${ALLOW_RO_XLAT_TABLES}, 1) + ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1) + BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + else + BL31_CPPFLAGS += -DPLAT_RO_XLAT_TABLES + endif +endif + +BL1_CPPFLAGS += -march=armv8-a+crc +BL2_CPPFLAGS += -march=armv8-a+crc +BL2U_CPPFLAGS += -march=armv8-a+crc +BL31_CPPFLAGS += -march=armv8-a+crc +BL32_CPPFLAGS += -march=armv8-a+crc + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += plat/arm/board/juno/fdts/${PLAT}_fw_config.dts \ + plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts \ + fdts/${PLAT}.dts + +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb +HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config,${HW_CONFIG})) + +include plat/arm/board/common/board_common.mk +include plat/arm/common/arm_common.mk +include plat/arm/soc/common/soc_css.mk +include plat/arm/css/common/css_common.mk diff --git a/arm-trusted-firmware/plat/arm/board/juno/sp_min/sp_min-juno.mk b/arm-trusted-firmware/plat/arm/board/juno/sp_min/sp_min-juno.mk new file mode 100644 index 0000000..b3471c1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/sp_min/sp_min-juno.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to JUNO platform +BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/cpus/aarch32/cortex_a53.S \ + lib/cpus/aarch32/cortex_a57.S \ + lib/cpus/aarch32/cortex_a72.S \ + lib/utils/mem_region.c \ + plat/arm/board/juno/juno_pm.c \ + plat/arm/board/juno/juno_topology.c \ + plat/arm/common/arm_nor_psci_mem_protect.c \ + plat/arm/soc/common/soc_css_security.c \ + ${JUNO_GIC_SOURCES} \ + ${JUNO_INTERCONNECT_SOURCES} \ + ${JUNO_SECURITY_SOURCES} + +include plat/arm/common/sp_min/arm_sp_min.mk +include plat/arm/css/common/sp_min/css_sp_min.mk diff --git a/arm-trusted-firmware/plat/arm/board/juno/tsp/tsp-juno.mk b/arm-trusted-firmware/plat/arm/board/juno/tsp/tsp-juno.mk new file mode 100644 index 0000000..be75c4d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/tsp/tsp-juno.mk @@ -0,0 +1,12 @@ +# +# Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += plat/arm/board/juno/juno_topology.c \ + plat/arm/css/common/css_topology.c \ + ${JUNO_GIC_SOURCES} \ + ${JUNO_SECURITY_SOURCES} + +include plat/arm/common/tsp/arm_tsp.mk diff --git a/arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S b/arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S new file mode 100644 index 0000000..60470a8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Helper function to calculate the core position. + * ((ChipId * MORELLO_MAX_CLUSTERS_PER_CHIP + ClusterId) * + * MORELLO_MAX_CPUS_PER_CLUSTER * MORELLO_MAX_PE_PER_CPU) + + * (CPUId * MORELLO_MAX_PE_PER_CPU) + ThreadId + * + * which can be simplified as: + * + * (((ChipId * MORELLO_MAX_CLUSTERS_PER_CHIP + ClusterId) * + * MORELLO_MAX_CPUS_PER_CLUSTER + CPUId) * MORELLO_MAX_PE_PER_CPU) + + * ThreadId + * ------------------------------------------------------ + */ + +func plat_arm_calc_core_pos + mov x4, x0 + + /* + * The MT bit in MPIDR is always set for morello and the + * affinity level 0 corresponds to thread affinity level. + */ + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #MORELLO_MAX_CLUSTERS_PER_CHIP + madd x2, x3, x4, x2 + mov x4, #MORELLO_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x4, #MORELLO_MAX_PE_PER_CPU + madd x0, x1, x4, x0 + ret +endfunc plat_arm_calc_core_pos diff --git a/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts new file mode 100644 index 0000000..c47bae5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts new file mode 100644 index 0000000..e730d34 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,morello"; + + /* + * Place holder for platform-info node with default values. + * The values will be set to the correct values during + * the BL2 stage of boot. + */ + platform-info { + local-ddr-size = <0x0 0x0>; +#ifdef TARGET_PLATFORM_SOC + remote-ddr-size = <0x0 0x0>; + remote-chip-count = <0x0>; + multichip-mode = <0x0>; + scc-config = <0x0>; +#endif + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts new file mode 100644 index 0000000..305a818 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S new file mode 100644 index 0000000..195be84 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * + * There are currently no platform specific regs + * to print. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h new file mode 100644 index 0000000..08e2d60 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE ULL(0x2A400000) +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ U(50000000) + +/* IOFPGA UART0 */ +#define PLAT_ARM_RUN_UART_BASE ULL(0x1C090000) +#define PLAT_ARM_RUN_UART_CLK_IN_HZ U(24000000) + +#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_DRAM2_BASE ULL(0x8080000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0xF80000000) + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +#define PLAT_ARM_FLASH_IMAGE_BASE ULL(0x1A000000) +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE ULL(0x01000000) + +#define PLAT_ARM_NVM_BASE ULL(0x1A000000) +#define PLAT_ARM_NVM_SIZE ULL(0x01000000) + +#if defined NS_BL1U_BASE +#undef NS_BL1U_BASE +#define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x00800000)) +#endif + +/* + * There are no non-volatile counters in morello, these macros points + * to unused addresses. + */ +#define SOC_TRUSTED_NVCTR_BASE ULL(0x7FE70000) +#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + U(0x0000)) +#define TFW_NVCTR_SIZE U(4) +#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + U(0x0004)) +#define NTFW_CTR_SIZE U(4) + +/* + * To access the complete DDR memory along with remote chip's DDR memory, + * which is at 4 TB offset, physical and virtual address space limits are + * extended to 43-bits. + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 43) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 43) + +#if CSS_USE_SCMI_SDS_DRIVER +#define MORELLO_SCMI_PAYLOAD_BASE ULL(0x45400000) +#else +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE ULL(0x45400000) +#endif + +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00080000) + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xC000) + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xE000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE U(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE U(0) +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE UL(0x1D000) +#else +# define PLAT_ARM_MAX_BL2_SIZE UL(0x14000) +#endif + +#define PLAT_ARM_MAX_BL31_SIZE UL(0x3B000) + +/******************************************************************************* + * MORELLO topology related constants + ******************************************************************************/ +#define MORELLO_MAX_CPUS_PER_CLUSTER U(2) +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define PLAT_MORELLO_CHIP_COUNT U(1) +#define MORELLO_MAX_CLUSTERS_PER_CHIP U(2) +#define MORELLO_MAX_PE_PER_CPU U(1) + +#define PLATFORM_CORE_COUNT (PLAT_MORELLO_CHIP_COUNT * \ + PLAT_ARM_CLUSTER_COUNT * \ + MORELLO_MAX_CPUS_PER_CLUSTER * \ + MORELLO_MAX_PE_PER_CPU) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3 + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if IMAGE_BL1 || IMAGE_BL31 +# define PLAT_ARM_MMAP_ENTRIES U(6) +# define MAX_XLAT_TABLES U(7) +#else +# define PLAT_ARM_MMAP_ENTRIES U(5) +# define MAX_XLAT_TABLES U(6) +#endif + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x440) +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else +# define PLATFORM_STACK_SIZE UL(0x400) +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE UL(0x400) +#elif defined(IMAGE_BL31) +# if SPM_MM +# define PLATFORM_STACK_SIZE UL(0x500) +# else +# define PLATFORM_STACK_SIZE UL(0x400) +# endif +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE UL(0x440) +#endif + +#define PLAT_ARM_NSTIMER_FRAME_ID U(0) + +#define PLAT_ARM_TRUSTED_ROM_BASE U(0x0) +#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00020000) /* 128KB */ + +#define PLAT_ARM_NSRAM_BASE ULL(0x06000000) +#define PLAT_ARM_NSRAM_SIZE UL(0x00010000) /* 64KB */ + +#define PLAT_CSS_MHU_BASE UL(0x45000000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE +#define PLAT_MAX_PWR_LVL U(2) + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp) +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#define MORELLO_DEVICE_BASE ULL(0x08000000) +#define MORELLO_DEVICE_SIZE ULL(0x48000000) + +/*Secure Watchdog Constants */ +#define SBSA_SECURE_WDOG_BASE UL(0x2A480000) +#define SBSA_SECURE_WDOG_TIMEOUT UL(1000) + +#define MORELLO_MAP_DEVICE MAP_REGION_FLAT( \ + MORELLO_DEVICE_BASE, \ + MORELLO_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_DRAM1 MAP_REGION_FLAT( \ + ARM_DRAM1_BASE, \ + ARM_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x300C0000) + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c new file mode 100644 index 0000000..9155542 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ + +void soc_css_init_nic400(void) +{ +} + +void soc_css_init_pcie(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c new file mode 100644 index 0000000..0d4b6d0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void bl2_platform_setup(void) +{ +#ifdef TARGET_PLATFORM_SOC + /* + * Morello platform supports RDIMMs with ECC capability. To use the ECC + * capability, the entire DDR memory space has to be zeroed out before + * enabling the ECC bits in DMC-Bing. + * Zeroing DDR memory range 0x80000000 - 0xFFFFFFFF during BL2 stage, + * as BL33 binary cannot be copied to DDR memory before enabling ECC. + * Rest of the DDR memory space is zeroed out during BL31 stage. + */ + INFO("Zeroing DDR memory range 0x80000000 - 0xFFFFFFFF\n"); + zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE); + flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE); +#endif + arm_bl2_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c new file mode 100644 index 0000000..e418518 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "morello_def.h" +#include + +#ifdef TARGET_PLATFORM_FVP +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size + * - Local DDR size in bytes, DDR memory in main board + */ +struct morello_plat_info { + uint64_t local_ddr_size; +} __packed; +#else +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which is an information about multichip setup + * - Local DDR size in bytes, DDR memory in main board + * - Remote DDR size in bytes, DDR memory in remote board + * - remote_chip_count + * - multichip mode + * - scc configuration + */ +struct morello_plat_info { + uint64_t local_ddr_size; + uint64_t remote_ddr_size; + uint8_t remote_chip_count; + bool multichip_mode; + uint32_t scc_config; +} __packed; +#endif + +/* Compile time assertion to ensure the size of structure is 18 bytes */ +CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE, + assert_invalid_plat_info_size); + +static scmi_channel_plat_info_t morello_scmi_plat_info = { + .scmi_mbx_mem = MORELLO_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + return &morello_scmi_plat_info; +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return css_scmi_override_pm_ops(ops); +} + +#ifdef TARGET_PLATFORM_SOC +/* + * Morello platform supports RDIMMs with ECC capability. To use the ECC + * capability, the entire DDR memory space has to be zeroed out before + * enabling the ECC bits in DMC-Bing. Zeroing out several gigabytes of + * memory from SCP is quite time consuming so the following function + * is added to zero out the DDR memory from application processor which is + * much faster compared to SCP. + */ + +static void dmc_ecc_setup(struct morello_plat_info *plat_info) +{ + uint64_t dram2_size; + uint32_t val; + uint64_t tag_mem_base; + uint64_t usable_mem_size; + + INFO("Total DIMM size: %uGB\n", + (uint32_t)(plat_info->local_ddr_size / 0x40000000)); + + assert(plat_info->local_ddr_size > ARM_DRAM1_SIZE); + dram2_size = plat_info->local_ddr_size - ARM_DRAM1_SIZE; + + INFO("Zeroing DDR memory range 0x%llx - 0x%llx\n", + ARM_DRAM2_BASE, ARM_DRAM2_BASE + dram2_size); + zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size); + flush_dcache_range(ARM_DRAM2_BASE, dram2_size); + + /* Clear previous ECC errors while zeroing out the memory */ + val = mmio_read_32(MORELLO_DMC0_ERR2STATUS_REG); + mmio_write_32(MORELLO_DMC0_ERR2STATUS_REG, val); + + val = mmio_read_32(MORELLO_DMC1_ERR2STATUS_REG); + mmio_write_32(MORELLO_DMC1_ERR2STATUS_REG, val); + + /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ + mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG); + mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG); + + while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) & + MORELLO_DMC_MEMC_STATUS_MASK) != + MORELLO_DMC_MEMC_CMD_CONFIG) { + continue; + } + + while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) & + MORELLO_DMC_MEMC_STATUS_MASK) != + MORELLO_DMC_MEMC_CMD_CONFIG) { + continue; + } + + /* Configure Bing client/server mode based on SCC configuration */ + if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) { + INFO("Configuring DMC Bing in client mode\n"); + usable_mem_size = plat_info->local_ddr_size - + (plat_info->local_ddr_size / 128ULL); + + /* Linear DDR address */ + tag_mem_base = usable_mem_size; + tag_mem_base = tag_mem_base / 4; + + /* Reverse translation */ + if (tag_mem_base < ARM_DRAM1_BASE) { + tag_mem_base += ARM_DRAM1_BASE; + } else { + tag_mem_base = tag_mem_base - ARM_DRAM1_BASE + + ARM_DRAM2_BASE; + } + + mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x1); + mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x1); + mmio_write_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x1); + mmio_write_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x1); + + if (plat_info->scc_config & MORELLO_SCC_C1_TAG_CACHE_EN_MASK) { + mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x2); + mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x2); + INFO("C1 Tag Cache Enabled\n"); + } + + if (plat_info->scc_config & MORELLO_SCC_C2_TAG_CACHE_EN_MASK) { + mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x4); + mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x4); + INFO("C2 Tag Cache Enabled\n"); + } + + mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL, + (uint32_t)tag_mem_base); + mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL, + (uint32_t)tag_mem_base); + mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL2, + (uint32_t)(tag_mem_base >> 32)); + mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL2, + (uint32_t)(tag_mem_base >> 32)); + + mmio_setbits_32(MORELLO_DMC0_MEM_ACCESS_CTL, + MORELLO_DMC_MEM_ACCESS_DIS); + mmio_setbits_32(MORELLO_DMC1_MEM_ACCESS_CTL, + MORELLO_DMC_MEM_ACCESS_DIS); + + INFO("Tag base set to 0x%lx\n", tag_mem_base); + plat_info->local_ddr_size = usable_mem_size; + } else { + INFO("Configuring DMC Bing in server mode\n"); + mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x0); + mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x0); + } + + INFO("Enabling ECC on DMCs\n"); + /* Enable ECC in DMCs */ + mmio_setbits_32(MORELLO_DMC0_ERR0CTLR0_REG, + MORELLO_DMC_ERR0CTLR0_ECC_EN); + mmio_setbits_32(MORELLO_DMC1_ERR0CTLR0_REG, + MORELLO_DMC_ERR0CTLR0_ECC_EN); + + /* Set DMCs to READY state */ + mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY); + mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY); + + while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) & + MORELLO_DMC_MEMC_STATUS_MASK) != + MORELLO_DMC_MEMC_CMD_READY) { + continue; + } + + while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) & + MORELLO_DMC_MEMC_STATUS_MASK) != + MORELLO_DMC_MEMC_CMD_READY) { + continue; + } +} +#endif + +void bl31_platform_setup(void) +{ + int ret; + struct morello_plat_info plat_info; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SDS initialization failed. ret:%d\n", ret); + panic(); + } + + ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID, + MORELLO_SDS_PLATFORM_INFO_OFFSET, + &plat_info, + MORELLO_SDS_PLATFORM_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting platform info from SDS. ret:%d\n", ret); + panic(); + } + + /* Validate plat_info SDS */ +#ifdef TARGET_PLATFORM_FVP + if (plat_info.local_ddr_size == 0U) { +#else + if ((plat_info.local_ddr_size == 0U) + || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT) + ) { +#endif + ERROR("platform info SDS is corrupted\n"); + panic(); + } + + arm_bl31_platform_setup(); + +#ifdef TARGET_PLATFORM_SOC + dmc_ecc_setup(&plat_info); +#endif +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_def.h b/arm-trusted-firmware/plat/arm/board/morello/morello_def.h new file mode 100644 index 0000000..f154924 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_def.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MORELLO_DEF_H +#define MORELLO_DEF_H + +/* Non-secure SRAM MMU mapping */ +#define MORELLO_NS_SRAM_BASE UL(0x06000000) +#define MORELLO_NS_SRAM_SIZE UL(0x00010000) +#define MORELLO_MAP_NS_SRAM MAP_REGION_FLAT( \ + MORELLO_NS_SRAM_BASE, \ + MORELLO_NS_SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* SDS Platform information defines */ +#define MORELLO_SDS_PLATFORM_INFO_STRUCT_ID U(8) +#define MORELLO_SDS_PLATFORM_INFO_OFFSET U(0) +#ifdef TARGET_PLATFORM_FVP +# define MORELLO_SDS_PLATFORM_INFO_SIZE U(8) +#else +# define MORELLO_SDS_PLATFORM_INFO_SIZE U(22) +#endif +#define MORELLO_MAX_DDR_CAPACITY U(0x1000000000) +#define MORELLO_MAX_REMOTE_CHIP_COUNT U(16) + +#define MORELLO_SCC_SERVER_MODE U(0) +#define MORELLO_SCC_CLIENT_MODE_MASK U(1) +#define MORELLO_SCC_C1_TAG_CACHE_EN_MASK U(4) +#define MORELLO_SCC_C2_TAG_CACHE_EN_MASK U(8) + +/* Base address of non-secure SRAM where Platform information will be filled */ +#define MORELLO_PLATFORM_INFO_BASE UL(0x06000000) + +/* DMC memory status registers */ +#define MORELLO_DMC0_MEMC_STATUS_REG UL(0x4E000000) +#define MORELLO_DMC1_MEMC_STATUS_REG UL(0x4E100000) + +#define MORELLO_DMC_MEMC_STATUS_MASK U(7) + +/* DMC memory command registers */ +#define MORELLO_DMC0_MEMC_CMD_REG UL(0x4E000008) +#define MORELLO_DMC1_MEMC_CMD_REG UL(0x4E100008) + +/* DMC capability control register */ +#define MORELLO_DMC0_CAP_CTRL_REG UL(0x4E000D00) +#define MORELLO_DMC1_CAP_CTRL_REG UL(0x4E100D00) + +/* DMC tag cache control register */ +#define MORELLO_DMC0_TAG_CACHE_CTL UL(0x4E000D04) +#define MORELLO_DMC1_TAG_CACHE_CTL UL(0x4E100D04) + +/* DMC tag cache config register */ +#define MORELLO_DMC0_TAG_CACHE_CFG UL(0x4E000D08) +#define MORELLO_DMC1_TAG_CACHE_CFG UL(0x4E100D08) + +/* DMC memory access control register */ +#define MORELLO_DMC0_MEM_ACCESS_CTL UL(0x4E000D0C) +#define MORELLO_DMC1_MEM_ACCESS_CTL UL(0x4E100D0C) + +#define MORELLO_DMC_MEM_ACCESS_DIS (1UL << 16) + +/* DMC memory address control register */ +#define MORELLO_DMC0_MEM_ADDR_CTL UL(0x4E000D10) +#define MORELLO_DMC1_MEM_ADDR_CTL UL(0x4E100D10) + +/* DMC memory address control 2 register */ +#define MORELLO_DMC0_MEM_ADDR_CTL2 UL(0x4E000D14) +#define MORELLO_DMC1_MEM_ADDR_CTL2 UL(0x4E100D14) + +/* DMC special control register */ +#define MORELLO_DMC0_SPL_CTL_REG UL(0x4E000D18) +#define MORELLO_DMC1_SPL_CTL_REG UL(0x4E100D18) + +/* DMC ERR0CTLR0 registers */ +#define MORELLO_DMC0_ERR0CTLR0_REG UL(0x4E000708) +#define MORELLO_DMC1_ERR0CTLR0_REG UL(0x4E100708) + +/* DMC ECC in ERR0CTLR0 register */ +#define MORELLO_DMC_ERR0CTLR0_ECC_EN U(9) + +/* DMC ERR2STATUS register */ +#define MORELLO_DMC0_ERR2STATUS_REG UL(0x4E000790) +#define MORELLO_DMC1_ERR2STATUS_REG UL(0x4E100790) + +/* DMC memory commands */ +#define MORELLO_DMC_MEMC_CMD_CONFIG U(0) +#define MORELLO_DMC_MEMC_CMD_READY U(3) + +#endif /* MORELLO_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_err.c b/arm-trusted-firmware/plat/arm/board/morello/morello_err.c new file mode 100644 index 0000000..4d20a09 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * morello error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c b/arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c new file mode 100644 index 0000000..52d46f3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include "morello_def.h" +#include +#include + +#ifdef TARGET_PLATFORM_FVP +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which is an information about multichip setup + * - Local DDR size in bytes, DDR memory in main board + */ +struct morello_plat_info { + uint64_t local_ddr_size; +} __packed; +#else +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which is an information about multichip setup + * - Local DDR size in bytes, DDR memory in main board + * - Remote DDR size in bytes, DDR memory in remote board + * - remote_chip_count + * - multichip mode + * - scc configuration + */ +struct morello_plat_info { + uint64_t local_ddr_size; + uint64_t remote_ddr_size; + uint8_t remote_chip_count; + bool multichip_mode; + uint32_t scc_config; +} __packed; +#endif + +/* In client mode, a part of the DDR memory is reserved for Tag bits. + * Calculate the usable memory size after subtracting the Tag memory. + */ +static inline uint64_t get_mem_client_mode(uint64_t size) +{ + return (size - (size / 128ULL)); +} + +/******************************************************************************* + * This function inserts Platform information via device tree nodes as, + * platform-info { + * local-ddr-size = <0x0 0x0>; + *#ifdef TARGET_PLATFORM_SOC + * remote-ddr-size = <0x0 0x0>; + * remote-chip-count = <0x0>; + * multichip-mode = <0x0>; + * scc-config = <0x0>; + *#endif + * }; + ******************************************************************************/ +static int plat_morello_append_config_node(struct morello_plat_info *plat_info) +{ + bl_mem_params_node_t *mem_params; + void *fdt; + int nodeoffset, err; + uint64_t usable_mem_size; + + usable_mem_size = plat_info->local_ddr_size; + + mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); + if (mem_params == NULL) { + ERROR("NT_FW CONFIG base address is NULL\n"); + return -1; + } + + fdt = (void *)(mem_params->image_info.image_base); + + /* Check the validity of the fdt */ + if (fdt_check_header(fdt) != 0) { + ERROR("Invalid NT_FW_CONFIG DTB passed\n"); + return -1; + } + + nodeoffset = fdt_subnode_offset(fdt, 0, "platform-info"); + if (nodeoffset < 0) { + ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n"); + return -1; + } + +#ifdef TARGET_PLATFORM_SOC + err = fdt_setprop_u64(fdt, nodeoffset, "remote-ddr-size", + plat_info->remote_ddr_size); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "remote-chip-count", + plat_info->remote_chip_count); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set remote-chip-count\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "multichip-mode", + plat_info->multichip_mode); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "scc-config", + plat_info->scc_config); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set scc-config\n"); + return -1; + } + + if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) { + usable_mem_size = get_mem_client_mode(plat_info->local_ddr_size); + } +#endif + err = fdt_setprop_u64(fdt, nodeoffset, "local-ddr-size", + usable_mem_size); + if (err < 0) { + ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n"); + return -1; + } + + flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size); + + return 0; +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + int ret; + struct morello_plat_info plat_info; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SDS initialization failed. ret:%d\n", ret); + panic(); + } + + ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID, + MORELLO_SDS_PLATFORM_INFO_OFFSET, + &plat_info, + MORELLO_SDS_PLATFORM_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting platform info from SDS. ret:%d\n", ret); + panic(); + } + + /* Validate plat_info SDS */ +#ifdef TARGET_PLATFORM_FVP + if (plat_info.local_ddr_size == 0U) { +#else + if ((plat_info.local_ddr_size == 0U) + || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT) + ){ +#endif + ERROR("platform info SDS is corrupted\n"); + panic(); + } + + ret = plat_morello_append_config_node(&plat_info); + if (ret != 0) { + panic(); + } + + return arm_get_next_bl_params(); +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c b/arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c new file mode 100644 index 0000000..d941bfe --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/* + * For MORELLO which supports FCM (with automatic interconnect enter/exit), + * we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_plat.c b/arm-trusted-firmware/plat/arm/board/morello/morello_plat.c new file mode 100644 index 0000000..42e5171 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_plat.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "morello_def.h" + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ +#if IMAGE_BL1 || IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MORELLO_MAP_DEVICE, + MORELLO_MAP_NS_SRAM, + ARM_MAP_DRAM1, + ARM_MAP_DRAM2, + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MORELLO_MAP_DEVICE, + MORELLO_MAP_NS_SRAM, + ARM_MAP_DRAM1, +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_security.c b/arm-trusted-firmware/plat/arm/board/morello/morello_security.c new file mode 100644 index 0000000..a388a80 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_security.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * TZC programming is currently not done. + */ +void plat_arm_security_setup(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_topology.c b/arm-trusted-firmware/plat/arm/board/morello/morello_topology.c new file mode 100644 index 0000000..ef2f753 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_topology.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* Compile time assertion to ensure the core count is 4 */ +CASSERT(PLATFORM_CORE_COUNT == 4U, assert_invalid_platform_core_count); + +/* Topology */ +typedef struct morello_topology { + const unsigned char *power_tree; + unsigned int plat_cluster_core_count; +} morello_topology_t; + +/* + * The power domain tree descriptor. The cluster power domains are + * arranged so that when the PSCI generic code creates the power domain tree, + * the indices of the CPU power domain nodes it allocates match the linear + * indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char morello_pd_tree_desc[] = { + PLAT_MORELLO_CHIP_COUNT, + PLAT_ARM_CLUSTER_COUNT, + MORELLO_MAX_CPUS_PER_CLUSTER, + MORELLO_MAX_CPUS_PER_CLUSTER, +}; + +/* Topology configuration for morello */ +const morello_topology_t morello_topology = { + .power_tree = morello_pd_tree_desc, + .plat_cluster_core_count = MORELLO_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return morello_topology.power_tree; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return morello_topology.plat_cluster_core_count; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 0, 1, 2, 3}; diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c new file mode 100644 index 0000000..f9bc009 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * will contain the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = MORELLO_FW_NVCTR_VAL; + + return 0; +} + +/* + * Store a new non-volatile counter value. By default on ARM development + * platforms, the non-volatile counters are RO and cannot be modified. We expect + * the values in the certificates to always match the RO values so that this + * function is never called. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/platform.mk b/arm-trusted-firmware/plat/arm/board/morello/platform.mk new file mode 100644 index 0000000..86047e3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/platform.mk @@ -0,0 +1,108 @@ +# +# Copyright (c) 2020-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Making sure the Morello platform type is specified +ifeq ($(filter ${TARGET_PLATFORM}, fvp soc),) + $(error TARGET_PLATFORM must be fvp or soc) +endif + +MORELLO_BASE := plat/arm/board/morello + +INTERCONNECT_SOURCES := ${MORELLO_BASE}/morello_interconnect.c + +PLAT_INCLUDES := -I${MORELLO_BASE}/include + +MORELLO_CPU_SOURCES := lib/cpus/aarch64/rainier.S + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +MORELLO_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c \ + +PLAT_BL_COMMON_SOURCES := ${MORELLO_BASE}/morello_plat.c \ + ${MORELLO_BASE}/aarch64/morello_helper.S + +BL1_SOURCES := ${MORELLO_CPU_SOURCES} \ + ${INTERCONNECT_SOURCES} \ + ${MORELLO_BASE}/morello_err.c \ + ${MORELLO_BASE}/morello_trusted_boot.c \ + ${MORELLO_BASE}/morello_bl1_setup.c \ + drivers/arm/sbsa/sbsa.c + +BL2_SOURCES := ${MORELLO_BASE}/morello_security.c \ + ${MORELLO_BASE}/morello_err.c \ + ${MORELLO_BASE}/morello_trusted_boot.c \ + ${MORELLO_BASE}/morello_bl2_setup.c \ + ${MORELLO_BASE}/morello_image_load.c \ + lib/utils/mem_region.c \ + drivers/arm/css/sds/sds.c + +BL31_SOURCES := ${MORELLO_CPU_SOURCES} \ + ${INTERCONNECT_SOURCES} \ + ${MORELLO_GIC_SOURCES} \ + ${MORELLO_BASE}/morello_bl31_setup.c \ + ${MORELLO_BASE}/morello_topology.c \ + ${MORELLO_BASE}/morello_security.c \ + drivers/arm/css/sds/sds.c + +FDT_SOURCES += fdts/morello-${TARGET_PLATFORM}.dts \ + ${MORELLO_BASE}/fdts/morello_fw_config.dts \ + ${MORELLO_BASE}/fdts/morello_tb_fw_config.dts \ + ${MORELLO_BASE}/fdts/morello_nt_fw_config.dts + +FW_CONFIG := ${BUILD_PLAT}/fdts/morello_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/morello_tb_fw_config.dtb +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/morello_nt_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +MORELLO_FW_NVCTR_VAL := 0 +TFW_NVCTR_VAL := ${MORELLO_FW_NVCTR_VAL} +NTFW_NVCTR_VAL := ${MORELLO_FW_NVCTR_VAL} + +# TF-A not required to load the SCP Images +override CSS_LOAD_SCP_IMAGES := 0 + +override NEED_BL2U := no + +# 32 bit mode not supported +override CTX_INCLUDE_AARCH32_REGS := 0 + +override ARM_PLAT_MT := 1 + +# Errata workarounds: +ERRATA_N1_1868343 := 1 + +# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the +# SCP during power management operations and for SCP RAM Firmware transfer. +CSS_USE_SCMI_SDS_DRIVER := 1 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# 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. +USE_COHERENT_MEM := 0 + +# Add TARGET_PLATFORM to differentiate between Morello FVP and Morello SoC platform +$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM}))) + +# Add MORELLO_FW_NVCTR_VAL +$(eval $(call add_define,MORELLO_FW_NVCTR_VAL)) + +include plat/arm/common/arm_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/board/common/board_common.mk diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S b/arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S new file mode 100644 index 0000000..3da55b6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Helper function to calculate the core position. + * ((ChipId * N1SDP_MAX_CLUSTERS_PER_CHIP + ClusterId) * + * N1SDP_MAX_CPUS_PER_CLUSTER * N1SDP_MAX_PE_PER_CPU) + + * (CPUId * N1SDP_MAX_PE_PER_CPU) + ThreadId + * + * which can be simplified as: + * + * (((ChipId * N1SDP_MAX_CLUSTERS_PER_CHIP + ClusterId) * + * N1SDP_MAX_CPUS_PER_CLUSTER + CPUId) * N1SDP_MAX_PE_PER_CPU) + + * ThreadId + * ------------------------------------------------------ + */ + +func plat_arm_calc_core_pos + mov x4, x0 + + /* + * The MT bit in MPIDR is always set for n1sdp and the + * affinity level 0 corresponds to thread affinity level. + */ + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #N1SDP_MAX_CLUSTERS_PER_CHIP + madd x2, x3, x4, x2 + mov x4, #N1SDP_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x4, #N1SDP_MAX_PE_PER_CPU + madd x0, x1, x4, x0 + ret +endfunc plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the CPU MIDR and disable power down bit for + * that CPU. + * ----------------------------------------------------- + */ + +func plat_reset_handler + jump_if_cpu_midr NEOVERSE_N1_MIDR, N1 + ret + + /* ----------------------------------------------------- + * Disable CPU power down bit in power control register + * ----------------------------------------------------- + */ +N1: + mrs x0, NEOVERSE_N1_CPUPWRCTLR_EL1 + bic x0, x0, #NEOVERSE_N1_CORE_PWRDN_EN_MASK + msr NEOVERSE_N1_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S new file mode 100644 index 0000000..521bcc3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * + * There are currently no platform specific regs + * to print. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h new file mode 100644 index 0000000..cc07852 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE 0x2A400000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ 50000000 + +#define PLAT_ARM_RUN_UART_BASE 0x2A410000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ 50000000 + +#define PLAT_ARM_SP_MIN_RUN_UART_BASE 0x2A410000 +#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ 50000000 + +#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_DRAM2_BASE ULL(0x8080000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0xF80000000) + +/* N1SDP remote chip at 4 TB offset */ +#define PLAT_ARM_REMOTE_CHIP_OFFSET (ULL(1) << 42) + +#define N1SDP_REMOTE_DRAM1_BASE ARM_DRAM1_BASE + \ + PLAT_ARM_REMOTE_CHIP_OFFSET +#define N1SDP_REMOTE_DRAM1_SIZE ARM_DRAM1_SIZE + +#define N1SDP_REMOTE_DRAM2_BASE PLAT_ARM_DRAM2_BASE + \ + PLAT_ARM_REMOTE_CHIP_OFFSET +#define N1SDP_REMOTE_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE + +/* + * N1SDP platform supports RDIMMs with ECC capability. To use the ECC + * capability, the entire DDR memory space has to be zeroed out before + * enabling the ECC bits in DMC620. To access the complete DDR memory + * along with remote chip's DDR memory, which is at 4 TB offset, physical + * and virtual address space limits are extended to 43-bits. + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 43) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 43) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +#if CSS_USE_SCMI_SDS_DRIVER +#define N1SDP_SCMI_PAYLOAD_BASE 0x45400000 +#else +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE 0x45400000 +#endif + +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */ +#define PLAT_ARM_MAX_BL31_SIZE 0X20000 + +/******************************************************************************* + * N1SDP topology related constants + ******************************************************************************/ +#define N1SDP_MAX_CPUS_PER_CLUSTER U(2) +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define PLAT_N1SDP_CHIP_COUNT U(2) +#define N1SDP_MAX_CLUSTERS_PER_CHIP U(2) +#define N1SDP_MAX_PE_PER_CPU U(1) + +#define PLATFORM_CORE_COUNT (PLAT_N1SDP_CHIP_COUNT * \ + PLAT_ARM_CLUSTER_COUNT * \ + N1SDP_MAX_CPUS_PER_CLUSTER * \ + N1SDP_MAX_PE_PER_CPU) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3 + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#define PLAT_ARM_MMAP_ENTRIES 9 +#define MAX_XLAT_TABLES 10 + +#define PLATFORM_STACK_SIZE 0x400 + +#define PLAT_ARM_NSTIMER_FRAME_ID 0 +#define PLAT_CSS_MHU_BASE 0x45000000 +#define PLAT_MAX_PWR_LVL 2 + +#define PLAT_ARM_G1S_IRQS ARM_G1S_IRQS, \ + CSS_IRQ_MHU +#define PLAT_ARM_G0_IRQS ARM_G0_IRQS + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp) +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + + +#define N1SDP_DEVICE_BASE ULL(0x08000000) +#define N1SDP_DEVICE_SIZE ULL(0x48000000) +#define N1SDP_REMOTE_DEVICE_BASE N1SDP_DEVICE_BASE + \ + PLAT_ARM_REMOTE_CHIP_OFFSET +#define N1SDP_REMOTE_DEVICE_SIZE N1SDP_DEVICE_SIZE + +#define N1SDP_MAP_DEVICE MAP_REGION_FLAT( \ + N1SDP_DEVICE_BASE, \ + N1SDP_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_DRAM1 MAP_REGION_FLAT( \ + ARM_DRAM1_BASE, \ + ARM_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define N1SDP_MAP_REMOTE_DEVICE MAP_REGION_FLAT( \ + N1SDP_REMOTE_DEVICE_BASE, \ + N1SDP_REMOTE_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define N1SDP_MAP_REMOTE_DRAM1 MAP_REGION_FLAT( \ + N1SDP_REMOTE_DRAM1_BASE, \ + N1SDP_REMOTE_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define N1SDP_MAP_REMOTE_DRAM2 MAP_REGION_FLAT( \ + N1SDP_REMOTE_DRAM2_BASE, \ + N1SDP_REMOTE_DRAM2_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x30000000 +#define PLAT_ARM_GICC_BASE 0x2C000000 +#define PLAT_ARM_GICR_BASE 0x300C0000 + +/* Platform ID address */ +#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET) + +/* Secure Watchdog Constants */ +#define SBSA_SECURE_WDOG_BASE UL(0x2A480000) +#define SBSA_SECURE_WDOG_TIMEOUT UL(100) + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c new file mode 100644 index 0000000..d7003e9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c @@ -0,0 +1,241 @@ +/* + * 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 + +#include "n1sdp_def.h" + +/* + * Platform information structure stored in SDS. + * This structure holds information about platform's DDR + * size which will be used to zero out the memory before + * enabling the ECC capability as well as information + * about multichip setup + * - multichip mode + * - slave_count + * - Local DDR size in GB, DDR memory in master board + * - Remote DDR size in GB, DDR memory in slave board + */ +struct n1sdp_plat_info { + bool multichip_mode; + uint8_t slave_count; + uint8_t local_ddr_size; + uint8_t remote_ddr_size; +} __packed; + +/* + * BL33 image information structure stored in SDS. + * This structure holds the source & destination addresses and + * the size of the BL33 image which will be loaded by BL31. + */ +struct n1sdp_bl33_info { + uint32_t bl33_src_addr; + uint32_t bl33_dst_addr; + uint32_t bl33_size; +}; + +static scmi_channel_plat_info_t n1sdp_scmi_plat_info = { + .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell +}; + +static struct gic600_multichip_data n1sdp_multichip_data __init = { + .rt_owner_base = PLAT_ARM_GICD_BASE, + .rt_owner = 0, + .chip_count = 1, + .chip_addrs = { + PLAT_ARM_GICD_BASE >> 16, + PLAT_ARM_GICD_BASE >> 16 + }, + .spi_ids = { + {32, 479}, + {512, 959} + } +}; + +static uintptr_t n1sdp_multichip_gicr_frames[3] = { + PLAT_ARM_GICR_BASE, + PLAT_ARM_GICR_BASE + PLAT_ARM_REMOTE_CHIP_OFFSET, + 0 +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + return &n1sdp_scmi_plat_info; +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return css_scmi_override_pm_ops(ops); +} + +/* + * N1SDP platform supports RDIMMs with ECC capability. To use the ECC + * capability, the entire DDR memory space has to be zeroed out before + * enabling the ECC bits in DMC620. Zeroing out several gigabytes of + * memory from SCP is quite time consuming so the following function + * is added to zero out the DDR memory from application processor which is + * much faster compared to SCP. BL33 binary cannot be copied to DDR memory + * before enabling ECC so copy_bl33 function is added to copy BL33 binary + * from IOFPGA-DDR3 memory to main DDR4 memory. + */ + +void dmc_ecc_setup(uint8_t ddr_size_gb) +{ + uint64_t dram2_size; + + dram2_size = (ddr_size_gb * 1024UL * 1024UL * 1024UL) - + ARM_DRAM1_SIZE; + + INFO("Zeroing DDR memories\n"); + zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE); + flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE); + zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size); + flush_dcache_range(ARM_DRAM2_BASE, dram2_size); + + INFO("Enabling ECC on DMCs\n"); + /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ + mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG); + mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG); + + /* Enable ECC in DMCs */ + mmio_setbits_32(N1SDP_DMC0_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN); + mmio_setbits_32(N1SDP_DMC1_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN); + + /* Set DMCs to READY state */ + mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); + mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); +} + +void remote_dmc_ecc_setup(uint8_t remote_ddr_size) +{ + uint64_t remote_dram2_size; + + remote_dram2_size = (remote_ddr_size * 1024UL * 1024UL * 1024UL) - + N1SDP_REMOTE_DRAM1_SIZE; + /* multichip setup */ + INFO("Zeroing remote DDR memories\n"); + zero_normalmem((void *)N1SDP_REMOTE_DRAM1_BASE, + N1SDP_REMOTE_DRAM1_SIZE); + flush_dcache_range(N1SDP_REMOTE_DRAM1_BASE, N1SDP_REMOTE_DRAM1_SIZE); + zero_normalmem((void *)N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size); + flush_dcache_range(N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size); + + INFO("Enabling ECC on remote DMCs\n"); + /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ + mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, + N1SDP_DMC_MEMC_CMD_CONFIG); + mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, + N1SDP_DMC_MEMC_CMD_CONFIG); + + /* Enable ECC in DMCs */ + mmio_setbits_32(N1SDP_REMOTE_DMC0_ERR0CTLR0_REG, + N1SDP_DMC_ERR0CTLR0_ECC_EN); + mmio_setbits_32(N1SDP_REMOTE_DMC1_ERR0CTLR0_REG, + N1SDP_DMC_ERR0CTLR0_ECC_EN); + + /* Set DMCs to READY state */ + mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); + mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); +} + +void copy_bl33(uint32_t src, uint32_t dst, uint32_t size) +{ + uint32_t i; + + INFO("Copying BL33 to DDR memory\n"); + for (i = 0; i < size; i = i + 8) + mmio_write_64((dst + i), mmio_read_64(src + i)); + + for (i = 0; i < size; i = i + 8) { + if (mmio_read_64(src + i) != mmio_read_64(dst + i)) { + ERROR("Copy failed!\n"); + panic(); + } + } +} + +void n1sdp_bl31_multichip_setup(void) +{ + plat_arm_override_gicr_frames(n1sdp_multichip_gicr_frames); + gic600_multichip_init(&n1sdp_multichip_data); +} + +void bl31_platform_setup(void) +{ + int ret; + struct n1sdp_plat_info plat_info; + struct n1sdp_bl33_info bl33_info; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SDS initialization failed\n"); + panic(); + } + + ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID, + N1SDP_SDS_PLATFORM_INFO_OFFSET, + &plat_info, + N1SDP_SDS_PLATFORM_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting platform info from SDS\n"); + panic(); + } + /* Validate plat_info SDS */ + if ((plat_info.local_ddr_size == 0) + || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) + || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) + || (plat_info.slave_count > N1SDP_MAX_SLAVE_COUNT)) { + ERROR("platform info SDS is corrupted\n"); + panic(); + } + + if (plat_info.multichip_mode) { + n1sdp_multichip_data.chip_count = plat_info.slave_count + 1; + n1sdp_bl31_multichip_setup(); + } + arm_bl31_platform_setup(); + + dmc_ecc_setup(plat_info.local_ddr_size); + + /* Check if remote memory is present */ + if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0)) + remote_dmc_ecc_setup(plat_info.remote_ddr_size); + + ret = sds_struct_read(N1SDP_SDS_BL33_INFO_STRUCT_ID, + N1SDP_SDS_BL33_INFO_OFFSET, + &bl33_info, + N1SDP_SDS_BL33_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting BL33 info from SDS\n"); + panic(); + } + copy_bl33(bl33_info.bl33_src_addr, + bl33_info.bl33_dst_addr, + bl33_info.bl33_size); + /* + * Pass platform information to BL33. This method is followed as + * currently there is no BL1/BL2 involved in boot flow of N1SDP. + * When TBBR is implemented for N1SDP, this method should be removed + * and platform information should be passed to BL33 using NT_FW_CONFIG + * passing mechanism. + */ + mmio_write_32(N1SDP_PLATFORM_INFO_BASE, *(uint32_t *)&plat_info); +} diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h new file mode 100644 index 0000000..30e29a7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef N1SDP_DEF_H +#define N1SDP_DEF_H + +/* Non-secure SRAM MMU mapping */ +#define N1SDP_NS_SRAM_BASE (0x06000000) +#define N1SDP_NS_SRAM_SIZE (0x00010000) +#define N1SDP_MAP_NS_SRAM MAP_REGION_FLAT( \ + N1SDP_NS_SRAM_BASE, \ + N1SDP_NS_SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* SDS Platform information defines */ +#define N1SDP_SDS_PLATFORM_INFO_STRUCT_ID 8 +#define N1SDP_SDS_PLATFORM_INFO_OFFSET 0 +#define N1SDP_SDS_PLATFORM_INFO_SIZE 4 +#define N1SDP_MAX_DDR_CAPACITY_GB 64 +#define N1SDP_MAX_SLAVE_COUNT 16 + +/* SDS BL33 image information defines */ +#define N1SDP_SDS_BL33_INFO_STRUCT_ID 9 +#define N1SDP_SDS_BL33_INFO_OFFSET 0 +#define N1SDP_SDS_BL33_INFO_SIZE 12 + +/* DMC memory command registers */ +#define N1SDP_DMC0_MEMC_CMD_REG 0x4E000008 +#define N1SDP_DMC1_MEMC_CMD_REG 0x4E100008 + +/* DMC ERR0CTLR0 registers */ +#define N1SDP_DMC0_ERR0CTLR0_REG 0x4E000708 +#define N1SDP_DMC1_ERR0CTLR0_REG 0x4E100708 + +/* Remote DMC memory command registers */ +#define N1SDP_REMOTE_DMC0_MEMC_CMD_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\ + N1SDP_DMC0_MEMC_CMD_REG +#define N1SDP_REMOTE_DMC1_MEMC_CMD_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\ + N1SDP_DMC1_MEMC_CMD_REG + +/* Remote DMC ERR0CTLR0 registers */ +#define N1SDP_REMOTE_DMC0_ERR0CTLR0_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\ + N1SDP_DMC0_ERR0CTLR0_REG +#define N1SDP_REMOTE_DMC1_ERR0CTLR0_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\ + N1SDP_DMC1_ERR0CTLR0_REG + +/* DMC memory commands */ +#define N1SDP_DMC_MEMC_CMD_CONFIG 0 +#define N1SDP_DMC_MEMC_CMD_READY 3 + +/* DMC ECC enable bit in ERR0CTLR0 register */ +#define N1SDP_DMC_ERR0CTLR0_ECC_EN 0x1 + +/* Base address of non-secure SRAM where Platform information will be filled */ +#define N1SDP_PLATFORM_INFO_BASE 0x06008000 + +#endif /* N1SDP_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c new file mode 100644 index 0000000..908f41c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/* + * For N1SDP which support FCM (with automatic interconnect enter/exit), + * we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c new file mode 100644 index 0000000..951a562 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "n1sdp_def.h" + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ + +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + N1SDP_MAP_DEVICE, + N1SDP_MAP_NS_SRAM, + ARM_MAP_DRAM1, + ARM_MAP_DRAM2, + N1SDP_MAP_REMOTE_DEVICE, + N1SDP_MAP_REMOTE_DRAM1, + N1SDP_MAP_REMOTE_DRAM2, + {0} +}; + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c new file mode 100644 index 0000000..d2a187b --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * TZC programming is currently not done. + */ +void plat_arm_security_setup(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c new file mode 100644 index 0000000..5c2db71 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* Topology */ +typedef struct n1sdp_topology { + const unsigned char *power_tree; + unsigned int plat_cluster_core_count; +} n1sdp_topology_t; + +/* + * The power domain tree descriptor. The cluster power domains are + * arranged so that when the PSCI generic code creates the power domain tree, + * the indices of the CPU power domain nodes it allocates match the linear + * indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char n1sdp_pd_tree_desc[] = { + PLAT_N1SDP_CHIP_COUNT, + PLAT_ARM_CLUSTER_COUNT, + PLAT_ARM_CLUSTER_COUNT, + N1SDP_MAX_CPUS_PER_CLUSTER, + N1SDP_MAX_CPUS_PER_CLUSTER, + N1SDP_MAX_CPUS_PER_CLUSTER, + N1SDP_MAX_CPUS_PER_CLUSTER +}; + +/* Topology configuration for n1sdp */ +const n1sdp_topology_t n1sdp_topology = { + .power_tree = n1sdp_pd_tree_desc, + .plat_cluster_core_count = N1SDP_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return n1sdp_topology.power_tree; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return n1sdp_topology.plat_cluster_core_count; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 0, 1, 2, 3, 4, 5, 6, 7}; diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/platform.mk b/arm-trusted-firmware/plat/arm/board/n1sdp/platform.mk new file mode 100644 index 0000000..f20397a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/platform.mk @@ -0,0 +1,76 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + + +N1SDP_BASE := plat/arm/board/n1sdp + +INTERCONNECT_SOURCES := ${N1SDP_BASE}/n1sdp_interconnect.c + +PLAT_INCLUDES := -I${N1SDP_BASE}/include + + +N1SDP_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 +GICV3_IMPL_GIC600_MULTICHIP := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +N1SDP_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c \ + +PLAT_BL_COMMON_SOURCES := ${N1SDP_BASE}/n1sdp_plat.c \ + ${N1SDP_BASE}/aarch64/n1sdp_helper.S + +BL1_SOURCES += drivers/arm/sbsa/sbsa.c + +BL31_SOURCES := ${N1SDP_CPU_SOURCES} \ + ${INTERCONNECT_SOURCES} \ + ${N1SDP_GIC_SOURCES} \ + ${N1SDP_BASE}/n1sdp_bl31_setup.c \ + ${N1SDP_BASE}/n1sdp_topology.c \ + ${N1SDP_BASE}/n1sdp_security.c \ + drivers/arm/css/sds/sds.c + +FDT_SOURCES += fdts/${PLAT}-single-chip.dts \ + fdts/${PLAT}-multi-chip.dts + +# TF-A not required to load the SCP Images +override CSS_LOAD_SCP_IMAGES := 0 + +# BL1/BL2 Image not a part of the capsule Image for n1sdp +override NEED_BL1 := no +override NEED_BL2 := no +override NEED_BL2U := no + +#TFA for n1sdp starts from BL31 +override RESET_TO_BL31 := 1 + +# 32 bit mode not supported +override CTX_INCLUDE_AARCH32_REGS := 0 + +override ARM_PLAT_MT := 1 + +# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the +# SCP during power management operations and for SCP RAM Firmware transfer. +CSS_USE_SCMI_SDS_DRIVER := 1 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# 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. +USE_COHERENT_MEM := 0 + +# Enable the flag since N1SDP has a system level cache +NEOVERSE_Nx_EXTERNAL_LLC := 1 +include plat/arm/common/arm_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/board/common/board_common.mk + diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts new file mode 100644 index 0000000..69fb0d4 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts new file mode 100644 index 0000000..0af821e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-e1edge"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; + +}; diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts new file mode 100644 index 0000000..dba91e5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h new file mode 100644 index 0000000..a9b30a4 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#include +#include + +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(8) +#define CSS_SGI_MAX_PE_PER_CPU U(2) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) + +/* Base address of DMC-620 instances */ +#define RDE1EDGE_DMC620_BASE0 UL(0x4e000000) +#define RDE1EDGE_DMC620_BASE1 UL(0x4e100000) + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3 + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x300C0000) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/platform.mk b/arm-trusted-firmware/plat/arm/board/rde1edge/platform.mk new file mode 100644 index 0000000..0f9dd49 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/platform.mk @@ -0,0 +1,66 @@ +# +# Copyright (c) 2018-2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/arm/css/sgi/sgi-common.mk + +RDE1EDGE_BASE = plat/arm/board/rde1edge + +PLAT_INCLUDES += -I${RDE1EDGE_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_e1.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDE1EDGE_BASE}/rde1edge_err.c + +BL2_SOURCES += ${RDE1EDGE_BASE}/rde1edge_plat.c \ + ${RDE1EDGE_BASE}/rde1edge_security.c \ + ${RDE1EDGE_BASE}/rde1edge_err.c \ + drivers/arm/tzc/tzc_dmc620.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDE1EDGE_BASE}/rde1edge_plat.c \ + ${RDE1EDGE_BASE}/rde1edge_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDE1EDGE_BASE}/rde1edge_trusted_boot.c +BL2_SOURCES += ${RDE1EDGE_BASE}/rde1edge_trusted_boot.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDE1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDE1EDGE_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +ifneq ($(CSS_SGI_CHIP_COUNT),1) + $(error "Chip count for RDE1Edge should be 1, currently set to \ + ${CSS_SGI_CHIP_COUNT}.") +endif + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-E1-Edge should always be 0, \ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif + +override CTX_INCLUDE_AARCH32_REGS := 0 diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c new file mode 100644 index 0000000..c72c18c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * rde1edge error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c new file mode 100644 index 0000000..44d818a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return 0; +} + +void bl31_platform_setup(void) +{ + sgi_bl31_common_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c new file mode 100644 index 0000000..35f81d1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +uintptr_t rde1edge_dmc_base[] = { + RDE1EDGE_DMC620_BASE0, + RDE1EDGE_DMC620_BASE1 +}; + +static const tzc_dmc620_driver_data_t rde1edge_plat_driver_data = { + .dmc_base = rde1edge_dmc_base, + .dmc_count = ARRAY_SIZE(rde1edge_dmc_base) +}; + +static const tzc_dmc620_acc_addr_data_t rde1edge_acc_addr_data[] = { + CSS_SGI_DMC620_TZC_REGIONS_DEF +}; + +static const tzc_dmc620_config_data_t rde1edge_plat_config_data = { + .plat_drv_data = &rde1edge_plat_driver_data, + .plat_acc_addr_data = rde1edge_acc_addr_data, + .acc_addr_count = ARRAY_SIZE(rde1edge_acc_addr_data) +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + arm_tzc_dmc620_setup(&rde1edge_plat_config_data); +} diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c new file mode 100644 index 0000000..a16283e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/****************************************************************************** + * The power domain tree descriptor. RD-E1-Edge platform consists of two + * clusters with eight CPUs in each cluster. The CPUs are multi-threaded with + * two threads per CPU. + ******************************************************************************/ +static const unsigned char rde1edge_pd_tree_desc[] = { + CSS_SGI_CHIP_COUNT, + PLAT_ARM_CLUSTER_COUNT, + CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU, + CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU +}; + +/****************************************************************************** + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rde1edge_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +}; diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts new file mode 100644 index 0000000..d3b7fba --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; + diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts new file mode 100644 index 0000000..68366c5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-n1edge"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts new file mode 100644 index 0000000..257ef4a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h new file mode 100644 index 0000000..a61b0d5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#include +#include + +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(4) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) + +/* Base address of DMC-620 instances */ +#define RDN1EDGE_DMC620_BASE0 UL(0x4e000000) +#define RDN1EDGE_DMC620_BASE1 UL(0x4e100000) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* Virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 43) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 43) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x300C0000) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/platform.mk b/arm-trusted-firmware/plat/arm/board/rdn1edge/platform.mk new file mode 100644 index 0000000..22ab312 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/platform.mk @@ -0,0 +1,73 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# GIC-600 configuration +GICV3_IMPL_GIC600_MULTICHIP := 1 + +include plat/arm/css/sgi/sgi-common.mk + +RDN1EDGE_BASE = plat/arm/board/rdn1edge + +PLAT_INCLUDES += -I${RDN1EDGE_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN1EDGE_BASE}/rdn1edge_err.c + +BL2_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_plat.c \ + ${RDN1EDGE_BASE}/rdn1edge_security.c \ + ${RDN1EDGE_BASE}/rdn1edge_err.c \ + drivers/arm/tzc/tzc_dmc620.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN1EDGE_BASE}/rdn1edge_plat.c \ + ${RDN1EDGE_BASE}/rdn1edge_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c +BL2_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c +endif + +# Enable dynamic addition of MMAP regions in BL31 +BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDN1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDN1EDGE_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +$(eval $(call CREATE_SEQ,SEQ,2)) +ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ))) + $(error "Chip count for RDN1Edge platform should be one of $(SEQ), currently \ + set to ${CSS_SGI_CHIP_COUNT}.") +endif + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-N1-Edge should always be 0, \ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif + +override CTX_INCLUDE_AARCH32_REGS := 0 diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c new file mode 100644 index 0000000..46d318c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * rdn1edge error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c new file mode 100644 index 0000000..1dbbf26 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#if defined(IMAGE_BL31) +static const mmap_region_t rdn1edge_dynamic_mmap[] = { + ARM_MAP_SHARED_RAM_REMOTE_CHIP(1), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1), + SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1) +}; + +static struct gic600_multichip_data rdn1e1_multichip_data __init = { + .rt_owner_base = PLAT_ARM_GICD_BASE, + .rt_owner = 0, + .chip_count = CSS_SGI_CHIP_COUNT, + .chip_addrs = { + PLAT_ARM_GICD_BASE >> 16, + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16 + }, + .spi_ids = { + {32, 255}, + {0, 0} + } +}; + +static uintptr_t rdn1e1_multichip_gicr_frames[] = { + PLAT_ARM_GICR_BASE, /* Chip 0's GICR Base */ + PLAT_ARM_GICR_BASE + + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1), /* Chip 1's GICR BASE */ + UL(0) /* Zero Termination */ +}; +#endif /* IMAGE_BL31 */ + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT; +} + +/* + * IMAGE_BL31 macro is added to build bl31_platform_setup function only for BL31 + * because PLAT_XLAT_TABLES_DYNAMIC macro is set to build only for BL31 and not + * for other stages. + */ +#if defined(IMAGE_BL31) +void bl31_platform_setup(void) +{ + int i, ret; + + if (plat_arm_sgi_get_multi_chip_mode() == 0 && CSS_SGI_CHIP_COUNT > 1) { + ERROR("Chip Count is set to %d but multi-chip mode not enabled\n", + CSS_SGI_CHIP_COUNT); + panic(); + } else if (plat_arm_sgi_get_multi_chip_mode() == 1 && + CSS_SGI_CHIP_COUNT > 1) { + INFO("Enabling support for multi-chip in RD-N1-Edge\n"); + + for (i = 0; i < ARRAY_SIZE(rdn1edge_dynamic_mmap); i++) { + ret = mmap_add_dynamic_region( + rdn1edge_dynamic_mmap[i].base_pa, + rdn1edge_dynamic_mmap[i].base_va, + rdn1edge_dynamic_mmap[i].size, + rdn1edge_dynamic_mmap[i].attr + ); + if (ret != 0) { + ERROR("Failed to add dynamic mmap entry\n"); + panic(); + } + } + + plat_arm_override_gicr_frames(rdn1e1_multichip_gicr_frames); + gic600_multichip_init(&rdn1e1_multichip_data); + } + + sgi_bl31_common_platform_setup(); +} +#endif /* IMAGE_BL31 */ diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c new file mode 100644 index 0000000..4943532 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +uintptr_t rdn1edge_dmc_base[] = { + RDN1EDGE_DMC620_BASE0, + RDN1EDGE_DMC620_BASE1 +}; + +static const tzc_dmc620_driver_data_t rdn1edge_plat_driver_data = { + .dmc_base = rdn1edge_dmc_base, + .dmc_count = ARRAY_SIZE(rdn1edge_dmc_base) +}; + +static const tzc_dmc620_acc_addr_data_t rdn1edge_acc_addr_data[] = { + CSS_SGI_DMC620_TZC_REGIONS_DEF +}; + +static const tzc_dmc620_config_data_t rdn1edge_plat_config_data = { + .plat_drv_data = &rdn1edge_plat_driver_data, + .plat_acc_addr_data = rdn1edge_acc_addr_data, + .acc_addr_count = ARRAY_SIZE(rdn1edge_acc_addr_data) +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + arm_tzc_dmc620_setup(&rdn1edge_plat_config_data); +} diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c new file mode 100644 index 0000000..5bbea69 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +static const unsigned char rdn1edge_pd_tree_desc[] = { + (PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT), + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#if (CSS_SGI_CHIP_COUNT > 1) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER +#endif +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rdn1edge_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), +#if (CSS_SGI_CHIP_COUNT > 1) + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x7)), +#endif +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts new file mode 100644 index 0000000..bbc36fc --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-n2"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h new file mode 100644 index 0000000..e4015f7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#include + +#if (CSS_SGI_PLATFORM_VARIANT == 1) +#define PLAT_ARM_CLUSTER_COUNT U(8) +#elif (CSS_SGI_PLATFORM_VARIANT == 2) +#define PLAT_ARM_CLUSTER_COUNT U(4) +#else +#define PLAT_ARM_CLUSTER_COUNT U(16) +#endif + +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x2A920000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x10720000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC400_OFFSET UL(0x1000000) + +#if (CSS_SGI_PLATFORM_VARIANT == 1) +#define TZC400_COUNT U(2) +#elif (CSS_SGI_PLATFORM_VARIANT == 2) +#define TZC400_COUNT U(4) +#else +#define TZC400_COUNT U(8) +#endif + +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) + +#define TZC_NSAID_ALL_AP U(0) +#define TZC_NSAID_PCI U(1) +#define TZC_NSAID_HDLCD0 U(2) +#define TZC_NSAID_DMA U(5) +#define TZC_NSAID_DMA2 U(8) +#define TZC_NSAID_CLCD U(7) +#define TZC_NSAID_AP U(9) +#define TZC_NSAID_VIRTIO U(15) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA2)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO)) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#if (CSS_SGI_PLATFORM_VARIANT == 2) +#define PLAT_PHY_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) +#define PLAT_VIRT_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 42) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 42) +#endif +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) + +/* Virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xC0000000) + +#if (CSS_SGI_PLATFORM_VARIANT == 1) +#define PLAT_ARM_GICR_BASE UL(0x30100000) +#else +#define PLAT_ARM_GICR_BASE UL(0x301C0000) +#endif + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/platform.mk b/arm-trusted-firmware/plat/arm/board/rdn2/platform.mk new file mode 100644 index 0000000..b882dc8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/platform.mk @@ -0,0 +1,86 @@ +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RD_N2_VARIANTS := 0 1 2 +ifneq ($(CSS_SGI_PLATFORM_VARIANT),\ + $(filter $(CSS_SGI_PLATFORM_VARIANT),$(RD_N2_VARIANTS))) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-N2 should be 0, 1 or 2, currently set \ + to ${CSS_SGI_PLATFORM_VARIANT}.") +endif + +$(eval $(call CREATE_SEQ,SEQ,4)) +ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ))) + $(error "Chip count for RD-N2-MC should be either $(SEQ) \ + currently it is set to ${CSS_SGI_CHIP_COUNT}.") +endif + +# RD-N2 platform uses GIC-700 which is based on GICv4.1 +GIC_ENABLE_V4_EXTN := 1 + +#Enable GIC Multichip Extension only for Multichip Platforms +ifeq (${CSS_SGI_PLATFORM_VARIANT}, 2) +GICV3_IMPL_GIC600_MULTICHIP := 1 +endif + +include plat/arm/css/sgi/sgi-common.mk + +RDN2_BASE = plat/arm/board/rdn2 + +PLAT_INCLUDES += -I${RDN2_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n2.S \ + lib/cpus/aarch64/neoverse_demeter.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat_v2.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN2_BASE}/rdn2_err.c + +BL2_SOURCES += ${RDN2_BASE}/rdn2_plat.c \ + ${RDN2_BASE}/rdn2_security.c \ + ${RDN2_BASE}/rdn2_err.c \ + lib/utils/mem_region.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDN2_BASE}/rdn2_plat.c \ + ${RDN2_BASE}/rdn2_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDN2_BASE}/rdn2_trusted_boot.c +BL2_SOURCES += ${RDN2_BASE}/rdn2_trusted_boot.c +endif + +ifeq (${CSS_SGI_PLATFORM_VARIANT}, 2) +BL31_SOURCES += drivers/arm/gic/v3/gic600_multichip.c + +# Enable dynamic addition of MMAP regions in BL31 +BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDN2_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config)) + +override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c new file mode 100644 index 0000000..802ac21 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * rdn2 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c new file mode 100644 index 0000000..8cf1929 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#if defined(IMAGE_BL31) +#if (CSS_SGI_PLATFORM_VARIANT == 2) +static const mmap_region_t rdn2mc_dynamic_mmap[] = { +#if CSS_SGI_CHIP_COUNT > 1 + ARM_MAP_SHARED_RAM_REMOTE_CHIP(1), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1), +#endif +#if CSS_SGI_CHIP_COUNT > 2 + ARM_MAP_SHARED_RAM_REMOTE_CHIP(2), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2), +#endif +#if CSS_SGI_CHIP_COUNT > 3 + ARM_MAP_SHARED_RAM_REMOTE_CHIP(3), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3), +#endif +}; +#endif + +#if (CSS_SGI_PLATFORM_VARIANT == 2) +static struct gic600_multichip_data rdn2mc_multichip_data __init = { + .rt_owner_base = PLAT_ARM_GICD_BASE, + .rt_owner = 0, + .chip_count = CSS_SGI_CHIP_COUNT, + .chip_addrs = { + PLAT_ARM_GICD_BASE >> 16, +#if CSS_SGI_CHIP_COUNT > 1 + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16, +#endif +#if CSS_SGI_CHIP_COUNT > 2 + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2)) >> 16, +#endif +#if CSS_SGI_CHIP_COUNT > 3 + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3)) >> 16, +#endif + }, + .spi_ids = { + {32, 479}, + #if CSS_SGI_CHIP_COUNT > 1 + {0, 0}, + #endif + #if CSS_SGI_CHIP_COUNT > 2 + {0, 0}, + #endif + #if CSS_SGI_CHIP_COUNT > 3 + {0, 0}, + #endif + } +}; +#endif + +#if (CSS_SGI_PLATFORM_VARIANT == 2) +static uintptr_t rdn2mc_multichip_gicr_frames[] = { + /* Chip 0's GICR Base */ + PLAT_ARM_GICR_BASE, +#if CSS_SGI_CHIP_COUNT > 1 + /* Chip 1's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1), +#endif +#if CSS_SGI_CHIP_COUNT > 2 + /* Chip 2's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2), +#endif +#if CSS_SGI_CHIP_COUNT > 3 + /* Chip 3's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3), +#endif + UL(0) /* Zero Termination */ +}; +#endif +#endif /* IMAGE_BL31 */ + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> + SID_MULTI_CHIP_MODE_SHIFT; +} + +#if defined(IMAGE_BL31) +void bl31_platform_setup(void) +{ +#if (CSS_SGI_PLATFORM_VARIANT == 2) + int ret; + unsigned int i; + + if (plat_arm_sgi_get_multi_chip_mode() == 0) { + ERROR("Chip Count is set to %u but multi-chip mode is not " + "enabled\n", CSS_SGI_CHIP_COUNT); + panic(); + } else { + INFO("Enabling multi-chip support for RD-N2 variant\n"); + + for (i = 0; i < ARRAY_SIZE(rdn2mc_dynamic_mmap); i++) { + ret = mmap_add_dynamic_region( + rdn2mc_dynamic_mmap[i].base_pa, + rdn2mc_dynamic_mmap[i].base_va, + rdn2mc_dynamic_mmap[i].size, + rdn2mc_dynamic_mmap[i].attr); + if (ret != 0) { + ERROR("Failed to add dynamic mmap entry for" + " i: %d " "(ret=%d)\n", i, ret); + panic(); + } + } + + plat_arm_override_gicr_frames( + rdn2mc_multichip_gicr_frames); + gic600_multichip_init(&rdn2mc_multichip_data); + } +#endif + + sgi_bl31_common_platform_setup(); +} +#endif /* IMAGE_BL31 */ diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c new file mode 100644 index 0000000..dff6a19 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static const arm_tzc_regions_info_t tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {} +}; + +#if (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1) +static const arm_tzc_regions_info_t tzc_regions_mc[][CSS_SGI_CHIP_COUNT - 1] = { + { + /* TZC memory regions for second chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(1), + {} + }, +#if CSS_SGI_CHIP_COUNT > 2 + { + /* TZC memory regions for third chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(2), + {} + }, +#endif +#if CSS_SGI_CHIP_COUNT > 3 + { + /* TZC memory regions for fourth chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(3), + {} + }, +#endif +}; +#endif /* CSS_SGI_PLATFORM_VARIANT && CSS_SGI_CHIP_COUNT */ + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + unsigned int i; + + INFO("Configuring TrustZone Controller for Chip 0\n"); + + for (i = 0; i < TZC400_COUNT; i++) { + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); + } + +#if (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1) + unsigned int j; + + for (i = 1; i < CSS_SGI_CHIP_COUNT; i++) { + INFO("Configuring TrustZone Controller for Chip %u\n", i); + + for (j = 0; j < TZC400_COUNT; j++) { + arm_tzc400_setup(CSS_SGI_REMOTE_CHIP_MEM_OFFSET(i) + + TZC400_BASE(j), tzc_regions_mc[i-1]); + } + } +#endif +} diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c new file mode 100644 index 0000000..89300f8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char rd_n2_pd_tree_desc[] = { + (PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT), + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#if (CSS_SGI_PLATFORM_VARIANT != 2 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1)) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +#if (CSS_SGI_PLATFORM_VARIANT == 0 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 2)) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +#if (CSS_SGI_PLATFORM_VARIANT == 0 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 3)) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rd_n2_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +#if (CSS_SGI_PLATFORM_VARIANT == 2) +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), +#if (CSS_SGI_CHIP_COUNT > 1) + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +#if (CSS_SGI_CHIP_COUNT > 2) + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +}; +#else +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), +#if (CSS_SGI_PLATFORM_VARIANT == 0) + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF)), +#endif +}; +#endif diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts new file mode 100644 index 0000000..62ba2c3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-v1"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h new file mode 100644 index 0000000..5b98b4e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#include + +#define PLAT_ARM_CLUSTER_COUNT U(16) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x21830000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC400_OFFSET UL(0x1000000) +#define TZC400_COUNT 4 + +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) + +#define TZC_NSAID_ALL_AP U(0) +#define TZC_NSAID_PCI U(1) +#define TZC_NSAID_HDLCD0 U(2) +#define TZC_NSAID_CLCD U(7) +#define TZC_NSAID_AP U(9) +#define TZC_NSAID_VIRTIO U(15) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO)) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 42) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 42) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x30140000) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/platform.mk b/arm-trusted-firmware/plat/arm/board/rdv1/platform.mk new file mode 100644 index 0000000..11f5212 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/platform.mk @@ -0,0 +1,65 @@ +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# RD-V1 platform uses GIC-700 which is based on GICv4.1 +GIC_ENABLE_V4_EXTN := 1 + +include plat/arm/css/sgi/sgi-common.mk + +RDV1_BASE = plat/arm/board/rdv1 + +PLAT_INCLUDES += -I${RDV1_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_v1.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDV1_BASE}/rdv1_err.c + +BL2_SOURCES += ${RDV1_BASE}/rdv1_plat.c \ + ${RDV1_BASE}/rdv1_security.c \ + ${RDV1_BASE}/rdv1_err.c \ + lib/utils/mem_region.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDV1_BASE}/rdv1_plat.c \ + ${RDV1_BASE}/rdv1_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDV1_BASE}/rdv1_trusted_boot.c +BL2_SOURCES += ${RDV1_BASE}/rdv1_trusted_boot.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDV1_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDV1_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${RDV1_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-V1 should always be 0, \ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c new file mode 100644 index 0000000..68f9a3e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * rdv1 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c new file mode 100644 index 0000000..ab5251e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT; +} + +void bl31_platform_setup(void) +{ + sgi_bl31_common_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c new file mode 100644 index 0000000..1247db8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +static const arm_tzc_regions_info_t tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {} +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + int i; + + for (i = 0; i < TZC400_COUNT; i++) + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c new file mode 100644 index 0000000..ab64fd8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char rd_v1_pd_tree_desc[] = { + PLAT_ARM_CLUSTER_COUNT, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rd_v1_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF)) +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts new file mode 100644 index 0000000..71c7db3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,rd-v1-mc"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h new file mode 100644 index 0000000..12ce806 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#define PLAT_ARM_CLUSTER_COUNT U(4) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x21830000) +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) +#define TZC400_OFFSET UL(0x1000000) +#define TZC400_COUNT U(8) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC_NSAID_ALL_AP U(0) +#define TZC_NSAID_PCI U(1) +#define TZC_NSAID_HDLCD0 U(2) +#define TZC_NSAID_CLCD U(7) +#define TZC_NSAID_AP U(9) +#define TZC_NSAID_VIRTIO U(15) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO)) + +/* Virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xC0000000) + +/* Physical and virtual address space limits for MMU in AARCH64 mode */ +#define PLAT_PHY_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) +#define PLAT_VIRT_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \ + CSS_SGI_CHIP_COUNT) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x30140000) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/platform.mk b/arm-trusted-firmware/plat/arm/board/rdv1mc/platform.mk new file mode 100644 index 0000000..df0b09a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/platform.mk @@ -0,0 +1,76 @@ +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Enable GICv4 extension with multichip driver +GIC_ENABLE_V4_EXTN := 1 +GICV3_IMPL_GIC600_MULTICHIP := 1 + +include plat/arm/css/sgi/sgi-common.mk + +RDV1MC_BASE = plat/arm/board/rdv1mc + +PLAT_INCLUDES += -I${RDV1MC_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_v1.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDV1MC_BASE}/rdv1mc_err.c + +BL2_SOURCES += ${RDV1MC_BASE}/rdv1mc_plat.c \ + ${RDV1MC_BASE}/rdv1mc_security.c \ + ${RDV1MC_BASE}/rdv1mc_err.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${RDV1MC_BASE}/rdv1mc_plat.c \ + ${RDV1MC_BASE}/rdv1mc_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/arm/gic/v3/gic600_multichip.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${RDV1MC_BASE}/rdv1mc_trusted_boot.c +BL2_SOURCES += ${RDV1MC_BASE}/rdv1mc_trusted_boot.c +endif + +# Enable dynamic addition of MMAP regions in BL31 +BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${RDV1MC_BASE}/fdts/${PLAT}_fw_config.dts \ + ${RDV1MC_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +$(eval $(call CREATE_SEQ,SEQ,4)) +ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ))) + $(error "Chip count for RD-V1-MC should be either $(SEQ) \ + currently it is set to ${CSS_SGI_CHIP_COUNT}.") +endif + +FDT_SOURCES += ${RDV1MC_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for RD-V1-MC should always be 0, \ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c new file mode 100644 index 0000000..755a503 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * rdv1mc error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c new file mode 100644 index 0000000..d859400 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#if defined(IMAGE_BL31) +static const mmap_region_t rdv1mc_dynamic_mmap[] = { + ARM_MAP_SHARED_RAM_REMOTE_CHIP(1), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1), + SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1), +#if (CSS_SGI_CHIP_COUNT > 2) + ARM_MAP_SHARED_RAM_REMOTE_CHIP(2), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2), + SOC_CSS_MAP_DEVICE_REMOTE_CHIP(2), +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + ARM_MAP_SHARED_RAM_REMOTE_CHIP(3), + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3), + SOC_CSS_MAP_DEVICE_REMOTE_CHIP(3) +#endif +}; + +static struct gic600_multichip_data rdv1mc_multichip_data __init = { + .rt_owner_base = PLAT_ARM_GICD_BASE, + .rt_owner = 0, + .chip_count = CSS_SGI_CHIP_COUNT, + .chip_addrs = { + PLAT_ARM_GICD_BASE >> 16, + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16, +#if (CSS_SGI_CHIP_COUNT > 2) + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2)) >> 16, +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3)) >> 16, +#endif + }, + .spi_ids = { + {32, 255}, + {0, 0}, +#if (CSS_SGI_CHIP_COUNT > 2) + {0, 0}, +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + {0, 0}, +#endif + } +}; + +static uintptr_t rdv1mc_multichip_gicr_frames[] = { + /* Chip 0's GICR Base */ + PLAT_ARM_GICR_BASE, + /* Chip 1's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1), +#if (CSS_SGI_CHIP_COUNT > 2) + /* Chip 2's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2), +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + /* Chip 3's GICR BASE */ + PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3), +#endif + UL(0) /* Zero Termination */ +}; +#endif /* IMAGE_BL31 */ + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) & + SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT; +} + +/* + * bl31_platform_setup_function is guarded by IMAGE_BL31 macro because + * PLAT_XLAT_TABLES_DYNAMIC macro is set to build only for BL31 and not + * for other stages. + */ +#if defined(IMAGE_BL31) +void bl31_platform_setup(void) +{ + int ret; + unsigned int i; + + if ((plat_arm_sgi_get_multi_chip_mode() == 0) && + (CSS_SGI_CHIP_COUNT > 1)) { + ERROR("Chip Count is set to %u but multi-chip mode is not " + "enabled\n", CSS_SGI_CHIP_COUNT); + panic(); + } else if ((plat_arm_sgi_get_multi_chip_mode() == 1) && + (CSS_SGI_CHIP_COUNT > 1)) { + INFO("Enabling support for multi-chip in RD-V1-MC\n"); + + for (i = 0; i < ARRAY_SIZE(rdv1mc_dynamic_mmap); i++) { + ret = mmap_add_dynamic_region( + rdv1mc_dynamic_mmap[i].base_pa, + rdv1mc_dynamic_mmap[i].base_va, + rdv1mc_dynamic_mmap[i].size, + rdv1mc_dynamic_mmap[i].attr); + if (ret != 0) { + ERROR("Failed to add dynamic mmap entry " + "(ret=%d)\n", ret); + panic(); + } + } + + plat_arm_override_gicr_frames( + rdv1mc_multichip_gicr_frames); + gic600_multichip_init(&rdv1mc_multichip_data); + } + + sgi_bl31_common_platform_setup(); +} +#endif /* IMAGE_BL31 */ diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c new file mode 100644 index 0000000..adc0bf8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* TZC memory regions for the first chip */ +static const arm_tzc_regions_info_t tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {} +}; + +#if CSS_SGI_CHIP_COUNT > 1 +static const arm_tzc_regions_info_t tzc_regions_mc[][CSS_SGI_CHIP_COUNT - 1] = { + { + /* TZC memory regions for second chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(1), + {} + }, +#if CSS_SGI_CHIP_COUNT > 2 + { + /* TZC memory regions for third chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(2), + {} + }, +#endif +#if CSS_SGI_CHIP_COUNT > 3 + { + /* TZC memory regions for fourth chip */ + SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(3), + {} + }, +#endif +}; +#endif /* CSS_SGI_CHIP_COUNT */ + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + unsigned int i; + + INFO("Configuring TrustZone Controller for Chip 0\n"); + + for (i = 0; i < TZC400_COUNT; i++) { + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); + } + +#if CSS_SGI_CHIP_COUNT > 1 + unsigned int j; + + for (i = 1; i < CSS_SGI_CHIP_COUNT; i++) { + INFO("Configuring TrustZone Controller for Chip %u\n", i); + + for (j = 0; j < TZC400_COUNT; j++) { + arm_tzc400_setup(CSS_SGI_REMOTE_CHIP_MEM_OFFSET(i) + + TZC400_BASE(j), tzc_regions_mc[i-1]); + } + } +#endif +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c new file mode 100644 index 0000000..4486e5c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char rd_v1_mc_pd_tree_desc_multi_chip[] = { + ((PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT)), + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#if (CSS_SGI_CHIP_COUNT > 1) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +#if (CSS_SGI_CHIP_COUNT > 2) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER +#endif +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + if (plat_arm_sgi_get_multi_chip_mode() == 1) + return rd_v1_mc_pd_tree_desc_multi_chip; + panic(); +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), +#if (CSS_SGI_CHIP_COUNT > 1) + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +#if (CSS_SGI_CHIP_COUNT > 2) + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x3)), +#endif +#if (CSS_SGI_CHIP_COUNT > 3) + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x3)) +#endif +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts new file mode 100644 index 0000000..84fc1ad --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts new file mode 100644 index 0000000..260247a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,sgi575"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + multi-chip-mode = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h new file mode 100644 index 0000000..72d5f7c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#include +#include + +#define PLAT_ARM_CLUSTER_COUNT U(2) +#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(4) +#define CSS_SGI_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45000000) + +/* Base address of DMC-620 instances */ +#define SGI575_DMC620_BASE0 UL(0x4e000000) +#define SGI575_DMC620_BASE1 UL(0x4e100000) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x300C0000) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/platform.mk b/arm-trusted-firmware/plat/arm/board/sgi575/platform.mk new file mode 100644 index 0000000..0761b77 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/platform.mk @@ -0,0 +1,65 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/arm/css/sgi/sgi-common.mk + +SGI575_BASE = plat/arm/board/sgi575 + +PLAT_INCLUDES += -I${SGI575_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_a75.S + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c + +BL1_SOURCES += ${SGI_CPU_SOURCES} \ + ${SGI575_BASE}/sgi575_err.c + +BL2_SOURCES += ${SGI575_BASE}/sgi575_plat.c \ + ${SGI575_BASE}/sgi575_security.c \ + ${SGI575_BASE}/sgi575_err.c \ + drivers/arm/tzc/tzc_dmc620.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + ${SGI575_BASE}/sgi575_plat.c \ + ${SGI575_BASE}/sgi575_topology.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${SGI575_BASE}/sgi575_trusted_boot.c +BL2_SOURCES += ${SGI575_BASE}/sgi575_trusted_boot.c +endif + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_fw_config.dts \ + ${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts + +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_nt_fw_config.dts +NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb + +# Add the NT_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) + +ifneq ($(CSS_SGI_CHIP_COUNT),1) + $(error "Chip count for SGI575 should be 1, currently set to \ + ${CSS_SGI_CHIP_COUNT}.") +endif + +ifneq ($(CSS_SGI_PLATFORM_VARIANT),0) + $(error "CSS_SGI_PLATFORM_VARIANT for SGI575 should always be 0,\ + currently set to ${CSS_SGI_PLATFORM_VARIANT}.") +endif diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c new file mode 100644 index 0000000..21bfcb7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * sgi575 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c new file mode 100644 index 0000000..dc294e6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +unsigned int plat_arm_sgi_get_platform_id(void) +{ + return mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK; +} + +unsigned int plat_arm_sgi_get_config_id(void) +{ + return (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT) + & SSC_VERSION_CONFIG_MASK; +} + +unsigned int plat_arm_sgi_get_multi_chip_mode(void) +{ + return 0; +} + +void bl31_platform_setup(void) +{ + sgi_bl31_common_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c new file mode 100644 index 0000000..17d07d1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +uintptr_t sgi575_dmc_base[] = { + SGI575_DMC620_BASE0, + SGI575_DMC620_BASE1 +}; + +static const tzc_dmc620_driver_data_t sgi575_plat_driver_data = { + .dmc_base = sgi575_dmc_base, + .dmc_count = ARRAY_SIZE(sgi575_dmc_base) +}; + +static const tzc_dmc620_acc_addr_data_t sgi575_acc_addr_data[] = { + CSS_SGI_DMC620_TZC_REGIONS_DEF +}; + +static const tzc_dmc620_config_data_t sgi575_plat_config_data = { + .plat_drv_data = &sgi575_plat_driver_data, + .plat_acc_addr_data = sgi575_acc_addr_data, + .acc_addr_count = ARRAY_SIZE(sgi575_acc_addr_data) +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + arm_tzc_dmc620_setup(&sgi575_plat_config_data); +} diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c new file mode 100644 index 0000000..f7c3856 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +static const unsigned char sgi575_pd_tree_desc[] = { + PLAT_ARM_CLUSTER_COUNT, + CSS_SGI_MAX_CPUS_PER_CLUSTER, + CSS_SGI_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return sgi575_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + 0, 1, 2, 3, 4, 5, 6, 7 +}; diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts new file mode 100644 index 0000000..5d478e9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h new file mode 100644 index 0000000..e83cd57 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#define PLAT_MAX_CPUS_PER_CLUSTER U(8) +#define PLAT_MAX_PE_PER_CPU U(1) + +#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#endif + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/platform.mk b/arm-trusted-firmware/plat/arm/board/sgm775/platform.mk new file mode 100644 index 0000000..f8df1a7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/platform.mk @@ -0,0 +1,39 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +$(warning Platform ${PLAT} is deprecated. Some of the features might not work as expected) + +include plat/arm/css/sgm/sgm-common.mk + +SGM775_BASE= plat/arm/board/sgm775 + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${SGM775_BASE}/fdts/${PLAT}_fw_config.dts \ + ${SGM775_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +PLAT_INCLUDES +=-I${SGM775_BASE}/include/ + +BL1_SOURCES += ${SGM775_BASE}/sgm775_err.c + +BL2_SOURCES += lib/utils/mem_region.c \ + ${SGM775_BASE}/sgm775_err.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +BL1_SOURCES += ${SGM775_BASE}/sgm775_trusted_boot.c +BL2_SOURCES += ${SGM775_BASE}/sgm775_trusted_boot.c +endif diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c b/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c new file mode 100644 index 0000000..dc114f0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * sgm775 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/tsp/tsp-sgm775.mk b/arm-trusted-firmware/plat/arm/board/sgm775/tsp/tsp-sgm775.mk new file mode 100644 index 0000000..129b586 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/tsp/tsp-sgm775.mk @@ -0,0 +1,7 @@ +# +# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/arm/css/sgm/tsp/tsp-sgm.mk \ No newline at end of file diff --git a/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts new file mode 100644 index 0000000..a84c7f8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x400>; + id = ; + }; + + tos_fw-config { + load-address = <0x0 0x04001700>; + max-size = <0x1000>; + id = ; + }; + + hw-config { + load-address = <0x0 0x83000000>; + max-size = <0x8000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts new file mode 100644 index 0000000..d3a5e1a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0xfd000000>; + entrypoint = <0x0 0xfd000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "cactus-primary"; + load_address = <0xfe000000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + vm2 { + is_ffa_partition; + debug_name = "cactus-secondary"; + load_address = <0xfe100000>; + vcpu_count = <8>; + mem_size = <1048576>; + }; + vm3 { + is_ffa_partition; + debug_name = "cactus-tertiary"; + load_address = <0xfe200000>; + vcpu_count = <1>; + mem_size = <1048576>; + }; + vm4 { + is_ffa_partition; + debug_name = "ivy"; + load_address = <0xfe600000>; + vcpu_count = <1>; + mem_size = <1048576>; + }; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + /* + * SPMC (Hafnium) requires secondary cpu nodes are declared in + * descending order + */ + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x700>; + enable-method = "psci"; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x600>; + enable-method = "psci"; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x500>; + enable-method = "psci"; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x400>; + enable-method = "psci"; + }; + + CPU3:cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x300>; + enable-method = "psci"; + }; + + CPU2:cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x200>; + enable-method = "psci"; + }; + + CPU1:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + }; + }; + + /* 32MB of TC_TZC_DRAM1_BASE */ + memory@fd000000 { + device_type = "memory"; + reg = <0x0 0xfd000000 0x2000000>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts new file mode 100644 index 0000000..92e2ddd --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/dts-v1/; + +/ { + compatible = "arm,ffa-core-manifest-1.0"; + #address-cells = <2>; + #size-cells = <1>; + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x1>; + exec_state = <0x0>; + load_address = <0x0 0xfd000000>; + entrypoint = <0x0 0xfd000000>; + binary_size = <0x80000>; + }; + + hypervisor { + compatible = "hafnium,hafnium"; + vm1 { + is_ffa_partition; + debug_name = "op-tee"; + load_address = <0xfd280000>; + vcpu_count = <8>; +#ifdef TS_SP_FW_CONFIG + mem_size = <26738688>; /* 25MB TZC DRAM */ +#else + mem_size = <30928896>; /* 29MB TZC DRAM */ +#endif + }; +#ifdef TS_SP_FW_CONFIG + vm2 { + is_ffa_partition; + debug_name = "internal-trusted-storage"; + load_address = <0xfee00000>; + vcpu_count = <1>; + mem_size = <2097152>; /* 2MB TZC DRAM */ + }; + vm3 { + is_ffa_partition; + debug_name = "crypto"; + load_address = <0xfec00000>; + vcpu_count = <1>; + mem_size = <2097152>; /* 2MB TZC DRAM */ + }; +#endif + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + /* + * SPMC (Hafnium) requires secondary cpu nodes are declared in + * descending order + */ + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x700>; + enable-method = "psci"; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x600>; + enable-method = "psci"; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x500>; + enable-method = "psci"; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x400>; + enable-method = "psci"; + }; + + CPU3:cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x300>; + enable-method = "psci"; + }; + + CPU2:cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x200>; + enable-method = "psci"; + }; + + CPU1:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + }; + }; + + /* 32MB of TC_TZC_DRAM1_BASE */ + memory@fd000000 { + device_type = "memory"; + reg = <0x0 0xfd000000 0x2000000>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts new file mode 100644 index 0000000..4c6ccef --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + tb_fw-config { + compatible = "arm,tb_fw"; + + /* Disable authentication for development */ + disable_auth = <0x0>; + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; + + secure-partitions { + compatible = "arm,sp"; +#ifdef ARM_BL2_SP_LIST_DTS + #include __XSTRING(ARM_BL2_SP_LIST_DTS) +#else +#ifdef TS_SP_FW_CONFIG + internal-trusted-storage { + uuid = "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14"; + load-address = <0xfee00000>; + }; + crypto { + uuid = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0"; + load-address = <0xfec00000>; + }; +#endif +#if OPTEE_SP_FW_CONFIG + op-tee { + uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b"; + load-address = <0xfd280000>; + }; +#else + cactus-primary { + uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb"; + load-address = <0xfe000000>; + owner = "SiP"; + }; + + cactus-secondary { + uuid = "d1582309-f023-47b9-827c-4464f5578fc8"; + load-address = <0xfe100000>; + owner = "Plat"; + }; + + cactus-tertiary { + uuid = "79b55c73-1d8c-44b9-8593-61e1770ad8d2"; + load-address = <0xfe200000>; + }; + + ivy { + uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7"; + load-address = <0xfe600000>; + owner = "Plat"; + }; +#endif +#endif /* ARM_BL2_SP_LIST_DTS */ + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S new file mode 100644 index 0000000..6006fa5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * + * There are currently no platform specific regs + * to print. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h new file mode 100644 index 0000000..745d91c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLATFORM_CORE_COUNT 8 + +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */ + +/* + * The top 16MB of ARM_DRAM1 is configured as secure access only using the TZC, + * its base is ARM_AP_TZC_DRAM1_BASE. + * + * Reserve 32MB below ARM_AP_TZC_DRAM1_BASE for: + * - BL32_BASE when SPD_spmd is enabled + * - Region to load Trusted OS + */ +#define TC_TZC_DRAM1_BASE (ARM_AP_TZC_DRAM1_BASE - \ + TC_TZC_DRAM1_SIZE) +#define TC_TZC_DRAM1_SIZE UL(0x02000000) /* 32 MB */ +#define TC_TZC_DRAM1_END (TC_TZC_DRAM1_BASE + \ + TC_TZC_DRAM1_SIZE - 1) + +#define TC_NS_DRAM1_BASE ARM_DRAM1_BASE +#define TC_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + ARM_TZC_DRAM1_SIZE - \ + TC_TZC_DRAM1_SIZE) +#define TC_NS_DRAM1_END (TC_NS_DRAM1_BASE + \ + TC_NS_DRAM1_SIZE - 1) + +/* + * Mappings for TC DRAM1 (non-secure) and TC TZC DRAM1 (secure) + */ +#define TC_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + TC_NS_DRAM1_BASE, \ + TC_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + + +#define TC_MAP_TZC_DRAM1 MAP_REGION_FLAT( \ + TC_TZC_DRAM1_BASE, \ + TC_TZC_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define PLAT_HW_CONFIG_DTB_BASE ULL(0x83000000) +#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000) + +#define PLAT_DTB_DRAM_NS MAP_REGION_FLAT( \ + PLAT_HW_CONFIG_DTB_BASE, \ + PLAT_HW_CONFIG_DTB_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) +/* + * Max size of SPMC is 2MB for tc. With SPMD enabled this value corresponds to + * max size of BL32 image. + */ +#if defined(SPD_spmd) +#define PLAT_ARM_SPMC_BASE TC_TZC_DRAM1_BASE +#define PLAT_ARM_SPMC_SIZE UL(0x200000) /* 2 MB */ +#endif + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL31) +# if SPM_MM +# define PLAT_ARM_MMAP_ENTRIES 9 +# define MAX_XLAT_TABLES 7 +# define PLAT_SP_IMAGE_MMAP_REGIONS 7 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10 +# else +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 8 +# endif +#elif defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 5 +#elif !USE_ROMLIB +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 7 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xC000 + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000 +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000 +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0 +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0 +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE 0x20000 +#else +# define PLAT_ARM_MAX_BL2_SIZE 0x14000 +#endif + +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL31_SIZE 0x3F000 + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x440 +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +# if SPM_MM +# define PLATFORM_STACK_SIZE 0x500 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + + +#define TC_DEVICE_BASE 0x21000000 +#define TC_DEVICE_SIZE 0x5f000000 + +// TC_MAP_DEVICE covers different peripherals +// available to the platform +#define TC_MAP_DEVICE MAP_REGION_FLAT( \ + TC_DEVICE_BASE, \ + TC_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + + +#define TC_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE) + +#define PLAT_ARM_NSTIMER_FRAME_ID 0 + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x0 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x00080000 /* 512KB */ + +#define PLAT_ARM_NSRAM_BASE 0x06000000 +#define PLAT_ARM_NSRAM_SIZE 0x00080000 /* 512KB */ + +#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000) +#define PLAT_ARM_DRAM2_END (PLAT_ARM_DRAM2_BASE + PLAT_ARM_DRAM2_SIZE - 1ULL) + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp) +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) + +/******************************************************************************* + * Memprotect definitions + ******************************************************************************/ +/* PSCI memory protect definitions: + * This variable is stored in a non-secure flash because some ARM reference + * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT + * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions. + */ +#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \ + V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/*Secure Watchdog Constants */ +#define SBSA_SECURE_WDOG_BASE UL(0x2A480000) +#define SBSA_SECURE_WDOG_TIMEOUT UL(100) + +#define PLAT_ARM_SCMI_CHANNEL_COUNT 1 + +#define PLAT_ARM_CLUSTER_COUNT U(1) +#define PLAT_MAX_CPUS_PER_CLUSTER U(8) +#define PLAT_MAX_PE_PER_CPU U(1) + +#define PLAT_CSS_MHU_BASE UL(0x45400000) +#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE + +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 + +/* + * Physical and virtual address space limits for MMU in AARCH64 + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE UL(0x30000000) +#define PLAT_ARM_GICC_BASE UL(0x2C000000) +#define PLAT_ARM_GICR_BASE UL(0x30080000) + +/* + * PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current + * SCP_BL2 size plus a little space for growth. + */ +#define PLAT_CSS_MAX_SCP_BL2_SIZE 0x20000 + +/* + * PLAT_CSS_MAX_SCP_BL2U_SIZE is calculated using the current + * SCP_BL2U size plus a little space for growth. + */ +#define PLAT_CSS_MAX_SCP_BL2U_SIZE 0x20000 + +/* TZC Related Constants */ +#define PLAT_ARM_TZC_BASE UL(0x25000000) +#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0) + +#define TZC400_OFFSET UL(0x1000000) +#define TZC400_COUNT 4 + +#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \ + (n * TZC400_OFFSET)) + +#define TZC_NSAID_DEFAULT U(0) + +#define PLAT_ARM_TZC_NS_DEV_ACCESS \ + (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT)) + +/* + * The first region below, TC_TZC_DRAM1_BASE (0xfd000000) to + * ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 48 MB of DRAM as + * secure. The second and third regions gives non secure access to rest of DRAM. + */ +#define TC_TZC_REGIONS_DEF \ + {TC_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END, \ + TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {TC_NS_DRAM1_BASE, TC_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {PLAT_ARM_DRAM2_BASE, PLAT_ARM_DRAM2_END, \ + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS} + +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S b/arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S new file mode 100644 index 0000000..5f54856 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on TC. + * + * (ClusterId * PLAT_MAX_CPUS_PER_CLUSTER * PLAT_MAX_PE_PER_CPU) + + * (CPUId * PLAT_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * PLAT_MAX_CPUS_PER_CLUSTER + CPUId) * PLAT_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation. + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #PLAT_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x5, #PLAT_MAX_PE_PER_CPU + madd x0, x1, x5, x0 + ret +endfunc plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the CPU MIDR and disable power down bit for + * that CPU. + * ----------------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h b/arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h new file mode 100644 index 0000000..28c0308 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TC_PLAT_H +#define TC_PLAT_H + +void tc_bl31_common_platform_setup(void); + +#endif /* TC_PLAT_H */ diff --git a/arm-trusted-firmware/plat/arm/board/tc/platform.mk b/arm-trusted-firmware/plat/arm/board/tc/platform.mk new file mode 100644 index 0000000..3acd88e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/platform.mk @@ -0,0 +1,161 @@ +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +ifeq ($(filter ${TARGET_PLATFORM}, 0 1),) + $(error TARGET_PLATFORM must be 0 or 1) +endif + +CSS_LOAD_SCP_IMAGES := 1 + +CSS_USE_SCMI_SDS_DRIVER := 1 + +RAS_EXTENSION := 0 + +SDEI_SUPPORT := 0 + +EL3_EXCEPTION_HANDLING := 0 + +HANDLE_EA_EL3_FIRST := 0 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# 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. +USE_COHERENT_MEM := 0 + +GIC_ENABLE_V4_EXTN := 1 + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 + +# Enable SVE +ENABLE_SVE_FOR_NS := 1 +ENABLE_SVE_FOR_SWD := 1 + +# enable trace buffer control registers access to NS by default +ENABLE_TRBE_FOR_NS := 1 + +# enable trace system registers access to NS by default +ENABLE_SYS_REG_TRACE_FOR_NS := 1 + +# enable trace filter control registers access to NS by default +ENABLE_TRF_FOR_NS := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +ENT_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c + +override NEED_BL2U := no + +override ARM_PLAT_MT := 1 + +TC_BASE = plat/arm/board/tc + +PLAT_INCLUDES += -I${TC_BASE}/include/ + +# Common CPU libraries +TC_CPU_SOURCES := lib/cpus/aarch64/cortex_a510.S + +# CPU libraries for TARGET_PLATFORM=0 +ifeq (${TARGET_PLATFORM}, 0) +TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a710.S \ + lib/cpus/aarch64/cortex_x2.S +endif + +# CPU libraries for TARGET_PLATFORM=1 +ifeq (${TARGET_PLATFORM}, 1) +TC_CPU_SOURCES += lib/cpus/aarch64/cortex_makalu.S \ + lib/cpus/aarch64/cortex_makalu_elp_arm.S +endif + +INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c + +PLAT_BL_COMMON_SOURCES += ${TC_BASE}/tc_plat.c \ + ${TC_BASE}/include/tc_helpers.S + +BL1_SOURCES += ${INTERCONNECT_SOURCES} \ + ${TC_CPU_SOURCES} \ + ${TC_BASE}/tc_trusted_boot.c \ + ${TC_BASE}/tc_err.c \ + drivers/arm/sbsa/sbsa.c + + +BL2_SOURCES += ${TC_BASE}/tc_security.c \ + ${TC_BASE}/tc_err.c \ + ${TC_BASE}/tc_trusted_boot.c \ + ${TC_BASE}/tc_bl2_setup.c \ + lib/utils/mem_region.c \ + drivers/arm/tzc/tzc400.c \ + plat/arm/common/arm_tzc400.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${INTERCONNECT_SOURCES} \ + ${TC_CPU_SOURCES} \ + ${ENT_GIC_SOURCES} \ + ${TC_BASE}/tc_bl31_setup.c \ + ${TC_BASE}/tc_topology.c \ + lib/fconf/fconf.c \ + lib/fconf/fconf_dyn_cfg_getter.c \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${TC_BASE}/fdts/${PLAT}_fw_config.dts \ + ${TC_BASE}/fdts/${PLAT}_tb_fw_config.dts +FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) + +ifeq (${SPD},spmd) +ifeq ($(ARM_SPMC_MANIFEST_DTS),) +ARM_SPMC_MANIFEST_DTS := ${TC_BASE}/fdts/${PLAT}_spmc_manifest.dts +endif + +FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS} +TC_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb + +# Add the TOS_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TC_TOS_FW_CONFIG},--tos-fw-config,${TC_TOS_FW_CONFIG})) +endif + +#Device tree +TC_HW_CONFIG_DTS := fdts/tc.dts +TC_HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb +FDT_SOURCES += ${TC_HW_CONFIG_DTS} +$(eval TC_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(TC_HW_CONFIG_DTS))) + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TC_HW_CONFIG},--hw-config,${TC_HW_CONFIG})) + +override CTX_INCLUDE_AARCH32_REGS := 0 + +override CTX_INCLUDE_PAUTH_REGS := 1 + +override ENABLE_SPE_FOR_LOWER_ELS := 0 + +override ENABLE_AMU := 1 +override ENABLE_AMU_AUXILIARY_COUNTERS := 1 +override ENABLE_AMU_FCONF := 1 + +override ENABLE_MPMM := 1 +override ENABLE_MPMM_FCONF := 1 + +include plat/arm/common/arm_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/soc/common/soc_css.mk +include plat/arm/board/common/board_common.mk diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c new file mode 100644 index 0000000..74ef569 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include + +/******************************************************************************* + * This function returns the list of executable images + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + struct bl_params *arm_bl_params = arm_get_next_bl_params(); + + const struct dyn_cfg_dtb_info_t *fw_config_info; + bl_mem_params_node_t *param_node; + uintptr_t fw_config_base = 0U; + entry_point_info_t *ep_info; + + /* Get BL31 image node */ + param_node = get_bl_mem_params_node(BL31_IMAGE_ID); + assert(param_node != NULL); + + /* Get fw_config load address */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + assert(fw_config_info != NULL); + + fw_config_base = fw_config_info->config_addr; + assert(fw_config_base != 0U); + + /* + * Get the entry point info of BL31 image and override + * arg1 of entry point info with fw_config base address + */ + ep_info = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; + + return arm_bl_params; +} diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c new file mode 100644 index 0000000..0523ef8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-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 + +static scmi_channel_plat_info_t tc_scmi_plat_info[] = { + { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0), + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhuv2_ring_doorbell, + } +}; + +void bl31_platform_setup(void) +{ + tc_bl31_common_platform_setup(); +} + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + + return &tc_scmi_plat_info[channel_id]; + +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", arg1); +} + +void tc_bl31_common_platform_setup(void) +{ + arm_bl31_platform_setup(); +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return css_scmi_override_pm_ops(ops); +} + +void __init bl31_plat_arch_setup(void) +{ + arm_bl31_plat_arch_setup(); + + /* HW_CONFIG was also loaded by BL2 */ + const struct dyn_cfg_dtb_info_t *hw_config_info; + + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + + fconf_populate("HW_CONFIG", hw_config_info->config_addr); +} diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_err.c b/arm-trusted-firmware/plat/arm/board/tc/tc_err.c new file mode 100644 index 0000000..9ed7e92 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/tc_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * tc error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c b/arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c new file mode 100644 index 0000000..e2fc4e1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* + * For Total Compute we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void __init plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_plat.c b/arm-trusted-firmware/plat/arm/board/tc/tc_plat.c new file mode 100644 index 0000000..a9668e1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/tc_plat.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if SPM_MM +#include +#endif + +/* + * Table of regions for different BL stages to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * arm_configure_mmu_elx() will give the available subset of that. + */ +#if IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + TC_FLASH0_RO, + TC_MAP_DEVICE, + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + TC_FLASH0_RO, + TC_MAP_DEVICE, + TC_MAP_NS_DRAM1, +#if defined(SPD_spmd) + TC_MAP_TZC_DRAM1, +#endif +#if ARM_BL31_IN_DRAM + ARM_MAP_BL31_SEC_DRAM, +#endif +#if SPM_MM + ARM_SP_IMAGE_MMAP, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif +#ifdef SPD_opteed + ARM_MAP_OPTEE_CORE_MEM, + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif + {0} +}; +#endif +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + TC_MAP_DEVICE, + PLAT_DTB_DRAM_NS, +#if SPM_MM + ARM_SPM_BUF_EL3_MMAP, +#endif + {0} +}; + +#if SPM_MM && defined(IMAGE_BL31) +const mmap_region_t plat_arm_secure_partition_mmap[] = { + PLAT_ARM_SECURE_MAP_DEVICE, + ARM_SP_IMAGE_MMAP, + ARM_SP_IMAGE_NS_BUF_MMAP, + ARM_SP_CPER_BUF_MMAP, + ARM_SP_IMAGE_RW_MMAP, + ARM_SPM_BUF_EL0_MMAP, + {0} +}; +#endif /* SPM_MM && defined(IMAGE_BL31) */ +#endif + +ARM_CASSERT_MMAP + +#if SPM_MM && defined(IMAGE_BL31) +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static spm_mm_mp_info_t sp_mp_info[] = { + [0] = {0x81000000, 0}, + [1] = {0x81000100, 0}, + [2] = {0x81000200, 0}, + [3] = {0x81000300, 0}, + [4] = {0x81010000, 0}, + [5] = {0x81010100, 0}, + [6] = {0x81010200, 0}, + [7] = {0x81010300, 0}, +}; + +const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = ARM_SP_IMAGE_BASE, + .sp_mem_limit = ARM_SP_IMAGE_LIMIT, + .sp_image_base = ARM_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = ARM_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = &sp_mp_info[0], +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} +#endif /* SPM_MM && defined(IMAGE_BL31) */ + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_security.c b/arm-trusted-firmware/plat/arm/board/tc/tc_security.c new file mode 100644 index 0000000..6a34501 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/tc_security.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +static const arm_tzc_regions_info_t tzc_regions[] = { + TC_TZC_REGIONS_DEF, + {} +}; + +/* Initialize the secure environment */ +void plat_arm_security_setup(void) +{ + unsigned int i; + + for (i = 0U; i < TZC400_COUNT; i++) { + arm_tzc400_setup(TZC400_BASE(i), tzc_regions); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_topology.c b/arm-trusted-firmware/plat/arm/board/tc/tc_topology.c new file mode 100644 index 0000000..9e18da6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/tc_topology.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/****************************************************************************** + * The power domain tree descriptor. + ******************************************************************************/ +const unsigned char tc_pd_tree_desc[] = { + PLAT_ARM_CLUSTER_COUNT, + PLAT_MAX_CPUS_PER_CLUSTER, +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return tc_pd_tree_desc; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), +}; + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return PLAT_MAX_CPUS_PER_CLUSTER; +} + +#if ARM_PLAT_MT +/****************************************************************************** + * Return the number of PE's supported by the CPU. + *****************************************************************************/ +unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr) +{ + return PLAT_MAX_PE_PER_CPU; +} +#endif diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c new file mode 100644 index 0000000..614f7e2 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + return arm_get_rotpk_info(cookie, key_ptr, key_len, flags); +} diff --git a/arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c new file mode 100644 index 0000000..78360b0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = PLAT_CSS_MAX_SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL32_BASE, + .ep_info.spsr = SPSR_MODE32(MODE32_mon, SPSR_T_ARM, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + /* Fill HW_CONFIG related information if it exists */ + { + .image_id = HW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, NON_SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +#ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#else + .ep_info.pc = PLAT_ARM_NS_IMAGE_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_ARM_NS_IMAGE_BASE, + .image_info.image_max_size = ARM_DRAM1_BASE + ARM_DRAM1_SIZE + - PLAT_ARM_NS_IMAGE_BASE, +#endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S b/arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S new file mode 100644 index 0000000..1da2d4c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + + .weak plat_arm_calc_core_pos + .weak plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_arm_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + ldcopr r0, MPIDR + b plat_arm_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(uint64_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func plat_arm_calc_core_pos + and r1, r0, #MPIDR_CPU_MASK + and r0, r0, #MPIDR_CLUSTER_MASK + add r0, r1, r0, LSR #6 + bx lr +endfunc plat_arm_calc_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : r0 - r3 + * --------------------------------------------- + */ +func plat_crash_console_init + ldr r0, =PLAT_ARM_CRASH_UART_BASE + ldr r1, =PLAT_ARM_CRASH_UART_CLK_IN_HZ + ldr r2, =ARM_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : r1 - r2 + * --------------------------------------------- + */ +func plat_crash_console_putc + ldr r1, =PLAT_ARM_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : r0 + * --------------------------------------------- + */ +func plat_crash_console_flush + ldr r0, =PLAT_ARM_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush diff --git a/arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c new file mode 100644 index 0000000..0666e57 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = PLAT_CSS_MAX_SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .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.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + 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 /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg3 = ARM_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# if defined(BL32_BASE) + .next_handoff_image_id = BL32_IMAGE_ID, +# elif ENABLE_RME + .next_handoff_image_id = RMM_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + /* Fill HW_CONFIG related information */ + { + .image_id = HW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, NON_SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + /* Fill SOC_FW_CONFIG related information */ + { + .image_id = SOC_FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + +# if ENABLE_RME + /* Fill RMM related information */ + { + .image_id = RMM_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, EP_REALM | EXECUTABLE), + .ep_info.pc = RMM_BASE, + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = RMM_BASE, + .image_info.image_max_size = RMM_LIMIT - RMM_BASE, + .next_handoff_image_id = BL33_IMAGE_ID, + }, +# endif + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + +# if ENABLE_RME + .next_handoff_image_id = RMM_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = ARM_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = ARM_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* Fill TOS_FW_CONFIG related information */ + { + .image_id = TOS_FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = PLAT_ARM_NS_IMAGE_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_ARM_NS_IMAGE_BASE, + .image_info.image_max_size = ARM_DRAM1_BASE + ARM_DRAM1_SIZE + - PLAT_ARM_NS_IMAGE_BASE, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + /* Fill NT_FW_CONFIG related information */ + { + .image_id = NT_FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, NON_SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S b/arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S new file mode 100644 index 0000000..b470781 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + + .weak plat_arm_calc_core_pos + .weak plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_arm_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_arm_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func plat_arm_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_arm_calc_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, PLAT_ARM_CRASH_UART_BASE + mov_imm x1, PLAT_ARM_CRASH_UART_CLK_IN_HZ + mov_imm x2, ARM_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, PLAT_ARM_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : r0 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, PLAT_ARM_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on ARM + * platforms. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + +/* + * Need to use coherent stack when ARM Cryptocell is used to autheticate images + * since Cryptocell uses DMA to transfer data and it is not coherent with the + * AP CPU. + */ +#if ARM_CRYPTOCELL_INTEG +#if defined(IMAGE_BL1) || defined(IMAGE_BL2) + .globl plat_get_my_stack + .globl plat_set_my_stack + .local platform_coherent_stacks + + /* ------------------------------------------------------- + * 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 coherent memory. + * ------------------------------------------------------- + */ +func plat_get_my_stack + get_up_stack platform_coherent_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 coherent memory. + * ------------------------------------------------------- + */ +func plat_set_my_stack + get_up_stack platform_coherent_stacks, PLATFORM_STACK_SIZE + mov sp, x0 + ret +endfunc plat_set_my_stack + + /* ---------------------------------------------------- + * Single cpu stack in coherent memory. + * ---------------------------------------------------- + */ +declare_stack platform_coherent_stacks, tzfw_coherent_mem, \ + PLATFORM_STACK_SIZE, 1, CACHE_WRITEBACK_GRANULE + +#endif /* defined(IMAGE_BL1) || defined(IMAGE_BL2) */ +#endif /* ARM_CRYPTOCELL_INTEG */ diff --git a/arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c b/arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c new file mode 100644 index 0000000..7cea8a0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* + * This is only a toy implementation to generate a seemingly random + * 128-bit key from sp, x30 and cntpct_el0 values. + * A production system must re-implement this function to generate + * keys from a reliable randomness source. + */ +uint128_t plat_init_apkey(void) +{ + uint64_t return_addr = (uint64_t)__builtin_return_address(0U); + uint64_t frame_addr = (uint64_t)__builtin_frame_address(0U); + uint64_t cntpct = read_cntpct_el0(); + + /* Generate 128-bit key */ + uint64_t key_lo = (return_addr << 13) ^ frame_addr ^ cntpct; + uint64_t key_hi = (frame_addr << 15) ^ return_addr ^ cntpct; + + return ((uint128_t)(key_hi) << 64) | key_lo; +} diff --git a/arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c b/arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c new file mode 100644 index 0000000..3c74a46 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* SDEI configuration for ARM platforms */ + +#include +#include +#include + +#if SDEI_IN_FCONF +#include +#endif +#include +#include + + +#if SDEI_IN_FCONF +/* Private event mappings */ +static sdei_ev_map_t arm_sdei_private[PLAT_SDEI_DP_EVENT_MAX_CNT + 1] = { 0 }; + +/* Shared event mappings */ +static sdei_ev_map_t arm_sdei_shared[PLAT_SDEI_DS_EVENT_MAX_CNT] = { 0 }; + +void plat_sdei_setup(void) +{ + uint32_t i; + + arm_sdei_private[0] = (sdei_ev_map_t)SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI); + + for (i = 0; i < FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_cnt); i++) { + arm_sdei_private[i + 1] = (sdei_ev_map_t)SDEI_PRIVATE_EVENT( + FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_nums[i]), + FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_intrs[i]), + FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_flags[i])); + } + + for (i = 0; i < FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_cnt); i++) { + arm_sdei_shared[i] = (sdei_ev_map_t)SDEI_SHARED_EVENT( \ + FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_nums[i]), + FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_intrs[i]), + FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_flags[i])); + } + INFO("FCONF: SDEI platform setup\n"); +} +#else +/* Private event mappings */ +static sdei_ev_map_t arm_sdei_private[] = { + PLAT_ARM_PRIVATE_SDEI_EVENTS +}; + +/* Shared event mappings */ +static sdei_ev_map_t arm_sdei_shared[] = { + PLAT_ARM_SHARED_SDEI_EVENTS +}; + +void plat_sdei_setup(void) +{ + INFO("SDEI platform setup\n"); +} +#endif /* SDEI_IN_FCONF */ + +/* Export ARM SDEI events */ +REGISTER_SDEI_MAP(arm_sdei_private, arm_sdei_shared); diff --git a/arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c b/arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c new file mode 100644 index 0000000..bed929a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c @@ -0,0 +1,180 @@ +/* + * 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 + +/* + * Handle SMC from a lower exception level to switch its execution state + * (either from AArch64 to AArch32, or vice versa). + * + * smc_fid: + * SMC function ID - either ARM_SIP_SVC_STATE_SWITCH_64 or + * ARM_SIP_SVC_STATE_SWITCH_32. + * pc_hi, pc_lo: + * PC upon re-entry to the calling exception level; width dependent on the + * calling exception level. + * cookie_hi, cookie_lo: + * Opaque pointer pairs received from the caller to pass it back, upon + * re-entry. + * handle: + * Handle to saved context. + */ +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) +{ + bool caller_64, thumb = false, from_el2; + unsigned int el, endianness; + u_register_t spsr, pc, scr, sctlr; + entry_point_info_t ep; + cpu_context_t *ctx = (cpu_context_t *) handle; + el3_state_t *el3_ctx = get_el3state_ctx(ctx); + + /* Validate supplied entry point */ + pc = (u_register_t) (((uint64_t) pc_hi << 32) | pc_lo); + if (arm_validate_ns_entrypoint(pc) != 0) + goto invalid_param; + + /* That the SMC originated from NS is already validated by the caller */ + + /* + * Disallow state switch if any of the secondaries have been brought up. + */ + if (psci_secondaries_brought_up() != 0) + goto exec_denied; + + spsr = read_ctx_reg(el3_ctx, CTX_SPSR_EL3); + caller_64 = (GET_RW(spsr) == MODE_RW_64); + + if (caller_64) { + /* + * If the call originated from AArch64, expect 32-bit pointers when + * switching to AArch32. + */ + if ((pc_hi != 0U) || (cookie_hi != 0U)) + goto invalid_param; + + pc = pc_lo; + + /* Instruction state when entering AArch32 */ + thumb = (pc & 1U) != 0U; + } else { + /* Construct AArch64 PC */ + pc = (((u_register_t) pc_hi) << 32) | pc_lo; + } + + /* Make sure PC is 4-byte aligned, except for Thumb */ + if (((pc & 0x3U) != 0U) && !thumb) + goto invalid_param; + + /* + * EL3 controls register width of the immediate lower EL only. Expect + * this request from EL2/Hyp unless: + * + * - EL2 is not implemented; + * - EL2 is implemented, but was disabled. This can be inferred from + * SCR_EL3.HCE. + */ + from_el2 = caller_64 ? (GET_EL(spsr) == MODE_EL2) : + (GET_M32(spsr) == MODE32_hyp); + scr = read_ctx_reg(el3_ctx, CTX_SCR_EL3); + if (!from_el2) { + /* The call is from NS privilege level other than HYP */ + + /* + * Disallow switching state if there's a Hypervisor in place; + * this request must be taken up with the Hypervisor instead. + */ + if ((scr & SCR_HCE_BIT) != 0U) + goto exec_denied; + } + + /* + * Return to the caller using the same endianness. Extract + * endianness bit from the respective system control register + * directly. + */ + sctlr = from_el2 ? read_sctlr_el2() : read_sctlr_el1(); + endianness = ((sctlr & SCTLR_EE_BIT) != 0U) ? 1U : 0U; + + /* Construct SPSR for the exception state we're about to switch to */ + if (caller_64) { + unsigned long long impl; + + /* + * Switching from AArch64 to AArch32. Ensure this CPU implements + * the target EL in AArch32. + */ + impl = from_el2 ? el_implemented(2) : el_implemented(1); + if (impl != EL_IMPL_A64_A32) + goto exec_denied; + + /* Return to the equivalent AArch32 privilege level */ + el = from_el2 ? MODE32_hyp : MODE32_svc; + spsr = SPSR_MODE32((u_register_t) el, + thumb ? SPSR_T_THUMB : SPSR_T_ARM, + endianness, DISABLE_ALL_EXCEPTIONS); + } else { + /* + * Switching from AArch32 to AArch64. Since it's not possible to + * implement an EL as AArch32-only (from which this call was + * raised), it's safe to assume AArch64 is also implemented. + */ + el = from_el2 ? MODE_EL2 : MODE_EL1; + spsr = SPSR_64((u_register_t) el, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } + + /* + * Use the context management library to re-initialize the existing + * context with the execution state flipped. Since the library takes + * entry_point_info_t pointer as the argument, construct a dummy one + * with PC, state width, endianness, security etc. appropriately set. + * Other entries in the entry point structure are irrelevant for + * purpose. + */ + zeromem(&ep, sizeof(ep)); + ep.pc = pc; + ep.spsr = (uint32_t) spsr; + SET_PARAM_HEAD(&ep, PARAM_EP, VERSION_1, + ((unsigned int) ((endianness != 0U) ? EP_EE_BIG : + EP_EE_LITTLE) + | NON_SECURE | EP_ST_DISABLE)); + + /* + * Re-initialize the system register context, and exit EL3 as if for the + * first time. State switch is effectively a soft reset of the + * calling EL. + */ + cm_init_my_context(&ep); + cm_prepare_el3_exit(NON_SECURE); + + /* + * State switch success. The caller of SMC wouldn't see the SMC + * returning. Instead, execution starts at the supplied entry point, + * with context pointers populated in registers 0 and 1. + */ + SMC_RET2(handle, cookie_hi, cookie_lo); + +invalid_param: + SMC_RET1(handle, STATE_SW_E_PARAM); + +exec_denied: + /* State switch denied */ + SMC_RET1(handle, STATE_SW_E_DENIED); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c b/arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c new file mode 100644 index 0000000..ce2c356 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c @@ -0,0 +1,102 @@ +/* + * 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 + +#pragma weak bl1_plat_get_image_desc + +/* Struct to keep track of usable memory */ +typedef struct bl1_mem_info { + uintptr_t mem_base; + unsigned int mem_size; +} bl1_mem_info_t; + +static bl1_mem_info_t fwu_addr_map_secure[] = { + { + .mem_base = ARM_SHARED_RAM_BASE, + .mem_size = ARM_SHARED_RAM_SIZE + }, + { + .mem_size = 0 + } +}; + +static bl1_mem_info_t fwu_addr_map_non_secure[] = { + { + .mem_base = ARM_NS_DRAM1_BASE, + .mem_size = ARM_NS_DRAM1_SIZE + }, + { + .mem_base = PLAT_ARM_NVM_BASE, + .mem_size = PLAT_ARM_NVM_SIZE + }, + { + .mem_size = 0 + } +}; + +int bl1_plat_mem_check(uintptr_t mem_base, + unsigned int mem_size, + unsigned int flags) +{ + unsigned int index = 0; + bl1_mem_info_t *mmap; + + assert(mem_base); + assert(mem_size); + /* + * The caller of this function is responsible for checking upfront that + * the end address doesn't overflow. We double-check this in debug + * builds. + */ + assert(!check_uptr_overflow(mem_base, mem_size - 1)); + + /* + * Check the given image source and size. + */ + if (GET_SECURITY_STATE(flags) == SECURE) + mmap = fwu_addr_map_secure; + else + mmap = fwu_addr_map_non_secure; + + while (mmap[index].mem_size) { + if ((mem_base >= mmap[index].mem_base) && + ((mem_base + mem_size) + <= (mmap[index].mem_base + + mmap[index].mem_size))) + return 0; + + index++; + } + + return -ENOMEM; +} + +/******************************************************************************* + * This function does linear search for image_id and returns image_desc. + ******************************************************************************/ +image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) +{ + unsigned int index = 0; + + while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { + if (bl1_tbbr_image_descs[index].image_id == image_id) + return &bl1_tbbr_image_descs[index]; + index++; + } + + return NULL; +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c new file mode 100644 index 0000000..73338cb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak bl1_early_platform_setup +#pragma weak bl1_plat_arch_setup +#pragma weak bl1_plat_sec_mem_layout +#pragma weak arm_bl1_early_platform_setup +#pragma weak bl1_plat_prepare_exit +#pragma weak bl1_plat_get_next_image_id +#pragma weak plat_arm_bl1_fwu_needed +#pragma weak arm_bl1_plat_arch_setup +#pragma weak arm_bl1_platform_setup + +#define MAP_BL1_TOTAL MAP_REGION_FLAT( \ + bl1_tzram_layout.total_base, \ + bl1_tzram_layout.total_size, \ + MT_MEMORY | MT_RW | EL3_PAS) +/* + * 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 MAP_BL1_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL1_CODE_END - BL_CODE_BASE, \ + MT_CODE | EL3_PAS), \ + MAP_REGION_FLAT( \ + BL1_RO_DATA_BASE, \ + BL1_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | EL3_PAS) +#else +#define MAP_BL1_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL1_CODE_END - BL_CODE_BASE, \ + MT_CODE | EL3_PAS) +#endif + +/* Data structure which holds the extents of the trusted SRAM for BL1*/ +static meminfo_t bl1_tzram_layout; + +/* Boolean variable to hold condition whether firmware update needed or not */ +static bool is_fwu_needed; + +struct meminfo *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/******************************************************************************* + * BL1 specific platform actions shared between ARM standard platforms. + ******************************************************************************/ +void arm_bl1_early_platform_setup(void) +{ + +#if !ARM_DISABLE_TRUSTED_WDOG + /* Enable watchdog */ + plat_arm_secure_wdt_start(); +#endif + + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = ARM_BL_RAM_BASE; + bl1_tzram_layout.total_size = ARM_BL_RAM_SIZE; +} + +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + plat_arm_interconnect_enter_coherency(); +} + +/****************************************************************************** + * Perform the very early platform specific architecture setup shared between + * ARM standard platforms. This only does basic initialization. Later + * architectural setup (bl1_arch_setup()) does not do anything platform + * specific. + *****************************************************************************/ +void arm_bl1_plat_arch_setup(void) +{ +#if USE_COHERENT_MEM && !ARM_CRYPTOCELL_INTEG + /* + * Ensure ARM platforms don't use coherent memory in BL1 unless + * cryptocell integration is enabled. + */ + assert((BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE) == 0U); +#endif + + const mmap_region_t bl_regions[] = { + MAP_BL1_TOTAL, + MAP_BL1_RO, +#if USE_ROMLIB + ARM_MAP_ROMLIB_CODE, + ARM_MAP_ROMLIB_DATA, +#endif +#if ARM_CRYPTOCELL_INTEG + ARM_MAP_BL_COHERENT_RAM, +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); +#ifdef __aarch64__ + enable_mmu_el3(0); +#else + enable_mmu_svc_mon(0); +#endif /* __aarch64__ */ + + arm_setup_romlib(); +} + +void bl1_plat_arch_setup(void) +{ + arm_bl1_plat_arch_setup(); +} + +/* + * Perform the platform specific architecture setup shared between + * ARM standard platforms. + */ +void arm_bl1_platform_setup(void) +{ + const struct dyn_cfg_dtb_info_t *fw_config_info; + image_desc_t *desc; + uint32_t fw_config_max_size; + int err = -1; + + /* Initialise the IO layer and register platform IO devices */ + plat_arm_io_setup(); + + /* Check if we need FWU before further processing */ + is_fwu_needed = plat_arm_bl1_fwu_needed(); + if (is_fwu_needed) { + ERROR("Skip platform setup as FWU detected\n"); + return; + } + + /* Set global DTB info for fixed fw_config information */ + fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE; + set_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size, FW_CONFIG_ID); + + /* Fill the device tree information struct with the info from the config dtb */ + err = fconf_load_config(FW_CONFIG_ID); + if (err < 0) { + ERROR("Loading of FW_CONFIG failed %d\n", err); + plat_error_handler(err); + } + + /* + * FW_CONFIG loaded successfully. If FW_CONFIG device tree parsing + * is successful then load TB_FW_CONFIG device tree. + */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + if (fw_config_info != NULL) { + err = fconf_populate_dtb_registry(fw_config_info->config_addr); + if (err < 0) { + ERROR("Parsing of FW_CONFIG failed %d\n", err); + plat_error_handler(err); + } + /* load TB_FW_CONFIG */ + err = fconf_load_config(TB_FW_CONFIG_ID); + if (err < 0) { + ERROR("Loading of TB_FW_CONFIG failed %d\n", err); + plat_error_handler(err); + } + } else { + ERROR("Invalid FW_CONFIG address\n"); + plat_error_handler(err); + } + + /* The BL2 ep_info arg0 is modified to point to FW_CONFIG */ + desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(desc != NULL); + desc->ep_info.args.arg0 = fw_config_info->config_addr; + +#if CRYPTO_SUPPORT + /* Share the Mbed TLS heap info with other images */ + arm_bl1_set_mbedtls_heap(); +#endif /* CRYPTO_SUPPORT */ + + /* + * Allow access to the System counter timer module and program + * counter frequency for non secure images during FWU + */ +#ifdef ARM_SYS_TIMCTL_BASE + arm_configure_sys_timer(); +#endif +#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER) + write_cntfrq_el0(plat_get_syscnt_freq2()); +#endif +} + +void bl1_plat_prepare_exit(entry_point_info_t *ep_info) +{ +#if !ARM_DISABLE_TRUSTED_WDOG + /* Disable watchdog before leaving BL1 */ + plat_arm_secure_wdt_stop(); +#endif + +#ifdef EL3_PAYLOAD_BASE + /* + * Program the EL3 payload's entry point address into the CPUs mailbox + * in order to release secondary CPUs from their holding pen and make + * them jump there. + */ + plat_arm_program_trusted_mailbox(ep_info->pc); + dsbsy(); + sev(); +#endif +} + +/* + * On Arm platforms, the FWU process is triggered when the FIP image has + * been tampered with. + */ +bool plat_arm_bl1_fwu_needed(void) +{ + return !arm_io_is_toc_valid(); +} + +/******************************************************************************* + * The following function checks if Firmware update is needed, + * by checking if TOC in FIP image is valid or not. + ******************************************************************************/ +unsigned int bl1_plat_get_next_image_id(void) +{ + return is_fwu_needed ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID; +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c new file mode 100644 index 0000000..97b5a88 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#pragma weak bl2_el3_early_platform_setup +#pragma weak bl2_el3_plat_arch_setup +#pragma weak bl2_el3_plat_prepare_exit + +#define MAP_BL2_EL3_TOTAL MAP_REGION_FLAT( \ + bl2_el3_tzram_layout.total_base, \ + bl2_el3_tzram_layout.total_size, \ + MT_MEMORY | MT_RW | MT_SECURE) + +static meminfo_t bl2_el3_tzram_layout; + +/* + * Perform arm specific early platform setup. At this moment we only initialize + * the console and the memory layout. + */ +void arm_bl2_el3_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + + /* + * Allow BL2 to see the whole Trusted RAM. This is determined + * statically since we cannot rely on BL1 passing this information + * in the BL2_AT_EL3 case. + */ + bl2_el3_tzram_layout.total_base = ARM_BL_RAM_BASE; + bl2_el3_tzram_layout.total_size = ARM_BL_RAM_SIZE; + + /* Initialise the IO layer and register platform IO devices */ + plat_arm_io_setup(); +} + +void bl2_el3_early_platform_setup(u_register_t arg0 __unused, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) +{ + arm_bl2_el3_early_platform_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + plat_arm_interconnect_enter_coherency(); + + generic_delay_timer_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only initializes the mmu in a quick and dirty way. + ******************************************************************************/ +void arm_bl2_el3_plat_arch_setup(void) +{ + +#if USE_COHERENT_MEM + /* Ensure ARM platforms dont use coherent memory in BL2_AT_EL3 */ + assert(BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE == 0U); +#endif + + const mmap_region_t bl_regions[] = { + MAP_BL2_EL3_TOTAL, + ARM_MAP_BL_RO, + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + +#ifdef __aarch64__ + enable_mmu_el3(0); +#else + enable_mmu_svc_mon(0); +#endif +} + +void bl2_el3_plat_arch_setup(void) +{ + arm_bl2_el3_plat_arch_setup(); +} + +void bl2_el3_plat_prepare_exit(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c new file mode 100644 index 0000000..08c014d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c @@ -0,0 +1,322 @@ +/* + * 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 +#if ENABLE_RME +#include +#endif /* ENABLE_RME */ +#ifdef SPD_opteed +#include +#endif +#include +#if ENABLE_RME +#include +#endif /* ENABLE_RME */ +#include +#include + +/* Data structure which holds the extents of the trusted SRAM for BL2 */ +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/* Base address of fw_config received from BL1 */ +static uintptr_t config_base; + +/* + * Check that BL2_BASE is above ARM_FW_CONFIG_LIMIT. This reserved page is + * for `meminfo_t` data structure and fw_configs passed from BL1. + */ +CASSERT(BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl2_base_overflows); + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak bl2_early_platform_setup2 +#pragma weak bl2_platform_setup +#pragma weak bl2_plat_arch_setup +#pragma weak bl2_plat_sec_mem_layout + +#if ENABLE_RME +#define MAP_BL2_TOTAL MAP_REGION_FLAT( \ + bl2_tzram_layout.total_base, \ + bl2_tzram_layout.total_size, \ + MT_MEMORY | MT_RW | MT_ROOT) +#else +#define MAP_BL2_TOTAL MAP_REGION_FLAT( \ + bl2_tzram_layout.total_base, \ + bl2_tzram_layout.total_size, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* ENABLE_RME */ + +#pragma weak arm_bl2_plat_handle_post_image_load + +/******************************************************************************* + * BL1 has passed the extents of the trusted SRAM that should be visible to BL2 + * in x0. This memory layout is sitting at the base of the free trusted SRAM. + * Copy it to a safe location before its reclaimed by later BL2 functionality. + ******************************************************************************/ +void arm_bl2_early_platform_setup(uintptr_t fw_config, + struct meminfo *mem_layout) +{ + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; + + config_base = fw_config; + + /* Initialise the IO layer and register platform IO devices */ + plat_arm_io_setup(); + + /* Load partition table */ +#if ARM_GPT_SUPPORT + partition_init(GPT_IMAGE_ID); +#endif /* ARM_GPT_SUPPORT */ + +} + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); + + generic_delay_timer_init(); +} + +/* + * Perform BL2 preload setup. Currently we initialise the dynamic + * configuration here. + */ +void bl2_plat_preload_setup(void) +{ + arm_bl2_dyn_cfg_init(); + +#if ARM_GPT_SUPPORT && !PSA_FWU_SUPPORT + /* Always use the FIP from bank 0 */ + arm_set_fip_addr(0U); +#endif /* ARM_GPT_SUPPORT && !PSA_FWU_SUPPORT */ +} + +/* + * Perform ARM standard platform setup. + */ +void arm_bl2_platform_setup(void) +{ +#if !ENABLE_RME + /* Initialize the secure environment */ + plat_arm_security_setup(); +#endif + +#if defined(PLAT_ARM_MEM_PROT_ADDR) + arm_nor_psci_do_static_mem_protect(); +#endif +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); +} + +#if ENABLE_RME + +static void arm_bl2_plat_gpt_setup(void) +{ + /* + * The GPT library might modify the gpt regions structure to optimize + * the layout, so the array cannot be constant. + */ + pas_region_t pas_regions[] = { + ARM_PAS_KERNEL, + ARM_PAS_SECURE, + ARM_PAS_REALM, + ARM_PAS_EL3_DRAM, + ARM_PAS_GPTS + }; + + /* Initialize entire protected space to GPT_GPI_ANY. */ + if (gpt_init_l0_tables(GPCCR_PPS_4GB, ARM_L0_GPT_ADDR_BASE, + ARM_L0_GPT_SIZE) < 0) { + ERROR("gpt_init_l0_tables() failed!\n"); + panic(); + } + + /* Carve out defined PAS ranges. */ + if (gpt_init_pas_l1_tables(GPCCR_PGS_4K, + ARM_L1_GPT_ADDR_BASE, + ARM_L1_GPT_SIZE, + pas_regions, + (unsigned int)(sizeof(pas_regions) / + sizeof(pas_region_t))) < 0) { + ERROR("gpt_init_pas_l1_tables() failed!\n"); + panic(); + } + + INFO("Enabling Granule Protection Checks\n"); + if (gpt_enable() < 0) { + ERROR("gpt_enable() failed!\n"); + panic(); + } +} + +#endif /* ENABLE_RME */ + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. + * When RME is enabled the secure environment is initialised before + * initialising and enabling Granule Protection. + * This function initialises the MMU in a quick and dirty way. + ******************************************************************************/ +void arm_bl2_plat_arch_setup(void) +{ +#if USE_COHERENT_MEM && !ARM_CRYPTOCELL_INTEG + /* + * Ensure ARM platforms don't use coherent memory in BL2 unless + * cryptocell integration is enabled. + */ + assert((BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE) == 0U); +#endif + + const mmap_region_t bl_regions[] = { + MAP_BL2_TOTAL, + ARM_MAP_BL_RO, +#if USE_ROMLIB + ARM_MAP_ROMLIB_CODE, + ARM_MAP_ROMLIB_DATA, +#endif +#if ARM_CRYPTOCELL_INTEG + ARM_MAP_BL_COHERENT_RAM, +#endif + ARM_MAP_BL_CONFIG_REGION, +#if ENABLE_RME + ARM_MAP_L0_GPT_REGION, +#endif + {0} + }; + +#if ENABLE_RME + /* Initialise the secure environment */ + plat_arm_security_setup(); +#endif + setup_page_tables(bl_regions, plat_arm_get_mmap()); + +#ifdef __aarch64__ +#if ENABLE_RME + /* BL2 runs in EL3 when RME enabled. */ + assert(get_armv9_2_feat_rme_support() != 0U); + enable_mmu_el3(0); + + /* Initialise and enable granule protection after MMU. */ + arm_bl2_plat_gpt_setup(); +#else + enable_mmu_el1(0); +#endif +#else + enable_mmu_svc_mon(0); +#endif + + arm_setup_romlib(); +} + +void bl2_plat_arch_setup(void) +{ + const struct dyn_cfg_dtb_info_t *tb_fw_config_info; + + arm_bl2_plat_arch_setup(); + + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", config_base); + + /* TB_FW_CONFIG was also loaded by BL1 */ + tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID); + assert(tb_fw_config_info != NULL); + + fconf_populate("TB_FW", tb_fw_config_info->config_addr); +} + +int arm_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif + assert(bl_mem_params != NULL); + + switch (image_id) { +#ifdef __aarch64__ + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } +#endif + bl_mem_params->ep_info.spsr = arm_get_spsr_for_bl32_entry(); + break; +#endif + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = arm_get_spsr_for_bl33_entry(); + break; + +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = plat_arm_bl2_handle_scp_bl2(&bl_mem_params->image_info); + if (err) { + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + } + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int arm_bl2_plat_handle_post_image_load(unsigned int image_id) +{ +#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD + /* For Secure Partitions we don't need post processing */ + if ((image_id >= (MAX_NUMBER_IDS - MAX_SP_IDS)) && + (image_id < MAX_NUMBER_IDS)) { + return 0; + } +#endif + return arm_bl2_handle_post_image_load(image_id); +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return arm_bl2_plat_handle_post_image_load(image_id); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c new file mode 100644 index 0000000..3614c7d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak bl2u_platform_setup +#pragma weak bl2u_early_platform_setup +#pragma weak bl2u_plat_arch_setup + +#define MAP_BL2U_TOTAL MAP_REGION_FLAT( \ + BL2U_BASE, \ + BL2U_LIMIT - BL2U_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Perform ARM standard platform setup for BL2U + */ +void arm_bl2u_platform_setup(void) +{ + /* Initialize the secure environment */ + plat_arm_security_setup(); +} + +void bl2u_platform_setup(void) +{ + arm_bl2u_platform_setup(); +} + +void arm_bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info) +{ + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + + generic_delay_timer_init(); +} + +/******************************************************************************* + * BL1 can pass platform dependent information to BL2U in x1. + * In case of ARM CSS platforms x1 contains SCP_BL2U image info. + * In case of ARM FVP platforms x1 is not used. + * In both cases, x0 contains the extents of the memory available to BL2U + ******************************************************************************/ +void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info) +{ + arm_bl2u_early_platform_setup(mem_layout, plat_info); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only initializes the mmu in a quick and dirty way. + * The memory that is used by BL2U is only mapped. + ******************************************************************************/ +void arm_bl2u_plat_arch_setup(void) +{ + +#if USE_COHERENT_MEM + /* Ensure ARM platforms dont use coherent memory in BL2U */ + assert((BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE) == 0U); +#endif + + const mmap_region_t bl_regions[] = { + MAP_BL2U_TOTAL, + ARM_MAP_BL_RO, +#if USE_ROMLIB + ARM_MAP_ROMLIB_CODE, + ARM_MAP_ROMLIB_DATA, +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + +#ifdef __aarch64__ + enable_mmu_el1(0); +#else + enable_mmu_svc_mon(0); +#endif + arm_setup_romlib(); +} + +void bl2u_plat_arch_setup(void) +{ + arm_bl2u_plat_arch_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c new file mode 100644 index 0000000..a6f7df5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c @@ -0,0 +1,427 @@ +/* + * 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 +#if ENABLE_RME +#include +#endif +#include +#include +#include +#include +#include + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; +#if ENABLE_RME +static entry_point_info_t rmm_image_ep_info; +#endif + +#if !RESET_TO_BL31 +/* + * Check that BL31_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page + * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2. + */ +CASSERT(BL31_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl31_base_overflows); +#endif + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak bl31_early_platform_setup2 +#pragma weak bl31_platform_setup +#pragma weak bl31_plat_arch_setup +#pragma weak bl31_plat_get_next_image_ep_info + +#define MAP_BL31_TOTAL MAP_REGION_FLAT( \ + BL31_START, \ + BL31_END - BL31_START, \ + MT_MEMORY | MT_RW | EL3_PAS) +#if RECLAIM_INIT_CODE +IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE); +IMPORT_SYM(unsigned long, __INIT_CODE_END__, BL_CODE_END_UNALIGNED); +IMPORT_SYM(unsigned long, __STACKS_END__, BL_STACKS_END_UNALIGNED); + +#define BL_INIT_CODE_END ((BL_CODE_END_UNALIGNED + PAGE_SIZE - 1) & \ + ~(PAGE_SIZE - 1)) +#define BL_STACKS_END ((BL_STACKS_END_UNALIGNED + PAGE_SIZE - 1) & \ + ~(PAGE_SIZE - 1)) + +#define MAP_BL_INIT_CODE MAP_REGION_FLAT( \ + BL_INIT_CODE_BASE, \ + BL_INIT_CODE_END \ + - BL_INIT_CODE_BASE, \ + MT_CODE | EL3_PAS) +#endif + +#if SEPARATE_NOBITS_REGION +#define MAP_BL31_NOBITS MAP_REGION_FLAT( \ + BL31_NOBITS_BASE, \ + BL31_NOBITS_LIMIT \ + - BL31_NOBITS_BASE, \ + MT_MEMORY | MT_RW | EL3_PAS) + +#endif +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for the + * security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + if (type == NON_SECURE) { + next_image_info = &bl33_image_ep_info; + } +#if ENABLE_RME + else if (type == REALM) { + next_image_info = &rmm_image_ep_info; + } +#endif + else { + next_image_info = &bl32_image_ep_info; + } + + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Perform any BL31 early platform setup common to ARM standard platforms. + * Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be + * done before the MMU is initialized so that the memory layout can be used + * while creating page tables. BL2 has flushed this information to memory, so + * we are guaranteed to pick up good data. + ******************************************************************************/ +void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config, + uintptr_t hw_config, void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + +#if RESET_TO_BL31 + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + +# ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry(); + +#if defined(SPD_spmd) + /* SPM (hafnium in secure world) expects SPM Core manifest base address + * in x0, which in !RESET_TO_BL31 case loaded after base of non shared + * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non + * shared SRAM is allocated to BL31, so to avoid overwriting of manifest + * keep it in the last page. + */ + bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE + + PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE; +#endif + +# endif /* BL32_BASE */ + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + + bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#else /* RESET_TO_BL31 */ + + /* + * In debug builds, we pass a special value in 'plat_params_from_bl2' + * to verify platform parameters from BL2 to BL31. + * In release builds, it's not used. + */ + assert(((unsigned long long)plat_params_from_bl2) == + ARM_BL31_PLAT_PARAM_VAL); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33, BL32 and RMM (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params != NULL) { + if (bl_params->image_id == BL32_IMAGE_ID) { + bl32_image_ep_info = *bl_params->ep_info; + } +#if ENABLE_RME + else if (bl_params->image_id == RMM_IMAGE_ID) { + rmm_image_ep_info = *bl_params->ep_info; + } +#endif + else if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + } + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0U) + panic(); +#if ENABLE_RME + if (rmm_image_ep_info.pc == 0U) + panic(); +#endif +#endif /* RESET_TO_BL31 */ + +# if ARM_LINUX_KERNEL_AS_BL33 + /* + * According to the file ``Documentation/arm64/booting.txt`` of the + * Linux kernel tree, Linux expects the physical address of the device + * tree blob (DTB) in x0, while x1-x3 are reserved for future use and + * must be 0. + * Repurpose the option to load Hafnium hypervisor in the normal world. + * It expects its manifest address in x0. This is essentially the linux + * dts (passed to the primary VM) by adding 'hypervisor' and chosen + * nodes specifying the Hypervisor configuration. + */ +#if RESET_TO_BL31 + bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE; +#else + bl33_image_ep_info.args.arg0 = (u_register_t)hw_config; +#endif + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = 0U; + bl33_image_ep_info.args.arg3 = 0U; +# endif +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * Platform specific PSCI code will enable coherency for other + * clusters. + */ + plat_arm_interconnect_enter_coherency(); +} + +/******************************************************************************* + * Perform any BL31 platform setup common to ARM standard platforms + ******************************************************************************/ +void arm_bl31_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + plat_arm_gic_driver_init(); + plat_arm_gic_init(); + +#if RESET_TO_BL31 + /* + * Do initial security configuration to allow DRAM/device access + * (if earlier BL has not already done so). + */ + plat_arm_security_setup(); + +#if defined(PLAT_ARM_MEM_PROT_ADDR) + arm_nor_psci_do_dyn_mem_protect(); +#endif /* PLAT_ARM_MEM_PROT_ADDR */ + +#endif /* RESET_TO_BL31 */ + + /* Enable and initialize the System level generic timer */ + mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0U) | CNTCR_EN); + + /* Allow access to the System counter timer module */ + arm_configure_sys_timer(); + + /* Initialize power controller before setting up topology */ + plat_arm_pwrc_setup(); + +#if RAS_EXTENSION + ras_init(); +#endif + +#if USE_DEBUGFS + debugfs_init(); +#endif /* USE_DEBUGFS */ +} + +/******************************************************************************* + * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM + * standard platforms + * Perform BL31 platform setup + ******************************************************************************/ +void arm_bl31_plat_runtime_setup(void) +{ + console_switch_state(CONSOLE_FLAG_RUNTIME); + + /* Initialize the runtime console */ + arm_console_runtime_init(); + +#if RECLAIM_INIT_CODE + arm_free_init_memory(); +#endif + +#if PLAT_RO_XLAT_TABLES + arm_xlat_make_tables_readonly(); +#endif +} + +#if RECLAIM_INIT_CODE +/* + * Make memory for image boot time code RW to reclaim it as stack for the + * secondary cores, or RO where it cannot be reclaimed: + * + * |-------- INIT SECTION --------| + * ----------------------------------------- + * | CORE 0 | CORE 1 | CORE 2 | EXTRA | + * | STACK | STACK | STACK | SPACE | + * ----------------------------------------- + * <-------------------> <------> + * MAKE RW AND XN MAKE + * FOR STACKS RO AND XN + */ +void arm_free_init_memory(void) +{ + int ret = 0; + + if (BL_STACKS_END < BL_INIT_CODE_END) { + /* Reclaim some of the init section as stack if possible. */ + if (BL_INIT_CODE_BASE < BL_STACKS_END) { + ret |= xlat_change_mem_attributes(BL_INIT_CODE_BASE, + BL_STACKS_END - BL_INIT_CODE_BASE, + MT_RW_DATA); + } + /* Make the rest of the init section read-only. */ + ret |= xlat_change_mem_attributes(BL_STACKS_END, + BL_INIT_CODE_END - BL_STACKS_END, + MT_RO_DATA); + } else { + /* The stacks cover the init section, so reclaim it all. */ + ret |= xlat_change_mem_attributes(BL_INIT_CODE_BASE, + BL_INIT_CODE_END - BL_INIT_CODE_BASE, + MT_RW_DATA); + } + + if (ret != 0) { + ERROR("Could not reclaim initialization code"); + panic(); + } +} +#endif + +void __init bl31_platform_setup(void) +{ + arm_bl31_platform_setup(); +} + +void bl31_plat_runtime_setup(void) +{ + arm_bl31_plat_runtime_setup(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup shared between + * ARM standard platforms. This only does basic initialization. Later + * architectural setup (bl31_arch_setup()) does not do anything platform + * specific. + ******************************************************************************/ +void __init arm_bl31_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_BL31_TOTAL, +#if ENABLE_RME + ARM_MAP_L0_GPT_REGION, +#endif +#if RECLAIM_INIT_CODE + MAP_BL_INIT_CODE, +#endif +#if SEPARATE_NOBITS_REGION + MAP_BL31_NOBITS, +#endif + ARM_MAP_BL_RO, +#if USE_ROMLIB + ARM_MAP_ROMLIB_CODE, + ARM_MAP_ROMLIB_DATA, +#endif +#if USE_COHERENT_MEM + ARM_MAP_BL_COHERENT_RAM, +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + + enable_mmu_el3(0); + +#if ENABLE_RME + /* + * Initialise Granule Protection library and enable GPC for the primary + * processor. The tables have already been initialized by a previous BL + * stage, so there is no need to provide any PAS here. This function + * sets up pointers to those tables. + */ + if (gpt_runtime_init() < 0) { + ERROR("gpt_runtime_init() failed!\n"); + panic(); + } +#endif /* ENABLE_RME */ + + arm_setup_romlib(); +} + +void __init bl31_plat_arch_setup(void) +{ + arm_bl31_plat_arch_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_cci.c b/arm-trusted-firmware/plat/arm/common/arm_cci.c new file mode 100644 index 0000000..3795fc5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_cci.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +static const int cci_map[] = { + PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX +}; + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way ARM CCI driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_arm_interconnect_init +#pragma weak plat_arm_interconnect_enter_coherency +#pragma weak plat_arm_interconnect_exit_coherency + + +/****************************************************************************** + * Helper function to initialize ARM CCI driver. + *****************************************************************************/ +void __init plat_arm_interconnect_init(void) +{ + cci_init(PLAT_ARM_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_ccn.c b/arm-trusted-firmware/plat/arm/common/arm_ccn.c new file mode 100644 index 0000000..2e681ca --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_ccn.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static const unsigned char master_to_rn_id_map[] = { + PLAT_ARM_CLUSTER_TO_CCN_ID_MAP +}; + +static const ccn_desc_t arm_ccn_desc = { + .periphbase = PLAT_ARM_CCN_BASE, + .num_masters = ARRAY_SIZE(master_to_rn_id_map), + .master_to_rn_id_map = master_to_rn_id_map +}; + +CASSERT(PLAT_ARM_CLUSTER_COUNT == ARRAY_SIZE(master_to_rn_id_map), + assert_invalid_cluster_count_for_ccn_variant); + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way ARM CCN driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_arm_interconnect_init +#pragma weak plat_arm_interconnect_enter_coherency +#pragma weak plat_arm_interconnect_exit_coherency + + +/****************************************************************************** + * Helper function to initialize ARM CCN driver. + *****************************************************************************/ +void __init plat_arm_interconnect_init(void) +{ + ccn_init(&arm_ccn_desc); +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ + ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ + ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_common.c b/arm-trusted-firmware/plat/arm/common/arm_common.c new file mode 100644 index 0000000..946b732 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_common.c @@ -0,0 +1,239 @@ +/* + * 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 + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak plat_get_ns_image_entrypoint +#pragma weak plat_arm_get_mmap + +/* Conditionally provide a weak definition of plat_get_syscnt_freq2 to avoid + * conflicts with the definition in plat/common. */ +#pragma weak plat_get_syscnt_freq2 + +/* Get ARM SOC-ID */ +#pragma weak plat_arm_get_soc_id + +/******************************************************************************* + * Changes the memory attributes for the region of mapped memory where the BL + * image's translation tables are located such that the tables will have + * read-only permissions. + ******************************************************************************/ +#if PLAT_RO_XLAT_TABLES +void arm_xlat_make_tables_readonly(void) +{ + int rc = xlat_make_tables_readonly(); + + if (rc != 0) { + ERROR("Failed to make translation tables read-only at EL%u.\n", + get_current_el()); + panic(); + } + + INFO("Translation tables are now read-only at EL%u.\n", + get_current_el()); +} +#endif + +void arm_setup_romlib(void) +{ +#if USE_ROMLIB + if (!rom_lib_init(ROMLIB_VERSION)) + panic(); +#endif +} + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_ARM_NS_IMAGE_BASE; +#endif +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t arm_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifdef __aarch64__ +uint32_t arm_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +uint32_t arm_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* __aarch64__ */ + +/******************************************************************************* + * Configures access to the system counter timer module. + ******************************************************************************/ +#ifdef ARM_SYS_TIMCTL_BASE +void arm_configure_sys_timer(void) +{ + unsigned int reg_val; + + /* Read the frequency of the system counter */ + unsigned int freq_val = plat_get_syscnt_freq2(); + +#if ARM_CONFIG_CNTACR + reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT); + reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT); + reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT); + mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTACR_BASE(PLAT_ARM_NSTIMER_FRAME_ID), reg_val); +#endif /* ARM_CONFIG_CNTACR */ + + reg_val = (1U << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID)); + mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val); + + /* + * Initialize CNTFRQ register in CNTCTLBase frame. The CNTFRQ + * system register initialized during psci_arch_setup() is different + * from this and has to be updated independently. + */ + mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val); + +#if defined(PLAT_juno) || defined(PLAT_n1sdp) || defined(PLAT_morello) + /* + * Initialize CNTFRQ register in Non-secure CNTBase frame. + * This is required for Juno, N1SDP and Morello because they do not + * follow ARM ARM in that the value updated in CNTFRQ is not + * reflected in CNTBASEN_CNTFRQ. Hence update the value manually. + */ + mmio_write_32(ARM_SYS_CNT_BASE_NS + CNTBASEN_CNTFRQ, freq_val); +#endif +} +#endif /* ARM_SYS_TIMCTL_BASE */ + +/******************************************************************************* + * Returns ARM platform specific memory map regions. + ******************************************************************************/ +const mmap_region_t *plat_arm_get_mmap(void) +{ + return plat_arm_mmap; +} + +#ifdef ARM_SYS_CNTCTL_BASE + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + + /* Read the frequency from Frequency modes table */ + counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF); + + /* The first entry of the frequency modes table must not be 0 */ + if (counter_base_frequency == 0U) + panic(); + + return counter_base_frequency; +} + +#endif /* ARM_SYS_CNTCTL_BASE */ + +#if SDEI_SUPPORT +/* + * Translate SDEI entry point to PA, and perform standard ARM entry point + * validation on it. + */ +int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) +{ + uint64_t par, pa; + u_register_t scr_el3; + + /* Doing Non-secure address translation requires SCR_EL3.NS set */ + scr_el3 = read_scr_el3(); + write_scr_el3(scr_el3 | SCR_NS_BIT); + isb(); + + assert((client_mode == MODE_EL2) || (client_mode == MODE_EL1)); + if (client_mode == MODE_EL2) { + /* + * Translate entry point to Physical Address using the EL2 + * translation regime. + */ + ats1e2r(ep); + } else { + /* + * Translate entry point to Physical Address using the EL1&0 + * translation regime, including stage 2. + */ + AT(ats12e1r, ep); + } + isb(); + par = read_par_el1(); + + /* Restore original SCRL_EL3 */ + write_scr_el3(scr_el3); + isb(); + + /* If the translation resulted in fault, return failure */ + if ((par & PAR_F_MASK) != 0) + return -1; + + /* Extract Physical Address from PAR */ + pa = (par & (PAR_ADDR_MASK << PAR_ADDR_SHIFT)); + + /* Perform NS entry point validation on the physical address */ + return arm_validate_ns_entrypoint(pa); +} +#endif + diff --git a/arm-trusted-firmware/plat/arm/common/arm_common.mk b/arm-trusted-firmware/plat/arm/common/arm_common.mk new file mode 100644 index 0000000..6d7aa2d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_common.mk @@ -0,0 +1,429 @@ +# +# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +ifeq (${ARCH}, aarch64) + # On ARM standard platorms, the TSP can execute from Trusted SRAM, Trusted + # DRAM (if available) or the TZC secured area of DRAM. + # TZC secured DRAM is the default. + + ARM_TSP_RAM_LOCATION ?= dram + + ifeq (${ARM_TSP_RAM_LOCATION}, tsram) + ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID + else ifeq (${ARM_TSP_RAM_LOCATION}, tdram) + ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_DRAM_ID + else ifeq (${ARM_TSP_RAM_LOCATION}, dram) + ARM_TSP_RAM_LOCATION_ID = ARM_DRAM_ID + else + $(error "Unsupported ARM_TSP_RAM_LOCATION value") + endif + + # Process flags + # Process ARM_BL31_IN_DRAM flag + ARM_BL31_IN_DRAM := 0 + $(eval $(call assert_boolean,ARM_BL31_IN_DRAM)) + $(eval $(call add_define,ARM_BL31_IN_DRAM)) +else + ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID +endif + +$(eval $(call add_define,ARM_TSP_RAM_LOCATION_ID)) + + +# For the original power-state parameter format, the State-ID can be encoded +# according to the recommended encoding or zero. This flag determines which +# State-ID encoding to be parsed. +ARM_RECOM_STATE_ID_ENC := 0 + +# If the PSCI_EXTENDED_STATE_ID is set, then ARM_RECOM_STATE_ID_ENC need to +# be set. Else throw a build error. +ifeq (${PSCI_EXTENDED_STATE_ID}, 1) + ifeq (${ARM_RECOM_STATE_ID_ENC}, 0) + $(error Build option ARM_RECOM_STATE_ID_ENC needs to be set if \ + PSCI_EXTENDED_STATE_ID is set for ARM platforms) + endif +endif + +# Process ARM_RECOM_STATE_ID_ENC flag +$(eval $(call assert_boolean,ARM_RECOM_STATE_ID_ENC)) +$(eval $(call add_define,ARM_RECOM_STATE_ID_ENC)) + +# Process ARM_DISABLE_TRUSTED_WDOG flag +# By default, Trusted Watchdog is always enabled unless +# SPIN_ON_BL1_EXIT or ENABLE_RME is set +ARM_DISABLE_TRUSTED_WDOG := 0 +ifneq ($(filter 1,${SPIN_ON_BL1_EXIT} ${ENABLE_RME}),) +ARM_DISABLE_TRUSTED_WDOG := 1 +endif +$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG)) + +# Process ARM_CONFIG_CNTACR +ARM_CONFIG_CNTACR := 1 +$(eval $(call assert_boolean,ARM_CONFIG_CNTACR)) +$(eval $(call add_define,ARM_CONFIG_CNTACR)) + +# Process ARM_BL31_IN_DRAM flag +ARM_BL31_IN_DRAM := 0 +$(eval $(call assert_boolean,ARM_BL31_IN_DRAM)) +$(eval $(call add_define,ARM_BL31_IN_DRAM)) + +# Process ARM_PLAT_MT flag +ARM_PLAT_MT := 0 +$(eval $(call assert_boolean,ARM_PLAT_MT)) +$(eval $(call add_define,ARM_PLAT_MT)) + +# Use translation tables library v2 by default +ARM_XLAT_TABLES_LIB_V1 := 0 +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) + +# Don't have the Linux kernel as a BL33 image by default +ARM_LINUX_KERNEL_AS_BL33 := 0 +$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33)) +$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33)) + +ifeq (${ARM_LINUX_KERNEL_AS_BL33},1) + ifneq (${ARCH},aarch64) + ifneq (${RESET_TO_SP_MIN},1) + $(error "ARM_LINUX_KERNEL_AS_BL33 is only available if RESET_TO_SP_MIN=1.") + endif + endif + ifndef PRELOADED_BL33_BASE + $(error "PRELOADED_BL33_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.") + endif + ifeq (${RESET_TO_BL31},1) + ifndef ARM_PRELOADED_DTB_BASE + $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is + used with RESET_TO_BL31.") + endif + $(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) + endif +endif + +# Arm Ethos-N NPU SiP service +ARM_ETHOSN_NPU_DRIVER := 0 +$(eval $(call assert_boolean,ARM_ETHOSN_NPU_DRIVER)) +$(eval $(call add_define,ARM_ETHOSN_NPU_DRIVER)) + +# Use an implementation of SHA-256 with a smaller memory footprint but reduced +# speed. +$(eval $(call add_define,MBEDTLS_SHA256_SMALLER)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) +endif + +# Enable PSCI_STAT_COUNT/RESIDENCY APIs on ARM platforms +ENABLE_PSCI_STAT := 1 +ENABLE_PMF := 1 + +# Override the standard libc with optimised libc_asm +OVERRIDE_LIBC := 1 +ifeq (${OVERRIDE_LIBC},1) + include lib/libc/libc_asm.mk +endif + +# On ARM platforms, separate the code and read-only data sections to allow +# mapping the former as executable and the latter as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# On ARM platforms, disable SEPARATE_NOBITS_REGION by default. Both PROGBITS +# and NOBITS sections of BL31 image are adjacent to each other and loaded +# into Trusted SRAM. +SEPARATE_NOBITS_REGION := 0 + +# In order to support SEPARATE_NOBITS_REGION for Arm platforms, we need to load +# BL31 PROGBITS into secure DRAM space and BL31 NOBITS into SRAM. Hence mandate +# the build to require that ARM_BL31_IN_DRAM is enabled as well. +ifeq ($(SEPARATE_NOBITS_REGION),1) + ifneq ($(ARM_BL31_IN_DRAM),1) + $(error For SEPARATE_NOBITS_REGION, ARM_BL31_IN_DRAM must be enabled) + endif + ifneq ($(RECLAIM_INIT_CODE),0) + $(error For SEPARATE_NOBITS_REGION, RECLAIM_INIT_CODE cannot be supported) + endif +endif + +# Disable ARM Cryptocell by default +ARM_CRYPTOCELL_INTEG := 0 +$(eval $(call assert_boolean,ARM_CRYPTOCELL_INTEG)) +$(eval $(call add_define,ARM_CRYPTOCELL_INTEG)) + +# Enable PIE support for RESET_TO_BL31/RESET_TO_SP_MIN case +ifneq ($(filter 1,${RESET_TO_BL31} ${RESET_TO_SP_MIN}),) + ENABLE_PIE := 1 +endif + +# CryptoCell integration relies on coherent buffers for passing data from +# the AP CPU to the CryptoCell +ifeq (${ARM_CRYPTOCELL_INTEG},1) + ifeq (${USE_COHERENT_MEM},0) + $(error "ARM_CRYPTOCELL_INTEG needs USE_COHERENT_MEM to be set.") + endif +endif + +# Disable GPT parser support, use FIP image by default +ARM_GPT_SUPPORT := 0 +$(eval $(call assert_boolean,ARM_GPT_SUPPORT)) +$(eval $(call add_define,ARM_GPT_SUPPORT)) + +# Include necessary sources to parse GPT image +ifeq (${ARM_GPT_SUPPORT}, 1) + BL2_SOURCES += drivers/partition/gpt.c \ + drivers/partition/partition.c +endif + +# Enable CRC instructions via extension for ARMv8-A CPUs. +# For ARMv8.1-A, and onwards CRC instructions are default enabled. +# Enable HW computed CRC support unconditionally in BL2 component. +ifeq (${ARM_ARCH_MINOR},0) + BL2_CPPFLAGS += -march=armv8-a+crc +endif + +ifeq ($(PSA_FWU_SUPPORT),1) + # GPT support is recommended as per PSA FWU specification hence + # PSA FWU implementation is tightly coupled with GPT support, + # and it does not support other formats. + ifneq ($(ARM_GPT_SUPPORT),1) + $(error For PSA_FWU_SUPPORT, ARM_GPT_SUPPORT must be enabled) + endif + FWU_MK := drivers/fwu/fwu.mk + $(info Including ${FWU_MK}) + include ${FWU_MK} +endif + +ifeq (${ARCH}, aarch64) +PLAT_INCLUDES += -Iinclude/plat/arm/common/aarch64 +endif + +PLAT_BL_COMMON_SOURCES += plat/arm/common/${ARCH}/arm_helpers.S \ + plat/arm/common/arm_common.c \ + plat/arm/common/arm_console.c + +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) +PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/${ARCH}/xlat_tables.c +else +ifeq (${XLAT_MPU_LIB_V1}, 1) +include lib/xlat_mpu/xlat_mpu.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_MPU_LIB_V1_SRCS} +else +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} +endif +endif + +ARM_IO_SOURCES += plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c +ifeq (${SPD},spmd) + ifeq (${BL2_ENABLE_SP_LOAD},1) + ARM_IO_SOURCES += plat/arm/common/fconf/arm_fconf_sp.c + endif +endif + +BL1_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + ${ARM_IO_SOURCES} + +ifdef EL3_PAYLOAD_BASE +# Need the plat_arm_program_trusted_mailbox() function to release secondary CPUs from +# their holding pen +BL1_SOURCES += plat/arm/common/arm_pm.c +endif + +BL2_SOURCES += drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl2_setup.c \ + plat/arm/common/arm_err.c \ + common/tf_crc32.c \ + ${ARM_IO_SOURCES} + +# Firmware Configuration Framework sources +include lib/fconf/fconf.mk + +BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} +BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} + +# Add `libfdt` and Arm common helpers required for Dynamic Config +include lib/libfdt/libfdt.mk + +DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \ + plat/arm/common/arm_dyn_cfg_helpers.c \ + common/uuid.c + +DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES} + +BL1_SOURCES += ${DYN_CFG_SOURCES} +BL2_SOURCES += ${DYN_CFG_SOURCES} + +ifeq (${BL2_AT_EL3},1) +BL2_SOURCES += plat/arm/common/arm_bl2_el3_setup.c +endif + +# Because BL1/BL2 execute in AArch64 mode but BL32 in AArch32 we need to use +# the AArch32 descriptors. +ifeq (${JUNO_AARCH32_EL3_RUNTIME},1) +BL2_SOURCES += plat/arm/common/aarch32/arm_bl2_mem_params_desc.c +else +ifneq (${PLAT}, corstone1000) +BL2_SOURCES += plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c +endif +endif +BL2_SOURCES += plat/arm/common/arm_image_load.c \ + common/desc_image_load.c +ifeq (${SPD},opteed) +BL2_SOURCES += lib/optee/optee_utils.c +endif + +BL2U_SOURCES += drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + plat/arm/common/arm_bl2u_setup.c + +BL31_SOURCES += plat/arm/common/arm_bl31_setup.c \ + plat/arm/common/arm_pm.c \ + plat/arm/common/arm_topology.c \ + plat/common/plat_psci_common.c + +ifneq ($(filter 1,${ENABLE_PMF} ${ARM_ETHOSN_NPU_DRIVER}),) +ARM_SVC_HANDLER_SRCS := + +ifeq (${ENABLE_PMF},1) +ARM_SVC_HANDLER_SRCS += lib/pmf/pmf_smc.c +endif + +ifeq (${ARM_ETHOSN_NPU_DRIVER},1) +ARM_SVC_HANDLER_SRCS += plat/arm/common/fconf/fconf_ethosn_getter.c \ + drivers/delay_timer/delay_timer.c \ + drivers/arm/ethosn/ethosn_smc.c +endif + +ifeq (${ARCH}, aarch64) +BL31_SOURCES += plat/arm/common/aarch64/execution_state_switch.c\ + plat/arm/common/arm_sip_svc.c \ + ${ARM_SVC_HANDLER_SRCS} +else +BL32_SOURCES += plat/arm/common/arm_sip_svc.c \ + ${ARM_SVC_HANDLER_SRCS} +endif +endif + +ifeq (${EL3_EXCEPTION_HANDLING},1) +BL31_SOURCES += plat/common/aarch64/plat_ehf.c +endif + +ifeq (${SDEI_SUPPORT},1) +BL31_SOURCES += plat/arm/common/aarch64/arm_sdei.c +ifeq (${SDEI_IN_FCONF},1) +BL31_SOURCES += plat/arm/common/fconf/fconf_sdei_getter.c +endif +endif + +# RAS sources +ifeq (${RAS_EXTENSION},1) +BL31_SOURCES += lib/extensions/ras/std_err_record.c \ + lib/extensions/ras/ras_common.c +endif + +# Pointer Authentication sources +ifeq (${ENABLE_PAUTH}, 1) +PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c \ + lib/extensions/pauth/pauth_helpers.S +endif + +ifeq (${SPD},spmd) +BL31_SOURCES += plat/common/plat_spmd_manifest.c \ + common/uuid.c \ + ${LIBFDT_SRCS} + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} +endif + +ifneq (${TRUSTED_BOARD_BOOT},0) + + # Include common TBB sources + AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/img_parser_mod.c + + # Include the selected chain of trust sources. + ifeq (${COT},tbbr) + BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \ + drivers/auth/tbbr/tbbr_cot_bl1.c + ifneq (${COT_DESC_IN_DTB},0) + BL2_SOURCES += lib/fconf/fconf_cot_getter.c + else + BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \ + drivers/auth/tbbr/tbbr_cot_bl2.c + endif + else ifeq (${COT},dualroot) + AUTH_SOURCES += drivers/auth/dualroot/cot.c + else + $(error Unknown chain of trust ${COT}) + endif + + BL1_SOURCES += ${AUTH_SOURCES} \ + bl1/tbbr/tbbr_img_desc.c \ + plat/arm/common/arm_bl1_fwu.c \ + plat/common/tbbr/plat_tbbr.c + + BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c + + $(eval $(call TOOL_ADD_IMG,ns_bl2u,--fwu,FWU_)) + + IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk + + $(info Including ${IMG_PARSER_LIB_MK}) + include ${IMG_PARSER_LIB_MK} +endif + +# Include Measured Boot makefile before any Crypto library makefile. +# Crypto library makefile may need default definitions of Measured Boot build +# flags present in Measured Boot makefile. +ifeq (${MEASURED_BOOT},1) + MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk + $(info Including ${MEASURED_BOOT_MK}) + include ${MEASURED_BOOT_MK} + + BL1_SOURCES += ${EVENT_LOG_SOURCES} + BL2_SOURCES += ${EVENT_LOG_SOURCES} +endif + +ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT}),) + CRYPTO_SOURCES := drivers/auth/crypto_mod.c \ + lib/fconf/fconf_tbbr_getter.c + BL1_SOURCES += ${CRYPTO_SOURCES} + BL2_SOURCES += ${CRYPTO_SOURCES} + + # We expect to locate the *.mk files under the directories specified below + ifeq (${ARM_CRYPTOCELL_INTEG},0) + CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk + else + CRYPTO_LIB_MK := drivers/auth/cryptocell/cryptocell_crypto.mk + endif + + $(info Including ${CRYPTO_LIB_MK}) + include ${CRYPTO_LIB_MK} +endif + +ifeq (${RECLAIM_INIT_CODE}, 1) + ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) + $(error "To reclaim init code xlat tables v2 must be used") + endif +endif diff --git a/arm-trusted-firmware/plat/arm/common/arm_console.c b/arm-trusted-firmware/plat/arm/common/arm_console.c new file mode 100644 index 0000000..51830c9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_console.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include + +#pragma weak arm_console_runtime_init +#pragma weak arm_console_runtime_end + +/******************************************************************************* + * Functions that set up the console + ******************************************************************************/ +static console_t arm_boot_console; +static console_t arm_runtime_console; + +/* Initialize the console to provide early debug support */ +void __init arm_console_boot_init(void) +{ + /* If the console was initialized already, don't initialize again */ + if (arm_boot_console.base == PLAT_ARM_BOOT_UART_BASE) { + return; + } + + int rc = console_pl011_register(PLAT_ARM_BOOT_UART_BASE, + PLAT_ARM_BOOT_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE, + &arm_boot_console); + if (rc == 0) { + /* + * The crash console doesn't use the multi console API, it uses + * the core console functions directly. It is safe to call panic + * and let it print debug information. + */ + panic(); + } + + console_set_scope(&arm_boot_console, CONSOLE_FLAG_BOOT); +} + +void arm_console_boot_end(void) +{ + console_flush(); + (void)console_unregister(&arm_boot_console); +} + +/* Initialize the runtime console */ +void arm_console_runtime_init(void) +{ + int rc = console_pl011_register(PLAT_ARM_RUN_UART_BASE, + PLAT_ARM_RUN_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE, + &arm_runtime_console); + if (rc == 0) + panic(); + + console_set_scope(&arm_runtime_console, CONSOLE_FLAG_RUNTIME); +} + +void arm_console_runtime_end(void) +{ + console_flush(); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c b/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c new file mode 100644 index 0000000..7abd1cd --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#if CRYPTO_SUPPORT +#include +#endif /* CRYPTO_SUPPORT */ +#include +#include +#include + +#include +#include + +#if CRYPTO_SUPPORT + +static void *mbedtls_heap_addr; +static size_t mbedtls_heap_size; + +/* + * This function is the implementation of the shared Mbed TLS heap between + * BL1 and BL2 for Arm platforms. The shared heap address is passed from BL1 + * to BL2 with a pointer. This pointer resides inside the TB_FW_CONFIG file + * which is a DTB. + * + * This function is placed inside an #if directive for the below reasons: + * - To allocate space for the Mbed TLS heap --only if-- Trusted Board Boot + * is enabled. + * - This implementation requires the DTB to be present so that BL1 has a + * mechanism to pass the pointer to BL2. + */ +int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + +#if defined(IMAGE_BL1) || BL2_AT_EL3 + + /* If in BL1 or BL2_AT_EL3 define a heap */ + static unsigned char heap[TF_MBEDTLS_HEAP_SIZE]; + + *heap_addr = heap; + *heap_size = sizeof(heap); + mbedtls_heap_addr = heap; + mbedtls_heap_size = sizeof(heap); + +#elif defined(IMAGE_BL2) + + /* If in BL2, retrieve the already allocated heap's info from DTB */ + *heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr); + *heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size); + +#endif + + return 0; +} + +/* + * Puts the shared Mbed TLS heap information to the DTB. + * Executed only from BL1. + */ +void arm_bl1_set_mbedtls_heap(void) +{ + int err; + uintptr_t tb_fw_cfg_dtb; + const struct dyn_cfg_dtb_info_t *tb_fw_config_info; + + /* + * If tb_fw_cfg_dtb==NULL then DTB is not present for the current + * platform. As such, we don't attempt to write to the DTB at all. + * + * If mbedtls_heap_addr==NULL, then it means we are using the default + * heap implementation. As such, BL2 will have its own heap for sure + * and hence there is no need to pass any information to the DTB. + * + * In the latter case, if we still wanted to write in the DTB the heap + * information, we would need to call plat_get_mbedtls_heap to retrieve + * the default heap's address and size. + */ + + tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID); + assert(tb_fw_config_info != NULL); + + tb_fw_cfg_dtb = tb_fw_config_info->config_addr; + + if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) { + /* As libfdt uses void *, we can't avoid this cast */ + void *dtb = (void *)tb_fw_cfg_dtb; + + err = arm_set_dtb_mbedtls_heap_info(dtb, + mbedtls_heap_addr, mbedtls_heap_size); + if (err < 0) { + ERROR("%swrite shared Mbed TLS heap information%s", + "BL1: unable to ", " to DTB\n"); + panic(); + } +#if !MEASURED_BOOT + /* + * Ensure that the info written to the DTB is visible to other + * images. It's critical because BL2 won't be able to proceed + * without the heap info. + * + * In MEASURED_BOOT case flushing is done in a function which + * is called after heap information is written in the DTB. + */ + flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize(dtb)); +#endif /* !MEASURED_BOOT */ + } +} +#endif /* CRYPTO_SUPPORT */ + +/* + * BL2 utility function to initialize dynamic configuration specified by + * FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if + * specified in FW_CONFIG. + */ +void arm_bl2_dyn_cfg_init(void) +{ + unsigned int i; + bl_mem_params_node_t *cfg_mem_params = NULL; + uintptr_t image_base; + uint32_t image_size; + const unsigned int config_ids[] = { + HW_CONFIG_ID, + SOC_FW_CONFIG_ID, + NT_FW_CONFIG_ID, + TOS_FW_CONFIG_ID + }; + + const struct dyn_cfg_dtb_info_t *dtb_info; + + /* Iterate through all the fw config IDs */ + for (i = 0; i < ARRAY_SIZE(config_ids); i++) { + /* Get the config load address and size from TB_FW_CONFIG */ + cfg_mem_params = get_bl_mem_params_node(config_ids[i]); + if (cfg_mem_params == NULL) { + VERBOSE("%sHW_CONFIG in bl_mem_params_node\n", + "Couldn't find "); + continue; + } + + dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]); + if (dtb_info == NULL) { + VERBOSE("%sconfig_id %d load info in TB_FW_CONFIG\n", + "Couldn't find ", config_ids[i]); + continue; + } + + image_base = dtb_info->config_addr; + image_size = dtb_info->config_max_size; + + /* + * Do some runtime checks on the load addresses of soc_fw_config, + * tos_fw_config, nt_fw_config. This is not a comprehensive check + * of all invalid addresses but to prevent trivial porting errors. + */ + if (config_ids[i] != HW_CONFIG_ID) { + + if (check_uptr_overflow(image_base, image_size)) { + continue; + } +#ifdef BL31_BASE + /* Ensure the configs don't overlap with BL31 */ + if ((image_base >= BL31_BASE) && + (image_base <= BL31_LIMIT)) { + continue; + } +#endif + /* Ensure the configs are loaded in a valid address */ + if (image_base < ARM_BL_RAM_BASE) { + continue; + } +#ifdef BL32_BASE + /* + * If BL32 is present, ensure that the configs don't + * overlap with it. + */ + if ((image_base >= BL32_BASE) && + (image_base <= BL32_LIMIT)) { + continue; + } +#endif + } + + cfg_mem_params->image_info.image_base = image_base; + cfg_mem_params->image_info.image_max_size = (uint32_t)image_size; + + /* + * Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from + * HW_CONFIG or FW_CONFIG nodes + */ + cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; + } +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c b/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c new file mode 100644 index 0000000..6a2a6f8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#if MEASURED_BOOT +#include +#endif +#include + +#include +#include +#include + +#include +#include + +#define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr" +#define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size" + +#if MEASURED_BOOT +#ifdef SPD_opteed +/* + * Currently OP-TEE does not support reading DTBs from Secure memory + * and this property should be removed when this feature is supported. + */ +#define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr" +#endif /* SPD_opteed */ +#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr" +#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size" +#endif /* MEASURED_BOOT */ + +/******************************************************************************* + * Validate the tb_fw_config is a valid DTB file and returns the node offset + * to "arm,tb_fw" property. + * Arguments: + * void *dtb - pointer to the TB_FW_CONFIG in memory + * int *node - Returns the node offset to "arm,tb_fw" property if found. + * + * Returns 0 on success and -1 on error. + ******************************************************************************/ +int arm_dyn_tb_fw_cfg_init(void *dtb, int *node) +{ + assert(dtb != NULL); + assert(node != NULL); + + /* Check if the pointer to DT is correct */ + if (fdt_check_header(dtb) != 0) { + WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG"); + return -1; + } + + /* Assert the node offset point to "arm,tb_fw" compatible property */ + *node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"); + if (*node < 0) { + WARN("The compatible property '%s' not%s", "arm,tb_fw", + " found in the config\n"); + return -1; + } + + VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n"); + return 0; +} + +/* + * This function writes the Mbed TLS heap address and size in the DTB. When it + * is called, it is guaranteed that a DTB is available. However it is not + * guaranteed that the shared Mbed TLS heap implementation is used. Thus we + * return error code from here and it's the responsibility of the caller to + * determine the action upon error. + * + * This function is supposed to be called only by BL1. + * + * Returns: + * 0 = success + * -1 = error + */ +int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size) +{ + int dtb_root; + + /* + * Verify that the DTB is valid, before attempting to write to it, + * and get the DTB root node. + */ + int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root); + if (err < 0) { + ERROR("Invalid%s loaded. Unable to get root node\n", + " TB_FW_CONFIG"); + return -1; + } + + /* + * Write the heap address and size in the DTB. + * + * NOTE: The variables heap_addr and heap_size are corrupted + * by the "fdtw_write_inplace_cells" function. After the + * function calls they must NOT be reused. + */ + err = fdtw_write_inplace_cells(dtb, dtb_root, + DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr); + if (err < 0) { + ERROR("%sDTB property '%s'\n", + "Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR); + return -1; + } + + err = fdtw_write_inplace_cells(dtb, dtb_root, + DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size); + if (err < 0) { + ERROR("%sDTB property '%s'\n", + "Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE); + return -1; + } + + return 0; +} + +#if MEASURED_BOOT +/* + * Write the Event Log address and its size in the DTB. + * + * Returns: + * 0 = success + * < 0 = error + */ +static int arm_set_event_log_info(uintptr_t config_base, +#ifdef SPD_opteed + uintptr_t sm_log_addr, +#endif + uintptr_t log_addr, size_t log_size) +{ + /* As libfdt uses void *, we can't avoid this cast */ + void *dtb = (void *)config_base; + const char *compatible = "arm,tpm_event_log"; + int err, node; + + /* + * Verify that the DTB is valid, before attempting to write to it, + * and get the DTB root node. + */ + + /* Check if the pointer to DT is correct */ + err = fdt_check_header(dtb); + if (err < 0) { + WARN("Invalid DTB file passed\n"); + return err; + } + + /* Assert the node offset point to compatible property */ + node = fdt_node_offset_by_compatible(dtb, -1, compatible); + if (node < 0) { + WARN("The compatible property '%s' not%s", compatible, + " found in the config\n"); + return node; + } + + VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n"); + +#ifdef SPD_opteed + if (sm_log_addr != 0UL) { + err = fdtw_write_inplace_cells(dtb, node, + DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr); + if (err < 0) { + ERROR("%sDTB property '%s'\n", + "Unable to write ", DTB_PROP_HW_SM_LOG_ADDR); + return err; + } + } +#endif + err = fdtw_write_inplace_cells(dtb, node, + DTB_PROP_HW_LOG_ADDR, 2, &log_addr); + if (err < 0) { + ERROR("%sDTB property '%s'\n", + "Unable to write ", DTB_PROP_HW_LOG_ADDR); + return err; + } + + err = fdtw_write_inplace_cells(dtb, node, + DTB_PROP_HW_LOG_SIZE, 1, &log_size); + if (err < 0) { + ERROR("%sDTB property '%s'\n", + "Unable to write ", DTB_PROP_HW_LOG_SIZE); + } else { + /* + * Ensure that the info written to the DTB is visible + * to other images. + */ + flush_dcache_range(config_base, fdt_totalsize(dtb)); + } + + return err; +} + +/* + * This function writes the Event Log address and its size + * in the TOS_FW_CONFIG DTB. + * + * This function is supposed to be called only by BL2. + * + * Returns: + * 0 = success + * < 0 = error + */ +int arm_set_tos_fw_info(uintptr_t log_addr, size_t log_size) +{ + uintptr_t config_base; + const bl_mem_params_node_t *cfg_mem_params; + int err; + + assert(log_addr != 0UL); + + /* Get the config load address and size of TOS_FW_CONFIG */ + cfg_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID); + assert(cfg_mem_params != NULL); + + config_base = cfg_mem_params->image_info.image_base; + + /* Write the Event Log address and its size in the DTB */ + err = arm_set_event_log_info(config_base, +#ifdef SPD_opteed + 0UL, +#endif + log_addr, log_size); + if (err < 0) { + ERROR("%sEvent Log data to TOS_FW_CONFIG\n", + "Unable to write "); + } + + return err; +} + +/* + * This function writes the Event Log address and its size + * in the NT_FW_CONFIG DTB. + * + * This function is supposed to be called only by BL2. + * + * Returns: + * 0 = success + * < 0 = error + */ +int arm_set_nt_fw_info( +#ifdef SPD_opteed + uintptr_t log_addr, +#endif + size_t log_size, uintptr_t *ns_log_addr) +{ + uintptr_t config_base; + uintptr_t ns_addr; + const bl_mem_params_node_t *cfg_mem_params; + int err; + + assert(ns_log_addr != NULL); + + /* Get the config load address and size from NT_FW_CONFIG */ + cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); + assert(cfg_mem_params != NULL); + + config_base = cfg_mem_params->image_info.image_base; + + /* Calculate Event Log address in Non-secure memory */ + ns_addr = cfg_mem_params->image_info.image_base + + cfg_mem_params->image_info.image_max_size; + + /* Check for memory space */ + if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) { + return -1; + } + + /* Write the Event Log address and its size in the DTB */ + err = arm_set_event_log_info(config_base, +#ifdef SPD_opteed + log_addr, +#endif + ns_addr, log_size); + + /* Return Event Log address in Non-secure memory */ + *ns_log_addr = (err < 0) ? 0UL : ns_addr; + return err; +} + +/* + * This function writes the Event Log address and its size + * in the TB_FW_CONFIG DTB. + * + * This function is supposed to be called only by BL1. + * + * Returns: + * 0 = success + * < 0 = error + */ +int arm_set_tb_fw_info(uintptr_t log_addr, size_t log_size) +{ + /* + * Read tb_fw_config device tree for Event Log properties + * and write the Event Log address and its size in the DTB + */ + const struct dyn_cfg_dtb_info_t *tb_fw_config_info; + uintptr_t tb_fw_cfg_dtb; + int err; + + tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID); + assert(tb_fw_config_info != NULL); + + tb_fw_cfg_dtb = tb_fw_config_info->config_addr; + + err = arm_set_event_log_info(tb_fw_cfg_dtb, +#ifdef SPD_opteed + 0UL, +#endif + log_addr, log_size); + return err; +} + +/* + * This function reads the Event Log address and its size + * properties present in TB_FW_CONFIG DTB. + * + * This function is supposed to be called only by BL2. + * + * Returns: + * 0 = success + * < 0 = error + * Alongside returns Event Log address and its size. + */ + +int arm_get_tb_fw_info(uint64_t *log_addr, size_t *log_size) +{ + /* As libfdt uses void *, we can't avoid this cast */ + const struct dyn_cfg_dtb_info_t *tb_fw_config_info; + int node, rc; + + tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID); + assert(tb_fw_config_info != NULL); + + void *dtb = (void *)tb_fw_config_info->config_addr; + const char *compatible = "arm,tpm_event_log"; + + /* Assert the node offset point to compatible property */ + node = fdt_node_offset_by_compatible(dtb, -1, compatible); + if (node < 0) { + WARN("The compatible property '%s'%s", compatible, + " not specified in TB_FW config.\n"); + return node; + } + + VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n"); + + rc = fdt_read_uint64(dtb, node, DTB_PROP_HW_LOG_ADDR, log_addr); + if (rc != 0) { + ERROR("%s%s", DTB_PROP_HW_LOG_ADDR, + " not specified in TB_FW config.\n"); + return rc; + } + + rc = fdt_read_uint32(dtb, node, DTB_PROP_HW_LOG_SIZE, (uint32_t *)log_size); + if (rc != 0) { + ERROR("%s%s", DTB_PROP_HW_LOG_SIZE, + " not specified in TB_FW config.\n"); + } + + return rc; +} +#endif /* MEASURED_BOOT */ diff --git a/arm-trusted-firmware/plat/arm/common/arm_err.c b/arm-trusted-firmware/plat/arm/common/arm_err.c new file mode 100644 index 0000000..f80ba78 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_err.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +void __dead2 plat_error_handler(int err) +{ + plat_arm_error_handler(err); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_gicv2.c b/arm-trusted-firmware/plat/arm/common/arm_gicv2.c new file mode 100644 index 0000000..80a845f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_gicv2.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way the GICv2 driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_arm_gic_driver_init +#pragma weak plat_arm_gic_init +#pragma weak plat_arm_gic_cpuif_enable +#pragma weak plat_arm_gic_cpuif_disable +#pragma weak plat_arm_gic_pcpu_init + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t arm_interrupt_props[] = { + PLAT_ARM_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_ARM_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const gicv2_driver_data_t arm_gic_data = { + .gicd_base = PLAT_ARM_GICD_BASE, + .gicc_base = PLAT_ARM_GICC_BASE, + .interrupt_props = arm_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(arm_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/****************************************************************************** + * ARM common helper to initialize the GICv2 only driver. + *****************************************************************************/ +void plat_arm_gic_driver_init(void) +{ + gicv2_driver_init(&arm_gic_data); +} + +void plat_arm_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * ARM common helper to enable the GICv2 CPU interface + *****************************************************************************/ +void plat_arm_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * ARM common helper to disable the GICv2 CPU interface + *****************************************************************************/ +void plat_arm_gic_cpuif_disable(void) +{ + gicv2_cpuif_disable(); +} + +/****************************************************************************** + * ARM common helper to initialize the per cpu distributor interface in GICv2 + *****************************************************************************/ +void plat_arm_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); +} + +/****************************************************************************** + * Stubs for Redistributor power management. Although GICv2 doesn't have + * Redistributor interface, these are provided for the sake of uniform GIC API + *****************************************************************************/ +void plat_arm_gic_redistif_on(void) +{ + return; +} + +void plat_arm_gic_redistif_off(void) +{ + return; +} + + +/****************************************************************************** + * ARM common helper to save & restore the GICv3 on resume from system suspend. + * The normal world currently takes care of saving and restoring the GICv2 + * registers due to legacy reasons. Hence we just initialize the Distributor + * on resume from system suspend. + *****************************************************************************/ +void plat_arm_gic_save(void) +{ + return; +} + +void plat_arm_gic_resume(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_gicv3.c b/arm-trusted-firmware/plat/arm/common/arm_gicv3.c new file mode 100644 index 0000000..4a3a22e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_gicv3.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way the GICv3 driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_arm_gic_driver_init +#pragma weak plat_arm_gic_init +#pragma weak plat_arm_gic_cpuif_enable +#pragma weak plat_arm_gic_cpuif_disable +#pragma weak plat_arm_gic_pcpu_init +#pragma weak plat_arm_gic_redistif_on +#pragma weak plat_arm_gic_redistif_off + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +/* Default GICR base address to be used for GICR probe. */ +static const uintptr_t gicr_base_addrs[2] = { + PLAT_ARM_GICR_BASE, /* GICR Base address of the primary CPU */ + 0U /* Zero Termination */ +}; + +/* List of zero terminated GICR frame addresses which CPUs will probe */ +static const uintptr_t *gicr_frames = gicr_base_addrs; + +static const interrupt_prop_t arm_interrupt_props[] = { + PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) +}; + +/* + * We save and restore the GICv3 context on system suspend. Allocate the + * data in the designated EL3 Secure carve-out memory. The `used` attribute + * is used to prevent the compiler from removing the gicv3 contexts. + */ +static gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram") __used; +static gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram") __used; + +/* Define accessor function to get reference to the GICv3 context */ +DEFINE_LOAD_SYM_ADDR(rdist_ctx) +DEFINE_LOAD_SYM_ADDR(dist_ctx) + +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static unsigned int arm_gicv3_mpidr_hash(u_register_t mpidr) +{ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return plat_arm_calc_core_pos(mpidr); +} + +static const gicv3_driver_data_t arm_gic_data __unused = { + .gicd_base = PLAT_ARM_GICD_BASE, + .gicr_base = 0U, + .interrupt_props = arm_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(arm_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = arm_gicv3_mpidr_hash +}; + +/* + * By default, gicr_frames will be pointing to gicr_base_addrs. If + * the platform supports a non-contiguous GICR frames (GICR frames located + * at uneven offset), plat_arm_override_gicr_frames function can be used by + * such platform to override the gicr_frames. + */ +void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames) +{ + assert(plat_gicr_frames != NULL); + gicr_frames = plat_gicr_frames; +} + +void __init plat_arm_gic_driver_init(void) +{ + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ +#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ + (defined(__aarch64__) && defined(IMAGE_BL31)) + gicv3_driver_init(&arm_gic_data); + + if (gicv3_rdistif_probe(gicr_base_addrs[0]) == -1) { + ERROR("No GICR base frame found for Primary CPU\n"); + panic(); + } +#endif +} + +/****************************************************************************** + * ARM common helper to initialize the GIC. Only invoked by BL31 + *****************************************************************************/ +void __init plat_arm_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * ARM common helper to enable the GIC CPU interface + *****************************************************************************/ +void plat_arm_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * ARM common helper to disable the GIC CPU interface + *****************************************************************************/ +void plat_arm_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/****************************************************************************** + * ARM common helper function to iterate over all GICR frames and discover the + * corresponding per-cpu redistributor frame as well as initialize the + * corresponding interface in GICv3. + *****************************************************************************/ +void plat_arm_gic_pcpu_init(void) +{ + int result; + const uintptr_t *plat_gicr_frames = gicr_frames; + + do { + result = gicv3_rdistif_probe(*plat_gicr_frames); + + /* If the probe is successful, no need to proceed further */ + if (result == 0) + break; + + plat_gicr_frames++; + } while (*plat_gicr_frames != 0U); + + if (result == -1) { + ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); + panic(); + } + gicv3_rdistif_init(plat_my_core_pos()); +} + +/****************************************************************************** + * ARM common helpers to power GIC redistributor interface + *****************************************************************************/ +void plat_arm_gic_redistif_on(void) +{ + gicv3_rdistif_on(plat_my_core_pos()); +} + +void plat_arm_gic_redistif_off(void) +{ + gicv3_rdistif_off(plat_my_core_pos()); +} + +/****************************************************************************** + * ARM common helper to save & restore the GICv3 on resume from system suspend + *****************************************************************************/ +void plat_arm_gic_save(void) +{ + gicv3_redist_ctx_t * const rdist_context = + (gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx); + gicv3_dist_ctx_t * const dist_context = + (gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx); + + /* + * If an ITS is available, save its context before + * the Redistributor using: + * gicv3_its_save_disable(gits_base, &its_ctx[i]) + * Additionally, an implementation-defined sequence may + * be required to save the whole ITS state. + */ + + /* + * Save the GIC Redistributors and ITS contexts before the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to save the context of the CPU that is issuing + * the SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_save(plat_my_core_pos(), rdist_context); + + /* Save the GIC Distributor context */ + gicv3_distif_save(dist_context); + + /* + * From here, all the components of the GIC can be safely powered down + * as long as there is an alternate way to handle wakeup interrupt + * sources. + */ +} + +void plat_arm_gic_resume(void) +{ + const gicv3_redist_ctx_t *rdist_context = + (gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx); + const gicv3_dist_ctx_t *dist_context = + (gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx); + + /* Restore the GIC Distributor context */ + gicv3_distif_init_restore(dist_context); + + /* + * Restore the GIC Redistributor and ITS contexts after the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to restore the context of the CPU that issued + * the SYSTEM SUSPEND call. + */ + gicv3_rdistif_init_restore(plat_my_core_pos(), rdist_context); + + /* + * If an ITS is available, restore its context after + * the Redistributor using: + * gicv3_its_restore(gits_base, &its_ctx[i]) + * An implementation-defined sequence may be required to + * restore the whole ITS state. The ITS must also be + * re-enabled after this sequence has been executed. + */ +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_image_load.c b/arm-trusted-firmware/plat/arm/common/arm_image_load.c new file mode 100644 index 0000000..c411c6c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_image_load.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#if defined(SPD_spmd) +#include +#endif +#include +#include + +#pragma weak plat_flush_next_bl_params +#pragma weak plat_get_bl_image_load_info +#pragma weak plat_get_next_bl_params + +static bl_params_t *next_bl_params_cpy_ptr; + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + assert(next_bl_params_cpy_ptr != NULL); + + flush_bl_params_desc_args(bl_mem_params_desc_ptr, + bl_mem_params_desc_num, + next_bl_params_cpy_ptr); +} + +#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD +/******************************************************************************* + * This function appends Secure Partitions to list of loadable images. + ******************************************************************************/ +static void plat_add_sp_images_load_info(struct bl_load_info *load_info) +{ + bl_load_info_node_t *curr_node = load_info->head; + bl_load_info_node_t *prev_node; + + /* Shortcut for empty SP list */ + if (sp_mem_params_descs[0].image_id == 0) { + ERROR("No Secure Partition Image available\n"); + return; + } + + /* Traverse through the bl images list */ + do { + curr_node = curr_node->next_load_info; + } while (curr_node->next_load_info != NULL); + + prev_node = curr_node; + + for (unsigned int index = 0; index < MAX_SP_IDS; index++) { + if (sp_mem_params_descs[index].image_id == 0) { + return; + } + curr_node = &sp_mem_params_descs[index].load_node_mem; + /* Populate the image information */ + curr_node->image_id = sp_mem_params_descs[index].image_id; + curr_node->image_info = &sp_mem_params_descs[index].image_info; + + prev_node->next_load_info = curr_node; + prev_node = curr_node; + } + + INFO("Reached Max number of SPs\n"); +} +#endif + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +struct bl_load_info *plat_get_bl_image_load_info(void) +{ +#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD + bl_load_info_t *bl_load_info; + + bl_load_info = get_bl_load_info_from_mem_params_desc(); + plat_add_sp_images_load_info(bl_load_info); + + return bl_load_info; +#else + return get_bl_load_info_from_mem_params_desc(); +#endif +} + +/******************************************************************************* + * ARM helper function to return the list of executable images.Since the default + * descriptors are allocated within BL2 RW memory, this prevents BL31/BL32 + * overlay of BL2 memory. Hence this function also copies the descriptors to a + * pre-allocated memory indicated by ARM_BL2_MEM_DESC_BASE. + ******************************************************************************/ +struct bl_params *arm_get_next_bl_params(void) +{ + bl_mem_params_node_t *bl2_mem_params_descs_cpy + = (bl_mem_params_node_t *)ARM_BL2_MEM_DESC_BASE; + const bl_params_t *next_bl_params; + + next_bl_params_cpy_ptr = + (bl_params_t *)(ARM_BL2_MEM_DESC_BASE + + (bl_mem_params_desc_num * sizeof(bl_mem_params_node_t))); + + /* + * Copy the memory descriptors to ARM_BL2_MEM_DESC_BASE area. + */ + (void) memcpy(bl2_mem_params_descs_cpy, bl_mem_params_desc_ptr, + (bl_mem_params_desc_num * sizeof(bl_mem_params_node_t))); + + /* + * Modify the global 'bl_mem_params_desc_ptr' to point to the + * copied location. + */ + bl_mem_params_desc_ptr = bl2_mem_params_descs_cpy; + + next_bl_params = get_next_bl_params_from_mem_params_desc(); + assert(next_bl_params != NULL); + + /* + * Copy 'next_bl_params' to the reserved location after the copied + * memory descriptors. + */ + (void) memcpy(next_bl_params_cpy_ptr, next_bl_params, + (sizeof(bl_params_t))); + + populate_next_bl_params_config(next_bl_params_cpy_ptr); + + return next_bl_params_cpy_ptr; +} + +/******************************************************************************* + * This function returns the list of executable images + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + return arm_get_next_bl_params(); +} + diff --git a/arm-trusted-firmware/plat/arm/common/arm_io_storage.c b/arm-trusted-firmware/plat/arm/common/arm_io_storage.c new file mode 100644 index 0000000..19ee1b0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_io_storage.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2015-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* IO devices */ +static const io_dev_connector_t *fip_dev_con; +uintptr_t fip_dev_handle; +static const io_dev_connector_t *memmap_dev_con; +uintptr_t memmap_dev_handle; + +#if ARM_GPT_SUPPORT +/* fip partition names */ +static const char * const fip_part_names[] = {"FIP_A", "FIP_B"}; +CASSERT(sizeof(fip_part_names)/sizeof(char *) == NR_OF_FW_BANKS, + assert_fip_partition_names_missing); +#endif /* ARM_GPT_SUPPORT */ + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak plat_arm_io_setup +#pragma weak plat_arm_get_alt_image_source + +int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +int open_memmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Memmap\n"); + io_close(local_image_handle); + } + } + return result; +} + +int arm_io_setup(void) +{ + int io_result; + + io_result = register_io_dev_fip(&fip_dev_con); + if (io_result < 0) { + return io_result; + } + + io_result = register_io_dev_memmap(&memmap_dev_con); + if (io_result < 0) { + return io_result; + } + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + if (io_result < 0) { + return io_result; + } + + io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &memmap_dev_handle); + + return io_result; +} + +void plat_arm_io_setup(void) +{ + int err; + + err = arm_io_setup(); + if (err < 0) { + panic(); + } +} + +int plat_arm_get_alt_image_source( + unsigned int image_id __unused, + uintptr_t *dev_handle __unused, + uintptr_t *image_spec __unused) +{ + /* By default do not try an alternative */ + return -ENOENT; +} + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + policy = FCONF_GET_PROPERTY(arm, io_policies, image_id); + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } else { + VERBOSE("Trying alternative IO\n"); + result = plat_arm_get_alt_image_source(image_id, dev_handle, + image_spec); + } + + return result; +} + +/* + * See if a Firmware Image Package is available, + * by checking if TOC is valid or not. + */ +bool arm_io_is_toc_valid(void) +{ + return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0); +} + +#if ARM_GPT_SUPPORT +/****************************************************************************** + * Retrieve partition entry details such as offset and length, and set these + * details in the I/O policy of the requested image. + * + * @image_id: image id whose I/O policy to be updated + * + * @part_name: partition name whose details to be retrieved + * + * Returns 0 on success, error otherwise + * Alongside, returns device handle and image specification of requested + * image. + ******************************************************************************/ +int arm_set_image_source(unsigned int image_id, const char *part_name, + uintptr_t *dev_handle, uintptr_t *image_spec) +{ + const partition_entry_t *entry = get_partition_entry(part_name); + + if (entry == NULL) { + ERROR("Unable to find the %s partition\n", part_name); + return -ENOENT; + } + + struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm, + io_policies, + image_id); + + assert(policy != NULL); + assert(policy->image_spec != 0UL); + + io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec; + /* set offset and length of the image */ + spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start; + spec->length = entry->length; + + *dev_handle = *(policy->dev_handle); + *image_spec = policy->image_spec; + + return 0; +} + +/******************************************************************************* + * Set the source offset and length of the FIP image in its I/O policy. + * + * @active_fw_bank_idx: active firmware bank index gathered from FWU metadata. + ******************************************************************************/ +void arm_set_fip_addr(uint32_t active_fw_bank_idx) +{ + uintptr_t dev_handle __unused; + uintptr_t image_spec __unused; + + assert(active_fw_bank_idx < NR_OF_FW_BANKS); + + INFO("Booting with partition %s\n", fip_part_names[active_fw_bank_idx]); + + int result = arm_set_image_source(FIP_IMAGE_ID, + fip_part_names[active_fw_bank_idx], + &dev_handle, + &image_spec); + if (result != 0) { + panic(); + } +} +#endif /* ARM_GPT_SUPPORT */ + +#if PSA_FWU_SUPPORT +/******************************************************************************* + * Read the FIP partition of the GPT image corresponding to the active firmware + * bank to get its offset and length, and update these details in the I/O policy + * of the FIP image. + ******************************************************************************/ +void plat_fwu_set_images_source(const struct fwu_metadata *metadata) +{ + arm_set_fip_addr(metadata->active_index); +} + +/******************************************************************************* + * Read the requested FWU metadata partition of the GPT image to get its offset + * and length, and update these details in the I/O policy of the requested FWU + * metadata image. + ******************************************************************************/ +int plat_fwu_set_metadata_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = -1; + + if (image_id == FWU_METADATA_IMAGE_ID) { + result = arm_set_image_source(FWU_METADATA_IMAGE_ID, + "FWU-Metadata", + dev_handle, + image_spec); + } else if (image_id == BKUP_FWU_METADATA_IMAGE_ID) { + result = arm_set_image_source(BKUP_FWU_METADATA_IMAGE_ID, + "Bkup-FWU-Metadata", + dev_handle, + image_spec); + } + + return result; +} +#endif /* PSA_FWU_SUPPORT */ diff --git a/arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c b/arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c new file mode 100644 index 0000000..1fa234d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +/* + * DRAM1 is used also to load the NS boot loader. For this reason we + * cannot clear the full DRAM1, because in that case we would clear + * the NS images (especially for RESET_TO_BL31 and RESET_TO_SPMIN cases). + * For this reason we reserve 64 MB for the NS images and protect the RAM + * until the end of DRAM1. + * We limit the size of DRAM2 to 1 GB to avoid big delays while booting + */ +#define DRAM1_NS_IMAGE_LIMIT (PLAT_ARM_NS_IMAGE_BASE + (32 << TWO_MB_SHIFT)) +#define DRAM1_PROTECTED_SIZE (ARM_NS_DRAM1_END+1u - DRAM1_NS_IMAGE_LIMIT) + +static mem_region_t arm_ram_ranges[] = { + {DRAM1_NS_IMAGE_LIMIT, DRAM1_PROTECTED_SIZE}, +#ifdef __aarch64__ + {ARM_DRAM2_BASE, 1u << ONE_GB_SHIFT}, +#endif +}; + +/******************************************************************************* + * Function that reads the content of the memory protect variable that + * enables clearing of non secure memory when system boots. This variable + * should be stored in a secure NVRAM. + ******************************************************************************/ +int arm_psci_read_mem_protect(int *enabled) +{ + int tmp; + + tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR; + *enabled = (tmp == 1) ? 1 : 0; + return 0; +} + +/******************************************************************************* + * Function that writes the content of the memory protect variable that + * enables overwritten of non secure memory when system boots. + ******************************************************************************/ +int arm_nor_psci_write_mem_protect(int val) +{ + unsigned long enable = (val != 0) ? 1UL : 0UL; + + if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) { + ERROR("unlocking memory protect variable\n"); + return -1; + } + + if (enable == 1UL) { + /* + * If we want to write a value different than 0 + * then we have to erase the full block because + * otherwise we cannot ensure that the value programmed + * into the flash is going to be the same than the value + * requested by the caller + */ + if (nor_erase(PLAT_ARM_MEM_PROT_ADDR) != 0) { + ERROR("erasing block containing memory protect variable\n"); + return -1; + } + } + + if (nor_word_program(PLAT_ARM_MEM_PROT_ADDR, enable) != 0) { + ERROR("programming memory protection variable\n"); + return -1; + } + return 0; +} + +/******************************************************************************* + * Function used for required psci operations performed when + * system boots + ******************************************************************************/ +/* + * PLAT_MEM_PROTECT_VA_FRAME is a address specifically + * selected in a way that is not needed an additional + * translation table for memprotect. It happens because + * we use a chunk of size 2MB and it means that it can + * be mapped in a level 2 table and the level 2 table + * for 0xc0000000 is already used and the entry for + * 0xc0000000 is not used. + */ +#if defined(PLAT_XLAT_TABLES_DYNAMIC) +void arm_nor_psci_do_dyn_mem_protect(void) +{ + int enable; + + arm_psci_read_mem_protect(&enable); + if (enable == 0) + return; + + INFO("PSCI: Overwriting non secure memory\n"); + clear_map_dyn_mem_regions(arm_ram_ranges, + ARRAY_SIZE(arm_ram_ranges), + PLAT_ARM_MEM_PROTEC_VA_FRAME, + 1 << TWO_MB_SHIFT); +} +#endif + +/******************************************************************************* + * Function used for required psci operations performed when + * system boots and dynamic memory is not used. + ******************************************************************************/ +void arm_nor_psci_do_static_mem_protect(void) +{ + int enable; + + (void) arm_psci_read_mem_protect(&enable); + if (enable == 0) + return; + + INFO("PSCI: Overwriting non secure memory\n"); + clear_mem_regions(arm_ram_ranges, + ARRAY_SIZE(arm_ram_ranges)); + (void) arm_nor_psci_write_mem_protect(0); +} + +/******************************************************************************* + * Function that checks if a region is protected by the memory protect + * mechanism + ******************************************************************************/ +int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length) +{ + return mem_region_in_array_chk(arm_ram_ranges, + ARRAY_SIZE(arm_ram_ranges), + base, length); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_pm.c b/arm-trusted-firmware/plat/arm/common/arm_pm.c new file mode 100644 index 0000000..5434c94 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_pm.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include + +/* Allow ARM Standard platforms to override these functions */ +#pragma weak plat_arm_program_trusted_mailbox + +#if !ARM_RECOM_STATE_ID_ENC +/******************************************************************************* + * ARM standard platform handler called to check the validity of the power state + * parameter. + ******************************************************************************/ +int arm_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int pstate = psci_get_pstate_type(power_state); + unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + unsigned int i; + + assert(req_state != NULL); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != ARM_PWR_LVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[ARM_PWR_LVL0] = + ARM_LOCAL_STATE_RET; + } else { + for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + ARM_LOCAL_STATE_OFF; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state) != 0U) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +#else +/******************************************************************************* + * ARM standard platform handler called to check the validity of the power + * state parameter. The power state parameter has to be a composite power + * state. + ******************************************************************************/ +int arm_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + assert(req_state != NULL); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; !!arm_pm_idle_states[i]; i++) { + if (power_state == arm_pm_idle_states[i]) + break; + } + + /* Return error if entry not found in the idle state array */ + if (!arm_pm_idle_states[i]) + return PSCI_E_INVALID_PARAMS; + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + ARM_LOCAL_PSTATE_MASK; + state_id >>= ARM_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} +#endif /* __ARM_RECOM_STATE_ID_ENC__ */ + +/******************************************************************************* + * ARM standard platform handler called to check the validity of the non secure + * entrypoint. Returns 0 if the entrypoint is valid, or -1 otherwise. + ******************************************************************************/ +int arm_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < + (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) { + return 0; + } +#ifdef __aarch64__ + if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < + (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) { + return 0; + } +#endif + + return -1; +} + +int arm_validate_psci_entrypoint(uintptr_t entrypoint) +{ + return (arm_validate_ns_entrypoint(entrypoint) == 0) ? PSCI_E_SUCCESS : + PSCI_E_INVALID_ADDRESS; +} + +/****************************************************************************** + * Helper function to save the platform state before a system suspend. Save the + * state of the system components which are not in the Always ON power domain. + *****************************************************************************/ +void arm_system_pwr_domain_save(void) +{ + /* Assert system power domain is available on the platform */ + assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); + + plat_arm_gic_save(); + + /* + * Unregister console now so that it is not registered for a second + * time during resume. + */ + arm_console_runtime_end(); + + /* + * All the other peripheral which are configured by ARM TF are + * re-initialized on resume from system suspend. Hence we + * don't save their state here. + */ +} + +/****************************************************************************** + * Helper function to resume the platform from system suspend. Reinitialize + * the system components which are not in the Always ON power domain. + * TODO: Unify the platform setup when waking up from cold boot and system + * resume in arm_bl31_platform_setup(). + *****************************************************************************/ +void arm_system_pwr_domain_resume(void) +{ + /* Initialize the console */ + arm_console_runtime_init(); + + /* Assert system power domain is available on the platform */ + assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); + + plat_arm_gic_resume(); + + plat_arm_security_setup(); + arm_configure_sys_timer(); +} + +/******************************************************************************* + * ARM platform function to program the mailbox for a cpu before it is released + * from reset. This function assumes that the Trusted mail box base is within + * the ARM_SHARED_RAM region + ******************************************************************************/ +void plat_arm_program_trusted_mailbox(uintptr_t address) +{ + uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; + + *mailbox = address; + + /* + * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within + * ARM_SHARED_RAM region. + */ + assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && + ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \ + (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); +} + +/******************************************************************************* + * The ARM Standard platform definition of platform porting API + * `plat_setup_psci_ops`. + ******************************************************************************/ +int __init plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); + + /* Setup mailbox with entry point. */ + plat_arm_program_trusted_mailbox(sec_entrypoint); + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_sip_svc.c b/arm-trusted-firmware/plat/arm/common/arm_sip_svc.c new file mode 100644 index 0000000..6456c78 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_sip_svc.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* ARM SiP Service UUID */ +DEFINE_SVC_UUID2(arm_sip_svc_uid, + 0x556d75e2, 0x6033, 0xb54b, 0xb5, 0x75, + 0x62, 0x79, 0xfd, 0x11, 0x37, 0xff); + +static int arm_sip_setup(void) +{ + if (pmf_setup() != 0) { + return 1; + } + +#if USE_DEBUGFS + + if (debugfs_smc_setup() != 0) { + return 1; + } + +#endif /* USE_DEBUGFS */ + + return 0; +} + +/* + * This function handles ARM defined SiP Calls + */ +static uintptr_t arm_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) +{ + int call_count = 0; + +#if ENABLE_PMF + + /* + * Dispatch PMF calls to PMF SMC handler and return its return + * value + */ + if (is_pmf_fid(smc_fid)) { + return pmf_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + +#endif /* ENABLE_PMF */ + +#if USE_DEBUGFS + + if (is_debugfs_fid(smc_fid)) { + return debugfs_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + +#endif /* USE_DEBUGFS */ + +#if ARM_ETHOSN_NPU_DRIVER + + if (is_ethosn_fid(smc_fid)) { + return ethosn_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + +#endif /* ARM_ETHOSN_NPU_DRIVER */ + + switch (smc_fid) { + case ARM_SIP_SVC_EXE_STATE_SWITCH: { + /* Execution state can be switched only if EL3 is AArch64 */ +#ifdef __aarch64__ + /* Allow calls from non-secure only */ + if (!is_caller_non_secure(flags)) + SMC_RET1(handle, STATE_SW_E_DENIED); + + /* + * Pointers used in execution state switch are all 32 bits wide + */ + return (uintptr_t) arm_execution_state_switch(smc_fid, + (uint32_t) x1, (uint32_t) x2, (uint32_t) x3, + (uint32_t) x4, handle); +#else + /* State switch denied */ + SMC_RET1(handle, STATE_SW_E_DENIED); +#endif /* __aarch64__ */ + } + + case ARM_SIP_SVC_CALL_COUNT: + /* PMF calls */ + call_count += PMF_NUM_SMC_CALLS; + +#if ARM_ETHOSN_NPU_DRIVER + /* ETHOSN calls */ + call_count += ETHOSN_NUM_SMC_CALLS; +#endif /* ARM_ETHOSN_NPU_DRIVER */ + + /* State switch call */ + call_count += 1; + + SMC_RET1(handle, call_count); + + case ARM_SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, arm_sip_svc_uid); + + case ARM_SIP_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, ARM_SIP_SVC_VERSION_MAJOR, ARM_SIP_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented ARM SiP Service Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } + +} + + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + arm_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + arm_sip_setup, + arm_sip_handler +); diff --git a/arm-trusted-firmware/plat/arm/common/arm_topology.c b/arm-trusted-firmware/plat/arm/common/arm_topology.c new file mode 100644 index 0000000..c9993a7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_topology.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/******************************************************************************* + * This function validates an MPIDR by checking whether it falls within the + * acceptable bounds. An error code (-1) is returned if an incorrect mpidr + * is passed. + ******************************************************************************/ +int arm_check_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + uint64_t valid_mask; + +#if ARM_PLAT_MT + unsigned int pe_id; + + valid_mask = ~(MPIDR_AFFLVL_MASK | + (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) | + (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT) | + (MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)); + cluster_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + pe_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; +#else + valid_mask = ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK); + cluster_id = (unsigned int) ((mpidr >> MPIDR_AFF1_SHIFT) & + MPIDR_AFFLVL_MASK); + cpu_id = (unsigned int) ((mpidr >> MPIDR_AFF0_SHIFT) & + MPIDR_AFFLVL_MASK); +#endif /* ARM_PLAT_MT */ + + mpidr &= MPIDR_AFFINITY_MASK; + if ((mpidr & valid_mask) != 0U) + return -1; + + if (cluster_id >= PLAT_ARM_CLUSTER_COUNT) + return -1; + + /* Validate cpu_id by checking whether it represents a CPU in + one of the two clusters present on the platform. */ + if (cpu_id >= plat_arm_get_cluster_core_count(mpidr)) + return -1; + +#if ARM_PLAT_MT + if (pe_id >= plat_arm_get_cpu_pe_count(mpidr)) + return -1; +#endif /* ARM_PLAT_MT */ + + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_tzc400.c b/arm-trusted-firmware/plat/arm/common/arm_tzc400.c new file mode 100644 index 0000000..370ef0a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_tzc400.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak plat_arm_security_setup + + +/******************************************************************************* + * Initialize the TrustZone Controller for ARM standard platforms. + * When booting an EL3 payload, this is simplified: we configure region 0 with + * secure access only and do not enable any other region. + ******************************************************************************/ +void arm_tzc400_setup(uintptr_t tzc_base, + const arm_tzc_regions_info_t *tzc_regions) +{ +#ifndef EL3_PAYLOAD_BASE + unsigned int region_index = 1U; + const arm_tzc_regions_info_t *p; + const arm_tzc_regions_info_t init_tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {0} + }; +#endif + + INFO("Configuring TrustZone Controller\n"); + + tzc400_init(tzc_base); + + /* Disable filters. */ + tzc400_disable_filters(); + +#ifndef EL3_PAYLOAD_BASE + if (tzc_regions == NULL) + p = init_tzc_regions; + else + p = tzc_regions; + + /* Region 0 set to no access by default */ + tzc400_configure_region0(TZC_REGION_S_NONE, 0); + + /* Rest Regions set according to tzc_regions array */ + for (; p->base != 0ULL; p++) { + tzc400_configure_region(PLAT_ARM_TZC_FILTERS, region_index, + p->base, p->end, p->sec_attr, p->nsaid_permissions); + region_index++; + } + + INFO("Total %u regions set.\n", region_index); + +#else /* if defined(EL3_PAYLOAD_BASE) */ + + /* Allow Secure and Non-secure access to DRAM for EL3 payloads */ + tzc400_configure_region0(TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS); + +#endif /* EL3_PAYLOAD_BASE */ + + /* + * Raise an exception if a NS device tries to access secure memory + * TODO: Add interrupt handling support. + */ + tzc400_set_action(TZC_ACTION_ERR); + + /* Enable filters. */ + tzc400_enable_filters(); +} + +void plat_arm_security_setup(void) +{ + arm_tzc400_setup(PLAT_ARM_TZC_BASE, NULL); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c b/arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c new file mode 100644 index 0000000..e9f897f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +/******************************************************************************* + * Initialize the DMC500-TrustZone Controller for ARM standard platforms. + * When booting an EL3 payload, this is simplified: we configure region 0 with + * secure access only and do not enable any other region. + ******************************************************************************/ +void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data, + const arm_tzc_regions_info_t *tzc_regions) +{ +#ifndef EL3_PAYLOAD_BASE + unsigned int region_index = 1U; + const arm_tzc_regions_info_t *p; + const arm_tzc_regions_info_t init_tzc_regions[] = { + ARM_TZC_REGIONS_DEF, + {0} + }; +#endif + + assert(plat_driver_data); + + INFO("Configuring DMC-500 TZ Settings\n"); + + tzc_dmc500_driver_init(plat_driver_data); + +#ifndef EL3_PAYLOAD_BASE + if (tzc_regions == NULL) + p = init_tzc_regions; + else + p = tzc_regions; + + /* Region 0 set to no access by default */ + tzc_dmc500_configure_region0(TZC_REGION_S_NONE, 0); + + /* Rest Regions set according to tzc_regions array */ + for (; p->base != 0ULL; p++) { + tzc_dmc500_configure_region(region_index, p->base, p->end, + p->sec_attr, p->nsaid_permissions); + region_index++; + } + + INFO("Total %u regions set.\n", region_index); + +#else + /* Allow secure access only to DRAM for EL3 payloads */ + tzc_dmc500_configure_region0(TZC_REGION_S_RDWR, 0); +#endif + /* + * Raise an exception if a NS device tries to access secure memory + * TODO: Add interrupt handling support. + */ + tzc_dmc500_set_action(TZC_ACTION_RV_LOWERR); + + /* + * Flush the configuration settings to have an affect. Validate + * flush by checking FILTER_EN is set on region 1 attributes + * register. + */ + tzc_dmc500_config_complete(); + + /* + * Wait for the flush to complete. + * TODO: Have a timeout for this loop + */ + while (tzc_dmc500_verify_complete()) + ; +} diff --git a/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c b/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c new file mode 100644 index 0000000..aea2f38 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2019-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if PSA_FWU_SUPPORT +/* metadata entry details */ +static io_block_spec_t fwu_metadata_spec; +#endif /* PSA_FWU_SUPPORT */ + +io_block_spec_t fip_block_spec = { +/* + * This is fixed FIP address used by BL1, BL2 loads partition table + * to get FIP address. + */ +#if ARM_GPT_SUPPORT + .offset = PLAT_ARM_FLASH_IMAGE_BASE + PLAT_ARM_FIP_OFFSET_IN_GPT, +#else + .offset = PLAT_ARM_FLASH_IMAGE_BASE, +#endif /* ARM_GPT_SUPPORT */ + .length = PLAT_ARM_FLASH_IMAGE_MAX_SIZE +}; + +#if ARM_GPT_SUPPORT +static const io_block_spec_t gpt_spec = { + .offset = PLAT_ARM_FLASH_IMAGE_BASE, + /* + * PLAT_PARTITION_BLOCK_SIZE = 512 + * PLAT_PARTITION_MAX_ENTRIES = 128 + * each sector has 4 partition entries, and there are + * 2 reserved sectors i.e. protective MBR and primary + * GPT header hence length gets calculated as, + * length = 512 * (128/4 + 2) + */ + .length = PLAT_PARTITION_BLOCK_SIZE * + (PLAT_PARTITION_MAX_ENTRIES / 4 + 2), +}; +#endif /* ARM_GPT_SUPPORT */ + +const io_uuid_spec_t arm_uuid_spec[MAX_NUMBER_IDS] = { + [BL2_IMAGE_ID] = {UUID_TRUSTED_BOOT_FIRMWARE_BL2}, + [TB_FW_CONFIG_ID] = {UUID_TB_FW_CONFIG}, + [FW_CONFIG_ID] = {UUID_FW_CONFIG}, +#if !ARM_IO_IN_DTB + [SCP_BL2_IMAGE_ID] = {UUID_SCP_FIRMWARE_SCP_BL2}, + [BL31_IMAGE_ID] = {UUID_EL3_RUNTIME_FIRMWARE_BL31}, + [BL32_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32}, + [BL32_EXTRA1_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32_EXTRA1}, + [BL32_EXTRA2_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32_EXTRA2}, + [BL33_IMAGE_ID] = {UUID_NON_TRUSTED_FIRMWARE_BL33}, + [HW_CONFIG_ID] = {UUID_HW_CONFIG}, + [SOC_FW_CONFIG_ID] = {UUID_SOC_FW_CONFIG}, + [TOS_FW_CONFIG_ID] = {UUID_TOS_FW_CONFIG}, + [NT_FW_CONFIG_ID] = {UUID_NT_FW_CONFIG}, + [RMM_IMAGE_ID] = {UUID_REALM_MONITOR_MGMT_FIRMWARE}, +#endif /* ARM_IO_IN_DTB */ +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = {UUID_TRUSTED_BOOT_FW_CERT}, +#if !ARM_IO_IN_DTB + [TRUSTED_KEY_CERT_ID] = {UUID_TRUSTED_KEY_CERT}, + [SCP_FW_KEY_CERT_ID] = {UUID_SCP_FW_KEY_CERT}, + [SOC_FW_KEY_CERT_ID] = {UUID_SOC_FW_KEY_CERT}, + [TRUSTED_OS_FW_KEY_CERT_ID] = {UUID_TRUSTED_OS_FW_KEY_CERT}, + [NON_TRUSTED_FW_KEY_CERT_ID] = {UUID_NON_TRUSTED_FW_KEY_CERT}, + [SCP_FW_CONTENT_CERT_ID] = {UUID_SCP_FW_CONTENT_CERT}, + [SOC_FW_CONTENT_CERT_ID] = {UUID_SOC_FW_CONTENT_CERT}, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = {UUID_TRUSTED_OS_FW_CONTENT_CERT}, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = {UUID_NON_TRUSTED_FW_CONTENT_CERT}, +#if defined(SPD_spmd) + [SIP_SP_CONTENT_CERT_ID] = {UUID_SIP_SECURE_PARTITION_CONTENT_CERT}, + [PLAT_SP_CONTENT_CERT_ID] = {UUID_PLAT_SECURE_PARTITION_CONTENT_CERT}, +#endif +#endif /* ARM_IO_IN_DTB */ +#endif /* TRUSTED_BOARD_BOOT */ +}; + +/* By default, ARM platforms load images from the FIP */ +struct plat_io_policy policies[MAX_NUMBER_IDS] = { +#if ARM_GPT_SUPPORT + [GPT_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&gpt_spec, + open_memmap + }, +#endif /* ARM_GPT_SUPPORT */ +#if PSA_FWU_SUPPORT + [FWU_METADATA_IMAGE_ID] = { + &memmap_dev_handle, + /* filled runtime from partition information */ + (uintptr_t)&fwu_metadata_spec, + open_memmap + }, + [BKUP_FWU_METADATA_IMAGE_ID] = { + &memmap_dev_handle, + /* filled runtime from partition information */ + (uintptr_t)&fwu_metadata_spec, + open_memmap + }, +#endif /* PSA_FWU_SUPPORT */ + [FIP_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[BL2_IMAGE_ID], + open_fip + }, + [TB_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[TB_FW_CONFIG_ID], + open_fip + }, + [FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[FW_CONFIG_ID], + open_fip + }, +#if !ARM_IO_IN_DTB + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[SCP_BL2_IMAGE_ID], + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[BL31_IMAGE_ID], + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[BL32_IMAGE_ID], + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[BL32_EXTRA1_IMAGE_ID], + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[BL32_EXTRA2_IMAGE_ID], + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[BL33_IMAGE_ID], + open_fip + }, + [RMM_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[RMM_IMAGE_ID], + open_fip + }, + [HW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[HW_CONFIG_ID], + open_fip + }, + [SOC_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[SOC_FW_CONFIG_ID], + open_fip + }, + [TOS_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[TOS_FW_CONFIG_ID], + open_fip + }, + [NT_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[NT_FW_CONFIG_ID], + open_fip + }, +#endif /* ARM_IO_IN_DTB */ +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[TRUSTED_BOOT_FW_CERT_ID], + open_fip + }, +#if !ARM_IO_IN_DTB + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[TRUSTED_KEY_CERT_ID], + open_fip + }, + [SCP_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[SCP_FW_KEY_CERT_ID], + open_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[SOC_FW_KEY_CERT_ID], + open_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[TRUSTED_OS_FW_KEY_CERT_ID], + open_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[NON_TRUSTED_FW_KEY_CERT_ID], + open_fip + }, + [SCP_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[SCP_FW_CONTENT_CERT_ID], + open_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[SOC_FW_CONTENT_CERT_ID], + open_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[TRUSTED_OS_FW_CONTENT_CERT_ID], + open_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[NON_TRUSTED_FW_CONTENT_CERT_ID], + open_fip + }, +#if defined(SPD_spmd) + [SIP_SP_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[SIP_SP_CONTENT_CERT_ID], + open_fip + }, + [PLAT_SP_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&arm_uuid_spec[PLAT_SP_CONTENT_CERT_ID], + open_fip + }, +#endif +#endif /* ARM_IO_IN_DTB */ +#endif /* TRUSTED_BOARD_BOOT */ +}; + +#ifdef IMAGE_BL2 + +#if TRUSTED_BOARD_BOOT +#define FCONF_ARM_IO_UUID_NUMBER U(21) +#else +#define FCONF_ARM_IO_UUID_NUMBER U(10) +#endif + +static io_uuid_spec_t fconf_arm_uuids[FCONF_ARM_IO_UUID_NUMBER]; +static OBJECT_POOL_ARRAY(fconf_arm_uuids_pool, fconf_arm_uuids); + +struct policies_load_info { + unsigned int image_id; + const char *name; +}; + +/* image id to property name table */ +static const struct policies_load_info load_info[FCONF_ARM_IO_UUID_NUMBER] = { + {SCP_BL2_IMAGE_ID, "scp_bl2_uuid"}, + {BL31_IMAGE_ID, "bl31_uuid"}, + {BL32_IMAGE_ID, "bl32_uuid"}, + {BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"}, + {BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"}, + {BL33_IMAGE_ID, "bl33_uuid"}, + {HW_CONFIG_ID, "hw_cfg_uuid"}, + {SOC_FW_CONFIG_ID, "soc_fw_cfg_uuid"}, + {TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"}, + {NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"}, +#if TRUSTED_BOARD_BOOT + {TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"}, + {SCP_FW_KEY_CERT_ID, "scp_fw_key_uuid"}, + {SOC_FW_KEY_CERT_ID, "soc_fw_key_uuid"}, + {TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"}, + {NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"}, + {SCP_FW_CONTENT_CERT_ID, "scp_fw_content_cert_uuid"}, + {SOC_FW_CONTENT_CERT_ID, "soc_fw_content_cert_uuid"}, + {TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"}, + {NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"}, +#if defined(SPD_spmd) + {SIP_SP_CONTENT_CERT_ID, "sip_sp_content_cert_uuid"}, + {PLAT_SP_CONTENT_CERT_ID, "plat_sp_content_cert_uuid"}, +#endif +#endif /* TRUSTED_BOARD_BOOT */ +}; + +int fconf_populate_arm_io_policies(uintptr_t config) +{ + int err, node; + unsigned int i; + + union uuid_helper_t uuid_helper; + io_uuid_spec_t *uuid_ptr; + + /* As libfdt uses void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* Assert the node offset point to "arm,io-fip-handle" compatible property */ + const char *compatible_str = "arm,io-fip-handle"; + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); + return node; + } + + /* Locate the uuid cells and read the value for all the load info uuid */ + for (i = 0; i < FCONF_ARM_IO_UUID_NUMBER; i++) { + uuid_ptr = pool_alloc(&fconf_arm_uuids_pool); + err = fdtw_read_uuid(dtb, node, load_info[i].name, 16, + (uint8_t *)&uuid_helper); + if (err < 0) { + WARN("FCONF: Read cell failed for %s\n", load_info[i].name); + return err; + } + + VERBOSE("FCONF: arm-io_policies.%s cell found with value = " + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + load_info[i].name, + uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1], + uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3], + uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1], + uuid_helper.uuid_struct.time_hi_and_version[0], + uuid_helper.uuid_struct.time_hi_and_version[1], + uuid_helper.uuid_struct.clock_seq_hi_and_reserved, + uuid_helper.uuid_struct.clock_seq_low, + uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1], + uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3], + uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5]); + + uuid_ptr->uuid = uuid_helper.uuid_struct; + policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr; + policies[load_info[i].image_id].dev_handle = &fip_dev_handle; + policies[load_info[i].image_id].check = open_fip; + } + return 0; +} + +#if ARM_IO_IN_DTB +FCONF_REGISTER_POPULATOR(TB_FW, arm_io, fconf_populate_arm_io_policies); +#endif /* ARM_IO_IN_DTB */ + +#endif /* IMAGE_BL2 */ diff --git a/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c b/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c new file mode 100644 index 0000000..18c83c7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020-2022, 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 + +#ifdef IMAGE_BL2 + +bl_mem_params_node_t sp_mem_params_descs[MAX_SP_IDS]; + +struct arm_sp_t arm_sp; + +int fconf_populate_arm_sp(uintptr_t config) +{ + int sp_node, node, err; + union uuid_helper_t uuid_helper; + unsigned int index = 0; + uint32_t val32; + const unsigned int sip_start = SP_PKG1_ID; + unsigned int sip_index = sip_start; +#if defined(ARM_COT_dualroot) + const unsigned int sip_end = sip_start + MAX_SP_IDS / 2; + /* Allocating index range for platform SPs */ + const unsigned int plat_start = SP_PKG5_ID; + unsigned int plat_index = plat_start; + const unsigned int plat_end = plat_start + MAX_SP_IDS / 2; + bool is_plat_owned = false; +#endif /* ARM_COT_dualroot */ + + /* As libfdt use void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* Assert the node offset point to "arm,sp" compatible property */ + const char *compatible_str = "arm,sp"; + + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find %s in dtb\n", compatible_str); + return node; + } + + fdt_for_each_subnode(sp_node, dtb, node) { + if (index == MAX_SP_IDS) { + ERROR("FCONF: Reached max number of SPs\n"); + return -1; + } + +#if defined(ARM_COT_dualroot) + if ((sip_index == sip_end) || (plat_index == plat_end)) { + ERROR("FCONF: Reached max number of plat/SiP SPs\n"); + return -1; + } +#endif /* ARM_COT_dualroot */ + + /* Read UUID */ + err = fdtw_read_uuid(dtb, sp_node, "uuid", 16, + (uint8_t *)&uuid_helper); + if (err < 0) { + ERROR("FCONF: cannot read SP uuid\n"); + return -1; + } + + arm_sp.uuids[index] = uuid_helper; + + /* Read Load address */ + err = fdt_read_uint32(dtb, sp_node, "load-address", &val32); + if (err < 0) { + ERROR("FCONF: cannot read SP load address\n"); + return -1; + } + arm_sp.load_addr[index] = val32; + + VERBOSE("FCONF: %s UUID" + " %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" + " load_addr=%lx\n", + __func__, + uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1], + uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3], + uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1], + uuid_helper.uuid_struct.time_hi_and_version[0], + uuid_helper.uuid_struct.time_hi_and_version[1], + uuid_helper.uuid_struct.clock_seq_hi_and_reserved, + uuid_helper.uuid_struct.clock_seq_low, + uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1], + uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3], + uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5], + arm_sp.load_addr[index]); + + /* Read owner field only for dualroot CoT */ +#if defined(ARM_COT_dualroot) + /* Owner is an optional field, no need to catch error */ + fdtw_read_string(dtb, sp_node, "owner", + arm_sp.owner[index], ARM_SP_OWNER_NAME_LEN); + + /* If owner is empty mark it as SiP owned */ + if ((strncmp(arm_sp.owner[index], "SiP", + ARM_SP_OWNER_NAME_LEN) == 0) || + (strncmp(arm_sp.owner[index], "", + ARM_SP_OWNER_NAME_LEN) == 0)) { + is_plat_owned = false; + } else if (strcmp(arm_sp.owner[index], "Plat") == 0) { + is_plat_owned = true; + } else { + ERROR("FCONF: %s is not a valid SP owner\n", + arm_sp.owner[index]); + return -1; + } + /* + * Add SP information in mem param descriptor and IO policies + * structure. + */ + if (is_plat_owned) { + sp_mem_params_descs[index].image_id = plat_index; + policies[plat_index].image_spec = + (uintptr_t)&arm_sp.uuids[index]; + policies[plat_index].dev_handle = &fip_dev_handle; + policies[plat_index].check = open_fip; + plat_index++; + } else +#endif /* ARM_COT_dualroot */ + { + sp_mem_params_descs[index].image_id = sip_index; + policies[sip_index].image_spec = + (uintptr_t)&arm_sp.uuids[index]; + policies[sip_index].dev_handle = &fip_dev_handle; + policies[sip_index].check = open_fip; + sip_index++; + } + SET_PARAM_HEAD(&sp_mem_params_descs[index].image_info, + PARAM_IMAGE_BINARY, VERSION_2, 0); + sp_mem_params_descs[index].image_info.image_max_size = + ARM_SP_MAX_SIZE; + sp_mem_params_descs[index].next_handoff_image_id = + INVALID_IMAGE_ID; + sp_mem_params_descs[index].image_info.image_base = + arm_sp.load_addr[index]; + index++; + } + + if ((sp_node < 0) && (sp_node != -FDT_ERR_NOTFOUND)) { + ERROR("%u: fdt_for_each_subnode(): %d\n", __LINE__, node); + return sp_node; + } + + arm_sp.number_of_sp = index; + return 0; +} + +FCONF_REGISTER_POPULATOR(TB_FW, arm_sp, fconf_populate_arm_sp); + +#endif /* IMAGE_BL2 */ diff --git a/arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c b/arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c new file mode 100644 index 0000000..0af1a20 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +struct ethosn_config_t ethosn_config = {.num_cores = 0}; + +static uint8_t fdt_node_get_status(const void *fdt, int node) +{ + int len; + uint8_t status = ETHOSN_STATUS_DISABLED; + const char *node_status; + + node_status = fdt_getprop(fdt, node, "status", &len); + if (node_status == NULL || + (len == 5 && /* Includes null character */ + strncmp(node_status, "okay", 4U) == 0)) { + status = ETHOSN_STATUS_ENABLED; + } + + return status; +} + +int fconf_populate_ethosn_config(uintptr_t config) +{ + int ethosn_node; + const void *hw_conf_dtb = (const void *)config; + + /* Find offset to node with 'ethosn' compatible property */ + INFO("Probing Arm Ethos-N NPU\n"); + uint32_t total_core_count = 0U; + + fdt_for_each_compatible_node(hw_conf_dtb, ethosn_node, "ethosn") { + int sub_node; + uint8_t ethosn_status; + uint32_t device_core_count = 0U; + + /* If the Arm Ethos-N NPU is disabled the core check can be skipped */ + ethosn_status = fdt_node_get_status(hw_conf_dtb, ethosn_node); + if (ethosn_status == ETHOSN_STATUS_DISABLED) { + continue; + } + + fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) { + int err; + uintptr_t core_addr; + uint8_t core_status; + + if (total_core_count >= ETHOSN_CORE_NUM_MAX) { + ERROR("FCONF: Reached max number of Arm Ethos-N NPU cores\n"); + return -FDT_ERR_BADSTRUCTURE; + } + + /* Check that the sub node is "ethosn-core" compatible */ + if (fdt_node_check_compatible(hw_conf_dtb, + sub_node, + "ethosn-core") != 0) { + /* Ignore incompatible sub node */ + continue; + } + + core_status = fdt_node_get_status(hw_conf_dtb, sub_node); + if (core_status == ETHOSN_STATUS_DISABLED) { + continue; + } + + err = fdt_get_reg_props_by_index(hw_conf_dtb, + ethosn_node, + device_core_count, + &core_addr, + NULL); + if (err < 0) { + ERROR( + "FCONF: Failed to read reg property for Arm Ethos-N NPU core %u\n", + device_core_count); + return err; + } + + INFO("NPU core probed at address 0x%lx\n", core_addr); + ethosn_config.core[total_core_count].addr = core_addr; + total_core_count++; + device_core_count++; + } + + if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) { + ERROR("FCONF: Failed to parse sub nodes\n"); + return -FDT_ERR_BADSTRUCTURE; + } + + if (device_core_count == 0U) { + ERROR( + "FCONF: Enabled Arm Ethos-N NPU device must have at least one enabled core\n"); + return -FDT_ERR_BADSTRUCTURE; + } + } + + if (total_core_count == 0U) { + ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n"); + return -FDT_ERR_BADSTRUCTURE; + } + + ethosn_config.num_cores = total_core_count; + + INFO("%d NPU core%s probed\n", + ethosn_config.num_cores, + ethosn_config.num_cores > 1 ? "s" : ""); + + return 0; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config); diff --git a/arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c b/arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c new file mode 100644 index 0000000..8d645ef --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#include + +/******************************************************************************* + * fconf_populate_cot_descs() - Populate available nv-counters and update global + * structure. + * @config[in]: Pointer to the device tree blob in memory + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int fconf_populate_nv_cntrs(uintptr_t config) +{ + int rc, node, child; + uint32_t id; + uintptr_t reg; + + /* As libfdt uses void *, we can't avoid this cast */ + const void *dtb = (void *)config; + const char *compatible_str = "arm, non-volatile-counter"; + + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find %s compatible in node\n", + compatible_str); + return node; + } + + fdt_for_each_subnode(child, dtb, node) { + + rc = fdt_read_uint32(dtb, child, "id", &id); + if (rc < 0) { + ERROR("FCONF: Can't find %s property in node\n", "id"); + return rc; + } + + assert(id < MAX_NV_CTR_IDS); + + rc = fdt_get_reg_props_by_index(dtb, child, 0, ®, NULL); + if (rc < 0) { + ERROR("FCONF: Can't find %s property in node\n", "reg"); + return rc; + } + + nv_cntr_base_addr[id] = reg; + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(TB_FW, nv_cntrs, fconf_populate_nv_cntrs); diff --git a/arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c b/arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c new file mode 100644 index 0000000..c26e316 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include + +#define PRIVATE_EVENT_NUM(i) private_events[3 * (i)] +#define PRIVATE_EVENT_INTR(i) private_events[3 * (i) + 1] +#define PRIVATE_EVENT_FLAGS(i) private_events[3 * (i) + 2] + +#define SHARED_EVENT_NUM(i) shared_events[3 * (i)] +#define SHARED_EVENT_INTR(i) shared_events[3 * (i) + 1] +#define SHARED_EVENT_FLAGS(i) shared_events[3 * (i) + 2] + +struct sdei_dyn_config_t sdei_dyn_config; + +int fconf_populate_sdei_dyn_config(uintptr_t config) +{ + uint32_t i; + int node, err; + uint32_t private_events[PLAT_SDEI_DP_EVENT_MAX_CNT * 3]; + uint32_t shared_events[PLAT_SDEI_DS_EVENT_MAX_CNT * 3]; + + const void *dtb = (void *)config; + + /* Check that the node offset points to compatible property */ + node = fdt_node_offset_by_compatible(dtb, -1, "arm,sdei-1.0"); + if (node < 0) { + ERROR("FCONF: Can't find 'arm,sdei-1.0' compatible node in dtb\n"); + return node; + } + + /* Read number of private mappings */ + err = fdt_read_uint32(dtb, node, "private_event_count", + &sdei_dyn_config.private_ev_cnt); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'private_event_count': %u\n", + sdei_dyn_config.private_ev_cnt); + return err; + } + + /* Check if the value is in range */ + if (sdei_dyn_config.private_ev_cnt > PLAT_SDEI_DP_EVENT_MAX_CNT) { + ERROR("FCONF: Invalid value for 'private_event_count': %u\n", + sdei_dyn_config.private_ev_cnt); + return -1; + } + + /* Read private mappings */ + err = fdt_read_uint32_array(dtb, node, "private_events", + sdei_dyn_config.private_ev_cnt * 3, private_events); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'private_events': %d\n", err); + return err; + } + + /* Move data to fconf struct */ + for (i = 0; i < sdei_dyn_config.private_ev_cnt; i++) { + sdei_dyn_config.private_ev_nums[i] = PRIVATE_EVENT_NUM(i); + sdei_dyn_config.private_ev_intrs[i] = PRIVATE_EVENT_INTR(i); + sdei_dyn_config.private_ev_flags[i] = PRIVATE_EVENT_FLAGS(i); + } + + /* Read number of shared mappings */ + err = fdt_read_uint32(dtb, node, "shared_event_count", + &sdei_dyn_config.shared_ev_cnt); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'shared_event_count'\n"); + return err; + } + + /* Check if the value is in range */ + if (sdei_dyn_config.shared_ev_cnt > PLAT_SDEI_DS_EVENT_MAX_CNT) { + ERROR("FCONF: Invalid value for 'shared_event_count': %u\n", + sdei_dyn_config.shared_ev_cnt); + return -1; + } + + /* Read shared mappings */ + err = fdt_read_uint32_array(dtb, node, "shared_events", + sdei_dyn_config.shared_ev_cnt * 3, shared_events); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'shared_events': %d\n", err); + return err; + } + + /* Move data to fconf struct */ + for (i = 0; i < sdei_dyn_config.shared_ev_cnt; i++) { + sdei_dyn_config.shared_ev_nums[i] = SHARED_EVENT_NUM(i); + sdei_dyn_config.shared_ev_intrs[i] = SHARED_EVENT_INTR(i); + sdei_dyn_config.shared_ev_flags[i] = SHARED_EVENT_FLAGS(i); + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, sdei, fconf_populate_sdei_dyn_config); diff --git a/arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c b/arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c new file mode 100644 index 0000000..f28be24 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include + +#define G0_INTR_NUM(i) g0_intr_prop[3U * (i)] +#define G0_INTR_PRIORITY(i) g0_intr_prop[3U * (i) + 1] +#define G0_INTR_CONFIG(i) g0_intr_prop[3U * (i) + 2] + +#define G1S_INTR_NUM(i) g1s_intr_prop[3U * (i)] +#define G1S_INTR_PRIORITY(i) g1s_intr_prop[3U * (i) + 1] +#define G1S_INTR_CONFIG(i) g1s_intr_prop[3U * (i) + 2] + +struct sec_intr_prop_t sec_intr_prop; + +static void print_intr_prop(interrupt_prop_t prop) +{ + VERBOSE("FCONF: Secure Interrupt NUM: %d, PRI: %d, TYPE: %d\n", + prop.intr_num, prop.intr_pri, prop.intr_cfg); +} + +int fconf_populate_sec_intr_config(uintptr_t config) +{ + int node, err; + uint32_t g0_intr_count, g1s_intr_count; + uint32_t g0_intr_prop[SEC_INT_COUNT_MAX * 3]; + uint32_t g1s_intr_prop[SEC_INT_COUNT_MAX * 3]; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)config; + + node = fdt_node_offset_by_compatible(hw_config_dtb, -1, + "arm,secure_interrupt_desc"); + if (node < 0) { + ERROR("FCONF: Unable to locate node with %s compatible property\n", + "arm,secure_interrupt_desc"); + return node; + } + + /* Read number of Group 0 interrupts specified by platform */ + err = fdt_read_uint32(hw_config_dtb, node, "g0_intr_cnt", &g0_intr_count); + if (err < 0) { + ERROR("FCONF: Could not locate g0s_intr_cnt property\n"); + return err; + } + + /* At least 1 Group 0 interrupt description has to be provided*/ + if (g0_intr_count < 1U) { + ERROR("FCONF: Invalid number of Group 0 interrupts count specified\n"); + return -1; + } + + /* Read number of Group 1 secure interrupts specified by platform */ + err = fdt_read_uint32(hw_config_dtb, node, "g1s_intr_cnt", + &g1s_intr_count); + if (err < 0) { + ERROR("FCONF: Could not locate g1s_intr_cnt property\n"); + return err; + } + + /* At least one Group 1 interrupt description has to be provided*/ + if (g1s_intr_count < 1U) { + ERROR("FCONF: Invalid number of Group 1 secure interrupts count specified\n"); + return -1; + } + + /* + * Check if the total number of secure interrupts described are within + * the limit defined statically by the platform. + */ + if ((g0_intr_count + g1s_intr_count) > SEC_INT_COUNT_MAX) { + ERROR("FCONF: Total number of secure interrupts exceed limit the of %d\n", + SEC_INT_COUNT_MAX); + return -1; + } + + sec_intr_prop.count = g0_intr_count + g1s_intr_count; + + /* Read the Group 0 interrupt descriptors */ + err = fdt_read_uint32_array(hw_config_dtb, node, "g0_intr_desc", + g0_intr_count * 3, g0_intr_prop); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'g0s_intr_desc': %d\n", err); + return err; + } + + /* Read the Group 1 secure interrupt descriptors */ + err = fdt_read_uint32_array(hw_config_dtb, node, "g1s_intr_desc", + g1s_intr_count * 3, g1s_intr_prop); + if (err < 0) { + ERROR("FCONF: Read cell failed for 'g1s_intr_desc': %d\n", err); + return err; + } + + /* Populate Group 0 interrupt descriptors into fconf based C struct */ + for (uint32_t i = 0; i < g0_intr_count; i++) { + interrupt_prop_t sec_intr_property; + + /* Secure Interrupt Group: INTR_GROUP0 i.e., 0x1 */ + sec_intr_property.intr_grp = 1; + sec_intr_property.intr_num = G0_INTR_NUM(i); + sec_intr_property.intr_pri = G0_INTR_PRIORITY(i); + sec_intr_property.intr_cfg = G0_INTR_CONFIG(i); + sec_intr_prop.descriptor[i] = sec_intr_property; + print_intr_prop(sec_intr_property); + } + + /* Populate G1 secure interrupt descriptors into fconf based C struct */ + for (uint32_t i = 0; i < g1s_intr_count; i++) { + interrupt_prop_t sec_intr_property; + + /* Secure Interrupt Group: INTR_GROUP1S i.e., 0x0 */ + sec_intr_property.intr_grp = 0; + sec_intr_property.intr_num = G1S_INTR_NUM(i); + sec_intr_property.intr_pri = G1S_INTR_PRIORITY(i); + sec_intr_property.intr_cfg = G1S_INTR_CONFIG(i); + sec_intr_prop.descriptor[i + g0_intr_count] = sec_intr_property; + print_intr_prop(sec_intr_property); + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, sec_intr_prop, fconf_populate_sec_intr_config); diff --git a/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min.mk b/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min.mk new file mode 100644 index 0000000..dbd451c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min.mk @@ -0,0 +1,20 @@ +# +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP MIN source files common to ARM standard platforms + +# Skip building BL1, BL2 and BL2U if RESET_TO_SP_MIN flag is set. +ifeq (${RESET_TO_SP_MIN},1) + BL1_SOURCES = + BL2_SOURCES = + BL2U_SOURCES = +endif + +BL32_SOURCES += plat/arm/common/arm_pm.c \ + plat/arm/common/arm_topology.c \ + plat/arm/common/sp_min/arm_sp_min_setup.c \ + plat/common/aarch32/platform_mp_stack.S \ + plat/common/plat_psci_common.c diff --git a/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c b/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c new file mode 100644 index 0000000..f15c137 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c @@ -0,0 +1,241 @@ +/* + * 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 + +static entry_point_info_t bl33_image_ep_info; + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak sp_min_platform_setup +#pragma weak sp_min_plat_arch_setup +#pragma weak plat_arm_sp_min_early_platform_setup + +#define MAP_BL_SP_MIN_TOTAL MAP_REGION_FLAT( \ + BL32_BASE, \ + BL32_END - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Check that BL32_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page + * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2. + */ +#if !RESET_TO_SP_MIN +CASSERT(BL32_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl32_base_overflows); +#endif + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for the + * security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) +{ + entry_point_info_t *next_image_info; + + next_image_info = &bl33_image_ep_info; + + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Utility function to perform early platform setup. + ******************************************************************************/ +void arm_sp_min_early_platform_setup(void *from_bl2, uintptr_t tos_fw_config, + uintptr_t hw_config, void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + arm_console_boot_init(); + +#if RESET_TO_SP_MIN + /* There are no parameters from BL2 if SP_MIN is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell SP_MIN where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +# if ARM_LINUX_KERNEL_AS_BL33 + /* + * According to the file ``Documentation/arm/Booting`` of the Linux + * kernel tree, Linux expects: + * r0 = 0 + * r1 = machine type number, optional in DT-only platforms (~0 if so) + * r2 = Physical address of the device tree blob + */ + bl33_image_ep_info.args.arg0 = 0U; + bl33_image_ep_info.args.arg1 = ~0U; + bl33_image_ep_info.args.arg2 = (u_register_t)ARM_PRELOADED_DTB_BASE; +# endif + +#else /* RESET_TO_SP_MIN */ + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + break; + } + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0) + panic(); + +#endif /* RESET_TO_SP_MIN */ + +} + +/******************************************************************************* + * Default implementation for sp_min_platform_setup2() for ARM platforms + ******************************************************************************/ +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * Platform specific PSCI code will enable coherency for other + * clusters. + */ + plat_arm_interconnect_enter_coherency(); +} + +void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + plat_arm_sp_min_early_platform_setup(arg0, arg1, arg2, arg3); +} + +/******************************************************************************* + * Perform any SP_MIN platform runtime setup prior to SP_MIN exit. + * Common to ARM standard platforms. + ******************************************************************************/ +void arm_sp_min_plat_runtime_setup(void) +{ + /* Initialize the runtime console */ + arm_console_runtime_init(); + +#if PLAT_RO_XLAT_TABLES + arm_xlat_make_tables_readonly(); +#endif +} + +/******************************************************************************* + * Perform platform specific setup for SP_MIN + ******************************************************************************/ +void sp_min_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + plat_arm_gic_driver_init(); + plat_arm_gic_init(); + + /* + * Do initial security configuration to allow DRAM/device access + * (if earlier BL has not already done so). + */ +#if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME + plat_arm_security_setup(); + +#if defined(PLAT_ARM_MEM_PROT_ADDR) + arm_nor_psci_do_dyn_mem_protect(); +#endif /* PLAT_ARM_MEM_PROT_ADDR */ + +#endif + + /* Enable and initialize the System level generic timer */ +#ifdef ARM_SYS_CNTCTL_BASE + mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0U) | CNTCR_EN); +#endif +#ifdef ARM_SYS_TIMCTL_BASE + /* Allow access to the System counter timer module */ + arm_configure_sys_timer(); +#endif + /* Initialize power controller before setting up topology */ + plat_arm_pwrc_setup(); +} + +void sp_min_plat_runtime_setup(void) +{ + arm_sp_min_plat_runtime_setup(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this only initializes the MMU + ******************************************************************************/ +void arm_sp_min_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_BL_SP_MIN_TOTAL, + ARM_MAP_BL_RO, +#if USE_COHERENT_MEM + ARM_MAP_BL_COHERENT_RAM, +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + + enable_mmu_svc_mon(0); +} + +void sp_min_plat_arch_setup(void) +{ + arm_sp_min_plat_arch_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/common/trp/arm_trp.mk b/arm-trusted-firmware/plat/arm/common/trp/arm_trp.mk new file mode 100644 index 0000000..997111f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/trp/arm_trp.mk @@ -0,0 +1,10 @@ +# +# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# TRP source files common to ARM standard platforms +RMM_SOURCES += plat/arm/common/trp/arm_trp_setup.c \ + plat/arm/common/arm_topology.c \ + plat/common/aarch64/platform_mp_stack.S diff --git a/arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c b/arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c new file mode 100644 index 0000000..8e48293 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Initialize the UART + ******************************************************************************/ +static console_t arm_trp_runtime_console; + +void arm_trp_early_platform_setup(void) +{ + /* + * Initialize a different console than already in use to display + * messages from trp + */ + int rc = console_pl011_register(PLAT_ARM_TRP_UART_BASE, + PLAT_ARM_TRP_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE, + &arm_trp_runtime_console); + if (rc == 0) { + panic(); + } + + console_set_scope(&arm_trp_runtime_console, + CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME); +} + +void trp_early_platform_setup(void) +{ + arm_trp_early_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp.mk b/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp.mk new file mode 100644 index 0000000..4ad77c6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp.mk @@ -0,0 +1,10 @@ +# +# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# TSP source files common to ARM standard platforms +BL32_SOURCES += plat/arm/common/arm_topology.c \ + plat/arm/common/tsp/arm_tsp_setup.c \ + plat/common/aarch64/platform_mp_stack.S diff --git a/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c b/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c new file mode 100644 index 0000000..a4da8c3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak tsp_early_platform_setup +#pragma weak tsp_platform_setup +#pragma weak tsp_plat_arch_setup + +#define MAP_BL_TSP_TOTAL MAP_REGION_FLAT( \ + BL32_BASE, \ + BL32_END - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/******************************************************************************* + * Initialize the UART + ******************************************************************************/ +static console_t arm_tsp_runtime_console; + +void arm_tsp_early_platform_setup(void) +{ + /* + * Initialize a different console than already in use to display + * messages from TSP + */ + int rc = console_pl011_register(PLAT_ARM_TSP_UART_BASE, + PLAT_ARM_TSP_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE, + &arm_tsp_runtime_console); + if (rc == 0) + panic(); + + console_set_scope(&arm_tsp_runtime_console, + CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME); +} + +void tsp_early_platform_setup(void) +{ + arm_tsp_early_platform_setup(); +} + +/******************************************************************************* + * Perform platform specific setup placeholder + ******************************************************************************/ +void tsp_platform_setup(void) +{ + plat_arm_gic_driver_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the MMU + ******************************************************************************/ +void tsp_plat_arch_setup(void) +{ +#if USE_COHERENT_MEM + /* Ensure ARM platforms don't use coherent memory in TSP */ + assert((BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE) == 0U); +#endif + + const mmap_region_t bl_regions[] = { + MAP_BL_TSP_TOTAL, + ARM_MAP_BL_RO, + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + enable_mmu_el1(0); + +#if PLAT_RO_XLAT_TABLES + arm_xlat_make_tables_readonly(); +#endif +} diff --git a/arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S b/arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S new file mode 100644 index 0000000..d47e13d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .weak plat_secondary_cold_boot_setup + .weak plat_get_my_entrypoint + .globl css_calc_core_pos_swap_cluster + .weak plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup(void); + * In the normal boot flow, cold-booting secondary + * CPUs is not yet implemented and they panic. + * --------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* TODO: Implement secondary CPU cold boot setup on CSS platforms */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. On CSS platforms, this distinction is based on the contents of + * the Trusted Mailbox. It is initialised to zero by the SCP before the + * AP cores are released from reset. Therefore, a zero mailbox means + * it's a cold reset. + * + * This functions returns the contents of the mailbox, i.e.: + * - 0 for a cold boot; + * - the warm boot entrypoint for a warm boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr r0, [r0] + bx lr +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------------- + * unsigned int css_calc_core_pos_swap_cluster(u_register_t mpidr) + * Utility function to calculate the core position by + * swapping the cluster order. This is necessary in order to + * match the format of the boot information passed by the SCP + * and read in plat_is_my_cpu_primary below. + * ----------------------------------------------------------- + */ +func css_calc_core_pos_swap_cluster + and r1, r0, #MPIDR_CPU_MASK + and r0, r0, #MPIDR_CLUSTER_MASK + eor r0, r0, #(1 << MPIDR_AFFINITY_BITS) // swap cluster order + add r0, r1, r0, LSR #6 + bx lr +endfunc css_calc_core_pos_swap_cluster + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu (applicable ony after a cold boot) + * ----------------------------------------------------- + */ +#if CSS_USE_SCMI_SDS_DRIVER +func plat_is_my_cpu_primary + mov r10, lr + bl plat_my_core_pos + mov r4, r0 + bl sds_get_primary_cpu_id + /* Check for error */ + mov r1, #0xffffffff + cmp r0, r1 + beq 1f + cmp r0, r4 + moveq r0, #1 + movne r0, #0 + bx r10 +1: + no_ret plat_panic_handler +endfunc plat_is_my_cpu_primary +#else +func plat_is_my_cpu_primary + mov r10, lr + bl plat_my_core_pos + ldr r1, =SCP_BOOT_CFG_ADDR + ldr r1, [r1] + ubfx r1, r1, #PLAT_CSS_PRIMARY_CPU_SHIFT, \ + #PLAT_CSS_PRIMARY_CPU_BIT_WIDTH + cmp r0, r1 + moveq r0, #1 + movne r0, #0 + bx r10 +endfunc plat_is_my_cpu_primary +#endif diff --git a/arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S b/arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S new file mode 100644 index 0000000..01669be --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .weak plat_secondary_cold_boot_setup + .weak plat_get_my_entrypoint + .globl css_calc_core_pos_swap_cluster + .weak plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup(void); + * + * In the normal boot flow, cold-booting secondary CPUs is not yet + * implemented and they panic. + * + * When booting an EL3 payload, secondary CPUs are placed in a holding + * pen, waiting for their mailbox to be populated. Note that all CPUs + * share the same mailbox ; therefore, populating it will release all + * CPUs from their holding pen. If finer-grained control is needed then + * this should be handled in the code that secondary CPUs jump to. + * --------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +#ifndef EL3_PAYLOAD_BASE + /* TODO: Implement secondary CPU cold boot setup on CSS platforms */ +cb_panic: + b cb_panic +#else + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + + /* Wait until the mailbox gets populated */ +poll_mailbox: + ldr x1, [x0] + cbz x1, 1f + br x1 +1: + wfe + b poll_mailbox +#endif /* EL3_PAYLOAD_BASE */ +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. On CSS platforms, this distinction is based on the contents of + * the Trusted Mailbox. It is initialised to zero by the SCP before the + * AP cores are released from reset. Therefore, a zero mailbox means + * it's a cold reset. + * + * This functions returns the contents of the mailbox, i.e.: + * - 0 for a cold boot; + * - the warm boot entrypoint for a warm boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr x0, [x0] + ret +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------------- + * unsigned int css_calc_core_pos_swap_cluster(u_register_t mpidr) + * Utility function to calculate the core position by + * swapping the cluster order. This is necessary in order to + * match the format of the boot information passed by the SCP + * and read in plat_is_my_cpu_primary below. + * ----------------------------------------------------------- + */ +func css_calc_core_pos_swap_cluster + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + eor x0, x0, #(1 << MPIDR_AFFINITY_BITS) // swap cluster order + add x0, x1, x0, LSR #6 + ret +endfunc css_calc_core_pos_swap_cluster + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu (applicable ony after a cold boot) + * ----------------------------------------------------- + */ +#if CSS_USE_SCMI_SDS_DRIVER +func plat_is_my_cpu_primary + mov x9, x30 + bl plat_my_core_pos + mov x4, x0 + bl sds_get_primary_cpu_id + /* Check for error */ + mov x1, #0xffffffff + cmp x0, x1 + b.eq 1f + cmp x0, x4 + cset w0, eq + ret x9 +1: + no_ret plat_panic_handler +endfunc plat_is_my_cpu_primary +#else +func plat_is_my_cpu_primary + mov x9, x30 + bl plat_my_core_pos + mov_imm x1, SCP_BOOT_CFG_ADDR + ldr x1, [x1] + ubfx x1, x1, #PLAT_CSS_PRIMARY_CPU_SHIFT, \ + #PLAT_CSS_PRIMARY_CPU_BIT_WIDTH + cmp x0, x1 + cset w0, eq + ret x9 +endfunc plat_is_my_cpu_primary +#endif diff --git a/arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c b/arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c new file mode 100644 index 0000000..596cc3d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +void bl1_platform_setup(void) +{ + arm_bl1_platform_setup(); + /* + * Do ARM CSS SoC security setup. + * BL1 needs to enable normal world access to memory. + */ + soc_css_security_setup(); +} + diff --git a/arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c b/arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c new file mode 100644 index 0000000..002c6eb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Weak definition may be overridden in specific CSS based platform */ +#pragma weak plat_arm_bl2_handle_scp_bl2 + +/******************************************************************************* + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int plat_arm_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + int ret; + + INFO("BL2: Initiating SCP_BL2 transfer to SCP\n"); + + ret = css_scp_boot_image_xfer((void *)scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + + if (ret == 0) + ret = css_scp_boot_ready(); + + if (ret == 0) + INFO("BL2: SCP_BL2 transferred to SCP\n"); + else + ERROR("BL2: SCP_BL2 transfer failure\n"); + + return ret; +} + +#if !CSS_USE_SCMI_SDS_DRIVER +# if defined(EL3_PAYLOAD_BASE) || JUNO_AARCH32_EL3_RUNTIME + +/* + * We need to override some of the platform functions when booting an EL3 + * payload or SP_MIN on Juno AArch32. This needs to be done only for + * SCPI/BOM SCP systems as in case of SDS, the structures remain in memory and + * don't need to be overwritten. + */ + +static unsigned int scp_boot_config; + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); + + /* Save SCP Boot config before it gets overwritten by SCP_BL2 loading */ + scp_boot_config = mmio_read_32(SCP_BOOT_CFG_ADDR); + VERBOSE("BL2: Saved SCP Boot config = 0x%x\n", scp_boot_config); +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); + + /* + * Before releasing the AP cores out of reset, the SCP writes some data + * at the beginning of the Trusted SRAM. It is is overwritten before + * reaching this function. We need to restore this data, as if the + * target had just come out of reset. This implies: + * - zeroing the first 128 bytes of Trusted SRAM using zeromem instead + * of zero_normalmem since this is device memory. + * - restoring the SCP boot configuration. + */ + VERBOSE("BL2: Restoring SCP reset data in Trusted SRAM\n"); + zeromem((void *) ARM_SHARED_RAM_BASE, 128); + mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config); +} + +# endif /* EL3_PAYLOAD_BASE */ + +#endif /* CSS_USE_SCMI_SDS_DRIVER */ diff --git a/arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c b/arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c new file mode 100644 index 0000000..15cf4f6 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* Weak definition may be overridden in specific CSS based platform */ +#pragma weak bl2u_plat_handle_scp_bl2u + +/* Data structure which holds the SCP_BL2U image info for BL2U */ +static image_info_t scp_bl2u_image_info; + +/******************************************************************************* + * BL1 can pass platform dependent information to BL2U in x1. + * In case of ARM CSS platforms x1 contains SCP_BL2U image info. + * In case of ARM FVP platforms x1 is not used. + * In both cases, x0 contains the extents of the memory available to BL2U + ******************************************************************************/ +void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) +{ + if (!plat_info) + panic(); + + arm_bl2u_early_platform_setup(mem_layout, plat_info); + + scp_bl2u_image_info = *(image_info_t *)plat_info; +} + +/******************************************************************************* + * Transfer SCP_BL2U from Trusted RAM using the SCP Download protocol. + ******************************************************************************/ +int bl2u_plat_handle_scp_bl2u(void) +{ + int ret; + + INFO("BL2U: Initiating SCP_BL2U transfer to SCP\n"); + + ret = css_scp_boot_image_xfer((void *)scp_bl2u_image_info.image_base, + scp_bl2u_image_info.image_size); + + if (ret == 0) + ret = css_scp_boot_ready(); + + if (ret == 0) + INFO("BL2U: SCP_BL2U transferred to SCP\n"); + else + ERROR("BL2U: SCP_BL2U transfer failure\n"); + + return ret; +} diff --git a/arm-trusted-firmware/plat/arm/css/common/css_common.mk b/arm-trusted-firmware/plat/arm/css/common/css_common.mk new file mode 100644 index 0000000..2fbbe45 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/css_common.mk @@ -0,0 +1,90 @@ +# +# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + + +# By default, SCP images are needed by CSS platforms. +CSS_LOAD_SCP_IMAGES ?= 1 + +# By default, SCMI driver is disabled for CSS platforms +CSS_USE_SCMI_SDS_DRIVER ?= 0 + +PLAT_INCLUDES += -Iinclude/plat/arm/css/common/aarch64 + + +PLAT_BL_COMMON_SOURCES += plat/arm/css/common/${ARCH}/css_helpers.S + +BL1_SOURCES += plat/arm/css/common/css_bl1_setup.c + +BL2_SOURCES += plat/arm/css/common/css_bl2_setup.c + +BL2U_SOURCES += plat/arm/css/common/css_bl2u_setup.c + +BL31_SOURCES += plat/arm/css/common/css_pm.c \ + plat/arm/css/common/css_topology.c + +ifeq (${CSS_USE_SCMI_SDS_DRIVER},0) +BL31_SOURCES += drivers/arm/css/mhu/css_mhu.c \ + drivers/arm/css/scp/css_pm_scpi.c \ + drivers/arm/css/scpi/css_scpi.c +else +BL31_SOURCES += drivers/arm/css/mhu/css_mhu_doorbell.c \ + drivers/arm/css/scmi/scmi_ap_core_proto.c \ + drivers/arm/css/scmi/scmi_common.c \ + drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \ + drivers/arm/css/scmi/scmi_sys_pwr_proto.c \ + drivers/arm/css/scp/css_pm_scmi.c +endif + +# Process CSS_LOAD_SCP_IMAGES flag +$(eval $(call assert_boolean,CSS_LOAD_SCP_IMAGES)) +$(eval $(call add_define,CSS_LOAD_SCP_IMAGES)) + +ifeq (${CSS_LOAD_SCP_IMAGES},1) + NEED_SCP_BL2 := yes + ifneq (${TRUSTED_BOARD_BOOT},0) + $(eval $(call TOOL_ADD_IMG,scp_bl2u,--scp-fwu-cfg,FWU_)) + endif + + ifeq (${CSS_USE_SCMI_SDS_DRIVER},1) + BL2U_SOURCES += drivers/arm/css/scp/css_sds.c \ + drivers/arm/css/sds/sds.c + + BL2_SOURCES += drivers/arm/css/scp/css_sds.c \ + drivers/arm/css/sds/sds.c + else + BL2U_SOURCES += drivers/arm/css/mhu/css_mhu.c \ + drivers/arm/css/scp/css_bom_bootloader.c \ + drivers/arm/css/scpi/css_scpi.c + + BL2_SOURCES += drivers/arm/css/mhu/css_mhu.c \ + drivers/arm/css/scp/css_bom_bootloader.c \ + drivers/arm/css/scpi/css_scpi.c + # Enable option to detect whether the SCP ROM firmware in use predates version + # 1.7.0 and therefore, is incompatible. + CSS_DETECT_PRE_1_7_0_SCP := 1 + + # Process CSS_DETECT_PRE_1_7_0_SCP flag + $(eval $(call assert_boolean,CSS_DETECT_PRE_1_7_0_SCP)) + $(eval $(call add_define,CSS_DETECT_PRE_1_7_0_SCP)) + endif +endif + +ifeq (${CSS_USE_SCMI_SDS_DRIVER},1) + PLAT_BL_COMMON_SOURCES += drivers/arm/css/sds/${ARCH}/sds_helpers.S +endif + +# Process CSS_USE_SCMI_SDS_DRIVER flag +$(eval $(call assert_boolean,CSS_USE_SCMI_SDS_DRIVER)) +$(eval $(call add_define,CSS_USE_SCMI_SDS_DRIVER)) + +# Process CSS_NON_SECURE_UART flag +# This undocumented build option is only to enable debug access to the UART +# from non secure code, which is useful on some platforms. +# Default (obviously) is off. +CSS_NON_SECURE_UART := 0 +$(eval $(call assert_boolean,CSS_NON_SECURE_UART)) +$(eval $(call add_define,CSS_NON_SECURE_UART)) + diff --git a/arm-trusted-firmware/plat/arm/css/common/css_pm.c b/arm-trusted-firmware/plat/arm/css/common/css_pm.c new file mode 100644 index 0000000..926b8ec --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/css_pm.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* Allow CSS platforms to override `plat_arm_psci_pm_ops` */ +#pragma weak plat_arm_psci_pm_ops + +#if ARM_RECOM_STATE_ID_ENC +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +const unsigned int arm_pm_idle_states[] = { + /* State-id - 0x001 */ + arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RUN, + ARM_LOCAL_STATE_RET, ARM_PWR_LVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x002 */ + arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RUN, + ARM_LOCAL_STATE_OFF, ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x022 */ + arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF, + ARM_LOCAL_STATE_OFF, ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN), +#if PLAT_MAX_PWR_LVL > ARM_PWR_LVL1 + /* State-id - 0x222 */ + arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF, + ARM_LOCAL_STATE_OFF, ARM_PWR_LVL2, PSTATE_TYPE_POWERDOWN), +#endif + 0, +}; +#endif /* __ARM_RECOM_STATE_ID_ENC__ */ + +/* + * All the power management helpers in this file assume at least cluster power + * level is supported. + */ +CASSERT(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL1, + assert_max_pwr_lvl_supported_mismatch); + +/* + * Ensure that the PLAT_MAX_PWR_LVL is not greater than CSS_SYSTEM_PWR_DMN_LVL + * assumed by the CSS layer. + */ +CASSERT(PLAT_MAX_PWR_LVL <= CSS_SYSTEM_PWR_DMN_LVL, + assert_max_pwr_lvl_higher_than_css_sys_lvl); + +/******************************************************************************* + * Handler called when a power domain is about to be turned on. The + * level and mpidr determine the affinity instance. + ******************************************************************************/ +int css_pwr_domain_on(u_register_t mpidr) +{ + css_scp_on(mpidr); + + return PSCI_E_SUCCESS; +} + +static void css_pwr_domain_on_finisher_common( + const psci_power_state_t *target_state) +{ + assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF); + + /* + * Perform the common cluster specific operations i.e enable coherency + * if this cluster was off. + */ + if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) + plat_arm_interconnect_enter_coherency(); +} + +/******************************************************************************* + * Handler called when a power level has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. This handler would never be invoked with + * the system power domain uninitialized as either the primary would have taken + * care of it as part of cold boot or the first core awakened from system + * suspend would have already initialized it. + ******************************************************************************/ +void css_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* Assert that the system power domain need not be initialized */ + assert(css_system_pwr_state(target_state) == ARM_LOCAL_STATE_RUN); + + css_pwr_domain_on_finisher_common(target_state); +} + +/******************************************************************************* + * Handler called when a power domain has just been powered on and the cpu + * and its cluster are fully participating in coherent transaction on the + * interconnect. Data cache must be enabled for CPU at this point. + ******************************************************************************/ +void css_pwr_domain_on_finish_late(const psci_power_state_t *target_state) +{ + /* Program the gic per-cpu distributor or re-distributor interface */ + plat_arm_gic_pcpu_init(); + + /* Enable the gic cpu interface */ + plat_arm_gic_cpuif_enable(); +} + +/******************************************************************************* + * Common function called while turning a cpu off or suspending it. It is called + * from css_off() or css_suspend() when these functions in turn are called for + * power domain at the highest power level which will be powered down. It + * performs the actions common to the OFF and SUSPEND calls. + ******************************************************************************/ +static void css_power_down_common(const psci_power_state_t *target_state) +{ + /* Prevent interrupts from spuriously waking up this cpu */ + plat_arm_gic_cpuif_disable(); + + /* Turn redistributor off */ + plat_arm_gic_redistif_off(); + + /* Cluster is to be turned off, so disable coherency */ + if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) { + plat_arm_interconnect_exit_coherency(); + +#if HW_ASSISTED_COHERENCY + uint32_t reg; + + /* + * If we have determined this core to be the last man standing and we + * intend to power down the cluster proactively, we provide a hint to + * the power controller that cluster power is not required when all + * cores are powered down. + * Note that this is only an advisory to power controller and is supported + * by SoCs with DynamIQ Shared Units only. + */ + reg = read_clusterpwrdn(); + + /* Clear and set bit 0 : Cluster power not required */ + reg &= ~DSU_CLUSTER_PWR_MASK; + reg |= DSU_CLUSTER_PWR_OFF; + write_clusterpwrdn(reg); +#endif + } +} + +/******************************************************************************* + * Handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void css_pwr_domain_off(const psci_power_state_t *target_state) +{ + assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF); + css_power_down_common(target_state); + css_scp_off(target_state); +} + +/******************************************************************************* + * Handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void css_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + /* + * CSS currently supports retention only at cpu level. Just return + * as nothing is to be done for retention. + */ + if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET) + return; + + + assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF); + css_power_down_common(target_state); + + /* Perform system domain state saving if issuing system suspend */ + if (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF) { + arm_system_pwr_domain_save(); + + /* Power off the Redistributor after having saved its context */ + plat_arm_gic_redistif_off(); + } + + css_scp_suspend(target_state); +} + +/******************************************************************************* + * Handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ******************************************************************************/ +void css_pwr_domain_suspend_finish( + const psci_power_state_t *target_state) +{ + /* Return as nothing is to be done on waking up from retention. */ + if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET) + return; + + /* Perform system domain restore if woken up from system suspend */ + if (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF) + /* + * At this point, the Distributor must be powered on to be ready + * to have its state restored. The Redistributor will be powered + * on as part of gicv3_rdistif_init_restore. + */ + arm_system_pwr_domain_resume(); + + css_pwr_domain_on_finisher_common(target_state); + + /* Enable the gic cpu interface */ + plat_arm_gic_cpuif_enable(); +} + +/******************************************************************************* + * Handlers to shutdown/reboot the system + ******************************************************************************/ +void __dead2 css_system_off(void) +{ + css_scp_sys_shutdown(); +} + +void __dead2 css_system_reset(void) +{ + css_scp_sys_reboot(); +} + +/******************************************************************************* + * Handler called when the CPU power domain is about to enter standby. + ******************************************************************************/ +void css_cpu_standby(plat_local_state_t cpu_state) +{ + unsigned int scr; + + assert(cpu_state == ARM_LOCAL_STATE_RET); + + scr = read_scr_el3(); + /* + * Enable the Non secure interrupt to wake the CPU. + * In GICv3 affinity routing mode, the non secure group1 interrupts use + * the PhysicalFIQ at EL3 whereas in GICv2, it uses the PhysicalIRQ. + * Enabling both the bits works for both GICv2 mode and GICv3 affinity + * routing mode. + */ + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + isb(); + dsb(); + wfi(); + + /* + * Restore SCR to the original value, synchronisation of scr_el3 is + * done by eret while el3_exit to save some execution cycles. + */ + write_scr_el3(scr); +} + +/******************************************************************************* + * Handler called to return the 'req_state' for system suspend. + ******************************************************************************/ +void css_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + /* + * System Suspend is supported only if the system power domain node + * is implemented. + */ + assert(PLAT_MAX_PWR_LVL == CSS_SYSTEM_PWR_DMN_LVL); + + for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF; +} + +/******************************************************************************* + * Handler to query CPU/cluster power states from SCP + ******************************************************************************/ +int css_node_hw_state(u_register_t mpidr, unsigned int power_level) +{ + return css_scp_get_power_state(mpidr, power_level); +} + +/* + * The system power domain suspend is only supported only via + * PSCI SYSTEM_SUSPEND API. PSCI CPU_SUSPEND request to system power domain + * will be downgraded to the lower level. + */ +static int css_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int rc; + rc = arm_validate_power_state(power_state, req_state); + + /* + * Ensure that we don't overrun the pwr_domain_state array in the case + * where the platform supported max power level is less than the system + * power level + */ + +#if (PLAT_MAX_PWR_LVL == CSS_SYSTEM_PWR_DMN_LVL) + + /* + * Ensure that the system power domain level is never suspended + * via PSCI CPU SUSPEND API. Currently system suspend is only + * supported via PSCI SYSTEM SUSPEND API. + */ + + req_state->pwr_domain_state[CSS_SYSTEM_PWR_DMN_LVL] = + ARM_LOCAL_STATE_RUN; +#endif + + return rc; +} + +/* + * Custom `translate_power_state_by_mpidr` handler for CSS. Unlike in the + * `css_validate_power_state`, we do not downgrade the system power + * domain level request in `power_state` as it will be used to query the + * PSCI_STAT_COUNT/RESIDENCY at the system power domain level. + */ +static int css_translate_power_state_by_mpidr(u_register_t mpidr, + unsigned int power_state, + psci_power_state_t *output_state) +{ + return arm_validate_power_state(power_state, output_state); +} + +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t plat_arm_psci_pm_ops = { + .pwr_domain_on = css_pwr_domain_on, + .pwr_domain_on_finish = css_pwr_domain_on_finish, + .pwr_domain_on_finish_late = css_pwr_domain_on_finish_late, + .pwr_domain_off = css_pwr_domain_off, + .cpu_standby = css_cpu_standby, + .pwr_domain_suspend = css_pwr_domain_suspend, + .pwr_domain_suspend_finish = css_pwr_domain_suspend_finish, + .system_off = css_system_off, + .system_reset = css_system_reset, + .validate_power_state = css_validate_power_state, + .validate_ns_entrypoint = arm_validate_psci_entrypoint, + .translate_power_state_by_mpidr = css_translate_power_state_by_mpidr, + .get_node_hw_state = css_node_hw_state, + .get_sys_suspend_power_state = css_get_sys_suspend_power_state, + +#if defined(PLAT_ARM_MEM_PROT_ADDR) + .mem_protect_chk = arm_psci_mem_protect_chk, + .read_mem_protect = arm_psci_read_mem_protect, + .write_mem_protect = arm_nor_psci_write_mem_protect, +#endif +#if CSS_USE_SCMI_SDS_DRIVER + .system_reset2 = css_system_reset2, +#endif +}; diff --git a/arm-trusted-firmware/plat/arm/css/common/css_topology.c b/arm-trusted-firmware/plat/arm/css/common/css_topology.c new file mode 100644 index 0000000..8aca744 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/css_topology.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#if ARM_PLAT_MT +#pragma weak plat_arm_get_cpu_pe_count +#endif + +/****************************************************************************** + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is + * returned in case the MPIDR is invalid. + *****************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + if (arm_check_mpidr(mpidr) == 0) { +#if ARM_PLAT_MT + assert((read_mpidr_el1() & MPIDR_MT_MASK) != 0); + + /* + * The DTB files don't provide the MT bit in the mpidr argument + * so set it manually before calculating core position + */ + mpidr |= MPIDR_MT_MASK; +#endif + return plat_arm_calc_core_pos(mpidr); + } + return -1; +} + +#if ARM_PLAT_MT +/****************************************************************************** + * This function returns the PE count within the physical cpu corresponding to + * `mpidr`. Now one cpu only have one thread, so just return 1. + *****************************************************************************/ +unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr) +{ + return 1; +} +#endif /* ARM_PLAT_MT */ diff --git a/arm-trusted-firmware/plat/arm/css/common/sp_min/css_sp_min.mk b/arm-trusted-firmware/plat/arm/css/common/sp_min/css_sp_min.mk new file mode 100644 index 0000000..6523a16 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/sp_min/css_sp_min.mk @@ -0,0 +1,21 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP MIN source files common to CSS platforms +BL32_SOURCES += plat/arm/css/common/css_pm.c \ + plat/arm/css/common/css_topology.c + +ifeq (${CSS_USE_SCMI_SDS_DRIVER},0) +BL32_SOURCES += drivers/arm/css/mhu/css_mhu.c \ + drivers/arm/css/scp/css_pm_scpi.c \ + drivers/arm/css/scpi/css_scpi.c +else +BL32_SOURCES += drivers/arm/css/mhu/css_mhu_doorbell.c \ + drivers/arm/css/scp/css_pm_scmi.c \ + drivers/arm/css/scmi/scmi_common.c \ + drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \ + drivers/arm/css/scmi/scmi_sys_pwr_proto.c +endif diff --git a/arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S b/arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S new file mode 100644 index 0000000..ced59e8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S @@ -0,0 +1,106 @@ +/* + * 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 + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Helper function to calculate the core position. + * (ChipId * PLAT_ARM_CLUSTER_COUNT * + * CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU) + + * (ClusterId * CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU) + + * (CPUId * CSS_SGI_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((((ChipId * PLAT_ARM_CLUSTER_COUNT) + ClusterId) * + * CSS_SGI_MAX_CPUS_PER_CLUSTER) + CPUId) * CSS_SGI_MAX_PE_PER_CPU + + * ThreadId + * ------------------------------------------------------ + */ + +func plat_arm_calc_core_pos + mov x4, x0 + + /* + * The MT bit in MPIDR is always set for SGI platforms + * and the affinity level 0 corresponds to thread affinity level. + */ + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #PLAT_ARM_CLUSTER_COUNT + madd x2, x3, x4, x2 + mov x4, #CSS_SGI_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x4, #CSS_SGI_MAX_PE_PER_CPU + madd x0, x1, x4, x0 + ret +endfunc plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the CPU MIDR and disable power down bit for + * that CPU. + * ----------------------------------------------------- + */ +func plat_reset_handler + jump_if_cpu_midr CORTEX_A75_MIDR, A75 + jump_if_cpu_midr NEOVERSE_N1_MIDR, N1 + jump_if_cpu_midr NEOVERSE_V1_MIDR, V1 + jump_if_cpu_midr NEOVERSE_N2_MIDR, N2 + ret + + /* ----------------------------------------------------- + * Disable CPU power down bit in power control register + * ----------------------------------------------------- + */ +A75: + mrs x0, CORTEX_A75_CPUPWRCTLR_EL1 + bic x0, x0, #CORTEX_A75_CORE_PWRDN_EN_MASK + msr CORTEX_A75_CPUPWRCTLR_EL1, x0 + isb + ret + +N1: + mrs x0, NEOVERSE_N1_CPUPWRCTLR_EL1 + bic x0, x0, #NEOVERSE_N1_CORE_PWRDN_EN_MASK + msr NEOVERSE_N1_CPUPWRCTLR_EL1, x0 + isb + ret + +V1: + mrs x0, NEOVERSE_V1_CPUPWRCTLR_EL1 + bic x0, x0, #NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_V1_CPUPWRCTLR_EL1, x0 + isb + ret + +N2: + mrs x0, NEOVERSE_N2_CPUPWRCTLR_EL1 + bic x0, x0, #NEOVERSE_N2_CORE_PWRDN_EN_BIT + msr NEOVERSE_N2_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S b/arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S new file mode 100644 index 0000000..521bcc3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * + * There are currently no platform specific regs + * to print. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h new file mode 100644 index 0000000..c9c8c04 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_BASE_PLATFORM_DEF_H +#define SGI_BASE_PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include + +#define PLATFORM_CORE_COUNT (CSS_SGI_CHIP_COUNT * \ + PLAT_ARM_CLUSTER_COUNT * \ + CSS_SGI_MAX_CPUS_PER_CLUSTER * \ + CSS_SGI_MAX_PE_PER_CPU) + +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00040000 /* 256 KB */ + +/* Remote chip address offset (4TB per chip) */ +#define CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) ((ULL(1) << 42) * (n)) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. In addition to that, on + * multi-chip platforms, address regions on each of the remote chips are + * also mapped. In BL31, for instance, three address regions on the remote + * chips are accessed - secure ram, css device and soc device regions. + */ +#if defined(IMAGE_BL31) +# if SPM_MM +# define PLAT_ARM_MMAP_ENTRIES (9 + ((CSS_SGI_CHIP_COUNT - 1) * 3)) +# define MAX_XLAT_TABLES (7 + ((CSS_SGI_CHIP_COUNT - 1) * 3)) +# define PLAT_SP_IMAGE_MMAP_REGIONS 9 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 11 +# else +# define PLAT_ARM_MMAP_ENTRIES (5 + ((CSS_SGI_CHIP_COUNT - 1) * 3)) +# define MAX_XLAT_TABLES (6 + ((CSS_SGI_CHIP_COUNT - 1) * 3)) +# endif +#elif defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 5 +#elif defined(IMAGE_BL2) +# define PLAT_ARM_MMAP_ENTRIES (11 + (CSS_SGI_CHIP_COUNT - 1)) + +/* + * MAX_XLAT_TABLES entries need to be doubled because when the address width + * exceeds 40 bits an additional level of translation is required. In case of + * multichip platforms peripherals also fall into address space with width + * > 40 bits + * + */ +# define MAX_XLAT_TABLES (7 + ((CSS_SGI_CHIP_COUNT - 1) * 2)) +#elif !USE_ROMLIB +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 7 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xC000 + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000 +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000 +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0 +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0 +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. Additional 8KiB space is added per chip in + * order to accommodate the additional level of translation required for "TZC" + * peripheral access which lies in >4TB address space. + * + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE (0x20000 + ((CSS_SGI_CHIP_COUNT - 1) * \ + 0x2000)) +#else +# define PLAT_ARM_MAX_BL2_SIZE (0x14000 + ((CSS_SGI_CHIP_COUNT - 1) * \ + 0x2000)) +#endif + +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL31_SIZE 0x3B000 + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x440 +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +# if SPM_MM +# define PLATFORM_STACK_SIZE 0x500 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + + +#define PLAT_ARM_NSTIMER_FRAME_ID 0 + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x0 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x00080000 /* 512KB */ + +#define PLAT_ARM_NSRAM_BASE 0x06000000 +#define PLAT_ARM_NSRAM_SIZE 0x00080000 /* 512KB */ + +#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000) + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp) +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#define CSS_SGI_DEVICE_BASE (0x20000000) +#define CSS_SGI_DEVICE_SIZE (0x20000000) +#define CSS_SGI_MAP_DEVICE MAP_REGION_FLAT( \ + CSS_SGI_DEVICE_BASE, \ + CSS_SGI_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_SHARED_RAM_REMOTE_CHIP(n) \ + MAP_REGION_FLAT( \ + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + \ + ARM_SHARED_RAM_BASE, \ + ARM_SHARED_RAM_SIZE, \ + MT_NON_CACHEABLE | MT_RW | MT_SECURE \ + ) + +#define CSS_SGI_MAP_DEVICE_REMOTE_CHIP(n) \ + MAP_REGION_FLAT( \ + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + \ + CSS_SGI_DEVICE_BASE, \ + CSS_SGI_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE \ + ) + +#define SOC_CSS_MAP_DEVICE_REMOTE_CHIP(n) \ + MAP_REGION_FLAT( \ + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + \ + SOC_CSS_DEVICE_BASE, \ + SOC_CSS_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE \ + ) + +/* Map the secure region for access from S-EL0 */ +#define PLAT_ARM_SECURE_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_CSS_DEVICE_BASE, \ + SOC_CSS_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE | MT_USER) + +#define PLAT_SP_PRI PLAT_RAS_PRI + +#if SPM_MM && RAS_EXTENSION +/* + * CPER buffer memory of 128KB is reserved and it is placed adjacent to the + * memory shared between EL3 and S-EL0. + */ +#define CSS_SGI_SP_CPER_BUF_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) +#define CSS_SGI_SP_CPER_BUF_SIZE ULL(0x20000) +#define CSS_SGI_SP_CPER_BUF_MMAP MAP_REGION2( \ + CSS_SGI_SP_CPER_BUF_BASE, \ + CSS_SGI_SP_CPER_BUF_BASE, \ + CSS_SGI_SP_CPER_BUF_SIZE, \ + MT_RW_DATA | MT_NS | MT_USER, \ + PAGE_SIZE) + +/* + * Secure partition stack follows right after the memory space reserved for + * CPER buffer memory. + */ +#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE + \ + CSS_SGI_SP_CPER_BUF_SIZE) +#elif SPM_MM +/* + * Secure partition stack follows right after the memory region that is shared + * between EL3 and S-EL0. + */ +#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) +#endif /* SPM_MM && RAS_EXTENSION */ + +/* Platform ID address */ +#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET) +#ifndef __ASSEMBLER__ +/* SSC_VERSION related accessors */ +/* Returns the part number of the platform */ +#define GET_SGI_PART_NUM \ + GET_SSC_VERSION_PART_NUM(mmio_read_32(SSC_VERSION)) +/* Returns the configuration number of the platform */ +#define GET_SGI_CONFIG_NUM \ + GET_SSC_VERSION_CONFIG(mmio_read_32(SSC_VERSION)) +#endif /* __ASSEMBLER__ */ + +/******************************************************************************* + * Memprotect definitions + ******************************************************************************/ +/* PSCI memory protect definitions: + * This variable is stored in a non-secure flash because some ARM reference + * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT + * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions. + */ +#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \ + V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/*Secure Watchdog Constants */ +#define SBSA_SECURE_WDOG_BASE UL(0x2A480000) +#define SBSA_SECURE_WDOG_TIMEOUT UL(100) + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT CSS_SGI_CHIP_COUNT + +/* + * Mapping definition of the TrustZone Controller for ARM SGI/RD platforms + * where both the DRAM regions are marked for non-secure access. This applies + * to multi-chip platforms. + */ +#define SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(n) \ + {CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + ARM_DRAM1_BASE, \ + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + ARM_DRAM1_END, \ + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + ARM_DRAM2_BASE, \ + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + ARM_DRAM2_END, \ + ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS} + +#endif /* SGI_BASE_PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h new file mode 100644 index 0000000..e939163 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_DMC620_TZC_REGIONS_H +#define SGI_DMC620_TZC_REGIONS_H + +#include + +#if SPM_MM +#define CSS_SGI_DMC620_TZC_REGIONS_DEF \ + { \ + .region_base = ARM_AP_TZC_DRAM1_BASE, \ + .region_top = PLAT_SP_IMAGE_NS_BUF_BASE - 1, \ + .sec_attr = TZC_DMC620_REGION_S_RDWR \ + }, { \ + .region_base = PLAT_SP_IMAGE_NS_BUF_BASE, \ + .region_top = PLAT_ARM_SP_IMAGE_STACK_BASE - 1, \ + .sec_attr = TZC_DMC620_REGION_S_NS_RDWR \ + }, { \ + .region_base = PLAT_ARM_SP_IMAGE_STACK_BASE, \ + .region_top = ARM_AP_TZC_DRAM1_END, \ + .sec_attr = TZC_DMC620_REGION_S_RDWR \ + } +#else +#define CSS_SGI_DMC620_TZC_REGIONS_DEF \ + { \ + .region_base = ARM_AP_TZC_DRAM1_BASE, \ + .region_top = ARM_AP_TZC_DRAM1_END, \ + .sec_attr = TZC_DMC620_REGION_S_RDWR \ + } +#endif /* SPM_MM */ + +#endif /* SGI_DMC620_TZC_REGIONS_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h new file mode 100644 index 0000000..a5fbded --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_PLAT_H +#define SGI_PLAT_H + +/* BL31 platform setup common to all SGI based platforms */ +void sgi_bl31_common_platform_setup(void); + +#endif /* SGI_PLAT_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h new file mode 100644 index 0000000..e69a684 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_RAS_H +#define SGI_RAS_H + +/* + * Mapping the RAS interrupt with SDEI event number and the event + * id used with Standalone MM code + */ +struct sgi_ras_ev_map { + int sdei_ev_num; /* SDEI Event number */ + int intr; /* Physical intr number */ +}; + +int sgi_ras_intr_handler_setup(void); + +#endif /* SGI_RAS_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h new file mode 100644 index 0000000..f380122 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_SDEI_H +#define SGI_SDEI_H + +#if SDEI_SUPPORT + +/* ARM SDEI dynamic shared event numbers */ +#define SGI_SDEI_DS_EVENT_0 U(804) +#define SGI_SDEI_DS_EVENT_1 U(805) + +#define PLAT_ARM_PRIVATE_SDEI_EVENTS \ + SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), \ + SDEI_EXPLICIT_EVENT(SGI_SDEI_DS_EVENT_0, SDEI_MAPF_CRITICAL), \ + SDEI_EXPLICIT_EVENT(SGI_SDEI_DS_EVENT_1, SDEI_MAPF_CRITICAL), + +#define PLAT_ARM_SHARED_SDEI_EVENTS + +#endif /* SDEI_SUPPORT */ + +#endif /* SGI_SDEI_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h new file mode 100644 index 0000000..639b687 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_SOC_CSS_DEF_V2_H +#define SGI_SOC_CSS_DEF_V2_H + +#include +#include + +/* + * Definitions common to all ARM CSS SoCs + */ + +/* Following covers ARM CSS SoC Peripherals */ + +#define SOC_SYSTEM_PERIPH_BASE UL(0x0C000000) +#define SOC_SYSTEM_PERIPH_SIZE UL(0x02000000) + +#define SOC_PLATFORM_PERIPH_BASE UL(0x0E000000) +#define SOC_PLATFORM_PERIPH_SIZE UL(0x02000000) + +#define SOC_CSS_PCIE_CONTROL_BASE UL(0x0ef20000) + +/* PL011 UART related constants */ +#define SOC_CSS_UART1_BASE UL(0x0ef80000) +#define SOC_CSS_UART0_BASE UL(0x0ef70000) + +/* Memory controller */ +#define SOC_MEMCNTRL_BASE UL(0x10000000) +#define SOC_MEMCNTRL_SIZE UL(0x10000000) + +#define SOC_CSS_UART0_CLK_IN_HZ UL(7372800) +#define SOC_CSS_UART1_CLK_IN_HZ UL(7372800) + +/* SoC NIC-400 Global Programmers View (GPV) */ +#define SOC_CSS_NIC400_BASE UL(0x0ED00000) + +#define SOC_CSS_NIC400_USB_EHCI U(0) +#define SOC_CSS_NIC400_TLX_MASTER U(1) +#define SOC_CSS_NIC400_USB_OHCI U(2) +#define SOC_CSS_NIC400_PL354_SMC U(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 U(4) + +/* Non-volatile counters */ +#define SOC_TRUSTED_NVCTR_BASE UL(0x0EE70000) +#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0000) +#define TFW_NVCTR_SIZE U(4) +#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004) +#define NTFW_CTR_SIZE U(4) + +/* Keys */ +#define SOC_KEYS_BASE UL(0x0EE80000) +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000) +#define TZ_PUB_KEY_HASH_SIZE U(32) +#define HU_KEY_BASE (SOC_KEYS_BASE + 0x0020) +#define HU_KEY_SIZE U(16) +#define END_KEY_BASE (SOC_KEYS_BASE + 0x0044) +#define END_KEY_SIZE U(32) + +#define SOC_PLATFORM_PERIPH_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_PLATFORM_PERIPH_BASE, \ + SOC_PLATFORM_PERIPH_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#if SPM_MM +/* + * Memory map definition for the platform peripheral memory region that is + * accessible from S-EL0 (with secure user mode access). + */ +#define SOC_PLATFORM_PERIPH_MAP_DEVICE_USER \ + MAP_REGION_FLAT( \ + SOC_PLATFORM_PERIPH_BASE, \ + SOC_PLATFORM_PERIPH_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE | MT_USER) +#endif + +#define SOC_SYSTEM_PERIPH_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_SYSTEM_PERIPH_BASE, \ + SOC_SYSTEM_PERIPH_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define SOC_MEMCNTRL_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_MEMCNTRL_BASE, \ + SOC_MEMCNTRL_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define SOC_MEMCNTRL_MAP_DEVICE_REMOTE_CHIP(n) \ + MAP_REGION_FLAT( \ + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + SOC_MEMCNTRL_BASE, \ + SOC_MEMCNTRL_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 U(5) +#define SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1 UL(1 << 12) + +/* + * Required platform porting definitions common to all ARM CSS SoCs + */ +/* 2MB used for SCP DDR retraining */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x00200000) + +/* V2M motherboard system registers & offsets */ +#define V2M_SYSREGS_BASE UL(0x0C010000) +#define V2M_SYS_LED U(0x8) + +/* + * 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 U(0) +#define V2M_SYS_LED_EL_SHIFT U(1) +#define V2M_SYS_LED_EC_SHIFT U(3) + +#define V2M_SYS_LED_SS_MASK U(0x01) +#define V2M_SYS_LED_EL_MASK U(0x03) +#define V2M_SYS_LED_EC_MASK U(0x1f) + +/* NOR Flash */ +#define V2M_FLASH0_BASE UL(0x08000000) +#define V2M_FLASH0_SIZE UL(0x04000000) +#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */ + +/* + * 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 SGI_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE) + +/* Platform ID address */ +#define BOARD_CSS_PLAT_ID_REG_ADDR UL(0x0EFE00E0) + +/* Platform ID related accessors */ +#define BOARD_CSS_PLAT_ID_REG_ID_MASK U(0x0F) +#define BOARD_CSS_PLAT_ID_REG_ID_SHIFT U(0x00) +#define BOARD_CSS_PLAT_ID_REG_VERSION_MASK U(0xF00) +#define BOARD_CSS_PLAT_ID_REG_VERSION_SHIFT U(0x08) +#define BOARD_CSS_PLAT_TYPE_RTL U(0x00) +#define BOARD_CSS_PLAT_TYPE_FPGA U(0x01) +#define BOARD_CSS_PLAT_TYPE_EMULATOR U(0x02) +#define BOARD_CSS_PLAT_TYPE_FVP U(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 U(3) +#define MAX_IO_HANDLES U(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 + +#endif /* SGI_SOC_CSS_DEF_V2_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h new file mode 100644 index 0000000..405d62f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_SOC_PLATFORM_DEF_H +#define SGI_SOC_PLATFORM_DEF_H + +#include +#include +#include +#include + +/* Map the System registers to access from S-EL0 */ +#define CSS_SYSTEMREG_DEVICE_BASE (0x1C010000) +#define CSS_SYSTEMREG_DEVICE_SIZE (0x00010000) +#define PLAT_ARM_SECURE_MAP_SYSTEMREG MAP_REGION_FLAT( \ + CSS_SYSTEMREG_DEVICE_BASE, \ + CSS_SYSTEMREG_DEVICE_SIZE, \ + (MT_DEVICE | MT_RW | \ + MT_SECURE | MT_USER)) + +/* Map the NOR2 Flash to access from S-EL0 */ +#define CSS_NOR2_FLASH_DEVICE_BASE (0x10000000) +#define CSS_NOR2_FLASH_DEVICE_SIZE (0x04000000) +#define PLAT_ARM_SECURE_MAP_NOR2 MAP_REGION_FLAT( \ + CSS_NOR2_FLASH_DEVICE_BASE, \ + CSS_NOR2_FLASH_DEVICE_SIZE, \ + (MT_DEVICE | MT_RW | \ + MT_SECURE | MT_USER)) + +#endif /* SGI_SOC_PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h new file mode 100644 index 0000000..20dd682 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_SOC_PLATFORM_DEF_V2_H +#define SGI_SOC_PLATFORM_DEF_V2_H + +#include +#include + +/* Map the System registers to access from S-EL0 */ +#define CSS_SYSTEMREG_DEVICE_BASE (0x0C010000) +#define CSS_SYSTEMREG_DEVICE_SIZE (0x00010000) +#define PLAT_ARM_SECURE_MAP_SYSTEMREG MAP_REGION_FLAT( \ + CSS_SYSTEMREG_DEVICE_BASE, \ + CSS_SYSTEMREG_DEVICE_SIZE, \ + (MT_DEVICE | MT_RW | \ + MT_SECURE | MT_USER)) + +/* Map the NOR2 Flash to access from S-EL0 */ +#define CSS_NOR2_FLASH_DEVICE_BASE (0x001054000000) +#define CSS_NOR2_FLASH_DEVICE_SIZE (0x000004000000) +#define PLAT_ARM_SECURE_MAP_NOR2 MAP_REGION_FLAT( \ + CSS_NOR2_FLASH_DEVICE_BASE, \ + CSS_NOR2_FLASH_DEVICE_SIZE, \ + (MT_DEVICE | MT_RW | \ + MT_SECURE | MT_USER)) + +#endif /* SGI_SOC_PLATFORM_DEF_V2_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h new file mode 100644 index 0000000..41467f7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGI_VARIANT_H +#define SGI_VARIANT_H + +/* SSC_VERSION values for SGI575 */ +#define SGI575_SSC_VER_PART_NUM 0x0783 + +/* SID Version values for RD-N1E1-Edge */ +#define RD_N1E1_EDGE_SID_VER_PART_NUM 0x0786 +#define RD_E1_EDGE_CONFIG_ID 0x2 + +/* SID Version values for RD-V1 */ +#define RD_V1_SID_VER_PART_NUM 0x078a + +/* SID Version values for RD-N2 */ +#define RD_N2_SID_VER_PART_NUM 0x07B7 + +/* SID Version values for RD-N2 variants */ +#define RD_N2_CFG1_SID_VER_PART_NUM 0x07B6 + +/* SID Version values for RD-Edmunds */ +#define RD_EDMUNDS_SID_VER_PART_NUM 0x07F2 +#define RD_EDMUNDS_CONFIG_ID 0x1 + +/* Structure containing SGI platform variant information */ +typedef struct sgi_platform_info { + unsigned int platform_id; /* Part Number of the platform */ + unsigned int config_id; /* Config Id of the platform */ + unsigned int chip_id; /* Chip Id or Node number */ + unsigned int multi_chip_mode; /* Multi-chip mode availability */ +} sgi_platform_info_t; + +extern sgi_platform_info_t sgi_plat_info; + +/* returns the part number of the platform*/ +unsigned int plat_arm_sgi_get_platform_id(void); + +/* returns the configuration id of the platform */ +unsigned int plat_arm_sgi_get_config_id(void); + +/* returns true if operating in multi-chip configuration */ +unsigned int plat_arm_sgi_get_multi_chip_mode(void); + +#endif /* SGI_VARIANT_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/sgi-common.mk b/arm-trusted-firmware/plat/arm/css/sgi/sgi-common.mk new file mode 100644 index 0000000..f56fe35 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi-common.mk @@ -0,0 +1,84 @@ +# +# Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +CSS_USE_SCMI_SDS_DRIVER := 1 + +CSS_ENT_BASE := plat/arm/css/sgi + +RAS_EXTENSION := 0 + +SDEI_SUPPORT := 0 + +EL3_EXCEPTION_HANDLING := 0 + +HANDLE_EA_EL3_FIRST := 0 + +CSS_SGI_CHIP_COUNT := 1 + +CSS_SGI_PLATFORM_VARIANT := 0 + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +INTERCONNECT_SOURCES := ${CSS_ENT_BASE}/sgi_interconnect.c + +PLAT_INCLUDES += -I${CSS_ENT_BASE}/include + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +ENT_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c + +PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/aarch64/sgi_helper.S + +BL1_SOURCES += ${INTERCONNECT_SOURCES} \ + drivers/arm/sbsa/sbsa.c + +BL2_SOURCES += ${CSS_ENT_BASE}/sgi_image_load.c + +BL31_SOURCES += ${INTERCONNECT_SOURCES} \ + ${ENT_GIC_SOURCES} \ + ${CSS_ENT_BASE}/sgi_bl31_setup.c \ + ${CSS_ENT_BASE}/sgi_topology.c + +ifeq (${RAS_EXTENSION},1) +BL31_SOURCES += ${CSS_ENT_BASE}/sgi_ras.c +endif + +ifneq (${RESET_TO_BL31},0) + $(error "Using BL31 as the reset vector is not supported on ${PLAT} platform. \ + Please set RESET_TO_BL31 to 0.") +endif + +$(eval $(call add_define,SGI_PLAT)) + +$(eval $(call add_define,CSS_SGI_CHIP_COUNT)) + +$(eval $(call add_define,CSS_SGI_PLATFORM_VARIANT)) + +override CSS_LOAD_SCP_IMAGES := 0 +override NEED_BL2U := no +override ARM_BL31_IN_DRAM := 1 +override ARM_PLAT_MT := 1 +override PSCI_EXTENDED_STATE_ID := 1 +override ARM_RECOM_STATE_ID_ENC := 1 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# 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. +USE_COHERENT_MEM := 0 + +include plat/arm/common/arm_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/soc/common/soc_css.mk +include plat/arm/board/common/board_common.mk diff --git a/arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c new file mode 100644 index 0000000..99f2f20 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c @@ -0,0 +1,127 @@ +/* + * 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 +#include + +sgi_platform_info_t sgi_plat_info; + +static scmi_channel_plat_info_t sgi575_scmi_plat_info = { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell, +}; + +static scmi_channel_plat_info_t plat_rd_scmi_info[] = { + { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0), + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhuv2_ring_doorbell, + }, + #if (CSS_SGI_CHIP_COUNT > 1) + { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1), + .db_reg_addr = PLAT_CSS_MHU_BASE + + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1) + SENDER_REG_SET(0), + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhuv2_ring_doorbell, + }, + #endif + #if (CSS_SGI_CHIP_COUNT > 2) + { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2), + .db_reg_addr = PLAT_CSS_MHU_BASE + + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2) + SENDER_REG_SET(0), + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhuv2_ring_doorbell, + }, + #endif + #if (CSS_SGI_CHIP_COUNT > 3) + { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3), + .db_reg_addr = PLAT_CSS_MHU_BASE + + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3) + SENDER_REG_SET(0), + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhuv2_ring_doorbell, + }, + #endif +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM || + sgi_plat_info.platform_id == RD_V1_SID_VER_PART_NUM || + sgi_plat_info.platform_id == RD_N2_SID_VER_PART_NUM || + sgi_plat_info.platform_id == RD_EDMUNDS_SID_VER_PART_NUM || + sgi_plat_info.platform_id == RD_N2_CFG1_SID_VER_PART_NUM) { + if (channel_id >= ARRAY_SIZE(plat_rd_scmi_info)) + panic(); + return &plat_rd_scmi_info[channel_id]; + } + else if (sgi_plat_info.platform_id == SGI575_SSC_VER_PART_NUM) + return &sgi575_scmi_plat_info; + else + panic(); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + sgi_plat_info.platform_id = plat_arm_sgi_get_platform_id(); + sgi_plat_info.config_id = plat_arm_sgi_get_config_id(); + sgi_plat_info.multi_chip_mode = plat_arm_sgi_get_multi_chip_mode(); + + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); +} + +void sgi_bl31_common_platform_setup(void) +{ + arm_bl31_platform_setup(); + +#if RAS_EXTENSION + sgi_ras_intr_handler_setup(); +#endif +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + /* + * For RD-E1-Edge, only CPU power ON/OFF, PSCI platform callbacks are + * supported. + */ + if (((sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) && + (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID))) { + ops->cpu_standby = NULL; + ops->system_off = NULL; + ops->system_reset = NULL; + ops->get_sys_suspend_power_state = NULL; + ops->pwr_domain_suspend = NULL; + ops->pwr_domain_suspend_finish = NULL; + } + + return css_scmi_override_pm_ops(ops); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c new file mode 100644 index 0000000..09f3b72 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include + +/******************************************************************************* + * This function inserts Platform information via device tree nodes as, + * system-id { + * platform-id = <0>; + * config-id = <0>; + * } + ******************************************************************************/ +static int plat_sgi_append_config_node(void) +{ + bl_mem_params_node_t *mem_params; + void *fdt; + int nodeoffset, err; + unsigned int platid = 0, platcfg = 0; + + mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); + if (mem_params == NULL) { + ERROR("NT_FW CONFIG base address is NULL"); + return -1; + } + + fdt = (void *)(mem_params->image_info.image_base); + + /* Check the validity of the fdt */ + if (fdt_check_header(fdt) != 0) { + ERROR("Invalid NT_FW_CONFIG DTB passed\n"); + return -1; + } + + nodeoffset = fdt_subnode_offset(fdt, 0, "system-id"); + if (nodeoffset < 0) { + ERROR("Failed to get system-id node offset\n"); + return -1; + } + + platid = plat_arm_sgi_get_platform_id(); + err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid); + if (err < 0) { + ERROR("Failed to set platform-id\n"); + return -1; + } + + platcfg = plat_arm_sgi_get_config_id(); + err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg); + if (err < 0) { + ERROR("Failed to set config-id\n"); + return -1; + } + + platcfg = plat_arm_sgi_get_multi_chip_mode(); + err = fdt_setprop_u32(fdt, nodeoffset, "multi-chip-mode", platcfg); + if (err < 0) { + ERROR("Failed to set multi-chip-mode\n"); + return -1; + } + + flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size); + + return 0; +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + int ret; + + ret = plat_sgi_append_config_node(); + if (ret != 0) + panic(); + + return arm_get_next_bl_params(); +} + diff --git a/arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c new file mode 100644 index 0000000..e9cd812 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* + * For SGI575 which support FCM (with automatic interconnect enter/exit), + * we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void __init plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c new file mode 100644 index 0000000..20c52e9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if SPM_MM +#include +#endif + +#define SGI_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_DEVICE | MT_RO | MT_SECURE) +/* + * Table of regions for different BL stages to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * arm_configure_mmu_elx() will give the available subset of that. + * + * Replace or extend the below regions as required + */ +#if IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + SGI_MAP_FLASH0_RO, + CSS_SGI_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + SGI_MAP_FLASH0_RO, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + CSS_SGI_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, + ARM_MAP_NS_DRAM1, +#if CSS_SGI_CHIP_COUNT > 1 + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1), +#endif +#if CSS_SGI_CHIP_COUNT > 2 + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2), +#endif +#if CSS_SGI_CHIP_COUNT > 3 + CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3), +#endif +#if ARM_BL31_IN_DRAM + ARM_MAP_BL31_SEC_DRAM, +#endif +#if SPM_MM + ARM_SP_IMAGE_MMAP, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + CSS_SGI_MAP_DEVICE, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + SOC_CSS_MAP_DEVICE, +#if SPM_MM + ARM_SPM_BUF_EL3_MMAP, +#endif + {0} +}; + +#if SPM_MM && defined(IMAGE_BL31) +const mmap_region_t plat_arm_secure_partition_mmap[] = { + PLAT_ARM_SECURE_MAP_SYSTEMREG, + PLAT_ARM_SECURE_MAP_NOR2, + PLAT_ARM_SECURE_MAP_DEVICE, + ARM_SP_IMAGE_MMAP, + ARM_SP_IMAGE_NS_BUF_MMAP, +#if RAS_EXTENSION + CSS_SGI_SP_CPER_BUF_MMAP, +#endif + ARM_SP_IMAGE_RW_MMAP, + ARM_SPM_BUF_EL0_MMAP, + {0} +}; +#endif /* SPM_MM && defined(IMAGE_BL31) */ +#endif + +ARM_CASSERT_MMAP + +#if SPM_MM && defined(IMAGE_BL31) +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static spm_mm_mp_info_t sp_mp_info[] = { + [0] = {0x81000000, 0}, + [1] = {0x81000100, 0}, + [2] = {0x81000200, 0}, + [3] = {0x81000300, 0}, + [4] = {0x81010000, 0}, + [5] = {0x81010100, 0}, + [6] = {0x81010200, 0}, + [7] = {0x81010300, 0}, +}; + +const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = ARM_SP_IMAGE_BASE, + .sp_mem_limit = ARM_SP_IMAGE_LIMIT, + .sp_image_base = ARM_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = ARM_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = &sp_mp_info[0], +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} +#endif /* SPM_MM && defined(IMAGE_BL31) */ + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c new file mode 100644 index 0000000..1a2a966 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#if SPM_MM +#include +#endif + +/* + * Table of regions for different BL stages to map using the MMU. + */ +#if IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + SGI_MAP_FLASH0_RO, + CSS_SGI_MAP_DEVICE, + SOC_PLATFORM_PERIPH_MAP_DEVICE, + SOC_SYSTEM_PERIPH_MAP_DEVICE, + {0} +}; +#endif + +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + SGI_MAP_FLASH0_RO, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + CSS_SGI_MAP_DEVICE, + SOC_MEMCNTRL_MAP_DEVICE, + SOC_PLATFORM_PERIPH_MAP_DEVICE, + SOC_SYSTEM_PERIPH_MAP_DEVICE, + ARM_MAP_NS_DRAM1, +#if CSS_SGI_CHIP_COUNT > 1 + SOC_MEMCNTRL_MAP_DEVICE_REMOTE_CHIP(1), +#endif +#if CSS_SGI_CHIP_COUNT > 2 + SOC_MEMCNTRL_MAP_DEVICE_REMOTE_CHIP(2), +#endif +#if CSS_SGI_CHIP_COUNT > 3 + SOC_MEMCNTRL_MAP_DEVICE_REMOTE_CHIP(3), +#endif +#if ARM_BL31_IN_DRAM + ARM_MAP_BL31_SEC_DRAM, +#endif +#if SPM_MM + ARM_SP_IMAGE_MMAP, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif + +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif + CSS_SGI_MAP_DEVICE, + SOC_PLATFORM_PERIPH_MAP_DEVICE, + SOC_SYSTEM_PERIPH_MAP_DEVICE, +#if SPM_MM + ARM_SPM_BUF_EL3_MMAP, +#endif + {0} +}; + +#if SPM_MM && defined(IMAGE_BL31) +const mmap_region_t plat_arm_secure_partition_mmap[] = { + PLAT_ARM_SECURE_MAP_SYSTEMREG, + PLAT_ARM_SECURE_MAP_NOR2, + SOC_PLATFORM_PERIPH_MAP_DEVICE_USER, + ARM_SP_IMAGE_MMAP, + ARM_SP_IMAGE_NS_BUF_MMAP, + ARM_SP_IMAGE_RW_MMAP, + ARM_SPM_BUF_EL0_MMAP, + {0} +}; +#endif /* SPM_MM && defined(IMAGE_BL31) */ +#endif + +ARM_CASSERT_MMAP + +#if SPM_MM && defined(IMAGE_BL31) +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static spm_mm_mp_info_t sp_mp_info[] = { + [0] = {0x81000000, 0}, + [1] = {0x81010000, 0}, + [2] = {0x81020000, 0}, + [3] = {0x81030000, 0}, + [4] = {0x81040000, 0}, + [5] = {0x81050000, 0}, + [6] = {0x81060000, 0}, + [7] = {0x81070000, 0}, + [8] = {0x81080000, 0}, + [9] = {0x81090000, 0}, + [10] = {0x810a0000, 0}, + [11] = {0x810b0000, 0}, + [12] = {0x810c0000, 0}, + [13] = {0x810d0000, 0}, + [14] = {0x810e0000, 0}, + [15] = {0x810f0000, 0}, +}; + +const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = ARM_SP_IMAGE_BASE, + .sp_mem_limit = ARM_SP_IMAGE_LIMIT, + .sp_image_base = ARM_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = ARM_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = &sp_mp_info[0], +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} +#endif /* SPM_MM && defined(IMAGE_BL31) */ + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + assert(heap_addr != NULL); + assert(heap_size != NULL); + + return arm_get_mbedtls_heap(heap_addr, heap_size); +} +#endif + +void plat_arm_secure_wdt_start(void) +{ + sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT); +} + +void plat_arm_secure_wdt_stop(void) +{ + sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c new file mode 100644 index 0000000..4f03ac4 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +static int sgi_ras_intr_handler(const struct err_record_info *err_rec, + int probe_data, + const struct err_handler_data *const data); +typedef struct mm_communicate_header { + struct efi_guid header_guid; + size_t message_len; + uint8_t data[8]; +} mm_communicate_header_t; + +/* + * GUID to indicate that the MM communication message is intended for DMC-620 + * MM driver. + */ +const struct efi_guid dmc620_ecc_event_guid = { + 0x5ef0afd5, 0xe01a, 0x4c30, + {0x86, 0x19, 0x45, 0x46, 0x26, 0x91, 0x80, 0x98} +}; + +struct sgi_ras_ev_map sgi575_ras_map[] = { + + /* DMC 0 error ECC error interrupt*/ + {SGI_SDEI_DS_EVENT_0, 35}, + + /* DMC 1 error ECC error interrupt*/ + {SGI_SDEI_DS_EVENT_1, 39}, +}; + +#define SGI575_RAS_MAP_SIZE ARRAY_SIZE(sgi575_ras_map) + +struct err_record_info sgi_err_records[] = { + { + /* DMC 0 error record info */ + .handler = &sgi_ras_intr_handler, + .aux_data = (void *)0, + }, { + /* DMC 1 error record info */ + .handler = &sgi_ras_intr_handler, + .aux_data = (void *)1, + }, +}; + +struct ras_interrupt sgi_ras_interrupts[] = { + { + .intr_number = 35, + .err_record = &sgi_err_records[0], + }, { + .intr_number = 39, + .err_record = &sgi_err_records[1], + } +}; + +REGISTER_ERR_RECORD_INFO(sgi_err_records); +REGISTER_RAS_INTERRUPTS(sgi_ras_interrupts); + +static struct sgi_ras_ev_map *plat_sgi_get_ras_ev_map(void) +{ + return sgi575_ras_map; +} + +static int plat_sgi_get_ras_ev_map_size(void) +{ + return SGI575_RAS_MAP_SIZE; +} + +/* + * Find event mapping for a given interrupt number: On success, returns pointer + * to the event mapping. On error, returns NULL. + */ +static struct sgi_ras_ev_map *find_ras_event_map_by_intr(uint32_t intr_num) +{ + struct sgi_ras_ev_map *map = plat_sgi_get_ras_ev_map(); + int i; + int size = plat_sgi_get_ras_ev_map_size(); + + for (i = 0; i < size; i++) { + if (map->intr == intr_num) + return map; + + map++; + } + + return NULL; +} + +static void sgi_ras_intr_configure(int intr) +{ + plat_ic_set_interrupt_type(intr, INTR_TYPE_EL3); + plat_ic_set_interrupt_priority(intr, PLAT_RAS_PRI); + plat_ic_clear_interrupt_pending(intr); + plat_ic_set_spi_routing(intr, INTR_ROUTING_MODE_ANY, + (u_register_t)read_mpidr_el1()); + plat_ic_enable_interrupt(intr); +} + +static int sgi_ras_intr_handler(const struct err_record_info *err_rec, + int probe_data, + const struct err_handler_data *const data) +{ + struct sgi_ras_ev_map *ras_map; + mm_communicate_header_t *header; + uint32_t intr; + int ret; + + cm_el1_sysregs_context_save(NON_SECURE); + intr = data->interrupt; + + /* + * Find if this is a RAS interrupt. There must be an event against + * this interrupt + */ + ras_map = find_ras_event_map_by_intr(intr); + assert(ras_map != NULL); + + /* + * Populate the MM_COMMUNICATE payload to share the + * event info with StandaloneMM code. This allows us to use + * MM_COMMUNICATE as a common entry mechanism into S-EL0. The + * header data will be parsed in StandaloneMM to process the + * corresponding event. + * + * TBD - Currently, the buffer allocated by SPM for communication + * between EL3 and S-EL0 is being used(PLAT_SPM_BUF_BASE). But this + * should happen via a dynamic mem allocation, which should be + * managed by SPM -- the individual platforms then call the mem + * alloc api to get memory for the payload. + */ + header = (void *) PLAT_SPM_BUF_BASE; + memset(header, 0, sizeof(*header)); + memcpy(&header->data, &err_rec->aux_data, sizeof(err_rec->aux_data)); + header->message_len = sizeof(err_rec->aux_data); + memcpy(&header->header_guid, (void *) &dmc620_ecc_event_guid, + sizeof(const struct efi_guid)); + + spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0, + plat_my_core_pos()); + + /* + * Do an EOI of the RAS interrupt. This allows the + * sdei event to be dispatched at the SDEI event's + * priority. + */ + plat_ic_end_of_interrupt(intr); + + /* Dispatch the event to the SDEI client */ + ret = sdei_dispatch_event(ras_map->sdei_ev_num); + if (ret != 0) { + /* + * sdei_dispatch_event() may return failing result in some cases, + * for example kernel may not have registered a handler or RAS event + * may happen early during boot. We restore the NS context when + * sdei_dispatch_event() returns failing result. + */ + ERROR("SDEI dispatch failed: %d", ret); + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + } + + return ret; +} + +int sgi_ras_intr_handler_setup(void) +{ + int i; + struct sgi_ras_ev_map *map = plat_sgi_get_ras_ev_map(); + int size = plat_sgi_get_ras_ev_map_size(); + + for (i = 0; i < size; i++) { + sgi_ras_intr_configure(map->intr); + map++; + } + + INFO("SGI: RAS Interrupt Handler successfully registered\n"); + + return 0; +} diff --git a/arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c new file mode 100644 index 0000000..1c3b5bf --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Common topology related methods for SGI and RD based platforms + */ +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return CSS_SGI_MAX_CPUS_PER_CLUSTER; +} + +#if ARM_PLAT_MT +/****************************************************************************** + * Return the number of PE's supported by the CPU. + *****************************************************************************/ +unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr) +{ + return CSS_SGI_MAX_PE_PER_CPU; +} +#endif diff --git a/arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S b/arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S new file mode 100644 index 0000000..32ca1bb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * MAX_CPUS_PER_CLUSTER * MAX_PE_PER_CPU) + + * (CPUId * MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * MAX_CPUS_PER_CLUSTER + CPUId) * MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation. + */ + tst x0, #MPIDR_MT_MASK + lsr x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #PLAT_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x5, #PLAT_MAX_PE_PER_CPU + madd x0, x1, x5, x0 + ret +endfunc plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the CPU MIDR and disable power down bit for + * that CPU. + * ----------------------------------------------------- + */ +func plat_reset_handler + jump_if_cpu_midr CORTEX_A75_MIDR, A75 + jump_if_cpu_midr CORTEX_A55_MIDR, A55 + ret + + /* ----------------------------------------------------- + * Disable CPU power down bit in power control register + * ----------------------------------------------------- + */ +A75: + mrs x0, CORTEX_A75_CPUPWRCTLR_EL1 + bic x0, x0, #CORTEX_A75_CORE_PWRDN_EN_MASK + msr CORTEX_A75_CPUPWRCTLR_EL1, x0 + isb + ret +A55: + mrs x0, CORTEX_A55_CPUPWRCTLR_EL1 + bic x0, x0, #CORTEX_A55_CORE_PWRDN_EN_MASK + msr CORTEX_A55_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts new file mode 100644 index 0000000..54b2423 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + /* Platform Config */ + tb_fw-config { + compatible = "arm,tb_fw"; + hw_config_addr = <0x0 0x83000000>; + hw_config_max_size = <0x01000000>; + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S b/arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S new file mode 100644 index 0000000..715ded2 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs +css_print_gic_regs +print_cci_regs +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h new file mode 100644 index 0000000..2d8e677 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM_BASE_PLATFORM_DEF_H +#define SGM_BASE_PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* CPU topology */ +#define PLAT_ARM_CLUSTER_COUNT U(1) +#define PLAT_ARM_CLUSTER_CORE_COUNT U(8) +#define PLATFORM_CORE_COUNT PLAT_ARM_CLUSTER_CORE_COUNT + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 +#define PLAT_NUM_PWR_DOMAINS (ARM_SYSTEM_COUNT + \ + PLAT_ARM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + CSS_G1S_IRQ_PROPS(grp), \ + ARM_G1S_IRQ_PROPS(grp) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x30000000 +#define PLAT_ARM_GICR_BASE 0x300C0000 +#define PLAT_ARM_GICC_BASE 0x2c000000 + +#define CSS_GIC_SIZE 0x00200000 + +#define CSS_MAP_GIC_DEVICE MAP_REGION_FLAT( \ + PLAT_ARM_GICD_BASE, \ + CSS_GIC_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* Platform ID address */ +#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET) +#ifndef __ASSEMBLER__ +/* SSC_VERSION related accessors */ +/* Returns the part number of the platform */ +#define GET_PLAT_PART_NUM \ + GET_SSC_VERSION_PART_NUM(mmio_read_32(SSC_VERSION)) +/* Returns the configuration number of the platform */ +#define GET_PLAT_CONFIG_NUM \ + GET_SSC_VERSION_CONFIG(mmio_read_32(SSC_VERSION)) +#endif /* __ASSEMBLER__ */ + + +/************************************************************************* + * Definitions common to all SGM CSS based platforms + *************************************************************************/ + +/* TZC-400 related constants */ +#define PLAT_ARM_TZC_BASE 0x2a500000 +#define TZC_NSAID_ALL_AP 0 /* Note: Same as default NSAID!! */ +#define TZC_NSAID_HDLCD0 2 +#define TZC_NSAID_HDLCD1 3 +#define TZC_NSAID_GPU 9 +#define TZC_NSAID_VIDEO 10 +#define TZC_NSAID_DISP0 11 +#define TZC_NSAID_DISP1 12 + + +/************************************************************************* + * Required platform porting definitions common to all SGM CSS based + * platforms + *************************************************************************/ + +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00040000 /* 256 KB */ + +/* MHU related constants */ +#define PLAT_CSS_MHU_BASE 0x2b1f0000 + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x00080000 + +#define PLAT_ARM_CCI_BASE 0x2a000000 + +/* Cluster to CCI slave mapping */ +#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 6 +#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 5 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID 0 + +/* TZC related constants */ +#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD1) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_GPU) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIDEO) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_DISP0) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_DISP1)) + +/* Display Processor register definitions to setup the NSAIDs */ +#define MALI_DP_BASE 0x2cc00000 +#define DP_NPROT_NSAID_OFFSET 0x1000c +#define W_NPROT_NSAID_SHIFT 24 +#define LS_NPORT_NSAID_SHIFT 12 + +/* + * Base address of the first memory region used for communication between AP + * and SCP. Used by the BootOverMHU and SCPI protocols. + */ +#if !CSS_USE_SCMI_SDS_DRIVER +/* + * Note that this is located at the same address as SCP_BOOT_CFG_ADDR, which + * means the SCP/AP configuration data gets overwritten when the AP initiates + * communication with the SCP. The configuration data is expected to be a + * 32-bit word on all CSS platforms. Part of this configuration is + * which CPU is the primary, according to the shift and mask definitions below. + */ +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE (ARM_TRUSTED_SRAM_BASE + 0x80) +#define PLAT_CSS_PRIMARY_CPU_SHIFT 8 +#define PLAT_CSS_PRIMARY_CPU_BIT_WIDTH 4 +#endif + +/* + * SCP_BL2 uses up whatever remaining space is available as it is loaded before + * anything else in this memory region and is handed over to the SCP before + * BL31 is loaded over the top. + */ +#define PLAT_CSS_MAX_SCP_BL2_SIZE \ + ((SCP_BL2_LIMIT - ARM_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK) + +#define PLAT_CSS_MAX_SCP_BL2U_SIZE PLAT_CSS_MAX_SCP_BL2_SIZE + +/* + * Most platform porting definitions provided by included headers + */ + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL31) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 5 +#elif defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 5 +#elif !USE_ROMLIB +# define PLAT_ARM_MMAP_ENTRIES 11 +# define MAX_XLAT_TABLES 5 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000 + +/* + * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page + */ + +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000 +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000 +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0 +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0 +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE 0x1D000 +#else +# define PLAT_ARM_MAX_BL2_SIZE 0x12000 +#endif + +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is + * calculated using the current BL31 PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL31_SIZE 0x3B000 + +/* + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x440 +# endif +#elif defined(IMAGE_BL2) +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif defined(IMAGE_BL2U) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +/******************************************************************************* + * Memprotect definitions + ******************************************************************************/ +/* PSCI memory protect definitions: + * This variable is stored in a non-secure flash because some ARM reference + * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT + * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions. + */ +#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \ + V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1) + +#endif /* SGM_BASE_PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h new file mode 100644 index 0000000..29b98d4 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM_PLAT_CONFIG_H +#define SGM_PLAT_CONFIG_H + +#include +#include + +/* The type of interconnect */ +typedef enum { + ARM_CCI = 0, + ARM_CCN, + ARM_CMN +} css_inteconn_type_t; + +typedef ccn_desc_t inteconn_desc_t; + +/* Interconnect configurations */ +typedef struct css_inteconn_config { + css_inteconn_type_t ip_type; + const inteconn_desc_t *plat_inteconn_desc; +} css_inteconn_config_t; + +/* Topology configurations */ +typedef struct css_topology { + const unsigned char *power_tree; + unsigned int plat_cluster_core_count; +} css_topology_t; + +typedef struct css_plat_config { + const gicv3_driver_data_t *gic_data; + const css_inteconn_config_t *inteconn; + const css_topology_t *topology; +} css_plat_config_t; + +void plat_config_init(void); +css_plat_config_t *get_plat_config(void); + +#endif /* SGM_PLAT_CONFIG_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h new file mode 100644 index 0000000..859ddb5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM_VARIANT_H +#define SGM_VARIANT_H + +/* SSC_VERSION values for sgm */ +#define SGM775_SSC_VER_PART_NUM 0x0790 + +/* DMC configuration for sgm */ +#define SGM_DMC_SIZE 0x40000 +#define SGM775_DMC_COUNT 4 + +#endif /* SGM_VARIANT_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm-common.mk b/arm-trusted-firmware/plat/arm/css/sgm/sgm-common.mk new file mode 100644 index 0000000..5b954f8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm-common.mk @@ -0,0 +1,76 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +CSS_USE_SCMI_SDS_DRIVER := 1 + +CSS_SGM_BASE := plat/arm/css/sgm + +PLAT_INCLUDES := -I${CSS_SGM_BASE}/include + +PLAT_BL_COMMON_SOURCES := ${CSS_SGM_BASE}/sgm_mmap_config.c \ + ${CSS_SGM_BASE}/aarch64/css_sgm_helpers.S + +SECURITY_SOURCES := drivers/arm/tzc/tzc_dmc500.c \ + plat/arm/common/arm_tzc_dmc500.c \ + ${CSS_SGM_BASE}/sgm_security.c + +SGM_CPU_SOURCES := lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a75.S + +INTERCONNECT_SOURCES := ${CSS_SGM_BASE}/sgm_interconnect.c + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +SGM_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c + +BL1_SOURCES += $(SGM_CPU_SOURCES) \ + ${INTERCONNECT_SOURCES} \ + ${CSS_SGM_BASE}/sgm_bl1_setup.c \ + ${CSS_SGM_BASE}/sgm_plat_config.c \ + drivers/arm/sp805/sp805.c + +BL2_SOURCES += ${SECURITY_SOURCES} \ + ${CSS_SGM_BASE}/sgm_plat_config.c + +BL2U_SOURCES += ${SECURITY_SOURCES} + +BL31_SOURCES += $(SGM_CPU_SOURCES) \ + ${INTERCONNECT_SOURCES} \ + ${SECURITY_SOURCES} \ + ${SGM_GIC_SOURCES} \ + ${CSS_SGM_BASE}/sgm_topology.c \ + ${CSS_SGM_BASE}/sgm_bl31_setup.c \ + ${CSS_SGM_BASE}/sgm_plat_config.c + +ifneq (${RESET_TO_BL31},0) + $(error "Using BL31 as the reset vector is not supported on ${PLAT} platform. \ + Please set RESET_TO_BL31 to 0.") +endif + +# sgm uses CCI-500 as Cache Coherent Interconnect +ARM_CCI_PRODUCT_ID := 500 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# 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. +USE_COHERENT_MEM := 0 + +override ARM_PLAT_MT := 1 + +$(eval $(call add_define,SGM_PLAT)) + +include plat/arm/common/arm_common.mk +include plat/arm/board/common/board_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/soc/common/soc_css.mk diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c new file mode 100644 index 0000000..5fd9655 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +void bl1_early_platform_setup(void) +{ + + /* Initialize the console before anything else */ + arm_bl1_early_platform_setup(); + + /* Initialize the platform configuration structure */ + plat_config_init(); + +#if !HW_ASSISTED_COHERENCY + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + plat_arm_interconnect_enter_coherency(); +#endif +} + +void plat_arm_secure_wdt_start(void) +{ + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +} + +void plat_arm_secure_wdt_stop(void) +{ + sp805_stop(ARM_SP805_TWDG_BASE); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c new file mode 100644 index 0000000..907e9fd --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +static scmi_channel_plat_info_t sgm775_scmi_plat_info = { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell, +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) +{ + return &sgm775_scmi_plat_info; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + uint32_t plat_version; + bl_params_node_t *bl_params; + + bl_params = ((bl_params_t *)arg0)->head; + + /* Initialize the platform configuration structure */ + plat_config_init(); + + while (bl_params) { + if (bl_params->image_id == BL33_IMAGE_ID) { + plat_version = mmio_read_32(SSC_VERSION); + bl_params->ep_info->args.arg2 = plat_version; + break; + } + + bl_params = bl_params->next_params_info; + } + + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return css_scmi_override_pm_ops(ops); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c new file mode 100644 index 0000000..5b45341 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * As the SGM platform supports FCM (with automatic interconnect + * enter/exit), we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void __init plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c new file mode 100644 index 0000000..e5b4b03 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +/* + * Table of regions for different BL stages to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * arm_configure_mmu_elx() will give the available subset of that. + */ +#if IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RO, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, +#if TRUSTED_BOARD_BOOT + ARM_MAP_NS_DRAM1, +#endif + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RO, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, + ARM_MAP_NS_DRAM1, +#ifdef SPD_tspd + ARM_MAP_TSP_SEC_MEM, +#endif +#ifdef SPD_opteed + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif +#if IMAGE_BL2U +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif +#if IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +const mmap_region_t *plat_arm_get_mmap(void) +{ + return plat_arm_mmap; +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c new file mode 100644 index 0000000..eed3631 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include + +#include +#include + +static css_plat_config_t *css_plat_info; + +/* Interconnect */ +const css_inteconn_config_t sgm_inteconn = { + .ip_type = ARM_CCI, + .plat_inteconn_desc = NULL +}; + +/* Special definition for SGM775 */ +/* Topology configuration for SGM775 */ +const unsigned char sgm775_power_domain_tree_desc[] = { + /* No of root nodes */ + ARM_SYSTEM_COUNT, + /* No of children for the root node */ + PLAT_ARM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLAT_ARM_CLUSTER_CORE_COUNT, +}; + +const css_topology_t sgm775_topology = { + .power_tree = sgm775_power_domain_tree_desc, + .plat_cluster_core_count = PLAT_ARM_CLUSTER_CORE_COUNT +}; + +/* Configuration structure for SGM775 */ +css_plat_config_t sgm775_config = { + .inteconn = &sgm_inteconn, + .topology = &sgm775_topology +}; + +/******************************************************************************* + * This function initializes the platform structure. + ******************************************************************************/ +void plat_config_init(void) +{ + /* Get the platform configurations */ + switch (GET_PLAT_PART_NUM) { + case SGM775_SSC_VER_PART_NUM: + css_plat_info = &sgm775_config; + + break; + default: + ERROR("Not a valid sgm variant!\n"); + panic(); + } +} + +/******************************************************************************* + * This function returns the platform structure pointer. + ******************************************************************************/ +css_plat_config_t *get_plat_config(void) +{ + assert(css_plat_info != NULL); + return css_plat_info; +} + +#if TRUSTED_BOARD_BOOT +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} +#endif diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c new file mode 100644 index 0000000..21d5306 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +/* Is populated with the DMC-500 controllers base addresses */ +static tzc_dmc500_driver_data_t plat_driver_data; + +void plat_sgm_dp_security_setup(void) +{ + unsigned int nprot_nsaid; + + /* + * At reset the Mali display processors start with NSAIDs set to zero + * so the firmware must set them up to the expected values for ARM sgm + * platforms. + */ + + nprot_nsaid = mmio_read_32(MALI_DP_BASE + DP_NPROT_NSAID_OFFSET); + nprot_nsaid &= ~((0xF << W_NPROT_NSAID_SHIFT) | + (0xF << LS_NPORT_NSAID_SHIFT)); + nprot_nsaid |= ((TZC_NSAID_DISP1 << W_NPROT_NSAID_SHIFT) | + (TZC_NSAID_DISP0 << LS_NPORT_NSAID_SHIFT)); + mmio_write_32(MALI_DP_BASE + DP_NPROT_NSAID_OFFSET, nprot_nsaid); +} + +void plat_arm_security_setup(void) +{ + unsigned int i; + unsigned int part_num = GET_PLAT_PART_NUM; + + INFO("part_num: 0x%x\n", part_num); + + /* + * Initialise plat_driver_data with platform specific DMC_BASE + * addresses + */ + switch (part_num) { + case SGM775_SSC_VER_PART_NUM: + for (i = 0; i < SGM775_DMC_COUNT; i++) + plat_driver_data.dmc_base[i] = PLAT_ARM_TZC_BASE + + SGM_DMC_SIZE * i; + plat_driver_data.dmc_count = SGM775_DMC_COUNT; + break; + default: + /* Unexpected platform */ + ERROR("Unexpected platform\n"); + panic(); + } + /* Initialize the TrustZone Controller in DMC-500 */ + arm_tzc_dmc500_setup(&plat_driver_data, NULL); + + /* Do DP NSAID setup */ + plat_sgm_dp_security_setup(); + /* Do ARM CSS SoC security setup */ + soc_css_security_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c new file mode 100644 index 0000000..2d9552d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return get_plat_config()->topology->power_tree; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return get_plat_config()->topology->plat_cluster_core_count; +} + +/* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + */ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 0, 1, 2, 3, 4, 5, 6, 7 }; diff --git a/arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c b/arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c new file mode 100644 index 0000000..5f40c4c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +void tsp_early_platform_setup(void) +{ + /* Initialize the platform configuration structure */ + plat_config_init(); + + arm_tsp_early_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/tsp/tsp-sgm.mk b/arm-trusted-firmware/plat/arm/css/sgm/tsp/tsp-sgm.mk new file mode 100644 index 0000000..de5e5b7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/tsp/tsp-sgm.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += ${SGM_GIC_SOURCES} \ + ${CSS_SGM_BASE}/sgm_plat_config.c \ + plat/arm/css/sgm/tsp/sgm_tsp_setup.c + +include plat/arm/common/tsp/arm_tsp.mk diff --git a/arm-trusted-firmware/plat/arm/soc/common/soc_css.mk b/arm-trusted-firmware/plat/arm/soc/common/soc_css.mk new file mode 100644 index 0000000..8cad2a5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/soc/common/soc_css.mk @@ -0,0 +1,15 @@ +# +# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +#PLAT_BL_COMMON_SOURCES += + +BL1_SOURCES += plat/arm/soc/common/soc_css_security.c + +BL2_SOURCES += plat/arm/soc/common/soc_css_security.c + +BL2U_SOURCES += plat/arm/soc/common/soc_css_security.c + +BL31_SOURCES += plat/arm/soc/common/soc_css_security.c diff --git a/arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c b/arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c new file mode 100644 index 0000000..4f6bf61 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +void soc_css_init_nic400(void) +{ + /* + * NIC-400 Access Control Initialization + * + * Define access privileges by setting each corresponding bit to: + * 0 = Secure access only + * 1 = Non-secure access allowed + */ + + /* + * Allow non-secure access to some SOC regions, excluding UART1, which + * remains secure (unless CSS_NON_SECURE_UART is set). + * Note: This is the NIC-400 device on the SOC + */ + mmio_write_32(SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_USB_EHCI), ~0); + mmio_write_32(SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_TLX_MASTER), ~0); + mmio_write_32(SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_USB_OHCI), ~0); + mmio_write_32(SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_PL354_SMC), ~0); + mmio_write_32(SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_APB4_BRIDGE), ~0); +#if CSS_NON_SECURE_UART + /* Configure UART for non-secure access */ + mmio_write_32(SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_BOOTSEC_BRIDGE), ~0); +#else + mmio_write_32(SOC_CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_BOOTSEC_BRIDGE), + ~SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1); +#endif /* CSS_NON_SECURE_UART */ + +} + + +#define PCIE_SECURE_REG 0x3000 +/* Mask uses REG and MEM access bits */ +#define PCIE_SEC_ACCESS_MASK ((1 << 0) | (1 << 1)) + +void soc_css_init_pcie(void) +{ +#if !PLAT_juno + /* + * Do not initialize PCIe in emulator environment. + * Platform ID register not supported on Juno + */ + if (BOARD_CSS_GET_PLAT_TYPE(BOARD_CSS_PLAT_ID_REG_ADDR) == + BOARD_CSS_PLAT_TYPE_EMULATOR) + return; +#endif /* PLAT_juno */ + + /* + * PCIE Root Complex Security settings to enable non-secure + * access to config registers. + */ + mmio_write_32(SOC_CSS_PCIE_CONTROL_BASE + PCIE_SECURE_REG, + PCIE_SEC_ACCESS_MASK); +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/bcm_console.c b/arm-trusted-firmware/plat/brcm/board/common/bcm_console.c new file mode 100644 index 0000000..5f20094 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/bcm_console.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +/******************************************************************************* + * Functions that set up the console + ******************************************************************************/ +static console_t bcm_boot_console; +static console_t bcm_runtime_console; + +/* Initialize the console to provide early debug support */ +void bcm_console_boot_init(void) +{ + int rc = console_16550_register(PLAT_BRCM_BOOT_UART_BASE, + PLAT_BRCM_BOOT_UART_CLK_IN_HZ, + BRCM_CONSOLE_BAUDRATE, + &bcm_boot_console); + if (rc == 0) { + /* + * The crash console doesn't use the multi console API, it uses + * the core console functions directly. It is safe to call panic + * and let it print debug information. + */ + panic(); + } + + console_set_scope(&bcm_boot_console, CONSOLE_FLAG_BOOT); +} + +void bcm_console_boot_end(void) +{ + console_flush(); + + (void)console_unregister(&bcm_boot_console); +} + +/* Initialize the runtime console */ +void bcm_console_runtime_init(void) +{ + int rc = console_16550_register(PLAT_BRCM_BL31_RUN_UART_BASE, + PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ, + BRCM_CONSOLE_BAUDRATE, + &bcm_runtime_console); + if (rc == 0) + panic(); + + console_set_scope(&bcm_runtime_console, CONSOLE_FLAG_RUNTIME); +} + +void bcm_console_runtime_end(void) +{ + console_flush(); + + (void)console_unregister(&bcm_runtime_console); +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c new file mode 100644 index 0000000..093157e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2018 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include + +/* error logging signature */ +#define BCM_ELOG_SIG_OFFSET 0x0000 +#define BCM_ELOG_SIG_VAL 0x75767971 + +/* current logging offset that points to where new logs should be added */ +#define BCM_ELOG_OFF_OFFSET 0x0004 + +/* current logging length (excluding header) */ +#define BCM_ELOG_LEN_OFFSET 0x0008 + +#define BCM_ELOG_HEADER_LEN 12 + +/* + * @base: base address of memory where log is saved + * @max_size: max size of memory reserved for logging + * @is_active: indicates logging is currently active + * @level: current logging level + */ +struct bcm_elog { + uintptr_t base; + uint32_t max_size; + unsigned int is_active; + unsigned int level; +}; + +static struct bcm_elog global_elog; + +extern void memcpy16(void *dst, const void *src, unsigned int len); + +/* + * Log one character + */ +static void elog_putchar(struct bcm_elog *elog, unsigned char c) +{ + uint32_t offset, len; + + offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET); + len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET); + mmio_write_8(elog->base + offset, c); + offset++; + + /* log buffer is now full and need to wrap around */ + if (offset >= elog->max_size) + offset = BCM_ELOG_HEADER_LEN; + + /* only increment length when log buffer is not full */ + if (len < elog->max_size - BCM_ELOG_HEADER_LEN) + len++; + + mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset); + mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len); +} + +static void elog_unsigned_num(struct bcm_elog *elog, unsigned long unum, + unsigned int radix) +{ + /* Just need enough space to store 64 bit decimal integer */ + unsigned char num_buf[20]; + int i = 0, rem; + + do { + rem = unum % radix; + if (rem < 0xa) + num_buf[i++] = '0' + rem; + else + num_buf[i++] = 'a' + (rem - 0xa); + } while (unum /= radix); + + while (--i >= 0) + elog_putchar(elog, num_buf[i]); +} + +static void elog_string(struct bcm_elog *elog, const char *str) +{ + while (*str) + elog_putchar(elog, *str++); +} + +/* + * Routine to initialize error logging + */ +int bcm_elog_init(void *base, uint32_t size, unsigned int level) +{ + struct bcm_elog *elog = &global_elog; + uint32_t val; + + elog->base = (uintptr_t)base; + elog->max_size = size; + elog->is_active = 1; + elog->level = level / 10; + + /* + * If a valid signature can be found, it means logs have been copied + * into designated memory by another software. In this case, we should + * not re-initialize the entry header in the designated memory + */ + val = mmio_read_32(elog->base + BCM_ELOG_SIG_OFFSET); + if (val != BCM_ELOG_SIG_VAL) { + mmio_write_32(elog->base + BCM_ELOG_SIG_OFFSET, + BCM_ELOG_SIG_VAL); + mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, + BCM_ELOG_HEADER_LEN); + mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, 0); + } + + return 0; +} + +/* + * Routine to disable error logging + */ +void bcm_elog_exit(void) +{ + struct bcm_elog *elog = &global_elog; + + if (!elog->is_active) + return; + + elog->is_active = 0; + + flush_dcache_range(elog->base, elog->max_size); +} + +/* + * Routine to copy error logs from current memory to 'dst' memory and continue + * logging from the new 'dst' memory. + * dst and base addresses must be 16-bytes aligned. + */ +int bcm_elog_copy_log(void *dst, uint32_t max_size) +{ + struct bcm_elog *elog = &global_elog; + uint32_t offset, len; + + if (!elog->is_active || ((uintptr_t)dst == elog->base)) + return -1; + + /* flush cache before copying logs */ + flush_dcache_range(elog->base, max_size); + + /* + * If current offset exceeds the new max size, then that is considered + * as a buffer overflow situation. In this case, we reset the offset + * back to the beginning + */ + offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET); + if (offset >= max_size) { + offset = BCM_ELOG_HEADER_LEN; + mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset); + } + + /* note payload length does not include header */ + len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET); + if (len > max_size - BCM_ELOG_HEADER_LEN) { + len = max_size - BCM_ELOG_HEADER_LEN; + mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len); + } + + /* Need to copy everything including the header. */ + memcpy16(dst, (const void *)elog->base, len + BCM_ELOG_HEADER_LEN); + elog->base = (uintptr_t)dst; + elog->max_size = max_size; + + return 0; +} + +/* + * Main routine to save logs into memory + */ +void bcm_elog(const char *fmt, ...) +{ + va_list args; + const char *prefix_str; + int bit64; + int64_t num; + uint64_t unum; + char *str; + struct bcm_elog *elog = &global_elog; + + /* We expect the LOG_MARKER_* macro as the first character */ + unsigned int level = fmt[0]; + + if (!elog->is_active || level > elog->level) + return; + + prefix_str = plat_log_get_prefix(level); + + while (*prefix_str != '\0') { + elog_putchar(elog, *prefix_str); + prefix_str++; + } + + va_start(args, fmt); + fmt++; + while (*fmt) { + bit64 = 0; + + if (*fmt == '%') { + fmt++; + /* Check the format specifier */ +loop: + switch (*fmt) { + case 'i': /* Fall through to next one */ + case 'd': + if (bit64) + num = va_arg(args, int64_t); + else + num = va_arg(args, int32_t); + + if (num < 0) { + elog_putchar(elog, '-'); + unum = (unsigned long)-num; + } else + unum = (unsigned long)num; + + elog_unsigned_num(elog, unum, 10); + break; + case 's': + str = va_arg(args, char *); + elog_string(elog, str); + break; + case 'x': + if (bit64) + unum = va_arg(args, uint64_t); + else + unum = va_arg(args, uint32_t); + + elog_unsigned_num(elog, unum, 16); + break; + case 'l': + bit64 = 1; + fmt++; + goto loop; + case 'u': + if (bit64) + unum = va_arg(args, uint64_t); + else + unum = va_arg(args, uint32_t); + + elog_unsigned_num(elog, unum, 10); + break; + default: + /* Exit on any other format specifier */ + goto exit; + } + fmt++; + continue; + } + elog_putchar(elog, *fmt++); + } +exit: + va_end(args); +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c new file mode 100644 index 0000000..89e7bff --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c @@ -0,0 +1,133 @@ +/* + * Copyright 2019-2020 Broadcom. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include "bcm_elog_ddr.h" +#include "m0_cfg.h" +#include "m0_ipc.h" + +void elog_init_ddr_log(void) +{ + struct elog_setup setup = {0}; + struct elog_global_header global; + struct elog_meta_record rec; + unsigned int rec_idx = 0; + uint32_t log_offset; + uintptr_t metadata; + char *rec_desc[ELOG_SUPPORTED_REC_CNT] = {"SYSRESET", "THERMAL", + "DDR_ECC", "APBOOTLG", + "IDM"}; + + /* + * If this is warm boot, return immediately. + * We expect metadata to be initialized already + */ + if (is_warmboot()) { + WARN("Warmboot detected, skip ELOG metadata initialization\n"); + return; + } + + memset(&global, 0, sizeof(global)); + + global.sector_size = ELOG_SECTOR_SIZE; + global.signature = ELOG_GLOBAL_META_HDR_SIG; + global.rec_count = ELOG_SUPPORTED_REC_CNT; + + /* Start of logging area in DDR memory */ + log_offset = ELOG_STORE_OFFSET; + + /* Shift to the first RECORD header */ + log_offset += 2 * global.sector_size; + + /* Temporary place to hold metadata */ + metadata = TMP_ELOG_METADATA_BASE; + + memcpy((void *)metadata, &global, sizeof(global)); + metadata += sizeof(global); + + while (rec_idx < global.rec_count) { + memset(&rec, 0, sizeof(rec)); + + rec.type = rec_idx; + if (rec_idx == ELOG_REC_UART_LOG) { + rec.format = ELOG_REC_FMT_ASCII; + rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR; + rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_FS4_SCRATCH; + rec.src_mem_addr = BCM_ELOG_BL31_BASE; + rec.alt_src_mem_addr = BCM_ELOG_BL2_BASE; + rec.rec_size = ELOG_APBOOTLG_REC_SIZE; + } else if (rec_idx == ELOG_REC_IDM_LOG) { + rec.type = IDM_ELOG_REC_TYPE; + rec.format = ELOG_REC_FMT_CUSTOM; + rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR; + rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH; + rec.src_mem_addr = ELOG_IDM_SRC_MEM_ADDR; + rec.alt_src_mem_addr = 0x0; + rec.rec_size = ELOG_DEFAULT_REC_SIZE; + } else { + rec.format = ELOG_REC_FMT_CUSTOM; + rec.src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH; + rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH; + rec.src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR; + rec.alt_src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR; + rec.rec_size = ELOG_DEFAULT_REC_SIZE; + } + + rec.nvm_type = LOG_MEDIA_DDR; + rec.sector_size = ELOG_SECTOR_SIZE; + + rec.rec_addr = (uint64_t)log_offset; + log_offset += rec.rec_size; + + /* Sanity checks */ + if (rec.type > ELOG_MAX_REC_COUNT || + rec.format > ELOG_MAX_REC_FORMAT || + (rec.nvm_type > ELOG_MAX_NVM_TYPE && + rec.nvm_type != ELOG_NVM_DEFAULT) || + !rec.rec_size || + !rec.sector_size || + rec_idx >= ELOG_SUPPORTED_REC_CNT) { + ERROR("Invalid ELOG record(%u) detected\n", rec_idx); + return; + } + + memset(rec.rec_desc, ' ', sizeof(rec.rec_desc)); + + memcpy(rec.rec_desc, rec_desc[rec_idx], + strlen(rec_desc[rec_idx])); + + memcpy((void *)metadata, &rec, sizeof(rec)); + metadata += sizeof(rec); + + rec_idx++; + } + + setup.params[0] = TMP_ELOG_METADATA_BASE; + setup.params[1] = (sizeof(global) + global.rec_count * sizeof(rec)); + setup.cmd = ELOG_SETUP_CMD_WRITE_META; + + flush_dcache_range((uintptr_t)&setup, sizeof(struct elog_setup)); + flush_dcache_range((uintptr_t)setup.params[0], setup.params[1]); + + /* initialize DDR Logging METADATA if this is NOT warmboot */ + if (!is_warmboot()) { + if (scp_send_cmd(MCU_IPC_MCU_CMD_ELOG_SETUP, + (uint32_t)(uintptr_t)(&setup), + SCP_CMD_DEFAULT_TIMEOUT_US)) { + ERROR("scp_send_cmd: timeout/error for elog setup\n"); + return; + } + } + + NOTICE("MCU Error logging initialized\n"); +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h new file mode 100644 index 0000000..6f21a68 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h @@ -0,0 +1,107 @@ +/* + * Copyright 2019-2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BCM_ELOG_DDR_H +#define BCM_ELOG_DDR_H + +#define ELOG_GLOBAL_META_HDR_SIG 0x45524c47 +#define ELOG_MAX_REC_COUNT 13 +#define ELOG_MAX_REC_FORMAT 1 +#define ELOG_MAX_NVM_TYPE 4 +/* Use a default NVM, set by m0 configuration */ +#define ELOG_NVM_DEFAULT 0xff + +/* Max. number of cmd parameters per elog spec */ +#define ELOG_PARAM_COUNT 3 +/* + * Number of supported RECORD Types- + * SYSRESET, THERMAL, DDR_ECC, APBOOTLG, IDM + */ +#define ELOG_SUPPORTED_REC_CNT 5 + +#define ELOG_REC_DESC_LENGTH 8 + +#define ELOG_SECTOR_SIZE 0x1000 + +/* Default Record size for all record types except APBOOTLOG */ +#define ELOG_DEFAULT_REC_SIZE 0x10000 + +/* Default record size for APBOOTLOG record */ +#define ELOG_APBOOTLG_REC_SIZE 0x60000 + +/* Use default CRMU provided mem address */ +#define ELOG_USE_DEFAULT_MEM_ADDR 0x0 + +/* Temporary place to hold metadata */ +#define TMP_ELOG_METADATA_BASE (ELOG_AP_UART_LOG_BASE + \ + BCM_ELOG_BL2_SIZE) +/* IDM ELOG source memory address */ +#define ELOG_IDM_SRC_MEM_ADDR 0x8f213000 + +#define IDM_ELOG_REC_TYPE 5 + +enum elog_record_type { + ELOG_REC_SYS_RESET_EVT = 0, + ELOG_REC_THERMAL_EVT, + ELOG_REC_DDR_ECC, + ELOG_REC_UART_LOG, + ELOG_REC_IDM_LOG, + ELOG_REC_MAX +}; + +enum elog_record_format { + ELOG_REC_FMT_ASCII = 0, + ELOG_REC_FMT_CUSTOM +}; + +enum elog_src_memory_type { + ELOG_SRC_MEM_TYPE_CRMU_SCRATCH = 0, + ELOG_SRC_MEM_TYPE_FS4_SCRATCH, + ELOG_SRC_MEM_TYPE_DDR, + ELOG_SRC_MEM_TYPE_CHIMP_SCRATCH +}; + +enum elog_setup_cmd { + ELOG_SETUP_CMD_VALIDATE_META, + ELOG_SETUP_CMD_WRITE_META, + ELOG_SETUP_CMD_ERASE, + ELOG_SETUP_CMD_READ, + ELOG_SETUP_CMD_CHECK +}; + +struct elog_setup { + uint32_t cmd; + uint32_t params[ELOG_PARAM_COUNT]; + uint32_t result; + uint32_t ret_code; +}; + +struct elog_meta_record { + uint8_t type; + uint8_t format; + uint8_t src_mem_type; + uint8_t alt_src_mem_type; + uint8_t nvm_type; + char rec_desc[ELOG_REC_DESC_LENGTH]; + uint64_t src_mem_addr; + uint64_t alt_src_mem_addr; + uint64_t rec_addr; + uint32_t rec_size; + uint32_t sector_size; + uint8_t padding[3]; +} __packed; + +struct elog_global_header { + uint32_t signature; + uint32_t sector_size; + uint8_t revision; + uint8_t rec_count; + uint16_t padding; +} __packed; + +void elog_init_ddr_log(void); + +#endif /* BCM_ELOG_DDR_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c b/arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c new file mode 100644 index 0000000..da18c31 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c @@ -0,0 +1,625 @@ +/* + * Copyright 2015 - 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +/* Weak definition may be overridden in specific platform */ +#pragma weak plat_match_rotpk +#pragma weak plat_get_nv_ctr +#pragma weak plat_set_nv_ctr + +/* SHA256 algorithm */ +#define SHA256_BYTES 32 + +/* ROTPK locations */ +#define ARM_ROTPK_REGS_ID 1 +#define ARM_ROTPK_DEVEL_RSA_ID 2 +#define BRCM_ROTPK_SOTP_RSA_ID 3 + +#if !ARM_ROTPK_LOCATION_ID + #error "ARM_ROTPK_LOCATION_ID not defined" +#endif + +static const unsigned char rotpk_hash_hdr[] = + "\x30\x31\x30\x0D\x06\x09\x60\x86\x48" + "\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"; +static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1; +static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES]; + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) +static const unsigned char arm_devel_rotpk_hash[] = + "\xB0\xF3\x82\x09\x12\x97\xD8\x3A" + "\x37\x7A\x72\x47\x1B\xEC\x32\x73" + "\xE9\x92\x32\xE2\x49\x59\xF6\x5E" + "\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA"; +#endif + +#pragma weak plat_rotpk_hash +const unsigned char plat_rotpk_hash[] = + "\xdb\x06\x67\x95\x4f\x88\x2b\x88" + "\x49\xbf\x70\x3f\xde\x50\x4a\x96" + "\xd8\x17\x69\xd4\xa0\x6c\xba\xee" + "\x66\x3e\x71\x82\x2d\x95\x69\xe4"; + +#pragma weak rom_slice +const unsigned char rom_slice[] = + "\x77\x06\xbc\x98\x40\xbe\xfd\xab" + "\x60\x4b\x74\x3c\x9a\xb3\x80\x75" + "\x39\xb6\xda\x27\x07\x2e\x5b\xbf" + "\x5c\x47\x91\xc9\x95\x26\x26\x0c"; + +#if (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID) +static int plat_is_trusted_boot(void) +{ + uint64_t section3_row0_data; + + section3_row0_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0); + + if ((section3_row0_data & SOTP_DEVICE_SECURE_CFG0_AB_MASK) == 0) { + INFO("NOT AB\n"); + return 0; + } + + INFO("AB\n"); + return TRUSTED_BOARD_BOOT; +} + +/* + * FAST AUTH is enabled if all following conditions are met: + * - AB part + * - SOTP.DEV != 0 + * - SOTP.CID != 0 + * - SOTP.ENC_DEV_TYPE = ENC_AB_DEV + * - Manuf_debug strap set high + */ +static int plat_fast_auth_enabled(void) +{ + uint32_t chip_state; + uint64_t section3_row0_data; + uint64_t section3_row1_data; + + section3_row0_data = + sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0); + section3_row1_data = + sotp_mem_read(SOTP_DEVICE_SECURE_CFG1_ROW, 0); + + chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES); + + if (plat_is_trusted_boot() && + (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_DEV_MASK) && + (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_CID_MASK) && + ((section3_row1_data & SOTP_ENC_DEV_TYPE_MASK) == + SOTP_ENC_DEV_TYPE_AB_DEV) && + (chip_state & SOTP_CHIP_STATES_MANU_DEBUG_MASK)) + return 1; + + return 0; +} +#endif + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + uint8_t *dst; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + *flags = 0; + + /* Copy the DER header */ + memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len); + dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len]; + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) + memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES); +#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + uint32_t *src, tmp; + unsigned int words, i; + + /* + * Append the hash from Trusted Root-Key Storage registers. The hash has + * not been written linearly into the registers, so we have to do a bit + * of byte swapping: + * + * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C + * +---------------------------------------------------------------+ + * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 | + * +---------------------------------------------------------------+ + * | ... ... | | ... ... | + * | +--------------------+ | +-------+ + * | | | | + * +----------------------------+ +----------------------------+ + * | | | | + * +-------+ | +--------------------+ | + * | | | | + * v v v v + * +---------------------------------------------------------------+ + * | | | + * +---------------------------------------------------------------+ + * 0 15 16 31 + * + * Additionally, we have to access the registers in 32-bit words + */ + words = SHA256_BYTES >> 3; + + /* Swap bytes 0-15 (first four registers) */ + src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + /* Words are read in little endian */ + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } + + /* Swap bytes 16-31 (last four registers) */ + src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2); + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } +#elif (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID) +{ + int i; + int ret = -1; + + /* + * In non-AB mode, we do not read the key. + * In AB mode: + * - The Dauth is in BL11 if SBL is enabled + * - The Dauth is in SOTP if SBL is disabled. + */ + if (plat_is_trusted_boot() == 0) { + + INFO("NON-AB: Do not read DAUTH!\n"); + *flags = ROTPK_NOT_DEPLOYED; + ret = 0; + + } else if ((sbl_status() == SBL_ENABLED) && + (mmio_read_32(BL11_DAUTH_BASE) == BL11_DAUTH_ID)) { + + /* Read hash from BL11 */ + INFO("readKeys (DAUTH) from BL11\n"); + + memcpy(dst, + (void *)(BL11_DAUTH_BASE + sizeof(uint32_t)), + SHA256_BYTES); + + for (i = 0; i < SHA256_BYTES; i++) + if (dst[i] != 0) + break; + + if (i >= SHA256_BYTES) + ERROR("Hash not valid from BL11\n"); + else + ret = 0; + + } else if (sotp_key_erased()) { + + memcpy(dst, plat_rotpk_hash, SHA256_BYTES); + + INFO("SOTP erased, Use internal key hash.\n"); + ret = 0; + + } else if (plat_fast_auth_enabled()) { + + INFO("AB DEV: FAST AUTH!\n"); + *flags = ROTPK_NOT_DEPLOYED; + ret = 0; + + } else if (!(mmio_read_32(SOTP_STATUS_1) & SOTP_DAUTH_ECC_ERROR_MASK)) { + + /* Read hash from SOTP */ + ret = sotp_read_key(dst, + SHA256_BYTES, + SOTP_DAUTH_ROW, + SOTP_K_HMAC_ROW-1); + + INFO("sotp_read_key (DAUTH): %i\n", ret); + + } else { + + uint64_t row_data; + uint32_t k; + + for (k = 0; k < (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW); k++) { + row_data = sotp_mem_read(SOTP_DAUTH_ROW + k, + SOTP_ROW_NO_ECC); + + if (row_data != 0) + break; + } + + if (k == (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW)) { + INFO("SOTP NOT PROGRAMMED: Do not use DAUTH!\n"); + + if (sotp_mem_read(SOTP_ATF2_CFG_ROW_ID, + SOTP_ROW_NO_ECC) & SOTP_ROMKEY_MASK) { + memcpy(dst, plat_rotpk_hash, SHA256_BYTES); + + INFO("Use internal key hash.\n"); + ret = 0; + } else { + *flags = ROTPK_NOT_DEPLOYED; + ret = 0; + } + } else { + INFO("No hash found in SOTP\n"); + } + } + if (ret) + return ret; +} +#endif + + *key_ptr = (void *)rotpk_hash_der; + *key_len = (unsigned int)sizeof(rotpk_hash_der); + *flags |= ROTPK_IS_HASH; + + return 0; +} + +#define SOTP_NUM_BITS_PER_ROW 41 +#define SOTP_NVCTR_ROW_ALL_ONES 0x1ffffffffff +#define SOTP_NVCTR_TRUSTED_IN_USE \ + ((uint64_t)0x3 << (SOTP_NUM_BITS_PER_ROW-2)) +#define SOTP_NVCTR_NON_TRUSTED_IN_USE ((uint64_t)0x3) +#define SOTP_NVCTR_TRUSTED_NEAR_END SOTP_NVCTR_NON_TRUSTED_IN_USE +#define SOTP_NVCTR_NON_TRUSTED_NEAR_END SOTP_NVCTR_TRUSTED_IN_USE + +#define SOTP_NVCTR_ROW_START 64 +#define SOTP_NVCTR_ROW_END 75 + +/* + * SOTP NVCTR are stored in section 10 of SOTP (rows 64-75). + * Each row of SOTP is 41 bits. + * NVCTR's are stored in a bitstream format. + * We are tolerant to consecutive bit errors. + * Trusted NVCTR starts at the top of row 64 in bitstream format. + * Non Trusted NVCTR starts at the bottom of row 75 in reverse bitstream. + * Each row can only be used by 1 of the 2 counters. This is determined + * by 2 zeros remaining at the beginning or end of the last available row. + * If one counter has already starting using a row, the other will be + * prevent from writing to that row. + * + * Example counter values for SOTP programmed below: + * Trusted Counter (rows64-69) = 5 * 41 + 40 = 245 + * NonTrusted Counter (row75-71) = 3 * 41 + 4 = 127 + * 40 39 38 37 36 ..... 5 4 3 2 1 0 + * row 64 1 1 1 1 1 1 1 1 1 1 1 + * row 65 1 1 1 1 1 1 1 1 1 1 1 + * row 66 1 1 1 1 1 1 1 1 1 1 1 + * row 67 1 1 1 1 1 1 1 1 1 1 1 + * row 68 1 1 1 1 1 1 1 1 1 1 1 + * row 69 1 1 1 1 1 1 1 1 1 1 0 + * row 71 0 0 0 0 0 0 0 0 0 0 0 + * row 71 0 0 0 0 0 0 0 0 0 0 0 + * row 71 0 0 0 0 0 0 0 1 1 1 1 + * row 73 1 1 1 1 1 1 1 1 1 1 1 + * row 74 1 1 1 1 1 1 1 1 1 1 1 + * row 75 1 1 1 1 1 1 1 1 1 1 1 + * + */ + +#if (DEBUG == 1) +/* + * Dump sotp rows + */ +void sotp_dump_rows(uint32_t start_row, uint32_t end_row) +{ + int32_t rownum; + uint64_t rowdata; + + for (rownum = start_row; rownum <= end_row; rownum++) { + rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); + INFO("%d 0x%" PRIx64 "\n", rownum, rowdata); + } +} +#endif + +/* + * Get SOTP Trusted nvctr + */ +unsigned int sotp_get_trusted_nvctr(void) +{ + uint64_t rowdata; + uint64_t nextrowdata; + uint32_t rownum; + unsigned int nvctr; + + rownum = SOTP_NVCTR_ROW_START; + nvctr = SOTP_NUM_BITS_PER_ROW; + + /* + * Determine what row has last valid data for trusted ctr + */ + rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); + while ((rowdata & SOTP_NVCTR_TRUSTED_IN_USE) && + (rowdata & SOTP_NVCTR_TRUSTED_NEAR_END) && + (rownum < SOTP_NVCTR_ROW_END)) { + /* + * Current row in use and has data in last 2 bits as well. + * Check if next row also has data for this counter + */ + nextrowdata = sotp_mem_read(rownum+1, SOTP_ROW_NO_ECC); + if (nextrowdata & SOTP_NVCTR_TRUSTED_IN_USE) { + /* Next row also has data so increment rownum */ + rownum++; + nvctr += SOTP_NUM_BITS_PER_ROW; + rowdata = nextrowdata; + } else { + /* Next row does not have data */ + break; + } + } + + if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) { + while ((rowdata & 0x1) == 0) { + nvctr--; + rowdata >>= 1; + } + } else + nvctr -= SOTP_NUM_BITS_PER_ROW; + + INFO("CTR %i\n", nvctr); + return nvctr; +} + +/* + * Get SOTP NonTrusted nvctr + */ +unsigned int sotp_get_nontrusted_nvctr(void) +{ + uint64_t rowdata; + uint64_t nextrowdata; + uint32_t rownum; + unsigned int nvctr; + + nvctr = SOTP_NUM_BITS_PER_ROW; + rownum = SOTP_NVCTR_ROW_END; + + /* + * Determine what row has last valid data for nontrusted ctr + */ + rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); + while ((rowdata & SOTP_NVCTR_NON_TRUSTED_NEAR_END) && + (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) && + (rownum > SOTP_NVCTR_ROW_START)) { + /* + * Current row in use and has data in last 2 bits as well. + * Check if next row also has data for this counter + */ + nextrowdata = sotp_mem_read(rownum-1, SOTP_ROW_NO_ECC); + if (nextrowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) { + /* Next row also has data so decrement rownum */ + rownum--; + nvctr += SOTP_NUM_BITS_PER_ROW; + rowdata = nextrowdata; + } else { + /* Next row does not have data */ + break; + } + } + + if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) { + while ((rowdata & ((uint64_t)0x1 << (SOTP_NUM_BITS_PER_ROW-1))) + == + 0) { + nvctr--; + rowdata <<= 1; + } + } else + nvctr -= SOTP_NUM_BITS_PER_ROW; + + INFO("NCTR %i\n", nvctr); + return nvctr; +} + +/* + * Set SOTP Trusted nvctr + */ +int sotp_set_trusted_nvctr(unsigned int nvctr) +{ + int numrows_available; + uint32_t nontrusted_rownum; + uint32_t trusted_rownum; + uint64_t rowdata; + unsigned int maxnvctr; + + /* + * Read SOTP to find out how many rows are used by the + * NON Trusted nvctr + */ + nontrusted_rownum = SOTP_NVCTR_ROW_END; + do { + rowdata = sotp_mem_read(nontrusted_rownum, SOTP_ROW_NO_ECC); + if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) + nontrusted_rownum--; + else + break; + } while (nontrusted_rownum >= SOTP_NVCTR_ROW_START); + + /* + * Calculate maximum value we can have for nvctr based on + * number of available rows. + */ + numrows_available = nontrusted_rownum - SOTP_NVCTR_ROW_START + 1; + maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW; + if (maxnvctr) { + /* + * Last 2 bits of counter can't be written or it will + * overflow with nontrusted counter + */ + maxnvctr -= 2; + } + + if (nvctr > maxnvctr) { + /* Error - not enough room */ + WARN("tctr not set\n"); + return 1; + } + + /* + * It is safe to write the nvctr, fill all 1's up to the + * last row and then fill the last row with partial bitstream + */ + trusted_rownum = SOTP_NVCTR_ROW_START; + rowdata = SOTP_NVCTR_ROW_ALL_ONES; + + while (nvctr >= SOTP_NUM_BITS_PER_ROW) { + sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata); + nvctr -= SOTP_NUM_BITS_PER_ROW; + trusted_rownum++; + } + rowdata <<= (SOTP_NUM_BITS_PER_ROW - nvctr); + sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata); + return 0; +} + +/* + * Set SOTP NonTrusted nvctr + */ +int sotp_set_nontrusted_nvctr(unsigned int nvctr) +{ + int numrows_available; + uint32_t nontrusted_rownum; + uint32_t trusted_rownum; + uint64_t rowdata; + unsigned int maxnvctr; + + /* + * Read SOTP to find out how many rows are used by the + * Trusted nvctr + */ + trusted_rownum = SOTP_NVCTR_ROW_START; + do { + rowdata = sotp_mem_read(trusted_rownum, SOTP_ROW_NO_ECC); + if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) + trusted_rownum++; + else + break; + } while (trusted_rownum <= SOTP_NVCTR_ROW_END); + + /* + * Calculate maximum value we can have for nvctr based on + * number of available rows. + */ + numrows_available = SOTP_NVCTR_ROW_END - trusted_rownum + 1; + maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW; + if (maxnvctr) { + /* + * Last 2 bits of counter can't be written or it will + * overflow with nontrusted counter + */ + maxnvctr -= 2; + } + + if (nvctr > maxnvctr) { + /* Error - not enough room */ + WARN("nctr not set\n"); + return 1; + } + + /* + * It is safe to write the nvctr, fill all 1's up to the + * last row and then fill the last row with partial bitstream + */ + nontrusted_rownum = SOTP_NVCTR_ROW_END; + rowdata = SOTP_NVCTR_ROW_ALL_ONES; + + while (nvctr >= SOTP_NUM_BITS_PER_ROW) { + sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata); + nvctr -= SOTP_NUM_BITS_PER_ROW; + nontrusted_rownum--; + } + rowdata >>= (SOTP_NUM_BITS_PER_ROW - nvctr); + sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata); + return 0; +} + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * will contain the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + const char *oid; + + assert(cookie != NULL); + assert(nv_ctr != NULL); + + *nv_ctr = 0; + if ((sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & + SOTP_ATF_NVCOUNTER_ENABLE_MASK)) { + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) + *nv_ctr = sotp_get_trusted_nvctr(); + else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) + *nv_ctr = sotp_get_nontrusted_nvctr(); + else + return 1; + } + return 0; +} + +/* + * Store a new non-volatile counter value. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + const char *oid; + + if (sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & + SOTP_ATF_NVCOUNTER_ENABLE_MASK) { + INFO("set CTR %i\n", nv_ctr); + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) + return sotp_set_trusted_nvctr(nv_ctr); + else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) + return sotp_set_nontrusted_nvctr(nv_ctr); + return 1; + } + return 0; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/board_common.c b/arm-trusted-firmware/plat/brcm/board/common/board_common.c new file mode 100644 index 0000000..2f764ab --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/board_common.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#if IMAGE_BL2 +const mmap_region_t plat_brcm_mmap[] = { + HSLS_REGION, + BRCM_MAP_SHARED_RAM, + BRCM_MAP_NAND_RO, + BRCM_MAP_QSPI_RO, +#ifdef PERIPH0_REGION + PERIPH0_REGION, +#endif +#ifdef PERIPH1_REGION + PERIPH1_REGION, +#endif +#ifdef USE_DDR + BRCM_MAP_NS_DRAM1, +#if BRCM_BL31_IN_DRAM + BRCM_MAP_BL31_SEC_DRAM, +#endif +#else +#ifdef BRCM_MAP_EXT_SRAM + BRCM_MAP_EXT_SRAM, +#endif +#endif +#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE) + CRMU_SRAM_REGION, +#endif + {0} +}; +#endif + +#if IMAGE_BL31 +const mmap_region_t plat_brcm_mmap[] = { + HSLS_REGION, +#ifdef PERIPH0_REGION + PERIPH0_REGION, +#endif +#ifdef PERIPH1_REGION + PERIPH1_REGION, +#endif +#ifdef PERIPH2_REGION + PERIPH2_REGION, +#endif +#ifdef USB_REGION + USB_REGION, +#endif +#ifdef USE_DDR + BRCM_MAP_NS_DRAM1, +#ifdef BRCM_MAP_NS_SHARED_DRAM + BRCM_MAP_NS_SHARED_DRAM, +#endif +#else +#ifdef BRCM_MAP_EXT_SRAM + BRCM_MAP_EXT_SRAM, +#endif +#endif +#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE) + CRMU_SRAM_REGION, +#endif + {0} +}; +#endif + +CASSERT((ARRAY_SIZE(plat_brcm_mmap) - 1) <= PLAT_BRCM_MMAP_ENTRIES, + assert_plat_brcm_mmap_mismatch); +CASSERT((PLAT_BRCM_MMAP_ENTRIES + BRCM_BL_REGIONS) <= MAX_MMAP_REGIONS, + assert_max_mmap_regions); diff --git a/arm-trusted-firmware/plat/brcm/board/common/board_common.mk b/arm-trusted-firmware/plat/brcm/board/common/board_common.mk new file mode 100644 index 0000000..24a27ed --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/board_common.mk @@ -0,0 +1,294 @@ +# +# Copyright (c) 2015 - 2021, Broadcom +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_BL_COMMON_SOURCES += plat/brcm/board/common/board_common.c + +# If no board config makefile, do not include it +ifneq (${BOARD_CFG},) +BOARD_CFG_MAKE := $(shell find plat/brcm/board/${PLAT} -name '${BOARD_CFG}.mk') +$(eval $(call add_define,BOARD_CFG)) +ifneq (${BOARD_CFG_MAKE},) +$(info Including ${BOARD_CFG_MAKE}) +include ${BOARD_CFG_MAKE} +else +$(error Error: File ${BOARD_CFG}.mk not found in plat/brcm/board/${PLAT}) +endif +endif + +# To compile with highest log level (VERBOSE) set value to 50 +LOG_LEVEL := 40 + +# Use custom generic timer clock +ifneq (${GENTIMER_ACTUAL_CLOCK},) +$(info Using GENTIMER_ACTUAL_CLOCK=$(GENTIMER_ACTUAL_CLOCK)) +SYSCNT_FREQ := $(GENTIMER_ACTUAL_CLOCK) +$(eval $(call add_define,SYSCNT_FREQ)) +endif + +ifeq (${DRIVER_EMMC_ENABLE},) +DRIVER_EMMC_ENABLE :=1 +endif + +ifeq (${DRIVER_SPI_ENABLE},) +DRIVER_SPI_ENABLE := 0 +endif + +ifeq (${DRIVER_I2C_ENABLE},) +DRIVER_I2C_ENABLE := 0 +endif + +# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set +ifeq (${BRCM_DISABLE_TRUSTED_WDOG},) +BRCM_DISABLE_TRUSTED_WDOG := 0 +endif +ifeq (${SPIN_ON_BL1_EXIT}, 1) +BRCM_DISABLE_TRUSTED_WDOG := 1 +endif + +$(eval $(call assert_boolean,BRCM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,BRCM_DISABLE_TRUSTED_WDOG)) + +# Process ARM_BL31_IN_DRAM flag +ifeq (${ARM_BL31_IN_DRAM},) +ARM_BL31_IN_DRAM := 0 +endif +$(eval $(call assert_boolean,ARM_BL31_IN_DRAM)) +$(eval $(call add_define,ARM_BL31_IN_DRAM)) + +ifeq (${STANDALONE_BL2},yes) +BL2_LOG_LEVEL := 40 +$(eval $(call add_define,MMU_DISABLED)) +endif + +# BL2 XIP from QSPI +RUN_BL2_FROM_QSPI := 0 +ifeq (${RUN_BL2_FROM_QSPI},1) +$(eval $(call add_define,RUN_BL2_FROM_QSPI)) +endif + +# BL2 XIP from NAND +RUN_BL2_FROM_NAND := 0 +ifeq (${RUN_BL2_FROM_NAND},1) +$(eval $(call add_define,RUN_BL2_FROM_NAND)) +endif + +ifneq (${ELOG_AP_UART_LOG_BASE},) +$(eval $(call add_define,ELOG_AP_UART_LOG_BASE)) +endif + +ifeq (${ELOG_SUPPORT},1) +ifeq (${ELOG_STORE_MEDIA},DDR) +$(eval $(call add_define,ELOG_STORE_MEDIA_DDR)) +ifneq (${ELOG_STORE_OFFSET},) +$(eval $(call add_define,ELOG_STORE_OFFSET)) +endif +endif +endif + +ifneq (${BL2_LOG_LEVEL},) +$(eval $(call add_define,BL2_LOG_LEVEL)) +endif + +ifneq (${BL31_LOG_LEVEL},) +$(eval $(call add_define,BL31_LOG_LEVEL)) +endif + +# Use CRMU SRAM from iHOST +ifneq (${USE_CRMU_SRAM},) +$(eval $(call add_define,USE_CRMU_SRAM)) +endif + +# Use PIO mode if DDR is not used +ifeq (${USE_DDR},yes) +EMMC_USE_DMA := 1 +else +EMMC_USE_DMA := 0 +endif +$(eval $(call add_define,EMMC_USE_DMA)) + +# On BRCM platforms, separate the code and read-only data sections to allow +# mapping the former as executable and the latter as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# Use generic OID definition (tbbr_oid.h) +USE_TBBR_DEFS := 1 + +PLAT_INCLUDES += -Iplat/brcm/board/common \ + -Iinclude/drivers/brcm \ + -Iinclude/drivers/brcm/emmc \ + -Iinclude/drivers/brcm/mdio + +PLAT_BL_COMMON_SOURCES += plat/brcm/common/brcm_common.c \ + plat/brcm/board/common/cmn_sec.c \ + plat/brcm/board/common/bcm_console.c \ + plat/brcm/board/common/brcm_mbedtls.c \ + plat/brcm/board/common/plat_setup.c \ + plat/brcm/board/common/platform_common.c \ + drivers/arm/sp804/sp804_delay_timer.c \ + drivers/brcm/sotp.c \ + drivers/delay_timer/delay_timer.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/brcm/common/brcm_io_storage.c \ + plat/brcm/board/common/err.c \ + plat/brcm/board/common/sbl_util.c \ + drivers/arm/sp805/sp805.c + +# Add RNG driver +DRIVER_RNG_ENABLE := 1 +ifeq (${DRIVER_RNG_ENABLE},1) +PLAT_BL_COMMON_SOURCES += drivers/brcm/rng.c +endif + +# Add eMMC driver +ifeq (${DRIVER_EMMC_ENABLE},1) +$(eval $(call add_define,DRIVER_EMMC_ENABLE)) + +EMMC_SOURCES += drivers/brcm/emmc/emmc_chal_sd.c \ + drivers/brcm/emmc/emmc_csl_sdcard.c \ + drivers/brcm/emmc/emmc_csl_sdcmd.c \ + drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c + +PLAT_BL_COMMON_SOURCES += ${EMMC_SOURCES} + +ifeq (${DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT},) +$(eval $(call add_define,DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT)) +endif +endif + +BL2_SOURCES += plat/brcm/common/brcm_bl2_mem_params_desc.c \ + plat/brcm/common/brcm_image_load.c \ + common/desc_image_load.c + +BL2_SOURCES += plat/brcm/common/brcm_bl2_setup.c + +BL31_SOURCES += plat/brcm/common/brcm_bl31_setup.c + +ifeq (${BCM_ELOG},yes) +ELOG_SOURCES += plat/brcm/board/common/bcm_elog.c +BL2_SOURCES += ${ELOG_SOURCES} +BL31_SOURCES += ${ELOG_SOURCES} +endif + +# Add spi driver +ifeq (${DRIVER_SPI_ENABLE},1) +PLAT_BL_COMMON_SOURCES += drivers/brcm/spi/iproc_spi.c \ + drivers/brcm/spi/iproc_qspi.c +endif + +# Add spi nor/flash driver +ifeq (${DRIVER_SPI_NOR_ENABLE},1) +PLAT_BL_COMMON_SOURCES += drivers/brcm/spi_sf.c \ + drivers/brcm/spi_flash.c +endif + +ifeq (${DRIVER_I2C_ENABLE},1) +$(eval $(call add_define,DRIVER_I2C_ENABLE)) +BL2_SOURCES += drivers/brcm/i2c/i2c.c +PLAT_INCLUDES += -Iinclude/drivers/brcm/i2c +endif + +ifeq (${DRIVER_OCOTP_ENABLE},1) +$(eval $(call add_define,DRIVER_OCOTP_ENABLE)) +BL2_SOURCES += drivers/brcm/ocotp.c +endif + +# Enable FRU table support +ifeq (${USE_FRU},yes) +$(eval $(call add_define,USE_FRU)) +BL2_SOURCES += drivers/brcm/fru.c +endif + +# Enable GPIO support +ifeq (${USE_GPIO},yes) +$(eval $(call add_define,USE_GPIO)) +BL2_SOURCES += drivers/gpio/gpio.c +BL2_SOURCES += drivers/brcm/iproc_gpio.c +ifeq (${GPIO_SUPPORT_FLOAT_DETECTION},yes) +$(eval $(call add_define,GPIO_SUPPORT_FLOAT_DETECTION)) +endif +endif + +# Include mbedtls if it can be located +MBEDTLS_DIR ?= mbedtls +MBEDTLS_CHECK := $(shell find ${MBEDTLS_DIR}/include -name '$(notdir ${MBEDTLS_DIR})') + +ifneq (${MBEDTLS_CHECK},) +$(info Found mbedTLS at ${MBEDTLS_DIR}) +PLAT_INCLUDES += -I${MBEDTLS_DIR}/include/mbedtls + +# By default, use RSA keys +KEY_ALG := rsa_1_5 + +# Include common TBB sources +AUTH_SOURCES += drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +BL2_SOURCES += ${AUTH_SOURCES} + +# Use ATF framework for MBEDTLS +TRUSTED_BOARD_BOOT := 1 +CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk +IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk +$(info Including ${CRYPTO_LIB_MK}) +include ${CRYPTO_LIB_MK} +$(info Including ${IMG_PARSER_LIB_MK}) +include ${IMG_PARSER_LIB_MK} + +# Use ATF secure boot functions +# Use Hardcoded hash for devel + +ARM_ROTPK_LOCATION=arm_rsa +ifeq (${ARM_ROTPK_LOCATION}, arm_rsa) +ARM_ROTPK_LOCATION_ID=ARM_ROTPK_DEVEL_RSA_ID +ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem +else ifeq (${ARM_ROTPK_LOCATION}, brcm_rsa) +ARM_ROTPK_LOCATION_ID=BRCM_ROTPK_SOTP_RSA_ID +ifeq (${ROT_KEY},) +ROT_KEY=plat/brcm/board/common/rotpk/rsa_dauth2048_key.pem +endif +KEY_FIND := $(shell m="${ROT_KEY}"; [ -f "$$m" ] && echo "$$m") +ifeq (${KEY_FIND},) +$(error Error: No ${ROT_KEY} located) +else +$(info Using ROT_KEY: ${ROT_KEY}) +endif +else +$(error "Unsupported ARM_ROTPK_LOCATION value") +endif + +$(eval $(call add_define,ARM_ROTPK_LOCATION_ID)) +PLAT_BL_COMMON_SOURCES+=plat/brcm/board/common/board_arm_trusted_boot.c +endif + +#M0 runtime firmware +ifdef SCP_BL2 +$(eval $(call add_define,NEED_SCP_BL2)) +SCP_CFG_DIR=$(dir ${SCP_BL2}) +PLAT_INCLUDES += -I${SCP_CFG_DIR} +endif + +ifneq (${NEED_BL33},yes) +# If there is no BL33, BL31 will jump to this address. +ifeq (${USE_DDR},yes) +PRELOADED_BL33_BASE := 0x80000000 +else +PRELOADED_BL33_BASE := 0x74000000 +endif +endif + +# Use translation tables library v1 by default +ARM_XLAT_TABLES_LIB_V1 := 1 +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) +PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c +endif diff --git a/arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c b/arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c new file mode 100644 index 0000000..af42b86 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c @@ -0,0 +1,12 @@ +/* + * Copyright 2015 - 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void tls_exit(int code) +{ + INFO("%s: 0x%x\n", __func__, code); +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/chip_id.h b/arm-trusted-firmware/plat/brcm/board/common/chip_id.h new file mode 100644 index 0000000..842ac1f --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/chip_id.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CHIP_ID_H +#define CHIP_ID_H + +#include + +#include + +#define CHIP_REV_MAJOR_MASK 0xF0 +#define CHIP_REV_MAJOR_AX 0x00 +#define CHIP_REV_MAJOR_BX 0x10 +#define CHIP_REV_MAJOR_CX 0x20 +#define CHIP_REV_MAJOR_DX 0x30 + +/* Get Chip ID (product number) of the chip */ +static inline unsigned int chip_get_product_id(void) +{ + return PLAT_CHIP_ID_GET; +} + +/* Get Revision ID (major and minor) number of the chip */ +static inline unsigned int chip_get_rev_id(void) +{ + return PLAT_CHIP_REV_GET; +} + +static inline unsigned int chip_get_rev_id_major(void) +{ + return (chip_get_rev_id() & CHIP_REV_MAJOR_MASK); +} + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h b/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h new file mode 100644 index 0000000..8aa7fd4 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMN_PLAT_DEF_H +#define CMN_PLAT_DEF_H + +#include + +#ifndef GET_LOG_LEVEL +#define GET_LOG_LEVEL() LOG_LEVEL +#endif + +#ifndef SET_LOG_LEVEL +#define SET_LOG_LEVEL(x) ((void)(x)) +#endif + +#define PLAT_LOG_NOTICE(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_NOTICE) { \ + bcm_elog(LOG_MARKER_NOTICE __VA_ARGS__); \ + tf_log(LOG_MARKER_NOTICE __VA_ARGS__); \ + } \ + } while (0) + +#define PLAT_LOG_ERROR(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_ERROR) { \ + bcm_elog(LOG_MARKER_ERROR, __VA_ARGS__); \ + tf_log(LOG_MARKER_ERROR __VA_ARGS__); \ + } \ + } while (0) + +#define PLAT_LOG_WARN(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_WARNING) { \ + bcm_elog(LOG_MARKER_WARNING, __VA_ARGS__);\ + tf_log(LOG_MARKER_WARNING __VA_ARGS__); \ + } \ + } while (0) + +#define PLAT_LOG_INFO(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_INFO) { \ + bcm_elog(LOG_MARKER_INFO __VA_ARGS__); \ + tf_log(LOG_MARKER_INFO __VA_ARGS__); \ + } \ + } while (0) + +#define PLAT_LOG_VERBOSE(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_VERBOSE) { \ + bcm_elog(LOG_MARKER_VERBOSE __VA_ARGS__);\ + tf_log(LOG_MARKER_VERBOSE __VA_ARGS__); \ + } \ + } while (0) + +/* Print file and line number on assert */ +#define PLAT_LOG_LEVEL_ASSERT LOG_LEVEL_INFO + +/* + * The number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#if USE_COHERENT_MEM +#define CMN_BL_REGIONS 3 +#else +#define CMN_BL_REGIONS 2 +#endif + +/* + * FIP definitions + */ +#define PLAT_FIP_ATTEMPT_OFFSET 0x20000 +#define PLAT_FIP_NUM_ATTEMPTS 128 + +#define PLAT_BRCM_FIP_QSPI_BASE QSPI_BASE_ADDR +#define PLAT_BRCM_FIP_NAND_BASE NAND_BASE_ADDR +#define PLAT_BRCM_FIP_MAX_SIZE 0x01000000 + +#define PLAT_BRCM_FIP_BASE PLAT_BRCM_FIP_QSPI_BASE +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h b/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h new file mode 100644 index 0000000..178c843 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMN_PLAT_UTIL_H +#define CMN_PLAT_UTIL_H + +#include + +/* BOOT source */ +#define BOOT_SOURCE_MASK 7 +#define BOOT_SOURCE_QSPI 0 +#define BOOT_SOURCE_NAND 1 +#define BOOT_SOURCE_SPI_NAND 2 +#define BOOT_SOURCE_UART 3 +#define BOOT_SOURCE_RES4 4 +#define BOOT_SOURCE_EMMC 5 +#define BOOT_SOURCE_ATE 6 +#define BOOT_SOURCE_USB 7 +#define BOOT_SOURCE_MAX 8 +#define BOOT_SOURCE_UNKNOWN (-1) + +#define KHMAC_SHA256_KEY_SIZE 32 + +#define SOFT_PWR_UP_RESET_L0 0 +#define SOFT_SYS_RESET_L1 1 +#define SOFT_RESET_L3 0x3 + +#define BOOT_SOURCE_SOFT_DATA_OFFSET 8 +#define BOOT_SOURCE_SOFT_ENABLE_OFFSET 14 +#define BOOT_SOURCE_SOFT_ENABLE_MASK BIT(BOOT_SOURCE_SOFT_ENABLE_OFFSET) + +typedef struct _key { + uint8_t hmac_sha256[KHMAC_SHA256_KEY_SIZE]; +} cmn_key_t; + +uint32_t boot_source_get(void); +void bl1_platform_wait_events(void); +void plat_soft_reset(uint32_t reset); + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c b/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c new file mode 100644 index 0000000..c80d5dd --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#pragma weak plat_tz_master_default_cfg +#pragma weak plat_tz_sdio_ns_master_set +#pragma weak plat_tz_usb_ns_master_set + +void plat_tz_master_default_cfg(void) +{ + /* This function should be implemented in the platform side. */ + ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__); +} + +void plat_tz_sdio_ns_master_set(uint32_t ns) +{ + /* This function should be implemented in the platform side. */ + ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__); +} + +void plat_tz_usb_ns_master_set(uint32_t ns) +{ + /* This function should be implemented in the platform side. */ + ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__); +} + +void tz_master_default_cfg(void) +{ + plat_tz_master_default_cfg(); +} + +void tz_sdio_ns_master_set(uint32_t ns) +{ + plat_tz_sdio_ns_master_set(ns); +} + +void tz_usb_ns_master_set(uint32_t ns) +{ + plat_tz_usb_ns_master_set(ns); +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h b/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h new file mode 100644 index 0000000..f74863d --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMN_SEC_H +#define CMN_SEC_H + +#include + +#define SECURE_MASTER 0 +#define NS_MASTER 1 + +void tz_master_default_cfg(void); +void tz_usb_ns_master_set(uint32_t ns); +void tz_sdio_ns_master_set(uint32_t ns); + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/common/err.c b/arm-trusted-firmware/plat/brcm/board/common/err.c new file mode 100644 index 0000000..1fc73c4 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/err.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include + +#define L0_RESET 0x2 + +/* + * Brcm error handler + */ +void plat_error_handler(int err) +{ + INFO("L0 reset...\n"); + + /* Ensure the characters are flushed out */ + console_flush(); + + mmio_write_32(CRMU_SOFT_RESET_CTRL, L0_RESET); + + /* + * In case we get here: + * Loop until the watchdog resets the system + */ + while (1) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/plat_setup.c b/arm-trusted-firmware/plat/brcm/board/common/plat_setup.c new file mode 100644 index 0000000..95e12ed --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/plat_setup.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* + * This function returns the fixed clock frequency at which private + * timers run. This value will be programmed into CNTFRQ_EL0. + */ +unsigned int plat_get_syscnt_freq2(void) +{ + return SYSCNT_FREQ; +} + +static const char * const plat_prefix_str[] = { + "E: ", "N: ", "W: ", "I: ", "V: " +}; + +const char *plat_log_get_prefix(unsigned int log_level) +{ + return plat_prefix_str[log_level - 1U]; +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/platform_common.c b/arm-trusted-firmware/plat/brcm/board/common/platform_common.c new file mode 100644 index 0000000..f4c9a73 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/platform_common.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +uint32_t boot_source_get(void) +{ + uint32_t data; + +#ifdef FORCE_BOOTSOURCE + data = FORCE_BOOTSOURCE; +#else + /* Read primary boot strap from CRMU persistent registers */ + data = mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1); + if (data & BOOT_SOURCE_SOFT_ENABLE_MASK) { + data >>= BOOT_SOURCE_SOFT_DATA_OFFSET; + } else { + uint64_t sotp_atf_row; + + sotp_atf_row = + sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC); + + if (sotp_atf_row & SOTP_BOOT_SOURCE_ENABLE_MASK) { + /* Construct the boot source based on SOTP bits */ + data = 0; + if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS0) + data |= 0x1; + if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS1) + data |= 0x2; + if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS2) + data |= 0x4; + } else { + + /* + * This path is for L0 reset with + * Primary Boot source disabled in SOTP. + * BOOT_SOURCE_FROM_PR_ON_L1 compile flag will allow + * to never come back here so that the + * external straps will not be read on L1 reset. + */ + + /* Use the external straps */ + data = mmio_read_32(ROM_S0_IDM_IO_STATUS); + +#ifdef BOOT_SOURCE_FROM_PR_ON_L1 + /* Enable boot source read from PR#1 */ + mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, + BOOT_SOURCE_SOFT_ENABLE_MASK); + + /* set boot source */ + data &= BOOT_SOURCE_MASK; + mmio_clrsetbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, + BOOT_SOURCE_MASK << BOOT_SOURCE_SOFT_DATA_OFFSET, + data << BOOT_SOURCE_SOFT_DATA_OFFSET); +#endif + } + } +#endif + return (data & BOOT_SOURCE_MASK); +} + +void __dead2 plat_soft_reset(uint32_t reset) +{ + if (reset == SOFT_RESET_L3) { + mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, reset); + mmio_write_32(CRMU_MAIL_BOX0, 0x0); + mmio_write_32(CRMU_MAIL_BOX1, 0xFFFFFFFF); + } + + if (reset != SOFT_SYS_RESET_L1) + reset = SOFT_PWR_UP_RESET_L0; + + if (reset == SOFT_PWR_UP_RESET_L0) + INFO("L0 RESET...\n"); + + if (reset == SOFT_SYS_RESET_L1) + INFO("L1 RESET...\n"); + + console_flush(); + + mmio_clrbits_32(CRMU_SOFT_RESET_CTRL, 1 << reset); + + while (1) { + ; + } +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/sbl_util.c b/arm-trusted-firmware/plat/brcm/board/common/sbl_util.c new file mode 100644 index 0000000..06e5b33 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/sbl_util.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#pragma weak plat_sbl_status + +int plat_sbl_status(uint64_t sbl_status) +{ + return sbl_status ? 1:0; +} + +int sbl_status(void) +{ + uint64_t sbl_sotp = 0; + int ret = SBL_DISABLED; + + sbl_sotp = sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC); + + if (sbl_sotp != SOTP_ECC_ERR_DETECT) { + + sbl_sotp &= SOTP_SBL_MASK; + + if (plat_sbl_status(sbl_sotp)) + ret = SBL_ENABLED; + } + + VERBOSE("SBL status: %d\n", ret); + + return ret; +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/sbl_util.h b/arm-trusted-firmware/plat/brcm/board/common/sbl_util.h new file mode 100644 index 0000000..0747389 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/sbl_util.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SBL_UTIL_H +#define SBL_UTIL_H + +#include + +#include + +#define SBL_DISABLED 0 +#define SBL_ENABLED 1 + +int sbl_status(void); + +#endif /* #ifdef SBL_UTIL_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/common/timer_sync.c b/arm-trusted-firmware/plat/brcm/board/common/timer_sync.c new file mode 100644 index 0000000..7e33a94 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/timer_sync.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/******************************************************************************* + * Defines related to time sync and satelite timers + ******************************************************************************/ +#define TIME_SYNC_WR_ENA ((uint32_t)0xACCE55 << 8) +#define IHOST_STA_TMR_CTRL 0x1800 +#define IHOST_SAT_TMR_INC_L 0x1814 +#define IHOST_SAT_TMR_INC_H 0x1818 + +#define SAT_TMR_CYCLE_DELAY 2 +#define SAT_TMR_32BIT_WRAP_VAL (BIT_64(32) - SAT_TMR_CYCLE_DELAY) + +void ihost_enable_satellite_timer(unsigned int cluster_id) +{ + uintptr_t ihost_base; + uint32_t time_lx, time_h; + uintptr_t ihost_enable; + + VERBOSE("Program iHost%u satellite timer\n", cluster_id); + ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE; + + /* this read starts the satellite timer counting from 0 */ + ihost_enable = CENTRAL_TIMER_GET_IHOST_ENA_BASE + cluster_id * 4; + time_lx = mmio_read_32(ihost_enable); + + /* + * Increment the satellite timer by the central timer plus 2 + * to accommodate for a 1 cycle delay through NOC + * plus counter starting from 0. + */ + mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_L, + time_lx + SAT_TMR_CYCLE_DELAY); + + /* + * Read the latched upper data, if lx will wrap by adding 2 to it + * we need to handle the wrap + */ + time_h = mmio_read_32(CENTRAL_TIMER_GET_H); + if (time_lx >= SAT_TMR_32BIT_WRAP_VAL) + mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h + 1); + else + mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h); +} + +void brcm_timer_sync_init(void) +{ + unsigned int cluster_id; + + /* Get the Time Sync module out of reset */ + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, + BIT(CDRU_MISC_RESET_CONTROL_TS_RESET_N)); + + /* Deassert the Central Timer TIMER_EN signal for all module */ + mmio_write_32(CENTRAL_TIMER_SAT_TMR_ENA, TIME_SYNC_WR_ENA); + + /* enables/programs iHost0 satellite timer*/ + cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr()); + ihost_enable_satellite_timer(cluster_id); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S new file mode 100644 index 0000000..9a2039d --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include + + .globl plat_reset_handler + .globl platform_get_entrypoint + .globl plat_secondary_cold_boot_setup + .globl platform_mem_init + .globl platform_check_mpidr + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_disable_acp + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl platform_is_primary_cpu + .globl plat_brcm_calc_core_pos + .globl plat_get_my_entrypoint + + + /* ------------------------------------------------------------ + * void plat_l2_init(void); + * + * BL1 and BL2 run with one core, one cluster + * This is safe to disable cluster coherency + * to make use of the data cache MMU WB attribute + * for the SRAM. + * + * Set L2 Auxiliary Control Register + * -------------------------------------------------------------------- + */ +func plat_l2_init + mrs x0, CORTEX_A72_L2ACTLR_EL1 +#if (IMAGE_BL1 || IMAGE_BL2) || defined(USE_SINGLE_CLUSTER) + orr x0, x0, #CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI +#else + bic x0, x0, #CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI +#endif + msr CORTEX_A72_L2ACTLR_EL1, x0 + + /* Set L2 Control Register */ + mrs x0, CORTEX_A72_L2CTLR_EL1 + mov x1, #((CORTEX_A72_L2_DATA_RAM_LATENCY_MASK << \ + CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (CORTEX_A72_L2_TAG_RAM_LATENCY_MASK << \ + CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT) | \ + (U(0x1) << CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT) | \ + (U(0x1) << CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT)) + bic x0, x0, x1 + mov x1, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << \ + CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (U(0x1) << CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT) | \ + (U(0x1) << CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT)) + orr x0, x0, x1 + msr CORTEX_A72_L2CTLR_EL1, x0 + + isb + ret +endfunc plat_l2_init + + /* -------------------------------------------------------------------- + * void plat_reset_handler(void); + * + * Before adding code in this function, refer to the guidelines in + * docs/firmware-design.md. + * + * -------------------------------------------------------------------- + */ +func plat_reset_handler + mov x9, x30 + bl plat_l2_init + mov x30, x9 + ret +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * void platform_get_entrypoint (unsigned int mpid); + * + * Main job of this routine is to distinguish between + * a cold and warm boot. + * On a cold boot the secondaries first wait for the + * platform to be initialized after which they are + * hotplugged in. The primary proceeds to perform the + * platform initialization. + * ----------------------------------------------------- + */ +func platform_get_entrypoint + /*TBD-STINGRAY*/ + mov x0, #0 + ret +endfunc platform_get_entrypoint + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + bl plat_my_core_pos + mov_imm x1, SECONDARY_CPU_SPIN_BASE_ADDR + add x0, x1, x0, LSL #3 + mov x1, #0 + str x1, [x0] + + /* Wait until the entrypoint gets populated */ +poll_mailbox: + ldr x1, [x0] + cbz x1, 1f + br x1 +1: + wfe + b poll_mailbox +endfunc plat_secondary_cold_boot_setup + + + /* ----------------------------------------------------- + * void platform_mem_init(void); + * + * We don't need to carry out any memory initialization + * on CSS platforms. The Secure RAM is accessible straight away. + * ----------------------------------------------------- + */ +func platform_mem_init + /*TBD-STINGRAY*/ + ret +endfunc platform_mem_init + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * ----------------------------------------------------- + */ +func platform_check_mpidr + /*TBD-STINGRAY*/ + mov x0, xzr + ret +endfunc platform_check_mpidr + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ + +func plat_crash_console_init + mov_imm x0, BRCM_CRASH_CONSOLE_BASE + mov_imm x1, BRCM_CRASH_CONSOLE_REFCLK + mov_imm x2, BRCM_CRASH_CONSOLE_BAUDRATE + b console_16550_core_init + ret +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(void) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2, x3 + * --------------------------------------------- + */ + +func plat_crash_console_putc + mov_imm x1, BRCM_CRASH_CONSOLE_BASE + b console_16550_core_putc + ret +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush(void) + * Function to flush crash console + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, BRCM_CRASH_CONSOLE_BASE + b console_16550_core_flush + ret +endfunc plat_crash_console_flush + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. This function is allowed to use + * registers x0 - x17. + * ----------------------------------------------------- + */ + +func plat_disable_acp + /*TBD-STINGRAY*/ + ret +endfunc plat_disable_acp + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu (applicable only after a cold boot) + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + b platform_is_primary_cpu +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_brcm_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_brcm_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int platform_is_primary_cpu (void); + * + * Find out whether the current cpu is the primary + * cpu (applicable only after a cold boot) + * ----------------------------------------------------- + */ +func platform_is_primary_cpu + mov x9, x30 + bl plat_my_core_pos + cmp x0, #PRIMARY_CPU + cset x0, eq + ret x9 +endfunc platform_is_primary_cpu + + /* ----------------------------------------------------- + * unsigned int plat_brcm_calc_core_pos(uint64_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func plat_brcm_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #7 + ret +endfunc plat_brcm_calc_core_pos + +func plat_get_my_entrypoint + mrs x0, mpidr_el1 + b platform_get_entrypoint +endfunc plat_get_my_entrypoint diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t-ns3.mk b/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t-ns3.mk new file mode 100644 index 0000000..5164eeb --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t-ns3.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2015 - 2020, Broadcom +# +# SPDX-License-Identifier: BSD-3-Clause +# + +####################################################### +# Board config file for bcm958742t-ns3 Stingray SST100-NS3 +####################################################### + +include plat/brcm/board/stingray/bcm958742t.mk + +# Load BL33 at 0xFF00_0000 address +ifneq (${BL33_OVERRIDE_LOAD_ADDR},) +$(eval $(call add_define_val,BL33_OVERRIDE_LOAD_ADDR,0xFF000000)) +endif + +# Nitro DDR secure memory +# Nitro FW and config 0x8AE00000 - 0x8B000000 +# Nitro Crash dump 0x8B000000 - 0x8D000000 +DDR_NITRO_SECURE_REGION_START := 0x8AE00000 +DDR_NITRO_SECURE_REGION_END := 0x8D000000 diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t.mk b/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t.mk new file mode 100644 index 0000000..5e164b8 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2015 - 2020, Broadcom +# +# SPDX-License-Identifier: BSD-3-Clause +# + +####################################################### +# Board config file for bcm958742t Stingray SST100 +####################################################### +BOARD_FAMILY := "" +$(eval $(call add_define,BOARD_FAMILY)) + +# Board has internal programmable regulator +IHOST_REG_TYPE := IHOST_REG_INTEGRATED +$(eval $(call add_define,IHOST_REG_TYPE)) + +# Board has internal programmable regulator +VDDC_REG_TYPE := VDDC_REG_INTEGRATED +$(eval $(call add_define,VDDC_REG_TYPE)) diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h new file mode 100644 index 0000000..b2427cf --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_FAMILY_H +#define BOARD_FAMILY_H + +#if defined(DRIVER_SPD_ENABLE) && !defined(DRIVER_SPD_SPOOF) +#include +#endif + +#ifdef USE_GPIO +/* max number of supported GPIOs to construct the bitmap for board detection */ +#define MAX_NR_GPIOS 4 + +/* max GPIO bitmap value */ +#define MAX_GPIO_BITMAP_VAL (BIT(MAX_NR_GPIOS) - 1) +#endif + +struct mcb_ref_group { + uint32_t mcb_ref; + unsigned int *mcb_cfg; +}; + +#define MCB_REF_GROUP(ref) \ +{ \ + .mcb_ref = 0x ## ref, \ + .mcb_cfg = mcb_ ## ref, \ +} + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c new file mode 100644 index 0000000..74d2077 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include + +static void brcm_stingray_pnor_pinmux_init(void) +{ + unsigned int i; + + INFO(" - pnor pinmux init start.\n"); + + /* Set PNOR_ADV_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2dc), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_BAA_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e0), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_BLS_0_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e4), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_BLS_1_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e8), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_CRE_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2ec), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_CS_2_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f0), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_CS_1_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f4), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_CS_0_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f8), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_WE_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2fc), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_OE_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x300), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_INTR_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x304), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set PNOR_DAT_x_MODE_SEL_CONTROL.fsel = 0x2 */ + for (i = 0; i < 0x40; i += 0x4) { + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x308 + i), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + } + + /* Set NAND_CE1_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x348), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set NAND_CE0_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x34c), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set NAND_WE_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x350), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set NAND_WP_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x354), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set NAND_RE_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x358), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set NAND_RDY_BSY_N_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x35c), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set NAND_IOx_0_MODE_SEL_CONTROL.fsel = 0x2 */ + for (i = 0; i < 0x40; i += 0x4) { + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x360 + i), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + } + + /* Set NAND_ALE_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x3a0), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + /* Set NAND_CLE_MODE_SEL_CONTROL.fsel = 0x2 */ + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x3a4), + MODE_SEL_CONTROL_FSEL_MASK, + MODE_SEL_CONTROL_FSEL_MODE2); + + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x40), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x44), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x48), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x4c), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x50), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x54), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x58), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x5c), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x60), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x64), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x68), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x6c), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x70), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x74), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x78), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x7c), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x80), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x84), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x88), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x8c), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x90), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x94), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x98), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x9c), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa0), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa4), (7 << 1), 0x8); + mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa8), (7 << 1), 0x8); + + INFO(" - pnor pinmux init done.\n"); +} + +#if BL2_TEST_EXT_SRAM +#define SRAM_CHECKS_GRANUL 0x100000 +#define SRAM_CHECKS_CNT 8 +static unsigned int sram_checks[SRAM_CHECKS_CNT] = { + /* offset, magic */ + 0xd00dfeed, + 0xfadebabe, + 0xc001d00d, + 0xa5a5b5b5, + 0x5a5a5b5b, + 0xc5c5d5d5, + 0x5c5c5d5d, + 0xe5e5f5f5, +}; +#endif + +static void brcm_stingray_pnor_sram_init(void) +{ + unsigned int val, tmp; +#if BL2_TEST_EXT_SRAM + unsigned int off, i; +#endif + INFO(" - pnor sram init start.\n"); + + /* Enable PNOR Clock */ + INFO(" -- enable pnor clock\n"); + mmio_write_32((uintptr_t)(PNOR_IDM_IO_CONTROL_DIRECT), 0x1); + udelay(500); + + /* Reset PNOR */ + INFO(" -- reset pnor\n"); + mmio_setbits_32((uintptr_t)(PNOR_IDM_IO_RESET_CONTROL), 0x1); + udelay(500); + mmio_clrbits_32((uintptr_t)(PNOR_IDM_IO_RESET_CONTROL), 0x1); + udelay(500); + + /* Configure slave address to chip-select mapping */ + INFO(" -- configure pnor slave address to chip-select mapping\n"); + /* 0x74000000-0x75ffffff => CS0 (32MB) */ + val = (0xfe << PNOR_ICFG_CS_x_MASK0_SHIFT); + val |= (0x74); + mmio_write_32((uintptr_t)(PNOR_ICFG_CS_0), val); + /* 0x76000000-0x77ffffff => CS1 (32MB) */ + val = (0xfe << PNOR_ICFG_CS_x_MASK0_SHIFT); + val |= (0x76); + mmio_write_32((uintptr_t)(PNOR_ICFG_CS_1), val); + /* 0xffffffff-0xffffffff => CS2 (0MB) */ + val = (0x00 << PNOR_ICFG_CS_x_MASK0_SHIFT); + val |= (0xff); + mmio_write_32((uintptr_t)(PNOR_ICFG_CS_2), val); + + /* Print PNOR ID */ + tmp = 0x0; + val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID0)); + tmp |= (val & PNOR_REG_PERIPH_IDx_MASK); + val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID1)); + tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 8); + val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID2)); + tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 16); + val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID3)); + tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 24); + INFO(" -- pnor primecell_id = 0x%x\n", tmp); + + /* PNOR set_cycles */ +#ifdef EMULATION_SETUP + val = 0x00129A44; +#else + val = 0x00125954; /* 0x00002DEF; */ +#endif + mmio_write_32((uintptr_t)(PNOR_REG_SET_CYCLES), val); + INFO(" -- pnor set_cycles = 0x%x\n", val); + + /* PNOR set_opmode */ + val = 0x0; +#ifdef EMULATION_SETUP + /* TODO: Final values to be provided by DV folks */ + val &= ~(0x7 << 7); /* set_wr_bl */ + val &= ~(0x7 << 3); /* set_rd_bl */ + val &= ~(0x3); + val |= (0x1); /* set_mw */ +#else + /* TODO: Final values to be provided by DV folks */ + val &= ~(0x7 << 7); /* set_wr_bl */ + val &= ~(0x7 << 3); /* set_rd_bl */ + val &= ~(0x3); + val |= (0x1); /* set_mw */ +#endif + mmio_write_32((uintptr_t)(PNOR_REG_SET_OPMODE), val); + INFO(" -- pnor set_opmode = 0x%x\n", val); + +#ifndef EMULATION_SETUP + /* Actual SRAM chip will require self-refresh */ + val = 0x1; + mmio_write_32((uintptr_t)(PNOR_REG_REFRESH_0), val); + INFO(" -- pnor refresh_0 = 0x%x\n", val); +#endif + +#if BL2_TEST_EXT_SRAM + /* Check PNOR SRAM access */ + for (off = 0; off < NOR_SIZE; off += SRAM_CHECKS_GRANUL) { + i = (off / SRAM_CHECKS_GRANUL) % SRAM_CHECKS_CNT; + val = sram_checks[i]; + INFO(" -- pnor sram write addr=0x%lx value=0x%lx\n", + (unsigned long)(NOR_BASE_ADDR + off), + (unsigned long)val); + mmio_write_32((uintptr_t)(NOR_BASE_ADDR + off), val); + } + tmp = 0; + for (off = 0; off < NOR_SIZE; off += SRAM_CHECKS_GRANUL) { + i = (off / SRAM_CHECKS_GRANUL) % SRAM_CHECKS_CNT; + val = mmio_read_32((uintptr_t)(NOR_BASE_ADDR + off)); + INFO(" -- pnor sram read addr=0x%lx value=0x%lx\n", + (unsigned long)(NOR_BASE_ADDR + off), + (unsigned long)val); + if (val == sram_checks[i]) + tmp++; + } + INFO(" -- pnor sram checks pass=%d total=%d\n", + tmp, (NOR_SIZE / SRAM_CHECKS_GRANUL)); + + if (tmp != (NOR_SIZE / SRAM_CHECKS_GRANUL)) { + INFO(" - pnor sram init failed.\n"); + while (1) + ; + } else { + INFO(" - pnor sram init done.\n"); + } +#endif +} + +void ext_sram_init(void) +{ + INFO("%s start.\n", __func__); + + brcm_stingray_pnor_pinmux_init(); + + brcm_stingray_pnor_sram_init(); + + INFO("%s done.\n", __func__); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h new file mode 100644 index 0000000..8508653 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EXT_SRAM_INIT_H +#define EXT_SRAM_INIT_H + +void ext_sram_init(void); +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c new file mode 100644 index 0000000..1184928 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#define IHOST0_CONFIG_ROOT 0x66000000 +#define IHOST1_CONFIG_ROOT 0x66002000 +#define IHOST2_CONFIG_ROOT 0x66004000 +#define IHOST3_CONFIG_ROOT 0x66006000 +#define A72_CRM_PLL_PWR_ON 0x00000070 +#define A72_CRM_PLL_PWR_ON__PLL0_RESETB_R 4 +#define A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R 5 +#define A72_CRM_PLL_CHNL_BYPS_EN 0x000000ac +#define A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R 0 +#define A72_CRM_PLL_CHNL_BYPS_EN_DATAMASK 0x0000ec1f +#define A72_CRM_PLL_CMD 0x00000080 +#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R 0 +#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R 1 +#define A72_CRM_PLL_STATUS 0x00000084 +#define A72_CRM_PLL_STATUS__PLL0_LOCK_R 9 +#define A72_CRM_PLL0_CTRL1 0x00000100 +#define A72_CRM_PLL0_CTRL2 0x00000104 +#define A72_CRM_PLL0_CTRL3 0x00000108 +#define A72_CRM_PLL0_CTRL3__PLL0_PDIV_R 12 +#define A72_CRM_PLL0_CTRL4 0x0000010c +#define A72_CRM_PLL0_CTRL4__PLL0_KP_R 0 +#define A72_CRM_PLL0_CTRL4__PLL0_KI_R 4 +#define A72_CRM_PLL0_CTRL4__PLL0_KA_R 7 +#define A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R 10 + +#define PLL_MODE_VCO 0x0 +#define PLL_MODE_BYPASS 0x1 +#define PLL_RESET_TYPE_PLL 0x1 +#define PLL_RESET_TYPE_POST 0x2 +#define PLL_VCO 0x1 +#define PLL_POSTDIV 0x2 +#define ARM_FREQ_3G PLL_FREQ_FULL +#define ARM_FREQ_1P5G PLL_FREQ_HALF +#define ARM_FREQ_750M PLL_FREQ_QRTR + +static unsigned int ARMCOE_crm_getBaseAddress(unsigned int cluster_num) +{ + unsigned int ihostx_config_root; + + switch (cluster_num) { + case 0: + default: + ihostx_config_root = IHOST0_CONFIG_ROOT; + break; + case 1: + ihostx_config_root = IHOST1_CONFIG_ROOT; + break; + case 2: + ihostx_config_root = IHOST2_CONFIG_ROOT; + break; + case 3: + ihostx_config_root = IHOST3_CONFIG_ROOT; + break; + } + + return ihostx_config_root; +} + +static void ARMCOE_crm_pllAssertReset(unsigned int cluster_num, + unsigned int reset_type) +{ + unsigned long ihostx_config_root; + unsigned int pll_rst_ctrl; + + ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num); + pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON); + + // PLL reset + if (reset_type & PLL_RESET_TYPE_PLL) { + pll_rst_ctrl &= ~(0x1< + +#include + +#include + +#define ICFG_IPROC_IOPAD_CTRL_4 (IPROC_ROOT + 0x9c0) +#define ICFG_IPROC_IOPAD_CTRL_5 (IPROC_ROOT + 0x9c4) +#define ICFG_IPROC_IOPAD_CTRL_6 (IPROC_ROOT + 0x9c8) +#define ICFG_IPROC_IOPAD_CTRL_7 (IPROC_ROOT + 0x9cc) + +#define IOPAD_CTRL4_SDIO0_CD_IND_R 30 +#define IOPAD_CTRL4_SDIO0_CD_SRC_R 31 +#define IOPAD_CTRL4_SDIO0_CD_HYS_R 29 +#define IOPAD_CTRL4_SDIO0_CD_PULL_R 28 +#define IOPAD_CTRL4_SDIO0_CD_DRIVE_R 24 +#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R 23 +#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R 21 +#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R 17 + +#define IOPAD_CTRL4_SDIO0_DATA0_SRC_R 15 +#define IOPAD_CTRL4_SDIO0_DATA0_HYS_R 13 +#define IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R 9 +#define IOPAD_CTRL4_SDIO0_DATA1_SRC_R 7 +#define IOPAD_CTRL4_SDIO0_DATA1_HYS_R 5 +#define IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R 1 + +#define IOPAD_CTRL5_SDIO0_DATA2_SRC_R 31 +#define IOPAD_CTRL5_SDIO0_DATA2_HYS_R 29 +#define IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R 25 +#define IOPAD_CTRL5_SDIO0_DATA3_SRC_R 23 +#define IOPAD_CTRL5_SDIO0_DATA3_IND_R 22 +#define IOPAD_CTRL5_SDIO0_DATA3_HYS_R 21 +#define IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R 17 +#define IOPAD_CTRL5_SDIO0_DATA4_SRC_R 15 +#define IOPAD_CTRL5_SDIO0_DATA4_HYS_R 13 +#define IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R 9 +#define IOPAD_CTRL5_SDIO0_DATA5_SRC_R 7 +#define IOPAD_CTRL5_SDIO0_DATA5_HYS_R 5 +#define IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R 1 + +#define IOPAD_CTRL6_SDIO0_DATA6_SRC_R 31 +#define IOPAD_CTRL6_SDIO0_DATA6_HYS_R 29 +#define IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R 25 +#define IOPAD_CTRL6_SDIO0_DATA7_SRC_R 23 +#define IOPAD_CTRL6_SDIO0_DATA7_HYS_R 21 +#define IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R 17 + +void emmc_soft_reset(void) +{ + uint32_t val = 0; + + val = (BIT(IOPAD_CTRL6_SDIO0_DATA7_SRC_R) | + BIT(IOPAD_CTRL6_SDIO0_DATA7_HYS_R) | + BIT(IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R) | + BIT(IOPAD_CTRL6_SDIO0_DATA6_SRC_R) | + BIT(IOPAD_CTRL6_SDIO0_DATA6_HYS_R) | + BIT(IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R)); + + mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val); + + val = (BIT(IOPAD_CTRL5_SDIO0_DATA3_SRC_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA3_HYS_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA4_SRC_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA4_HYS_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA5_SRC_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA5_HYS_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R)); + + mmio_write_32(ICFG_IPROC_IOPAD_CTRL_5, val); + + val = (BIT(IOPAD_CTRL4_SDIO0_DATA0_SRC_R) | + BIT(IOPAD_CTRL4_SDIO0_DATA0_HYS_R) | + BIT(IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R) | + BIT(IOPAD_CTRL4_SDIO0_DATA1_SRC_R) | + BIT(IOPAD_CTRL4_SDIO0_DATA1_HYS_R) | + BIT(IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA2_SRC_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA2_HYS_R) | + BIT(IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R)); + + mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val); + + val = (BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R) | + BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R) | + BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R) | + BIT(IOPAD_CTRL4_SDIO0_CD_SRC_R) | + BIT(IOPAD_CTRL4_SDIO0_CD_HYS_R)); + + /* + * set pull-down, clear pull-up=0 + * bit 12: pull-down bit 11: pull-up + * Note: In emulation, this pull-down setting was not + * sufficient. Board design likely requires pull down on + * this pin for eMMC. + */ + + val |= BIT(IOPAD_CTRL4_SDIO0_CD_PULL_R); + + mmio_write_32(ICFG_IPROC_IOPAD_CTRL_4, val); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h b/arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h new file mode 100644 index 0000000..5033683 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2019 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SR_USB_H +#define SR_USB_H + +#define CDRU_PM_RESET_N_R BIT(CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R) +#define CDRU_USBSS_RESET_N BIT(CDRU_MISC_RESET_CONTROL__CDRU_USBSS_RESET_N) +#define CDRU_MISC_CLK_USBSS \ + BIT(CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_USBSS_CLK_EN_R) + +#define RESCAL_I_RSTB BIT(26) +#define RESCAL_I_PWRDNB BIT(27) + +#define DRDU3_U3PHY_CTRL 0x68500014 +#define PHY_RESET BIT(1) +#define POR_RESET BIT(28) +#define MDIO_RESET BIT(29) + +#define DRDU3_PWR_CTRL 0x6850002c +#define POWER_CTRL_OVRD BIT(2) + +#define USB3H_U3PHY_CTRL 0x68510014 +#define USB3H_U3SOFT_RST_N BIT(30) + +#define USB3H_PWR_CTRL 0x68510028 + +#define USB3_PHY_MDIO_BLOCK_BASE_REG 0x1f +#define BDC_AXI_SOFT_RST_N_OFFSET 0 +#define XHC_AXI_SOFT_RST_N_OFFSET 1 +#define MDIO_BUS_ID 3 +#define USB3H_PHY_ID 5 +#define USB3DRD_PHY_ID 2 + +#define USB3_PHY_RXPMD_BLOCK_BASE 0x8020 +#define USB3_PHY_RXPMD_REG1 0x1 +#define USB3_PHY_RXPMD_REG2 0x2 +#define USB3_PHY_RXPMD_REG5 0x5 +#define USB3_PHY_RXPMD_REG7 0x7 + +#define USB3_PHY_TXPMD_BLOCK_BASE 0x8040 +#define USB3_PHY_TXPMD_REG1 0x1 +#define USB3_PHY_TXPMD_REG2 0x2 + +#define USB3_PHY_ANA_BLOCK_BASE 0x8090 +#define USB3_PHY_ANA_REG0 0x0 +#define USB3_PHY_ANA_REG1 0x1 +#define USB3_PHY_ANA_REG2 0x2 +#define USB3_PHY_ANA_REG5 0x5 +#define USB3_PHY_ANA_REG8 0x8 +#define USB3_PHY_ANA_REG11 0xb + +#define USB3_PHY_AEQ_BLOCK_BASE 0x80e0 +#define USB3_PHY_AEQ_REG1 0x1 +#define USB3_PHY_AEQ_REG3 0x3 + +#ifdef USB_DMA_COHERENT +#define DRDU3_U3XHC_SOFT_RST_N BIT(31) +#define DRDU3_U3BDC_SOFT_RST_N BIT(30) + +#define DRDU3_SOFT_RESET_CTRL 0x68500030 +#define DRDU3_XHC_AXI_SOFT_RST_N BIT(1) +#define DRDU3_BDC_AXI_SOFT_RST_N BIT(0) + +#define DRDU2_PHY_CTRL 0x6852000c +#define DRDU2_U2SOFT_RST_N BIT(29) + +#define USB3H_SOFT_RESET_CTRL 0x6851002c +#define USB3H_XHC_AXI_SOFT_RST_N BIT(1) + +#define DRDU2_SOFT_RESET_CTRL 0x68520020 +#define DRDU2_BDC_AXI_SOFT_RST_N BIT(0) + +#define DRD2U3H_XHC_REGS_AXIWRA 0x68511c08 +#define DRD2U3H_XHC_REGS_AXIRDA 0x68511c0c +#define DRDU2D_BDC_REGS_AXIWRA 0x68521c08 +#define DRDU2D_BDC_REGS_AXIRDA 0x68521c0c +#define DRDU3H_XHC_REGS_AXIWRA 0x68501c08 +#define DRDU3H_XHC_REGS_AXIRDA 0x68501c0c +#define DRDU3D_BDC_REGS_AXIWRA 0x68502c08 +#define DRDU3D_BDC_REGS_AXIRDA 0x68502c0c +/* cacheable write-back, allocate on both reads and writes */ +#define USBAXI_AWCACHE 0xf +#define USBAXI_ARCACHE 0xf +/* non-secure */ +#define USBAXI_AWPROT 0x8 +#define USBAXI_ARPROT 0x8 +#define USBAXIWR_SA_VAL ((USBAXI_AWCACHE << 4 | USBAXI_AWPROT) << 0) +#define USBAXIWR_SA_MASK ((0xf << 4 | 0xf) << 0) +#define USBAXIWR_UA_VAL ((USBAXI_AWCACHE << 4 | USBAXI_AWPROT) << 16) +#define USBAXIWR_UA_MASK ((0xf << 4 | 0xf) << 0) +#define USBAXIRD_SA_VAL ((USBAXI_ARCACHE << 4 | USBAXI_ARPROT) << 0) +#define USBAXIRD_SA_MASK ((0xf << 4 | 0xf) << 0) +#define USBAXIRD_UA_VAL ((USBAXI_ARCACHE << 4 | USBAXI_ARPROT) << 16) +#define USBAXIRD_UA_MASK ((0xf << 4 | 0xf) << 0) +#endif /* USB_DMA_COHERENT */ + +#define ICFG_DRDU3_SID_CTRL 0x6850001c +#define ICFG_USB3H_SID_CTRL 0x6851001c +#define ICFG_DRDU2_SID_CTRL 0x68520010 +#define ICFG_USB_SID_SHIFT 5 +#define ICFG_USB_SID_AWADDR_OFFSET 0x0 +#define ICFG_USB_SID_ARADDR_OFFSET 0x4 + +#define USBIC_GPV_BASE 0x68600000 +#define USBIC_GPV_SECURITY0 (USBIC_GPV_BASE + 0x8) +#define USBIC_GPV_SECURITY0_FIELD BIT(0) +#define USBIC_GPV_SECURITY1 (USBIC_GPV_BASE + 0xc) +#define USBIC_GPV_SECURITY1_FIELD (BIT(0) | BIT(1)) +#define USBIC_GPV_SECURITY2 (USBIC_GPV_BASE + 0x10) +#define USBIC_GPV_SECURITY2_FIELD (BIT(0) | BIT(1)) +#define USBIC_GPV_SECURITY4 (USBIC_GPV_BASE + 0x18) +#define USBIC_GPV_SECURITY4_FIELD BIT(0) +#define USBIC_GPV_SECURITY10 (USBIC_GPV_BASE + 0x30) +#define USBIC_GPV_SECURITY10_FIELD (0x7 << 0) + +#define USBSS_TZPCDECPROT_BASE 0x68540800 +#define USBSS_TZPCDECPROT0set (USBSS_TZPCDECPROT_BASE + 0x4) +#define USBSS_TZPCDECPROT0clr (USBSS_TZPCDECPROT_BASE + 0x8) +#define DECPROT0_USBSS_DRD2U3H BIT(3) +#define DECPROT0_USBSS_DRDU2H BIT(2) +#define DECPROT0_USBSS_DRDU3D BIT(1) +#define DECPROT0_USBSS_DRDU2D BIT(0) +#define USBSS_TZPCDECPROT0 \ + (DECPROT0_USBSS_DRD2U3H | \ + DECPROT0_USBSS_DRDU2H | \ + DECPROT0_USBSS_DRDU3D | \ + DECPROT0_USBSS_DRDU2D) + +int32_t usb_device_init(unsigned int); + +#endif /* SR_USB_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c new file mode 100644 index 0000000..2b7c53b --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define MIN_VOLT 760000 +#define MAX_VOLT 1060000 + +#define BSTI_WRITE 0x1 +#define BSTI_READ 0x2 +#define BSTI_COMMAND_TA 0x2 +#define BSTI_COMMAND_DATA 0xFF +#define BSTI_CONTROL_VAL 0x81 +#define BSTI_CONTROL_BUSY 0x100 +#define BSTI_TOGGLE_BIT 0x2 +#define BSTI_CONFI_DONE_MASK 0xFFFFFFFD +#define BSTI_REG_DATA_MASK 0xFFFF +#define BSTI_CMD(sb, op, pa, ra, ta, data) \ + ((((sb) & 0x3) << 30) | (((op) & 0x3) << 28) | \ + (((pa) & 0x1F) << 23) | (((ra) & 0x1F) << 18) | \ + (((ta) & 0x3) << 16) | (data)) + +#define PHY_REG0 0x0 +#define PHY_REG1 0x1 +#define PHY_REG4 0x4 +#define PHY_REG5 0x5 +#define PHY_REG6 0x6 +#define PHY_REG7 0x7 +#define PHY_REGC 0xc + +#define IHOST_VDDC_DATA 0x560 +#define DDR_CORE_DATA 0x2560 +#define UPDATE_POS_EDGE(data, set) ((data) | ((set) << 1)) + +/* + * Formula for SR A2 reworked board: + * step = ((vol/(1.4117 * 0.98)) - 500000)/3125 + * where, + * vol - input voltage + * 500000 - Reference voltage + * 3125 - one step value + */ +#define A2_VOL_REF 500000 +#define ONE_STEP_VALUE 3125 +#define VOL_DIV(vol) (((vol*10000ull)/(14117*98ull)) * 100ull) +#define STEP_VALUE(vol) \ + ((((((VOL_DIV(vol)) - A2_VOL_REF) / ONE_STEP_VALUE) & 0xFF) << 8) | 4) + +#define B0_VOL_REF ((500000/100)*98) +#define B0_ONE_STEP_VALUE 3125 +/* + * Formula for SR B0 chip for IHOST12/03 and VDDC_CORE + * step = ((vol/1.56) - (500000 * 0.98))/3125 + * where, + * vol - input voltage + * 500000 - Reference voltage + * 3125 - one step value + */ +#define B0_VOL_DIV(vol) (((vol)*100ull)/156) +#define B0_STEP_VALUE(vol) \ + ((((((B0_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \ + & 0xFF) << 8) | 4) + +/* + * Formula for SR B0 chip for DDR-CORE + * step = ((vol/1) - (500000 * 0.98))/3125 + * where, + * vol - input voltage + * 500000 - Reference voltage + * 3125 - one step value + */ +#define B0_DDR_VDDC_VOL_DIV(vol) ((vol)/1) +#define B0_DDR_VDDC_STEP_VALUE(vol) \ + ((((((B0_DDR_VDDC_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \ + & 0xFF) << 8) | 4) + +#define MAX_SWREG_CNT 8 +#define MAX_ADDR_PER_SWREG 16 +#define MAX_REG_ADDR 0xF +#define MIN_REG_ADDR 0x0 + +static const char *sw_reg_name[MAX_SWREG_CNT] = { + "DDR_VDDC", + "IHOST03", + "IHOST12", + "IHOST_ARRAY", + "DDRIO_SLAVE", + "VDDC_CORE", + "VDDC1", + "DDRIO_MASTER" +}; + +/* firmware values for all SWREG for 3.3V input operation */ +static const uint16_t swreg_fm_data_bx[MAX_SWREG_CNT][MAX_ADDR_PER_SWREG] = { + /* DDR logic: Power Domains independent of 12v or 3p3v */ + {0x25E0, 0x2D54, 0x0EC6, 0x01EC, 0x28BB, 0x1144, 0x0200, 0x69C0, + 0x0010, 0x0EDF, 0x90D7, 0x8000, 0x820C, 0x0003, 0x0001, 0x0000}, + + /* ihost03, 3p3V */ + {0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80, + 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000}, + + /* ihost12 3p3v */ + {0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80, + 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000}, + + /* ihost array */ + {0x25E0, 0x2D94, 0x0EC6, 0x01EC, 0x2ABB, 0x1144, 0x0340, 0x69C0, + 0x0010, 0x0EDF, 0x90D7, 0x8000, 0x860C, 0x0003, 0x0001, 0x0000}, + + /* ddr io slave : 3p3v */ + {0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380, + 0x003F, 0x0FFF, 0x10D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000}, + + /* core master 3p3v */ + {0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80, + 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000}, + + /* core slave 3p3v */ + {0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380, + 0x003F, 0x0FFF, 0x10D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000}, + + /* ddr io master : 3p3v */ + {0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80, + 0x003F, 0x0FFF, 0x90D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000}, +}; + +#define FM_DATA swreg_fm_data_bx + +static int swreg_poll(void) +{ + uint32_t data; + int retry = 100; + + do { + data = mmio_read_32(BSTI_CONTROL_OFFSET); + if ((data & BSTI_CONTROL_BUSY) != BSTI_CONTROL_BUSY) + return 0; + retry--; + udelay(1); + } while (retry > 0); + + return -ETIMEDOUT; +} + +static int write_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t data) +{ + uint32_t cmd; + int ret; + + cmd = BSTI_CMD(0x1, BSTI_WRITE, reg_id, addr, BSTI_COMMAND_TA, data); + mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL); + mmio_write_32(BSTI_COMMAND_OFFSET, cmd); + ret = swreg_poll(); + if (ret) { + ERROR("Failed to write swreg %s addr 0x%x\n", + sw_reg_name[reg_id-1], addr); + return ret; + } + return ret; +} + +static int read_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t *data) +{ + uint32_t cmd; + int ret; + + cmd = BSTI_CMD(0x1, BSTI_READ, reg_id, addr, BSTI_COMMAND_TA, PHY_REG0); + mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL); + mmio_write_32(BSTI_COMMAND_OFFSET, cmd); + ret = swreg_poll(); + if (ret) { + ERROR("Failed to read swreg %s addr 0x%x\n", + sw_reg_name[reg_id-1], addr); + return ret; + } + + *data = mmio_read_32(BSTI_COMMAND_OFFSET); + *data &= BSTI_REG_DATA_MASK; + return ret; +} + +static int swreg_config_done(enum sw_reg reg_id) +{ + uint32_t read_data; + int ret; + + ret = read_swreg_config(reg_id, PHY_REG0, &read_data); + if (ret) + return ret; + + read_data &= BSTI_CONFI_DONE_MASK; + read_data |= BSTI_TOGGLE_BIT; + ret = write_swreg_config(reg_id, PHY_REG0, read_data); + if (ret) + return ret; + + ret = read_swreg_config(reg_id, PHY_REG0, &read_data); + if (ret) + return ret; + + read_data &= BSTI_CONFI_DONE_MASK; + ret = write_swreg_config(reg_id, PHY_REG0, read_data); + if (ret) + return ret; + + return ret; +} + +#ifdef DUMP_SWREG +static void dump_swreg_firmware(void) +{ + enum sw_reg reg_id; + uint32_t data; + int addr; + int ret; + + for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) { + INFO("SWREG: %s\n", sw_reg_name[reg_id - 1]); + for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) { + ret = read_swreg_config(reg_id, addr, &data); + if (ret) + ERROR("Failed to read offset %d\n", addr); + INFO("\t0x%x: 0x%04x\n", addr, data); + } + } +} +#endif + +int set_swreg(enum sw_reg reg_id, uint32_t micro_volts) +{ + uint32_t step, programmed_step; + uint32_t data = IHOST_VDDC_DATA; + int ret; + + if ((micro_volts > MAX_VOLT) || (micro_volts < MIN_VOLT)) { + ERROR("input voltage out-of-range\n"); + ret = -EINVAL; + goto failed; + } + + ret = read_swreg_config(reg_id, PHY_REGC, &programmed_step); + if (ret) + goto failed; + + if (reg_id == DDR_VDDC) + step = B0_DDR_VDDC_STEP_VALUE(micro_volts); + else + step = B0_STEP_VALUE(micro_volts); + + if ((step >> 8) != (programmed_step >> 8)) { + ret = write_swreg_config(reg_id, PHY_REGC, step); + if (ret) + goto failed; + + if (reg_id == DDR_VDDC) + data = DDR_CORE_DATA; + + ret = write_swreg_config(reg_id, PHY_REG0, + UPDATE_POS_EDGE(data, 1)); + if (ret) + goto failed; + + ret = write_swreg_config(reg_id, PHY_REG0, + UPDATE_POS_EDGE(data, 0)); + if (ret) + goto failed; + } + + INFO("%s voltage updated to %duV\n", sw_reg_name[reg_id-1], + micro_volts); + return ret; + +failed: + /* + * Stop booting if voltages are not set + * correctly. Booting will fail at random point + * if we continue with wrong voltage settings. + */ + ERROR("Failed to set %s voltage to %duV\n", sw_reg_name[reg_id-1], + micro_volts); + assert(0); + + return ret; +} + +/* Update SWREG firmware for all power doman for A2 chip */ +int swreg_firmware_update(void) +{ + enum sw_reg reg_id; + uint32_t data; + int addr; + int ret; + + /* write firmware values */ + for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) { + /* write higher location first */ + for (addr = MAX_REG_ADDR; addr >= MIN_REG_ADDR; addr--) { + ret = write_swreg_config(reg_id, addr, + FM_DATA[reg_id - 1][addr]); + if (ret) + goto exit; + } + } + + /* trigger SWREG firmware update */ + for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) { + /* + * Slave regulator doesn't have to be updated, + * Updating Master is enough + */ + if ((reg_id == DDRIO_SLAVE) || (reg_id == VDDC1)) + continue; + + ret = swreg_config_done(reg_id); + if (ret) { + ERROR("Failed to trigger SWREG firmware update for %s\n" + , sw_reg_name[reg_id-1]); + return ret; + } + } + + for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) { + /* + * IHOST_ARRAY will be used on some boards like STRATUS and + * there will not be any issue even if it is updated on other + * boards where it is not used. + */ + if (reg_id == IHOST_ARRAY) + continue; + + for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) { + ret = read_swreg_config(reg_id, addr, &data); + if (ret || (!ret && + (data != FM_DATA[reg_id - 1][addr]))) { + ERROR("swreg fm update failed: %s at off %d\n", + sw_reg_name[reg_id - 1], addr); + ERROR("Read val: 0x%x, expected val: 0x%x\n", + data, FM_DATA[reg_id - 1][addr]); + return -1; + } + } + } + + INFO("Updated SWREG firmware\n"); + +#ifdef DUMP_SWREG + dump_swreg_firmware(); +#endif + return ret; + +exit: + /* + * Stop booting if swreg firmware update fails. + * Booting will fail at random point if we + * continue with wrong voltage settings. + */ + ERROR("Failed to update firmware for %s SWREG\n", + sw_reg_name[reg_id-1]); + assert(0); + + return ret; +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c new file mode 100644 index 0000000..4a84141 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2019 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include "sr_usb.h" +#include + +static uint32_t usb_func = USB3_DRD | USB3H_USB2DRD; + +static void usb_pm_rescal_init(void) +{ + uint32_t data; + uint32_t try; + + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PM_RESET_N_R); + /* release reset */ + mmio_setbits_32(CDRU_CHIP_TOP_SPARE_REG0, RESCAL_I_RSTB); + udelay(10U); + /* power up */ + mmio_setbits_32(CDRU_CHIP_TOP_SPARE_REG0, + RESCAL_I_RSTB | RESCAL_I_PWRDNB); + try = 1000U; + do { + udelay(1U); + data = mmio_read_32(CDRU_CHIP_TOP_SPARE_REG1); + try--; + } while ((data & RESCAL_I_PWRDNB) == 0x0U && (try != 0U)); + + if (try == 0U) { + ERROR("CDRU_CHIP_TOP_SPARE_REG1: 0x%x\n", data); + } + + INFO("USB and PM Rescal Init done..\n"); +} + +const unsigned int xhc_portsc_reg_offset[MAX_USB_PORTS] = { + XHC_PORTSC1_OFFSET, + XHC_PORTSC2_OFFSET, + XHC_PORTSC3_OFFSET, +}; + +static void usb3h_usb2drd_init(void) +{ + uint32_t val; + + INFO("USB3H + USB 2DRD init\n"); + mmio_clrbits_32(USB3H_U3PHY_CTRL, POR_RESET); + val = mmio_read_32(USB3H_PWR_CTRL); + val &= ~(0x3U << POWER_CTRL_OVRD); + val |= (1U << POWER_CTRL_OVRD); + mmio_write_32(USB3H_PWR_CTRL, val); + mmio_setbits_32(USB3H_U3PHY_CTRL, PHY_RESET); + /* Phy to come out of reset */ + udelay(2U); + mmio_clrbits_32(USB3H_U3PHY_CTRL, MDIO_RESET); + + /* MDIO in reset */ + udelay(2U); + mmio_setbits_32(USB3H_U3PHY_CTRL, MDIO_RESET); + + /* After MDIO reset release */ + udelay(2U); + + /* USB 3.0 phy Analog Block Initialization */ + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG, + USB3_PHY_ANA_BLOCK_BASE); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG0, 0x4646U); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG1, 0x80c9U); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG2, 0x88a6U); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG5, 0x7c12U); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG8, 0x1d07U); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG11, 0x25cU); + + /* USB 3.0 phy RXPMD Block initialization*/ + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG, + USB3_PHY_RXPMD_BLOCK_BASE); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG1, 0x4052U); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG2, 0x4cU); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG5, 0x7U); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG7, 0x173U); + + /* USB 3.0 phy AEQ Block initialization*/ + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG, + USB3_PHY_AEQ_BLOCK_BASE); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_AEQ_REG1, 0x3000U); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_AEQ_REG3, 0x2c70U); + + /* USB 3.0 phy TXPMD Block initialization*/ + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG, + USB3_PHY_TXPMD_BLOCK_BASE); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_TXPMD_REG1, 0x100fU); + mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_TXPMD_REG2, 0x238cU); +} + +static void usb3drd_init(void) +{ + uint32_t val; + + INFO("USB3DRD init\n"); + mmio_clrbits_32(DRDU3_U3PHY_CTRL, POR_RESET); + val = mmio_read_32(DRDU3_PWR_CTRL); + val &= ~(0x3U << POWER_CTRL_OVRD); + val |= (1U << POWER_CTRL_OVRD); + mmio_write_32(DRDU3_PWR_CTRL, val); + mmio_setbits_32(DRDU3_U3PHY_CTRL, PHY_RESET); + /* Phy to come out of reset */ + udelay(2U); + mmio_clrbits_32(DRDU3_U3PHY_CTRL, MDIO_RESET); + + /* MDIO in reset */ + udelay(2U); + mmio_setbits_32(DRDU3_U3PHY_CTRL, MDIO_RESET); + + /* After MDIO reset release */ + udelay(2U); + + /* USB 3.0 DRD phy Analog Block Initialization */ + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG, + USB3_PHY_ANA_BLOCK_BASE); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG0, 0x4646U); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG1, 0x80c9U); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG2, 0x88a6U); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG5, 0x7c12U); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG8, 0x1d07U); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG11, 0x25cU); + + /* USB 3.0 DRD phy RXPMD Block initialization*/ + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG, + USB3_PHY_RXPMD_BLOCK_BASE); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG1, 0x4052U); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG2, 0x4cU); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG5, 0x7U); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG7, 0x173U); + + /* USB 3.0 DRD phy AEQ Block initialization*/ + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG, + USB3_PHY_AEQ_BLOCK_BASE); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_AEQ_REG1, 0x3000U); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_AEQ_REG3, 0x2c70U); + + /* USB 3.0 DRD phy TXPMD Block initialization*/ + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG, + USB3_PHY_TXPMD_BLOCK_BASE); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_TXPMD_REG1, 0x100fU); + mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_TXPMD_REG2, 0x238cU); +} + +static void usb3_phy_init(void) +{ + usb_pm_rescal_init(); + + if ((usb_func & USB3H_USB2DRD) != 0U) { + usb3h_usb2drd_init(); + } + + if ((usb_func & USB3_DRD) != 0U) { + usb3drd_init(); + } +} + +#ifdef USB_DMA_COHERENT +void usb_enable_coherence(void) +{ + if (usb_func & USB3H_USB2DRD) { + mmio_setbits_32(USB3H_SOFT_RESET_CTRL, + USB3H_XHC_AXI_SOFT_RST_N); + mmio_setbits_32(DRDU2_SOFT_RESET_CTRL, + DRDU2_BDC_AXI_SOFT_RST_N); + mmio_setbits_32(USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N); + mmio_setbits_32(DRDU2_PHY_CTRL, DRDU2_U2SOFT_RST_N); + + mmio_clrsetbits_32(DRD2U3H_XHC_REGS_AXIWRA, + (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK), + (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL)); + + mmio_clrsetbits_32(DRD2U3H_XHC_REGS_AXIRDA, + (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK), + (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL)); + + mmio_clrsetbits_32(DRDU2D_BDC_REGS_AXIWRA, + (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK), + (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL)); + + mmio_clrsetbits_32(DRDU2D_BDC_REGS_AXIRDA, + (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK), + (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL)); + + } + + if (usb_func & USB3_DRD) { + mmio_setbits_32(DRDU3_SOFT_RESET_CTRL, + (DRDU3_XHC_AXI_SOFT_RST_N | + DRDU3_BDC_AXI_SOFT_RST_N)); + mmio_setbits_32(DRDU3_U3PHY_CTRL, + (DRDU3_U3XHC_SOFT_RST_N | + DRDU3_U3BDC_SOFT_RST_N)); + + mmio_clrsetbits_32(DRDU3H_XHC_REGS_AXIWRA, + (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK), + (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL)); + + mmio_clrsetbits_32(DRDU3H_XHC_REGS_AXIRDA, + (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK), + (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL)); + + mmio_clrsetbits_32(DRDU3D_BDC_REGS_AXIWRA, + (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK), + (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL)); + + mmio_clrsetbits_32(DRDU3D_BDC_REGS_AXIRDA, + (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK), + (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL)); + } +} +#endif + +void xhci_phy_init(void) +{ + uint32_t val; + + INFO("usb init start\n"); + mmio_setbits_32(CDRU_MISC_CLK_ENABLE_CONTROL, + CDRU_MISC_CLK_USBSS); + + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_USBSS_RESET_N); + + if (usb_func & USB3_DRD) { + VERBOSE(" - configure stream_id = 0x6800 for DRDU3\n"); + val = SR_SID_VAL(0x3U, 0x1U, 0x0U) << ICFG_USB_SID_SHIFT; + mmio_write_32(ICFG_DRDU3_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET, + val); + mmio_write_32(ICFG_DRDU3_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET, + val); + + /* + * DRDU3 Device USB Space, DRDU3 Host USB Space, + * DRDU3 SS Config + */ + mmio_setbits_32(USBIC_GPV_SECURITY10, + USBIC_GPV_SECURITY10_FIELD); + } + + if (usb_func & USB3H_USB2DRD) { + VERBOSE(" - configure stream_id = 0x6801 for USB3H\n"); + val = SR_SID_VAL(0x3U, 0x1U, 0x1U) << ICFG_USB_SID_SHIFT; + mmio_write_32(ICFG_USB3H_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET, + val); + mmio_write_32(ICFG_USB3H_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET, + val); + + VERBOSE(" - configure stream_id = 0x6802 for DRDU2\n"); + val = SR_SID_VAL(0x3U, 0x1U, 0x2U) << ICFG_USB_SID_SHIFT; + mmio_write_32(ICFG_DRDU2_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET, + val); + mmio_write_32(ICFG_DRDU2_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET, + val); + + /* DRDU2 APB Bridge:DRDU2 USB Device, USB3H SS Config */ + mmio_setbits_32(USBIC_GPV_SECURITY1, USBIC_GPV_SECURITY1_FIELD); + + /* + * USB3H APB Bridge:DRDU2 Host + USB3 Host USB Space, + * USB3H SS Config + */ + mmio_setbits_32(USBIC_GPV_SECURITY2, USBIC_GPV_SECURITY2_FIELD); + } + + /* Configure Host masters as non-Secure */ + mmio_setbits_32(USBSS_TZPCDECPROT0set, USBSS_TZPCDECPROT0); + + /* CCN Slave on USBIC */ + mmio_setbits_32(USBIC_GPV_SECURITY0, USBIC_GPV_SECURITY0_FIELD); + + /* SLAVE_8:IDM Register Space */ + mmio_setbits_32(USBIC_GPV_SECURITY4, USBIC_GPV_SECURITY4_FIELD); + + usb3_phy_init(); +#ifdef USB_DMA_COHERENT + usb_enable_coherence(); +#endif + + usb_device_init(usb_func); + + INFO("PLAT USB: init done.\n"); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c new file mode 100644 index 0000000..54c98e1 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c @@ -0,0 +1,601 @@ +/* + * Copyright (c) 2019 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define USB_PHY_ALREADY_STARTED (-2) +#define USB_MAX_DEVICES 2 +#define USB3H_USB2DRD_PHY 0 +#define USB3_DRD_PHY 1 + +/* Common bit fields for all the USB2 phy */ +#define USB2_PHY_ISO DRDU2_U2PHY_ISO +#define USB2_AFE_PLL_PWRDWNB DRDU2_U2AFE_PLL_PWRDWNB +#define USB2_AFE_BG_PWRDWNB DRDU2_U2AFE_BG_PWRDWNB +#define USB2_AFE_LDO_PWRDWNB DRDU2_U2AFE_LDO_PWRDWNB +#define USB2_CTRL_CORERDY DRDU2_U2CTRL_CORERDY + +#define USB2_PHY_PCTL_MASK DRDU2_U2PHY_PCTL_MASK +#define USB2_PHY_PCTL_OFFSET DRDU2_U2PHY_PCTL_OFFSET +#define USB2_PHY_PCTL_VAL U2PHY_PCTL_VAL + +#define USB2_PLL_RESETB DRDU2_U2PLL_RESETB +#define USB2_PHY_RESETB DRDU2_U2PHY_RESETB + +static usb_phy_port_t usb_phy_port[2U][MAX_NR_PORTS]; + +static usb_phy_t usb_phy_info[2U] = { + {DRDU2_U2PLL_NDIV_FRAC, USB3H_PIPE_CTRL, 0U, USB3H_DRDU2_PHY}, + {0U, 0U, DRDU3_PIPE_CTRL, DRDU3_PHY} +}; + +typedef struct { + void *pcd_id; +} usb_platform_dev; + +/* index 0: USB3H + USB2 DRD, 1: USB3 DRD */ +static usb_platform_dev xhci_devices_configs[USB_MAX_DEVICES] = { + {&usb_phy_info[0U]}, + {&usb_phy_info[1U]} +}; + +static int32_t pll_lock_check(uint32_t address, uint32_t bit) +{ + uint32_t retry; + uint32_t data; + + retry = PLL_LOCK_RETRY_COUNT; + do { + data = mmio_read_32(address); + if ((data & bit) != 0U) { + return 0; + } + udelay(1); + } while (--retry != 0); + + ERROR("%s(): FAIL (0x%08x)\n", __func__, address); + return -1; +} + +/* + * USB2 PHY using external FSM bringup sequence + * Total #3 USB2 phys. All phys has the same + * bringup sequence. Register bit fields for + * some of the PHY's are different. + * Bit fields which are different are passed using + * struct u2_phy_ext_fsm with bit-fields and register addr. + */ + +static void u2_phy_ext_fsm_power_on(struct u2_phy_ext_fsm *u2_phy) +{ + mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO); + /* Delay as per external FSM spec */ + udelay(10U); + + mmio_setbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq); + /* Delay as per external FSM spec */ + udelay(10U); + + mmio_clrbits_32(u2_phy->phy_ctrl_reg, + (USB2_AFE_BG_PWRDWNB | + USB2_AFE_PLL_PWRDWNB | + USB2_AFE_LDO_PWRDWNB | + USB2_CTRL_CORERDY)); + + mmio_clrsetbits_32(u2_phy->phy_ctrl_reg, + (USB2_PHY_PCTL_MASK << USB2_PHY_PCTL_OFFSET), + (USB2_PHY_PCTL_VAL << USB2_PHY_PCTL_OFFSET)); + /* Delay as per external FSM spec */ + udelay(160U); + + mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_CTRL_CORERDY); + /* Delay as per external FSM spec */ + udelay(50U); + + mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_BG_PWRDWNB); + /* Delay as per external FSM spec */ + udelay(200U); + + mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_onin); + mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_LDO_PWRDWNB); + /* Delay as per external FSM spec */ + udelay(10U); + + mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_okin); + /* Delay as per external FSM spec */ + udelay(10U); + + mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_PLL_PWRDWNB); + /* Delay as per external FSM spec */ + udelay(10U); + + mmio_clrbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO); + /* Delay as per external FSM spec */ + udelay(10U); + mmio_clrbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq); + /* Delay as per external FSM spec */ + udelay(1U); + + mmio_setbits_32(u2_phy->pll_ctrl_reg, USB2_PLL_RESETB); + mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_RESETB); + +} + +static int32_t usb3h_u2_phy_power_on(uint32_t base) +{ + int32_t status; + struct u2_phy_ext_fsm u2_phy; + + u2_phy.pll_ctrl_reg = base + USB3H_U2PLL_CTRL; + u2_phy.phy_ctrl_reg = base + USB3H_U2PHY_CTRL; + u2_phy.phy_iddq = USB3H_U2PHY_IDDQ; + u2_phy.pwr_ctrl_reg = base + USB3H_PWR_CTRL; + u2_phy.pwr_okin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN; + u2_phy.pwr_onin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN; + + u2_phy_ext_fsm_power_on(&u2_phy); + + status = pll_lock_check(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_LOCK); + if (status != 0) { + /* re-try by toggling the PLL reset */ + mmio_clrbits_32(base + USB3H_U2PLL_CTRL, + (uint32_t)USB3H_U2PLL_RESETB); + mmio_setbits_32(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_RESETB); + status = pll_lock_check(base + USB3H_U2PLL_CTRL, + USB3H_U2PLL_LOCK); + if (status != 0) + ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__, + base + USB3H_U2PLL_CTRL); + } + + mmio_clrsetbits_32(base + USB3H_U2PHY_CTRL, + (USB3H_U2PHY_PCTL_MASK << USB3H_U2PHY_PCTL_OFFSET), + (U2PHY_PCTL_NON_DRV_LOW << USB3H_U2PHY_PCTL_OFFSET)); + return status; +} + +static int32_t usb3h_u3_phy_power_on(uint32_t base) +{ + int32_t status; + + /* Set pctl with mode and soft reset */ + mmio_clrsetbits_32(base + USB3H_U3PHY_CTRL, + (USB3H_U3PHY_PCTL_MASK << USB3H_U3PHY_PCTL_OFFSET), + (U3PHY_PCTL_VAL << USB3H_U3PHY_PCTL_OFFSET)); + + mmio_clrbits_32(base + USB3H_U3PHY_PLL_CTRL, + (uint32_t) USB3H_U3SSPLL_SUSPEND_EN); + mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_SEQ_START); + mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_RESETB); + + /* Time to stabilize the PLL Control */ + mdelay(1U); + + status = pll_lock_check(base + USB3H_U3PHY_PLL_CTRL, + USB3H_U3PLL_SS_LOCK); + + return status; +} + +static int32_t drdu3_u2_phy_power_on(uint32_t base) +{ + int32_t status; + struct u2_phy_ext_fsm u2_phy; + + u2_phy.pll_ctrl_reg = base + DRDU3_U2PLL_CTRL; + u2_phy.phy_ctrl_reg = base + DRDU3_U2PHY_CTRL; + u2_phy.phy_iddq = DRDU3_U2PHY_IDDQ; + u2_phy.pwr_ctrl_reg = base + DRDU3_PWR_CTRL; + u2_phy.pwr_okin = DRDU3_U2PHY_DFE_SWITCH_PWROKIN; + u2_phy.pwr_onin = DRDU3_U2PHY_DFE_SWITCH_PWRONIN; + + u2_phy_ext_fsm_power_on(&u2_phy); + + status = pll_lock_check(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_LOCK); + if (status != 0) { + /* re-try by toggling the PLL reset */ + mmio_clrbits_32(base + DRDU3_U2PLL_CTRL, + (uint32_t)DRDU2_U2PLL_RESETB); + mmio_setbits_32(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_RESETB); + + status = pll_lock_check(base + DRDU3_U2PLL_CTRL, + DRDU3_U2PLL_LOCK); + if (status != 0) { + ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__, + base + DRDU3_U2PLL_CTRL); + } + } + mmio_clrsetbits_32(base + DRDU3_U2PHY_CTRL, + (DRDU3_U2PHY_PCTL_MASK << DRDU3_U2PHY_PCTL_OFFSET), + (U2PHY_PCTL_NON_DRV_LOW << DRDU3_U2PHY_PCTL_OFFSET)); + + return status; +} + +static int32_t drdu3_u3_phy_power_on(uint32_t base) +{ + int32_t status; + + /* Set pctl with mode and soft reset */ + mmio_clrsetbits_32(base + DRDU3_U3PHY_CTRL, + (DRDU3_U3PHY_PCTL_MASK << DRDU3_U3PHY_PCTL_OFFSET), + (U3PHY_PCTL_VAL << DRDU3_U3PHY_PCTL_OFFSET)); + + mmio_clrbits_32(base + DRDU3_U3PHY_PLL_CTRL, + (uint32_t) DRDU3_U3SSPLL_SUSPEND_EN); + mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_SEQ_START); + mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_RESETB); + + /* Time to stabilize the PLL Control */ + mdelay(1U); + + status = pll_lock_check(base + DRDU3_U3PHY_PLL_CTRL, + DRDU3_U3PLL_SS_LOCK); + + return status; +} + +static int32_t drdu2_u2_phy_power_on(uint32_t base) +{ + int32_t status; + struct u2_phy_ext_fsm u2_phy; + + u2_phy.pll_ctrl_reg = base + DRDU2_U2PLL_CTRL; + u2_phy.phy_ctrl_reg = base + DRDU2_PHY_CTRL; + u2_phy.phy_iddq = DRDU2_U2IDDQ; + u2_phy.pwr_ctrl_reg = base + DRDU2_PWR_CTRL; + u2_phy.pwr_okin = DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I; + u2_phy.pwr_onin = DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I; + + u2_phy_ext_fsm_power_on(&u2_phy); + + status = pll_lock_check(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_LOCK); + if (status != 0) { + /* re-try by toggling the PLL reset */ + mmio_clrbits_32(base + DRDU2_U2PLL_CTRL, + (uint32_t)DRDU2_U2PLL_RESETB); + mmio_setbits_32(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_RESETB); + + status = pll_lock_check(base + DRDU2_U2PLL_CTRL, + DRDU2_U2PLL_LOCK); + if (status != 0) + ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__, + base + DRDU2_U2PLL_CTRL); + } + mmio_clrsetbits_32(base + DRDU2_PHY_CTRL, + (DRDU2_U2PHY_PCTL_MASK << DRDU2_U2PHY_PCTL_OFFSET), + (U2PHY_PCTL_NON_DRV_LOW << DRDU2_U2PHY_PCTL_OFFSET)); + + return status; +} + +void u3h_u2drd_phy_reset(usb_phy_port_t *phy_port) +{ + usb_phy_t *phy = phy_port->p; + + switch (phy_port->port_id) { + case USB3HS_PORT: + mmio_clrbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL, + (uint32_t) USB3H_U2CTRL_CORERDY); + mmio_setbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL, + USB3H_U2CTRL_CORERDY); + break; + case DRDU2_PORT: + mmio_clrbits_32(phy->drdu2reg + DRDU2_PHY_CTRL, + (uint32_t) DRDU2_U2CTRL_CORERDY); + mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL, + DRDU2_U2CTRL_CORERDY); + break; + } +} + +void u3drd_phy_reset(usb_phy_port_t *phy_port) +{ + usb_phy_t *phy = phy_port->p; + + if (phy_port->port_id == DRD3HS_PORT) { + mmio_clrbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL, + (uint32_t) DRDU3_U2CTRL_CORERDY); + mmio_setbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL, + DRDU3_U2CTRL_CORERDY); + } +} + +static int32_t u3h_u2drd_phy_power_on(usb_phy_port_t *phy_port) +{ + usb_phy_t *phy = phy_port->p; + int32_t status; + + switch (phy_port->port_id) { + case USB3SS_PORT: + mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, + (uint32_t) USB3H_DISABLE_USB30_P0); + status = usb3h_u3_phy_power_on(phy->usb3hreg); + if (status != 0) { + goto err_usb3h_phy_on; + } + break; + case USB3HS_PORT: + mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, + (uint32_t) USB3H_DISABLE_EUSB_P1); + mmio_setbits_32(AXI_DEBUG_CTRL, + AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); + mmio_setbits_32(USB3H_DEBUG_CTRL, + USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); + + mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL, + USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN); + /* Delay as per external FSM spec */ + udelay(10U); + mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL, + USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN); + status = usb3h_u2_phy_power_on(phy->usb3hreg); + if (status != 0) { + goto err_usb3h_phy_on; + } + break; + case DRDU2_PORT: + mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, + (uint32_t) USB3H_DISABLE_EUSB_P0); + mmio_setbits_32(AXI_DEBUG_CTRL, + AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); + mmio_setbits_32(USB3H_DEBUG_CTRL, + USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); + + mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL, + DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I); + /* Delay as per external FSM spec */ + udelay(10U); + mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL, + DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I); + + status = drdu2_u2_phy_power_on(phy->drdu2reg); + if (status != 0) { + mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, + USB3H_DISABLE_EUSB_P0); + goto err_drdu2_phy_on; + } + break; + } + + /* Device Mode */ + if (phy_port->port_id == DRDU2_PORT) { + mmio_write_32(phy->drdu2reg + DRDU2_SOFT_RESET_CTRL, + DRDU2_BDC_AXI_SOFT_RST_N); + mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL, + DRDU2_U2SOFT_RST_N); + } + /* Host Mode */ + mmio_write_32(phy->usb3hreg + USB3H_SOFT_RESET_CTRL, + USB3H_XHC_AXI_SOFT_RST_N); + mmio_setbits_32(phy->usb3hreg + USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N); + + return 0U; + err_usb3h_phy_on:mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, + (USB3H_DISABLE_EUSB_P1 | + USB3H_DISABLE_USB30_P0)); + err_drdu2_phy_on: + + return status; +} + +static int32_t u3drd_phy_power_on(usb_phy_port_t *phy_port) +{ + usb_phy_t *phy = phy_port->p; + int32_t status; + + switch (phy_port->port_id) { + case DRD3SS_PORT: + mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL, + (uint32_t) DRDU3_DISABLE_USB30_P0); + + status = drdu3_u3_phy_power_on(phy->drdu3reg); + if (status != 0) { + goto err_drdu3_phy_on; + } + break; + case DRD3HS_PORT: + mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL, + (uint32_t) DRDU3_DISABLE_EUSB_P0); + mmio_setbits_32(AXI_DEBUG_CTRL, + AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); + mmio_setbits_32(USB3H_DEBUG_CTRL, + USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); + + mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL, + DRDU3_U2PHY_DFE_SWITCH_PWRONIN); + /* Delay as per external FSM spec */ + udelay(10U); + mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL, + DRDU3_U2PHY_DFE_SWITCH_PWROKIN); + + status = drdu3_u2_phy_power_on(phy->drdu3reg); + if (status != 0) { + goto err_drdu3_phy_on; + } + + /* Host Mode */ + mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL, + DRDU3_XHC_AXI_SOFT_RST_N); + mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL, + DRDU3_U3XHC_SOFT_RST_N); + /* Device Mode */ + mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL, + DRDU3_BDC_AXI_SOFT_RST_N); + mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL, + DRDU3_U3BDC_SOFT_RST_N); + break; + } + + return 0U; + err_drdu3_phy_on:mmio_setbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL, + (DRDU3_DISABLE_EUSB_P0 | + DRDU3_DISABLE_USB30_P0)); + + return status; +} + +static void u3h_u2drd_phy_power_off(usb_phy_port_t *phy_port) +{ + usb_phy_t *p = phy_port->p; + + switch (phy_port->port_id) { + case USB3SS_PORT: + mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL, + USB3H_DISABLE_USB30_P0); + break; + case USB3HS_PORT: + mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL, + USB3H_DISABLE_EUSB_P1); + break; + case DRDU2_PORT: + mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL, + USB3H_DISABLE_EUSB_P0); + break; + } +} + +static void u3drd_phy_power_off(usb_phy_port_t *phy_port) +{ + usb_phy_t *p = phy_port->p; + + switch (phy_port->port_id) { + case DRD3SS_PORT: + mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL, + DRDU3_DISABLE_USB30_P0); + break; + case DRD3HS_PORT: + mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL, + DRDU3_DISABLE_EUSB_P0); + break; + } +} + +int32_t usb_info_fill(usb_phy_t *phy_info) +{ + int32_t index; + + if (phy_info->initialized != 0U) { + return USB_PHY_ALREADY_STARTED; + } + + if (phy_info->phy_id == USB3H_DRDU2_PHY) { + phy_info->phy_port = usb_phy_port[USB3H_DRDU2_PHY - 1U]; + phy_info->ports_enabled = 0x7U; + } else { + phy_info->phy_port = usb_phy_port[DRDU3_PHY - 1U]; + phy_info->ports_enabled = 0x3U; + } + + for (index = MAX_NR_PORTS - 1U; index > -1; index--) { + phy_info->phy_port[index].enabled = (phy_info->ports_enabled + >> index) & 0x1U; + phy_info->phy_port[index].p = phy_info; + phy_info->phy_port[index].port_id = index; + } + + return 0U; +} + +int32_t usb_phy_init(usb_platform_dev *device) +{ + int32_t status; + usb_phy_t *phy_info; + uint32_t index; + + phy_info = (usb_phy_t *)device->pcd_id; + + status = usb_info_fill(phy_info); + if (status != 0) { + return (status == USB_PHY_ALREADY_STARTED) ? 0 : status; + } + + for (index = 0U; index < MAX_NR_PORTS; index++) { + if (phy_info->phy_port[index].enabled != 0U) { + switch (phy_info->phy_id) { + case USB3H_DRDU2_PHY: + status = + u3h_u2drd_phy_power_on(&phy_info-> + phy_port[index]); + break; + default: + status = + u3drd_phy_power_on(&phy_info-> + phy_port[index]); + } + } + } + + phy_info->initialized = !status; + return status; +} + +void usb_phy_shutdown(usb_platform_dev *device) +{ + usb_phy_t *phy_info; + uint32_t index; + + phy_info = (usb_phy_t *)device->pcd_id; + + phy_info->initialized = 0U; + + for (index = 0U; index < MAX_NR_PORTS; index++) { + if (phy_info->phy_port[index].enabled != 0U) { + switch (phy_info->phy_id) { + case USB3H_DRDU2_PHY: + u3h_u2drd_phy_power_off(&phy_info-> + phy_port[index]); + break; + case DRDU3_PHY: + u3drd_phy_power_off(&phy_info->phy_port[index]); + break; + default: + INFO("%s: invalid phy id 0x%x\n", __func__, + phy_info->phy_id); + } + } + } +} + +int32_t usb_xhci_init(usb_platform_dev *device) +{ + int32_t status; + + status = usb_phy_init(device); + if (status == USB_PHY_ALREADY_STARTED) { + status = 0U; + } + + return status; +} + +int32_t usb_device_init(unsigned int usb_func) +{ + int32_t status; + int32_t devices_initialized = 0U; + + if ((usb_func & USB3H_USB2DRD) != 0U) { + status = usb_xhci_init( + &xhci_devices_configs[USB3H_USB2DRD_PHY]); + if (status == 0) { + devices_initialized++; + } else { + ERROR("%s(): USB3H_USB2DRD init failure\n", __func__); + } + } + + if ((usb_func & USB3_DRD) != 0U) { + status = usb_xhci_init(&xhci_devices_configs[USB3_DRD_PHY]); + if (status == 0) { + devices_initialized++; + } else { + ERROR("%s(): USB3_DRD init failure\n", __func__); + } + } + + return devices_initialized; +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h new file mode 100644 index 0000000..1dac48c --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL33_INFO_H +#define BL33_INFO_H + +/* Increase version number each time this file is modified */ +#define BL33_INFO_VERSION 4 + +struct chip_info { + unsigned int chip_id; + unsigned int rev_id; +}; + +struct boot_time_info { + unsigned int bl1_start; + unsigned int bl1_end; + unsigned int bl2_start; + unsigned int bl2_end; + unsigned int bl31_start; + unsigned int bl31_end; + unsigned int bl32_start; + unsigned int bl32_end; + unsigned int bl33_start; + unsigned int bl33_prompt; + unsigned int bl33_end; +}; + +struct bl33_info { + unsigned int version; + struct chip_info chip; + struct boot_time_info boot_time_info; +}; + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h new file mode 100644 index 0000000..8901259 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_INFO_H +#define BOARD_INFO_H + +#define IHOST_REG_INTEGRATED 0 +#define IHOST_REG_EXT_PROGRAMMABLE 1 +#define IHOST_REG_EXT_FIXED 2 + +#if defined(IHOST_REG_TYPE) + #if ((IHOST_REG_TYPE != IHOST_REG_INTEGRATED) && \ + (IHOST_REG_TYPE != IHOST_REG_EXT_PROGRAMMABLE) && \ + (IHOST_REG_TYPE != IHOST_REG_EXT_FIXED)) + #error "IHOST_REG_TYPE not valid" + #endif +#else + #define IHOST_REG_TYPE IHOST_REG_INTEGRATED +#endif + +#define VDDC_REG_INTEGRATED 0 +#define VDDC_REG_EXT_PROGRAMMABLE 1 +#define VDDC_REG_EXT_FIXED 2 + +#if defined(VDDC_REG_TYPE) + #if ((VDDC_REG_TYPE != VDDC_REG_INTEGRATED) && \ + (VDDC_REG_TYPE != VDDC_REG_EXT_PROGRAMMABLE) && \ + (VDDC_REG_TYPE != VDDC_REG_EXT_FIXED)) + #error "VDDC_REG_TYPE not valid" + #endif +#else + #define VDDC_REG_TYPE VDDC_REG_INTEGRATED +#endif + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h new file mode 100644 index 0000000..ebc2bb6 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CRMU_DEF_H +#define CRMU_DEF_H + +#define CRMU_REGS_BASE 0x66410000 +/* 32 kB IDRAM */ +#define CRMU_IDRAM_BASE_ADDR CRMU_REGS_BASE +#define CRMU_IDRAM_SIZE 0x8000 +/* 4 kB Scratch RAM */ +#define CRMU_SRAM_BASE (CRMU_IDRAM_BASE_ADDR + CRMU_IDRAM_SIZE) +#define CRMU_SRAM_SIZE 0x1000 + +#define CRMU_RESERVED_SPACE 0x3000 +#define CRMU_CORE_BASE (CRMU_SRAM_BASE + CRMU_SRAM_SIZE + \ + CRMU_RESERVED_SPACE) + +#define CRMU_SHARED_SRAM_BASE CRMU_SRAM_BASE +#define CRMU_SHARED_SRAM_SIZE 0x200 +#define CRMU_CFG_BASE (CRMU_SHARED_SRAM_BASE + \ + CRMU_SHARED_SRAM_SIZE) + +#define CRMU_PWR_GOOD_STATUS CRMU_CORE_BASE +#define CRMU_PWR_GOOD_STATUS__BBL_POWER_GOOD 0 +#define CRMU_ISO_CELL_CONTROL (CRMU_CORE_BASE + 0x4) +#define CRMU_ISO_CELL_CONTROL__CRMU_ISO_PDBBL 16 +#define CRMU_ISO_CELL_CONTROL__CRMU_ISO_PDBBL_TAMPER 24 +#define CRMU_SPRU_SOURCE_SEL_STAT (CRMU_CORE_BASE + 0xc) +#define CRMU_SPRU_SOURCE_SEL_STAT__SPRU_SOURCE_SELECT 0 +#define BSTI_BASE (CRMU_CORE_BASE + 0x28) +#define BSTI_CONTROL_OFFSET BSTI_BASE +#define BSTI_COMMAND_OFFSET (BSTI_BASE + 0x4) + +#define OCOTP_REGS_BASE (CRMU_CORE_BASE + 0x400) + +#define CRMU_TCI_BASE (CRMU_CORE_BASE + 0x800) +#define CRMU_SWREG_STATUS_ADDR (CRMU_TCI_BASE + 0x0c) +#define CRMU_CHIP_OTPC_STATUS (CRMU_TCI_BASE + 0x10) +#define CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE 19 +#define CRMU_BISR_PDG_MASK (CRMU_TCI_BASE + 0x4c) +#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST0 2 +#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST1 3 +#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST2 4 +#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST3 0 +#define CRMU_POWER_POLL (CRMU_TCI_BASE + 0x60) +#define CRMU_OTP_STATUS CRMU_POWER_POLL +#define CRMU_OTP_STATUS_BIT 1 +#define CRMU_DDR_PHY_AON_CTRL (CRMU_TCI_BASE + 0x64) +#define CRMU_DDRPHY2_HW_RESETN_R BIT(21) +#define CRMU_DDRPHY2_PWROKIN_PHY_R BIT(20) +#define CRMU_DDRPHY2_PWRONIN_PHY_R BIT(19) +#define CRMU_DDRPHY2_ISO_PHY_DFI_R BIT(18) +#define CRMU_DDRPHY2_ISO_PHY_REGS_R BIT(17) +#define CRMU_DDRPHY2_ISO_PHY_PLL_R BIT(16) +#define CRMU_DDRPHY1_HW_RESETN_R BIT(13) +#define CRMU_DDRPHY1_PWROKIN_PHY_R BIT(12) +#define CRMU_DDRPHY1_PWRONIN_PHY_R BIT(11) +#define CRMU_DDRPHY1_ISO_PHY_DFI_R BIT(10) +#define CRMU_DDRPHY1_ISO_PHY_REGS_R BIT(9) +#define CRMU_DDRPHY1_ISO_PHY_PLL_R BIT(8) +#define CRMU_DDRPHY0_HW_RESETN_R BIT(5) +#define CRMU_DDRPHY0_PWROKIN_PHY_R BIT(4) +#define CRMU_DDRPHY0_PWRONIN_PHY_R BIT(3) +#define CRMU_DDRPHY0_ISO_PHY_DFI_R BIT(2) +#define CRMU_DDRPHY0_ISO_PHY_REGS_R BIT(1) +#define CRMU_DDRPHY0_ISO_PHY_PLL_R BIT(0) +#define CRMU_EMEM_RESET_N_R BIT(16) +#define CRMU_EMEM_PRESET_N_R BIT(0) +#define CRMU_SWREG_CTRL_ADDR (CRMU_TCI_BASE + 0x6c) +#define CRMU_AON_CTRL1 (CRMU_TCI_BASE + 0x70) +#define CRMU_AON_CTRL1__LCPLL1_ISO_IN 18 +#define CRMU_AON_CTRL1__LCPLL1_PWRON_LDO 19 +#define CRMU_AON_CTRL1__LCPLL1_PWR_ON 20 +#define CRMU_AON_CTRL1__LCPLL0_ISO_IN 21 +#define CRMU_AON_CTRL1__LCPLL0_PWRON_LDO 22 +#define CRMU_AON_CTRL1__LCPLL0_PWR_ON 23 +#define CRMU_PCIE_LCPLL_PWR_ON_SHIFT 29 +#define CRMU_PCIE_LCPLL_PWR_ON_MASK BIT(CRMU_PCIE_LCPLL_PWR_ON_SHIFT) +#define CRMU_PCIE_LCPLL_PWRON_LDO_SHIFT 28 +#define CRMU_PCIE_LCPLL_PWRON_LDO_MASK BIT(CRMU_PCIE_LCPLL_PWRON_LDO_SHIFT) +#define CRMU_PCIE_LCPLL_ISO_IN_SHIFT 27 +#define CRMU_PCIE_LCPLL_ISO_IN_MASK BIT(CRMU_PCIE_LCPLL_ISO_IN_SHIFT) +#define CRMU_MASTER_AXI_ARUSER_CONFIG (CRMU_TCI_BASE + 0x74) +#define CRMU_MASTER_AXI_AWUSER_CONFIG (CRMU_TCI_BASE + 0x78) +#define CRMU_DDR_PHY_AON_CTRL_1 (CRMU_TCI_BASE + 0x8c) + +#define CDRU_BASE_ADDR (CRMU_CORE_BASE + 0x1000) +#define CDRU_MISC_RESET_CONTROL CDRU_BASE_ADDR +#define CDRU_MISC_RESET_CONTROL_TS_RESET_N 16 +#define CDRU_MISC_RESET_CONTROL__CDRU_USBSS_RESET_N 14 +#define CDRU_MISC_RESET_CONTROL__CDRU_SATA_RESET_N_R 15 +#define CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R 13 +#define CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R 3 +#define CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R 2 +#define CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R 1 + +#define CDRU_PROC_EVENT_CLEAR (CDRU_BASE_ADDR + 0x48) +#define CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2 0 +#define CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI 3 +#define CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2 5 +#define CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI 8 +#define CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2 10 +#define CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI 13 +#define CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2 15 +#define CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI 18 + +#define CDRU_CHIP_STRAP_CTRL (CDRU_BASE_ADDR + 0x50) +#define CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE 31 + +#define CDRU_CHIP_IO_PAD_CONTROL (CDRU_BASE_ADDR + 0x58) +#define CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PDN_R 8 +#define CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R 0 + +#define CDRU_CHIP_STRAP_DATA_LSW (CDRU_BASE_ADDR + 0x5c) +#define CDRU_CHIP_STRAP_DATA_LSW__BISR_BYPASS_MODE 18 +#define CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK BIT(8) +#define CDRU_CHIP_STRAP_DATA_LSW_PAD_USB_MODE BIT(26) + +#define CDRU_CHIP_STRAP_DATA (CDRU_BASE_ADDR + 0x5c) +#define CDRU_DDR0_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xb8) +#define CDRU_DDR1_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xbc) +#define CDRU_DDR2_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xc0) +#define CRMU_SW_POR_RESET_CTRL (CDRU_BASE_ADDR + 0x100) + +#define CDRU_GENPLL2_CONTROL1 (CDRU_BASE_ADDR + 0x1b0) +#define CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK BIT(11) +#define CDRU_GENPLL5_CONTROL1 (CDRU_BASE_ADDR + 0x24c) +#define CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK BIT(6) +#define CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK BIT(7) +#define CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK BIT(8) + +#define CDRU_NITRO_CONTROL (CDRU_BASE_ADDR + 0x2c4) +#define CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R 20 +#define CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R 16 + +#define CDRU_MISC_CLK_ENABLE_CONTROL (CDRU_BASE_ADDR + 0x2c8) +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM2_CLK_EN_R 11 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM1_CLK_EN_R 10 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM0_CLK_EN_R 9 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SATA_CLK_EN_R 8 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_USBSS_CLK_EN_R 7 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_MHB_CLK_EN_R 6 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_HSLS_CLK_EN_R 5 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SCR_CLK_EN_R 4 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_FS4_CLK_EN_R 3 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_PCIE_CLK_EN_R 2 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_PM_CLK_EN_R 1 +#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_NITRO_CLK_EN_R 0 + +#define CDRU_CCN_REGISTER_CONTROL_1 (CDRU_BASE_ADDR + 0x324) +#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM0_BIT 6 +#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM1_BIT 5 +#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM2_BIT 4 + +#define CDRU_CHIP_TOP_SPARE_REG0 (CDRU_BASE_ADDR + 0x378) +#define CDRU_CHIP_TOP_SPARE_REG1 (CDRU_BASE_ADDR + 0x37c) + +#define CENTRAL_TIMER_BASE (CRMU_CORE_BASE + 0x5000) +#define CENTRAL_TIMER_CTRL (CENTRAL_TIMER_BASE + 0x0) +#define CENTRAL_TIMER_GET_L (CENTRAL_TIMER_BASE + 0x4) +#define CENTRAL_TIMER_GET_L0 (CENTRAL_TIMER_BASE + 0x8) /* SCR STM */ +#define CENTRAL_TIMER_GET_L1 (CENTRAL_TIMER_BASE + 0xC) /* FS STM */ +#define CENTRAL_TIMER_GET_L2 (CENTRAL_TIMER_BASE + 0x10) /* iHost0 */ +#define CENTRAL_TIMER_GET_L3 (CENTRAL_TIMER_BASE + 0x14) /* iHost1 */ +#define CENTRAL_TIMER_GET_L4 (CENTRAL_TIMER_BASE + 0x18) /* iHost2 */ +#define CENTRAL_TIMER_GET_L5 (CENTRAL_TIMER_BASE + 0x1C) /* iHost3 */ +#define CENTRAL_TIMER_GET_H (CENTRAL_TIMER_BASE + 0x28) +#define CENTRAL_TIMER_SAT_TMR_ENA (CENTRAL_TIMER_BASE + 0x34) +#define CENTRAL_TIMER_GET_IHOST_ENA_BASE (CENTRAL_TIMER_GET_L2) + +#define CRMU_WDT_REGS_BASE (CRMU_CORE_BASE + 0x6000) + +#define CRMU_MAIL_BOX0 (CRMU_CORE_BASE + 0x8024) +#define CRMU_MAIL_BOX1 (CRMU_CORE_BASE + 0x8028) +#define CRMU_READ_MAIL_BOX0 (CRMU_CORE_BASE + 0x802c) +#define CRMU_READ_MAIL_BOX1 (CRMU_CORE_BASE + 0x8030) +#define AP_TO_SCP_MAILBOX1 CRMU_MAIL_BOX1 +#define SCP_TO_AP_MAILBOX1 CRMU_READ_MAIL_BOX1 +#define CRMU_IHOST_POWER_CONFIG (CRMU_CORE_BASE + 0x8038) +#define CRMU_RESET_EVENT_LOG (CRMU_CORE_BASE + 0x8064) +#define CRMU_SOFT_RESET_CTRL (CRMU_CORE_BASE + 0x8090) +#define CRMU_SOFT_RESET_CTRL__SOFT_PWR_UP_RST 0 +#define CRMU_SOFT_RESET_CTRL__SOFT_SYS_RST 1 +#define CRMU_SPARE_REG_0 (CRMU_CORE_BASE + 0x80b8) +#define CRMU_SPARE_REG_1 (CRMU_CORE_BASE + 0x80bc) +#define CRMU_SPARE_REG_2 (CRMU_CORE_BASE + 0x80c0) +#define CRMU_SPARE_REG_3 (CRMU_CORE_BASE + 0x80c4) +#define CRMU_SPARE_REG_4 (CRMU_CORE_BASE + 0x80c8) +#define CRMU_SPARE_REG_5 (CRMU_CORE_BASE + 0x80cc) +#define CRMU_CORE_ADDR_RANGE0_LOW (CRMU_CORE_BASE + 0x8c30) +#define CRMU_CORE_ADDR_RANGE1_LOW (CRMU_CORE_BASE + 0x8c38) +#define CRMU_CORE_ADDR_RANGE2_LOW (CRMU_CORE_BASE + 0x8c40) +#define CRMU_IHOST_SW_PERSISTENT_REG0 (CRMU_CORE_BASE + 0x8c54) +#define CRMU_IHOST_SW_PERSISTENT_REG1 (CRMU_CORE_BASE + 0x8c58) +#define CRMU_IHOST_SW_PERSISTENT_REG2 (CRMU_CORE_BASE + 0x8c5c) +#define CRMU_IHOST_SW_PERSISTENT_REG3 (CRMU_CORE_BASE + 0x8c60) +#define CRMU_IHOST_SW_PERSISTENT_REG4 (CRMU_CORE_BASE + 0x8c64) +#define CRMU_IHOST_SW_PERSISTENT_REG5 (CRMU_CORE_BASE + 0x8c68) +#define CRMU_IHOST_SW_PERSISTENT_REG6 (CRMU_CORE_BASE + 0x8c6c) +#define CRMU_IHOST_SW_PERSISTENT_REG7 (CRMU_CORE_BASE + 0x8c70) +#define CRMU_BBL_AUTH_CHECK (CRMU_CORE_BASE + 0x8c78) +#define CRMU_SOTP_NEUTRALIZE_ENABLE (CRMU_CORE_BASE + 0x8c84) +#define CRMU_IHOST_SW_PERSISTENT_REG8 (CRMU_CORE_BASE + 0x8c88) +#define CRMU_IHOST_SW_PERSISTENT_REG9 (CRMU_CORE_BASE + 0x8c8c) +#define CRMU_IHOST_SW_PERSISTENT_REG10 (CRMU_CORE_BASE + 0x8c90) +#define CRMU_IHOST_SW_PERSISTENT_REG11 (CRMU_CORE_BASE + 0x8c94) + +#define CNT_CONTROL_BASE (CRMU_CORE_BASE + 0x9000) +#define CNTCR (CNT_CONTROL_BASE) +#define CNTCR__EN BIT(0) + +#define SPRU_BBL_WDATA (CRMU_CORE_BASE + 0xa000) +#define SPRU_BBL_CMD (CRMU_CORE_BASE + 0xa004) +#define SPRU_BBL_CMD__IND_SOFT_RST_N 10 +#define SPRU_BBL_CMD__IND_WR 11 +#define SPRU_BBL_CMD__BBL_ADDR_R 0 +#define SPRU_BBL_CMD__IND_RD 12 +#define SPRU_BBL_CMD__BBL_ADDR_R 0 +#define SPRU_BBL_STATUS (CRMU_CORE_BASE + 0xa008) +#define SPRU_BBL_STATUS__ACC_DONE 0 +#define SPRU_BBL_RDATA (CRMU_CORE_BASE + 0xa00c) + +#endif /* CRMU_DEF_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h new file mode 100644 index 0000000..0c135b1 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DDR_INIT_H +#define DDR_INIT_H + +#include + +#pragma weak ddr_initialize +#pragma weak ddr_secure_region_config +#pragma weak ddr_info_save +#pragma weak get_active_ddr_channel +#pragma weak is_warmboot + +void ddr_initialize(struct ddr_info *ddr) +{ +} + +void ddr_secure_region_config(uint64_t start, uint64_t end) +{ +} + +void ddr_info_save(void) +{ +} + +unsigned char get_active_ddr_channel(void) +{ + return 0; +} + +static inline unsigned int is_warmboot(void) +{ + return 0; +} +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h new file mode 100644 index 0000000..c52ff0a --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FSX_H +#define FSX_H + +#include + +typedef enum FSX_TYPE { + eFS4_RAID, + eFS4_CRYPTO, + eFS6_PKI, +} eFSX_TYPE; + +void fsx_init(eFSX_TYPE fsx_type, + unsigned int ring_count, + unsigned int dme_count, + unsigned int ae_count, + unsigned int start_stream_id, + unsigned int msi_dev_id, + uintptr_t idm_io_control_direct, + uintptr_t idm_reset_control, + uintptr_t base, + uintptr_t dme_base); + +void fsx_meminit(const char *name, + uintptr_t idm_io_control_direct, + uintptr_t idm_io_status); + +void fs4_disable_clocks(bool disable_sram, + bool disable_crypto, + bool disable_raid); + +#endif /* FSX_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h new file mode 100644 index 0000000..83493ab --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IHOST_PM +#define IHOST_PM + +#include + +#define CLUSTER_POWER_ON 0x1 +#define CLUSTER_POWER_OFF 0x0 + +void ihost_power_on_cluster(u_register_t mpidr); +void ihost_power_on_secondary_core(u_register_t mpidr, uint64_t rvbar); +void ihost_enable_satellite_timer(unsigned int cluster_id); + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h new file mode 100644 index 0000000..e7b2985 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IOMMU_H +#define IOMMU_H + +enum iommu_domain { + PCIE_PAXC, + DOMAIN_CRMU, +}; + +void arm_smmu_create_identity_map(enum iommu_domain dom); +void arm_smmu_reserve_secure_cntxt(void); +void arm_smmu_enable_secure_client_port(void); + +#endif /* IOMMU_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h new file mode 100644 index 0000000..04dd640 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NCSI_H +#define NCSI_H + +/* + * There are 10 registers for NCSI IO drivers. + */ +#define NITRO_NCSI_IOPAD_CONTROL_NUM 10 +#define NITRO_NCSI_IOPAD_CONTROL_BASE 0x60e05080 + +/* + * NCSI IO Drive strength + * 000 - Drives 2mA + * 001 - Drives 4mA + * 010 - Drives 6mA + * 011 - Drives 8mA + * 100 - Drives 10mA + * 101 - Drives 12mA + * 110 - Drives 14mA + * 111 - Drives 16mA + */ +#define PAD_SELX_VALUE(selx) ((selx) << 1) +#define PAD_SELX_MASK (0x7 << 1) + +void brcm_stingray_ncsi_init(void); + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h new file mode 100644 index 0000000..c64c8a6 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PAXB_H +#define PAXB_H + +/* total number of PCIe cores */ +#define NUM_OF_SR_PCIE_CORES 8 +#define NUM_OF_NS3Z_PCIE_CORES 1 + +/* + * List of PCIe core and PAXB wrapper memory power registers + */ +#define PCIE_CORE_BASE 0x40000800 +#define PCIE_CORE_SOFT_RST_CFG_BASE (PCIE_CORE_BASE + 0x40) +#define PCIE_CORE_SOFT_RST 0x1 +#define PCIE_CORE_ISO_CFG_BASE (PCIE_CORE_BASE + 0x54) +#define PCIE_CORE_MEM_ISO 0x2 +#define PCIE_CORE_ISO 0x1 + +#define PCIE_CORE_MEM_PWR_BASE (PCIE_CORE_BASE + 0x58) +#define PCIE_PAXB_MEM_PWR_BASE (PCIE_CORE_BASE + 0x5c) +#define PCIE_CORE_PMI_CFG_BASE (PCIE_CORE_BASE + 0x64) +#define PCIE_CORE_RESERVED_CFG (PCIE_CORE_BASE + 0x6c) +#define PCIE_CORE_MEM_PWR_STATUS_BASE (PCIE_CORE_BASE + 0x74) +#define PCIE_PAXB_MEM_PWR_STATUS_BASE (PCIE_CORE_BASE + 0x78) +#define PCIE_CORE_PWR_OFFSET 0x100 + +#define SR_A0_DEVICE_ID 0xd713 +#define SR_B0_DEVICE_ID 0xd714 +/* TODO: Modify device ID once available */ +#define NS3Z_DEVICE_ID 0xd715 + +/* FIXME: change link speed to GEN3 when it's ready */ +#define GEN1_LINK_SPEED 1 +#define GEN2_LINK_SPEED 2 +#define GEN3_LINK_SPEED 3 + +typedef struct { + uint32_t type; + uint32_t device_id; + uint32_t pipemux_idx; + uint32_t num_cores; + int (*pipemux_init)(void); + int (*phy_init)(void); + int (*core_needs_enable)(unsigned int core_idx); + unsigned int (*get_link_width)(unsigned int core_idx); + unsigned int (*get_link_speed)(void); +} paxb_cfg; + +enum paxb_type { + PAXB_SR, + PAXB_NS3Z, +}; + +extern const paxb_cfg *paxb; + +#ifdef USE_PAXB +void paxb_init(void); +void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where, + uint32_t val); +unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where); +int pcie_core_needs_enable(unsigned int core_idx); +const paxb_cfg *paxb_get_sr_config(void); +#else +static inline void paxb_init(void) +{ +} +#endif + +#endif /* PAXB_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h new file mode 100644 index 0000000..ae1af2e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PAXC_H +#define PAXC_H + +#ifdef USE_PAXC +void paxc_init(void); +void paxc_mhb_ns_init(void); +#else +static inline void paxc_init(void) +{ +} + +static inline void paxc_mhb_ns_init(void) +{ +} +#endif + +#endif /* PAXC_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S b/arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S new file mode 100644 index 0000000..dccd54a --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant registers whenever an + * unhandled exception is taken in BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + nop +.endm + +/* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31. + * --------------------------------------------- + */ +.macro plat_print_gic_regs + nop + /*TBD-STINGRAY*/ +.endm + +/* ------------------------------------------------ + * The below required platform porting macro prints + * out relevant interconnect registers whenever an + * unhandled exception is taken in BL3-1. + * ------------------------------------------------ + */ +.macro plat_print_interconnect_regs + nop + /*TBD-STINGRAY*/ +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h new file mode 100644 index 0000000..4742124 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#include +#include "sr_def.h" +#include + +/* + * Most platform porting definitions provided by included headers + */ +#define PLAT_BRCM_SCP_TZC_DRAM1_SIZE ULL(0x0) + +/* + * Required by standard platform porting definitions + */ +#define PLATFORM_CLUSTER0_CORE_COUNT 2 +#define PLATFORM_CLUSTER1_CORE_COUNT 2 +#define PLATFORM_CLUSTER2_CORE_COUNT 2 +#define PLATFORM_CLUSTER3_CORE_COUNT 2 + +#define BRCM_SYSTEM_COUNT 1 +#define BRCM_CLUSTER_COUNT 4 + +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ + PLATFORM_CLUSTER1_CORE_COUNT+ \ + PLATFORM_CLUSTER2_CORE_COUNT+ \ + PLATFORM_CLUSTER3_CORE_COUNT) + +#define PLAT_NUM_PWR_DOMAINS (BRCM_SYSTEM_COUNT + \ + BRCM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* TBD-STINGRAY */ +#define CACHE_WRITEBACK_SHIFT 6 +/* + * 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 (1 << CACHE_WRITEBACK_SHIFT) + +/* TBD-STINGRAY */ +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL1 + +#define BL1_PLATFORM_STACK_SIZE 0x3300 +#define BL2_PLATFORM_STACK_SIZE 0xc000 +#define BL11_PLATFORM_STACK_SIZE 0x2b00 +#define DEFAULT_PLATFORM_STACK_SIZE 0x400 +#if IMAGE_BL1 +# define PLATFORM_STACK_SIZE BL1_PLATFORM_STACK_SIZE +#else +#if IMAGE_BL2 +#ifdef USE_BL1_RW +# define PLATFORM_STACK_SIZE BL2_PLATFORM_STACK_SIZE +#else +# define PLATFORM_STACK_SIZE BL1_PLATFORM_STACK_SIZE +#endif +#else +#if IMAGE_BL11 +# define PLATFORM_STACK_SIZE BL11_PLATFORM_STACK_SIZE +#else +# define PLATFORM_STACK_SIZE DEFAULT_PLATFORM_STACK_SIZE +#endif +#endif +#endif + +#define PLAT_BRCM_TRUSTED_SRAM_BASE 0x66D00000 +#define PLAT_BRCM_TRUSTED_SRAM_SIZE 0x00040000 + +#ifdef RUN_BL1_FROM_QSPI /* BL1 XIP from QSPI */ +# define PLAT_BRCM_TRUSTED_ROM_BASE QSPI_BASE_ADDR +#elif RUN_BL1_FROM_NAND /* BL1 XIP from NAND */ +# define PLAT_BRCM_TRUSTED_ROM_BASE NAND_BASE_ADDR +#else /* BL1 executed in ROM */ +# define PLAT_BRCM_TRUSTED_ROM_BASE ROM_BASE_ADDR +#endif +#define PLAT_BRCM_TRUSTED_ROM_SIZE 0x00040000 + +/******************************************************************************* + * BL1 specific defines. + ******************************************************************************/ +#define BL1_RO_BASE PLAT_BRCM_TRUSTED_ROM_BASE +#define BL1_RO_LIMIT (PLAT_BRCM_TRUSTED_ROM_BASE \ + + PLAT_BRCM_TRUSTED_ROM_SIZE) + +/* + * Put BL1 RW at the beginning of the Trusted SRAM. + */ +#define BL1_RW_BASE (BRCM_BL_RAM_BASE) +#define BL1_RW_LIMIT (BL1_RW_BASE + 0x12000) + +#define BL11_RW_BASE BL1_RW_LIMIT +#define BL11_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \ + PLAT_BRCM_TRUSTED_SRAM_SIZE) + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ +#if RUN_BL2_FROM_QSPI /* BL2 XIP from QSPI */ +#define BL2_BASE QSPI_BASE_ADDR +#define BL2_LIMIT (BL2_BASE + 0x40000) +#define BL2_RW_BASE BL1_RW_LIMIT +#define BL2_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \ + PLAT_BRCM_TRUSTED_SRAM_SIZE) +#elif RUN_BL2_FROM_NAND /* BL2 XIP from NAND */ +#define BL2_BASE NAND_BASE_ADDR +#define BL2_LIMIT (BL2_BASE + 0x40000) +#define BL2_RW_BASE BL1_RW_LIMIT +#define BL2_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \ + PLAT_BRCM_TRUSTED_SRAM_SIZE) +#else +#define BL2_BASE (BL1_RW_LIMIT + PAGE_SIZE) +#define BL2_LIMIT (BRCM_BL_RAM_BASE + BRCM_BL_RAM_SIZE) +#endif + +/* + * BL1 persistent area in internal SRAM + * This area will increase as more features gets into BL1 + */ +#define BL1_PERSISTENT_DATA_SIZE 0x2000 + +/* To reduce BL2 runtime footprint, we can re-use some BL1_RW area */ +#define BL1_RW_RECLAIM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE + \ + BL1_PERSISTENT_DATA_SIZE) + +/******************************************************************************* + * BL3-1 specific defines. + ******************************************************************************/ +/* Max Size of BL31 (in DRAM) */ +#define PLAT_BRCM_MAX_BL31_SIZE 0x30000 + +#ifdef USE_DDR +#define BL31_BASE BRCM_AP_TZC_DRAM1_BASE + +#define BL31_LIMIT (BRCM_AP_TZC_DRAM1_BASE + \ + PLAT_BRCM_MAX_BL31_SIZE) +#else +/* Put BL3-1 at the end of external on-board SRAM connected as NOR flash */ +#define BL31_BASE (NOR_BASE_ADDR + NOR_SIZE - \ + PLAT_BRCM_MAX_BL31_SIZE) + +#define BL31_LIMIT (NOR_BASE_ADDR + NOR_SIZE) +#endif + +#define SECURE_DDR_END_ADDRESS BL31_LIMIT + +#ifdef NEED_SCP_BL2 +#define SCP_BL2_BASE BL31_BASE +#define PLAT_MAX_SCP_BL2_SIZE 0x9000 +#define PLAT_SCP_COM_SHARED_MEM_BASE (CRMU_SHARED_SRAM_BASE) +/* dummy defined */ +#define PLAT_BRCM_MHU_BASE 0x0 +#endif + +#define SECONDARY_CPU_SPIN_BASE_ADDR BRCM_SHARED_RAM_BASE + +/* Generic system timer counter frequency */ +#ifndef SYSCNT_FREQ +#define SYSCNT_FREQ (125 * 1000 * 1000) +#endif + +/* + * Enable the BL32 definitions, only when optee os is selected as secure + * payload (BL32). + */ +#ifdef SPD_opteed +/* + * Reserved Memory Map : SHMEM & TZDRAM. + * + * +--------+----------+ 0x8D000000 + * | SHMEM (NS) | 16MB + * +-------------------+ 0x8E000000 + * | | TEE_RAM(S)| 4MB + * + TZDRAM +----------+ 0x8E400000 + * | | TA_RAM(S) | 12MB + * +-------------------+ 0x8F000000 + * | BL31 Binary (S) | 192KB + * +-------------------+ 0x8F030000 + */ + +#define BL32_VA_SIZE (4 * 1024 * 1024) +#define BL32_BASE (0x8E000000) +#define BL32_LIMIT (BL32_BASE + BL32_VA_SIZE) +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE BL32_VA_SIZE +#endif + +#ifdef SPD_opteed + #define SECURE_DDR_BASE_ADDRESS BL32_BASE +#else + #define SECURE_DDR_BASE_ADDRESS BL31_BASE +#endif +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ + +#define MAX_XLAT_TABLES 7 + +#define PLAT_BRCM_MMAP_ENTRIES 10 + +#define MAX_MMAP_REGIONS (PLAT_BRCM_MMAP_ENTRIES + \ + BRCM_BL_REGIONS) + +#ifdef USE_DDR +#ifdef BL33_OVERRIDE_LOAD_ADDR +#define PLAT_BRCM_NS_IMAGE_OFFSET BL33_OVERRIDE_LOAD_ADDR +#else +/* + * BL3-3 image starting offset. + * Putting start of DRAM as of now. + */ +#define PLAT_BRCM_NS_IMAGE_OFFSET 0x80000000 +#endif /* BL33_OVERRIDE_LOAD_ADDR */ +#else +/* + * BL3-3 image starting offset. + * Putting start of external on-board SRAM as of now. + */ +#define PLAT_BRCM_NS_IMAGE_OFFSET NOR_BASE_ADDR +#endif /* USE_DDR */ +/****************************************************************************** + * Required platform porting definitions common to all BRCM platforms + *****************************************************************************/ + +#define MAX_IO_DEVICES 5 +#define MAX_IO_HANDLES 6 + +#define PRIMARY_CPU 0 + +/* GIC Parameter */ +#define PLAT_BRCM_GICD_BASE GIC500_BASE +#define PLAT_BRCM_GICR_BASE (GIC500_BASE + 0x200000) + +/* Define secure interrupt as per Group here */ +#define PLAT_BRCM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(BRCM_IRQ_SEC_SPI_0, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define PLAT_BRCM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \ + GIC_INTR_CFG_EDGE), \ + +/* + *CCN 502 related constants. + */ +#define PLAT_BRCM_CLUSTER_COUNT 4 /* Number of RN-F Masters */ +#define PLAT_BRCM_CLUSTER_TO_CCN_ID_MAP CLUSTER0_NODE_ID, CLUSTER1_NODE_ID, CLUSTER2_NODE_ID, CLUSTER3_NODE_ID +#define CCN_SIZE 0x1000000 +#define CLUSTER0_NODE_ID 1 +#define CLUSTER1_NODE_ID 7 +#define CLUSTER2_NODE_ID 9 +#define CLUSTER3_NODE_ID 15 + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h new file mode 100644 index 0000000..0389f38 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_SOTP_H +#define PLATFORM_SOTP_H + +#define SOTP_DEVICE_SECURE_CFG0_ROW 17 +#define SOTP_DEVICE_SECURE_CFG1_ROW 18 +#define SOTP_DEVICE_SECURE_CFG2_ROW 19 +#define SOTP_DEVICE_SECURE_CFG3_ROW 20 +#define SOTP_BRCM_SOFTWARE_CFG0_ROW 21 +#define SOTP_BRCM_SOFTWARE_CFG1_ROW 22 +#define SOTP_BRCM_SOFTWARE_CFG2_ROW 23 +#define SOTP_BRCM_SOFTWARE_CFG3_ROW 24 +#define SOTP_CUSTOMER_ID_CFG0_ROW 25 +#define SOTP_CUSTOMER_ID_CFG1_ROW 26 +#define SOTP_CUSTOMER_ID_CFG2_ROW 27 +#define SOTP_CUSTOMER_ID_CFG3_ROW 28 +#define SOTP_CUSTOMER_DEV_CFG0_ROW 29 +#define SOTP_CUSTOMER_DEV_CFG1_ROW 30 +#define SOTP_CUSTOMER_DEV_CFG2_ROW 31 +#define SOTP_CUSTOMER_DEV_CFG3_ROW 32 +#define SOTP_DAUTH_ROW 33 +#define SOTP_K_HMAC_ROW 45 +#define SOTP_K_AES_ROW 57 +#define SOTP_NVCOUNTER_ROW 69 + +#define SOTP_BRCM_CFG_ECC_ERROR_MASK 0x100000 +#define SOTP_DAUTH_ECC_ERROR_MASK 0x800000 +#define SOTP_K_HMAC_ECC_ERROR_MASK 0x1000000 +#define SOTP_K_AES_ECC_ERROR_MASK 0x2000000 + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h new file mode 100644 index 0000000..5b5309f --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_USB_H +#define PLATFORM_USB_H + +#include + +#define USB3_DRD BIT(0U) +#define USB3H_USB2DRD BIT(1U) + +extern const unsigned int xhc_portsc_reg_offset[MAX_USB_PORTS]; + +void xhci_phy_init(void); + +#endif /* PLATFORM_USB_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h new file mode 100644 index 0000000..806ef56 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCP_CMD_H +#define SCP_SMD_H + +#include + +typedef struct { + int cmd; + int completed; + int ret; +} crmu_response_t; + + +#define SCP_CMD_MASK 0xffff +#define SCP_CMD_DEFAULT_TIMEOUT_US 1000 +#define SCP_CMD_SCP_BOOT_TIMEOUT_US 5000 + +int scp_send_cmd(uint32_t cmd, uint32_t param, uint32_t timeout); + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h new file mode 100644 index 0000000..c39b18c --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCP_UTILS_H +#define SCP_UTILS_H + +#include +#include + +#include + +int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info); + +bool is_crmu_alive(void); +bool bcm_scp_issue_sys_reset(void); + +#define SCP_READ_CFG(cfg) mmio_read_32(CRMU_CFG_BASE + \ + offsetof(M0CFG, cfg)) +#define SCP_WRITE_CFG(cfg, value) mmio_write_32(CRMU_CFG_BASE + \ + offsetof(M0CFG, cfg), value) + +#define SCP_READ_CFG16(cfg) mmio_read_16(CRMU_CFG_BASE + \ + offsetof(M0CFG, cfg)) +#define SCP_WRITE_CFG16(cfg, value) mmio_write_16(CRMU_CFG_BASE + \ + offsetof(M0CFG, cfg), value) + +#define SCP_READ_CFG8(cfg) mmio_read_8(CRMU_CFG_BASE + \ + offsetof(M0CFG, cfg)) +#define SCP_WRITE_CFG8(cfg, value) mmio_write_8(CRMU_CFG_BASE + \ + offsetof(M0CFG, cfg), value) +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h new file mode 100644 index 0000000..e08904e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDIO_H +#define SDIO_H + +#include + +#define SR_IPROC_SDIO0_CFG_BASE 0x689006e4 +#define SR_IPROC_SDIO0_SID_BASE 0x68900b00 +#define SR_IPROC_SDIO0_PAD_BASE 0x68a4017c +#define SR_IPROC_SDIO0_IOCTRL_BASE 0x68e02408 + +#define SR_IPROC_SDIO1_CFG_BASE 0x68900734 +#define SR_IPROC_SDIO1_SID_BASE 0x68900b08 +#define SR_IPROC_SDIO1_PAD_BASE 0x68a401b4 +#define SR_IPROC_SDIO1_IOCTRL_BASE 0x68e03408 + +#define NS3Z_IPROC_SDIO0_CFG_BASE 0x68a20540 +#define NS3Z_IPROC_SDIO0_SID_BASE 0x68900b00 +#define NS3Z_IPROC_SDIO0_TP_OUT_SEL 0x68a20308 +#define NS3Z_IPROC_SDIO0_PAD_BASE 0x68a20500 +#define NS3Z_IPROC_SDIO0_IOCTRL_BASE 0x68e02408 + +#define PHY_BYPASS BIT(14) +#define LEGACY_EN BIT(31) +#define PHY_DISABLE (LEGACY_EN | PHY_BYPASS) + +#define NS3Z_IPROC_SDIO1_CFG_BASE 0x68a30540 +#define NS3Z_IPROC_SDIO1_SID_BASE 0x68900b08 +#define NS3Z_IPROC_SDIO1_PAD_BASE 0x68a30500 +#define NS3Z_IPROC_SDIO1_IOCTRL_BASE 0x68e03408 + +#define ICFG_SDIO_CAP0 0x10 +#define ICFG_SDIO_CAP1 0x14 +#define ICFG_SDIO_STRAPSTATUS_0 0x0 +#define ICFG_SDIO_STRAPSTATUS_1 0x4 +#define ICFG_SDIO_STRAPSTATUS_2 0x8 +#define ICFG_SDIO_STRAPSTATUS_3 0xc +#define ICFG_SDIO_STRAPSTATUS_4 0x18 + +#define ICFG_SDIO_SID_ARADDR 0x0 +#define ICFG_SDIO_SID_AWADDR 0x4 + +#define ICFG_SDIOx_CAP0__SLOT_TYPE_MASK 0x3 +#define ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT 27 +#define ICFG_SDIOx_CAP0__INT_MODE_SHIFT 26 +#define ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT 25 +#define ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT 24 +#define ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT 23 +#define ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT 22 +#define ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT 21 +#define ICFG_SDIOx_CAP0__SDMA_SHIFT 20 +#define ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT 19 +#define ICFG_SDIOx_CAP0__ADMA2_SHIFT 18 +#define ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT 17 +#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_MASK 0x3 +#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT 15 +#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_MASK 0xff +#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT 7 +#define ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT 6 +#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_MASK 0x3f +#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT 0 + +#define ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT 22 +#define ICFG_SDIOx_CAP1__SPI_MODE_SHIFT 21 +#define ICFG_SDIOx_CAP1__CLK_MULT_MASK 0xff +#define ICFG_SDIOx_CAP1__CLK_MULT_SHIFT 13 +#define ICFG_SDIOx_CAP1__RETUNING_MODE_MASK 0x3 +#define ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT 11 +#define ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT 10 +#define ICFG_SDIOx_CAP1__TIME_RETUNE_MASK 0xf +#define ICFG_SDIOx_CAP1__TIME_RETUNE_SHIFT 6 +#define ICFG_SDIOx_CAP1__DRIVER_D_SHIFT 5 +#define ICFG_SDIOx_CAP1__DRIVER_C_SHIFT 4 +#define ICFG_SDIOx_CAP1__DRIVER_A_SHIFT 3 +#define ICFG_SDIOx_CAP1__DDR50_SHIFT 2 +#define ICFG_SDIOx_CAP1__SDR104_SHIFT 1 +#define ICFG_SDIOx_CAP1__SDR50_SHIFT 0 + +#ifdef USE_DDR +#define SDIO_DMA 1 +#else +#define SDIO_DMA 0 +#endif + +#define SDIO0_CAP0_CFG \ + (0x1 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \ + | (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \ + | (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \ + | (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \ + | (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \ + | (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \ + | (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \ + | (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT) + +#define SDIO0_CAP1_CFG \ + (0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\ + | (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\ + | (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\ + | (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\ + | (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT) + +#define SDIO1_CAP0_CFG \ + (0x0 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \ + | (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \ + | (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \ + | (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \ + | (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \ + | (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \ + | (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \ + | (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \ + | (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT) + +#define SDIO1_CAP1_CFG \ + (0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\ + | (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\ + | (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\ + | (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\ + | (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\ + | (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT) + +#define PAD_SDIO_CLK 0x4 +#define PAD_SDIO_DATA0 0x8 +#define PAD_SDIO_DATA1 0xc +#define PAD_SDIO_DATA2 0x10 +#define PAD_SDIO_DATA3 0x14 +#define PAD_SDIO_DATA4 0x18 +#define PAD_SDIO_DATA5 0x1c +#define PAD_SDIO_DATA6 0x20 +#define PAD_SDIO_DATA7 0x24 +#define PAD_SDIO_CMD 0x28 + +/* 12mA Drive strength*/ +#define PAD_SDIO_SELX (0x5 << 1) +#define PAD_SDIO_SRC (1 << 0) +#define PAD_SDIO_MASK (0xF << 0) +#define PAD_SDIO_VALUE (PAD_SDIO_SELX | PAD_SDIO_SRC) + +/* + * SDIO_PRESETVAL0 + * + * Each 13 Bit filed consists: + * drivestrength - 12:11 + * clkgensel - b10 + * sdkclkfreqsel - 9:0 + * Field Bit(s) Description + * ============================================================ + * SDR25_PRESET 25:13 Preset Value for SDR25 + * SDR50_PRESET 12:0 Preset Value for SDR50 + */ +#define SDIO_PRESETVAL0 0x01005001 + +/* + * SDIO_PRESETVAL1 + * + * Each 13 Bit filed consists: + * drivestrength - 12:11 + * clkgensel - b10 + * sdkclkfreqsel - 9:0 + * Field Bit(s) Description + * ============================================================ + * SDR104_PRESET 25:13 Preset Value for SDR104 + * SDR12_PRESET 12:0 Preset Value for SDR12 + */ +#define SDIO_PRESETVAL1 0x03000004 + +/* + * SDIO_PRESETVAL2 + * + * Each 13 Bit filed consists: + * drivestrength - 12:11 + * clkgensel - b10 + * sdkclkfreqsel - 9:0 + * Field Bit(s) Description + * ============================================================ + * HIGH_SPEED_PRESET 25:13 Preset Value for High Speed + * INIT_PRESET 12:0 Preset Value for Initialization + */ +#define SDIO_PRESETVAL2 0x010040FA + +/* + * SDIO_PRESETVAL3 + * + * Each 13 Bit filed consists: + * drivestrength - 12:11 + * clkgensel - b10 + * sdkclkfreqsel - 9:0 + * Field Bit(s) Description + * ============================================================ + * DDR50_PRESET 25:13 Preset Value for DDR50 + * DEFAULT_PRESET 12:0 Preset Value for Default Speed + */ +#define SDIO_PRESETVAL3 0x01004004 + +/* + * SDIO_PRESETVAL4 + * + * Field Bit(s) Description + * ============================================================ + * FORCE_USE_IP_TUNE_CLK 30 Force use IP clock + * TUNING_COUNT 29:24 Tuning count + * OVERRIDE_1P8V 23:16 + * OVERRIDE_3P3V 15:8 + * OVERRIDE_3P0V 7:0 + */ +#define SDIO_PRESETVAL4 0x20010101 + +#define SDIO_SID_SHIFT 5 + +typedef struct { + uintptr_t cfg_base; + uintptr_t sid_base; + uintptr_t io_ctrl_base; + uintptr_t pad_base; +} SDIO_CFG; + +void brcm_stingray_sdio_init(void); + +#endif /* SDIO_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h new file mode 100644 index 0000000..277836e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h @@ -0,0 +1,624 @@ +/* + * Copyright (c) 2016-2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SR_DEF_H +#define SR_DEF_H + +#ifndef __ASSEMBLER__ +#include +#endif + +#include +#include + +#include + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define BRCM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978) + +#define MHB_BASE_ADDR 0x60000000 +#define PLAT_BRCM_CCN_BASE 0x61000000 +#define CORESIGHT_BASE_ADDR 0x62000000 +#define SMMU_BASE 0x64000000 + +/* memory map entries*/ +/* Grouping block device for bigger MMU region */ +/* covers MHB, CNN, coresight, GIC, MMU, APB, CRMU */ +#define PERIPH0_BASE MHB_BASE_ADDR +#define PERIPH0_SIZE 0x06d00000 + +#define PERIPH1_BASE 0x66d80000 +#define PERIPH1_SIZE 0x00f80000 + +#define HSLS_BASE_ADDR 0x68900000 +#define HSLS_SIZE 0x04500000 + +#define GIC500_BASE 0x63c00000 +#define GIC500_SIZE 0x400000 + +/******************************************************************************* + * CCN related constants + ******************************************************************************/ +#define OLY_MN_REGISTERS_NODE0_SECURE_ACCESS (PLAT_BRCM_CCN_BASE + 0x0) + +#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x880500) + +/* Used for acceleration of coherent ordered writes */ +#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WUO BIT(4) +/* Wait for completion of requests at RN-I */ +#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WFC BIT(3) + +/* + * Forces all reads from the RN-I to be sent with the request order bit set + * and this ensures ordered allocation of read data buffers in the RN-I + */ +#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_RQO BIT(5) + +#define OLY_RNI3PDVM_REGISTERS_NODE14_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x8e0500) + +/* Wait for completion of requests at RN-I */ +#define OLY_RNI3PDVM_REGISTERS_NODE14_AUX_CTL_WFC BIT(3) + +#define OLY_HNI_REGISTERS_NODE0_POS_CONTROL (PLAT_BRCM_CCN_BASE + 0x80000) +#define POS_CONTROL_HNI_POS_EN BIT(0) + +#define OLY_HNI_REGISTERS_NODE0_PCIERC_RNI_NODEID_LIST \ + (PLAT_BRCM_CCN_BASE + 0x80008) +/* PAXB and PAXC connected to 8th Node */ +#define SR_RNI_PCIE_CONNECTED BIT(8) +/* PAXB connected to 6th Node */ +#define SRP_RNI_PCIE_CONNECTED BIT(6) + +#define OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x80500) +#define SA_AUX_CTL_POS_EARLY_WR_COMP_EN BIT(5) +#define SA_AUX_CTL_SER_DEVNE_WR BIT(9) + +/******************************************************************************* + * Coresight related constants + ******************************************************************************/ +#define CORESIGHT_BASE_ADDR 0x62000000 + +#define IHOST0_BASE 0x66000000 +#define IHOST_ADDR_SPACE 0x2000 + +/******************************************************************************* + * SCR related constants + ******************************************************************************/ +#define SCR_BASE 0x6600a000 +#define SCR_ARCACHE_OFFSET 4 +#define SCR_ARCACHE_MASK (0x3 << SCR_ARCACHE_OFFSET) +#define SCR_AWCACHE_OFFSET 6 +#define SCR_AWCACHE_MASK (0x3 << SCR_AWCACHE_OFFSET) +#define SCR_AXCACHE_CONFIG_MASK (SCR_ARCACHE_MASK | SCR_AWCACHE_MASK) +#define SCR_TBUX_AXCACHE_CONFIG ((0x1 << SCR_AWCACHE_OFFSET) | \ + (0x1 << SCR_ARCACHE_OFFSET)) + +#define SCR_REGS_SCR_SOFT_RESET (SCR_BASE + 0x1c) +#define SCR_REGS_GIC_SOFT_RESET BIT(0) + +#define SCR_GPV_BASE 0x66100000 +#define SCR_NOC_SECURITY0 (SCR_GPV_BASE + 0x08) +#define SCR_NOC_DDR_REGISTER_ACCESS (SCR_GPV_BASE + 0x30) + +/******************************************************************************* + * MEMC and DDR related constants + ******************************************************************************/ +#define DDR0_CONTROL_ROOT 0x66200000 +#define EMEM_SS_CFG_0_ROOT 0x66202000 +#define EMEM_SYS_IF_0_ROOT 0x66204000 +#define DDR_PHY0_ROOT 0x66240000 + +#define DDR1_CONTROL_ROOT 0x66280000 +#define EMEM_SS_CFG_1_ROOT 0x66282000 +#define EMEM_SYS_IF_1_ROOT 0x66284000 +#define DDR_PHY1_ROOT 0x662c0000 + +#define DDR2_CONTROL_ROOT 0x66300000 +#define EMEM_SS_CFG_2_ROOT 0x66302000 +#define EMEM_SYS_IF_2_ROOT 0x66304000 +#define DDR_PHY2_ROOT 0x66340000 + +/******************************************************************************* + * TZC400 related constants + ******************************************************************************/ +#define TZC_400_BASE 0x66d84000 + +/******************************************************************************* + * FS4 related constants + ******************************************************************************/ +#define FS4_SRAM_IDM_IO_CONTROL_DIRECT 0x66d8a408 + +#define FS4_CRYPTO_IDM_IO_CONTROL_DIRECT 0x66d8e408 +#define FS4_CRYPTO_IDM_RESET_CONTROL 0x66d8e800 +#define FS4_CRYPTO_BASE 0x67000000 +#define FS4_CRYPTO_DME_BASE (FS4_CRYPTO_BASE + 0x280000) + +#define FS4_RAID_IDM_IO_CONTROL_DIRECT 0x66d8f408 +#define FS4_RAID_IDM_IO_STATUS 0x66d8f500 +#define FS4_RAID_IDM_RESET_CONTROL 0x66d8f800 +#define FS4_RAID_BASE 0x67400000 +#define FS4_RAID_DME_BASE (FS4_RAID_BASE + 0x280000) + +#define FS4_CRYPTO_GPV_BASE 0x67300000 +#define FS4_RAID_GPV_BASE 0x67700000 + +#define FS6_PKI_BASE 0x67400000 +#define FS6_PKI_DME_BASE 0x66D90000 + +#define TZC400_FS_SRAM_ROOT 0x66d84000 +#define GATE_KEEPER_OFFSET 0x8 +#define REGION_ATTRIBUTES_0_OFFSET 0x110 +#define REGION_ID_ACCESS_0_OFFSET 0x114 + +#define NIC400_FS_NOC_ROOT 0x66e00000 +#define NIC400_FS_NOC_SECURITY2_OFFSET 0x10 +#define NIC400_FS_NOC_SECURITY4_OFFSET 0x18 +#define NIC400_FS_NOC_SECURITY7_OFFSET 0x24 + +/******************************************************************************* + * SATA PHY related constants + ******************************************************************************/ +#define SATA_BASE 0x67d00000 + +/******************************************************************************* + * USB related constants + ******************************************************************************/ +#define USB_BASE 0x68500000 +#define USB_SIZE 0x00400000 +#define XHC_BASE (USB_BASE + 0x11000) +#define MAX_USB_PORTS 3 + +/******************************************************************************* + * HSLS related constants + ******************************************************************************/ +#define IPROC_ROOT 0x68900000 +#define HSLS_ICFG_REGS_BASE IPROC_ROOT +#define HSLS_IDM_REGS_BASE 0x68e00000 +#define HSLS_MODE_SEL_CONTROL 0x68a40000 +#define HSLS_TZPC_BASE 0x68b40000 +#define HSLS_GPV_BASE 0x6cd00000 + +/******************************************************************************* + * Chip ID related constants + ******************************************************************************/ +#define ICFG_CHIP_ID HSLS_ICFG_REGS_BASE +#define CHIP_ID_SR 0xd730 +#define CHIP_ID_NS3Z 0xe56d +#define CHIP_ID_MASK 0xf000 +#define ICFG_CHIP_REVISION_ID (HSLS_ICFG_REGS_BASE + 0x4) +#define PLAT_CHIP_ID_GET (mmio_read_32(ICFG_CHIP_ID)) +#define PLAT_CHIP_REV_GET (mmio_read_32(ICFG_CHIP_REVISION_ID)) + +/******************************************************************************* + * CMIC MII (MDIO) related constant + ******************************************************************************/ +#define PLAT_CMIC_MIIM_BASE 0x68920000U + +/******************************************************************************* + * Timers related constants + ******************************************************************************/ +/* ChipcommonG_tim0_TIM_TIMER1Load 0x68930000 */ +#define SP804_TIMER0_BASE 0x68930000 +#define SP804_TIMER1_BASE 0x68940000 +#define SP804_TIMER0_TIMER_VAL_REG_OFFSET 0x4 +#define SP804_TIMER0_CLKMULT 2 +#define SP804_TIMER0_CLKDIV 25 + +/******************************************************************************* + * GPIO related constants + ******************************************************************************/ +#define IPROC_GPIO_NS_BASE 0x689d0000 +#define IPROC_GPIO_S_BASE 0x68b00000 +#define IPROC_GPIO_NR 151 +#define GPIO_S_CNTRL_REG 0x68b60000 + +/******************************************************************************* + * I2C SMBUS related constants + ******************************************************************************/ +#define SMBUS0_REGS_BASE 0x689b0000 +#define SMBUS1_REGS_BASE 0x689e0000 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define ChipcommonG_UART0_UART_RBR_THR_DLL 0x68a00000 +#define ChipcommonG_UART1_UART_RBR_THR_DLL 0x68a10000 +#define ChipcommonG_UART2_UART_RBR_THR_DLL 0x68a20000 +#define ChipcommonG_UART3_UART_RBR_THR_DLL 0x68a30000 + +#define UART0_BASE_ADDR ChipcommonG_UART0_UART_RBR_THR_DLL +#define UART1_BASE_ADDR ChipcommonG_UART1_UART_RBR_THR_DLL +#define UART2_BASE_ADDR ChipcommonG_UART2_UART_RBR_THR_DLL +#define UART3_BASE_ADDR ChipcommonG_UART3_UART_RBR_THR_DLL + +#define UART_SPR_OFFSET 0x1c /* Scratch Pad Register */ + +#define LOG_LEVEL_REGISTER CRMU_SPARE_REG_3 +#define GET_LOG_LEVEL() (mmio_read_32(LOG_LEVEL_REGISTER)) +#define SET_LOG_LEVEL(x) (mmio_write_32(LOG_LEVEL_REGISTER, x)) + +#define IO_RETRY_REGISTER CRMU_SPARE_REG_4 + +#define DWC_UART_REFCLK (25 * 1000 * 1000) +#define DWC_UART_REFCLK_DIV 16 +/* Baud rate in emulation will vary based on setting of 25MHz SCLK */ +#define DWC_UART_BAUDRATE 115200 + +#define BRCM_CRASH_CONSOLE_BASE UART1_BASE_ADDR +#define BRCM_CRASH_CONSOLE_REFCLK DWC_UART_REFCLK +#define BRCM_CRASH_CONSOLE_BAUDRATE DWC_UART_BAUDRATE + +#ifdef BOARD_CONSOLE_UART +#define PLAT_BRCM_BOOT_UART_BASE BOARD_CONSOLE_UART +#else +#define PLAT_BRCM_BOOT_UART_BASE UART1_BASE_ADDR +#endif +#define CONSOLE_UART_ID ((PLAT_BRCM_BOOT_UART_BASE >> 16) & 0x3) + +#define PLAT_BRCM_BOOT_UART_CLK_IN_HZ DWC_UART_REFCLK +#define BRCM_CONSOLE_BAUDRATE DWC_UART_BAUDRATE + +#define PLAT_BRCM_BL31_RUN_UART_BASE PLAT_BRCM_BOOT_UART_BASE +#define PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ PLAT_BRCM_BOOT_UART_CLK_IN_HZ + +/******************************************************************************* + * IOMUX related constants + ******************************************************************************/ +#define HSLS_IOPAD_BASE HSLS_MODE_SEL_CONTROL +#define MODE_SEL_CONTROL_FSEL_MASK 0x7 +#define MODE_SEL_CONTROL_FSEL_MODE0 0x0 +#define MODE_SEL_CONTROL_FSEL_MODE1 0x1 +#define MODE_SEL_CONTROL_FSEL_MODE2 0x2 +#define MODE_SEL_CONTROL_FSEL_MODE3 0x3 +#define MODE_SEL_CONTROL_FSEL_DEBUG 0x4 +#define IPROC_IOPAD_MODE_BASE (HSLS_MODE_SEL_CONTROL + 0x29c) +#define UART0_SIN_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x4a8) +#define UART0_SOUT_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x4ac) +#define UART1_SIN_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3b8) +#define UART1_SOUT_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3bc) +#define UARTx_SIN_MODE_SEL_CONTROL_FSEL 0 +#define UARTx_SOUT_MODE_SEL_CONTROL_FSEL 0 + +/******************************************************************************* + * PKA constants + ******************************************************************************/ +#define ICFG_PKA_MEM_PWR_CTRL (HSLS_ICFG_REGS_BASE + 0xac0) +#define ICFG_PKA_MEM_PWR_CTRL__POWERONIN BIT(0) +#define ICFG_PKA_MEM_PWR_CTRL__POWEROKIN BIT(1) +#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONIN BIT(2) +#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKIN BIT(3) +#define ICFG_PKA_MEM_PWR_CTRL__POWERONOUT BIT(4) +#define ICFG_PKA_MEM_PWR_CTRL__POWEROKOUT BIT(5) +#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONOUT BIT(6) +#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKOUT BIT(7) +#define ICFG_PKA_MEM_PWR_CTRL__ISO BIT(8) + +/******************************************************************************* + * RNG constants + ******************************************************************************/ +#define RNG_BASE_ADDR 0x68b20000 + +/******************************************************************************* + * Trusted Watchdog constants + ******************************************************************************/ +#define ARM_SP805_TWDG_BASE 0x68b30000 +#define ARM_SP805_TWDG_CLK_HZ ((25 * 1000 * 1000) / 2) +/* + * 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) + +/******************************************************************************* + * SOTP related constants + ******************************************************************************/ +#define SOTP_REGS_OTP_BASE 0x68b50000 +#define SOTP_CHIP_CTRL (SOTP_REGS_OTP_BASE + 0x4c) +#define SOTP_CLEAR_SYSCTRL_ALL_MASTER_NS 0 + +/******************************************************************************* + * DMAC/PL330 related constants + ******************************************************************************/ +#define DMAC_M0_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x408) +#define BOOT_MANAGER_NS BIT(25) +#define DMAC_M0_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0x800) +#define ICFG_DMAC_CONFIG_0 (HSLS_ICFG_REGS_BASE + 0x190) +#define ICFG_DMAC_CONFIG_1 (HSLS_ICFG_REGS_BASE + 0x194) +#define ICFG_DMAC_CONFIG_2 (HSLS_ICFG_REGS_BASE + 0x198) +#define BOOT_PERIPHERAL_NS 0xffffffff +#define ICFG_DMAC_CONFIG_3 (HSLS_ICFG_REGS_BASE + 0x19c) +#define BOOT_IRQ_NS 0x0000ffff +#define ICFG_DMAC_SID_ARADDR_CONTROL (HSLS_ICFG_REGS_BASE + 0xaf0) +#define ICFG_DMAC_SID_AWADDR_CONTROL (HSLS_ICFG_REGS_BASE + 0xaf4) +#define ICFG_DMAC_MEM_PWR_CTRL__POWERONIN BIT(0) +#define ICFG_DMAC_MEM_PWR_CTRL__POWEROKIN BIT(1) +#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONIN BIT(2) +#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKIN BIT(3) +#define ICFG_DMAC_MEM_PWR_CTRL__POWERONOUT BIT(4) +#define ICFG_DMAC_MEM_PWR_CTRL__POWEROKOUT BIT(5) +#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONOUT BIT(6) +#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKOUT BIT(7) +#define ICFG_DMAC_MEM_PWR_CTRL__ISO BIT(8) +#define ICFG_DMAC_MEM_PWR_CTRL (HSLS_ICFG_REGS_BASE + 0xadc) + +/******************************************************************************* + * PNOR related constants + ******************************************************************************/ +#define PNOR_ICFG_BASE (HSLS_ICFG_REGS_BASE + 0x780) +#define PNOR_ICFG_CS_0 PNOR_ICFG_BASE +#define PNOR_ICFG_CS_1 (PNOR_ICFG_BASE + 0x4) +#define PNOR_ICFG_CS_2 (PNOR_ICFG_BASE + 0x8) +#define PNOR_ICFG_CS_x_MASK0_MASK 0xff +#define PNOR_ICFG_CS_x_MASK0_SHIFT 8 +#define PNOR_ICFG_CS_x_MATCH0_MASK 0xff +#define PNOR_ICFG_CS_x_MATCH0_SHIFT 0 + +#define PNOR_IDM_BASE (HSLS_IDM_REGS_BASE + 0xb000) +#define PNOR_IDM_IO_CONTROL_DIRECT (PNOR_IDM_BASE + 0x408) +#define PNOR_IDM_IO_RESET_CONTROL (PNOR_IDM_BASE + 0x800) + +#define PNOR_REG_BASE 0x68c50000 +#define PNOR_REG_DIRECT_CMD (PNOR_REG_BASE + 0x010) +#define PNOR_REG_SET_CYCLES (PNOR_REG_BASE + 0x014) +#define PNOR_REG_SET_OPMODE (PNOR_REG_BASE + 0x018) +#define PNOR_REG_REFRESH_0 (PNOR_REG_BASE + 0x020) +#define PNOR_REG_PERIPH_ID0 (PNOR_REG_BASE + 0xfe0) +#define PNOR_REG_PERIPH_ID1 (PNOR_REG_BASE + 0xfe4) +#define PNOR_REG_PERIPH_ID2 (PNOR_REG_BASE + 0xfe8) +#define PNOR_REG_PERIPH_ID3 (PNOR_REG_BASE + 0xfec) +#define PNOR_REG_PERIPH_IDx_MASK 0xff + +/******************************************************************************* + * NAND related constants + ******************************************************************************/ +#define NAND_FLASH_REVISION 0x68c60000 +#define NAND_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0xa408) +#define NAND_IDM_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xa800) + +/******************************************************************************* + * eMMC related constants + ******************************************************************************/ +#define PLAT_SD_MAX_READ_LENGTH 0x400 + +#define SDIO0_EMMCSDXC_SYSADDR 0x68cf1000 +#define SDIO_IDM0_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x2408) +#define SDIO_IDM1_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x3408) +#define SDIO_IDM0_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0x2800) +#define ICFG_SDIO0_BASE (HSLS_ICFG_REGS_BASE + 0x6e4) +#define ICFG_SDIO1_BASE (HSLS_ICFG_REGS_BASE + 0x734) +#define ICFG_SDIO0_CAP0 (ICFG_SDIO0_BASE + 0x10) +#define ICFG_SDIO0_CAP1 (ICFG_SDIO0_BASE + 0x14) +#define ICFG_SDIO0_SID (HSLS_ICFG_REGS_BASE + 0xb00) +#define ICFG_SDIO1_SID (HSLS_ICFG_REGS_BASE + 0xb08) + +/******************************************************************************* + * Bootstrap related constants + ******************************************************************************/ +#define ROM_S0_IDM_IO_STATUS (HSLS_IDM_REGS_BASE + 0x9500) + +/******************************************************************************* + * ROM related constants + ******************************************************************************/ +#define ROM_BASE_ADDR 0x6ce00000 +#define ROM_VERSION_STRING_ADDR (ROM_BASE_ADDR + 0x28000) +#define ROM_BUILD_MESSAGE_ADDR (ROM_BASE_ADDR + 0x28018) + +/******************************************************************************* + * Boot source peripheral related constants + ******************************************************************************/ +#define QSPI_CTRL_BASE_ADDR 0x68c70000 +#define QSPI_BASE_ADDR 0x70000000 +#define QSPI_SIZE 0x08000000 +#define NOR_BASE_ADDR 0x74000000 +#define NOR_SIZE 0x04000000 +#define NAND_BASE_ADDR 0x78000000 +#define NAND_SIZE 0x08000000 + +#define QSPI_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xc800) + +#define APBR_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xe800) +#define APBS_IDM_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xf800) + +#define APBX_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x10408) +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_WDOG_SCLK_SEL 2 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM0_SCLK_SEL 4 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM1_SCLK_SEL 6 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM2_SCLK_SEL 8 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM3_SCLK_SEL 10 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM4_SCLK_SEL 12 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM5_SCLK_SEL 13 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM6_SCLK_SEL 14 +#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM7_SCLK_SEL 15 + +#define APBY_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x11408) +#define APBY_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0 +#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART0_SCLK_SEL 2 +#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART1_SCLK_SEL 4 +#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART2_SCLK_SEL 6 +#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART3_SCLK_SEL 8 + +#define APBZ_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x12408) +#define APBZ_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0 +#define APBZ_IDM_IDM_IO_CONTROL_DIRECT_WDOG_SCLK_SEL 2 + +/******************************************************************************* + * Stingray memory map related constants + ******************************************************************************/ + +/* The last 4KB of Trusted SRAM are used as shared memory */ +#define BRCM_SHARED_RAM_SIZE 0x0 +#define BRCM_SHARED_RAM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE + \ + PLAT_BRCM_TRUSTED_SRAM_SIZE - \ + BRCM_SHARED_RAM_SIZE) + +/* Reserve 4 KB to store error logs in BL2 */ +#define BCM_ELOG_BL2_SIZE 0x00001000 +#define BCM_ELOG_BL2_BASE BL1_RW_LIMIT + +/* The remaining Trusted SRAM is used to load the BL images */ +#define BRCM_BL_RAM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE) +#define BRCM_BL_RAM_SIZE (PLAT_BRCM_TRUSTED_SRAM_SIZE - \ + BRCM_SHARED_RAM_SIZE) + +/* DDR Address where TMON temperature values are written */ +#define TMON_SHARED_DDR_ADDRESS 0x8f100000 + +/* Reserve 4 kB to pass data to BL33 */ +#define BL33_SHARED_DDR_BASE 0x8f102000 +#define BL33_SHARED_DDR_SIZE 0x1000 + +/* Default AP error logging base addr */ +#ifndef ELOG_AP_UART_LOG_BASE +#define ELOG_AP_UART_LOG_BASE 0x8f110000 +#endif + +/* Reserve 16 to store error logs in BL31 */ +#define BCM_ELOG_BL31_BASE ELOG_AP_UART_LOG_BASE +#define BCM_ELOG_BL31_SIZE 0x4000 + +/******************************************************************************* + * Non-secure DDR Map + ******************************************************************************/ +#define BRCM_DRAM1_BASE ULL(0x80000000) +#define BRCM_DRAM1_SIZE ULL(0x10000000) +#define BRCM_DRAM2_BASE ULL(0x880000000) +#define BRCM_DRAM2_SIZE ULL(0x780000000) +#define BRCM_DRAM3_BASE ULL(0x8800000000) +#define BRCM_DRAM3_SIZE ULL(0x7800000000) +#define BRCM_SHARED_DRAM_BASE BL33_SHARED_DDR_BASE +#define BRCM_SHARED_DRAM_SIZE BL33_SHARED_DDR_SIZE +#define BRCM_EXT_SRAM_BASE ULL(0x74000000) +#define BRCM_EXT_SRAM_SIZE ULL(0x4000000) + +/* Priority levels for platforms */ +#define PLAT_RAS_PRI 0x10 +#define PLAT_SDEI_CRITICAL_PRI 0x60 +#define PLAT_SDEI_NORMAL_PRI 0x70 + +/* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 */ +#define BRCM_IRQ_SEC_SGI_0 14 +#define BRCM_IRQ_SEC_SGI_1 15 + +/* RTC periodic interrupt */ +#define BRCM_IRQ_SEC_SPI_0 49 + +/* + * Macros for local power states in SR platforms encoded by State-ID field + * within the power-state parameter. + */ + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN 0 + +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET 1 + +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF 2 + +/* + * 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 PLAT_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 PLAT_LOCAL_STATE_OFF + +/* ChiMP-related constants */ + +#define NITRO_TZPC_TZPCDECPROT0clr 0x60c01808 +#define NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R 1 + +#define NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT 0x60e00408 + +#define CHIMP_INDIRECT_ADDR_MASK 0x3fffff +#define CHIMP_INDIRECT_BASE 0x60800000 + +#define CHIMP_REG_ECO_RESERVED 0x3042400 + +#define CHIMP_FLASH_ACCESS_DONE_BIT 2 + +/* indicate FRU table programming is done successfully */ +#define CHIMP_FRU_PROG_DONE_BIT 9 + +#define CHIMP_REG_CTRL_BPE_MODE_REG 0x0 +#define CHIMP_REG_CTRL_BPE_STAT_REG 0x4 +#define CHIMP_REG_CTRL_FSTBOOT_PTR_REG 0x8 +#define CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_L 1 +#define CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R 1 +#define CHIMP_REG_CTRL_BASE 0x3040000 +#define CHIMP_FAST_BOOT_MODE_BIT 2 +#define CHIMP_REG_CHIMP_APE_SCPAD 0x3300000 +#define CHIMP_REG_CHIMP_SCPAD 0x3100000 + +/* Chimp health status offset in scratch pad ram */ +#define CHIMP_HEALTH_STATUS_OFFSET 0x8 +/* + * If not in NIC mode then FASTBOOT can be enabled. + * "Not in NIC mode" means that FORCE_FASTBOOT is set + * and a valid (1 or 2) fastboot type is specified. + * + * Three types of fastboot are supported: + * 0 = No fastboot. Boots Nitro/ChiMP and lets ROM loader + * initialize ChiMP from NVRAM (QSPI). + * + * 1 = Jump in place (need a flat image) + * This is intended to speedup Nitro FW boot on Palladium, + * can be used with a real chip as well. + * 2 = Jump normally with decompression + * Modus operandi for a real chip. Works also on Palladium + * Note: image decompressing takes time on Palladium. + * 3 = No fastboot support. No ChiMP bringup + * (use only for AP debug or for ChiMP's deferred setup). + */ +#define CHIMP_FASTBOOT_JUMP_DECOMPRESS 2 +#define CHIMP_FASTBOOT_JUMP_IN_PLACE 1 +#define CHIMP_FASTBOOT_NITRO_RESET 0 +/* + * Definitions for a non-Nitro access + * to QSPI PAD after the handshake + */ +#define QSPI_HOLD_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3e8) +#define QSPI_WP_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3ec) +#define QSPI_SCK_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f0) +#define QSPI_CS_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f4) +#define QSPI_MOSI_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f8) +#define QSPI_MISO_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3fc) + +/******************************************************************************* + * Stream IDs for different blocks of SR + * block_id for different blocks is as follows: + * PCIE : 0x0 + * PAXC : 0x1 + * FS4 : 0x2 + * Rest of the masters(includes MHB via RNI): 0x3 + ******************************************************************************/ +#define SR_SID_VAL(block_id, subblock_id, device_num) ((block_id << 13) | \ + (subblock_id << 11) | \ + (device_num)) + +#define CRMU_STREAM_ID SR_SID_VAL(0x3, 0x0, 0x7) +#define CRMU_SID_SHIFT 5 + +#define DMAC_STREAM_ID SR_SID_VAL(0x3, 0x0, 0x0) +#define DMAC_SID_SHIFT 5 + +/* DDR SHMOO Values defines */ +#define IDRAM_SHMOO_VALUES_ADDR CRMU_IDRAM_BASE_ADDR +#define DDR_SHMOO_VALUES_ADDR 0x8f103000 +#define SHMOO_SIZE_PER_CHANNEL 0x1000 + +#endif /* SR_DEF_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h new file mode 100644 index 0000000..b3fc735 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SR_UTILS_H +#define SR_UTILS_H + +#include + +#include +#include +#include + +static inline void brcm_stingray_set_qspi_mux(int enable_ap) +{ + mmio_write_32(QSPI_HOLD_N_MODE_SEL_CONTROL, enable_ap); + mmio_write_32(QSPI_WP_N_MODE_SEL_CONTROL, enable_ap); + mmio_write_32(QSPI_SCK_MODE_SEL_CONTROL, enable_ap); + mmio_write_32(QSPI_CS_N_MODE_SEL_CONTROL, enable_ap); + mmio_write_32(QSPI_MOSI_MODE_SEL_CONTROL, enable_ap); + mmio_write_32(QSPI_MISO_MODE_SEL_CONTROL, enable_ap); +} + +static inline void brcm_stingray_set_straps(uint32_t boot_source) +{ + /* Enable software strap override */ + mmio_setbits_32(CDRU_CHIP_STRAP_CTRL, + BIT(CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE)); + + /* set straps to the next boot source */ + mmio_clrsetbits_32(CDRU_CHIP_STRAP_DATA, + BOOT_SOURCE_MASK, + boot_source); + + /* Disable software strap override */ + mmio_clrbits_32(CDRU_CHIP_STRAP_CTRL, + BIT(CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE)); +} + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h new file mode 100644 index 0000000..6e971ce --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SWREG_H +#define SWREG_H + +/* default voltage if no valid OTP */ +#define VDDC_CORE_DEF_VOLT 910000 /* 0.91v */ +#define IHOST_DEF_VOLT 940000 /* 0.94v */ + +#define B0_VDDC_CORE_DEF_VOLT 950000 /* 0.95v */ +#define B0_IHOST_DEF_VOLT 950000 /* 0.95v */ +#define B0_DDR_VDDC_DEF_VOLT 1000000 /* 1v */ + +#define SWREG_IHOST1_DIS 4 +#define SWREG_IHOST1_REG_RESETB 5 +#define SWREG_IHOST1_PMU_STABLE 2 + +enum sw_reg { + DDR_VDDC = 1, + IHOST03, + IHOST12, + IHOST_ARRAY, + DDRIO_SLAVE, + VDDC_CORE, + VDDC1, + DDRIO_MASTER +}; + +int set_swreg(enum sw_reg reg_id, uint32_t micro_volts); +int swreg_firmware_update(void); + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h new file mode 100644 index 0000000..1f15bb0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TIMER_SYNC_H +#define TIMER_SYNC_H + +void brcm_timer_sync_init(void); + +#endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h new file mode 100644 index 0000000..7d83182 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2017 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef USB_PHY_H +#define USB_PHY_H + +#include + +#include +#include +#include + +#include + +#define DRDU2_U2PLL_NDIV_FRAC_OFFSET 0x0U + +#define DRDU2_U2PLL_NDIV_INT 0x4U + +#define DRDU2_U2PLL_CTRL 0x8U +#define DRDU2_U2PLL_LOCK BIT(6U) +#define DRDU2_U2PLL_RESETB BIT(5U) +#define DRDU2_U2PLL_PDIV_MASK 0xFU +#define DRDU2_U2PLL_PDIV_OFFSET 1U +#define DRDU2_U2PLL_SUSPEND_EN BIT(0U) + +#define DRDU2_PHY_CTRL 0x0CU +#define DRDU2_U2IDDQ BIT(30U) +#define DRDU2_U2SOFT_RST_N BIT(29U) +#define DRDU2_U2PHY_ON_FLAG BIT(22U) +#define DRDU2_U2PHY_PCTL_MASK 0xFFFFU +#define DRDU2_U2PHY_PCTL_OFFSET 6U +#define DRDU2_U2PHY_RESETB BIT(5U) +#define DRDU2_U2PHY_ISO BIT(4U) +#define DRDU2_U2AFE_BG_PWRDWNB BIT(3U) +#define DRDU2_U2AFE_PLL_PWRDWNB BIT(2U) +#define DRDU2_U2AFE_LDO_PWRDWNB BIT(1U) +#define DRDU2_U2CTRL_CORERDY BIT(0U) + +#define DRDU2_STRAP_CTRL 0x18U +#define DRDU2_FORCE_HOST_MODE BIT(5U) +#define DRDU2_FORCE_DEVICE_MODE BIT(4U) +#define BDC_USB_STP_SPD_MASK 0x7U +#define BDC_USB_STP_SPD_OFFSET 0U + +#define DRDU2_PWR_CTRL 0x1CU +#define DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I BIT(2U) +#define DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I BIT(1U) + +#define DRDU2_SOFT_RESET_CTRL 0x20U +#define DRDU2_BDC_AXI_SOFT_RST_N BIT(0U) + +#define USB3H_U2PLL_NDIV_FRAC 0x4U + +#define USB3H_U2PLL_NDIV_INT 0x8U + +#define USB3H_U2PLL_CTRL 0xCU +#define USB3H_U2PLL_LOCK BIT(6U) +#define USB3H_U2PLL_RESETB BIT(5U) +#define USB3H_U2PLL_PDIV_MASK 0xFU +#define USB3H_U2PLL_PDIV_OFFSET 1U + +#define USB3H_U2PHY_CTRL 0x10U +#define USB3H_U2PHY_ON_FLAG 22U +#define USB3H_U2PHY_PCTL_MASK 0xFFFFU +#define USB3H_U2PHY_PCTL_OFFSET 6U +#define USB3H_U2PHY_IDDQ BIT(29U) +#define USB3H_U2PHY_RESETB BIT(5U) +#define USB3H_U2PHY_ISO BIT(4U) +#define USB3H_U2AFE_BG_PWRDWNB BIT(3U) +#define USB3H_U2AFE_PLL_PWRDWNB BIT(2U) +#define USB3H_U2AFE_LDO_PWRDWNB BIT(1U) +#define USB3H_U2CTRL_CORERDY BIT(0U) + +#define USB3H_U3PHY_CTRL 0x14U +#define USB3H_U3SOFT_RST_N BIT(30U) +#define USB3H_U3MDIO_RESETB_I BIT(29U) +#define USB3H_U3POR_RESET_I BIT(28U) +#define USB3H_U3PHY_PCTL_MASK 0xFFFFU +#define USB3H_U3PHY_PCTL_OFFSET 2U +#define USB3H_U3PHY_RESETB BIT(1U) + +#define USB3H_U3PHY_PLL_CTRL 0x18U +#define USB3H_U3PLL_REFCLK_MASK 0x7U +#define USB3H_U3PLL_REFCLK_OFFSET 4U +#define USB3H_U3PLL_SS_LOCK BIT(3U) +#define USB3H_U3PLL_SEQ_START BIT(2U) +#define USB3H_U3SSPLL_SUSPEND_EN BIT(1U) +#define USB3H_U3PLL_RESETB BIT(0U) + +#define USB3H_PWR_CTRL 0x28U +#define USB3H_PWR_CTRL_OVERRIDE_I_R 4U +#define USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN BIT(11U) +#define USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN BIT(10U) + +#define USB3H_SOFT_RESET_CTRL 0x2CU +#define USB3H_XHC_AXI_SOFT_RST_N BIT(1U) + +#define USB3H_PHY_PWR_CTRL 0x38U +#define USB3H_DISABLE_USB30_P0 BIT(2U) +#define USB3H_DISABLE_EUSB_P1 BIT(1U) +#define USB3H_DISABLE_EUSB_P0 BIT(0U) + + +#define DRDU3_U2PLL_NDIV_FRAC 0x4U + +#define DRDU3_U2PLL_NDIV_INT 0x8U + +#define DRDU3_U2PLL_CTRL 0xCU +#define DRDU3_U2PLL_LOCK BIT(6U) +#define DRDU3_U2PLL_RESETB BIT(5U) +#define DRDU3_U2PLL_PDIV_MASK 0xFU +#define DRDU3_U2PLL_PDIV_OFFSET 1U + +#define DRDU3_U2PHY_CTRL 0x10U +#define DRDU3_U2PHY_IDDQ BIT(29U) +#define DRDU3_U2PHY_ON_FLAG BIT(22U) +#define DRDU3_U2PHY_PCTL_MASK 0xFFFFU +#define DRDU3_U2PHY_PCTL_OFFSET 6U +#define DRDU3_U2PHY_RESETB BIT(5U) +#define DRDU3_U2PHY_ISO BIT(4U) +#define DRDU3_U2AFE_BG_PWRDWNB BIT(3U) +#define DRDU3_U2AFE_PLL_PWRDWNB BIT(2U) +#define DRDU3_U2AFE_LDO_PWRDWNB BIT(1U) +#define DRDU3_U2CTRL_CORERDY BIT(0U) + +#define DRDU3_U3PHY_CTRL 0x14U +#define DRDU3_U3XHC_SOFT_RST_N BIT(31U) +#define DRDU3_U3BDC_SOFT_RST_N BIT(30U) +#define DRDU3_U3MDIO_RESETB_I BIT(29U) +#define DRDU3_U3POR_RESET_I BIT(28U) +#define DRDU3_U3PHY_PCTL_MASK 0xFFFFU +#define DRDU3_U3PHY_PCTL_OFFSET 2U +#define DRDU3_U3PHY_RESETB BIT(1U) + +#define DRDU3_U3PHY_PLL_CTRL 0x18U +#define DRDU3_U3PLL_REFCLK_MASK 0x7U +#define DRDU3_U3PLL_REFCLK_OFFSET 4U +#define DRDU3_U3PLL_SS_LOCK BIT(3U) +#define DRDU3_U3PLL_SEQ_START BIT(2U) +#define DRDU3_U3SSPLL_SUSPEND_EN BIT(1U) +#define DRDU3_U3PLL_RESETB BIT(0U) + +#define DRDU3_STRAP_CTRL 0x28U +#define BDC_USB_STP_SPD_MASK 0x7U +#define BDC_USB_STP_SPD_OFFSET 0U +#define BDC_USB_STP_SPD_SS 0x0U +#define BDC_USB_STP_SPD_HS 0x2U + +#define DRDU3_PWR_CTRL 0x2cU +#define DRDU3_U2PHY_DFE_SWITCH_PWROKIN BIT(12U) +#define DRDU3_U2PHY_DFE_SWITCH_PWRONIN BIT(11U) +#define DRDU3_PWR_CTRL_OVERRIDE_I_R 4U + +#define DRDU3_SOFT_RESET_CTRL 0x30U +#define DRDU3_XHC_AXI_SOFT_RST_N BIT(1U) +#define DRDU3_BDC_AXI_SOFT_RST_N BIT(0U) + +#define DRDU3_PHY_PWR_CTRL 0x3cU +#define DRDU3_DISABLE_USB30_P0 BIT(2U) +#define DRDU3_DISABLE_EUSB_P1 BIT(1U) +#define DRDU3_DISABLE_EUSB_P0 BIT(0U) + +#define PLL_REFCLK_PAD 0x0U +#define PLL_REFCLK_25MHZ 0x1U +#define PLL_REFCLK_96MHZ 0x2U +#define PLL_REFCLK_INTERNAL 0x3U +/* USB PLL lock time out for 10 ms */ +#define PLL_LOCK_RETRY_COUNT 10000U + + +#define U2PLL_NDIV_INT_VAL 0x13U +#define U2PLL_NDIV_FRAC_VAL 0x1005U +#define U2PLL_PDIV_VAL 0x1U +/* + * Using external FSM + * BIT-3:2: device mode; mode is not effect + * BIT-1: soft reset active low + */ +#define U2PHY_PCTL_VAL 0x0003U +/* Non-driving signal low */ +#define U2PHY_PCTL_NON_DRV_LOW 0x0002U +#define U3PHY_PCTL_VAL 0x0006U + +#define MAX_NR_PORTS 3U + +#define USB3H_DRDU2_PHY 1U +#define DRDU3_PHY 2U + +#define USB_HOST_MODE 1U +#define USB_DEV_MODE 2U + +#define USB3SS_PORT 0U +#define DRDU2_PORT 1U +#define USB3HS_PORT 2U + +#define DRD3SS_PORT 0U +#define DRD3HS_PORT 1U + +#define SR_USB_PHY_COUNT 2U + +#define DRDU3_PIPE_CTRL 0x68500000U +#define DRDU3H_XHC_REGS_CPLIVER 0x68501000U +#define USB3H_PIPE_CTRL 0x68510000U +#define DRD2U3H_XHC_REGS_CPLIVER 0x68511000U +#define DRDU2_U2PLL_NDIV_FRAC 0x68520000U + +#define AXI_DEBUG_CTRL 0x68500038U +#define AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE BIT(12U) + +#define USB3H_DEBUG_CTRL 0x68510034U +#define USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE BIT(7U) + +typedef struct _usb_phy_port usb_phy_port_t; + +typedef struct { + uint32_t drdu2reg; + uint32_t usb3hreg; + uint32_t drdu3reg; + uint32_t phy_id; + uint32_t ports_enabled; + uint32_t initialized; + usb_phy_port_t *phy_port; +} usb_phy_t; + +struct _usb_phy_port { + uint32_t port_id; + uint32_t mode; + uint32_t enabled; + usb_phy_t *p; +}; + +struct u2_phy_ext_fsm { + uint32_t pll_ctrl_reg; + uint32_t phy_ctrl_reg; + uint32_t phy_iddq; + uint32_t pwr_ctrl_reg; + uint32_t pwr_okin; + uint32_t pwr_onin; +}; + +#endif /* USB_PHY_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/platform.mk b/arm-trusted-firmware/plat/brcm/board/stingray/platform.mk new file mode 100644 index 0000000..aa2fe86 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/platform.mk @@ -0,0 +1,304 @@ +# +# Copyright (c) 2019-2021, Broadcom +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Set the toc_flags to 1 for 100% speed operation +# Set the toc_flags to 2 for 50% speed operation +# Set the toc_flags to 3 for 25% speed operation +# Set the toc_flags bit 3 to indicate ignore the fip in UEFI copy mode +PLAT_TOC_FLAGS := 0x0 + +# Set the IHOST_PLL_FREQ to, +# 1 for full speed +# 2 for 50% speed +# 3 for 25% speed +# 0 for bypass +$(eval $(call add_define_val,IHOST_PLL_FREQ,1)) + +# Enable workaround for ERRATA_A72_859971 +ERRATA_A72_859971 := 1 + +# Cache Coherency Interconnect Driver needed +DRIVER_CC_ENABLE := 1 +$(eval $(call add_define,DRIVER_CC_ENABLE)) + +# Enable to erase eMMC +INCLUDE_EMMC_DRIVER_ERASE_CODE := 0 + +ifeq (${INCLUDE_EMMC_DRIVER_ERASE_CODE},1) +$(eval $(call add_define,INCLUDE_EMMC_DRIVER_ERASE_CODE)) +endif + +# BL31 is in DRAM +ARM_BL31_IN_DRAM := 1 + +ifneq (${USE_EMULATOR},yes) +STINGRAY_EMULATION_SETUP := 0 +ifeq (${FASTBOOT_TYPE},) +override FASTBOOT_TYPE := 0 +endif +USE_PAXB := yes +USE_PAXC := yes +USE_CHIMP := yes +endif + +USE_CRMU_SRAM := yes + +# Disable FS4 clocks - they can be reenabled when needed by linux +FS4_DISABLE_CLOCK := yes + +# Enable error logging by default for Stingray +BCM_ELOG := yes + +# Enable FRU support by default for Stingray +ifeq (${USE_FRU},) +USE_FRU := no +endif + +# Use single cluster +ifeq (${USE_SINGLE_CLUSTER},yes) +$(info Using Single Cluster) +$(eval $(call add_define,USE_SINGLE_CLUSTER)) +endif + +# Use DDR +ifeq (${USE_DDR},yes) +$(info Using DDR) +$(eval $(call add_define,USE_DDR)) +endif + +ifeq (${BOARD_CFG},) +BOARD_CFG := bcm958742t +endif + +# Use USB +ifeq (${USE_USB},yes) +$(info Using USB) +$(eval $(call add_define,USE_USB)) +endif + +# Use PAXB +ifeq (${USE_PAXB},yes) +$(info Using PAXB) +$(eval $(call add_define,USE_PAXB)) +endif + +# Use FS4 +ifeq (${USE_FS4},yes) +$(info Using FS4) +$(eval $(call add_define,USE_FS4)) +endif + +# Use FS6 +ifeq (${USE_FS6},yes) +$(info Using FS6) +$(eval $(call add_define,USE_FS6)) +endif + +# Disable FS4 clock +ifeq (${FS4_DISABLE_CLOCK},yes) +$(info Using FS4_DISABLE_CLOCK) +$(eval $(call add_define,FS4_DISABLE_CLOCK)) +endif + +ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},) +$(info Using NCSI_IO_DRIVE_STRENGTH_MA) +$(eval $(call add_define,NCSI_IO_DRIVE_STRENGTH_MA)) +endif + +# Use NAND +ifeq (${USE_NAND},$(filter yes, ${USE_NAND})) +$(info Using NAND) +$(eval $(call add_define,USE_NAND)) +endif + +# Enable Broadcom error logging support +ifeq (${BCM_ELOG},yes) +$(info Using BCM_ELOG) +$(eval $(call add_define,BCM_ELOG)) +endif + +# BL31 build for standalone mode +ifeq (${STANDALONE_BL31},yes) +RESET_TO_BL31 := 1 +$(info Using RESET_TO_BL31) +endif + +# BL31 force full frequency for all CPUs +ifeq (${BL31_FORCE_CPU_FULL_FREQ},yes) +$(info Using BL31_FORCE_CPU_FULL_FREQ) +$(eval $(call add_define,BL31_FORCE_CPU_FULL_FREQ)) +endif + +# Enable non-secure accesses to CCN registers +ifeq (${BL31_CCN_NONSECURE},yes) +$(info Using BL31_CCN_NONSECURE) +$(eval $(call add_define,BL31_CCN_NONSECURE)) +endif + +# Use ChiMP +ifeq (${USE_CHIMP},yes) +$(info Using ChiMP) +$(eval $(call add_define,USE_CHIMP)) +endif + +# Use PAXC +ifeq (${USE_PAXC},yes) +$(info Using PAXC) +$(eval $(call add_define,USE_PAXC)) +ifeq (${CHIMPFW_USE_SIDELOAD},yes) +$(info Using ChiMP FW sideload) +$(eval $(call add_define,CHIMPFW_USE_SIDELOAD)) +endif +$(eval $(call add_define,FASTBOOT_TYPE)) +$(eval $(call add_define,CHIMP_FB1_ENTRY)) +endif + +ifeq (${DEFAULT_SWREG_CONFIG}, 1) +$(eval $(call add_define,DEFAULT_SWREG_CONFIG)) +endif + +ifeq (${CHIMP_ALWAYS_NEEDS_QSPI},yes) +$(eval $(call add_define,CHIMP_ALWAYS_NEEDS_QSPI)) +endif + +# For testing purposes, use memsys stubs. Remove once memsys is fully tested. +USE_MEMSYS_STUBS := yes + +# Default, use BL1_RW area +ifneq (${BL2_USE_BL1_RW},no) +$(eval $(call add_define,USE_BL1_RW)) +endif + +# Default soft reset is L3 +$(eval $(call add_define,CONFIG_SOFT_RESET_L3)) + +# Enable Chip OTP driver +DRIVER_OCOTP_ENABLE := 1 + +ifneq (${WARMBOOT_DDR_S3_SUPPORT},) +DRIVER_SPI_ENABLE := 1 +endif + +include plat/brcm/board/common/board_common.mk + +SOC_DIR := brcm/board/stingray + +PLAT_INCLUDES += -Iplat/${SOC_DIR}/include/ \ + -Iinclude/plat/brcm/common/ \ + -Iplat/brcm/common/ + +PLAT_BL_COMMON_SOURCES += lib/cpus/aarch64/cortex_a72.S \ + plat/${SOC_DIR}/aarch64/plat_helpers.S \ + drivers/ti/uart/aarch64/16550_console.S \ + plat/${SOC_DIR}/src/tz_sec.c \ + drivers/arm/tzc/tzc400.c \ + plat/${SOC_DIR}/driver/plat_emmc.c \ + plat/${SOC_DIR}/src/topology.c \ + drivers/brcm/mdio/mdio.c + +ifeq (${USE_CHIMP},yes) +PLAT_BL_COMMON_SOURCES += drivers/brcm/chimp.c +endif + +ifeq (${USE_USB},yes) +PLAT_BL_COMMON_SOURCES += plat/${SOC_DIR}/driver/usb.c \ + plat/${SOC_DIR}/driver/usb_phy.c +endif + +BL2_SOURCES += plat/${SOC_DIR}/driver/ihost_pll_config.c \ + plat/${SOC_DIR}/src/bl2_setup.c \ + plat/${SOC_DIR}/driver/swreg.c + +ifeq (${USE_DDR},yes) +PLAT_INCLUDES += -Iplat/${SOC_DIR}/driver/ddr/soc/include +else +PLAT_INCLUDES += -Iplat/${SOC_DIR}/driver/ext_sram_init +BL2_SOURCES += plat/${SOC_DIR}/driver/ext_sram_init/ext_sram_init.c +endif + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +BRCM_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/brcm/common/brcm_gicv3.c + +BL31_SOURCES += \ + drivers/arm/ccn/ccn.c \ + plat/brcm/board/common/timer_sync.c \ + plat/brcm/common/brcm_ccn.c \ + plat/common/plat_psci_common.c \ + plat/${SOC_DIR}/driver/ihost_pll_config.c \ + plat/${SOC_DIR}/src/bl31_setup.c \ + plat/${SOC_DIR}/src/fsx.c \ + plat/${SOC_DIR}/src/iommu.c \ + plat/${SOC_DIR}/src/sdio.c \ + ${BRCM_GIC_SOURCES} + +ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},) +BL31_SOURCES += plat/${SOC_DIR}/src/ncsi.c +endif + +ifeq (${USE_PAXB},yes) +BL31_SOURCES += plat/${SOC_DIR}/src/paxb.c +BL31_SOURCES += plat/${SOC_DIR}/src/sr_paxb_phy.c +endif + +ifeq (${USE_PAXC},yes) +BL31_SOURCES += plat/${SOC_DIR}/src/paxc.c +endif + +ifdef SCP_BL2 +PLAT_INCLUDES += -Iplat/brcm/common/ + +BL2_SOURCES += plat/brcm/common/brcm_mhu.c \ + plat/brcm/common/brcm_scpi.c \ + plat/${SOC_DIR}/src/scp_utils.c \ + plat/${SOC_DIR}/src/scp_cmd.c \ + drivers/brcm/scp.c + +BL31_SOURCES += plat/brcm/common/brcm_mhu.c \ + plat/brcm/common/brcm_scpi.c \ + plat/${SOC_DIR}/src/brcm_pm_ops.c +else +BL31_SOURCES += plat/${SOC_DIR}/src/ihost_pm.c \ + plat/${SOC_DIR}/src/pm.c +endif + +ifeq (${ELOG_SUPPORT},1) +ifeq (${ELOG_STORE_MEDIA},DDR) +BL2_SOURCES += plat/brcm/board/common/bcm_elog_ddr.c +endif +endif + +ifeq (${BL31_BOOT_PRELOADED_SCP}, 1) +ifdef SCP_BL2 +SCP_CFG_DIR=$(dir ${SCP_BL2}) +PLAT_INCLUDES += -I${SCP_CFG_DIR} +endif +PLAT_INCLUDES += -Iplat/brcm/common/ + +# By default use OPTEE Assigned memory +PRELOADED_SCP_BASE ?= 0x8E000000 +PRELOADED_SCP_SIZE ?= 0x10000 +$(eval $(call add_define,PRELOADED_SCP_BASE)) +$(eval $(call add_define,PRELOADED_SCP_SIZE)) +$(eval $(call add_define,BL31_BOOT_PRELOADED_SCP)) +BL31_SOURCES += plat/${SOC_DIR}/src/scp_utils.c \ + plat/${SOC_DIR}/src/scp_cmd.c \ + drivers/brcm/scp.c +endif + +# Do not execute the startup code on warm reset. +PROGRAMMABLE_RESET_ADDRESS := 1 + +# Nitro FW, config and Crash log uses secure DDR memory +# Inaddition to above, Nitro master and slave is also secure +ifneq ($(NITRO_SECURE_ACCESS),) +$(eval $(call add_define,NITRO_SECURE_ACCESS)) +$(eval $(call add_define,DDR_NITRO_SECURE_REGION_START)) +$(eval $(call add_define,DDR_NITRO_SECURE_REGION_END)) +endif diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c new file mode 100644 index 0000000..b2c8aec --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c @@ -0,0 +1,743 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef USE_GPIO +#include +#include +#endif +#include +#include +#include +#include +#ifdef USE_DDR +#include +#else +#include +#endif +#if DRIVER_OCOTP_ENABLE +#include +#endif +#include "board_info.h" + +#define WORD_SIZE 8 +#define SWREG_AVS_OTP_OFFSET (13 * WORD_SIZE) /* 13th row byte offset */ +#define AON_GPIO_OTP_OFFSET (28 * WORD_SIZE) /* 28th row byte offset */ +#define BYTES_TO_READ 8 + +/* OTP voltage step definitions */ +#define MVOLT_STEP_MAX 0x18 /* 1v */ +#define MVOLT_PER_STEP 10 /* 0.01mv per step */ +#define MVOLT_BASE 760 /* 0.76v */ + +#define STEP_TO_UVOLTS(step) \ + ((MVOLT_BASE + (MVOLT_PER_STEP * (step))) * 1000) + +#define GET_BITS(first, last, data) \ + ((data >> first) & ((1 << (last - first + 1)) - 1)) + +/* + * SW-REG OTP encoding: + * + * SWREG_bits[11:0] = OTP 13th row 12 bits[55:44] + * SWREG_bits[11:10] - Valid Bits (0x2 - valid, if not 0x2 - Invalid) + * SWREG_bits[9:5] - iHost03, iHost12 + * SWREG_bits[4:0] - Core VDDC + */ +#define SWREG_OTP_BITS_START 12 /* 44th bit in MSB 32-bits */ +#define SWREG_OTP_BITS_END 23 /* 55th bit in MSB 32-bits */ +#define SWREG_VDDC_FIELD_START 0 +#define SWREG_VDDC_FIELD_END 4 +#define SWREG_IHOST_FIELD_START 5 +#define SWREG_IHOST_FIELD_END 9 +#define SWREG_VALID_BIT_START 10 +#define SWREG_VALID_BIT_END 11 +#define SWREG_VALID_BITS 0x2 + +/* + * Row 13 bit 56 is programmed as '1' today. It is not being used, so plan + * is to flip this bit to '0' for B1 rev. Hence SW can leverage this bit + * to identify Bx chip to program different sw-regulators. + */ +#define SPARE_BIT 24 + +#define IS_SR_B0(data) (((data) >> SPARE_BIT) & 0x1) + +#if DRIVER_OCOTP_ENABLE +static struct otpc_map otp_stingray_map = { + .otpc_row_size = 2, + .data_r_offset = {0x10, 0x5c}, + .data_w_offset = {0x2c, 0x64}, + .word_size = 8, + .stride = 8, +}; +#endif + +void plat_bcm_bl2_early_platform_setup(void) +{ + /* Select UART0 for AP via mux setting*/ + if (PLAT_BRCM_BOOT_UART_BASE == UART0_BASE_ADDR) { + mmio_write_32(UART0_SIN_MODE_SEL_CONTROL, 1); + mmio_write_32(UART0_SOUT_MODE_SEL_CONTROL, 1); + } +} + +#ifdef USE_NAND +static void brcm_stingray_nand_init(void) +{ + unsigned int val; + unsigned int nand_idm_reset_control = 0x68e0a800; + + VERBOSE(" stingray nand init start.\n"); + + /* Reset NAND */ + VERBOSE(" - reset nand\n"); + val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0)); + mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val | 0x1); + udelay(500); + val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0)); + mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val & ~0x1); + udelay(500); + + VERBOSE(" stingray nand init done.\n"); +} +#endif + +#if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA) +#define PCIE_RESCAL_CFG_0 0x40000130 +#define PCIE_CFG_RESCAL_RSTB_R (1 << 16) +#define PCIE_CFG_RESCAL_PWRDNB_R (1 << 8) +#define PCIE_RESCAL_STATUS_0 0x4000014c +#define PCIE_STAT_PON_VALID_R (1 << 0) +#define PCIE_RESCAL_OUTPUT_STATUS 0x40000154 +#define CDRU_PCIE_RESET_N_R (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) + +#ifdef EMULATION_SETUP +static void brcm_stingray_pcie_reset(void) +{ +} +#else +static void brcm_stingray_pcie_reset(void) +{ + unsigned int data; + int try; + + if (bcm_chimp_is_nic_mode()) { + INFO("NIC mode detected; PCIe reset/rescal not executed\n"); + return; + } + + mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R); + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R); + /* Release reset */ + mmio_setbits_32(PCIE_RESCAL_CFG_0, PCIE_CFG_RESCAL_RSTB_R); + mdelay(1); + /* Power UP */ + mmio_setbits_32(PCIE_RESCAL_CFG_0, + (PCIE_CFG_RESCAL_RSTB_R | PCIE_CFG_RESCAL_PWRDNB_R)); + + try = 1000; + do { + udelay(1); + data = mmio_read_32(PCIE_RESCAL_STATUS_0); + try--; + } while ((data & PCIE_STAT_PON_VALID_R) == 0x0 && (try > 0)); + + if (try <= 0) + ERROR("PCIE_RESCAL_STATUS_0: 0x%x\n", data); + + VERBOSE("PCIE_SATA_RESCAL_STATUS_0 0x%x.\n", + mmio_read_32(PCIE_RESCAL_STATUS_0)); + VERBOSE("PCIE_SATA_RESCAL_OUTPUT_STATUS 0x%x.\n", + mmio_read_32(PCIE_RESCAL_OUTPUT_STATUS)); + INFO("PCIE SATA Rescal Init done\n"); +} +#endif /* EMULATION_SETUP */ +#endif /* USE_PAXB || USE_PAXC || USE_SATA */ + +#ifdef USE_PAXC +void brcm_stingray_chimp_check_and_fastboot(void) +{ + int fastboot_init_result; + + if (bcm_chimp_is_nic_mode()) + /* Do not wait here */ + return; + +#if WARMBOOT_DDR_S3_SUPPORT + /* + * Currently DDR shmoo parameters and QSPI boot source are + * tied. DDR shmoo parameters are stored in QSPI, which is + * used for warmboot. + * Do not reset nitro for warmboot + */ + if (is_warmboot() && (boot_source_get() == BOOT_SOURCE_QSPI)) + return; +#endif /* WARMBOOT_DDR_S3_SUPPORT */ + + /* + * Not in NIC mode, + * initiate fastboot (if enabled) + */ + if (FASTBOOT_TYPE == CHIMP_FASTBOOT_NITRO_RESET) { + + VERBOSE("Bring up Nitro/ChiMP\n"); + + if (boot_source_get() == BOOT_SOURCE_QSPI) + WARN("Nitro boots from QSPI when AP has booted from QSPI.\n"); + brcm_stingray_set_qspi_mux(0); + VERBOSE("Nitro controls the QSPI\n"); + } + + fastboot_init_result = bcm_chimp_initiate_fastboot(FASTBOOT_TYPE); + if (fastboot_init_result && boot_source_get() != BOOT_SOURCE_QSPI) + ERROR("Nitro init error %d. Status: 0x%x; bpe_mod reg: 0x%x\n" + "fastboot register: 0x%x; handshake register 0x%x\n", + fastboot_init_result, + bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG), + bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG), + bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG), + bcm_chimp_read(CHIMP_REG_ECO_RESERVED)); + + /* + * CRMU watchdog kicks is an example, which is L1 reset, + * does not clear Nitro scratch pad ram. + * For Nitro resets: Clear the Nitro health status memory. + */ + bcm_chimp_write((CHIMP_REG_CHIMP_SCPAD + CHIMP_HEALTH_STATUS_OFFSET), + 0); +} +#endif + +void set_ihost_vddc_swreg(uint32_t ihost_uvolts, uint32_t vddc_uvolts) +{ + NOTICE("ihost_uvolts: %duv, vddc_uvolts: %duv\n", + ihost_uvolts, vddc_uvolts); + + set_swreg(VDDC_CORE, vddc_uvolts); + set_swreg(IHOST03, ihost_uvolts); + set_swreg(IHOST12, ihost_uvolts); +} + +/* + * Reads SWREG AVS OTP bits (13th row) with ECC enabled and get voltage + * defined in OTP if valid OTP is found + */ +void read_avs_otp_bits(uint32_t *ihost_uvolts, uint32_t *vddc_uvolts) +{ + uint32_t offset = SWREG_AVS_OTP_OFFSET; + uint32_t ihost_step, vddc_step; + uint32_t avs_bits; + uint32_t buf[2]; + + if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1) + return; + + VERBOSE("AVS OTP %d ROW: 0x%x.0x%x\n", + offset/WORD_SIZE, buf[1], buf[0]); + + /* get voltage readings from AVS OTP bits */ + avs_bits = GET_BITS(SWREG_OTP_BITS_START, + SWREG_OTP_BITS_END, + buf[1]); + + /* check for valid otp bits */ + if (GET_BITS(SWREG_VALID_BIT_START, SWREG_VALID_BIT_END, avs_bits) != + SWREG_VALID_BITS) { + WARN("Invalid AVS OTP bits at %d row\n", offset/WORD_SIZE); + return; + } + + /* get ihost and vddc step value */ + vddc_step = GET_BITS(SWREG_VDDC_FIELD_START, + SWREG_VDDC_FIELD_END, + avs_bits); + + ihost_step = GET_BITS(SWREG_IHOST_FIELD_START, + SWREG_IHOST_FIELD_END, + avs_bits); + + if ((ihost_step > MVOLT_STEP_MAX) || (vddc_step > MVOLT_STEP_MAX)) { + WARN("OTP entry invalid\n"); + return; + } + + /* get voltage in micro-volts */ + *ihost_uvolts = STEP_TO_UVOLTS(ihost_step); + *vddc_uvolts = STEP_TO_UVOLTS(vddc_step); +} + +/* + * This api reads otp bits and program internal swreg's - ihos12, ihost03, + * vddc_core and ddr_core based on different chip. External swreg's + * programming will be done from crmu. + * + * For A2 chip: + * Read OTP row 20, bit 50. This bit will be set for A2 chip. Once A2 chip is + * found, read AVS OTP row 13, 12bits[55:44], if valid otp bits are found + * then set ihost and vddc according to avs otp bits else set them to 0.94v + * and 0.91v respectively. Also update the firmware after setting voltage. + * + * For B0 chip: + * Read OTP row 13, bit 56. This bit will be set for B0 chip. Once B0 chip is + * found then set ihost and vddc to 0.95v and ddr_core to 1v. No AVS OTP bits + * are used get ihost/vddc voltages. + * + * For B1 chip: + * Read AVS OTP row 13, 12bits[55:44], if valid otp bits are found then set + * ihost and vddc according to avs otp bits else set them to 0.94v and 0.91v + * respectively. + */ +void set_swreg_based_on_otp(void) +{ + /* default voltage if no valid OTP */ + uint32_t vddc_uvolts = VDDC_CORE_DEF_VOLT; + uint32_t ihost_uvolts = IHOST_DEF_VOLT; + uint32_t ddrc_uvolts; + uint32_t offset; + uint32_t buf[2]; + + offset = SWREG_AVS_OTP_OFFSET; + if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1) + return; + + VERBOSE("OTP %d ROW: 0x%x.0x%x\n", + offset/WORD_SIZE, buf[1], buf[0]); + + if (IS_SR_B0(buf[1])) { + /* don't read AVS OTP for B0 */ + ihost_uvolts = B0_IHOST_DEF_VOLT; + vddc_uvolts = B0_VDDC_CORE_DEF_VOLT; + ddrc_uvolts = B0_DDR_VDDC_DEF_VOLT; + } else { + read_avs_otp_bits(&ihost_uvolts, &vddc_uvolts); + } + +#if (IHOST_REG_TYPE == IHOST_REG_INTEGRATED) && \ + (VDDC_REG_TYPE == VDDC_REG_INTEGRATED) + /* enable IHOST12 cluster before changing voltage */ + NOTICE("Switching on the Regulator idx: %u\n", + SWREG_IHOST1_DIS); + mmio_clrsetbits_32(CRMU_SWREG_CTRL_ADDR, + BIT(SWREG_IHOST1_DIS), + BIT(SWREG_IHOST1_REG_RESETB)); + + /* wait for regulator supply gets stable */ + while (!(mmio_read_32(CRMU_SWREG_STATUS_ADDR) & + (1 << SWREG_IHOST1_PMU_STABLE))) + ; + + INFO("Regulator supply got stable\n"); + +#ifndef DEFAULT_SWREG_CONFIG + swreg_firmware_update(); +#endif + + set_ihost_vddc_swreg(ihost_uvolts, vddc_uvolts); +#endif + if (IS_SR_B0(buf[1])) { + NOTICE("ddrc_uvolts: %duv\n", ddrc_uvolts); + set_swreg(DDR_VDDC, ddrc_uvolts); + } +} + +#ifdef USE_DDR +static struct ddr_info ddr_info; +#endif +#ifdef USE_FRU +static struct fru_area_info fru_area[FRU_MAX_NR_AREAS]; +static struct fru_board_info board_info; +static struct fru_time fru_tm; +static uint8_t fru_tbl[BCM_MAX_FRU_LEN]; + +static void board_detect_fru(void) +{ + uint32_t i, result; + int ret = -1; + + result = bcm_emmc_init(false); + if (!result) { + ERROR("eMMC init failed\n"); + return; + } + + /* go through eMMC boot partitions looking for FRU table */ + for (i = EMMC_BOOT_PARTITION1; i <= EMMC_BOOT_PARTITION2; i++) { + result = emmc_partition_select(i); + if (!result) { + ERROR("Switching to eMMC part %u failed\n", i); + return; + } + + result = emmc_read(BCM_FRU_TBL_OFFSET, (uintptr_t)fru_tbl, + BCM_MAX_FRU_LEN, BCM_MAX_FRU_LEN); + if (!result) { + ERROR("Failed to read from eMMC part %u\n", i); + return; + } + + /* + * Run sanity check and checksum to make sure valid FRU table + * is detected + */ + ret = fru_validate(fru_tbl, fru_area); + if (ret < 0) { + WARN("FRU table not found in eMMC part %u\n", i); + continue; + } + + /* parse DDR information from FRU table */ + ret = fru_parse_ddr(fru_tbl, &fru_area[FRU_AREA_INTERNAL], + &ddr_info); + if (ret < 0) { + WARN("No FRU DDR info found in eMMC part %u\n", i); + continue; + } + + /* parse board information from FRU table */ + ret = fru_parse_board(fru_tbl, &fru_area[FRU_AREA_BOARD_INFO], + &board_info); + if (ret < 0) { + WARN("No FRU board info found in eMMC part %u\n", i); + continue; + } + + /* if we reach here, valid FRU table is parsed */ + break; + } + + if (ret < 0) { + WARN("FRU table missing for this board\n"); + return; + } + + for (i = 0; i < BCM_MAX_NR_DDR; i++) { + INFO("DDR channel index: %d\n", ddr_info.mcb[i].idx); + INFO("DDR size %u GB\n", ddr_info.mcb[i].size_mb / 1024); + INFO("DDR ref ID by SW (Not MCB Ref ID) 0x%x\n", + ddr_info.mcb[i].ref_id); + } + + fru_format_time(board_info.mfg_date, &fru_tm); + + INFO("**** FRU board information ****\n"); + INFO("Language 0x%x\n", board_info.lang); + INFO("Manufacturing Date %u.%02u.%02u, %02u:%02u\n", + fru_tm.year, fru_tm.month, fru_tm.day, + fru_tm.hour, fru_tm.min); + INFO("Manufacturing Date(Raw) 0x%x\n", board_info.mfg_date); + INFO("Manufacturer %s\n", board_info.manufacturer); + INFO("Product Name %s\n", board_info.product_name); + INFO("Serial number %s\n", board_info.serial_number); + INFO("Part number %s\n", board_info.part_number); + INFO("File ID %s\n", board_info.file_id); +} +#endif /* USE_FRU */ + +#ifdef USE_GPIO + +#define INVALID_GPIO 0xffff + +static const int gpio_cfg_bitmap[MAX_NR_GPIOS] = { +#ifdef BRD_DETECT_GPIO_BIT0 + BRD_DETECT_GPIO_BIT0, +#else + INVALID_GPIO, +#endif +#ifdef BRD_DETECT_GPIO_BIT1 + BRD_DETECT_GPIO_BIT1, +#else + INVALID_GPIO, +#endif +#ifdef BRD_DETECT_GPIO_BIT2 + BRD_DETECT_GPIO_BIT2, +#else + INVALID_GPIO, +#endif +#ifdef BRD_DETECT_GPIO_BIT3 + BRD_DETECT_GPIO_BIT3, +#else + INVALID_GPIO, +#endif +}; + +static uint8_t gpio_bitmap; + +/* + * Use an odd number to avoid potential conflict with public GPIO level + * defines + */ +#define GPIO_STATE_FLOAT 15 + +/* + * If GPIO_SUPPORT_FLOAT_DETECTION is disabled, simply return GPIO level + * + * If GPIO_SUPPORT_FLOAT_DETECTION is enabled, add additional test for possible + * pin floating (unconnected) scenario. This support is assuming externally + * applied pull up / pull down will have a stronger pull than the internal pull + * up / pull down. + */ +static uint8_t gpio_get_state(int gpio) +{ + uint8_t val; + + /* set direction to GPIO input */ + gpio_set_direction(gpio, GPIO_DIR_IN); + +#ifndef GPIO_SUPPORT_FLOAT_DETECTION + if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) + val = GPIO_LEVEL_HIGH; + else + val = GPIO_LEVEL_LOW; + + return val; +#else + /* + * Enable internal pull down. If GPIO level is still high, there must + * be an external pull up + */ + gpio_set_pull(gpio, GPIO_PULL_DOWN); + if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) { + val = GPIO_LEVEL_HIGH; + goto exit; + } + + /* + * Enable internal pull up. If GPIO level is still low, there must + * be an external pull down + */ + gpio_set_pull(gpio, GPIO_PULL_UP); + if (gpio_get_value(gpio) == GPIO_LEVEL_LOW) { + val = GPIO_LEVEL_LOW; + goto exit; + } + + /* if reached here, the pin must be not connected */ + val = GPIO_STATE_FLOAT; + +exit: + /* make sure internall pull is disabled */ + if (gpio_get_pull(gpio) != GPIO_PULL_NONE) + gpio_set_pull(gpio, GPIO_PULL_NONE); + + return val; +#endif +} + +static void board_detect_gpio(void) +{ + unsigned int i, val; + int gpio; + + iproc_gpio_init(IPROC_GPIO_S_BASE, IPROC_GPIO_NR, + IPROC_IOPAD_MODE_BASE, HSLS_IOPAD_BASE); + + gpio_bitmap = 0; + for (i = 0; i < MAX_NR_GPIOS; i++) { + if (gpio_cfg_bitmap[i] == INVALID_GPIO) + continue; + + /* + * Construct the bitmap based on GPIO value. Floating pin + * detection is a special case. As soon as a floating pin is + * detected, a special value of MAX_GPIO_BITMAP_VAL is + * assigned and we break out of the loop immediately + */ + gpio = gpio_cfg_bitmap[i]; + val = gpio_get_state(gpio); + if (val == GPIO_STATE_FLOAT) { + gpio_bitmap = MAX_GPIO_BITMAP_VAL; + break; + } + + if (val == GPIO_LEVEL_HIGH) + gpio_bitmap |= BIT(i); + } + + memcpy(&ddr_info, &gpio_ddr_info[gpio_bitmap], sizeof(ddr_info)); + INFO("Board detection GPIO bitmap = 0x%x\n", gpio_bitmap); +} +#endif /* USE_GPIO */ + +static void bcm_board_detect(void) +{ +#ifdef DDR_LEGACY_MCB_SUPPORTED + /* Loading default DDR info */ + memcpy(&ddr_info, &default_ddr_info, sizeof(ddr_info)); +#endif +#ifdef USE_FRU + board_detect_fru(); +#endif +#ifdef USE_GPIO + board_detect_gpio(); +#endif +} + +static void dump_persistent_regs(void) +{ + NOTICE("pr0: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG0)); + NOTICE("pr1: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1)); + NOTICE("pr2: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG2)); + NOTICE("pr3: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG3)); + NOTICE("pr4: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG4)); + NOTICE("pr5: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG5)); + NOTICE("pr6: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG6)); + NOTICE("pr7: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG7)); + NOTICE("pr8: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG8)); + NOTICE("pr9: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9)); + NOTICE("pr10: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG10)); + NOTICE("pr11: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG11)); +} + +void plat_bcm_bl2_plat_arch_setup(void) +{ + if (chip_get_rev_id_major() == CHIP_REV_MAJOR_AX) { + if (!(sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & + SOTP_ATF_WATCHDOG_ENABLE_MASK)) { + /* + * Stop sp805 watchdog timer immediately. + * It might has been set up by MCU patch earlier for + * eMMC workaround. + * + * Note the watchdog timer started in CRMU has a very + * short timeout and needs to be stopped immediately. + * Down below we restart it with a much longer timeout + * for BL2 and BL31 + */ + sp805_stop(ARM_SP805_TWDG_BASE); + } + } + +#if !BRCM_DISABLE_TRUSTED_WDOG + /* + * start secure watchdog for BL2 and BL31. + * Note that UART download can take a longer time, + * so do not allow watchdog for UART download, + * as this boot source is not a standard modus operandi. + */ + if (boot_source_get() != BOOT_SOURCE_UART) + sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); +#endif + +#ifdef BCM_ELOG + /* Ensure logging is started out fresh in BL2. */ + mmio_write_32(BCM_ELOG_BL2_BASE, 0); +#endif + /* + * In BL2, since we have very limited space to store logs, we only + * save logs that are >= the WARNING level. + */ + bcm_elog_init((void *)BCM_ELOG_BL2_BASE, BCM_ELOG_BL2_SIZE, + LOG_LEVEL_WARNING); + + dump_persistent_regs(); + + /* Read CRMU mailbox 0 */ + NOTICE("RESET (reported by CRMU): 0x%x\n", + mmio_read_32(CRMU_READ_MAIL_BOX0)); + + /* + * All non-boot-source PADs are in forced input-mode at + * reset so clear the force on non-boot-source PADs using + * CDRU register. + */ + mmio_clrbits_32((uintptr_t)CDRU_CHIP_IO_PAD_CONTROL, + (1 << CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R)); + +#if DRIVER_OCOTP_ENABLE + bcm_otpc_init(&otp_stingray_map); +#endif + + set_swreg_based_on_otp(); + +#if IHOST_PLL_FREQ != 0 + bcm_set_ihost_pll_freq(0x0, IHOST_PLL_FREQ); +#endif + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE + /* The erasable unit of the eMMC is the "Erase Group"; + * Erase group is measured in write blocks which are the + * basic writable units of the Device. + * The size of the Erase Group is a Device specific parameter + */ + emmc_erase(EMMC_ERASE_START_BLOCK, EMMC_ERASE_BLOCK_COUNT, + EMMC_ERASE_PARTITION); +#endif + + bcm_board_detect(); +#ifdef DRIVER_EMMC_ENABLE + /* Initialize the card, if it is not */ + if (bcm_emmc_init(true) == 0) + WARN("eMMC Card Initialization Failed!!!\n"); +#endif + +#if BL2_TEST_I2C + i2c_test(); +#endif + +#ifdef USE_DDR + ddr_initialize(&ddr_info); + + ddr_secure_region_config(SECURE_DDR_BASE_ADDRESS, + SECURE_DDR_END_ADDRESS); +#ifdef NITRO_SECURE_ACCESS + ddr_secure_region_config(DDR_NITRO_SECURE_REGION_START, + DDR_NITRO_SECURE_REGION_END); +#endif +#else + ext_sram_init(); +#endif + +#if BL2_TEST_MEM + ddr_test(); +#endif + +#ifdef USE_NAND + brcm_stingray_nand_init(); +#endif + +#if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA) + brcm_stingray_pcie_reset(); +#endif + +#ifdef USE_PAXC + if (boot_source_get() != BOOT_SOURCE_QSPI) + brcm_stingray_chimp_check_and_fastboot(); +#endif + +#if ((!CLEAN_DDR || MMU_DISABLED)) + /* + * Now DDR has been initialized. We want to copy all the logs in SRAM + * into DDR so we will have much more space to store the logs in the + * next boot stage + */ + bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE, + MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE) + ); + + /* + * We are not yet at the end of BL2, but we can stop log here so we do + * not need to add 'bcm_elog_exit' to the standard BL2 code. The + * benefit of capturing BL2 logs after this is very minimal in a + * production system + * NOTE: BL2 logging must be exited before going forward to setup + * page tables + */ + bcm_elog_exit(); +#endif +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c new file mode 100644 index 0000000..04df6a0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c @@ -0,0 +1,1071 @@ +/* + * Copyright (c) 2015 - 2021, Broadcom + * + * 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 +#ifdef USE_USB +#include +#endif +#include +#include +#include + +/******************************************************************************* + * Perform any BL3-1 platform setup common to ARM standard platforms + ******************************************************************************/ + +static void brcm_stingray_gain_qspi_control(void) +{ + if (boot_source_get() != BOOT_SOURCE_QSPI) { + if (bcm_chimp_is_nic_mode() && + (!bcm_chimp_handshake_done())) { + /* + * Last chance to wait for ChiMP firmware to report + * "I am done" before grabbing the QSPI + */ + WARN("ChiMP still not booted\n"); +#ifndef CHIMP_ALWAYS_NEEDS_QSPI + WARN("ChiMP is given the last chance to boot (%d s)\n", + CHIMP_HANDSHAKE_TIMEOUT_MS / 1000); + + if (!bcm_chimp_wait_handshake()) { + ERROR("ChiMP failed to boot\n"); + } else { + INFO("ChiMP booted successfully\n"); + } +#endif + } + +#ifndef CHIMP_ALWAYS_NEEDS_QSPI + INFO("AP grabs QSPI\n"); + /* + * For QSPI boot sbl/bl1 has already taken care. + * For other boot sources QSPI needs to be muxed to + * AP for exclusive use + */ + brcm_stingray_set_qspi_mux(1); + INFO("AP (bl31) gained control over QSPI\n"); +#endif + } +} + +static void brcm_stingray_dma_pl330_init(void) +{ + unsigned int val; + + VERBOSE("dma pl330 init start\n"); + + /* Set DMAC boot_manager_ns = 0x1 */ + VERBOSE(" - configure boot security state\n"); + mmio_setbits_32(DMAC_M0_IDM_IO_CONTROL_DIRECT, BOOT_MANAGER_NS); + /* Set boot_peripheral_ns[n:0] = 0xffffffff */ + mmio_write_32(ICFG_DMAC_CONFIG_2, BOOT_PERIPHERAL_NS); + /* Set boot_irq_ns[n:0] = 0x0000ffff */ + mmio_write_32(ICFG_DMAC_CONFIG_3, BOOT_IRQ_NS); + + /* Set DMAC stream_id */ + VERBOSE(" - configure stream_id = 0x6000\n"); + val = (DMAC_STREAM_ID << DMAC_SID_SHIFT); + mmio_write_32(ICFG_DMAC_SID_ARADDR_CONTROL, val); + mmio_write_32(ICFG_DMAC_SID_AWADDR_CONTROL, val); + + /* Reset DMAC */ + VERBOSE(" - reset dma pl330\n"); + + mmio_setbits_32(DMAC_M0_IDM_RESET_CONTROL, 0x1); + udelay(500); + + mmio_clrbits_32(DMAC_M0_IDM_RESET_CONTROL, 0x1); + udelay(500); + + INFO("dma pl330 init done\n"); +} + +static void brcm_stingray_spi_pl022_init(uintptr_t idm_reset_control) +{ + VERBOSE("spi pl022 init start\n"); + + /* Reset APB SPI bridge */ + VERBOSE(" - reset apb spi bridge\n"); + mmio_setbits_32(idm_reset_control, 0x1); + udelay(500); + + mmio_clrbits_32(idm_reset_control, 0x1); + udelay(500); + + INFO("spi pl022 init done\n"); +} + +#define CDRU_SATA_RESET_N \ + BIT(CDRU_MISC_RESET_CONTROL__CDRU_SATA_RESET_N_R) +#define CDRU_MISC_CLK_SATA \ + BIT(CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SATA_CLK_EN_R) +#define CCN_CONFIG_CLK_ENABLE (1 << 2) +#define MMU_CONFIG_CLK_ENABLE (0x3F << 16) + +#define SATA_SATA_TOP_CTRL_BUS_CTRL (SATA_BASE + 0x2044) +#define DMA_BIT_CTRL_MASK 0x003 +#define DMA_DESCR_ENDIAN_CTRL (DMA_BIT_CTRL_MASK << 0x002) +#define DMA_DATA_ENDIAN_CTRL (DMA_BIT_CTRL_MASK << 0x004) + +#define SATA_PORT_SATA3_PCB_REG8 (SATA_BASE + 0x2320) +#define SATA_PORT_SATA3_PCB_REG11 (SATA_BASE + 0x232c) +#define SATA_PORT_SATA3_PCB_BLOCK_ADDR (SATA_BASE + 0x233c) + +#define SATA3_AFE_TXRX_ACTRL 0x1d0 +/* TXDriver swing setting is 800mV */ +#define DFS_SWINGNOPE_VALUE (0x0 << 6) +#define DFS_SWINGNOPE_MASK (0x3 << 6) + +#define DFS_SWINGPE_VALUE (0x1 << 4) +#define DFS_SWINGPE_MASK (0x3 << 4) + +#define DFS_INJSTRENGTH_VALUE (0x0 << 4) +#define DFS_INJSTRENGTH_MASK (0x3 << 4) + +#define DFS_INJEN (0x1 << 3) + +#define SATA_CORE_MEM_CTRL (SATA_BASE + 0x3a08) +#define SATA_CORE_MEM_CTRL_ISO BIT(0) +#define SATA_CORE_MEM_CTRL_ARRPOWEROKIN BIT(1) +#define SATA_CORE_MEM_CTRL_ARRPOWERONIN BIT(2) +#define SATA_CORE_MEM_CTRL_POWEROKIN BIT(3) +#define SATA_CORE_MEM_CTRL_POWERONIN BIT(4) + +#define SATA0_IDM_RESET_CONTROL (SATA_BASE + 0x500800) +#define SATA_APBT0_IDM_IO_CONTROL_DIRECT (SATA_BASE + 0x51a408) +#define IO_CONTROL_DIRECT_CLK_ENABLE BIT(0) +#define SATA_APBT0_IDM_RESET_CONTROL (SATA_BASE + 0x51a800) +#define IDM_RESET_CONTROL_RESET BIT(0) + +#define NIC400_SATA_NOC_SECURITY1 0x6830000c +#define SATA_NOC_SECURITY1_FIELD 0xf +#define NIC400_SATA_NOC_SECURITY2 0x68300010 +#define SATA_NOC_SECURITY2_FIELD 0xf +#define NIC400_SATA_NOC_SECURITY3 0x68300014 +#define SATA_NOC_SECURITY3_FIELD 0x1 +#define NIC400_SATA_NOC_SECURITY4 0x68300018 +#define SATA_NOC_SECURITY4_FIELD 0x1 +#define NIC400_SATA_NOC_SECURITY5 0x6830001c +#define SATA_NOC_SECURITY5_FIELD 0xf +#define NIC400_SATA_NOC_SECURITY6 0x68300020 +#define SATA_NOC_SECURITY6_FIELD 0x1 +#define NIC400_SATA_NOC_SECURITY7 0x68300024 +#define SATA_NOC_SECURITY7_FIELD 0xf +#define NIC400_SATA_NOC_SECURITY8 0x68300028 +#define SATA_NOC_SECURITY8_FIELD 0xf +#define NIC400_SATA_NOC_SECURITY9 0x6830002c +#define SATA_NOC_SECURITY9_FIELD 0x1 + +#define SATA_APBT_IDM_PORT_REG(port, reg) \ + (((port/4) << 12) + reg) + +#define SATA_IDM_PORT_REG(port, reg) ((port << 12) + reg) + +#define SATA_PORT_REG(port, reg) \ + (((port%4) << 16) + ((port/4) << 20) + reg) + +#define MAX_SATA_PORTS 8 +#define USE_SATA_PORTS 8 + +#ifdef USE_SATA +static const uint8_t sr_b0_sata_port[MAX_SATA_PORTS] = { + 0, 1, 2, 3, 4, 5, 6, 7 +}; + +static uint32_t brcm_stingray_get_sata_port(unsigned int port) +{ + return sr_b0_sata_port[port]; +} + +static void brcm_stingray_sata_init(void) +{ + unsigned int port = 0; + uint32_t sata_port; + + mmio_setbits_32(CDRU_MISC_CLK_ENABLE_CONTROL, + CDRU_MISC_CLK_SATA); + + mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_SATA_RESET_N); + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_SATA_RESET_N); + + for (port = 0; port < USE_SATA_PORTS; port++) { + + sata_port = brcm_stingray_get_sata_port(port); + mmio_write_32(SATA_APBT_IDM_PORT_REG(sata_port, + SATA_APBT0_IDM_RESET_CONTROL), + 0x0); + mmio_setbits_32(SATA_APBT_IDM_PORT_REG(sata_port, + SATA_APBT0_IDM_IO_CONTROL_DIRECT), + IO_CONTROL_DIRECT_CLK_ENABLE); + mmio_write_32(SATA_IDM_PORT_REG(sata_port, + SATA0_IDM_RESET_CONTROL), + 0x0); + + mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL), + SATA_CORE_MEM_CTRL_ARRPOWERONIN); + mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL), + SATA_CORE_MEM_CTRL_ARRPOWEROKIN); + mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL), + SATA_CORE_MEM_CTRL_POWERONIN); + mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL), + SATA_CORE_MEM_CTRL_POWEROKIN); + mmio_clrbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL), + SATA_CORE_MEM_CTRL_ISO); + + mmio_clrbits_32(SATA_PORT_REG(sata_port, + SATA_SATA_TOP_CTRL_BUS_CTRL), + (DMA_DESCR_ENDIAN_CTRL | DMA_DATA_ENDIAN_CTRL)); + } + + mmio_setbits_32(NIC400_SATA_NOC_SECURITY1, SATA_NOC_SECURITY1_FIELD); + mmio_setbits_32(NIC400_SATA_NOC_SECURITY2, SATA_NOC_SECURITY2_FIELD); + mmio_setbits_32(NIC400_SATA_NOC_SECURITY3, SATA_NOC_SECURITY3_FIELD); + mmio_setbits_32(NIC400_SATA_NOC_SECURITY4, SATA_NOC_SECURITY4_FIELD); + mmio_setbits_32(NIC400_SATA_NOC_SECURITY5, SATA_NOC_SECURITY5_FIELD); + mmio_setbits_32(NIC400_SATA_NOC_SECURITY6, SATA_NOC_SECURITY6_FIELD); + mmio_setbits_32(NIC400_SATA_NOC_SECURITY7, SATA_NOC_SECURITY7_FIELD); + mmio_setbits_32(NIC400_SATA_NOC_SECURITY8, SATA_NOC_SECURITY8_FIELD); + mmio_setbits_32(NIC400_SATA_NOC_SECURITY9, SATA_NOC_SECURITY9_FIELD); + + INFO("sata init done\n"); +} +#else +static void poweroff_sata_pll(void) +{ + /* + * SATA subsystem is clocked by LCPLL0 which is enabled by + * default by bootrom. Poweroff the PLL if SATA is not used + */ + + /* enable isolation */ + mmio_setbits_32(CRMU_AON_CTRL1, + BIT(CRMU_AON_CTRL1__LCPLL0_ISO_IN)); + + /* Power off the SATA PLL/LDO */ + mmio_clrbits_32(CRMU_AON_CTRL1, + (BIT(CRMU_AON_CTRL1__LCPLL0_PWRON_LDO) | + BIT(CRMU_AON_CTRL1__LCPLL0_PWR_ON))); +} +#endif + +#ifdef USE_AMAC +#ifdef EMULATION_SETUP +#define ICFG_AMAC_STRAP_CONFIG (HSLS_ICFG_REGS_BASE + 0xa5c) +#define ICFG_AMAC_STRAP_DLL_BYPASS (1 << 2) +#endif +#define ICFG_AMAC_MAC_CTRL_REG (HSLS_ICFG_REGS_BASE + 0xa6c) +#define ICFG_AMAC_MAC_FULL_DUPLEX (1 << 1) +#define ICFG_AMAC_RGMII_PHY_CONFIG (HSLS_ICFG_REGS_BASE + 0xa60) +#define ICFG_AMAC_SID_CONTROL (HSLS_ICFG_REGS_BASE + 0xb10) +#define ICFG_AMAC_SID_SHIFT 5 +#define ICFG_AMAC_SID_AWADDR_OFFSET 0x0 +#define ICFG_AMAC_SID_ARADDR_OFFSET 0x4 +#define AMAC_RPHY_1000_DATARATE (1 << 20) +#define AMAC_RPHY_FULL_DUPLEX (1 << 5) +#define AMAC_RPHY_SPEED_OFFSET 2 +#define AMAC_RPHY_SPEED_MASK (7 << AMAC_RPHY_SPEED_OFFSET) +#define AMAC_RPHY_1G_SPEED (2 << AMAC_RPHY_SPEED_OFFSET) +#define ICFG_AMAC_MEM_PWR_CTRL (HSLS_ICFG_REGS_BASE + 0xa68) +#define AMAC_ISO BIT(9) +#define AMAC_STDBY BIT(8) +#define AMAC_ARRPOWEROKIN BIT(7) +#define AMAC_ARRPOWERONIN BIT(6) +#define AMAC_POWEROKIN BIT(5) +#define AMAC_POWERONIN BIT(4) + +#define AMAC_IDM0_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x4408) +#define AMAC_IDM0_ARCACHE_OFFSET 16 +#define AMAC_IDM0_AWCACHE_OFFSET 7 +#define AMAC_IDM0_ARCACHE_MASK (0xF << AMAC_IDM0_ARCACHE_OFFSET) +#define AMAC_IDM0_AWCACHE_MASK (0xF << AMAC_IDM0_AWCACHE_OFFSET) +/* ARCACHE - AWCACHE is 0xB7 for write-back no allocate */ +#define AMAC_IDM0_ARCACHE_VAL (0xb << AMAC_IDM0_ARCACHE_OFFSET) +#define AMAC_IDM0_AWCACHE_VAL (0x7 << AMAC_IDM0_AWCACHE_OFFSET) + +static void brcm_stingray_amac_init(void) +{ + unsigned int val; + uintptr_t icfg_amac_sid = ICFG_AMAC_SID_CONTROL; + + VERBOSE("amac init start\n"); + + val = SR_SID_VAL(0x3, 0x0, 0x4) << ICFG_AMAC_SID_SHIFT; + mmio_write_32(icfg_amac_sid + ICFG_AMAC_SID_AWADDR_OFFSET, val); + mmio_write_32(icfg_amac_sid + ICFG_AMAC_SID_ARADDR_OFFSET, val); + + mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ARRPOWEROKIN); + mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ARRPOWERONIN); + mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_POWEROKIN); + mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_POWERONIN); + mmio_clrbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ISO); + mmio_write_32(APBR_IDM_RESET_CONTROL, 0x0); + mmio_clrsetbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_SPEED_MASK, + AMAC_RPHY_1G_SPEED); /*1 Gbps line rate*/ + /* 1000 datarate set */ + mmio_setbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_1000_DATARATE); + /* full duplex */ + mmio_setbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_FULL_DUPLEX); +#ifdef EMULATION_SETUP + /* DLL bypass */ + mmio_setbits_32(ICFG_AMAC_STRAP_CONFIG, ICFG_AMAC_STRAP_DLL_BYPASS); +#endif + /* serdes full duplex */ + mmio_setbits_32(ICFG_AMAC_MAC_CTRL_REG, ICFG_AMAC_MAC_FULL_DUPLEX); + mmio_clrsetbits_32(AMAC_IDM0_IO_CONTROL_DIRECT, AMAC_IDM0_ARCACHE_MASK, + AMAC_IDM0_ARCACHE_VAL); + mmio_clrsetbits_32(AMAC_IDM0_IO_CONTROL_DIRECT, AMAC_IDM0_AWCACHE_MASK, + AMAC_IDM0_AWCACHE_VAL); + INFO("amac init done\n"); +} +#endif /* USE_AMAC */ + +static void brcm_stingray_pka_meminit(void) +{ + uintptr_t icfg_mem_ctrl = ICFG_PKA_MEM_PWR_CTRL; + + VERBOSE("pka meminit start\n"); + + VERBOSE(" - arrpoweron\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONOUT)) + ; + + VERBOSE(" - arrpowerok\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKOUT)) + ; + + VERBOSE(" - poweron\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_PKA_MEM_PWR_CTRL__POWERONIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_PKA_MEM_PWR_CTRL__POWERONOUT)) + ; + + VERBOSE(" - powerok\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_PKA_MEM_PWR_CTRL__POWEROKIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_PKA_MEM_PWR_CTRL__POWEROKOUT)) + ; + + /* Wait sometime */ + mdelay(1); + + VERBOSE(" - remove isolation\n"); + mmio_clrbits_32(icfg_mem_ctrl, ICFG_PKA_MEM_PWR_CTRL__ISO); + + INFO("pka meminit done\n"); +} + +static void brcm_stingray_smmu_init(void) +{ + unsigned int val; + uintptr_t smmu_base = SMMU_BASE; + + VERBOSE("smmu init start\n"); + + /* Configure SCR0 */ + VERBOSE(" - configure scr0\n"); + val = mmio_read_32(smmu_base + 0x0); + val |= (0x1 << 12); + mmio_write_32(smmu_base + 0x0, val); + + /* Reserve context banks for secure masters */ + arm_smmu_reserve_secure_cntxt(); + + /* Print configuration */ + VERBOSE(" - scr0=0x%x scr1=0x%x scr2=0x%x\n", + mmio_read_32(smmu_base + 0x0), + mmio_read_32(smmu_base + 0x4), + mmio_read_32(smmu_base + 0x8)); + + VERBOSE(" - idr0=0x%x idr1=0x%x idr2=0x%x\n", + mmio_read_32(smmu_base + 0x20), + mmio_read_32(smmu_base + 0x24), + mmio_read_32(smmu_base + 0x28)); + + VERBOSE(" - idr3=0x%x idr4=0x%x idr5=0x%x\n", + mmio_read_32(smmu_base + 0x2c), + mmio_read_32(smmu_base + 0x30), + mmio_read_32(smmu_base + 0x34)); + + VERBOSE(" - idr6=0x%x idr7=0x%x\n", + mmio_read_32(smmu_base + 0x38), + mmio_read_32(smmu_base + 0x3c)); + + INFO("smmu init done\n"); +} + +static void brcm_stingray_dma_pl330_meminit(void) +{ + uintptr_t icfg_mem_ctrl = ICFG_DMAC_MEM_PWR_CTRL; + + VERBOSE("dmac meminit start\n"); + + VERBOSE(" - arrpoweron\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONOUT)) + ; + + VERBOSE(" - arrpowerok\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKOUT)) + ; + + VERBOSE(" - poweron\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_DMAC_MEM_PWR_CTRL__POWERONIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_DMAC_MEM_PWR_CTRL__POWERONOUT)) + ; + + VERBOSE(" - powerok\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_DMAC_MEM_PWR_CTRL__POWEROKIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_DMAC_MEM_PWR_CTRL__POWEROKOUT)) + ; + + /* Wait sometime */ + mdelay(1); + + VERBOSE(" - remove isolation\n"); + mmio_clrbits_32(icfg_mem_ctrl, ICFG_DMAC_MEM_PWR_CTRL__ISO); + + INFO("dmac meminit done\n"); +} + +/* program the crmu access ranges for allowing non sec access*/ +static void brcm_stingray_crmu_access_init(void) +{ + /* Enable 0x6641c001 - 0x6641c701 for non secure access */ + mmio_write_32(CRMU_CORE_ADDR_RANGE0_LOW, 0x6641c001); + mmio_write_32(CRMU_CORE_ADDR_RANGE0_LOW + 0x4, 0x6641c701); + + /* Enable 0x6641d001 - 0x66424b01 for non secure access */ + mmio_write_32(CRMU_CORE_ADDR_RANGE1_LOW, 0x6641d001); + mmio_write_32(CRMU_CORE_ADDR_RANGE1_LOW + 0x4, 0x66424b01); + + /* Enable 0x66425001 - 0x66425f01 for non secure access */ + mmio_write_32(CRMU_CORE_ADDR_RANGE2_LOW, 0x66425001); + mmio_write_32(CRMU_CORE_ADDR_RANGE2_LOW + 0x4, 0x66425f01); + + INFO("crmu access init done\n"); +} + +static void brcm_stingray_scr_init(void) +{ + unsigned int val; + uintptr_t scr_base = SCR_BASE; + unsigned int clr_mask = SCR_AXCACHE_CONFIG_MASK; + unsigned int set_mask = SCR_TBUX_AXCACHE_CONFIG; + + VERBOSE("scr init start\n"); + + /* awdomain=0x1 and ardomain=0x1 */ + mmio_clrsetbits_32(scr_base + 0x0, clr_mask, set_mask); + val = mmio_read_32(scr_base + 0x0); + VERBOSE(" - set tbu0_config=0x%x\n", val); + + /* awdomain=0x1 and ardomain=0x1 */ + mmio_clrsetbits_32(scr_base + 0x4, clr_mask, set_mask); + val = mmio_read_32(scr_base + 0x4); + VERBOSE(" - set tbu1_config=0x%x\n", val); + + /* awdomain=0x1 and ardomain=0x1 */ + mmio_clrsetbits_32(scr_base + 0x8, clr_mask, set_mask); + val = mmio_read_32(scr_base + 0x8); + VERBOSE(" - set tbu2_config=0x%x\n", val); + + /* awdomain=0x1 and ardomain=0x1 */ + mmio_clrsetbits_32(scr_base + 0xc, clr_mask, set_mask); + val = mmio_read_32(scr_base + 0xc); + VERBOSE(" - set tbu3_config=0x%x\n", val); + + /* awdomain=0x1 and ardomain=0x1 */ + mmio_clrsetbits_32(scr_base + 0x10, clr_mask, set_mask); + val = mmio_read_32(scr_base + 0x10); + VERBOSE(" - set tbu4_config=0x%x\n", val); + + /* awdomain=0x0 and ardomain=0x0 */ + mmio_clrbits_32(scr_base + 0x14, clr_mask); + val = mmio_read_32(scr_base + 0x14); + VERBOSE(" - set gic_config=0x%x\n", val); + + INFO("scr init done\n"); +} + +static void brcm_stingray_hsls_tzpcprot_init(void) +{ + unsigned int val; + uintptr_t tzpcdecprot_base = HSLS_TZPC_BASE; + + VERBOSE("hsls tzpcprot init start\n"); + + /* Treat third-party masters as non-secured */ + val = 0; + val |= BIT(6); /* SDIO1 */ + val |= BIT(5); /* SDIO0 */ + val |= BIT(0); /* AMAC */ + mmio_write_32(tzpcdecprot_base + 0x810, val); + + /* Print TZPC decode status registers */ + VERBOSE(" - tzpcdecprot0=0x%x\n", + mmio_read_32(tzpcdecprot_base + 0x800)); + + VERBOSE(" - tzpcdecprot1=0x%x\n", + mmio_read_32(tzpcdecprot_base + 0x80c)); + + INFO("hsls tzpcprot init done\n"); +} + +#ifdef USE_I2S +#define ICFG_AUDIO_POWER_CTRL (HSLS_ICFG_REGS_BASE + 0xaa8) +#define ICFG_AUDIO_POWER_CTRL__POWERONIN BIT(0) +#define ICFG_AUDIO_POWER_CTRL__POWEROKIN BIT(1) +#define ICFG_AUDIO_POWER_CTRL__ARRPOWERONIN BIT(2) +#define ICFG_AUDIO_POWER_CTRL__ARRPOWEROKIN BIT(3) +#define ICFG_AUDIO_POWER_CTRL__POWERONOUT BIT(4) +#define ICFG_AUDIO_POWER_CTRL__POWEROKOUT BIT(5) +#define ICFG_AUDIO_POWER_CTRL__ARRPOWERONOUT BIT(6) +#define ICFG_AUDIO_POWER_CTRL__ARRPOWEROKOUT BIT(7) +#define ICFG_AUDIO_POWER_CTRL__ISO BIT(8) +#define ICFG_AUDIO_SID_CONTROL (HSLS_ICFG_REGS_BASE + 0xaf8) +#define ICFG_AUDIO_SID_SHIFT 5 +#define ICFG_AUDIO_SID_AWADDR_OFFSET 0x0 +#define ICFG_AUDIO_SID_ARADDR_OFFSET 0x4 + +#define I2S_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0x1800) +#define I2S_IDM_IO_CONTROL (HSLS_IDM_REGS_BASE + 0x1408) +#define IO_CONTROL_CLK_ENABLE BIT(0) +#define I2S_IDM0_ARCACHE_OFFSET 16 +#define I2S_IDM0_AWCACHE_OFFSET 20 +#define I2S_IDM0_ARCACHE_MASK (0xF << I2S_IDM0_ARCACHE_OFFSET) +#define I2S_IDM0_AWCACHE_MASK (0xF << I2S_IDM0_AWCACHE_OFFSET) +/* ARCACHE - AWCACHE is 0x22 Normal Non-cacheable Non-bufferable. */ +#define I2S_IDM0_ARCACHE_VAL (0x2 << I2S_IDM0_ARCACHE_OFFSET) +#define I2S_IDM0_AWCACHE_VAL (0x2 << I2S_IDM0_AWCACHE_OFFSET) + +static void brcm_stingray_audio_init(void) +{ + unsigned int val; + uintptr_t icfg_mem_ctrl = ICFG_AUDIO_POWER_CTRL; + uintptr_t icfg_audio_sid = ICFG_AUDIO_SID_CONTROL; + + mmio_write_32(I2S_RESET_CONTROL, 0x0); + + mmio_clrsetbits_32(I2S_IDM_IO_CONTROL, I2S_IDM0_ARCACHE_MASK, + I2S_IDM0_ARCACHE_VAL); + + mmio_clrsetbits_32(I2S_IDM_IO_CONTROL, I2S_IDM0_AWCACHE_MASK, + I2S_IDM0_AWCACHE_VAL); + + mmio_setbits_32(I2S_IDM_IO_CONTROL, IO_CONTROL_CLK_ENABLE); + + VERBOSE("audio meminit start\n"); + + VERBOSE(" - configure stream_id = 0x6001\n"); + val = SR_SID_VAL(0x3, 0x0, 0x1) << ICFG_AUDIO_SID_SHIFT; + mmio_write_32(icfg_audio_sid + ICFG_AUDIO_SID_AWADDR_OFFSET, val); + mmio_write_32(icfg_audio_sid + ICFG_AUDIO_SID_ARADDR_OFFSET, val); + + VERBOSE(" - arrpoweron\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_AUDIO_POWER_CTRL__ARRPOWERONIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_AUDIO_POWER_CTRL__ARRPOWERONOUT)) + ; + + VERBOSE(" - arrpowerok\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_AUDIO_POWER_CTRL__ARRPOWEROKIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_AUDIO_POWER_CTRL__ARRPOWEROKOUT)) + ; + + VERBOSE(" - poweron\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_AUDIO_POWER_CTRL__POWERONIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_AUDIO_POWER_CTRL__POWERONOUT)) + ; + + VERBOSE(" - powerok\n"); + mmio_setbits_32(icfg_mem_ctrl, + ICFG_AUDIO_POWER_CTRL__POWEROKIN); + while (!(mmio_read_32(icfg_mem_ctrl) & + ICFG_AUDIO_POWER_CTRL__POWEROKOUT)) + ; + + /* Wait sometime */ + mdelay(1); + + VERBOSE(" - remove isolation\n"); + mmio_clrbits_32(icfg_mem_ctrl, ICFG_AUDIO_POWER_CTRL__ISO); + + INFO("audio meminit done\n"); +} +#endif /* USE_I2S */ + +/* + * These defines do not match the regfile but they are renamed in a way such + * that they are much more readible + */ + +#define SCR_GPV_SMMU_NS (SCR_GPV_BASE + 0x28) +#define SCR_GPV_GIC500_NS (SCR_GPV_BASE + 0x34) +#define HSLS_GPV_NOR_S0_NS (HSLS_GPV_BASE + 0x14) +#define HSLS_GPV_IDM1_NS (HSLS_GPV_BASE + 0x18) +#define HSLS_GPV_IDM2_NS (HSLS_GPV_BASE + 0x1c) +#define HSLS_SDIO0_SLAVE_NS (HSLS_GPV_BASE + 0x20) +#define HSLS_SDIO1_SLAVE_NS (HSLS_GPV_BASE + 0x24) +#define HSLS_GPV_APBY_NS (HSLS_GPV_BASE + 0x2c) +#define HSLS_GPV_APBZ_NS (HSLS_GPV_BASE + 0x30) +#define HSLS_GPV_APBX_NS (HSLS_GPV_BASE + 0x34) +#define HSLS_GPV_APBS_NS (HSLS_GPV_BASE + 0x38) +#define HSLS_GPV_QSPI_S0_NS (HSLS_GPV_BASE + 0x68) +#define HSLS_GPV_APBR_NS (HSLS_GPV_BASE + 0x6c) +#define FS4_CRYPTO_GPV_RM_SLAVE_NS (FS4_CRYPTO_GPV_BASE + 0x8) +#define FS4_CRYPTO_GPV_APB_SWITCH_NS (FS4_CRYPTO_GPV_BASE + 0xc) +#define FS4_RAID_GPV_RM_SLAVE_NS (FS4_RAID_GPV_BASE + 0x8) +#define FS4_RAID_GPV_APB_SWITCH_NS (FS4_RAID_GPV_BASE + 0xc) +#define FS4_CRYPTO_IDM_NS (NIC400_FS_NOC_ROOT + 0x1c) +#define FS4_RAID_IDM_NS (NIC400_FS_NOC_ROOT + 0x28) + +#define FS4_CRYPTO_RING_COUNT 32 +#define FS4_CRYPTO_DME_COUNT 10 +#define FS4_CRYPTO_AE_COUNT 10 +#define FS4_CRYPTO_START_STREAM_ID 0x4000 +#define FS4_CRYPTO_MSI_DEVICE_ID 0x4100 + +#define FS4_RAID_RING_COUNT 32 +#define FS4_RAID_DME_COUNT 8 +#define FS4_RAID_AE_COUNT 8 +#define FS4_RAID_START_STREAM_ID 0x4200 +#define FS4_RAID_MSI_DEVICE_ID 0x4300 + +#define FS6_PKI_AXI_SLAVE_NS \ + (NIC400_FS_NOC_ROOT + NIC400_FS_NOC_SECURITY2_OFFSET) + +#define FS6_PKI_AE_DME_APB_NS \ + (NIC400_FS_NOC_ROOT + NIC400_FS_NOC_SECURITY7_OFFSET) +#define FS6_PKI_IDM_IO_CONTROL_DIRECT 0x0 +#define FS6_PKI_IDM_RESET_CONTROL 0x0 +#define FS6_PKI_RING_COUNT 32 +#define FS6_PKI_DME_COUNT 1 +#define FS6_PKI_AE_COUNT 4 +#define FS6_PKI_START_STREAM_ID 0x4000 +#define FS6_PKI_MSI_DEVICE_ID 0x4100 + +static void brcm_stingray_security_init(void) +{ + unsigned int val; + + val = mmio_read_32(SCR_GPV_SMMU_NS); + val |= BIT(0); /* SMMU NS = 1 */ + mmio_write_32(SCR_GPV_SMMU_NS, val); + + val = mmio_read_32(SCR_GPV_GIC500_NS); + val |= BIT(0); /* GIC-500 NS = 1 */ + mmio_write_32(SCR_GPV_GIC500_NS, val); + + val = mmio_read_32(HSLS_GPV_NOR_S0_NS); + val |= BIT(0); /* NOR SLAVE NS = 1 */ + mmio_write_32(HSLS_GPV_NOR_S0_NS, val); + + val = mmio_read_32(HSLS_GPV_IDM1_NS); + val |= BIT(0); /* DMA IDM NS = 1 */ + val |= BIT(1); /* I2S IDM NS = 1 */ + val |= BIT(2); /* AMAC IDM NS = 1 */ + val |= BIT(3); /* SDIO0 IDM NS = 1 */ + val |= BIT(4); /* SDIO1 IDM NS = 1 */ + val |= BIT(5); /* DS_3 IDM NS = 1 */ + mmio_write_32(HSLS_GPV_IDM1_NS, val); + + val = mmio_read_32(HSLS_GPV_IDM2_NS); + val |= BIT(2); /* QSPI IDM NS = 1 */ + val |= BIT(1); /* NOR IDM NS = 1 */ + val |= BIT(0); /* NAND IDM NS = 1 */ + mmio_write_32(HSLS_GPV_IDM2_NS, val); + + val = mmio_read_32(HSLS_GPV_APBY_NS); + val |= BIT(10); /* I2S NS = 1 */ + val |= BIT(4); /* IOPAD NS = 1 */ + val |= 0xf; /* UARTx NS = 1 */ + mmio_write_32(HSLS_GPV_APBY_NS, val); + + val = mmio_read_32(HSLS_GPV_APBZ_NS); + val |= BIT(2); /* RNG NS = 1 */ + mmio_write_32(HSLS_GPV_APBZ_NS, val); + + val = mmio_read_32(HSLS_GPV_APBS_NS); + val |= 0x3; /* SPIx NS = 1 */ + mmio_write_32(HSLS_GPV_APBS_NS, val); + + val = mmio_read_32(HSLS_GPV_APBR_NS); + val |= BIT(7); /* QSPI APB NS = 1 */ + val |= BIT(6); /* NAND APB NS = 1 */ + val |= BIT(5); /* NOR APB NS = 1 */ + val |= BIT(4); /* AMAC APB NS = 1 */ + val |= BIT(1); /* DMA S1 APB NS = 1 */ + mmio_write_32(HSLS_GPV_APBR_NS, val); + + val = mmio_read_32(HSLS_SDIO0_SLAVE_NS); + val |= BIT(0); /* SDIO0 NS = 1 */ + mmio_write_32(HSLS_SDIO0_SLAVE_NS, val); + + val = mmio_read_32(HSLS_SDIO1_SLAVE_NS); + val |= BIT(0); /* SDIO1 NS = 1 */ + mmio_write_32(HSLS_SDIO1_SLAVE_NS, val); + + val = mmio_read_32(HSLS_GPV_APBX_NS); + val |= BIT(14); /* SMBUS1 NS = 1 */ + val |= BIT(13); /* GPIO NS = 1 */ + val |= BIT(12); /* WDT NS = 1 */ + val |= BIT(11); /* SMBUS0 NS = 1 */ + val |= BIT(10); /* Timer7 NS = 1 */ + val |= BIT(9); /* Timer6 NS = 1 */ + val |= BIT(8); /* Timer5 NS = 1 */ + val |= BIT(7); /* Timer4 NS = 1 */ + val |= BIT(6); /* Timer3 NS = 1 */ + val |= BIT(5); /* Timer2 NS = 1 */ + val |= BIT(4); /* Timer1 NS = 1 */ + val |= BIT(3); /* Timer0 NS = 1 */ + val |= BIT(2); /* MDIO NS = 1 */ + val |= BIT(1); /* PWM NS = 1 */ + mmio_write_32(HSLS_GPV_APBX_NS, val); + + val = mmio_read_32(HSLS_GPV_QSPI_S0_NS); + val |= BIT(0); /* QSPI NS = 1 */ + mmio_write_32(HSLS_GPV_QSPI_S0_NS, val); + +#ifdef USE_FS4 + val = 0x1; /* FS4 Crypto rm_slave */ + mmio_write_32(FS4_CRYPTO_GPV_RM_SLAVE_NS, val); + val = 0x1; /* FS4 Crypto apb_switch */ + mmio_write_32(FS4_CRYPTO_GPV_APB_SWITCH_NS, val); + + val = 0x1; /* FS4 Raid rm_slave */ + mmio_write_32(FS4_RAID_GPV_RM_SLAVE_NS, val); + val = 0x1; /* FS4 Raid apb_switch */ + mmio_write_32(FS4_RAID_GPV_APB_SWITCH_NS, val); + + val = 0x1; /* FS4 Crypto IDM */ + mmio_write_32(FS4_CRYPTO_IDM_NS, val); + val = 0x1; /* FS4 RAID IDM */ + mmio_write_32(FS4_RAID_IDM_NS, val); +#endif + +#ifdef BL31_CCN_NONSECURE + /* Enable non-secure access to CCN registers */ + mmio_write_32(OLY_MN_REGISTERS_NODE0_SECURE_ACCESS, 0x1); +#endif + +#ifdef DDR_CTRL_PHY_NONSECURE + mmio_write_32(SCR_NOC_DDR_REGISTER_ACCESS, 0x1); +#endif + + paxc_mhb_ns_init(); + + /* unlock scr idm for non secure access */ + mmio_write_32(SCR_NOC_SECURITY0, 0xffffffff); + + INFO("security init done\r\n"); +} + +void brcm_gpio_pad_ns_init(void) +{ + /* configure all GPIO pads for non secure world access*/ + mmio_write_32(GPIO_S_CNTRL_REG, 0xffffffff); /* 128-140 gpio pads */ + mmio_write_32(GPIO_S_CNTRL_REG + 0x4, 0xffffffff); /* 96-127 gpio pad */ + mmio_write_32(GPIO_S_CNTRL_REG + 0x8, 0xffffffff); /* 64-95 gpio pad */ + mmio_write_32(GPIO_S_CNTRL_REG + 0xc, 0xffffffff); /* 32-63 gpio pad */ + mmio_write_32(GPIO_S_CNTRL_REG + 0x10, 0xffffffff); /* 0-31 gpio pad */ +} + +#ifndef USE_DDR +static void brcm_stingray_sram_ns_init(void) +{ + uintptr_t sram_root = TZC400_FS_SRAM_ROOT; + uintptr_t noc_root = NIC400_FS_NOC_ROOT; + + mmio_write_32(sram_root + GATE_KEEPER_OFFSET, 1); + mmio_write_32(sram_root + REGION_ATTRIBUTES_0_OFFSET, 0xc0000000); + mmio_write_32(sram_root + REGION_ID_ACCESS_0_OFFSET, 0x00010001); + mmio_write_32(noc_root + NIC400_FS_NOC_SECURITY4_OFFSET, 0x1); + INFO(" stingray sram ns init done.\n"); +} +#endif + +static void ccn_pre_init(void) +{ + /* + * Set WFC bit of RN-I nodes where FS4 is connected. + * This is required inorder to wait for read/write requests + * completion acknowledgment. Otherwise FS4 Ring Manager is + * getting stale data because of re-ordering of read/write + * requests at CCN level + */ + mmio_setbits_32(OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL, + OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WFC); +} + +static void ccn_post_init(void) +{ + mmio_setbits_32(OLY_HNI_REGISTERS_NODE0_PCIERC_RNI_NODEID_LIST, + SRP_RNI_PCIE_CONNECTED); + mmio_setbits_32(OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL, + SA_AUX_CTL_SER_DEVNE_WR); + + mmio_clrbits_32(OLY_HNI_REGISTERS_NODE0_POS_CONTROL, + POS_CONTROL_HNI_POS_EN); + mmio_clrbits_32(OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL, + SA_AUX_CTL_POS_EARLY_WR_COMP_EN); +} + +#ifndef BL31_BOOT_PRELOADED_SCP +static void crmu_init(void) +{ + /* + * Configure CRMU for using SMMU + */ + + /*Program CRMU Stream ID */ + mmio_write_32(CRMU_MASTER_AXI_ARUSER_CONFIG, + (CRMU_STREAM_ID << CRMU_SID_SHIFT)); + mmio_write_32(CRMU_MASTER_AXI_AWUSER_CONFIG, + (CRMU_STREAM_ID << CRMU_SID_SHIFT)); + + /* Create Identity mapping */ + arm_smmu_create_identity_map(DOMAIN_CRMU); + + /* Enable Client Port for Secure Masters*/ + arm_smmu_enable_secure_client_port(); +} +#endif + +static void brcm_fsx_init(void) +{ +#if defined(USE_FS4) && defined(USE_FS6) + #error "USE_FS4 and USE_FS6 should not be used together" +#endif + +#ifdef USE_FS4 + fsx_init(eFS4_CRYPTO, FS4_CRYPTO_RING_COUNT, FS4_CRYPTO_DME_COUNT, + FS4_CRYPTO_AE_COUNT, FS4_CRYPTO_START_STREAM_ID, + FS4_CRYPTO_MSI_DEVICE_ID, FS4_CRYPTO_IDM_IO_CONTROL_DIRECT, + FS4_CRYPTO_IDM_RESET_CONTROL, FS4_CRYPTO_BASE, + FS4_CRYPTO_DME_BASE); + + fsx_init(eFS4_RAID, FS4_RAID_RING_COUNT, FS4_RAID_DME_COUNT, + FS4_RAID_AE_COUNT, FS4_RAID_START_STREAM_ID, + FS4_RAID_MSI_DEVICE_ID, FS4_RAID_IDM_IO_CONTROL_DIRECT, + FS4_RAID_IDM_RESET_CONTROL, FS4_RAID_BASE, + FS4_RAID_DME_BASE); + + fsx_meminit("raid", + FS4_RAID_IDM_IO_CONTROL_DIRECT, + FS4_RAID_IDM_IO_STATUS); +#endif +} + +static void bcm_bl33_pass_info(void) +{ + struct bl33_info *info = (struct bl33_info *)BL33_SHARED_DDR_BASE; + + if (sizeof(*info) > BL33_SHARED_DDR_SIZE) + WARN("bl33 shared area not reserved\n"); + + info->version = BL33_INFO_VERSION; + info->chip.chip_id = PLAT_CHIP_ID_GET; + info->chip.rev_id = PLAT_CHIP_REV_GET; +} + +DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, CORTEX_A72_L2CTLR_EL1) + +void plat_bcm_bl31_early_platform_setup(void *from_bl2, + bl_params_t *plat_params_from_bl2) +{ +#ifdef BL31_BOOT_PRELOADED_SCP + image_info_t scp_image_info; + + scp_image_info.image_base = PRELOADED_SCP_BASE; + scp_image_info.image_size = PRELOADED_SCP_SIZE; + plat_bcm_bl2_plat_handle_scp_bl2(&scp_image_info); +#endif + /* + * In BL31, logs are saved to DDR and we have much larger space to + * store logs. We can now afford to save all logs >= the 'INFO' level + */ + bcm_elog_init((void *)BCM_ELOG_BL31_BASE, BCM_ELOG_BL31_SIZE, + LOG_LEVEL_INFO); + + INFO("L2CTLR = 0x%lx\n", read_l2ctlr_el1()); + + brcm_timer_sync_init(); + + brcm_stingray_dma_pl330_init(); + + brcm_stingray_dma_pl330_meminit(); + + brcm_stingray_spi_pl022_init(APBS_IDM_IDM_RESET_CONTROL); + +#ifdef USE_AMAC + brcm_stingray_amac_init(); +#endif + + brcm_stingray_sdio_init(); + +#ifdef NCSI_IO_DRIVE_STRENGTH_MA + brcm_stingray_ncsi_init(); +#endif + +#ifdef USE_USB + xhci_phy_init(); +#endif + +#ifdef USE_SATA + brcm_stingray_sata_init(); +#else + poweroff_sata_pll(); +#endif + + ccn_pre_init(); + + brcm_fsx_init(); + + brcm_stingray_smmu_init(); + + brcm_stingray_pka_meminit(); + + brcm_stingray_crmu_access_init(); + + brcm_stingray_scr_init(); + + brcm_stingray_hsls_tzpcprot_init(); + +#ifdef USE_I2S + brcm_stingray_audio_init(); +#endif + + ccn_post_init(); + + paxb_init(); + + paxc_init(); + +#ifndef BL31_BOOT_PRELOADED_SCP + crmu_init(); +#endif + + /* Note: this should be last thing because + * FS4 GPV registers only work after FS4 block + * (i.e. crypto,raid,cop) is out of reset. + */ + brcm_stingray_security_init(); + + brcm_gpio_pad_ns_init(); + +#ifndef USE_DDR + brcm_stingray_sram_ns_init(); +#endif + +#ifdef BL31_FORCE_CPU_FULL_FREQ + bcm_set_ihost_pll_freq(0x0, PLL_FREQ_FULL); +#endif + + brcm_stingray_gain_qspi_control(); + +#ifdef USE_PAXC + /* + * Check that the handshake has occurred and report ChiMP status. + * This is required. Otherwise (especially on Palladium) + * Linux might have booted to the pcie stage whereas + * ChiMP has not yet booted. Note that nic_mode case has already + * been considered above. + */ + if ((boot_source_get() != BOOT_SOURCE_QSPI) && + (!bcm_chimp_is_nic_mode()) && + (!bcm_chimp_wait_handshake()) + ) { + /* Does ChiMP report an error ? */ + uint32_t err; + + err = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG); + if ((err & CHIMP_ERROR_MASK) == 0) + /* ChiMP has not booted yet, but no error reported */ + WARN("ChiMP not booted yet, but no error reported.\n"); + } + +#if DEBUG + if (boot_source_get() != BOOT_SOURCE_QSPI) + INFO("Current ChiMP Status: 0x%x; bpe_mod reg: 0x%x\n" + "fastboot register: 0x%x; handshake register 0x%x\n", + bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG), + bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG), + bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG), + bcm_chimp_read(CHIMP_REG_ECO_RESERVED)); +#endif /* DEBUG */ +#endif + +#ifdef FS4_DISABLE_CLOCK + flush_dcache_range( + PLAT_BRCM_TRUSTED_SRAM_BASE, + PLAT_BRCM_TRUSTED_SRAM_SIZE); + fs4_disable_clocks(true, true, true); +#endif + + /* pass information to BL33 through shared DDR region */ + bcm_bl33_pass_info(); + + /* + * We are not yet at the end of BL31, but we can stop log here so we do + * not need to add 'bcm_elog_exit' to the standard BL31 code. The + * benefit of capturing BL31 logs after this is very minimal in a + * production system + */ + bcm_elog_exit(); + +#if !BRCM_DISABLE_TRUSTED_WDOG + /* + * Secure watchdog was started earlier in BL2, now it's time to stop + * it + */ + sp805_stop(ARM_SP805_TWDG_BASE); +#endif +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c new file mode 100644 index 0000000..5e07fac --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "m0_cfg.h" + + +#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL2]) + +#define VENDOR_RST_TYPE_SHIFT 4 + +#if HW_ASSISTED_COHERENCY +/* + * On systems where participant CPUs are cache-coherent, we can use spinlocks + * instead of bakery locks. + */ +spinlock_t event_lock; +#define event_lock_get(_lock) spin_lock(&_lock) +#define event_lock_release(_lock) spin_unlock(&_lock) + +#else +/* + * Use bakery locks for state coordination as not all participants are + * cache coherent now. + */ +DEFINE_BAKERY_LOCK(event_lock); +#define event_lock_get(_lock) bakery_lock_get(&_lock) +#define event_lock_release(_lock) bakery_lock_release(&_lock) +#endif + +static int brcm_pwr_domain_on(u_register_t mpidr) +{ + /* + * SCP takes care of powering up parent power domains so we + * only need to care about level 0 + */ + scpi_set_brcm_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Handler called when a power level has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. This handler would never be invoked with + * the system power domain uninitialized as either the primary would have taken + * care of it as part of cold boot or the first core awakened from system + * suspend would have already initialized it. + ******************************************************************************/ +static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr()); + + /* Assert that the system power domain need not be initialized */ + assert(SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_RUN); + + assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF); + + /* + * Perform the common cluster specific operations i.e enable coherency + * if this cluster was off. + */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) { + INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id); + ccn_enter_snoop_dvm_domain(1 << cluster_id); + } + + /* Program the gic per-cpu distributor or re-distributor interface */ + plat_brcm_gic_pcpu_init(); + + /* Enable the gic cpu interface */ + plat_brcm_gic_cpuif_enable(); +} + +static void brcm_power_down_common(void) +{ + unsigned int standbywfil2, standbywfi; + uint64_t mpidr = read_mpidr_el1(); + + switch (MPIDR_AFFLVL1_VAL(mpidr)) { + case 0x0: + standbywfi = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI; + standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2; + break; + case 0x1: + standbywfi = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI; + standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2; + break; + case 0x2: + standbywfi = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI; + standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2; + break; + case 0x3: + standbywfi = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI; + standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2; + break; + default: + ERROR("Invalid cluster #%" PRIx64 "\n", MPIDR_AFFLVL1_VAL(mpidr)); + return; + } + /* Clear the WFI status bit */ + event_lock_get(event_lock); + mmio_setbits_32(CDRU_PROC_EVENT_CLEAR, + (1 << (standbywfi + MPIDR_AFFLVL0_VAL(mpidr))) | + (1 << standbywfil2)); + event_lock_release(event_lock); +} + +/* + * Helper function to inform power down state to SCP. + */ +static void brcm_scp_suspend(const psci_power_state_t *target_state) +{ + uint32_t cluster_state = scpi_power_on; + uint32_t system_state = scpi_power_on; + + /* Check if power down at system power domain level is requested */ + if (SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) + system_state = scpi_power_retention; + + /* Check if Cluster is to be turned off */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) + cluster_state = scpi_power_off; + + /* + * Ask the SCP to power down the appropriate components depending upon + * their state. + */ + scpi_set_brcm_power_state(read_mpidr_el1(), + scpi_power_off, + cluster_state, + system_state); +} + +/* + * Helper function to turn off a CPU power domain and its parent power domains + * if applicable. Since SCPI doesn't differentiate between OFF and suspend, we + * call the suspend helper here. + */ +static void brcm_scp_off(const psci_power_state_t *target_state) +{ + brcm_scp_suspend(target_state); +} + +static void brcm_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr_el1()); + + assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF); + /* Prevent interrupts from spuriously waking up this cpu */ + plat_brcm_gic_cpuif_disable(); + + /* Turn redistributor off */ + plat_brcm_gic_redistif_off(); + + /* If Cluster is to be turned off, disable coherency */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) + ccn_exit_snoop_dvm_domain(1 << cluster_id); + + brcm_power_down_common(); + + brcm_scp_off(target_state); +} + +/******************************************************************************* + * Handler called when the CPU power domain is about to enter standby. + ******************************************************************************/ +static void brcm_cpu_standby(plat_local_state_t cpu_state) +{ + unsigned int scr; + + assert(cpu_state == PLAT_LOCAL_STATE_RET); + + scr = read_scr_el3(); + /* + * Enable the Non secure interrupt to wake the CPU. + * In GICv3 affinity routing mode, the non secure group1 interrupts use + * the PhysicalFIQ at EL3 whereas in GICv2, it uses the PhysicalIRQ. + * Enabling both the bits works for both GICv2 mode and GICv3 affinity + * routing mode. + */ + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + isb(); + dsb(); + wfi(); + + /* + * Restore SCR to the original value, synchronisation of scr_el3 is + * done by eret while el3_exit to save some execution cycles. + */ + write_scr_el3(scr); +} + +/* + * Helper function to shutdown the system via SCPI. + */ +static void __dead2 brcm_scp_sys_shutdown(void) +{ + /* + * Disable GIC CPU interface to prevent pending interrupt + * from waking up the AP from WFI. + */ + plat_brcm_gic_cpuif_disable(); + + /* Flush and invalidate data cache */ + dcsw_op_all(DCCISW); + + /* Bring Cluster out of coherency domain as its going to die */ + plat_brcm_interconnect_exit_coherency(); + + brcm_power_down_common(); + + /* Send the power down request to the SCP */ + scpi_sys_power_state(scpi_system_shutdown); + + wfi(); + ERROR("BRCM System Off: operation not handled.\n"); + panic(); +} + +/* + * Helper function to reset the system + */ +static void __dead2 brcm_scp_sys_reset(unsigned int reset_type) +{ + /* + * Disable GIC CPU interface to prevent pending interrupt + * from waking up the AP from WFI. + */ + plat_brcm_gic_cpuif_disable(); + + /* Flush and invalidate data cache */ + dcsw_op_all(DCCISW); + + /* Bring Cluster out of coherency domain as its going to die */ + plat_brcm_interconnect_exit_coherency(); + + brcm_power_down_common(); + + /* Send the system reset request to the SCP + * + * As per PSCI spec system power state could be + * 0-> Shutdown + * 1-> Reboot- Board level Reset + * 2-> Reset - SoC level Reset + * + * Spec allocates 8 bits, 2 nibble, for this. One nibble is sufficient + * for sending the state hence We are utilizing 2nd nibble for vendor + * define reset type. + */ + scpi_sys_power_state((reset_type << VENDOR_RST_TYPE_SHIFT) | + scpi_system_reboot); + + wfi(); + ERROR("BRCM System Reset: operation not handled.\n"); + panic(); +} + +static void __dead2 brcm_system_reset(void) +{ + unsigned int reset_type; + + if (bcm_chimp_is_nic_mode()) + reset_type = SOFT_RESET_L3; + else + reset_type = SOFT_SYS_RESET_L1; + + brcm_scp_sys_reset(reset_type); +} + +static int brcm_system_reset2(int is_vendor, int reset_type, + u_register_t cookie) +{ + if (!is_vendor) { + /* Architectural warm boot: only warm reset is supported */ + reset_type = SOFT_RESET_L3; + } else { + uint32_t boot_source = (uint32_t)cookie; + + boot_source &= BOOT_SOURCE_MASK; + brcm_stingray_set_straps(boot_source); + } + brcm_scp_sys_reset(reset_type); + + /* + * brcm_scp_sys_reset cannot return (it is a __dead function), + * but brcm_system_reset2 has to return some value, even in + * this case. + */ + return 0; +} + +static int brcm_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint >= BRCM_NS_DRAM1_BASE) && + (entrypoint < (BRCM_NS_DRAM1_BASE + BRCM_NS_DRAM1_SIZE))) + return PSCI_E_SUCCESS; +#ifdef __aarch64__ + if ((entrypoint >= BRCM_DRAM2_BASE) && + (entrypoint < (BRCM_DRAM2_BASE + BRCM_DRAM2_SIZE))) + return PSCI_E_SUCCESS; + + if ((entrypoint >= BRCM_DRAM3_BASE) && + (entrypoint < (BRCM_DRAM3_BASE + BRCM_DRAM3_SIZE))) + return PSCI_E_SUCCESS; +#endif + + return PSCI_E_INVALID_ADDRESS; +} + +/******************************************************************************* + * ARM standard platform handler called to check the validity of the power state + * parameter. + ******************************************************************************/ +static int brcm_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pstate = psci_get_pstate_type(power_state); + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MPIDR_AFFLVL0] = + PLAT_LOCAL_STATE_RET; + } else { + for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + PLAT_LOCAL_STATE_OFF; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard + * platform will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t plat_brcm_psci_pm_ops = { + .pwr_domain_on = brcm_pwr_domain_on, + .pwr_domain_on_finish = brcm_pwr_domain_on_finish, + .pwr_domain_off = brcm_pwr_domain_off, + .cpu_standby = brcm_cpu_standby, + .system_off = brcm_scp_sys_shutdown, + .system_reset = brcm_system_reset, + .system_reset2 = brcm_system_reset2, + .validate_ns_entrypoint = brcm_validate_ns_entrypoint, + .validate_power_state = brcm_validate_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + *psci_ops = &plat_brcm_psci_pm_ops; + + /* Setup mailbox with entry point. */ + mmio_write_64(CRMU_CFG_BASE + offsetof(M0CFG, core_cfg.rvbar), + sec_entrypoint); + + return 0; +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c new file mode 100644 index 0000000..5725a2e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN 0 + +#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON 11 +#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK 12 +#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON 13 +#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK 14 +#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO 15 +#define FS4_IDM_IO_CONTROL_DIRECT__CLK_EN 31 + +#define FS4_IDM_IO_STATUS__MEM_POWERON 0 +#define FS4_IDM_IO_STATUS__MEM_POWEROK 1 +#define FS4_IDM_IO_STATUS__MEM_ARRPOWERON 2 +#define FS4_IDM_IO_STATUS__MEM_ARRPOWEROK 3 +#define FS4_IDM_IO_STATUS__MEM_ALLOK 0xf + +#define FS4_IDM_RESET_CONTROL__RESET 0 + +#define FSX_RINGx_BASE(__b, __i) \ + ((__b) + (__i) * 0x10000) + +#define FSX_RINGx_VERSION_NUMBER(__b, __i) \ + (FSX_RINGx_BASE(__b, __i) + 0x0) + +#define FSX_RINGx_MSI_DEV_ID(__b, __i) \ + (FSX_RINGx_BASE(__b, __i) + 0x44) + +#define FSX_COMM_RINGx_BASE(__b, __i) \ + ((__b) + 0x200000 + (__i) * 0x100) + +#define FSX_COMM_RINGx_CONTROL(__b, __i) \ + (FSX_COMM_RINGx_BASE(__b, __i) + 0x0) +#define FSX_COMM_RINGx_CONTROL__AXI_ID 8 +#define FSX_COMM_RINGx_CONTROL__AXI_ID_MASK 0x1f +#define FSX_COMM_RINGx_CONTROL__PRIORITY 4 +#define FSX_COMM_RINGx_CONTROL__PRIORITY_MASK 0x7 +#define FSX_COMM_RINGx_CONTROL__AE_GROUP 0 +#define FSX_COMM_RINGx_CONTROL__AE_GROUP_MASK 0x7 + +#define FSX_COMM_RINGx_MSI_DEV_ID(__b, __i) \ + (FSX_COMM_RINGx_BASE(__b, __i) + 0x4) + +#define FSX_AEx_BASE(__b, __i) \ + ((__b) + 0x202000 + (__i) * 0x100) + +#define FSX_AEx_CONTROL_REGISTER(__b, __i) \ + (FSX_AEx_BASE(__b, __i) + 0x0) +#define FSX_AEx_CONTROL_REGISTER__ACTIVE 4 +#define FSX_AEx_CONTROL_REGISTER__GROUP_ID 0 +#define FSX_AEx_CONTROL_REGISTER__GROUP_ID_MASK 0x7 + +#define FSX_COMM_RM_RING_SECURITY_SETTING 0x0 + +#define FSX_COMM_RM_SSID_CONTROL 0x4 +#define FSX_COMM_RM_SSID_CONTROL__RING_BITS 5 +#define FSX_COMM_RM_SSID_CONTROL__MASK 0x3ff + +#define FSX_COMM_RM_CONTROL_REGISTER 0x8 +#define FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE 2 +#define FSX_COMM_RM_CONTROL_REGISTER__AE_TIMEOUT 5 +#define FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING 7 + +#define FSX_COMM_RM_TIMER_CONTROL_0 0xc +#define FSX_COMM_RM_TIMER_CONTROL_0__FAST 16 +#define FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM 0 + +#define FSX_COMM_RM_TIMER_CONTROL_1 0x10 +#define FSX_COMM_RM_TIMER_CONTROL_1__SLOW 16 +#define FSX_COMM_RM_TIMER_CONTROL_1__IDLE 0 + +#define FSX_COMM_RM_BURST_BD_THRESHOLD 0x14 +#define FSX_COMM_RM_BURST_BD_THRESHOLD_LOW 0 +#define FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH 16 + +#define FSX_COMM_RM_BURST_LENGTH 0x18 +#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN 16 +#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN_MASK 0x1ff +#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE 0 +#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE_MASK 0x1ff + +#define FSX_COMM_RM_FIFO_THRESHOLD 0x1c +#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL 16 +#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL_MASK 0x1ff +#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL 0 +#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL_MASK 0x1f + +#define FSX_COMM_RM_AE_TIMEOUT 0x24 + +#define FSX_COMM_RM_RING_FLUSH_TIMEOUT 0x2c + +#define FSX_COMM_RM_MEMORY_CONFIGURATION 0x30 +#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN 12 +#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN 13 +#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN 14 +#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN 15 + +#define FSX_COMM_RM_AXI_CONTROL 0x34 +#define FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN 28 +#define FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN 24 +#define FSX_COMM_RM_AXI_CONTROL__AWQOS 20 +#define FSX_COMM_RM_AXI_CONTROL__ARQOS 16 +#define FSX_COMM_RM_AXI_CONTROL__AWPROT 12 +#define FSX_COMM_RM_AXI_CONTROL__ARPROT 8 +#define FSX_COMM_RM_AXI_CONTROL__AWCACHE 4 +#define FSX_COMM_RM_AXI_CONTROL__ARCACHE 0 + +#define FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR 0x48 + +#define FSX_COMM_RM_GROUP_PKT_EXTENSION_SUPPORT 0xc0 + +#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD 0xc8 +#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MASK 0x1ff +#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX 16 +#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN 0 + +#define FSX_COMM_RM_GROUP_RING_COUNT 0xcc + +#define FSX_COMM_RM_MAIN_HW_INIT_DONE 0x12c +#define FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK 0x1 + +#define FSX_DMEx_BASE(__b, __i) \ + ((__b) + (__i) * 0x1000) + +#define FSX_DMEx_AXI_CONTROL(__b, __i) \ + (FSX_DMEx_BASE(__b, __i) + 0x4) +#define FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN 28 +#define FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN 24 +#define FSX_DMEx_AXI_CONTROL__AWQOS 20 +#define FSX_DMEx_AXI_CONTROL__ARQOS 16 +#define FSX_DMEx_AXI_CONTROL__AWCACHE 4 +#define FSX_DMEx_AXI_CONTROL__ARCACHE 0 + +#define FSX_DMEx_WR_FIFO_THRESHOLD(__b, __i) \ + (FSX_DMEx_BASE(__b, __i) + 0xc) +#define FSX_DMEx_WR_FIFO_THRESHOLD__MASK 0x3ff +#define FSX_DMEx_WR_FIFO_THRESHOLD__MAX 10 +#define FSX_DMEx_WR_FIFO_THRESHOLD__MIN 0 + +#define FSX_DMEx_RD_FIFO_THRESHOLD(__b, __i) \ + (FSX_DMEx_BASE(__b, __i) + 0x14) +#define FSX_DMEx_RD_FIFO_THRESHOLD__MASK 0x3ff +#define FSX_DMEx_RD_FIFO_THRESHOLD__MAX 10 +#define FSX_DMEx_RD_FIFO_THRESHOLD__MIN 0 + +#define FS6_SUB_TOP_BASE 0x66D8F800 +#define FS6_PKI_DME_RESET 0x4 +#define PKI_DME_RESET 1 + +char *fsx_type_names[] = { + "fs4-raid", + "fs4-crypto", + "fs6-pki", +}; + +void fsx_init(eFSX_TYPE fsx_type, + unsigned int ring_count, + unsigned int dme_count, + unsigned int ae_count, + unsigned int start_stream_id, + unsigned int msi_dev_id, + uintptr_t idm_io_control_direct, + uintptr_t idm_reset_control, + uintptr_t base, + uintptr_t dme_base) +{ + int try; + unsigned int i, v, data; + uintptr_t fs4_idm_io_control_direct = idm_io_control_direct; + uintptr_t fs4_idm_reset_control = idm_reset_control; + uintptr_t fsx_comm_rm = (base + 0x203000); + + VERBOSE("fsx %s init start\n", fsx_type_names[fsx_type]); + + if (fsx_type == eFS4_RAID || fsx_type == eFS4_CRYPTO) { + /* Enable FSx engine clock */ + VERBOSE(" - enable fsx clock\n"); + mmio_write_32(fs4_idm_io_control_direct, + (1U << FS4_IDM_IO_CONTROL_DIRECT__CLK_EN)); + udelay(500); + + /* Reset FSx engine */ + VERBOSE(" - reset fsx\n"); + v = mmio_read_32(fs4_idm_reset_control); + v |= (1 << FS4_IDM_RESET_CONTROL__RESET); + mmio_write_32(fs4_idm_reset_control, v); + udelay(500); + v = mmio_read_32(fs4_idm_reset_control); + v &= ~(1 << FS4_IDM_RESET_CONTROL__RESET); + mmio_write_32(fs4_idm_reset_control, v); + } else { + /* + * Default RM and AE are out of reset, + * So only DME Reset added here + */ + v = mmio_read_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET); + v &= ~(PKI_DME_RESET); + mmio_write_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET, v); + } + + /* Wait for HW-init done */ + VERBOSE(" - wait for HW-init done\n"); + try = 10000; + do { + udelay(1); + data = mmio_read_32(fsx_comm_rm + + FSX_COMM_RM_MAIN_HW_INIT_DONE); + try--; + } while (!(data & FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK) && (try > 0)); + + if (try <= 0) + ERROR("fsx_comm_rm + 0x%x: 0x%x\n", + data, FSX_COMM_RM_MAIN_HW_INIT_DONE); + + /* Make all rings non-secured */ + VERBOSE(" - make all rings non-secured\n"); + v = 0xffffffff; + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_SECURITY_SETTING, v); + + /* Set start stream-id for rings to */ + VERBOSE(" - set start stream-id for rings to 0x%x\n", + start_stream_id); + v = start_stream_id >> FSX_COMM_RM_SSID_CONTROL__RING_BITS; + v &= FSX_COMM_RM_SSID_CONTROL__MASK; + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_SSID_CONTROL, v); + + /* Set timer configuration */ + VERBOSE(" - set timer configuration\n"); + v = 0x0271 << FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM; + v |= (0x0138 << FSX_COMM_RM_TIMER_CONTROL_0__FAST); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_0, v); + v = 0x09c4 << FSX_COMM_RM_TIMER_CONTROL_1__IDLE; + v |= (0x04e2 << FSX_COMM_RM_TIMER_CONTROL_1__SLOW); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_1, v); + v = 0x0000f424; + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_FLUSH_TIMEOUT, v); + + /* Set burst length and fifo threshold */ + VERBOSE(" - set burst length, fifo and bd threshold\n"); + v = 0x0; + v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN); + v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_LENGTH, v); + v = 0x0; + v |= (0x67 << FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL); + v |= (0x18 << FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_FIFO_THRESHOLD, v); + v = 0x0; + v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_LOW); + v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_BD_THRESHOLD, v); + + /* Set memory configuration */ + VERBOSE(" - set memory configuration\n"); + v = 0x0; + v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN); + v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN); + v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN); + v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_MEMORY_CONFIGURATION, v); + + /* AXI configuration for RM */ + v = 0; + v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN); + v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN); + v |= (0xe << FSX_COMM_RM_AXI_CONTROL__AWQOS); + v |= (0xa << FSX_COMM_RM_AXI_CONTROL__ARQOS); + v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__AWPROT); + v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__ARPROT); + v |= (0xf << FSX_COMM_RM_AXI_CONTROL__AWCACHE); + v |= (0xf << FSX_COMM_RM_AXI_CONTROL__ARCACHE); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL, v); + VERBOSE(" - set AXI control = 0x%x\n", + mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL)); + v = 0x0; + v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX); + v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD, v); + VERBOSE(" - set AXI read burst threshold = 0x%x\n", + mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD)); + + /* Configure group ring count for all groups */ + /* By default we schedule extended packets + * on all AEs/DMEs in a group. + */ + v = (dme_count & 0xf) << 0; + v |= (dme_count & 0xf) << 4; + v |= (dme_count & 0xf) << 8; + v |= (dme_count & 0xf) << 12; + v |= (dme_count & 0xf) << 16; + v |= (dme_count & 0xf) << 20; + v |= (dme_count & 0xf) << 24; + v |= (dme_count & 0xf) << 28; + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_GROUP_RING_COUNT, v); + + /* + * Due to HW issue spurious interrupts are getting generated. + * To fix sw needs to clear the config status interrupts + * before setting CONFIG_DONE. + */ + mmio_write_32(fsx_comm_rm + + FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR, + 0xffffffff); + + /* Configure RM control */ + VERBOSE(" - configure RM control\n"); + v = mmio_read_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER); + v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v); + v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE); + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v); + + /* Configure AE timeout */ + VERBOSE(" - configure AE timeout\n"); + v = 0x00003fff; + mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AE_TIMEOUT, v); + + /* Initialize all AEs */ + for (i = 0; i < ae_count; i++) { + VERBOSE(" - initialize AE%d\n", i); + v = (0x1 << FSX_AEx_CONTROL_REGISTER__ACTIVE); + mmio_write_32(FSX_AEx_CONTROL_REGISTER(base, i), v); + } + + /* Initialize all DMEs */ + for (i = 0; i < dme_count; i++) { + VERBOSE(" - initialize DME%d\n", i); + v = 0; + v |= (0x1 << FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN); + v |= (0x1 << FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN); + v |= (0xe << FSX_DMEx_AXI_CONTROL__AWQOS); + v |= (0xa << FSX_DMEx_AXI_CONTROL__ARQOS); + v |= (0xf << FSX_DMEx_AXI_CONTROL__AWCACHE); + v |= (0xf << FSX_DMEx_AXI_CONTROL__ARCACHE); + mmio_write_32(FSX_DMEx_AXI_CONTROL(dme_base, i), v); + VERBOSE(" -- AXI_CONTROL = 0x%x\n", + mmio_read_32(FSX_DMEx_AXI_CONTROL(dme_base, i))); + v = 0; + v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MIN); + v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MAX); + mmio_write_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i), v); + VERBOSE(" -- WR_FIFO_THRESHOLD = 0x%x\n", + mmio_read_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i))); + v = 0; + v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MIN); + v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MAX); + mmio_write_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i), v); + VERBOSE(" -- RD_FIFO_THRESHOLD = 0x%x\n", + mmio_read_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i))); + } + + /* Configure ring axi id and msi device id */ + for (i = 0; i < ring_count; i++) { + VERBOSE(" - ring%d version=0x%x\n", i, + mmio_read_32(FSX_RINGx_VERSION_NUMBER(base, i))); + mmio_write_32(FSX_COMM_RINGx_MSI_DEV_ID(base, i), + msi_dev_id); + v = 0; + v |= ((i & FSX_COMM_RINGx_CONTROL__AXI_ID_MASK) << + FSX_COMM_RINGx_CONTROL__AXI_ID); + mmio_write_32(FSX_COMM_RINGx_CONTROL(base, i), v); + } + + INFO("fsx %s init done\n", fsx_type_names[fsx_type]); +} + +void fsx_meminit(const char *name, + uintptr_t idm_io_control_direct, + uintptr_t idm_io_status) +{ + int try; + unsigned int val; + + VERBOSE("fsx %s meminit start\n", name); + + VERBOSE(" - arrpoweron\n"); + mmio_setbits_32(idm_io_control_direct, + BIT(FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON)); + while (!(mmio_read_32(idm_io_status) & + BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWERON))) + ; + + VERBOSE(" - arrpowerok\n"); + mmio_setbits_32(idm_io_control_direct, + (1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK)); + while (!(mmio_read_32(idm_io_status) & + BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWEROK))) + ; + + VERBOSE(" - poweron\n"); + mmio_setbits_32(idm_io_control_direct, + (1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON)); + while (!(mmio_read_32(idm_io_status) & + BIT(FS4_IDM_IO_STATUS__MEM_POWERON))) + ; + + VERBOSE(" - powerok\n"); + mmio_setbits_32(idm_io_control_direct, + (1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK)); + while (!(mmio_read_32(idm_io_status) & + BIT(FS4_IDM_IO_STATUS__MEM_POWEROK))) + ; + + /* Final check on all power bits */ + try = 10; + do { + val = mmio_read_32(idm_io_status); + if (val == FS4_IDM_IO_STATUS__MEM_ALLOK) + break; + + /* Wait sometime */ + mdelay(1); + + try--; + } while (try > 0); + + /* Remove memory isolation if things are fine. */ + if (try <= 0) { + INFO(" - powerup failed\n"); + } else { + VERBOSE(" - remove isolation\n"); + mmio_clrbits_32(idm_io_control_direct, + (1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO)); + VERBOSE(" - powerup done\n"); + } + + INFO("fsx %s meminit done\n", name); +} + +void fs4_disable_clocks(bool disable_sram, + bool disable_crypto, + bool disable_raid) +{ + VERBOSE("fs4 disable clocks start\n"); + + if (disable_sram) { + VERBOSE(" - disable sram clock\n"); + mmio_clrbits_32(FS4_SRAM_IDM_IO_CONTROL_DIRECT, + (1 << FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN)); + } + + if (disable_crypto) { + VERBOSE(" - disable crypto clock\n"); + mmio_setbits_32(CDRU_GENPLL5_CONTROL1, + CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK); + } + + if (disable_raid) { + VERBOSE(" - disable raid clock\n"); + mmio_setbits_32(CDRU_GENPLL5_CONTROL1, + CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK); + } + + if (disable_sram && disable_crypto && disable_raid) { + VERBOSE(" - disable root clock\n"); + mmio_setbits_32(CDRU_GENPLL5_CONTROL1, + CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK); + mmio_setbits_32(CDRU_GENPLL2_CONTROL1, + CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK); + } + + INFO("fs4 disable clocks done\n"); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c new file mode 100644 index 0000000..9141d3e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST1 2 +#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST2 1 +#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST3 0 +#define CDRU_MISC_RESET_CONTROL__CDRU_IH1_RESET 9 +#define CDRU_MISC_RESET_CONTROL__CDRU_IH2_RESET 8 +#define CDRU_MISC_RESET_CONTROL__CDRU_IH3_RESET 7 +#define A72_CRM_SOFTRESETN_0 0x480 +#define A72_CRM_SOFTRESETN_1 0x484 +#define A72_CRM_DOMAIN_4_CONTROL 0x810 +#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_DFT 3 +#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_MEM 6 +#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_I_O 0 +#define A72_CRM_SUBSYSTEM_MEMORY_CONTROL_3 0xB4C +#define MEMORY_PDA_HI_SHIFT 0x0 +#define A72_CRM_PLL_PWR_ON 0x70 +#define A72_CRM_PLL_PWR_ON__PLL0_ISO_PLLOUT 4 +#define A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO 1 +#define A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL 0 +#define A72_CRM_SUBSYSTEM_MEMORY_CONTROL_2 0xB48 +#define A72_CRM_PLL_INTERRUPT_STATUS 0x8c +#define A72_CRM_PLL_INTERRUPT_STATUS__PLL0_LOCK_LOST_STATUS 8 +#define A72_CRM_PLL_INTERRUPT_STATUS__PLL0_LOCK_STATUS 9 +#define A72_CRM_INTERRUPT_ENABLE 0x4 +#define A72_CRM_INTERRUPT_ENABLE__PLL0_INT_ENABLE 4 +#define A72_CRM_PLL_INTERRUPT_ENABLE 0x88 +#define A72_CRM_PLL_INTERRUPT_ENABLE__PLL0_LOCK_STATUS_INT_ENB 9 +#define A72_CRM_PLL_INTERRUPT_ENABLE__PLL0_LOCK_LOST_STATUS_INT_ENB 8 +#define A72_CRM_PLL0_CFG0_CTRL 0x120 +#define A72_CRM_PLL0_CFG1_CTRL 0x124 +#define A72_CRM_PLL0_CFG2_CTRL 0x128 +#define A72_CRM_PLL0_CFG3_CTRL 0x12C +#define A72_CRM_CORE_CONFIG_DBGCTRL__DBGROMADDRV 0 +#define A72_CRM_CORE_CONFIG_DBGCTRL 0xD50 +#define A72_CRM_CORE_CONFIG_DBGROM_LO 0xD54 +#define A72_CRM_CORE_CONFIG_DBGROM_HI 0xD58 +#define A72_CRM_SUBSYSTEM_CONFIG_1__DBGL1RSTDISABLE 2 +#define A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN 0 +#define A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN 1 +#define A72_CRM_AXI_CLK_DESC 0x304 +#define A72_CRM_ACP_CLK_DESC 0x308 +#define A72_CRM_ATB_CLK_DESC 0x30C +#define A72_CRM_PCLKDBG_DESC 0x310 +#define A72_CRM_CLOCK_MODE_CONTROL 0x40 +#define A72_CRM_CLOCK_MODE_CONTROL__CLK_CHANGE_TRIGGER 0 +#define A72_CRM_CLOCK_CONTROL_0 0x200 +#define A72_CRM_CLOCK_CONTROL_0__ARM_HW_SW_ENABLE_SEL 0 +#define A72_CRM_CLOCK_CONTROL_0__AXI_HW_SW_ENABLE_SEL 2 +#define A72_CRM_CLOCK_CONTROL_0__ACP_HW_SW_ENABLE_SEL 4 +#define A72_CRM_CLOCK_CONTROL_0__ATB_HW_SW_ENABLE_SEL 6 +#define A72_CRM_CLOCK_CONTROL_0__PCLKDBG_HW_SW_ENA_SEL 8 +#define A72_CRM_CLOCK_CONTROL_1 0x204 +#define A72_CRM_CLOCK_CONTROL_1__TMON_HW_SW_ENABLE_SEL 6 +#define A72_CRM_CLOCK_CONTROL_1__APB_HW_SW_ENABLE_SEL 8 +#define A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN 0 +#define A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN 1 +#define A72_CRM_SOFTRESETN_0__AXI_SOFTRESETN 9 +#define A72_CRM_SOFTRESETN_0__ACP_SOFTRESETN 10 +#define A72_CRM_SOFTRESETN_0__ATB_SOFTRESETN 11 +#define A72_CRM_SOFTRESETN_0__PCLKDBG_SOFTRESETN 12 +#define A72_CRM_SOFTRESETN_0__TMON_SOFTRESETN 15 +#define A72_CRM_SOFTRESETN_0__L2_SOFTRESETN 3 +#define A72_CRM_SOFTRESETN_1__APB_SOFTRESETN 8 + +/* core related regs */ +#define A72_CRM_DOMAIN_0_CONTROL 0x800 +#define A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_MEM 0x6 +#define A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_I_O 0x0 +#define A72_CRM_DOMAIN_1_CONTROL 0x804 +#define A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_MEM 0x6 +#define A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_I_O 0x0 +#define A72_CRM_CORE_CONFIG_RVBA0_LO 0xD10 +#define A72_CRM_CORE_CONFIG_RVBA0_MID 0xD14 +#define A72_CRM_CORE_CONFIG_RVBA0_HI 0xD18 +#define A72_CRM_CORE_CONFIG_RVBA1_LO 0xD20 +#define A72_CRM_CORE_CONFIG_RVBA1_MID 0xD24 +#define A72_CRM_CORE_CONFIG_RVBA1_HI 0xD28 +#define A72_CRM_SUBSYSTEM_CONFIG_0 0xC80 +#define A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT 4 +#define A72_CRM_SOFTRESETN_0__COREPOR0_SOFTRESETN 4 +#define A72_CRM_SOFTRESETN_0__COREPOR1_SOFTRESETN 5 +#define A72_CRM_SOFTRESETN_1__CORE0_SOFTRESETN 0 +#define A72_CRM_SOFTRESETN_1__DEBUG0_SOFTRESETN 4 +#define A72_CRM_SOFTRESETN_1__CORE1_SOFTRESETN 1 +#define A72_CRM_SOFTRESETN_1__DEBUG1_SOFTRESETN 5 + +#define SPROC_MEMORY_BISR 0 + +static int cluster_power_status[PLAT_BRCM_CLUSTER_COUNT] = {CLUSTER_POWER_ON, + CLUSTER_POWER_OFF, + CLUSTER_POWER_OFF, + CLUSTER_POWER_OFF}; + +void ihost_power_on_cluster(u_register_t mpidr) +{ + uint32_t rst, d2xs; + uint32_t cluster_id; + uint32_t ihost_base; +#if SPROC_MEMORY_BISR + uint32_t bisr, cnt; +#endif + cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + uint32_t cluster0_freq_sel; + + if (cluster_power_status[cluster_id] == CLUSTER_POWER_ON) + return; + + cluster_power_status[cluster_id] = CLUSTER_POWER_ON; + INFO("enabling Cluster #%u\n", cluster_id); + + switch (cluster_id) { + case 1: + rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH1_RESET); + d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST1); +#if SPROC_MEMORY_BISR + bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST1; +#endif + break; + case 2: + rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH2_RESET); + d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST2); +#if SPROC_MEMORY_BISR + bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST2; +#endif + break; + case 3: + rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH3_RESET); + d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST3); +#if SPROC_MEMORY_BISR + bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST3; +#endif + break; + default: + ERROR("Invalid cluster :%u\n", cluster_id); + return; + } + + /* Releasing ihost resets */ + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, rst); + + /* calculate cluster/ihost base address */ + ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE; + + /* Remove Cluster IO isolation */ + mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_4_CONTROL, + (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_I_O), + (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_DFT) | + (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_MEM)); + + /* + * Since BISR sequence requires that all cores of cluster should + * have removed I/O isolation hence doing same here. + */ + /* Remove core0 memory IO isolations */ + mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_0_CONTROL, + (1 << A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_I_O), + (1 << A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_MEM)); + + /* Remove core1 memory IO isolations */ + mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_1_CONTROL, + (1 << A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_I_O), + (1 << A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_MEM)); + +#if SPROC_MEMORY_BISR + mmio_setbits_32(CRMU_BISR_PDG_MASK, (1 << bisr)); + + if (!(mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW) & + (1 << CDRU_CHIP_STRAP_DATA_LSW__BISR_BYPASS_MODE))) { + /* BISR completion would take max 2 usec */ + cnt = 0; + while (cnt < 2) { + udelay(1); + if (mmio_read_32(CRMU_CHIP_OTPC_STATUS) & + (1 << CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE)) + break; + cnt++; + } + } + + /* if BISR is not completed, need to be checked with ASIC team */ + if (((mmio_read_32(CRMU_CHIP_OTPC_STATUS)) & + (1 << CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE)) == 0) { + WARN("BISR did not completed and need to be addressed\n"); + } +#endif + + /* PLL Power up. supply is already on. Turn on PLL LDO/PWR */ + mmio_write_32(ihost_base + A72_CRM_PLL_PWR_ON, + (1 << A72_CRM_PLL_PWR_ON__PLL0_ISO_PLLOUT) | + (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO) | + (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL)); + + /* 1us in spec; Doubling it to be safe*/ + udelay(2); + + /* Remove PLL output ISO */ + mmio_write_32(ihost_base + A72_CRM_PLL_PWR_ON, + (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO) | + (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL)); + + /* + * PLL0 Configuration Control Register + * these 4 registers drive the i_pll_ctrl[63:0] input of pll + * (16b per register). + * the values are derived from the spec (sections 8 and 10). + */ + + mmio_write_32(ihost_base + A72_CRM_PLL0_CFG0_CTRL, 0x00000000); + mmio_write_32(ihost_base + A72_CRM_PLL0_CFG1_CTRL, 0x00008400); + mmio_write_32(ihost_base + A72_CRM_PLL0_CFG2_CTRL, 0x00000001); + mmio_write_32(ihost_base + A72_CRM_PLL0_CFG3_CTRL, 0x00000000); + + /* Read the freq_sel from cluster 0, which is up already */ + cluster0_freq_sel = bcm_get_ihost_pll_freq(0); + bcm_set_ihost_pll_freq(cluster_id, cluster0_freq_sel); + + udelay(1); + + /* Release clock source reset */ + mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0, + (1 << A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN) | + (1 << A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN)); + + udelay(1); + + /* + * Integer division for clks (divider value = n+1). + * These are the divisor of ARM PLL clock frequecy. + */ + mmio_write_32(ihost_base + A72_CRM_AXI_CLK_DESC, 0x00000001); + mmio_write_32(ihost_base + A72_CRM_ACP_CLK_DESC, 0x00000001); + mmio_write_32(ihost_base + A72_CRM_ATB_CLK_DESC, 0x00000004); + mmio_write_32(ihost_base + A72_CRM_PCLKDBG_DESC, 0x0000000b); + + /* + * clock change trigger - must set to take effect after clock + * source change + */ + mmio_setbits_32(ihost_base + A72_CRM_CLOCK_MODE_CONTROL, + (1 << A72_CRM_CLOCK_MODE_CONTROL__CLK_CHANGE_TRIGGER)); + + /* turn on functional clocks */ + mmio_setbits_32(ihost_base + A72_CRM_CLOCK_CONTROL_0, + (3 << A72_CRM_CLOCK_CONTROL_0__ARM_HW_SW_ENABLE_SEL) | + (3 << A72_CRM_CLOCK_CONTROL_0__AXI_HW_SW_ENABLE_SEL) | + (3 << A72_CRM_CLOCK_CONTROL_0__ACP_HW_SW_ENABLE_SEL) | + (3 << A72_CRM_CLOCK_CONTROL_0__ATB_HW_SW_ENABLE_SEL) | + (3 << A72_CRM_CLOCK_CONTROL_0__PCLKDBG_HW_SW_ENA_SEL)); + + mmio_setbits_32(ihost_base + A72_CRM_CLOCK_CONTROL_1, + (3 << A72_CRM_CLOCK_CONTROL_1__TMON_HW_SW_ENABLE_SEL) | + (3 << A72_CRM_CLOCK_CONTROL_1__APB_HW_SW_ENABLE_SEL)); + + /* Program D2XS Power Down Registers */ + mmio_setbits_32(CDRU_CCN_REGISTER_CONTROL_1, d2xs); + + /* Program Core Config Debug ROM Address Registers */ + /* mark valid for Debug ROM base address */ + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGCTRL, + (1 << A72_CRM_CORE_CONFIG_DBGCTRL__DBGROMADDRV)); + + /* Program Lo and HI address of coresight DBG rom address */ + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGROM_LO, + (CORESIGHT_BASE_ADDR >> 12) & 0xffff); + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGROM_HI, + (CORESIGHT_BASE_ADDR >> 28) & 0xffff); + + /* + * Release soft resets of different components. + * Order: Bus clocks --> PERIPH --> L2 --> cores + */ + + /* Bus clocks soft resets */ + mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0, + (1 << A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN) | + (1 << A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN) | + (1 << A72_CRM_SOFTRESETN_0__AXI_SOFTRESETN) | + (1 << A72_CRM_SOFTRESETN_0__ACP_SOFTRESETN) | + (1 << A72_CRM_SOFTRESETN_0__ATB_SOFTRESETN) | + (1 << A72_CRM_SOFTRESETN_0__PCLKDBG_SOFTRESETN)); + + mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_1, + (1 << A72_CRM_SOFTRESETN_1__APB_SOFTRESETN)); + + /* Periph component softreset */ + mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0, + (1 << A72_CRM_SOFTRESETN_0__TMON_SOFTRESETN)); + + /* L2 softreset */ + mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0, + (1 << A72_CRM_SOFTRESETN_0__L2_SOFTRESETN)); + + /* Enable and program Satellite timer */ + ihost_enable_satellite_timer(cluster_id); +} + +void ihost_power_on_secondary_core(u_register_t mpidr, uint64_t rvbar) +{ + uint32_t ihost_base; + uint32_t coreid = MPIDR_AFFLVL0_VAL(mpidr); + uint32_t cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + + ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE; + INFO("programming core #%u\n", coreid); + + if (coreid) { + /* program the entry point for core1 */ + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_LO, + rvbar & 0xFFFF); + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_MID, + (rvbar >> 16) & 0xFFFF); + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_HI, + (rvbar >> 32) & 0xFFFF); + } else { + /* program the entry point for core */ + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_LO, + rvbar & 0xFFFF); + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_MID, + (rvbar >> 16) & 0xFFFF); + mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_HI, + (rvbar >> 32) & 0xFFFF); + } + + /* Tell debug logic which processor is up */ + mmio_setbits_32(ihost_base + A72_CRM_SUBSYSTEM_CONFIG_0, + (coreid ? + (2 << A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT) : + (1 << A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT))); + + /* releasing soft resets for IHOST core */ + mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0, + (coreid ? + (1 << A72_CRM_SOFTRESETN_0__COREPOR1_SOFTRESETN) : + (1 << A72_CRM_SOFTRESETN_0__COREPOR0_SOFTRESETN))); + + mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_1, + (coreid ? + ((1 << A72_CRM_SOFTRESETN_1__CORE1_SOFTRESETN) | + (1 << A72_CRM_SOFTRESETN_1__DEBUG1_SOFTRESETN)) : + ((1 << A72_CRM_SOFTRESETN_1__CORE0_SOFTRESETN) | + (1 << A72_CRM_SOFTRESETN_1__DEBUG0_SOFTRESETN)))); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c new file mode 100644 index 0000000..de8b995 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include + +#define SMMU_BASE 0x64000000 +#define ARM_SMMU_MAX_NUM_CNTXT_BANK 64 +#define SMMU_CTX_BANK_IDX_SECURE_CRMU 63 +#define ARM_SMMU_NUM_SECURE_MASTER 1 +#define ARM_SMMU_NSNUMCBO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \ + ARM_SMMU_NUM_SECURE_MASTER) +#define ARM_SMMU_NSNUMSMRGO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \ + ARM_SMMU_NUM_SECURE_MASTER) +/* Reserved Banks. */ +#define SMMU_CTX_BANK_IDX (SMMU_CTX_BANK_IDX_SECURE_CRMU - \ + ARM_SMMU_NUM_SECURE_MASTER) +#define NUM_OF_SMRS 1 + +#define STG1_WITH_STG2_BYPASS 1 +#define ARM_LPAE_PGTBL_PHYS_CRMU 0x880000000 +#define ARM_LPAE_PGTBL_PHYS 0x880200000 +#define ARM_LPAE_PGTBL_PTE_CNT 512 +#define ARM_LPAE_PTE_L1_BLOCK_SIZE 0x40000000 +#define ARM_LPAE_PTE_L1_ADDR_MASK 0x0000FFFFC0000000UL +#define ARM_LPAE_PTE_TABLE 0x2UL +#define ARM_LPAE_PTE_VALID 0x1UL +#define ARM_LPAE_PTE_ATTRINDX 2 +#define ARM_LPAE_PTE_NS 5 +#define ARM_LPAE_PTE_AP 6 +#define ARM_LPAE_PTE_AP_EL1_RW 0x0 +#define ARM_LPAE_PTE_AP_EL0_RW 0x1 +#define ARM_LPAE_PTE_SH 8 +#define ARM_LPAE_PTE_SH_NON 0x0 +#define ARM_LPAE_PTE_SH_OUTER 0x2 +#define ARM_LPAE_PTE_SH_INNER 0x3 +#define ARM_LPAE_PTE_AF 10 +#define ARM_SMMU_RES_SIZE 0x80000 + +#define ARM_LPAE_PTE_NSTABLE 0x8000000000000000UL +#define ARM_LPAE_PTE_L1_INDEX_SHIFT 30 +#define ARM_LPAE_PTE_L1_INDEX_MASK 0x1ff +#define ARM_LPAE_PTE_L0_INDEX_SHIFT 39 +#define ARM_LPAE_PTE_L0_INDEX_MASK 0x1ff +#define ARM_LPAE_PTE_TABLE_MASK ~(0xfffUL) +/* Configuration registers */ +#define ARM_SMMU_GR0_sCR0 0x0 +#define sCR0_CLIENTPD (1 << 0) +#define sCR0_GFRE (1 << 1) +#define sCR0_GFIE (1 << 2) +#define sCR0_GCFGFRE (1 << 4) +#define sCR0_GCFGFIE (1 << 5) +#define sCR0_USFCFG (1 << 10) +#define sCR0_VMIDPNE (1 << 11) +#define sCR0_PTM (1 << 12) +#define sCR0_FB (1 << 13) +#define sCR0_VMID16EN (1 << 31) +#define sCR0_BSU_SHIFT 14 +#define sCR0_BSU_MASK 0x3 +#define ARM_SMMU_SMMU_SCR1 0x4 +#define SCR1_NSNUMCBO_MASK 0xFF +#define SCR1_NSNUMCBO_SHIFT 0x0 +#define SCR1_NSNUMSMRGO_MASK 0xFF00 +#define SCR1_NSNUMSMRGO_SHIFT 0x8 + +/* Identification registers */ +#define ARM_SMMU_GR0_ID0 0x20 +#define ARM_SMMU_GR0_ID1 0x24 +#define ARM_SMMU_GR0_ID2 0x28 +#define ARM_SMMU_GR0_ID3 0x2c +#define ARM_SMMU_GR0_ID4 0x30 +#define ARM_SMMU_GR0_ID5 0x34 +#define ARM_SMMU_GR0_ID6 0x38 +#define ARM_SMMU_GR0_ID7 0x3c +#define ARM_SMMU_GR0_sGFSR 0x48 +#define ARM_SMMU_GR0_sGFSYNR0 0x50 +#define ARM_SMMU_GR0_sGFSYNR1 0x54 +#define ARM_SMMU_GR0_sGFSYNR2 0x58 + +#define ID1_PAGESIZE (1U << 31) +#define ID1_NUMPAGENDXB_SHIFT 28 +#define ID1_NUMPAGENDXB_MASK 7 +#define ID1_NUMS2CB_SHIFT 16 +#define ID1_NUMS2CB_MASK 0xff +#define ID1_NUMCB_SHIFT 0 +#define ID1_NUMCB_MASK 0xff + +/* SMMU global address space */ +#define ARM_SMMU_GR0(smmu) ((smmu)->base) +#define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift)) + +/* Stream mapping registers */ +#define ARM_SMMU_GR0_SMR(n) (0x800 + (n << 2)) +#define SMR_VALID (1U << 31) +#define SMR_MASK_SHIFT 16 +#define SMR_ID_SHIFT 0 + +#define ARM_SMMU_GR0_S2CR(n) (0xc00 + (n << 2)) +#define S2CR_CBNDX_SHIFT 0 +#define S2CR_CBNDX_MASK 0xff +#define S2CR_TYPE_SHIFT 16 +#define S2CR_TYPE_MASK 0x3 + +#define ARM_SMMU_GR1_CBA2R(n) (0x800 + (n << 2)) +#define CBA2R_RW64_32BIT (0 << 0) +#define CBA2R_RW64_64BIT (1 << 0) +#define CBA2R_VMID_SHIFT 16 +#define CBA2R_VMID_MASK 0xffff + +#define ARM_SMMU_GR1_CBAR(n) (0x0 + (n << 2)) +#define CBAR_VMID_SHIFT 0 +#define CBAR_VMID_MASK 0xff +#define CBAR_S1_BPSHCFG_SHIFT 8 +#define CBAR_S1_BPSHCFG_MASK 3 +#define CBAR_S1_BPSHCFG_NSH 3 +#define CBAR_S1_MEMATTR_SHIFT 12 +#define CBAR_S1_MEMATTR_MASK 0xf +#define CBAR_S1_MEMATTR_WB 0xf +#define CBAR_TYPE_SHIFT 16 +#define CBAR_TYPE_MASK 0x3 +#define CBAR_TYPE_S2_TRANS (0 << CBAR_TYPE_SHIFT) +#define CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << CBAR_TYPE_SHIFT) +#define CBAR_TYPE_S1_TRANS_S2_FAULT (2 << CBAR_TYPE_SHIFT) +#define CBAR_TYPE_S1_TRANS_S2_TRANS (3 << CBAR_TYPE_SHIFT) +#define CBAR_IRPTNDX_SHIFT 24 +#define CBAR_IRPTNDX_MASK 0xff + +/* Translation context bank */ +#define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1)) +#define ARM_SMMU_CB(smmu, n) ((n) * (1 << (smmu)->pgshift)) + +#define ARM_SMMU_CB_SCTLR 0x0 +#define ARM_SMMU_CB_ACTLR 0x4 +#define ARM_SMMU_CB_RESUME 0x8 +#define ARM_SMMU_CB_TTBCR2 0x10 +#define ARM_SMMU_CB_TTBR0 0x20 +#define ARM_SMMU_CB_TTBR1 0x28 +#define ARM_SMMU_CB_TTBCR 0x30 +#define ARM_SMMU_CB_CONTEXTIDR 0x34 +#define ARM_SMMU_CB_S1_MAIR0 0x38 +#define ARM_SMMU_CB_S1_MAIR1 0x3c +#define ARM_SMMU_CB_PAR 0x50 +#define ARM_SMMU_CB_FSR 0x58 +#define ARM_SMMU_CB_FAR 0x60 +#define ARM_SMMU_CB_FSYNR0 0x68 +#define ARM_SMMU_CB_S1_TLBIVA 0x600 +#define ARM_SMMU_CB_S1_TLBIASID 0x610 +#define ARM_SMMU_CB_S1_TLBIVAL 0x620 +#define ARM_SMMU_CB_S2_TLBIIPAS2 0x630 +#define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638 +#define ARM_SMMU_CB_ATS1PR 0x800 +#define ARM_SMMU_CB_ATSR 0x8f0 + +#define SCTLR_S1_ASIDPNE (1 << 12) +#define SCTLR_CFCFG (1 << 7) +#define SCTLR_CFIE (1 << 6) +#define SCTLR_CFRE (1 << 5) +#define SCTLR_E (1 << 4) +#define SCTLR_AFE (1 << 2) +#define SCTLR_TRE (1 << 1) +#define SCTLR_M (1 << 0) + +/* ARM LPAE configuration. */ +/**************************************************************/ +/* Register bits */ +#define ARM_32_LPAE_TCR_EAE (1 << 31) +#define ARM_64_LPAE_S2_TCR_RES1 (1 << 31) + +#define ARM_LPAE_TCR_EPD1 (1 << 23) + +#define ARM_LPAE_TCR_TG0_4K (0 << 14) +#define ARM_LPAE_TCR_TG0_64K (1 << 14) +#define ARM_LPAE_TCR_TG0_16K (2 << 14) + +#define ARM_LPAE_TCR_SH0_SHIFT 12 +#define ARM_LPAE_TCR_SH0_MASK 0x3 +#define ARM_LPAE_TCR_SH_NS 0 +#define ARM_LPAE_TCR_SH_OS 2 +#define ARM_LPAE_TCR_SH_IS 3 + +#define ARM_LPAE_TCR_ORGN0_SHIFT 10 +#define ARM_LPAE_TCR_IRGN0_SHIFT 8 +#define ARM_LPAE_TCR_RGN_MASK 0x3 +#define ARM_LPAE_TCR_RGN_NC 0 +#define ARM_LPAE_TCR_RGN_WBWA 1 +#define ARM_LPAE_TCR_RGN_WT 2 +#define ARM_LPAE_TCR_RGN_WB 3 + +#define ARM_LPAE_TCR_SL0_SHIFT 6 +#define ARM_LPAE_TCR_SL0_MASK 0x3 + +#define ARM_LPAE_TCR_T0SZ_SHIFT 0 +#define ARM_LPAE_TCR_SZ_MASK 0xf + +#define ARM_LPAE_TCR_PS_SHIFT 16 +#define ARM_LPAE_TCR_PS_MASK 0x7 + +#define ARM_LPAE_TCR_IPS_SHIFT 32 +#define ARM_LPAE_TCR_IPS_MASK 0x7 + +#define ARM_LPAE_TCR_PS_32_BIT 0x0ULL +#define ARM_LPAE_TCR_PS_36_BIT 0x1ULL +#define ARM_LPAE_TCR_PS_40_BIT 0x2ULL +#define ARM_LPAE_TCR_PS_42_BIT 0x3ULL +#define ARM_LPAE_TCR_PS_44_BIT 0x4ULL +#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL + +#define ARM_LPAE_MAIR_ATTR_SHIFT(n) ((n) << 3) +#define ARM_LPAE_MAIR_ATTR_MASK 0xff +#define ARM_LPAE_MAIR_ATTR_DEVICE 0x04 +#define ARM_LPAE_MAIR_ATTR_NC 0x44 +#define ARM_LPAE_MAIR_ATTR_WBRWA 0xff +#define ARM_LPAE_MAIR_ATTR_IDX_NC 0 +#define ARM_LPAE_MAIR_ATTR_IDX_CACHE 1 +#define ARM_LPAE_MAIR_ATTR_IDX_DEV 2 + +#define TTBRn_ASID_SHIFT 48 +#define TTBCR2_SEP_SHIFT 15 +#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT) +#define TTBCR2_AS (1 << 4) +#define TTBCR_T0SZ(ia_bits) (64 - (ia_bits)) + +#define S2CR_PRIVCFG_SHIFT 24 +#define S2CR_PRIVCFG_MASK 0x3 + +/**************************************************************/ + +uint16_t paxc_stream_ids[] = { 0x2000 }; + +uint16_t paxc_stream_ids_mask[] = { 0x1fff }; +uint16_t crmu_stream_ids[] = { CRMU_STREAM_ID }; +uint16_t crmu_stream_ids_mask[] = { 0x0 }; + +enum arm_smmu_s2cr_type { + S2CR_TYPE_TRANS, + S2CR_TYPE_BYPASS, + S2CR_TYPE_FAULT, +}; + +enum arm_smmu_s2cr_privcfg { + S2CR_PRIVCFG_DEFAULT, + S2CR_PRIVCFG_DIPAN, + S2CR_PRIVCFG_UNPRIV, + S2CR_PRIVCFG_PRIV, +}; + +struct arm_smmu_smr { + uint16_t mask; + uint16_t id; + uint32_t valid; +}; + +struct arm_smmu_s2cr { + int count; + enum arm_smmu_s2cr_type type; + enum arm_smmu_s2cr_privcfg privcfg; + uint8_t cbndx; +}; + +struct arm_smmu_cfg { + uint8_t cbndx; + uint8_t irptndx; + uint32_t cbar; +}; + +struct arm_smmu_device { + uint8_t *base; + uint32_t streams; + unsigned long size; + unsigned long pgshift; + unsigned long va_size; + unsigned long ipa_size; + unsigned long pa_size; + struct arm_smmu_smr smr[NUM_OF_SMRS]; + struct arm_smmu_s2cr s2cr[NUM_OF_SMRS]; + struct arm_smmu_cfg cfg[NUM_OF_SMRS]; + uint16_t *stream_ids; + uint16_t *stream_ids_mask; +}; + +void arm_smmu_enable_secure_client_port(void) +{ + uintptr_t smmu_base = SMMU_BASE; + + mmio_clrbits_32(smmu_base, sCR0_CLIENTPD); +} + +void arm_smmu_reserve_secure_cntxt(void) +{ + uintptr_t smmu_base = SMMU_BASE; + + mmio_clrsetbits_32(smmu_base + ARM_SMMU_SMMU_SCR1, + (SCR1_NSNUMSMRGO_MASK | SCR1_NSNUMCBO_MASK), + ((ARM_SMMU_NSNUMCBO << SCR1_NSNUMCBO_SHIFT) | + (ARM_SMMU_NSNUMSMRGO << SCR1_NSNUMSMRGO_SHIFT))); +} + +static void arm_smmu_smr_cfg(struct arm_smmu_device *smmu, uint32_t index) +{ + uint32_t idx = smmu->cfg[index].cbndx; + struct arm_smmu_smr *smr = &smmu->smr[index]; + uint32_t reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT; + + if (smr->valid) + reg |= SMR_VALID; + + mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) + + ARM_SMMU_GR0_SMR(idx)), reg); +} + +static void arm_smmu_s2cr_cfg(struct arm_smmu_device *smmu, uint32_t index) +{ + uint32_t idx = smmu->cfg[index].cbndx; + struct arm_smmu_s2cr *s2cr = &smmu->s2cr[index]; + + uint32_t reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT | + (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT | + (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT; + + mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) + + ARM_SMMU_GR0_S2CR(idx)), reg); +} + +static void smmu_set_pgtbl(struct arm_smmu_device *smmu, + enum iommu_domain dom, + uint64_t *pg_table_base) +{ + int i, l0_index, l1_index; + uint64_t addr, *pte, *l0_base, *l1_base; + uint64_t addr_space_limit; + + if (dom == PCIE_PAXC) { + addr_space_limit = 0xffffffffff; + } else if (dom == DOMAIN_CRMU) { + addr_space_limit = 0xffffffff; + } else { + ERROR("dom is not supported\n"); + return; + } + + l0_base = pg_table_base; + /* clear L0 descriptors. */ + for (i = 0; i < ARM_LPAE_PGTBL_PTE_CNT; i++) + l0_base[i] = 0x0; + + addr = 0x0; + while (addr < addr_space_limit) { + /* find L0 pte */ + l0_index = ((addr >> ARM_LPAE_PTE_L0_INDEX_SHIFT) & + ARM_LPAE_PTE_L0_INDEX_MASK); + l1_base = l0_base + ((l0_index + 1) * ARM_LPAE_PGTBL_PTE_CNT); + + /* setup L0 pte if required */ + pte = l0_base + l0_index; + if (*pte == 0x0) { + *pte |= ((uint64_t)l1_base & ARM_LPAE_PTE_TABLE_MASK); + if (dom == PCIE_PAXC) + *pte |= ARM_LPAE_PTE_NSTABLE; + *pte |= ARM_LPAE_PTE_TABLE; + *pte |= ARM_LPAE_PTE_VALID; + } + + /* find L1 pte */ + l1_index = ((addr >> ARM_LPAE_PTE_L1_INDEX_SHIFT) & + ARM_LPAE_PTE_L1_INDEX_MASK); + pte = l1_base + l1_index; + + /* setup L1 pte */ + *pte = 0x0; + *pte |= (addr & ARM_LPAE_PTE_L1_ADDR_MASK); + if (addr < 0x80000000) { + *pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV << + ARM_LPAE_PTE_ATTRINDX); + if (dom == PCIE_PAXC) + *pte |= (1 << ARM_LPAE_PTE_NS); + } else { + *pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE << + ARM_LPAE_PTE_ATTRINDX); + *pte |= (1 << ARM_LPAE_PTE_NS); + } + *pte |= (ARM_LPAE_PTE_AP_EL0_RW << ARM_LPAE_PTE_AP); + *pte |= (ARM_LPAE_PTE_SH_INNER << ARM_LPAE_PTE_SH); + *pte |= (1 << ARM_LPAE_PTE_AF); + *pte |= ARM_LPAE_PTE_VALID; + + addr += ARM_LPAE_PTE_L1_BLOCK_SIZE; + } +} + +void arm_smmu_create_identity_map(enum iommu_domain dom) +{ + struct arm_smmu_device iommu; + struct arm_smmu_device *smmu = &iommu; + uint32_t reg, reg2; + unsigned long long reg64; + uint32_t idx; + uint16_t asid; + unsigned int context_bank_index; + unsigned long long pg_table_base; + + smmu->base = (uint8_t *) SMMU_BASE; + reg = mmio_read_32((uintptr_t) (ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID1)); + smmu->pgshift = (reg & ID1_PAGESIZE) ? 16 : 12; + smmu->size = ARM_SMMU_RES_SIZE; + smmu->stream_ids = NULL; + + switch (dom) { + case PCIE_PAXC: + smmu->stream_ids = &paxc_stream_ids[0]; + smmu->stream_ids_mask = &paxc_stream_ids_mask[0]; + smmu->streams = ARRAY_SIZE(paxc_stream_ids); + context_bank_index = SMMU_CTX_BANK_IDX; + pg_table_base = ARM_LPAE_PGTBL_PHYS; + break; + case DOMAIN_CRMU: + smmu->stream_ids = &crmu_stream_ids[0]; + smmu->stream_ids_mask = &crmu_stream_ids_mask[0]; + smmu->streams = ARRAY_SIZE(crmu_stream_ids); + context_bank_index = SMMU_CTX_BANK_IDX_SECURE_CRMU; + pg_table_base = ARM_LPAE_PGTBL_PHYS_CRMU; + break; + default: + ERROR("domain not supported\n"); + return; + } + + if (smmu->streams > NUM_OF_SMRS) { + INFO("can not support more than %d sids\n", NUM_OF_SMRS); + return; + } + + /* set up iommu dev. */ + for (idx = 0; idx < smmu->streams; idx++) { + /* S2CR. */ + smmu->s2cr[idx].type = S2CR_TYPE_TRANS; + smmu->s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT; + smmu->s2cr[idx].cbndx = context_bank_index; + smmu->cfg[idx].cbndx = context_bank_index; + smmu->cfg[idx].cbar = STG1_WITH_STG2_BYPASS << CBAR_TYPE_SHIFT; + arm_smmu_s2cr_cfg(smmu, idx); + + /* SMR. */ + smmu->smr[idx].mask = smmu->stream_ids_mask[idx]; + smmu->smr[idx].id = smmu->stream_ids[idx]; + smmu->smr[idx].valid = 1; + arm_smmu_smr_cfg(smmu, idx); + + /* CBA2R. 64-bit Translation */ + mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) + + ARM_SMMU_GR1_CBA2R(smmu->cfg[idx].cbndx)), + 0x1); + /* CBAR.*/ + reg = smmu->cfg[idx].cbar; + reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) | + (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); + + mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) + + ARM_SMMU_GR1_CBAR(smmu->cfg[idx].cbndx)), + reg); + + /* TTBCR. */ + reg64 = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) | + (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) | + (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT); + reg64 |= ARM_LPAE_TCR_TG0_4K; + reg64 |= (ARM_LPAE_TCR_PS_40_BIT << ARM_LPAE_TCR_IPS_SHIFT); + /* ias 40 bits.*/ + reg64 |= TTBCR_T0SZ(40) << ARM_LPAE_TCR_T0SZ_SHIFT; + /* Disable speculative walks through TTBR1 */ + reg64 |= ARM_LPAE_TCR_EPD1; + reg = (uint32_t) reg64; + reg2 = (uint32_t) (reg64 >> 32); + reg2 |= TTBCR2_SEP_UPSTREAM; + reg2 |= TTBCR2_AS; + + mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + + ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + + ARM_SMMU_CB_TTBCR2), reg2); + + mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + + ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + + ARM_SMMU_CB_TTBCR), reg); + + /* TTBR0. */ + asid = smmu->cfg[idx].cbndx; + reg64 = pg_table_base; + reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT; + + mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + + ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + + ARM_SMMU_CB_TTBR0), reg64); + /* TTBR1. */ + reg64 = 0; + reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT; + + mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + + ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + + ARM_SMMU_CB_TTBR1), reg64); + /* MAIR. */ + reg = (ARM_LPAE_MAIR_ATTR_NC + << ARM_LPAE_MAIR_ATTR_SHIFT + (ARM_LPAE_MAIR_ATTR_IDX_NC)) | + (ARM_LPAE_MAIR_ATTR_WBRWA << + ARM_LPAE_MAIR_ATTR_SHIFT + (ARM_LPAE_MAIR_ATTR_IDX_CACHE)) | + (ARM_LPAE_MAIR_ATTR_DEVICE << + ARM_LPAE_MAIR_ATTR_SHIFT + (ARM_LPAE_MAIR_ATTR_IDX_DEV)); + + mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + + ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + + ARM_SMMU_CB_S1_MAIR0), reg); + + /* MAIR1. */ + reg = 0; + mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + + ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + + ARM_SMMU_CB_S1_MAIR1), reg); + /* SCTLR. */ + reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M; + /* stage 1.*/ + reg |= SCTLR_S1_ASIDPNE; + mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) + + ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) + + ARM_SMMU_CB_SCTLR), reg); + } + smmu_set_pgtbl(smmu, dom, (uint64_t *)pg_table_base); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c new file mode 100644 index 0000000..58ea9e2 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include +#include +#include + +static const char *const io_drives[] = { + "2mA", "4mA", "6mA", "8mA", + "10mA", "12mA", "14mA", "16mA" +}; + +void brcm_stingray_ncsi_init(void) +{ + unsigned int i = 0; + unsigned int selx = 0; + +#if NCSI_IO_DRIVE_STRENGTH_MA == 2 + selx = 0x0; +#elif NCSI_IO_DRIVE_STRENGTH_MA == 4 + selx = 0x1; +#elif NCSI_IO_DRIVE_STRENGTH_MA == 6 + selx = 0x2; +#elif NCSI_IO_DRIVE_STRENGTH_MA == 8 + selx = 0x3; +#elif NCSI_IO_DRIVE_STRENGTH_MA == 10 + selx = 0x4; +#elif NCSI_IO_DRIVE_STRENGTH_MA == 12 + selx = 0x5; +#elif NCSI_IO_DRIVE_STRENGTH_MA == 14 + selx = 0x6; +#elif NCSI_IO_DRIVE_STRENGTH_MA == 16 + selx = 0x7; +#else + ERROR("Unsupported NCSI_IO_DRIVE_STRENGTH_MA. Please check it.\n"); + return; +#endif + INFO("ncsi io drives: %s\n", io_drives[selx]); + + for (i = 0; i < NITRO_NCSI_IOPAD_CONTROL_NUM; i++) { + mmio_clrsetbits_32((NITRO_NCSI_IOPAD_CONTROL_BASE + (i * 4)), + PAD_SELX_MASK, PAD_SELX_VALUE(selx)); + } + + INFO("ncsi init done\n"); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c new file mode 100644 index 0000000..89f76d0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c @@ -0,0 +1,911 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define PCIE_CORE_PWR_ARR_POWERON 0x8 +#define PCIE_CORE_PWR_ARR_POWEROK 0x4 +#define PCIE_CORE_PWR_POWERON 0x2 +#define PCIE_CORE_PWR_POWEROK 0x1 + +#define PCIE_CORE_USER_CFG (PCIE_CORE_BASE + 0x38) +#define PCIE_PAXB_SMMU_SID_CFG (PCIE_CORE_BASE + 0x60) +#ifdef SID_B8_D1_F1 +#define PAXB_SMMU_SID_CFG_BUS_WIDTH (0x8 << 8) +#define PAXB_SMMU_SID_CFG_DEV_WIDTH (0x1 << 12) +#define PAXB_SMMU_SID_CFG_FUN_WIDTH (0x1 << 16) +#else +#define PAXB_SMMU_SID_CFG_BUS_WIDTH (0x2 << 8) +#define PAXB_SMMU_SID_CFG_DEV_WIDTH (0x5 << 12) +#define PAXB_SMMU_SID_CFG_FUN_WIDTH (0x3 << 16) +#endif + +#define PAXB_APB_TIMEOUT_COUNT_OFFSET 0x034 + +/* allow up to 5 ms for each power switch to stabilize */ +#define PCIE_CORE_PWR_TIMEOUT_MS 5 + +/* wait 1 microsecond for PCIe core soft reset */ +#define PCIE_CORE_SOFT_RST_DELAY_US 1 + +/* + * List of PAXB APB registers + */ +#define PAXB_BASE 0x48000000 +#define PAXB_BASE_OFFSET 0x4000 +#define PAXB_OFFSET(core) (PAXB_BASE + \ + (core) * PAXB_BASE_OFFSET) + +#define PAXB_CLK_CTRL_OFFSET 0x000 +#define PAXB_EP_PERST_SRC_SEL_MASK (1 << 2) +#define PAXB_EP_MODE_PERST_MASK (1 << 1) +#define PAXB_RC_PCIE_RST_OUT_MASK (1 << 0) + +#define PAXB_MAX_IMAP_WINDOWS 8 +#define PAXB_IMAP_REG_WIDTH 8 +#define PAXB_IMAP0_REG_WIDTH 4 +#define PAXB_AXUSER_REG_WIDTH 4 + +#define PAXB_CFG_IND_ADDR_OFFSET 0x120 +#define PAXB_CFG_IND_DATA_OFFSET 0x124 +#define PAXB_CFG_IND_ADDR_MASK 0x1ffc +#define PAXB_CFG_CFG_TYPE_MASK 0x1 + +#define PAXB_EP_CFG_ADDR_OFFSET 0x1f8 +#define PAXB_EP_CFG_DATA_OFFSET 0x1fc +#define PAXB_EP_CFG_ADDR_MASK 0xffc +#define PAXB_EP_CFG_TYPE_MASK 0x1 + +#define PAXB_0_DEFAULT_IMAP 0xed0 +#define DEFAULT_ADDR_INVALID BIT(0) +#define PAXB_0_DEFAULT_IMAP_AXUSER 0xed8 +#define PAXB_0_DEFAULT_IMAP_AXCACHE 0xedc +#define IMAP_AXCACHE 0xff +#define OARR_VALID BIT(0) +#define IMAP_VALID BIT(0) + +#define PAXB_IMAP0_BASE_OFFSET 0xc00 +#define PAXB_IARR0_BASE_OFFSET 0xd00 +#define PAXB_IMAP0_OFFSET(idx) (PAXB_IMAP0_BASE_OFFSET + \ + (idx) * PAXB_IMAP0_REG_WIDTH) +#define PAXB_IMAP0_WINDOW_SIZE 0x1000 + +#define PAXB_IMAP2_OFFSET 0xcc0 +#define PAXB_IMAP0_REGS_TYPE_OFFSET 0xcd0 +#define PAXB_IARR2_LOWER_OFFSET 0xd10 + +#define PAXB_IMAP3_BASE_OFFSET 0xe08 +#define PAXB_IMAP3_OFFSET(idx) (PAXB_IMAP3_BASE_OFFSET + \ + (idx) * PAXB_IMAP_REG_WIDTH) + +#define PAXB_IMAP3_0_AXUSER_B_OFFSET 0xe48 +#define PAXB_IMAP3_0_AXUSER_OFFSET(idx) (PAXB_IMAP3_0_AXUSER_B_OFFSET + \ + (idx) * PAXB_AXUSER_REG_WIDTH) + +#define PAXB_IMAP4_BASE_OFFSET 0xe70 +#define PAXB_IMAP4_OFFSET(idx) (PAXB_IMAP4_BASE_OFFSET + \ + (idx) * PAXB_IMAP_REG_WIDTH) + +#define PAXB_IMAP4_0_AXUSER_B_OFFSET 0xeb0 +#define PAXB_IMAP4_0_AXUSER_OFFSET(idx) (PAXB_IMAP4_0_AXUSER_B_OFFSET + \ + (idx) * PAXB_AXUSER_REG_WIDTH) + +#define PAXB_CFG_LINK_STATUS_OFFSET 0xf0c +#define PAXB_CFG_PHYLINKUP_MASK (1 << 3) +#define PAXB_CFG_DL_ACTIVE_MASK (1 << 2) + +#define PAXB_IMAP0_0_AXUSER_OFFSET 0xf60 +#define PAXB_IMAP2_AXUSER_OFFSET 0xfe0 + +/* cacheable write-back, allocate on both reads and writes */ +#define IMAP_ARCACHE 0x0f0 +#define IMAP_AWCACHE 0xf00 +/* normal access, nonsecure access, and data access */ +/* AWQOS:0xe and ARQOS:0xa */ +/* AWPROT:0x2 and ARPROT:0x1 */ +#define IMAP_AXUSER 0x002e002a + +/* + * List of NIC security and PIPEMUX related registers + */ +#define SR_PCIE_NIC_SECURITY_BASE 0x58100000 +#define NS3Z_PCIE_NIC_SECURITY_BASE 0x48100000 + +#define GITS_TRANSLATER 0x63c30000 + +#define VENDOR_ID 0x14e4 +#define CFG_RC_DEV_ID 0x434 +#define CFG_RC_DEV_SUBID 0x438 +#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c +#define PCI_CLASS_BRIDGE_MASK 0xffff00 +#define PCI_CLASS_BRIDGE_SHIFT 8 +#define PCI_CLASS_BRIDGE_PCI 0x0604 + +/* + * List of PAXB RC configuration space registers + */ + +/* first capability list entry */ +#define PCI_CAPABILITY_LIST_OFFSET 0x34 +#define PCI_CAPABILITY_SPEED_OFFSET 0xc +#define PCI_EP_CAPABILITY_OFFSET 0x10 + +#define CFG_RC_LINK_STATUS_CTRL_2 0x0dc +#define CFG_RC_LINK_SPEED_SHIFT 0 +#define CFG_RC_LINK_SPEED_MASK (0xf << CFG_RC_LINK_SPEED_SHIFT) + +#define CFG_RC_DEVICE_CAP 0x4d4 +#define CFG_RC_DEVICE_CAP_MPS_SHIFT 0 +#define CFG_RC_DEVICE_CAP_MPS_MASK (0x7 << CFG_RC_DEVICE_CAP_MPS_SHIFT) +/* MPS 256 bytes */ +#define CFG_RC_DEVICE_CAP_MPS_256B (0x1 << CFG_RC_DEVICE_CAP_MPS_SHIFT) +/* MPS 512 bytes */ +#define CFG_RC_DEVICE_CAP_MPS_512B (0x2 << CFG_RC_DEVICE_CAP_MPS_SHIFT) + +#define CFG_RC_TL_FCIMM_NP_LIMIT 0xa10 +#define CFG_RC_TL_FCIMM_NP_VAL 0x01500000 +#define CFG_RC_TL_FCIMM_P_LIMIT 0xa14 +#define CFG_RC_TL_FCIMM_P_VAL 0x03408080 + +#define CFG_RC_LINK_CAP 0x4dc +#define CFG_RC_LINK_CAP_SPEED_SHIFT 0 +#define CFG_RC_LINK_CAP_SPEED_MASK (0xf << CFG_RC_LINK_CAP_SPEED_SHIFT) +#define CFG_RC_LINK_CAP_WIDTH_SHIFT 4 +#define CFG_RC_LINK_CAP_WIDTH_MASK (0x1f << CFG_RC_LINK_CAP_WIDTH_SHIFT) + +#define CFG_LINK_CAP_RC 0x4f0 +#define CFG_RC_DL_ACTIVE_SHIFT 0 +#define CFG_RC_DL_ACTIVE_MASK (0x1 << CFG_RC_DL_ACTIVE_SHIFT) +#define CFG_RC_SLOT_CLK_SHIFT 1 +#define CFG_RC_SLOT_CLK_MASK (0x1 << CFG_RC_SLOT_CLK_SHIFT) + +#define CFG_ROOT_CAP_RC 0x4f8 +#define CFG_ROOT_CAP_LTR_SHIFT 1 +#define CFG_ROOT_CAP_LTR_MASK (0x1 << CFG_ROOT_CAP_LTR_SHIFT) + +#define CFG_RC_CLKREQ_ENABLED 0x4fc +#define CFG_RC_CLKREQ_ENABLED_SHIFT 0 +#define CFG_RC_CLKREQ_ENABLED_MASK (0x1 << CFG_RC_CLKREQ_ENABLED_SHIFT) + +#define CFG_RC_COEFF_ADDR 0x638 + +#define CFG_RC_TL_CTRL_0 0x800 +#define RC_MEM_DW_CHK_MASK 0x03fe + +#define CFG_RC_PDL_CTRL_4 0x1010 +#define NPH_FC_INIT_SHIFT 24 +#define NPH_FC_INIT_MASK (U(0xff) << NPH_FC_INIT_SHIFT) +#define PD_FC_INIT_SHIFT 12 +#define PD_FC_INIT_MASK (0xffff << PD_FC_INIT_SHIFT) + +#define CFG_RC_PDL_CTRL_5 0x1014 +#define PH_INIT_SHIFT 0 +#define PH_INIT_MASK (0xff << PH_INIT_SHIFT) + +#define DL_STATUS_OFFSET 0x1048 +#define PHYLINKUP BIT(13) + +#define PH_INIT 0x10 +#define PD_FC_INIT 0x100 +#define NPH_FC_INIT 0x8 + +#define SRP_PH_INIT 0x7F +#define SRP_PD_FC_INIT 0x200 +#define SRP_NPH_FC_INIT 0x7F + +#define CFG_ADDR_BUS_NUM_SHIFT 20 +#define CFG_ADDR_DEV_NUM_SHIFT 15 +#define CFG_ADDR_FUNC_NUM_SHIFT 12 +#define CFG_ADDR_REG_NUM_SHIFT 2 +#define CFG_ADDR_REG_NUM_MASK 0x00000ffc +#define CFG_ADDR_CFG_TYPE_MASK 0x00000003 + +#define DL_LINK_UP_TIMEOUT_MS 1000 + +#define CFG_RETRY_STATUS 0xffff0001 +#define CRS_TIMEOUT_MS 5000 + +/* create EP config data to write */ +#define DEF_BUS_NO 1 /* default bus 1 */ +#define DEF_SLOT_NO 0 /* default slot 0 */ +#define DEF_FN_NO 0 /* default fn 0 */ + +#define EP_CONFIG_VAL(bus_no, slot, fn, where) \ + (((bus_no) << CFG_ADDR_BUS_NUM_SHIFT) | \ + ((slot) << CFG_ADDR_DEV_NUM_SHIFT) | \ + ((fn) << CFG_ADDR_FUNC_NUM_SHIFT) | \ + ((where) & CFG_ADDR_REG_NUM_MASK) | \ + (1 & CFG_ADDR_CFG_TYPE_MASK)) + +/* PAXB security offset */ +#define PAXB_SECURITY_IDM_OFFSET 0x1c +#define PAXB_SECURITY_APB_OFFSET 0x24 +#define PAXB_SECURITY_ECAM_OFFSET 0x3c + +#define paxb_get_config(type) paxb_get_##type##_config() + +static unsigned int paxb_sec_reg_offset[] = { + 0x0c, /* PAXB0 AXI */ + 0x10, /* PAXB1 AXI */ + 0x14, /* PAXB2 AXI */ + 0x18, /* PAXB3 AXI */ + 0x20, /* PAXB4 AXI */ + 0x28, /* PAXB5 AXI */ + 0x2c, /* PAXB6 AXI */ + 0x30, /* PAXB7 AXI */ + 0x24, /* PAXB APB */ +}; + +const paxb_cfg *paxb; + +/* + * Given a PIPEMUX strap and PCIe core index, this function returns 1 if a + * PCIe core needs to be enabled + */ +int pcie_core_needs_enable(unsigned int core_idx) +{ + if (paxb->core_needs_enable) + return paxb->core_needs_enable(core_idx); + + return 0; +} + +static void pcie_set_default_tx_coeff(uint32_t core_idx, uint32_t link_width) +{ + unsigned int lanes = 0; + uint32_t data, addr; + + addr = CFG_RC_COEFF_ADDR; + for (lanes = 0; lanes < link_width; lanes = lanes + 2) { + data = paxb_rc_cfg_read(core_idx, addr); + data &= 0xf0f0f0f0; + data |= (7 & 0xf); + data |= (7 & 0xf) << 8; + data |= (7 & 0xf) << 16; + data |= (7 & 0xf) << 24; + + paxb_rc_cfg_write(core_idx, addr, data); + addr += 4; + } +} + +static int paxb_rc_link_init(void) +{ + uint32_t val, link_speed; + unsigned int link_width; + uint32_t core_idx; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + link_width = paxb->get_link_width(core_idx); + if (!link_width) { + ERROR("Unsupported PIPEMUX\n"); + return -EOPNOTSUPP; + } + + link_speed = paxb->get_link_speed(); + /* program RC's link cap reg to advertise proper link width */ + val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP); + val &= ~CFG_RC_LINK_CAP_WIDTH_MASK; + val |= (link_width << CFG_RC_LINK_CAP_WIDTH_SHIFT); + paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val); + + /* program RC's link cap reg to advertise proper link speed */ + val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP); + val &= ~CFG_RC_LINK_CAP_SPEED_MASK; + val |= link_speed << CFG_RC_LINK_CAP_SPEED_SHIFT; + paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val); + + /* also need to program RC's link status control register */ + val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_STATUS_CTRL_2); + val &= ~(CFG_RC_LINK_SPEED_MASK); + val |= link_speed << CFG_RC_LINK_SPEED_SHIFT; + paxb_rc_cfg_write(core_idx, CFG_RC_LINK_STATUS_CTRL_2, val); + +#ifdef WAR_PLX_PRESET_PARITY_FAIL + /* WAR to avoid crash with PLX switch in GEN3*/ + /* While PRESET, PLX switch is not fixing parity so disabled */ + val = paxb_rc_cfg_read(core_idx, CFG_RC_REG_PHY_CTL_10); + val &= ~(PHY_CTL_10_GEN3_MATCH_PARITY); + paxb_rc_cfg_write(core_idx, CFG_RC_REG_PHY_CTL_10, val); +#endif + pcie_set_default_tx_coeff(core_idx, link_width); + } + return 0; +} + +#ifdef PAXB_LINKUP +static void paxb_perst_ctrl(unsigned int core_idx, bool assert) +{ + uint32_t clk_ctrl = PAXB_OFFSET(core_idx) + PAXB_CLK_CTRL_OFFSET; + + if (assert) { + mmio_clrbits_32(clk_ctrl, PAXB_EP_PERST_SRC_SEL_MASK | + PAXB_EP_MODE_PERST_MASK | + PAXB_RC_PCIE_RST_OUT_MASK); + udelay(250); + } else { + mmio_setbits_32(clk_ctrl, PAXB_RC_PCIE_RST_OUT_MASK); + mdelay(100); + } +} + +static void paxb_start_link_up(void) +{ + unsigned int core_idx; + uint32_t val, timeout; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + /* toggle PERST */ + paxb_perst_ctrl(core_idx, true); + paxb_perst_ctrl(core_idx, false); + + timeout = DL_LINK_UP_TIMEOUT_MS; + /* wait for Link up */ + do { + val = mmio_read_32(PAXB_OFFSET(core_idx) + + PAXB_CFG_LINK_STATUS_OFFSET); + if (val & PAXB_CFG_DL_ACTIVE_MASK) + break; + + mdelay(1); + } while (--timeout); + + if (!timeout) + ERROR("PAXB core %u link is down\n", core_idx); + } +} +#endif + +static void pcie_core_soft_reset(unsigned int core_idx) +{ + uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET; + uintptr_t ctrl = (uintptr_t)(PCIE_CORE_SOFT_RST_CFG_BASE + offset); + + /* Put PCIe core in soft reset */ + mmio_clrbits_32(ctrl, PCIE_CORE_SOFT_RST); + + /* Wait for 1 us before pulling PCIe core out of soft reset */ + udelay(PCIE_CORE_SOFT_RST_DELAY_US); + + mmio_setbits_32(ctrl, PCIE_CORE_SOFT_RST); +} + +static int pcie_core_pwron_switch(uintptr_t ctrl, uintptr_t status, + uint32_t mask) +{ + uint32_t val; + unsigned int timeout = PCIE_CORE_PWR_TIMEOUT_MS; + + /* enable switch */ + mmio_setbits_32(ctrl, mask); + + /* now wait for it to stabilize */ + do { + val = mmio_read_32(status); + if ((val & mask) == mask) + return 0; + mdelay(1); + } while (--timeout); + + return -EIO; +} + +static int pcie_core_pwr_seq(uintptr_t ctrl, uintptr_t status) +{ + int ret; + + /* + * Enable the switch with the following sequence: + * 1. Array weak switch output switch + * 2. Array strong switch + * 3. Weak switch output acknowledge + * 4. Strong switch output acknowledge + */ + ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWERON); + if (ret) + return ret; + + ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWEROK); + if (ret) + return ret; + + ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWERON); + if (ret) + return ret; + + ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWEROK); + if (ret) + return ret; + + return 0; +} + +/* + * This function enables PCIe core and PAXB memory buffer power, and then + * remove the PCIe core from isolation + */ +static int pcie_core_pwr_init(unsigned int core_idx) +{ + int ret; + uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET; + uintptr_t ctrl, status; + + /* enable mem power to PCIe core */ + ctrl = (uintptr_t)(PCIE_CORE_MEM_PWR_BASE + offset); + status = (uintptr_t)(PCIE_CORE_MEM_PWR_STATUS_BASE + offset); + ret = pcie_core_pwr_seq(ctrl, status); + if (ret) { + ERROR("PCIe core mem power failed\n"); + return ret; + } + + /* now enable mem power to PAXB wrapper */ + ctrl = (uintptr_t)(PCIE_PAXB_MEM_PWR_BASE + offset); + status = (uintptr_t)(PCIE_PAXB_MEM_PWR_STATUS_BASE + offset); + ret = pcie_core_pwr_seq(ctrl, status); + if (ret) { + ERROR("PAXB mem power failed\n"); + return ret; + } + + /* now remove power isolation */ + ctrl = (uintptr_t)(PCIE_CORE_ISO_CFG_BASE + offset); + mmio_clrbits_32(ctrl, PCIE_CORE_ISO | PCIE_CORE_MEM_ISO); + + return 0; +} + +static void pcie_ss_reset(void) +{ + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, + 1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R); +} + +/* + * This function reads the PIPEMUX strap, figures out all the PCIe cores that + * need to be enabled and enable the mem power for those cores + */ +static int pcie_cores_init(void) +{ + int ret = 0; + uint32_t core_idx; + + if (paxb->pipemux_init) { + ret = paxb->pipemux_init(); + if (ret) + return ret; + } + + /* bring PCIe subsystem out of reset */ + pcie_ss_reset(); + + /* power up all PCIe cores that will be used as RC */ + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + ret = pcie_core_pwr_init(core_idx); + if (ret) { + ERROR("PCIe core %u power up failed\n", core_idx); + return ret; + } + + pcie_core_soft_reset(core_idx); + + VERBOSE("PCIe core %u is powered up\n", core_idx); + } + + return ret; +} + +void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where, + uint32_t val) +{ + mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET, + (where & PAXB_CFG_IND_ADDR_MASK) | + PAXB_CFG_CFG_TYPE_MASK); + mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET, val); +} + +unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where) +{ + unsigned int val; + + mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET, + (where & PAXB_CFG_IND_ADDR_MASK) | + PAXB_CFG_CFG_TYPE_MASK); + val = mmio_read_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET); + + return val; +} + +static void paxb_cfg_mps(void) +{ + uint32_t val, core_idx, mps; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + val = paxb_rc_cfg_read(core_idx, CFG_RC_DEVICE_CAP); + val &= ~CFG_RC_DEVICE_CAP_MPS_MASK; + mps = CFG_RC_DEVICE_CAP_MPS_256B; + if (core_idx == 0 || core_idx == 1 || + core_idx == 6 || core_idx == 7) { + mps = CFG_RC_DEVICE_CAP_MPS_512B; + } + val |= mps; + paxb_rc_cfg_write(core_idx, CFG_RC_DEVICE_CAP, val); + } +} + +static void paxb_cfg_dev_id(void) +{ + uint32_t val, core_idx; + uint32_t device_id; + + device_id = paxb->device_id; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + /* Set Core in RC mode */ + mmio_setbits_32(PCIE_CORE_USER_CFG + + (core_idx * PCIE_CORE_PWR_OFFSET), 1); + + /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ + val = paxb_rc_cfg_read(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET); + val &= ~PCI_CLASS_BRIDGE_MASK; + val |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); + paxb_rc_cfg_write(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET, val); + + val = (VENDOR_ID << 16) | device_id; + paxb_rc_cfg_write(core_idx, CFG_RC_DEV_ID, val); + + val = (device_id << 16) | VENDOR_ID; + paxb_rc_cfg_write(core_idx, CFG_RC_DEV_SUBID, val); + } +} + +static void paxb_cfg_tgt_trn(void) +{ + uint32_t val, core_idx; + + /* + * Disable all mem Rd/Wr size check so it allows target read/write + * transactions to be more than stipulated DW. As a result, PAXB root + * complex will not abort these read/write transcations beyond + * stipulated limit + */ + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + val = paxb_rc_cfg_read(core_idx, CFG_RC_TL_CTRL_0); + val &= ~(RC_MEM_DW_CHK_MASK); + paxb_rc_cfg_write(core_idx, CFG_RC_TL_CTRL_0, val); + } +} + +static void paxb_cfg_pdl_ctrl(void) +{ + uint32_t val, core_idx; + uint32_t nph, ph, pd; + + /* increase the credit counter to 4 for non-posted header */ + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + nph = NPH_FC_INIT; + ph = PH_INIT; + pd = PD_FC_INIT; + + if (core_idx == 0 || core_idx == 1 || + core_idx == 6 || core_idx == 7) { + nph = SRP_NPH_FC_INIT; + ph = SRP_PH_INIT; + pd = SRP_PD_FC_INIT; + } + val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_4); + val &= ~NPH_FC_INIT_MASK; + val &= ~PD_FC_INIT_MASK; + val = val | (nph << NPH_FC_INIT_SHIFT); + val = val | (pd << PD_FC_INIT_SHIFT); + paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_4, val); + + val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_5); + val &= ~PH_INIT_MASK; + val = val | (ph << PH_INIT_SHIFT); + paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_5, val); + + /* + * ASIC to give more optmized value after further investigation. + * till then this is important to have to get similar + * performance on all the slots. + */ + paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_NP_LIMIT, + CFG_RC_TL_FCIMM_NP_VAL); + + paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_P_LIMIT, + CFG_RC_TL_FCIMM_P_VAL); + } +} + +static void paxb_cfg_clkreq(void) +{ + uint32_t val, core_idx; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + val = paxb_rc_cfg_read(core_idx, CFG_RC_CLKREQ_ENABLED); + val &= ~CFG_RC_CLKREQ_ENABLED_MASK; + paxb_rc_cfg_write(core_idx, CFG_RC_CLKREQ_ENABLED, val); + } +} + +static void paxb_cfg_dl_active(bool enable) +{ + uint32_t val, core_idx; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + val = paxb_rc_cfg_read(core_idx, CFG_LINK_CAP_RC); + if (enable) + val |= CFG_RC_DL_ACTIVE_MASK; + else + val &= ~CFG_RC_DL_ACTIVE_MASK; + paxb_rc_cfg_write(core_idx, CFG_LINK_CAP_RC, val); + } +} + +static void paxb_cfg_LTR(int enable) +{ + uint32_t val, core_idx; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + val = paxb_rc_cfg_read(core_idx, CFG_ROOT_CAP_RC); + if (enable) + val |= CFG_ROOT_CAP_LTR_MASK; + else + val &= ~CFG_ROOT_CAP_LTR_MASK; + paxb_rc_cfg_write(core_idx, CFG_ROOT_CAP_RC, val); + } +} + +static void paxb_ib_regs_bypass(void) +{ + unsigned int i, j; + + for (i = 0; i < paxb->num_cores; i++) { + if (!pcie_core_needs_enable(i)) + continue; + + /* Configure Default IMAP window */ + mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP, + DEFAULT_ADDR_INVALID); + mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXUSER, + IMAP_AXUSER); + mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXCACHE, + IMAP_AXCACHE); + + /* Configure MSI IMAP window */ + mmio_setbits_32(PAXB_OFFSET(i) + + PAXB_IMAP0_REGS_TYPE_OFFSET, + 0x1); + mmio_write_32(PAXB_OFFSET(i) + PAXB_IARR0_BASE_OFFSET, + GITS_TRANSLATER | OARR_VALID); + for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) { + mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j), + (GITS_TRANSLATER + + (j * PAXB_IMAP0_WINDOW_SIZE)) | + IMAP_VALID); + } + } +} + +static void paxb_ib_regs_init(void) +{ + unsigned int core_idx; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + /* initialize IARR2 to zero */ + mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_IARR2_LOWER_OFFSET, + 0x0); + mmio_setbits_32(PAXB_OFFSET(core_idx) + + PAXB_IMAP0_REGS_TYPE_OFFSET, + 0x1); + } +} + +static void paxb_cfg_apb_timeout(void) +{ + unsigned int core_idx; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + /* allow unlimited timeout */ + mmio_write_32(PAXB_OFFSET(core_idx) + + PAXB_APB_TIMEOUT_COUNT_OFFSET, + 0xFFFFFFFF); + } +} + +static void paxb_smmu_cfg(void) +{ + unsigned int core_idx; + uint32_t offset; + uint32_t val; + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + + offset = core_idx * PCIE_CORE_PWR_OFFSET; + val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset); + val &= ~(0xFFF00); + val |= (PAXB_SMMU_SID_CFG_FUN_WIDTH | + PAXB_SMMU_SID_CFG_DEV_WIDTH | + PAXB_SMMU_SID_CFG_BUS_WIDTH); + mmio_write_32(PCIE_PAXB_SMMU_SID_CFG + offset, val); + val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset); + VERBOSE("smmu cfg reg 0x%x\n", val); + } +} + +static void paxb_cfg_coherency(void) +{ + unsigned int i, j; + + for (i = 0; i < paxb->num_cores; i++) { + if (!pcie_core_needs_enable(i)) + continue; + +#ifdef USE_DDR + mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_OFFSET, + IMAP_ARCACHE | IMAP_AWCACHE); +#endif + + mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_0_AXUSER_OFFSET, + IMAP_AXUSER); + + mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_AXUSER_OFFSET, + IMAP_AXUSER); + + for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) { +#ifdef USE_DDR + mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP3_OFFSET(j), + IMAP_ARCACHE | IMAP_AWCACHE); + mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP4_OFFSET(j), + IMAP_ARCACHE | IMAP_AWCACHE); +#endif + /* zero out IMAP0 mapping windows for MSI/MSI-X */ + mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j), + 0x0); + + mmio_write_32(PAXB_OFFSET(i) + + PAXB_IMAP3_0_AXUSER_OFFSET(j), + IMAP_AXUSER); + mmio_write_32(PAXB_OFFSET(i) + + PAXB_IMAP4_0_AXUSER_OFFSET(j), + IMAP_AXUSER); + } + } +} + +/* + * This function configures all PAXB related blocks to allow non-secure access + */ +void paxb_ns_init(enum paxb_type type) +{ + unsigned int reg; + + switch (type) { + case PAXB_SR: + for (reg = 0; reg < ARRAY_SIZE(paxb_sec_reg_offset); reg++) { + + mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE + + paxb_sec_reg_offset[reg], 0x1); + } + /* Enabled all PAXB's relevant IDM blocks access in non-secure mode */ + mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE + PAXB_SECURITY_IDM_OFFSET, + 0xffff); + break; + case PAXB_NS3Z: + mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE + + paxb_sec_reg_offset[0], 0x1); + mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE + + PAXB_SECURITY_IDM_OFFSET, 0xffff); + mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE + + PAXB_SECURITY_APB_OFFSET, 0x7); + mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE + + PAXB_SECURITY_ECAM_OFFSET, 0x1); + break; + } +} + +static int paxb_set_config(void) +{ + paxb = paxb_get_config(sr); + if (paxb) + return 0; + + return -ENODEV; +} + +void paxb_init(void) +{ + int ret; + + ret = paxb_set_config(); + if (ret) + return; + + paxb_ns_init(paxb->type); + + ret = pcie_cores_init(); + if (ret) + return; + + if (paxb->phy_init) { + ret = paxb->phy_init(); + if (ret) + return; + } + + paxb_cfg_dev_id(); + paxb_cfg_tgt_trn(); + paxb_cfg_pdl_ctrl(); + if (paxb->type == PAXB_SR) { + paxb_ib_regs_init(); + paxb_cfg_coherency(); + } else + paxb_ib_regs_bypass(); + + paxb_cfg_apb_timeout(); + paxb_smmu_cfg(); + paxb_cfg_clkreq(); + paxb_rc_link_init(); + + /* Stingray Doesn't support LTR */ + paxb_cfg_LTR(false); + paxb_cfg_dl_active(true); + + paxb_cfg_mps(); + +#ifdef PAXB_LINKUP + paxb_start_link_up(); +#endif + INFO("PAXB init done\n"); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c new file mode 100644 index 0000000..44af4b0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#define PAXC_BASE 0x60400000 +#define PAXC_AXI_CFG_PF 0x10 +#define PAXC_AXI_CFG_PF_OFFSET(pf) (PAXC_AXI_CFG_PF + (pf) * 4) +#define PAXC_ARPROT_PF_CFG 0x40 +#define PAXC_AWPROT_PF_CFG 0x44 + +#define PAXC_ARQOS_PF_CFG 0x48 +#define PAXC_ARQOS_VAL 0xaaaaaaaa + +#define PAXC_AWQOS_PF_CFG 0x4c +#define PAXC_AWQOS_VAL 0xeeeeeeee + +#define PAXC_CFG_IND_ADDR_OFFSET 0x1f0 +#define PAXC_CFG_IND_ADDR_MASK 0xffc +#define PAXC_CFG_IND_DATA_OFFSET 0x1f4 + +/* offsets for PAXC root complex configuration space registers */ + +#define PAXC_CFG_ID_OFFSET 0x434 +#define PAXC_RC_VENDOR_ID 0x14e4 +#define PAXC_RC_VENDOR_ID_SHIFT 16 + +#define PAXC_RC_DEVICE_ID 0xd750 + +#define PAXC_CFG_LINK_CAP_OFFSET 0x4dc +#define PAXC_RC_LINK_CAP_SPD_SHIFT 0 +#define PAXC_RC_LINK_CAP_SPD_MASK (0xf << PAXC_RC_LINK_CAP_SPD_SHIFT) +#define PAXC_RC_LINK_CAP_SPD 3 +#define PAXC_RC_LINK_CAP_WIDTH_SHIFT 4 +#define PAXC_RC_LINK_CAP_WIDTH_MASK (0x1f << PAXC_RC_LINK_CAP_WIDTH_SHIFT) +#define PAXC_RC_LINK_CAP_WIDTH 16 + +/* offsets for MHB registers */ + +#define MHB_BASE 0x60401000 +#define MHB_MEM_PWR_STATUS_PAXC (MHB_BASE + 0x1c0) +#define MHB_PWR_ARR_POWERON 0x8 +#define MHB_PWR_ARR_POWEROK 0x4 +#define MHB_PWR_POWERON 0x2 +#define MHB_PWR_POWEROK 0x1 +#define MHB_PWR_STATUS_MASK (MHB_PWR_ARR_POWERON | \ + MHB_PWR_ARR_POWEROK | \ + MHB_PWR_POWERON | \ + MHB_PWR_POWEROK) + +/* max number of PFs from Nitro that PAXC sees */ +#define MAX_NR_NITRO_PF 8 + +#ifdef EMULATION_SETUP +static void paxc_reg_dump(void) +{ +} +#else +/* total number of PAXC registers */ +#define NR_PAXC_REGS 53 +static void paxc_reg_dump(void) +{ + uint32_t idx, offset = 0; + + VERBOSE("PAXC register dump start\n"); + for (idx = 0; idx < NR_PAXC_REGS; idx++, offset += 4) + VERBOSE("offset: 0x%x val: 0x%x\n", offset, + mmio_read_32(PAXC_BASE + offset)); + VERBOSE("PAXC register dump end\n"); +} +#endif /* EMULATION_SETUP */ + +#ifdef EMULATION_SETUP +static void mhb_reg_dump(void) +{ +} +#else +#define NR_MHB_REGS 227 +static void mhb_reg_dump(void) +{ + uint32_t idx, offset = 0; + + VERBOSE("MHB register dump start\n"); + for (idx = 0; idx < NR_MHB_REGS; idx++, offset += 4) + VERBOSE("offset: 0x%x val: 0x%x\n", offset, + mmio_read_32(MHB_BASE + offset)); + VERBOSE("MHB register dump end\n"); +} +#endif /* EMULATION_SETUP */ + +static void paxc_rc_cfg_write(uint32_t where, uint32_t val) +{ + mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET, + where & PAXC_CFG_IND_ADDR_MASK); + mmio_write_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET, val); +} + +static uint32_t paxc_rc_cfg_read(uint32_t where) +{ + mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET, + where & PAXC_CFG_IND_ADDR_MASK); + return mmio_read_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET); +} + +/* + * Function to program PAXC root complex link capability register + */ +static void paxc_cfg_link_cap(void) +{ + uint32_t val; + + val = paxc_rc_cfg_read(PAXC_CFG_LINK_CAP_OFFSET); + val &= ~(PAXC_RC_LINK_CAP_SPD_MASK | PAXC_RC_LINK_CAP_WIDTH_MASK); + val |= (PAXC_RC_LINK_CAP_SPD << PAXC_RC_LINK_CAP_SPD_SHIFT) | + (PAXC_RC_LINK_CAP_WIDTH << PAXC_RC_LINK_CAP_WIDTH_SHIFT); + paxc_rc_cfg_write(PAXC_CFG_LINK_CAP_OFFSET, val); +} + +/* + * Function to program PAXC root complex vendor ID and device ID + */ +static void paxc_cfg_id(void) +{ + uint32_t val; + + val = (PAXC_RC_VENDOR_ID << PAXC_RC_VENDOR_ID_SHIFT) | + PAXC_RC_DEVICE_ID; + paxc_rc_cfg_write(PAXC_CFG_ID_OFFSET, val); +} + +void paxc_init(void) +{ + unsigned int pf_index; + unsigned int val; + + val = mmio_read_32(MHB_MEM_PWR_STATUS_PAXC); + if ((val & MHB_PWR_STATUS_MASK) != MHB_PWR_STATUS_MASK) { + INFO("PAXC not powered\n"); + return; + } + + paxc_cfg_id(); + paxc_cfg_link_cap(); + + paxc_reg_dump(); + mhb_reg_dump(); + +#ifdef USE_DDR + /* + * Set AWCACHE and ARCACHE to 0xff (Cacheable write-back, + * allocate on both reads and writes) per + * recommendation from the ASIC team + */ + val = 0xff; +#else + /* disable IO cache if non-DDR memory is used, e.g., external SRAM */ + val = 0x0; +#endif + for (pf_index = 0; pf_index < MAX_NR_NITRO_PF; pf_index++) + mmio_write_32(PAXC_BASE + PAXC_AXI_CFG_PF_OFFSET(pf_index), + val); + + /* + * Set ARPROT and AWPROT to enable non-secure access from + * PAXC to all PFs, PF0 to PF7 + */ + mmio_write_32(PAXC_BASE + PAXC_ARPROT_PF_CFG, 0x22222222); + mmio_write_32(PAXC_BASE + PAXC_AWPROT_PF_CFG, 0x22222222); + + mmio_write_32(PAXC_BASE + PAXC_ARQOS_PF_CFG, PAXC_ARQOS_VAL); + mmio_write_32(PAXC_BASE + PAXC_AWQOS_PF_CFG, PAXC_AWQOS_VAL); + + INFO("PAXC init done\n"); +} + +/* + * These defines do not match the regfile but they are renamed in a way such + * that they are much more readible + */ + +#define MHB_NIC_SECURITY_BASE 0x60500000 +#define MHB_NIC_PAXC_AXI_NS 0x0008 +#define MHB_NIC_IDM_NS 0x000c +#define MHB_NIC_MHB_APB_NS 0x0010 +#define MHB_NIC_NITRO_AXI_NS 0x0014 +#define MHB_NIC_PCIE_AXI_NS 0x0018 +#define MHB_NIC_PAXC_APB_NS 0x001c +#define MHB_NIC_EP_APB_NS 0x0020 + +#define MHB_NIC_PAXC_APB_S_IDM_SHIFT 5 +#define MHB_NIC_EP_APB_S_IDM_SHIFT 4 +#define MHB_NIC_MHB_APB_S_IDM_SHIFT 3 +#define MHB_NIC_PAXC_AXI_S_IDM_SHIFT 2 +#define MHB_NIC_PCIE_AXI_S_IDM_SHIFT 1 +#define MHB_NIC_NITRO_AXI_S_IDM_SHIFT 0 + +#define NIC400_NITRO_TOP_NIC_SECURITY_BASE 0x60d00000 + +#define NITRO_NIC_SECURITY_3_SHIFT 0x14 +#define NITRO_NIC_SECURITY_4_SHIFT 0x18 +#define NITRO_NIC_SECURITY_5_SHIFT 0x1c +#define NITRO_NIC_SECURITY_6_SHIFT 0x20 + +void paxc_mhb_ns_init(void) +{ + unsigned int val; + uintptr_t mhb_nic_gpv = MHB_NIC_SECURITY_BASE; +#ifndef NITRO_SECURE_ACCESS + uintptr_t nic400_nitro_gpv = NIC400_NITRO_TOP_NIC_SECURITY_BASE; +#endif /* NITRO_SECURE_ACCESS */ + + /* set PAXC AXI to allow non-secure access */ + val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS); + val |= 0x1; + mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS, val); + + /* set various MHB IDM interfaces to allow non-secure access */ + val = mmio_read_32(mhb_nic_gpv + MHB_NIC_IDM_NS); + val |= (0x1 << MHB_NIC_PAXC_APB_S_IDM_SHIFT); + val |= (0x1 << MHB_NIC_EP_APB_S_IDM_SHIFT); + val |= (0x1 << MHB_NIC_MHB_APB_S_IDM_SHIFT); + val |= (0x1 << MHB_NIC_PAXC_AXI_S_IDM_SHIFT); + val |= (0x1 << MHB_NIC_PCIE_AXI_S_IDM_SHIFT); + val |= (0x1 << MHB_NIC_NITRO_AXI_S_IDM_SHIFT); + mmio_write_32(mhb_nic_gpv + MHB_NIC_IDM_NS, val); + + /* set MHB APB to allow non-secure access */ + val = mmio_read_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS); + val |= 0x1; + mmio_write_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS, val); + + /* set Nitro AXI to allow non-secure access */ + val = mmio_read_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS); + val |= 0x1; + mmio_write_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS, val); + + /* set PCIe AXI to allow non-secure access */ + val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS); + val |= 0x1; + mmio_write_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS, val); + + /* set PAXC APB to allow non-secure access */ + val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS); + val |= 0x1; + mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS, val); + + /* set EP APB to allow non-secure access */ + val = mmio_read_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS); + val |= 0x1; + mmio_write_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS, val); + +#ifndef NITRO_SECURE_ACCESS + /* Set NIC400 to allow non-secure access */ + mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_3_SHIFT, 0x1); + mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_4_SHIFT, 0x1); + mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_5_SHIFT, 0x1); + mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_6_SHIFT, 0x1); +#endif /* NITRO_SECURE_ACCESS */ +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c new file mode 100644 index 0000000..a5ac2e7 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_PAXC +#include +#endif +#include +#include +#include +#include + +static uint64_t plat_sec_entrypoint; + +/******************************************************************************* + * SR handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int brcm_pwr_domain_on(u_register_t mpidr) +{ + int cpuid; + + cpuid = plat_brcm_calc_core_pos(mpidr); + INFO("mpidr :%lu, cpuid:%d\n", mpidr, cpuid); + +#ifdef USE_SINGLE_CLUSTER + if (cpuid > 1) + return PSCI_E_INTERN_FAIL; +#endif + + ihost_power_on_cluster(mpidr); + + ihost_power_on_secondary_core(mpidr, plat_sec_entrypoint); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * SR handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr()); + + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + if (target_state->pwr_domain_state[MPIDR_AFFLVL1] == + PLAT_LOCAL_STATE_OFF) { + INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id); + ccn_enter_snoop_dvm_domain(1 << cluster_id); + } + + /* Enable the gic cpu interface */ + plat_brcm_gic_pcpu_init(); + + /* Program the gic per-cpu distributor or re-distributor interface */ + plat_brcm_gic_cpuif_enable(); + + INFO("Gic Initialization done for this affinity instance\n"); +} + +static void __dead2 brcm_system_reset(void) +{ + uint32_t reset_type = SOFT_SYS_RESET_L1; + +#ifdef USE_PAXC + if (bcm_chimp_is_nic_mode()) + reset_type = SOFT_RESET_L3; +#endif + INFO("System rebooting - L%d...\n", reset_type); + + plat_soft_reset(reset_type); + + /* Prevent the function to return due to the attribute */ + while (1) + ; +} + +static int brcm_system_reset2(int is_vendor, int reset_type, + u_register_t cookie) +{ + INFO("System rebooting - L%d...\n", reset_type); + + plat_soft_reset(reset_type); + + /* + * plat_soft_reset cannot return (it is a __dead function), + * but brcm_system_reset2 has to return some value, even in + * this case. + */ + return 0; +} + +/******************************************************************************* + * Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard + * platform will take care of registering the handlers with PSCI. + ******************************************************************************/ +const plat_psci_ops_t plat_brcm_psci_pm_ops = { + .pwr_domain_on = brcm_pwr_domain_on, + .pwr_domain_on_finish = brcm_pwr_domain_on_finish, + .system_reset = brcm_system_reset, + .system_reset2 = brcm_system_reset2 +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &plat_brcm_psci_pm_ops; + plat_sec_entrypoint = sec_entrypoint; + + return 0; +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c new file mode 100644 index 0000000..2aa9519 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include "m0_ipc.h" + +/* + * Reads a response from CRMU MAILBOX + * Assumes that access has been granted and locked. + * Note that this is just a temporary implementation until + * channels are introduced + */ +static void scp_read_response(crmu_response_t *resp) +{ + uint32_t code; + + code = mmio_read_32(CRMU_MAIL_BOX0); + resp->completed = code & MCU_IPC_CMD_DONE_MASK; + resp->cmd = code & SCP_CMD_MASK; + resp->ret = (code & MCU_IPC_CMD_REPLY_MASK) >> MCU_IPC_CMD_REPLY_SHIFT; +} + +/* + * Send a command to SCP and wait for timeout us. + * Return: 0 on success + * -1 if there was no proper reply from SCP + * >0 if there was a response from MCU, but + * command completed with an error. + */ +int scp_send_cmd(uint32_t cmd, uint32_t param, uint32_t timeout) +{ + int ret = -1; + + mmio_write_32(CRMU_MAIL_BOX0, cmd); + mmio_write_32(CRMU_MAIL_BOX1, param); + do { + crmu_response_t scp_resp; + + udelay(1); + scp_read_response(&scp_resp); + if (scp_resp.completed && + (scp_resp.cmd == cmd)) { + /* This command has completed */ + ret = scp_resp.ret; + break; + } + } while (--timeout); + + return ret; +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c new file mode 100644 index 0000000..1d82cef --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2017-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m0_cfg.h" +#include "m0_ipc.h" + +#ifdef BCM_ELOG +static void prepare_elog(void) +{ +#if (CLEAN_DDR && !defined(MMU_DISABLED)) + /* + * Now DDR has been initialized. We want to copy all the logs in SRAM + * into DDR so we will have much more space to store the logs in the + * next boot stage + */ + bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE, + MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE) + ); + + /* + * We are almost at the end of BL2, and we can stop log here so we do + * not need to add 'bcm_elog_exit' to the standard BL2 code. The + * benefit of capturing BL2 logs after this is very minimal in a + * production system. + */ + bcm_elog_exit(); +#endif + + /* + * Notify CRMU that now it should pull logs from DDR instead of from + * FS4 SRAM. + */ + SCP_WRITE_CFG(flash_log.can_use_ddr, 1); +} +#endif + +bool is_crmu_alive(void) +{ + return (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0, SCP_CMD_DEFAULT_TIMEOUT_US) + == 0); +} + +bool bcm_scp_issue_sys_reset(void) +{ + return (scp_send_cmd(MCU_IPC_MCU_CMD_L1_RESET, 0, + SCP_CMD_DEFAULT_TIMEOUT_US)); +} + +/* + * Note that this is just a temporary implementation until + * channels are introduced + */ + +int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + int scp_patch_activated, scp_patch_version; +#ifndef EMULATION_SETUP + uint8_t active_ch_bitmap, i; +#endif + uint32_t reset_state = 0; + uint32_t mcu_ap_init_param = 0; + + /* + * First check if SCP patch has already been loaded + * Send NOP command and see if there is a valid response + */ + scp_patch_activated = + (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0, + SCP_CMD_DEFAULT_TIMEOUT_US) == 0); + if (scp_patch_activated) { + INFO("SCP Patch is already active.\n"); + + reset_state = SCP_READ_CFG(board_cfg.reset_state); + mcu_ap_init_param = SCP_READ_CFG(board_cfg.mcu_init_param); + + /* Clear reset state, it's been already read */ + SCP_WRITE_CFG(board_cfg.reset_state, 0); + + if (mcu_ap_init_param & MCU_PATCH_LOADED_BY_NITRO) { + /* + * Reset "MCU_PATCH_LOADED_BY_NITRO" flag, but + * Preserve any other flags we don't deal with here + */ + INFO("AP booted by Nitro\n"); + SCP_WRITE_CFG( + board_cfg.mcu_init_param, + mcu_ap_init_param & + ~MCU_PATCH_LOADED_BY_NITRO + ); + } + } else { + /* + * MCU Patch not loaded, so load it. + * MCU patch stamps critical points in REG9 (debug test-point) + * Display its last content here. This helps to locate + * where crash occurred if a CRMU watchdog kicked in. + */ + int ret; + + INFO("MCU Patch Point: 0x%x\n", + mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9)); + + ret = download_scp_patch((void *)scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + if (ret != 0) + return ret; + + VERBOSE("SCP Patch loaded OK.\n"); + + ret = scp_send_cmd(MCU_IPC_MCU_CMD_INIT, + MCU_PATCH_LOADED_BY_AP, + SCP_CMD_SCP_BOOT_TIMEOUT_US); + if (ret) { + ERROR("SCP Patch could not initialize; error %d\n", + ret); + return ret; + } + + INFO("SCP Patch successfully initialized.\n"); + } + + scp_patch_version = scp_send_cmd(MCU_IPC_MCU_CMD_GET_FW_VERSION, 0, + SCP_CMD_DEFAULT_TIMEOUT_US); + INFO("SCP Patch version :0x%x\n", scp_patch_version); + + /* Next block just reports current AVS voltages (if applicable) */ + { + uint16_t vcore_mv, ihost03_mv, ihost12_mv; + + vcore_mv = SCP_READ_CFG16(vcore.millivolts) + + SCP_READ_CFG8(vcore.avs_cfg.additive_margin); + ihost03_mv = SCP_READ_CFG16(ihost03.millivolts) + + SCP_READ_CFG8(ihost03.avs_cfg.additive_margin); + ihost12_mv = SCP_READ_CFG16(ihost12.millivolts) + + SCP_READ_CFG8(ihost12.avs_cfg.additive_margin); + + if (vcore_mv || ihost03_mv || ihost12_mv) { + INFO("AVS voltages from cfg (including margin)\n"); + if (vcore_mv > 0) + INFO("%s\tVCORE: %dmv\n", + SCP_READ_CFG8(vcore.avs_cfg.avs_set) ? + "*" : "n/a", vcore_mv); + if (ihost03_mv > 0) + INFO("%s\tIHOST03: %dmv\n", + SCP_READ_CFG8(ihost03.avs_cfg.avs_set) ? + "*" : "n/a", ihost03_mv); + if (ihost12_mv > 0) + INFO("%s\tIHOST12: %dmv\n", + SCP_READ_CFG8(ihost12.avs_cfg.avs_set) ? + "*" : "n/a", ihost12_mv); + } else { + INFO("AVS settings not applicable\n"); + } + } + +#if (CLEAN_DDR && !defined(MMU_DISABLED) && !defined(EMULATION_SETUP)) + /* This will clean the DDR and enable ECC if set */ + check_ddr_clean(); +#endif + +#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR) + elog_init_ddr_log(); +#endif + +#ifdef BCM_ELOG + /* Prepare ELOG to use DDR */ + prepare_elog(); +#endif + +#ifndef EMULATION_SETUP + /* Ask ddr_init to save obtained DDR information into DDR */ + ddr_info_save(); +#endif + + /* + * Configure TMON DDR address. + * This cfg is common for all cases + */ + SCP_WRITE_CFG(tmon_cfg.ddr_desc, TMON_SHARED_DDR_ADDRESS); + + if (reset_state == SOFT_RESET_L3 && !mcu_ap_init_param) { + INFO("SCP configuration after L3 RESET done.\n"); + return 0; + } + + if (bcm_chimp_is_nic_mode()) + /* Configure AP WDT to not reset the NIC interface */ + SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3); + +#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR) + /* When AP WDog triggers perform L3 reset if DDR err logging enabled */ + SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3); +#endif + +#ifndef EMULATION_SETUP + +#ifdef DDR_SCRUB_ENA + ddr_scrub_enable(); +#endif + /* Fill the Active channel information */ + active_ch_bitmap = get_active_ddr_channel(); + for (i = 0; i < MAX_NR_DDR_CH; i++) + SCP_WRITE_CFG(ddr_cfg.ddr_cfg[i], + (active_ch_bitmap & BIT(i)) ? 1 : 0); +#endif + return 0; +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c new file mode 100644 index 0000000..aa2b71a --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +const SDIO_CFG sr_sdio0_cfg = { + .cfg_base = SR_IPROC_SDIO0_CFG_BASE, + .sid_base = SR_IPROC_SDIO0_SID_BASE, + .io_ctrl_base = SR_IPROC_SDIO0_IOCTRL_BASE, + .pad_base = SR_IPROC_SDIO0_PAD_BASE, +}; +const SDIO_CFG sr_sdio1_cfg = { + .cfg_base = SR_IPROC_SDIO1_CFG_BASE, + .sid_base = SR_IPROC_SDIO1_SID_BASE, + .io_ctrl_base = SR_IPROC_SDIO1_IOCTRL_BASE, + .pad_base = SR_IPROC_SDIO1_PAD_BASE, +}; + +void brcm_stingray_sdio_init(void) +{ + unsigned int val; + const SDIO_CFG *sdio0_cfg, *sdio1_cfg; + + sdio0_cfg = &sr_sdio0_cfg; + sdio1_cfg = &sr_sdio1_cfg; + + INFO("set sdio0 caps\n"); + /* SDIO0 CAPS0 */ + val = SDIO0_CAP0_CFG; + INFO("caps0 0x%x\n", val); + mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP0, val); + + /* SDIO0 CAPS1 */ + val = SDIO0_CAP1_CFG; + INFO("caps1 0x%x\n", val); + mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP1, val); + + mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0, + SDIO_PRESETVAL0); + mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1, + SDIO_PRESETVAL1); + mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2, + SDIO_PRESETVAL2); + mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3, + SDIO_PRESETVAL3); + mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4, + SDIO_PRESETVAL4); + + val = SR_SID_VAL(0x3, 0x0, 0x2) << SDIO_SID_SHIFT; + mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val); + mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val); + + val = mmio_read_32(sdio0_cfg->io_ctrl_base); + val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */ + val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */ + mmio_write_32(sdio0_cfg->io_ctrl_base, val); + + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CLK, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA0, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA1, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA2, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA3, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA4, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA5, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA6, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA7, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CMD, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + + INFO("set sdio1 caps\n"); + + /* SDIO1 CAPS0 */ + val = SDIO1_CAP0_CFG; + INFO("caps0 0x%x\n", val); + mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP0, val); + /* SDIO1 CAPS1 */ + val = SDIO1_CAP1_CFG; + INFO("caps1 0x%x\n", val); + mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP1, val); + + mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0, + SDIO_PRESETVAL0); + mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1, + SDIO_PRESETVAL1); + mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2, + SDIO_PRESETVAL2); + mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3, + SDIO_PRESETVAL3); + mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4, + SDIO_PRESETVAL4); + + val = SR_SID_VAL(0x3, 0x0, 0x3) << SDIO_SID_SHIFT; + mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val); + mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val); + + val = mmio_read_32(sdio1_cfg->io_ctrl_base); + val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */ + val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */ + mmio_write_32(sdio1_cfg->io_ctrl_base, val); + + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CLK, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA0, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA1, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA2, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA3, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA4, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA5, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA6, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA7, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CMD, + PAD_SDIO_MASK, PAD_SDIO_VALUE); + + INFO("sdio init done\n"); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c new file mode 100644 index 0000000..7380e09 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c @@ -0,0 +1,806 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* total number of PCIe Phys */ +#define NUM_OF_PCIE_SERDES 8 + +#define CFG_RC_PMI_ADDR 0x1130 +#define PMI_RX_TERM_SEQ ((0x1 << 27) | (0x1ff << 16) | (0xd090)) +#define PMI_RX_TERM_VAL 0x4c00 +#define PMI_PLL_CTRL_4 0xd0b4 +#define PMI_SERDES_CLK_ENABLE (1 << 12) + +#define WAR_PLX_PRESET_PARITY_FAIL + +#define CFG_RC_REG_PHY_CTL_10 0x1838 +#define PHY_CTL_10_GEN3_MATCH_PARITY (1 << 15) + +#define PMI_X8_CORE0_7_PATCH_SEQ ((0x1 << 27) | (0x1ff << 16) | (0xd2a5)) +#define PMI_X8_CORE0_7_PATCH_VAL 0xd864 + +#define PMI_ADDR_BCAST(addr) ((0x1 << 27) | (0x1ff << 16) | (addr)) +#define PMI_ADDR_LANE0(addr) ((0x1 << 27) | (addr)) +#define PMI_ADDR_LANE1(addr) ((0x1 << 27) | (0x1 << 16) | (addr)) + +#define MERLIN16_PCIE_BLK2_PWRMGMT_7 ((0x1 << 27) | (0x1ff << 16) | 0x1208) +#define MERLIN16_PCIE_BLK2_PWRMGMT_8 ((0x1 << 27) | (0x1ff << 16) | 0x1209) +#define MERLIN16_AMS_TX_CTRL_5 ((0x1 << 27) | (0x1ff << 16) | 0xd0a5) +#define MERLIN16_AMS_TX_CTRL_5_VAL \ + ((1 << 13) | (1 << 12) | (1 << 11) | (1 << 10)) +#define MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL 0x96 +#define MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL 0x12c + +#define CFG_RC_PMI_WDATA 0x1134 +#define CFG_RC_WCMD_SHIFT 31 +#define CFG_RC_WCMD_MASK ((uint32_t)1U << CFG_RC_WCMD_SHIFT) +#define CFG_RC_RCMD_SHIFT 30 +#define CFG_RC_RCMD_MASK ((uint32_t)1U << CFG_RC_RCMD_SHIFT) +#define CFG_RC_RWCMD_MASK (CFG_RC_RCMD_MASK | CFG_RC_WCMD_MASK) +#define CFG_RC_PMI_RDATA 0x1138 +#define CFG_RC_RACK_SHIFT 31 +#define CFG_RC_RACK_MASK ((uint32_t)1U << CFG_RC_RACK_SHIFT) + +/* allow up to 5 ms for PMI write to finish */ +#define PMI_TIMEOUT_MS 5 + +/* in 2x8 RC mode, one needs to patch up Serdes 3 and 7 for link to come up */ +#define SERDES_PATCH_PIPEMUX_INDEX 0x3 +#define SERDES_PATCH_INDEX 0x8 + +#define DSC_UC_CTRL 0xd00d +#define DSC_UC_CTRL_RDY_CMD (1 << 7) +#define LANE_DBG_RST_CTRL 0xd164 +#define UC_A_CLK_CTRL0 0xd200 +#define UC_A_RST_CTRL0 0xd201 +#define UC_A_AHB_CTRL0 0xd202 +#define UC_A_AHB_STAT0 0xd203 +#define UC_A_AHB_WADDR_LSW 0xd204 +#define UC_A_AHB_WADDR_MSW 0xd205 +#define UC_A_AHB_WDATA_LSW 0xd206 +#define UC_A_AHB_WDATA_MSW 0xd207 +#define UC_A_AHB_RADDR_LSW 0xd208 +#define UC_A_AHB_RADDR_MSW 0xd209 +#define UC_A_AHB_RDATA_LSW 0xd20a +#define UC_A_AHB_RDATA_MSW 0xd20b +#define UC_VERSION_NUM 0xd230 +#define DSC_SM_CTL22 0xd267 +#define UC_DBG1 0xd251 + +#define LOAD_UC_CHECK 0 +#define UC_RAM_INIT_TIMEOUT 100 +#define UC_RAM_CONTROL 0xd225 +#define UC_INIT_TIMEOUT 100 +#define SIZE_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define SZ_4 4 +#define GET_2_BYTES(p, i) ((uint16_t)p[i] | (uint16_t)p[i+1] << 8) + +/* + * List of PCIe LCPLL related registers + * + * LCPLL channel 0 provides the Serdes pad clock when running in RC mode + */ +#define PCIE_LCPLL_BASE 0x40000000 + +#define PCIE_LCPLL_CTRL0_OFFSET 0x00 +#define PCIE_LCPLL_RESETB_SHIFT 31 +#define PCIE_LCPLL_RESETB_MASK BIT(PCIE_LCPLL_RESETB_SHIFT) +#define PCIE_LCPLL_P_RESETB_SHIFT 30 +#define PCIE_LCPLL_P_RESETB_MASK BIT(PCIE_LCPLL_P_RESETB_SHIFT) + +#define PCIE_LCPLL_CTRL3_OFFSET 0x0c +#define PCIE_LCPLL_EN_CTRL_SHIFT 16 +#define PCIE_LCPLL_CM_ENA 0x1a +#define PCIE_LCPLL_CM_BUF_ENA 0x18 +#define PCIE_LCPLL_D2C2_ENA 0x2 +#define PCIE_LCPLL_REF_CLK_SHIFT 1 +#define PCIE_LCPLL_REF_CLK_MASK BIT(PCIE_LCPLL_REF_CLK_SHIFT) +#define PCIE_LCPLL_CTRL13_OFFSET 0x34 +#define PCIE_LCPLL_D2C2_CTRL_SHIFT 16 +#define PCIE_LCPLL_D2C2_TERM_DISC 0xe0 + +#define PCIE_LCPLL_STATUS_OFFSET 0x40 +#define PCIE_LCPLL_LOCK_SHIFT 12 +#define PCIE_LCPLL_LOCK_MASK BIT(PCIE_LCPLL_LOCK_SHIFT) + +#define PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG 0x114 +#define PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG 0x11c + +/* wait 500 microseconds for PCIe LCPLL to power up */ +#define PCIE_LCPLL_DELAY_US 500 + +/* allow up to 5 ms for PCIe LCPLL VCO to lock */ +#define PCIE_LCPLL_TIMEOUT_MS 5 + +#define PCIE_PIPE_MUX_CONFIGURATION_CFG 0x4000010c + +#define PCIE_PIPEMUX_SHIFT 19 +#define PCIE_PIPEMUX_MASK 0xf + +/* keep track of PIPEMUX index to use */ +static unsigned int pipemux_idx; + +/* + * PCIe PIPEMUX lookup table + * + * Each array index represents a PIPEMUX strap setting + * The array element represents a bitmap where a set bit means the PCIe core + * needs to be enabled as RC + */ +static uint8_t pipemux_table[] = { + /* PIPEMUX = 0, EP 1x16 */ + 0x00, + /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */ + 0x80, + /* PIPEMUX = 2, EP 4x4 */ + 0x00, + /* PIPEMUX = 3, RC 2x8, cores 0, 7 */ + 0x81, + /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */ + 0xc3, + /* PIPEMUX = 5, RC 8x2, all 8 cores */ + 0xff, + /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */ + 0xcd, + /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */ + 0xfd, + /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */ + 0xf0, + /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */ + 0xc0, + /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */ + 0x42, + /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */ + 0x3c, + /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */ + 0xfc, + /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */ + 0x4c, +}; + +/* + * Return 1 if pipemux strap is supported + */ +static int pipemux_strap_is_valid(uint32_t pipemux) +{ + if (pipemux < ARRAY_SIZE(pipemux_table)) + return 1; + else + return 0; +} + +/* + * Read the PCIe PIPEMUX from strap + */ +static uint32_t pipemux_strap_read(void) +{ + uint32_t pipemux; + + pipemux = mmio_read_32(PCIE_PIPE_MUX_CONFIGURATION_CFG); + pipemux &= PCIE_PIPEMUX_MASK; + if (pipemux == PCIE_PIPEMUX_MASK) { + /* read the PCIe PIPEMUX strap setting */ + pipemux = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW); + pipemux >>= PCIE_PIPEMUX_SHIFT; + pipemux &= PCIE_PIPEMUX_MASK; + } + + return pipemux; +} + +/* + * Store the PIPEMUX index (set for each boot) + */ +static void pipemux_save_index(unsigned int idx) +{ + pipemux_idx = idx; +} + +static int paxb_sr_core_needs_enable(unsigned int core_idx) +{ + return !!((pipemux_table[pipemux_idx] >> core_idx) & 0x1); +} + +static int pipemux_sr_init(void) +{ + uint32_t pipemux; + + /* read the PCIe PIPEMUX strap setting */ + pipemux = pipemux_strap_read(); + if (!pipemux_strap_is_valid(pipemux)) { + ERROR("Invalid PCIe PIPEMUX strap %u\n", pipemux); + return -EIO; + } + + /* no PCIe RC is needed */ + if (!pipemux_table[pipemux]) { + WARN("PIPEMUX indicates no PCIe RC required\n"); + return -ENODEV; + } + + /* save the PIPEMUX strap */ + pipemux_save_index(pipemux); + + return 0; +} + +/* + * PCIe RC serdes link width + * + * The array is first organized in rows as indexed by the PIPEMUX setting. + * Within each row, eight lane width entries are specified -- one entry + * per PCIe core, from 0 to 7. + * + * Note: The EP lanes/cores are not mapped in this table! EP cores are + * controlled and thus configured by Nitro. + */ +static uint8_t link_width_table[][NUM_OF_SR_PCIE_CORES] = { + /* PIPEMUX = 0, EP 1x16 */ + {0, 0, 0, 0, 0, 0, 0, 0}, + /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */ + {0, 0, 0, 0, 0, 0, 0, 8}, + /* PIPEMUX = 2, EP 4x4 */ + {0, 0, 0, 0, 0, 0, 0, 0}, + /* PIPEMUX = 3, RC 2x8, cores 0, 7 */ + {8, 0, 0, 0, 0, 0, 0, 8}, + /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */ + {4, 4, 0, 0, 0, 0, 4, 4}, + /* PIPEMUX = 5, RC 8x2, all 8 cores */ + {2, 2, 2, 2, 2, 2, 2, 2}, + /* PIPEMUX = 6, RC 3x4 (cores 0, 6, 7), RC 2x2 (cores 2, 3) */ + {4, 0, 2, 2, 0, 0, 4, 4}, + /* PIPEMUX = 7, RC 1x4 (core 0), RC 6x2 (cores 2, 3, 4, 5, 6, 7 */ + {4, 0, 2, 2, 2, 2, 2, 2}, + /* PIPEMUX = 8, EP 1x8 + RC 4x2 (cores 4, 5, 6, 7) */ + {0, 0, 0, 0, 2, 2, 2, 2}, + /* PIPEMUX = 9, EP 1x8 + RC 2x4 (cores 6, 7) */ + {0, 0, 0, 0, 0, 0, 4, 4}, + /* PIPEMUX = 10, EP 2x4 + RC 2x4 (cores 1, 6) */ + {0, 4, 0, 0, 0, 0, 4, 0}, + /* PIPEMUX = 11, EP 2x4 + RC 4x2 (cores 2, 3, 4, 5) */ + {0, 0, 2, 2, 2, 2, 0, 0}, + /* PIPEMUX = 12, EP 1x4 + RC 6x2 (cores 2, 3, 4, 5, 6, 7) */ + {0, 0, 2, 2, 2, 2, 2, 2}, + /* PIPEMUX = 13, EP 2x4 + RC 1x4 (core 6) + RC 2x2 (cores 2, 3) */ + {0, 0, 2, 2, 0, 0, 4, 0} +}; + +/* + * function for writes to the Serdes registers through the PMI interface + */ +static int paxb_pmi_write(unsigned int core_idx, uint32_t pmi, uint32_t val) +{ + uint32_t status; + unsigned int timeout = PMI_TIMEOUT_MS; + + paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi); + + val &= ~CFG_RC_RWCMD_MASK; + val |= CFG_RC_WCMD_MASK; + paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, val); + + do { + status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_WDATA); + + /* wait for write command bit to clear */ + if ((status & CFG_RC_WCMD_MASK) == 0) + return 0; + } while (--timeout); + + return -EIO; +} + +/* + * function for reads from the Serdes registers through the PMI interface + */ +static int paxb_pmi_read(unsigned int core_idx, uint32_t pmi, uint32_t *val) +{ + uint32_t status; + unsigned int timeout = PMI_TIMEOUT_MS; + + paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi); + + paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, CFG_RC_RCMD_MASK); + + do { + status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA); + + /* wait for read ack bit set */ + if ((status & CFG_RC_RACK_MASK)) { + *val = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA); + return 0; + } + } while (--timeout); + + return -EIO; +} + + +#ifndef BOARD_PCIE_EXT_CLK +/* + * PCIe Override clock lookup table + * + * Each array index represents pcie override clock has been done + * by CFW or not. + */ +static uint8_t pcie_override_clk_table[] = { + /* PIPEMUX = 0, EP 1x16 */ + 0x0, + /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */ + 0x1, + /* PIPEMUX = 2, EP 4x4 */ + 0x0, + /* PIPEMUX = 3, RC 2x8, cores 0, 7 */ + 0x0, + /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */ + 0x0, + /* PIPEMUX = 5, RC 8x2, all 8 cores */ + 0x0, + /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */ + 0x0, + /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */ + 0x0, + /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */ + 0x0, + /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */ + 0x0, + /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */ + 0x0, + /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */ + 0x0, + /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */ + 0x0, + /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */ + 0x0, +}; + +/* + * Bring up LCPLL channel 0 reference clock for PCIe serdes used in RC mode + */ +static int pcie_lcpll_init(void) +{ + uintptr_t reg; + unsigned int timeout = PCIE_LCPLL_TIMEOUT_MS; + uint32_t val; + + if (pcie_override_clk_table[pipemux_idx]) { + /* + * Check rc_mode_override again to avoid halt + * because of cfw uninitialized lcpll. + */ + reg = (uintptr_t)(PCIE_LCPLL_BASE + + PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG); + val = mmio_read_32(reg); + if (val & 0x1) + return 0; + else + return -ENODEV; + } + + /* power on PCIe LCPLL and its LDO */ + reg = (uintptr_t)CRMU_AON_CTRL1; + mmio_setbits_32(reg, CRMU_PCIE_LCPLL_PWR_ON_MASK | + CRMU_PCIE_LCPLL_PWRON_LDO_MASK); + udelay(PCIE_LCPLL_DELAY_US); + + /* remove isolation */ + mmio_clrbits_32(reg, CRMU_PCIE_LCPLL_ISO_IN_MASK); + udelay(PCIE_LCPLL_DELAY_US); + + /* disconnect termination */ + reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL13_OFFSET); + mmio_setbits_32(reg, PCIE_LCPLL_D2C2_TERM_DISC << + PCIE_LCPLL_D2C2_CTRL_SHIFT); + + /* enable CML buf1/2 and D2C2 */ + reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET); + mmio_setbits_32(reg, PCIE_LCPLL_CM_ENA << PCIE_LCPLL_EN_CTRL_SHIFT); + + /* select diff clock mux out as ref clock */ + mmio_clrbits_32(reg, PCIE_LCPLL_REF_CLK_MASK); + + /* delay for 500 microseconds per ASIC spec for PCIe LCPLL */ + udelay(PCIE_LCPLL_DELAY_US); + + /* now bring PCIe LCPLL out of reset */ + reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL0_OFFSET); + mmio_setbits_32(reg, PCIE_LCPLL_RESETB_MASK); + + /* wait for PLL to lock */ + reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_STATUS_OFFSET); + do { + val = mmio_read_32(reg); + if ((val & PCIE_LCPLL_LOCK_MASK) == PCIE_LCPLL_LOCK_MASK) { + /* now bring the post divider out of reset */ + reg = (uintptr_t)(PCIE_LCPLL_BASE + + PCIE_LCPLL_CTRL0_OFFSET); + mmio_setbits_32(reg, PCIE_LCPLL_P_RESETB_MASK); + VERBOSE("PCIe LCPLL locked\n"); + return 0; + } + mdelay(1); + } while (--timeout); + + ERROR("PCIe LCPLL failed to lock\n"); + return -EIO; +} +#else +/* + * Bring up EXT CLK reference clock for PCIe serdes used in RC mode + * XTAL_BYPASS (3 << 0) + * INTR_LC_REF (5 << 0) + * PD_CML_LC_REF_OUT (1 << 4) + * PD_CML_REF_CH_OUT (1 << 8) + * CLK_MASTER_SEL (1 << 11) + * CLK_MASTER_CTRL_A (1 << 12) + * CLK_MASTER_CTRL_B (2 << 14) + */ +static const uint16_t pcie_ext_clk[][NUM_OF_PCIE_SERDES] = { + /* PIPEMUX = 0, EP 1x16 */ + {0}, + /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */ + {0}, + /* PIPEMUX = 2, EP 4x4 */ + {0}, + /* PIPEMUX = 3, RC 2x8, cores 0, 7 */ + {0x8803, 0x9115, 0x9115, 0x1115, 0x8803, 0x9115, 0x9115, 0x1115}, + /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */ + {0x8803, 0x1115, 0x8915, 0x1115, 0x8803, 0x1115, 0x8915, 0x1115,}, + /* PIPEMUX = 5, RC 8x2, all 8 cores */ + {0x0803, 0x0915, 0x0915, 0x0915, 0x0803, 0x0915, 0x0915, 0x0915,}, + /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */ + {0}, + /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */ + {0}, + /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */ + {0}, + /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */ + {0}, + /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */ + {0}, + /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */ + {0}, + /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */ + {0}, + /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */ + {0}, +}; + +static void pcie_ext_clk_init(void) +{ + unsigned int serdes; + uint32_t val; + + for (serdes = 0; serdes < NUM_OF_PCIE_SERDES; serdes++) { + val = pcie_ext_clk[pipemux_idx][serdes]; + if (!val) + return; + mmio_write_32(PCIE_CORE_RESERVED_CFG + + serdes * PCIE_CORE_PWR_OFFSET, val); + } + /* disable CML buf1/2 and enable D2C2 */ + mmio_clrsetbits_32((PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET), + PCIE_LCPLL_CM_BUF_ENA << PCIE_LCPLL_EN_CTRL_SHIFT, + PCIE_LCPLL_D2C2_ENA << PCIE_LCPLL_EN_CTRL_SHIFT); + mmio_write_32(PCIE_LCPLL_BASE + PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG, 1); + INFO("Overriding Clocking - using REF clock from PAD...\n"); +} +#endif + +static int load_uc(unsigned int core_idx) +{ + return 0; +} + +static int paxb_serdes_gate_clock(unsigned int core_idx, int gate_clk) +{ + unsigned int link_width, serdes, nr_serdes; + uintptr_t pmi_base; + unsigned int rdata; + uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET; + + link_width = paxb->get_link_width(core_idx); + if (!link_width) { + ERROR("Unsupported PIPEMUX\n"); + return -EOPNOTSUPP; + } + + nr_serdes = link_width / 2; + pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset); + + for (serdes = 0; serdes < nr_serdes; serdes++) { + mmio_write_32(pmi_base, serdes); + paxb_pmi_read(core_idx, PMI_ADDR_LANE0(PMI_PLL_CTRL_4), &rdata); + if (!gate_clk) + rdata |= PMI_SERDES_CLK_ENABLE; + else + rdata &= ~PMI_SERDES_CLK_ENABLE; + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(PMI_PLL_CTRL_4), rdata); + } + return 0; +} + +static int paxb_gen3_serdes_init(unsigned int core_idx, uint32_t nSerdes) +{ + uint32_t rdata; + int serdes; + uintptr_t pmi_base; + unsigned int timeout; + unsigned int reg_d230, reg_d267; + + + pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + + (core_idx * PCIE_CORE_PWR_OFFSET)); + + for (serdes = 0; serdes < nSerdes; serdes++) { + /* select the PMI interface */ + mmio_write_32(pmi_base, serdes); + + /* Clock enable */ + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_CLK_CTRL0), + 0x3); + + /* Release reset of master */ + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0), + 0x1); + + /* clearing PRAM memory */ + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0), + 0x100); + + timeout = UC_RAM_INIT_TIMEOUT; + do { + paxb_pmi_read(core_idx, + PMI_ADDR_LANE0(UC_A_AHB_STAT0), + &rdata); + } while ((rdata & 0x01) == 0 && timeout--); + + if (!timeout) + return -EIO; + + timeout = UC_RAM_INIT_TIMEOUT; + do { + paxb_pmi_read(core_idx, + PMI_ADDR_LANE1(UC_A_AHB_STAT0), + &rdata); + } while ((rdata & 0x01) == 0 && timeout--); + + if (!timeout) + return -EIO; + + /* clearing PRAM memory */ + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0), + 0); + + /* to identify 2 lane serdes */ + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_DBG1), 0x1); + + /* De-Assert Pram & master resets */ + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0), + 0x9); + + if (load_uc(core_idx)) + return -EIO; + + /* UC UC ready for command */ + paxb_pmi_read(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL), + &rdata); + rdata |= DSC_UC_CTRL_RDY_CMD; + paxb_pmi_write(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL), + rdata); + + paxb_pmi_read(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL), + &rdata); + rdata |= DSC_UC_CTRL_RDY_CMD; + paxb_pmi_write(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL), + rdata); + + /* Lane reset */ + paxb_pmi_write(core_idx, + PMI_ADDR_BCAST(LANE_DBG_RST_CTRL), 0x3); + + /* De-Assert Core and Master resets */ + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0), + 0x3); + + timeout = UC_INIT_TIMEOUT; + while (timeout--) { + paxb_pmi_read(core_idx, + PMI_ADDR_LANE0(UC_VERSION_NUM), + ®_d230); + paxb_pmi_read(core_idx, + PMI_ADDR_LANE0(DSC_SM_CTL22), + ®_d267); + + if (((reg_d230 & 0xffff) != 0) & + ((reg_d267 & 0xc000) == 0xc000)) { + break; + } + mdelay(1); + } + + if (!timeout) + return -EIO; + + timeout = UC_INIT_TIMEOUT; + while (timeout--) { + paxb_pmi_read(core_idx, + PMI_ADDR_LANE1(UC_VERSION_NUM), + ®_d230); + paxb_pmi_read(core_idx, + PMI_ADDR_LANE1(DSC_SM_CTL22), + ®_d267); + + if (((reg_d230 & 0xffff) != 0) & + ((reg_d267 & 0xc000) == 0xc000)) { + break; + } + mdelay(1); + } + + if (!timeout) + return -EIO; + } + return 0; +} + +static int pcie_serdes_requires_patch(unsigned int serdes_idx) +{ + if (pipemux_idx != SERDES_PATCH_PIPEMUX_INDEX) + return 0; + + return !!((SERDES_PATCH_INDEX >> serdes_idx) & 0x1); +} + +static void pcie_tx_coeff_p7(unsigned int core_idx) +{ + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11b), 0x00aa); + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11c), 0x1155); + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11d), 0x2449); + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11e), 0x000f); + paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd307), 0x0001); +} + + +static unsigned int paxb_sr_get_rc_link_width(unsigned int core_idx) +{ + return link_width_table[pipemux_idx][core_idx]; +} + +static uint32_t paxb_sr_get_rc_link_speed(void) +{ + return GEN3_LINK_SPEED; +} + + +static int paxb_serdes_init(unsigned int core_idx, unsigned int nr_serdes) +{ + uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET; + unsigned int serdes; + uintptr_t pmi_base; + int ret; + + /* + * Each serdes has a x2 link width + * + * Use PAXB to patch the serdes for proper RX termination through the + * PMI interface + */ + pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset); + for (serdes = 0; serdes < nr_serdes; serdes++) { + /* select the PMI interface */ + mmio_write_32(pmi_base, serdes); + + /* patch Serdes for RX termination */ + ret = paxb_pmi_write(core_idx, PMI_RX_TERM_SEQ, + PMI_RX_TERM_VAL); + if (ret) + goto err_pmi; + + ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_7, + MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL); + if (ret) + goto err_pmi; + + ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_8, + MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL); + if (ret) + goto err_pmi; + + ret = paxb_pmi_write(core_idx, MERLIN16_AMS_TX_CTRL_5, + MERLIN16_AMS_TX_CTRL_5_VAL); + if (ret) + goto err_pmi; + + pcie_tx_coeff_p7(core_idx); + + if (pcie_serdes_requires_patch(serdes)) { + if (((core_idx == 0) || (core_idx == 7))) { + ret = paxb_pmi_write(core_idx, + PMI_X8_CORE0_7_PATCH_SEQ, + PMI_X8_CORE0_7_PATCH_VAL); + if (ret) + goto err_pmi; + } + } + } + + return 0; + +err_pmi: + ERROR("PCIe PMI write failed\n"); + return ret; +} + +static int paxb_sr_phy_init(void) +{ + int ret; + unsigned int core_idx; + +#ifndef BOARD_PCIE_EXT_CLK + ret = pcie_lcpll_init(); + if (ret) + return ret; +#else + pcie_ext_clk_init(); +#endif + + for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) { + if (!pcie_core_needs_enable(core_idx)) + continue; + unsigned int link_width; + + paxb_serdes_gate_clock(core_idx, 0); + + link_width = paxb->get_link_width(core_idx); + if (!link_width) { + ERROR("Unsupported PIPEMUX\n"); + return -EOPNOTSUPP; + } + + ret = paxb_serdes_init(core_idx, link_width / 2); + if (ret) { + ERROR("PCIe serdes initialization failed for core %u\n", + core_idx); + return ret; + } + + + ret = paxb_gen3_serdes_init(core_idx, link_width / 2); + if (ret) { + ERROR("PCIe GEN3 serdes initialization failed\n"); + return ret; + } + + } + return 0; +} + +const paxb_cfg sr_paxb_cfg = { + .type = PAXB_SR, + .device_id = SR_B0_DEVICE_ID, + .pipemux_init = pipemux_sr_init, + .phy_init = paxb_sr_phy_init, + .core_needs_enable = paxb_sr_core_needs_enable, + .num_cores = NUM_OF_SR_PCIE_CORES, + .get_link_width = paxb_sr_get_rc_link_width, + .get_link_speed = paxb_sr_get_rc_link_speed, +}; + +const paxb_cfg *paxb_get_sr_config(void) +{ + return &sr_paxb_cfg; +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c new file mode 100644 index 0000000..24718e5 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include + +/* + * On Stingray, the system power level is the highest power level. + * The first entry in the power domain descriptor specifies the + * number of system power domains i.e. 1. + */ +#define SR_PWR_DOMAINS_AT_MAX_PWR_LVL 1 + +/* + * The Stingray power domain tree descriptor. The cluster power domains + * are arranged so that when the PSCI generic code creates the power + * domain tree, the indices of the CPU power domain nodes it allocates + * match the linear indices returned by plat_core_pos_by_mpidr() + * i.e. CLUSTER0 CPUs are allocated indices from 0 to 1 and the higher + * indices for other Cluster CPUs. + */ +const unsigned char sr_power_domain_tree_desc[] = { + /* No of root nodes */ + SR_PWR_DOMAINS_AT_MAX_PWR_LVL, + /* No of children for the root node */ + BRCM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, + /* No of children for the second cluster node */ + PLATFORM_CLUSTER1_CORE_COUNT, + /* No of children for the third cluster node */ + PLATFORM_CLUSTER2_CORE_COUNT, + /* No of children for the fourth cluster node */ + PLATFORM_CLUSTER3_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the Stingray topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return sr_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return plat_brcm_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c new file mode 100644 index 0000000..07b12a7 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/* + * Trust Zone controllers + */ +#define TZC400_FS_SRAM_ROOT 0x66d84000 + +/* + * TZPC Master configure registers + */ + +/* TZPC_TZPCDECPROT0set */ +#define TZPC0_MASTER_NS_BASE 0x68b40804 +#define TZPC0_SATA3_BIT 5 +#define TZPC0_SATA2_BIT 4 +#define TZPC0_SATA1_BIT 3 +#define TZPC0_SATA0_BIT 2 +#define TZPC0_USB3H1_BIT 1 +#define TZPC0_USB3H0_BIT 0 +#define TZPC0_MASTER_SEC_DEFAULT 0 + +/* TZPC_TZPCDECPROT1set */ +#define TZPC1_MASTER_NS_BASE 0x68b40810 +#define TZPC1_SDIO1_BIT 6 +#define TZPC1_SDIO0_BIT 5 +#define TZPC1_AUDIO0_BIT 4 +#define TZPC1_USB2D_BIT 3 +#define TZPC1_USB2H1_BIT 2 +#define TZPC1_USB2H0_BIT 1 +#define TZPC1_AMAC0_BIT 0 +#define TZPC1_MASTER_SEC_DEFAULT 0 + + +struct tz_sec_desc { + uintptr_t addr; + uint32_t val; +}; + +static const struct tz_sec_desc tz_master_defaults[] = { +{ TZPC0_MASTER_NS_BASE, TZPC0_MASTER_SEC_DEFAULT }, +{ TZPC1_MASTER_NS_BASE, TZPC1_MASTER_SEC_DEFAULT } +}; + +/* + * Initialize the TrustZone Controller for SRAM partitioning. + */ +static void bcm_tzc_setup(void) +{ + VERBOSE("Configuring SRAM TrustZone Controller\n"); + + /* Init the TZASC controller */ + tzc400_init(TZC400_FS_SRAM_ROOT); + + /* + * Close the entire SRAM space + * Region 0 covers the entire SRAM space + * None of the NS device can access it. + */ + tzc400_configure_region0(TZC_REGION_S_RDWR, 0); + + /* Do raise an exception if a NS device tries to access secure memory */ + tzc400_set_action(TZC_ACTION_ERR); +} + +/* + * Configure TZ Master as NS_MASTER or SECURE_MASTER + * To set a Master to non-secure, use *_SET registers + * To set a Master to secure, use *_CLR registers (set + 0x4 address) + */ +static void tz_master_set(uint32_t base, uint32_t value, uint32_t ns) +{ + if (ns == SECURE_MASTER) { + mmio_write_32(base + 4, value); + } else { + mmio_write_32(base, value); + } +} + +/* + * Initialize the secure environment for sdio. + */ +void plat_tz_sdio_ns_master_set(uint32_t ns) +{ + tz_master_set(TZPC1_MASTER_NS_BASE, + 1 << TZPC1_SDIO0_BIT, + ns); +} + +/* + * Initialize the secure environment for usb. + */ +void plat_tz_usb_ns_master_set(uint32_t ns) +{ + tz_master_set(TZPC1_MASTER_NS_BASE, + 1 << TZPC1_USB2H0_BIT, + ns); +} + +/* + * Set masters to default configuration. + * + * DMA security settings are programmed into the PL-330 controller and + * are not set by iProc TZPC registers. + * DMA always comes up as secure master (*NS bit is 0). + * + * Because the default reset values of TZPC are 0 (== Secure), + * ARM Verilog code makes all masters, including PCIe, come up as + * secure. + * However, SOTP has a bit called SOTP_ALLMASTER_NS that overrides + * TZPC and makes all masters non-secure for AB devices. + * + * Hence we first set all the TZPC bits to program all masters, + * including PCIe, as non-secure, then set the CLEAR_ALLMASTER_NS bit + * so that the SOTP_ALLMASTER_NS cannot override TZPC. + * now security settings for each masters come from TZPC + * (which makes all masters other than DMA as non-secure). + * + * During the boot, all masters other than DMA Ctrlr + list + * are non-secure in an AB Prod/AB Dev/AB Pending device. + * + */ +void plat_tz_master_default_cfg(void) +{ + int i; + + /* Configure default secure and non-secure TZ Masters */ + for (i = 0; i < ARRAY_SIZE(tz_master_defaults); i++) { + tz_master_set(tz_master_defaults[i].addr, + tz_master_defaults[i].val, + SECURE_MASTER); + tz_master_set(tz_master_defaults[i].addr, + ~tz_master_defaults[i].val, + NS_MASTER); + } + + /* Clear all master NS */ + mmio_setbits_32(SOTP_CHIP_CTRL, + 1 << SOTP_CLEAR_SYSCTRL_ALL_MASTER_NS); + + /* Initialize TZ controller and Set SRAM to secure */ + bcm_tzc_setup(); +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c new file mode 100644 index 0000000..f711354 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = PLAT_MAX_SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg3 = BRCM_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +#ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +#else + .next_handoff_image_id = BL33_IMAGE_ID, +#endif + }, + +#ifdef BL32_BASE + /* Fill BL32 related information */ + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, +#endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +#ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#else + .ep_info.pc = PLAT_BRCM_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_BRCM_NS_IMAGE_OFFSET, + .image_info.image_max_size = BRCM_DRAM1_SIZE, +#endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c b/arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c new file mode 100644 index 0000000..9a7153b --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2019-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 + +/* Data structure which holds the extents of the trusted SRAM for BL2 */ +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/* Weak definitions may be overridden in specific BRCM platform */ +#pragma weak plat_bcm_bl2_platform_setup +#pragma weak plat_bcm_bl2_plat_arch_setup +#pragma weak plat_bcm_security_setup +#pragma weak plat_bcm_bl2_plat_handle_scp_bl2 +#pragma weak plat_bcm_bl2_early_platform_setup + +void plat_bcm_bl2_early_platform_setup(void) +{ +} + +void plat_bcm_bl2_platform_setup(void) +{ +} + +void plat_bcm_bl2_plat_arch_setup(void) +{ +} + +void plat_bcm_security_setup(void) +{ +} + +void bcm_bl2_early_platform_setup(uintptr_t tb_fw_config, + meminfo_t *mem_layout) +{ + /* Initialize the console to provide early debug support */ + bcm_console_boot_init(); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; + + /* Initialise the IO layer and register platform IO devices */ + plat_brcm_io_setup(); + + /* Log HW reset event */ + INFO("RESET: 0x%x\n", + mmio_read_32(CRMU_RESET_EVENT_LOG)); +} + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* SoC specific setup */ + plat_bcm_bl2_early_platform_setup(); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(SP804_TIMER0_BASE, + SP804_TIMER0_CLKMULT, SP804_TIMER0_CLKDIV); + + /* BRCM platforms generic setup */ + bcm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); +} + +/* + * Perform Broadcom platform setup. + */ +void bcm_bl2_platform_setup(void) +{ + /* Initialize the secure environment */ + plat_bcm_security_setup(); +} + +void bl2_platform_setup(void) +{ + bcm_bl2_platform_setup(); + plat_bcm_bl2_platform_setup(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only initializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bcm_bl2_plat_arch_setup(void) +{ +#ifndef MMU_DISABLED + if (!(read_sctlr_el1() & SCTLR_M_BIT)) { + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + 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), +#if USE_COHERENT_MEM + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - + BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_brcm_get_mmap()); + enable_mmu_el1(0); + } +#endif +} + +void bl2_plat_arch_setup(void) +{ +#ifdef ENA_MMU_BEFORE_DDR_INIT + /* + * Once MMU is enabled before DDR, MEMORY TESTS + * get affected as read/write transaction might occures from + * caches. So For running memory test, one should not set this + * flag. + */ + bcm_bl2_plat_arch_setup(); + plat_bcm_bl2_plat_arch_setup(); +#else + plat_bcm_bl2_plat_arch_setup(); + bcm_bl2_plat_arch_setup(); +#endif +} + +int bcm_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + assert(bl_mem_params); + + switch (image_id) { + case BL32_IMAGE_ID: + bl_mem_params->ep_info.spsr = brcm_get_spsr_for_bl32_entry(); + break; + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = brcm_get_spsr_for_bl33_entry(); + break; + +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = bcm_bl2_handle_scp_bl2(&bl_mem_params->image_info); + if (err) + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bcm_bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return bcm_bl2_handle_post_image_load(image_id); +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return bcm_bl2_plat_handle_post_image_load(image_id); +} + +#ifdef SCP_BL2_BASE +int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + return 0; +} + +int bcm_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + return plat_bcm_bl2_plat_handle_scp_bl2(scp_bl2_image_info); +} +#endif diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c b/arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c new file mode 100644 index 0000000..d3fa83d --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2015-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 + +#ifdef BL33_SHARED_DDR_BASE +struct bl33_info *bl33_info = (struct bl33_info *)BL33_SHARED_DDR_BASE; +#endif + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* Weak definitions may be overridden in specific BRCM platform */ +#pragma weak plat_bcm_bl31_early_platform_setup +#pragma weak plat_brcm_pwrc_setup +#pragma weak plat_brcm_security_setup + +void plat_brcm_security_setup(void) +{ + +} + +void plat_brcm_pwrc_setup(void) +{ + +} + +void plat_bcm_bl31_early_platform_setup(void *from_bl2, + bl_params_t *plat_params_from_bl2) +{ + +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Perform any BL31 early platform setup common to ARM standard platforms. + * Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be + * done before the MMU is initialized so that the memory layout can be used + * while creating page tables. BL2 has flushed this information to memory, so + * we are guaranteed to pick up good data. + ******************************************************************************/ +void __init brcm_bl31_early_platform_setup(void *from_bl2, + uintptr_t soc_fw_config, + uintptr_t hw_config, + void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + bcm_console_boot_init(); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(SP804_TIMER0_BASE, + SP804_TIMER0_CLKMULT, SP804_TIMER0_CLKDIV); + +#if RESET_TO_BL31 + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + +# ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = brcm_get_spsr_for_bl32_entry(); +# endif /* BL32_BASE */ + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + + bl33_image_ep_info.spsr = brcm_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +# if ARM_LINUX_KERNEL_AS_BL33 + /* + * According to the file ``Documentation/arm64/booting.txt`` of the + * Linux kernel tree, Linux expects the physical address of the device + * tree blob (DTB) in x0, while x1-x3 are reserved for future use and + * must be 0. + */ + bl33_image_ep_info.args.arg0 = (u_register_t)PRELOADED_DTB_BASE; + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = 0U; + bl33_image_ep_info.args.arg3 = 0U; +# endif + +#else /* RESET_TO_BL31 */ + + /* + * In debug builds, we pass a special value in 'plat_params_from_bl2' + * to verify platform parameters from BL2 to BL31. + * In release builds, it's not used. + */ + assert(((unsigned long long)plat_params_from_bl2) == + BRCM_BL31_PLAT_PARAM_VAL); + + /* + * Check params passed from BL2 should not be NULL + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params != NULL) { + if (bl_params->image_id == BL32_IMAGE_ID && + bl_params->image_info->h.attr != IMAGE_ATTRIB_SKIP_LOADING) + bl32_image_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0U) + panic(); +#endif /* RESET_TO_BL31 */ + +#ifdef BL33_SHARED_DDR_BASE + /* Pass information to BL33 thorugh x0 */ + bl33_image_ep_info.args.arg0 = (u_register_t)BL33_SHARED_DDR_BASE; + bl33_image_ep_info.args.arg1 = 0ULL; + bl33_image_ep_info.args.arg2 = 0ULL; + bl33_image_ep_info.args.arg3 = 0ULL; +#endif +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ +#ifdef BL31_LOG_LEVEL + SET_LOG_LEVEL(BL31_LOG_LEVEL); +#endif + + brcm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + plat_bcm_bl31_early_platform_setup((void *)arg0, (void *)arg3); + +#ifdef DRIVER_CC_ENABLE + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_brcm_interconnect_init(); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * Platform specific PSCI code will enable coherency for other + * clusters. + */ + plat_brcm_interconnect_enter_coherency(); +#endif +} + +/******************************************************************************* + * Perform any BL31 platform setup common to ARM standard platforms + ******************************************************************************/ +void brcm_bl31_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + plat_brcm_gic_driver_init(); + plat_brcm_gic_init(); + + /* Initialize power controller before setting up topology */ + plat_brcm_pwrc_setup(); +} + +/******************************************************************************* + * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM + * standard platforms + * Perform BL31 platform setup + ******************************************************************************/ +void brcm_bl31_plat_runtime_setup(void) +{ + console_switch_state(CONSOLE_FLAG_RUNTIME); + + /* Initialize the runtime console */ + bcm_console_runtime_init(); +} + +void bl31_platform_setup(void) +{ + brcm_bl31_platform_setup(); + + /* Initialize the secure environment */ + plat_brcm_security_setup(); +} + +void bl31_plat_runtime_setup(void) +{ + brcm_bl31_plat_runtime_setup(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup shared between + * ARM standard platforms. This only does basic initialization. Later + * architectural setup (bl31_arch_setup()) does not do anything platform + * specific. + ******************************************************************************/ +void __init brcm_bl31_plat_arch_setup(void) +{ +#ifndef MMU_DISABLED + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_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), +#if USE_COHERENT_MEM + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_brcm_get_mmap()); + + enable_mmu_el3(0); +#endif +} + +void __init bl31_plat_arch_setup(void) +{ + brcm_bl31_plat_arch_setup(); +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_ccn.c b/arm-trusted-firmware/plat/brcm/common/brcm_ccn.c new file mode 100644 index 0000000..9396aaa --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_ccn.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +static const unsigned char master_to_rn_id_map[] = { + PLAT_BRCM_CLUSTER_TO_CCN_ID_MAP +}; + +static const ccn_desc_t bcm_ccn_desc = { + .periphbase = PLAT_BRCM_CCN_BASE, + .num_masters = ARRAY_SIZE(master_to_rn_id_map), + .master_to_rn_id_map = master_to_rn_id_map +}; + +void plat_brcm_interconnect_init(void) +{ + ccn_init(&bcm_ccn_desc); +} + +void plat_brcm_interconnect_enter_coherency(void) +{ + ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +void plat_brcm_interconnect_exit_coherency(void) +{ + ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_common.c b/arm-trusted-firmware/plat/brcm/common/brcm_common.c new file mode 100644 index 0000000..f23719d --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_common.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include + +/* Weak definitions may be overridden in specific BRCM platform */ +#pragma weak plat_get_ns_image_entrypoint +#pragma weak plat_brcm_get_mmap + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_BRCM_NS_IMAGE_OFFSET; +#endif +} + +uint32_t brcm_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +uint32_t brcm_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + mode = el_implemented(2) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +const mmap_region_t *plat_brcm_get_mmap(void) +{ + return plat_brcm_mmap; +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c b/arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c new file mode 100644 index 0000000..c4137c0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t brcm_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t brcm_interrupt_props[] = { + /* G1S interrupts */ + PLAT_BRCM_G1S_IRQ_PROPS(INTR_GROUP1S), + /* G0 interrupts */ + PLAT_BRCM_G0_IRQ_PROPS(INTR_GROUP0) +}; + +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static unsigned int brcm_gicv3_mpidr_hash(u_register_t mpidr) +{ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return plat_core_pos_by_mpidr(mpidr); +} + +static const gicv3_driver_data_t brcm_gic_data = { + .gicd_base = PLAT_BRCM_GICD_BASE, + .gicr_base = PLAT_BRCM_GICR_BASE, + .interrupt_props = brcm_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(brcm_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = brcm_rdistif_base_addrs, + .mpidr_to_core_pos = brcm_gicv3_mpidr_hash +}; + +void plat_brcm_gic_driver_init(void) +{ + /* TODO Check if this is required to be initialized here + * after getting initialized in EL3, should we re-init this here + * in S-EL1 + */ + gicv3_driver_init(&brcm_gic_data); +} + +void plat_brcm_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void plat_brcm_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void plat_brcm_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void plat_brcm_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} + +void plat_brcm_gic_redistif_on(void) +{ + gicv3_rdistif_on(plat_my_core_pos()); +} + +void plat_brcm_gic_redistif_off(void) +{ + gicv3_rdistif_off(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_image_load.c b/arm-trusted-firmware/plat/brcm/common/brcm_image_load.c new file mode 100644 index 0000000..ba02bda --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_image_load.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#pragma weak plat_flush_next_bl_params +#pragma weak plat_get_bl_image_load_info +#pragma weak plat_get_next_bl_params + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +struct bl_load_info *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + bl_params_t *next_bl_params = get_next_bl_params_from_mem_params_desc(); + + populate_next_bl_params_config(next_bl_params); + return next_bl_params; +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c b/arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c new file mode 100644 index 0000000..66ec292 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2019-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 + +/* IO devices */ +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *memmap_dev_con; +static uintptr_t memmap_dev_handle; + +static const io_block_spec_t fip_block_spec = { + .offset = PLAT_BRCM_FIP_BASE, + .length = PLAT_BRCM_FIP_MAX_SIZE +}; + +static const io_block_spec_t qspi_fip_block_spec = { + .offset = PLAT_BRCM_FIP_QSPI_BASE, + .length = PLAT_BRCM_FIP_MAX_SIZE +}; + +static const io_block_spec_t nand_fip_block_spec = { + .offset = PLAT_BRCM_FIP_NAND_BASE, + .length = PLAT_BRCM_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t scp_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +static const io_uuid_spec_t tb_fw_config_uuid_spec = { + .uuid = UUID_TB_FW_CONFIG, +}; + +static const io_uuid_spec_t hw_config_uuid_spec = { + .uuid = UUID_HW_CONFIG, +}; + +static const io_uuid_spec_t soc_fw_config_uuid_spec = { + .uuid = UUID_SOC_FW_CONFIG, +}; + +static const io_uuid_spec_t tos_fw_config_uuid_spec = { + .uuid = UUID_TOS_FW_CONFIG, +}; + +static const io_uuid_spec_t nt_fw_config_uuid_spec = { + .uuid = UUID_NT_FW_CONFIG, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t tb_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FW_CERT, +}; + +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = { + .uuid = UUID_SCP_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_cert_uuid_spec = { + .uuid = UUID_SCP_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static int open_fip(const uintptr_t spec); +static int open_memmap(const uintptr_t spec); +static int open_qspi(const uintptr_t spec); +static int open_nand(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, BRCM platforms load images from the FIP */ +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, + [TB_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_config_uuid_spec, + open_fip + }, + [HW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&hw_config_uuid_spec, + open_fip + }, + [SOC_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_config_uuid_spec, + open_fip + }, + [TOS_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_config_uuid_spec, + open_fip + }, + [NT_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_config_uuid_spec, + open_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + open_fip + }, + [SCP_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_key_cert_uuid_spec, + open_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + open_fip + }, + [SCP_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_cert_uuid_spec, + open_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + open_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + +/* By default, BRCM platforms load images from the FIP */ +static const struct plat_io_policy boot_source_policies[] = { + [BOOT_SOURCE_QSPI] = { + &memmap_dev_handle, + (uintptr_t)&qspi_fip_block_spec, + open_qspi + }, + [BOOT_SOURCE_NAND] = { + &memmap_dev_handle, + (uintptr_t)&nand_fip_block_spec, + open_nand + }, +}; + +/* Weak definitions may be overridden in specific brcm platform */ +#pragma weak plat_brcm_io_setup +#pragma weak plat_brcm_process_flags + +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + + +static int open_memmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Memmap\n"); + io_close(local_image_handle); + } + } + return result; +} + +static int open_qspi(const uintptr_t spec) +{ + return open_memmap(spec); +} + +static int open_nand(const uintptr_t spec) +{ + return open_memmap(spec); +} + + +void brcm_io_setup(void) +{ + int io_result; + uint32_t boot_source; + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + assert(io_result == 0); + + boot_source = boot_source_get(); + switch (boot_source) { + case BOOT_SOURCE_QSPI: + case BOOT_SOURCE_NAND: + default: + io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &memmap_dev_handle); + break; + } + assert(io_result == 0); + + /* Ignore improbable errors in release builds */ + (void)io_result; +} + +void plat_brcm_io_setup(void) +{ + brcm_io_setup(); +} + +void plat_brcm_process_flags(uint16_t plat_toc_flags __unused) +{ + WARN("%s not implemented\n", __func__); +} + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + uint32_t boot_source; + uint16_t lcl_plat_toc_flg; + + assert(image_id < ARRAY_SIZE(policies)); + + boot_source = boot_source_get(); + if (image_id == FIP_IMAGE_ID) + policy = &boot_source_policies[boot_source]; + else + policy = &policies[image_id]; + + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + if (image_id == TRUSTED_BOOT_FW_CERT_ID) { + /* + * Process the header flags to perform + * such custom actions as speeding up PLL. + * CERT seems to be the first image accessed + * by BL1 so this is where we process the flags. + */ + fip_dev_get_plat_toc_flag((io_dev_info_t *)fip_dev_handle, + &lcl_plat_toc_flg); + plat_brcm_process_flags(lcl_plat_toc_flg); + } + } + + return result; +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_mhu.c b/arm-trusted-firmware/plat/brcm/common/brcm_mhu.c new file mode 100644 index 0000000..56f44e0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_mhu.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#include "m0_ipc.h" + +#define PLAT_MHU_INTR_REG AP_TO_SCP_MAILBOX1 + +/* SCP MHU secure channel registers */ +#define SCP_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG11 +#define SCP_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG11 +#define SCP_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG11 + +/* CPU MHU secure channel registers */ +#define CPU_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG10 +#define CPU_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG10 +#define CPU_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG10 + +static DEFINE_BAKERY_LOCK(bcm_lock); + +/* + * Slot 31 is reserved because the MHU hardware uses this register bit to + * indicate a non-secure access attempt. The total number of available slots is + * therefore 31 [30:0]. + */ +#define MHU_MAX_SLOT_ID 30 + +void mhu_secure_message_start(unsigned int slot_id) +{ + int iter = 1000000; + + assert(slot_id <= MHU_MAX_SLOT_ID); + + bakery_lock_get(&bcm_lock); + /* Make sure any previous command has finished */ + do { + if (!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id))) + break; + + udelay(1); + + } while (--iter); + + assert(iter != 0); +} + +void mhu_secure_message_send(unsigned int slot_id) +{ + uint32_t response, iter = 1000000; + + assert(slot_id <= MHU_MAX_SLOT_ID); + assert(!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id))); + + /* Send command to SCP */ + mmio_setbits_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id); + mmio_write_32(CRMU_MAIL_BOX0, MCU_IPC_MCU_CMD_SCPI); + mmio_write_32(PLAT_BRCM_MHU_BASE + PLAT_MHU_INTR_REG, 0x1); + + /* Wait until IPC transport acknowledges reception of SCP command */ + do { + response = mmio_read_32(CRMU_MAIL_BOX0); + if ((response & ~MCU_IPC_CMD_REPLY_MASK) == + (MCU_IPC_CMD_DONE_MASK | MCU_IPC_MCU_CMD_SCPI)) + break; + + udelay(1); + + } while (--iter); + + assert(iter != 0); +} + +uint32_t mhu_secure_message_wait(void) +{ + /* Wait for response from SCP */ + uint32_t response, iter = 1000000; + + do { + response = mmio_read_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT); + if (!response) + break; + + udelay(1); + } while (--iter); + assert(iter != 0); + + return response; +} + +void mhu_secure_message_end(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + + /* + * Clear any response we got by writing one in the relevant slot bit to + * the CLEAR register + */ + mmio_clrbits_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id); + bakery_lock_release(&bcm_lock); +} + +void mhu_secure_init(void) +{ + bakery_lock_init(&bcm_lock); + + /* + * The STAT register resets to zero. Ensure it is in the expected state, + * as a stale or garbage value would make us think it's a message we've + * already sent. + */ + mmio_write_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT, 0); + mmio_write_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT, 0); +} + +void plat_brcm_pwrc_setup(void) +{ + mhu_secure_init(); +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_mhu.h b/arm-trusted-firmware/plat/brcm/common/brcm_mhu.h new file mode 100644 index 0000000..6c89a34 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_mhu.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BRCM_MHU_H +#define BRCM_MHU_H + +#include + +void mhu_secure_message_start(unsigned int slot_id); +void mhu_secure_message_send(unsigned int slot_id); +uint32_t mhu_secure_message_wait(void); +void mhu_secure_message_end(unsigned int slot_id); + +void mhu_secure_init(void); + +#endif /* BRCM_MHU_H */ diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_scpi.c b/arm-trusted-firmware/plat/brcm/common/brcm_scpi.c new file mode 100644 index 0000000..0a703cb --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_scpi.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#define SCPI_SHARED_MEM_SCP_TO_AP (PLAT_SCP_COM_SHARED_MEM_BASE) +#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_SCP_COM_SHARED_MEM_BASE \ + + 0x100) + +/* Header and payload addresses for commands from AP to SCP */ +#define SCPI_CMD_HEADER_AP_TO_SCP \ + ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP) +#define SCPI_CMD_PAYLOAD_AP_TO_SCP \ + ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t))) + +/* Header and payload addresses for responses from SCP to AP */ +#define SCPI_RES_HEADER_SCP_TO_AP \ + ((scpi_cmd_t *) SCPI_SHARED_MEM_SCP_TO_AP) +#define SCPI_RES_PAYLOAD_SCP_TO_AP \ + ((void *) (SCPI_SHARED_MEM_SCP_TO_AP + sizeof(scpi_cmd_t))) + +/* ID of the MHU slot used for the SCPI protocol */ +#define SCPI_MHU_SLOT_ID 0 + +static void scpi_secure_message_start(void) +{ + mhu_secure_message_start(SCPI_MHU_SLOT_ID); +} + +static void scpi_secure_message_send(size_t payload_size) +{ + /* + * Ensure that any write to the SCPI payload area is seen by SCP before + * we write to the MHU register. If these 2 writes were reordered by + * the CPU then SCP would read stale payload data + */ + dmbst(); + + mhu_secure_message_send(SCPI_MHU_SLOT_ID); +} + +static void scpi_secure_message_receive(scpi_cmd_t *cmd) +{ + uint32_t mhu_status; + + assert(cmd != NULL); + + mhu_status = mhu_secure_message_wait(); + + /* Expect an SCPI message, reject any other protocol */ + if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) { + ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", + mhu_status); + panic(); + } + + /* + * Ensure that any read to the SCPI payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); + + memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd)); +} + +static void scpi_secure_message_end(void) +{ + mhu_secure_message_end(SCPI_MHU_SLOT_ID); +} + +int scpi_wait_ready(void) +{ + scpi_cmd_t scpi_cmd; + + VERBOSE("Waiting for SCP_READY command...\n"); + + /* Get a message from the SCP */ + scpi_secure_message_start(); + scpi_secure_message_receive(&scpi_cmd); + scpi_secure_message_end(); + + /* We are expecting 'SCP Ready', produce correct error if it's not */ + scpi_status_t status = SCP_OK; + + if (scpi_cmd.id != SCPI_CMD_SCP_READY) { + ERROR("Unexpected SCP command: expected #%u, received #%u\n", + SCPI_CMD_SCP_READY, scpi_cmd.id); + status = SCP_E_SUPPORT; + } else if (scpi_cmd.size != 0) { + ERROR("SCP_READY cmd has incorrect size: expected 0, got %u\n", + scpi_cmd.size); + status = SCP_E_SIZE; + } + + VERBOSE("Sending response for SCP_READY command\n"); + + /* + * Send our response back to SCP. + * We are using the same SCPI header, just update the status field. + */ + scpi_cmd.status = status; + scpi_secure_message_start(); + memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd)); + scpi_secure_message_send(0); + scpi_secure_message_end(); + + return status == SCP_OK ? 0 : -1; +} + +void scpi_set_brcm_power_state(unsigned int mpidr, + scpi_power_state_t cpu_state, scpi_power_state_t cluster_state, + scpi_power_state_t brcm_state) +{ + scpi_cmd_t *cmd; + uint32_t state = 0; + uint32_t *payload_addr; + +#if ARM_PLAT_MT + /* + * The current SCPI driver only caters for single-threaded platforms. + * Hence we ignore the thread ID (which is always 0) for such platforms. + */ + state |= (mpidr >> MPIDR_AFF1_SHIFT) & 0x0f; /* CPU ID */ + state |= ((mpidr >> MPIDR_AFF2_SHIFT) & 0x0f) << 4; /* Cluster ID */ +#else + state |= mpidr & 0x0f; /* CPU ID */ + state |= (mpidr & 0xf00) >> 4; /* Cluster ID */ +#endif /* ARM_PLAT_MT */ + + state |= cpu_state << 8; + state |= cluster_state << 12; + state |= brcm_state << 16; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SET_POWER_STATE; + cmd->set = SCPI_SET_NORMAL; + cmd->sender = 0; + cmd->size = sizeof(state); + /* Populate the command payload */ + payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; + *payload_addr = state; + scpi_secure_message_send(sizeof(state)); + + /* + * SCP does not reply to this command in order to avoid MHU interrupts + * from the sender, which could interfere with its power state request. + */ + scpi_secure_message_end(); +} + +/* + * Query and obtain power state from SCP. + * + * In response to the query, SCP returns power states of all CPUs in all + * clusters of the system. The returned response is then filtered based on the + * supplied MPIDR. Power states of requested cluster and CPUs within are updated + * via. supplied non-NULL pointer arguments. + * + * Returns 0 on success, or -1 on errors. + */ +int scpi_get_brcm_power_state(unsigned int mpidr, unsigned int *cpu_state_p, + unsigned int *cluster_state_p) +{ + scpi_cmd_t *cmd; + scpi_cmd_t response; + int power_state, cpu, cluster, rc = -1; + + /* + * Extract CPU and cluster membership of the given MPIDR. SCPI caters + * for only up to 0xf clusters, and 8 CPUs per cluster + */ + cpu = mpidr & MPIDR_AFFLVL_MASK; + cluster = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + if (cpu >= 8 || cluster >= 0xf) + return -1; + + scpi_secure_message_start(); + + /* Populate request headers */ + zeromem(SCPI_CMD_HEADER_AP_TO_SCP, sizeof(*cmd)); + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_GET_POWER_STATE; + + /* + * Send message and wait for SCP's response + */ + scpi_secure_message_send(0); + scpi_secure_message_receive(&response); + + if (response.status != SCP_OK) + goto exit; + + /* Validate SCP response */ + if (!CHECK_RESPONSE(response, cluster)) + goto exit; + + /* Extract power states for required cluster */ + power_state = *(((uint16_t *) SCPI_RES_PAYLOAD_SCP_TO_AP) + cluster); + if (CLUSTER_ID(power_state) != cluster) + goto exit; + + /* Update power state via. pointers */ + if (cluster_state_p) + *cluster_state_p = CLUSTER_POWER_STATE(power_state); + if (cpu_state_p) + *cpu_state_p = CPU_POWER_STATE(power_state); + rc = 0; + +exit: + scpi_secure_message_end(); + return rc; +} + +uint32_t scpi_sys_power_state(scpi_system_state_t system_state) +{ + scpi_cmd_t *cmd; + uint8_t *payload_addr; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SYS_POWER_STATE; + cmd->set = 0; + cmd->sender = 0; + cmd->size = sizeof(*payload_addr); + /* Populate the command payload */ + payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; + *payload_addr = system_state & 0xff; + scpi_secure_message_send(sizeof(*payload_addr)); + + scpi_secure_message_end(); + + return SCP_OK; +} diff --git a/arm-trusted-firmware/plat/brcm/common/brcm_scpi.h b/arm-trusted-firmware/plat/brcm/common/brcm_scpi.h new file mode 100644 index 0000000..f3b658f --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/common/brcm_scpi.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BRCM_SCPI_H +#define BRCM_SCPI_H + +#include +#include + +/* + * An SCPI command consists of a header and a payload. + * The following structure describes the header. It is 64-bit long. + */ +typedef struct { + /* Command ID */ + uint32_t id : 7; + /* Set ID. Identifies whether this is a standard or extended command. */ + uint32_t set : 1; + /* Sender ID to match a reply. The value is sender specific. */ + uint32_t sender : 8; + /* Size of the payload in bytes (0 - 511) */ + uint32_t size : 9; + uint32_t reserved : 7; + /* + * Status indicating the success of a command. + * See the enum below. + */ + uint32_t status; +} scpi_cmd_t; + +typedef enum { + SCPI_SET_NORMAL = 0, /* Normal SCPI commands */ + SCPI_SET_EXTENDED /* Extended SCPI commands */ +} scpi_set_t; + +enum { + SCP_OK = 0, /* Success */ + SCP_E_PARAM, /* Invalid parameter(s) */ + SCP_E_ALIGN, /* Invalid alignment */ + SCP_E_SIZE, /* Invalid size */ + SCP_E_HANDLER, /* Invalid handler or callback */ + SCP_E_ACCESS, /* Invalid access or permission denied */ + SCP_E_RANGE, /* Value out of range */ + SCP_E_TIMEOUT, /* Time out has ocurred */ + SCP_E_NOMEM, /* Invalid memory area or pointer */ + SCP_E_PWRSTATE, /* Invalid power state */ + SCP_E_SUPPORT, /* Feature not supported or disabled */ + SCPI_E_DEVICE, /* Device error */ + SCPI_E_BUSY, /* Device is busy */ +}; + +typedef uint32_t scpi_status_t; +typedef enum { + SCPI_CMD_SCP_READY = 0x01, + SCPI_CMD_SET_POWER_STATE = 0x03, + SCPI_CMD_GET_POWER_STATE = 0x04, + SCPI_CMD_SYS_POWER_STATE = 0x05 +} scpi_command_t; + +/* + * Macros to parse SCP response to GET_POWER_STATE command + * + * [3:0] : cluster ID + * [7:4] : cluster state: 0 = on; 3 = off; rest are reserved + * [15:8]: on/off state for individual CPUs in the cluster + * + * Payload is in little-endian + */ +#define CLUSTER_ID(_resp) ((_resp) & 0xf) +#define CLUSTER_POWER_STATE(_resp) (((_resp) >> 4) & 0xf) + +/* Result is a bit mask of CPU on/off states in the cluster */ +#define CPU_POWER_STATE(_resp) (((_resp) >> 8) & 0xff) + +/* + * For GET_POWER_STATE, SCP returns the power states of every cluster. The + * size of response depends on the number of clusters in the system. The + * SCP-to-AP payload contains 2 bytes per cluster. Make sure the response is + * large enough to contain power states of a given cluster + */ +#define CHECK_RESPONSE(_resp, _clus) (_resp.size >= (((_clus) + 1) * 2)) + +typedef enum { + scpi_power_on = 0, + scpi_power_retention = 1, + scpi_power_off = 3, +} scpi_power_state_t; + +typedef enum { + scpi_system_shutdown = 0, + scpi_system_reboot = 1, + scpi_system_reset = 2 +} scpi_system_state_t; + +extern int scpi_wait_ready(void); +extern void scpi_set_brcm_power_state(unsigned int mpidr, + scpi_power_state_t cpu_state, + scpi_power_state_t cluster_state, + scpi_power_state_t css_state); +int scpi_get_brcm_power_state(unsigned int mpidr, unsigned int *cpu_state_p, + unsigned int *cluster_state_p); +uint32_t scpi_sys_power_state(scpi_system_state_t system_state); + +#endif /* BRCM_SCPI_H */ diff --git a/arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S b/arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S new file mode 100644 index 0000000..ea04f56 --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + + /* ----------------------------------------------------- + * int plat_crash_console_init(void) + * Use normal console by default. Switch it to crash + * mode so serial consoles become active again. + * NOTE: This default implementation will only work for + * crashes that occur after a normal console (marked + * valid for the crash state) has been registered with + * the console framework. To debug crashes that occur + * earlier, the platform has to override these functions + * with an implementation that initializes a console + * driver with hardcoded parameters. See + * docs/porting-guide.rst for more information. + * ----------------------------------------------------- + */ +func plat_crash_console_init +#if defined(IMAGE_BL1) + /* + * BL1 code can possibly crash so early that the data segment is not yet + * accessible. Don't risk undefined behavior by trying to run the normal + * console framework. Platforms that want to debug BL1 will need to + * override this with custom functions that can run from registers only. + */ + mov r0, #0 + bx lr +#else /* IMAGE_BL1 */ + mov r3, lr + mov r0, #CONSOLE_FLAG_CRASH + bl console_switch_state + mov r0, #1 + bx r3 +#endif +endfunc plat_crash_console_init + + /* ----------------------------------------------------- + * void plat_crash_console_putc(int character) + * Output through the normal console by default. + * ----------------------------------------------------- + */ +func plat_crash_console_putc + b console_putc +endfunc plat_crash_console_putc + + /* ----------------------------------------------------- + * void plat_crash_console_flush(void) + * Flush normal console by default. + * ----------------------------------------------------- + */ +func plat_crash_console_flush + b console_flush +endfunc plat_crash_console_flush diff --git a/arm-trusted-firmware/plat/common/aarch32/plat_common.c b/arm-trusted-firmware/plat/common/aarch32/plat_common.c new file mode 100644 index 0000000..2c1a8fa --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch32/plat_common.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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 bl32_plat_enable_mmu + + +void bl32_plat_enable_mmu(uint32_t flags) +{ + enable_mmu_svc_mon(flags); +} diff --git a/arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c b/arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c new file mode 100644 index 0000000..9493587 --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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 sp_min_plat_runtime_setup + +void sp_min_plat_runtime_setup(void) +{ + /* + * Finish the use of console driver in SP_MIN so that any runtime logs + * from SP_MIN will be suppressed. + */ + console_switch_state(CONSOLE_FLAG_RUNTIME); +} diff --git a/arm-trusted-firmware/plat/common/aarch32/platform_helpers.S b/arm-trusted-firmware/plat/common/aarch32/platform_helpers.S new file mode 100644 index 0000000..5b9cb59 --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch32/platform_helpers.S @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .weak plat_report_exception + .weak plat_reset_handler + .weak plat_disable_acp + .weak bl1_plat_prepare_exit + .weak platform_mem_init + .weak plat_panic_handler + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * ----------------------------------------------------- + */ +func plat_report_exception + bx lr +endfunc plat_report_exception + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * ----------------------------------------------------- + */ +func plat_reset_handler + bx lr +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * ----------------------------------------------------- + */ +func plat_disable_acp + bx lr +endfunc plat_disable_acp + + /* --------------------------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * --------------------------------------------------------------------- + */ +func platform_mem_init + bx lr +endfunc platform_mem_init + + /* ----------------------------------------------------- + * void bl1_plat_prepare_exit(entry_point_info_t *ep_info); + * Called before exiting BL1. Default: do nothing + * ----------------------------------------------------- + */ +func bl1_plat_prepare_exit + bx lr +endfunc bl1_plat_prepare_exit + + /* ----------------------------------------------------- + * void plat_panic_handler(void) __dead2; + * Endless loop by default. + * ----------------------------------------------------- + */ +func plat_panic_handler + b plat_panic_handler +endfunc plat_panic_handler diff --git a/arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S b/arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S new file mode 100644 index 0000000..6c3d08d --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .weak plat_get_my_stack + .weak plat_set_my_stack + + /* ----------------------------------------------------- + * uintptr_t plat_get_my_stack (u_register_t mpidr) + * + * For a given CPU, this function returns the stack + * pointer for a stack allocated in device memory. + * ----------------------------------------------------- + */ +func plat_get_my_stack + push {r4, lr} + get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE + pop {r4, pc} +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 r4, lr + get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE + mov sp, r0 + bx r4 +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 diff --git a/arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S b/arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S new file mode 100644 index 0000000..836c13a --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .weak plat_get_my_stack + .weak plat_set_my_stack + + /* ----------------------------------------------------- + * unsigned long 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 normal memory. + * ----------------------------------------------------- + */ +func plat_get_my_stack + get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE + bx lr +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, r0 + bx lr +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, 1, CACHE_WRITEBACK_GRANULE diff --git a/arm-trusted-firmware/plat/common/aarch64/crash_console_helpers.S b/arm-trusted-firmware/plat/common/aarch64/crash_console_helpers.S new file mode 100644 index 0000000..e2950f5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/common/aarch64/plat_common.c b/arm-trusted-firmware/plat/common/aarch64/plat_common.c new file mode 100644 index 0000000..38a5786 --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch64/plat_common.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#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 = plat_default_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 %" PRIx64 "\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_default_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_NL(); + ERROR("Unhandled External Abort received on 0x%lx from %s\n", + read_mpidr_el1(), get_el_str(level)); + ERROR("exception reason=%u syndrome=0x%" PRIx64 "\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/arm-trusted-firmware/plat/common/aarch64/plat_ehf.c b/arm-trusted-firmware/plat/common/aarch64/plat_ehf.c new file mode 100644 index 0000000..da76884 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/common/aarch64/platform_helpers.S b/arm-trusted-firmware/plat/common/aarch64/platform_helpers.S new file mode 100644 index 0000000..bc650c9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/common/aarch64/platform_mp_stack.S b/arm-trusted-firmware/plat/common/aarch64/platform_mp_stack.S new file mode 100644 index 0000000..c0668ea --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/common/aarch64/platform_up_stack.S b/arm-trusted-firmware/plat/common/aarch64/platform_up_stack.S new file mode 100644 index 0000000..c6e5e2d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/common/plat_bl1_common.c b/arm-trusted-firmware/plat/common/plat_bl1_common.c new file mode 100644 index 0000000..bcf9f89 --- /dev/null +++ b/arm-trusted-firmware/plat/common/plat_bl1_common.c @@ -0,0 +1,117 @@ +/* + * 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 + +/* + * The following platform functions are weakly defined. They + * are default implementations that allow BL1 to compile in + * absence of real definitions. The Platforms may override + * with more complex definitions. + */ +#pragma weak bl1_plat_get_next_image_id +#pragma weak bl1_plat_set_ep_info +#pragma weak bl1_plat_get_image_desc +#pragma weak bl1_plat_fwu_done +#pragma weak bl1_plat_handle_pre_image_load +#pragma weak bl1_plat_handle_post_image_load + +unsigned int bl1_plat_get_next_image_id(void) +{ + /* BL2 load will be done by default. */ + return BL2_IMAGE_ID; +} + +void bl1_plat_set_ep_info(unsigned int image_id, + struct entry_point_info *ep_info) +{ + +} + +int bl1_plat_handle_pre_image_load(unsigned int image_id) +{ + return 0; +} + +/* + * Following is the default definition that always + * returns BL2 image details. + */ +struct image_desc *bl1_plat_get_image_desc(unsigned int image_id) +{ + static image_desc_t bl2_img_desc = BL2_IMAGE_DESC; + return &bl2_img_desc; +} + +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved) +{ + while (true) + wfi(); +} + +/* + * The Platforms must override with real definition. + */ +#pragma weak bl1_plat_mem_check + +int bl1_plat_mem_check(uintptr_t mem_base, unsigned int mem_size, + unsigned int flags) +{ + assert(0); + return -ENOMEM; +} + +/* + * Default implementation for bl1_plat_handle_post_image_load(). This function + * populates the default arguments to BL2. The BL2 memory layout structure + * is allocated and the calculated layout is populated in arg1 to BL2. + */ +int bl1_plat_handle_post_image_load(unsigned int image_id) +{ + meminfo_t *bl2_secram_layout; + meminfo_t *bl1_secram_layout; + image_desc_t *image_desc; + entry_point_info_t *ep_info; + + if (image_id != BL2_IMAGE_ID) + return 0; + + /* Get the image descriptor */ + image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(image_desc != NULL); + + /* Get the entry point info */ + ep_info = &image_desc->ep_info; + + /* Find out how much free trusted ram remains after BL1 load */ + bl1_secram_layout = bl1_plat_sec_mem_layout(); + + /* + * Create a new layout of memory for BL2 as seen by BL1 i.e. + * tell it the amount of total and free memory available. + * This layout is created at the first free address visible + * to BL2. BL2 will read the memory layout before using its + * memory for other purposes. + */ + bl2_secram_layout = (meminfo_t *) bl1_secram_layout->total_base; + + bl1_calc_bl2_mem_layout(bl1_secram_layout, bl2_secram_layout); + + ep_info->args.arg1 = (uintptr_t)bl2_secram_layout; + + VERBOSE("BL1: BL2 memory layout address = %p\n", + (void *) bl2_secram_layout); + return 0; +} diff --git a/arm-trusted-firmware/plat/common/plat_bl_common.c b/arm-trusted-firmware/plat/common/plat_bl_common.c new file mode 100644 index 0000000..89b77ba --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/common/plat_gicv2.c b/arm-trusted-firmware/plat/common/plat_gicv2.c new file mode 100644 index 0000000..4c76f1b --- /dev/null +++ b/arm-trusted-firmware/plat/common/plat_gicv2.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +/* + * The following platform GIC 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 plat_ic_get_pending_interrupt_id +#pragma weak plat_ic_get_pending_interrupt_type +#pragma weak plat_ic_acknowledge_interrupt +#pragma weak plat_ic_get_interrupt_type +#pragma weak plat_ic_end_of_interrupt +#pragma weak plat_interrupt_type_to_line + +#pragma weak plat_ic_get_running_priority +#pragma weak plat_ic_is_spi +#pragma weak plat_ic_is_ppi +#pragma weak plat_ic_is_sgi +#pragma weak plat_ic_get_interrupt_active +#pragma weak plat_ic_enable_interrupt +#pragma weak plat_ic_disable_interrupt +#pragma weak plat_ic_set_interrupt_priority +#pragma weak plat_ic_set_interrupt_type +#pragma weak plat_ic_raise_el3_sgi +#pragma weak plat_ic_set_spi_routing + +/* + * This function returns the highest priority pending interrupt at + * the Interrupt controller + */ +uint32_t plat_ic_get_pending_interrupt_id(void) +{ + unsigned int id; + + id = gicv2_get_pending_interrupt_id(); + if (id == GIC_SPURIOUS_INTERRUPT) + return INTR_ID_UNAVAILABLE; + + return id; +} + +/* + * This function returns the type of the highest priority pending interrupt + * at the Interrupt controller. In the case of GICv2, the Highest Priority + * Pending interrupt register (`GICC_HPPIR`) is read to determine the id of + * the pending interrupt. The type of interrupt depends upon the id value + * as follows. + * 1. id < PENDING_G1_INTID (1022) is reported as a S-EL1 interrupt + * 2. id = PENDING_G1_INTID (1022) is reported as a Non-secure interrupt. + * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt + * type. + */ +uint32_t plat_ic_get_pending_interrupt_type(void) +{ + unsigned int id; + + id = gicv2_get_pending_interrupt_type(); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + if (id < PENDING_G1_INTID) { +#if GICV2_G0_FOR_EL3 + return INTR_TYPE_EL3; +#else + return INTR_TYPE_S_EL1; +#endif + } + + if (id == GIC_SPURIOUS_INTERRUPT) + return INTR_TYPE_INVAL; + + return INTR_TYPE_NS; +} + +/* + * This function returns the highest priority pending interrupt at + * the Interrupt controller and indicates to the Interrupt controller + * that the interrupt processing has started. + */ +uint32_t plat_ic_acknowledge_interrupt(void) +{ + return gicv2_acknowledge_interrupt(); +} + +/* + * This function returns the type of the interrupt `id`, depending on how + * the interrupt has been configured in the interrupt controller + */ +uint32_t plat_ic_get_interrupt_type(uint32_t id) +{ + unsigned int type; + + type = gicv2_get_interrupt_group(id); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + return (type == GICV2_INTR_GROUP1) ? INTR_TYPE_NS : +#if GICV2_G0_FOR_EL3 + INTR_TYPE_EL3; +#else + INTR_TYPE_S_EL1; +#endif +} + +/* + * This functions is used to indicate to the interrupt controller that + * the processing of the interrupt corresponding to the `id` has + * finished. + */ +void plat_ic_end_of_interrupt(uint32_t id) +{ + gicv2_end_of_interrupt(id); +} + +/* + * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. + * The interrupt controller knows which pin/line it uses to signal a type of + * interrupt. It lets the interrupt management framework determine + * for a type of interrupt and security state, which line should be used in the + * SCR_EL3 to control its routing to EL3. The interrupt line is represented + * as the bit position of the IRQ or FIQ bit in the SCR_EL3. + */ +uint32_t plat_interrupt_type_to_line(uint32_t type, + uint32_t security_state) +{ + assert((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_EL3) || + (type == INTR_TYPE_NS)); + + assert(sec_state_is_valid(security_state)); + + /* Non-secure interrupts are signaled on the IRQ line always */ + if (type == INTR_TYPE_NS) + return __builtin_ctz(SCR_IRQ_BIT); + + /* + * Secure interrupts are signaled using the IRQ line if the FIQ is + * not enabled else they are signaled using the FIQ line. + */ + return ((gicv2_is_fiq_enabled() != 0U) ? __builtin_ctz(SCR_FIQ_BIT) : + __builtin_ctz(SCR_IRQ_BIT)); +} + +unsigned int plat_ic_get_running_priority(void) +{ + return gicv2_get_running_priority(); +} + +int plat_ic_is_spi(unsigned int id) +{ + return (id >= MIN_SPI_ID) && (id <= MAX_SPI_ID); +} + +int plat_ic_is_ppi(unsigned int id) +{ + return (id >= MIN_PPI_ID) && (id < MIN_SPI_ID); +} + +int plat_ic_is_sgi(unsigned int id) +{ + return (id >= MIN_SGI_ID) && (id < MIN_PPI_ID); +} + +unsigned int plat_ic_get_interrupt_active(unsigned int id) +{ + return gicv2_get_interrupt_active(id); +} + +void plat_ic_enable_interrupt(unsigned int id) +{ + gicv2_enable_interrupt(id); +} + +void plat_ic_disable_interrupt(unsigned int id) +{ + gicv2_disable_interrupt(id); +} + +void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority) +{ + gicv2_set_interrupt_priority(id, priority); +} + +int plat_ic_has_interrupt_type(unsigned int type) +{ + int has_interrupt_type = 0; + + switch (type) { +#if GICV2_G0_FOR_EL3 + case INTR_TYPE_EL3: +#else + case INTR_TYPE_S_EL1: +#endif + case INTR_TYPE_NS: + has_interrupt_type = 1; + break; + default: + /* Do nothing in default case */ + break; + } + + return has_interrupt_type; +} + +void plat_ic_set_interrupt_type(unsigned int id, unsigned int type) +{ + unsigned int gicv2_type = 0U; + + /* Map canonical interrupt type to GICv2 type */ + switch (type) { +#if GICV2_G0_FOR_EL3 + case INTR_TYPE_EL3: +#else + case INTR_TYPE_S_EL1: +#endif + gicv2_type = GICV2_INTR_GROUP0; + break; + case INTR_TYPE_NS: + gicv2_type = GICV2_INTR_GROUP1; + break; + default: + assert(0); /* Unreachable */ + break; + } + + gicv2_set_interrupt_type(id, gicv2_type); +} + +void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target) +{ +#if GICV2_G0_FOR_EL3 + int id; + + /* Target must be a valid MPIDR in the system */ + id = plat_core_pos_by_mpidr(target); + assert(id >= 0); + + /* Verify that this is a secure SGI */ + assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_EL3); + + gicv2_raise_sgi(sgi_num, id); +#else + assert(false); +#endif +} + +void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, + u_register_t mpidr) +{ + int proc_num = 0; + + switch (routing_mode) { + case INTR_ROUTING_MODE_PE: + proc_num = plat_core_pos_by_mpidr(mpidr); + assert(proc_num >= 0); + break; + case INTR_ROUTING_MODE_ANY: + /* Bit mask selecting all 8 CPUs as candidates */ + proc_num = -1; + break; + default: + assert(0); /* Unreachable */ + break; + } + + gicv2_set_spi_routing(id, proc_num); +} + +void plat_ic_set_interrupt_pending(unsigned int id) +{ + gicv2_set_interrupt_pending(id); +} + +void plat_ic_clear_interrupt_pending(unsigned int id) +{ + gicv2_clear_interrupt_pending(id); +} + +unsigned int plat_ic_set_priority_mask(unsigned int mask) +{ + return gicv2_set_pmr(mask); +} + +unsigned int plat_ic_get_interrupt_id(unsigned int raw) +{ + unsigned int id = (raw & INT_ID_MASK); + + if (id == GIC_SPURIOUS_INTERRUPT) + id = INTR_ID_UNAVAILABLE; + + return id; +} diff --git a/arm-trusted-firmware/plat/common/plat_gicv3.c b/arm-trusted-firmware/plat/common/plat_gicv3.c new file mode 100644 index 0000000..4a8a7ee --- /dev/null +++ b/arm-trusted-firmware/plat/common/plat_gicv3.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef IMAGE_BL31 + +/* + * The following platform GIC 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 plat_ic_get_pending_interrupt_id +#pragma weak plat_ic_get_pending_interrupt_type +#pragma weak plat_ic_acknowledge_interrupt +#pragma weak plat_ic_get_interrupt_type +#pragma weak plat_ic_end_of_interrupt +#pragma weak plat_interrupt_type_to_line + +#pragma weak plat_ic_get_running_priority +#pragma weak plat_ic_is_spi +#pragma weak plat_ic_is_ppi +#pragma weak plat_ic_is_sgi +#pragma weak plat_ic_get_interrupt_active +#pragma weak plat_ic_enable_interrupt +#pragma weak plat_ic_disable_interrupt +#pragma weak plat_ic_set_interrupt_priority +#pragma weak plat_ic_set_interrupt_type +#pragma weak plat_ic_raise_el3_sgi +#pragma weak plat_ic_set_spi_routing +#pragma weak plat_ic_set_interrupt_pending +#pragma weak plat_ic_clear_interrupt_pending + +CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) && + (INTR_TYPE_NS == INTR_GROUP1NS) && + (INTR_TYPE_EL3 == INTR_GROUP0), assert_interrupt_type_mismatch); + +/* + * This function returns the highest priority pending interrupt at + * the Interrupt controller + */ +uint32_t plat_ic_get_pending_interrupt_id(void) +{ + unsigned int irqnr; + + assert(IS_IN_EL3()); + irqnr = gicv3_get_pending_interrupt_id(); + return gicv3_is_intr_id_special_identifier(irqnr) ? + INTR_ID_UNAVAILABLE : irqnr; +} + +/* + * This function returns the type of the highest priority pending interrupt + * at the Interrupt controller. In the case of GICv3, the Highest Priority + * Pending interrupt system register (`ICC_HPPIR0_EL1`) is read to determine + * the id of the pending interrupt. The type of interrupt depends upon the + * id value as follows. + * 1. id = PENDING_G1S_INTID (1020) is reported as a S-EL1 interrupt + * 2. id = PENDING_G1NS_INTID (1021) is reported as a Non-secure interrupt. + * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt + * type. + * 4. All other interrupt id's are reported as EL3 interrupt. + */ +uint32_t plat_ic_get_pending_interrupt_type(void) +{ + unsigned int irqnr; + uint32_t type; + + assert(IS_IN_EL3()); + irqnr = gicv3_get_pending_interrupt_type(); + + switch (irqnr) { + case PENDING_G1S_INTID: + type = INTR_TYPE_S_EL1; + break; + case PENDING_G1NS_INTID: + type = INTR_TYPE_NS; + break; + case GIC_SPURIOUS_INTERRUPT: + type = INTR_TYPE_INVAL; + break; + default: + type = INTR_TYPE_EL3; + break; + } + + return type; +} + +/* + * This function returns the highest priority pending interrupt at + * the Interrupt controller and indicates to the Interrupt controller + * that the interrupt processing has started. + */ +uint32_t plat_ic_acknowledge_interrupt(void) +{ + assert(IS_IN_EL3()); + return gicv3_acknowledge_interrupt(); +} + +/* + * This function returns the type of the interrupt `id`, depending on how + * the interrupt has been configured in the interrupt controller + */ +uint32_t plat_ic_get_interrupt_type(uint32_t id) +{ + assert(IS_IN_EL3()); + return gicv3_get_interrupt_type(id, plat_my_core_pos()); +} + +/* + * This functions is used to indicate to the interrupt controller that + * the processing of the interrupt corresponding to the `id` has + * finished. + */ +void plat_ic_end_of_interrupt(uint32_t id) +{ + assert(IS_IN_EL3()); + gicv3_end_of_interrupt(id); +} + +/* + * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. + * The interrupt controller knows which pin/line it uses to signal a type of + * interrupt. It lets the interrupt management framework determine for a type of + * interrupt and security state, which line should be used in the SCR_EL3 to + * control its routing to EL3. The interrupt line is represented as the bit + * position of the IRQ or FIQ bit in the SCR_EL3. + */ +uint32_t plat_interrupt_type_to_line(uint32_t type, + uint32_t security_state) +{ + assert((type == INTR_TYPE_S_EL1) || + (type == INTR_TYPE_EL3) || + (type == INTR_TYPE_NS)); + + assert(sec_state_is_valid(security_state)); + assert(IS_IN_EL3()); + + switch (type) { + case INTR_TYPE_S_EL1: + /* + * The S-EL1 interrupts are signaled as IRQ in S-EL0/1 contexts + * and as FIQ in the NS-EL0/1/2 contexts + */ + if (security_state == SECURE) + return __builtin_ctz(SCR_IRQ_BIT); + else + return __builtin_ctz(SCR_FIQ_BIT); + assert(0); /* Unreachable */ + case INTR_TYPE_NS: + /* + * The Non secure interrupts will be signaled as FIQ in S-EL0/1 + * contexts and as IRQ in the NS-EL0/1/2 contexts. + */ + if (security_state == SECURE) + return __builtin_ctz(SCR_FIQ_BIT); + else + return __builtin_ctz(SCR_IRQ_BIT); + assert(0); /* Unreachable */ + case INTR_TYPE_EL3: + /* + * The EL3 interrupts are signaled as FIQ in both S-EL0/1 and + * NS-EL0/1/2 contexts + */ + return __builtin_ctz(SCR_FIQ_BIT); + default: + panic(); + } +} + +unsigned int plat_ic_get_running_priority(void) +{ + return gicv3_get_running_priority(); +} + +int plat_ic_is_spi(unsigned int id) +{ + return (id >= MIN_SPI_ID) && (id <= MAX_SPI_ID); +} + +int plat_ic_is_ppi(unsigned int id) +{ + return (id >= MIN_PPI_ID) && (id < MIN_SPI_ID); +} + +int plat_ic_is_sgi(unsigned int id) +{ + return (id >= MIN_SGI_ID) && (id < MIN_PPI_ID); +} + +unsigned int plat_ic_get_interrupt_active(unsigned int id) +{ + return gicv3_get_interrupt_active(id, plat_my_core_pos()); +} + +void plat_ic_enable_interrupt(unsigned int id) +{ + gicv3_enable_interrupt(id, plat_my_core_pos()); +} + +void plat_ic_disable_interrupt(unsigned int id) +{ + gicv3_disable_interrupt(id, plat_my_core_pos()); +} + +void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority) +{ + gicv3_set_interrupt_priority(id, plat_my_core_pos(), priority); +} + +int plat_ic_has_interrupt_type(unsigned int type) +{ + assert((type == INTR_TYPE_EL3) || (type == INTR_TYPE_S_EL1) || + (type == INTR_TYPE_NS)); + return 1; +} + +void plat_ic_set_interrupt_type(unsigned int id, unsigned int type) +{ + gicv3_set_interrupt_type(id, plat_my_core_pos(), type); +} + +void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target) +{ + /* Target must be a valid MPIDR in the system */ + assert(plat_core_pos_by_mpidr(target) >= 0); + + /* Verify that this is a secure EL3 SGI */ + assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) == + INTR_TYPE_EL3); + + gicv3_raise_secure_g0_sgi((unsigned int)sgi_num, target); +} + +void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, + u_register_t mpidr) +{ + unsigned int irm = 0; + + switch (routing_mode) { + case INTR_ROUTING_MODE_PE: + assert(plat_core_pos_by_mpidr(mpidr) >= 0); + irm = GICV3_IRM_PE; + break; + case INTR_ROUTING_MODE_ANY: + irm = GICV3_IRM_ANY; + break; + default: + assert(0); /* Unreachable */ + break; + } + + gicv3_set_spi_routing(id, irm, mpidr); +} + +void plat_ic_set_interrupt_pending(unsigned int id) +{ + /* Disallow setting SGIs pending */ + assert(id >= MIN_PPI_ID); + gicv3_set_interrupt_pending(id, plat_my_core_pos()); +} + +void plat_ic_clear_interrupt_pending(unsigned int id) +{ + /* Disallow setting SGIs pending */ + assert(id >= MIN_PPI_ID); + gicv3_clear_interrupt_pending(id, plat_my_core_pos()); +} + +unsigned int plat_ic_set_priority_mask(unsigned int mask) +{ + return gicv3_set_pmr(mask); +} + +unsigned int plat_ic_get_interrupt_id(unsigned int raw) +{ + unsigned int id = raw & INT_ID_MASK; + + return gicv3_is_intr_id_special_identifier(id) ? + INTR_ID_UNAVAILABLE : id; +} +#endif +#ifdef IMAGE_BL32 + +#pragma weak plat_ic_get_pending_interrupt_id +#pragma weak plat_ic_acknowledge_interrupt +#pragma weak plat_ic_end_of_interrupt + +/* In AArch32, the secure group1 interrupts are targeted to Secure PL1 */ +#ifndef __aarch64__ +#define IS_IN_EL1() IS_IN_SECURE() +#endif + +/* + * This function returns the highest priority pending interrupt at + * the Interrupt controller + */ +uint32_t plat_ic_get_pending_interrupt_id(void) +{ + unsigned int irqnr; + + assert(IS_IN_EL1()); + irqnr = gicv3_get_pending_interrupt_id_sel1(); + return (irqnr == GIC_SPURIOUS_INTERRUPT) ? + INTR_ID_UNAVAILABLE : irqnr; +} + +/* + * This function returns the highest priority pending interrupt at + * the Interrupt controller and indicates to the Interrupt controller + * that the interrupt processing has started. + */ +uint32_t plat_ic_acknowledge_interrupt(void) +{ + assert(IS_IN_EL1()); + return gicv3_acknowledge_interrupt_sel1(); +} + +/* + * This functions is used to indicate to the interrupt controller that + * the processing of the interrupt corresponding to the `id` has + * finished. + */ +void plat_ic_end_of_interrupt(uint32_t id) +{ + assert(IS_IN_EL1()); + gicv3_end_of_interrupt_sel1(id); +} +#endif diff --git a/arm-trusted-firmware/plat/common/plat_log_common.c b/arm-trusted-firmware/plat/common/plat_log_common.c new file mode 100644 index 0000000..66b9758 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/common/plat_psci_common.c b/arm-trusted-firmware/plat/common/plat_psci_common.c new file mode 100644 index 0000000..c32e59f --- /dev/null +++ b/arm-trusted-firmware/plat/common/plat_psci_common.c @@ -0,0 +1,167 @@ +/* + * 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 + */ + +#include + +#include +#include +#include +#include +#include + +#if ENABLE_PSCI_STAT && ENABLE_PMF +#pragma weak plat_psci_stat_accounting_start +#pragma weak plat_psci_stat_accounting_stop +#pragma weak plat_psci_stat_get_residency + +/* Maximum time-stamp value read from architectural counters */ +#ifdef __aarch64__ +#define MAX_TS UINT64_MAX +#else +#define MAX_TS UINT32_MAX +#endif + +/* Following are used as ID's to capture time-stamp */ +#define PSCI_STAT_ID_ENTER_LOW_PWR 0 +#define PSCI_STAT_ID_EXIT_LOW_PWR 1 +#define PSCI_STAT_TOTAL_IDS 2 + +PMF_DECLARE_CAPTURE_TIMESTAMP(psci_svc) +PMF_DECLARE_GET_TIMESTAMP(psci_svc) +PMF_REGISTER_SERVICE(psci_svc, PMF_PSCI_STAT_SVC_ID, PSCI_STAT_TOTAL_IDS, + PMF_STORE_ENABLE) + +/* + * This function calculates the stats residency in microseconds, + * taking in account the wrap around condition. + */ +static u_register_t calc_stat_residency(unsigned long long pwrupts, + unsigned long long pwrdnts) +{ + /* The divisor to use to convert raw timestamp into microseconds. */ + u_register_t residency_div; + u_register_t res; + + /* + * Calculate divisor so that it can be directly used to + * convert time-stamp into microseconds. + */ + residency_div = read_cntfrq_el0() / MHZ_TICKS_PER_SEC; + assert(residency_div > 0U); + + if (pwrupts < pwrdnts) + res = MAX_TS - pwrdnts + pwrupts; + else + res = pwrupts - pwrdnts; + + return res / residency_div; +} + +/* + * Capture timestamp before entering a low power state. + * Cache maintenance may be needed when reading these timestamps. + */ +void plat_psci_stat_accounting_start( + __unused const psci_power_state_t *state_info) +{ + assert(state_info != NULL); + PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR, + PMF_CACHE_MAINT); +} + +/* + * Capture timestamp after exiting a low power state. + * Cache maintenance may be needed when reading these timestamps. + */ +void plat_psci_stat_accounting_stop( + __unused const psci_power_state_t *state_info) +{ + assert(state_info != NULL); + PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR, + PMF_CACHE_MAINT); +} + +/* + * Calculate the residency for the given level and power state + * information. + */ +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 state; + unsigned long long pwrup_ts = 0, pwrdn_ts = 0; + unsigned int pmf_flags; + + assert((lvl >= PSCI_CPU_PWR_LVL) && (lvl <= PLAT_MAX_PWR_LVL)); + assert(state_info != NULL); + assert(last_cpu_idx <= PLATFORM_CORE_COUNT); + + if (lvl == PSCI_CPU_PWR_LVL) + assert(last_cpu_idx == plat_my_core_pos()); + + /* + * If power down is requested, then timestamp capture will + * be with caches OFF. Hence we have to do cache maintenance + * when reading the timestamp. + */ + state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL]; + if (is_local_state_off(state) != 0) { + pmf_flags = PMF_CACHE_MAINT; + } else { + assert(is_local_state_retn(state) == 1); + pmf_flags = PMF_NO_CACHE_MAINT; + } + + PMF_GET_TIMESTAMP_BY_INDEX(psci_svc, + PSCI_STAT_ID_ENTER_LOW_PWR, + last_cpu_idx, + pmf_flags, + pwrdn_ts); + + PMF_GET_TIMESTAMP_BY_INDEX(psci_svc, + PSCI_STAT_ID_EXIT_LOW_PWR, + plat_my_core_pos(), + pmf_flags, + pwrup_ts); + + return calc_stat_residency(pwrup_ts, pwrdn_ts); +} +#endif /* ENABLE_PSCI_STAT && ENABLE_PMF */ + +/* + * The PSCI generic code uses this API to let the platform participate in state + * coordination during a power management operation. It compares the platform + * specific local power states requested by each cpu for a given power domain + * and returns the coordinated target power state that the domain should + * enter. A platform assigns a number to a local power state. This default + * implementation assumes that the platform assigns these numbers in order of + * increasing depth of the power state i.e. for two power states X & Y, if X < Y + * then X represents a shallower power state than Y. As a result, the + * coordinated target local power state for a power domain will be the minimum + * of the requested local power states. + */ +plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, + const plat_local_state_t *states, + unsigned int ncpu) +{ + plat_local_state_t target = PLAT_MAX_OFF_STATE, temp; + const plat_local_state_t *st = states; + unsigned int n = ncpu; + + assert(ncpu > 0U); + + do { + temp = *st; + st++; + if (temp < target) + target = temp; + n--; + } while (n > 0U); + + return target; +} diff --git a/arm-trusted-firmware/plat/common/plat_spmd_manifest.c b/arm-trusted-firmware/plat/common/plat_spmd_manifest.c new file mode 100644 index 0000000..7f7d796 --- /dev/null +++ b/arm-trusted-firmware/plat/common/plat_spmd_manifest.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ATTRIBUTE_ROOT_NODE_STR "attribute" + +/******************************************************************************* + * SPMC attribute node parser + ******************************************************************************/ +static int manifest_parse_attribute(spmc_manifest_attribute_t *attr, + const void *fdt, + int node) +{ + uint32_t val32; + int rc; + + assert((attr != NULL) && (fdt != NULL)); + + rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version); + if (rc != 0) { + ERROR("Missing FFA %s version in SPM Core manifest.\n", + "major"); + return rc; + } + + rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version); + if (rc != 0) { + ERROR("Missing FFA %s version in SPM Core manifest.\n", + "minor"); + return rc; + } + + rc = fdt_read_uint32(fdt, node, "spmc_id", &val32); + if (rc != 0) { + ERROR("Missing SPMC ID in manifest.\n"); + return rc; + } + + attr->spmc_id = val32 & 0xffff; + + rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state); + if (rc != 0) { + NOTICE("%s not specified in SPM Core manifest.\n", + "Execution state"); + } + + rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size); + if (rc != 0) { + NOTICE("%s not specified in SPM Core manifest.\n", + "Binary size"); + } + + rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address); + if (rc != 0) { + NOTICE("%s not specified in SPM Core manifest.\n", + "Load address"); + } + + rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint); + if (rc != 0) { + NOTICE("%s not specified in SPM Core manifest.\n", + "Entry point"); + } + + VERBOSE("SPM Core manifest attribute section:\n"); + VERBOSE(" version: %u.%u\n", attr->major_version, attr->minor_version); + VERBOSE(" spmc_id: 0x%x\n", attr->spmc_id); + VERBOSE(" binary_size: 0x%x\n", attr->binary_size); + VERBOSE(" load_address: 0x%" PRIx64 "\n", attr->load_address); + VERBOSE(" entrypoint: 0x%" PRIx64 "\n", attr->entrypoint); + + return 0; +} + +/******************************************************************************* + * Root node handler + ******************************************************************************/ +static int manifest_parse_root(spmc_manifest_attribute_t *manifest, + const void *fdt, + int root) +{ + int node; + + assert(manifest != NULL); + + node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR, + sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1); + if (node < 0) { + ERROR("Root node doesn't contain subnode '%s'\n", + ATTRIBUTE_ROOT_NODE_STR); + return node; + } + + return manifest_parse_attribute(manifest, fdt, node); +} + +/******************************************************************************* + * Platform handler to parse a SPM Core manifest. + ******************************************************************************/ +int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest, + const void *pm_addr) +{ + int rc, unmap_ret; + uintptr_t pm_base, pm_base_align; + size_t mapped_size, manifest_size; + + assert(manifest != NULL); + assert(pm_addr != NULL); + + /* + * Assume TOS_FW_CONFIG is not necessarily aligned to a page + * boundary, thus calculate the remaining space between SPMC + * manifest start address and upper page limit. + * + */ + pm_base = (uintptr_t)pm_addr; + pm_base_align = page_align(pm_base, UP); + + if (pm_base == pm_base_align) { + /* Page aligned */ + mapped_size = PAGE_SIZE; + } else { + mapped_size = pm_base_align - pm_base; + } + + /* Check space within the page at least maps the FDT header */ + if (mapped_size < sizeof(struct fdt_header)) { + ERROR("Error while mapping SPM Core manifest.\n"); + return -EINVAL; + } + + /* Map first SPMC manifest page in the SPMD translation regime */ + pm_base_align = page_align(pm_base, DOWN); + rc = mmap_add_dynamic_region((unsigned long long)pm_base_align, + pm_base_align, + PAGE_SIZE, + MT_RO_DATA); + if (rc != 0) { + ERROR("Error while mapping SPM Core manifest (%d).\n", rc); + return rc; + } + + rc = fdt_check_header(pm_addr); + if (rc != 0) { + ERROR("Wrong format for SPM Core manifest (%d).\n", rc); + goto exit_unmap; + } + + manifest_size = fdt_totalsize(pm_addr); + + /* Map more memory for larger manifest */ + if (manifest_size > mapped_size) { + /* unmap the smaller sized manifest */ + rc = mmap_remove_dynamic_region(pm_base_align, mapped_size); + if (rc != 0) { + ERROR("Error while unmapping previous SPM Core manifest (%d).\n", + rc); + return rc; + } + + /* align size to multiple of PAGE_SIZE */ + mapped_size = page_align(manifest_size, UP); + + /* map the manifest with a larger size */ + rc = mmap_add_dynamic_region( + (unsigned long long)pm_base_align, + pm_base_align, + mapped_size, + MT_RO_DATA); + if (rc != 0) { + ERROR("Error while mapping larger SPM Core manifest (%d).\n", rc); + return rc; + } + } + + VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr); + + rc = fdt_node_offset_by_compatible(pm_addr, -1, + "arm,ffa-core-manifest-1.0"); + if (rc < 0) { + ERROR("Unrecognized SPM Core manifest\n"); + goto exit_unmap; + } + + rc = manifest_parse_root(manifest, pm_addr, rc); + +exit_unmap: + unmap_ret = mmap_remove_dynamic_region(pm_base_align, mapped_size); + if (unmap_ret != 0) { + ERROR("Error while unmapping SPM Core manifest (%d).\n", + unmap_ret); + if (rc == 0) { + rc = unmap_ret; + } + } + + return rc; +} diff --git a/arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c b/arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c new file mode 100644 index 0000000..12ab0a9 --- /dev/null +++ b/arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016-2017, 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 + +/* + * Store a new non-volatile counter value. This implementation + * only allows updating of the platform's Trusted NV counter when a + * certificate protected by the Trusted NV counter is signed with + * the ROT key. This avoids a compromised secondary certificate from + * updating the platform's Trusted NV counter, which could lead to the + * platform becoming unusable. The function is suitable for all TBBR + * compliant platforms. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc, + unsigned int nv_ctr) +{ + int trusted_nv_ctr; + + assert(cookie != NULL); + assert(img_desc != NULL); + + trusted_nv_ctr = strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0; + + /* + * Only update the Trusted NV Counter if the certificate + * has been signed with the ROT key. Non Trusted NV counter + * updates are unconditional. + */ + if (!trusted_nv_ctr || img_desc->parent == NULL) + return plat_set_nv_ctr(cookie, nv_ctr); + + /* + * Trusted certificates not signed with the ROT key are not + * allowed to update the Trusted NV Counter. + */ + return 1; +} diff --git a/arm-trusted-firmware/plat/common/ubsan.c b/arm-trusted-firmware/plat/common/ubsan.c new file mode 100644 index 0000000..45b0f7c --- /dev/null +++ b/arm-trusted-firmware/plat/common/ubsan.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +struct source_location { + const char *file_name; + uint32_t line; + uint32_t column; +}; + +struct type_descriptor { + uint16_t type_kind; + uint16_t type_info; + char type_name[1]; +}; + +struct type_mismatch_data { + struct source_location loc; + struct type_descriptor *type; + unsigned long alignment; + unsigned char type_check_kind; +}; + +struct overflow_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct shift_out_of_bounds_data { + struct source_location loc; + struct type_descriptor *lhs_type; + struct type_descriptor *rhs_type; +}; + +struct out_of_bounds_data { + struct source_location loc; + struct type_descriptor *array_type; + struct type_descriptor *index_type; +}; + +struct unreachable_data { + struct source_location loc; +}; + +struct vla_bound_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct invalid_value_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct nonnull_arg_data { + struct source_location loc; +}; + +/* + * When compiling with -fsanitize=undefined the compiler expects functions + * with the following signatures. The functions are never called directly, + * only when undefined behavior is detected in instrumented code. + */ +void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data, + unsigned long ptr); +void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data, + unsigned long ptr); +void __ubsan_handle_add_overflow_abort(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_sub_overflow_abort(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_mul_overflow_abort(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_negate_overflow_abort(struct overflow_data *data, + unsigned long old_val); +void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data, + unsigned long old_val); +void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data, + unsigned long idx); +void __ubsan_handle_unreachable_abort(struct unreachable_data *data); +void __ubsan_handle_missing_return_abort(struct unreachable_data *data); +void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data, + unsigned long bound); +void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data, + unsigned long val); +void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data +#if __GCC_VERSION < 60000 + , size_t arg_no +#endif + ); + +static void print_loc(const char *func, struct source_location *loc) +{ + ERROR("Undefined behavior at %s:%d col %d (%s)", + loc->file_name, loc->line, loc->column, func); +} + + +void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data, + unsigned long ptr __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data, + unsigned long ptr __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_add_overflow_abort(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_sub_overflow_abort(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_mul_overflow_abort(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_negate_overflow_abort(struct overflow_data *data, + unsigned long old_val __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data, + unsigned long old_val __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data, + unsigned long idx __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_unreachable_abort(struct unreachable_data *data) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_missing_return_abort(struct unreachable_data *data) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data, + unsigned long bound __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data, + unsigned long val __unused) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} + +void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data +#if __GCC_VERSION < 60000 + , size_t arg_no __unused +#endif + ) +{ + print_loc(__func__, &data->loc); + plat_panic_handler(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c b/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c new file mode 100644 index 0000000..702fc2d --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \ + DDR_SIZE - DDR_SEC_SIZE, \ + MT_DEVICE | MT_RW | MT_NS) + +#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \ + DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_ROM_PARAM MAP_REGION_FLAT(XG2RAM0_BASE, \ + BL1_XG2RAM0_OFFSET, \ + MT_DEVICE | MT_RO | MT_SECURE) + +#define MAP_SRAM MAP_REGION_FLAT(SRAM_BASE, \ + SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * BL1 needs to access the areas of MMC_SRAM. + * BL1 loads BL2 from eMMC into SRAM before DDR initialized. + */ +#define MAP_MMC_SRAM MAP_REGION_FLAT(HIKEY_BL1_MMC_DESC_BASE, \ + HIKEY_BL1_MMC_DESC_SIZE + \ + HIKEY_BL1_MMC_DATA_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Table of regions for different BL stages to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * hikey_init_mmu_elx() will give the available subset of that, + */ +#ifdef IMAGE_BL1 +static const mmap_region_t hikey_mmap[] = { + MAP_DEVICE, + MAP_ROM_PARAM, + MAP_MMC_SRAM, + {0} +}; +#endif + +#ifdef IMAGE_BL2 +static const mmap_region_t hikey_mmap[] = { + MAP_DDR, + MAP_DEVICE, + MAP_TSP_MEM, + MAP_SRAM, + {0} +}; +#endif + +#ifdef IMAGE_BL31 +static const mmap_region_t hikey_mmap[] = { + MAP_DEVICE, + MAP_SRAM, + MAP_TSP_MEM, + {0} +}; +#endif + +#ifdef IMAGE_BL32 +static const mmap_region_t hikey_mmap[] = { + MAP_DEVICE, + MAP_DDR, + {0} +}; +#endif + +/* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + */ +#define HIKEY_CONFIGURE_MMU_EL(_el) \ + void hikey_init_mmu_el##_el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(hikey_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(0); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +HIKEY_CONFIGURE_MMU_EL(1) +HIKEY_CONFIGURE_MMU_EL(3) + +unsigned long plat_get_ns_image_entrypoint(void) +{ + return HIKEY_NS_IMAGE_OFFSET; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return 1200000; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S b/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S new file mode 100644 index 0000000..82a404a --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_my_core_pos + .globl platform_mem_init + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_report_exception + .globl plat_reset_handler + +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * void platform_mem_init(void); + * + * We don't need to carry out any memory initialization + * on HIKEY. The Secure RAM is accessible straight away. + * ----------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, CRASH_CONSOLE_BASE + mov_imm x1, PL011_UART_CLK_IN_HZ + mov_imm x2, PL011_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, CRASH_CONSOLE_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On HIKEY platform, it updates the LEDs + * to indicate where we are + * --------------------------------------------- + */ +func plat_report_exception + mov x8, x30 + + /* Turn on LED according to x0 (0 -- f) */ + ldr x2, =0xf7020000 + and x1, x0, #1 + str w1, [x2, #4] + and x1, x0, #2 + str w1, [x2, #8] + and x1, x0, #4 + str w1, [x2, #16] + and x1, x0, #8 + str w1, [x2, #32] + + mrs x2, currentel + and x2, x2, #0xc0 + /* Check EL1 */ + cmp x2, #0x04 + beq plat_report_el1 + + adr x4, plat_err_str + bl asm_print_str + + adr x4, esr_el3_str + bl asm_print_str + + mrs x4, esr_el3 + bl asm_print_hex + + adr x4, elr_el3_str + bl asm_print_str + + mrs x4, elr_el3 + bl asm_print_hex + b plat_report_end + +plat_report_el1: + adr x4, plat_err_str + bl asm_print_str + + adr x4, esr_el1_str + bl asm_print_str + + mrs x4, esr_el1 + bl asm_print_hex + + adr x4, elr_el1_str + bl asm_print_str + + mrs x4, elr_el1 + bl asm_print_hex +plat_report_end: + mov x30, x8 + ret +endfunc plat_report_exception + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * ----------------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler + +.section .rodata.rev_err_str, "aS" +plat_err_str: + .asciz "\nPlatform exception reporting:" +esr_el3_str: + .asciz "\nESR_EL3: " +elr_el3_str: + .asciz "\nELR_EL3: " +esr_el1_str: + .asciz "\nESR_EL1: " +elr_el1_str: + .asciz "\nELR_EL1: " diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c new file mode 100644 index 0000000..31ff820 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2017-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 + +#include +#include +#include + +#include "hikey_private.h" + +/* Data structure which holds the extents of the trusted RAM for BL1 */ +static meminfo_t bl1_tzram_layout; +static console_t console; +static struct mmc_device_info mmc_info; + +enum { + BOOT_NORMAL = 0, + BOOT_USB_DOWNLOAD, + BOOT_UART_DOWNLOAD, +}; + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/* + * Perform any BL1 specific platform actions. + */ +void bl1_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL1_RW_BASE; + bl1_tzram_layout.total_size = BL1_RW_SIZE; + + INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, + BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */ +} + +/* + * Perform the very early platform specific architecture setup here. At the + * moment this only does basic initialization. Later architectural setup + * (bl1_arch_setup()) does not do anything platform specific. + */ +void bl1_plat_arch_setup(void) +{ + hikey_init_mmu_el3(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL1_RO_BASE, + BL1_RO_LIMIT, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +/* + * Function which will perform any remaining platform-specific setup that can + * occur after the MMU and data cache have been enabled. + */ +void bl1_platform_setup(void) +{ + dw_mmc_params_t params; + + assert((HIKEY_BL1_MMC_DESC_BASE >= SRAM_BASE) && + ((SRAM_BASE + SRAM_SIZE) >= + (HIKEY_BL1_MMC_DATA_BASE + HIKEY_BL1_MMC_DATA_SIZE))); + hikey_sp804_init(); + hikey_gpio_init(); + hikey_pmussi_init(); + hikey_hi6553_init(); + + hikey_rtc_init(); + + hikey_mmc_pll_init(); + + memset(¶ms, 0, sizeof(dw_mmc_params_t)); + params.reg_base = DWMMC0_BASE; + params.desc_base = HIKEY_BL1_MMC_DESC_BASE; + params.desc_size = 1 << 20; + params.clk_rate = 24 * 1000 * 1000; + params.bus_width = MMC_BUS_WIDTH_8; + params.flags = MMC_FLAG_CMD23; + mmc_info.mmc_dev_type = MMC_IS_EMMC; + dw_mmc_init(¶ms, &mmc_info); + + hikey_io_setup(); +} + +/* + * The following function checks if Firmware update is needed, + * by checking if TOC in FIP image is valid or not. + */ +unsigned int bl1_plat_get_next_image_id(void) +{ + int32_t boot_mode; + unsigned int ret; + + boot_mode = mmio_read_32(ONCHIPROM_PARAM_BASE); + switch (boot_mode) { + case BOOT_USB_DOWNLOAD: + case BOOT_UART_DOWNLOAD: + ret = NS_BL1U_IMAGE_ID; + break; + default: + WARN("Invalid boot mode is found:%d\n", boot_mode); + panic(); + } + return ret; +} + +image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) +{ + unsigned int index = 0; + + while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { + if (bl1_tbbr_image_descs[index].image_id == image_id) + return &bl1_tbbr_image_descs[index]; + + index++; + } + + return NULL; +} + +void bl1_plat_set_ep_info(unsigned int image_id, + entry_point_info_t *ep_info) +{ + uint64_t data = 0; + + if (image_id == BL2_IMAGE_ID) + panic(); + inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); + __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data)); + do { + data |= 3 << 20; + __asm__ volatile ("msr cpacr_el1, %0" : : "r"(data)); + __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data)); + } while ((data & (3 << 20)) != (3 << 20)); + INFO("cpacr_el1:0x%" PRIx64 "\n", data); + + ep_info->args.arg0 = 0xffff & read_mpidr(); + ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c new file mode 100644 index 0000000..4e013a0 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* also includes hikey_def.h and hikey_layout.h*/ + +#include +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .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.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + 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 /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = HIKEY_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = HIKEY_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = HIKEY_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = HIKEY_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = HIKEY_NS_IMAGE_OFFSET, + .image_info.image_max_size = 0x200000 /* 2MB */, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c new file mode 100644 index 0000000..a90f12c --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include /* also includes hikey_def.h and hikey_layout.h*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SPD_opteed +#include +#endif +#include + +#include +#include +#include +#include "hikey_private.h" + +#define BL2_RW_BASE (BL_CODE_END) + +static meminfo_t bl2_el3_tzram_layout; +static console_t console; +static struct mmc_device_info mmc_info; + +enum { + BOOT_MODE_RECOVERY = 0, + BOOT_MODE_NORMAL, + BOOT_MODE_MASK = 1, +}; + +/******************************************************************************* + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int plat_hikey_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + /* Enable MCU SRAM */ + hisi_mcu_enable_sram(); + + /* Load MCU binary into SRAM */ + hisi_mcu_load_image(scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + /* Let MCU running */ + hisi_mcu_start_run(); + + INFO("%s: MCU PC is at 0x%x\n", + __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2)); + INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n", + __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4)); + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t hikey_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL3-2 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifdef __aarch64__ +uint32_t hikey_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +uint32_t hikey_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* __aarch64__ */ + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + return hikey_set_fip_addr(image_id, "fastboot"); +} + +int hikey_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif + assert(bl_mem_params); + + switch (image_id) { +#ifdef __aarch64__ + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } +#endif + bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl32_entry(); + break; +#endif + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl33_entry(); + break; + +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = plat_hikey_bl2_handle_scp_bl2(&bl_mem_params->image_info); + if (err) { + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + } + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return hikey_bl2_handle_post_image_load(image_id); +} + +static void reset_dwmmc_clk(void) +{ + unsigned int data; + + /* disable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (data & PERI_CLK0_MMC0); + /* enable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & PERI_CLK0_MMC0)); + /* reset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); + + /* bypass mmc0 clock phase */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL2); + data |= 3; + mmio_write_32(PERI_SC_PERIPH_CTRL2, data); + + /* disable low power */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL13); + data |= 1 << 3; + mmio_write_32(PERI_SC_PERIPH_CTRL13, data); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (!(data & PERI_RST0_MMC0)); + + /* unreset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (data & PERI_RST0_MMC0); +} + +static void hikey_boardid_init(void) +{ + u_register_t midr; + + midr = read_midr(); + mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr); + INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR, + (unsigned int)midr); + + mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0); + mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b); + + mmio_write_32(ACPU_ARM64_FLAGA, 0x1234); + mmio_write_32(ACPU_ARM64_FLAGB, 0x5678); +} + +static void hikey_sd_init(void) +{ + /* switch pinmux to SD */ + mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0); + mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0); + + mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA); + mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA); + mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA); + + /* set SD Card detect as nopull */ + mmio_write_32(IOCG_GPIO8, 0); +} + +static void hikey_jumper_init(void) +{ + /* set jumper detect as nopull */ + mmio_write_32(IOCG_GPIO24, 0); + /* set jumper detect as GPIO */ + mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0); +} + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + /* Initialize the console to provide early debug support */ + console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + /* + * Allow BL2 to see the whole Trusted RAM. + */ + bl2_el3_tzram_layout.total_base = BL2_RW_BASE; + bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE; +} + +void bl2_el3_plat_arch_setup(void) +{ + hikey_init_mmu_el3(bl2_el3_tzram_layout.total_base, + bl2_el3_tzram_layout.total_size, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void bl2_platform_setup(void) +{ + dw_mmc_params_t params; + + hikey_sp804_init(); + hikey_gpio_init(); + hikey_pmussi_init(); + hikey_hi6553_init(); + /* Clear SRAM since it'll be used by MCU right now. */ + memset((void *)SRAM_BASE, 0, SRAM_SIZE); + + dsb(); + hikey_ddr_init(DDR_FREQ_800M); + hikey_security_setup(); + + hikey_boardid_init(); + init_acpu_dvfs(); + hikey_rtc_init(); + hikey_sd_init(); + hikey_jumper_init(); + + hikey_mmc_pll_init(); + + /* Clean SRAM before MCU used */ + clean_dcache_range(SRAM_BASE, SRAM_SIZE); + + reset_dwmmc_clk(); + memset(¶ms, 0, sizeof(dw_mmc_params_t)); + params.reg_base = DWMMC0_BASE; + params.desc_base = HIKEY_MMC_DESC_BASE; + params.desc_size = 1 << 20; + params.clk_rate = 24 * 1000 * 1000; + params.bus_width = MMC_BUS_WIDTH_8; + params.flags = MMC_FLAG_CMD23; + mmc_info.mmc_dev_type = MMC_IS_EMMC; + dw_mmc_init(¶ms, &mmc_info); + + hikey_io_setup(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c new file mode 100644 index 0000000..7d008e7 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2017-2018, 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 +#include + +#include "hikey_private.h" + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; +static console_t console; + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +/* + * Ideally `arm_gic_data` structure definition should be a `const` but it is + * kept as modifiable for overwriting with different GICD and GICC base when + * running on FVP with VE memory map. + */ +gicv2_driver_data_t hikey_gic_data = { + .gicd_base = PLAT_ARM_GICD_BASE, + .gicc_base = PLAT_ARM_GICC_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +static const int cci_map[] = { + CCI400_SL_IFACE3_CLUSTER_IX, + CCI400_SL_IFACE4_CLUSTER_IX +}; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + return NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + void *from_bl2; + + from_bl2 = (void *) arg0; + + /* Initialize the console to provide early debug support */ + console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Initialize CCI driver */ + cci_init(CCI400_BASE, cci_map, ARRAY_SIZE(cci_map)); + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (bl33_ep_info.pc == 0) + panic(); +} + +void bl31_plat_arch_setup(void) +{ + hikey_init_mmu_el3(BL31_BASE, + BL31_LIMIT - BL31_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +/* Initialize EDMAC controller with non-secure mode. */ +static void hikey_edma_init(void) +{ + int i; + uint32_t non_secure; + + non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC; + mmio_write_32(EDMAC_SEC_CTRL, non_secure); + + for (i = 0; i < EDMAC_CHANNEL_NUMS; i++) { + mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18)); + } +} + +void bl31_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + gicv2_driver_init(&hikey_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + hikey_edma_init(); + + hisi_ipc_init(); + hisi_pwrc_setup(); +} + +void bl31_plat_runtime_setup(void) +{ +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c new file mode 100644 index 0000000..d062de4 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include "hikey_private.h" + +void hikey_sp804_init(void) +{ + uint32_t data; + + /* select the clock of dual timer0 */ + data = mmio_read_32(AO_SC_TIMER_EN0); + while (data & 3) { + data &= ~3; + data |= 3 << 16; + mmio_write_32(AO_SC_TIMER_EN0, data); + data = mmio_read_32(AO_SC_TIMER_EN0); + } + /* enable the pclk of dual timer0 */ + data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); + while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) { + mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0); + data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4); + } + /* reset dual timer0 */ + data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); + mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0); + do { + data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); + } while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)); + /* unreset dual timer0 */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0); + do { + data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); + } while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0)); + + sp804_timer_init(SP804_TIMER0_BASE, 10, 192); +} + +void hikey_gpio_init(void) +{ + pl061_gpio_init(); + pl061_gpio_register(GPIO0_BASE, 0); + pl061_gpio_register(GPIO1_BASE, 1); + pl061_gpio_register(GPIO2_BASE, 2); + pl061_gpio_register(GPIO3_BASE, 3); + pl061_gpio_register(GPIO4_BASE, 4); + pl061_gpio_register(GPIO5_BASE, 5); + pl061_gpio_register(GPIO6_BASE, 6); + pl061_gpio_register(GPIO7_BASE, 7); + pl061_gpio_register(GPIO8_BASE, 8); + pl061_gpio_register(GPIO9_BASE, 9); + pl061_gpio_register(GPIO10_BASE, 10); + pl061_gpio_register(GPIO11_BASE, 11); + pl061_gpio_register(GPIO12_BASE, 12); + pl061_gpio_register(GPIO13_BASE, 13); + pl061_gpio_register(GPIO14_BASE, 14); + pl061_gpio_register(GPIO15_BASE, 15); + pl061_gpio_register(GPIO16_BASE, 16); + pl061_gpio_register(GPIO17_BASE, 17); + pl061_gpio_register(GPIO18_BASE, 18); + pl061_gpio_register(GPIO19_BASE, 19); + + /* Power on indicator LED (USER_LED1). */ + gpio_set_direction(32, GPIO_DIR_OUT); /* LED1 */ + gpio_set_value(32, GPIO_LEVEL_HIGH); + gpio_set_direction(33, GPIO_DIR_OUT); /* LED2 */ + gpio_set_value(33, GPIO_LEVEL_LOW); + gpio_set_direction(34, GPIO_DIR_OUT); /* LED3 */ + gpio_set_direction(35, GPIO_DIR_OUT); /* LED4 */ +} + +void hikey_pmussi_init(void) +{ + uint32_t data; + + /* Initialize PWR_HOLD GPIO */ + gpio_set_direction(0, GPIO_DIR_OUT); + gpio_set_value(0, GPIO_LEVEL_LOW); + + /* + * After reset, PMUSSI stays in reset mode. + * Now make it out of reset. + */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, + AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N); + do { + data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4); + } while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N); + + /* Set PMUSSI clock latency for read operation. */ + data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3); + data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK; + data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3; + mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data); + + /* enable PMUSSI clock */ + data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU | + AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU; + mmio_write_32(AO_SC_PERIPH_CLKEN5, data); + data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI; + mmio_write_32(AO_SC_PERIPH_CLKEN4, data); + + gpio_set_value(0, GPIO_LEVEL_HIGH); +} + +void hikey_hi6553_init(void) +{ + uint8_t data; + + mmio_write_8(HI6553_PERI_EN_MARK, 0x1e); + mmio_write_8(HI6553_NP_REG_ADJ1, 0); + data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC | + DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2; + mmio_write_8(HI6553_DISABLE6_XO_CLK, data); + + /* configure BUCK0 & BUCK1 */ + mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e); + mmio_write_8(HI6553_BUCK0_CTRL7, 0x10); + mmio_write_8(HI6553_BUCK1_CTRL7, 0x10); + mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e); + mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e); + mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc); + mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc); + + /* configure BUCK2 */ + mmio_write_8(HI6553_BUCK2_REG1, 0x4f); + mmio_write_8(HI6553_BUCK2_REG5, 0x99); + mmio_write_8(HI6553_BUCK2_REG6, 0x45); + mdelay(1); + mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22); + mdelay(1); + + /* configure BUCK3 */ + mmio_write_8(HI6553_BUCK3_REG3, 0x02); + mmio_write_8(HI6553_BUCK3_REG5, 0x99); + mmio_write_8(HI6553_BUCK3_REG6, 0x41); + mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02); + mdelay(1); + + /* configure BUCK4 */ + mmio_write_8(HI6553_BUCK4_REG2, 0x9a); + mmio_write_8(HI6553_BUCK4_REG5, 0x99); + mmio_write_8(HI6553_BUCK4_REG6, 0x45); + + /* configure LDO20 */ + mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50); + + mmio_write_8(HI6553_NP_REG_CHG, 0x0f); + mmio_write_8(HI6553_CLK_TOP0, 0x06); + mmio_write_8(HI6553_CLK_TOP3, 0xc0); + mmio_write_8(HI6553_CLK_TOP4, 0x00); + + /* configure LDO7 & LDO10 for SD slot */ + /* enable LDO7 */ + data = mmio_read_8(HI6553_LDO7_REG_ADJ); + data = (data & 0xf8) | 0x2; + mmio_write_8(HI6553_LDO7_REG_ADJ, data); + mdelay(5); + mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6); + mdelay(5); + /* enable LDO10 */ + data = mmio_read_8(HI6553_LDO10_REG_ADJ); + data = (data & 0xf8) | 0x5; + mmio_write_8(HI6553_LDO10_REG_ADJ, data); + mdelay(5); + mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1); + mdelay(5); + /* enable LDO15 */ + data = mmio_read_8(HI6553_LDO15_REG_ADJ); + data = (data & 0xf8) | 0x4; + mmio_write_8(HI6553_LDO15_REG_ADJ, data); + mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6); + mdelay(5); + /* enable LDO19 */ + data = mmio_read_8(HI6553_LDO19_REG_ADJ); + data |= 0x7; + mmio_write_8(HI6553_LDO19_REG_ADJ, data); + mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2); + mdelay(5); + /* enable LDO21 */ + data = mmio_read_8(HI6553_LDO21_REG_ADJ); + data = (data & 0xf8) | 0x3; + mmio_write_8(HI6553_LDO21_REG_ADJ, data); + mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4); + mdelay(5); + /* enable LDO22 */ + data = mmio_read_8(HI6553_LDO22_REG_ADJ); + data = (data & 0xf8) | 0x7; + mmio_write_8(HI6553_LDO22_REG_ADJ, data); + mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5); + mdelay(5); + + /* select 32.764KHz */ + mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01); + + /* Disable vbus_det interrupts */ + data = mmio_read_8(HI6553_IRQ2_MASK); + data = data | 0x3; + mmio_write_8(HI6553_IRQ2_MASK, data); +} + +void init_mmc0_pll(void) +{ + unsigned int data; + + /* select SYSPLL as the source of MMC0 */ + /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ + mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21); + do { + data = mmio_read_32(PERI_SC_CLK_SEL0); + } while (!(data & (1 << 5))); + /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ + mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29); + do { + data = mmio_read_32(PERI_SC_CLK_SEL0); + } while (data & (1 << 13)); + + mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0)); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & (1 << 0))); + + data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); + data |= 1 << 1; + mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); + + do { + mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb); + data = mmio_read_32(PERI_SC_CLKCFG8BIT1); + } while ((data & 0xb) != 0xb); +} + +void reset_mmc0_clk(void) +{ + unsigned int data; + + /* disable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (data & PERI_CLK0_MMC0); + /* enable mmc0 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & PERI_CLK0_MMC0)); + /* reset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0); + + /* bypass mmc0 clock phase */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL2); + data |= 3; + mmio_write_32(PERI_SC_PERIPH_CTRL2, data); + + /* disable low power */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL13); + data |= 1 << 3; + mmio_write_32(PERI_SC_PERIPH_CTRL13, data); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (!(data & PERI_RST0_MMC0)); + + /* unreset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (data & PERI_RST0_MMC0); +} + +void init_media_clk(void) +{ + unsigned int data, value; + + data = mmio_read_32(PMCTRL_MEDPLLCTRL); + data |= 1; + mmio_write_32(PMCTRL_MEDPLLCTRL, data); + + for (;;) { + data = mmio_read_32(PMCTRL_MEDPLLCTRL); + value = 1 << 28; + if ((data & value) == value) + break; + } + + data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); + data = 1 << 10; + mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); +} + +void init_mmc1_pll(void) +{ + uint32_t data; + + /* select SYSPLL as the source of MMC1 */ + /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ + mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27); + do { + data = mmio_read_32(PERI_SC_CLK_SEL0); + } while (!(data & (1 << 11))); + /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ + mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30); + do { + data = mmio_read_32(PERI_SC_CLK_SEL0); + } while (data & (1 << 14)); + + mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1)); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & (1 << 1))); + + data = mmio_read_32(PERI_SC_PERIPH_CLKEN12); + data |= 1 << 2; + mmio_write_32(PERI_SC_PERIPH_CLKEN12, data); + + do { + /* 1.2GHz / 50 = 24MHz */ + mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7)); + data = mmio_read_32(PERI_SC_CLKCFG8BIT2); + } while ((data & 0x31) != 0x31); +} + +void reset_mmc1_clk(void) +{ + unsigned int data; + + /* disable mmc1 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (data & PERI_CLK0_MMC1); + /* enable mmc1 bus clock */ + mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1); + do { + data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0); + } while (!(data & PERI_CLK0_MMC1)); + /* reset mmc1 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1); + + /* bypass mmc1 clock phase */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL2); + data |= 3 << 2; + mmio_write_32(PERI_SC_PERIPH_CTRL2, data); + + /* disable low power */ + data = mmio_read_32(PERI_SC_PERIPH_CTRL13); + data |= 1 << 4; + mmio_write_32(PERI_SC_PERIPH_CTRL13, data); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (!(data & PERI_RST0_MMC1)); + + /* unreset mmc0 clock domain */ + mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1); + do { + data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0); + } while (data & PERI_RST0_MMC1); +} + +/* Initialize PLL of both eMMC and SD controllers. */ +void hikey_mmc_pll_init(void) +{ + init_mmc0_pll(); + reset_mmc0_clk(); + init_media_clk(); + + dsb(); + + init_mmc1_pll(); + reset_mmc1_clk(); +} + +void hikey_rtc_init(void) +{ + uint32_t data; + + data = mmio_read_32(AO_SC_PERIPH_CLKEN4); + data |= AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N; + mmio_write_32(AO_SC_PERIPH_CLKEN4, data); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c new file mode 100644 index 0000000..cd9e9a2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c @@ -0,0 +1,1451 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include "hikey_private.h" + +static void init_pll(void) +{ + unsigned int data; + + data = mmio_read_32((0xf7032000 + 0x000)); + data |= 0x1; + mmio_write_32((0xf7032000 + 0x000), data); + do { + data = mmio_read_32((0xf7032000 + 0x000)); + } while (!(data & (1 << 28))); + + data = mmio_read_32((0xf7800000 + 0x000)); + data &= ~0x007; + data |= 0x004; + mmio_write_32((0xf7800000 + 0x000), data); + do { + data = mmio_read_32((0xf7800000 + 0x014)); + data &= 0x007; + } while (data != 0x004); + + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2001); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2201); + dsb(); + isb(); + udelay(10); + mmio_write_32(0xf7032000 + 0x02c, 0x5110103e); + dsb(); + isb(); + udelay(10); + data = mmio_read_32(0xf7032000 + 0x050); + data |= 1 << 28; + mmio_write_32(0xf7032000 + 0x050, data); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2001); + dsb(); + isb(); + udelay(10); + mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2201); + dsb(); + isb(); + udelay(10); +} + +static void init_freq(void) +{ + unsigned int data, tmp; + unsigned int cpuext_cfg, ddr_cfg; + + mmio_write_32((0xf7032000 + 0x374), 0x4a); + mmio_write_32((0xf7032000 + 0x368), 0xda); + mmio_write_32((0xf7032000 + 0x36c), 0x01); + mmio_write_32((0xf7032000 + 0x370), 0x01); + mmio_write_32((0xf7032000 + 0x360), 0x60); + mmio_write_32((0xf7032000 + 0x364), 0x60); + + mmio_write_32((0xf7032000 + 0x114), 0x1000); + + data = mmio_read_32((0xf7032000 + 0x110)); + data |= (3 << 12); + mmio_write_32((0xf7032000 + 0x110), data); + + data = mmio_read_32((0xf7032000 + 0x110)); + data |= (1 << 4); + mmio_write_32((0xf7032000 + 0x110), data); + + + data = mmio_read_32((0xf7032000 + 0x110)); + data &= ~0x7; + data |= 0x5; + mmio_write_32((0xf7032000 + 0x110), data); + dsb(); + mdelay(10); + + + do { + data = mmio_read_32((0xf6504000 + 0x008)); + data &= (3 << 20); + } while (data != (3 << 20)); + dsb(); + mdelay(10); + + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~((1 << 0) | (1 << 11)); + mmio_write_32((0xf6504000 + 0x054), data); + mdelay(10); + + data = mmio_read_32((0xf7032000 + 0x104)); + data &= ~(3 << 8); + data |= (1 << 8); + mmio_write_32((0xf7032000 + 0x104), data); + + data = mmio_read_32((0xf7032000 + 0x100)); + data |= (1 << 0); + mmio_write_32((0xf7032000 + 0x100), data); + dsb(); + + do { + data = mmio_read_32((0xf7032000 + 0x100)); + data &= (1 << 2); + } while (data != (1 << 2)); + + data = mmio_read_32((0xf6504000 + 0x06c)); + data &= ~0xffff; + data |= 0x56; + mmio_write_32((0xf6504000 + 0x06c), data); + + data = mmio_read_32((0xf6504000 + 0x06c)); + data &= ~(0xffffffu << 8); + data |= 0xc7a << 8; + mmio_write_32((0xf6504000 + 0x06c), data); + + data = mmio_read_32((0xf6504000 + 0x058)); + data &= ((1 << 13) - 1); + data |= 0xccb; + mmio_write_32((0xf6504000 + 0x058), data); + + mmio_write_32((0xf6504000 + 0x060), 0x1fff); + mmio_write_32((0xf6504000 + 0x064), 0x1ffffff); + mmio_write_32((0xf6504000 + 0x068), 0x7fffffff); + mmio_write_32((0xf6504000 + 0x05c), 0x1); + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~(0xf << 12); + data |= 1 << 12; + mmio_write_32((0xf6504000 + 0x054), data); + dsb(); + + + data = mmio_read_32((0xf7032000 + 0x000)); + data &= ~(1 << 0); + mmio_write_32((0xf7032000 + 0x000), data); + + mmio_write_32((0xf7032000 + 0x004), 0x5110207d); + mmio_write_32((0xf7032000 + 0x134), 0x10000005); + data = mmio_read_32((0xf7032000 + 0x134)); + + + data = mmio_read_32((0xf7032000 + 0x000)); + data |= (1 << 0); + mmio_write_32((0xf7032000 + 0x000), data); + + mmio_write_32((0xf7032000 + 0x368), 0x100da); + data = mmio_read_32((0xf7032000 + 0x378)); + data &= ~((1 << 7) - 1); + data |= 0x6b; + mmio_write_32((0xf7032000 + 0x378), data); + dsb(); + do { + data = mmio_read_32((0xf7032000 + 0x378)); + tmp = data & 0x7f; + data = (data & (0x7f << 8)) >> 8; + if (data != tmp) + continue; + data = mmio_read_32((0xf7032000 + 0x37c)); + } while (!(data & 1)); + + data = mmio_read_32((0xf7032000 + 0x104)); + data &= ~((3 << 0) | + (3 << 8)); + cpuext_cfg = 1; + ddr_cfg = 1; + data |= cpuext_cfg | (ddr_cfg << 8); + mmio_write_32((0xf7032000 + 0x104), data); + dsb(); + + do { + data = mmio_read_32((0xf7032000 + 0x104)); + tmp = (data & (3 << 16)) >> 16; + if (cpuext_cfg != tmp) + continue; + tmp = (data & (3 << 24)) >> 24; + if (ddr_cfg != tmp) + continue; + data = mmio_read_32((0xf7032000 + 0x000)); + data &= 1 << 28; + } while (!data); + + data = mmio_read_32((0xf7032000 + 0x100)); + data &= ~(1 << 0); + mmio_write_32((0xf7032000 + 0x100), data); + dsb(); + do { + data = mmio_read_32((0xf7032000 + 0x100)); + data &= (1 << 1); + } while (data != (1 << 1)); + mdelay(1000); + + data = mmio_read_32((0xf6504000 + 0x054)); + data &= ~(1 << 28); + mmio_write_32((0xf6504000 + 0x054), data); + dsb(); + + data = mmio_read_32((0xf7032000 + 0x110)); + data &= ~((1 << 4) | + (3 << 12)); + mmio_write_32((0xf7032000 + 0x110), data); +} + +int cat_533mhz_800mhz(void) +{ + unsigned int data, i; + unsigned int bdl[5]; + + + data = mmio_read_32((0xf712c000 + 0x1c8)); + data &= 0xfffff0f0; + data |= 0x100f01; + mmio_write_32((0xf712c000 + 0x1c8), data); + + for (i = 0; i < 0x20; i++) { + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + data = (i << 0x10) + i; + mmio_write_32((0xf712c000 + 0x140), data); + mmio_write_32((0xf712c000 + 0x144), data); + mmio_write_32((0xf712c000 + 0x148), data); + mmio_write_32((0xf712c000 + 0x14c), data); + mmio_write_32((0xf712c000 + 0x150), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x801); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if ((data & 0x400) == 0) { + mdelay(10); + return 0; + } + WARN("lpddr3 cat fail\n"); + data = mmio_read_32((0xf712c000 + 0x1d4)); + if ((data & 0x1f00) && ((data & 0x1f) == 0)) { + bdl[0] = mmio_read_32((0xf712c000 + 0x140)); + bdl[1] = mmio_read_32((0xf712c000 + 0x144)); + bdl[2] = mmio_read_32((0xf712c000 + 0x148)); + bdl[3] = mmio_read_32((0xf712c000 + 0x14c)); + bdl[4] = mmio_read_32((0xf712c000 + 0x150)); + if ((!(bdl[0] & 0x1f001f)) || (!(bdl[1] & 0x1f001f)) || + (!(bdl[2] & 0x1f001f)) || (!(bdl[3] & 0x1f001f)) || + (!(bdl[4] & 0x1f001f))) { + WARN("lpddr3 cat deskew error\n"); + if (i == 0x1f) { + WARN("addrnbdl is max\n"); + return -EINVAL; + } + mmio_write_32((0xf712c000 + 0x008), 0x400); + } else { + WARN("lpddr3 cat other error1\n"); + return -EINVAL; + } + } else { + WARN("lpddr3 cat other error2\n"); + return -EINVAL; + } + } + return -EINVAL; +} + +static void ddrx_rdet(void) +{ + unsigned int data, rdet, bdl[4]; + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= 0xf800ffff; + data |= 0x8f0000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + data = mmio_read_32((0xf712c000 + 0x0dc)); + data &= 0xfffffff0; + data |= 0xf; + mmio_write_32((0xf712c000 + 0x0dc), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x80000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (!(data & 1)); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x100) + WARN("rdet lbs fail\n"); + + bdl[0] = mmio_read_32((0xf712c000 + 0x22c)) & 0x7f; + bdl[1] = mmio_read_32((0xf712c000 + 0x2ac)) & 0x7f; + bdl[2] = mmio_read_32((0xf712c000 + 0x32c)) & 0x7f; + bdl[3] = mmio_read_32((0xf712c000 + 0x3ac)) & 0x7f; + do { + data = mmio_read_32((0xf712c000 + 0x22c)); + data &= ~0x7f; + data |= bdl[0]; + mmio_write_32((0xf712c000 + 0x22c), data); + data = mmio_read_32((0xf712c000 + 0x2ac)); + data &= ~0x7f; + data |= bdl[1]; + mmio_write_32((0xf712c000 + 0x2ac), data); + data = mmio_read_32((0xf712c000 + 0x32c)); + data &= ~0x7f; + data |= bdl[2]; + mmio_write_32((0xf712c000 + 0x32c), data); + data = mmio_read_32((0xf712c000 + 0x3ac)); + data &= ~0x7f; + data |= bdl[3]; + mmio_write_32((0xf712c000 + 0x3ac), data); + + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xfff7ffff; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + rdet = data & 0x100; + if (rdet) { + INFO("rdet ds fail\n"); + mmio_write_32((0xf712c000 + 0x008), 0x100); + } + bdl[0]++; + bdl[1]++; + bdl[2]++; + bdl[3]++; + } while (rdet); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf0000000; + data |= 0x30000000; + mmio_write_32((0xf712c000 + 0x0d0), data); + + mmio_write_32((0xf712c000 + 0x004), 0x101); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x100) + INFO("rdet rbs av fail\n"); +} + +static void ddrx_wdet(void) +{ + unsigned int data, wdet, zero_bdl = 0, dq[4]; + int i; + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf; + data |= 0xf; + mmio_write_32((0xf712c000 + 0x0d0), data); + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= ~0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x8000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x200) + INFO("wdet lbs fail\n"); + + dq[0] = mmio_read_32((0xf712c000 + 0x234)) & 0x1f00; + dq[1] = mmio_read_32((0xf712c000 + 0x2b4)) & 0x1f00; + dq[2] = mmio_read_32((0xf712c000 + 0x334)) & 0x1f00; + dq[3] = mmio_read_32((0xf712c000 + 0x3b4)) & 0x1f00; + + do { + mmio_write_32((0xf712c000 + 0x234), dq[0]); + mmio_write_32((0xf712c000 + 0x2b4), dq[1]); + mmio_write_32((0xf712c000 + 0x334), dq[2]); + mmio_write_32((0xf712c000 + 0x3b4), dq[3]); + + data = mmio_read_32((0xf712c000 + 0x070)); + data |= 0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= ~0x80000; + mmio_write_32((0xf712c000 + 0x070), data); + mmio_write_32((0xf712c000 + 0x004), 0x8000); + mmio_write_32((0xf712c000 + 0x004), 0); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x4000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + wdet = data & 0x200; + if (wdet) { + INFO("wdet ds fail\n"); + mmio_write_32((0xf712c000 + 0x008), 0x200); + } + mdelay(10); + + for (i = 0; i < 4; i++) { + data = mmio_read_32((0xf712c000 + 0x210 + i * 0x80)); + if ((!(data & 0x1f)) || (!(data & 0x1f00)) || + (!(data & 0x1f0000)) || (!(data & 0x1f000000))) + zero_bdl = 1; + data = mmio_read_32((0xf712c000 + 0x214 + i * 0x80)); + if ((!(data & 0x1f)) || (!(data & 0x1f00)) || + (!(data & 0x1f0000)) || (!(data & 0x1f000000))) + zero_bdl = 1; + data = mmio_read_32((0xf712c000 + 0x218 + i * 0x80)); + if (!(data & 0x1f)) + zero_bdl = 1; + if (zero_bdl) { + if (i == 0) + dq[0] = dq[0] - 0x100; + if (i == 1) + dq[1] = dq[1] - 0x100; + if (i == 2) + dq[2] = dq[2] - 0x100; + if (i == 3) + dq[3] = dq[3] - 0x100; + } + } + } while (wdet); + + data = mmio_read_32((0xf712c000 + 0x0d0)); + data &= ~0xf000; + data |= 0x3000; + mmio_write_32((0xf712c000 + 0x0d0), data); + mmio_write_32((0xf712c000 + 0x004), 0x201); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x200) + INFO("wdet rbs av fail\n"); +} + +void set_ddrc_150mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x1); + mmio_write_32((0xf7032000 + 0x5a8), 0x7); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x31); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f); + mmio_write_32((0xf712c000 + 0x00c), 0xf0f); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x7200000); + mmio_write_32((0xf712c000 + 0x258), 0x720); + mmio_write_32((0xf712c000 + 0x2d8), 0x720); + mmio_write_32((0xf712c000 + 0x358), 0x720); + mmio_write_32((0xf712c000 + 0x3d8), 0x720); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x30c82355); + mmio_write_32((0xf712c000 + 0x034), 0x62112bb); + mmio_write_32((0xf712c000 + 0x038), 0x20041022); + mmio_write_32((0xf712c000 + 0x03c), 0x63177497); + mmio_write_32((0xf712c000 + 0x040), 0x3008407); + mmio_write_32((0xf712c000 + 0x064), 0x10483); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x184; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data &= 0xbfffffff; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0x90420880); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x146d); + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0xb3290d08); + mmio_write_32((0xf7128000 + 0x104), 0x9621821); + mmio_write_32((0xf7128000 + 0x108), 0x45009023); + mmio_write_32((0xf7128000 + 0x10c), 0xaf44c145); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x11080806); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 8) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x8) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 150mhz\n"); +} + +void set_ddrc_266mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x3); + mmio_write_32((0xf7032000 + 0x5a8), 0x1003); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x31); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f); + mmio_write_32((0xf712c000 + 0x00c), 0xf0f); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x7200000); + mmio_write_32((0xf712c000 + 0x258), 0x720); + mmio_write_32((0xf712c000 + 0x2d8), 0x720); + mmio_write_32((0xf712c000 + 0x358), 0x720); + mmio_write_32((0xf712c000 + 0x3d8), 0x720); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x510d4455); + mmio_write_32((0xf712c000 + 0x034), 0x8391ebb); + mmio_write_32((0xf712c000 + 0x038), 0x2005103c); + mmio_write_32((0xf712c000 + 0x03c), 0x6329950b); + mmio_write_32((0xf712c000 + 0x040), 0x300858c); + mmio_write_32((0xf712c000 + 0x064), 0x10483); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x184; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data &= 0xbfffffff; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0x90420880); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x146d); + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0xb441d50d); + mmio_write_32((0xf7128000 + 0x104), 0xf721839); + mmio_write_32((0xf7128000 + 0x108), 0x5500f03f); + mmio_write_32((0xf7128000 + 0x10c), 0xaf486145); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x12080d06); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 8) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x8) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 266mhz\n"); +} + +void set_ddrc_400mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x2); + mmio_write_32((0xf7032000 + 0x5a8), 0x1003); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x31); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f); + mmio_write_32((0xf712c000 + 0x00c), 0xf0f); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x7200000); + mmio_write_32((0xf712c000 + 0x258), 0x720); + mmio_write_32((0xf712c000 + 0x2d8), 0x720); + mmio_write_32((0xf712c000 + 0x358), 0x720); + mmio_write_32((0xf712c000 + 0x3d8), 0x720); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x75525655); + mmio_write_32((0xf712c000 + 0x034), 0xa552abb); + mmio_write_32((0xf712c000 + 0x038), 0x20071059); + mmio_write_32((0xf712c000 + 0x03c), 0x633e8591); + mmio_write_32((0xf712c000 + 0x040), 0x3008691); + mmio_write_32((0xf712c000 + 0x064), 0x10483); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x184; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data &= 0xbfffffff; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0x90420880); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x146d); + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0xb55a9d12); + mmio_write_32((0xf7128000 + 0x104), 0x17721855); + mmio_write_32((0xf7128000 + 0x108), 0x7501505f); + mmio_write_32((0xf7128000 + 0x10c), 0xaf4ca245); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x13081306); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 8) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x8) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 400mhz\n"); +} + +void set_ddrc_533mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x3); + mmio_write_32((0xf7032000 + 0x5a8), 0x11111); + data = mmio_read_32((0xf7032000 + 0x104)); + data |= 0x100; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x30); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x6400000); + mmio_write_32((0xf712c000 + 0x258), 0x640); + mmio_write_32((0xf712c000 + 0x2d8), 0x640); + mmio_write_32((0xf712c000 + 0x358), 0x640); + mmio_write_32((0xf712c000 + 0x3d8), 0x640); + mmio_write_32((0xf712c000 + 0x018), 0x0); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0x9dd87855); + mmio_write_32((0xf712c000 + 0x034), 0xa7138bb); + mmio_write_32((0xf712c000 + 0x038), 0x20091477); + mmio_write_32((0xf712c000 + 0x03c), 0x84534e16); + mmio_write_32((0xf712c000 + 0x040), 0x3008817); + mmio_write_32((0xf712c000 + 0x064), 0x106c3); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x305; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= ~0x10; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= ~0x2000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0xd0420900); + + mmio_write_32((0xf7128000 + 0x040), 0x0); + mmio_write_32((0xf712c000 + 0x004), 0x140f); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + NOTICE("failed to init lpddr3 rank0 dram phy\n"); + return; + } + cat_533mhz_800mhz(); + + mmio_write_32((0xf712c000 + 0x004), 0xf1); + mmio_write_32((0xf7128000 + 0x050), 0x100123); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0xb77b6718); + mmio_write_32((0xf7128000 + 0x104), 0x1e82a071); + mmio_write_32((0xf7128000 + 0x108), 0x9501c07e); + mmio_write_32((0xf7128000 + 0x10c), 0xaf50c255); + mmio_write_32((0xf7128000 + 0x110), 0x10b00000); + mmio_write_32((0xf7128000 + 0x114), 0x13181908); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + ddrx_rdet(); + ddrx_wdet(); + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 533mhz\n"); +} + +void set_ddrc_800mhz(void) +{ + unsigned int data; + + mmio_write_32((0xf7032000 + 0x580), 0x2); + mmio_write_32((0xf7032000 + 0x5a8), 0x1003); + data = mmio_read_32((0xf7032000 + 0x104)); + data &= 0xfffffcff; + mmio_write_32((0xf7032000 + 0x104), data); + + mmio_write_32((0xf7030000 + 0x050), 0x30); + mmio_write_32((0xf7030000 + 0x240), 0x5ffff); + mmio_write_32((0xf7030000 + 0x344), 0xf5ff); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x00c), 0x400); + mmio_write_32((0xf712c000 + 0x018), 0x7); + mmio_write_32((0xf712c000 + 0x090), 0x5400000); + mmio_write_32((0xf712c000 + 0x258), 0x540); + mmio_write_32((0xf712c000 + 0x2d8), 0x540); + mmio_write_32((0xf712c000 + 0x358), 0x540); + mmio_write_32((0xf712c000 + 0x3d8), 0x540); + mmio_write_32((0xf712c000 + 0x018), 0x0); + mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f); + mmio_write_32((0xf712c000 + 0x0b4), 0xf); + mmio_write_32((0xf712c000 + 0x088), 0x3fff801); + mmio_write_32((0xf712c000 + 0x070), 0x8940000); + + data = mmio_read_32((0xf712c000 + 0x078)); + data |= 4; + mmio_write_32((0xf712c000 + 0x078), data); + mmio_write_32((0xf712c000 + 0x01c), 0x8000080); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xfffffffe; + mmio_write_32((0xf712c000 + 0x020), data); + mmio_write_32((0xf712c000 + 0x1d4), 0xc0000); + mmio_write_32((0xf712c000 + 0x010), 0x500000f); + mmio_write_32((0xf712c000 + 0x014), 0x10); + data = mmio_read_32((0xf712c000 + 0x1e4)); + data &= 0xffffff00; + mmio_write_32((0xf712c000 + 0x1e4), data); + mmio_write_32((0xf712c000 + 0x030), 0xe663ab77); + mmio_write_32((0xf712c000 + 0x034), 0xea952db); + mmio_write_32((0xf712c000 + 0x038), 0x200d1cb1); + mmio_write_32((0xf712c000 + 0x03c), 0xc67d0721); + mmio_write_32((0xf712c000 + 0x040), 0x3008aa1); + mmio_write_32((0xf712c000 + 0x064), 0x11a43); + mmio_write_32((0xf712c000 + 0x068), 0xff0a0000); + data = mmio_read_32((0xf712c000 + 0x070)); + data &= 0xffff0000; + data |= 0x507; + mmio_write_32((0xf712c000 + 0x070), data); + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 0x40000000; + mmio_write_32((0xf712c000 + 0x048), data); + data = mmio_read_32((0xf712c000 + 0x020)); + data &= 0xffffffef; + mmio_write_32((0xf712c000 + 0x020), data); + data = mmio_read_32((0xf712c000 + 0x080)); + data &= 0xffffdfff; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf712c000 + 0x270), 0x3); + mmio_write_32((0xf712c000 + 0x2f0), 0x3); + mmio_write_32((0xf712c000 + 0x370), 0x3); + mmio_write_32((0xf712c000 + 0x3f0), 0x3); + mmio_write_32((0xf712c000 + 0x048), 0xd0420900); + + mmio_write_32((0xf7128000 + 0x040), 0x2001); + mmio_write_32((0xf712c000 + 0x004), 0x140f); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + WARN("failed to init lpddr3 rank0 dram phy\n"); + return; + } + cat_533mhz_800mhz(); + + mmio_write_32((0xf712c000 + 0x004), 0xf1); + mmio_write_32((0xf7128000 + 0x050), 0x100023); + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7128000 + 0x200), 0xa1000); + + mmio_write_32((0xf7128000 + 0x100), 0x755a9d12); + mmio_write_32((0xf7128000 + 0x104), 0x1753b055); + mmio_write_32((0xf7128000 + 0x108), 0x7401505f); + mmio_write_32((0xf7128000 + 0x10c), 0x578ca244); + mmio_write_32((0xf7128000 + 0x110), 0x10700000); + mmio_write_32((0xf7128000 + 0x114), 0x13141306); + mmio_write_32((0xf7128000 + 0x118), 0x44); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) { + NOTICE("fail to init ddr3 rank0\n"); + return; + } + ddrx_rdet(); + ddrx_wdet(); + + data = mmio_read_32((0xf712c000 + 0x048)); + data |= 1; + mmio_write_32((0xf712c000 + 0x048), data); + mmio_write_32((0xf712c000 + 0x004), 0x21); + do { + data = mmio_read_32((0xf712c000 + 0x004)); + } while (data & 1); + + data = mmio_read_32((0xf712c000 + 0x008)); + if (data & 0x7fe) + NOTICE("ddr3 rank1 init failure\n"); + else + INFO("ddr3 rank1 init pass\n"); + + data = mmio_read_32((0xf712c000 + 0x048)); + data &= ~0xf; + mmio_write_32((0xf712c000 + 0x048), data); + INFO("succeed to set ddrc 800mhz\n"); +} + +static void ddrc_common_init(int freq) +{ + unsigned int data; + + mmio_write_32((0xf7120000 + 0x020), 0x1); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32((0xf7121400 + 0x104), 0xf); + mmio_write_32((0xf7121800 + 0x104), 0xf); + mmio_write_32((0xf7121c00 + 0x104), 0xf); + mmio_write_32((0xf7122000 + 0x104), 0xf); + mmio_write_32((0xf7128000 + 0x02c), 0x6); + mmio_write_32((0xf7128000 + 0x020), 0x30003); + mmio_write_32((0xf7128000 + 0x028), 0x310201); + mmio_write_32((0xf712c000 + 0x1e4), 0xfe007600); + mmio_write_32((0xf7128000 + 0x01c), 0xaf001); + + + data = mmio_read_32((0xf7128000 + 0x280)); + data |= 1 << 7; + mmio_write_32((0xf7128000 + 0x280), data); + mmio_write_32((0xf7128000 + 0x244), 0x3); + + if (freq == DDR_FREQ_800M) + mmio_write_32((0xf7128000 + 0x240), 167 * (freq / 2) / 1024); + else + mmio_write_32((0xf7128000 + 0x240), 167 * freq / 1024); + + data = mmio_read_32((0xf712c000 + 0x080)); + data &= 0xffff; + data |= 0x4002000; + mmio_write_32((0xf712c000 + 0x080), data); + mmio_write_32((0xf7128000 + 0x000), 0x0); + do { + data = mmio_read_32((0xf7128000 + 0x294)); + } while (data & 1); + mmio_write_32((0xf7128000 + 0x000), 0x2); +} + + +static int dienum_det_and_rowcol_cfg(void) +{ + unsigned int data; + + mmio_write_32((0xf7128000 + 0x210), 0x87); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)) & 0xfc; + switch (data) { + case 0x18: + mmio_write_32((0xf7128000 + 0x060), 0x132); + mmio_write_32((0xf7128000 + 0x064), 0x132); + mmio_write_32((0xf7120000 + 0x100), 0x1600); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x40000000); + break; + case 0x1c: + mmio_write_32((0xf7128000 + 0x060), 0x142); + mmio_write_32((0xf7128000 + 0x064), 0x142); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000); + break; + case 0x58: + mmio_write_32((0xf7128000 + 0x060), 0x133); + mmio_write_32((0xf7128000 + 0x064), 0x133); + mmio_write_32((0xf7120000 + 0x100), 0x1700); + mmio_write_32((0xf7120000 + 0x104), 0x71040004); + mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000); + break; + default: + mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000); + break; + } + if (!data) + return -EINVAL; + return 0; +} + +static int detect_ddr_chip_info(void) +{ + unsigned int data, mr5, mr6, mr7; + + mmio_write_32((0xf7128000 + 0x210), 0x57); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr5 = data & 0xff; + switch (mr5) { + case 1: + INFO("Samsung DDR\n"); + break; + case 6: + INFO("Hynix DDR\n"); + break; + case 3: + INFO("Elpida DDR\n"); + break; + default: + INFO("DDR from other vendors\n"); + break; + } + + mmio_write_32((0xf7128000 + 0x210), 0x67); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr6 = data & 0xff; + mmio_write_32((0xf7128000 + 0x210), 0x77); + mmio_write_32((0xf7128000 + 0x218), 0x10000); + mmio_write_32((0xf7128000 + 0x00c), 0x1); + do { + data = mmio_read_32((0xf7128000 + 0x00c)); + } while (data & 1); + data = mmio_read_32((0xf7128000 + 0x4a8)); + mr7 = data & 0xff; + data = mr5 + (mr6 << 8) + (mr7 << 16); + return data; +} + +void ddr_phy_reset(void) +{ + mmio_write_32(0xf7030340, 0xa000); + mmio_write_32(0xf7030344, 0xa000); +} + +void lpddrx_save_ddl_para_bypass(uint32_t *ddr_ddl_para, unsigned int index) +{ + uint32_t value; + uint32_t cnt = index; + uint32_t i; + + for (i = 0; i < 4; i++) { + value = mmio_read_32(0xf712c000 + 0x22c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x23c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x240 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x640 + i * 0x80); + ddr_ddl_para[cnt++] = value; + } +} + +void lpddrx_save_ddl_para_mission(uint32_t *ddr_ddl_para, unsigned int index) +{ + uint32_t value; + uint32_t cnt = index; + uint32_t i; + + value = mmio_read_32(0xf712c000 + 0x140); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x144); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x148); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x14c); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x150); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x1d4); + ddr_ddl_para[cnt++] = value; + for (i = 0; i < 4; i++) { + value = mmio_read_32(0xf712c000 + 0x210 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x214 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x218 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x21c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x220 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x224 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x228 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x22c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x230 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x234 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x238 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x23c + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x240 + i * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x640 + i * 0x80); + ddr_ddl_para[cnt++] = value; + } + value = mmio_read_32(0xf712c000 + 0x168); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x24c + 0 * 0x80); + ddr_ddl_para[cnt++] = value; + value = mmio_read_32(0xf712c000 + 0x24c + 2 * 0x80); + ddr_ddl_para[cnt++] = value; +} + +int lpddr3_freq_init(int freq) +{ + set_ddrc_150mhz(); + lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, 0); + if (freq > DDR_FREQ_150M) { + ddr_phy_reset(); + set_ddrc_266mhz(); + lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, + 16); + } + if (freq > DDR_FREQ_266M) { + ddr_phy_reset(); + set_ddrc_400mhz(); + lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, + 16 * 2); + } + if (freq > DDR_FREQ_400M) { + ddr_phy_reset(); + set_ddrc_533mhz(); + lpddrx_save_ddl_para_mission((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, + 16 * 3); + } + if (freq > DDR_FREQ_533M) { + ddr_phy_reset(); + set_ddrc_800mhz(); + lpddrx_save_ddl_para_mission((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, + 16 * 3 + 61); + } + return 0; +} + +static void init_ddr(int freq) +{ + unsigned int data; + int ret; + + + data = mmio_read_32((0xf7032000 + 0x030)); + data |= 1; + mmio_write_32((0xf7032000 + 0x030), data); + data = mmio_read_32((0xf7032000 + 0x010)); + data |= 1; + mmio_write_32((0xf7032000 + 0x010), data); + + udelay(300); + do { + data = mmio_read_32((0xf7032000 + 0x030)); + data &= 3 << 28; + } while (data != (3 << 28)); + do { + data = mmio_read_32((0xf7032000 + 0x010)); + data &= 3 << 28; + } while (data != (3 << 28)); + + ret = lpddr3_freq_init(freq); + if (ret) + return; +} + +static void init_ddrc_qos(void) +{ + unsigned int port, data; + + mmio_write_32((0xf7124000 + 0x088), 1); + + port = 0; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x11111111); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x11111111); + mmio_write_32((0xf7120000 + 0x400 + 0 * 0x10), 0x001d0007); + + for (port = 3; port <= 4; port++) { + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x77777777); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x77777777); + } + + port = 1; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567); + + mmio_write_32((0xf7124000 + 0x1f0), 0); + mmio_write_32((0xf7124000 + 0x0bc), 0x3020100); + mmio_write_32((0xf7124000 + 0x0d0), 0x3020100); + mmio_write_32((0xf7124000 + 0x1f4), 0x01000100); + mmio_write_32((0xf7124000 + 0x08c + 0 * 4), 0xd0670402); + mmio_write_32((0xf7124000 + 0x068 + 0 * 4), 0x31); + mmio_write_32((0xf7124000 + 0x000), 0x7); + + data = mmio_read_32((0xf7124000 + 0x09c)); + data &= ~0xff0000; + data |= 0x400000; + mmio_write_32((0xf7124000 + 0x09c), data); + data = mmio_read_32((0xf7124000 + 0x0ac)); + data &= ~0xff0000; + data |= 0x400000; + mmio_write_32((0xf7124000 + 0x0ac), data); + port = 2; + mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000); + mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567); + mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567); + + + mmio_write_32((0xf7124000 + 0x09c), 0xff7fff); + mmio_write_32((0xf7124000 + 0x0a0), 0xff); + mmio_write_32((0xf7124000 + 0x0ac), 0xff7fff); + mmio_write_32((0xf7124000 + 0x0b0), 0xff); + mmio_write_32((0xf7124000 + 0x0bc), 0x3020100); + mmio_write_32((0xf7124000 + 0x0d0), 0x3020100); +} + +void hikey_ddr_init(unsigned int ddr_freq) +{ + uint32_t data; + + assert((ddr_freq == DDR_FREQ_150M) || (ddr_freq == DDR_FREQ_266M) || + (ddr_freq == DDR_FREQ_400M) || (ddr_freq == DDR_FREQ_533M) || + (ddr_freq == DDR_FREQ_800M)); + init_pll(); + init_freq(); + + init_ddr(ddr_freq); + + ddrc_common_init(ddr_freq); + dienum_det_and_rowcol_cfg(); + detect_ddr_chip_info(); + + if ((ddr_freq == DDR_FREQ_400M) || (ddr_freq == DDR_FREQ_800M)) { + data = mmio_read_32(0xf7032000 + 0x010); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x010, data); + } else if ((ddr_freq == DDR_FREQ_266M) || (ddr_freq == DDR_FREQ_533M)) { + data = mmio_read_32(0xf7032000 + 0x030); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x030, data); + } else { + data = mmio_read_32(0xf7032000 + 0x010); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x010, data); + data = mmio_read_32(0xf7032000 + 0x030); + data &= ~0x1; + mmio_write_32(0xf7032000 + 0x030, data); + } + dsb(); + isb(); + + /* + * Test memory access. Do not use address 0x0 because the compiler + * may assume it is not a valid address and generate incorrect code + * (GCC 4.9.1 without -fno-delete-null-pointer-checks for instance). + */ + mmio_write_32(0x4, 0xa5a55a5a); + INFO("ddr test value:0x%x\n", mmio_read_32(0x4)); + init_ddrc_qos(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c new file mode 100644 index 0000000..0ab1ca4 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c new file mode 100644 index 0000000..fd610d8 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2017-2018, 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 +#include +#include + +#include "hikey_private.h" + +#define EMMC_BLOCK_SHIFT 9 + +/* Page 1024, since only a few pages before 2048 are used as partition table */ +#define SERIALNO_EMMC_OFFSET (1024 * 512) + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const io_dev_connector_t *emmc_dev_con; +static uintptr_t emmc_dev_handle; +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; + +static int check_emmc(const uintptr_t spec); +static int check_fip(const uintptr_t spec); + +static io_block_spec_t emmc_fip_spec; + +static const io_block_spec_t emmc_gpt_spec = { + .offset = 0, + .length = PLAT_PARTITION_BLOCK_SIZE * + (PLAT_PARTITION_MAX_ENTRIES / 4 + 2), +}; + +static const io_block_dev_spec_t emmc_dev_spec = { + /* It's used as temp buffer in block driver. */ +#ifdef IMAGE_BL1 + .buffer = { + .offset = HIKEY_BL1_MMC_DATA_BASE, + .length = HIKEY_BL1_MMC_DATA_SIZE, + }, +#else + .buffer = { + .offset = HIKEY_MMC_DATA_BASE, + .length = HIKEY_MMC_DATA_SIZE, + }, +#endif + .ops = { + .read = mmc_read_blocks, + .write = mmc_write_blocks, + }, + .block_size = MMC_BLOCK_SIZE, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +static const io_uuid_spec_t scp_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = { + .uuid = UUID_SCP_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_cert_uuid_spec = { + .uuid = UUID_SCP_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &emmc_dev_handle, + (uintptr_t)&emmc_fip_spec, + check_emmc + }, + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_bl2_uuid_spec, + check_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + check_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + check_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + check_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + check_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + check_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + check_fip + }, + [SCP_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_key_cert_uuid_spec, + check_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + check_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + check_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + check_fip + }, + [SCP_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_cert_uuid_spec, + check_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + check_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + check_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + check_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ + [GPT_IMAGE_ID] = { + &emmc_dev_handle, + (uintptr_t)&emmc_gpt_spec, + check_emmc + }, +}; + +static int check_emmc(const uintptr_t spec) +{ + int result; + uintptr_t local_handle; + + result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(emmc_dev_handle, spec, &local_handle); + if (result == 0) + io_close(local_handle); + } + return result; +} + +static int check_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +void hikey_io_setup(void) +{ + int result; + + result = register_io_dev_block(&emmc_dev_con); + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + + result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec, + &emmc_dev_handle); + assert(result == 0); + + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); + assert(result == 0); + + /* Ignore improbable errors in release builds */ + (void)result; +} + +int hikey_set_fip_addr(unsigned int image_id, const char *name) +{ + const partition_entry_t *entry; + + if (emmc_fip_spec.length == 0) { + partition_init(GPT_IMAGE_ID); + entry = get_partition_entry(name); + if (entry == NULL) { + ERROR("Could NOT find the %s partition!\n", name); + return -ENOENT; + } + emmc_fip_spec.offset = entry->start; + emmc_fip_spec.length = entry->length; + } + return 0; +} + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + assert(result == 0); + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return result; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c new file mode 100644 index 0000000..05c1e7f --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2017-2018, 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 + +#define CORE_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +static uintptr_t hikey_sec_entrypoint; + +static int hikey_pwr_domain_on(u_register_t mpidr) +{ + int cpu, cluster; + int curr_cluster; + + cluster = MPIDR_AFFLVL1_VAL(mpidr); + cpu = MPIDR_AFFLVL0_VAL(mpidr); + curr_cluster = MPIDR_AFFLVL1_VAL(read_mpidr()); + if (cluster != curr_cluster) + hisi_ipc_cluster_on(cpu, cluster); + + hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint); + hisi_pwrc_enable_debug(cpu, cluster); + hisi_ipc_cpu_on(cpu, cluster); + + return 0; +} + +static void hikey_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + int cpu, cluster; + + mpidr = read_mpidr(); + cluster = MPIDR_AFFLVL1_VAL(mpidr); + cpu = MPIDR_AFFLVL0_VAL(mpidr); + + + /* + * Enable CCI coherency for this cluster. + * No need for locks as no other cpu is active at the moment. + */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + /* Zero the jump address in the mailbox for this cpu */ + hisi_pwrc_set_core_bx_addr(cpu, cluster, 0); + + /* Program the GIC per-cpu distributor or re-distributor interface */ + gicv2_pcpu_distif_init(); + /* Enable the GIC cpu interface */ + gicv2_cpuif_enable(); +} + +void hikey_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + int cpu, cluster; + + mpidr = read_mpidr(); + cluster = MPIDR_AFFLVL1_VAL(mpidr); + cpu = MPIDR_AFFLVL0_VAL(mpidr); + + gicv2_cpuif_disable(); + hisi_ipc_cpu_off(cpu, cluster); + + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_cluster_off(cpu, cluster); + } +} + +static void hikey_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int cpu = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + + /* Program the jump address for the target cpu */ + hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint); + + gicv2_cpuif_disable(); + + if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + hisi_ipc_cpu_suspend(cpu, cluster); + } + + /* Perform the common cluster specific operations */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_pwrc_set_cluster_wfi(1); + hisi_pwrc_set_cluster_wfi(0); + hisi_ipc_psci_system_off(); + } else + hisi_ipc_cluster_suspend(cpu, cluster); + } +} + +static void hikey_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + unsigned long mpidr; + unsigned int cluster, cpu; + + /* Nothing to be done on waking up from retention from CPU level */ + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + /* Get the mpidr for this cpu */ + mpidr = read_mpidr_el1(); + cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT; + cpu = mpidr & MPIDR_CPU_MASK; + + /* Enable CCI coherency for cluster */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + hisi_pwrc_set_core_bx_addr(cpu, cluster, 0); + + if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + } else { + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + } +} + +static void hikey_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +static void __dead2 hikey_system_off(void) +{ + NOTICE("%s: off system\n", __func__); + + /* Pull down GPIO_0_0 to trigger PMIC shutdown */ + mmio_write_32(0xF8001810, 0x2); /* Pinmux */ + mmio_write_8(0xF8011400, 1); /* Pin direction */ + mmio_write_8(0xF8011004, 0); /* Pin output value */ + + /* Wait for 2s to power off system by PMIC */ + sp804_timer_init(SP804_TIMER0_BASE, 10, 192); + mdelay(2000); + + /* + * PMIC shutdown depends on two conditions: GPIO_0_0 (PWR_HOLD) low, + * and VBUS_DET < 3.6V. For HiKey, VBUS_DET is connected to VDD_4V2 + * through Jumper 1-2. So, to complete shutdown, user needs to manually + * remove Jumper 1-2. + */ + NOTICE("+------------------------------------------+\n"); + NOTICE("| IMPORTANT: Remove Jumper 1-2 to shutdown |\n"); + NOTICE("| DANGER: SoC is still burning. DANGER! |\n"); + NOTICE("| Board will be reboot to avoid overheat |\n"); + NOTICE("+------------------------------------------+\n"); + + /* Send the system reset request */ + mmio_write_32(AO_SC_SYS_STAT0, 0x48698284); + + wfi(); + panic(); +} + +static void __dead2 hikey_system_reset(void) +{ + /* Send the system reset request */ + mmio_write_32(AO_SC_SYS_STAT0, 0x48698284); + isb(); + dsb(); + + wfi(); + panic(); +} + +int hikey_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pstate = psci_get_pstate_type(power_state); + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MPIDR_AFFLVL0] = + PLAT_MAX_RET_STATE; + } else { + for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + PLAT_MAX_OFF_STATE; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +static int hikey_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE))) + return PSCI_E_SUCCESS; + + return PSCI_E_INVALID_ADDRESS; +} + +static const plat_psci_ops_t hikey_psci_ops = { + .cpu_standby = NULL, + .pwr_domain_on = hikey_pwr_domain_on, + .pwr_domain_on_finish = hikey_pwr_domain_on_finish, + .pwr_domain_off = hikey_pwr_domain_off, + .pwr_domain_suspend = hikey_pwr_domain_suspend, + .pwr_domain_suspend_finish = hikey_pwr_domain_suspend_finish, + .system_off = hikey_system_off, + .system_reset = hikey_system_reset, + .validate_power_state = hikey_validate_power_state, + .validate_ns_entrypoint = hikey_validate_ns_entrypoint, + .get_sys_suspend_power_state = hikey_get_sys_suspend_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + hikey_sec_entrypoint = sec_entrypoint; + + /* + * Initialize PSCI ops struct + */ + *psci_ops = &hikey_psci_ops; + return 0; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h new file mode 100644 index 0000000..b75bc72 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY_PRIVATE_H +#define HIKEY_PRIVATE_H + +#include + +#define RANDOM_MAX 0x7fffffffffffffff +#define RANDOM_MAGIC 0x9a4dbeaf + +enum { + DDR_FREQ_150M = 150 * 1000, + DDR_FREQ_266M = 266 * 1000, + DDR_FREQ_400M = 400 * 1000, + DDR_FREQ_533M = 533 * 1000, + DDR_FREQ_800M = 800 * 1000 +}; + +struct random_serial_num { + uint64_t magic; + uint64_t data; + char serialno[32]; +}; + +/* + * Function and variable prototypes + */ +void hikey_init_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); +void hikey_init_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); + +void hikey_ddr_init(unsigned int ddr_freq); +void hikey_io_setup(void); + +void hikey_sp804_init(void); +void hikey_gpio_init(void); +void hikey_pmussi_init(void); +void hikey_hi6553_init(void); +void init_mmc0_pll(void); +void reset_mmc0_clk(void); +void init_media_clk(void); +void init_mmc1_pll(void); +void reset_mmc1_clk(void); +void hikey_mmc_pll_init(void); +void hikey_rtc_init(void); + +int hikey_get_partition_size(const char *arg, int left, char *response); +int hikey_get_partition_type(const char *arg, int left, char *response); + +int hikey_erase(const char *arg); +int hikey_flash(const char *arg); +int hikey_oem(const char *arg); +int hikey_reboot(const char *arg); +void hikey_security_setup(void); + +const char *hikey_init_serialno(void); +int hikey_read_serialno(struct random_serial_num *serialno); +int hikey_write_serialno(struct random_serial_num *serialno); + +void init_acpu_dvfs(void); + +int hikey_set_fip_addr(unsigned int image_id, const char *name); + +#endif /* HIKEY_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S new file mode 100644 index 0000000..f308eee --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global hikey_rotpk_hash + .global hikey_rotpk_hash_end + .section .rodata.hikey_rotpk_hash, "a" +hikey_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +hikey_rotpk_hash_end: diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c new file mode 100644 index 0000000..4b95939 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include + +#include "hikey_private.h" + +#define PORTNUM_MAX 5 + +#define MDDRC_SECURITY_BASE 0xF7121000 + +struct int_en_reg { + unsigned in_en:1; + unsigned reserved:31; +}; + +struct rgn_map_reg { + unsigned rgn_base_addr:24; + unsigned rgn_size:6; + unsigned reserved:1; + unsigned rgn_en:1; +}; + +struct rgn_attr_reg { + unsigned sp:4; + unsigned security_inv:1; + unsigned reserved_0:3; + unsigned mid_en:1; + unsigned mid_inv:1; + unsigned reserved_1:6; + unsigned rgn_en:1; + unsigned subrgn_disable:16; +}; + +static volatile struct int_en_reg *get_int_en_reg(uint32_t base) +{ + uint64_t addr = base + 0x20; + return (struct int_en_reg *)addr; +} + +static volatile struct rgn_map_reg *get_rgn_map_reg(uint32_t base, int region, int port) +{ + uint64_t addr = base + 0x100 + 0x10 * region + 0x400 * (uint64_t)port; + return (struct rgn_map_reg *)addr; +} + +static volatile struct rgn_attr_reg *get_rgn_attr_reg(uint32_t base, int region, + int port) +{ + uint64_t addr = base + 0x104 + 0x10 * region + 0x400 * (uint64_t)port; + return (struct rgn_attr_reg *)addr; +} + +/* + * Configure secure memory region + * region_size must be a power of 2 and at least 64KB + * region_base must be region_size aligned + */ +static void sec_protect(uint32_t region_base, uint32_t region_size, + int region) +{ + volatile struct int_en_reg *int_en; + volatile struct rgn_map_reg *rgn_map; + volatile struct rgn_attr_reg *rgn_attr; + uint32_t i = 0; + + /* ensure secure region number is between 1-15 */ + assert(region > 0 && region < 16); + /* ensure secure region size is a power of 2 >= 64KB */ + assert(IS_POWER_OF_TWO(region_size) && region_size >= 0x10000); + /* ensure secure region address is aligned to region size */ + assert(!(region_base & (region_size - 1))); + + INFO("BL2: TrustZone: protecting %u bytes of memory at 0x%x\n", region_size, + region_base); + + int_en = get_int_en_reg(MDDRC_SECURITY_BASE); + int_en->in_en = 0x1; + + for (i = 0; i < PORTNUM_MAX; i++) { + rgn_map = get_rgn_map_reg(MDDRC_SECURITY_BASE, region, i); + rgn_attr = get_rgn_attr_reg(MDDRC_SECURITY_BASE, region, i); + rgn_map->rgn_base_addr = region_base >> 16; + rgn_attr->subrgn_disable = 0x0; + rgn_attr->sp = (i == 3) ? 0xC : 0x0; + rgn_map->rgn_size = __builtin_ffs(region_size) - 2; + rgn_map->rgn_en = 0x1; + } +} + +/******************************************************************************* + * Initialize the secure environment. + ******************************************************************************/ +void hikey_security_setup(void) +{ + sec_protect(DDR_SEC_BASE, DDR_SEC_SIZE, 1); + sec_protect(DDR_SDP_BASE, DDR_SDP_SIZE, 2); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c new file mode 100644 index 0000000..b7dda8d --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +extern char hikey_rotpk_hash[], hikey_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = hikey_rotpk_hash; + *key_len = hikey_rotpk_hash_end - hikey_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c new file mode 100644 index 0000000..7890eb7 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * The HiKey power domain tree descriptor. The cluster power domains + * are arranged so that when the PSCI generic code creates the power + * domain tree, the indices of the CPU power domain nodes it allocates + * match the linear indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char hikey_power_domain_tree_desc[] = { + /* Number of root nodes */ + 1, + /* Number of clusters */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, + /* Number of children for the second cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, +}; + +/******************************************************************************* + * This function returns the HiKey topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return hikey_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c new file mode 100644 index 0000000..22a67fd --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c @@ -0,0 +1,781 @@ +/* + * Copyright (c) 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 +#include + +#define ACPU_FREQ_MAX_NUM 5 +#define ACPU_OPP_NUM 7 + +#define ACPU_VALID_VOLTAGE_MAGIC (0x5A5AC5C5) + +#define ACPU_WAIT_TIMEOUT (200) +#define ACPU_WAIT_FOR_WFI_TIMOUT (2000) +#define ACPU_DFS_STATE_CNT (0x10000) + +struct acpu_dvfs_sram_stru { + unsigned int magic; + unsigned int support_freq_num; + unsigned int support_freq_max; + unsigned int start_prof; + unsigned int vol[ACPU_OPP_NUM]; +}; + +struct acpu_volt_cal_para { + unsigned int freq; + unsigned int ul_vol; + unsigned int dl_vol; + unsigned int core_ref_hpm; +}; + +struct ddr_volt_cal_para { + unsigned int freq; + unsigned int ul_vol; + unsigned int dl_vol; + unsigned int ddr_ref_hpm; +}; + +struct acpu_dvfs_opp_para { + unsigned int freq; + unsigned int acpu_clk_profile0; + unsigned int acpu_clk_profile1; + unsigned int acpu_vol_profile; + unsigned int acpu_pll_freq; + unsigned int acpu_pll_frac; +}; + +unsigned int efuse_acpu_freq[] = { + 1200000, 1250000, 1300000, 1350000, + 1400000, 1450000, 1500000, 1550000, + 1600000, 1650000, 1700000, 1750000, + 1800000, 1850000, 1900000, 1950000, +}; + +struct acpu_dvfs_opp_para hi6220_acpu_profile[] = { + { 208000, 0x61E5, 0x022, 0x3A, 0x5220102B, 0x05555555 }, + { 432000, 0x10A6, 0x121, 0x3A, 0x5120102D, 0x10000005 }, + { 729000, 0x2283, 0x100, 0x4A, 0x51101026, 0x10000005 }, + { 960000, 0x1211, 0x100, 0x5B, 0x51101032, 0x10000005 }, + { 1200000, 0x1211, 0x100, 0x6B, 0x5110207D, 0x10000005 }, + { 1400000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, + { 1500000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 }, +}; + +struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile; +struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf = + (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; + +static inline void write_reg_mask(uintptr_t addr, + uint32_t val, uint32_t mask) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg = (reg & ~(mask)) | val; + mmio_write_32(addr, reg); +} + +static inline uint32_t read_reg_mask(uintptr_t addr, + uint32_t mask, uint32_t offset) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg &= (mask << offset); + return (reg >> offset); +} + +static int acpu_dvfs_syspll_cfg(unsigned int prof_id) +{ + uint32_t reg0 = 0; + uint32_t count = 0; + uint32_t clk_div_status = 0; + + /* + * step 1: + * - ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; + */ + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x3 << 12, 0x3 << 12); + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 4, 0x1 << 4); + + /* + * step 2: + * - ACPUSYSPLLCFG.acpu_syspll_div_cfg: + * 208MHz, set to 0x5; + * 500MHz, set to 0x2; + * other opps set to 0x1 + */ + if (prof_id == 0) + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x5 << 0, 0x7 << 0); + else if (prof_id == 1) + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x2 << 0, 0x7 << 0); + else + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 0, 0x7 << 0); + + /* + * step 3: + * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x3; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0 + * - ACPU_SC_VD_CTRL.tune_en_int = 0 + * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1 + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 + */ + clk_div_status = 0x3; + do { + reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, 20); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: clk div status timeout!\n", __func__); + return -1; + } + } while (clk_div_status != reg0); + + write_reg_mask(ACPU_SC_VD_CTRL, 0x0, (0x1 << 0) | (0x1 << 11)); + write_reg_mask(PMCTRL_ACPUCLKDIV, 0x1 << 8, 0x3 << 8); + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x1 << 0, 0x1 << 0); + + return 0; +} + +static void acpu_dvfs_clk_div_cfg(unsigned int prof_id, + unsigned int *cpuext_cfg, + unsigned int *acpu_ddr_cfg) +{ + if (prof_id == 0) { + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x1; + } else if (prof_id == 1) { + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x1; + } else { + /* ddr has not been inited */ + write_reg_mask(PMCTRL_ACPUCLKDIV, + (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x0 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START), + (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) | + (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START)); + *cpuext_cfg = 0x1; + *acpu_ddr_cfg = 0x0; + } +} + +static int acpu_dvfs_freq_ascend(unsigned int cur_prof, unsigned int tar_prof) +{ + unsigned int reg0 = 0; + unsigned int reg1 = 0; + unsigned int reg2 = 0; + unsigned int count = 0; + unsigned int cpuext_cfg_val = 0; + unsigned int acpu_ddr_cfg_val = 0; + int ret = 0; + + /* + * step 1: + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1; + * + * step 2: + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x5 (208MHz) + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x2 (500MHz) + * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x1 (Other OPPs) + * + * step 3: + * - ACPU_SC_CPU_STAT.clk_div_status_vd = 0x3; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x0; + * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1 + */ + ret = acpu_dvfs_syspll_cfg(cur_prof); + if (ret) + return -1; + + /* + * step 4: + * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: syspll sw status timeout\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + /* Enable VD functionality if > 800MHz */ + if (acpu_dvfs_profile[tar_prof].freq > 800000) { + + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); + + /* + * step 5: + * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; + * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; + */ + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); + write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, + ACPU_SC_VD_MASK_PATTERN_VAL, + ACPU_SC_VD_MASK_PATTERN_MASK); + + /* + * step 6: + * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; + * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; + * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; + * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; + */ + mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); + + /* + * step 7: + * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; + * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; + * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; + * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; + * + * step 8: + * - ACPU_SC_VD_CTRL.tune = 0x7; + */ + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); + } + + /* step 9: ACPUPLLCTRL.acpupll_en_cfg = 0x0 */ + write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* step 10: set PMCTRL_ACPUPLLFREQ and PMCTRL_ACPUPLLFRAC */ + mmio_write_32(PMCTRL_ACPUPLLFREQ, + acpu_dvfs_profile[tar_prof].acpu_pll_freq); + mmio_write_32(PMCTRL_ACPUPLLFRAC, + acpu_dvfs_profile[tar_prof].acpu_pll_frac); + + /* + * step 11: + * - wait for 1us; + * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 + */ + count = 0; + while (count < ACPU_WAIT_TIMEOUT) + count++; + + write_reg_mask(PMCTRL_ACPUPLLCTRL, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* step 12: PMCTRL_ACPUVOLPMUADDR = 0x100da */ + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); + + /* + * step 13: + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (208MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (500MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x20 (798MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1300MHz); + * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1500MHz); + */ + write_reg_mask(PMCTRL_ACPUDESTVOL, + acpu_dvfs_profile[tar_prof].acpu_vol_profile, + ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); + + /* + * step 14: + * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol + * - Polling ACPUVOLTIMEOUT.acpu_vol_timeout == 0x1 + * - Config PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg + * - Config ACPUCLKDIV.cpuext_clk_div_cfg; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); + reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); + reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, + SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu destvol cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != reg1) || (reg2 != 0x1)); + + acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); + + /* + * step 15: + * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; + * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; + * - ACPUPLLCTRL.acpupll_timeout = 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); + reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); + reg2 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, + SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu clk div cfg timeout.\n", __func__); + return -1; + } + } while ((reg1 != cpuext_cfg_val) || + (reg0 != acpu_ddr_cfg_val) || + (reg2 != 0x1)); + + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); + + /* + * step 16: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu pll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + if (acpu_dvfs_profile[tar_prof].freq > 800000) + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); + + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, + (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | + (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); + + return 0; +} + +static int acpu_dvfs_freq_descend(unsigned int cur_prof, unsigned int tar_prof) +{ + unsigned int reg0 = 0; + unsigned int reg1 = 0; + unsigned int reg2 = 0; + unsigned int count = 0; + unsigned int cpuext_cfg_val = 0; + unsigned int acpu_ddr_cfg_val = 0; + int ret = 0; + + ret = acpu_dvfs_syspll_cfg(tar_prof); + if (ret) + return -1; + + /* + * step 4: + * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1 + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 2); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: syspll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + /* + * Step 5: + * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x0 + */ + write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, 0x1 << 0); + + /* + * step 6 + * - Config PMCTRL_ACPUPLLFREQ and ACPUPLLFRAC + */ + mmio_write_32(PMCTRL_ACPUPLLFREQ, acpu_dvfs_profile[tar_prof].acpu_pll_freq); + mmio_write_32(PMCTRL_ACPUPLLFRAC, acpu_dvfs_profile[tar_prof].acpu_pll_frac); + + /* + * step 7: + * - Wait 1us; + * - Config PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1 + */ + count = 0; + while (count < ACPU_WAIT_TIMEOUT) + count++; + + write_reg_mask(PMCTRL_ACPUPLLCTRL, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START, + 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START); + + /* Enable VD functionality if > 800MHz */ + if (acpu_dvfs_profile[tar_prof].freq > 800000) { + + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK); + + /* + * step 9: + * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A; + * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB; + */ + write_reg_mask(ACPU_SC_VD_HPM_CTRL, + HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK); + write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL, + ACPU_SC_VD_MASK_PATTERN_VAL, + ACPU_SC_VD_MASK_PATTERN_MASK); + + /* + * step 10: + * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF; + * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF; + * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF; + * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1; + */ + mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF); + mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1); + + /* + * step 11: + * - ACPU_SC_VD_CTRL.shift_table0 = 0x1; + * - ACPU_SC_VD_CTRL.shift_table1 = 0x3; + * - ACPU_SC_VD_CTRL.shift_table2 = 0x5; + * - ACPU_SC_VD_CTRL.shift_table3 = 0x6; + * + * step 12: + * - ACPU_SC_VD_CTRL.tune = 0x7; + */ + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL, + ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK); + } + + /* + * step 13: + * - Pollig PMCTRL_ACPUPLLCTRL.acpupll_timeout == 0x1; + * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1, + SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpupll timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0, + 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START); + + /* + * step 14: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, + SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpupll sw status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x1); + + if (acpu_dvfs_profile[tar_prof].freq > 800000) + write_reg_mask(ACPU_SC_VD_CTRL, + ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK); + + /* + * step 15: + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0, + (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) | + (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START)); + + /* + * step 16: + * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x0; + */ + count = 0; + do { + reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, + ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: clk div status timeout.\n", __func__); + return -1; + } + } while (reg0 != 0x0); + + acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val); + + /* + * step 17: + * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat; + * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat; + * - PMCTRL_ACPUVOLPMUADDR = 0x1006C; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START); + reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3, + SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu clk div cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != cpuext_cfg_val) || (reg1 != acpu_ddr_cfg_val)); + + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da); + + /* + * step 16: + * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1; + * - ACPU_SC_VD_CTRL.force_clk_en = 0x0; + * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0; + * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0; + * - ACPU_SC_VD_CTRL.div_en_dif = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_int = 0x1; + * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1; + * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0; + * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0; + */ + write_reg_mask(PMCTRL_ACPUDESTVOL, + acpu_dvfs_profile[tar_prof].acpu_vol_profile, + ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1)); + + /* + * step 19: + * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol + * - ACPUVOLTIMEOUT.acpu_vol_timeout = 0x1; + */ + count = 0; + do { + reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START); + reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F, + SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START); + reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1, + SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START); + if ((count++) > ACPU_DFS_STATE_CNT) { + ERROR("%s: acpu destvol cfg timeout.\n", __func__); + return -1; + } + } while ((reg0 != reg1) || (reg2 != 0x1)); + + return 0; +} + +int acpu_dvfs_target(unsigned int curr_prof, unsigned int target_prof) +{ + int ret = 0; + + if (curr_prof == target_prof) { + INFO("%s: target_prof is equal curr_prof: is %d!\n", + __func__, curr_prof); + return 0; + } + + if ((curr_prof >= ACPU_FREQ_MAX_NUM) || + (target_prof >= ACPU_FREQ_MAX_NUM)) { + INFO("%s: invalid parameter %d %d\n", + __func__, curr_prof, target_prof); + return -1; + } + + if (target_prof > acpu_dvfs_sram_buf->support_freq_num) + target_prof = acpu_dvfs_sram_buf->support_freq_num; + + if (target_prof < curr_prof) + ret = acpu_dvfs_freq_descend(curr_prof, target_prof); + else if (target_prof > curr_prof) + ret = acpu_dvfs_freq_ascend(curr_prof, target_prof); + + if (ret) { + ERROR("%s: acpu_dvfs_target failed!\n", __func__); + return -1; + } + + /* Complete acpu dvfs setting and set magic number */ + acpu_dvfs_sram_buf->start_prof = target_prof; + acpu_dvfs_sram_buf->magic = ACPU_VALID_VOLTAGE_MAGIC; + + mmio_write_32(DDR_DFS_FREQ_ADDR, 800000); + return 0; +} + +static int acpu_dvfs_set_freq(void) +{ + unsigned int i; + unsigned int curr_prof; + unsigned int target_prof; + unsigned int max_freq = 0; + + max_freq = acpu_dvfs_sram_buf->support_freq_max; + + for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) { + + if (max_freq == hi6220_acpu_profile[i].freq) { + target_prof = i; + break; + } + } + + if (i == acpu_dvfs_sram_buf->support_freq_num) { + ERROR("%s: cannot found max freq profile\n", __func__); + return -1; + } + + curr_prof = 0; + target_prof = i; + + /* if max freq is 208MHz, do nothing */ + if (curr_prof == target_prof) + return 0; + + if (acpu_dvfs_target(curr_prof, target_prof)) { + ERROR("%s: set acpu freq failed!", __func__); + return -1; + } + + INFO("%s: support freq num is %d\n", + __func__, acpu_dvfs_sram_buf->support_freq_num); + INFO("%s: start prof is 0x%x\n", + __func__, acpu_dvfs_sram_buf->start_prof); + INFO("%s: magic is 0x%x\n", + __func__, acpu_dvfs_sram_buf->magic); + INFO("%s: voltage:\n", __func__); + for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) + INFO(" - %d: 0x%x\n", i, acpu_dvfs_sram_buf->vol[i]); + + NOTICE("%s: set acpu freq success!", __func__); + return 0; +} + +struct acpu_dvfs_volt_setting { + unsigned int magic; + unsigned int support_freq_num; + unsigned int support_freq_max; + unsigned int start_prof; + unsigned int vol[7]; + unsigned int hmp_dly_threshold[7]; +}; + +static void acpu_dvfs_volt_init(void) +{ + struct acpu_dvfs_volt_setting *volt; + + /* + * - set default voltage; + * - set pmu address; + * - set voltage up and down step; + * - set voltage stable time; + */ + mmio_write_32(PMCTRL_ACPUDFTVOL, 0x4a); + mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0xda); + mmio_write_32(PMCTRL_ACPUVOLUPSTEP, 0x1); + mmio_write_32(PMCTRL_ACPUVOLDNSTEP, 0x1); + mmio_write_32(PMCTRL_ACPUPMUVOLUPTIME, 0x60); + mmio_write_32(PMCTRL_ACPUPMUVOLDNTIME, 0x60); + mmio_write_32(PMCTRL_ACPUCLKOFFCFG, 0x1000); + + volt = (void *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR; + volt->magic = 0x5a5ac5c5; + volt->support_freq_num = 5; + volt->support_freq_max = 1200000; + volt->start_prof = 4; + volt->vol[0] = 0x49; + volt->vol[1] = 0x49; + volt->vol[2] = 0x50; + volt->vol[3] = 0x60; + volt->vol[4] = 0x78; + volt->vol[5] = 0x78; + volt->vol[6] = 0x78; + + volt->hmp_dly_threshold[0] = 0x0; + volt->hmp_dly_threshold[1] = 0x0; + volt->hmp_dly_threshold[2] = 0x0; + volt->hmp_dly_threshold[3] = 0x0e8b0e45; + volt->hmp_dly_threshold[4] = 0x10691023; + volt->hmp_dly_threshold[5] = 0x10691023; + volt->hmp_dly_threshold[6] = 0x10691023; + + INFO("%s: success!\n", __func__); +} + +void init_acpu_dvfs(void) +{ + unsigned int i = 0; + + INFO("%s: pmic version %d\n", __func__, + mmio_read_8(HI6553_VERSION_REG)); + + /* init parameters */ + mmio_write_32(ACPU_CHIP_MAX_FREQ, efuse_acpu_freq[8]); + INFO("%s: ACPU_CHIP_MAX_FREQ=0x%x.\n", + __func__, mmio_read_32(ACPU_CHIP_MAX_FREQ)); + + /* set maximum support frequency to 1.2GHz */ + for (i = 0; i < ACPU_FREQ_MAX_NUM; i++) + acpu_dvfs_sram_buf->vol[i] = hi6220_acpu_profile[i].acpu_vol_profile; + + acpu_dvfs_sram_buf->support_freq_num = ACPU_FREQ_MAX_NUM; + acpu_dvfs_sram_buf->support_freq_max = 1200000; + + /* init acpu dvfs */ + acpu_dvfs_volt_init(); + acpu_dvfs_set_freq(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c new file mode 100644 index 0000000..43ee0b2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +static int ipc_init; + +static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = { + { + HISI_IPC_MCU_INT_SRC_ACPU0_PD, + HISI_IPC_MCU_INT_SRC_ACPU1_PD, + HISI_IPC_MCU_INT_SRC_ACPU2_PD, + HISI_IPC_MCU_INT_SRC_ACPU3_PD, + }, + { + HISI_IPC_MCU_INT_SRC_ACPU4_PD, + HISI_IPC_MCU_INT_SRC_ACPU5_PD, + HISI_IPC_MCU_INT_SRC_ACPU6_PD, + HISI_IPC_MCU_INT_SRC_ACPU7_PD, + } +}; + +int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu, + unsigned int cluster) +{ + unsigned int val = 0, cpu_val = 0; + int i; + + val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); + val = val >> (cluster * 16); + + for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) { + + if (cpu == i) + continue; + + cpu_val = (val >> (i * 4)) & 0xF; + if (cpu_val == 0x8) + return 0; + } + + return 1; +} + +int hisi_cpus_powered_off_besides_curr(unsigned int cpu) +{ + unsigned int val; + + val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); + return (val == (0x8 << (cpu * 4))); +} + +static void hisi_ipc_send(unsigned int ipc_num) +{ + if (!ipc_init) { + printf("error ipc base is null!!!\n"); + return; + } + + mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num); +} + +void hisi_ipc_spin_lock(unsigned int signal) +{ + unsigned int hs_ctrl; + + if (signal >= HISI_IPC_INT_SRC_NUM) + return; + + do { + hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal)); + } while (hs_ctrl); +} + +void hisi_ipc_spin_unlock(unsigned int signal) +{ + if (signal >= HISI_IPC_INT_SRC_NUM) + return; + + mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0); +} + +void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster, + unsigned int mode) +{ + unsigned int val = 0; + unsigned int offset; + + if (mode == HISI_IPC_PM_ON) + offset = cluster * 16 + cpu * 4; + else + offset = cluster * 16 + cpu * 4 + 1; + + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); + val |= (0x01 << offset); + mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val); + isb(); + dsb(); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_send(cpu_ipc_num[cluster][cpu]); +} + +void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster) +{ + hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON); +} + +void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster) +{ + hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF); +} + +void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster, + unsigned int mode) +{ + unsigned int val = 0; + unsigned int offset; + + if (mode == HISI_IPC_PM_ON) + offset = cluster * 4; + else + offset = cluster * 4 + 1; + + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR); + val |= (0x01 << offset); + mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val); + isb(); + dsb(); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_send(cpu_ipc_num[cluster][cpu]); +} + +void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster) +{ + hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON); +} + +void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster) +{ + hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF); +} + +void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster) +{ + unsigned int val = 0; + unsigned int offset; + + offset = cluster * 16 + cpu * 4 + 2; + + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR); + val |= (0x01 << offset); + mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val); + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_send(cpu_ipc_num[cluster][cpu]); +} + +void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster) +{ + unsigned int val; + unsigned int offset; + + offset = cluster * 4 + 1; + + hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE); + if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) { + val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR); + val |= (0x01 << offset); + mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val); + } + hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE); + + hisi_ipc_send(cpu_ipc_num[cluster][cpu]); +} + +void hisi_ipc_psci_system_off(void) +{ + hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD); +} + +int hisi_ipc_init(void) +{ + ipc_init = 1; + + mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8); + mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8); + return 0; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c new file mode 100644 index 0000000..ac83bd8 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define MCU_SECTION_MAX 30 + +enum MCU_IMAGE_SEC_TYPE_ENUM { + MCU_IMAGE_SEC_TYPE_TEXT = 0, /* text section */ + MCU_IMAGE_SEC_TYPE_DATA, /* data section */ + MCU_IMAGE_SEC_TYPE_BUTT +}; + +enum MCU_IMAGE_SEC_LOAD_ENUM { + MCU_IMAGE_SEC_LOAD_STATIC = 0, + MCU_IMAGE_SEC_LOAD_DYNAMIC, + MCU_IMAGE_SEC_LOAD_BUFFER, + MCU_IMAGE_SEC_LOAD_MODEM_ENTRY, + MCU_IMAGE_SEC_LOAD_BUTT +}; + +struct mcu_image_sec { + unsigned short serial; + char type; + char load_attr; + uint32_t src_offset; /* offset in image */ + uint32_t dst_offset; /* offset in memory */ + uint32_t size; +}; + +struct mcu_image_head { + char time_stamp[24]; + uint32_t image_size; + uint32_t secs_num; + struct mcu_image_sec secs[MCU_SECTION_MAX]; +}; + +#define SOC_SRAM_M3_BASE_ADDR (0xF6000000) + +#define MCU_SRAM_SIZE (0x0000C000) +#define MCU_CACHE_SIZE (0x00004000) +#define MCU_CODE_SIZE (MCU_SRAM_SIZE - MCU_CACHE_SIZE) + +#define MCU_SYS_MEM_ADDR (0x05E00000) +#define MCU_SYS_MEM_SIZE (0x00100000) + +static uint32_t mcu2ap_addr(uint32_t mcu_addr) +{ + if (mcu_addr < MCU_CODE_SIZE) + return (mcu_addr + SOC_SRAM_M3_BASE_ADDR); + else if ((mcu_addr >= MCU_SRAM_SIZE) && + (mcu_addr < MCU_SRAM_SIZE + MCU_SYS_MEM_SIZE)) + return mcu_addr - MCU_SRAM_SIZE + MCU_SYS_MEM_ADDR; + else + return mcu_addr; +} + +static int is_binary_header_invalid(struct mcu_image_head *head, + unsigned int length) +{ + /* invalid cases */ + if ((head->image_size == 0) || + (head->image_size > length) || + (head->secs_num > MCU_SECTION_MAX) || + (head->secs_num == 0)) + return 1; + + return 0; +} + +static int is_binary_section_invalid(struct mcu_image_sec *sec, + struct mcu_image_head *head) +{ + unsigned long ap_dst_offset = 0; + + if ((sec->serial >= head->secs_num) || + (sec->src_offset + sec->size > head->image_size)) + return 1; + + if ((sec->type >= MCU_IMAGE_SEC_TYPE_BUTT) || + (sec->load_attr >= MCU_IMAGE_SEC_LOAD_BUTT)) + return 1; + + ap_dst_offset = mcu2ap_addr(sec->dst_offset); + if ((ap_dst_offset >= SOC_SRAM_M3_BASE_ADDR) && + (ap_dst_offset < SOC_SRAM_M3_BASE_ADDR + 0x20000 - sec->size)) + return 0; + else if ((ap_dst_offset >= MCU_SYS_MEM_ADDR) && + (ap_dst_offset < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE - sec->size)) + return 0; + else if ((ap_dst_offset >= 0xfff8e000) && + (ap_dst_offset < 0xfff91c00 - sec->size)) + return 0; + + ERROR("%s: mcu destination address invalid.\n", __func__); + ERROR("%s: number=%d, dst offset=%d size=%d\n", + __func__, sec->serial, sec->dst_offset, sec->size); + return 1; +} + +void hisi_mcu_enable_sram(void) +{ + mmio_write_32(AO_SC_PERIPH_CLKEN4, + AO_SC_PERIPH_CLKEN4_HCLK_IPC_S | + AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS); + + /* set register to enable dvfs which is used by mcu */ + mmio_write_32(PERI_SC_RESERVED8_ADDR, 0x0A001022); + + /* mcu mem is powered on, need de-assert reset */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, + AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N); + + /* enable mcu hclk */ + mmio_write_32(AO_SC_PERIPH_CLKEN4, + AO_SC_PERIPH_CLKEN4_HCLK_MCU | + AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP); +} + +void hisi_mcu_start_run(void) +{ + unsigned int val; + + /* set mcu ddr remap configuration */ + mmio_write_32(AO_SC_MCU_SUBSYS_CTRL2, MCU_SYS_MEM_ADDR); + + /* de-assert reset for mcu and to run */ + mmio_write_32(AO_SC_PERIPH_RSTDIS4, + AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N | + AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N); + + val = mmio_read_32(AO_SC_SYS_CTRL2); + mmio_write_32(AO_SC_SYS_CTRL2, + val | AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR); + + INFO("%s: AO_SC_SYS_CTRL2=%x\n", __func__, + mmio_read_32(AO_SC_SYS_CTRL2)); +} + +int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size) +{ + unsigned int i; + struct mcu_image_head *head; + char *buf; + + head = (struct mcu_image_head *)image_base; + if (is_binary_header_invalid(head, image_size)) { + ERROR("Invalid %s image header.\n", head->time_stamp); + return -1; + } + + buf = (char *)head; + for (i = 0; i < head->secs_num; i++) { + + int *src, *dst; + + /* check the sections */ + if (is_binary_section_invalid(&head->secs[i], head)) { + ERROR("Invalid mcu section.\n"); + return -1; + } + + /* check if the section is static-loaded */ + if (head->secs[i].load_attr != MCU_IMAGE_SEC_LOAD_STATIC) + continue; + + /* copy the sections */ + src = (int *)(intptr_t)(buf + head->secs[i].src_offset); + dst = (int *)(intptr_t)mcu2ap_addr(head->secs[i].dst_offset); + + memcpy((void *)dst, (void *)src, head->secs[i].size); + + INFO("%s: mcu sections %d:\n", __func__, i); + INFO("%s: src = 0x%x\n", + __func__, (unsigned int)(uintptr_t)src); + INFO("%s: dst = 0x%x\n", + __func__, (unsigned int)(uintptr_t)dst); + INFO("%s: size = %d\n", __func__, head->secs[i].size); + + INFO("%s: [SRC 0x%x] 0x%x 0x%x 0x%x 0x%x\n", + __func__, (unsigned int)(uintptr_t)src, + src[0], src[1], src[2], src[3]); + INFO("%s: [DST 0x%x] 0x%x 0x%x 0x%x 0x%x\n", + __func__, (unsigned int)(uintptr_t)dst, + dst[0], dst[1], dst[2], dst[3]); + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c new file mode 100644 index 0000000..e2e3db7 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 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 + +#define CLUSTER_CORE_COUNT (4) +#define CLUSTER_CORE_MASK ((1 << CLUSTER_CORE_COUNT) - 1) + +void hisi_pwrc_set_core_bx_addr(unsigned int core, unsigned int cluster, + uintptr_t entry_point) +{ + uintptr_t *core_entry = (uintptr_t *)PWRCTRL_ACPU_ASM_D_ARM_PARA_AD; + unsigned int i; + + if (!core_entry) { + INFO("%s: core entry point is null!\n", __func__); + return; + } + + i = cluster * CLUSTER_CORE_COUNT + core; + mmio_write_64((uintptr_t)(core_entry + i), entry_point); +} + +void hisi_pwrc_set_cluster_wfi(unsigned int cluster) +{ + unsigned int reg = 0; + + if (cluster == 0) { + reg = mmio_read_32(ACPU_SC_SNOOP_PWD); + reg |= PD_DETECT_START0; + mmio_write_32(ACPU_SC_SNOOP_PWD, reg); + } else if (cluster == 1) { + reg = mmio_read_32(ACPU_SC_SNOOP_PWD); + reg |= PD_DETECT_START1; + mmio_write_32(ACPU_SC_SNOOP_PWD, reg); + } +} + +void hisi_pwrc_enable_debug(unsigned int core, unsigned int cluster) +{ + unsigned int val, enable; + + enable = 1U << (core + PDBGUP_CLUSTER1_SHIFT * cluster); + + /* Enable debug module */ + val = mmio_read_32(ACPU_SC_PDBGUP_MBIST); + mmio_write_32(ACPU_SC_PDBGUP_MBIST, val | enable); + do { + /* RAW barrier */ + val = mmio_read_32(ACPU_SC_PDBGUP_MBIST); + } while (!(val & enable)); +} + +int hisi_pwrc_setup(void) +{ + unsigned int reg, sec_entrypoint; + extern char pm_asm_code[], pm_asm_code_end[]; + extern char v7_asm[], v7_asm_end[]; + + sec_entrypoint = PWRCTRL_ACPU_ASM_CODE_BASE; + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(0), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(1), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(2), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(3), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(4), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(5), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(6), sec_entrypoint >> 2); + mmio_write_32(ACPU_SC_CPUx_RVBARADDR(7), sec_entrypoint >> 2); + + memset((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, 0, 0x400); + memcpy((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, (void *)v7_asm, + v7_asm_end - v7_asm); + + memcpy((void *)PWRCTRL_ACPU_ASM_CODE_BASE, (void *)pm_asm_code, + pm_asm_code_end - pm_asm_code); + + reg = mmio_read_32(AO_SC_SYS_CTRL1); + /* Remap SRAM address for ACPU */ + reg |= AO_SC_SYS_CTRL1_REMAP_SRAM_AARM | + AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK; + + /* Enable reset signal for watchdog */ + reg |= AO_SC_SYS_CTRL1_AARM_WD_RST_CFG | + AO_SC_SYS_CTRL1_AARM_WD_RST_CFG_MSK; + mmio_write_32(AO_SC_SYS_CTRL1, reg); + + return 0; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S new file mode 100644 index 0000000..62542f2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .global pm_asm_code + .global pm_asm_code_end + .global v7_asm + .global v7_asm_end + +func pm_asm_code _align=3 + mov x0, 0 + msr oslar_el1, x0 + + mrs x0, CORTEX_A53_CPUACTLR_EL1 + bic x0, x0, #(CORTEX_A53_CPUACTLR_EL1_RADIS | \ + CORTEX_A53_CPUACTLR_EL1_L1RADIS) + orr x0, x0, #0x180000 + orr x0, x0, #0xe000 + msr CORTEX_A53_CPUACTLR_EL1, x0 + + mrs x3, actlr_el3 + orr x3, x3, #ACTLR_EL3_L2ECTLR_BIT + msr actlr_el3, x3 + + mrs x3, actlr_el2 + orr x3, x3, #ACTLR_EL2_L2ECTLR_BIT + msr actlr_el2, x3 + + ldr x3, =PWRCTRL_ACPU_ASM_D_ARM_PARA_AD + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 +pen: ldr x4, [x3, x0, LSL #3] + cbz x4, pen + + mov x0, #0x0 + mov x1, #0x0 + mov x2, #0x0 + mov x3, #0x0 + br x4 + + .ltorg + +pm_asm_code_end: +endfunc pm_asm_code + + /* + * By default, all cores in Hi6220 reset with aarch32 mode. + * Now hardcode ARMv7 instructions to execute warm reset for + * switching aarch64 mode. + */ + .align 3 + .section .rodata.v7_asm, "aS" +v7_asm: + .word 0xE1A00000 // nop + .word 0xE3A02003 // mov r2, #3 + .word 0xEE0C2F50 // mcr 15, 0, r2, cr12, cr0, {2} + .word 0xE320F003 // wfi + + .ltorg +v7_asm_end: diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c new file mode 100644 index 0000000..3cd1bd0 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include + +/* Hisi SiP Service UUID */ +DEFINE_SVC_UUID2(hisi_sip_svc_uid, + 0x74df99e5, 0x8276, 0xaa40, 0x9f, 0xf8, + 0xc0, 0x85, 0x52, 0xbc, 0x39, 0x3f); + +static int hisi_sip_setup(void) +{ + if (pmf_setup() != 0) + return 1; + return 0; +} + +/* + * This function handles Hisi defined SiP Calls + */ +static uintptr_t hisi_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) +{ + int call_count = 0; + + /* + * Dispatch PMF calls to PMF SMC handler and return its return + * value + */ + if (is_pmf_fid(smc_fid)) { + return pmf_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + + switch (smc_fid) { + case HISI_SIP_SVC_CALL_COUNT: + /* PMF calls */ + call_count += PMF_NUM_SMC_CALLS; + + /* State switch call */ + call_count += 1; + + SMC_RET1(handle, call_count); + + case HISI_SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, hisi_sip_svc_uid); + + case HISI_SIP_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, HISI_SIP_SVC_VERSION_MAJOR, HISI_SIP_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented HISI SiP Service Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } + +} + + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + hisi_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + hisi_sip_setup, + hisi_sip_handler +); diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h new file mode 100644 index 0000000..f67ee5c --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_H +#define HI6220_H + +#include +#include +#include +#include +#include + +/******************************************************************************* + * Implementation defined ACTLR_EL2 bit definitions + ******************************************************************************/ +#define ACTLR_EL2_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL2_L2ECTLR_BIT (1 << 5) +#define ACTLR_EL2_L2CTLR_BIT (1 << 4) +#define ACTLR_EL2_CPUECTLR_BIT (1 << 1) +#define ACTLR_EL2_CPUACTLR_BIT (1 << 0) + +/******************************************************************************* + * Implementation defined ACTLR_EL3 bit definitions + ******************************************************************************/ +#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL3_L2ECTLR_BIT (1 << 5) +#define ACTLR_EL3_L2CTLR_BIT (1 << 4) +#define ACTLR_EL3_CPUECTLR_BIT (1 << 1) +#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define CCI400_BASE 0xF6E90000 +#define CCI400_SL_IFACE3_CLUSTER_IX 3 +#define CCI400_SL_IFACE4_CLUSTER_IX 4 + +#define DWMMC0_BASE 0xF723D000 + +#define DWUSB_BASE 0xF72C0000 + +#define EDMAC_BASE 0xf7370000 +#define EDMAC_SEC_CTRL (EDMAC_BASE + 0x694) +#define EDMAC_AXI_CONF(x) (EDMAC_BASE + 0x820 + (x << 6)) +#define EDMAC_SEC_CTRL_INTR_SEC (1 << 1) +#define EDMAC_SEC_CTRL_GLOBAL_SEC (1 << 0) +#define EDMAC_CHANNEL_NUMS 16 + +#define PMUSSI_BASE 0xF8000000 + +#define SP804_TIMER0_BASE 0xF8008000 + +#define GPIO0_BASE 0xF8011000 +#define GPIO1_BASE 0xF8012000 +#define GPIO2_BASE 0xF8013000 +#define GPIO3_BASE 0xF8014000 +#define GPIO4_BASE 0xF7020000 +#define GPIO5_BASE 0xF7021000 +#define GPIO6_BASE 0xF7022000 +#define GPIO7_BASE 0xF7023000 +#define GPIO8_BASE 0xF7024000 +#define GPIO9_BASE 0xF7025000 +#define GPIO10_BASE 0xF7026000 +#define GPIO11_BASE 0xF7027000 +#define GPIO12_BASE 0xF7028000 +#define GPIO13_BASE 0xF7029000 +#define GPIO14_BASE 0xF702A000 +#define GPIO15_BASE 0xF702B000 +#define GPIO16_BASE 0xF702C000 +#define GPIO17_BASE 0xF702D000 +#define GPIO18_BASE 0xF702E000 +#define GPIO19_BASE 0xF702F000 + +#endif /* HI6220_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h new file mode 100644 index 0000000..a43db68 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_ACPU_H +#define HI6220_REGS_ACPU_H + +#define ACPU_CTRL_BASE 0xF6504000 + +#define ACPU_SC_CPU_CTRL (ACPU_CTRL_BASE + 0x000) +#define ACPU_SC_CPU_STAT (ACPU_CTRL_BASE + 0x008) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2 (1 << 0) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2_SHIFT (0) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0 (1 << 1) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0_SHIFT (1) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1 (1 << 2) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1_SHIFT (2) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2 (1 << 3) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2_SHIFT (3) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3 (1 << 4) +#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3_SHIFT (4) +#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2 (1 << 8) +#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2_SHIFT (8) +#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI (1 << 9) +#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI_SHIFT (9) +#define ACPU_SC_CPU_STAT_L2FLSHUDONE0 (1 << 16) +#define ACPU_SC_CPU_STAT_L2FLSHUDONE0_SHIFT (16) +#define ACPU_SC_CPU_STAT_L2FLSHUDONE1 (1 << 17) +#define ACPU_SC_CPU_STAT_L2FLSHUDONE1_SHIFT (17) +#define ACPU_SC_CPU_STAT_CCI400_ACTIVE (1 << 18) +#define ACPU_SC_CPU_STAT_CCI400_ACTIVE_SHIFT (18) +#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD (1 << 20) +#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT (20) + +#define ACPU_SC_CLKEN (ACPU_CTRL_BASE + 0x00c) +#define HPM_L2_1_CLKEN (1 << 9) +#define G_CPU_1_CLKEN (1 << 8) +#define HPM_L2_CLKEN (1 << 1) +#define G_CPU_CLKEN (1 << 0) + +#define ACPU_SC_CLKDIS (ACPU_CTRL_BASE + 0x010) +#define ACPU_SC_CLK_STAT (ACPU_CTRL_BASE + 0x014) +#define ACPU_SC_RSTEN (ACPU_CTRL_BASE + 0x018) +#define SRST_PRESET1_RSTEN (1 << 11) +#define SRST_PRESET0_RSTEN (1 << 10) +#define SRST_CLUSTER1_RSTEN (1 << 9) +#define SRST_CLUSTER0_RSTEN (1 << 8) +#define SRST_L2_HPM_1_RSTEN (1 << 5) +#define SRST_AARM_L2_1_RSTEN (1 << 4) +#define SRST_L2_HPM_0_RSTEN (1 << 3) +#define SRST_AARM_L2_0_RSTEN (1 << 1) +#define SRST_CLUSTER1 (SRST_PRESET1_RSTEN | \ + SRST_CLUSTER1_RSTEN | \ + SRST_L2_HPM_1_RSTEN | \ + SRST_AARM_L2_1_RSTEN) +#define SRST_CLUSTER0 (SRST_PRESET0_RSTEN | \ + SRST_CLUSTER0_RSTEN | \ + SRST_L2_HPM_0_RSTEN | \ + SRST_AARM_L2_0_RSTEN) + +#define ACPU_SC_RSTDIS (ACPU_CTRL_BASE + 0x01c) +#define ACPU_SC_RST_STAT (ACPU_CTRL_BASE + 0x020) +#define ACPU_SC_PDBGUP_MBIST (ACPU_CTRL_BASE + 0x02c) +#define PDBGUP_CLUSTER1_SHIFT 8 + +#define ACPU_SC_VD_CTRL (ACPU_CTRL_BASE + 0x054) +#define ACPU_SC_VD_MASK_PATTERN_CTRL (ACPU_CTRL_BASE + 0x058) +#define ACPU_SC_VD_MASK_PATTERN_VAL (0xCCB << 12) +#define ACPU_SC_VD_MASK_PATTERN_MASK ((0x1 << 13) - 1) + +#define ACPU_SC_VD_DLY_FIXED_CTRL (ACPU_CTRL_BASE + 0x05c) +#define ACPU_SC_VD_DLY_TABLE0_CTRL (ACPU_CTRL_BASE + 0x060) +#define ACPU_SC_VD_DLY_TABLE1_CTRL (ACPU_CTRL_BASE + 0x064) +#define ACPU_SC_VD_DLY_TABLE2_CTRL (ACPU_CTRL_BASE + 0x068) +#define ACPU_SC_VD_HPM_CTRL (ACPU_CTRL_BASE + 0x06c) +#define ACPU_SC_A53_CLUSTER_MTCMOS_EN (ACPU_CTRL_BASE + 0x088) +#define PW_MTCMOS_EN_A53_1_EN (1 << 1) +#define PW_MTCMOS_EN_A53_0_EN (1 << 0) + +#define ACPU_SC_A53_CLUSTER_MTCMOS_STA (ACPU_CTRL_BASE + 0x090) +#define ACPU_SC_A53_CLUSTER_ISO_EN (ACPU_CTRL_BASE + 0x098) +#define PW_ISO_A53_1_EN (1 << 1) +#define PW_ISO_A53_0_EN (1 << 0) + +#define ACPU_SC_A53_CLUSTER_ISO_DIS (ACPU_CTRL_BASE + 0x09c) +#define ACPU_SC_A53_CLUSTER_ISO_STA (ACPU_CTRL_BASE + 0x0a0) +#define ACPU_SC_A53_1_MTCMOS_TIMER (ACPU_CTRL_BASE + 0x0b4) +#define ACPU_SC_A53_0_MTCMOS_TIMER (ACPU_CTRL_BASE + 0x0bc) +#define ACPU_SC_A53_x_MTCMOS_TIMER(x) ((x) ? ACPU_SC_A53_1_MTCMOS_TIMER : ACPU_SC_A53_0_MTCMOS_TIMER) + +#define ACPU_SC_SNOOP_PWD (ACPU_CTRL_BASE + 0xe4) +#define PD_DETECT_START1 (1 << 16) +#define PD_DETECT_START0 (1 << 0) + +#define ACPU_SC_CPU0_CTRL (ACPU_CTRL_BASE + 0x100) +#define CPU_CTRL_AARCH64_MODE (1 << 7) + +#define ACPU_SC_CPU0_STAT (ACPU_CTRL_BASE + 0x104) +#define ACPU_SC_CPU0_CLKEN (ACPU_CTRL_BASE + 0x108) +#define CPU_CLKEN_HPM (1 << 1) + +#define ACPU_SC_CPU0_CLK_STAT (ACPU_CTRL_BASE + 0x110) + +#define ACPU_SC_CPU0_RSTEN (ACPU_CTRL_BASE + 0x114) +#define ACPU_SC_CPU0_RSTDIS (ACPU_CTRL_BASE + 0x118) +#define ACPU_SC_CPU0_MTCMOS_EN (ACPU_CTRL_BASE + 0x120) +#define CPU_MTCMOS_PW (1 << 0) + +#define ACPU_SC_CPU0_PW_ISOEN (ACPU_CTRL_BASE + 0x130) +#define CPU_PW_ISO (1 << 0) + +#define ACPU_SC_CPU0_PW_ISODIS (ACPU_CTRL_BASE + 0x134) +#define ACPU_SC_CPU0_PW_ISO_STAT (ACPU_CTRL_BASE + 0x138) +#define ACPU_SC_CPU0_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x154) +#define CPU_MTCMOS_TIMER_STA (1 << 0) + +#define ACPU_SC_CPU0_RVBARADDR (ACPU_CTRL_BASE + 0x158) +#define ACPU_SC_CPU1_CTRL (ACPU_CTRL_BASE + 0x200) +#define ACPU_SC_CPU1_STAT (ACPU_CTRL_BASE + 0x204) +#define ACPU_SC_CPU1_CLKEN (ACPU_CTRL_BASE + 0x208) +#define ACPU_SC_CPU1_CLK_STAT (ACPU_CTRL_BASE + 0x210) +#define ACPU_SC_CPU1_RSTEN (ACPU_CTRL_BASE + 0x214) +#define ACPU_SC_CPU1_RSTDIS (ACPU_CTRL_BASE + 0x218) +#define ACPU_SC_CPU1_MTCMOS_EN (ACPU_CTRL_BASE + 0x220) +#define ACPU_SC_CPU1_PW_ISODIS (ACPU_CTRL_BASE + 0x234) +#define ACPU_SC_CPU1_PW_ISO_STAT (ACPU_CTRL_BASE + 0x238) +#define ACPU_SC_CPU1_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x254) +#define ACPU_SC_CPU1_RVBARADDR (ACPU_CTRL_BASE + 0x258) +#define ACPU_SC_CPU2_CTRL (ACPU_CTRL_BASE + 0x300) +#define ACPU_SC_CPU2_STAT (ACPU_CTRL_BASE + 0x304) +#define ACPU_SC_CPU2_CLKEN (ACPU_CTRL_BASE + 0x308) +#define ACPU_SC_CPU2_CLK_STAT (ACPU_CTRL_BASE + 0x310) +#define ACPU_SC_CPU2_RSTEN (ACPU_CTRL_BASE + 0x314) +#define ACPU_SC_CPU2_RSTDIS (ACPU_CTRL_BASE + 0x318) +#define ACPU_SC_CPU2_MTCMOS_EN (ACPU_CTRL_BASE + 0x320) +#define ACPU_SC_CPU2_PW_ISODIS (ACPU_CTRL_BASE + 0x334) +#define ACPU_SC_CPU2_PW_ISO_STAT (ACPU_CTRL_BASE + 0x338) +#define ACPU_SC_CPU2_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x354) +#define ACPU_SC_CPU2_RVBARADDR (ACPU_CTRL_BASE + 0x358) +#define ACPU_SC_CPU3_CTRL (ACPU_CTRL_BASE + 0x400) +#define ACPU_SC_CPU3_STAT (ACPU_CTRL_BASE + 0x404) +#define ACPU_SC_CPU3_CLKEN (ACPU_CTRL_BASE + 0x408) +#define ACPU_SC_CPU3_CLK_STAT (ACPU_CTRL_BASE + 0x410) +#define ACPU_SC_CPU3_RSTEN (ACPU_CTRL_BASE + 0x414) +#define ACPU_SC_CPU3_RSTDIS (ACPU_CTRL_BASE + 0x418) +#define ACPU_SC_CPU3_MTCMOS_EN (ACPU_CTRL_BASE + 0x420) +#define ACPU_SC_CPU3_PW_ISODIS (ACPU_CTRL_BASE + 0x434) +#define ACPU_SC_CPU3_PW_ISO_STAT (ACPU_CTRL_BASE + 0x438) +#define ACPU_SC_CPU3_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x454) +#define ACPU_SC_CPU3_RVBARADDR (ACPU_CTRL_BASE + 0x458) +#define ACPU_SC_CPU4_CTRL (ACPU_CTRL_BASE + 0x500) +#define ACPU_SC_CPU4_STAT (ACPU_CTRL_BASE + 0x504) +#define ACPU_SC_CPU4_CLKEN (ACPU_CTRL_BASE + 0x508) +#define ACPU_SC_CPU4_CLK_STAT (ACPU_CTRL_BASE + 0x510) +#define ACPU_SC_CPU4_RSTEN (ACPU_CTRL_BASE + 0x514) +#define ACPU_SC_CPU4_RSTDIS (ACPU_CTRL_BASE + 0x518) +#define ACPU_SC_CPU4_MTCMOS_EN (ACPU_CTRL_BASE + 0x520) +#define ACPU_SC_CPU4_PW_ISODIS (ACPU_CTRL_BASE + 0x534) +#define ACPU_SC_CPU4_PW_ISO_STAT (ACPU_CTRL_BASE + 0x538) +#define ACPU_SC_CPU4_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x554) +#define ACPU_SC_CPU4_RVBARADDR (ACPU_CTRL_BASE + 0x558) +#define ACPU_SC_CPU5_CTRL (ACPU_CTRL_BASE + 0x600) +#define ACPU_SC_CPU5_STAT (ACPU_CTRL_BASE + 0x604) +#define ACPU_SC_CPU5_CLKEN (ACPU_CTRL_BASE + 0x608) +#define ACPU_SC_CPU5_CLK_STAT (ACPU_CTRL_BASE + 0x610) +#define ACPU_SC_CPU5_RSTEN (ACPU_CTRL_BASE + 0x614) +#define ACPU_SC_CPU5_RSTDIS (ACPU_CTRL_BASE + 0x618) +#define ACPU_SC_CPU5_MTCMOS_EN (ACPU_CTRL_BASE + 0x620) +#define ACPU_SC_CPU5_PW_ISODIS (ACPU_CTRL_BASE + 0x634) +#define ACPU_SC_CPU5_PW_ISO_STAT (ACPU_CTRL_BASE + 0x638) +#define ACPU_SC_CPU5_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x654) +#define ACPU_SC_CPU5_RVBARADDR (ACPU_CTRL_BASE + 0x658) +#define ACPU_SC_CPU6_CTRL (ACPU_CTRL_BASE + 0x700) +#define ACPU_SC_CPU6_STAT (ACPU_CTRL_BASE + 0x704) +#define ACPU_SC_CPU6_CLKEN (ACPU_CTRL_BASE + 0x708) +#define ACPU_SC_CPU6_CLK_STAT (ACPU_CTRL_BASE + 0x710) +#define ACPU_SC_CPU6_RSTEN (ACPU_CTRL_BASE + 0x714) +#define ACPU_SC_CPU6_RSTDIS (ACPU_CTRL_BASE + 0x718) +#define ACPU_SC_CPU6_MTCMOS_EN (ACPU_CTRL_BASE + 0x720) +#define ACPU_SC_CPU6_PW_ISODIS (ACPU_CTRL_BASE + 0x734) +#define ACPU_SC_CPU6_PW_ISO_STAT (ACPU_CTRL_BASE + 0x738) +#define ACPU_SC_CPU6_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x754) +#define ACPU_SC_CPU6_RVBARADDR (ACPU_CTRL_BASE + 0x758) +#define ACPU_SC_CPU7_CTRL (ACPU_CTRL_BASE + 0x800) +#define ACPU_SC_CPU7_STAT (ACPU_CTRL_BASE + 0x804) +#define ACPU_SC_CPU7_CLKEN (ACPU_CTRL_BASE + 0x808) +#define ACPU_SC_CPU7_CLK_STAT (ACPU_CTRL_BASE + 0x810) +#define ACPU_SC_CPU7_RSTEN (ACPU_CTRL_BASE + 0x814) +#define ACPU_SC_CPU7_RSTDIS (ACPU_CTRL_BASE + 0x818) +#define ACPU_SC_CPU7_MTCMOS_EN (ACPU_CTRL_BASE + 0x820) +#define ACPU_SC_CPU7_PW_ISODIS (ACPU_CTRL_BASE + 0x834) +#define ACPU_SC_CPU7_PW_ISO_STAT (ACPU_CTRL_BASE + 0x838) +#define ACPU_SC_CPU7_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x854) +#define ACPU_SC_CPU7_RVBARADDR (ACPU_CTRL_BASE + 0x858) +#define ACPU_SC_CPUx_CTRL(x) ((x < 8) ? (ACPU_SC_CPU0_CTRL + 0x100 * x) : ACPU_SC_CPU0_CTRL) +#define ACPU_SC_CPUx_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_STAT + 0x100 * x) : ACPU_SC_CPU0_STAT) +#define ACPU_SC_CPUx_CLKEN(x) ((x < 8) ? (ACPU_SC_CPU0_CLKEN + 0x100 * x) : ACPU_SC_CPU0_CLKEN) +#define ACPU_SC_CPUx_CLK_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_CLK_STAT + 0x100 * x) : ACPU_SC_CPU0_CLK_STAT) +#define ACPU_SC_CPUx_RSTEN(x) ((x < 8) ? (ACPU_SC_CPU0_RSTEN + 0x100 * x) : ACPU_SC_CPU0_RSTEN) +#define ACPU_SC_CPUx_RSTDIS(x) ((x < 8) ? (ACPU_SC_CPU0_RSTDIS + 0x100 * x) : ACPU_SC_CPU0_RSTDIS) +#define ACPU_SC_CPUx_MTCMOS_EN(x) ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_EN + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_EN) +#define ACPU_SC_CPUx_PW_ISODIS(x) ((x < 8) ? (ACPU_SC_CPU0_PW_ISODIS + 0x100 * x) : ACPU_SC_CPU0_PW_ISODIS) +#define ACPU_SC_CPUx_PW_ISO_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_PW_ISO_STAT + 0x100 * x) : ACPU_SC_CPU0_PW_ISO_STAT) +#define ACPU_SC_CPUx_MTCMOS_TIMER_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_TIMER_STAT + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_TIMER_STAT) +#define ACPU_SC_CPUx_RVBARADDR(x) ((x < 8) ? (ACPU_SC_CPU0_RVBARADDR + 0x100 * x) : ACPU_SC_CPU0_RVBARADDR) + +#define ACPU_SC_CPU_STAT_CLKDIV_VD_MASK (3 << 20) + +#define ACPU_SC_VD_CTRL_TUNE_EN_DIF (1 << 0) +#define ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT (0) +#define ACPU_SC_VD_CTRL_TUNE (1 << 1) +#define ACPU_SC_VD_CTRL_TUNE_SHIFT (1) +#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF (1 << 7) +#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT (7) +#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI (1 << 8) +#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT (8) +#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR (1 << 9) +#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR_SHIFT (9) +#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN (1 << 10) +#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT (10) +#define ACPU_SC_VD_CTRL_TUNE_EN_INT (1 << 11) +#define ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT (11) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE0 (1 << 12) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_MASK (0xf << 12) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT (12) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE1 (1 << 16) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_MASK (0xf << 16) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT (16) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE2 (1 << 20) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_MASK (0xf << 20) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT (20) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE3 (1 << 24) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_MASK (0xf << 24) +#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT (24) +#define ACPU_SC_VD_CTRL_FORCE_CLK_EN (1 << 28) +#define ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT (28) +#define ACPU_SC_VD_CTRL_DIV_EN_DIF (1 << 29) +#define ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT (29) + +#define ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL \ + ((0x1 << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) | \ + (0x3 << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) | \ + (0x5 << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) | \ + (0x6 << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) | \ + (0x7 << ACPU_SC_VD_CTRL_TUNE_SHIFT)) + +#define ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK \ + ((0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) | \ + (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) | \ + (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) | \ + (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) | \ + (0x3F << ACPU_SC_VD_CTRL_TUNE_SHIFT)) + +#define ACPU_SC_VD_HPM_CTRL_OSC_DIV (1 << 0) +#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT (0) +#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK (0x000000FF) +#define ACPU_SC_VD_HPM_CTRL_DLY_EXP (1 << 8) +#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT (8) +#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK (0x001FFF00) + +#define HPM_OSC_DIV_VAL \ + (0x56 << ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT) +#define HPM_OSC_DIV_MASK \ + (ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK) + +#define HPM_DLY_EXP_VAL \ + (0xC7A << ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT) +#define HPM_DLY_EXP_MASK \ + (ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK) + +#define ACPU_SC_VD_EN_ASIC_VAL \ + ((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \ + (0X0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \ + (0X0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT)) + +#define ACPU_SC_VD_EN_SFT_VAL \ + ((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \ + (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT)) + +#define ACPU_SC_VD_EN_MASK \ + ((0x1 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \ + (0x1 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT)) + +#endif /* HI6220_REGS_ACPU_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h new file mode 100644 index 0000000..614eba2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_AO_H +#define HI6220_REGS_AO_H + +#define AO_CTRL_BASE 0xF7800000 + +#define AO_SC_SYS_CTRL0 (AO_CTRL_BASE + 0x000) +#define AO_SC_SYS_CTRL1 (AO_CTRL_BASE + 0x004) +#define AO_SC_SYS_CTRL2 (AO_CTRL_BASE + 0x008) +#define AO_SC_SYS_STAT0 (AO_CTRL_BASE + 0x010) +#define AO_SC_SYS_STAT1 (AO_CTRL_BASE + 0x014) +#define AO_SC_MCU_IMCTRL (AO_CTRL_BASE + 0x018) +#define AO_SC_MCU_IMSTAT (AO_CTRL_BASE + 0x01C) +#define AO_SC_SECONDRY_INT_EN0 (AO_CTRL_BASE + 0x044) +#define AO_SC_SECONDRY_INT_STATR0 (AO_CTRL_BASE + 0x048) +#define AO_SC_SECONDRY_INT_STATM0 (AO_CTRL_BASE + 0x04C) +#define AO_SC_MCU_WKUP_INT_EN6 (AO_CTRL_BASE + 0x054) +#define AO_SC_MCU_WKUP_INT_STATR6 (AO_CTRL_BASE + 0x058) +#define AO_SC_MCU_WKUP_INT_STATM6 (AO_CTRL_BASE + 0x05C) +#define AO_SC_MCU_WKUP_INT_EN5 (AO_CTRL_BASE + 0x064) +#define AO_SC_MCU_WKUP_INT_STATR5 (AO_CTRL_BASE + 0x068) +#define AO_SC_MCU_WKUP_INT_STATM5 (AO_CTRL_BASE + 0x06C) +#define AO_SC_MCU_WKUP_INT_EN4 (AO_CTRL_BASE + 0x094) +#define AO_SC_MCU_WKUP_INT_STATR4 (AO_CTRL_BASE + 0x098) +#define AO_SC_MCU_WKUP_INT_STATM4 (AO_CTRL_BASE + 0x09C) +#define AO_SC_MCU_WKUP_INT_EN0 (AO_CTRL_BASE + 0x0A8) +#define AO_SC_MCU_WKUP_INT_STATR0 (AO_CTRL_BASE + 0x0AC) +#define AO_SC_MCU_WKUP_INT_STATM0 (AO_CTRL_BASE + 0x0B0) +#define AO_SC_MCU_WKUP_INT_EN1 (AO_CTRL_BASE + 0x0B4) +#define AO_SC_MCU_WKUP_INT_STATR1 (AO_CTRL_BASE + 0x0B8) +#define AO_SC_MCU_WKUP_INT_STATM1 (AO_CTRL_BASE + 0x0BC) +#define AO_SC_INT_STATR (AO_CTRL_BASE + 0x0C4) +#define AO_SC_INT_STATM (AO_CTRL_BASE + 0x0C8) +#define AO_SC_INT_CLEAR (AO_CTRL_BASE + 0x0CC) +#define AO_SC_INT_EN_SET (AO_CTRL_BASE + 0x0D0) +#define AO_SC_INT_EN_DIS (AO_CTRL_BASE + 0x0D4) +#define AO_SC_INT_EN_STAT (AO_CTRL_BASE + 0x0D8) +#define AO_SC_INT_STATR1 (AO_CTRL_BASE + 0x0E4) +#define AO_SC_INT_STATM1 (AO_CTRL_BASE + 0x0E8) +#define AO_SC_INT_CLEAR1 (AO_CTRL_BASE + 0x0EC) +#define AO_SC_INT_EN_SET1 (AO_CTRL_BASE + 0x0F0) +#define AO_SC_INT_EN_DIS1 (AO_CTRL_BASE + 0x0F4) +#define AO_SC_INT_EN_STAT1 (AO_CTRL_BASE + 0x0F8) +#define AO_SC_TIMER_EN0 (AO_CTRL_BASE + 0x1D0) +#define AO_SC_TIMER_EN1 (AO_CTRL_BASE + 0x1D4) +#define AO_SC_TIMER_EN4 (AO_CTRL_BASE + 0x1F0) +#define AO_SC_TIMER_EN5 (AO_CTRL_BASE + 0x1F4) +#define AO_SC_MCU_SUBSYS_CTRL0 (AO_CTRL_BASE + 0x400) +#define AO_SC_MCU_SUBSYS_CTRL1 (AO_CTRL_BASE + 0x404) +#define AO_SC_MCU_SUBSYS_CTRL2 (AO_CTRL_BASE + 0x408) +#define AO_SC_MCU_SUBSYS_CTRL3 (AO_CTRL_BASE + 0x40C) +#define AO_SC_MCU_SUBSYS_CTRL4 (AO_CTRL_BASE + 0x410) +#define AO_SC_MCU_SUBSYS_CTRL5 (AO_CTRL_BASE + 0x414) +#define AO_SC_MCU_SUBSYS_CTRL6 (AO_CTRL_BASE + 0x418) +#define AO_SC_MCU_SUBSYS_CTRL7 (AO_CTRL_BASE + 0x41C) +#define AO_SC_MCU_SUBSYS_STAT0 (AO_CTRL_BASE + 0x440) +#define AO_SC_MCU_SUBSYS_STAT1 (AO_CTRL_BASE + 0x444) +#define AO_SC_MCU_SUBSYS_STAT2 (AO_CTRL_BASE + 0x448) +#define AO_SC_MCU_SUBSYS_STAT3 (AO_CTRL_BASE + 0x44C) +#define AO_SC_MCU_SUBSYS_STAT4 (AO_CTRL_BASE + 0x450) +#define AO_SC_MCU_SUBSYS_STAT5 (AO_CTRL_BASE + 0x454) +#define AO_SC_MCU_SUBSYS_STAT6 (AO_CTRL_BASE + 0x458) +#define AO_SC_MCU_SUBSYS_STAT7 (AO_CTRL_BASE + 0x45C) +#define AO_SC_PERIPH_CLKEN4 (AO_CTRL_BASE + 0x630) +#define AO_SC_PERIPH_CLKDIS4 (AO_CTRL_BASE + 0x634) +#define AO_SC_PERIPH_CLKSTAT4 (AO_CTRL_BASE + 0x638) +#define AO_SC_PERIPH_CLKEN5 (AO_CTRL_BASE + 0x63C) +#define AO_SC_PERIPH_CLKDIS5 (AO_CTRL_BASE + 0x640) +#define AO_SC_PERIPH_CLKSTAT5 (AO_CTRL_BASE + 0x644) +#define AO_SC_PERIPH_RSTEN4 (AO_CTRL_BASE + 0x6F0) +#define AO_SC_PERIPH_RSTDIS4 (AO_CTRL_BASE + 0x6F4) +#define AO_SC_PERIPH_RSTSTAT4 (AO_CTRL_BASE + 0x6F8) +#define AO_SC_PERIPH_RSTEN5 (AO_CTRL_BASE + 0x6FC) +#define AO_SC_PERIPH_RSTDIS5 (AO_CTRL_BASE + 0x700) +#define AO_SC_PERIPH_RSTSTAT5 (AO_CTRL_BASE + 0x704) +#define AO_SC_PW_CLKEN0 (AO_CTRL_BASE + 0x800) +#define AO_SC_PW_CLKDIS0 (AO_CTRL_BASE + 0x804) +#define AO_SC_PW_CLK_STAT0 (AO_CTRL_BASE + 0x808) +#define AO_SC_PW_RSTEN0 (AO_CTRL_BASE + 0x810) +#define AO_SC_PW_RSTDIS0 (AO_CTRL_BASE + 0x814) +#define AO_SC_PW_RST_STAT0 (AO_CTRL_BASE + 0x818) +#define AO_SC_PW_ISOEN0 (AO_CTRL_BASE + 0x820) +#define AO_SC_PW_ISODIS0 (AO_CTRL_BASE + 0x824) +#define AO_SC_PW_ISO_STAT0 (AO_CTRL_BASE + 0x828) +#define AO_SC_PW_MTCMOS_EN0 (AO_CTRL_BASE + 0x830) +#define AO_SC_PW_MTCMOS_DIS0 (AO_CTRL_BASE + 0x834) +#define AO_SC_PW_MTCMOS_STAT0 (AO_CTRL_BASE + 0x838) +#define AO_SC_PW_MTCMOS_ACK_STAT0 (AO_CTRL_BASE + 0x83C) +#define AO_SC_PW_MTCMOS_TIMEOUT_STAT0 (AO_CTRL_BASE + 0x840) +#define AO_SC_PW_STAT0 (AO_CTRL_BASE + 0x850) +#define AO_SC_PW_STAT1 (AO_CTRL_BASE + 0x854) +#define AO_SC_SYSTEST_STAT (AO_CTRL_BASE + 0x880) +#define AO_SC_SYSTEST_SLICER_CNT0 (AO_CTRL_BASE + 0x890) +#define AO_SC_SYSTEST_SLICER_CNT1 (AO_CTRL_BASE + 0x894) +#define AO_SC_PW_CTRL1 (AO_CTRL_BASE + 0x8C8) +#define AO_SC_PW_CTRL (AO_CTRL_BASE + 0x8CC) +#define AO_SC_MCPU_VOTEEN (AO_CTRL_BASE + 0x8D0) +#define AO_SC_MCPU_VOTEDIS (AO_CTRL_BASE + 0x8D4) +#define AO_SC_MCPU_VOTESTAT (AO_CTRL_BASE + 0x8D8) +#define AO_SC_MCPU_VOTE_MSK0 (AO_CTRL_BASE + 0x8E0) +#define AO_SC_MCPU_VOTE_MSK1 (AO_CTRL_BASE + 0x8E4) +#define AO_SC_MCPU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x8E8) +#define AO_SC_MCPU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x8EC) +#define AO_SC_PERI_VOTEEN (AO_CTRL_BASE + 0x8F0) +#define AO_SC_PERI_VOTEDIS (AO_CTRL_BASE + 0x8F4) +#define AO_SC_PERI_VOTESTAT (AO_CTRL_BASE + 0x8F8) +#define AO_SC_PERI_VOTE_MSK0 (AO_CTRL_BASE + 0x900) +#define AO_SC_PERI_VOTE_MSK1 (AO_CTRL_BASE + 0x904) +#define AO_SC_PERI_VOTESTAT0_MSK (AO_CTRL_BASE + 0x908) +#define AO_SC_PERI_VOTESTAT1_MSK (AO_CTRL_BASE + 0x90C) +#define AO_SC_ACPU_VOTEEN (AO_CTRL_BASE + 0x910) +#define AO_SC_ACPU_VOTEDIS (AO_CTRL_BASE + 0x914) +#define AO_SC_ACPU_VOTESTAT (AO_CTRL_BASE + 0x918) +#define AO_SC_ACPU_VOTE_MSK0 (AO_CTRL_BASE + 0x920) +#define AO_SC_ACPU_VOTE_MSK1 (AO_CTRL_BASE + 0x924) +#define AO_SC_ACPU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x928) +#define AO_SC_ACPU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x92C) +#define AO_SC_MCU_VOTEEN (AO_CTRL_BASE + 0x930) +#define AO_SC_MCU_VOTEDIS (AO_CTRL_BASE + 0x934) +#define AO_SC_MCU_VOTESTAT (AO_CTRL_BASE + 0x938) +#define AO_SC_MCU_VOTE_MSK0 (AO_CTRL_BASE + 0x940) +#define AO_SC_MCU_VOTE_MSK1 (AO_CTRL_BASE + 0x944) +#define AO_SC_MCU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x948) +#define AO_SC_MCU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x94C) +#define AO_SC_MCU_VOTE1EN (AO_CTRL_BASE + 0x960) +#define AO_SC_MCU_VOTE1DIS (AO_CTRL_BASE + 0x964) +#define AO_SC_MCU_VOTE1STAT (AO_CTRL_BASE + 0x968) +#define AO_SC_MCU_VOTE1_MSK0 (AO_CTRL_BASE + 0x970) +#define AO_SC_MCU_VOTE1_MSK1 (AO_CTRL_BASE + 0x974) +#define AO_SC_MCU_VOTE1STAT0_MSK (AO_CTRL_BASE + 0x978) +#define AO_SC_MCU_VOTE1STAT1_MSK (AO_CTRL_BASE + 0x97C) +#define AO_SC_MCU_VOTE2EN (AO_CTRL_BASE + 0x980) +#define AO_SC_MCU_VOTE2DIS (AO_CTRL_BASE + 0x984) +#define AO_SC_MCU_VOTE2STAT (AO_CTRL_BASE + 0x988) +#define AO_SC_MCU_VOTE2_MSK0 (AO_CTRL_BASE + 0x990) +#define AO_SC_MCU_VOTE2_MSK1 (AO_CTRL_BASE + 0x994) +#define AO_SC_MCU_VOTE2STAT0_MSK (AO_CTRL_BASE + 0x998) +#define AO_SC_MCU_VOTE2STAT1_MSK (AO_CTRL_BASE + 0x99C) +#define AO_SC_VOTE_CTRL (AO_CTRL_BASE + 0x9A0) +#define AO_SC_VOTE_STAT (AO_CTRL_BASE + 0x9A4) +#define AO_SC_ECONUM (AO_CTRL_BASE + 0xF00) +#define AO_SCCHIPID (AO_CTRL_BASE + 0xF10) +#define AO_SCSOCID (AO_CTRL_BASE + 0xF1C) +#define AO_SC_SOC_FPGA_RTL_DEF (AO_CTRL_BASE + 0xFE0) +#define AO_SC_SOC_FPGA_PR_DEF (AO_CTRL_BASE + 0xFE4) +#define AO_SC_SOC_FPGA_RES_DEF0 (AO_CTRL_BASE + 0xFE8) +#define AO_SC_SOC_FPGA_RES_DEF1 (AO_CTRL_BASE + 0xFEC) +#define AO_SC_XTAL_CTRL0 (AO_CTRL_BASE + 0x102) +#define AO_SC_XTAL_CTRL1 (AO_CTRL_BASE + 0x102) +#define AO_SC_XTAL_CTRL3 (AO_CTRL_BASE + 0x103) +#define AO_SC_XTAL_CTRL5 (AO_CTRL_BASE + 0x103) +#define AO_SC_XTAL_STAT0 (AO_CTRL_BASE + 0x106) +#define AO_SC_XTAL_STAT1 (AO_CTRL_BASE + 0x107) +#define AO_SC_EFUSE_CHIPID0 (AO_CTRL_BASE + 0x108) +#define AO_SC_EFUSE_CHIPID1 (AO_CTRL_BASE + 0x108) +#define AO_SC_EFUSE_SYS_CTRL (AO_CTRL_BASE + 0x108) +#define AO_SC_DEBUG_CTRL1 (AO_CTRL_BASE + 0x128) +#define AO_SC_DBG_STAT (AO_CTRL_BASE + 0x12B) +#define AO_SC_ARM_DBG_KEY0 (AO_CTRL_BASE + 0x12B) +#define AO_SC_RESERVED31 (AO_CTRL_BASE + 0x13A) +#define AO_SC_RESERVED32 (AO_CTRL_BASE + 0x13A) +#define AO_SC_RESERVED33 (AO_CTRL_BASE + 0x13A) +#define AO_SC_RESERVED34 (AO_CTRL_BASE + 0x13A) +#define AO_SC_RESERVED35 (AO_CTRL_BASE + 0x13B) +#define AO_SC_RESERVED36 (AO_CTRL_BASE + 0x13B) +#define AO_SC_RESERVED37 (AO_CTRL_BASE + 0x13B) +#define AO_SC_RESERVED38 (AO_CTRL_BASE + 0x13B) +#define AO_SC_ALWAYSON_SYS_CTRL0 (AO_CTRL_BASE + 0x148) +#define AO_SC_ALWAYSON_SYS_CTRL1 (AO_CTRL_BASE + 0x148) +#define AO_SC_ALWAYSON_SYS_CTRL2 (AO_CTRL_BASE + 0x148) +#define AO_SC_ALWAYSON_SYS_CTRL3 (AO_CTRL_BASE + 0x148) +#define AO_SC_ALWAYSON_SYS_CTRL10 (AO_CTRL_BASE + 0x14A) +#define AO_SC_ALWAYSON_SYS_CTRL11 (AO_CTRL_BASE + 0x14A) +#define AO_SC_ALWAYSON_SYS_STAT0 (AO_CTRL_BASE + 0x14C) +#define AO_SC_ALWAYSON_SYS_STAT1 (AO_CTRL_BASE + 0x14C) +#define AO_SC_ALWAYSON_SYS_STAT2 (AO_CTRL_BASE + 0x14C) +#define AO_SC_ALWAYSON_SYS_STAT3 (AO_CTRL_BASE + 0x14C) +#define AO_SC_PWUP_TIME0 (AO_CTRL_BASE + 0x188) +#define AO_SC_PWUP_TIME1 (AO_CTRL_BASE + 0x188) +#define AO_SC_PWUP_TIME2 (AO_CTRL_BASE + 0x188) +#define AO_SC_PWUP_TIME3 (AO_CTRL_BASE + 0x188) +#define AO_SC_PWUP_TIME4 (AO_CTRL_BASE + 0x189) +#define AO_SC_PWUP_TIME5 (AO_CTRL_BASE + 0x189) +#define AO_SC_PWUP_TIME6 (AO_CTRL_BASE + 0x189) +#define AO_SC_PWUP_TIME7 (AO_CTRL_BASE + 0x189) +#define AO_SC_SECURITY_CTRL1 (AO_CTRL_BASE + 0x1C0) +#define AO_SC_SYSTEST_SLICER_CNT0 (AO_CTRL_BASE + 0x890) +#define AO_SC_SYSTEST_SLICER_CNT1 (AO_CTRL_BASE + 0x894) + +#define AO_SC_SYS_CTRL0_MODE_NORMAL 0x004 +#define AO_SC_SYS_CTRL0_MODE_MASK 0x007 + +#define AO_SC_SYS_CTRL1_AARM_WD_RST_CFG (1 << 0) +#define AO_SC_SYS_CTRL1_REMAP_SRAM_AARM (1 << 1) +#define AO_SC_SYS_CTRL1_EFUSEC_REMAP (1 << 2) +#define AO_SC_SYS_CTRL1_EXT_PLL_SEL (1 << 3) +#define AO_SC_SYS_CTRL1_MCU_WDG0_RSTMCU_CFG (1 << 4) +#define AO_SC_SYS_CTRL1_USIM0_HPD_DE_BOUNCE_CFG (1 << 6) +#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_CFG (1 << 7) +#define AO_SC_SYS_CTRL1_USIM1_HPD_DE_BOUNCE_CFG (1 << 8) +#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_CFG (1 << 9) +#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG (1 << 10) +#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG1 (1 << 11) +#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_SFT (1 << 12) +#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_SFT (1 << 13) +#define AO_SC_SYS_CTRL1_MCU_CLKEN_HARDCFG (1 << 15) +#define AO_SC_SYS_CTRL1_AARM_WD_RST_CFG_MSK (1 << 16) +#define AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK (1 << 17) +#define AO_SC_SYS_CTRL1_EFUSEC_REMAP_MSK (1 << 18) +#define AO_SC_SYS_CTRL1_EXT_PLL_SEL_MSK (1 << 19) +#define AO_SC_SYS_CTRL1_MCU_WDG0_RSTMCU_CFG_MSK (1 << 20) +#define AO_SC_SYS_CTRL1_USIM0_HPD_DE_BOUNCE_CFG_MSK (1 << 22) +#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_CFG_MSK (1 << 23) +#define AO_SC_SYS_CTRL1_USIM1_HPD_DE_BOUNCE_CFG_MSK (1 << 24) +#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_CFG_MSK (1 << 25) +#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG_MSK (1 << 26) +#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG1_MSK (1 << 27) +#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_SFT_MSK (1 << 28) +#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_SFT_MSK (1 << 29) +#define AO_SC_SYS_CTRL1_MCU_CLKEN_HARDCFG_MSK (1U << 31) + +#define AO_SC_SYS_CTRL2_MCU_SFT_RST_STAT_CLEAR (1 << 26) +#define AO_SC_SYS_CTRL2_MCU_WDG0_RST_STAT_CLEAR (1 << 27) +#define AO_SC_SYS_CTRL2_TSENSOR_RST_STAT_CLEAR (1 << 28) +#define AO_SC_SYS_CTRL2_ACPU_WDG_RST_STAT_CLEAR (1 << 29) +#define AO_SC_SYS_CTRL2_MCU_WDG1_RST_STAT_CLEAR (1 << 30) +#define AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR (1U << 31) + +#define AO_SC_SYS_STAT0_MCU_RST_STAT (1 << 25) +#define AO_SC_SYS_STAT0_MCU_SOFTRST_STAT (1 << 26) +#define AO_SC_SYS_STAT0_MCU_WDGRST_STAT (1 << 27) +#define AO_SC_SYS_STAT0_TSENSOR_HARDRST_STAT (1 << 28) +#define AO_SC_SYS_STAT0_ACPU_WD_GLB_RST_STAT (1 << 29) +#define AO_SC_SYS_STAT0_CM3_WDG1_RST_STAT (1 << 30) +#define AO_SC_SYS_STAT0_GLB_SRST_STAT (1U << 31) + +#define AO_SC_SYS_STAT1_MODE_STATUS (1 << 0) +#define AO_SC_SYS_STAT1_BOOT_SEL_LOCK (1 << 16) +#define AO_SC_SYS_STAT1_FUNC_MODE_LOCK (1 << 17) +#define AO_SC_SYS_STAT1_BOOT_MODE_LOCK (1 << 19) +#define AO_SC_SYS_STAT1_FUN_JTAG_MODE_OUT (1 << 20) +#define AO_SC_SYS_STAT1_SECURITY_BOOT_FLG (1 << 27) +#define AO_SC_SYS_STAT1_EFUSE_NANDBOOT_MSK (1 << 28) +#define AO_SC_SYS_STAT1_EFUSE_NAND_BITWIDE (1 << 29) + +#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N (1 << 0) +#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N (1 << 1) +#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N (1 << 2) +#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N (1 << 3) +#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_TIMER0_N (1 << 4) +#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_TIMER1_N (1 << 5) +#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_WDT0_N (1 << 6) +#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_WDT1_N (1 << 7) +#define AO_SC_PERIPH_RSTDIS4_HRESET_IPC_S_N (1 << 8) +#define AO_SC_PERIPH_RSTDIS4_HRESET_IPC_NS_N (1 << 9) +#define AO_SC_PERIPH_RSTDIS4_PRESET_EFUSEC_N (1 << 10) +#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT0_N (1 << 12) +#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT1_N (1 << 13) +#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT2_N (1 << 14) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER0_N (1 << 15) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER1_N (1 << 16) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER2_N (1 << 17) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER3_N (1 << 18) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER4_N (1 << 19) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER5_N (1 << 20) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER6_N (1 << 21) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER7_N (1 << 22) +#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER8_N (1 << 23) +#define AO_SC_PERIPH_RSTDIS4_PRESET_UART0_N (1 << 24) +#define AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N (1 << 25) +#define AO_SC_PERIPH_RSTDIS4_RESET_RTC1_N (1 << 26) +#define AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N (1 << 27) +#define AO_SC_PERIPH_RSTDIS4_RESET_JTAG_AUTH_N (1 << 28) +#define AO_SC_PERIPH_RSTDIS4_RESET_CS_DAPB_ON_N (1 << 29) +#define AO_SC_PERIPH_RSTDIS4_MDM_SUBSYS_GLB (1 << 30) + +#define AO_SC_PERIPH_CLKEN4_HCLK_MCU (1 << 0) +#define AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP (1 << 3) +#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_TIMER0 (1 << 4) +#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_TIMER1 (1 << 5) +#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_WDT0 (1 << 6) +#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_WDT1 (1 << 7) +#define AO_SC_PERIPH_CLKEN4_HCLK_IPC_S (1 << 8) +#define AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS (1 << 9) +#define AO_SC_PERIPH_CLKEN4_PCLK_EFUSEC (1 << 10) +#define AO_SC_PERIPH_CLKEN4_PCLK_TZPC (1 << 11) +#define AO_SC_PERIPH_CLKEN4_PCLK_WDT0 (1 << 12) +#define AO_SC_PERIPH_CLKEN4_PCLK_WDT1 (1 << 13) +#define AO_SC_PERIPH_CLKEN4_PCLK_WDT2 (1 << 14) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER0 (1 << 15) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER1 (1 << 16) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER2 (1 << 17) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER3 (1 << 18) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER4 (1 << 19) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER5 (1 << 20) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER6 (1 << 21) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER7 (1 << 22) +#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER8 (1 << 23) +#define AO_SC_PERIPH_CLKEN4_CLK_UART0 (1 << 24) +#define AO_SC_PERIPH_CLKEN4_CLK_RTC0 (1 << 25) +#define AO_SC_PERIPH_CLKEN4_CLK_RTC1 (1 << 26) +#define AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI (1 << 27) +#define AO_SC_PERIPH_CLKEN4_CLK_JTAG_AUTH (1 << 28) +#define AO_SC_PERIPH_CLKEN4_CLK_CS_DAPB_ON (1 << 29) +#define AO_SC_PERIPH_CLKEN4_CLK_PDM (1 << 30) +#define AO_SC_PERIPH_CLKEN4_CLK_SSI_PAD (1U << 31) + +#define AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU (1 << 0) +#define AO_SC_PERIPH_CLKEN5_PCLK_EFUSEC_CCPU (1 << 1) +#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_CCPU (1 << 2) +#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_NS_CCPU (1 << 3) +#define AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU (1 << 16) +#define AO_SC_PERIPH_CLKEN5_PCLK_EFUSEC_MCU (1 << 17) +#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_MCU (1 << 18) +#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_NS_MCU (1 << 19) + +#define AO_SC_MCU_SUBSYS_CTRL3_RCLK_3 0x003 +#define AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK 0x007 +#define AO_SC_MCU_SUBSYS_CTRL3_CSSYS_CTRL_PROT (1 << 3) +#define AO_SC_MCU_SUBSYS_CTRL3_TCXO_AFC_OEN_CRG (1 << 4) +#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_USIM1 (1 << 8) +#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_USIM0 (1 << 9) +#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_SD (1 << 10) +#define AO_SC_MCU_SUBSYS_CTRL3_MCU_SUBSYS_CTRL3_RESERVED (1 << 11) + +#define PCLK_TIMER1 (1 << 16) +#define PCLK_TIMER0 (1 << 15) + +#endif /* HI6220_REGS_AO_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h new file mode 100644 index 0000000..77236e8 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_PERI_H +#define HI6220_REGS_PERI_H + +#define PERI_BASE 0xF7030000 + +#define PERI_SC_PERIPH_CTRL1 (PERI_BASE + 0x000) +#define PERI_SC_PERIPH_CTRL2 (PERI_BASE + 0x004) +#define PERI_SC_PERIPH_CTRL3 (PERI_BASE + 0x008) +#define PERI_SC_PERIPH_CTRL4 (PERI_BASE + 0x00c) +#define PERI_SC_PERIPH_CTRL5 (PERI_BASE + 0x010) +#define PERI_SC_PERIPH_CTRL6 (PERI_BASE + 0x014) +#define PERI_SC_PERIPH_CTRL8 (PERI_BASE + 0x018) +#define PERI_SC_PERIPH_CTRL9 (PERI_BASE + 0x01c) +#define PERI_SC_PERIPH_CTRL10 (PERI_BASE + 0x020) +#define PERI_SC_PERIPH_CTRL12 (PERI_BASE + 0x024) +#define PERI_SC_PERIPH_CTRL13 (PERI_BASE + 0x028) +#define PERI_SC_PERIPH_CTRL14 (PERI_BASE + 0x02c) + +#define PERI_SC_DDR_CTRL0 (PERI_BASE + 0x050) +#define PERI_SC_PERIPH_STAT1 (PERI_BASE + 0x094) + +#define PERI_SC_PERIPH_CLKEN0 (PERI_BASE + 0x200) +#define PERI_SC_PERIPH_CLKDIS0 (PERI_BASE + 0x204) +#define PERI_SC_PERIPH_CLKSTAT0 (PERI_BASE + 0x208) +#define PERI_SC_PERIPH_CLKEN1 (PERI_BASE + 0x210) +#define PERI_SC_PERIPH_CLKDIS1 (PERI_BASE + 0x214) +#define PERI_SC_PERIPH_CLKSTAT1 (PERI_BASE + 0x218) +#define PERI_SC_PERIPH_CLKEN2 (PERI_BASE + 0x220) +#define PERI_SC_PERIPH_CLKDIS2 (PERI_BASE + 0x224) +#define PERI_SC_PERIPH_CLKSTAT2 (PERI_BASE + 0x228) +#define PERI_SC_PERIPH_CLKEN3 (PERI_BASE + 0x230) +#define PERI_SC_PERIPH_CLKDIS3 (PERI_BASE + 0x234) +#define PERI_SC_PERIPH_CLKSTAT3 (PERI_BASE + 0x238) +#define PERI_SC_PERIPH_CLKEN8 (PERI_BASE + 0x240) +#define PERI_SC_PERIPH_CLKDIS8 (PERI_BASE + 0x244) +#define PERI_SC_PERIPH_CLKSTAT8 (PERI_BASE + 0x248) +#define PERI_SC_PERIPH_CLKEN9 (PERI_BASE + 0x250) +#define PERI_SC_PERIPH_CLKDIS9 (PERI_BASE + 0x254) +#define PERI_SC_PERIPH_CLKSTAT9 (PERI_BASE + 0x258) +#define PERI_SC_PERIPH_CLKEN10 (PERI_BASE + 0x260) +#define PERI_SC_PERIPH_CLKDIS10 (PERI_BASE + 0x264) +#define PERI_SC_PERIPH_CLKSTAT10 (PERI_BASE + 0x268) +#define PERI_SC_PERIPH_CLKEN12 (PERI_BASE + 0x270) +#define PERI_SC_PERIPH_CLKDIS12 (PERI_BASE + 0x274) +#define PERI_SC_PERIPH_CLKSTAT12 (PERI_BASE + 0x278) + +#define PERI_SC_PERIPH_RSTEN0 (PERI_BASE + 0x300) +#define PERI_SC_PERIPH_RSTDIS0 (PERI_BASE + 0x304) +#define PERI_SC_PERIPH_RSTSTAT0 (PERI_BASE + 0x308) +#define PERI_SC_PERIPH_RSTEN1 (PERI_BASE + 0x310) +#define PERI_SC_PERIPH_RSTDIS1 (PERI_BASE + 0x314) +#define PERI_SC_PERIPH_RSTSTAT1 (PERI_BASE + 0x318) +#define PERI_SC_PERIPH_RSTEN2 (PERI_BASE + 0x320) +#define PERI_SC_PERIPH_RSTDIS2 (PERI_BASE + 0x324) +#define PERI_SC_PERIPH_RSTSTAT2 (PERI_BASE + 0x328) +#define PERI_SC_PERIPH_RSTEN3 (PERI_BASE + 0x330) +#define PERI_SC_PERIPH_RSTDIS3 (PERI_BASE + 0x334) +#define PERI_SC_PERIPH_RSTSTAT3 (PERI_BASE + 0x338) +#define PERI_SC_PERIPH_RSTEN8 (PERI_BASE + 0x340) +#define PERI_SC_PERIPH_RSTDIS8 (PERI_BASE + 0x344) +#define PERI_SC_PERIPH_RSTSTAT8 (PERI_BASE + 0x338) + +#define PERI_SC_CLK_SEL0 (PERI_BASE + 0x400) +#define PERI_SC_CLKCFG8BIT1 (PERI_BASE + 0x494) +#define PERI_SC_CLKCFG8BIT2 (PERI_BASE + 0x498) +#define PERI_SC_RESERVED8_ADDR (PERI_BASE + 0xd04) + +/* PERI_SC_PERIPH_CTRL1 */ +#define PERI_CTRL1_ETR_AXI_CSYSREQ_N (1 << 0) +#define PERI_CTRL1_ETR_AXI_CSYSREQ_N (1 << 0) +#define PERI_CTRL1_HIFI_INT_MASK (1 << 1) +#define PERI_CTRL1_HIFI_ALL_INT_MASK (1 << 2) +#define PERI_CTRL1_ETR_AXI_CSYSREQ_N_MSK (1 << 16) +#define PERI_CTRL1_HIFI_INT_MASK_MSK (1 << 17) +#define PERI_CTRL1_HIFI_ALL_INT_MASK_MSK (1 << 18) + +/* PERI_SC_PERIPH_CTRL2 */ +#define PERI_CTRL2_MMC_CLK_PHASE_BYPASS_EN_MMC0 (1 << 0) +#define PERI_CTRL2_MMC_CLK_PHASE_BYPASS_EN_MMC1 (1 << 2) +#define PERI_CTRL2_NAND_SYS_MEM_SEL (1 << 6) +#define PERI_CTRL2_G3D_DDRT_AXI_SEL (1 << 7) +#define PERI_CTRL2_GU_MDM_BBP_TESTPIN_SEL (1 << 8) +#define PERI_CTRL2_CODEC_SSI_MASTER_CHECK (1 << 9) +#define PERI_CTRL2_FUNC_TEST_SOFT (1 << 12) +#define PERI_CTRL2_CSSYS_TS_ENABLE (1 << 15) +#define PERI_CTRL2_HIFI_RAMCTRL_S_EMA (1 << 16) +#define PERI_CTRL2_HIFI_RAMCTRL_S_EMAW (1 << 20) +#define PERI_CTRL2_HIFI_RAMCTRL_S_EMAS (1 << 22) +#define PERI_CTRL2_HIFI_RAMCTRL_S_RET1N (1 << 26) +#define PERI_CTRL2_HIFI_RAMCTRL_S_RET2N (1 << 27) +#define PERI_CTRL2_HIFI_RAMCTRL_S_PGEN (1 << 28) + +/* PERI_SC_PERIPH_CTRL3 */ +#define PERI_CTRL3_HIFI_DDR_HARQMEM_ADDR (1 << 0) +#define PERI_CTRL3_HIFI_HARQMEMRMP_EN (1 << 12) +#define PERI_CTRL3_HARQMEM_SYS_MED_SEL (1 << 13) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP1 (1 << 14) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP2 (1 << 16) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP3 (1 << 18) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP4 (1 << 20) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP5 (1 << 22) +#define PERI_CTRL3_SOC_AP_OCCUPY_GRP6 (1 << 24) + +/* PERI_SC_PERIPH_CTRL4 */ +#define PERI_CTRL4_PICO_FSELV (1 << 0) +#define PERI_CTRL4_FPGA_EXT_PHY_SEL (1 << 3) +#define PERI_CTRL4_PICO_REFCLKSEL (1 << 4) +#define PERI_CTRL4_PICO_SIDDQ (1 << 6) +#define PERI_CTRL4_PICO_SUSPENDM_SLEEPM (1 << 7) +#define PERI_CTRL4_PICO_OGDISABLE (1 << 8) +#define PERI_CTRL4_PICO_COMMONONN (1 << 9) +#define PERI_CTRL4_PICO_VBUSVLDEXT (1 << 10) +#define PERI_CTRL4_PICO_VBUSVLDEXTSEL (1 << 11) +#define PERI_CTRL4_PICO_VATESTENB (1 << 12) +#define PERI_CTRL4_PICO_SUSPENDM (1 << 14) +#define PERI_CTRL4_PICO_SLEEPM (1 << 15) +#define PERI_CTRL4_BC11_C (1 << 16) +#define PERI_CTRL4_BC11_B (1 << 17) +#define PERI_CTRL4_BC11_A (1 << 18) +#define PERI_CTRL4_BC11_GND (1 << 19) +#define PERI_CTRL4_BC11_FLOAT (1 << 20) +#define PERI_CTRL4_OTG_PHY_SEL (1 << 21) +#define PERI_CTRL4_USB_OTG_SS_SCALEDOWN_MODE (1 << 22) +#define PERI_CTRL4_OTG_DM_PULLDOWN (1 << 24) +#define PERI_CTRL4_OTG_DP_PULLDOWN (1 << 25) +#define PERI_CTRL4_OTG_IDPULLUP (1 << 26) +#define PERI_CTRL4_OTG_DRVBUS (1 << 27) +#define PERI_CTRL4_OTG_SESSEND (1 << 28) +#define PERI_CTRL4_OTG_BVALID (1 << 29) +#define PERI_CTRL4_OTG_AVALID (1 << 30) +#define PERI_CTRL4_OTG_VBUSVALID (1U << 31) + +/* PERI_SC_PERIPH_CTRL5 */ +#define PERI_CTRL5_USBOTG_RES_SEL (1 << 3) +#define PERI_CTRL5_PICOPHY_ACAENB (1 << 4) +#define PERI_CTRL5_PICOPHY_BC_MODE (1 << 5) +#define PERI_CTRL5_PICOPHY_CHRGSEL (1 << 6) +#define PERI_CTRL5_PICOPHY_VDATSRCEND (1 << 7) +#define PERI_CTRL5_PICOPHY_VDATDETENB (1 << 8) +#define PERI_CTRL5_PICOPHY_DCDENB (1 << 9) +#define PERI_CTRL5_PICOPHY_IDDIG (1 << 10) +#define PERI_CTRL5_DBG_MUX (1 << 11) + +/* PERI_SC_PERIPH_CTRL6 */ +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMA (1 << 0) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMAW (1 << 4) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMAS (1 << 6) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_RET1N (1 << 10) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_RET2N (1 << 11) +#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_PGEN (1 << 12) + +/* PERI_SC_PERIPH_CTRL8 */ +#define PERI_CTRL8_PICOPHY_TXRISETUNE0 (1 << 0) +#define PERI_CTRL8_PICOPHY_TXPREEMPAMPTUNE0 (1 << 2) +#define PERI_CTRL8_PICOPHY_TXRESTUNE0 (1 << 4) +#define PERI_CTRL8_PICOPHY_TXHSSVTUNE0 (1 << 6) +#define PERI_CTRL8_PICOPHY_COMPDISTUNE0 (1 << 8) +#define PERI_CTRL8_PICOPHY_TXPREEMPPULSETUNE0 (1 << 11) +#define PERI_CTRL8_PICOPHY_OTGTUNE0 (1 << 12) +#define PERI_CTRL8_PICOPHY_SQRXTUNE0 (1 << 16) +#define PERI_CTRL8_PICOPHY_TXVREFTUNE0 (1 << 20) +#define PERI_CTRL8_PICOPHY_TXFSLSTUNE0 (1 << 28) + +/* PERI_SC_PERIPH_CTRL9 */ +#define PERI_CTRL9_PICOPLY_TESTCLKEN (1 << 0) +#define PERI_CTRL9_PICOPLY_TESTDATAOUTSEL (1 << 1) +#define PERI_CTRL9_PICOPLY_TESTADDR (1 << 4) +#define PERI_CTRL9_PICOPLY_TESTDATAIN (1 << 8) + +/* + * PERI_SC_PERIPH_CLKEN0 + * PERI_SC_PERIPH_CLKDIS0 + * PERI_SC_PERIPH_CLKSTAT0 + */ +#define PERI_CLK0_MMC0 (1 << 0) +#define PERI_CLK0_MMC1 (1 << 1) +#define PERI_CLK0_MMC2 (1 << 2) +#define PERI_CLK0_NANDC (1 << 3) +#define PERI_CLK0_USBOTG (1 << 4) +#define PERI_CLK0_PICOPHY (1 << 5) +#define PERI_CLK0_PLL (1 << 6) + +/* + * PERI_SC_PERIPH_CLKEN1 + * PERI_SC_PERIPH_CLKDIS1 + * PERI_SC_PERIPH_CLKSTAT1 + */ +#define PERI_CLK1_HIFI (1 << 0) +#define PERI_CLK1_DIGACODEC (1 << 5) + +/* + * PERI_SC_PERIPH_CLKEN2 + * PERI_SC_PERIPH_CLKDIS2 + * PERI_SC_PERIPH_CLKSTAT2 + */ +#define PERI_CLK2_IPF (1 << 0) +#define PERI_CLK2_SOCP (1 << 1) +#define PERI_CLK2_DMAC (1 << 2) +#define PERI_CLK2_SECENG (1 << 3) +#define PERI_CLK2_HPM0 (1 << 5) +#define PERI_CLK2_HPM1 (1 << 6) +#define PERI_CLK2_HPM2 (1 << 7) +#define PERI_CLK2_HPM3 (1 << 8) + +/* + * PERI_SC_PERIPH_CLKEN3 + * PERI_SC_PERIPH_CLKDIS3 + * PERI_SC_PERIPH_CLKSTAT3 + */ +#define PERI_CLK3_CSSYS (1 << 0) +#define PERI_CLK3_I2C0 (1 << 1) +#define PERI_CLK3_I2C1 (1 << 2) +#define PERI_CLK3_I2C2 (1 << 3) +#define PERI_CLK3_I2C3 (1 << 4) +#define PERI_CLK3_UART1 (1 << 5) +#define PERI_CLK3_UART2 (1 << 6) +#define PERI_CLK3_UART3 (1 << 7) +#define PERI_CLK3_UART4 (1 << 8) +#define PERI_CLK3_SSP (1 << 9) +#define PERI_CLK3_PWM (1 << 10) +#define PERI_CLK3_BLPWM (1 << 11) +#define PERI_CLK3_TSENSOR (1 << 12) +#define PERI_CLK3_GPS (1 << 15) +#define PERI_CLK3_TCXO_PAD0 (1 << 16) +#define PERI_CLK3_TCXO_PAD1 (1 << 17) +#define PERI_CLK3_DAPB (1 << 18) +#define PERI_CLK3_HKADC (1 << 19) +#define PERI_CLK3_CODEC_SSI (1 << 20) +#define PERI_CLK3_TZPC_DEP (1 << 21) + +/* + * PERI_SC_PERIPH_CLKEN8 + * PERI_SC_PERIPH_CLKDIS8 + * PERI_SC_PERIPH_CLKSTAT8 + */ +#define PERI_CLK8_RS0 (1 << 0) +#define PERI_CLK8_RS2 (1 << 1) +#define PERI_CLK8_RS3 (1 << 2) +#define PERI_CLK8_MS0 (1 << 3) +#define PERI_CLK8_MS2 (1 << 5) +#define PERI_CLK8_XG2RAM0 (1 << 6) +#define PERI_CLK8_X2SRAM (1 << 7) +#define PERI_CLK8_SRAM (1 << 8) +#define PERI_CLK8_ROM (1 << 9) +#define PERI_CLK8_HARQ (1 << 10) +#define PERI_CLK8_MMU (1 << 11) +#define PERI_CLK8_DDRC (1 << 12) +#define PERI_CLK8_DDRPHY (1 << 13) +#define PERI_CLK8_DDRPHY_REF (1 << 14) +#define PERI_CLK8_X2X_SYSNOC (1 << 15) +#define PERI_CLK8_X2X_CCPU (1 << 16) +#define PERI_CLK8_DDRT (1 << 17) +#define PERI_CLK8_DDRPACK_RS (1 << 18) + +/* + * PERI_SC_PERIPH_CLKEN9 + * PERI_SC_PERIPH_CLKDIS9 + * PERI_SC_PERIPH_CLKSTAT9 + */ +#define PERI_CLK9_CARM_DAP (1 << 0) +#define PERI_CLK9_CARM_ATB (1 << 1) +#define PERI_CLK9_CARM_LBUS (1 << 2) +#define PERI_CLK9_CARM_KERNEL (1 << 3) + +/* + * PERI_SC_PERIPH_CLKEN10 + * PERI_SC_PERIPH_CLKDIS10 + * PERI_SC_PERIPH_CLKSTAT10 + */ +#define PERI_CLK10_IPF_CCPU (1 << 0) +#define PERI_CLK10_SOCP_CCPU (1 << 1) +#define PERI_CLK10_SECENG_CCPU (1 << 2) +#define PERI_CLK10_HARQ_CCPU (1 << 3) +#define PERI_CLK10_IPF_MCU (1 << 16) +#define PERI_CLK10_SOCP_MCU (1 << 17) +#define PERI_CLK10_SECENG_MCU (1 << 18) +#define PERI_CLK10_HARQ_MCU (1 << 19) + +/* + * PERI_SC_PERIPH_CLKEN12 + * PERI_SC_PERIPH_CLKDIS12 + * PERI_SC_PERIPH_CLKSTAT12 + */ +#define PERI_CLK12_HIFI_SRC (1 << 0) +#define PERI_CLK12_MMC0_SRC (1 << 1) +#define PERI_CLK12_MMC1_SRC (1 << 2) +#define PERI_CLK12_MMC2_SRC (1 << 3) +#define PERI_CLK12_SYSPLL_DIV (1 << 4) +#define PERI_CLK12_TPIU_SRC (1 << 5) +#define PERI_CLK12_MMC0_HF (1 << 6) +#define PERI_CLK12_MMC1_HF (1 << 7) +#define PERI_CLK12_PLL_TEST_SRC (1 << 8) +#define PERI_CLK12_CODEC_SOC (1 << 9) +#define PERI_CLK12_MEDIA (1 << 10) + +/* + * PERI_SC_PERIPH_RSTEN0 + * PERI_SC_PERIPH_RSTDIS0 + * PERI_SC_PERIPH_RSTSTAT0 + */ +#define PERI_RST0_MMC0 (1 << 0) +#define PERI_RST0_MMC1 (1 << 1) +#define PERI_RST0_MMC2 (1 << 2) +#define PERI_RST0_NANDC (1 << 3) +#define PERI_RST0_USBOTG_BUS (1 << 4) +#define PERI_RST0_POR_PICOPHY (1 << 5) +#define PERI_RST0_USBOTG (1 << 6) +#define PERI_RST0_USBOTG_32K (1 << 7) + +/* + * PERI_SC_PERIPH_RSTEN1 + * PERI_SC_PERIPH_RSTDIS1 + * PERI_SC_PERIPH_RSTSTAT1 + */ +#define PERI_RST1_HIFI (1 << 0) +#define PERI_RST1_DIGACODEC (1 << 5) + +/* + * PERI_SC_PERIPH_RSTEN2 + * PERI_SC_PERIPH_RSTDIS2 + * PERI_SC_PERIPH_RSTSTAT2 + */ +#define PERI_RST2_IPF (1 << 0) +#define PERI_RST2_SOCP (1 << 1) +#define PERI_RST2_DMAC (1 << 2) +#define PERI_RST2_SECENG (1 << 3) +#define PERI_RST2_ABB (1 << 4) +#define PERI_RST2_HPM0 (1 << 5) +#define PERI_RST2_HPM1 (1 << 6) +#define PERI_RST2_HPM2 (1 << 7) +#define PERI_RST2_HPM3 (1 << 8) + +/* + * PERI_SC_PERIPH_RSTEN3 + * PERI_SC_PERIPH_RSTDIS3 + * PERI_SC_PERIPH_RSTSTAT3 + */ +#define PERI_RST3_CSSYS (1 << 0) +#define PERI_RST3_I2C0 (1 << 1) +#define PERI_RST3_I2C1 (1 << 2) +#define PERI_RST3_I2C2 (1 << 3) +#define PERI_RST3_I2C3 (1 << 4) +#define PERI_RST3_UART1 (1 << 5) +#define PERI_RST3_UART2 (1 << 6) +#define PERI_RST3_UART3 (1 << 7) +#define PERI_RST3_UART4 (1 << 8) +#define PERI_RST3_SSP (1 << 9) +#define PERI_RST3_PWM (1 << 10) +#define PERI_RST3_BLPWM (1 << 11) +#define PERI_RST3_TSENSOR (1 << 12) +#define PERI_RST3_DAPB (1 << 18) +#define PERI_RST3_HKADC (1 << 19) +#define PERI_RST3_CODEC (1 << 20) + +/* + * PERI_SC_PERIPH_RSTEN8 + * PERI_SC_PERIPH_RSTDIS8 + * PERI_SC_PERIPH_RSTSTAT8 + */ +#define PERI_RST8_RS0 (1 << 0) +#define PERI_RST8_RS2 (1 << 1) +#define PERI_RST8_RS3 (1 << 2) +#define PERI_RST8_MS0 (1 << 3) +#define PERI_RST8_MS2 (1 << 5) +#define PERI_RST8_XG2RAM0 (1 << 6) +#define PERI_RST8_X2SRAM_TZMA (1 << 7) +#define PERI_RST8_SRAM (1 << 8) +#define PERI_RST8_HARQ (1 << 10) +#define PERI_RST8_DDRC (1 << 12) +#define PERI_RST8_DDRC_APB (1 << 13) +#define PERI_RST8_DDRPACK_APB (1 << 14) +#define PERI_RST8_DDRT (1 << 17) + +#endif /* HI6220_REGS_PERI_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h new file mode 100644 index 0000000..05620ea --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_PIN_H +#define HI6220_REGS_PIN_H + +#define IOMG_BASE 0xF7010000 + +#define IOMG_SD_CLK (IOMG_BASE + 0x0C) +#define IOMG_SD_CMD (IOMG_BASE + 0x10) +#define IOMG_SD_DATA0 (IOMG_BASE + 0x14) +#define IOMG_SD_DATA1 (IOMG_BASE + 0x18) +#define IOMG_SD_DATA2 (IOMG_BASE + 0x1C) +#define IOMG_SD_DATA3 (IOMG_BASE + 0x20) +#define IOMG_GPIO24 (IOMG_BASE + 0x140) + +#define IOMG_MUX_FUNC0 0 +#define IOMG_MUX_FUNC1 1 +#define IOMG_MUX_FUNC2 2 + +#define IOCG1_BASE 0xF7010800 +#define IOCG2_BASE 0xF8001800 + +#define IOCG_SD_CLK (IOCG1_BASE + 0x0C) +#define IOCG_SD_CMD (IOCG1_BASE + 0x10) +#define IOCG_SD_DATA0 (IOCG1_BASE + 0x14) +#define IOCG_SD_DATA1 (IOCG1_BASE + 0x18) +#define IOCG_SD_DATA2 (IOCG1_BASE + 0x1C) +#define IOCG_SD_DATA3 (IOCG1_BASE + 0x20) +#define IOCG_GPIO24 (IOCG1_BASE + 0x150) +#define IOCG_GPIO8 (IOCG2_BASE + 0x30) + +#define IOCG_DRIVE_8MA (2 << 4) +#define IOCG_DRIVE_10MA (3 << 4) +#define IOCG_INPUT_16MA 0x64 +#define IOCG_INPUT_12MA 0x54 +#define IOCG_PULLDOWN (1 << 1) +#define IOCG_PULLUP (1 << 0) + +#endif /* HI6220_REGS_PIN_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h new file mode 100644 index 0000000..404405b --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6220_REGS_PMCTRL_H +#define HI6220_REGS_PMCTRL_H + +#define PMCTRL_BASE 0xF7032000 + +#define PMCTRL_ACPUPLLCTRL (PMCTRL_BASE + 0x000) +#define PMCTRL_ACPUPLLFREQ (PMCTRL_BASE + 0x004) +#define PMCTRL_DDRPLL1CTRL (PMCTRL_BASE + 0x010) +#define PMCTRL_DDRPLL0CTRL (PMCTRL_BASE + 0x030) +#define PMCTRL_MEDPLLCTRL (PMCTRL_BASE + 0x038) +#define PMCTRL_ACPUPLLSEL (PMCTRL_BASE + 0x100) +#define PMCTRL_ACPUCLKDIV (PMCTRL_BASE + 0x104) +#define PMCTRL_ACPUSYSPLLCFG (PMCTRL_BASE + 0x110) +#define PMCTRL_ACPUCLKOFFCFG (PMCTRL_BASE + 0x114) +#define PMCTRL_ACPUPLLFRAC (PMCTRL_BASE + 0x134) +#define PMCTRL_ACPUPMUVOLUPTIME (PMCTRL_BASE + 0x360) +#define PMCTRL_ACPUPMUVOLDNTIME (PMCTRL_BASE + 0x364) +#define PMCTRL_ACPUVOLPMUADDR (PMCTRL_BASE + 0x368) +#define PMCTRL_ACPUVOLUPSTEP (PMCTRL_BASE + 0x36c) +#define PMCTRL_ACPUVOLDNSTEP (PMCTRL_BASE + 0x370) +#define PMCTRL_ACPUDFTVOL (PMCTRL_BASE + 0x374) +#define PMCTRL_ACPUDESTVOL (PMCTRL_BASE + 0x378) +#define PMCTRL_ACPUVOLTTIMEOUT (PMCTRL_BASE + 0x37c) + +#define PMCTRL_ACPUPLLCTRL_EN_CFG (1 << 0) + +#define PMCTRL_ACPUCLKDIV_CPUEXT_CFG_MASK (3 << 0) +#define PMCTRL_ACPUCLKDIV_DDR_CFG_MASK (3 << 8) +#define PMCTRL_ACPUCLKDIV_CPUEXT_STAT_MASK (3 << 16) +#define PMCTRL_ACPUCLKDIV_DDR_STAT_MASK (3 << 24) + +#define PMCTRL_ACPUPLLSEL_ACPUPLL_CFG (1 << 0) +#define PMCTRL_ACPUPLLSEL_ACPUPLL_STAT (1 << 1) +#define PMCTRL_ACPUPLLSEL_SYSPLL_STAT (1 << 2) + +#define PMCTRL_ACPUSYSPLL_CLKDIV_CFG_MASK 0x7 +#define PMCTRL_ACPUSYSPLL_CLKEN_CFG (1 << 4) +#define PMCTRL_ACPUSYSPLL_CLKDIV_SW (3 << 12) + +#define PMCTRL_ACPUSYSPLLCFG_SYSPLL_CLKEN (1 << 4) +#define PMCTRL_ACPUSYSPLLCFG_CLKDIV_MASK (3 << 12) + +#define PMCTRL_ACPUDESTVOL_DEST_VOL_MASK 0x7f +#define PMCTRL_ACPUDESTVOL_CURR_VOL_MASK (0x7f << 8) + +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START (0) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_END (0) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_rst_START (2) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_rst_END (2) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_time_START (4) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_time_END (27) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START (28) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_END (28) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_lock_START (29) +#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_lock_END (29) + +#define SOC_PMCTRL_ACPUPLLFRAC_ADDR(base) ((base) + (0x134)) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START (12) + +#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START (0) +#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_END (0) +#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START (1) +#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_END (1) +#define SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START (2) +#define SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_END (2) + +#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START (0) +#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_END (1) +#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START (8) +#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_END (9) +#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START (16) +#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_END (17) +#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START (24) +#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_END (25) + +#define SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START (0) +#define SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END (6) +#define SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START (8) +#define SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_END (14) + +#define SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START (0) +#define SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_END (0) + +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_cfg_START (0) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_cfg_END (2) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START (4) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_END (4) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_cfg_START (8) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_cfg_END (9) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_stat_START (16) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_stat_END (19) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_stat_START (20) +#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_stat_END (20) + +#endif /* HI6220_REGS_PMCTRL_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h new file mode 100644 index 0000000..fc991f8 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI6553_H +#define HI6553_H + +#include + +#include + +#define HI6553_DISABLE6_XO_CLK (PMUSSI_BASE + (0x036 << 2)) + +#define DISABLE6_XO_CLK_BB (1 << 0) +#define DISABLE6_XO_CLK_CONN (1 << 1) +#define DISABLE6_XO_CLK_NFC (1 << 2) +#define DISABLE6_XO_CLK_RF1 (1 << 3) +#define DISABLE6_XO_CLK_RF2 (1 << 4) + +#define HI6553_VERSION_REG (PMUSSI_BASE + (0x000 << 2)) +#define HI6553_IRQ2_MASK (PMUSSI_BASE + (0x008 << 2)) +#define HI6553_ENABLE2_LDO1_8 (PMUSSI_BASE + (0x029 << 2)) +#define HI6553_DISABLE2_LDO1_8 (PMUSSI_BASE + (0x02a << 2)) +#define HI6553_ONOFF_STATUS2_LDO1_8 (PMUSSI_BASE + (0x02b << 2)) +#define HI6553_ENABLE3_LDO9_16 (PMUSSI_BASE + (0x02c << 2)) +#define HI6553_DISABLE3_LDO9_16 (PMUSSI_BASE + (0x02d << 2)) +#define HI6553_ONOFF_STATUS3_LDO9_16 (PMUSSI_BASE + (0x02e << 2)) +#define HI6553_ENABLE4_LDO17_22 (PMUSSI_BASE + (0x02f << 2)) +#define HI6553_DISABLE4_LDO17_22 (PMUSSI_BASE + (0x030 << 2)) +#define HI6553_ONOFF_STATUS4_LDO17_22 (PMUSSI_BASE + (0x031 << 2)) +#define HI6553_PERI_EN_MARK (PMUSSI_BASE + (0x040 << 2)) +#define HI6553_BUCK2_REG1 (PMUSSI_BASE + (0x04a << 2)) +#define HI6553_BUCK2_REG5 (PMUSSI_BASE + (0x04e << 2)) +#define HI6553_BUCK2_REG6 (PMUSSI_BASE + (0x04f << 2)) +#define HI6553_BUCK3_REG3 (PMUSSI_BASE + (0x054 << 2)) +#define HI6553_BUCK3_REG5 (PMUSSI_BASE + (0x056 << 2)) +#define HI6553_BUCK3_REG6 (PMUSSI_BASE + (0x057 << 2)) +#define HI6553_BUCK4_REG2 (PMUSSI_BASE + (0x05b << 2)) +#define HI6553_BUCK4_REG5 (PMUSSI_BASE + (0x05e << 2)) +#define HI6553_BUCK4_REG6 (PMUSSI_BASE + (0x05f << 2)) +#define HI6553_CLK_TOP0 (PMUSSI_BASE + (0x063 << 2)) +#define HI6553_CLK_TOP3 (PMUSSI_BASE + (0x066 << 2)) +#define HI6553_CLK_TOP4 (PMUSSI_BASE + (0x067 << 2)) +#define HI6553_VSET_BUCK2_ADJ (PMUSSI_BASE + (0x06d << 2)) +#define HI6553_VSET_BUCK3_ADJ (PMUSSI_BASE + (0x06e << 2)) +#define HI6553_LDO7_REG_ADJ (PMUSSI_BASE + (0x078 << 2)) +#define HI6553_LDO10_REG_ADJ (PMUSSI_BASE + (0x07b << 2)) +#define HI6553_LDO15_REG_ADJ (PMUSSI_BASE + (0x080 << 2)) +#define HI6553_LDO19_REG_ADJ (PMUSSI_BASE + (0x084 << 2)) +#define HI6553_LDO20_REG_ADJ (PMUSSI_BASE + (0x085 << 2)) +#define HI6553_LDO21_REG_ADJ (PMUSSI_BASE + (0x086 << 2)) +#define HI6553_LDO22_REG_ADJ (PMUSSI_BASE + (0x087 << 2)) +#define HI6553_DR_LED_CTRL (PMUSSI_BASE + (0x098 << 2)) +#define HI6553_DR_OUT_CTRL (PMUSSI_BASE + (0x099 << 2)) +#define HI6553_DR3_ISET (PMUSSI_BASE + (0x09a << 2)) +#define HI6553_DR3_START_DEL (PMUSSI_BASE + (0x09b << 2)) +#define HI6553_DR4_ISET (PMUSSI_BASE + (0x09c << 2)) +#define HI6553_DR4_START_DEL (PMUSSI_BASE + (0x09d << 2)) +#define HI6553_DR345_TIM_CONF0 (PMUSSI_BASE + (0x0a0 << 2)) +#define HI6553_NP_REG_ADJ1 (PMUSSI_BASE + (0x0be << 2)) +#define HI6553_NP_REG_CHG (PMUSSI_BASE + (0x0c0 << 2)) +#define HI6553_BUCK01_CTRL2 (PMUSSI_BASE + (0x0d9 << 2)) +#define HI6553_BUCK0_CTRL1 (PMUSSI_BASE + (0x0dd << 2)) +#define HI6553_BUCK0_CTRL5 (PMUSSI_BASE + (0x0e1 << 2)) +#define HI6553_BUCK0_CTRL7 (PMUSSI_BASE + (0x0e3 << 2)) +#define HI6553_BUCK1_CTRL1 (PMUSSI_BASE + (0x0e8 << 2)) +#define HI6553_BUCK1_CTRL5 (PMUSSI_BASE + (0x0ec << 2)) +#define HI6553_BUCK1_CTRL7 (PMUSSI_BASE + (0x0ef << 2)) +#define HI6553_CLK19M2_600_586_EN (PMUSSI_BASE + (0x0fe << 2)) + +#define LED_START_DELAY_TIME 0x00 +#define LED_ELEC_VALUE 0x07 +#define LED_LIGHT_TIME 0xf0 +#define LED_GREEN_ENABLE (1 << 1) +#define LED_OUT_CTRL 0x00 + +#define PMU_HI6552_V300 0x30 +#define PMU_HI6552_V310 0x31 + +#endif /* HI6553_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h new file mode 100644 index 0000000..590700d --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY_DEF_H +#define HIKEY_DEF_H + +/* Always assume DDR is 1GB size. */ +#define DDR_BASE 0x0 +#define DDR_SIZE 0x40000000 + +#define DEVICE_BASE 0xF4000000 +#define DEVICE_SIZE 0x05800000 + +/* Memory location options for TSP */ +#define HIKEY_SRAM_ID 0 +#define HIKEY_DRAM_ID 1 + +/* + * DDR for OP-TEE (32MB from 0x3E00000-0x3FFFFFFF) is divided in several + * regions + * - Secure DDR (default is the top 16MB) used by OP-TEE + * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB) + * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature + * - Non-secure DDR (8MB) reserved for OP-TEE's future use + */ +#define DDR_SEC_SIZE 0x01000000 +#define DDR_SEC_BASE (DDR_BASE + DDR_SIZE - DDR_SEC_SIZE) /* 0x3F000000 */ + +#define DDR_SDP_SIZE 0x00400000 +#define DDR_SDP_BASE (DDR_SEC_BASE - 0x400000 /* align */ - \ + DDR_SDP_SIZE) + +#define SRAM_BASE 0xFFF80000 +#define SRAM_SIZE 0x00012000 + +/* + * PL011 related constants + */ +#define PL011_UART0_BASE 0xF8015000 +#define PL011_UART2_BASE 0xF7112000 +#define PL011_UART3_BASE 0xF7113000 +#define PL011_BAUDRATE 115200 +#define PL011_UART_CLK_IN_HZ 19200000 + +#define HIKEY_USB_DESC_BASE (DDR_BASE + 0x00800000) +#define HIKEY_USB_DESC_SIZE 0x00100000 +#define HIKEY_USB_DATA_BASE (DDR_BASE + 0x10000000) +#define HIKEY_USB_DATA_SIZE 0x10000000 +#define HIKEY_FB_BUFFER_BASE (HIKEY_USB_DATA_BASE) +#define HIKEY_FB_BUFFER_SIZE HIKEY_USB_DATA_SIZE +#define HIKEY_FB_DOWNLOAD_BASE (HIKEY_FB_BUFFER_BASE + \ + HIKEY_FB_BUFFER_SIZE) +#define HIKEY_FB_DOWNLOAD_SIZE HIKEY_USB_DATA_SIZE + +#define HIKEY_USB_DESC_IN_BASE (DDR_BASE + 0x00800000) +#define HIKEY_USB_DESC_IN_SIZE 0x00040000 +#define HIKEY_USB_DESC_EP0_OUT_BASE (HIKEY_USB_DESC_IN_BASE + \ + HIKEY_USB_DESC_IN_SIZE) +#define HIKEY_USB_DESC_EP0_OUT_SIZE 0x00040000 +#define HIKEY_USB_DESC_EPX_OUT_BASE (HIKEY_USB_DESC_EP0_OUT_BASE + \ + HIKEY_USB_DESC_EP0_OUT_SIZE) +#define HIKEY_USB_DESC_EPX_OUT_SIZE 0x00080000 + +#define HIKEY_MMC_DESC_BASE (DDR_BASE + 0x03000000) +#define HIKEY_MMC_DESC_SIZE 0x00100000 + +/* + * HIKEY_MMC_DATA_BASE & HIKEY_MMC_DATA_SIZE are shared between fastboot + * and eMMC driver. Since it could avoid to memory copy. + * So this SRAM region is used twice. First, it's used in BL1 as temporary + * buffer in eMMC driver. Second, it's used by MCU in BL2. The SRAM region + * needs to be clear before used in BL2. + */ +#define HIKEY_MMC_DATA_BASE (DDR_BASE + 0x10000000) +#define HIKEY_MMC_DATA_SIZE 0x20000000 +#define HIKEY_NS_IMAGE_OFFSET (DDR_BASE + 0x35000000) +#define HIKEY_BL1_MMC_DESC_BASE (SRAM_BASE) +#define HIKEY_BL1_MMC_DESC_SIZE 0x00001000 +#define HIKEY_BL1_MMC_DATA_BASE (HIKEY_BL1_MMC_DESC_BASE + \ + HIKEY_BL1_MMC_DESC_SIZE) +#define HIKEY_BL1_MMC_DATA_SIZE 0x0000B000 + +#define EMMC_BASE 0 +#define HIKEY_EMMC_RPMB_BASE (EMMC_BASE + 0) +#define HIKEY_EMMC_RPMB_MAX_SIZE (128 << 10) +#define HIKEY_EMMC_USERDATA_BASE (EMMC_BASE + 0) +#define HIKEY_EMMC_USERDATA_MAX_SIZE (4 << 30) + +/* + * GIC400 interrupt handling related constants + */ +#define IRQ_SEC_PHY_TIMER 29 +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 +#define IRQ_SEC_SGI_8 16 + +#endif /* HIKEY_DEF_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h new file mode 100644 index 0000000..4b8dc53 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY_LAYOUT_H +#define HIKEY_LAYOUT_H + +/* + * Platform memory map related constants + */ +#define XG2RAM0_BASE 0xF9800000 +#define XG2RAM0_SIZE 0x00400000 + +/* + * BL1 is stored in XG2RAM0_HIRQ that is 784KB large (0xF980_0000~0xF98C_4000). + */ +#define ONCHIPROM_PARAM_BASE (XG2RAM0_BASE + 0x700) +#define LOADER_RAM_BASE (XG2RAM0_BASE + 0x800) +#define BL1_XG2RAM0_OFFSET 0x1000 + +/* + * BL1 specific defines. + * + * Both loader and BL1_RO region stay in SRAM since they are used to simulate + * ROM. + * Loader is used to switch Hi6220 SoC from 32-bit to 64-bit mode. + * + * ++++++++++ 0xF980_0000 + * + loader + + * ++++++++++ 0xF980_1000 + * + BL1_RO + + * ++++++++++ 0xF981_8000 + * + BL1_RW + + * ++++++++++ 0xF989_8000 + */ +#define BL1_RO_BASE (XG2RAM0_BASE + BL1_XG2RAM0_OFFSET) +#define BL1_RO_LIMIT (XG2RAM0_BASE + 0x18000) +#define BL1_RW_BASE (BL1_RO_LIMIT) /* 0xf981_8000 */ +#define BL1_RW_SIZE (0x00080000) +#define BL1_RW_LIMIT (0xF9898000) + +/* + * Non-Secure BL1U specific defines. + */ +#define NS_BL1U_BASE (0xf9828000) +#define NS_BL1U_SIZE (0x00010000) +#define NS_BL1U_LIMIT (NS_BL1U_BASE + NS_BL1U_SIZE) + +/* + * BL2 specific defines. + * + * Both loader and BL2 region stay in SRAM. + * Loader is used to switch Hi6220 SoC from 32-bit to 64-bit mode. + * + * ++++++++++ 0xF980_0000 + * + loader + + * ++++++++++ 0xF980_1000 + * + BL2 + + * ++++++++++ 0xF983_0000 + */ +#define BL2_BASE (BL1_RO_BASE) /* 0xf980_1000 */ +#define BL2_LIMIT (0xF9830000) /* 0xf983_0000 */ + +/* + * SCP_BL2 specific defines. + * In HiKey, SCP_BL2 means MCU firmware. It's loaded into the temporary buffer + * at 0x0100_0000. Then BL2 will parse the sections and loaded them into + * predefined separated buffers. + */ +#define SCP_BL2_BASE (DDR_BASE + 0x01000000) +#define SCP_BL2_LIMIT (SCP_BL2_BASE + 0x00100000) +#define SCP_BL2_SIZE (SCP_BL2_LIMIT - SCP_BL2_BASE) + +/* + * BL31 specific defines. + */ +#define BL31_BASE (0xF9858000) /* 0xf985_8000 */ +#define BL31_LIMIT (0xF9898000) + +/* + * BL3-2 specific defines. + */ + +/* + * The TSP currently executes from TZC secured area of DRAM or SRAM. + */ +#define BL32_SRAM_BASE BL31_LIMIT +#define BL32_SRAM_LIMIT (BL31_LIMIT+0x80000) /* 512K */ + +#define BL32_DRAM_BASE DDR_SEC_BASE +#define BL32_DRAM_LIMIT (DDR_SEC_BASE+DDR_SEC_SIZE) + +#ifdef SPD_opteed +/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */ +#define HIKEY_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - HIKEY_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x3FC0_0000 */ +#define HIKEY_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */ +#endif + +#if (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_DRAM_ID) +#define TSP_SEC_MEM_BASE BL32_DRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE) +#define BL32_BASE BL32_DRAM_BASE +#define BL32_LIMIT BL32_DRAM_LIMIT +#elif (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_SRAM_ID) +#define TSP_SEC_MEM_BASE BL32_SRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_SRAM_LIMIT - BL32_SRAM_BASE) +#define BL32_BASE BL32_SRAM_BASE +#define BL32_LIMIT BL32_SRAM_LIMIT +#else +#error "Currently unsupported HIKEY_TSP_LOCATION_ID value" +#endif + +/* BL32 is mandatory in AArch32 */ +#ifdef __aarch64__ +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ +#endif + +#endif /* HIKEY_LAYOUT_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h new file mode 100644 index 0000000..b0c0ae8 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_IPC_H +#define HISI_IPC_H + +#define HISI_IPC_CORE_ACPU 0x0 + +#define HISI_IPC_MCU_INT_SRC_ACPU0_PD 10 +#define HISI_IPC_MCU_INT_SRC_ACPU1_PD 11 +#define HISI_IPC_MCU_INT_SRC_ACPU2_PD 12 +#define HISI_IPC_MCU_INT_SRC_ACPU3_PD 13 +#define HISI_IPC_MCU_INT_SRC_ACPU_PD 16 +#define HISI_IPC_MCU_INT_SRC_ACPU4_PD 26 +#define HISI_IPC_MCU_INT_SRC_ACPU5_PD 27 +#define HISI_IPC_MCU_INT_SRC_ACPU6_PD 28 +#define HISI_IPC_MCU_INT_SRC_ACPU7_PD 29 + +#define HISI_IPC_SEM_CPUIDLE 27 +#define HISI_IPC_INT_SRC_NUM 32 + +#define HISI_IPC_PM_ON 0 +#define HISI_IPC_PM_OFF 1 + +#define HISI_IPC_OK (0) +#define HISI_IPC_ERROR (-1) + +#define HISI_IPC_BASE_ADDR (0xF7510000) +#define HISI_IPC_CPU_RAW_INT_ADDR (0xF7510420) +#define HISI_IPC_ACPU_CTRL(i) (0xF7510800 + (i << 3)) + +void hisi_ipc_spin_lock(unsigned int signal); +void hisi_ipc_spin_unlock(unsigned int signal); +void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster); +void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster); +void hisi_ipc_psci_system_off(void); +int hisi_ipc_init(void); + +#endif /* HISI_IPC_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h new file mode 100644 index 0000000..731c51a --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_MCU_H +#define HISI_MCU_H + +#include + +extern void hisi_mcu_enable_sram(void); +extern void hisi_mcu_start_run(void); +extern int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size); + +#endif /* HISI_MCU_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h new file mode 100644 index 0000000..cbb4651 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_PWRC_H +#define HISI_PWRC_H + +#ifndef __ASSEMBLER__ + +void hisi_pwrc_set_cluster_wfi(unsigned int id); +void hisi_pwrc_set_core_bx_addr(unsigned int core, + unsigned int cluster, + uintptr_t entry_point); +void hisi_pwrc_enable_debug(unsigned int core, + unsigned int cluster); +int hisi_pwrc_setup(void); + +#endif /*__ASSEMBLER__*/ + +#endif /* HISI_PWRC_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h new file mode 100644 index 0000000..a1fad7a --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_SIP_SVC_H +#define HISI_SIP_SVC_H + +/* SMC function IDs for SiP Service queries */ + +#define HISI_SIP_SVC_CALL_COUNT 0x8200ff00 +#define HISI_SIP_SVC_UID 0x8200ff01 +/* 0x8200ff02 is reserved */ +#define HISI_SIP_SVC_VERSION 0x8200ff03 + +/* HISI SiP Service Calls version numbers */ +#define HISI_SIP_SVC_VERSION_MAJOR 0x0 +#define HISI_SIP_SVC_VERSION_MINOR 0x1 + +#endif /* HISI_SIP_SVC_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h new file mode 100644 index 0000000..f93e418 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_SRAM_MAP_H +#define HISI_SRAM_MAP_H + +/* + * SRAM Memory Region Layout + * + * +-----------------------+ + * | Low Power Mode | 7KB + * +-----------------------+ + * | Secure OS | 64KB + * +-----------------------+ + * | Software Flag | 1KB + * +-----------------------+ + * + */ + +#define SOC_SRAM_OFF_BASE_ADDR (0xFFF80000) + +/* PM Section: 7KB */ +#define SRAM_PM_ADDR (SOC_SRAM_OFF_BASE_ADDR) +#define SRAM_PM_SIZE (0x00001C00) + +/* TEE OS Section: 64KB */ +#define SRAM_TEEOS_ADDR (SRAM_PM_ADDR + SRAM_PM_SIZE) +#define SRAM_TEEOS_SIZE (0x00010000) + +/* General Use Section: 1KB */ +#define SRAM_GENERAL_ADDR (SRAM_TEEOS_ADDR + SRAM_TEEOS_SIZE) +#define SRAM_GENERAL_SIZE (0x00000400) + +/* + * General Usage Section Layout: + * + * +-----------------------+ + * | AP boot flag | 64B + * +-----------------------+ + * | DICC flag | 32B + * +-----------------------+ + * | Soft flag | 256B + * +-----------------------+ + * | Thermal flag | 128B + * +-----------------------+ + * | CSHELL | 4B + * +-----------------------+ + * | Uart Switching | 4B + * +-----------------------+ + * | ICC | 1024B + * +-----------------------+ + * | Memory Management | 1024B + * +-----------------------+ + * | IFC | 32B + * +-----------------------+ + * | HIFI | 32B + * +-----------------------+ + * | DDR capacity | 4B + * +-----------------------+ + * | Reserved | + * +-----------------------+ + * + */ + +/* App Core Boot Flags */ +#define MEMORY_AXI_ACPU_START_ADDR (SRAM_GENERAL_ADDR) +#define MEMORY_AXI_ACPU_START_SIZE (64) + +#define MEMORY_AXI_SRESET_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0000) +#define MEMORY_AXI_SECOND_CPU_BOOT_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0004) +#define MEMORY_AXI_READY_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0008) +#define MEMORY_AXI_FASTBOOT_ENTRY_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x000C) +#define MEMORY_AXI_PD_CHARGE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0010) +#define MEMORY_AXI_DBG_ALARM_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0014) +#define MEMORY_AXI_CHIP_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0018) +#define MEMORY_AXI_BOARD_TYPE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x001C) +#define MEMORY_AXI_BOARD_ID_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0020) +#define MEMORY_AXI_CHARGETYPE_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0024) +#define MEMORY_AXI_COLD_START_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0028) +#define MEMORY_AXI_ANDROID_REBOOT_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x002C) +#define MEMORY_AXI_ACPU_WDTRST_REBOOT_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0030) +#define MEMORY_AXI_ABNRST_BITMAP_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0034) +#define MEMORY_AXI_32K_CLK_TYPE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0038) +#define AXI_MODEM_PANIC_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x003C) +#define AXI_MODEM_PANIC_FLAG (0x68697369) +#define MEMORY_AXI_ACPU_END_ADDR (AXI_MODEM_PANIC_FLAG_ADDR + 4) + +/* DICC Flags */ +#define MEMORY_AXI_DICC_ADDR (MEMORY_AXI_ACPU_START_ADDR + MEMORY_AXI_ACPU_START_SIZE) +#define MEMORY_AXI_DICC_SIZE (32) + +#define MEMORY_AXI_SOFT_FLAG_ADDR (MEMORY_AXI_DICC_ADDR + MEMORY_AXI_DICC_SIZE) +#define MEMORY_AXI_SOFT_FLAG_SIZE (256) + +/* Thermal Flags */ +#define MEMORY_AXI_TEMP_PROTECT_ADDR (MEMORY_AXI_SOFT_FLAG_ADDR + MEMORY_AXI_SOFT_FLAG_SIZE) +#define MEMORY_AXI_TEMP_PROTECT_SIZE (128) + +/* CSHELL */ +#define MEMORY_AXI_USB_CSHELL_ADDR (MEMORY_AXI_TEMP_PROTECT_ADDR + MEMORY_AXI_TEMP_PROTECT_SIZE) +#define MEMORY_AXI_USB_CSHELL_SIZE (4) + +/* Uart and A/C Shell Switch Flags */ +#define MEMORY_AXI_UART_INOUT_ADDR (MEMORY_AXI_USB_CSHELL_ADDR + MEMORY_AXI_USB_CSHELL_SIZE) +#define MEMORY_AXI_UART_INOUT_SIZE (4) + +/* IFC Flags */ +#define MEMORY_AXI_IFC_ADDR (MEMORY_AXI_UART_INOUT_ADDR + MEMORY_AXI_UART_INOUT_SIZE) +#define MEMORY_AXI_IFC_SIZE (32) + +/* HIFI Data */ +#define MEMORY_AXI_HIFI_ADDR (MEMORY_AXI_IFC_ADDR + MEMORY_AXI_IFC_SIZE) +#define MEMORY_AXI_HIFI_SIZE (32) + +/* CONFIG Flags */ +#define MEMORY_AXI_CONFIG_ADDR (MEMORY_AXI_HIFI_ADDR + MEMORY_AXI_HIFI_SIZE) +#define MEMORY_AXI_CONFIG_SIZE (32) + +/* DDR Capacity Flags */ +#define MEMORY_AXI_DDR_CAPACITY_ADDR (MEMORY_AXI_CONFIG_ADDR + MEMORY_AXI_CONFIG_SIZE) +#define MEMORY_AXI_DDR_CAPACITY_SIZE (4) + +/* USB Shell Flags */ +#define MEMORY_AXI_USB_SHELL_FLAG_ADDR (MEMORY_AXI_DDR_CAPACITY_ADDR + MEMORY_AXI_DDR_CAPACITY_SIZE) +#define MEMORY_AXI_USB_SHELL_FLAG_SIZE (4) + +/* MCU WDT Switch Flag */ +#define MEMORY_AXI_MCU_WDT_FLAG_ADDR (MEMORY_AXI_USB_SHELL_FLAG_ADDR + MEMORY_AXI_USB_SHELL_FLAG_SIZE) +#define MEMORY_AXI_MCU_WDT_FLAG_SIZE (4) + +/* TLDSP Mailbox MNTN */ +#define SRAM_DSP_MNTN_INFO_ADDR (MEMORY_AXI_MCU_WDT_FLAG_ADDR + MEMORY_AXI_MCU_WDT_FLAG_SIZE) +#define SRAM_DSP_MNTN_SIZE (32) + +/* TLDSP ARM Mailbox Protect Flag */ +#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR (SRAM_DSP_MNTN_INFO_ADDR + SRAM_DSP_MNTN_SIZE) +#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE (4) + +/* RTT Sleep Flag */ +#define SRAM_RTT_SLEEP_FLAG_ADDR (SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR + SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE) +#define SRAM_RTT_SLEEP_FLAG_SIZE (32) + +/* LDSP Awake Flag */ +#define MEMORY_AXI_LDSP_AWAKE_ADDR (SRAM_RTT_SLEEP_FLAG_ADDR + SRAM_RTT_SLEEP_FLAG_SIZE) +#define MEMORY_AXI_LDSP_AWAKE_SIZE (4) + +#define NVUPDATE_SUCCESS 0x5555AAAA +#define NVUPDATE_FAILURE 0xAAAA5555 + +/* + * Low Power Mode Region + */ +#define PWRCTRL_ACPU_ASM_SPACE_ADDR (SRAM_PM_ADDR) +#define PWRCTRL_ACPU_ASM_SPACE_SIZE (SRAM_PM_SIZE) + +#define PWRCTRL_ACPU_ASM_MEM_BASE (PWRCTRL_ACPU_ASM_SPACE_ADDR) +#define PWRCTRL_ACPU_ASM_MEM_SIZE (PWRCTRL_ACPU_ASM_SPACE_SIZE) +#define PWRCTRL_ACPU_ASM_CODE_BASE (PWRCTRL_ACPU_ASM_MEM_BASE + 0x200) +#define PWRCTRL_ACPU_ASM_DATA_BASE (PWRCTRL_ACPU_ASM_MEM_BASE + 0xE00) +#define PWRCTRL_ACPU_ASM_DATA_SIZE (0xE00) + +#define PWRCTRL_ACPU_ASM_D_C0_ADDR (PWRCTRL_ACPU_ASM_DATA_BASE) +#define PWRCTRL_ACPU_ASM_D_C0_MMU_PARA_AD (PWRCTRL_ACPU_ASM_DATA_BASE + 0) +#define PWRCTRL_ACPU_ASM_D_ARM_PARA_AD (PWRCTRL_ACPU_ASM_DATA_BASE + 0x20) + +#define PWRCTRL_ACPU_ASM_D_COMM_ADDR (PWRCTRL_ACPU_ASM_DATA_BASE + 0x700) + +#define PWRCTRL_ACPU_REBOOT (PWRCTRL_ACPU_ASM_D_COMM_ADDR) +#define PWRCTRL_ACPU_REBOOT_SIZE (0x200) +#define PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR (PWRCTRL_ACPU_REBOOT + PWRCTRL_ACPU_REBOOT_SIZE) +#define PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE (4) +#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR (PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR + PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE) +#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE (4) +#define EXCH_A_CORE_POWRCTRL_CONV_ADDR (PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR + PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE) +#define EXCH_A_CORE_POWRCTRL_CONV_SIZE (4) + +/* + * Below region memory mapping is: + * 4 + 12 + 16 + 28 + 28 + 16 + 28 + 12 + 24 + 20 + 64 + + * 4 + 4 + 4 + 4 + 12 + 4 + 4 + 4 + 4 + 16 + 4 + 0x2BC + + * 24 + 20 + 12 + 16 + */ + +#define MEMORY_AXI_CPU_IDLE_ADDR (EXCH_A_CORE_POWRCTRL_CONV_ADDR + EXCH_A_CORE_POWRCTRL_CONV_SIZE) +#define MEMORY_AXI_CPU_IDLE_SIZE (4) + +#define MEMORY_AXI_CUR_FREQ_ADDR (MEMORY_AXI_CPU_IDLE_ADDR + MEMORY_AXI_CPU_IDLE_SIZE) +#define MEMORY_AXI_CUR_FREQ_SIZE (12) + +#define MEMORY_AXI_ACPU_FREQ_VOL_ADDR (MEMORY_AXI_CUR_FREQ_ADDR + MEMORY_AXI_CUR_FREQ_SIZE) +#define MEMORY_AXI_ACPU_FREQ_VOL_SIZE (16 + 28 + 28) + +#define MEMORY_AXI_DDR_FREQ_VOL_ADDR (MEMORY_AXI_ACPU_FREQ_VOL_ADDR + MEMORY_AXI_ACPU_FREQ_VOL_SIZE) +#define MEMORY_AXI_DDR_FREQ_VOL_SIZE (16 + 28) + +#define MEMORY_AXI_ACPU_FIQ_TEST_ADDR (MEMORY_AXI_DDR_FREQ_VOL_ADDR + MEMORY_AXI_DDR_FREQ_VOL_SIZE) +#define MEMORY_AXI_ACPU_FIQ_TEST_SIZE (12) + +#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR (MEMORY_AXI_ACPU_FIQ_TEST_ADDR + MEMORY_AXI_ACPU_FIQ_TEST_SIZE) +#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE (24) + +#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR (MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE) +#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE (20) + +#define MEMORY_FREQDUMP_ADDR (MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE) +#define MEMORY_FREQDUMP_SIZE (64) + +#define MEMORY_AXI_CCPU_LOG_ADDR (MEMORY_FREQDUMP_ADDR + MEMORY_FREQDUMP_SIZE) +#define MEMORY_AXI_CCPU_LOG_SIZE (4) + +#define MEMORY_AXI_MCU_LOG_ADDR (MEMORY_AXI_CCPU_LOG_ADDR + MEMORY_AXI_CCPU_LOG_SIZE) +#define MEMORY_AXI_MCU_LOG_SIZE (4) + +#define MEMORY_AXI_SEC_CORE_BOOT_ADDR (MEMORY_AXI_MCU_LOG_ADDR + MEMORY_AXI_MCU_LOG_SIZE) +#define MEMORY_AXI_SEC_CORE_BOOT_SIZE (4) + +#define MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR (MEMORY_AXI_SEC_CORE_BOOT_ADDR + MEMORY_AXI_SEC_CORE_BOOT_SIZE) +#define MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE (0x4) + +#define POLICY_AREA_RESERVED (MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR + MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE) +#define POLICY_AREA_RESERVED_SIZE (12) + +#define DDR_POLICY_VALID_MAGIC (POLICY_AREA_RESERVED + POLICY_AREA_RESERVED_SIZE) +#define DDR_POLICY_VALID_MAGIC_SIZE (4) + +#define DDR_POLICY_MAX_NUM (DDR_POLICY_VALID_MAGIC + DDR_POLICY_VALID_MAGIC_SIZE) +#define DDR_POLICY_MAX_NUM_SIZE (4) + +#define DDR_POLICY_SUPPORT_NUM (DDR_POLICY_MAX_NUM + DDR_POLICY_MAX_NUM_SIZE) +#define DDR_POLICY_SUPPORT_NUM_SIZE (4) + +#define DDR_POLICY_CUR_POLICY (DDR_POLICY_SUPPORT_NUM + DDR_POLICY_SUPPORT_NUM_SIZE) +#define DDR_POLICY_CUR_POLICY_SIZE (4) + +#define ACPU_POLICY_VALID_MAGIC (DDR_POLICY_CUR_POLICY + DDR_POLICY_CUR_POLICY_SIZE) +#define ACPU_POLICY_VALID_MAGIC_SIZE (4) + +#define ACPU_POLICY_MAX_NUM (ACPU_POLICY_VALID_MAGIC + ACPU_POLICY_VALID_MAGIC_SIZE) +#define ACPU_POLICY_MAX_NUM_SIZE (4) + +#define ACPU_POLICY_SUPPORT_NUM (ACPU_POLICY_MAX_NUM + ACPU_POLICY_MAX_NUM_SIZE) +#define ACPU_POLICY_SUPPORT_NUM_SIZE (4) + +#define ACPU_POLICY_CUR_POLICY (ACPU_POLICY_SUPPORT_NUM + ACPU_POLICY_SUPPORT_NUM_SIZE) +#define ACPU_POLICY_CUR_POLICY_SIZE (4) + +#define LPDDR_OPTION_ADDR (ACPU_POLICY_CUR_POLICY + ACPU_POLICY_CUR_POLICY_SIZE) +#define LPDDR_OPTION_SIZE (4) + +#define MEMORY_AXI_DDR_DDL_ADDR (LPDDR_OPTION_ADDR + LPDDR_OPTION_SIZE) +#define MEMORY_AXI_DDR_DDL_SIZE (0x2BC) + +#define DDR_TEST_DFS_ADDR (MEMORY_AXI_DDR_DDL_ADDR + MEMORY_AXI_DDR_DDL_SIZE) +#define DDR_TEST_DFS_ADDR_SIZE (4) + +#define DDR_TEST_DFS_TIMES_ADDR (DDR_TEST_DFS_ADDR + DDR_TEST_DFS_ADDR_SIZE) +#define DDR_TEST_DFS_TIMES_ADDR_SIZE (4) + +#define DDR_TEST_QOS_ADDR (DDR_TEST_DFS_TIMES_ADDR + DDR_TEST_DFS_TIMES_ADDR_SIZE) +#define DDR_TEST_QOS_ADDR_SIZE (4) + +#define DDR_TEST_FUN_ADDR (DDR_TEST_QOS_ADDR + DDR_TEST_QOS_ADDR_SIZE) +#define DDR_TEST_FUN_ADDR_SIZE (4) + +#define BOARD_TYPE_ADDR (DDR_TEST_FUN_ADDR + DDR_TEST_FUN_ADDR_SIZE) +#define BOARD_ADDR_SIZE (4) +#define DDR_DFS_FREQ_ADDR (BOARD_TYPE_ADDR + BOARD_ADDR_SIZE) +#define DDR_DFS_FREQ_SIZE (4) + +#define DDR_PASR_ADDR (DDR_DFS_FREQ_ADDR + DDR_DFS_FREQ_SIZE) +#define DDR_PASR_SIZE (20) + +#define ACPU_DFS_FREQ_ADDR (DDR_PASR_ADDR + DDR_PASR_SIZE) +#define ACPU_DFS_FREQ_ADDR_SIZE (12) + +#define ACPU_CHIP_MAX_FREQ (ACPU_DFS_FREQ_ADDR + ACPU_DFS_FREQ_ADDR_SIZE) +#define ACPU_CHIP_MAX_FREQ_SIZE (4) + +#define MEMORY_MEDPLL_STATE_ADDR (ACPU_CHIP_MAX_FREQ + ACPU_CHIP_MAX_FREQ_SIZE) +#define MEMORY_MEDPLL_STATE_SIZE (8) + +#define MEMORY_CCPU_LOAD_FLAG_ADDR (MEMORY_MEDPLL_STATE_ADDR + MEMORY_MEDPLL_STATE_SIZE) +#define MEMORY_CCPU_LOAD_FLAG_SIZE (4) + + +#define ACPU_CORE_BITS_ADDR (MEMORY_CCPU_LOAD_FLAG_ADDR + MEMORY_CCPU_LOAD_FLAG_SIZE) +#define ACPU_CORE_BITS_SIZE (4) + +#define ACPU_CLUSTER_IDLE_ADDR (ACPU_CORE_BITS_ADDR + ACPU_CORE_BITS_SIZE) +#define ACPU_CLUSTER_IDLE_SIZE (4) + +#define ACPU_A53_FLAGS_ADDR (ACPU_CLUSTER_IDLE_ADDR + ACPU_CLUSTER_IDLE_SIZE) +#define ACPU_A53_FLAGS_SIZE (4) + +#define ACPU_POWER_STATE_QOS_ADDR (ACPU_A53_FLAGS_ADDR+ACPU_A53_FLAGS_SIZE) +#define ACPU_POWER_STATE_QOS_SIZE (4) + +#define ACPU_UNLOCK_CORE_FLAGS_ADDR (ACPU_POWER_STATE_QOS_ADDR+ACPU_POWER_STATE_QOS_SIZE) +#define ACPU_UNLOCK_CORE_FLAGS_SIZE (8) + +#define ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR (ACPU_UNLOCK_CORE_FLAGS_ADDR + ACPU_UNLOCK_CORE_FLAGS_SIZE) +#define ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_CORE_POWERDOWN_FLAGS_ADDR (ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR + ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE) +#define ACPU_CORE_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR (ACPU_CORE_POWERDOWN_FLAGS_ADDR + ACPU_CORE_POWERDOWN_FLAGS_SIZE) +#define ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE (4) + +#define ACPU_ARM64_FLAGA (ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR + ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE) +#define ACPU_ARM64_FLAGA_SIZE (4) + +#define ACPU_ARM64_FLAGB (ACPU_ARM64_FLAGA + ACPU_ARM64_FLAGA_SIZE) +#define ACPU_ARM64_FLAGB_SIZE (4) + +#define MCU_EXCEPTION_FLAGS_ADDR (ACPU_ARM64_FLAGB + ACPU_ARM64_FLAGB_SIZE) +#define MCU_EXCEPTION_FLAGS_SIZE (4) + +#define ACPU_MASTER_CORE_STATE_ADDR (MCU_EXCEPTION_FLAGS_ADDR + MCU_EXCEPTION_FLAGS_SIZE) +#define ACPU_MASTER_CORE_STATE_SIZE (4) + +#define PWRCTRL_AXI_RESERVED_ADDR (ACPU_MASTER_CORE_STATE_ADDR + ACPU_MASTER_CORE_STATE_SIZE) + +#endif /* HISI_SRAM_MAP_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S b/arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S new file mode 100644 index 0000000..9cd276a --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include +#include +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + +/* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + mov_imm x16, PLAT_ARM_GICD_BASE + mov_imm x17, PLAT_ARM_GICC_BASE + + /* 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 cosole */ + bl str_in_crash_buf_print + + /* Print the GICD_ISPENDR regs */ + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +2: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq 1f + bl asm_print_hex + adr x4, spacer + bl asm_print_str + ldr x4, [x7], #8 + bl asm_print_hex + adr x4, newline + bl asm_print_str + b 2b +1: + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (CCI400_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE3_CLUSTER_IX)) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (CCI400_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE4_CLUSTER_IX)) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h new file mode 100644 index 0000000..04ea71f --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include + +#include +#include /* BL memory region sizes, etc */ + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define HIKEY_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/* + * Generic platform constants + */ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x1000 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CORE_COUNT_PER_CLUSTER U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_CORE_COUNT_PER_CLUSTER) +#define PLAT_MAX_PWR_LVL (MPIDR_AFFLVL2) +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + U(1)) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 +/* eMMC RPMB and eMMC User Data */ +#define MAX_IO_BLOCK_DEVICES U(2) + +/* GIC related constants (no GICR in GIC-400) */ +#define PLAT_ARM_GICD_BASE 0xF6801000 +#define PLAT_ARM_GICC_BASE 0xF6802000 +#define PLAT_ARM_GICH_BASE 0xF6804000 +#define PLAT_ARM_GICV_BASE 0xF6806000 + +/* + * Platform specific page table and MMU setup constants + */ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) + +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) +#define MAX_XLAT_TABLES 3 +#endif + +#ifdef IMAGE_BL31 +#define MAX_XLAT_TABLES 4 +#endif + +#ifdef IMAGE_BL2 +#define MAX_XLAT_TABLES 4 +#endif + +#define MAX_MMAP_REGIONS 16 + +/* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/platform.mk b/arm-trusted-firmware/plat/hisilicon/hikey/platform.mk new file mode 100644 index 0000000..18197cf --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/platform.mk @@ -0,0 +1,168 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Non-TF Boot ROM +BL2_AT_EL3 := 1 + +# On Hikey, the TSP can execute from TZC secure area in DRAM (default) +# or SRAM. +HIKEY_TSP_RAM_LOCATION ?= dram +ifeq (${HIKEY_TSP_RAM_LOCATION}, dram) + HIKEY_TSP_RAM_LOCATION_ID = HIKEY_DRAM_ID +else ifeq (${HIKEY_TSP_RAM_LOCATION}, sram) + HIKEY_TSP_RAM_LOCATION_ID = HIKEY_SRAM_ID +else + $(error "Currently unsupported HIKEY_TSP_RAM_LOCATION value") +endif + +CONSOLE_BASE := PL011_UART3_BASE +CRASH_CONSOLE_BASE := PL011_UART3_BASE +PLAT_PARTITION_MAX_ENTRIES := 12 +PLAT_PL061_MAX_GPIOS := 160 +COLD_BOOT_SINGLE_CPU := 1 +PROGRAMMABLE_RESET_ADDRESS := 1 +ENABLE_SVE_FOR_NS := 0 + +# Process flags +$(eval $(call add_define,HIKEY_TSP_RAM_LOCATION_ID)) +$(eval $(call add_define,CONSOLE_BASE)) +$(eval $(call add_define,CRASH_CONSOLE_BASE)) +$(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) +$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) +endif + +USE_COHERENT_MEM := 1 + +PLAT_INCLUDES := -Iplat/hisilicon/hikey/include + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/hisilicon/hikey/aarch64/hikey_common.c + +BL1_SOURCES += bl1/tbbr/tbbr_img_desc.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/arm/sp804/sp804_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/mmc/mmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey/aarch64/hikey_helpers.S \ + plat/hisilicon/hikey/hikey_bl1_setup.c \ + plat/hisilicon/hikey/hikey_bl_common.c \ + plat/hisilicon/hikey/hikey_io_storage.c + +BL2_SOURCES += common/desc_image_load.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/arm/sp804/sp804_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/mmc/mmc.c \ + drivers/partition/gpt.c \ + drivers/partition/partition.c \ + drivers/synopsys/emmc/dw_mmc.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey/aarch64/hikey_helpers.S \ + plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c \ + plat/hisilicon/hikey/hikey_bl2_setup.c \ + plat/hisilicon/hikey/hikey_bl_common.c \ + plat/hisilicon/hikey/hikey_security.c \ + plat/hisilicon/hikey/hikey_ddr.c \ + plat/hisilicon/hikey/hikey_image_load.c \ + plat/hisilicon/hikey/hikey_io_storage.c \ + plat/hisilicon/hikey/hisi_dvfs.c \ + plat/hisilicon/hikey/hisi_mcu.c + +ifeq (${SPD},opteed) +BL2_SOURCES += lib/optee/optee_utils.c +endif + +HIKEY_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL31_SOURCES += drivers/arm/cci/cci.c \ + drivers/arm/sp804/sp804_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/hisilicon/hikey/aarch64/hikey_helpers.S \ + plat/hisilicon/hikey/hikey_bl31_setup.c \ + plat/hisilicon/hikey/hikey_pm.c \ + plat/hisilicon/hikey/hikey_topology.c \ + plat/hisilicon/hikey/hisi_ipc.c \ + plat/hisilicon/hikey/hisi_pwrc.c \ + plat/hisilicon/hikey/hisi_pwrc_sram.S \ + ${HIKEY_GIC_SOURCES} +ifeq (${ENABLE_PMF}, 1) +BL31_SOURCES += plat/hisilicon/hikey/hisi_sip_svc.c \ + lib/pmf/pmf_smc.c +endif + +ifneq (${TRUSTED_BOARD_BOOT},0) + +include drivers/auth/mbedtls/mbedtls_crypto.mk +include drivers/auth/mbedtls/mbedtls_x509.mk + +AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c + +BL1_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/hisilicon/hikey/hikey_tbbr.c \ + plat/hisilicon/hikey/hikey_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl1.c + +BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/hisilicon/hikey/hikey_tbbr.c \ + plat/hisilicon/hikey/hikey_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +ROT_KEY = $(BUILD_PLAT)/rot_key.pem +ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + +$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) +$(BUILD_PLAT)/bl1/hikey_rotpk.o: $(ROTPK_HASH) +$(BUILD_PLAT)/bl2/hikey_rotpk.o: $(ROTPK_HASH) + +certificates: $(ROT_KEY) +$(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + $(Q)openssl genrsa 2048 > $@ 2>/dev/null + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +# Enable workarounds for selected Cortex-A53 errata. +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +FIP_ALIGN := 512 diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c b/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c new file mode 100644 index 0000000..612a7f2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "../hikey960_def.h" +#include "../hikey960_private.h" + +#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \ + DDR_SIZE - DDR_SEC_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \ + DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_BL1_RW MAP_REGION_FLAT(BL1_RW_BASE, \ + BL1_RW_LIMIT - BL1_RW_BASE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_UFS_DATA MAP_REGION_FLAT(HIKEY960_UFS_DATA_BASE, \ + HIKEY960_UFS_DATA_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_UFS_DESC MAP_REGION_FLAT(HIKEY960_UFS_DESC_BASE, \ + HIKEY960_UFS_DESC_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Table of regions for different BL stages to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * hikey960_init_mmu_elx() will give the available subset of that, + */ +#ifdef IMAGE_BL1 +static const mmap_region_t hikey960_mmap[] = { + MAP_UFS_DATA, + MAP_BL1_RW, + MAP_UFS_DESC, + MAP_DEVICE, + {0} +}; +#endif + +#ifdef IMAGE_BL2 +static const mmap_region_t hikey960_mmap[] = { + MAP_DDR, + MAP_DEVICE, + MAP_TSP_MEM, + {0} +}; +#endif + +#ifdef IMAGE_BL31 +static const mmap_region_t hikey960_mmap[] = { + MAP_DEVICE, + MAP_TSP_MEM, + {0} +}; +#endif + +#ifdef IMAGE_BL32 +static const mmap_region_t hikey960_mmap[] = { + MAP_DEVICE, + MAP_DDR, + {0} +}; +#endif + +/* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + */ +#define HIKEY960_CONFIGURE_MMU_EL(_el) \ + void hikey960_init_mmu_el##_el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(hikey960_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(0); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +HIKEY960_CONFIGURE_MMU_EL(1) +HIKEY960_CONFIGURE_MMU_EL(3) + +unsigned long plat_get_ns_image_entrypoint(void) +{ + return NS_BL1U_BASE; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return 1920000; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S b/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S new file mode 100644 index 0000000..5381369 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "../hikey960_def.h" + + .globl plat_my_core_pos + .globl platform_mem_init + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_report_exception + .globl plat_reset_handler + .globl clr_ex + .globl nop + +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * void platform_mem_init(void); + * + * We don't need to carry out any memory initialization + * on HIKEY. The Secure RAM is accessible straight away. + * ----------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, CRASH_CONSOLE_BASE + mov_imm x1, PL011_UART_CLK_IN_HZ + mov_imm x2, PL011_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, CRASH_CONSOLE_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On HIKEY platform, it updates the LEDs + * to indicate where we are + * --------------------------------------------- + */ +func plat_report_exception + mov x8, x30 + + /* Turn on LED according to x0 (0 -- f) */ + ldr x2, =0xf7020000 + and x1, x0, #1 + str w1, [x2, #4] + and x1, x0, #2 + str w1, [x2, #8] + and x1, x0, #4 + str w1, [x2, #16] + and x1, x0, #8 + str w1, [x2, #32] + + mrs x2, currentel + and x2, x2, #0x0c + /* Check EL1 */ + cmp x2, #0x04 + beq plat_report_el1 + + adr x4, plat_err_str + bl asm_print_str + + adr x4, esr_el3_str + bl asm_print_str + + mrs x4, esr_el3 + bl asm_print_hex + + adr x4, elr_el3_str + bl asm_print_str + + mrs x4, elr_el3 + bl asm_print_hex + b plat_report_end + +plat_report_el1: + adr x4, plat_err_str + bl asm_print_str + + adr x4, esr_el1_str + bl asm_print_str + + mrs x4, esr_el1 + bl asm_print_hex + + adr x4, elr_el1_str + bl asm_print_str + + mrs x4, elr_el1 + bl asm_print_hex +plat_report_end: + mov x30, x8 + ret +endfunc plat_report_exception + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * ----------------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * void clrex(void); + * ----------------------------------------------------- + */ +func clr_ex + clrex + ret +endfunc clr_ex + + /* ----------------------------------------------------- + * void nop(void); + * ----------------------------------------------------- + */ +func nop + nop + ret +endfunc nop + +.section .rodata.rev_err_str, "aS" +plat_err_str: + .asciz "\nPlatform exception reporting:" +esr_el3_str: + .asciz "\nESR_EL3: " +elr_el3_str: + .asciz "\nELR_EL3: " +esr_el1_str: + .asciz "\nESR_EL1: " +elr_el1_str: + .asciz "\nELR_EL1: " diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c new file mode 100644 index 0000000..a6a4949 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include "../../hikey960_private.h" + +#define IPC_MBX_SOURCE_REG(m) (IPC_BASE + ((m) << 6)) +#define IPC_MBX_DSET_REG(m) (IPC_BASE + ((m) << 6) + 0x04) +#define IPC_MBX_DCLEAR_REG(m) (IPC_BASE + ((m) << 6) + 0x08) +#define IPC_MBX_DSTATUS_REG(m) (IPC_BASE + ((m) << 6) + 0x0C) +#define IPC_MBX_MODE_REG(m) (IPC_BASE + ((m) << 6) + 0x10) +#define IPC_MBX_IMASK_REG(m) (IPC_BASE + ((m) << 6) + 0x14) +#define IPC_MBX_ICLR_REG(m) (IPC_BASE + ((m) << 6) + 0x18) +#define IPC_MBX_SEND_REG(m) (IPC_BASE + ((m) << 6) + 0x1C) +#define IPC_MBX_DATA_REG(m, d) (IPC_BASE + ((m) << 6) + 0x20 + \ + ((d) * 4)) +#define IPC_CPU_IMST_REG(m) (IPC_BASE + ((m) << 3)) +#define IPC_LOCK_REG (IPC_BASE + 0xA00) +#define IPC_ACK_BIT_SHIFT (1 << 7) +#define IPC_UNLOCK_VALUE (0x1ACCE551) + +/********************************************************* + *bit[31:24]:0~AP + *bit[23:16]:0x1~A15, 0x2~A7 + *bit[15:8]:0~ON, 1~OFF + *bit[7:0]:0x3 cpu power mode + *********************************************************/ +#define IPC_CMD_TYPE(src_obj, cluster_obj, is_off, mode) \ + ((src_obj << 24) | (((cluster_obj) + 1) << 16) | (is_off << 8) | (mode)) + +/********************************************************* + *bit[15:8]:0~no idle, 1~idle + *bit[7:0]:cpux + *********************************************************/ + +#define IPC_CMD_PARA(is_idle, cpu) \ + ((is_idle << 8) | (cpu)) + +#define IPC_STATE_IDLE 0x10 + +enum src_id { + SRC_IDLE = 0, + SRC_A15 = 1 << 0, + SRC_A7 = 1 << 1, + SRC_IOM3 = 1 << 2, + SRC_LPM3 = 1 << 3 +}; + +/*lpm3's mailboxs are 13~17*/ +enum lpm3_mbox_id { + LPM3_MBX0 = 13, + LPM3_MBX1, + LPM3_MBX2, + LPM3_MBX3, + LPM3_MBX4, +}; + +static void cpu_relax(void) +{ + volatile int i; + + for (i = 0; i < 10; i++) + nop(); +} + +static inline void +hisi_ipc_clear_ack(enum src_id source, enum lpm3_mbox_id mbox) +{ + unsigned int int_status = 0; + + do { + int_status = mmio_read_32(IPC_MBX_MODE_REG(mbox)); + int_status &= 0xF0; + cpu_relax(); + } while (int_status != IPC_ACK_BIT_SHIFT); + + mmio_write_32(IPC_MBX_ICLR_REG(mbox), source); +} + +static void +hisi_ipc_send_cmd_with_ack(enum src_id source, enum lpm3_mbox_id mbox, + unsigned int cmdtype, unsigned int cmdpara) +{ + unsigned int regval; + unsigned int mask; + unsigned int state; + + mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE); + /* wait for idle and occupy */ + do { + state = mmio_read_32(IPC_MBX_MODE_REG(mbox)); + if (state == IPC_STATE_IDLE) { + mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source); + regval = mmio_read_32(IPC_MBX_SOURCE_REG(mbox)); + if (regval == source) + break; + } + cpu_relax(); + + } while (1); + + /* auto answer */ + mmio_write_32(IPC_MBX_MODE_REG(mbox), 0x1); + + mask = (~((int)source | SRC_LPM3) & 0x3F); + /* mask the other cpus */ + mmio_write_32(IPC_MBX_IMASK_REG(mbox), mask); + /* set data */ + mmio_write_32(IPC_MBX_DATA_REG(mbox, 0), cmdtype); + mmio_write_32(IPC_MBX_DATA_REG(mbox, 1), cmdpara); + /* send cmd */ + mmio_write_32(IPC_MBX_SEND_REG(mbox), source); + /* wait ack and clear */ + hisi_ipc_clear_ack(source, mbox); + + /* release mailbox */ + mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source); +} + +void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster, + enum pm_mode mode) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, cluster, mode, 0x3); + cmdpara = IPC_CMD_PARA(0, core); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster, + unsigned int affinity_level) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + if (affinity_level == 0x3) + cmdtype = IPC_CMD_TYPE(0, -1, 0x1, 0x3 + affinity_level); + else + cmdtype = IPC_CMD_TYPE(0, cluster, 0x1, 0x3 + affinity_level); + + cmdpara = IPC_CMD_PARA(1, core); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x1, 0x0); + cmdpara = IPC_CMD_PARA(0, 0); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster, + unsigned int cmd_id) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x0, 0x0); + cmdpara = cmd_id; + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +int hisi_ipc_init(void) +{ + int ret = 0; + enum lpm3_mbox_id i = LPM3_MBX0; + + mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE); + for (i = LPM3_MBX0; i <= LPM3_MBX4; i++) { + mmio_write_32(IPC_MBX_MODE_REG(i), 1); + mmio_write_32(IPC_MBX_IMASK_REG(i), + ((int)SRC_IOM3 | (int)SRC_A15 | (int)SRC_A7)); + mmio_write_32(IPC_MBX_ICLR_REG(i), SRC_A7); + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c new file mode 100644 index 0000000..91d8033 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#include <../hikey960_def.h> +#include +#include "hisi_pwrc.h" + + +/* resource lock api */ +#define RES0_LOCK_BASE (SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE)) +#define RES1_LOCK_BASE (SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE)) +#define RES2_LOCK_BASE (SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE)) + +#define LOCK_BIT (0x1 << 28) +#define LOCK_ID_MASK (0x7u << 29) +#define CPUIDLE_LOCK_ID(core) (0x6 - (core)) +#define LOCK_UNLOCK_OFFSET 0x4 +#define LOCK_STAT_OFFSET 0x8 + +#define CLUSTER0_CPUS_ONLINE_MASK (0xF << 16) +#define CLUSTER1_CPUS_ONLINE_MASK (0xF << 20) + +/* cpu hotplug flag api */ +#define SCTRL_BASE (SOC_ACPU_SCTRL_BASE_ADDR) +#define REG_SCBAKDATA3_OFFSET (SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE)) +#define REG_SCBAKDATA8_OFFSET (SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE)) +#define REG_SCBAKDATA9_OFFSET (SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE)) + +#define CPUIDLE_FLAG_REG(cluster) \ + ((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \ + REG_SCBAKDATA9_OFFSET) +#define CLUSTER_IDLE_BIT BIT(8) +#define CLUSTER_IDLE_MASK (CLUSTER_IDLE_BIT | 0x0F) + +#define AP_SUSPEND_FLAG (1 << 16) + +#define CLUSTER_PWDN_IDLE (0<<28) +#define CLUSTER_PWDN_HOTPLUG (1<<28) +#define CLUSTER_PWDN_SR (2<<28) + +#define CLUSTER0_PDC_OFFSET 0x260 +#define CLUSTER1_PDC_OFFSET 0x300 + +#define PDC_EN_OFFSET 0x0 +#define PDC_COREPWRINTEN_OFFSET 0x4 +#define PDC_COREPWRINTSTAT_OFFSET 0x8 +#define PDC_COREGICMASK_OFFSET 0xc +#define PDC_COREPOWERUP_OFFSET 0x10 +#define PDC_COREPOWERDN_OFFSET 0x14 +#define PDC_COREPOWERSTAT_OFFSET 0x18 + +#define PDC_COREPWRSTAT_MASK (0XFFFF) + +enum pdc_gic_mask { + PDC_MASK_GIC_WAKE_IRQ, + PDC_UNMASK_GIC_WAKE_IRQ +}; + +enum pdc_finish_int_mask { + PDC_DISABLE_FINISH_INT, + PDC_ENABLE_FINISH_INT +}; + +static void hisi_resource_lock(unsigned int lockid, unsigned int offset) +{ + unsigned int lock_id = (lockid << 29); + unsigned int lock_val = lock_id | LOCK_BIT; + unsigned int lock_state; + + do { + mmio_write_32(offset, lock_val); + lock_state = mmio_read_32(LOCK_STAT_OFFSET + (uintptr_t)offset); + } while ((lock_state & LOCK_ID_MASK) != lock_id); +} + +static void hisi_resource_unlock(unsigned int lockid, unsigned int offset) +{ + unsigned int lock_val = (lockid << 29) | LOCK_BIT; + + mmio_write_32((LOCK_UNLOCK_OFFSET + (uintptr_t)offset), lock_val); +} + + +static void hisi_cpuhotplug_lock(unsigned int cluster, unsigned int core) +{ + unsigned int lock_id; + + lock_id = (cluster << 2) + core; + + hisi_resource_lock(lock_id, RES2_LOCK_BASE); +} + +static void hisi_cpuhotplug_unlock(unsigned int cluster, unsigned int core) +{ + unsigned int lock_id; + + lock_id = (cluster << 2) + core; + + hisi_resource_unlock(lock_id, RES2_LOCK_BASE); +} + +/* get the resource lock */ +void hisi_cpuidle_lock(unsigned int cluster, unsigned int core) +{ + unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); + + hisi_resource_lock(CPUIDLE_LOCK_ID(core), offset); +} + +/* release the resource lock */ +void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core) +{ + unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); + + hisi_resource_unlock(CPUIDLE_LOCK_ID(core), offset); +} + +unsigned int hisi_get_cpuidle_flag(unsigned int cluster) +{ + unsigned int val; + + val = mmio_read_32(CPUIDLE_FLAG_REG(cluster)); + val &= 0xF; + + return val; +} + +void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core) +{ + mmio_setbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); +} + +void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core) +{ + mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); + +} + +int hisi_test_ap_suspend_flag(void) +{ + unsigned int val1; + unsigned int val2; + + val1 = mmio_read_32(CPUIDLE_FLAG_REG(0)); + val1 &= AP_SUSPEND_FLAG; + + val2 = mmio_read_32(CPUIDLE_FLAG_REG(1)); + val2 &= AP_SUSPEND_FLAG; + + val1 |= val2; + return (val1 != 0); +} + +void hisi_set_cluster_pwdn_flag(unsigned int cluster, + unsigned int core, unsigned int value) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val &= ~(0x3U << ((2 * cluster) + 28)); + val |= (value << (2 * cluster)); + mmio_write_32(REG_SCBAKDATA3_OFFSET, val); + + hisi_cpuhotplug_unlock(cluster, core); +} + +unsigned int hisi_get_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = val >> (16 + (cluster << 2)); + val &= 0xF; + hisi_cpuhotplug_unlock(cluster, core); + + return val; +} + +unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = val >> (16 + (cluster << 2)); + val &= 0xF; + hisi_cpuhotplug_unlock(cluster, core); + + if (val) + return 0; + else + return 1; +} + +void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int flag = BIT((cluster<<2) + core + 16); + + hisi_cpuhotplug_lock(cluster, core); + + mmio_setbits_32(REG_SCBAKDATA3_OFFSET, flag); + + hisi_cpuhotplug_unlock(cluster, core); +} + +void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int flag = BIT((cluster<<2) + core + 16); + + hisi_cpuhotplug_lock(cluster, core); + + mmio_clrbits_32(REG_SCBAKDATA3_OFFSET, flag); + + hisi_cpuhotplug_unlock(cluster, core); +} + +int cluster_is_powered_on(unsigned int cluster) +{ + unsigned int val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + int ret; + + if (cluster == 0) + ret = val & CLUSTER0_CPUS_ONLINE_MASK; + else + ret = val & CLUSTER1_CPUS_ONLINE_MASK; + + return !!ret; +} + +static void *hisi_get_pdc_addr(unsigned int cluster) +{ + void *pdc_base_addr; + uintptr_t addr; + + if (cluster == 0) + addr = SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE); + else + addr = SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE); + pdc_base_addr = (void *)addr; + + return pdc_base_addr; +} + +static unsigned int hisi_get_pdc_stat(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPOWERSTAT_OFFSET); + + return val; +} + +static int check_hotplug(unsigned int cluster, unsigned int boot_flag) +{ + unsigned int mask = 0xF; + + if (hisi_test_ap_suspend_flag() || + ((boot_flag & mask) == mask)) + return 0; + + return 1; +} + +int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core) +{ + unsigned int mask = 0xf << (core * 4); + unsigned int pdc_stat = hisi_get_pdc_stat(cluster); + unsigned int boot_flag = hisi_get_cpu_boot_flag(cluster, core); + unsigned int cpuidle_flag = hisi_get_cpuidle_flag(cluster); + + mask = (PDC_COREPWRSTAT_MASK & (~mask)); + pdc_stat &= mask; + + if ((boot_flag ^ cpuidle_flag) || pdc_stat || + check_hotplug(cluster, boot_flag)) + return 0; + else + return 1; +} + +void hisi_disable_pdc(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr, 0x0); +} + +void hisi_enable_pdc(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr, 0x1); +} + +void hisi_pdc_set_intmask(void *pdc_base_addr, + unsigned int core, + enum pdc_finish_int_mask intmask) +{ + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET); + if (intmask == PDC_ENABLE_FINISH_INT) + val |= BIT(core); + else + val &= ~BIT(core); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, val); +} + +static inline void hisi_pdc_set_gicmask(void *pdc_base_addr, + unsigned int core, + enum pdc_gic_mask gicmask) +{ + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET); + if (gicmask == PDC_MASK_GIC_WAKE_IRQ) + val |= BIT(core); + else + val &= ~BIT(core); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET, val); +} + +void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster) +{ + int i; + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + for (i = 0; i < 4; i++) + hisi_pdc_set_gicmask(pdc_base_addr, i, PDC_MASK_GIC_WAKE_IRQ); +} + +static void hisi_pdc_powerup_core(unsigned int cluster, unsigned int core, + enum pdc_gic_mask gicmask, + enum pdc_finish_int_mask intmask) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERUP_OFFSET, + BIT(core)); +} + +static void hisi_pdc_powerdn_core(unsigned int cluster, unsigned int core, + enum pdc_gic_mask gicmask, + enum pdc_finish_int_mask intmask) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_powerup_core(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerup_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_powerdn_core(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerdn_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_powerup_cluster(unsigned int cluster, unsigned int core) +{ + hisi_ipc_pm_on_off(core, cluster, PM_ON); +} + +void hisi_powerdn_cluster(unsigned int cluster, unsigned int core) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_HOTPLUG); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, + (0x10001 << core)); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_enter_core_idle(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerdn_core(cluster, core, PDC_UNMASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_IDLE); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, + (0x10001 << core)); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core) +{ + hisi_ipc_pm_suspend(core, cluster, 0x3); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h new file mode 100644 index 0000000..e0cb381 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_PWRC_H +#define HISI_PWRC_H + +#include +#include + +#define PCTRL_BASE (PCTRL_REG_BASE) +#define CRG_BASE (CRG_REG_BASE) + +#define SOC_CRGPERIPH_A53_PDCEN_ADDR(base) ((base) + (0x260)) +#define SOC_CRGPERIPH_MAIA_PDCEN_ADDR(base) ((base) + (0x300)) + +#define SOC_PCTRL_RESOURCE0_LOCK_ADDR(base) ((base) + (0x400)) +#define SOC_PCTRL_RESOURCE0_UNLOCK_ADDR(base) ((base) + (0x404)) +#define SOC_PCTRL_RESOURCE0_LOCK_ST_ADDR(base) ((base) + (0x408)) +#define SOC_PCTRL_RESOURCE1_LOCK_ADDR(base) ((base) + (0x40C)) +#define SOC_PCTRL_RESOURCE1_UNLOCK_ADDR(base) ((base) + (0x410)) +#define SOC_PCTRL_RESOURCE1_LOCK_ST_ADDR(base) ((base) + (0x414)) +#define SOC_PCTRL_RESOURCE2_LOCK_ADDR(base) ((base) + (0x418)) + +#define SOC_SCTRL_SCBAKDATA3_ADDR(base) ((base) + (0x418)) +#define SOC_SCTRL_SCBAKDATA8_ADDR(base) ((base) + (0x42C)) +#define SOC_SCTRL_SCBAKDATA9_ADDR(base) ((base) + (0x430)) + +#define SOC_ACPU_SCTRL_BASE_ADDR (0xFFF0A000) + +void hisi_cpuidle_lock(unsigned int cluster, unsigned int core); +void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core); +void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core); +void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core); +void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core); +void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core); +int cluster_is_powered_on(unsigned int cluster); +void hisi_enter_core_idle(unsigned int cluster, unsigned int core); +void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core); +int hisi_test_ap_suspend_flag(void); +void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core); + + +/* pdc api */ +void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster); +int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core); +void hisi_disable_pdc(unsigned int cluster); +void hisi_enable_pdc(unsigned int cluster); +void hisi_powerup_core(unsigned int cluster, unsigned int core); +void hisi_powerdn_core(unsigned int cluster, unsigned int core); +void hisi_powerup_cluster(unsigned int cluster, unsigned int core); +void hisi_powerdn_cluster(unsigned int cluster, unsigned int core); +unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core); + +#endif /* HISI_PWRC_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c new file mode 100644 index 0000000..0a2d062 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2017-2018, 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 +#include +#include +#include + +#include +#include "hikey960_def.h" +#include "hikey960_private.h" + +enum { + BOOT_MODE_RECOVERY = 0, + BOOT_MODE_NORMAL, + BOOT_MODE_MASK = 1, +}; + +/* + * Declarations of linker defined symbols which will help us find the layout + * of trusted RAM + */ + +/* Data structure which holds the extents of the trusted RAM for BL1 */ +static meminfo_t bl1_tzram_layout; +static console_t console; + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +const gicv2_driver_data_t hikey960_gic_data = { + .gicd_base = GICD_REG_BASE, + .gicc_base = GICC_REG_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/* + * Perform any BL1 specific platform actions. + */ +void bl1_early_platform_setup(void) +{ + unsigned int id, uart_base; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + /* Initialize the console to provide early debug support */ + console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL1_RW_BASE; + bl1_tzram_layout.total_size = BL1_RW_SIZE; + + INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, + BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */ +} + +/* + * Perform the very early platform specific architecture setup here. At the + * moment this only does basic initialization. Later architectural setup + * (bl1_arch_setup()) does not do anything platform specific. + */ +void bl1_plat_arch_setup(void) +{ + hikey960_init_mmu_el3(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL1_RO_BASE, + BL1_RO_LIMIT, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +static void hikey960_ufs_reset(void) +{ + unsigned int data, mask; + + mmio_write_32(CRG_PERDIS7_REG, 1 << 14); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + do { + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + } while (data & BIT_SYSCTRL_REF_CLOCK_EN); + /* use abb clk */ + mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); + mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); + mdelay(1); + mmio_write_32(CRG_PEREN7_REG, 1 << 14); + mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + + mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while ((data & PERI_UFS_BIT) == 0); + mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); + mdelay(1); + mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET); + /* clear SC_DIV_UFS_PERIBUS */ + mask = SC_DIV_UFS_PERIBUS << 16; + mmio_write_32(CRG_CLKDIV17_REG, mask); + /* set SC_DIV_UFSPHY_CFG(3) */ + mask = SC_DIV_UFSPHY_CFG_MASK << 16; + data = SC_DIV_UFSPHY_CFG(3); + mmio_write_32(CRG_CLKDIV16_REG, mask | data); + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; + data |= 0x39; + mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); + mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, + MASK_UFS_CLK_GATE_BYPASS); + mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); + + mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); + mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); + mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); + mdelay(1); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); + mdelay(20); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + 0x03300330); + + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while (data & PERI_UFS_BIT); +} + +static void hikey960_ufs_init(void) +{ + dw_ufs_params_t ufs_params; + + memset(&ufs_params, 0, sizeof(ufs_params)); + ufs_params.reg_base = UFS_REG_BASE; + ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; + ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; + + if ((ufs_params.flags & UFS_FLAGS_SKIPINIT) == 0) + hikey960_ufs_reset(); + dw_ufs_init(&ufs_params); +} + +/* + * Function which will perform any remaining platform-specific setup that can + * occur after the MMU and data cache have been enabled. + */ +void bl1_platform_setup(void) +{ + hikey960_clk_init(); + hikey960_pmu_init(); + hikey960_regulator_enable(); + hikey960_tzc_init(); + hikey960_peri_init(); + hikey960_ufs_init(); + hikey960_pinmux_init(); + hikey960_gpio_init(); + hikey960_io_setup(); +} + +/* + * The following function checks if Firmware update is needed, + * by checking if TOC in FIP image is valid or not. + */ +unsigned int bl1_plat_get_next_image_id(void) +{ + unsigned int mode, ret; + + mode = mmio_read_32(SCTRL_BAK_DATA0_REG); + switch (mode & BOOT_MODE_MASK) { + case BOOT_MODE_RECOVERY: + ret = NS_BL1U_IMAGE_ID; + break; + default: + WARN("Invalid boot mode is found:%d\n", mode); + panic(); + } + return ret; +} + +image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) +{ + unsigned int index = 0; + + while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) { + if (bl1_tbbr_image_descs[index].image_id == image_id) + return &bl1_tbbr_image_descs[index]; + index++; + } + + return NULL; +} + +void bl1_plat_set_ep_info(unsigned int image_id, + entry_point_info_t *ep_info) +{ + unsigned int data = 0; + uintptr_t tmp = HIKEY960_NS_TMP_OFFSET; + + if (image_id != NS_BL1U_IMAGE_ID) + panic(); + /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */ + memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET, + NS_BL1U_SIZE); + memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE); + inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); + /* Initialize the GIC driver, cpu and distributor interfaces */ + gicv2_driver_init(&hikey960_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + /* CNTFRQ is read-only in EL1 */ + write_cntfrq_el0(plat_get_syscnt_freq2()); + data = read_cpacr_el1(); + do { + data |= 3 << 20; + write_cpacr_el1(data); + data = read_cpacr_el1(); + } while ((data & (3 << 20)) != (3 << 20)); + INFO("cpacr_el1:0x%x\n", data); + + ep_info->args.arg0 = 0xffff & read_mpidr(); + ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c new file mode 100644 index 0000000..ba236d2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .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.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + 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 /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = HIKEY960_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = HIKEY960_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = NS_BL1U_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = NS_BL1U_BASE, + .image_info.image_max_size = 0x200000 /* 2MB */, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c new file mode 100644 index 0000000..c1c2a8c --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2017-2018, 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 +#include +#ifdef SPD_opteed +#include +#endif + +#include +#include "hikey960_def.h" +#include "hikey960_private.h" + +#define BL2_RW_BASE (BL_CODE_END) + +static meminfo_t bl2_el3_tzram_layout; +static console_t console; +extern int load_lpm3(void); + +enum { + BOOT_MODE_RECOVERY = 0, + BOOT_MODE_NORMAL, + BOOT_MODE_MASK = 1, +}; + +/******************************************************************************* + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int plat_hikey960_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + int i; + int *buf; + + assert(scp_bl2_image_info->image_size < SCP_BL2_SIZE); + + INFO("BL2: Initiating SCP_BL2 transfer to SCP\n"); + + INFO("BL2: SCP_BL2: 0x%lx@0x%x\n", + scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + + buf = (int *)scp_bl2_image_info->image_base; + + INFO("BL2: SCP_BL2 HEAD:\n"); + for (i = 0; i < 64; i += 4) + INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n", + buf[i], buf[i+1], buf[i+2], buf[i+3]); + + buf = (int *)(scp_bl2_image_info->image_base + + scp_bl2_image_info->image_size - 256); + + INFO("BL2: SCP_BL2 TAIL:\n"); + for (i = 0; i < 64; i += 4) + INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n", + buf[i], buf[i+1], buf[i+2], buf[i+3]); + + INFO("BL2: SCP_BL2 transferred to SCP\n"); + + load_lpm3(); + (void)buf; + + return 0; +} + +static void hikey960_ufs_reset(void) +{ + unsigned int data, mask; + + mmio_write_32(CRG_PERDIS7_REG, 1 << 14); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + do { + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + } while (data & BIT_SYSCTRL_REF_CLOCK_EN); + /* use abb clk */ + mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); + mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); + mdelay(1); + mmio_write_32(CRG_PEREN7_REG, 1 << 14); + mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + + mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while ((data & PERI_UFS_BIT) == 0); + mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); + mdelay(1); + mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET); + /* clear SC_DIV_UFS_PERIBUS */ + mask = SC_DIV_UFS_PERIBUS << 16; + mmio_write_32(CRG_CLKDIV17_REG, mask); + /* set SC_DIV_UFSPHY_CFG(3) */ + mask = SC_DIV_UFSPHY_CFG_MASK << 16; + data = SC_DIV_UFSPHY_CFG(3); + mmio_write_32(CRG_CLKDIV16_REG, mask | data); + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; + data |= 0x39; + mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); + mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, + MASK_UFS_CLK_GATE_BYPASS); + mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); + + mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); + mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); + mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); + mdelay(1); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); + mdelay(20); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + 0x03300330); + + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while (data & PERI_UFS_BIT); +} + +static void hikey960_init_ufs(void) +{ + dw_ufs_params_t ufs_params; + + memset(&ufs_params, 0, sizeof(ufs_params_t)); + ufs_params.reg_base = UFS_REG_BASE; + ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; + ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; + hikey960_ufs_reset(); + dw_ufs_init(&ufs_params); +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t hikey960_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL3-2 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifdef __aarch64__ +uint32_t hikey960_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +uint32_t hikey960_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* __aarch64__ */ + +int hikey960_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif + assert(bl_mem_params); + + switch (image_id) { +#ifdef __aarch64__ + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } +#endif + bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl32_entry(); + break; +#endif + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl33_entry(); + break; + +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = plat_hikey960_bl2_handle_scp_bl2(&bl_mem_params->image_info); + if (err) { + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + } + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * 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) +{ + return hikey960_set_fip_addr(image_id, "fip"); +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return hikey960_bl2_handle_post_image_load(image_id); +} + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + unsigned int id, uart_base; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + /* Initialize the console to provide early debug support */ + console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + /* + * Allow BL2 to see the whole Trusted RAM. + */ + bl2_el3_tzram_layout.total_base = BL2_RW_BASE; + bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE; +} + +void bl2_el3_plat_arch_setup(void) +{ + hikey960_init_mmu_el3(bl2_el3_tzram_layout.total_base, + bl2_el3_tzram_layout.total_size, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void bl2_platform_setup(void) +{ + /* disable WDT0 */ + if (mmio_read_32(WDT0_REG_BASE + WDT_LOCK_OFFSET) == WDT_LOCKED) { + mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, WDT_UNLOCK); + mmio_write_32(WDT0_REG_BASE + WDT_CONTROL_OFFSET, 0); + mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, 0); + } + hikey960_clk_init(); + hikey960_pmu_init(); + hikey960_regulator_enable(); + hikey960_tzc_init(); + hikey960_peri_init(); + hikey960_pinmux_init(); + hikey960_gpio_init(); + hikey960_init_ufs(); + hikey960_io_setup(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c new file mode 100644 index 0000000..f5f8ffe --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 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 +#include +#include +#include +#include + +#include +#include +#include "hikey960_def.h" +#include "hikey960_private.h" + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; +static console_t console; + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +const gicv2_driver_data_t hikey960_gic_data = { + .gicd_base = GICD_REG_BASE, + .gicc_base = GICC_REG_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +static const int cci_map[] = { + CCI400_SL_IFACE3_CLUSTER_IX, + CCI400_SL_IFACE4_CLUSTER_IX +}; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + return NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + unsigned int id, uart_base; + void *from_bl2; + + from_bl2 = (void *) arg0; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + + /* Initialize the console to provide early debug support */ + console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Initialize CCI driver */ + cci_init(CCI400_REG_BASE, cci_map, ARRAY_SIZE(cci_map)); + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (bl33_ep_info.pc == 0) + panic(); +} + +void bl31_plat_arch_setup(void) +{ + hikey960_init_mmu_el3(BL31_BASE, + BL31_LIMIT - BL31_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +static void hikey960_edma_init(void) +{ + int i; + uint32_t non_secure; + + non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC; + mmio_write_32(EDMAC_SEC_CTRL, non_secure); + + /* Channel 0 is reserved for LPM3, keep secure */ + for (i = 1; i < EDMAC_CHANNEL_NUMS; i++) { + mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18)); + } +} + +static void hikey960_iomcu_dma_init(void) +{ + int i; + uint32_t non_secure; + + non_secure = IOMCU_DMAC_SEC_CTRL_INTR_SEC | IOMCU_DMAC_SEC_CTRL_GLOBAL_SEC; + mmio_write_32(IOMCU_DMAC_SEC_CTRL, non_secure); + + /* channels 0-3 are reserved */ + for (i = 4; i < IOMCU_DMAC_CHANNEL_NUMS; i++) { + mmio_write_32(IOMCU_DMAC_AXI_CONF(i), IOMCU_DMAC_AXI_CONF_ARPROT_NS | + IOMCU_DMAC_AXI_CONF_AWPROT_NS); + } +} + +void bl31_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + gicv2_driver_init(&hikey960_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + hikey960_edma_init(); + hikey960_iomcu_dma_init(); + hikey960_gpio_init(); + + hisi_ipc_init(); +} + +#ifdef SPD_none +static uint64_t hikey_debug_fiq_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + int intr, intr_raw; + + /* Acknowledge interrupt */ + intr_raw = plat_ic_acknowledge_interrupt(); + intr = plat_ic_get_interrupt_id(intr_raw); + ERROR("Invalid interrupt: intr=%d\n", intr); + console_flush(); + panic(); + + return 0; +} +#endif + +void bl31_plat_runtime_setup(void) +{ +#ifdef SPD_none + uint32_t flags; + int32_t rc; + + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + hikey_debug_fiq_handler, + flags); + if (rc != 0) + panic(); +#endif +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c new file mode 100644 index 0000000..3c4a164 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include "hikey960_private.h" + +void hikey960_clk_init(void) +{ + /* change ldi0 sel to ppll2 */ + mmio_write_32(0xfff350b4, 0xf0002000); + /* ldi0 20' */ + mmio_write_32(0xfff350bc, 0xfc004c00); +} + +void hikey960_pmu_init(void) +{ + /* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */ + mmio_clrbits_32(PMU_SSI0_CLK_TOP_CTRL7_REG, NP_XO_ABB_DIG); +} + +static void hikey960_enable_ppll3(void) +{ + /* enable ppll3 */ + mmio_write_32(PMC_PPLL3_CTRL0_REG, 0x4904305); + mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x2300000); + mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x6300000); +} + +static void bus_idle_clear(unsigned int value) +{ + unsigned int pmc_value, value1, value2; + int timeout = 100; + + pmc_value = value << 16; + pmc_value &= ~value; + mmio_write_32(PMC_NOC_POWER_IDLEREQ_REG, pmc_value); + + for (;;) { + value1 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLEACK_REG); + value2 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLE_REG); + if (((value1 & value) == 0) && ((value2 & value) == 0)) + break; + udelay(1); + timeout--; + if (timeout <= 0) { + WARN("%s timeout\n", __func__); + break; + } + } +} + +static void set_vivobus_power_up(void) +{ + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x00020002); + mmio_write_32(CRG_PEREN0_REG, 0x00001000); +} + +static void set_dss_power_up(void) +{ + /* set edc0 133MHz = 1600MHz / 12 */ + mmio_write_32(CRG_CLKDIV5_REG, 0x003f000b); + /* set ldi0 ppl0 */ + mmio_write_32(CRG_CLKDIV3_REG, 0xf0001000); + /* set ldi0 133MHz, 1600MHz / 12 */ + mmio_write_32(CRG_CLKDIV5_REG, 0xfc002c00); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000020); + udelay(100); + /* DISP CRG */ + mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000010); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); + mmio_write_32(CRG_PEREN0_REG, 0x00002000); + mmio_write_32(CRG_PEREN3_REG, 0x0003b000); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x0003b000); + mmio_write_32(CRG_PERDIS0_REG, 0x00002000); + mmio_write_32(CRG_CLKDIV18_REG, 0x01400000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000040); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000006); + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000c00); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); + mmio_write_32(CRG_PEREN0_REG, 0x00002000); + mmio_write_32(CRG_PEREN3_REG, 0x0003b000); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_DSS); + /* set edc0 400MHz for 2K 1600MHz / 4 */ + mmio_write_32(CRG_CLKDIV5_REG, 0x003f0003); + /* set ldi 266MHz, 1600MHz / 6 */ + mmio_write_32(CRG_CLKDIV5_REG, 0xfc001400); +} + +static void set_vcodec_power_up(void) +{ + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x00040004); + mmio_write_32(CRG_PEREN0_REG, 0x00000060); + mmio_write_32(CRG_PEREN2_REG, 0x10000000); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS0_REG, 0x00000018); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VCODEC); +} + +static void set_vdec_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000004); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); + mmio_write_32(CRG_PEREN2_REG, 0x20080000); + mmio_write_32(CRG_PEREN3_REG, 0x00000800); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x00000800); + mmio_write_32(CRG_PERDIS2_REG, 0x20080000); + mmio_write_32(CRG_CLKDIV18_REG, 0x80000000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000004); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000200); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); + mmio_write_32(CRG_PEREN2_REG, 0x20080000); + mmio_write_32(CRG_PEREN3_REG, 0x00000800); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VDEC); +} + +static void set_venc_power_up(void) +{ + /* set venc ppll3 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x18001000); + /* set venc 258MHz, 1290MHz / 5 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x07c00100); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000002); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); + mmio_write_32(CRG_PEREN2_REG, 0x40000100); + mmio_write_32(CRG_PEREN3_REG, 0x00000400); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x00000400); + mmio_write_32(CRG_PERDIS2_REG, 0x40000100); + mmio_write_32(CRG_CLKDIV19_REG, 0x00010000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000002); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); + mmio_write_32(CRG_PEREN2_REG, 0x40000100); + mmio_write_32(CRG_PEREN3_REG, 0x00000400); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VENC); + /* set venc 645MHz, 1290MHz / 2 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x07c00040); +} + +static void set_isp_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000001); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); + mmio_write_32(CRG_PEREN5_REG, 0x01000010); + mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS5_REG, 0x01000010); + mmio_write_32(CRG_PERDIS3_REG, 0x0bf00000); + mmio_write_32(CRG_CLKDIV18_REG, 0x70000000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000001); + /* unreset */ + mmio_write_32(CRG_ISP_SEC_RSTDIS_REG, 0x0000002f); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); + mmio_write_32(CRG_PEREN5_REG, 0x01000010); + mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_ISP); + /* csi clk enable */ + mmio_write_32(CRG_PEREN3_REG, 0x00700000); +} + +static void set_ivp_power_up(void) +{ + /* set ivp ppll0 */ + mmio_write_32(CRG_CLKDIV0_REG, 0xc0000000); + /* set ivp 267MHz, 1600MHz / 6 */ + mmio_write_32(CRG_CLKDIV0_REG, 0x3c001400); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00200000); + udelay(100); + /* IVP CRG unreset */ + mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000001); + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); + mmio_write_32(CRG_PEREN4_REG, 0x000000a8); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS4_REG, 0x000000a8); + mmio_write_32(CRG_CLKDIV20_REG, 0x02000000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x01000000); + /* unreset */ + mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000002); + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); + mmio_write_32(CRG_PEREN4_REG, 0x000000a8); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_IVP); + /* set ivp 533MHz, 1600MHz / 3 */ + mmio_write_32(CRG_CLKDIV0_REG, 0x3c000800); +} + +static void set_audio_power_up(void) +{ + unsigned int ret; + int timeout = 100; + /* mtcmos on */ + mmio_write_32(SCTRL_SCPWREN_REG, 0x00000001); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); + mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); + mmio_write_32(CRG_PEREN0_REG, 0x04000000); + mmio_write_32(CRG_PEREN5_REG, 0x00000080); + mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); + udelay(1); + /* clk disable */ + mmio_write_32(SCTRL_SCPERDIS1_REG, 0x0000000f); + mmio_write_32(SCTRL_SCPERDIS0_REG, 0x0c000000); + mmio_write_32(CRG_PERDIS5_REG, 0x00000080); + mmio_write_32(CRG_PERDIS0_REG, 0x04000000); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010000); + mmio_write_32(CRG_CLKDIV19_REG, 0x80100000); + udelay(1); + /* iso disable */ + mmio_write_32(SCTRL_SCISODIS_REG, 0x00000001); + udelay(1); + /* unreset */ + mmio_write_32(SCTRL_PERRSTDIS1_SEC_REG, 0x00000001); + mmio_write_32(SCTRL_SCPERRSTDIS0_REG, 0x00000780); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); + mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); + mmio_write_32(CRG_PEREN0_REG, 0x04000000); + mmio_write_32(CRG_PEREN5_REG, 0x00000080); + mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); + /* bus idle clear */ + mmio_write_32(SCTRL_SCPERCTRL7_REG, 0x00040000); + for (;;) { + ret = mmio_read_32(SCTRL_SCPERSTAT6_REG); + if (((ret & (1 << 5)) == 0) && ((ret & (1 << 8)) == 0)) + break; + udelay(1); + timeout--; + if (timeout <= 0) { + WARN("%s timeout\n", __func__); + break; + } + } + mmio_write_32(ASP_CFG_MMBUF_CTRL_REG, 0x00ff0000); +} + +static void set_pcie_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(SCTRL_SCPWREN_REG, 0x00000010); + udelay(100); + /* clk enable */ + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); + mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); + mmio_write_32(CRG_PEREN7_REG, 0x000003a0); + udelay(1); + /* clk disable */ + mmio_write_32(SCTRL_SCPERDIS2_REG, 0x00104000); + mmio_write_32(CRG_PERDIS7_REG, 0x000003a0); + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000000); + udelay(1); + /* iso disable */ + mmio_write_32(SCTRL_SCISODIS_REG, 0x00000030); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x8c000000); + /* clk enable */ + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); + mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); + mmio_write_32(CRG_PEREN7_REG, 0x000003a0); +} + +static void ispfunc_enable(void) +{ + /* enable ispfunc. Otherwise powerup isp_srt causes exception. */ + mmio_write_32(0xfff35000, 0x00000008); + mmio_write_32(0xfff35460, 0xc004ffff); + mmio_write_32(0xfff35030, 0x02000000); + mdelay(10); +} + +static void isps_control_clock(int flag) +{ + unsigned int ret; + + /* flag: 0 -- disable clock, 1 -- enable clock */ + if (flag) { + ret = mmio_read_32(0xe8420364); + ret |= 1; + mmio_write_32(0xe8420364, ret); + } else { + ret = mmio_read_32(0xe8420364); + ret &= ~1; + mmio_write_32(0xe8420364, ret); + } +} + +static void set_isp_srt_power_up(void) +{ + unsigned int ret; + + ispfunc_enable(); + /* reset */ + mmio_write_32(0xe8420374, 0x00000001); + mmio_write_32(0xe8420350, 0x00000000); + mmio_write_32(0xe8420358, 0x00000000); + /* mtcmos on */ + mmio_write_32(0xfff35150, 0x00400000); + udelay(100); + /* clk enable */ + isps_control_clock(1); + udelay(1); + isps_control_clock(0); + udelay(1); + /* iso disable */ + mmio_write_32(0xfff35148, 0x08000000); + /* unreset */ + ret = mmio_read_32(0xe8420374); + ret &= ~0x1; + mmio_write_32(0xe8420374, ret); + /* clk enable */ + isps_control_clock(1); + /* enable clock gating for accessing csi registers */ + mmio_write_32(0xe8420010, ~0); +} + +void hikey960_regulator_enable(void) +{ + set_vivobus_power_up(); + hikey960_enable_ppll3(); + set_dss_power_up(); + set_vcodec_power_up(); + set_vdec_power_up(); + set_venc_power_up(); + set_isp_power_up(); + set_ivp_power_up(); + set_audio_power_up(); + set_pcie_power_up(); + set_isp_srt_power_up(); + + /* set ISP_CORE_CTRL_S to unsecure mode */ + mmio_write_32(0xe8583800, 0x7); + /* set ISP_SUB_CTRL_S to unsecure mode */ + mmio_write_32(0xe8583804, 0xf); +} + +void hikey960_tzc_init(void) +{ + mmio_write_32(TZC_EN0_REG, 0x7fbff066); + mmio_write_32(TZC_EN1_REG, 0xfffff5fc); + mmio_write_32(TZC_EN2_REG, 0x0007005c); + mmio_write_32(TZC_EN3_REG, 0x37030700); + mmio_write_32(TZC_EN4_REG, 0xf63fefae); + mmio_write_32(TZC_EN5_REG, 0x000410fd); + mmio_write_32(TZC_EN6_REG, 0x0063ff68); + mmio_write_32(TZC_EN7_REG, 0x030000f3); + mmio_write_32(TZC_EN8_REG, 0x00000007); +} + +void hikey960_peri_init(void) +{ + /* unreset */ + mmio_setbits_32(CRG_PERRSTDIS4_REG, 1); +} + +void hikey960_pinmux_init(void) +{ + unsigned int id; + + hikey960_read_boardid(&id); + if (id == 5301) { + /* hikey960 hardware v2 */ + /* GPIO150: LED */ + mmio_write_32(IOMG_FIX_006_REG, 0); + /* GPIO151: LED */ + mmio_write_32(IOMG_FIX_007_REG, 0); + /* GPIO189: LED */ + mmio_write_32(IOMG_AO_011_REG, 0); + /* GPIO190: LED */ + mmio_write_32(IOMG_AO_012_REG, 0); + /* GPIO46 */ + mmio_write_32(IOMG_044_REG, 0); + /* GPIO202 */ + mmio_write_32(IOMG_AO_023_REG, 0); + /* GPIO206 */ + mmio_write_32(IOMG_AO_026_REG, 0); + /* GPIO219 - PD pullup */ + mmio_write_32(IOMG_AO_039_REG, 0); + mmio_write_32(IOCG_AO_043_REG, 1 << 0); + } + /* GPIO005 - PMU SSI, 10mA */ + mmio_write_32(IOCG_006_REG, 2 << 4); + /* GPIO213 - PCIE_CLKREQ_N */ + mmio_write_32(IOMG_AO_033_REG, 1); +} + +void hikey960_gpio_init(void) +{ + pl061_gpio_init(); + pl061_gpio_register(GPIO0_BASE, 0); + pl061_gpio_register(GPIO1_BASE, 1); + pl061_gpio_register(GPIO2_BASE, 2); + pl061_gpio_register(GPIO3_BASE, 3); + pl061_gpio_register(GPIO4_BASE, 4); + pl061_gpio_register(GPIO5_BASE, 5); + pl061_gpio_register(GPIO6_BASE, 6); + pl061_gpio_register(GPIO7_BASE, 7); + pl061_gpio_register(GPIO8_BASE, 8); + pl061_gpio_register(GPIO9_BASE, 9); + pl061_gpio_register(GPIO10_BASE, 10); + pl061_gpio_register(GPIO11_BASE, 11); + pl061_gpio_register(GPIO12_BASE, 12); + pl061_gpio_register(GPIO13_BASE, 13); + pl061_gpio_register(GPIO14_BASE, 14); + pl061_gpio_register(GPIO15_BASE, 15); + pl061_gpio_register(GPIO16_BASE, 16); + pl061_gpio_register(GPIO17_BASE, 17); + pl061_gpio_register(GPIO18_BASE, 18); + pl061_gpio_register(GPIO19_BASE, 19); + pl061_gpio_register(GPIO20_BASE, 20); + pl061_gpio_register(GPIO21_BASE, 21); + pl061_gpio_register(GPIO22_BASE, 22); + pl061_gpio_register(GPIO23_BASE, 23); + pl061_gpio_register(GPIO24_BASE, 24); + pl061_gpio_register(GPIO25_BASE, 25); + pl061_gpio_register(GPIO26_BASE, 26); + pl061_gpio_register(GPIO27_BASE, 27); + pl061_gpio_register(GPIO28_BASE, 28); + + /* PCIE_PERST_N output low */ + gpio_set_direction(89, GPIO_DIR_OUT); + gpio_set_value(89, GPIO_LEVEL_LOW); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c new file mode 100644 index 0000000..1e1126f --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include "hikey960_private.h" + +#define ADC_ADCIN0 0 +#define ADC_ADCIN1 1 +#define ADC_ADCIN2 2 + +#define HKADC_DATA_GRADE0 0 +#define HKADC_DATA_GRADE1 100 +#define HKADC_DATA_GRADE2 300 +#define HKADC_DATA_GRADE3 500 +#define HKADC_DATA_GRADE4 700 +#define HKADC_DATA_GRADE5 900 +#define HKADC_DATA_GRADE6 1100 +#define HKADC_DATA_GRADE7 1300 +#define HKADC_DATA_GRADE8 1500 +#define HKADC_DATA_GRADE9 1700 +#define HKADC_DATA_GRADE10 1800 + +#define BOARDID_VALUE0 0 +#define BOARDID_VALUE1 1 +#define BOARDID_VALUE2 2 +#define BOARDID_VALUE3 3 +#define BOARDID_VALUE4 4 +#define BOARDID_VALUE5 5 +#define BOARDID_VALUE6 6 +#define BOARDID_VALUE7 7 +#define BOARDID_VALUE8 8 +#define BOARDID_VALUE9 9 +#define BOARDID_UNKNOWN 0xF + +#define BOARDID3_BASE 5 + + +static void init_adc(void) +{ + /* reset hkadc */ + mmio_write_32(CRG_PERRSTEN2_REG, PERRSTEN2_HKADCSSI); + /* wait a few clock cycles */ + udelay(2); + mmio_write_32(CRG_PERRSTDIS2_REG, PERRSTEN2_HKADCSSI); + udelay(2); + /* enable hkadc clock */ + mmio_write_32(CRG_PERDIS2_REG, PEREN2_HKADCSSI); + udelay(2); + mmio_write_32(CRG_PEREN2_REG, PEREN2_HKADCSSI); + udelay(2); +} + +static int get_adc(unsigned int channel, unsigned int *value) +{ + unsigned int data, value1, value0; + + if (channel > HKADC_CHANNEL_MAX) { + WARN("invalid channel:%d\n", channel); + return -EFAULT; + } + /* configure the read/write operation for external HKADC */ + mmio_write_32(HKADC_WR01_DATA_REG, HKADC_WR01_VALUE | channel); + mmio_write_32(HKADC_WR23_DATA_REG, HKADC_WR23_VALUE); + mmio_write_32(HKADC_WR45_DATA_REG, HKADC_WR45_VALUE); + /* configure the number of accessing registers */ + mmio_write_32(HKADC_WR_NUM_REG, HKADC_WR_NUM_VALUE); + /* configure delay of accessing registers */ + mmio_write_32(HKADC_DELAY01_REG, HKADC_CHANNEL0_DELAY01_VALUE); + mmio_write_32(HKADC_DELAY23_REG, HKADC_DELAY23_VALUE); + + /* start HKADC */ + mmio_write_32(HKADC_DSP_START_REG, 1); + do { + data = mmio_read_32(HKADC_DSP_START_REG); + } while (data & 1); + + /* convert AD result */ + value1 = mmio_read_32(HKADC_DSP_RD2_DATA_REG) & 0xffff; + value0 = mmio_read_32(HKADC_DSP_RD3_DATA_REG) & 0xffff; + + data = ((value1 << 4) & HKADC_VALUE_HIGH) | + ((value0 >> 4) & HKADC_VALUE_LOW); + *value = data; + return 0; +} + +static int get_value(unsigned int channel, unsigned int *value) +{ + int ret; + + ret = get_adc(channel, value); + if (ret) + return ret; + + /* convert ADC value to micro-volt */ + ret = ((*value & HKADC_VALID_VALUE) * HKADC_VREF_1V8) / HKADC_ACCURACY; + *value = ret; + return 0; +} + +static int adcin_data_remap(unsigned int adcin_value) +{ + int ret; + + if (adcin_value < HKADC_DATA_GRADE1) + ret = BOARDID_VALUE0; + else if (adcin_value < HKADC_DATA_GRADE2) + ret = BOARDID_VALUE1; + else if (adcin_value < HKADC_DATA_GRADE3) + ret = BOARDID_VALUE2; + else if (adcin_value < HKADC_DATA_GRADE4) + ret = BOARDID_VALUE3; + else if (adcin_value < HKADC_DATA_GRADE5) + ret = BOARDID_VALUE4; + else if (adcin_value < HKADC_DATA_GRADE6) + ret = BOARDID_VALUE5; + else if (adcin_value < HKADC_DATA_GRADE7) + ret = BOARDID_VALUE6; + else if (adcin_value < HKADC_DATA_GRADE8) + ret = BOARDID_VALUE7; + else if (adcin_value < HKADC_DATA_GRADE9) + ret = BOARDID_VALUE8; + else if (adcin_value < HKADC_DATA_GRADE10) + ret = BOARDID_VALUE9; + else + ret = BOARDID_UNKNOWN; + return ret; +} + +int hikey960_read_boardid(unsigned int *id) +{ + unsigned int adcin0, adcin1, adcin2; + unsigned int adcin0_remap, adcin1_remap, adcin2_remap; + + assert(id != NULL); + + init_adc(); + + /* read ADC channel0 data */ + get_value(ADC_ADCIN0, &adcin0); + adcin0_remap = adcin_data_remap(adcin0); + if (adcin0_remap == BOARDID_UNKNOWN) + return -EINVAL; + /* read ADC channel1 data */ + get_value(ADC_ADCIN1, &adcin1); + adcin1_remap = adcin_data_remap(adcin1); + if (adcin1_remap == BOARDID_UNKNOWN) + return -EINVAL; + /* read ADC channel2 data */ + get_value(ADC_ADCIN2, &adcin2); + adcin2_remap = adcin_data_remap(adcin2); + if (adcin2_remap == BOARDID_UNKNOWN) + return -EINVAL; + *id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) + + (adcin1_remap * 10) + adcin0_remap; + return 0; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h new file mode 100644 index 0000000..9651d78 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY960_DEF_H +#define HIKEY960_DEF_H + +#include +#include + +#define DDR_BASE 0x0 +#define DDR_SIZE 0xE0000000 + +#define DEVICE_BASE 0xE0000000 +#define DEVICE_SIZE 0x20000000 + +/* Memory location options for TSP */ +#define HIKEY960_SRAM_ID 0 +#define HIKEY960_DRAM_ID 1 + +/* + * DDR for OP-TEE (32MB from 0x3E00000-0x3FFFFFFF) is divided in several + * regions: + * - Secure DDR (default is the top 16MB) used by OP-TEE + * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB) + * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature + * - Non-secure DDR (8MB) reserved for OP-TEE's future use + */ +#define DDR_SEC_SIZE 0x01000000 +#define DDR_SEC_BASE 0x3F000000 + +#define DDR_SDP_SIZE 0x00400000 +#define DDR_SDP_BASE (DDR_SEC_BASE - 0x400000 /* align */ - \ + DDR_SDP_SIZE) + +/* + * PL011 related constants + */ +#define PL011_UART5_BASE 0xFDF05000 +#define PL011_UART6_BASE 0xFFF32000 +#define PL011_BAUDRATE 115200 +#define PL011_UART_CLK_IN_HZ 19200000 + +#define UFS_BASE 0 + +#define HIKEY960_UFS_DESC_BASE 0x20000000 +#define HIKEY960_UFS_DESC_SIZE 0x00200000 /* 2MB */ +#define HIKEY960_UFS_DATA_BASE 0x10000000 +#define HIKEY960_UFS_DATA_SIZE 0x0A000000 /* 160MB */ + +#endif /* HIKEY960_DEF_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c new file mode 100644 index 0000000..57cb1b2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c new file mode 100644 index 0000000..e1c5845 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2017-2018, 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 +#include +#include + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const io_dev_connector_t *ufs_dev_con, *fip_dev_con; +static uintptr_t ufs_dev_handle, fip_dev_handle; + +static int check_ufs(const uintptr_t spec); +static int check_fip(const uintptr_t spec); +size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size); +size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size); + +static io_block_spec_t ufs_fip_spec; + +static const io_block_spec_t ufs_gpt_spec = { + .offset = 0, + .length = PLAT_PARTITION_BLOCK_SIZE * + (PLAT_PARTITION_MAX_ENTRIES / 4 + 2), +}; + +static const io_block_dev_spec_t ufs_dev_spec = { + /* It's used as temp buffer in block driver. */ + .buffer = { + .offset = HIKEY960_UFS_DATA_BASE, + .length = HIKEY960_UFS_DATA_SIZE, + }, + .ops = { + .read = ufs_read_lun3_blks, + .write = ufs_write_lun3_blks, + }, + .block_size = UFS_BLOCK_SIZE, +}; + +static const io_uuid_spec_t scp_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = { + .uuid = UUID_SCP_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t scp_fw_cert_uuid_spec = { + .uuid = UUID_SCP_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &ufs_dev_handle, + (uintptr_t)&ufs_fip_spec, + check_ufs + }, + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_bl2_uuid_spec, + check_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + check_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + check_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + check_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + check_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + check_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + check_fip + }, + [SCP_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_key_cert_uuid_spec, + check_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + check_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + check_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + check_fip + }, + [SCP_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_fw_cert_uuid_spec, + check_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + check_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + check_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + check_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ + [GPT_IMAGE_ID] = { + &ufs_dev_handle, + (uintptr_t)&ufs_gpt_spec, + check_ufs + }, +}; + +static int check_ufs(const uintptr_t spec) +{ + int result; + uintptr_t local_handle; + + result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(ufs_dev_handle, spec, &local_handle); + if (result == 0) + io_close(local_handle); + } + return result; +} + +static int check_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +void hikey960_io_setup(void) +{ + int result; + + result = register_io_dev_block(&ufs_dev_con); + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + + result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, + &ufs_dev_handle); + assert(result == 0); + + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); + assert(result == 0); + + /* Ignore improbable errors in release builds */ + (void)result; +} + +int hikey960_set_fip_addr(unsigned int image_id, const char *name) +{ + const partition_entry_t *entry; + + if (ufs_fip_spec.length == 0) { + partition_init(GPT_IMAGE_ID); + entry = get_partition_entry(name); + if (entry == NULL) { + ERROR("Could NOT find the %s partition!\n", name); + return -ENOENT; + } + ufs_fip_spec.offset = entry->start; + ufs_fip_spec.length = entry->length; + } + return 0; +} + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + assert(result == 0); + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return result; +} + +size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) +{ + return ufs_read_blocks(3, lba, buf, size); +} + +size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) +{ + return ufs_write_blocks(3, lba, buf, size); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c new file mode 100644 index 0000000..b9ae313 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define ADDR_CONVERT(addr) ((addr) < 0x40000 ? \ + (addr) + 0xFFF30000 : \ + (addr) + 0x40000000) + +static void fw_data_init(void) +{ + unsigned long data_head_addr; + unsigned int *data_addr; + + data_head_addr = mmio_read_32((uintptr_t) HISI_DATA_HEAD_BASE) + 0x14; + data_addr = (unsigned int *) ADDR_CONVERT(data_head_addr); + + memcpy((void *)HISI_DATA0_BASE, + (const void *)(unsigned long)ADDR_CONVERT(data_addr[0]), + HISI_DATA0_SIZE); + memcpy((void *)HISI_DATA1_BASE, + (const void *)(unsigned long)ADDR_CONVERT(data_addr[1]), + HISI_DATA1_SIZE); +} + +int load_lpm3(void) +{ + INFO("start fw loading\n"); + + fw_data_init(); + + flush_dcache_range((uintptr_t)HISI_RESERVED_MEM_BASE, + HISI_RESERVED_MEM_SIZE); + + sev(); + sev(); + + INFO("fw load success\n"); + + return 0; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c new file mode 100644 index 0000000..f836508 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 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 +#include + +#include "drivers/pwrc/hisi_pwrc.h" +#include "hikey960_def.h" +#include "hikey960_private.h" + +#define CORE_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +#define DMAC_GLB_REG_SEC 0x694 +#define AXI_CONF_BASE 0x820 + +static unsigned int uart_base; +static console_t console; +static uintptr_t hikey960_sec_entrypoint; + +static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state) +{ + unsigned long scr; + + scr = read_scr_el3(); + + /* Enable Physical IRQ and FIQ to wake the CPU */ + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + /* Add barrier before CPU enter WFI state */ + isb(); + dsb(); + wfi(); + + /* + * Restore SCR to the original value, synchronisazion of + * scr_el3 is done by eret while el3_exit to save some + * execution cycles. + */ + write_scr_el3(scr); +} + +static int hikey960_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + int cluster_stat = cluster_is_powered_on(cluster); + + hisi_set_cpu_boot_flag(cluster, core); + + mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core), + hikey960_sec_entrypoint >> 2); + + if (cluster_stat) + hisi_powerup_core(cluster, core); + else + hisi_powerup_cluster(cluster, core); + + return PSCI_E_SUCCESS; +} + +static void +hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +void hikey960_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + clr_ex(); + isb(); + dsbsy(); + + gicv2_cpuif_disable(); + + hisi_clear_cpu_boot_flag(cluster, core); + hisi_powerdn_core(cluster, core); + + /* check if any core is powered up */ + if (hisi_test_cpu_down(cluster, core)) { + + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + isb(); + dsbsy(); + + hisi_powerdn_cluster(cluster, core); + } +} + +static void __dead2 hikey960_system_off(void) +{ + gpio_set_direction(176, GPIO_DIR_OUT); + gpio_set_value(176, GPIO_LEVEL_LOW); + panic(); +} + +static void __dead2 hikey960_system_reset(void) +{ + dsb(); + isb(); + mdelay(2000); + mmio_write_32(SCTRL_SCPEREN1_REG, + SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS); + mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef); + panic(); +} + +int hikey960_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int pstate = psci_get_pstate_type(power_state); + unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MPIDR_AFFLVL0] = + PLAT_MAX_RET_STATE; + } else { + for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + PLAT_MAX_OFF_STATE; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +static int hikey960_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE))) + return PSCI_E_SUCCESS; + + return PSCI_E_INVALID_ADDRESS; +} + +static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + clr_ex(); + isb(); + dsbsy(); + + gicv2_cpuif_disable(); + + hisi_cpuidle_lock(cluster, core); + hisi_set_cpuidle_flag(cluster, core); + hisi_cpuidle_unlock(cluster, core); + + mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core), + hikey960_sec_entrypoint >> 2); + + hisi_enter_core_idle(cluster, core); + } + + /* Perform the common cluster specific operations */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_cpuidle_lock(cluster, core); + hisi_disable_pdc(cluster); + + /* check if any core is powered up */ + if (hisi_test_pwrdn_allcores(cluster, core)) { + + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + isb(); + dsbsy(); + + /* mask the pdc wakeup irq, then + * enable pdc to power down the core + */ + hisi_pdc_mask_cluster_wakeirq(cluster); + hisi_enable_pdc(cluster); + + hisi_cpuidle_unlock(cluster, core); + + /* check the SR flag bit to determine + * CLUSTER_IDLE_IPC or AP_SR_IPC to send + */ + if (hisi_test_ap_suspend_flag()) + hisi_enter_ap_suspend(cluster, core); + else + hisi_enter_cluster_idle(cluster, core); + } else { + /* enable pdc */ + hisi_enable_pdc(cluster); + hisi_cpuidle_unlock(cluster, core); + } + } +} + +static void hikey960_sr_dma_reinit(void) +{ + unsigned int ctr = 0; + + mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3); + + /* 1~15 channel is set non_secure */ + for (ctr = 1; ctr <= 15; ctr++) + mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40), + (1 << 6) | (1 << 18)); +} + +static void +hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + /* Nothing to be done on waking up from retention from CPU level */ + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + hisi_cpuidle_lock(cluster, core); + hisi_clear_cpuidle_flag(cluster, core); + hisi_cpuidle_unlock(cluster, core); + + if (hisi_test_ap_suspend_flag()) { + hikey960_sr_dma_reinit(); + gicv2_cpuif_enable(); + console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE, &console); + } + + hikey960_pwr_domain_on_finish(target_state); +} + +static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +static const plat_psci_ops_t hikey960_psci_ops = { + .cpu_standby = hikey960_pwr_domain_standby, + .pwr_domain_on = hikey960_pwr_domain_on, + .pwr_domain_on_finish = hikey960_pwr_domain_on_finish, + .pwr_domain_off = hikey960_pwr_domain_off, + .pwr_domain_suspend = hikey960_pwr_domain_suspend, + .pwr_domain_suspend_finish = hikey960_pwr_domain_suspend_finish, + .system_off = hikey960_system_off, + .system_reset = hikey960_system_reset, + .validate_power_state = hikey960_validate_power_state, + .validate_ns_entrypoint = hikey960_validate_ns_entrypoint, + .get_sys_suspend_power_state = hikey960_get_sys_suspend_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + unsigned int id = 0; + int ret; + + ret = hikey960_read_boardid(&id); + if (ret == 0) { + if (id == 5300U) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + } else { + uart_base = PL011_UART6_BASE; + } + + hikey960_sec_entrypoint = sec_entrypoint; + + INFO("%s: sec_entrypoint=0x%lx\n", __func__, + (unsigned long)hikey960_sec_entrypoint); + + /* + * Initialize PSCI ops struct + */ + *psci_ops = &hikey960_psci_ops; + return 0; +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h new file mode 100644 index 0000000..54bf501 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY960_PRIVATE_H +#define HIKEY960_PRIVATE_H + +#include + +/* + * Function and variable prototypes + */ +void hikey960_init_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); +void hikey960_init_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); +void hikey960_io_setup(void); +int hikey960_read_boardid(unsigned int *id); +int hikey960_set_fip_addr(unsigned int image_id, const char *name); +void hikey960_clk_init(void); +void hikey960_pmu_init(void); +void hikey960_regulator_enable(void); +void hikey960_tzc_init(void); +void hikey960_peri_init(void); +void hikey960_pinmux_init(void); +void hikey960_gpio_init(void); +void set_retention_ticks(unsigned int val); +void clr_retention_ticks(unsigned int val); +void clr_ex(void); +void nop(void); + +#endif /* HIKEY960_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S new file mode 100644 index 0000000..f230ed6 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global hikey960_rotpk_hash + .global hikey960_rotpk_hash_end + .section .rodata.hikey960_rotpk_hash, "a" +hikey960_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +hikey960_rotpk_hash_end: diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c new file mode 100644 index 0000000..ed4da3b --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +extern char hikey960_rotpk_hash[], hikey960_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = hikey960_rotpk_hash; + *key_len = hikey960_rotpk_hash_end - hikey960_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c new file mode 100644 index 0000000..a242bb1 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * The HiKey power domain tree descriptor. The cluster power domains + * are arranged so that when the PSCI generic code creates the power + * domain tree, the indices of the CPU power domain nodes it allocates + * match the linear indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char hikey960_power_domain_tree_desc[] = { + /* Number of root nodes */ + 1, + /* Number of clusters */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, + /* Number of children for the second cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, +}; + +/******************************************************************************* + * This function returns the HiKey topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return hikey960_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h new file mode 100644 index 0000000..17b495f --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef HI3660_H +#define HI3660_H + +#include +#include +#include + +#define ASP_CFG_REG_BASE 0xE804E000 + +#define ASP_CFG_MMBUF_CTRL_REG (ASP_CFG_REG_BASE + 0x148) + +#define LP_RAM_BASE 0xFFF50000 + +#define SCTRL_REG_BASE 0xFFF0A000 + +#define SCTRL_CONTROL_REG (SCTRL_REG_BASE + 0x000) +#define SCTRL_CONTROL_SYS_MODE(x) (((x) & 0xf) << 3) +#define SCTRL_CONTROL_SYS_MODE_NORMAL ((1 << 2) << 3) +#define SCTRL_CONTROL_SYS_MODE_SLOW ((1 << 1) << 3) +#define SCTRL_CONTROL_SYS_MODE_MASK (0xf << 3) +#define SCTRL_CONTROL_MODE_CTRL_NORMAL (1 << 2) +#define SCTRL_CONTROL_MODE_CTRL_SLOW (1 << 1) +#define SCTRL_CONTROL_MODE_CTRL_MASK 0x7 + +#define SCTRL_SCSYSSTAT_REG (SCTRL_REG_BASE + 0x004) + +#define SCTRL_DEEPSLEEPED_REG (SCTRL_REG_BASE + 0x008) +#define SCTRL_EFUSE_USB_MASK (1 << 30) +#define SCTRL_EFUSE_USB_PLL (1 << 30) +#define SCTRL_EFUSE_USB_ABB (0 << 30) +#define SCTRL_EFUSE_UFS_MASK (3 << 6) +#define SCTRL_EFUSE_UFS_PLL (1 << 6) +#define SCTRL_EFUSE_UFS_ABB (0 << 6) + +#define SCTRL_SCISOEN_REG (SCTRL_REG_BASE + 0x040) +#define SCTRL_SCISODIS_REG (SCTRL_REG_BASE + 0x044) +#define SCISO_MMBUFISO (1 << 3) + +#define SCTRL_SCPWREN_REG (SCTRL_REG_BASE + 0x060) +#define SCPWREN_MMBUFPWREN (1 << 3) + +#define SCTRL_PLL_CTRL0_REG (SCTRL_REG_BASE + 0x100) +#define SCTRL_PLL0_POSTDIV2(x) (((x) & 0x7) << 23) +#define SCTRL_PLL0_POSTDIV1(x) (((x) & 0x7) << 20) +#define SCTRL_PLL0_FBDIV(x) (((x) & 0xfff) << 8) +#define SCTRL_PLL0_REFDIV(x) (((x) & 0x3f) << 2) +#define SCTRL_PLL0_EN (1 << 0) + +#define SCTRL_PLL_CTRL1_REG (SCTRL_REG_BASE + 0x104) +#define SCTRL_PLL0_CLK_NO_GATE (1 << 26) +#define SCTRL_PLL0_CFG_VLD (1 << 25) +#define SCTRL_PLL0_FRACDIV(x) ((x) & 0xFFFFFF) + +#define SCTRL_PLL_STAT_REG (SCTRL_REG_BASE + 0x10C) +#define SCTRL_PLL0_STAT (1 << 0) + +#define SCTRL_SCPEREN0_REG (SCTRL_REG_BASE + 0x160) +#define SCTRL_SCPERDIS0_REG (SCTRL_REG_BASE + 0x164) +#define SCTRL_SCPERSTAT0_REG (SCTRL_REG_BASE + 0x168) + +#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170) +#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174) +#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170) +#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174) +#define SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS (1u << 31) +#define SCPEREN_GT_PCLK_MMBUFCFG (1 << 25) +#define SCPEREN_GT_PCLK_MMBUF (1 << 23) +#define SCPEREN_GT_ACLK_MMBUF (1 << 22) +#define SCPEREN_GT_CLK_NOC_AOBUS2MMBUF (1 << 6) + +#define SCTRL_SCPEREN2_REG (SCTRL_REG_BASE + 0x190) +#define SCTRL_SCPERDIS2_REG (SCTRL_REG_BASE + 0x194) +#define SCTRL_SCPERSTAT2_REG (SCTRL_REG_BASE + 0x198) +#define SCTRL_SCPERRSTEN0_REG (SCTRL_REG_BASE + 0x200) +#define SCTRL_SCPERRSTDIS0_REG (SCTRL_REG_BASE + 0x204) +#define SCTRL_SCPERRSTSTAT0_REG (SCTRL_REG_BASE + 0x208) +#define SCTRL_SCPERRSTEN1_REG (SCTRL_REG_BASE + 0x20C) +#define SCTRL_SCPERRSTDIS1_REG (SCTRL_REG_BASE + 0x210) +#define SCTRL_SCPERRSTSTAT1_REG (SCTRL_REG_BASE + 0x214) +#define IP_RST_MMBUFCFG (1 << 12) +#define IP_RST_MMBUF (1 << 11) + +#define SCTRL_SCPERRSTEN2_REG (SCTRL_REG_BASE + 0x218) +#define SCTRL_SCPERRSTDIS2_REG (SCTRL_REG_BASE + 0x21C) +#define SCTRL_SCPERRSTSTAT2_REG (SCTRL_REG_BASE + 0x220) + +#define SCTRL_SCCLKDIV2_REG (SCTRL_REG_BASE + 0x258) +#define SEL_CLK_MMBUF_MASK (0x3 << 8) +#define SEL_CLK_MMBUF_PLL0 (0x3 << 8) +#define SCCLKDIV2_GT_PCLK_MMBUF (1 << 7) + +#define SCTRL_SCCLKDIV4_REG (SCTRL_REG_BASE + 0x260) +#define GT_MMBUF_SYS (1 << 13) +#define GT_MMBUF_FLL (1 << 12) +#define GT_PLL_CLK_MMBUF (1 << 11) + +#define SCTRL_SCCLKDIV6_REG (SCTRL_REG_BASE + 0x268) + +#define SCTRL_SCPERCTRL7_REG (SCTRL_REG_BASE + 0x31C) +#define SCTRL_SCPERSTAT6_REG (SCTRL_REG_BASE + 0x378) + +#define SCTRL_SCINNERSTAT_REG (SCTRL_REG_BASE + 0x3A0) +#define EMMC_UFS_SEL (1 << 15) + +#define SCTRL_BAK_DATA0_REG (SCTRL_REG_BASE + 0x40C) +#define SCTRL_BAK_DATA4_REG (SCTRL_REG_BASE + 0x41C) + +#define SCTRL_LPMCU_CLKEN_REG (SCTRL_REG_BASE + 0x480) +#define SCTRL_LPMCU_CLKDIS_REG (SCTRL_REG_BASE + 0x484) +#define SCTRL_LPMCU_RSTEN_REG (SCTRL_REG_BASE + 0x500) +#define SCTRL_LPMCU_RSTDIS_REG (SCTRL_REG_BASE + 0x504) +#define DDRC_SOFT_BIT (1 << 6) +#define DDRC_CLK_BIT (1 << 5) + +#define SCTRL_SCPEREN0_SEC_REG (SCTRL_REG_BASE + 0x900) +#define SCTRL_SCPERDIS0_SEC_REG (SCTRL_REG_BASE + 0x904) +#define MMBUF_SEC_CTRL_MASK (0xfff << 20) +#define MMBUF_SEC_CTRL(x) (((x) & 0xfff) << 20) + +#define SCTRL_PERRSTEN1_SEC_REG (SCTRL_REG_BASE + 0xA50) +#define SCTRL_PERRSTDIS1_SEC_REG (SCTRL_REG_BASE + 0xA54) +#define SCTRL_PERRSTSTAT1_SEC_REG (SCTRL_REG_BASE + 0xA58) +#define RST_ASP_SUBSYS_BIT (1 << 0) + +#define SCTRL_PERRSTEN2_SEC_REG (SCTRL_REG_BASE + 0xB50) +#define SCTRL_PERRSTDIS2_SEC_REG (SCTRL_REG_BASE + 0xB54) +#define SCTRL_PERRSTSTAT2_SEC_REG (SCTRL_REG_BASE + 0xB58) + +#define SCTRL_HISEECLKDIV_REG (SCTRL_REG_BASE + 0xC28) +#define SC_SEL_HISEE_PLL_MASK (1 << 4) +#define SC_SEL_HISEE_PLL0 (1 << 4) +#define SC_SEL_HISEE_PLL2 (0 << 4) +#define SC_DIV_HISEE_PLL_MASK (7 << 16) +#define SC_DIV_HISEE_PLL(x) ((x) & 0x7) + +#define SCTRL_SCSOCID0_REG (SCTRL_REG_BASE + 0xE00) + +#define PMC_REG_BASE 0xFFF31000 +#define PMC_PPLL1_CTRL0_REG (PMC_REG_BASE + 0x038) +#define PMC_PPLL1_CTRL1_REG (PMC_REG_BASE + 0x03C) +#define PMC_PPLL2_CTRL0_REG (PMC_REG_BASE + 0x040) +#define PMC_PPLL2_CTRL1_REG (PMC_REG_BASE + 0x044) +#define PMC_PPLL3_CTRL0_REG (PMC_REG_BASE + 0x048) +#define PMC_PPLL3_CTRL1_REG (PMC_REG_BASE + 0x04C) +#define PPLLx_LOCK (1 << 26) +#define PPLLx_WITHOUT_CLK_GATE (1 << 26) +#define PPLLx_CFG_VLD (1 << 25) +#define PPLLx_INT_MOD (1 << 24) +#define PPLLx_POSTDIV2_MASK (0x7 << 23) +#define PPLLx_POSTDIV2(x) (((x) & 0x7) << 23) +#define PPLLx_POSTDIV1_MASK (0x7 << 20) +#define PPLLx_POSTDIV1(x) (((x) & 0x7) << 20) +#define PPLLx_FRACDIV_MASK (0x00FFFFFF) +#define PPLLx_FRACDIV(x) ((x) & 0x00FFFFFF) +#define PPLLx_FBDIV_MASK (0xfff << 8) +#define PPLLx_FBDIV(x) (((x) & 0xfff) << 8) +#define PPLLx_REFDIV_MASK (0x3f << 2) +#define PPLLx_REFDIV(x) (((x) & 0x3f) << 2) +#define PPLLx_BP (1 << 1) +#define PPLLx_EN (1 << 0) + +#define PMC_DDRLP_CTRL_REG (PMC_REG_BASE + 0x30C) +#define DDRC_CSYSREQ_CFG(x) ((x) & 0xF) + +#define PMC_NOC_POWER_IDLEREQ_REG (PMC_REG_BASE + 0x380) +#define PMC_NOC_POWER_IDLEREQ_IVP (1 << 14) +#define PMC_NOC_POWER_IDLEREQ_DSS (1 << 13) +#define PMC_NOC_POWER_IDLEREQ_VENC (1 << 11) +#define PMC_NOC_POWER_IDLEREQ_VDEC (1 << 10) +#define PMC_NOC_POWER_IDLEREQ_ISP (1 << 5) +#define PMC_NOC_POWER_IDLEREQ_VCODEC (1 << 4) +#define DDRPHY_BYPASS_MODE (1 << 0) + +#define PMC_NOC_POWER_IDLEACK_REG (PMC_REG_BASE + 0x384) +#define PMC_NOC_POWER_IDLE_REG (PMC_REG_BASE + 0x388) + +#define PMU_SSI0_REG_BASE 0xFFF34000 + +#define PMU_SSI0_LDO8_CTRL0_REG (PMU_SSI0_REG_BASE + (0x68 << 2)) +#define LDO8_CTRL0_EN_1_8V 0x02 + +#define PMU_SSI0_CLK_TOP_CTRL7_REG (PMU_SSI0_REG_BASE + (0x10C << 2)) +#define NP_XO_ABB_DIG (1 << 1) + +#define LP_CONFIG_REG_BASE 0xFFF3F000 + +#define DMAC_BASE 0xFDF30000 + +#define CCI400_REG_BASE 0xE8100000 +#define CCI400_SL_IFACE3_CLUSTER_IX 0 +#define CCI400_SL_IFACE4_CLUSTER_IX 1 + +#define GICD_REG_BASE 0xE82B1000 +#define GICC_REG_BASE 0xE82B2000 +/* + * GIC400 interrupt handling related constants + */ +#define IRQ_SEC_PHY_TIMER 29 +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 +#define IRQ_SEC_SGI_8 16 + +#define IPC_REG_BASE 0xE896A000 +#define IPC_BASE (IPC_REG_BASE) + +#define IOMG_REG_BASE 0xE896C000 + +/* GPIO46: HUB 3.3V enable. active low */ +#define IOMG_044_REG (IOMG_REG_BASE + 0x0B0) +#define IOMG_UART5_RX_REG (IOMG_REG_BASE + 0x0BC) +#define IOMG_UART5_TX_REG (IOMG_REG_BASE + 0x0C0) + +#define IOCG_REG_BASE 0xE896C800 + +/* GPIO005: PMIC SSI. (2 << 4) */ +#define IOCG_006_REG (IOCG_REG_BASE + 0x018) + +#define TIMER9_REG_BASE 0xE8A00000 + +#define WDT0_REG_BASE 0xE8A06000 +#define WDT1_REG_BASE 0xE8A07000 +#define WDT_CONTROL_OFFSET 0x008 +#define WDT_LOCK_OFFSET 0xC00 + +#define WDT_UNLOCK 0x1ACCE551 +#define WDT_LOCKED 1 + +#define PCTRL_REG_BASE 0xE8A09000 +#define PCTRL_PERI_CTRL3_REG (PCTRL_REG_BASE + 0x010) +#define PCTRL_PERI_CTRL24_REG (PCTRL_REG_BASE + 0x064) + +#define GPIO0_BASE UL(0xE8A0B000) +#define GPIO1_BASE UL(0xE8A0C000) +#define GPIO2_BASE UL(0xE8A0D000) +#define GPIO3_BASE UL(0xE8A0E000) +#define GPIO4_BASE UL(0xE8A0F000) +#define GPIO5_BASE UL(0xE8A10000) +#define GPIO6_BASE UL(0xE8A11000) +#define GPIO7_BASE UL(0xE8A12000) +#define GPIO8_BASE UL(0xE8A13000) +#define GPIO9_BASE UL(0xE8A14000) +#define GPIO10_BASE UL(0xE8A15000) +#define GPIO11_BASE UL(0xE8A16000) +#define GPIO12_BASE UL(0xE8A17000) +#define GPIO13_BASE UL(0xE8A18000) +#define GPIO14_BASE UL(0xE8A19000) +#define GPIO15_BASE UL(0xE8A1A000) +#define GPIO16_BASE UL(0xE8A1B000) +#define GPIO17_BASE UL(0xE8A1C000) +#define GPIO20_BASE UL(0xE8A1F000) +#define GPIO21_BASE UL(0xE8A20000) +#define GPIO22_BASE UL(0xFFF0B000) +#define GPIO23_BASE UL(0xFFF0C000) +#define GPIO24_BASE UL(0xFFF0D000) +#define GPIO25_BASE UL(0xFFF0E000) +#define GPIO26_BASE UL(0xFFF0F000) +#define GPIO27_BASE UL(0xFFF10000) +#define GPIO28_BASE UL(0xFFF1D000) + +#define TZC_REG_BASE 0xE8A21000 +#define TZC_STAT0_REG (TZC_REG_BASE + 0x800) +#define TZC_EN0_REG (TZC_REG_BASE + 0x804) +#define TZC_DIS0_REG (TZC_REG_BASE + 0x808) +#define TZC_STAT1_REG (TZC_REG_BASE + 0x80C) +#define TZC_EN1_REG (TZC_REG_BASE + 0x810) +#define TZC_DIS1_REG (TZC_REG_BASE + 0x814) +#define TZC_STAT2_REG (TZC_REG_BASE + 0x818) +#define TZC_EN2_REG (TZC_REG_BASE + 0x81C) +#define TZC_DIS2_REG (TZC_REG_BASE + 0x820) +#define TZC_STAT3_REG (TZC_REG_BASE + 0x824) +#define TZC_EN3_REG (TZC_REG_BASE + 0x828) +#define TZC_DIS3_REG (TZC_REG_BASE + 0x82C) +#define TZC_STAT4_REG (TZC_REG_BASE + 0x830) +#define TZC_EN4_REG (TZC_REG_BASE + 0x834) +#define TZC_DIS4_REG (TZC_REG_BASE + 0x838) +#define TZC_STAT5_REG (TZC_REG_BASE + 0x83C) +#define TZC_EN5_REG (TZC_REG_BASE + 0x840) +#define TZC_DIS5_REG (TZC_REG_BASE + 0x844) +#define TZC_STAT6_REG (TZC_REG_BASE + 0x848) +#define TZC_EN6_REG (TZC_REG_BASE + 0x84C) +#define TZC_DIS6_REG (TZC_REG_BASE + 0x850) +#define TZC_STAT7_REG (TZC_REG_BASE + 0x854) +#define TZC_EN7_REG (TZC_REG_BASE + 0x858) +#define TZC_DIS7_REG (TZC_REG_BASE + 0x85C) +#define TZC_STAT8_REG (TZC_REG_BASE + 0x860) +#define TZC_EN8_REG (TZC_REG_BASE + 0x864) +#define TZC_DIS8_REG (TZC_REG_BASE + 0x868) + +#define MMBUF_BASE 0xEA800000 + +#define ACPU_DMCPACK0_BASE 0xEA900000 + +#define ACPU_DMCPACK1_BASE 0xEA920000 + +#define ACPU_DMCPACK2_BASE 0xEA940000 + +#define ACPU_DMCPACK3_BASE 0xEA960000 + +#define UART5_REG_BASE 0xFDF05000 + +#define USB3OTG_REG_BASE 0xFF100000 + +#define UFS_REG_BASE 0xFF3B0000 + +#define UFS_SYS_REG_BASE 0xFF3B1000 + +#define UFS_SYS_PSW_POWER_CTRL_REG (UFS_SYS_REG_BASE + 0x004) +#define UFS_SYS_PHY_ISO_EN_REG (UFS_SYS_REG_BASE + 0x008) +#define UFS_SYS_HC_LP_CTRL_REG (UFS_SYS_REG_BASE + 0x00C) +#define UFS_SYS_PHY_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x010) +#define UFS_SYS_PSW_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x014) +#define UFS_SYS_CLOCK_GATE_BYPASS_REG (UFS_SYS_REG_BASE + 0x018) +#define UFS_SYS_RESET_CTRL_EN_REG (UFS_SYS_REG_BASE + 0x01C) +#define UFS_SYS_MONITOR_HH_REG (UFS_SYS_REG_BASE + 0x03C) +#define UFS_SYS_UFS_SYSCTRL_REG (UFS_SYS_REG_BASE + 0x05C) +#define UFS_SYS_UFS_DEVICE_RESET_CTRL_REG (UFS_SYS_REG_BASE + 0x060) +#define UFS_SYS_UFS_APB_ADDR_MASK_REG (UFS_SYS_REG_BASE + 0x064) + +#define BIT_UFS_PSW_ISO_CTRL (1 << 16) +#define BIT_UFS_PSW_MTCMOS_EN (1 << 0) +#define BIT_UFS_REFCLK_ISO_EN (1 << 16) +#define BIT_UFS_PHY_ISO_CTRL (1 << 0) +#define BIT_SYSCTRL_LP_ISOL_EN (1 << 16) +#define BIT_SYSCTRL_PWR_READY (1 << 8) +#define BIT_SYSCTRL_REF_CLOCK_EN (1 << 24) +#define MASK_SYSCTRL_REF_CLOCK_SEL (3 << 8) +#define MASK_SYSCTRL_CFG_CLOCK_FREQ (0xFF) +#define BIT_SYSCTRL_PSW_CLK_EN (1 << 4) +#define MASK_UFS_CLK_GATE_BYPASS (0x3F) +#define BIT_SYSCTRL_LP_RESET_N (1 << 0) +#define BIT_UFS_REFCLK_SRC_SE1 (1 << 0) +#define MASK_UFS_SYSCTRL_BYPASS (0x3F << 16) +#define MASK_UFS_DEVICE_RESET (1 << 16) +#define BIT_UFS_DEVICE_RESET (1 << 0) + +#define GPIO18_BASE UL(0xFF3B4000) +#define GPIO19_BASE UL(0xFF3B5000) + +#define IOMG_FIX_REG_BASE 0xFF3B6000 + +/* GPIO150: LED */ +#define IOMG_FIX_006_REG (IOMG_FIX_REG_BASE + 0x018) +/* GPIO151: LED */ +#define IOMG_FIX_007_REG (IOMG_FIX_REG_BASE + 0x01C) + +#define IOMG_AO_REG_BASE 0xFFF11000 + +/* GPIO189: LED */ +#define IOMG_AO_011_REG (IOMG_AO_REG_BASE + 0x02C) +/* GPIO190: LED */ +#define IOMG_AO_012_REG (IOMG_AO_REG_BASE + 0x030) +/* GPIO202: type C enable. active low */ +#define IOMG_AO_023_REG (IOMG_AO_REG_BASE + 0x05C) +/* GPIO206: USB switch. active low */ +#define IOMG_AO_026_REG (IOMG_AO_REG_BASE + 0x068) +/* GPIO219: PD interrupt. pull up */ +#define IOMG_AO_039_REG (IOMG_AO_REG_BASE + 0x09C) +/* GPIO213: PCIE_CLKREQ_N */ +#define IOMG_AO_033_REG (IOMG_AO_REG_BASE + 0x084) + +#define IOCG_AO_REG_BASE 0xFFF1187C +/* GPIO219: PD interrupt. pull up */ +#define IOCG_AO_043_REG (IOCG_AO_REG_BASE + 0x030) + +#define EDMAC_BASE 0xfdf30000 +#define EDMAC_SEC_CTRL (EDMAC_BASE + 0x694) +#define EDMAC_AXI_CONF(x) (EDMAC_BASE + 0x820 + (x << 6)) +#define EDMAC_SEC_CTRL_INTR_SEC (1 << 1) +#define EDMAC_SEC_CTRL_GLOBAL_SEC (1 << 0) +#define EDMAC_CHANNEL_NUMS 16 + +#define IOMCU_DMAC_BASE 0xffd77000 +#define IOMCU_DMAC_SEC_CTRL (IOMCU_DMAC_BASE + 0x694) +#define IOMCU_DMAC_AXI_CONF(x) (IOMCU_DMAC_BASE + 0x820 + ((x) << 6)) +#define IOMCU_DMAC_AXI_CONF_ARPROT_NS (1 << 6) +#define IOMCU_DMAC_AXI_CONF_AWPROT_NS (1 << 18) +#define IOMCU_DMAC_SEC_CTRL_INTR_SEC (1 << 1) +#define IOMCU_DMAC_SEC_CTRL_GLOBAL_SEC (1 << 0) +#define IOMCU_DMAC_CHANNEL_NUMS 8 + +#endif /* HI3660_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h new file mode 100644 index 0000000..eb5a6c5 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef HI3660_CRG_H +#define HI3660_CRG_H + +#define CRG_REG_BASE 0xFFF35000 + +#define CRG_PEREN0_REG (CRG_REG_BASE + 0x000) +#define CRG_PERDIS0_REG (CRG_REG_BASE + 0x004) +#define CRG_PERSTAT0_REG (CRG_REG_BASE + 0x008) +#define PEREN0_GT_CLK_AOMM (1U << 31) + +#define CRG_PEREN1_REG (CRG_REG_BASE + 0x010) +#define CRG_PERDIS1_REG (CRG_REG_BASE + 0x014) +#define CRG_PERSTAT1_REG (CRG_REG_BASE + 0x018) +#define CRG_PEREN2_REG (CRG_REG_BASE + 0x020) +#define CRG_PERDIS2_REG (CRG_REG_BASE + 0x024) +#define CRG_PERSTAT2_REG (CRG_REG_BASE + 0x028) +#define PEREN2_HKADCSSI (1 << 24) + +#define CRG_PEREN3_REG (CRG_REG_BASE + 0x030) +#define CRG_PERDIS3_REG (CRG_REG_BASE + 0x034) + +#define CRG_PEREN4_REG (CRG_REG_BASE + 0x040) +#define CRG_PERDIS4_REG (CRG_REG_BASE + 0x044) +#define CRG_PERCLKEN4_REG (CRG_REG_BASE + 0x048) +#define CRG_PERSTAT4_REG (CRG_REG_BASE + 0x04C) +#define GT_ACLK_USB3OTG (1 << 1) +#define GT_CLK_USB3OTG_REF (1 << 0) + +#define CRG_PEREN5_REG (CRG_REG_BASE + 0x050) +#define CRG_PERDIS5_REG (CRG_REG_BASE + 0x054) +#define CRG_PERSTAT5_REG (CRG_REG_BASE + 0x058) +#define CRG_PERRSTEN0_REG (CRG_REG_BASE + 0x060) +#define CRG_PERRSTDIS0_REG (CRG_REG_BASE + 0x064) +#define CRG_PERRSTSTAT0_REG (CRG_REG_BASE + 0x068) +#define CRG_PERRSTEN1_REG (CRG_REG_BASE + 0x06C) +#define CRG_PERRSTDIS1_REG (CRG_REG_BASE + 0x070) +#define CRG_PERRSTSTAT1_REG (CRG_REG_BASE + 0x074) +#define CRG_PERRSTEN2_REG (CRG_REG_BASE + 0x078) +#define CRG_PERRSTDIS2_REG (CRG_REG_BASE + 0x07C) +#define CRG_PERRSTSTAT2_REG (CRG_REG_BASE + 0x080) +#define PERRSTEN2_HKADCSSI (1 << 24) + +#define CRG_PERRSTEN3_REG (CRG_REG_BASE + 0x084) +#define CRG_PERRSTDIS3_REG (CRG_REG_BASE + 0x088) +#define CRG_PERRSTSTAT3_REG (CRG_REG_BASE + 0x08C) +#define CRG_PERRSTEN4_REG (CRG_REG_BASE + 0x090) +#define CRG_PERRSTDIS4_REG (CRG_REG_BASE + 0x094) +#define CRG_PERRSTSTAT4_REG (CRG_REG_BASE + 0x098) +#define IP_RST_USB3OTG_MUX (1 << 8) +#define IP_RST_USB3OTG_AHBIF (1 << 7) +#define IP_RST_USB3OTG_32K (1 << 6) +#define IP_RST_USB3OTG (1 << 5) +#define IP_RST_USB3OTGPHY_POR (1 << 3) + +#define CRG_PERRSTEN5_REG (CRG_REG_BASE + 0x09C) +#define CRG_PERRSTDIS5_REG (CRG_REG_BASE + 0x0A0) +#define CRG_PERRSTSTAT5_REG (CRG_REG_BASE + 0x0A4) + +/* bit fields in CRG_PERI */ +#define PERI_PCLK_PCTRL_BIT (1U << 31) +#define PERI_TIMER12_BIT (1 << 25) +#define PERI_TIMER11_BIT (1 << 24) +#define PERI_TIMER10_BIT (1 << 23) +#define PERI_TIMER9_BIT (1 << 22) +#define PERI_UART5_BIT (1 << 15) +#define PERI_UFS_BIT (1 << 12) +#define PERI_ARST_UFS_BIT (1 << 7) +#define PERI_PPLL2_EN_CPU (1 << 3) +#define PERI_PWM_BIT (1 << 0) +#define PERI_DDRC_BIT (1 << 0) +#define PERI_DDRC_D_BIT (1 << 4) +#define PERI_DDRC_C_BIT (1 << 3) +#define PERI_DDRC_B_BIT (1 << 2) +#define PERI_DDRC_A_BIT (1 << 1) +#define PERI_DDRC_DMUX_BIT (1 << 0) + +#define CRG_CLKDIV0_REG (CRG_REG_BASE + 0x0A0) +#define SC_DIV_LPMCU_MASK ((0x1F << 5) << 16) +#define SC_DIV_LPMCU(x) (((x) & 0x1F) << 5) + +#define CRG_CLKDIV1_REG (CRG_REG_BASE + 0x0B0) +#define SEL_LPMCU_PLL_MASK ((1 << 1) << 16) +#define SEL_SYSBUS_MASK ((1 << 0) << 16) +#define SEL_LPMCU_PLL1 (1 << 1) +#define SEL_LPMCU_PLL0 (0 << 1) +#define SEL_SYSBUS_PLL0 (1 << 0) +#define SEL_SYSBUS_PLL1 (0 << 0) + +#define CRG_CLKDIV3_REG (CRG_REG_BASE + 0x0B4) +#define CRG_CLKDIV5_REG (CRG_REG_BASE + 0x0BC) +#define CRG_CLKDIV8_REG (CRG_REG_BASE + 0x0C8) + +#define CRG_CLKDIV12_REG (CRG_REG_BASE + 0x0D8) +#define SC_DIV_A53HPM_MASK (0x7 << 13) +#define SC_DIV_A53HPM(x) (((x) & 0x7) << 13) + +#define CRG_CLKDIV16_REG (CRG_REG_BASE + 0x0E8) +#define DDRC_CLK_SW_REQ_CFG_MASK (0x3 << 12) +#define DDRC_CLK_SW_REQ_CFG(x) (((x) & 0x3) << 12) +#define SC_DIV_UFSPHY_CFG_MASK (0x3 << 9) +#define SC_DIV_UFSPHY_CFG(x) (((x) & 0x3) << 9) +#define DDRCPLL_SW (1 << 8) + +#define CRG_CLKDIV17_REG (CRG_REG_BASE + 0x0EC) +#define SC_DIV_UFS_PERIBUS (1 << 14) + +#define CRG_CLKDIV18_REG (CRG_REG_BASE + 0x0F0) +#define CRG_CLKDIV19_REG (CRG_REG_BASE + 0x0F4) +#define CRG_CLKDIV20_REG (CRG_REG_BASE + 0x0F8) +#define CLKDIV20_GT_CLK_AOMM (1 << 3) + +#define CRG_CLKDIV22_REG (CRG_REG_BASE + 0x100) +#define SEL_PLL_320M_MASK (1 << 16) +#define SEL_PLL2_320M (1 << 0) +#define SEL_PLL0_320M (0 << 0) + +#define CRG_CLKDIV23_REG (CRG_REG_BASE + 0x104) +#define PERI_DDRC_SW_BIT (1 << 13) +#define DIV_CLK_DDRSYS_MASK (0x3 << 10) +#define DIV_CLK_DDRSYS(x) (((x) & 0x3) << 10) +#define GET_DIV_CLK_DDRSYS(x) (((x) & DIV_CLK_DDRSYS_MASK) >> 10) +#define DIV_CLK_DDRCFG_MASK (0x6 << 5) +#define DIV_CLK_DDRCFG(x) (((x) & 0x6) << 5) +#define GET_DIV_CLK_DDRCFG(x) (((x) & DIV_CLK_DDRCFG_MASK) >> 5) +#define DIV_CLK_DDRC_MASK 0x1F +#define DIV_CLK_DDRC(x) ((x) & DIV_CLK_DDRC_MASK) +#define GET_DIV_CLK_DDRC(x) ((x) & DIV_CLK_DDRC_MASK) + +#define CRG_CLKDIV25_REG (CRG_REG_BASE + 0x10C) +#define DIV_SYSBUS_PLL_MASK (0xF << 16) +#define DIV_SYSBUS_PLL(x) ((x) & 0xF) + +#define CRG_PERI_CTRL2_REG (CRG_REG_BASE + 0x128) +#define PERI_TIME_STAMP_CLK_MASK (0x7 << 28) +#define PERI_TIME_STAMP_CLK_DIV(x) (((x) & 0x7) << 22) + +#define CRG_ISODIS_REG (CRG_REG_BASE + 0x148) +#define CRG_PERPWREN_REG (CRG_REG_BASE + 0x150) + +#define CRG_PEREN7_REG (CRG_REG_BASE + 0x420) +#define CRG_PERDIS7_REG (CRG_REG_BASE + 0x424) +#define CRG_PERSTAT7_REG (CRG_REG_BASE + 0x428) +#define GT_CLK_UFSPHY_CFG (1 << 14) + +#define CRG_PEREN8_REG (CRG_REG_BASE + 0x430) +#define CRG_PERDIS8_REG (CRG_REG_BASE + 0x434) +#define CRG_PERSTAT8_REG (CRG_REG_BASE + 0x438) +#define PERI_DMC_D_BIT (1 << 22) +#define PERI_DMC_C_BIT (1 << 21) +#define PERI_DMC_B_BIT (1 << 20) +#define PERI_DMC_A_BIT (1 << 19) +#define PERI_DMC_BIT (1 << 18) + +#define CRG_PEREN11_REG (CRG_REG_BASE + 0x460) +#define PPLL1_GATE_CPU (1 << 18) + +#define CRG_PERSTAT11_REG (CRG_REG_BASE + 0x46C) +#define PPLL3_EN_STAT (1 << 21) +#define PPLL2_EN_STAT (1 << 20) +#define PPLL1_EN_STAT (1 << 19) + +#define CRG_IVP_SEC_RSTDIS_REG (CRG_REG_BASE + 0xC04) +#define CRG_ISP_SEC_RSTDIS_REG (CRG_REG_BASE + 0xC84) + +#define CRG_RVBAR(c, n) (0xE00 + (0x10 * c) + (0x4 * n)) +#define CRG_GENERAL_SEC_RSTEN_REG (CRG_REG_BASE + 0xE20) +#define CRG_GENERAL_SEC_RSTDIS_REG (CRG_REG_BASE + 0xE24) +#define IP_RST_GPIO0_SEC (1 << 2) + +#define CRG_GENERAL_SEC_CLKDIV0_REG (CRG_REG_BASE + 0xE90) +#define SC_DIV_AO_HISE_MASK 3 +#define SC_DIV_AO_HISE(x) ((x) & 0x3) + +#endif /* HI3660_CRG_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h new file mode 100644 index 0000000..dc9e813 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef HI3660_HKADC_H +#define HI3660_HKADC_H + +#define HKADC_SSI_REG_BASE 0xE82B8000 + +#define HKADC_DSP_START_REG (HKADC_SSI_REG_BASE + 0x000) +#define HKADC_WR_NUM_REG (HKADC_SSI_REG_BASE + 0x008) +#define HKADC_DSP_START_CLR_REG (HKADC_SSI_REG_BASE + 0x01C) +#define HKADC_WR01_DATA_REG (HKADC_SSI_REG_BASE + 0x020) + +#define WR1_WRITE_MODE (1U << 31) +#define WR1_READ_MODE (0 << 31) +#define WR1_ADDR(x) (((x) & 0x7F) << 24) +#define WR1_DATA(x) (((x) & 0xFF) << 16) +#define WR0_WRITE_MODE (1 << 15) +#define WR0_READ_MODE (0 << 15) +#define WR0_ADDR(x) (((x) & 0x7F) << 8) +#define WR0_DATA(x) ((x) & 0xFF) + +#define HKADC_WR23_DATA_REG (HKADC_SSI_REG_BASE + 0x024) +#define HKADC_WR45_DATA_REG (HKADC_SSI_REG_BASE + 0x028) +#define HKADC_DELAY01_REG (HKADC_SSI_REG_BASE + 0x030) +#define HKADC_DELAY23_REG (HKADC_SSI_REG_BASE + 0x034) +#define HKADC_DELAY45_REG (HKADC_SSI_REG_BASE + 0x038) +#define HKADC_DSP_RD2_DATA_REG (HKADC_SSI_REG_BASE + 0x048) +#define HKADC_DSP_RD3_DATA_REG (HKADC_SSI_REG_BASE + 0x04C) + +/* HKADC Internal Registers */ +#define HKADC_CTRL_ADDR 0x00 +#define HKADC_START_ADDR 0x01 +#define HKADC_DATA1_ADDR 0x03 /* high 8 bits */ +#define HKADC_DATA0_ADDR 0x04 /* low 8 bits */ +#define HKADC_MODE_CFG 0x0A + +#define HKADC_VALUE_HIGH 0x0FF0 +#define HKADC_VALUE_LOW 0x000F +#define HKADC_VALID_VALUE 0x0FFF + +#define HKADC_CHANNEL_MAX 15 +#define HKADC_VREF_1V8 1800 +#define HKADC_ACCURACY 0x0FFF + +#define HKADC_WR01_VALUE ((HKADC_START_ADDR << 24) | \ + (0x1 << 16)) +#define HKADC_WR23_VALUE ((0x1u << 31) | \ + (HKADC_DATA0_ADDR << 24) | \ + (1 << 15) | \ + (HKADC_DATA1_ADDR << 8)) +#define HKADC_WR45_VALUE (0x80) +#define HKADC_CHANNEL0_DELAY01_VALUE ((0x0700 << 16) | 0xFFFF) +#define HKADC_DELAY01_VALUE ((0x0700 << 16) | 0x0200) +#define HKADC_DELAY23_VALUE ((0x00C8 << 16) | 0x00C8) +#define START_DELAY_TIMEOUT 2000 +#define HKADC_WR_NUM_VALUE 4 + +#endif /* HI3660_HKADC_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h new file mode 100644 index 0000000..cadc4a4 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI3660_MEM_MAP_H +#define HI3660_MEM_MAP_H + +#define HISI_DATA_HEAD_BASE (0x89C44400) + +#define HISI_RESERVED_MEM_BASE (0x89C80000) +#define HISI_RESERVED_MEM_SIZE (0x00040000) + +#define HISI_DATA0_BASE (0x89C96180) +#define HISI_DATA0_SIZE (0x000003A0) +#define HISI_DATA1_BASE (0x89C93480) +#define HISI_DATA1_SIZE (0x00002D00) + +#endif /* HI3660_MEM_MAP_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h new file mode 100644 index 0000000..6a97968 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_IPC_H +#define HISI_IPC_H + +enum pm_mode { + PM_ON = 0, + PM_OFF, +}; + +void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster, + enum pm_mode mode); +void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster, + unsigned int affinity_level); +void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster); +void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster, + unsigned int cmd_id); +int hisi_ipc_init(void); + +#endif /* HISI_IPC_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S b/arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S new file mode 100644 index 0000000..8765562 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include +#include +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + +/* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + mov_imm x16, GICD_REG_BASE + mov_imm x17, GICC_REG_BASE + + /* 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 cosole */ + bl str_in_crash_buf_print + + /* Print the GICD_ISPENDR regs */ + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +2: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq 1f + bl asm_print_hex + adr x4, spacer + bl asm_print_str + ldr x4, [x7], #8 + bl asm_print_hex + adr x4, newline + bl asm_print_str + b 2b +1: + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (CCI400_REG_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE3_CLUSTER_IX)) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (CCI400_REG_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE4_CLUSTER_IX)) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h new file mode 100644 index 0000000..215eebe --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include "../hikey960_def.h" + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define HIKEY960_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/* + * Generic platform constants + */ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x1000 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CORE_COUNT_PER_CLUSTER U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_CORE_COUNT_PER_CLUSTER) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + 1) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 +/* UFS RPMB and UFS User Data */ +#define MAX_IO_BLOCK_DEVICES U(2) + + +/* + * Platform memory map related constants + */ + +/* + * BL1 specific defines. + */ +#define BL1_RO_BASE (0x1AC00000) +#define BL1_RO_LIMIT (BL1_RO_BASE + 0x20000) +#define BL1_RW_BASE (BL1_RO_LIMIT) /* 1AC2_0000 */ +#define BL1_RW_SIZE (0x00188000) +#define BL1_RW_LIMIT (0x1B000000) + +/* + * BL2 specific defines. + */ +#define BL2_BASE (0x1AC00000) +#define BL2_LIMIT (BL2_BASE + 0x58000) /* 1AC5_8000 */ + +/* + * BL31 specific defines. + */ +#define BL31_BASE (BL2_LIMIT) /* 1AC5_8000 */ +#define BL31_LIMIT (BL31_BASE + 0x40000) /* 1AC9_8000 */ + +/* + * BL3-2 specific defines. + */ + +/* + * The TSP currently executes from TZC secured area of DRAM. + */ +#define BL32_DRAM_BASE DDR_SEC_BASE +#define BL32_DRAM_LIMIT (DDR_SEC_BASE+DDR_SEC_SIZE) + +#ifdef SPD_opteed +/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */ +#define HIKEY960_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x3FC0_0000 */ +#define HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */ +#endif + +#if (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_DRAM_ID) +#define TSP_SEC_MEM_BASE BL32_DRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE) +#define BL32_BASE BL32_DRAM_BASE +#define BL32_LIMIT BL32_DRAM_LIMIT +#elif (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_SRAM_ID) +#error "SRAM storage of TSP payload is currently unsupported" +#else +#error "Currently unsupported HIKEY960_TSP_LOCATION_ID value" +#endif + +/* BL32 is mandatory in AArch32 */ +#ifdef __aarch64__ +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ +#endif + +#define NS_BL1U_BASE (BL31_LIMIT) /* 1AC9_8000 */ +#define NS_BL1U_SIZE (0x00100000) +#define NS_BL1U_LIMIT (NS_BL1U_BASE + NS_BL1U_SIZE) + +#define HIKEY960_NS_IMAGE_OFFSET (0x1AC28000) /* offset in l-loader */ +#define HIKEY960_NS_TMP_OFFSET (0x1AE00000) + +#define SCP_BL2_BASE (0x89C80000) +#define SCP_BL2_SIZE (0x00040000) + +/* + * Platform specific page table and MMU setup constants + */ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) + +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || defined(IMAGE_BL32) +#define MAX_XLAT_TABLES 3 +#endif + +#ifdef IMAGE_BL2 +#define MAX_XLAT_TABLES 4 +#endif + +#define MAX_MMAP_REGIONS 16 + +/* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/platform.mk b/arm-trusted-firmware/plat/hisilicon/hikey960/platform.mk new file mode 100644 index 0000000..fc2c209 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/platform.mk @@ -0,0 +1,158 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Non-TF Boot ROM +BL2_AT_EL3 := 1 + +# On Hikey960, the TSP can execute from TZC secure area in DRAM. +HIKEY960_TSP_RAM_LOCATION ?= dram +ifeq (${HIKEY960_TSP_RAM_LOCATION}, dram) + HIKEY960_TSP_RAM_LOCATION_ID = HIKEY960_DRAM_ID +else ifeq (${HIKEY960_TSP_RAM_LOCATION}, sram) + HIKEY960_TSP_RAM_LOCATION_ID = HIKEY960_SRAM_ID +else + $(error "Currently unsupported HIKEY960_TSP_RAM_LOCATION value") +endif + +CRASH_CONSOLE_BASE := PL011_UART6_BASE +COLD_BOOT_SINGLE_CPU := 1 +PLAT_PL061_MAX_GPIOS := 232 +PROGRAMMABLE_RESET_ADDRESS := 1 +ENABLE_SVE_FOR_NS := 0 +PLAT_PARTITION_BLOCK_SIZE := 4096 + +# Process flags +$(eval $(call add_define,HIKEY960_TSP_RAM_LOCATION_ID)) +$(eval $(call add_define,CRASH_CONSOLE_BASE)) +$(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) +$(eval $(call add_define,PLAT_PARTITION_BLOCK_SIZE)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) +endif + +USE_COHERENT_MEM := 1 + +PLAT_INCLUDES := -Iplat/hisilicon/hikey960/include + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/hisilicon/hikey960/aarch64/hikey960_common.c \ + plat/hisilicon/hikey960/hikey960_boardid.c + +HIKEY960_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL1_SOURCES += bl1/tbbr/tbbr_img_desc.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/gpio/gpio.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/synopsys/ufs/dw_ufs.c \ + drivers/ufs/ufs.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \ + plat/hisilicon/hikey960/hikey960_bl1_setup.c \ + plat/hisilicon/hikey960/hikey960_bl_common.c \ + plat/hisilicon/hikey960/hikey960_io_storage.c \ + ${HIKEY960_GIC_SOURCES} + +BL2_SOURCES += common/desc_image_load.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/gpio/gpio.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/partition/gpt.c \ + drivers/partition/partition.c \ + drivers/synopsys/ufs/dw_ufs.c \ + drivers/ufs/ufs.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \ + plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c \ + plat/hisilicon/hikey960/hikey960_bl2_setup.c \ + plat/hisilicon/hikey960/hikey960_bl_common.c \ + plat/hisilicon/hikey960/hikey960_image_load.c \ + plat/hisilicon/hikey960/hikey960_io_storage.c \ + plat/hisilicon/hikey960/hikey960_mcu_load.c + +ifeq (${SPD},opteed) +BL2_SOURCES += lib/optee/optee_utils.c +endif + +BL31_SOURCES += drivers/arm/cci/cci.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/gpio/gpio.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/cortex_a73.S \ + plat/common/plat_psci_common.c \ + plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \ + plat/hisilicon/hikey960/hikey960_bl31_setup.c \ + plat/hisilicon/hikey960/hikey960_bl_common.c \ + plat/hisilicon/hikey960/hikey960_pm.c \ + plat/hisilicon/hikey960/hikey960_topology.c \ + plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c \ + plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c \ + ${HIKEY960_GIC_SOURCES} + +ifneq (${TRUSTED_BOARD_BOOT},0) + +include drivers/auth/mbedtls/mbedtls_crypto.mk +include drivers/auth/mbedtls/mbedtls_x509.mk + +AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c + +BL1_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/hisilicon/hikey960/hikey960_tbbr.c \ + plat/hisilicon/hikey960/hikey960_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl1.c + +BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/hisilicon/hikey960/hikey960_tbbr.c \ + plat/hisilicon/hikey960/hikey960_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +ROT_KEY = $(BUILD_PLAT)/rot_key.pem +ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + +$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) +$(BUILD_PLAT)/bl1/hikey960_rotpk.o: $(ROTPK_HASH) +$(BUILD_PLAT)/bl2/hikey960_rotpk.o: $(ROTPK_HASH) + +certificates: $(ROT_KEY) +$(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + $(Q)openssl genrsa 2048 > $@ 2>/dev/null + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +# Enable workarounds for selected Cortex-A53 errata. +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +FIP_ALIGN := 512 diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c b/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c new file mode 100644 index 0000000..fcd0a8b --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "hi3798cv200.h" +#include "platform_def.h" + +#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \ + DDR_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \ + DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#ifdef SPD_opteed +#define MAP_OPTEE_PAGEABLE MAP_REGION_FLAT( \ + POPLAR_OPTEE_PAGEABLE_LOAD_BASE, \ + POPLAR_OPTEE_PAGEABLE_LOAD_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +static const mmap_region_t poplar_mmap[] = { + MAP_DDR, + MAP_DEVICE, + MAP_TSP_MEM, +#ifdef SPD_opteed + MAP_OPTEE_PAGEABLE, +#endif + {0} +}; + +#define DEFINE_CONFIGURE_MMU_EL(_el) \ + void plat_configure_mmu_el##_el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(poplar_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(0); \ + } + +DEFINE_CONFIGURE_MMU_EL(3) +DEFINE_CONFIGURE_MMU_EL(1) + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S b/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S new file mode 100644 index 0000000..063ee64 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + + .globl plat_my_core_pos + .globl poplar_calc_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses poplar_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b poplar_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int poplar_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func poplar_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc poplar_calc_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, POPLAR_CRASH_UART_BASE + mov_imm x1, POPLAR_CRASH_UART_CLK_IN_HZ + mov_imm x2, POPLAR_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, POPLAR_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : r0 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, POPLAR_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on ARM + * platforms. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c b/arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c new file mode 100644 index 0000000..acc1f0e --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017-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 +#include + +#include "hi3798cv200.h" +#include "plat_private.h" + +/* Data structure which holds the extents of the trusted RAM for BL1 */ +static meminfo_t bl1_tzram_layout; +static meminfo_t bl2_tzram_layout; +static console_t console; + +#if !POPLAR_RECOVERY +static struct mmc_device_info mmc_info; +#endif + +/* + * Cannot use default weak implementation in bl1_main.c because BL1 RW data is + * not at the top of the secure memory. + */ +int bl1_plat_handle_post_image_load(unsigned int image_id) +{ + image_desc_t *image_desc; + entry_point_info_t *ep_info; + + if (image_id != BL2_IMAGE_ID) + return 0; + + /* Get the image descriptor */ + image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(image_desc != NULL); + + /* Get the entry point info */ + ep_info = &image_desc->ep_info; + + bl2_tzram_layout.total_base = BL2_BASE; + bl2_tzram_layout.total_size = BL32_LIMIT - BL2_BASE; + + flush_dcache_range((uintptr_t)&bl2_tzram_layout, sizeof(meminfo_t)); + + ep_info->args.arg1 = (uintptr_t)&bl2_tzram_layout; + + VERBOSE("BL1: BL2 memory layout address = %p\n", + (void *)&bl2_tzram_layout); + + return 0; +} + +void bl1_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL1_RW_BASE; + bl1_tzram_layout.total_size = BL1_RW_SIZE; + + INFO("BL1: 0x%lx - 0x%lx [size = %zu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, + BL1_RAM_LIMIT - BL1_RAM_BASE); +} + +void bl1_plat_arch_setup(void) +{ + plat_configure_mmu_el3(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL1_RO_BASE, /* l-loader and BL1 ROM */ + BL1_RO_LIMIT, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void bl1_platform_setup(void) +{ + int i; +#if !POPLAR_RECOVERY + dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE); +#endif + + generic_delay_timer_init(); + + pl061_gpio_init(); + for (i = 0; i < GPIO_MAX; i++) + pl061_gpio_register(GPIO_BASE(i), i); + +#if !POPLAR_RECOVERY + /* SoC-specific emmc register are initialized/configured by bootrom */ + INFO("BL1: initializing emmc\n"); + mmc_info.mmc_dev_type = MMC_IS_EMMC; + dw_mmc_init(¶ms, &mmc_info); +#endif + + plat_io_setup(); +} + +unsigned int bl1_plat_get_next_image_id(void) +{ + return BL2_IMAGE_ID; +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c b/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c new file mode 100644 index 0000000..f683d75 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .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.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + 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 /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = POPLAR_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = POPLAR_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = POPLAR_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = PLAT_POPLAR_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_POPLAR_NS_IMAGE_OFFSET, + .image_info.image_max_size = DDR_BASE + DDR_SIZE - + PLAT_POPLAR_NS_IMAGE_OFFSET, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c b/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c new file mode 100644 index 0000000..ee46772 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2017-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 +#include + +#include "hi3798cv200.h" +#include "plat_private.h" + +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); +static console_t console; +#if !POPLAR_RECOVERY +static struct mmc_device_info mmc_info; +#endif + +/******************************************************************************* + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int plat_poplar_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + /* + * This platform has no SCP_BL2 yet + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t poplar_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL3-2 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifdef __aarch64__ +uint32_t poplar_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +uint32_t poplar_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* __aarch64__ */ + +int poplar_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif + + assert(bl_mem_params); + + switch (image_id) { +#ifdef __aarch64__ + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } + + /* + * OP-TEE expect to receive DTB address in x2. + * This will be copied into x2 by dispatcher. + * Set this (arg3) if necessary + */ + /* bl_mem_params->ep_info.args.arg3 = PLAT_HIKEY_DT_BASE; */ +#endif + bl_mem_params->ep_info.spsr = poplar_get_spsr_for_bl32_entry(); + break; +#endif + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = poplar_get_spsr_for_bl33_entry(); + break; + +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = plat_poplar_bl2_handle_scp_bl2(&bl_mem_params->image_info); + if (err) { + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + } + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return poplar_bl2_handle_post_image_load(image_id); +} + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct meminfo *mem_layout = (struct meminfo *)arg1; +#if !POPLAR_RECOVERY + dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE); +#endif + + console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Enable arch timer */ + generic_delay_timer_init(); + + bl2_tzram_layout = *mem_layout; + +#if !POPLAR_RECOVERY + /* SoC-specific emmc register are initialized/configured by bootrom */ + INFO("BL2: initializing emmc\n"); + mmc_info.mmc_dev_type = MMC_IS_EMMC; + dw_mmc_init(¶ms, &mmc_info); +#endif + + plat_io_setup(); +} + +void bl2_plat_arch_setup(void) +{ + plat_configure_mmu_el1(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void bl2_platform_setup(void) +{ +} + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_POPLAR_NS_IMAGE_OFFSET; +#endif +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c b/arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c new file mode 100644 index 0000000..fe60ddc --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2017-2019, 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 +#include +#include +#include + +#include "hi3798cv200.h" +#include "plat_private.h" + +#define TZPC_SEC_ATTR_CTRL_VALUE (0x9DB98D45) + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; +static console_t console; + +static void hisi_tzpc_sec_init(void) +{ + mmio_write_32(HISI_TZPC_SEC_ATTR_CTRL, TZPC_SEC_ATTR_CTRL_VALUE); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Perform any BL31 early platform setup common to ARM standard platforms. + * Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be + * done before the MMU is initialized so that the memory layout can be used + * while creating page tables. BL2 has flushed this information to memory, so + * we are guaranteed to pick up good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + void *from_bl2; + + from_bl2 = (void *) arg0; + + console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, + PL011_BAUDRATE, &console); + + /* Init console for crash report */ + plat_crash_console_init(); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_image_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0) + panic(); +} + +void bl31_platform_setup(void) +{ + /* Init arch timer */ + generic_delay_timer_init(); + + /* Init GIC distributor and CPU interface */ + poplar_gic_driver_init(); + poplar_gic_init(); + + /* Init security properties of IP blocks */ + hisi_tzpc_sec_init(); +} + +void bl31_plat_runtime_setup(void) +{ + /* do nothing */ +} + +void bl31_plat_arch_setup(void) +{ + plat_configure_mmu_el3(BL31_BASE, + (BL31_LIMIT - BL31_BASE), + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); + + INFO("Boot BL33 from 0x%lx for %" PRIu64 " Bytes\n", + bl33_image_ep_info.pc, bl33_image_ep_info.args.arg2); +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h b/arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h new file mode 100644 index 0000000..e31f4b3 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HI3798CV200_H +#define HI3798CV200_H + +#include + +/* PL011 */ +#define PL011_UART0_BASE (0xF8B00000) +#define PL011_BAUDRATE (115200) +#define PL011_UART0_CLK_IN_HZ (75000000) + +/* Sys Counter */ +#define SYS_COUNTER_FREQ_IN_TICKS (24000000) +#define SYS_COUNTER_FREQ_IN_MHZ (24) + +/* Timer */ +#define SEC_TIMER0_BASE (0xF8008000) +#define TIMER00_LOAD (SEC_TIMER0_BASE + 0x000) +#define TIMER00_VALUE (SEC_TIMER0_BASE + 0x004) +#define TIMER00_CONTROL (SEC_TIMER0_BASE + 0x008) +#define TIMER00_BGLOAD (SEC_TIMER0_BASE + 0x018) + +#define SEC_TIMER2_BASE (0xF8009000) +#define TIMER20_LOAD (SEC_TIMER2_BASE + 0x000) +#define TIMER20_VALUE (SEC_TIMER2_BASE + 0x004) +#define TIMER20_CONTROL (SEC_TIMER2_BASE + 0x008) +#define TIMER20_BGLOAD (SEC_TIMER2_BASE + 0x018) + +/* GPIO */ +#define GPIO_MAX (13) +#define GPIO_BASE(x) (x != 5 ? \ + 0xf820000 + x * 0x1000 : 0xf8004000) + +/* SCTL */ +#define REG_BASE_SCTL (0xF8000000) +#define REG_SC_GEN12 (0x00B0) + +/* CRG */ +#define REG_BASE_CRG (0xF8A22000) +#define REG_CPU_LP (0x48) +#define REG_CPU_RST (0x50) +#define REG_PERI_CRG39 (0x9C) +#define REG_PERI_CRG40 (0xA0) + +/* MCI */ +#define REG_BASE_MCI (0xF9830000) +#define MCI_CDETECT (0x50) +#define MCI_VERID (0x6C) +#define MCI_VERID_VALUE (0x5342250A) +#define MCI_VERID_VALUE2 (0x5342270A) + +/* EMMC */ +#define REG_EMMC_PERI_CRG REG_PERI_CRG40 +#define REG_SDCARD_PERI_CRG REG_PERI_CRG39 +#define EMMC_CLK_MASK (0x7 << 8) +#define EMMC_SRST_REQ (0x1 << 4) +#define EMMC_CKEN (0x1 << 1) +#define EMMC_BUS_CKEN (0x1 << 0) +#define EMMC_CLK_100M (0 << 8) +#define EMMC_CLK_50M (1 << 8) +#define EMMC_CLK_25M (2 << 8) + +#define EMMC_DESC_SIZE U(0x00100000) /* 1MB */ +#define EMMC_INIT_PARAMS(base) \ + { .bus_width = MMC_BUS_WIDTH_8, \ + .clk_rate = 25 * 1000 * 1000, \ + .desc_base = (base), \ + .desc_size = EMMC_DESC_SIZE, \ + .flags = MMC_FLAG_CMD23, \ + .reg_base = REG_BASE_MCI, \ + } + +/* GIC-400 */ +#define GICD_BASE (0xF1001000) +#define GICC_BASE (0xF1002000) +#define GICR_BASE (0xF1000000) + +/* FIQ platform related define */ +#define HISI_IRQ_SEC_SGI_0 8 +#define HISI_IRQ_SEC_SGI_1 9 +#define HISI_IRQ_SEC_SGI_2 10 +#define HISI_IRQ_SEC_SGI_3 11 +#define HISI_IRQ_SEC_SGI_4 12 +#define HISI_IRQ_SEC_SGI_5 13 +#define HISI_IRQ_SEC_SGI_6 14 +#define HISI_IRQ_SEC_SGI_7 15 +#define HISI_IRQ_SEC_PPI_0 29 +#define HISI_IRQ_SEC_TIMER0 60 +#define HISI_IRQ_SEC_TIMER1 50 +#define HISI_IRQ_SEC_TIMER2 52 +#define HISI_IRQ_SEC_TIMER3 88 +#define HISI_IRQ_SEC_AXI 110 + +/* Watchdog */ +#define HISI_WDG0_BASE (0xF8A2C000) + +#define HISI_TZPC_BASE (0xF8A80000) +#define HISI_TZPC_SEC_ATTR_CTRL (HISI_TZPC_BASE + 0x10) + +#endif /* HI3798CV200_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S b/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S new file mode 100644 index 0000000..82d10c1 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +.section .rodata.gic_reg_name, "aS" + .macro plat_crash_print_regs + nop + .endm diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h b/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h new file mode 100644 index 0000000..a34f138 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#include + +#include "hi3798cv200.h" + +void plat_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); + +void plat_configure_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); + +void plat_io_setup(void); + +unsigned int poplar_calc_core_pos(u_register_t mpidr); + +void poplar_gic_driver_init(void); +void poplar_gic_init(void); +void poplar_gic_cpuif_enable(void); +void poplar_gic_pcpu_init(void); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h b/arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h new file mode 100644 index 0000000..ce0fbbc --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include + +#include "hi3798cv200.h" +#include "poplar_layout.h" /* BL memory region sizes, etc */ + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define POPLAR_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define POPLAR_CRASH_UART_BASE PL011_UART0_BASE +#define POPLAR_CRASH_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ +#define POPLAR_CONSOLE_BAUDRATE PL011_BAUDRATE + +/* Generic platform constants */ +#define PLATFORM_STACK_SIZE (0x800) + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" +#define BOOT_EMMC_NAME "l-loader.bin" + +#define PLATFORM_CACHE_LINE_SIZE (64) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CORE_COUNT U(4) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) + +/* IO framework user */ +#define MAX_IO_DEVICES (4) +#define MAX_IO_HANDLES (4) +#define MAX_IO_BLOCK_DEVICES U(2) + +/* Memory size options */ +#define POPLAR_DRAM_SIZE_1G 0 +#define POPLAR_DRAM_SIZE_2G 1 + +/* Memory map related constants */ +#define DDR_BASE (0x00000000) + +#if (POPLAR_DRAM_SIZE_ID == POPLAR_DRAM_SIZE_2G) +#define DDR_SIZE (0x80000000) +#elif (POPLAR_DRAM_SIZE_ID == POPLAR_DRAM_SIZE_1G) +#define DDR_SIZE (0x40000000) +#else +#error "Currently unsupported POPLAR_DRAM_SIZE_ID value" +#endif + +#define DEVICE_BASE (0xF0000000) +#define DEVICE_SIZE (0x0F000000) + +#define TEE_SEC_MEM_BASE (0x70000000) +#define TEE_SEC_MEM_SIZE (0x10000000) + +/* Memory location options for TSP */ +#define POPLAR_SRAM_ID 0 +#define POPLAR_DRAM_ID 1 + +/* + * DDR for OP-TEE (26MB from 0x02400000 -0x04000000) is divided in several + * regions: + * - Secure DDR (default is the top 16MB) used by OP-TEE + * - Non-secure DDR (4MB) reserved for OP-TEE's future use + * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature + * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB) + */ +#define DDR_SEC_SIZE 0x01000000 +#define DDR_SEC_BASE 0x03000000 + +/* + * BL3-2 specific defines. + */ + +/* + * The TSP currently executes from TZC secured area of DRAM. + */ +#define BL32_DRAM_BASE 0x03000000 +#define BL32_DRAM_LIMIT 0x04000000 + +#ifdef SPD_opteed +/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */ +#define POPLAR_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */ +#define POPLAR_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - POPLAR_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x03C0_0000 */ +#endif + +#if (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_DRAM_ID) +#define TSP_SEC_MEM_BASE BL32_DRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE) +#define BL32_BASE BL32_DRAM_BASE +#define BL32_LIMIT BL32_DRAM_LIMIT +#elif (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_SRAM_ID) +#error "SRAM storage of TSP payload is currently unsupported" +#else +#error "Currently unsupported POPLAR_TSP_LOCATION_ID value" +#endif + +/* BL32 is mandatory in AArch32 */ +#ifdef __aarch64__ +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ +#endif + +#define POPLAR_EMMC_DATA_BASE U(0x02200000) +#define POPLAR_EMMC_DATA_SIZE EMMC_DESC_SIZE +#define POPLAR_EMMC_DESC_BASE (POPLAR_EMMC_DATA_BASE + POPLAR_EMMC_DATA_SIZE) +#define POPLAR_EMMC_DESC_SIZE EMMC_DESC_SIZE + +#define PLAT_POPLAR_NS_IMAGE_OFFSET 0x37000000 + +/* Page table and MMU setup constants */ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES (4) +#define MAX_MMAP_REGIONS (16) + +#define CACHE_WRITEBACK_SHIFT (6) +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* Power states */ +#define PLAT_MAX_PWR_LVL (MPIDR_AFFLVL1) +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_RET_STATE U(1) + +/* Interrupt controller */ +#define POPLAR_GICD_BASE GICD_BASE +#define POPLAR_GICC_BASE GICC_BASE + +#define POPLAR_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_TIMER0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_TIMER1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_TIMER2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_TIMER3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(HISI_IRQ_SEC_AXI, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define POPLAR_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h b/arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h new file mode 100644 index 0000000..03047f9 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POPLAR_LAYOUT_H +#define POPLAR_LAYOUT_H + +/* + * Boot memory layout definitions for the HiSilicon Poplar board + */ + +/* + * When Poplar is powered on, boot ROM verifies the initial content of + * boot media, loads it into low memory, and begins executing it + * in 32-bit mode. The image loaded is "l-loader.bin", which contains + * a small amount code along with an embedded ARM Trusted Firmware + * BL1 image. The main purpose of "l-loader" is to prepare the + * processor to execute the BL1 image in 64-bit mode, and to trigger + * that execution. + * + * Also embedded in "l-loader.bin" is a FIP image that contains + * other ARM Trusted Firmware images: BL2; BL31; and for BL33, + * U-Boot. When BL1 executes, it unpacks the BL2 image from the FIP + * image into a region of memory set aside to hold it. Similarly, + * BL2 unpacks BL31 into memory reserved for it, and unpacks U-Boot + * into high memory. + * + * Because the BL1 code is embedded in "l-loader", its base address + * in memory is derived from the base address of the "l-loader" + * text section, together with an offset. Memory space for BL2 is + * reserved immediately following BL1, and memory space is reserved + * for BL31 after that. ARM Trusted Firmware requires each of these + * memory regions to be aligned on page boundaries, so the size of + * each region is a multiple of a page size (ending in 000). Note + * that ARM Trusted Firmware requires the read-only and read-write + * regions of memory used for BL1 to be defined separately. + * + * --------------------- + * | (unused memory) | + * +-------------------+ - - - - - + * | (l-loader text) | \ + * +-------------------+ \ + * | BL1 (read-only) | \ \ + * |- - - - - - - - - -| | | + * | BL1 (read-write) | | | + * +-------------------+ > BL Memory | + * | Reserved for BL2 | | > "l-loader.bin" image + * +-------------------+ | | + * | Reserved for BL31 | / | + * +-------------------+ | + * . . . / + * +-------------------+ / + * | FIP | / + * +-------------------+ - - - - - + * . . . + * | (unused memory) | + * . . . + * +-------------------+ + * |Reserved for U-Boot| + * +-------------------+ + * . . . + * | (unused memory) | + * --------------------- + * + * The size of each of these regions is defined below. The base + * address of the "l-loader" TEXT section and the offset of the BL1 + * image within that serve as anchors for defining the positions of + * all other regions. The FIP is placed in a section of its own. + * + * A "BASE" is the memory address of the start of a region; a "LIMIT" + * marks its end. A "SIZE" is the size of a region (in bytes). An + * "OFFSET" is an offset to the start of a region relative to the + * base of the "l-loader" TEXT section (also a multiple of page size). + */ +#define LLOADER_TEXT_BASE 0x02001000 /* page aligned */ +#define BL1_OFFSET 0x0000D000 /* page multiple */ +#define FIP_BASE 0x02040000 + +/* + * FIP_BASE_EMMC = 0x40000 - 0x1000 + * = fip.bin offset - l-loader text offset + * in l-loader.bin + */ +#define FIP_BASE_EMMC 0x0003f000 + +#define BL1_RO_SIZE 0x00008000 /* page multiple */ +#define BL1_RW_SIZE 0x00008000 /* page multiple */ +#define BL1_SIZE (BL1_RO_SIZE + BL1_RW_SIZE) +#define BL2_SIZE 0x0000d000 /* page multiple */ +#define BL31_SIZE 0x00014000 +#if !POPLAR_RECOVERY +/* + * emmc partition1 4096KB + * - l-loader.bin 1984KB + * |- l-loader + bl1.bin 256KB + * |- fip.bin 1728KB (0x001b0000) + * - u-boot persistent data 64KB + * - uefi persistent data 2048KB + */ +#define FIP_SIZE 0x001b0000 /* absolute max */ +#else +/* + * same as above, but bootrom can only load an image (l-loader.bin) of + * 1024KB max, so after deducting the size of l-loader + bl1.bin (256KB), + * that leaves 768KB (0x000c0000) for fip.bin + */ +#define FIP_SIZE 0x000c0000 /* absolute max */ +#endif + + /* BL1_OFFSET */ /* (Defined above) */ +#define BL1_BASE (LLOADER_TEXT_BASE + BL1_OFFSET) +#define BL1_LIMIT (BL1_BASE + BL1_SIZE) + +#define BL1_RO_OFFSET (BL1_OFFSET) +#define BL1_RO_BASE (LLOADER_TEXT_BASE + BL1_RO_OFFSET) +#define BL1_RO_LIMIT (BL1_RO_BASE + BL1_RO_SIZE) + +#define BL1_RW_OFFSET (BL1_RO_OFFSET + BL1_RO_SIZE) +#define BL1_RW_BASE (LLOADER_TEXT_BASE + BL1_RW_OFFSET) +#define BL1_RW_LIMIT (BL1_RW_BASE + BL1_RW_SIZE) + +#define BL2_OFFSET (BL1_OFFSET + BL1_SIZE) +#define BL2_BASE (LLOADER_TEXT_BASE + BL2_OFFSET) +#define BL2_LIMIT (BL2_BASE + BL2_SIZE) + +#define BL31_OFFSET (BL2_OFFSET + BL2_SIZE) +#define BL31_BASE (LLOADER_TEXT_BASE + BL31_OFFSET) +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +#endif /* POPLAR_LAYOUT_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c b/arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c new file mode 100644 index 0000000..67ebca1 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hi3798cv200.h" +#include "plat_private.h" + +#define REG_PERI_CPU_RVBARADDR 0xF8A80034 +#define REG_PERI_CPU_AARCH_MODE 0xF8A80030 + +#define REG_CPU_LP_CPU_SW_BEGIN 10 +#define CPU_REG_COREPO_SRST 12 +#define CPU_REG_CORE_SRST 8 + +static void poplar_cpu_standby(plat_local_state_t cpu_state) +{ + dsb(); + wfi(); +} + +static int poplar_pwr_domain_on(u_register_t mpidr) +{ + unsigned int cpu = plat_core_pos_by_mpidr(mpidr); + unsigned int regval, regval_bak; + + /* Select 400MHz before start slave cores */ + regval_bak = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP)); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x206); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x606); + + /* Clear the slave cpu arm_por_srst_req reset */ + regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST)); + regval &= ~(1 << (cpu + CPU_REG_COREPO_SRST)); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval); + + /* Clear the slave cpu reset */ + regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST)); + regval &= ~(1 << (cpu + CPU_REG_CORE_SRST)); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval); + + /* Restore cpu frequency */ + regval = regval_bak & (~(1 << REG_CPU_LP_CPU_SW_BEGIN)); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval); + mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval_bak); + + return PSCI_E_SUCCESS; +} + +static void poplar_pwr_domain_off(const psci_power_state_t *target_state) +{ + assert(0); +} + +static void poplar_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + assert(0); +} + +static void poplar_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_MAX_OFF_STATE); + + /* Enable the gic cpu interface */ + poplar_gic_pcpu_init(); + + /* Program the gic per-cpu distributor or re-distributor interface */ + poplar_gic_cpuif_enable(); +} + +static void poplar_pwr_domain_suspend_finish( + const psci_power_state_t *target_state) +{ + assert(0); +} + +static void __dead2 poplar_system_off(void) +{ + ERROR("Poplar System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 poplar_system_reset(void) +{ + mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551); + mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x0), 0x00000100); + mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8), 0x00000003); + + wfi(); + ERROR("Poplar System Reset: operation not handled.\n"); + panic(); +} + +static int32_t poplar_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); + + int pstate = psci_get_pstate_type(power_state); + + assert(req_state); + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + else + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE; + + /* We expect the 'state id' to be zero */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +static int poplar_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint >= DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE))) + return PSCI_E_SUCCESS; + + return PSCI_E_INVALID_ADDRESS; +} + +static void poplar_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +static const plat_psci_ops_t poplar_plat_psci_ops = { + .cpu_standby = poplar_cpu_standby, + .pwr_domain_on = poplar_pwr_domain_on, + .pwr_domain_off = poplar_pwr_domain_off, + .pwr_domain_suspend = poplar_pwr_domain_suspend, + .pwr_domain_on_finish = poplar_pwr_domain_on_finish, + .pwr_domain_suspend_finish = poplar_pwr_domain_suspend_finish, + .system_off = poplar_system_off, + .system_reset = poplar_system_reset, + .validate_power_state = poplar_validate_power_state, + .validate_ns_entrypoint = poplar_validate_ns_entrypoint, + .get_sys_suspend_power_state = poplar_get_sys_suspend_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &poplar_plat_psci_ops; + + mmio_write_32((uintptr_t)REG_PERI_CPU_AARCH_MODE, 0xF); + mmio_write_32((uintptr_t)REG_PERI_CPU_RVBARADDR, sec_entrypoint); + return 0; +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c b/arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c new file mode 100644 index 0000000..a17e0f1 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 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 +#include +#include +#include +#include +#include +#include + +#if !POPLAR_RECOVERY +static const io_dev_connector_t *emmc_dev_con; +static uintptr_t emmc_dev_handle; +static int open_emmc(const uintptr_t spec); + +static const io_block_spec_t emmc_fip_spec = { + .offset = FIP_BASE_EMMC, + .length = FIP_SIZE +}; + +static const io_block_dev_spec_t emmc_dev_spec = { + .buffer = { + .offset = POPLAR_EMMC_DATA_BASE, + .length = POPLAR_EMMC_DATA_SIZE, + }, + .ops = { + .read = mmc_read_blocks, + .write = mmc_write_blocks, + }, + .block_size = MMC_BLOCK_SIZE, +}; +#else +static const io_dev_connector_t *mmap_dev_con; +static uintptr_t mmap_dev_handle; +static int open_mmap(const uintptr_t spec); + +static const io_block_spec_t loader_fip_spec = { + .offset = FIP_BASE, + .length = FIP_SIZE +}; +#endif + +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static int open_fip(const uintptr_t spec); + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const struct plat_io_policy policies[] = { +#if !POPLAR_RECOVERY + [FIP_IMAGE_ID] = { + &emmc_dev_handle, + (uintptr_t)&emmc_fip_spec, + open_emmc + }, +#else + [FIP_IMAGE_ID] = { + &mmap_dev_handle, + (uintptr_t)&loader_fip_spec, + open_mmap + }, +#endif + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, +}; + +#if !POPLAR_RECOVERY +static int open_emmc(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(emmc_dev_handle, spec, &local_image_handle); + if (result == 0) { + INFO("Using eMMC\n"); + io_close(local_image_handle); + } else { + ERROR("error opening emmc\n"); + } + } else { + ERROR("error initializing emmc\n"); + } + + return result; +} +#else +static int open_mmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(mmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(mmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + INFO("Using mmap\n"); + io_close(local_image_handle); + } else { + ERROR("error opening mmap\n"); + } + } else { + ERROR("error initializing mmap\n"); + } + + return result; +} +#endif + +static int open_fip(const uintptr_t spec) +{ + uintptr_t local_image_handle; + int result; + + result = io_dev_init(fip_dev_handle, (uintptr_t) FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + INFO("Using FIP\n"); + io_close(local_image_handle); + } else { + ERROR("error opening fip\n"); + } + } else { + ERROR("error initializing fip\n"); + } + + return result; +} + +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; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + assert(result == 0); + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return result; +} + +void plat_io_setup(void) +{ + int result; + +#if !POPLAR_RECOVERY + result = register_io_dev_block(&emmc_dev_con); +#else + result = register_io_dev_memmap(&mmap_dev_con); +#endif + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + +#if !POPLAR_RECOVERY + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); +#else + result = io_dev_open(fip_dev_con, (uintptr_t)&loader_fip_spec, + &fip_dev_handle); +#endif + assert(result == 0); + +#if !POPLAR_RECOVERY + result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec, + &emmc_dev_handle); +#else + result = io_dev_open(mmap_dev_con, (uintptr_t)NULL, &mmap_dev_handle); +#endif + assert(result == 0); + + (void) result; +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c b/arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c new file mode 100644 index 0000000..764008e --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "plat_private.h" + +const unsigned char hisi_power_domain_tree_desc[] = { + PLATFORM_CLUSTER_COUNT, + PLATFORM_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return hisi_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + return -1; + + if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) + return -1; + + return poplar_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/platform.mk b/arm-trusted-firmware/plat/hisilicon/poplar/platform.mk new file mode 100644 index 0000000..b5d9867 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/platform.mk @@ -0,0 +1,112 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# On Poplar, the TSP can execute from TZC secure area in DRAM. +POPLAR_TSP_RAM_LOCATION ?= dram +ifeq (${POPLAR_TSP_RAM_LOCATION}, dram) + POPLAR_TSP_RAM_LOCATION_ID = POPLAR_DRAM_ID +else ifeq (${POPLAR_TSP_RAM_LOCATION}, sram) + POPLAR_TSP_RAM_LOCATION_ID = POPLAR_SRAM_ID +else + $(error "Currently unsupported POPLAR_TSP_RAM_LOCATION value") +endif +$(eval $(call add_define,POPLAR_TSP_RAM_LOCATION_ID)) + +POPLAR_DRAM_SIZE ?= two_gig +ifeq (${POPLAR_DRAM_SIZE}, two_gig) + POPLAR_DRAM_SIZE_ID = POPLAR_DRAM_SIZE_2G +else ifeq (${POPLAR_DRAM_SIZE}, one_gig) + POPLAR_DRAM_SIZE_ID = POPLAR_DRAM_SIZE_1G +else + $(error "Currently unsupported POPLAR_DRAM_SIZE value") +endif +$(eval $(call add_define,POPLAR_DRAM_SIZE_ID)) + +POPLAR_RECOVERY := 0 +$(eval $(call add_define,POPLAR_RECOVERY)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif + +NEED_BL33 := yes + +COLD_BOOT_SINGLE_CPU := 1 +PROGRAMMABLE_RESET_ADDRESS := 1 +CTX_INCLUDE_FPREGS := 1 +ERRATA_A53_855873 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ENABLE_SVE_FOR_NS := 0 +WORKAROUND_CVE_2017_5715 := 0 + +PLAT_PL061_MAX_GPIOS := 104 +$(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) + +PLAT_INCLUDES := -Iplat/hisilicon/poplar/include \ + -Iplat/hisilicon/poplar + +PLAT_BL_COMMON_SOURCES := \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/delay_timer/delay_timer.c \ + drivers/arm/pl011/aarch64/pl011_console.S \ + drivers/arm/gic/v2/gicv2_main.c \ + plat/common/plat_gicv2.c \ + plat/hisilicon/poplar/aarch64/platform_common.c \ + plat/hisilicon/poplar/aarch64/poplar_helpers.S \ + plat/hisilicon/poplar/poplar_gicv2.c + +BL1_SOURCES += \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/mmc/mmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ + drivers/io/io_storage.c \ + drivers/io/io_block.c \ + drivers/gpio/gpio.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + plat/hisilicon/poplar/bl1_plat_setup.c \ + plat/hisilicon/poplar/plat_storage.c + +BL2_SOURCES += \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/mmc/mmc.c \ + drivers/synopsys/emmc/dw_mmc.c \ + drivers/io/io_storage.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/gpio/gpio.c \ + drivers/io/io_memmap.c \ + plat/hisilicon/poplar/bl2_plat_setup.c \ + plat/hisilicon/poplar/plat_storage.c + +BL2_SOURCES += \ + plat/hisilicon/poplar/bl2_plat_mem_params_desc.c \ + plat/hisilicon/poplar/poplar_image_load.c \ + common/desc_image_load.c + +ifeq (${SPD},opteed) +BL2_SOURCES += \ + lib/optee/optee_utils.c +endif + +BL31_SOURCES += \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/hisilicon/poplar/bl31_plat_setup.c \ + plat/hisilicon/poplar/plat_topology.c \ + plat/hisilicon/poplar/plat_pm.c diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c b/arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c new file mode 100644 index 0000000..59f7b76 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t poplar_interrupt_props[] = { + POPLAR_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + POPLAR_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const gicv2_driver_data_t poplar_gic_data = { + .gicd_base = POPLAR_GICD_BASE, + .gicc_base = POPLAR_GICC_BASE, + .interrupt_props = poplar_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(poplar_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/****************************************************************************** + * Helper to initialize the GICv2 only driver. + *****************************************************************************/ +void poplar_gic_driver_init(void) +{ + gicv2_driver_init(&poplar_gic_data); +} + +void poplar_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Helper to enable the GICv2 CPU interface + *****************************************************************************/ +void poplar_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Helper to initialize the per cpu distributor interface in GICv2 + *****************************************************************************/ +void poplar_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c b/arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c new file mode 100644 index 0000000..0ab1ca4 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S b/arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S new file mode 100644 index 0000000..1a1229a --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "imx_uart.h" + + .globl console_imx_uart_register + .globl console_imx_uart_putc + .globl console_imx_uart_getc + .globl console_imx_uart_flush + +func console_imx_uart_register + push {r4, lr} + mov r4, r3 + cmp r4, #0 + beq register_fail + str r0, [r4, #CONSOLE_T_BASE] + + bl console_imx_uart_core_init + cmp r0, #0 + bne register_fail + + mov r0, r4 + pop {r4, lr} + finish_console_register imx_uart putc=1, getc=1, flush=1 + +register_fail: + pop {r4, pc} +endfunc console_imx_uart_register + +func console_imx_uart_putc + ldr r1, [r1, #CONSOLE_T_BASE] + b console_imx_uart_core_putc +endfunc console_imx_uart_putc + +func console_imx_uart_getc + ldr r0, [r0, #CONSOLE_T_BASE] + b console_imx_uart_core_getc +endfunc console_imx_uart_getc + +func console_imx_uart_flush + ldr r0, [r0, #CONSOLE_T_BASE] + b console_imx_uart_core_flush +endfunc console_imx_uart_flush diff --git a/arm-trusted-firmware/plat/imx/common/imx7_clock.c b/arm-trusted-firmware/plat/imx/common/imx7_clock.c new file mode 100644 index 0000000..6bd2e0e --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx7_clock.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + +static void imx7_clock_uart_init(void) +{ + unsigned int i; + + for (i = 0; i < MXC_MAX_UART_NUM; i++) + imx_clock_disable_uart(i); +} + +static void imx7_clock_wdog_init(void) +{ + unsigned int i; + + for (i = 0; i < MXC_MAX_WDOG_NUM; i++) + imx_clock_disable_wdog(i); +} + +static void imx7_clock_usb_init(void) +{ + /* Disable the clock root */ + imx_clock_target_clr(CCM_TRT_ID_USB_HSIC_CLK_ROOT, 0xFFFFFFFF); +} + +void imx_clock_init(void) +{ + /* + * The BootROM hands off to the next stage with the internal 24 MHz XTAL + * crystal already clocking the main PLL, which is very handy. + * Here we should enable whichever peripherals are required for ATF and + * OPTEE. + * + * Subsequent stages in the boot process such as u-boot and Linux + * already have a significant and mature code-base around clocks, so our + * objective should be to enable what we need for ATF/OPTEE without + * breaking any existing upstream code in Linux and u-boot. + */ + + /* Initialize UART clocks */ + imx7_clock_uart_init(); + + /* Watchdog clocks */ + + imx7_clock_wdog_init(); + + /* USB clocks */ + imx7_clock_usb_init(); + +} diff --git a/arm-trusted-firmware/plat/imx/common/imx8_helpers.S b/arm-trusted-firmware/plat/imx/common/imx8_helpers.S new file mode 100644 index 0000000..19293bf --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx8_helpers.S @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_calc_core_pos + .globl plat_reset_handler + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + .globl imx_mailbox_init + + /* -------------------------------------------------------------------- + * 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 + + /* ---------------------------------------------- + * The mailbox_base is used to distinguish warm/cold + * reset. The mailbox_base is in the data section, not + * in .bss, this allows function to start using this + * variable before the runtime memory is initialized. + * ---------------------------------------------- + */ + .section .data.mailbox_base + .align 3 + mailbox_base: .quad 0x0 + + /* ---------------------------------------------- + * unsigned int plat_is_my_cpu_primary(void); + * This function checks if this is the primary CPU + * ---------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ---------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This Function uses the plat_calc_core_pos() + * to get the index of the calling CPU. + * ---------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos + + /* + * unsigned int plat_calc_core_pos(uint64_t mpidr) + * helper function to calculate the core position. + * With this function. + */ +func plat_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_calc_core_pos + + /* --------------------------------------------- + * function to get the entrypoint. + * --------------------------------------------- + */ +func plat_get_my_entrypoint + adrp x1, mailbox_base + ldr x0, [x1, :lo12:mailbox_base] + ret +endfunc plat_get_my_entrypoint + +func imx_mailbox_init + adrp x1, mailbox_base + str x0, [x1, :lo12:mailbox_base] + ret +endfunc imx_mailbox_init + +func plat_secondary_cold_boot_setup + b . +endfunc plat_secondary_cold_boot_setup + +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 + +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/arm-trusted-firmware/plat/imx/common/imx8_psci.c b/arm-trusted-firmware/plat/imx/common/imx8_psci.c new file mode 100644 index 0000000..91d3370 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx8_psci.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +void __dead2 imx_system_off(void) +{ + sc_pm_set_sys_power_mode(ipc_handle, SC_PM_PW_MODE_OFF); + wfi(); + ERROR("power off failed.\n"); + panic(); +} + +void __dead2 imx_system_reset(void) +{ + sc_pm_reset(ipc_handle, SC_PM_RESET_TYPE_BOARD); + wfi(); + ERROR("system reset failed.\n"); + panic(); +} + +int imx_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int pwr_type = psci_get_pstate_type(power_state); + int state_id = psci_get_pstate_id(power_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + if (pwr_type == PSTATE_TYPE_POWERDOWN) { + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE; + if (!state_id) + req_state->pwr_domain_state[MPIDR_AFFLVL1] = PLAT_MAX_RET_STATE; + else + req_state->pwr_domain_state[MPIDR_AFFLVL1] = PLAT_MAX_OFF_STATE; + } + + return PSCI_E_SUCCESS; +} + +void imx_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + /* CPU & cluster off, system in retention */ + for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE; +} + diff --git a/arm-trusted-firmware/plat/imx/common/imx8_topology.c b/arm-trusted-firmware/plat/imx/common/imx8_topology.c new file mode 100644 index 0000000..5e14d17 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx8_topology.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +const unsigned char imx_power_domain_tree_desc[] = { + PWR_DOMAIN_AT_MAX_LVL, + PLATFORM_CLUSTER_COUNT, + PLATFORM_CLUSTER0_CORE_COUNT, + PLATFORM_CLUSTER1_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return imx_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (cluster_id > PLATFORM_CLUSTER_COUNT || + cpu_id > PLATFORM_MAX_CPU_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_aips.c b/arm-trusted-firmware/plat/imx/common/imx_aips.c new file mode 100644 index 0000000..532d9c0 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_aips.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +static void imx_aips_set_default_access(struct aipstz_regs *aips_regs) +{ + int i; + uintptr_t addr; + + /* + * See section 4.7.7.1 AIPSTZ_MPR field descriptions + * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016 + * 0111 -> + * 0: Write Access from master not buffered + * 1: Master is trusted for read access + * 1: Master is trsuted for write access + * 1: Access from master is not forced to user mode + */ + addr = (uintptr_t)&aips_regs->aipstz_mpr; + mmio_write_32(addr, 0x77777777); + + /* + * Helpfully the OPACR registers have the logical inversion of the above + * See section 4.7.7.1 AIPSTZ_MPR field descriptions + * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016 + * 0000 -> + * 0: Write Access to the peripheral is not buffered by AIPSTZ + * 0: The peripheral does not require supervisor priv to access + * 0: Master is trsuted for write access + * 0: Access from master is not forced to user mode + */ + for (i = 0; i < AIPSTZ_OAPCR_COUNT; i++) { + addr = (uintptr_t)&aips_regs->aipstz_opacr[i]; + mmio_write_32(addr, 0x00000000); + } +} + +void imx_aips_init(void) +{ + int i; + struct aipstz_regs *aips_regs[] = { + (struct aipstz_regs *)(AIPS1_BASE + AIPSTZ_CONFIG_OFFSET), + (struct aipstz_regs *)(AIPS2_BASE + AIPSTZ_CONFIG_OFFSET), + (struct aipstz_regs *)(AIPS3_BASE + AIPSTZ_CONFIG_OFFSET), + }; + + for (i = 0; i < ARRAY_SIZE(aips_regs); i++) + imx_aips_set_default_access(aips_regs[i]); +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_caam.c b/arm-trusted-firmware/plat/imx/common/imx_caam.c new file mode 100644 index 0000000..d9c141f --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_caam.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +void imx_caam_init(void) +{ + struct caam_ctrl *caam = (struct caam_ctrl *)CAAM_AIPS_BASE; + uint32_t reg; + int i; + + for (i = 0; i < CAAM_NUM_JOB_RINGS; i++) { + reg = mmio_read_32((uintptr_t)&caam->jr[i].jrmidr_ms); + reg |= JROWN_NS | JROWN_MID; + mmio_write_32((uintptr_t)&caam->jr[i].jrmidr_ms, reg); + } +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_clock.c b/arm-trusted-firmware/plat/imx/common/imx_clock.c new file mode 100644 index 0000000..743de55 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_clock.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#include +#include + +void imx_clock_target_set(unsigned int id, uint32_t val) +{ + struct ccm *ccm = ((struct ccm *)CCM_BASE); + uintptr_t addr; + + if (id > CCM_ROOT_CTRL_NUM) + return; + + addr = (uintptr_t)&ccm->ccm_root_ctrl[id].ccm_target_root; + mmio_write_32(addr, val); +} + +void imx_clock_target_clr(unsigned int id, uint32_t val) +{ + struct ccm *ccm = ((struct ccm *)CCM_BASE); + uintptr_t addr; + + if (id > CCM_ROOT_CTRL_NUM) + return; + + addr = (uintptr_t)&ccm->ccm_root_ctrl[id].ccm_target_root_clr; + mmio_write_32(addr, val); +} + +void imx_clock_gate_enable(unsigned int id, bool enable) +{ + struct ccm *ccm = ((struct ccm *)CCM_BASE); + uintptr_t addr; + + if (id > CCM_CLK_GATE_CTRL_NUM) + return; + + /* TODO: add support for more than DOMAIN0 clocks */ + if (enable) + addr = (uintptr_t)&ccm->ccm_clk_gate_ctrl[id].ccm_ccgr_set; + else + addr = (uintptr_t)&ccm->ccm_clk_gate_ctrl[id].ccm_ccgr_clr; + + mmio_write_32(addr, CCM_CCGR_SETTING0_DOM_CLK_ALWAYS); +} + +void imx_clock_enable_uart(unsigned int uart_id, uint32_t uart_clk_en_bits) +{ + unsigned int ccm_trgt_id = CCM_TRT_ID_UART1_CLK_ROOT + uart_id; + unsigned int ccm_ccgr_id = CCM_CCGR_ID_UART1 + uart_id; + + /* Check for error */ + if (uart_id > MXC_MAX_UART_NUM) + return; + + /* Set target register values */ + imx_clock_target_set(ccm_trgt_id, uart_clk_en_bits); + + /* Enable the clock gate */ + imx_clock_gate_enable(ccm_ccgr_id, true); +} + +void imx_clock_disable_uart(unsigned int uart_id) +{ + unsigned int ccm_trgt_id = CCM_TRT_ID_UART1_CLK_ROOT + uart_id; + unsigned int ccm_ccgr_id = CCM_CCGR_ID_UART1 + uart_id; + + /* Check for error */ + if (uart_id > MXC_MAX_UART_NUM) + return; + + /* Disable the clock gate */ + imx_clock_gate_enable(ccm_ccgr_id, false); + + /* Clear the target */ + imx_clock_target_clr(ccm_trgt_id, 0xFFFFFFFF); +} + +void imx_clock_enable_usdhc(unsigned int usdhc_id, uint32_t usdhc_clk_en_bits) +{ + unsigned int ccm_trgt_id = CCM_TRT_ID_USDHC1_CLK_ROOT + usdhc_id; + unsigned int ccm_ccgr_id = CCM_CCGR_ID_USBHDC1 + usdhc_id; + + /* Check for error */ + if (usdhc_id > MXC_MAX_USDHC_NUM) + return; + + /* Set target register values */ + imx_clock_target_set(ccm_trgt_id, usdhc_clk_en_bits); + + /* Enable the clock gate */ + imx_clock_gate_enable(ccm_ccgr_id, true); +} + +void imx_clock_enable_wdog(unsigned int wdog_id) +{ + unsigned int ccm_ccgr_id = CCM_CCGR_ID_WDOG1 + wdog_id; + + /* Check for error */ + if (wdog_id > MXC_MAX_WDOG_NUM) + return; + + /* Enable the clock gate */ + imx_clock_gate_enable(ccm_ccgr_id, true); +} + +void imx_clock_disable_wdog(unsigned int wdog_id) +{ + unsigned int ccm_trgt_id = CCM_TRT_ID_WDOG_CLK_ROOT; + unsigned int ccm_ccgr_id = CCM_CCGR_ID_WDOG1 + wdog_id; + + /* Check for error */ + if (wdog_id > MXC_MAX_WDOG_NUM) + return; + + /* Disable the clock gate */ + imx_clock_gate_enable(ccm_ccgr_id, false); + + /* Clear the target */ + imx_clock_target_clr(ccm_trgt_id, 0xFFFFFFFF); +} + +void imx_clock_set_wdog_clk_root_bits(uint32_t wdog_clk_root_en_bits) +{ + /* Enable the common clock root just once */ + imx_clock_target_set(CCM_TRT_ID_WDOG_CLK_ROOT, wdog_clk_root_en_bits); +} + +void imx_clock_enable_usb(unsigned int ccm_ccgr_usb_id) +{ + /* Enable the clock gate */ + imx_clock_gate_enable(ccm_ccgr_usb_id, true); +} + +void imx_clock_disable_usb(unsigned int ccm_ccgr_usb_id) +{ + /* Disable the clock gate */ + imx_clock_gate_enable(ccm_ccgr_usb_id, false); +} + +void imx_clock_set_usb_clk_root_bits(uint32_t usb_clk_root_en_bits) +{ + /* Enable the common clock root just once */ + imx_clock_target_set(CCM_TRT_ID_USB_HSIC_CLK_ROOT, usb_clk_root_en_bits); +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_csu.c b/arm-trusted-firmware/plat/imx/common/imx_csu.c new file mode 100644 index 0000000..7e165d9 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_csu.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +void imx_csu_init(void) +{ + int i; + uintptr_t *csl_reg = (uintptr_t *)CSU_BASE; + + for (i = 0; i < MXC_MAX_CSU_REGS; i++, csl_reg++) + mmio_write_32((uintptr_t)csl_reg, CSU_CSL_OPEN_ACCESS); +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_ehf.c b/arm-trusted-firmware/plat/imx/common/imx_ehf.c new file mode 100644 index 0000000..a9396cd --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_ehf.c @@ -0,0 +1,22 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +ehf_pri_desc_t imx_exceptions[] = { +#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 +}; + +/* Plug in ARM exceptions to Exception Handling Framework. */ +EHF_REGISTER_PRIORITIES(imx_exceptions, ARRAY_SIZE(imx_exceptions), PLAT_PRI_BITS); diff --git a/arm-trusted-firmware/plat/imx/common/imx_io_mux.c b/arm-trusted-firmware/plat/imx/common/imx_io_mux.c new file mode 100644 index 0000000..75de5d1 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_io_mux.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +void imx_io_muxc_set_pad_alt_function(uint32_t pad_mux_offset, uint32_t alt_function) +{ + uintptr_t addr = (uintptr_t)(MXC_IO_MUXC_BASE + pad_mux_offset); + + mmio_write_32(addr, alt_function); +} + +void imx_io_muxc_set_pad_features(uint32_t pad_feature_offset, uint32_t pad_features) +{ + uintptr_t addr = (uintptr_t)(MXC_IO_MUXC_BASE + pad_feature_offset); + + mmio_write_32(addr, pad_features); +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_io_storage.c b/arm-trusted-firmware/plat/imx/common/imx_io_storage.c new file mode 100644 index 0000000..bb35662 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_io_storage.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 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 + +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; + +#ifndef IMX_FIP_MMAP +static const io_dev_connector_t *mmc_dev_con; +static uintptr_t mmc_dev_handle; + +static const io_block_spec_t mmc_fip_spec = { + .offset = IMX_FIP_MMC_BASE, + .length = IMX_FIP_SIZE +}; + +static const io_block_dev_spec_t mmc_dev_spec = { + /* It's used as temp buffer in block driver. */ + .buffer = { + .offset = IMX_FIP_BASE, + /* do we need a new value? */ + .length = IMX_FIP_SIZE + }, + .ops = { + .read = mmc_read_blocks, + .write = mmc_write_blocks, + }, + .block_size = MMC_BLOCK_SIZE, +}; + +static int open_mmc(const uintptr_t spec); + +#else +static const io_dev_connector_t *memmap_dev_con; +static uintptr_t memmap_dev_handle; + +static const io_block_spec_t fip_block_spec = { + .offset = IMX_FIP_BASE, + .length = IMX_FIP_SIZE +}; +static int open_memmap(const uintptr_t spec); +#endif + +static int open_fip(const uintptr_t spec); + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t tb_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FW_CERT, +}; + +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t soc_fw_content_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +/* TODO: this structure is replicated multiple times. rationalize it ! */ +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const struct plat_io_policy policies[] = { +#ifndef IMX_FIP_MMAP + [FIP_IMAGE_ID] = { + &mmc_dev_handle, + (uintptr_t)&mmc_fip_spec, + open_mmc + }, +#else + [FIP_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, +#endif + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_cert_uuid_spec, + open_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + open_fip + }, + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + open_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_content_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + open_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +#ifndef IMX_FIP_MMAP +static int open_mmc(const uintptr_t spec) +{ + int result; + uintptr_t local_handle; + + result = io_dev_init(mmc_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(mmc_dev_handle, spec, &local_handle); + if (result == 0) { + io_close(local_handle); + } + } + return result; +} +#else +static int open_memmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Memmap\n"); + io_close(local_image_handle); + } + } + return result; +} +#endif + +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + assert(result == 0); + + *image_spec = policy->image_spec; + *dev_handle = *policy->dev_handle; + + return result; +} + +void plat_imx_io_setup(void) +{ + int result __unused; + +#ifndef IMX_FIP_MMAP + result = register_io_dev_block(&mmc_dev_con); + assert(result == 0); + + result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_dev_spec, + &mmc_dev_handle); + assert(result == 0); + +#else + result = register_io_dev_memmap(&memmap_dev_con); + assert(result == 0); + + result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &memmap_dev_handle); + assert(result == 0); +#endif + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + assert(result == 0); +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_sdei.c b/arm-trusted-firmware/plat/imx/common/imx_sdei.c new file mode 100644 index 0000000..4b6033f --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_sdei.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* SDEI configuration for ARM platforms */ + +#include +#include +#include +#include + +#include + +/* Private event mappings */ +static sdei_ev_map_t imx_sdei_private[] = { + SDEI_DEFINE_EVENT_0(PLAT_SDEI_SGI_PRIVATE), +}; + +/* Shared event mappings */ +static sdei_ev_map_t imx_sdei_shared[] = { +}; + +void plat_sdei_setup(void) +{ + INFO("SDEI platform setup\n"); +} + +/* Export ARM SDEI events */ +REGISTER_SDEI_MAP(imx_sdei_private, imx_sdei_shared); diff --git a/arm-trusted-firmware/plat/imx/common/imx_sip_handler.c b/arm-trusted-firmware/plat/imx/common/imx_sip_handler.c new file mode 100644 index 0000000..d4b3425 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_sip_handler.c @@ -0,0 +1,255 @@ +/* + * Copyright 2019 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PLAT_imx8qm) || defined(PLAT_imx8qx) + +#ifdef PLAT_imx8qm +const static int ap_cluster_index[PLATFORM_CLUSTER_COUNT] = { + SC_R_A53, SC_R_A72, +}; +#endif + +static int imx_srtc_set_time(uint32_t year_mon, + unsigned long day_hour, + unsigned long min_sec) +{ + return sc_timer_set_rtc_time(ipc_handle, + year_mon >> 16, year_mon & 0xffff, + day_hour >> 16, day_hour & 0xffff, + min_sec >> 16, min_sec & 0xffff); +} + +int imx_srtc_handler(uint32_t smc_fid, + void *handle, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4) +{ + int ret; + + switch (x1) { + case IMX_SIP_SRTC_SET_TIME: + ret = imx_srtc_set_time(x2, x3, x4); + break; + default: + ret = SMC_UNK; + } + + SMC_RET1(handle, ret); +} + +static void imx_cpufreq_set_target(uint32_t cluster_id, unsigned long freq) +{ + sc_pm_clock_rate_t rate = (sc_pm_clock_rate_t)freq; + +#ifdef PLAT_imx8qm + sc_pm_set_clock_rate(ipc_handle, ap_cluster_index[cluster_id], SC_PM_CLK_CPU, &rate); +#endif +#ifdef PLAT_imx8qx + sc_pm_set_clock_rate(ipc_handle, SC_R_A35, SC_PM_CLK_CPU, &rate); +#endif +} + +int imx_cpufreq_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3) +{ + switch (x1) { + case IMX_SIP_SET_CPUFREQ: + imx_cpufreq_set_target(x2, x3); + break; + default: + return SMC_UNK; + } + + return 0; +} + +static bool wakeup_src_irqsteer; + +bool imx_is_wakeup_src_irqsteer(void) +{ + return wakeup_src_irqsteer; +} + +int imx_wakeup_src_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3) +{ + switch (x1) { + case IMX_SIP_WAKEUP_SRC_IRQSTEER: + wakeup_src_irqsteer = true; + break; + case IMX_SIP_WAKEUP_SRC_SCU: + wakeup_src_irqsteer = false; + break; + default: + return SMC_UNK; + } + + return SMC_OK; +} + +int imx_otp_handler(uint32_t smc_fid, + void *handle, + u_register_t x1, + u_register_t x2) +{ + int ret; + uint32_t fuse; + + switch (smc_fid) { + case IMX_SIP_OTP_READ: + ret = sc_misc_otp_fuse_read(ipc_handle, x1, &fuse); + SMC_RET2(handle, ret, fuse); + break; + case IMX_SIP_OTP_WRITE: + ret = sc_misc_otp_fuse_write(ipc_handle, x1, x2); + SMC_RET1(handle, ret); + break; + default: + ret = SMC_UNK; + SMC_RET1(handle, ret); + break; + } + + return ret; +} + +int imx_misc_set_temp_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4) +{ + return sc_misc_set_temp(ipc_handle, x1, x2, x3, x4); +} + +#endif /* defined(PLAT_imx8qm) || defined(PLAT_imx8qx) */ + +#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq) +int imx_src_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + void *handle) +{ + uint32_t val; + + switch (x1) { + case IMX_SIP_SRC_SET_SECONDARY_BOOT: + if (x2 != 0U) { + mmio_setbits_32(IMX_SRC_BASE + SRC_GPR10_OFFSET, + SRC_GPR10_PERSIST_SECONDARY_BOOT); + } else { + mmio_clrbits_32(IMX_SRC_BASE + SRC_GPR10_OFFSET, + SRC_GPR10_PERSIST_SECONDARY_BOOT); + } + break; + case IMX_SIP_SRC_IS_SECONDARY_BOOT: + val = mmio_read_32(IMX_SRC_BASE + SRC_GPR10_OFFSET); + return !!(val & SRC_GPR10_PERSIST_SECONDARY_BOOT); + default: + return SMC_UNK; + + }; + + return 0; +} +#endif /* defined(PLAT_imx8mm) || defined(PLAT_imx8mq) */ + +static uint64_t imx_get_commit_hash(u_register_t x2, + u_register_t x3, + u_register_t x4) +{ + /* Parse the version_string */ + char *parse = (char *)version_string; + uint64_t hash = 0; + + do { + parse = strchr(parse, '-'); + if (parse) { + parse += 1; + if (*(parse) == 'g') { + /* Default is 7 hexadecimal digits */ + memcpy((void *)&hash, (void *)(parse + 1), 7); + break; + } + } + + } while (parse != NULL); + + return hash; +} + +uint64_t imx_buildinfo_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4) +{ + uint64_t ret; + + switch (x1) { + case IMX_SIP_BUILDINFO_GET_COMMITHASH: + ret = imx_get_commit_hash(x2, x3, x4); + break; + default: + return SMC_UNK; + } + + return ret; +} + +int imx_kernel_entry_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4) +{ + static entry_point_info_t bl33_image_ep_info; + entry_point_info_t *next_image_info; + unsigned int mode; + + if (x1 < (PLAT_NS_IMAGE_OFFSET & 0xF0000000)) + return SMC_UNK; + + mode = MODE32_svc; + + next_image_info = &bl33_image_ep_info; + + next_image_info->pc = x1; + + next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE, + (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT)); + + next_image_info->args.arg0 = 0; + next_image_info->args.arg1 = 0; + next_image_info->args.arg2 = x3; + + SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE); + + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(NON_SECURE); + + return 0; +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_sip_svc.c b/arm-trusted-firmware/plat/imx/common/imx_sip_svc.c new file mode 100644 index 0000000..fd54820 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_sip_svc.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +static int32_t imx_sip_setup(void) +{ + return 0; +} + +static uintptr_t imx_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) +{ + switch (smc_fid) { + case IMX_SIP_AARCH32: + SMC_RET1(handle, imx_kernel_entry_handler(smc_fid, x1, x2, x3, x4)); + break; +#if defined(PLAT_imx8mq) + case IMX_SIP_GET_SOC_INFO: + SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3)); + break; +#endif +#if (defined(PLAT_imx8qm) || defined(PLAT_imx8qx)) + case IMX_SIP_SRTC: + return imx_srtc_handler(smc_fid, handle, x1, x2, x3, x4); + case IMX_SIP_CPUFREQ: + SMC_RET1(handle, imx_cpufreq_handler(smc_fid, x1, x2, x3)); + break; + case IMX_SIP_WAKEUP_SRC: + SMC_RET1(handle, imx_wakeup_src_handler(smc_fid, x1, x2, x3)); + case IMX_SIP_OTP_READ: + case IMX_SIP_OTP_WRITE: + return imx_otp_handler(smc_fid, handle, x1, x2); + case IMX_SIP_MISC_SET_TEMP: + SMC_RET1(handle, imx_misc_set_temp_handler(smc_fid, x1, x2, x3, x4)); +#endif +#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq) + case IMX_SIP_SRC: + SMC_RET1(handle, imx_src_handler(smc_fid, x1, x2, x3, handle)); + break; +#endif + case IMX_SIP_BUILDINFO: + SMC_RET1(handle, imx_buildinfo_handler(smc_fid, x1, x2, x3, x4)); + default: + WARN("Unimplemented i.MX SiP Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + break; + } +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + imx_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + imx_sip_setup, + imx_sip_handler +); diff --git a/arm-trusted-firmware/plat/imx/common/imx_snvs.c b/arm-trusted-firmware/plat/imx/common/imx_snvs.c new file mode 100644 index 0000000..9b3a737 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_snvs.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +void imx_snvs_init(void) +{ + struct snvs *snvs = (struct snvs *)SNVS_BASE; + uintptr_t addr; + uint32_t val; + + addr = (uintptr_t)&snvs->hpcomr; + val = mmio_read_32(addr); + val |= HPCOMR_NPSWA_EN; + mmio_write_32(addr, val); +} diff --git a/arm-trusted-firmware/plat/imx/common/imx_uart_console.S b/arm-trusted-firmware/plat/imx/common/imx_uart_console.S new file mode 100644 index 0000000..ceeb3a7 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_uart_console.S @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "imx_uart.h" + +#define URXD 0x0 /* Receiver Register */ +#define UTXD 0x40 /* Transmitter Register */ +#define UTS 0xb4 /* UART Test Register (mx31) */ +#define URXD_RX_DATA (0xFF) + + .globl console_imx_uart_register + .globl console_imx_uart_init + .globl console_imx_uart_putc + .globl console_imx_uart_getc + .globl console_imx_uart_flush + +func console_imx_uart_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_imx_uart_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register imx_uart putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_imx_uart_register + +func console_imx_uart_init + mov w0, #1 + ret +endfunc console_imx_uart_init + +func console_imx_uart_putc + ldr x1, [x1, #CONSOLE_T_BASE] + cbz x1, putc_error + + /* Prepare '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f +1: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #UTS] + tbz w2, #6, 1b + mov w2, #0xD + str w2, [x1, #UTXD] +2: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #UTS] + tbz w2, #6, 2b + str w0, [x1, #UTXD] + ret +putc_error: + mov w0, #-1 + ret +endfunc console_imx_uart_putc + +func console_imx_uart_getc + ldr x0, [x0, #CONSOLE_T_BASE] + cbz x0, getc_error +1: + ldr w1, [x0, #UTS] + tbnz w1, #5, 1b + + ldr w1, [x0, #URXD] + and w0, w1, #URXD_RX_DATA + + ret +getc_error: + mov w0, #-1 + ret +endfunc console_imx_uart_getc + +func console_imx_uart_flush + ret +endfunc console_imx_uart_flush diff --git a/arm-trusted-firmware/plat/imx/common/imx_wdog.c b/arm-trusted-firmware/plat/imx/common/imx_wdog.c new file mode 100644 index 0000000..af6d767 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_wdog.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +static void imx_wdog_power_down(unsigned long base) +{ + struct wdog_regs *wdog = (struct wdog_regs *)base; + + mmio_write_16((uintptr_t)&wdog->wmcr, 0); +} + +void imx_wdog_init(void) +{ + imx_wdog_power_down(WDOG1_BASE); + imx_wdog_power_down(WDOG2_BASE); + imx_wdog_power_down(WDOG3_BASE); + imx_wdog_power_down(WDOG4_BASE); +} diff --git a/arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h b/arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h new file mode 100644 index 0000000..264c295 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8_IOMUX_H +#define IMX8_IOMUX_H + +#define PADRING_IFMUX_EN_SHIFT U(31) +#define PADRING_IFMUX_EN_MASK (U(0x1) << PADRING_IFMUX_EN_SHIFT) +#define PADRING_GP_EN_SHIFT U(30) +#define PADRING_GP_EN_MASK (U(0x1) << PADRING_GP_EN_SHIFT) +#define PADRING_IFMUX_SHIFT U(27) +#define PADRING_IFMUX_MASK (U(0x7) << PADRING_IFMUX_SHIFT) +#define PADRING_CONFIG_SHIFT U(25) +#define PADRING_CONFIG_MASK (U(0x3) << PADRING_CONFIG_SHIFT) +#define PADRING_LPCONFIG_SHIFT U(23) +#define PADRING_LPCONFIG_MASK (U(0x3) << PADRING_LPCONFIG_SHIFT) +#define PADRING_PULL_SHIFT U(5) +#define PADRING_PULL_MASK (U(0x3) << PADRING_PULL_SHIFT) +#define PADRING_DSE_SHIFT U(0) +#define PADRING_DSE_MASK (U(0x7) << PADRING_DSE_SHIFT) + +#endif /* IMX8_IOMUX_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h b/arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h new file mode 100644 index 0000000..26470e0 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8_LPUART_H +#define IMX8_LPUART_H + +#include + +#define VERID 0x0 +#define PARAM 0x4 +#define GLOBAL 0x8 +#define PINCFG 0xC +#define BAUD 0x10 +#define STAT 0x14 +#define CTRL 0x18 +#define DATA 0x1C +#define MATCH 0x20 +#define MODIR 0x24 +#define FIFO 0x28 +#define WATER 0x2c + +#define US1_TDRE (1 << 23) +#define US1_RDRF (1 << 21) + +#define CTRL_TE (1 << 19) +#define CTRL_RE (1 << 18) + +#define FIFO_TXFE 0x80 +#define FIFO_RXFE 0x40 + +#define WATER_TXWATER_OFF 1 +#define WATER_RXWATER_OFF 16 + +#define LPUART_CTRL_PT_MASK 0x1 +#define LPUART_CTRL_PE_MASK 0x2 +#define LPUART_CTRL_M_MASK 0x10 + +#define LPUART_BAUD_OSR_MASK (0x1F000000U) +#define LPUART_BAUD_OSR_SHIFT (24U) +#define LPUART_BAUD_OSR(x) (((uint32_t)(((uint32_t)(x)) << LPUART_BAUD_OSR_SHIFT)) & LPUART_BAUD_OSR_MASK) + +#define LPUART_BAUD_SBR_MASK (0x1FFFU) +#define LPUART_BAUD_SBR_SHIFT (0U) +#define LPUART_BAUD_SBR(x) (((uint32_t)(((uint32_t)(x)) << LPUART_BAUD_SBR_SHIFT)) & LPUART_BAUD_SBR_MASK) + +#define LPUART_BAUD_SBNS_MASK (0x2000U) +#define LPUART_BAUD_BOTHEDGE_MASK (0x20000U) +#define LPUART_BAUD_M10_MASK (0x20000000U) + +#ifndef __ASSEMBLER__ + +#include + +int console_lpuart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); +#endif /*__ASSEMBLER__*/ + +#endif /* IMX8_LPUART_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h b/arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h new file mode 100644 index 0000000..a5c1d2c --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file used to configure SoC pad list. + */ + +#ifndef IMX8QM_PADS_H +#define IMX8QM_PADS_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Pad Definitions + */ +/*@{*/ +#define SC_P_SIM0_CLK 0 /* DMA.SIM0.CLK, LSIO.GPIO0.IO00 */ +#define SC_P_SIM0_RST 1 /* DMA.SIM0.RST, LSIO.GPIO0.IO01 */ +#define SC_P_SIM0_IO 2 /* DMA.SIM0.IO, LSIO.GPIO0.IO02 */ +#define SC_P_SIM0_PD 3 /* DMA.SIM0.PD, DMA.I2C3.SCL, LSIO.GPIO0.IO03 */ +#define SC_P_SIM0_POWER_EN 4 /* DMA.SIM0.POWER_EN, DMA.I2C3.SDA, LSIO.GPIO0.IO04 */ +#define SC_P_SIM0_GPIO0_00 5 /* DMA.SIM0.POWER_EN, LSIO.GPIO0.IO05 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_SIM 6 /* */ +#define SC_P_M40_I2C0_SCL 7 /* M40.I2C0.SCL, M40.UART0.RX, M40.GPIO0.IO02, LSIO.GPIO0.IO06 */ +#define SC_P_M40_I2C0_SDA 8 /* M40.I2C0.SDA, M40.UART0.TX, M40.GPIO0.IO03, LSIO.GPIO0.IO07 */ +#define SC_P_M40_GPIO0_00 9 /* M40.GPIO0.IO00, M40.TPM0.CH0, DMA.UART4.RX, LSIO.GPIO0.IO08 */ +#define SC_P_M40_GPIO0_01 10 /* M40.GPIO0.IO01, M40.TPM0.CH1, DMA.UART4.TX, LSIO.GPIO0.IO09 */ +#define SC_P_M41_I2C0_SCL 11 /* M41.I2C0.SCL, M41.UART0.RX, M41.GPIO0.IO02, LSIO.GPIO0.IO10 */ +#define SC_P_M41_I2C0_SDA 12 /* M41.I2C0.SDA, M41.UART0.TX, M41.GPIO0.IO03, LSIO.GPIO0.IO11 */ +#define SC_P_M41_GPIO0_00 13 /* M41.GPIO0.IO00, M41.TPM0.CH0, DMA.UART3.RX, LSIO.GPIO0.IO12 */ +#define SC_P_M41_GPIO0_01 14 /* M41.GPIO0.IO01, M41.TPM0.CH1, DMA.UART3.TX, LSIO.GPIO0.IO13 */ +#define SC_P_GPT0_CLK 15 /* LSIO.GPT0.CLK, DMA.I2C1.SCL, LSIO.KPP0.COL4, LSIO.GPIO0.IO14 */ +#define SC_P_GPT0_CAPTURE 16 /* LSIO.GPT0.CAPTURE, DMA.I2C1.SDA, LSIO.KPP0.COL5, LSIO.GPIO0.IO15 */ +#define SC_P_GPT0_COMPARE 17 /* LSIO.GPT0.COMPARE, LSIO.PWM3.OUT, LSIO.KPP0.COL6, LSIO.GPIO0.IO16 */ +#define SC_P_GPT1_CLK 18 /* LSIO.GPT1.CLK, DMA.I2C2.SCL, LSIO.KPP0.COL7, LSIO.GPIO0.IO17 */ +#define SC_P_GPT1_CAPTURE 19 /* LSIO.GPT1.CAPTURE, DMA.I2C2.SDA, LSIO.KPP0.ROW4, LSIO.GPIO0.IO18 */ +#define SC_P_GPT1_COMPARE 20 /* LSIO.GPT1.COMPARE, LSIO.PWM2.OUT, LSIO.KPP0.ROW5, LSIO.GPIO0.IO19 */ +#define SC_P_UART0_RX 21 /* DMA.UART0.RX, SCU.UART0.RX, LSIO.GPIO0.IO20 */ +#define SC_P_UART0_TX 22 /* DMA.UART0.TX, SCU.UART0.TX, LSIO.GPIO0.IO21 */ +#define SC_P_UART0_RTS_B 23 /* DMA.UART0.RTS_B, LSIO.PWM0.OUT, DMA.UART2.RX, LSIO.GPIO0.IO22 */ +#define SC_P_UART0_CTS_B 24 /* DMA.UART0.CTS_B, LSIO.PWM1.OUT, DMA.UART2.TX, LSIO.GPIO0.IO23 */ +#define SC_P_UART1_TX 25 /* DMA.UART1.TX, DMA.SPI3.SCK, LSIO.GPIO0.IO24 */ +#define SC_P_UART1_RX 26 /* DMA.UART1.RX, DMA.SPI3.SDO, LSIO.GPIO0.IO25 */ +#define SC_P_UART1_RTS_B 27 /* DMA.UART1.RTS_B, DMA.SPI3.SDI, DMA.UART1.CTS_B, LSIO.GPIO0.IO26 */ +#define SC_P_UART1_CTS_B 28 /* DMA.UART1.CTS_B, DMA.SPI3.CS0, DMA.UART1.RTS_B, LSIO.GPIO0.IO27 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLH 29 /* */ +#define SC_P_SCU_PMIC_MEMC_ON 30 /* SCU.GPIO0.IOXX_PMIC_MEMC_ON */ +#define SC_P_SCU_WDOG_OUT 31 /* SCU.WDOG0.WDOG_OUT */ +#define SC_P_PMIC_I2C_SDA 32 /* SCU.PMIC_I2C.SDA */ +#define SC_P_PMIC_I2C_SCL 33 /* SCU.PMIC_I2C.SCL */ +#define SC_P_PMIC_EARLY_WARNING 34 /* SCU.PMIC_EARLY_WARNING */ +#define SC_P_PMIC_INT_B 35 /* SCU.DSC.PMIC_INT_B */ +#define SC_P_SCU_GPIO0_00 36 /* SCU.GPIO0.IO00, SCU.UART0.RX, LSIO.GPIO0.IO28 */ +#define SC_P_SCU_GPIO0_01 37 /* SCU.GPIO0.IO01, SCU.UART0.TX, LSIO.GPIO0.IO29 */ +#define SC_P_SCU_GPIO0_02 38 /* SCU.GPIO0.IO02, SCU.GPIO0.IOXX_PMIC_GPU0_ON, LSIO.GPIO0.IO30 */ +#define SC_P_SCU_GPIO0_03 39 /* SCU.GPIO0.IO03, SCU.GPIO0.IOXX_PMIC_GPU1_ON, LSIO.GPIO0.IO31 */ +#define SC_P_SCU_GPIO0_04 40 /* SCU.GPIO0.IO04, SCU.GPIO0.IOXX_PMIC_A72_ON, LSIO.GPIO1.IO00 */ +#define SC_P_SCU_GPIO0_05 41 /* SCU.GPIO0.IO05, SCU.GPIO0.IOXX_PMIC_A53_ON, LSIO.GPIO1.IO01 */ +#define SC_P_SCU_GPIO0_06 42 /* SCU.GPIO0.IO06, SCU.TPM0.CH0, LSIO.GPIO1.IO02 */ +#define SC_P_SCU_GPIO0_07 43 /* SCU.GPIO0.IO07, SCU.TPM0.CH1, SCU.DSC.RTC_CLOCK_OUTPUT_32K, LSIO.GPIO1.IO03 */ +#define SC_P_SCU_BOOT_MODE0 44 /* SCU.DSC.BOOT_MODE0 */ +#define SC_P_SCU_BOOT_MODE1 45 /* SCU.DSC.BOOT_MODE1 */ +#define SC_P_SCU_BOOT_MODE2 46 /* SCU.DSC.BOOT_MODE2 */ +#define SC_P_SCU_BOOT_MODE3 47 /* SCU.DSC.BOOT_MODE3 */ +#define SC_P_SCU_BOOT_MODE4 48 /* SCU.DSC.BOOT_MODE4, SCU.PMIC_I2C.SCL */ +#define SC_P_SCU_BOOT_MODE5 49 /* SCU.DSC.BOOT_MODE5, SCU.PMIC_I2C.SDA */ +#define SC_P_LVDS0_GPIO00 50 /* LVDS0.GPIO0.IO00, LVDS0.PWM0.OUT, LSIO.GPIO1.IO04 */ +#define SC_P_LVDS0_GPIO01 51 /* LVDS0.GPIO0.IO01, LSIO.GPIO1.IO05 */ +#define SC_P_LVDS0_I2C0_SCL 52 /* LVDS0.I2C0.SCL, LVDS0.GPIO0.IO02, LSIO.GPIO1.IO06 */ +#define SC_P_LVDS0_I2C0_SDA 53 /* LVDS0.I2C0.SDA, LVDS0.GPIO0.IO03, LSIO.GPIO1.IO07 */ +#define SC_P_LVDS0_I2C1_SCL 54 /* LVDS0.I2C1.SCL, DMA.UART2.TX, LSIO.GPIO1.IO08 */ +#define SC_P_LVDS0_I2C1_SDA 55 /* LVDS0.I2C1.SDA, DMA.UART2.RX, LSIO.GPIO1.IO09 */ +#define SC_P_LVDS1_GPIO00 56 /* LVDS1.GPIO0.IO00, LVDS1.PWM0.OUT, LSIO.GPIO1.IO10 */ +#define SC_P_LVDS1_GPIO01 57 /* LVDS1.GPIO0.IO01, LSIO.GPIO1.IO11 */ +#define SC_P_LVDS1_I2C0_SCL 58 /* LVDS1.I2C0.SCL, LVDS1.GPIO0.IO02, LSIO.GPIO1.IO12 */ +#define SC_P_LVDS1_I2C0_SDA 59 /* LVDS1.I2C0.SDA, LVDS1.GPIO0.IO03, LSIO.GPIO1.IO13 */ +#define SC_P_LVDS1_I2C1_SCL 60 /* LVDS1.I2C1.SCL, DMA.UART3.TX, LSIO.GPIO1.IO14 */ +#define SC_P_LVDS1_I2C1_SDA 61 /* LVDS1.I2C1.SDA, DMA.UART3.RX, LSIO.GPIO1.IO15 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_LVDSGPIO 62 /* */ +#define SC_P_MIPI_DSI0_I2C0_SCL 63 /* MIPI_DSI0.I2C0.SCL, LSIO.GPIO1.IO16 */ +#define SC_P_MIPI_DSI0_I2C0_SDA 64 /* MIPI_DSI0.I2C0.SDA, LSIO.GPIO1.IO17 */ +#define SC_P_MIPI_DSI0_GPIO0_00 65 /* MIPI_DSI0.GPIO0.IO00, MIPI_DSI0.PWM0.OUT, LSIO.GPIO1.IO18 */ +#define SC_P_MIPI_DSI0_GPIO0_01 66 /* MIPI_DSI0.GPIO0.IO01, LSIO.GPIO1.IO19 */ +#define SC_P_MIPI_DSI1_I2C0_SCL 67 /* MIPI_DSI1.I2C0.SCL, LSIO.GPIO1.IO20 */ +#define SC_P_MIPI_DSI1_I2C0_SDA 68 /* MIPI_DSI1.I2C0.SDA, LSIO.GPIO1.IO21 */ +#define SC_P_MIPI_DSI1_GPIO0_00 69 /* MIPI_DSI1.GPIO0.IO00, MIPI_DSI1.PWM0.OUT, LSIO.GPIO1.IO22 */ +#define SC_P_MIPI_DSI1_GPIO0_01 70 /* MIPI_DSI1.GPIO0.IO01, LSIO.GPIO1.IO23 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_MIPIDSIGPIO 71 /* */ +#define SC_P_MIPI_CSI0_MCLK_OUT 72 /* MIPI_CSI0.ACM.MCLK_OUT, LSIO.GPIO1.IO24 */ +#define SC_P_MIPI_CSI0_I2C0_SCL 73 /* MIPI_CSI0.I2C0.SCL, LSIO.GPIO1.IO25 */ +#define SC_P_MIPI_CSI0_I2C0_SDA 74 /* MIPI_CSI0.I2C0.SDA, LSIO.GPIO1.IO26 */ +#define SC_P_MIPI_CSI0_GPIO0_00 75 /* MIPI_CSI0.GPIO0.IO00, DMA.I2C0.SCL, MIPI_CSI1.I2C0.SCL, LSIO.GPIO1.IO27 */ +#define SC_P_MIPI_CSI0_GPIO0_01 76 /* MIPI_CSI0.GPIO0.IO01, DMA.I2C0.SDA, MIPI_CSI1.I2C0.SDA, LSIO.GPIO1.IO28 */ +#define SC_P_MIPI_CSI1_MCLK_OUT 77 /* MIPI_CSI1.ACM.MCLK_OUT, LSIO.GPIO1.IO29 */ +#define SC_P_MIPI_CSI1_GPIO0_00 78 /* MIPI_CSI1.GPIO0.IO00, DMA.UART4.RX, LSIO.GPIO1.IO30 */ +#define SC_P_MIPI_CSI1_GPIO0_01 79 /* MIPI_CSI1.GPIO0.IO01, DMA.UART4.TX, LSIO.GPIO1.IO31 */ +#define SC_P_MIPI_CSI1_I2C0_SCL 80 /* MIPI_CSI1.I2C0.SCL, LSIO.GPIO2.IO00 */ +#define SC_P_MIPI_CSI1_I2C0_SDA 81 /* MIPI_CSI1.I2C0.SDA, LSIO.GPIO2.IO01 */ +#define SC_P_HDMI_TX0_TS_SCL 82 /* HDMI_TX0.I2C0.SCL, DMA.I2C0.SCL, LSIO.GPIO2.IO02 */ +#define SC_P_HDMI_TX0_TS_SDA 83 /* HDMI_TX0.I2C0.SDA, DMA.I2C0.SDA, LSIO.GPIO2.IO03 */ +#define SC_P_COMP_CTL_GPIO_3V3_HDMIGPIO 84 /* */ +#define SC_P_ESAI1_FSR 85 /* AUD.ESAI1.FSR, LSIO.GPIO2.IO04 */ +#define SC_P_ESAI1_FST 86 /* AUD.ESAI1.FST, AUD.SPDIF0.EXT_CLK, LSIO.GPIO2.IO05 */ +#define SC_P_ESAI1_SCKR 87 /* AUD.ESAI1.SCKR, LSIO.GPIO2.IO06 */ +#define SC_P_ESAI1_SCKT 88 /* AUD.ESAI1.SCKT, AUD.SAI2.RXC, AUD.SPDIF0.EXT_CLK, LSIO.GPIO2.IO07 */ +#define SC_P_ESAI1_TX0 89 /* AUD.ESAI1.TX0, AUD.SAI2.RXD, AUD.SPDIF0.RX, LSIO.GPIO2.IO08 */ +#define SC_P_ESAI1_TX1 90 /* AUD.ESAI1.TX1, AUD.SAI2.RXFS, AUD.SPDIF0.TX, LSIO.GPIO2.IO09 */ +#define SC_P_ESAI1_TX2_RX3 91 /* AUD.ESAI1.TX2_RX3, AUD.SPDIF0.RX, LSIO.GPIO2.IO10 */ +#define SC_P_ESAI1_TX3_RX2 92 /* AUD.ESAI1.TX3_RX2, AUD.SPDIF0.TX, LSIO.GPIO2.IO11 */ +#define SC_P_ESAI1_TX4_RX1 93 /* AUD.ESAI1.TX4_RX1, LSIO.GPIO2.IO12 */ +#define SC_P_ESAI1_TX5_RX0 94 /* AUD.ESAI1.TX5_RX0, LSIO.GPIO2.IO13 */ +#define SC_P_SPDIF0_RX 95 /* AUD.SPDIF0.RX, AUD.MQS.R, AUD.ACM.MCLK_IN1, LSIO.GPIO2.IO14 */ +#define SC_P_SPDIF0_TX 96 /* AUD.SPDIF0.TX, AUD.MQS.L, AUD.ACM.MCLK_OUT1, LSIO.GPIO2.IO15 */ +#define SC_P_SPDIF0_EXT_CLK 97 /* AUD.SPDIF0.EXT_CLK, DMA.DMA0.REQ_IN0, LSIO.GPIO2.IO16 */ +#define SC_P_SPI3_SCK 98 /* DMA.SPI3.SCK, LSIO.GPIO2.IO17 */ +#define SC_P_SPI3_SDO 99 /* DMA.SPI3.SDO, DMA.FTM.CH0, LSIO.GPIO2.IO18 */ +#define SC_P_SPI3_SDI 100 /* DMA.SPI3.SDI, DMA.FTM.CH1, LSIO.GPIO2.IO19 */ +#define SC_P_SPI3_CS0 101 /* DMA.SPI3.CS0, DMA.FTM.CH2, LSIO.GPIO2.IO20 */ +#define SC_P_SPI3_CS1 102 /* DMA.SPI3.CS1, LSIO.GPIO2.IO21 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHB 103 /* */ +#define SC_P_ESAI0_FSR 104 /* AUD.ESAI0.FSR, LSIO.GPIO2.IO22 */ +#define SC_P_ESAI0_FST 105 /* AUD.ESAI0.FST, LSIO.GPIO2.IO23 */ +#define SC_P_ESAI0_SCKR 106 /* AUD.ESAI0.SCKR, LSIO.GPIO2.IO24 */ +#define SC_P_ESAI0_SCKT 107 /* AUD.ESAI0.SCKT, LSIO.GPIO2.IO25 */ +#define SC_P_ESAI0_TX0 108 /* AUD.ESAI0.TX0, LSIO.GPIO2.IO26 */ +#define SC_P_ESAI0_TX1 109 /* AUD.ESAI0.TX1, LSIO.GPIO2.IO27 */ +#define SC_P_ESAI0_TX2_RX3 110 /* AUD.ESAI0.TX2_RX3, LSIO.GPIO2.IO28 */ +#define SC_P_ESAI0_TX3_RX2 111 /* AUD.ESAI0.TX3_RX2, LSIO.GPIO2.IO29 */ +#define SC_P_ESAI0_TX4_RX1 112 /* AUD.ESAI0.TX4_RX1, LSIO.GPIO2.IO30 */ +#define SC_P_ESAI0_TX5_RX0 113 /* AUD.ESAI0.TX5_RX0, LSIO.GPIO2.IO31 */ +#define SC_P_MCLK_IN0 114 /* AUD.ACM.MCLK_IN0, AUD.ESAI0.RX_HF_CLK, AUD.ESAI1.RX_HF_CLK, LSIO.GPIO3.IO00 */ +#define SC_P_MCLK_OUT0 115 /* AUD.ACM.MCLK_OUT0, AUD.ESAI0.TX_HF_CLK, AUD.ESAI1.TX_HF_CLK, LSIO.GPIO3.IO01 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHC 116 /* */ +#define SC_P_SPI0_SCK 117 /* DMA.SPI0.SCK, AUD.SAI0.RXC, LSIO.GPIO3.IO02 */ +#define SC_P_SPI0_SDO 118 /* DMA.SPI0.SDO, AUD.SAI0.TXD, LSIO.GPIO3.IO03 */ +#define SC_P_SPI0_SDI 119 /* DMA.SPI0.SDI, AUD.SAI0.RXD, LSIO.GPIO3.IO04 */ +#define SC_P_SPI0_CS0 120 /* DMA.SPI0.CS0, AUD.SAI0.RXFS, LSIO.GPIO3.IO05 */ +#define SC_P_SPI0_CS1 121 /* DMA.SPI0.CS1, AUD.SAI0.TXC, LSIO.GPIO3.IO06 */ +#define SC_P_SPI2_SCK 122 /* DMA.SPI2.SCK, LSIO.GPIO3.IO07 */ +#define SC_P_SPI2_SDO 123 /* DMA.SPI2.SDO, LSIO.GPIO3.IO08 */ +#define SC_P_SPI2_SDI 124 /* DMA.SPI2.SDI, LSIO.GPIO3.IO09 */ +#define SC_P_SPI2_CS0 125 /* DMA.SPI2.CS0, LSIO.GPIO3.IO10 */ +#define SC_P_SPI2_CS1 126 /* DMA.SPI2.CS1, AUD.SAI0.TXFS, LSIO.GPIO3.IO11 */ +#define SC_P_SAI1_RXC 127 /* AUD.SAI1.RXC, AUD.SAI0.TXD, LSIO.GPIO3.IO12 */ +#define SC_P_SAI1_RXD 128 /* AUD.SAI1.RXD, AUD.SAI0.TXFS, LSIO.GPIO3.IO13 */ +#define SC_P_SAI1_RXFS 129 /* AUD.SAI1.RXFS, AUD.SAI0.RXD, LSIO.GPIO3.IO14 */ +#define SC_P_SAI1_TXC 130 /* AUD.SAI1.TXC, AUD.SAI0.TXC, LSIO.GPIO3.IO15 */ +#define SC_P_SAI1_TXD 131 /* AUD.SAI1.TXD, AUD.SAI1.RXC, LSIO.GPIO3.IO16 */ +#define SC_P_SAI1_TXFS 132 /* AUD.SAI1.TXFS, AUD.SAI1.RXFS, LSIO.GPIO3.IO17 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHT 133 /* */ +#define SC_P_ADC_IN7 134 /* DMA.ADC1.IN3, DMA.SPI1.CS1, LSIO.KPP0.ROW3, LSIO.GPIO3.IO25 */ +#define SC_P_ADC_IN6 135 /* DMA.ADC1.IN2, DMA.SPI1.CS0, LSIO.KPP0.ROW2, LSIO.GPIO3.IO24 */ +#define SC_P_ADC_IN5 136 /* DMA.ADC1.IN1, DMA.SPI1.SDI, LSIO.KPP0.ROW1, LSIO.GPIO3.IO23 */ +#define SC_P_ADC_IN4 137 /* DMA.ADC1.IN0, DMA.SPI1.SDO, LSIO.KPP0.ROW0, LSIO.GPIO3.IO22 */ +#define SC_P_ADC_IN3 138 /* DMA.ADC0.IN3, DMA.SPI1.SCK, LSIO.KPP0.COL3, LSIO.GPIO3.IO21 */ +#define SC_P_ADC_IN2 139 /* DMA.ADC0.IN2, LSIO.KPP0.COL2, LSIO.GPIO3.IO20 */ +#define SC_P_ADC_IN1 140 /* DMA.ADC0.IN1, LSIO.KPP0.COL1, LSIO.GPIO3.IO19 */ +#define SC_P_ADC_IN0 141 /* DMA.ADC0.IN0, LSIO.KPP0.COL0, LSIO.GPIO3.IO18 */ +#define SC_P_MLB_SIG 142 /* CONN.MLB.SIG, AUD.SAI3.RXC, LSIO.GPIO3.IO26 */ +#define SC_P_MLB_CLK 143 /* CONN.MLB.CLK, AUD.SAI3.RXFS, LSIO.GPIO3.IO27 */ +#define SC_P_MLB_DATA 144 /* CONN.MLB.DATA, AUD.SAI3.RXD, LSIO.GPIO3.IO28 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLHT 145 /* */ +#define SC_P_FLEXCAN0_RX 146 /* DMA.FLEXCAN0.RX, LSIO.GPIO3.IO29 */ +#define SC_P_FLEXCAN0_TX 147 /* DMA.FLEXCAN0.TX, LSIO.GPIO3.IO30 */ +#define SC_P_FLEXCAN1_RX 148 /* DMA.FLEXCAN1.RX, LSIO.GPIO3.IO31 */ +#define SC_P_FLEXCAN1_TX 149 /* DMA.FLEXCAN1.TX, LSIO.GPIO4.IO00 */ +#define SC_P_FLEXCAN2_RX 150 /* DMA.FLEXCAN2.RX, LSIO.GPIO4.IO01 */ +#define SC_P_FLEXCAN2_TX 151 /* DMA.FLEXCAN2.TX, LSIO.GPIO4.IO02 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOTHR 152 /* */ +#define SC_P_USB_SS3_TC0 153 /* DMA.I2C1.SCL, CONN.USB_OTG1.PWR, LSIO.GPIO4.IO03 */ +#define SC_P_USB_SS3_TC1 154 /* DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO04 */ +#define SC_P_USB_SS3_TC2 155 /* DMA.I2C1.SDA, CONN.USB_OTG1.OC, LSIO.GPIO4.IO05 */ +#define SC_P_USB_SS3_TC3 156 /* DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO06 */ +#define SC_P_COMP_CTL_GPIO_3V3_USB3IO 157 /* */ +#define SC_P_USDHC1_RESET_B 158 /* CONN.USDHC1.RESET_B, LSIO.GPIO4.IO07 */ +#define SC_P_USDHC1_VSELECT 159 /* CONN.USDHC1.VSELECT, LSIO.GPIO4.IO08 */ +#define SC_P_USDHC2_RESET_B 160 /* CONN.USDHC2.RESET_B, LSIO.GPIO4.IO09 */ +#define SC_P_USDHC2_VSELECT 161 /* CONN.USDHC2.VSELECT, LSIO.GPIO4.IO10 */ +#define SC_P_USDHC2_WP 162 /* CONN.USDHC2.WP, LSIO.GPIO4.IO11 */ +#define SC_P_USDHC2_CD_B 163 /* CONN.USDHC2.CD_B, LSIO.GPIO4.IO12 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSELSEP 164 /* */ +#define SC_P_ENET0_MDIO 165 /* CONN.ENET0.MDIO, DMA.I2C4.SDA, LSIO.GPIO4.IO13 */ +#define SC_P_ENET0_MDC 166 /* CONN.ENET0.MDC, DMA.I2C4.SCL, LSIO.GPIO4.IO14 */ +#define SC_P_ENET0_REFCLK_125M_25M 167 /* CONN.ENET0.REFCLK_125M_25M, CONN.ENET0.PPS, LSIO.GPIO4.IO15 */ +#define SC_P_ENET1_REFCLK_125M_25M 168 /* CONN.ENET1.REFCLK_125M_25M, CONN.ENET1.PPS, LSIO.GPIO4.IO16 */ +#define SC_P_ENET1_MDIO 169 /* CONN.ENET1.MDIO, DMA.I2C4.SDA, LSIO.GPIO4.IO17 */ +#define SC_P_ENET1_MDC 170 /* CONN.ENET1.MDC, DMA.I2C4.SCL, LSIO.GPIO4.IO18 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOCT 171 /* */ +#define SC_P_QSPI1A_SS0_B 172 /* LSIO.QSPI1A.SS0_B, LSIO.GPIO4.IO19 */ +#define SC_P_QSPI1A_SS1_B 173 /* LSIO.QSPI1A.SS1_B, LSIO.QSPI1A.SCLK2, LSIO.GPIO4.IO20 */ +#define SC_P_QSPI1A_SCLK 174 /* LSIO.QSPI1A.SCLK, LSIO.GPIO4.IO21 */ +#define SC_P_QSPI1A_DQS 175 /* LSIO.QSPI1A.DQS, LSIO.GPIO4.IO22 */ +#define SC_P_QSPI1A_DATA3 176 /* LSIO.QSPI1A.DATA3, DMA.I2C1.SDA, CONN.USB_OTG1.OC, LSIO.GPIO4.IO23 */ +#define SC_P_QSPI1A_DATA2 177 /* LSIO.QSPI1A.DATA2, DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO24 */ +#define SC_P_QSPI1A_DATA1 178 /* LSIO.QSPI1A.DATA1, DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO25 */ +#define SC_P_QSPI1A_DATA0 179 /* LSIO.QSPI1A.DATA0, LSIO.GPIO4.IO26 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI1 180 /* */ +#define SC_P_QSPI0A_DATA0 181 /* LSIO.QSPI0A.DATA0 */ +#define SC_P_QSPI0A_DATA1 182 /* LSIO.QSPI0A.DATA1 */ +#define SC_P_QSPI0A_DATA2 183 /* LSIO.QSPI0A.DATA2 */ +#define SC_P_QSPI0A_DATA3 184 /* LSIO.QSPI0A.DATA3 */ +#define SC_P_QSPI0A_DQS 185 /* LSIO.QSPI0A.DQS */ +#define SC_P_QSPI0A_SS0_B 186 /* LSIO.QSPI0A.SS0_B */ +#define SC_P_QSPI0A_SS1_B 187 /* LSIO.QSPI0A.SS1_B, LSIO.QSPI0A.SCLK2 */ +#define SC_P_QSPI0A_SCLK 188 /* LSIO.QSPI0A.SCLK */ +#define SC_P_QSPI0B_SCLK 189 /* LSIO.QSPI0B.SCLK */ +#define SC_P_QSPI0B_DATA0 190 /* LSIO.QSPI0B.DATA0 */ +#define SC_P_QSPI0B_DATA1 191 /* LSIO.QSPI0B.DATA1 */ +#define SC_P_QSPI0B_DATA2 192 /* LSIO.QSPI0B.DATA2 */ +#define SC_P_QSPI0B_DATA3 193 /* LSIO.QSPI0B.DATA3 */ +#define SC_P_QSPI0B_DQS 194 /* LSIO.QSPI0B.DQS */ +#define SC_P_QSPI0B_SS0_B 195 /* LSIO.QSPI0B.SS0_B */ +#define SC_P_QSPI0B_SS1_B 196 /* LSIO.QSPI0B.SS1_B, LSIO.QSPI0B.SCLK2 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0 197 /* */ +#define SC_P_PCIE_CTRL0_CLKREQ_B 198 /* HSIO.PCIE0.CLKREQ_B, LSIO.GPIO4.IO27 */ +#define SC_P_PCIE_CTRL0_WAKE_B 199 /* HSIO.PCIE0.WAKE_B, LSIO.GPIO4.IO28 */ +#define SC_P_PCIE_CTRL0_PERST_B 200 /* HSIO.PCIE0.PERST_B, LSIO.GPIO4.IO29 */ +#define SC_P_PCIE_CTRL1_CLKREQ_B 201 /* HSIO.PCIE1.CLKREQ_B, DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO30 */ +#define SC_P_PCIE_CTRL1_WAKE_B 202 /* HSIO.PCIE1.WAKE_B, DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO31 */ +#define SC_P_PCIE_CTRL1_PERST_B 203 /* HSIO.PCIE1.PERST_B, DMA.I2C1.SCL, CONN.USB_OTG1.PWR, LSIO.GPIO5.IO00 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_PCIESEP 204 /* */ +#define SC_P_USB_HSIC0_DATA 205 /* CONN.USB_HSIC0.DATA, DMA.I2C1.SDA, LSIO.GPIO5.IO01 */ +#define SC_P_USB_HSIC0_STROBE 206 /* CONN.USB_HSIC0.STROBE, DMA.I2C1.SCL, LSIO.GPIO5.IO02 */ +#define SC_P_CALIBRATION_0_HSIC 207 /* */ +#define SC_P_CALIBRATION_1_HSIC 208 /* */ +#define SC_P_EMMC0_CLK 209 /* CONN.EMMC0.CLK, CONN.NAND.READY_B */ +#define SC_P_EMMC0_CMD 210 /* CONN.EMMC0.CMD, CONN.NAND.DQS, AUD.MQS.R, LSIO.GPIO5.IO03 */ +#define SC_P_EMMC0_DATA0 211 /* CONN.EMMC0.DATA0, CONN.NAND.DATA00, LSIO.GPIO5.IO04 */ +#define SC_P_EMMC0_DATA1 212 /* CONN.EMMC0.DATA1, CONN.NAND.DATA01, LSIO.GPIO5.IO05 */ +#define SC_P_EMMC0_DATA2 213 /* CONN.EMMC0.DATA2, CONN.NAND.DATA02, LSIO.GPIO5.IO06 */ +#define SC_P_EMMC0_DATA3 214 /* CONN.EMMC0.DATA3, CONN.NAND.DATA03, LSIO.GPIO5.IO07 */ +#define SC_P_EMMC0_DATA4 215 /* CONN.EMMC0.DATA4, CONN.NAND.DATA04, LSIO.GPIO5.IO08 */ +#define SC_P_EMMC0_DATA5 216 /* CONN.EMMC0.DATA5, CONN.NAND.DATA05, LSIO.GPIO5.IO09 */ +#define SC_P_EMMC0_DATA6 217 /* CONN.EMMC0.DATA6, CONN.NAND.DATA06, LSIO.GPIO5.IO10 */ +#define SC_P_EMMC0_DATA7 218 /* CONN.EMMC0.DATA7, CONN.NAND.DATA07, LSIO.GPIO5.IO11 */ +#define SC_P_EMMC0_STROBE 219 /* CONN.EMMC0.STROBE, CONN.NAND.CLE, LSIO.GPIO5.IO12 */ +#define SC_P_EMMC0_RESET_B 220 /* CONN.EMMC0.RESET_B, CONN.NAND.WP_B, CONN.USDHC1.VSELECT, LSIO.GPIO5.IO13 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX 221 /* */ +#define SC_P_USDHC1_CLK 222 /* CONN.USDHC1.CLK, AUD.MQS.R */ +#define SC_P_USDHC1_CMD 223 /* CONN.USDHC1.CMD, AUD.MQS.L, LSIO.GPIO5.IO14 */ +#define SC_P_USDHC1_DATA0 224 /* CONN.USDHC1.DATA0, CONN.NAND.RE_N, LSIO.GPIO5.IO15 */ +#define SC_P_USDHC1_DATA1 225 /* CONN.USDHC1.DATA1, CONN.NAND.RE_P, LSIO.GPIO5.IO16 */ +#define SC_P_CTL_NAND_RE_P_N 226 /* */ +#define SC_P_USDHC1_DATA2 227 /* CONN.USDHC1.DATA2, CONN.NAND.DQS_N, LSIO.GPIO5.IO17 */ +#define SC_P_USDHC1_DATA3 228 /* CONN.USDHC1.DATA3, CONN.NAND.DQS_P, LSIO.GPIO5.IO18 */ +#define SC_P_CTL_NAND_DQS_P_N 229 /* */ +#define SC_P_USDHC1_DATA4 230 /* CONN.USDHC1.DATA4, CONN.NAND.CE0_B, AUD.MQS.R, LSIO.GPIO5.IO19 */ +#define SC_P_USDHC1_DATA5 231 /* CONN.USDHC1.DATA5, CONN.NAND.RE_B, AUD.MQS.L, LSIO.GPIO5.IO20 */ +#define SC_P_USDHC1_DATA6 232 /* CONN.USDHC1.DATA6, CONN.NAND.WE_B, CONN.USDHC1.WP, LSIO.GPIO5.IO21 */ +#define SC_P_USDHC1_DATA7 233 /* CONN.USDHC1.DATA7, CONN.NAND.ALE, CONN.USDHC1.CD_B, LSIO.GPIO5.IO22 */ +#define SC_P_USDHC1_STROBE 234 /* CONN.USDHC1.STROBE, CONN.NAND.CE1_B, CONN.USDHC1.RESET_B, LSIO.GPIO5.IO23 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL2 235 /* */ +#define SC_P_USDHC2_CLK 236 /* CONN.USDHC2.CLK, AUD.MQS.R, LSIO.GPIO5.IO24 */ +#define SC_P_USDHC2_CMD 237 /* CONN.USDHC2.CMD, AUD.MQS.L, LSIO.GPIO5.IO25 */ +#define SC_P_USDHC2_DATA0 238 /* CONN.USDHC2.DATA0, DMA.UART4.RX, LSIO.GPIO5.IO26 */ +#define SC_P_USDHC2_DATA1 239 /* CONN.USDHC2.DATA1, DMA.UART4.TX, LSIO.GPIO5.IO27 */ +#define SC_P_USDHC2_DATA2 240 /* CONN.USDHC2.DATA2, DMA.UART4.CTS_B, LSIO.GPIO5.IO28 */ +#define SC_P_USDHC2_DATA3 241 /* CONN.USDHC2.DATA3, DMA.UART4.RTS_B, LSIO.GPIO5.IO29 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL3 242 /* */ +#define SC_P_ENET0_RGMII_TXC 243 /* CONN.ENET0.RGMII_TXC, CONN.ENET0.RCLK50M_OUT, CONN.ENET0.RCLK50M_IN, LSIO.GPIO5.IO30 */ +#define SC_P_ENET0_RGMII_TX_CTL 244 /* CONN.ENET0.RGMII_TX_CTL, LSIO.GPIO5.IO31 */ +#define SC_P_ENET0_RGMII_TXD0 245 /* CONN.ENET0.RGMII_TXD0, LSIO.GPIO6.IO00 */ +#define SC_P_ENET0_RGMII_TXD1 246 /* CONN.ENET0.RGMII_TXD1, LSIO.GPIO6.IO01 */ +#define SC_P_ENET0_RGMII_TXD2 247 /* CONN.ENET0.RGMII_TXD2, DMA.UART3.TX, VPU.TSI_S1.VID, LSIO.GPIO6.IO02 */ +#define SC_P_ENET0_RGMII_TXD3 248 /* CONN.ENET0.RGMII_TXD3, DMA.UART3.RTS_B, VPU.TSI_S1.SYNC, LSIO.GPIO6.IO03 */ +#define SC_P_ENET0_RGMII_RXC 249 /* CONN.ENET0.RGMII_RXC, DMA.UART3.CTS_B, VPU.TSI_S1.DATA, LSIO.GPIO6.IO04 */ +#define SC_P_ENET0_RGMII_RX_CTL 250 /* CONN.ENET0.RGMII_RX_CTL, VPU.TSI_S0.VID, LSIO.GPIO6.IO05 */ +#define SC_P_ENET0_RGMII_RXD0 251 /* CONN.ENET0.RGMII_RXD0, VPU.TSI_S0.SYNC, LSIO.GPIO6.IO06 */ +#define SC_P_ENET0_RGMII_RXD1 252 /* CONN.ENET0.RGMII_RXD1, VPU.TSI_S0.DATA, LSIO.GPIO6.IO07 */ +#define SC_P_ENET0_RGMII_RXD2 253 /* CONN.ENET0.RGMII_RXD2, CONN.ENET0.RMII_RX_ER, VPU.TSI_S0.CLK, LSIO.GPIO6.IO08 */ +#define SC_P_ENET0_RGMII_RXD3 254 /* CONN.ENET0.RGMII_RXD3, DMA.UART3.RX, VPU.TSI_S1.CLK, LSIO.GPIO6.IO09 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB 255 /* */ +#define SC_P_ENET1_RGMII_TXC 256 /* CONN.ENET1.RGMII_TXC, CONN.ENET1.RCLK50M_OUT, CONN.ENET1.RCLK50M_IN, LSIO.GPIO6.IO10 */ +#define SC_P_ENET1_RGMII_TX_CTL 257 /* CONN.ENET1.RGMII_TX_CTL, LSIO.GPIO6.IO11 */ +#define SC_P_ENET1_RGMII_TXD0 258 /* CONN.ENET1.RGMII_TXD0, LSIO.GPIO6.IO12 */ +#define SC_P_ENET1_RGMII_TXD1 259 /* CONN.ENET1.RGMII_TXD1, LSIO.GPIO6.IO13 */ +#define SC_P_ENET1_RGMII_TXD2 260 /* CONN.ENET1.RGMII_TXD2, DMA.UART3.TX, VPU.TSI_S1.VID, LSIO.GPIO6.IO14 */ +#define SC_P_ENET1_RGMII_TXD3 261 /* CONN.ENET1.RGMII_TXD3, DMA.UART3.RTS_B, VPU.TSI_S1.SYNC, LSIO.GPIO6.IO15 */ +#define SC_P_ENET1_RGMII_RXC 262 /* CONN.ENET1.RGMII_RXC, DMA.UART3.CTS_B, VPU.TSI_S1.DATA, LSIO.GPIO6.IO16 */ +#define SC_P_ENET1_RGMII_RX_CTL 263 /* CONN.ENET1.RGMII_RX_CTL, VPU.TSI_S0.VID, LSIO.GPIO6.IO17 */ +#define SC_P_ENET1_RGMII_RXD0 264 /* CONN.ENET1.RGMII_RXD0, VPU.TSI_S0.SYNC, LSIO.GPIO6.IO18 */ +#define SC_P_ENET1_RGMII_RXD1 265 /* CONN.ENET1.RGMII_RXD1, VPU.TSI_S0.DATA, LSIO.GPIO6.IO19 */ +#define SC_P_ENET1_RGMII_RXD2 266 /* CONN.ENET1.RGMII_RXD2, CONN.ENET1.RMII_RX_ER, VPU.TSI_S0.CLK, LSIO.GPIO6.IO20 */ +#define SC_P_ENET1_RGMII_RXD3 267 /* CONN.ENET1.RGMII_RXD3, DMA.UART3.RX, VPU.TSI_S1.CLK, LSIO.GPIO6.IO21 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETA 268 /* */ +/*@}*/ + +#endif /* IMX8QM_PADS_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h b/arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h new file mode 100644 index 0000000..5445aa1 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file used to configure SoC pad list. + */ + +#ifndef IMX8QX_PADS_H +#define IMX8QX_PADS_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Pad Definitions + */ +/*@{*/ +#define SC_P_PCIE_CTRL0_PERST_B 0 /* HSIO.PCIE0.PERST_B, LSIO.GPIO4.IO00 */ +#define SC_P_PCIE_CTRL0_CLKREQ_B 1 /* HSIO.PCIE0.CLKREQ_B, LSIO.GPIO4.IO01 */ +#define SC_P_PCIE_CTRL0_WAKE_B 2 /* HSIO.PCIE0.WAKE_B, LSIO.GPIO4.IO02 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_PCIESEP 3 /* */ +#define SC_P_USB_SS3_TC0 4 /* ADMA.I2C1.SCL, CONN.USB_OTG1.PWR, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO03 */ +#define SC_P_USB_SS3_TC1 5 /* ADMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO04 */ +#define SC_P_USB_SS3_TC2 6 /* ADMA.I2C1.SDA, CONN.USB_OTG1.OC, CONN.USB_OTG2.OC, LSIO.GPIO4.IO05 */ +#define SC_P_USB_SS3_TC3 7 /* ADMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO06 */ +#define SC_P_COMP_CTL_GPIO_3V3_USB3IO 8 /* */ +#define SC_P_EMMC0_CLK 9 /* CONN.EMMC0.CLK, CONN.NAND.READY_B, LSIO.GPIO4.IO07 */ +#define SC_P_EMMC0_CMD 10 /* CONN.EMMC0.CMD, CONN.NAND.DQS, LSIO.GPIO4.IO08 */ +#define SC_P_EMMC0_DATA0 11 /* CONN.EMMC0.DATA0, CONN.NAND.DATA00, LSIO.GPIO4.IO09 */ +#define SC_P_EMMC0_DATA1 12 /* CONN.EMMC0.DATA1, CONN.NAND.DATA01, LSIO.GPIO4.IO10 */ +#define SC_P_EMMC0_DATA2 13 /* CONN.EMMC0.DATA2, CONN.NAND.DATA02, LSIO.GPIO4.IO11 */ +#define SC_P_EMMC0_DATA3 14 /* CONN.EMMC0.DATA3, CONN.NAND.DATA03, LSIO.GPIO4.IO12 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX0 15 /* */ +#define SC_P_EMMC0_DATA4 16 /* CONN.EMMC0.DATA4, CONN.NAND.DATA04, CONN.EMMC0.WP, LSIO.GPIO4.IO13 */ +#define SC_P_EMMC0_DATA5 17 /* CONN.EMMC0.DATA5, CONN.NAND.DATA05, CONN.EMMC0.VSELECT, LSIO.GPIO4.IO14 */ +#define SC_P_EMMC0_DATA6 18 /* CONN.EMMC0.DATA6, CONN.NAND.DATA06, CONN.MLB.CLK, LSIO.GPIO4.IO15 */ +#define SC_P_EMMC0_DATA7 19 /* CONN.EMMC0.DATA7, CONN.NAND.DATA07, CONN.MLB.SIG, LSIO.GPIO4.IO16 */ +#define SC_P_EMMC0_STROBE 20 /* CONN.EMMC0.STROBE, CONN.NAND.CLE, CONN.MLB.DATA, LSIO.GPIO4.IO17 */ +#define SC_P_EMMC0_RESET_B 21 /* CONN.EMMC0.RESET_B, CONN.NAND.WP_B, LSIO.GPIO4.IO18 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX1 22 /* */ +#define SC_P_USDHC1_RESET_B 23 /* CONN.USDHC1.RESET_B, CONN.NAND.RE_N, ADMA.SPI2.SCK, LSIO.GPIO4.IO19 */ +#define SC_P_USDHC1_VSELECT 24 /* CONN.USDHC1.VSELECT, CONN.NAND.RE_P, ADMA.SPI2.SDO, CONN.NAND.RE_B, LSIO.GPIO4.IO20 */ +#define SC_P_CTL_NAND_RE_P_N 25 /* */ +#define SC_P_USDHC1_WP 26 /* CONN.USDHC1.WP, CONN.NAND.DQS_N, ADMA.SPI2.SDI, LSIO.GPIO4.IO21 */ +#define SC_P_USDHC1_CD_B 27 /* CONN.USDHC1.CD_B, CONN.NAND.DQS_P, ADMA.SPI2.CS0, CONN.NAND.DQS, LSIO.GPIO4.IO22 */ +#define SC_P_CTL_NAND_DQS_P_N 28 /* */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSELSEP 29 /* */ +#define SC_P_USDHC1_CLK 30 /* CONN.USDHC1.CLK, ADMA.UART3.RX, LSIO.GPIO4.IO23 */ +#define SC_P_USDHC1_CMD 31 /* CONN.USDHC1.CMD, CONN.NAND.CE0_B, ADMA.MQS.R, LSIO.GPIO4.IO24 */ +#define SC_P_USDHC1_DATA0 32 /* CONN.USDHC1.DATA0, CONN.NAND.CE1_B, ADMA.MQS.L, LSIO.GPIO4.IO25 */ +#define SC_P_USDHC1_DATA1 33 /* CONN.USDHC1.DATA1, CONN.NAND.RE_B, ADMA.UART3.TX, LSIO.GPIO4.IO26 */ +#define SC_P_USDHC1_DATA2 34 /* CONN.USDHC1.DATA2, CONN.NAND.WE_B, ADMA.UART3.CTS_B, LSIO.GPIO4.IO27 */ +#define SC_P_USDHC1_DATA3 35 /* CONN.USDHC1.DATA3, CONN.NAND.ALE, ADMA.UART3.RTS_B, LSIO.GPIO4.IO28 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL3 36 /* */ +#define SC_P_ENET0_RGMII_TXC 37 /* CONN.ENET0.RGMII_TXC, CONN.ENET0.RCLK50M_OUT, CONN.ENET0.RCLK50M_IN, CONN.NAND.CE1_B, LSIO.GPIO4.IO29 */ +#define SC_P_ENET0_RGMII_TX_CTL 38 /* CONN.ENET0.RGMII_TX_CTL, CONN.USDHC1.RESET_B, LSIO.GPIO4.IO30 */ +#define SC_P_ENET0_RGMII_TXD0 39 /* CONN.ENET0.RGMII_TXD0, CONN.USDHC1.VSELECT, LSIO.GPIO4.IO31 */ +#define SC_P_ENET0_RGMII_TXD1 40 /* CONN.ENET0.RGMII_TXD1, CONN.USDHC1.WP, LSIO.GPIO5.IO00 */ +#define SC_P_ENET0_RGMII_TXD2 41 /* CONN.ENET0.RGMII_TXD2, CONN.MLB.CLK, CONN.NAND.CE0_B, CONN.USDHC1.CD_B, LSIO.GPIO5.IO01 */ +#define SC_P_ENET0_RGMII_TXD3 42 /* CONN.ENET0.RGMII_TXD3, CONN.MLB.SIG, CONN.NAND.RE_B, LSIO.GPIO5.IO02 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB0 43 /* */ +#define SC_P_ENET0_RGMII_RXC 44 /* CONN.ENET0.RGMII_RXC, CONN.MLB.DATA, CONN.NAND.WE_B, CONN.USDHC1.CLK, LSIO.GPIO5.IO03 */ +#define SC_P_ENET0_RGMII_RX_CTL 45 /* CONN.ENET0.RGMII_RX_CTL, CONN.USDHC1.CMD, LSIO.GPIO5.IO04 */ +#define SC_P_ENET0_RGMII_RXD0 46 /* CONN.ENET0.RGMII_RXD0, CONN.USDHC1.DATA0, LSIO.GPIO5.IO05 */ +#define SC_P_ENET0_RGMII_RXD1 47 /* CONN.ENET0.RGMII_RXD1, CONN.USDHC1.DATA1, LSIO.GPIO5.IO06 */ +#define SC_P_ENET0_RGMII_RXD2 48 /* CONN.ENET0.RGMII_RXD2, CONN.ENET0.RMII_RX_ER, CONN.USDHC1.DATA2, LSIO.GPIO5.IO07 */ +#define SC_P_ENET0_RGMII_RXD3 49 /* CONN.ENET0.RGMII_RXD3, CONN.NAND.ALE, CONN.USDHC1.DATA3, LSIO.GPIO5.IO08 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB1 50 /* */ +#define SC_P_ENET0_REFCLK_125M_25M 51 /* CONN.ENET0.REFCLK_125M_25M, CONN.ENET0.PPS, CONN.ENET1.PPS, LSIO.GPIO5.IO09 */ +#define SC_P_ENET0_MDIO 52 /* CONN.ENET0.MDIO, ADMA.I2C3.SDA, CONN.ENET1.MDIO, LSIO.GPIO5.IO10 */ +#define SC_P_ENET0_MDC 53 /* CONN.ENET0.MDC, ADMA.I2C3.SCL, CONN.ENET1.MDC, LSIO.GPIO5.IO11 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOCT 54 /* */ +#define SC_P_ESAI0_FSR 55 /* ADMA.ESAI0.FSR, CONN.ENET1.RCLK50M_OUT, ADMA.LCDIF.D00, CONN.ENET1.RGMII_TXC, CONN.ENET1.RCLK50M_IN */ +#define SC_P_ESAI0_FST 56 /* ADMA.ESAI0.FST, CONN.MLB.CLK, ADMA.LCDIF.D01, CONN.ENET1.RGMII_TXD2, LSIO.GPIO0.IO01 */ +#define SC_P_ESAI0_SCKR 57 /* ADMA.ESAI0.SCKR, ADMA.LCDIF.D02, CONN.ENET1.RGMII_TX_CTL, LSIO.GPIO0.IO02 */ +#define SC_P_ESAI0_SCKT 58 /* ADMA.ESAI0.SCKT, CONN.MLB.SIG, ADMA.LCDIF.D03, CONN.ENET1.RGMII_TXD3, LSIO.GPIO0.IO03 */ +#define SC_P_ESAI0_TX0 59 /* ADMA.ESAI0.TX0, CONN.MLB.DATA, ADMA.LCDIF.D04, CONN.ENET1.RGMII_RXC, LSIO.GPIO0.IO04 */ +#define SC_P_ESAI0_TX1 60 /* ADMA.ESAI0.TX1, ADMA.LCDIF.D05, CONN.ENET1.RGMII_RXD3, LSIO.GPIO0.IO05 */ +#define SC_P_ESAI0_TX2_RX3 61 /* ADMA.ESAI0.TX2_RX3, CONN.ENET1.RMII_RX_ER, ADMA.LCDIF.D06, CONN.ENET1.RGMII_RXD2, LSIO.GPIO0.IO06 */ +#define SC_P_ESAI0_TX3_RX2 62 /* ADMA.ESAI0.TX3_RX2, ADMA.LCDIF.D07, CONN.ENET1.RGMII_RXD1, LSIO.GPIO0.IO07 */ +#define SC_P_ESAI0_TX4_RX1 63 /* ADMA.ESAI0.TX4_RX1, ADMA.LCDIF.D08, CONN.ENET1.RGMII_TXD0, LSIO.GPIO0.IO08 */ +#define SC_P_ESAI0_TX5_RX0 64 /* ADMA.ESAI0.TX5_RX0, ADMA.LCDIF.D09, CONN.ENET1.RGMII_TXD1, LSIO.GPIO0.IO09 */ +#define SC_P_SPDIF0_RX 65 /* ADMA.SPDIF0.RX, ADMA.MQS.R, ADMA.LCDIF.D10, CONN.ENET1.RGMII_RXD0, LSIO.GPIO0.IO10 */ +#define SC_P_SPDIF0_TX 66 /* ADMA.SPDIF0.TX, ADMA.MQS.L, ADMA.LCDIF.D11, CONN.ENET1.RGMII_RX_CTL, LSIO.GPIO0.IO11 */ +#define SC_P_SPDIF0_EXT_CLK 67 /* ADMA.SPDIF0.EXT_CLK, ADMA.LCDIF.D12, CONN.ENET1.REFCLK_125M_25M, LSIO.GPIO0.IO12 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHB 68 /* */ +#define SC_P_SPI3_SCK 69 /* ADMA.SPI3.SCK, ADMA.LCDIF.D13, LSIO.GPIO0.IO13 */ +#define SC_P_SPI3_SDO 70 /* ADMA.SPI3.SDO, ADMA.LCDIF.D14, LSIO.GPIO0.IO14 */ +#define SC_P_SPI3_SDI 71 /* ADMA.SPI3.SDI, ADMA.LCDIF.D15, LSIO.GPIO0.IO15 */ +#define SC_P_SPI3_CS0 72 /* ADMA.SPI3.CS0, ADMA.ACM.MCLK_OUT1, ADMA.LCDIF.HSYNC, LSIO.GPIO0.IO16 */ +#define SC_P_SPI3_CS1 73 /* ADMA.SPI3.CS1, ADMA.I2C3.SCL, ADMA.LCDIF.RESET, ADMA.SPI2.CS0, ADMA.LCDIF.D16 */ +#define SC_P_MCLK_IN1 74 /* ADMA.ACM.MCLK_IN1, ADMA.I2C3.SDA, ADMA.LCDIF.EN, ADMA.SPI2.SCK, ADMA.LCDIF.D17 */ +#define SC_P_MCLK_IN0 75 /* ADMA.ACM.MCLK_IN0, ADMA.ESAI0.RX_HF_CLK, ADMA.LCDIF.VSYNC, ADMA.SPI2.SDI, LSIO.GPIO0.IO19 */ +#define SC_P_MCLK_OUT0 76 /* ADMA.ACM.MCLK_OUT0, ADMA.ESAI0.TX_HF_CLK, ADMA.LCDIF.CLK, ADMA.SPI2.SDO, LSIO.GPIO0.IO20 */ +#define SC_P_UART1_TX 77 /* ADMA.UART1.TX, LSIO.PWM0.OUT, LSIO.GPT0.CAPTURE, LSIO.GPIO0.IO21 */ +#define SC_P_UART1_RX 78 /* ADMA.UART1.RX, LSIO.PWM1.OUT, LSIO.GPT0.COMPARE, LSIO.GPT1.CLK, LSIO.GPIO0.IO22 */ +#define SC_P_UART1_RTS_B 79 /* ADMA.UART1.RTS_B, LSIO.PWM2.OUT, ADMA.LCDIF.D16, LSIO.GPT1.CAPTURE, LSIO.GPT0.CLK */ +#define SC_P_UART1_CTS_B 80 /* ADMA.UART1.CTS_B, LSIO.PWM3.OUT, ADMA.LCDIF.D17, LSIO.GPT1.COMPARE, LSIO.GPIO0.IO24 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHK 81 /* */ +#define SC_P_SAI0_TXD 82 /* ADMA.SAI0.TXD, ADMA.SAI1.RXC, ADMA.SPI1.SDO, ADMA.LCDIF.D18, LSIO.GPIO0.IO25 */ +#define SC_P_SAI0_TXC 83 /* ADMA.SAI0.TXC, ADMA.SAI1.TXD, ADMA.SPI1.SDI, ADMA.LCDIF.D19, LSIO.GPIO0.IO26 */ +#define SC_P_SAI0_RXD 84 /* ADMA.SAI0.RXD, ADMA.SAI1.RXFS, ADMA.SPI1.CS0, ADMA.LCDIF.D20, LSIO.GPIO0.IO27 */ +#define SC_P_SAI0_TXFS 85 /* ADMA.SAI0.TXFS, ADMA.SPI2.CS1, ADMA.SPI1.SCK, LSIO.GPIO0.IO28 */ +#define SC_P_SAI1_RXD 86 /* ADMA.SAI1.RXD, ADMA.SAI0.RXFS, ADMA.SPI1.CS1, ADMA.LCDIF.D21, LSIO.GPIO0.IO29 */ +#define SC_P_SAI1_RXC 87 /* ADMA.SAI1.RXC, ADMA.SAI1.TXC, ADMA.LCDIF.D22, LSIO.GPIO0.IO30 */ +#define SC_P_SAI1_RXFS 88 /* ADMA.SAI1.RXFS, ADMA.SAI1.TXFS, ADMA.LCDIF.D23, LSIO.GPIO0.IO31 */ +#define SC_P_SPI2_CS0 89 /* ADMA.SPI2.CS0, LSIO.GPIO1.IO00 */ +#define SC_P_SPI2_SDO 90 /* ADMA.SPI2.SDO, LSIO.GPIO1.IO01 */ +#define SC_P_SPI2_SDI 91 /* ADMA.SPI2.SDI, LSIO.GPIO1.IO02 */ +#define SC_P_SPI2_SCK 92 /* ADMA.SPI2.SCK, LSIO.GPIO1.IO03 */ +#define SC_P_SPI0_SCK 93 /* ADMA.SPI0.SCK, ADMA.SAI0.TXC, M40.I2C0.SCL, M40.GPIO0.IO00, LSIO.GPIO1.IO04 */ +#define SC_P_SPI0_SDI 94 /* ADMA.SPI0.SDI, ADMA.SAI0.TXD, M40.TPM0.CH0, M40.GPIO0.IO02, LSIO.GPIO1.IO05 */ +#define SC_P_SPI0_SDO 95 /* ADMA.SPI0.SDO, ADMA.SAI0.TXFS, M40.I2C0.SDA, M40.GPIO0.IO01, LSIO.GPIO1.IO06 */ +#define SC_P_SPI0_CS1 96 /* ADMA.SPI0.CS1, ADMA.SAI0.RXC, ADMA.SAI1.TXD, ADMA.LCD_PWM0.OUT, LSIO.GPIO1.IO07 */ +#define SC_P_SPI0_CS0 97 /* ADMA.SPI0.CS0, ADMA.SAI0.RXD, M40.TPM0.CH1, M40.GPIO0.IO03, LSIO.GPIO1.IO08 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHT 98 /* */ +#define SC_P_ADC_IN1 99 /* ADMA.ADC.IN1, M40.I2C0.SDA, M40.GPIO0.IO01, LSIO.GPIO1.IO09 */ +#define SC_P_ADC_IN0 100 /* ADMA.ADC.IN0, M40.I2C0.SCL, M40.GPIO0.IO00, LSIO.GPIO1.IO10 */ +#define SC_P_ADC_IN3 101 /* ADMA.ADC.IN3, M40.UART0.TX, M40.GPIO0.IO03, ADMA.ACM.MCLK_OUT0, LSIO.GPIO1.IO11 */ +#define SC_P_ADC_IN2 102 /* ADMA.ADC.IN2, M40.UART0.RX, M40.GPIO0.IO02, ADMA.ACM.MCLK_IN0, LSIO.GPIO1.IO12 */ +#define SC_P_ADC_IN5 103 /* ADMA.ADC.IN5, M40.TPM0.CH1, M40.GPIO0.IO05, LSIO.GPIO1.IO13 */ +#define SC_P_ADC_IN4 104 /* ADMA.ADC.IN4, M40.TPM0.CH0, M40.GPIO0.IO04, LSIO.GPIO1.IO14 */ +#define SC_P_FLEXCAN0_RX 105 /* ADMA.FLEXCAN0.RX, ADMA.SAI2.RXC, ADMA.UART0.RTS_B, ADMA.SAI1.TXC, LSIO.GPIO1.IO15 */ +#define SC_P_FLEXCAN0_TX 106 /* ADMA.FLEXCAN0.TX, ADMA.SAI2.RXD, ADMA.UART0.CTS_B, ADMA.SAI1.TXFS, LSIO.GPIO1.IO16 */ +#define SC_P_FLEXCAN1_RX 107 /* ADMA.FLEXCAN1.RX, ADMA.SAI2.RXFS, ADMA.FTM.CH2, ADMA.SAI1.TXD, LSIO.GPIO1.IO17 */ +#define SC_P_FLEXCAN1_TX 108 /* ADMA.FLEXCAN1.TX, ADMA.SAI3.RXC, ADMA.DMA0.REQ_IN0, ADMA.SAI1.RXD, LSIO.GPIO1.IO18 */ +#define SC_P_FLEXCAN2_RX 109 /* ADMA.FLEXCAN2.RX, ADMA.SAI3.RXD, ADMA.UART3.RX, ADMA.SAI1.RXFS, LSIO.GPIO1.IO19 */ +#define SC_P_FLEXCAN2_TX 110 /* ADMA.FLEXCAN2.TX, ADMA.SAI3.RXFS, ADMA.UART3.TX, ADMA.SAI1.RXC, LSIO.GPIO1.IO20 */ +#define SC_P_UART0_RX 111 /* ADMA.UART0.RX, ADMA.MQS.R, ADMA.FLEXCAN0.RX, SCU.UART0.RX, LSIO.GPIO1.IO21 */ +#define SC_P_UART0_TX 112 /* ADMA.UART0.TX, ADMA.MQS.L, ADMA.FLEXCAN0.TX, SCU.UART0.TX, LSIO.GPIO1.IO22 */ +#define SC_P_UART2_TX 113 /* ADMA.UART2.TX, ADMA.FTM.CH1, ADMA.FLEXCAN1.TX, LSIO.GPIO1.IO23 */ +#define SC_P_UART2_RX 114 /* ADMA.UART2.RX, ADMA.FTM.CH0, ADMA.FLEXCAN1.RX, LSIO.GPIO1.IO24 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLH 115 /* */ +#define SC_P_MIPI_DSI0_I2C0_SCL 116 /* MIPI_DSI0.I2C0.SCL, MIPI_DSI1.GPIO0.IO02, LSIO.GPIO1.IO25 */ +#define SC_P_MIPI_DSI0_I2C0_SDA 117 /* MIPI_DSI0.I2C0.SDA, MIPI_DSI1.GPIO0.IO03, LSIO.GPIO1.IO26 */ +#define SC_P_MIPI_DSI0_GPIO0_00 118 /* MIPI_DSI0.GPIO0.IO00, ADMA.I2C1.SCL, MIPI_DSI0.PWM0.OUT, LSIO.GPIO1.IO27 */ +#define SC_P_MIPI_DSI0_GPIO0_01 119 /* MIPI_DSI0.GPIO0.IO01, ADMA.I2C1.SDA, LSIO.GPIO1.IO28 */ +#define SC_P_MIPI_DSI1_I2C0_SCL 120 /* MIPI_DSI1.I2C0.SCL, MIPI_DSI0.GPIO0.IO02, LSIO.GPIO1.IO29 */ +#define SC_P_MIPI_DSI1_I2C0_SDA 121 /* MIPI_DSI1.I2C0.SDA, MIPI_DSI0.GPIO0.IO03, LSIO.GPIO1.IO30 */ +#define SC_P_MIPI_DSI1_GPIO0_00 122 /* MIPI_DSI1.GPIO0.IO00, ADMA.I2C2.SCL, MIPI_DSI1.PWM0.OUT, LSIO.GPIO1.IO31 */ +#define SC_P_MIPI_DSI1_GPIO0_01 123 /* MIPI_DSI1.GPIO0.IO01, ADMA.I2C2.SDA, LSIO.GPIO2.IO00 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_MIPIDSIGPIO 124 /* */ +#define SC_P_JTAG_TRST_B 125 /* SCU.JTAG.TRST_B, SCU.WDOG0.WDOG_OUT */ +#define SC_P_PMIC_I2C_SCL 126 /* SCU.PMIC_I2C.SCL, SCU.GPIO0.IOXX_PMIC_A35_ON, LSIO.GPIO2.IO01 */ +#define SC_P_PMIC_I2C_SDA 127 /* SCU.PMIC_I2C.SDA, SCU.GPIO0.IOXX_PMIC_GPU_ON, LSIO.GPIO2.IO02 */ +#define SC_P_PMIC_INT_B 128 /* SCU.DSC.PMIC_INT_B */ +#define SC_P_SCU_GPIO0_00 129 /* SCU.GPIO0.IO00, SCU.UART0.RX, M40.UART0.RX, ADMA.UART3.RX, LSIO.GPIO2.IO03 */ +#define SC_P_SCU_GPIO0_01 130 /* SCU.GPIO0.IO01, SCU.UART0.TX, M40.UART0.TX, ADMA.UART3.TX, SCU.WDOG0.WDOG_OUT */ +#define SC_P_SCU_PMIC_STANDBY 131 /* SCU.DSC.PMIC_STANDBY */ +#define SC_P_SCU_BOOT_MODE0 132 /* SCU.DSC.BOOT_MODE0 */ +#define SC_P_SCU_BOOT_MODE1 133 /* SCU.DSC.BOOT_MODE1 */ +#define SC_P_SCU_BOOT_MODE2 134 /* SCU.DSC.BOOT_MODE2, SCU.PMIC_I2C.SDA */ +#define SC_P_SCU_BOOT_MODE3 135 /* SCU.DSC.BOOT_MODE3, SCU.PMIC_I2C.SCL, SCU.DSC.RTC_CLOCK_OUTPUT_32K */ +#define SC_P_CSI_D00 136 /* CI_PI.D02, ADMA.SAI0.RXC */ +#define SC_P_CSI_D01 137 /* CI_PI.D03, ADMA.SAI0.RXD */ +#define SC_P_CSI_D02 138 /* CI_PI.D04, ADMA.SAI0.RXFS */ +#define SC_P_CSI_D03 139 /* CI_PI.D05, ADMA.SAI2.RXC */ +#define SC_P_CSI_D04 140 /* CI_PI.D06, ADMA.SAI2.RXD */ +#define SC_P_CSI_D05 141 /* CI_PI.D07, ADMA.SAI2.RXFS */ +#define SC_P_CSI_D06 142 /* CI_PI.D08, ADMA.SAI3.RXC */ +#define SC_P_CSI_D07 143 /* CI_PI.D09, ADMA.SAI3.RXD */ +#define SC_P_CSI_HSYNC 144 /* CI_PI.HSYNC, CI_PI.D00, ADMA.SAI3.RXFS */ +#define SC_P_CSI_VSYNC 145 /* CI_PI.VSYNC, CI_PI.D01 */ +#define SC_P_CSI_PCLK 146 /* CI_PI.PCLK, MIPI_CSI0.I2C0.SCL, ADMA.SPI1.SCK, LSIO.GPIO3.IO00 */ +#define SC_P_CSI_MCLK 147 /* CI_PI.MCLK, MIPI_CSI0.I2C0.SDA, ADMA.SPI1.SDO, LSIO.GPIO3.IO01 */ +#define SC_P_CSI_EN 148 /* CI_PI.EN, CI_PI.I2C.SCL, ADMA.I2C3.SCL, ADMA.SPI1.SDI, LSIO.GPIO3.IO02 */ +#define SC_P_CSI_RESET 149 /* CI_PI.RESET, CI_PI.I2C.SDA, ADMA.I2C3.SDA, ADMA.SPI1.CS0, LSIO.GPIO3.IO03 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHD 150 /* */ +#define SC_P_MIPI_CSI0_MCLK_OUT 151 /* MIPI_CSI0.ACM.MCLK_OUT, LSIO.GPIO3.IO04 */ +#define SC_P_MIPI_CSI0_I2C0_SCL 152 /* MIPI_CSI0.I2C0.SCL, MIPI_CSI0.GPIO0.IO02, LSIO.GPIO3.IO05 */ +#define SC_P_MIPI_CSI0_I2C0_SDA 153 /* MIPI_CSI0.I2C0.SDA, MIPI_CSI0.GPIO0.IO03, LSIO.GPIO3.IO06 */ +#define SC_P_MIPI_CSI0_GPIO0_01 154 /* MIPI_CSI0.GPIO0.IO01, ADMA.I2C0.SDA, LSIO.GPIO3.IO07 */ +#define SC_P_MIPI_CSI0_GPIO0_00 155 /* MIPI_CSI0.GPIO0.IO00, ADMA.I2C0.SCL, LSIO.GPIO3.IO08 */ +#define SC_P_QSPI0A_DATA0 156 /* LSIO.QSPI0A.DATA0, LSIO.GPIO3.IO09 */ +#define SC_P_QSPI0A_DATA1 157 /* LSIO.QSPI0A.DATA1, LSIO.GPIO3.IO10 */ +#define SC_P_QSPI0A_DATA2 158 /* LSIO.QSPI0A.DATA2, LSIO.GPIO3.IO11 */ +#define SC_P_QSPI0A_DATA3 159 /* LSIO.QSPI0A.DATA3, LSIO.GPIO3.IO12 */ +#define SC_P_QSPI0A_DQS 160 /* LSIO.QSPI0A.DQS, LSIO.GPIO3.IO13 */ +#define SC_P_QSPI0A_SS0_B 161 /* LSIO.QSPI0A.SS0_B, LSIO.GPIO3.IO14 */ +#define SC_P_QSPI0A_SS1_B 162 /* LSIO.QSPI0A.SS1_B, LSIO.GPIO3.IO15 */ +#define SC_P_QSPI0A_SCLK 163 /* LSIO.QSPI0A.SCLK, LSIO.GPIO3.IO16 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0A 164 /* */ +#define SC_P_QSPI0B_SCLK 165 /* LSIO.QSPI0B.SCLK, LSIO.QSPI1A.SCLK, LSIO.KPP0.COL0, LSIO.GPIO3.IO17 */ +#define SC_P_QSPI0B_DATA0 166 /* LSIO.QSPI0B.DATA0, LSIO.QSPI1A.DATA0, LSIO.KPP0.COL1, LSIO.GPIO3.IO18 */ +#define SC_P_QSPI0B_DATA1 167 /* LSIO.QSPI0B.DATA1, LSIO.QSPI1A.DATA1, LSIO.KPP0.COL2, LSIO.GPIO3.IO19 */ +#define SC_P_QSPI0B_DATA2 168 /* LSIO.QSPI0B.DATA2, LSIO.QSPI1A.DATA2, LSIO.KPP0.COL3, LSIO.GPIO3.IO20 */ +#define SC_P_QSPI0B_DATA3 169 /* LSIO.QSPI0B.DATA3, LSIO.QSPI1A.DATA3, LSIO.KPP0.ROW0, LSIO.GPIO3.IO21 */ +#define SC_P_QSPI0B_DQS 170 /* LSIO.QSPI0B.DQS, LSIO.QSPI1A.DQS, LSIO.KPP0.ROW1, LSIO.GPIO3.IO22 */ +#define SC_P_QSPI0B_SS0_B 171 /* LSIO.QSPI0B.SS0_B, LSIO.QSPI1A.SS0_B, LSIO.KPP0.ROW2, LSIO.GPIO3.IO23 */ +#define SC_P_QSPI0B_SS1_B 172 /* LSIO.QSPI0B.SS1_B, LSIO.QSPI1A.SS1_B, LSIO.KPP0.ROW3, LSIO.GPIO3.IO24 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0B 173 /* */ +/*@}*/ + +#endif /* IMX8QX_PADS_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_aips.h b/arm-trusted-firmware/plat/imx/common/include/imx_aips.h new file mode 100644 index 0000000..1d41fe0 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_aips.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_AIPS_H +#define IMX_AIPS_H + +#include + +#define AIPSTZ_OAPCR_COUNT 0x05 + +struct aipstz_regs { + uint32_t aipstz_mpr; + uint32_t res[15]; + uint32_t aipstz_opacr[AIPSTZ_OAPCR_COUNT]; +}; + +void imx_aips_init(void); + +#endif /* IMX_AIPS_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_caam.h b/arm-trusted-firmware/plat/imx/common/include/imx_caam.h new file mode 100644 index 0000000..61005b5 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_caam.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_CAAM_H +#define IMX_CAAM_H + +#include +#include +#include +#include + +struct caam_job_ring { + uint32_t jrmidr_ms; + uint32_t jrmidr_ls; +}; + +struct caam_rtic_mid { + uint32_t rticmidr_ms; + uint32_t rticmidr_ls; +}; + +struct caam_deco { + uint32_t deco_mid_ms; + uint32_t deco_mid_ls; +}; + +#define JOB_RING_OFFSET 0x10 +#define DEBUGCTL_OFFSET 0x58 +#define RES2_SIZE (DEBUGCTL_OFFSET - JOB_RING_OFFSET - \ + (sizeof(struct caam_job_ring) * CAAM_NUM_JOB_RINGS)) + +#define RTIC_MID_OFFSET 0x60 +#define DECORR_OFFSET 0x9C +#define RES3_SIZE (DECORR_OFFSET - RTIC_MID_OFFSET - \ + (sizeof(struct caam_rtic_mid) * CAAM_NUM_RTIC)) + +#define DECO_MID_OFFSET 0xA0 +#define DAR_OFFSET 0x120 +#define RES4_SIZE (DAR_OFFSET - DECO_MID_OFFSET - \ + (sizeof(struct caam_deco) * CAAM_NUM_DECO)) + +struct caam_ctrl { + uint32_t res0; + uint32_t mcfgr; + uint32_t res1; + uint32_t scfgr; + struct caam_job_ring jr[CAAM_NUM_JOB_RINGS]; + uint8_t res2[RES2_SIZE]; + uint32_t debuctl; + uint32_t jrstartr; + struct caam_rtic_mid mid[CAAM_NUM_RTIC]; + uint8_t res3[RES3_SIZE]; + uint32_t decorr; + struct caam_deco deco[CAAM_NUM_DECO]; + uint8_t res4[RES4_SIZE]; + uint32_t dar; + uint32_t drr; +} __packed; + +/* Job ring control bits */ +#define JROWN_NS BIT(3) +#define JROWN_MID 0x01 + +/* Declare CAAM API */ +void imx_caam_init(void); + +#endif /* IMX_CAAM_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_clock.h b/arm-trusted-firmware/plat/imx/common/include/imx_clock.h new file mode 100644 index 0000000..d75dcff --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_clock.h @@ -0,0 +1,1003 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef IMX_CLOCK_H +#define IMX_CLOCK_H + +#include +#include + +struct ccm_pll_ctrl { + uint32_t ccm_pll_ctrl; + uint32_t ccm_pll_ctrl_set; + uint32_t ccm_pll_ctrl_clr; + uint32_t ccm_pll_ctrl_tog; +}; + +/* Clock gate control */ +struct ccm_clk_gate_ctrl { + uint32_t ccm_ccgr; + uint32_t ccm_ccgr_set; + uint32_t ccm_ccgr_clr; + uint32_t ccm_ccgr_tog; +}; + +#define CCM_CCGR_SETTING0_DOM_CLK_NONE 0 +#define CCM_CCGR_SETTING0_DOM_CLK_RUN BIT(0) +#define CCM_CCGR_SETTING0_DOM_CLK_RUN_WAIT BIT(1) +#define CCM_CCGR_SETTING0_DOM_CLK_ALWAYS (BIT(1) | BIT(0)) +#define CCM_CCGR_SETTING1_DOM_CLK_NONE 0 +#define CCM_CCGR_SETTING1_DOM_CLK_RUN BIT(4) +#define CCM_CCGR_SETTING1_DOM_CLK_RUN_WAIT BIT(5) +#define CCM_CCGR_SETTING1_DOM_CLK_ALWAYS (BIT(5) | BIT(4)) +#define CCM_CCGR_SETTING2_DOM_CLK_NONE 0 +#define CCM_CCGR_SETTING2_DOM_CLK_RUN BIT(8) +#define CCM_CCGR_SETTING2_DOM_CLK_RUN_WAIT BIT(9) +#define CCM_CCGR_SETTING2_DOM_CLK_ALWAYS (BIT(9) | BIT(8)) +#define CCM_CCGR_SETTING3_DOM_CLK_NONE 0 +#define CCM_CCGR_SETTING3_DOM_CLK_RUN BIT(12) +#define CCM_CCGR_SETTING3_DOM_CLK_RUN_WAIT BIT(13) +#define CCM_CCGR_SETTING3_DOM_CLK_ALWAYS (BIT(13) | BIT(12)) + +enum { + CCM_CCGR_ID_ADC = 32, + CCM_CCGR_ID_AIPS1TZ = 10, + CCM_CCGR_ID_AIPS2TZ = 11, + CCM_CCGR_ID_AIPS3TZ = 12, + CCM_CCGR_ID_APBHDMA = 20, + CCM_CCGR_ID_CAAM = 36, + CCM_CCGR_ID_CM4 = 1, + CCM_CCGR_ID_CSI = 73, + CCM_CCGR_ID_CSU = 45, + CCM_CCGR_ID_DAP = 47, + CCM_CCGR_ID_DBGMON = 46, + CCM_CCGR_ID_DDRC = 19, + CCM_CCGR_ID_ECSPI1 = 120, + CCM_CCGR_ID_ECSPI2 = 121, + CCM_CCGR_ID_ECSPI3 = 122, + CCM_CCGR_ID_ECSPI4 = 123, + CCM_CCGR_ID_EIM = 22, + CCM_CCGR_ID_ENET1 = 112, + CCM_CCGR_ID_ENET2 = 113, + CCM_CCGR_ID_EPDC = 74, + CCM_CCGR_ID_FLEXCAN1 = 116, + CCM_CCGR_ID_FLEXCAN2 = 117, + CCM_CCGR_ID_FLEXTIMER1 = 128, + CCM_CCGR_ID_FLEXTIMER2 = 129, + CCM_CCGR_ID_GPIO1 = 160, + CCM_CCGR_ID_GPIO2 = 161, + CCM_CCGR_ID_GPIO3 = 162, + CCM_CCGR_ID_GPIO4 = 163, + CCM_CCGR_ID_GPIO5 = 164, + CCM_CCGR_ID_GPIO6 = 165, + CCM_CCGR_ID_GPIO7 = 166, + CCM_CCGR_ID_GPT1 = 124, + CCM_CCGR_ID_GPT2 = 125, + CCM_CCGR_ID_GPT3 = 126, + CCM_CCGR_ID_GPT4 = 127, + CCM_CCGR_ID_I2C1 = 136, + CCM_CCGR_ID_I2C2 = 137, + CCM_CCGR_ID_I2C3 = 138, + CCM_CCGR_ID_I2C4 = 139, + CCM_CCGR_ID_IOMUXC1 = 168, + CCM_CCGR_ID_IOMUXC2 = 169, + CCM_CCGR_ID_KPP = 120, + CCM_CCGR_ID_LCDIF = 75, + CCM_CCGR_ID_MIPI_CSI = 100, + CCM_CCGR_ID_MIPI_DSI = 101, + CCM_CCGR_ID_MIPI_PHY = 102, + CCM_CCGR_ID_MU = 39, + CCM_CCGR_ID_OCOTP = 35, + CCM_CCGR_ID_OCRAM = 17, + CCM_CCGR_ID_OCRAM_S = 18, + CCM_CCGR_ID_PCIE = 96, + CCM_CCGR_ID_PCIE_PHY = 96, + CCM_CCGR_ID_PERFMON1 = 68, + CCM_CCGR_ID_PERFMON2 = 69, + CCM_CCGR_ID_PWM1 = 132, + CCM_CCGR_ID_PWM2 = 133, + CCM_CCGR_ID_PWM3 = 134, + CCM_CCGR_ID_PMM4 = 135, + CCM_CCGR_ID_PXP = 76, + CCM_CCGR_ID_QOS1 = 42, + CCM_CCGR_ID_QOS2 = 43, + CCM_CCGR_ID_QOS3 = 44, + CCM_CCGR_ID_QUADSPI = 21, + CCM_CCGR_ID_RDC = 38, + CCM_CCGR_ID_ROMCP = 16, + CCM_CCGR_ID_SAI1 = 140, + CCM_CCGR_ID_SAI2 = 141, + CCM_CCGR_ID_SAI3 = 142, + CCM_CCGR_ID_SCTR = 34, + CCM_CCGR_ID_SDMA = 72, + CCM_CCGR_ID_SEC = 49, + CCM_CCGR_ID_SEMA42_1 = 64, + CCM_CCGR_ID_SEMA42_2 = 65, + CCM_CCGR_ID_SIM_DISPLAY = 5, + CCM_CCGR_ID_SIM_ENET = 6, + CCM_CCGR_ID_SIM_M = 7, + CCM_CCGR_ID_SIM_MAIN = 4, + CCM_CCGR_ID_SIM_S = 8, + CCM_CCGR_ID_SIM_WAKEUP = 9, + CCM_CCGR_ID_SIM1 = 144, + CCM_CCGR_ID_SIM2 = 145, + CCM_CCGR_ID_SIM_NAND = 20, + CCM_CCGR_ID_DISPLAY_CM4 = 1, + CCM_CCGR_ID_DRAM = 19, + CCM_CCGR_ID_SNVS = 37, + CCM_CCGR_ID_SPBA = 12, + CCM_CCGR_ID_TRACE = 48, + CCM_CCGR_ID_TZASC = 19, + CCM_CCGR_ID_UART1 = 148, + CCM_CCGR_ID_UART2 = 149, + CCM_CCGR_ID_UART3 = 150, + CCM_CCGR_ID_UART4 = 151, + CCM_CCGR_ID_UART5 = 152, + CCM_CCGR_ID_UART6 = 153, + CCM_CCGR_ID_UART7 = 154, + CCM_CCGR_ID_USB_HS = 40, + CCM_CCGR_ID_USB_IPG = 104, + CCM_CCGR_ID_USB_PHY_480MCLK = 105, + CCM_CCGR_ID_USB_OTG1_PHY = 106, + CCM_CCGR_ID_USB_OTG2_PHY = 107, + CCM_CCGR_ID_USBHDC1 = 108, + CCM_CCGR_ID_USBHDC2 = 109, + CCM_CCGR_ID_USBHDC3 = 110, + CCM_CCGR_ID_WDOG1 = 156, + CCM_CCGR_ID_WDOG2 = 157, + CCM_CCGR_ID_WDOG3 = 158, + CCM_CCGR_ID_WDOG4 = 159, +}; + +/* Clock target block */ +struct ccm_target_root_ctrl { + uint32_t ccm_target_root; + uint32_t ccm_target_root_set; + uint32_t ccm_target_root_clr; + uint32_t ccm_target_root_tog; + uint32_t ccm_misc; + uint32_t ccm_misc_set; + uint32_t ccm_misc_clr; + uint32_t ccm_misc_tog; + uint32_t ccm_post; + uint32_t ccm_post_set; + uint32_t ccm_post_clr; + uint32_t ccm_post_tog; + uint32_t ccm_pre; + uint32_t ccm_pre_set; + uint32_t ccm_pre_clr; + uint32_t ccm_pre_tog; + uint32_t reserved[0x0c]; + uint32_t ccm_access_ctrl; + uint32_t ccm_access_ctrl_set; + uint32_t ccm_access_ctrl_clr; + uint32_t ccm_access_ctrl_tog; +}; + +#define CCM_TARGET_ROOT_ENABLE BIT(28) +#define CCM_TARGET_MUX(x) (((x) - 1) << 24) +#define CCM_TARGET_PRE_PODF(x) (((x) - 1) << 16) +#define CCM_TARGET_POST_PODF(x) ((x) - 1) + +/* Target root MUX values - selects the clock source for a block */ +/* ARM_A7_CLK_ROOT */ + +#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_ARM_PLL BIT(24) +#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_ENET_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_DDR_PLL (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_SYS_PLL_PFD0 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* ARM_M4_CLK_ROOT */ + +#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_ENET_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_SYS_PLL_PFD2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_DDR_PLL_DIV2 BIT(26) +#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ARM_M4_CLK_ROOTV_IDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ARM_M4_CLK_ROOTUSB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* MAIN_AXI_CLK_ROOT */ + +#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_SYS_PLL_PFD1 BIT(24) +#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_ENET_PLL_DIV4 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_SYS_PLL_PFD5 BIT(26) +#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24)) + +/* DISP_AXI_CLK_ROOT */ + +#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_SYS_PLL_PFD1 BIT(24) +#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_ENET_PLL_DIV4 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_SYS_PLL_PFD6 BIT(26) +#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_SYS_PLL_PFD7 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* ENET_AXI_CLK_ROOT */ + +#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_SYS_PLL_PFD2 BIT(24) +#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_ENET_PLL_DIV4 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_SYS_PLL_DIV2 BIT(26) +#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_SYS_PLL_PFD4 ((BIT(26) | BIT(25) | BIT(24)) + +/* NAND_USDHC_BUS_CLK_ROOT */ + +#define CM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_AHB BIT(24) +#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_SYS_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(26) +#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_AUDIO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* AHB_CLK_ROOT */ + +#define CCM_TRGT_MUX_AHB_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_AHB_CLK_ROOT_SYS_PLL_PFD2 BIT(24) +#define CCM_TRGT_MUX_AHB_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_AHB_CLK_ROOT_SYS_PLL_PFD0 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_AHB_CLK_ROOT_ENET_PLL_DIV8 BIT(26) +#define CCM_TRGT_MUX_AHB_CLK_ROOT_USB_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_AHB_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_AHB_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* IPG_CLK_ROOT */ +#define CCM_TRGT_MUX_IPG_CLK_ROOT_AHB_CLK_ROOT 0 + +/* DRAM_PHYM_CLK_ROOT */ +#define CCM_TRGT_MUX_DRAM_PHYM_CLK_ROOT_DDR_PLL 0 +#define CCM_TRGT_MUX_DRAM_PHYM_CLK_ROOT_DRAM_PHYM_ALT_CLK_ROOT BIT(24) + +/* DRAM_CLK_ROOT */ + +#define CCM_TRGT_MUX_DRAM_CLK_ROOT_DDR_PLL 0 +#define CCM_TRGT_MUX_DRAM_CLK_ROOT_DRAM_ALT_CLK_ROOT BIT(24) + +/* DRAM_PHYM_ALT_CLK_ROOT */ +#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_DDR_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_SYS_PLL BIT(25) +#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_USB_PLL BIT(26) +#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_SYS_PLL_PFD7 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* DRAM_ALT_CLK_ROOT */ + +#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_DDR_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_SYS_PLL BIT(25) +#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_ENET_PLL_DIV4 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_USB_PLL BIT(26) +#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_SYS_PLL_PFD0 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_SYS_PLL_PFD2 ((BIT(26) | BIT(25) | BIT(24)) + +/* USB_HSIC_CLK_ROOT */ + +#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL BIT(24) +#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_USB_PLL BIT(25) +#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD3 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD4 BIT(26) +#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD5 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24)) + +/* LCDIF_PIXEL_CLK_ROOT */ + +#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_SYS_PLL_PFD5 BIT(24) +#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_EXT_CLK3 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_SYS_PLL_PFD4 BIT(26) +#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* MIPI_DSI_CLK_ROOT */ + +#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_SYS_PLL_PFD5 BIT(24) +#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_SYS_PLL_PFD3 BIT(25) +#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_SYS_PLL (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_SYS_PLL_PFD0_DIV2 BIT(26) +#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_DDR_PLL_DIV2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_AUDIO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* MIPI_CSI_CLK_ROOT */ + +#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_SYS_PLL_PFD4 BIT(24) +#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_SYS_PLL_PFD3 BIT(25) +#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_SYS_PLL (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_SYS_PLL_PFD0_DIV2 BIT(26) +#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_DDR_PLL_DIV2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_AUDIO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* MIPI_DPHY_REF_CLK_ROOT */ + +#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_SYS_PLL_DIV4 BIT(24) +#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_SYS_PLL_PFD5 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_REF_1M BIT(26) +#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24)) + +/* SAI1_CLK_ROOT */ + +#define CCM_TRGT_MUX_SAI1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_SAI1_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_SAI1_CLK_ROOT_AUDIO_PLL BIT(25) +#define CCM_TRGT_MUX_SAI1_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_SAI1_CLK_ROOT_VIDEO_PLL BIT(26) +#define CCM_TRGT_MUX_SAI1_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_SAI1_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_SAI1_CLK_ROOT_EXT_CLK2 ((BIT(26) | BIT(25) | BIT(24)) + +/* SAI2_CLK_ROOT */ + +#define CCM_TRGT_MUX_SAI2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_SAI2_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_SAI2_CLK_ROOT_AUDIO_PLL BIT(25) +#define CCM_TRGT_MUX_SAI2_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_SAI2_CLK_ROOT_VIDEO_PLL BIT(26) +#define CCM_TRGT_MUX_SAI2_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_SAI2_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_SAI2_CLK_ROOT_EXT_CLK2 ((BIT(26) | BIT(25) | BIT(24)) + +/* SAI3_CLK_ROOT */ + +#define CCM_TRGT_MUX_SAI3_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_SAI3_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_SAI3_CLK_ROOT_AUDIO_PLL BIT(25) +#define CCM_TRGT_MUX_SAI3_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_SAI3_CLK_ROOT_VIDEO_PLL BIT(26) +#define CCM_TRGT_MUX_SAI3_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_SAI3_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_SAI3_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24)) + +/* ENET1_REF_CLK_ROOT */ + +#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_ENET_PLL_DIV8 BIT(24) +#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_ENET_PLL_DIV20 BIT(25) +#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_ENET_PLL_DIV40 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_SYS_PLL_DIV4 BIT(26) +#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_EXT_CLK4 ((BIT(26) | BIT(25) | BIT(24)) + +/* ENET1_TIME_CLK_ROOT */ + +#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_AUDIO_PLL BIT(25) +#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_EXT_CLK1 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_EXT_CLK2 BIT(26) +#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* ENET_PHY_REF_CLK_ROOT */ + +#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_ENET_PLL_DIV40 BIT(24) +#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_ENET_PLL_DIV20 BIT(25) +#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_ENET_PLL_DIV8 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_DDR_PLL_DIV2 BIT(26) +#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_SYS_PLL_PFD3 ((BIT(26) | BIT(25) | BIT(24)) + +/* EIM_CLK_ROOT */ + +#define CCM_TRGT_MUX_EIM_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_EIM_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_EIM_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_EIM_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_EIM_CLK_ROOT_SYS_PLL_PFD2 BIT(26) +#define CCM_TRGT_MUX_EIM_CLK_ROOT_SYS_PLL_PFD3 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_EIM_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_EIM_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* NAND_CLK_ROOT */ + +#define CCM_TRGT_MUX_NAND_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_NAND_CLK_ROOT_SYS_PLL BIT(24) +#define CCM_TRGT_MUX_NAND_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_NAND_CLK_ROOT_SYS_PLL_PFD0 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_NAND_CLK_ROOT_SYS_PLL_PFD3 BIT(26) +#define CCM_TRGT_MUX_NAND_CLK_ROOT_ENET_PLL_DIV2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_NAND_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_NAND_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* QSPI_CLK_ROOT */ + +#define CCM_TRGT_MUX_QSPI_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD4 BIT(24) +#define CCM_TRGT_MUX_QSPI_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_QSPI_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD3 BIT(26) +#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24)) + +/* USDHC1_CLK_ROOT */ + +#define CM_TRGT_MUX_USDHC1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD0 BIT(24) +#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD4 BIT(26) +#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24)) + +/* USDHC2_CLK_ROOT */ + +#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD0 BIT(24) +#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD4 BIT(26) +#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24)) + +/* USDHC3_CLK_ROOT */ + +#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD0 BIT(24) +#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD4 BIT(26) +#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24)) + +/* CAN1_CLK_ROOT */ + +#define CCM_TRGT_MUX_CAN1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_CAN1_CLK_ROOT_SYS_PLL_DIV4 BIT(24) +#define CCM_TRGT_MUX_CAN1_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_CAN1_CLK_ROOT_SYS_PLL (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_CAN1_CLK_ROOT_ENET_PLL_DIV25 BIT(26) +#define CCM_TRGT_MUX_CAN1_CLK_ROOT_USB_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_CAN1_CLK_ROOT_EXT_CLK1 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_CAN1_CLK_ROOT_EXT_CLK4 ((BIT(26) | BIT(25) | BIT(24)) + +/* CAN2_CLK_ROOT */ + +#define CCM_TRGT_MUX_CAN2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_CAN2_CLK_ROOT_SYS_PLL_DIV4 BIT(24) +#define CCM_TRGT_MUX_CAN2_CLK_ROOT_DDR_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_CAN2_CLK_ROOT_SYS_PLL (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_CAN2_CLK_ROOT_ENET_PLL_DIV25 BIT(26) +#define CCM_TRGT_MUX_CAN2_CLK_ROOT_USB_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_CAN2_CLK_ROOT_EXT_CLK1 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_CAN2_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24)) + +/* I2C1_CLK_ROOT */ + +#define CCM_TRGT_MUX_I2C1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_I2C1_CLK_ROOT_SYS_PLL_DIV4 BIT(24) +#define CCM_TRGT_MUX_I2C1_CLK_ROOT_ENET_PLL_DIV20 BIT(25) +#define CCM_TRGT_MUX_I2C1_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_I2C1_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_I2C1_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_I2C1_CLK_ROOT_USB_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_I2C1_CLK_ROOT_SYS_PLL_PFD2_DIV2 ((BIT(26) | BIT(25) | BIT(24)) + +/* I2C2_CLK_ROOT */ + +#define CCM_TRGT_MUX_I2C2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_I2C2_CLK_ROOT_SYS_PLL_DIV4 BIT(24) +#define CCM_TRGT_MUX_I2C2_CLK_ROOT_ENET_PLL_DIV20 BIT(25) +#define CCM_TRGT_MUX_I2C2_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_I2C2_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_I2C2_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_I2C2_CLK_ROOT_USB_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_I2C2_CLK_ROOT_SYS_PLL_PFD2_DIV2 ((BIT(26) | BIT(25) | BIT(24)) + +/* I2C3_CLK_ROOT */ + +#define CCM_TRGT_MUX_I2C3_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_I2C3_CLK_ROOT_SYS_PLL_DIV4 BIT(24) +#define CCM_TRGT_MUX_I2C3_CLK_ROOT_ENET_PLL_DIV20 BIT(25) +#define CCM_TRGT_MUX_I2C3_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_I2C3_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_I2C3_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_I2C3_CLK_ROOT_USB_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_I2C3_CLK_ROOT_SYS_PLL_PFD2_DIV2 ((BIT(26) | BIT(25) | BIT(24)) + +/* I2C4_CLK_ROOT */ + +#define CCM_TRGT_MUX_I2C4_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_I2C4_CLK_ROOT_SYS_PLL_DIV4 BIT(24) +#define CCM_TRGT_MUX_I2C4_CLK_ROOT_ENET_PLL_DIV20 BIT(25) +#define CCM_TRGT_MUX_I2C4_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_I2C4_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_I2C4_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_I2C4_CLK_ROOT_USB_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_I2C4_CLK_ROOT_SYS_PLL_PFD2_DIV2 ((BIT(26) | BIT(25) | BIT(24)) + +/* UART1_CLK_ROOT */ + +#define CCM_TRGT_MUX_UART1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_UART1_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_UART1_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_UART1_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_UART1_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_UART1_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_UART1_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_UART1_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* UART2_CLK_ROOT */ + +#define CCM_TRGT_MUX_UART2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_UART2_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_UART2_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_UART2_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_UART2_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_UART2_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_UART2_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_UART2_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* UART3_CLK_ROOT */ + +#define CCM_TRGT_MUX_UART3_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_UART3_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_UART3_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_UART3_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_UART3_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_UART3_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_UART3_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_UART3_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* UART4_CLK_ROOT */ + +#define CCM_TRGT_MUX_UART4_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_UART4_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_UART4_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_UART4_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_UART4_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_UART4_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_UART4_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_UART4_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* UART5_CLK_ROOT */ + +#define CCM_TRGT_MUX_UART5_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_UART5_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_UART5_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_UART5_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_UART5_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_UART5_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_UART5_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_UART5_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* UART6_CLK_ROOT */ + +#define CCM_TRGT_MUX_UART6_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_UART6_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_UART6_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_UART6_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_UART6_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_UART6_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_UART6_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_UART6_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* UART7_CLK_ROOT */ + +#define CCM_TRGT_MUX_UART7_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_UART7_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_UART7_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_UART7_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_UART7_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_UART7_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_UART7_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_UART7_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* ECSPI1_CLK_ROOT */ + +#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_SYS_PLL_DIV4 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* ECSPI2_CLK_ROOT */ + +#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_SYS_PLL_DIV4 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* ECSPI3_CLK_ROOT */ + +#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_SYS_PLL_DIV4 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* ECSPI4_CLK_ROOT */ + +#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_ENET_PLL_DIV25 BIT(25) +#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_SYS_PLL_DIV4 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_SYS_PLL BIT(26) +#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* PWM1_CLK_ROOT */ + +#define CCM_TRGT_MUX_PWM1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_PWM1_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_PWM1_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_PWM1_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_PWM1_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_PWM1_CLK_ROOT_EXT_CLK1 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_PWM1_CLK_ROOT_REF_1M (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_PWM1_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* PWM2_CLK_ROOT */ + +#define CCM_TRGT_MUX_PWM2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_PWM2_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_PWM2_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_PWM2_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_PWM2_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_PWM2_CLK_ROOT_EXT_CLK1 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_PWM2_CLK_ROOT_REF_1M (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_PWM2_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* PWM3_CLK_ROOT */ + +#define CCM_TRGT_MUX_PWM3_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_PWM3_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_PWM3_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_PWM3_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_PWM3_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_PWM3_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_PWM3_CLK_ROOT_REF_1M (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_PWM3_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* PWM4_CLK_ROOT */ + +#define CCM_TRGT_MUX_PWM4_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_PWM4_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_PWM4_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_PWM4_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_PWM4_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_PWM4_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_PWM4_CLK_ROOT_REF_1M (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_PWM4_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* FLEXTIMER1_CLK_ROOT */ + +#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_REF_1M (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* FLEXTIMER2_CLK_ROOT */ + +#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_AUDIO_PLL BIT(26) +#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_REF_1M (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* Target SIM1_CLK_ROOT */ + +#define CCM_TRGT_MUX_SIM1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_SIM1_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_SIM1_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_SIM1_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_SIM1_CLK_ROOT_USB_PLL BIT(26) +#define CCM_TRGT_MUX_SIM1_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_SIM1_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_SIM1_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24)) + +/* Target SIM2_CLK_ROOT */ + +#define CCM_TRGT_MUX_SIM2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_SIM2_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_SIM2_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_SIM2_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_SIM2_CLK_ROOT_USB_PLL BIT(26) +#define CCM_TRGT_MUX_SIM2_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_SIM2_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_SIM2_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24)) + +/* Target GPT1_CLK_ROOT */ + +#define CCM_TRGT_MUX_GPT1_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_GPT1_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_GPT1_CLK_ROOT_SYS_PLL_PFD0 BIT(25) +#define CCM_TRGT_MUX_GPT1_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_GPT1_CLK_ROOT_VIDEO_PLL BIT(26) +#define CCM_TRGT_MUX_GPT1_CLK_ROOT_REF_1M (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_GPT1_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_GPT1_CLK_ROOT_EXT_CLK1 ((BIT(26) | BIT(25) | BIT(24)) + +/* Target GPT2_CLK_ROOT */ + +#define CCM_TRGT_MUX_GPT2_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_GPT2_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_GPT2_CLK_ROOT_SYS_PLL_PFD0 BIT(25) +#define CCM_TRGT_MUX_GPT2_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_GPT2_CLK_ROOT_VIDEO_PLL BIT(26) +#define CCM_TRGT_MUX_GPT2_CLK_ROOT_REF_1M (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_GPT2_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_GPT2_CLK_ROOT_EXT_CLK2 ((BIT(26) | BIT(25) | BIT(24)) + +/* Target GPT3_CLK_ROOT */ + +#define CCM_TRGT_MUX_GPT3_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_GPT3_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_GPT3_CLK_ROOT_SYS_PLL_PFD0 BIT(25) +#define CCM_TRGT_MUX_GPT3_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_GPT3_CLK_ROOT_VIDEO_PLL BIT(26) +#define CCM_TRGT_MUX_GPT3_CLK_ROOT_REF_1M (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_GPT3_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_GPT3_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24)) + +/*Target GPT4_CLK_ROOT */ + +#define CCM_TRGT_MUX_GPT4_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_GPT4_CLK_ROOT_ENET_PLL_DIV10 BIT(24) +#define CCM_TRGT_MUX_GPT4_CLK_ROOT_SYS_PLL_PFD0 BIT(25) +#define CCM_TRGT_MUX_GPT4_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_GPT4_CLK_ROOT_VIDEO_PLL BIT(26) +#define CCM_TRGT_MUX_GPT4_CLK_ROOT_REF_1M (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_GPT4_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_GPT4_CLK_ROOT_EXT_CLK4 ((BIT(26) | BIT(25) | BIT(24)) + +/* Target TRACE_CLK_ROOT */ + +#define CCM_TRGT_MUX_TRACE_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_TRACE_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_TRACE_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_TRACE_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_TRACE_CLK_ROOT_ENET_PLL_DIV8 BIT(26) +#define CCM_TRGT_MUX_TRACE_CLK_ROOT_USB_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_TRACE_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_TRACE_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24)) + +/* Target WDOG_CLK_ROOT */ + +#define CCM_TRGT_MUX_WDOG_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_WDOG_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_WDOG_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_WDOG_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_WDOG_CLK_ROOT_ENET_PLL_DIV8 BIT(26) +#define CCM_TRGT_MUX_WDOG_CLK_ROOT_USB_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_WDOG_CLK_ROOT_REF_1M (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_WDOG_CLK_ROOT_SYS_PLL_PFD1_DIV2 ((BIT(26) | BIT(25) | BIT(24)) +#define WDOG_DEFAULT_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\ + CCM_TRGT_MUX_WDOG_CLK_ROOT_OSC_24M) + +/* Target CSI_MCLK_CLK_ROOT */ + +#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_ENET_PLL_DIV8 BIT(26) +#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* Target AUDIO_MCLK_CLK_ROOT */ +#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_OSC_24M 0 +#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24) +#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_SYS_PLL_DIV4 BIT(25) +#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_ENET_PLL_DIV8 BIT(26) +#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24)) + +/* Target CCM_CLKO1 */ +#define CCM_TRGT_MUX_CCM_CLKO1_OSC_24M 0 +#define CCM_TRGT_MUX_CCM_CLKO1_SYS_PLL BIT(24) +#define CCM_TRGT_MUX_CCM_CLKO1_SYS_PLL_DIV2 BIT(25) +#define CCM_TRGT_MUX_CCM_CLKO1_SYS_PLL_PFD0_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_CCM_CLKO1_SYS_PLL_PFD3 BIT(26) +#define CCM_TRGT_MUX_CCM_CLKO1_ENET_PLL_DIV2 (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_CCM_CLKO1_DDR_PLL_DIV2 (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_CCM_CLKO1_REF_1M ((BIT(26) | BIT(25) | BIT(24)) + +/* Target CCM_CLKO2 */ +#define CCM_TRGT_MUX_CCM_CLKO2_OSC_24M 0 +#define CCM_TRGT_MUX_CCM_CLKO2_SYS_PLL_DIV2 BIT(24) +#define CCM_TRGT_MUX_CCM_CLKO2_SYS_PLL_PFD0 BIT(25) +#define CCM_TRGT_MUX_CCM_CLKO2_SYS_PLL_PFD1_DIV2 (BIT(25) | BIT(24)) +#define CCM_TRGT_MUX_CCM_CLKO2_SYS_PLL_PFD4 BIT(26) +#define CCM_TRGT_MUX_CCM_CLKO2_AUDIO_PLL (BIT(26) | BIT(24)) +#define CCM_TRGT_MUX_CCM_CLKO2_VIDEO_PLL (BIT(26) | BIT(25)) +#define CCM_TRGT_MUX_CCM_CLKO2_OSC_32K ((BIT(26) | BIT(25) | BIT(24)) + +/* + * See Table 5-11 in i.MX7 Solo Reference manual rev 0.1 + * The indices must be calculated by dividing the offset by + * sizeof (struct ccm_target_root_ctrl) => 0x80 bytes for each index + */ +enum { + CCM_TRT_ID_ARM_A7_CLK_ROOT = 0, + CCM_TRT_ID_ARM_M4_CLK_ROOT = 1, + CCM_TRT_ID_MAIN_AXI_CLK_ROOT = 16, + CCM_TRT_ID_DISP_AXI_CLK_ROOT = 17, + CCM_TRT_ID_ENET_AXI_CLK_ROOT = 18, + CCM_TRT_ID_NAND_USDHC_BUS_CLK_ROOT = 19, + CCM_TRT_ID_AHB_CLK_ROOT = 32, + CCM_TRT_ID_IPG_CLK_ROOT = 33, + CCM_TRT_ID_DRAM_PHYM_CLK_ROOT = 48, + CCM_TRT_ID_DRAM_CLK_ROOT = 49, + CCM_TRT_ID_DRAM_PHYM_ALT_CLK_ROOT = 64, + CCM_TRT_ID_DRAM_ALT_CLK_ROOT = 65, + CCM_TRT_ID_USB_HSIC_CLK_ROOT = 66, + CCM_TRT_ID_LCDIF_PIXEL_CLK_ROOT = 70, + CCM_TRT_ID_MIPI_DSI_CLK_ROOT = 71, + CCM_TRT_ID_MIPI_CSI_CLK_ROOT = 72, + CCM_TRT_ID_MIPI_DPHY_REF_CLK_ROOT = 73, + CCM_TRT_ID_SAI1_CLK_ROOT = 74, + CCM_TRT_ID_SAI2_CLK_ROOT = 75, + CCM_TRT_ID_SAI3_CLK_ROOT = 76, + CCM_TRT_ID_ENET1_REF_CLK_ROOT = 78, + CCM_TRT_ID_ENET1_TIME_CLK_ROOT = 79, + CCM_TRT_ID_ENET_PHY_REF_CLK_ROOT = 82, + CCM_TRT_ID_EIM_CLK_ROOT = 83, + CCM_TRT_ID_NAND_CLK_ROOT = 84, + CCM_TRT_ID_QSPI_CLK_ROOT = 85, + CCM_TRT_ID_USDHC1_CLK_ROOT = 86, + CCM_TRT_ID_USDHC2_CLK_ROOT = 87, + CCM_TRT_ID_USDHC3_CLK_ROOT = 88, + CCM_TRT_ID_CAN1_CLK_ROOT = 89, + CCM_TRT_ID_CAN2_CLK_ROOT = 90, + CCM_TRT_ID_I2C1_CLK_ROOT = 91, + CCM_TRT_ID_I2C2_CLK_ROOT = 92, + CCM_TRT_ID_I2C3_CLK_ROOT = 93, + CCM_TRT_ID_I2C4_CLK_ROOT = 94, + CCM_TRT_ID_UART1_CLK_ROOT = 95, + CCM_TRT_ID_UART2_CLK_ROOT = 96, + CCM_TRT_ID_UART3_CLK_ROOT = 97, + CCM_TRT_ID_UART4_CLK_ROOT = 98, + CCM_TRT_ID_UART5_CLK_ROOT = 99, + CCM_TRT_ID_UART6_CLK_ROOT = 100, + CCM_TRT_ID_UART7_CLK_ROOT = 101, + CCM_TRT_ID_ECSPI1_CLK_ROOT = 102, + CCM_TRT_ID_ECSPI2_CLK_ROOT = 103, + CCM_TRT_ID_ECSPI3_CLK_ROOT = 104, + CCM_TRT_ID_ECSPI4_CLK_ROOT = 105, + CCM_TRT_ID_PWM1_CLK_ROOT = 106, + CCM_TRT_ID_PWM2_CLK_ROOT = 107, + CCM_TRT_ID_PWM3_CLK_ROOT = 108, + CCM_TRT_ID_PWM4_CLK_ROOT = 109, + CCM_TRT_ID_FLEXTIMER1_CLK_ROOT = 110, + CCM_TRT_ID_FLEXTIMER2_CLK_ROOT = 111, + CCM_TRT_ID_SIM1_CLK_ROOT = 112, + CCM_TRT_ID_SIM2_CLK_ROOT = 113, + CCM_TRT_ID_GPT1_CLK_ROOT = 114, + CCM_TRT_ID_GPT2_CLK_ROOT = 115, + CCM_TRT_ID_GPT3_CLK_ROOT = 116, + CCM_TRT_ID_GPT4_CLK_ROOT = 117, + CCM_TRT_ID_TRACE_CLK_ROOT = 118, + CCM_TRT_ID_WDOG_CLK_ROOT = 119, + CCM_TRT_ID_CSI_MCLK_CLK_ROOT = 120, + CCM_TRT_ID_AUDIO_MCLK_CLK_ROOT = 121, + CCM_TRT_ID_CCM_CLKO1 = 123, + CCM_TRT_ID_CCM_CLKO2 = 124, +}; + +#define CCM_MISC_VIOLATE BIT(8) +#define CCM_MISC_TIMEOUT BIT(4) +#define CCM_MISC_AUTHEN_FAIL BIT(0) + +#define CCM_POST_BUSY2 BIT(31) +#define CCM_POST_SELECT_BRANCH_A BIT(28) +#define CCM_POST_BUSY1 BIT(7) +#define CCM_POST_POST_PODF(x) ((x) - 1) + +#define CCM_PRE_BUSY4 BIT(31) +#define CCM_PRE_ENABLE_A BIT(28) +#define CCM_PRE_MUX_A(x) (((x) - 1) << 24) +#define CCM_PRE_BUSY3 BIT(19) +#define CCM_PRE_PODF_A(x) (((x) - 1) << 16) +#define CCM_PRE_BUSY1 BIT(15) +#define CCM_PRE_ENABLE_B BIT(12) +#define CCM_PRE_MUX_B(x) (((x) - 1) << 8) +#define CCM_PRE_BUSY0 BIT(3) +#define CCM_PRE_POST_PODF(x) ((x) - 1) + +#define CCM_ACCESS_CTRL_LOCK BIT(31) +#define CCM_ACCESS_SEMA_ENABLE BIT(28) +#define CCM_ACCESS_DOM3_WHITELIST BIT(27) +#define CCM_ACCESS_DOM2_WHITELIST BIT(26) +#define CCM_ACCESS_DOM1_WHITELIST BIT(25) +#define CCM_ACCESS_DOM0_WHITELIST BIT(24) +#define CCM_ACCESS_MUTEX BIT(20) +#define CCM_ACCESS_OWNER_ID(x) ((x) << 16) +#define CCM_ACCESS_DOM3_INFO(x) ((x) << 12) +#define CCM_ACCESS_DOM2_INFO(x) ((x) << 8) +#define CCM_ACCESS_DOM1_INFO(x) ((x) << 4) +#define CCM_ACCESS_DOM0_INFO(x) (x) + +#define CCM_PLL_CTRL_NUM 0x21 +#define CCM_CLK_GATE_CTRL_NUM 0xbf +#define CCM_ROOT_CTRL_NUM 0x79 + +struct ccm { + uint32_t ccm_gpr0; + uint32_t ccm_gpr0_set; + uint32_t ccm_gpr0_clr; + uint32_t ccm_grp0_tog; + uint32_t reserved[0x1fc]; + struct ccm_pll_ctrl ccm_pll_ctrl[CCM_PLL_CTRL_NUM]; + uint32_t reserved1[0xd7c]; + struct ccm_clk_gate_ctrl ccm_clk_gate_ctrl[CCM_CLK_GATE_CTRL_NUM]; + uint32_t reserved2[0xd04]; + struct ccm_target_root_ctrl ccm_root_ctrl[CCM_ROOT_CTRL_NUM]; +}; + +void imx_clock_target_set(unsigned int id, uint32_t val); +void imx_clock_target_clr(unsigned int id, uint32_t val); +void imx_clock_gate_enable(unsigned int id, bool enable); + +void imx_clock_init(void); + +void imx_clock_enable_uart(unsigned int uart_id, uint32_t uart_clk_en_bits); +void imx_clock_disable_uart(unsigned int uart_id); +void imx_clock_enable_usdhc(unsigned int usdhc_id, uint32_t usdhc_clk_en_bits); +void imx_clock_set_wdog_clk_root_bits(uint32_t wdog_clk_root_en_bits); +void imx_clock_enable_wdog(unsigned int wdog_id); +void imx_clock_disable_wdog(unsigned int wdog_id); +void imx_clock_enable_usb(unsigned int usb_id); +void imx_clock_disable_usb(unsigned int usb_id); +void imx_clock_set_usb_clk_root_bits(uint32_t usb_clk_root_en_bits); + +#endif /* IMX_CLOCK_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_csu.h b/arm-trusted-firmware/plat/imx/common/include/imx_csu.h new file mode 100644 index 0000000..879d10b --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_csu.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef IMX_CSU_H +#define IMX_CSU_H + +#include + +/* + * Security Reference Manual for i.MX 7Dual and 7Solo Applications Processors, + * Rev. 0, 03/2017 Section 3.3.1 + * + * Config secure level register (CSU_CSLn) + */ +#define CSU_CSL_LOCK_S1 BIT(24) +#define CSU_CSL_NSW_S1 BIT(23) +#define CSU_CSL_NUW_S1 BIT(22) +#define CSU_CSL_SSW_S1 BIT(21) +#define CSU_CSL_SUW_S1 BIT(20) +#define CSU_CSL_NSR_S1 BIT(19) +#define CSU_CSL_NUR_S1 BIT(18) +#define CSU_CSL_SSR_S1 BIT(17) +#define CSU_CSL_SUR_S1 BIT(16) +#define CSU_CSL_LOCK_S2 BIT(8) +#define CSU_CSL_NSW_S2 BIT(7) +#define CSU_CSL_NUW_S2 BIT(6) +#define CSU_CSL_SSW_S2 BIT(5) +#define CSU_CSL_SUW_S2 BIT(4) +#define CSU_CSL_NSR_S2 BIT(3) +#define CSU_CSL_NUR_S2 BIT(2) +#define CSU_CSL_SSR_S2 BIT(1) +#define CSU_CSL_SUR_S2 BIT(0) + +#define CSU_CSL_OPEN_ACCESS (CSU_CSL_NSW_S1 | CSU_CSL_NUW_S1 | CSU_CSL_SSW_S1 |\ + CSU_CSL_SUW_S1 | CSU_CSL_NSR_S1 | CSU_CSL_NUR_S1 |\ + CSU_CSL_SSR_S1 | CSU_CSL_SUR_S1 | CSU_CSL_NSW_S2 |\ + CSU_CSL_NUW_S2 | CSU_CSL_SSW_S2 | CSU_CSL_SUW_S2 |\ + CSU_CSL_NSR_S2 | CSU_CSL_NUR_S2 | CSU_CSL_SSR_S2 |\ + CSU_CSL_SUR_S2) +void imx_csu_init(void); + +#endif /* IMX_CSU_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_hab.h b/arm-trusted-firmware/plat/imx/common/include/imx_hab.h new file mode 100644 index 0000000..22c0742 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_hab.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef IMX_HAB_H +#define IMX_HAB_H + +#include +#include + +#define HAB_ROM_VECTOR_BASE\ + (BOOTROM_BASE + HAB_CALLBACK_OFFSET) +/* + * Section 4.5 of the High Assurance Boot Version 4 Application Programming + * Interface Reference Manual defines the ROM Vector table as coming after a 4 + * byte header + * + * A series of function pointers are enumerated at fixed addresses, which are + * described below + */ +#define HAB_ROM_VECTOR_TABLE_ENTRY (HAB_ROM_VECTOR_BASE + 0x04) +#define HAB_ROM_VECTOR_TABLE_EXIT (HAB_ROM_VECTOR_BASE + 0x08) +#define HAB_ROM_VECTOR_TABLE_CHECK_TARGET (HAB_ROM_VECTOR_BASE + 0x0C) +#define HAB_ROM_VECTOR_TABLE_AUTHENTICATE_IMAGE (HAB_ROM_VECTOR_BASE + 0x10) +#define HAB_ROM_VECTOR_TABLE_RUN_DCD (HAB_ROM_VECTOR_BASE + 0x14) +#define HAB_ROM_VECTOR_TABLE_RUN_CSF (HAB_ROM_VECTOR_BASE + 0x18) +#define HAB_ROM_VECTOR_TABLE_ASSERT (HAB_ROM_VECTOR_BASE + 0x1C) +#define HAB_ROM_VECTOR_TABLE_REPORT_EVENT (HAB_ROM_VECTOR_BASE + 0x20) +#define HAB_ROM_VECTOR_TABLE_REPORT_STATUS (HAB_ROM_VECTOR_BASE + 0x24) +#define HAB_ROM_VECTOR_TABLE_FAILSAFE (HAB_ROM_VECTOR_BASE + 0x28) + +#endif /* IMX_HAB_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h b/arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h new file mode 100644 index 0000000..d588cfd --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h @@ -0,0 +1,652 @@ +/* + * Copyright 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_IO_MUX_H +#define IMX_IO_MUX_H + +#include +#include + +/* + * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016 + * Section 8.2.7 IOMUXC Memory Map/Register Definition + */ + +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO08_OFFSET 0x0014 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09_OFFSET 0x0018 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO10_OFFSET 0x001C +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO11_OFFSET 0x0020 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO12_OFFSET 0x0024 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO13_OFFSET 0x0028 + +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO14_OFFSET 0x002C +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO14_ALT1_SD3_CD_B BIT(0) + +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO15_OFFSET 0x0030 + +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA00_OFFSET 0x0034 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA01_OFFSET 0x0038 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA02_OFFSET 0x003C +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA03_OFFSET 0x0040 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA04_OFFSET 0x0044 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA05_OFFSET 0x0048 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA06_OFFSET 0x004C +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA07_OFFSET 0x0050 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA08_OFFSET 0x0054 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA09_OFFSET 0x0058 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA10_OFFSET 0x005C +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA11_OFFSET 0x0060 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA12_OFFSET 0x0064 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA13_OFFSET 0x0068 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA14_OFFSET 0x006C +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA15_OFFSET 0x0070 + +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCLK_OFFSET 0x0074 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDLE_OFFSET 0x0078 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDOE_OFFSET 0x007C +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDSHR_OFFSET 0x0080 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCE0_OFFSET 0x0084 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCE1_OFFSET 0x0088 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCE2_OFFSET 0x008C +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCE3_OFFSET 0x0090 + +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_GDCLK_OFFSET 0x0094 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_GDOE_OFFSET 0x0098 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_GDRL_OFFSET 0x009C +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_GDSP_OFFSET 0x00A0 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_BDR0_OFFSET 0x00A4 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_BDR1_OFFSET 0x00A8 +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_PWR_COM_OFFSET 0x00AC +#define IOMUXC_SW_MUX_CTL_PAD_EPDC_PWR_STAT_OFFSET 0x00B0 + +#define IOMUXC_SW_MUX_CTL_PAD_LCD_CLK_OFFSET 0x00B4 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_ENABLE_OFFSET 0x00B8 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_HSYNC_OFFSET 0x00BC +#define IOMUXC_SW_MUX_CTL_PAD_LCD_VSYNC_OFFSET 0x00C0 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_RESET_OFFSET 0x00C4 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA00_OFFSET 0x00C8 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA01_OFFSET 0x00CC +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA02_OFFSET 0x00D0 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA03_OFFSET 0x00D4 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA04_OFFSET 0x00D8 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA05_OFFSET 0x00DC +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA06_OFFSET 0x00E0 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA07_OFFSET 0x00E4 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA08_OFFSET 0x00E8 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA09_OFFSET 0x00EC +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA10_OFFSET 0x00F0 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA11_OFFSET 0x00F4 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA12_OFFSET 0x00F8 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA13_OFFSET 0x00FC +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA14_OFFSET 0x0100 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA15_OFFSET 0x0104 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA16_OFFSET 0x0108 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA17_OFFSET 0x010C +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA18_OFFSET 0x0110 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA19_OFFSET 0x0114 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA20_OFFSET 0x0118 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA21_OFFSET 0x011C +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA22_OFFSET 0x0120 +#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA23_OFFSET 0x0124 + +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_OFFSET 0x0128 +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT0_UART1_RX_DATA 0x00 +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT1_I2C1_SCL BIT(0) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT2_PMIC_READY BIT(1) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT3_ECSPI1_SS1 (BIT(1) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT4_ENET2_1588_EVENT0_IN BIT(3) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT5_GPIO4_IO0 (BIT(2) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT6_ENET1_MDIO (BIT(2) | BIT(1)) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_SION BIT(3) + +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_OFFSET 0x012C +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT0_UART1_TX_DATA 0x00 +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT1_I2C1_SDA BIT(0) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT2_SAI3_MCLK BIT(1) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT3_ECSPI1_SS2 (BIT(1) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT4_ENET2_1588_EVENT0_OUT BIT(3) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT5_GPIO4_IO1 (BIT(2) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT6_ENET1_MDC (BIT(2) | BIT(1)) +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_SION BIT(3) + +#define IOMUXC_SW_MUX_CTL_PAD_UART2_RX_DATA_OFFSET 0x0130 +#define IOMUXC_SW_MUX_CTL_PAD_UART2_TX_DATA_OFFSET 0x0134 +#define IOMUXC_SW_MUX_CTL_PAD_UART3_RX_DATA_OFFSET 0x0138 +#define IOMUXC_SW_MUX_CTL_PAD_UART3_TX_DATA_OFFSET 0x013C +#define IOMUXC_SW_MUX_CTL_PAD_UART3_RTS_B_OFFSET 0x0140 +#define IOMUXC_SW_MUX_CTL_PAD_UART3_CTS_B_OFFSET 0x0144 + +#define IOMUXC_SW_MUX_CTL_PAD_I2C1_SCL_OFFSET 0x0148 +#define IOMUXC_SW_MUX_CTL_PAD_I2C1_SDA_OFFSET 0x014C +#define IOMUXC_SW_MUX_CTL_PAD_I2C2_SCL_OFFSET 0x0150 +#define IOMUXC_SW_MUX_CTL_PAD_I2C2_SDA_OFFSET 0x0154 +#define IOMUXC_SW_MUX_CTL_PAD_I2C3_SCL_OFFSET 0x0158 +#define IOMUXC_SW_MUX_CTL_PAD_I2C3_SDA_OFFSET 0x015C + +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_OFFSET 0x0160 +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT0_I2C4_SCL 0x0 +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT1_UART5_RX_DATA BIT(0) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT2_WDOG4_WDOG_B BIT(1) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT3_CSI_PIXCLK (BIT(1) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT4_USB_OTG1_ID BIT(2) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT5_GPIO4_IO14 (BIT(2) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT6_EPDC_VCOM0 (BIT(2) | BIT(1)) + +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_OFFSET 0x0164 +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT0_I2C4_SDA 0x0 +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT1_UART5_TX_DATA BIT(0) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT2_WDOG4_WDOG_RST_B_DEB BIT(1) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT3_CSI_MCLK (BIT(1) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT4_USB_OTG2_ID BIT(2) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT5_GPIO4_IO15 (BIT(1) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT6_EPDC_VCOM1 (BIT(2) | BIT(1)) + +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_OFFSET 0x0168 +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT0_ECSPI1_SCLK 0x00 +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT1_UART6_RX_DATA BIT(0) +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT2_SD2_DATA4 BIT(1) +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT3_CSI_DATA2 (BIT(1) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT5_GPIO4_IO16 (BIT(2) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT6_EPDC_PWR_COM (BIT(2) | (BIT(1)) + +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_OFFSET 0x016C +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT0_ECSPI1_MOSI 0x00 +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT1_UART6_TX_DATA BIT(0) +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT2_SD2_DATA5 BIT(1) +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT3_CSI_DATA3 (BIT(1) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT5_GPIO4_IO17 (BIT(2) | BIT(0)) +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT6_EPDC_PWR_STAT (BIT(2) | (BIT(1)) + +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MISO_OFFSET 0x0170 +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SS0_OFFSET 0x0174 +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI2_SCLK_OFFSET 0x0178 +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI2_MOSI_OFFSET 0x017C +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI2_MISO_OFFSET 0x0180 +#define IOMUXC_SW_MUX_CTL_PAD_ECSPI2_SS0_OFFSET 0x0184 + +#define IOMUXC_SW_MUX_CTL_PAD_SD1_CD_B_OFFSET 0x0188 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_WP_OFFSET 0x018C +#define IOMUXC_SW_MUX_CTL_PAD_SD1_RESET_B_OFFSET 0x0190 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_CLK_OFFSET 0x0194 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_CMD_OFFSET 0x0198 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA0_OFFSET 0x019C +#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA1_OFFSET 0x01A0 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2_OFFSET 0x01A4 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA3_OFFSET 0x01A8 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_CD_B_OFFSET 0x01AC +#define IOMUXC_SW_MUX_CTL_PAD_SD2_WP_OFFSET 0x01B0 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_RESET_B_OFFSET 0x01B4 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_CLK_OFFSET 0x01B8 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_CMD_OFFSET 0x01BC +#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA0_OFFSET 0x01C0 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA1_OFFSET 0x01C4 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA2_OFFSET 0x01C8 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA3_OFFSET 0x01CC + +#define IOMUXC_SW_MUX_CTL_PAD_SD3_CLK_OFFSET 0x01D0 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_CMD_OFFSET 0x01D4 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA0_OFFSET 0x01D8 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA1_OFFSET 0x01DC +#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA2_OFFSET 0x01E0 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA3_OFFSET 0x01E4 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA4_OFFSET 0x01E8 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA5_OFFSET 0x01EC +#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA6_OFFSET 0x01F0 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA7_OFFSET 0x01F4 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_STROBE_OFFSET 0x01F8 +#define IOMUXC_SW_MUX_CTL_PAD_SD3_RESET_B_OFFSET 0x01FC + +#define IOMUXC_SW_MUX_CTL_PAD_SAI1_RX_DATA_OFFSET 0x0200 +#define IOMUXC_SW_MUX_CTL_PAD_SAI1_TX_BCLK_OFFSET 0x0204 +#define IOMUXC_SW_MUX_CTL_PAD_SAI1_TX_SYNC_OFFSET 0x0208 +#define IOMUXC_SW_MUX_CTL_PAD_SAI1_TX_DATA_OFFSET 0x020C +#define IOMUXC_SW_MUX_CTL_PAD_SAI1_RX_SYNC_OFFSET 0x0210 +#define IOMUXC_SW_MUX_CTL_PAD_SAI1_RX_BCLK_OFFSET 0x0214 +#define IOMUXC_SW_MUX_CTL_PAD_SAI1_MCLK_OFFSET 0x0218 +#define IOMUXC_SW_MUX_CTL_PAD_SAI2_TX_SYNC_OFFSET 0x021C +#define IOMUXC_SW_MUX_CTL_PAD_SAI2_TX_BCLK_OFFSET 0x0220 +#define IOMUXC_SW_MUX_CTL_PAD_SAI2_RX_DATA_OFFSET 0x0224 +#define IOMUXC_SW_MUX_CTL_PAD_SAI2_TX_DATA_OFFSET 0x0228 + +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RD0_OFFSET 0x022C +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RD1_OFFSET 0x0230 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RD2_OFFSET 0x0234 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RD3_OFFSET 0x0238 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RX_CTL_OFFSET 0x023C +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RXC_OFFSET 0x0240 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TD0_OFFSET 0x0244 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TD1_OFFSET 0x0248 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TD2_OFFSET 0x024C +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TD3_OFFSET 0x0250 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TX_CTL_OFFSET 0x0254 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TXC_OFFSET 0x0258 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_CLK_OFFSET 0x025C +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_CLK_OFFSET 0x0260 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_CRS_OFFSET 0x0264 +#define IOMUXC_SW_MUX_CTL_PAD_ENET1_COL_OFFSET 0x0268 + +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO08_OFFSET 0x026C +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO09_OFFSET 0x0270 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO10_OFFSET 0x0274 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO11_OFFSET 0x0278 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO12_OFFSET 0x027C +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO13_OFFSET 0x0280 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO14_OFFSET 0x0284 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO15_OFFSET 0x0288 + +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_MOD_OFFSET 0x028C +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TCK_OFFSET 0x0290 +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TDI_OFFSET 0x0294 +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TDO_OFFSET 0x0298 +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TMS_OFFSET 0x029C +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TRST_B_OFFSET 0x02A0 + +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA00_OFFSET 0x02A4 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA01_OFFSET 0x02A8 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA02_OFFSET 0x02AC +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA03_OFFSET 0x02B0 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA04_OFFSET 0x02B4 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA05_OFFSET 0x02B8 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA06_OFFSET 0x02BC +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA07_OFFSET 0x02C0 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA08_OFFSET 0x02C4 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA09_OFFSET 0x02C8 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA10_OFFSET 0x02CC +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA11_OFFSET 0x02D0 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA12_OFFSET 0x02D4 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA13_OFFSET 0x02D8 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA14_OFFSET 0x02DC +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA15_OFFSET 0x02E0 + +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCLK_OFFSET 0x02E4 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDLE_OFFSET 0x02E8 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDOE_OFFSET 0x02EC +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDSHR_OFFSET 0x02F0 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCE0_OFFSET 0x02F4 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCE1_OFFSET 0x02F8 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCE2_OFFSET 0x02FC +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCE3_OFFSET 0x0300 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_GDCLK_OFFSET 0x0304 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_GDOE_OFFSET 0x0308 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_GDRL_OFFSET 0x030C +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_GDSP_OFFSET 0x0310 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_BDR0_OFFSET 0x0314 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_BDR1_OFFSET 0x0318 +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_PWR_COM_OFFSET 0x031C +#define IOMUXC_SW_PAD_CTL_PAD_EPDC_PWR_STAT_OFFSET 0x0320 + +#define IOMUXC_SW_PAD_CTL_PAD_LCD_CLK_OFFSET 0x0324 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_ENABLE_OFFSET 0x0328 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_HSYNC_OFFSET 0x032C +#define IOMUXC_SW_PAD_CTL_PAD_LCD_VSYNC_OFFSET 0x0330 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_RESET_OFFSET 0x0334 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA00_OFFSET 0x0338 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA01_OFFSET 0x033C +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA02_OFFSET 0x0340 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA03_OFFSET 0x0344 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA04_OFFSET 0x0348 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA05_OFFSET 0x034C +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA06_OFFSET 0x0350 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA07_OFFSET 0x0354 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA08_OFFSET 0x0358 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA09_OFFSET 0x035C +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA10_OFFSET 0x0360 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA11_OFFSET 0x0364 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA12_OFFSET 0x0368 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA13_OFFSET 0x036C +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA14_OFFSET 0x0370 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA15_OFFSET 0x0374 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA16_OFFSET 0x0378 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA17_OFFSET 0x037C +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA18_OFFSET 0x0380 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA19_OFFSET 0x0384 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA20_OFFSET 0x0388 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA21_OFFSET 0x038C +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA22_OFFSET 0x0390 +#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA23_OFFSET 0x0394 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_OFFSET 0x0398 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_0_X1 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_1_X4 BIT(0) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_2_X2 BIT(1) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_3_X6 (BIT(1) | BIT(0)) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_SRE_FAST 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_SRE_SLOW BIT(2) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_HYS_DIS 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_HYS_EN BIT(3) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PE_DIS 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PE_EN BIT(4) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_0_100K_PD 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_1_5K_PU BIT(5) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_2_47K_PU BIT(6) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_3_100K_PU (BIT(6) | BIT(5)) + +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_OFFSET 0x039C +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_0_X1 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_1_X4 BIT(0) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_2_X2 BIT(1) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_3_X6 (BIT(1) | BIT(0)) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_SRE_FAST 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_SRE_SLOW BIT(2) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_HYS_DIS 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_HYS_EN BIT(3) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PE_DIS 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PE_EN BIT(4) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_0_100K_PD 0 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_1_5K_PU BIT(5) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_2_47K_PU BIT(6) +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_3_100K_PU (BIT(6) | BIT(5)) + +#define IOMUXC_SW_PAD_CTL_PAD_UART2_RX_DATA_OFFSET 0x03A0 +#define IOMUXC_SW_PAD_CTL_PAD_UART2_TX_DATA_OFFSET 0x03A4 +#define IOMUXC_SW_PAD_CTL_PAD_UART3_RX_DATA_OFFSET 0x03A8 +#define IOMUXC_SW_PAD_CTL_PAD_UART3_TX_DATA_OFFSET 0x03AC +#define IOMUXC_SW_PAD_CTL_PAD_UART3_RTS_B_OFFSET 0x03B0 +#define IOMUXC_SW_PAD_CTL_PAD_UART3_CTS_B_OFFSET 0x03B4 + +#define IOMUXC_SW_PAD_CTL_PAD_I2C1_SCL_OFFSET 0x03B8 +#define IOMUXC_SW_PAD_CTL_PAD_I2C1_SDA_OFFSET 0x03BC +#define IOMUXC_SW_PAD_CTL_PAD_I2C2_SCL_OFFSET 0x03C0 +#define IOMUXC_SW_PAD_CTL_PAD_I2C2_SDA_OFFSET 0x03C4 +#define IOMUXC_SW_PAD_CTL_PAD_I2C3_SCL_OFFSET 0x03C8 +#define IOMUXC_SW_PAD_CTL_PAD_I2C3_SDA_OFFSET 0x03CC +#define IOMUXC_SW_PAD_CTL_PAD_I2C4_SCL_OFFSET 0x03D0 +#define IOMUXC_SW_PAD_CTL_PAD_I2C4_SDA_OFFSET 0x03D4 + +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_OFFSET 0x03D8 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_0_X1 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_1_X4 BIT(0) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_2_X2 BIT(1) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_3_X6 (BIT(1) | BIT(0)) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_SRE_FAST 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_SRE_SLOW BIT(2) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_HYS_DIS 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_HYS_EN BIT(3) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PE_DIS 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PE_EN BIT(4) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_0_100K_PD 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_1_5K_PU BIT(5) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_2_47K_PU BIT(6) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_3_100K_PU (BIT(6) | BIT(5)) + +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_OFFSET 0x03DC +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_0_X1 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_1_X4 BIT(0) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_2_X2 BIT(1) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_3_X6 (BIT(1) | BIT(0)) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_SRE_FAST 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_SRE_SLOW BIT(2) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_HYS_DIS 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_HYS_EN BIT(3) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PE_DIS 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PE_EN BIT(4) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_0_100K_PD 0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_1_5K_PU BIT(5) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_2_47K_PU BIT(6) +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_3_100K_PU (BIT(6) | BIT(5)) + +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MISO_OFFSET 0x03E0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SS0_OFFSET 0x03E4 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI2_SCLK_OFFSET 0x03E8 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI2_MOSI_OFFSET 0x03EC +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI2_MISO_OFFSET 0x03F0 +#define IOMUXC_SW_PAD_CTL_PAD_ECSPI2_SS0_OFFSET 0x03F4 + +#define IOMUXC_SW_PAD_CTL_PAD_SD1_CD_B_OFFSET 0x03F8 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_WP_OFFSET 0x03FC +#define IOMUXC_SW_PAD_CTL_PAD_SD1_RESET_B_OFFSET 0x0400 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_CLK_OFFSET 0x0404 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_CMD_OFFSET 0x0408 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA0_OFFSET 0x040C +#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA1_OFFSET 0x0410 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2_OFFSET 0x0414 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA3_OFFSET 0x0418 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_CD_B_OFFSET 0x041C +#define IOMUXC_SW_PAD_CTL_PAD_SD2_WP_OFFSET 0x0420 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_RESET_B_OFFSET 0x0424 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_CLK_OFFSET 0x0428 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_CMD_OFFSET 0x042C +#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA0_OFFSET 0x0430 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA1_OFFSET 0x0434 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA2_OFFSET 0x0438 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA3_OFFSET 0x043C + +#define IOMUXC_SW_PAD_CTL_PAD_SD3_CLK_OFFSET 0x0440 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_CMD_OFFSET 0x0444 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA0_OFFSET 0x0448 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA1_OFFSET 0x044C +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA2_OFFSET 0x0450 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA3_OFFSET 0x0454 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA4_OFFSET 0x0458 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA5_OFFSET 0x045C +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA6_OFFSET 0x0460 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA7_OFFSET 0x0464 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_STROBE_OFFSET 0x0468 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_RESET_B_OFFSET 0x046C +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_0_X1 0 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_1_X4 BIT(0) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_2_X2 BIT(1) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_3_X6 (BIT(1) | BIT(0)) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_1_X4 BIT(0) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_SLEW_SLOW BIT(2) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_SLEW_FAST 0 +#define IOMUXC_SW_PAD_CTL_PAD_SD3_HYS BIT(3) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_PE BIT(4) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_PD_100K (0 << 5) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_PU_5K (1 << 5) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_PU_47K (2 << 5) +#define IOMUXC_SW_PAD_CTL_PAD_SD3_PU_100K (3 << 5) + +#define IOMUXC_SW_PAD_CTL_PAD_SAI1_RX_DATA_OFFSET 0x0470 +#define IOMUXC_SW_PAD_CTL_PAD_SAI1_TX_BCLK_OFFSET 0x0474 +#define IOMUXC_SW_PAD_CTL_PAD_SAI1_TX_SYNC_OFFSET 0x0478 +#define IOMUXC_SW_PAD_CTL_PAD_SAI1_TX_DATA_OFFSET 0x047C +#define IOMUXC_SW_PAD_CTL_PAD_SAI1_RX_SYNC_OFFSET 0x0480 +#define IOMUXC_SW_PAD_CTL_PAD_SAI1_RX_BCLK_OFFSET 0x0484 +#define IOMUXC_SW_PAD_CTL_PAD_SAI1_MCLK_OFFSET 0x0488 +#define IOMUXC_SW_PAD_CTL_PAD_SAI2_TX_SYNC_OFFSET 0x048C +#define IOMUXC_SW_PAD_CTL_PAD_SAI2_TX_BCLK_OFFSET 0x0490 +#define IOMUXC_SW_PAD_CTL_PAD_SAI2_RX_DATA_OFFSET 0x0494 +#define IOMUXC_SW_PAD_CTL_PAD_SAI2_TX_DATA_OFFSET 0x0498 + +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RD0_OFFSET 0x049C +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RD1_OFFSET 0x04A0 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RD2_OFFSET 0x04A4 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RD3_OFFSET 0x04A8 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RX_CTL_OFFSET 0x04AC +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RXC_OFFSET 0x04B0 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TD0_OFFSET 0x04B4 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TD1_OFFSET 0x04B8 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TD2_OFFSET 0x04BC +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TD3_OFFSET 0x04C0 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TX_CTL_OFFSET 0x04C4 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TXC_OFFSET 0x04C8 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_CLK_OFFSET 0x04CC +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_CLK_OFFSET 0x04D0 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_CRS_OFFSET 0x04D4 +#define IOMUXC_SW_PAD_CTL_PAD_ENET1_COL_OFFSET 0x04D8 + +#define IOMUXC_FLEXCAN1_RX_SELECT_INPUT_OFFSET 0x04DC +#define IOMUXC_FLEXCAN2_RX_SELECT_INPUT_OFFSET 0x04E0 + +#define IOMUXC_CCM_EXT_CLK_1_SELECT_INPUT_OFFSET 0x04E4 +#define IOMUXC_CCM_EXT_CLK_2_SELECT_INPUT_OFFSET 0x04E8 +#define IOMUXC_CCM_EXT_CLK_3_SELECT_INPUT_OFFSET 0x04EC +#define IOMUXC_CCM_EXT_CLK_4_SELECT_INPUT_OFFSET 0x04F0 + +#define IOMUXC_CCM_PMIC_READY_SELECT_INPUT_OFFSET 0x04F4 + +#define IOMUXC_CSI_DATA2_SELECT_INPUT_OFFSET 0x04F8 +#define IOMUXC_CSI_DATA3_SELECT_INPUT_OFFSET 0x04FC +#define IOMUXC_CSI_DATA4_SELECT_INPUT_OFFSET 0x0500 +#define IOMUXC_CSI_DATA5_SELECT_INPUT_OFFSET 0x0504 +#define IOMUXC_CSI_DATA6_SELECT_INPUT_OFFSET 0x0508 +#define IOMUXC_CSI_DATA7_SELECT_INPUT_OFFSET 0x050C +#define IOMUXC_CSI_DATA8_SELECT_INPUT_OFFSET 0x0510 +#define IOMUXC_CSI_DATA9_SELECT_INPUT_OFFSET 0x0514 +#define IOMUXC_CSI_HSYNC_SELECT_INPUT_OFFSET 0x0518 +#define IOMUXC_CSI_PIXCLK_SELECT_INPUT_OFFSET 0x051C +#define IOMUXC_CSI_VSYNC_SELECT_INPUT_OFFSET 0x0520 + +#define IOMUXC_ECSPI1_SCLK_SELECT_INPUT_OFFSET 0x0524 +#define IOMUXC_ECSPI1_MISO_SELECT_INPUT_OFFSET 0x0528 +#define IOMUXC_ECSPI1_MOSI_SELECT_INPUT_OFFSET 0x052C +#define IOMUXC_ECSPI1_SS0_B_SELECT_INPUT_OFFSET 0x0530 +#define IOMUXC_ECSPI2_SCLK_SELECT_INPUT_OFFSET 0x0534 +#define IOMUXC_ECSPI2_MISO_SELECT_INPUT_OFFSET 0x0538 +#define IOMUXC_ECSPI2_MOSI_SELECT_INPUT_OFFSET 0x053C +#define IOMUXC_ECSPI2_SS0_B_SELECT_INPUT_OFFSET 0x0540 +#define IOMUXC_ECSPI3_SCLK_SELECT_INPUT_OFFSET 0x0544 +#define IOMUXC_ECSPI3_MISO_SELECT_INPUT_OFFSET 0x0548 +#define IOMUXC_ECSPI3_MOSI_SELECT_INPUT_OFFSET 0x054C +#define IOMUXC_ECSPI3_SS0_B_SELECT_INPUT_OFFSET 0x0550 +#define IOMUXC_ECSPI4_SCLK_SELECT_INPUT_OFFSET 0x0554 +#define IOMUXC_ECSPI4_MISO_SELECT_INPUT_OFFSET 0x0558 +#define IOMUXC_ECSPI4_MOSI_SELECT_INPUT_OFFSET 0x055C +#define IOMUXC_ECSPI4_SS0_B_SELECT_INPUT_OFFSET 0x0560 + +#define IOMUXC_CCM_ENET1_REF_CLK_SELECT_INPUT_OFFSET 0x0564 +#define IOMUXC_ENET1_MDIO_SELECT_INPUT_OFFSET 0x0568 +#define IOMUXC_ENET1_RX_CLK_SELECT_INPUT_OFFSET 0x056C +#define IOMUXC_CCM_ENET2_REF_CLK_SELECT_INPUT_OFFSET 0x0570 +#define IOMUXC_ENET2_MDIO_SELECT_INPUT_OFFSET 0x0574 +#define IOMUXC_ENET2_RX_CLK_SELECT_INPUT_OFFSET 0x0578 + +#define IOMUXC_EPDC_PWR_IRQ_SELECT_INPUT_OFFSET 0x057C +#define IOMUXC_EPDC_PWR_STAT_SELECT_INPUT_OFFSET 0x0580 + +#define IOMUXC_FLEXTIMER1_CH0_SELECT_INPUT_OFFSET 0x0584 +#define IOMUXC_FLEXTIMER1_CH1_SELECT_INPUT_OFFSET 0x0588 +#define IOMUXC_FLEXTIMER1_CH2_SELECT_INPUT_OFFSET 0x058C +#define IOMUXC_FLEXTIMER1_CH3_SELECT_INPUT_OFFSET 0x0590 +#define IOMUXC_FLEXTIMER1_CH4_SELECT_INPUT_OFFSET 0x0594 +#define IOMUXC_FLEXTIMER1_CH5_SELECT_INPUT_OFFSET 0x0598 +#define IOMUXC_FLEXTIMER1_CH6_SELECT_INPUT_OFFSET 0x059C +#define IOMUXC_FLEXTIMER1_CH7_SELECT_INPUT_OFFSET 0x05A0 +#define IOMUXC_FLEXTIMER1_PHA_SELECT_INPUT_OFFSET 0x05A4 +#define IOMUXC_FLEXTIMER1_PHB_SELECT_INPUT_OFFSET 0x05A8 +#define IOMUXC_FLEXTIMER2_CH0_SELECT_INPUT_OFFSET 0x05AC +#define IOMUXC_FLEXTIMER2_CH1_SELECT_INPUT_OFFSET 0x05B0 +#define IOMUXC_FLEXTIMER2_CH2_SELECT_INPUT_OFFSET 0x05B4 +#define IOMUXC_FLEXTIMER2_CH3_SELECT_INPUT_OFFSET 0x05B8 +#define IOMUXC_FLEXTIMER2_CH4_SELECT_INPUT_OFFSET 0x05BC +#define IOMUXC_FLEXTIMER2_CH5_SELECT_INPUT_OFFSET 0x05C0 +#define IOMUXC_FLEXTIMER2_CH6_SELECT_INPUT_OFFSET 0x05C4 +#define IOMUXC_FLEXTIMER2_CH7_SELECT_INPUT_OFFSET 0x05C8 +#define IOMUXC_FLEXTIMER2_PHA_SELECT_INPUT_OFFSET 0x05CC +#define IOMUXC_FLEXTIMER2_PHB_SELECT_INPUT_OFFSET 0x05D0 + +#define IOMUXC_I2C1_SCL_SELECT_INPUT_OFFSET 0x05D4 +#define IOMUXC_I2C1_SDA_SELECT_INPUT_OFFSET 0x05D8 +#define IOMUXC_I2C2_SCL_SELECT_INPUT_OFFSET 0x05DC +#define IOMUXC_I2C2_SDA_SELECT_INPUT_OFFSET 0x05E0 +#define IOMUXC_I2C3_SCL_SELECT_INPUT_OFFSET 0x05E4 +#define IOMUXC_I2C3_SDA_SELECT_INPUT_OFFSET 0x05E8 +#define IOMUXC_I2C4_SCL_SELECT_INPUT_OFFSET 0x05EC +#define IOMUXC_I2C4_SDA_SELECT_INPUT_OFFSET 0x05F0 + +#define IOMUXC_KPP_COL0_SELECT_INPUT_OFFSET 0x05F4 +#define IOMUXC_KPP_COL1_SELECT_INPUT_OFFSET 0x05F8 +#define IOMUXC_KPP_COL2_SELECT_INPUT_OFFSET 0x05FC +#define IOMUXC_KPP_COL3_SELECT_INPUT_OFFSET 0x0600 +#define IOMUXC_KPP_COL4_SELECT_INPUT_OFFSET 0x0604 +#define IOMUXC_KPP_COL5_SELECT_INPUT_OFFSET 0x0608 +#define IOMUXC_KPP_COL6_SELECT_INPUT_OFFSET 0x060C +#define IOMUXC_KPP_COL7_SELECT_INPUT_OFFSET 0x0610 +#define IOMUXC_KPP_ROW0_SELECT_INPUT_OFFSET 0x0614 +#define IOMUXC_KPP_ROW1_SELECT_INPUT_OFFSET 0x0618 +#define IOMUXC_KPP_ROW2_SELECT_INPUT_OFFSET 0x061C +#define IOMUXC_KPP_ROW3_SELECT_INPUT_OFFSET 0x0620 +#define IOMUXC_KPP_ROW4_SELECT_INPUT_OFFSET 0x0624 +#define IOMUXC_KPP_ROW5_SELECT_INPUT_OFFSET 0x0628 +#define IOMUXC_KPP_ROW6_SELECT_INPUT_OFFSET 0x062C +#define IOMUXC_KPP_ROW7_SELECT_INPUT_OFFSET 0x0630 + +#define IOMUXC_LCD_BUSY_SELECT_INPUT_OFFSET 0x0634 +#define IOMUXC_LCD_DATA00_SELECT_INPUT_OFFSET 0x0638 +#define IOMUXC_LCD_DATA01_SELECT_INPUT_OFFSET 0x063C +#define IOMUXC_LCD_DATA02_SELECT_INPUT_OFFSET 0x0640 +#define IOMUXC_LCD_DATA03_SELECT_INPUT_OFFSET 0x0644 +#define IOMUXC_LCD_DATA04_SELECT_INPUT_OFFSET 0x0648 +#define IOMUXC_LCD_DATA05_SELECT_INPUT_OFFSET 0x064C +#define IOMUXC_LCD_DATA06_SELECT_INPUT_OFFSET 0x0650 +#define IOMUXC_LCD_DATA07_SELECT_INPUT_OFFSET 0x0654 +#define IOMUXC_LCD_DATA08_SELECT_INPUT_OFFSET 0x0658 +#define IOMUXC_LCD_DATA09_SELECT_INPUT_OFFSET 0x065C +#define IOMUXC_LCD_DATA10_SELECT_INPUT_OFFSET 0x0660 +#define IOMUXC_LCD_DATA11_SELECT_INPUT_OFFSET 0x0664 +#define IOMUXC_LCD_DATA12_SELECT_INPUT_OFFSET 0x0668 +#define IOMUXC_LCD_DATA13_SELECT_INPUT_OFFSET 0x066C +#define IOMUXC_LCD_DATA14_SELECT_INPUT_OFFSET 0x0670 +#define IOMUXC_LCD_DATA15_SELECT_INPUT_OFFSET 0x0674 +#define IOMUXC_LCD_DATA16_SELECT_INPUT_OFFSET 0x0678 +#define IOMUXC_LCD_DATA17_SELECT_INPUT_OFFSET 0x067C +#define IOMUXC_LCD_DATA18_SELECT_INPUT_OFFSET 0x0680 +#define IOMUXC_LCD_DATA19_SELECT_INPUT_OFFSET 0x0684 +#define IOMUXC_LCD_DATA20_SELECT_INPUT_OFFSET 0x0688 +#define IOMUXC_LCD_DATA21_SELECT_INPUT_OFFSET 0x068C +#define IOMUXC_LCD_DATA22_SELECT_INPUT_OFFSET 0x0690 +#define IOMUXC_LCD_DATA23_SELECT_INPUT_OFFSET 0x0694 +#define IOMUXC_LCD_VSYNC_SELECT_INPUT_OFFSET 0x0698 + +#define IOMUXC_SAI1_RX_BCLK_SELECT_INPUT_OFFSET 0x069C +#define IOMUXC_SAI1_RX_DATA_SELECT_INPUT_OFFSET 0x06A0 +#define IOMUXC_SAI1_RX_SYNC_SELECT_INPUT_OFFSET 0x06A4 +#define IOMUXC_SAI1_TX_BCLK_SELECT_INPUT_OFFSET 0x06A8 +#define IOMUXC_SAI1_TX_SYNC_SELECT_INPUT_OFFSET 0x06AC +#define IOMUXC_SAI2_RX_BCLK_SELECT_INPUT_OFFSET 0x06B0 +#define IOMUXC_SAI2_RX_DATA_SELECT_INPUT_OFFSET 0x06B4 +#define IOMUXC_SAI2_RX_SYNC_SELECT_INPUT_OFFSET 0x06B8 +#define IOMUXC_SAI2_TX_BCLK_SELECT_INPUT_OFFSET 0x06BC +#define IOMUXC_SAI2_TX_SYNC_SELECT_INPUT_OFFSET 0x06C0 +#define IOMUXC_SAI3_RX_BCLK_SELECT_INPUT_OFFSET 0x06C4 +#define IOMUXC_SAI3_RX_DATA_SELECT_INPUT_OFFSET 0x06C8 +#define IOMUXC_SAI3_RX_SYNC_SELECT_INPUT_OFFSET 0x06CC +#define IOMUXC_SAI3_TX_BCLK_SELECT_INPUT_OFFSET 0x06D0 +#define IOMUXC_SAI3_TX_SYNC_SELECT_INPUT_OFFSET 0x06D4 +#define IOMUXC_SDMA_EVENTS0_SELECT_INPUT_OFFSET 0x06D8 +#define IOMUXC_SDMA_EVENTS1_SELECT_INPUT_OFFSET 0x06DC + +#define IOMUXC_SIM1_PORT1_PD_SELECT_INPUT_OFFSET 0x06E0 +#define IOMUXC_SIM1_PORT1_TRXD_SELECT_INPUT_OFFSET 0x06E4 +#define IOMUXC_SIM2_PORT1_PD_SELECT_INPUT_OFFSET 0x06E8 +#define IOMUXC_SIM2_PORT1_TRXD_SELECT_INPUT_OFFSET 0x06EC + +#define IOMUXC_UART1_RTS_B_SELECT_INPUT_OFFSET 0x06F0 +#define IOMUXC_UART1_RX_DATA_SELECT_INPUT_OFFSET 0x06F4 +#define IOMUXC_UART2_RTS_B_SELECT_INPUT_OFFSET 0x06F8 +#define IOMUXC_UART2_RX_DATA_SELECT_INPUT_OFFSET 0x06FC +#define IOMUXC_UART3_RTS_B_SELECT_INPUT_OFFSET 0x0700 +#define IOMUXC_UART3_RX_DATA_SELECT_INPUT_OFFSET 0x0704 +#define IOMUXC_UART4_RTS_B_SELECT_INPUT_OFFSET 0x0708 +#define IOMUXC_UART4_RX_DATA_SELECT_INPUT_OFFSET 0x070C +#define IOMUXC_UART5_RTS_B_SELECT_INPUT_OFFSET 0x0710 + +#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_OFFSET 0x0714 +#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_I2C4_SCL_ALT1 0x00 +#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_I2C4_SDA_ALT1 BIT(0) +#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_SAI1_RX_DATA_ALT2 BIT(1) +#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_SAI1_TX_BCLK_ALT2 (BIT(1) | BIT(0)) +#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_GPIO1_IO06_ALT3 BIT(2) +#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_GPIO1_IO07_ALT3 (BIT(2) | BIT(1)) + +#define IOMUXC_UART6_RTS_B_SELECT_INPUT_OFFSET 0x0718 +#define IOMUXC_UART6_RX_DATA_SELECT_INPUT_OFFSET 0x071C +#define IOMUXC_UART7_RTS_B_SELECT_INPUT_OFFSET 0x0720 +#define IOMUXC_UART7_RX_DATA_SELECT_INPUT_OFFSET 0x0724 + +#define IOMUXC_USB_OTG2_OC_SELECT_INPUT_OFFSET 0x0728 +#define IOMUXC_USB_OTG1_OC_SELECT_INPUT_OFFSET 0x072C +#define IOMUXC_USB_OTG2_ID_SELECT_INPUT_OFFSET 0x0730 +#define IOMUXC_USB_OTG1_ID_SELECT_INPUT_OFFSET 0x0734 +#define IOMUXC_SD3_CD_B_SELECT_INPUT_OFFSET 0x0738 +#define IOMUXC_SD3_WP_SELECT_INPUT_OFFSET 0x073C + +/* Pad mux/feature set routines */ + +void imx_io_muxc_set_pad_alt_function(uint32_t pad_mux_offset, uint32_t alt_function); +void imx_io_muxc_set_pad_features(uint32_t pad_feature_offset, uint32_t pad_features); + +#endif /* IMX_IO_MUX_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h b/arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h new file mode 100644 index 0000000..6c7a760 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IMX_SIP_SVC_H__ +#define __IMX_SIP_SVC_H__ + +/* SMC function IDs for SiP Service queries */ +#define IMX_SIP_CPUFREQ 0xC2000001 +#define IMX_SIP_SET_CPUFREQ 0x00 + +#define IMX_SIP_SRTC 0xC2000002 +#define IMX_SIP_SRTC_SET_TIME 0x00 + +#define IMX_SIP_BUILDINFO 0xC2000003 +#define IMX_SIP_BUILDINFO_GET_COMMITHASH 0x00 + +#define IMX_SIP_SRC 0xC2000005 +#define IMX_SIP_SRC_SET_SECONDARY_BOOT 0x10 +#define IMX_SIP_SRC_IS_SECONDARY_BOOT 0x11 + +#define IMX_SIP_GET_SOC_INFO 0xC2000006 + +#define IMX_SIP_WAKEUP_SRC 0xC2000009 +#define IMX_SIP_WAKEUP_SRC_SCU 0x1 +#define IMX_SIP_WAKEUP_SRC_IRQSTEER 0x2 + +#define IMX_SIP_OTP_READ 0xC200000A +#define IMX_SIP_OTP_WRITE 0xC200000B + +#define IMX_SIP_MISC_SET_TEMP 0xC200000C + +#define IMX_SIP_AARCH32 0xC20000FD + +int imx_kernel_entry_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4); +#if defined(PLAT_imx8mq) +int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3); +#endif + +#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq) +int imx_src_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, void *handle); +#endif + +#if (defined(PLAT_imx8qm) || defined(PLAT_imx8qx)) +int imx_cpufreq_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3); +int imx_srtc_handler(uint32_t smc_fid, void *handle, u_register_t x1, + u_register_t x2, u_register_t x3, u_register_t x4); +int imx_wakeup_src_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3); +int imx_otp_handler(uint32_t smc_fid, void *handle, + u_register_t x1, u_register_t x2); +int imx_misc_set_temp_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4); +#endif +uint64_t imx_buildinfo_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4); + +#endif /* __IMX_SIP_SVC_H__ */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_snvs.h b/arm-trusted-firmware/plat/imx/common/include/imx_snvs.h new file mode 100644 index 0000000..565c451 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_snvs.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef IMX_SNVS_H +#define IMX_SNVS_H + +#include +#include + +#include + +struct snvs { + uint32_t hplr; + uint32_t hpcomr; + uint32_t hpcr; + uint32_t hpsicr; + uint32_t hpsvcr; + uint32_t hpsr; + uint32_t hpsvsr; + uint32_t hphacivr; + uint32_t hphacr; + uint32_t hprtcmr; + uint32_t hprtclr; + uint32_t hptamr; + uint32_t hptalr; + uint32_t lplr; + uint32_t lpcr; + uint32_t lpmkcr; + uint32_t lpsvcr; + uint32_t lptgfcr; + uint32_t lptdcr; + uint32_t lpsr; + uint32_t lpsrtcmr; + uint32_t lpsrtclr; + uint32_t lptar; + uint32_t lpsmcmr; + uint32_t lpsmclr; + uint32_t lppgdr; + uint32_t lpgpr0_alias; + uint8_t lpzmkr[32]; + uint16_t res0; + uint32_t lpgpr0[4]; + uint32_t lptdc2r; + uint32_t lptdsr; + uint32_t lptgf1cr; + uint32_t lptgf2cr; + uint32_t res1[4]; + uint32_t lpat1cr; + uint32_t lpat2cr; + uint32_t lpat3cr; + uint32_t lpat4cr; + uint32_t lpat5cr; + uint32_t res2[3]; + uint32_t lpatctlr; + uint32_t lpatclkr; + uint32_t lpatrc1r; + uint32_t lpatrc2r; + uint32_t res3[706]; + uint32_t hpvidr1; + uint32_t hpvidr2; +} __packed; + +/* Define the HPCOMR bits */ +#define HPCOMR_NPSWA_EN BIT(31) +#define HPCOMR_HAC_STOP BIT(19) +#define HPCOMR_HAC_CLEAR BIT(18) +#define HPCOMR_HAC_LOAD BIT(17) +#define HPCOMR_HAC_EN BIT(16) +#define HPCOMR_MKS_EN BIT(13) +#define HPCOMR_PROG_ZMK BIT(12) +#define HPCOMR_SW_LPSV BIT(10) +#define HPCOMR_SW_FSV BIT(9) +#define HPCOMR_SW_SV BIT(8) +#define HPCOMR_LP_SWR_DIS BIT(5) +#define HPCOMR_LP_SWR BIT(4) +#define HPCOMR_SSM_SFNS_DIS BIT(2) +#define HPCOMR_SSM_ST_DIS BIT(1) +#define HPCOMR_SSM_ST BIT(0) + +void imx_snvs_init(void); + +#endif /* IMX_SNVS_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_uart.h b/arm-trusted-firmware/plat/imx/common/include/imx_uart.h new file mode 100644 index 0000000..6c4d62f --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_uart.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_UART_H +#define IMX_UART_H + +#include + +#ifndef __ASSEMBLER__ + +int console_imx_uart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); +#endif /*__ASSEMBLER__*/ + +#endif /* IMX_UART_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/imx_wdog.h b/arm-trusted-firmware/plat/imx/common/include/imx_wdog.h new file mode 100644 index 0000000..75a729a --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_wdog.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_WDOG_H +#define IMX_WDOG_H + +#include + +#include + +struct wdog_regs { + uint16_t wcr; + uint16_t wsr; + uint16_t wrsr; + uint16_t wicr; + uint16_t wmcr; +}; + +/* WCR bits */ +#define WCR_WDZST BIT(0) +#define WCR_WDBG BIT(1) +#define WCR_WDE BIT(2) +#define WCR_WDT BIT(3) +#define WCR_SRS BIT(4) +#define WCR_WDA BIT(5) +#define WCR_SRE BIT(6) +#define WCR_WDW BIT(7) +#define WCR_WT(x) ((x) << 8) + +/* WSR bits */ +#define WSR_FIRST 0x5555 +#define WSR_SECOND 0xAAAA + +/* WRSR bits */ +#define WRSR_SFTW BIT(0) +#define WRSR_TOUT BIT(1) +#define WRSR_POR BIT(4) + +/* WICR bits */ +static inline int wicr_calc_wict(int sec, int half_sec) +{ + int wict_bits; + + /* Represents WICR bits 7 - 0 */ + wict_bits = ((sec << 1) | (half_sec ? 1 : 0)); + + return wict_bits; +} + +#define WICR_WTIS BIT(14) +#define WICR_WIE BIT(15) + +/* WMCR bits */ +#define WMCR_PDE BIT(0) + +/* External facing API */ +void imx_wdog_init(void); + +#endif /* IMX_WDOG_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/plat_imx8.h b/arm-trusted-firmware/plat/imx/common/include/plat_imx8.h new file mode 100644 index 0000000..be99b97 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/plat_imx8.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_IMX8_H +#define PLAT_IMX8_H + +#include +#include + +struct plat_gic_ctx { + gicv3_redist_ctx_t rdist_ctx[PLATFORM_CORE_COUNT]; + gicv3_dist_ctx_t dist_ctx; +}; + +unsigned int plat_calc_core_pos(uint64_t mpidr); +void imx_mailbox_init(uintptr_t base_addr); +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); + +void __dead2 imx_system_off(void); +void __dead2 imx_system_reset(void); +int imx_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state); +void imx_get_sys_suspend_power_state(psci_power_state_t *req_state); +bool imx_is_wakeup_src_irqsteer(void); +void plat_gic_save(unsigned int proc_num, struct plat_gic_ctx *ctx); +void plat_gic_restore(unsigned int proc_num, struct plat_gic_ctx *ctx); + +#endif /* PLAT_IMX8_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/plat_macros.S b/arm-trusted-firmware/plat/imx/common/include/plat_macros.S new file mode 100644 index 0000000..30cce0a --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/plat_macros.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * the below macros print out relevant GIC + * registers whenever an unhandled exception is + * taken in BL3-1 + */ +.macro plat_print_gic_regs + /* TODO */ +.endm + +/* + * the below macros print out relevant interconnect + * registers whenever an unhandled exception is + * taken in BL3-1 + */ +.macro plat_print_interconnect_regs + /* TODO */ +.endm + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + /* TODO */ +.endm diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/sci.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci.h new file mode 100644 index 0000000..2c45bb8 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/sci.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCI_H +#define SCI_H + +/* Defines */ + +/* Includes */ + +#include +#include +#include +#include +#include +#include + +#endif /* SCI_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h new file mode 100644 index 0000000..39e9012 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the IPC implementation. + */ + +#ifndef SCI_IPC_H +#define SCI_IPC_H + +/* Includes */ + +#include + +/* Defines */ + +/* Types */ + +/* Functions */ + +/*! + * This function opens an IPC channel. + * + * @param[out] ipc return pointer for ipc handle + * @param[in] id id of channel to open + * + * @return Returns an error code (SC_ERR_NONE = success, SC_ERR_IPC + * otherwise). + * + * The \a id parameter is implementation specific. Could be an MU + * address, pointer to a driver path, channel index, etc. + */ +sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id); + +/*! + * This function closes an IPC channel. + * + * @param[in] ipc id of channel to close + */ +void sc_ipc_close(sc_ipc_t ipc); + +/*! + * This function reads a message from an IPC channel. + * + * @param[in] ipc id of channel read from + * @param[out] data pointer to message buffer to read + * + * This function will block if no message is available to be read. + */ +void sc_ipc_read(sc_ipc_t ipc, void *data); + +/*! + * This function writes a message to an IPC channel. + * + * @param[in] ipc id of channel to write to + * @param[in] data pointer to message buffer to write + * + * This function will block if the outgoing buffer is full. + */ +void sc_ipc_write(sc_ipc_t ipc, void *data); + +extern sc_ipc_t ipc_handle; + +#endif /* SCI_IPC_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h new file mode 100644 index 0000000..60dbc27 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the RPC implementation. + */ + +#ifndef SCI_RPC_H +#define SCI_RPC_H + +/* Includes */ + +#include + +#include +#include + +/* Defines */ + +#define SC_RPC_VERSION 1U + +#define SC_RPC_MAX_MSG 8U + +#define RPC_VER(MSG) ((MSG)->version) +#define RPC_SIZE(MSG) ((MSG)->size) +#define RPC_SVC(MSG) ((MSG)->svc) +#define RPC_FUNC(MSG) ((MSG)->func) +#define RPC_R8(MSG) ((MSG)->func) +#define RPC_I32(MSG, IDX) ((MSG)->DATA.i32[(IDX) / 4U]) +#define RPC_I16(MSG, IDX) ((MSG)->DATA.i16[(IDX) / 2U]) +#define RPC_I8(MSG, IDX) ((MSG)->DATA.i8[(IDX)]) +#define RPC_U32(MSG, IDX) ((MSG)->DATA.u32[(IDX) / 4U]) +#define RPC_U16(MSG, IDX) ((MSG)->DATA.u16[(IDX) / 2U]) +#define RPC_U8(MSG, IDX) ((MSG)->DATA.u8[(IDX)]) + +#define SC_RPC_SVC_UNKNOWN 0U +#define SC_RPC_SVC_RETURN 1U +#define SC_RPC_SVC_PM 2U +#define SC_RPC_SVC_RM 3U +#define SC_RPC_SVC_TIMER 5U +#define SC_RPC_SVC_PAD 6U +#define SC_RPC_SVC_MISC 7U +#define SC_RPC_SVC_IRQ 8U +#define SC_RPC_SVC_ABORT 9U + +#define SC_RPC_ASYNC_STATE_RD_START 0U +#define SC_RPC_ASYNC_STATE_RD_ACTIVE 1U +#define SC_RPC_ASYNC_STATE_RD_DONE 2U +#define SC_RPC_ASYNC_STATE_WR_START 3U +#define SC_RPC_ASYNC_STATE_WR_ACTIVE 4U +#define SC_RPC_ASYNC_STATE_WR_DONE 5U + +#define SC_RPC_MU_GIR_SVC 0x1U +#define SC_RPC_MU_GIR_DBG 0x8U + +/* Types */ + +typedef uint8_t sc_rpc_svc_t; + +typedef struct sc_rpc_msg_s { + uint8_t version; + uint8_t size; + uint8_t svc; + uint8_t func; + union { + int32_t i32[(SC_RPC_MAX_MSG - 1U)]; + int16_t i16[(SC_RPC_MAX_MSG - 1U) * 2U]; + int8_t i8[(SC_RPC_MAX_MSG - 1U) * 4U]; + uint32_t u32[(SC_RPC_MAX_MSG - 1U)]; + uint16_t u16[(SC_RPC_MAX_MSG - 1U) * 2U]; + uint8_t u8[(SC_RPC_MAX_MSG - 1U) * 4U]; + } DATA; +} sc_rpc_msg_t; + +typedef uint8_t sc_rpc_async_state_t; + +typedef struct sc_rpc_async_msg_s { + sc_rpc_async_state_t state; + uint8_t wordIdx; + sc_rpc_msg_t msg; + uint32_t timeStamp; +} sc_rpc_async_msg_t; + +/* Functions */ + +/*! + * This is an internal function to send an RPC message over an IPC + * channel. It is called by client-side SCFW API function shims. + * + * @param[in] ipc IPC handle + * @param[in,out] msg handle to a message + * @param[in] no_resp response flag + * + * If \a no_resp is SC_FALSE then this function waits for a response + * and returns the result in \a msg. + */ +void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp); + +/*! + * This is an internal function to dispath an RPC call that has + * arrived via IPC over an MU. It is called by server-side SCFW. + * + * @param[in] mu MU message arrived on + * @param[in,out] msg handle to a message + * + * The function result is returned in \a msg. + */ +void sc_rpc_dispatch(sc_rsrc_t mu, sc_rpc_msg_t *msg); + +/*! + * This function translates an RPC message and forwards on to the + * normal RPC API. It is used only by hypervisors. + * + * @param[in] ipc IPC handle + * @param[in,out] msg handle to a message + * + * This function decodes a message, calls macros to translate the + * resources, pads, addresses, partitions, memory regions, etc. and + * then forwards on to the hypervisors SCFW API.Return results are + * translated back abd placed back into the message to be returned + * to the original API. + */ +void sc_rpc_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SCI_RPC_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h new file mode 100644 index 0000000..a169f88 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCI_SCFW_H +#define SCI_SCFW_H + +/* Includes */ + +#include + +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*! + * This type is used to declare a handle for an IPC communication + * channel. Its meaning is specific to the IPC implementation. + */ +typedef uint64_t sc_ipc_t; + +/*! + * This type is used to declare an ID for an IPC communication + * channel. For the reference IPC implementation, this ID + * selects the base address of the MU used for IPC. + */ +typedef uint64_t sc_ipc_id_t; + + +#endif /* SCI_SCFW_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h new file mode 100644 index 0000000..6ade01c --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h @@ -0,0 +1,849 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing types used across multiple service APIs. + */ + +#ifndef SCI_TYPES_H +#define SCI_TYPES_H + +/* Includes */ + +#include + +/* Defines */ + +/*! + * @name Defines for common frequencies + */ +/*@{*/ +#define SC_32KHZ 32768U /* 32KHz */ +#define SC_10MHZ 10000000U /* 10MHz */ +#define SC_20MHZ 20000000U /* 20MHz */ +#define SC_25MHZ 25000000U /* 25MHz */ +#define SC_27MHZ 27000000U /* 27MHz */ +#define SC_40MHZ 40000000U /* 40MHz */ +#define SC_45MHZ 45000000U /* 45MHz */ +#define SC_50MHZ 50000000U /* 50MHz */ +#define SC_60MHZ 60000000U /* 60MHz */ +#define SC_66MHZ 66666666U /* 66MHz */ +#define SC_74MHZ 74250000U /* 74.25MHz */ +#define SC_80MHZ 80000000U /* 80MHz */ +#define SC_83MHZ 83333333U /* 83MHz */ +#define SC_84MHZ 84375000U /* 84.37MHz */ +#define SC_100MHZ 100000000U /* 100MHz */ +#define SC_125MHZ 125000000U /* 125MHz */ +#define SC_133MHZ 133333333U /* 133MHz */ +#define SC_135MHZ 135000000U /* 135MHz */ +#define SC_150MHZ 150000000U /* 150MHz */ +#define SC_160MHZ 160000000U /* 160MHz */ +#define SC_166MHZ 166666666U /* 166MHz */ +#define SC_175MHZ 175000000U /* 175MHz */ +#define SC_180MHZ 180000000U /* 180MHz */ +#define SC_200MHZ 200000000U /* 200MHz */ +#define SC_250MHZ 250000000U /* 250MHz */ +#define SC_266MHZ 266666666U /* 266MHz */ +#define SC_300MHZ 300000000U /* 300MHz */ +#define SC_312MHZ 312500000U /* 312.5MHZ */ +#define SC_320MHZ 320000000U /* 320MHz */ +#define SC_325MHZ 325000000U /* 325MHz */ +#define SC_333MHZ 333333333U /* 333MHz */ +#define SC_350MHZ 350000000U /* 350MHz */ +#define SC_372MHZ 372000000U /* 372MHz */ +#define SC_375MHZ 375000000U /* 375MHz */ +#define SC_400MHZ 400000000U /* 400MHz */ +#define SC_500MHZ 500000000U /* 500MHz */ +#define SC_594MHZ 594000000U /* 594MHz */ +#define SC_625MHZ 625000000U /* 625MHz */ +#define SC_640MHZ 640000000U /* 640MHz */ +#define SC_650MHZ 650000000U /* 650MHz */ +#define SC_667MHZ 666666667U /* 667MHz */ +#define SC_675MHZ 675000000U /* 675MHz */ +#define SC_700MHZ 700000000U /* 700MHz */ +#define SC_720MHZ 720000000U /* 720MHz */ +#define SC_750MHZ 750000000U /* 750MHz */ +#define SC_800MHZ 800000000U /* 800MHz */ +#define SC_850MHZ 850000000U /* 850MHz */ +#define SC_900MHZ 900000000U /* 900MHz */ +#define SC_1000MHZ 1000000000U /* 1GHz */ +#define SC_1056MHZ 1056000000U /* 1.056GHz */ +#define SC_1188MHZ 1188000000U /* 1.188GHz */ +#define SC_1260MHZ 1260000000U /* 1.26GHz */ +#define SC_1280MHZ 1280000000U /* 1.28GHz */ +#define SC_1300MHZ 1300000000U /* 1.3GHz */ +#define SC_1400MHZ 1400000000U /* 1.4GHz */ +#define SC_1500MHZ 1500000000U /* 1.5GHz */ +#define SC_1600MHZ 1600000000U /* 1.6GHz */ +#define SC_1800MHZ 1800000000U /* 1.8GHz */ +#define SC_2000MHZ 2000000000U /* 2.0GHz */ +#define SC_2112MHZ 2112000000U /* 2.12GHz */ +/*@}*/ + +/*! + * @name Defines for 24M related frequencies + */ +/*@{*/ +#define SC_8MHZ 8000000U /* 8MHz */ +#define SC_12MHZ 12000000U /* 12MHz */ +#define SC_19MHZ 19800000U /* 19.8MHz */ +#define SC_24MHZ 24000000U /* 24MHz */ +#define SC_48MHZ 48000000U /* 48MHz */ +#define SC_120MHZ 120000000U /* 120MHz */ +#define SC_132MHZ 132000000U /* 132MHz */ +#define SC_144MHZ 144000000U /* 144MHz */ +#define SC_192MHZ 192000000U /* 192MHz */ +#define SC_211MHZ 211200000U /* 211.2MHz */ +#define SC_240MHZ 240000000U /* 240MHz */ +#define SC_264MHZ 264000000U /* 264MHz */ +#define SC_352MHZ 352000000U /* 352MHz */ +#define SC_360MHZ 360000000U /* 360MHz */ +#define SC_384MHZ 384000000U /* 384MHz */ +#define SC_396MHZ 396000000U /* 396MHz */ +#define SC_432MHZ 432000000U /* 432MHz */ +#define SC_480MHZ 480000000U /* 480MHz */ +#define SC_600MHZ 600000000U /* 600MHz */ +#define SC_744MHZ 744000000U /* 744MHz */ +#define SC_792MHZ 792000000U /* 792MHz */ +#define SC_864MHZ 864000000U /* 864MHz */ +#define SC_960MHZ 960000000U /* 960MHz */ +#define SC_1056MHZ 1056000000U /* 1056MHz */ +#define SC_1200MHZ 1200000000U /* 1.2GHz */ +#define SC_1464MHZ 1464000000U /* 1.464GHz */ +#define SC_2400MHZ 2400000000U /* 2.4GHz */ +/*@}*/ + +/*! + * @name Defines for A/V related frequencies + */ +/*@{*/ +#define SC_62MHZ 62937500U /* 62.9375MHz */ +#define SC_755MHZ 755250000U /* 755.25MHz */ +/*@}*/ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_FADDR_W 36U /* Width of sc_faddr_t */ +#define SC_BOOL_W 1U /* Width of sc_bool_t */ +#define SC_ERR_W 4U /* Width of sc_err_t */ +#define SC_RSRC_W 10U /* Width of sc_rsrc_t */ +#define SC_CTRL_W 6U /* Width of sc_ctrl_t */ +/*@}*/ + +/*! + * @name Defines for sc_bool_t + */ +/*@{*/ +#define SC_FALSE ((sc_bool_t) 0U) /* True */ +#define SC_TRUE ((sc_bool_t) 1U) /* False */ +/*@}*/ + +/*! + * @name Defines for sc_err_t. + */ +/*@{*/ +#define SC_ERR_NONE 0U /* Success */ +#define SC_ERR_VERSION 1U /* Incompatible API version */ +#define SC_ERR_CONFIG 2U /* Configuration error */ +#define SC_ERR_PARM 3U /* Bad parameter */ +#define SC_ERR_NOACCESS 4U /* Permission error (no access) */ +#define SC_ERR_LOCKED 5U /* Permission error (locked) */ +#define SC_ERR_UNAVAILABLE 6U /* Unavailable (out of resources) */ +#define SC_ERR_NOTFOUND 7U /* Not found */ +#define SC_ERR_NOPOWER 8U /* No power */ +#define SC_ERR_IPC 9U /* Generic IPC error */ +#define SC_ERR_BUSY 10U /* Resource is currently busy/active */ +#define SC_ERR_FAIL 11U /* General I/O failure */ +#define SC_ERR_LAST 12U +/*@}*/ + +/*! + * @name Defines for sc_rsrc_t. + */ +/*@{*/ +#define SC_R_A53 0U +#define SC_R_A53_0 1U +#define SC_R_A53_1 2U +#define SC_R_A53_2 3U +#define SC_R_A53_3 4U +#define SC_R_A72 5U +#define SC_R_A72_0 6U +#define SC_R_A72_1 7U +#define SC_R_A72_2 8U +#define SC_R_A72_3 9U +#define SC_R_CCI 10U +#define SC_R_DB 11U +#define SC_R_DRC_0 12U +#define SC_R_DRC_1 13U +#define SC_R_GIC_SMMU 14U +#define SC_R_IRQSTR_M4_0 15U +#define SC_R_IRQSTR_M4_1 16U +#define SC_R_SMMU 17U +#define SC_R_GIC 18U +#define SC_R_DC_0_BLIT0 19U +#define SC_R_DC_0_BLIT1 20U +#define SC_R_DC_0_BLIT2 21U +#define SC_R_DC_0_BLIT_OUT 22U +#define SC_R_DC_0_CAPTURE0 23U +#define SC_R_DC_0_CAPTURE1 24U +#define SC_R_DC_0_WARP 25U +#define SC_R_DC_0_INTEGRAL0 26U +#define SC_R_DC_0_INTEGRAL1 27U +#define SC_R_DC_0_VIDEO0 28U +#define SC_R_DC_0_VIDEO1 29U +#define SC_R_DC_0_FRAC0 30U +#define SC_R_DC_0_FRAC1 31U +#define SC_R_DC_0 32U +#define SC_R_GPU_2_PID0 33U +#define SC_R_DC_0_PLL_0 34U +#define SC_R_DC_0_PLL_1 35U +#define SC_R_DC_1_BLIT0 36U +#define SC_R_DC_1_BLIT1 37U +#define SC_R_DC_1_BLIT2 38U +#define SC_R_DC_1_BLIT_OUT 39U +#define SC_R_DC_1_CAPTURE0 40U +#define SC_R_DC_1_CAPTURE1 41U +#define SC_R_DC_1_WARP 42U +#define SC_R_DC_1_INTEGRAL0 43U +#define SC_R_DC_1_INTEGRAL1 44U +#define SC_R_DC_1_VIDEO0 45U +#define SC_R_DC_1_VIDEO1 46U +#define SC_R_DC_1_FRAC0 47U +#define SC_R_DC_1_FRAC1 48U +#define SC_R_DC_1 49U +#define SC_R_GPU_3_PID0 50U +#define SC_R_DC_1_PLL_0 51U +#define SC_R_DC_1_PLL_1 52U +#define SC_R_SPI_0 53U +#define SC_R_SPI_1 54U +#define SC_R_SPI_2 55U +#define SC_R_SPI_3 56U +#define SC_R_UART_0 57U +#define SC_R_UART_1 58U +#define SC_R_UART_2 59U +#define SC_R_UART_3 60U +#define SC_R_UART_4 61U +#define SC_R_EMVSIM_0 62U +#define SC_R_EMVSIM_1 63U +#define SC_R_DMA_0_CH0 64U +#define SC_R_DMA_0_CH1 65U +#define SC_R_DMA_0_CH2 66U +#define SC_R_DMA_0_CH3 67U +#define SC_R_DMA_0_CH4 68U +#define SC_R_DMA_0_CH5 69U +#define SC_R_DMA_0_CH6 70U +#define SC_R_DMA_0_CH7 71U +#define SC_R_DMA_0_CH8 72U +#define SC_R_DMA_0_CH9 73U +#define SC_R_DMA_0_CH10 74U +#define SC_R_DMA_0_CH11 75U +#define SC_R_DMA_0_CH12 76U +#define SC_R_DMA_0_CH13 77U +#define SC_R_DMA_0_CH14 78U +#define SC_R_DMA_0_CH15 79U +#define SC_R_DMA_0_CH16 80U +#define SC_R_DMA_0_CH17 81U +#define SC_R_DMA_0_CH18 82U +#define SC_R_DMA_0_CH19 83U +#define SC_R_DMA_0_CH20 84U +#define SC_R_DMA_0_CH21 85U +#define SC_R_DMA_0_CH22 86U +#define SC_R_DMA_0_CH23 87U +#define SC_R_DMA_0_CH24 88U +#define SC_R_DMA_0_CH25 89U +#define SC_R_DMA_0_CH26 90U +#define SC_R_DMA_0_CH27 91U +#define SC_R_DMA_0_CH28 92U +#define SC_R_DMA_0_CH29 93U +#define SC_R_DMA_0_CH30 94U +#define SC_R_DMA_0_CH31 95U +#define SC_R_I2C_0 96U +#define SC_R_I2C_1 97U +#define SC_R_I2C_2 98U +#define SC_R_I2C_3 99U +#define SC_R_I2C_4 100U +#define SC_R_ADC_0 101U +#define SC_R_ADC_1 102U +#define SC_R_FTM_0 103U +#define SC_R_FTM_1 104U +#define SC_R_CAN_0 105U +#define SC_R_CAN_1 106U +#define SC_R_CAN_2 107U +#define SC_R_DMA_1_CH0 108U +#define SC_R_DMA_1_CH1 109U +#define SC_R_DMA_1_CH2 110U +#define SC_R_DMA_1_CH3 111U +#define SC_R_DMA_1_CH4 112U +#define SC_R_DMA_1_CH5 113U +#define SC_R_DMA_1_CH6 114U +#define SC_R_DMA_1_CH7 115U +#define SC_R_DMA_1_CH8 116U +#define SC_R_DMA_1_CH9 117U +#define SC_R_DMA_1_CH10 118U +#define SC_R_DMA_1_CH11 119U +#define SC_R_DMA_1_CH12 120U +#define SC_R_DMA_1_CH13 121U +#define SC_R_DMA_1_CH14 122U +#define SC_R_DMA_1_CH15 123U +#define SC_R_DMA_1_CH16 124U +#define SC_R_DMA_1_CH17 125U +#define SC_R_DMA_1_CH18 126U +#define SC_R_DMA_1_CH19 127U +#define SC_R_DMA_1_CH20 128U +#define SC_R_DMA_1_CH21 129U +#define SC_R_DMA_1_CH22 130U +#define SC_R_DMA_1_CH23 131U +#define SC_R_DMA_1_CH24 132U +#define SC_R_DMA_1_CH25 133U +#define SC_R_DMA_1_CH26 134U +#define SC_R_DMA_1_CH27 135U +#define SC_R_DMA_1_CH28 136U +#define SC_R_DMA_1_CH29 137U +#define SC_R_DMA_1_CH30 138U +#define SC_R_DMA_1_CH31 139U +#define SC_R_UNUSED1 140U +#define SC_R_UNUSED2 141U +#define SC_R_UNUSED3 142U +#define SC_R_UNUSED4 143U +#define SC_R_GPU_0_PID0 144U +#define SC_R_GPU_0_PID1 145U +#define SC_R_GPU_0_PID2 146U +#define SC_R_GPU_0_PID3 147U +#define SC_R_GPU_1_PID0 148U +#define SC_R_GPU_1_PID1 149U +#define SC_R_GPU_1_PID2 150U +#define SC_R_GPU_1_PID3 151U +#define SC_R_PCIE_A 152U +#define SC_R_SERDES_0 153U +#define SC_R_MATCH_0 154U +#define SC_R_MATCH_1 155U +#define SC_R_MATCH_2 156U +#define SC_R_MATCH_3 157U +#define SC_R_MATCH_4 158U +#define SC_R_MATCH_5 159U +#define SC_R_MATCH_6 160U +#define SC_R_MATCH_7 161U +#define SC_R_MATCH_8 162U +#define SC_R_MATCH_9 163U +#define SC_R_MATCH_10 164U +#define SC_R_MATCH_11 165U +#define SC_R_MATCH_12 166U +#define SC_R_MATCH_13 167U +#define SC_R_MATCH_14 168U +#define SC_R_PCIE_B 169U +#define SC_R_SATA_0 170U +#define SC_R_SERDES_1 171U +#define SC_R_HSIO_GPIO 172U +#define SC_R_MATCH_15 173U +#define SC_R_MATCH_16 174U +#define SC_R_MATCH_17 175U +#define SC_R_MATCH_18 176U +#define SC_R_MATCH_19 177U +#define SC_R_MATCH_20 178U +#define SC_R_MATCH_21 179U +#define SC_R_MATCH_22 180U +#define SC_R_MATCH_23 181U +#define SC_R_MATCH_24 182U +#define SC_R_MATCH_25 183U +#define SC_R_MATCH_26 184U +#define SC_R_MATCH_27 185U +#define SC_R_MATCH_28 186U +#define SC_R_LCD_0 187U +#define SC_R_LCD_0_PWM_0 188U +#define SC_R_LCD_0_I2C_0 189U +#define SC_R_LCD_0_I2C_1 190U +#define SC_R_PWM_0 191U +#define SC_R_PWM_1 192U +#define SC_R_PWM_2 193U +#define SC_R_PWM_3 194U +#define SC_R_PWM_4 195U +#define SC_R_PWM_5 196U +#define SC_R_PWM_6 197U +#define SC_R_PWM_7 198U +#define SC_R_GPIO_0 199U +#define SC_R_GPIO_1 200U +#define SC_R_GPIO_2 201U +#define SC_R_GPIO_3 202U +#define SC_R_GPIO_4 203U +#define SC_R_GPIO_5 204U +#define SC_R_GPIO_6 205U +#define SC_R_GPIO_7 206U +#define SC_R_GPT_0 207U +#define SC_R_GPT_1 208U +#define SC_R_GPT_2 209U +#define SC_R_GPT_3 210U +#define SC_R_GPT_4 211U +#define SC_R_KPP 212U +#define SC_R_MU_0A 213U +#define SC_R_MU_1A 214U +#define SC_R_MU_2A 215U +#define SC_R_MU_3A 216U +#define SC_R_MU_4A 217U +#define SC_R_MU_5A 218U +#define SC_R_MU_6A 219U +#define SC_R_MU_7A 220U +#define SC_R_MU_8A 221U +#define SC_R_MU_9A 222U +#define SC_R_MU_10A 223U +#define SC_R_MU_11A 224U +#define SC_R_MU_12A 225U +#define SC_R_MU_13A 226U +#define SC_R_MU_5B 227U +#define SC_R_MU_6B 228U +#define SC_R_MU_7B 229U +#define SC_R_MU_8B 230U +#define SC_R_MU_9B 231U +#define SC_R_MU_10B 232U +#define SC_R_MU_11B 233U +#define SC_R_MU_12B 234U +#define SC_R_MU_13B 235U +#define SC_R_ROM_0 236U +#define SC_R_FSPI_0 237U +#define SC_R_FSPI_1 238U +#define SC_R_IEE 239U +#define SC_R_IEE_R0 240U +#define SC_R_IEE_R1 241U +#define SC_R_IEE_R2 242U +#define SC_R_IEE_R3 243U +#define SC_R_IEE_R4 244U +#define SC_R_IEE_R5 245U +#define SC_R_IEE_R6 246U +#define SC_R_IEE_R7 247U +#define SC_R_SDHC_0 248U +#define SC_R_SDHC_1 249U +#define SC_R_SDHC_2 250U +#define SC_R_ENET_0 251U +#define SC_R_ENET_1 252U +#define SC_R_MLB_0 253U +#define SC_R_DMA_2_CH0 254U +#define SC_R_DMA_2_CH1 255U +#define SC_R_DMA_2_CH2 256U +#define SC_R_DMA_2_CH3 257U +#define SC_R_DMA_2_CH4 258U +#define SC_R_USB_0 259U +#define SC_R_USB_1 260U +#define SC_R_USB_0_PHY 261U +#define SC_R_USB_2 262U +#define SC_R_USB_2_PHY 263U +#define SC_R_DTCP 264U +#define SC_R_NAND 265U +#define SC_R_LVDS_0 266U +#define SC_R_LVDS_0_PWM_0 267U +#define SC_R_LVDS_0_I2C_0 268U +#define SC_R_LVDS_0_I2C_1 269U +#define SC_R_LVDS_1 270U +#define SC_R_LVDS_1_PWM_0 271U +#define SC_R_LVDS_1_I2C_0 272U +#define SC_R_LVDS_1_I2C_1 273U +#define SC_R_LVDS_2 274U +#define SC_R_LVDS_2_PWM_0 275U +#define SC_R_LVDS_2_I2C_0 276U +#define SC_R_LVDS_2_I2C_1 277U +#define SC_R_M4_0_PID0 278U +#define SC_R_M4_0_PID1 279U +#define SC_R_M4_0_PID2 280U +#define SC_R_M4_0_PID3 281U +#define SC_R_M4_0_PID4 282U +#define SC_R_M4_0_RGPIO 283U +#define SC_R_M4_0_SEMA42 284U +#define SC_R_M4_0_TPM 285U +#define SC_R_M4_0_PIT 286U +#define SC_R_M4_0_UART 287U +#define SC_R_M4_0_I2C 288U +#define SC_R_M4_0_INTMUX 289U +#define SC_R_M4_0_SIM 290U +#define SC_R_M4_0_WDOG 291U +#define SC_R_M4_0_MU_0B 292U +#define SC_R_M4_0_MU_0A0 293U +#define SC_R_M4_0_MU_0A1 294U +#define SC_R_M4_0_MU_0A2 295U +#define SC_R_M4_0_MU_0A3 296U +#define SC_R_M4_0_MU_1A 297U +#define SC_R_M4_1_PID0 298U +#define SC_R_M4_1_PID1 299U +#define SC_R_M4_1_PID2 300U +#define SC_R_M4_1_PID3 301U +#define SC_R_M4_1_PID4 302U +#define SC_R_M4_1_RGPIO 303U +#define SC_R_M4_1_SEMA42 304U +#define SC_R_M4_1_TPM 305U +#define SC_R_M4_1_PIT 306U +#define SC_R_M4_1_UART 307U +#define SC_R_M4_1_I2C 308U +#define SC_R_M4_1_INTMUX 309U +#define SC_R_M4_1_SIM 310U +#define SC_R_M4_1_WDOG 311U +#define SC_R_M4_1_MU_0B 312U +#define SC_R_M4_1_MU_0A0 313U +#define SC_R_M4_1_MU_0A1 314U +#define SC_R_M4_1_MU_0A2 315U +#define SC_R_M4_1_MU_0A3 316U +#define SC_R_M4_1_MU_1A 317U +#define SC_R_SAI_0 318U +#define SC_R_SAI_1 319U +#define SC_R_SAI_2 320U +#define SC_R_IRQSTR_SCU2 321U +#define SC_R_IRQSTR_DSP 322U +#define SC_R_UNUSED5 323U +#define SC_R_OCRAM 324U +#define SC_R_AUDIO_PLL_0 325U +#define SC_R_PI_0 326U +#define SC_R_PI_0_PWM_0 327U +#define SC_R_PI_0_PWM_1 328U +#define SC_R_PI_0_I2C_0 329U +#define SC_R_PI_0_PLL 330U +#define SC_R_PI_1 331U +#define SC_R_PI_1_PWM_0 332U +#define SC_R_PI_1_PWM_1 333U +#define SC_R_PI_1_I2C_0 334U +#define SC_R_PI_1_PLL 335U +#define SC_R_SC_PID0 336U +#define SC_R_SC_PID1 337U +#define SC_R_SC_PID2 338U +#define SC_R_SC_PID3 339U +#define SC_R_SC_PID4 340U +#define SC_R_SC_SEMA42 341U +#define SC_R_SC_TPM 342U +#define SC_R_SC_PIT 343U +#define SC_R_SC_UART 344U +#define SC_R_SC_I2C 345U +#define SC_R_SC_MU_0B 346U +#define SC_R_SC_MU_0A0 347U +#define SC_R_SC_MU_0A1 348U +#define SC_R_SC_MU_0A2 349U +#define SC_R_SC_MU_0A3 350U +#define SC_R_SC_MU_1A 351U +#define SC_R_SYSCNT_RD 352U +#define SC_R_SYSCNT_CMP 353U +#define SC_R_DEBUG 354U +#define SC_R_SYSTEM 355U +#define SC_R_SNVS 356U +#define SC_R_OTP 357U +#define SC_R_VPU_PID0 358U +#define SC_R_VPU_PID1 359U +#define SC_R_VPU_PID2 360U +#define SC_R_VPU_PID3 361U +#define SC_R_VPU_PID4 362U +#define SC_R_VPU_PID5 363U +#define SC_R_VPU_PID6 364U +#define SC_R_VPU_PID7 365U +#define SC_R_VPU_UART 366U +#define SC_R_VPUCORE 367U +#define SC_R_VPUCORE_0 368U +#define SC_R_VPUCORE_1 369U +#define SC_R_VPUCORE_2 370U +#define SC_R_VPUCORE_3 371U +#define SC_R_DMA_4_CH0 372U +#define SC_R_DMA_4_CH1 373U +#define SC_R_DMA_4_CH2 374U +#define SC_R_DMA_4_CH3 375U +#define SC_R_DMA_4_CH4 376U +#define SC_R_ISI_CH0 377U +#define SC_R_ISI_CH1 378U +#define SC_R_ISI_CH2 379U +#define SC_R_ISI_CH3 380U +#define SC_R_ISI_CH4 381U +#define SC_R_ISI_CH5 382U +#define SC_R_ISI_CH6 383U +#define SC_R_ISI_CH7 384U +#define SC_R_MJPEG_DEC_S0 385U +#define SC_R_MJPEG_DEC_S1 386U +#define SC_R_MJPEG_DEC_S2 387U +#define SC_R_MJPEG_DEC_S3 388U +#define SC_R_MJPEG_ENC_S0 389U +#define SC_R_MJPEG_ENC_S1 390U +#define SC_R_MJPEG_ENC_S2 391U +#define SC_R_MJPEG_ENC_S3 392U +#define SC_R_MIPI_0 393U +#define SC_R_MIPI_0_PWM_0 394U +#define SC_R_MIPI_0_I2C_0 395U +#define SC_R_MIPI_0_I2C_1 396U +#define SC_R_MIPI_1 397U +#define SC_R_MIPI_1_PWM_0 398U +#define SC_R_MIPI_1_I2C_0 399U +#define SC_R_MIPI_1_I2C_1 400U +#define SC_R_CSI_0 401U +#define SC_R_CSI_0_PWM_0 402U +#define SC_R_CSI_0_I2C_0 403U +#define SC_R_CSI_1 404U +#define SC_R_CSI_1_PWM_0 405U +#define SC_R_CSI_1_I2C_0 406U +#define SC_R_HDMI 407U +#define SC_R_HDMI_I2S 408U +#define SC_R_HDMI_I2C_0 409U +#define SC_R_HDMI_PLL_0 410U +#define SC_R_HDMI_RX 411U +#define SC_R_HDMI_RX_BYPASS 412U +#define SC_R_HDMI_RX_I2C_0 413U +#define SC_R_ASRC_0 414U +#define SC_R_ESAI_0 415U +#define SC_R_SPDIF_0 416U +#define SC_R_SPDIF_1 417U +#define SC_R_SAI_3 418U +#define SC_R_SAI_4 419U +#define SC_R_SAI_5 420U +#define SC_R_GPT_5 421U +#define SC_R_GPT_6 422U +#define SC_R_GPT_7 423U +#define SC_R_GPT_8 424U +#define SC_R_GPT_9 425U +#define SC_R_GPT_10 426U +#define SC_R_DMA_2_CH5 427U +#define SC_R_DMA_2_CH6 428U +#define SC_R_DMA_2_CH7 429U +#define SC_R_DMA_2_CH8 430U +#define SC_R_DMA_2_CH9 431U +#define SC_R_DMA_2_CH10 432U +#define SC_R_DMA_2_CH11 433U +#define SC_R_DMA_2_CH12 434U +#define SC_R_DMA_2_CH13 435U +#define SC_R_DMA_2_CH14 436U +#define SC_R_DMA_2_CH15 437U +#define SC_R_DMA_2_CH16 438U +#define SC_R_DMA_2_CH17 439U +#define SC_R_DMA_2_CH18 440U +#define SC_R_DMA_2_CH19 441U +#define SC_R_DMA_2_CH20 442U +#define SC_R_DMA_2_CH21 443U +#define SC_R_DMA_2_CH22 444U +#define SC_R_DMA_2_CH23 445U +#define SC_R_DMA_2_CH24 446U +#define SC_R_DMA_2_CH25 447U +#define SC_R_DMA_2_CH26 448U +#define SC_R_DMA_2_CH27 449U +#define SC_R_DMA_2_CH28 450U +#define SC_R_DMA_2_CH29 451U +#define SC_R_DMA_2_CH30 452U +#define SC_R_DMA_2_CH31 453U +#define SC_R_ASRC_1 454U +#define SC_R_ESAI_1 455U +#define SC_R_SAI_6 456U +#define SC_R_SAI_7 457U +#define SC_R_AMIX 458U +#define SC_R_MQS_0 459U +#define SC_R_DMA_3_CH0 460U +#define SC_R_DMA_3_CH1 461U +#define SC_R_DMA_3_CH2 462U +#define SC_R_DMA_3_CH3 463U +#define SC_R_DMA_3_CH4 464U +#define SC_R_DMA_3_CH5 465U +#define SC_R_DMA_3_CH6 466U +#define SC_R_DMA_3_CH7 467U +#define SC_R_DMA_3_CH8 468U +#define SC_R_DMA_3_CH9 469U +#define SC_R_DMA_3_CH10 470U +#define SC_R_DMA_3_CH11 471U +#define SC_R_DMA_3_CH12 472U +#define SC_R_DMA_3_CH13 473U +#define SC_R_DMA_3_CH14 474U +#define SC_R_DMA_3_CH15 475U +#define SC_R_DMA_3_CH16 476U +#define SC_R_DMA_3_CH17 477U +#define SC_R_DMA_3_CH18 478U +#define SC_R_DMA_3_CH19 479U +#define SC_R_DMA_3_CH20 480U +#define SC_R_DMA_3_CH21 481U +#define SC_R_DMA_3_CH22 482U +#define SC_R_DMA_3_CH23 483U +#define SC_R_DMA_3_CH24 484U +#define SC_R_DMA_3_CH25 485U +#define SC_R_DMA_3_CH26 486U +#define SC_R_DMA_3_CH27 487U +#define SC_R_DMA_3_CH28 488U +#define SC_R_DMA_3_CH29 489U +#define SC_R_DMA_3_CH30 490U +#define SC_R_DMA_3_CH31 491U +#define SC_R_AUDIO_PLL_1 492U +#define SC_R_AUDIO_CLK_0 493U +#define SC_R_AUDIO_CLK_1 494U +#define SC_R_MCLK_OUT_0 495U +#define SC_R_MCLK_OUT_1 496U +#define SC_R_PMIC_0 497U +#define SC_R_PMIC_1 498U +#define SC_R_SECO 499U +#define SC_R_CAAM_JR1 500U +#define SC_R_CAAM_JR2 501U +#define SC_R_CAAM_JR3 502U +#define SC_R_SECO_MU_2 503U +#define SC_R_SECO_MU_3 504U +#define SC_R_SECO_MU_4 505U +#define SC_R_HDMI_RX_PWM_0 506U +#define SC_R_A35 507U +#define SC_R_A35_0 508U +#define SC_R_A35_1 509U +#define SC_R_A35_2 510U +#define SC_R_A35_3 511U +#define SC_R_DSP 512U +#define SC_R_DSP_RAM 513U +#define SC_R_CAAM_JR1_OUT 514U +#define SC_R_CAAM_JR2_OUT 515U +#define SC_R_CAAM_JR3_OUT 516U +#define SC_R_VPU_DEC_0 517U +#define SC_R_VPU_ENC_0 518U +#define SC_R_CAAM_JR0 519U +#define SC_R_CAAM_JR0_OUT 520U +#define SC_R_PMIC_2 521U +#define SC_R_DBLOGIC 522U +#define SC_R_HDMI_PLL_1 523U +#define SC_R_BOARD_R0 524U +#define SC_R_BOARD_R1 525U +#define SC_R_BOARD_R2 526U +#define SC_R_BOARD_R3 527U +#define SC_R_BOARD_R4 528U +#define SC_R_BOARD_R5 529U +#define SC_R_BOARD_R6 530U +#define SC_R_BOARD_R7 531U +#define SC_R_MJPEG_DEC_MP 532U +#define SC_R_MJPEG_ENC_MP 533U +#define SC_R_VPU_TS_0 534U +#define SC_R_VPU_MU_0 535U +#define SC_R_VPU_MU_1 536U +#define SC_R_VPU_MU_2 537U +#define SC_R_VPU_MU_3 538U +#define SC_R_VPU_ENC_1 539U +#define SC_R_VPU 540U +#define SC_R_LAST 541U +#define SC_R_ALL ((sc_rsrc_t) UINT16_MAX) /* All resources */ +/*@}*/ + +/* NOTE - please add by replacing some of the UNUSED from above! */ + +/*! + * Defnes for sc_ctrl_t. + */ +#define SC_C_TEMP 0U +#define SC_C_TEMP_HI 1U +#define SC_C_TEMP_LOW 2U +#define SC_C_PXL_LINK_MST1_ADDR 3U +#define SC_C_PXL_LINK_MST2_ADDR 4U +#define SC_C_PXL_LINK_MST_ENB 5U +#define SC_C_PXL_LINK_MST1_ENB 6U +#define SC_C_PXL_LINK_MST2_ENB 7U +#define SC_C_PXL_LINK_SLV1_ADDR 8U +#define SC_C_PXL_LINK_SLV2_ADDR 9U +#define SC_C_PXL_LINK_MST_VLD 10U +#define SC_C_PXL_LINK_MST1_VLD 11U +#define SC_C_PXL_LINK_MST2_VLD 12U +#define SC_C_SINGLE_MODE 13U +#define SC_C_ID 14U +#define SC_C_PXL_CLK_POLARITY 15U +#define SC_C_LINESTATE 16U +#define SC_C_PCIE_G_RST 17U +#define SC_C_PCIE_BUTTON_RST 18U +#define SC_C_PCIE_PERST 19U +#define SC_C_PHY_RESET 20U +#define SC_C_PXL_LINK_RATE_CORRECTION 21U +#define SC_C_PANIC 22U +#define SC_C_PRIORITY_GROUP 23U +#define SC_C_TXCLK 24U +#define SC_C_CLKDIV 25U +#define SC_C_DISABLE_50 26U +#define SC_C_DISABLE_125 27U +#define SC_C_SEL_125 28U +#define SC_C_MODE 29U +#define SC_C_SYNC_CTRL0 30U +#define SC_C_KACHUNK_CNT 31U +#define SC_C_KACHUNK_SEL 32U +#define SC_C_SYNC_CTRL1 33U +#define SC_C_DPI_RESET 34U +#define SC_C_MIPI_RESET 35U +#define SC_C_DUAL_MODE 36U +#define SC_C_VOLTAGE 37U +#define SC_C_PXL_LINK_SEL 38U +#define SC_C_OFS_SEL 39U +#define SC_C_OFS_AUDIO 40U +#define SC_C_OFS_PERIPH 41U +#define SC_C_OFS_IRQ 42U +#define SC_C_RST0 43U +#define SC_C_RST1 44U +#define SC_C_SEL0 45U +#define SC_C_LAST 46U + +#define SC_P_ALL ((sc_pad_t) UINT16_MAX) /* All pads */ + +/* Types */ + +/*! + * This type is used to store a boolean + */ +typedef uint8_t sc_bool_t; + +/*! + * This type is used to store a system (full-size) address. + */ +typedef uint64_t sc_faddr_t; + +/*! + * This type is used to indicate error response for most functions. + */ +typedef uint8_t sc_err_t; + +/*! + * This type is used to indicate a resource. Resources include peripherals + * and bus masters (but not memory regions). Note items from list should + * never be changed or removed (only added to at the end of the list). + */ +typedef uint16_t sc_rsrc_t; + +/*! + * This type is used to indicate a control. + */ +typedef uint8_t sc_ctrl_t; + +/*! + * This type is used to indicate a pad. Valid values are SoC specific. + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +typedef uint16_t sc_pad_t; + +/* Extra documentation of standard types */ + +#ifdef DOXYGEN + /*! + * Type used to declare an 8-bit integer. + */ +typedef __INT8_TYPE__ int8_t; + + /*! + * Type used to declare a 16-bit integer. + */ +typedef __INT16_TYPE__ int16_t; + + /*! + * Type used to declare a 32-bit integer. + */ +typedef __INT32_TYPE__ int32_t; + + /*! + * Type used to declare a 64-bit integer. + */ +typedef __INT64_TYPE__ int64_t; + + /*! + * Type used to declare an 8-bit unsigned integer. + */ +typedef __UINT8_TYPE__ uint8_t; + + /*! + * Type used to declare a 16-bit unsigned integer. + */ +typedef __UINT16_TYPE__ uint16_t; + + /*! + * Type used to declare a 32-bit unsigned integer. + */ +typedef __UINT32_TYPE__ uint32_t; + + /*! + * Type used to declare a 64-bit unsigned integer. + */ +typedef __UINT64_TYPE__ uint64_t; +#endif + +#endif /* SCI_TYPES_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h new file mode 100644 index 0000000..d9dd49d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h @@ -0,0 +1,539 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2019 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing the public API for the System Controller (SC) + * Miscellaneous (MISC) function. + * + * @addtogroup MISC_SVC (SVC) Miscellaneous Service + * + * Module for the Miscellaneous (MISC) service. + * + * @{ + */ + +#ifndef SC_MISC_API_H +#define SC_MISC_API_H + +/* Includes */ + +#include +#include + +/* Defines */ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_MISC_DMA_GRP_W 5U /* Width of sc_misc_dma_group_t */ +/*@}*/ + +/*! Max DMA channel priority group */ +#define SC_MISC_DMA_GRP_MAX 31U + +/*! + * @name Defines for sc_misc_boot_status_t + */ +/*@{*/ +#define SC_MISC_BOOT_STATUS_SUCCESS 0U /* Success */ +#define SC_MISC_BOOT_STATUS_SECURITY 1U /* Security violation */ +/*@}*/ + +/*! + * @name Defines for sc_misc_seco_auth_cmd_t + */ +/*@{*/ +#define SC_MISC_SECO_AUTH_SECO_FW 0U /* SECO Firmware */ +#define SC_MISC_SECO_AUTH_HDMI_TX_FW 1U /* HDMI TX Firmware */ +#define SC_MISC_SECO_AUTH_HDMI_RX_FW 2U /* HDMI RX Firmware */ +/*@}*/ + +/*! + * @name Defines for sc_misc_temp_t + */ +/*@{*/ +#define SC_MISC_TEMP 0U /* Temp sensor */ +#define SC_MISC_TEMP_HIGH 1U /* Temp high alarm */ +#define SC_MISC_TEMP_LOW 2U /* Temp low alarm */ +/*@}*/ + +/*! + * @name Defines for sc_misc_seco_auth_cmd_t + */ +/*@{*/ +#define SC_MISC_AUTH_CONTAINER 0U /* Authenticate container */ +#define SC_MISC_VERIFY_IMAGE 1U /* Verify image */ +#define SC_MISC_REL_CONTAINER 2U /* Release container */ +/*@}*/ + +/* Types */ + +/*! + * This type is used to store a DMA channel priority group. + */ +typedef uint8_t sc_misc_dma_group_t; + +/*! + * This type is used report boot status. + */ +typedef uint8_t sc_misc_boot_status_t; + +/*! + * This type is used to issue SECO authenticate commands. + */ +typedef uint8_t sc_misc_seco_auth_cmd_t; + +/*! + * This type is used report boot status. + */ +typedef uint8_t sc_misc_temp_t; + +/* Functions */ + +/*! + * @name Control Functions + * @{ + */ + +/*! + * This function sets a miscellaneous control value. + * + * @param[in] ipc IPC handle + * @param[in] resource resource the control is associated with + * @param[in] ctrl control to change + * @param[in] val value to apply to the control + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent + * of the owner + * + * Refer to the [Control List](@ref CONTROLS) for valid control values. + */ +sc_err_t sc_misc_set_control(sc_ipc_t ipc, sc_rsrc_t resource, + sc_ctrl_t ctrl, uint32_t val); + +/*! + * This function gets a miscellaneous control value. + * + * @param[in] ipc IPC handle + * @param[in] resource resource the control is associated with + * @param[in] ctrl control to get + * @param[out] val pointer to return the control value + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent + * of the owner + * + * Refer to the [Control List](@ref CONTROLS) for valid control values. + */ +sc_err_t sc_misc_get_control(sc_ipc_t ipc, sc_rsrc_t resource, + sc_ctrl_t ctrl, uint32_t *val); + +/* @} */ + +/*! + * @name DMA Functions + * @{ + */ + +/*! + * This function configures the max DMA channel priority group for a + * partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to assign \a max + * @param[in] max max priority group (0-31) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the parent + * of the affected partition + * + * Valid \a max range is 0-31 with 0 being the lowest and 31 the highest. + * Default is the max priority group for the parent partition of \a pt. + */ +sc_err_t sc_misc_set_max_dma_group(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_misc_dma_group_t max); + +/*! + * This function configures the priority group for a DMA channel. + * + * @param[in] ipc IPC handle + * @param[in] resource DMA channel resource + * @param[in] group priority group (0-31) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the owner or parent + * of the owner of the DMA channel + * + * Valid \a group range is 0-31 with 0 being the lowest and 31 the highest. + * The max value of \a group is limited by the partition max set using + * sc_misc_set_max_dma_group(). + */ +sc_err_t sc_misc_set_dma_group(sc_ipc_t ipc, sc_rsrc_t resource, + sc_misc_dma_group_t group); + +/* @} */ + +/*! + * @name Security Functions + * @{ + */ + +/*! + * This function loads a SECO image. + * + * @param[in] ipc IPC handle + * @param[in] addr_src address of image source + * @param[in] addr_dst address of image destination + * @param[in] len length of image to load + * @param[in] fw SC_TRUE = firmware load + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_PARM if word fuse index param out of range or invalid + * - SC_ERR_UNAVAILABLE if SECO not available + * + * This is used to load images via the SECO. Examples include SECO + * Firmware and IVT/CSF data used for authentication. These are usually + * loaded into SECO TCM. \a addr_src is in secure memory. + * + * See the Security Reference Manual (SRM) for more info. + */ +sc_err_t sc_misc_seco_image_load(sc_ipc_t ipc, sc_faddr_t addr_src, + sc_faddr_t addr_dst, uint32_t len, + sc_bool_t fw); + +/*! + * This function is used to authenticate a SECO image or command. + * + * @param[in] ipc IPC handle + * @param[in] cmd authenticate command + * @param[in] addr address of/or metadata + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_PARM if word fuse index param out of range or invalid + * - SC_ERR_UNAVAILABLE if SECO not available + * + * This is used to authenticate a SECO image or issue a security + * command. \a addr often points to an container. It is also + * just data (or even unused) for some commands. + * + * See the Security Reference Manual (SRM) for more info. + */ +sc_err_t sc_misc_seco_authenticate(sc_ipc_t ipc, + sc_misc_seco_auth_cmd_t cmd, + sc_faddr_t addr); + +/*! + * This function securely writes a group of fuse words. + * + * @param[in] ipc IPC handle + * @param[in] addr address of message block + * + * @return Returns and error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_UNAVAILABLE if SECO not available + * + * Note \a addr must be a pointer to a signed message block. + * + * See the Security Reference Manual (SRM) for more info. + */ +sc_err_t sc_misc_seco_fuse_write(sc_ipc_t ipc, sc_faddr_t addr); + +/*! + * This function securely enables debug. + * + * @param[in] ipc IPC handle + * @param[in] addr address of message block + * + * @return Returns and error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_UNAVAILABLE if SECO not available + * + * Note \a addr must be a pointer to a signed message block. + * + * See the Security Reference Manual (SRM) for more info. + */ +sc_err_t sc_misc_seco_enable_debug(sc_ipc_t ipc, sc_faddr_t addr); + +/*! + * This function updates the lifecycle of the device. + * + * @param[in] ipc IPC handle + * @param[in] lifecycle new lifecycle + * + * @return Returns and error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_UNAVAILABLE if SECO not available + * + * This message is used for going from Open to NXP Closed to OEM Closed. + * + * See the Security Reference Manual (SRM) for more info. + */ +sc_err_t sc_misc_seco_forward_lifecycle(sc_ipc_t ipc, uint32_t lifecycle); + +/*! + * This function updates the lifecycle to one of the return lifecycles. + * + * @param[in] ipc IPC handle + * @param[in] addr address of message block + * + * @return Returns and error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_UNAVAILABLE if SECO not available + * + * Note \a addr must be a pointer to a signed message block. + * + * To switch back to NXP states (Full Field Return), message must be signed + * by NXP SRK. For OEM States (Partial Field Return), must be signed by OEM + * SRK. + * + * See the Security Reference Manual (SRM) for more info. + */ +sc_err_t sc_misc_seco_return_lifecycle(sc_ipc_t ipc, sc_faddr_t addr); + +/*! + * This function is used to return the SECO FW build info. + * + * @param[in] ipc IPC handle + * @param[out] version pointer to return build number + * @param[out] commit pointer to return commit ID (git SHA-1) + */ +void sc_misc_seco_build_info(sc_ipc_t ipc, uint32_t *version, uint32_t *commit); + +/*! + * This function is used to return SECO chip info. + * + * @param[in] ipc IPC handle + * @param[out] lc pointer to return lifecycle + * @param[out] monotonic pointer to return monotonic counter + * @param[out] uid_l pointer to return UID (lower 32 bits) + * @param[out] uid_h pointer to return UID (upper 32 bits) + */ +sc_err_t sc_misc_seco_chip_info(sc_ipc_t ipc, uint16_t *lc, + uint16_t *monotonic, uint32_t *uid_l, + uint32_t *uid_h); + +/* @} */ + +/*! + * @name Debug Functions + * @{ + */ + +/*! + * This function is used output a debug character from the SCU UART. + * + * @param[in] ipc IPC handle + * @param[in] ch character to output + */ +void sc_misc_debug_out(sc_ipc_t ipc, uint8_t ch); + +/*! + * This function starts/stops emulation waveform capture. + * + * @param[in] ipc IPC handle + * @param[in] enable flag to enable/disable capture + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_UNAVAILABLE if not running on emulation + */ +sc_err_t sc_misc_waveform_capture(sc_ipc_t ipc, sc_bool_t enable); + +/*! + * This function is used to return the SCFW build info. + * + * @param[in] ipc IPC handle + * @param[out] build pointer to return build number + * @param[out] commit pointer to return commit ID (git SHA-1) + */ +void sc_misc_build_info(sc_ipc_t ipc, uint32_t *build, uint32_t *commit); + +/*! + * This function is used to return the device's unique ID. + * + * @param[in] ipc IPC handle + * @param[out] id_l pointer to return lower 32-bit of ID [31:0] + * @param[out] id_h pointer to return upper 32-bits of ID [63:32] + */ +void sc_misc_unique_id(sc_ipc_t ipc, uint32_t *id_l, uint32_t *id_h); + +/* @} */ + +/*! + * @name Other Functions + * @{ + */ + +/*! + * This function configures the ARI match value for PCIe/SATA resources. + * + * @param[in] ipc IPC handle + * @param[in] resource match resource + * @param[in] resource_mst PCIe/SATA master to match + * @param[in] ari ARI to match + * @param[in] enable enable match or not + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the owner or parent + * of the owner of the resource and translation + * + * For PCIe, the ARI is the 16-bit value that includes the bus number, + * device number, and function number. For SATA, this value includes the + * FISType and PM_Port. + */ +sc_err_t sc_misc_set_ari(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rsrc_t resource_mst, uint16_t ari, + sc_bool_t enable); + +/*! + * This function reports boot status. + * + * @param[in] ipc IPC handle + * @param[in] status boot status + * + * This is used by SW partitions to report status of boot. This is + * normally used to report a boot failure. + */ +void sc_misc_boot_status(sc_ipc_t ipc, sc_misc_boot_status_t status); + +/*! + * This function tells the SCFW that a CPU is done booting. + * + * @param[in] ipc IPC handle + * @param[in] cpu CPU that is done booting + * + * This is called by early booting CPUs to report they are done with + * initialization. After starting early CPUs, the SCFW halts the + * booting process until they are done. During this time, early + * CPUs can call the SCFW with lower latency as the SCFW is idle. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the CPU owner + */ +sc_err_t sc_misc_boot_done(sc_ipc_t ipc, sc_rsrc_t cpu); + +/*! + * This function reads a given fuse word index. + * + * @param[in] ipc IPC handle + * @param[in] word fuse word index + * @param[out] val fuse read value + * + * @return Returns and error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_PARM if word fuse index param out of range or invalid + * - SC_ERR_NOACCESS if read operation failed + * - SC_ERR_LOCKED if read operation is locked + */ +sc_err_t sc_misc_otp_fuse_read(sc_ipc_t ipc, uint32_t word, uint32_t *val); + +/*! + * This function writes a given fuse word index. + * + * @param[in] ipc IPC handle + * @param[in] word fuse word index + * @param[in] val fuse write value + * + * @return Returns and error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_PARM if word fuse index param out of range or invalid + * - SC_ERR_NOACCESS if write operation failed + * - SC_ERR_LOCKED if write operation is locked + */ +sc_err_t sc_misc_otp_fuse_write(sc_ipc_t ipc, uint32_t word, uint32_t val); + +/*! + * This function sets a temp sensor alarm. + * + * @param[in] ipc IPC handle + * @param[in] resource resource with sensor + * @param[in] temp alarm to set + * @param[in] celsius whole part of temp to set + * @param[in] tenths fractional part of temp to set + * + * @return Returns and error code (SC_ERR_NONE = success). + * + * This function will enable the alarm interrupt if the temp requested is + * not the min/max temp. This enable automatically clears when the alarm + * occurs and this function has to be called again to re-enable. + * + * Return errors codes: + * - SC_ERR_PARM if parameters invalid + */ +sc_err_t sc_misc_set_temp(sc_ipc_t ipc, sc_rsrc_t resource, + sc_misc_temp_t temp, int16_t celsius, int8_t tenths); + +/*! + * This function gets a temp sensor value. + * + * @param[in] ipc IPC handle + * @param[in] resource resource with sensor + * @param[in] temp value to get (sensor or alarm) + * @param[out] celsius whole part of temp to get + * @param[out] tenths fractional part of temp to get + * + * @return Returns and error code (SC_ERR_NONE = success). + * + * Return errors codes: + * - SC_ERR_PARM if parameters invalid + */ +sc_err_t sc_misc_get_temp(sc_ipc_t ipc, sc_rsrc_t resource, + sc_misc_temp_t temp, int16_t *celsius, + int8_t *tenths); + +/*! + * This function returns the boot device. + * + * @param[in] ipc IPC handle + * @param[out] dev pointer to return boot device + */ +void sc_misc_get_boot_dev(sc_ipc_t ipc, sc_rsrc_t *dev); + +/*! + * This function returns the current status of the ON/OFF button. + * + * @param[in] ipc IPC handle + * @param[out] status pointer to return button status + */ +void sc_misc_get_button_status(sc_ipc_t ipc, sc_bool_t *status); + +/* @} */ + +#endif /* SC_MISC_API_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h new file mode 100644 index 0000000..dc23eed --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing the public API for the System Controller (SC) + * Pad Control (PAD) function. + * + * @addtogroup PAD_SVC (SVC) Pad Service + * + * Module for the Pad Control (PAD) service. + * + * @details + * + * Pad configuration is managed by SC firmware. The pad configuration + * features supported by the SC firmware include: + * + * - Configuring the mux, input/output connection, and low-power isolation + mode. + * - Configuring the technology-specific pad setting such as drive strength, + * pullup/pulldown, etc. + * - Configuring compensation for pad groups with dual voltage capability. + * + * Pad functions fall into one of three categories. Generic functions are + * common to all SoCs and all process technologies. SoC functions are raw + * low-level functions. Technology-specific functions are specific to the + * process technology. + * + * The list of pads is SoC specific. Refer to the SoC [Pad List](@ref PADS) + * for valid pad values. Note that all pads exist on a die but may or + * may not be brought out by the specific package. Mapping of pads to + * package pins/balls is documented in the associated Data Sheet. Some pads + * may not be brought out because the part (die+package) is defeatured and + * some pads may connect to the substrate in the package. + * + * Some pads (SC_P_COMP_*) that can be specified are not individual pads + * but are in fact pad groups. These groups have additional configuration + * that can be done using the sc_pad_set_gp_28fdsoi_comp() function. More + * info on these can be found in the associated Reference Manual. + * + * Pads are managed as a resource by the Resource Manager (RM). They have + * assigned owners and only the owners can configure the pads. Some of the + * pads are reserved for use by the SCFW itself and this can be overriden + * with the implementation of board_config_sc(). Additionally, pads may + * be assigned to various other partitions via the implementation of + * board_system_config(). + * + * Note muxing two input pads to the same IP functional signal will + * result in undefined behavior. + * @{ + */ + +#ifndef SCI_PAD_API_H +#define SCI_PAD_API_H + +/* Includes */ + +#include +#include + +/* Defines */ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_PAD_MUX_W 3 /* Width of mux parameter */ +/*@}*/ + +/*! + * @name Defines for sc_pad_config_t + */ +/*@{*/ +#define SC_PAD_CONFIG_NORMAL 0U /* Normal */ +#define SC_PAD_CONFIG_OD 1U /* Open Drain */ +#define SC_PAD_CONFIG_OD_IN 2U /* Open Drain and input */ +#define SC_PAD_CONFIG_OUT_IN 3U /* Output and input */ +/*@}*/ + +/*! + * @name Defines for sc_pad_iso_t + */ +/*@{*/ +#define SC_PAD_ISO_OFF 0U /* ISO latch is transparent */ +#define SC_PAD_ISO_EARLY 1U /* Follow EARLY_ISO */ +#define SC_PAD_ISO_LATE 2U /* Follow LATE_ISO */ +#define SC_PAD_ISO_ON 3U /* ISO latched data is held */ +/*@}*/ + +/*! + * @name Defines for sc_pad_28fdsoi_dse_t + */ +/*@{*/ +#define SC_PAD_28FDSOI_DSE_18V_1MA 0U /* Drive strength of 1mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_2MA 1U /* Drive strength of 2mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_4MA 2U /* Drive strength of 4mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_6MA 3U /* Drive strength of 6mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_8MA 4U /* Drive strength of 8mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_10MA 5U /* Drive strength of 10mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_12MA 6U /* Drive strength of 12mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_HS 7U /* High-speed drive strength for 1.8v */ +#define SC_PAD_28FDSOI_DSE_33V_2MA 0U /* Drive strength of 2mA for 3.3v */ +#define SC_PAD_28FDSOI_DSE_33V_4MA 1U /* Drive strength of 4mA for 3.3v */ +#define SC_PAD_28FDSOI_DSE_33V_8MA 2U /* Drive strength of 8mA for 3.3v */ +#define SC_PAD_28FDSOI_DSE_33V_12MA 3U /* Drive strength of 12mA for 3.3v */ +#define SC_PAD_28FDSOI_DSE_DV_HIGH 0U /* High drive strength for dual volt */ +#define SC_PAD_28FDSOI_DSE_DV_LOW 1U /* Low drive strength for dual volt */ +/*@}*/ + +/*! + * @name Defines for sc_pad_28fdsoi_ps_t + */ +/*@{*/ +#define SC_PAD_28FDSOI_PS_KEEPER 0U /* Bus-keeper (only valid for 1.8v) */ +#define SC_PAD_28FDSOI_PS_PU 1U /* Pull-up */ +#define SC_PAD_28FDSOI_PS_PD 2U /* Pull-down */ +#define SC_PAD_28FDSOI_PS_NONE 3U /* No pull (disabled) */ +/*@}*/ + +/*! + * @name Defines for sc_pad_28fdsoi_pus_t + */ +/*@{*/ +#define SC_PAD_28FDSOI_PUS_30K_PD 0U /* 30K pull-down */ +#define SC_PAD_28FDSOI_PUS_100K_PU 1U /* 100K pull-up */ +#define SC_PAD_28FDSOI_PUS_3K_PU 2U /* 3K pull-up */ +#define SC_PAD_28FDSOI_PUS_30K_PU 3U /* 30K pull-up */ +/*@}*/ + +/*! + * @name Defines for sc_pad_wakeup_t + */ +/*@{*/ +#define SC_PAD_WAKEUP_OFF 0U /* Off */ +#define SC_PAD_WAKEUP_CLEAR 1U /* Clears pending flag */ +#define SC_PAD_WAKEUP_LOW_LVL 4U /* Low level */ +#define SC_PAD_WAKEUP_FALL_EDGE 5U /* Falling edge */ +#define SC_PAD_WAKEUP_RISE_EDGE 6U /* Rising edge */ +#define SC_PAD_WAKEUP_HIGH_LVL 7U /* High-level */ +/*@}*/ + +/* Types */ + +/*! + * This type is used to declare a pad config. It determines how the + * output data is driven, pull-up is controlled, and input signal is + * connected. Normal and OD are typical and only connect the input + * when the output is not driven. The IN options are less common and + * force an input connection even when driving the output. + */ +typedef uint8_t sc_pad_config_t; + +/*! + * This type is used to declare a pad low-power isolation config. + * ISO_LATE is the most common setting. ISO_EARLY is only used when + * an output pad is directly determined by another input pad. The + * other two are only used when SW wants to directly contol isolation. + */ +typedef uint8_t sc_pad_iso_t; + +/*! + * This type is used to declare a drive strength. Note it is specific + * to 28FDSOI. Also note that valid values depend on the pad type. + */ +typedef uint8_t sc_pad_28fdsoi_dse_t; + +/*! + * This type is used to declare a pull select. Note it is specific + * to 28FDSOI. + */ +typedef uint8_t sc_pad_28fdsoi_ps_t; + +/*! + * This type is used to declare a pull-up select. Note it is specific + * to 28FDSOI HSIC pads. + */ +typedef uint8_t sc_pad_28fdsoi_pus_t; + +/*! + * This type is used to declare a wakeup mode of a pad. + */ +typedef uint8_t sc_pad_wakeup_t; + +/* Functions */ + +/*! + * @name Generic Functions + * @{ + */ + +/*! + * This function configures the mux settings for a pad. This includes + * the signal mux, pad config, and low-power isolation mode. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] mux mux setting + * @param[in] config pad config + * @param[in] iso low-power isolation mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Note muxing two input pads to the same IP functional signal will + * result in undefined behavior. + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_mux(sc_ipc_t ipc, sc_pad_t pad, + uint8_t mux, sc_pad_config_t config, sc_pad_iso_t iso); + +/*! + * This function gets the mux settings for a pad. This includes + * the signal mux, pad config, and low-power isolation mode. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] mux pointer to return mux setting + * @param[out] config pointer to return pad config + * @param[out] iso pointer to return low-power isolation mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_mux(sc_ipc_t ipc, sc_pad_t pad, + uint8_t *mux, sc_pad_config_t *config, + sc_pad_iso_t *iso); + +/*! + * This function configures the general purpose pad control. This + * is technology dependent and includes things like drive strength, + * slew rate, pull up/down, etc. Refer to the SoC Reference Manual + * for bit field details. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] ctrl control value to set + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t ctrl); + +/*! + * This function gets the general purpose pad control. This + * is technology dependent and includes things like drive strength, + * slew rate, pull up/down, etc. Refer to the SoC Reference Manual + * for bit field details. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] ctrl pointer to return control value + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t *ctrl); + +/*! + * This function configures the wakeup mode of the pad. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] wakeup wakeup to set + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t wakeup); + +/*! + * This function gets the wakeup mode of a pad. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] wakeup pointer to return wakeup + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t *wakeup); + +/*! + * This function configures a pad. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] mux mux setting + * @param[in] config pad config + * @param[in] iso low-power isolation mode + * @param[in] ctrl control value + * @param[in] wakeup wakeup to set + * + * @see sc_pad_set_mux(). + * @see sc_pad_set_gp(). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Note muxing two input pads to the same IP functional signal will + * result in undefined behavior. + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t mux, + sc_pad_config_t config, sc_pad_iso_t iso, uint32_t ctrl, + sc_pad_wakeup_t wakeup); + +/*! + * This function gets a pad's config. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] mux pointer to return mux setting + * @param[out] config pointer to return pad config + * @param[out] iso pointer to return low-power isolation mode + * @param[out] ctrl pointer to return control value + * @param[out] wakeup pointer to return wakeup to set + * + * @see sc_pad_set_mux(). + * @see sc_pad_set_gp(). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t *mux, + sc_pad_config_t *config, sc_pad_iso_t *iso, + uint32_t *ctrl, sc_pad_wakeup_t *wakeup); + +/* @} */ + +/*! + * @name SoC Specific Functions + * @{ + */ + +/*! + * This function configures the settings for a pad. This setting is SoC + * specific. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] val value to set + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, uint32_t val); + +/*! + * This function gets the settings for a pad. This setting is SoC + * specific. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] val pointer to return setting + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val); + +/* @} */ + +/*! + * @name Technology Specific Functions + * @{ + */ + +/*! + * This function configures the pad control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] dse drive strength + * @param[in] ps pull select + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t dse, + sc_pad_28fdsoi_ps_t ps); + +/*! + * This function gets the pad control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] dse pointer to return drive strength + * @param[out] ps pointer to return pull select + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t *dse, + sc_pad_28fdsoi_ps_t *ps); + +/*! + * This function configures the pad control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] dse drive strength + * @param[in] hys hysteresis + * @param[in] pus pull-up select + * @param[in] pke pull keeper enable + * @param[in] pue pull-up enable + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t dse, sc_bool_t hys, + sc_pad_28fdsoi_pus_t pus, sc_bool_t pke, + sc_bool_t pue); + +/*! + * This function gets the pad control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] dse pointer to return drive strength + * @param[out] hys pointer to return hysteresis + * @param[out] pus pointer to return pull-up select + * @param[out] pke pointer to return pull keeper enable + * @param[out] pue pointer to return pull-up enable + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t *dse, sc_bool_t *hys, + sc_pad_28fdsoi_pus_t *pus, sc_bool_t *pke, + sc_bool_t *pue); + +/*! + * This function configures the compensation control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] compen compensation/freeze mode + * @param[in] fastfrz fast freeze + * @param[in] rasrcp compensation code for PMOS + * @param[in] rasrcn compensation code for NMOS + * @param[in] nasrc_sel NASRC read select + * @param[in] psw_ovr 2.5v override + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + * + * Note \a psw_ovr is only applicable to pads supporting 2.5 volt + * operation (e.g. some Ethernet pads). + */ +sc_err_t sc_pad_set_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad, + uint8_t compen, sc_bool_t fastfrz, + uint8_t rasrcp, uint8_t rasrcn, + sc_bool_t nasrc_sel, sc_bool_t psw_ovr); + +/*! + * This function gets the compensation control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] compen pointer to return compensation/freeze mode + * @param[out] fastfrz pointer to return fast freeze + * @param[out] rasrcp pointer to return compensation code for PMOS + * @param[out] rasrcn pointer to return compensation code for NMOS + * @param[out] nasrc_sel pointer to return NASRC read select + * @param[out] compok pointer to return compensation status + * @param[out] nasrc pointer to return NASRCP/NASRCN + * @param[out] psw_ovr pointer to return the 2.5v override + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad, + uint8_t *compen, sc_bool_t *fastfrz, + uint8_t *rasrcp, uint8_t *rasrcn, + sc_bool_t *nasrc_sel, sc_bool_t *compok, + uint8_t *nasrc, sc_bool_t *psw_ovr); + +/* @} */ + +#endif /* SCI_PAD_API_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h new file mode 100644 index 0000000..76ca5c4 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h @@ -0,0 +1,684 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing the public API for the System Controller (SC) + * Power Management (PM) function. This includes functions for power state + * control, clock control, reset control, and wake-up event control. + * + * @addtogroup PM_SVC (SVC) Power Management Service + * + * Module for the Power Management (PM) service. + * + * @{ + */ + +#ifndef SCI_PM_API_H +#define SCI_PM_API_H + +/* Includes */ + +#include +#include + +/* Defines */ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_PM_POWER_MODE_W 2 /* Width of sc_pm_power_mode_t */ +#define SC_PM_CLOCK_MODE_W 3 /* Width of sc_pm_clock_mode_t */ +#define SC_PM_RESET_TYPE_W 2 /* Width of sc_pm_reset_type_t */ +#define SC_PM_RESET_REASON_W 3 /* Width of sc_pm_reset_reason_t */ +/*@}*/ + +/*! + * @name Defines for clock indexes (sc_pm_clk_t) + */ +/*@{*/ +/*@}*/ + +/*! + * @name Defines for ALL parameters + */ +/*@{*/ +#define SC_PM_CLK_ALL UINT8_MAX /* All clocks */ +/*@}*/ + +/*! + * @name Defines for sc_pm_power_mode_t + */ +/*@{*/ +#define SC_PM_PW_MODE_OFF 0U /* Power off */ +#define SC_PM_PW_MODE_STBY 1U /* Power in standby */ +#define SC_PM_PW_MODE_LP 2U /* Power in low-power */ +#define SC_PM_PW_MODE_ON 3U /* Power on */ +/*@}*/ + +/*! + * @name Defines for sc_pm_clk_t + */ +/*@{*/ +#define SC_PM_CLK_SLV_BUS 0U /* Slave bus clock */ +#define SC_PM_CLK_MST_BUS 1U /* Master bus clock */ +#define SC_PM_CLK_PER 2U /* Peripheral clock */ +#define SC_PM_CLK_PHY 3U /* Phy clock */ +#define SC_PM_CLK_MISC 4U /* Misc clock */ +#define SC_PM_CLK_MISC0 0U /* Misc 0 clock */ +#define SC_PM_CLK_MISC1 1U /* Misc 1 clock */ +#define SC_PM_CLK_MISC2 2U /* Misc 2 clock */ +#define SC_PM_CLK_MISC3 3U /* Misc 3 clock */ +#define SC_PM_CLK_MISC4 4U /* Misc 4 clock */ +#define SC_PM_CLK_CPU 2U /* CPU clock */ +#define SC_PM_CLK_PLL 4U /* PLL */ +#define SC_PM_CLK_BYPASS 4U /* Bypass clock */ +/*@}*/ + +/*! + * @name Defines for sc_pm_clk_mode_t + */ +/*@{*/ +#define SC_PM_CLK_MODE_ROM_INIT 0U /* Clock is initialized by ROM. */ +#define SC_PM_CLK_MODE_OFF 1U /* Clock is disabled */ +#define SC_PM_CLK_MODE_ON 2U /* Clock is enabled. */ +#define SC_PM_CLK_MODE_AUTOGATE_SW 3U /* Clock is in SW autogate mode */ +#define SC_PM_CLK_MODE_AUTOGATE_HW 4U /* Clock is in HW autogate mode */ +#define SC_PM_CLK_MODE_AUTOGATE_SW_HW 5U /* Clock is in SW-HW autogate mode */ +/*@}*/ + +/*! + * @name Defines for sc_pm_clk_parent_t + */ +/*@{*/ +#define SC_PM_PARENT_XTAL 0U /* Parent is XTAL. */ +#define SC_PM_PARENT_PLL0 1U /* Parent is PLL0 */ +#define SC_PM_PARENT_PLL1 2U /* Parent is PLL1 or PLL0/2 */ +#define SC_PM_PARENT_PLL2 3U /* Parent in PLL2 or PLL0/4 */ +#define SC_PM_PARENT_BYPS 4U /* Parent is a bypass clock. */ +/*@}*/ + +/*! + * @name Defines for sc_pm_reset_type_t + */ +/*@{*/ +#define SC_PM_RESET_TYPE_COLD 0U /* Cold reset */ +#define SC_PM_RESET_TYPE_WARM 1U /* Warm reset */ +#define SC_PM_RESET_TYPE_BOARD 2U /* Board reset */ +/*@}*/ + +/*! + * @name Defines for sc_pm_reset_cause_t + */ +/*@{*/ +#define SC_PM_RESET_CAUSE_TEMP 0U /* Reset due to temp panic alarm */ +#define SC_PM_RESET_CAUSE_FAULT 1U /* Reset due to fault exception */ +#define SC_PM_RESET_CAUSE_IRQ 2U /* Reset due to SCU reset IRQ */ +#define SC_PM_RESET_CAUSE_WDOG 3U /* Reset due to SW WDOG */ +#define SC_PM_RESET_CAUSE_API 4U /* Reset due to pm_reset() or monitor */ +/*@}*/ + +/*! + * @name Defines for sc_pm_reset_reason_t + */ +/*@{*/ +#define SC_PM_RESET_REASON_POR 0U /* Power on reset */ +#define SC_PM_RESET_REASON_WARM 1U /* Warm reset */ +#define SC_PM_RESET_REASON_SW 2U /* Software reset */ +#define SC_PM_RESET_REASON_WDOG 3U /* Watchdog reset */ +#define SC_PM_RESET_REASON_LOCKUP 4U /* Lockup reset */ +#define SC_PM_RESET_REASON_TAMPER 5U /* Tamper reset */ +#define SC_PM_RESET_REASON_TEMP 6U /* Temp reset */ +#define SC_PM_RESET_REASON_LOW_VOLT 7U /* Low voltage reset */ +/*@}*/ + +/*! + * @name Defines for sc_pm_sys_if_t + */ +/*@{*/ +#define SC_PM_SYS_IF_INTERCONNECT 0U /* System interconnect */ +#define SC_PM_SYS_IF_MU 1U /* AP -> SCU message units */ +#define SC_PM_SYS_IF_OCMEM 2U /* On-chip memory (ROM/OCRAM) */ +#define SC_PM_SYS_IF_DDR 3U /* DDR memory */ +/*@}*/ + +/*! + * @name Defines for sc_pm_wake_src_t + */ +/*@{*/ +#define SC_PM_WAKE_SRC_NONE 0U /* No wake source, used for self-kill */ +#define SC_PM_WAKE_SRC_SCU 1U /* Wakeup from SCU to resume CPU (IRQSTEER & GIC powered down) */ +#define SC_PM_WAKE_SRC_IRQSTEER 2U /* Wakeup from IRQSTEER to resume CPU (GIC powered down) */ +#define SC_PM_WAKE_SRC_IRQSTEER_GIC 3U /* Wakeup from IRQSTEER+GIC to wake CPU (GIC clock gated) */ +#define SC_PM_WAKE_SRC_GIC 4U /* Wakeup from GIC to wake CPU */ +/*@}*/ + +/* Types */ + +/*! + * This type is used to declare a power mode. Note resources only use + * SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON. The other modes are used only + * as system power modes. + */ +typedef uint8_t sc_pm_power_mode_t; + +/*! + * This type is used to declare a clock. + */ +typedef uint8_t sc_pm_clk_t; + +/*! + * This type is used to declare a clock mode. + */ +typedef uint8_t sc_pm_clk_mode_t; + +/*! + * This type is used to declare the clock parent. + */ +typedef uint8_t sc_pm_clk_parent_t; + +/*! + * This type is used to declare clock rates. + */ +typedef uint32_t sc_pm_clock_rate_t; + +/*! + * This type is used to declare a desired reset type. + */ +typedef uint8_t sc_pm_reset_type_t; + +/*! + * This type is used to declare a desired reset type. + */ +typedef uint8_t sc_pm_reset_cause; + +/*! + * This type is used to declare a reason for a reset. + */ +typedef uint8_t sc_pm_reset_reason_t; + +/*! + * This type is used to specify a system-level interface to be power managed. + */ +typedef uint8_t sc_pm_sys_if_t; + +/*! + * This type is used to specify a wake source for CPU resources. + */ +typedef uint8_t sc_pm_wake_src_t; + +/* Functions */ + +/*! + * @name Power Functions + * @{ + */ + +/*! + * This function sets the system power mode. Only the owner of the + * SC_R_SYSTEM resource can do this. + * + * @param[in] ipc IPC handle + * @param[in] mode power mode to apply + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid mode, + * - SC_ERR_NOACCESS if caller not the owner of SC_R_SYSTEM + * + * @see sc_pm_set_sys_power_mode(). + */ +sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode); + +/*! + * This function sets the power mode of a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition + * @param[in] mode power mode to apply + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid partition or mode, + * - SC_ERR_NOACCESS if caller's partition is not the owner or + * parent of \a pt + * + * The power mode of the partitions is a max power any resource will + * be set to. Calling this will result in all resources owned + * by \a pt to have their power changed to the lower of \a mode or the + * individual resource mode set using sc_pm_set_resource_power_mode(). + */ +sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_power_mode_t mode); + +/*! + * This function gets the power mode of a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition + * @param[out] mode pointer to return power mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid partition + */ +sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_power_mode_t *mode); + +/*! + * This function sets the power mode of a resource. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] mode power mode to apply + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or mode, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner + * + * This function will record the individual resource power mode + * and change it if the requested mode is lower than or equal to the + * partition power mode set with sc_pm_set_partition_power_mode(). + * In other words, the power mode of the resource will be the minimum + * of the resource power mode and the partition power mode. + * + * Note some resources are still not accessible even when powered up if bus + * transactions go through a fabric not powered up. Examples of this are + * resources in display and capture subsystems which require the display + * controller or the imaging subsytem to be powered up first. + * + * Not that resources are grouped into power domains by the underlying + * hardware. If any resource in the domain is on, the entire power domain + * will be on. Other power domains required to access the resource will + * also be turned on. Clocks required to access the peripheral will be + * turned on. Refer to the SoC RM for more info on power domains and access + * infrastructure (bus fabrics, clock domains, etc.). + */ +sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode); + +/*! + * This function gets the power mode of a resource. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[out] mode pointer to return power mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Note only SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON are valid. The value + * returned does not reflect the power mode of the partition.. + */ +sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t *mode); + +/*! + * This function requests the low power mode some of the resources + * can enter based on their state. This API is only valid for the + * following resources : SC_R_A53, SC_R_A53_0, SC_R_A53_1, SC_A53_2, + * SC_A53_3, SC_R_A72, SC_R_A72_0, SC_R_A72_1, SC_R_CC1, SC_R_A35, + * SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3. + * For all other resources it will return SC_ERR_PARAM. + * This function will set the low power mode the cores, cluster + * and cluster associated resources will enter when all the cores + * in a given cluster execute WFI + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] mode power mode to apply + * + * @return Returns an error code (SC_ERR_NONE = success). + * + */ +sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode); + +/*! + * This function requests low-power mode entry for CPU/cluster + * resources. This API is only valid for the following resources: + * SC_R_A53, SC_R_A53_x, SC_R_A72, SC_R_A72_x, SC_R_A35, SC_R_A35_x, + * SC_R_CCI. For all other resources it will return SC_ERR_PARAM. + * For individual core resources, the specified power mode + * and wake source will be applied after the core has entered + * WFI. For cluster resources, the specified power mode is + * applied after all cores in the cluster have entered low-power mode. + * For multicluster resources, the specified power mode is applied + * after all clusters have reached low-power mode. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] mode power mode to apply + * @param[in] wake_src wake source for low-power exit + * + * @return Returns an error code (SC_ERR_NONE = success). + * + */ +sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode, + sc_pm_wake_src_t wake_src); + +/*! + * This function is used to set the resume address of a CPU. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the CPU resource + * @param[in] address 64-bit resume address + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or address, + * - SC_ERR_NOACCESS if caller's partition is not the parent of the + * resource (CPU) owner + */ +sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource, + sc_faddr_t address); + +/*! + * This function is used to set parameters for CPU resume from + * low-power mode. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the CPU resource + * @param[in] isPrimary set SC_TRUE if primary wake CPU + * @param[in] address 64-bit resume address + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or address, + * - SC_ERR_NOACCESS if caller's partition is not the parent of the + * resource (CPU) owner + */ +sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource, + sc_bool_t isPrimary, sc_faddr_t address); + +/*! + * This function requests the power mode configuration for system-level + * interfaces including messaging units, interconnect, and memories. This API + * is only valid for the following resources : SC_R_A53, SC_R_A72, and + * SC_R_M4_x_PID_y. For all other resources, it will return SC_ERR_PARAM. + * The requested power mode will be captured and applied to system-level + * resources as system conditions allow. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] sys_if system-level interface to be configured + * @param[in] hpm high-power mode for the system interface + * @param[in] lpm low-power mode for the system interface + * + * @return Returns an error code (SC_ERR_NONE = success). + * + */ +sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_sys_if_t sys_if, + sc_pm_power_mode_t hpm, + sc_pm_power_mode_t lpm); + +/* @} */ + +/*! + * @name Clock/PLL Functions + * @{ + */ + +/*! + * This function sets the rate of a resource's clock/PLL. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock/PLL to affect + * @param[in,out] rate pointer to rate to set, + * return actual rate + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock/PLL, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock/PLL not applicable to this resource, + * - SC_ERR_LOCKED if rate locked (usually because shared clock/PLL) + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock/PLL values. + */ +sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clock_rate_t *rate); + +/*! + * This function gets the rate of a resource's clock/PLL. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock/PLL to affect + * @param[out] rate pointer to return rate + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock/PLL, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock/PLL not applicable to this resource + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock/PLL values. + */ +sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clock_rate_t *rate); + +/*! + * This function enables/disables a resource's clock. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock to affect + * @param[in] enable enable if SC_TRUE; otherwise disabled + * @param[in] autog HW auto clock gating + * + * If \a resource is SC_R_ALL then all resources owned will be affected. + * No error will be returned. + * + * If \a clk is SC_PM_CLK_ALL, then an error will be returned if any + * of the available clocks returns an error. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock not applicable to this resource + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock values. + */ +sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog); + +/*! + * This function sets the parent of a resource's clock. + * This function should only be called when the clock is disabled. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock to affect + * @param[in] parent New parent of the clock. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock not applicable to this resource + * - SC_ERR_BUSY if clock is currently enabled. + * - SC_ERR_NOPOWER if resource not powered + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock values. + */ +sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clk_parent_t parent); + +/*! + * This function gets the parent of a resource's clock. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock to affect + * @param[out] parent pointer to return parent of clock. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock not applicable to this resource + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock values. + */ +sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clk_parent_t *parent); + +/* @} */ + +/*! + * @name Reset Functions + * @{ + */ + +/*! + * This function is used to reset the system. Only the owner of the + * SC_R_SYSTEM resource can do this. + * + * @param[in] ipc IPC handle + * @param[in] type reset type + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid type, + * - SC_ERR_NOACCESS if caller not the owner of SC_R_SYSTEM + * + * If this function returns, then the reset did not occur due to an + * invalid parameter. + */ +sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type); + +/*! + * This function gets a caller's reset reason. + * + * @param[in] ipc IPC handle + * @param[out] reason pointer to return reset reason + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason); + +/*! + * This function is used to boot a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to boot + * @param[in] resource_cpu ID of the CPU resource to start + * @param[in] boot_addr 64-bit boot address + * @param[in] resource_mu ID of the MU that must be powered + * @param[in] resource_dev ID of the boot device that must be powered + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid partition, resource, or addr, + * - SC_ERR_NOACCESS if caller's partition is not the parent of the + * partition to boot + */ +sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_rsrc_t resource_cpu, sc_faddr_t boot_addr, + sc_rsrc_t resource_mu, sc_rsrc_t resource_dev); + +/*! + * This function is used to reboot the caller's partition. + * + * @param[in] ipc IPC handle + * @param[in] type reset type + * + * If \a type is SC_PM_RESET_TYPE_COLD, then most peripherals owned by + * the calling partition will be reset if possible. SC state (partitions, + * power, clocks, etc.) is reset. The boot SW of the booting CPU must be + * able to handle peripherals that that are not reset. + * + * If \a type is SC_PM_RESET_TYPE_WARM, then only the boot CPU is reset. + * SC state (partitions, power, clocks, etc.) are NOT reset. The boot SW + * of the booting CPU must be able to handle peripherals and SC state that + * that are not reset. + * + * If \a type is SC_PM_RESET_TYPE_BOARD, then return with no action. + * + * If this function returns, then the reset did not occur due to an + * invalid parameter. + */ +void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type); + +/*! + * This function is used to reboot a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to reboot + * @param[in] type reset type + * + * If \a type is SC_PM_RESET_TYPE_COLD, then most peripherals owned by + * the calling partition will be reset if possible. SC state (partitions, + * power, clocks, etc.) is reset. The boot SW of the booting CPU must be + * able to handle peripherals that that are not reset. + * + * If \a type is SC_PM_RESET_TYPE_WARM, then only the boot CPU is reset. + * SC state (partitions, power, clocks, etc.) are NOT reset. The boot SW + * of the booting CPU must be able to handle peripherals and SC state that + * that are not reset. + * + * If \a type is SC_PM_RESET_TYPE_BOARD, then return with no action. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid partition or type + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt, + * + * Most peripherals owned by the partition will be reset if + * possible. SC state (partitions, power, clocks, etc.) is reset. The + * boot SW of the booting CPU must be able to handle peripherals that + * that are not reset. + */ +sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_reset_type_t type); + +/*! + * This function is used to start/stop a CPU. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the CPU resource + * @param[in] enable start if SC_TRUE; otherwise stop + * @param[in] address 64-bit boot address + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or address, + * - SC_ERR_NOACCESS if caller's partition is not the parent of the + * resource (CPU) owner + */ +sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, + sc_faddr_t address); + +/* @} */ + +#endif /* SCI_PM_API_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h new file mode 100644 index 0000000..df1bc40 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h @@ -0,0 +1,757 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing the public API for the System Controller (SC) + * Resource Management (RM) function. This includes functions for + * partitioning resources, pads, and memory regions. + * + * @addtogroup RM_SVC (SVC) Resource Management Service + * + * Module for the Resource Management (RM) service. + * + * @includedoc rm/details.dox + * + * @{ + */ + +#ifndef SCI_RM_API_H +#define SCI_RM_API_H + +/* Includes */ + +#include + +/* Defines */ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_RM_PARTITION_W 5 /* Width of sc_rm_pt_t */ +#define SC_RM_MEMREG_W 6 /* Width of sc_rm_mr_t */ +#define SC_RM_DID_W 4 /* Width of sc_rm_did_t */ +#define SC_RM_SID_W 6 /* Width of sc_rm_sid_t */ +#define SC_RM_SPA_W 2 /* Width of sc_rm_spa_t */ +#define SC_RM_PERM_W 3 /* Width of sc_rm_perm_t */ +/*@}*/ + +/*! + * @name Defines for ALL parameters + */ +/*@{*/ +#define SC_RM_PT_ALL ((sc_rm_pt_t) UINT8_MAX) /* All partitions */ +#define SC_RM_MR_ALL ((sc_rm_mr_t) UINT8_MAX) /* All memory regions */ +/*@}*/ + +/*! + * @name Defines for sc_rm_spa_t + */ +/*@{*/ +#define SC_RM_SPA_PASSTHRU 0U /* Pass through (attribute driven by master) */ +#define SC_RM_SPA_PASSSID 1U /* Pass through and output on SID */ +#define SC_RM_SPA_ASSERT 2U /* Assert (force to be secure/privileged) */ +#define SC_RM_SPA_NEGATE 3U /* Negate (force to be non-secure/user) */ +/*@}*/ + +/*! + * @name Defines for sc_rm_perm_t + */ +/*@{*/ +#define SC_RM_PERM_NONE 0U /* No access */ +#define SC_RM_PERM_SEC_R 1U /* Secure RO */ +#define SC_RM_PERM_SECPRIV_RW 2U /* Secure privilege R/W */ +#define SC_RM_PERM_SEC_RW 3U /* Secure R/W */ +#define SC_RM_PERM_NSPRIV_R 4U /* Secure R/W, non-secure privilege RO */ +#define SC_RM_PERM_NS_R 5U /* Secure R/W, non-secure RO */ +#define SC_RM_PERM_NSPRIV_RW 6U /* Secure R/W, non-secure privilege R/W */ +#define SC_RM_PERM_FULL 7U /* Full access */ +/*@}*/ + +/* Types */ + +/*! + * This type is used to declare a resource partition. + */ +typedef uint8_t sc_rm_pt_t; + +/*! + * This type is used to declare a memory region. + */ +typedef uint8_t sc_rm_mr_t; + +/*! + * This type is used to declare a resource domain ID used by the + * isolation HW. + */ +typedef uint8_t sc_rm_did_t; + +/*! + * This type is used to declare an SMMU StreamID. + */ +typedef uint16_t sc_rm_sid_t; + +/*! + * This type is a used to declare master transaction attributes. + */ +typedef uint8_t sc_rm_spa_t; + +/*! + * This type is used to declare a resource/memory region access permission. + * Refer to the XRDC2 Block Guide for more information. + */ +typedef uint8_t sc_rm_perm_t; + +/* Functions */ + +/*! + * @name Partition Functions + * @{ + */ + +/*! + * This function requests that the SC create a new resource partition. + * + * @param[in] ipc IPC handle + * @param[out] pt return handle for partition; used for subsequent function + * calls associated with this partition + * @param[in] secure boolean indicating if this partition should be secure; only + * valid if caller is secure + * @param[in] isolated boolean indicating if this partition should be HW isolated + * via XRDC; set SC_TRUE if new DID is desired + * @param[in] restricted boolean indicating if this partition should be restricted; set + * SC_TRUE if masters in this partition cannot create new partitions + * @param[in] grant boolean indicating if this partition should always grant + * access and control to the parent + * @param[in] coherent boolean indicating if this partition is coherent; + * set SC_TRUE if only this partition will contain both AP clusters + * and they will be coherent via the CCI + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_ERR_PARM if caller's partition is not secure but a new secure partition is requested, + * - SC_ERR_LOCKED if caller's partition is locked, + * - SC_ERR_UNAVAILABLE if partition table is full (no more allocation space) + * + * Marking as non-secure prevents subsequent functions from configuring masters in this + * partition to assert the secure signal. If restricted then the new partition is limited + * in what functions it can call, especially those associated with managing partitions. + * + * The grant option is usually used to isolate a bus master's traffic to specific + * memory without isolating the peripheral interface of the master or the API + * controls of that master. + */ +sc_err_t sc_rm_partition_alloc(sc_ipc_t ipc, sc_rm_pt_t *pt, sc_bool_t secure, + sc_bool_t isolated, sc_bool_t restricted, + sc_bool_t grant, sc_bool_t coherent); + +/*! + * This function makes a partition confidential. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition that is granting + * @param[in] retro retroactive + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a pt out of range, + * - SC_ERR_NOACCESS if caller's not allowed to change \a pt + * - SC_ERR_LOCKED if partition \a pt is locked + * + * Call to make a partition confidential. Confidential means only this + * partition should be able to grant access permissions to this partition. + * + * If retroactive, then all resources owned by other partitions will have + * access rights for this partition removed, even if locked. + */ +sc_err_t sc_rm_set_confidential(sc_ipc_t ipc, sc_rm_pt_t pt, sc_bool_t retro); + +/*! + * This function frees a partition and assigns all resources to the caller. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to free + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if \a pt out of range or invalid, + * - SC_ERR_NOACCESS if \a pt is the SC partition, + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt, + * - SC_ERR_LOCKED if \a pt or caller's partition is locked + * + * All resources, memory regions, and pads are assigned to the caller/parent. + * The partition watchdog is disabled (even if locked). DID is freed. + */ +sc_err_t sc_rm_partition_free(sc_ipc_t ipc, sc_rm_pt_t pt); + +/*! + * This function returns the DID of a partition. + * + * @param[in] ipc IPC handle + * + * @return Returns the domain ID (DID) of the caller's partition. + * + * The DID is a SoC-specific internal ID used by the HW resource + * protection mechanism. It is only required by clients when using the + * SEMA42 module as the DID is sometimes connected to the master ID. + */ +sc_rm_did_t sc_rm_get_did(sc_ipc_t ipc); + +/*! + * This function forces a partition to use a specific static DID. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to assign \a did + * @param[in] did static DID to assign + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if \a pt or \a did out of range, + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt, + * - SC_ERR_LOCKED if \a pt is locked + * + * Assumes no assigned resources or memory regions yet! The number of static + * DID is fixed by the SC at boot. + */ +sc_err_t sc_rm_partition_static(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_did_t did); + +/*! + * This function locks a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to lock + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a pt out of range, + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt + * + * If a partition is locked it cannot be freed, have resources/pads assigned + * to/from it, memory regions created/assigned, DID changed, or parent changed. + */ +sc_err_t sc_rm_partition_lock(sc_ipc_t ipc, sc_rm_pt_t pt); + +/*! + * This function gets the partition handle of the caller. + * + * @param[in] ipc IPC handle + * @param[out] pt return handle for caller's partition + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_rm_get_partition(sc_ipc_t ipc, sc_rm_pt_t *pt); + +/*! + * This function sets a new parent for a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition for which parent is to be + * changed + * @param[in] pt_parent handle of partition to set as parent + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt, + * - SC_ERR_LOCKED if either partition is locked + */ +sc_err_t sc_rm_set_parent(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_pt_t pt_parent); + +/*! + * This function moves all movable resources/pads owned by a source partition + * to a destination partition. It can be used to more quickly set up a new + * partition if a majority of the caller's resources are to be moved to a + * new partition. + * + * @param[in] ipc IPC handle + * @param[in] pt_src handle of partition from which resources should + * be moved from + * @param[in] pt_dst handle of partition to which resources should be + * moved to + * @param[in] move_rsrc boolean to indicate if resources should be moved + * @param[in] move_pads boolean to indicate if pads should be moved + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * By default, all resources are movable. This can be changed using the + * sc_rm_set_resource_movable() function. Note all masters defaulted to SMMU + * bypass. + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not \a pt_src or the + * parent of \a pt_src, + * - SC_ERR_LOCKED if either partition is locked + */ +sc_err_t sc_rm_move_all(sc_ipc_t ipc, sc_rm_pt_t pt_src, sc_rm_pt_t pt_dst, + sc_bool_t move_rsrc, sc_bool_t move_pads); + +/* @} */ + +/*! + * @name Resource Functions + * @{ + */ + +/*! + * This function assigns ownership of a resource to a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to which resource should be + * assigned + * @param[in] resource resource to assign + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * This action resets the resource's master and peripheral attributes. + * Privilege attribute will be PASSTHRU, security attribute will be + * ASSERT if the partition si secure and NEGATE if it is not, and + * masters will defaulted to SMMU bypass. Access permissions will reset + * to SEC_RW for the owning partition only for secure partitions, FULL for + * non-secure. DEfault is no access by other partitions. + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition or \a pt is locked + */ +sc_err_t sc_rm_assign_resource(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rsrc_t resource); + +/*! + * This function flags resources as movable or not. + * + * @param[in] ipc IPC handle + * @param[in] resource_fst first resource for which flag should be set + * @param[in] resource_lst last resource for which flag should be set + * @param[in] movable movable flag (SC_TRUE is movable) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if resources are out of range, + * - SC_ERR_NOACCESS if caller's partition is not a parent of a resource owner, + * - SC_ERR_LOCKED if the owning partition is locked + * + * This function is used to determine the set of resources that will be + * moved using the sc_rm_move_all() function. All resources are movable + * by default so this function is normally used to prevent a set of + * resources from moving. + */ +sc_err_t sc_rm_set_resource_movable(sc_ipc_t ipc, sc_rsrc_t resource_fst, + sc_rsrc_t resource_lst, sc_bool_t movable); + +/*! + * This function flags all of a subsystem's resources as movable + * or not. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to use to identify subsystem + * @param[in] movable movable flag (SC_TRUE is movable) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if a function argument is out of range + * + * Note \a resource is used to find the associated subsystem. Only + * resources owned by the caller are set. + */ +sc_err_t sc_rm_set_subsys_rsrc_movable(sc_ipc_t ipc, sc_rsrc_t resource, + sc_bool_t movable); + +/*! + * This function sets attributes for a resource which is a bus master (i.e. + * capable of DMA). + * + * @param[in] ipc IPC handle + * @param[in] resource master resource for which attributes should apply + * @param[in] sa security attribute + * @param[in] pa privilege attribute + * @param[in] smmu_bypass SMMU bypass mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not a parent of the resource owner, + * - SC_ERR_LOCKED if the owning partition is locked + * + * This function configures how the HW isolation will see bus transactions + * from the specified master. Note the security attribute will only be + * changed if the caller's partition is secure. + */ +sc_err_t sc_rm_set_master_attributes(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_spa_t sa, sc_rm_spa_t pa, + sc_bool_t smmu_bypass); + +/*! + * This function sets the StreamID for a resource which is a bus master (i.e. + * capable of DMA). + * + * @param[in] ipc IPC handle + * @param[in] resource master resource for which attributes should apply + * @param[in] sid StreamID + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition is locked + * + * This function configures the SID attribute associated with all bus transactions + * from this master. Note 0 is not a valid SID as it is reserved to indicate + * bypass. + */ +sc_err_t sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_sid_t sid); + +/*! + * This function sets access permissions for a peripheral resource. + * + * @param[in] ipc IPC handle + * @param[in] resource peripheral resource for which permissions should apply + * @param[in] pt handle of partition \a perm should by applied for + * @param[in] perm permissions to apply to \a resource for \a pt + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition is locked + * - SC_ERR_LOCKED if the \a pt is confidential and the caller isn't \a pt + * + * This function configures how the HW isolation will restrict access to a + * peripheral based on the attributes of a transaction from bus master. + */ +sc_err_t sc_rm_set_peripheral_permissions(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_pt_t pt, sc_rm_perm_t perm); + +/*! + * This function gets ownership status of a resource. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to check + * + * @return Returns a boolean (SC_TRUE if caller's partition owns the resource). + * + * If \a resource is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource); + +/*! + * This function is used to test if a resource is a bus master. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to check + * + * @return Returns a boolean (SC_TRUE if the resource is a bus master). + * + * If \a resource is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_resource_master(sc_ipc_t ipc, sc_rsrc_t resource); + +/*! + * This function is used to test if a resource is a peripheral. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to check + * + * @return Returns a boolean (SC_TRUE if the resource is a peripheral). + * + * If \a resource is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_resource_peripheral(sc_ipc_t ipc, sc_rsrc_t resource); + +/*! + * This function is used to obtain info about a resource. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to inquire about + * @param[out] sid pointer to return StreamID + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a resource is out of range + */ +sc_err_t sc_rm_get_resource_info(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_sid_t *sid); + +/* @} */ + +/*! + * @name Memory Region Functions + * @{ + */ + +/*! + * This function requests that the SC create a new memory region. + * + * @param[in] ipc IPC handle + * @param[out] mr return handle for region; used for + * subsequent function calls + * associated with this region + * @param[in] addr_start start address of region (physical) + * @param[in] addr_end end address of region (physical) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if the new memory region is misaligned, + * - SC_ERR_LOCKED if caller's partition is locked, + * - SC_ERR_PARM if the new memory region spans multiple existing regions, + * - SC_ERR_NOACCESS if caller's partition does not own the memory containing + * the new region, + * - SC_ERR_UNAVAILABLE if memory region table is full (no more allocation + * space) + * + * The area covered by the memory region must currently be owned by the caller. + * By default, the new region will have access permission set to allow the + * caller to access. + */ +sc_err_t sc_rm_memreg_alloc(sc_ipc_t ipc, sc_rm_mr_t *mr, + sc_faddr_t addr_start, sc_faddr_t addr_end); + +/*! + * This function requests that the SC split a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region to split + * @param[out] mr_ret return handle for new region; used for + * subsequent function calls + * associated with this region + * @param[in] addr_start start address of region (physical) + * @param[in] addr_end end address of region (physical) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if the new memory region is not start/end part of mr, + * - SC_ERR_LOCKED if caller's partition is locked, + * - SC_ERR_PARM if the new memory region spans multiple existing regions, + * - SC_ERR_NOACCESS if caller's partition does not own the memory containing + * the new region, + * - SC_ERR_UNAVAILABLE if memory region table is full (no more allocation + * space) + * + * Note the new region must start or end on the split region. + */ +sc_err_t sc_rm_memreg_split(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_rm_mr_t *mr_ret, sc_faddr_t addr_start, + sc_faddr_t addr_end); + +/*! + * This function frees a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region to free + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a mr out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not a parent of \a mr, + * - SC_ERR_LOCKED if the owning partition of \a mr is locked + */ +sc_err_t sc_rm_memreg_free(sc_ipc_t ipc, sc_rm_mr_t mr); + +/*! + * Internal SC function to find a memory region. + * + * @see sc_rm_find_memreg(). + */ +/*! + * This function finds a memory region. + * + * @param[in] ipc IPC handle + * @param[out] mr return handle for region; used for + * subsequent function calls + * associated with this region + * @param[in] addr_start start address of region to search for + * @param[in] addr_end end address of region to search for + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOTFOUND if region not found, + * + * Searches only for regions owned by the caller. Finds first + * region containing the range specified. + */ +sc_err_t sc_rm_find_memreg(sc_ipc_t ipc, sc_rm_mr_t *mr, + sc_faddr_t addr_start, sc_faddr_t addr_end); + +/*! + * This function assigns ownership of a memory region. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to which memory region + * should be assigned + * @param[in] mr handle of memory region to assign + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the \a mr owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition or \a pt is locked + */ +sc_err_t sc_rm_assign_memreg(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_mr_t mr); + +/*! + * This function sets access permissions for a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region for which permissions + * should apply + * @param[in] pt handle of partition \a perm should by + * applied for + * @param[in] perm permissions to apply to \a mr for \a pt + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the region owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition is locked + * - SC_ERR_LOCKED if the \a pt is confidential and the caller isn't \a pt + * + * This function configures how the HW isolation will restrict access to a + * memory region based on the attributes of a transaction from bus master. + */ +sc_err_t sc_rm_set_memreg_permissions(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_rm_pt_t pt, sc_rm_perm_t perm); + +/*! + * This function gets ownership status of a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region to check + * + * @return Returns a boolean (SC_TRUE if caller's partition owns the + * memory region). + * + * If \a mr is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr); + +/*! + * This function is used to obtain info about a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region to inquire about + * @param[out] addr_start pointer to return start address + * @param[out] addr_end pointer to return end address + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a mr is out of range + */ +sc_err_t sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_faddr_t *addr_start, sc_faddr_t *addr_end); + +/* @} */ + +/*! + * @name Pad Functions + * @{ + */ + +/*! + * This function assigns ownership of a pad to a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to which pad should + * be assigned + * @param[in] pad pad to assign + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition or \a pt is locked + */ +sc_err_t sc_rm_assign_pad(sc_ipc_t ipc, sc_rm_pt_t pt, sc_pad_t pad); + +/*! + * This function flags pads as movable or not. + * + * @param[in] ipc IPC handle + * @param[in] pad_fst first pad for which flag should be set + * @param[in] pad_lst last pad for which flag should be set + * @param[in] movable movable flag (SC_TRUE is movable) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if pads are out of range, + * - SC_ERR_NOACCESS if caller's partition is not a parent of a pad owner, + * - SC_ERR_LOCKED if the owning partition is locked + * + * This function is used to determine the set of pads that will be + * moved using the sc_rm_move_all() function. All pads are movable + * by default so this function is normally used to prevent a set of + * pads from moving. + */ +sc_err_t sc_rm_set_pad_movable(sc_ipc_t ipc, sc_pad_t pad_fst, + sc_pad_t pad_lst, sc_bool_t movable); + +/*! + * This function gets ownership status of a pad. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to check + * + * @return Returns a boolean (SC_TRUE if caller's partition owns the pad). + * + * If \a pad is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_pad_owned(sc_ipc_t ipc, sc_pad_t pad); + +/* @} */ + +/*! + * @name Debug Functions + * @{ + */ + +/*! + * This function dumps the RM state for debug. + * + * @param[in] ipc IPC handle + */ +void sc_rm_dump(sc_ipc_t ipc); + +/* @} */ + +#endif /* SCI_RM_API_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h new file mode 100644 index 0000000..f8423ab --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2019 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing the public API for the System Controller (SC) + * Timer function. + * + * @addtogroup TIMER_SVC (SVC) Timer Service + * + * Module for the Timer service. This includes support for the watchdog, RTC, + * and system counter. Note every resource partition has a watchdog it can + * use. + * + * @{ + */ + +#ifndef SC_TIMER_API_H +#define SC_TIMER_API_H + +/* Includes */ + +#include + +/* Defines */ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_TIMER_ACTION_W 3U /* Width of sc_timer_wdog_action_t */ +/*@}*/ + +/*! + * @name Defines for sc_timer_wdog_action_t + */ +/*@{*/ +#define SC_TIMER_WDOG_ACTION_PARTITION 0U /* Reset partition */ +#define SC_TIMER_WDOG_ACTION_WARM 1U /* Warm reset system */ +#define SC_TIMER_WDOG_ACTION_COLD 2U /* Cold reset system */ +#define SC_TIMER_WDOG_ACTION_BOARD 3U /* Reset board */ +#define SC_TIMER_WDOG_ACTION_IRQ 4U /* Only generate IRQs */ +/*@}*/ + +/* Types */ + +/*! + * This type is used to configure the watchdog action. + */ +typedef uint8_t sc_timer_wdog_action_t; + +/*! + * This type is used to declare a watchdog time value in milliseconds. + */ +typedef uint32_t sc_timer_wdog_time_t; + +/* Functions */ + +/*! + * @name Watchdog Functions + * @{ + */ + +/*! + * This function sets the watchdog timeout in milliseconds. If not + * set then the timeout defaults to the max. Once locked this value + * cannot be changed. + * + * @param[in] ipc IPC handle + * @param[in] timeout timeout period for the watchdog + * + * @return Returns an error code (SC_ERR_NONE = success, SC_ERR_LOCKED + * = locked). + */ +sc_err_t sc_timer_set_wdog_timeout(sc_ipc_t ipc, sc_timer_wdog_time_t timeout); + +/*! + * This function sets the watchdog pre-timeout in milliseconds. If not + * set then the pre-timeout defaults to the max. Once locked this value + * cannot be changed. + * + * @param[in] ipc IPC handle + * @param[in] pre_timeout pre-timeout period for the watchdog + * + * When the pre-timeout expires an IRQ will be generated. Note this timeout + * clears when the IRQ is triggered. An IRQ is generated for the failing + * partition and all of its child partitions. + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_timer_set_wdog_pre_timeout(sc_ipc_t ipc, + sc_timer_wdog_time_t pre_timeout); + +/*! + * This function starts the watchdog. + * + * @param[in] ipc IPC handle + * @param[in] lock boolean indicating the lock status + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * If \a lock is set then the watchdog cannot be stopped or the timeout + * period changed. + */ +sc_err_t sc_timer_start_wdog(sc_ipc_t ipc, sc_bool_t lock); + +/*! + * This function stops the watchdog if it is not locked. + * + * @param[in] ipc IPC handle + * + * @return Returns an error code (SC_ERR_NONE = success, SC_ERR_LOCKED + * = locked). + */ +sc_err_t sc_timer_stop_wdog(sc_ipc_t ipc); + +/*! + * This function pings (services, kicks) the watchdog resetting the time + * before expiration back to the timeout. + * + * @param[in] ipc IPC handle + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_timer_ping_wdog(sc_ipc_t ipc); + +/*! + * This function gets the status of the watchdog. All arguments are + * in milliseconds. + * + * @param[in] ipc IPC handle + * @param[out] timeout pointer to return the timeout + * @param[out] max_timeout pointer to return the max timeout + * @param[out] remaining_time pointer to return the time remaining + * until trigger + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_timer_get_wdog_status(sc_ipc_t ipc, + sc_timer_wdog_time_t *timeout, + sc_timer_wdog_time_t *max_timeout, + sc_timer_wdog_time_t *remaining_time); + +/*! + * This function gets the status of the watchdog of a partition. All + * arguments are in milliseconds. + * + * @param[in] ipc IPC handle + * @param[in] pt partition to query + * @param[out] enb pointer to return enable status + * @param[out] timeout pointer to return the timeout + * @param[out] remaining_time pointer to return the time remaining + * until trigger + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_timer_pt_get_wdog_status(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_bool_t *enb, + sc_timer_wdog_time_t *timeout, + sc_timer_wdog_time_t *remaining_time); + +/*! + * This function configures the action to be taken when a watchdog + * expires. + * + * @param[in] ipc IPC handle + * @param[in] pt partition to affect + * @param[in] action action to take + * + * Default action is inherited from the parent. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid parameters, + * - SC_ERR_NOACCESS if caller's partition is not the SYSTEM owner, + * - SC_ERR_LOCKED if the watchdog is locked + */ +sc_err_t sc_timer_set_wdog_action(sc_ipc_t ipc, + sc_rm_pt_t pt, sc_timer_wdog_action_t action); + +/* @} */ + +/*! + * @name Real-Time Clock (RTC) Functions + * @{ + */ + +/*! + * This function sets the RTC time. Only the owner of the SC_R_SYSTEM + * resource can set the time. + * + * @param[in] ipc IPC handle + * @param[in] year year (min 1970) + * @param[in] mon month (1-12) + * @param[in] day day of the month (1-31) + * @param[in] hour hour (0-23) + * @param[in] min minute (0-59) + * @param[in] sec second (0-59) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid time/date parameters, + * - SC_ERR_NOACCESS if caller's partition is not the SYSTEM owner + */ +sc_err_t sc_timer_set_rtc_time(sc_ipc_t ipc, uint16_t year, uint8_t mon, + uint8_t day, uint8_t hour, uint8_t min, + uint8_t sec); + +/*! + * This function gets the RTC time. + * + * @param[in] ipc IPC handle + * @param[out] year pointer to return year (min 1970) + * @param[out] mon pointer to return month (1-12) + * @param[out] day pointer to return day of the month (1-31) + * @param[out] hour pointer to return hour (0-23) + * @param[out] min pointer to return minute (0-59) + * @param[out] sec pointer to return second (0-59) + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_timer_get_rtc_time(sc_ipc_t ipc, uint16_t *year, uint8_t *mon, + uint8_t *day, uint8_t *hour, uint8_t *min, + uint8_t *sec); + +/*! + * This function gets the RTC time in seconds since 1/1/1970. + * + * @param[in] ipc IPC handle + * @param[out] sec pointer to return second + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_timer_get_rtc_sec1970(sc_ipc_t ipc, uint32_t *sec); + +/*! + * This function sets the RTC alarm. + * + * @param[in] ipc IPC handle + * @param[in] year year (min 1970) + * @param[in] mon month (1-12) + * @param[in] day day of the month (1-31) + * @param[in] hour hour (0-23) + * @param[in] min minute (0-59) + * @param[in] sec second (0-59) + * + * Note this alarm setting clears when the alarm is triggered. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid time/date parameters + */ +sc_err_t sc_timer_set_rtc_alarm(sc_ipc_t ipc, uint16_t year, uint8_t mon, + uint8_t day, uint8_t hour, uint8_t min, + uint8_t sec); + +/*! + * This function sets the RTC alarm (periodic mode). + * + * @param[in] ipc IPC handle + * @param[in] sec period in seconds + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid time/date parameters + */ +sc_err_t sc_timer_set_rtc_periodic_alarm(sc_ipc_t ipc, uint32_t sec); + +/*! + * This function cancels the RTC alarm. + * + * @param[in] ipc IPC handle + * + * Note this alarm setting clears when the alarm is triggered. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid time/date parameters + */ +sc_err_t sc_timer_cancel_rtc_alarm(sc_ipc_t ipc); + +/*! + * This function sets the RTC calibration value. Only the owner of the SC_R_SYSTEM + * resource can set the calibration. + * + * @param[in] ipc IPC handle + * @param[in] count calbration count (-16 to 15) + * + * The calibration value is a 5-bit value including the sign bit, which is + * implemented in 2's complement. It is added or subtracted from the RTC on + * a perdiodic basis, once per 32768 cycles of the RTC clock. + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_timer_set_rtc_calb(sc_ipc_t ipc, int8_t count); + +/* @} */ + +/*! + * @name System Counter (SYSCTR) Functions + * @{ + */ + +/*! + * This function sets the SYSCTR alarm. + * + * @param[in] ipc IPC handle + * @param[in] ticks number of 8MHz cycles + * + * Note this alarm setting clears when the alarm is triggered. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid time/date parameters + */ +sc_err_t sc_timer_set_sysctr_alarm(sc_ipc_t ipc, uint64_t ticks); + +/*! + * This function sets the SYSCTR alarm (periodic mode). + * + * @param[in] ipc IPC handle + * @param[in] ticks number of 8MHz cycles + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid time/date parameters + */ +sc_err_t sc_timer_set_sysctr_periodic_alarm(sc_ipc_t ipc, uint64_t ticks); + +/*! + * This function cancels the SYSCTR alarm. + * + * @param[in] ipc IPC handle + * + * Note this alarm setting clears when the alarm is triggered. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid time/date parameters + */ +sc_err_t sc_timer_cancel_sysctr_alarm(sc_ipc_t ipc); + +/* @} */ + +#endif /* SC_TIMER_API_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/lpuart_console.S b/arm-trusted-firmware/plat/imx/common/lpuart_console.S new file mode 100644 index 0000000..ff01e35 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/lpuart_console.S @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "imx8_lpuart.h" + + .globl console_lpuart_register + .globl console_lpuart_init + .globl console_lpuart_putc + .globl console_lpuart_getc + .globl console_lpuart_flush + +func console_lpuart_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_lpuart_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register lpuart putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_lpuart_register + +func console_lpuart_init + mov w0, #1 + ret +endfunc console_lpuart_init + +func console_lpuart_putc + ldr x1, [x1, #CONSOLE_T_BASE] + cbz x1, putc_error + /* Prepare '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f +1: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #STAT] + tbz w2, #23, 1b + mov w2, #0xD + str w2, [x1, #DATA] +2: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #STAT] + tbz w2, #23, 2b + str w0, [x1, #DATA] + ret +putc_error: + mov w0, #-1 + ret +endfunc console_lpuart_putc + +func console_lpuart_getc + ldr x0, [x0, #CONSOLE_T_BASE] + cbz x0, getc_error + /* Check if the receive FIFO state */ + ret +getc_error: + mov w0, #-1 + ret +endfunc console_lpuart_getc + +func console_lpuart_flush + ret +endfunc console_lpuart_flush diff --git a/arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c b/arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c new file mode 100644 index 0000000..150e81e --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* the GICv3 driver only needs to be initialized in EL3 */ +uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t g01s_interrupt_props[] = { + INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, GIC_INTR_CFG_LEVEL), +#if SDEI_SUPPORT + INTR_PROP_DESC(PLAT_SDEI_SGI_PRIVATE, PLAT_SDEI_NORMAL_PRI, + INTR_GROUP0, GIC_INTR_CFG_LEVEL), +#endif +}; + +static unsigned int plat_imx_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +const gicv3_driver_data_t arm_gic_data = { + .gicd_base = PLAT_GICD_BASE, + .gicr_base = PLAT_GICR_BASE, + .interrupt_props = g01s_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g01s_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = plat_imx_mpidr_to_core_pos, +}; + +void plat_gic_driver_init(void) +{ + /* + * the GICv3 driver is initialized in EL3 and does not need + * to be initialized again in S-EL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ +#if IMAGE_BL31 + gicv3_driver_init(&arm_gic_data); +#endif +} + +static __inline void plat_gicr_exit_sleep(void) +{ + unsigned int val = mmio_read_32(PLAT_GICR_BASE + GICR_WAKER); + + /* + * ProcessorSleep bit can ONLY be set to zero when + * Quiescent bit and Sleep bit are both zero, so + * need to make sure Quiescent bit and Sleep bit + * are zero before clearing ProcessorSleep bit. + */ + if (val & WAKER_QSC_BIT) { + mmio_write_32(PLAT_GICR_BASE + GICR_WAKER, val & ~WAKER_SL_BIT); + /* Wait till the WAKER_QSC_BIT changes to 0 */ + while ((mmio_read_32(PLAT_GICR_BASE + GICR_WAKER) & WAKER_QSC_BIT) != 0U) + ; + } +} + +void plat_gic_init(void) +{ + plat_gicr_exit_sleep(); + 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()); +} + +void plat_gic_save(unsigned int proc_num, struct plat_gic_ctx *ctx) +{ + /* save the gic rdist/dist context */ + for (int i = 0; i < PLATFORM_CORE_COUNT; i++) + gicv3_rdistif_save(i, &ctx->rdist_ctx[i]); + gicv3_distif_save(&ctx->dist_ctx); +} + +void plat_gic_restore(unsigned int proc_num, struct plat_gic_ctx *ctx) +{ + /* restore the gic rdist/dist context */ + gicv3_distif_init_restore(&ctx->dist_ctx); + for (int i = 0; i < PLATFORM_CORE_COUNT; i++) + gicv3_rdistif_init_restore(i, &ctx->rdist_ctx[i]); +} diff --git a/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c b/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c new file mode 100644 index 0000000..66e956d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "imx8_mu.h" + +void MU_Resume(uint32_t base) +{ + uint32_t reg, i; + + reg = mmio_read_32(base + MU_ACR_OFFSET1); + /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */ + reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1 + | MU_CR_GIRn_MASK1 | MU_CR_Fn_MASK1); + mmio_write_32(base + MU_ACR_OFFSET1, reg); + + /* Enable all RX interrupts */ + for (i = 0; i < MU_RR_COUNT; i++) + MU_EnableRxFullInt(base, i); +} + +void MU_EnableRxFullInt(uint32_t base, uint32_t index) +{ + uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1); + + reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1); + reg |= MU_CR_RIE0_MASK1 >> index; + mmio_write_32(base + MU_ACR_OFFSET1, reg); +} + +void MU_EnableGeneralInt(uint32_t base, uint32_t index) +{ + uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1); + + reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1); + reg |= MU_CR_GIE0_MASK1 >> index; + mmio_write_32(base + MU_ACR_OFFSET1, reg); +} + +void MU_SendMessage(uint32_t base, uint32_t regIndex, uint32_t msg) +{ + uint32_t mask = MU_SR_TE0_MASK1 >> regIndex; + + /* Wait TX register to be empty. */ + while (!(mmio_read_32(base + MU_ASR_OFFSET1) & mask)) + ; + mmio_write_32(base + MU_ATR0_OFFSET1 + (regIndex * 4), msg); +} + +void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg) +{ + uint32_t mask = MU_SR_RF0_MASK1 >> regIndex; + + /* Wait RX register to be full. */ + while (!(mmio_read_32(base + MU_ASR_OFFSET1) & mask)) + ; + *msg = mmio_read_32(base + MU_ARR0_OFFSET1 + (regIndex * 4)); +} + +void MU_Init(uint32_t base) +{ + uint32_t reg; + + reg = mmio_read_32(base + MU_ACR_OFFSET1); + /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */ + reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1 + | MU_CR_GIRn_MASK1 | MU_CR_Fn_MASK1); + mmio_write_32(base + MU_ACR_OFFSET1, reg); +} diff --git a/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h b/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h new file mode 100644 index 0000000..7885219 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#define MU_ATR0_OFFSET1 0x0 +#define MU_ARR0_OFFSET1 0x10 +#define MU_ASR_OFFSET1 0x20 +#define MU_ACR_OFFSET1 0x24 +#define MU_TR_COUNT1 4 +#define MU_RR_COUNT1 4 + +#define MU_CR_GIEn_MASK1 (0xFu << 28) +#define MU_CR_RIEn_MASK1 (0xF << 24) +#define MU_CR_TIEn_MASK1 (0xF << 20) +#define MU_CR_GIRn_MASK1 (0xF << 16) +#define MU_CR_NMI_MASK1 (1 << 3) +#define MU_CR_Fn_MASK1 0x7 + +#define MU_SR_TE0_MASK1 (1 << 23) +#define MU_SR_RF0_MASK1 (1 << 27) +#define MU_CR_RIE0_MASK1 (1 << 27) +#define MU_CR_GIE0_MASK1 (1U << 31) + +#define MU_TR_COUNT 4 +#define MU_RR_COUNT 4 + +void MU_Init(uint32_t base); +void MU_SendMessage(uint32_t base, uint32_t regIndex, uint32_t msg); +void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg); +void MU_EnableGeneralInt(uint32_t base, uint32_t index); +void MU_EnableRxFullInt(uint32_t base, uint32_t index); +void MU_Resume(uint32_t base); diff --git a/arm-trusted-firmware/plat/imx/common/sci/ipc.c b/arm-trusted-firmware/plat/imx/common/sci/ipc.c new file mode 100644 index 0000000..5769119 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/ipc.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include "imx8_mu.h" + +sc_ipc_t ipc_handle; + +DEFINE_BAKERY_LOCK(sc_ipc_bakery_lock); +#define sc_ipc_lock_init() bakery_lock_init(&sc_ipc_bakery_lock) +#define sc_ipc_lock() bakery_lock_get(&sc_ipc_bakery_lock) +#define sc_ipc_unlock() bakery_lock_release(&sc_ipc_bakery_lock) + +void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp) +{ + sc_ipc_lock(); + + sc_ipc_write(ipc, msg); + if (!no_resp) + sc_ipc_read(ipc, msg); + + sc_ipc_unlock(); +} + +sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id) +{ + uint32_t base = id; + uint32_t i; + + /* Get MU base associated with IPC channel */ + if ((ipc == NULL) || (base == 0)) + return SC_ERR_IPC; + + sc_ipc_lock_init(); + + /* Init MU */ + MU_Init(base); + + /* Enable all RX interrupts */ + for (i = 0; i < MU_RR_COUNT; i++) { + MU_EnableRxFullInt(base, i); + } + + /* Return MU address as handle */ + *ipc = (sc_ipc_t) id; + + return SC_ERR_NONE; +} + +void sc_ipc_close(sc_ipc_t ipc) +{ + uint32_t base = ipc; + + if (base != 0) + MU_Init(base); +} + +void sc_ipc_read(sc_ipc_t ipc, void *data) +{ + uint32_t base = ipc; + sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data; + uint8_t count = 0; + + /* Check parms */ + if ((base == 0) || (msg == NULL)) + return; + + /* Read first word */ + MU_ReceiveMsg(base, 0, (uint32_t *) msg); + count++; + + /* Check size */ + if (msg->size > SC_RPC_MAX_MSG) { + *((uint32_t *) msg) = 0; + return; + } + + /* Read remaining words */ + while (count < msg->size) { + MU_ReceiveMsg(base, count % MU_RR_COUNT, + &(msg->DATA.u32[count - 1])); + count++; + } +} + +void sc_ipc_write(sc_ipc_t ipc, void *data) +{ + sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data; + uint32_t base = ipc; + uint8_t count = 0; + + /* Check parms */ + if ((base == 0) || (msg == NULL)) + return; + + /* Check size */ + if (msg->size > SC_RPC_MAX_MSG) + return; + + /* Write first word */ + MU_SendMessage(base, 0, *((uint32_t *) msg)); + count++; + + /* Write remaining words */ + while (count < msg->size) { + MU_SendMessage(base, count % MU_TR_COUNT, + msg->DATA.u32[count - 1]); + count++; + } +} + diff --git a/arm-trusted-firmware/plat/imx/common/sci/sci_api.mk b/arm-trusted-firmware/plat/imx/common/sci/sci_api.mk new file mode 100644 index 0000000..92c7190 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/sci_api.mk @@ -0,0 +1,13 @@ +# +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL31_SOURCES += plat/imx/common/sci/ipc.c \ + plat/imx/common/sci/imx8_mu.c \ + plat/imx/common/sci/svc/pad/pad_rpc_clnt.c \ + plat/imx/common/sci/svc/pm/pm_rpc_clnt.c \ + plat/imx/common/sci/svc/rm/rm_rpc_clnt.c \ + plat/imx/common/sci/svc/timer/timer_rpc_clnt.c \ + plat/imx/common/sci/svc/misc/misc_rpc_clnt.c diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c new file mode 100644 index 0000000..080de6a --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * File containing client-side RPC functions for the MISC service. These + * functions are ported to clients that communicate to the SC. + * + * @addtogroup MISC_SVC + * @{ + */ + +/* Includes */ + +#include +#include +#include +#include +#include +#include "sci_misc_rpc.h" + +/* Local Defines */ + +/* Local Types */ + +/* Local Functions */ + +sc_err_t sc_misc_set_control(sc_ipc_t ipc, sc_rsrc_t resource, + sc_ctrl_t ctrl, uint32_t val) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_CONTROL; + RPC_U32(&msg, 0U) = (uint32_t)ctrl; + RPC_U32(&msg, 4U) = (uint32_t)val; + RPC_U16(&msg, 8U) = (uint16_t)resource; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_get_control(sc_ipc_t ipc, sc_rsrc_t resource, + sc_ctrl_t ctrl, uint32_t *val) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_GET_CONTROL; + RPC_U32(&msg, 0U) = (uint32_t)ctrl; + RPC_U16(&msg, 4U) = (uint16_t)resource; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (val != NULL) + *val = RPC_U32(&msg, 0U); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_set_max_dma_group(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_misc_dma_group_t max) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_MAX_DMA_GROUP; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)max; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_set_dma_group(sc_ipc_t ipc, sc_rsrc_t resource, + sc_misc_dma_group_t group) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_DMA_GROUP; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)group; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_seco_image_load(sc_ipc_t ipc, sc_faddr_t addr_src, + sc_faddr_t addr_dst, uint32_t len, + sc_bool_t fw) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_IMAGE_LOAD; + RPC_U32(&msg, 0U) = (uint32_t)(addr_src >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr_src; + RPC_U32(&msg, 8U) = (uint32_t)(addr_dst >> 32U); + RPC_U32(&msg, 12U) = (uint32_t)addr_dst; + RPC_U32(&msg, 16U) = (uint32_t)len; + RPC_U8(&msg, 20U) = (uint8_t)fw; + RPC_SIZE(&msg) = 7U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_seco_authenticate(sc_ipc_t ipc, + sc_misc_seco_auth_cmd_t cmd, sc_faddr_t addr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_AUTHENTICATE; + RPC_U32(&msg, 0U) = (uint32_t)(addr >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr; + RPC_U8(&msg, 8U) = (uint8_t)cmd; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_seco_fuse_write(sc_ipc_t ipc, sc_faddr_t addr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_FUSE_WRITE; + RPC_U32(&msg, 0U) = (uint32_t)(addr >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_seco_enable_debug(sc_ipc_t ipc, sc_faddr_t addr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_ENABLE_DEBUG; + RPC_U32(&msg, 0U) = (uint32_t)(addr >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_seco_forward_lifecycle(sc_ipc_t ipc, uint32_t lifecycle) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_FORWARD_LIFECYCLE; + RPC_U32(&msg, 0U) = (uint32_t)lifecycle; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_seco_return_lifecycle(sc_ipc_t ipc, sc_faddr_t addr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_RETURN_LIFECYCLE; + RPC_U32(&msg, 0U) = (uint32_t)(addr >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +void sc_misc_seco_build_info(sc_ipc_t ipc, uint32_t *version, uint32_t *commit) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_BUILD_INFO; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (version != NULL) + *version = RPC_U32(&msg, 0U); + + if (commit != NULL) + *commit = RPC_U32(&msg, 4U); +} + +sc_err_t sc_misc_seco_chip_info(sc_ipc_t ipc, uint16_t *lc, + uint16_t *monotonic, uint32_t *uid_l, + uint32_t *uid_h) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_CHIP_INFO; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (uid_l != NULL) + *uid_l = RPC_U32(&msg, 0U); + + if (uid_h != NULL) + *uid_h = RPC_U32(&msg, 4U); + + if (lc != NULL) + *lc = RPC_U16(&msg, 8U); + + if (monotonic != NULL) + *monotonic = RPC_U16(&msg, 10U); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +void sc_misc_debug_out(sc_ipc_t ipc, uint8_t ch) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_DEBUG_OUT; + RPC_U8(&msg, 0U) = (uint8_t)ch; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); +} + +sc_err_t sc_misc_waveform_capture(sc_ipc_t ipc, sc_bool_t enable) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_WAVEFORM_CAPTURE; + RPC_U8(&msg, 0U) = (uint8_t)enable; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +void sc_misc_build_info(sc_ipc_t ipc, uint32_t *build, uint32_t *commit) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_BUILD_INFO; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (build != NULL) + *build = RPC_U32(&msg, 0U); + + if (commit != NULL) + *commit = RPC_U32(&msg, 4U); +} + +void sc_misc_unique_id(sc_ipc_t ipc, uint32_t *id_l, uint32_t *id_h) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_UNIQUE_ID; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (id_l != NULL) + *id_l = RPC_U32(&msg, 0U); + + if (id_h != NULL) + *id_h = RPC_U32(&msg, 4U); +} + +sc_err_t sc_misc_set_ari(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rsrc_t resource_mst, uint16_t ari, sc_bool_t enable) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_ARI; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U16(&msg, 2U) = (uint16_t)resource_mst; + RPC_U16(&msg, 4U) = (uint16_t)ari; + RPC_U8(&msg, 6U) = (uint8_t)enable; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +void sc_misc_boot_status(sc_ipc_t ipc, sc_misc_boot_status_t status) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_BOOT_STATUS; + RPC_U8(&msg, 0U) = (uint8_t)status; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_TRUE); +} + +sc_err_t sc_misc_boot_done(sc_ipc_t ipc, sc_rsrc_t cpu) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_BOOT_DONE; + RPC_U16(&msg, 0U) = (uint16_t)cpu; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_otp_fuse_read(sc_ipc_t ipc, uint32_t word, uint32_t *val) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_OTP_FUSE_READ; + RPC_U32(&msg, 0U) = (uint32_t)word; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (val != NULL) + *val = RPC_U32(&msg, 0U); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_otp_fuse_write(sc_ipc_t ipc, uint32_t word, uint32_t val) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_OTP_FUSE_WRITE; + RPC_U32(&msg, 0U) = (uint32_t)word; + RPC_U32(&msg, 4U) = (uint32_t)val; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_set_temp(sc_ipc_t ipc, sc_rsrc_t resource, + sc_misc_temp_t temp, int16_t celsius, int8_t tenths) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_TEMP; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_I16(&msg, 2U) = (int16_t) celsius; + RPC_U8(&msg, 4U) = (uint8_t)temp; + RPC_I8(&msg, 5U) = (int8_t) tenths; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_misc_get_temp(sc_ipc_t ipc, sc_rsrc_t resource, + sc_misc_temp_t temp, int16_t *celsius, + int8_t *tenths) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_GET_TEMP; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)temp; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (celsius != NULL) + *celsius = RPC_I16(&msg, 0U); + + result = RPC_R8(&msg); + if (tenths != NULL) + *tenths = RPC_I8(&msg, 2U); + + return (sc_err_t)result; +} + +void sc_misc_get_boot_dev(sc_ipc_t ipc, sc_rsrc_t *dev) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_GET_BOOT_DEV; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (dev != NULL) + *dev = RPC_U16(&msg, 0U); +} + +void sc_misc_get_button_status(sc_ipc_t ipc, sc_bool_t *status) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC; + RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_GET_BUTTON_STATUS; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (status != NULL) + *status = RPC_U8(&msg, 0U); +} + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h new file mode 100644 index 0000000..03b1a51 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2019 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the MISC RPC implementation. + * + * @addtogroup MISC_SVC + * @{ + */ + +#ifndef SC_MISC_RPC_H +#define SC_MISC_RPC_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Defines for RPC MISC function calls + */ +/*@{*/ +#define MISC_FUNC_UNKNOWN 0 /* Unknown function */ +#define MISC_FUNC_SET_CONTROL 1U /* Index for misc_set_control() RPC call */ +#define MISC_FUNC_GET_CONTROL 2U /* Index for misc_get_control() RPC call */ +#define MISC_FUNC_SET_MAX_DMA_GROUP 4U /* Index for misc_set_max_dma_group() RPC call */ +#define MISC_FUNC_SET_DMA_GROUP 5U /* Index for misc_set_dma_group() RPC call */ +#define MISC_FUNC_SECO_IMAGE_LOAD 8U /* Index for misc_seco_image_load() RPC call */ +#define MISC_FUNC_SECO_AUTHENTICATE 9U /* Index for misc_seco_authenticate() RPC call */ +#define MISC_FUNC_SECO_FUSE_WRITE 20U /* Index for misc_seco_fuse_write() RPC call */ +#define MISC_FUNC_SECO_ENABLE_DEBUG 21U /* Index for misc_seco_enable_debug() RPC call */ +#define MISC_FUNC_SECO_FORWARD_LIFECYCLE 22U /* Index for misc_seco_forward_lifecycle() RPC call */ +#define MISC_FUNC_SECO_RETURN_LIFECYCLE 23U /* Index for misc_seco_return_lifecycle() RPC call */ +#define MISC_FUNC_SECO_BUILD_INFO 24U /* Index for misc_seco_build_info() RPC call */ +#define MISC_FUNC_SECO_CHIP_INFO 25U /* Index for misc_seco_chip_info() RPC call */ +#define MISC_FUNC_DEBUG_OUT 10U /* Index for misc_debug_out() RPC call */ +#define MISC_FUNC_WAVEFORM_CAPTURE 6U /* Index for misc_waveform_capture() RPC call */ +#define MISC_FUNC_BUILD_INFO 15U /* Index for misc_build_info() RPC call */ +#define MISC_FUNC_UNIQUE_ID 19U /* Index for misc_unique_id() RPC call */ +#define MISC_FUNC_SET_ARI 3U /* Index for misc_set_ari() RPC call */ +#define MISC_FUNC_BOOT_STATUS 7U /* Index for misc_boot_status() RPC call */ +#define MISC_FUNC_BOOT_DONE 14U /* Index for misc_boot_done() RPC call */ +#define MISC_FUNC_OTP_FUSE_READ 11U /* Index for misc_otp_fuse_read() RPC call */ +#define MISC_FUNC_OTP_FUSE_WRITE 17U /* Index for misc_otp_fuse_write() RPC call */ +#define MISC_FUNC_SET_TEMP 12U /* Index for misc_set_temp() RPC call */ +#define MISC_FUNC_GET_TEMP 13U /* Index for misc_get_temp() RPC call */ +#define MISC_FUNC_GET_BOOT_DEV 16U /* Index for misc_get_boot_dev() RPC call */ +#define MISC_FUNC_GET_BUTTON_STATUS 18U /* Index for misc_get_button_status() RPC call */ +/*@}*/ + +/* Types */ + +/* Functions */ + +/*! + * This function dispatches an incoming MISC RPC request. + * + * @param[in] caller_pt caller partition + * @param[in] msg pointer to RPC message + */ +void misc_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg); + +/*! + * This function translates and dispatches an MISC RPC request. + * + * @param[in] ipc IPC handle + * @param[in] msg pointer to RPC message + */ +void misc_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SC_MISC_RPC_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c new file mode 100644 index 0000000..319d469 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * File containing client-side RPC functions for the PAD service. These + * functions are ported to clients that communicate to the SC. + * + * @addtogroup PAD_SVC + * @{ + */ + +/* Includes */ + +#include + +#include +#include +#include +#include +#include "sci_pad_rpc.h" + +/* Local Defines */ + +/* Local Types */ + +/* Local Functions */ + +sc_err_t sc_pad_set_mux(sc_ipc_t ipc, sc_pad_t pad, + uint8_t mux, sc_pad_config_t config, sc_pad_iso_t iso) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_MUX; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)mux; + RPC_U8(&msg, 3U) = (uint8_t)config; + RPC_U8(&msg, 4U) = (uint8_t)iso; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_mux(sc_ipc_t ipc, sc_pad_t pad, + uint8_t *mux, sc_pad_config_t *config, + sc_pad_iso_t *iso) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_MUX; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mux != NULL) { + *mux = RPC_U8(&msg, 0U); + } + + if (config != NULL) { + *config = RPC_U8(&msg, 1U); + } + + if (iso != NULL) { + *iso = RPC_U8(&msg, 2U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t ctrl) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP; + RPC_U32(&msg, 0U) = (uint32_t)ctrl; + RPC_U16(&msg, 4U) = (uint16_t)pad; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t *ctrl) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (ctrl != NULL) { + *ctrl = RPC_U32(&msg, 0U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t wakeup) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_WAKEUP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)wakeup; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t *wakeup) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_WAKEUP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (wakeup != NULL) { + *wakeup = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t mux, + sc_pad_config_t config, sc_pad_iso_t iso, uint32_t ctrl, + sc_pad_wakeup_t wakeup) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_ALL; + RPC_U32(&msg, 0U) = (uint32_t)ctrl; + RPC_U16(&msg, 4U) = (uint16_t)pad; + RPC_U8(&msg, 6U) = (uint8_t)mux; + RPC_U8(&msg, 7U) = (uint8_t)config; + RPC_U8(&msg, 8U) = (uint8_t)iso; + RPC_U8(&msg, 9U) = (uint8_t)wakeup; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t *mux, + sc_pad_config_t *config, sc_pad_iso_t *iso, + uint32_t *ctrl, sc_pad_wakeup_t *wakeup) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_ALL; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (ctrl != NULL) { + *ctrl = RPC_U32(&msg, 0U); + } + + result = RPC_R8(&msg); + if (mux != NULL) { + *mux = RPC_U8(&msg, 4U); + } + + if (config != NULL) { + *config = RPC_U8(&msg, 5U); + } + + if (iso != NULL) { + *iso = RPC_U8(&msg, 6U); + } + + if (wakeup != NULL) { + *wakeup = RPC_U8(&msg, 7U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, uint32_t val) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET; + RPC_U32(&msg, 0U) = (uint32_t)val; + RPC_U16(&msg, 4U) = (uint16_t)pad; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (val != NULL) { + *val = RPC_U32(&msg, 0U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t dse, sc_pad_28fdsoi_ps_t ps) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)dse; + RPC_U8(&msg, 3U) = (uint8_t)ps; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t *dse, + sc_pad_28fdsoi_ps_t *ps) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (dse != NULL) { + *dse = RPC_U8(&msg, 0U); + } + + if (ps != NULL) { + *ps = RPC_U8(&msg, 1U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t dse, sc_bool_t hys, + sc_pad_28fdsoi_pus_t pus, sc_bool_t pke, + sc_bool_t pue) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI_HSIC; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)dse; + RPC_U8(&msg, 3U) = (uint8_t)pus; + RPC_U8(&msg, 4U) = (uint8_t)hys; + RPC_U8(&msg, 5U) = (uint8_t)pke; + RPC_U8(&msg, 6U) = (uint8_t)pue; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t *dse, sc_bool_t *hys, + sc_pad_28fdsoi_pus_t *pus, sc_bool_t *pke, + sc_bool_t *pue) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI_HSIC; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (dse != NULL) { + *dse = RPC_U8(&msg, 0U); + } + + if (pus != NULL) { + *pus = RPC_U8(&msg, 1U); + } + + if (hys != NULL) { + *hys = RPC_U8(&msg, 2U); + } + + if (pke != NULL) { + *pke = RPC_U8(&msg, 3U); + } + + if (pue != NULL) { + *pue = RPC_U8(&msg, 4U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad, + uint8_t compen, sc_bool_t fastfrz, + uint8_t rasrcp, uint8_t rasrcn, + sc_bool_t nasrc_sel, sc_bool_t psw_ovr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI_COMP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)compen; + RPC_U8(&msg, 3U) = (uint8_t)rasrcp; + RPC_U8(&msg, 4U) = (uint8_t)rasrcn; + RPC_U8(&msg, 5U) = (uint8_t)fastfrz; + RPC_U8(&msg, 6U) = (uint8_t)nasrc_sel; + RPC_U8(&msg, 7U) = (uint8_t)psw_ovr; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad, + uint8_t *compen, sc_bool_t *fastfrz, + uint8_t *rasrcp, uint8_t *rasrcn, + sc_bool_t *nasrc_sel, sc_bool_t *compok, + uint8_t *nasrc, sc_bool_t *psw_ovr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI_COMP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (compen != NULL) { + *compen = RPC_U8(&msg, 0U); + } + + if (rasrcp != NULL) { + *rasrcp = RPC_U8(&msg, 1U); + } + + if (rasrcn != NULL) { + *rasrcn = RPC_U8(&msg, 2U); + } + + if (nasrc != NULL) { + *nasrc = RPC_U8(&msg, 3U); + } + + if (fastfrz != NULL) { + *fastfrz = RPC_U8(&msg, 4U); + } + + if (nasrc_sel != NULL) { + *nasrc_sel = RPC_U8(&msg, 5U); + } + + if (compok != NULL) { + *compok = RPC_U8(&msg, 6U); + } + + if (psw_ovr != NULL) { + *psw_ovr = RPC_U8(&msg, 7U); + } + + return (sc_err_t)result; +} + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h new file mode 100644 index 0000000..8e9c4bb --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the PAD RPC implementation. + * + * @addtogroup PAD_SVC + * @{ + */ + +#ifndef SCI_PAD_RPC_H +#define SCI_PAD_RPC_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Defines for RPC PAD function calls + */ +/*@{*/ +#define PAD_FUNC_UNKNOWN 0 /* Unknown function */ +#define PAD_FUNC_SET_MUX 1U /* Index for pad_set_mux() RPC call */ +#define PAD_FUNC_GET_MUX 6U /* Index for pad_get_mux() RPC call */ +#define PAD_FUNC_SET_GP 2U /* Index for pad_set_gp() RPC call */ +#define PAD_FUNC_GET_GP 7U /* Index for pad_get_gp() RPC call */ +#define PAD_FUNC_SET_WAKEUP 4U /* Index for pad_set_wakeup() RPC call */ +#define PAD_FUNC_GET_WAKEUP 9U /* Index for pad_get_wakeup() RPC call */ +#define PAD_FUNC_SET_ALL 5U /* Index for pad_set_all() RPC call */ +#define PAD_FUNC_GET_ALL 10U /* Index for pad_get_all() RPC call */ +#define PAD_FUNC_SET 15U /* Index for pad_set() RPC call */ +#define PAD_FUNC_GET 16U /* Index for pad_get() RPC call */ +#define PAD_FUNC_SET_GP_28FDSOI 11U /* Index for pad_set_gp_28fdsoi() RPC call */ +#define PAD_FUNC_GET_GP_28FDSOI 12U /* Index for pad_get_gp_28fdsoi() RPC call */ +#define PAD_FUNC_SET_GP_28FDSOI_HSIC 3U /* Index for pad_set_gp_28fdsoi_hsic() RPC call */ +#define PAD_FUNC_GET_GP_28FDSOI_HSIC 8U /* Index for pad_get_gp_28fdsoi_hsic() RPC call */ +#define PAD_FUNC_SET_GP_28FDSOI_COMP 13U /* Index for pad_set_gp_28fdsoi_comp() RPC call */ +#define PAD_FUNC_GET_GP_28FDSOI_COMP 14U /* Index for pad_get_gp_28fdsoi_comp() RPC call */ +/*@}*/ + +/* Types */ + +/* Functions */ + +/*! + * This function dispatches an incoming PAD RPC request. + * + * @param[in] caller_pt caller partition + * @param[in] msg pointer to RPC message + */ +void pad_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg); + +/*! + * This function translates and dispatches an PAD RPC request. + * + * @param[in] ipc IPC handle + * @param[in] msg pointer to RPC message + */ +void pad_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SCI_PAD_RPC_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c new file mode 100644 index 0000000..66a57a1 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * File containing client-side RPC functions for the PM service. These + * functions are ported to clients that communicate to the SC. + * + * @addtogroup PM_SVC + * @{ + */ + +/* Includes */ + +#include + +#include +#include +#include +#include + +#include "sci_pm_rpc.h" + +/* Local Defines */ + +/* Local Types */ + +/* Local Functions */ + +sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_SYS_POWER_MODE; + RPC_U8(&msg, 0U) = (uint8_t)mode; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_power_mode_t mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_PARTITION_POWER_MODE; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)mode; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_power_mode_t *mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_SYS_POWER_MODE; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mode != NULL) { + *mode = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_RESOURCE_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)mode; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t *mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_RESOURCE_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mode != NULL) { + *mode = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_LOW_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)mode; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode, + sc_pm_wake_src_t wake_src) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_CPU_LOW_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)mode; + RPC_U8(&msg, 3U) = (uint8_t)wake_src; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource, + sc_faddr_t address) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME_ADDR; + RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)address; + RPC_U16(&msg, 8U) = (uint16_t)resource; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource, + sc_bool_t isPrimary, sc_faddr_t address) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME; + RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)address; + RPC_U16(&msg, 8U) = (uint16_t)resource; + RPC_U8(&msg, 10U) = (uint8_t)isPrimary; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_sys_if_t sys_if, + sc_pm_power_mode_t hpm, + sc_pm_power_mode_t lpm) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_SYS_IF_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)sys_if; + RPC_U8(&msg, 3U) = (uint8_t)hpm; + RPC_U8(&msg, 4U) = (uint8_t)lpm; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clock_rate_t *rate) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_RATE; + RPC_U32(&msg, 0U) = *(uint32_t *)rate; + RPC_U16(&msg, 4U) = (uint16_t)resource; + RPC_U8(&msg, 6U) = (uint8_t)clk; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + *rate = RPC_U32(&msg, 0U); + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clock_rate_t *rate) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_RATE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)clk; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (rate != NULL) { + *rate = RPC_U32(&msg, 0U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CLOCK_ENABLE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)clk; + RPC_U8(&msg, 3U) = (uint8_t)enable; + RPC_U8(&msg, 4U) = (uint8_t)autog; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clk_parent_t parent) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_PARENT; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)clk; + RPC_U8(&msg, 3U) = (uint8_t)parent; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clk_parent_t *parent) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_PARENT; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)clk; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (parent != NULL) { + *parent = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET; + RPC_U8(&msg, 0U) = (uint8_t)type; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET_REASON; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (reason != NULL) { + *reason = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_rsrc_t resource_cpu, sc_faddr_t boot_addr, + sc_rsrc_t resource_mu, sc_rsrc_t resource_dev) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_BOOT; + RPC_U32(&msg, 0U) = (uint32_t)(boot_addr >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)boot_addr; + RPC_U16(&msg, 8U) = (uint16_t)resource_cpu; + RPC_U16(&msg, 10U) = (uint16_t)resource_mu; + RPC_U16(&msg, 12U) = (uint16_t)resource_dev; + RPC_U8(&msg, 14U) = (uint8_t)pt; + RPC_SIZE(&msg) = 5U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT; + RPC_U8(&msg, 0U) = (uint8_t)type; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_TRUE); + + return; +} + +sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_reset_type_t type) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT_PARTITION; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)type; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, + sc_faddr_t address) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CPU_START; + RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)address; + RPC_U16(&msg, 8U) = (uint16_t)resource; + RPC_U8(&msg, 10U) = (uint8_t)enable; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h new file mode 100644 index 0000000..8bad3c7 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the PM RPC implementation. + * + * @addtogroup PM_SVC + * @{ + */ + +#ifndef SCI_PM_RPC_H +#define SCI_PM_RPC_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Defines for RPC PM function calls + */ +/*@{*/ +#define PM_FUNC_UNKNOWN 0 /* Unknown function */ +#define PM_FUNC_SET_SYS_POWER_MODE 19U /* Index for pm_set_sys_power_mode() RPC call */ +#define PM_FUNC_SET_PARTITION_POWER_MODE 1U /* Index for pm_set_partition_power_mode() RPC call */ +#define PM_FUNC_GET_SYS_POWER_MODE 2U /* Index for pm_get_sys_power_mode() RPC call */ +#define PM_FUNC_SET_RESOURCE_POWER_MODE 3U /* Index for pm_set_resource_power_mode() RPC call */ +#define PM_FUNC_GET_RESOURCE_POWER_MODE 4U /* Index for pm_get_resource_power_mode() RPC call */ +#define PM_FUNC_REQ_LOW_POWER_MODE 16U /* Index for pm_req_low_power_mode() RPC call */ +#define PM_FUNC_REQ_CPU_LOW_POWER_MODE 20U /* Index for pm_req_cpu_low_power_mode() RPC call */ +#define PM_FUNC_SET_CPU_RESUME_ADDR 17U /* Index for pm_set_cpu_resume_addr() RPC call */ +#define PM_FUNC_SET_CPU_RESUME 21U /* Index for pm_set_cpu_resume() RPC call */ +#define PM_FUNC_REQ_SYS_IF_POWER_MODE 18U /* Index for pm_req_sys_if_power_mode() RPC call */ +#define PM_FUNC_SET_CLOCK_RATE 5U /* Index for pm_set_clock_rate() RPC call */ +#define PM_FUNC_GET_CLOCK_RATE 6U /* Index for pm_get_clock_rate() RPC call */ +#define PM_FUNC_CLOCK_ENABLE 7U /* Index for pm_clock_enable() RPC call */ +#define PM_FUNC_SET_CLOCK_PARENT 14U /* Index for pm_set_clock_parent() RPC call */ +#define PM_FUNC_GET_CLOCK_PARENT 15U /* Index for pm_get_clock_parent() RPC call */ +#define PM_FUNC_RESET 13U /* Index for pm_reset() RPC call */ +#define PM_FUNC_RESET_REASON 10U /* Index for pm_reset_reason() RPC call */ +#define PM_FUNC_BOOT 8U /* Index for pm_boot() RPC call */ +#define PM_FUNC_REBOOT 9U /* Index for pm_reboot() RPC call */ +#define PM_FUNC_REBOOT_PARTITION 12U /* Index for pm_reboot_partition() RPC call */ +#define PM_FUNC_CPU_START 11U /* Index for pm_cpu_start() RPC call */ +/*@}*/ + +/* Types */ + +/* Functions */ + +/*! + * This function dispatches an incoming PM RPC request. + * + * @param[in] caller_pt caller partition + * @param[in] msg pointer to RPC message + */ +void pm_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg); + +/*! + * This function translates and dispatches an PM RPC request. + * + * @param[in] ipc IPC handle + * @param[in] msg pointer to RPC message + */ +void pm_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SCI_PM_RPC_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c new file mode 100644 index 0000000..16771a5 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c @@ -0,0 +1,639 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * File containing client-side RPC functions for the RM service. These + * functions are ported to clients that communicate to the SC. + * + * @addtogroup RM_SVC + * @{ + */ + +/* Includes */ + +#include + +#include +#include +#include + +#include "sci_rm_rpc.h" + +/* Local Defines */ + +/* Local Types */ + +/* Local Functions */ + +sc_err_t sc_rm_partition_alloc(sc_ipc_t ipc, sc_rm_pt_t *pt, sc_bool_t secure, + sc_bool_t isolated, sc_bool_t restricted, + sc_bool_t grant, sc_bool_t coherent) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_ALLOC; + RPC_U8(&msg, 0U) = (uint8_t)secure; + RPC_U8(&msg, 1U) = (uint8_t)isolated; + RPC_U8(&msg, 2U) = (uint8_t)restricted; + RPC_U8(&msg, 3U) = (uint8_t)grant; + RPC_U8(&msg, 4U) = (uint8_t)coherent; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (pt != NULL) { + *pt = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_confidential(sc_ipc_t ipc, sc_rm_pt_t pt, sc_bool_t retro) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_CONFIDENTIAL; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)retro; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_partition_free(sc_ipc_t ipc, sc_rm_pt_t pt) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_FREE; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_rm_did_t sc_rm_get_did(sc_ipc_t ipc) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_DID; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_rm_did_t) result; +} + +sc_err_t sc_rm_partition_static(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_did_t did) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_STATIC; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)did; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_partition_lock(sc_ipc_t ipc, sc_rm_pt_t pt) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_LOCK; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_get_partition(sc_ipc_t ipc, sc_rm_pt_t *pt) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_PARTITION; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (pt != NULL) { + *pt = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_parent(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_pt_t pt_parent) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PARENT; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)pt_parent; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_move_all(sc_ipc_t ipc, sc_rm_pt_t pt_src, sc_rm_pt_t pt_dst, + sc_bool_t move_rsrc, sc_bool_t move_pads) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MOVE_ALL; + RPC_U8(&msg, 0U) = (uint8_t)pt_src; + RPC_U8(&msg, 1U) = (uint8_t)pt_dst; + RPC_U8(&msg, 2U) = (uint8_t)move_rsrc; + RPC_U8(&msg, 3U) = (uint8_t)move_pads; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_assign_resource(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rsrc_t resource) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_RESOURCE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_resource_movable(sc_ipc_t ipc, sc_rsrc_t resource_fst, + sc_rsrc_t resource_lst, sc_bool_t movable) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_RESOURCE_MOVABLE; + RPC_U16(&msg, 0U) = (uint16_t)resource_fst; + RPC_U16(&msg, 2U) = (uint16_t)resource_lst; + RPC_U8(&msg, 4U) = (uint8_t)movable; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_subsys_rsrc_movable(sc_ipc_t ipc, sc_rsrc_t resource, + sc_bool_t movable) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_SUBSYS_RSRC_MOVABLE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)movable; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_master_attributes(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_spa_t sa, sc_rm_spa_t pa, + sc_bool_t smmu_bypass) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MASTER_ATTRIBUTES; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)sa; + RPC_U8(&msg, 3U) = (uint8_t)pa; + RPC_U8(&msg, 4U) = (uint8_t)smmu_bypass; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource, sc_rm_sid_t sid) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MASTER_SID; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U16(&msg, 2U) = (uint16_t)sid; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_peripheral_permissions(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_pt_t pt, sc_rm_perm_t perm) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PERIPHERAL_PERMISSIONS; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)pt; + RPC_U8(&msg, 3U) = (uint8_t)perm; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_OWNED; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +sc_bool_t sc_rm_is_resource_master(sc_ipc_t ipc, sc_rsrc_t resource) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_MASTER; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +sc_bool_t sc_rm_is_resource_peripheral(sc_ipc_t ipc, sc_rsrc_t resource) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_PERIPHERAL; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +sc_err_t sc_rm_get_resource_info(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_sid_t *sid) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_RESOURCE_INFO; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (sid != NULL) { + *sid = RPC_U16(&msg, 0U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_memreg_alloc(sc_ipc_t ipc, sc_rm_mr_t *mr, + sc_faddr_t addr_start, sc_faddr_t addr_end) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_ALLOC; + RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr_start; + RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U); + RPC_U32(&msg, 12U) = (uint32_t)addr_end; + RPC_SIZE(&msg) = 5U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mr != NULL) { + *mr = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_memreg_split(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_rm_mr_t *mr_ret, sc_faddr_t addr_start, + sc_faddr_t addr_end) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_SPLIT; + RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr_start; + RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U); + RPC_U32(&msg, 12U) = (uint32_t)addr_end; + RPC_U8(&msg, 16U) = (uint8_t)mr; + RPC_SIZE(&msg) = 6U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mr_ret != NULL) { + *mr_ret = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_memreg_free(sc_ipc_t ipc, sc_rm_mr_t mr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_FREE; + RPC_U8(&msg, 0U) = (uint8_t)mr; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_find_memreg(sc_ipc_t ipc, sc_rm_mr_t *mr, + sc_faddr_t addr_start, sc_faddr_t addr_end) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_FIND_MEMREG; + RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr_start; + RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U); + RPC_U32(&msg, 12U) = (uint32_t)addr_end; + RPC_SIZE(&msg) = 5U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mr != NULL) { + *mr = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_assign_memreg(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_mr_t mr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_MEMREG; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)mr; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_memreg_permissions(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_rm_pt_t pt, sc_rm_perm_t perm) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MEMREG_PERMISSIONS; + RPC_U8(&msg, 0U) = (uint8_t)mr; + RPC_U8(&msg, 1U) = (uint8_t)pt; + RPC_U8(&msg, 2U) = (uint8_t)perm; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_MEMREG_OWNED; + RPC_U8(&msg, 0U) = (uint8_t)mr; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +sc_err_t sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_faddr_t *addr_start, sc_faddr_t *addr_end) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_MEMREG_INFO; + RPC_U8(&msg, 0U) = (uint8_t)mr; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (addr_start != NULL) { + *addr_start = + ((uint64_t) RPC_U32(&msg, 0U) << 32U) | RPC_U32(&msg, 4U); + } + + if (addr_end != NULL) { + *addr_end = + ((uint64_t) RPC_U32(&msg, 8U) << 32U) | RPC_U32(&msg, 12U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_assign_pad(sc_ipc_t ipc, sc_rm_pt_t pt, sc_pad_t pad) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_PAD; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_pad_movable(sc_ipc_t ipc, sc_pad_t pad_fst, + sc_pad_t pad_lst, sc_bool_t movable) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PAD_MOVABLE; + RPC_U16(&msg, 0U) = (uint16_t)pad_fst; + RPC_U16(&msg, 2U) = (uint16_t)pad_lst; + RPC_U8(&msg, 4U) = (uint8_t)movable; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_bool_t sc_rm_is_pad_owned(sc_ipc_t ipc, sc_pad_t pad) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_PAD_OWNED; + RPC_U8(&msg, 0U) = (uint8_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +void sc_rm_dump(sc_ipc_t ipc) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_DUMP; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + return; +} + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h new file mode 100644 index 0000000..45d05f9 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the RM RPC implementation. + * + * @addtogroup RM_SVC + * @{ + */ + +#ifndef SCI_RM_RPC_H +#define SCI_RM_RPC_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Defines for RPC RM function calls + */ +/*@{*/ +#define RM_FUNC_UNKNOWN 0 /* Unknown function */ +#define RM_FUNC_PARTITION_ALLOC 1U /* Index for rm_partition_alloc() RPC call */ +#define RM_FUNC_SET_CONFIDENTIAL 31U /* Index for rm_set_confidential() RPC call */ +#define RM_FUNC_PARTITION_FREE 2U /* Index for rm_partition_free() RPC call */ +#define RM_FUNC_GET_DID 26U /* Index for rm_get_did() RPC call */ +#define RM_FUNC_PARTITION_STATIC 3U /* Index for rm_partition_static() RPC call */ +#define RM_FUNC_PARTITION_LOCK 4U /* Index for rm_partition_lock() RPC call */ +#define RM_FUNC_GET_PARTITION 5U /* Index for rm_get_partition() RPC call */ +#define RM_FUNC_SET_PARENT 6U /* Index for rm_set_parent() RPC call */ +#define RM_FUNC_MOVE_ALL 7U /* Index for rm_move_all() RPC call */ +#define RM_FUNC_ASSIGN_RESOURCE 8U /* Index for rm_assign_resource() RPC call */ +#define RM_FUNC_SET_RESOURCE_MOVABLE 9U /* Index for rm_set_resource_movable() RPC call */ +#define RM_FUNC_SET_SUBSYS_RSRC_MOVABLE 28U /* Index for rm_set_subsys_rsrc_movable() RPC call */ +#define RM_FUNC_SET_MASTER_ATTRIBUTES 10U /* Index for rm_set_master_attributes() RPC call */ +#define RM_FUNC_SET_MASTER_SID 11U /* Index for rm_set_master_sid() RPC call */ +#define RM_FUNC_SET_PERIPHERAL_PERMISSIONS 12U /* Index for rm_set_peripheral_permissions() RPC call */ +#define RM_FUNC_IS_RESOURCE_OWNED 13U /* Index for rm_is_resource_owned() RPC call */ +#define RM_FUNC_IS_RESOURCE_MASTER 14U /* Index for rm_is_resource_master() RPC call */ +#define RM_FUNC_IS_RESOURCE_PERIPHERAL 15U /* Index for rm_is_resource_peripheral() RPC call */ +#define RM_FUNC_GET_RESOURCE_INFO 16U /* Index for rm_get_resource_info() RPC call */ +#define RM_FUNC_MEMREG_ALLOC 17U /* Index for rm_memreg_alloc() RPC call */ +#define RM_FUNC_MEMREG_SPLIT 29U /* Index for rm_memreg_split() RPC call */ +#define RM_FUNC_MEMREG_FREE 18U /* Index for rm_memreg_free() RPC call */ +#define RM_FUNC_FIND_MEMREG 30U /* Index for rm_find_memreg() RPC call */ +#define RM_FUNC_ASSIGN_MEMREG 19U /* Index for rm_assign_memreg() RPC call */ +#define RM_FUNC_SET_MEMREG_PERMISSIONS 20U /* Index for rm_set_memreg_permissions() RPC call */ +#define RM_FUNC_IS_MEMREG_OWNED 21U /* Index for rm_is_memreg_owned() RPC call */ +#define RM_FUNC_GET_MEMREG_INFO 22U /* Index for rm_get_memreg_info() RPC call */ +#define RM_FUNC_ASSIGN_PAD 23U /* Index for rm_assign_pad() RPC call */ +#define RM_FUNC_SET_PAD_MOVABLE 24U /* Index for rm_set_pad_movable() RPC call */ +#define RM_FUNC_IS_PAD_OWNED 25U /* Index for rm_is_pad_owned() RPC call */ +#define RM_FUNC_DUMP 27U /* Index for rm_dump() RPC call */ +/*@}*/ + +/* Types */ + +/* Functions */ + +/*! + * This function dispatches an incoming RM RPC request. + * + * @param[in] caller_pt caller partition + * @param[in] msg pointer to RPC message + */ +void rm_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg); + +/*! + * This function translates and dispatches an RM RPC request. + * + * @param[in] ipc IPC handle + * @param[in] msg pointer to RPC message + */ +void rm_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SCI_RM_RPC_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h new file mode 100644 index 0000000..6716399 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2019 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the TIMER RPC implementation. + * + * @addtogroup TIMER_SVC + * @{ + */ + +#ifndef SC_TIMER_RPC_H +#define SC_TIMER_RPC_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Defines for RPC TIMER function calls + */ +/*@{*/ +#define TIMER_FUNC_UNKNOWN 0 /* Unknown function */ +#define TIMER_FUNC_SET_WDOG_TIMEOUT 1U /* Index for timer_set_wdog_timeout() RPC call */ +#define TIMER_FUNC_SET_WDOG_PRE_TIMEOUT 12U /* Index for timer_set_wdog_pre_timeout() RPC call */ +#define TIMER_FUNC_START_WDOG 2U /* Index for timer_start_wdog() RPC call */ +#define TIMER_FUNC_STOP_WDOG 3U /* Index for timer_stop_wdog() RPC call */ +#define TIMER_FUNC_PING_WDOG 4U /* Index for timer_ping_wdog() RPC call */ +#define TIMER_FUNC_GET_WDOG_STATUS 5U /* Index for timer_get_wdog_status() RPC call */ +#define TIMER_FUNC_PT_GET_WDOG_STATUS 13U /* Index for timer_pt_get_wdog_status() RPC call */ +#define TIMER_FUNC_SET_WDOG_ACTION 10U /* Index for timer_set_wdog_action() RPC call */ +#define TIMER_FUNC_SET_RTC_TIME 6U /* Index for timer_set_rtc_time() RPC call */ +#define TIMER_FUNC_GET_RTC_TIME 7U /* Index for timer_get_rtc_time() RPC call */ +#define TIMER_FUNC_GET_RTC_SEC1970 9U /* Index for timer_get_rtc_sec1970() RPC call */ +#define TIMER_FUNC_SET_RTC_ALARM 8U /* Index for timer_set_rtc_alarm() RPC call */ +#define TIMER_FUNC_SET_RTC_PERIODIC_ALARM 14U /* Index for timer_set_rtc_periodic_alarm() RPC call */ +#define TIMER_FUNC_CANCEL_RTC_ALARM 15U /* Index for timer_cancel_rtc_alarm() RPC call */ +#define TIMER_FUNC_SET_RTC_CALB 11U /* Index for timer_set_rtc_calb() RPC call */ +#define TIMER_FUNC_SET_SYSCTR_ALARM 16U /* Index for timer_set_sysctr_alarm() RPC call */ +#define TIMER_FUNC_SET_SYSCTR_PERIODIC_ALARM 17U /* Index for timer_set_sysctr_periodic_alarm() RPC call */ +#define TIMER_FUNC_CANCEL_SYSCTR_ALARM 18U /* Index for timer_cancel_sysctr_alarm() RPC call */ +/*@}*/ + +/* Types */ + +/* Functions */ + +/*! + * This function dispatches an incoming TIMER RPC request. + * + * @param[in] caller_pt caller partition + * @param[in] msg pointer to RPC message + */ +void timer_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg); + +/*! + * This function translates and dispatches an TIMER RPC request. + * + * @param[in] ipc IPC handle + * @param[in] msg pointer to RPC message + */ +void timer_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SC_TIMER_RPC_H */ + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c new file mode 100644 index 0000000..a82be96 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2019 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * File containing client-side RPC functions for the TIMER service. These + * functions are ported to clients that communicate to the SC. + * + * @addtogroup TIMER_SVC + * @{ + */ + +/* Includes */ + +#include +#include +#include +#include +#include +#include "sci_timer_rpc.h" + +/* Local Defines */ + +/* Local Types */ + +/* Local Functions */ + +sc_err_t sc_timer_set_wdog_timeout(sc_ipc_t ipc, sc_timer_wdog_time_t timeout) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_WDOG_TIMEOUT; + RPC_U32(&msg, 0U) = (uint32_t)timeout; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_set_wdog_pre_timeout(sc_ipc_t ipc, + sc_timer_wdog_time_t pre_timeout) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_WDOG_PRE_TIMEOUT; + RPC_U32(&msg, 0U) = (uint32_t)pre_timeout; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_start_wdog(sc_ipc_t ipc, sc_bool_t lock) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_START_WDOG; + RPC_U8(&msg, 0U) = (uint8_t)lock; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_stop_wdog(sc_ipc_t ipc) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_STOP_WDOG; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_ping_wdog(sc_ipc_t ipc) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_PING_WDOG; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_get_wdog_status(sc_ipc_t ipc, + sc_timer_wdog_time_t *timeout, + sc_timer_wdog_time_t *max_timeout, + sc_timer_wdog_time_t *remaining_time) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_GET_WDOG_STATUS; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (timeout != NULL) + *timeout = RPC_U32(&msg, 0U); + + if (max_timeout != NULL) + *max_timeout = RPC_U32(&msg, 4U); + + if (remaining_time != NULL) + *remaining_time = RPC_U32(&msg, 8U); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_pt_get_wdog_status(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_bool_t *enb, + sc_timer_wdog_time_t *timeout, + sc_timer_wdog_time_t *remaining_time) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_PT_GET_WDOG_STATUS; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (timeout != NULL) + *timeout = RPC_U32(&msg, 0U); + + if (remaining_time != NULL) + *remaining_time = RPC_U32(&msg, 4U); + + result = RPC_R8(&msg); + if (enb != NULL) + *enb = RPC_U8(&msg, 8U); + + return (sc_err_t)result; +} + +sc_err_t sc_timer_set_wdog_action(sc_ipc_t ipc, + sc_rm_pt_t pt, sc_timer_wdog_action_t action) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_WDOG_ACTION; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)action; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_set_rtc_time(sc_ipc_t ipc, uint16_t year, uint8_t mon, + uint8_t day, uint8_t hour, uint8_t min, + uint8_t sec) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_RTC_TIME; + RPC_U16(&msg, 0U) = (uint16_t)year; + RPC_U8(&msg, 2U) = (uint8_t)mon; + RPC_U8(&msg, 3U) = (uint8_t)day; + RPC_U8(&msg, 4U) = (uint8_t)hour; + RPC_U8(&msg, 5U) = (uint8_t)min; + RPC_U8(&msg, 6U) = (uint8_t)sec; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_get_rtc_time(sc_ipc_t ipc, uint16_t *year, uint8_t *mon, + uint8_t *day, uint8_t *hour, uint8_t *min, + uint8_t *sec) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_GET_RTC_TIME; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (year != NULL) + *year = RPC_U16(&msg, 0U); + + result = RPC_R8(&msg); + if (mon != NULL) + *mon = RPC_U8(&msg, 2U); + + if (day != NULL) + *day = RPC_U8(&msg, 3U); + + if (hour != NULL) + *hour = RPC_U8(&msg, 4U); + + if (min != NULL) + *min = RPC_U8(&msg, 5U); + + if (sec != NULL) + *sec = RPC_U8(&msg, 6U); + + return (sc_err_t)result; +} + +sc_err_t sc_timer_get_rtc_sec1970(sc_ipc_t ipc, uint32_t *sec) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_GET_RTC_SEC1970; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (sec != NULL) + *sec = RPC_U32(&msg, 0U); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_set_rtc_alarm(sc_ipc_t ipc, uint16_t year, uint8_t mon, + uint8_t day, uint8_t hour, uint8_t min, + uint8_t sec) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_RTC_ALARM; + RPC_U16(&msg, 0U) = (uint16_t)year; + RPC_U8(&msg, 2U) = (uint8_t)mon; + RPC_U8(&msg, 3U) = (uint8_t)day; + RPC_U8(&msg, 4U) = (uint8_t)hour; + RPC_U8(&msg, 5U) = (uint8_t)min; + RPC_U8(&msg, 6U) = (uint8_t)sec; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_set_rtc_periodic_alarm(sc_ipc_t ipc, uint32_t sec) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_RTC_PERIODIC_ALARM; + RPC_U32(&msg, 0U) = (uint32_t)sec; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_cancel_rtc_alarm(sc_ipc_t ipc) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_CANCEL_RTC_ALARM; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_set_rtc_calb(sc_ipc_t ipc, int8_t count) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_RTC_CALB; + RPC_I8(&msg, 0U) = (int8_t) count; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_set_sysctr_alarm(sc_ipc_t ipc, uint64_t ticks) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_SYSCTR_ALARM; + RPC_U32(&msg, 0U) = (uint32_t)(ticks >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)ticks; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_set_sysctr_periodic_alarm(sc_ipc_t ipc, uint64_t ticks) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_SYSCTR_PERIODIC_ALARM; + RPC_U32(&msg, 0U) = (uint32_t)(ticks >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)ticks; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_timer_cancel_sysctr_alarm(sc_ipc_t ipc) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER; + RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_CANCEL_SYSCTR_ALARM; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +/**@}*/ diff --git a/arm-trusted-firmware/plat/imx/imx7/common/imx7.mk b/arm-trusted-firmware/plat/imx/imx7/common/imx7.mk new file mode 100644 index 0000000..fdde9a9 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/common/imx7.mk @@ -0,0 +1,112 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Architecture +$(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)) + +TF_CFLAGS += -mfpu=neon +ASFLAGS += -mfpu=neon + +# Platform +PLAT_INCLUDES := -Idrivers/imx/uart \ + -Iplat/imx/common/include \ + -Iplat/imx/imx7/include \ + -Idrivers/imx/timer \ + -Idrivers/imx/usdhc \ + -Iinclude/common/tbbr + +# Translation tables library +include lib/xlat_tables_v2/xlat_tables.mk + +BL2_SOURCES += common/desc_image_load.c \ + drivers/delay_timer/delay_timer.c \ + drivers/mmc/mmc.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + drivers/imx/timer/imx_gpt.c \ + drivers/imx/uart/imx_uart.c \ + drivers/imx/uart/imx_crash_uart.S \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + lib/cpus/aarch32/cortex_a7.S \ + lib/optee/optee_utils.c \ + plat/imx/common/imx_aips.c \ + plat/imx/common/imx_caam.c \ + plat/imx/common/imx_clock.c \ + plat/imx/common/imx_csu.c \ + plat/imx/common/imx_io_mux.c \ + plat/imx/common/imx_snvs.c \ + plat/imx/common/imx_wdog.c \ + plat/imx/common/imx7_clock.c \ + plat/imx/imx7/common/imx7_bl2_mem_params_desc.c \ + plat/imx/imx7/common/imx7_bl2_el3_common.c \ + plat/imx/imx7/common/imx7_helpers.S \ + plat/imx/imx7/common/imx7_image_load.c \ + plat/imx/common/imx_io_storage.c \ + plat/imx/common/aarch32/imx_uart_console.S \ + ${XLAT_TABLES_LIB_SRCS} + +ifneq (${TRUSTED_BOARD_BOOT},0) + +include drivers/auth/mbedtls/mbedtls_crypto.mk +include drivers/auth/mbedtls/mbedtls_x509.mk + +AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c + +BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/imx/imx7/common/imx7_trusted_boot.c \ + plat/imx/imx7/common/imx7_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +ROT_KEY = $(BUILD_PLAT)/rot_key.pem +ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + +$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) +$(eval $(call MAKE_LIB_DIRS)) + +$(BUILD_PLAT)/bl2/imx7_rotpk.o: $(ROTPK_HASH) + +certificates: $(ROT_KEY) + +$(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + @if [ ! -f $(ROT_KEY) ]; then \ + openssl genrsa 2048 > $@ 2>/dev/null; \ + fi + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +# Add the build options to pack BLx images and kernel device tree +# in the FIP if the platform requires. +ifneq ($(BL2),) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) +endif +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif +ifneq ($(HW_CONFIG),) +$(eval $(call TOOL_ADD_IMG,HW_CONFIG,--hw-config)) +endif + +# Verify build config +# ------------------- + +ifeq (${ARCH},aarch64) + $(error Error: AArch64 not supported on i.mx7) +endif diff --git a/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c b/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c new file mode 100644 index 0000000..4e5028c --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2018-2019, 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 +#include +#include +#include +#include +#include +#include +#include + +#ifndef AARCH32_SP_OPTEE +#error "Must build with OPTEE support included" +#endif + +uintptr_t plat_get_ns_image_entrypoint(void) +{ + return IMX7_UBOOT_BASE; +} + +static uint32_t imx7_get_spsr_for_bl32_entry(void) +{ + return SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS); +} + +static uint32_t imx7_get_spsr_for_bl33_entry(void) +{ + return SPSR_MODE32(MODE32_svc, + plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + bl_mem_params_node_t *hw_cfg_mem_params = NULL; + + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; + + assert(bl_mem_params); + + switch (image_id) { + case BL32_IMAGE_ID: + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) + WARN("OPTEE header parse error.\n"); + + /* + * When ATF loads the DTB the address of the DTB is passed in + * arg2, if an hw config image is present use the base address + * as DTB address an pass it as arg2 + */ + hw_cfg_mem_params = get_bl_mem_params_node(HW_CONFIG_ID); + + bl_mem_params->ep_info.args.arg0 = + bl_mem_params->ep_info.args.arg1; + bl_mem_params->ep_info.args.arg1 = 0; + if (hw_cfg_mem_params) + bl_mem_params->ep_info.args.arg2 = + hw_cfg_mem_params->image_info.image_base; + else + bl_mem_params->ep_info.args.arg2 = 0; + bl_mem_params->ep_info.args.arg3 = 0; + bl_mem_params->ep_info.spsr = imx7_get_spsr_for_bl32_entry(); + break; + + case BL33_IMAGE_ID: + /* AArch32 only core: OP-TEE expects NSec EP in register LR */ + pager_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID); + assert(pager_mem_params); + pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc; + + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = imx7_get_spsr_for_bl33_entry(); + break; + + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +void bl2_el3_plat_arch_setup(void) +{ + /* Setup the MMU here */ +} + +static void imx7_setup_system_counter(void) +{ + unsigned long freq = SYS_COUNTER_FREQ_IN_TICKS; + + /* Set the frequency table index to our target frequency */ + write_cntfrq(freq); + + /* Enable system counter @ frequency table index 0, halt on debug */ + mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0) | CNTCR_HDBG | CNTCR_EN); +} + +static void imx7_setup_wdog_clocks(void) +{ + uint32_t wdog_en_bits = (uint32_t)WDOG_DEFAULT_CLK_SELECT; + + imx_clock_set_wdog_clk_root_bits(wdog_en_bits); + imx_clock_enable_wdog(0); + imx_clock_enable_wdog(1); + imx_clock_enable_wdog(2); + imx_clock_enable_wdog(3); +} + + +/* + * bl2_el3_early_platform_setup() + * MMU off + */ +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + static console_t console; + int console_scope = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME; + + /* Initialize common components */ + imx_aips_init(); + imx_csu_init(); + imx_snvs_init(); + imx_gpt_ops_init(GPT1_BASE_ADDR); + imx_clock_init(); + imx7_setup_system_counter(); + imx7_setup_wdog_clocks(); + + /* Platform specific setup */ + imx7_platform_setup(arg1, arg2, arg3, arg4); + + /* Init UART, clock should be enabled in imx7_platform_setup() */ + console_imx_uart_register(PLAT_IMX7_BOOT_UART_BASE, + PLAT_IMX7_BOOT_UART_CLK_IN_HZ, + PLAT_IMX7_CONSOLE_BAUDRATE, + &console); + console_set_scope(&console, console_scope); + + /* Open handles to persistent storage */ + plat_imx_io_setup(); + + /* Setup higher-level functionality CAAM, RTC etc */ + imx_caam_init(); + imx_wdog_init(); + + /* Print out the expected memory map */ + VERBOSE("\tOPTEE 0x%08x-0x%08x\n", IMX7_OPTEE_BASE, IMX7_OPTEE_LIMIT); + VERBOSE("\tATF/BL2 0x%08x-0x%08x\n", BL2_RAM_BASE, BL2_RAM_LIMIT); + VERBOSE("\tSHRAM 0x%08x-0x%08x\n", SHARED_RAM_BASE, SHARED_RAM_LIMIT); + VERBOSE("\tFIP 0x%08x-0x%08x\n", IMX_FIP_BASE, IMX_FIP_LIMIT); + VERBOSE("\tDTB-OVERLAY 0x%08x-0x%08x\n", IMX7_DTB_OVERLAY_BASE, IMX7_DTB_OVERLAY_LIMIT); + VERBOSE("\tDTB 0x%08x-0x%08x\n", IMX7_DTB_BASE, IMX7_DTB_LIMIT); + VERBOSE("\tUBOOT/BL33 0x%08x-0x%08x\n", IMX7_UBOOT_BASE, IMX7_UBOOT_LIMIT); +} + +/* + * bl2_platform_setup() + * MMU on - enabled by bl2_el3_plat_arch_setup() + */ +void bl2_platform_setup(void) +{ +} diff --git a/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c new file mode 100644 index 0000000..f9b2983 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bl_mem_params_node_t bl2_mem_params_descs[] = { + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL32_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, 0), + + .image_info.image_base = IMX7_OPTEE_BASE, + .image_info.image_max_size = IMX7_OPTEE_SIZE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = IMX7_OPTEE_BASE, + .image_info.image_max_size = IMX7_OPTEE_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + /* This is a zero sized image so we don't set base or size */ + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, + NON_SECURE | EXECUTABLE), + # ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + # else + .ep_info.pc = BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = IMX7_UBOOT_BASE, + .image_info.image_max_size = IMX7_UBOOT_SIZE, + # endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs); diff --git a/arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S b/arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S new file mode 100644 index 0000000..661fd29 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S @@ -0,0 +1,59 @@ +/* + * Copyright (c) Linaro 2018-2019 Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl platform_mem_init + .globl plat_get_my_entrypoint + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_panic_handler + + /* --------------------------------------------- + * int plat_mem_init(void) + * Function to initialize memory. + * The HAB hands off the DDR controller already + * setup and ready to use. + * Implement the mandatory function as a NOP + * --------------------------------------------- + */ +func platform_mem_init + bx lr +endfunc platform_mem_init + +func plat_get_my_entrypoint + mov r0, #0 + bx lr +endfunc plat_get_my_entrypoint + +func plat_crash_console_init + mov_imm r0, PLAT_IMX7_BOOT_UART_BASE + mov_imm r1, PLAT_IMX7_BOOT_UART_CLK_IN_HZ + mov_imm r2, PLAT_IMX7_CONSOLE_BAUDRATE + b imx_crash_uart_init +endfunc plat_crash_console_init + +func plat_crash_console_putc + mov_imm r1, PLAT_IMX7_BOOT_UART_BASE + b imx_crash_uart_putc +endfunc plat_crash_console_putc + +func plat_crash_console_flush + /* Placeholder */ + mov r0, #0 + bx lr +endfunc plat_crash_console_flush + +func plat_panic_handler + mov r3, #HAB_ROM_VECTOR_TABLE_FAILSAFE + ldr r3, [r3, #0] + blx r3 +endfunc plat_panic_handler diff --git a/arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c b/arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c new file mode 100644 index 0000000..c3e47b9 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +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(); +} diff --git a/arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S b/arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S new file mode 100644 index 0000000..8bd53c2 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global imx7_rotpk_hash + .global imx7_rotpk_hash_end +imx7_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +imx7_rotpk_hash_end: diff --git a/arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c b/arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c new file mode 100644 index 0000000..cd27128 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +extern char imx7_rotpk_hash[], imx7_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = imx7_rotpk_hash; + *key_len = imx7_rotpk_hash_end - imx7_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h b/arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h new file mode 100644 index 0000000..d92a2d1 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX7_DEF_H +#define IMX7_DEF_H + +#include + + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_imx_io_setup(void); +void imx7_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4); + +#endif /*IMX7_DEF_H */ diff --git a/arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h b/arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h new file mode 100644 index 0000000..2a34c6a --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef IMX_HAB_ARCH_H +#define IMX_HAB_ARCH_H + +/* Define the offset the High Assurance Boot callback table is at */ +#define HAB_CALLBACK_OFFSET 0x100 + +#endif /* IMX_HAB_ARCH_H */ diff --git a/arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h b/arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h new file mode 100644 index 0000000..3c7e20f --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_REGS_H +#define IMX_REGS_H + +/* Define the processor memory map */ + +#define OCRAM_S_ALIAS_BASE 0x00000000 /* CM4 Alias Code */ +#define ROM_HIGH_BASE 0x00008000 /* ROM high 64k */ +#define ROM_HIGH_PROT_BASE 0x00017000 /* ROM high 64k protected */ +#define CAAM_BASE 0x00020000 /* CAAM block base address */ +#define OCRAM_S_BASE 0x00180000 /* OCRAM_S */ +#define ROM_LOW_BASE 0x007f8000 /* ROM low 64k */ +#define OCRAM_BASE 0x00900000 /* OCRAM base */ +#define CM4_ALIAS_CODE_BASE 0x04000000 /* CM4 alias code */ +#define TCM_BASE 0x1fff0000 /* TCM */ +#define BOOTROM_CP_BASE 0x20020000 /* Boot ROM (all 96KB) */ +#define CM4_ALIAS_SYSTEM_BASE 0x20100000 /* CM4 Alias system */ +#define EIM_BASE 0x28000000 /* EIM */ + +/* BootROM absolute base address */ +#define BOOTROM_BASE 0x00000000 /* BootROM */ + +/* Peripherals like GPIO live in the AIPS range */ +#define AIPS1_BASE 0x30000000 /* AIPS1 */ +#define AIPS2_BASE 0x30400000 /* AIPS2 */ +#define AIPS3_BASE 0x30800000 /* AIPS3 */ +#define AIPS4_BASE 0x30c00000 /* AIPS4 */ + +/* ARM peripherals like GIC */ +#define ARM_PERIPHERAL_GIC_BASE 0x31000000 /* GIC */ + +/* Configuration ports */ +#define GPV0_BASE 0x32000000 /* Main config port */ +#define GPV1_BASE 0x32100000 /* Wakeup config port */ +#define GPV2_BASE 0x32200000 /* Per_s config port */ +#define GPV3_BASE 0x32300000 /* Per_m config port */ +#define GPV4_BASE 0x32400000 /* Enet config port */ +#define GPV5_BASE 0x32500000 /* Display config port */ +#define GPV6_BASE 0x32600000 /* M4 conig port */ + +/* MMAP peripherals - like APBH DMA */ +#define APBH_DMA_BASE 0x33000000 /* APBH DMA block */ + +/* QSPI RX BUFFERS */ +#define QSPI_RX_BUFFER_BASE 0x34000000 /* QSPI RX buffers */ + +/* QSPI1 FLASH */ +#define QSPI_FLASH_BASE 0x60000000 /* QSPI1 flash */ + +/* AIPS1 block addresses */ +#define AIPSTZ_CONFIG_OFFSET 0x001f0000 +#define CCM_BASE (AIPS1_BASE + 0x380000) + +/* Define the maximum number of UART blocks on this SoC */ +#define MXC_UART1_BASE (AIPS3_BASE + 0x060000) +#define MXC_UART2_BASE (AIPS3_BASE + 0x070000) +#define MXC_UART3_BASE (AIPS3_BASE + 0x080000) +#define MXC_UART4_BASE (AIPS3_BASE + 0x260000) +#define MXC_UART5_BASE (AIPS3_BASE + 0x270000) +#define MXC_UART6_BASE (AIPS3_BASE + 0x280000) +#define MXC_UART7_BASE (AIPS3_BASE + 0x290000) +#define MXC_MAX_UART_NUM 0x07 + +/* Define the maximum number of USDHCI blocks on this SoC */ +#define MXC_MAX_USDHC_NUM 3 + +/* Define the number of CSU registers for this SoC */ +#define MXC_MAX_CSU_REGS 0x40 +#define CSU_BASE (AIPS1_BASE + 0x3E0000) + +/* IO Mux block base */ +#define MXC_IO_MUXC_BASE (AIPS1_BASE + 0x330000) + +/* SNVS base */ +#define SNVS_BASE (AIPS1_BASE + 0x370000) + +/* GP Timer base */ +#define GPT1_BASE_ADDR (AIPS1_BASE + 0x2d0000) + +/* MMC base */ +#define USDHC1_BASE (AIPS1_BASE + 0xb40000) +#define USDHC2_BASE (AIPS1_BASE + 0xb50000) +#define USDHC3_BASE (AIPS1_BASE + 0xb60000) + +/* Arm optional memory mapped counter module base address */ +#define SYS_CNTCTL_BASE (AIPS2_BASE + 0x2c0000) + +/* Define CAAM AIPS offset */ +#define CAAM_AIPS_BASE (AIPS3_BASE + 0x100000) +#define CAAM_NUM_JOB_RINGS 0x03 +#define CAAM_NUM_RTIC 0x04 +#define CAAM_NUM_DECO 0x01 + +/* Define watchdog base addresses */ +#define WDOG1_BASE (AIPS1_BASE + 0x280000) +#define WDOG2_BASE (AIPS1_BASE + 0x290000) +#define WDOG3_BASE (AIPS1_BASE + 0x2A0000) +#define WDOG4_BASE (AIPS1_BASE + 0x280000) + +/* Define the maximum number of WDOG blocks on this SoC */ +#define MXC_MAX_WDOG_NUM 0x04 + +#endif /* IMX_REGS_H */ diff --git a/arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h new file mode 100644 index 0000000..5f2975d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#define PLATFORM_STACK_SIZE 0x1000 + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(2) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER + +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define PICOPI_PRIMARY_CPU U(0) + +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 + +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN 0 + +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET 1 + +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF 2 + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH 4 +#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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. + * i.MX7 has a 32 byte cacheline size + * i.MX 7Dual Applications Processor Reference Manual, Rev. 1, 01/2018 pg 298 + */ +#define CACHE_WRITEBACK_SHIFT 4 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Partition memory into secure BootROM, OCRAM_S, non-secure DRAM, secure DRAM + */ +#define BOOT_ROM_BASE 0x00000000 +#define BOOT_ROM_SIZE 0x00020000 + +#define OCRAM_S_BASE 0x00180000 +#define OCRAM_S_SIZE 0x00008000 + +/* Controller maps 2GB, board contains 512 MB. 0x80000000 - 0xa0000000 */ +#define DRAM_BASE 0x80000000 +#define DRAM_SIZE 0x20000000 +#define DRAM_LIMIT (DRAM_BASE + DRAM_SIZE) + +/* Place OPTEE at minus 32 MB from the end of memory. 0x9e000000 - 0xa0000000 */ +#define IMX7_OPTEE_SIZE 0x02000000 +#define IMX7_OPTEE_BASE (DRAM_LIMIT - IMX7_OPTEE_SIZE) +#define IMX7_OPTEE_LIMIT (IMX7_OPTEE_BASE + IMX7_OPTEE_SIZE) + +/* Place ATF directly beneath OPTEE. 0x9df00000 - 0x9e000000 */ +#define BL2_RAM_SIZE 0x00100000 +#define BL2_RAM_BASE (IMX7_OPTEE_BASE - BL2_RAM_SIZE) +#define BL2_RAM_LIMIT (BL2_RAM_BASE + BL2_RAM_SIZE) + +/* Optional Mailbox. Only relevant on i.MX7D. 0x9deff000 - 0x9df00000*/ +#define SHARED_RAM_SIZE 0x00001000 +#define SHARED_RAM_BASE (BL2_RAM_BASE - SHARED_RAM_SIZE) +#define SHARED_RAM_LIMIT (SHARED_RAM_BASE + SHARED_RAM_SIZE) + +/* Define the absolute location of u-boot 0x87800000 - 0x87900000 */ +#define IMX7_UBOOT_SIZE 0x00100000 +#define IMX7_UBOOT_BASE (DRAM_BASE + 0x7800000) +#define IMX7_UBOOT_LIMIT (IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE) + +/* Define FIP image absolute location 0x80000000 - 0x80100000 */ +#define IMX_FIP_SIZE 0x00100000 +#define IMX_FIP_BASE (DRAM_BASE) +#define IMX_FIP_LIMIT (IMX_FIP_BASE + IMX_FIP_SIZE) + +/* Define FIP image location at 1MB offset */ +#define IMX_FIP_MMC_BASE (1024 * 1024) + +/* Define the absolute location of DTB 0x83000000 - 0x83100000 */ +#define IMX7_DTB_SIZE 0x00100000 +#define IMX7_DTB_BASE (DRAM_BASE + 0x03000000) +#define IMX7_DTB_LIMIT (IMX7_DTB_BASE + IMX7_DTB_SIZE) + +/* Define the absolute location of DTB Overlay 0x83100000 - 0x83101000 */ +#define IMX7_DTB_OVERLAY_SIZE 0x00001000 +#define IMX7_DTB_OVERLAY_BASE IMX7_DTB_LIMIT +#define IMX7_DTB_OVERLAY_LIMIT (IMX7_DTB_OVERLAY_BASE + \ + IMX7_DTB_OVERLAY_SIZE) +/* + * BL2 specific defines. + * + * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define BL2_BASE BL2_RAM_BASE +#define BL2_LIMIT (BL2_RAM_BASE + BL2_RAM_SIZE) + +/* + * BL3-2/OPTEE + */ +# define BL32_BASE IMX7_OPTEE_BASE +# define BL32_LIMIT (IMX7_OPTEE_BASE + IMX7_OPTEE_SIZE) + +/* + * BL3-3/U-BOOT + */ +#define BL33_BASE IMX7_UBOOT_BASE +#define BL33_LIMIT (IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE) + +/* + * ATF's view of memory + * + * 0xa0000000 +-----------------+ + * | DDR | BL32/OPTEE + * 0x9e000000 +-----------------+ + * | DDR | BL23 ATF + * 0x9df00000 +-----------------+ + * | DDR | Shared MBOX RAM + * 0x9de00000 +-----------------+ + * | DDR | Unallocated + * 0x87900000 +-----------------+ + * | DDR | BL33/U-BOOT + * 0x87800000 +-----------------+ + * | DDR | Unallocated + * 0x83100000 +-----------------+ + * | DDR | DTB + * 0x83000000 +-----------------+ + * | DDR | Unallocated + * 0x80100000 +-----------------+ + * | DDR | FIP + * 0x80000000 +-----------------+ + * | SOC I/0 | + * 0x00a00000 +-----------------+ + * | OCRAM | Not used + * 0x00900000 +-----------------+ + * | SOC I/0 | + * 0x00188000 +-----------------+ + * | OCRAM_S | Not used + * 0x00180000 +-----------------+ + * | SOC I/0 | + * 0x00020000 +-----------------+ + * | BootROM | BL1 + * 0x00000000 +-----------------+ + */ + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_MMAP_REGIONS 10 +#define MAX_XLAT_TABLES 6 +#define MAX_IO_DEVICES 2 +#define MAX_IO_HANDLES 3 +#define MAX_IO_BLOCK_DEVICES 1 + +/* UART defines */ +#define PLAT_IMX7_BOOT_UART_BASE MXC_UART5_BASE +#define PLAT_IMX7_BOOT_UART_CLK_IN_HZ 24000000 +#define PLAT_IMX7_CONSOLE_BAUDRATE 115200 + +/* MMC defines */ +#ifndef PLAT_PICOPI_SD +#define PLAT_PICOPI_SD 3 +#endif + +#if PLAT_PICOPI_SD == 1 +#define PLAT_PICOPI_BOOT_MMC_BASE USDHC1_BASE +#endif /* PLAT_PICOPI_SD == 1 */ + +#if PLAT_PICOPI_SD == 2 +#define PLAT_PICOPI_BOOT_MMC_BASE USDHC2_BASE +#endif /* PLAT_PICOPI_SD == 2 */ + +#if PLAT_PICOPI_SD == 3 +#define PLAT_PICOPI_BOOT_MMC_BASE USDHC3_BASE +#endif /* PLAT_PICOPI_SD == 3 */ + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS 8000000 /* 8 MHz */ + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c b/arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c new file mode 100644 index 0000000..2df96ae --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018-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 + +#define UART5_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\ + CCM_TRGT_MUX_UART5_CLK_ROOT_OSC_24M) + +#define USDHC_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\ + CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_AHB |\ + CCM_TARGET_POST_PODF(2)) + +#define USB_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\ + CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL) + +#define PICOPI_UART5_RX_MUX \ + IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT1_UART5_RX_DATA + +#define PICOPI_UART5_TX_MUX \ + IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT1_UART5_TX_DATA + +#define PICOPI_SD3_FEATURES \ + (IOMUXC_SW_PAD_CTL_PAD_SD3_PU_47K | \ + IOMUXC_SW_PAD_CTL_PAD_SD3_PE | \ + IOMUXC_SW_PAD_CTL_PAD_SD3_HYS | \ + IOMUXC_SW_PAD_CTL_PAD_SD3_SLEW_SLOW | \ + IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_3_X6) + +static struct mmc_device_info mmc_info; + +static void picopi_setup_pinmux(void) +{ + /* Configure UART5 TX */ + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_OFFSET, + PICOPI_UART5_TX_MUX); + /* Configure UART5 RX */ + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_OFFSET, + PICOPI_UART5_RX_MUX); + + /* Configure USDHC3 */ + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_CLK_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_CMD_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA0_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA1_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA2_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA3_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA4_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA5_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA6_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA7_OFFSET, 0); + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO14_OFFSET, + IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO14_ALT1_SD3_CD_B); + + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_CLK_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_CMD_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA0_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA1_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA2_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA3_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA4_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA5_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA6_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA7_OFFSET, + PICOPI_SD3_FEATURES); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO14_OFFSET, + PICOPI_SD3_FEATURES); +} + +static void picopi_usdhc_setup(void) +{ + imx_usdhc_params_t params; + + zeromem(¶ms, sizeof(imx_usdhc_params_t)); + params.reg_base = PLAT_PICOPI_BOOT_MMC_BASE; + params.clk_rate = 25000000; + params.bus_width = MMC_BUS_WIDTH_8; + mmc_info.mmc_dev_type = MMC_IS_EMMC; + imx_usdhc_init(¶ms, &mmc_info); +} + +static void picopi_setup_usb_clocks(void) +{ + uint32_t usb_en_bits = (uint32_t)USB_CLK_SELECT; + + imx_clock_set_usb_clk_root_bits(usb_en_bits); + imx_clock_enable_usb(CCM_CCGR_ID_USB_IPG); + imx_clock_enable_usb(CCM_CCGR_ID_USB_PHY_480MCLK); + imx_clock_enable_usb(CCM_CCGR_ID_USB_OTG1_PHY); + imx_clock_enable_usb(CCM_CCGR_ID_USB_OTG2_PHY); +} + +void imx7_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + uint32_t uart5_en_bits = (uint32_t)UART5_CLK_SELECT; + uint32_t usdhc_clock_sel = PLAT_PICOPI_SD - 1; + + /* Initialize clocks etc */ + imx_clock_enable_uart(4, uart5_en_bits); + imx_clock_enable_usdhc(usdhc_clock_sel, USDHC_CLK_SELECT); + + picopi_setup_usb_clocks(); + + /* Setup pin-muxes */ + picopi_setup_pinmux(); + + picopi_usdhc_setup(); +} diff --git a/arm-trusted-firmware/plat/imx/imx7/picopi/platform.mk b/arm-trusted-firmware/plat/imx/imx7/picopi/platform.mk new file mode 100644 index 0000000..5901001 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/picopi/platform.mk @@ -0,0 +1,40 @@ +# +# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Include imx7 common +include plat/imx/imx7/common/imx7.mk + +# Platform +PLAT_INCLUDES += -Iplat/imx/imx7/picopi/include \ + +BL2_SOURCES += drivers/imx/usdhc/imx_usdhc.c \ + plat/imx/imx7/picopi/picopi_bl2_el3_setup.c \ + +# Build config flags +# ------------------ + +ARM_CORTEX_A7 := yes +WORKAROUND_CVE_2017_5715 := 0 + +RESET_TO_BL31 := 0 + +# Non-TF Boot ROM +BL2_AT_EL3 := 1 + +# Indicate single-core +COLD_BOOT_SINGLE_CPU := 1 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Use multi console API +MULTI_CONSOLE_API := 1 + +PLAT_PICOPI_UART :=5 +$(eval $(call add_define,PLAT_PICOPI_UART)) diff --git a/arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h new file mode 100644 index 0000000..683e50d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#define PLATFORM_STACK_SIZE 0x1000 + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(2) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) + +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ + PLATFORM_CLUSTER1_CORE_COUNT) + +#define WARP7_PRIMARY_CPU U(0) + +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 + +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN 0 + +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET 1 + +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF 2 + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH 4 +#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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. + * i.MX7 has a 32 byte cacheline size + * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016 pg 244 + */ +#define CACHE_WRITEBACK_SHIFT 4 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Partition memory into secure BootROM, OCRAM_S, non-secure DRAM, secure DRAM + */ +#define BOOT_ROM_BASE 0x00000000 +#define BOOT_ROM_SIZE 0x00020000 + +#define OCRAM_S_BASE 0x00180000 +#define OCRAM_S_SIZE 0x00008000 + +/* Controller maps 2GB, board contains 512 MB. 0x80000000 - 0xa0000000 */ +#define DRAM_BASE 0x80000000 +#define DRAM_SIZE 0x20000000 +#define DRAM_LIMIT (DRAM_BASE + DRAM_SIZE) + +/* Place OPTEE at minus 32 MB from the end of memory. 0x9e000000 - 0xa0000000 */ +#define IMX7_OPTEE_SIZE 0x02000000 +#define IMX7_OPTEE_BASE (DRAM_LIMIT - IMX7_OPTEE_SIZE) +#define IMX7_OPTEE_LIMIT (IMX7_OPTEE_BASE + IMX7_OPTEE_SIZE) + +/* Place ATF directly beneath OPTEE. 0x9df00000 - 0x9e000000 */ +#define BL2_RAM_SIZE 0x00100000 +#define BL2_RAM_BASE (IMX7_OPTEE_BASE - BL2_RAM_SIZE) +#define BL2_RAM_LIMIT (BL2_RAM_BASE + BL2_RAM_SIZE) + +/* Optional Mailbox. Only relevant on i.MX7D. 0x9deff000 - 0x9df00000*/ +#define SHARED_RAM_SIZE 0x00001000 +#define SHARED_RAM_BASE (BL2_RAM_BASE - SHARED_RAM_SIZE) +#define SHARED_RAM_LIMIT (SHARED_RAM_BASE + SHARED_RAM_SIZE) + +/* Define the absolute location of u-boot 0x87800000 - 0x87900000 */ +#define IMX7_UBOOT_SIZE 0x00100000 +#define IMX7_UBOOT_BASE (DRAM_BASE + 0x7800000) +#define IMX7_UBOOT_LIMIT (IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE) + +/* Define FIP image absolute location 0x80000000 - 0x80100000 */ +#define IMX_FIP_SIZE 0x00100000 +#define IMX_FIP_BASE (DRAM_BASE) +#define IMX_FIP_LIMIT (IMX_FIP_BASE + IMX_FIP_SIZE) + +/* Define FIP image location at 1MB offset */ +#define IMX_FIP_MMC_BASE (1024 * 1024) + +/* Define the absolute location of DTB 0x83000000 - 0x83100000 */ +#define IMX7_DTB_SIZE 0x00100000 +#define IMX7_DTB_BASE (DRAM_BASE + 0x03000000) +#define IMX7_DTB_LIMIT (IMX7_DTB_BASE + IMX7_DTB_SIZE) + +/* Define the absolute location of DTB Overlay 0x83100000 - 0x83101000 */ +#define IMX7_DTB_OVERLAY_SIZE 0x00001000 +#define IMX7_DTB_OVERLAY_BASE IMX7_DTB_LIMIT +#define IMX7_DTB_OVERLAY_LIMIT (IMX7_DTB_OVERLAY_BASE + \ + IMX7_DTB_OVERLAY_SIZE) + +/* + * BL2 specific defines. + * + * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define BL2_BASE BL2_RAM_BASE +#define BL2_LIMIT (BL2_RAM_BASE + BL2_RAM_SIZE) + +/* + * BL3-2/OPTEE + */ +# define BL32_BASE IMX7_OPTEE_BASE +# define BL32_LIMIT (IMX7_OPTEE_BASE + IMX7_OPTEE_SIZE) + +/* + * BL3-3/U-BOOT + */ +#define BL33_BASE IMX7_UBOOT_BASE +#define BL33_LIMIT (IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE) + +/* + * ATF's view of memory + * + * 0xa0000000 +-----------------+ + * | DDR | BL32/OPTEE + * 0x9e000000 +-----------------+ + * | DDR | BL23 ATF + * 0x9df00000 +-----------------+ + * | DDR | Shared MBOX RAM + * 0x9de00000 +-----------------+ + * | DDR | Unallocated + * 0x87900000 +-----------------+ + * | DDR | BL33/U-BOOT + * 0x87800000 +-----------------+ + * | DDR | Unallocated + * 0x83101000 +-----------------+ + * | DDR | DTB Overlay + * 0x83100000 +-----------------+ + * | DDR | DTB + * 0x83000000 +-----------------+ + * | DDR | Unallocated + * 0x80100000 +-----------------+ + * | DDR | FIP + * 0x80000000 +-----------------+ + * | SOC I/0 | + * 0x00a00000 +-----------------+ + * | OCRAM | Not used + * 0x00900000 +-----------------+ + * | SOC I/0 | + * 0x00188000 +-----------------+ + * | OCRAM_S | Not used + * 0x00180000 +-----------------+ + * | SOC I/0 | + * 0x00020000 +-----------------+ + * | BootROM | BL1 + * 0x00000000 +-----------------+ + */ + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_MMAP_REGIONS 10 +#define MAX_XLAT_TABLES 6 +#define MAX_IO_DEVICES 2 +#define MAX_IO_HANDLES 3 +#define MAX_IO_BLOCK_DEVICES 1U + +/* UART defines */ +#if PLAT_WARP7_UART == 1 +#define PLAT_WARP7_UART_BASE MXC_UART1_BASE +#elif PLAT_WARP7_UART == 6 +#define IMX_UART_DTE +#define PLAT_WARP7_UART_BASE MXC_UART6_BASE +#else +#error "define PLAT_WARP7_UART=1 or PLAT_WARP7_UART=6" +#endif + +#define PLAT_IMX7_BOOT_UART_BASE PLAT_WARP7_UART_BASE +#define PLAT_IMX7_BOOT_UART_CLK_IN_HZ 24000000 +#define PLAT_IMX7_CONSOLE_BAUDRATE 115200 + +/* MMC defines */ +#ifndef PLAT_WARP7_SD +#define PLAT_WARP7_SD 3 +#endif + +#if PLAT_WARP7_SD == 1 +#define PLAT_WARP7_BOOT_MMC_BASE USDHC1_BASE +#endif /* PLAT_WARP7_SD == 1 */ + +#if PLAT_WARP7_SD == 2 +#define PLAT_WARP7_BOOT_MMC_BASE USDHC2_BASE +#endif /* PLAT_WARP7_SD == 2 */ + +#if PLAT_WARP7_SD == 3 +#define PLAT_WARP7_BOOT_MMC_BASE USDHC3_BASE +#endif /* PLAT_WARP7_SD == 3 */ + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS 8000000 /* 8 MHz */ + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/imx/imx7/warp7/platform.mk b/arm-trusted-firmware/plat/imx/imx7/warp7/platform.mk new file mode 100644 index 0000000..ea0f001 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/warp7/platform.mk @@ -0,0 +1,37 @@ +# +# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Include imx7 common +include plat/imx/imx7/common/imx7.mk + +# Platform +PLAT_INCLUDES += -Iplat/imx/imx7/warp7/include + +BL2_SOURCES += drivers/imx/usdhc/imx_usdhc.c \ + plat/imx/imx7/warp7/warp7_bl2_el3_setup.c + +# Build config flags +# ------------------ + +ARM_CORTEX_A7 := yes +WORKAROUND_CVE_2017_5715 := 0 + +RESET_TO_BL31 := 0 + +# Non-TF Boot ROM +BL2_AT_EL3 := 1 + +# Indicate single-core +COLD_BOOT_SINGLE_CPU := 1 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +PLAT_WARP7_UART :=1 +$(eval $(call add_define,PLAT_WARP7_UART)) diff --git a/arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c b/arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c new file mode 100644 index 0000000..ec13ade --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018-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 + +#define UART1_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\ + CCM_TRGT_MUX_UART1_CLK_ROOT_OSC_24M) + +#define UART6_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\ + CCM_TRGT_MUX_UART6_CLK_ROOT_OSC_24M) + +#define USDHC_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\ + CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_AHB |\ + CCM_TARGET_POST_PODF(2)) + +#define USB_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\ + CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL) + +#define WARP7_UART1_TX_MUX \ + IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT0_UART1_TX_DATA + +#define WARP7_UART1_TX_FEATURES \ + (IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_3_100K_PU | \ + IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PE_EN | \ + IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_HYS_EN | \ + IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_1_X4) + +#define WARP7_UART1_RX_MUX \ + IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT0_UART1_RX_DATA + +#define WARP7_UART1_RX_FEATURES \ + (IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_3_100K_PU | \ + IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PE_EN | \ + IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_HYS_EN | \ + IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_1_X4) + +#define WARP7_UART6_TX_MUX \ + IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT1_UART6_TX_DATA + +#define WARP7_UART6_TX_FEATURES \ + (IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_3_100K_PU | \ + IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PE_EN | \ + IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_HYS_EN | \ + IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_1_X4) + +#define WARP7_UART6_RX_MUX \ + IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT1_UART6_RX_DATA + +#define WARP7_UART6_RX_FEATURES \ + (IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_3_100K_PU | \ + IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PE_EN | \ + IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_HYS_EN | \ + IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_1_X4) + +static struct mmc_device_info mmc_info; + +static void warp7_setup_pinmux(void) +{ + /* Configure UART1 TX */ + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_OFFSET, + WARP7_UART1_TX_MUX); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_OFFSET, + WARP7_UART1_TX_FEATURES); + + /* Configure UART1 RX */ + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_OFFSET, + WARP7_UART1_RX_MUX); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_OFFSET, + WARP7_UART1_RX_FEATURES); + + /* Configure UART6 TX */ + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_OFFSET, + WARP7_UART6_TX_MUX); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_OFFSET, + WARP7_UART6_TX_FEATURES); + + /* Configure UART6 RX */ + imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_OFFSET, + WARP7_UART6_RX_MUX); + imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_OFFSET, + WARP7_UART6_RX_FEATURES); +} + +static void warp7_usdhc_setup(void) +{ + imx_usdhc_params_t params; + + zeromem(¶ms, sizeof(imx_usdhc_params_t)); + params.reg_base = PLAT_WARP7_BOOT_MMC_BASE; + params.clk_rate = 25000000; + params.bus_width = MMC_BUS_WIDTH_8; + mmc_info.mmc_dev_type = MMC_IS_EMMC; + imx_usdhc_init(¶ms, &mmc_info); +} + +static void warp7_setup_usb_clocks(void) +{ + uint32_t usb_en_bits = (uint32_t)USB_CLK_SELECT; + + imx_clock_set_usb_clk_root_bits(usb_en_bits); + imx_clock_enable_usb(CCM_CCGR_ID_USB_IPG); + imx_clock_enable_usb(CCM_CCGR_ID_USB_PHY_480MCLK); + imx_clock_enable_usb(CCM_CCGR_ID_USB_OTG1_PHY); + imx_clock_enable_usb(CCM_CCGR_ID_USB_OTG2_PHY); +} + +void imx7_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + uint32_t uart1_en_bits = (uint32_t)UART1_CLK_SELECT; + uint32_t uart6_en_bits = (uint32_t)UART6_CLK_SELECT; + uint32_t usdhc_clock_sel = PLAT_WARP7_SD - 1; + + /* Initialize clocks etc */ + imx_clock_enable_uart(0, uart1_en_bits); + imx_clock_enable_uart(5, uart6_en_bits); + + imx_clock_enable_usdhc(usdhc_clock_sel, USDHC_CLK_SELECT); + + warp7_setup_usb_clocks(); + + /* Setup pin-muxes */ + warp7_setup_pinmux(); + + warp7_usdhc_setup(); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/gpc_common.c b/arm-trusted-firmware/plat/imx/imx8m/gpc_common.c new file mode 100644 index 0000000..1e55f05 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/gpc_common.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +static uint32_t gpc_imr_offset[] = { IMR1_CORE0_A53, IMR1_CORE1_A53, IMR1_CORE2_A53, IMR1_CORE3_A53, }; + +DEFINE_BAKERY_LOCK(gpc_lock); + +#pragma weak imx_set_cpu_pwr_off +#pragma weak imx_set_cpu_pwr_on +#pragma weak imx_set_cpu_lpm +#pragma weak imx_set_cluster_powerdown + +void imx_set_cpu_secure_entry(unsigned int core_id, uintptr_t sec_entrypoint) +{ + uint64_t temp_base; + + temp_base = (uint64_t) sec_entrypoint; + temp_base >>= 2; + + mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3), + ((uint32_t)(temp_base >> 22) & 0xffff)); + mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3) + 4, + ((uint32_t)temp_base & 0x003fffff)); +} + +void imx_set_cpu_pwr_off(unsigned int core_id) +{ + + bakery_lock_get(&gpc_lock); + + /* enable the wfi power down of the core */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id)); + + bakery_lock_release(&gpc_lock); + + /* assert the pcg pcr bit of the core */ + mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); +} + +void imx_set_cpu_pwr_on(unsigned int core_id) +{ + bakery_lock_get(&gpc_lock); + + /* clear the wfi power down bit of the core */ + mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id)); + + bakery_lock_release(&gpc_lock); + + /* assert the ncpuporeset */ + mmio_clrbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id)); + /* assert the pcg pcr bit of the core */ + mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); + /* sw power up the core */ + mmio_setbits_32(IMX_GPC_BASE + CPU_PGC_UP_TRG, (1 << core_id)); + + /* wait for the power up finished */ + while ((mmio_read_32(IMX_GPC_BASE + CPU_PGC_UP_TRG) & (1 << core_id)) != 0) + ; + + /* deassert the pcg pcr bit of the core */ + mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); + /* deassert the ncpuporeset */ + mmio_setbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id)); +} + +void imx_set_cpu_lpm(unsigned int core_id, bool pdn) +{ + bakery_lock_get(&gpc_lock); + + if (pdn) { + /* enable the core WFI PDN & IRQ PUP */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | + COREx_IRQ_WUP(core_id)); + /* assert the pcg pcr bit of the core */ + mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); + } else { + /* disbale CORE WFI PDN & IRQ PUP */ + mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | + COREx_IRQ_WUP(core_id)); + /* deassert the pcg pcr bit of the core */ + mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); + } + + bakery_lock_release(&gpc_lock); +} + +/* + * the plat and noc can only be power up & down by slot method, + * slot0: plat power down; slot1: noc power down; slot2: noc power up; + * slot3: plat power up. plat's pup&pdn ack is used by default. if + * noc is config to power down, then noc's pdn ack should be used. + */ +static void imx_a53_plat_slot_config(bool pdn) +{ + if (pdn) { + mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), PLAT_PDN_SLT_CTRL); + mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(3), PLAT_PUP_SLT_CTRL); + mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_PLAT_PDN_ACK | + A53_PLAT_PUP_ACK); + mmio_setbits_32(IMX_GPC_BASE + PLAT_PGC_PCR, 0x1); + } else { + mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), PLAT_PDN_SLT_CTRL); + mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(3), PLAT_PUP_SLT_CTRL); + mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK | + A53_DUMMY_PDN_ACK); + mmio_clrbits_32(IMX_GPC_BASE + PLAT_PGC_PCR, 0x1); + } +} + +void imx_set_cluster_standby(bool enter) +{ + /* + * Enable BIT 6 of A53 AD register to make sure system + * don't enter LPM mode. + */ + if (enter) + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6)); + else + mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6)); +} + +/* i.mx8mq need to override it */ +void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state) +{ + uint32_t val; + + if (!is_local_state_run(power_state)) { + /* config C0~1's LPM, enable a53 clock off in LPM */ + mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, A53_CLK_ON_LPM, + LPM_MODE(power_state)); + /* config C2-3's LPM */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, LPM_MODE(power_state)); + + /* enable PLAT/SCU power down */ + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); + val &= ~EN_L2_WFI_PDN; + /* L2 cache memory is on in WAIT mode */ + if (is_local_state_off(power_state)) { + val |= (L2PGE | EN_PLAT_PDN); + imx_a53_plat_slot_config(true); + } + + mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); + } else { + /* clear the slot and ack for cluster power down */ + imx_a53_plat_slot_config(false); + /* reverse the cluster level setting */ + mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, 0xf, A53_CLK_ON_LPM); + mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, 0xf); + + /* clear PLAT/SCU power down */ + mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_AD, (L2PGE | EN_PLAT_PDN), + EN_L2_WFI_PDN); + } +} + +static 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)); +} + +/* + * gic's clock will be gated in system suspend, so gic has no ability to + * to wakeup the system, we need to config the imr based on the irq + * enable status in gic, then gpc will monitor the wakeup irq + */ +void imx_set_sys_wakeup(unsigned int last_core, bool pdn) +{ + uint32_t irq_mask; + uintptr_t gicd_base = PLAT_GICD_BASE; + + if (pdn) + mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, A53_CORE_WUP_SRC(last_core), + IRQ_SRC_A53_WUP); + else + mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, IRQ_SRC_A53_WUP, + A53_CORE_WUP_SRC(last_core)); + + /* clear last core's IMR based on GIC's mask setting */ + for (int i = 0; i < IRQ_IMR_NUM; i++) { + if (pdn) + /* set the wakeup irq base GIC */ + irq_mask = ~gicd_read_isenabler(gicd_base, 32 * (i + 1)); + else + irq_mask = IMR_MASK_ALL; + + mmio_write_32(IMX_GPC_BASE + gpc_imr_offset[last_core] + i * 4, + irq_mask); + } +} + +#pragma weak imx_noc_slot_config +/* + * this function only need to be override by platform + * that support noc power down, for example: imx8mm. + * otherwize, keep it empty. + */ +void imx_noc_slot_config(bool pdn) +{ + +} + +/* this is common for all imx8m soc */ +void imx_set_sys_lpm(unsigned int last_core, bool retention) +{ + uint32_t val; + + val = mmio_read_32(IMX_GPC_BASE + SLPCR); + val &= ~(SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS | + SLPCR_BYPASS_PMIC_READY | SLPCR_A53_FASTWUP_STOP_MODE); + + if (retention) + val |= (SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS | + SLPCR_BYPASS_PMIC_READY | SLPCR_A53_FASTWUP_STOP_MODE); + + mmio_write_32(IMX_GPC_BASE + SLPCR, val); + + /* config the noc power down */ + imx_noc_slot_config(retention); + + /* config wakeup irqs' mask in gpc */ + imx_set_sys_wakeup(last_core, retention); +} + +void imx_set_rbc_count(void) +{ + mmio_setbits_32(IMX_GPC_BASE + SLPCR, SLPCR_RBC_EN | + (0x8 << SLPCR_RBC_COUNT_SHIFT)); +} + +void imx_clear_rbc_count(void) +{ + mmio_clrbits_32(IMX_GPC_BASE + SLPCR, SLPCR_RBC_EN | + (0x3f << SLPCR_RBC_COUNT_SHIFT)); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c new file mode 100644 index 0000000..478005e --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +void imx8m_caam_init(void) +{ + uint32_t sm_cmd; + + /* Dealloc part 0 and 2 with current DID */ + sm_cmd = (0 << SMC_PART_SHIFT | SMC_CMD_DEALLOC_PART); + mmio_write_32(SM_CMD, sm_cmd); + + sm_cmd = (2 << SMC_PART_SHIFT | SMC_CMD_DEALLOC_PART); + mmio_write_32(SM_CMD, sm_cmd); + + /* config CAAM JRaMID set MID to Cortex A */ + mmio_write_32(CAAM_JR0MID, CAAM_NS_MID); + mmio_write_32(CAAM_JR1MID, CAAM_NS_MID); + mmio_write_32(CAAM_JR2MID, CAAM_NS_MID); + + /* Alloc partition 0 writing SMPO and SMAGs */ + mmio_write_32(SM_P0_PERM, 0xff); + mmio_write_32(SM_P0_SMAG2, 0xffffffff); + mmio_write_32(SM_P0_SMAG1, 0xffffffff); + + /* Allocate page 0 and 1 to partition 0 with DID set */ + sm_cmd = (0 << SMC_PAGE_SHIFT | 0 << SMC_PART_SHIFT | + SMC_CMD_ALLOC_PAGE); + mmio_write_32(SM_CMD, sm_cmd); + + sm_cmd = (1 << SMC_PAGE_SHIFT | 0 << SMC_PART_SHIFT | + SMC_CMD_ALLOC_PAGE); + mmio_write_32(SM_CMD, sm_cmd); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c new file mode 100644 index 0000000..8b2fdd6 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2022, Linaro. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#if MEASURED_BOOT +#include +#endif +#include +#include + +#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr" +#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size" + +#if MEASURED_BOOT + +static int imx8m_event_log_fdt_init_overlay(uintptr_t dt_base, int dt_size) +{ + int ret; + int offset; + void *dtb = (void *)dt_base; + + ret = fdt_create_empty_tree(dtb, dt_size); + if (ret < 0) { + ERROR("cannot create empty dtb tree: %s\n", + fdt_strerror(ret)); + return ret; + } + + offset = fdt_path_offset(dtb, "/"); + if (offset < 0) { + ERROR("cannot find root of the tree: %s\n", + fdt_strerror(offset)); + return offset; + } + + offset = fdt_add_subnode(dtb, offset, "fragment@0"); + if (offset < 0) { + ERROR("cannot add fragment node: %s\n", + fdt_strerror(offset)); + return offset; + } + + ret = fdt_setprop_string(dtb, offset, "target-path", "/"); + if (ret < 0) { + ERROR("cannot set target-path property: %s\n", + fdt_strerror(ret)); + return ret; + } + + offset = fdt_add_subnode(dtb, offset, "__overlay__"); + if (offset < 0) { + ERROR("cannot add __overlay__ node: %s\n", + fdt_strerror(offset)); + return ret; + } + + offset = fdt_add_subnode(dtb, offset, "tpm_event_log"); + if (offset < 0) { + ERROR("cannot add tpm_event_log node: %s\n", + fdt_strerror(offset)); + return offset; + } + + ret = fdt_setprop_string(dtb, offset, "compatible", + "arm,tpm_event_log"); + if (ret < 0) { + ERROR("cannot set compatible property: %s\n", + fdt_strerror(ret)); + return ret; + } + + ret = fdt_setprop_u64(dtb, offset, "tpm_event_log_addr", 0); + if (ret < 0) { + ERROR("cannot set tpm_event_log_addr property: %s\n", + fdt_strerror(ret)); + return ret; + } + + ret = fdt_setprop_u32(dtb, offset, "tpm_event_log_size", 0); + if (ret < 0) { + ERROR("cannot set tpm_event_log_size property: %s\n", + fdt_strerror(ret)); + return ret; + } + + return ret; +} + +/* + * Write the Event Log address and its size in the DTB. + * + * This function is supposed to be called only by BL2. + * + * Returns: + * 0 = success + * < 0 = error + */ +static int imx8m_set_event_log_info(uintptr_t config_base, + uintptr_t log_addr, size_t log_size) +{ + /* As libfdt uses void *, we can't avoid this cast */ + void *dtb = (void *)config_base; + const char *compatible_tpm = "arm,tpm_event_log"; + uint64_t base = cpu_to_fdt64(log_addr); + uint32_t sz = cpu_to_fdt32(log_size); + int err, node; + + err = fdt_open_into(dtb, dtb, PLAT_IMX8M_DTO_MAX_SIZE); + if (err < 0) { + ERROR("Invalid Device Tree at %p: error %d\n", dtb, err); + return err; + } + + /* + * Verify that the DTB is valid, before attempting to write to it, + * and get the DTB root node. + */ + + /* Check if the pointer to DT is correct */ + err = fdt_check_header(dtb); + if (err < 0) { + WARN("Invalid DTB file passed\n"); + return err; + } + + /* + * Find the TPM node in device tree. + */ + node = fdt_node_offset_by_compatible(dtb, -1, compatible_tpm); + if (node < 0) { + ERROR("The compatible property '%s' not%s", compatible_tpm, + " found in the config\n"); + return node; + } + + err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_ADDR, &base, 8); + if (err < 0) { + ERROR("Failed to add log addr err %d\n", err); + return err; + } + + err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_SIZE, &sz, 4); + if (err < 0) { + ERROR("Failed to add log addr err %d\n", err); + return err; + } + + err = fdt_pack(dtb); + if (err < 0) { + ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, err); + return err; + } + + /* + * Ensure that the info written to the DTB is visible + * to other images. + */ + flush_dcache_range(config_base, fdt_totalsize(dtb)); + + return err; +} + +/* + * This function writes the Event Log address and its size + * in the QEMU DTB. + * + * This function is supposed to be called only by BL2. + * + * Returns: + * 0 = success + * < 0 = error + */ +int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr) +{ + uintptr_t ns_addr; + int err; + + assert(ns_log_addr != NULL); + + ns_addr = PLAT_IMX8M_DTO_BASE + PLAT_IMX8M_DTO_MAX_SIZE; + + imx8m_event_log_fdt_init_overlay(PLAT_IMX8M_DTO_BASE, + PLAT_IMX8M_DTO_MAX_SIZE); + + /* Write the Event Log address and its size in the DTB */ + err = imx8m_set_event_log_info(PLAT_IMX8M_DTO_BASE, + ns_addr, log_size); + + /* Return Event Log address in Non-secure memory */ + *ns_log_addr = (err < 0) ? 0UL : ns_addr; + return err; +} + +#endif /* MEASURED_BOOT */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c new file mode 100644 index 0000000..3a03069 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +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(); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c new file mode 100644 index 0000000..ec61606 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2022, Linaro. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "./include/imx8m_measured_boot.h" +#include +#include + +/* Event Log data */ +static uint8_t event_log[PLAT_IMX_EVENT_LOG_MAX_SIZE]; + +/* FVP table with platform specific image IDs, names and PCRs */ +static const event_log_metadata_t imx8m_event_log_metadata[] = { + { BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 }, + { BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 }, + { BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 }, + { BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 }, + { BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 }, + { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */ +}; + +const event_log_metadata_t *plat_event_log_get_metadata(void) +{ + return imx8m_event_log_metadata; +} + +int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data) +{ + /* Calculate image hash and record data in Event Log */ + int err = event_log_measure_and_record(image_data->image_base, + image_data->image_size, + image_id); + if (err != 0) { + ERROR("%s%s image id %u (%i)\n", + "Failed to ", "record", image_id, err); + return err; + } + + return 0; +} + +void bl2_plat_mboot_init(void) +{ + event_log_init(event_log, event_log + sizeof(event_log)); + event_log_write_header(); +} + +void bl2_plat_mboot_finish(void) +{ + int rc = 0; + + /* Event Log address in Non-Secure memory */ + uintptr_t ns_log_addr; + + /* Event Log filled size */ + size_t event_log_cur_size; + + event_log_cur_size = event_log_get_cur_size(event_log); + + rc = imx8m_set_nt_fw_info(event_log_cur_size, &ns_log_addr); + if (rc != 0) { + ERROR("%s(): Unable to update %s_FW_CONFIG\n", + __func__, "NT"); + /* + * It is a fatal error because on i.MX U-boot assumes that + * a valid event log exists and will use it to record the + * measurements into the fTPM. + */ + panic(); + } + + /* Copy Event Log to Non-secure memory */ + (void)memcpy((void *)ns_log_addr, (const void *)event_log, + event_log_cur_size); + + /* Ensure that the Event Log is visible in Non-secure memory */ + flush_dcache_range(ns_log_addr, event_log_cur_size); + + dump_event_log((uint8_t *)event_log, event_log_cur_size); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c new file mode 100644 index 0000000..9dfd311 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * below callback functions need to be override by i.mx8mq, + * for other i.mx8m soc, if no special requirement, + * reuse below ones. + */ +#pragma weak imx_validate_power_state +#pragma weak imx_domain_suspend +#pragma weak imx_domain_suspend_finish +#pragma weak imx_get_sys_suspend_power_state + +int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) +{ + /* The non-secure entrypoint should be in RAM space */ + if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +int imx_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core_id; + uint64_t base_addr = BL31_BASE; + + core_id = MPIDR_AFFLVL0_VAL(mpidr); + + imx_set_cpu_secure_entry(core_id, base_addr); + imx_set_cpu_pwr_on(core_id); + + return PSCI_E_SUCCESS; +} + +void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + plat_gic_pcpu_init(); + plat_gic_cpuif_enable(); +} + +void imx_pwr_domain_off(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); + + plat_gic_cpuif_disable(); + imx_set_cpu_pwr_off(core_id); +} + +int imx_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int pwr_type = psci_get_pstate_type(power_state); + int state_id = psci_get_pstate_id(power_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + if (pwr_type == PSTATE_TYPE_STANDBY) { + CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + } + + if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) { + CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_WAIT_RET_STATE; + } + + return PSCI_E_SUCCESS; +} + +void imx_cpu_standby(plat_local_state_t cpu_state) +{ + dsb(); + write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); + isb(); + + wfi(); + + write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT)); + isb(); +} + +void imx_domain_suspend(const psci_power_state_t *target_state) +{ + uint64_t base_addr = BL31_BASE; + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + plat_gic_cpuif_disable(); + imx_set_cpu_secure_entry(core_id, base_addr); + imx_set_cpu_lpm(core_id, true); + } else { + dsb(); + write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); + isb(); + } + + if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) + imx_set_cluster_powerdown(core_id, CLUSTER_PWR_STATE(target_state)); + + if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) + imx_set_sys_lpm(core_id, true); +} + +void imx_domain_suspend_finish(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) + imx_set_sys_lpm(core_id, false); + + if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) { + imx_clear_rbc_count(); + imx_set_cluster_powerdown(core_id, PSCI_LOCAL_STATE_RUN); + } + + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + imx_set_cpu_lpm(core_id, false); + plat_gic_cpuif_enable(); + } else { + write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT)); + isb(); + } +} + +void imx_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE; +} + +static void __dead2 imx_wdog_restart(bool external_reset) +{ + uintptr_t wdog_base = IMX_WDOG_BASE; + unsigned int val; + + val = mmio_read_16(wdog_base); + /* + * Common watchdog init flags, for additional details check + * 6.6.4.1 Watchdog Control Register (WDOGx_WCR) + * + * Initial bit selection: + * WDOG_WCR_WDE - Enable the watchdog. + * + * 0x000E mask is used to keep previous values (that could be set + * in SPL) of WDBG and WDE/WDT (both are write-one once-only bits). + */ + val = (val & 0x000E) | WDOG_WCR_WDE; + if (external_reset) { + /* + * To assert WDOG_B (external reset) we have + * to set WDA bit 0 (already set in previous step). + * SRS bits are required to be set to 1 (no effect on the + * system). + */ + val |= WDOG_WCR_SRS; + } else { + /* + * To assert Software Reset Signal (internal reset) we have + * to set SRS bit to 0 (already set in previous step). + * SRE bit is required to be set to 1 when used in + * conjunction with the Software Reset Signal before + * SRS asserton, otherwise SRS bit will just automatically + * reset to 1. + * + * Also we set WDA to 1 (no effect on system). + */ + val |= WDOG_WCR_SRE | WDOG_WCR_WDA; + } + + mmio_write_16(wdog_base, val); + + mmio_write_16(wdog_base + WDOG_WSR, 0x5555); + mmio_write_16(wdog_base + WDOG_WSR, 0xaaaa); + while (1) + ; +} + +void __dead2 imx_system_reset(void) +{ +#ifdef IMX_WDOG_B_RESET + imx_wdog_restart(true); +#else + imx_wdog_restart(false); +#endif +} + +int imx_system_reset2(int is_vendor, int reset_type, u_register_t cookie) +{ + imx_wdog_restart(false); + + /* + * imx_wdog_restart cannot return (as it's a __dead function), + * however imx_system_reset2 has to return some value according + * to PSCI v1.1 spec. + */ + return 0; +} + +void __dead2 imx_system_off(void) +{ + mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, SNVS_LPCR_SRTC_ENV | + SNVS_LPCR_DP_EN | SNVS_LPCR_TOP); + + while (1) + ; +} + +void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + /* + * before enter WAIT or STOP mode with PLAT(SCU) power down, + * rbc count need to be enabled to make sure PLAT is + * power down successfully even if the the wakeup IRQ is pending + * early before the power down sequence. the RBC counter is + * drived by the 32K OSC, so delay 30us to make sure the counter + * is really running. + */ + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) { + imx_set_rbc_count(); + udelay(30); + } + + while (1) + wfi(); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c new file mode 100644 index 0000000..ab59292 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019, 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 + +void imx_gpc_init(void) +{ + unsigned int val; + int i; + + /* mask all the wakeup irq by default */ + for (i = 0; i < 4; i++) { + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0); + } + + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + /* use GIC wake_request to wakeup C0~C3 from LPM */ + val |= 0x30c00000; + /* clear the MASTER0 LPM handshake */ + val &= ~(1 << 6); + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */ + mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING | + MASTER2_MAPPING)); + + /* set all mix/PU in A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff); + + /* + * Set the CORE & SCU power up timing: + * SW = 0x1, SW2ISO = 0x1; + * the CPU CORE and SCU power up timming counter + * is drived by 32K OSC, each domain's power up + * latency is (SW + SW2ISO) / 32768 + */ + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING, + (0x59 << 10) | 0x5B | (0x2 << 20)); + + /* set DUMMY PDN/PUP ACK by default for A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, + A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK); + + /* clear DSM by default */ + val = mmio_read_32(IMX_GPC_BASE + SLPCR); + val &= ~SLPCR_EN_DSM; + /* enable the fast wakeup wait mode */ + val |= SLPCR_A53_FASTWUP_WAIT_MODE; + /* clear the RBC */ + val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT); + /* set the STBY_COUNT to 0x5, (128 * 30)us */ + val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT); + val |= (0x5 << SLPCR_STBY_COUNT_SHFT); + mmio_write_32(IMX_GPC_BASE + SLPCR, val); + + /* + * USB PHY power up needs to make sure RESET bit in SRC is clear, + * otherwise, the PU power up bit in GPC will NOT self-cleared. + * only need to do it once. + */ + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1); + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1); + + /* enable all the power domain by default */ + mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x3fcf); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c new file mode 100644 index 0000000..c39dd93 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c @@ -0,0 +1,143 @@ +/* + * Copyright 2017-2021 NXP + * Copyright 2021 Arm + * + * 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 "imx8mm_private.h" +#include "platform_def.h" + +static const struct aipstz_cfg aipstz[] = { + {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {0}, +}; + +static void imx8mm_usdhc_setup(void) +{ + imx_usdhc_params_t params; + struct mmc_device_info info; + + params.reg_base = PLAT_IMX8MM_BOOT_MMC_BASE; + /* + The imx8mm SD Card Speed modes for USDHC2 + +--------------+--------------------+--------------+--------------+ + |Bus Speed Mode|Max. Clock Frequency|Max. Bus Speed|Signal Voltage| + +--------------+--------------------+--------------+--------------+ + |Default Speed | 25 MHz | 12.5 MB/s | 3.3V | + |High Speed | 50 MHz | 25 MB/s | 3.3V | + +--------------+--------------------+--------------+--------------+ + + We pick 50 Mhz here for High Speed access. + */ + params.clk_rate = 50000000; + params.bus_width = MMC_BUS_WIDTH_1; + params.flags = 0; + info.mmc_dev_type = MMC_IS_SD; + info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3; + imx_usdhc_init(¶ms, &info); +} + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + int i; + static console_t console; + + /* enable CSU NS access permission */ + for (i = 0; i < MAX_CSU_NUM; i++) { + mmio_write_32(IMX_CSU_BASE + i * 4, CSU_CSL_OPEN_ACCESS); + } + + /* config the aips access permission */ + imx_aipstz_init(aipstz); + + console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); + + generic_delay_timer_init(); + + /* select the CKIL source to 32K OSC */ + mmio_write_32(0x30360124, 0x1); + + imx8mm_usdhc_setup(); + + /* Open handles to a FIP image */ + plat_imx_io_setup(); +} + +void bl2_el3_plat_arch_setup(void) +{ +} + +void bl2_platform_setup(void) +{ +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; + + assert(bl_mem_params); + + switch (image_id) { + case BL32_IMAGE_ID: + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } + + break; + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} + +void bl2_plat_runtime_setup(void) +{ + return; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c new file mode 100644 index 0000000..e44345d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static bl_mem_params_node_t bl2_mem_params_descs[] = { + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, 0), + + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_SIZE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + /* This is a zero sized image so we don't set base or size */ + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, + NON_SECURE | EXECUTABLE), + # ifdef PRELOADED_BL33_BASE + .ep_info.pc = PLAT_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + # else + .ep_info.pc = PLAT_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_NS_IMAGE_OFFSET, + .image_info.image_max_size = PLAT_NS_IMAGE_SIZE, + # endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs); diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c new file mode 100644 index 0000000..40110d7 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2019, 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 + +#include +#include +#include +#include +#include +#include + +static const mmap_region_t imx_mmap[] = { + MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */ + {0}, +}; + +static const struct aipstz_cfg aipstz[] = { + {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {0}, +}; + +static const struct imx_rdc_cfg rdc[] = { + /* Master domain assignment */ + RDC_MDAn(0x1, DID1), + + /* peripherals domain permission */ + + /* memory region */ + + /* Sentinel */ + {0}, +}; + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* get SPSR for BL33 entry */ +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +void bl31_tzc380_setup(void) +{ + unsigned int val; + + val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28); + if ((val & GPR_TZASC_EN) != GPR_TZASC_EN) + return; + + tzc380_init(IMX_TZASC_BASE); + + /* + * Need to substact offset 0x40000000 from CPU address when + * programming tzasc region for i.mx8mm. + */ + + /* Enable 1G-5G S/NS RW */ + tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) | + TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + int i; + + /* Enable CSU NS access permission */ + for (i = 0; i < 64; i++) { + mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff); + } + + imx_aipstz_init(aipstz); + + imx_rdc_init(rdc); + + imx8m_caam_init(); + + console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); + /* This console is only used for boot stage */ + console_set_scope(&console, CONSOLE_FLAG_BOOT); + + /* + * tell BL3-1 where the non-secure software image is located + * and the entry state information. + */ + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#ifdef SPD_opteed + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = 0; + + /* Pass TEE base and size to bl33 */ + bl33_image_ep_info.args.arg1 = BL32_BASE; + bl33_image_ep_info.args.arg2 = BL32_SIZE; +#endif + + bl31_tzc380_setup(); +} + +void bl31_plat_arch_setup(void) +{ + mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE), + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE), + MT_MEMORY | MT_RO | MT_SECURE); +#if USE_COHERENT_MEM + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + (BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE), + MT_DEVICE | MT_RW | MT_SECURE); +#endif + mmap_add(imx_mmap); + + init_xlat_tables(); + + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + + /* select the CKIL source to 32K OSC */ + mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1); + + plat_gic_driver_init(); + plat_gic_init(); + + imx_gpc_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) + return &bl33_image_ep_info; + if (type == SECURE) + return &bl32_image_ep_info; + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c new file mode 100644 index 0000000..815d3a2 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +static const plat_psci_ops_t imx_plat_psci_ops = { + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .pwr_domain_off = imx_pwr_domain_off, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, + .validate_power_state = imx_validate_power_state, + .cpu_standby = imx_cpu_standby, + .pwr_domain_suspend = imx_domain_suspend, + .pwr_domain_suspend_finish = imx_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi, + .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, + .system_reset = imx_system_reset, + .system_reset2 = imx_system_reset2, + .system_off = imx_system_off, +}; + +/* export the platform specific psci ops */ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + /* sec_entrypoint is used for warm reset */ + imx_mailbox_init(sec_entrypoint); + + *psci_ops = &imx_plat_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S new file mode 100644 index 0000000..544ee8a --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global imx8mm_rotpk_hash + .global imx8mm_rotpk_hash_end +imx8mm_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +imx8mm_rotpk_hash_end: diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c new file mode 100644 index 0000000..a4384d7 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +extern char imx8mm_rotpk_hash[], imx8mm_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = imx8mm_rotpk_hash; + *key_len = imx8mm_rotpk_hash_end - imx8mm_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h new file mode 100644 index 0000000..1a4eae5 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h @@ -0,0 +1,129 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPC_REG_H +#define GPC_REG_H + +#define LPCR_A53_BSC 0x0 +#define LPCR_A53_BSC2 0x108 +#define LPCR_A53_AD 0x4 +#define LPCR_M4 0x8 +#define SLPCR 0x14 +#define MST_CPU_MAPPING 0x18 +#define MLPCR 0x20 +#define PGC_ACK_SEL_A53 0x24 +#define IMR1_CORE0_A53 0x30 +#define IMR1_CORE1_A53 0x40 +#define IMR1_CORE2_A53 0x1C0 +#define IMR1_CORE3_A53 0x1D0 +#define IMR1_CORE0_M4 0x50 +#define SLT0_CFG 0xB0 +#define GPC_PU_PWRHSK 0x1FC +#define PGC_CPU_0_1_MAPPING 0xEC +#define CPU_PGC_UP_TRG 0xF0 +#define PU_PGC_UP_TRG 0xF8 +#define CPU_PGC_DN_TRG 0xFC +#define PU_PGC_DN_TRG 0x104 +#define LPS_CPU1 0x114 +#define A53_CORE0_PGC 0x800 +#define A53_PLAT_PGC 0x900 +#define PLAT_PGC_PCR 0x900 +#define NOC_PGC_PCR 0xa40 +#define PGC_SCU_TIMING 0x910 + +#define MASK_DSM_TRIGGER_A53 BIT(31) +#define IRQ_SRC_A53_WUP BIT(30) +#define IRQ_SRC_A53_WUP_SHIFT 30 +#define IRQ_SRC_C1 BIT(29) +#define IRQ_SRC_C0 BIT(28) +#define IRQ_SRC_C3 BIT(23) +#define IRQ_SRC_C2 BIT(22) +#define CPU_CLOCK_ON_LPM BIT(14) +#define A53_CLK_ON_LPM BIT(14) +#define MASTER0_LPM_HSK BIT(6) +#define MASTER1_LPM_HSK BIT(7) +#define MASTER2_LPM_HSK BIT(8) + +#define L2PGE BIT(31) +#define EN_L2_WFI_PDN BIT(5) +#define EN_PLAT_PDN BIT(4) + +#define SLPCR_EN_DSM BIT(31) +#define SLPCR_RBC_EN BIT(30) +#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17) +#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16) +#define SLPCR_VSTBY BIT(2) +#define SLPCR_SBYOS BIT(1) +#define SLPCR_BYPASS_PMIC_READY BIT(0) +#define SLPCR_RBC_COUNT_SHIFT 24 +#define SLPCR_STBY_COUNT_SHFT 3 + +#define A53_DUMMY_PDN_ACK BIT(15) +#define A53_DUMMY_PUP_ACK BIT(31) +#define A53_PLAT_PDN_ACK BIT(2) +#define A53_PLAT_PUP_ACK BIT(18) +#define NOC_PDN_SLT_CTRL BIT(10) +#define NOC_PUP_SLT_CTRL BIT(11) +#define NOC_PGC_PDN_ACK BIT(3) +#define NOC_PGC_PUP_ACK BIT(19) + +#define PLAT_PUP_SLT_CTRL BIT(9) +#define PLAT_PDN_SLT_CTRL BIT(8) + +#define SLT_PLAT_PDN BIT(8) +#define SLT_PLAT_PUP BIT(9) + +#define MASTER1_MAPPING BIT(1) +#define MASTER2_MAPPING BIT(2) + +#define MIPI_PWR_REQ BIT(0) +#define PCIE_PWR_REQ BIT(1) +#define OTG1_PWR_REQ BIT(2) +#define OTG2_PWR_REQ BIT(3) +#define HSIOMIX_PWR_REQ BIT(4) +#define DDRMIX_PWR_REQ BIT(5) +#define GPU2D_PWR_REQ BIT(6) +#define GPUMIX_PWR_REQ BIT(7) +#define VPUMIX_PWR_REQ BIT(8) +#define GPU3D_PWR_REQ BIT(9) +#define DISPMIX_PWR_REQ BIT(10) +#define VPU_G1_PWR_REQ BIT(11) +#define VPU_G2_PWR_REQ BIT(12) +#define VPU_H1_PWR_REQ BIT(13) + +#define DDRMIX_ADB400_SYNC BIT(2) +#define HSIOMIX_ADB400_SYNC (0x3 << 5) +#define DISPMIX_ADB400_SYNC BIT(7) +#define VPUMIX_ADB400_SYNC BIT(8) +#define GPU3D_ADB400_SYNC BIT(9) +#define GPU2D_ADB400_SYNC BIT(10) +#define GPUMIX_ADB400_SYNC BIT(11) +#define DDRMIX_ADB400_ACK BIT(20) +#define HSIOMIX_ADB400_ACK (0x3 << 23) +#define DISPMIX_ADB400_ACK BIT(25) +#define VPUMIX_ADB400_ACK BIT(26) +#define GPU3D_ADB400_ACK BIT(27) +#define GPU2D_ADB400_ACK BIT(28) +#define GPUMIX_ADB400_ACK BIT(29) + +#define MIPI_PGC 0xc00 +#define PCIE_PGC 0xc40 +#define OTG1_PGC 0xc80 +#define OTG2_PGC 0xcc0 +#define HSIOMIX_PGC 0xd00 +#define DDRMIX_PGC 0xd40 +#define GPU2D_PGC 0xd80 +#define GPUMIX_PGC 0xdc0 +#define VPUMIX_PGC 0xe00 +#define GPU3D_PGC 0xe40 +#define DISPMIX_PGC 0xe80 +#define VPU_G1_PGC 0xec0 +#define VPU_G2_PGC 0xf00 +#define VPU_H1_PGC 0xf40 + +#define IRQ_IMR_NUM U(4) + +#endif /* GPC_REG_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h new file mode 100644 index 0000000..5e0ef97 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8MM_PRIVATE_H +#define IMX8MM_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_imx_io_setup(void); + +#endif /* IMX8MM_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h new file mode 100644 index 0000000..300ef9e --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0xB00 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU U(0x0) +#define PLATFORM_MAX_CPU_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) + +#define IMX_PWR_LVL0 MPIDR_AFFLVL0 +#define IMX_PWR_LVL1 MPIDR_AFFLVL1 +#define IMX_PWR_LVL2 MPIDR_AFFLVL2 + +#define PWR_DOMAIN_AT_MAX_LVL U(1) +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_OFF_STATE U(4) +#define PLAT_MAX_RET_STATE U(2) + +#define PLAT_WAIT_RET_STATE U(1) +#define PLAT_STOP_OFF_STATE U(3) + +#define PLAT_PRI_BITS U(3) +#define PLAT_SDEI_CRITICAL_PRI 0x10 +#define PLAT_SDEI_NORMAL_PRI 0x20 +#define PLAT_SDEI_SGI_PRIVATE U(9) + +#if defined(NEED_BL2) +#define BL2_BASE U(0x920000) +#define BL2_LIMIT U(0x940000) +#define BL31_BASE U(0x900000) +#define BL31_LIMIT U(0x920000) +#define IMX_FIP_BASE U(0x40310000) +#define IMX_FIP_SIZE U(0x000300000) +#define IMX_FIP_LIMIT U(FIP_BASE + FIP_SIZE) + +/* Define FIP image location on eMMC */ +#define IMX_FIP_MMC_BASE U(0x100000) + +#define PLAT_IMX8MM_BOOT_MMC_BASE U(0x30B50000) /* SD */ +#else +#define BL31_BASE U(0x920000) +#define BL31_LIMIT U(0x940000) +#endif + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET U(0x40200000) +#define PLAT_NS_IMAGE_SIZE U(0x00200000) + +/* GICv3 base address */ +#define PLAT_GICD_BASE U(0x38800000) +#define PLAT_GICR_BASE U(0x38880000) + +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) + +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 16 + +#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */ + +#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */ + +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT_CRASH_UART_CLK_IN_HZ 24000000 +#define IMX_CONSOLE_BAUDRATE 115200 + +#define IMX_AIPSTZ1 U(0x301f0000) +#define IMX_AIPSTZ2 U(0x305f0000) +#define IMX_AIPSTZ3 U(0x309f0000) +#define IMX_AIPSTZ4 U(0x32df0000) + +#define IMX_AIPS_BASE U(0x30000000) +#define IMX_AIPS_SIZE U(0xC00000) +#define IMX_GPV_BASE U(0x32000000) +#define IMX_GPV_SIZE U(0x800000) +#define IMX_AIPS1_BASE U(0x30200000) +#define IMX_AIPS4_BASE U(0x32c00000) +#define IMX_ANAMIX_BASE U(0x30360000) +#define IMX_CCM_BASE U(0x30380000) +#define IMX_SRC_BASE U(0x30390000) +#define IMX_GPC_BASE U(0x303a0000) +#define IMX_RDC_BASE U(0x303d0000) +#define IMX_CSU_BASE U(0x303e0000) +#define IMX_WDOG_BASE U(0x30280000) +#define IMX_SNVS_BASE U(0x30370000) +#define IMX_NOC_BASE U(0x32700000) +#define IMX_TZASC_BASE U(0x32F80000) +#define IMX_IOMUX_GPR_BASE U(0x30340000) +#define IMX_CAAM_BASE U(0x30900000) +#define IMX_DDRC_BASE U(0x3d400000) +#define IMX_DDRPHY_BASE U(0x3c000000) +#define IMX_DDR_IPS_BASE U(0x3d000000) +#define IMX_ROM_BASE U(0x0) + +#define GPV_BASE U(0x32000000) +#define GPV_SIZE U(0x800000) +#define IMX_GIC_BASE PLAT_GICD_BASE +#define IMX_GIC_SIZE U(0x200000) + +#define WDOG_WSR U(0x2) +#define WDOG_WCR_WDZST BIT(0) +#define WDOG_WCR_WDBG BIT(1) +#define WDOG_WCR_WDE BIT(2) +#define WDOG_WCR_WDT BIT(3) +#define WDOG_WCR_SRS BIT(4) +#define WDOG_WCR_WDA BIT(5) +#define WDOG_WCR_SRE BIT(6) +#define WDOG_WCR_WDW BIT(7) + +#define SRC_A53RCR0 U(0x4) +#define SRC_A53RCR1 U(0x8) +#define SRC_OTG1PHY_SCR U(0x20) +#define SRC_OTG2PHY_SCR U(0x24) +#define SRC_GPR1_OFFSET U(0x74) +#define SRC_GPR10_OFFSET U(0x98) +#define SRC_GPR10_PERSIST_SECONDARY_BOOT BIT(30) + +#define SNVS_LPCR U(0x38) +#define SNVS_LPCR_SRTC_ENV BIT(0) +#define SNVS_LPCR_DP_EN BIT(5) +#define SNVS_LPCR_TOP BIT(6) + +#define IOMUXC_GPR10 U(0x28) +#define GPR_TZASC_EN BIT(0) +#define GPR_TZASC_EN_LOCK BIT(16) + +#define ANAMIX_MISC_CTL U(0x124) + +#define MAX_CSU_NUM U(64) + +#define OCRAM_S_BASE U(0x00180000) +#define OCRAM_S_SIZE U(0x8000) +#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE) + +#define COUNTER_FREQUENCY 8000000 /* 8MHz */ + +#define IMX_WDOG_B_RESET + +#define MAX_IO_HANDLES 3U +#define MAX_IO_DEVICES 2U +#define MAX_IO_BLOCK_DEVICES 1U + +#define PLAT_IMX8M_DTO_BASE 0x53000000 +#define PLAT_IMX8M_DTO_MAX_SIZE 0x1000 +#define PLAT_IMX_EVENT_LOG_MAX_SIZE UL(0x400) diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/platform.mk b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/platform.mk new file mode 100644 index 0000000..cd8de89 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/platform.mk @@ -0,0 +1,165 @@ +# +# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/common/include \ + -Iplat/imx/imx8m/include \ + -Iplat/imx/imx8m/imx8mm/include \ + -Idrivers/imx/usdhc \ + -Iinclude/common/tbbr \ + -Iinclude/lib/libfdt + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +include lib/libfdt/libfdt.mk + +IMX_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/imx/common/imx8_helpers.S \ + plat/imx/imx8m/gpc_common.c \ + plat/imx/imx8m/imx_aipstz.c \ + plat/imx/imx8m/imx_rdc.c \ + plat/imx/imx8m/imx8m_caam.c \ + plat/imx/imx8m/imx8m_psci_common.c \ + plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c \ + plat/imx/imx8m/imx8mm/imx8mm_psci.c \ + plat/imx/imx8m/imx8mm/gpc.c \ + plat/imx/common/imx8_topology.c \ + plat/imx/common/imx_sip_handler.c \ + plat/imx/common/imx_sip_svc.c \ + plat/imx/common/imx_uart_console.S \ + plat/imx/common/imx_ehf.c \ + plat/imx/common/imx_sdei.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/arm/tzc/tzc380.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${IMX_GIC_SOURCES} + +ifeq (${NEED_BL2},yes) +BL2_SOURCES += common/desc_image_load.c \ + common/fdt_wrappers.c \ + plat/imx/common/imx8_helpers.S \ + plat/imx/common/imx_uart_console.S \ + plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c \ + plat/imx/imx8m/imx8mm/gpc.c \ + plat/imx/imx8m/imx_aipstz.c \ + plat/common/plat_psci_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${PLAT_GIC_SOURCES} \ + ${PLAT_DRAM_SOURCES} \ + drivers/mmc/mmc.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + drivers/imx/usdhc/imx_usdhc.c \ + plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c \ + plat/imx/common/imx_io_storage.c \ + plat/imx/imx8m/imx8m_image_load.c \ + lib/optee/optee_utils.c +endif + +# Add the build options to pack BLx images and kernel device tree +# in the FIP if the platform requires. +ifneq ($(BL2),) +RESET_TO_BL31 := 0 +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) +endif +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif +ifneq ($(HW_CONFIG),) +$(eval $(call TOOL_ADD_IMG,HW_CONFIG,--hw-config)) +endif + +ifeq (${NEED_BL2},yes) +$(eval $(call add_define,NEED_BL2)) +LOAD_IMAGE_V2 := 1 +# Non-TF Boot ROM +BL2_AT_EL3 := 1 +endif + +ifneq (${TRUSTED_BOARD_BOOT},0) + +include drivers/auth/mbedtls/mbedtls_crypto.mk +include drivers/auth/mbedtls/mbedtls_x509.mk + +AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c \ + plat/imx/imx8m/imx8mm/imx8mm_rotpk.S + +ROT_KEY = $(BUILD_PLAT)/rot_key.pem +ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + +$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) +$(eval $(call MAKE_LIB_DIRS)) + +$(BUILD_PLAT)/bl2/imx8mm_rotpk.o: $(ROTPK_HASH) + +certificates: $(ROT_KEY) + +$(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + @if [ ! -f $(ROT_KEY) ]; then \ + openssl genrsa 2048 > $@ 2>/dev/null; \ + fi + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 + +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +BL32_BASE ?= 0xbe000000 +$(eval $(call add_define,BL32_BASE)) + +BL32_SIZE ?= 0x2000000 +$(eval $(call add_define,BL32_SIZE)) + +IMX_BOOT_UART_BASE ?= 0x30890000 +$(eval $(call add_define,IMX_BOOT_UART_BASE)) + +EL3_EXCEPTION_HANDLING := 1 +SDEI_SUPPORT := 1 + +ifeq (${MEASURED_BOOT},1) + MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk + $(info Including ${MEASURED_BOOT_MK}) + include ${MEASURED_BOOT_MK} + +BL2_SOURCES += plat/imx/imx8m/imx8m_measured_boot.c \ + plat/imx/imx8m/imx8m_dyn_cfg_helpers.c \ + ${EVENT_LOG_SOURCES} + +endif diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c new file mode 100644 index 0000000..37d4226 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c @@ -0,0 +1,94 @@ +/* + * Copyright 2019-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define CCGR(x) (0x4000 + (x) * 0x10) + +void imx_gpc_init(void) +{ + unsigned int val; + int i; + + /* mask all the wakeup irq by default */ + for (i = 0; i < 4; i++) { + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0); + } + + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + /* use GIC wake_request to wakeup C0~C3 from LPM */ + val |= CORE_WKUP_FROM_GIC; + /* clear the MASTER0 LPM handshake */ + val &= ~MASTER0_LPM_HSK; + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */ + mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING | + MASTER2_MAPPING)); + + /* set all mix/PU in A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff); + + /* + * Set the CORE & SCU power up timing: + * SW = 0x1, SW2ISO = 0x1; + * the CPU CORE and SCU power up timming counter + * is drived by 32K OSC, each domain's power up + * latency is (SW + SW2ISO) / 32768 + */ + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING, + (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT)); + + /* set DUMMY PDN/PUP ACK by default for A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, + A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK); + + /* clear DSM by default */ + val = mmio_read_32(IMX_GPC_BASE + SLPCR); + val &= ~SLPCR_EN_DSM; + /* enable the fast wakeup wait mode */ + val |= SLPCR_A53_FASTWUP_WAIT_MODE; + /* clear the RBC */ + val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT); + /* set the STBY_COUNT to 0x5, (128 * 30)us */ + val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT); + val |= (0x5 << SLPCR_STBY_COUNT_SHFT); + mmio_write_32(IMX_GPC_BASE + SLPCR, val); + + /* + * USB PHY power up needs to make sure RESET bit in SRC is clear, + * otherwise, the PU power up bit in GPC will NOT self-cleared. + * only need to do it once. + */ + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1); + + /* enable all the power domain by default */ + for (i = 0; i < 103; i++) + mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3); + mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x485); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c new file mode 100644 index 0000000..d4705ee --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c @@ -0,0 +1,186 @@ +/* + * Copyright 2019-2020 NXP + * + * 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 + +static const mmap_region_t imx_mmap[] = { + GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP, {0}, +}; + +static const struct aipstz_cfg aipstz[] = { + {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {0}, +}; + +static const struct imx_rdc_cfg rdc[] = { + /* Master domain assignment */ + RDC_MDAn(0x1, DID1), + + /* peripherals domain permission */ + + /* memory region */ + RDC_MEM_REGIONn(16, 0x0, 0x0, 0xff), + RDC_MEM_REGIONn(17, 0x0, 0x0, 0xff), + RDC_MEM_REGIONn(18, 0x0, 0x0, 0xff), + + /* Sentinel */ + {0}, +}; + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* get SPSR for BL33 entry */ +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +static void bl31_tzc380_setup(void) +{ + unsigned int val; + + val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28); + if ((val & GPR_TZASC_EN) != GPR_TZASC_EN) + return; + + tzc380_init(IMX_TZASC_BASE); + + /* + * Need to substact offset 0x40000000 from CPU address when + * programming tzasc region for i.mx8mn. + */ + + /* Enable 1G-5G S/NS RW */ + tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) | + TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + int i; + + /* Enable CSU NS access permission */ + for (i = 0; i < 64; i++) { + mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff); + } + + imx_aipstz_init(aipstz); + + imx_rdc_init(rdc); + + imx8m_caam_init(); + + console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); + /* This console is only used for boot stage */ + console_set_scope(&console, CONSOLE_FLAG_BOOT); + + /* + * tell BL3-1 where the non-secure software image is located + * and the entry state information. + */ + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#ifdef SPD_opteed + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = 0; + + /* Pass TEE base and size to bl33 */ + bl33_image_ep_info.args.arg1 = BL32_BASE; + bl33_image_ep_info.args.arg2 = BL32_SIZE; +#endif + + bl31_tzc380_setup(); +} + +void bl31_plat_arch_setup(void) +{ + mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE), + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE), + MT_MEMORY | MT_RO | MT_SECURE); +#if USE_COHERENT_MEM + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + (BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE), + MT_DEVICE | MT_RW | MT_SECURE); +#endif + mmap_add(imx_mmap); + + init_xlat_tables(); + + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + + /* select the CKIL source to 32K OSC */ + mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1); + + plat_gic_driver_init(); + plat_gic_init(); + + imx_gpc_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) + return &bl33_image_ep_info; + if (type == SECURE) + return &bl32_image_ep_info; + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c new file mode 100644 index 0000000..f541fc1 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c @@ -0,0 +1,44 @@ +/* + * Copyright 2019-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +static const plat_psci_ops_t imx_plat_psci_ops = { + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .pwr_domain_off = imx_pwr_domain_off, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, + .validate_power_state = imx_validate_power_state, + .cpu_standby = imx_cpu_standby, + .pwr_domain_suspend = imx_domain_suspend, + .pwr_domain_suspend_finish = imx_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi, + .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, + .system_reset = imx_system_reset, + .system_off = imx_system_off, +}; + +/* export the platform specific psci ops */ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + /* sec_entrypoint is used for warm reset */ + imx_mailbox_init(sec_entrypoint); + + *psci_ops = &imx_plat_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h new file mode 100644 index 0000000..8a81368 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h @@ -0,0 +1,111 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPC_REG_H +#define GPC_REG_H + +#define LPCR_A53_BSC 0x0 +#define LPCR_A53_BSC2 0x108 +#define LPCR_A53_AD 0x4 +#define LPCR_M4 0x8 +#define SLPCR 0x14 +#define MST_CPU_MAPPING 0x18 +#define MLPCR 0x20 +#define PGC_ACK_SEL_A53 0x24 +#define IMR1_CORE0_A53 0x30 +#define IMR1_CORE1_A53 0x40 +#define IMR1_CORE2_A53 0x1C0 +#define IMR1_CORE3_A53 0x1D0 +#define IMR1_CORE0_M4 0x50 +#define SLT0_CFG 0xB0 +#define GPC_PU_PWRHSK 0x1FC +#define PGC_CPU_0_1_MAPPING 0xEC +#define CPU_PGC_UP_TRG 0xF0 +#define PU_PGC_UP_TRG 0xF8 +#define CPU_PGC_DN_TRG 0xFC +#define PU_PGC_DN_TRG 0x104 +#define LPS_CPU1 0x114 +#define A53_CORE0_PGC 0x800 +#define A53_PLAT_PGC 0x900 +#define PLAT_PGC_PCR 0x900 +#define NOC_PGC_PCR 0xa40 +#define PGC_SCU_TIMING 0x910 + +#define MASK_DSM_TRIGGER_A53 BIT(31) +#define IRQ_SRC_A53_WUP BIT(30) +#define IRQ_SRC_A53_WUP_SHIFT 30 +#define IRQ_SRC_C1 BIT(29) +#define IRQ_SRC_C0 BIT(28) +#define IRQ_SRC_C3 BIT(23) +#define IRQ_SRC_C2 BIT(22) +#define CPU_CLOCK_ON_LPM BIT(14) +#define A53_CLK_ON_LPM BIT(14) +#define MASTER0_LPM_HSK BIT(6) +#define MASTER1_LPM_HSK BIT(7) +#define MASTER2_LPM_HSK BIT(8) + +#define L2PGE BIT(31) +#define EN_L2_WFI_PDN BIT(5) +#define EN_PLAT_PDN BIT(4) + +#define SLPCR_EN_DSM BIT(31) +#define SLPCR_RBC_EN BIT(30) +#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17) +#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16) +#define SLPCR_VSTBY BIT(2) +#define SLPCR_SBYOS BIT(1) +#define SLPCR_BYPASS_PMIC_READY BIT(0) +#define SLPCR_RBC_COUNT_SHIFT 24 +#define SLPCR_STBY_COUNT_SHFT 3 + +#define A53_DUMMY_PDN_ACK BIT(15) +#define A53_DUMMY_PUP_ACK BIT(31) +#define A53_PLAT_PDN_ACK BIT(2) +#define A53_PLAT_PUP_ACK BIT(18) +#define NOC_PDN_SLT_CTRL BIT(10) +#define NOC_PUP_SLT_CTRL BIT(11) +#define NOC_PGC_PDN_ACK BIT(3) +#define NOC_PGC_PUP_ACK BIT(19) + +#define PLAT_PUP_SLT_CTRL BIT(9) +#define PLAT_PDN_SLT_CTRL BIT(8) + +#define SLT_PLAT_PDN BIT(8) +#define SLT_PLAT_PUP BIT(9) + +#define MASTER1_MAPPING BIT(1) +#define MASTER2_MAPPING BIT(2) + +#define TMR_TCD2_SHIFT 0 +#define TMC_TMR_SHIFT 10 +#define TRC1_TMC_SHIFT 20 + +#define MIPI_PWR_REQ BIT(0) +#define OTG1_PWR_REQ BIT(2) +#define HSIOMIX_PWR_REQ BIT(4) +#define DDRMIX_PWR_REQ BIT(5) +#define GPUMIX_PWR_REQ BIT(7) +#define DISPMIX_PWR_REQ BIT(10) + +#define DDRMIX_ADB400_SYNC BIT(2) +#define HSIOMIX_ADB400_SYNC BIT(5) +#define DISPMIX_ADB400_SYNC BIT(7) +#define GPUMIX_ADB400_SYNC (0x5 << 9) +#define DDRMIX_ADB400_ACK BIT(20) +#define HSIOMIX_ADB400_ACK BIT(23) +#define DISPMIX_ADB400_ACK BIT(25) +#define GPUMIX_ADB400_ACK (0x5 << 27) + +#define MIPI_PGC 0xc00 +#define OTG1_PGC 0xc80 +#define HSIOMIX_PGC 0xd00 +#define DDRMIX_PGC 0xd40 +#define GPUMIX_PGC 0xdc0 +#define DISPMIX_PGC 0xe80 + +#define IRQ_IMR_NUM U(4) + +#endif /* GPC_REG_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h new file mode 100644 index 0000000..9c46d8d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h @@ -0,0 +1,140 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0xB00 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU U(0x0) +#define PLATFORM_MAX_CPU_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) + +#define IMX_PWR_LVL0 MPIDR_AFFLVL0 +#define IMX_PWR_LVL1 MPIDR_AFFLVL1 +#define IMX_PWR_LVL2 MPIDR_AFFLVL2 + +#define PWR_DOMAIN_AT_MAX_LVL U(1) +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_OFF_STATE U(4) +#define PLAT_MAX_RET_STATE U(2) + +#define PLAT_WAIT_RET_STATE U(1) +#define PLAT_STOP_OFF_STATE U(3) + +#define PLAT_PRI_BITS U(3) +#define PLAT_SDEI_CRITICAL_PRI 0x10 +#define PLAT_SDEI_NORMAL_PRI 0x20 +#define PLAT_SDEI_SGI_PRIVATE U(9) + +#define BL31_BASE U(0x960000) +#define BL31_LIMIT U(0x980000) + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET U(0x40200000) + +/* GICv3 base address */ +#define PLAT_GICD_BASE U(0x38800000) +#define PLAT_GICR_BASE U(0x38880000) + +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 16 + +#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */ + +#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */ +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT_CRASH_UART_CLK_IN_HZ 24000000 +#define IMX_CONSOLE_BAUDRATE 115200 + +#define IMX_AIPSTZ1 U(0x301f0000) +#define IMX_AIPSTZ2 U(0x305f0000) +#define IMX_AIPSTZ3 U(0x309f0000) +#define IMX_AIPSTZ4 U(0x32df0000) + +#define IMX_AIPS_BASE U(0x30000000) +#define IMX_AIPS_SIZE U(0xC00000) +#define IMX_GPV_BASE U(0x32000000) +#define IMX_GPV_SIZE U(0x800000) +#define IMX_AIPS1_BASE U(0x30200000) +#define IMX_AIPS4_BASE U(0x32c00000) +#define IMX_ANAMIX_BASE U(0x30360000) +#define IMX_CCM_BASE U(0x30380000) +#define IMX_SRC_BASE U(0x30390000) +#define IMX_GPC_BASE U(0x303a0000) +#define IMX_RDC_BASE U(0x303d0000) +#define IMX_CSU_BASE U(0x303e0000) +#define IMX_WDOG_BASE U(0x30280000) +#define IMX_SNVS_BASE U(0x30370000) +#define IMX_NOC_BASE U(0x32700000) +#define IMX_TZASC_BASE U(0x32F80000) +#define IMX_IOMUX_GPR_BASE U(0x30340000) +#define IMX_CAAM_BASE U(0x30900000) +#define IMX_DDRC_BASE U(0x3d400000) +#define IMX_DDRPHY_BASE U(0x3c000000) +#define IMX_DDR_IPS_BASE U(0x3d000000) +#define IMX_DDR_IPS_SIZE U(0x1800000) +#define IMX_ROM_BASE U(0x0) + +#define IMX_GIC_BASE PLAT_GICD_BASE +#define IMX_GIC_SIZE U(0x200000) + +#define WDOG_WSR U(0x2) +#define WDOG_WCR_WDZST BIT(0) +#define WDOG_WCR_WDBG BIT(1) +#define WDOG_WCR_WDE BIT(2) +#define WDOG_WCR_WDT BIT(3) +#define WDOG_WCR_SRS BIT(4) +#define WDOG_WCR_WDA BIT(5) +#define WDOG_WCR_SRE BIT(6) +#define WDOG_WCR_WDW BIT(7) + +#define SRC_A53RCR0 U(0x4) +#define SRC_A53RCR1 U(0x8) +#define SRC_OTG1PHY_SCR U(0x20) +#define SRC_GPR1_OFFSET U(0x74) + +#define SNVS_LPCR U(0x38) +#define SNVS_LPCR_SRTC_ENV BIT(0) +#define SNVS_LPCR_DP_EN BIT(5) +#define SNVS_LPCR_TOP BIT(6) + +#define IOMUXC_GPR10 U(0x28) +#define GPR_TZASC_EN BIT(0) +#define GPR_TZASC_EN_LOCK BIT(16) + +#define ANAMIX_MISC_CTL U(0x124) +#define DRAM_PLL_CTRL (IMX_ANAMIX_BASE + 0x50) + +#define MAX_CSU_NUM U(64) + +#define OCRAM_S_BASE U(0x00180000) +#define OCRAM_S_SIZE U(0x8000) +#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE) +#define SAVED_DRAM_TIMING_BASE OCRAM_S_BASE + +#define COUNTER_FREQUENCY 8000000 /* 8MHz */ + +#define IMX_WDOG_B_RESET + +#define GIC_MAP MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW) +#define AIPS_MAP MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */ +#define OCRAM_S_MAP MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_DEVICE | MT_RW) /* OCRAM_S */ +#define DDRC_MAP MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */ + +#endif /* platform_def.h */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/platform.mk b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/platform.mk new file mode 100644 index 0000000..2087089 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/platform.mk @@ -0,0 +1,61 @@ +# +# Copyright 2019-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/common/include \ + -Iplat/imx/imx8m/include \ + -Iplat/imx/imx8m/imx8mn/include +# Translation tables library +include lib/xlat_tables_v2/xlat_tables.mk + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +IMX_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/imx/common/imx8_helpers.S \ + plat/imx/imx8m/gpc_common.c \ + plat/imx/imx8m/imx_aipstz.c \ + plat/imx/imx8m/imx_rdc.c \ + plat/imx/imx8m/imx8m_caam.c \ + plat/imx/imx8m/imx8m_psci_common.c \ + plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c \ + plat/imx/imx8m/imx8mn/imx8mn_psci.c \ + plat/imx/imx8m/imx8mn/gpc.c \ + plat/imx/common/imx8_topology.c \ + plat/imx/common/imx_sip_handler.c \ + plat/imx/common/imx_sip_svc.c \ + plat/imx/common/imx_uart_console.S \ + plat/imx/common/imx_ehf.c \ + plat/imx/common/imx_sdei.c \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/arm/tzc/tzc380.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${IMX_GIC_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} + +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 + +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +BL32_BASE ?= 0xbe000000 +$(eval $(call add_define,BL32_BASE)) + +BL32_SIZE ?= 0x2000000 +$(eval $(call add_define,BL32_SIZE)) + +IMX_BOOT_UART_BASE ?= 0x30890000 +$(eval $(call add_define,IMX_BOOT_UART_BASE)) + +EL3_EXCEPTION_HANDLING := 1 +SDEI_SUPPORT := 1 diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c new file mode 100644 index 0000000..d660e3d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c @@ -0,0 +1,379 @@ +/* + * Copyright 2019-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define CCGR(x) (0x4000 + (x) * 0x10) +#define IMR_NUM U(5) + +struct imx_noc_setting { + uint32_t domain_id; + uint32_t start; + uint32_t end; + uint32_t prioriy; + uint32_t mode; + uint32_t socket_qos_en; +}; + +enum clk_type { + CCM_ROOT_SLICE, + CCM_CCGR, +}; + +struct clk_setting { + uint32_t offset; + uint32_t val; + enum clk_type type; +}; + +enum pu_domain_id { + /* hsio ss */ + HSIOMIX, + PCIE_PHY, + USB1_PHY, + USB2_PHY, + MLMIX, + AUDIOMIX, + /* gpu ss */ + GPUMIX, + GPU2D, + GPU3D, + /* vpu ss */ + VPUMIX, + VPU_G1, + VPU_G2, + VPU_H1, + /* media ss */ + MEDIAMIX, + MEDIAMIX_ISPDWP, + MIPI_PHY1, + MIPI_PHY2, + /* HDMI ss */ + HDMIMIX, + HDMI_PHY, + DDRMIX, +}; + +/* PU domain, add some hole to minimize the uboot change */ +static struct imx_pwr_domain pu_domains[20] = { + [MIPI_PHY1] = IMX_PD_DOMAIN(MIPI_PHY1, false), + [PCIE_PHY] = IMX_PD_DOMAIN(PCIE_PHY, false), + [USB1_PHY] = IMX_PD_DOMAIN(USB1_PHY, true), + [USB2_PHY] = IMX_PD_DOMAIN(USB2_PHY, true), + [MLMIX] = IMX_MIX_DOMAIN(MLMIX, false), + [AUDIOMIX] = IMX_MIX_DOMAIN(AUDIOMIX, false), + [GPU2D] = IMX_PD_DOMAIN(GPU2D, false), + [GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false), + [VPUMIX] = IMX_MIX_DOMAIN(VPUMIX, false), + [GPU3D] = IMX_PD_DOMAIN(GPU3D, false), + [MEDIAMIX] = IMX_MIX_DOMAIN(MEDIAMIX, false), + [VPU_G1] = IMX_PD_DOMAIN(VPU_G1, false), + [VPU_G2] = IMX_PD_DOMAIN(VPU_G2, false), + [VPU_H1] = IMX_PD_DOMAIN(VPU_H1, false), + [HDMIMIX] = IMX_MIX_DOMAIN(HDMIMIX, false), + [HDMI_PHY] = IMX_PD_DOMAIN(HDMI_PHY, false), + [MIPI_PHY2] = IMX_PD_DOMAIN(MIPI_PHY2, false), + [HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false), + [MEDIAMIX_ISPDWP] = IMX_PD_DOMAIN(MEDIAMIX_ISPDWP, false), +}; + +static struct imx_noc_setting noc_setting[] = { + {MLMIX, 0x180, 0x180, 0x80000303, 0x0, 0x0}, + {AUDIOMIX, 0x200, 0x200, 0x80000303, 0x0, 0x0}, + {AUDIOMIX, 0x280, 0x480, 0x80000404, 0x0, 0x0}, + {GPUMIX, 0x500, 0x580, 0x80000303, 0x0, 0x0}, + {HDMIMIX, 0x600, 0x680, 0x80000202, 0x0, 0x1}, + {HDMIMIX, 0x700, 0x700, 0x80000505, 0x0, 0x0}, + {HSIOMIX, 0x780, 0x900, 0x80000303, 0x0, 0x0}, + {MEDIAMIX, 0x980, 0xb80, 0x80000202, 0x0, 0x1}, + {MEDIAMIX_ISPDWP, 0xc00, 0xd00, 0x80000505, 0x0, 0x0}, + {VPU_G1, 0xd80, 0xd80, 0x80000303, 0x0, 0x0}, + {VPU_G2, 0xe00, 0xe00, 0x80000303, 0x0, 0x0}, + {VPU_H1, 0xe80, 0xe80, 0x80000303, 0x0, 0x0} +}; + +static struct clk_setting hsiomix_clk[] = { + { 0x8380, 0x0, CCM_ROOT_SLICE }, + { 0x44d0, 0x0, CCM_CCGR }, + { 0x45c0, 0x0, CCM_CCGR }, +}; + +static struct aipstz_cfg aipstz5[] = { + {IMX_AIPSTZ5, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {0}, +}; + +static unsigned int pu_domain_status; + +static void imx_noc_qos(unsigned int domain_id) +{ + unsigned int i; + uint32_t hurry; + + if (domain_id == HDMIMIX) { + mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22018); + mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22010); + + /* set GPR to make lcdif read hurry level 0x7 */ + hurry = mmio_read_32(IMX_HDMI_CTL_BASE + TX_CONTROL0); + hurry |= 0x00077000; + mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL0, hurry); + } + + if (domain_id == MEDIAMIX) { + /* handle mediamix special */ + mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RSTn_CSR, 0x1FFFFFF); + mmio_write_32(IMX_MEDIAMIX_CTL_BASE + CLK_EN_CSR, 0x1FFFFFF); + mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RST_DIV, 0x40030000); + + /* set GPR to make lcdif read hurry level 0x7 */ + hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL); + hurry |= 0xfc00; + mmio_write_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL, hurry); + /* set GPR to make isi write hurry level 0x7 */ + hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL); + hurry |= 0x1ff00000; + mmio_write_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL, hurry); + } + + /* set MIX NoC */ + for (i = 0; i < ARRAY_SIZE(noc_setting); i++) { + if (noc_setting[i].domain_id == domain_id) { + udelay(50); + uint32_t offset = noc_setting[i].start; + + while (offset <= noc_setting[i].end) { + mmio_write_32(IMX_NOC_BASE + offset + 0x8, noc_setting[i].prioriy); + mmio_write_32(IMX_NOC_BASE + offset + 0xc, noc_setting[i].mode); + mmio_write_32(IMX_NOC_BASE + offset + 0x18, noc_setting[i].socket_qos_en); + offset += 0x80; + } + } + } +} + +static void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on) +{ + struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id]; + unsigned int i; + + if (domain_id == HSIOMIX) { + for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) { + hsiomix_clk[i].val = mmio_read_32(IMX_CCM_BASE + hsiomix_clk[i].offset); + mmio_setbits_32(IMX_CCM_BASE + hsiomix_clk[i].offset, + hsiomix_clk[i].type == CCM_ROOT_SLICE ? BIT(28) : 0x3); + } + } + + if (on) { + if (pwr_domain->need_sync) { + pu_domain_status |= (1 << domain_id); + } + + if (domain_id == HDMIMIX) { + /* assert the reset */ + mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0x0); + /* enable all th function clock */ + mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF); + mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e); + } + + /* clear the PGC bit */ + mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1); + + /* power up the domain */ + mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req); + + /* wait for power request done */ + while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req) + ; + + if (domain_id == HDMIMIX) { + /* wait for memory repair done for HDMIMIX */ + while (!(mmio_read_32(IMX_SRC_BASE + 0x94) & BIT(8))) + ; + /* disable all the function clock */ + mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0x0); + mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x0); + /* deassert the reset */ + mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0xffffffff); + /* enable all the clock again */ + mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF); + mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e); + } + + if (domain_id == HSIOMIX) { + /* enable HSIOMIX clock */ + mmio_write_32(IMX_HSIOMIX_CTL_BASE, 0x2); + } + + /* handle the ADB400 sync */ + if (pwr_domain->need_sync) { + /* clear adb power down request */ + mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync); + + /* wait for adb power request ack */ + while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) + ; + } + + imx_noc_qos(domain_id); + + /* AIPS5 config is lost when audiomix is off, so need to re-init it */ + if (domain_id == AUDIOMIX) { + imx_aipstz_init(aipstz5); + } + } else { + if (pwr_domain->always_on) { + return; + } + + if (pwr_domain->need_sync) { + pu_domain_status &= ~(1 << domain_id); + } + + /* handle the ADB400 sync */ + if (pwr_domain->need_sync) { + /* set adb power down request */ + mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync); + + /* wait for adb power request ack */ + while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) + ; + } + + /* set the PGC bit */ + mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1); + + /* + * leave the G1, G2, H1 power domain on until VPUMIX power off, + * otherwise system will hang due to VPUMIX ACK + */ + if (domain_id == VPU_H1 || domain_id == VPU_G1 || domain_id == VPU_G2) { + return; + } + + if (domain_id == VPUMIX) { + mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, VPU_G1_PWR_REQ | + VPU_G2_PWR_REQ | VPU_H1_PWR_REQ); + + while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & (VPU_G1_PWR_REQ | + VPU_G2_PWR_REQ | VPU_H1_PWR_REQ)) + ; + } + + /* power down the domain */ + mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req); + + /* wait for power request done */ + while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req) + ; + + if (domain_id == HDMIMIX) { + /* disable all the clocks of HDMIMIX */ + mmio_write_32(IMX_HDMI_CTL_BASE + 0x40, 0x0); + mmio_write_32(IMX_HDMI_CTL_BASE + 0x50, 0x0); + } + } + + if (domain_id == HSIOMIX) { + for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) { + mmio_write_32(IMX_CCM_BASE + hsiomix_clk[i].offset, hsiomix_clk[i].val); + } + } +} + +void imx_gpc_init(void) +{ + uint32_t val; + unsigned int i; + + /* mask all the wakeup irq by default */ + for (i = 0; i < IMR_NUM; i++) { + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0); + } + + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + /* use GIC wake_request to wakeup C0~C3 from LPM */ + val |= CORE_WKUP_FROM_GIC; + /* clear the MASTER0 LPM handshake */ + val &= ~MASTER0_LPM_HSK; + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */ + mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING | + MASTER2_MAPPING)); + + /* set all mix/PU in A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0x3fffff); + + /* + * Set the CORE & SCU power up timing: + * SW = 0x1, SW2ISO = 0x1; + * the CPU CORE and SCU power up timming counter + * is drived by 32K OSC, each domain's power up + * latency is (SW + SW2ISO) / 32768 + */ + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401); + mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING, + (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT)); + + /* set DUMMY PDN/PUP ACK by default for A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, + A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK); + + /* clear DSM by default */ + val = mmio_read_32(IMX_GPC_BASE + SLPCR); + val &= ~SLPCR_EN_DSM; + /* enable the fast wakeup wait/stop mode */ + val |= SLPCR_A53_FASTWUP_WAIT_MODE; + val |= SLPCR_A53_FASTWUP_STOP_MODE; + /* clear the RBC */ + val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT); + /* set the STBY_COUNT to 0x5, (128 * 30)us */ + val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT); + val |= (0x5 << SLPCR_STBY_COUNT_SHFT); + mmio_write_32(IMX_GPC_BASE + SLPCR, val); + + /* + * USB PHY power up needs to make sure RESET bit in SRC is clear, + * otherwise, the PU power up bit in GPC will NOT self-cleared. + * only need to do it once. + */ + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1); + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1); + + /* enable all the power domain by default */ + for (i = 0; i < 101; i++) { + mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3); + } + + for (i = 0; i < 20; i++) { + imx_gpc_pm_domain_enable(i, true); + } +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c new file mode 100644 index 0000000..08cbeeb --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c @@ -0,0 +1,117 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "imx8mp_private.h" +#include +#include +#include +#include +#include +#include + + +static const struct aipstz_cfg aipstz[] = { + {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {0}, +}; + +void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + unsigned int i; + + /* Enable CSU NS access permission */ + for (i = 0U; i < 64; i++) { + mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff); + } + + imx_aipstz_init(aipstz); + + console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); + + generic_delay_timer_init(); + + /* select the CKIL source to 32K OSC */ + mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1); + + /* Open handles to a FIP image */ + plat_imx_io_setup(); +} + +void bl2_el3_plat_arch_setup(void) +{ +} + +void bl2_platform_setup(void) +{ +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; + + assert(bl_mem_params); + + switch (image_id) { + case BL32_IMAGE_ID: + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } + + break; + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} + +void bl2_plat_runtime_setup(void) +{ + return; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c new file mode 100644 index 0000000..f2f6808 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static bl_mem_params_node_t bl2_mem_params_descs[] = { + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, 0), + + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_SIZE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + /* This is a zero sized image so we don't set base or size */ + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, + NON_SECURE | EXECUTABLE), + # ifdef PRELOADED_BL33_BASE + .ep_info.pc = PLAT_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + # else + .ep_info.pc = PLAT_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_NS_IMAGE_OFFSET, + .image_info.image_max_size = PLAT_NS_IMAGE_SIZE, + # endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs); diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c new file mode 100644 index 0000000..22fbd5e --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c @@ -0,0 +1,187 @@ +/* + * Copyright 2020 NXP + * + * 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 + +static const mmap_region_t imx_mmap[] = { + GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP, + NOC_MAP, {0}, +}; + +static const struct aipstz_cfg aipstz[] = { + {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {0}, +}; + +static const struct imx_rdc_cfg rdc[] = { + /* Master domain assignment */ + RDC_MDAn(0x1, DID1), + + /* peripherals domain permission */ + + /* memory region */ + + /* Sentinel */ + {0}, +}; + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* get SPSR for BL33 entry */ +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +static void bl31_tzc380_setup(void) +{ + unsigned int val; + + val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28); + if ((val & GPR_TZASC_EN) != GPR_TZASC_EN) + return; + + tzc380_init(IMX_TZASC_BASE); + + /* + * Need to substact offset 0x40000000 from CPU address when + * programming tzasc region for i.mx8mp. + */ + + /* Enable 1G-5G S/NS RW */ + tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) | + TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + unsigned int i; + + /* Enable CSU NS access permission */ + for (i = 0; i < 64; i++) { + mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff); + } + + imx_aipstz_init(aipstz); + + imx_rdc_init(rdc); + + imx8m_caam_init(); + + console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); + /* This console is only used for boot stage */ + console_set_scope(&console, CONSOLE_FLAG_BOOT); + + /* + * tell BL3-1 where the non-secure software image is located + * and the entry state information. + */ + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#ifdef SPD_opteed + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = 0; + + /* Pass TEE base and size to bl33 */ + bl33_image_ep_info.args.arg1 = BL32_BASE; + bl33_image_ep_info.args.arg2 = BL32_SIZE; +#endif + + bl31_tzc380_setup(); +} + +void bl31_plat_arch_setup(void) +{ + mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE), + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE), + MT_MEMORY | MT_RO | MT_SECURE); +#if USE_COHERENT_MEM + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + (BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE), + MT_DEVICE | MT_RW | MT_SECURE); +#endif + mmap_add(imx_mmap); + + init_xlat_tables(); + + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + + /* select the CKIL source to 32K OSC */ + mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1); + + plat_gic_driver_init(); + plat_gic_init(); + + imx_gpc_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) { + return &bl33_image_ep_info; + } + + if (type == SECURE) { + return &bl32_image_ep_info; + } + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c new file mode 100644 index 0000000..bc7b246 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c @@ -0,0 +1,44 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +static const plat_psci_ops_t imx_plat_psci_ops = { + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .pwr_domain_off = imx_pwr_domain_off, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, + .validate_power_state = imx_validate_power_state, + .cpu_standby = imx_cpu_standby, + .pwr_domain_suspend = imx_domain_suspend, + .pwr_domain_suspend_finish = imx_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi, + .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, + .system_reset = imx_system_reset, + .system_off = imx_system_off, +}; + +/* export the platform specific psci ops */ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + /* sec_entrypoint is used for warm reset */ + imx_mailbox_init(sec_entrypoint); + + *psci_ops = &imx_plat_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S new file mode 100644 index 0000000..a4c7ce1 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global imx8mp_rotpk_hash + .global imx8mp_rotpk_hash_end +imx8mp_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +imx8mp_rotpk_hash_end: diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c new file mode 100644 index 0000000..5d1a6c2 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +extern char imx8mp_rotpk_hash[], imx8mp_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = imx8mp_rotpk_hash; + *key_len = imx8mp_rotpk_hash_end - imx8mp_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h new file mode 100644 index 0000000..7909937 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h @@ -0,0 +1,151 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPC_REG_H +#define GPC_REG_H + +#define LPCR_A53_BSC 0x0 +#define LPCR_A53_BSC2 0x180 +#define LPCR_A53_AD 0x4 +#define LPCR_M4 0x8 +#define SLPCR 0x14 +#define MST_CPU_MAPPING 0x18 +#define MLPCR 0x20 +#define PGC_ACK_SEL_A53 0x24 +#define IMR1_CORE0_A53 0x30 +#define IMR1_CORE1_A53 0x44 +#define IMR1_CORE2_A53 0x194 +#define IMR1_CORE3_A53 0x1A8 +#define IMR1_CORE0_M4 0x58 + +#define SLT0_CFG 0x200 +#define GPC_PU_PWRHSK 0x190 +#define PGC_CPU_0_1_MAPPING 0x1CC +#define CPU_PGC_UP_TRG 0xD0 +#define PU_PGC_UP_TRG 0xD8 +#define CPU_PGC_DN_TRG 0xDC +#define PU_PGC_DN_TRG 0xE4 +#define LPS_CPU1 0xEC + +#define A53_CORE0_PGC 0x800 +#define A53_PLAT_PGC 0x900 +#define PLAT_PGC_PCR 0x900 +#define NOC_PGC_PCR 0xa40 +#define PGC_SCU_TIMING 0x910 + +#define MASK_DSM_TRIGGER_A53 BIT(31) +#define IRQ_SRC_A53_WUP BIT(30) +#define IRQ_SRC_A53_WUP_SHIFT 30 +#define IRQ_SRC_C1 BIT(29) +#define IRQ_SRC_C0 BIT(28) +#define IRQ_SRC_C3 BIT(23) +#define IRQ_SRC_C2 BIT(22) +#define CPU_CLOCK_ON_LPM BIT(14) +#define A53_CLK_ON_LPM BIT(14) +#define MASTER0_LPM_HSK BIT(6) +#define MASTER1_LPM_HSK BIT(7) +#define MASTER2_LPM_HSK BIT(8) + +#define L2PGE BIT(31) +#define EN_L2_WFI_PDN BIT(5) +#define EN_PLAT_PDN BIT(4) + +#define SLPCR_EN_DSM BIT(31) +#define SLPCR_RBC_EN BIT(30) +#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17) +#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16) +#define SLPCR_VSTBY BIT(2) +#define SLPCR_SBYOS BIT(1) +#define SLPCR_BYPASS_PMIC_READY BIT(0) +#define SLPCR_RBC_COUNT_SHIFT 24 +#define SLPCR_STBY_COUNT_SHFT 3 + +#define A53_DUMMY_PDN_ACK BIT(30) +#define A53_DUMMY_PUP_ACK BIT(31) +#define A53_PLAT_PDN_ACK BIT(8) +#define A53_PLAT_PUP_ACK BIT(9) + +#define NOC_PDN_SLT_CTRL BIT(12) +#define NOC_PUP_SLT_CTRL BIT(13) +#define NOC_PGC_PDN_ACK BIT(12) +#define NOC_PGC_PUP_ACK BIT(13) + +#define PLAT_PUP_SLT_CTRL BIT(9) +#define PLAT_PDN_SLT_CTRL BIT(8) + +#define SLT_PLAT_PDN BIT(8) +#define SLT_PLAT_PUP BIT(9) + +#define MASTER1_MAPPING BIT(1) +#define MASTER2_MAPPING BIT(2) + +#define TMR_TCD2_SHIFT 0 +#define TMC_TMR_SHIFT 10 +#define TRC1_TMC_SHIFT 20 + +#define MIPI_PHY1_PWR_REQ BIT(0) +#define PCIE_PHY_PWR_REQ BIT(1) +#define USB1_PHY_PWR_REQ BIT(2) +#define USB2_PHY_PWR_REQ BIT(3) +#define MLMIX_PWR_REQ BIT(4) +#define AUDIOMIX_PWR_REQ BIT(5) +#define GPU2D_PWR_REQ BIT(6) +#define GPUMIX_PWR_REQ BIT(7) +#define VPUMIX_PWR_REQ BIT(8) +#define GPU3D_PWR_REQ BIT(9) +#define MEDIAMIX_PWR_REQ BIT(10) +#define VPU_G1_PWR_REQ BIT(11) +#define VPU_G2_PWR_REQ BIT(12) +#define VPU_H1_PWR_REQ BIT(13) +#define HDMIMIX_PWR_REQ BIT(14) +#define HDMI_PHY_PWR_REQ BIT(15) +#define MIPI_PHY2_PWR_REQ BIT(16) +#define HSIOMIX_PWR_REQ BIT(17) +#define MEDIAMIX_ISPDWP_PWR_REQ BIT(18) +#define DDRMIX_PWR_REQ BIT(19) + +#define AUDIOMIX_ADB400_SYNC (BIT(4) | BIT(15)) +#define MLMIX_ADB400_SYNC (BIT(7) | BIT(8)) +#define GPUMIX_ADB400_SYNC BIT(9) +#define VPUMIX_ADB400_SYNC BIT(10) +#define DDRMIX_ADB400_SYNC BIT(11) +#define HSIOMIX_ADB400_SYNC BIT(12) +#define HDMIMIX_ADB400_SYNC BIT(13) +#define MEDIAMIX_ADB400_SYNC BIT(14) + +#define AUDIOMIX_ADB400_ACK (BIT(20) | BIT(31)) +#define MLMIX_ADB400_ACK (BIT(23) | BIT(24)) +#define GPUMIX_ADB400_ACK BIT(25) +#define VPUMIX_ADB400_ACK BIT(26) +#define DDRMIX_ADB400_ACK BIT(27) +#define HSIOMIX_ADB400_ACK BIT(28) +#define HDMIMIX_ADB400_ACK BIT(29) +#define MEDIAMIX_ADB400_ACK BIT(30) + +#define MIPI_PHY1_PGC 0xb00 +#define PCIE_PHY_PGC 0xb40 +#define USB1_PHY_PGC 0xb80 +#define USB2_PHY_PGC 0xbc0 +#define MLMIX_PGC 0xc00 +#define AUDIOMIX_PGC 0xc40 +#define GPU2D_PGC 0xc80 +#define GPUMIX_PGC 0xcc0 +#define VPUMIX_PGC 0xd00 +#define GPU3D_PGC 0xd40 +#define MEDIAMIX_PGC 0xd80 +#define VPU_G1_PGC 0xdc0 +#define VPU_G2_PGC 0xe00 +#define VPU_H1_PGC 0xe40 +#define HDMIMIX_PGC 0xe80 +#define HDMI_PHY_PGC 0xec0 +#define MIPI_PHY2_PGC 0xf00 +#define HSIOMIX_PGC 0xf40 +#define MEDIAMIX_ISPDWP_PGC 0xf80 +#define DDRMIX_PGC 0xfc0 + +#define IRQ_IMR_NUM U(5) + +#endif /* GPC_REG_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h new file mode 100644 index 0000000..0a02334 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8MP_PRIVATE_H +#define IMX8MP_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_imx_io_setup(void); + +#endif /* IMX8MP_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h new file mode 100644 index 0000000..486c1ee --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h @@ -0,0 +1,180 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0xB00 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU U(0x0) +#define PLATFORM_MAX_CPU_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) + +#define IMX_PWR_LVL0 MPIDR_AFFLVL0 +#define IMX_PWR_LVL1 MPIDR_AFFLVL1 +#define IMX_PWR_LVL2 MPIDR_AFFLVL2 + +#define PWR_DOMAIN_AT_MAX_LVL U(1) +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_OFF_STATE U(4) +#define PLAT_MAX_RET_STATE U(2) + +#define PLAT_WAIT_RET_STATE U(1) +#define PLAT_STOP_OFF_STATE U(3) + +#if defined(NEED_BL2) +#define BL2_BASE U(0x970000) +#define BL2_LIMIT U(0x990000) +#define BL31_BASE U(0x950000) +#define BL31_LIMIT U(0x970000) +#define IMX_FIP_BASE U(0x40310000) +#define IMX_FIP_SIZE U(0x000300000) +#define IMX_FIP_LIMIT U(FIP_BASE + FIP_SIZE) + +/* Define FIP image location on eMMC */ +#define IMX_FIP_MMC_BASE U(0x100000) + +#define PLAT_IMX8MP_BOOT_MMC_BASE U(0x30B50000) /* SD */ +#else +#define BL31_BASE U(0x970000) +#define BL31_LIMIT U(0x990000) +#endif + +#define PLAT_PRI_BITS U(3) +#define PLAT_SDEI_CRITICAL_PRI 0x10 +#define PLAT_SDEI_NORMAL_PRI 0x20 +#define PLAT_SDEI_SGI_PRIVATE U(9) + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET U(0x40200000) +#define PLAT_NS_IMAGE_SIZE U(0x00200000) + +/* GICv3 base address */ +#define PLAT_GICD_BASE U(0x38800000) +#define PLAT_GICR_BASE U(0x38880000) + +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 16 + +#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */ + +#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */ +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT_CRASH_UART_CLK_IN_HZ 24000000 +#define IMX_CONSOLE_BAUDRATE 115200 + +#define IMX_AIPSTZ1 U(0x301f0000) +#define IMX_AIPSTZ2 U(0x305f0000) +#define IMX_AIPSTZ3 U(0x309f0000) +#define IMX_AIPSTZ4 U(0x32df0000) +#define IMX_AIPSTZ5 U(0x30df0000) + +#define IMX_AIPS_BASE U(0x30000000) +#define IMX_AIPS_SIZE U(0x3000000) +#define IMX_GPV_BASE U(0x32000000) +#define IMX_GPV_SIZE U(0x800000) +#define IMX_AIPS1_BASE U(0x30200000) +#define IMX_AIPS4_BASE U(0x32c00000) +#define IMX_ANAMIX_BASE U(0x30360000) +#define IMX_CCM_BASE U(0x30380000) +#define IMX_SRC_BASE U(0x30390000) +#define IMX_GPC_BASE U(0x303a0000) +#define IMX_RDC_BASE U(0x303d0000) +#define IMX_CSU_BASE U(0x303e0000) +#define IMX_WDOG_BASE U(0x30280000) +#define IMX_SNVS_BASE U(0x30370000) +#define IMX_NOC_BASE U(0x32700000) +#define IMX_NOC_SIZE U(0x100000) +#define IMX_TZASC_BASE U(0x32F80000) +#define IMX_IOMUX_GPR_BASE U(0x30340000) +#define IMX_CAAM_BASE U(0x30900000) +#define IMX_DDRC_BASE U(0x3d400000) +#define IMX_DDRPHY_BASE U(0x3c000000) +#define IMX_DDR_IPS_BASE U(0x3d000000) +#define IMX_DDR_IPS_SIZE U(0x1800000) +#define IMX_ROM_BASE U(0x0) + +#define IMX_GIC_BASE PLAT_GICD_BASE +#define IMX_GIC_SIZE U(0x200000) + +#define IMX_HSIOMIX_CTL_BASE U(0x32f10000) +#define IMX_HDMI_CTL_BASE U(0x32fc0000) +#define RTX_RESET_CTL0 U(0x20) +#define RTX_CLK_CTL0 U(0x40) +#define RTX_CLK_CTL1 U(0x50) +#define TX_CONTROL0 U(0x200) +#define TX_CONTROL1 U(0x220) + +#define IMX_MEDIAMIX_CTL_BASE U(0x32ec0000) +#define RSTn_CSR U(0x0) +#define CLK_EN_CSR U(0x4) +#define RST_DIV U(0x8) +#define LCDIF_ARCACHE_CTRL U(0x4c) +#define ISI_CACHE_CTRL U(0x50) + +#define WDOG_WSR U(0x2) +#define WDOG_WCR_WDZST BIT(0) +#define WDOG_WCR_WDBG BIT(1) +#define WDOG_WCR_WDE BIT(2) +#define WDOG_WCR_WDT BIT(3) +#define WDOG_WCR_SRS BIT(4) +#define WDOG_WCR_WDA BIT(5) +#define WDOG_WCR_SRE BIT(6) +#define WDOG_WCR_WDW BIT(7) + +#define SRC_A53RCR0 U(0x4) +#define SRC_A53RCR1 U(0x8) +#define SRC_OTG1PHY_SCR U(0x20) +#define SRC_OTG2PHY_SCR U(0x24) +#define SRC_GPR1_OFFSET U(0x74) + +#define SNVS_LPCR U(0x38) +#define SNVS_LPCR_SRTC_ENV BIT(0) +#define SNVS_LPCR_DP_EN BIT(5) +#define SNVS_LPCR_TOP BIT(6) + +#define IOMUXC_GPR10 U(0x28) +#define GPR_TZASC_EN BIT(0) +#define GPR_TZASC_EN_LOCK BIT(16) + +#define ANAMIX_MISC_CTL U(0x124) +#define DRAM_PLL_CTRL (IMX_ANAMIX_BASE + 0x50) + +#define MAX_CSU_NUM U(64) + +#define OCRAM_S_BASE U(0x00180000) +#define OCRAM_S_SIZE U(0x8000) +#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE) +#define SAVED_DRAM_TIMING_BASE OCRAM_S_BASE + +#define COUNTER_FREQUENCY 8000000 /* 8MHz */ + +#define IMX_WDOG_B_RESET + +#define MAX_IO_HANDLES 3U +#define MAX_IO_DEVICES 2U +#define MAX_IO_BLOCK_DEVICES 1U + +#define GIC_MAP MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW) +#define AIPS_MAP MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */ +#define OCRAM_S_MAP MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW) /* OCRAM_S */ +#define DDRC_MAP MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */ +#define NOC_MAP MAP_REGION_FLAT(IMX_NOC_BASE, IMX_NOC_SIZE, MT_DEVICE | MT_RW) /* NOC QoS */ + +#endif /* platform_def.h */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/platform.mk b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/platform.mk new file mode 100644 index 0000000..823b5d6 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/platform.mk @@ -0,0 +1,153 @@ +# +# Copyright 2019-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/common/include \ + -Iplat/imx/imx8m/include \ + -Iplat/imx/imx8m/imx8mp/include \ + -Idrivers/imx/usdhc \ + -Iinclude/common/tbbr +# Translation tables library +include lib/xlat_tables_v2/xlat_tables.mk + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +IMX_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/imx/common/imx8_helpers.S \ + plat/imx/imx8m/gpc_common.c \ + plat/imx/imx8m/imx_aipstz.c \ + plat/imx/imx8m/imx_rdc.c \ + plat/imx/imx8m/imx8m_caam.c \ + plat/imx/imx8m/imx8m_psci_common.c \ + plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c \ + plat/imx/imx8m/imx8mp/imx8mp_psci.c \ + plat/imx/imx8m/imx8mp/gpc.c \ + plat/imx/common/imx8_topology.c \ + plat/imx/common/imx_ehf.c \ + plat/imx/common/imx_sdei.c \ + plat/imx/common/imx_sip_handler.c \ + plat/imx/common/imx_sip_svc.c \ + plat/imx/common/imx_uart_console.S \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/arm/tzc/tzc380.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${IMX_GIC_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} + +ifeq (${NEED_BL2},yes) +BL2_SOURCES += common/desc_image_load.c \ + plat/imx/common/imx8_helpers.S \ + plat/imx/common/imx_uart_console.S \ + plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c \ + plat/imx/imx8m/imx8mp/gpc.c \ + plat/imx/imx8m/imx_aipstz.c \ + plat/imx/imx8m/imx_rdc.c \ + plat/imx/imx8m/imx8m_caam.c \ + plat/common/plat_psci_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/arm/tzc/tzc380.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${PLAT_GIC_SOURCES} \ + ${PLAT_DRAM_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} \ + drivers/mmc/mmc.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + drivers/imx/usdhc/imx_usdhc.c \ + plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c \ + plat/imx/common/imx_io_storage.c \ + plat/imx/imx8m/imx8m_image_load.c \ + lib/optee/optee_utils.c +endif + +# Add the build options to pack BLx images and kernel device tree +# in the FIP if the platform requires. +ifneq ($(BL2),) +RESET_TO_BL31 := 0 +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) +endif +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif +ifneq ($(HW_CONFIG),) +$(eval $(call TOOL_ADD_IMG,HW_CONFIG,--hw-config)) +endif + +ifeq (${NEED_BL2},yes) +$(eval $(call add_define,NEED_BL2)) +LOAD_IMAGE_V2 := 1 +# Non-TF Boot ROM +BL2_AT_EL3 := 1 +endif + +ifneq (${TRUSTED_BOARD_BOOT},0) + +include drivers/auth/mbedtls/mbedtls_crypto.mk +include drivers/auth/mbedtls/mbedtls_x509.mk + +AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c \ + plat/imx/imx8m/imx8mp/imx8mp_rotpk.S + +ROT_KEY = $(BUILD_PLAT)/rot_key.pem +ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + +$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) +$(eval $(call MAKE_LIB_DIRS)) + +$(BUILD_PLAT)/bl2/imx8mp_rotpk.o: $(ROTPK_HASH) + +certificates: $(ROT_KEY) + +$(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + @if [ ! -f $(ROT_KEY) ]; then \ + openssl genrsa 2048 > $@ 2>/dev/null; \ + fi + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 + +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +BL32_BASE ?= 0x56000000 +$(eval $(call add_define,BL32_BASE)) + +BL32_SIZE ?= 0x2000000 +$(eval $(call add_define,BL32_SIZE)) + +IMX_BOOT_UART_BASE ?= 0x30890000 +$(eval $(call add_define,IMX_BOOT_UART_BASE)) + +EL3_EXCEPTION_HANDLING := 1 +SDEI_SUPPORT := 1 diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c new file mode 100644 index 0000000..367c941 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* use wfi power down the core */ +void imx_set_cpu_pwr_off(unsigned int core_id) +{ + bakery_lock_get(&gpc_lock); + + /* enable the wfi power down of the core */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | + (1 << (core_id + 20))); + + bakery_lock_release(&gpc_lock); + + /* assert the pcg pcr bit of the core */ + mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); +}; + +/* if out of lpm, we need to do reverse steps */ +void imx_set_cpu_lpm(unsigned int core_id, bool pdn) +{ + bakery_lock_get(&gpc_lock); + + if (pdn) { + /* enable the core WFI PDN & IRQ PUP */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | + (1 << (core_id + 20)) | COREx_IRQ_WUP(core_id)); + /* assert the pcg pcr bit of the core */ + mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); + } else { + /* disable CORE WFI PDN & IRQ PUP */ + mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | + COREx_IRQ_WUP(core_id)); + /* deassert the pcg pcr bit of the core */ + mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); + } + + bakery_lock_release(&gpc_lock); +} + +void imx_pup_pdn_slot_config(int last_core, bool pdn) +{ + if (pdn) { + /* SLOT0 for A53 PLAT power down */ + mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), SLT_PLAT_PDN); + /* SLOT1 for A53 PLAT power up */ + mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(1), SLT_PLAT_PUP); + /* SLOT2 for A53 primary core power up */ + mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(2), SLT_COREx_PUP(last_core)); + /* ACK setting: PLAT ACK for PDN, CORE ACK for PUP */ + mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF, + A53_PLAT_PDN_ACK | A53_PLAT_PUP_ACK); + } else { + mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), 0xFFFFFFFF); + mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(1), 0xFFFFFFFF); + mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(2), 0xFFFFFFFF); + mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF, + A53_DUMMY_PDN_ACK | A53_DUMMY_PUP_ACK); + } +} + +void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state) +{ + uint32_t val; + + if (is_local_state_off(power_state)) { + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + val |= A53_LPM_STOP; /* enable C0-C1's STOP mode */ + val &= ~CPU_CLOCK_ON_LPM; /* disable CPU clock in LPM mode */ + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + /* enable C2-3's STOP mode */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_STOP); + + /* enable PLAT/SCU power down */ + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); + val &= ~EN_L2_WFI_PDN; + val |= L2PGE | EN_PLAT_PDN; + val &= ~COREx_IRQ_WUP(last_core); /* disable IRQ PUP for last core */ + val |= COREx_LPM_PUP(last_core); /* enable LPM PUP for last core */ + mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); + + imx_pup_pdn_slot_config(last_core, true); + + /* enable PLAT PGC */ + mmio_setbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1); + } else { + /* clear PLAT PGC */ + mmio_clrbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1); + + /* clear the slot and ack for cluster power down */ + imx_pup_pdn_slot_config(last_core, false); + + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + val &= ~A53_LPM_MASK; /* clear the C0~1 LPM */ + val |= CPU_CLOCK_ON_LPM; /* disable cpu clock in LPM */ + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + /* set A53 LPM to RUN mode */ + mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_MASK); + + /* clear PLAT/SCU power down */ + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); + val |= EN_L2_WFI_PDN; + val &= ~(L2PGE | EN_PLAT_PDN); + val &= ~COREx_LPM_PUP(last_core); /* disable C0's LPM PUP */ + mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); + } +} + +void imx_gpc_init(void) +{ + uint32_t val; + int i; + /* mask all the interrupt by default */ + for (i = 0; i < 4; i++) { + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0); + } + /* Due to the hardware design requirement, need to make + * sure GPR interrupt(#32) is unmasked during RUN mode to + * avoid entering DSM mode by mistake. + */ + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53, 0xFFFFFFFE); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53, 0xFFFFFFFE); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53, 0xFFFFFFFE); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53, 0xFFFFFFFE); + + /* use external IRQs to wakeup C0~C3 from LPM */ + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + val |= IRQ_SRC_A53_WUP; + /* clear the MASTER0 LPM handshake */ + val &= ~MASTER0_LPM_HSK; + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + /* mask M4 DSM trigger if M4 is NOT enabled */ + mmio_setbits_32(IMX_GPC_BASE + LPCR_M4, DSM_MODE_MASK); + + /* set all mix/PU in A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xfffd); + + /* set SCU timming */ + mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING, + (0x59 << 10) | 0x5B | (0x2 << 20)); + + /* set DUMMY PDN/PUP ACK by default for A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK | + A53_DUMMY_PDN_ACK); + + /* disable DSM mode by default */ + mmio_clrbits_32(IMX_GPC_BASE + SLPCR, DSM_MODE_MASK); + + /* + * USB PHY power up needs to make sure RESET bit in SRC is clear, + * otherwise, the PU power up bit in GPC will NOT self-cleared. + * only need to do it once. + */ + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1); + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1); + + /* enable all the power domain by default */ + mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x3fcf); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c new file mode 100644 index 0000000..05b5970 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2018-2019, 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 + +#include +#include +#include +#include +#include + +static const mmap_region_t imx_mmap[] = { + MAP_REGION_FLAT(GPV_BASE, GPV_SIZE, MT_DEVICE | MT_RW), /* GPV map */ + MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO), /* ROM map */ + MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */ + MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), /* GIC map */ + {0}, +}; + +static const struct aipstz_cfg aipstz[] = { + {AIPSTZ1_BASE, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {AIPSTZ2_BASE, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {AIPSTZ3_BASE, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {AIPSTZ4_BASE, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, }, + {0}, +}; + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +static uint32_t imx_soc_revision; + +int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, + u_register_t x3) +{ + return imx_soc_revision; +} + +#define ANAMIX_DIGPROG 0x6c +#define ROM_SOC_INFO_A0 0x800 +#define ROM_SOC_INFO_B0 0x83C +#define OCOTP_SOC_INFO_B1 0x40 + +static void imx8mq_soc_info_init(void) +{ + uint32_t rom_version; + uint32_t ocotp_val; + + imx_soc_revision = mmio_read_32(IMX_ANAMIX_BASE + ANAMIX_DIGPROG); + rom_version = mmio_read_8(IMX_ROM_BASE + ROM_SOC_INFO_A0); + if (rom_version == 0x10) + return; + + rom_version = mmio_read_8(IMX_ROM_BASE + ROM_SOC_INFO_B0); + if (rom_version == 0x20) { + imx_soc_revision &= ~0xff; + imx_soc_revision |= rom_version; + return; + } + + /* 0xff0055aa is magic number for B1 */ + ocotp_val = mmio_read_32(IMX_OCOTP_BASE + OCOTP_SOC_INFO_B1); + if (ocotp_val == 0xff0055aa) { + imx_soc_revision &= ~0xff; + imx_soc_revision |= 0x21; + return; + } +} + +/* get SPSR for BL33 entry */ +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +static void bl31_tz380_setup(void) +{ + unsigned int val; + + val = mmio_read_32(IMX_IOMUX_GPR_BASE + IOMUXC_GPR10); + if ((val & GPR_TZASC_EN) != GPR_TZASC_EN) + return; + + tzc380_init(IMX_TZASC_BASE); + /* + * Need to substact offset 0x40000000 from CPU address when + * programming tzasc region for i.mx8mq. Enable 1G-5G S/NS RW + */ + tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) | + TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + int i; + /* enable CSU NS access permission */ + for (i = 0; i < 64; i++) { + mmio_write_32(IMX_CSU_BASE + i * 4, 0xffffffff); + } + + imx_aipstz_init(aipstz); + + imx8m_caam_init(); + +#if DEBUG_CONSOLE + static console_t console; + + console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); +#endif + /* + * tell BL3-1 where the non-secure software image is located + * and the entry state information. + */ + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#ifdef SPD_opteed + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = 0; + + /* Pass TEE base and size to bl33 */ + bl33_image_ep_info.args.arg1 = BL32_BASE; + bl33_image_ep_info.args.arg2 = BL32_SIZE; +#endif + + bl31_tz380_setup(); +} + +void bl31_plat_arch_setup(void) +{ + mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE), + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE), + MT_MEMORY | MT_RO | MT_SECURE); + + mmap_add(imx_mmap); + +#if USE_COHERENT_MEM + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + /* setup xlat table */ + init_xlat_tables(); + /* enable the MMU */ + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + + /* init the GICv3 cpu and distributor interface */ + plat_gic_driver_init(); + plat_gic_init(); + + /* determine SOC revision for erratas */ + imx8mq_soc_info_init(); + + /* gpc init */ + imx_gpc_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) + return &bl33_image_ep_info; + if (type == SECURE) + return &bl32_image_ep_info; + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} + +void bl31_plat_runtime_setup(void) +{ + return; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c new file mode 100644 index 0000000..662017d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +int imx_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int pwr_type = psci_get_pstate_type(power_state); + int state_id = psci_get_pstate_id(power_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + if (pwr_type == PSTATE_TYPE_STANDBY) { + CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + } + + if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) { + CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + } + + return PSCI_E_SUCCESS; +} + +void imx_domain_suspend(const psci_power_state_t *target_state) +{ + uint64_t base_addr = BL31_BASE; + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + /* disable the cpu interface */ + plat_gic_cpuif_disable(); + imx_set_cpu_secure_entry(core_id, base_addr); + imx_set_cpu_lpm(core_id, true); + } else { + dsb(); + write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); + isb(); + } + + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) + imx_set_cluster_powerdown(core_id, true); + else + imx_set_cluster_standby(true); + + if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) { + imx_set_sys_lpm(core_id, true); + } +} + +void imx_domain_suspend_finish(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); + + /* check the system level status */ + if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) { + imx_set_sys_lpm(core_id, false); + imx_clear_rbc_count(); + } + + /* check the cluster level power status */ + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) + imx_set_cluster_powerdown(core_id, false); + else + imx_set_cluster_standby(false); + + /* check the core level power status */ + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + /* clear the core lpm setting */ + imx_set_cpu_lpm(core_id, false); + /* enable the gic cpu interface */ + plat_gic_cpuif_enable(); + } else { + write_scr_el3(read_scr_el3() & (~0x4)); + isb(); + } +} + +void imx_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + for (i = IMX_PWR_LVL0; i < PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE; + + req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE; +} + +static const plat_psci_ops_t imx_plat_psci_ops = { + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .pwr_domain_off = imx_pwr_domain_off, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, + .validate_power_state = imx_validate_power_state, + .cpu_standby = imx_cpu_standby, + .pwr_domain_suspend = imx_domain_suspend, + .pwr_domain_suspend_finish = imx_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi, + .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, + .system_reset = imx_system_reset, + .system_reset2 = imx_system_reset2, + .system_off = imx_system_off, +}; + +/* export the platform specific psci ops */ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + imx_mailbox_init(sec_entrypoint); + /* sec_entrypoint is used for warm reset */ + *psci_ops = &imx_plat_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h new file mode 100644 index 0000000..f171bd9 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h @@ -0,0 +1,89 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPC_REG_H +#define GPC_REG_H + +#define LPCR_A53_BSC 0x0 +#define LPCR_A53_BSC2 0x108 +#define LPCR_A53_AD 0x4 +#define LPCR_M4 0x8 +#define SLPCR 0x14 +#define MST_CPU_MAPPING 0x18 +#define MLPCR 0x20 +#define PGC_ACK_SEL_A53 0x24 +#define IMR1_CORE0_A53 0x30 +#define IMR1_CORE1_A53 0x40 +#define IMR1_CORE2_A53 0x1C0 +#define IMR1_CORE3_A53 0x1D0 +#define IMR1_CORE0_M4 0x50 +#define SLT0_CFG 0xB0 +#define GPC_PU_PWRHSK 0x1FC +#define PGC_CPU_0_1_MAPPING 0xEC +#define CPU_PGC_UP_TRG 0xF0 +#define PU_PGC_UP_TRG 0xF8 +#define CPU_PGC_DN_TRG 0xFC +#define PU_PGC_DN_TRG 0x104 +#define LPS_CPU1 0x114 +#define A53_CORE0_PGC 0x800 +#define A53_PLAT_PGC 0x900 +#define PLAT_PGC_PCR 0x900 +#define NOC_PGC_PCR 0xa40 +#define PGC_SCU_TIMING 0x910 + +#define MASK_DSM_TRIGGER_A53 BIT(31) +#define IRQ_SRC_A53_WUP BIT(30) +#define IRQ_SRC_A53_WUP_SHIFT 30 +#define IRQ_SRC_C1 BIT(29) +#define IRQ_SRC_C0 BIT(28) +#define IRQ_SRC_C3 BIT(23) +#define IRQ_SRC_C2 BIT(22) +#define CPU_CLOCK_ON_LPM BIT(14) +#define A53_CLK_ON_LPM BIT(14) +#define MASTER0_LPM_HSK BIT(6) +#define MASTER1_LPM_HSK BIT(7) +#define MASTER2_LPM_HSK BIT(8) + +#define L2PGE BIT(31) +#define EN_L2_WFI_PDN BIT(5) +#define EN_PLAT_PDN BIT(4) + +#define SLPCR_EN_DSM BIT(31) +#define SLPCR_RBC_EN BIT(30) +#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17) +#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16) +#define SLPCR_VSTBY BIT(2) +#define SLPCR_SBYOS BIT(1) +#define SLPCR_BYPASS_PMIC_READY BIT(0) +#define SLPCR_RBC_COUNT_SHIFT 24 +#define SLPCR_STBY_COUNT_SHFT 3 + +#define A53_DUMMY_PDN_ACK BIT(15) +#define A53_DUMMY_PUP_ACK BIT(31) +#define A53_PLAT_PDN_ACK BIT(2) +#define A53_PLAT_PUP_ACK BIT(18) +#define NOC_PDN_SLT_CTRL BIT(10) +#define NOC_PUP_SLT_CTRL BIT(11) +#define NOC_PGC_PDN_ACK BIT(3) +#define NOC_PGC_PUP_ACK BIT(19) + +#define DDRMIX_PWR_REQ BIT(5) +#define DDRMIX_ADB400_SYNC BIT(1) +#define DDRMIX_ADB400_ACK BIT(18) +#define DDRMIX_PGC 0xd40 + +#define PLAT_PUP_SLT_CTRL BIT(9) +#define PLAT_PDN_SLT_CTRL BIT(8) + +#define SLT_PLAT_PDN BIT(8) +#define SLT_PLAT_PUP BIT(9) + +#define MASTER1_MAPPING BIT(1) +#define MASTER2_MAPPING BIT(2) + +#define IRQ_IMR_NUM U(4) + +#endif /* GPC_REG_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h new file mode 100644 index 0000000..6d6a865 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0x800 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU U(0x0) +#define PLATFORM_MAX_CPU_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) + +#define IMX_PWR_LVL0 MPIDR_AFFLVL0 +#define IMX_PWR_LVL1 MPIDR_AFFLVL1 +#define IMX_PWR_LVL2 MPIDR_AFFLVL2 + +#define PWR_DOMAIN_AT_MAX_LVL U(1) +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_OFF_STATE U(4) +#define PLAT_MAX_RET_STATE U(1) + +#define PLAT_WAIT_RET_STATE PLAT_MAX_RET_STATE +#define PLAT_WAIT_OFF_STATE U(2) +#define PLAT_STOP_OFF_STATE U(3) + +#define BL31_BASE U(0x910000) +#define BL31_LIMIT U(0x920000) + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET U(0x40200000) + +/* GICv3 base address */ +#define PLAT_GICD_BASE U(0x38800000) +#define PLAT_GICR_BASE U(0x38880000) + +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) + +#define MAX_XLAT_TABLES 4 +#define MAX_MMAP_REGIONS 14 + +#define HAB_RVT_BASE U(0x00000880) /* HAB_RVT for i.MX8MQ */ + +#define IMX_BOOT_UART_BASE U(0x30860000) +#define IMX_BOOT_UART_CLK_IN_HZ 25000000 /* Select 25Mhz oscillator */ +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT_CRASH_UART_CLK_IN_HZ 25000000 +#define IMX_CONSOLE_BAUDRATE 115200 + +#define IMX_AIPS_BASE U(0x30200000) +#define IMX_AIPS_SIZE U(0xC00000) +#define IMX_AIPS1_BASE U(0x30200000) +#define IMX_AIPS3_ARB_BASE U(0x30800000) +#define IMX_OCOTP_BASE U(0x30350000) +#define IMX_ANAMIX_BASE U(0x30360000) +#define IMX_CCM_BASE U(0x30380000) +#define IMX_SRC_BASE U(0x30390000) +#define IMX_GPC_BASE U(0x303a0000) +#define IMX_RDC_BASE U(0x303d0000) +#define IMX_CSU_BASE U(0x303e0000) +#define IMX_WDOG_BASE U(0x30280000) +#define IMX_SNVS_BASE U(0x30370000) +#define IMX_NOC_BASE U(0x32700000) +#define IMX_TZASC_BASE U(0x32F80000) +#define IMX_CAAM_BASE U(0x30900000) +#define IMX_IOMUX_GPR_BASE U(0x30340000) +#define IMX_DDRC_BASE U(0x3d400000) +#define IMX_DDRPHY_BASE U(0x3c000000) +#define IMX_DDR_IPS_BASE U(0x3d000000) + +#define IMX_ROM_BASE U(0x00000000) +#define IMX_ROM_SIZE U(0x20000) + +#define AIPSTZ1_BASE U(0x301f0000) +#define AIPSTZ2_BASE U(0x305f0000) +#define AIPSTZ3_BASE U(0x309f0000) +#define AIPSTZ4_BASE U(0x32df0000) + +#define GPV_BASE U(0x32000000) +#define GPV_SIZE U(0x800000) +#define IMX_GIC_BASE PLAT_GICD_BASE +#define IMX_GIC_SIZE U(0x200000) + +#define WDOG_WSR U(0x2) +#define WDOG_WCR_WDZST BIT(0) +#define WDOG_WCR_WDBG BIT(1) +#define WDOG_WCR_WDE BIT(2) +#define WDOG_WCR_WDT BIT(3) +#define WDOG_WCR_SRS BIT(4) +#define WDOG_WCR_WDA BIT(5) +#define WDOG_WCR_SRE BIT(6) +#define WDOG_WCR_WDW BIT(7) + +#define SRC_A53RCR0 U(0x4) +#define SRC_A53RCR1 U(0x8) +#define SRC_OTG1PHY_SCR U(0x20) +#define SRC_OTG2PHY_SCR U(0x24) +#define SRC_GPR1_OFFSET U(0x74) +#define SRC_GPR10_OFFSET U(0x98) +#define SRC_GPR10_PERSIST_SECONDARY_BOOT BIT(30) + +#define SNVS_LPCR U(0x38) +#define SNVS_LPCR_SRTC_ENV BIT(0) +#define SNVS_LPCR_DP_EN BIT(5) +#define SNVS_LPCR_TOP BIT(6) + + +#define IOMUXC_GPR10 U(0x28) +#define GPR_TZASC_EN BIT(0) +#define GPR_TZASC_EN_LOCK BIT(16) + +#define OCRAM_S_BASE U(0x00180000) +#define OCRAM_S_SIZE U(0x8000) +#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE) + +#define COUNTER_FREQUENCY 8000000 /* 8MHz */ + +#define DEBUG_CONSOLE 0 +#define IMX_WDOG_B_RESET diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/platform.mk b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/platform.mk new file mode 100644 index 0000000..5461010 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/platform.mk @@ -0,0 +1,51 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/common/include \ + -Iplat/imx/imx8m/include \ + -Iplat/imx/imx8m/imx8mq/include + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +IMX_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/imx/common/imx8_helpers.S \ + plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c \ + plat/imx/imx8m/imx8mq/imx8mq_psci.c \ + plat/imx/imx8m/gpc_common.c \ + plat/imx/imx8m/imx_aipstz.c \ + plat/imx/imx8m/imx8m_caam.c \ + plat/imx/imx8m/imx8m_psci_common.c \ + plat/imx/imx8m/imx8mq/gpc.c \ + plat/imx/common/imx8_topology.c \ + plat/imx/common/imx_sip_handler.c \ + plat/imx/common/imx_sip_svc.c \ + plat/imx/common/imx_uart_console.S \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/arm/tzc/tzc380.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${IMX_GIC_SOURCES} + +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 + +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +BL32_BASE ?= 0xfe000000 +$(eval $(call add_define,BL32_BASE)) + +BL32_SIZE ?= 0x2000000 +$(eval $(call add_define,BL32_SIZE)) diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c b/arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c new file mode 100644 index 0000000..ecf8b1d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +void imx_aipstz_init(const struct aipstz_cfg *aipstz_cfg) +{ + const struct aipstz_cfg *aipstz = aipstz_cfg; + + while (aipstz->base != 0U) { + mmio_write_32(aipstz->base + AIPSTZ_MPR0, aipstz->mpr0); + mmio_write_32(aipstz->base + AIPSTZ_MPR1, aipstz->mpr1); + + for (int i = 0; i < AIPSTZ_OPACR_NUM; i++) + mmio_write_32(aipstz->base + OPACR_OFFSET(i), aipstz->opacr[i]); + + aipstz++; + } +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c b/arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c new file mode 100644 index 0000000..85de191 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +void imx_rdc_init(const struct imx_rdc_cfg *rdc_cfg) +{ + const struct imx_rdc_cfg *rdc = rdc_cfg; + + while (rdc->type != RDC_INVALID) { + switch (rdc->type) { + case RDC_MDA: + /* MDA config */ + mmio_write_32(MDAn(rdc->index), rdc->setting.rdc_mda); + break; + case RDC_PDAP: + /* peripheral access permission config */ + mmio_write_32(PDAPn(rdc->index), rdc->setting.rdc_pdap); + break; + case RDC_MEM_REGION: + /* memory region access permission config */ + mmio_write_32(MRSAn(rdc->index), rdc->setting.rdc_mem_region[0]); + mmio_write_32(MREAn(rdc->index), rdc->setting.rdc_mem_region[1]); + mmio_write_32(MRCn(rdc->index), rdc->setting.rdc_mem_region[2]); + break; + default: + break; + } + + rdc++; + } +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/include/gpc.h b/arm-trusted-firmware/plat/imx/imx8m/include/gpc.h new file mode 100644 index 0000000..29b8ecf --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/include/gpc.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8M_GPC_H +#define IMX8M_GPC_H + +#include + +/* helper macro */ +#define A53_LPM_MASK U(0xF) +#define A53_LPM_WAIT U(0x5) +#define A53_LPM_STOP U(0xA) +#define LPM_MODE(local_state) ((local_state) == PLAT_WAIT_RET_STATE ? A53_LPM_WAIT : A53_LPM_STOP) + +#define DSM_MODE_MASK BIT(31) +#define CORE_WKUP_FROM_GIC (IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3) +#define A53_CORE_WUP_SRC(core_id) (1 << ((core_id) < 2 ? 28 + (core_id) : 22 + (core_id) - 2)) +#define COREx_PGC_PCR(core_id) (0x800 + (core_id) * 0x40) +#define COREx_WFI_PDN(core_id) (1 << ((core_id) < 2 ? (core_id) * 2 : ((core_id) - 2) * 2 + 16)) +#define COREx_IRQ_WUP(core_id) ((core_id) < 2 ? (1 << ((core_id) * 2 + 8)) : (1 << ((core_id) * 2 + 20))) +#define COREx_LPM_PUP(core_id) ((core_id) < 2 ? (1 << ((core_id) * 2 + 9)) : (1 << ((core_id) * 2 + 21))) +#define SLTx_CFG(n) ((SLT0_CFG + ((n) * 4))) +#define SLT_COREx_PUP(core_id) (0x2 << ((core_id) * 2)) + +#define IMR_MASK_ALL 0xffffffff + +#define IMX_PD_DOMAIN(name, on) \ + { \ + .pwr_req = name##_PWR_REQ, \ + .pgc_offset = name##_PGC, \ + .need_sync = false, \ + .always_on = (on), \ + } + +#define IMX_MIX_DOMAIN(name, on) \ + { \ + .pwr_req = name##_PWR_REQ, \ + .pgc_offset = name##_PGC, \ + .adb400_sync = name##_ADB400_SYNC, \ + .adb400_ack = name##_ADB400_ACK, \ + .need_sync = true, \ + .always_on = (on), \ + } + +struct imx_pwr_domain { + uint32_t pwr_req; + uint32_t adb400_sync; + uint32_t adb400_ack; + uint32_t pgc_offset; + bool need_sync; + bool always_on; +}; + +DECLARE_BAKERY_LOCK(gpc_lock); + +/* function declare */ +void imx_gpc_init(void); +void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint); +void imx_set_cpu_pwr_off(unsigned int core_index); +void imx_set_cpu_pwr_on(unsigned int core_index); +void imx_set_cpu_lpm(unsigned int core_index, bool pdn); +void imx_set_cluster_standby(bool retention); +void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state); +void imx_noc_slot_config(bool pdn); +void imx_set_sys_wakeup(unsigned int last_core, bool pdn); +void imx_set_sys_lpm(unsigned last_core, bool retention); +void imx_set_rbc_count(void); +void imx_clear_rbc_count(void); + +#endif /*IMX8M_GPC_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h new file mode 100644 index 0000000..84725b1 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8M_CAAM_H +#define IMX8M_CAAM_H + +#include + +#include + +#define CAAM_JR0MID (IMX_CAAM_BASE + 0x10) +#define CAAM_JR1MID (IMX_CAAM_BASE + 0x18) +#define CAAM_JR2MID (IMX_CAAM_BASE + 0x20) +#define CAAM_NS_MID (0x1) + +#define JR0_BASE (IMX_CAAM_BASE + 0x1000) + +#define SM_P0_PERM (JR0_BASE + 0xa04) +#define SM_P0_SMAG2 (JR0_BASE + 0xa08) +#define SM_P0_SMAG1 (JR0_BASE + 0xa0c) +#define SM_CMD (JR0_BASE + 0xbe4) + +/* secure memory command */ +#define SMC_PAGE_SHIFT 16 +#define SMC_PART_SHIFT 8 + +#define SMC_CMD_ALLOC_PAGE 0x01 /* allocate page to this partition */ +#define SMC_CMD_DEALLOC_PART 0x03 /* deallocate partition */ + +void imx8m_caam_init(void); + +#endif /* IMX8M_CAAM_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h new file mode 100644 index 0000000..2ec0c46 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2022, Linaro + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8M_MEASURED_BOOT_H +#define IMX8M_MEASURED_BOOT_H + +#include + +#include + +int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr); + +#endif /* IMX8M_MEASURED_BOOT_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h new file mode 100644 index 0000000..7d14d11 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8M_PSCI_H +#define IMX8M_PSCI_H + +#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +int imx_pwr_domain_on(u_register_t mpidr); +void imx_pwr_domain_on_finish(const psci_power_state_t *target_state); +void imx_pwr_domain_off(const psci_power_state_t *target_state); +int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint); +void imx_cpu_standby(plat_local_state_t cpu_state); +void imx_domain_suspend(const psci_power_state_t *target_state); +void imx_domain_suspend_finish(const psci_power_state_t *target_state); +void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state); +int imx_system_reset2(int is_vendor, int reset_type, u_register_t cookie); + +#endif /* IMX8M_PSCI_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h new file mode 100644 index 0000000..7616862 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_AIPSTZ_H +#define IMX_AIPSTZ_H + +#include + +#define AIPSTZ_MPR0 U(0x0) +#define AIPSTZ_MPR1 U(0x4) + +#define AIPSTZ_OPACR_NUM U(0x5) +#define OPACR_OFFSET(i) U((i) * 4 + 0x40) + +struct aipstz_cfg { + uintptr_t base; + uint32_t mpr0; + uint32_t mpr1; + uint32_t opacr[AIPSTZ_OPACR_NUM]; +}; + +void imx_aipstz_init(const struct aipstz_cfg *aipstz_cfg); + +#endif /* IMX_AIPSTZ_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h new file mode 100644 index 0000000..e25b0e6 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_RDC_H +#define IMX_RDC_H + +#include + +#include + +#define MDAn(x) (IMX_RDC_BASE + 0x200 + (x) * 4) +#define PDAPn(x) (IMX_RDC_BASE + 0x400 + (x) * 4) +#define MRSAn(x) (IMX_RDC_BASE + 0x800 + (x) * 0x10) +#define MREAn(x) (IMX_RDC_BASE + 0x804 + (x) * 0x10) +#define MRCn(x) (IMX_RDC_BASE + 0x808 + (x) * 0x10) + +#define LCK BIT(31) +#define SREQ BIT(30) +#define ENA BIT(30) + +#define DID0 U(0x0) +#define DID1 U(0x1) +#define DID2 U(0x2) +#define DID3 U(0x3) + +#define D3R BIT(7) +#define D3W BIT(6) +#define D2R BIT(5) +#define D2W BIT(4) +#define D1R BIT(3) +#define D1W BIT(2) +#define D0R BIT(1) +#define D0W BIT(0) + +union rdc_setting { + uint32_t rdc_mda; /* Master Domain Assignment */ + uint32_t rdc_pdap; /* Peripheral Domain Access Permissions */ + uint32_t rdc_mem_region[3]; /* Memory Region Access Control */ +}; + +enum rdc_type { + RDC_INVALID, + RDC_MDA, + RDC_PDAP, + RDC_MEM_REGION, +}; + +struct imx_rdc_cfg { + enum rdc_type type; /* config type Master, Peripheral or Memory region */ + int index; + union rdc_setting setting; +}; + +#define RDC_MDAn(i, mda) \ + {RDC_MDA, (i), .setting.rdc_mda = (mda), } +#define RDC_PDAPn(i, pdap) \ + {RDC_PDAP, (i), .setting.rdc_pdap = (pdap), } + +#define RDC_MEM_REGIONn(i, msa, mea, mrc) \ + { RDC_MEM_REGION, (i), \ + .setting.rdc_mem_region[0] = (msa), \ + .setting.rdc_mem_region[1] = (mea), \ + .setting.rdc_mem_region[2] = (mrc), \ + } + +void imx_rdc_init(const struct imx_rdc_cfg *cfg); + +#endif /* IMX_RDC_H */ + diff --git a/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c new file mode 100644 index 0000000..d9c9110 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2015-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 +#include + +#include +#include +#include +#include +#include +#include + +static const unsigned long BL31_COHERENT_RAM_START = BL_COHERENT_RAM_BASE; +static const unsigned long BL31_COHERENT_RAM_END = BL_COHERENT_RAM_END; +static const unsigned long BL31_RO_START = BL_CODE_BASE; +static const unsigned long BL31_RO_END = BL_CODE_END; +static const unsigned long BL31_RW_END = BL_END; + +IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START); + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +#define UART_PAD_CTRL (PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \ + (SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \ + (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \ + (SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \ + (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT)) + +#if defined(IMX_USE_UART0) +#define IMX_RES_UART SC_R_UART_0 +#define IMX_PAD_UART_RX SC_P_UART0_RX +#define IMX_PAD_UART_TX SC_P_UART0_TX +#define IMX_PAD_UART_RTS_B SC_P_UART0_RTS_B +#define IMX_PAD_UART_CTS_B SC_P_UART0_CTS_B +#elif defined(IMX_USE_UART1) +#define IMX_RES_UART SC_R_UART_1 +#define IMX_PAD_UART_RX SC_P_UART1_RX +#define IMX_PAD_UART_TX SC_P_UART1_TX +#define IMX_PAD_UART_RTS_B SC_P_UART1_RTS_B +#define IMX_PAD_UART_CTS_B SC_P_UART1_CTS_B +#else +#error "Provide proper UART number in IMX_DEBUG_UART" +#endif + +const static int imx8qm_cci_map[] = { + CLUSTER0_CCI_SLVAE_IFACE, + CLUSTER1_CCI_SLVAE_IFACE +}; + +static const mmap_region_t imx_mmap[] = { + MAP_REGION_FLAT(IMX_REG_BASE, IMX_REG_SIZE, MT_DEVICE | MT_RW), + {0} +}; + +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + + return spsr; +} + +#if DEBUG_CONSOLE_A53 +static void lpuart32_serial_setbrg(unsigned int base, int baudrate) +{ + unsigned int sbr, osr, baud_diff, tmp_osr, tmp_sbr; + unsigned int diff1, diff2, tmp, rate; + + if (baudrate == 0) + panic(); + + sc_pm_get_clock_rate(ipc_handle, IMX_RES_UART, 2, &rate); + + baud_diff = baudrate; + osr = 0; + sbr = 0; + for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) { + tmp_sbr = (rate / (baudrate * tmp_osr)); + if (tmp_sbr == 0) + tmp_sbr = 1; + + /* calculate difference in actual baud w/ current values */ + diff1 = rate / (tmp_osr * tmp_sbr) - baudrate; + diff2 = rate / (tmp_osr * (tmp_sbr + 1)); + + /* select best values between sbr and sbr+1 */ + if (diff1 > (baudrate - diff2)) { + diff1 = baudrate - diff2; + tmp_sbr++; + } + + if (diff1 <= baud_diff) { + baud_diff = diff1; + osr = tmp_osr; + sbr = tmp_sbr; + } + } + + tmp = mmio_read_32(IMX_BOOT_UART_BASE + BAUD); + + if ((osr > 3) && (osr < 8)) + tmp |= LPUART_BAUD_BOTHEDGE_MASK; + + tmp &= ~LPUART_BAUD_OSR_MASK; + tmp |= LPUART_BAUD_OSR(osr - 1); + tmp &= ~LPUART_BAUD_SBR_MASK; + tmp |= LPUART_BAUD_SBR(sbr); + + /* explicitly disable 10 bit mode & set 1 stop bit */ + tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK); + + mmio_write_32(IMX_BOOT_UART_BASE + BAUD, tmp); +} + +static int lpuart32_serial_init(unsigned int base) +{ + unsigned int tmp; + + /* disable TX & RX before enabling clocks */ + tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL); + tmp &= ~(CTRL_TE | CTRL_RE); + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp); + + mmio_write_32(IMX_BOOT_UART_BASE + MODIR, 0); + mmio_write_32(IMX_BOOT_UART_BASE + FIFO, ~(FIFO_TXFE | FIFO_RXFE)); + + mmio_write_32(IMX_BOOT_UART_BASE + MATCH, 0); + + /* provide data bits, parity, stop bit, etc */ + lpuart32_serial_setbrg(base, IMX_BOOT_UART_BAUDRATE); + + /* eight data bits no parity bit */ + tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL); + tmp &= ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK); + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp); + + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, CTRL_RE | CTRL_TE); + + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55); + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55); + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x0A); + + return 0; +} +#endif + +void mx8_partition_resources(void) +{ + sc_rm_pt_t secure_part, os_part; + sc_rm_mr_t mr, mr_record = 64; + sc_faddr_t start, end; + bool owned, owned2; + sc_err_t err; + int i; + + err = sc_rm_get_partition(ipc_handle, &secure_part); + + err = sc_rm_partition_alloc(ipc_handle, &os_part, false, false, + false, false, false); + + err = sc_rm_set_parent(ipc_handle, os_part, secure_part); + + /* set secure resources to NOT-movable */ + for (i = 0; i < ARRAY_SIZE(secure_rsrcs); i++) { + err = sc_rm_set_resource_movable(ipc_handle, secure_rsrcs[i], + secure_rsrcs[i], false); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + secure_rsrcs[i], err); + } + + owned = sc_rm_is_resource_owned(ipc_handle, SC_R_M4_0_PID0); + if (owned) { + err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_0_PID0, + SC_R_M4_0_PID0, false); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + SC_R_M4_0_PID0, err); + } + + owned2 = sc_rm_is_resource_owned(ipc_handle, SC_R_M4_1_PID0); + if (owned2) { + err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_1_PID0, + SC_R_M4_1_PID0, false); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + SC_R_M4_1_PID0, err); + } + /* move all movable resources and pins to non-secure partition */ + err = sc_rm_move_all(ipc_handle, secure_part, os_part, true, true); + if (err) + ERROR("sc_rm_move_all: %u\n", err); + + /* iterate through peripherals to give NS OS part access */ + for (i = 0; i < ARRAY_SIZE(ns_access_allowed); i++) { + err = sc_rm_set_peripheral_permissions(ipc_handle, ns_access_allowed[i], + os_part, SC_RM_PERM_FULL); + if (err) + ERROR("sc_rm_set_peripheral_permissions: rsrc %u, \ + ret %u\n", ns_access_allowed[i], err); + } + + if (owned) { + err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_0_PID0, + SC_R_M4_0_PID0, true); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + SC_R_M4_0_PID0, err); + err = sc_rm_assign_resource(ipc_handle, os_part, SC_R_M4_0_PID0); + if (err) + ERROR("sc_rm_assign_resource: rsrc %u, ret %u\n", + SC_R_M4_0_PID0, err); + } + if (owned2) { + err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_1_PID0, + SC_R_M4_1_PID0, true); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + SC_R_M4_1_PID0, err); + err = sc_rm_assign_resource(ipc_handle, os_part, SC_R_M4_1_PID0); + if (err) + ERROR("sc_rm_assign_resource: rsrc %u, ret %u\n", + SC_R_M4_1_PID0, err); + } + + /* + * sc_rm_set_peripheral_permissions + * sc_rm_set_memreg_permissions + * sc_rm_set_pin_movable + */ + + for (mr = 0; mr < 64; mr++) { + owned = sc_rm_is_memreg_owned(ipc_handle, mr); + if (owned) { + err = sc_rm_get_memreg_info(ipc_handle, mr, &start, &end); + if (err) + ERROR("Memreg get info failed, %u\n", mr); + NOTICE("Memreg %u 0x%" PRIx64 " -- 0x%" PRIx64 "\n", mr, start, end); + if (BL31_BASE >= start && (BL31_LIMIT - 1) <= end) { + mr_record = mr; /* Record the mr for ATF running */ + } else { + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 ", \ + err %d\n", start, end, err); + } + } + } + + if (mr_record != 64) { + err = sc_rm_get_memreg_info(ipc_handle, mr_record, &start, &end); + if (err) + ERROR("Memreg get info failed, %u\n", mr_record); + if ((BL31_LIMIT - 1) < end) { + err = sc_rm_memreg_alloc(ipc_handle, &mr, BL31_LIMIT, end); + if (err) + ERROR("sc_rm_memreg_alloc failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n", + (sc_faddr_t)BL31_LIMIT, end); + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n", + (sc_faddr_t)BL31_LIMIT, end); + } + + if (start < (BL31_BASE - 1)) { + err = sc_rm_memreg_alloc(ipc_handle, &mr, start, BL31_BASE - 1); + if (err) + ERROR("sc_rm_memreg_alloc failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n", + start, (sc_faddr_t)BL31_BASE - 1); + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n", + start, (sc_faddr_t)BL31_BASE - 1); + } + } + + if (err) + NOTICE("Partitioning Failed\n"); + else + NOTICE("Non-secure Partitioning Succeeded\n"); + +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ +#if DEBUG_CONSOLE + static console_t console; +#endif + if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE) + panic(); + +#if DEBUG_CONSOLE_A53 + sc_pm_set_resource_power_mode(ipc_handle, IMX_RES_UART, + SC_PM_PW_MODE_ON); + sc_pm_clock_rate_t rate = 80000000; + sc_pm_set_clock_rate(ipc_handle, IMX_RES_UART, 2, &rate); + sc_pm_clock_enable(ipc_handle, IMX_RES_UART, 2, true, false); + + /* configure UART pads */ + sc_pad_set(ipc_handle, IMX_PAD_UART_RX, UART_PAD_CTRL); + sc_pad_set(ipc_handle, IMX_PAD_UART_TX, UART_PAD_CTRL); + sc_pad_set(ipc_handle, IMX_PAD_UART_RTS_B, UART_PAD_CTRL); + sc_pad_set(ipc_handle, IMX_PAD_UART_CTS_B, UART_PAD_CTRL); + lpuart32_serial_init(IMX_BOOT_UART_BASE); +#endif + +#if DEBUG_CONSOLE + console_lpuart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); +#endif + + /* turn on MU1 for non-secure OS/Hypervisor */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON); + /* Turn on GPT_0's power & clock for non-secure OS/Hypervisor */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON); + sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0); + mmio_write_32(IMX_GPT_LPCG_BASE, mmio_read_32(IMX_GPT_LPCG_BASE) | (1 << 25)); + + /* + * create new partition for non-secure OS/Hypervisor + * uses global structs defined in sec_rsrc.h + */ + mx8_partition_resources(); + + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + /* init the first cluster's cci slave interface */ + cci_init(PLAT_CCI_BASE, imx8qm_cci_map, PLATFORM_CLUSTER_COUNT); + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +void bl31_plat_arch_setup(void) +{ + unsigned long ro_start = BL31_RO_START; + unsigned long ro_size = BL31_RO_END - BL31_RO_START; + unsigned long rw_start = BL31_RW_START; + unsigned long rw_size = BL31_RW_END - BL31_RW_START; +#if USE_COHERENT_MEM + unsigned long coh_start = BL31_COHERENT_RAM_START; + unsigned long coh_size = BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START; +#endif + + mmap_add_region(ro_start, ro_start, ro_size, + MT_RO | MT_MEMORY | MT_SECURE); + mmap_add_region(rw_start, rw_start, rw_size, + MT_RW | MT_MEMORY | MT_SECURE); + mmap_add(imx_mmap); + +#if USE_COHERENT_MEM + mmap_add_region(coh_start, coh_start, coh_size, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + /* setup xlat table */ + init_xlat_tables(); + /* enable the MMU */ + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + plat_gic_driver_init(); + plat_gic_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) + return &bl33_image_ep_info; + if (type == SECURE) + return &bl32_image_ep_info; + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} + +void bl31_plat_runtime_setup(void) +{ + return; +} diff --git a/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c b/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c new file mode 100644 index 0000000..bdba37c --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../../common/sci/imx8_mu.h" + +#define CORE_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +const static int ap_core_index[PLATFORM_CORE_COUNT] = { + SC_R_A53_0, SC_R_A53_1, SC_R_A53_2, + SC_R_A53_3, SC_R_A72_0, SC_R_A72_1, +}; + +/* save gic dist/redist context when GIC is poewr down */ +static struct plat_gic_ctx imx_gicv3_ctx; +static unsigned int gpt_lpcg, gpt_reg[2]; + +static void imx_enable_irqstr_wakeup(void) +{ + uint32_t irq_mask; + gicv3_dist_ctx_t *dist_ctx = &imx_gicv3_ctx.dist_ctx; + + /* put IRQSTR into ON mode */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON); + + /* enable the irqsteer to handle wakeup irq */ + mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x1); + for (int i = 0; i < 15; i++) { + irq_mask = dist_ctx->gicd_isenabler[i]; + mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask); + } + + /* set IRQSTR low power mode */ + if (imx_is_wakeup_src_irqsteer()) + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY); + else + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF); +} + +static void imx_disable_irqstr_wakeup(void) +{ + /* put IRQSTR into ON from STBY mode */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON); + + /* disable the irqsteer */ + mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x0); + for (int i = 0; i < 16; i++) + mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x4 + 0x4 * i, 0x0); + + /* put IRQSTR into OFF mode */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF); +} + +int imx_pwr_domain_on(u_register_t mpidr) +{ + int ret = PSCI_E_SUCCESS; + unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + sc_pm_set_resource_power_mode(ipc_handle, cluster_id == 0 ? + SC_R_A53 : SC_R_A72, SC_PM_PW_MODE_ON); + + if (cluster_id == 1) + sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON); + + if (sc_pm_set_resource_power_mode(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + SC_PM_PW_MODE_ON) != SC_ERR_NONE) { + ERROR("core %d power on failed!\n", cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id); + ret = PSCI_E_INTERN_FAIL; + } + + if (sc_pm_cpu_start(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + true, BL31_BASE) != SC_ERR_NONE) { + ERROR("boot core %d failed!\n", cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id); + ret = PSCI_E_INTERN_FAIL; + } + + return ret; +} + +void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + plat_gic_pcpu_init(); + plat_gic_cpuif_enable(); +} + +void imx_pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + plat_gic_cpuif_disable(); + sc_pm_req_cpu_low_power_mode(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE); + + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) { + cci_disable_snoop_dvm_reqs(cluster_id); + if (cluster_id == 1) + sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF); + } + printf("turn off cluster:%d core:%d\n", cluster_id, cpu_id); +} + +void imx_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + plat_gic_cpuif_disable(); + sc_pm_set_cpu_resume(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + true, BL31_BASE); + sc_pm_req_cpu_low_power_mode(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC); + } else { + dsb(); + write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); + isb(); + } + + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) { + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + if (cluster_id == 1) + sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF); + } + + if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) { + plat_gic_cpuif_disable(); + + /* save gic context */ + plat_gic_save(cpu_id, &imx_gicv3_ctx); + /* enable the irqsteer for wakeup */ + imx_enable_irqstr_wakeup(); + + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + /* Put GIC in LP mode. */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF); + /* Save GPT clock and registers, then turn off its power */ + gpt_lpcg = mmio_read_32(IMX_GPT_LPCG_BASE); + gpt_reg[0] = mmio_read_32(IMX_GPT_BASE); + gpt_reg[1] = mmio_read_32(IMX_GPT_BASE + 0x4); + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_OFF); + + sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_OFF); + sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF); + sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF); + + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF); + + sc_pm_set_cpu_resume(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + true, BL31_BASE); + if (imx_is_wakeup_src_irqsteer()) + sc_pm_req_cpu_low_power_mode(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER); + else + sc_pm_req_cpu_low_power_mode(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU); + } +} + +void imx_domain_suspend_finish(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + /* check the system level status */ + if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) { + MU_Resume(SC_IPC_BASE); + + sc_pm_req_cpu_low_power_mode(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC); + + /* Put GIC/IRQSTR back to high power mode. */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_ON); + + /* Turn GPT power and restore its clock and registers */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON); + sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0); + mmio_write_32(IMX_GPT_BASE, gpt_reg[0]); + mmio_write_32(IMX_GPT_BASE + 0x4, gpt_reg[1]); + mmio_write_32(IMX_GPT_LPCG_BASE, gpt_lpcg); + + sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON); + sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON); + sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON); + + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON); + + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + /* restore gic context */ + plat_gic_restore(cpu_id, &imx_gicv3_ctx); + /* disable the irqsteer wakeup */ + imx_disable_irqstr_wakeup(); + + plat_gic_cpuif_enable(); + } + + /* check the cluster level power status */ + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) { + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + if (cluster_id == 1) + sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON); + } + + /* check the core level power status */ + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + sc_pm_set_cpu_resume(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + false, BL31_BASE); + sc_pm_req_cpu_low_power_mode(ipc_handle, + ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id], + SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC); + plat_gic_cpuif_enable(); + } else { + write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT)); + isb(); + } +} + +int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) +{ + return PSCI_E_SUCCESS; +} + +static const plat_psci_ops_t imx_plat_psci_ops = { + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .pwr_domain_off = imx_pwr_domain_off, + .pwr_domain_suspend = imx_domain_suspend, + .pwr_domain_suspend_finish = imx_domain_suspend_finish, + .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, + .validate_power_state = imx_validate_power_state, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, + .system_off = imx_system_off, + .system_reset = imx_system_reset, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + imx_mailbox_init(sec_entrypoint); + *psci_ops = &imx_plat_psci_ops; + + /* make sure system sources power ON in low power mode by default */ + sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON); + sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON); + sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON); + + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + + return 0; +} diff --git a/arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h new file mode 100644 index 0000000..671c77f --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0X400 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU U(0x0) +#define PLATFORM_MAX_CPU_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(2) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ + PLATFORM_CLUSTER1_CORE_COUNT) + +#define IMX_PWR_LVL0 MPIDR_AFFLVL0 +#define IMX_PWR_LVL1 MPIDR_AFFLVL1 +#define IMX_PWR_LVL2 MPIDR_AFFLVL2 + +#define PWR_DOMAIN_AT_MAX_LVL U(1) +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_RET_STATE U(1) + +#define BL31_BASE 0x80000000 +#define BL31_LIMIT 0x80020000 + +#define PLAT_GICD_BASE 0x51a00000 +#define PLAT_GICR_BASE 0x51b00000 +#define PLAT_CCI_BASE 0x52090000 +#define CLUSTER0_CCI_SLVAE_IFACE 3 +#define CLUSTER1_CCI_SLVAE_IFACE 4 + +/* UART */ +#if defined(IMX_USE_UART0) +#define IMX_BOOT_UART_BASE 0x5a060000 +#elif defined(IMX_USE_UART1) +#define IMX_BOOT_UART_BASE 0x5a070000 +#else +#error "Provide proper UART number in IMX_DEBUG_UART" +#endif + +#define IMX_BOOT_UART_BAUDRATE 115200 +#define IMX_BOOT_UART_CLK_IN_HZ 24000000 +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT__CRASH_UART_CLK_IN_HZ 24000000 +#define IMX_CONSOLE_BAUDRATE 115200 + +#define SC_IPC_BASE 0x5d1b0000 +#define IMX_GPT_LPCG_BASE 0x5d540000 +#define IMX_GPT_BASE 0x5d140000 +#define IMX_WUP_IRQSTR_BASE 0x51090000 +#define IMX_REG_BASE 0x50000000 +#define IMX_REG_SIZE 0x10000000 + +#define COUNTER_FREQUENCY 8000000 /* 8MHz */ + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET 0x80020000 + +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) + +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 12 + +#define DEBUG_CONSOLE_A53 DEBUG_CONSOLE + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h b/arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h new file mode 100644 index 0000000..d16d051 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* resources that are going to stay in secure partition */ +sc_rsrc_t secure_rsrcs[] = { + SC_R_MU_0A, + SC_R_A53, + SC_R_A53_0, + SC_R_A53_1, + SC_R_A53_2, + SC_R_A53_3, + SC_R_A72, + SC_R_A72_0, + SC_R_A72_1, + SC_R_GIC, + SC_R_GIC_SMMU, + SC_R_CCI, + SC_R_SYSTEM, + SC_R_IRQSTR_SCU2, + SC_R_GPT_0 +}; + +/* resources that have register access for non-secure domain */ +sc_rsrc_t ns_access_allowed[] = { + SC_R_GIC, + SC_R_GIC_SMMU, + SC_R_CCI, + SC_R_GPT_0 +}; diff --git a/arm-trusted-firmware/plat/imx/imx8qm/platform.mk b/arm-trusted-firmware/plat/imx/imx8qm/platform.mk new file mode 100644 index 0000000..f35fa00 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qm/platform.mk @@ -0,0 +1,48 @@ +# +# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/imx8qm/include \ + -Iplat/imx/common/include \ + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +IMX_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/imx/common/lpuart_console.S \ + plat/imx/common/imx8_helpers.S \ + plat/imx/imx8qm/imx8qm_bl31_setup.c \ + plat/imx/imx8qm/imx8qm_psci.c \ + plat/imx/common/imx8_topology.c \ + plat/imx/common/imx8_psci.c \ + plat/imx/common/imx_sip_svc.c \ + plat/imx/common/imx_sip_handler.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + drivers/arm/cci/cci.c \ + ${IMX_GIC_SOURCES} \ + +include plat/imx/common/sci/sci_api.mk + +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 +ERRATA_A72_859971 := 1 + +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +IMX_DEBUG_UART ?= 0 +$(eval $(call add_define,IMX_USE_UART${IMX_DEBUG_UART})) + +DEBUG_CONSOLE ?= 0 +$(eval $(call add_define,DEBUG_CONSOLE)) diff --git a/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c new file mode 100644 index 0000000..3739cd6 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2015-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 +#include + +#include +#include +#include +#include +#include +#include + +static const unsigned long BL31_COHERENT_RAM_START = BL_COHERENT_RAM_BASE; +static const unsigned long BL31_COHERENT_RAM_END = BL_COHERENT_RAM_END; +static const unsigned long BL31_RO_START = BL_CODE_BASE; +static const unsigned long BL31_RO_END = BL_CODE_END; +static const unsigned long BL31_RW_END = BL_END; + +IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START); + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* Default configuration for i.MX8QM/QXP MEK */ +#if defined(IMX_USE_UART0) +#define UART_PAD_CTRL (PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \ + (SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \ + (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \ + (SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \ + (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT)) +#define IMX_RES_UART SC_R_UART_0 +#define IMX_PAD_UART_RX SC_P_UART0_RX +#define IMX_PAD_UART_TX SC_P_UART0_TX + +/* + * On Toradex Colibri i.MX8QXP UART3 on the FLEXCAN2. + * Use custom pad control for this + */ +#elif defined(IMX_USE_UART3) +/* + * FLEXCAN2_RX/TX pads are muxed to ADMA_UART3_RX/TX, + * For ref: + * 000b - ADMA_FLEXCAN2_RX + * 001b - ADMA_SAI3_RXD + * 010b - ADMA_UART3_RX + * 011b - ADMA_SAI1_RXFS + * 100b - LSIO_GPIO1_IO19 + */ +#define UART_PAD_CTRL (PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \ + (SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \ + (2U << PADRING_IFMUX_SHIFT) | \ + (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \ + (SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \ + (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT)) +#define IMX_RES_UART SC_R_UART_3 +#define IMX_PAD_UART_RX SC_P_FLEXCAN2_RX +#define IMX_PAD_UART_TX SC_P_FLEXCAN2_TX +#else +#error "Provide proper UART configuration in IMX_DEBUG_UART" +#endif + +static const mmap_region_t imx_mmap[] = { + MAP_REGION_FLAT(IMX_REG_BASE, IMX_REG_SIZE, MT_DEVICE | MT_RW), + {0} +}; + +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +#if DEBUG_CONSOLE_A35 +static void lpuart32_serial_setbrg(unsigned int base, int baudrate) +{ + unsigned int sbr, osr, baud_diff, tmp_osr, tmp_sbr; + unsigned int diff1, diff2, tmp, rate; + + if (baudrate == 0) + panic(); + + sc_pm_get_clock_rate(ipc_handle, IMX_RES_UART, 2, &rate); + + baud_diff = baudrate; + osr = 0; + sbr = 0; + for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) { + tmp_sbr = (rate / (baudrate * tmp_osr)); + if (tmp_sbr == 0) + tmp_sbr = 1; + + /* calculate difference in actual baud w/ current values */ + diff1 = rate / (tmp_osr * tmp_sbr) - baudrate; + diff2 = rate / (tmp_osr * (tmp_sbr + 1)); + + /* select best values between sbr and sbr+1 */ + if (diff1 > (baudrate - diff2)) { + diff1 = baudrate - diff2; + tmp_sbr++; + } + + if (diff1 <= baud_diff) { + baud_diff = diff1; + osr = tmp_osr; + sbr = tmp_sbr; + } + } + + tmp = mmio_read_32(IMX_BOOT_UART_BASE + BAUD); + + if ((osr > 3) && (osr < 8)) + tmp |= LPUART_BAUD_BOTHEDGE_MASK; + + tmp &= ~LPUART_BAUD_OSR_MASK; + tmp |= LPUART_BAUD_OSR(osr - 1); + tmp &= ~LPUART_BAUD_SBR_MASK; + tmp |= LPUART_BAUD_SBR(sbr); + + /* explicitly disable 10 bit mode & set 1 stop bit */ + tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK); + + mmio_write_32(IMX_BOOT_UART_BASE + BAUD, tmp); +} + +static int lpuart32_serial_init(unsigned int base) +{ + unsigned int tmp; + + /* disable TX & RX before enabling clocks */ + tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL); + tmp &= ~(CTRL_TE | CTRL_RE); + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp); + + mmio_write_32(IMX_BOOT_UART_BASE + MODIR, 0); + mmio_write_32(IMX_BOOT_UART_BASE + FIFO, ~(FIFO_TXFE | FIFO_RXFE)); + + mmio_write_32(IMX_BOOT_UART_BASE + MATCH, 0); + + /* provide data bits, parity, stop bit, etc */ + lpuart32_serial_setbrg(base, IMX_BOOT_UART_BAUDRATE); + + /* eight data bits no parity bit */ + tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL); + tmp &= ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK); + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp); + + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, CTRL_RE | CTRL_TE); + + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55); + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55); + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x0A); + + return 0; +} +#endif + +void imx8_partition_resources(void) +{ + sc_rm_pt_t secure_part, os_part; + sc_rm_mr_t mr, mr_record = 64; + sc_faddr_t start, end; + sc_err_t err; + bool owned; + int i; + + err = sc_rm_get_partition(ipc_handle, &secure_part); + if (err) + ERROR("sc_rm_get_partition failed: %u\n", err); + + err = sc_rm_partition_alloc(ipc_handle, &os_part, false, false, + false, false, false); + if (err) + ERROR("sc_rm_partition_alloc failed: %u\n", err); + + err = sc_rm_set_parent(ipc_handle, os_part, secure_part); + if (err) + ERROR("sc_rm_set_parent: %u\n", err); + + /* set secure resources to NOT-movable */ + for (i = 0; i < (ARRAY_SIZE(secure_rsrcs)); i++) { + err = sc_rm_set_resource_movable(ipc_handle, + secure_rsrcs[i], secure_rsrcs[i], false); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + secure_rsrcs[i], err); + } + + /* move all movable resources and pins to non-secure partition */ + err = sc_rm_move_all(ipc_handle, secure_part, os_part, true, true); + if (err) + ERROR("sc_rm_move_all: %u\n", err); + + /* iterate through peripherals to give NS OS part access */ + for (i = 0; i < ARRAY_SIZE(ns_access_allowed); i++) { + err = sc_rm_set_peripheral_permissions(ipc_handle, + ns_access_allowed[i], os_part, SC_RM_PERM_FULL); + if (err) + ERROR("sc_rm_set_peripheral_permissions: rsrc %u, \ + ret %u\n", ns_access_allowed[i], err); + } + + /* + * sc_rm_set_peripheral_permissions + * sc_rm_set_memreg_permissions + * sc_rm_set_pin_movable + */ + for (mr = 0; mr < 64; mr++) { + owned = sc_rm_is_memreg_owned(ipc_handle, mr); + if (owned) { + err = sc_rm_get_memreg_info(ipc_handle, mr, &start, &end); + if (err) + ERROR("Memreg get info failed, %u\n", mr); + + NOTICE("Memreg %u 0x%" PRIx64 " -- 0x%" PRIx64 "\n", mr, start, end); + if (BL31_BASE >= start && (BL31_LIMIT - 1) <= end) { + mr_record = mr; /* Record the mr for ATF running */ + } else { + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 ", \ + err %d\n", start, end, err); + } + } + } + + if (mr_record != 64) { + err = sc_rm_get_memreg_info(ipc_handle, mr_record, &start, &end); + if (err) + ERROR("Memreg get info failed, %u\n", mr_record); + if ((BL31_LIMIT - 1) < end) { + err = sc_rm_memreg_alloc(ipc_handle, &mr, BL31_LIMIT, end); + if (err) + ERROR("sc_rm_memreg_alloc failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n", + (sc_faddr_t)BL31_LIMIT, end); + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n", + (sc_faddr_t)BL31_LIMIT, end); + } + + if (start < (BL31_BASE - 1)) { + err = sc_rm_memreg_alloc(ipc_handle, &mr, start, BL31_BASE - 1); + if (err) + ERROR("sc_rm_memreg_alloc failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n", + start, (sc_faddr_t)BL31_BASE - 1); + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n", + start, (sc_faddr_t)BL31_BASE - 1); + } + } + + if (err) + NOTICE("Partitioning Failed\n"); + else + NOTICE("Non-secure Partitioning Succeeded\n"); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ +#if DEBUG_CONSOLE + static console_t console; +#endif + if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE) + panic(); + +#if DEBUG_CONSOLE_A35 + sc_pm_set_resource_power_mode(ipc_handle, IMX_RES_UART, + SC_PM_PW_MODE_ON); + sc_pm_clock_rate_t rate = 80000000; + sc_pm_set_clock_rate(ipc_handle, IMX_RES_UART, 2, &rate); + sc_pm_clock_enable(ipc_handle, IMX_RES_UART, 2, true, false); + + /* Configure UART pads */ + sc_pad_set(ipc_handle, IMX_PAD_UART_RX, UART_PAD_CTRL); + sc_pad_set(ipc_handle, IMX_PAD_UART_TX, UART_PAD_CTRL); + lpuart32_serial_init(IMX_BOOT_UART_BASE); +#endif + +#if DEBUG_CONSOLE + console_lpuart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); +#endif + /* Turn on MU1 for non-secure OS/Hypervisor */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON); + + /* Turn on GPT_0's power & clock for non-secure OS/Hypervisor */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON); + sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0); + mmio_write_32(IMX_GPT0_LPCG_BASE, mmio_read_32(IMX_GPT0_LPCG_BASE) | (1 << 25)); + + /* + * create new partition for non-secure OS/Hypervisor + * uses global structs defined in sec_rsrc.h + */ + imx8_partition_resources(); + + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +void bl31_plat_arch_setup(void) +{ + unsigned long ro_start = BL31_RO_START; + unsigned long ro_size = BL31_RO_END - BL31_RO_START; + unsigned long rw_start = BL31_RW_START; + unsigned long rw_size = BL31_RW_END - BL31_RW_START; +#if USE_COHERENT_MEM + unsigned long coh_start = BL31_COHERENT_RAM_START; + unsigned long coh_size = BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START; +#endif + + mmap_add_region(ro_start, ro_start, ro_size, + MT_RO | MT_MEMORY | MT_SECURE); + mmap_add_region(rw_start, rw_start, rw_size, + MT_RW | MT_MEMORY | MT_SECURE); + mmap_add(imx_mmap); + +#if USE_COHERENT_MEM + mmap_add_region(coh_start, coh_start, coh_size, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + init_xlat_tables(); + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + plat_gic_driver_init(); + plat_gic_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) + return &bl33_image_ep_info; + if (type == SECURE) + return &bl32_image_ep_info; + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} + +void bl31_plat_runtime_setup(void) +{ + return; +} diff --git a/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c b/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c new file mode 100644 index 0000000..aab3a2d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../../common/sci/imx8_mu.h" + +const static int ap_core_index[PLATFORM_CORE_COUNT] = { + SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3 +}; + +/* save gic dist/redist context when GIC is power down */ +static struct plat_gic_ctx imx_gicv3_ctx; +static unsigned int gpt_lpcg, gpt_reg[2]; + +static void imx_enable_irqstr_wakeup(void) +{ + uint32_t irq_mask; + gicv3_dist_ctx_t *dist_ctx = &imx_gicv3_ctx.dist_ctx; + + /* put IRQSTR into ON mode */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON); + + /* enable the irqsteer to handle wakeup irq */ + mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x1); + for (int i = 0; i < 15; i++) { + irq_mask = dist_ctx->gicd_isenabler[i]; + mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask); + } + + /* set IRQSTR low power mode */ + if (imx_is_wakeup_src_irqsteer()) + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY); + else + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF); +} + +static void imx_disable_irqstr_wakeup(void) +{ + /* Put IRQSTEER back to ON mode */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON); + + /* disable the irqsteer */ + mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x0); + for (int i = 0; i < 16; i++) + mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x4 + 0x4 * i, 0x0); + + /* Put IRQSTEER into OFF mode */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF); +} + +int imx_pwr_domain_on(u_register_t mpidr) +{ + int ret = PSCI_E_SUCCESS; + unsigned int cpu_id; + + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + printf("imx_pwr_domain_on cpu_id %d\n", cpu_id); + + if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_ON) != SC_ERR_NONE) { + ERROR("core %d power on failed!\n", cpu_id); + ret = PSCI_E_INTERN_FAIL; + } + + if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id], + true, BL31_BASE) != SC_ERR_NONE) { + ERROR("boot core %d failed!\n", cpu_id); + ret = PSCI_E_INTERN_FAIL; + } + + return ret; +} + +void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + plat_gic_pcpu_init(); + plat_gic_cpuif_enable(); +} + +int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) +{ + return PSCI_E_SUCCESS; +} + +void imx_pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + plat_gic_cpuif_disable(); + sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE); + printf("turn off core:%d\n", cpu_id); +} + +void imx_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL0])) { + plat_gic_cpuif_disable(); + sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE); + sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC); + } else { + dsb(); + write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); + isb(); + } + + if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL1])) + sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF); + + if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) { + plat_gic_cpuif_disable(); + + /* save gic context */ + plat_gic_save(cpu_id, &imx_gicv3_ctx); + /* enable the irqsteer for wakeup */ + imx_enable_irqstr_wakeup(); + + /* Save GPT clock and registers, then turn off its power */ + gpt_lpcg = mmio_read_32(IMX_GPT0_LPCG_BASE); + gpt_reg[0] = mmio_read_32(IMX_GPT0_BASE); + gpt_reg[1] = mmio_read_32(IMX_GPT0_BASE + 0x4); + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_OFF); + + sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF); + + /* Put GIC in OFF mode. */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF); + sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE); + if (imx_is_wakeup_src_irqsteer()) + sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER); + else + sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU); + } +} + +void imx_domain_suspend_finish(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) { + MU_Resume(SC_IPC_BASE); + + sc_pm_req_low_power_mode(ipc_handle, ap_core_index[cpu_id], SC_PM_PW_MODE_ON); + sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC); + + /* Put GIC back to high power mode. */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_ON); + + /* restore gic context */ + plat_gic_restore(cpu_id, &imx_gicv3_ctx); + + /* Turn on GPT power and restore its clock and registers */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON); + sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0); + mmio_write_32(IMX_GPT0_BASE, gpt_reg[0]); + mmio_write_32(IMX_GPT0_BASE + 0x4, gpt_reg[1]); + mmio_write_32(IMX_GPT0_LPCG_BASE, gpt_lpcg); + + sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + + /* disable the irqsteer wakeup */ + imx_disable_irqstr_wakeup(); + + plat_gic_cpuif_enable(); + } + + if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL1])) + sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON); + + if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL0])) { + sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC); + plat_gic_cpuif_enable(); + } else { + write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT)); + isb(); + } +} + +static const plat_psci_ops_t imx_plat_psci_ops = { + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, + .system_off = imx_system_off, + .system_reset = imx_system_reset, + .pwr_domain_off = imx_pwr_domain_off, + .pwr_domain_suspend = imx_domain_suspend, + .pwr_domain_suspend_finish = imx_domain_suspend_finish, + .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, + .validate_power_state = imx_validate_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + imx_mailbox_init(sec_entrypoint); + *psci_ops = &imx_plat_psci_ops; + + /* make sure system sources power ON in low power mode by default */ + sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON); + + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT, + SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON); + + return 0; +} diff --git a/arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h new file mode 100644 index 0000000..b880e1b --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0x400 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU U(0x0) +#define PLATFORM_MAX_CPU_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CORE_COUNT U(4) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) + +#define PWR_DOMAIN_AT_MAX_LVL U(1) +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_RET_STATE U(1) + +#define BL31_BASE 0x80000000 +#define BL31_LIMIT 0x80020000 + +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) + +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 8 + +#define PLAT_GICD_BASE 0x51a00000 +#define PLAT_GICR_BASE 0x51b00000 + +#if defined(IMX_USE_UART0) +#define IMX_BOOT_UART_BASE 0x5a060000 +#elif defined(IMX_USE_UART3) +#define IMX_BOOT_UART_BASE 0x5a090000 +#else +#error "Provide proper UART configuration in IMX_DEBUG_UART" +#endif + +#define IMX_BOOT_UART_BAUDRATE 115200 +#define IMX_BOOT_UART_CLK_IN_HZ 24000000 +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT__CRASH_UART_CLK_IN_HZ 24000000 +#define IMX_CONSOLE_BAUDRATE 115200 +#define SC_IPC_BASE 0x5d1b0000 +#define IMX_GPT0_LPCG_BASE 0x5d540000 +#define IMX_GPT0_BASE 0x5d140000 +#define IMX_WUP_IRQSTR_BASE 0x51090000 +#define IMX_REG_BASE 0x50000000 +#define IMX_REG_SIZE 0x10000000 + +#define COUNTER_FREQUENCY 8000000 + +/* non-secure u-boot base */ +#define PLAT_NS_IMAGE_OFFSET 0x80020000 +#define DEBUG_CONSOLE_A35 DEBUG_CONSOLE + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h b/arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h new file mode 100644 index 0000000..b7fe0e8 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* resources that are going to stay in secure partition */ +sc_rsrc_t secure_rsrcs[] = { + SC_R_MU_0A, + SC_R_A35, + SC_R_A35_0, + SC_R_A35_1, + SC_R_A35_2, + SC_R_A35_3, + SC_R_GIC, + SC_R_SYSTEM, + SC_R_IRQSTR_SCU2, + SC_R_GPT_0 +}; + +/* resources that have register access for non-secure domain */ +sc_rsrc_t ns_access_allowed[] = { + SC_R_GIC, + SC_R_GPT_0 +}; diff --git a/arm-trusted-firmware/plat/imx/imx8qx/platform.mk b/arm-trusted-firmware/plat/imx/imx8qx/platform.mk new file mode 100644 index 0000000..b25be07 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qx/platform.mk @@ -0,0 +1,40 @@ +# +# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/imx8qx/include \ + -Iplat/imx/common/include \ + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +IMX_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/imx/common/lpuart_console.S \ + plat/imx/common/imx8_helpers.S \ + plat/imx/imx8qx/imx8qx_bl31_setup.c \ + plat/imx/imx8qx/imx8qx_psci.c \ + plat/imx/common/imx8_topology.c \ + plat/imx/common/imx8_psci.c \ + plat/imx/common/imx_sip_svc.c \ + plat/imx/common/imx_sip_handler.c \ + plat/common/plat_psci_common.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/cpus/aarch64/cortex_a35.S \ + ${IMX_GIC_SOURCES} \ + +include plat/imx/common/sci/sci_api.mk + +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 + +IMX_DEBUG_UART ?= 0 +$(eval $(call add_define,IMX_USE_UART${IMX_DEBUG_UART})) + +DEBUG_CONSOLE ?= 0 +$(eval $(call add_define,DEBUG_CONSOLE)) diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c new file mode 100644 index 0000000..6e67502 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "agilex_mmc.h" +#include "agilex_clock_manager.h" +#include "agilex_memory_controller.h" +#include "agilex_pinmux.h" +#include "ccu/ncore_ccu.h" +#include "qspi/cadence_qspi.h" +#include "socfpga_emac.h" +#include "socfpga_handoff.h" +#include "socfpga_mailbox.h" +#include "socfpga_private.h" +#include "socfpga_reset_manager.h" +#include "socfpga_system_manager.h" +#include "wdt/watchdog.h" + +static struct mmc_device_info mmc_info; + +const mmap_region_t agilex_plat_mmap[] = { + MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, + MT_MEMORY | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, + MT_DEVICE | MT_RW | MT_NS), + {0}, +}; + +boot_source_type boot_source = BOOT_SOURCE; + +void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1, + u_register_t x2, u_register_t x4) +{ + static console_t console; + handoff reverse_handoff_ptr; + + generic_delay_timer_init(); + + if (socfpga_get_handoff(&reverse_handoff_ptr)) + return; + config_pinmux(&reverse_handoff_ptr); + config_clkmgr_handoff(&reverse_handoff_ptr); + + enable_nonsecure_access(); + deassert_peripheral_reset(); + config_hps_hs_before_warm_reset(); + + watchdog_init(get_wdt_clk()); + + console_16550_register(PLAT_UART0_BASE, get_uart_clk(), PLAT_BAUDRATE, + &console); + + socfpga_delay_timer_init(); + init_ncore_ccu(); + socfpga_emac_init(); + init_hard_memory_controller(); + mailbox_init(); + agx_mmc_init(); + + if (!intel_mailbox_is_fpga_not_ready()) + socfpga_bridges_enable(); +} + + +void bl2_el3_plat_arch_setup(void) +{ + + const mmap_region_t bl_regions[] = { + 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), +#if USE_COHERENT_MEM_BAR + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0}, + }; + + setup_page_tables(bl_regions, agilex_plat_mmap); + + enable_mmu_el3(0); + + dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000, get_mmc_clk()); + + mmc_info.mmc_dev_type = MMC_IS_SD; + mmc_info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3; + + /* Request ownership and direct access to QSPI */ + mailbox_hps_qspi_enable(); + + switch (boot_source) { + case BOOT_SOURCE_SDMMC: + dw_mmc_init(¶ms, &mmc_info); + socfpga_io_setup(boot_source); + break; + + case BOOT_SOURCE_QSPI: + cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL, + QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS, + QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0); + socfpga_io_setup(boot_source); + break; + + default: + ERROR("Unsupported boot source\n"); + panic(); + break; + } +} + +uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + assert(bl_mem_params); + + switch (image_id) { + case BL33_IMAGE_ID: + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = get_spsr_for_bl33_entry(); + break; + default: + break; + } + + return 0; +} + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl2_platform_setup(void) +{ +} + diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c new file mode 100644 index 0000000..168236b --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socfpga_mailbox.h" +#include "socfpga_private.h" + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + mmio_write_64(PLAT_SEC_ENTRY, PLAT_SEC_WARM_ENTRY); + + console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE, + &console); + /* + * Check params passed from BL31 should not be NULL, + */ + void *from_bl2 = (void *) arg0; + + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + + /* + * Copy BL32 (if populated by BL31) and BL33 entry point information. + * They are stored in Secure RAM, in BL31's address space. + */ + + if (params_from_bl2->h.type == PARAM_BL_PARAMS && + params_from_bl2->h.version >= VERSION_2) { + + bl_params_node_t *bl_params = params_from_bl2->head; + + while (bl_params) { + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + } else { + struct socfpga_bl31_params *arg_from_bl2 = + (struct socfpga_bl31_params *) from_bl2; + + assert(arg_from_bl2->h.type == PARAM_BL31); + assert(arg_from_bl2->h.version >= VERSION_1); + + bl32_image_ep_info = *arg_from_bl2->bl32_ep_info; + bl33_image_ep_info = *arg_from_bl2->bl33_ep_info; + } + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +static const interrupt_prop_t s10_interrupt_props[] = { + PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const gicv2_driver_data_t plat_gicv2_gic_data = { + .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE, + .gicc_base = PLAT_INTEL_SOCFPGA_GICC_BASE, + .interrupt_props = s10_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(s10_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + socfpga_delay_timer_init(); + + /* Initialize the gic cpu and distributor interfaces */ + gicv2_driver_init(&plat_gicv2_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + /* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */ + mmio_write_64(PLAT_CPU_RELEASE_ADDR, + (uint64_t)plat_secondary_cpus_bl31_entry); + + mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); +} + +const mmap_region_t plat_agilex_mmap[] = { + MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, MT_DEVICE | MT_RW | MT_NS), + {0} +}; + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_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), +#if USE_COHERENT_MEM + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_agilex_mmap); + enable_mmu_el3(0); +} + diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h new file mode 100644 index 0000000..20667f0 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CLOCKMANAGER_H +#define CLOCKMANAGER_H + +#include "socfpga_handoff.h" + +/* Clock Manager Registers */ +#define CLKMGR_OFFSET 0xffd10000 + +#define CLKMGR_CTRL 0x0 +#define CLKMGR_STAT 0x4 +#define CLKMGR_INTRCLR 0x14 + +/* Main PLL Group */ +#define CLKMGR_MAINPLL 0xffd10024 +#define CLKMGR_MAINPLL_EN 0x0 +#define CLKMGR_MAINPLL_BYPASS 0xc +#define CLKMGR_MAINPLL_MPUCLK 0x18 +#define CLKMGR_MAINPLL_NOCCLK 0x1c +#define CLKMGR_MAINPLL_NOCDIV 0x20 +#define CLKMGR_MAINPLL_PLLGLOB 0x24 +#define CLKMGR_MAINPLL_FDBCK 0x28 +#define CLKMGR_MAINPLL_MEM 0x2c +#define CLKMGR_MAINPLL_MEMSTAT 0x30 +#define CLKMGR_MAINPLL_PLLC0 0x34 +#define CLKMGR_MAINPLL_PLLC1 0x38 +#define CLKMGR_MAINPLL_VCOCALIB 0x3c +#define CLKMGR_MAINPLL_PLLC2 0x40 +#define CLKMGR_MAINPLL_PLLC3 0x44 +#define CLKMGR_MAINPLL_PLLM 0x48 +#define CLKMGR_MAINPLL_LOSTLOCK 0x54 + +/* Peripheral PLL Group */ +#define CLKMGR_PERPLL 0xffd1007c +#define CLKMGR_PERPLL_EN 0x0 +#define CLKMGR_PERPLL_BYPASS 0xc +#define CLKMGR_PERPLL_EMACCTL 0x18 +#define CLKMGR_PERPLL_GPIODIV 0x1c +#define CLKMGR_PERPLL_PLLGLOB 0x20 +#define CLKMGR_PERPLL_FDBCK 0x24 +#define CLKMGR_PERPLL_MEM 0x28 +#define CLKMGR_PERPLL_MEMSTAT 0x2c +#define CLKMGR_PERPLL_PLLC0 0x30 +#define CLKMGR_PERPLL_PLLC1 0x34 +#define CLKMGR_PERPLL_VCOCALIB 0x38 +#define CLKMGR_PERPLL_PLLC2 0x3c +#define CLKMGR_PERPLL_PLLC3 0x40 +#define CLKMGR_PERPLL_PLLM 0x44 +#define CLKMGR_PERPLL_LOSTLOCK 0x50 + +/* Altera Group */ +#define CLKMGR_ALTERA 0xffd100d0 +#define CLKMGR_ALTERA_JTAG 0x0 +#define CLKMGR_ALTERA_EMACACTR 0x4 +#define CLKMGR_ALTERA_EMACBCTR 0x8 +#define CLKMGR_ALTERA_EMACPTPCTR 0xc +#define CLKMGR_ALTERA_GPIODBCTR 0x10 +#define CLKMGR_ALTERA_SDMMCCTR 0x14 +#define CLKMGR_ALTERA_S2FUSER0CTR 0x18 +#define CLKMGR_ALTERA_S2FUSER1CTR 0x1c +#define CLKMGR_ALTERA_PSIREFCTR 0x20 +#define CLKMGR_ALTERA_EXTCNTRST 0x24 + +/* Membus */ +#define CLKMGR_MEM_REQ BIT(24) +#define CLKMGR_MEM_WR BIT(25) +#define CLKMGR_MEM_ERR BIT(26) +#define CLKMGR_MEM_WDAT_OFFSET 16 +#define CLKMGR_MEM_ADDR 0x4027 +#define CLKMGR_MEM_WDAT 0x80 + +/* Clock Manager Macros */ +#define CLKMGR_CTRL_BOOTMODE_SET_MSK 0x00000001 +#define CLKMGR_STAT_BUSY_E_BUSY 0x1 +#define CLKMGR_STAT_BUSY(x) (((x) & 0x00000001) >> 0) +#define CLKMGR_STAT_MAINPLLLOCKED(x) (((x) & 0x00000100) >> 8) +#define CLKMGR_STAT_PERPLLLOCKED(x) (((x) & 0x00010000) >> 16) +#define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK 0x00000004 +#define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK 0x00000008 +#define CLKMGR_INTOSC_HZ 460000000 + +/* Main PLL Macros */ +#define CLKMGR_MAINPLL_EN_RESET 0x000000ff + +/* Peripheral PLL Macros */ +#define CLKMGR_PERPLL_EN_RESET 0x00000fff +#define CLKMGR_PERPLL_EN_SDMMCCLK BIT(5) +#define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x) (((x) << 0) & 0x0000ffff) + +/* Altera Macros */ +#define CLKMGR_ALTERA_EXTCNTRST_RESET 0xff + +/* Shared Macros */ +#define CLKMGR_PSRC(x) (((x) & 0x00030000) >> 16) +#define CLKMGR_PSRC_MAIN 0 +#define CLKMGR_PSRC_PER 1 + +#define CLKMGR_PLLGLOB_PSRC_EOSC1 0x0 +#define CLKMGR_PLLGLOB_PSRC_INTOSC 0x1 +#define CLKMGR_PLLGLOB_PSRC_F2S 0x2 + +#define CLKMGR_PLLM_MDIV(x) ((x) & 0x000003ff) +#define CLKMGR_PLLGLOB_PD_SET_MSK 0x00000001 +#define CLKMGR_PLLGLOB_RST_SET_MSK 0x00000002 + +#define CLKMGR_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8) +#define CLKMGR_PLLGLOB_AREFCLKDIV(x) (((x) & 0x00000f00) >> 8) +#define CLKMGR_PLLGLOB_DREFCLKDIV(x) (((x) & 0x00003000) >> 12) + +#define CLKMGR_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000003ff) +#define CLKMGR_VCOCALIB_MSCNT_SET(x) (((x) << 16) & 0x00ff0000) + +#define CLKMGR_CLR_LOSTLOCK_BYPASS 0x20000000 + +typedef struct { + uint32_t clk_freq_of_eosc1; + uint32_t clk_freq_of_f2h_free; + uint32_t clk_freq_of_cb_intosc_ls; +} CLOCK_SOURCE_CONFIG; + +void config_clkmgr_handoff(handoff *hoff_ptr); +uint32_t get_wdt_clk(void); +uint32_t get_uart_clk(void); +uint32_t get_mmc_clk(void); + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h new file mode 100644 index 0000000..3746d92 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_MEMORYCONTROLLER_H +#define AGX_MEMORYCONTROLLER_H + +#define AGX_MPFE_IOHMC_REG_DRAMADDRW 0xf80100a8 +#define AGX_MPFE_IOHMC_CTRLCFG0 0xf8010028 +#define AGX_MPFE_IOHMC_CTRLCFG1 0xf801002c +#define AGX_MPFE_IOHMC_CTRLCFG2 0xf8010030 +#define AGX_MPFE_IOHMC_CTRLCFG3 0xf8010034 +#define AGX_MPFE_IOHMC_DRAMADDRW 0xf80100a8 +#define AGX_MPFE_IOHMC_DRAMTIMING0 0xf8010050 +#define AGX_MPFE_IOHMC_CALTIMING0 0xf801007c +#define AGX_MPFE_IOHMC_CALTIMING1 0xf8010080 +#define AGX_MPFE_IOHMC_CALTIMING2 0xf8010084 +#define AGX_MPFE_IOHMC_CALTIMING3 0xf8010088 +#define AGX_MPFE_IOHMC_CALTIMING4 0xf801008c +#define AGX_MPFE_IOHMC_CALTIMING9 0xf80100a0 +#define AGX_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(x) (((x) & 0x000000ff) >> 0) +#define AGX_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(value) \ + (((value) & 0x00000060) >> 5) + +#define AGX_MPFE_HMC_ADP_ECCCTRL1 0xf8011100 +#define AGX_MPFE_HMC_ADP_ECCCTRL2 0xf8011104 +#define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT 0xf8011218 +#define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE 0x000000ff +#define AGX_MPFE_HMC_ADP_RSTHANDSHAKECTRL 0xf8011214 + + +#define AGX_MPFE_IOHMC_REG_CTRLCFG1 0xf801002c + +#define AGX_MPFE_IOHMC_REG_NIOSRESERVE0_OFST 0xf8010110 + +#define IOHMC_DRAMADDRW_COL_ADDR_WIDTH(x) (((x) & 0x0000001f) >> 0) +#define IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(x) (((x) & 0x000003e0) >> 5) +#define IOHMC_DRAMADDRW_CS_ADDR_WIDTH(x) (((x) & 0x00070000) >> 16) +#define IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(x) (((x) & 0x0000c000) >> 14) +#define IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(x) (((x) & 0x00003c00) >> 10) + +#define AGX_MPFE_DDR(x) (0xf8000000 + x) +#define AGX_MPFE_HMC_ADP_DDRCALSTAT 0xf801100c +#define AGX_MPFE_DDR_MAIN_SCHED 0xf8000400 +#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF 0xf8000408 +#define AGX_MPFE_DDR_MAIN_SCHED_DDRTIMING 0xf800040c +#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK 0x0000001f +#define AGX_MPFE_DDR_MAIN_SCHED_DDRMODE 0xf8000410 +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV 0xf800043c +#define AGX_MPFE_DDR_MAIN_SCHED_READLATENCY 0xf8000414 +#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE 0xf8000438 +#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST 10 +#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST 4 +#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST 0 +#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(x) (((x) << 0) & 0x0000001f) +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST 0 +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK (BIT(0) | BIT(1)) +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST 2 +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK (BIT(2) | BIT(3)) +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST 4 +#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK (BIT(4) | BIT(5)) + +#define AGX_MPFE_HMC_ADP(x) (0xf8011000 + (x)) +#define AGX_MPFE_HMC_ADP_HPSINTFCSEL 0xf8011210 +#define AGX_MPFE_HMC_ADP_DDRIOCTRL 0xf8011008 +#define HMC_ADP_DDRIOCTRL 0x8 +#define HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0) +#define HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(x) (((x) & 0x00003e00) >> 9) +#define ADP_DRAMADDRWIDTH 0xe0 + +#define ACT_TO_ACT_DIFF_BANK(value) (((value) & 0x00fc0000) >> 18) +#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12) +#define ACT_TO_RDWR(value) (((value) & 0x0000003f) >> 0) +#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12) + +/* timing 2 */ +#define RD_TO_RD_DIFF_CHIP(value) (((value) & 0x00000fc0) >> 6) +#define RD_TO_WR_DIFF_CHIP(value) (((value) & 0x3f000000) >> 24) +#define RD_TO_WR(value) (((value) & 0x00fc0000) >> 18) +#define RD_TO_PCH(value) (((value) & 0x00000fc0) >> 6) + +/* timing 3 */ +#define CALTIMING3_WR_TO_RD_DIFF_CHIP(value) (((value) & 0x0003f000) >> 12) +#define CALTIMING3_WR_TO_RD(value) (((value) & 0x00000fc0) >> 6) + +/* timing 4 */ +#define PCH_TO_VALID(value) (((value) & 0x00000fc0) >> 6) + +#define DDRTIMING_BWRATIO_OFST 31 +#define DDRTIMING_WRTORD_OFST 26 +#define DDRTIMING_RDTOWR_OFST 21 +#define DDRTIMING_BURSTLEN_OFST 18 +#define DDRTIMING_WRTOMISS_OFST 12 +#define DDRTIMING_RDTOMISS_OFST 6 +#define DDRTIMING_ACTTOACT_OFST 0 + +#define ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x3) >> 0) + +#define DDRMODE_AUTOPRECHARGE_OFST 1 +#define DDRMODE_BWRATIOEXTENDED_OFST 0 + + +#define AGX_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(x) (((x) & 0x7f) >> 0) +#define AGX_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(x) (((x) & 0x0f) >> 0) + +#define AGX_CCU_CPU0_MPRT_DDR 0xf7004400 +#define AGX_CCU_CPU0_MPRT_MEM0 0xf70045c0 +#define AGX_CCU_CPU0_MPRT_MEM1A 0xf70045e0 +#define AGX_CCU_CPU0_MPRT_MEM1B 0xf7004600 +#define AGX_CCU_CPU0_MPRT_MEM1C 0xf7004620 +#define AGX_CCU_CPU0_MPRT_MEM1D 0xf7004640 +#define AGX_CCU_CPU0_MPRT_MEM1E 0xf7004660 +#define AGX_CCU_IOM_MPRT_MEM0 0xf7018560 +#define AGX_CCU_IOM_MPRT_MEM1A 0xf7018580 +#define AGX_CCU_IOM_MPRT_MEM1B 0xf70185a0 +#define AGX_CCU_IOM_MPRT_MEM1C 0xf70185c0 +#define AGX_CCU_IOM_MPRT_MEM1D 0xf70185e0 +#define AGX_CCU_IOM_MPRT_MEM1E 0xf7018600 + +#define AGX_NOC_FW_DDR_SCR 0xf8020200 +#define AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT 0xf802021c +#define AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT 0xf8020218 +#define AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT 0xf802029c +#define AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT 0xf8020298 + +#define AGX_SOC_NOC_FW_DDR_SCR_ENABLE 0xf8020200 +#define AGX_SOC_NOC_FW_DDR_SCR_ENABLESET 0xf8020204 +#define AGX_CCU_NOC_DI_SET_MSK 0x10 + +#define AGX_SYSMGR_CORE_HMC_CLK 0xffd120b4 +#define AGX_SYSMGR_CORE_HMC_CLK_STATUS 0x00000001 + +#define AGX_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0(x) (((x) & 0xffff) >> 0) +#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_MSK 0x00000003 +#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_OFST 0 +#define AGX_MPFE_HMC_ADP_HPSINTFCSEL_ENABLE 0x001f1f1f +#define AGX_IOHMC_CTRLCFG1_ENABLE_ECC_OFST 7 + +#define AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK 0x00010000 +#define AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK 0x00000100 +#define AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK 0x00000001 + +#define AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK 0x00000001 +#define AGX_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK 0x00010000 +#define AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK 0x00000100 +#define AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(value) (((value) & 0x1) >> 0) + + +#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00003) >> 0) +#define IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(x) (((x) & 0x03c00) >> 10) +#define IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(x) (((x) & 0x0c000) >> 14) +#define IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(x) (((x) & 0x0001f) >> 0) +#define IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(x) (((x) & 0x70000) >> 16) +#define IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(x) (((x) & 0x003e0) >> 5) + +#define AGX_SDRAM_0_LB_ADDR 0x0 +#define AGX_DDR_SIZE 0x40000000 + +int init_hard_memory_controller(void); + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h new file mode 100644 index 0000000..00f4ca5 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2020, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +void agx_mmc_init(void); diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h new file mode 100644 index 0000000..22db3e2 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_NOC_H +#define AGX_NOC_H + + +#define AXI_AP (1<<0) +#define FPGA2SOC (1<<16) +#define MPU (1<<24) +#define AGX_NOC_PER_SCR_NAND 0xffd21000 +#define AGX_NOC_PER_SCR_NAND_DATA 0xffd21004 +#define AGX_NOC_PER_SCR_USB0 0xffd2100c +#define AGX_NOC_PER_SCR_USB1 0xffd21010 +#define AGX_NOC_PER_SCR_SPI_M0 0xffd2101c +#define AGX_NOC_PER_SCR_SPI_M1 0xffd21020 +#define AGX_NOC_PER_SCR_SPI_S0 0xffd21024 +#define AGX_NOC_PER_SCR_SPI_S1 0xffd21028 +#define AGX_NOC_PER_SCR_EMAC0 0xffd2102c +#define AGX_NOC_PER_SCR_EMAC1 0xffd21030 +#define AGX_NOC_PER_SCR_EMAC2 0xffd21034 +#define AGX_NOC_PER_SCR_SDMMC 0xffd21040 +#define AGX_NOC_PER_SCR_GPIO0 0xffd21044 +#define AGX_NOC_PER_SCR_GPIO1 0xffd21048 +#define AGX_NOC_PER_SCR_I2C0 0xffd21050 +#define AGX_NOC_PER_SCR_I2C1 0xffd21058 +#define AGX_NOC_PER_SCR_I2C2 0xffd2105c +#define AGX_NOC_PER_SCR_I2C3 0xffd21060 +#define AGX_NOC_PER_SCR_SP_TIMER0 0xffd21064 +#define AGX_NOC_PER_SCR_SP_TIMER1 0xffd21068 +#define AGX_NOC_PER_SCR_UART0 0xffd2106c +#define AGX_NOC_PER_SCR_UART1 0xffd21070 + + +#define AGX_NOC_SYS_SCR_DMA_ECC 0xffd21108 +#define AGX_NOC_SYS_SCR_EMAC0RX_ECC 0xffd2110c +#define AGX_NOC_SYS_SCR_EMAC0TX_ECC 0xffd21110 +#define AGX_NOC_SYS_SCR_EMAC1RX_ECC 0xffd21114 +#define AGX_NOC_SYS_SCR_EMAC1TX_ECC 0xffd21118 +#define AGX_NOC_SYS_SCR_EMAC2RX_ECC 0xffd2111c +#define AGX_NOC_SYS_SCR_EMAC2TX_ECC 0xffd21120 +#define AGX_NOC_SYS_SCR_NAND_ECC 0xffd2112c +#define AGX_NOC_SYS_SCR_NAND_READ_ECC 0xffd21130 +#define AGX_NOC_SYS_SCR_NAND_WRITE_ECC 0xffd21134 +#define AGX_NOC_SYS_SCR_OCRAM_ECC 0xffd21138 +#define AGX_NOC_SYS_SCR_SDMMC_ECC 0xffd21140 +#define AGX_NOC_SYS_SCR_USB0_ECC 0xffd21144 +#define AGX_NOC_SYS_SCR_USB1_ECC 0xffd21148 +#define AGX_NOC_SYS_SCR_CLK_MGR 0xffd2114c +#define AGX_NOC_SYS_SCR_IO_MGR 0xffd21154 +#define AGX_NOC_SYS_SCR_RST_MGR 0xffd21158 +#define AGX_NOC_SYS_SCR_SYS_MGR 0xffd2115c +#define AGX_NOC_SYS_SCR_OSC0_TIMER 0xffd21160 +#define AGX_NOC_SYS_SCR_OSC1_TIMER 0xffd21164 +#define AGX_NOC_SYS_SCR_WATCHDOG0 0xffd21168 +#define AGX_NOC_SYS_SCR_WATCHDOG1 0xffd2116c +#define AGX_NOC_SYS_SCR_WATCHDOG2 0xffd21170 +#define AGX_NOC_SYS_SCR_WATCHDOG3 0xffd21174 +#define AGX_NOC_SYS_SCR_DAP 0xffd21178 +#define AGX_NOC_SYS_SCR_L4_NOC_PROBES 0xffd21190 +#define AGX_NOC_SYS_SCR_L4_NOC_QOS 0xffd21194 + +#define AGX_CCU_NOC_BRIDGE_CPU0_RAM 0xf7004688 +#define AGX_CCU_NOC_BRIDGE_IOM_RAM 0xf7004688 + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h new file mode 100644 index 0000000..fe01062 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_PINMUX_H +#define AGX_PINMUX_H + +#define AGX_PINMUX_PIN0SEL 0xffd13000 +#define AGX_PINMUX_IO0CTRL 0xffd13130 +#define AGX_PINMUX_PINMUX_EMAC0_USEFPGA 0xffd13300 +#define AGX_PINMUX_IO0_DELAY 0xffd13400 + +#include "socfpga_handoff.h" + +void config_pinmux(handoff *handoff); + +#endif + diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h new file mode 100644 index 0000000..9c87e45 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SOCFPGA_DEF_H +#define PLAT_SOCFPGA_DEF_H + +#include + +/* Platform Setting */ +#define PLATFORM_MODEL PLAT_SOCFPGA_AGILEX +#define BOOT_SOURCE BOOT_SOURCE_SDMMC + +/* FPGA config helpers */ +#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x400000 +#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE 0x2000000 + +/* Register Mapping */ +#define SOCFPGA_MMC_REG_BASE 0xff808000 + +#define SOCFPGA_RSTMGR_REG_BASE 0xffd11000 +#define SOCFPGA_SYSMGR_REG_BASE 0xffd12000 + +#define SOCFPGA_L4_PER_SCR_REG_BASE 0xffd21000 +#define SOCFPGA_L4_SYS_SCR_REG_BASE 0xffd21100 +#define SOCFPGA_SOC2FPGA_SCR_REG_BASE 0xffd21200 +#define SOCFPGA_LWSOC2FPGA_SCR_REG_BASE 0xffd21300 + +#endif /* PLAT_SOCFPGA_DEF_H */ + diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/platform.mk b/arm-trusted-firmware/plat/intel/soc/agilex/platform.mk new file mode 100644 index 0000000..10a3eec --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/platform.mk @@ -0,0 +1,78 @@ +# +# Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2019-2022, Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := \ + -Iplat/intel/soc/agilex/include/ \ + -Iplat/intel/soc/common/drivers/ \ + -Iplat/intel/soc/common/include/ + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk +AGX_GICv2_SOURCES := \ + ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c + + +PLAT_BL_COMMON_SOURCES := \ + ${AGX_GICv2_SOURCES} \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/intel/soc/common/aarch64/platform_common.c \ + plat/intel/soc/common/aarch64/plat_helpers.S \ + plat/intel/soc/common/socfpga_delay_timer.c + +BL2_SOURCES += \ + common/desc_image_load.c \ + drivers/mmc/mmc.c \ + drivers/intel/soc/stratix10/io/s10_memmap_qspi.c \ + drivers/io/io_storage.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/partition/partition.c \ + drivers/partition/gpt.c \ + drivers/synopsys/emmc/dw_mmc.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/intel/soc/agilex/bl2_plat_setup.c \ + plat/intel/soc/agilex/soc/agilex_clock_manager.c \ + plat/intel/soc/agilex/soc/agilex_memory_controller.c \ + plat/intel/soc/agilex/soc/agilex_mmc.c \ + plat/intel/soc/agilex/soc/agilex_pinmux.c \ + plat/intel/soc/common/bl2_plat_mem_params_desc.c \ + plat/intel/soc/common/socfpga_image_load.c \ + plat/intel/soc/common/socfpga_storage.c \ + plat/intel/soc/common/soc/socfpga_emac.c \ + plat/intel/soc/common/soc/socfpga_handoff.c \ + plat/intel/soc/common/soc/socfpga_mailbox.c \ + plat/intel/soc/common/soc/socfpga_reset_manager.c \ + plat/intel/soc/common/soc/socfpga_system_manager.c \ + plat/intel/soc/common/drivers/qspi/cadence_qspi.c \ + plat/intel/soc/common/drivers/wdt/watchdog.c \ + plat/intel/soc/common/drivers/ccu/ncore_ccu.c + +BL31_SOURCES += \ + drivers/arm/cci/cci.c \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/intel/soc/agilex/bl31_plat_setup.c \ + plat/intel/soc/common/socfpga_psci.c \ + plat/intel/soc/common/socfpga_sip_svc.c \ + plat/intel/soc/common/socfpga_topology.c \ + plat/intel/soc/common/sip/socfpga_sip_ecc.c \ + plat/intel/soc/common/sip/socfpga_sip_fcs.c \ + plat/intel/soc/common/soc/socfpga_mailbox.c \ + plat/intel/soc/common/soc/socfpga_reset_manager.c + +PROGRAMMABLE_RESET_ADDRESS := 0 +BL2_AT_EL3 := 1 +BL2_INV_DCACHE := 0 +MULTI_CONSOLE_API := 1 +SIMICS_BUILD := 0 +USE_COHERENT_MEM := 1 diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c new file mode 100644 index 0000000..4efd713 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include "agilex_clock_manager.h" +#include "socfpga_handoff.h" +#include "socfpga_system_manager.h" + + +uint32_t wait_pll_lock(void) +{ + uint32_t data; + uint32_t count = 0; + + do { + data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT); + count++; + if (count >= 1000) + return -ETIMEDOUT; + + } while ((CLKMGR_STAT_MAINPLLLOCKED(data) == 0) || + (CLKMGR_STAT_PERPLLLOCKED(data) == 0)); + return 0; +} + +uint32_t wait_fsm(void) +{ + uint32_t data; + uint32_t count = 0; + + do { + data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT); + count++; + if (count >= 1000) + return -ETIMEDOUT; + + } while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY); + + return 0; +} + +uint32_t pll_source_sync_config(uint32_t pll_mem_offset, uint32_t data) +{ + uint32_t val = 0; + uint32_t count = 0; + uint32_t req_status = 0; + + val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ | + (data << CLKMGR_MEM_WDAT_OFFSET) | CLKMGR_MEM_ADDR); + mmio_write_32(pll_mem_offset, val); + + do { + req_status = mmio_read_32(pll_mem_offset); + count++; + } while ((req_status & CLKMGR_MEM_REQ) && (count < 10)); + + if (count >= 100) + return -ETIMEDOUT; + + return 0; +} + +uint32_t pll_source_sync_read(uint32_t pll_mem_offset) +{ + uint32_t val = 0; + uint32_t rdata = 0; + uint32_t count = 0; + uint32_t req_status = 0; + + val = (CLKMGR_MEM_REQ | CLKMGR_MEM_ADDR); + mmio_write_32(pll_mem_offset, val); + + do { + req_status = mmio_read_32(pll_mem_offset); + count++; + } while ((req_status & CLKMGR_MEM_REQ) && (count < 10)); + + if (count >= 100) + return -ETIMEDOUT; + + rdata = mmio_read_32(pll_mem_offset + 0x4); + INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata); + + return rdata; +} + +void config_clkmgr_handoff(handoff *hoff_ptr) +{ + uint32_t mdiv, mscnt, hscnt; + uint32_t drefclk_div, refclk_div, rdata; + + /* Set clock maanger into boot mode before running configuration */ + mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_CTRL, + CLKMGR_CTRL_BOOTMODE_SET_MSK); + /* Bypass all mainpllgrp's clocks */ + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0x7); + wait_fsm(); + + /* Bypass all perpllgrp's clocks */ + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0x7f); + wait_fsm(); + + /* Put both PLL in reset and power down */ + mmio_clrbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_SET_MSK | + CLKMGR_PLLGLOB_RST_SET_MSK); + mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_SET_MSK | + CLKMGR_PLLGLOB_RST_SET_MSK); + + /* Setup main PLL dividers */ + mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->main_pll_pllm); + + drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV( + hoff_ptr->main_pll_pllglob); + refclk_div = CLKMGR_PLLGLOB_REFCLKDIV( + hoff_ptr->main_pll_pllglob); + + mscnt = 100 / (mdiv * BIT(drefclk_div)); + if (!mscnt) + mscnt = 1; + hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4; + + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, + hoff_ptr->main_pll_pllglob & + ~CLKMGR_PLLGLOB_RST_SET_MSK); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK, + hoff_ptr->main_pll_fdbck); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB, + CLKMGR_VCOCALIB_HSCNT_SET(hscnt) | + CLKMGR_VCOCALIB_MSCNT_SET(mscnt)); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC0, + hoff_ptr->main_pll_pllc0); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC1, + hoff_ptr->main_pll_pllc1); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC2, + hoff_ptr->main_pll_pllc2); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC3, + hoff_ptr->main_pll_pllc3); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM, + hoff_ptr->main_pll_pllm); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MPUCLK, + hoff_ptr->main_pll_mpuclk); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCCLK, + hoff_ptr->main_pll_nocclk); + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV, + hoff_ptr->main_pll_nocdiv); + + /* Setup peripheral PLL dividers */ + mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->per_pll_pllm); + + drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV( + hoff_ptr->per_pll_pllglob); + refclk_div = CLKMGR_PLLGLOB_REFCLKDIV( + hoff_ptr->per_pll_pllglob); + + + mscnt = 100 / (mdiv * BIT(drefclk_div)); + if (!mscnt) + mscnt = 1; + hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4; + + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, + hoff_ptr->per_pll_pllglob & + ~CLKMGR_PLLGLOB_RST_SET_MSK); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK, + hoff_ptr->per_pll_fdbck); + + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB, + CLKMGR_VCOCALIB_HSCNT_SET(hscnt) | + CLKMGR_VCOCALIB_MSCNT_SET(mscnt)); + + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC0, + hoff_ptr->per_pll_pllc0); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC1, + hoff_ptr->per_pll_pllc1); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC2, + hoff_ptr->per_pll_pllc2); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC3, + hoff_ptr->per_pll_pllc3); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM, + hoff_ptr->per_pll_pllm); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL, + hoff_ptr->per_pll_emacctl); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV, + hoff_ptr->per_pll_gpiodiv); + + /* Take both PLL out of reset and power up */ + mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_SET_MSK | + CLKMGR_PLLGLOB_RST_SET_MSK); + mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_SET_MSK | + CLKMGR_PLLGLOB_RST_SET_MSK); + + rdata = pll_source_sync_read(CLKMGR_MAINPLL + + CLKMGR_MAINPLL_MEM); + pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM, + rdata | 0x80); + + rdata = pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM); + pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM, + rdata | 0x80); + + wait_pll_lock(); + + /*Configure Ping Pong counters in altera group */ + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACACTR, + hoff_ptr->alt_emacactr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACBCTR, + hoff_ptr->alt_emacbctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACPTPCTR, + hoff_ptr->alt_emacptpctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_GPIODBCTR, + hoff_ptr->alt_gpiodbctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR, + hoff_ptr->alt_sdmmcctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER0CTR, + hoff_ptr->alt_s2fuser0ctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER1CTR, + hoff_ptr->alt_s2fuser1ctr); + mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_PSIREFCTR, + hoff_ptr->alt_psirefctr); + + /* Clear lost lock bypass mode */ + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_LOSTLOCK, 0x1); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_LOSTLOCK, 0x1); + + mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_CLR_LOSTLOCK_BYPASS); + + mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, + CLKMGR_CLR_LOSTLOCK_BYPASS); + + /* Take all PLLs out of bypass */ + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0); + wait_fsm(); + + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0); + wait_fsm(); + + /* Clear loss lock interrupt status register that */ + /* might be set during configuration */ + mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR, + CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK | + CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK); + + /* Take all ping pong counters out of reset */ + mmio_clrbits_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EXTCNTRST, + CLKMGR_ALTERA_EXTCNTRST_RESET); + + /* Set safe mode / out of boot mode */ + mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_CTRL, + CLKMGR_CTRL_BOOTMODE_SET_MSK); + wait_fsm(); + + /* Enable mainpllgrp's software-managed clock */ + mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_EN, + CLKMGR_MAINPLL_EN_RESET); + mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN, + CLKMGR_PERPLL_EN_RESET); + + /* Pass clock source frequency into scratch register */ + mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1), + hoff_ptr->hps_osc_clk_h); + mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2), + hoff_ptr->fpga_clk_hz); +} + +/* Extract reference clock from platform clock source */ +uint32_t get_ref_clk(uint32_t pllglob) +{ + uint32_t arefclkdiv, ref_clk; + uint32_t scr_reg; + + switch (CLKMGR_PSRC(pllglob)) { + case CLKMGR_PLLGLOB_PSRC_EOSC1: + scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1); + ref_clk = mmio_read_32(scr_reg); + break; + case CLKMGR_PLLGLOB_PSRC_INTOSC: + ref_clk = CLKMGR_INTOSC_HZ; + break; + case CLKMGR_PLLGLOB_PSRC_F2S: + scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2); + ref_clk = mmio_read_32(scr_reg); + break; + default: + ref_clk = 0; + assert(0); + break; + } + + arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob); + ref_clk /= arefclkdiv; + + return ref_clk; +} + +/* Calculate clock frequency based on parameter */ +uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc) +{ + uint32_t clk_psrc, mdiv, ref_clk; + uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg; + + clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg); + + switch (CLKMGR_PSRC(clk_psrc)) { + case CLKMGR_PSRC_MAIN: + pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM; + pllc_reg = CLKMGR_MAINPLL + main_pllc; + pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB; + break; + case CLKMGR_PSRC_PER: + pllm_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM; + pllc_reg = CLKMGR_PERPLL + per_pllc; + pllglob_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB; + break; + default: + return 0; + } + + ref_clk = get_ref_clk(mmio_read_32(pllglob_reg)); + mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg)); + ref_clk *= mdiv; + + pllc_div = mmio_read_32(pllc_reg) & 0x7ff; + + return ref_clk / pllc_div; +} + +/* Return L3 interconnect clock */ +uint32_t get_l3_clk(void) +{ + uint32_t l3_clk; + + l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1, + CLKMGR_PERPLL_PLLC1); + return l3_clk; +} + +/* Calculate clock frequency to be used for watchdog timer */ +uint32_t get_wdt_clk(void) +{ + uint32_t l3_clk, l4_sys_clk; + + l3_clk = get_l3_clk(); + l4_sys_clk = l3_clk / 4; + + return l4_sys_clk; +} + +/* Calculate clock frequency to be used for UART driver */ +uint32_t get_uart_clk(void) +{ + uint32_t data32, l3_clk, l4_sp_clk; + + l3_clk = get_l3_clk(); + + data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV); + data32 = (data32 >> 16) & 0x3; + + l4_sp_clk = l3_clk >> data32; + + return l4_sp_clk; +} + +/* Calculate clock frequency to be used for SDMMC driver */ +uint32_t get_mmc_clk(void) +{ + uint32_t data32, mmc_clk; + + mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR, + CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3); + + data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR); + data32 = (data32 & 0x7ff) + 1; + mmc_clk = (mmc_clk / data32) / 4; + + return mmc_clk; +} diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c new file mode 100644 index 0000000..2aabe87 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "agilex_memory_controller.h" + +#define ALT_CCU_NOC_DI_SET_MSK 0x10 + +#define DDR_READ_LATENCY_DELAY 40 +#define MAX_MEM_CAL_RETRY 3 +#define PRE_CALIBRATION_DELAY 1 +#define POST_CALIBRATION_DELAY 1 +#define TIMEOUT_EMIF_CALIBRATION 1000 +#define CLEAR_EMIF_DELAY 1000 +#define CLEAR_EMIF_TIMEOUT 1000 + +#define DDR_CONFIG(A, B, C, R) (((A) << 24) | ((B) << 16) | ((C) << 8) | (R)) +#define DDR_CONFIG_ELEMENTS (sizeof(ddr_config)/sizeof(uint32_t)) + +/* tWR = Min. 15ns constant, see JEDEC standard eg. DDR4 is JESD79-4.pdf */ +#define tWR_IN_NS 15 + +void configure_hmc_adaptor_regs(void); +void configure_ddr_sched_ctrl_regs(void); + +/* The followring are the supported configurations */ +uint32_t ddr_config[] = { + /* DDR_CONFIG(Address order,Bank,Column,Row) */ + /* List for DDR3 or LPDDR3 (pinout order > chip, row, bank, column) */ + DDR_CONFIG(0, 3, 10, 12), + DDR_CONFIG(0, 3, 9, 13), + DDR_CONFIG(0, 3, 10, 13), + DDR_CONFIG(0, 3, 9, 14), + DDR_CONFIG(0, 3, 10, 14), + DDR_CONFIG(0, 3, 10, 15), + DDR_CONFIG(0, 3, 11, 14), + DDR_CONFIG(0, 3, 11, 15), + DDR_CONFIG(0, 3, 10, 16), + DDR_CONFIG(0, 3, 11, 16), + DDR_CONFIG(0, 3, 12, 15), /* 0xa */ + /* List for DDR4 only (pinout order > chip, bank, row, column) */ + DDR_CONFIG(1, 3, 10, 14), + DDR_CONFIG(1, 4, 10, 14), + DDR_CONFIG(1, 3, 10, 15), + DDR_CONFIG(1, 4, 10, 15), + DDR_CONFIG(1, 3, 10, 16), + DDR_CONFIG(1, 4, 10, 16), + DDR_CONFIG(1, 3, 10, 17), + DDR_CONFIG(1, 4, 10, 17), +}; + +static int match_ddr_conf(uint32_t ddr_conf) +{ + int i; + + for (i = 0; i < DDR_CONFIG_ELEMENTS; i++) { + if (ddr_conf == ddr_config[i]) + return i; + } + return 0; +} + +static int check_hmc_clk(void) +{ + unsigned long timeout = 0; + uint32_t hmc_clk; + + do { + hmc_clk = mmio_read_32(AGX_SYSMGR_CORE_HMC_CLK); + if (hmc_clk & AGX_SYSMGR_CORE_HMC_CLK_STATUS) + break; + udelay(1); + } while (++timeout < 1000); + if (timeout >= 1000) + return -ETIMEDOUT; + + return 0; +} + +static int clear_emif(void) +{ + uint32_t data; + unsigned long timeout; + + mmio_write_32(AGX_MPFE_HMC_ADP_RSTHANDSHAKECTRL, 0); + + timeout = 0; + do { + data = mmio_read_32(AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT); + if ((data & AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE) == 0) + break; + udelay(CLEAR_EMIF_DELAY); + } while (++timeout < CLEAR_EMIF_TIMEOUT); + if (timeout >= CLEAR_EMIF_TIMEOUT) + return -ETIMEDOUT; + + return 0; +} + +static int mem_calibration(void) +{ + int status; + uint32_t data; + unsigned long timeout; + unsigned long retry = 0; + + udelay(PRE_CALIBRATION_DELAY); + + do { + if (retry != 0) + INFO("DDR: Retrying DRAM calibration\n"); + + timeout = 0; + do { + data = mmio_read_32(AGX_MPFE_HMC_ADP_DDRCALSTAT); + if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 1) + break; + udelay(500); + } while (++timeout < TIMEOUT_EMIF_CALIBRATION); + + if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) { + status = clear_emif(); + if (status) + ERROR("Failed to clear Emif\n"); + } else { + break; + } + } while (++retry < MAX_MEM_CAL_RETRY); + + if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) { + ERROR("DDR: DRAM calibration failed.\n"); + status = -EIO; + } else { + INFO("DDR: DRAM calibration success.\n"); + status = 0; + } + + udelay(POST_CALIBRATION_DELAY); + + return status; +} + +int init_hard_memory_controller(void) +{ + int status; + + status = check_hmc_clk(); + if (status) { + ERROR("DDR: Error, HMC clock not running\n"); + return status; + } + + status = mem_calibration(); + if (status) { + ERROR("DDR: Memory Calibration Failed\n"); + return status; + } + + configure_hmc_adaptor_regs(); + + return 0; +} + +void configure_ddr_sched_ctrl_regs(void) +{ + uint32_t data, dram_addr_order, ddr_conf, bank, row, col, + rd_to_miss, wr_to_miss, burst_len, burst_len_ddr_clk, + burst_len_sched_clk, act_to_act, rd_to_wr, wr_to_rd, bw_ratio, + t_rtp, t_rp, t_rcd, rd_latency, tw_rin_clk_cycles, + bw_ratio_extended, auto_precharge = 0, act_to_act_bank, faw, + faw_bank, bus_rd_to_rd, bus_rd_to_wr, bus_wr_to_rd; + + INFO("Init HPS NOC's DDR Scheduler.\n"); + + data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG1); + dram_addr_order = AGX_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_DRAMADDRW); + + col = IOHMC_DRAMADDRW_COL_ADDR_WIDTH(data); + row = IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(data); + bank = IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(data); + + ddr_conf = match_ddr_conf(DDR_CONFIG(dram_addr_order, bank, col, row)); + + if (ddr_conf) { + mmio_clrsetbits_32( + AGX_MPFE_DDR_MAIN_SCHED_DDRCONF, + AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK, + AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(ddr_conf)); + } else { + ERROR("DDR: Cannot find predefined ddrConf configuration.\n"); + } + + mmio_write_32(AGX_MPFE_HMC_ADP(ADP_DRAMADDRWIDTH), data); + + data = mmio_read_32(AGX_MPFE_IOHMC_DRAMTIMING0); + rd_latency = AGX_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING0); + act_to_act = ACT_TO_ACT(data); + t_rcd = ACT_TO_RDWR(data); + act_to_act_bank = ACT_TO_ACT_DIFF_BANK(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING1); + rd_to_wr = RD_TO_WR(data); + bus_rd_to_rd = RD_TO_RD_DIFF_CHIP(data); + bus_rd_to_wr = RD_TO_WR_DIFF_CHIP(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING2); + t_rtp = RD_TO_PCH(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING3); + wr_to_rd = CALTIMING3_WR_TO_RD(data); + bus_wr_to_rd = CALTIMING3_WR_TO_RD_DIFF_CHIP(data); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING4); + t_rp = PCH_TO_VALID(data); + + data = mmio_read_32(AGX_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL)); + bw_ratio = ((HMC_ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 0 : 1); + + data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG0); + burst_len = HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(data); + burst_len_ddr_clk = burst_len / 2; + burst_len_sched_clk = ((burst_len/2) / 2); + + data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG0); + switch (AGX_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(data)) { + case 1: + /* DDR4 - 1333MHz */ + /* 20 (19.995) clock cycles = 15ns */ + /* Calculate with rounding */ + tw_rin_clk_cycles = (((tWR_IN_NS * 1333) % 1000) >= 500) ? + ((tWR_IN_NS * 1333) / 1000) + 1 : + ((tWR_IN_NS * 1333) / 1000); + break; + default: + /* Others - 1066MHz or slower */ + /* 16 (15.990) clock cycles = 15ns */ + /* Calculate with rounding */ + tw_rin_clk_cycles = (((tWR_IN_NS * 1066) % 1000) >= 500) ? + ((tWR_IN_NS * 1066) / 1000) + 1 : + ((tWR_IN_NS * 1066) / 1000); + break; + } + + rd_to_miss = t_rtp + t_rp + t_rcd - burst_len_sched_clk; + wr_to_miss = ((rd_latency + burst_len_ddr_clk + 2 + tw_rin_clk_cycles) + / 2) - rd_to_wr + t_rp + t_rcd; + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DDRTIMING, + bw_ratio << DDRTIMING_BWRATIO_OFST | + wr_to_rd << DDRTIMING_WRTORD_OFST| + rd_to_wr << DDRTIMING_RDTOWR_OFST | + burst_len_sched_clk << DDRTIMING_BURSTLEN_OFST | + wr_to_miss << DDRTIMING_WRTOMISS_OFST | + rd_to_miss << DDRTIMING_RDTOMISS_OFST | + act_to_act << DDRTIMING_ACTTOACT_OFST); + + data = mmio_read_32(AGX_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL)); + bw_ratio_extended = ((ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 1 : 0); + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DDRMODE, + bw_ratio_extended << DDRMODE_BWRATIOEXTENDED_OFST | + auto_precharge << DDRMODE_AUTOPRECHARGE_OFST); + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_READLATENCY, + (rd_latency / 2) + DDR_READ_LATENCY_DELAY); + + data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING9); + faw = AGX_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(data); + + faw_bank = 1; // always 1 because we always have 4 bank DDR. + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE, + faw_bank << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST | + faw << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST | + act_to_act_bank << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST); + + mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV, + ((bus_rd_to_rd + << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST) + & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK) | + ((bus_rd_to_wr + << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST) + & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK) | + ((bus_wr_to_rd + << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST) + & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK)); + +} + +unsigned long get_physical_dram_size(void) +{ + uint32_t data; + unsigned long ram_addr_width, ram_ext_if_io_width; + + data = mmio_read_32(AGX_MPFE_HMC_ADP_DDRIOCTRL); + switch (AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(data)) { + case 0: + ram_ext_if_io_width = 16; + break; + case 1: + ram_ext_if_io_width = 32; + break; + case 2: + ram_ext_if_io_width = 64; + break; + default: + ram_ext_if_io_width = 0; + break; + } + + data = mmio_read_32(AGX_MPFE_IOHMC_REG_DRAMADDRW); + ram_addr_width = IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(data); + + return (1 << ram_addr_width) * (ram_ext_if_io_width / 8); +} + + + +void configure_hmc_adaptor_regs(void) +{ + uint32_t data; + uint32_t dram_io_width; + + /* Configure DDR data rate */ + dram_io_width = AGX_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0( + mmio_read_32(AGX_MPFE_IOHMC_REG_NIOSRESERVE0_OFST)); + dram_io_width = (dram_io_width & 0xFF) >> 5; + + data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG3); + + dram_io_width |= (data & 0x4); + + mmio_write_32(AGX_MPFE_HMC_ADP_DDRIOCTRL, dram_io_width); + + /* Copy dram addr width from IOHMC to HMC ADP */ + data = mmio_read_32(AGX_MPFE_IOHMC_DRAMADDRW); + mmio_write_32(AGX_MPFE_HMC_ADP(ADP_DRAMADDRWIDTH), data); + + /* Enable nonsecure access to DDR */ + data = get_physical_dram_size(); + + if (data < AGX_DDR_SIZE) + data = AGX_DDR_SIZE; + + mmio_write_32(AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT, data - 1); + mmio_write_32(AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT, 0x1f); + + mmio_write_32(AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT, data - 1); + + mmio_write_32(AGX_SOC_NOC_FW_DDR_SCR_ENABLESET, BIT(0) | BIT(8)); + + /* ECC enablement */ + data = mmio_read_32(AGX_MPFE_IOHMC_REG_CTRLCFG1); + if (data & (1 << AGX_IOHMC_CTRLCFG1_ENABLE_ECC_OFST)) { + mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL1, + AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK, + AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK); + + mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL2, + AGX_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK, + AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK); + + mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL1, + AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK | + AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK, + AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK); + INFO("Scrubbing ECC\n"); + + /* ECC Scrubbing */ + zeromem(DRAM_BASE, DRAM_SIZE); + } else { + INFO("ECC is disabled.\n"); + } +} diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c new file mode 100644 index 0000000..e05d92a --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include "socfpga_system_manager.h" +#include "agilex_clock_manager.h" + +void agx_mmc_init(void) +{ + mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN, + CLKMGR_PERPLL_EN_SDMMCCLK); + mmio_write_32(SOCFPGA_SYSMGR(SDMMC), + SYSMGR_SDMMC_SMPLSEL(0) | SYSMGR_SDMMC_DRVSEL(3)); + mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN, + CLKMGR_PERPLL_EN_SDMMCCLK); +} diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c new file mode 100644 index 0000000..0b908cf --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "agilex_pinmux.h" +#include "socfpga_system_manager.h" + +const uint32_t sysmgr_pinmux_array_sel[] = { + 0x00000000, 0x00000001, /* usb */ + 0x00000004, 0x00000001, + 0x00000008, 0x00000001, + 0x0000000c, 0x00000001, + 0x00000010, 0x00000001, + 0x00000014, 0x00000001, + 0x00000018, 0x00000001, + 0x0000001c, 0x00000001, + 0x00000020, 0x00000001, + 0x00000024, 0x00000001, + 0x00000028, 0x00000001, + 0x0000002c, 0x00000001, + 0x00000030, 0x00000000, /* emac0 */ + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x0000004c, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x00000000, + 0x0000005c, 0x00000000, + 0x00000060, 0x00000008, /* gpio1 */ + 0x00000064, 0x00000008, + 0x00000068, 0x00000005, /* uart0 tx */ + 0x0000006c, 0x00000005, /* uart 0 rx */ + 0x00000070, 0x00000008, /* gpio */ + 0x00000074, 0x00000008, + 0x00000078, 0x00000004, /* i2c1 */ + 0x0000007c, 0x00000004, + 0x00000080, 0x00000007, /* jtag */ + 0x00000084, 0x00000007, + 0x00000088, 0x00000007, + 0x0000008c, 0x00000007, + 0x00000090, 0x00000001, /* sdmmc data0 */ + 0x00000094, 0x00000001, + 0x00000098, 0x00000001, + 0x0000009c, 0x00000001, + 0x00000100, 0x00000001, + 0x00000104, 0x00000001, /* sdmmc.data3 */ + 0x00000108, 0x00000008, /* loan */ + 0x0000010c, 0x00000008, /* gpio */ + 0x00000110, 0x00000008, + 0x00000114, 0x00000008, /* gpio1.io21 */ + 0x00000118, 0x00000005, /* mdio0.mdio */ + 0x0000011c, 0x00000005 /* mdio0.mdc */ +}; + +const uint32_t sysmgr_pinmux_array_ctrl[] = { + 0x00000000, 0x00502c38, /* Q1_1 */ + 0x00000004, 0x00102c38, + 0x00000008, 0x00502c38, + 0x0000000c, 0x00502c38, + 0x00000010, 0x00502c38, + 0x00000014, 0x00502c38, + 0x00000018, 0x00502c38, + 0x0000001c, 0x00502c38, + 0x00000020, 0x00502c38, + 0x00000024, 0x00502c38, + 0x00000028, 0x00502c38, + 0x0000002c, 0x00502c38, + 0x00000030, 0x00102c38, /* Q2_1 */ + 0x00000034, 0x00102c38, + 0x00000038, 0x00502c38, + 0x0000003c, 0x00502c38, + 0x00000040, 0x00102c38, + 0x00000044, 0x00102c38, + 0x00000048, 0x00502c38, + 0x0000004c, 0x00502c38, + 0x00000050, 0x00102c38, + 0x00000054, 0x00102c38, + 0x00000058, 0x00502c38, + 0x0000005c, 0x00502c38, + 0x00000060, 0x00502c38, /* Q3_1 */ + 0x00000064, 0x00502c38, + 0x00000068, 0x00102c38, + 0x0000006c, 0x00502c38, + 0x000000d0, 0x00502c38, + 0x000000d4, 0x00502c38, + 0x000000d8, 0x00542c38, + 0x000000dc, 0x00542c38, + 0x000000e0, 0x00502c38, + 0x000000e4, 0x00502c38, + 0x000000e8, 0x00102c38, + 0x000000ec, 0x00502c38, + 0x000000f0, 0x00502c38, /* Q4_1 */ + 0x000000f4, 0x00502c38, + 0x000000f8, 0x00102c38, + 0x000000fc, 0x00502c38, + 0x00000100, 0x00502c38, + 0x00000104, 0x00502c38, + 0x00000108, 0x00102c38, + 0x0000010c, 0x00502c38, + 0x00000110, 0x00502c38, + 0x00000114, 0x00502c38, + 0x00000118, 0x00542c38, + 0x0000011c, 0x00102c38 +}; + +const uint32_t sysmgr_pinmux_array_fpga[] = { + 0x00000000, 0x00000000, + 0x00000004, 0x00000000, + 0x00000008, 0x00000000, + 0x0000000c, 0x00000000, + 0x00000010, 0x00000000, + 0x00000014, 0x00000000, + 0x00000018, 0x00000000, + 0x0000001c, 0x00000000, + 0x00000020, 0x00000000, + 0x00000028, 0x00000000, + 0x0000002c, 0x00000000, + 0x00000030, 0x00000000, + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x0000002a +}; + +const uint32_t sysmgr_pinmux_array_iodelay[] = { + 0x00000000, 0x00000000, + 0x00000004, 0x00000000, + 0x00000008, 0x00000000, + 0x0000000c, 0x00000000, + 0x00000010, 0x00000000, + 0x00000014, 0x00000000, + 0x00000018, 0x00000000, + 0x0000001c, 0x00000000, + 0x00000020, 0x00000000, + 0x00000024, 0x00000000, + 0x00000028, 0x00000000, + 0x0000002c, 0x00000000, + 0x00000030, 0x00000000, + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x0000004c, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x00000000, + 0x0000005c, 0x00000000, + 0x00000060, 0x00000000, + 0x00000064, 0x00000000, + 0x00000068, 0x00000000, + 0x0000006c, 0x00000000, + 0x00000070, 0x00000000, + 0x00000074, 0x00000000, + 0x00000078, 0x00000000, + 0x0000007c, 0x00000000, + 0x00000080, 0x00000000, + 0x00000084, 0x00000000, + 0x00000088, 0x00000000, + 0x0000008c, 0x00000000, + 0x00000090, 0x00000000, + 0x00000094, 0x00000000, + 0x00000098, 0x00000000, + 0x0000009c, 0x00000000, + 0x00000100, 0x00000000, + 0x00000104, 0x00000000, + 0x00000108, 0x00000000, + 0x0000010c, 0x00000000, + 0x00000110, 0x00000000, + 0x00000114, 0x00000000, + 0x00000118, 0x00000000, + 0x0000011c, 0x00000000 +}; + +void config_fpgaintf_mod(void) +{ + mmio_write_32(SOCFPGA_SYSMGR(FPGAINTF_EN_2), 1<<8); +} + + +void config_pinmux(handoff *hoff_ptr) +{ + unsigned int i; + + for (i = 0; i < 96; i += 2) { + mmio_write_32(AGX_PINMUX_PIN0SEL + + hoff_ptr->pinmux_sel_array[i], + hoff_ptr->pinmux_sel_array[i+1]); + } + + for (i = 0; i < 96; i += 2) { + mmio_write_32(AGX_PINMUX_IO0CTRL + + hoff_ptr->pinmux_io_array[i], + hoff_ptr->pinmux_io_array[i+1]); + } + + for (i = 0; i < 42; i += 2) { + mmio_write_32(AGX_PINMUX_PINMUX_EMAC0_USEFPGA + + hoff_ptr->pinmux_fpga_array[i], + hoff_ptr->pinmux_fpga_array[i+1]); + } + + for (i = 0; i < 96; i += 2) { + mmio_write_32(AGX_PINMUX_IO0_DELAY + + hoff_ptr->pinmux_iodelay_array[i], + hoff_ptr->pinmux_iodelay_array[i+1]); + } + + config_fpgaintf_mod(); +} + diff --git a/arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..5cb9b69 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl platform_is_primary_cpu + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + .globl plat_secondary_cpus_bl31_entry + + .globl plat_get_my_entrypoint + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Wait until the it gets reset signal from rstmgr gets populated */ +poll_mailbox: + wfi + mov_imm x0, PLAT_SEC_ENTRY + ldr x1, [x0] + mov_imm x2, PLAT_CPUID_RELEASE + ldr x3, [x2] + mrs x4, mpidr_el1 + and x4, x4, #0xff + cmp x3, x4 + b.ne poll_mailbox + br x1 +endfunc plat_secondary_cold_boot_setup + +func platform_is_primary_cpu + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc platform_is_primary_cpu + +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + b platform_is_primary_cpu +endfunc plat_is_my_cpu_primary + +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos + +func warm_reset_req + str xzr, [x4] + bl plat_is_my_cpu_primary + cbz x0, cpu_in_wfi + mov_imm x1, PLAT_SEC_ENTRY + str xzr, [x1] + mrs x1, rmr_el3 + orr x1, x1, #0x02 + msr rmr_el3, x1 + isb + dsb sy +cpu_in_wfi: + wfi + b cpu_in_wfi +endfunc warm_reset_req + +func plat_get_my_entrypoint + ldr x4, =L2_RESET_DONE_REG + ldr x5, [x4] + ldr x1, =L2_RESET_DONE_STATUS + cmp x1, x5 + b.eq warm_reset_req + mov_imm x1, PLAT_SEC_ENTRY + ldr x0, [x1] + ret +endfunc plat_get_my_entrypoint + + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, PLAT_UART0_BASE + mov_imm x1, PLAT_UART_CLOCK + mov_imm x2, PLAT_BAUDRATE + b console_16550_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(void) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, PLAT_UART0_BASE + b console_16550_core_putc +endfunc plat_crash_console_putc + +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_16550_core_flush +endfunc plat_crash_console_flush + + + /* -------------------------------------------------------- + * void platform_mem_init (void); + * + * Any memory init, relocation to be done before the + * platform boots. Called very early in the boot process. + * -------------------------------------------------------- + */ +func platform_mem_init + mov x0, #0 + ret +endfunc platform_mem_init + +func plat_secondary_cpus_bl31_entry + el3_entrypoint_common \ + _init_sctlr=0 \ + _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ + _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ + _init_memory=1 \ + _init_c_runtime=1 \ + _exception_vectors=runtime_exceptions \ + _pie_fixup_size=BL31_LIMIT - BL31_BASE +endfunc plat_secondary_cpus_bl31_entry diff --git a/arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c b/arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c new file mode 100644 index 0000000..b79a63c --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "socfpga_private.h" + + +unsigned int plat_get_syscnt_freq2(void) +{ + return PLAT_SYS_COUNTER_FREQ_IN_TICKS; +} + +unsigned long socfpga_get_ns_image_entrypoint(void) +{ + return PLAT_NS_IMAGE_OFFSET; +} + +/****************************************************************************** + * Gets SPSR for BL32 entry + *****************************************************************************/ +uint32_t socfpga_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/****************************************************************************** + * Gets SPSR for BL33 entry + *****************************************************************************/ +uint32_t socfpga_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + diff --git a/arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c b/arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c new file mode 100644 index 0000000..4f75665 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .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.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + 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 /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, +#endif /* EL3_PAYLOAD_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.pc = PLAT_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_NS_IMAGE_OFFSET, + .image_info.image_max_size = + 0x0 + 0x40000000 - PLAT_NS_IMAGE_OFFSET, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c b/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c new file mode 100644 index 0000000..d4716cf --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "ncore_ccu.h" + +uint32_t poll_active_bit(uint32_t dir); + +static coh_ss_id_t subsystem_id; + + +void get_subsystem_id(void) +{ + uint32_t snoop_filter, directory, coh_agent; + + snoop_filter = CSIDR_NUM_SF(mmio_read_32(NCORE_CCU_CSR(NCORE_CSIDR))); + directory = CSUIDR_NUM_DIR(mmio_read_32(NCORE_CCU_CSR(NCORE_CSUIDR))); + coh_agent = CSUIDR_NUM_CAI(mmio_read_32(NCORE_CCU_CSR(NCORE_CSUIDR))); + + subsystem_id.num_snoop_filter = snoop_filter + 1; + subsystem_id.num_directory = directory; + subsystem_id.num_coh_agent = coh_agent; +} + +uint32_t directory_init(void) +{ + uint32_t dir_sf_mtn, dir_sf_en; + uint32_t dir, sf, ret; + + for (dir = 0; dir < subsystem_id.num_directory; dir++) { + for (sf = 0; sf < subsystem_id.num_snoop_filter; sf++) { + dir_sf_mtn = DIRECTORY_UNIT(dir, NCORE_DIRUSFMCR); + dir_sf_en = DIRECTORY_UNIT(dir, NCORE_DIRUSFER); + + /* Initialize All Entries */ + mmio_write_32(dir_sf_mtn, SNOOP_FILTER_ID(dir)); + + /* Poll Active Bit */ + ret = poll_active_bit(dir); + if (ret != 0) { + ERROR("Timeout during active bit polling"); + return -ETIMEDOUT; + } + + /* Snoope Filter Enable */ + mmio_setbits_32(dir_sf_en, BIT(sf)); + } + } + + return 0; +} + +uint32_t coherent_agent_intfc_init(void) +{ + uint32_t dir, ca, ca_id, ca_type, ca_snoop_en; + + for (dir = 0; dir < subsystem_id.num_directory; dir++) { + for (ca = 0; ca < subsystem_id.num_coh_agent; ca++) { + ca_snoop_en = DIRECTORY_UNIT(ca, NCORE_DIRUCASER0); + ca_id = mmio_read_32(COH_AGENT_UNIT(ca, NCORE_CAIUIDR)); + + /* Coh Agent Snoop Enable */ + if (CACHING_AGENT_BIT(ca_id)) + mmio_write_32(ca_snoop_en, BIT(ca)); + + /* Coh Agent Snoop DVM Enable */ + ca_type = CACHING_AGENT_TYPE(ca_id); + if (ca_type == ACE_W_DVM || ca_type == ACE_L_W_DVM) + mmio_write_32(NCORE_CCU_CSR(NCORE_CSADSER0), + BIT(ca)); + } + } + + return 0; +} + +uint32_t poll_active_bit(uint32_t dir) +{ + uint32_t timeout = 80000; + uint32_t poll_dir = DIRECTORY_UNIT(dir, NCORE_DIRUSFMAR); + + while (timeout > 0) { + if (mmio_read_32(poll_dir) == 0) + return 0; + timeout--; + } + + return -1; +} + +void bypass_ocram_firewall(void) +{ + mmio_clrbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF1), + OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK); + mmio_clrbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF2), + OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK); + mmio_clrbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF3), + OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK); + mmio_clrbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF4), + OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK); +} + +void ncore_enable_ocram_firewall(void) +{ + mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF1), + OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK); + mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF2), + OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK); + mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF3), + OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK); + mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF4), + OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK); +} +uint32_t init_ncore_ccu(void) +{ + uint32_t status; + + get_subsystem_id(); + status = directory_init(); + status = coherent_agent_intfc_init(); + bypass_ocram_firewall(); + + return status; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h b/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h new file mode 100644 index 0000000..3f662ff --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NCORE_CCU_H +#define NCORE_CCU_H + + +#define NCORE_CCU_OFFSET 0xf7000000 + + +/* Coherent Sub-System Address Map */ +#define NCORE_CAIU_OFFSET 0x00000 +#define NCORE_CAIU_SIZE 0x01000 + +#define NCORE_NCBU_OFFSET 0x60000 +#define NCORE_NCBU_SIZE 0x01000 + +#define NCORE_DIRU_OFFSET 0x80000 +#define NCORE_DIRU_SIZE 0x01000 + +#define NCORE_CMIU_OFFSET 0xc0000 +#define NCORE_CMIU_SIZE 0x01000 + +#define NCORE_CSR_OFFSET 0xff000 +#define NCORE_CSADSERO 0x00040 +#define NCORE_CSUIDR 0x00ff8 +#define NCORE_CSIDR 0x00ffc + +/* Directory Unit Register Map */ +#define NCORE_DIRUSFER 0x00010 +#define NCORE_DIRUMRHER 0x00070 +#define NCORE_DIRUSFMCR 0x00080 +#define NCORE_DIRUSFMAR 0x00084 + +/* Coherent Agent Interface Unit Register Map */ +#define NCORE_CAIUIDR 0x00ffc + +/* Snoop Enable Register */ +#define NCORE_DIRUCASER0 0x00040 +#define NCORE_DIRUCASER1 0x00044 +#define NCORE_DIRUCASER2 0x00048 +#define NCORE_DIRUCASER3 0x0004c + +#define NCORE_CSADSER0 0x00040 +#define NCORE_CSADSER1 0x00044 +#define NCORE_CSADSER2 0x00048 +#define NCORE_CSADSER3 0x0004c + +/* Protocols Definition */ +#define ACE_W_DVM 0 +#define ACE_L_W_DVM 1 +#define ACE_WO_DVM 2 +#define ACE_L_WO_DVM 3 + +/* Bypass OC Ram Firewall */ +#define NCORE_FW_OCRAM_BLK_BASE 0x100200 +#define NCORE_FW_OCRAM_BLK_CGF1 0x04 +#define NCORE_FW_OCRAM_BLK_CGF2 0x08 +#define NCORE_FW_OCRAM_BLK_CGF3 0x0c +#define NCORE_FW_OCRAM_BLK_CGF4 0x10 + +#define OCRAM_PRIVILEGED_MASK BIT(29) +#define OCRAM_SECURE_MASK BIT(30) + +/* Macros */ +#define NCORE_CCU_REG(base) (NCORE_CCU_OFFSET + (base)) +#define NCORE_CCU_CSR(reg) (NCORE_CCU_REG(NCORE_CSR_OFFSET)\ + + (reg)) +#define NCORE_CCU_DIR(reg) (NCORE_CCU_REG(NCORE_DIRU_OFFSET)\ + + (reg)) +#define NCORE_CCU_CAI(reg) (NCORE_CCU_REG(NCORE_CAIU_OFFSET)\ + + (reg)) + +#define DIRECTORY_UNIT(x, reg) (NCORE_CCU_DIR(reg)\ + + NCORE_DIRU_SIZE * (x)) +#define COH_AGENT_UNIT(x, reg) (NCORE_CCU_CAI(reg)\ + + NCORE_CAIU_SIZE * (x)) + +#define COH_CPU0_BYPASS_REG(reg) (NCORE_CCU_REG(NCORE_FW_OCRAM_BLK_BASE)\ + + (reg)) + +#define CSUIDR_NUM_CMI(x) (((x) & 0x3f000000) >> 24) +#define CSUIDR_NUM_DIR(x) (((x) & 0x003f0000) >> 16) +#define CSUIDR_NUM_NCB(x) (((x) & 0x00003f00) >> 8) +#define CSUIDR_NUM_CAI(x) (((x) & 0x0000007f) >> 0) + +#define CSIDR_NUM_SF(x) (((x) & 0x007c0000) >> 18) + +#define SNOOP_FILTER_ID(x) (((x) << 16)) + +#define CACHING_AGENT_BIT(x) (((x) & 0x08000) >> 15) +#define CACHING_AGENT_TYPE(x) (((x) & 0xf0000) >> 16) + + +typedef struct coh_ss_id { + uint8_t num_coh_mem; + uint8_t num_directory; + uint8_t num_non_coh_bridge; + uint8_t num_coh_agent; + uint8_t num_snoop_filter; +} coh_ss_id_t; + +uint32_t init_ncore_ccu(void); +void ncore_enable_ocram_firewall(void); + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c b/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c new file mode 100644 index 0000000..cecf560 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c @@ -0,0 +1,822 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "cadence_qspi.h" + +#define LESS(a, b) (((a) < (b)) ? (a) : (b)) +#define MORE(a, b) (((a) > (b)) ? (a) : (b)) + + +uint32_t qspi_device_size; +int cad_qspi_cs; + +int cad_qspi_idle(void) +{ + return (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG) + & CAD_QSPI_CFG_IDLE) >> 31; +} + +int cad_qspi_set_baudrate_div(uint32_t div) +{ + if (div > 0xf) + return CAD_INVALID; + + mmio_clrsetbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, + ~CAD_QSPI_CFG_BAUDDIV_MSK, + CAD_QSPI_CFG_BAUDDIV(div)); + + return 0; +} + +int cad_qspi_configure_dev_size(uint32_t addr_bytes, + uint32_t bytes_per_dev, uint32_t bytes_per_block) +{ + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVSZ, + CAD_QSPI_DEVSZ_ADDR_BYTES(addr_bytes) | + CAD_QSPI_DEVSZ_BYTES_PER_PAGE(bytes_per_dev) | + CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(bytes_per_block)); + return 0; +} + +int cad_qspi_set_read_config(uint32_t opcode, uint32_t instr_type, + uint32_t addr_type, uint32_t data_type, + uint32_t mode_bit, uint32_t dummy_clk_cycle) +{ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVRD, + CAD_QSPI_DEV_OPCODE(opcode) | + CAD_QSPI_DEV_INST_TYPE(instr_type) | + CAD_QSPI_DEV_ADDR_TYPE(addr_type) | + CAD_QSPI_DEV_DATA_TYPE(data_type) | + CAD_QSPI_DEV_MODE_BIT(mode_bit) | + CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle)); + + return 0; +} + +int cad_qspi_set_write_config(uint32_t opcode, uint32_t addr_type, + uint32_t data_type, uint32_t dummy_clk_cycle) +{ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVWR, + CAD_QSPI_DEV_OPCODE(opcode) | + CAD_QSPI_DEV_ADDR_TYPE(addr_type) | + CAD_QSPI_DEV_DATA_TYPE(data_type) | + CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle)); + + return 0; +} + +int cad_qspi_timing_config(uint32_t clkphase, uint32_t clkpol, uint32_t csda, + uint32_t csdads, uint32_t cseot, uint32_t cssot, + uint32_t rddatacap) +{ + uint32_t cfg = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG); + + cfg &= CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK & + CAD_QSPI_CFG_SELCLKPOL_CLR_MSK; + cfg |= CAD_QSPI_SELCLKPHASE(clkphase) | CAD_QSPI_SELCLKPOL(clkpol); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, cfg); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DELAY, + CAD_QSPI_DELAY_CSSOT(cssot) | CAD_QSPI_DELAY_CSEOT(cseot) | + CAD_QSPI_DELAY_CSDADS(csdads) | CAD_QSPI_DELAY_CSDA(csda)); + + return 0; +} + +int cad_qspi_stig_cmd_helper(int cs, uint32_t cmd) +{ + uint32_t count = 0; + + /* chip select */ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, + (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG) + & CAD_QSPI_CFG_CS_MSK) | CAD_QSPI_CFG_CS(cs)); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD, cmd); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD, + cmd | CAD_QSPI_FLASHCMD_EXECUTE); + + do { + uint32_t reg = mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_FLASHCMD); + if (!(reg & CAD_QSPI_FLASHCMD_EXECUTE_STAT)) + break; + count++; + } while (count < CAD_QSPI_COMMAND_TIMEOUT); + + if (count >= CAD_QSPI_COMMAND_TIMEOUT) { + ERROR("Error sending QSPI command %x, timed out\n", + cmd); + return CAD_QSPI_ERROR; + } + + return 0; +} + +int cad_qspi_stig_cmd(uint32_t opcode, uint32_t dummy) +{ + if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { + ERROR("Faulty dummy bytes\n"); + return -1; + } + + return cad_qspi_stig_cmd_helper(cad_qspi_cs, + CAD_QSPI_FLASHCMD_OPCODE(opcode) | + CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(dummy)); +} + +int cad_qspi_stig_read_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes, + uint32_t *output) +{ + if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { + ERROR("Faulty dummy byes\n"); + return -1; + } + + if ((num_bytes > 8) || (num_bytes == 0)) + return -1; + + uint32_t cmd = + CAD_QSPI_FLASHCMD_OPCODE(opcode) | + CAD_QSPI_FLASHCMD_ENRDDATA(1) | + CAD_QSPI_FLASHCMD_NUMRDDATABYTES(num_bytes - 1) | + CAD_QSPI_FLASHCMD_ENCMDADDR(0) | + CAD_QSPI_FLASHCMD_ENMODEBIT(0) | + CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) | + CAD_QSPI_FLASHCMD_ENWRDATA(0) | + CAD_QSPI_FLASHCMD_NUMWRDATABYTES(0) | + CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy); + + if (cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd)) { + ERROR("failed to send stig cmd\n"); + return -1; + } + + output[0] = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_RDDATA0); + + if (num_bytes > 4) { + output[1] = mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_FLASHCMD_RDDATA1); + } + + return 0; +} + +int cad_qspi_stig_wr_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes, + uint32_t *input) +{ + if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { + ERROR("Faulty dummy byes\n"); + return -1; + } + + if ((num_bytes > 8) || (num_bytes == 0)) + return -1; + + uint32_t cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) | + CAD_QSPI_FLASHCMD_ENRDDATA(0) | + CAD_QSPI_FLASHCMD_NUMRDDATABYTES(0) | + CAD_QSPI_FLASHCMD_ENCMDADDR(0) | + CAD_QSPI_FLASHCMD_ENMODEBIT(0) | + CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) | + CAD_QSPI_FLASHCMD_ENWRDATA(1) | + CAD_QSPI_FLASHCMD_NUMWRDATABYTES(num_bytes - 1) | + CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA0, input[0]); + + if (num_bytes > 4) + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA1, + input[1]); + + return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd); +} + +int cad_qspi_stig_addr_cmd(uint32_t opcode, uint32_t dummy, uint32_t addr) +{ + uint32_t cmd; + + if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) + return -1; + + cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) | + CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy) | + CAD_QSPI_FLASHCMD_ENCMDADDR(1) | + CAD_QSPI_FLASHCMD_NUMADDRBYTES(2); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_ADDR, addr); + + return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd); +} + +int cad_qspi_device_bank_select(uint32_t bank) +{ + int status = 0; + + status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); + if (status != 0) + return status; + + status = cad_qspi_stig_wr_cmd(CAD_QSPI_STIG_OPCODE_WREN_EXT_REG, + 0, 1, &bank); + if (status != 0) + return status; + + return cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WRDIS, 0); +} + +int cad_qspi_device_status(uint32_t *status) +{ + return cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDSR, 0, 1, status); +} + +#if CAD_QSPI_MICRON_N25Q_SUPPORT +int cad_qspi_n25q_enable(void) +{ + cad_qspi_set_read_config(QSPI_FAST_READ, CAD_QSPI_INST_SINGLE, + CAD_QSPI_ADDR_FASTREAD, CAT_QSPI_ADDR_SINGLE_IO, 1, + 0); + cad_qspi_set_write_config(QSPI_WRITE, 0, 0, 0); + + return 0; +} + +int cad_qspi_n25q_wait_for_program_and_erase(int program_only) +{ + uint32_t status, flag_sr; + int count = 0; + + while (count < CAD_QSPI_COMMAND_TIMEOUT) { + status = cad_qspi_device_status(&status); + if (status != 0) { + ERROR("Error getting device status\n"); + return -1; + } + if (!CAD_QSPI_STIG_SR_BUSY(status)) + break; + count++; + } + + if (count >= CAD_QSPI_COMMAND_TIMEOUT) { + ERROR("Timed out waiting for idle\n"); + return -1; + } + + count = 0; + + while (count < CAD_QSPI_COMMAND_TIMEOUT) { + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDFLGSR, + 0, 1, &flag_sr); + if (status != 0) { + ERROR("Error waiting program and erase.\n"); + return status; + } + + if ((program_only && + CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(flag_sr)) || + (!program_only && + CAD_QSPI_STIG_FLAGSR_ERASEREADY(flag_sr))) + break; + } + + if (count >= CAD_QSPI_COMMAND_TIMEOUT) + ERROR("Timed out waiting for program and erase\n"); + + if ((program_only && CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(flag_sr)) || + (!program_only && + CAD_QSPI_STIG_FLAGSR_ERASEERROR(flag_sr))) { + ERROR("Error programming/erasing flash\n"); + cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_CLFSR, 0); + return -1; + } + + return 0; +} +#endif + +int cad_qspi_indirect_read_start_bank(uint32_t flash_addr, uint32_t num_bytes) +{ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDSTADDR, flash_addr); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDCNT, num_bytes); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRD, + CAD_QSPI_INDRD_START | + CAD_QSPI_INDRD_IND_OPS_DONE); + + return 0; +} + + +int cad_qspi_indirect_write_start_bank(uint32_t flash_addr, + uint32_t num_bytes) +{ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRSTADDR, flash_addr); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRCNT, num_bytes); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWR, + CAD_QSPI_INDWR_START | + CAD_QSPI_INDWR_INDDONE); + + return 0; +} + +int cad_qspi_indirect_write_finish(void) +{ +#if CAD_QSPI_MICRON_N25Q_SUPPORT + return cad_qspi_n25q_wait_for_program_and_erase(1); +#else + return 0; +#endif + +} + +int cad_qspi_enable(void) +{ + int status; + + mmio_setbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, CAD_QSPI_CFG_ENABLE); + +#if CAD_QSPI_MICRON_N25Q_SUPPORT + status = cad_qspi_n25q_enable(); + if (status != 0) + return status; +#endif + return 0; +} + +int cad_qspi_enable_subsector_bank(uint32_t addr) +{ + int status = 0; + + status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); + if (status != 0) + return status; + + status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE, 0, + addr); + if (status != 0) + return status; + +#if CAD_QSPI_MICRON_N25Q_SUPPORT + status = cad_qspi_n25q_wait_for_program_and_erase(0); +#endif + return status; +} + +int cad_qspi_erase_subsector(uint32_t addr) +{ + int status = 0; + + status = cad_qspi_device_bank_select(addr >> 24); + if (status != 0) + return status; + + return cad_qspi_enable_subsector_bank(addr); +} + +int cad_qspi_erase_sector(uint32_t addr) +{ + int status = 0; + + status = cad_qspi_device_bank_select(addr >> 24); + if (status != 0) + return status; + + status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); + if (status != 0) + return status; + + status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SEC_ERASE, 0, + addr); + if (status != 0) + return status; + +#if CAD_QSPI_MICRON_N25Q_SUPPORT + status = cad_qspi_n25q_wait_for_program_and_erase(0); +#endif + return status; +} + +void cad_qspi_calibration(uint32_t dev_clk, uint32_t qspi_clk_mhz) +{ + int status; + uint32_t dev_sclk_mhz = 27; /*min value to get biggest 0xF div factor*/ + uint32_t data_cap_delay; + uint32_t sample_rdid; + uint32_t rdid; + uint32_t div_actual; + uint32_t div_bits; + int first_pass, last_pass; + + /*1. Set divider to bigger value (slowest SCLK) + *2. RDID and save the value + */ + div_actual = (qspi_clk_mhz + (dev_sclk_mhz - 1)) / dev_sclk_mhz; + div_bits = (((div_actual + 1) / 2) - 1); + status = cad_qspi_set_baudrate_div(0xf); + + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, + 0, 3, &sample_rdid); + if (status != 0) + return; + + /*3. Set divider to the intended frequency + *4. Set the read delay = 0 + *5. RDID and check whether the value is same as item 2 + *6. Increase read delay and compared the value against item 2 + *7. Find the range of read delay that have same as + * item 2 and divide it to 2 + */ + div_actual = (qspi_clk_mhz + (dev_clk - 1)) / dev_clk; + div_bits = (((div_actual + 1) / 2) - 1); + status = cad_qspi_set_baudrate_div(div_bits); + if (status != 0) + return; + + data_cap_delay = 0; + first_pass = -1; + last_pass = -1; + + do { + if (status != 0) + break; + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, + 3, &rdid); + if (status != 0) + break; + if (rdid == sample_rdid) { + if (first_pass == -1) + first_pass = data_cap_delay; + else + last_pass = data_cap_delay; + } + + data_cap_delay++; + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP, + CAD_QSPI_RDDATACAP_BYP(1) | + CAD_QSPI_RDDATACAP_DELAY(data_cap_delay)); + + } while (data_cap_delay < 0x10); + + if (first_pass > 0) { + int diff = first_pass - last_pass; + + data_cap_delay = first_pass + diff / 2; + } + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP, + CAD_QSPI_RDDATACAP_BYP(1) | + CAD_QSPI_RDDATACAP_DELAY(data_cap_delay)); + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3, &rdid); + + if (status != 0) + return; +} + +int cad_qspi_int_disable(uint32_t mask) +{ + if (cad_qspi_idle() == 0) + return -1; + + if ((CAD_QSPI_INT_STATUS_ALL & mask) == 0) + return -1; + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_IRQMSK, mask); + return 0; +} + +void cad_qspi_set_chip_select(int cs) +{ + cad_qspi_cs = cs; +} + +int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase, + uint32_t clk_pol, uint32_t csda, uint32_t csdads, + uint32_t cseot, uint32_t cssot, uint32_t rddatacap) +{ + int status = 0; + uint32_t qspi_desired_clk_freq; + uint32_t rdid = 0; + uint32_t cap_code; + + INFO("Initializing Qspi\n"); + + if (cad_qspi_idle() == 0) { + ERROR("device not idle\n"); + return -1; + } + + + status = cad_qspi_timing_config(clk_phase, clk_pol, csda, csdads, + cseot, cssot, rddatacap); + + if (status != 0) { + ERROR("config set timing failure\n"); + return status; + } + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_REMAPADDR, + CAD_QSPI_REMAPADDR_VALUE_SET(0)); + + status = cad_qspi_int_disable(CAD_QSPI_INT_STATUS_ALL); + if (status != 0) { + ERROR("failed disable\n"); + return status; + } + + cad_qspi_set_baudrate_div(0xf); + status = cad_qspi_enable(); + if (status != 0) { + ERROR("failed enable\n"); + return status; + } + + qspi_desired_clk_freq = 100; + cad_qspi_calibration(qspi_desired_clk_freq, 50000000); + + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3, + &rdid); + + if (status != 0) { + ERROR("Error reading RDID\n"); + return status; + } + + /* + * NOTE: The Size code seems to be a form of BCD (binary coded decimal). + * The first nibble is the 10's digit and the second nibble is the 1's + * digit in the number of bytes. + * + * Capacity ID samples: + * 0x15 : 16 Mb => 2 MiB => 1 << 21 ; BCD=15 + * 0x16 : 32 Mb => 4 MiB => 1 << 22 ; BCD=16 + * 0x17 : 64 Mb => 8 MiB => 1 << 23 ; BCD=17 + * 0x18 : 128 Mb => 16 MiB => 1 << 24 ; BCD=18 + * 0x19 : 256 Mb => 32 MiB => 1 << 25 ; BCD=19 + * 0x1a + * 0x1b + * 0x1c + * 0x1d + * 0x1e + * 0x1f + * 0x20 : 512 Mb => 64 MiB => 1 << 26 ; BCD=20 + * 0x21 : 1024 Mb => 128 MiB => 1 << 27 ; BCD=21 + */ + + cap_code = CAD_QSPI_STIG_RDID_CAPACITYID(rdid); + + if (!(((cap_code >> 4) > 0x9) || ((cap_code & 0xf) > 0x9))) { + uint32_t decoded_cap = ((cap_code >> 4) * 10) + + (cap_code & 0xf); + qspi_device_size = 1 << (decoded_cap + 6); + INFO("QSPI Capacity: %x\n\n", qspi_device_size); + + } else { + ERROR("Invalid CapacityID encountered: 0x%02x\n", + cap_code); + return -1; + } + + cad_qspi_configure_dev_size(INTEL_QSPI_ADDR_BYTES, + INTEL_QSPI_BYTES_PER_DEV, + INTEL_BYTES_PER_BLOCK); + + INFO("Flash size: %d Bytes\n", qspi_device_size); + + return status; +} + +int cad_qspi_indirect_page_bound_write(uint32_t offset, + uint8_t *buffer, uint32_t len) +{ + int status = 0, i; + uint32_t write_count, write_capacity, *write_data, space, + write_fill_level, sram_partition; + + status = cad_qspi_indirect_write_start_bank(offset, len); + if (status != 0) + return status; + + write_count = 0; + sram_partition = CAD_QSPI_SRAMPART_ADDR(mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_SRAMPART)); + write_capacity = (uint32_t) CAD_QSPI_SRAM_FIFO_ENTRY_COUNT - + sram_partition; + + while (write_count < len) { + write_fill_level = CAD_QSPI_SRAMFILL_INDWRPART( + mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_SRAMFILL)); + space = LESS(write_capacity - write_fill_level, + (len - write_count) / sizeof(uint32_t)); + write_data = (uint32_t *)(buffer + write_count); + for (i = 0; i < space; ++i) + mmio_write_32(CAD_QSPIDATA_OFST, *write_data++); + + write_count += space * sizeof(uint32_t); + } + return cad_qspi_indirect_write_finish(); +} + +int cad_qspi_read_bank(uint8_t *buffer, uint32_t offset, uint32_t size) +{ + int status; + uint32_t read_count = 0, *read_data; + int level = 1, count = 0, i; + + status = cad_qspi_indirect_read_start_bank(offset, size); + + if (status != 0) + return status; + + while (read_count < size) { + do { + level = CAD_QSPI_SRAMFILL_INDRDPART( + mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_SRAMFILL)); + read_data = (uint32_t *)(buffer + read_count); + for (i = 0; i < level; ++i) + *read_data++ = mmio_read_32(CAD_QSPIDATA_OFST); + + read_count += level * sizeof(uint32_t); + count++; + } while (level > 0); + } + + return 0; +} + +int cad_qspi_write_bank(uint32_t offset, uint8_t *buffer, uint32_t size) +{ + int status = 0; + uint32_t page_offset = offset & (CAD_QSPI_PAGE_SIZE - 1); + uint32_t write_size = LESS(size, CAD_QSPI_PAGE_SIZE - page_offset); + + while (size) { + status = cad_qspi_indirect_page_bound_write(offset, buffer, + write_size); + if (status != 0) + break; + + offset += write_size; + buffer += write_size; + size -= write_size; + write_size = LESS(size, CAD_QSPI_PAGE_SIZE); + } + return status; +} + +int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size) +{ + uint32_t bank_count, bank_addr, bank_offset, copy_len; + uint8_t *read_data; + int i, status; + + status = 0; + + if ((offset >= qspi_device_size) || + (offset + size - 1 >= qspi_device_size) || + (size == 0)) { + ERROR("Invalid read parameter\n"); + return -1; + } + + if (CAD_QSPI_INDRD_RD_STAT(mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_INDRD))) { + ERROR("Read in progress\n"); + return -1; + } + + /* + * bank_count : Number of bank(s) affected, including partial banks. + * bank_addr : Aligned address of the first bank, + * including partial bank. + * bank_ofst : The offset of the bank to read. + * Only used when reading the first bank. + */ + bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) - + CAD_QSPI_BANK_ADDR(offset) + 1; + bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK; + bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1); + + read_data = (uint8_t *)buffer; + + copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset); + + for (i = 0; i < bank_count; ++i) { + status = cad_qspi_device_bank_select(CAD_QSPI_BANK_ADDR( + bank_addr)); + if (status != 0) + break; + status = cad_qspi_read_bank(read_data, bank_offset, copy_len); + if (status != 0) + break; + + bank_addr += CAD_QSPI_BANK_SIZE; + read_data += copy_len; + size -= copy_len; + bank_offset = 0; + copy_len = LESS(size, CAD_QSPI_BANK_SIZE); + } + + return status; +} + +int cad_qspi_erase(uint32_t offset, uint32_t size) +{ + int status = 0; + uint32_t subsector_offset = offset & (CAD_QSPI_SUBSECTOR_SIZE - 1); + uint32_t erase_size = LESS(size, + CAD_QSPI_SUBSECTOR_SIZE - subsector_offset); + + while (size) { + status = cad_qspi_erase_subsector(offset); + if (status != 0) + break; + + offset += erase_size; + size -= erase_size; + erase_size = LESS(size, CAD_QSPI_SUBSECTOR_SIZE); + } + return status; +} + +int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size) +{ + int status, i; + uint32_t bank_count, bank_addr, bank_offset, copy_len; + uint8_t *write_data; + + status = 0; + + if ((offset >= qspi_device_size) || + (offset + size - 1 >= qspi_device_size) || + (size == 0)) { + return -2; + } + + if (CAD_QSPI_INDWR_RDSTAT(mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_INDWR))) { + ERROR("QSPI Error: Write in progress\n"); + return -1; + } + + bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) - + CAD_QSPI_BANK_ADDR(offset) + 1; + bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK; + bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1); + + write_data = buffer; + + copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset); + + for (i = 0; i < bank_count; ++i) { + status = cad_qspi_device_bank_select( + CAD_QSPI_BANK_ADDR(bank_addr)); + if (status != 0) + break; + + status = cad_qspi_write_bank(bank_offset, write_data, + copy_len); + if (status != 0) + break; + + bank_addr += CAD_QSPI_BANK_SIZE; + write_data += copy_len; + size -= copy_len; + bank_offset = 0; + + copy_len = LESS(size, CAD_QSPI_BANK_SIZE); + } + return status; +} + +int cad_qspi_update(void *Buffer, uint32_t offset, uint32_t size) +{ + int status = 0; + + status = cad_qspi_erase(offset, size); + if (status != 0) + return status; + + return cad_qspi_write(Buffer, offset, size); +} + +void cad_qspi_reset(void) +{ + cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_EN, 0); + cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_MEM, 0); +} + diff --git a/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h b/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h new file mode 100644 index 0000000..cfef585 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CAD_QSPI_H +#define CAD_QSPI_H + +#define CAD_QSPI_MICRON_N25Q_SUPPORT 1 + +#define CAD_QSPI_OFFSET 0xff8d2000 + +#define CAD_INVALID -1 +#define CAD_QSPI_ERROR -2 + +#define CAD_QSPI_ADDR_FASTREAD 0 +#define CAD_QSPI_ADDR_FASTREAD_DUAL_IO 1 +#define CAD_QSPI_ADDR_FASTREAD_QUAD_IO 2 +#define CAT_QSPI_ADDR_SINGLE_IO 0 +#define CAT_QSPI_ADDR_DUAL_IO 1 +#define CAT_QSPI_ADDR_QUAD_IO 2 + +#define CAD_QSPI_BANK_ADDR(x) ((x) >> 24) +#define CAD_QSPI_BANK_ADDR_MSK 0xff000000 + +#define CAD_QSPI_COMMAND_TIMEOUT 0x10000000 + +#define CAD_QSPI_CFG 0x0 +#define CAD_QSPI_CFG_BAUDDIV_MSK 0xff87ffff +#define CAD_QSPI_CFG_BAUDDIV(x) (((x) << 19) & 0x780000) +#define CAD_QSPI_CFG_CS_MSK ~0x3c00 +#define CAD_QSPI_CFG_CS(x) (((x) << 11)) +#define CAD_QSPI_CFG_ENABLE (1 << 0) +#define CAD_QSPI_CFG_ENDMA_CLR_MSK 0xffff7fff +#define CAD_QSPI_CFG_IDLE (1U << 31) +#define CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK 0xfffffffb +#define CAD_QSPI_CFG_SELCLKPOL_CLR_MSK 0xfffffffd + +#define CAD_QSPIDATA_OFST 0xff900000 + +#define CAD_QSPI_DELAY 0xc +#define CAD_QSPI_DELAY_CSSOT(x) (((x) & 0xff) << 0) +#define CAD_QSPI_DELAY_CSEOT(x) (((x) & 0xff) << 8) +#define CAD_QSPI_DELAY_CSDADS(x) (((x) & 0xff) << 16) +#define CAD_QSPI_DELAY_CSDA(x) (((x) & 0xff) << 24) + +#define CAD_QSPI_DEVSZ 0x14 +#define CAD_QSPI_DEVSZ_ADDR_BYTES(x) ((x) << 0) +#define CAD_QSPI_DEVSZ_BYTES_PER_PAGE(x) ((x) << 4) +#define CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(x) ((x) << 16) + +#define CAD_QSPI_DEVWR 0x8 +#define CAD_QSPI_DEVRD 0x4 +#define CAD_QSPI_DEV_OPCODE(x) (((x) & 0xff) << 0) +#define CAD_QSPI_DEV_INST_TYPE(x) (((x) & 0x03) << 8) +#define CAD_QSPI_DEV_ADDR_TYPE(x) (((x) & 0x03) << 12) +#define CAD_QSPI_DEV_DATA_TYPE(x) (((x) & 0x03) << 16) +#define CAD_QSPI_DEV_MODE_BIT(x) (((x) & 0x01) << 20) +#define CAD_QSPI_DEV_DUMMY_CLK_CYCLE(x) (((x) & 0x0f) << 24) + +#define CAD_QSPI_FLASHCMD 0x90 +#define CAD_QSPI_FLASHCMD_ADDR 0x94 +#define CAD_QSPI_FLASHCMD_EXECUTE 0x1 +#define CAD_QSPI_FLASHCMD_EXECUTE_STAT 0x2 +#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX 5 +#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(x) (((x) << 7) & 0x000f80) +#define CAD_QSPI_FLASHCMD_OPCODE(x) (((x) & 0xff) << 24) +#define CAD_QSPI_FLASHCMD_ENRDDATA(x) (((x) & 1) << 23) +#define CAD_QSPI_FLASHCMD_NUMRDDATABYTES(x) (((x) & 0xf) << 20) +#define CAD_QSPI_FLASHCMD_ENCMDADDR(x) (((x) & 1) << 19) +#define CAD_QSPI_FLASHCMD_ENMODEBIT(x) (((x) & 1) << 18) +#define CAD_QSPI_FLASHCMD_NUMADDRBYTES(x) (((x) & 0x3) << 16) +#define CAD_QSPI_FLASHCMD_ENWRDATA(x) (((x) & 1) << 15) +#define CAD_QSPI_FLASHCMD_NUMWRDATABYTES(x) (((x) & 0x7) << 12) +#define CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(x) (((x) & 0x1f) << 7) +#define CAD_QSPI_FLASHCMD_RDDATA0 0xa0 +#define CAD_QSPI_FLASHCMD_RDDATA1 0xa4 +#define CAD_QSPI_FLASHCMD_WRDATA0 0xa8 +#define CAD_QSPI_FLASHCMD_WRDATA1 0xac + +#define CAD_QSPI_RDDATACAP 0x10 +#define CAD_QSPI_RDDATACAP_BYP(x) (((x) & 1) << 0) +#define CAD_QSPI_RDDATACAP_DELAY(x) (((x) & 0xf) << 1) + +#define CAD_QSPI_REMAPADDR 0x24 +#define CAD_QSPI_REMAPADDR_VALUE_SET(x) (((x) & 0xffffffff) << 0) + +#define CAD_QSPI_SRAMPART 0x18 +#define CAD_QSPI_SRAMFILL 0x2c +#define CAD_QSPI_SRAMPART_ADDR(x) (((x) >> 0) & 0x3ff) +#define CAD_QSPI_SRAM_FIFO_ENTRY_COUNT (512 / sizeof(uint32_t)) +#define CAD_QSPI_SRAMFILL_INDWRPART(x) (((x) >> 16) & 0x00ffff) +#define CAD_QSPI_SRAMFILL_INDRDPART(x) (((x) >> 0) & 0x00ffff) + +#define CAD_QSPI_SELCLKPHASE(x) (((x) & 1) << 2) +#define CAD_QSPI_SELCLKPOL(x) (((x) & 1) << 1) + +#define CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(x) (((x) >> 7) & 1) +#define CAD_QSPI_STIG_FLAGSR_ERASEREADY(x) (((x) >> 7) & 1) +#define CAD_QSPI_STIG_FLAGSR_ERASEERROR(x) (((x) >> 5) & 1) +#define CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(x) (((x) >> 4) & 1) +#define CAD_QSPI_STIG_OPCODE_CLFSR 0x50 +#define CAD_QSPI_STIG_OPCODE_RDID 0x9f +#define CAD_QSPI_STIG_OPCODE_WRDIS 0x4 +#define CAD_QSPI_STIG_OPCODE_WREN 0x6 +#define CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE 0x20 +#define CAD_QSPI_STIG_OPCODE_SEC_ERASE 0xd8 +#define CAD_QSPI_STIG_OPCODE_WREN_EXT_REG 0xc5 +#define CAD_QSPI_STIG_OPCODE_DIE_ERASE 0xc4 +#define CAD_QSPI_STIG_OPCODE_BULK_ERASE 0xc7 +#define CAD_QSPI_STIG_OPCODE_RDSR 0x5 +#define CAD_QSPI_STIG_OPCODE_RDFLGSR 0x70 +#define CAD_QSPI_STIG_OPCODE_RESET_EN 0x66 +#define CAD_QSPI_STIG_OPCODE_RESET_MEM 0x99 +#define CAD_QSPI_STIG_RDID_CAPACITYID(x) (((x) >> 16) & 0xff) +#define CAD_QSPI_STIG_SR_BUSY(x) (((x) >> 0) & 1) + + +#define CAD_QSPI_INST_SINGLE 0 +#define CAD_QSPI_INST_DUAL 1 +#define CAD_QSPI_INST_QUAD 2 + +#define CAD_QSPI_INDRDSTADDR 0x68 +#define CAD_QSPI_INDRDCNT 0x6c +#define CAD_QSPI_INDRD 0x60 +#define CAD_QSPI_INDRD_RD_STAT(x) (((x) >> 2) & 1) +#define CAD_QSPI_INDRD_START 1 +#define CAD_QSPI_INDRD_IND_OPS_DONE 0x20 + +#define CAD_QSPI_INDWR 0x70 +#define CAD_QSPI_INDWR_RDSTAT(x) (((x) >> 2) & 1) +#define CAD_QSPI_INDWRSTADDR 0x78 +#define CAD_QSPI_INDWRCNT 0x7c +#define CAD_QSPI_INDWR 0x70 +#define CAD_QSPI_INDWR_START 0x1 +#define CAD_QSPI_INDWR_INDDONE 0x20 + +#define CAD_QSPI_INT_STATUS_ALL 0x0000ffff + +#define CAD_QSPI_N25Q_DIE_SIZE 0x02000000 +#define CAD_QSPI_BANK_SIZE 0x01000000 +#define CAD_QSPI_PAGE_SIZE 0x00000100 + +#define CAD_QSPI_IRQMSK 0x44 + +#define CAD_QSPI_SUBSECTOR_SIZE 0x1000 + +#define INTEL_QSPI_ADDR_BYTES 2 +#define INTEL_QSPI_BYTES_PER_DEV 256 +#define INTEL_BYTES_PER_BLOCK 16 + +#define QSPI_FAST_READ 0xb + +#define QSPI_WRITE 0x2 + +// QSPI CONFIGURATIONS + +#define QSPI_CONFIG_CPOL 1 +#define QSPI_CONFIG_CPHA 1 + +#define QSPI_CONFIG_CSSOT 0x14 +#define QSPI_CONFIG_CSEOT 0x14 +#define QSPI_CONFIG_CSDADS 0xff +#define QSPI_CONFIG_CSDA 0xc8 + +int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase, + uint32_t clk_pol, uint32_t csda, uint32_t csdads, + uint32_t cseot, uint32_t cssot, uint32_t rddatacap); +void cad_qspi_set_chip_select(int cs); +int cad_qspi_erase(uint32_t offset, uint32_t size); +int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size); +int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size); +int cad_qspi_update(void *buffer, uint32_t offset, uint32_t size); + +#endif + diff --git a/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c b/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c new file mode 100644 index 0000000..651189b --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "watchdog.h" + + +/* Reset watchdog timer */ +void watchdog_sw_rst(void) +{ + mmio_write_32(WDT_CRR, WDT_SW_RST); +} + +/* Print component information */ +void watchdog_info(void) +{ + INFO("Component Type : %x\r\n", mmio_read_32(WDT_COMP_VERSION)); + INFO("Component Version : %x\r\n", mmio_read_32(WDT_COMP_TYPE)); +} + +/* Check watchdog current status */ +void watchdog_status(void) +{ + if (mmio_read_32(WDT_CR) & 1) { + INFO("Watchdog Timer is currently enabled\n"); + INFO("Current Counter : 0x%x\r\n", mmio_read_32(WDT_CCVR)); + } else { + INFO("Watchdog Timer is currently disabled\n"); + } +} + +/* Initialize & enable watchdog */ +void watchdog_init(int watchdog_clk) +{ + uint8_t cycles_i = 0; + uint32_t wdt_cycles = WDT_MIN_CYCLES; + uint32_t top_init_cycles = WDT_PERIOD * watchdog_clk; + + while ((cycles_i < 15) && (wdt_cycles < top_init_cycles)) { + wdt_cycles = (wdt_cycles << 1); + cycles_i++; + } + + mmio_write_32(WDT_TORR, (cycles_i << 4) | cycles_i); + + mmio_write_32(WDT_CR, WDT_CR_RMOD|WDT_CR_EN); +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h b/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h new file mode 100644 index 0000000..2c72463 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CAD_WATCHDOG_H +#define CAD_WATCHDOG_H + +#define WDT_BASE (0xFFD00200) +#define WDT_REG_SIZE_OFFSET (0x4) +#define WDT_MIN_CYCLES (65536) +#define WDT_PERIOD (20) + +#define WDT_CR (WDT_BASE + 0x0) +#define WDT_TORR (WDT_BASE + 0x4) + +#define WDT_CRR (WDT_BASE + 0xC) + +#define WDT_CCVR (WDT_BASE + 0x8) +#define WDT_STAT (WDT_BASE + 0x10) +#define WDT_EOI (WDT_BASE + 0x14) + +#define WDT_COMP_PARAM_1 (WDT_BASE + 0xF4) +#define WDT_COMP_VERSION (WDT_BASE + 0xF8) +#define WDT_COMP_TYPE (WDT_BASE + 0XFC) + +#define WDT_CR_RMOD (0x0) +#define WDT_CR_EN (0x1) + +#define WDT_SW_RST (0x76) + + +void watchdog_init(int watchdog_clk); +void watchdog_info(void); +void watchdog_status(void); +void watchdog_sw_rst(void); + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S b/arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S new file mode 100644 index 0000000..43db9a2 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h b/arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h new file mode 100644 index 0000000..7859493 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include + +/* Platform Type */ +#define PLAT_SOCFPGA_STRATIX10 1 +#define PLAT_SOCFPGA_AGILEX 2 +#define PLAT_SOCFPGA_N5X 3 + +/* sysmgr.boot_scratch_cold4 & 5 used for CPU release address for SPL */ +#define PLAT_CPU_RELEASE_ADDR 0xffd12210 + +/* + * sysmgr.boot_scratch_cold6 & 7 (64bit) are used to indicate L2 reset + * is done and HPS should trigger warm reset via RMR_EL3. + */ +#define L2_RESET_DONE_REG 0xFFD12218 + +/* Magic word to indicate L2 reset is completed */ +#define L2_RESET_DONE_STATUS 0x1228E5E7 + +/* Define next boot image name and offset */ +#define PLAT_NS_IMAGE_OFFSET 0x10000000 +#define PLAT_HANDOFF_OFFSET 0xFFE3F000 + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/* SoCFPGA supports up to 124GB RAM */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 39) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 39) + + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ +#define PLAT_PRIMARY_CPU 0 +#define PLAT_SECONDARY_ENTRY_BASE 0x01f78bf0 + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x2000 + +/* PSCI related constant */ +#define PLAT_NUM_POWER_DOMAINS 5 +#define PLAT_MAX_PWR_LVL 1 +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) + +/* Interrupt related constant */ + +#define INTEL_SOCFPGA_IRQ_SEC_PHY_TIMER 29 + +#define INTEL_SOCFPGA_IRQ_SEC_SGI_0 8 +#define INTEL_SOCFPGA_IRQ_SEC_SGI_1 9 +#define INTEL_SOCFPGA_IRQ_SEC_SGI_2 10 +#define INTEL_SOCFPGA_IRQ_SEC_SGI_3 11 +#define INTEL_SOCFPGA_IRQ_SEC_SGI_4 12 +#define INTEL_SOCFPGA_IRQ_SEC_SGI_5 13 +#define INTEL_SOCFPGA_IRQ_SEC_SGI_6 14 +#define INTEL_SOCFPGA_IRQ_SEC_SGI_7 15 + +#define TSP_IRQ_SEC_PHY_TIMER INTEL_SOCFPGA_IRQ_SEC_PHY_TIMER +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1) +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +#define DRAM_BASE (0x0) +#define DRAM_SIZE (0x80000000) + +#define OCRAM_BASE (0xFFE00000) +#define OCRAM_SIZE (0x00040000) + +#define MEM64_BASE (0x0100000000) +#define MEM64_SIZE (0x1F00000000) + +#define DEVICE1_BASE (0x80000000) +#define DEVICE1_SIZE (0x60000000) + +#define DEVICE2_BASE (0xF7000000) +#define DEVICE2_SIZE (0x08E00000) + +#define DEVICE3_BASE (0xFFFC0000) +#define DEVICE3_SIZE (0x00008000) + +#define DEVICE4_BASE (0x2000000000) +#define DEVICE4_SIZE (0x0100000000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL3-1 debug size plus a + * little space for growth. + */ + + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define BL1_RO_BASE (0xffe00000) +#define BL1_RO_LIMIT (0xffe0f000) +#define BL1_RW_BASE (0xffe10000) +#define BL1_RW_LIMIT (0xffe1ffff) +#define BL1_RW_SIZE (0x14000) + +#define BL2_BASE (0xffe00000) +#define BL2_LIMIT (0xffe1b000) + +#define BL31_BASE (0x1000) +#define BL31_LIMIT (0x81000) + +#define BL_DATA_LIMIT PLAT_HANDOFF_OFFSET + +#define PLAT_CPUID_RELEASE (BL_DATA_LIMIT - 16) +#define PLAT_SEC_ENTRY (BL_DATA_LIMIT - 8) + +#define PLAT_SEC_WARM_ENTRY 0 + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define PLAT_GIC_BASE (0xFFFC0000) +#define PLAT_GICC_BASE (PLAT_GIC_BASE + 0x2000) +#define PLAT_GICD_BASE (PLAT_GIC_BASE + 0x1000) +#define PLAT_GICR_BASE 0 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define PLAT_UART0_BASE (0xFFC02000) +#define PLAT_UART1_BASE (0xFFC02100) + +#define CRASH_CONSOLE_BASE PLAT_UART0_BASE + +#ifndef SIMICS_BUILD +#define PLAT_BAUDRATE (115200) +#define PLAT_UART_CLOCK (100000000) + +#else +#define PLAT_BAUDRATE (4800) +#define PLAT_UART_CLOCK (76800) + +#endif + +/******************************************************************************* + * PHY related constants + ******************************************************************************/ + +#define EMAC0_PHY_MODE PHY_INTERFACE_MODE_RGMII +#define EMAC1_PHY_MODE PHY_INTERFACE_MODE_RGMII +#define EMAC2_PHY_MODE PHY_INTERFACE_MODE_RGMII + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define PLAT_SYS_COUNTER_FREQ_IN_TICKS (400000000) +#define PLAT_SYS_COUNTER_FREQ_IN_MHZ (400) + +#define PLAT_INTEL_SOCFPGA_GICD_BASE PLAT_GICD_BASE +#define PLAT_INTEL_SOCFPGA_GICC_BASE PLAT_GICC_BASE + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_PHY_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_0, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_1, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_2, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_3, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_4, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_5, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_6, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_7, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE) + +#define PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(grp) + +#define MAX_IO_HANDLES 4 +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 2 + +#ifndef __ASSEMBLER__ +struct socfpga_bl31_params { + 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; +}; +#endif + +#endif /* PLATFORM_DEF_H */ + diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h new file mode 100644 index 0000000..5b98006 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_EMAC_H +#define SOCFPGA_EMAC_H + +/* EMAC PHY Mode */ + +#define PHY_INTERFACE_MODE_GMII_MII 0 +#define PHY_INTERFACE_MODE_RGMII 1 +#define PHY_INTERFACE_MODE_RMII 2 +#define PHY_INTERFACE_MODE_RESET 3 + +/* Mask Definitions */ + +#define PHY_INTF_SEL_MSK 0x3 +#define FPGAINTF_EN_3_EMAC_MSK(x) (1 << (x * 8)) + +void socfpga_emac_init(void); + +#endif /* SOCFPGA_EMAC_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h new file mode 100644 index 0000000..ff10d36 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_FCS_H +#define SOCFPGA_FCS_H + +/* FCS Definitions */ + +#define FCS_RANDOM_WORD_SIZE 8U +#define FCS_PROV_DATA_WORD_SIZE 44U + +#define FCS_RANDOM_BYTE_SIZE (FCS_RANDOM_WORD_SIZE * 4U) +#define FCS_PROV_DATA_BYTE_SIZE (FCS_PROV_DATA_WORD_SIZE * 4U) + +#define FCS_CRYPTION_DATA_0 0x10100 + +/* FCS Payload Structure */ + +typedef struct fcs_crypt_payload_t { + uint32_t first_word; + uint32_t src_addr; + uint32_t src_size; + uint32_t dst_addr; + uint32_t dst_size; +} fcs_crypt_payload; + +/* Functions Definitions */ + +uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size, + uint32_t *mbox_error); +uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size, + uint32_t *send_id); +uint32_t intel_fcs_get_provision_data(uint32_t *send_id); +uint32_t intel_fcs_cryption(uint32_t mode, uint32_t src_addr, + uint32_t src_size, uint32_t dst_addr, + uint32_t dst_size, uint32_t *send_id); + +#endif /* SOCFPGA_FCS_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h new file mode 100644 index 0000000..ba0f7f3 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HANDOFF_H +#define HANDOFF_H + +#define HANDOFF_MAGIC_HEADER 0x424f4f54 /* BOOT */ +#define HANDOFF_MAGIC_PINMUX_SEL 0x504d5558 /* PMUX */ +#define HANDOFF_MAGIC_IOCTLR 0x494f4354 /* IOCT */ +#define HANDOFF_MAGIC_FPGA 0x46504741 /* FPGA */ +#define HANDOFF_MAGIC_IODELAY 0x444c4159 /* DLAY */ +#define HANDOFF_MAGIC_CLOCK 0x434c4b53 /* CLKS */ +#define HANDOFF_MAGIC_MISC 0x4d495343 /* MISC */ + +#include + +typedef struct handoff_t { + /* header */ + uint32_t header_magic; + uint32_t header_device; + uint32_t _pad_0x08_0x10[2]; + + /* pinmux configuration - select */ + uint32_t pinmux_sel_magic; + uint32_t pinmux_sel_length; + uint32_t _pad_0x18_0x20[2]; + uint32_t pinmux_sel_array[96]; /* offset, value */ + + /* pinmux configuration - io control */ + uint32_t pinmux_io_magic; + uint32_t pinmux_io_length; + uint32_t _pad_0x1a8_0x1b0[2]; + uint32_t pinmux_io_array[96]; /* offset, value */ + + /* pinmux configuration - use fpga switch */ + uint32_t pinmux_fpga_magic; + uint32_t pinmux_fpga_length; + uint32_t _pad_0x338_0x340[2]; + uint32_t pinmux_fpga_array[42]; /* offset, value */ + uint32_t _pad_0x3e8_0x3f0[2]; + + /* pinmux configuration - io delay */ + uint32_t pinmux_delay_magic; + uint32_t pinmux_delay_length; + uint32_t _pad_0x3f8_0x400[2]; + uint32_t pinmux_iodelay_array[96]; /* offset, value */ + + /* clock configuration */ + +#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10 + uint32_t clock_magic; + uint32_t clock_length; + uint32_t _pad_0x588_0x590[2]; + uint32_t main_pll_mpuclk; + uint32_t main_pll_nocclk; + uint32_t main_pll_cntr2clk; + uint32_t main_pll_cntr3clk; + uint32_t main_pll_cntr4clk; + uint32_t main_pll_cntr5clk; + uint32_t main_pll_cntr6clk; + uint32_t main_pll_cntr7clk; + uint32_t main_pll_cntr8clk; + uint32_t main_pll_cntr9clk; + uint32_t main_pll_nocdiv; + uint32_t main_pll_pllglob; + uint32_t main_pll_fdbck; + uint32_t main_pll_pllc0; + uint32_t main_pll_pllc1; + uint32_t _pad_0x5cc_0x5d0[1]; + uint32_t per_pll_cntr2clk; + uint32_t per_pll_cntr3clk; + uint32_t per_pll_cntr4clk; + uint32_t per_pll_cntr5clk; + uint32_t per_pll_cntr6clk; + uint32_t per_pll_cntr7clk; + uint32_t per_pll_cntr8clk; + uint32_t per_pll_cntr9clk; + uint32_t per_pll_emacctl; + uint32_t per_pll_gpiodiv; + uint32_t per_pll_pllglob; + uint32_t per_pll_fdbck; + uint32_t per_pll_pllc0; + uint32_t per_pll_pllc1; + uint32_t hps_osc_clk_h; + uint32_t fpga_clk_hz; +#elif PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX + uint32_t clock_magic; + uint32_t clock_length; + uint32_t _pad_0x588_0x590[2]; + uint32_t main_pll_mpuclk; + uint32_t main_pll_nocclk; + uint32_t main_pll_nocdiv; + uint32_t main_pll_pllglob; + uint32_t main_pll_fdbck; + uint32_t main_pll_pllc0; + uint32_t main_pll_pllc1; + uint32_t main_pll_pllc2; + uint32_t main_pll_pllc3; + uint32_t main_pll_pllm; + uint32_t per_pll_emacctl; + uint32_t per_pll_gpiodiv; + uint32_t per_pll_pllglob; + uint32_t per_pll_fdbck; + uint32_t per_pll_pllc0; + uint32_t per_pll_pllc1; + uint32_t per_pll_pllc2; + uint32_t per_pll_pllc3; + uint32_t per_pll_pllm; + uint32_t alt_emacactr; + uint32_t alt_emacbctr; + uint32_t alt_emacptpctr; + uint32_t alt_gpiodbctr; + uint32_t alt_sdmmcctr; + uint32_t alt_s2fuser0ctr; + uint32_t alt_s2fuser1ctr; + uint32_t alt_psirefctr; + uint32_t hps_osc_clk_h; + uint32_t fpga_clk_hz; + uint32_t _pad_0x604_0x610[3]; +#endif + /* misc configuration */ + uint32_t misc_magic; + uint32_t misc_length; + uint32_t _pad_0x618_0x620[2]; +} handoff; + +int verify_handoff_image(handoff *hoff_ptr, handoff *reverse_hoff_ptr); +int socfpga_get_handoff(handoff *hoff_ptr); + +#endif + + diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h new file mode 100644 index 0000000..6b7e0fc --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_MBOX_H +#define SOCFPGA_MBOX_H + +#include + + +#define MBOX_OFFSET 0xffa30000 + +#define MBOX_ATF_CLIENT_ID 0x1U +#define MBOX_MAX_JOB_ID 0xFU +#define MBOX_MAX_IND_JOB_ID (MBOX_MAX_JOB_ID - 1U) +#define MBOX_JOB_ID MBOX_MAX_JOB_ID + + +/* Mailbox Shared Memory Register Map */ +#define MBOX_CIN 0x00 +#define MBOX_ROUT 0x04 +#define MBOX_URG 0x08 +#define MBOX_INT 0x0C +#define MBOX_COUT 0x20 +#define MBOX_RIN 0x24 +#define MBOX_STATUS 0x2C +#define MBOX_CMD_BUFFER 0x40 +#define MBOX_RESP_BUFFER 0xC0 + +/* Mailbox SDM doorbell */ +#define MBOX_DOORBELL_TO_SDM 0x400 +#define MBOX_DOORBELL_FROM_SDM 0x480 + + +/* Mailbox commands */ + +#define MBOX_CMD_NOOP 0x00 +#define MBOX_CMD_SYNC 0x01 +#define MBOX_CMD_RESTART 0x02 +#define MBOX_CMD_CANCEL 0x03 +#define MBOX_CMD_VAB_SRC_CERT 0x0B +#define MBOX_CMD_GET_IDCODE 0x10 +#define MBOX_CMD_REBOOT_HPS 0x47 + +/* Reconfiguration Commands */ +#define MBOX_CONFIG_STATUS 0x04 +#define MBOX_RECONFIG 0x06 +#define MBOX_RECONFIG_DATA 0x08 +#define MBOX_RECONFIG_STATUS 0x09 + +/* QSPI Commands */ +#define MBOX_CMD_QSPI_OPEN 0x32 +#define MBOX_CMD_QSPI_CLOSE 0x33 +#define MBOX_CMD_QSPI_SET_CS 0x34 +#define MBOX_CMD_QSPI_DIRECT 0x3B + +/* RSU Commands */ +#define MBOX_GET_SUBPARTITION_TABLE 0x5A +#define MBOX_RSU_STATUS 0x5B +#define MBOX_RSU_UPDATE 0x5C +#define MBOX_HPS_STAGE_NOTIFY 0x5D + +/* FCS Command */ +#define MBOX_FCS_GET_PROVISION 0x7B +#define MBOX_FCS_ENCRYPT_REQ 0x7E +#define MBOX_FCS_DECRYPT_REQ 0x7F +#define MBOX_FCS_RANDOM_GEN 0x80 + +/* Mailbox Definitions */ + +#define CMD_DIRECT 0 +#define CMD_INDIRECT 1 +#define CMD_CASUAL 0 +#define CMD_URGENT 1 + +#define MBOX_WORD_BYTE 4U +#define MBOX_RESP_BUFFER_SIZE 16 +#define MBOX_CMD_BUFFER_SIZE 32 + +/* Execution states for HPS_STAGE_NOTIFY */ +#define HPS_EXECUTION_STATE_FSBL 0 +#define HPS_EXECUTION_STATE_SSBL 1 +#define HPS_EXECUTION_STATE_OS 2 + +/* Status Response */ +#define MBOX_RET_OK 0 +#define MBOX_RET_ERROR -1 +#define MBOX_NO_RESPONSE -2 +#define MBOX_WRONG_ID -3 +#define MBOX_BUFFER_FULL -4 +#define MBOX_TIMEOUT -2047 + +/* Reconfig Status Response */ +#define RECONFIG_STATUS_STATE 0 +#define RECONFIG_STATUS_PIN_STATUS 2 +#define RECONFIG_STATUS_SOFTFUNC_STATUS 3 +#define PIN_STATUS_NSTATUS (U(1) << 31) +#define SOFTFUNC_STATUS_SEU_ERROR (1 << 3) +#define SOFTFUNC_STATUS_INIT_DONE (1 << 1) +#define SOFTFUNC_STATUS_CONF_DONE (1 << 0) +#define MBOX_CFGSTAT_STATE_IDLE 0x00000000 +#define MBOX_CFGSTAT_STATE_CONFIG 0x10000000 +#define MBOX_CFGSTAT_STATE_FAILACK 0x08000000 +#define MBOX_CFGSTAT_STATE_ERROR_INVALID 0xf0000001 +#define MBOX_CFGSTAT_STATE_ERROR_CORRUPT 0xf0000002 +#define MBOX_CFGSTAT_STATE_ERROR_AUTH 0xf0000003 +#define MBOX_CFGSTAT_STATE_ERROR_CORE_IO 0xf0000004 +#define MBOX_CFGSTAT_STATE_ERROR_HARDWARE 0xf0000005 +#define MBOX_CFGSTAT_STATE_ERROR_FAKE 0xf0000006 +#define MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO 0xf0000007 +#define MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR 0xf0000008 + + +/* Mailbox Macros */ + +#define MBOX_ENTRY_TO_ADDR(_buf, ptr) (MBOX_OFFSET + (MBOX_##_buf##_BUFFER) \ + + MBOX_WORD_BYTE * (ptr)) + +/* Mailbox interrupt flags and masks */ +#define MBOX_INT_FLAG_COE 0x1 +#define MBOX_INT_FLAG_RIE 0x2 +#define MBOX_INT_FLAG_UAE 0x100 +#define MBOX_COE_BIT(INTERRUPT) ((INTERRUPT) & 0x3) +#define MBOX_UAE_BIT(INTERRUPT) (((INTERRUPT) & (1<<8))) + +/* Mailbox response and status */ +#define MBOX_RESP_ERR(BUFFER) ((BUFFER) & 0x00000fff) +#define MBOX_RESP_LEN(BUFFER) (((BUFFER) & 0x007ff000) >> 12) +#define MBOX_RESP_CLIENT_ID(BUFFER) (((BUFFER) & 0xf0000000) >> 28) +#define MBOX_RESP_JOB_ID(BUFFER) (((BUFFER) & 0x0f000000) >> 24) +#define MBOX_STATUS_UA_MASK (1<<8) + +/* Mailbox command and response */ +#define MBOX_CLIENT_ID_CMD(CLIENT_ID) ((CLIENT_ID) << 28) +#define MBOX_JOB_ID_CMD(JOB_ID) (JOB_ID<<24) +#define MBOX_CMD_LEN_CMD(CMD_LEN) ((CMD_LEN) << 12) +#define MBOX_INDIRECT(val) ((val) << 11) +#define MBOX_CMD_MASK(header) ((header) & 0x7ff) + +/* RSU Macros */ +#define RSU_VERSION_ACMF BIT(8) +#define RSU_VERSION_ACMF_MASK 0xff00 + + +/* Mailbox Function Definitions */ + +void mailbox_set_int(uint32_t interrupt_input); +int mailbox_init(void); +void mailbox_set_qspi_close(void); +void mailbox_hps_qspi_enable(void); + +int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args, + unsigned int len, uint32_t urgent, uint32_t *response, + unsigned int *resp_len); +int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args, + unsigned int len, unsigned int indirect); +int mailbox_read_response(uint32_t *job_id, uint32_t *response, + unsigned int *resp_len); +int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf, + unsigned int *resp_len); + +void mailbox_reset_cold(void); +void mailbox_clear_response(void); + +int intel_mailbox_get_config_status(uint32_t cmd, bool init_done); +int intel_mailbox_is_fpga_not_ready(void); + +int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len); +int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len); +int mailbox_rsu_update(uint32_t *flash_offset); +int mailbox_hps_stage_notify(uint32_t execution_stage); + +#endif /* SOCFPGA_MBOX_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h new file mode 100644 index 0000000..ca38f62 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_PRIVATE_H +#define SOCFPGA_PRIVATE_H + +#include "socfpga_plat_def.h" + +#define EMMC_DESC_SIZE (1<<20) + +#define EMMC_INIT_PARAMS(base, clk) \ + { .bus_width = MMC_BUS_WIDTH_4, \ + .clk_rate = (clk), \ + .desc_base = (base), \ + .desc_size = EMMC_DESC_SIZE, \ + .flags = 0, \ + .reg_base = SOCFPGA_MMC_REG_BASE \ + } + +typedef enum { + BOOT_SOURCE_FPGA = 0, + BOOT_SOURCE_SDMMC, + BOOT_SOURCE_NAND, + BOOT_SOURCE_RSVD, + BOOT_SOURCE_QSPI +} boot_source_type; + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void enable_nonsecure_access(void); + +void socfpga_io_setup(int boot_source); + +void socfgpa_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); + + +void socfpga_configure_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); + +void socfpga_delay_timer_init(void); + +void socfpga_gic_driver_init(void); + +uint32_t socfpga_get_spsr_for_bl32_entry(void); + +uint32_t socfpga_get_spsr_for_bl33_entry(void); + +unsigned long socfpga_get_ns_image_entrypoint(void); + +void plat_secondary_cpus_bl31_entry(void); + +#endif /* SOCFPGA_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h new file mode 100644 index 0000000..a976df7 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_RESETMANAGER_H +#define SOCFPGA_RESETMANAGER_H + +#include "socfpga_plat_def.h" + + +/* Register Mapping */ + +#define SOCFPGA_RSTMGR_STAT 0x000 +#define SOCFPGA_RSTMGR_HDSKEN 0x010 +#define SOCFPGA_RSTMGR_MPUMODRST 0x020 +#define SOCFPGA_RSTMGR_PER0MODRST 0x024 +#define SOCFPGA_RSTMGR_PER1MODRST 0x028 +#define SOCFPGA_RSTMGR_BRGMODRST 0x02c +#define SOCFPGA_RSTMGR_COLDMODRST 0x034 +#define SOCFPGA_RSTMGR_HDSKTIMEOUT 0x064 + +/* Field Mapping */ + +#define RSTMGR_PER0MODRST_EMAC0 0x00000001 +#define RSTMGR_PER0MODRST_EMAC1 0x00000002 +#define RSTMGR_PER0MODRST_EMAC2 0x00000004 +#define RSTMGR_PER0MODRST_USB0 0x00000008 +#define RSTMGR_PER0MODRST_USB1 0x00000010 +#define RSTMGR_PER0MODRST_NAND 0x00000020 +#define RSTMGR_PER0MODRST_SDMMC 0x00000080 +#define RSTMGR_PER0MODRST_EMAC0OCP 0x00000100 +#define RSTMGR_PER0MODRST_EMAC1OCP 0x00000200 +#define RSTMGR_PER0MODRST_EMAC2OCP 0x00000400 +#define RSTMGR_PER0MODRST_USB0OCP 0x00000800 +#define RSTMGR_PER0MODRST_USB1OCP 0x00001000 +#define RSTMGR_PER0MODRST_NANDOCP 0x00002000 +#define RSTMGR_PER0MODRST_SDMMCOCP 0x00008000 +#define RSTMGR_PER0MODRST_DMA 0x00010000 +#define RSTMGR_PER0MODRST_SPIM0 0x00020000 +#define RSTMGR_PER0MODRST_SPIM1 0x00040000 +#define RSTMGR_PER0MODRST_SPIS0 0x00080000 +#define RSTMGR_PER0MODRST_SPIS1 0x00100000 +#define RSTMGR_PER0MODRST_DMAOCP 0x00200000 +#define RSTMGR_PER0MODRST_EMACPTP 0x00400000 +#define RSTMGR_PER0MODRST_DMAIF0 0x01000000 +#define RSTMGR_PER0MODRST_DMAIF1 0x02000000 +#define RSTMGR_PER0MODRST_DMAIF2 0x04000000 +#define RSTMGR_PER0MODRST_DMAIF3 0x08000000 +#define RSTMGR_PER0MODRST_DMAIF4 0x10000000 +#define RSTMGR_PER0MODRST_DMAIF5 0x20000000 +#define RSTMGR_PER0MODRST_DMAIF6 0x40000000 +#define RSTMGR_PER0MODRST_DMAIF7 0x80000000 + +#define RSTMGR_PER1MODRST_WATCHDOG0 0x00000001 +#define RSTMGR_PER1MODRST_WATCHDOG1 0x00000002 +#define RSTMGR_PER1MODRST_WATCHDOG2 0x00000004 +#define RSTMGR_PER1MODRST_WATCHDOG3 0x00000008 +#define RSTMGR_PER1MODRST_L4SYSTIMER0 0x00000010 +#define RSTMGR_PER1MODRST_L4SYSTIMER1 0x00000020 +#define RSTMGR_PER1MODRST_SPTIMER0 0x00000040 +#define RSTMGR_PER1MODRST_SPTIMER1 0x00000080 +#define RSTMGR_PER1MODRST_I2C0 0x00000100 +#define RSTMGR_PER1MODRST_I2C1 0x00000200 +#define RSTMGR_PER1MODRST_I2C2 0x00000400 +#define RSTMGR_PER1MODRST_I2C3 0x00000800 +#define RSTMGR_PER1MODRST_I2C4 0x00001000 +#define RSTMGR_PER1MODRST_UART0 0x00010000 +#define RSTMGR_PER1MODRST_UART1 0x00020000 +#define RSTMGR_PER1MODRST_GPIO0 0x01000000 +#define RSTMGR_PER1MODRST_GPIO1 0x02000000 + +#define RSTMGR_HDSKEN_FPGAHSEN 0x00000004 +#define RSTMGR_HDSKEN_ETRSTALLEN 0x00000008 +#define RSTMGR_HDSKEN_L2FLUSHEN 0x00000100 +#define RSTMGR_HDSKEN_L3NOC_DBG 0x00010000 +#define RSTMGR_HDSKEN_DEBUG_L3NOC 0x00020000 +#define RSTMGR_HDSKEN_SDRSELFREFEN 0x00000001 + +#define RSTMGR_BRGMODRST_SOC2FPGA 0x1 +#define RSTMGR_BRGMODRST_LWHPS2FPGA 0x2 +#define RSTMGR_BRGMODRST_FPGA2SOC 0x4 +#define RSTMGR_BRGMODRST_F2SSDRAM1 0x10 +#define RSTMGR_BRGMODRST_F2SSDRAM2 0x20 +#define RSTMGR_BRGMODRST_MPFE 0x40 +#define RSTMGR_BRGMODRST_DDRSCH 0x40 + +/* Definitions */ + +#define RSTMGR_L2_MODRST 0x0100 +#define RSTMGR_HDSKEN_SET 0x010D + +/* Macros */ + +#define SOCFPGA_RSTMGR(_reg) (SOCFPGA_RSTMGR_REG_BASE \ + + (SOCFPGA_RSTMGR_##_reg)) +#define RSTMGR_FIELD(_reg, _field) (RSTMGR_##_reg##MODRST_##_field) + +/* Function Declarations */ + +void deassert_peripheral_reset(void); +void config_hps_hs_before_warm_reset(void); + +int socfpga_bridges_enable(void); +int socfpga_bridges_disable(void); + +#endif /* SOCFPGA_RESETMANAGER_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h new file mode 100644 index 0000000..0db71e2 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_SIP_SVC_H +#define SOCFPGA_SIP_SVC_H + + +/* SiP status response */ +#define INTEL_SIP_SMC_STATUS_OK 0 +#define INTEL_SIP_SMC_STATUS_BUSY 0x1 +#define INTEL_SIP_SMC_STATUS_REJECTED 0x2 +#define INTEL_SIP_SMC_STATUS_ERROR 0x4 +#define INTEL_SIP_SMC_RSU_ERROR 0x7 + +/* SiP mailbox error code */ +#define GENERIC_RESPONSE_ERROR 0x3FF + +/* SMC SiP service function identifier */ + +/* FPGA Reconfig */ +#define INTEL_SIP_SMC_FPGA_CONFIG_START 0xC2000001 +#define INTEL_SIP_SMC_FPGA_CONFIG_WRITE 0x42000002 +#define INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE 0xC2000003 +#define INTEL_SIP_SMC_FPGA_CONFIG_ISDONE 0xC2000004 +#define INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM 0xC2000005 + +/* Secure Register Access */ +#define INTEL_SIP_SMC_REG_READ 0xC2000007 +#define INTEL_SIP_SMC_REG_WRITE 0xC2000008 +#define INTEL_SIP_SMC_REG_UPDATE 0xC2000009 + +/* Remote System Update */ +#define INTEL_SIP_SMC_RSU_STATUS 0xC200000B +#define INTEL_SIP_SMC_RSU_UPDATE 0xC200000C +#define INTEL_SIP_SMC_RSU_NOTIFY 0xC200000E +#define INTEL_SIP_SMC_RSU_RETRY_COUNTER 0xC200000F +#define INTEL_SIP_SMC_RSU_DCMF_VERSION 0xC2000010 +#define INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION 0xC2000011 + + +/* ECC */ +#define INTEL_SIP_SMC_ECC_DBE 0xC200000D + +/* Send Mailbox Command */ +#define INTEL_SIP_SMC_MBOX_SEND_CMD 0xC200001E + + +/* SiP Definitions */ + +/* ECC DBE */ +#define WARM_RESET_WFI_FLAG BIT(31) +#define SYSMGR_ECC_DBE_COLD_RST_MASK (SYSMGR_ECC_OCRAM_MASK |\ + SYSMGR_ECC_DDR0_MASK |\ + SYSMGR_ECC_DDR1_MASK) + +/* SMC function IDs for SiP Service queries */ +#define SIP_SVC_CALL_COUNT 0x8200ff00 +#define SIP_SVC_UID 0x8200ff01 +#define SIP_SVC_VERSION 0x8200ff03 + +/* SiP Service Calls version numbers */ +#define SIP_SVC_VERSION_MAJOR 0 +#define SIP_SVC_VERSION_MINOR 1 + + +/* Structure Definitions */ +struct fpga_config_info { + uint32_t addr; + int size; + int size_written; + uint32_t write_requested; + int subblocks_sent; + int block_number; +}; + +/* Function Definitions */ + +bool is_address_in_ddr_range(uint64_t addr, uint64_t size); + +/* ECC DBE */ +bool cold_reset_for_ecc_dbe(void); +uint32_t intel_ecc_dbe_notification(uint64_t dbe_value); + +#endif /* SOCFPGA_SIP_SVC_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h new file mode 100644 index 0000000..2b13f1f --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_SYSTEMMANAGER_H +#define SOCFPGA_SYSTEMMANAGER_H + +#include "socfpga_plat_def.h" + +/* System Manager Register Map */ + +#define SOCFPGA_SYSMGR_SDMMC 0x28 + +#define SOCFPGA_SYSMGR_FPGAINTF_EN_2 0x6c + +#define SOCFPGA_SYSMGR_EMAC_0 0x44 +#define SOCFPGA_SYSMGR_EMAC_1 0x48 +#define SOCFPGA_SYSMGR_EMAC_2 0x4c +#define SOCFPGA_SYSMGR_FPGAINTF_EN_3 0x70 + +#define SOCFPGA_SYSMGR_NOC_TIMEOUT 0xc0 +#define SOCFPGA_SYSMGR_NOC_IDLEREQ_SET 0xc4 +#define SOCFPGA_SYSMGR_NOC_IDLEREQ_CLR 0xc8 +#define SOCFPGA_SYSMGR_NOC_IDLEREQ_VAL 0xcc +#define SOCFPGA_SYSMGR_NOC_IDLEACK 0xd0 +#define SOCFPGA_SYSMGR_NOC_IDLESTATUS 0xd4 + +#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_0 0x200 +#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_1 0x204 +#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_2 0x208 +#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_8 0x220 +#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_9 0x224 + +/* Field Masking */ + +#define SYSMGR_SDMMC_DRVSEL(x) (((x) & 0x7) << 0) +#define SYSMGR_SDMMC_SMPLSEL(x) (((x) & 0x7) << 4) + +#define IDLE_DATA_LWSOC2FPGA BIT(0) +#define IDLE_DATA_SOC2FPGA BIT(4) +#define IDLE_DATA_MASK (IDLE_DATA_LWSOC2FPGA | IDLE_DATA_SOC2FPGA) + +#define SCR_AXI_AP_MASK BIT(24) +#define SCR_FPGA2SOC_MASK BIT(16) +#define SCR_MPU_MASK BIT(0) +#define DISABLE_L4_FIREWALL (SCR_AXI_AP_MASK | SCR_FPGA2SOC_MASK \ + | SCR_MPU_MASK) +#define DISABLE_BRIDGE_FIREWALL 0x0ffe0101 + +#define SYSMGR_ECC_OCRAM_MASK BIT(1) +#define SYSMGR_ECC_DDR0_MASK BIT(16) +#define SYSMGR_ECC_DDR1_MASK BIT(17) + +/* Macros */ + +#define SOCFPGA_SYSMGR(_reg) (SOCFPGA_SYSMGR_REG_BASE \ + + (SOCFPGA_SYSMGR_##_reg)) + +#define SOCFPGA_L4_PER_SCR(_reg) (SOCFPGA_L4_PER_SCR_REG_BASE \ + + (SOCFPGA_NOC_FW_L4_PER_SCR_##_reg)) + +#define SOCFPGA_L4_SYS_SCR(_reg) (SOCFPGA_L4_SYS_SCR_REG_BASE \ + + (SOCFPGA_NOC_FW_L4_SYS_SCR_##_reg)) + +/* L3 Interconnect Register Map */ +#define SOCFPGA_NOC_FW_L4_PER_SCR_NAND_REGISTER 0x0000 +#define SOCFPGA_NOC_FW_L4_PER_SCR_NAND_DATA 0x0004 +#define SOCFPGA_NOC_FW_L4_PER_SCR_USB0_REGISTER 0x000c +#define SOCFPGA_NOC_FW_L4_PER_SCR_USB1_REGISTER 0x0010 +#define SOCFPGA_NOC_FW_L4_PER_SCR_SPI_MASTER0 0x001c +#define SOCFPGA_NOC_FW_L4_PER_SCR_SPI_MASTER1 0x0020 +#define SOCFPGA_NOC_FW_L4_PER_SCR_SPI_SLAVE0 0x0024 +#define SOCFPGA_NOC_FW_L4_PER_SCR_SPI_SLAVE1 0x0028 +#define SOCFPGA_NOC_FW_L4_PER_SCR_EMAC0 0x002c +#define SOCFPGA_NOC_FW_L4_PER_SCR_EMAC1 0x0030 +#define SOCFPGA_NOC_FW_L4_PER_SCR_EMAC2 0x0034 +#define SOCFPGA_NOC_FW_L4_PER_SCR_SDMMC 0x0040 +#define SOCFPGA_NOC_FW_L4_PER_SCR_GPIO0 0x0044 +#define SOCFPGA_NOC_FW_L4_PER_SCR_GPIO1 0x0048 +#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C0 0x0050 +#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C1 0x0054 +#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C2 0x0058 +#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C3 0x005c +#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C4 0x0060 +#define SOCFPGA_NOC_FW_L4_PER_SCR_SP_TIMER0 0x0064 +#define SOCFPGA_NOC_FW_L4_PER_SCR_SP_TIMER1 0x0068 +#define SOCFPGA_NOC_FW_L4_PER_SCR_UART0 0x006c +#define SOCFPGA_NOC_FW_L4_PER_SCR_UART1 0x0070 + +#define SOCFPGA_NOC_FW_L4_SYS_SCR_DMA_ECC 0x0008 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC0RX_ECC 0x000c +#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC0TX_ECC 0x0010 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC1RX_ECC 0x0014 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC1TX_ECC 0x0018 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC2RX_ECC 0x001c +#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC2TX_ECC 0x0020 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_NAND_ECC 0x002c +#define SOCFPGA_NOC_FW_L4_SYS_SCR_NAND_READ_ECC 0x0030 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_NAND_WRITE_ECC 0x0034 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_OCRAM_ECC 0x0038 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_SDMMC_ECC 0x0040 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_USB0_ECC 0x0044 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_USB1_ECC 0x0048 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_CLK_MGR 0x004c +#define SOCFPGA_NOC_FW_L4_SYS_SCR_IO_MGR 0x0054 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_RST_MGR 0x0058 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_SYS_MGR 0x005c +#define SOCFPGA_NOC_FW_L4_SYS_SCR_OSC0_TIMER 0x0060 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_OSC1_TIMER 0x0064 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_WATCHDOG0 0x0068 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_WATCHDOG1 0x006c +#define SOCFPGA_NOC_FW_L4_SYS_SCR_WATCHDOG2 0x0070 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_WATCHDOG3 0x0074 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_DAP 0x0078 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_L4_NOC_PROBES 0x0090 +#define SOCFPGA_NOC_FW_L4_SYS_SCR_L4_NOC_QOS 0x0094 + +#define SOCFPGA_CCU_NOC_CPU0_RAMSPACE0_0 0xf7004688 +#define SOCFPGA_CCU_NOC_IOM_RAMSPACE0_0 0xf7018628 + +void enable_ns_peripheral_access(void); +void enable_ns_bridge_access(void); + +#endif /* SOCFPGA_SYSTEMMANAGER_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c b/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c new file mode 100644 index 0000000..c4e06a6 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "socfpga_fcs.h" +#include "socfpga_mailbox.h" +#include "socfpga_reset_manager.h" +#include "socfpga_sip_svc.h" +#include "socfpga_system_manager.h" + +uint32_t intel_ecc_dbe_notification(uint64_t dbe_value) +{ + dbe_value &= WARM_RESET_WFI_FLAG; + + /* Trap CPUs in WFI if warm reset flag is set */ + if (dbe_value > 0) { + while (1) { + wfi(); + } + } + + return INTEL_SIP_SMC_STATUS_OK; +} + +bool cold_reset_for_ecc_dbe(void) +{ + uint32_t dbe_int_status; + + dbe_int_status = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_8)); + + /* Trigger cold reset only for error in critical memory (DDR/OCRAM) */ + dbe_int_status &= SYSMGR_ECC_DBE_COLD_RST_MASK; + + if (dbe_int_status > 0) { + return true; + } + + return false; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c new file mode 100644 index 0000000..fe5461b --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "socfpga_fcs.h" +#include "socfpga_mailbox.h" +#include "socfpga_sip_svc.h" + +uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size, + uint32_t *mbox_error) +{ + int status; + unsigned int i; + unsigned int resp_len = FCS_RANDOM_WORD_SIZE; + uint32_t random_data[FCS_RANDOM_WORD_SIZE] = {0U}; + + if (!is_address_in_ddr_range(addr, FCS_RANDOM_BYTE_SIZE)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_RANDOM_GEN, NULL, 0U, + CMD_CASUAL, random_data, &resp_len); + + if (status < 0) { + *mbox_error = -status; + return INTEL_SIP_SMC_STATUS_ERROR; + } + + if (resp_len != FCS_RANDOM_WORD_SIZE) { + *mbox_error = GENERIC_RESPONSE_ERROR; + return INTEL_SIP_SMC_STATUS_ERROR; + } + + *ret_size = FCS_RANDOM_BYTE_SIZE; + + for (i = 0U; i < FCS_RANDOM_WORD_SIZE; i++) { + mmio_write_32(addr, random_data[i]); + addr += MBOX_WORD_BYTE; + } + + flush_dcache_range(addr - *ret_size, *ret_size); + + return INTEL_SIP_SMC_STATUS_OK; +} + +uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size, + uint32_t *send_id) +{ + int status; + + if (!is_address_in_ddr_range(addr, size)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + status = mailbox_send_cmd_async(send_id, MBOX_CMD_VAB_SRC_CERT, + (uint32_t *)addr, size / MBOX_WORD_BYTE, + CMD_DIRECT); + + if (status < 0) { + return INTEL_SIP_SMC_STATUS_ERROR; + } + + return INTEL_SIP_SMC_STATUS_OK; +} + +uint32_t intel_fcs_get_provision_data(uint32_t *send_id) +{ + int status; + + status = mailbox_send_cmd_async(send_id, MBOX_FCS_GET_PROVISION, + NULL, 0U, CMD_DIRECT); + + if (status < 0) { + return INTEL_SIP_SMC_STATUS_ERROR; + } + + return INTEL_SIP_SMC_STATUS_OK; +} + +uint32_t intel_fcs_cryption(uint32_t mode, uint32_t src_addr, + uint32_t src_size, uint32_t dst_addr, + uint32_t dst_size, uint32_t *send_id) +{ + int status; + uint32_t cmd; + + if (!is_address_in_ddr_range(src_addr, src_size) || + !is_address_in_ddr_range(dst_addr, dst_size)) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + fcs_crypt_payload payload = { + FCS_CRYPTION_DATA_0, + src_addr, + src_size, + dst_addr, + dst_size }; + + if (mode != 0U) { + cmd = MBOX_FCS_ENCRYPT_REQ; + } else { + cmd = MBOX_FCS_DECRYPT_REQ; + } + + status = mailbox_send_cmd_async(send_id, cmd, (uint32_t *) &payload, + sizeof(fcs_crypt_payload) / MBOX_WORD_BYTE, + CMD_INDIRECT); + inv_dcache_range(dst_addr, dst_size); + + if (status < 0) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + return INTEL_SIP_SMC_STATUS_OK; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c new file mode 100644 index 0000000..cacfd53 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "socfpga_emac.h" +#include "socfpga_reset_manager.h" +#include "socfpga_system_manager.h" + +void socfpga_emac_init(void) +{ + mmio_setbits_32(SOCFPGA_RSTMGR(PER0MODRST), + RSTMGR_PER0MODRST_EMAC0 | + RSTMGR_PER0MODRST_EMAC1 | + RSTMGR_PER0MODRST_EMAC2); + + mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_0), + PHY_INTF_SEL_MSK, EMAC0_PHY_MODE); + mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_1), + PHY_INTF_SEL_MSK, EMAC1_PHY_MODE); + mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_2), + PHY_INTF_SEL_MSK, EMAC2_PHY_MODE); + + mmio_clrbits_32(SOCFPGA_SYSMGR(FPGAINTF_EN_3), + FPGAINTF_EN_3_EMAC_MSK(0) | + FPGAINTF_EN_3_EMAC_MSK(1) | + FPGAINTF_EN_3_EMAC_MSK(2)); + + mmio_clrbits_32(SOCFPGA_RSTMGR(PER0MODRST), + RSTMGR_PER0MODRST_EMAC0 | + RSTMGR_PER0MODRST_EMAC1 | + RSTMGR_PER0MODRST_EMAC2); +} + diff --git a/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c new file mode 100644 index 0000000..4bb3a96 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "socfpga_handoff.h" + +#define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | \ + (((x) & 0x0000FF00) << 8) | ((x) << 24)) + +int socfpga_get_handoff(handoff *reverse_hoff_ptr) +{ + int i; + uint32_t *buffer; + handoff *handoff_ptr = (handoff *) PLAT_HANDOFF_OFFSET; + + memcpy(reverse_hoff_ptr, handoff_ptr, sizeof(handoff)); + buffer = (uint32_t *)reverse_hoff_ptr; + + /* convert big endian to little endian */ + for (i = 0; i < sizeof(handoff) / 4; i++) + buffer[i] = SWAP_UINT32(buffer[i]); + + if (reverse_hoff_ptr->header_magic != HANDOFF_MAGIC_HEADER) + return -1; + if (reverse_hoff_ptr->pinmux_sel_magic != HANDOFF_MAGIC_PINMUX_SEL) + return -1; + if (reverse_hoff_ptr->pinmux_io_magic != HANDOFF_MAGIC_IOCTLR) + return -1; + if (reverse_hoff_ptr->pinmux_fpga_magic != HANDOFF_MAGIC_FPGA) + return -1; + if (reverse_hoff_ptr->pinmux_delay_magic != HANDOFF_MAGIC_IODELAY) + return -1; + + return 0; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c new file mode 100644 index 0000000..be900c9 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2020-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "socfpga_mailbox.h" +#include "socfpga_sip_svc.h" + + +static bool is_mailbox_cmdbuf_full(uint32_t cin) +{ + uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT); + + return (((cin + 1U) % MBOX_CMD_BUFFER_SIZE) == cout); +} + +static bool is_mailbox_cmdbuf_empty(uint32_t cin) +{ + uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT); + + return (((cout + 1U) % MBOX_CMD_BUFFER_SIZE) == cin); +} + +static int wait_for_mailbox_cmdbuf_empty(uint32_t cin) +{ + unsigned int timeout = 200U; + + do { + if (is_mailbox_cmdbuf_empty(cin)) { + break; + } + mdelay(10U); + } while (--timeout != 0U); + + if (timeout == 0U) { + return MBOX_TIMEOUT; + } + + return MBOX_RET_OK; +} + +static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout, + uint32_t data, + bool *is_doorbell_triggered) +{ + unsigned int timeout = 100U; + + do { + if (is_mailbox_cmdbuf_full(*cin)) { + if (!(*is_doorbell_triggered)) { + mmio_write_32(MBOX_OFFSET + + MBOX_DOORBELL_TO_SDM, 1U); + *is_doorbell_triggered = true; + } + mdelay(10U); + } else { + mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data); + *cin %= MBOX_CMD_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin); + break; + } + } while (--timeout != 0U); + + if (timeout == 0U) { + return MBOX_TIMEOUT; + } + + if (*is_doorbell_triggered) { + int ret = wait_for_mailbox_cmdbuf_empty(*cin); + return ret; + } + + return MBOX_RET_OK; +} + +static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args, + unsigned int len) +{ + uint32_t sdm_read_offset, cmd_free_offset; + unsigned int i; + int ret; + bool is_doorbell_triggered = false; + + cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN); + sdm_read_offset = mmio_read_32(MBOX_OFFSET + MBOX_COUT); + + ret = write_mailbox_cmd_buffer(&cmd_free_offset, sdm_read_offset, + header_cmd, &is_doorbell_triggered); + if (ret != 0) { + goto restart_mailbox; + } + + for (i = 0U; i < len; i++) { + is_doorbell_triggered = false; + ret = write_mailbox_cmd_buffer(&cmd_free_offset, + sdm_read_offset, args[i], + &is_doorbell_triggered); + if (ret != 0) { + goto restart_mailbox; + } + } + + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U); + + return MBOX_RET_OK; + +restart_mailbox: + /* + * Attempt to restart mailbox if the driver not able to write + * into mailbox command buffer + */ + if (MBOX_CMD_MASK(header_cmd) != MBOX_CMD_RESTART) { + INFO("Mailbox timed out: Attempting mailbox reset\n"); + ret = mailbox_init(); + + if (ret == MBOX_TIMEOUT) { + INFO("Error: Mailbox fail to restart\n"); + } + } + + return MBOX_TIMEOUT; +} + +int mailbox_read_response(unsigned int *job_id, uint32_t *response, + unsigned int *resp_len) +{ + uint32_t rin; + uint32_t rout; + uint32_t resp_data; + unsigned int ret_resp_len; + + if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) { + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U); + } + + rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); + rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); + + if (rout != rin) { + resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++)); + + rout %= MBOX_RESP_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); + + + if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) { + return MBOX_WRONG_ID; + } + + *job_id = MBOX_RESP_JOB_ID(resp_data); + + ret_resp_len = MBOX_RESP_LEN(resp_data); + + if (iterate_resp(ret_resp_len, response, resp_len) + != MBOX_RET_OK) { + return MBOX_TIMEOUT; + } + + if (MBOX_RESP_ERR(resp_data) > 0U) { + INFO("Error in response: %x\n", resp_data); + return -MBOX_RESP_ERR(resp_data); + } + + return MBOX_RET_OK; + } + return MBOX_NO_RESPONSE; +} + + +int mailbox_poll_response(uint32_t job_id, uint32_t urgent, uint32_t *response, + unsigned int *resp_len) +{ + unsigned int timeout = 40U; + unsigned int sdm_loop = 255U; + unsigned int ret_resp_len; + uint32_t rin; + uint32_t rout; + uint32_t resp_data; + + while (sdm_loop != 0U) { + + do { + if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) + == 1U) { + break; + } + mdelay(10U); + } while (--timeout != 0U); + + if (timeout == 0U) { + break; + } + + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U); + + if ((urgent & 1U) != 0U) { + mdelay(5U); + if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) & + MBOX_STATUS_UA_MASK) ^ + (urgent & MBOX_STATUS_UA_MASK)) { + mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U); + return MBOX_RET_OK; + } + + mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U); + INFO("Error: Mailbox did not get UA"); + return MBOX_RET_ERROR; + } + + rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); + rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); + + while (rout != rin) { + resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, + (rout)++)); + + rout %= MBOX_RESP_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); + + if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID + || MBOX_RESP_JOB_ID(resp_data) != job_id) { + continue; + } + + ret_resp_len = MBOX_RESP_LEN(resp_data); + + if (iterate_resp(ret_resp_len, response, resp_len) + != MBOX_RET_OK) { + return MBOX_TIMEOUT; + } + + if (MBOX_RESP_ERR(resp_data) > 0U) { + INFO("Error in response: %x\n", resp_data); + return -MBOX_RESP_ERR(resp_data); + } + + return MBOX_RET_OK; + } + + sdm_loop--; + } + + INFO("Timed out waiting for SDM\n"); + return MBOX_TIMEOUT; +} + +int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf, + unsigned int *resp_len) +{ + unsigned int timeout, total_resp_len = 0U; + uint32_t resp_data; + uint32_t rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); + uint32_t rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); + + while (mbox_resp_len > 0U) { + timeout = 100U; + mbox_resp_len--; + resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++)); + + if ((resp_buf != NULL) && (resp_len != NULL) + && (*resp_len != 0U)) { + *(resp_buf + total_resp_len) + = resp_data; + *resp_len = *resp_len - 1; + total_resp_len++; + } + rout %= MBOX_RESP_BUFFER_SIZE; + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); + + do { + rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); + if (rout == rin) { + mdelay(10U); + } else { + break; + } + timeout--; + } while ((mbox_resp_len > 0U) && (timeout != 0U)); + + if (timeout == 0U) { + INFO("Timed out waiting for SDM\n"); + return MBOX_TIMEOUT; + } + } + + if (resp_len) + *resp_len = total_resp_len; + + return MBOX_RET_OK; +} + +int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args, + unsigned int len, unsigned int indirect) +{ + int status; + + status = fill_mailbox_circular_buffer( + MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) | + MBOX_JOB_ID_CMD(*job_id) | + MBOX_CMD_LEN_CMD(len) | + MBOX_INDIRECT(indirect) | + cmd, args, len); + if (status < 0) { + return status; + } + + *job_id = (*job_id + 1U) % MBOX_MAX_IND_JOB_ID; + + return MBOX_RET_OK; +} + +int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args, + unsigned int len, uint32_t urgent, uint32_t *response, + unsigned int *resp_len) +{ + int status = 0; + + if (urgent != 0U) { + urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) & + MBOX_STATUS_UA_MASK; + mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd); + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U); + } + + else { + status = fill_mailbox_circular_buffer( + MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) | + MBOX_JOB_ID_CMD(job_id) | + MBOX_CMD_LEN_CMD(len) | + cmd, args, len); + } + + if (status != 0) { + return status; + } + + status = mailbox_poll_response(job_id, urgent, response, resp_len); + + return status; +} + +void mailbox_clear_response(void) +{ + mmio_write_32(MBOX_OFFSET + MBOX_ROUT, + mmio_read_32(MBOX_OFFSET + MBOX_RIN)); +} + +void mailbox_set_int(uint32_t interrupt) +{ + + mmio_write_32(MBOX_OFFSET+MBOX_INT, MBOX_COE_BIT(interrupt) | + MBOX_UAE_BIT(interrupt)); +} + + +void mailbox_set_qspi_open(void) +{ + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_OPEN, NULL, 0U, + CMD_CASUAL, NULL, NULL); +} + +void mailbox_set_qspi_direct(void) +{ + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, NULL, 0U, + CMD_CASUAL, NULL, NULL); +} + +void mailbox_set_qspi_close(void) +{ + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_CLOSE, NULL, 0U, + CMD_CASUAL, NULL, NULL); +} + +void mailbox_qspi_set_cs(uint32_t device_select) +{ + uint32_t cs_setting; + + /* QSPI device select settings at 31:28 */ + cs_setting = (device_select << 28); + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_SET_CS, &cs_setting, + 1U, CMD_CASUAL, NULL, NULL); +} + +void mailbox_hps_qspi_enable(void) +{ + mailbox_set_qspi_open(); + mailbox_set_qspi_direct(); +} + +void mailbox_reset_cold(void) +{ + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, NULL, 0U, + CMD_CASUAL, NULL, NULL); +} + +int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, unsigned int resp_buf_len) +{ + return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE, + NULL, 0U, CMD_CASUAL, resp_buf, + &resp_buf_len); +} + +struct rsu_status_info { + uint64_t current_image; + uint64_t fail_image; + uint32_t state; + uint32_t version; + uint32_t error_location; + uint32_t error_details; + uint32_t retry_counter; +}; + +int mailbox_rsu_status(uint32_t *resp_buf, unsigned int resp_buf_len) +{ + int ret; + struct rsu_status_info *info = (struct rsu_status_info *)resp_buf; + + info->retry_counter = ~0U; + + ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0U, + CMD_CASUAL, resp_buf, + &resp_buf_len); + + if (ret < 0) { + return ret; + } + + if (info->retry_counter != ~0U) { + if ((info->version & RSU_VERSION_ACMF_MASK) == 0U) { + info->version |= RSU_VERSION_ACMF; + } + } + + return ret; +} + +int mailbox_rsu_update(uint32_t *flash_offset) +{ + return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE, + flash_offset, 2U, + CMD_CASUAL, NULL, NULL); +} + +int mailbox_hps_stage_notify(uint32_t execution_stage) +{ + return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY, + &execution_stage, 1U, CMD_CASUAL, + NULL, NULL); +} + +int mailbox_init(void) +{ + int status; + + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE | + MBOX_INT_FLAG_UAE); + mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U); + mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U); + + status = mailbox_send_cmd(0U, MBOX_CMD_RESTART, NULL, 0U, + CMD_URGENT, NULL, NULL); + + if (status != 0) { + return status; + } + + mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE | + MBOX_INT_FLAG_UAE); + + return MBOX_RET_OK; +} + +int intel_mailbox_get_config_status(uint32_t cmd, bool init_done) +{ + int status; + uint32_t res, response[6]; + unsigned int resp_len = ARRAY_SIZE(response); + + status = mailbox_send_cmd(MBOX_JOB_ID, cmd, NULL, 0U, CMD_CASUAL, + response, &resp_len); + + if (status < 0) { + return status; + } + + res = response[RECONFIG_STATUS_STATE]; + if ((res != 0U) && (res != MBOX_CFGSTAT_STATE_CONFIG)) { + return res; + } + + res = response[RECONFIG_STATUS_PIN_STATUS]; + if ((res & PIN_STATUS_NSTATUS) == 0U) { + return MBOX_CFGSTAT_STATE_ERROR_HARDWARE; + } + + res = response[RECONFIG_STATUS_SOFTFUNC_STATUS]; + if ((res & SOFTFUNC_STATUS_SEU_ERROR) != 0U) { + return MBOX_CFGSTAT_STATE_ERROR_HARDWARE; + } + + if ((res & SOFTFUNC_STATUS_CONF_DONE) == 0U) + return MBOX_CFGSTAT_STATE_CONFIG; + + if (init_done && (res & SOFTFUNC_STATUS_INIT_DONE) == 0U) + return MBOX_CFGSTAT_STATE_CONFIG; + + return MBOX_RET_OK; +} + +int intel_mailbox_is_fpga_not_ready(void) +{ + int ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true); + + if ((ret != MBOX_RET_OK) && (ret != MBOX_CFGSTAT_STATE_CONFIG)) { + ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS, + false); + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c new file mode 100644 index 0000000..b0de60e --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "socfpga_mailbox.h" +#include "socfpga_reset_manager.h" +#include "socfpga_system_manager.h" + + +void deassert_peripheral_reset(void) +{ + mmio_clrbits_32(SOCFPGA_RSTMGR(PER1MODRST), + RSTMGR_FIELD(PER1, WATCHDOG0) | + RSTMGR_FIELD(PER1, WATCHDOG1) | + RSTMGR_FIELD(PER1, WATCHDOG2) | + RSTMGR_FIELD(PER1, WATCHDOG3) | + RSTMGR_FIELD(PER1, L4SYSTIMER0) | + RSTMGR_FIELD(PER1, L4SYSTIMER1) | + RSTMGR_FIELD(PER1, SPTIMER0) | + RSTMGR_FIELD(PER1, SPTIMER1) | + RSTMGR_FIELD(PER1, I2C0) | + RSTMGR_FIELD(PER1, I2C1) | + RSTMGR_FIELD(PER1, I2C2) | + RSTMGR_FIELD(PER1, I2C3) | + RSTMGR_FIELD(PER1, I2C4) | + RSTMGR_FIELD(PER1, UART0) | + RSTMGR_FIELD(PER1, UART1) | + RSTMGR_FIELD(PER1, GPIO0) | + RSTMGR_FIELD(PER1, GPIO1)); + + mmio_clrbits_32(SOCFPGA_RSTMGR(PER0MODRST), + RSTMGR_FIELD(PER0, EMAC0OCP) | + RSTMGR_FIELD(PER0, EMAC1OCP) | + RSTMGR_FIELD(PER0, EMAC2OCP) | + RSTMGR_FIELD(PER0, USB0OCP) | + RSTMGR_FIELD(PER0, USB1OCP) | + RSTMGR_FIELD(PER0, NANDOCP) | + RSTMGR_FIELD(PER0, SDMMCOCP) | + RSTMGR_FIELD(PER0, DMAOCP)); + + mmio_clrbits_32(SOCFPGA_RSTMGR(PER0MODRST), + RSTMGR_FIELD(PER0, EMAC0) | + RSTMGR_FIELD(PER0, EMAC1) | + RSTMGR_FIELD(PER0, EMAC2) | + RSTMGR_FIELD(PER0, USB0) | + RSTMGR_FIELD(PER0, USB1) | + RSTMGR_FIELD(PER0, NAND) | + RSTMGR_FIELD(PER0, SDMMC) | + RSTMGR_FIELD(PER0, DMA) | + RSTMGR_FIELD(PER0, SPIM0) | + RSTMGR_FIELD(PER0, SPIM1) | + RSTMGR_FIELD(PER0, SPIS0) | + RSTMGR_FIELD(PER0, SPIS1) | + RSTMGR_FIELD(PER0, EMACPTP) | + RSTMGR_FIELD(PER0, DMAIF0) | + RSTMGR_FIELD(PER0, DMAIF1) | + RSTMGR_FIELD(PER0, DMAIF2) | + RSTMGR_FIELD(PER0, DMAIF3) | + RSTMGR_FIELD(PER0, DMAIF4) | + RSTMGR_FIELD(PER0, DMAIF5) | + RSTMGR_FIELD(PER0, DMAIF6) | + RSTMGR_FIELD(PER0, DMAIF7)); + +#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX + mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST), + RSTMGR_FIELD(BRG, MPFE)); +#endif +} + +void config_hps_hs_before_warm_reset(void) +{ + uint32_t or_mask = 0; + + or_mask |= RSTMGR_HDSKEN_SDRSELFREFEN; + or_mask |= RSTMGR_HDSKEN_FPGAHSEN; + or_mask |= RSTMGR_HDSKEN_ETRSTALLEN; + or_mask |= RSTMGR_HDSKEN_L2FLUSHEN; + or_mask |= RSTMGR_HDSKEN_L3NOC_DBG; + or_mask |= RSTMGR_HDSKEN_DEBUG_L3NOC; + + mmio_setbits_32(SOCFPGA_RSTMGR(HDSKEN), or_mask); +} + +static int poll_idle_status(uint32_t addr, uint32_t mask, uint32_t match) +{ + int time_out = 1000; + + while (time_out--) { + if ((mmio_read_32(addr) & mask) == match) { + return 0; + } + } + return -ETIMEDOUT; +} + +int socfpga_bridges_enable(void) +{ + /* Clear idle request */ + mmio_setbits_32(SOCFPGA_SYSMGR(NOC_IDLEREQ_CLR), ~0); + + /* De-assert all bridges */ + mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST), ~0); + + /* Wait until idle ack becomes 0 */ + return poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLEACK), + IDLE_DATA_MASK, 0); +} + +int socfpga_bridges_disable(void) +{ + /* Set idle request */ + mmio_write_32(SOCFPGA_SYSMGR(NOC_IDLEREQ_SET), ~0); + + /* Enable NOC timeout */ + mmio_setbits_32(SOCFPGA_SYSMGR(NOC_TIMEOUT), 1); + + /* Wait until each idle ack bit toggle to 1 */ + if (poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLEACK), + IDLE_DATA_MASK, IDLE_DATA_MASK)) + return -ETIMEDOUT; + + /* Wait until each idle status bit toggle to 1 */ + if (poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLESTATUS), + IDLE_DATA_MASK, IDLE_DATA_MASK)) + return -ETIMEDOUT; + + /* Assert all bridges */ +#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10 + mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST), + ~(RSTMGR_FIELD(BRG, DDRSCH) | RSTMGR_FIELD(BRG, FPGA2SOC))); +#else + mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST), + ~(RSTMGR_FIELD(BRG, MPFE) | RSTMGR_FIELD(BRG, FPGA2SOC))); +#endif + + /* Disable NOC timeout */ + mmio_clrbits_32(SOCFPGA_SYSMGR(NOC_TIMEOUT), 1); + + return 0; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c new file mode 100644 index 0000000..a64053c --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "socfpga_system_manager.h" + +void enable_nonsecure_access(void) +{ + enable_ns_peripheral_access(); + enable_ns_bridge_access(); +} + +void enable_ns_peripheral_access(void) +{ + mmio_write_32(SOCFPGA_L4_PER_SCR(NAND_REGISTER), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(NAND_DATA), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(NAND_ECC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(NAND_READ_ECC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(NAND_WRITE_ECC), + DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_PER_SCR(USB0_REGISTER), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(USB1_REGISTER), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(USB0_ECC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(USB1_ECC), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_PER_SCR(SPI_MASTER0), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(SPI_MASTER1), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(SPI_SLAVE0), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(SPI_SLAVE1), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_PER_SCR(EMAC0), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(EMAC1), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(EMAC2), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC0RX_ECC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC0TX_ECC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC1RX_ECC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC1TX_ECC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC2RX_ECC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC2TX_ECC), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_PER_SCR(SDMMC), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(SDMMC_ECC), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_PER_SCR(GPIO0), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(GPIO1), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_PER_SCR(I2C0), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(I2C1), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(I2C2), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(I2C3), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(I2C4), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_PER_SCR(SP_TIMER1), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_PER_SCR(UART0), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_PER_SCR(UART1), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(DMA_ECC), DISABLE_L4_FIREWALL); + + + mmio_write_32(SOCFPGA_L4_SYS_SCR(OCRAM_ECC), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(CLK_MGR), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(IO_MGR), DISABLE_L4_FIREWALL); + + + mmio_write_32(SOCFPGA_L4_SYS_SCR(RST_MGR), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(SYS_MGR), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(OSC0_TIMER), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(OSC1_TIMER), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(WATCHDOG0), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(WATCHDOG1), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(WATCHDOG2), DISABLE_L4_FIREWALL); + mmio_write_32(SOCFPGA_L4_SYS_SCR(WATCHDOG3), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(DAP), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(L4_NOC_PROBES), DISABLE_L4_FIREWALL); + + mmio_write_32(SOCFPGA_L4_SYS_SCR(L4_NOC_QOS), DISABLE_L4_FIREWALL); + +#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10 + mmio_clrbits_32(SOCFPGA_CCU_NOC_CPU0_RAMSPACE0_0, 0x03); + mmio_clrbits_32(SOCFPGA_CCU_NOC_IOM_RAMSPACE0_0, 0x03); + + mmio_write_32(SOCFPGA_SYSMGR(SDMMC), SYSMGR_SDMMC_DRVSEL(3)); +#endif + +} + +void enable_ns_bridge_access(void) +{ + mmio_write_32(SOCFPGA_SOC2FPGA_SCR_REG_BASE, DISABLE_BRIDGE_FIREWALL); + mmio_write_32(SOCFPGA_LWSOC2FPGA_SCR_REG_BASE, DISABLE_BRIDGE_FIREWALL); +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c new file mode 100644 index 0000000..c55cc9d --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define SOCFPGA_GLOBAL_TIMER 0xffd01000 +#define SOCFPGA_GLOBAL_TIMER_EN 0x3 + +/******************************************************************** + * The timer delay function + ********************************************************************/ +static uint32_t socfpga_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()); +} + +static const timer_ops_t plat_timer_ops = { + .get_timer_value = socfpga_get_timer_value, + .clk_mult = 1, + .clk_div = PLAT_SYS_COUNTER_FREQ_IN_MHZ, +}; + +void socfpga_delay_timer_init(void) +{ + timer_init(&plat_timer_ops); + mmio_write_32(SOCFPGA_GLOBAL_TIMER, SOCFPGA_GLOBAL_TIMER_EN); + + asm volatile("msr cntp_ctl_el0, %0" : : "r" (SOCFPGA_GLOBAL_TIMER_EN)); + asm volatile("msr cntp_tval_el0, %0" : : "r" (~0)); + +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c new file mode 100644 index 0000000..a5c3279 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + unsigned int count; + unsigned int img_id = 0U; + unsigned int link_index = 0U; + bl_params_node_t *bl_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; + + /* Clean next_params_info in BL image node */ + for (count = 0U; count < bl_mem_params_desc_num; count++) { + + desc_ptr = &bl_mem_params_desc_ptr[link_index]; + bl_exec_node = &desc_ptr->params_node_mem; + bl_exec_node->next_params_info = NULL; + + /* 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); + } + + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c new file mode 100644 index 0000000..5fd6559 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "socfpga_mailbox.h" +#include "socfpga_plat_def.h" +#include "socfpga_reset_manager.h" +#include "socfpga_sip_svc.h" + + +/******************************************************************************* + * plat handler called when a CPU is about to enter standby. + ******************************************************************************/ +void socfpga_cpu_standby(plat_local_state_t cpu_state) +{ + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state); + dsb(); + wfi(); +} + +/******************************************************************************* + * plat handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +int socfpga_pwr_domain_on(u_register_t mpidr) +{ + unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); + + VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); + + if (cpu_id == -1) + return PSCI_E_INTERN_FAIL; + + mmio_write_64(PLAT_CPUID_RELEASE, cpu_id); + + /* release core reset */ + mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id); + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * plat handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void socfpga_pwr_domain_off(const psci_power_state_t *target_state) +{ + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* Prevent interrupts from spuriously waking up this cpu */ + gicv2_cpuif_disable(); +} + +/******************************************************************************* + * plat handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void socfpga_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* assert core reset */ + mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id); + +} + +/******************************************************************************* + * plat handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void socfpga_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* Program the gic per-cpu distributor or re-distributor interface */ + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + + /* Enable the gic cpu interface */ + gicv2_cpuif_enable(); +} + +/******************************************************************************* + * plat handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ******************************************************************************/ +void socfpga_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* release core reset */ + mmio_clrbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id); +} + +/******************************************************************************* + * plat handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 socfpga_system_off(void) +{ + wfi(); + ERROR("System Off: operation not handled.\n"); + panic(); +} + +extern uint64_t intel_rsu_update_address; + +static void __dead2 socfpga_system_reset(void) +{ + uint32_t addr_buf[2]; + + memcpy(addr_buf, &intel_rsu_update_address, + sizeof(intel_rsu_update_address)); + + if (intel_rsu_update_address) + mailbox_rsu_update(addr_buf); + else + mailbox_reset_cold(); + + while (1) + wfi(); +} + +static int socfpga_system_reset2(int is_vendor, int reset_type, + u_register_t cookie) +{ + if (cold_reset_for_ecc_dbe()) { + mailbox_reset_cold(); + } + /* disable cpuif */ + gicv2_cpuif_disable(); + + /* Store magic number */ + mmio_write_32(L2_RESET_DONE_REG, L2_RESET_DONE_STATUS); + + /* Increase timeout */ + mmio_write_32(SOCFPGA_RSTMGR(HDSKTIMEOUT), 0xffffff); + + /* Enable handshakes */ + mmio_setbits_32(SOCFPGA_RSTMGR(HDSKEN), RSTMGR_HDSKEN_SET); + + /* Reset L2 module */ + mmio_setbits_32(SOCFPGA_RSTMGR(COLDMODRST), 0x100); + + while (1) + wfi(); + + /* Should not reach here */ + return 0; +} + +int socfpga_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); + + return PSCI_E_SUCCESS; +} + +int socfpga_validate_ns_entrypoint(unsigned long ns_entrypoint) +{ + VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint); + return PSCI_E_SUCCESS; +} + +void socfpga_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE; +} + +/******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +const plat_psci_ops_t socfpga_psci_pm_ops = { + .cpu_standby = socfpga_cpu_standby, + .pwr_domain_on = socfpga_pwr_domain_on, + .pwr_domain_off = socfpga_pwr_domain_off, + .pwr_domain_suspend = socfpga_pwr_domain_suspend, + .pwr_domain_on_finish = socfpga_pwr_domain_on_finish, + .pwr_domain_suspend_finish = socfpga_pwr_domain_suspend_finish, + .system_off = socfpga_system_off, + .system_reset = socfpga_system_reset, + .system_reset2 = socfpga_system_reset2, + .validate_power_state = socfpga_validate_power_state, + .validate_ns_entrypoint = socfpga_validate_ns_entrypoint, + .get_sys_suspend_power_state = socfpga_get_sys_suspend_power_state +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + /* Save warm boot entrypoint.*/ + mmio_write_64(PLAT_SEC_ENTRY, sec_entrypoint); + *psci_ops = &socfpga_psci_pm_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c new file mode 100644 index 0000000..14cd9e0 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include "socfpga_fcs.h" +#include "socfpga_mailbox.h" +#include "socfpga_reset_manager.h" +#include "socfpga_sip_svc.h" + + +/* Total buffer the driver can hold */ +#define FPGA_CONFIG_BUFFER_SIZE 4 + +static int current_block, current_buffer; +static int read_block, max_blocks, is_partial_reconfig; +static uint32_t send_id, rcv_id; +static uint32_t bytes_per_block, blocks_submitted; + + +/* SiP Service UUID */ +DEFINE_SVC_UUID2(intl_svc_uid, + 0xa85273b0, 0xe85a, 0x4862, 0xa6, 0x2a, + 0xfa, 0x88, 0x88, 0x17, 0x68, 0x81); + +static uint64_t socfpga_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +struct fpga_config_info fpga_config_buffers[FPGA_CONFIG_BUFFER_SIZE]; + +static int intel_fpga_sdm_write_buffer(struct fpga_config_info *buffer) +{ + uint32_t args[3]; + + while (max_blocks > 0 && buffer->size > buffer->size_written) { + args[0] = (1<<8); + args[1] = buffer->addr + buffer->size_written; + if (buffer->size - buffer->size_written <= bytes_per_block) { + args[2] = buffer->size - buffer->size_written; + current_buffer++; + current_buffer %= FPGA_CONFIG_BUFFER_SIZE; + } else + args[2] = bytes_per_block; + + buffer->size_written += args[2]; + mailbox_send_cmd_async(&send_id, MBOX_RECONFIG_DATA, args, + 3U, CMD_INDIRECT); + + buffer->subblocks_sent++; + max_blocks--; + } + + return !max_blocks; +} + +static int intel_fpga_sdm_write_all(void) +{ + for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) + if (intel_fpga_sdm_write_buffer( + &fpga_config_buffers[current_buffer])) + break; + return 0; +} + +static uint32_t intel_mailbox_fpga_config_isdone(uint32_t query_type) +{ + uint32_t ret; + + if (query_type == 1) + ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS, false); + else + ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true); + + if (ret) { + if (ret == MBOX_CFGSTAT_STATE_CONFIG) + return INTEL_SIP_SMC_STATUS_BUSY; + else + return INTEL_SIP_SMC_STATUS_ERROR; + } + + if (query_type != 1) { + /* full reconfiguration */ + if (!is_partial_reconfig) + socfpga_bridges_enable(); /* Enable bridge */ + } + + return INTEL_SIP_SMC_STATUS_OK; +} + +static int mark_last_buffer_xfer_completed(uint32_t *buffer_addr_completed) +{ + int i; + + for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) { + if (fpga_config_buffers[i].block_number == current_block) { + fpga_config_buffers[i].subblocks_sent--; + if (fpga_config_buffers[i].subblocks_sent == 0 + && fpga_config_buffers[i].size <= + fpga_config_buffers[i].size_written) { + fpga_config_buffers[i].write_requested = 0; + current_block++; + *buffer_addr_completed = + fpga_config_buffers[i].addr; + return 0; + } + } + } + + return -1; +} + +static int intel_fpga_config_completed_write(uint32_t *completed_addr, + uint32_t *count, uint32_t *job_id) +{ + uint32_t resp[5]; + unsigned int resp_len = ARRAY_SIZE(resp); + int status = INTEL_SIP_SMC_STATUS_OK; + int all_completed = 1; + *count = 0; + + while (*count < 3) { + + status = mailbox_read_response(job_id, + resp, &resp_len); + + if (status < 0) { + break; + } + + max_blocks++; + + if (mark_last_buffer_xfer_completed( + &completed_addr[*count]) == 0) { + *count = *count + 1; + } else { + break; + } + } + + if (*count <= 0) { + if (status != MBOX_NO_RESPONSE && + status != MBOX_TIMEOUT && resp_len != 0) { + mailbox_clear_response(); + return INTEL_SIP_SMC_STATUS_ERROR; + } + + *count = 0; + } + + intel_fpga_sdm_write_all(); + + if (*count > 0) + status = INTEL_SIP_SMC_STATUS_OK; + else if (*count == 0) + status = INTEL_SIP_SMC_STATUS_BUSY; + + for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) { + if (fpga_config_buffers[i].write_requested != 0) { + all_completed = 0; + break; + } + } + + if (all_completed == 1) + return INTEL_SIP_SMC_STATUS_OK; + + return status; +} + +static int intel_fpga_config_start(uint32_t config_type) +{ + uint32_t argument = 0x1; + uint32_t response[3]; + int status = 0; + unsigned int size = 0; + unsigned int resp_len = ARRAY_SIZE(response); + + is_partial_reconfig = config_type; + + mailbox_clear_response(); + + mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_CANCEL, NULL, 0U, + CMD_CASUAL, NULL, NULL); + + status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RECONFIG, &argument, size, + CMD_CASUAL, response, &resp_len); + + if (status < 0) + return status; + + max_blocks = response[0]; + bytes_per_block = response[1]; + + for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) { + fpga_config_buffers[i].size = 0; + fpga_config_buffers[i].size_written = 0; + fpga_config_buffers[i].addr = 0; + fpga_config_buffers[i].write_requested = 0; + fpga_config_buffers[i].block_number = 0; + fpga_config_buffers[i].subblocks_sent = 0; + } + + blocks_submitted = 0; + current_block = 0; + read_block = 0; + current_buffer = 0; + + /* full reconfiguration */ + if (!is_partial_reconfig) { + /* Disable bridge */ + socfpga_bridges_disable(); + } + + return 0; +} + +static bool is_fpga_config_buffer_full(void) +{ + for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) + if (!fpga_config_buffers[i].write_requested) + return false; + return true; +} + +bool is_address_in_ddr_range(uint64_t addr, uint64_t size) +{ + if (!addr && !size) { + return true; + } + if (size > (UINT64_MAX - addr)) + return false; + if (addr < BL31_LIMIT) + return false; + if (addr + size > DRAM_BASE + DRAM_SIZE) + return false; + + return true; +} + +static uint32_t intel_fpga_config_write(uint64_t mem, uint64_t size) +{ + int i; + + intel_fpga_sdm_write_all(); + + if (!is_address_in_ddr_range(mem, size) || + is_fpga_config_buffer_full()) + return INTEL_SIP_SMC_STATUS_REJECTED; + + for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) { + int j = (i + current_buffer) % FPGA_CONFIG_BUFFER_SIZE; + + if (!fpga_config_buffers[j].write_requested) { + fpga_config_buffers[j].addr = mem; + fpga_config_buffers[j].size = size; + fpga_config_buffers[j].size_written = 0; + fpga_config_buffers[j].write_requested = 1; + fpga_config_buffers[j].block_number = + blocks_submitted++; + fpga_config_buffers[j].subblocks_sent = 0; + break; + } + } + + if (is_fpga_config_buffer_full()) + return INTEL_SIP_SMC_STATUS_BUSY; + + return INTEL_SIP_SMC_STATUS_OK; +} + +static int is_out_of_sec_range(uint64_t reg_addr) +{ + switch (reg_addr) { + case(0xF8011100): /* ECCCTRL1 */ + case(0xF8011104): /* ECCCTRL2 */ + case(0xF8011110): /* ERRINTEN */ + case(0xF8011114): /* ERRINTENS */ + case(0xF8011118): /* ERRINTENR */ + case(0xF801111C): /* INTMODE */ + case(0xF8011120): /* INTSTAT */ + case(0xF8011124): /* DIAGINTTEST */ + case(0xF801112C): /* DERRADDRA */ + case(0xFFD12028): /* SDMMCGRP_CTRL */ + case(0xFFD12044): /* EMAC0 */ + case(0xFFD12048): /* EMAC1 */ + case(0xFFD1204C): /* EMAC2 */ + case(0xFFD12090): /* ECC_INT_MASK_VALUE */ + case(0xFFD12094): /* ECC_INT_MASK_SET */ + case(0xFFD12098): /* ECC_INT_MASK_CLEAR */ + case(0xFFD1209C): /* ECC_INTSTATUS_SERR */ + case(0xFFD120A0): /* ECC_INTSTATUS_DERR */ + case(0xFFD120C0): /* NOC_TIMEOUT */ + case(0xFFD120C4): /* NOC_IDLEREQ_SET */ + case(0xFFD120C8): /* NOC_IDLEREQ_CLR */ + case(0xFFD120D0): /* NOC_IDLEACK */ + case(0xFFD120D4): /* NOC_IDLESTATUS */ + case(0xFFD12200): /* BOOT_SCRATCH_COLD0 */ + case(0xFFD12204): /* BOOT_SCRATCH_COLD1 */ + case(0xFFD12220): /* BOOT_SCRATCH_COLD8 */ + case(0xFFD12224): /* BOOT_SCRATCH_COLD9 */ + return 0; + + default: + break; + } + + return -1; +} + +/* Secure register access */ +uint32_t intel_secure_reg_read(uint64_t reg_addr, uint32_t *retval) +{ + if (is_out_of_sec_range(reg_addr)) + return INTEL_SIP_SMC_STATUS_ERROR; + + *retval = mmio_read_32(reg_addr); + + return INTEL_SIP_SMC_STATUS_OK; +} + +uint32_t intel_secure_reg_write(uint64_t reg_addr, uint32_t val, + uint32_t *retval) +{ + if (is_out_of_sec_range(reg_addr)) + return INTEL_SIP_SMC_STATUS_ERROR; + + mmio_write_32(reg_addr, val); + + return intel_secure_reg_read(reg_addr, retval); +} + +uint32_t intel_secure_reg_update(uint64_t reg_addr, uint32_t mask, + uint32_t val, uint32_t *retval) +{ + if (!intel_secure_reg_read(reg_addr, retval)) { + *retval &= ~mask; + *retval |= val & mask; + return intel_secure_reg_write(reg_addr, *retval, retval); + } + + return INTEL_SIP_SMC_STATUS_ERROR; +} + +/* Intel Remote System Update (RSU) services */ +uint64_t intel_rsu_update_address; + +static uint32_t intel_rsu_status(uint64_t *respbuf, unsigned int respbuf_sz) +{ + if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0) + return INTEL_SIP_SMC_RSU_ERROR; + + return INTEL_SIP_SMC_STATUS_OK; +} + +static uint32_t intel_rsu_update(uint64_t update_address) +{ + intel_rsu_update_address = update_address; + return INTEL_SIP_SMC_STATUS_OK; +} + +static uint32_t intel_rsu_notify(uint32_t execution_stage) +{ + if (mailbox_hps_stage_notify(execution_stage) < 0) + return INTEL_SIP_SMC_RSU_ERROR; + + return INTEL_SIP_SMC_STATUS_OK; +} + +static uint32_t intel_rsu_retry_counter(uint32_t *respbuf, uint32_t respbuf_sz, + uint32_t *ret_stat) +{ + if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0) + return INTEL_SIP_SMC_RSU_ERROR; + + *ret_stat = respbuf[8]; + return INTEL_SIP_SMC_STATUS_OK; +} + +/* Mailbox services */ +static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args, + unsigned int len, + uint32_t urgent, uint32_t *response, + unsigned int resp_len, int *mbox_status, + unsigned int *len_in_resp) +{ + *len_in_resp = 0; + *mbox_status = 0; + + if (!is_address_in_ddr_range((uint64_t)args, sizeof(uint32_t) * len)) + return INTEL_SIP_SMC_STATUS_REJECTED; + + int status = mailbox_send_cmd(MBOX_JOB_ID, cmd, args, len, urgent, + response, &resp_len); + + if (status < 0) { + *mbox_status = -status; + return INTEL_SIP_SMC_STATUS_ERROR; + } + + *mbox_status = 0; + *len_in_resp = resp_len; + return INTEL_SIP_SMC_STATUS_OK; +} + +/* + * This function is responsible for handling all SiP calls from the NS world + */ + +uintptr_t sip_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) +{ + uint32_t retval = 0; + uint32_t completed_addr[3]; + uint64_t rsu_respbuf[9]; + int status = INTEL_SIP_SMC_STATUS_OK; + int mbox_status; + unsigned int len_in_resp; + u_register_t x5, x6; + + switch (smc_fid) { + case SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, intl_svc_uid); + + case INTEL_SIP_SMC_FPGA_CONFIG_ISDONE: + status = intel_mailbox_fpga_config_isdone(x1); + SMC_RET4(handle, status, 0, 0, 0); + + case INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM: + SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK, + INTEL_SIP_SMC_FPGA_CONFIG_ADDR, + INTEL_SIP_SMC_FPGA_CONFIG_SIZE - + INTEL_SIP_SMC_FPGA_CONFIG_ADDR); + + case INTEL_SIP_SMC_FPGA_CONFIG_START: + status = intel_fpga_config_start(x1); + SMC_RET4(handle, status, 0, 0, 0); + + case INTEL_SIP_SMC_FPGA_CONFIG_WRITE: + status = intel_fpga_config_write(x1, x2); + SMC_RET4(handle, status, 0, 0, 0); + + case INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE: + status = intel_fpga_config_completed_write(completed_addr, + &retval, &rcv_id); + switch (retval) { + case 1: + SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, + completed_addr[0], 0, 0); + + case 2: + SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, + completed_addr[0], + completed_addr[1], 0); + + case 3: + SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, + completed_addr[0], + completed_addr[1], + completed_addr[2]); + + case 0: + SMC_RET4(handle, status, 0, 0, 0); + + default: + mailbox_clear_response(); + SMC_RET1(handle, INTEL_SIP_SMC_STATUS_ERROR); + } + + case INTEL_SIP_SMC_REG_READ: + status = intel_secure_reg_read(x1, &retval); + SMC_RET3(handle, status, retval, x1); + + case INTEL_SIP_SMC_REG_WRITE: + status = intel_secure_reg_write(x1, (uint32_t)x2, &retval); + SMC_RET3(handle, status, retval, x1); + + case INTEL_SIP_SMC_REG_UPDATE: + status = intel_secure_reg_update(x1, (uint32_t)x2, + (uint32_t)x3, &retval); + SMC_RET3(handle, status, retval, x1); + + case INTEL_SIP_SMC_RSU_STATUS: + status = intel_rsu_status(rsu_respbuf, + ARRAY_SIZE(rsu_respbuf)); + if (status) { + SMC_RET1(handle, status); + } else { + SMC_RET4(handle, rsu_respbuf[0], rsu_respbuf[1], + rsu_respbuf[2], rsu_respbuf[3]); + } + + case INTEL_SIP_SMC_RSU_UPDATE: + status = intel_rsu_update(x1); + SMC_RET1(handle, status); + + case INTEL_SIP_SMC_RSU_NOTIFY: + status = intel_rsu_notify(x1); + SMC_RET1(handle, status); + + case INTEL_SIP_SMC_RSU_RETRY_COUNTER: + status = intel_rsu_retry_counter((uint32_t *)rsu_respbuf, + ARRAY_SIZE(rsu_respbuf), &retval); + if (status) { + SMC_RET1(handle, status); + } else { + SMC_RET2(handle, status, retval); + } + + case INTEL_SIP_SMC_ECC_DBE: + status = intel_ecc_dbe_notification(x1); + SMC_RET1(handle, status); + + case INTEL_SIP_SMC_MBOX_SEND_CMD: + x5 = SMC_GET_GP(handle, CTX_GPREG_X5); + x6 = SMC_GET_GP(handle, CTX_GPREG_X6); + status = intel_mbox_send_cmd(x1, (uint32_t *)x2, x3, x4, + (uint32_t *)x5, x6, &mbox_status, + &len_in_resp); + SMC_RET3(handle, status, mbox_status, len_in_resp); + + default: + return socfpga_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + } +} + +DECLARE_RT_SVC( + socfpga_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + sip_smc_handler +); + +DECLARE_RT_SVC( + socfpga_sip_svc_std, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_YIELD, + NULL, + sip_smc_handler +); diff --git a/arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c new file mode 100644 index 0000000..a2f2c18 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socfpga_private.h" + +#define PLAT_FIP_BASE (0) +#define PLAT_FIP_MAX_SIZE (0x1000000) +#define PLAT_MMC_DATA_BASE (0xffe3c000) +#define PLAT_MMC_DATA_SIZE (0x2000) +#define PLAT_QSPI_DATA_BASE (0x3C00000) +#define PLAT_QSPI_DATA_SIZE (0x1000000) + + +static const io_dev_connector_t *fip_dev_con; +static const io_dev_connector_t *boot_dev_con; + +static uintptr_t fip_dev_handle; +static uintptr_t boot_dev_handle; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +uintptr_t a2_lba_offset; +const char a2[] = {0xa2, 0x0}; + +static const io_block_spec_t gpt_block_spec = { + .offset = 0, + .length = MMC_BLOCK_SIZE +}; + +static int check_fip(const uintptr_t spec); +static int check_dev(const uintptr_t spec); + +static io_block_dev_spec_t boot_dev_spec; +static int (*register_io_dev)(const io_dev_connector_t **); + +static io_block_spec_t fip_spec = { + .offset = PLAT_FIP_BASE, + .length = PLAT_FIP_MAX_SIZE, +}; + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &boot_dev_handle, + (uintptr_t)&fip_spec, + check_dev + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + check_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + check_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t) &bl33_uuid_spec, + check_fip + }, + [GPT_IMAGE_ID] = { + &boot_dev_handle, + (uintptr_t) &gpt_block_spec, + check_dev + }, +}; + +static int check_dev(const uintptr_t spec) +{ + int result; + uintptr_t local_handle; + + result = io_dev_init(boot_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(boot_dev_handle, spec, &local_handle); + if (result == 0) + io_close(local_handle); + } + return result; +} + +static int check_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) + io_close(local_image_handle); + } + return result; +} + +void socfpga_io_setup(int boot_source) +{ + int result; + + switch (boot_source) { + case BOOT_SOURCE_SDMMC: + register_io_dev = ®ister_io_dev_block; + boot_dev_spec.buffer.offset = PLAT_MMC_DATA_BASE; + boot_dev_spec.buffer.length = MMC_BLOCK_SIZE; + boot_dev_spec.ops.read = mmc_read_blocks; + boot_dev_spec.ops.write = mmc_write_blocks; + boot_dev_spec.block_size = MMC_BLOCK_SIZE; + break; + + case BOOT_SOURCE_QSPI: + register_io_dev = ®ister_io_dev_memmap; + fip_spec.offset = fip_spec.offset + PLAT_QSPI_DATA_BASE; + break; + + default: + ERROR("Unsupported boot source\n"); + panic(); + break; + } + + result = (*register_io_dev)(&boot_dev_con); + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + + result = io_dev_open(boot_dev_con, (uintptr_t)&boot_dev_spec, + &boot_dev_handle); + assert(result == 0); + + result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); + assert(result == 0); + + if (boot_source == BOOT_SOURCE_SDMMC) { + partition_init(GPT_IMAGE_ID); + fip_spec.offset = get_partition_entry(a2)->start; + } + + (void)result; +} + +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + assert(result == 0); + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return result; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c new file mode 100644 index 0000000..ca1a91e --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static const unsigned char plat_power_domain_tree_desc[] = {1, 4}; + +/******************************************************************************* + * This function returns the default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} + diff --git a/arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c new file mode 100644 index 0000000..2a8daa6 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccu/ncore_ccu.h" +#include "socfpga_mailbox.h" +#include "socfpga_private.h" + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + mmio_write_64(PLAT_SEC_ENTRY, 0); + + console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE, + &console); + /* + * Check params passed from BL31 should not be NULL, + */ + void *from_bl2 = (void *) arg0; + + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + + /* + * Copy BL32 (if populated by BL31) and BL33 entry point information. + * They are stored in Secure RAM, in BL31's address space. + */ + + if (params_from_bl2->h.type == PARAM_BL_PARAMS && + params_from_bl2->h.version >= VERSION_2) { + + bl_params_node_t *bl_params = params_from_bl2->head; + + while (bl_params != NULL) { + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + } else { + struct socfpga_bl31_params *arg_from_bl2 = + (struct socfpga_bl31_params *) from_bl2; + + assert(arg_from_bl2->h.type == PARAM_BL31); + assert(arg_from_bl2->h.version >= VERSION_1); + + bl32_image_ep_info = *arg_from_bl2->bl32_ep_info; + bl33_image_ep_info = *arg_from_bl2->bl33_ep_info; + } + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +static const interrupt_prop_t s10_interrupt_props[] = { + PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const gicv2_driver_data_t plat_gicv2_gic_data = { + .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE, + .gicc_base = PLAT_INTEL_SOCFPGA_GICC_BASE, + .interrupt_props = s10_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(s10_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + socfpga_delay_timer_init(); + + /* Initialize the gic cpu and distributor interfaces */ + gicv2_driver_init(&plat_gicv2_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + /* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */ + mmio_write_64(PLAT_CPU_RELEASE_ADDR, + (uint64_t)plat_secondary_cpus_bl31_entry); + + mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); + + ncore_enable_ocram_firewall(); +} + +const mmap_region_t plat_dm_mmap[] = { + MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, + MT_MEMORY | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, + MT_DEVICE | MT_RW | MT_NS), + {0} +}; + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_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), +#if USE_COHERENT_MEM + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_dm_mmap); + enable_mmu_el3(0); +} diff --git a/arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h b/arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h new file mode 100644 index 0000000..9186852 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SOCFPGA_DEF_H +#define PLAT_SOCFPGA_DEF_H + +#include + +/* Platform Setting */ +#define PLATFORM_MODEL PLAT_SOCFPGA_N5X +#define BOOT_SOURCE BOOT_SOURCE_SDMMC + +/* FPGA config helpers */ +#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x400000 +#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE 0x2000000 + +/* Register Mapping */ +#define SOCFPGA_MMC_REG_BASE U(0xff808000) + +#define SOCFPGA_RSTMGR_REG_BASE U(0xffd11000) +#define SOCFPGA_SYSMGR_REG_BASE U(0xffd12000) + +#define SOCFPGA_L4_PER_SCR_REG_BASE U(0xffd21000) +#define SOCFPGA_L4_SYS_SCR_REG_BASE U(0xffd21100) +#define SOCFPGA_SOC2FPGA_SCR_REG_BASE U(0xffd21200) +#define SOCFPGA_LWSOC2FPGA_SCR_REG_BASE U(0xffd21300) + +#endif /* PLAT_SOCFPGA_DEF_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/n5x/platform.mk b/arm-trusted-firmware/plat/intel/soc/n5x/platform.mk new file mode 100644 index 0000000..b72bcc4 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/n5x/platform.mk @@ -0,0 +1,52 @@ +# +# Copyright (c) 2020-2022, Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := \ + -Iplat/intel/soc/n5x/include/ \ + -Iplat/intel/soc/common/drivers/ \ + -Iplat/intel/soc/common/include/ + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk +DM_GICv2_SOURCES := \ + ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c + + +PLAT_BL_COMMON_SOURCES := \ + ${DM_GICv2_SOURCES} \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/intel/soc/common/aarch64/platform_common.c \ + plat/intel/soc/common/aarch64/plat_helpers.S \ + plat/intel/soc/common/socfpga_delay_timer.c \ + plat/intel/soc/common/drivers/ccu/ncore_ccu.c + +BL2_SOURCES += + +BL31_SOURCES += \ + drivers/arm/cci/cci.c \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/intel/soc/n5x/bl31_plat_setup.c \ + plat/intel/soc/common/socfpga_psci.c \ + plat/intel/soc/common/socfpga_sip_svc.c \ + plat/intel/soc/common/socfpga_topology.c \ + plat/intel/soc/common/sip/socfpga_sip_ecc.c \ + plat/intel/soc/common/sip/socfpga_sip_fcs.c \ + plat/intel/soc/common/soc/socfpga_mailbox.c \ + plat/intel/soc/common/soc/socfpga_reset_manager.c + +PROGRAMMABLE_RESET_ADDRESS := 0 +BL2_AT_EL3 := 1 +BL2_INV_DCACHE := 0 +MULTI_CONSOLE_API := 1 +SIMICS_BUILD := 0 +USE_COHERENT_MEM := 1 diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c new file mode 100644 index 0000000..a8026ea --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qspi/cadence_qspi.h" +#include "socfpga_emac.h" +#include "socfpga_handoff.h" +#include "socfpga_mailbox.h" +#include "socfpga_private.h" +#include "socfpga_reset_manager.h" +#include "socfpga_system_manager.h" +#include "s10_clock_manager.h" +#include "s10_memory_controller.h" +#include "s10_pinmux.h" +#include "wdt/watchdog.h" + +static struct mmc_device_info mmc_info; + +const mmap_region_t plat_stratix10_mmap[] = { + MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, + MT_MEMORY | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, + MT_DEVICE | MT_RW | MT_NS), + {0}, +}; + +boot_source_type boot_source = BOOT_SOURCE; + +void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1, + u_register_t x2, u_register_t x4) +{ + static console_t console; + handoff reverse_handoff_ptr; + + generic_delay_timer_init(); + + if (socfpga_get_handoff(&reverse_handoff_ptr)) + return; + config_pinmux(&reverse_handoff_ptr); + + config_clkmgr_handoff(&reverse_handoff_ptr); + enable_nonsecure_access(); + deassert_peripheral_reset(); + config_hps_hs_before_warm_reset(); + + watchdog_init(get_wdt_clk()); + + console_16550_register(PLAT_UART0_BASE, get_uart_clk(), PLAT_BAUDRATE, + &console); + + socfpga_emac_init(); + socfpga_delay_timer_init(); + init_hard_memory_controller(); + mailbox_init(); + + if (!intel_mailbox_is_fpga_not_ready()) + socfpga_bridges_enable(); +} + + +void bl2_el3_plat_arch_setup(void) +{ + + const mmap_region_t bl_regions[] = { + 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), +#if USE_COHERENT_MEM_BAR + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0}, + }; + + setup_page_tables(bl_regions, plat_stratix10_mmap); + + enable_mmu_el3(0); + + dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000, get_mmc_clk()); + + mmc_info.mmc_dev_type = MMC_IS_SD; + mmc_info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3; + + /* Request ownership and direct access to QSPI */ + mailbox_hps_qspi_enable(); + + switch (boot_source) { + case BOOT_SOURCE_SDMMC: + dw_mmc_init(¶ms, &mmc_info); + socfpga_io_setup(boot_source); + break; + + case BOOT_SOURCE_QSPI: + cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL, + QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS, + QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0); + socfpga_io_setup(boot_source); + break; + + default: + ERROR("Unsupported boot source\n"); + panic(); + break; + } +} + +uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + assert(bl_mem_params); + + switch (image_id) { + case BL33_IMAGE_ID: + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = get_spsr_for_bl33_entry(); + break; + default: + break; + } + + return 0; +} + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl2_platform_setup(void) +{ +} + diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c new file mode 100644 index 0000000..128a808 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socfpga_mailbox.h" +#include "socfpga_private.h" +#include "socfpga_reset_manager.h" +#include "socfpga_system_manager.h" +#include "s10_memory_controller.h" +#include "s10_pinmux.h" +#include "s10_clock_manager.h" + + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + mmio_write_64(PLAT_SEC_ENTRY, PLAT_SEC_WARM_ENTRY); + + console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE, + &console); + /* + * Check params passed from BL31 should not be NULL, + */ + void *from_bl2 = (void *) arg0; + + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + + /* + * Copy BL32 (if populated by BL31) and BL33 entry point information. + * They are stored in Secure RAM, in BL31's address space. + */ + + if (params_from_bl2->h.type == PARAM_BL_PARAMS && + params_from_bl2->h.version >= VERSION_2) { + + bl_params_node_t *bl_params = params_from_bl2->head; + + while (bl_params) { + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + } else { + struct socfpga_bl31_params *arg_from_bl2 = + (struct socfpga_bl31_params *) from_bl2; + + assert(arg_from_bl2->h.type == PARAM_BL31); + assert(arg_from_bl2->h.version >= VERSION_1); + + bl32_image_ep_info = *arg_from_bl2->bl32_ep_info; + bl33_image_ep_info = *arg_from_bl2->bl33_ep_info; + } + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +static const interrupt_prop_t s10_interrupt_props[] = { + PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const gicv2_driver_data_t plat_gicv2_gic_data = { + .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE, + .gicc_base = PLAT_INTEL_SOCFPGA_GICC_BASE, + .interrupt_props = s10_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(s10_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + socfpga_delay_timer_init(); + + /* Initialize the gic cpu and distributor interfaces */ + gicv2_driver_init(&plat_gicv2_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + /* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */ + mmio_write_64(PLAT_CPU_RELEASE_ADDR, + (uint64_t)plat_secondary_cpus_bl31_entry); + + mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); +} + +const mmap_region_t plat_stratix10_mmap[] = { + MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, + MT_MEMORY | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, + MT_DEVICE | MT_RW | MT_NS), + {0} +}; + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_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), +#if USE_COHERENT_MEM + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), +#endif + {0} + }; + + setup_page_tables(bl_regions, plat_stratix10_mmap); + enable_mmu_el3(0); +} + diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h new file mode 100644 index 0000000..acc700a --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CLOCKMANAGER_H__ +#define __CLOCKMANAGER_H__ + +#include "socfpga_handoff.h" + +#define ALT_CLKMGR 0xffd10000 + +#define ALT_CLKMGR_CTRL 0x0 +#define ALT_CLKMGR_STAT 0x4 +#define ALT_CLKMGR_INTRCLR 0x14 +#define ALT_CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK 0x00000004 +#define ALT_CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK 0x00000008 + +#define ALT_CLKMGR_CTRL_BOOTMODE_SET_MSK 0x00000001 +#define ALT_CLKMGR_STAT_BUSY_E_BUSY 0x1 +#define ALT_CLKMGR_STAT_BUSY(x) (((x) & 0x00000001) >> 0) +#define ALT_CLKMGR_STAT_MAINPLLLOCKED(x) (((x) & 0x00000100) >> 8) +#define ALT_CLKMGR_STAT_PERPLLLOCKED(x) (((x) & 0x00000200) >> 9) + +#define ALT_CLKMGR_MAINPLL 0xffd10030 +#define ALT_CLKMGR_MAINPLL_EN 0x0 +#define ALT_CLKMGR_MAINPLL_BYPASS 0xc +#define ALT_CLKMGR_MAINPLL_MPUCLK 0x18 +#define ALT_CLKMGR_MAINPLL_NOCCLK 0x1c +#define ALT_CLKMGR_MAINPLL_CNTR2CLK 0x20 +#define ALT_CLKMGR_MAINPLL_CNTR3CLK 0x24 +#define ALT_CLKMGR_MAINPLL_CNTR4CLK 0x28 +#define ALT_CLKMGR_MAINPLL_CNTR5CLK 0x2c +#define ALT_CLKMGR_MAINPLL_CNTR6CLK 0x30 +#define ALT_CLKMGR_MAINPLL_CNTR7CLK 0x34 +#define ALT_CLKMGR_MAINPLL_CNTR8CLK 0x38 +#define ALT_CLKMGR_MAINPLL_CNTR9CLK 0x3c +#define ALT_CLKMGR_MAINPLL_NOCDIV 0x40 +#define ALT_CLKMGR_MAINPLL_PLLGLOB 0x44 +#define ALT_CLKMGR_MAINPLL_FDBCK 0x48 +#define ALT_CLKMGR_MAINPLL_PLLC0 0x54 +#define ALT_CLKMGR_MAINPLL_PLLC1 0x58 +#define ALT_CLKMGR_MAINPLL_VCOCALIB 0x5c +#define ALT_CLKMGR_MAINPLL_EN_RESET 0x000000ff +#define ALT_CLKMGR_MAINPLL_FDBCK_MDIV(x) (((x) & 0xff000000) >> 24) +#define ALT_CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK 0x00000001 +#define ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8) +#define ALT_CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK 0x00000002 +#define ALT_CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000000ff) +#define ALT_CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(x) (((x) << 9) & 0x0001fe00) + +#define ALT_CLKMGR_PSRC(x) (((x) & 0x00030000) >> 16) +#define ALT_CLKMGR_SRC_MAIN 0 +#define ALT_CLKMGR_SRC_PER 1 + +#define ALT_CLKMGR_PLLGLOB_PSRC_EOSC1 0x0 +#define ALT_CLKMGR_PLLGLOB_PSRC_INTOSC 0x1 +#define ALT_CLKMGR_PLLGLOB_PSRC_F2S 0x2 + +#define ALT_CLKMGR_PERPLL 0xffd100a4 +#define ALT_CLKMGR_PERPLL_EN 0x0 +#define ALT_CLKMGR_PERPLL_BYPASS 0xc +#define ALT_CLKMGR_PERPLL_CNTR2CLK 0x18 +#define ALT_CLKMGR_PERPLL_CNTR3CLK 0x1c +#define ALT_CLKMGR_PERPLL_CNTR4CLK 0x20 +#define ALT_CLKMGR_PERPLL_CNTR5CLK 0x24 +#define ALT_CLKMGR_PERPLL_CNTR6CLK 0x28 +#define ALT_CLKMGR_PERPLL_CNTR7CLK 0x2c +#define ALT_CLKMGR_PERPLL_CNTR8CLK 0x30 +#define ALT_CLKMGR_PERPLL_CNTR9CLK 0x34 +#define ALT_CLKMGR_PERPLL_GPIODIV 0x3c +#define ALT_CLKMGR_PERPLL_EMACCTL 0x38 +#define ALT_CLKMGR_PERPLL_PLLGLOB 0x40 +#define ALT_CLKMGR_PERPLL_FDBCK 0x44 +#define ALT_CLKMGR_PERPLL_PLLC0 0x50 +#define ALT_CLKMGR_PERPLL_PLLC1 0x54 +#define ALT_CLKMGR_PERPLL_EN_RESET 0x00000fff +#define ALT_CLKMGR_PERPLL_FDBCK_MDIV(x) (((x) & 0xff000000) >> 24) +#define ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x) (((x) << 0) & 0x0000ffff) +#define ALT_CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK 0x00000001 +#define ALT_CLKMGR_PERPLL_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8) +#define ALT_CLKMGR_PERPLL_PLLGLOB_REFCLKDIV_SET(x) (((x) << 8) & 0x00003f00) +#define ALT_CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK 0x00000002 +#define ALT_CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000000ff) +#define ALT_CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(x) (((x) << 9) & 0x0001fe00) +#define ALT_CLKMGR_PERPLL_VCOCALIB 0x58 + +#define ALT_CLKMGR_INTOSC_HZ 460000000 + +void config_clkmgr_handoff(handoff *hoff_ptr); +uint32_t get_wdt_clk(void); +uint32_t get_uart_clk(void); +uint32_t get_mmc_clk(void); + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h new file mode 100644 index 0000000..155b279 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __S10_MEMORYCONTROLLER_H__ +#define __S10_MEMORYCONTROLLER_H__ + +#define S10_MPFE_IOHMC_REG_DRAMADDRW 0xf80100a8 +#define S10_MPFE_IOHMC_CTRLCFG0 0xf8010028 +#define S10_MPFE_IOHMC_CTRLCFG1 0xf801002c +#define S10_MPFE_IOHMC_DRAMADDRW 0xf80100a8 +#define S10_MPFE_IOHMC_DRAMTIMING0 0xf8010050 +#define S10_MPFE_IOHMC_CALTIMING0 0xf801007c +#define S10_MPFE_IOHMC_CALTIMING1 0xf8010080 +#define S10_MPFE_IOHMC_CALTIMING2 0xf8010084 +#define S10_MPFE_IOHMC_CALTIMING3 0xf8010088 +#define S10_MPFE_IOHMC_CALTIMING4 0xf801008c +#define S10_MPFE_IOHMC_CALTIMING9 0xf80100a0 +#define S10_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(x) (((x) & 0x000000ff) >> 0) +#define S10_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(value) \ + (((value) & 0x00000060) >> 5) + + +#define S10_MPFE_HMC_ADP_ECCCTRL1 0xf8011100 +#define S10_MPFE_HMC_ADP_ECCCTRL2 0xf8011104 +#define S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT 0xf8011218 +#define S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE 0x000000ff +#define S10_MPFE_HMC_ADP_RSTHANDSHAKECTRL 0xf8011214 + + +#define S10_MPFE_IOHMC_REG_CTRLCFG1 0xf801002c + +#define S10_MPFE_IOHMC_REG_NIOSRESERVE0_OFST 0xf8010110 + +#define IOHMC_DRAMADDRW_COL_ADDR_WIDTH(x) (((x) & 0x0000001f) >> 0) +#define IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(x) (((x) & 0x000003e0) >> 5) +#define IOHMC_DRAMADDRW_CS_ADDR_WIDTH(x) (((x) & 0x00070000) >> 16) +#define IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(x) (((x) & 0x0000c000) >> 14) +#define IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(x) (((x) & 0x00003c00) >> 10) + +#define S10_MPFE_DDR(x) (0xf8000000 + x) +#define S10_MPFE_HMC_ADP_DDRCALSTAT 0xf801100c +#define S10_MPFE_DDR_MAIN_SCHED 0xf8000400 +#define S10_MPFE_DDR_MAIN_SCHED_DDRCONF 0xf8000408 +#define S10_MPFE_DDR_MAIN_SCHED_DDRTIMING 0xf800040c +#define S10_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK 0x0000001f +#define S10_MPFE_DDR_MAIN_SCHED_DDRMODE 0xf8000410 +#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV 0xf800043c +#define S10_MPFE_DDR_MAIN_SCHED_READLATENCY 0xf8000414 +#define S10_MPFE_DDR_MAIN_SCHED_ACTIVATE 0xf8000438 +#define S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST 10 +#define S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST 4 +#define S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST 0 +#define S10_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(x) (((x) << 0) & 0x0000001f) +#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST 0 +#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK (BIT(0) | BIT(1)) +#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST 2 +#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK (BIT(2) | BIT(3)) +#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST 4 +#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK (BIT(4) | BIT(5)) + +#define S10_MPFE_HMC_ADP(x) (0xf8011000 + (x)) +#define S10_MPFE_HMC_ADP_HPSINTFCSEL 0xf8011210 +#define S10_MPFE_HMC_ADP_DDRIOCTRL 0xf8011008 +#define HMC_ADP_DDRIOCTRL 0x8 +#define HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0) +#define HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(x) (((x) & 0x00003e00) >> 9) +#define ADP_DRAMADDRWIDTH 0xe0 + +#define ACT_TO_ACT_DIFF_BANK(value) (((value) & 0x00fc0000) >> 18) +#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12) +#define ACT_TO_RDWR(value) (((value) & 0x0000003f) >> 0) +#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12) + +/* timing 2 */ +#define RD_TO_RD_DIFF_CHIP(value) (((value) & 0x00000fc0) >> 6) +#define RD_TO_WR_DIFF_CHIP(value) (((value) & 0x3f000000) >> 24) +#define RD_TO_WR(value) (((value) & 0x00fc0000) >> 18) +#define RD_TO_PCH(value) (((value) & 0x00000fc0) >> 6) + +/* timing 3 */ +#define CALTIMING3_WR_TO_RD_DIFF_CHIP(value) (((value) & 0x0003f000) >> 12) +#define CALTIMING3_WR_TO_RD(value) (((value) & 0x00000fc0) >> 6) + +/* timing 4 */ +#define PCH_TO_VALID(value) (((value) & 0x00000fc0) >> 6) + +#define DDRTIMING_BWRATIO_OFST 31 +#define DDRTIMING_WRTORD_OFST 26 +#define DDRTIMING_RDTOWR_OFST 21 +#define DDRTIMING_BURSTLEN_OFST 18 +#define DDRTIMING_WRTOMISS_OFST 12 +#define DDRTIMING_RDTOMISS_OFST 6 +#define DDRTIMING_ACTTOACT_OFST 0 + +#define ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0) + +#define DDRMODE_AUTOPRECHARGE_OFST 1 +#define DDRMODE_BWRATIOEXTENDED_OFST 0 + + +#define S10_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(x) (((x) & 0x0000007f) >> 0) +#define S10_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(x) (((x) & 0x0000000f) >> 0) + +#define S10_CCU_CPU0_MPRT_DDR 0xf7004400 +#define S10_CCU_CPU0_MPRT_MEM0 0xf70045c0 +#define S10_CCU_CPU0_MPRT_MEM1A 0xf70045e0 +#define S10_CCU_CPU0_MPRT_MEM1B 0xf7004600 +#define S10_CCU_CPU0_MPRT_MEM1C 0xf7004620 +#define S10_CCU_CPU0_MPRT_MEM1D 0xf7004640 +#define S10_CCU_CPU0_MPRT_MEM1E 0xf7004660 +#define S10_CCU_IOM_MPRT_MEM0 0xf7018560 +#define S10_CCU_IOM_MPRT_MEM1A 0xf7018580 +#define S10_CCU_IOM_MPRT_MEM1B 0xf70185a0 +#define S10_CCU_IOM_MPRT_MEM1C 0xf70185c0 +#define S10_CCU_IOM_MPRT_MEM1D 0xf70185e0 +#define S10_CCU_IOM_MPRT_MEM1E 0xf7018600 + +#define S10_NOC_FW_DDR_SCR 0xf8020100 +#define S10_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT 0xf802011c +#define S10_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT 0xf8020118 +#define S10_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT 0xf802019c +#define S10_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT 0xf8020198 + +#define S10_SOC_NOC_FW_DDR_SCR_ENABLE 0xf8020100 +#define S10_CCU_NOC_DI_SET_MSK 0x10 + +#define S10_SYSMGR_CORE_HMC_CLK 0xffd120b4 +#define S10_SYSMGR_CORE_HMC_CLK_STATUS 0x00000001 + +#define S10_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0(x) (((x) & 0x0000ffff) >> 0) +#define S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_MSK 0x00000003 +#define S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_OFST 0 +#define S10_MPFE_HMC_ADP_HPSINTFCSEL_ENABLE 0x001f1f1f +#define S10_IOHMC_CTRLCFG1_ENABLE_ECC_OFST 7 + +#define S10_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK 0x00010000 +#define S10_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK 0x00000100 +#define S10_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK 0x00000001 + +#define S10_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK 0x00000001 +#define S10_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK 0x00010000 +#define S10_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK 0x00000100 +#define S10_MPFE_HMC_ADP_DDRCALSTAT_CAL(value) (((value) & 0x00000001) >> 0) + + +#define S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0) +#define IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(x) (((x) & 0x00003c00) >> 10) +#define IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(x) (((x) & 0x0000c000) >> 14) +#define IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(x) (((x) & 0x0000001f) >> 0) +#define IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(x) (((x) & 0x00070000) >> 16) +#define IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(x) (((x) & 0x000003e0) >> 5) + +#define S10_SDRAM_0_LB_ADDR 0x0 + +int init_hard_memory_controller(void); + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h new file mode 100644 index 0000000..3e1e527 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define AXI_AP (1<<0) +#define FPGA2SOC (1<<16) +#define MPU (1<<24) +#define S10_NOC_PER_SCR_NAND 0xffd21000 +#define S10_NOC_PER_SCR_NAND_DATA 0xffd21004 +#define S10_NOC_PER_SCR_USB0 0xffd2100c +#define S10_NOC_PER_SCR_USB1 0xffd21010 +#define S10_NOC_PER_SCR_SPI_M0 0xffd2101c +#define S10_NOC_PER_SCR_SPI_M1 0xffd21020 +#define S10_NOC_PER_SCR_SPI_S0 0xffd21024 +#define S10_NOC_PER_SCR_SPI_S1 0xffd21028 +#define S10_NOC_PER_SCR_EMAC0 0xffd2102c +#define S10_NOC_PER_SCR_EMAC1 0xffd21030 +#define S10_NOC_PER_SCR_EMAC2 0xffd21034 +#define S10_NOC_PER_SCR_SDMMC 0xffd21040 +#define S10_NOC_PER_SCR_GPIO0 0xffd21044 +#define S10_NOC_PER_SCR_GPIO1 0xffd21048 +#define S10_NOC_PER_SCR_I2C0 0xffd21050 +#define S10_NOC_PER_SCR_I2C1 0xffd21058 +#define S10_NOC_PER_SCR_I2C2 0xffd2105c +#define S10_NOC_PER_SCR_I2C3 0xffd21060 +#define S10_NOC_PER_SCR_SP_TIMER0 0xffd21064 +#define S10_NOC_PER_SCR_SP_TIMER1 0xffd21068 +#define S10_NOC_PER_SCR_UART0 0xffd2106c +#define S10_NOC_PER_SCR_UART1 0xffd21070 + + +#define S10_NOC_SYS_SCR_DMA_ECC 0xffd21108 +#define S10_NOC_SYS_SCR_EMAC0RX_ECC 0xffd2110c +#define S10_NOC_SYS_SCR_EMAC0TX_ECC 0xffd21110 +#define S10_NOC_SYS_SCR_EMAC1RX_ECC 0xffd21114 +#define S10_NOC_SYS_SCR_EMAC1TX_ECC 0xffd21118 +#define S10_NOC_SYS_SCR_EMAC2RX_ECC 0xffd2111c +#define S10_NOC_SYS_SCR_EMAC2TX_ECC 0xffd21120 +#define S10_NOC_SYS_SCR_NAND_ECC 0xffd2112c +#define S10_NOC_SYS_SCR_NAND_READ_ECC 0xffd21130 +#define S10_NOC_SYS_SCR_NAND_WRITE_ECC 0xffd21134 +#define S10_NOC_SYS_SCR_OCRAM_ECC 0xffd21138 +#define S10_NOC_SYS_SCR_SDMMC_ECC 0xffd21140 +#define S10_NOC_SYS_SCR_USB0_ECC 0xffd21144 +#define S10_NOC_SYS_SCR_USB1_ECC 0xffd21148 +#define S10_NOC_SYS_SCR_CLK_MGR 0xffd2114c +#define S10_NOC_SYS_SCR_IO_MGR 0xffd21154 +#define S10_NOC_SYS_SCR_RST_MGR 0xffd21158 +#define S10_NOC_SYS_SCR_SYS_MGR 0xffd2115c +#define S10_NOC_SYS_SCR_OSC0_TIMER 0xffd21160 +#define S10_NOC_SYS_SCR_OSC1_TIMER 0xffd21164 +#define S10_NOC_SYS_SCR_WATCHDOG0 0xffd21168 +#define S10_NOC_SYS_SCR_WATCHDOG1 0xffd2116c +#define S10_NOC_SYS_SCR_WATCHDOG2 0xffd21170 +#define S10_NOC_SYS_SCR_WATCHDOG3 0xffd21174 +#define S10_NOC_SYS_SCR_DAP 0xffd21178 +#define S10_NOC_SYS_SCR_L4_NOC_PROBES 0xffd21190 +#define S10_NOC_SYS_SCR_L4_NOC_QOS 0xffd21194 + +#define S10_CCU_NOC_BRIDGE_CPU0_RAM 0xf7004688 +#define S10_CCU_NOC_BRIDGE_IOM_RAM 0xf7004688 diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h new file mode 100644 index 0000000..82367d7 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __S10_PINMUX_H__ +#define __S10_PINMUX_H__ + +#define S10_PINMUX_PIN0SEL 0xffd13000 +#define S10_PINMUX_IO0CTRL 0xffd13130 +#define S10_PINMUX_PINMUX_EMAC0_USEFPGA 0xffd13300 +#define S10_PINMUX_IO0_DELAY 0xffd13400 + +#include "socfpga_handoff.h" + +void config_pinmux(handoff *handoff); + +#endif + diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h new file mode 100644 index 0000000..b84a567 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SOCFPGA_DEF_H +#define PLAT_SOCFPGA_DEF_H + +#include + +/* Platform Setting */ +#define PLATFORM_MODEL PLAT_SOCFPGA_STRATIX10 +#define BOOT_SOURCE BOOT_SOURCE_SDMMC + +/* FPGA config helpers */ +#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x400000 +#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE 0x1000000 + +/* Register Mapping */ +#define SOCFPGA_MMC_REG_BASE 0xff808000 + +#define SOCFPGA_RSTMGR_REG_BASE 0xffd11000 +#define SOCFPGA_SYSMGR_REG_BASE 0xffd12000 + +#define SOCFPGA_L4_PER_SCR_REG_BASE 0xffd21000 +#define SOCFPGA_L4_SYS_SCR_REG_BASE 0xffd21100 +#define SOCFPGA_SOC2FPGA_SCR_REG_BASE 0xffd21200 +#define SOCFPGA_LWSOC2FPGA_SCR_REG_BASE 0xffd21300 + + +#endif /* PLATSOCFPGA_DEF_H */ + diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/platform.mk b/arm-trusted-firmware/plat/intel/soc/stratix10/platform.mk new file mode 100644 index 0000000..d9d88d4 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/platform.mk @@ -0,0 +1,74 @@ +# +# Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2019-2022, Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := \ + -Iplat/intel/soc/stratix10/include/ \ + -Iplat/intel/soc/common/drivers/ \ + -Iplat/intel/soc/common/include/ + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk +AGX_GICv2_SOURCES := \ + ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c + + +PLAT_BL_COMMON_SOURCES := \ + ${AGX_GICv2_SOURCES} \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/intel/soc/common/aarch64/platform_common.c \ + plat/intel/soc/common/aarch64/plat_helpers.S \ + plat/intel/soc/common/socfpga_delay_timer.c + +BL2_SOURCES += \ + common/desc_image_load.c \ + drivers/mmc/mmc.c \ + drivers/intel/soc/stratix10/io/s10_memmap_qspi.c \ + drivers/io/io_storage.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/partition/partition.c \ + drivers/partition/gpt.c \ + drivers/synopsys/emmc/dw_mmc.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/intel/soc/stratix10/bl2_plat_setup.c \ + plat/intel/soc/stratix10/soc/s10_clock_manager.c \ + plat/intel/soc/stratix10/soc/s10_memory_controller.c \ + plat/intel/soc/stratix10/soc/s10_pinmux.c \ + plat/intel/soc/common/bl2_plat_mem_params_desc.c \ + plat/intel/soc/common/socfpga_image_load.c \ + plat/intel/soc/common/socfpga_storage.c \ + plat/intel/soc/common/soc/socfpga_emac.c \ + plat/intel/soc/common/soc/socfpga_handoff.c \ + plat/intel/soc/common/soc/socfpga_mailbox.c \ + plat/intel/soc/common/soc/socfpga_reset_manager.c \ + plat/intel/soc/common/soc/socfpga_system_manager.c \ + plat/intel/soc/common/drivers/qspi/cadence_qspi.c \ + plat/intel/soc/common/drivers/wdt/watchdog.c + +BL31_SOURCES += \ + drivers/arm/cci/cci.c \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/intel/soc/stratix10/bl31_plat_setup.c \ + plat/intel/soc/common/socfpga_psci.c \ + plat/intel/soc/common/socfpga_sip_svc.c \ + plat/intel/soc/common/socfpga_topology.c \ + plat/intel/soc/common/sip/socfpga_sip_ecc.c \ + plat/intel/soc/common/sip/socfpga_sip_fcs.c \ + plat/intel/soc/common/soc/socfpga_mailbox.c \ + plat/intel/soc/common/soc/socfpga_reset_manager.c + +PROGRAMMABLE_RESET_ADDRESS := 0 +BL2_AT_EL3 := 1 +SIMICS_BUILD := 0 +USE_COHERENT_MEM := 1 diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c new file mode 100644 index 0000000..1e092de --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "s10_clock_manager.h" +#include "socfpga_handoff.h" +#include "socfpga_system_manager.h" + + +void wait_pll_lock(void) +{ + uint32_t data; + + do { + data = mmio_read_32(ALT_CLKMGR + ALT_CLKMGR_STAT); + } while ((ALT_CLKMGR_STAT_MAINPLLLOCKED(data) == 0) || + (ALT_CLKMGR_STAT_PERPLLLOCKED(data) == 0)); +} + +void wait_fsm(void) +{ + uint32_t data; + + do { + data = mmio_read_32(ALT_CLKMGR + ALT_CLKMGR_STAT); + } while (ALT_CLKMGR_STAT_BUSY(data) == ALT_CLKMGR_STAT_BUSY_E_BUSY); +} + +void config_clkmgr_handoff(handoff *hoff_ptr) +{ + uint32_t m_div, refclk_div, mscnt, hscnt; + + /* Bypass all mainpllgrp's clocks */ + mmio_write_32(ALT_CLKMGR_MAINPLL + + ALT_CLKMGR_MAINPLL_BYPASS, + 0x7); + wait_fsm(); + /* Bypass all perpllgrp's clocks */ + mmio_write_32(ALT_CLKMGR_PERPLL + + ALT_CLKMGR_PERPLL_BYPASS, + 0x7f); + wait_fsm(); + + /* Setup main PLL dividers */ + m_div = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(hoff_ptr->main_pll_fdbck); + refclk_div = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV( + hoff_ptr->main_pll_pllglob); + mscnt = 200 / ((6 + m_div) / refclk_div); + hscnt = (m_div + 6) * mscnt / refclk_div - 9; + + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB, + hoff_ptr->main_pll_pllglob); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK, + hoff_ptr->main_pll_fdbck); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_VCOCALIB, + ALT_CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(hscnt) | + ALT_CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(mscnt)); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC0, + hoff_ptr->main_pll_pllc0); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC1, + hoff_ptr->main_pll_pllc1); + + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCDIV, + hoff_ptr->main_pll_nocdiv); + + /* Setup peripheral PLL dividers */ + m_div = ALT_CLKMGR_PERPLL_FDBCK_MDIV(hoff_ptr->per_pll_fdbck); + refclk_div = ALT_CLKMGR_PERPLL_PLLGLOB_REFCLKDIV( + hoff_ptr->per_pll_pllglob); + mscnt = 200 / ((6 + m_div) / refclk_div); + hscnt = (m_div + 6) * mscnt / refclk_div - 9; + + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB, + hoff_ptr->per_pll_pllglob); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_FDBCK, + hoff_ptr->per_pll_fdbck); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_VCOCALIB, + ALT_CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(hscnt) | + ALT_CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(mscnt)); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC0, + hoff_ptr->per_pll_pllc0); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC1, + hoff_ptr->per_pll_pllc1); + + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_GPIODIV, + ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET( + hoff_ptr->per_pll_gpiodiv)); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EMACCTL, + hoff_ptr->per_pll_emacctl); + + + /* Take both PLL out of reset and power up */ + mmio_setbits_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB, + ALT_CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK | + ALT_CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK); + mmio_setbits_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB, + ALT_CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK | + ALT_CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK); + + wait_pll_lock(); + + /* Dividers for C2 to C9 only init after PLLs are lock. */ + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_MPUCLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR2CLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR3CLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR4CLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR5CLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR7CLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR8CLK, 0xff); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR9CLK, 0xff); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR2CLK, 0xff); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR3CLK, 0xff); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR4CLK, 0xff); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR5CLK, 0xff); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR6CLK, 0xff); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR7CLK, 0xff); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR8CLK, 0xff); + + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_MPUCLK, + hoff_ptr->main_pll_mpuclk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK, + hoff_ptr->main_pll_nocclk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR2CLK, + hoff_ptr->main_pll_cntr2clk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR3CLK, + hoff_ptr->main_pll_cntr3clk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR4CLK, + hoff_ptr->main_pll_cntr4clk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR5CLK, + hoff_ptr->main_pll_cntr5clk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK, + hoff_ptr->main_pll_cntr6clk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR7CLK, + hoff_ptr->main_pll_cntr7clk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR8CLK, + hoff_ptr->main_pll_cntr8clk); + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR9CLK, + hoff_ptr->main_pll_cntr9clk); + + /* Peripheral PLL Clock Source and Counters/Divider */ + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR2CLK, + hoff_ptr->per_pll_cntr2clk); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR3CLK, + hoff_ptr->per_pll_cntr3clk); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR4CLK, + hoff_ptr->per_pll_cntr4clk); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR5CLK, + hoff_ptr->per_pll_cntr5clk); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR6CLK, + hoff_ptr->per_pll_cntr6clk); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR7CLK, + hoff_ptr->per_pll_cntr7clk); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR8CLK, + hoff_ptr->per_pll_cntr8clk); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR9CLK, + hoff_ptr->per_pll_cntr9clk); + + /* Take all PLLs out of bypass */ + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_BYPASS, 0); + wait_fsm(); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_BYPASS, 0); + wait_fsm(); + + /* Set safe mode/ out of boot mode */ + mmio_clrbits_32(ALT_CLKMGR + ALT_CLKMGR_CTRL, + ALT_CLKMGR_CTRL_BOOTMODE_SET_MSK); + wait_fsm(); + + /* 10 Enable mainpllgrp's software-managed clock */ + mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_EN, + ALT_CLKMGR_MAINPLL_EN_RESET); + mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EN, + ALT_CLKMGR_PERPLL_EN_RESET); + + /* Clear loss lock interrupt status register that */ + /* might be set during configuration */ + mmio_write_32(ALT_CLKMGR + ALT_CLKMGR_INTRCLR, + ALT_CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK | + ALT_CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK); + + /* Pass clock source frequency into scratch register */ + mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1), + hoff_ptr->hps_osc_clk_h); + mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2), + hoff_ptr->fpga_clk_hz); + +} + +/* Extract reference clock from platform clock source */ +uint32_t get_ref_clk(uint32_t pllglob) +{ + uint32_t data32, mdiv, refclkdiv, ref_clk; + uint32_t scr_reg; + + switch (ALT_CLKMGR_PSRC(pllglob)) { + case ALT_CLKMGR_PLLGLOB_PSRC_EOSC1: + scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1); + ref_clk = mmio_read_32(scr_reg); + break; + case ALT_CLKMGR_PLLGLOB_PSRC_INTOSC: + ref_clk = ALT_CLKMGR_INTOSC_HZ; + break; + case ALT_CLKMGR_PLLGLOB_PSRC_F2S: + scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2); + ref_clk = mmio_read_32(scr_reg); + break; + default: + ref_clk = 0; + assert(0); + break; + } + + refclkdiv = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(pllglob); + data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK); + mdiv = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(data32); + + ref_clk = (ref_clk / refclkdiv) * (6 + mdiv); + + return ref_clk; +} + +/* Calculate L3 interconnect main clock */ +uint32_t get_l3_clk(uint32_t ref_clk) +{ + uint32_t noc_base_clk, l3_clk, noc_clk, data32; + uint32_t pllc1_reg; + + noc_clk = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK); + + switch (ALT_CLKMGR_PSRC(noc_clk)) { + case ALT_CLKMGR_SRC_MAIN: + pllc1_reg = ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC1; + break; + case ALT_CLKMGR_SRC_PER: + pllc1_reg = ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC1; + break; + default: + pllc1_reg = 0; + assert(0); + break; + } + + data32 = mmio_read_32(pllc1_reg); + noc_base_clk = ref_clk / (data32 & 0xff); + l3_clk = noc_base_clk / (noc_clk + 1); + + return l3_clk; +} + +/* Calculate clock frequency to be used for watchdog timer */ +uint32_t get_wdt_clk(void) +{ + uint32_t data32, ref_clk, l3_clk, l4_sys_clk; + + data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB); + ref_clk = get_ref_clk(data32); + + l3_clk = get_l3_clk(ref_clk); + + l4_sys_clk = l3_clk / 4; + + return l4_sys_clk; +} + +/* Calculate clock frequency to be used for UART driver */ +uint32_t get_uart_clk(void) +{ + uint32_t data32, ref_clk, l3_clk, l4_sp_clk; + + data32 = mmio_read_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB); + ref_clk = get_ref_clk(data32); + + l3_clk = get_l3_clk(ref_clk); + + data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCDIV); + data32 = (data32 >> 16) & 0x3; + data32 = 1 << data32; + + l4_sp_clk = (l3_clk / data32); + + return l4_sp_clk; +} + +/* Calculate clock frequency to be used for SDMMC driver */ +uint32_t get_mmc_clk(void) +{ + uint32_t data32, ref_clk, l3_clk, mmc_clk; + + data32 = mmio_read_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB); + ref_clk = get_ref_clk(data32); + + l3_clk = get_l3_clk(ref_clk); + + data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK); + mmc_clk = (l3_clk / (data32 + 1)) / 4; + + return mmc_clk; +} diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c new file mode 100644 index 0000000..ac756ab --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "s10_memory_controller.h" +#include "socfpga_reset_manager.h" + +#define ALT_CCU_NOC_DI_SET_MSK 0x10 + +#define DDR_READ_LATENCY_DELAY 40 +#define MAX_MEM_CAL_RETRY 3 +#define PRE_CALIBRATION_DELAY 1 +#define POST_CALIBRATION_DELAY 1 +#define TIMEOUT_EMIF_CALIBRATION 1000 +#define CLEAR_EMIF_DELAY 1000 +#define CLEAR_EMIF_TIMEOUT 1000 + +#define DDR_CONFIG(A, B, C, R) (((A) << 24) | ((B) << 16) | ((C) << 8) | (R)) +#define DDR_CONFIG_ELEMENTS (sizeof(ddr_config)/sizeof(uint32_t)) + +/* tWR = Min. 15ns constant, see JEDEC standard eg. DDR4 is JESD79-4.pdf */ +#define tWR_IN_NS 15 + +void configure_hmc_adaptor_regs(void); +void configure_ddr_sched_ctrl_regs(void); + +/* The followring are the supported configurations */ +uint32_t ddr_config[] = { + /* DDR_CONFIG(Address order,Bank,Column,Row) */ + /* List for DDR3 or LPDDR3 (pinout order > chip, row, bank, column) */ + DDR_CONFIG(0, 3, 10, 12), + DDR_CONFIG(0, 3, 9, 13), + DDR_CONFIG(0, 3, 10, 13), + DDR_CONFIG(0, 3, 9, 14), + DDR_CONFIG(0, 3, 10, 14), + DDR_CONFIG(0, 3, 10, 15), + DDR_CONFIG(0, 3, 11, 14), + DDR_CONFIG(0, 3, 11, 15), + DDR_CONFIG(0, 3, 10, 16), + DDR_CONFIG(0, 3, 11, 16), + DDR_CONFIG(0, 3, 12, 15), /* 0xa */ + /* List for DDR4 only (pinout order > chip, bank, row, column) */ + DDR_CONFIG(1, 3, 10, 14), + DDR_CONFIG(1, 4, 10, 14), + DDR_CONFIG(1, 3, 10, 15), + DDR_CONFIG(1, 4, 10, 15), + DDR_CONFIG(1, 3, 10, 16), + DDR_CONFIG(1, 4, 10, 16), + DDR_CONFIG(1, 3, 10, 17), + DDR_CONFIG(1, 4, 10, 17), +}; + +static int match_ddr_conf(uint32_t ddr_conf) +{ + int i; + + for (i = 0; i < DDR_CONFIG_ELEMENTS; i++) { + if (ddr_conf == ddr_config[i]) + return i; + } + return 0; +} + +static int check_hmc_clk(void) +{ + unsigned long timeout = 0; + uint32_t hmc_clk; + + do { + hmc_clk = mmio_read_32(S10_SYSMGR_CORE_HMC_CLK); + if (hmc_clk & S10_SYSMGR_CORE_HMC_CLK_STATUS) + break; + udelay(1); + } while (++timeout < 1000); + if (timeout >= 1000) + return -ETIMEDOUT; + + return 0; +} + +static int clear_emif(void) +{ + uint32_t data; + unsigned long timeout; + + mmio_write_32(S10_MPFE_HMC_ADP_RSTHANDSHAKECTRL, 0); + + timeout = 0; + do { + data = mmio_read_32(S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT); + if ((data & S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE) == 0) + break; + udelay(CLEAR_EMIF_DELAY); + } while (++timeout < CLEAR_EMIF_TIMEOUT); + if (timeout >= CLEAR_EMIF_TIMEOUT) + return -ETIMEDOUT; + + return 0; +} + +static int mem_calibration(void) +{ + int status = 0; + uint32_t data; + unsigned long timeout; + unsigned long retry = 0; + + udelay(PRE_CALIBRATION_DELAY); + + do { + if (retry != 0) + INFO("DDR: Retrying DRAM calibration\n"); + + timeout = 0; + do { + data = mmio_read_32(S10_MPFE_HMC_ADP_DDRCALSTAT); + if (S10_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 1) + break; + udelay(500); + } while (++timeout < TIMEOUT_EMIF_CALIBRATION); + + if (S10_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) { + status = clear_emif(); + if (status) + ERROR("Failed to clear Emif\n"); + } else { + break; + } + } while (++retry < MAX_MEM_CAL_RETRY); + + if (S10_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) { + ERROR("DDR: DRAM calibration failed.\n"); + status = -EIO; + } else { + INFO("DDR: DRAM calibration success.\n"); + status = 0; + } + + udelay(POST_CALIBRATION_DELAY); + + return status; +} + +int init_hard_memory_controller(void) +{ + int status; + + mmio_clrbits_32(S10_CCU_CPU0_MPRT_DDR, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM0, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1A, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1B, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1C, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1D, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1E, S10_CCU_NOC_DI_SET_MSK); + + mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM0, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1A, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1B, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1C, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1D, S10_CCU_NOC_DI_SET_MSK); + mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1E, S10_CCU_NOC_DI_SET_MSK); + + mmio_write_32(S10_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT, 0xFFFF0000); + mmio_write_32(S10_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT, 0x1F); + + mmio_write_32(S10_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT, 0xFFFF0000); + mmio_write_32(S10_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT, 0x1F); + mmio_write_32(S10_SOC_NOC_FW_DDR_SCR_ENABLE, BIT(0) | BIT(8)); + + status = check_hmc_clk(); + if (status) { + ERROR("DDR: Error, HMC clock not running\n"); + return status; + } + + mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST), RSTMGR_FIELD(BRG, DDRSCH)); + + status = mem_calibration(); + if (status) { + ERROR("DDR: Memory Calibration Failed\n"); + return status; + } + + configure_hmc_adaptor_regs(); + configure_ddr_sched_ctrl_regs(); + + return 0; +} + +void configure_ddr_sched_ctrl_regs(void) +{ + uint32_t data, dram_addr_order, ddr_conf, bank, row, col, + rd_to_miss, wr_to_miss, burst_len, burst_len_ddr_clk, + burst_len_sched_clk, act_to_act, rd_to_wr, wr_to_rd, bw_ratio, + t_rtp, t_rp, t_rcd, rd_latency, tw_rin_clk_cycles, + bw_ratio_extended, auto_precharge = 0, act_to_act_bank, faw, + faw_bank, bus_rd_to_rd, bus_rd_to_wr, bus_wr_to_rd; + + INFO("Init HPS NOC's DDR Scheduler.\n"); + + data = mmio_read_32(S10_MPFE_IOHMC_CTRLCFG1); + dram_addr_order = S10_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(data); + + data = mmio_read_32(S10_MPFE_IOHMC_DRAMADDRW); + + col = IOHMC_DRAMADDRW_COL_ADDR_WIDTH(data); + row = IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(data); + bank = IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(data); + + ddr_conf = match_ddr_conf(DDR_CONFIG(dram_addr_order, bank, col, row)); + + if (ddr_conf) { + mmio_clrsetbits_32( + S10_MPFE_DDR_MAIN_SCHED_DDRCONF, + S10_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK, + S10_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(ddr_conf)); + } else { + ERROR("DDR: Cannot find predefined ddrConf configuration.\n"); + } + + mmio_write_32(S10_MPFE_HMC_ADP(ADP_DRAMADDRWIDTH), data); + + data = mmio_read_32(S10_MPFE_IOHMC_DRAMTIMING0); + rd_latency = S10_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(data); + + data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING0); + act_to_act = ACT_TO_ACT(data); + t_rcd = ACT_TO_RDWR(data); + act_to_act_bank = ACT_TO_ACT_DIFF_BANK(data); + + data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING1); + rd_to_wr = RD_TO_WR(data); + bus_rd_to_rd = RD_TO_RD_DIFF_CHIP(data); + bus_rd_to_wr = RD_TO_WR_DIFF_CHIP(data); + + data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING2); + t_rtp = RD_TO_PCH(data); + + data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING3); + wr_to_rd = CALTIMING3_WR_TO_RD(data); + bus_wr_to_rd = CALTIMING3_WR_TO_RD_DIFF_CHIP(data); + + data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING4); + t_rp = PCH_TO_VALID(data); + + data = mmio_read_32(S10_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL)); + bw_ratio = ((HMC_ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 0 : 1); + + data = mmio_read_32(S10_MPFE_IOHMC_CTRLCFG0); + burst_len = HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(data); + burst_len_ddr_clk = burst_len / 2; + burst_len_sched_clk = ((burst_len/2) / 2); + + data = mmio_read_32(S10_MPFE_IOHMC_CTRLCFG0); + switch (S10_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(data)) { + case 1: + /* DDR4 - 1333MHz */ + /* 20 (19.995) clock cycles = 15ns */ + /* Calculate with rounding */ + tw_rin_clk_cycles = (((tWR_IN_NS * 1333) % 1000) >= 500) ? + ((tWR_IN_NS * 1333) / 1000) + 1 : + ((tWR_IN_NS * 1333) / 1000); + break; + default: + /* Others - 1066MHz or slower */ + /* 16 (15.990) clock cycles = 15ns */ + /* Calculate with rounding */ + tw_rin_clk_cycles = (((tWR_IN_NS * 1066) % 1000) >= 500) ? + ((tWR_IN_NS * 1066) / 1000) + 1 : + ((tWR_IN_NS * 1066) / 1000); + break; + } + + rd_to_miss = t_rtp + t_rp + t_rcd - burst_len_sched_clk; + wr_to_miss = ((rd_latency + burst_len_ddr_clk + 2 + tw_rin_clk_cycles) + / 2) - rd_to_wr + t_rp + t_rcd; + + mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_DDRTIMING, + bw_ratio << DDRTIMING_BWRATIO_OFST | + wr_to_rd << DDRTIMING_WRTORD_OFST| + rd_to_wr << DDRTIMING_RDTOWR_OFST | + burst_len_sched_clk << DDRTIMING_BURSTLEN_OFST | + wr_to_miss << DDRTIMING_WRTOMISS_OFST | + rd_to_miss << DDRTIMING_RDTOMISS_OFST | + act_to_act << DDRTIMING_ACTTOACT_OFST); + + data = mmio_read_32(S10_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL)); + bw_ratio_extended = ((ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 1 : 0); + + mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_DDRMODE, + bw_ratio_extended << DDRMODE_BWRATIOEXTENDED_OFST | + auto_precharge << DDRMODE_AUTOPRECHARGE_OFST); + + mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_READLATENCY, + (rd_latency / 2) + DDR_READ_LATENCY_DELAY); + + data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING9); + faw = S10_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(data); + + faw_bank = 1; // always 1 because we always have 4 bank DDR. + + mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_ACTIVATE, + faw_bank << S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST | + faw << S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST | + act_to_act_bank << S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST); + + mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_DEVTODEV, + ((bus_rd_to_rd + << S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST) + & S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK) | + ((bus_rd_to_wr + << S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST) + & S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK) | + ((bus_wr_to_rd + << S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST) + & S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK)); + +} + +unsigned long get_physical_dram_size(void) +{ + uint32_t data; + unsigned long ram_addr_width, ram_ext_if_io_width; + + data = mmio_read_32(S10_MPFE_HMC_ADP_DDRIOCTRL); + switch (S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(data)) { + case 0: + ram_ext_if_io_width = 16; + break; + case 1: + ram_ext_if_io_width = 32; + break; + case 2: + ram_ext_if_io_width = 64; + break; + default: + ram_ext_if_io_width = 0; + break; + } + + data = mmio_read_32(S10_MPFE_IOHMC_REG_DRAMADDRW); + ram_addr_width = IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(data) + + IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(data); + + return (1 << ram_addr_width) * (ram_ext_if_io_width / 8); +} + + + +void configure_hmc_adaptor_regs(void) +{ + uint32_t data; + uint32_t dram_io_width; + + dram_io_width = S10_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0( + mmio_read_32(S10_MPFE_IOHMC_REG_NIOSRESERVE0_OFST)); + + dram_io_width = (dram_io_width & 0xFF) >> 5; + + mmio_clrsetbits_32(S10_MPFE_HMC_ADP_DDRIOCTRL, + S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_MSK, + dram_io_width << S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_OFST); + + mmio_write_32(S10_MPFE_HMC_ADP_HPSINTFCSEL, + S10_MPFE_HMC_ADP_HPSINTFCSEL_ENABLE); + + data = mmio_read_32(S10_MPFE_IOHMC_REG_CTRLCFG1); + if (data & (1 << S10_IOHMC_CTRLCFG1_ENABLE_ECC_OFST)) { + mmio_clrsetbits_32(S10_MPFE_HMC_ADP_ECCCTRL1, + S10_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + S10_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK | + S10_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK, + S10_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + S10_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK); + + mmio_clrsetbits_32(S10_MPFE_HMC_ADP_ECCCTRL2, + S10_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK | + S10_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK | + S10_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK, + S10_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK | + S10_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK); + + mmio_clrsetbits_32(S10_MPFE_HMC_ADP_ECCCTRL1, + S10_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK | + S10_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK | + S10_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK, + S10_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK); + INFO("Scrubbing ECC\n"); + + /* ECC Scrubbing */ + zeromem(DRAM_BASE, DRAM_SIZE); + } else { + INFO("ECC is disabled.\n"); + } +} + diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c new file mode 100644 index 0000000..7fb4711 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "s10_pinmux.h" + +const uint32_t sysmgr_pinmux_array_sel[] = { + 0x00000000, 0x00000001, /* usb */ + 0x00000004, 0x00000001, + 0x00000008, 0x00000001, + 0x0000000c, 0x00000001, + 0x00000010, 0x00000001, + 0x00000014, 0x00000001, + 0x00000018, 0x00000001, + 0x0000001c, 0x00000001, + 0x00000020, 0x00000001, + 0x00000024, 0x00000001, + 0x00000028, 0x00000001, + 0x0000002c, 0x00000001, + 0x00000030, 0x00000000, /* emac0 */ + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x0000004c, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x00000000, + 0x0000005c, 0x00000000, + 0x00000060, 0x00000008, /* gpio1 */ + 0x00000064, 0x00000008, + 0x00000068, 0x00000005, /* uart0 tx */ + 0x0000006c, 0x00000005, /* uart 0 rx */ + 0x00000070, 0x00000008, /* gpio */ + 0x00000074, 0x00000008, + 0x00000078, 0x00000004, /* i2c1 */ + 0x0000007c, 0x00000004, + 0x00000080, 0x00000007, /* jtag */ + 0x00000084, 0x00000007, + 0x00000088, 0x00000007, + 0x0000008c, 0x00000007, + 0x00000090, 0x00000001, /* sdmmc data0 */ + 0x00000094, 0x00000001, + 0x00000098, 0x00000001, + 0x0000009c, 0x00000001, + 0x00000100, 0x00000001, + 0x00000104, 0x00000001, /* sdmmc.data3 */ + 0x00000108, 0x00000008, /* loan */ + 0x0000010c, 0x00000008, /* gpio */ + 0x00000110, 0x00000008, + 0x00000114, 0x00000008, /* gpio1.io21 */ + 0x00000118, 0x00000005, /* mdio0.mdio */ + 0x0000011c, 0x00000005 /* mdio0.mdc */ +}; + +const uint32_t sysmgr_pinmux_array_ctrl[] = { + 0x00000000, 0x00502c38, /* Q1_1 */ + 0x00000004, 0x00102c38, + 0x00000008, 0x00502c38, + 0x0000000c, 0x00502c38, + 0x00000010, 0x00502c38, + 0x00000014, 0x00502c38, + 0x00000018, 0x00502c38, + 0x0000001c, 0x00502c38, + 0x00000020, 0x00502c38, + 0x00000024, 0x00502c38, + 0x00000028, 0x00502c38, + 0x0000002c, 0x00502c38, + 0x00000030, 0x00102c38, /* Q2_1 */ + 0x00000034, 0x00102c38, + 0x00000038, 0x00502c38, + 0x0000003c, 0x00502c38, + 0x00000040, 0x00102c38, + 0x00000044, 0x00102c38, + 0x00000048, 0x00502c38, + 0x0000004c, 0x00502c38, + 0x00000050, 0x00102c38, + 0x00000054, 0x00102c38, + 0x00000058, 0x00502c38, + 0x0000005c, 0x00502c38, + 0x00000060, 0x00502c38, /* Q3_1 */ + 0x00000064, 0x00502c38, + 0x00000068, 0x00102c38, + 0x0000006c, 0x00502c38, + 0x000000d0, 0x00502c38, + 0x000000d4, 0x00502c38, + 0x000000d8, 0x00542c38, + 0x000000dc, 0x00542c38, + 0x000000e0, 0x00502c38, + 0x000000e4, 0x00502c38, + 0x000000e8, 0x00102c38, + 0x000000ec, 0x00502c38, + 0x000000f0, 0x00502c38, /* Q4_1 */ + 0x000000f4, 0x00502c38, + 0x000000f8, 0x00102c38, + 0x000000fc, 0x00502c38, + 0x00000100, 0x00502c38, + 0x00000104, 0x00502c38, + 0x00000108, 0x00102c38, + 0x0000010c, 0x00502c38, + 0x00000110, 0x00502c38, + 0x00000114, 0x00502c38, + 0x00000118, 0x00542c38, + 0x0000011c, 0x00102c38 +}; + +const uint32_t sysmgr_pinmux_array_fpga[] = { + 0x00000000, 0x00000000, + 0x00000004, 0x00000000, + 0x00000008, 0x00000000, + 0x0000000c, 0x00000000, + 0x00000010, 0x00000000, + 0x00000014, 0x00000000, + 0x00000018, 0x00000000, + 0x0000001c, 0x00000000, + 0x00000020, 0x00000000, + 0x00000028, 0x00000000, + 0x0000002c, 0x00000000, + 0x00000030, 0x00000000, + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x0000002a +}; + +const uint32_t sysmgr_pinmux_array_iodelay[] = { + 0x00000000, 0x00000000, + 0x00000004, 0x00000000, + 0x00000008, 0x00000000, + 0x0000000c, 0x00000000, + 0x00000010, 0x00000000, + 0x00000014, 0x00000000, + 0x00000018, 0x00000000, + 0x0000001c, 0x00000000, + 0x00000020, 0x00000000, + 0x00000024, 0x00000000, + 0x00000028, 0x00000000, + 0x0000002c, 0x00000000, + 0x00000030, 0x00000000, + 0x00000034, 0x00000000, + 0x00000038, 0x00000000, + 0x0000003c, 0x00000000, + 0x00000040, 0x00000000, + 0x00000044, 0x00000000, + 0x00000048, 0x00000000, + 0x0000004c, 0x00000000, + 0x00000050, 0x00000000, + 0x00000054, 0x00000000, + 0x00000058, 0x00000000, + 0x0000005c, 0x00000000, + 0x00000060, 0x00000000, + 0x00000064, 0x00000000, + 0x00000068, 0x00000000, + 0x0000006c, 0x00000000, + 0x00000070, 0x00000000, + 0x00000074, 0x00000000, + 0x00000078, 0x00000000, + 0x0000007c, 0x00000000, + 0x00000080, 0x00000000, + 0x00000084, 0x00000000, + 0x00000088, 0x00000000, + 0x0000008c, 0x00000000, + 0x00000090, 0x00000000, + 0x00000094, 0x00000000, + 0x00000098, 0x00000000, + 0x0000009c, 0x00000000, + 0x00000100, 0x00000000, + 0x00000104, 0x00000000, + 0x00000108, 0x00000000, + 0x0000010c, 0x00000000, + 0x00000110, 0x00000000, + 0x00000114, 0x00000000, + 0x00000118, 0x00000000, + 0x0000011c, 0x00000000 +}; + +void config_pinmux(handoff *hoff_ptr) +{ + unsigned int i; + + for (i = 0; i < 96; i += 2) { + mmio_write_32(S10_PINMUX_PIN0SEL + + hoff_ptr->pinmux_sel_array[i], + hoff_ptr->pinmux_sel_array[i+1]); + } + + for (i = 0; i < 96; i += 2) { + mmio_write_32(S10_PINMUX_IO0CTRL + + hoff_ptr->pinmux_io_array[i], + hoff_ptr->pinmux_io_array[i+1]); + } + + for (i = 0; i < 42; i += 2) { + mmio_write_32(S10_PINMUX_PINMUX_EMAC0_USEFPGA + + hoff_ptr->pinmux_fpga_array[i], + hoff_ptr->pinmux_fpga_array[i+1]); + } + + for (i = 0; i < 96; i += 2) { + mmio_write_32(S10_PINMUX_IO0_DELAY + + hoff_ptr->pinmux_iodelay_array[i], + hoff_ptr->pinmux_iodelay_array[i+1]); + } + +} + diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c new file mode 100644 index 0000000..247f73b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +/* This struct provides the PM wake up src configuration for A3720 Development Board */ +static struct pm_wake_up_src_config wake_up_src_cfg = { + .wake_up_src_num = 3, + .wake_up_src[0] = { + .wake_up_src_type = WAKE_UP_SRC_GPIO, + .wake_up_data = { + .gpio_data.bank_num = 0, /* North Bridge */ + .gpio_data.gpio_num = 14 + } + }, + .wake_up_src[1] = { + .wake_up_src_type = WAKE_UP_SRC_GPIO, + .wake_up_data = { + .gpio_data.bank_num = 1, /* South Bridge */ + .gpio_data.gpio_num = 2 + } + }, + .wake_up_src[2] = { + .wake_up_src_type = WAKE_UP_SRC_UART1, + } +}; + +struct pm_wake_up_src_config *mv_wake_up_src_config_get(void) +{ + return &wake_up_src_cfg; +} + diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h new file mode 100644 index 0000000..dad1085 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_DEF_H +#define MVEBU_DEF_H + +#include + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c new file mode 100644 index 0000000..6862a86 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#include +#include + +/* This routine does MPP initialization */ +static void marvell_bl31_mpp_init(void) +{ + mmio_clrbits_32(MVEBU_NB_GPIO_SEL_REG, 1 << MVEBU_GPIO_TW1_GPIO_EN_OFF); + + /* Set hidden GPIO setting for SPI. + * In north_bridge_pin_out_en_high register 13804, + * bit 28 is the one which enables CS, CLK pins to be + * output, need to set it to 1. + * The initial value of this bit is 1, but in UART boot mode + * initialization, this bit is disabled and the SPI CS and CLK pins + * are used for downloading image purpose; so after downloading, + * we should set this bit to 1 again to enable SPI CS and CLK pins. + * And anyway, this bit value should be 1 in all modes, + * so here we does not judge boot mode and set this bit to 1 always. + */ + mmio_setbits_32(MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG, + 1 << MVEBU_GPIO_NB_SPI_PIN_MODE_OFF); +} + +/* This function overruns the same function in marvell_bl31_setup.c */ +void bl31_plat_arch_setup(void) +{ + struct dec_win_config *io_dec_map; + uint32_t dec_win_num; + struct dram_win_map dram_wins_map; + + marvell_bl31_plat_arch_setup(); + + /* MPP init */ + marvell_bl31_mpp_init(); + + /* initialize the timer for delay functionality */ + plat_delay_timer_init(); + + /* CPU address decoder windows initialization. */ + cpu_wins_init(); + + /* fetch CPU-DRAM window mapping information by reading + * CPU-DRAM decode windows (only the enabled ones) + */ + dram_win_map_build(&dram_wins_map); + + /* Get IO address decoder windows */ + if (marvell_get_io_dec_win_conf(&io_dec_map, &dec_win_num)) { + printf("No IO address decoder windows configurations found!\n"); + return; + } + + /* IO address decoder init */ + if (init_io_addr_dec(&dram_wins_map, io_dec_map, dec_win_num)) { + printf("IO address decoder windows initialization failed!\n"); + return; + } +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/platform.mk new file mode 100644 index 0000000..050af41 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/platform.mk @@ -0,0 +1,10 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +include plat/marvell/armada/a3k/common/a3700_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_common.mk b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_common.mk new file mode 100644 index 0000000..d0e8688 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_common.mk @@ -0,0 +1,247 @@ +# +# Copyright (C) 2018-2021 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +MARVELL_PLAT_BASE := plat/marvell/armada +MARVELL_PLAT_INCLUDE_BASE := include/plat/marvell/armada +PLAT_FAMILY := a3k +PLAT_FAMILY_BASE := $(MARVELL_PLAT_BASE)/$(PLAT_FAMILY) +PLAT_INCLUDE_BASE := $(MARVELL_PLAT_INCLUDE_BASE)/$(PLAT_FAMILY) +PLAT_COMMON_BASE := $(PLAT_FAMILY_BASE)/common +MARVELL_DRV_BASE := drivers/marvell +MARVELL_COMMON_BASE := $(MARVELL_PLAT_BASE)/common +ERRATA_A53_1530924 := 1 + +include plat/marvell/marvell.mk + +#*********** A3700 ************* + +# GICV3 +$(eval $(call add_define,CONFIG_GICV3)) + +# CCI-400 +$(eval $(call add_define,USE_CCI)) + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +MARVELL_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c + +PLAT_INCLUDES := -I$(PLAT_FAMILY_BASE)/$(PLAT) \ + -I$(PLAT_COMMON_BASE)/include \ + -I$(PLAT_INCLUDE_BASE)/common \ + -I$(MARVELL_DRV_BASE) \ + -I$/drivers/arm/gic/common/ + +PLAT_BL_COMMON_SOURCES := $(PLAT_COMMON_BASE)/aarch64/a3700_common.c \ + $(PLAT_COMMON_BASE)/aarch64/a3700_clock.S \ + $(MARVELL_DRV_BASE)/uart/a3700_console.S + +BL1_SOURCES += $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \ + lib/cpus/aarch64/cortex_a53.S + +MARVELL_DRV := $(MARVELL_DRV_BASE)/comphy/phy-comphy-3700.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \ + $(PLAT_COMMON_BASE)/plat_cci.c \ + $(PLAT_COMMON_BASE)/plat_pm.c \ + $(PLAT_COMMON_BASE)/dram_win.c \ + $(PLAT_COMMON_BASE)/io_addr_dec.c \ + $(PLAT_COMMON_BASE)/marvell_plat_config.c \ + $(PLAT_FAMILY_BASE)/$(PLAT)/plat_bl31_setup.c \ + $(MARVELL_COMMON_BASE)/marvell_cci.c \ + $(MARVELL_COMMON_BASE)/marvell_ddr_info.c \ + $(MARVELL_COMMON_BASE)/marvell_gicv3.c \ + $(MARVELL_GIC_SOURCES) \ + drivers/arm/cci/cci.c \ + $(PLAT_COMMON_BASE)/a3700_sip_svc.c \ + $(MARVELL_DRV) + +ifeq ($(HANDLE_EA_EL3_FIRST),1) +BL31_SOURCES += $(PLAT_COMMON_BASE)/a3700_ea.c +endif + +ifeq ($(CM3_SYSTEM_RESET),1) +BL31_SOURCES += $(PLAT_COMMON_BASE)/cm3_system_reset.c +endif + +ifeq ($(A3720_DB_PM_WAKEUP_SRC),1) +BL31_SOURCES += $(PLAT_FAMILY_BASE)/$(PLAT)/board/pm_src.c +endif + +ifdef WTP + +# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds +$(if $(wildcard $(value WTP)/*),,$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' directory does not exist")) +$(if $(shell git -C $(value WTP) rev-parse --show-cdup 2>&1),$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' does not contain valid A3700-utils-marvell git repository")) + +TBB := $(WTP)/wtptp/src/TBB_Linux/release/TBB_linux + +BUILD_UART := uart-images +UART_IMAGE := $(BUILD_UART).tgz.bin + +ifeq ($(MARVELL_SECURE_BOOT),1) +TIM_CFG := $(BUILD_PLAT)/atf-tim.txt +TIM_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-tim.txt +IMAGESPATH := $(WTP)/tim/trusted +TIMN_CFG := $(BUILD_PLAT)/atf-timN.txt +TIMN_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-timN.txt +TIMN_SIG := $(IMAGESPATH)/timnsign.txt +TIM2IMGARGS := -i $(TIM_CFG) -n $(TIMN_CFG) +TIMN_UART_IMAGE := $$(grep "Image Filename:" -m 1 $(TIMN_UART_CFG) | cut -c 17-) +else #MARVELL_SECURE_BOOT +TIM_CFG := $(BUILD_PLAT)/atf-ntim.txt +TIM_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-ntim.txt +IMAGESPATH := $(WTP)/tim/untrusted +TIM2IMGARGS := -i $(TIM_CFG) +endif #MARVELL_SECURE_BOOT + +TIM_UART_IMAGE := $$(grep "Image Filename:" -m 1 $(TIM_UART_CFG) | cut -c 17-) + +TIMBUILD := $(WTP)/script/buildtim.sh +TIM2IMG := $(WTP)/script/tim2img.pl +TIMDDRTOOL := $(WTP)/tim/ddr/ddr_tool + +$(TIMBUILD): $(TIMDDRTOOL) + +# WTMI_IMG is used to specify the customized RTOS image running over +# Service CPU (CM3 processor). By the default, it points to a +# baremetal binary of fuse programming in A3700_utils. +WTMI_IMG := $(WTP)/wtmi/fuse/build/fuse.bin + +# WTMI_MULTI_IMG is composed of CM3 RTOS image (WTMI_IMG) +# and sys-init image. +WTMI_MULTI_IMG := $(WTP)/wtmi/build/wtmi.bin + +WTMI_ENC_IMG := wtmi-enc.bin + +SRCPATH := $(dir $(BL33)) + +CLOCKSPRESET ?= CPU_800_DDR_800 + +DDR_TOPOLOGY ?= 0 + +BOOTDEV ?= SPINOR +PARTNUM ?= 0 + +TIMBLDARGS := $(MARVELL_SECURE_BOOT) $(BOOTDEV) $(IMAGESPATH) $(WTP) $(CLOCKSPRESET) \ + $(DDR_TOPOLOGY) $(PARTNUM) $(DEBUG) $(TIM_CFG) $(TIMN_CFG) $(TIMN_SIG) 1 +TIMBLDUARTARGS := $(MARVELL_SECURE_BOOT) UART $(IMAGESPATH) $(WTP) $(CLOCKSPRESET) \ + $(DDR_TOPOLOGY) 0 0 $(TIM_UART_CFG) $(TIMN_UART_CFG) $(TIMN_SIG) 0 + +UART_IMAGES := $(BUILD_UART)/$(TIM_UART_IMAGE) +ifeq ($(MARVELL_SECURE_BOOT),1) +UART_IMAGES += $(BUILD_UART)/$(TIMN_UART_IMAGE) +endif +UART_IMAGES += $(BUILD_UART)/wtmi_h.bin $(BUILD_UART)/boot-image_h.bin + +CRYPTOPP_LIBDIR ?= $(CRYPTOPP_PATH) +CRYPTOPP_INCDIR ?= $(CRYPTOPP_PATH) + +$(TBB): FORCE +# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds + $(if $(CRYPTOPP_LIBDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_LIBDIR. Please set CRYPTOPP_PATH or CRYPTOPP_LIBDIR to point to the right directory")) + $(if $(CRYPTOPP_INCDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_INCDIR. Please set CRYPTOPP_PATH or CRYPTOPP_INCDIR to point to the right directory")) + $(if $(wildcard $(CRYPTOPP_LIBDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_LIB' was set to '$(CRYPTOPP_LIBDIR)', but '$(CRYPTOPP_LIBDIR)' does not exist")) + $(if $(wildcard $(CRYPTOPP_INCDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_INCDIR' was set to '$(CRYPTOPP_INCDIR)', but '$(CRYPTOPP_INCDIR)' does not exist")) +ifdef CRYPTOPP_PATH + $(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile +endif + $(Q)$(MAKE) --no-print-directory -C $(WTP)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_LIBDIR) INCDIR=$(CRYPTOPP_INCDIR) + +$(WTMI_MULTI_IMG): FORCE + $(Q)$(MAKE) --no-print-directory -C $(WTP) WTMI_IMG=$(WTMI_IMG) DDR_TOPOLOGY=$(DDR_TOPOLOGY) CLOCKSPRESET=$(CLOCKSPRESET) WTMI + +$(BUILD_PLAT)/wtmi.bin: $(WTMI_MULTI_IMG) + $(Q)cp -a $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi.bin + +$(TIMDDRTOOL): FORCE +# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds + $(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for ddr tool requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory")) + $(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist")) + $(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository")) + $(Q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr + +$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL) + @$(ECHO_BLANK_LINE) + @echo "Building uart images" + $(Q)mkdir -p $(BUILD_PLAT)/$(BUILD_UART) + $(Q)cp -a $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/$(BUILD_UART)/wtmi.bin + $(Q)cp -a $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/$(BUILD_UART)/$(BOOT_IMAGE) + $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TIMBUILD) $(TIMBLDUARTARGS) + $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIM_UART_CFG) + $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIM_UART_CFG) +ifeq ($(MARVELL_SECURE_BOOT),1) + $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMN_UART_CFG) + $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMN_UART_CFG) +endif + $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TBB) -r $(TIM_UART_CFG) -v -D +ifeq ($(MARVELL_SECURE_BOOT),1) + $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TBB) -r $(TIMN_UART_CFG) +endif + $(Q)tar czf $(BUILD_PLAT)/$(UART_IMAGE) -C $(BUILD_PLAT) $(UART_IMAGES) + @$(ECHO_BLANK_LINE) + @echo "Built $@ successfully" + @$(ECHO_BLANK_LINE) + +$(BUILD_PLAT)/$(FLASH_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL) $(TIM2IMG) + @$(ECHO_BLANK_LINE) + @echo "Building flash image" + $(Q)cd $(BUILD_PLAT) && $(TIMBUILD) $(TIMBLDARGS) + $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIM_CFG) + $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIM_CFG) +ifeq ($(MARVELL_SECURE_BOOT),1) + $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMN_CFG) + $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMN_CFG) + @$(ECHO_BLANK_LINE) + @echo "======================================================="; + @echo " Secure boot. Encrypting wtmi and boot-image"; + @echo "======================================================="; + @$(ECHO_BLANK_LINE) + $(Q)cp $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/wtmi-align.bin + $(Q)truncate -s %16 $(BUILD_PLAT)/wtmi-align.bin + $(Q)openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/wtmi-align.bin \ + -out $(BUILD_PLAT)/$(WTMI_ENC_IMG) \ + -K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \ + -iv `cat $(IMAGESPATH)/iv.txt` -p + $(Q)truncate -s %16 $(BUILD_PLAT)/$(BOOT_IMAGE); + $(Q)openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/$(BOOT_IMAGE) \ + -out $(BUILD_PLAT)/$(BOOT_ENC_IMAGE) \ + -K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \ + -iv `cat $(IMAGESPATH)/iv.txt` -p +endif + $(Q)cd $(BUILD_PLAT) && $(TBB) -r $(TIM_CFG) -v -D +ifeq ($(MARVELL_SECURE_BOOT),1) + $(Q)cd $(BUILD_PLAT) && $(TBB) -r $(TIMN_CFG) + $(Q)sed -i 's|wtmi.bin|$(WTMI_ENC_IMG)|1' $(TIMN_CFG) + $(Q)sed -i 's|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1' $(TIMN_CFG) +endif + $(Q)cd $(BUILD_PLAT) && $(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE) + @$(ECHO_BLANK_LINE) + @echo "Built $@ successfully" + @$(ECHO_BLANK_LINE) + +clean realclean distclean: mrvl_clean + +.PHONY: mrvl_clean +mrvl_clean: + -$(Q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) clean + -$(Q)$(MAKE) --no-print-directory -C $(WTP)/wtptp/src/TBB_Linux -f TBB_linux.mak clean +ifdef CRYPTOPP_PATH + -$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile clean +endif + +else # WTP + +$(BUILD_PLAT)/$(UART_IMAGE) $(BUILD_PLAT)/$(FLASH_IMAGE): + $(error "Platform '${PLAT}' for target '$@' requires WTP. Please set WTP to point to the right directory") + +endif # WTP + +.PHONY: mrvl_uart +mrvl_uart: $(BUILD_PLAT)/$(UART_IMAGE) diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c new file mode 100644 index 0000000..bc12845 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2019 Repk repk@triplefau.lt + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include +#include +#include +#include +#include + +#define A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS 0xbf000002 + +#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 */ + +/* + * This source file with custom plat_ea_handler function is compiled only when + * building TF-A with compile option HANDLE_EA_EL3_FIRST=1 + */ +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ + unsigned int level = (unsigned int)GET_EL(read_spsr_el3()); + + /* + * Asynchronous External Abort with syndrome 0xbf000002 on Cortex A53 + * core means SError interrupt caused by AXI SLVERR on external access. + * + * In most cases this indicates a bug in U-Boot or Linux kernel driver + * pci-aardvark.c which implements access to A3700 PCIe config space. + * Driver does not wait for PCIe PIO transfer completion and try to + * start a new PCIe PIO transfer while previous has not finished yet. + * A3700 PCIe controller in this case sends SLVERR via AXI which results + * in a fatal Asynchronous SError interrupt on Cortex A53 CPU. + * + * Following patches fix that bug in U-Boot and Linux kernel drivers: + * https://source.denx.de/u-boot/u-boot/-/commit/eccbd4ad8e4e182638eafbfb87ac139c04f24a01 + * https://git.kernel.org/stable/c/f18139966d072dab8e4398c95ce955a9742e04f7 + * + * As a hacky workaround for unpatched U-Boot and Linux kernel drivers + * ignore all asynchronous aborts with that syndrome value received on + * CPU from level lower than EL3. + * + * Because these aborts are delivered on CPU asynchronously, they are + * imprecise and we cannot check the real reason of abort and neither + * who and why sent this abort. We expect that on A3700 it is always + * PCIe controller. + * + * Hence ignoring all aborts with this syndrome value is just a giant + * hack that we need only because of bugs in old U-Boot and Linux kernel + * versions and because it was decided that TF-A would implement this + * hack for U-Boot and Linux kernel it in this way. New patched U-Boot + * and kernel versions do not need it anymore. + * + * Links to discussion about this workaround: + * https://lore.kernel.org/linux-pci/20190316161243.29517-1-repk@triplefau.lt/ + * https://lore.kernel.org/linux-pci/971be151d24312cc533989a64bd454b4@www.loen.fr/ + * https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/1541 + */ + if (level < MODE_EL3 && ea_reason == ERROR_EA_ASYNC && + syndrome == A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS) { + ERROR_NL(); + ERROR("Ignoring Asynchronous External Abort with" + " syndrome 0x%" PRIx64 " received on 0x%lx from %s\n", + syndrome, read_mpidr_el1(), get_el_str(level)); + ERROR("SError interrupt: AXI SLVERR on external access\n"); + ERROR("This indicates a bug in pci-aardvark.c driver\n"); + ERROR("Please update U-Boot/Linux to the latest version\n"); + ERROR_NL(); + console_flush(); + return; + } + + plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c new file mode 100644 index 0000000..e8ac5fc --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include + +#include +#include + +#include "comphy/phy-comphy-3700.h" + +/* Comphy related FID's */ +#define MV_SIP_COMPHY_POWER_ON 0x82000001 +#define MV_SIP_COMPHY_POWER_OFF 0x82000002 +#define MV_SIP_COMPHY_PLL_LOCK 0x82000003 + +/* Miscellaneous FID's' */ +#define MV_SIP_DRAM_SIZE 0x82000010 + +/* This macro is used to identify COMPHY related calls from SMC function ID */ +#define is_comphy_fid(fid) \ + ((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_PLL_LOCK) + +uintptr_t mrvl_sip_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) +{ + u_register_t ret; + + VERBOSE("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx\n", + __func__, smc_fid, x1, x2); + if (is_comphy_fid(smc_fid)) { + if (x1 >= MAX_LANE_NR) { + ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n", + __func__, smc_fid, x2); + SMC_RET1(handle, SMC_UNK); + } + } + + switch (smc_fid) { + /* Comphy related FID's */ + case MV_SIP_COMPHY_POWER_ON: + /* x1: comphy_index, x2: comphy_mode */ + ret = mvebu_3700_comphy_power_on(x1, x2); + SMC_RET1(handle, ret); + case MV_SIP_COMPHY_POWER_OFF: + /* x1: comphy_index, x2: comphy_mode */ + ret = mvebu_3700_comphy_power_off(x1, x2); + SMC_RET1(handle, ret); + case MV_SIP_COMPHY_PLL_LOCK: + /* x1: comphy_index, x2: comphy_mode */ + ret = mvebu_3700_comphy_is_pll_locked(x1, x2); + SMC_RET1(handle, ret); + /* Miscellaneous FID's' */ + case MV_SIP_DRAM_SIZE: + /* x1: ap_base_addr */ + ret = mvebu_get_dram_size(MVEBU_REGS_BASE); + SMC_RET1(handle, ret); + + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + marvell_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + mrvl_sip_smc_handler +); diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S new file mode 100644 index 0000000..f79516f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +/* + * Below address in used only for reading, therefore no problem with concurrent + * Linux access. + */ +#define MVEBU_TEST_PIN_LATCH_N (MVEBU_NB_GPIO_REG_BASE + 0x8) + #define MVEBU_XTAL_MODE_MASK BIT(9) + + /* ----------------------------------------------------- + * uint32_t get_ref_clk (void); + * + * returns reference clock in MHz (25 or 40) + * ----------------------------------------------------- + */ +.globl get_ref_clk +func get_ref_clk + mov_imm x0, MVEBU_TEST_PIN_LATCH_N + ldr w0, [x0] + tst w0, #MVEBU_XTAL_MODE_MASK + bne 40 + mov w0, #25 + ret +40: + mov w0, #40 + ret +endfunc get_ref_clk diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c new file mode 100644 index 0000000..6351285 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ +#include + +/* MMU entry for internal (register) space access */ +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Table of regions for various BL stages to map using the MMU. + */ +#if IMAGE_BL1 +const mmap_region_t plat_marvell_mmap[] = { + MARVELL_MAP_SHARED_RAM, + MAP_DEVICE0, + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t plat_marvell_mmap[] = { + MARVELL_MAP_SHARED_RAM, + MAP_DEVICE0, + MARVELL_MAP_DRAM, + {0} +}; +#endif +#if IMAGE_BL2U +const mmap_region_t plat_marvell_mmap[] = { + MAP_DEVICE0, + {0} +}; +#endif +#if IMAGE_BL31 +const mmap_region_t plat_marvell_mmap[] = { + MARVELL_MAP_SHARED_RAM, + MAP_DEVICE0, + MARVELL_MAP_DRAM, + {0} +}; +#endif +#if IMAGE_BL32 +const mmap_region_t plat_marvell_mmap[] = { + MAP_DEVICE0, + {0} +}; +#endif + +MARVELL_CASSERT_MMAP; diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..90d76f0 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset. Right + * now this is a stub function. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + mov x0, #0 + ret +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between cold and warm boot + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * A magic number is placed before entrypoint to avoid mistake caused by + * uninitialized mailbox data area. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* Read first word and compare it with magic num */ + mov_imm x0, PLAT_MARVELL_MAILBOX_BASE + ldr x1, [x0] + mov_imm x2, PLAT_MARVELL_MAILBOX_MAGIC_NUM + cmp x1, x2 + /* If compare failed, return 0, i.e. cold boot */ + beq entrypoint + mov x0, #0 + ret +entrypoint: + /* Second word contains the jump address */ + add x0, x0, #8 + ldr x0, [x0] + ret +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #MVEBU_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c new file mode 100644 index 0000000..f105d59 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020 Marek Behun, CZ.NIC + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include + +#include + +/* Cortex-M3 Secure Processor Mailbox Registers */ +#define MVEBU_RWTM_PARAM0_REG (MVEBU_RWTM_REG_BASE) +#define MVEBU_RWTM_CMD_REG (MVEBU_RWTM_REG_BASE + 0x40) +#define MVEBU_RWTM_HOST_INT_RESET_REG (MVEBU_RWTM_REG_BASE + 0xC8) +#define MVEBU_RWTM_HOST_INT_MASK_REG (MVEBU_RWTM_REG_BASE + 0xCC) +#define MVEBU_RWTM_HOST_INT_SP_COMPLETE BIT(0) + +#define MVEBU_RWTM_REBOOT_CMD 0x0009 +#define MVEBU_RWTM_REBOOT_MAGIC 0xDEADBEEF + +static inline bool rwtm_completed(void) +{ + return (mmio_read_32(MVEBU_RWTM_HOST_INT_RESET_REG) & + MVEBU_RWTM_HOST_INT_SP_COMPLETE) != 0; +} + +static bool rwtm_wait(int ms) +{ + while (ms && !rwtm_completed()) { + mdelay(1); + --ms; + } + + return rwtm_completed(); +} + +void cm3_system_reset(void) +{ + int tries = 5; + + for (; tries > 0; --tries) { + mmio_clrbits_32(MVEBU_RWTM_HOST_INT_RESET_REG, + MVEBU_RWTM_HOST_INT_SP_COMPLETE); + + mmio_write_32(MVEBU_RWTM_PARAM0_REG, MVEBU_RWTM_REBOOT_MAGIC); + mmio_write_32(MVEBU_RWTM_CMD_REG, MVEBU_RWTM_REBOOT_CMD); + + if (rwtm_wait(10)) { + break; + } + + mdelay(100); + } + + /* If we reach here, the command is not implemented. */ + WARN("System reset command not implemented in WTMI firmware!\n"); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c new file mode 100644 index 0000000..9d7b3a9 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2018-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include + +#include +#include +#include +#include + +/* Armada 3700 has 5 configurable windows */ +#define MV_CPU_WIN_NUM 5 + +#define CPU_WIN_DISABLED 0 +#define CPU_WIN_ENABLED 1 + +/* + * There are 2 different cpu decode window configuration cases: + * - DRAM size is not over 2GB; + * - DRAM size is 4GB. + */ +enum cpu_win_config_num { + CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB = 0, + CPU_WIN_CONFIG_DRAM_4GB, + CPU_WIN_CONFIG_MAX +}; + +enum cpu_win_target { + CPU_WIN_TARGET_DRAM = 0, + CPU_WIN_TARGET_INTERNAL_REG, + CPU_WIN_TARGET_PCIE, + CPU_WIN_TARGET_PCIE_OVER_MCI, + CPU_WIN_TARGET_BOOT_ROM, + CPU_WIN_TARGET_MCI_EXTERNAL, + CPU_WIN_TARGET_RWTM_RAM = 7, + CPU_WIN_TARGET_CCI400_REG +}; + +struct cpu_win_configuration { + uint32_t enabled; + enum cpu_win_target target; + uint64_t base_addr; + uint64_t size; + uint64_t remap_addr; +}; + +struct cpu_win_configuration mv_cpu_wins[CPU_WIN_CONFIG_MAX][MV_CPU_WIN_NUM] = { + /* + * When total dram size is not over 2GB: + * DDR window 0 is configured in tim header, its size may be not 512MB, + * but the actual dram size, no need to configure it again; + * other cpu windows are kept as default. + */ + { + /* enabled + * target + * base + * size + * remap + */ + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_DRAM, + 0x0, + 0x08000000, + 0x0}, + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_MCI_EXTERNAL, + 0xe0000000, + 0x08000000, + 0xe0000000}, + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_PCIE, + 0xe8000000, + 0x08000000, + 0xe8000000}, + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_RWTM_RAM, + 0xf0000000, + 0x00020000, + 0x1fff0000}, + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_PCIE_OVER_MCI, + 0x80000000, + 0x10000000, + 0x80000000}, + }, + + /* + * If total DRAM size is more than 2GB, now there is only one case: + * 4GB of DRAM; to better utilize address space (for maximization of + * DRAM usage), we will use the configuration of CPU windows below: + * - Internal Regs and Boot ROM windows are kept as default; + * - CCI-400 is moved from its default address to another address + * (this is actually done even if DRAM size is not more than 2 GB, + * because the firmware is compiled with that address as a + * constant); + * - PCIe window is moved to another address; + * - Use 4 CPU decode windows for DRAM, which cover 3.75GB DRAM; + * DDR window 0 is configured in tim header with 2G B size, no need + * to configure it again here; + * + * 0xFFFFFFFF ---> +-----------------------+ + * | Boot ROM | 1 MB + * | AP Boot ROM - 16 KB: | + * | 0xFFFF0000-0xFFFF4000 | + * 0xFFF00000 ---> +-----------------------+ + * : : + * 0xFE010000 ---> +-----------------------+ + * | CCI Regs | 64 KB + * 0xFE000000 ---> +-----------------------+ + * : : + * 0xFA000000 ---> +-----------------------+ + * | PCIE | 128 MB + * 0xF2000000 ---> +-----------------------+ + * | DDR window 3 | 512 MB + * 0xD2000000 ---> +-----------------------+ + * | Internal Regs | 32 MB + * 0xD0000000 ---> |-----------------------| + * | DDR window 2 | 256 MB + * 0xC0000000 ---> |-----------------------| + * | | + * | DDR window 1 | 1 GB + * | | + * 0x80000000 ---> |-----------------------| + * | | + * | | + * | DDR window 0 | 2 GB + * | | + * | | + * 0x00000000 ---> +-----------------------+ + */ + { + /* win_id + * target + * base + * size + * remap + */ + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_DRAM, + 0x0, + 0x80000000, + 0x0}, + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_DRAM, + 0x80000000, + 0x40000000, + 0x80000000}, + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_DRAM, + 0xc0000000, + 0x10000000, + 0xc0000000}, + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_DRAM, + 0xd2000000, + 0x20000000, + 0xd2000000}, + {CPU_WIN_ENABLED, + CPU_WIN_TARGET_PCIE, + 0xf2000000, + 0x08000000, + 0xf2000000}, + }, +}; + +/* + * dram_win_map_build + * + * This function builds cpu dram windows mapping + * which includes base address and window size by + * reading cpu dram decode windows registers. + * + * @input: N/A + * + * @output: + * - win_map: cpu dram windows mapping + * + * @return: N/A + */ +void dram_win_map_build(struct dram_win_map *win_map) +{ + int32_t win_id; + struct dram_win *win; + uint32_t base_reg, ctrl_reg, size_reg, enabled, target; + + memset(win_map, 0, sizeof(struct dram_win_map)); + for (win_id = 0; win_id < DRAM_WIN_MAP_NUM_MAX; win_id++) { + ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id)); + target = (ctrl_reg & CPU_DEC_CR_WIN_TARGET_MASK) >> + CPU_DEC_CR_WIN_TARGET_OFFS; + enabled = ctrl_reg & CPU_DEC_CR_WIN_ENABLE; + /* Ignore invalid and non-dram windows*/ + if ((enabled == 0) || (target != DRAM_CPU_DEC_TARGET_NUM)) + continue; + + win = win_map->dram_windows + win_map->dram_win_num; + base_reg = mmio_read_32(CPU_DEC_WIN_BASE_REG(win_id)); + size_reg = mmio_read_32(CPU_DEC_WIN_SIZE_REG(win_id)); + /* Base reg [15:0] corresponds to transaction address [39:16] */ + win->base_addr = (base_reg & CPU_DEC_BR_BASE_MASK) >> + CPU_DEC_BR_BASE_OFFS; + win->base_addr *= CPU_DEC_CR_WIN_SIZE_ALIGNMENT; + /* + * Size reg [15:0] is programmed from LSB to MSB as a sequence + * of 1s followed by a sequence of 0s and the number of 1s + * specifies the size of the window in 64 KB granularity, + * for example, a value of 00FFh specifies 256 x 64 KB = 16 MB + */ + win->win_size = (size_reg & CPU_DEC_CR_WIN_SIZE_MASK) >> + CPU_DEC_CR_WIN_SIZE_OFFS; + win->win_size = (win->win_size + 1) * + CPU_DEC_CR_WIN_SIZE_ALIGNMENT; + + win_map->dram_win_num++; + } +} + +static void cpu_win_set(uint32_t win_id, struct cpu_win_configuration *win_cfg) +{ + uint32_t base_reg, ctrl_reg, size_reg, remap_reg; + + /* Disable window */ + ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id)); + ctrl_reg &= ~CPU_DEC_CR_WIN_ENABLE; + mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg); + + /* For an disabled window, only disable it. */ + if (!win_cfg->enabled) + return; + + /* Set Base Register */ + base_reg = (uint32_t)(win_cfg->base_addr / + CPU_DEC_CR_WIN_SIZE_ALIGNMENT); + base_reg <<= CPU_DEC_BR_BASE_OFFS; + base_reg &= CPU_DEC_BR_BASE_MASK; + mmio_write_32(CPU_DEC_WIN_BASE_REG(win_id), base_reg); + + /* Set Remap Register with the same value + * as the field in Base Register + */ + remap_reg = (uint32_t)(win_cfg->remap_addr / + CPU_DEC_CR_WIN_SIZE_ALIGNMENT); + remap_reg <<= CPU_DEC_RLR_REMAP_LOW_OFFS; + remap_reg &= CPU_DEC_RLR_REMAP_LOW_MASK; + mmio_write_32(CPU_DEC_REMAP_LOW_REG(win_id), remap_reg); + + /* Set Size Register */ + size_reg = (win_cfg->size / CPU_DEC_CR_WIN_SIZE_ALIGNMENT) - 1; + size_reg <<= CPU_DEC_CR_WIN_SIZE_OFFS; + size_reg &= CPU_DEC_CR_WIN_SIZE_MASK; + mmio_write_32(CPU_DEC_WIN_SIZE_REG(win_id), size_reg); + + /* Set Control Register - set target id and enable window */ + ctrl_reg &= ~CPU_DEC_CR_WIN_TARGET_MASK; + ctrl_reg |= (win_cfg->target << CPU_DEC_CR_WIN_TARGET_OFFS); + ctrl_reg |= CPU_DEC_CR_WIN_ENABLE; + mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg); +} + +void cpu_wins_init(void) +{ + uint32_t cfg_idx, win_id; + + if (mvebu_get_dram_size(MVEBU_REGS_BASE) <= _2GB_) + cfg_idx = CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB; + else + cfg_idx = CPU_WIN_CONFIG_DRAM_4GB; + + /* Window 0 is configured always for DRAM in tim header + * already, no need to configure it again here + */ + for (win_id = 1; win_id < MV_CPU_WIN_NUM; win_id++) + cpu_win_set(win_id, &mv_cpu_wins[cfg_idx][win_id]); +} + diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h new file mode 100644 index 0000000..4d45e15 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2018-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef A3700_PLAT_DEF_H +#define A3700_PLAT_DEF_H + +#include + + +#define MVEBU_MAX_CPUS_PER_CLUSTER 2 + +#define MVEBU_PRIMARY_CPU 0x0 + +/* + * The counter on A3700 is always fed from reference 25M clock (XTAL). + * However minimal CPU counter prescaler is 2, so the counter + * frequency will be divided by 2, the number is 12.5M + */ +#define COUNTER_FREQUENCY 12500000 + +#define MVEBU_REGS_BASE 0xD0000000 + +/***************************************************************************** + * MVEBU memory map related constants + ***************************************************************************** + */ +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE MVEBU_REGS_BASE +#define DEVICE0_SIZE 0x10000000 + +/***************************************************************************** + * GIC-500 & interrupt handling related constants + ***************************************************************************** + */ +/* Base MVEBU compatible GIC memory map */ +#define MVEBU_GICD_BASE 0x1D00000 +#define MVEBU_GICR_BASE 0x1D40000 +#define MVEBU_GICC_BASE 0x1D80000 + +/* + * CCI-400 base address + * This address is absolute, not relative to MVEBU_REGS_BASE. + * This is not the default CCI base address (that would be 0xD8000000). + * Rather we remap CCI to this address to better utilize the address space. + * (The remapping is done in plat/marvell/armada/a3k/common/plat_cci.c) + */ +#define MVEBU_CCI_BASE 0xFE000000 + +/***************************************************************************** + * North and south bridge reset registers + ***************************************************************************** + */ +#define MVEBU_NB_RESET_REG (MVEBU_REGS_BASE + 0x12400) +#define MVEBU_NB_RESET_I2C1_N (1 << 0) +#define MVEBU_NB_RESET_1WIRE_N (1 << 1) +#define MVEBU_NB_RESET_SPI_N (1 << 2) +#define MVEBU_NB_RESET_UART_N (1 << 3) +#define MVEBU_NB_RESET_XTL_N (1 << 4) +#define MVEBU_NB_RESET_I2C2_N (1 << 5) +#define MVEBU_NB_RESET_UART2_N (1 << 6) +#define MVEBU_NB_RESET_AVS_N (1 << 7) +#define MVEBU_NB_RESET_DDR_N (1 << 10) +#define MVEBU_NB_RESET_SETM_N (1 << 11) +#define MVEBU_NB_RESET_DMA_N (1 << 12) +#define MVEBU_NB_RESET_TSECM_N (1 << 13) +#define MVEBU_NB_RESET_SDIO_N (1 << 14) +#define MVEBU_NB_RESET_SATA_N (1 << 15) +#define MVEBU_NB_RESET_PWRMGT_N (1 << 16) +#define MVEBU_NB_RESET_OTP_N (1 << 17) +#define MVEBU_NB_RESET_EIP_N (1 << 18) +#define MVEBU_SB_RESET_REG (MVEBU_REGS_BASE + 0x18600) +#define MVEBU_SB_RESET_MCIPHY (1 << 1) +#define MVEBU_SB_RESET_SDIO_N (1 << 2) +#define MVEBU_SB_RESET_PCIE_N (1 << 3) +#define MVEBU_SB_RESET_GBE1_N (1 << 4) +#define MVEBU_SB_RESET_GBE0_N (1 << 5) +#define MVEBU_SB_RESET_USB2PHY (1 << 6) +#define MVEBU_SB_RESET_USB2HPHY (1 << 7) +#define MVEBU_SB_RESET_MCI_N (1 << 8) +#define MVEBU_SB_RESET_PWRMGT_N (1 << 9) +#define MVEBU_SB_RESET_EBM_N (1 << 10) +#define MVEBU_SB_RESET_OTP_N (1 << 11) + +/***************************************************************************** + * North and south bridge register base + ***************************************************************************** + */ +#define MVEBU_NB_REGS_BASE (MVEBU_REGS_BASE + 0x13000) +#define MVEBU_SB_REGS_BASE (MVEBU_REGS_BASE + 0x18000) + +/***************************************************************************** + * GPIO registers related constants + ***************************************************************************** + */ +/* North and south bridge GPIO register base address */ +#define MVEBU_NB_GPIO_REG_BASE (MVEBU_NB_REGS_BASE + 0x800) +#define MVEBU_NB_GPIO_IRQ_REG_BASE (MVEBU_NB_REGS_BASE + 0xC00) +#define MVEBU_SB_GPIO_REG_BASE (MVEBU_SB_REGS_BASE + 0x800) +#define MVEBU_SB_GPIO_IRQ_REG_BASE (MVEBU_SB_REGS_BASE + 0xC00) +#define MVEBU_NB_SB_IRQ_REG_BASE (MVEBU_REGS_BASE + 0x8A00) + +/* North Bridge GPIO selection register */ +#define MVEBU_NB_GPIO_SEL_REG (MVEBU_NB_GPIO_REG_BASE + 0x30) +#define MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG (MVEBU_NB_GPIO_REG_BASE + 0x04) +/* I2C1 GPIO Enable bit offset */ +#define MVEBU_GPIO_TW1_GPIO_EN_OFF (10) +/* SPI pins mode bit offset */ +#define MVEBU_GPIO_NB_SPI_PIN_MODE_OFF (28) + +/***************************************************************************** + * DRAM registers related constants + ***************************************************************************** + */ +#define MVEBU_DRAM_REG_BASE (MVEBU_REGS_BASE) + +/***************************************************************************** + * SB wake-up registers related constants + ***************************************************************************** + */ +#define MVEBU_SB_WAKEUP_REG_BASE (MVEBU_REGS_BASE + 0x19000) + +/***************************************************************************** + * PMSU registers related constants + ***************************************************************************** + */ +#define MVEBU_PMSU_REG_BASE (MVEBU_REGS_BASE + 0x14000) + +/***************************************************************************** + * North Bridge Step-Down Registers + ***************************************************************************** + */ +#define MVEBU_NB_STEP_DOWN_REG_BASE (MVEBU_REGS_BASE + 0x12800) + +/***************************************************************************** + * DRAM CS memory map register base + ***************************************************************************** + */ +#define MVEBU_CS_MMAP_REG_BASE (MVEBU_REGS_BASE + 0x200) + +/***************************************************************************** + * CPU decoder window registers related constants + ***************************************************************************** + */ +#define MVEBU_CPU_DEC_WIN_REG_BASE (MVEBU_REGS_BASE + 0xCF00) + +/***************************************************************************** + * AVS registers related constants + ***************************************************************************** + */ +#define MVEBU_AVS_REG_BASE (MVEBU_REGS_BASE + 0x11500) + + +/***************************************************************************** + * AVS registers related constants + ***************************************************************************** + */ +#define MVEBU_COMPHY_REG_BASE (MVEBU_REGS_BASE + 0x18300) + +/***************************************************************************** + * Cortex-M3 Secure Processor Mailbox constants + ***************************************************************************** + */ +#define MVEBU_RWTM_REG_BASE (MVEBU_REGS_BASE + 0xB0000) + +#endif /* A3700_PLAT_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h new file mode 100644 index 0000000..44dbb9f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016-2020 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef A3700_PM_H +#define A3700_PM_H + +#include + +/* supported wake up sources */ +enum pm_wake_up_src_type { + WAKE_UP_SRC_GPIO, + /* FOLLOWING SRC NOT SUPPORTED YET */ + WAKE_UP_SRC_TIMER, + WAKE_UP_SRC_UART0, + WAKE_UP_SRC_UART1, + WAKE_UP_SRC_MAX, +}; + +struct pm_gpio_data { + /* + * bank 0: North bridge GPIO + * bank 1: South bridge GPIO + */ + uint32_t bank_num; + uint32_t gpio_num; +}; + +union pm_wake_up_src_data { + struct pm_gpio_data gpio_data; + /* delay in seconds */ + uint32_t timer_delay; +}; + +struct pm_wake_up_src { + enum pm_wake_up_src_type wake_up_src_type; + + union pm_wake_up_src_data wake_up_data; +}; + +struct pm_wake_up_src_config { + uint32_t wake_up_src_num; + struct pm_wake_up_src wake_up_src[WAKE_UP_SRC_MAX]; +}; + +struct pm_wake_up_src_config *mv_wake_up_src_config_get(void); + +void cm3_system_reset(void); + +#endif /* A3700_PM_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h new file mode 100644 index 0000000..254f78c --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef DDR_INFO_H +#define DDR_INFO_H + +#define DRAM_MAX_IFACE 1 +#define DRAM_CH0_MMAP_LOW_OFFSET 0x200 + +#endif /* DDR_INFO_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h new file mode 100644 index 0000000..26a0137 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef DRAM_WIN_H +#define DRAM_WIN_H + +#include + +#include + +void dram_win_map_build(struct dram_win_map *win_map); +void cpu_wins_init(void); + +#endif /* DRAM_WIN_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h new file mode 100644 index 0000000..42ef30b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef IO_ADDR_DEC_H +#define IO_ADDR_DEC_H + +#include + +/* There are 5 configurable cpu decoder windows. */ +#define DRAM_WIN_MAP_NUM_MAX 5 +/* Target number for dram in cpu decoder windows. */ +#define DRAM_CPU_DEC_TARGET_NUM 0 + +/* + * Not all configurable decode windows could be used for dram, some units have + * to reserve one decode window for other unit they have to communicate with; + * for example, DMA engineer has 3 configurable windows, but only two could be + * for dram while the last one has to be for pcie, so for DMA, its max_dram_win + * is 2. + */ +struct dec_win_config { + uint32_t dec_reg_base; /* IO address decoder register base address */ + uint32_t win_attr; /* IO address decoder windows attributes */ + /* How many configurable dram decoder windows that this unit has; */ + uint32_t max_dram_win; + /* The decoder windows number including remapping that this unit has */ + uint32_t max_remap; + /* The offset between continuous decode windows + * within the same unit, typically 0x10 + */ + uint32_t win_offset; +}; + +struct dram_win { + uintptr_t base_addr; + uintptr_t win_size; +}; + +struct dram_win_map { + int dram_win_num; + struct dram_win dram_windows[DRAM_WIN_MAP_NUM_MAX]; +}; + +/* + * init_io_addr_dec + * + * This function initializes io address decoder windows by + * cpu dram window mapping information + * + * @input: N/A + * - dram_wins_map: cpu dram windows mapping + * - io_dec_config: io address decoder windows configuration + * - io_unit_num: io address decoder unit number + * @output: N/A + * + * @return: 0 on success and others on failure + */ +int init_io_addr_dec(struct dram_win_map *dram_wins_map, + struct dec_win_config *io_dec_config, + uint32_t io_unit_num); + +#endif /* IO_ADDR_DEC_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S new file mode 100644 index 0000000..f689b4f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +/* --------------------------------------------- + * The below macro prints out relevant GIC and + * CCI registers registers whenever an unhandled + * exception is taken in BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + mov_imm x17, MVEBU_GICC_BASE + mov_imm x16, MVEBU_GICD_BASE + marvell_print_gic_regs + print_cci_regs +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h new file mode 100644 index 0000000..f19d96b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2016-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#ifndef __ASSEMBLER__ +#include +#endif /* __ASSEMBLER__ */ + +#include +#include + +/* + * Most platform porting definitions provided by included headers + */ + +/* + * DRAM Memory layout: + * +-----------------------+ + * : : + * : Linux : + * 0x04X00000-->+-----------------------+ + * | BL3-3(u-boot) |>>}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + * |-----------------------| } | + * | BL3-[0,1, 2] | }---------------------------------> | + * |-----------------------| } || | + * | BL2 | }->FIP (loaded by || | + * |-----------------------| } BootROM to DRAM) || | + * | FIP_TOC | } || | + * 0x04120000-->|-----------------------| || | + * | BL1 (RO) | || | + * 0x04100000-->+-----------------------+ || | + * : : || | + * : Trusted SRAM section : \/ | + * 0x04040000-->+-----------------------+ Replaced by BL2 +----------------+ | + * | BL1 (RW) | <<<<<<<<<<<<<<<< | BL3-1 NOBITS | | + * 0x04037000-->|-----------------------| <<<<<<<<<<<<<<<< |----------------| | + * | | <<<<<<<<<<<<<<<< | BL3-1 PROGBITS | | + * 0x04023000-->|-----------------------| +----------------+ | + * | BL2 | | + * |-----------------------| | + * | | | + * 0x04001000-->|-----------------------| | + * | Shared | | + * 0x04000000-->+-----------------------+ | + * : : | + * : Linux : | + * : : | + * |-----------------------| | + * | | U-Boot(BL3-3) Loaded by BL2 | + * | U-Boot | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + * 0x00000000-->+-----------------------+ + * + * Trusted SRAM section 0x4000000..0x4200000: + * ---------------------------------------- + * SRAM_BASE = 0x4001000 + * BL2_BASE = 0x4006000 + * BL2_LIMIT = BL31_BASE + * BL31_BASE = 0x4023000 = (64MB + 256KB - 0x1D000) + * BL31_PROGBITS_LIMIT = BL1_RW_BASE + * BL1_RW_BASE = 0x4037000 = (64MB + 256KB - 0x9000) + * BL1_RW_LIMIT = BL31_LIMIT = 0x4040000 + * + * + * PLAT_MARVELL_FIP_BASE = 0x4120000 + */ + +/* + * Since BL33 is loaded by BL2 (and validated by BL31) to DRAM offset 0, + * it is allowed to load/copy images to 'NULL' pointers + */ +#if defined(IMAGE_BL2) || defined(IMAGE_BL31) +#define PLAT_ALLOW_ZERO_ADDR_COPY +#endif + +#define PLAT_MARVELL_ATF_BASE 0x4000000 +#define PLAT_MARVELL_ATF_LOAD_ADDR \ + (PLAT_MARVELL_ATF_BASE + 0x100000) + +#define PLAT_MARVELL_FIP_BASE \ + (PLAT_MARVELL_ATF_LOAD_ADDR + 0x20000) +#define PLAT_MARVELL_FIP_MAX_SIZE 0x4000000 + +#define PLAT_MARVELL_CLUSTER_CORE_COUNT U(2) +/* DRAM[2MB..66MB] is used as Trusted ROM */ +#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR +/* 4 MB for FIP image */ +#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x00400000 +/* Reserve 12M for SCP (Secure PayLoad) Trusted RAM + * OP-TEE SHMEM follows this region + */ +#define PLAT_MARVELL_TRUSTED_RAM_BASE 0x04400000 +#define PLAT_MARVELL_TRUSTED_RAM_SIZE 0x00C00000 /* 12 MB DRAM */ + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_MARVELL_MAX_BL1_RW_SIZE 0xA000 + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#define PLAT_MARVELL_MAX_BL2_SIZE 0xF000 + +/* + * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#define PLAT_MARVEL_MAX_BL31_SIZE 0x5D000 + +#define PLAT_MARVELL_CPU_ENTRY_ADDR BL1_RO_BASE + +/* GIC related definitions */ +#define PLAT_MARVELL_GICD_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE) +#define PLAT_MARVELL_GICR_BASE (MVEBU_REGS_BASE + MVEBU_GICR_BASE) +#define PLAT_MARVELL_GICC_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE) + +#define PLAT_MARVELL_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_PHY_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + + +#define PLAT_MARVELL_SHARED_RAM_CACHED 1 + +/* CCI related constants */ +#define PLAT_MARVELL_CCI_BASE MVEBU_CCI_BASE +#define PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX 3 +#define PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX 4 + +/* + * Load address of BL3-3 for this platform port + */ +#define PLAT_MARVELL_NS_IMAGE_OFFSET 0x0 + +/* System Reference Clock*/ +#define PLAT_REF_CLK_IN_HZ COUNTER_FREQUENCY + +/* + * PL011 related constants + */ +#define PLAT_MARVELL_UART_BASE (MVEBU_REGS_BASE + 0x12000) + +/* Required platform porting definitions */ +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 + +/* System timer related constants */ +#define PLAT_MARVELL_NSTIMER_FRAME_ID 1 + +/* Mailbox base address */ +#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_SHARED_RAM_BASE + 0x400) +#define PLAT_MARVELL_MAILBOX_SIZE 0x100 +#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C /* mrvl */ + +/* DRAM CS memory map registers related constants */ +#define MVEBU_CS_MMAP_LOW(cs_num) \ + (MVEBU_CS_MMAP_REG_BASE + (cs_num) * 0x8) +#define MVEBU_CS_MMAP_ENABLE 0x1 +#define MVEBU_CS_MMAP_AREA_LEN_OFFS 16 +#define MVEBU_CS_MMAP_AREA_LEN_MASK \ + (0x1f << MVEBU_CS_MMAP_AREA_LEN_OFFS) +#define MVEBU_CS_MMAP_START_ADDR_LOW_OFFS 23 +#define MVEBU_CS_MMAP_START_ADDR_LOW_MASK \ + (0x1ff << MVEBU_CS_MMAP_START_ADDR_LOW_OFFS) + +#define MVEBU_CS_MMAP_HIGH(cs_num) \ + (MVEBU_CS_MMAP_REG_BASE + 0x4 + (cs_num) * 0x8) + +/* DRAM max CS number */ +#define MVEBU_MAX_CS_MMAP_NUM (2) + +/* CPU decoder window related constants */ +#define CPU_DEC_WIN_CTRL_REG(win_num) \ + (MVEBU_CPU_DEC_WIN_REG_BASE + (win_num) * 0x10) +#define CPU_DEC_CR_WIN_ENABLE 0x1 +#define CPU_DEC_CR_WIN_TARGET_OFFS 4 +#define CPU_DEC_CR_WIN_TARGET_MASK \ + (0xf << CPU_DEC_CR_WIN_TARGET_OFFS) + +#define CPU_DEC_WIN_SIZE_REG(win_num) \ + (MVEBU_CPU_DEC_WIN_REG_BASE + 0x4 + (win_num) * 0x10) +#define CPU_DEC_CR_WIN_SIZE_OFFS 0 +#define CPU_DEC_CR_WIN_SIZE_MASK \ + (0xffff << CPU_DEC_CR_WIN_SIZE_OFFS) +#define CPU_DEC_CR_WIN_SIZE_ALIGNMENT 0x10000 + +#define CPU_DEC_WIN_BASE_REG(win_num) \ + (MVEBU_CPU_DEC_WIN_REG_BASE + 0x8 + (win_num) * 0x10) +#define CPU_DEC_BR_BASE_OFFS 0 +#define CPU_DEC_BR_BASE_MASK \ + (0xffff << CPU_DEC_BR_BASE_OFFS) + +#define CPU_DEC_REMAP_LOW_REG(win_num) \ + (MVEBU_CPU_DEC_WIN_REG_BASE + 0xC + (win_num) * 0x10) +#define CPU_DEC_RLR_REMAP_LOW_OFFS 0 +#define CPU_DEC_RLR_REMAP_LOW_MASK \ + (0xffff << CPU_DEC_BR_BASE_OFFS) + +#define CPU_DEC_CCI_BASE_REG (MVEBU_CPU_DEC_WIN_REG_BASE + 0xe0) + +/* Securities */ +#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c new file mode 100644 index 0000000..fea7f81 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include +#include + +#define MVEBU_DEC_WIN_CTRL_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \ + (win) * (off)) +#define MVEBU_DEC_WIN_BASE_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \ + (win) * (off) + 0x4) +#define MVEBU_DEC_WIN_REMAP_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \ + (win) * (off) + 0x8) + +#define MVEBU_DEC_WIN_CTRL_SIZE_OFF (16) +#define MVEBU_DEC_WIN_ENABLE (0x1) +#define MVEBU_DEC_WIN_CTRL_ATTR_OFF (8) +#define MVEBU_DEC_WIN_CTRL_TARGET_OFF (4) +#define MVEBU_DEC_WIN_CTRL_EN_OFF (0) +#define MVEBU_DEC_WIN_BASE_OFF (16) + +#define MVEBU_WIN_BASE_SIZE_ALIGNMENT (0x10000) + +/* There are up to 14 IO unit which need address decode in Armada-3700 */ +#define IO_UNIT_NUM_MAX (14) + +#define MVEBU_MAX_ADDRSS_4GB (0x100000000ULL) + + +static void set_io_addr_dec_win(int win_id, uintptr_t base_addr, + uintptr_t win_size, + struct dec_win_config *dec_win) +{ + uint32_t ctrl = 0; + uint32_t base = 0; + + /* set size */ + ctrl = ((win_size / MVEBU_WIN_BASE_SIZE_ALIGNMENT) - 1) << + MVEBU_DEC_WIN_CTRL_SIZE_OFF; + /* set attr according to IO decode window */ + ctrl |= dec_win->win_attr << MVEBU_DEC_WIN_CTRL_ATTR_OFF; + /* set target */ + ctrl |= DRAM_CPU_DEC_TARGET_NUM << MVEBU_DEC_WIN_CTRL_TARGET_OFF; + /* set base */ + base = (base_addr / MVEBU_WIN_BASE_SIZE_ALIGNMENT) << + MVEBU_DEC_WIN_BASE_OFF; + + /* set base address*/ + mmio_write_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base, + win_id, dec_win->win_offset), + base); + /* set remap window, some unit does not have remap window */ + if (win_id < dec_win->max_remap) + mmio_write_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base, + win_id, dec_win->win_offset), base); + /* set control register */ + mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, + win_id, dec_win->win_offset), ctrl); + /* enable the address decode window at last to make it effective */ + ctrl |= MVEBU_DEC_WIN_ENABLE << MVEBU_DEC_WIN_CTRL_EN_OFF; + mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, + win_id, dec_win->win_offset), ctrl); + + INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x) remap(0x%x)\n", + win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, + win_id, dec_win->win_offset)), + mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base, + win_id, dec_win->win_offset)), + (win_id < dec_win->max_remap) ? + mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base, + win_id, dec_win->win_offset)) : 0); +} + +/* Set io decode window */ +static int set_io_addr_dec(struct dram_win_map *win_map, + struct dec_win_config *dec_win) +{ + struct dram_win *win; + int id; + + /* disable all windows first */ + for (id = 0; id < dec_win->max_dram_win; id++) + mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, id, + dec_win->win_offset), 0); + + /* configure IO decode windows for DRAM, inheritate DRAM size, + * base and target from CPU-DRAM decode window and others + * from hard coded IO decode window settings array. + */ + if (win_map->dram_win_num > dec_win->max_dram_win) { + /* + * If cpu dram windows number exceeds the io decode windows + * max number, then fill the first io decode window + * with base(0) and size(4GB). + */ + set_io_addr_dec_win(0, 0, MVEBU_MAX_ADDRSS_4GB, dec_win); + + return 0; + } + + for (id = 0; id < win_map->dram_win_num; id++, win++) { + win = &win_map->dram_windows[id]; + set_io_addr_dec_win(id, win->base_addr, win->win_size, dec_win); + } + + return 0; +} + +/* + * init_io_addr_dec + * + * This function initializes io address decoder windows by + * cpu dram window mapping information + * + * @input: N/A + * - dram_wins_map: cpu dram windows mapping + * - io_dec_config: io address decoder windows configuration + * - io_unit_num: io address decoder unit number + * @output: N/A + * + * @return: 0 on success and others on failure + */ +int init_io_addr_dec(struct dram_win_map *dram_wins_map, + struct dec_win_config *io_dec_config, uint32_t io_unit_num) +{ + int32_t index; + struct dec_win_config *io_dec_win; + int32_t ret; + + INFO("Initializing IO address decode windows\n"); + + if (io_dec_config == NULL || io_unit_num == 0) { + ERROR("No IO address decoder windows configurations!\n"); + return -1; + } + + if (io_unit_num > IO_UNIT_NUM_MAX) { + ERROR("IO address decoder windows number %d is over max %d\n", + io_unit_num, IO_UNIT_NUM_MAX); + return -1; + } + + if (dram_wins_map == NULL) { + ERROR("No cpu dram decoder windows map!\n"); + return -1; + } + + for (index = 0; index < dram_wins_map->dram_win_num; index++) + INFO("DRAM mapping %d base(0x%lx) size(0x%lx)\n", + index, dram_wins_map->dram_windows[index].base_addr, + dram_wins_map->dram_windows[index].win_size); + + /* Set address decode window for each IO */ + for (index = 0; index < io_unit_num; index++) { + io_dec_win = io_dec_config + index; + ret = set_io_addr_dec(dram_wins_map, io_dec_win); + if (ret) { + ERROR("Failed to set IO address decode\n"); + return -1; + } + INFO("Set IO decode window successfully, base(0x%x)" + " win_attr(%x) max_dram_win(%d) max_remap(%d)" + " win_offset(%d)\n", io_dec_win->dec_reg_base, + io_dec_win->win_attr, io_dec_win->max_dram_win, + io_dec_win->max_remap, io_dec_win->win_offset); + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c new file mode 100644 index 0000000..3bf3d96 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include + +struct dec_win_config io_dec_win_conf[] = { + /* dec_reg_base win_attr max_dram_win max_remap win_offset */ + {0xc000, 0x3d, 2, 0, 0x08}, /* USB */ + {0xc100, 0x3d, 3, 0, 0x10}, /* USB3 */ + {0xc200, 0x3d, 2, 0, 0x10}, /* DMA */ + {0xc300, 0x3d, 2, 0, 0x10}, /* NETA0 */ + {0xc400, 0x3d, 2, 0, 0x10}, /* NETA1 */ + {0xc500, 0x3d, 2, 0, 0x10}, /* PCIe */ + {0xc800, 0x3d, 3, 0, 0x10}, /* SATA */ + {0xca00, 0x3d, 3, 0, 0x08}, /* SD */ + {0xcb00, 0x3d, 3, 0, 0x10}, /* eMMC */ + {0xce00, 0x3d, 2, 0, 0x08}, /* EIP97 */ +}; + +int marvell_get_io_dec_win_conf(struct dec_win_config **win, uint32_t *size) +{ + *win = io_dec_win_conf; + *size = sizeof(io_dec_win_conf)/sizeof(struct dec_win_config); + + return 0; +} + diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c new file mode 100644 index 0000000..56f091f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 Marek Behun + * + * Based on plat/marvell/armada/common/marvell_cci.c + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include + +static const int cci_map[] = { + PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX +}; + +/* + * This redefines the weak definition in + * plat/marvell/armada/common/marvell_cci.c + */ +void plat_marvell_interconnect_init(void) +{ + /* + * To better utilize the address space, we remap CCI base address from + * the default (0xD8000000) to MVEBU_CCI_BASE. + * This has to be done here, rather than in cpu_wins_init(), because + * cpu_wins_init() is called later. + */ + mmio_write_32(CPU_DEC_CCI_BASE_REG, MVEBU_CCI_BASE >> 20); + + cci_init(PLAT_MARVELL_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c new file mode 100644 index 0000000..e2d15ab --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c @@ -0,0 +1,822 @@ +/* + * Copyright (C) 2018-2020 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#ifdef USE_CCI +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Warm reset register */ +#define MVEBU_WARM_RESET_REG (MVEBU_NB_REGS_BASE + 0x840) +#define MVEBU_WARM_RESET_MAGIC 0x1D1E + +/* North Bridge GPIO1 SEL register */ +#define MVEBU_NB_GPIO1_SEL_REG (MVEBU_NB_REGS_BASE + 0x830) + #define MVEBU_NB_GPIO1_UART1_SEL BIT(19) + #define MVEBU_NB_GPIO1_GPIO_25_26_EN BIT(17) + #define MVEBU_NB_GPIO1_GPIO_19_EN BIT(14) + #define MVEBU_NB_GPIO1_GPIO_18_EN BIT(13) + +/* CPU 1 reset register */ +#define MVEBU_CPU_1_RESET_VECTOR (MVEBU_REGS_BASE + 0x14044) +#define MVEBU_CPU_1_RESET_REG (MVEBU_REGS_BASE + 0xD00C) +#define MVEBU_CPU_1_RESET_BIT 31 + +/* IRQ register */ +#define MVEBU_NB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE) +#define MVEBU_NB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ + 0x10) +#define MVEBU_NB_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ + 0x18) +#define MVEBU_SB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ + 0x40) +#define MVEBU_SB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ + 0x50) +#define MVEBU_NB_GPIO_IRQ_MASK_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ + 0xC8) +#define MVEBU_NB_GPIO_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ + 0xD8) +#define MVEBU_SB_GPIO_IRQ_MASK_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ + 0xE8) +#define MVEBU_NB_GPIO_IRQ_EN_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE) +#define MVEBU_NB_GPIO_IRQ_EN_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ + 0x04) +#define MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ + 0x10) +#define MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ + 0x14) +#define MVEBU_NB_GPIO_IRQ_WK_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ + 0x18) +#define MVEBU_NB_GPIO_IRQ_WK_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ + 0x1C) +#define MVEBU_SB_GPIO_IRQ_EN_REG (MVEBU_SB_GPIO_IRQ_REG_BASE) +#define MVEBU_SB_GPIO_IRQ_STATUS_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \ + 0x10) +#define MVEBU_SB_GPIO_IRQ_WK_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \ + 0x18) + +/* PMU registers */ +#define MVEBU_PM_NB_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE) + #define MVEBU_PM_PWR_DN_CNT_SEL BIT(28) + #define MVEBU_PM_SB_PWR_DWN BIT(4) + #define MVEBU_PM_INTERFACE_IDLE BIT(0) +#define MVEBU_PM_NB_CPU_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x4) + #define MVEBU_PM_L2_FLUSH_EN BIT(22) +#define MVEBU_PM_NB_PWR_OPTION_REG (MVEBU_PMSU_REG_BASE + 0x8) + #define MVEBU_PM_DDR_SR_EN BIT(29) + #define MVEBU_PM_DDR_CLK_DIS_EN BIT(28) + #define MVEBU_PM_WARM_RESET_EN BIT(27) + #define MVEBU_PM_DDRPHY_PWRDWN_EN BIT(23) + #define MVEBU_PM_DDRPHY_PAD_PWRDWN_EN BIT(22) + #define MVEBU_PM_OSC_OFF_EN BIT(21) + #define MVEBU_PM_TBG_OFF_EN BIT(20) + #define MVEBU_PM_CPU_VDDV_OFF_EN BIT(19) + #define MVEBU_PM_AVS_DISABLE_MODE BIT(14) + #define MVEBU_PM_AVS_VDD2_MODE BIT(13) + #define MVEBU_PM_AVS_HOLD_MODE BIT(12) + #define MVEBU_PM_L2_SRAM_LKG_PD_EN BIT(8) + #define MVEBU_PM_EIP_SRAM_LKG_PD_EN BIT(7) + #define MVEBU_PM_DDRMC_SRAM_LKG_PD_EN BIT(6) + #define MVEBU_PM_MCI_SRAM_LKG_PD_EN BIT(5) + #define MVEBU_PM_MMC_SRAM_LKG_PD_EN BIT(4) + #define MVEBU_PM_SATA_SRAM_LKG_PD_EN BIT(3) + #define MVEBU_PM_DMA_SRAM_LKG_PD_EN BIT(2) + #define MVEBU_PM_SEC_SRAM_LKG_PD_EN BIT(1) + #define MVEBU_PM_CPU_SRAM_LKG_PD_EN BIT(0) + #define MVEBU_PM_NB_SRAM_LKG_PD_EN (MVEBU_PM_L2_SRAM_LKG_PD_EN |\ + MVEBU_PM_EIP_SRAM_LKG_PD_EN | MVEBU_PM_DDRMC_SRAM_LKG_PD_EN |\ + MVEBU_PM_MCI_SRAM_LKG_PD_EN | MVEBU_PM_MMC_SRAM_LKG_PD_EN |\ + MVEBU_PM_SATA_SRAM_LKG_PD_EN | MVEBU_PM_DMA_SRAM_LKG_PD_EN |\ + MVEBU_PM_SEC_SRAM_LKG_PD_EN | MVEBU_PM_CPU_SRAM_LKG_PD_EN) +#define MVEBU_PM_NB_PWR_DEBUG_REG (MVEBU_PMSU_REG_BASE + 0xC) + #define MVEBU_PM_NB_FORCE_CLK_ON BIT(30) + #define MVEBU_PM_IGNORE_CM3_SLEEP BIT(21) + #define MVEBU_PM_IGNORE_CM3_DEEP BIT(20) +#define MVEBU_PM_NB_WAKE_UP_EN_REG (MVEBU_PMSU_REG_BASE + 0x2C) + #define MVEBU_PM_SB_WKP_NB_EN BIT(31) + #define MVEBU_PM_NB_GPIO_WKP_EN BIT(27) + #define MVEBU_PM_SOC_TIMER_WKP_EN BIT(26) + #define MVEBU_PM_UART_WKP_EN BIT(25) + #define MVEBU_PM_UART2_WKP_EN BIT(19) + #define MVEBU_PM_CPU_TIMER_WKP_EN BIT(17) + #define MVEBU_PM_NB_WKP_EN BIT(16) + #define MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN BIT(13) + #define MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN BIT(12) +#define MVEBU_PM_CPU_0_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x34) +#define MVEBU_PM_CPU_1_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x38) + #define MVEBU_PM_CORE_SOC_PD BIT(2) + #define MVEBU_PM_CORE_PROC_PD BIT(1) + #define MVEBU_PM_CORE_PD BIT(0) +#define MVEBU_PM_CORE_1_RETURN_ADDR_REG (MVEBU_PMSU_REG_BASE + 0x44) +#define MVEBU_PM_CPU_VDD_OFF_INFO_1_REG (MVEBU_PMSU_REG_BASE + 0x48) +#define MVEBU_PM_CPU_VDD_OFF_INFO_2_REG (MVEBU_PMSU_REG_BASE + 0x4C) + #define MVEBU_PM_LOW_POWER_STATE BIT(0) +#define MVEBU_PM_CPU_WAKE_UP_CONF_REG (MVEBU_PMSU_REG_BASE + 0x54) + #define MVEBU_PM_CORE1_WAKEUP BIT(13) + #define MVEBU_PM_CORE0_WAKEUP BIT(12) +#define MVEBU_PM_WAIT_DDR_RDY_VALUE (0x15) +#define MVEBU_PM_SB_CPU_PWR_CTRL_REG (MVEBU_SB_WAKEUP_REG_BASE) + #define MVEBU_PM_SB_PM_START BIT(0) +#define MVEBU_PM_SB_PWR_OPTION_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x4) + #define MVEBU_PM_SDIO_PHY_PDWN_EN BIT(17) + #define MVEBU_PM_SB_VDDV_OFF_EN BIT(16) + #define MVEBU_PM_EBM_SRAM_LKG_PD_EN BIT(11) + #define MVEBU_PM_PCIE_SRAM_LKG_PD_EN BIT(10) + #define MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN BIT(9) + #define MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN BIT(8) + #define MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN BIT(7) + #define MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN BIT(6) + #define MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN BIT(5) + #define MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN BIT(4) + #define MVEBU_PM_SDIO_SRAM_LKG_PD_EN BIT(3) + #define MVEBU_PM_USB2_SRAM_LKG_PD_EN BIT(2) + #define MVEBU_PM_USB3_H_SRAM_LKG_PD_EN BIT(1) + #define MVEBU_PM_SB_SRAM_LKG_PD_EN (MVEBU_PM_EBM_SRAM_LKG_PD_EN |\ + MVEBU_PM_PCIE_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN |\ + MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN |\ + MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN | MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN |\ + MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN | MVEBU_PM_SDIO_SRAM_LKG_PD_EN |\ + MVEBU_PM_USB2_SRAM_LKG_PD_EN | MVEBU_PM_USB3_H_SRAM_LKG_PD_EN) +#define MVEBU_PM_SB_WK_EN_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x10) + #define MVEBU_PM_SB_GPIO_WKP_EN BIT(24) + #define MVEBU_PM_SB_WKP_EN BIT(20) + +/* DRAM registers */ +#define MVEBU_DRAM_STATS_CH0_REG (MVEBU_DRAM_REG_BASE + 0x4) + #define MVEBU_DRAM_WCP_EMPTY BIT(19) +#define MVEBU_DRAM_CMD_0_REG (MVEBU_DRAM_REG_BASE + 0x20) + #define MVEBU_DRAM_CH0_CMD0 BIT(28) + #define MVEBU_DRAM_CS_CMD0 BIT(24) + #define MVEBU_DRAM_WCB_DRAIN_REQ BIT(1) +#define MVEBU_DRAM_PWR_CTRL_REG (MVEBU_DRAM_REG_BASE + 0x54) + #define MVEBU_DRAM_PHY_CLK_GATING_EN BIT(1) + #define MVEBU_DRAM_PHY_AUTO_AC_OFF_EN BIT(0) + +/* AVS registers */ +#define MVEBU_AVS_CTRL_2_REG (MVEBU_AVS_REG_BASE + 0x8) + #define MVEBU_LOW_VDD_MODE_EN BIT(6) + +/* Clock registers */ +#define MVEBU_NB_CLOCK_SEL_REG (MVEBU_NB_REGS_BASE + 0x10) + #define MVEBU_A53_CPU_CLK_SEL BIT(15) + +/* North Bridge Step-Down Registers */ +#define MVEBU_NB_STEP_DOWN_INT_EN_REG MVEBU_NB_STEP_DOWN_REG_BASE + #define MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK BIT(8) + +#define MVEBU_NB_GPIO_18 18 +#define MVEBU_NB_GPIO_19 19 +#define MVEBU_NB_GPIO_25 25 +#define MVEBU_NB_GPIO_26 26 + +typedef int (*wake_up_src_func)(union pm_wake_up_src_data *); + +struct wake_up_src_func_map { + enum pm_wake_up_src_type type; + wake_up_src_func func; +}; + +void marvell_psci_arch_init(int die_index) +{ +} + +static void a3700_pm_ack_irq(void) +{ + uint32_t reg; + + reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_1_REG); + if (reg) + mmio_write_32(MVEBU_NB_IRQ_STATUS_1_REG, reg); + + reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_2_REG); + if (reg) + mmio_write_32(MVEBU_NB_IRQ_STATUS_2_REG, reg); + + reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_1_REG); + if (reg) + mmio_write_32(MVEBU_SB_IRQ_STATUS_1_REG, reg); + + reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_2_REG); + if (reg) + mmio_write_32(MVEBU_SB_IRQ_STATUS_2_REG, reg); + + reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG); + if (reg) + mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG, reg); + + reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG); + if (reg) + mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG, reg); + + reg = mmio_read_32(MVEBU_SB_GPIO_IRQ_STATUS_REG); + if (reg) + mmio_write_32(MVEBU_SB_GPIO_IRQ_STATUS_REG, reg); +} + +/***************************************************************************** + * A3700 handler called to check the validity of the power state + * parameter. + ***************************************************************************** + */ +int a3700_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + ERROR("%s needs to be implemented\n", __func__); + panic(); +} + +/***************************************************************************** + * A3700 handler called when a CPU is about to enter standby. + ***************************************************************************** + */ +void a3700_cpu_standby(plat_local_state_t cpu_state) +{ + ERROR("%s needs to be implemented\n", __func__); + panic(); +} + +/***************************************************************************** + * A3700 handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ***************************************************************************** + */ +int a3700_pwr_domain_on(u_register_t mpidr) +{ + /* Set barrier */ + dsbsy(); + + /* Set the cpu start address to BL1 entry point */ + mmio_write_32(MVEBU_CPU_1_RESET_VECTOR, + PLAT_MARVELL_CPU_ENTRY_ADDR >> 2); + + /* Get the cpu out of reset */ + mmio_clrbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT)); + mmio_setbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT)); + + return 0; +} + +/***************************************************************************** + * A3700 handler called to validate the entry point. + ***************************************************************************** + */ +int a3700_validate_ns_entrypoint(uintptr_t entrypoint) +{ + return PSCI_E_SUCCESS; +} + +/***************************************************************************** + * A3700 handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ***************************************************************************** + */ +void a3700_pwr_domain_off(const psci_power_state_t *target_state) +{ + /* Prevent interrupts from spuriously waking up this cpu */ + plat_marvell_gic_cpuif_disable(); + + /* Core can not be powered down with pending IRQ, + * acknowledge all the pending IRQ + */ + a3700_pm_ack_irq(); +} + +static void a3700_set_gen_pwr_off_option(void) +{ + /* Enable L2 flush -> processor state-machine option */ + mmio_setbits_32(MVEBU_PM_NB_CPU_PWR_CTRL_REG, MVEBU_PM_L2_FLUSH_EN); + + /* + * North bridge cannot be VDD off (always ON). + * The NB state machine support low power mode by its state machine. + * This bit MUST be set for north bridge power down, e.g., + * OSC input cutoff(NOT TEST), SRAM power down, PMIC, etc. + * It is not related to CPU VDD OFF!! + */ + mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_CPU_VDDV_OFF_EN); + + /* + * MUST: Switch CPU/AXI clock to OSC + * NB state machine clock is always connected to OSC (slow clock). + * But Core0/1/processor state machine's clock are connected to AXI + * clock. Now, AXI clock takes the TBG as clock source. + * If using AXI clock, Core0/1/processor state machine may much faster + * than NB state machine. It will cause problem in this case if cores + * are released before north bridge gets ready. + */ + mmio_clrbits_32(MVEBU_NB_CLOCK_SEL_REG, MVEBU_A53_CPU_CLK_SEL); + + /* + * These register bits will trigger north bridge + * power-down state machine regardless CM3 status. + */ + mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_SLEEP); + mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_DEEP); + + /* + * SRAM => controlled by north bridge state machine. + * Core VDD OFF is not related to CPU SRAM power down. + */ + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_NB_SRAM_LKG_PD_EN); + + /* + * Idle AXI interface in order to get L2_WFI + * L2 WFI is only asserted after CORE-0 and CORE-1 WFI asserted. + * (only both core-0/1in WFI, L2 WFI will be issued by CORE.) + * Once L2 WFI asserted, this bit is used for signalling assertion + * to AXI IO masters. + */ + mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_INTERFACE_IDLE); + + /* Enable core0 and core1 VDD_OFF */ + mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PD); + mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PD); + + /* Enable North bridge power down - + * Both Cores MUST enable this bit to power down north bridge! + */ + mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD); + mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD); + + /* CA53 (processor domain) power down */ + mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD); + mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD); +} + +static void a3700_en_ddr_self_refresh(void) +{ + /* + * Both count is 16 bits and configurable. By default, osc stb cnt + * is 0xFFF for lower 12 bits. + * Thus, powerdown count is smaller than osc count. + * This count is used for exiting DDR SR mode on wakeup event. + * The powerdown count also has impact on the following + * state changes: idle -> count-down -> ... (power-down, vdd off, etc) + * Here, make stable counter shorter + * Use power down count value instead of osc_stb_cnt to speed up + * DDR self refresh exit + */ + mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_PWR_DN_CNT_SEL); + + /* + * Enable DDR SR mode => controlled by north bridge state machine + * Therefore, we must powerdown north bridge to trigger the DDR SR + * mode switching. + */ + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_SR_EN); + /* Disable DDR clock, otherwise DDR will not enter into SR mode. */ + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_CLK_DIS_EN); + /* Power down DDR PHY (PAD) */ + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDRPHY_PWRDWN_EN); + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, + MVEBU_PM_DDRPHY_PAD_PWRDWN_EN); + + /* Set wait time for DDR ready in ROM code */ + mmio_write_32(MVEBU_PM_CPU_VDD_OFF_INFO_1_REG, + MVEBU_PM_WAIT_DDR_RDY_VALUE); + + /* DDR flush write buffer - mandatory */ + mmio_write_32(MVEBU_DRAM_CMD_0_REG, MVEBU_DRAM_CH0_CMD0 | + MVEBU_DRAM_CS_CMD0 | MVEBU_DRAM_WCB_DRAIN_REQ); + while ((mmio_read_32(MVEBU_DRAM_STATS_CH0_REG) & + MVEBU_DRAM_WCP_EMPTY) != MVEBU_DRAM_WCP_EMPTY) + ; + + /* Trigger PHY reset after ddr out of self refresh => + * supply reset pulse for DDR phy after wake up + */ + mmio_setbits_32(MVEBU_DRAM_PWR_CTRL_REG, MVEBU_DRAM_PHY_CLK_GATING_EN | + MVEBU_DRAM_PHY_AUTO_AC_OFF_EN); +} + +static void a3700_pwr_dn_avs(void) +{ + /* + * AVS power down - controlled by north bridge statemachine + * Enable AVS power down by clear the AVS disable bit. + */ + mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_DISABLE_MODE); + /* + * Should set BIT[12:13] to powerdown AVS. + * 1. Enable AVS VDD2 mode + * 2. After power down AVS, we must hold AVS output voltage. + * 3. We can choose the lower VDD for AVS power down. + */ + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_VDD2_MODE); + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_HOLD_MODE); + + /* Enable low VDD mode, AVS will set CPU to lowest core VDD 747mV */ + mmio_setbits_32(MVEBU_AVS_CTRL_2_REG, MVEBU_LOW_VDD_MODE_EN); +} + +static void a3700_pwr_dn_tbg(void) +{ + /* Power down TBG */ + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_TBG_OFF_EN); +} + +static void a3700_pwr_dn_sb(void) +{ + /* Enable south bridge power down option */ + mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_SB_PWR_DWN); + + /* Enable SDIO_PHY_PWRDWN */ + mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SDIO_PHY_PDWN_EN); + + /* Enable SRAM LRM on SB */ + mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_SRAM_LKG_PD_EN); + + /* Enable SB Power Off */ + mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_VDDV_OFF_EN); + + /* Kick off South Bridge Power Off */ + mmio_setbits_32(MVEBU_PM_SB_CPU_PWR_CTRL_REG, MVEBU_PM_SB_PM_START); +} + +static void a3700_set_pwr_off_option(void) +{ + /* Set general power off option */ + a3700_set_gen_pwr_off_option(); + + /* Enable DDR self refresh in low power mode */ + a3700_en_ddr_self_refresh(); + + /* Power down AVS */ + a3700_pwr_dn_avs(); + + /* Power down TBG */ + a3700_pwr_dn_tbg(); + + /* Power down south bridge, pay attention south bridge setting + * should be done before + */ + a3700_pwr_dn_sb(); +} + +static void a3700_set_wake_up_option(void) +{ + /* + * Enable the wakeup event for NB SOC => north-bridge + * state-machine enablement on wake-up event + */ + mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_WKP_EN); + + /* Enable both core0 and core1 wakeup on demand */ + mmio_setbits_32(MVEBU_PM_CPU_WAKE_UP_CONF_REG, + MVEBU_PM_CORE1_WAKEUP | MVEBU_PM_CORE0_WAKEUP); + + /* Enable warm reset in low power mode */ + mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_WARM_RESET_EN); +} + +static void a3700_pm_en_nb_gpio(uint32_t gpio) +{ + /* For GPIO1 interrupt -- North bridge only */ + if (gpio >= 32) { + /* GPIO int mask */ + mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_2_REG, BIT(gpio - 32)); + + /* NB_CPU_WAKE-up ENABLE GPIO int */ + mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_HIGH_REG, BIT(gpio - 32)); + } else { + /* GPIO int mask */ + mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_1_REG, BIT(gpio)); + + /* NB_CPU_WAKE-up ENABLE GPIO int */ + mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_LOW_REG, BIT(gpio)); + } + + mmio_setbits_32(MVEBU_NB_STEP_DOWN_INT_EN_REG, + MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK); + + /* Enable using GPIO as wakeup event + * (actually not only for north bridge) + */ + mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_GPIO_WKP_EN | + MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN | + MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN); +} + +static void a3700_pm_en_sb_gpio(uint32_t gpio) +{ + /* Enable using GPIO as wakeup event */ + mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_SB_WKP_NB_EN | + MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN | + MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN); + + /* SB GPIO Wake UP | South Bridge Wake Up Enable */ + mmio_setbits_32(MVEBU_PM_SB_WK_EN_REG, MVEBU_PM_SB_GPIO_WKP_EN | + MVEBU_PM_SB_GPIO_WKP_EN); + + /* GPIO int mask */ + mmio_clrbits_32(MVEBU_SB_GPIO_IRQ_MASK_REG, BIT(gpio)); + + /* NB_CPU_WAKE-up ENABLE GPIO int */ + mmio_setbits_32(MVEBU_SB_GPIO_IRQ_EN_REG, BIT(gpio)); +} + +int a3700_pm_src_gpio(union pm_wake_up_src_data *src_data) +{ + if (src_data->gpio_data.bank_num == 0) + /* North Bridge GPIO */ + a3700_pm_en_nb_gpio(src_data->gpio_data.gpio_num); + else + a3700_pm_en_sb_gpio(src_data->gpio_data.gpio_num); + return 0; +} + +int a3700_pm_src_uart1(union pm_wake_up_src_data *src_data) +{ + /* Clear Uart1 select */ + mmio_clrbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_UART1_SEL); + /* set pin 19 gpio usage*/ + mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_19_EN); + /* Enable gpio wake-up*/ + a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_19); + /* set pin 18 gpio usage*/ + mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_18_EN); + /* Enable gpio wake-up*/ + a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_18); + + return 0; +} + +int a3700_pm_src_uart0(union pm_wake_up_src_data *src_data) +{ + /* set pin 25/26 gpio usage*/ + mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_25_26_EN); + /* Enable gpio wake-up*/ + a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_25); + /* Enable gpio wake-up*/ + a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_26); + + return 0; +} + +struct wake_up_src_func_map src_func_table[WAKE_UP_SRC_MAX] = { + {WAKE_UP_SRC_GPIO, a3700_pm_src_gpio}, + {WAKE_UP_SRC_UART1, a3700_pm_src_uart1}, + {WAKE_UP_SRC_UART0, a3700_pm_src_uart0}, + /* FOLLOWING SRC NOT SUPPORTED YET */ + {WAKE_UP_SRC_TIMER, NULL} +}; + +static wake_up_src_func a3700_get_wake_up_src_func( + enum pm_wake_up_src_type type) +{ + uint32_t loop; + + for (loop = 0; loop < WAKE_UP_SRC_MAX; loop++) { + if (src_func_table[loop].type == type) + return src_func_table[loop].func; + } + return NULL; +} + +#pragma weak mv_wake_up_src_config_get +struct pm_wake_up_src_config *mv_wake_up_src_config_get(void) +{ + static struct pm_wake_up_src_config wake_up_src_cfg = {}; + return &wake_up_src_cfg; +} + +static void a3700_set_wake_up_source(void) +{ + struct pm_wake_up_src_config *wake_up_src; + uint32_t loop; + wake_up_src_func src_func = NULL; + + wake_up_src = mv_wake_up_src_config_get(); + for (loop = 0; loop < wake_up_src->wake_up_src_num; loop++) { + src_func = a3700_get_wake_up_src_func( + wake_up_src->wake_up_src[loop].wake_up_src_type); + if (src_func) + src_func( + &(wake_up_src->wake_up_src[loop].wake_up_data)); + } +} + +static void a3700_pm_save_lp_flag(void) +{ + /* Save the flag for enter the low power mode */ + mmio_setbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG, + MVEBU_PM_LOW_POWER_STATE); +} + +static void a3700_pm_clear_lp_flag(void) +{ + /* Clear the flag for enter the low power mode */ + mmio_clrbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG, + MVEBU_PM_LOW_POWER_STATE); +} + +static uint32_t a3700_pm_get_lp_flag(void) +{ + /* Get the flag for enter the low power mode */ + return mmio_read_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG) & + MVEBU_PM_LOW_POWER_STATE; +} + +/***************************************************************************** + * A3700 handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ***************************************************************************** + */ +void a3700_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + /* Prevent interrupts from spuriously waking up this cpu */ + plat_marvell_gic_cpuif_disable(); + + /* Save IRQ states */ + plat_marvell_gic_irq_save(); + + /* Set wake up options */ + a3700_set_wake_up_option(); + + /* Set wake up sources */ + a3700_set_wake_up_source(); + + /* SoC can not be powered down with pending IRQ, + * acknowledge all the pending IRQ + */ + a3700_pm_ack_irq(); + + /* Set power off options */ + a3700_set_pwr_off_option(); + + /* Save the flag for enter the low power mode */ + a3700_pm_save_lp_flag(); + + isb(); +} + +/***************************************************************************** + * A3700 handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ***************************************************************************** + */ +void a3700_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* arch specific configuration */ + marvell_psci_arch_init(0); + + /* Per-CPU interrupt initialization */ + plat_marvell_gic_pcpu_init(); + plat_marvell_gic_cpuif_enable(); + + /* Restore the per-cpu IRQ state */ + if (a3700_pm_get_lp_flag()) + plat_marvell_gic_irq_pcpu_restore(); +} + +/***************************************************************************** + * A3700 handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ***************************************************************************** + */ +void a3700_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + struct dec_win_config *io_dec_map; + uint32_t dec_win_num; + struct dram_win_map dram_wins_map; + + /* arch specific configuration */ + marvell_psci_arch_init(0); + + /* Interrupt initialization */ + plat_marvell_gic_init(); + + /* Restore IRQ states */ + plat_marvell_gic_irq_restore(); + + /* + * Initialize CCI for this cluster after resume from suspend state. + * No need for locks as no other CPU is active. + */ + plat_marvell_interconnect_init(); + /* + * Enable CCI coherency for the primary CPU's cluster. + * Platform specific PSCI code will enable coherency for other + * clusters. + */ + plat_marvell_interconnect_enter_coherency(); + + /* CPU address decoder windows initialization. */ + cpu_wins_init(); + + /* fetch CPU-DRAM window mapping information by reading + * CPU-DRAM decode windows (only the enabled ones) + */ + dram_win_map_build(&dram_wins_map); + + /* Get IO address decoder windows */ + if (marvell_get_io_dec_win_conf(&io_dec_map, &dec_win_num)) { + printf("No IO address decoder windows configurations found!\n"); + return; + } + + /* IO address decoder init */ + if (init_io_addr_dec(&dram_wins_map, io_dec_map, dec_win_num)) { + printf("IO address decoder windows initialization failed!\n"); + return; + } + + /* Clear low power mode flag */ + a3700_pm_clear_lp_flag(); +} + +/***************************************************************************** + * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND + * call to get the `power_state` parameter. This allows the platform to encode + * the appropriate State-ID field within the `power_state` parameter which can + * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. + ***************************************************************************** + */ +void a3700_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + /* lower affinities use PLAT_MAX_OFF_STATE */ + for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +/***************************************************************************** + * A3700 handlers to shutdown/reboot the system + ***************************************************************************** + */ +static void __dead2 a3700_system_off(void) +{ + ERROR("%s needs to be implemented\n", __func__); + panic(); +} + +#pragma weak cm3_system_reset +void cm3_system_reset(void) +{ +} + +/***************************************************************************** + * A3700 handlers to reset the system + ***************************************************************************** + */ +static void __dead2 a3700_system_reset(void) +{ + /* Clean the mailbox magic number to let it as act like cold boot */ + mmio_write_32(PLAT_MARVELL_MAILBOX_BASE, 0x0); + + dsbsy(); + + /* Flush data cache if the mail box shared RAM is cached */ +#if PLAT_MARVELL_SHARED_RAM_CACHED + flush_dcache_range((uintptr_t)PLAT_MARVELL_MAILBOX_BASE, + 2 * sizeof(uint64_t)); +#endif + + /* Use Cortex-M3 secure coprocessor for system reset */ + cm3_system_reset(); + + /* Trigger the warm reset */ + mmio_write_32(MVEBU_WARM_RESET_REG, MVEBU_WARM_RESET_MAGIC); + + /* Shouldn't get to this point */ + panic(); +} + +/***************************************************************************** + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ***************************************************************************** + */ +const plat_psci_ops_t plat_arm_psci_pm_ops = { + .cpu_standby = a3700_cpu_standby, + .pwr_domain_on = a3700_pwr_domain_on, + .pwr_domain_off = a3700_pwr_domain_off, + .pwr_domain_suspend = a3700_pwr_domain_suspend, + .pwr_domain_on_finish = a3700_pwr_domain_on_finish, + .pwr_domain_suspend_finish = a3700_pwr_domain_suspend_finish, + .get_sys_suspend_power_state = a3700_get_sys_suspend_power_state, + .system_off = a3700_system_off, + .system_reset = a3700_system_reset, + .validate_power_state = a3700_validate_power_state, + .validate_ns_entrypoint = a3700_validate_ns_entrypoint +}; diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c new file mode 100644 index 0000000..355770b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include +#include + +/* + * This function may modify the default DRAM parameters + * based on information received from SPD or bootloader + * configuration located on non volatile storage + */ +void plat_marvell_dram_update_topology(void) +{ +} + +/* + * This struct provides the DRAM training code with + * the appropriate board DRAM configuration + */ +static struct mv_ddr_topology_map board_topology_map = { +/* FIXME: MISL board 2CS 4Gb x8 devices of micron - 2133P */ + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0} }, + SPEED_BIN_DDR_2133P, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_4GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ + MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */ + }, + { + MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */ + MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */ + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */ + }, + } +}; + +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) +{ + /* Return the board topology as defined in the board code */ + return &board_topology_map; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c new file mode 100644 index 0000000..a409261 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#ifndef IMAGE_BLE + +/***************************************************************************** + * AMB Configuration + ***************************************************************************** + */ +struct addr_map_win amb_memory_map[] = { + /* CP0 SPI1 CS0 Direct Mode access */ + {0xf900, 0x1000000, AMB_SPI1_CS0_ID}, +}; + +int marvell_get_amb_memory_map(struct addr_map_win **win, + uint32_t *size, uintptr_t base) +{ + *win = amb_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(amb_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * IO_WIN Configuration + ***************************************************************************** + */ +struct addr_map_win io_win_memory_map[] = { +#ifndef IMAGE_BLE + /* MCI 0 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID}, + /* MCI 1 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID}, +#endif +}; + +uint32_t marvell_get_io_win_gcr_target(int ap_index) +{ + return PIDI_TID; +} + +int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = io_win_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(io_win_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * IOB Configuration + ***************************************************************************** + */ +struct addr_map_win iob_memory_map[] = { + /* PEX1_X1 window */ + {0x00000000f7000000, 0x1000000, PEX1_TID}, + /* PEX2_X1 window */ + {0x00000000f8000000, 0x1000000, PEX2_TID}, + {0x00000000c0000000, 0x30000000, PEX2_TID}, + {0x0000000800000000, 0x100000000, PEX2_TID}, + /* PEX0_X4 window */ + {0x00000000f6000000, 0x1000000, PEX0_TID}, + /* SPI1_CS0 (RUNIT) window */ + {0x00000000f9000000, 0x1000000, RUNIT_TID}, +}; + +int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + *win = iob_memory_map; + *size = ARRAY_SIZE(iob_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * CCU Configuration + ***************************************************************************** + */ +struct addr_map_win ccu_memory_map[] = { /* IO window */ +#ifdef IMAGE_BLE + {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */ +#else +#if LLC_SRAM + /* This entry is prepared for OP-TEE OS that enables the LLC SRAM + * and changes the window target to SRAM_TID. + */ + {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID}, +#endif + {0x00000000f2000000, 0xe000000, IO_0_TID}, + {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */ + {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */ +#endif +}; + +uint32_t marvell_get_ccu_gcr_target(int ap) +{ + return DRAM_0_TID; +} + +int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = ccu_memory_map; + *size = ARRAY_SIZE(ccu_memory_map); + + return 0; +} + +#ifdef IMAGE_BLE +/***************************************************************************** + * SKIP IMAGE Configuration + ***************************************************************************** + */ +#if PLAT_RECOVERY_IMAGE_ENABLE +struct skip_image skip_im = { + .detection_method = GPIO, + .info.gpio.num = 33, + .info.gpio.button_state = HIGH, + .info.test.cp_ap = CP, + .info.test.cp_index = 0, +}; + +void *plat_marvell_get_skip_image_data(void) +{ + /* Return the skip_image configurations */ + return &skip_im; +} +#endif +#endif diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h new file mode 100644 index 0000000..72bca12 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_DEF_H +#define MVEBU_DEF_H + +#include + +#define CP_COUNT 1 /* A70x0 has single CP0 */ + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/platform.mk new file mode 100644 index 0000000..39eb712 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/platform.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PCI_EP_SUPPORT := 0 + +CP_NUM := 1 +$(eval $(call add_define,CP_NUM)) + +DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg + +MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c + +BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST))) +include plat/marvell/armada/a8k/common/a8k_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c new file mode 100644 index 0000000..9c8c97e --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include +#include + +/* + * This function may modify the default DRAM parameters + * based on information received from SPD or bootloader + * configuration located on non volatile storage + */ +void plat_marvell_dram_update_topology(void) +{ +} + +/* + * This struct provides the DRAM training code with + * the appropriate board DRAM configuration + */ +static struct mv_ddr_topology_map board_topology_map = { +/* FIXME: MISL board 2CS 8Gb x8 devices of micron - 2133P */ + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0} }, + SPEED_BIN_DDR_2400T, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_8GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ + MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */ + }, + { + MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */ + MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */ + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */ + }, + } +}; + +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) +{ + /* Return the board topology as defined in the board code */ + return &board_topology_map; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c new file mode 100644 index 0000000..3b68e91 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#ifndef IMAGE_BLE + +/***************************************************************************** + * AMB Configuration + ***************************************************************************** + */ +struct addr_map_win *amb_memory_map; + +int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + *win = amb_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(amb_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * IO WIN Configuration + ***************************************************************************** + */ +struct addr_map_win io_win_memory_map[] = { +#ifndef IMAGE_BLE + /* MCI 0 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID}, + /* MCI 1 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID}, +#endif +}; + +uint32_t marvell_get_io_win_gcr_target(int ap_index) +{ + return PIDI_TID; +} + +int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = io_win_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(io_win_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * IOB Configuration + ***************************************************************************** + */ +struct addr_map_win iob_memory_map[] = { + /* PEX0_X4 window */ + {0x00000000f6000000, 0x6000000, PEX0_TID}, + {0x00000000c0000000, 0x30000000, PEX0_TID}, + {0x0000000800000000, 0x200000000, PEX0_TID}, +}; + +int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + *win = iob_memory_map; + *size = ARRAY_SIZE(iob_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * CCU Configuration + ***************************************************************************** + */ +struct addr_map_win ccu_memory_map[] = { +#ifdef IMAGE_BLE + {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */ +#else +#if LLC_SRAM + /* This entry is prepared for OP-TEE OS that enables the LLC SRAM + * and changes the window target to SRAM_TID. + */ + {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID}, +#endif + {0x00000000f2000000, 0xe000000, IO_0_TID}, + {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */ + {0x0000000800000000, 0x200000000, IO_0_TID}, /* IO window */ +#endif +}; + +uint32_t marvell_get_ccu_gcr_target(int ap) +{ + return DRAM_0_TID; +} + +int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = ccu_memory_map; + *size = ARRAY_SIZE(ccu_memory_map); + + return 0; +} + +#ifdef IMAGE_BLE + +struct pci_hw_cfg *plat_get_pcie_hw_data(void) +{ + return NULL; +} + +/***************************************************************************** + * SKIP IMAGE Configuration + ***************************************************************************** + */ +#if PLAT_RECOVERY_IMAGE_ENABLE +struct skip_image skip_im = { + .detection_method = GPIO, + .info.gpio.num = 33, + .info.gpio.button_state = HIGH, + .info.test.cp_ap = CP, + .info.test.cp_index = 0, +}; + +void *plat_marvell_get_skip_image_data(void) +{ + /* Return the skip_image configurations */ + return &skip_im; +} +#endif +#endif diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h new file mode 100644 index 0000000..cedf323 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_DEF_H +#define MVEBU_DEF_H + +#include + +#define CP_COUNT 1 /* A70x0 has single CP0 */ + +/*********************************************************************** + * Required platform porting definitions common to all + * Management Compute SubSystems (MSS) + *********************************************************************** + */ +/* + * Load address of SCP_BL2 + * SCP_BL2 is loaded to the same place as BL31. + * Once SCP_BL2 is transferred to the SCP, + * it is discarded and BL31 is loaded over the top. + */ +#ifdef SCP_IMAGE +#define SCP_BL2_BASE BL31_BASE +#endif + + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/platform.mk new file mode 100644 index 0000000..39eb712 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/platform.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PCI_EP_SUPPORT := 0 + +CP_NUM := 1 +$(eval $(call add_define,CP_NUM)) + +DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg + +MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c + +BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST))) +include plat/marvell/armada/a8k/common/a8k_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c new file mode 100644 index 0000000..68d335b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2021 Sartura Ltd. + * Copyright (C) 2021 Globalscale technologies, Inc. + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include +#include + +/* + * This function may modify the default DRAM parameters + * based on information received from SPD or bootloader + * configuration located on non volatile storage + */ +void plat_marvell_dram_update_topology(void) +{ +} + +/* + * This struct provides the DRAM training code with + * the appropriate board DRAM configuration + */ +#if DDR_TOPOLOGY == 0 +static struct mv_ddr_topology_map board_topology_map_2g = { +/* 1CS 4Gb x4 devices of Samsung K4A4G085WF */ + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0} }, + SPEED_BIN_DDR_2400R, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_4GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* subphys mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */ + }, + { + MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */ + MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */ + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */ + }, + } +}; +#endif + +#if DDR_TOPOLOGY == 1 +static struct mv_ddr_topology_map board_topology_map_4g = { +/* 1CS 8Gb x4 devices of Samsung K4A8G085WC-BCTD */ + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0}, + {0x1, 0x2, 0, 0} }, + SPEED_BIN_DDR_2400R, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_8GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* subphys mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */ + }, + { + MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */ + MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */ + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */ + }, + } +}; +#endif + +#if DDR_TOPOLOGY == 2 +static struct mv_ddr_topology_map board_topology_map_8g = { +/* 2CS 8Gb x8 devices of Micron MT40A1G8WE-083E IT */ + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0}, + {0x3, 0x2, 0, 0} }, + SPEED_BIN_DDR_2400R, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_8GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* subphys mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */ + }, + { + MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */ + MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */ + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */ + }, + } +}; +#endif + +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) +{ +/* a70x0_mochabin board supports 3 DDR4 models (2G/1CS, 4G/1CS, 8G/2CS) */ +#if DDR_TOPOLOGY == 0 + return &board_topology_map_2g; +#elif DDR_TOPOLOGY == 1 + return &board_topology_map_4g; +#elif DDR_TOPOLOGY == 2 + return &board_topology_map_8g; +#else + #error "Unknown DDR topology" +#endif +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c new file mode 100644 index 0000000..1ed6323 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2021 Sartura Ltd. + * Copyright (C) 2021 Globalscale technologies, Inc. + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#ifndef IMAGE_BLE + +/***************************************************************************** + * AMB Configuration + ***************************************************************************** + */ +struct addr_map_win amb_memory_map[] = { + /* CP0 SPI1 CS0 Direct Mode access */ + {0xf900, 0x1000000, AMB_SPI1_CS0_ID}, +}; + +int marvell_get_amb_memory_map(struct addr_map_win **win, + uint32_t *size, uintptr_t base) +{ + *win = amb_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(amb_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * IO_WIN Configuration + ***************************************************************************** + */ +struct addr_map_win io_win_memory_map[] = { +#ifndef IMAGE_BLE + /* MCI 0 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID}, + /* MCI 1 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID}, +#endif +}; + +uint32_t marvell_get_io_win_gcr_target(int ap_index) +{ + return PIDI_TID; +} + +int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = io_win_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(io_win_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * IOB Configuration + ***************************************************************************** + */ +struct addr_map_win iob_memory_map[] = { + /* PEX1_X1 window */ + {0x00000000f7000000, 0x1000000, PEX1_TID}, + /* PEX2_X1 window */ + {0x00000000f8000000, 0x1000000, PEX2_TID}, + {0x00000000c0000000, 0x30000000, PEX2_TID}, + {0x0000000800000000, 0x100000000, PEX2_TID}, + /* PEX0_X4 window */ + {0x00000000f6000000, 0x1000000, PEX0_TID}, + /* SPI1_CS0 (RUNIT) window */ + {0x00000000f9000000, 0x1000000, RUNIT_TID}, +}; + +int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + *win = iob_memory_map; + *size = ARRAY_SIZE(iob_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * CCU Configuration + ***************************************************************************** + */ +struct addr_map_win ccu_memory_map[] = { /* IO window */ +#ifdef IMAGE_BLE + {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */ +#else +#if LLC_SRAM + /* This entry is prepared for OP-TEE OS that enables the LLC SRAM + * and changes the window target to SRAM_TID. + */ + {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID}, +#endif + {0x00000000f2000000, 0xe000000, IO_0_TID}, + {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */ + {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */ +#endif +}; + +uint32_t marvell_get_ccu_gcr_target(int ap) +{ + return DRAM_0_TID; +} + +int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = ccu_memory_map; + *size = ARRAY_SIZE(ccu_memory_map); + + return 0; +} + +#ifdef IMAGE_BLE +/***************************************************************************** + * SKIP IMAGE Configuration + ***************************************************************************** + */ +#if PLAT_RECOVERY_IMAGE_ENABLE +void *plat_marvell_get_skip_image_data(void) +{ + /* No recovery button on a70x0_mochabin board */ + return NULL; +} +#endif +#endif diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h new file mode 100644 index 0000000..ab76c31 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2021 Sartura Ltd. + * Copyright (C) 2021 Globalscale technologies, Inc. + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef __PHY_PORTING_LAYER_H +#define __PHY_PORTING_LAYER_H + +#define MAX_LANE_NR 6 + +static const struct xfi_params + xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + /* AP0 */ + { + /* CP 0 */ + { + { 0 }, /* Comphy0 */ + { 0 }, /* Comphy1 */ + { 0 }, /* Comphy2 */ + { 0 }, /* Comphy3 */ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, .align90 = 0x60, + .g1_dfe_res = 0x1, .g1_amp = 0x1c, .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, .g1_tx_emph_en = 0x1, + .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 1 }, /* Comphy4 */ + { 0 }, /* Comphy5 */ + }, + }, +}; + +static const struct sata_params + sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + /* AP0 */ + { + /* CP 0 */ + { + { 0 }, /* Comphy0 */ + { 0 }, /* Comphy1 */ + { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e, + .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe, + .g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1, + .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, .g3_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, .g3_tx_emph_en = 0x0, + .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1, + .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf, + .align90 = 0x61, + .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, .g3_rx_selmuff = 0x3, + .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, .g3_rx_selmufi = 0x3, + .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, .g3_rx_selmupf = 0x2, + .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, .g3_rx_selmupi = 0x2, + .polarity_invert = COMPHY_POLARITY_NO_INVERT, + .valid = 0x1 + }, /* Comphy2 */ + { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e, + .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe, + .g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1, + .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, .g3_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, .g3_tx_emph_en = 0x0, + .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1, + .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf, + .align90 = 0x61, + .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, .g3_rx_selmuff = 0x3, + .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, .g3_rx_selmufi = 0x3, + .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, .g3_rx_selmupf = 0x2, + .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, .g3_rx_selmupi = 0x2, + .polarity_invert = COMPHY_POLARITY_NO_INVERT, + .valid = 0x1 + }, /* Comphy3 */ + { 0 }, /* Comphy4 */ + { 0 }, /* Comphy5 */ + }, + }, +}; + +static const struct usb_params + usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = { + .polarity_invert = COMPHY_POLARITY_NO_INVERT + }, +}; + +#endif /* __PHY_PORTING_LAYER_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h new file mode 100644 index 0000000..768f735 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_DEF_H +#define MVEBU_DEF_H + +#include + +#define CP_COUNT 1 /* A70x0 has single CP0 */ + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk new file mode 100644 index 0000000..2495591 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2021 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PCI_EP_SUPPORT := 0 + +CP_NUM := 1 +$(eval $(call add_define,CP_NUM)) + +DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg + +MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c + +BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST))) +include plat/marvell/armada/a8k/common/a8k_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c new file mode 100644 index 0000000..47bc0a8 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include + +#include +#include +#include + +#define MVEBU_AP_MPP_CTRL0_7_REG MVEBU_AP_MPP_REGS(0) +#define MVEBU_AP_MPP_CTRL4_OFFS 16 +#define MVEBU_AP_MPP_CTRL5_OFFS 20 +#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA 0x3 +#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA 0x3 + +#define MVEBU_CP_MPP_CTRL37_OFFS 20 +#define MVEBU_CP_MPP_CTRL38_OFFS 24 +#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2 +#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2 + +#define MVEBU_MPP_CTRL_MASK 0xf + +/* + * This struct provides the DRAM training code with + * the appropriate board DRAM configuration + */ +static struct mv_ddr_topology_map board_topology_map = { + /* MISL board with 1CS 8Gb x4 devices of Micron 2400T */ + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */ + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0} }, + /* TODO: double check if the speed bin is 2400T */ + SPEED_BIN_DDR_2400T, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_8GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ +#if DDR32 + MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */ +#else + MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */ +#endif + MV_DDR_CFG_SPD, /* ddr configuration data source */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */ + }, + { + MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */ + MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */ + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */ + }, + } +}; + +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) +{ + /* Return the board topology as defined in the board code */ + return &board_topology_map; +} + +static void mpp_config(void) +{ + uintptr_t reg; + uint32_t val; + + reg = MVEBU_CP_MPP_REGS(0, 4); + /* configure CP0 MPP 37 and 38 to i2c */ + val = mmio_read_32(reg); + val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS)); + val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA << + MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA << + MVEBU_CP_MPP_CTRL38_OFFS); + mmio_write_32(reg, val); +} + +/* + * This function may modify the default DRAM parameters + * based on information received from SPD or bootloader + * configuration located on non volatile storage + */ +void plat_marvell_dram_update_topology(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + INFO("Gathering DRAM information\n"); + + if (tm->cfg_src == MV_DDR_CFG_SPD) { + /* configure MPPs to enable i2c */ + mpp_config(); + + /* initialize i2c */ + i2c_init((void *)MVEBU_CP0_I2C_BASE); + + /* select SPD memory page 0 to access DRAM configuration */ + i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0); + + /* read data from spd */ + i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes, + sizeof(tm->spd_data.all_bytes)); + } +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c new file mode 100644 index 0000000..4ccda14 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#ifndef IMAGE_BLE + +/***************************************************************************** + * AMB Configuration + ***************************************************************************** + */ +struct addr_map_win amb_memory_map[] = { + /* CP1 SPI1 CS0 Direct Mode access */ + {0xf900, 0x1000000, AMB_SPI1_CS0_ID}, +}; + +int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + *win = amb_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(amb_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * IO WIN Configuration + ***************************************************************************** + */ +struct addr_map_win io_win_memory_map[] = { + /* CP1 (MCI0) internal regs */ + {0x00000000f4000000, 0x2000000, MCI_0_TID}, +#ifndef IMAGE_BLE + /* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/ + {0x00000000f9000000, 0x2000000, MCI_0_TID}, + /* PCIe1 on CP1*/ + {0x00000000fb000000, 0x1000000, MCI_0_TID}, + /* PCIe2 on CP1*/ + {0x00000000fc000000, 0x1000000, MCI_0_TID}, + /* MCI 0 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID}, + /* MCI 1 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID}, +#endif +}; + +uint32_t marvell_get_io_win_gcr_target(int ap_index) +{ + return PIDI_TID; +} + +int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = io_win_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(io_win_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * IOB Configuration + ***************************************************************************** + */ +struct addr_map_win iob_memory_map_cp0[] = { + /* CP0 */ + /* PEX1_X1 window */ + {0x00000000f7000000, 0x1000000, PEX1_TID}, + /* PEX2_X1 window */ + {0x00000000f8000000, 0x1000000, PEX2_TID}, + /* PEX0_X4 window */ + {0x00000000f6000000, 0x1000000, PEX0_TID}, + {0x00000000c0000000, 0x30000000, PEX0_TID}, + {0x0000000800000000, 0x100000000, PEX0_TID}, +}; + +struct addr_map_win iob_memory_map_cp1[] = { + /* CP1 */ + /* SPI1_CS0 (RUNIT) window */ + {0x00000000f9000000, 0x1000000, RUNIT_TID}, + /* PEX1_X1 window */ + {0x00000000fb000000, 0x1000000, PEX1_TID}, + /* PEX2_X1 window */ + {0x00000000fc000000, 0x1000000, PEX2_TID}, + /* PEX0_X4 window */ + {0x00000000fa000000, 0x1000000, PEX0_TID} +}; + +int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + switch (base) { + case MVEBU_CP_REGS_BASE(0): + *win = iob_memory_map_cp0; + *size = ARRAY_SIZE(iob_memory_map_cp0); + return 0; + case MVEBU_CP_REGS_BASE(1): + *win = iob_memory_map_cp1; + *size = ARRAY_SIZE(iob_memory_map_cp1); + return 0; + default: + *size = 0; + *win = 0; + return 1; + } +} +#endif + +/***************************************************************************** + * CCU Configuration + ***************************************************************************** + */ +struct addr_map_win ccu_memory_map[] = { +#ifdef IMAGE_BLE + {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */ +#else +#if LLC_SRAM + /* This entry is prepared for OP-TEE OS that enables the LLC SRAM + * and changes the window target to SRAM_TID. + */ + {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID}, +#endif + {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */ + {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */ + {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */ +#endif +}; + +uint32_t marvell_get_ccu_gcr_target(int ap) +{ + return DRAM_0_TID; +} + +int marvell_get_ccu_memory_map(int ap, struct addr_map_win **win, + uint32_t *size) +{ + *win = ccu_memory_map; + *size = ARRAY_SIZE(ccu_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * SoC PM configuration + ***************************************************************************** + */ +/* CP GPIO should be used and the GPIOs should be within same GPIO register */ +struct power_off_method pm_cfg = { + .type = PMIC_GPIO, + .cfg.gpio.pin_count = 1, + .cfg.gpio.info = {{0, 35} }, + .cfg.gpio.step_count = 7, + .cfg.gpio.seq = {1, 0, 1, 0, 1, 0, 1}, + .cfg.gpio.delay_ms = 10, +}; + +void *plat_marvell_get_pm_cfg(void) +{ + /* Return the PM configurations */ + return &pm_cfg; +} + +/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */ +#else +/***************************************************************************** + * SKIP IMAGE Configuration + ***************************************************************************** + */ +#if PLAT_RECOVERY_IMAGE_ENABLE +struct skip_image skip_im = { + .detection_method = GPIO, + .info.gpio.num = 33, + .info.gpio.button_state = HIGH, + .info.test.cp_ap = CP, + .info.test.cp_index = 0, +}; + +void *plat_marvell_get_skip_image_data(void) +{ + /* Return the skip_image configurations */ + return &skip_im; +} +#endif +#endif diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h new file mode 100644 index 0000000..afa3be1 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PHY_PORTING_LAYER_H +#define PHY_PORTING_LAYER_H + +#define MAX_LANE_NR 6 + +static const struct xfi_params + xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + /* AP0 */ + { + /* CP 0 */ + { + { 0 }, /* Comphy0 */ + { 0 }, /* Comphy1 */ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0, + .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 0x1 }, /* Comphy2 */ + { 0 }, /* Comphy3 */ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0, + .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 0x1 }, /* Comphy4 */ + { 0 }, /* Comphy5 */ + }, + + /* CP 1 */ + { + { 0 }, /* Comphy0 */ + { 0 }, /* Comphy1 */ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0, + .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 0x1 }, /* Comphy2 */ + { 0 }, /* Comphy3 */ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0, + .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 0x1 }, /* Comphy4 */ + { 0 }, /* Comphy5 */ + }, + }, +}; + +static const struct sata_params + sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + /* AP0 */ + { + /* CP 0 */ + { + { 0 }, /* Comphy0 */ + { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e, + .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe, + .g1_emph_en = 0x1, .g2_emph_en = 0x1, + .g3_emph_en = 0x1, + .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, + .g3_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, + .g3_tx_emph_en = 0x0, + .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, + .g3_tx_emph = 0x1, + .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, + .g3_ffe_cap_sel = 0xf, + .align90 = 0x61, + .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, + .g3_rx_selmuff = 0x3, + .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, + .g3_rx_selmufi = 0x3, + .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, + .g3_rx_selmupf = 0x2, + .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, + .g3_rx_selmupi = 0x2, + .polarity_invert = COMPHY_POLARITY_NO_INVERT, + .valid = 0x1 + }, /* Comphy1 */ + { 0 }, /* Comphy2 */ + { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e, + .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe, + .g1_emph_en = 0x1, .g2_emph_en = 0x1, + .g3_emph_en = 0x1, + .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, + .g3_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, + .g3_tx_emph_en = 0x0, + .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, + .g3_tx_emph = 0x1, + .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, + .g3_ffe_cap_sel = 0xf, + .align90 = 0x61, + .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, + .g3_rx_selmuff = 0x3, + .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, + .g3_rx_selmufi = 0x3, + .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, + .g3_rx_selmupf = 0x2, + .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, + .g3_rx_selmupi = 0x2, + .polarity_invert = COMPHY_POLARITY_NO_INVERT, + .valid = 0x1 + }, /* Comphy3 */ + { 0 }, /* Comphy4 */ + { 0 }, /* Comphy5 */ + }, + + /* CP 1 */ + { + { 0 }, /* Comphy0 */ + { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e, + .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe, + .g1_emph_en = 0x1, .g2_emph_en = 0x1, + .g3_emph_en = 0x1, + .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, + .g3_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, + .g3_tx_emph_en = 0x0, + .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, + .g3_tx_emph = 0x1, + .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, + .g3_ffe_cap_sel = 0xf, + .align90 = 0x61, + .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, + .g3_rx_selmuff = 0x3, + .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, + .g3_rx_selmufi = 0x3, + .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, + .g3_rx_selmupf = 0x2, + .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, + .g3_rx_selmupi = 0x2, + .polarity_invert = COMPHY_POLARITY_NO_INVERT, + .valid = 0x1 + }, /* Comphy1 */ + { 0 }, /* Comphy2 */ + { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e, + .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe, + .g1_emph_en = 0x1, .g2_emph_en = 0x1, + .g3_emph_en = 0x1, + .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, + .g3_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, + .g3_tx_emph_en = 0x0, + .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, + .g3_tx_emph = 0x1, + .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, + .g3_ffe_cap_sel = 0xf, + .align90 = 0x61, + .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, + .g3_rx_selmuff = 0x3, + .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, + .g3_rx_selmufi = 0x3, + .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, + .g3_rx_selmupf = 0x2, + .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, + .g3_rx_selmupi = 0x2, + .polarity_invert = COMPHY_POLARITY_NO_INVERT, + .valid = 0x1 + }, /* Comphy3 */ + { 0 }, /* Comphy4 */ + { 0 }, /* Comphy5 */ + + }, + }, +}; + +static const struct usb_params + usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = { + .polarity_invert = COMPHY_POLARITY_NO_INVERT + }, +}; +#endif /* PHY_PORTING_LAYER_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h new file mode 100644 index 0000000..3fa119a --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_DEF_H +#define MVEBU_DEF_H + +#include + +#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */ +#define I2C_SPD_ADDR 0x53 /* Access SPD data */ +#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */ + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/platform.mk new file mode 100644 index 0000000..115dd4a --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/platform.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PCI_EP_SUPPORT := 0 + +CP_NUM := 2 +$(eval $(call add_define,CP_NUM)) + +DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg + +MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c + +BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST))) +include plat/marvell/armada/a8k/common/a8k_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c new file mode 100644 index 0000000..85c931c --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include + +#include +#include +#include + +#define MVEBU_CP_MPP_CTRL37_OFFS 20 +#define MVEBU_CP_MPP_CTRL38_OFFS 24 +#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2 +#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2 + +#define MVEBU_MPP_CTRL_MASK 0xf + +/* + * This struct provides the DRAM training code with + * the appropriate board DRAM configuration + */ +static struct mv_ddr_topology_map board_topology_map = { + /* Board with 1CS 8Gb x4 devices of Micron 2400T */ + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */ + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0} }, + /* TODO: double check if the speed bin is 2400T */ + SPEED_BIN_DDR_2400T, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_8GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ + MV_DDR_64BIT_BUS_MASK, /* subphys mask */ + MV_DDR_CFG_SPD, /* ddr configuration data source */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */ + }, + { + MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */ + MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */ + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */ + }, + } +}; + +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) +{ + /* Return the board topology as defined in the board code */ + return &board_topology_map; +} + +static void mpp_config(void) +{ + uint32_t val; + uintptr_t reg = MVEBU_CP_MPP_REGS(0, 4); + + /* configure CP0 MPP 37 and 38 to i2c */ + val = mmio_read_32(reg); + val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS)); + val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA << MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA << MVEBU_CP_MPP_CTRL38_OFFS); + mmio_write_32(reg, val); +} + +/* + * This function may modify the default DRAM parameters + * based on information received from SPD or bootloader + * configuration located on non volatile storage + */ +void plat_marvell_dram_update_topology(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + INFO("Gathering DRAM information\n"); + + if (tm->cfg_src == MV_DDR_CFG_SPD) { + /* configure MPPs to enable i2c */ + mpp_config(); + /* initialize the i2c */ + i2c_init((void *)MVEBU_CP0_I2C_BASE); + /* select SPD memory page 0 to access DRAM configuration */ + i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0); + /* read data from spd */ + i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes, + sizeof(tm->spd_data.all_bytes)); + } +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c new file mode 100644 index 0000000..75a1b0c --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#ifndef IMAGE_BLE + +/***************************************************************************** + * GPIO Configuration + ***************************************************************************** + */ +#define MPP_CONTROL_REGISTER 0xf2440018 +#define MPP_CONTROL_MPP_SEL_52_MASK 0xf0000 +#define GPIO_DATA_OUT1_REGISTER 0xf2440140 +#define GPIO_DATA_OUT_EN_CTRL1_REGISTER 0xf2440144 +#define GPIO52_MASK 0x100000 + +/* Reset PCIe via GPIO number 52 */ +int marvell_gpio_config(void) +{ + uint32_t reg; + + reg = mmio_read_32(MPP_CONTROL_REGISTER); + reg |= MPP_CONTROL_MPP_SEL_52_MASK; + mmio_write_32(MPP_CONTROL_REGISTER, reg); + + reg = mmio_read_32(GPIO_DATA_OUT1_REGISTER); + reg |= GPIO52_MASK; + mmio_write_32(GPIO_DATA_OUT1_REGISTER, reg); + + reg = mmio_read_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER); + reg &= ~GPIO52_MASK; + mmio_write_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER, reg); + udelay(100); + + return 0; +} + +/***************************************************************************** + * AMB Configuration + ***************************************************************************** + */ +struct addr_map_win amb_memory_map[] = { + /* CP1 SPI1 CS0 Direct Mode access */ + {0xf900, 0x1000000, AMB_SPI1_CS0_ID}, +}; + +int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + *win = amb_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(amb_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * IO WIN Configuration + ***************************************************************************** + */ +struct addr_map_win io_win_memory_map[] = { + /* CP1 (MCI0) internal regs */ + {0x00000000f4000000, 0x2000000, MCI_0_TID}, +#ifndef IMAGE_BLE + /* PCIe0-2 and SPI1_CS0 (RUNIT) on CP1*/ + {0x00000000f9000000, 0x4000000, MCI_0_TID}, + /* MCI 0 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID}, + /* MCI 1 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID}, +#endif +}; + +uint32_t marvell_get_io_win_gcr_target(int ap_index) +{ + return PIDI_TID; +} + +int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = io_win_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(io_win_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * IOB Configuration + ***************************************************************************** + */ +struct addr_map_win iob_memory_map_cp0[] = { + /* CP0 */ + /* PEX1_X1 window */ + {0x00000000f7000000, 0x1000000, PEX1_TID}, + /* PEX2_X1 window */ + {0x00000000f8000000, 0x1000000, PEX2_TID}, + /* PEX0_X4 window */ + {0x00000000f6000000, 0x1000000, PEX0_TID}, + {0x00000000c0000000, 0x30000000, PEX0_TID}, + {0x0000000800000000, 0x100000000, PEX0_TID}, +}; + +struct addr_map_win iob_memory_map_cp1[] = { + /* CP1 */ + /* SPI1_CS0 (RUNIT) window */ + {0x00000000f9000000, 0x1000000, RUNIT_TID}, + /* PEX1_X1 window */ + {0x00000000fb000000, 0x1000000, PEX1_TID}, + /* PEX2_X1 window */ + {0x00000000fc000000, 0x1000000, PEX2_TID}, + /* PEX0_X4 window */ + {0x00000000fa000000, 0x1000000, PEX0_TID} +}; + +int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + switch (base) { + case MVEBU_CP_REGS_BASE(0): + *win = iob_memory_map_cp0; + *size = ARRAY_SIZE(iob_memory_map_cp0); + return 0; + case MVEBU_CP_REGS_BASE(1): + *win = iob_memory_map_cp1; + *size = ARRAY_SIZE(iob_memory_map_cp1); + return 0; + default: + *size = 0; + *win = 0; + return 1; + } +} +#endif + +/***************************************************************************** + * CCU Configuration + ***************************************************************************** + */ +struct addr_map_win ccu_memory_map[] = { +#ifdef IMAGE_BLE + {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */ +#else +#if LLC_SRAM + /* This entry is prepared for OP-TEE OS that enables the LLC SRAM + * and changes the window target to SRAM_TID. + */ + {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID}, +#endif + {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */ + {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */ + {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */ +#endif +}; + +uint32_t marvell_get_ccu_gcr_target(int ap) +{ + return DRAM_0_TID; +} + +int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = ccu_memory_map; + *size = ARRAY_SIZE(ccu_memory_map); + + return 0; +} + +/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */ + +/***************************************************************************** + * SKIP IMAGE Configuration + ***************************************************************************** + */ +void *plat_marvell_get_skip_image_data(void) +{ + /* No recovery button on A8k-MCBIN board */ + return NULL; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h new file mode 100644 index 0000000..3fa119a --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_DEF_H +#define MVEBU_DEF_H + +#include + +#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */ +#define I2C_SPD_ADDR 0x53 /* Access SPD data */ +#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */ + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk new file mode 100644 index 0000000..115dd4a --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PCI_EP_SUPPORT := 0 + +CP_NUM := 2 +$(eval $(call add_define,CP_NUM)) + +DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg + +MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c + +BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST))) +include plat/marvell/armada/a8k/common/a8k_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c new file mode 100644 index 0000000..1d8e9d2 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include + +#include +#include +#include + +#define MVEBU_AP_MPP_CTRL0_7_REG MVEBU_AP_MPP_REGS(0) +#define MVEBU_AP_MPP_CTRL4_OFFS 16 +#define MVEBU_AP_MPP_CTRL5_OFFS 20 +#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA 0x3 +#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA 0x3 + +#define MVEBU_CP_MPP_CTRL37_OFFS 20 +#define MVEBU_CP_MPP_CTRL38_OFFS 24 +#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2 +#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2 + +#define MVEBU_MPP_CTRL_MASK 0xf + +/* + * This struct provides the DRAM training code with + * the appropriate board DRAM configuration + */ +static struct mv_ddr_topology_map board_topology_map = { + /* Board with 1CS 8Gb x4 devices of Micron 2400T */ + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */ + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0} }, + /* TODO: double check if the speed bin is 2400T */ + SPEED_BIN_DDR_2400T, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_8GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ + MV_DDR_64BIT_BUS_MASK, /* subphys mask */ + MV_DDR_CFG_SPD, /* ddr configuration data source */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */ + }, + { + MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */ + MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */ + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */ + }, + } +}; + +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) +{ + /* Return the board topology as defined in the board code */ + return &board_topology_map; +} + +static void mpp_config(void) +{ + uint32_t val; + uintptr_t reg; + + /* configure ap mmps 4, 5 to I2C */ + reg = MVEBU_AP_MPP_CTRL0_7_REG; + + val = mmio_read_32(reg); + val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL4_OFFS) | + (MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL5_OFFS)); + val |= ((MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA << MVEBU_AP_MPP_CTRL4_OFFS) | + (MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA << MVEBU_AP_MPP_CTRL5_OFFS)); + + mmio_write_32(reg, val); +} + +/* + * This function may modify the default DRAM parameters + * based on information received from SPD or bootloader + * configuration located on non volatile storage + */ +void plat_marvell_dram_update_topology(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + INFO("Gathering DRAM information\n"); + + if (tm->cfg_src == MV_DDR_CFG_SPD) { + /* configure MPPs to enable i2c */ + mpp_config(); + /* initialize the MVEBU_AP_I2C_BASE I2C bus */ + i2c_init((void *)MVEBU_AP_I2C_BASE); + /* select SPD memory page 0 to access DRAM configuration */ + i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0); + /* read data from spd */ + i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes, + sizeof(tm->spd_data.all_bytes)); + } +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c new file mode 100644 index 0000000..0edc977 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#ifndef IMAGE_BLE + +/***************************************************************************** + * GPIO Configuration + ***************************************************************************** + */ +#define MPP_CONTROL_REGISTER 0xf2440018 +#define MPP_CONTROL_MPP_SEL_52_MASK 0xf0000 +#define GPIO_DATA_OUT1_REGISTER 0xf2440140 +#define GPIO_DATA_OUT_EN_CTRL1_REGISTER 0xf2440144 +#define GPIO52_MASK 0x100000 + +/* Reset PCIe via GPIO number 52 */ +int marvell_gpio_config(void) +{ + uint32_t reg; + + reg = mmio_read_32(MPP_CONTROL_REGISTER); + reg |= MPP_CONTROL_MPP_SEL_52_MASK; + mmio_write_32(MPP_CONTROL_REGISTER, reg); + + reg = mmio_read_32(GPIO_DATA_OUT1_REGISTER); + reg |= GPIO52_MASK; + mmio_write_32(GPIO_DATA_OUT1_REGISTER, reg); + + reg = mmio_read_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER); + reg &= ~GPIO52_MASK; + mmio_write_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER, reg); + udelay(100); + + return 0; +} + +/***************************************************************************** + * AMB Configuration + ***************************************************************************** + */ +struct addr_map_win amb_memory_map[] = { + /* CP1 SPI1 CS0 Direct Mode access */ + {0xf900, 0x1000000, AMB_SPI1_CS0_ID}, +}; + +int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + *win = amb_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(amb_memory_map); + + return 0; +} +#endif + +/***************************************************************************** + * IO WIN Configuration + ***************************************************************************** + */ +struct addr_map_win io_win_memory_map[] = { + /* CP1 (MCI0) internal regs */ + {0x00000000f4000000, 0x2000000, MCI_0_TID}, +#ifndef IMAGE_BLE + /* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/ + {0x00000000f9000000, 0x2000000, MCI_0_TID}, + /* PCIe1 on CP1*/ + {0x00000000fb000000, 0x1000000, MCI_0_TID}, + /* PCIe2 on CP1*/ + {0x00000000fc000000, 0x1000000, MCI_0_TID}, + /* MCI 0 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID}, + /* MCI 1 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID}, +#endif +}; + +uint32_t marvell_get_io_win_gcr_target(int ap_index) +{ + return PIDI_TID; +} + +int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = io_win_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(io_win_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * IOB Configuration + ***************************************************************************** + */ +struct addr_map_win iob_memory_map_cp0[] = { + /* CP0 */ + /* PEX1_X1 window */ + {0x00000000f7000000, 0x1000000, PEX1_TID}, + /* PEX2_X1 window */ + {0x00000000f8000000, 0x1000000, PEX2_TID}, + /* PEX0_X4 window */ + {0x00000000f6000000, 0x1000000, PEX0_TID}, + {0x00000000c0000000, 0x30000000, PEX0_TID}, + {0x0000000800000000, 0x100000000, PEX0_TID}, +}; + +struct addr_map_win iob_memory_map_cp1[] = { + /* CP1 */ + /* SPI1_CS0 (RUNIT) window */ + {0x00000000f9000000, 0x1000000, RUNIT_TID}, + /* PEX1_X1 window */ + {0x00000000fb000000, 0x1000000, PEX1_TID}, + /* PEX2_X1 window */ + {0x00000000fc000000, 0x1000000, PEX2_TID}, + /* PEX0_X4 window */ + {0x00000000fa000000, 0x1000000, PEX0_TID} +}; + +int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + switch (base) { + case MVEBU_CP_REGS_BASE(0): + *win = iob_memory_map_cp0; + *size = ARRAY_SIZE(iob_memory_map_cp0); + return 0; + case MVEBU_CP_REGS_BASE(1): + *win = iob_memory_map_cp1; + *size = ARRAY_SIZE(iob_memory_map_cp1); + return 0; + default: + *size = 0; + *win = 0; + return 1; + } +} +#endif + +/***************************************************************************** + * CCU Configuration + ***************************************************************************** + */ +struct addr_map_win ccu_memory_map[] = { +#ifdef IMAGE_BLE + {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */ +#else +#if LLC_SRAM + {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID}, +#endif + {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */ + {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */ + {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */ +#endif +}; + +uint32_t marvell_get_ccu_gcr_target(int ap) +{ + return DRAM_0_TID; +} + +int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = ccu_memory_map; + *size = ARRAY_SIZE(ccu_memory_map); + + return 0; +} + +/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */ + +/***************************************************************************** + * SKIP IMAGE Configuration + ***************************************************************************** + */ +void *plat_marvell_get_skip_image_data(void) +{ + /* No recovery button on A8k-MCBIN board */ + return NULL; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c new file mode 100644 index 0000000..eb00874 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 Sartura Ltd. + * Author: Luka Kovacic + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include + +/***************************************************************************** + * Platform specific power off functions + * Power off PSU / Send command to power management MCU / ... + ***************************************************************************** + */ + +unsigned char add_xor_checksum(unsigned char *buf, unsigned char xor_len) +{ + unsigned char xor_sum = 0; + unsigned int i; + + for (i = 0; i < xor_len; i++) + xor_sum ^= buf[i]; + + return xor_sum; +} + +int system_power_off(void) +{ + static console_t console; + + /* WT61P803 MCU system_off_now command */ + unsigned char system_off_now[4] = { '@', 'C', '0' }; + int i, len; + + len = sizeof(system_off_now); + system_off_now[len - 1] = add_xor_checksum(system_off_now, len); + + console_16550_register(PLAT_MARVELL_UART_BASE + 0x100, + PLAT_MARVELL_UART_CLK_IN_HZ, 115200, &console); + + /* Send system_off_now to console */ + for (i = 0; i < len; i++) { + console.putc(system_off_now[i], &console); + udelay(1000); + } + + console.flush(&console); + (void)console_unregister(&console); + + mdelay(100); + + return 0; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h new file mode 100644 index 0000000..3fa119a --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_DEF_H +#define MVEBU_DEF_H + +#include + +#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */ +#define I2C_SPD_ADDR 0x53 /* Access SPD data */ +#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */ + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk new file mode 100644 index 0000000..3378d53 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PCI_EP_SUPPORT := 0 + +CP_NUM := 2 +$(eval $(call add_define,CP_NUM)) + +DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg + +MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c + +BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST))) +include plat/marvell/armada/a8k/common/a8k_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/a8k_common.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/common/a8k_common.mk new file mode 100644 index 0000000..4d8a87f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/a8k_common.mk @@ -0,0 +1,192 @@ +# +# Copyright (C) 2016 - 2020 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +PLAT_FAMILY := a8k +PLAT_INCLUDE_BASE := include/plat/marvell/armada/$(PLAT_FAMILY) +PLAT_COMMON_BASE := plat/marvell/armada/a8k/common +MARVELL_DRV_BASE := drivers/marvell +MARVELL_COMMON_BASE := plat/marvell/armada/common + +MARVELL_SVC_TEST := 0 +$(eval $(call add_define,MARVELL_SVC_TEST)) + +ERRATA_A72_859971 := 1 + +# Enable MSS support for a8k family +MSS_SUPPORT := 1 +$(eval $(call add_define,MSS_SUPPORT)) + +# Disable EL3 cache for power management +BL31_CACHE_DISABLE := 0 +$(eval $(call add_define,BL31_CACHE_DISABLE)) + +$(eval $(call add_define,PCI_EP_SUPPORT)) +$(eval $(call assert_boolean,PCI_EP_SUPPORT)) + +AP_NUM := 1 +$(eval $(call add_define,AP_NUM)) + +DOIMAGEPATH ?= tools/marvell/doimage +DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage + +include plat/marvell/marvell.mk +include tools/marvell/doimage/doimage.mk + +ifeq (${MARVELL_SECURE_BOOT},1) +DOIMAGE_SEC_FLAGS := -c $(DOIMAGE_SEC) +DOIMAGE_LIBS_CHECK = \ + if ! [ -d "/usr/include/mbedtls" ]; then \ + echo "****************************************" >&2; \ + echo "Missing mbedTLS installation! " >&2; \ + echo "Please download it from \"tls.mbed.org\"" >&2; \ + echo "Alternatively on Debian/Ubuntu system install" >&2; \ + echo "\"libmbedtls-dev\" package" >&2; \ + echo "Make sure to use version 2.1.0 or later" >&2; \ + echo "****************************************" >&2; \ + exit 1; \ + else if ! [ -f "/usr/include/libconfig.h" ]; then \ + echo "********************************************************" >&2; \ + echo "Missing Libconfig installation!" >&2; \ + echo "Please download it from \"www.hyperrealm.com/libconfig/\"" >&2; \ + echo "Alternatively on Debian/Ubuntu system install packages" >&2; \ + echo "\"libconfig8\" and \"libconfig8-dev\"" >&2; \ + echo "********************************************************" >&2; \ + exit 1; \ + fi \ + fi +else #MARVELL_SECURE_BOOT +DOIMAGE_LIBS_CHECK = +DOIMAGE_SEC_FLAGS = +endif #MARVELL_SECURE_BOOT + +ROM_BIN_EXT ?= $(BUILD_PLAT)/ble.bin +DOIMAGE_FLAGS += -b $(ROM_BIN_EXT) $(NAND_DOIMAGE_FLAGS) $(DOIMAGE_SEC_FLAGS) + +# Check whether to build system_power.c for the platform +ifneq ("$(wildcard $(BOARD_DIR)/board/system_power.c)","") +SYSTEM_POWER_SUPPORT = 1 +else +SYSTEM_POWER_SUPPORT = 0 +endif + +# This define specifies DDR type for BLE +$(eval $(call add_define,CONFIG_DDR4)) + +# This define specifies DDR topology for BLE +DDR_TOPOLOGY ?= 0 +$(eval $(call add_define,DDR_TOPOLOGY)) + +MARVELL_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +PLAT_INCLUDES += -I$(BOARD_DIR) \ + -I$(BOARD_DIR)/board \ + -I$(CURDIR)/drivers/marvell \ + -I$(PLAT_COMMON_BASE)/include \ + -I$(PLAT_INCLUDE_BASE)/common + +PLAT_BL_COMMON_SOURCES := $(PLAT_COMMON_BASE)/aarch64/a8k_common.c \ + drivers/ti/uart/aarch64/16550_console.S + +ifndef BLE_PORTING_SOURCES +BLE_PORTING_SOURCES := $(BOARD_DIR)/board/dram_port.c \ + $(BOARD_DIR)/board/marvell_plat_config.c +endif + +MARVELL_MOCHI_DRV += $(MARVELL_DRV_BASE)/mochi/cp110_setup.c + +BLE_SOURCES := drivers/mentor/i2c/mi2cv.c \ + $(PLAT_COMMON_BASE)/plat_ble_setup.c \ + $(MARVELL_MOCHI_DRV) \ + $(PLAT_COMMON_BASE)/plat_pm.c \ + $(MARVELL_DRV_BASE)/ap807_clocks_init.c \ + $(MARVELL_DRV_BASE)/thermal.c \ + $(PLAT_COMMON_BASE)/plat_thermal.c \ + $(BLE_PORTING_SOURCES) \ + $(MARVELL_DRV_BASE)/ccu.c \ + $(MARVELL_DRV_BASE)/io_win.c + +BL1_SOURCES += $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \ + lib/cpus/aarch64/cortex_a72.S + +MARVELL_DRV := $(MARVELL_DRV_BASE)/io_win.c \ + $(MARVELL_DRV_BASE)/iob.c \ + $(MARVELL_DRV_BASE)/mci.c \ + $(MARVELL_DRV_BASE)/amb_adec.c \ + $(MARVELL_DRV_BASE)/ccu.c \ + $(MARVELL_DRV_BASE)/cache_llc.c \ + $(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \ + $(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \ + $(MARVELL_DRV_BASE)/secure_dfx_access/armada_thermal.c \ + $(MARVELL_DRV_BASE)/secure_dfx_access/misc_dfx.c \ + $(MARVELL_DRV_BASE)/ddr_phy_access.c \ + drivers/rambus/trng_ip_76.c + +ifeq (${MSS_SUPPORT}, 1) +MARVELL_DRV += $(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c +endif + +ifndef BL31_PORTING_SOURCES +BL31_PORTING_SOURCES := $(BOARD_DIR)/board/marvell_plat_config.c +endif + +ifeq ($(SYSTEM_POWER_SUPPORT),1) +BL31_PORTING_SOURCES += $(BOARD_DIR)/board/system_power.c +endif + +BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \ + $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \ + $(PLAT_COMMON_BASE)/aarch64/plat_arch_config.c \ + $(PLAT_COMMON_BASE)/plat_pm.c \ + $(PLAT_COMMON_BASE)/plat_bl31_setup.c \ + $(MARVELL_COMMON_BASE)/marvell_gicv2.c \ + $(MARVELL_COMMON_BASE)/mrvl_sip_svc.c \ + $(MARVELL_COMMON_BASE)/marvell_ddr_info.c \ + $(BL31_PORTING_SOURCES) \ + $(MARVELL_DRV) \ + $(MARVELL_MOCHI_DRV) \ + $(MARVELL_GIC_SOURCES) + +# Add trace functionality for PM +BL31_SOURCES += $(PLAT_COMMON_BASE)/plat_pm_trace.c + + +ifeq (${MSS_SUPPORT}, 1) +# Force builds with BL2 image on a80x0 platforms +ifndef SCP_BL2 + $(error "Error: SCP_BL2 image is mandatory for a8k family") +endif + +# MSS (SCP) build +include $(PLAT_COMMON_BASE)/mss/mss_a8k.mk +endif + +# BLE (ROM context execution code, AKA binary extension) +BLE_PATH ?= $(PLAT_COMMON_BASE)/ble + +include ${BLE_PATH}/ble.mk +$(eval $(call MAKE_BL,ble)) + +clean realclean distclean: mrvl_clean + +.PHONY: mrvl_clean +mrvl_clean: + @echo " Doimage CLEAN" + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${DOIMAGEPATH} clean + +${DOIMAGETOOL}: FORCE + @$(DOIMAGE_LIBS_CHECK) + ${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH} + +${BUILD_PLAT}/${FLASH_IMAGE}: ${ROM_BIN_EXT} ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL} + @${ECHO_BLANK_LINE} + @echo "Building flash image" + ${Q}${DOIMAGETOOL} ${DOIMAGE_FLAGS} ${BUILD_PLAT}/${BOOT_IMAGE} ${BUILD_PLAT}/${FLASH_IMAGE} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c new file mode 100644 index 0000000..4332a76 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + + +/* MMU entry for internal (register) space access */ +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Table of regions for various BL stages to map using the MMU. + */ +#if IMAGE_BL1 +const mmap_region_t plat_marvell_mmap[] = { + MARVELL_MAP_SECURE_RAM, + MAP_DEVICE0, + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t plat_marvell_mmap[] = { + MARVELL_MAP_SECURE_RAM, + MAP_DEVICE0, + MARVELL_MAP_DRAM, +#ifdef SPD_opteed + MARVELL_MAP_OPTEE_CORE_MEM, + MARVELL_OPTEE_PAGEABLE_LOAD_MEM, +#endif + {0} +}; +#endif + +#if IMAGE_BL2U +const mmap_region_t plat_marvell_mmap[] = { + MARVELL_MAP_SECURE_RAM, + MAP_DEVICE0, + {0} +}; +#endif + +#if IMAGE_BLE +const mmap_region_t plat_marvell_mmap[] = { + MAP_DEVICE0, + {0} +}; +#endif + +#if IMAGE_BL31 +const mmap_region_t plat_marvell_mmap[] = { + MARVELL_MAP_SECURE_RAM, + MAP_DEVICE0, + MARVELL_MAP_DRAM, + {0} +}; +#endif +#if IMAGE_BL32 +const mmap_region_t plat_marvell_mmap[] = { + MARVELL_MAP_SECURE_RAM, + MAP_DEVICE0, + {0} +}; +#endif + +MARVELL_CASSERT_MMAP; diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c new file mode 100644 index 0000000..d576514 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include + +#define CCU_HTC_ASET (MVEBU_CCU_BASE(MVEBU_AP0) + 0x264) +#define MVEBU_IO_AFFINITY (0xF00) +#define MVEBU_SF_REG (MVEBU_REGS_BASE + 0x40) +#define MVEBU_SF_EN BIT(8) +#define MVEBU_DFX_REG(cluster_id) (MVEBU_REGS_BASE + 0x6F82A0 + \ + (cluster_id) * 0x4) +#define MVEBU_DFX_CLK_EN_POS 0x3 +#define MVEBU_DFX_CL0_CLK_OFFS 16 +#define MVEBU_DFX_CL0_CLK_MASK (0xF << MVEBU_DFX_CL0_CLK_OFFS) +#define MVEBU_DFX_CL1_CLK_OFFS 8 +#define MVEBU_DFX_CL1_CLK_MASK (0xF << MVEBU_DFX_CL1_CLK_OFFS) + +#ifdef MVEBU_SOC_AP807 +static void plat_enable_snoop_filter(void) +{ + int cpu_id = plat_my_core_pos(); + + /* Snoop filter needs to be enabled once per cluster */ + if (cpu_id % 2) + return; + + mmio_setbits_32(MVEBU_SF_REG, MVEBU_SF_EN); +} +#endif + +#ifndef MVEBU_SOC_AP807 +static void plat_config_dfx_clock(void) +{ + int cluster_id = plat_my_core_pos(); + uint32_t val; + + /* DFX clock needs to be configured once per cluster */ + if ((cluster_id % PLAT_MAX_CPUS_PER_CLUSTER) != 0) { + return; + } + + val = mmio_read_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER)); + if (cluster_id == 0) { + val &= ~MVEBU_DFX_CL0_CLK_MASK; + val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL0_CLK_OFFS); + } else { + val &= ~MVEBU_DFX_CL1_CLK_MASK; + val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL1_CLK_OFFS); + } + mmio_write_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER), val); +} +#endif + +static void plat_enable_affinity(void) +{ + int cluster_id; + int affinity; + + /* set CPU Affinity */ + cluster_id = plat_my_core_pos() / PLAT_MARVELL_CLUSTER_CORE_COUNT; + affinity = (MVEBU_IO_AFFINITY | (1 << cluster_id)); + mmio_write_32(CCU_HTC_ASET, affinity); + + /* set barier */ + isb(); +} + +void marvell_psci_arch_init(int die_index) +{ +#if LLC_ENABLE + /* check if LLC is in exclusive mode + * as L2 is configured to UniqueClean eviction + * (in a8k reset handler) + */ + if (llc_is_exclusive(0) == 0) + ERROR("LLC should be configured to exclusice mode\n"); +#endif + + /* Enable Affinity */ + plat_enable_affinity(); + +#ifdef MVEBU_SOC_AP807 + plat_enable_snoop_filter(); +#else + plat_config_dfx_clock(); +#endif +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..fadc4c2 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_reset_handler + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset. Right + * now this is a stub function. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + mov x0, #0 + ret +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish + * between a cold and warm boot + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* Read first word and compare it with magic num */ + mov_imm x0, PLAT_MARVELL_MAILBOX_BASE + ldr x1, [x0] + mov_imm x2, MVEBU_MAILBOX_MAGIC_NUM + cmp x1, x2 + beq warm_boot /* If compare failed, return 0, i.e. cold boot */ + mov x0, #0 + ret +warm_boot: + mov_imm x1, MBOX_IDX_SEC_ADDR /* Get the jump address */ + subs x1, x1, #1 + mov x2, #(MBOX_IDX_SEC_ADDR * 8) + lsl x3, x2, x1 + add x0, x0, x3 + ldr x0, [x0] + ret +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #MVEBU_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_reset_handler (void); + * + * Platform specific configuration right after cpu is + * is our of reset. + * + * The plat_reset_handler can clobber x0 - x18, x30. + * ----------------------------------------------------- + */ +func plat_reset_handler + /* + * Note: the configurations below should be done before MMU, + * I Cache and L2are enabled. + * The reset handler is executed right after reset + * and before Caches are enabled. + */ + + /* Enable L1/L2 ECC and Parity */ + mrs x5, s3_1_c11_c0_2 /* L2 Ctrl */ + orr x5, x5, #(1 << 21) /* Enable L1/L2 cache ECC & Parity */ + msr s3_1_c11_c0_2, x5 /* L2 Ctrl */ + +#if LLC_ENABLE + /* + * Enable L2 UniqueClean evictions + * Note: this configuration assumes that LLC is configured + * in exclusive mode. + * Later on in the code this assumption will be validated + */ + mrs x5, s3_1_c15_c0_0 /* L2 Ctrl */ + orr x5, x5, #(1 << 14) /* Enable UniqueClean evictions with data */ + msr s3_1_c15_c0_0, x5 /* L2 Ctrl */ +#endif + + /* Instruction Barrier to allow msr command completion */ + isb + + ret +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S new file mode 100644 index 0000000..d7a0592 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(ble_main) + +MEMORY { + RAM (rwx): ORIGIN = BLE_BASE, LENGTH = BLE_LIMIT - BLE_BASE +} + +SECTIONS +{ + . = BLE_BASE; + + ro . : { + __RO_START__ = .; + *ble_main.o(.entry*) + *(.text*) + *(.rodata*) + __RO_END_UNALIGNED__ = .; + __RO_END__ = .; + } >RAM + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + .data . : { + __DATA_START__ = .; + *(.data*) + __DATA_END__ = .; + } >RAM + + stacks . (NOLOAD) : { + __STACKS_START__ = .; + *(tzfw_normal_stacks) + __STACKS_END__ = .; + } >RAM + + .bss : { + __BSS_START__ = .; + *(.bss*) + __BSS_END__ = .; + } >RAM + + /* + * Extend the BLE binary to the maximum size allocated for it in platform + * definition files and prevent overlapping between BLE BSS section and + * additional extensions that can follow the BLE in flash image preamble. + * This situation happens for instance when secure extension is added to + * the image preamble. + */ + .fill LOADADDR(.bss) + SIZEOF(.bss) : { + FILL(0xDEADC0DE); + . = ORIGIN(RAM) + LENGTH(RAM) - 1; + BYTE(0x00) + } >RAM + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BLE_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.mk new file mode 100644 index 0000000..160e98f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.mk @@ -0,0 +1,35 @@ +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +MV_DDR_LIB = $(BUILD_PLAT)/ble/mv_ddr_lib.a +LIBC_LIB = $(BUILD_PLAT)/lib/libc.a +BLE_LIBS = $(MV_DDR_LIB) $(LIBC_LIB) +PLAT_MARVELL = plat/marvell/armada + +BLE_SOURCES += $(BLE_PATH)/ble_main.c \ + $(BLE_PATH)/ble_mem.S \ + drivers/delay_timer/delay_timer.c \ + drivers/marvell/iob.c \ + $(PLAT_MARVELL)/common/aarch64/marvell_helpers.S \ + $(PLAT_MARVELL)/common/plat_delay_timer.c \ + $(PLAT_MARVELL)/common/marvell_console.c + +MV_DDR_INCLUDES := -I$(CURDIR)/include \ + -I$(CURDIR)/include/arch/aarch64 \ + -I$(CURDIR)/include/lib/libc \ + -I$(CURDIR)/include/lib/libc/aarch64 + +BLE_LINKERFILE := $(BLE_PATH)/ble.ld.S + +BLE_OBJS := $(addprefix $(BUILD_PLAT)/ble/,$(call SOURCES_TO_OBJS,$(BLE_SOURCES))) +$(BLE_OBJS): PLAT_INCLUDES += -I$(MV_DDR_PATH) +$(BLE_OBJS): $(MV_DDR_LIB) + +$(MV_DDR_LIB): FORCE +# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds + $(if $(value MV_DDR_PATH),,$(error "Platform '$(PLAT)' for BLE requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory")) + $(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist")) + $(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository")) + @+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(MV_DDR_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c new file mode 100644 index 0000000..5b3acec --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#define BR_FLAG_SILENT 0x1 +#define SKIP_IMAGE_CODE 0xDEADB002 + +void mailbox_clean(void) +{ + uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE; + + memset(mailbox, 0, PLAT_MARVELL_MAILBOX_SIZE); +} + +int exec_ble_main(int bootrom_flags) +{ + int skip = 0; + uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE; + + /* + * In some situations, like boot from UART, bootrom will + * request to avoid printing to console. in that case don't + * initialize the console and prints will be ignored + */ + if ((bootrom_flags & BR_FLAG_SILENT) == 0) + marvell_console_boot_init(); + + NOTICE("Starting binary extension\n"); + + /* initialize time (for delay functionality) */ + plat_delay_timer_init(); + + ble_plat_setup(&skip); + + /* if there's skip image request, bootrom will load from the image + * saved on the next address of the flash + */ + if (skip) + return SKIP_IMAGE_CODE; + + /* + * Check if the mailbox magic number is stored at index MBOX_IDX_MAGIC + * and the suspend to RAM magic number at index MBOX_IDX_SUSPEND_MAGIC. + * If the above is true, this is the recovery from suspend to RAM state. + * In such case the mailbox should remain intact, since it stores the + * warm boot jump address to be used by the TF-A in BL31. + * Othervise the mailbox should be cleaned from a garbage data. + */ + if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM || + mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE) { + NOTICE("Cold boot\n"); + mailbox_clean(); + } else { + void (*bootrom_exit)(void) = + (void (*)(void))mailbox[MBOX_IDX_ROM_EXIT_ADDR]; + + INFO("Recovery...\n"); + /* + * If this is recovery from suspend, two things has to be done: + * 1. Define the DRAM region as executable memory for preparing + * jump to TF-A + * 2. Instead of returning control to the BootROM, invalidate + * and flush caches, and continue execution at address stored + * in the mailbox. + * This should be done until the BootROM have a native support + * for the system restore flow. + */ + marvell_ble_prepare_exit(); + bootrom_exit(); + } + + return 0; +} + +/* NOTE: don't notify this function, all code must be added to exec_ble_main + * in order to keep the end of ble_main as a fixed address. + */ +int __attribute__ ((section(".entry"))) ble_main(int bootrom_flags) +{ + volatile int ret; + + ret = exec_ble_main(bootrom_flags); + return ret; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S new file mode 100644 index 0000000..a48d546 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include + +#define PTE_NON_EXEC_OFF 54 /* XN - eXecute Never bit offset - see VMSAv8-64 */ + + .globl marvell_ble_prepare_exit + +func marvell_ble_prepare_exit + /* + * Read the page table base and set the first page to be executable. + * This is required for jumping to DRAM for further execution. + */ + mrs x0, ttbr0_el3 + ldr x1, [x0] + mov x2, #1 + bic x1, x1, x2, lsl #PTE_NON_EXEC_OFF + str x1, [x0] + tlbi alle3 + dsb sy + isb + ret +endfunc marvell_ble_prepare_exit diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h new file mode 100644 index 0000000..3a0fd4b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef A8K_PLAT_DEF_H +#define A8K_PLAT_DEF_H + +#include + +#define MVEBU_PRIMARY_CPU 0x0 +#define MVEBU_AP0 0x0 + +/* APN806 revision ID */ +#define MVEBU_CSS_GWD_CTRL_IIDR2_REG (MVEBU_REGS_BASE + 0x610FCC) +#define GWD_IIDR2_REV_ID_OFFSET 12 +#define GWD_IIDR2_REV_ID_MASK 0xF +#define GWD_IIDR2_CHIP_ID_OFFSET 20 +#define GWD_IIDR2_CHIP_ID_MASK (0xFFFu << GWD_IIDR2_CHIP_ID_OFFSET) + +#define CHIP_ID_AP806 0x806 +#define CHIP_ID_AP807 0x807 + +#define COUNTER_FREQUENCY 25000000 + +#define MVEBU_REGS_BASE 0xF0000000 +#define MVEBU_REGS_BASE_MASK 0xF0000000 +#define MVEBU_REGS_BASE_AP(ap) MVEBU_REGS_BASE +#define MVEBU_AP_IO_BASE(ap) 0xF2000000 +#define MVEBU_CP_OFFSET 0x2000000 +#define MVEBU_CP_REGS_BASE(cp_index) (MVEBU_AP_IO_BASE(0) + \ + (cp_index) * MVEBU_CP_OFFSET) +#define MVEBU_RFU_BASE (MVEBU_REGS_BASE + 0x6F0000) +#define MVEBU_IO_WIN_BASE(ap_index) (MVEBU_RFU_BASE) +#define MVEBU_IO_WIN_GCR_OFFSET (0x70) +#define MVEBU_IO_WIN_MAX_WINS (7) + +/* Misc SoC configurations Base */ +#define MVEBU_MISC_SOC_BASE (MVEBU_REGS_BASE + 0x6F4300) + +#define MVEBU_CCU_BASE(ap_index) (MVEBU_REGS_BASE + 0x4000) +#define MVEBU_CCU_MAX_WINS (8) + +#define MVEBU_LLC_BASE(ap_index) (MVEBU_REGS_BASE + 0x8000) +#define MVEBU_DRAM_MAC_BASE (MVEBU_REGS_BASE + 0x20000) +#define MVEBU_DRAM_PHY_BASE (MVEBU_REGS_BASE + 0x20000) +#define MVEBU_SMMU_BASE (MVEBU_REGS_BASE + 0x100000) +#define MVEBU_CP_MPP_REGS(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \ + 0x440000 + ((n) << 2)) +#define MVEBU_PM_MPP_REGS(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \ + 0x440000 + ((n / 8) << 2)) +#define MVEBU_CP_GPIO_DATA_OUT(cp_index, n) \ + (MVEBU_CP_REGS_BASE(cp_index) + \ + 0x440100 + ((n > 31) ? 0x40 : 0x00)) +#define MVEBU_CP_GPIO_DATA_OUT_EN(cp_index, n) \ + (MVEBU_CP_REGS_BASE(cp_index) + \ + 0x440104 + ((n > 31) ? 0x40 : 0x00)) +#define MVEBU_CP_GPIO_DATA_IN(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \ + 0x440110 + ((n > 31) ? 0x40 : 0x00)) +#define MVEBU_AP_MPP_REGS(n) (MVEBU_RFU_BASE + 0x4000 + ((n) << 2)) +#define MVEBU_AP_GPIO_REGS (MVEBU_RFU_BASE + 0x5040) +#define MVEBU_AP_GPIO_DATA_IN (MVEBU_AP_GPIO_REGS + 0x10) +#define MVEBU_AP_I2C_BASE (MVEBU_REGS_BASE + 0x511000) +#define MVEBU_CP0_I2C_BASE (MVEBU_CP_REGS_BASE(0) + 0x701000) +#define MVEBU_AP_GEN_MGMT_BASE (MVEBU_RFU_BASE + 0x8000) +#define MVEBU_AP_EXT_TSEN_BASE (MVEBU_AP_GEN_MGMT_BASE + 0x84) + +#define MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap, win) (MVEBU_REGS_BASE_AP(ap) + \ + 0x20080 + ((win) * 0x8)) +#define MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap, win) (MVEBU_REGS_BASE_AP(ap) + \ + 0x20084 + ((win) * 0x8)) + +/* MCI indirect access definitions */ +#define MCI_MAX_UNIT_ID 2 +/* SoC RFU / IHBx4 Control */ +#define MCIX4_REG_START_ADDRESS_REG(unit_id) (MVEBU_RFU_BASE + \ + 0x4218 + (unit_id * 0x20)) +#define MCI_REMAP_OFF_SHIFT 8 + +#define MVEBU_MCI_REG_BASE_REMAP(index) (0xFD000000 + \ + ((index) * 0x1000000)) + +#define MVEBU_PCIE_X4_MAC_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x600000) +#define MVEBU_COMPHY_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x441000) +#define MVEBU_HPIPE_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x120000) +#define MVEBU_CP_DFX_OFFSET (0x400200) + +/***************************************************************************** + * MVEBU memory map related constants + ***************************************************************************** + */ +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE MVEBU_REGS_BASE +#define DEVICE0_SIZE 0x10000000 + +/***************************************************************************** + * GIC-400 & interrupt handling related constants + ***************************************************************************** + */ +/* Base MVEBU compatible GIC memory map */ +#define MVEBU_GICD_BASE 0x210000 +#define MVEBU_GICC_BASE 0x220000 + + +/***************************************************************************** + * AXI Configuration + ***************************************************************************** + */ +#define MVEBU_AXI_ATTR_ARCACHE_OFFSET 4 +#define MVEBU_AXI_ATTR_ARCACHE_MASK (0xF << \ + MVEBU_AXI_ATTR_ARCACHE_OFFSET) +#define MVEBU_AXI_ATTR_ARDOMAIN_OFFSET 12 +#define MVEBU_AXI_ATTR_ARDOMAIN_MASK (0x3 << \ + MVEBU_AXI_ATTR_ARDOMAIN_OFFSET) +#define MVEBU_AXI_ATTR_AWCACHE_OFFSET 20 +#define MVEBU_AXI_ATTR_AWCACHE_MASK (0xF << \ + MVEBU_AXI_ATTR_AWCACHE_OFFSET) +#define MVEBU_AXI_ATTR_AWDOMAIN_OFFSET 28 +#define MVEBU_AXI_ATTR_AWDOMAIN_MASK (0x3 << \ + MVEBU_AXI_ATTR_AWDOMAIN_OFFSET) + +/* SATA MBUS to AXI configuration */ +#define MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET 1 +#define MVEBU_SATA_M2A_AXI_ARCACHE_MASK (0xF << \ + MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET) +#define MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET 5 +#define MVEBU_SATA_M2A_AXI_AWCACHE_MASK (0xF << \ + MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET) + +/* ARM cache attributes */ +#define CACHE_ATTR_BUFFERABLE 0x1 +#define CACHE_ATTR_CACHEABLE 0x2 +#define CACHE_ATTR_READ_ALLOC 0x4 +#define CACHE_ATTR_WRITE_ALLOC 0x8 +/* Domain */ +#define DOMAIN_NON_SHAREABLE 0x0 +#define DOMAIN_INNER_SHAREABLE 0x1 +#define DOMAIN_OUTER_SHAREABLE 0x2 +#define DOMAIN_SYSTEM_SHAREABLE 0x3 + +/************************************************************************ + * Required platform porting definitions common to all + * Management Compute SubSystems (MSS) + ************************************************************************ + */ +/* + * Load address of SCP_BL2 + * SCP_BL2 is loaded to the same place as BL31. + * Once SCP_BL2 is transferred to the SCP, + * it is discarded and BL31 is loaded over the top. + */ +#ifdef SCP_IMAGE +#define SCP_BL2_BASE BL31_BASE +#define SCP_BL2_SIZE BL31_LIMIT +#endif + +#ifndef __ASSEMBLER__ +enum ap806_sar_target_dev { + SAR_PIDI_MCIX2 = 0x0, + SAR_MCIX4 = 0x1, + SAR_SPI = 0x2, + SAR_SD = 0x3, + SAR_PIDI_MCIX2_BD = 0x4, /* BootRom disabled */ + SAR_MCIX4_DB = 0x5, /* BootRom disabled */ + SAR_SPI_DB = 0x6, /* BootRom disabled */ + SAR_EMMC = 0x7 +}; + +enum io_win_target_ids { + MCI_0_TID = 0x0, + MCI_1_TID = 0x1, + MCI_2_TID = 0x2, + PIDI_TID = 0x3, + SPI_TID = 0x4, + STM_TID = 0x5, + BOOTROM_TID = 0x6, + IO_WIN_MAX_TID +}; + +enum ccu_target_ids { + IO_0_TID = 0x00, + DRAM_0_TID = 0x03, + IO_1_TID = 0x0F, + CFG_REG_TID = 0x10, + RAR_TID = 0x20, + SRAM_TID = 0x40, + DRAM_1_TID = 0xC0, + CCU_MAX_TID, + INVALID_TID = 0xFF +}; +#endif /* __ASSEMBLER__ */ + +#endif /* A8K_PLAT_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h new file mode 100644 index 0000000..e19036a --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#define DRAM_MAX_IFACE 1 +#define DRAM_CH0_MMAP_LOW_OFFSET 0x20200 diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h new file mode 100644 index 0000000..e03c448 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ +/* This driver provides I2C support for Marvell A8K and compatible SoCs */ + +#ifndef MENTOR_I2C_PLAT_H +#define MENTOR_I2C_PLAT_H + +#define CONFIG_SYS_TCLK 250000000 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_SYS_I2C_SLAVE 0x0 + +#define I2C_CAN_UNSTUCK + +struct mentor_i2c_regs { + uint32_t slave_address; + uint32_t data; + uint32_t control; + union { + uint32_t status; /* when reading */ + uint32_t baudrate; /* when writing */ + }; + uint32_t xtnd_slave_addr; + uint32_t reserved[2]; + uint32_t soft_reset; + uint8_t reserved2[0xa0 - 0x20]; + uint32_t unstuck; +}; + +#endif /* MENTOR_I2C_PLAT_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S new file mode 100644 index 0000000..8faccf0 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +/* + * Required platform porting macros + * (Provided by included headers) + */ +.macro plat_crash_print_regs +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h new file mode 100644 index 0000000..45860ba --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#ifndef __ASSEMBLER__ +#include +#endif /* __ASSEMBLER__ */ + +#include +#include + +#include +#include + +/* + * Most platform porting definitions provided by included headers + */ + +/* + * DRAM Memory layout: + * +-----------------------+ + * : : + * : Linux : + * 0x04X00000-->+-----------------------+ + * | BL3-3(u-boot) |>>}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + * |-----------------------| } | + * | BL3-[0,1, 2] | }---------------------------------> | + * |-----------------------| } || | + * | BL2 | }->FIP (loaded by || | + * |-----------------------| } BootROM to DRAM) || | + * | FIP_TOC | } || | + * 0x04120000-->|-----------------------| || | + * | BL1 (RO) | || | + * 0x04100000-->+-----------------------+ || | + * : : || | + * : Trusted SRAM section : \/ | + * 0x04040000-->+-----------------------+ Replaced by BL2 +----------------+ | + * | BL1 (RW) | <<<<<<<<<<<<<<<< | BL3-1 NOBITS | | + * 0x04037000-->|-----------------------| <<<<<<<<<<<<<<<< |----------------| | + * | | <<<<<<<<<<<<<<<< | BL3-1 PROGBITS | | + * 0x04023000-->|-----------------------| +----------------+ | + * | BL2 | | + * |-----------------------| | + * | | | + * 0x04001000-->|-----------------------| | + * | Shared | | + * 0x04000000-->+-----------------------+ | + * : : | + * : Linux : | + * : : | + * |-----------------------| | + * | | U-Boot(BL3-3) Loaded by BL2 | + * | U-Boot | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + * 0x00000000-->+-----------------------+ + * + * Trusted SRAM section 0x4000000..0x4200000: + * ---------------------------------------- + * SRAM_BASE = 0x4001000 + * BL2_BASE = 0x4006000 + * BL2_LIMIT = BL31_BASE + * BL31_BASE = 0x4023000 = (64MB + 256KB - 0x1D000) + * BL31_PROGBITS_LIMIT = BL1_RW_BASE + * BL1_RW_BASE = 0x4037000 = (64MB + 256KB - 0x9000) + * BL1_RW_LIMIT = BL31_LIMIT = 0x4040000 + * + * + * PLAT_MARVELL_FIP_BASE = 0x4120000 + */ + +#define PLAT_MARVELL_SRAM_BASE 0xFFE1C048 +#define PLAT_MARVELL_SRAM_END 0xFFE78000 + +#define PLAT_MARVELL_ATF_BASE 0x4000000 +#define PLAT_MARVELL_ATF_LOAD_ADDR (PLAT_MARVELL_ATF_BASE + \ + 0x100000) + +#define PLAT_MARVELL_FIP_BASE (PLAT_MARVELL_ATF_LOAD_ADDR + \ + 0x20000) +#define PLAT_MARVELL_FIP_MAX_SIZE 0x4000000 + +#define PLAT_MARVELL_NORTHB_COUNT 1 + +#define PLAT_MARVELL_CLUSTER_COUNT U(2) +#define PLAT_MARVELL_CLUSTER_CORE_COUNT U(2) + +#define PLAT_MARVELL_CORE_COUNT (PLAT_MARVELL_CLUSTER_COUNT * \ + PLAT_MARVELL_CLUSTER_CORE_COUNT) + +#define PLAT_MAX_CPUS_PER_CLUSTER PLAT_MARVELL_CLUSTER_CORE_COUNT + +/* Part of DRAM that is used as Trusted ROM */ +#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR +/* 4 MB for FIP image */ +#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x00400000 +/* Reserve 12MB for SCP (Secure PayLoad) Trusted RAM + * OP-TEE 4MB SHMEM follows this region + */ +#define PLAT_MARVELL_TRUSTED_RAM_BASE 0x04400000 +#define PLAT_MARVELL_TRUSTED_RAM_SIZE 0x00C00000 /* 12 MB DRAM */ + +#define PLAT_MARVELL_LLC_SRAM_BASE 0x05400000 +#define PLAT_MARVELL_LLC_SRAM_SIZE 0x00100000 /* 1 MB SRAM */ + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_MARVELL_MAX_BL1_RW_SIZE 0xA000 + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#define PLAT_MARVELL_MAX_BL2_SIZE 0xF000 + +/* + * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#define PLAT_MARVEL_MAX_BL31_SIZE 0x5D000 + +#define PLAT_MARVELL_CPU_ENTRY_ADDR BL1_RO_BASE + +/* GIC related definitions */ +#define PLAT_MARVELL_GICD_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE) +#define PLAT_MARVELL_GICC_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE) + +#define PLAT_MARVELL_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_PIC0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_MARVELL_SHARED_RAM_CACHED 1 + +/* + * Load address of BL3-3 for this platform port + */ +#define PLAT_MARVELL_NS_IMAGE_OFFSET 0x0 + +/* System Reference Clock*/ +#define PLAT_REF_CLK_IN_HZ COUNTER_FREQUENCY + +/* + * PL011 related constants + */ +#define PLAT_MARVELL_UART_BASE (MVEBU_REGS_BASE + 0x512000) +#define PLAT_MARVELL_UART_CLK_IN_HZ 200000000 + +/* Recovery image enable */ +#define PLAT_RECOVERY_IMAGE_ENABLE 0 + +/* Required platform porting definitions */ +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 + +/* System timer related constants */ +#define PLAT_MARVELL_NSTIMER_FRAME_ID 1 + +/* Mailbox base address (note the lower memory space + * is reserved for BLE data) + */ +#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_SHARED_RAM_BASE \ + + 0x400) +#define PLAT_MARVELL_MAILBOX_SIZE 0x100 +#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C /* mrvl */ + +/* Securities */ +#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER + +#define MVEBU_PMU_IRQ_WA + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_a8k.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_a8k.mk new file mode 100644 index 0000000..315fc87 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_a8k.mk @@ -0,0 +1,22 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PLAT_MARVELL := plat/marvell/armada +A8K_MSS_SOURCE := $(PLAT_MARVELL)/a8k/common/mss + +BL2_SOURCES += $(A8K_MSS_SOURCE)/mss_bl2_setup.c \ + $(MARVELL_MOCHI_DRV) + +BL31_SOURCES += $(A8K_MSS_SOURCE)/mss_pm_ipc.c \ + $(A8K_MSS_SOURCE)/mss_bl31_setup.c + +PLAT_INCLUDES += -I$(A8K_MSS_SOURCE) + +ifneq (${SCP_BL2},) +# This define is used to inidcate the SCP image is present +$(eval $(call add_define,SCP_IMAGE)) +endif diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c new file mode 100644 index 0000000..dee2d5b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include /* timer functionality */ +#include "mss_defs.h" +#include "mss_scp_bootloader.h" + +/* MSS windows configuration */ +#define MSS_AEBR(base) (base + 0x160) +#define MSS_AIBR(base) (base + 0x164) +#define MSS_AEBR_MASK 0xFFF +#define MSS_AIBR_MASK 0xFFF + +#define MSS_EXTERNAL_SPACE 0x50000000 +#define MSS_EXTERNAL_ACCESS_BIT 28 +#define MSS_EXTERNAL_ADDR_MASK 0xfffffff +#define MSS_INTERNAL_ACCESS_BIT 28 + +struct addr_map_win ccu_mem_map[] = { + {MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID} +}; + +/* Since the scp_bl2 image can contain firmware for cp1 and cp0 coprocessors, + * the access to cp0 and cp1 need to be provided. More precisely it is + * required to: + * - get the information about device id which is stored in CP0 registers + * (to distinguish between cases where we have cp0 and cp1 or standalone cp0) + * - get the access to cp which is needed for loading fw for cp0/cp1 + * coprocessors + * This function configures ccu windows accordingly. + * + * Note: there is no need to restore previous ccu configuration, since in next + * phase (BL31) the init_ccu will be called (via apn806_init/ + * bl31_plat_arch_setu) and therefore the ccu configuration will be overwritten. + */ +static int bl2_plat_mmap_init(void) +{ + int cfg_num, win_id, cfg_idx, cp; + + cfg_num = ARRAY_SIZE(ccu_mem_map); + + /* CCU window-0 should not be counted - it's already used */ + if (cfg_num > (MVEBU_CCU_MAX_WINS - 1)) { + ERROR("BL2: %s: trying to open too many windows\n", __func__); + return -1; + } + + /* Enable required CCU windows + * Do not touch CCU window 0, + * it's used for the internal registers access + */ + for (cfg_idx = 0, win_id = 1; + (win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) { + /* Skip already enabled CCU windows */ + if (ccu_is_win_enabled(MVEBU_AP0, win_id)) + continue; + /* Enable required CCU windows */ + ccu_win_check(&ccu_mem_map[cfg_idx]); + ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id); + cfg_idx++; + } + + /* Config address for each cp other than cp0 */ + for (cp = 1; cp < CP_COUNT; cp++) + update_cp110_default_win(cp); + + /* There is need to configure IO_WIN windows again to overwrite + * temporary configuration done during update_cp110_default_win + */ + init_io_win(MVEBU_AP0); + + /* Open AMB bridge required for MG access */ + for (cp = 0; cp < CP_COUNT; cp++) + cp110_amb_init(MVEBU_CP_REGS_BASE(cp)); + + return 0; +} + +/***************************************************************************** + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ***************************************************************************** + */ +int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + int ret; + + INFO("BL2: Initiating SCP_BL2 transfer to SCP\n"); + + /* initialize time (for delay functionality) */ + plat_delay_timer_init(); + + ret = bl2_plat_mmap_init(); + if (ret != 0) + return ret; + + ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + + if (ret == 0) + INFO("BL2: SCP_BL2 transferred to SCP\n"); + else + ERROR("BL2: SCP_BL2 transfer failure\n"); + + return ret; +} + +uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx) +{ + return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET; +} + +uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx) +{ + return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET; +} + +uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx) +{ + return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET; +} + +uint32_t bl2_plat_get_cp_count(int ap_idx) +{ + uint32_t revision = cp110_device_id_get(MVEBU_CP_REGS_BASE(0)); + /* A8040: two CPs. + * A7040: one CP. + */ + if (revision == MVEBU_80X0_DEV_ID || + revision == MVEBU_80X0_CP115_DEV_ID) + return 2; + else if (revision == MVEBU_CN9130_DEV_ID) + return CP_COUNT; + else + return 1; +} + +uint32_t bl2_plat_get_ap_count(void) +{ + /* A8040 and A7040 have only one AP */ + return 1; +} + +void bl2_plat_configure_mss_windows(uintptr_t mss_regs) +{ + /* set AXI External and Internal Address Bus extension */ + mmio_write_32(MSS_AEBR(mss_regs), + ((0x0 >> MSS_EXTERNAL_ACCESS_BIT) & MSS_AEBR_MASK)); + mmio_write_32(MSS_AIBR(mss_regs), + ((mss_regs >> MSS_INTERNAL_ACCESS_BIT) & MSS_AIBR_MASK)); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c new file mode 100644 index 0000000..52a8929 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include + +#include + +#include "mss_defs.h" + +void mss_start_cp_cm3(int cp) +{ + uint32_t magic; + uintptr_t sram = MVEBU_CP_REGS_BASE(cp) + MSS_CP_SRAM_OFFSET; + uintptr_t regs = MVEBU_CP_REGS_BASE(cp) + MSS_CP_REGS_OFFSET; + + magic = mmio_read_32(sram); + + /* Make sure the FW was loaded */ + if (magic != MSS_FW_READY_MAGIC) { + return; + } + + NOTICE("Starting CP%d MSS CPU\n", cp); + /* remove the magic */ + mmio_write_32(sram, 0); + /* Release M3 from reset */ + mmio_write_32(MSS_M3_RSTCR(regs), + (MSS_M3_RSTCR_RST_OFF << MSS_M3_RSTCR_RST_OFFSET)); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h new file mode 100644 index 0000000..6956461 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MSS_DEFS_H +#define MSS_DEFS_H + +#define MSS_DMA_SRCBR(base) (base + 0xC0) +#define MSS_DMA_DSTBR(base) (base + 0xC4) +#define MSS_DMA_CTRLR(base) (base + 0xC8) +#define MSS_M3_RSTCR(base) (base + 0xFC) + +#define MSS_DMA_CTRLR_SIZE_OFFSET (0) +#define MSS_DMA_CTRLR_REQ_OFFSET (15) +#define MSS_DMA_CTRLR_REQ_SET (1) +#define MSS_DMA_CTRLR_ACK_OFFSET (12) +#define MSS_DMA_CTRLR_ACK_MASK (0x1) +#define MSS_DMA_CTRLR_ACK_READY (1) +#define MSS_M3_RSTCR_RST_OFFSET (0) +#define MSS_M3_RSTCR_RST_OFF (1) + +#define MSS_FW_READY_MAGIC 0x46575144 /* FWRD */ + +#define MSS_AP_REGS_OFFSET 0x00580000 +#define MSS_CP_SRAM_OFFSET 0x00220000 +#define MSS_CP_REGS_OFFSET 0x00280000 + +void mss_start_cp_cm3(int cp); + +#endif /* MSS_DEFS_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c new file mode 100644 index 0000000..a070583 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include + +#include + +/* + * SISR is 32 bit interrupt register representing 32 interrupts + * + * +======+=============+=============+ + * + Bits + 31 + 30 - 00 + + * +======+=============+=============+ + * + Desc + MSS Msg Int + Reserved + + * +======+=============+=============+ + */ +#define MSS_SISR (MVEBU_REGS_BASE + 0x5800D0) +#define MSS_SISTR (MVEBU_REGS_BASE + 0x5800D8) + +#define MSS_MSG_INT_MASK (0x80000000) +#define MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110) +#define MSS_TRIGGER_TIMEOUT (2000) + +/***************************************************************************** + * mss_pm_ipc_msg_send + * + * DESCRIPTION: create and transmit IPC message + ***************************************************************************** + */ +int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id, + const psci_power_state_t *target_state) +{ + /* Transmit IPC message */ +#ifndef DISABLE_CLUSTER_LEVEL + mv_pm_ipc_msg_tx(channel_id, msg_id, + (unsigned int)target_state->pwr_domain_state[ + MPIDR_AFFLVL1]); +#else + mv_pm_ipc_msg_tx(channel_id, msg_id, 0); +#endif + + return 0; +} + +/***************************************************************************** + * mss_pm_ipc_msg_trigger + * + * DESCRIPTION: Trigger IPC message interrupt to MSS + ***************************************************************************** + */ +int mss_pm_ipc_msg_trigger(void) +{ + unsigned int timeout; + unsigned int t_end; + unsigned int t_start = mmio_read_32(MSS_TIMER_BASE); + + mmio_write_32(MSS_SISR, MSS_MSG_INT_MASK); + + do { + /* wait while SCP process incoming interrupt */ + if (mmio_read_32(MSS_SISTR) != MSS_MSG_INT_MASK) + break; + + /* check timeout */ + t_end = mmio_read_32(MSS_TIMER_BASE); + + timeout = ((t_start > t_end) ? + (t_start - t_end) : (t_end - t_start)); + if (timeout > MSS_TRIGGER_TIMEOUT) { + ERROR("PM MSG Trigger Timeout\n"); + break; + } + + } while (1); + + return 0; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h new file mode 100644 index 0000000..1dfa9fa --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MSS_PM_IPC_H +#define MSS_PM_IPC_H + +#include + +/* Currently MSS does not support Cluster level Power Down */ +#define DISABLE_CLUSTER_LEVEL + + +/***************************************************************************** + * mss_pm_ipc_msg_send + * + * DESCRIPTION: create and transmit IPC message + ***************************************************************************** + */ +int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id, + const psci_power_state_t *target_state); + +/***************************************************************************** + * mss_pm_ipc_msg_trigger + * + * DESCRIPTION: Trigger IPC message interrupt to MSS + ***************************************************************************** + */ +int mss_pm_ipc_msg_trigger(void); + + +#endif /* MSS_PM_IPC_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c new file mode 100644 index 0000000..f9521c8 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include + +void marvell_bl1_setup_mpps(void) +{ + /* Enable UART MPPs. + ** In a normal system, this is done by Bootrom. + */ + mmio_write_32(MVEBU_AP_MPP_REGS(1), 0x3000); + mmio_write_32(MVEBU_AP_MPP_REGS(2), 0x3000); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c new file mode 100644 index 0000000..db85cce --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#if MSS_SUPPORT +#include +#include +#include +#endif + +/* In Armada-8k family AP806/AP807, CP0 connected to PIDI + * and CP1 connected to IHB via MCI #0 + */ +#define MVEBU_MCI0 0 + +static _Bool pm_fw_running; + +/* Set a weak stub for platforms that don't need to configure GPIO */ +#pragma weak marvell_gpio_config +int marvell_gpio_config(void) +{ + return 0; +} + +static void marvell_bl31_mpp_init(int cp) +{ + uint32_t reg; + + /* need to do for CP#0 only */ + if (cp) + return; + + + /* + * Enable CP0 I2C MPPs (MPP: 37-38) + * U-Boot rely on proper MPP settings for I2C EEPROM usage + * (only for CP0) + */ + reg = mmio_read_32(MVEBU_CP_MPP_REGS(0, 4)); + mmio_write_32(MVEBU_CP_MPP_REGS(0, 4), reg | 0x2200000); +} + +#if MSS_SUPPORT +void marvell_bl31_mss_init(void) +{ + struct mss_pm_ctrl_block *mss_pm_crtl = + (struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE; + + /* Check that the image was loaded successfully */ + if (mss_pm_crtl->handshake != HOST_ACKNOWLEDGMENT) { + NOTICE("MSS PM is not supported in this build\n"); + return; + } + + /* If we got here it means that the PM firmware is running */ + pm_fw_running = 1; + + INFO("MSS IPC init\n"); + + if (mss_pm_crtl->ipc_state == IPC_INITIALIZED) + mv_pm_ipc_init(mss_pm_crtl->ipc_base_address | MVEBU_REGS_BASE); +} +#endif + +_Bool is_pm_fw_running(void) +{ + return pm_fw_running; +} + +/* For TrusTzone we treat the "target" field of addr_map_win + * struct as attribute + */ +static const struct addr_map_win tz_map[] = { + {PLAT_MARVELL_ATF_BASE, 0x200000, TZ_PERM_ABORT} +}; + +/* Configure MC TrustZone regions */ +static void marvell_bl31_security_setup(void) +{ + int tz_nr, win_id; + + tz_nr = ARRAY_SIZE(tz_map); + + for (win_id = 0; win_id < tz_nr; win_id++) + tz_enable_win(MVEBU_AP0, tz_map, win_id); +} + +/* This function overruns the same function in marvell_bl31_setup.c */ +void bl31_plat_arch_setup(void) +{ + int cp; + uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE; + + /* initialize the timer for mdelay/udelay functionality */ + plat_delay_timer_init(); + + /* configure apn806 */ + ap_init(); + + /* In marvell_bl31_plat_arch_setup, el3 mmu is configured. + * el3 mmu configuration MUST be called after apn806_init, if not, + * this will cause an hang in init_io_win + * (after setting the IO windows GCR values). + */ + if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM || + mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE) + marvell_bl31_plat_arch_setup(); + + for (cp = 0; cp < CP_COUNT; cp++) { + cp110_init(MVEBU_CP_REGS_BASE(cp), + STREAM_ID_BASE + (cp * MAX_STREAM_ID_PER_CP)); + + marvell_bl31_mpp_init(cp); + +#if MSS_SUPPORT + /* Release CP MSS CPU from reset once the CP init is done */ + mss_start_cp_cm3(cp); +#endif + } + + for (cp = 1; cp < CP_COUNT; cp++) + mci_link_tune(cp - 1); + +#if MSS_SUPPORT + /* initialize IPC between MSS and ATF */ + if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM || + mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE) + marvell_bl31_mss_init(); +#endif + /* Configure GPIO */ + marvell_gpio_config(); + + marvell_bl31_security_setup(); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c new file mode 100644 index 0000000..9c5ee15 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c @@ -0,0 +1,765 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Register for skip image use */ +#define SCRATCH_PAD_REG2 0xF06F00A8 +#define SCRATCH_PAD_SKIP_VAL 0x01 +#define NUM_OF_GPIO_PER_REG 32 + +#define MMAP_SAVE_AND_CONFIG 0 +#define MMAP_RESTORE_SAVED 1 + +/* SAR clock settings */ +#define MVEBU_AP_SAR_REG_BASE(r) (MVEBU_AP_GEN_MGMT_BASE + 0x200 +\ + ((r) << 2)) + +#define SAR_CLOCK_FREQ_MODE_OFFSET (0) +#define SAR_CLOCK_FREQ_MODE_MASK (0x1f << SAR_CLOCK_FREQ_MODE_OFFSET) +#define SAR_PIDI_LOW_SPEED_OFFSET (20) +#define SAR_PIDI_LOW_SPEED_MASK (1 << SAR_PIDI_LOW_SPEED_OFFSET) +#define SAR_PIDI_LOW_SPEED_SHIFT (15) +#define SAR_PIDI_LOW_SPEED_SET (1 << SAR_PIDI_LOW_SPEED_SHIFT) + +#define FREQ_MODE_AP_SAR_REG_NUM (0) +#define SAR_CLOCK_FREQ_MODE(v) (((v) & SAR_CLOCK_FREQ_MODE_MASK) >> \ + SAR_CLOCK_FREQ_MODE_OFFSET) + +#define AVS_I2C_EEPROM_ADDR 0x57 /* EEPROM */ +#define AVS_EN_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x130) +#define AVS_ENABLE_OFFSET (0) +#define AVS_SOFT_RESET_OFFSET (2) +#define AVS_TARGET_DELTA_OFFSET (21) + +#ifndef MVEBU_SOC_AP807 + /* AP806 SVC bits */ + #define AVS_LOW_VDD_LIMIT_OFFSET (4) + #define AVS_HIGH_VDD_LIMIT_OFFSET (12) + #define AVS_VDD_LOW_LIMIT_MASK (0xFF << AVS_LOW_VDD_LIMIT_OFFSET) + #define AVS_VDD_HIGH_LIMIT_MASK (0xFF << AVS_HIGH_VDD_LIMIT_OFFSET) +#else + /* AP807 SVC bits */ + #define AVS_LOW_VDD_LIMIT_OFFSET (3) + #define AVS_HIGH_VDD_LIMIT_OFFSET (13) + #define AVS_VDD_LOW_LIMIT_MASK (0x3FF << AVS_LOW_VDD_LIMIT_OFFSET) + #define AVS_VDD_HIGH_LIMIT_MASK (0x3FF << AVS_HIGH_VDD_LIMIT_OFFSET) +#endif + +/* VDD limit is 0.9V for A70x0 @ CPU frequency < 1600MHz */ +#define AVS_A7K_LOW_CLK_VALUE ((0x80 << AVS_TARGET_DELTA_OFFSET) | \ + (0x1A << AVS_HIGH_VDD_LIMIT_OFFSET) | \ + (0x1A << AVS_LOW_VDD_LIMIT_OFFSET) | \ + (0x1 << AVS_SOFT_RESET_OFFSET) | \ + (0x1 << AVS_ENABLE_OFFSET)) +/* VDD limit is 1.0V for all A80x0 devices */ +#define AVS_A8K_CLK_VALUE ((0x80 << AVS_TARGET_DELTA_OFFSET) | \ + (0x24 << AVS_HIGH_VDD_LIMIT_OFFSET) | \ + (0x24 << AVS_LOW_VDD_LIMIT_OFFSET) | \ + (0x1 << AVS_SOFT_RESET_OFFSET) | \ + (0x1 << AVS_ENABLE_OFFSET)) + +/* VDD is 0.88V for 2GHz clock on CN913x devices */ +#define AVS_AP807_CLK_VALUE ((0x80UL << 24) | \ + (0x2dc << 13) | \ + (0x2dc << 3) | \ + (0x1 << AVS_SOFT_RESET_OFFSET) | \ + (0x1 << AVS_ENABLE_OFFSET)) + +/* + * - Identification information in the LD-0 eFuse: + * DRO: LD0[74:65] - Not used by the SW + * Revision: LD0[78:75] - Not used by the SW + * Bin: LD0[80:79] - Not used by the SW + * SW Revision: LD0[115:113] + * Cluster 1 PWR: LD0[193] - if set to 1, power down CPU Cluster-1 + * resulting in 2 CPUs active only (7020) + */ +/* Offsets for 2 efuse fields combined into single 64-bit value [125:63] */ +#define EFUSE_AP_LD0_DRO_OFFS 2 /* LD0[74:65] */ +#define EFUSE_AP_LD0_DRO_MASK 0x3FF +#define EFUSE_AP_LD0_REVID_OFFS 12 /* LD0[78:75] */ +#define EFUSE_AP_LD0_REVID_MASK 0xF +#define EFUSE_AP_LD0_BIN_OFFS 16 /* LD0[80:79] */ +#define EFUSE_AP_LD0_BIN_MASK 0x3 +#define EFUSE_AP_LD0_SWREV_MASK 0x7 + +#ifndef MVEBU_SOC_AP807 + /* AP806 AVS work points in the LD0 eFuse + * SVC1 work point: LD0[88:81] + * SVC2 work point: LD0[96:89] + * SVC3 work point: LD0[104:97] + * SVC4 work point: LD0[112:105] + */ + #define EFUSE_AP_LD0_SVC1_OFFS 18 /* LD0[88:81] */ + #define EFUSE_AP_LD0_SVC2_OFFS 26 /* LD0[96:89] */ + #define EFUSE_AP_LD0_SVC3_OFFS 34 /* LD0[104:97] */ + #define EFUSE_AP_LD0_WP_MASK 0xFF + #define EFUSE_AP_LD0_SWREV_OFFS 50 /* LD0[115:113] */ +#else + /* AP807 AVS work points in the LD0 eFuse + * SVC1 work point: LD0[91:81] + * SVC2 work point: LD0[102:92] + * SVC3 work point: LD0[113:103] + */ + #define EFUSE_AP_LD0_SVC1_OFFS 18 /* LD0[91:81] */ + #define EFUSE_AP_LD0_SVC2_OFFS 29 /* LD0[102:92] */ + #define EFUSE_AP_LD0_SVC3_OFFS 40 /* LD0[113:103] */ + #define EFUSE_AP_LD0_WP_MASK 0x7FF /* 10 data,1 parity */ + #define EFUSE_AP_LD0_SWREV_OFFS 51 /* LD0[116:114] */ +#endif + +#define EFUSE_AP_LD0_SVC4_OFFS 42 /* LD0[112:105] */ + +#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4 + +#if MARVELL_SVC_TEST +#define MVEBU_CP_MPP_CTRL37_OFFS 20 +#define MVEBU_CP_MPP_CTRL38_OFFS 24 +#define MVEBU_CP_MPP_I2C_FUNC 2 +#define MVEBU_MPP_CTRL_MASK 0xf +#endif + +/* Return the AP revision of the chip */ +static unsigned int ble_get_ap_type(void) +{ + unsigned int chip_rev_id; + + chip_rev_id = mmio_read_32(MVEBU_CSS_GWD_CTRL_IIDR2_REG); + chip_rev_id = ((chip_rev_id & GWD_IIDR2_CHIP_ID_MASK) >> + GWD_IIDR2_CHIP_ID_OFFSET); + + return chip_rev_id; +} + +/****************************************************************************** + * The routine allows to save the CCU and IO windows configuration during DRAM + * setup and restore them afterwards before exiting the BLE stage. + * Such window configuration is required since not all default settings coming + * from the HW and the BootROM allow access to peripherals connected to + * all available CPn components. + * For instance, when the boot device is located on CP0, the IO window to CP1 + * is not opened automatically by the HW and if the DRAM SPD is located on CP1 + * i2c channel, it cannot be read at BLE stage. + * Therefore the DRAM init procedure have to provide access to all available + * CPn peripherals during the BLE stage by setting the CCU IO window to all + * CPnph addresses and by enabling the IO windows accordingly. + * Additionally this function configures the CCU GCR to DRAM, which allows + * usage or more than 4GB DRAM as it configured by the default CCU DRAM window. + * + * IN: + * MMAP_SAVE_AND_CONFIG - save the existing configuration and update it + * MMAP_RESTORE_SAVED - restore saved configuration + * OUT: + * NONE + **************************************************************************** + */ +static void ble_plat_mmap_config(int restore) +{ + if (restore == MMAP_RESTORE_SAVED) { + /* Restore all orig. settings that were modified by BLE stage */ + ccu_restore_win_all(MVEBU_AP0); + /* Restore CCU */ + iow_restore_win_all(MVEBU_AP0); + return; + } + + /* Store original values */ + ccu_save_win_all(MVEBU_AP0); + /* Save CCU */ + iow_save_win_all(MVEBU_AP0); + + init_ccu(MVEBU_AP0); + /* The configuration saved, now all the changes can be done */ + init_io_win(MVEBU_AP0); +} + +/**************************************************************************** + * Setup Adaptive Voltage Switching - this is required for some platforms + **************************************************************************** + */ +#if !MARVELL_SVC_TEST +static void ble_plat_avs_config(void) +{ + uint32_t freq_mode, device_id; + uint32_t avs_val = 0; + + freq_mode = + SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE( + FREQ_MODE_AP_SAR_REG_NUM))); + /* Check which SoC is running and act accordingly */ + if (ble_get_ap_type() == CHIP_ID_AP807) { + + avs_val = AVS_AP807_CLK_VALUE; + + } else { + /* Check which SoC is running and act accordingly */ + device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0)); + switch (device_id) { + case MVEBU_80X0_DEV_ID: + case MVEBU_80X0_CP115_DEV_ID: + /* Always fix the default AVS value on A80x0 */ + avs_val = AVS_A8K_CLK_VALUE; + break; + case MVEBU_70X0_DEV_ID: + case MVEBU_70X0_CP115_DEV_ID: + /* Fix AVS for CPU clocks lower than 1600MHz on A70x0 */ + if ((freq_mode > CPU_1600_DDR_900_RCLK_900_2) && + (freq_mode < CPU_DDR_RCLK_INVALID)) + avs_val = AVS_A7K_LOW_CLK_VALUE; + break; + default: + ERROR("Unsupported Device ID 0x%x\n", device_id); + return; + } + } + + if (avs_val) { + VERBOSE("AVS: Setting AVS CTRL to 0x%x\n", avs_val); + mmio_write_32(AVS_EN_CTRL_REG, avs_val); + } +} +#endif +/****************************************************************************** + * Update or override current AVS work point value using data stored in EEPROM + * This is only required by QA/validation flows and activated by + * MARVELL_SVC_TEST flag. + * + * The function is expected to be called twice. + * + * First time with AVS value of 0 for testing if the EEPROM requests completely + * override the AVS value and bypass the eFuse test + * + * Second time - with non-zero AVS value obtained from eFuses as an input. + * In this case the EEPROM may contain AVS correction value (either positive + * or negative) that is added to the input AVS value and returned back for + * further processing. + ****************************************************************************** + */ +static uint32_t avs_update_from_eeprom(uint32_t avs_workpoint) +{ + uint32_t new_wp = avs_workpoint; +#if MARVELL_SVC_TEST + /* --------------------------------------------------------------------- + * EEPROM | Data description (avs_step) + * address | + * --------------------------------------------------------------------- + * 0x120 | AVS workpoint correction value + * | if not 0 and not 0xff, correct the AVS taken from eFuse + * | by the number of steps indicated by bit[6:0] + * | bit[7] defines correction direction. + * | If bit[7]=1, add the value from bit[6:0] to AVS workpoint, + * | othervise substruct this value from AVS workpoint. + * --------------------------------------------------------------------- + * 0x121 | AVS workpoint override value + * | Override the AVS workpoint with the value stored in this + * | byte. When running on AP806, the AVS workpoint is 7 bits + * | wide and override value is valid when bit[6:0] holds + * | value greater than zero and smaller than 0x33. + * | When running on AP807, the AVS workpoint is 10 bits wide. + * | Additional 2 MSB bits are supplied by EEPROM byte 0x122. + * | AVS override value is valid when byte @ 0x121 and bit[1:0] + * | of byte @ 0x122 combined have non-zero value. + * --------------------------------------------------------------------- + * 0x122 | Extended AVS workpoint override value + * | Valid only for AP807 platforms and must be less than 0x4 + * --------------------------------------------------------------------- + */ + static uint8_t avs_step[3] = {0}; + uintptr_t reg; + uint32_t val; + unsigned int ap_type = ble_get_ap_type(); + + /* Always happens on second call to this function */ + if (avs_workpoint != 0) { + /* Get correction steps from the EEPROM */ + if ((avs_step[0] != 0) && (avs_step[0] != 0xff)) { + NOTICE("AVS request to step %s by 0x%x from old 0x%x\n", + avs_step[0] & 0x80 ? "DOWN" : "UP", + avs_step[0] & 0x7f, new_wp); + if (avs_step[0] & 0x80) + new_wp -= avs_step[0] & 0x7f; + else + new_wp += avs_step[0] & 0x7f; + } + + return new_wp; + } + + /* AVS values are located in EEPROM + * at CP0 i2c bus #0, device 0x57 offset 0x120 + * The SDA and SCK pins of CP0 i2c-0: MPP[38:37], i2c function 0x2. + */ + reg = MVEBU_CP_MPP_REGS(0, 4); + val = mmio_read_32(reg); + val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS)); + val |= (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL38_OFFS); + mmio_write_32(reg, val); + + /* Init CP0 i2c-0 */ + i2c_init((void *)(MVEBU_CP0_I2C_BASE)); + + /* Read EEPROM only once at the fist call! */ + i2c_read(AVS_I2C_EEPROM_ADDR, 0x120, 2, avs_step, 3); + NOTICE("== SVC test build ==\n"); + NOTICE("EEPROM holds values 0x%x, 0x%x and 0x%x\n", + avs_step[0], avs_step[1], avs_step[2]); + + /* Override the AVS value? */ + if ((ap_type != CHIP_ID_AP807) && (avs_step[1] < 0x33)) { + /* AP806 - AVS is 7 bits */ + new_wp = avs_step[1]; + + } else if (ap_type == CHIP_ID_AP807 && (avs_step[2] < 0x4)) { + /* AP807 - AVS is 10 bits */ + new_wp = avs_step[2]; + new_wp <<= 8; + new_wp |= avs_step[1]; + } + + if (new_wp == 0) + NOTICE("Ignore BAD AVS Override value in EEPROM!\n"); + else + NOTICE("Override AVS by EEPROM value 0x%x\n", new_wp); +#endif /* MARVELL_SVC_TEST */ + return new_wp; +} + +/**************************************************************************** + * SVC flow - v0.10 + * The feature is intended to configure AVS value according to eFuse values + * that are burned individually for each SoC during the test process. + * Primary AVS value is stored in HD efuse and processed on power on + * by the HW engine + * Secondary AVS value is located in LD efuse and contains 4 work points for + * various CPU frequencies. + * The Secondary AVS value is only taken into account if the SW Revision stored + * in the efuse is greater than 0 and the CPU is running in a certain speed. + **************************************************************************** + */ +static void ble_plat_svc_config(void) +{ + uint32_t reg_val, avs_workpoint, freq_pidi_mode; + uint64_t efuse; + uint32_t device_id, single_cluster; + uint16_t svc[4], perr[4], i, sw_ver; + uint8_t avs_data_bits, min_sw_ver, svc_fields; + unsigned int ap_type; + + /* Get test EERPOM data */ + avs_workpoint = avs_update_from_eeprom(0); + if (avs_workpoint) + goto set_aws_wp; + + /* Set access to LD0 */ + reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG); + reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_MASK; + mmio_write_32(MVEBU_AP_EFUSE_SRV_CTRL_REG, reg_val); + + /* Obtain the value of LD0[125:63] */ + efuse = mmio_read_32(MVEBU_AP_LDX_125_95_EFUSE_OFFS); + efuse <<= 32; + efuse |= mmio_read_32(MVEBU_AP_LDX_94_63_EFUSE_OFFS); + + /* SW Revision: + * Starting from SW revision 1 the SVC flow is supported. + * SW version 0 (efuse not programmed) should follow the + * regular AVS update flow. + */ + sw_ver = (efuse >> EFUSE_AP_LD0_SWREV_OFFS) & EFUSE_AP_LD0_SWREV_MASK; + if (sw_ver < 1) { + NOTICE("SVC: SW Revision 0x%x. SVC is not supported\n", sw_ver); +#if MARVELL_SVC_TEST + NOTICE("SVC_TEST: AVS bypassed\n"); + +#else + ble_plat_avs_config(); +#endif + return; + } + + /* Frequency mode from SAR */ + freq_pidi_mode = SAR_CLOCK_FREQ_MODE( + mmio_read_32( + MVEBU_AP_SAR_REG_BASE( + FREQ_MODE_AP_SAR_REG_NUM))); + + /* Decode all SVC work points */ + svc[0] = (efuse >> EFUSE_AP_LD0_SVC1_OFFS) & EFUSE_AP_LD0_WP_MASK; + svc[1] = (efuse >> EFUSE_AP_LD0_SVC2_OFFS) & EFUSE_AP_LD0_WP_MASK; + svc[2] = (efuse >> EFUSE_AP_LD0_SVC3_OFFS) & EFUSE_AP_LD0_WP_MASK; + + /* Fetch AP type to distinguish between AP806 and AP807 */ + ap_type = ble_get_ap_type(); + + if (ap_type != CHIP_ID_AP807) { + svc[3] = (efuse >> EFUSE_AP_LD0_SVC4_OFFS) + & EFUSE_AP_LD0_WP_MASK; + INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x, [3]=0x%x\n", + svc[0], svc[1], svc[2], svc[3]); + avs_data_bits = 7; + min_sw_ver = 2; /* parity check from sw revision 2 */ + svc_fields = 4; + } else { + INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x\n", + svc[0], svc[1], svc[2]); + avs_data_bits = 10; + min_sw_ver = 1; /* parity check required from sw revision 1 */ + svc_fields = 3; + } + + /* Validate parity of SVC workpoint values */ + for (i = 0; i < svc_fields; i++) { + uint8_t parity, bit; + perr[i] = 0; + + for (bit = 1, parity = (svc[i] & 1); bit < avs_data_bits; bit++) + parity ^= (svc[i] >> bit) & 1; + + /* From SW version 1 or 2 (AP806/AP807), check parity */ + if ((sw_ver >= min_sw_ver) && + (parity != ((svc[i] >> avs_data_bits) & 1))) + perr[i] = 1; /* register the error */ + } + + single_cluster = mmio_read_32(MVEBU_AP_LDX_220_189_EFUSE_OFFS); + single_cluster = (single_cluster >> EFUSE_AP_LD0_CLUSTER_DOWN_OFFS) & 1; + + device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0)); + if (device_id == MVEBU_80X0_DEV_ID || + device_id == MVEBU_80X0_CP115_DEV_ID) { + /* A8040/A8020 */ + NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n", + single_cluster == 0 ? "8040" : "8020", freq_pidi_mode); + switch (freq_pidi_mode) { + case CPU_1800_DDR_1050_RCLK_1050: + if (perr[1]) + goto perror; + avs_workpoint = svc[1]; + break; + case CPU_1600_DDR_1050_RCLK_1050: + case CPU_1600_DDR_900_RCLK_900_2: + if (perr[2]) + goto perror; + avs_workpoint = svc[2]; + break; + case CPU_1300_DDR_800_RCLK_800: + case CPU_1300_DDR_650_RCLK_650: + if (perr[3]) + goto perror; + avs_workpoint = svc[3]; + break; + case CPU_2000_DDR_1200_RCLK_1200: + case CPU_2000_DDR_1050_RCLK_1050: + default: + if (perr[0]) + goto perror; + avs_workpoint = svc[0]; + break; + } + } else if (device_id == MVEBU_70X0_DEV_ID || + device_id == MVEBU_70X0_CP115_DEV_ID) { + /* A7040/A7020/A6040 */ + NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n", + single_cluster == 0 ? "7040" : "7020", freq_pidi_mode); + switch (freq_pidi_mode) { + case CPU_1400_DDR_800_RCLK_800: + if (single_cluster) {/* 7020 */ + if (perr[1]) + goto perror; + avs_workpoint = svc[1]; + } else { + if (perr[0]) + goto perror; + avs_workpoint = svc[0]; + } + break; + case CPU_1200_DDR_800_RCLK_800: + if (single_cluster) {/* 7020 */ + if (perr[2]) + goto perror; + avs_workpoint = svc[2]; + } else { + if (perr[1]) + goto perror; + avs_workpoint = svc[1]; + } + break; + case CPU_800_DDR_800_RCLK_800: + case CPU_1000_DDR_800_RCLK_800: + if (single_cluster) {/* 7020 */ + if (perr[3]) + goto perror; + avs_workpoint = svc[3]; + } else { + if (perr[2]) + goto perror; + avs_workpoint = svc[2]; + } + break; + case CPU_600_DDR_800_RCLK_800: + if (perr[3]) + goto perror; + avs_workpoint = svc[3]; /* Same for 6040 and 7020 */ + break; + case CPU_1600_DDR_800_RCLK_800: /* 7020 only */ + default: + if (single_cluster) {/* 7020 */ + if (perr[0]) + goto perror; + avs_workpoint = svc[0]; + } else { +#if MARVELL_SVC_TEST + reg_val = mmio_read_32(AVS_EN_CTRL_REG); + avs_workpoint = (reg_val & + AVS_VDD_LOW_LIMIT_MASK) >> + AVS_LOW_VDD_LIMIT_OFFSET; + NOTICE("7040 1600Mhz, avs = 0x%x\n", + avs_workpoint); +#else + NOTICE("SVC: AVS work point not changed\n"); + return; +#endif + } + break; + } + } else if (device_id == MVEBU_3900_DEV_ID) { + NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n", + "3900", freq_pidi_mode); + switch (freq_pidi_mode) { + case CPU_1600_DDR_1200_RCLK_1200: + if (perr[0]) + goto perror; + avs_workpoint = svc[0]; + break; + case CPU_1300_DDR_800_RCLK_800: + if (perr[1]) + goto perror; + avs_workpoint = svc[1]; + break; + default: + if (perr[0]) + goto perror; + avs_workpoint = svc[0]; + break; + } + } else if (device_id == MVEBU_CN9130_DEV_ID) { + NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n", + "CN913x", freq_pidi_mode); + switch (freq_pidi_mode) { + case CPU_2200_DDR_1200_RCLK_1200: + if (perr[0]) + goto perror; + avs_workpoint = svc[0]; + break; + case CPU_2000_DDR_1200_RCLK_1200: + if (perr[1]) + goto perror; + avs_workpoint = svc[1]; + break; + case CPU_1600_DDR_1200_RCLK_1200: + if (perr[2]) + goto perror; + avs_workpoint = svc[2]; + break; + default: + ERROR("SVC: Unsupported Frequency 0x%x\n", + freq_pidi_mode); + return; + + } + } else { + ERROR("SVC: Unsupported Device ID 0x%x\n", device_id); + return; + } + + /* Set AVS control if needed */ + if (avs_workpoint == 0) { + ERROR("SVC: You are using a frequency setup which is\n"); + ERROR("Not supported by this device\n"); + ERROR("This may result in malfunction of the device\n"); + return; + } + + /* Remove parity bit */ + if (ap_type != CHIP_ID_AP807) + avs_workpoint &= 0x7F; + else + avs_workpoint &= 0x3FF; + + /* Update WP from EEPROM if needed */ + avs_workpoint = avs_update_from_eeprom(avs_workpoint); + +set_aws_wp: + reg_val = mmio_read_32(AVS_EN_CTRL_REG); + NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n", + (reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET, + avs_workpoint); + reg_val &= ~(AVS_VDD_LOW_LIMIT_MASK | AVS_VDD_HIGH_LIMIT_MASK); + reg_val |= 0x1 << AVS_ENABLE_OFFSET; + reg_val |= avs_workpoint << AVS_HIGH_VDD_LIMIT_OFFSET; + reg_val |= avs_workpoint << AVS_LOW_VDD_LIMIT_OFFSET; + mmio_write_32(AVS_EN_CTRL_REG, reg_val); + return; + +perror: + ERROR("Failed SVC WP[%d] parity check!\n", i); + ERROR("Ignoring the WP values\n"); +} + +#if PLAT_RECOVERY_IMAGE_ENABLE +static int ble_skip_image_i2c(struct skip_image *skip_im) +{ + ERROR("skipping image using i2c is not supported\n"); + /* not supported */ + return 0; +} + +static int ble_skip_image_other(struct skip_image *skip_im) +{ + ERROR("implementation missing for skip image request\n"); + /* not supported, make your own implementation */ + return 0; +} + +static int ble_skip_image_gpio(struct skip_image *skip_im) +{ + unsigned int val; + unsigned int mpp_address = 0; + unsigned int offset = 0; + + switch (skip_im->info.test.cp_ap) { + case(CP): + mpp_address = MVEBU_CP_GPIO_DATA_IN(skip_im->info.test.cp_index, + skip_im->info.gpio.num); + if (skip_im->info.gpio.num > NUM_OF_GPIO_PER_REG) + offset = skip_im->info.gpio.num - NUM_OF_GPIO_PER_REG; + else + offset = skip_im->info.gpio.num; + break; + case(AP): + mpp_address = MVEBU_AP_GPIO_DATA_IN; + offset = skip_im->info.gpio.num; + break; + } + + val = mmio_read_32(mpp_address); + val &= (1 << offset); + if ((!val && skip_im->info.gpio.button_state == HIGH) || + (val && skip_im->info.gpio.button_state == LOW)) { + mmio_write_32(SCRATCH_PAD_REG2, SCRATCH_PAD_SKIP_VAL); + return 1; + } + + return 0; +} + +/* + * This function checks if there's a skip image request: + * return values: + * 1: (true) images request been made. + * 0: (false) no image request been made. + */ +static int ble_skip_current_image(void) +{ + struct skip_image *skip_im; + + /*fetching skip image info*/ + skip_im = (struct skip_image *)plat_marvell_get_skip_image_data(); + + if (skip_im == NULL) + return 0; + + /* check if skipping image request has already been made */ + if (mmio_read_32(SCRATCH_PAD_REG2) == SCRATCH_PAD_SKIP_VAL) + return 0; + + switch (skip_im->detection_method) { + case GPIO: + return ble_skip_image_gpio(skip_im); + case I2C: + return ble_skip_image_i2c(skip_im); + case USER_DEFINED: + return ble_skip_image_other(skip_im); + } + + return 0; +} +#endif + + +int ble_plat_setup(int *skip) +{ + int ret, cp; + unsigned int freq_mode; + + /* Power down unused CPUs */ + plat_marvell_early_cpu_powerdown(); + + /* + * Save the current CCU configuration and make required changes: + * - Allow access to DRAM larger than 4GB + * - Open memory access to all CPn peripherals + */ + ble_plat_mmap_config(MMAP_SAVE_AND_CONFIG); + +#if PLAT_RECOVERY_IMAGE_ENABLE + /* Check if there's a skip request to bootRom recovery Image */ + if (ble_skip_current_image()) { + /* close memory access to all CPn peripherals. */ + ble_plat_mmap_config(MMAP_RESTORE_SAVED); + *skip = 1; + return 0; + } +#endif + /* Do required CP-110 setups for BLE stage */ + cp110_ble_init(MVEBU_CP_REGS_BASE(0)); + + /* Config address for each cp other than cp0 */ + for (cp = 1; cp < CP_COUNT; cp++) + update_cp110_default_win(cp); + + /* Setup AVS */ + ble_plat_svc_config(); + + /* read clk option from sampled-at-reset register */ + freq_mode = + SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE( + FREQ_MODE_AP_SAR_REG_NUM))); + + /* work with PLL clock driver in AP807 */ + if (ble_get_ap_type() == CHIP_ID_AP807) + ap807_clocks_init(freq_mode); + + /* Do required AP setups for BLE stage */ + ap_ble_init(); + + /* Update DRAM topology (scan DIMM SPDs) */ + plat_marvell_dram_update_topology(); + + /* Kick it in */ + ret = dram_init(); + + /* Restore the original CCU configuration before exit from BLE */ + ble_plat_mmap_config(MMAP_RESTORE_SAVED); + + return ret; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c new file mode 100644 index 0000000..9ea9276 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c @@ -0,0 +1,853 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#if MSS_SUPPORT +#include +#endif +#include +#include + +#define MVEBU_PRIVATE_UID_REG 0x30 +#define MVEBU_RFU_GLOBL_SW_RST 0x84 +#define MVEBU_CCU_RVBAR(cpu) (MVEBU_REGS_BASE + 0x640 + (cpu * 4)) +#define MVEBU_CCU_CPU_UN_RESET(cpu) (MVEBU_REGS_BASE + 0x650 + (cpu * 4)) + +#define MPIDR_CPU_GET(mpidr) ((mpidr) & MPIDR_CPU_MASK) +#define MPIDR_CLUSTER_GET(mpidr) MPIDR_AFFLVL1_VAL((mpidr)) + +#define MVEBU_GPIO_MASK(index) (1 << (index % 32)) +#define MVEBU_MPP_MASK(index) (0xF << (4 * (index % 8))) +#define MVEBU_GPIO_VALUE(index, value) (value << (index % 32)) + +#define MVEBU_USER_CMD_0_REG (MVEBU_DRAM_MAC_BASE + 0x20) +#define MVEBU_USER_CMD_CH0_OFFSET 28 +#define MVEBU_USER_CMD_CH0_MASK (1 << MVEBU_USER_CMD_CH0_OFFSET) +#define MVEBU_USER_CMD_CH0_EN (1 << MVEBU_USER_CMD_CH0_OFFSET) +#define MVEBU_USER_CMD_CS_OFFSET 24 +#define MVEBU_USER_CMD_CS_MASK (0xF << MVEBU_USER_CMD_CS_OFFSET) +#define MVEBU_USER_CMD_CS_ALL (0xF << MVEBU_USER_CMD_CS_OFFSET) +#define MVEBU_USER_CMD_SR_OFFSET 6 +#define MVEBU_USER_CMD_SR_MASK (0x3 << MVEBU_USER_CMD_SR_OFFSET) +#define MVEBU_USER_CMD_SR_ENTER (0x1 << MVEBU_USER_CMD_SR_OFFSET) +#define MVEBU_MC_PWR_CTRL_REG (MVEBU_DRAM_MAC_BASE + 0x54) +#define MVEBU_MC_AC_ON_DLY_OFFSET 8 +#define MVEBU_MC_AC_ON_DLY_MASK (0xF << MVEBU_MC_AC_ON_DLY_OFFSET) +#define MVEBU_MC_AC_ON_DLY_DEF_VAR (8 << MVEBU_MC_AC_ON_DLY_OFFSET) +#define MVEBU_MC_AC_OFF_DLY_OFFSET 4 +#define MVEBU_MC_AC_OFF_DLY_MASK (0xF << MVEBU_MC_AC_OFF_DLY_OFFSET) +#define MVEBU_MC_AC_OFF_DLY_DEF_VAR (0xC << MVEBU_MC_AC_OFF_DLY_OFFSET) +#define MVEBU_MC_PHY_AUTO_OFF_OFFSET 0 +#define MVEBU_MC_PHY_AUTO_OFF_MASK (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET) +#define MVEBU_MC_PHY_AUTO_OFF_EN (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET) + +/* this lock synchronize AP multiple cores execution with MSS */ +DEFINE_BAKERY_LOCK(pm_sys_lock); + +/* Weak definitions may be overridden in specific board */ +#pragma weak plat_marvell_get_pm_cfg + +/* AP806 CPU power down /power up definitions */ +enum CPU_ID { + CPU0, + CPU1, + CPU2, + CPU3 +}; + +#define REG_WR_VALIDATE_TIMEOUT (2000) + +#define FEATURE_DISABLE_STATUS_REG \ + (MVEBU_REGS_BASE + 0x6F8230) +#define FEATURE_DISABLE_STATUS_CPU_CLUSTER_OFFSET 4 +#define FEATURE_DISABLE_STATUS_CPU_CLUSTER_MASK \ + (0x1 << FEATURE_DISABLE_STATUS_CPU_CLUSTER_OFFSET) + +#ifdef MVEBU_SOC_AP807 + #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 1 + #define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 0 +#else + #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 0 + #define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 31 +#endif + +#define PWRC_CPUN_CR_REG(cpu_id) \ + (MVEBU_REGS_BASE + 0x680000 + (cpu_id * 0x10)) +#define PWRC_CPUN_CR_PWR_DN_RQ_MASK \ + (0x1 << PWRC_CPUN_CR_PWR_DN_RQ_OFFSET) +#define PWRC_CPUN_CR_ISO_ENABLE_OFFSET 16 +#define PWRC_CPUN_CR_ISO_ENABLE_MASK \ + (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET) +#define PWRC_CPUN_CR_LDO_BYPASS_RDY_MASK \ + (0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET) + +#define CCU_B_PRCRN_REG(cpu_id) \ + (MVEBU_REGS_BASE + 0x1A50 + \ + ((cpu_id / 2) * (0x400)) + ((cpu_id % 2) * 4)) +#define CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET 0 +#define CCU_B_PRCRN_CPUPORESET_STATIC_MASK \ + (0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET) + +/* power switch fingers */ +#define AP807_PWRC_LDO_CR0_REG \ + (MVEBU_REGS_BASE + 0x680000 + 0x100) +#define AP807_PWRC_LDO_CR0_OFFSET 16 +#define AP807_PWRC_LDO_CR0_MASK \ + (0xff << AP807_PWRC_LDO_CR0_OFFSET) +#define AP807_PWRC_LDO_CR0_VAL 0xfc + +/* + * Power down CPU: + * Used to reduce power consumption, and avoid SoC unnecessary temperature rise. + */ +static int plat_marvell_cpu_powerdown(int cpu_id) +{ + uint32_t reg_val; + int exit_loop = REG_WR_VALIDATE_TIMEOUT; + + INFO("Powering down CPU%d\n", cpu_id); + + /* 1. Isolation enable */ + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + reg_val |= 0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET; + mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); + + /* 2. Read and check Isolation enabled - verify bit set to 1 */ + do { + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + exit_loop--; + } while (!(reg_val & (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)) && + exit_loop > 0); + + /* 3. Switch off CPU power */ + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + reg_val &= ~PWRC_CPUN_CR_PWR_DN_RQ_MASK; + mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); + + /* 4. Read and check Switch Off - verify bit set to 0 */ + exit_loop = REG_WR_VALIDATE_TIMEOUT; + do { + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + exit_loop--; + } while (reg_val & PWRC_CPUN_CR_PWR_DN_RQ_MASK && exit_loop > 0); + + if (exit_loop <= 0) + goto cpu_poweroff_error; + + /* 5. De-Assert power ready */ + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + reg_val &= ~PWRC_CPUN_CR_LDO_BYPASS_RDY_MASK; + mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); + + /* 6. Assert CPU POR reset */ + reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id)); + reg_val &= ~CCU_B_PRCRN_CPUPORESET_STATIC_MASK; + mmio_write_32(CCU_B_PRCRN_REG(cpu_id), reg_val); + + /* 7. Read and poll on Validate the CPU is out of reset */ + exit_loop = REG_WR_VALIDATE_TIMEOUT; + do { + reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id)); + exit_loop--; + } while (reg_val & CCU_B_PRCRN_CPUPORESET_STATIC_MASK && exit_loop > 0); + + if (exit_loop <= 0) + goto cpu_poweroff_error; + + INFO("Successfully powered down CPU%d\n", cpu_id); + + return 0; + +cpu_poweroff_error: + ERROR("ERROR: Can't power down CPU%d\n", cpu_id); + return -1; +} + +/* + * Power down CPUs 1-3 at early boot stage, + * to reduce power consumption and SoC temperature. + * This is triggered by BLE prior to DDR initialization. + * + * Note: + * All CPUs will be powered up by plat_marvell_cpu_powerup on Linux boot stage, + * which is triggered by PSCI ops (pwr_domain_on). + */ +int plat_marvell_early_cpu_powerdown(void) +{ + uint32_t cpu_cluster_status = + mmio_read_32(FEATURE_DISABLE_STATUS_REG) & + FEATURE_DISABLE_STATUS_CPU_CLUSTER_MASK; + /* if cpu_cluster_status bit is set, + * that means we have only single cluster + */ + int cluster_count = cpu_cluster_status ? 1 : 2; + + INFO("Powering off unused CPUs\n"); + + /* CPU1 is in AP806 cluster-0, which always exists, so power it down */ + if (plat_marvell_cpu_powerdown(CPU1) == -1) + return -1; + + /* + * CPU2-3 are in AP806 2nd cluster (cluster-1), + * which doesn't exists in dual-core systems. + * so need to check if we have dual-core (single cluster) + * or quad-code (2 clusters) + */ + if (cluster_count == 2) { + /* CPU2-3 are part of 2nd cluster */ + if (plat_marvell_cpu_powerdown(CPU2) == -1) + return -1; + if (plat_marvell_cpu_powerdown(CPU3) == -1) + return -1; + } + + return 0; +} + +/* + * Power up CPU - part of Linux boot stage + */ +static int plat_marvell_cpu_powerup(u_register_t mpidr) +{ + uint32_t reg_val; + int cpu_id = MPIDR_CPU_GET(mpidr), + cluster = MPIDR_CLUSTER_GET(mpidr); + int exit_loop = REG_WR_VALIDATE_TIMEOUT; + + /* calculate absolute CPU ID */ + cpu_id = cluster * PLAT_MARVELL_CLUSTER_CORE_COUNT + cpu_id; + + INFO("Powering on CPU%d\n", cpu_id); + +#ifdef MVEBU_SOC_AP807 + /* Activate 2 power switch fingers */ + reg_val = mmio_read_32(AP807_PWRC_LDO_CR0_REG); + reg_val &= ~(AP807_PWRC_LDO_CR0_MASK); + reg_val |= (AP807_PWRC_LDO_CR0_VAL << AP807_PWRC_LDO_CR0_OFFSET); + mmio_write_32(AP807_PWRC_LDO_CR0_REG, reg_val); + udelay(100); +#endif + + /* 1. Switch CPU power ON */ + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + reg_val |= 0x1 << PWRC_CPUN_CR_PWR_DN_RQ_OFFSET; + mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); + + /* 2. Wait for CPU on, up to 100 uSec: */ + udelay(100); + + /* 3. Assert power ready */ + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + reg_val |= 0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET; + mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); + + /* 4. Read & Validate power ready + * used in order to generate 16 Host CPU cycles + */ + do { + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + exit_loop--; + } while (!(reg_val & (0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET)) && + exit_loop > 0); + + if (exit_loop <= 0) + goto cpu_poweron_error; + + /* 5. Isolation disable */ + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + reg_val &= ~PWRC_CPUN_CR_ISO_ENABLE_MASK; + mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); + + /* 6. Read and check Isolation enabled - verify bit set to 1 */ + exit_loop = REG_WR_VALIDATE_TIMEOUT; + do { + reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); + exit_loop--; + } while ((reg_val & (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)) && + exit_loop > 0); + + /* 7. De Assert CPU POR reset & Core reset */ + reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id)); + reg_val |= 0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET; + mmio_write_32(CCU_B_PRCRN_REG(cpu_id), reg_val); + + /* 8. Read & Validate CPU POR reset */ + exit_loop = REG_WR_VALIDATE_TIMEOUT; + do { + reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id)); + exit_loop--; + } while (!(reg_val & (0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET)) && + exit_loop > 0); + + if (exit_loop <= 0) + goto cpu_poweron_error; + + INFO("Successfully powered on CPU%d\n", cpu_id); + + return 0; + +cpu_poweron_error: + ERROR("ERROR: Can't power up CPU%d\n", cpu_id); + return -1; +} + +static int plat_marvell_cpu_on(u_register_t mpidr) +{ + int cpu_id; + int cluster; + + /* Set barierr */ + dsbsy(); + + /* Get cpu number - use CPU ID */ + cpu_id = MPIDR_CPU_GET(mpidr); + + /* Get cluster number - use affinity level 1 */ + cluster = MPIDR_CLUSTER_GET(mpidr); + + /* Set CPU private UID */ + mmio_write_32(MVEBU_REGS_BASE + MVEBU_PRIVATE_UID_REG, cluster + 0x4); + + /* Set the cpu start address to BL1 entry point (align to 0x10000) */ + mmio_write_32(MVEBU_CCU_RVBAR(cpu_id), + PLAT_MARVELL_CPU_ENTRY_ADDR >> 16); + + /* Get the cpu out of reset */ + mmio_write_32(MVEBU_CCU_CPU_UN_RESET(cpu_id), 0x10001); + + return 0; +} + +/***************************************************************************** + * A8K handler called to check the validity of the power state + * parameter. + ***************************************************************************** + */ +static int a8k_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pstate = psci_get_pstate_type(power_state); + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != MARVELL_PWR_LVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MARVELL_PWR_LVL0] = + MARVELL_LOCAL_STATE_RET; + } else { + for (i = MARVELL_PWR_LVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + MARVELL_LOCAL_STATE_OFF; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +/***************************************************************************** + * A8K handler called when a CPU is about to enter standby. + ***************************************************************************** + */ +static void a8k_cpu_standby(plat_local_state_t cpu_state) +{ + if (!is_pm_fw_running()) { + ERROR("%s: needs to be implemented\n", __func__); + panic(); + } +} + +/***************************************************************************** + * A8K handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ***************************************************************************** + */ +static int a8k_pwr_domain_on(u_register_t mpidr) +{ + /* Power up CPU (CPUs 1-3 are powered off at start of BLE) */ + plat_marvell_cpu_powerup(mpidr); + +#if MSS_SUPPORT + if (is_pm_fw_running()) { + unsigned int target = + ((mpidr & 0xFF) + (((mpidr >> 8) & 0xFF) * 2)); + + /* + * pm system synchronization - used to synchronize + * multiple core access to MSS + */ + bakery_lock_get(&pm_sys_lock); + + /* send CPU ON IPC Message to MSS */ + mss_pm_ipc_msg_send(target, PM_IPC_MSG_CPU_ON, 0); + + /* trigger IPC message to MSS */ + mss_pm_ipc_msg_trigger(); + + /* pm system synchronization */ + bakery_lock_release(&pm_sys_lock); + + /* trace message */ + PM_TRACE(TRACE_PWR_DOMAIN_ON | target); + } else +#endif + { + /* proprietary CPU ON exection flow */ + plat_marvell_cpu_on(mpidr); + } + return 0; +} + +/***************************************************************************** + * A8K handler called to validate the entry point. + ***************************************************************************** + */ +static int a8k_validate_ns_entrypoint(uintptr_t entrypoint) +{ + return PSCI_E_SUCCESS; +} + +/***************************************************************************** + * A8K handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ***************************************************************************** + */ +static void a8k_pwr_domain_off(const psci_power_state_t *target_state) +{ +#if MSS_SUPPORT + if (is_pm_fw_running()) { + unsigned int idx = plat_my_core_pos(); + + /* Prevent interrupts from spuriously waking up this cpu */ + gicv2_cpuif_disable(); + + /* pm system synchronization - used to synchronize multiple + * core access to MSS + */ + bakery_lock_get(&pm_sys_lock); + + /* send CPU OFF IPC Message to MSS */ + mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_OFF, target_state); + + /* trigger IPC message to MSS */ + mss_pm_ipc_msg_trigger(); + + /* pm system synchronization */ + bakery_lock_release(&pm_sys_lock); + + /* trace message */ + PM_TRACE(TRACE_PWR_DOMAIN_OFF); + } else { + INFO("%s: is not supported without SCP\n", __func__); + } +#endif +} + +/* Get PM config to power off the SoC */ +void *plat_marvell_get_pm_cfg(void) +{ + return NULL; +} + +/* + * This function should be called on restore from + * "suspend to RAM" state when the execution flow + * has to bypass BootROM image to RAM copy and speed up + * the system recovery + * + */ +static void plat_marvell_exit_bootrom(void) +{ + marvell_exit_bootrom(PLAT_MARVELL_TRUSTED_ROM_BASE); +} + +/* + * Prepare for the power off of the system via GPIO + */ +static void plat_marvell_power_off_gpio(struct power_off_method *pm_cfg, + register_t *gpio_addr, + register_t *gpio_data) +{ + unsigned int gpio; + unsigned int idx; + unsigned int shift; + unsigned int reg; + unsigned int addr; + gpio_info_t *info; + unsigned int tog_bits; + + assert((pm_cfg->cfg.gpio.pin_count < PMIC_GPIO_MAX_NUMBER) && + (pm_cfg->cfg.gpio.step_count < PMIC_GPIO_MAX_TOGGLE_STEP)); + + /* Prepare GPIOs for PMIC */ + for (gpio = 0; gpio < pm_cfg->cfg.gpio.pin_count; gpio++) { + info = &pm_cfg->cfg.gpio.info[gpio]; + /* Set PMIC GPIO to output mode */ + reg = mmio_read_32(MVEBU_CP_GPIO_DATA_OUT_EN( + info->cp_index, info->gpio_index)); + mmio_write_32(MVEBU_CP_GPIO_DATA_OUT_EN( + info->cp_index, info->gpio_index), + reg & ~MVEBU_GPIO_MASK(info->gpio_index)); + + /* Set the appropriate MPP to GPIO mode */ + reg = mmio_read_32(MVEBU_PM_MPP_REGS(info->cp_index, + info->gpio_index)); + mmio_write_32(MVEBU_PM_MPP_REGS(info->cp_index, + info->gpio_index), + reg & ~MVEBU_MPP_MASK(info->gpio_index)); + } + + /* Wait for MPP & GPIO pre-configurations done */ + mdelay(pm_cfg->cfg.gpio.delay_ms); + + /* Toggle the GPIO values, and leave final step to be triggered + * after DDR self-refresh is enabled + */ + for (idx = 0; idx < pm_cfg->cfg.gpio.step_count; idx++) { + tog_bits = pm_cfg->cfg.gpio.seq[idx]; + + /* The GPIOs must be within same GPIO register, + * thus could get the original value by first GPIO + */ + info = &pm_cfg->cfg.gpio.info[0]; + reg = mmio_read_32(MVEBU_CP_GPIO_DATA_OUT( + info->cp_index, info->gpio_index)); + addr = MVEBU_CP_GPIO_DATA_OUT(info->cp_index, info->gpio_index); + + for (gpio = 0; gpio < pm_cfg->cfg.gpio.pin_count; gpio++) { + shift = pm_cfg->cfg.gpio.info[gpio].gpio_index % 32; + if (GPIO_LOW == (tog_bits & (1 << gpio))) + reg &= ~(1 << shift); + else + reg |= (1 << shift); + } + + /* Set the GPIO register, for last step just store + * register address and values to system registers + */ + if (idx < pm_cfg->cfg.gpio.step_count - 1) { + mmio_write_32(MVEBU_CP_GPIO_DATA_OUT( + info->cp_index, info->gpio_index), reg); + mdelay(pm_cfg->cfg.gpio.delay_ms); + } else { + /* Save GPIO register and address values for + * finishing the power down operation later + */ + *gpio_addr = addr; + *gpio_data = reg; + } + } +} + +/* + * Prepare for the power off of the system + */ +static void plat_marvell_power_off_prepare(struct power_off_method *pm_cfg, + register_t *addr, register_t *data) +{ + switch (pm_cfg->type) { + case PMIC_GPIO: + plat_marvell_power_off_gpio(pm_cfg, addr, data); + break; + default: + break; + } +} + +/***************************************************************************** + * A8K handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ***************************************************************************** + */ +static void a8k_pwr_domain_suspend(const psci_power_state_t *target_state) +{ +#if MSS_SUPPORT + if (is_pm_fw_running()) { + unsigned int idx; + + /* Prevent interrupts from spuriously waking up this cpu */ + gicv2_cpuif_disable(); + + idx = plat_my_core_pos(); + + /* pm system synchronization - used to synchronize multiple + * core access to MSS + */ + bakery_lock_get(&pm_sys_lock); + + /* send CPU Suspend IPC Message to MSS */ + mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_SUSPEND, target_state); + + /* trigger IPC message to MSS */ + mss_pm_ipc_msg_trigger(); + + /* pm system synchronization */ + bakery_lock_release(&pm_sys_lock); + + /* trace message */ + PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND); + } else +#endif + { + uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE; + + INFO("Suspending to RAM\n"); + + marvell_console_runtime_end(); + + /* Prevent interrupts from spuriously waking up this cpu */ + gicv2_cpuif_disable(); + + mailbox[MBOX_IDX_SUSPEND_MAGIC] = MVEBU_MAILBOX_SUSPEND_STATE; + mailbox[MBOX_IDX_ROM_EXIT_ADDR] = (uintptr_t)&plat_marvell_exit_bootrom; + +#if PLAT_MARVELL_SHARED_RAM_CACHED + flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE + + MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t), + 2 * sizeof(uintptr_t)); +#endif + /* Flush and disable LLC before going off-power */ + llc_disable(0); + + isb(); + /* + * Do not halt here! + * The function must return for allowing the caller function + * psci_power_up_finish() to do the proper context saving and + * to release the CPU lock. + */ + } +} + +/***************************************************************************** + * A8K handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ***************************************************************************** + */ +static void a8k_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* arch specific configuration */ + marvell_psci_arch_init(0); + + /* Interrupt initialization */ + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + if (is_pm_fw_running()) { + /* trace message */ + PM_TRACE(TRACE_PWR_DOMAIN_ON_FINISH); + } +} + +/***************************************************************************** + * A8K handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ***************************************************************************** + */ +static void a8k_pwr_domain_suspend_finish( + const psci_power_state_t *target_state) +{ + if (is_pm_fw_running()) { + /* arch specific configuration */ + marvell_psci_arch_init(0); + + /* Interrupt initialization */ + gicv2_cpuif_enable(); + + /* trace message */ + PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND_FINISH); + } else { + uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE; + + /* Only primary CPU requres platform init */ + if (!plat_my_core_pos()) { + /* Initialize the console to provide + * early debug support + */ + marvell_console_runtime_init(); + + bl31_plat_arch_setup(); + marvell_bl31_platform_setup(); + /* + * Remove suspend to RAM marker from the mailbox + * for treating a regular reset as a cold boot + */ + mailbox[MBOX_IDX_SUSPEND_MAGIC] = 0; + mailbox[MBOX_IDX_ROM_EXIT_ADDR] = 0; +#if PLAT_MARVELL_SHARED_RAM_CACHED + flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE + + MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t), + 2 * sizeof(uintptr_t)); +#endif + } + } +} + +/***************************************************************************** + * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND` + * call to get the `power_state` parameter. This allows the platform to encode + * the appropriate State-ID field within the `power_state` parameter which can + * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. + ***************************************************************************** + */ +static void a8k_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + /* lower affinities use PLAT_MAX_OFF_STATE */ + for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +static void +__dead2 a8k_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + struct power_off_method *pm_cfg; + unsigned int srcmd; + unsigned int sdram_reg; + register_t gpio_data = 0, gpio_addr = 0; + + if (is_pm_fw_running()) { + psci_power_down_wfi(); + panic(); + } + + pm_cfg = (struct power_off_method *)plat_marvell_get_pm_cfg(); + + /* Prepare for power off */ + plat_marvell_power_off_prepare(pm_cfg, &gpio_addr, &gpio_data); + + /* First step to enable DDR self-refresh + * to keep the data during suspend + */ + mmio_write_32(MVEBU_MC_PWR_CTRL_REG, 0x8C1); + + /* Save DDR self-refresh second step register + * and value to be issued later + */ + sdram_reg = MVEBU_USER_CMD_0_REG; + srcmd = mmio_read_32(sdram_reg); + srcmd &= ~(MVEBU_USER_CMD_CH0_MASK | MVEBU_USER_CMD_CS_MASK | + MVEBU_USER_CMD_SR_MASK); + srcmd |= (MVEBU_USER_CMD_CH0_EN | MVEBU_USER_CMD_CS_ALL | + MVEBU_USER_CMD_SR_ENTER); + + /* + * Wait for DRAM is done using registers access only. + * At this stage any access to DRAM (procedure call) will + * release it from the self-refresh mode + */ + __asm__ volatile ( + /* Align to a cache line */ + " .balign 64\n\t" + + /* Enter self refresh */ + " str %[srcmd], [%[sdram_reg]]\n\t" + + /* + * Wait 100 cycles for DDR to enter self refresh, by + * doing 50 times two instructions. + */ + " mov x1, #50\n\t" + "1: subs x1, x1, #1\n\t" + " bne 1b\n\t" + + /* Issue the command to trigger the SoC power off */ + " str %[gpio_data], [%[gpio_addr]]\n\t" + + /* Trap the processor */ + " b .\n\t" + : : [srcmd] "r" (srcmd), [sdram_reg] "r" (sdram_reg), + [gpio_addr] "r" (gpio_addr), [gpio_data] "r" (gpio_data) + : "x1"); + + panic(); +} + +/***************************************************************************** + * A8K handlers to shutdown/reboot the system + ***************************************************************************** + */ + +/* Set a weak stub for platforms that don't configure system power off */ +#pragma weak system_power_off +int system_power_off(void) +{ + return 0; +} + +static void __dead2 a8k_system_off(void) +{ + /* Call the platform specific system power off function */ + system_power_off(); + + /* board doesn't have a system off implementation */ + ERROR("%s: needs to be implemented\n", __func__); + panic(); +} + +void plat_marvell_system_reset(void) +{ + mmio_write_32(MVEBU_RFU_BASE + MVEBU_RFU_GLOBL_SW_RST, 0x0); +} + +static void __dead2 a8k_system_reset(void) +{ + plat_marvell_system_reset(); + + /* we shouldn't get to this point */ + panic(); +} + +/***************************************************************************** + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ***************************************************************************** + */ +const plat_psci_ops_t plat_arm_psci_pm_ops = { + .cpu_standby = a8k_cpu_standby, + .pwr_domain_on = a8k_pwr_domain_on, + .pwr_domain_off = a8k_pwr_domain_off, + .pwr_domain_suspend = a8k_pwr_domain_suspend, + .pwr_domain_on_finish = a8k_pwr_domain_on_finish, + .get_sys_suspend_power_state = a8k_get_sys_suspend_power_state, + .pwr_domain_suspend_finish = a8k_pwr_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = a8k_pwr_domain_pwr_down_wfi, + .system_off = a8k_system_off, + .system_reset = a8k_system_reset, + .validate_power_state = a8k_validate_power_state, + .validate_ns_entrypoint = a8k_validate_ns_entrypoint +}; diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c new file mode 100644 index 0000000..e02a893 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#if MSS_SUPPORT +#include + +#ifdef PM_TRACE_ENABLE +#include + +/* core trace APIs */ +core_trace_func funcTbl[PLATFORM_CORE_COUNT] = { + pm_core_0_trace, + pm_core_1_trace, + pm_core_2_trace, + pm_core_3_trace}; + +/***************************************************************************** + * pm_core0_trace + * pm_core1_trace + * pm_core2_trace + * pm_core_3trace + * + * This functions set trace info into core cyclic trace queue in MSS SRAM + * memory space + ***************************************************************************** + */ +void pm_core_0_trace(unsigned int trace) +{ + unsigned int current_position_core_0 = + mmio_read_32(AP_MSS_ATF_CORE_0_CTRL_BASE); + mmio_write_32((AP_MSS_ATF_CORE_0_INFO_BASE + + (current_position_core_0 * AP_MSS_ATF_CORE_ENTRY_SIZE)), + mmio_read_32(AP_MSS_TIMER_BASE)); + mmio_write_32((AP_MSS_ATF_CORE_0_INFO_TRACE + + (current_position_core_0 * AP_MSS_ATF_CORE_ENTRY_SIZE)), + trace); + mmio_write_32(AP_MSS_ATF_CORE_0_CTRL_BASE, + ((current_position_core_0 + 1) & + AP_MSS_ATF_TRACE_SIZE_MASK)); +} + +void pm_core_1_trace(unsigned int trace) +{ + unsigned int current_position_core_1 = + mmio_read_32(AP_MSS_ATF_CORE_1_CTRL_BASE); + mmio_write_32((AP_MSS_ATF_CORE_1_INFO_BASE + + (current_position_core_1 * AP_MSS_ATF_CORE_ENTRY_SIZE)), + mmio_read_32(AP_MSS_TIMER_BASE)); + mmio_write_32((AP_MSS_ATF_CORE_1_INFO_TRACE + + (current_position_core_1 * AP_MSS_ATF_CORE_ENTRY_SIZE)), + trace); + mmio_write_32(AP_MSS_ATF_CORE_1_CTRL_BASE, + ((current_position_core_1 + 1) & + AP_MSS_ATF_TRACE_SIZE_MASK)); +} + +void pm_core_2_trace(unsigned int trace) +{ + unsigned int current_position_core_2 = + mmio_read_32(AP_MSS_ATF_CORE_2_CTRL_BASE); + mmio_write_32((AP_MSS_ATF_CORE_2_INFO_BASE + + (current_position_core_2 * AP_MSS_ATF_CORE_ENTRY_SIZE)), + mmio_read_32(AP_MSS_TIMER_BASE)); + mmio_write_32((AP_MSS_ATF_CORE_2_INFO_TRACE + + (current_position_core_2 * AP_MSS_ATF_CORE_ENTRY_SIZE)), + trace); + mmio_write_32(AP_MSS_ATF_CORE_2_CTRL_BASE, + ((current_position_core_2 + 1) & + AP_MSS_ATF_TRACE_SIZE_MASK)); +} + +void pm_core_3_trace(unsigned int trace) +{ + unsigned int current_position_core_3 = + mmio_read_32(AP_MSS_ATF_CORE_3_CTRL_BASE); + mmio_write_32((AP_MSS_ATF_CORE_3_INFO_BASE + + (current_position_core_3 * AP_MSS_ATF_CORE_ENTRY_SIZE)), + mmio_read_32(AP_MSS_TIMER_BASE)); + mmio_write_32((AP_MSS_ATF_CORE_3_INFO_TRACE + + (current_position_core_3 * AP_MSS_ATF_CORE_ENTRY_SIZE)), + trace); + mmio_write_32(AP_MSS_ATF_CORE_3_CTRL_BASE, + ((current_position_core_3 + 1) & + AP_MSS_ATF_TRACE_SIZE_MASK)); +} +#endif /* PM_TRACE_ENABLE */ +#endif /* MSS_SUPPORT */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c new file mode 100644 index 0000000..a2fc0d0 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include + +#include + +#define THERMAL_TIMEOUT 1200 + +#define THERMAL_SEN_CTRL_LSB_STRT_OFFSET 0 +#define THERMAL_SEN_CTRL_LSB_STRT_MASK \ + (0x1 << THERMAL_SEN_CTRL_LSB_STRT_OFFSET) +#define THERMAL_SEN_CTRL_LSB_RST_OFFSET 1 +#define THERMAL_SEN_CTRL_LSB_RST_MASK \ + (0x1 << THERMAL_SEN_CTRL_LSB_RST_OFFSET) +#define THERMAL_SEN_CTRL_LSB_EN_OFFSET 2 +#define THERMAL_SEN_CTRL_LSB_EN_MASK \ + (0x1 << THERMAL_SEN_CTRL_LSB_EN_OFFSET) + +#define THERMAL_SEN_CTRL_STATS_VALID_OFFSET 16 +#define THERMAL_SEN_CTRL_STATS_VALID_MASK \ + (0x1 << THERMAL_SEN_CTRL_STATS_VALID_OFFSET) +#define THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET 0 +#define THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK \ + (0x3FF << THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET) + +#define THERMAL_SEN_OUTPUT_MSB 512 +#define THERMAL_SEN_OUTPUT_COMP 1024 + +struct tsen_regs { + uint32_t ext_tsen_ctrl_lsb; + uint32_t ext_tsen_ctrl_msb; + uint32_t ext_tsen_status; +}; + +static int ext_tsen_probe(struct tsen_config *tsen_cfg) +{ + uint32_t reg, timeout = 0; + struct tsen_regs *base; + + if (tsen_cfg == NULL && tsen_cfg->regs_base == NULL) { + ERROR("initial thermal sensor configuration is missing\n"); + return -1; + } + base = (struct tsen_regs *)tsen_cfg->regs_base; + + INFO("initializing thermal sensor\n"); + + /* initialize thermal sensor hardware reset once */ + reg = mmio_read_32((uintptr_t)&base->ext_tsen_ctrl_lsb); + reg &= ~THERMAL_SEN_CTRL_LSB_RST_OFFSET; /* de-assert TSEN_RESET */ + reg |= THERMAL_SEN_CTRL_LSB_EN_MASK; /* set TSEN_EN to 1 */ + reg |= THERMAL_SEN_CTRL_LSB_STRT_MASK; /* set TSEN_START to 1 */ + mmio_write_32((uintptr_t)&base->ext_tsen_ctrl_lsb, reg); + + reg = mmio_read_32((uintptr_t)&base->ext_tsen_status); + while ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0 && + timeout < THERMAL_TIMEOUT) { + udelay(100); + reg = mmio_read_32((uintptr_t)&base->ext_tsen_status); + timeout++; + } + + if ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0) { + ERROR("thermal sensor is not ready\n"); + return -1; + } + + tsen_cfg->tsen_ready = 1; + + VERBOSE("thermal sensor was initialized\n"); + + return 0; +} + +static int ext_tsen_read(struct tsen_config *tsen_cfg, int *temp) +{ + uint32_t reg; + struct tsen_regs *base; + + if (tsen_cfg == NULL && !tsen_cfg->tsen_ready) { + ERROR("thermal sensor was not initialized\n"); + return -1; + } + base = (struct tsen_regs *)tsen_cfg->regs_base; + + reg = mmio_read_32((uintptr_t)&base->ext_tsen_status); + reg = ((reg & THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK) >> + THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET); + + /* + * TSEN output format is signed as a 2s complement number + * ranging from-512 to +511. when MSB is set, need to + * calculate the complement number + */ + if (reg >= THERMAL_SEN_OUTPUT_MSB) + reg -= THERMAL_SEN_OUTPUT_COMP; + + if (tsen_cfg->tsen_divisor == 0) { + ERROR("thermal sensor divisor cannot be zero\n"); + return -1; + } + + *temp = ((tsen_cfg->tsen_gain * ((int)reg)) + + tsen_cfg->tsen_offset) / tsen_cfg->tsen_divisor; + + return 0; +} + +static struct tsen_config tsen_cfg = { + .tsen_offset = 153400, + .tsen_gain = 425, + .tsen_divisor = 1000, + .tsen_ready = 0, + .regs_base = (void *)MVEBU_AP_EXT_TSEN_BASE, + .ptr_tsen_probe = ext_tsen_probe, + .ptr_tsen_read = ext_tsen_read +}; + +struct tsen_config *marvell_thermal_config_get(void) +{ + return &tsen_cfg; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c new file mode 100644 index 0000000..8d909dc --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef SCP_BL2_BASE + /* Fill SCP_BL2 related information if it exists */ + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), + .image_info.image_base = SCP_BL2_BASE, + .image_info.image_max_size = SCP_BL2_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* SCP_BL2_BASE */ + +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload)*/ + { + .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.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + 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 /* EL3_PAYLOAD_BASE */ + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg3 = MARVELL_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE + * where it is the pager image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE, + * where it is the paged image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = MARVELL_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = MARVELL_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = MARVELL_DRAM_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = MARVELL_DRAM_BASE, + .image_info.image_max_size = MARVELL_DRAM_SIZE, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c new file mode 100644 index 0000000..21a62d4 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak plat_get_ns_image_entrypoint +#pragma weak plat_marvell_get_mmap + +/* + * Set up the page tables for the generic and platform-specific memory regions. + * The extents of the generic memory regions are specified by the function + * arguments and consist of: + * - Trusted SRAM seen by the BL image; + * - Code section; + * - Read-only data section; + * - Coherent memory region, if applicable. + */ +void marvell_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit +#if USE_COHERENT_MEM + , + uintptr_t coh_start, + uintptr_t coh_limit +#endif + ) +{ + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n", + (void *) total_base, (void *) (total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, + MT_MEMORY | MT_RW | MT_SECURE); + + /* Re-map the code section */ + VERBOSE("Code region: %p - %p\n", + (void *) code_start, (void *) code_limit); + mmap_add_region(code_start, code_start, + code_limit - code_start, + MT_CODE | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *) rodata_start, (void *) rodata_limit); + mmap_add_region(rodata_start, rodata_start, + rodata_limit - rodata_start, + MT_RO_DATA | MT_SECURE); + +#if USE_COHERENT_MEM + /* Re-map the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *) coh_start, (void *) coh_limit); + mmap_add_region(coh_start, coh_start, + coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + /* Now (re-)map the platform-specific memory regions */ + mmap_add(plat_marvell_get_mmap()); + + /* Create the page tables to reflect the above mappings */ + init_xlat_tables(); +} + +unsigned long plat_get_ns_image_entrypoint(void) +{ + return PLAT_MARVELL_NS_IMAGE_OFFSET; +} + +/***************************************************************************** + * Gets SPSR for BL32 entry + ***************************************************************************** + */ +uint32_t marvell_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/***************************************************************************** + * Gets SPSR for BL33 entry + ***************************************************************************** + */ +uint32_t marvell_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +/***************************************************************************** + * Returns ARM platform specific memory map regions. + ***************************************************************************** + */ +const mmap_region_t *plat_marvell_get_mmap(void) +{ + return plat_marvell_mmap; +} + diff --git a/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S new file mode 100644 index 0000000..3038ec0 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#ifndef PLAT_a3700 +#include +#include +#endif +#include +#include + + .weak plat_marvell_calc_core_pos + .weak plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + .globl disable_mmu_dcache + .globl invalidate_tlb_all + .globl platform_unmap_sram + .globl disable_sram + .globl disable_icache + .globl invalidate_icache_all + .globl marvell_exit_bootrom + .globl ca72_l2_enable_unique_clean + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_marvell_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_marvell_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_marvell_calc_core_pos(uint64_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 2) + + * CoreId + * ----------------------------------------------------- + */ +func plat_marvell_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #7 + ret +endfunc plat_marvell_calc_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init +#ifdef PLAT_a3700 + mov x1, x30 + bl get_ref_clk + mov x30, x1 + mov_imm x1, 1000000 + mul x1, x0, x1 +#else + mov_imm x1, PLAT_MARVELL_UART_CLK_IN_HZ +#endif + mov_imm x0, PLAT_MARVELL_UART_BASE + mov_imm x2, MARVELL_CONSOLE_BAUDRATE +#ifdef PLAT_a3700 + b console_a3700_core_init +#else + b console_16550_core_init +#endif +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, PLAT_MARVELL_UART_BASE +#ifdef PLAT_a3700 + + b console_a3700_core_putc +#else + b console_16550_core_putc +#endif +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : r0 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, PLAT_MARVELL_UART_BASE +#ifdef PLAT_a3700 + b console_a3700_core_flush +#else + b console_16550_core_flush +#endif +endfunc plat_crash_console_flush + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on ARM + * platforms. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* ----------------------------------------------------- + * Disable icache, dcache, and MMU + * ----------------------------------------------------- + */ +func disable_mmu_dcache + mrs x0, sctlr_el3 + bic x0, x0, 0x1 /* M bit - MMU */ + bic x0, x0, 0x4 /* C bit - Dcache L1 & L2 */ + msr sctlr_el3, x0 + isb + b mmu_off +mmu_off: + ret +endfunc disable_mmu_dcache + + /* ----------------------------------------------------- + * Disable all TLB entries + * ----------------------------------------------------- + */ +func invalidate_tlb_all + tlbi alle3 + dsb sy + isb + ret +endfunc invalidate_tlb_all + + /* ----------------------------------------------------- + * Disable the i cache + * ----------------------------------------------------- + */ +func disable_icache + mrs x0, sctlr_el3 + bic x0, x0, 0x1000 /* I bit - Icache L1 & L2 */ + msr sctlr_el3, x0 + isb + ret +endfunc disable_icache + + /* ----------------------------------------------------- + * Disable all of the i caches + * ----------------------------------------------------- + */ +func invalidate_icache_all + ic ialluis + isb sy + ret +endfunc invalidate_icache_all + + /* ----------------------------------------------------- + * Clear the SRAM enabling bit to unmap SRAM + * ----------------------------------------------------- + */ +func platform_unmap_sram + ldr x0, =CCU_SRAM_WIN_CR + str wzr, [x0] + ret +endfunc platform_unmap_sram + + /* ----------------------------------------------------- + * Disable the SRAM + * ----------------------------------------------------- + */ +func disable_sram + /* Disable the line lockings. They must be disabled expictly + * or the OS will have problems using the cache */ + ldr x1, =MASTER_LLC_TC0_LOCK + str wzr, [x1] + + /* Invalidate all ways */ + ldr w1, =LLC_WAY_MASK + ldr x0, =MASTER_LLC_INV_WAY + str w1, [x0] + + /* Finally disable LLC */ + ldr x0, =MASTER_LLC_CTRL + str wzr, [x0] + + ret +endfunc disable_sram + + /* ----------------------------------------------------- + * Operation when exit bootROM: + * Disable the MMU + * Disable and invalidate the dcache + * Unmap and disable the SRAM + * Disable and invalidate the icache + * ----------------------------------------------------- + */ +func marvell_exit_bootrom + /* Save the system restore address */ + mov x28, x0 + + /* Close the caches and MMU */ + bl disable_mmu_dcache + + /* + * There is nothing important in the caches now, + * so invalidate them instead of cleaning. + */ + adr x0, __RW_START__ + adr x1, __RW_END__ + sub x1, x1, x0 + bl inv_dcache_range + bl invalidate_tlb_all + + /* + * Clean the memory mapping of SRAM + * the DDR mapping will remain to enable boot image to execute + */ + bl platform_unmap_sram + + /* Disable the SRAM */ + bl disable_sram + + /* Disable and invalidate icache */ + bl disable_icache + bl invalidate_icache_all + + mov x0, x28 + br x0 +endfunc marvell_exit_bootrom + + /* + * Enable L2 UniqueClean evictions with data + */ +func ca72_l2_enable_unique_clean + + mrs x0, CORTEX_A72_L2ACTLR_EL1 + orr x0, x0, #CORTEX_A72_L2ACTLR_ENABLE_UNIQUE_CLEAN + msr CORTEX_A72_L2ACTLR_EL1, x0 + + ret +endfunc ca72_l2_enable_unique_clean diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c new file mode 100644 index 0000000..7b7cef3 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* Weak definitions may be overridden in specific Marvell standard platform */ +#pragma weak bl1_early_platform_setup +#pragma weak bl1_plat_arch_setup +#pragma weak bl1_platform_setup +#pragma weak bl1_plat_sec_mem_layout + +/* Data structure which holds the extents of the RAM for BL1*/ +static meminfo_t bl1_ram_layout; + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_ram_layout; +} + +/* + * BL1 specific platform actions shared between Marvell standard platforms. + */ +void marvell_bl1_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + marvell_console_boot_init(); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_ram_layout.total_base = MARVELL_BL_RAM_BASE; + bl1_ram_layout.total_size = MARVELL_BL_RAM_SIZE; +} + +void bl1_early_platform_setup(void) +{ + marvell_bl1_early_platform_setup(); +} + +/* + * Perform the very early platform specific architecture setup shared between + * MARVELL standard platforms. This only does basic initialization. Later + * architectural setup (bl1_arch_setup()) does not do anything platform + * specific. + */ +void marvell_bl1_plat_arch_setup(void) +{ + marvell_setup_page_tables(bl1_ram_layout.total_base, + bl1_ram_layout.total_size, + BL1_RO_BASE, + BL1_RO_LIMIT, + BL1_RO_DATA_BASE, + BL1_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END +#endif + ); + enable_mmu_el3(0); +} + +void bl1_plat_arch_setup(void) +{ + marvell_bl1_plat_arch_setup(); +} + +/* + * Perform the platform specific architecture setup shared between + * MARVELL standard platforms. + */ +void marvell_bl1_platform_setup(void) +{ + /* Initialise the IO layer and register platform IO devices */ + plat_marvell_io_setup(); +} + +void bl1_platform_setup(void) +{ + marvell_bl1_platform_setup(); +} + +void bl1_plat_prepare_exit(entry_point_info_t *ep_info) +{ +#ifdef EL3_PAYLOAD_BASE + /* + * Program the EL3 payload's entry point address into the CPUs mailbox + * in order to release secondary CPUs from their holding pen and make + * them jump there. + */ + marvell_program_trusted_mailbox(ep_info->pc); + dsbsy(); + sev(); +#endif +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c new file mode 100644 index 0000000..3dfa82e --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef SPD_opteed +#include +#endif +#include +#include + +/* Data structure which holds the extents of the trusted SRAM for BL2 */ +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/* Weak definitions may be overridden in specific MARVELL standard platform */ +#pragma weak bl2_early_platform_setup2 +#pragma weak bl2_platform_setup +#pragma weak bl2_plat_arch_setup +#pragma weak bl2_plat_sec_mem_layout + +meminfo_t *bl2_plat_sec_mem_layout(void) +{ + return &bl2_tzram_layout; +} + +/***************************************************************************** + * BL1 has passed the extents of the trusted SRAM that should be visible to BL2 + * in x0. This memory layout is sitting at the base of the free trusted SRAM. + * Copy it to a safe location before its reclaimed by later BL2 functionality. + ***************************************************************************** + */ +void marvell_bl2_early_platform_setup(meminfo_t *mem_layout) +{ + /* Initialize the console to provide early debug support */ + marvell_console_boot_init(); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; + + /* Initialise the IO layer and register platform IO devices */ + plat_marvell_io_setup(); +} + + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct meminfo *mem_layout = (struct meminfo *)arg1; + + marvell_bl2_early_platform_setup(mem_layout); +} + +void bl2_platform_setup(void) +{ + /* Nothing to do */ +} + +/***************************************************************************** + * Perform the very early platform specific architectural setup here. At the + * moment this is only initializes the mmu in a quick and dirty way. + ***************************************************************************** + */ +void marvell_bl2_plat_arch_setup(void) +{ + marvell_setup_page_tables(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END +#endif + ); + enable_mmu_el1(0); +} + +void bl2_plat_arch_setup(void) +{ + marvell_bl2_plat_arch_setup(); +} + +int marvell_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif /* SPD_opteed */ + assert(bl_mem_params); + + switch (image_id) { + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) + WARN("OPTEE header parse error.\n"); +#endif /* SPD_opteed */ + bl_mem_params->ep_info.spsr = marvell_get_spsr_for_bl32_entry(); + break; + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = marvell_get_spsr_for_bl33_entry(); + break; +#ifdef SCP_BL2_BASE + case SCP_BL2_IMAGE_ID: + /* The subsequent handling of SCP_BL2 is platform specific */ + err = bl2_plat_handle_scp_bl2(&bl_mem_params->image_info); + if (err) { + WARN("Failure in platform-specific handling of SCP_BL2 image.\n"); + } + break; +#endif + default: + /* Do nothing in default case */ + break; + } + + return err; + +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return marvell_bl2_handle_post_image_load(image_id); +} + diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c new file mode 100644 index 0000000..26ba906 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#ifdef USE_CCI +#include +#endif +#include +#include + +#include +#include +#include + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak bl31_early_platform_setup2 +#pragma weak bl31_platform_setup +#pragma weak bl31_plat_arch_setup +#pragma weak bl31_plat_get_next_image_ep_info +#pragma weak plat_get_syscnt_freq2 + +/***************************************************************************** + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ***************************************************************************** + */ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + + return next_image_info; +} + +/***************************************************************************** + * Perform any BL31 early platform setup common to ARM standard platforms. + * Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be + * done before the MMU is initialized so that the memory layout can be used + * while creating page tables. BL2 has flushed this information to memory, so + * we are guaranteed to pick up good data. + ***************************************************************************** + */ +void marvell_bl31_early_platform_setup(void *from_bl2, + uintptr_t soc_fw_config, + uintptr_t hw_config, + void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + marvell_console_boot_init(); + +#if RESET_TO_BL31 + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + +#ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = marvell_get_spsr_for_bl32_entry(); +#endif /* BL32_BASE */ + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = marvell_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#else + /* + * In debug builds, we pass a special value in 'plat_params_from_bl2' + * to verify platform parameters from BL2 to BL31. + * In release builds, it's not used. + */ + assert(((unsigned long long)plat_params_from_bl2) == + MARVELL_BL31_PLAT_PARAM_VAL); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params != NULL) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_image_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } +#endif +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) + +{ + marvell_bl31_early_platform_setup((void *)arg0, arg1, arg2, + (void *)arg3); + +#ifdef USE_CCI + /* + * Initialize CCI for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_marvell_interconnect_init(); + + /* + * Enable CCI coherency for the primary CPU's cluster. + * Platform specific PSCI code will enable coherency for other + * clusters. + */ + plat_marvell_interconnect_enter_coherency(); +#endif +} + +/***************************************************************************** + * Perform any BL31 platform setup common to ARM standard platforms + ***************************************************************************** + */ +void marvell_bl31_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + plat_marvell_gic_driver_init(); + plat_marvell_gic_init(); + + /* For Armada-8k-plus family, the SoC includes more than + * a single AP die, but the default die that boots is AP #0. + * For other families there is only one die (#0). + * Initialize psci arch from die 0 + */ + marvell_psci_arch_init(0); +} + +/***************************************************************************** + * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM + * standard platforms + ***************************************************************************** + */ +void marvell_bl31_plat_runtime_setup(void) +{ + console_switch_state(CONSOLE_FLAG_RUNTIME); + + /* Initialize the runtime console */ + marvell_console_runtime_init(); +} + +void bl31_platform_setup(void) +{ + marvell_bl31_platform_setup(); +} + +void bl31_plat_runtime_setup(void) +{ + marvell_bl31_plat_runtime_setup(); +} + +/***************************************************************************** + * Perform the very early platform specific architectural setup shared between + * ARM standard platforms. This only does basic initialization. Later + * architectural setup (bl31_arch_setup()) does not do anything platform + * specific. + ***************************************************************************** + */ +void marvell_bl31_plat_arch_setup(void) +{ + marvell_setup_page_tables(BL31_BASE, + BL31_END - BL31_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END +#endif + ); + +#if BL31_CACHE_DISABLE + enable_mmu_el3(DISABLE_DCACHE); + INFO("Cache is disabled in BL3\n"); +#else + enable_mmu_el3(0); +#endif +} + +void bl31_plat_arch_setup(void) +{ + marvell_bl31_plat_arch_setup(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return PLAT_REF_CLK_IN_HZ; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c new file mode 100644 index 0000000..80351ae --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include + +static const int cci_map[] = { + PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX +}; + +/**************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way ARM CCI driver is initialised and used. + **************************************************************************** + */ +#pragma weak plat_marvell_interconnect_init +#pragma weak plat_marvell_interconnect_enter_coherency +#pragma weak plat_marvell_interconnect_exit_coherency + + +/**************************************************************************** + * Helper function to initialize ARM CCI driver. + **************************************************************************** + */ +void plat_marvell_interconnect_init(void) +{ + cci_init(PLAT_MARVELL_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); +} + +/**************************************************************************** + * Helper function to place current master into coherency + **************************************************************************** + */ +void plat_marvell_interconnect_enter_coherency(void) +{ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +/**************************************************************************** + * Helper function to remove current master from coherency + **************************************************************************** + */ +void plat_marvell_interconnect_exit_coherency(void) +{ + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_common.mk b/arm-trusted-firmware/plat/marvell/armada/common/marvell_common.mk new file mode 100644 index 0000000..f0e6edf --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_common.mk @@ -0,0 +1,99 @@ +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +MARVELL_PLAT_BASE := plat/marvell/armada +MARVELL_PLAT_INCLUDE_BASE := include/plat/marvell/armada + +SEPARATE_CODE_AND_RODATA := 1 + +# flag to switch from PLL to ARO +ARO_ENABLE := 0 +$(eval $(call add_define,ARO_ENABLE)) + +# Convert LLC to secure SRAM +LLC_SRAM := 0 +$(eval $(call add_define,LLC_SRAM)) + +# Enable/Disable LLC +LLC_ENABLE := 1 +$(eval $(call add_define,LLC_ENABLE)) + +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_INCLUDES += -I$(MARVELL_PLAT_INCLUDE_BASE)/common \ + -I$(MARVELL_PLAT_INCLUDE_BASE)/common/aarch64 + + +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} \ + $(MARVELL_PLAT_BASE)/common/aarch64/marvell_common.c \ + $(MARVELL_PLAT_BASE)/common/aarch64/marvell_helpers.S \ + $(MARVELL_COMMON_BASE)/marvell_console.c + +BL1_SOURCES += drivers/delay_timer/delay_timer.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + $(MARVELL_PLAT_BASE)/common/marvell_bl1_setup.c \ + $(MARVELL_PLAT_BASE)/common/marvell_io_storage.c \ + $(MARVELL_PLAT_BASE)/common/plat_delay_timer.c + +ifdef EL3_PAYLOAD_BASE +# Need the arm_program_trusted_mailbox() function to release secondary CPUs from +# their holding pen +endif + +BL2_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + common/desc_image_load.c \ + $(MARVELL_PLAT_BASE)/common/marvell_bl2_setup.c \ + $(MARVELL_PLAT_BASE)/common/marvell_io_storage.c \ + $(MARVELL_PLAT_BASE)/common/aarch64/marvell_bl2_mem_params_desc.c \ + $(MARVELL_PLAT_BASE)/common/marvell_image_load.c + +ifeq (${SPD},opteed) +PLAT_INCLUDES += -Iinclude/lib +BL2_SOURCES += lib/optee/optee_utils.c +endif + +BL31_SOURCES += $(MARVELL_PLAT_BASE)/common/marvell_bl31_setup.c \ + $(MARVELL_PLAT_BASE)/common/marvell_pm.c \ + $(MARVELL_PLAT_BASE)/common/marvell_topology.c \ + plat/common/plat_psci_common.c \ + $(MARVELL_PLAT_BASE)/common/plat_delay_timer.c \ + drivers/delay_timer/delay_timer.c + +# PSCI functionality +$(eval $(call add_define,CONFIG_ARM64)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) +endif + +# MSS (SCP) build +ifeq (${MSS_SUPPORT}, 1) +include $(MARVELL_PLAT_BASE)/common/mss/mss_common.mk +endif + +$(BUILD_PLAT)/$(BOOT_IMAGE): $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/$(FIP_NAME) + $(if $(shell find $(BUILD_PLAT)/bl1.bin -type f -size +128k),$(error "Image '$(BUILD_PLAT)/bl1.bin' is bigger than 128kB")) + @cp $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; } + @truncate -s %128K $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; } + @cat $(BUILD_PLAT)/$(FIP_NAME) >> $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; } + @truncate -s %4 $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; } + @$(ECHO_BLANK_LINE) + @echo "Built $@ successfully" + @$(ECHO_BLANK_LINE) + +.PHONY: mrvl_bootimage +mrvl_bootimage: $(BUILD_PLAT)/$(BOOT_IMAGE) + +.PHONY: mrvl_flash +mrvl_flash: $(BUILD_PLAT)/$(FLASH_IMAGE) diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c new file mode 100644 index 0000000..ef54bff --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include + +#include +#include + +#include + +#ifdef PLAT_a3700 +#include +#define PLAT_MARVELL_UART_CLK_IN_HZ (get_ref_clk() * 1000000) +#define console_marvell_register console_a3700_register +#else +#include +#define console_marvell_register console_16550_register +#endif + +static console_t marvell_boot_console; +static console_t marvell_runtime_console; + +/******************************************************************************* + * Functions that set up the console + ******************************************************************************/ + +/* Initialize the console to provide early debug support */ +void marvell_console_boot_init(void) +{ + int rc = + console_marvell_register(PLAT_MARVELL_UART_BASE, + PLAT_MARVELL_UART_CLK_IN_HZ, + MARVELL_CONSOLE_BAUDRATE, + &marvell_boot_console); + if (rc == 0) { + /* + * The crash console doesn't use the multi console API, it uses + * the core console functions directly. It is safe to call panic + * and let it print debug information. + */ + panic(); + } + + console_set_scope(&marvell_boot_console, CONSOLE_FLAG_BOOT); +} + +void marvell_console_boot_end(void) +{ + console_flush(); + + (void)console_unregister(&marvell_boot_console); +} + +/* Initialize the runtime console */ +void marvell_console_runtime_init(void) +{ + int rc = + console_marvell_register(PLAT_MARVELL_UART_BASE, + PLAT_MARVELL_UART_CLK_IN_HZ, + MARVELL_CONSOLE_BAUDRATE, + &marvell_runtime_console); + if (rc == 0) + panic(); + + console_set_scope(&marvell_runtime_console, CONSOLE_FLAG_RUNTIME); +} + +void marvell_console_runtime_end(void) +{ + console_flush(); + + (void)console_unregister(&marvell_runtime_console); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c new file mode 100644 index 0000000..7340996 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include + +#include + +#define DRAM_CH0_MMAP_LOW_REG(iface, cs, base) \ + (base + DRAM_CH0_MMAP_LOW_OFFSET + (iface) * 0x10000 + (cs) * 0x8) +#define DRAM_CH0_MMAP_HIGH_REG(iface, cs, base) \ + (DRAM_CH0_MMAP_LOW_REG(iface, cs, base) + 4) +#define DRAM_CS_VALID_ENABLED_MASK 0x1 +#define DRAM_AREA_LENGTH_OFFS 16 +#define DRAM_AREA_LENGTH_MASK (0x1f << DRAM_AREA_LENGTH_OFFS) +#define DRAM_START_ADDRESS_L_OFFS 23 +#define DRAM_START_ADDRESS_L_MASK \ + (0x1ff << DRAM_START_ADDRESS_L_OFFS) +#define DRAM_START_ADDR_HTOL_OFFS 32 + +#define DRAM_MAX_CS_NUM 2 + +#define DRAM_CS_ENABLED(iface, cs, base) \ + (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \ + DRAM_CS_VALID_ENABLED_MASK) +#define GET_DRAM_REGION_SIZE_CODE(iface, cs, base) \ + (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \ + DRAM_AREA_LENGTH_MASK) >> DRAM_AREA_LENGTH_OFFS + +/* Mapping between DDR area length and real DDR size is specific and looks like + * bellow: + * 0 => 384 MB + * 1 => 768 MB + * 2 => 1536 MB + * 3 => 3 GB + * 4 => 6 GB + * + * 7 => 8 MB + * 8 => 16 MB + * 9 => 32 MB + * 10 => 64 MB + * 11 => 128 MB + * 12 => 256 MB + * 13 => 512 MB + * 14 => 1 GB + * 15 => 2 GB + * 16 => 4 GB + * 17 => 8 GB + * 18 => 16 GB + * 19 => 32 GB + * 20 => 64 GB + * 21 => 128 GB + * 22 => 256 GB + * 23 => 512 GB + * 24 => 1 TB + * 25 => 2 TB + * 26 => 4 TB + * + * to calculate real size we need to use two different formulas: + * -- GET_DRAM_REGION_SIZE_ODD for values 0-4 (DRAM_REGION_SIZE_ODD) + * -- GET_DRAM_REGION_SIZE_EVEN for values 7-26 (DRAM_REGION_SIZE_EVEN) + * using mentioned formulas we cover whole mapping between "Area length" value + * and real size (see above mapping). + */ +#define DRAM_REGION_SIZE_EVEN(C) (((C) >= 7) && ((C) <= 26)) +#define GET_DRAM_REGION_SIZE_EVEN(C) ((uint64_t)1 << ((C) + 16)) +#define DRAM_REGION_SIZE_ODD(C) ((C) <= 4) +#define GET_DRAM_REGION_SIZE_ODD(C) ((uint64_t)0x18000000 << (C)) + + +uint64_t mvebu_get_dram_size(uint64_t ap_base_addr) +{ + uint64_t mem_size = 0; + uint8_t region_code; + uint8_t cs, iface; + + for (iface = 0; iface < DRAM_MAX_IFACE; iface++) { + for (cs = 0; cs < DRAM_MAX_CS_NUM; cs++) { + + /* Exit loop on first disabled DRAM CS */ + if (!DRAM_CS_ENABLED(iface, cs, ap_base_addr)) + break; + + /* Decode area length for current CS + * from register value + */ + region_code = + GET_DRAM_REGION_SIZE_CODE(iface, cs, + ap_base_addr); + + if (DRAM_REGION_SIZE_EVEN(region_code)) { + mem_size += + GET_DRAM_REGION_SIZE_EVEN(region_code); + } else if (DRAM_REGION_SIZE_ODD(region_code)) { + mem_size += + GET_DRAM_REGION_SIZE_ODD(region_code); + } else { + WARN("%s: Invalid mem region (0x%x) CS#%d\n", + __func__, region_code, cs); + return 0; + } + } + } + + return mem_size; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c new file mode 100644 index 0000000..2505c9f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* + * The following functions are defined as weak to allow a platform to override + * the way the GICv2 driver is initialised and used. + */ +#pragma weak plat_marvell_gic_driver_init +#pragma weak plat_marvell_gic_init + +#define A7K8K_PIC_CAUSE_REG 0xf03f0100 +#define A7K8K_PIC0_MASK_REG 0xf03f0108 + +#define A7K8K_PIC_PMUOF_IRQ_MASK (1 << 17) + +#define A7K8K_PIC_MAX_IRQS 32 +#define A7K8K_PIC_MAX_IRQ_MASK ((1UL << A7K8K_PIC_MAX_IRQS) - 1) + +#define A7K8K_ODMIN_SET_REG 0xf0300040 +#define A7K8K_ODMI_PMU_IRQ(idx) ((2 + idx) << 12) + +#define A7K8K_ODMI_PMU_GIC_IRQ(idx) (130 + idx) + +static DEFINE_BAKERY_LOCK(a7k8k_irq_lock); + +/* + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + */ +static const interrupt_prop_t marvell_interrupt_props[] = { + PLAT_MARVELL_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_MARVELL_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +/* + * Ideally `marvell_gic_data` structure definition should be a `const` but it is + * kept as modifiable for overwriting with different GICD and GICC base when + * running on FVP with VE memory map. + */ +static gicv2_driver_data_t marvell_gic_data = { + .gicd_base = PLAT_MARVELL_GICD_BASE, + .gicc_base = PLAT_MARVELL_GICC_BASE, + .interrupt_props = marvell_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(marvell_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/* + * ARM common helper to initialize the GICv2 only driver. + */ +void plat_marvell_gic_driver_init(void) +{ + gicv2_driver_init(&marvell_gic_data); +} + +static uint64_t a7k8k_pmu_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + unsigned int idx = plat_my_core_pos(); + uint32_t irq; + + bakery_lock_get(&a7k8k_irq_lock); + + /* Acknowledge IRQ */ + irq = plat_ic_acknowledge_interrupt(); + + plat_ic_end_of_interrupt(irq); + + if (irq != MARVELL_IRQ_PIC0) { + bakery_lock_release(&a7k8k_irq_lock); + return 0; + } + + /* Acknowledge PMU overflow IRQ in PIC0 */ + mmio_setbits_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_PMUOF_IRQ_MASK); + + /* Trigger ODMI Frame IRQ */ + mmio_write_32(A7K8K_ODMIN_SET_REG, A7K8K_ODMI_PMU_IRQ(idx)); + + bakery_lock_release(&a7k8k_irq_lock); + + return 0; +} + +void mvebu_pmu_interrupt_enable(void) +{ + unsigned int idx; + uint32_t flags; + int32_t rc; + + /* Reset PIC */ + mmio_write_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_MAX_IRQ_MASK); + /* Unmask PMU overflow IRQ in PIC0 */ + mmio_clrbits_32(A7K8K_PIC0_MASK_REG, A7K8K_PIC_PMUOF_IRQ_MASK); + + /* Configure ODMI Frame IRQs as edge triggered */ + for (idx = 0; idx < PLATFORM_CORE_COUNT; idx++) + gicv2_interrupt_set_cfg(A7K8K_ODMI_PMU_GIC_IRQ(idx), + GIC_INTR_CFG_EDGE); + + /* + * Register IRQ handler as INTR_TYPE_S_EL1 as its the only valid type + * for GICv2 in ARM-TF. + */ + flags = 0U; + set_interrupt_rm_flag((flags), (NON_SECURE)); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + a7k8k_pmu_interrupt_handler, + flags); + if (rc != 0) + panic(); +} + +void mvebu_pmu_interrupt_disable(void) +{ + /* Reset PIC */ + mmio_write_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_MAX_IRQ_MASK); + /* Mask PMU overflow IRQ in PIC0 */ + mmio_setbits_32(A7K8K_PIC0_MASK_REG, A7K8K_PIC_PMUOF_IRQ_MASK); +} + +void plat_marvell_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + gicv2_cpuif_enable(); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c new file mode 100644 index 0000000..0bd5545 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#include + +#include +#include + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way the GICv3 driver is initialised and used. + ****************************************************************************** + */ +#pragma weak plat_marvell_gic_driver_init +#pragma weak plat_marvell_gic_init +#pragma weak plat_marvell_gic_cpuif_enable +#pragma weak plat_marvell_gic_cpuif_disable +#pragma weak plat_marvell_gic_pcpu_init + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t marvell_interrupt_props[] = { + PLAT_MARVELL_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_MARVELL_G0_IRQ_PROPS(INTR_GROUP0) +}; + +/* + * We save and restore the GICv3 context on system suspend. Allocate the + * data in the designated EL3 Secure carve-out memory + */ +static gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram"); +static gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram"); + +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static unsigned int marvell_gicv3_mpidr_hash(u_register_t mpidr) +{ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return plat_marvell_calc_core_pos(mpidr); +} + +const gicv3_driver_data_t marvell_gic_data = { + .gicd_base = PLAT_MARVELL_GICD_BASE, + .gicr_base = PLAT_MARVELL_GICR_BASE, + .interrupt_props = marvell_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(marvell_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = marvell_gicv3_mpidr_hash +}; + +void plat_marvell_gic_driver_init(void) +{ + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ +#if IMAGE_BL31 + gicv3_driver_init(&marvell_gic_data); +#endif +} + +/****************************************************************************** + * Marvell common helper to initialize the GIC. Only invoked by BL31 + ****************************************************************************** + */ +void plat_marvell_gic_init(void) +{ + /* Initialize GIC-600 Multi Chip feature, + * only if the maximum number of north bridges + * is more than 1 - otherwise no need for multi + * chip feature initialization + */ +#if (PLAT_MARVELL_NORTHB_COUNT > 1) + if (gic600_multi_chip_init()) + ERROR("GIC-600 Multi Chip initialization failed\n"); +#endif + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Marvell common helper to enable the GIC CPU interface + ****************************************************************************** + */ +void plat_marvell_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Marvell common helper to disable the GIC CPU interface + ****************************************************************************** + */ +void plat_marvell_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/****************************************************************************** + * Marvell common helper to init. the per-cpu redistributor interface in GICv3 + ****************************************************************************** + */ +void plat_marvell_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} + +/****************************************************************************** + * Marvell common helper to save SPI irq states in GICv3 + ****************************************************************************** + */ +void plat_marvell_gic_irq_save(void) +{ + + /* + * If an ITS is available, save its context before + * the Redistributor using: + * gicv3_its_save_disable(gits_base, &its_ctx[i]) + * Additionally, an implementation-defined sequence may + * be required to save the whole ITS state. + */ + + /* + * Save the GIC Redistributors and ITS contexts before the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to save the context of the CPU that is issuing + * the SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); + + /* Save the GIC Distributor context */ + gicv3_distif_save(&dist_ctx); + + /* + * From here, all the components of the GIC can be safely powered down + * as long as there is an alternate way to handle wakeup interrupt + * sources. + */ +} + +/****************************************************************************** + * Marvell common helper to restore SPI irq states in GICv3 + ****************************************************************************** + */ +void plat_marvell_gic_irq_restore(void) +{ + /* Restore the GIC Distributor context */ + gicv3_distif_init_restore(&dist_ctx); + + /* + * Restore the GIC Redistributor and ITS contexts after the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to restore the context of the CPU that issued + * the SYSTEM SUSPEND call. + */ + gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); + + /* + * If an ITS is available, restore its context after + * the Redistributor using: + * gicv3_its_restore(gits_base, &its_ctx[i]) + * An implementation-defined sequence may be required to + * restore the whole ITS state. The ITS must also be + * re-enabled after this sequence has been executed. + */ +} + +/****************************************************************************** + * Marvell common helper to save per-cpu PPI irq states in GICv3 + ****************************************************************************** + */ +void plat_marvell_gic_irq_pcpu_save(void) +{ + gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); +} + +/****************************************************************************** + * Marvell common helper to restore per-cpu PPI irq states in GICv3 + ****************************************************************************** + */ +void plat_marvell_gic_irq_pcpu_restore(void) +{ + gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c new file mode 100644 index 0000000..be16b08 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c new file mode 100644 index 0000000..2627ba4 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* IO devices */ +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *memmap_dev_con; +static uintptr_t memmap_dev_handle; + +static const io_block_spec_t fip_block_spec = { + .offset = PLAT_MARVELL_FIP_BASE, + .length = PLAT_MARVELL_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t scp_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +static int open_fip(const uintptr_t spec); +static int open_memmap(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, Marvell platforms load images from the FIP */ +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&scp_bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, +}; + + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak plat_marvell_io_setup +#pragma weak plat_marvell_get_alt_image_source + + +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + + +static int open_memmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Memmap\n"); + io_close(local_image_handle); + } + } + return result; +} + + +void marvell_io_setup(void) +{ + int io_result; + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + assert(io_result == 0); + + io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &memmap_dev_handle); + assert(io_result == 0); + + /* Ignore improbable errors in release builds */ + (void)io_result; +} + +void plat_marvell_io_setup(void) +{ + marvell_io_setup(); +} + +int plat_marvell_get_alt_image_source( + unsigned int image_id __attribute__((unused)), + uintptr_t *dev_handle __attribute__((unused)), + uintptr_t *image_spec __attribute__((unused))) +{ + /* By default do not try an alternative */ + return -ENOENT; +} + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } else { + VERBOSE("Trying alternative IO\n"); + result = plat_marvell_get_alt_image_source(image_id, dev_handle, + image_spec); + } + + return result; +} + +/* + * See if a Firmware Image Package is available, + * by checking if TOC is valid or not. + */ +int marvell_io_is_toc_valid(void) +{ + int result; + + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + + return result == 0; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c new file mode 100644 index 0000000..3c675b2 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include + +#include + +/* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ +extern const plat_psci_ops_t plat_arm_psci_pm_ops; + +/***************************************************************************** + * Private function to program the mailbox for a cpu before it is released + * from reset. This function assumes that the mail box base is within + * the MARVELL_SHARED_RAM region + ***************************************************************************** + */ +void marvell_program_mailbox(uintptr_t address) +{ + uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE; + + /* + * Ensure that the PLAT_MARVELL_MAILBOX_BASE is within + * MARVELL_SHARED_RAM region. + */ + assert((PLAT_MARVELL_MAILBOX_BASE >= MARVELL_SHARED_RAM_BASE) && + ((PLAT_MARVELL_MAILBOX_BASE + sizeof(*mailbox)) <= + (MARVELL_SHARED_RAM_BASE + MARVELL_SHARED_RAM_SIZE))); + + mailbox[MBOX_IDX_MAGIC] = MVEBU_MAILBOX_MAGIC_NUM; + mailbox[MBOX_IDX_SEC_ADDR] = address; + + /* Flush data cache if the mail box shared RAM is cached */ +#if PLAT_MARVELL_SHARED_RAM_CACHED + flush_dcache_range((uintptr_t)PLAT_MARVELL_MAILBOX_BASE + + 8 * MBOX_IDX_MAGIC, + 2 * sizeof(uint64_t)); +#endif +} + +/***************************************************************************** + * The ARM Standard platform definition of platform porting API + * `plat_setup_psci_ops`. + ***************************************************************************** + */ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &plat_arm_psci_pm_ops; + + /* Setup mailbox with entry point. */ + marvell_program_mailbox(sec_entrypoint); + return 0; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c new file mode 100644 index 0000000..a40ff6f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +/* The power domain tree descriptor */ +unsigned char marvell_power_domain_tree_desc[PLAT_MARVELL_CLUSTER_COUNT + 1]; + +/***************************************************************************** + * This function dynamically constructs the topology according to + * PLAT_MARVELL_CLUSTER_COUNT and returns it. + ***************************************************************************** + */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + /* + * The power domain tree does not have a single system level power + * domain i.e. a single root node. The first entry in the power domain + * descriptor specifies the number of power domains at the highest power + * level. + * For Marvell Platform this is the number of cluster power domains. + */ + marvell_power_domain_tree_desc[0] = PLAT_MARVELL_CLUSTER_COUNT; + + for (i = 0; i < PLAT_MARVELL_CLUSTER_COUNT; i++) + marvell_power_domain_tree_desc[i + 1] = + PLAT_MARVELL_CLUSTER_CORE_COUNT; + + return marvell_power_domain_tree_desc; +} + +/***************************************************************************** + * This function validates an MPIDR by checking whether it falls within the + * acceptable bounds. An error code (-1) is returned if an incorrect mpidr + * is passed. + ***************************************************************************** + */ +int marvell_check_mpidr(u_register_t mpidr) +{ + unsigned int nb_id, cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK | + MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT)) + return -1; + + /* Get north bridge ID */ + nb_id = MPIDR_AFFLVL3_VAL(mpidr); + cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (nb_id >= PLAT_MARVELL_CLUSTER_COUNT) + return -1; + + if (cluster_id >= PLAT_MARVELL_CLUSTER_COUNT) + return -1; + + if (cpu_id >= PLAT_MARVELL_CLUSTER_CORE_COUNT) + return -1; + + return 0; +} + +/***************************************************************************** + * This function implements a part of the critical interface between the PSCI + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ***************************************************************************** + */ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + if (marvell_check_mpidr(mpidr) == -1) + return -1; + + return plat_marvell_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c b/arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c new file mode 100644 index 0000000..c4c5c0e --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "comphy/phy-comphy-cp110.h" +#include "secure_dfx_access/dfx.h" +#include "ddr_phy_access.h" +#include + +/* #define DEBUG_COMPHY */ +#ifdef DEBUG_COMPHY +#define debug(format...) NOTICE(format) +#else +#define debug(format, arg...) +#endif + +/* Comphy related FID's */ +#define MV_SIP_COMPHY_POWER_ON 0x82000001 +#define MV_SIP_COMPHY_POWER_OFF 0x82000002 +#define MV_SIP_COMPHY_PLL_LOCK 0x82000003 +#define MV_SIP_COMPHY_XFI_TRAIN 0x82000004 +#define MV_SIP_COMPHY_DIG_RESET 0x82000005 + +/* Miscellaneous FID's' */ +#define MV_SIP_DRAM_SIZE 0x82000010 +#define MV_SIP_LLC_ENABLE 0x82000011 +#define MV_SIP_PMU_IRQ_ENABLE 0x82000012 +#define MV_SIP_PMU_IRQ_DISABLE 0x82000013 +#define MV_SIP_DFX 0x82000014 +#define MV_SIP_DDR_PHY_WRITE 0x82000015 +#define MV_SIP_DDR_PHY_READ 0x82000016 + +/* TRNG */ +#define MV_SIP_RNG_64 0xC200FF11 + +#define MAX_LANE_NR 6 +#define MVEBU_COMPHY_OFFSET 0x441000 +#define MVEBU_CP_BASE_MASK (~0xffffff) + +/* Common PHY register */ +#define COMPHY_TRX_TRAIN_CTRL_REG_0_OFFS 0x120a2c + +/* This macro is used to identify COMPHY related calls from SMC function ID */ +#define is_comphy_fid(fid) \ + ((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_DIG_RESET) + +_Bool is_cp_range_valid(u_register_t *addr) +{ + int cp_nr; + + *addr &= MVEBU_CP_BASE_MASK; + for (cp_nr = 0; cp_nr < CP_NUM; cp_nr++) { + if (*addr == MVEBU_CP_REGS_BASE(cp_nr)) + return true; + } + + return false; +} + +uintptr_t mrvl_sip_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) +{ + u_register_t ret, read, x5 = x1; + int i; + + debug("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx, x3 0x%lx\n", + __func__, smc_fid, x1, x2, x3); + + if (is_comphy_fid(smc_fid)) { + /* validate address passed via x1 */ + if (!is_cp_range_valid(&x1)) { + ERROR("%s: Wrong smc (0x%x) address: %lx\n", + __func__, smc_fid, x1); + SMC_RET1(handle, SMC_UNK); + } + + x5 = x1 + COMPHY_TRX_TRAIN_CTRL_REG_0_OFFS; + x1 += MVEBU_COMPHY_OFFSET; + + if (x2 >= MAX_LANE_NR) { + ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n", + __func__, smc_fid, x2); + SMC_RET1(handle, SMC_UNK); + } + } + + switch (smc_fid) { + + /* Comphy related FID's */ + case MV_SIP_COMPHY_POWER_ON: + /* x1: comphy_base, x2: comphy_index, x3: comphy_mode */ + ret = mvebu_cp110_comphy_power_on(x1, x2, x3, x5); + SMC_RET1(handle, ret); + case MV_SIP_COMPHY_POWER_OFF: + /* x1: comphy_base, x2: comphy_index */ + ret = mvebu_cp110_comphy_power_off(x1, x2, x3); + SMC_RET1(handle, ret); + case MV_SIP_COMPHY_PLL_LOCK: + /* x1: comphy_base, x2: comphy_index */ + ret = mvebu_cp110_comphy_is_pll_locked(x1, x2); + SMC_RET1(handle, ret); + case MV_SIP_COMPHY_XFI_TRAIN: + /* x1: comphy_base, x2: comphy_index */ + ret = mvebu_cp110_comphy_xfi_rx_training(x1, x2); + SMC_RET1(handle, ret); + case MV_SIP_COMPHY_DIG_RESET: + /* x1: comphy_base, x2: comphy_index, x3: mode, x4: command */ + ret = mvebu_cp110_comphy_digital_reset(x1, x2, x3, x4); + SMC_RET1(handle, ret); + + /* Miscellaneous FID's' */ + case MV_SIP_DRAM_SIZE: + ret = mvebu_get_dram_size(MVEBU_REGS_BASE); + SMC_RET1(handle, ret); + case MV_SIP_LLC_ENABLE: + for (i = 0; i < ap_get_count(); i++) + llc_runtime_enable(i); + + SMC_RET1(handle, 0); +#ifdef MVEBU_PMU_IRQ_WA + case MV_SIP_PMU_IRQ_ENABLE: + mvebu_pmu_interrupt_enable(); + SMC_RET1(handle, 0); + case MV_SIP_PMU_IRQ_DISABLE: + mvebu_pmu_interrupt_disable(); + SMC_RET1(handle, 0); +#endif + case MV_SIP_DFX: + if (x1 >= MV_SIP_DFX_THERMAL_INIT && + x1 <= MV_SIP_DFX_THERMAL_SEL_CHANNEL) { + ret = mvebu_dfx_thermal_handle(x1, &read, x2, x3); + SMC_RET2(handle, ret, read); + } + if (x1 >= MV_SIP_DFX_SREAD && x1 <= MV_SIP_DFX_SWRITE) { + ret = mvebu_dfx_misc_handle(x1, &read, x2, x3); + SMC_RET2(handle, ret, read); + } + + SMC_RET1(handle, SMC_UNK); + case MV_SIP_DDR_PHY_WRITE: + ret = mvebu_ddr_phy_write(x1, x2); + SMC_RET1(handle, ret); + case MV_SIP_DDR_PHY_READ: + read = 0; + ret = mvebu_ddr_phy_read(x1, (uint16_t *)&read); + SMC_RET2(handle, ret, read); + case MV_SIP_RNG_64: + if ((x1 % 2 + 1) > sizeof(read)/4) { + ERROR("%s: Maximum %ld random bytes per SMC call\n", + __func__, sizeof(read)); + SMC_RET1(handle, SMC_UNK); + } + ret = eip76_rng_get_random((uint8_t *)&read, 4 * (x1 % 2 + 1)); + SMC_RET2(handle, ret, read); + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + marvell_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + mrvl_sip_smc_handler +); diff --git a/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_common.mk b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_common.mk new file mode 100644 index 0000000..4ab4359 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_common.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + + +PLAT_MARVELL := plat/marvell/armada +MSS_SOURCE := $(PLAT_MARVELL)/common/mss + +BL2_SOURCES += $(MSS_SOURCE)/mss_scp_bootloader.c \ + $(PLAT_MARVELL)/common/plat_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + $(MARVELL_DRV) \ + $(BOARD_DIR)/board/marvell_plat_config.c + +BL31_SOURCES += $(MSS_SOURCE)/mss_ipc_drv.c + +PLAT_INCLUDES += -I$(MSS_SOURCE) diff --git a/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c new file mode 100644 index 0000000..70ccfa5 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include + +#include +#include + +#define IPC_MSG_BASE_MASK MVEBU_REGS_BASE_MASK + +#define IPC_CH_NUM_OF_MSG (16) +#define IPC_CH_MSG_IDX (-1) + +unsigned long mv_pm_ipc_msg_base; +unsigned int mv_pm_ipc_queue_size; + +unsigned int msg_sync; +int msg_index = IPC_CH_MSG_IDX; + +/****************************************************************************** + * mss_pm_ipc_init + * + * DESCRIPTION: Initialize PM IPC infrastructure + ****************************************************************************** + */ +int mv_pm_ipc_init(unsigned long ipc_control_addr) +{ + struct mss_pm_ipc_ctrl *ipc_control = + (struct mss_pm_ipc_ctrl *)ipc_control_addr; + + /* Initialize PM IPC control block */ + mv_pm_ipc_msg_base = ipc_control->msg_base_address | + IPC_MSG_BASE_MASK; + mv_pm_ipc_queue_size = ipc_control->queue_size; + + return 0; +} + +/****************************************************************************** + * mv_pm_ipc_queue_addr_get + * + * DESCRIPTION: Returns the IPC queue address + ****************************************************************************** + */ +unsigned int mv_pm_ipc_queue_addr_get(void) +{ + unsigned int addr; + + inv_dcache_range((uint64_t)&msg_index, sizeof(msg_index)); + msg_index = msg_index + 1; + if (msg_index >= IPC_CH_NUM_OF_MSG) + msg_index = 0; + + addr = (unsigned int)(mv_pm_ipc_msg_base + + (msg_index * mv_pm_ipc_queue_size)); + + flush_dcache_range((uint64_t)&msg_index, sizeof(msg_index)); + + return addr; +} + +/****************************************************************************** + * mv_pm_ipc_msg_rx + * + * DESCRIPTION: Retrieve message from IPC channel + ****************************************************************************** + */ +int mv_pm_ipc_msg_rx(unsigned int channel_id, struct mss_pm_ipc_msg *msg) +{ + unsigned int addr = mv_pm_ipc_queue_addr_get(); + + msg->msg_reply = mmio_read_32(addr + IPC_MSG_REPLY_LOC); + + return 0; +} + +/****************************************************************************** + * mv_pm_ipc_msg_tx + * + * DESCRIPTION: Send message via IPC channel + ****************************************************************************** + */ +int mv_pm_ipc_msg_tx(unsigned int channel_id, unsigned int msg_id, + unsigned int cluster_power_state) +{ + unsigned int addr = mv_pm_ipc_queue_addr_get(); + + /* Validate the entry for message placed by the host is free */ + if (mmio_read_32(addr + IPC_MSG_STATE_LOC) == IPC_MSG_FREE) { + inv_dcache_range((uint64_t)&msg_sync, sizeof(msg_sync)); + msg_sync = msg_sync + 1; + flush_dcache_range((uint64_t)&msg_sync, sizeof(msg_sync)); + + mmio_write_32(addr + IPC_MSG_SYNC_ID_LOC, msg_sync); + mmio_write_32(addr + IPC_MSG_ID_LOC, msg_id); + mmio_write_32(addr + IPC_MSG_CPU_ID_LOC, channel_id); + mmio_write_32(addr + IPC_MSG_POWER_STATE_LOC, + cluster_power_state); + mmio_write_32(addr + IPC_MSG_STATE_LOC, IPC_MSG_OCCUPY); + + } else { + ERROR("%s: FAILED\n", __func__); + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h new file mode 100644 index 0000000..bcb4b2d --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MSS_IPC_DRV_H +#define MSS_IPC_DRV_H + +#include + +#define MV_PM_FW_IPC_VERSION_MAGIC (0xCA530000) /* Do NOT change */ +/* Increament for each version */ +#define MV_PM_FW_IPC_VERSION_SEQ (0x00000001) +#define MV_PM_FW_IPC_VERSION (MV_PM_FW_IPC_VERSION_MAGIC | \ + MV_PM_FW_IPC_VERSION_SEQ) + +#define IPC_MSG_STATE_LOC (0x0) +#define IPC_MSG_SYNC_ID_LOC (0x4) +#define IPC_MSG_ID_LOC (0x8) +#define IPC_MSG_RET_CH_ID_LOC (0xC) +#define IPC_MSG_CPU_ID_LOC (0x10) +#define IPC_MSG_CLUSTER_ID_LOC (0x14) +#define IPC_MSG_SYSTEM_ID_LOC (0x18) +#define IPC_MSG_POWER_STATE_LOC (0x1C) +#define IPC_MSG_REPLY_LOC (0x20) +#define IPC_MSG_RESERVED_LOC (0x24) + +/* IPC initialization state */ +enum mss_pm_ipc_init_state { + IPC_UN_INITIALIZED = 1, + IPC_INITIALIZED = 2 +}; + +/* IPC queue direction */ +enum mss_pm_ipc_init_msg_dir { + IPC_MSG_TX = 0, + IPC_MSG_RX = 1 +}; + +/* IPC message state */ +enum mss_pm_ipc_msg_state { + IPC_MSG_FREE = 1, + IPC_MSG_OCCUPY = 2 + +}; + +/* IPC control block */ +struct mss_pm_ipc_ctrl { + unsigned int ctrl_base_address; + unsigned int msg_base_address; + unsigned int num_of_channels; + unsigned int channel_size; + unsigned int queue_size; +}; + +/* IPC message types */ +enum mss_pm_msg_id { + PM_IPC_MSG_CPU_SUSPEND = 1, + PM_IPC_MSG_CPU_OFF = 2, + PM_IPC_MSG_CPU_ON = 3, + PM_IPC_MSG_SYSTEM_RESET = 4, + PM_IPC_MSG_SYSTEM_SUSPEND = 5, + PM_IPC_MAX_MSG +}; + +struct mss_pm_ipc_msg { + unsigned int msg_sync_id; /* + * Sync number, validate message + * reply corresponding to message + * received + */ + unsigned int msg_id; /* Message Id */ + unsigned int ret_channel_id; /* IPC channel reply */ + unsigned int cpu_id; /* CPU Id */ + unsigned int cluster_id; /* Cluster Id */ + unsigned int system_id; /* System Id */ + unsigned int power_state; + unsigned int msg_reply; /* Message reply */ +}; + +/* IPC queue */ +struct mss_pm_ipc_queue { + unsigned int state; + struct mss_pm_ipc_msg msg; +}; + +/* IPC channel */ +struct mss_pm_ipc_ch { + struct mss_pm_ipc_queue *tx_queue; + struct mss_pm_ipc_queue *rx_queue; +}; + +/***************************************************************************** + * mv_pm_ipc_init + * + * DESCRIPTION: Initialize PM IPC infrastructure + ***************************************************************************** + */ +int mv_pm_ipc_init(unsigned long ipc_control_addr); + +/***************************************************************************** + * mv_pm_ipc_msg_rx + * + * DESCRIPTION: Retrieve message from IPC channel + ***************************************************************************** + */ +int mv_pm_ipc_msg_rx(unsigned int channel_id, struct mss_pm_ipc_msg *msg); + +/***************************************************************************** + * mv_pm_ipc_msg_tx + * + * DESCRIPTION: Send message via IPC channel + ***************************************************************************** + */ +int mv_pm_ipc_msg_tx(unsigned int channel_id, unsigned int msg_id, + unsigned int cluster_power_state); + +#endif /* MSS_IPC_DRV_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h new file mode 100644 index 0000000..5d68ac7 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MSS_MEM_H +#define MSS_MEM_H + +/* MSS SRAM Memory base */ +#define MSS_SRAM_PM_CONTROL_BASE (MVEBU_REGS_BASE + 0x520000) + +enum mss_pm_ctrl_handshake { + MSS_UN_INITIALIZED = 0, + MSS_COMPATIBILITY_ERROR = 1, + MSS_ACKNOWLEDGMENT = 2, + HOST_ACKNOWLEDGMENT = 3 +}; + +enum mss_pm_ctrl_rtos_env { + MSS_MULTI_PROCESS_ENV = 0, + MSS_SINGLE_PROCESS_ENV = 1, + MSS_MAX_PROCESS_ENV +}; + +struct mss_pm_ctrl_block { + /* This field is used to synchronize the Host + * and MSS initialization sequence + * Valid Values + * 0 - Un-Initialized + * 1 - Compatibility Error + * 2 - MSS Acknowledgment + * 3 - Host Acknowledgment + */ + unsigned int handshake; + + /* + * This field include Host IPC version. Once received by the MSS + * It will be compared to MSS IPC version and set MSS Acknowledge to + * "compatibility error" in case there is no match + */ + unsigned int ipc_version; + unsigned int ipc_base_address; + unsigned int ipc_state; + + /* Following fields defines firmware core architecture */ + unsigned int num_of_cores; + unsigned int num_of_clusters; + unsigned int num_of_cores_per_cluster; + + /* Following fields define pm trace debug base address */ + unsigned int pm_trace_ctrl_base_address; + unsigned int pm_trace_info_base_address; + unsigned int pm_trace_info_core_size; + + unsigned int ctrl_blk_size; +}; + +#endif /* MSS_MEM_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h new file mode 100644 index 0000000..90913b0 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MSS_SCP_BL2_FORMAT_H +#define MSS_SCP_BL2_FORMAT_H + +#define MAX_NR_OF_FILES 8 +#define FILE_MAGIC 0xddd01ff +#define HEADER_VERSION 0x1 + +#define MSS_IDRAM_SIZE 0x10000 /* 64KB */ +#define MSS_SRAM_SIZE 0x8000 /* 32KB */ + +/* Types definitions */ +typedef struct file_header { + /* Magic specific for concatenated file (used for validation) */ + uint32_t magic; + uint32_t nr_of_imgs; /* Number of images concatenated */ +} file_header_t; + +/* Types definitions */ +enum cm3_t { + MSS_AP, + MSS_CP0, + MSS_CP1, + MSS_CP2, + MSS_CP3, + MG_CP0, + MG_CP1, + MG_CP2, +}; + +typedef struct img_header { + uint32_t type; /* CM3 type, can be one of cm3_t */ + uint32_t length; /* Image length */ + uint32_t version; /* For sanity checks and future + * extended functionality + */ +} img_header_t; + +#endif /* MSS_SCP_BL2_FORMAT_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c new file mode 100644 index 0000000..fbede1b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define MSS_DMA_TIMEOUT 1000 +#define MSS_EXTERNAL_SPACE 0x50000000 +#define MSS_EXTERNAL_ADDR_MASK 0xfffffff +#define MSS_INTERNAL_SPACE 0x40000000 +#define MSS_INTERNAL_ADDR_MASK 0x00ffffff + +#define DMA_SIZE 128 + +#define MSS_HANDSHAKE_TIMEOUT 50 + +static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl) +{ + int timeout = MSS_HANDSHAKE_TIMEOUT; + + /* Wait for SCP to signal it's ready */ + while ((mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT) && + (timeout-- > 0)) + mdelay(1); + + if (mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT) + return -1; + + mss_pm_crtl->handshake = HOST_ACKNOWLEDGMENT; + + return 0; +} + +static int mss_iram_dma_load(uint32_t src_addr, uint32_t size, + uintptr_t mss_regs) +{ + uint32_t i, loop_num, timeout; + + /* load image to MSS RAM using DMA */ + loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE); + for (i = 0; i < loop_num; i++) { + /* write source address */ + mmio_write_32(MSS_DMA_SRCBR(mss_regs), + src_addr + (i * DMA_SIZE)); + /* write destination address */ + mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE)); + /* make sure DMA data is ready before triggering it */ + dsb(); + /* set the DMA control register */ + mmio_write_32(MSS_DMA_CTRLR(mss_regs), + ((MSS_DMA_CTRLR_REQ_SET << + MSS_DMA_CTRLR_REQ_OFFSET) | + (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET))); + /* Poll DMA_ACK at MSS_DMACTLR until it is ready */ + timeout = MSS_DMA_TIMEOUT; + while (timeout > 0U) { + if (((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >> + MSS_DMA_CTRLR_ACK_OFFSET) & + MSS_DMA_CTRLR_ACK_MASK) + == MSS_DMA_CTRLR_ACK_READY) { + break; + } + udelay(50); + timeout--; + } + if (timeout == 0) { + ERROR("\nMSS DMA failed (timeout)\n"); + return 1; + } + } + return 0; +} + +static int mss_image_load(uint32_t src_addr, uint32_t size, + uintptr_t mss_regs, uintptr_t sram) +{ + uint32_t chunks = 1; /* !sram case */ + uint32_t chunk_num; + int ret; + + /* Check if the img size is not bigger than ID-RAM size of MSS CM3 */ + if (size > MSS_IDRAM_SIZE) { + ERROR("image is too big to fit into MSS CM3 memory\n"); + return 1; + } + + /* The CPx MSS DMA cannot access DRAM directly in secure boot mode + * Copy the MSS FW image to MSS SRAM by the CPU first, then run + * MSS DMA for SRAM to IRAM copy + */ + if (sram != 0) { + chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE); + } + + NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n", + sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs); + for (chunk_num = 0; chunk_num < chunks; chunk_num++) { + size_t chunk_size = size; + uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */ + (src_addr & MSS_EXTERNAL_ADDR_MASK); + + if (sram != 0) { + uintptr_t chunk_source = + src_addr + MSS_SRAM_SIZE * chunk_num; + + if (chunk_num != (size / MSS_SRAM_SIZE)) { + chunk_size = MSS_SRAM_SIZE; + } else { + chunk_size = size % MSS_SRAM_SIZE; + } + + if (chunk_size == 0) { + break; + } + + VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n", + chunk_num, sram, chunk_source, chunk_size); + memcpy((void *)sram, (void *)chunk_source, chunk_size); + dsb(); + img_src = MSS_INTERNAL_SPACE | + (sram & MSS_INTERNAL_ADDR_MASK); + } + + ret = mss_iram_dma_load(img_src, chunk_size, mss_regs); + if (ret != 0) { + ERROR("MSS FW chunk %d load failed\n", chunk_num); + return ret; + } + } + + bl2_plat_configure_mss_windows(mss_regs); + + if (sram != 0) { + /* Wipe the MSS SRAM after using it as copy buffer */ + memset((void *)sram, 0, MSS_SRAM_SIZE); + NOTICE("CP MSS startup is postponed\n"); + /* FW loaded, but CPU startup postponed until final CP setup */ + mmio_write_32(sram, MSS_FW_READY_MAGIC); + dsb(); + } else { + /* Release M3 from reset */ + mmio_write_32(MSS_M3_RSTCR(mss_regs), + (MSS_M3_RSTCR_RST_OFF << + MSS_M3_RSTCR_RST_OFFSET)); + } + + NOTICE("Done\n"); + + return 0; +} + +/* Load image to MSS AP and do PM related initialization + * Note that this routine is different than other CM3 loading routines, because + * firmware for AP is dedicated for PM and therefore some additional PM + * initialization is required + */ +static int mss_ap_load_image(uintptr_t single_img, + uint32_t image_size, uint32_t ap_idx) +{ + volatile struct mss_pm_ctrl_block *mss_pm_crtl; + int ret; + + /* TODO: add PM Control Info from platform */ + mss_pm_crtl = (struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE; + mss_pm_crtl->ipc_version = MV_PM_FW_IPC_VERSION; + mss_pm_crtl->num_of_clusters = PLAT_MARVELL_CLUSTER_COUNT; + mss_pm_crtl->num_of_cores_per_cluster = + PLAT_MARVELL_CLUSTER_CORE_COUNT; + mss_pm_crtl->num_of_cores = PLAT_MARVELL_CLUSTER_COUNT * + PLAT_MARVELL_CLUSTER_CORE_COUNT; + mss_pm_crtl->pm_trace_ctrl_base_address = AP_MSS_ATF_CORE_CTRL_BASE; + mss_pm_crtl->pm_trace_info_base_address = AP_MSS_ATF_CORE_INFO_BASE; + mss_pm_crtl->pm_trace_info_core_size = AP_MSS_ATF_CORE_INFO_SIZE; + VERBOSE("MSS Control Block = 0x%x\n", MSS_SRAM_PM_CONTROL_BASE); + VERBOSE("mss_pm_crtl->ipc_version = 0x%x\n", + mss_pm_crtl->ipc_version); + VERBOSE("mss_pm_crtl->num_of_cores = 0x%x\n", + mss_pm_crtl->num_of_cores); + VERBOSE("mss_pm_crtl->num_of_clusters = 0x%x\n", + mss_pm_crtl->num_of_clusters); + VERBOSE("mss_pm_crtl->num_of_cores_per_cluster = 0x%x\n", + mss_pm_crtl->num_of_cores_per_cluster); + VERBOSE("mss_pm_crtl->pm_trace_ctrl_base_address = 0x%x\n", + mss_pm_crtl->pm_trace_ctrl_base_address); + VERBOSE("mss_pm_crtl->pm_trace_info_base_address = 0x%x\n", + mss_pm_crtl->pm_trace_info_base_address); + VERBOSE("mss_pm_crtl->pm_trace_info_core_size = 0x%x\n", + mss_pm_crtl->pm_trace_info_core_size); + + /* TODO: add checksum to image */ + VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n"); + + ret = mss_image_load(single_img, image_size, + bl2_plat_get_ap_mss_regs(ap_idx), 0); + if (ret != 0) { + ERROR("SCP Image load failed\n"); + return -1; + } + + /* check that the image was loaded successfully */ + ret = mss_check_image_ready(mss_pm_crtl); + if (ret != 0) + NOTICE("SCP Image doesn't contain PM firmware\n"); + + return 0; +} + +/* Load CM3 image (single_img) to CM3 pointed by cm3_type */ +static int load_img_to_cm3(enum cm3_t cm3_type, + uintptr_t single_img, uint32_t image_size) +{ + int ret, ap_idx, cp_index; + uint32_t ap_count = bl2_plat_get_ap_count(); + + switch (cm3_type) { + case MSS_AP: + for (ap_idx = 0; ap_idx < ap_count; ap_idx++) { + NOTICE("Load image to AP%d MSS\n", ap_idx); + ret = mss_ap_load_image(single_img, image_size, ap_idx); + if (ret != 0) + return ret; + } + break; + case MSS_CP0: + case MSS_CP1: + case MSS_CP2: + case MSS_CP3: + /* MSS_AP = 0 + * MSS_CP1 = 1 + * . + * . + * MSS_CP3 = 4 + * Actual CP index is MSS_CPX - 1 + */ + cp_index = cm3_type - 1; + for (ap_idx = 0; ap_idx < ap_count; ap_idx++) { + /* Check if we should load this image + * according to number of CPs + */ + if (bl2_plat_get_cp_count(ap_idx) <= cp_index) { + NOTICE("Skipping MSS CP%d related image\n", + cp_index); + break; + } + + NOTICE("Load image to CP%d MSS AP%d\n", + cp_index, ap_idx); + ret = mss_image_load(single_img, image_size, + bl2_plat_get_cp_mss_regs( + ap_idx, cp_index), + bl2_plat_get_cp_mss_sram( + ap_idx, cp_index)); + if (ret != 0) { + ERROR("SCP Image load failed\n"); + return -1; + } + } + break; + case MG_CP0: + case MG_CP1: + case MG_CP2: + cp_index = cm3_type - MG_CP0; + if (bl2_plat_get_cp_count(0) <= cp_index) { + NOTICE("Skipping MG CP%d related image\n", + cp_index); + break; + } + NOTICE("Load image to CP%d MG\n", cp_index); + ret = mg_image_load(single_img, image_size, cp_index); + if (ret != 0) { + ERROR("SCP Image load failed\n"); + return -1; + } + break; + default: + ERROR("SCP_BL2 wrong img format (cm3_type=%d)\n", cm3_type); + break; + } + + return 0; +} + +/* The Armada 8K has 5 service CPUs and Armada 7K has 3. Therefore it was + * required to provide a method for loading firmware to all of the service CPUs. + * To achieve that, the scp_bl2 image in fact is file containing up to 5 + * concatenated firmwares and this routine splits concatenated image into single + * images dedicated for appropriate service CPU and then load them. + */ +static int split_and_load_bl2_image(void *image) +{ + file_header_t *file_hdr; + img_header_t *img_hdr; + uintptr_t single_img; + int i; + + file_hdr = (file_header_t *)image; + + if (file_hdr->magic != FILE_MAGIC) { + ERROR("SCP_BL2 wrong img format\n"); + return -1; + } + + if (file_hdr->nr_of_imgs > MAX_NR_OF_FILES) { + ERROR("SCP_BL2 concatenated image contains too many images\n"); + return -1; + } + + img_hdr = (img_header_t *)((uintptr_t)image + sizeof(file_header_t)); + single_img = (uintptr_t)image + sizeof(file_header_t) + + sizeof(img_header_t) * file_hdr->nr_of_imgs; + + NOTICE("SCP_BL2 contains %d concatenated images\n", + file_hdr->nr_of_imgs); + for (i = 0; i < file_hdr->nr_of_imgs; i++) { + + /* Before loading make sanity check on header */ + if (img_hdr->version != HEADER_VERSION) { + ERROR("Wrong header, img corrupted exiting\n"); + return -1; + } + + load_img_to_cm3(img_hdr->type, single_img, img_hdr->length); + + /* Prepare offsets for next run */ + single_img += img_hdr->length; + img_hdr++; + } + + return 0; +} + +int scp_bootloader_transfer(void *image, unsigned int image_size) +{ +#ifdef SCP_BL2_BASE + assert((uintptr_t) image == SCP_BL2_BASE); +#endif + + VERBOSE("Concatenated img size %d\n", image_size); + + if (image_size == 0) { + ERROR("SCP_BL2 image size can't be 0 (current size = 0x%x)\n", + image_size); + return -1; + } + + if (split_and_load_bl2_image(image)) + return -1; + + return 0; +} diff --git a/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h new file mode 100644 index 0000000..d65354a --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MSS_SCP_BOOTLOADER_H +#define MSS_SCP_BOOTLOADER_H + +int scp_bootloader_transfer(void *image, unsigned int image_size); +uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx); +uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx); +uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx); +uint32_t bl2_plat_get_cp_count(int ap_idx); +uint32_t bl2_plat_get_ap_count(void); +void bl2_plat_configure_mss_windows(uintptr_t mss_regs); +int bl2_plat_mss_check_image_ready(void); + +#endif /* MSS_SCP_BOOTLOADER_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c b/arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c new file mode 100644 index 0000000..2539752 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include + +#define SYS_COUNTER_FREQ_IN_MHZ (COUNTER_FREQUENCY/1000000) + +static uint32_t plat_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. + */ + return (uint32_t)(~read_cntpct_el0()); +} + +static const timer_ops_t plat_timer_ops = { + .get_timer_value = plat_get_timer_value, + .clk_mult = 1, + .clk_div = SYS_COUNTER_FREQ_IN_MHZ +}; + +void plat_delay_timer_init(void) +{ + timer_init(&plat_timer_ops); +} diff --git a/arm-trusted-firmware/plat/marvell/marvell.mk b/arm-trusted-firmware/plat/marvell/marvell.mk new file mode 100644 index 0000000..b6a2b99 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/marvell.mk @@ -0,0 +1,21 @@ +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +# Marvell images +BOOT_IMAGE := boot-image.bin +BOOT_ENC_IMAGE := boot-image-enc.bin +FLASH_IMAGE := flash-image.bin + +# Make non-trusted image by default +MARVELL_SECURE_BOOT := 0 +$(eval $(call add_define,MARVELL_SECURE_BOOT)) + +# Enable compilation for Palladium emulation platform +PALLADIUM := 0 +$(eval $(call add_define,PALLADIUM)) + +# Set board to work with DDR 32bit +DDR32 := 0 +$(eval $(call add_define,DDR32)) diff --git a/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c new file mode 100644 index 0000000..82ce07b --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include + +#include +#include +#include + +#define MVEBU_CP_MPP_CTRL37_OFFS 20 +#define MVEBU_CP_MPP_CTRL38_OFFS 24 +#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2 +#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2 + +#define MVEBU_MPP_CTRL_MASK 0xf + +/* + * This struct provides the DRAM training code with + * the appropriate board DRAM configuration + */ +struct mv_ddr_iface dram_iface_ap0 = { + .ap_base = MVEBU_REGS_BASE_AP(0), + .state = MV_DDR_IFACE_NRDY, + .validation = MV_DDR_MEMORY_CHECK, + .sscg = SSCG_EN, + .id = 0, + .iface_base_addr = 0, + .tm = { + DEBUG_LEVEL_ERROR, + 0x1, /* active interfaces */ + /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ + { { { {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0}, + {0x1, 0x0, 0, 0} }, + SPEED_BIN_DDR_2400T, /* speed_bin */ + MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ + MV_DDR_DIE_CAP_8GBIT, /* die capacity */ + MV_DDR_FREQ_SAR, /* frequency */ + 0, 0, /* cas_l, cas_wl */ + MV_DDR_TEMP_LOW} }, /* temperature */ +#if DDR32 + MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */ +#else + MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */ +#endif + MV_DDR_CFG_SPD, /* ddr configuration data src */ + NOT_COMBINED, /* ddr twin-die combined*/ + { {0} }, /* raw spd data */ + {0}, /* timing parameters */ + { /* electrical configuration */ + { /* memory electrical configuration */ + MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ + { /* rtt_park 1cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV4, + /* rtt_park 2cs */ + MV_DDR_RTT_NOM_PARK_RZQ_DIV1 + }, + { /* rtt_wr 1cs */ + MV_DDR_RTT_WR_DYN_ODT_OFF, + /* rtt_wr 2cs */ + MV_DDR_RTT_WR_RZQ_DIV2 + }, + MV_DDR_DIC_RZQ_DIV7 /* dic */ + }, + { /* phy electrical configuration */ + MV_DDR_OHM_30, /* data_drv_p */ + MV_DDR_OHM_30, /* data_drv_n */ + MV_DDR_OHM_30, /* ctrl_drv_p */ + MV_DDR_OHM_30, /* ctrl_drv_n */ + { + MV_DDR_OHM_60, /* odt_p 1cs */ + MV_DDR_OHM_120 /* odt_p 2cs */ + }, + { + MV_DDR_OHM_60, /* odt_n 1cs */ + MV_DDR_OHM_120 /* odt_n 2cs */ + }, + }, + { /* mac electrical configuration */ + MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ + MV_DDR_ODT_CFG_ALWAYS_ON,/* odtcfg_write */ + MV_DDR_ODT_CFG_NORMAL /* odtcfg_read */ + }, + }, + }, +}; + +/* Pointer to the first DRAM interface in the system */ +struct mv_ddr_iface *ptr_iface = &dram_iface_ap0; + +struct mv_ddr_iface *mv_ddr_iface_get(void) +{ + /* Return current ddr interface */ + return ptr_iface; +} + +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) +{ + /* Return the board topology as defined in the board code */ + return &ptr_iface->tm; +} + +static void mpp_config(void) +{ + uintptr_t reg; + uint32_t val; + + reg = MVEBU_CP_MPP_REGS(0, 4); + /* configure CP0 MPP 37 and 38 to i2c */ + val = mmio_read_32(reg); + val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS)); + val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA << + MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA << + MVEBU_CP_MPP_CTRL38_OFFS); + mmio_write_32(reg, val); +} + +/* + * This function may modify the default DRAM parameters + * based on information received from SPD or bootloader + * configuration located on non volatile storage + */ +void plat_marvell_dram_update_topology(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + INFO("Gathering DRAM information\n"); + + if (tm->cfg_src == MV_DDR_CFG_SPD) { + /* configure MPPs to enable i2c */ + mpp_config(); + + /* initialize i2c */ + i2c_init((void *)MVEBU_CP0_I2C_BASE); + + /* select SPD memory page 0 to access DRAM configuration */ + i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0); + + /* read data from spd */ + i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes, + sizeof(tm->spd_data.all_bytes)); + } +} diff --git a/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c new file mode 100644 index 0000000..fbacf54 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#ifndef IMAGE_BLE + +/***************************************************************************** + * AMB Configuration + ***************************************************************************** + */ +struct addr_map_win amb_memory_map_cp0[] = { + /* CP0 SPI1 CS0 Direct Mode access */ + {0xe800, 0x2000000, AMB_SPI1_CS0_ID}, +}; + +int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + switch (base) { + case MVEBU_CP_REGS_BASE(0): + *win = amb_memory_map_cp0; + *size = ARRAY_SIZE(amb_memory_map_cp0); + return 0; + case MVEBU_CP_REGS_BASE(1): + case MVEBU_CP_REGS_BASE(2): + default: + *size = 0; + *win = 0; + return 1; + } +} +#endif + +/***************************************************************************** + * IO WIN Configuration + ***************************************************************************** + */ +struct addr_map_win io_win_memory_map[] = { +#if (CP_COUNT > 1) + /* SB (MCi0) internal regs */ + {0x00000000f4000000, 0x2000000, MCI_0_TID}, +#if (CP_COUNT > 2) + /* SB (MCi1) internal regs */ + {0x00000000f6000000, 0x2000000, MCI_1_TID}, +#endif +#endif +#ifndef IMAGE_BLE + /* SB (MCi0) PCIe0-2 on CP1 */ + {0x00000000e2000000, 0x3000000, MCI_0_TID}, + /* SB (MCi1) PCIe0-2 on CP2 */ + {0x00000000e5000000, 0x3000000, MCI_1_TID}, + /* MCI 0 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID}, + /* MCI 1 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID}, +#endif +}; + +/* Global Control Register - window default target */ +uint32_t marvell_get_io_win_gcr_target(int ap_index) +{ + /* + * PIDI == iMCIP AP to SB internal MoChi connection. + * In other words CP0 + */ + return PIDI_TID; +} + +int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = io_win_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(io_win_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * IOB Configuration + ***************************************************************************** + */ +struct addr_map_win iob_memory_map_cp0[] = { + /* SPI1_CS0 (RUNIT) window */ + {0x00000000e8000000, 0x2000000, RUNIT_TID}, + /* PEX2_X1 window */ + {0x00000000e1000000, 0x1000000, PEX2_TID}, + /* PEX1_X1 window */ + {0x00000000e0000000, 0x1000000, PEX1_TID}, + /* PEX0_X4 window */ + {0x00000000c0000000, 0x20000000, PEX0_TID}, +}; + +struct addr_map_win iob_memory_map_cp1[] = { + + /* PEX2_X1 window */ + {0x00000000e4000000, 0x1000000, PEX2_TID}, + /* PEX1_X1 window */ + {0x00000000e3000000, 0x1000000, PEX1_TID}, + /* PEX0_X4 window */ + {0x00000000e2000000, 0x1000000, PEX0_TID}, +}; + +struct addr_map_win iob_memory_map_cp2[] = { + + /* PEX2_X1 window */ + {0x00000000e7000000, 0x1000000, PEX2_TID}, + /* PEX1_X1 window */ + {0x00000000e6000000, 0x1000000, PEX1_TID}, + /* PEX0_X4 window */ + {0x00000000e5000000, 0x1000000, PEX0_TID}, +}; + +int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + switch (base) { + case MVEBU_CP_REGS_BASE(0): + *win = iob_memory_map_cp0; + *size = ARRAY_SIZE(iob_memory_map_cp0); + return 0; + case MVEBU_CP_REGS_BASE(1): + *win = iob_memory_map_cp1; + *size = ARRAY_SIZE(iob_memory_map_cp1); + return 0; + case MVEBU_CP_REGS_BASE(2): + *win = iob_memory_map_cp2; + *size = ARRAY_SIZE(iob_memory_map_cp2); + return 0; + default: + *size = 0; + *win = 0; + return 1; + } +} +#endif + +/***************************************************************************** + * CCU Configuration + ***************************************************************************** + */ +struct addr_map_win ccu_memory_map[] = { /* IO window */ +#ifdef IMAGE_BLE + {0x00000000f2000000, 0x6000000, IO_0_TID}, /* IO window */ +#else +#if LLC_SRAM + {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID}, +#endif + {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */ + {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */ + {0x0000002000000000, 0x70e000000, IO_0_TID}, /* IO for CV-OS */ +#endif +}; + +uint32_t marvell_get_ccu_gcr_target(int ap) +{ + return DRAM_0_TID; +} + +int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = ccu_memory_map; + *size = ARRAY_SIZE(ccu_memory_map); + + return 0; +} + +#ifdef IMAGE_BLE +/***************************************************************************** + * SKIP IMAGE Configuration + ***************************************************************************** + */ +void *plat_get_skip_image_data(void) +{ + /* No recovery button on CN-9130 board? */ + return NULL; +} +#endif diff --git a/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h new file mode 100644 index 0000000..6b55407 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef __PHY_PORTING_LAYER_H +#define __PHY_PORTING_LAYER_H + + +#define MAX_LANE_NR 6 +#define XFI_PARAMS static const struct xfi_params + + +XFI_PARAMS xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + /* AP0 */ + { + /* CP 0 */ + { + { 0 }, /* Comphy0 not relevant*/ + { 0 }, /* Comphy1 not relevant*/ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, + .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, + .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, + .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 1 }, /* Comphy2 */ + { 0 }, /* Comphy3 not relevant*/ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, + .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, + .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, + .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 1 }, /* Comphy4 */ + { 0 }, /* Comphy5 not relevant*/ + }, +#if CP_NUM > 1 + /* CP 1 */ + { + { 0 }, /* Comphy0 not relevant*/ + { 0 }, /* Comphy1 not relevant*/ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, + .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, + .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, + .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 1 }, /* Comphy2 */ + { 0 }, /* Comphy3 not relevant*/ + /* different from defaults */ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0xc, + .g1_emph = 0x5, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, + .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, + .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 1}, /* Comphy4 */ + { 0 }, /* Comphy5 not relevant*/ + }, +#if CP_NUM > 2 + /* CP 2 */ + { + { 0 }, /* Comphy0 not relevant*/ + { 0 }, /* Comphy1 not relevant*/ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, + .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, + .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, + .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 1 }, /* Comphy2 */ + { 0 }, /* Comphy3 not relevant*/ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, + .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, + .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, + .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 1 }, /* Comphy4 */ + { 0 }, /* Comphy5 not relevant*/ + }, +#endif +#endif + }, +}; + +#define SATA_PARAMS static const struct sata_params +SATA_PARAMS sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = { + .g1_amp = 0x8, .g2_amp = 0xa, + .g3_amp = 0x1e, + .g1_emph = 0x1, .g2_emph = 0x2, + .g3_emph = 0xe, + .g1_emph_en = 0x1, .g2_emph_en = 0x1, + .g3_emph_en = 0x1, + .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, + .g3_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, + .g3_tx_emph_en = 0x0, + .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, + .g3_tx_emph = 0x1, + .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, + .g3_ffe_cap_sel = 0xf, + .align90 = 0x61, + .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, + .g3_rx_selmuff = 0x3, + .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, + .g3_rx_selmufi = 0x3, + .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, + .g3_rx_selmupf = 0x2, + .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, + .g3_rx_selmupi = 0x2, + .polarity_invert = COMPHY_POLARITY_NO_INVERT, + .valid = 0x1 + }, +}; + +static const struct usb_params + usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = { + .polarity_invert = COMPHY_POLARITY_NO_INVERT + }, +}; +#endif /* __PHY_PORTING_LAYER_H */ diff --git a/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h new file mode 100644 index 0000000..490be73 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef __MVEBU_DEF_H__ +#define __MVEBU_DEF_H__ + +#include + +/* + * CN-9130 has single CP0 inside the package and 2 additional one + * from MoChi interface. In case of db-9130-modular board the MCI interface + * is routed to: + * - on-board CP115 (MCI0) + * - extension board CP115 (MCI1) + */ +#define CP_COUNT CP_NUM +#define MVEBU_SOC_AP807 1 +#define I2C_SPD_ADDR 0x53 /* Access SPD data */ +#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */ + +#endif /* __MVEBU_DEF_H__ */ diff --git a/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/platform.mk b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/platform.mk new file mode 100644 index 0000000..1e2716d --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/platform.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PCI_EP_SUPPORT := 0 + +CP_NUM := 1 +$(eval $(call add_define,CP_NUM)) + +DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg + +MARVELL_MOCHI_DRV := drivers/marvell/mochi/ap807_setup.c + +BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST))) +include plat/marvell/armada/a8k/common/a8k_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c new file mode 100644 index 0000000..5bae8eb --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * Copyright (C) 2021 Semihalf. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#ifndef IMAGE_BLE + +/***************************************************************************** + * AMB Configuration + ***************************************************************************** + */ +struct addr_map_win amb_memory_map_cp0[] = { + /* CP0 SPI1 CS0 Direct Mode access */ + {0xef00, 0x1000000, AMB_SPI1_CS0_ID}, +}; + +struct addr_map_win amb_memory_map_cp1[] = { + /* CP1 SPI1 CS0 Direct Mode access */ + {0xe800, 0x1000000, AMB_SPI1_CS0_ID}, +}; + +int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + switch (base) { + case MVEBU_CP_REGS_BASE(0): + *win = amb_memory_map_cp0; + *size = ARRAY_SIZE(amb_memory_map_cp0); + return 0; + case MVEBU_CP_REGS_BASE(1): + *win = amb_memory_map_cp1; + *size = ARRAY_SIZE(amb_memory_map_cp1); + return 0; + case MVEBU_CP_REGS_BASE(2): + default: + *size = 0; + *win = 0; + return 1; + } +} +#endif + +/***************************************************************************** + * IO WIN Configuration + ***************************************************************************** + */ +struct addr_map_win io_win_memory_map[] = { +#if (CP_COUNT > 1) + /* SB (MCi0) internal regs */ + {0x00000000f4000000, 0x2000000, MCI_0_TID}, + /* SB (MCi0) PCIe0-2 on CP1 */ + {0x00000000e2000000, 0x7000000, MCI_0_TID}, + /* + * Due to lack of sufficient number of IO windows registers, + * below CP1 PCIE configuration must be performed in the + * later firmware stages. It should replace the MCI 0 indirect + * window, which becomes no longer needed. + */ + /* {0x0000000890000000, 0x30000000, MCI_0_TID}, */ +#if (CP_COUNT > 2) + /* SB (MCi1) internal regs */ + {0x00000000f6000000, 0x2000000, MCI_1_TID}, + /* SB (MCi1) PCIe0-2 on CP2 */ + {0x00000000e9000000, 0x6000000, MCI_1_TID}, + /* + * Due to lack of sufficient number of IO windows registers, + * below CP2 PCIE configuration must be performed in the + * later firmware stages. It should replace the MCI 1 indirect + * window, which becomes no longer needed. + */ + /* {0x00000008c0000000, 0x30000000, MCI_1_TID}, */ +#endif +#endif +#ifndef IMAGE_BLE + /* MCI 0 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID}, + /* MCI 1 indirect window */ + {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID}, +#endif +}; + +/* Global Control Register - window default target */ +uint32_t marvell_get_io_win_gcr_target(int ap_index) +{ + /* + * PIDI == iMCIP AP to SB internal MoChi connection. + * In other words CP0 + */ + return PIDI_TID; +} + +int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = io_win_memory_map; + if (*win == NULL) + *size = 0; + else + *size = ARRAY_SIZE(io_win_memory_map); + + return 0; +} + +#ifndef IMAGE_BLE +/***************************************************************************** + * IOB Configuration + ***************************************************************************** + */ +struct addr_map_win iob_memory_map_cp0[] = { + /* SPI1_CS0 (RUNIT) window */ + {0x00000000ef000000, 0x1000000, RUNIT_TID}, + /* PEX2_X1 window */ + {0x00000000e1000000, 0x1000000, PEX2_TID}, + /* PEX1_X1 window */ + {0x00000000e0000000, 0x1000000, PEX1_TID}, + /* PEX0_X4 window */ + {0x00000000c0000000, 0x20000000, PEX0_TID}, + {0x0000000800000000, 0x90000000, PEX0_TID}, +}; + +struct addr_map_win iob_memory_map_cp1[] = { + /* SPI1_CS0 (RUNIT) window */ + {0x00000000e8000000, 0x1000000, RUNIT_TID}, + /* PEX2_X1 window */ + {0x00000000e6000000, 0x2000000, PEX2_TID}, + {0x00000008b0000000, 0x10000000, PEX2_TID}, + /* PEX1_X1 window */ + {0x00000000e4000000, 0x2000000, PEX1_TID}, + {0x00000008a0000000, 0x10000000, PEX1_TID}, + /* PEX0_X2 window */ + {0x00000000e2000000, 0x2000000, PEX0_TID}, + {0x0000000890000000, 0x10000000, PEX0_TID}, +}; + +struct addr_map_win iob_memory_map_cp2[] = { + + /* PEX2_X1 window */ + {0x00000000ed000000, 0x2000000, PEX2_TID}, + {0x00000008e0000000, 0x10000000, PEX2_TID}, + /* PEX1_X1 window */ + {0x00000000eb000000, 0x2000000, PEX1_TID}, + {0x00000008d0000000, 0x10000000, PEX1_TID}, + /* PEX0_X1 window */ + {0x00000000e9000000, 0x2000000, PEX0_TID}, + {0x00000008c0000000, 0x10000000, PEX0_TID}, +}; + +int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size, + uintptr_t base) +{ + switch (base) { + case MVEBU_CP_REGS_BASE(0): + *win = iob_memory_map_cp0; + *size = ARRAY_SIZE(iob_memory_map_cp0); + return 0; + case MVEBU_CP_REGS_BASE(1): + *win = iob_memory_map_cp1; + *size = ARRAY_SIZE(iob_memory_map_cp1); + return 0; + case MVEBU_CP_REGS_BASE(2): + *win = iob_memory_map_cp2; + *size = ARRAY_SIZE(iob_memory_map_cp2); + return 0; + default: + *size = 0; + *win = 0; + return 1; + } +} +#endif + +/***************************************************************************** + * CCU Configuration + ***************************************************************************** + */ +struct addr_map_win ccu_memory_map[] = { /* IO window */ +#ifdef IMAGE_BLE + {0x00000000f2000000, 0x6000000, IO_0_TID}, /* IO window */ +#else +#if LLC_SRAM + {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID}, +#endif + {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */ + {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */ + {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */ + {0x0000002000000000, 0x70e000000, IO_0_TID}, /* IO for CV-OS */ +#endif +}; + +uint32_t marvell_get_ccu_gcr_target(int ap) +{ + return DRAM_0_TID; +} + +int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win, + uint32_t *size) +{ + *win = ccu_memory_map; + *size = ARRAY_SIZE(ccu_memory_map); + + return 0; +} + +#ifdef IMAGE_BLE +/***************************************************************************** + * SKIP IMAGE Configuration + ***************************************************************************** + */ +void *plat_get_skip_image_data(void) +{ + /* No recovery button on CN-9130 board? */ + return NULL; +} +#endif diff --git a/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk new file mode 100644 index 0000000..ee55455 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk @@ -0,0 +1,33 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# Copyright (C) 2021 Semihalf. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# + +PCI_EP_SUPPORT := 0 + +CP_NUM := 1 +$(eval $(call add_define,CP_NUM)) + +DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg + +MARVELL_MOCHI_DRV := drivers/marvell/mochi/ap807_setup.c + +BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST))) + +# +# CN913X CEx7 Evaluation Board shares the DRAM connectivity +# and SerDes settings with the CN913X DB - reuse relevant +# board-specific files. +# +T9130_DIR := $(BOARD_DIR)/../t9130 +PLAT_INCLUDES := -I$(T9130_DIR) \ + -I$(T9130_DIR)/board +BLE_PORTING_SOURCES := $(T9130_DIR)/board/dram_port.c \ + $(BOARD_DIR)/board/marvell_plat_config.c + +include plat/marvell/armada/a8k/common/a8k_common.mk + +include plat/marvell/armada/common/marvell_common.mk diff --git a/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c b/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c new file mode 100644 index 0000000..27ee6aa --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* OEM Service UUID */ +DEFINE_SVC_UUID2(oem_svc_uid, + 0xd0ad43b9, 0x9b06, 0xe411, 0x91, 0x91, + 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66); + +/* Setup OEM Services */ +static int32_t oem_svc_setup(void) +{ + /* + * Invoke related module setup from here + */ + + return 0; +} + +/******************************************************************************* + * OEM top level handler for servicing SMCs. + ******************************************************************************/ +uintptr_t oem_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) +{ + WARN("Unimplemented OEM Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +/* + * Top-level OEM Service SMC handler. This handler will in turn dispatch + * calls to related SMC handler + */ +uintptr_t oem_svc_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) +{ + /* + * Dispatch OEM calls to OEM Common handler and return its return value + */ + if (is_oem_fid(smc_fid)) { + return oem_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + + switch (smc_fid) { + case OEM_SVC_CALL_COUNT: + /* + * Return the number of OEM Service Calls. + */ + SMC_RET1(handle, OEM_SVC_NUM_CALLS); + + case OEM_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, oem_svc_uid); + + case OEM_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, OEM_VERSION_MAJOR, OEM_VERSION_MINOR); + + default: + WARN("Unimplemented OEM Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register OEM Service Calls as runtime service */ +DECLARE_RT_SVC( + oem_svc, + OEN_OEM_START, + OEN_OEM_END, + SMC_TYPE_FAST, + oem_svc_setup, + oem_svc_smc_handler +); diff --git a/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h b/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h new file mode 100644 index 0000000..76f7c24 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OEM_SVC_H +#define OEM_SVC_H + +/******************************************************************************* + * Defines for runtime services func ids + ******************************************************************************/ +/* + * Number of OEM calls (above) implemented. + */ +#define OEM_SVC_NUM_CALLS 3 + +/******************************************************************************* + * Defines for OEM Service queries + ******************************************************************************/ +/* 0x83000000 - 0x8300FEFF is OEM service calls */ +#define OEM_SVC_CALL_COUNT 0x8300ff00 +#define OEM_SVC_UID 0x8300ff01 +/* 0x8300ff02 is reserved */ +#define OEM_SVC_VERSION 0x8300ff03 +/* 0x8300ff04 - 0x8300FFFF is reserved for future expansion */ + +/* OEM Service Calls version numbers */ +#define OEM_VERSION_MAJOR 0x0 +#define OEM_VERSION_MINOR 0x1 + +/* The macros below are used to identify OEM calls from the SMC function ID */ +/* SMC32 ID range from 0x83000000 to 0x83000FFF */ +/* SMC64 ID range from 0xC3000000 to 0xC3000FFF */ +#define OEM_FID_MASK 0xf000u +#define OEM_FID_VALUE 0u +#define is_oem_fid(_fid) \ + (((_fid) & OEM_FID_MASK) == OEM_FID_VALUE) + +#define OEM_SVC_E_SUCCESS 0 +#define OEM_SVC_E_NOT_SUPPORTED -1 +#define OEM_SVC_E_INVALID_PARAMS -2 + +#endif /* OEM_SVC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c b/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c new file mode 100644 index 0000000..ae8d697 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "../drivers/arm/gic/v3/gicv3_private.h" +#include +#include +#include + +#include +#include +#include +#include +#include + +#define SGI_MASK 0xffff + +uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; +static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT]; + +/* we save and restore the GICv3 context on system suspend */ +gicv3_dist_ctx_t dist_ctx; + +static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr) +{ + return plat_core_pos_by_mpidr(mpidr); +} + +gicv3_driver_data_t mt_gicv3_data = { + .gicd_base = MT_GIC_BASE, + .gicr_base = MT_GIC_RDIST_BASE, + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = mt_mpidr_to_core_pos, +}; + +struct gic_chip_data { + /* All cores share the same configuration */ + unsigned int saved_group; + unsigned int saved_enable; + unsigned int saved_conf0; + unsigned int saved_conf1; + unsigned int saved_grpmod; + /* Per-core sgi */ + unsigned int saved_sgi[PLATFORM_CORE_COUNT]; +}; + +static struct gic_chip_data gic_data; + +void mt_gic_driver_init(void) +{ + gicv3_driver_init(&mt_gicv3_data); +} + +void mt_gic_set_pending(uint32_t irq) +{ + gicv3_set_interrupt_pending(irq, plat_my_core_pos()); +} + +void mt_gic_distif_save(void) +{ + gicv3_distif_save(&dist_ctx); +} + +void mt_gic_distif_restore(void) +{ + gicv3_distif_init_restore(&dist_ctx); +} + +void mt_gic_rdistif_init(void) +{ + unsigned int proc_num; + unsigned int index; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + /* set all SGI/PPI as non-secure GROUP1 by default */ + mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U); + mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0); + + /* setup the default PPI/SGI priorities */ + for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U) + gicr_write_ipriorityr(gicr_base, index, + GICD_IPRIORITYR_DEF_VAL); +} + +void mt_gic_rdistif_save(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0); + gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0); + gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0); + gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1); + gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0); + + rdist_has_saved[proc_num] = 1; +} + +void mt_gic_rdistif_restore(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + if (rdist_has_saved[proc_num] == 1) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); + mmio_write_32(gicr_base + GICR_ISENABLER0, + gic_data.saved_enable); + mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); + mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); + mmio_write_32(gicr_base + GICR_IGRPMODR0, + gic_data.saved_grpmod); + } +} + +void mt_gic_rdistif_restore_all(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); + mmio_write_32(gicr_base + GICR_ISENABLER0, + gic_data.saved_enable); + mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); + mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); + mmio_write_32(gicr_base + GICR_IGRPMODR0, + gic_data.saved_grpmod); + } +} + +void gic_sgi_save_all(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + gic_data.saved_sgi[proc_num] = + mmio_read_32(gicr_base + GICR_ISPENDR0) & SGI_MASK; + } +} + +void gic_sgi_restore_all(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + mmio_write_32(gicr_base + GICR_ICPENDR0, SGI_MASK); + mmio_write_32(gicr_base + GICR_ISPENDR0, + gic_data.saved_sgi[proc_num] & SGI_MASK); + } +} + +void mt_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +uint32_t mt_irq_get_pending(uint32_t irq) +{ + uint32_t val; + + val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR + + irq / 32 * 4); + val = (val >> (irq % 32)) & 1U; + return val; +} + + +void mt_irq_set_pending(uint32_t irq) +{ + uint32_t bit = 1U << (irq % 32); + + mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR + + irq / 32 * 4, bit); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h b/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h new file mode 100644 index 0000000..c4ab44f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GIC_V3_H +#define MT_GIC_V3_H + +#include +#include + +void mt_gic_driver_init(void); +void mt_gic_init(void); +void mt_gic_set_pending(uint32_t irq); +void mt_gic_distif_save(void); +void mt_gic_distif_restore(void); +void mt_gic_rdistif_init(void); +void mt_gic_rdistif_save(void); +void mt_gic_rdistif_restore(void); +void mt_gic_rdistif_restore_all(void); +void gic_sgi_save_all(void); +void gic_sgi_restore_all(void); +uint32_t mt_irq_get_pending(uint32_t irq); +void mt_irq_set_pending(uint32_t irq); + +#endif /* MT_GIC_V3_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c b/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c new file mode 100644 index 0000000..89977a5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + *Macro Definition + ******************************************************************************/ +#define GPIO_MODE_BITS 4 +#define MAX_GPIO_MODE_PER_REG 8 +#define MAX_GPIO_REG_BITS 32 +#define DIR_BASE (GPIO_BASE + 0x000) +#define DOUT_BASE (GPIO_BASE + 0x100) +#define DIN_BASE (GPIO_BASE + 0x200) +#define MODE_BASE (GPIO_BASE + 0x300) +#define SET 0x4 +#define CLR 0x8 + +static void mt_set_gpio_dir_chip(uint32_t pin, int dir) +{ + uint32_t pos, bit; + + assert(pin < MAX_GPIO_PIN); + assert(dir < MT_GPIO_DIR_MAX); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + if (dir == MT_GPIO_DIR_IN) { + mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit); + } else { + mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit); + } +} + +static int mt_get_gpio_dir_chip(uint32_t pin) +{ + uint32_t pos, bit; + uint32_t reg; + + assert(pin < MAX_GPIO_PIN); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + reg = mmio_read_32(DIR_BASE + 0x10U * pos); + return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN); +} + +static void mt_set_gpio_out_chip(uint32_t pin, int output) +{ + uint32_t pos, bit; + + assert(pin < MAX_GPIO_PIN); + assert(output < MT_GPIO_OUT_MAX); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + if (output == MT_GPIO_OUT_ZERO) { + mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit); + } else { + mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit); + } +} + +static int mt_get_gpio_in_chip(uint32_t pin) +{ + uint32_t pos, bit; + uint32_t reg; + + assert(pin < MAX_GPIO_PIN); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + reg = mmio_read_32(DIN_BASE + 0x10U * pos); + return (((reg & (1U << bit)) != 0U) ? 1 : 0); +} + +static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable, + int select) +{ + uintptr_t reg1; + uintptr_t reg2; + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + uint32_t bit = gpio_info.bit; + + reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; + reg2 = reg1 + (gpio_info.base & 0xf0); + if (enable == MT_GPIO_PULL_ENABLE) { + mmio_write_32(reg2 + SET, (1U << bit)); + if (select == MT_GPIO_PULL_DOWN) { + mmio_write_32(reg1 + SET, (1U << bit)); + } else { + mmio_write_32(reg1 + CLR, (1U << bit)); + } + } else { + mmio_write_32(reg2 + CLR, (1U << bit)); + mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit)); + } +} + +static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable, + int select) +{ + uintptr_t reg1; + uintptr_t reg2; + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + uint32_t bit = gpio_info.bit; + + reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; + reg2 = reg1 - (gpio_info.base & 0xf0); + + if (enable == MT_GPIO_PULL_ENABLE) { + if (select == MT_GPIO_PULL_DOWN) { + mmio_write_32(reg1 + CLR, (1U << bit)); + mmio_write_32(reg2 + SET, (1U << bit)); + } else { + mmio_write_32(reg2 + CLR, (1U << bit)); + mmio_write_32(reg1 + SET, (1U << bit)); + } + } else { + mmio_write_32(reg1 + CLR, (1U << bit)); + mmio_write_32(reg2 + CLR, (1U << bit)); + } +} + +static void mt_gpio_set_pull_chip(uint32_t pin, int enable, + int select) +{ + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + if (gpio_info.flag) { + mt_gpio_set_spec_pull_pupd(pin, enable, select); + } else { + mt_gpio_set_pull_pu_pd(pin, enable, select); + } +} + +static int mt_gpio_get_spec_pull_pupd(uint32_t pin) +{ + uintptr_t reg1; + uintptr_t reg2; + uint32_t r0; + uint32_t r1; + + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + uint32_t bit = gpio_info.bit; + + reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; + reg2 = reg1 + (gpio_info.base & 0xf0); + + r0 = (mmio_read_32(reg2) >> bit) & 1U; + r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U; + if (r0 == 0U && r1 == 0U) { + return MT_GPIO_PULL_NONE; + } else { + if (mmio_read_32(reg1) & (1U << bit)) { + return MT_GPIO_PULL_DOWN; + } else { + return MT_GPIO_PULL_UP; + } + } +} + +static int mt_gpio_get_pull_pu_pd(uint32_t pin) +{ + uintptr_t reg1; + uintptr_t reg2; + uint32_t pu; + uint32_t pd; + + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + uint32_t bit = gpio_info.bit; + + reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; + reg2 = reg1 - (gpio_info.base & 0xf0); + pu = (mmio_read_32(reg1) >> bit) & 1U; + pd = (mmio_read_32(reg2) >> bit) & 1U; + if (pu == 1U) { + return MT_GPIO_PULL_UP; + } else if (pd == 1U) { + return MT_GPIO_PULL_DOWN; + } else { + return MT_GPIO_PULL_NONE; + } +} + +static int mt_gpio_get_pull_chip(uint32_t pin) +{ + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + if (gpio_info.flag) { + return mt_gpio_get_spec_pull_pupd(pin); + } else { + return mt_gpio_get_pull_pu_pd(pin); + } +} + +static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel) +{ + assert(pin < MAX_GPIO_PIN); + + if (sel == MT_GPIO_PULL_NONE) { + mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN); + } else if (sel == MT_GPIO_PULL_UP) { + mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP); + } else if (sel == MT_GPIO_PULL_DOWN) { + mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN); + } +} + +/* get pull-up or pull-down, regardless of resistor value */ +static int mt_get_gpio_pull_select_chip(uint32_t pin) +{ + assert(pin < MAX_GPIO_PIN); + + return mt_gpio_get_pull_chip(pin); +} + +static void mt_set_gpio_dir(int gpio, int direction) +{ + mt_set_gpio_dir_chip((uint32_t)gpio, direction); +} + +static int mt_get_gpio_dir(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_dir_chip(pin); +} + +static void mt_set_gpio_pull(int gpio, int pull) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + mt_set_gpio_pull_select_chip(pin, pull); +} + +static int mt_get_gpio_pull(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_pull_select_chip(pin); +} + +static void mt_set_gpio_out(int gpio, int value) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + mt_set_gpio_out_chip(pin, value); +} + +static int mt_get_gpio_in(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_in_chip(pin); +} + +const gpio_ops_t mtgpio_ops = { + .get_direction = mt_get_gpio_dir, + .set_direction = mt_set_gpio_dir, + .get_value = mt_get_gpio_in, + .set_value = mt_set_gpio_out, + .set_pull = mt_set_gpio_pull, + .get_pull = mt_get_gpio_pull, +}; + +void mt_gpio_init(void) +{ + gpio_init(&mtgpio_ops); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h b/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h new file mode 100644 index 0000000..bf51055 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_COMMON_H +#define MT_GPIO_COMMON_H + +#include +#include + +#include + +/* Error Code No. */ +#define RSUCCESS 0 +#define ERACCESS 1 +#define ERINVAL 2 +#define ERWRAPPER 3 +#define MAX_GPIO_PIN MT_GPIO_BASE_MAX + +/* GPIO MODE CONTROL VALUE*/ +typedef enum { + GPIO_MODE_UNSUPPORTED = -1, + GPIO_MODE_GPIO = 0, + GPIO_MODE_00 = 0, + GPIO_MODE_01, + GPIO_MODE_02, + GPIO_MODE_03, + GPIO_MODE_04, + GPIO_MODE_05, + GPIO_MODE_06, + GPIO_MODE_07, + + GPIO_MODE_MAX, + GPIO_MODE_DEFAULT = GPIO_MODE_00, +} GPIO_MODE; + +/* GPIO DIRECTION */ +typedef enum { + MT_GPIO_DIR_UNSUPPORTED = -1, + MT_GPIO_DIR_OUT = 0, + MT_GPIO_DIR_IN = 1, + MT_GPIO_DIR_MAX, + MT_GPIO_DIR_DEFAULT = MT_GPIO_DIR_IN, +} GPIO_DIR; + +/* GPIO PULL ENABLE*/ +typedef enum { + MT_GPIO_PULL_EN_UNSUPPORTED = -1, + MT_GPIO_PULL_DISABLE = 0, + MT_GPIO_PULL_ENABLE = 1, + MT_GPIO_PULL_ENABLE_R0 = 2, + MT_GPIO_PULL_ENABLE_R1 = 3, + MT_GPIO_PULL_ENABLE_R0R1 = 4, + + MT_GPIO_PULL_EN_MAX, + MT_GPIO_PULL_EN_DEFAULT = MT_GPIO_PULL_ENABLE, +} GPIO_PULL_EN; + +/* GPIO PULL-UP/PULL-DOWN*/ +typedef enum { + MT_GPIO_PULL_UNSUPPORTED = -1, + MT_GPIO_PULL_NONE = 0, + MT_GPIO_PULL_UP = 1, + MT_GPIO_PULL_DOWN = 2, + MT_GPIO_PULL_MAX, + MT_GPIO_PULL_DEFAULT = MT_GPIO_PULL_DOWN +} GPIO_PULL; + +/* GPIO OUTPUT */ +typedef enum { + MT_GPIO_OUT_UNSUPPORTED = -1, + MT_GPIO_OUT_ZERO = 0, + MT_GPIO_OUT_ONE = 1, + + MT_GPIO_OUT_MAX, + MT_GPIO_OUT_DEFAULT = MT_GPIO_OUT_ZERO, + MT_GPIO_DATA_OUT_DEFAULT = MT_GPIO_OUT_ZERO, /*compatible with DCT*/ +} GPIO_OUT; + +/* GPIO INPUT */ +typedef enum { + MT_GPIO_IN_UNSUPPORTED = -1, + MT_GPIO_IN_ZERO = 0, + MT_GPIO_IN_ONE = 1, + + MT_GPIO_IN_MAX, +} GPIO_IN; + +#define PIN(_id, _flag, _bit, _base, _offset) { \ + .id = _id, \ + .flag = _flag, \ + .bit = _bit, \ + .base = _base, \ + .offset = _offset, \ + } + +struct mt_pin_info { + uint8_t id; + uint8_t flag; + uint8_t bit; + uint16_t base; + uint16_t offset; +}; + +void mt_gpio_init(void); +uintptr_t mt_gpio_find_reg_addr(uint32_t pin); +#endif /* MT_GPIO_COMMON_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c b/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c new file mode 100644 index 0000000..e3cfd46 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* pmic wrap module wait_idle and read polling interval (in microseconds) */ +enum { + WAIT_IDLE_POLLING_DELAY_US = 1, + READ_POLLING_DELAY_US = 2 +}; + +static inline uint32_t wait_for_state_idle(uint32_t timeout_us, + void *wacs_register, + void *wacs_vldclr_register, + uint32_t *read_reg) +{ + uint32_t reg_rdata; + uint32_t retry; + + retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) / + WAIT_IDLE_POLLING_DELAY_US; + + do { + udelay(WAIT_IDLE_POLLING_DELAY_US); + reg_rdata = mmio_read_32((uintptr_t)wacs_register); + /* if last read command timeout,clear vldclr bit + * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR; + * write:FSM_REQ-->idle + */ + switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & + RDATA_WACS_FSM_MASK)) { + case WACS_FSM_WFVLDCLR: + mmio_write_32((uintptr_t)wacs_vldclr_register, 1); + ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n"); + break; + case WACS_FSM_WFDLE: + ERROR("WACS_FSM = WACS_FSM_WFDLE\n"); + break; + case WACS_FSM_REQ: + ERROR("WACS_FSM = WACS_FSM_REQ\n"); + break; + case WACS_FSM_IDLE: + goto done; + default: + break; + } + + retry--; + } while (retry); + +done: + if (!retry) /* timeout */ + return E_PWR_WAIT_IDLE_TIMEOUT; + + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +static inline uint32_t wait_for_state_ready(uint32_t timeout_us, + void *wacs_register, + uint32_t *read_reg) +{ + uint32_t reg_rdata; + uint32_t retry; + + retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US; + + do { + udelay(READ_POLLING_DELAY_US); + reg_rdata = mmio_read_32((uintptr_t)wacs_register); + + if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK) + == WACS_FSM_WFVLDCLR) + break; + + retry--; + } while (retry); + + if (!retry) { /* timeout */ + ERROR("timeout when waiting for idle\n"); + return E_PWR_WAIT_IDLE_TIMEOUT_READ; + } + + if (read_reg) + *read_reg = reg_rdata; + return 0; +} + +static int32_t pwrap_wacs2(uint32_t write, + uint32_t adr, + uint32_t wdata, + uint32_t *rdata, + uint32_t init_check) +{ + uint32_t reg_rdata = 0; + uint32_t wacs_write = 0; + uint32_t wacs_adr = 0; + uint32_t wacs_cmd = 0; + uint32_t return_value = 0; + + if (init_check) { + reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata); + /* Prevent someone to used pwrap before pwrap init */ + if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) & + RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) { + ERROR("initialization isn't finished\n"); + return E_PWR_NOT_INIT_DONE; + } + } + reg_rdata = 0; + /* Check IDLE in advance */ + return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE, + &mtk_pwrap->wacs2_rdata, + &mtk_pwrap->wacs2_vldclr, + 0); + if (return_value != 0) { + ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value); + goto FAIL; + } + wacs_write = write << 31; + wacs_adr = (adr >> 1) << 16; + wacs_cmd = wacs_write | wacs_adr | wdata; + + mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, wacs_cmd); + if (write == 0) { + if (rdata == NULL) { + ERROR("rdata is a NULL pointer\n"); + return_value = E_PWR_INVALID_ARG; + goto FAIL; + } + return_value = wait_for_state_ready(TIMEOUT_READ, + &mtk_pwrap->wacs2_rdata, + ®_rdata); + if (return_value != 0) { + ERROR("wait_for_fsm_vldclr fail,return_value=%d\n", + return_value); + goto FAIL; + } + *rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT) + & RDATA_WACS_RDATA_MASK); + mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 1); + } +FAIL: + return return_value; +} + +/* external API for pmic_wrap user */ + +int32_t pwrap_read(uint32_t adr, uint32_t *rdata) +{ + return pwrap_wacs2(0, adr, 0, rdata, 1); +} + +int32_t pwrap_write(uint32_t adr, uint32_t wdata) +{ + return pwrap_wacs2(1, adr, wdata, 0, 1); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c b/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c new file mode 100644 index 0000000..d9a79c4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "platform_def.h" +#include "pmic_wrap_init.h" + +/* pmic wrap module wait_idle and read polling interval (in microseconds) */ +enum pwrap_polling_interval { + WAIT_IDLE_POLLING_DELAY_US = 1, + READ_POLLING_DELAY_US = 2 +}; + +static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us) +{ + uint32_t reg_rdata = 0U, retry; + + retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) / + WAIT_IDLE_POLLING_DELAY_US; + while (retry != 0) { + udelay(WAIT_IDLE_POLLING_DELAY_US); + reg_rdata = mmio_read_32((uintptr_t)wacs_register); + /* if last read command timeout,clear vldclr bit + * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR; + * write:FSM_REQ-->idle + */ + switch (GET_WACS_FSM(reg_rdata)) { + case SWINF_FSM_WFVLDCLR: + mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1); + INFO("WACS_FSM = SWINF_FSM_WFVLDCLR\n"); + break; + case SWINF_FSM_WFDLE: + INFO("WACS_FSM = SWINF_FSM_WFDLE\n"); + break; + case SWINF_FSM_REQ: + INFO("WACS_FSM = SWINF_FSM_REQ\n"); + break; + case SWINF_FSM_IDLE: + goto done; + default: + break; + } + retry--; + }; + +done: + if (retry == 0) { + /* timeout */ + return E_PWR_WAIT_IDLE_TIMEOUT; + } + + return 0U; +} + +static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us) +{ + uint32_t reg_rdata = 0U, retry; + + retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US; + while (retry != 0) { + udelay(READ_POLLING_DELAY_US); + reg_rdata = mmio_read_32((uintptr_t)wacs_register); + if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) { + break; + } + retry--; + }; + + if (retry == 0) { + /* timeout */ + return E_PWR_WAIT_IDLE_TIMEOUT; + } + + return 0U; +} + +static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata, + uint32_t *rdata, uint32_t init_check) +{ + uint32_t reg_rdata, return_value; + + if (init_check != 0) { + if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) { + ERROR("initialization isn't finished\n"); + return E_PWR_NOT_INIT_DONE; + } + } + + /* Wait for Software Interface FSM state to be IDLE. */ + return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta, + PWRAP_WAIT_IDLE_US); + if (return_value != 0) { + return return_value; + } + + /* Set the write data */ + if (write == 1) { + /* Set the write data. */ + mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata); + } + + /* Send the command. */ + mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr); + + if (write == 0) { + /* + * Wait for Software Interface FSM state to be WFVLDCLR, + * read the data and clear the valid flag. + */ + return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta, + PWRAP_READ_US); + if (return_value != 0) { + return return_value; + } + + if (rdata == NULL) { + return E_PWR_INVALID_ARG; + } + + reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata); + *rdata = reg_rdata; + mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1); + } + + return return_value; +} + +/* external API for pmic_wrap user */ +int32_t pwrap_read(uint32_t adr, uint32_t *rdata) +{ + return pwrap_wacs2(0, adr, 0, rdata, 1); +} + +int32_t pwrap_write(uint32_t adr, uint32_t wdata) +{ + return pwrap_wacs2(1, adr, wdata, 0, 1); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c new file mode 100644 index 0000000..cad12a0 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +/* RTC busy status polling interval and retry count */ +enum { + RTC_WRTGR_POLLING_DELAY_MS = 10, + RTC_WRTGR_POLLING_CNT = 100 +}; + +uint16_t RTC_Read(uint32_t addr) +{ + uint32_t rdata = 0; + + pwrap_read((uint32_t)addr, &rdata); + return (uint16_t)rdata; +} + +void RTC_Write(uint32_t addr, uint16_t data) +{ + pwrap_write((uint32_t)addr, (uint32_t)data); +} + +int32_t rtc_busy_wait(void) +{ + uint64_t retry = RTC_WRTGR_POLLING_CNT; + + do { + mdelay(RTC_WRTGR_POLLING_DELAY_MS); + if (!(RTC_Read(RTC_BBPU) & RTC_BBPU_CBUSY)) + return 1; + retry--; + } while (retry); + + ERROR("[RTC] rtc cbusy time out!\n"); + return 0; +} + +int32_t RTC_Write_Trigger(void) +{ + RTC_Write(RTC_WRTGR, 1); + return rtc_busy_wait(); +} + +int32_t Writeif_unlock(void) +{ + RTC_Write(RTC_PROT, RTC_PROT_UNLOCK1); + if (!RTC_Write_Trigger()) + return 0; + RTC_Write(RTC_PROT, RTC_PROT_UNLOCK2); + if (!RTC_Write_Trigger()) + return 0; + + return 1; +} + diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c new file mode 100644 index 0000000..124bc8f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + +static void RTC_Config_Interface(uint32_t addr, uint16_t data, + uint16_t mask, uint16_t shift) +{ + uint16_t pmic_reg; + + pmic_reg = RTC_Read(addr); + + pmic_reg &= ~(mask << shift); + pmic_reg |= (data << shift); + + RTC_Write(addr, pmic_reg); +} + +static int32_t rtc_disable_2sec_reboot(void) +{ + uint16_t reboot; + + reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) & + ~RTC_BBPU_AUTO_PDN_SEL; + RTC_Write(RTC_AL_SEC, reboot); + + return RTC_Write_Trigger(); +} + +static int32_t rtc_enable_k_eosc(void) +{ + uint16_t alm_dow, alm_sec; + int16_t ret; + + /* Turning on eosc cali mode clock */ + RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0_CLR, 1, + PMIC_RG_RTC_EOSC32_CK_PDN_MASK, + PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT); + + alm_sec = RTC_Read(RTC_AL_SEC) & (~RTC_LPD_OPT_MASK); + RTC_Write(RTC_AL_SEC, alm_sec); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return 0; + } + + RTC_Write(RTC_CON, RTC_LPD_EN); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return 0; + } + + RTC_Write(RTC_CON, RTC_LPD_RST); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return 0; + } + + RTC_Write(RTC_CON, RTC_LPD_EN); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return 0; + } + + RTC_Write(RTC_POWERKEY1, RTC_POWERKEY1_KEY); + RTC_Write(RTC_POWERKEY2, RTC_POWERKEY2_KEY); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return 0; + } + + /* set RTC EOSC calibration period = 8sec */ + alm_dow = (RTC_Read(RTC_AL_DOW) & (~RTC_RG_EOSC_CALI_TD_MASK)) | + RTC_RG_EOSC_CALI_TD_8SEC; + RTC_Write(RTC_AL_DOW, alm_dow); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return 0; + } + + RTC_Write(RTC_BBPU, + RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return 0; + } + + /* Enable K EOSC mode :use solution1 of eosc cali to fix mt6359p 32K*/ + RTC_Write(RTC_AL_YEA, (((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0) + & (~RTC_K_EOSC_RSV_1)) | (RTC_K_EOSC_RSV_2))); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return 0; + } + + INFO("[RTC] RTC_enable_k_eosc\n"); + + return 1; +} + +void rtc_power_off_sequence(void) +{ + uint16_t bbpu; + int16_t ret; + + ret = rtc_disable_2sec_reboot(); + if (ret == 0) { + return; + } + + ret = rtc_enable_k_eosc(); + if (ret == 0) { + return; + } + + bbpu = RTC_BBPU_KEY | RTC_BBPU_PWREN; + + if (Writeif_unlock() != 0) { + RTC_Write(RTC_BBPU, + bbpu | RTC_BBPU_RESET_ALARM | RTC_BBPU_RESET_SPAR); + RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return; + } + mdelay(1); + + bbpu = RTC_Read(RTC_BBPU); + + if (((bbpu & RTC_BBPU_RESET_ALARM) > 0) || + ((bbpu & RTC_BBPU_RESET_SPAR) > 0)) { + INFO("[RTC] timeout\n"); + } + + bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; + RTC_Write(RTC_BBPU, bbpu); + ret = RTC_Write_Trigger(); + if (ret == 0) { + return; + } + } +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h new file mode 100644 index 0000000..04726e3 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RTC_MT6359P_H +#define RTC_MT6359P_H + +/* RTC registers */ +enum { + RTC_BBPU = 0x0588, + RTC_IRQ_STA = 0x058A, + RTC_IRQ_EN = 0x058C, + RTC_CII_EN = 0x058E +}; + +enum { + RTC_AL_SEC = 0x05A0, + RTC_AL_MIN = 0x05A2, + RTC_AL_HOU = 0x05A4, + RTC_AL_DOM = 0x05A6, + RTC_AL_DOW = 0x05A8, + RTC_AL_MTH = 0x05AA, + RTC_AL_YEA = 0x05AC, + RTC_AL_MASK = 0x0590 +}; + +enum { + RTC_OSC32CON = 0x05AE, + RTC_CON = 0x05C4, + RTC_WRTGR = 0x05C2 +}; + +enum { + RTC_POWERKEY1 = 0x05B0, + RTC_POWERKEY2 = 0x05B2 +}; + +enum { + RTC_POWERKEY1_KEY = 0xA357, + RTC_POWERKEY2_KEY = 0x67D2 +}; + +enum { + RTC_PDN1 = 0x05B4, + RTC_PDN2 = 0x05B6, + RTC_SPAR0 = 0x05B8, + RTC_SPAR1 = 0x05BA, + RTC_PROT = 0x05BC, + RTC_DIFF = 0x05BE, + RTC_CALI = 0x05C0 +}; + +enum { + RTC_OSC32CON_UNLOCK1 = 0x1A57, + RTC_OSC32CON_UNLOCK2 = 0x2B68 +}; + +enum { + RTC_LPD_EN = 0x0406, + RTC_LPD_RST = 0x040E +}; + +enum { + RTC_LPD_OPT_XOSC_AND_EOSC_LPD = 0U << 13, + RTC_LPD_OPT_EOSC_LPD = 1U << 13, + RTC_LPD_OPT_XOSC_LPD = 2U << 13, + RTC_LPD_OPT_F32K_CK_ALIVE = 3U << 13, +}; + +#define RTC_LPD_OPT_MASK (3U << 13) + +enum { + RTC_PROT_UNLOCK1 = 0x586A, + RTC_PROT_UNLOCK2 = 0x9136 +}; + +enum { + RTC_BBPU_PWREN = 1U << 0, + RTC_BBPU_SPAR_SW = 1U << 1, + RTC_BBPU_RESET_SPAR = 1U << 2, + RTC_BBPU_RESET_ALARM = 1U << 3, + RTC_BBPU_CLRPKY = 1U << 4, + RTC_BBPU_RELOAD = 1U << 5, + RTC_BBPU_CBUSY = 1U << 6 +}; + +enum { + RTC_AL_MASK_SEC = 1U << 0, + RTC_AL_MASK_MIN = 1U << 1, + RTC_AL_MASK_HOU = 1U << 2, + RTC_AL_MASK_DOM = 1U << 3, + RTC_AL_MASK_DOW = 1U << 4, + RTC_AL_MASK_MTH = 1U << 5, + RTC_AL_MASK_YEA = 1U << 6 +}; + +enum { + RTC_BBPU_AUTO_PDN_SEL = 1U << 6, + RTC_BBPU_2SEC_CK_SEL = 1U << 7, + RTC_BBPU_2SEC_EN = 1U << 8, + RTC_BBPU_2SEC_MODE = 0x3 << 9, + RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11, + RTC_BBPU_2SEC_STAT_STA = 1U << 12 +}; + +enum { + RTC_BBPU_KEY = 0x43 << 8 +}; + +enum { + RTC_EMBCK_SRC_SEL = 1 << 8, + RTC_EMBCK_SEL_MODE = 3 << 6, + RTC_XOSC32_ENB = 1 << 5, + RTC_REG_XOSC32_ENB = 1 << 15 +}; + +enum { + RTC_K_EOSC_RSV_0 = 1 << 8, + RTC_K_EOSC_RSV_1 = 1 << 9, + RTC_K_EOSC_RSV_2 = 1 << 10 +}; + +enum { + RTC_RG_EOSC_CALI_TD_1SEC = 3 << 5, + RTC_RG_EOSC_CALI_TD_2SEC = 4 << 5, + RTC_RG_EOSC_CALI_TD_4SEC = 5 << 5, + RTC_RG_EOSC_CALI_TD_8SEC = 6 << 5, + RTC_RG_EOSC_CALI_TD_16SEC = 7 << 5, + RTC_RG_EOSC_CALI_TD_MASK = 7 << 5 +}; + +/* PMIC TOP Register Definition */ +enum { + PMIC_RG_TOP_CON = 0x0020, + PMIC_RG_TOP_CKPDN_CON1 = 0x0112, + PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114, + PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116, + PMIC_RG_TOP_CKSEL_CON0 = 0x0118, + PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A, + PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C +}; + +/* PMIC SCK Register Definition */ +enum { + PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x0514, + PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x0516, + PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x0518, + PMIC_RG_EOSC_CALI_CON0 = 0x53A +}; + +enum { + PMIC_EOSC_CALI_START_ADDR = 0x53A +}; + +enum { + PMIC_EOSC_CALI_START_MASK = 0x1, + PMIC_EOSC_CALI_START_SHIFT = 0 +}; + +/* PMIC DCXO Register Definition */ +enum { + PMIC_RG_DCXO_CW00 = 0x0788, + PMIC_RG_DCXO_CW02 = 0x0790, + PMIC_RG_DCXO_CW08 = 0x079C, + PMIC_RG_DCXO_CW09 = 0x079E, + PMIC_RG_DCXO_CW09_CLR = 0x07A2, + PMIC_RG_DCXO_CW10 = 0x07A4, + PMIC_RG_DCXO_CW12 = 0x07A8, + PMIC_RG_DCXO_CW13 = 0x07AA, + PMIC_RG_DCXO_CW15 = 0x07AE, + PMIC_RG_DCXO_CW19 = 0x07B6, +}; + +enum { + PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1, + PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1, + PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1, + PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3, + PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1, + PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2, + PMIC_RG_EOSC_CALI_TD_MASK = 0x7, + PMIC_RG_EOSC_CALI_TD_SHIFT = 5, + PMIC_RG_XO_EN32K_MAN_MASK = 0x1, + PMIC_RG_XO_EN32K_MAN_SHIFT = 0 +}; + +/* external API */ +uint16_t RTC_Read(uint32_t addr); +void RTC_Write(uint32_t addr, uint16_t data); +int32_t rtc_busy_wait(void); +int32_t RTC_Write_Trigger(void); +int32_t Writeif_unlock(void); +void rtc_power_off_sequence(void); + +#endif /* RTC_MT6359P_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c b/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c new file mode 100644 index 0000000..0860885 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + +uint64_t normal_time_base; +uint64_t atf_time_base; + +void sched_clock_init(uint64_t normal_base, uint64_t atf_base) +{ + normal_time_base += normal_base; + atf_time_base = atf_base; +} + +uint64_t sched_clock(void) +{ + uint64_t cval; + uint64_t rel_base; + + rel_base = read_cntpct_el0() - atf_time_base; + cval = ((rel_base * 1000U) / SYS_COUNTER_FREQ_IN_MHZ) + - normal_time_base; + return cval; +} + +void mt_systimer_init(void) +{ + /* Enable access in NS mode */ + mmio_write_32(CNTWACR_REG, CNT_WRITE_ACCESS_CTL_MASK); + mmio_write_32(CNTRACR_REG, CNT_READ_ACCESS_CTL_MASK); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h b/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h new file mode 100644 index 0000000..b353177 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_TIMER_H +#define MT_TIMER_H + +#define SYSTIMER_BASE (0x10017000) +#define CNTCR_REG (SYSTIMER_BASE + 0x0) +#define CNTSR_REG (SYSTIMER_BASE + 0x4) +#define CNTSYS_L_REG (SYSTIMER_BASE + 0x8) +#define CNTSYS_H_REG (SYSTIMER_BASE + 0xc) +#define CNTWACR_REG (SYSTIMER_BASE + 0x10) +#define CNTRACR_REG (SYSTIMER_BASE + 0x14) + +#define TIEO_EN (1 << 3) +#define COMP_15_EN (1 << 10) +#define COMP_20_EN (1 << 11) +#define COMP_25_EN (1 << 12) + +#define COMP_FEATURE_MASK (COMP_15_EN | COMP_20_EN | COMP_25_EN | TIEO_EN) +#define COMP_15_MASK (COMP_15_EN) +#define COMP_20_MASK (COMP_20_EN | TIEO_EN) +#define COMP_25_MASK (COMP_20_EN | COMP_25_EN) + +#define CNT_WRITE_ACCESS_CTL_MASK (0x3FFFFF0U) +#define CNT_READ_ACCESS_CTL_MASK (0x3FFFFFFU) + +void sched_clock_init(uint64_t normal_base, uint64_t atf_base); +uint64_t sched_clock(void); +void mt_systimer_init(void); + +#endif /* MT_TIMER_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S new file mode 100644 index 0000000..7a946f9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + + .globl console_core_init + .globl console_core_putc + .globl console_core_getc + .globl console_core_flush + + /* ----------------------------------------------- + * int console_core_init(unsigned long base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : x1, x2, x3 + * ----------------------------------------------- + */ +func console_core_init + /* Check the input base address */ + cbz x0, core_init_fail + /* Check baud rate and uart clock for sanity */ + cbz w1, core_init_fail + cbz w2, core_init_fail + + /* Disable interrupt */ + str wzr, [x0, #UART_IER] + + /* Force DTR and RTS to high */ + mov w3, #(UART_MCR_DTR | UART_MCR_RTS) + str w3, [x0, #UART_MCR] + + /* Check high speed */ + movz w3, #:abs_g1:115200 + movk w3, #:abs_g0_nc:115200 + cmp w2, w3 + b.hi 1f + + /* Non high speed */ + lsl w2, w2, #4 + mov w3, wzr + b 2f + + /* High speed */ +1: lsl w2, w2, #2 + mov w3, #2 + + /* Set high speed UART register */ +2: str w3, [x0, #UART_HIGHSPEED] + + /* Calculate divisor */ + udiv w3, w1, w2 /* divisor = uartclk / (quot * baudrate) */ + msub w1, w3, w2, w1 /* remainder = uartclk % (quot * baudrate) */ + lsr w2, w2, #1 + cmp w1, w2 + cinc w3, w3, hs + + /* Set line configuration, access divisor latches */ + mov w1, #(UART_LCR_DLAB | UART_LCR_WLS_8) + str w1, [x0, #UART_LCR] + + /* Set the divisor */ + and w1, w3, #0xff + str w1, [x0, #UART_DLL] + lsr w1, w3, #8 + and w1, w1, #0xff + str w1, [x0, #UART_DLH] + + /* Hide the divisor latches */ + mov w1, #UART_LCR_WLS_8 + str w1, [x0, #UART_LCR] + + /* Enable FIFOs, and clear receive and transmit */ + mov w1, #(UART_FCR_FIFO_EN | UART_FCR_CLEAR_RCVR | \ + UART_FCR_CLEAR_XMIT) + str w1, [x0, #UART_FCR] + + mov w0, #1 + ret +core_init_fail: + mov w0, wzr + ret +endfunc console_core_init + + /* -------------------------------------------------------- + * int console_core_putc(int c, unsigned long base_addr) + * 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 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_core_putc + /* Check the input parameter */ + cbz x1, putc_error + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f + + /* Check if the transmit FIFO is full */ +1: ldr w2, [x1, #UART_LSR] + and w2, w2, #UART_LSR_THRE + cbz w2, 1b + mov w2, #0xD + str w2, [x1, #UART_THR] + + /* Check if the transmit FIFO is full */ +2: ldr w2, [x1, #UART_LSR] + and w2, w2, #UART_LSR_THRE + cbz w2, 2b + str w0, [x1, #UART_THR] + ret +putc_error: + mov w0, #-1 + ret +endfunc console_core_putc + + /* --------------------------------------------- + * int console_core_getc(unsigned long base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on error. + * In : x0 - console base address + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_core_getc + cbz x0, getc_error + + /* Check if the receive FIFO is empty */ +1: ldr w1, [x0, #UART_LSR] + tbz w1, #UART_LSR_DR, 1b + ldr w0, [x0, #UART_RBR] + ret +getc_error: + mov w0, #-1 + ret +endfunc console_core_getc + + /* --------------------------------------------- + * void console_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_core_flush + /* Placeholder */ + ret +endfunc console_core_flush diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c new file mode 100644 index 0000000..b940eb3 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS]; + +static const uint32_t uart_base_addr[DRV_SUPPORT_UART_PORTS] = { + UART0_BASE, + UART1_BASE +}; + +void mt_uart_restore(void) +{ + int uart_idx = UART_PORT0; + struct mt_uart *uart; + unsigned long base; + + /* Must NOT print any debug log before UART restore */ + for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS; + uart_idx++) { + + uart = &uart_save_addr[uart_idx]; + base = uart->base; + + mmio_write_32(UART_LCR(base), UART_LCR_MODE_B); + mmio_write_32(UART_EFR(base), uart->registers.efr); + mmio_write_32(UART_LCR(base), uart->registers.lcr); + mmio_write_32(UART_FCR(base), uart->registers.fcr); + + /* baudrate */ + mmio_write_32(UART_HIGHSPEED(base), uart->registers.highspeed); + mmio_write_32(UART_FRACDIV_L(base), uart->registers.fracdiv_l); + mmio_write_32(UART_FRACDIV_M(base), uart->registers.fracdiv_m); + mmio_write_32(UART_LCR(base), + uart->registers.lcr | UART_LCR_DLAB); + mmio_write_32(UART_DLL(base), uart->registers.dll); + mmio_write_32(UART_DLH(base), uart->registers.dlh); + mmio_write_32(UART_LCR(base), uart->registers.lcr); + mmio_write_32(UART_SAMPLE_COUNT(base), + uart->registers.sample_count); + mmio_write_32(UART_SAMPLE_POINT(base), + uart->registers.sample_point); + mmio_write_32(UART_GUARD(base), uart->registers.guard); + + /* flow control */ + mmio_write_32(UART_ESCAPE_EN(base), uart->registers.escape_en); + mmio_write_32(UART_MCR(base), uart->registers.mcr); + mmio_write_32(UART_IER(base), uart->registers.ier); + mmio_write_32(UART_SCR(base), uart->registers.scr); + } +} + +void mt_uart_save(void) +{ + int uart_idx = UART_PORT0; + struct mt_uart *uart; + unsigned long base; + + for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS; + uart_idx++) { + + uart_save_addr[uart_idx].base = uart_base_addr[uart_idx]; + base = uart_base_addr[uart_idx]; + uart = &uart_save_addr[uart_idx]; + uart->registers.lcr = mmio_read_32(UART_LCR(base)); + + mmio_write_32(UART_LCR(base), UART_LCR_MODE_B); + uart->registers.efr = mmio_read_32(UART_EFR(base)); + mmio_write_32(UART_LCR(base), uart->registers.lcr); + uart->registers.fcr = mmio_read_32(UART_FCR_RD(base)); + + /* baudrate */ + uart->registers.highspeed = mmio_read_32(UART_HIGHSPEED(base)); + uart->registers.fracdiv_l = mmio_read_32(UART_FRACDIV_L(base)); + uart->registers.fracdiv_m = mmio_read_32(UART_FRACDIV_M(base)); + mmio_write_32(UART_LCR(base), + uart->registers.lcr | UART_LCR_DLAB); + uart->registers.dll = mmio_read_32(UART_DLL(base)); + uart->registers.dlh = mmio_read_32(UART_DLH(base)); + mmio_write_32(UART_LCR(base), uart->registers.lcr); + uart->registers.sample_count = mmio_read_32( + UART_SAMPLE_COUNT(base)); + uart->registers.sample_point = mmio_read_32( + UART_SAMPLE_POINT(base)); + uart->registers.guard = mmio_read_32(UART_GUARD(base)); + + /* flow control */ + uart->registers.escape_en = mmio_read_32(UART_ESCAPE_EN(base)); + uart->registers.mcr = mmio_read_32(UART_MCR(base)); + uart->registers.ier = mmio_read_32(UART_IER(base)); + uart->registers.scr = mmio_read_32(UART_SCR(base)); + } +} + +void mt_console_uart_cg(int on) +{ + if (on == 1) { + mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT); + } else { + mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT); + } +} + +uint32_t mt_console_uart_cg_status(void) +{ + return mmio_read_32(UART_CLOCK_GATE_STA) & UART0_CLOCK_GATE_BIT; +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h new file mode 100644 index 0000000..ac8b94d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UART_H +#define UART_H + +#include + +/* UART HW information */ +#define HW_SUPPORT_UART_PORTS 2 +#define DRV_SUPPORT_UART_PORTS 2 + +/* console UART clock cg */ +#define UART_CLOCK_GATE_SET (INFRACFG_AO_BASE + 0x80) +#define UART_CLOCK_GATE_CLR (INFRACFG_AO_BASE + 0x84) +#define UART_CLOCK_GATE_STA (INFRACFG_AO_BASE + 0x90) +#define UART0_CLOCK_GATE_BIT (1U<<22) +#define UART1_CLOCK_GATE_BIT (1U<<23) + +/* UART registers */ +#define UART_RBR(_baseaddr) (_baseaddr + 0x0) +#define UART_THR(_baseaddr) (_baseaddr + 0x0) +#define UART_IER(_baseaddr) (_baseaddr + 0x4) +#define UART_IIR(_baseaddr) (_baseaddr + 0x8) +#define UART_FCR(_baseaddr) (_baseaddr + 0x8) +#define UART_LCR(_baseaddr) (_baseaddr + 0xc) +#define UART_MCR(_baseaddr) (_baseaddr + 0x10) +#define UART_LSR(_baseaddr) (_baseaddr + 0x14) +#define UART_MSR(_baseaddr) (_baseaddr + 0x18) +#define UART_SCR(_baseaddr) (_baseaddr + 0x1c) +#define UART_DLL(_baseaddr) (_baseaddr + 0x0) +#define UART_DLH(_baseaddr) (_baseaddr + 0x4) +#define UART_EFR(_baseaddr) (_baseaddr + 0x8) +#define UART_XON1(_baseaddr) (_baseaddr + 0x10) +#define UART_XON2(_baseaddr) (_baseaddr + 0x14) +#define UART_XOFF1(_baseaddr) (_baseaddr + 0x18) +#define UART_XOFF2(_baseaddr) (_baseaddr + 0x1c) +#define UART_AUTOBAUD(_baseaddr) (_baseaddr + 0x20) +#define UART_HIGHSPEED(_baseaddr) (_baseaddr + 0x24) +#define UART_SAMPLE_COUNT(_baseaddr) (_baseaddr + 0x28) +#define UART_SAMPLE_POINT(_baseaddr) (_baseaddr + 0x2c) +#define UART_AUTOBAUD_REG(_baseaddr) (_baseaddr + 0x30) +#define UART_RATE_FIX_REG(_baseaddr) (_baseaddr + 0x34) +#define UART_AUTO_BAUDSAMPLE(_baseaddr) (_baseaddr + 0x38) +#define UART_GUARD(_baseaddr) (_baseaddr + 0x3c) +#define UART_ESCAPE_DAT(_baseaddr) (_baseaddr + 0x40) +#define UART_ESCAPE_EN(_baseaddr) (_baseaddr + 0x44) +#define UART_SLEEP_EN(_baseaddr) (_baseaddr + 0x48) +#define UART_DMA_EN(_baseaddr) (_baseaddr + 0x4c) +#define UART_RXTRI_AD(_baseaddr) (_baseaddr + 0x50) +#define UART_FRACDIV_L(_baseaddr) (_baseaddr + 0x54) +#define UART_FRACDIV_M(_baseaddr) (_baseaddr + 0x58) +#define UART_FCR_RD(_baseaddr) (_baseaddr + 0x5C) +#define UART_USB_RX_SEL(_baseaddr) (_baseaddr + 0xB0) +#define UART_SLEEP_REQ(_baseaddr) (_baseaddr + 0xB4) +#define UART_SLEEP_ACK(_baseaddr) (_baseaddr + 0xB8) +#define UART_SPM_SEL(_baseaddr) (_baseaddr + 0xBC) +#define UART_LCR_DLAB 0x0080 +#define UART_LCR_MODE_B 0x00bf + +enum uart_port_ID { + UART_PORT0 = 0, + UART_PORT1 +}; + +struct mt_uart_register { + uint32_t dll; + uint32_t dlh; + uint32_t ier; + uint32_t lcr; + uint32_t mcr; + uint32_t fcr; + uint32_t lsr; + uint32_t scr; + uint32_t efr; + uint32_t highspeed; + uint32_t sample_count; + uint32_t sample_point; + uint32_t fracdiv_l; + uint32_t fracdiv_m; + uint32_t escape_en; + uint32_t guard; + uint32_t rx_sel; +}; + +struct mt_uart { + unsigned long base; + struct mt_uart_register registers; +}; + +/* external API */ +void mt_uart_save(void); +void mt_uart_restore(void); +void mt_console_uart_cg(int on); +uint32_t mt_console_uart_cg_status(void); + +#endif /* __UART_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h new file mode 100644 index 0000000..da7c7a1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef UART8250_H +#define UART8250_H + +/* UART register */ +#define UART_RBR 0x00 /* Receive buffer register */ +#define UART_DLL 0x00 /* Divisor latch lsb */ +#define UART_THR 0x00 /* Transmit holding register */ +#define UART_DLH 0x04 /* Divisor latch msb */ +#define UART_IER 0x04 /* Interrupt enable register */ +#define UART_FCR 0x08 /* FIFO control register */ +#define UART_LCR 0x0c /* Line control register */ +#define UART_MCR 0x10 /* Modem control register */ +#define UART_LSR 0x14 /* Line status register */ +#define UART_HIGHSPEED 0x24 /* High speed UART */ + +/* FCR */ +#define UART_FCR_FIFO_EN 0x01 /* enable FIFO */ +#define UART_FCR_CLEAR_RCVR 0x02 /* clear the RCVR FIFO */ +#define UART_FCR_CLEAR_XMIT 0x04 /* clear the XMIT FIFO */ + +/* LCR */ +#define UART_LCR_WLS_8 0x03 /* 8 bit character length */ +#define UART_LCR_DLAB 0x80 /* divisor latch access bit */ + +/* MCR */ +#define UART_MCR_DTR 0x01 +#define UART_MCR_RTS 0x02 + +/* LSR */ +#define UART_LSR_DR 0x01 /* Data ready */ +#define UART_LSR_THRE 0x20 /* Xmit holding register empty */ + +#endif /* UART8250_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c b/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c new file mode 100644 index 0000000..f3148fe --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +struct platform_mt_resource_manager { + unsigned int count; + struct mt_resource_manager *plat_rm; +}; + +static struct platform_mt_resource_manager plat_mt_rm; + +int mt_lp_rm_register(struct mt_resource_manager *rm) +{ + unsigned int i; + struct mt_resource_constraint *const *rc; + + if ((rm == NULL) || (rm->consts == NULL) || + (plat_mt_rm.plat_rm != NULL)) { + return MT_RM_STATUS_BAD; + } + + for (i = 0U, rc = rm->consts; *rc != NULL; i++, rc++) { + if ((*rc)->init != NULL) { + (*rc)->init(); + } + } + + plat_mt_rm.plat_rm = rm; + plat_mt_rm.count = i; + + return MT_RM_STATUS_OK; +} + +int mt_lp_rm_reset_constraint(int idx, unsigned int cpuid, int stateid) +{ + struct mt_resource_constraint const *rc = NULL; + + if ((plat_mt_rm.plat_rm == NULL) || (idx < 0) || + (idx >= plat_mt_rm.count)) { + return MT_RM_STATUS_BAD; + } + + rc = plat_mt_rm.plat_rm->consts[idx]; + + if ((rc == NULL) || (rc->reset == NULL)) { + return MT_RM_STATUS_BAD; + } + + return rc->reset(cpuid, stateid); +} + +int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid, + int stateid, void *priv) +{ + int i, res = MT_RM_STATUS_BAD; + struct mt_resource_constraint *const *rc; + struct mt_resource_manager *rm = plat_mt_rm.plat_rm; + + if ((rm == NULL) || (idx < 0) || (idx >= plat_mt_rm.count)) { + return res; + } + + /* If subsys clk/mtcmos is on, add block-resource-off flag */ + if (rm->update != NULL) { + res = rm->update(rm->consts, stateid, priv); + if (res != 0) { + return res; + } + } + + for (i = idx, rc = (rm->consts + idx); *rc != NULL; i++, rc++) { + if (((*rc)->is_valid != NULL) && + ((*rc)->is_valid(cpuid, stateid))) { + if (((*rc)->run != NULL) && + ((*rc)->run(cpuid, stateid) == 0)) { + res = i; + break; + } + } + } + + return res; +} + +int mt_lp_rm_do_update(int stateid, int type, void const *p) +{ + int res = MT_RM_STATUS_BAD; + struct mt_resource_constraint *const *rc; + struct mt_resource_manager *rm = plat_mt_rm.plat_rm; + + if (rm == NULL) { + return res; + } + + for (rc = rm->consts; *rc != NULL; rc++) { + if ((*rc)->update != NULL) { + res = (*rc)->update(stateid, type, p); + if (res != MT_RM_STATUS_OK) { + break; + } + } + } + + return res; +} diff --git a/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h b/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h new file mode 100644 index 0000000..39759f1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_LP_RM_H +#define MT_LP_RM_H + +#include + +#define MT_RM_STATUS_OK 0 +#define MT_RM_STATUS_BAD -1 + +enum PLAT_MT_LPM_RC_TYPE { + PLAT_RC_UPDATE_CONDITION, + PLAT_RC_UPDATE_REMAIN_IRQS +}; + +struct mt_resource_constraint { + int level; + int (*init)(void); + bool (*is_valid)(unsigned int cpu, int stateid); + int (*update)(int stateid, int type, const void *p); + int (*run)(unsigned int cpu, int stateid); + int (*reset)(unsigned int cpu, int stateid); + unsigned int (*allow)(int stateid); +}; + +struct mt_resource_manager { + int (*update)(struct mt_resource_constraint **con, + int stateid, void *priv); + struct mt_resource_constraint **consts; +}; + +extern int mt_lp_rm_register(struct mt_resource_manager *rm); +extern int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid, + int stateid, void *priv); +extern int mt_lp_rm_reset_constraint(int constraint_id, unsigned int cpuid, + int stateid); +extern int mt_lp_rm_do_update(int stateid, int type, void const *p); +#endif /* MT_LP_RM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c b/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c new file mode 100644 index 0000000..9cf7144 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include + +static struct cirq_events cirq_all_events = { + .spi_start = CIRQ_SPI_START, +}; +static uint32_t already_cloned; +/* + * mt_irq_mask_restore: restore all interrupts + * @mask: pointer to struct mtk_irq_mask for storing the original mask value. + * Return 0 for success; return negative values for failure. + * (This is ONLY used for the idle current measurement by the factory mode.) + */ +int mt_irq_mask_restore(struct mtk_irq_mask *mask) +{ + if (mask == NULL) { + return -1; + } + if (mask->header != IRQ_MASK_HEADER) { + return -1; + } + if (mask->footer != IRQ_MASK_FOOTER) { + return -1; + } + + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x4), + mask->mask1); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x8), + mask->mask2); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0xc), + mask->mask3); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x10), + mask->mask4); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x14), + mask->mask5); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x18), + mask->mask6); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x1c), + mask->mask7); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x20), + mask->mask8); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x24), + mask->mask9); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x28), + mask->mask10); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x2c), + mask->mask11); + mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x30), + mask->mask12); + /* make sure dist changes happen */ + dsb(); + + return 0; +} + +/* + * mt_irq_mask_all: disable all interrupts + * @mask: pointer to struct mtk_irq_mask for storing the original mask value. + * Return 0 for success; return negative values for failure. + * (This is ONLY used for the idle current measurement by the factory mode.) + */ +int mt_irq_mask_all(struct mtk_irq_mask *mask) +{ + if (mask != NULL) { + /* for SPI */ + mask->mask1 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x4)); + mask->mask2 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x8)); + mask->mask3 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0xc)); + mask->mask4 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x10)); + mask->mask5 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x14)); + mask->mask6 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x18)); + mask->mask7 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x1c)); + mask->mask8 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x20)); + mask->mask9 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x24)); + mask->mask10 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x28)); + mask->mask11 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x2c)); + mask->mask12 = mmio_read_32((BASE_GICD_BASE + + GICD_ISENABLER + 0x30)); + + /* for SPI */ + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x4), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x8), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0xC), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x10), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x14), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x18), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x1C), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x20), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x24), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x28), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x2c), + 0xFFFFFFFF); + mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x30), + 0xFFFFFFFF); + /* make sure distributor changes happen */ + dsb(); + + mask->header = IRQ_MASK_HEADER; + mask->footer = IRQ_MASK_FOOTER; + + return 0; + } else { + return -1; + } +} + +static uint32_t mt_irq_get_pol(uint32_t irq) +{ +#ifdef CIRQ_WITH_POLARITY + uint32_t reg; + uint32_t base = INT_POL_CTL0; + + if (irq < 32U) { + return 0; + } + + reg = ((irq - 32U) / 32U); + + return mmio_read_32(base + reg * 4U); +#else + return 0; +#endif +} + +unsigned int mt_irq_get_sens(unsigned int irq) +{ + unsigned int config; + + /* + * 2'b10 edge + * 2'b01 level + */ + config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U); + config = (config >> (irq % 16U) * 2U) & 0x3; + + return config; +} + +static void collect_all_wakeup_events(void) +{ + unsigned int i; + uint32_t gic_irq; + uint32_t cirq; + uint32_t cirq_reg; + uint32_t cirq_offset; + uint32_t mask; + uint32_t pol_mask; + uint32_t irq_offset; + uint32_t irq_mask; + + if ((cirq_all_events.wakeup_events == NULL) || + cirq_all_events.num_of_events == 0U) { + return; + } + + for (i = 0U; i < cirq_all_events.num_of_events; i++) { + if (cirq_all_events.wakeup_events[i] > 0U) { + gic_irq = cirq_all_events.wakeup_events[i]; + cirq = gic_irq - cirq_all_events.spi_start - 32U; + cirq_reg = cirq / 32U; + cirq_offset = cirq % 32U; + mask = 0x1 << cirq_offset; + irq_offset = gic_irq % 32U; + irq_mask = 0x1 << irq_offset; + /* + * CIRQ default masks all + */ + cirq_all_events.table[cirq_reg].mask |= mask; + /* + * CIRQ default pol is low + */ + pol_mask = mt_irq_get_pol( + cirq_all_events.wakeup_events[i]) + & irq_mask; + /* + * 0 means rising + */ + if (pol_mask == 0U) { + cirq_all_events.table[cirq_reg].pol |= mask; + } + /* + * CIRQ could monitor edge/level trigger + * cirq register (0: edge, 1: level) + */ + if (mt_irq_get_sens(cirq_all_events.wakeup_events[i]) + == SENS_EDGE) { + cirq_all_events.table[cirq_reg].sen |= mask; + } + + cirq_all_events.table[cirq_reg].used = 1U; + cirq_all_events.table[cirq_reg].reg_num = cirq_reg; + } + } +} + +/* + * mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number. + * @cirq_num: the SYS_CIRQ number to set + * @pol: polarity to set + * @return: + * 0: set pol success + * -1: cirq num is out of range + */ +#ifdef CIRQ_WITH_POLARITY +static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol) +{ + uint32_t base; + uint32_t bit = 1U << (cirq_num % 32U); + + if (cirq_num >= CIRQ_IRQ_NUM) { + return -1; + } + + if (pol == MT_CIRQ_POL_NEG) { + base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE; + } else if (pol == MT_CIRQ_POL_POS) { + base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE; + } else { + return -1; + } + + mmio_write_32(base, bit); + return 0; +} +#endif + +/* + * mt_cirq_mask: Mask the specified SYS_CIRQ. + * @cirq_num: the SYS_CIRQ number to mask + * @return: + * 0: mask success + * -1: cirq num is out of range + */ +static int mt_cirq_mask(uint32_t cirq_num) +{ + uint32_t bit = 1U << (cirq_num % 32U); + + if (cirq_num >= CIRQ_IRQ_NUM) { + return -1; + } + + mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit); + + return 0; +} + +/* + * mt_cirq_unmask: Unmask the specified SYS_CIRQ. + * @cirq_num: the SYS_CIRQ number to unmask + * @return: + * 0: umask success + * -1: cirq num is out of range + */ +static int mt_cirq_unmask(uint32_t cirq_num) +{ + uint32_t bit = 1U << (cirq_num % 32U); + + if (cirq_num >= CIRQ_IRQ_NUM) { + return -1; + } + + mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit); + + return 0; +} + +uint32_t mt_irq_get_en(uint32_t irq) +{ + uint32_t addr, st, val; + + addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U; + st = mmio_read_32(addr); + + val = (st >> (irq % 32U)) & 1U; + + return val; +} + +static void __cirq_fast_clone(void) +{ + struct cirq_reg *reg; + unsigned int i; + + for (i = 0U; i < CIRQ_REG_NUM ; ++i) { + uint32_t cirq_bit; + + reg = &cirq_all_events.table[i]; + + if (reg->used == 0U) { + continue; + } + + mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U), + reg->sen); + + for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) { + uint32_t val, cirq_id; + uint32_t gic_id; +#ifdef CIRQ_WITH_POLARITY + uint32_t gic_bit, pol; +#endif + uint32_t en; + + val = ((1U << cirq_bit) & reg->mask); + + if (val == 0U) { + continue; + } + + cirq_id = (reg->reg_num << 5U) + cirq_bit; + gic_id = CIRQ_TO_IRQ_NUM(cirq_id); +#ifdef CIRQ_WITH_POLARITY + gic_bit = (0x1U << ((gic_id - 32U) % 32U)); + pol = mt_irq_get_pol(gic_id) & gic_bit; + if (pol != 0U) { + mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_NEG); + } else { + mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_POS); + } +#endif + en = mt_irq_get_en(gic_id); + if (en == 1U) { + mt_cirq_unmask(cirq_id); + } else { + mt_cirq_mask(cirq_id); + } + } + } +} + +static void cirq_fast_clone(void) +{ + if (already_cloned == 0U) { + collect_all_wakeup_events(); + already_cloned = 1U; + } + __cirq_fast_clone(); +} + +void set_wakeup_sources(uint32_t *list, uint32_t num_of_events) +{ + cirq_all_events.num_of_events = num_of_events; + cirq_all_events.wakeup_events = list; +} +/* + * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ + */ +void mt_cirq_clone_gic(void) +{ + cirq_fast_clone(); +} + +uint32_t mt_irq_get_pending_vec(uint32_t start_irq) +{ + uint32_t base = 0U; + uint32_t pending_vec = 0U; + uint32_t reg = start_irq / 32U; + uint32_t LSB_num, MSB_num; + uint32_t LSB_vec, MSB_vec; + + base = BASE_GICD_BASE; + + /* if start_irq is not aligned 32, do some assembling */ + MSB_num = start_irq % 32U; + if (MSB_num != 0U) { + LSB_num = 32U - MSB_num; + LSB_vec = mmio_read_32(base + GICD_ISPENDR + + reg * 4U) >> MSB_num; + MSB_vec = mmio_read_32(base + GICD_ISPENDR + + (reg + 1U) * 4U) << LSB_num; + pending_vec = MSB_vec | LSB_vec; + } else { + pending_vec = mmio_read_32(base + GICD_ISPENDR + reg * 4); + } + + return pending_vec; +} + +static int mt_cirq_get_mask_vec(unsigned int i) +{ + return mmio_read_32((i * 4U) + CIRQ_MASK_BASE); +} + +/* + * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ + */ +void mt_cirq_ack_all(void) +{ + uint32_t ack_vec, pend_vec, mask_vec; + unsigned int i; + + for (i = 0; i < CIRQ_CTRL_REG_NUM; i++) { + /* + * if a irq is pending & not masked, don't ack it + * , since cirq start irq might not be 32 aligned with gic, + * need an exotic API to get proper vector of pending irq + */ + pend_vec = mt_irq_get_pending_vec(CIRQ_SPI_START + + (i + 1U) * 32U); + mask_vec = mt_cirq_get_mask_vec(i); + /* those should be acked are: "not (pending & not masked)", + */ + ack_vec = (~pend_vec) | mask_vec; + mmio_write_32(CIRQ_ACK_BASE + (i * 4U), ack_vec); + } + + /* + * make sure all cirq setting take effect + * before doing other things + */ + dsb(); +} +/* + * mt_cirq_enable: Enable SYS_CIRQ + */ +void mt_cirq_enable(void) +{ + uint32_t st; + + /* level only */ + mt_cirq_ack_all(); + + st = mmio_read_32(CIRQ_CON); + /* + * CIRQ could monitor edge/level trigger + */ + st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS); + + mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK)); +} + +/* + * mt_cirq_disable: Disable SYS_CIRQ + */ +void mt_cirq_disable(void) +{ + uint32_t st; + + st = mmio_read_32(CIRQ_CON); + st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS); + mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK)); +} + +void mt_irq_unmask_for_sleep_ex(uint32_t irq) +{ + uint32_t mask; + + mask = 1U << (irq % 32U); + + mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER + + ((irq / 32U) * 4U), mask); +} + +void mt_cirq_mask_all(void) +{ + unsigned int i; + + for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) { + mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF); + } + dsb(); +} + +static void cirq_fast_sw_flush(void) +{ + struct cirq_reg *reg; + unsigned int i; + + for (i = 0U; i < CIRQ_REG_NUM ; ++i) { + uint32_t cirq_bit; + + reg = &cirq_all_events.table[i]; + + if (reg->used == 0U) { + continue; + } + + reg->pending = mmio_read_32(CIRQ_STA_BASE + + (reg->reg_num << 2U)); + reg->pending &= reg->mask; + + for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) { + uint32_t val, cirq_id; + + val = (1U << cirq_bit) & reg->pending; + if (val == 0U) { + continue; + } + + cirq_id = (reg->reg_num << 5U) + cirq_bit; + mt_irq_set_pending(CIRQ_TO_IRQ_NUM(cirq_id)); + if (CIRQ_TO_IRQ_NUM(cirq_id) == MD_WDT_IRQ_BIT_ID) { + INFO("Set MD_WDT_IRQ pending in %s\n", + __func__); + } + } + } +} + +/* + * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC + */ +void mt_cirq_flush(void) +{ + cirq_fast_sw_flush(); + mt_cirq_mask_all(); + mt_cirq_ack_all(); +} + +void mt_cirq_sw_reset(void) +{ + uint32_t st; + + st = mmio_read_32(CIRQ_CON); + st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS); + mmio_write_32(CIRQ_CON, st); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h b/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h new file mode 100644 index 0000000..6e63bb8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MT_CIRQ_H +#define PLAT_MT_CIRQ_H + +#include +#include + +enum { + IRQ_MASK_HEADER = 0xF1F1F1F1, + IRQ_MASK_FOOTER = 0xF2F2F2F2 +}; + +struct mtk_irq_mask { + uint32_t header; /* for error checking */ + uint32_t mask0; + uint32_t mask1; + uint32_t mask2; + uint32_t mask3; + uint32_t mask4; + uint32_t mask5; + uint32_t mask6; + uint32_t mask7; + uint32_t mask8; + uint32_t mask9; + uint32_t mask10; + uint32_t mask11; + uint32_t mask12; + uint32_t footer; /* for error checking */ +}; + +/* + * Define hardware register + */ +#define CIRQ_STA_BASE (SYS_CIRQ_BASE + U(0x000)) +#define CIRQ_ACK_BASE (SYS_CIRQ_BASE + U(0x080)) +#define CIRQ_MASK_BASE (SYS_CIRQ_BASE + U(0x100)) +#define CIRQ_MASK_SET_BASE (SYS_CIRQ_BASE + U(0x180)) +#define CIRQ_MASK_CLR_BASE (SYS_CIRQ_BASE + U(0x200)) +#define CIRQ_SENS_BASE (SYS_CIRQ_BASE + U(0x280)) +#define CIRQ_SENS_SET_BASE (SYS_CIRQ_BASE + U(0x300)) +#define CIRQ_SENS_CLR_BASE (SYS_CIRQ_BASE + U(0x380)) +#define CIRQ_POL_BASE (SYS_CIRQ_BASE + U(0x400)) +#define CIRQ_POL_SET_BASE (SYS_CIRQ_BASE + U(0x480)) +#define CIRQ_POL_CLR_BASE (SYS_CIRQ_BASE + U(0x500)) +#define CIRQ_CON (SYS_CIRQ_BASE + U(0x600)) + +/* + * Register placement + */ +#define CIRQ_CON_EN_BITS U(0) +#define CIRQ_CON_EDGE_ONLY_BITS U(1) +#define CIRQ_CON_FLUSH_BITS U(2) +#define CIRQ_CON_SW_RST_BITS U(20) +#define CIRQ_CON_EVENT_BITS U(31) +#define CIRQ_CON_BITS_MASK U(0x7) + +/* + * Register setting + */ +#define CIRQ_CON_EN U(0x1) +#define CIRQ_CON_EDGE_ONLY U(0x1) +#define CIRQ_CON_FLUSH U(0x1) +#define CIRQ_SW_RESET U(0x1) + +/* + * Define constant + */ +#define CIRQ_CTRL_REG_NUM ((CIRQ_IRQ_NUM + 31U) / 32U) + +#define MT_CIRQ_POL_NEG U(0) +#define MT_CIRQ_POL_POS U(1) + +#define IRQ_TO_CIRQ_NUM(irq) ((irq) - (32U + CIRQ_SPI_START)) +#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (32U + CIRQ_SPI_START)) + +/* GIC sensitive */ +#define SENS_EDGE U(0x2) +#define SENS_LEVEL U(0x1) + + +/* + * Define function prototypes. + */ +int mt_cirq_test(void); +void mt_cirq_dump_reg(void); +int mt_irq_mask_restore(struct mtk_irq_mask *mask); +int mt_irq_mask_all(struct mtk_irq_mask *mask); +void mt_cirq_clone_gic(void); +void mt_cirq_enable(void); +void mt_cirq_flush(void); +void mt_cirq_disable(void); +void mt_irq_unmask_for_sleep_ex(uint32_t irq); +void set_wakeup_sources(uint32_t *list, uint32_t num_of_events); +void mt_cirq_sw_reset(void); + +struct cirq_reg { + uint32_t reg_num; + uint32_t used; + uint32_t mask; + uint32_t pol; + uint32_t sen; + uint32_t pending; + uint32_t the_link; +}; + +struct cirq_events { + uint32_t num_reg; + uint32_t spi_start; + uint32_t num_of_events; + uint32_t *wakeup_events; + struct cirq_reg table[CIRQ_REG_NUM]; + uint32_t dist_base; + uint32_t cirq_base; + uint32_t used_reg_head; +}; + +#endif /* PLAT_MT_CIRQ_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c b/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c new file mode 100644 index 0000000..142b5c9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016-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 + +struct atf_arg_t gteearg; + +void clean_top_32b_of_param(uint32_t smc_fid, + u_register_t *px1, + u_register_t *px2, + u_register_t *px3, + u_register_t *px4) +{ + /* if parameters from SMC32. Clean top 32 bits */ + if (0 == (smc_fid & SMC_AARCH64_BIT)) { + *px1 = *px1 & SMC32_PARAM_MASK; + *px2 = *px2 & SMC32_PARAM_MASK; + *px3 = *px3 & SMC32_PARAM_MASK; + *px4 = *px4 & SMC32_PARAM_MASK; + } +} + +#if MTK_SIP_KERNEL_BOOT_ENABLE +static struct kernel_info k_info; + +static void save_kernel_info(uint64_t pc, + uint64_t r0, + uint64_t r1, + uint64_t k32_64) +{ + k_info.k32_64 = k32_64; + k_info.pc = pc; + + if (LINUX_KERNEL_32 == k32_64) { + /* for 32 bits kernel */ + k_info.r0 = 0; + /* machtype */ + k_info.r1 = r0; + /* tags */ + k_info.r2 = r1; + } else { + /* for 64 bits kernel */ + k_info.r0 = r0; + k_info.r1 = r1; + } +} + +uint64_t get_kernel_info_pc(void) +{ + return k_info.pc; +} + +uint64_t get_kernel_info_r0(void) +{ + return k_info.r0; +} + +uint64_t get_kernel_info_r1(void) +{ + return k_info.r1; +} + +uint64_t get_kernel_info_r2(void) +{ + return k_info.r2; +} + +void boot_to_kernel(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4) +{ + static uint8_t kernel_boot_once_flag; + /* only support in booting flow */ + if (0 == kernel_boot_once_flag) { + kernel_boot_once_flag = 1; + + console_init(gteearg.atf_log_port, + UART_CLOCK, UART_BAUDRATE); + INFO("save kernel info\n"); + save_kernel_info(x1, x2, x3, x4); + bl31_prepare_kernel_entry(x4); + INFO("el3_exit\n"); + console_uninit(); + } +} +#endif + +uint32_t plat_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + unsigned int ee; + unsigned long daif; + + INFO("Secondary bootloader is AArch32\n"); + mode = MODE32_svc; + ee = 0; + /* + * TODO: Choose async. exception bits if HYP mode is not + * implemented according to the values of SCR.{AW, FW} bits + */ + daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT; + + spsr = SPSR_MODE32(mode, 0, ee, daif); + return spsr; +} + +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC + * feature is availabile for platform. + * @fid: SMCCC function id + * + * Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED + * otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} + +int32_t plat_get_soc_version(void) +{ + uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_MTK_BKID, JEDEC_MTK_MFID); + + return (int32_t)(manfid | (SOC_CHIP_ID & SOC_ID_IMPL_DEF_MASK)); +} + +int32_t plat_get_soc_revision(void) +{ + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h b/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h new file mode 100644 index 0000000..919c173 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef MTK_PLAT_COMMON_H +#define MTK_PLAT_COMMON_H + +#include + +#include +#include + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +#define DEVINFO_SIZE 4 +#define LINUX_KERNEL_32 0 +#define SMC32_PARAM_MASK (0xFFFFFFFF) + +#define JEDEC_MTK_BKID U(4) +#define JEDEC_MTK_MFID U(0x26) + +struct atf_arg_t { + unsigned int atf_magic; + unsigned int tee_support; + unsigned int tee_entry; + unsigned int tee_boot_arg_addr; + unsigned int hwuid[4]; /* HW Unique id for t-base used */ + unsigned int HRID[2]; /* HW random id for t-base used */ + unsigned int atf_log_port; + unsigned int atf_log_baudrate; + unsigned int atf_log_buf_start; + unsigned int atf_log_buf_size; + unsigned int atf_irq_num; + unsigned int devinfo[DEVINFO_SIZE]; + unsigned int atf_aee_debug_buf_start; + unsigned int atf_aee_debug_buf_size; +}; + +struct kernel_info { + uint64_t pc; + uint64_t r0; + uint64_t r1; + uint64_t r2; + uint64_t k32_64; +}; + +struct mtk_bl_param_t { + uint64_t bootarg_loc; + uint64_t bootarg_size; + uint64_t bl33_start_addr; + uint64_t tee_info_addr; +}; + +struct mtk_bl31_params { + 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; +}; + +/* Declarations for mtk_plat_common.c */ +uint32_t plat_get_spsr_for_bl32_entry(void); +uint32_t plat_get_spsr_for_bl33_entry(void); +void clean_top_32b_of_param(uint32_t smc_fid, u_register_t *x1, + u_register_t *x2, + u_register_t *x3, + u_register_t *x4); +void bl31_prepare_kernel_entry(uint64_t k32_64); +void enable_ns_access_to_cpuectlr(void); +void boot_to_kernel(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4); +uint64_t get_kernel_info_pc(void); +uint64_t get_kernel_info_r0(void); +uint64_t get_kernel_info_r1(void); +uint64_t get_kernel_info_r2(void); + +extern struct atf_arg_t gteearg; +#endif /* MTK_PLAT_COMMON_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c b/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c new file mode 100644 index 0000000..dab0d45 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Mediatek SiP Service UUID */ +DEFINE_SVC_UUID2(mtk_sip_svc_uid, + 0xa42b58f7, 0x6242, 0x7d4d, 0x80, 0xe5, + 0x8f, 0x95, 0x05, 0x00, 0x0f, 0x3d); + +#pragma weak mediatek_plat_sip_handler +uintptr_t mediatek_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) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +/* + * This function handles Mediatek defined SiP Calls */ +uintptr_t mediatek_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) +{ + uint32_t ns; + + /* if parameter is sent from SMC32. Clean top 32 bits */ + clean_top_32b_of_param(smc_fid, &x1, &x2, &x3, &x4); + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + if (!ns) { + /* SiP SMC service secure world's call */ + ; + } else { + /* SiP SMC service normal world's call */ + switch (smc_fid) { +#if MTK_SIP_SET_AUTHORIZED_SECURE_REG_ENABLE + case MTK_SIP_SET_AUTHORIZED_SECURE_REG: { + /* only use ret here */ + uint64_t ret; + + ret = mt_sip_set_authorized_sreg((uint32_t)x1, + (uint32_t)x2); + SMC_RET1(handle, ret); + } +#endif +#if MTK_SIP_KERNEL_BOOT_ENABLE + case MTK_SIP_KERNEL_BOOT_AARCH32: + boot_to_kernel(x1, x2, x3, x4); + SMC_RET0(handle); +#endif + default: + /* Do nothing in default case */ + break; + } + } + + return mediatek_plat_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + +} + +/* + * This function is responsible for handling all SiP calls from the NS world + */ +uintptr_t sip_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) +{ + switch (smc_fid) { + case SIP_SVC_CALL_COUNT: + /* Return the number of Mediatek SiP Service Calls. */ + SMC_RET1(handle, + MTK_COMMON_SIP_NUM_CALLS + MTK_PLAT_SIP_NUM_CALLS); + + case SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, mtk_sip_svc_uid); + + case SIP_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, MTK_SIP_SVC_VERSION_MAJOR, + MTK_SIP_SVC_VERSION_MINOR); + + default: + return mediatek_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + } +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + mediatek_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + sip_smc_handler +); diff --git a/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h b/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h new file mode 100644 index 0000000..74b17b6 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef MTK_SIP_SVC_H +#define MTK_SIP_SVC_H + +#include + +/* SMC function IDs for SiP Service queries */ +#define SIP_SVC_CALL_COUNT 0x8200ff00 +#define SIP_SVC_UID 0x8200ff01 +/* 0x8200ff02 is reserved */ +#define SIP_SVC_VERSION 0x8200ff03 + +/* Mediatek SiP Service Calls version numbers */ +#define MTK_SIP_SVC_VERSION_MAJOR 0x0 +#define MTK_SIP_SVC_VERSION_MINOR 0x1 + +#define SMC_AARCH64_BIT 0x40000000 + +/* Number of Mediatek SiP Calls implemented */ +#define MTK_COMMON_SIP_NUM_CALLS 4 + +/* Mediatek SiP Service Calls function IDs */ +#define MTK_SIP_SET_AUTHORIZED_SECURE_REG 0x82000001 + +/* For MTK SMC from Secure OS */ +/* 0x82000000 - 0x820000FF & 0xC2000000 - 0xC20000FF */ +#define MTK_SIP_KERNEL_BOOT_AARCH32 0x82000200 +#define MTK_SIP_KERNEL_BOOT_AARCH64 0xC2000200 + +/* VCORE */ +#define MTK_SIP_VCORE_CONTROL_ARCH32 0x82000506 +#define MTK_SIP_VCORE_CONTROL_ARCH64 0xC2000506 + +/* APUSYS SMC call */ +#define MTK_SIP_APUSYS_CONTROL_AARCH32 0x8200051E +#define MTK_SIP_APUSYS_CONTROL_AARCH64 0xC200051E + +/* Mediatek SiP Calls error code */ +enum { + MTK_SIP_E_SUCCESS = 0, + MTK_SIP_E_INVALID_PARAM = -1, + MTK_SIP_E_NOT_SUPPORTED = -2, + MTK_SIP_E_INVALID_RANGE = -3, + MTK_SIP_E_PERMISSION_DENY = -4, + MTK_SIP_E_LOCK_FAIL = -5 +}; + +/* + * This function should be implemented in Mediatek SOC directory. It fullfills + * MTK_SIP_SET_AUTHORIZED_SECURE_REG SiP call by checking the sreg with the + * predefined secure register list, if a match was found, set val to sreg. + * + * Return MTK_SIP_E_SUCCESS on success, and MTK_SIP_E_INVALID_PARAM on failure. + */ +uint64_t mt_sip_set_authorized_sreg(uint32_t sreg, uint32_t val); + +#endif /* MTK_SIP_SVC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/params_setup.c b/arm-trusted-firmware/plat/mediatek/common/params_setup.c new file mode 100644 index 0000000..a9df13e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/params_setup.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static struct bl_aux_gpio_info rst_gpio; + +struct bl_aux_gpio_info *plat_get_mtk_gpio_reset(void) +{ + return &rst_gpio; +} + +static bool mtk_aux_param_handler(struct bl_aux_param_header *param) +{ + /* Store platform parameters for later processing if needed. */ + switch (param->type) { + case BL_AUX_PARAM_MTK_RESET_GPIO: + rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio; + return true; + } + + return false; +} + +void params_early_setup(u_register_t plat_param_from_bl2) +{ + bl_aux_params_parse(plat_param_from_bl2, mtk_aux_param_handler); +} + diff --git a/arm-trusted-firmware/plat/mediatek/common/plat_params.h b/arm-trusted-firmware/plat/mediatek/common/plat_params.h new file mode 100644 index 0000000..828c3dc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/plat_params.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PARAMS_H +#define PLAT_PARAMS_H + +#include + +#include + +struct bl_aux_gpio_info *plat_get_mtk_gpio_reset(void); +void params_early_setup(u_register_t plat_param_from_bl2); + +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S new file mode 100644 index 0000000..aaddb2b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_report_exception + .globl platform_is_primary_cpu + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + + + .macro crash_ram_log + /* + * Check teearg->atf_log_buf_size. + * Exit if atf_log_buf_size equals 0 + */ + adr x2, ptr_atf_crash_flag + ldr x2, [x2] + /* exit if ptr_atf_crash_flag equals NULL */ + cbz x2, exit_putc + + /* + * set atf crash magic number + */ +1: + adr x2, ptr_atf_crash_flag + ldr x2, [x2] + mov_imm x1, 0xdead1abf + /* p_atf_log_ctrl->atf_crash_flag = 0xdead1abf */ + str w1, [x2] + /* can't use w3 return addr, w4, start of buffer addr */ + ldr w2, [x2] + cmp w2, w1 + b.ne 1b + + /* + * get cpu id + */ + mrs x1, mpidr_el1 + /* refer to platform_get_core_pos */ + and x2, x1, #MPIDR_CPU_MASK + and x1, x1, #MPIDR_CLUSTER_MASK + /* x1 = cpu id (cpu id = aff0 + aff1*4 ) */ + add x1, x2, x1, LSR #6 + + adr x2, ptr_atf_except_write_pos_per_cpu + ldr x2, [x2] + /* + * plus (cpu_id * 8)--> + * &p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id] + * x2 = &p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id]; + */ + add x2, x2, x1, LSL # 3 + /* log write */ + /* w1 = p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id] */ + ldr x1, [x2] + /* *x1 = w0--> + * *(p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id]) = c) + */ + strb w0, [x1] + /* w1++ */ + add x1, x1, #1 + /* p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id] = w1 */ + str x1, [x2] +exit_putc: + .endm + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Do not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +func platform_is_primary_cpu + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc platform_is_primary_cpu + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, UART0_BASE + mov_imm x1, UART_CLOCK + mov_imm x2, UART_BAUDRATE + b console_init + ret +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(void) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, UART0_BASE + b console_core_putc + ret +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush(int c) + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, UART0_BASE + b console_core_flush +endfunc plat_crash_console_flush + + /* -------------------------------------------------------- + * void platform_mem_init (void); + * + * Any memory init, relocation to be done before the + * platform boots. Called very early in the boot process. + * -------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S b/arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S new file mode 100644 index 0000000..3d881fc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-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(bl31_entrypoint) + + +MEMORY { + RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_TZRAM_SIZE + RAM2 (rwx): ORIGIN = TZRAM2_BASE, LENGTH = TZRAM2_SIZE +} + + +SECTIONS +{ + . = BL31_BASE; + + ASSERT(. == ALIGN(2048), + "vector base is not aligned on a 2K boundary.") + + __RO_START__ = .; + vector . : { + *(.vectors) + } >RAM + + ASSERT(. == ALIGN(PAGE_SIZE), + "BL31_BASE address is not aligned on a page boundary.") + + ro . : { + *bl31_entrypoint.o(.text*) + *(.text*) + *(.rodata*) + + RODATA_COMMON + + __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 + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + +#ifdef BL31_PROGBITS_LIMIT + ASSERT(. <= BL31_PROGBITS_LIMIT, "BL3-1 progbits has exceeded its limit.") +#endif + + STACK_SECTION >RAM + BSS_SECTION >RAM + __RW_END__ = __BSS_END__; + + ASSERT(. <= BL31_LIMIT, "BL3-1 image has exceeded its limit.") + + XLAT_TABLE_SECTION >RAM2 + +#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__ = .; + /* + * Bakery locks are stored in coherent memory + * + * Each lock's data is contiguous and fully allocated by the compiler + */ + *(bakery_lock) + *(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__ = .; + } >RAM2 +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __BL31_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= TZRAM2_LIMIT, "TZRAM2 image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c new file mode 100644 index 0000000..2051fe7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2016-2018, 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 + +#include +#include +#include +#include +#include + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted SRAM + ******************************************************************************/ +/* + * The next 2 constants identify the extents of the code & RO data 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 + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +IMPORT_SYM(unsigned long, __RO_START__, BL31_RO_BASE); +IMPORT_SYM(unsigned long, __RO_END__, BL31_RO_LIMIT); + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL3-1 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +static const int cci_map[] = { + PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX +}; + +static uint32_t cci_map_length = ARRAY_SIZE(cci_map); + +/* Table of regions to map using the MMU. */ +static const mmap_region_t plat_mmap[] = { + /* for TF text, RO, RW */ + MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(RAM_CONSOLE_BASE & ~(PAGE_SIZE_MASK), RAM_CONSOLE_SIZE, + MT_DEVICE | MT_RW | MT_NS), + { 0 } + +}; + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +#define DEFINE_CONFIGURE_MMU_EL(_el) \ + void plat_configure_mmu_el ## _el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(plat_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el ## _el(0); \ + } + +/* Define EL3 variants of the function initialising the MMU */ +DEFINE_CONFIGURE_MMU_EL(3) + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +void plat_cci_init(void) +{ + /* Initialize CCI driver */ + cci_init(PLAT_MT_CCI_BASE, cci_map, cci_map_length); +} + +void plat_cci_enable(void) +{ + /* + * Enable CCI coherency for this cluster. + * No need for locks as no other cpu is active at the moment. + */ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); +} + +void plat_cci_disable(void) +{ + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); +} + + +static void platform_setup_cpu(void) +{ + /* setup big cores */ + mmio_write_32((uintptr_t)&mt6795_mcucfg->mp1_config_res, + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK | + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK | + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK | + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK | + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK); + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_miscdbg, MP1_AINACTS); + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_clkenm_div, + MP1_SW_CG_GEN); + mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp1_rst_ctl, + MP1_L2RSTDISABLE); + + /* set big cores arm64 boot mode */ + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_cpucfg, + MP1_CPUCFG_64BIT); + + /* set LITTLE cores arm64 boot mode */ + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp0_rv_addr[0].rv_addr_hw, + MP0_CPUCFG_64BIT); +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Perform any BL3-1 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + * BL2 has flushed this information to memory, so we are guaranteed to pick up + * good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct mtk_bl_param_t *pmtk_bl_param = (struct mtk_bl_param_t *)arg0; + struct atf_arg_t *teearg; + unsigned long long normal_base; + unsigned long long atf_base; + + assert(pmtk_bl_param != NULL); + /* + * Mediatek preloader(i.e, BL2) is in 32 bit state, high 32bits + * of 64 bit GP registers are UNKNOWN if CPU warm reset from 32 bit + * to 64 bit state. So we need to clear high 32bit, + * which may be random value. + */ + pmtk_bl_param = + (struct mtk_bl_param_t *)((uint64_t)pmtk_bl_param & 0x00000000ffffffff); + + teearg = (struct atf_arg_t *)pmtk_bl_param->tee_info_addr; + + console_init(teearg->atf_log_port, UART_CLOCK, UART_BAUDRATE); + memcpy((void *)>eearg, (void *)teearg, sizeof(struct atf_arg_t)); + + normal_base = 0; + /* in ATF boot time, timer for cntpct_el0 is not initialized + * so it will not count now. + */ + atf_base = read_cntpct_el0(); + sched_clock_init(normal_base, atf_base); + + VERBOSE("bl31_setup\n"); + + /* Populate entry point information for BL3-2 and BL3-3 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL3-1 where the non-trusted software image + * is located and the entry state information + */ + /* BL33_START_ADDRESS */ + bl33_image_ep_info.pc = pmtk_bl_param->bl33_start_addr; + bl33_image_ep_info.spsr = plat_get_spsr_for_bl33_entry(); + bl33_image_ep_info.args.arg4 = pmtk_bl_param->bootarg_loc; + bl33_image_ep_info.args.arg5 = pmtk_bl_param->bootarg_size; + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ + +void bl31_platform_setup(void) +{ + platform_setup_cpu(); + + generic_delay_timer_init(); + + plat_mt_gic_driver_init(); + /* Initialize the gic cpu and distributor interfaces */ + plat_mt_gic_init(); + + /* Topologies are best known to the platform. */ + mt_setup_topology(); +} +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + * Init MTK propiartary log buffer control field. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + /* Enable non-secure access to CCI-400 registers */ + mmio_write_32(CCI400_BASE + CCI_SEC_ACCESS_OFFSET, 0x1); + + plat_cci_init(); + plat_cci_enable(); + + if (gteearg.atf_log_buf_size != 0) { + INFO("mmap atf buffer : 0x%x, 0x%x\n\r", + gteearg.atf_log_buf_start, + gteearg.atf_log_buf_size); + + mmap_add_region( + gteearg.atf_log_buf_start & + ~(PAGE_SIZE_2MB_MASK), + gteearg.atf_log_buf_start & + ~(PAGE_SIZE_2MB_MASK), + PAGE_SIZE_2MB, + MT_DEVICE | MT_RW | MT_NS); + + INFO("mmap atf buffer (force 2MB aligned):0x%x, 0x%x\n", + (gteearg.atf_log_buf_start & ~(PAGE_SIZE_2MB_MASK)), + PAGE_SIZE_2MB); + } + /* + * add TZRAM_BASE to memory map + * then set RO and COHERENT to different attribute + */ + plat_configure_mmu_el3( + (TZRAM_BASE & ~(PAGE_SIZE_MASK)), + (TZRAM_SIZE & ~(PAGE_SIZE_MASK)), + (BL31_RO_BASE & ~(PAGE_SIZE_MASK)), + BL31_RO_LIMIT, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); + /* Initialize for ATF log buffer */ + if (gteearg.atf_log_buf_size != 0) { + gteearg.atf_aee_debug_buf_size = ATF_AEE_BUFFER_SIZE; + gteearg.atf_aee_debug_buf_start = + gteearg.atf_log_buf_start + + gteearg.atf_log_buf_size - ATF_AEE_BUFFER_SIZE; + INFO("ATF log service is registered (0x%x, aee:0x%x)\n", + gteearg.atf_log_buf_start, + gteearg.atf_aee_debug_buf_start); + } else{ + gteearg.atf_aee_debug_buf_size = 0; + gteearg.atf_aee_debug_buf_start = 0; + } + + /* Platform code before bl31_main */ + /* compatible to the earlier chipset */ + + /* Show to ATF log buffer & UART */ + INFO("BL3-1: %s\n", version_string); + INFO("BL3-1: %s\n", build_message); + +} +#if 0 +/* MTK Define */ +#define ACTLR_CPUECTLR_BIT (1 << 1) + +void enable_ns_access_to_cpuectlr(void) +{ + unsigned int next_actlr; + + + /* ACTLR_EL1 do not implement CUPECTLR */ + next_actlr = read_actlr_el2(); + next_actlr |= ACTLR_CPUECTLR_BIT; + write_actlr_el2(next_actlr); + + next_actlr = read_actlr_el3(); + next_actlr |= ACTLR_CPUECTLR_BIT; + write_actlr_el3(next_actlr); +} +#endif +/******************************************************************************* + * This function prepare boot argument for 64 bit kernel entry + ******************************************************************************/ +static entry_point_info_t *bl31_plat_get_next_kernel64_ep_info(void) +{ + entry_point_info_t *next_image_info; + unsigned int mode; + + mode = 0; + + /* Kernel image is always non-secured */ + next_image_info = &bl33_image_ep_info; + + /* Figure out what mode we enter the non-secure world in */ + if (el_implemented(2) != EL_IMPL_NONE) { + INFO("Kernel_EL2\n"); + mode = MODE_EL2; + } else{ + INFO("Kernel_EL1\n"); + mode = MODE_EL1; + } + + INFO("Kernel is 64Bit\n"); + next_image_info->spsr = + SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + next_image_info->pc = get_kernel_info_pc(); + next_image_info->args.arg0 = get_kernel_info_r0(); + next_image_info->args.arg1 = get_kernel_info_r1(); + + INFO("pc=0x%lx, r0=0x%lx, r1=0x%lx\n", + next_image_info->pc, + next_image_info->args.arg0, + next_image_info->args.arg1); + + + SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * This function prepare boot argument for 32 bit kernel entry + ******************************************************************************/ +static entry_point_info_t *bl31_plat_get_next_kernel32_ep_info(void) +{ + entry_point_info_t *next_image_info; + unsigned int mode; + + mode = 0; + + /* Kernel image is always non-secured */ + next_image_info = &bl33_image_ep_info; + + /* Figure out what mode we enter the non-secure world in */ + mode = MODE32_hyp; + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + + INFO("Kernel is 32Bit\n"); + next_image_info->spsr = + SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE, + (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT)); + next_image_info->pc = get_kernel_info_pc(); + next_image_info->args.arg0 = get_kernel_info_r0(); + next_image_info->args.arg1 = get_kernel_info_r1(); + next_image_info->args.arg2 = get_kernel_info_r2(); + + INFO("pc=0x%lx, r0=0x%lx, r1=0x%lx, r2=0x%lx\n", + next_image_info->pc, + next_image_info->args.arg0, + next_image_info->args.arg1, + next_image_info->args.arg2); + + + SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * This function prepare boot argument for kernel entrypoint + ******************************************************************************/ +void bl31_prepare_kernel_entry(uint64_t k32_64) +{ + entry_point_info_t *next_image_info; + uint32_t image_type; + + /* Determine which image to execute next */ + /* image_type = bl31_get_next_image_type(); */ + image_type = NON_SECURE; + + /* Program EL3 registers to enable entry into the next EL */ + if (k32_64 == 0) + next_image_info = bl31_plat_get_next_kernel32_ep_info(); + else + next_image_info = bl31_plat_get_next_kernel64_ep_info(); + + assert(next_image_info); + assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr)); + + INFO("BL3-1: Preparing for EL3 exit to %s world, Kernel\n", + (image_type == SECURE) ? "secure" : "normal"); + INFO("BL3-1: Next image address = 0x%llx\n", + (unsigned long long) next_image_info->pc); + INFO("BL3-1: Next image spsr = 0x%x\n", next_image_info->spsr); + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(image_type); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c b/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c new file mode 100644 index 0000000..3696f8e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include + +#define CPUXGPT_BASE 0x10200000 +#define INDEX_BASE (CPUXGPT_BASE+0x0674) +#define CTL_BASE (CPUXGPT_BASE+0x0670) + +uint64_t normal_time_base; +uint64_t atf_time_base; + +void sched_clock_init(uint64_t normal_base, uint64_t atf_base) +{ + normal_time_base = normal_base; + atf_time_base = atf_base; +} + +uint64_t sched_clock(void) +{ + uint64_t cval; + + cval = (((read_cntpct_el0() - atf_time_base)*1000)/ + SYS_COUNTER_FREQ_IN_MHZ) + normal_time_base; + return cval; +} + +/* + * Return: 0 - Trying to disable the CPUXGPT control bit, + * and not allowed to disable it. + * Return: 1 - reg_addr is not realted to disable the control bit. + */ +unsigned char check_cpuxgpt_write_permission(unsigned int reg_addr, + unsigned int reg_value) +{ + unsigned int idx; + unsigned int ctl_val; + + if (reg_addr == CTL_BASE) { + idx = mmio_read_32(INDEX_BASE); + + /* idx 0: CPUXGPT system control */ + if (idx == 0) { + ctl_val = mmio_read_32(CTL_BASE); + if (ctl_val & 1) { + /* + * if enable bit already set, + * then bit 0 is not allow to set as 0 + */ + if (!(reg_value & 1)) + return 0; + } + } + } + return 1; +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h b/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h new file mode 100644 index 0000000..84df081 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_CPUXGPT_H +#define MT_CPUXGPT_H + +/* REG */ +#define INDEX_CTL_REG 0x000 +#define INDEX_STA_REG 0x004 +#define INDEX_CNT_L_INIT 0x008 +#define INDEX_CNT_H_INIT 0x00C + +/* CTL_REG SET */ +#define EN_CPUXGPT 0x01 +#define EN_AHLT_DEBUG 0x02 +#define CLK_DIV1 (0x1 << 8) +#define CLK_DIV2 (0x2 << 8) +#define CLK_DIV4 (0x4 << 8) +#define CLK_DIV_MASK (~(0x7<<8)) + +void generic_timer_backup(void); +void sched_clock_init(uint64_t normal_base, uint64_t atf_base); +uint64_t sched_clock(void); + +#endif /* MT_CPUXGPT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h new file mode 100644 index 0000000..21c5394 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCUCFG_H +#define MCUCFG_H + +#include + +#include + +struct mt6795_mcucfg_regs { + uint32_t mp0_ca7l_cache_config; + struct { + uint32_t mem_delsel0; + uint32_t mem_delsel1; + } mp0_cpu[4]; + uint32_t mp0_cache_mem_delsel0; + uint32_t mp0_cache_mem_delsel1; + uint32_t mp0_axi_config; + uint32_t mp0_misc_config[2]; + struct { + uint32_t rv_addr_lw; + uint32_t rv_addr_hw; + } mp0_rv_addr[4]; + uint32_t mp0_ca7l_cfg_dis; + uint32_t mp0_ca7l_clken_ctrl; + uint32_t mp0_ca7l_rst_ctrl; + uint32_t mp0_ca7l_misc_config; + uint32_t mp0_ca7l_dbg_pwr_ctrl; + uint32_t mp0_rw_rsvd0; + uint32_t mp0_rw_rsvd1; + uint32_t mp0_ro_rsvd; + uint32_t reserved0_0[100]; + uint32_t mp1_cpucfg; + uint32_t mp1_miscdbg; + uint32_t reserved0_1[13]; + uint32_t mp1_rst_ctl; + uint32_t mp1_clkenm_div; + uint32_t reserved0_2[7]; + uint32_t mp1_config_res; + uint32_t reserved0_3[13]; + struct { + uint32_t rv_addr_lw; + uint32_t rv_addr_hw; + } mp1_rv_addr[2]; + uint32_t reserved0_4[84]; + uint32_t mp0_rst_status; /* 0x400 */ + uint32_t mp0_dbg_ctrl; + uint32_t mp0_dbg_flag; + uint32_t mp0_ca7l_ir_mon; + struct { + uint32_t pc_lw; + uint32_t pc_hw; + uint32_t fp_arch32; + uint32_t sp_arch32; + uint32_t fp_arch64_lw; + uint32_t fp_arch64_hw; + uint32_t sp_arch64_lw; + uint32_t sp_arch64_hw; + } mp0_dbg_core[4]; + uint32_t dfd_ctrl; + uint32_t dfd_cnt_l; + uint32_t dfd_cnt_h; + uint32_t misccfg_mp0_rw_rsvd; + uint32_t misccfg_sec_vio_status0; + uint32_t misccfg_sec_vio_status1; + uint32_t reserved1[22]; + uint32_t misccfg_rw_rsvd; /* 0x500 */ + uint32_t mcusys_dbg_mon_sel_a; + uint32_t mcusys_dbg_mon; + uint32_t reserved2[61]; + uint32_t mcusys_config_a; /* 0x600 */ + uint32_t mcusys_config1_a; + uint32_t mcusys_gic_peribase_a; + uint32_t reserved3; + uint32_t sec_range0_start; /* 0x610 */ + uint32_t sec_range0_end; + uint32_t sec_range_enable; + uint32_t reserved4; + uint32_t int_pol_ctl[8]; /* 0x620 */ + uint32_t aclken_div; /* 0x640 */ + uint32_t pclken_div; + uint32_t l2c_sram_ctrl; + uint32_t armpll_jit_ctrl; + uint32_t cci_addrmap; /* 0x650 */ + uint32_t cci_config; + uint32_t cci_periphbase; + uint32_t cci_nevntcntovfl; + uint32_t cci_clk_ctrl; /* 0x660 */ + uint32_t cci_acel_s1_ctrl; + uint32_t bus_fabric_dcm_ctrl; + uint32_t reserved5; + uint32_t xgpt_ctl; /* 0x670 */ + uint32_t xgpt_idx; + uint32_t ptpod2_ctl0; + uint32_t ptpod2_ctl1; + uint32_t mcusys_revid; + uint32_t mcusys_rw_rsvd0; + uint32_t mcusys_rw_rsvd1; +}; + +static struct mt6795_mcucfg_regs *const mt6795_mcucfg = (void *)MCUCFG_BASE; + +/* cpu boot mode */ +#define MP0_CPUCFG_64BIT_SHIFT 12 +#define MP1_CPUCFG_64BIT_SHIFT 28 +#define MP0_CPUCFG_64BIT (U(0xf) << MP0_CPUCFG_64BIT_SHIFT) +#define MP1_CPUCFG_64BIT (U(0xf) << MP1_CPUCFG_64BIT_SHIFT) + +/* scu related */ +enum { + MP0_ACINACTM_SHIFT = 4, + MP1_ACINACTM_SHIFT = 0, + MP0_ACINACTM = 1 << MP0_ACINACTM_SHIFT, + MP1_ACINACTM = 1 << MP1_ACINACTM_SHIFT +}; + +enum { + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16, + + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT +}; + +enum { + MP1_AINACTS_SHIFT = 4, + MP1_AINACTS = 1 << MP1_AINACTS_SHIFT +}; + +enum { + MP1_SW_CG_GEN_SHIFT = 12, + MP1_SW_CG_GEN = 1 << MP1_SW_CG_GEN_SHIFT +}; + +enum { + MP1_L2RSTDISABLE_SHIFT = 14, + MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT +}; + +#endif /* MCUCFG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S new file mode 100644 index 0000000..d198fdc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL3-1. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x16, BASE_GICD_BASE + mov_imm x17, BASE_GICC_BASE + /* 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 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 + bl asm_print_hex + + 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 + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* ------------------------------------------------ + * The below macro prints out relevant interconnect + * registers whenever an unhandled exception is + * taken in BL3-1. + * Clobbers: x0 - x9, sp + * ------------------------------------------------ + */ + .macro plat_print_interconnect_regs + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MT_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_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MT_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 diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h new file mode 100644 index 0000000..f7450ca --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#include + +#include + +void plat_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long, + unsigned long, + unsigned long, + unsigned long); + +void plat_cci_init(void); +void plat_cci_enable(void); +void plat_cci_disable(void); + +/* Declarations for plat_mt_gic.c */ +void plat_mt_gic_init(void); + +/* Declarations for plat_topology.c */ +int mt_setup_topology(void); +void plat_delay_timer_init(void); + +void plat_mt_gic_driver_init(void); +void plat_mt_gic_init(void); +void plat_mt_gic_cpuif_enable(void); +void plat_mt_gic_cpuif_disable(void); +void plat_mt_gic_pcpu_init(void); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h new file mode 100644 index 0000000..b9a1363 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +/******************************************************************************* + * Plat SiP function constants + ******************************************************************************/ +#define MTK_PLAT_SIP_NUM_CALLS 0 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h new file mode 100644 index 0000000..b353a3d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#define PLAT_PRIMARY_CPU 0x0 + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define MT_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define IO_PHYS (0x10000000) +#define INFRACFG_AO_BASE (IO_PHYS + 0x1000) +#define MCUCFG_BASE (IO_PHYS + 0x200000) +#define PERI_BASE (IO_PHYS + 0x1000000) + + +#define GPIO_BASE (IO_PHYS + 0x370000) +#define SPM_BASE (IO_PHYS + 0x6000) +#define RGU_BASE (MCUCFG_BASE + 0x11000) +#define PMIC_WRAP_BASE (IO_PHYS + 0x10000) + +#define TRNG_base (MCUCFG_BASE + 0x230000) +#define MT_GIC_BASE (0x10220000) +#define MCU_SYS_SIZE (0x700000) +#define PLAT_MT_CCI_BASE (IO_PHYS + 0x390000) + +/* Aggregate of all devices in the first GB */ +#define MTK_DEV_RNG0_BASE IO_PHYS +#define MTK_DEV_RNG0_SIZE 0x400000 +#define MTK_DEV_RNG1_BASE (PERI_BASE) +#define MTK_DEV_RNG1_SIZE 0x4000000 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define UART0_BASE (PERI_BASE + 0x2000) + +#define UART_BAUDRATE (921600) +#define UART_CLOCK (26000000) + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 13000000 +#define SYS_COUNTER_FREQ_IN_MHZ (SYS_COUNTER_FREQ_IN_TICKS/1000000) + +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base MTK_platform compatible GIC memory map */ +#define BASE_GICD_BASE (MT_GIC_BASE+0x1000) +#define BASE_GICC_BASE (MT_GIC_BASE + 0x2000) +#define BASE_GICR_BASE (MT_GIC_BASE + 0x200000) +#define BASE_GICH_BASE (MT_GIC_BASE + 0x4000) +#define BASE_GICV_BASE (MT_GIC_BASE + 0x6000) + +#define INT_POL_CTL0 0x10200620 +#define GIC_PRIVATE_SIGNALS (32) + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX 4 +#define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX 3 + +/******************************************************************************* + * WDT Registers + ******************************************************************************/ +#define MTK_WDT_BASE (RGU_BASE) +#define MTK_WDT_SIZE (0x1000) +#define MTK_WDT_MODE (MTK_WDT_BASE+0x0000) +#define MTK_WDT_LENGTH (MTK_WDT_BASE+0x0004) +#define MTK_WDT_RESTART (MTK_WDT_BASE+0x0008) +#define MTK_WDT_STATUS (MTK_WDT_BASE+0x000C) +#define MTK_WDT_INTERVAL (MTK_WDT_BASE+0x0010) +#define MTK_WDT_SWRST (MTK_WDT_BASE+0x0014) +#define MTK_WDT_SWSYSRST (MTK_WDT_BASE+0x0018) +#define MTK_WDT_NONRST_REG (MTK_WDT_BASE+0x0020) +#define MTK_WDT_NONRST_REG2 (MTK_WDT_BASE+0x0024) +#define MTK_WDT_REQ_MODE (MTK_WDT_BASE+0x0030) +#define MTK_WDT_REQ_IRQ_EN (MTK_WDT_BASE+0x0034) +#define MTK_WDT_DEBUG_CTL (MTK_WDT_BASE+0x0040) + +/*WDT_STATUS*/ +#define MTK_WDT_STATUS_HWWDT_RST (0x80000000) +#define MTK_WDT_STATUS_SWWDT_RST (0x40000000) +#define MTK_WDT_STATUS_IRQWDT_RST (0x20000000) +#define MTK_WDT_STATUS_DEBUGWDT_RST (0x00080000) +#define MTK_WDT_STATUS_SPMWDT_RST (0x0002) +#define MTK_WDT_STATUS_SPM_THERMAL_RST (0x0001) +#define MTK_WDT_STATUS_THERMAL_DIRECT_RST (1<<18) +#define MTK_WDT_STATUS_SECURITY_RST (1<<28) + +#define MTK_WDT_MODE_DUAL_MODE 0x0040 +#define MTK_WDT_MODE_IRQ 0x0008 +#define MTK_WDT_MODE_KEY 0x22000000 +#define MTK_WDT_MODE_EXTEN 0x0004 +#define MTK_WDT_SWRST_KEY 0x1209 +#define MTK_WDT_RESTART_KEY (0x1971) + +/* FIQ platform related define */ +#define MT_IRQ_SEC_SGI_0 8 +#define MT_IRQ_SEC_SGI_1 9 +#define MT_IRQ_SEC_SGI_2 10 +#define MT_IRQ_SEC_SGI_3 11 +#define MT_IRQ_SEC_SGI_4 12 +#define MT_IRQ_SEC_SGI_5 13 +#define MT_IRQ_SEC_SGI_6 14 +#define MT_IRQ_SEC_SGI_7 15 + +#define FIQ_SMP_CALL_SGI MT_IRQ_SEC_SGI_5 + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL1) +#define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +#define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x800 +#elif defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" +#define PLAT_MAX_PWR_LVL U(2) /* MPIDR_AFFLVL2 */ + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* ATF Argument */ +#define ATF_ARG_SIZE (0x800) + +/* TF txet, ro, rw, internal SRAM, Size: release: 80KB, debug: 92KB */ +#define TZRAM_BASE (0x110000) +#if DEBUG +#define TZRAM_SIZE (0x1C400) +#else +#define TZRAM_SIZE (0x1C400) +#endif +#define TZRAM2_BASE 0x00100000 +#define TZRAM2_SIZE 0xDC00 +#define TZRAM2_LIMIT (TZRAM2_BASE + TZRAM2_SIZE) + +#define RAM_CONSOLE_BASE 0x0012D000 +#define RAM_CONSOLE_SIZE 0x00001000 +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL3-1 debug size plus a + * little space for growth. + */ +#define BL31_BASE (TZRAM_BASE + 0x1000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) +#define BSS1_STACK_LIMIT (TZRAM_BASE + TZRAM_SIZE) +#define BL31_TZRAM_SIZE (TZRAM_SIZE - ATF_ARG_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 7 +#define MAX_MMAP_REGIONS 16 + + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define CCI400_BASE 0x10390000 +#define CCI400_SL_IFACE_CLUSTER0 4 +#define CCI400_SL_IFACE_CLUSTER1 3 +#define CCI400_SL_IFACE_INDEX(mpidr) (mpidr & MPIDR_CLUSTER_MASK ? \ + CCI400_SL_IFACE_CLUSTER1 : \ + CCI400_SL_IFACE_CLUSTER0) +#define CCI_SEC_ACCESS_OFFSET (0x8) + + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define BL32_BASE (0x0) + +/* + * Load address of BL3-3 for this platform port + */ +#define LK_SIZE_LIMIT (0x100000) +#define PLAT_MTK_NS_IMAGE_OFFSET (0x41E00000) +/* 16KB */ +#define ATF_AEE_BUFFER_SIZE (0x4000) +#define PAGE_SIZE_2MB_MASK (PAGE_SIZE_2MB - 1) +#define IS_PAGE_2MB_ALIGNED(addr) (((addr) & PAGE_SIZE_2MB_MASK) == 0) +#define PAGE_SIZE_2MB (1 << PAGE_SIZE_2MB_SHIFT) +#define PAGE_SIZE_2MB_SHIFT TWO_MB_SHIFT + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h new file mode 100644 index 0000000..8c98dbd --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POWER_TRACER_H +#define POWER_TRACER_H + +#define CPU_UP 0 +#define CPU_DOWN 1 +#define CPU_SUSPEND 2 +#define CLUSTER_UP 3 +#define CLUSTER_DOWN 4 +#define CLUSTER_SUSPEND 5 + +void trace_power_flow(unsigned long mpidr, unsigned char mode); + +#endif /* POWER_TRACER_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h new file mode 100644 index 0000000..625418a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCU_H +#define SCU_H + +void disable_scu(unsigned long mpidr); +void enable_scu(unsigned long mpidr); + +#endif /* SCU_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h new file mode 100644 index 0000000..5227e1d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_H +#define SPM_H + +#define SPM_POWERON_CONFIG_SET (SPM_BASE + 0x000) +#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x010) +#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x014) +#define SPM_CLK_SETTLE (SPM_BASE + 0x100) +#define SPM_CA7_CPU1_PWR_CON (SPM_BASE + 0x218) +#define SPM_CA7_CPU2_PWR_CON (SPM_BASE + 0x21c) +#define SPM_CA7_CPU3_PWR_CON (SPM_BASE + 0x220) +#define SPM_CA7_CPU1_L1_PDN (SPM_BASE + 0x264) +#define SPM_CA7_CPU2_L1_PDN (SPM_BASE + 0x26c) +#define SPM_CA7_CPU3_L1_PDN (SPM_BASE + 0x274) +#define SPM_MD32_SRAM_CON (SPM_BASE + 0x2c8) +#define SPM_PCM_CON0 (SPM_BASE + 0x310) +#define SPM_PCM_CON1 (SPM_BASE + 0x314) +#define SPM_PCM_IM_PTR (SPM_BASE + 0x318) +#define SPM_PCM_IM_LEN (SPM_BASE + 0x31c) +#define SPM_PCM_REG_DATA_INI (SPM_BASE + 0x320) +#define SPM_PCM_EVENT_VECTOR0 (SPM_BASE + 0x340) +#define SPM_PCM_EVENT_VECTOR1 (SPM_BASE + 0x344) +#define SPM_PCM_EVENT_VECTOR2 (SPM_BASE + 0x348) +#define SPM_PCM_EVENT_VECTOR3 (SPM_BASE + 0x34c) +#define SPM_PCM_MAS_PAUSE_MASK (SPM_BASE + 0x354) +#define SPM_PCM_PWR_IO_EN (SPM_BASE + 0x358) +#define SPM_PCM_TIMER_VAL (SPM_BASE + 0x35c) +#define SPM_PCM_TIMER_OUT (SPM_BASE + 0x360) +#define SPM_PCM_REG0_DATA (SPM_BASE + 0x380) +#define SPM_PCM_REG1_DATA (SPM_BASE + 0x384) +#define SPM_PCM_REG2_DATA (SPM_BASE + 0x388) +#define SPM_PCM_REG3_DATA (SPM_BASE + 0x38c) +#define SPM_PCM_REG4_DATA (SPM_BASE + 0x390) +#define SPM_PCM_REG5_DATA (SPM_BASE + 0x394) +#define SPM_PCM_REG6_DATA (SPM_BASE + 0x398) +#define SPM_PCM_REG7_DATA (SPM_BASE + 0x39c) +#define SPM_PCM_REG8_DATA (SPM_BASE + 0x3a0) +#define SPM_PCM_REG9_DATA (SPM_BASE + 0x3a4) +#define SPM_PCM_REG10_DATA (SPM_BASE + 0x3a8) +#define SPM_PCM_REG11_DATA (SPM_BASE + 0x3ac) +#define SPM_PCM_REG12_DATA (SPM_BASE + 0x3b0) +#define SPM_PCM_REG13_DATA (SPM_BASE + 0x3b4) +#define SPM_PCM_REG14_DATA (SPM_BASE + 0x3b8) +#define SPM_PCM_REG15_DATA (SPM_BASE + 0x3bc) +#define SPM_PCM_EVENT_REG_STA (SPM_BASE + 0x3c0) +#define SPM_PCM_FSM_STA (SPM_BASE + 0x3c4) +#define SPM_PCM_IM_HOST_RW_PTR (SPM_BASE + 0x3c8) +#define SPM_PCM_IM_HOST_RW_DAT (SPM_BASE + 0x3cc) +#define SPM_PCM_EVENT_VECTOR4 (SPM_BASE + 0x3d0) +#define SPM_PCM_EVENT_VECTOR5 (SPM_BASE + 0x3d4) +#define SPM_PCM_EVENT_VECTOR6 (SPM_BASE + 0x3d8) +#define SPM_PCM_EVENT_VECTOR7 (SPM_BASE + 0x3dc) +#define SPM_PCM_SW_INT_SET (SPM_BASE + 0x3e0) +#define SPM_PCM_SW_INT_CLEAR (SPM_BASE + 0x3e4) +#define SPM_CLK_CON (SPM_BASE + 0x400) +#define SPM_SLEEP_PTPOD2_CON (SPM_BASE + 0x408) +#define SPM_APMCU_PWRCTL (SPM_BASE + 0x600) +#define SPM_AP_DVFS_CON_SET (SPM_BASE + 0x604) +#define SPM_AP_STANBY_CON (SPM_BASE + 0x608) +#define SPM_PWR_STATUS (SPM_BASE + 0x60c) +#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x610) +#define SPM_AP_BSI_REQ (SPM_BASE + 0x614) +#define SPM_SLEEP_TIMER_STA (SPM_BASE + 0x720) +#define SPM_SLEEP_WAKEUP_EVENT_MASK (SPM_BASE + 0x810) +#define SPM_SLEEP_CPU_WAKEUP_EVENT (SPM_BASE + 0x814) +#define SPM_SLEEP_MD32_WAKEUP_EVENT_MASK (SPM_BASE + 0x818) +#define SPM_PCM_WDT_TIMER_VAL (SPM_BASE + 0x824) +#define SPM_PCM_WDT_TIMER_OUT (SPM_BASE + 0x828) +#define SPM_PCM_MD32_MAILBOX (SPM_BASE + 0x830) +#define SPM_PCM_MD32_IRQ (SPM_BASE + 0x834) +#define SPM_SLEEP_ISR_MASK (SPM_BASE + 0x900) +#define SPM_SLEEP_ISR_STATUS (SPM_BASE + 0x904) +#define SPM_SLEEP_ISR_RAW_STA (SPM_BASE + 0x910) +#define SPM_SLEEP_MD32_ISR_RAW_STA (SPM_BASE + 0x914) +#define SPM_SLEEP_WAKEUP_MISC (SPM_BASE + 0x918) +#define SPM_SLEEP_BUS_PROTECT_RDY (SPM_BASE + 0x91c) +#define SPM_SLEEP_SUBSYS_IDLE_STA (SPM_BASE + 0x920) +#define SPM_PCM_RESERVE (SPM_BASE + 0xb00) +#define SPM_PCM_RESERVE2 (SPM_BASE + 0xb04) +#define SPM_PCM_FLAGS (SPM_BASE + 0xb08) +#define SPM_PCM_SRC_REQ (SPM_BASE + 0xb0c) +#define SPM_PCM_DEBUG_CON (SPM_BASE + 0xb20) +#define SPM_CA7_CPU0_IRQ_MASK (SPM_BASE + 0xb30) +#define SPM_CA7_CPU1_IRQ_MASK (SPM_BASE + 0xb34) +#define SPM_CA7_CPU2_IRQ_MASK (SPM_BASE + 0xb38) +#define SPM_CA7_CPU3_IRQ_MASK (SPM_BASE + 0xb3c) +#define SPM_CA15_CPU0_IRQ_MASK (SPM_BASE + 0xb40) +#define SPM_CA15_CPU1_IRQ_MASK (SPM_BASE + 0xb44) +#define SPM_CA15_CPU2_IRQ_MASK (SPM_BASE + 0xb48) +#define SPM_CA15_CPU3_IRQ_MASK (SPM_BASE + 0xb4c) +#define SPM_PCM_PASR_DPD_0 (SPM_BASE + 0xb60) +#define SPM_PCM_PASR_DPD_1 (SPM_BASE + 0xb64) +#define SPM_PCM_PASR_DPD_2 (SPM_BASE + 0xb68) +#define SPM_PCM_PASR_DPD_3 (SPM_BASE + 0xb6c) +#define SPM_SLEEP_CA7_WFI0_EN (SPM_BASE + 0xf00) +#define SPM_SLEEP_CA7_WFI1_EN (SPM_BASE + 0xf04) +#define SPM_SLEEP_CA7_WFI2_EN (SPM_BASE + 0xf08) +#define SPM_SLEEP_CA7_WFI3_EN (SPM_BASE + 0xf0c) +#define SPM_SLEEP_CA15_WFI0_EN (SPM_BASE + 0xf10) +#define SPM_SLEEP_CA15_WFI1_EN (SPM_BASE + 0xf14) +#define SPM_SLEEP_CA15_WFI2_EN (SPM_BASE + 0xf18) +#define SPM_SLEEP_CA15_WFI3_EN (SPM_BASE + 0xf1c) + +#define SPM_PROJECT_CODE 0xb16 + +#define SPM_REGWR_EN (1U << 0) +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) + +#define SPM_CPU_PDN_DIS (1U << 0) +#define SPM_INFRA_PDN_DIS (1U << 1) +#define SPM_DDRPHY_PDN_DIS (1U << 2) +#define SPM_DUALVCORE_PDN_DIS (1U << 3) +#define SPM_PASR_DIS (1U << 4) +#define SPM_DPD_DIS (1U << 5) +#define SPM_SODI_DIS (1U << 6) +#define SPM_MEMPLL_RESET (1U << 7) +#define SPM_MAINPLL_PDN_DIS (1U << 8) +#define SPM_CPU_DVS_DIS (1U << 9) +#define SPM_CPU_DORMANT (1U << 10) +#define SPM_EXT_VSEL_GPIO103 (1U << 11) +#define SPM_DDR_HIGH_SPEED (1U << 12) +#define SPM_OPT (1U << 13) + +#define POWER_ON_VAL1_DEF 0x01011820 +#define PCM_FSM_STA_DEF 0x48490 +#define PCM_END_FSM_STA_DEF 0x08490 +#define PCM_END_FSM_STA_MASK 0x3fff0 +#define PCM_HANDSHAKE_SEND1 0xbeefbeef + +#define PCM_WDT_TIMEOUT (30 * 32768) +#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT) + +#define CON0_PCM_KICK (1U << 0) +#define CON0_IM_KICK (1U << 1) +#define CON0_IM_SLEEP_DVS (1U << 3) +#define CON0_PCM_SW_RESET (1U << 15) +#define CON0_CFG_KEY (SPM_PROJECT_CODE << 16) + +#define CON1_IM_SLAVE (1U << 0) +#define CON1_MIF_APBEN (1U << 3) +#define CON1_PCM_TIMER_EN (1U << 5) +#define CON1_IM_NONRP_EN (1U << 6) +#define CON1_PCM_WDT_EN (1U << 8) +#define CON1_PCM_WDT_WAKE_MODE (1U << 9) +#define CON1_SPM_SRAM_SLP_B (1U << 10) +#define CON1_SPM_SRAM_ISO_B (1U << 11) +#define CON1_EVENT_LOCK_EN (1U << 12) +#define CON1_CFG_KEY (SPM_PROJECT_CODE << 16) + +#define PCM_PWRIO_EN_R0 (1U << 0) +#define PCM_PWRIO_EN_R7 (1U << 7) +#define PCM_RF_SYNC_R0 (1U << 16) +#define PCM_RF_SYNC_R2 (1U << 18) +#define PCM_RF_SYNC_R6 (1U << 22) +#define PCM_RF_SYNC_R7 (1U << 23) + +#define CC_SYSCLK0_EN_0 (1U << 0) +#define CC_SYSCLK0_EN_1 (1U << 1) +#define CC_SYSCLK1_EN_0 (1U << 2) +#define CC_SYSCLK1_EN_1 (1U << 3) +#define CC_SYSSETTLE_SEL (1U << 4) +#define CC_LOCK_INFRA_DCM (1U << 5) +#define CC_SRCLKENA_MASK_0 (1U << 6) +#define CC_CXO32K_RM_EN_MD1 (1U << 9) +#define CC_CXO32K_RM_EN_MD2 (1U << 10) +#define CC_CLKSQ1_SEL (1U << 12) +#define CC_DISABLE_DORM_PWR (1U << 14) +#define CC_MD32_DCM_EN (1U << 18) + +#define WFI_OP_AND 1 +#define WFI_OP_OR 0 + +#define WAKE_MISC_PCM_TIMER (1U << 19) +#define WAKE_MISC_CPU_WAKE (1U << 20) + +/* define WAKE_SRC_XXX */ +#define WAKE_SRC_SPM_MERGE (1 << 0) +#define WAKE_SRC_KP (1 << 2) +#define WAKE_SRC_WDT (1 << 3) +#define WAKE_SRC_GPT (1 << 4) +#define WAKE_SRC_EINT (1 << 6) +#define WAKE_SRC_LOW_BAT (1 << 9) +#define WAKE_SRC_MD32 (1 << 10) +#define WAKE_SRC_USB_CD (1 << 14) +#define WAKE_SRC_USB_PDN (1 << 15) +#define WAKE_SRC_AFE (1 << 20) +#define WAKE_SRC_THERM (1 << 21) +#define WAKE_SRC_SYSPWREQ (1 << 24) +#define WAKE_SRC_SEJ (1 << 27) +#define WAKE_SRC_ALL_MD32 (1 << 28) +#define WAKE_SRC_CPU_IRQ (1 << 29) + +#endif /* SPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c b/arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c new file mode 100644 index 0000000..965b653 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +static uint32_t plat_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. + */ + return (uint32_t)(~read_cntpct_el0()); +} + +static const timer_ops_t plat_timer_ops = { + .get_timer_value = plat_get_timer_value, + .clk_mult = 1, + .clk_div = SYS_COUNTER_FREQ_IN_MHZ, +}; + +void plat_delay_timer_init(void) +{ + timer_init(&plat_timer_ops); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c b/arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c new file mode 100644 index 0000000..20cb26d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(FIQ_SMP_CALL_SGI, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +gicv2_driver_data_t arm_gic_data = { + .gicd_base = BASE_GICD_BASE, + .gicc_base = BASE_GICC_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +void plat_mt_gic_driver_init(void) +{ + gicv2_driver_init(&arm_gic_data); +} + +void plat_mt_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +void plat_mt_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +void plat_mt_gic_cpuif_disable(void) +{ + gicv2_cpuif_disable(); +} + +void plat_mt_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c new file mode 100644 index 0000000..0dfbd18 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2016, 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 + +struct core_context { + unsigned long timer_data[8]; + unsigned int count; + unsigned int rst; + unsigned int abt; + unsigned int brk; +}; + +struct cluster_context { + struct core_context core[PLATFORM_MAX_CPUS_PER_CLUSTER]; +}; + +/* + * Top level structure to hold the complete context of a multi cluster system + */ +struct system_context { + struct cluster_context cluster[PLATFORM_CLUSTER_COUNT]; +}; + +/* + * Top level structure which encapsulates the context of the entire system + */ +static struct system_context dormant_data[1]; + +static inline struct cluster_context *system_cluster( + struct system_context *system, + uint32_t clusterid) +{ + return &system->cluster[clusterid]; +} + +static inline struct core_context *cluster_core(struct cluster_context *cluster, + uint32_t cpuid) +{ + return &cluster->core[cpuid]; +} + +static struct cluster_context *get_cluster_data(unsigned long mpidr) +{ + uint32_t clusterid; + + clusterid = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + return system_cluster(dormant_data, clusterid); +} + +static struct core_context *get_core_data(unsigned long mpidr) +{ + struct cluster_context *cluster; + uint32_t cpuid; + + cluster = get_cluster_data(mpidr); + cpuid = mpidr & MPIDR_CPU_MASK; + + return cluster_core(cluster, cpuid); +} + +static void mt_save_generic_timer(unsigned long *container) +{ + uint64_t ctl; + uint64_t val; + + __asm__ volatile("mrs %x0, cntkctl_el1\n\t" + "mrs %x1, cntp_cval_el0\n\t" + "stp %x0, %x1, [%2, #0]" + : "=&r" (ctl), "=&r" (val) + : "r" (container) + : "memory"); + + __asm__ volatile("mrs %x0, cntp_tval_el0\n\t" + "mrs %x1, cntp_ctl_el0\n\t" + "stp %x0, %x1, [%2, #16]" + : "=&r" (val), "=&r" (ctl) + : "r" (container) + : "memory"); + + __asm__ volatile("mrs %x0, cntv_tval_el0\n\t" + "mrs %x1, cntv_ctl_el0\n\t" + "stp %x0, %x1, [%2, #32]" + : "=&r" (val), "=&r" (ctl) + : "r" (container) + : "memory"); +} + +static void mt_restore_generic_timer(unsigned long *container) +{ + uint64_t ctl; + uint64_t val; + + __asm__ volatile("ldp %x0, %x1, [%2, #0]\n\t" + "msr cntkctl_el1, %x0\n\t" + "msr cntp_cval_el0, %x1" + : "=&r" (ctl), "=&r" (val) + : "r" (container) + : "memory"); + + __asm__ volatile("ldp %x0, %x1, [%2, #16]\n\t" + "msr cntp_tval_el0, %x0\n\t" + "msr cntp_ctl_el0, %x1" + : "=&r" (val), "=&r" (ctl) + : "r" (container) + : "memory"); + + __asm__ volatile("ldp %x0, %x1, [%2, #32]\n\t" + "msr cntv_tval_el0, %x0\n\t" + "msr cntv_ctl_el0, %x1" + : "=&r" (val), "=&r" (ctl) + : "r" (container) + : "memory"); +} + +static void stop_generic_timer(void) +{ + /* + * Disable the timer and mask the irq to prevent + * suprious interrupts on this cpu interface. It + * will bite us when we come back if we don't. It + * will be replayed on the inbound cluster. + */ + uint64_t cntpctl = read_cntp_ctl_el0(); + + write_cntp_ctl_el0(clr_cntp_ctl_enable(cntpctl)); +} + +static void mt_cpu_save(unsigned long mpidr) +{ + struct core_context *core; + + core = get_core_data(mpidr); + mt_save_generic_timer(core->timer_data); + + /* disable timer irq, and upper layer should enable it again. */ + stop_generic_timer(); +} + +static void mt_cpu_restore(unsigned long mpidr) +{ + struct core_context *core; + + core = get_core_data(mpidr); + mt_restore_generic_timer(core->timer_data); +} + +static void mt_platform_save_context(unsigned long mpidr) +{ + /* mcusys_save_context: */ + mt_cpu_save(mpidr); +} + +static void mt_platform_restore_context(unsigned long mpidr) +{ + /* mcusys_restore_context: */ + mt_cpu_restore(mpidr); +} + +/******************************************************************************* +* Private function which is used to determine if any platform actions +* should be performed for the specified affinity instance given its +* state. Nothing needs to be done if the 'state' is not off or if this is not +* the highest affinity level which will enter the 'state'. +*******************************************************************************/ +static int32_t plat_do_plat_actions(unsigned int afflvl, unsigned int state) +{ + unsigned int max_phys_off_afflvl; + + assert(afflvl <= MPIDR_AFFLVL2); + + if (state != PSCI_STATE_OFF) + return -EAGAIN; + + /* + * Find the highest affinity level which will be suspended and postpone + * all the platform specific actions until that level is hit. + */ + max_phys_off_afflvl = psci_get_max_phys_off_afflvl(); + assert(max_phys_off_afflvl != PSCI_INVALID_DATA); + if (afflvl != max_phys_off_afflvl) + return -EAGAIN; + + return 0; +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to enter + * standby. + ******************************************************************************/ +static void plat_affinst_standby(unsigned int power_state) +{ + unsigned int target_afflvl; + + /* Sanity check the requested state */ + target_afflvl = psci_get_pstate_afflvl(power_state); + + /* + * It's possible to enter standby only on affinity level 0 i.e. a cpu + * on the MTK_platform. Ignore any other affinity level. + */ + if (target_afflvl == MPIDR_AFFLVL0) { + /* + * Enter standby state. dsb is good practice before using wfi + * to enter low power states. + */ + dsb(); + wfi(); + } +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to be turned + * on. The level and mpidr determine the affinity instance. + ******************************************************************************/ +static int plat_affinst_on(unsigned long mpidr, + unsigned long sec_entrypoint, + unsigned int afflvl, + unsigned int state) +{ + int rc = PSCI_E_SUCCESS; + unsigned long cpu_id; + unsigned long cluster_id; + uintptr_t rv; + + /* + * It's possible to turn on only affinity level 0 i.e. a cpu + * on the MTK_platform. Ignore any other affinity level. + */ + if (afflvl != MPIDR_AFFLVL0) + return rc; + + cpu_id = mpidr & MPIDR_CPU_MASK; + cluster_id = mpidr & MPIDR_CLUSTER_MASK; + + if (cluster_id) + rv = (uintptr_t)&mt6795_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw; + else + rv = (uintptr_t)&mt6795_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw; + + mmio_write_32(rv, sec_entrypoint); + INFO("mt_on[%ld:%ld], entry %x\n", + cluster_id, cpu_id, mmio_read_32(rv)); + + return rc; +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to be turned + * off. The level and mpidr determine the affinity instance. The 'state' arg. + * allows the platform to decide whether the cluster is being turned off and + * take apt actions. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +static void plat_affinst_off(unsigned int afflvl, unsigned int state) +{ + unsigned long mpidr = read_mpidr_el1(); + + /* Determine if any platform actions need to be executed. */ + if (plat_do_plat_actions(afflvl, state) == -EAGAIN) + return; + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_mt_gic_cpuif_disable(); + + trace_power_flow(mpidr, CPU_DOWN); + + if (afflvl != MPIDR_AFFLVL0) { + /* Disable coherency if this cluster is to be turned off */ + plat_cci_disable(); + + trace_power_flow(mpidr, CLUSTER_DOWN); + } +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to be + * suspended. The level and mpidr determine the affinity instance. The 'state' + * arg. allows the platform to decide whether the cluster is being turned off + * and take apt actions. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +static void plat_affinst_suspend(unsigned long sec_entrypoint, + unsigned int afflvl, + unsigned int state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned long cluster_id; + unsigned long cpu_id; + uintptr_t rv; + + /* Determine if any platform actions need to be executed. */ + if (plat_do_plat_actions(afflvl, state) == -EAGAIN) + return; + + cpu_id = mpidr & MPIDR_CPU_MASK; + cluster_id = mpidr & MPIDR_CLUSTER_MASK; + + if (cluster_id) + rv = (uintptr_t)&mt6795_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw; + else + rv = (uintptr_t)&mt6795_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw; + + mmio_write_32(rv, sec_entrypoint); + + if (afflvl >= MPIDR_AFFLVL0) + mt_platform_save_context(mpidr); + + /* Perform the common cluster specific operations */ + if (afflvl >= MPIDR_AFFLVL1) { + /* Disable coherency if this cluster is to be turned off */ + plat_cci_disable(); + disable_scu(mpidr); + + trace_power_flow(mpidr, CLUSTER_SUSPEND); + } + + if (afflvl >= MPIDR_AFFLVL2) { + /* Prevent interrupts from spuriously waking up this cpu */ + plat_mt_gic_cpuif_disable(); + } +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance has just been powered + * on after being turned off earlier. The level and mpidr determine the affinity + * instance. The 'state' arg. allows the platform to decide whether the cluster + * was turned off prior to wakeup and do what's necessary to setup it up + * correctly. + ******************************************************************************/ +static void plat_affinst_on_finish(unsigned int afflvl, unsigned int state) +{ + unsigned long mpidr = read_mpidr_el1(); + + /* Determine if any platform actions need to be executed. */ + if (plat_do_plat_actions(afflvl, state) == -EAGAIN) + return; + + /* Perform the common cluster specific operations */ + if (afflvl >= MPIDR_AFFLVL1) { + enable_scu(mpidr); + + /* Enable coherency if this cluster was off */ + plat_cci_enable(); + trace_power_flow(mpidr, CLUSTER_UP); + } + + /* Enable the gic cpu interface */ + plat_mt_gic_cpuif_enable(); + plat_mt_gic_pcpu_init(); + trace_power_flow(mpidr, CPU_UP); +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance has just been powered + * on after having been suspended earlier. The level and mpidr determine the + * affinity instance. + ******************************************************************************/ +static void plat_affinst_suspend_finish(unsigned int afflvl, unsigned int state) +{ + unsigned long mpidr = read_mpidr_el1(); + + /* Determine if any platform actions need to be executed. */ + if (plat_do_plat_actions(afflvl, state) == -EAGAIN) + return; + + if (afflvl >= MPIDR_AFFLVL2) { + /* Enable the gic cpu interface */ + plat_mt_gic_init(); + plat_mt_gic_cpuif_enable(); + } + + /* Perform the common cluster specific operations */ + if (afflvl >= MPIDR_AFFLVL1) { + enable_scu(mpidr); + + /* Enable coherency if this cluster was off */ + plat_cci_enable(); + trace_power_flow(mpidr, CLUSTER_UP); + } + + if (afflvl >= MPIDR_AFFLVL0) + mt_platform_restore_context(mpidr); + + plat_mt_gic_pcpu_init(); +} + +static unsigned int plat_get_sys_suspend_power_state(void) +{ + /* StateID: 0, StateType: 1(power down), PowerLevel: 2(system) */ + return psci_make_powerstate(0, 1, 2); +} + +/******************************************************************************* + * MTK handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 plat_system_off(void) +{ + INFO("MTK System Off\n"); + wfi(); + ERROR("MTK System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 plat_system_reset(void) +{ + /* Write the System Configuration Control Register */ + INFO("MTK System Reset\n"); + + mmio_clrbits_32(MTK_WDT_BASE, + (MTK_WDT_MODE_DUAL_MODE | MTK_WDT_MODE_IRQ)); + mmio_setbits_32(MTK_WDT_BASE, (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN)); + mmio_setbits_32(MTK_WDT_SWRST, MTK_WDT_SWRST_KEY); + + wfi(); + ERROR("MTK System Reset: operation not handled.\n"); + panic(); +} + +/******************************************************************************* + * Export the platform handlers to enable psci to invoke them + ******************************************************************************/ +static const plat_pm_ops_t plat_plat_pm_ops = { + .affinst_standby = plat_affinst_standby, + .affinst_on = plat_affinst_on, + .affinst_off = plat_affinst_off, + .affinst_suspend = plat_affinst_suspend, + .affinst_on_finish = plat_affinst_on_finish, + .affinst_suspend_finish = plat_affinst_suspend_finish, + .system_off = plat_system_off, + .system_reset = plat_system_reset, + .get_sys_suspend_power_state = plat_get_sys_suspend_power_state, +}; + +/******************************************************************************* + * Export the platform specific power ops & initialize the mtk_platform power + * controller + ******************************************************************************/ +int platform_setup_pm(const plat_pm_ops_t **plat_ops) +{ + *plat_ops = &plat_plat_pm_ops; + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c new file mode 100644 index 0000000..7425d26 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr) +{ + /* Report 1 (absent) instance at levels higher that the cluster level */ + if (aff_lvl > MPIDR_AFFLVL1) + return PLATFORM_SYSTEM_COUNT; + + if (aff_lvl == MPIDR_AFFLVL1) + return PLATFORM_CLUSTER_COUNT; + + return mpidr & 0x100 ? PLATFORM_CLUSTER1_CORE_COUNT : + PLATFORM_CLUSTER0_CORE_COUNT; +} + +unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr) +{ + return aff_lvl <= MPIDR_AFFLVL2 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT; +} + +int mt_setup_topology(void) +{ + /* [TODO] Make topology configurable via SCC */ + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/platform.mk b/arm-trusted-firmware/plat/mediatek/mt6795/platform.mk new file mode 100644 index 0000000..4ab692d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/platform.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MTK_PLAT := plat/mediatek +MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} + +# Add OEM customized codes +OEMS := true +MTK_SIP_KERNEL_BOOT_ENABLE := 1 + + +ifneq (${OEMS},none) + OEMS_INCLUDES := -I${MTK_PLAT}/common/custom/ + OEMS_SOURCES := ${MTK_PLAT}/common/custom/oem_svc.c +endif + +PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT}/common/drivers/uart \ + -I${MTK_PLAT_SOC}/ \ + -I${MTK_PLAT_SOC}/drivers/timer/ \ + -I${MTK_PLAT_SOC}/include/ \ + -Iinclude/plat/arm/common/ \ + ${OEMS_INCLUDES} + +PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/common/plat_gic.c + +BL31_SOURCES += drivers/arm/cci/cci.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c \ + drivers/console/aarch64/console.S \ + drivers/delay_timer/delay_timer.c \ + lib/cpus/aarch64/cortex_a53.S \ + ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/plat_mt_gic.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/drivers/uart/8250_console.S \ + ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ + ${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \ + ${MTK_PLAT_SOC}/plat_delay_timer.c \ + ${MTK_PLAT_SOC}/plat_pm.c \ + ${MTK_PLAT_SOC}/plat_topology.c \ + ${MTK_PLAT_SOC}/power_tracer.c \ + ${MTK_PLAT_SOC}/scu.c \ + ${OEMS_SOURCES} + +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_826319 := 1 +ERRATA_A53_836870 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +# indicate the reset vector address can be programmed +PROGRAMMABLE_RESET_ADDRESS := 1 + +$(eval $(call add_define,MTK_SIP_KERNEL_BOOT_ENABLE)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c b/arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c new file mode 100644 index 0000000..64d086d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#define trace_log(...) INFO("psci: " __VA_ARGS__) + +void trace_power_flow(unsigned long mpidr, unsigned char mode) +{ + switch (mode) { + case CPU_UP: + trace_log("core %lld:%lld ON\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS, + (mpidr & MPIDR_CPU_MASK)); + break; + case CPU_DOWN: + trace_log("core %lld:%lld OFF\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS, + (mpidr & MPIDR_CPU_MASK)); + break; + case CPU_SUSPEND: + trace_log("core %lld:%lld SUSPEND\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS, + (mpidr & MPIDR_CPU_MASK)); + break; + case CLUSTER_UP: + trace_log("cluster %lld ON\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS); + break; + case CLUSTER_DOWN: + trace_log("cluster %lld OFF\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS); + break; + case CLUSTER_SUSPEND: + trace_log("cluster %lld SUSPEND\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS); + break; + default: + trace_log("unknown power mode\n"); + break; + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/scu.c b/arm-trusted-firmware/plat/mediatek/mt6795/scu.c new file mode 100644 index 0000000..3b74527 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/scu.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +void disable_scu(unsigned long mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_miscdbg, + MP1_ACINACTM); + else + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp0_axi_config, + MP0_ACINACTM); +} + +void enable_scu(unsigned long mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp1_miscdbg, + MP1_ACINACTM); + else + mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp0_axi_config, + MP0_ACINACTM); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S new file mode 100644 index 0000000..095dfc5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_report_exception + .globl platform_is_primary_cpu + .globl plat_my_core_pos + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* MT8173 Oak does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +func platform_is_primary_cpu + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #MT8173_PRIMARY_CPU + cset x0, eq + ret +endfunc platform_is_primary_cpu + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void); + * + * result: CorePos = CoreId + (ClusterId << 2) + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c new file mode 100644 index 0000000..a2dbe3e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +static const int cci_map[] = { + PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX +}; + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_mmap[] = { + /* for TF text, RO, RW */ + MAP_REGION_FLAT(TZRAM_BASE, TZRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } + +}; + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +#define DEFINE_CONFIGURE_MMU_EL(_el) \ + void plat_configure_mmu_el ## _el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(plat_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el ## _el(0); \ + } + +/* Define EL3 variants of the function initialising the MMU */ +DEFINE_CONFIGURE_MMU_EL(3) + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +void plat_cci_init(void) +{ + /* Initialize CCI driver */ + cci_init(PLAT_MT_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); +} + +void plat_cci_enable(void) +{ + /* + * Enable CCI coherency for this cluster. + * No need for locks as no other cpu is active at the moment. + */ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); +} + +void plat_cci_disable(void) +{ + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c new file mode 100644 index 0000000..bd7d0b0 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2013-2019, 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 +#include + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; + +static void platform_setup_cpu(void) +{ + /* turn off all the little core's power except cpu 0 */ + mtcmos_little_cpu_off(); + + /* setup big cores */ + mmio_write_32((uintptr_t)&mt8173_mcucfg->mp1_config_res, + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK | + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK | + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK | + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK | + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK); + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp1_miscdbg, MP1_AINACTS); + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp1_clkenm_div, + MP1_SW_CG_GEN); + mmio_clrbits_32((uintptr_t)&mt8173_mcucfg->mp1_rst_ctl, + MP1_L2RSTDISABLE); + + /* set big cores arm64 boot mode */ + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp1_cpucfg, + MP1_CPUCFG_64BIT); + + /* set LITTLE cores arm64 boot mode */ + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp0_rv_addr[0].rv_addr_hw, + MP0_CPUCFG_64BIT); + + /* enable dcm control */ + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->bus_fabric_dcm_ctrl, + ADB400_GRP_DCM_EN | CCI400_GRP_DCM_EN | ADBCLK_GRP_DCM_EN | + EMICLK_GRP_DCM_EN | ACLK_GRP_DCM_EN | L2C_IDLE_DCM_EN | + INFRACLK_PSYS_DYNAMIC_CG_EN); + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->l2c_sram_ctrl, + L2C_SRAM_DCM_EN); + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->cci_clk_ctrl, + MCU_BUS_DCM_EN); +} + +static void platform_setup_sram(void) +{ + /* protect BL31 memory from non-secure read/write access */ + mmio_write_32(SRAMROM_SEC_ADDR, (uint32_t)(BL31_END + 0x3ff) & 0x3fc00); + mmio_write_32(SRAMROM_SEC_CTRL, 0x10000ff9); +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Perform any BL3-1 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + * BL2 has flushed this information to memory, so we are guaranteed to pick up + * good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + console_16550_register(MT8173_UART0_BASE, MT8173_UART_CLOCK, MT8173_BAUDRATE, &console); + + VERBOSE("bl31_setup\n"); + + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); +} + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + platform_setup_cpu(); + platform_setup_sram(); + + generic_delay_timer_init(); + + /* Initialize the gic cpu and distributor interfaces */ + plat_arm_gic_driver_init(); + plat_arm_gic_init(); + + /* Initialize spm at boot time */ + spm_boot_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + plat_cci_init(); + plat_cci_enable(); + + plat_configure_mmu_el3(BL_CODE_BASE, + BL_COHERENT_RAM_END - BL_CODE_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c new file mode 100644 index 0000000..bfb3082 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define crypt_read32(offset) \ + mmio_read_32((uintptr_t)(CRYPT_BASE+((offset) * 4))) + +#define crypt_write32(offset, value) \ + mmio_write_32((uintptr_t)(CRYPT_BASE + ((offset) * 4)), (uint32_t)value) + +#define GET_L32(x) ((uint32_t)(x & 0xffffffff)) +#define GET_H32(x) ((uint32_t)((x >> 32) & 0xffffffff)) + +#define REG_INIT 0 +#define REG_MSC 4 +#define REG_TRIG 256 +#define REG_STAT 512 +#define REG_CLR 513 +#define REG_INT 514 +#define REG_P68 768 +#define REG_P69 769 +#define REG_P70 770 +#define REG_P71 771 +#define REG_P72 772 +#define REG_D20 820 +#define KEY_SIZE 160 +#define KEY_LEN 40 + +/* Wait until crypt is completed */ +uint64_t crypt_wait(void) +{ + crypt_write32(REG_TRIG, 0); + while (crypt_read32(REG_STAT) == 0) + ; + udelay(100); + crypt_write32(REG_CLR, crypt_read32(REG_STAT)); + crypt_write32(REG_INT, 0); + return MTK_SIP_E_SUCCESS; +} + +static uint32_t record[4]; +/* Copy encrypted key to crypt engine */ +uint64_t crypt_set_hdcp_key_ex(uint64_t x1, uint64_t x2, uint64_t x3) +{ + uint32_t i = (uint32_t)x1; + uint32_t j = 0; + + if (i > KEY_LEN) + return MTK_SIP_E_INVALID_PARAM; + + if (i < KEY_LEN) { + crypt_write32(REG_MSC, 0x80ff3800); + crypt_write32(REG_INIT, 0); + crypt_write32(REG_INIT, 0xF); + crypt_write32(REG_CLR, 1); + crypt_write32(REG_INT, 0); + + crypt_write32(REG_P68, 0x70); + crypt_write32(REG_P69, 0x1C0); + crypt_write32(REG_P70, 0x30); + crypt_write32(REG_P71, 0x4); + crypt_wait(); + + crypt_write32(REG_D20 + 4 * i, GET_L32(x2)); + crypt_write32(REG_D20 + 4 * i + 1, GET_H32(x2)); + crypt_write32(REG_D20 + 4 * i + 2, GET_L32(x3)); + crypt_write32(REG_D20 + 4 * i + 3, GET_H32(x3)); + + crypt_write32(REG_P69, 0); + crypt_write32(REG_P68, 0x20); + crypt_write32(REG_P71, 0x34 + 4 * i); + crypt_write32(REG_P72, 0x34 + 4 * i); + crypt_wait(); + + for (j = 0; j < 4; j++) { + crypt_write32(REG_P68, 0x71); + crypt_write32(REG_P69, 0x34 + 4 * i + j); + crypt_write32(REG_P70, record[j]); + crypt_wait(); + } + } + /* Prepare data for next iteration */ + record[0] = GET_L32(x2); + record[1] = GET_H32(x2); + record[2] = GET_L32(x3); + record[3] = GET_H32(x3); + return MTK_SIP_E_SUCCESS; +} + +/* Set key to hdcp */ +uint64_t crypt_set_hdcp_key_num(uint32_t num) +{ + if (num > KEY_LEN) + return MTK_SIP_E_INVALID_PARAM; + + crypt_write32(REG_P68, 0x6A); + crypt_write32(REG_P69, 0x34 + 4 * num); + crypt_wait(); + return MTK_SIP_E_SUCCESS; +} + +/* Clear key in crypt engine */ +uint64_t crypt_clear_hdcp_key(void) +{ + uint32_t i; + + for (i = 0; i < KEY_SIZE; i++) + crypt_write32(REG_D20 + i, 0); + return MTK_SIP_E_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h new file mode 100644 index 0000000..1a691a6 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CRYPT_H +#define CRYPT_H + +#include + +/* crypt function prototype */ +uint64_t crypt_set_hdcp_key_ex(uint64_t x1, uint64_t x2, uint64_t x3); +uint64_t crypt_set_hdcp_key_num(uint32_t num); +uint64_t crypt_clear_hdcp_key(void); + +#endif /* CRYPT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c new file mode 100644 index 0000000..452ac22 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +enum { + SRAM_ISOINT_B = 1U << 6, + SRAM_CKISO = 1U << 5, + PWR_CLK_DIS = 1U << 4, + PWR_ON_2ND = 1U << 3, + PWR_ON = 1U << 2, + PWR_ISO = 1U << 1, + PWR_RST_B = 1U << 0 +}; + +enum { + L1_PDN_ACK = 1U << 8, + L1_PDN = 1U << 0 +}; + +enum { + LITTLE_CPU3 = 1U << 12, + LITTLE_CPU2 = 1U << 11, + LITTLE_CPU1 = 1U << 10, +}; + +enum { + SRAM_PDN = 0xf << 8, + DIS_SRAM_ACK = 0x1 << 12, + AUD_SRAM_ACK = 0xf << 12, +}; + +enum { + DIS_PWR_STA_MASK = 0x1 << 3, + AUD_PWR_STA_MASK = 0x1 << 24, +}; + +#define SPM_VDE_PWR_CON 0x0210 +#define SPM_MFG_PWR_CON 0x0214 +#define SPM_VEN_PWR_CON 0x0230 +#define SPM_ISP_PWR_CON 0x0238 +#define SPM_DIS_PWR_CON 0x023c +#define SPM_VEN2_PWR_CON 0x0298 +#define SPM_AUDIO_PWR_CON 0x029c +#define SPM_MFG_2D_PWR_CON 0x02c0 +#define SPM_MFG_ASYNC_PWR_CON 0x02c4 +#define SPM_USB_PWR_CON 0x02cc + +#define MTCMOS_CTRL_SUCCESS 0 +#define MTCMOS_CTRL_ERROR -1 + +#define MTCMOS_CTRL_EN (0x1 << 18) + +#define VDE_PWR_ON 0 +#define VEN_PWR_ON 1 +#define ISP_PWR_ON 2 +#define DIS_PWR_ON 3 +#define VEN2_PWR_ON 4 +#define AUDIO_PWR_ON 5 +#define MFG_ASYNC_PWR_ON 6 +#define MFG_2D_PWR_ON 7 +#define MFG_PWR_ON 8 +#define USB_PWR_ON 9 + +#define VDE_PWR_OFF 10 +#define VEN_PWR_OFF 11 +#define ISP_PWR_OFF 12 +#define DIS_PWR_OFF 13 +#define VEN2_PWR_OFF 14 +#define AUDIO_PWR_OFF 15 +#define MFG_ASYNC_PWR_OFF 16 +#define MFG_2D_PWR_OFF 17 +#define MFG_PWR_OFF 18 +#define USB_PWR_OFF 19 + +#define VDE_PWR_CON_PWR_STA 7 +#define VEN_PWR_CON_PWR_STA 21 +#define ISP_PWR_CON_PWR_STA 5 +#define DIS_PWR_CON_PWR_STA 3 +#define VEN2_PWR_CON_PWR_STA 20 +#define AUDIO_PWR_CON_PWR_STA 24 +#define MFG_ASYNC_PWR_CON_PWR_STA 23 +#define MFG_2D_PWR_CON_PWR_STA 22 +#define MFG_PWR_CON_PWR_STA 4 +#define USB_PWR_CON_PWR_STA 25 + +/* + * Timeout if the ack is not signled after 1 second. + * According to designer, one mtcmos operation should be done + * around 10us. + */ +#define MTCMOS_ACK_POLLING_MAX_COUNT 10000 +#define MTCMOS_ACK_POLLING_INTERVAL 10 + +static void mtcmos_ctrl_little_off(unsigned int linear_id) +{ + uint32_t reg_pwr_con; + uint32_t reg_l1_pdn; + uint32_t bit_cpu; + + switch (linear_id) { + case 1: + reg_pwr_con = SPM_CA7_CPU1_PWR_CON; + reg_l1_pdn = SPM_CA7_CPU1_L1_PDN; + bit_cpu = LITTLE_CPU1; + break; + case 2: + reg_pwr_con = SPM_CA7_CPU2_PWR_CON; + reg_l1_pdn = SPM_CA7_CPU2_L1_PDN; + bit_cpu = LITTLE_CPU2; + break; + case 3: + reg_pwr_con = SPM_CA7_CPU3_PWR_CON; + reg_l1_pdn = SPM_CA7_CPU3_L1_PDN; + bit_cpu = LITTLE_CPU3; + break; + default: + /* should never come to here */ + return; + } + + /* enable register control */ + mmio_write_32(SPM_POWERON_CONFIG_SET, + (SPM_PROJECT_CODE << 16) | (1U << 0)); + + mmio_setbits_32(reg_pwr_con, PWR_ISO); + mmio_setbits_32(reg_pwr_con, SRAM_CKISO); + mmio_clrbits_32(reg_pwr_con, SRAM_ISOINT_B); + mmio_setbits_32(reg_l1_pdn, L1_PDN); + + while (!(mmio_read_32(reg_l1_pdn) & L1_PDN_ACK)) + continue; + + mmio_clrbits_32(reg_pwr_con, PWR_RST_B); + mmio_setbits_32(reg_pwr_con, PWR_CLK_DIS); + mmio_clrbits_32(reg_pwr_con, PWR_ON); + mmio_clrbits_32(reg_pwr_con, PWR_ON_2ND); + + while ((mmio_read_32(SPM_PWR_STATUS) & bit_cpu) || + (mmio_read_32(SPM_PWR_STATUS_2ND) & bit_cpu)) + continue; +} + +void mtcmos_little_cpu_off(void) +{ + /* turn off little cpu 1 - 3 */ + mtcmos_ctrl_little_off(1); + mtcmos_ctrl_little_off(2); + mtcmos_ctrl_little_off(3); +} + +uint32_t wait_mtcmos_ack(uint32_t on, uint32_t pwr_ctrl, uint32_t spm_pwr_sta) +{ + int i = 0; + uint32_t cmp, pwr_sta, pwr_sta_2nd; + + while (1) { + cmp = mmio_read_32(SPM_PCM_PASR_DPD_3) & pwr_ctrl; + pwr_sta = (mmio_read_32(SPM_PWR_STATUS) >> spm_pwr_sta) & 1; + pwr_sta_2nd = + (mmio_read_32(SPM_PWR_STATUS_2ND) >> spm_pwr_sta) & 1; + if (cmp && (pwr_sta == on) && (pwr_sta_2nd == on)) { + mmio_write_32(SPM_PCM_RESERVE2, 0); + return MTCMOS_CTRL_SUCCESS; + } + udelay(MTCMOS_ACK_POLLING_INTERVAL); + i++; + if (i > MTCMOS_ACK_POLLING_MAX_COUNT) { + INFO("MTCMOS control failed(%d), SPM_PWR_STA(%d),\n" + "SPM_PCM_RESERVE=0x%x,SPM_PCM_RESERVE2=0x%x,\n" + "SPM_PWR_STATUS=0x%x,SPM_PWR_STATUS_2ND=0x%x\n" + "SPM_PCM_PASR_DPD_3 = 0x%x\n", + on, spm_pwr_sta, mmio_read_32(SPM_PCM_RESERVE), + mmio_read_32(SPM_PCM_RESERVE2), + mmio_read_32(SPM_PWR_STATUS), + mmio_read_32(SPM_PWR_STATUS_2ND), + mmio_read_32(SPM_PCM_PASR_DPD_3)); + mmio_write_32(SPM_PCM_RESERVE2, 0); + return MTCMOS_CTRL_ERROR; + } + } +} + +uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num) +{ + uint32_t ret = MTCMOS_CTRL_SUCCESS; + uint32_t power_on; + uint32_t power_off; + uint32_t power_ctrl; + uint32_t power_status; + + spm_lock_get(); + spm_mcdi_prepare_for_mtcmos(); + mmio_setbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); + + switch (mtcmos_num) { + case SPM_VDE_PWR_CON: + power_on = VDE_PWR_ON; + power_off = VDE_PWR_OFF; + power_status = VDE_PWR_CON_PWR_STA; + break; + case SPM_MFG_PWR_CON: + power_on = MFG_PWR_ON; + power_off = MFG_PWR_OFF; + power_status = MFG_PWR_CON_PWR_STA; + break; + case SPM_VEN_PWR_CON: + power_on = VEN_PWR_ON; + power_off = VEN_PWR_OFF; + power_status = VEN_PWR_CON_PWR_STA; + break; + case SPM_ISP_PWR_CON: + power_on = ISP_PWR_ON; + power_off = ISP_PWR_OFF; + power_status = ISP_PWR_CON_PWR_STA; + break; + case SPM_DIS_PWR_CON: + power_on = DIS_PWR_ON; + power_off = DIS_PWR_OFF; + power_status = DIS_PWR_CON_PWR_STA; + break; + case SPM_VEN2_PWR_CON: + power_on = VEN2_PWR_ON; + power_off = VEN2_PWR_OFF; + power_status = VEN2_PWR_CON_PWR_STA; + break; + case SPM_AUDIO_PWR_CON: + power_on = AUDIO_PWR_ON; + power_off = AUDIO_PWR_OFF; + power_status = AUDIO_PWR_CON_PWR_STA; + break; + case SPM_MFG_2D_PWR_CON: + power_on = MFG_2D_PWR_ON; + power_off = MFG_2D_PWR_OFF; + power_status = MFG_2D_PWR_CON_PWR_STA; + break; + case SPM_MFG_ASYNC_PWR_CON: + power_on = MFG_ASYNC_PWR_ON; + power_off = MFG_ASYNC_PWR_OFF; + power_status = MFG_ASYNC_PWR_CON_PWR_STA; + break; + case SPM_USB_PWR_CON: + power_on = USB_PWR_ON; + power_off = USB_PWR_OFF; + power_status = USB_PWR_CON_PWR_STA; + break; + default: + ret = MTCMOS_CTRL_ERROR; + INFO("No mapping MTCMOS(%d), ret = %d\n", mtcmos_num, ret); + break; + } + if (ret == MTCMOS_CTRL_SUCCESS) { + power_ctrl = on ? (1 << power_on) : (1 << power_off); + mmio_setbits_32(SPM_PCM_RESERVE2, power_ctrl); + ret = wait_mtcmos_ack(on, power_ctrl, power_status); + VERBOSE("0x%x(%d), PWR_STATUS(0x%x), ret(%d)\n", + power_ctrl, on, mmio_read_32(SPM_PWR_STATUS), ret); + } + + mmio_clrbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); + spm_lock_release(); + + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h new file mode 100644 index 0000000..1e58027 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef MTCMOS_H +#define MTCMOS_H + +/* + * This function will turn off all the little core's power except cpu 0. The + * cores in cluster 0 are all powered when the system power on. The System + * Power Manager (SPM) will do nothing if it found the core's power was on + * during CPU_ON psci call. + */ +void mtcmos_little_cpu_off(void); +uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num); + +#endif /* MTCMOS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..0dffc23 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include + +/* external API */ +int32_t pwrap_read(uint32_t adr, uint32_t *rdata); +int32_t pwrap_write(uint32_t adr, uint32_t wdata); + +static struct mt8173_pmic_wrap_regs *const mtk_pwrap = + (void *)PMIC_WRAP_BASE; + +/* timeout setting */ +enum { + TIMEOUT_RESET = 50, /* us */ + TIMEOUT_READ = 50, /* us */ + TIMEOUT_WAIT_IDLE = 50 /* us */ +}; + +/* PMIC_WRAP registers */ +struct mt8173_pmic_wrap_regs { + uint32_t mux_sel; + uint32_t wrap_en; + uint32_t dio_en; + uint32_t sidly; + uint32_t rddmy; + uint32_t si_ck_con; + uint32_t cshext_write; + uint32_t cshext_read; + uint32_t cslext_start; + uint32_t cslext_end; + uint32_t staupd_prd; + uint32_t staupd_grpen; + uint32_t reserved[4]; + uint32_t staupd_man_trig; + uint32_t staupd_sta; + uint32_t wrap_sta; + uint32_t harb_init; + uint32_t harb_hprio; + uint32_t hiprio_arb_en; + uint32_t harb_sta0; + uint32_t harb_sta1; + uint32_t man_en; + uint32_t man_cmd; + uint32_t man_rdata; + uint32_t man_vldclr; + uint32_t wacs0_en; + uint32_t init_done0; + uint32_t wacs0_cmd; + uint32_t wacs0_rdata; + uint32_t wacs0_vldclr; + uint32_t wacs1_en; + uint32_t init_done1; + uint32_t wacs1_cmd; + uint32_t wacs1_rdata; + uint32_t wacs1_vldclr; + uint32_t wacs2_en; + uint32_t init_done2; + uint32_t wacs2_cmd; + uint32_t wacs2_rdata; + uint32_t wacs2_vldclr; + uint32_t int_en; + uint32_t int_flg_raw; + uint32_t int_flg; + uint32_t int_clr; + uint32_t sig_adr; + uint32_t sig_mode; + uint32_t sig_value; + uint32_t sig_errval; + uint32_t crc_en; + uint32_t timer_en; + uint32_t timer_sta; + uint32_t wdt_unit; + uint32_t wdt_src_en; + uint32_t wdt_flg; + uint32_t debug_int_sel; + uint32_t dvfs_adr0; + uint32_t dvfs_wdata0; + uint32_t dvfs_adr1; + uint32_t dvfs_wdata1; + uint32_t dvfs_adr2; + uint32_t dvfs_wdata2; + uint32_t dvfs_adr3; + uint32_t dvfs_wdata3; + uint32_t dvfs_adr4; + uint32_t dvfs_wdata4; + uint32_t dvfs_adr5; + uint32_t dvfs_wdata5; + uint32_t dvfs_adr6; + uint32_t dvfs_wdata6; + uint32_t dvfs_adr7; + uint32_t dvfs_wdata7; + uint32_t spminf_sta; + uint32_t cipher_key_sel; + uint32_t cipher_iv_sel; + uint32_t cipher_en; + uint32_t cipher_rdy; + uint32_t cipher_mode; + uint32_t cipher_swrst; + uint32_t dcm_en; + uint32_t dcm_dbc_prd; +}; + +enum { + RDATA_WACS_RDATA_SHIFT = 0, + RDATA_WACS_FSM_SHIFT = 16, + RDATA_WACS_REQ_SHIFT = 19, + RDATA_SYNC_IDLE_SHIFT, + RDATA_INIT_DONE_SHIFT, + RDATA_SYS_IDLE_SHIFT, +}; + +enum { + RDATA_WACS_RDATA_MASK = 0xffff, + RDATA_WACS_FSM_MASK = 0x7, + RDATA_WACS_REQ_MASK = 0x1, + RDATA_SYNC_IDLE_MASK = 0x1, + RDATA_INIT_DONE_MASK = 0x1, + RDATA_SYS_IDLE_MASK = 0x1, +}; + +/* WACS_FSM */ +enum { + WACS_FSM_IDLE = 0x00, + WACS_FSM_REQ = 0x02, + WACS_FSM_WFDLE = 0x04, + WACS_FSM_WFVLDCLR = 0x06, + WACS_INIT_DONE = 0x01, + WACS_SYNC_IDLE = 0x01, + WACS_SYNC_BUSY = 0x00 +}; + +/* error information flag */ +enum { + E_PWR_INVALID_ARG = 1, + E_PWR_INVALID_RW = 2, + E_PWR_INVALID_ADDR = 3, + E_PWR_INVALID_WDAT = 4, + E_PWR_INVALID_OP_MANUAL = 5, + E_PWR_NOT_IDLE_STATE = 6, + E_PWR_NOT_INIT_DONE = 7, + E_PWR_NOT_INIT_DONE_READ = 8, + E_PWR_WAIT_IDLE_TIMEOUT = 9, + E_PWR_WAIT_IDLE_TIMEOUT_READ = 10, + E_PWR_INIT_SIDLY_FAIL = 11, + E_PWR_RESET_TIMEOUT = 12, + E_PWR_TIMEOUT = 13, + E_PWR_INIT_RESET_SPI = 20, + E_PWR_INIT_SIDLY = 21, + E_PWR_INIT_REG_CLOCK = 22, + E_PWR_INIT_ENABLE_PMIC = 23, + E_PWR_INIT_DIO = 24, + E_PWR_INIT_CIPHER = 25, + E_PWR_INIT_WRITE_TEST = 26, + E_PWR_INIT_ENABLE_CRC = 27, + E_PWR_INIT_ENABLE_DEWRAP = 28, + E_PWR_INIT_ENABLE_EVENT = 29, + E_PWR_READ_TEST_FAIL = 30, + E_PWR_WRITE_TEST_FAIL = 31, + E_PWR_SWITCH_DIO = 32 +}; + +#endif /* PMIC_WRAP_INIT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c new file mode 100644 index 0000000..587886c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +void rtc_bbpu_power_down(void) +{ + uint16_t bbpu; + + /* pull PWRBB low */ + bbpu = RTC_BBPU_KEY | RTC_BBPU_AUTO | RTC_BBPU_PWREN; + if (Writeif_unlock()) { + RTC_Write(RTC_BBPU, bbpu); + if (!RTC_Write_Trigger()) + assert(0); + } else { + assert(0); + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h new file mode 100644 index 0000000..f60a4c1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RTC_H +#define RTC_H + +/* RTC registers */ +enum { + RTC_BBPU = 0xE000, + RTC_IRQ_STA = 0xE002, + RTC_IRQ_EN = 0xE004, + RTC_CII_EN = 0xE006 +}; + +enum { + RTC_OSC32CON = 0xE026, + RTC_CON = 0xE03E, + RTC_WRTGR = 0xE03C +}; + +enum { + RTC_PDN1 = 0xE02C, + RTC_PDN2 = 0xE02E, + RTC_SPAR0 = 0xE030, + RTC_SPAR1 = 0xE032, + RTC_PROT = 0xE036, + RTC_DIFF = 0xE038, + RTC_CALI = 0xE03A +}; + +enum { + RTC_PROT_UNLOCK1 = 0x586A, + RTC_PROT_UNLOCK2 = 0x9136 +}; + +enum { + RTC_BBPU_PWREN = 1U << 0, + RTC_BBPU_BBPU = 1U << 2, + RTC_BBPU_AUTO = 1U << 3, + RTC_BBPU_CLRPKY = 1U << 4, + RTC_BBPU_RELOAD = 1U << 5, + RTC_BBPU_CBUSY = 1U << 6 +}; + +enum { + RTC_BBPU_KEY = 0x43 << 8 +}; + +/* external API */ +uint16_t RTC_Read(uint32_t addr); +void RTC_Write(uint32_t addr, uint16_t data); +int32_t rtc_busy_wait(void); +int32_t RTC_Write_Trigger(void); +int32_t Writeif_unlock(void); +void rtc_bbpu_power_down(void); + +#endif /* RTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c new file mode 100644 index 0000000..1caab3b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +/* + * System Power Manager (SPM) is a hardware module, which controls cpu or + * system power for different power scenarios using different firmware, i.e., + * - spm_hotplug.c for cpu power control in cpu hotplug flow. + * - spm_mcdi.c for cpu power control in cpu idle power saving state. + * - spm_suspend.c for system power control in system suspend scenario. + * + * This file provide utility functions common to hotplug, mcdi(idle), suspend + * power scenarios. A bakery lock (software lock) is incoporated to protect + * certain critical sections to avoid kicking different SPM firmware + * concurrently. + */ + +#define SPM_SYSCLK_SETTLE 128 /* 3.9ms */ + +DEFINE_BAKERY_LOCK(spm_lock); + +static int spm_hotplug_ready __section("tzfw_coherent_mem"); +static int spm_mcdi_ready __section("tzfw_coherent_mem"); +static int spm_suspend_ready __section("tzfw_coherent_mem"); + +void spm_lock_init(void) +{ + bakery_lock_init(&spm_lock); +} + +void spm_lock_get(void) +{ + bakery_lock_get(&spm_lock); +} + +void spm_lock_release(void) +{ + bakery_lock_release(&spm_lock); +} + +int is_mcdi_ready(void) +{ + return spm_mcdi_ready; +} + +int is_hotplug_ready(void) +{ + return spm_hotplug_ready; +} + +int is_suspend_ready(void) +{ + return spm_suspend_ready; +} + +void set_mcdi_ready(void) +{ + spm_mcdi_ready = 1; + spm_hotplug_ready = 0; + spm_suspend_ready = 0; +} + +void set_hotplug_ready(void) +{ + spm_mcdi_ready = 0; + spm_hotplug_ready = 1; + spm_suspend_ready = 0; +} + +void set_suspend_ready(void) +{ + spm_mcdi_ready = 0; + spm_hotplug_ready = 0; + spm_suspend_ready = 1; +} + +void clear_all_ready(void) +{ + spm_mcdi_ready = 0; + spm_hotplug_ready = 0; + spm_suspend_ready = 0; +} + +void spm_register_init(void) +{ + mmio_write_32(SPM_POWERON_CONFIG_SET, SPM_REGWR_CFG_KEY | SPM_REGWR_EN); + + mmio_write_32(SPM_POWER_ON_VAL0, 0); + mmio_write_32(SPM_POWER_ON_VAL1, POWER_ON_VAL1_DEF); + mmio_write_32(SPM_PCM_PWR_IO_EN, 0); + + mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET); + mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY); + if (mmio_read_32(SPM_PCM_FSM_STA) != PCM_FSM_STA_DEF) + WARN("PCM reset failed\n"); + + mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS); + mmio_write_32(SPM_PCM_CON1, CON1_CFG_KEY | CON1_EVENT_LOCK_EN | + CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B | CON1_MIF_APBEN); + mmio_write_32(SPM_PCM_IM_PTR, 0); + mmio_write_32(SPM_PCM_IM_LEN, 0); + + mmio_write_32(SPM_CLK_CON, CC_SYSCLK0_EN_1 | CC_SYSCLK0_EN_0 | + CC_SYSCLK1_EN_0 | CC_SRCLKENA_MASK_0 | CC_CLKSQ1_SEL | + CC_CXO32K_RM_EN_MD2 | CC_CXO32K_RM_EN_MD1 | CC_MD32_DCM_EN); + + mmio_write_32(SPM_SLEEP_ISR_MASK, 0xff0c); + mmio_write_32(SPM_SLEEP_ISR_STATUS, 0xc); + mmio_write_32(SPM_PCM_SW_INT_CLEAR, 0xff); + mmio_write_32(SPM_MD32_SRAM_CON, 0xff0); +} + +void spm_reset_and_init_pcm(void) +{ + unsigned int con1; + int i = 0; + + mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET); + mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY); + while (mmio_read_32(SPM_PCM_FSM_STA) != PCM_FSM_STA_DEF) { + i++; + if (i > 1000) { + i = 0; + WARN("PCM reset failed\n"); + break; + } + } + + mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS); + + con1 = mmio_read_32(SPM_PCM_CON1) & + (CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN); + mmio_write_32(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_EVENT_LOCK_EN | + CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B | + CON1_IM_NONRP_EN | CON1_MIF_APBEN); +} + +void spm_init_pcm_register(void) +{ + mmio_write_32(SPM_PCM_REG_DATA_INI, mmio_read_32(SPM_POWER_ON_VAL0)); + mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R0); + mmio_write_32(SPM_PCM_PWR_IO_EN, 0); + + mmio_write_32(SPM_PCM_REG_DATA_INI, mmio_read_32(SPM_POWER_ON_VAL1)); + mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R7); + mmio_write_32(SPM_PCM_PWR_IO_EN, 0); +} + +void spm_set_power_control(const struct pwr_ctrl *pwrctrl) +{ + mmio_write_32(SPM_AP_STANBY_CON, (!pwrctrl->md32_req_mask << 21) | + (!pwrctrl->mfg_req_mask << 17) | + (!pwrctrl->disp_req_mask << 16) | + (!!pwrctrl->mcusys_idle_mask << 7) | + (!!pwrctrl->ca15top_idle_mask << 6) | + (!!pwrctrl->ca7top_idle_mask << 5) | + (!!pwrctrl->wfi_op << 4)); + mmio_write_32(SPM_PCM_SRC_REQ, (!!pwrctrl->pcm_apsrc_req << 0)); + mmio_write_32(SPM_PCM_PASR_DPD_2, 0); + + mmio_clrsetbits_32(SPM_CLK_CON, CC_SRCLKENA_MASK_0, + (pwrctrl->srclkenai_mask ? CC_SRCLKENA_MASK_0 : 0)); + + mmio_write_32(SPM_SLEEP_CA15_WFI0_EN, !!pwrctrl->ca15_wfi0_en); + mmio_write_32(SPM_SLEEP_CA15_WFI1_EN, !!pwrctrl->ca15_wfi1_en); + mmio_write_32(SPM_SLEEP_CA15_WFI2_EN, !!pwrctrl->ca15_wfi2_en); + mmio_write_32(SPM_SLEEP_CA15_WFI3_EN, !!pwrctrl->ca15_wfi3_en); + mmio_write_32(SPM_SLEEP_CA7_WFI0_EN, !!pwrctrl->ca7_wfi0_en); + mmio_write_32(SPM_SLEEP_CA7_WFI1_EN, !!pwrctrl->ca7_wfi1_en); + mmio_write_32(SPM_SLEEP_CA7_WFI2_EN, !!pwrctrl->ca7_wfi2_en); + mmio_write_32(SPM_SLEEP_CA7_WFI3_EN, !!pwrctrl->ca7_wfi3_en); +} + +void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl) +{ + unsigned int val, mask; + + if (pwrctrl->timer_val_cust == 0) + val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX; + else + val = pwrctrl->timer_val_cust; + + mmio_write_32(SPM_PCM_TIMER_VAL, val); + mmio_setbits_32(SPM_PCM_CON1, CON1_CFG_KEY); + + if (pwrctrl->wake_src_cust == 0) + mask = pwrctrl->wake_src; + else + mask = pwrctrl->wake_src_cust; + + if (pwrctrl->syspwreq_mask) + mask &= ~WAKE_SRC_SYSPWREQ; + + mmio_write_32(SPM_SLEEP_WAKEUP_EVENT_MASK, ~mask); + mmio_write_32(SPM_SLEEP_ISR_MASK, 0xfe04); +} + +void spm_get_wakeup_status(struct wake_status *wakesta) +{ + wakesta->assert_pc = mmio_read_32(SPM_PCM_REG_DATA_INI); + wakesta->r12 = mmio_read_32(SPM_PCM_REG12_DATA); + wakesta->raw_sta = mmio_read_32(SPM_SLEEP_ISR_RAW_STA); + wakesta->wake_misc = mmio_read_32(SPM_SLEEP_WAKEUP_MISC); + wakesta->timer_out = mmio_read_32(SPM_PCM_TIMER_OUT); + wakesta->r13 = mmio_read_32(SPM_PCM_REG13_DATA); + wakesta->idle_sta = mmio_read_32(SPM_SLEEP_SUBSYS_IDLE_STA); + wakesta->debug_flag = mmio_read_32(SPM_PCM_PASR_DPD_3); + wakesta->event_reg = mmio_read_32(SPM_PCM_EVENT_REG_STA); + wakesta->isr = mmio_read_32(SPM_SLEEP_ISR_STATUS); +} + +void spm_init_event_vector(const struct pcm_desc *pcmdesc) +{ + /* init event vector register */ + mmio_write_32(SPM_PCM_EVENT_VECTOR0, pcmdesc->vec0); + mmio_write_32(SPM_PCM_EVENT_VECTOR1, pcmdesc->vec1); + mmio_write_32(SPM_PCM_EVENT_VECTOR2, pcmdesc->vec2); + mmio_write_32(SPM_PCM_EVENT_VECTOR3, pcmdesc->vec3); + mmio_write_32(SPM_PCM_EVENT_VECTOR4, pcmdesc->vec4); + mmio_write_32(SPM_PCM_EVENT_VECTOR5, pcmdesc->vec5); + mmio_write_32(SPM_PCM_EVENT_VECTOR6, pcmdesc->vec6); + mmio_write_32(SPM_PCM_EVENT_VECTOR7, pcmdesc->vec7); + + /* event vector will be enabled by PCM itself */ +} + +void spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc) +{ + unsigned int ptr = 0, len, con0; + + ptr = (unsigned int)(unsigned long)(pcmdesc->base); + len = pcmdesc->size - 1; + if (mmio_read_32(SPM_PCM_IM_PTR) != ptr || + mmio_read_32(SPM_PCM_IM_LEN) != len || + pcmdesc->sess > 2) { + mmio_write_32(SPM_PCM_IM_PTR, ptr); + mmio_write_32(SPM_PCM_IM_LEN, len); + } else { + mmio_setbits_32(SPM_PCM_CON1, CON1_CFG_KEY | CON1_IM_SLAVE); + } + + /* kick IM to fetch (only toggle IM_KICK) */ + con0 = mmio_read_32(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK); + mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_IM_KICK); + mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY); + + /* kick IM to fetch (only toggle PCM_KICK) */ + con0 = mmio_read_32(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK); + mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_PCM_KICK); + mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY); +} + +void spm_set_sysclk_settle(void) +{ + mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE); + + INFO("settle = %u\n", mmio_read_32(SPM_CLK_SETTLE)); +} + +void spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl) +{ + unsigned int con1; + + con1 = mmio_read_32(SPM_PCM_CON1) & + ~(CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN); + + mmio_write_32(SPM_PCM_CON1, CON1_CFG_KEY | con1); + + if (mmio_read_32(SPM_PCM_TIMER_VAL) > PCM_TIMER_MAX) + mmio_write_32(SPM_PCM_TIMER_VAL, PCM_TIMER_MAX); + + mmio_write_32(SPM_PCM_WDT_TIMER_VAL, + mmio_read_32(SPM_PCM_TIMER_VAL) + PCM_WDT_TIMEOUT); + + mmio_write_32(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_PCM_WDT_EN); + mmio_write_32(SPM_PCM_PASR_DPD_0, 0); + + mmio_write_32(SPM_PCM_MAS_PAUSE_MASK, 0xffffffff); + mmio_write_32(SPM_PCM_REG_DATA_INI, 0); + mmio_clrbits_32(SPM_CLK_CON, CC_DISABLE_DORM_PWR); + + mmio_write_32(SPM_PCM_FLAGS, pwrctrl->pcm_flags); + + mmio_clrsetbits_32(SPM_CLK_CON, CC_LOCK_INFRA_DCM, + (pwrctrl->infra_dcm_lock ? CC_LOCK_INFRA_DCM : 0)); + + mmio_write_32(SPM_PCM_PWR_IO_EN, + (pwrctrl->r0_ctrl_en ? PCM_PWRIO_EN_R0 : 0) | + (pwrctrl->r7_ctrl_en ? PCM_PWRIO_EN_R7 : 0)); +} + +void spm_clean_after_wakeup(void) +{ + mmio_clrsetbits_32(SPM_PCM_CON1, CON1_PCM_WDT_EN, CON1_CFG_KEY); + + mmio_write_32(SPM_PCM_PWR_IO_EN, 0); + mmio_write_32(SPM_SLEEP_CPU_WAKEUP_EVENT, 0); + mmio_clrsetbits_32(SPM_PCM_CON1, CON1_PCM_TIMER_EN, CON1_CFG_KEY); + + mmio_write_32(SPM_SLEEP_WAKEUP_EVENT_MASK, ~0); + mmio_write_32(SPM_SLEEP_ISR_MASK, 0xFF0C); + mmio_write_32(SPM_SLEEP_ISR_STATUS, 0xC); + mmio_write_32(SPM_PCM_SW_INT_CLEAR, 0xFF); +} + +enum wake_reason_t spm_output_wake_reason(struct wake_status *wakesta) +{ + enum wake_reason_t wr; + int i; + + wr = WR_UNKNOWN; + + if (wakesta->assert_pc != 0) { + ERROR("PCM ASSERT AT %u, r12=0x%x, r13=0x%x, debug_flag=0x%x\n", + wakesta->assert_pc, wakesta->r12, wakesta->r13, + wakesta->debug_flag); + return WR_PCM_ASSERT; + } + + if (wakesta->r12 & WAKE_SRC_SPM_MERGE) { + if (wakesta->wake_misc & WAKE_MISC_PCM_TIMER) + wr = WR_PCM_TIMER; + if (wakesta->wake_misc & WAKE_MISC_CPU_WAKE) + wr = WR_WAKE_SRC; + } + + for (i = 1; i < 32; i++) { + if (wakesta->r12 & (1U << i)) + wr = WR_WAKE_SRC; + } + + if ((wakesta->event_reg & 0x100000) == 0) { + INFO("pcm sleep abort!\n"); + wr = WR_PCM_ABORT; + } + + INFO("timer_out = %u, r12 = 0x%x, r13 = 0x%x, debug_flag = 0x%x\n", + wakesta->timer_out, wakesta->r12, wakesta->r13, + wakesta->debug_flag); + + INFO("raw_sta = 0x%x, idle_sta = 0x%x, event_reg = 0x%x, isr = 0x%x\n", + wakesta->raw_sta, wakesta->idle_sta, wakesta->event_reg, + wakesta->isr); + + return wr; +} + +void spm_boot_init(void) +{ + /* set spm transaction to secure mode */ + mmio_write_32(DEVAPC0_APC_CON, 0x0); + mmio_write_32(DEVAPC0_MAS_SEC_0, 0x200); + + /* Only CPU0 is online during boot, initialize cpu online reserve bit */ + mmio_write_32(SPM_PCM_RESERVE, 0xFE); + mmio_clrbits_32(AP_PLL_CON3, 0xFFFFF); + mmio_clrbits_32(AP_PLL_CON4, 0xF); + spm_lock_init(); + spm_register_init(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h new file mode 100644 index 0000000..0c05410 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SPM_H +#define SPM_H + +#define SPM_POWERON_CONFIG_SET (SPM_BASE + 0x000) +#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x010) +#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x014) +#define SPM_CLK_SETTLE (SPM_BASE + 0x100) +#define SPM_CA7_CPU1_PWR_CON (SPM_BASE + 0x218) +#define SPM_CA7_CPU2_PWR_CON (SPM_BASE + 0x21c) +#define SPM_CA7_CPU3_PWR_CON (SPM_BASE + 0x220) +#define SPM_CA7_CPU1_L1_PDN (SPM_BASE + 0x264) +#define SPM_CA7_CPU2_L1_PDN (SPM_BASE + 0x26c) +#define SPM_CA7_CPU3_L1_PDN (SPM_BASE + 0x274) +#define SPM_MD32_SRAM_CON (SPM_BASE + 0x2c8) +#define SPM_PCM_CON0 (SPM_BASE + 0x310) +#define SPM_PCM_CON1 (SPM_BASE + 0x314) +#define SPM_PCM_IM_PTR (SPM_BASE + 0x318) +#define SPM_PCM_IM_LEN (SPM_BASE + 0x31c) +#define SPM_PCM_REG_DATA_INI (SPM_BASE + 0x320) +#define SPM_PCM_EVENT_VECTOR0 (SPM_BASE + 0x340) +#define SPM_PCM_EVENT_VECTOR1 (SPM_BASE + 0x344) +#define SPM_PCM_EVENT_VECTOR2 (SPM_BASE + 0x348) +#define SPM_PCM_EVENT_VECTOR3 (SPM_BASE + 0x34c) +#define SPM_PCM_MAS_PAUSE_MASK (SPM_BASE + 0x354) +#define SPM_PCM_PWR_IO_EN (SPM_BASE + 0x358) +#define SPM_PCM_TIMER_VAL (SPM_BASE + 0x35c) +#define SPM_PCM_TIMER_OUT (SPM_BASE + 0x360) +#define SPM_PCM_REG0_DATA (SPM_BASE + 0x380) +#define SPM_PCM_REG1_DATA (SPM_BASE + 0x384) +#define SPM_PCM_REG2_DATA (SPM_BASE + 0x388) +#define SPM_PCM_REG3_DATA (SPM_BASE + 0x38c) +#define SPM_PCM_REG4_DATA (SPM_BASE + 0x390) +#define SPM_PCM_REG5_DATA (SPM_BASE + 0x394) +#define SPM_PCM_REG6_DATA (SPM_BASE + 0x398) +#define SPM_PCM_REG7_DATA (SPM_BASE + 0x39c) +#define SPM_PCM_REG8_DATA (SPM_BASE + 0x3a0) +#define SPM_PCM_REG9_DATA (SPM_BASE + 0x3a4) +#define SPM_PCM_REG10_DATA (SPM_BASE + 0x3a8) +#define SPM_PCM_REG11_DATA (SPM_BASE + 0x3ac) +#define SPM_PCM_REG12_DATA (SPM_BASE + 0x3b0) +#define SPM_PCM_REG13_DATA (SPM_BASE + 0x3b4) +#define SPM_PCM_REG14_DATA (SPM_BASE + 0x3b8) +#define SPM_PCM_REG15_DATA (SPM_BASE + 0x3bc) +#define SPM_PCM_EVENT_REG_STA (SPM_BASE + 0x3c0) +#define SPM_PCM_FSM_STA (SPM_BASE + 0x3c4) +#define SPM_PCM_IM_HOST_RW_PTR (SPM_BASE + 0x3c8) +#define SPM_PCM_IM_HOST_RW_DAT (SPM_BASE + 0x3cc) +#define SPM_PCM_EVENT_VECTOR4 (SPM_BASE + 0x3d0) +#define SPM_PCM_EVENT_VECTOR5 (SPM_BASE + 0x3d4) +#define SPM_PCM_EVENT_VECTOR6 (SPM_BASE + 0x3d8) +#define SPM_PCM_EVENT_VECTOR7 (SPM_BASE + 0x3dc) +#define SPM_PCM_SW_INT_SET (SPM_BASE + 0x3e0) +#define SPM_PCM_SW_INT_CLEAR (SPM_BASE + 0x3e4) +#define SPM_CLK_CON (SPM_BASE + 0x400) +#define SPM_SLEEP_PTPOD2_CON (SPM_BASE + 0x408) +#define SPM_APMCU_PWRCTL (SPM_BASE + 0x600) +#define SPM_AP_DVFS_CON_SET (SPM_BASE + 0x604) +#define SPM_AP_STANBY_CON (SPM_BASE + 0x608) +#define SPM_PWR_STATUS (SPM_BASE + 0x60c) +#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x610) +#define SPM_AP_BSI_REQ (SPM_BASE + 0x614) +#define SPM_SLEEP_TIMER_STA (SPM_BASE + 0x720) +#define SPM_SLEEP_WAKEUP_EVENT_MASK (SPM_BASE + 0x810) +#define SPM_SLEEP_CPU_WAKEUP_EVENT (SPM_BASE + 0x814) +#define SPM_SLEEP_MD32_WAKEUP_EVENT_MASK (SPM_BASE + 0x818) +#define SPM_PCM_WDT_TIMER_VAL (SPM_BASE + 0x824) +#define SPM_PCM_WDT_TIMER_OUT (SPM_BASE + 0x828) +#define SPM_PCM_MD32_MAILBOX (SPM_BASE + 0x830) +#define SPM_PCM_MD32_IRQ (SPM_BASE + 0x834) +#define SPM_SLEEP_ISR_MASK (SPM_BASE + 0x900) +#define SPM_SLEEP_ISR_STATUS (SPM_BASE + 0x904) +#define SPM_SLEEP_ISR_RAW_STA (SPM_BASE + 0x910) +#define SPM_SLEEP_MD32_ISR_RAW_STA (SPM_BASE + 0x914) +#define SPM_SLEEP_WAKEUP_MISC (SPM_BASE + 0x918) +#define SPM_SLEEP_BUS_PROTECT_RDY (SPM_BASE + 0x91c) +#define SPM_SLEEP_SUBSYS_IDLE_STA (SPM_BASE + 0x920) +#define SPM_PCM_RESERVE (SPM_BASE + 0xb00) +#define SPM_PCM_RESERVE2 (SPM_BASE + 0xb04) +#define SPM_PCM_FLAGS (SPM_BASE + 0xb08) +#define SPM_PCM_SRC_REQ (SPM_BASE + 0xb0c) +#define SPM_PCM_DEBUG_CON (SPM_BASE + 0xb20) +#define SPM_CA7_CPU0_IRQ_MASK (SPM_BASE + 0xb30) +#define SPM_CA7_CPU1_IRQ_MASK (SPM_BASE + 0xb34) +#define SPM_CA7_CPU2_IRQ_MASK (SPM_BASE + 0xb38) +#define SPM_CA7_CPU3_IRQ_MASK (SPM_BASE + 0xb3c) +#define SPM_CA15_CPU0_IRQ_MASK (SPM_BASE + 0xb40) +#define SPM_CA15_CPU1_IRQ_MASK (SPM_BASE + 0xb44) +#define SPM_CA15_CPU2_IRQ_MASK (SPM_BASE + 0xb48) +#define SPM_CA15_CPU3_IRQ_MASK (SPM_BASE + 0xb4c) +#define SPM_PCM_PASR_DPD_0 (SPM_BASE + 0xb60) +#define SPM_PCM_PASR_DPD_1 (SPM_BASE + 0xb64) +#define SPM_PCM_PASR_DPD_2 (SPM_BASE + 0xb68) +#define SPM_PCM_PASR_DPD_3 (SPM_BASE + 0xb6c) +#define SPM_SLEEP_CA7_WFI0_EN (SPM_BASE + 0xf00) +#define SPM_SLEEP_CA7_WFI1_EN (SPM_BASE + 0xf04) +#define SPM_SLEEP_CA7_WFI2_EN (SPM_BASE + 0xf08) +#define SPM_SLEEP_CA7_WFI3_EN (SPM_BASE + 0xf0c) +#define SPM_SLEEP_CA15_WFI0_EN (SPM_BASE + 0xf10) +#define SPM_SLEEP_CA15_WFI1_EN (SPM_BASE + 0xf14) +#define SPM_SLEEP_CA15_WFI2_EN (SPM_BASE + 0xf18) +#define SPM_SLEEP_CA15_WFI3_EN (SPM_BASE + 0xf1c) + +#define AP_PLL_CON3 0x1020900c +#define AP_PLL_CON4 0x10209010 + +#define SPM_PROJECT_CODE 0xb16 + +#define SPM_REGWR_EN (1U << 0) +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) + +#define SPM_CPU_PDN_DIS (1U << 0) +#define SPM_INFRA_PDN_DIS (1U << 1) +#define SPM_DDRPHY_PDN_DIS (1U << 2) +#define SPM_DUALVCORE_PDN_DIS (1U << 3) +#define SPM_PASR_DIS (1U << 4) +#define SPM_DPD_DIS (1U << 5) +#define SPM_SODI_DIS (1U << 6) +#define SPM_MEMPLL_RESET (1U << 7) +#define SPM_MAINPLL_PDN_DIS (1U << 8) +#define SPM_CPU_DVS_DIS (1U << 9) +#define SPM_CPU_DORMANT (1U << 10) +#define SPM_EXT_VSEL_GPIO103 (1U << 11) +#define SPM_DDR_HIGH_SPEED (1U << 12) +#define SPM_OPT (1U << 13) + +#define POWER_ON_VAL1_DEF 0x01011820 +#define PCM_FSM_STA_DEF 0x48490 +#define PCM_END_FSM_STA_DEF 0x08490 +#define PCM_END_FSM_STA_MASK 0x3fff0 +#define PCM_HANDSHAKE_SEND1 0xbeefbeef + +#define PCM_WDT_TIMEOUT (30 * 32768) +#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT) + +#define CON0_PCM_KICK (1U << 0) +#define CON0_IM_KICK (1U << 1) +#define CON0_IM_SLEEP_DVS (1U << 3) +#define CON0_PCM_SW_RESET (1U << 15) +#define CON0_CFG_KEY (SPM_PROJECT_CODE << 16) + +#define CON1_IM_SLAVE (1U << 0) +#define CON1_MIF_APBEN (1U << 3) +#define CON1_PCM_TIMER_EN (1U << 5) +#define CON1_IM_NONRP_EN (1U << 6) +#define CON1_PCM_WDT_EN (1U << 8) +#define CON1_PCM_WDT_WAKE_MODE (1U << 9) +#define CON1_SPM_SRAM_SLP_B (1U << 10) +#define CON1_SPM_SRAM_ISO_B (1U << 11) +#define CON1_EVENT_LOCK_EN (1U << 12) +#define CON1_CFG_KEY (SPM_PROJECT_CODE << 16) + +#define PCM_PWRIO_EN_R0 (1U << 0) +#define PCM_PWRIO_EN_R7 (1U << 7) +#define PCM_RF_SYNC_R0 (1U << 16) +#define PCM_RF_SYNC_R2 (1U << 18) +#define PCM_RF_SYNC_R6 (1U << 22) +#define PCM_RF_SYNC_R7 (1U << 23) + +#define CC_SYSCLK0_EN_0 (1U << 0) +#define CC_SYSCLK0_EN_1 (1U << 1) +#define CC_SYSCLK1_EN_0 (1U << 2) +#define CC_SYSCLK1_EN_1 (1U << 3) +#define CC_SYSSETTLE_SEL (1U << 4) +#define CC_LOCK_INFRA_DCM (1U << 5) +#define CC_SRCLKENA_MASK_0 (1U << 6) +#define CC_CXO32K_RM_EN_MD1 (1U << 9) +#define CC_CXO32K_RM_EN_MD2 (1U << 10) +#define CC_CLKSQ1_SEL (1U << 12) +#define CC_DISABLE_DORM_PWR (1U << 14) +#define CC_MD32_DCM_EN (1U << 18) + +#define WFI_OP_AND 1 +#define WFI_OP_OR 0 + +#define WAKE_MISC_PCM_TIMER (1U << 19) +#define WAKE_MISC_CPU_WAKE (1U << 20) + +/* define WAKE_SRC_XXX */ +#define WAKE_SRC_SPM_MERGE (1 << 0) +#define WAKE_SRC_KP (1 << 2) +#define WAKE_SRC_WDT (1 << 3) +#define WAKE_SRC_GPT (1 << 4) +#define WAKE_SRC_EINT (1 << 6) +#define WAKE_SRC_LOW_BAT (1 << 9) +#define WAKE_SRC_MD32 (1 << 10) +#define WAKE_SRC_USB_CD (1 << 14) +#define WAKE_SRC_USB_PDN (1 << 15) +#define WAKE_SRC_AFE (1 << 20) +#define WAKE_SRC_THERM (1 << 21) +#define WAKE_SRC_CIRQ (1 << 22) +#define WAKE_SRC_SYSPWREQ (1 << 24) +#define WAKE_SRC_SEJ (1 << 27) +#define WAKE_SRC_ALL_MD32 (1 << 28) +#define WAKE_SRC_CPU_IRQ (1 << 29) + +enum wake_reason_t { + WR_NONE = 0, + WR_UART_BUSY = 1, + WR_PCM_ASSERT = 2, + WR_PCM_TIMER = 3, + WR_PCM_ABORT = 4, + WR_WAKE_SRC = 5, + WR_UNKNOWN = 6, +}; + +struct pwr_ctrl { + unsigned int pcm_flags; + unsigned int pcm_flags_cust; + unsigned int pcm_reserve; + unsigned int timer_val; + unsigned int timer_val_cust; + unsigned int wake_src; + unsigned int wake_src_cust; + unsigned int wake_src_md32; + unsigned short r0_ctrl_en; + unsigned short r7_ctrl_en; + unsigned short infra_dcm_lock; + unsigned short pcm_apsrc_req; + unsigned short mcusys_idle_mask; + unsigned short ca15top_idle_mask; + unsigned short ca7top_idle_mask; + unsigned short wfi_op; + unsigned short ca15_wfi0_en; + unsigned short ca15_wfi1_en; + unsigned short ca15_wfi2_en; + unsigned short ca15_wfi3_en; + unsigned short ca7_wfi0_en; + unsigned short ca7_wfi1_en; + unsigned short ca7_wfi2_en; + unsigned short ca7_wfi3_en; + unsigned short disp_req_mask; + unsigned short mfg_req_mask; + unsigned short md32_req_mask; + unsigned short syspwreq_mask; + unsigned short srclkenai_mask; +}; + +struct wake_status { + unsigned int assert_pc; + unsigned int r12; + unsigned int raw_sta; + unsigned int wake_misc; + unsigned int timer_out; + unsigned int r13; + unsigned int idle_sta; + unsigned int debug_flag; + unsigned int event_reg; + unsigned int isr; +}; + +struct pcm_desc { + const char *version; /* PCM code version */ + const unsigned int *base; /* binary array base */ + const unsigned int size; /* binary array size */ + const unsigned char sess; /* session number */ + const unsigned char replace; /* replace mode */ + + unsigned int vec0; /* event vector 0 config */ + unsigned int vec1; /* event vector 1 config */ + unsigned int vec2; /* event vector 2 config */ + unsigned int vec3; /* event vector 3 config */ + unsigned int vec4; /* event vector 4 config */ + unsigned int vec5; /* event vector 5 config */ + unsigned int vec6; /* event vector 6 config */ + unsigned int vec7; /* event vector 7 config */ +}; + +struct spm_lp_scen { + const struct pcm_desc *pcmdesc; + struct pwr_ctrl *pwrctrl; +}; + +#define EVENT_VEC(event, resume, imme, pc) \ + (((pc) << 16) | \ + (!!(imme) << 6) | \ + (!!(resume) << 5) | \ + ((event) & 0x1f)) + +#define spm_read(addr) mmio_read_32(addr) +#define spm_write(addr, val) mmio_write_32(addr, val) + +#define is_cpu_pdn(flags) (!((flags) & SPM_CPU_PDN_DIS)) +#define is_infra_pdn(flags) (!((flags) & SPM_INFRA_PDN_DIS)) +#define is_ddrphy_pdn(flags) (!((flags) & SPM_DDRPHY_PDN_DIS)) + +static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl, + unsigned int flags) +{ + flags &= ~SPM_EXT_VSEL_GPIO103; + + if (pwrctrl->pcm_flags_cust == 0) + pwrctrl->pcm_flags = flags; + else + pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust; +} + +static inline void set_pwrctrl_pcm_data(struct pwr_ctrl *pwrctrl, + unsigned int data) +{ + pwrctrl->pcm_reserve = data; +} + +void spm_reset_and_init_pcm(void); + +void spm_init_pcm_register(void); /* init r0 and r7 */ +void spm_set_power_control(const struct pwr_ctrl *pwrctrl); +void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl); + +void spm_get_wakeup_status(struct wake_status *wakesta); +void spm_set_sysclk_settle(void); +void spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl); +void spm_clean_after_wakeup(void); +enum wake_reason_t spm_output_wake_reason(struct wake_status *wakesta); +void spm_register_init(void); +void spm_go_to_hotplug(void); +void spm_init_event_vector(const struct pcm_desc *pcmdesc); +void spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc); +int is_mcdi_ready(void); +int is_hotplug_ready(void); +int is_suspend_ready(void); +void set_mcdi_ready(void); +void set_hotplug_ready(void); +void set_suspend_ready(void); +void clear_all_ready(void); +void spm_lock_init(void); +void spm_lock_get(void); +void spm_lock_release(void); +void spm_boot_init(void); + +#endif /* SPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c new file mode 100644 index 0000000..b2b9ada --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* + * System Power Manager (SPM) is a hardware module, which controls cpu or + * system power for different power scenarios using different firmware. + * This driver controls the cpu power in cpu hotplug flow. + */ + +#define PCM_HOTPLUG_VALID_MASK 0x0000ff00 +#define PCM_HOTPLUG_VALID_SHIFT 0x8 + +/********************************************************** + * PCM sequence for CPU hotplug + **********************************************************/ +static const unsigned int hotplug_binary[] = { + 0x1900001f, 0x1020020c, 0x1950001f, 0x1020020c, 0xa9400005, 0x00000001, + 0xe1000005, 0x1910001f, 0x10006720, 0x814c9001, 0xd82000e5, 0x17c07c1f, + 0x1900001f, 0x10001220, 0x1950001f, 0x10001220, 0xa15f0405, 0xe1000005, + 0x1900001f, 0x10001228, 0x1950001f, 0x10001228, 0x810f1401, 0xd8200244, + 0x17c07c1f, 0xe2e0006d, 0xe2e0002d, 0x1a00001f, 0x100062b8, 0x1910001f, + 0x100062b8, 0xa9000004, 0x00000001, 0xe2000004, 0x1910001f, 0x100062b8, + 0x81142804, 0xd8200444, 0x17c07c1f, 0xe2e0002c, 0xe2e0003c, 0xe2e0003e, + 0xe2e0003a, 0xe2e00032, 0x1910001f, 0x1000660c, 0x81079001, 0x1950001f, + 0x10006610, 0x81479401, 0xa1001404, 0xd8000584, 0x17c07c1f, 0x1900001f, + 0x10006404, 0x1950001f, 0x10006404, 0xa1568405, 0xe1000005, 0xf0000000, + 0x17c07c1f, 0x1900001f, 0x10006404, 0x1950001f, 0x10006404, 0x89400005, + 0x0000dfff, 0xe1000005, 0xe2e00036, 0xe2e0003e, 0x1910001f, 0x1000660c, + 0x81079001, 0x1950001f, 0x10006610, 0x81479401, 0x81001404, 0xd82008c4, + 0x17c07c1f, 0xe2e0002e, 0x1a00001f, 0x100062b8, 0x1910001f, 0x100062b8, + 0x89000004, 0x0000fffe, 0xe2000004, 0x1910001f, 0x100062b8, 0x81142804, + 0xd8000ae4, 0x17c07c1f, 0xe2e0006e, 0xe2e0004e, 0xe2e0004c, 0xe2e0004d, + 0x1900001f, 0x10001220, 0x1950001f, 0x10001220, 0x89400005, 0xbfffffff, + 0xe1000005, 0x1900001f, 0x10001228, 0x1950001f, 0x10001228, 0x810f1401, + 0xd8000ce4, 0x17c07c1f, 0x1900001f, 0x1020020c, 0x1950001f, 0x1020020c, + 0x89400005, 0xfffffffe, 0xe1000005, 0xf0000000, 0x17c07c1f, 0x1212841f, + 0xe2e00036, 0xe2e0003e, 0x1380201f, 0xe2e0003c, 0xe2a00000, 0x1b80001f, + 0x20000080, 0xe2e0007c, 0x1b80001f, 0x20000003, 0xe2e0005c, 0xe2e0004c, + 0xe2e0004d, 0xf0000000, 0x17c07c1f, 0xe2e0004f, 0xe2e0006f, 0xe2e0002f, + 0xe2a00001, 0x1b80001f, 0x20000080, 0xe2e0002e, 0xe2e0003e, 0xe2e00032, + 0xf0000000, 0x17c07c1f, 0x1212841f, 0xe2e00026, 0xe2e0002e, 0x1380201f, + 0x1a00001f, 0x100062b4, 0x1910001f, 0x100062b4, 0x81322804, 0xe2000004, + 0x81202804, 0xe2000004, 0x1b80001f, 0x20000034, 0x1910001f, 0x100062b4, + 0x81142804, 0xd8001404, 0x17c07c1f, 0xe2e0000e, 0xe2e0000c, 0xe2e0000d, + 0xf0000000, 0x17c07c1f, 0xe2e0002d, 0x1a00001f, 0x100062b4, 0x1910001f, + 0x100062b4, 0xa1002804, 0xe2000004, 0xa1122804, 0xe2000004, 0x1b80001f, + 0x20000080, 0x1910001f, 0x100062b4, 0x81142804, 0xd82016a4, 0x17c07c1f, + 0xe2e0002f, 0xe2e0002b, 0xe2e00023, 0x1380201f, 0xe2e00022, 0xf0000000, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x1840001f, 0x00000001, 0x1840001f, 0x00000001, + 0x1840001f, 0x00000001, 0xa1d48407, 0x1b00001f, 0x2f7be75f, 0xe8208000, + 0x10006354, 0xfffe7b47, 0xa1d10407, 0x1b80001f, 0x20000020, 0x17c07c1f, + 0x1910001f, 0x10006b00, 0x81461001, 0xb14690a1, 0xd82044e5, 0x17c07c1f, + 0x1910001f, 0x10006610, 0x81079001, 0xd80044e4, 0x17c07c1f, 0x1990001f, + 0x10006b00, 0x81421801, 0x82429801, 0x81402405, 0xd80044e5, 0x17c07c1f, + 0x1a40001f, 0x100062b0, 0x1280041f, 0xc24007a0, 0x17c07c1f, 0x1910001f, + 0x10006b00, 0x81449001, 0xd8204be5, 0x17c07c1f, 0x1910001f, 0x10006b00, + 0x81009001, 0xd8204984, 0x17c07c1f, 0x1910001f, 0x10006610, 0x81051001, + 0xd8204be4, 0x17c07c1f, 0x1910001f, 0x10006720, 0x81489001, 0xd82046c5, + 0x17c07c1f, 0x1a40001f, 0x10006218, 0x1a80001f, 0x10006264, 0xc24010e0, + 0x17c07c1f, 0x1910001f, 0x1000660c, 0x81051001, 0x1950001f, 0x10006610, + 0x81451401, 0xa1001404, 0xd8004824, 0x17c07c1f, 0xd0004b00, 0x17c07c1f, + 0x17c07c1f, 0x1910001f, 0x10006610, 0x81051001, 0xd8004be4, 0x17c07c1f, + 0x1a40001f, 0x10006218, 0x1a80001f, 0x10006264, 0xc2400ee0, 0x17c07c1f, + 0x1910001f, 0x10006b00, 0x89000004, 0xfffffdff, 0x1940001f, 0x10006b00, + 0xe1400004, 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81451001, 0xd8205305, + 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81011001, 0xd82050a4, 0x17c07c1f, + 0x1910001f, 0x10006610, 0x81059001, 0xd8205304, 0x17c07c1f, 0x1910001f, + 0x10006720, 0x81491001, 0xd8204de5, 0x17c07c1f, 0x1a40001f, 0x1000621c, + 0x1a80001f, 0x1000626c, 0xc24010e0, 0x17c07c1f, 0x1910001f, 0x1000660c, + 0x81059001, 0x1950001f, 0x10006610, 0x81459401, 0xa1001404, 0xd8004f44, + 0x17c07c1f, 0xd0005220, 0x17c07c1f, 0x17c07c1f, 0x1910001f, 0x10006610, + 0x81059001, 0xd8005304, 0x17c07c1f, 0x1a40001f, 0x1000621c, 0x1a80001f, + 0x1000626c, 0xc2400ee0, 0x17c07c1f, 0x1910001f, 0x10006b00, 0x89000004, + 0xfffffbff, 0x1940001f, 0x10006b00, 0xe1400004, 0x17c07c1f, 0x1910001f, + 0x10006b00, 0x81459001, 0xd8205a25, 0x17c07c1f, 0x1910001f, 0x10006b00, + 0x81019001, 0xd82057c4, 0x17c07c1f, 0x1910001f, 0x10006610, 0x81061001, + 0xd8205a24, 0x17c07c1f, 0x1910001f, 0x10006720, 0x81499001, 0xd8205505, + 0x17c07c1f, 0x1a40001f, 0x10006220, 0x1a80001f, 0x10006274, 0xc24010e0, + 0x17c07c1f, 0x1910001f, 0x1000660c, 0x81061001, 0x1950001f, 0x10006610, + 0x81461401, 0xa1001404, 0xd8005664, 0x17c07c1f, 0xd0005940, 0x17c07c1f, + 0x17c07c1f, 0x1910001f, 0x10006610, 0x81061001, 0xd8005a24, 0x17c07c1f, + 0x1a40001f, 0x10006220, 0x1a80001f, 0x10006274, 0xc2400ee0, 0x17c07c1f, + 0x1910001f, 0x10006b00, 0x89000004, 0xfffff7ff, 0x1940001f, 0x10006b00, + 0xe1400004, 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81461001, 0xd8206185, + 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81021001, 0xd8205ec4, 0x17c07c1f, + 0x1910001f, 0x10006610, 0x81081001, 0xd8206184, 0x17c07c1f, 0x1910001f, + 0x10006720, 0x814a1001, 0xd8205c25, 0x17c07c1f, 0x1a40001f, 0x100062a0, + 0x1280041f, 0xc2401540, 0x17c07c1f, 0x1910001f, 0x1000660c, 0x81081001, + 0x1950001f, 0x10006610, 0x81481401, 0xa1001404, 0xd8005d64, 0x17c07c1f, + 0xd00060a0, 0x17c07c1f, 0x17c07c1f, 0x1910001f, 0x10006610, 0x81479001, + 0x81881001, 0x69a00006, 0x00000000, 0x81401805, 0xd8206185, 0x17c07c1f, + 0x1a40001f, 0x100062a0, 0x1280041f, 0xc2401240, 0x17c07c1f, 0x1910001f, + 0x10006b00, 0x89000004, 0xffffefff, 0x1940001f, 0x10006b00, 0xe1400004, + 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81469001, 0xd82068e5, 0x17c07c1f, + 0x1910001f, 0x10006b00, 0x81029001, 0xd8206624, 0x17c07c1f, 0x1910001f, + 0x10006610, 0x81089001, 0xd82068e4, 0x17c07c1f, 0x1910001f, 0x10006720, + 0x814a9001, 0xd8206385, 0x17c07c1f, 0x1a40001f, 0x100062a4, 0x1290841f, + 0xc2401540, 0x17c07c1f, 0x1910001f, 0x1000660c, 0x81089001, 0x1950001f, + 0x10006610, 0x81489401, 0xa1001404, 0xd80064c4, 0x17c07c1f, 0xd0006800, + 0x17c07c1f, 0x17c07c1f, 0x1910001f, 0x10006610, 0x81479001, 0x81889001, + 0x69a00006, 0x00000000, 0x81401805, 0xd82068e5, 0x17c07c1f, 0x1a40001f, + 0x100062a4, 0x1290841f, 0xc2401240, 0x17c07c1f, 0x1910001f, 0x10006b00, + 0x89000004, 0xffffdfff, 0x1940001f, 0x10006b00, 0xe1400004, 0x1910001f, + 0x10006610, 0x81479001, 0x81881001, 0x69600005, 0x00000000, 0xa1401805, + 0x81889001, 0xa1401805, 0xd8006bc5, 0x17c07c1f, 0x1910001f, 0x10006b00, + 0x81421001, 0x82429001, 0x82802405, 0xd8206bca, 0x17c07c1f, 0x1a40001f, + 0x100062b0, 0x1280041f, 0xc2400000, 0x17c07c1f, 0x1990001f, 0x10006b00, + 0x89800006, 0x00003f00, 0x69200006, 0x00000000, 0xd82041e4, 0x17c07c1f, + 0x1990001f, 0x10006320, 0x69200006, 0xbeefbeef, 0xd8006dc4, 0x17c07c1f, + 0xd00041e0, 0x17c07c1f, 0x1910001f, 0x10006358, 0x810b1001, 0xd8006dc4, + 0x17c07c1f, 0x1980001f, 0xdeaddead, 0x19c0001f, 0x01411820, 0xf0000000 +}; +static const struct pcm_desc hotplug_pcm = { + .version = "pcm_power_down_mt8173_V37", + .base = hotplug_binary, + .size = 888, + .sess = 2, + .replace = 0, +}; + +static struct pwr_ctrl hotplug_ctrl = { + .wake_src = 0, + .wake_src_md32 = 0, + .wfi_op = WFI_OP_OR, + .mcusys_idle_mask = 1, + .ca7top_idle_mask = 1, + .ca15top_idle_mask = 1, + .disp_req_mask = 1, + .mfg_req_mask = 1, + .md32_req_mask = 1, + .syspwreq_mask = 1, + .pcm_flags = 0, +}; + +static const struct spm_lp_scen spm_hotplug = { + .pcmdesc = &hotplug_pcm, + .pwrctrl = &hotplug_ctrl, +}; + +void spm_go_to_hotplug(void) +{ + const struct pcm_desc *pcmdesc = spm_hotplug.pcmdesc; + struct pwr_ctrl *pwrctrl = spm_hotplug.pwrctrl; + + set_pwrctrl_pcm_flags(pwrctrl, 0); + spm_reset_and_init_pcm(); + spm_kick_im_to_fetch(pcmdesc); + spm_set_power_control(pwrctrl); + spm_set_wakeup_event(pwrctrl); + spm_kick_pcm_to_run(pwrctrl); +} + +void spm_clear_hotplug(void) +{ + /* Inform SPM that CPU wants to program CPU_WAKEUP_EVENT and + * DISABLE_CPU_DROM */ + + mmio_write_32(SPM_PCM_REG_DATA_INI, PCM_HANDSHAKE_SEND1); + mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R6); + mmio_write_32(SPM_PCM_PWR_IO_EN, 0); + + /* Wait SPM's response, can't use sleep api */ + while ((mmio_read_32(SPM_PCM_FSM_STA) & PCM_END_FSM_STA_MASK) + != PCM_END_FSM_STA_DEF) + ; + + /* no hotplug pcm running */ + clear_all_ready(); +} + +void spm_hotplug_on(unsigned long mpidr) +{ + unsigned long linear_id; + + linear_id = ((mpidr & MPIDR_CLUSTER_MASK) >> 6) | + (mpidr & MPIDR_CPU_MASK); + + spm_lock_get(); + if (is_hotplug_ready() == 0) { + spm_mcdi_wakeup_all_cores(); + mmio_clrbits_32(SPM_PCM_RESERVE, PCM_HOTPLUG_VALID_MASK); + spm_go_to_hotplug(); + set_hotplug_ready(); + } + /* turn on CPUx */ + mmio_clrsetbits_32(SPM_PCM_RESERVE, + PCM_HOTPLUG_VALID_MASK | (1 << linear_id), + 1 << (linear_id + PCM_HOTPLUG_VALID_SHIFT)); + spm_lock_release(); +} + +void spm_hotplug_off(unsigned long mpidr) +{ + unsigned long linear_id; + + linear_id = ((mpidr & MPIDR_CLUSTER_MASK) >> 6) | + (mpidr & MPIDR_CPU_MASK); + + spm_lock_get(); + if (is_hotplug_ready() == 0) { + spm_mcdi_wakeup_all_cores(); + mmio_clrbits_32(SPM_PCM_RESERVE, PCM_HOTPLUG_VALID_MASK); + spm_go_to_hotplug(); + set_hotplug_ready(); + } + mmio_clrsetbits_32(SPM_PCM_RESERVE, PCM_HOTPLUG_VALID_MASK, + (1 << linear_id) | + (1 << (linear_id + PCM_HOTPLUG_VALID_SHIFT))); + spm_lock_release(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h new file mode 100644 index 0000000..00849a2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SPM_HOTPLUG_H +#define SPM_HOTPLUG_H + +void spm_clear_hotplug(void); +void spm_hotplug_off(unsigned long mpidr); +void spm_hotplug_on(unsigned long mpidr); + +#endif /* SPM_HOTPLUG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c new file mode 100644 index 0000000..ea5f2bb --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * System Power Manager (SPM) is a hardware module, which controls cpu or + * system power for different power scenarios using different firmware. + * This driver controls the cpu power in cpu idle power saving state. + */ + +#define WAKE_SRC_FOR_MCDI \ + (WAKE_SRC_KP | WAKE_SRC_GPT | WAKE_SRC_EINT | \ + WAKE_SRC_MD32 | WAKE_SRC_USB_CD | WAKE_SRC_USB_PDN | \ + WAKE_SRC_AFE | WAKE_SRC_THERM | WAKE_SRC_CIRQ | \ + WAKE_SRC_SYSPWREQ | WAKE_SRC_CPU_IRQ) +#define PCM_MCDI_HANDSHAKE_SYNC 0xbeefbeef +#define PCM_MCDI_HANDSHAKE_ACK 0xdeaddead +#define PCM_MCDI_UPDATE_INFORM 0xabcdabcd +#define PCM_MCDI_CKECK_DONE 0x12345678 +#define PCM_MCDI_ALL_CORE_AWAKE 0x0 +#define PCM_MCDI_OFFLOADED 0xaa55aa55 +#define PCM_MCDI_CA72_CPUTOP_PWRCTL (0x1 << 16) +#define PCM_MCDI_CA53_CPUTOP_PWRCTL (0x1 << 17) +#define PCM_MCDI_CA72_PWRSTA_SHIFT 16 +#define PCM_MCDI_CA53_PWRSTA_SHIFT 9 + +static const unsigned int mcdi_binary[] = { + 0x1a10001f, 0x10006b04, 0x1890001f, 0x10006b6c, 0x1a40001f, 0x10006210, + 0x18d0001f, 0x10006210, 0x81002001, 0xd82001c4, 0x17c07c1f, 0xa0900402, + 0xc2401540, 0x17c07c1f, 0x81052001, 0xd8200284, 0x17c07c1f, 0xa0950402, + 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x10006230, 0x18d0001f, 0x10006230, + 0x8100a001, 0xd82003c4, 0x17c07c1f, 0xa0908402, 0xc2401540, 0x17c07c1f, + 0x8105a001, 0xd8200484, 0x17c07c1f, 0xa0958402, 0xc2401b80, 0x17c07c1f, + 0x1a40001f, 0x10006238, 0x18d0001f, 0x10006238, 0x81012001, 0xd82005c4, + 0x17c07c1f, 0xa0910402, 0xc2401540, 0x17c07c1f, 0x81062001, 0xd8200684, + 0x17c07c1f, 0xa0960402, 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x1000623c, + 0x18d0001f, 0x1000623c, 0x8101a001, 0xd82007c4, 0x17c07c1f, 0xa0918402, + 0xc2401540, 0x17c07c1f, 0x8106a001, 0xd8200884, 0x17c07c1f, 0xa0968402, + 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x10006298, 0x18d0001f, 0x10006298, + 0x81022001, 0xd82009c4, 0x17c07c1f, 0xa0920402, 0xc2401540, 0x17c07c1f, + 0x81072001, 0xd8200a84, 0x17c07c1f, 0xa0970402, 0xc2401b80, 0x17c07c1f, + 0x1a40001f, 0x1000629c, 0x18d0001f, 0x1000629c, 0x8102a001, 0xd8200bc4, + 0x17c07c1f, 0xa0928402, 0xc2401540, 0x17c07c1f, 0x8107a001, 0xd8200c84, + 0x17c07c1f, 0xa0978402, 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x100062c4, + 0x18d0001f, 0x100062c4, 0x81032001, 0xd8200dc4, 0x17c07c1f, 0xa0930402, + 0xc2401540, 0x17c07c1f, 0x81082001, 0xd8200e84, 0x17c07c1f, 0xa0980402, + 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x100062c0, 0x18d0001f, 0x100062c0, + 0x8103a001, 0xd8200fc4, 0x17c07c1f, 0xa0938402, 0xc2401540, 0x17c07c1f, + 0x8108a001, 0xd8201084, 0x17c07c1f, 0xa0988402, 0xc2401b80, 0x17c07c1f, + 0x1a40001f, 0x10006214, 0x18d0001f, 0x10006214, 0x81042001, 0xd82011c4, + 0x17c07c1f, 0xa0940402, 0xc2401540, 0x17c07c1f, 0x81092001, 0xd8201284, + 0x17c07c1f, 0xa0990402, 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x100062cc, + 0x18d0001f, 0x100062cc, 0x8104a001, 0xd82013c4, 0x17c07c1f, 0xa0948402, + 0xc2401540, 0x17c07c1f, 0x8109a001, 0xd8201484, 0x17c07c1f, 0xa0998402, + 0xc2401b80, 0x17c07c1f, 0x1900001f, 0x10006b6c, 0x80802002, 0xe1000002, + 0xf0000000, 0x17c07c1f, 0xa8c00003, 0x00000004, 0xe2400003, 0xa8c00003, + 0x00000008, 0xe2400003, 0x1b80001f, 0x00000020, 0x88c00003, 0xffffffef, + 0xe2400003, 0x88c00003, 0xfffffffd, 0xe2400003, 0xa8c00003, 0x00000001, + 0xe2400003, 0x88c00003, 0xfffff0ff, 0xe2400003, 0x1b80001f, 0x20000080, + 0x1a90001f, 0x10001220, 0x69200009, 0x1000623c, 0xd8001984, 0x17c07c1f, + 0x69200009, 0x10006214, 0xd8001a64, 0x17c07c1f, 0xd0001b00, 0x17c07c1f, + 0x1900001f, 0x10001220, 0x8a80000a, 0xfffffff9, 0xe100000a, 0xd0001b00, + 0x17c07c1f, 0x1900001f, 0x10001220, 0x8a80000a, 0xff1fbfff, 0xe100000a, + 0x1b80001f, 0x20000080, 0xf0000000, 0x17c07c1f, 0x1a90001f, 0x10001220, + 0x69200009, 0x1000623c, 0xd8001d04, 0x17c07c1f, 0x69200009, 0x10006214, + 0xd8001de4, 0x17c07c1f, 0xd0001e80, 0x17c07c1f, 0x1900001f, 0x10001220, + 0xaa80000a, 0x00000006, 0xe100000a, 0xd0001e80, 0x17c07c1f, 0x1900001f, + 0x10001220, 0xaa80000a, 0x00e04000, 0xe100000a, 0x1b80001f, 0x20000080, + 0x69200009, 0x10006214, 0xd8001fe4, 0x17c07c1f, 0xa8c00003, 0x00000f00, + 0xe2400003, 0xd0002040, 0x17c07c1f, 0xa8c00003, 0x00003f00, 0xe2400003, + 0x1b80001f, 0x20000080, 0xa8c00003, 0x00000002, 0xe2400003, 0x88c00003, + 0xfffffffe, 0xe2400003, 0xa8c00003, 0x00000010, 0xe2400003, 0x88c00003, + 0xfffffffb, 0xe2400003, 0x88c00003, 0xfffffff7, 0xe2400003, 0xf0000000, + 0x17c07c1f, 0xe2e00036, 0xe2e0003e, 0x1b80001f, 0x00000020, 0xe2e0003c, + 0xe8208000, 0x10006244, 0x00000000, 0x1b80001f, 0x20000080, 0xe2e0007c, + 0x1b80001f, 0x20000003, 0xe2e0005c, 0xe2e0004c, 0xe2e0004d, 0xf0000000, + 0x17c07c1f, 0xe2e0004f, 0xe2e0006f, 0xe2e0002f, 0xe8208000, 0x10006244, + 0x00000001, 0x1b80001f, 0x20000080, 0xe2e0002e, 0xe2e0003e, 0xe2e0003a, + 0xe2e00032, 0x1b80001f, 0x00000020, 0xf0000000, 0x17c07c1f, 0xe2e00036, + 0xe2e0003e, 0x1b80001f, 0x00000020, 0xe2e0003c, 0xe2a00000, 0x1b80001f, + 0x20000080, 0xe2e0007c, 0x1b80001f, 0x20000003, 0xe2e0005c, 0xe2e0004c, + 0xe2e0004d, 0xf0000000, 0x17c07c1f, 0xe2e0004f, 0xe2e0006f, 0xe2e0002f, + 0xe2a00001, 0x1b80001f, 0x20000080, 0xe2e0002e, 0xe2e0003e, 0xe2e0003a, + 0xe2e00032, 0xf0000000, 0x17c07c1f, 0xe2e00026, 0xe2e0002e, 0x1b80001f, + 0x00000020, 0x1a00001f, 0x100062b4, 0x1910001f, 0x100062b4, 0x81322804, + 0xe2000004, 0x81202804, 0xe2000004, 0x1b80001f, 0x20000080, 0xe2e0000e, + 0xe2e0000c, 0xe2e0000d, 0xf0000000, 0x17c07c1f, 0xe2e0002d, 0x1a00001f, + 0x100062b4, 0x1910001f, 0x100062b4, 0xa1002804, 0xe2000004, 0xa1122804, + 0xe2000004, 0x1b80001f, 0x20000080, 0xe2e0002f, 0xe2e0002b, 0xe2e00023, + 0x1b80001f, 0x00000020, 0xe2e00022, 0xf0000000, 0x17c07c1f, 0x1910001f, + 0x1000660c, 0x1a10001f, 0x10006610, 0xa2002004, 0x89000008, 0x00030000, + 0xd80036c4, 0x17c07c1f, 0x8207a001, 0xd82036c8, 0x17c07c1f, 0x1900001f, + 0x1020020c, 0x1a10001f, 0x1020020c, 0xaa000008, 0x00000001, 0xe1000008, + 0x1910001f, 0x1020020c, 0x81001001, 0xd8203184, 0x17c07c1f, 0x1910001f, + 0x10006720, 0x820c9001, 0xd8203228, 0x17c07c1f, 0x1900001f, 0x10001220, + 0x1a10001f, 0x10001220, 0xa21f0408, 0xe1000008, 0x1b80001f, 0x20000080, + 0xe2e0006d, 0xe2e0002d, 0x1a00001f, 0x100062b8, 0x1910001f, 0x100062b8, + 0xa9000004, 0x00000001, 0xe2000004, 0x1b80001f, 0x20000080, 0xe2e0002c, + 0xe2e0003c, 0xe2e0003e, 0xe2e0003a, 0xe2e00032, 0x1b80001f, 0x00000020, + 0x1900001f, 0x10006404, 0x1a10001f, 0x10006404, 0xa2168408, 0xe1000008, + 0xf0000000, 0x17c07c1f, 0x1a10001f, 0x10006610, 0x8207a001, 0xd8003e68, + 0x17c07c1f, 0x1a10001f, 0x10006918, 0x8a000008, 0x00003030, 0xb900010c, + 0x01000001, 0xd8203e64, 0x17c07c1f, 0x1900001f, 0x10006404, 0x1a10001f, + 0x10006404, 0x8a000008, 0x0000dfff, 0xe1000008, 0xe2e00036, 0xe2e0003e, + 0x1b80001f, 0x00000020, 0xe2e0002e, 0x1a00001f, 0x100062b8, 0x1910001f, + 0x100062b8, 0x89000004, 0x0000fffe, 0xe2000004, 0x1b80001f, 0x20000080, + 0xe2e0006e, 0xe2e0004e, 0xe2e0004c, 0xe2e0004d, 0x1900001f, 0x10001220, + 0x1a10001f, 0x10001220, 0x8a000008, 0xbfffffff, 0xe1000008, 0x1b80001f, + 0x20000080, 0x1900001f, 0x1020020c, 0x1a10001f, 0x1020020c, 0x8a000008, + 0xfffffffe, 0xe1000008, 0x1910001f, 0x1020020c, 0x81001001, 0xd8003dc4, + 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x1840001f, 0x00000001, 0x11407c1f, 0xe8208000, + 0x10006310, 0x0b160008, 0x1900001f, 0x000f7bde, 0x1a00001f, 0x10200268, + 0xe2000004, 0xe8208000, 0x10006600, 0x00000000, 0x69200006, 0xbeefbeef, + 0xd8204584, 0x17c07c1f, 0x1910001f, 0x10006358, 0x810b1001, 0xd8004244, + 0x17c07c1f, 0x1980001f, 0xdeaddead, 0x69200006, 0xabcdabcd, 0xd8204324, + 0x17c07c1f, 0x88900001, 0x10006814, 0x1910001f, 0x10006400, 0x81271002, + 0x1880001f, 0x10006600, 0xe0800004, 0x1910001f, 0x10006358, 0x810b1001, + 0xd80044a4, 0x17c07c1f, 0x1980001f, 0x12345678, 0x60a07c05, 0x89100002, + 0x10006600, 0x80801001, 0xd8007bc2, 0x17c07c1f, 0x1890001f, 0x10006b00, + 0x82090801, 0xc8800008, 0x17c07c1f, 0x1b00001f, 0x3fffe7ff, 0x8a00000c, + 0x3fffe7ff, 0xd82041c8, 0x17c07c1f, 0x1b80001f, 0xd0010000, 0x1a10001f, + 0x10006720, 0x82002001, 0x82201408, 0xd8204988, 0x17c07c1f, 0x1a40001f, + 0x10006200, 0x1a80001f, 0x1000625c, 0xc24028e0, 0x17c07c1f, 0xa1400405, + 0x1a10001f, 0x10006720, 0x8200a001, 0x82209408, 0xd8204b28, 0x17c07c1f, + 0x1a40001f, 0x10006218, 0x1a80001f, 0x10006264, 0xc24028e0, 0x17c07c1f, + 0xa1508405, 0x1a10001f, 0x10006720, 0x82012001, 0x82211408, 0xd8204cc8, + 0x17c07c1f, 0x1a40001f, 0x1000621c, 0x1a80001f, 0x1000626c, 0xc24028e0, + 0x17c07c1f, 0xa1510405, 0x1a10001f, 0x10006720, 0x8201a001, 0x82219408, + 0xd8204e68, 0x17c07c1f, 0x1a40001f, 0x10006220, 0x1a80001f, 0x10006274, + 0xc24028e0, 0x17c07c1f, 0xa1518405, 0x1a10001f, 0x10006720, 0x82022001, + 0x82221408, 0xd8204fe8, 0x17c07c1f, 0x1a40001f, 0x100062a0, 0x1280041f, + 0xc2402cc0, 0x17c07c1f, 0xa1520405, 0x1a10001f, 0x10006720, 0x8202a001, + 0x82229408, 0xd8205168, 0x17c07c1f, 0x1a40001f, 0x100062a4, 0x1290841f, + 0xc2402cc0, 0x17c07c1f, 0xa1528405, 0x1a10001f, 0x10006720, 0x82032001, + 0x82231408, 0xd8205248, 0x17c07c1f, 0xa1530405, 0x1a10001f, 0x10006720, + 0x8203a001, 0x82239408, 0xd8205328, 0x17c07c1f, 0xa1538405, 0x1a10001f, + 0x10006b00, 0x8108a001, 0xd8205e84, 0x17c07c1f, 0x1910001f, 0x1000660c, + 0x1a10001f, 0x10006610, 0xa2002004, 0x89000008, 0x00001e00, 0xd8005944, + 0x17c07c1f, 0x82042001, 0xd8205948, 0x17c07c1f, 0x1900001f, 0x1020002c, + 0x1a10001f, 0x1020002c, 0xaa000008, 0x00000010, 0xe1000008, 0x1910001f, + 0x10006720, 0x820c1001, 0xd8205628, 0x17c07c1f, 0x1900001f, 0x10001250, + 0x1a10001f, 0x10001250, 0xa2110408, 0xe1000008, 0x1b80001f, 0x20000080, + 0x1900001f, 0x10001220, 0x1a10001f, 0x10001220, 0xa21e8408, 0xe1000008, + 0x1b80001f, 0x20000080, 0x1a40001f, 0x10006208, 0xc24024e0, 0x17c07c1f, + 0x1a10001f, 0x10006610, 0x82042001, 0xd8005e88, 0x17c07c1f, 0x1a10001f, + 0x10006918, 0x8a000008, 0x00000f0f, 0xba00010c, 0x1fffe7ff, 0xd8205e88, + 0x17c07c1f, 0x1a40001f, 0x10006208, 0xc24022a0, 0x17c07c1f, 0x1900001f, + 0x10001250, 0x1a10001f, 0x10001250, 0x8a000008, 0xfffffffb, 0xe1000008, + 0x1b80001f, 0x20000080, 0x1900001f, 0x10001220, 0x1a10001f, 0x10001220, + 0x8a000008, 0xdfffffff, 0xe1000008, 0x1b80001f, 0x20000080, 0x1900001f, + 0x1020002c, 0x1a10001f, 0x1020002c, 0x8a000008, 0xffffffef, 0xe1000008, + 0x1a10001f, 0x10006b00, 0x81082001, 0xd8205fa4, 0x17c07c1f, 0x1a40001f, + 0x100062b0, 0xc2402f20, 0x17c07c1f, 0x1b80001f, 0x20000208, 0xd8207b8c, + 0x17c07c1f, 0x1a40001f, 0x100062b0, 0xc2403700, 0x17c07c1f, 0x81001401, + 0xd8206424, 0x17c07c1f, 0x1a10001f, 0x10006918, 0x81002001, 0xb1042081, + 0xb900008c, 0x1fffe7ff, 0xd8206424, 0x17c07c1f, 0x1a40001f, 0x10006200, + 0x1a80001f, 0x1000625c, 0xc24026e0, 0x17c07c1f, 0x89400005, 0xfffffffe, + 0xe8208000, 0x10006f00, 0x00000000, 0xe8208000, 0x10006b30, 0x00000000, + 0xe8208000, 0x100063e0, 0x00000001, 0x81009401, 0xd82067a4, 0x17c07c1f, + 0x1a10001f, 0x10006918, 0x8100a001, 0xb104a081, 0xb900008c, 0x01000001, + 0xd82067a4, 0x17c07c1f, 0x1a40001f, 0x10006218, 0x1a80001f, 0x10006264, + 0xc24026e0, 0x17c07c1f, 0x89400005, 0xfffffffd, 0xe8208000, 0x10006f04, + 0x00000000, 0xe8208000, 0x10006b34, 0x00000000, 0xe8208000, 0x100063e0, + 0x00000002, 0x81011401, 0xd8206b24, 0x17c07c1f, 0x1a10001f, 0x10006918, + 0x81012001, 0xb1052081, 0xb900008c, 0x01000001, 0xd8206b24, 0x17c07c1f, + 0x1a40001f, 0x1000621c, 0x1a80001f, 0x1000626c, 0xc24026e0, 0x17c07c1f, + 0x89400005, 0xfffffffb, 0xe8208000, 0x10006f08, 0x00000000, 0xe8208000, + 0x10006b38, 0x00000000, 0xe8208000, 0x100063e0, 0x00000004, 0x81019401, + 0xd8206ea4, 0x17c07c1f, 0x1a10001f, 0x10006918, 0x8101a001, 0xb105a081, + 0xb900008c, 0x01000001, 0xd8206ea4, 0x17c07c1f, 0x1a40001f, 0x10006220, + 0x1a80001f, 0x10006274, 0xc24026e0, 0x17c07c1f, 0x89400005, 0xfffffff7, + 0xe8208000, 0x10006f0c, 0x00000000, 0xe8208000, 0x10006b3c, 0x00000000, + 0xe8208000, 0x100063e0, 0x00000008, 0x1a10001f, 0x10006610, 0x8207a001, + 0xd8207608, 0x17c07c1f, 0x81021401, 0xd82072a4, 0x17c07c1f, 0x1a10001f, + 0x10006918, 0x81022001, 0xb1062081, 0xb900008c, 0x01000001, 0xd82072a4, + 0x17c07c1f, 0x1a40001f, 0x100062a0, 0x1280041f, 0xc2402a60, 0x17c07c1f, + 0x89400005, 0xffffffef, 0xe8208000, 0x10006f10, 0x00000000, 0xe8208000, + 0x10006b40, 0x00000000, 0xe8208000, 0x100063e0, 0x00000010, 0x81029401, + 0xd8207604, 0x17c07c1f, 0x1a10001f, 0x10006918, 0x8102a001, 0xb106a081, + 0xb900008c, 0x01000001, 0xd8207604, 0x17c07c1f, 0x1a40001f, 0x100062a4, + 0x1290841f, 0xc2402a60, 0x17c07c1f, 0x89400005, 0xffffffdf, 0xe8208000, + 0x10006f14, 0x00000000, 0xe8208000, 0x10006b44, 0x00000000, 0xe8208000, + 0x100063e0, 0x00000020, 0x81031401, 0xd82078c4, 0x17c07c1f, 0x1a10001f, + 0x10006918, 0x81032001, 0xb1072081, 0xb900008c, 0x01000001, 0xd82078c4, + 0x17c07c1f, 0x89400005, 0xffffffbf, 0xe8208000, 0x10006f18, 0x00000000, + 0xe8208000, 0x10006b48, 0x00000000, 0xe8208000, 0x100063e0, 0x00000040, + 0x81039401, 0xd8207b84, 0x17c07c1f, 0x1a10001f, 0x10006918, 0x8103a001, + 0xb107a081, 0xb900008c, 0x01000001, 0xd8207b84, 0x17c07c1f, 0x89400005, + 0xffffff7f, 0xe8208000, 0x10006f1c, 0x00000000, 0xe8208000, 0x10006b4c, + 0x00000000, 0xe8208000, 0x100063e0, 0x00000080, 0xd00041c0, 0x17c07c1f, + 0xe8208000, 0x10006600, 0x00000000, 0x1ac0001f, 0x55aa55aa, 0x1940001f, + 0xaa55aa55, 0x1b80001f, 0x00001000, 0xf0000000, 0x17c07c1f +}; + +static const struct pcm_desc mcdi_pcm = { + .version = "pcm_mcdi_mt8173_20160401_v1", + .base = mcdi_binary, + .size = 1001, + .sess = 2, + .replace = 0, +}; + +static struct pwr_ctrl mcdi_ctrl = { + .wake_src = WAKE_SRC_FOR_MCDI, + .wake_src_md32 = 0, + .wfi_op = WFI_OP_OR, + .mcusys_idle_mask = 1, + .ca7top_idle_mask = 1, + .ca15top_idle_mask = 1, + .disp_req_mask = 1, + .mfg_req_mask = 1, + .md32_req_mask = 1, +}; + +static const struct spm_lp_scen spm_mcdi = { + .pcmdesc = &mcdi_pcm, + .pwrctrl = &mcdi_ctrl, +}; + +void spm_mcdi_cpu_wake_up_event(int wake_up_event, int disable_dormant_power) +{ + if (((mmio_read_32(SPM_SLEEP_CPU_WAKEUP_EVENT) & 0x1) == 1) + && ((mmio_read_32(SPM_CLK_CON) & CC_DISABLE_DORM_PWR) == 0)) { + /* MCDI is offload? */ + INFO("%s: SPM_SLEEP_CPU_WAKEUP_EVENT:%x, SPM_CLK_CON %x", + __func__, mmio_read_32(SPM_SLEEP_CPU_WAKEUP_EVENT), + mmio_read_32(SPM_CLK_CON)); + return; + } + /* Inform SPM that CPU wants to program CPU_WAKEUP_EVENT and + * DISABLE_CPU_DROM */ + mmio_write_32(SPM_PCM_REG_DATA_INI, PCM_MCDI_HANDSHAKE_SYNC); + mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R6); + mmio_write_32(SPM_PCM_PWR_IO_EN, 0); + + /* Wait SPM's response, can't use sleep api */ + while (mmio_read_32(SPM_PCM_REG6_DATA) != PCM_MCDI_HANDSHAKE_ACK) + ; + + if (disable_dormant_power) { + mmio_setbits_32(SPM_CLK_CON, CC_DISABLE_DORM_PWR); + while (mmio_read_32(SPM_CLK_CON) != + (mmio_read_32(SPM_CLK_CON) | CC_DISABLE_DORM_PWR)) + ; + + } else { + mmio_clrbits_32(SPM_CLK_CON, CC_DISABLE_DORM_PWR); + while (mmio_read_32(SPM_CLK_CON) != + (mmio_read_32(SPM_CLK_CON) & ~CC_DISABLE_DORM_PWR)) + ; + } + + mmio_write_32(SPM_SLEEP_CPU_WAKEUP_EVENT, wake_up_event); + + while (mmio_read_32(SPM_SLEEP_CPU_WAKEUP_EVENT) != wake_up_event) + ; + + /* Inform SPM to see updated setting */ + mmio_write_32(SPM_PCM_REG_DATA_INI, PCM_MCDI_UPDATE_INFORM); + mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R6); + mmio_write_32(SPM_PCM_PWR_IO_EN, 0); + + while (mmio_read_32(SPM_PCM_REG6_DATA) != PCM_MCDI_CKECK_DONE) + ; + /* END OF sequence */ + + mmio_write_32(SPM_PCM_REG_DATA_INI, 0x0); + mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R6); + mmio_write_32(SPM_PCM_PWR_IO_EN, 0); +} + +void spm_mcdi_wakeup_all_cores(void) +{ + if (is_mcdi_ready() == 0) + return; + + spm_mcdi_cpu_wake_up_event(1, 1); + while (mmio_read_32(SPM_PCM_REG5_DATA) != PCM_MCDI_ALL_CORE_AWAKE) + ; + spm_mcdi_cpu_wake_up_event(1, 0); + while (mmio_read_32(SPM_PCM_REG5_DATA) != PCM_MCDI_OFFLOADED) + ; + + spm_clean_after_wakeup(); + clear_all_ready(); +} + +static void spm_mcdi_wfi_sel_enter(unsigned long mpidr) +{ + int core_id_val = mpidr & MPIDR_CPU_MASK; + int cluster_id = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + /* SPM WFI Select by core number */ + if (cluster_id) { + switch (core_id_val) { + case 0: + mmio_write_32(SPM_CA15_CPU0_IRQ_MASK, 1); + mmio_write_32(SPM_SLEEP_CA15_WFI0_EN, 1); + break; + case 1: + mmio_write_32(SPM_CA15_CPU1_IRQ_MASK, 1); + mmio_write_32(SPM_SLEEP_CA15_WFI1_EN, 1); + break; + case 2: + mmio_write_32(SPM_CA15_CPU2_IRQ_MASK, 1); + mmio_write_32(SPM_SLEEP_CA15_WFI2_EN, 1); + break; + case 3: + mmio_write_32(SPM_CA15_CPU3_IRQ_MASK, 1); + mmio_write_32(SPM_SLEEP_CA15_WFI3_EN, 1); + break; + default: + break; + } + } else { + switch (core_id_val) { + case 0: + mmio_write_32(SPM_CA7_CPU0_IRQ_MASK, 1); + mmio_write_32(SPM_SLEEP_CA7_WFI0_EN, 1); + break; + case 1: + mmio_write_32(SPM_CA7_CPU1_IRQ_MASK, 1); + mmio_write_32(SPM_SLEEP_CA7_WFI1_EN, 1); + break; + case 2: + mmio_write_32(SPM_CA7_CPU2_IRQ_MASK, 1); + mmio_write_32(SPM_SLEEP_CA7_WFI2_EN, 1); + break; + case 3: + mmio_write_32(SPM_CA7_CPU3_IRQ_MASK, 1); + mmio_write_32(SPM_SLEEP_CA7_WFI3_EN, 1); + break; + default: + break; + } + } +} + +static void spm_mcdi_wfi_sel_leave(unsigned long mpidr) +{ + int core_id_val = mpidr & MPIDR_CPU_MASK; + int cluster_id = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + /* SPM WFI Select by core number */ + if (cluster_id) { + switch (core_id_val) { + case 0: + mmio_write_32(SPM_SLEEP_CA15_WFI0_EN, 0); + mmio_write_32(SPM_CA15_CPU0_IRQ_MASK, 0); + break; + case 1: + mmio_write_32(SPM_SLEEP_CA15_WFI1_EN, 0); + mmio_write_32(SPM_CA15_CPU1_IRQ_MASK, 0); + break; + case 2: + mmio_write_32(SPM_SLEEP_CA15_WFI2_EN, 0); + mmio_write_32(SPM_CA15_CPU2_IRQ_MASK, 0); + break; + case 3: + mmio_write_32(SPM_SLEEP_CA15_WFI3_EN, 0); + mmio_write_32(SPM_CA15_CPU3_IRQ_MASK, 0); + break; + default: + break; + } + } else { + switch (core_id_val) { + case 0: + mmio_write_32(SPM_SLEEP_CA7_WFI0_EN, 0); + mmio_write_32(SPM_CA7_CPU0_IRQ_MASK, 0); + break; + case 1: + mmio_write_32(SPM_SLEEP_CA7_WFI1_EN, 0); + mmio_write_32(SPM_CA7_CPU1_IRQ_MASK, 0); + break; + case 2: + mmio_write_32(SPM_SLEEP_CA7_WFI2_EN, 0); + mmio_write_32(SPM_CA7_CPU2_IRQ_MASK, 0); + break; + case 3: + mmio_write_32(SPM_SLEEP_CA7_WFI3_EN, 0); + mmio_write_32(SPM_CA7_CPU3_IRQ_MASK, 0); + break; + default: + break; + } + } +} + +static void spm_mcdi_set_cputop_pwrctrl_for_cluster_off(unsigned long mpidr) +{ + unsigned long cluster_id = mpidr & MPIDR_CLUSTER_MASK; + unsigned long cpu_id = mpidr & MPIDR_CPU_MASK; + unsigned int pwr_status, shift, i, flag = 0; + + pwr_status = mmio_read_32(SPM_PWR_STATUS) | + mmio_read_32(SPM_PWR_STATUS_2ND); + + if (cluster_id) { + for (i = 0; i < PLATFORM_CLUSTER1_CORE_COUNT; i++) { + if (i == cpu_id) + continue; + shift = i + PCM_MCDI_CA72_PWRSTA_SHIFT; + flag |= (pwr_status & (1 << shift)) >> shift; + } + if (!flag) + mmio_setbits_32(SPM_PCM_RESERVE, + PCM_MCDI_CA72_CPUTOP_PWRCTL); + } else { + for (i = 0; i < PLATFORM_CLUSTER0_CORE_COUNT; i++) { + if (i == cpu_id) + continue; + shift = i + PCM_MCDI_CA53_PWRSTA_SHIFT; + flag |= (pwr_status & (1 << shift)) >> shift; + } + if (!flag) + mmio_setbits_32(SPM_PCM_RESERVE, + PCM_MCDI_CA53_CPUTOP_PWRCTL); + } +} + +static void spm_mcdi_clear_cputop_pwrctrl_for_cluster_on(unsigned long mpidr) +{ + unsigned long cluster_id = mpidr & MPIDR_CLUSTER_MASK; + + if (cluster_id) + mmio_clrbits_32(SPM_PCM_RESERVE, + PCM_MCDI_CA72_CPUTOP_PWRCTL); + else + mmio_clrbits_32(SPM_PCM_RESERVE, + PCM_MCDI_CA53_CPUTOP_PWRCTL); +} + +void spm_mcdi_prepare_for_mtcmos(void) +{ + const struct pcm_desc *pcmdesc = spm_mcdi.pcmdesc; + struct pwr_ctrl *pwrctrl = spm_mcdi.pwrctrl; + + if (is_mcdi_ready() == 0) { + if (is_hotplug_ready() == 1) + spm_clear_hotplug(); + set_pwrctrl_pcm_flags(pwrctrl, 0); + spm_reset_and_init_pcm(); + spm_kick_im_to_fetch(pcmdesc); + spm_set_power_control(pwrctrl); + spm_set_wakeup_event(pwrctrl); + spm_kick_pcm_to_run(pwrctrl); + set_mcdi_ready(); + } +} + +void spm_mcdi_prepare_for_off_state(unsigned long mpidr, unsigned int afflvl) +{ + const struct pcm_desc *pcmdesc = spm_mcdi.pcmdesc; + struct pwr_ctrl *pwrctrl = spm_mcdi.pwrctrl; + + spm_lock_get(); + if (is_mcdi_ready() == 0) { + if (is_hotplug_ready() == 1) + spm_clear_hotplug(); + set_pwrctrl_pcm_flags(pwrctrl, 0); + spm_reset_and_init_pcm(); + spm_kick_im_to_fetch(pcmdesc); + spm_set_power_control(pwrctrl); + spm_set_wakeup_event(pwrctrl); + spm_kick_pcm_to_run(pwrctrl); + set_mcdi_ready(); + } + spm_mcdi_wfi_sel_enter(mpidr); + if (afflvl == MPIDR_AFFLVL1) + spm_mcdi_set_cputop_pwrctrl_for_cluster_off(mpidr); + spm_lock_release(); +} + +void spm_mcdi_finish_for_on_state(unsigned long mpidr, unsigned int afflvl) +{ + unsigned long linear_id; + + linear_id = ((mpidr & MPIDR_CLUSTER_MASK) >> 6) | + (mpidr & MPIDR_CPU_MASK); + + spm_lock_get(); + spm_mcdi_clear_cputop_pwrctrl_for_cluster_on(mpidr); + spm_mcdi_wfi_sel_leave(mpidr); + mmio_write_32(SPM_PCM_SW_INT_CLEAR, (0x1 << linear_id)); + spm_lock_release(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h new file mode 100644 index 0000000..7f3f96e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SPM_MCDI_H +#define SPM_MCDI_H + +void spm_mcdi_wakeup_all_cores(void); +void spm_mcdi_prepare_for_mtcmos(void); +void spm_mcdi_prepare_for_off_state(unsigned long mpidr, unsigned int afflvl); +void spm_mcdi_finish_for_on_state(unsigned long mpidr, unsigned int afflvl); + +#endif /* SPM_MCDI_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c new file mode 100644 index 0000000..838455d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* + * System Power Manager (SPM) is a hardware module, which controls cpu or + * system power for different power scenarios using different firmware. + * This driver controls the system power in system suspend flow. + */ + +#define WAKE_SRC_FOR_SUSPEND \ + (WAKE_SRC_KP | WAKE_SRC_EINT | WAKE_SRC_MD32 | \ + WAKE_SRC_USB_CD | WAKE_SRC_USB_PDN | WAKE_SRC_THERM | \ + WAKE_SRC_SYSPWREQ | WAKE_SRC_ALL_MD32) + +#define WAKE_SRC_FOR_MD32 0 + +#define spm_is_wakesrc_invalid(wakesrc) \ + (!!((unsigned int)(wakesrc) & 0xc0003803)) + +#define ARMCA15PLL_CON0 (APMIXED_BASE + 0x200) +#define ARMCA15PLL_CON1 (APMIXED_BASE + 0x204) +#define ARMCA15PLL_PWR_CON0 (APMIXED_BASE + 0x20c) +#define ARMCA15PLL_PWR_ON (1U << 0) +#define ARMCA15PLL_ISO_EN (1U << 1) +#define ARMCA15PLL_EN (1U << 0) + +const unsigned int spm_flags = + SPM_DUALVCORE_PDN_DIS | SPM_PASR_DIS | SPM_DPD_DIS | + SPM_CPU_DVS_DIS | SPM_OPT | SPM_INFRA_PDN_DIS; + +enum wake_reason_t spm_wake_reason = WR_NONE; + +/********************************************************** + * PCM sequence for cpu suspend + **********************************************************/ +static const unsigned int suspend_binary_ca7[] = { + 0x81f58407, 0x81f68407, 0x803a0400, 0x803a8400, 0x1b80001f, 0x20000000, + 0x80300400, 0x80318400, 0x80328400, 0xa1d28407, 0x81f20407, 0x81009801, + 0xd8000244, 0x17c07c1f, 0x18c0001f, 0x10006234, 0xc0c032e0, 0x1200041f, + 0x80310400, 0x1b80001f, 0x2000000a, 0xa0110400, 0x18c0001f, 0x100062c8, + 0xe0e00010, 0xe0e00030, 0xe0e00070, 0xe0e000f0, 0x1b80001f, 0x2000001a, + 0xe0e00ff0, 0xe8208000, 0x10006354, 0xfffe7fff, 0xe8208000, 0x10006834, + 0x00000010, 0x81f00407, 0xa1dd0407, 0x81fd0407, 0xc2803800, 0x1290041f, + 0x8880000c, 0x2f7be75f, 0xd8200722, 0x17c07c1f, 0xd82006a9, 0x17c07c1f, + 0xe8208000, 0x10006814, 0x00000001, 0xc2803800, 0x1293841f, 0x1b00001f, + 0x7fffe7ff, 0xd0000760, 0x17c07c1f, 0x1b00001f, 0x7ffff7ff, 0xf0000000, + 0x17c07c1f, 0x80880001, 0xd8000842, 0x17c07c1f, 0xd00028e0, 0x1200041f, + 0xe8208000, 0x10006834, 0x00000000, 0x1b00001f, 0x3fffe7ff, 0x1b80001f, + 0x20000004, 0xd8200a0c, 0x17c07c1f, 0xe8208000, 0x10006834, 0x00000010, + 0xd0001280, 0x17c07c1f, 0x18c0001f, 0x10006608, 0x1910001f, 0x10006608, + 0x813b0404, 0xe0c00004, 0x1880001f, 0x10006320, 0xc0c03760, 0xe080000f, + 0xd8200c03, 0x17c07c1f, 0x1b00001f, 0x7ffff7ff, 0xd0001280, 0x17c07c1f, + 0xe080001f, 0xe8208000, 0x10006354, 0xffffffff, 0x18c0001f, 0x100062c8, + 0xe0e000f0, 0xe0e00030, 0xe0e00000, 0x81009801, 0xd80010c4, 0x17c07c1f, + 0x18c0001f, 0x10004094, 0x1910001f, 0x1020e374, 0xe0c00004, 0x18c0001f, + 0x10004098, 0x1910001f, 0x1020e378, 0xe0c00004, 0x18c0001f, 0x10011094, + 0x1910001f, 0x10213374, 0xe0c00004, 0x18c0001f, 0x10011098, 0x1910001f, + 0x10213378, 0xe0c00004, 0x1910001f, 0x10213378, 0x18c0001f, 0x10006234, + 0xc0c034a0, 0x17c07c1f, 0xc2803800, 0x1290841f, 0xa1d20407, 0x81f28407, + 0xa1d68407, 0xa0128400, 0xa0118400, 0xa0100400, 0xa01a8400, 0xa01a0400, + 0x19c0001f, 0x001c239f, 0x1b00001f, 0x3fffefff, 0xf0000000, 0x17c07c1f, + 0x808d8001, 0xd8201502, 0x17c07c1f, 0x803d8400, 0x1b80001f, 0x2000001a, + 0x80340400, 0x17c07c1f, 0x17c07c1f, 0x80310400, 0x81fa0407, 0x81f18407, + 0x81f08407, 0xa1dc0407, 0x1b80001f, 0x200000b6, 0xd0002220, 0x17c07c1f, + 0x1880001f, 0x20000208, 0x81011801, 0xd80016e4, 0x17c07c1f, 0xe8208000, + 0x1000f600, 0xd2000000, 0x1380081f, 0x18c0001f, 0x10006240, 0xe0e00016, + 0xe0e0001e, 0xe0e0000e, 0xe0e0000f, 0x80368400, 0x1380081f, 0x80370400, + 0x1380081f, 0x80360400, 0x803e0400, 0x1380081f, 0x80380400, 0x803b0400, + 0xa01d8400, 0x1b80001f, 0x20000034, 0x803d8400, 0x1b80001f, 0x20000152, + 0x803d0400, 0x1380081f, 0x18c0001f, 0x1000f5c8, 0x1910001f, 0x1000f5c8, + 0xa1000404, 0xe0c00004, 0x18c0001f, 0x100125c8, 0x1910001f, 0x100125c8, + 0xa1000404, 0xe0c00004, 0x1910001f, 0x100125c8, 0x80340400, 0x17c07c1f, + 0x17c07c1f, 0x80310400, 0xe8208000, 0x10000044, 0x00000100, 0x1b80001f, + 0x20000068, 0x1b80001f, 0x2000000a, 0x18c0001f, 0x10006240, 0xe0e0000d, + 0x81011801, 0xd8001f64, 0x17c07c1f, 0x18c0001f, 0x100040f4, 0x1910001f, + 0x100040f4, 0xa11c8404, 0xe0c00004, 0x1b80001f, 0x2000000a, 0x813c8404, + 0xe0c00004, 0x18c0001f, 0x100110f4, 0x1910001f, 0x100110f4, 0xa11c8404, + 0xe0c00004, 0x1b80001f, 0x2000000a, 0x813c8404, 0xe0c00004, 0x1b80001f, + 0x20000100, 0x81fa0407, 0x81f18407, 0x81f08407, 0xe8208000, 0x10006354, + 0xfffe7b47, 0x18c0001f, 0x65930003, 0xc0c031c0, 0x17c07c1f, 0xc2803800, + 0x1293041f, 0xa1d80407, 0xa1dc0407, 0x18c0001f, 0x10006608, 0x1910001f, + 0x10006608, 0xa11b0404, 0xe0c00004, 0xc2803800, 0x1291041f, 0x8880000c, + 0x2f7be75f, 0xd8202362, 0x17c07c1f, 0x1b00001f, 0x3fffe7ff, 0xd00023a0, + 0x17c07c1f, 0x1b00001f, 0xbfffe7ff, 0xf0000000, 0x17c07c1f, 0x1890001f, + 0x10006608, 0x808b0801, 0xd8202642, 0x17c07c1f, 0x1880001f, 0x10006320, + 0xc0c03540, 0xe080000f, 0xd80027a3, 0x17c07c1f, 0xe080001f, 0xa1da0407, + 0x81fc0407, 0xa0110400, 0xa0140400, 0xa01d8400, 0xd0003100, 0x17c07c1f, + 0x1b80001f, 0x20000fdf, 0x1890001f, 0x10006608, 0x80c98801, 0x810a8801, + 0x10918c1f, 0xa0939002, 0x8080080d, 0xd82028e2, 0x12007c1f, 0x1b00001f, + 0x3fffe7ff, 0x1b80001f, 0x20000004, 0xd800318c, 0x17c07c1f, 0x1b00001f, + 0xbfffe7ff, 0xd0003180, 0x17c07c1f, 0x81f80407, 0x81fc0407, 0x18c0001f, + 0x65930006, 0xc0c031c0, 0x17c07c1f, 0x18c0001f, 0x65930007, 0xc0c031c0, + 0x17c07c1f, 0x1880001f, 0x10006320, 0xc0c03540, 0xe080000f, 0xd80027a3, + 0x17c07c1f, 0xe080001f, 0x18c0001f, 0x65930005, 0xc0c031c0, 0x17c07c1f, + 0xa1da0407, 0xe8208000, 0x10000048, 0x00000100, 0x1b80001f, 0x20000068, + 0xa0110400, 0xa0140400, 0x18c0001f, 0x1000f5c8, 0x1910001f, 0x1000f5c8, + 0x81200404, 0xe0c00004, 0x18c0001f, 0x100125c8, 0x1910001f, 0x100125c8, + 0x81200404, 0xe0c00004, 0x1910001f, 0x100125c8, 0xa01d0400, 0xa01b0400, + 0xa0180400, 0x803d8400, 0xa01e0400, 0xa0160400, 0xa0170400, 0xa0168400, + 0x1b80001f, 0x20000104, 0x81011801, 0xd80030c4, 0x17c07c1f, 0x18c0001f, + 0x10006240, 0xc0c034a0, 0x17c07c1f, 0xe8208000, 0x1000f600, 0xd2000001, + 0xd8000848, 0x17c07c1f, 0xc2803800, 0x1291841f, 0x1b00001f, 0x7ffff7ff, + 0xf0000000, 0x17c07c1f, 0x1900001f, 0x10006830, 0xe1000003, 0x18c0001f, + 0x10006834, 0xe0e00000, 0xe0e00001, 0xf0000000, 0x17c07c1f, 0xe0f07f16, + 0x1380201f, 0xe0f07f1e, 0x1380201f, 0xe0f07f0e, 0x1b80001f, 0x20000104, + 0xe0f07f0c, 0xe0f07f0d, 0xe0f07e0d, 0xe0f07c0d, 0xe0f0780d, 0xf0000000, + 0xe0f0700d, 0xe0f07f0d, 0xe0f07f0f, 0xe0f07f1e, 0xf0000000, 0xe0f07f12, + 0x11407c1f, 0x81f08407, 0x81f18407, 0x1b80001f, 0x20000001, 0xa1d08407, + 0xa1d18407, 0x1392841f, 0x812ab401, 0x80ebb401, 0xa0c00c04, 0xd8203743, + 0x17c07c1f, 0x80c01403, 0xd8203563, 0x01400405, 0xf0000000, 0xa1d00407, + 0x1b80001f, 0x20000208, 0x80ea3401, 0xf0000000, 0x18c0001f, 0x10006b6c, + 0x1910001f, 0x10006b6c, 0xa1002804, 0xf0000000, 0xe0c00004, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, + 0x17c07c1f, 0x17c07c1f, 0x1840001f, 0x00000001, 0xa1d48407, 0x1990001f, + 0x10006b08, 0x1a50001f, 0x10006610, 0x8246a401, 0xe8208000, 0x10006b6c, + 0x00000000, 0x1b00001f, 0x2f7be75f, 0x81469801, 0xd8004305, 0x17c07c1f, + 0x1b80001f, 0xd00f0000, 0x8880000c, 0x2f7be75f, 0xd8005fa2, 0x17c07c1f, + 0xd0004340, 0x17c07c1f, 0x1b80001f, 0x500f0000, 0xe8208000, 0x10006354, + 0xfffe7b47, 0xc0c06c00, 0x81401801, 0xd80048e5, 0x17c07c1f, 0x81f60407, + 0x18c0001f, 0x10006200, 0xc0c06060, 0x12807c1f, 0xe8208000, 0x1000625c, + 0x00000001, 0x1b80001f, 0x20000080, 0xc0c06060, 0x1280041f, 0x18c0001f, + 0x10006204, 0xc0c06400, 0x1280041f, 0x18c0001f, 0x10006208, 0xc0c06060, + 0x12807c1f, 0xe8208000, 0x10006244, 0x00000001, 0x1b80001f, 0x20000080, + 0xc0c06060, 0x1280041f, 0x18d0001f, 0x10200200, 0x18c0001f, 0x10006290, + 0xc0c06060, 0x1280041f, 0xe8208000, 0x10006404, 0x00003101, 0xc2803800, + 0x1292041f, 0x81469801, 0xd8204a45, 0x17c07c1f, 0x1b00001f, 0x2f7be75f, + 0x1b80001f, 0x30000004, 0x8880000c, 0x2f7be75f, 0xd8005a02, 0x17c07c1f, + 0xc0c06780, 0x17c07c1f, 0x18c0001f, 0x10006294, 0xe0f07fff, 0xe0e00fff, + 0xe0e000ff, 0x81449801, 0xd8004c85, 0x17c07c1f, 0x1a00001f, 0x10006604, + 0xe2200003, 0xc0c06840, 0x17c07c1f, 0xe2200005, 0xc0c06840, 0x17c07c1f, + 0xa1d38407, 0xa1d98407, 0x1800001f, 0x00000012, 0x1800001f, 0x00000e12, + 0x1800001f, 0x03800e12, 0x1800001f, 0x038e0e12, 0xe8208000, 0x10006310, + 0x0b1600f8, 0x1940001f, 0x00000000, 0x12407c1f, 0x1b00001f, 0xbfffe7ff, + 0x1b80001f, 0x90100000, 0x17c07c1f, 0xd8004fc5, 0x17c07c1f, 0x8247b001, + 0x1940001f, 0xffffffff, 0x80c00400, 0xd82050c3, 0xa1d58407, 0xa1dd8407, + 0x1b00001f, 0x3fffefff, 0xd0004ec0, 0x17c07c1f, 0x1890001f, 0x100063e8, + 0x88c0000c, 0x2f7be75f, 0xd80052e3, 0x17c07c1f, 0x80c40001, 0xd8005263, + 0x17c07c1f, 0x1b00001f, 0xbfffe7ff, 0xd00052a0, 0x17c07c1f, 0x1b00001f, + 0x7ffff7ff, 0xd0004ec0, 0x17c07c1f, 0x80c40001, 0xd82053e3, 0x17c07c1f, + 0xa1de0407, 0x1b00001f, 0x7fffe7ff, 0xd0004ec0, 0x17c07c1f, 0xe8208000, + 0x10006814, 0x00000000, 0x18c0001f, 0x10006b00, 0xe0e00000, 0xe0c00009, + 0x18c0001f, 0x10006294, 0xe0e001fe, 0xe0e003fc, 0xe0e007f8, 0xe0e00ff0, + 0x1b80001f, 0x20000020, 0xe0f07ff0, 0xe0f07f00, 0x81449801, 0xd80057a5, + 0x17c07c1f, 0x1a00001f, 0x10006604, 0xe2200002, 0xc0c06840, 0x17c07c1f, + 0xe2200004, 0xc0c06840, 0x17c07c1f, 0x1b80001f, 0x200016a8, 0x1800001f, + 0x03800e12, 0x1b80001f, 0x20000300, 0x1800001f, 0x00000e12, 0x1b80001f, + 0x20000300, 0x1800001f, 0x00000012, 0x1b80001f, 0x20000104, 0x10007c1f, + 0x81f38407, 0x81f98407, 0x81f90407, 0x81f40407, 0x1b80001f, 0x200016a8, + 0x81401801, 0xd8005fa5, 0x17c07c1f, 0xe8208000, 0x10006404, 0x00002101, + 0x18c0001f, 0x10006290, 0x1212841f, 0xc0c061e0, 0x12807c1f, 0xc0c061e0, + 0x1280041f, 0x18c0001f, 0x10006208, 0x1212841f, 0xc0c061e0, 0x12807c1f, + 0xe8208000, 0x10006244, 0x00000000, 0x1b80001f, 0x20000080, 0xc0c061e0, + 0x1280041f, 0xe8208000, 0x10200268, 0x000ffffe, 0x18c0001f, 0x10006204, + 0x1212841f, 0xc0c065a0, 0x1280041f, 0x18c0001f, 0x10006200, 0x1212841f, + 0xc0c061e0, 0x12807c1f, 0xe8208000, 0x1000625c, 0x00000000, 0x1b80001f, + 0x20000080, 0xc0c061e0, 0x1280041f, 0x19c0001f, 0x01411820, 0x1ac0001f, + 0x55aa55aa, 0x10007c1f, 0xf0000000, 0xd800610a, 0x17c07c1f, 0xe2e0004f, + 0xe2e0006f, 0xe2e0002f, 0xd82061aa, 0x17c07c1f, 0xe2e0002e, 0xe2e0003e, + 0xe2e00032, 0xf0000000, 0x17c07c1f, 0xd80062aa, 0x17c07c1f, 0xe2e00036, + 0xe2e0003e, 0x1380201f, 0xe2e0003c, 0xd82063ca, 0x17c07c1f, 0x1380201f, + 0xe2e0007c, 0x1b80001f, 0x20000003, 0xe2e0005c, 0xe2e0004c, 0xe2e0004d, + 0xf0000000, 0x17c07c1f, 0x1a50001f, 0x10006610, 0x8246a401, 0xd8206569, + 0x17c07c1f, 0xe2e0000d, 0xe2e0000c, 0xe2e0001c, 0xe2e0001e, 0xe2e00016, + 0xe2e00012, 0xf0000000, 0x17c07c1f, 0x1a50001f, 0x10006610, 0x8246a401, + 0xd8206749, 0x17c07c1f, 0xe2e00016, 0x1380201f, 0xe2e0001e, 0x1380201f, + 0xe2e0001c, 0x1380201f, 0xe2e0000c, 0xe2e0000d, 0xf0000000, 0x17c07c1f, + 0xa1d40407, 0x1391841f, 0xa1d90407, 0x1393041f, 0xf0000000, 0x17c07c1f, + 0x18d0001f, 0x10006604, 0x10cf8c1f, 0xd8206843, 0x17c07c1f, 0xf0000000, + 0x17c07c1f, 0xe8208000, 0x11008014, 0x00000002, 0xe8208000, 0x11008020, + 0x00000101, 0xe8208000, 0x11008004, 0x000000d0, 0x1a00001f, 0x11008000, + 0xd8006b0a, 0xe220005d, 0xd8206b2a, 0xe2200000, 0xe2200001, 0xe8208000, + 0x11008024, 0x00000001, 0x1b80001f, 0x20000424, 0xf0000000, 0x17c07c1f, + 0xa1d10407, 0x1b80001f, 0x20000020, 0xf0000000, 0x17c07c1f +}; + +/* + * PCM binary for suspend scenario + */ +static const struct pcm_desc suspend_pcm_ca7 = { + .version = "pcm_suspend_20150917_V4", + .base = suspend_binary_ca7, + .size = 869, + .sess = 2, + .replace = 0, + .vec0 = EVENT_VEC(11, 1, 0, 0), + .vec1 = EVENT_VEC(12, 1, 0, 61), + .vec2 = EVENT_VEC(30, 1, 0, 150), + .vec3 = EVENT_VEC(31, 1, 0, 287), +}; + +/* + * SPM settings for suspend scenario + */ +static struct pwr_ctrl spm_ctrl = { + .wake_src = WAKE_SRC_FOR_SUSPEND, + .wake_src_md32 = WAKE_SRC_FOR_MD32, + .r0_ctrl_en = 1, + .r7_ctrl_en = 1, + .infra_dcm_lock = 1, + .wfi_op = WFI_OP_AND, + .pcm_apsrc_req = 0, + .ca7top_idle_mask = 0, + .ca15top_idle_mask = 0, + .mcusys_idle_mask = 0, + .disp_req_mask = 0, + .mfg_req_mask = 0, + .md32_req_mask = 1, + .srclkenai_mask = 1, + .ca7_wfi0_en = 1, + .ca7_wfi1_en = 1, + .ca7_wfi2_en = 1, + .ca7_wfi3_en = 1, + .ca15_wfi0_en = 1, + .ca15_wfi1_en = 1, + .ca15_wfi2_en = 1, + .ca15_wfi3_en = 1, +}; + +/* + * go_to_sleep_before_wfi() - trigger SPM to enter suspend scenario + */ +static void go_to_sleep_before_wfi(const unsigned int flags_spm) +{ + struct pwr_ctrl *pwrctrl; + + pwrctrl = &spm_ctrl; + + set_pwrctrl_pcm_flags(pwrctrl, flags_spm); + + spm_set_sysclk_settle(); + + INFO("sec = %u, wakesrc = 0x%x (%u)(%u)\n", + pwrctrl->timer_val, pwrctrl->wake_src, + is_cpu_pdn(pwrctrl->pcm_flags), + is_infra_pdn(pwrctrl->pcm_flags)); + + spm_reset_and_init_pcm(); + spm_init_pcm_register(); + spm_set_power_control(pwrctrl); + spm_set_wakeup_event(pwrctrl); + spm_kick_pcm_to_run(pwrctrl); + spm_init_event_vector(&suspend_pcm_ca7); + spm_kick_im_to_fetch(&suspend_pcm_ca7); +} + +/* + * go_to_sleep_after_wfi() - get wakeup reason after + * leaving suspend scenario and clean up SPM settings + */ +static enum wake_reason_t go_to_sleep_after_wfi(void) +{ + struct wake_status wakesta; + static enum wake_reason_t last_wr = WR_NONE; + + spm_get_wakeup_status(&wakesta); + spm_clean_after_wakeup(); + last_wr = spm_output_wake_reason(&wakesta); + + return last_wr; +} + +static void bigcore_pll_on(void) +{ + mmio_setbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_PWR_ON); + mmio_clrbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_ISO_EN); + mmio_setbits_32(ARMCA15PLL_CON0, ARMCA15PLL_EN); +} + +static void bigcore_pll_off(void) +{ + mmio_clrbits_32(ARMCA15PLL_CON0, ARMCA15PLL_EN); + mmio_setbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_ISO_EN); + mmio_clrbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_PWR_ON); +} + +void spm_system_suspend(void) +{ + bigcore_pll_off(); + spm_lock_get(); + go_to_sleep_before_wfi(spm_flags); + set_suspend_ready(); + spm_lock_release(); +} + +void spm_system_suspend_finish(void) +{ + spm_lock_get(); + spm_wake_reason = go_to_sleep_after_wfi(); + INFO("spm_wake_reason=%d\n", spm_wake_reason); + clear_all_ready(); + spm_lock_release(); + bigcore_pll_on(); + /* Add 20us delay for turning on PLL*/ + udelay(20); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h new file mode 100644 index 0000000..b00faa9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SPM_SUSPEND_H +#define SPM_SUSPEND_H + +/* cpu dormant return code */ +#define CPU_DORMANT_RESET 0 +#define CPU_DORMANT_ABORT 1 + +void spm_system_suspend(void); +void spm_system_suspend_finish(void); + +#endif /* SPM_SUSPEND_H*/ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c new file mode 100644 index 0000000..174a24d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +static void write_cpuxgpt(unsigned int reg_index, unsigned int value) +{ + mmio_write_32((uintptr_t)&mt8173_mcucfg->xgpt_idx, reg_index); + mmio_write_32((uintptr_t)&mt8173_mcucfg->xgpt_ctl, value); +} + +static void cpuxgpt_set_init_cnt(unsigned int countH, unsigned int countL) +{ + write_cpuxgpt(INDEX_CNT_H_INIT, countH); + /* update count when countL programmed */ + write_cpuxgpt(INDEX_CNT_L_INIT, countL); +} + +void generic_timer_backup(void) +{ + uint64_t cval; + + cval = read_cntpct_el0(); + cpuxgpt_set_init_cnt((uint32_t)(cval >> 32), + (uint32_t)(cval & 0xffffffff)); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h new file mode 100644 index 0000000..8c0fe83 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_CPUXGPT_H +#define MT_CPUXGPT_H + +/* REG */ +#define INDEX_CNT_L_INIT 0x008 +#define INDEX_CNT_H_INIT 0x00C + +void generic_timer_backup(void); + +#endif /* MT_CPUXGPT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c new file mode 100644 index 0000000..40f57ee --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2020, Google LLC. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#define WDT_BASE (RGU_BASE + 0) +#define WDT_MODE (WDT_BASE + 0x00) +#define WDT_LENGTH (WDT_BASE + 0x04) +#define WDT_RESTART (WDT_BASE + 0x08) +#define WDT_SWRST (WDT_BASE + 0x14) + +#define WDT_MODE_DUAL_MODE 0x40 +#define WDT_MODE_IRQ 0x8 +#define WDT_MODE_KEY 0x22000000 +#define WDT_MODE_EXTEN 0x4 +#define WDT_MODE_EN 0x1 +#define WDT_LENGTH_KEY 0x8 +#define WDT_RESTART_KEY 0x1971 +#define WDT_SWRST_KEY 0x1209 + + +#define WDT_MIN_TIMEOUT 1 +#define WDT_MAX_TIMEOUT 31 + +enum smcwd_call { + SMCWD_INFO = 0, + SMCWD_SET_TIMEOUT = 1, + SMCWD_ENABLE = 2, + SMCWD_PET = 3, +}; + +static int wdt_enabled_before_suspend; + +/* + * We expect the WDT registers to be correctly initialized by BL2 firmware + * (which may be board specific), so we do not reinitialize them here. + */ + +void wdt_trigger_reset(void) +{ + mmio_write_32(WDT_SWRST, WDT_SWRST_KEY); +} + +void wdt_pet(void) +{ + mmio_write_32(WDT_RESTART, WDT_RESTART_KEY); +} + +int wdt_set_timeout(uint32_t timeout) +{ + /* One tick here equals 512 32KHz ticks. 512 / 32000 * 125 / 2 = 1 */ + uint32_t ticks = timeout * 125 / 2; + + if (timeout < WDT_MIN_TIMEOUT || timeout > WDT_MAX_TIMEOUT) + return PSCI_E_INVALID_PARAMS; + + mmio_write_32(WDT_LENGTH, ticks << 5 | WDT_LENGTH_KEY); + + return PSCI_E_SUCCESS; +} + +void wdt_set_enable(int enable) +{ + if (enable) + wdt_pet(); + mmio_clrsetbits_32(WDT_MODE, WDT_MODE_EN, + WDT_MODE_KEY | (enable ? WDT_MODE_EN : 0)); +} + +void wdt_suspend(void) +{ + wdt_enabled_before_suspend = mmio_read_32(WDT_MODE) & WDT_MODE_EN; + if (wdt_enabled_before_suspend) + wdt_set_enable(0); +} + +void wdt_resume(void) +{ + if (wdt_enabled_before_suspend) + wdt_set_enable(1); +} + +uint64_t wdt_smc_handler(uint32_t x1, + uint32_t x2, + void *handle) +{ + int ret; + + switch (x1) { + case SMCWD_INFO: + SMC_RET3(handle, PSCI_E_SUCCESS, + WDT_MIN_TIMEOUT, WDT_MAX_TIMEOUT); + case SMCWD_SET_TIMEOUT: + ret = wdt_set_timeout(x2); + SMC_RET1(handle, ret); + case SMCWD_ENABLE: + wdt_set_enable(x2 > 0); + SMC_RET1(handle, PSCI_E_SUCCESS); + case SMCWD_PET: + wdt_pet(); + SMC_RET1(handle, PSCI_E_SUCCESS); + default: + ERROR("Unimplemented SMCWD call (%d)\n", x1); + SMC_RET1(handle, PSCI_E_NOT_SUPPORTED); + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h new file mode 100644 index 0000000..7262a57 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020, Google LLC. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WDT_H +#define WDT_H + +#include "stdint.h" + +void wdt_pet(void); +void wdt_resume(void); +void wdt_set_enable(int enable); +int wdt_set_timeout(uint32_t timeout); +uint64_t wdt_smc_handler(uint32_t x1, uint32_t x2, void *handle); +void wdt_suspend(void); +void wdt_trigger_reset(void); + +#endif /* WDT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h new file mode 100644 index 0000000..dedbc08 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef MCUCFG_H +#define MCUCFG_H + +#include + +#include + +struct mt8173_mcucfg_regs { + uint32_t mp0_ca7l_cache_config; + struct { + uint32_t mem_delsel0; + uint32_t mem_delsel1; + } mp0_cpu[4]; + uint32_t mp0_cache_mem_delsel0; + uint32_t mp0_cache_mem_delsel1; + uint32_t mp0_axi_config; + uint32_t mp0_misc_config[2]; + struct { + uint32_t rv_addr_lw; + uint32_t rv_addr_hw; + } mp0_rv_addr[4]; + uint32_t mp0_ca7l_cfg_dis; + uint32_t mp0_ca7l_clken_ctrl; + uint32_t mp0_ca7l_rst_ctrl; + uint32_t mp0_ca7l_misc_config; + uint32_t mp0_ca7l_dbg_pwr_ctrl; + uint32_t mp0_rw_rsvd0; + uint32_t mp0_rw_rsvd1; + uint32_t mp0_ro_rsvd; + uint32_t reserved0_0[100]; + uint32_t mp1_cpucfg; + uint32_t mp1_miscdbg; + uint32_t reserved0_1[13]; + uint32_t mp1_rst_ctl; + uint32_t mp1_clkenm_div; + uint32_t reserved0_2[7]; + uint32_t mp1_config_res; + uint32_t reserved0_3[13]; + struct { + uint32_t rv_addr_lw; + uint32_t rv_addr_hw; + } mp1_rv_addr[2]; + uint32_t reserved0_4[84]; + uint32_t mp0_rst_status; /* 0x400 */ + uint32_t mp0_dbg_ctrl; + uint32_t mp0_dbg_flag; + uint32_t mp0_ca7l_ir_mon; + struct { + uint32_t pc_lw; + uint32_t pc_hw; + uint32_t fp_arch32; + uint32_t sp_arch32; + uint32_t fp_arch64_lw; + uint32_t fp_arch64_hw; + uint32_t sp_arch64_lw; + uint32_t sp_arch64_hw; + } mp0_dbg_core[4]; + uint32_t dfd_ctrl; + uint32_t dfd_cnt_l; + uint32_t dfd_cnt_h; + uint32_t misccfg_mp0_rw_rsvd; + uint32_t misccfg_sec_vio_status0; + uint32_t misccfg_sec_vio_status1; + uint32_t reserved1[22]; + uint32_t misccfg_rw_rsvd; /* 0x500 */ + uint32_t mcusys_dbg_mon_sel_a; + uint32_t mcusys_dbg_mon; + uint32_t reserved2[61]; + uint32_t mcusys_config_a; /* 0x600 */ + uint32_t mcusys_config1_a; + uint32_t mcusys_gic_peribase_a; + uint32_t reserved3; + uint32_t sec_range0_start; /* 0x610 */ + uint32_t sec_range0_end; + uint32_t sec_range_enable; + uint32_t reserved4; + uint32_t int_pol_ctl[8]; /* 0x620 */ + uint32_t aclken_div; /* 0x640 */ + uint32_t pclken_div; + uint32_t l2c_sram_ctrl; + uint32_t armpll_jit_ctrl; + uint32_t cci_addrmap; /* 0x650 */ + uint32_t cci_config; + uint32_t cci_periphbase; + uint32_t cci_nevntcntovfl; + uint32_t cci_clk_ctrl; /* 0x660 */ + uint32_t cci_acel_s1_ctrl; + uint32_t bus_fabric_dcm_ctrl; + uint32_t reserved5; + uint32_t xgpt_ctl; /* 0x670 */ + uint32_t xgpt_idx; + uint32_t ptpod2_ctl0; + uint32_t ptpod2_ctl1; + uint32_t mcusys_revid; + uint32_t mcusys_rw_rsvd0; + uint32_t mcusys_rw_rsvd1; +}; + +static struct mt8173_mcucfg_regs *const mt8173_mcucfg = (void *)MCUCFG_BASE; + +/* cpu boot mode */ +#define MP0_CPUCFG_64BIT_SHIFT 12 +#define MP1_CPUCFG_64BIT_SHIFT 28 +#define MP0_CPUCFG_64BIT (U(0xf) << MP0_CPUCFG_64BIT_SHIFT) +#define MP1_CPUCFG_64BIT (U(0xf) << MP1_CPUCFG_64BIT_SHIFT) + +/* scu related */ +enum { + MP0_ACINACTM_SHIFT = 4, + MP1_ACINACTM_SHIFT = 0, + MP0_ACINACTM = 1 << MP0_ACINACTM_SHIFT, + MP1_ACINACTM = 1 << MP1_ACINACTM_SHIFT +}; + +enum { + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16, + + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT +}; + +enum { + MP1_AINACTS_SHIFT = 4, + MP1_AINACTS = 1 << MP1_AINACTS_SHIFT +}; + +enum { + MP1_SW_CG_GEN_SHIFT = 12, + MP1_SW_CG_GEN = 1 << MP1_SW_CG_GEN_SHIFT +}; + +enum { + MP1_L2RSTDISABLE_SHIFT = 14, + MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT +}; + +/* cci clock control related */ +enum { + MCU_BUS_DCM_EN = 1 << 8 +}; + +/* l2c sram control related */ +enum { + L2C_SRAM_DCM_EN = 1 << 0 +}; + +/* bus fabric dcm control related */ +enum { + PSYS_ADB400_DCM_EN = 1 << 29, + GPU_ADB400_DCM_EN = 1 << 28, + + EMI1_ADB400_DCM_EN = 1 << 27, + EMI_ADB400_DCM_EN = 1 << 26, + INFRA_ADB400_DCM_EN = 1 << 25, + L2C_ADB400_DCM_EN = 1 << 24, + + MP0_ADB400_DCM_EN = 1 << 23, + CCI400_CK_ONLY_DCM_EN = 1 << 22, + L2C_IDLE_DCM_EN = 1 << 21, + + CA15U_ADB_DYNAMIC_CG_EN = 1 << 19, + CA7L_ADB_DYNAMIC_CG_EN = 1 << 18, + L2C_ADB_DYNAMIC_CG_EN = 1 << 17, + + EMICLK_EMI1_DYNAMIC_CG_EN = 1 << 12, + + INFRACLK_PSYS_DYNAMIC_CG_EN = 1 << 11, + EMICLK_GPU_DYNAMIC_CG_EN = 1 << 10, + EMICLK_EMI_DYNAMIC_CG_EN = 1 << 8, + + CCI400_SLV_RW_DCM_EN = 1 << 7, + CCI400_SLV_DCM_EN = 1 << 5, + + ACLK_PSYS_DYNAMIC_CG_EN = 1 << 3, + ACLK_GPU_DYNAMIC_CG_EN = 1 << 2, + ACLK_EMI_DYNAMIC_CG_EN = 1 << 1, + ACLK_INFRA_DYNAMIC_CG_EN = 1 << 0, + + /* adb400 related */ + ADB400_GRP_DCM_EN = PSYS_ADB400_DCM_EN | GPU_ADB400_DCM_EN | + EMI1_ADB400_DCM_EN | EMI_ADB400_DCM_EN | + INFRA_ADB400_DCM_EN | L2C_ADB400_DCM_EN | + MP0_ADB400_DCM_EN, + + /* cci400 related */ + CCI400_GRP_DCM_EN = CCI400_CK_ONLY_DCM_EN | CCI400_SLV_RW_DCM_EN | + CCI400_SLV_DCM_EN, + + /* adb clock related */ + ADBCLK_GRP_DCM_EN = CA15U_ADB_DYNAMIC_CG_EN | CA7L_ADB_DYNAMIC_CG_EN | + L2C_ADB_DYNAMIC_CG_EN, + + /* emi clock related */ + EMICLK_GRP_DCM_EN = EMICLK_EMI1_DYNAMIC_CG_EN | + EMICLK_GPU_DYNAMIC_CG_EN | + EMICLK_EMI_DYNAMIC_CG_EN, + + /* bus clock related */ + ACLK_GRP_DCM_EN = ACLK_PSYS_DYNAMIC_CG_EN | ACLK_GPU_DYNAMIC_CG_EN | + ACLK_EMI_DYNAMIC_CG_EN | ACLK_INFRA_DYNAMIC_CG_EN, +}; + +#endif /* MCUCFG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h new file mode 100644 index 0000000..378b4da --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT8173_DEF_H +#define MT8173_DEF_H + +#if RESET_TO_BL31 +#error "MT8173 is incompatible with RESET_TO_BL31!" +#endif + +#define MT8173_PRIMARY_CPU 0x0 + +/* Register base address */ +#define IO_PHYS (0x10000000) +#define INFRACFG_AO_BASE (IO_PHYS + 0x1000) +#define SRAMROM_SEC_BASE (IO_PHYS + 0x1800) +#define PERI_CON_BASE (IO_PHYS + 0x3000) +#define GPIO_BASE (IO_PHYS + 0x5000) +#define SPM_BASE (IO_PHYS + 0x6000) +#define RGU_BASE (IO_PHYS + 0x7000) +#define PMIC_WRAP_BASE (IO_PHYS + 0xD000) +#define DEVAPC0_BASE (IO_PHYS + 0xE000) +#define MCUCFG_BASE (IO_PHYS + 0x200000) +#define APMIXED_BASE (IO_PHYS + 0x209000) +#define TRNG_BASE (IO_PHYS + 0x20F000) +#define CRYPT_BASE (IO_PHYS + 0x210000) +#define MT_GIC_BASE (IO_PHYS + 0x220000) +#define PLAT_MT_CCI_BASE (IO_PHYS + 0x390000) + +/* Aggregate of all devices in the first GB */ +#define MTK_DEV_RNG0_BASE IO_PHYS +#define MTK_DEV_RNG0_SIZE 0x400000 +#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x1000000) +#define MTK_DEV_RNG1_SIZE 0x4000000 + +/* SRAMROM related registers */ +#define SRAMROM_SEC_CTRL (SRAMROM_SEC_BASE + 0x4) +#define SRAMROM_SEC_ADDR (SRAMROM_SEC_BASE + 0x8) + +/* DEVAPC0 related registers */ +#define DEVAPC0_MAS_SEC_0 (DEVAPC0_BASE + 0x500) +#define DEVAPC0_APC_CON (DEVAPC0_BASE + 0xF00) + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define MT8173_UART0_BASE (IO_PHYS + 0x01002000) +#define MT8173_UART1_BASE (IO_PHYS + 0x01003000) +#define MT8173_UART2_BASE (IO_PHYS + 0x01004000) +#define MT8173_UART3_BASE (IO_PHYS + 0x01005000) + +#define MT8173_BAUDRATE (115200) +#define MT8173_UART_CLOCK (26000000) + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 13000000 + +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base MTK_platform compatible GIC memory map */ +#define BASE_GICD_BASE (MT_GIC_BASE + 0x1000) +#define BASE_GICC_BASE (MT_GIC_BASE + 0x2000) +#define BASE_GICR_BASE 0 /* no GICR in GIC-400 */ +#define BASE_GICH_BASE (MT_GIC_BASE + 0x4000) +#define BASE_GICV_BASE (MT_GIC_BASE + 0x6000) +#define INT_POL_CTL0 0x10200620 + +#define GIC_PRIVATE_SIGNALS (32) + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX 4 +#define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX 3 + +/* FIQ platform related define */ +#define MT_IRQ_SEC_SGI_0 8 +#define MT_IRQ_SEC_SGI_1 9 +#define MT_IRQ_SEC_SGI_2 10 +#define MT_IRQ_SEC_SGI_3 11 +#define MT_IRQ_SEC_SGI_4 12 +#define MT_IRQ_SEC_SGI_5 13 +#define MT_IRQ_SEC_SGI_6 14 +#define MT_IRQ_SEC_SGI_7 15 + +/* + * Macros for local power states in MTK platforms encoded by State-ID field + * within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define MTK_LOCAL_STATE_RUN 0 +/* Local power state for retention. Valid only for CPU power domains */ +#define MTK_LOCAL_STATE_RET 1 +/* Local power state for OFF/power-down. Valid for CPU and cluster power + * domains + */ +#define MTK_LOCAL_STATE_OFF 2 + +#if PSCI_EXTENDED_STATE_ID +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define MTK_LOCAL_PSTATE_WIDTH 4 +#define MTK_LOCAL_PSTATE_MASK ((1 << MTK_LOCAL_PSTATE_WIDTH) - 1) + +/* Macros to construct the composite power state */ + +/* Make composite power state parameter till power level 0 */ + +#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT)) +#else +#define mtk_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 mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << MTK_LOCAL_PSTATE_WIDTH) | \ + mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + +/* Make composite power state parameter till power level 2 */ +#define mtk_make_pwrstate_lvl2( \ + lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl2_state) << (MTK_LOCAL_PSTATE_WIDTH * 2)) | \ + mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type)) + + +#endif /* MT8173_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S new file mode 100644 index 0000000..ac9fb16 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* --------------------------------------------- + * The below macro prints out relevant GIC and + * CCI registers whenever an unhandled exception + * is taken in BL3-1. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x16, BASE_GICD_BASE + mov_imm x17, BASE_GICC_BASE + /* 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 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 + bl asm_print_hex + + 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: + + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MT_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_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MT_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 diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h new file mode 100644 index 0000000..cd92d34 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long, + unsigned long, + unsigned long, + unsigned long); + +void plat_cci_init(void); +void plat_cci_enable(void); +void plat_cci_disable(void); + +/* Declarations for plat_topology.c */ +int mt_setup_topology(void); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h new file mode 100644 index 0000000..ce9951a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +/******************************************************************************* + * Plat SiP function constants + ******************************************************************************/ +#define MTK_PLAT_SIP_NUM_CALLS 7 + +#define MTK_SIP_PWR_ON_MTCMOS 0x82000402 +#define MTK_SIP_PWR_OFF_MTCMOS 0x82000403 +#define MTK_SIP_PWR_MTCMOS_SUPPORT 0x82000404 +#define MTK_SIP_SET_HDCP_KEY_NUM 0x82000405 +#define MTK_SIP_CLR_HDCP_KEY 0x82000406 +#define MTK_SIP_SET_HDCP_KEY_EX 0x82000407 +#define MTK_SIP_SMC_WATCHDOG 0x82003D06 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h new file mode 100644 index 0000000..d340422 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#include "mt8173_def.h" + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL1) +#define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +#define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x800 +#elif defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(2) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define SOC_CHIP_ID U(0x8173) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* + * MT8173 SRAM memory layout + * 0x100000 +-------------------+ + * | shared mem (4KB) | + * 0x101000 +-------------------+ + * | | + * | BL3-1 (124KB) | + * | | + * 0x120000 +-------------------+ + * | reserved (64KB) | + * 0x130000 +-------------------+ + */ +/* TF txet, ro, rw, xlat table, coherent memory ... etc. + * Size: release: 128KB, debug: 128KB + */ +#define TZRAM_BASE (0x100000) +#if DEBUG +#define TZRAM_SIZE (0x20000) +#else +#define TZRAM_SIZE (0x20000) +#endif + +/* Reserved: 64KB */ +#define TZRAM2_BASE (TZRAM_BASE + TZRAM_SIZE) +#define TZRAM2_SIZE (0x10000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL3-1 debug size plus a + * little space for growth. + */ +#define BL31_BASE (TZRAM_BASE + 0x1000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) +#define TZRAM2_LIMIT (TZRAM2_BASE + TZRAM2_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 4 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + + +#define PLAT_ARM_GICD_BASE BASE_GICD_BASE +#define PLAT_ARM_GICC_BASE BASE_GICC_BASE + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(MT_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(MT_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(MT_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(MT_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(MT_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(MT_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(MT_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(MT_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h new file mode 100644 index 0000000..195366d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POWER_TRACER_H +#define POWER_TRACER_H + +#define CPU_UP 0 +#define CPU_DOWN 1 +#define CPU_SUSPEND 2 +#define CLUSTER_UP 3 +#define CLUSTER_DOWN 4 +#define CLUSTER_SUSPEND 5 + +void trace_power_flow(unsigned long mpidr, unsigned char mode); + +#endif /* POWER_TRACER_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h new file mode 100644 index 0000000..b1e9424 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCU_H +#define SCU_H + +void disable_scu(unsigned long mpidr); +void enable_scu(unsigned long mpidr); + +#endif /* SCU_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c b/arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c new file mode 100644 index 0000000..80b9010 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +const unsigned int mt_irq_sec_array[] = { + MT_IRQ_SEC_SGI_0, + MT_IRQ_SEC_SGI_1, + MT_IRQ_SEC_SGI_2, + MT_IRQ_SEC_SGI_3, + MT_IRQ_SEC_SGI_4, + MT_IRQ_SEC_SGI_5, + MT_IRQ_SEC_SGI_6, + MT_IRQ_SEC_SGI_7 +}; + +void plat_mt_gic_init(void) +{ + arm_gic_init(BASE_GICC_BASE, + BASE_GICD_BASE, + BASE_GICR_BASE, + mt_irq_sec_array, + ARRAY_SIZE(mt_irq_sec_array)); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c new file mode 100644 index 0000000..e72a343 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c @@ -0,0 +1,603 @@ +/* + * 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 +#include /* generic_timer_backup() */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MTK_PWR_LVL0 0 +#define MTK_PWR_LVL1 1 +#define MTK_PWR_LVL2 2 + +/* Macros to read the MTK power domain state */ +#define MTK_CORE_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL0] +#define MTK_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL1] +#define MTK_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ?\ + (state)->pwr_domain_state[MTK_PWR_LVL2] : 0) + +#if PSCI_EXTENDED_STATE_ID +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +const unsigned int mtk_pm_idle_states[] = { + /* State-id - 0x001 */ + mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN, + MTK_LOCAL_STATE_RET, MTK_PWR_LVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x002 */ + mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN, + MTK_LOCAL_STATE_OFF, MTK_PWR_LVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x022 */ + mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_OFF, + MTK_LOCAL_STATE_OFF, MTK_PWR_LVL1, PSTATE_TYPE_POWERDOWN), +#if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1 + /* State-id - 0x222 */ + mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_OFF, MTK_LOCAL_STATE_OFF, + MTK_LOCAL_STATE_OFF, MTK_PWR_LVL2, PSTATE_TYPE_POWERDOWN), +#endif + 0, +}; +#endif + +struct core_context { + unsigned long timer_data[8]; + unsigned int count; + unsigned int rst; + unsigned int abt; + unsigned int brk; +}; + +struct cluster_context { + struct core_context core[PLATFORM_MAX_CPUS_PER_CLUSTER]; +}; + +/* + * Top level structure to hold the complete context of a multi cluster system + */ +struct system_context { + struct cluster_context cluster[PLATFORM_CLUSTER_COUNT]; +}; + +/* + * Top level structure which encapsulates the context of the entire system + */ +static struct system_context dormant_data[1]; + +static inline struct cluster_context *system_cluster( + struct system_context *system, + uint32_t clusterid) +{ + return &system->cluster[clusterid]; +} + +static inline struct core_context *cluster_core(struct cluster_context *cluster, + uint32_t cpuid) +{ + return &cluster->core[cpuid]; +} + +static struct cluster_context *get_cluster_data(unsigned long mpidr) +{ + uint32_t clusterid; + + clusterid = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + return system_cluster(dormant_data, clusterid); +} + +static struct core_context *get_core_data(unsigned long mpidr) +{ + struct cluster_context *cluster; + uint32_t cpuid; + + cluster = get_cluster_data(mpidr); + cpuid = mpidr & MPIDR_CPU_MASK; + + return cluster_core(cluster, cpuid); +} + +static void mt_save_generic_timer(unsigned long *container) +{ + uint64_t ctl; + uint64_t val; + + __asm__ volatile("mrs %x0, cntkctl_el1\n\t" + "mrs %x1, cntp_cval_el0\n\t" + "stp %x0, %x1, [%2, #0]" + : "=&r" (ctl), "=&r" (val) + : "r" (container) + : "memory"); + + __asm__ volatile("mrs %x0, cntp_tval_el0\n\t" + "mrs %x1, cntp_ctl_el0\n\t" + "stp %x0, %x1, [%2, #16]" + : "=&r" (val), "=&r" (ctl) + : "r" (container) + : "memory"); + + __asm__ volatile("mrs %x0, cntv_tval_el0\n\t" + "mrs %x1, cntv_ctl_el0\n\t" + "stp %x0, %x1, [%2, #32]" + : "=&r" (val), "=&r" (ctl) + : "r" (container) + : "memory"); +} + +static void mt_restore_generic_timer(unsigned long *container) +{ + uint64_t ctl; + uint64_t val; + + __asm__ volatile("ldp %x0, %x1, [%2, #0]\n\t" + "msr cntkctl_el1, %x0\n\t" + "msr cntp_cval_el0, %x1" + : "=&r" (ctl), "=&r" (val) + : "r" (container) + : "memory"); + + __asm__ volatile("ldp %x0, %x1, [%2, #16]\n\t" + "msr cntp_tval_el0, %x0\n\t" + "msr cntp_ctl_el0, %x1" + : "=&r" (val), "=&r" (ctl) + : "r" (container) + : "memory"); + + __asm__ volatile("ldp %x0, %x1, [%2, #32]\n\t" + "msr cntv_tval_el0, %x0\n\t" + "msr cntv_ctl_el0, %x1" + : "=&r" (val), "=&r" (ctl) + : "r" (container) + : "memory"); +} + +static inline uint64_t read_cntpctl(void) +{ + uint64_t cntpctl; + + __asm__ volatile("mrs %x0, cntp_ctl_el0" + : "=r" (cntpctl) : : "memory"); + + return cntpctl; +} + +static inline void write_cntpctl(uint64_t cntpctl) +{ + __asm__ volatile("msr cntp_ctl_el0, %x0" : : "r"(cntpctl)); +} + +static void stop_generic_timer(void) +{ + /* + * Disable the timer and mask the irq to prevent + * suprious interrupts on this cpu interface. It + * will bite us when we come back if we don't. It + * will be replayed on the inbound cluster. + */ + uint64_t cntpctl = read_cntpctl(); + + write_cntpctl(clr_cntp_ctl_enable(cntpctl)); +} + +static void mt_cpu_save(unsigned long mpidr) +{ + struct core_context *core; + + core = get_core_data(mpidr); + mt_save_generic_timer(core->timer_data); + + /* disable timer irq, and upper layer should enable it again. */ + stop_generic_timer(); +} + +static void mt_cpu_restore(unsigned long mpidr) +{ + struct core_context *core; + + core = get_core_data(mpidr); + mt_restore_generic_timer(core->timer_data); +} + +static void mt_platform_save_context(unsigned long mpidr) +{ + /* mcusys_save_context: */ + mt_cpu_save(mpidr); +} + +static void mt_platform_restore_context(unsigned long mpidr) +{ + /* mcusys_restore_context: */ + mt_cpu_restore(mpidr); +} + +static void plat_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr; + + scr = read_scr_el3(); + write_scr_el3(scr | SCR_IRQ_BIT); + isb(); + dsb(); + wfi(); + write_scr_el3(scr); +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to be turned + * on. The level and mpidr determine the affinity instance. + ******************************************************************************/ +static uintptr_t secure_entrypoint; + +static int plat_power_domain_on(unsigned long mpidr) +{ + int rc = PSCI_E_SUCCESS; + unsigned long cpu_id; + unsigned long cluster_id; + uintptr_t rv; + + cpu_id = mpidr & MPIDR_CPU_MASK; + cluster_id = mpidr & MPIDR_CLUSTER_MASK; + + if (cluster_id) + rv = (uintptr_t)&mt8173_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw; + else + rv = (uintptr_t)&mt8173_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw; + + mmio_write_32(rv, secure_entrypoint); + INFO("mt_on[%ld:%ld], entry %x\n", + cluster_id, cpu_id, mmio_read_32(rv)); + + spm_hotplug_on(mpidr); + return rc; +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to be turned + * off. The level and mpidr determine the affinity instance. The 'state' arg. + * allows the platform to decide whether the cluster is being turned off and + * take apt actions. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +static void plat_power_domain_off(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + + /* Prevent interrupts from spuriously waking up this cpu */ + gicv2_cpuif_disable(); + + spm_hotplug_off(mpidr); + + trace_power_flow(mpidr, CPU_DOWN); + + if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) { + /* Disable coherency if this cluster is to be turned off */ + plat_cci_disable(); + + trace_power_flow(mpidr, CLUSTER_DOWN); + } +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to be + * suspended. The level and mpidr determine the affinity instance. The 'state' + * arg. allows the platform to decide whether the cluster is being turned off + * and take apt actions. + * + * CAUTION: This function is called with coherent stacks so that caches can be + * turned off, flushed and coherency disabled. There is no guarantee that caches + * will remain turned on across calls to this function as each affinity level is + * dealt with. So do not write & read global variables across calls. It will be + * wise to do flush a write to the global to prevent unpredictable results. + ******************************************************************************/ +static void plat_power_domain_suspend(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned long cluster_id; + unsigned long cpu_id; + uintptr_t rv; + + cpu_id = mpidr & MPIDR_CPU_MASK; + cluster_id = mpidr & MPIDR_CLUSTER_MASK; + + if (cluster_id) + rv = (uintptr_t)&mt8173_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw; + else + rv = (uintptr_t)&mt8173_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw; + + mmio_write_32(rv, secure_entrypoint); + + if (MTK_SYSTEM_PWR_STATE(state) != MTK_LOCAL_STATE_OFF) { + spm_mcdi_prepare_for_off_state(mpidr, MTK_PWR_LVL0); + if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) + spm_mcdi_prepare_for_off_state(mpidr, MTK_PWR_LVL1); + } + + mt_platform_save_context(mpidr); + + /* Perform the common cluster specific operations */ + if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) { + /* Disable coherency if this cluster is to be turned off */ + plat_cci_disable(); + } + + if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) { + wdt_suspend(); + disable_scu(mpidr); + generic_timer_backup(); + spm_system_suspend(); + /* Prevent interrupts from spuriously waking up this cpu */ + gicv2_cpuif_disable(); + } +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance has just been powered + * on after being turned off earlier. The level and mpidr determine the affinity + * instance. The 'state' arg. allows the platform to decide whether the cluster + * was turned off prior to wakeup and do what's necessary to setup it up + * correctly. + ******************************************************************************/ +void mtk_system_pwr_domain_resume(void); + +static void plat_power_domain_on_finish(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + + assert(state->pwr_domain_state[MPIDR_AFFLVL0] == MTK_LOCAL_STATE_OFF); + + if ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) && + (state->pwr_domain_state[MTK_PWR_LVL2] == MTK_LOCAL_STATE_OFF)) + mtk_system_pwr_domain_resume(); + + if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) { + plat_cci_enable(); + trace_power_flow(mpidr, CLUSTER_UP); + } + + if ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) && + (state->pwr_domain_state[MTK_PWR_LVL2] == MTK_LOCAL_STATE_OFF)) + return; + + /* Enable the gic cpu interface */ + gicv2_cpuif_enable(); + gicv2_pcpu_distif_init(); + trace_power_flow(mpidr, CPU_UP); +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance has just been powered + * on after having been suspended earlier. The level and mpidr determine the + * affinity instance. + ******************************************************************************/ +static void plat_power_domain_suspend_finish(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + + if (state->pwr_domain_state[MTK_PWR_LVL0] == MTK_LOCAL_STATE_RET) + return; + + if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) { + /* Enable the gic cpu interface */ + plat_arm_gic_init(); + spm_system_suspend_finish(); + enable_scu(mpidr); + wdt_resume(); + } + + /* Perform the common cluster specific operations */ + if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) { + /* Enable coherency if this cluster was off */ + plat_cci_enable(); + } + + mt_platform_restore_context(mpidr); + + if (MTK_SYSTEM_PWR_STATE(state) != MTK_LOCAL_STATE_OFF) { + spm_mcdi_finish_for_on_state(mpidr, MTK_PWR_LVL0); + if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) + spm_mcdi_finish_for_on_state(mpidr, MTK_PWR_LVL1); + } + + gicv2_pcpu_distif_init(); +} + +static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + assert(PLAT_MAX_PWR_LVL >= 2); + + for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF; +} + +/******************************************************************************* + * MTK handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 plat_system_off(void) +{ + INFO("MTK System Off\n"); + + rtc_bbpu_power_down(); + + wfi(); + ERROR("MTK System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 plat_system_reset(void) +{ + /* Write the System Configuration Control Register */ + INFO("MTK System Reset\n"); + + wdt_trigger_reset(); + + wfi(); + ERROR("MTK System Reset: operation not handled.\n"); + panic(); +} + +#if !PSCI_EXTENDED_STATE_ID +static int plat_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pstate = psci_get_pstate_type(power_state); + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != 0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MTK_PWR_LVL0] = + MTK_LOCAL_STATE_RET; + } else { + for (i = 0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + MTK_LOCAL_STATE_OFF; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} +#else +int plat_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + assert(req_state); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; !!mtk_pm_idle_states[i]; i++) { + if (power_state == mtk_pm_idle_states[i]) + break; + } + + /* Return error if entry not found in the idle state array */ + if (!mtk_pm_idle_states[i]) + return PSCI_E_INVALID_PARAMS; + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + MTK_LOCAL_PSTATE_MASK; + state_id >>= MTK_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} +#endif + +void mtk_system_pwr_domain_resume(void) +{ + console_switch_state(CONSOLE_FLAG_BOOT); + + /* Assert system power domain is available on the platform */ + assert(PLAT_MAX_PWR_LVL >= MTK_PWR_LVL2); + + plat_arm_gic_init(); + + console_switch_state(CONSOLE_FLAG_RUNTIME); +} + +static const plat_psci_ops_t plat_plat_pm_ops = { + .cpu_standby = plat_cpu_standby, + .pwr_domain_on = plat_power_domain_on, + .pwr_domain_on_finish = plat_power_domain_on_finish, + .pwr_domain_off = plat_power_domain_off, + .pwr_domain_suspend = plat_power_domain_suspend, + .pwr_domain_suspend_finish = plat_power_domain_suspend_finish, + .system_off = plat_system_off, + .system_reset = plat_system_reset, + .validate_power_state = plat_validate_power_state, + .get_sys_suspend_power_state = plat_get_sys_suspend_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &plat_plat_pm_ops; + secure_entrypoint = sec_entrypoint; + return 0; +} + +/* + * The PSCI generic code uses this API to let the platform participate in state + * coordination during a power management operation. It compares the platform + * specific local power states requested by each cpu for a given power domain + * and returns the coordinated target power state that the domain should + * enter. A platform assigns a number to a local power state. This default + * implementation assumes that the platform assigns these numbers in order of + * increasing depth of the power state i.e. for two power states X & Y, if X < Y + * then X represents a shallower power state than Y. As a result, the + * coordinated target local power state for a power domain will be the minimum + * of the requested local power states. + */ +plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, + const plat_local_state_t *states, + unsigned int ncpu) +{ + plat_local_state_t target = PLAT_MAX_OFF_STATE, temp; + + assert(ncpu); + + do { + temp = *states++; + if (temp < target) + target = temp; + } while (--ncpu); + + return target; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c b/arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c new file mode 100644 index 0000000..da9b91d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Authorized secure register list */ +enum { + SREG_HDMI_COLOR_EN = 0x14000904 +}; + +static const uint32_t authorized_sreg[] = { + SREG_HDMI_COLOR_EN +}; + +#define authorized_sreg_cnt \ + (sizeof(authorized_sreg) / sizeof(authorized_sreg[0])) + +uint64_t mt_sip_set_authorized_sreg(uint32_t sreg, uint32_t val) +{ + uint64_t i; + + for (i = 0; i < authorized_sreg_cnt; i++) { + if (authorized_sreg[i] == sreg) { + mmio_write_32(sreg, val); + return MTK_SIP_E_SUCCESS; + } + } + + return MTK_SIP_E_INVALID_PARAM; +} + +static uint64_t mt_sip_pwr_on_mtcmos(uint32_t val) +{ + uint32_t ret; + + ret = mtcmos_non_cpu_ctrl(1, val); + if (ret) + return MTK_SIP_E_INVALID_PARAM; + else + return MTK_SIP_E_SUCCESS; +} + +static uint64_t mt_sip_pwr_off_mtcmos(uint32_t val) +{ + uint32_t ret; + + ret = mtcmos_non_cpu_ctrl(0, val); + if (ret) + return MTK_SIP_E_INVALID_PARAM; + else + return MTK_SIP_E_SUCCESS; +} + +static uint64_t mt_sip_pwr_mtcmos_support(void) +{ + return MTK_SIP_E_SUCCESS; +} + +uint64_t mediatek_plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + uint64_t ret; + + switch (smc_fid) { + case MTK_SIP_PWR_ON_MTCMOS: + ret = mt_sip_pwr_on_mtcmos((uint32_t)x1); + SMC_RET1(handle, ret); + + case MTK_SIP_PWR_OFF_MTCMOS: + ret = mt_sip_pwr_off_mtcmos((uint32_t)x1); + SMC_RET1(handle, ret); + + case MTK_SIP_PWR_MTCMOS_SUPPORT: + ret = mt_sip_pwr_mtcmos_support(); + SMC_RET1(handle, ret); + + case MTK_SIP_SET_HDCP_KEY_EX: + ret = crypt_set_hdcp_key_ex(x1, x2, x3); + SMC_RET1(handle, ret); + + case MTK_SIP_SET_HDCP_KEY_NUM: + ret = crypt_set_hdcp_key_num((uint32_t)x1); + SMC_RET1(handle, ret); + + case MTK_SIP_CLR_HDCP_KEY: + ret = crypt_clear_hdcp_key(); + SMC_RET1(handle, ret); + + case MTK_SIP_SMC_WATCHDOG: + return wdt_smc_handler(x1, x2, handle); + + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c new file mode 100644 index 0000000..23e7d2d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +const unsigned char mtk_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, + /* No of children for the second cluster node */ + PLATFORM_CLUSTER1_CORE_COUNT +}; + +/******************************************************************************* + * This function returns the MT8173 default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return mtk_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8173/platform.mk new file mode 100644 index 0000000..f62802c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/platform.mk @@ -0,0 +1,74 @@ +# +# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MTK_PLAT := plat/mediatek +MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} + +PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -Iinclude/plat/arm/common/aarch64 \ + -I${MTK_PLAT_SOC}/drivers/crypt/ \ + -I${MTK_PLAT_SOC}/drivers/mtcmos/ \ + -I${MTK_PLAT_SOC}/drivers/pmic/ \ + -I${MTK_PLAT_SOC}/drivers/rtc/ \ + -I${MTK_PLAT_SOC}/drivers/spm/ \ + -I${MTK_PLAT_SOC}/drivers/timer/ \ + -I${MTK_PLAT_SOC}/drivers/wdt/ \ + -I${MTK_PLAT_SOC}/include/ + +PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + plat/arm/common/arm_gicv2.c \ + plat/common/plat_gicv2.c \ + plat/common/aarch64/crash_console_helpers.S + +BL31_SOURCES += common/desc_image_load.c \ + drivers/arm/cci/cci.c \ + drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ + ${MTK_PLAT_SOC}/aarch64/platform_common.c \ + ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/drivers/crypt/crypt.c \ + ${MTK_PLAT_SOC}/drivers/mtcmos/mtcmos.c \ + ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \ + ${MTK_PLAT_SOC}/drivers/spm/spm.c \ + ${MTK_PLAT_SOC}/drivers/spm/spm_hotplug.c \ + ${MTK_PLAT_SOC}/drivers/spm/spm_mcdi.c \ + ${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \ + ${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \ + ${MTK_PLAT_SOC}/drivers/wdt/wdt.c \ + ${MTK_PLAT_SOC}/plat_pm.c \ + ${MTK_PLAT_SOC}/plat_sip_calls.c \ + ${MTK_PLAT_SOC}/plat_topology.c \ + ${MTK_PLAT_SOC}/power_tracer.c \ + ${MTK_PLAT_SOC}/scu.c + +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_826319 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_855873 := 1 + +# indicate the reset vector address can be programmed +PROGRAMMABLE_RESET_ADDRESS := 1 + +$(eval $(call add_define,MTK_SIP_SET_AUTHORIZED_SECURE_REG_ENABLE)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +MULTI_CONSOLE_API := 1 diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c b/arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c new file mode 100644 index 0000000..d1fcf9f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#define trace_log(...) INFO("psci: " __VA_ARGS__) + +void trace_power_flow(unsigned long mpidr, unsigned char mode) +{ + switch (mode) { + case CPU_UP: + trace_log("core %lld:%lld ON\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS, + (mpidr & MPIDR_CPU_MASK)); + break; + case CPU_DOWN: + trace_log("core %lld:%lld OFF\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS, + (mpidr & MPIDR_CPU_MASK)); + break; + case CPU_SUSPEND: + trace_log("core %lld:%lld SUSPEND\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS, + (mpidr & MPIDR_CPU_MASK)); + break; + case CLUSTER_UP: + trace_log("cluster %lld ON\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS); + break; + case CLUSTER_DOWN: + trace_log("cluster %lld OFF\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS); + break; + case CLUSTER_SUSPEND: + trace_log("cluster %lld SUSPEND\n", + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS); + break; + default: + trace_log("unknown power mode\n"); + break; + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/scu.c b/arm-trusted-firmware/plat/mediatek/mt8173/scu.c new file mode 100644 index 0000000..2524d72 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/scu.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +void disable_scu(unsigned long mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp1_miscdbg, + MP1_ACINACTM); + else + mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp0_axi_config, + MP0_ACINACTM); +} + +void enable_scu(unsigned long mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + mmio_clrbits_32((uintptr_t)&mt8173_mcucfg->mp1_miscdbg, + MP1_ACINACTM); + else + mmio_clrbits_32((uintptr_t)&mt8173_mcucfg->mp0_axi_config, + MP0_ACINACTM); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S new file mode 100644 index 0000000..5c39633 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void); + * + * result: CorePos = CoreId + (ClusterId << 2) + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c new file mode 100644 index 0000000..31d1339 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +static const int cci_map[] = { + PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX +}; + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_mmap[] = { + /* for TF text, RO, RW */ + MAP_REGION_FLAT(TZRAM_BASE, TZRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit, + uintptr_t coh_start, + uintptr_t coh_limit) +{ + mmap_add_region(total_base, total_base, total_size, + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + MT_MEMORY | MT_RO | MT_SECURE); + mmap_add_region(coh_start, coh_start, coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); + mmap_add(plat_mmap); + init_xlat_tables(); + enable_mmu_el3(0); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +void plat_mtk_cci_init(void) +{ + /* Initialize CCI driver */ + mcsi_init(PLAT_MT_CCI_BASE, ARRAY_SIZE(cci_map)); +} + +void plat_mtk_cci_enable(void) +{ + /* Enable CCI coherency for this cluster. + * No need for locks as no other cpu is active at the moment. + */ + cci_enable_cluster_coherency(read_mpidr()); +} + +void plat_mtk_cci_disable(void) +{ + cci_disable_cluster_coherency(read_mpidr()); +} + +void plat_mtk_cci_init_sf(void) +{ + /* Init mcsi snoop filter. */ + cci_init_sf(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c new file mode 100644 index 0000000..7dac8a4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2019, MediaTek Inc. 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 +#include +#include + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; + +static void platform_setup_cpu(void) +{ + mmio_write_32((uintptr_t)&mt8183_mcucfg->mp0_rw_rsvd0, 0x00000001); + + /* Mcusys dcm control */ + /* Enable pll plldiv dcm */ + mmio_setbits_32((uintptr_t)&mt8183_mcucfg->bus_pll_divider_cfg, + BUS_PLLDIV_DCM); + mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp0_pll_divider_cfg, + MP0_PLLDIV_DCM); + mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp2_pll_divider_cfg, + MP2_PLLDIV_DCM); + /* Enable mscib dcm */ + mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->mscib_dcm_en, + MCSIB_CACTIVE_SEL_MASK, MCSIB_CACTIVE_SEL); + mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->mscib_dcm_en, + MCSIB_DCM_MASK, MCSIB_DCM); + /* Enable adb400 dcm */ + mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->cci_adb400_dcm_config, + CCI_ADB400_DCM_MASK, CCI_ADB400_DCM); + /* Enable bus clock dcm */ + mmio_setbits_32((uintptr_t)&mt8183_mcucfg->cci_clk_ctrl, + MCU_BUS_DCM); + /* Enable bus fabric dcm */ + mmio_clrsetbits_32( + (uintptr_t)&mt8183_mcucfg->mcusys_bus_fabric_dcm_ctrl, + MCUSYS_BUS_FABRIC_DCM_MASK, + MCUSYS_BUS_FABRIC_DCM); + /* Enable l2c sram dcm */ + mmio_setbits_32((uintptr_t)&mt8183_mcucfg->l2c_sram_ctrl, + L2C_SRAM_DCM); + /* Enable busmp0 sync dcm */ + mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->sync_dcm_config, + SYNC_DCM_MASK, SYNC_DCM); + /* Enable cntvalue dcm */ + mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mcu_misc_dcm_ctrl, + CNTVALUEB_DCM); + /* Enable dcm cluster stall */ + mmio_clrsetbits_32( + (uintptr_t)&mt8183_mcucfg->sync_dcm_cluster_config, + MCUSYS_MAX_ACCESS_LATENCY_MASK, + MCUSYS_MAX_ACCESS_LATENCY); + mmio_setbits_32((uintptr_t)&mt8183_mcucfg->sync_dcm_cluster_config, + MCU0_SYNC_DCM_STALL_WR_EN); + /* Enable rgu dcm */ + mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp0_rgu_dcm_config, + CPUSYS_RGU_DCM_CINFIG); +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + * BL2 has flushed this information to memory, so we are guaranteed to pick up + * good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + params_early_setup(arg1); + +#if COREBOOT + if (coreboot_serial.type) + console_16550_register(coreboot_serial.baseaddr, + coreboot_serial.input_hertz, + coreboot_serial.baud, + &console); +#else + console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console); +#endif + + NOTICE("MT8183 bl31_setup\n"); + + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); +} + + +/******************************************************************************* + * Perform any BL31 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + devapc_init(); + + emi_mpu_init(); + + platform_setup_cpu(); + generic_delay_timer_init(); + + /* Initialize the GIC driver, CPU and distributor interfaces */ + mt_gic_driver_init(); + mt_gic_init(); + + mt_systimer_init(); + + /* Init mcsi SF */ + plat_mtk_cci_init_sf(); + +#if SPMC_MODE == 1 + spmc_init(); +#endif + spm_boot_init(); + mcdi_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + plat_mtk_cci_init(); + plat_mtk_cci_enable(); + + enable_scu(read_mpidr()); + + plat_configure_mmu_el3(BL_CODE_BASE, + BL_COHERENT_RAM_END - BL_CODE_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c new file mode 100644 index 0000000..9d76aa5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static void set_master_transaction(uint32_t master_index, + enum TRANSACTION transaction_type) +{ + uintptr_t base; + uint32_t master_register_index; + uint32_t master_set_index; + uint32_t set_bit; + + master_register_index = master_index / (MOD_NO_IN_1_DEVAPC * 2); + master_set_index = master_index % (MOD_NO_IN_1_DEVAPC * 2); + + base = DEVAPC_INFRA_MAS_SEC_0 + master_register_index * 4; + + set_bit = 0x1 << master_set_index; + if (transaction_type == SECURE_TRANSACTION) + mmio_setbits_32(base, set_bit); + else + mmio_clrbits_32(base, set_bit); +} + +static void set_master_domain(uint32_t master_index, enum MASK_DOM domain) +{ + uintptr_t base; + uint32_t domain_reg; + uint32_t domain_index; + uint32_t clr_bit; + uint32_t set_bit; + + domain_reg = master_index / MASTER_MOD_NO_IN_1_DEVAPC; + domain_index = master_index % MASTER_MOD_NO_IN_1_DEVAPC; + clr_bit = 0xF << (4 * domain_index); + set_bit = domain << (4 * domain_index); + + base = DEVAPC_INFRA_MAS_DOM_0 + domain_reg * 4; + mmio_clrsetbits_32(base, clr_bit, set_bit); +} + +static void set_master_domain_remap_infra(enum MASK_DOM domain_emi_view, + enum MASK_DOM domain_infra_view) +{ + uintptr_t base; + uint32_t clr_bit; + uint32_t set_bit; + + if (domain_emi_view < DOMAIN_10) { + base = DEVAPC_INFRA_DOM_RMP_0; + clr_bit = 0x7 << (domain_emi_view * 3); + set_bit = domain_infra_view << (domain_emi_view * 3); + mmio_clrsetbits_32(base, clr_bit, set_bit); + } else if (domain_emi_view > DOMAIN_10) { + base = DEVAPC_INFRA_DOM_RMP_1; + domain_emi_view = domain_emi_view - DOMAIN_11; + clr_bit = 0x7 << (domain_emi_view * 3 + 1); + set_bit = domain_infra_view << (domain_emi_view * 3 + 1); + mmio_clrsetbits_32(base, clr_bit, set_bit); + } else { + base = DEVAPC_INFRA_DOM_RMP_0; + clr_bit = 0x3 << (domain_emi_view * 3); + set_bit = domain_infra_view << (domain_emi_view * 3); + mmio_clrsetbits_32(base, clr_bit, set_bit); + + base = DEVAPC_INFRA_DOM_RMP_1; + set_bit = (domain_infra_view & 0x4) >> 2; + mmio_clrsetbits_32(base, 0x1, set_bit); + } +} + +static void set_master_domain_remap_mm(enum MASK_DOM domain_emi_view, + enum MASK_DOM domain_mm_view) +{ + uintptr_t base; + uint32_t clr_bit; + uint32_t set_bit; + + base = DEVAPC_MM_DOM_RMP_0; + clr_bit = 0x3 << (domain_emi_view * 2); + set_bit = domain_mm_view << (domain_emi_view * 2); + + mmio_clrsetbits_32(base, clr_bit, set_bit); +} + +static void set_module_apc(enum DAPC_SLAVE_TYPE slave_type, uint32_t module, + enum MASK_DOM domain_num, + enum APC_ATTR permission_control) +{ + uintptr_t base; + uint32_t apc_index; + uint32_t apc_set_index; + uint32_t clr_bit; + uint32_t set_bit; + + apc_index = module / MOD_NO_IN_1_DEVAPC; + apc_set_index = module % MOD_NO_IN_1_DEVAPC; + clr_bit = 0x3 << (apc_set_index * 2); + set_bit = permission_control << (apc_set_index * 2); + + if (slave_type == DAPC_INFRA_SLAVE && module <= SLAVE_INFRA_MAX_INDEX) + base = DEVAPC_INFRA_D0_APC_0 + domain_num * 0x100 + + apc_index * 4; + else if (slave_type == DAPC_MM_SLAVE && module <= SLAVE_MM_MAX_INDEX) + base = DEVAPC_MM_D0_APC_0 + domain_num * 0x100 + apc_index * 4; + else + return; + + mmio_clrsetbits_32(base, clr_bit, set_bit); +} + +static void set_default_master_transaction(void) +{ + set_master_transaction(MASTER_SSPM, SECURE_TRANSACTION); +} + +static void set_default_master_domain(void) +{ + set_master_domain(MASTER_SCP, DOMAIN_1); + set_master_domain_remap_infra(DOMAIN_1, DOMAIN_1); + set_master_domain_remap_mm(DOMAIN_1, DOMAIN_1); + + set_master_domain(MASTER_SPM, DOMAIN_2); + set_master_domain_remap_infra(DOMAIN_2, DOMAIN_2); + set_master_domain_remap_mm(DOMAIN_2, DOMAIN_2); + + set_master_domain(MASTER_SSPM, DOMAIN_2); + set_master_domain_remap_infra(DOMAIN_2, DOMAIN_2); + set_master_domain_remap_mm(DOMAIN_2, DOMAIN_2); +} + +static void set_default_slave_permission(void) +{ + uint32_t module_index; + uint32_t infra_size; + uint32_t mm_size; + + infra_size = sizeof(D_APC_INFRA_Devices) / sizeof(struct DEVICE_INFO); + mm_size = sizeof(D_APC_MM_Devices) / sizeof(struct DEVICE_INFO); + + for (module_index = 0; module_index < infra_size; module_index++) { + if (D_APC_INFRA_Devices[module_index].d0_permission > 0) { + set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_0, + D_APC_INFRA_Devices[module_index].d0_permission); + } + if (D_APC_INFRA_Devices[module_index].d1_permission > 0) { + set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_1, + D_APC_INFRA_Devices[module_index].d1_permission); + } + if (D_APC_INFRA_Devices[module_index].d2_permission > 0) { + set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_2, + D_APC_INFRA_Devices[module_index].d2_permission); + } + } + + for (module_index = 0; module_index < mm_size; module_index++) { + if (D_APC_MM_Devices[module_index].d0_permission > 0) { + set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_0, + D_APC_MM_Devices[module_index].d0_permission); + } + if (D_APC_MM_Devices[module_index].d1_permission > 0) { + set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_1, + D_APC_MM_Devices[module_index].d1_permission); + } + if (D_APC_MM_Devices[module_index].d2_permission > 0) { + set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_2, + D_APC_MM_Devices[module_index].d2_permission); + } + } +} + +static void dump_devapc(void) +{ + int i; + + INFO("[DEVAPC] dump DEVAPC registers:\n"); + + for (i = 0; i < 13; i++) { + INFO("[DEVAPC] (INFRA)D0_APC_%d = 0x%x, " + "(INFRA)D1_APC_%d = 0x%x, " + "(INFRA)D2_APC_%d = 0x%x\n", + i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + i * 4), + i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + 0x100 + i * 4), + i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + 0x200 + i * 4)); + } + + for (i = 0; i < 9; i++) { + INFO("[DEVAPC] (MM)D0_APC_%d = 0x%x, " + "(MM)D1_APC_%d = 0x%x, " + "(MM)D2_APC_%d = 0x%x\n", + i, mmio_read_32(DEVAPC_MM_D0_APC_0 + i * 4), + i, mmio_read_32(DEVAPC_MM_D0_APC_0 + 0x100 + i * 4), + i, mmio_read_32(DEVAPC_MM_D0_APC_0 + 0x200 + i * 4)); + } + + for (i = 0; i < 4; i++) { + INFO("[DEVAPC] MAS_DOM_%d = 0x%x\n", i, + mmio_read_32(DEVAPC_INFRA_MAS_DOM_0 + i * 4)); + } + + INFO("[DEVAPC] MAS_SEC_0 = 0x%x\n", + mmio_read_32(DEVAPC_INFRA_MAS_SEC_0)); + + INFO("[DEVAPC] (INFRA)MAS_DOMAIN_REMAP_0 = 0x%x, " + "(INFRA)MAS_DOMAIN_REMAP_1 = 0x%x\n", + mmio_read_32(DEVAPC_INFRA_DOM_RMP_0), + mmio_read_32(DEVAPC_INFRA_DOM_RMP_1)); + + INFO("[DEVAPC] (MM)MAS_DOMAIN_REMAP_0 = 0x%x\n", + mmio_read_32(DEVAPC_MM_DOM_RMP_0)); +} + +void devapc_init(void) +{ + mmio_write_32(DEVAPC_INFRA_APC_CON, 0x80000001); + mmio_write_32(DEVAPC_MM_APC_CON, 0x80000001); + mmio_write_32(DEVAPC_MD_APC_CON, 0x80000001); + + set_default_master_transaction(); + set_default_master_domain(); + set_default_slave_permission(); + dump_devapc(); +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h new file mode 100644 index 0000000..042a8ff --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEVAPC_H +#define DEVAPC_H + +#include + +#define DEVAPC_AO_INFRA_BASE 0x1000E000 +#define DEVAPC_AO_MM_BASE 0x1001C000 +#define DEVAPC_AO_MD_BASE 0x10019000 + +#define DEVAPC_INFRA_D0_APC_0 (DEVAPC_AO_INFRA_BASE + 0x0000) +#define DEVAPC_INFRA_MAS_DOM_0 (DEVAPC_AO_INFRA_BASE + 0x0A00) +#define DEVAPC_INFRA_MAS_SEC_0 (DEVAPC_AO_INFRA_BASE + 0x0B00) +#define DEVAPC_INFRA_DOM_RMP_0 (DEVAPC_AO_INFRA_BASE + 0x0D00) +#define DEVAPC_INFRA_DOM_RMP_1 (DEVAPC_AO_INFRA_BASE + 0x0D04) +#define DEVAPC_INFRA_APC_CON (DEVAPC_AO_INFRA_BASE + 0x0F00) + +#define DEVAPC_MD_APC_CON (DEVAPC_AO_MD_BASE + 0x0F00) + +#define DEVAPC_MM_D0_APC_0 (DEVAPC_AO_MM_BASE + 0x0000) +#define DEVAPC_MM_DOM_RMP_0 (DEVAPC_AO_MM_BASE + 0x0D00) +#define DEVAPC_MM_APC_CON (DEVAPC_AO_MM_BASE + 0x0F00) + +#define MOD_NO_IN_1_DEVAPC 16 +#define MASTER_MOD_NO_IN_1_DEVAPC 8 +#define SLAVE_INFRA_MAX_INDEX 195 +#define SLAVE_MM_MAX_INDEX 140 + +enum { + MASTER_SCP = 0, + MASTER_SPM = 10, + MASTER_SSPM = 27 +}; + +enum MASK_DOM { + DOMAIN_0 = 0, + DOMAIN_1, + DOMAIN_2, + DOMAIN_3, + DOMAIN_4, + DOMAIN_5, + DOMAIN_6, + DOMAIN_7, + DOMAIN_8, + DOMAIN_9, + DOMAIN_10, + DOMAIN_11 +}; + +enum TRANSACTION { + NON_SECURE_TRANSACTION = 0, + SECURE_TRANSACTION +}; + +enum DAPC_SLAVE_TYPE { + DAPC_INFRA_SLAVE = 0, + DAPC_MM_SLAVE +}; + +enum APC_ATTR { + NO_SEC = 0, + S_RW_ONLY, + S_RW_NS_R, + FORBID, +}; + +struct DEVICE_INFO { + uint8_t d0_permission; + uint8_t d1_permission; + uint8_t d2_permission; +}; + +#define PERMISSION(DEV_NAME, ATTR1, ATTR2, ATTR3) \ +{(uint8_t)ATTR1, (uint8_t)ATTR2, (uint8_t)ATTR3} + +static const struct DEVICE_INFO D_APC_INFRA_Devices[] = { +/* module, domain0, domain1, domain2 */ + +/* 0 */ +PERMISSION("INFRA_AO_TOPCKGEN", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("INFRA_AO_INFRASYS_CONFIG_REGS", NO_SEC, FORBID, NO_SEC), +PERMISSION("IO_CFG", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_PERICFG", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_EFUSE_AO_DEBUG", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_GPIO", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_SLEEP_CONTROLLER", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_TOPRGU", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_APXGPT", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_RESERVE", NO_SEC, FORBID, NO_SEC), + +/* 10 */ +PERMISSION("INFRA_AO_SEJ", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_AP_CIRQ_EINT", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_APMIXEDSYS", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("INFRA_AO_PMIC_WRAP", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_DEVICE_APC_AO_INFRA_PERI", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_SLEEP_CONTROLLER_MD", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_KEYPAD", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_TOP_MISC", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_DVFS_CTRL_PROC", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_MBIST_AO_REG", NO_SEC, FORBID, NO_SEC), + +/* 20 */ +PERMISSION("INFRA_AO_CLDMA_AO_AP", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_DEVICE_MPU", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_AES_TOP_0", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_SYS_TIMER", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_MDEM_TEMP_SHARE", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_DEVICE_APC_AO_MD", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_SECURITY_AO", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_TOPCKGEN_REG", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_DEVICE_APC_AO_MM", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC), + +/* 30 */ +PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_SYS_CIRQ", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_MM_IOMMU", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_EFUSE_PDN_DEBUG", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DEVICE_APC", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DBG_TRACKER", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CCIF0_AP", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CCIF0_MD", NO_SEC, FORBID, NO_SEC), + +/* 40 */ +PERMISSION("INFRASYS_CCIF1_AP", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CCIF1_MD", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_MBIST", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_INFRA_PDN_REGISTER", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_TRNG", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DX_CC", NO_SEC, FORBID, NO_SEC), +PERMISSION("MD_CCIF_MD1", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CQ_DMA", NO_SEC, FORBID, NO_SEC), +PERMISSION("MD_CCIF_MD2", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_SRAMROM", NO_SEC, FORBID, NO_SEC), + +/* 50 */ +PERMISSION("ANA_MIPI_DSI0", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("ANA_MIPI_CSI0", NO_SEC, FORBID, NO_SEC), +PERMISSION("ANA_MIPI_CSI1", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_EMI", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CLDMA_PDN", NO_SEC, FORBID, NO_SEC), +PERMISSION("CLDMA_PDN_MD_MISC", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_MD", NO_SEC, FORBID, NO_SEC), +PERMISSION("BPI_BSI_SLV0", NO_SEC, FORBID, NO_SEC), + +/* 60 */ +PERMISSION("BPI_BSI_SLV1", NO_SEC, FORBID, NO_SEC), +PERMISSION("BPI_BSI_SLV2", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_EMI_MPU", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DVFS_PROC", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH0_TOP0", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH0_TOP1", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH0_TOP2", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH0_TOP3", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH0_TOP4", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH1_TOP0", NO_SEC, FORBID, NO_SEC), + +/* 70 */ +PERMISSION("INFRASYS_DRAMC_CH1_TOP1", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH1_TOP2", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH1_TOP3", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DRAMC_CH1_TOP4", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_GCE", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CCIF2_AP", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CCIF2_MD", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CCIF3_AP", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_CCIF3_MD", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRA_AO_PWRMCU Partition 1", S_RW_NS_R, FORBID, NO_SEC), + +/* 80 */ +PERMISSION("INFRA_AO_PWRMCU Partition 2", S_RW_NS_R, FORBID, NO_SEC), +PERMISSION("INFRA_AO_PWRMCU Partition 3", S_RW_NS_R, FORBID, NO_SEC), +PERMISSION("INFRA_AO_PWRMCU Partition 4", S_RW_NS_R, FORBID, NO_SEC), +PERMISSION("INFRA_AO_PWRMCU Partition 5", S_RW_NS_R, FORBID, NO_SEC), +PERMISSION("INFRA_AO_PWRMCU Partition 6", S_RW_NS_R, FORBID, NO_SEC), +PERMISSION("INFRA_AO_PWRMCU Partition 7", S_RW_NS_R, FORBID, NO_SEC), +PERMISSION("INFRA_AO_PWRMCU Partition 8", S_RW_NS_R, FORBID, NO_SEC), +PERMISSION("INFRA_AO_SCP", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("INFRA_AO_MCUCFG", NO_SEC, FORBID, NO_SEC), +PERMISSION("INFRASYS_DBUGSYS", NO_SEC, FORBID, NO_SEC), + +/* 90 */ +PERMISSION("PERISYS_APDMA", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_AUXADC", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_UART0", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("PERISYS_UART1", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_UART2", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C6", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_PWM", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C0", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C1", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C2", NO_SEC, FORBID, NO_SEC), + +/* 100 */ +PERMISSION("PERISYS_SPI0", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_PTP", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_BTIF", NO_SEC, FORBID, NO_SEC), +PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_DISP_PWM", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C3", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_SPI1", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C4", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_SPI2", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_SPI3", NO_SEC, FORBID, NO_SEC), + +/* 110 */ +PERMISSION("PERISYS_I2C1_IMM", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C2_IMM", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C5", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C5_IMM", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_SPI4", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_SPI5", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C7", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_I2C8", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_USB", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_USB_2_0_SUB", NO_SEC, FORBID, NO_SEC), + +/* 120 */ +PERMISSION("PERISYS_AUDIO", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_MSDC0", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_MSDC1", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_MSDC2", NO_SEC, FORBID, NO_SEC), +PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_UFS", NO_SEC, FORBID, NO_SEC), +PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_0", NO_SEC, FORBID, NO_SEC), + +/* 130 */ +PERMISSION("EAST_RESERVE_1", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_2", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_3", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_4", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_IO_CFG_RT", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_6", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_7", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_CSI0_TOP_AO", NO_SEC, FORBID, NO_SEC), +PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_A", NO_SEC, FORBID, NO_SEC), + +/* 140 */ +PERMISSION("EAST_RESERVE_B", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_C", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_D", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_E", NO_SEC, FORBID, NO_SEC), +PERMISSION("EAST_RESERVE_F", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_0", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_1", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_IO_CFG_RM", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_IO_CFG_RB", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_EFUSE", NO_SEC, FORBID, NO_SEC), + +/* 150 */ +PERMISSION("SOUTH_RESERVE_5", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_6", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_7", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_8", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_9", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_A", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_B", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_C", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_D", NO_SEC, FORBID, NO_SEC), +PERMISSION("SOUTH_RESERVE_E", NO_SEC, FORBID, NO_SEC), + +/* 160 */ +PERMISSION("SOUTH_RESERVE_F", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_0", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_MSDC1_PAD_MACRO", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_2", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_3", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_4", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_MIPI_TX_CONFIG", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_6", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_IO_CFG_LB", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_IO_CFG_LM", NO_SEC, FORBID, NO_SEC), + +/* 170 */ +PERMISSION("WEST_IO_CFG_BL", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_A", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_B", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_C", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_D", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_E", NO_SEC, FORBID, NO_SEC), +PERMISSION("WEST_RESERVE_F", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_0", NO_SEC, FORBID, NO_SEC), +PERMISSION("EFUSE_TOP", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_IO_CFG_LT", NO_SEC, FORBID, NO_SEC), + +/* 180 */ +PERMISSION("NORTH_IO_CFG_TL", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_USB20 PHY", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_MSDC0 PAD MACRO", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_6", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_7", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_8", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_9", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_UFS_MPHY", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_B", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_C", NO_SEC, FORBID, NO_SEC), + +/* 190 */ +PERMISSION("NORTH_RESERVE_D", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_E", NO_SEC, FORBID, NO_SEC), +PERMISSION("NORTH_RESERVE_F", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_CONN", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_MD_VIOLATION", NO_SEC, FORBID, NO_SEC), +PERMISSION("PERISYS_RESERVE", NO_SEC, FORBID, NO_SEC) +}; + +static const struct DEVICE_INFO D_APC_MM_Devices[] = { +/* module, domain0, domain1, domain2 */ + +/* 0 */ +PERMISSION("G3D_CONFIG", NO_SEC, FORBID, NO_SEC), +PERMISSION("MFG VAD", NO_SEC, FORBID, NO_SEC), +PERMISSION("SC0 VAD", NO_SEC, FORBID, NO_SEC), +PERMISSION("MFG_OTHERS", NO_SEC, FORBID, NO_SEC), +PERMISSION("MMSYS_CONFIG", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("MDP_RDMA0", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("MDP_RDMA1", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("MDP_RSZ0", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("MDP_RSZ1", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("MDP_WROT0", NO_SEC, NO_SEC, NO_SEC), + +/* 10 */ +PERMISSION("MDP_WDMA", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("MDP_TDSHP", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_OVL0", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_OVL0_2L", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_OVL1_2L", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_RDMA0", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_RDMA1", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_WDMA0", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_COLOR0", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_CCORR0", NO_SEC, FORBID, NO_SEC), + +/* 20 */ +PERMISSION("DISP_AAL0", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_GAMMA0", NO_SEC, FORBID, NO_SEC), +PERMISSION("DISP_DITHER0", NO_SEC, FORBID, NO_SEC), +PERMISSION("DSI_SPLIT", NO_SEC, FORBID, NO_SEC), +PERMISSION("DSI0", NO_SEC, FORBID, NO_SEC), +PERMISSION("DPI", NO_SEC, FORBID, NO_SEC), +PERMISSION("MM_MUTEX", NO_SEC, FORBID, NO_SEC), +PERMISSION("SMI_LARB0", NO_SEC, FORBID, NO_SEC), +PERMISSION("SMI_LARB1", NO_SEC, FORBID, NO_SEC), +PERMISSION("SMI_COMMON", NO_SEC, FORBID, NO_SEC), + +/* 30 */ +PERMISSION("DISP_RSZ", NO_SEC, FORBID, NO_SEC), +PERMISSION("MDP_AAL", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("MDP_CCORR", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("DBI", NO_SEC, FORBID, NO_SEC), +PERMISSION("MMSYS_OTHERS", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_CONFIG", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("IMGSYS_SMI_LARB1", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_DISP_A0", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("IMGSYS_DISP_A1", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_DISP_A2", NO_SEC, FORBID, NO_SEC), + +/* 40 */ +PERMISSION("IMGSYS_DISP_A3", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_DISP_A4", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_DISP_A5", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_DPE", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_RSC", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_WPEA", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_FDVT", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("IMGSYS_OWE", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_WPEB", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_MFB", NO_SEC, FORBID, NO_SEC), + +/* 50 */ +PERMISSION("IMGSYS_SMI_LARB2", NO_SEC, FORBID, NO_SEC), +PERMISSION("IMGSYS_OTHERS", NO_SEC, FORBID, NO_SEC), +PERMISSION("VENCSYS_GLOBAL_CON", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("VENCSYSSYS_SMI_LARB4", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("VENCSYS_VENC", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("VENCSYS_JPGENC", NO_SEC, FORBID, NO_SEC), +PERMISSION("VENCSYS_MBIST_CTRL", NO_SEC, FORBID, NO_SEC), +PERMISSION("VENCSYS_OTHERS", NO_SEC, FORBID, NO_SEC), +PERMISSION("VDECSYS_GLOBAL_CON", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("VDECSYS_SMI_LARB1", NO_SEC, FORBID, NO_SEC), + +/* 60 */ +PERMISSION("VDECSYS_FULL_TOP", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("VDECSYS_OTHERS", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAMSYS_TOP", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_LARB6", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("CAMSYS_LARB3", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("CAMSYS_CAM_TOP", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("CAMSYS_CAM_A", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("CAMSYS_CAM_A", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("CAMSYS_CAM_B", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("CAMSYS_CAM_B", NO_SEC, NO_SEC, NO_SEC), + +/* 70 */ +PERMISSION("CAMSYS_CAM_C", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("CAMSYS_CAM_C", NO_SEC, NO_SEC, NO_SEC), +PERMISSION("CAMSYS_CAM_TOP_SET", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_A_SET", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_A_SET", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_B_SET", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_B_SET", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_C_SET", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_C_SET", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_TOP_INNER", NO_SEC, FORBID, NO_SEC), + +/* 80 */ +PERMISSION("CAMSYS_CAM_A_INNER", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_A_INNER", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_B_INNER", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_B_INNER", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_C_INNER", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_C_INNER", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_A_EXT", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_B_EXT", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_C_EXT", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_TOP_CLR", NO_SEC, FORBID, NO_SEC), + +/* 90 */ +PERMISSION("CAMSYS_CAM_A_CLR", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_A_CLR", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_B_CLR", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_B_CLR", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_C_CLR", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_C_CLR", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_A_EXT", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_B_EXT", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_C_EXT", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAM_RESERVE", NO_SEC, FORBID, NO_SEC), + +/* 100 */ +PERMISSION("CAMSYS_SENINF_A", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_SENINF_B", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_SENINF_C", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_SENINF_D", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_SENINF_E", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_SENINF_F", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_SENINF_G", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_SENINF_H", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAMSV_A", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAMSV_B", NO_SEC, FORBID, NO_SEC), + +/* 110 */ +PERMISSION("CAMSYS_CAMSV_C", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CAMSV_D", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_MD32 DMEM_12", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_RESEVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CCU_CTL", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CCU_H2T_A", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CCU_T2H_A", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_RESERVE", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_CCU_DMA", NO_SEC, FORBID, NO_SEC), + +/* 120 */ +PERMISSION("CAMSYS_TSF", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_MD32_PMEM_24", NO_SEC, FORBID, NO_SEC), +PERMISSION("CAMSYS_OTHERS", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_CFG", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_ADL_CTRL", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREA_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREA_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREA_IMEM_256KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREA_CONTROL", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREA_DEBUG", NO_SEC, FORBID, NO_SEC), + +/* 130 */ +PERMISSION("VPUSYS_COREB_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREB_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREB_IMEM_256KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREB_CONTROL", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREB_DEBUG", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREC_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREC_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREC_IMEM_256KB", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREC_CONTROL", NO_SEC, FORBID, NO_SEC), +PERMISSION("VPUSYS_COREC_DEBUG", NO_SEC, FORBID, NO_SEC), + +/* 140 */ +PERMISSION("VPUSYS_OTHERS", NO_SEC, FORBID, NO_SEC) +}; + +void devapc_init(void); + +#endif /* DEVAPC_H */ + diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c new file mode 100644 index 0000000..56d2ce2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +int is_4GB(void) +{ + return 0; /* 8183 doesn't use 4GB */ +} + +/* + * emi_mpu_set_region_protection: protect a region. + * @start: start address of the region + * @end: end address of the region + * @region: EMI MPU region id + * @access_permission: EMI MPU access permission + * Return 0 for success, otherwise negative status code. + */ +int emi_mpu_set_region_protection( + unsigned long start, unsigned long end, + int region, + unsigned int access_permission) +{ + int ret = 0; + + if (end <= start) { + ERROR("[EMI][MTEE][MPU] Invalid address!.\n"); + return -1; + } + + if (is_4GB()) { + /* 4GB mode: emi_addr = phy_addr & 0xffff */ + start = EMI_PHY_OFFSET & 0xffff; + end = EMI_PHY_OFFSET & 0xffff; + } else { + /* non-4GB mode: emi_addr = phy_addr - MEM_OFFSET */ + start = start - EMI_PHY_OFFSET; + end = end - EMI_PHY_OFFSET; + } + + /*Address 64KB alignment*/ + start = start >> 16; + end = end >> 16; + + switch (region) { + case 0: + mmio_write_32(EMI_MPU_APC0, 0); + mmio_write_32(EMI_MPU_SA0, start); + mmio_write_32(EMI_MPU_EA0, end); + mmio_write_32(EMI_MPU_APC0, access_permission); + break; + + case 1: + mmio_write_32(EMI_MPU_APC1, 0); + mmio_write_32(EMI_MPU_SA1, start); + mmio_write_32(EMI_MPU_EA1, end); + mmio_write_32(EMI_MPU_APC1, access_permission); + break; + + case 2: + mmio_write_32(EMI_MPU_APC2, 0); + mmio_write_32(EMI_MPU_SA2, start); + mmio_write_32(EMI_MPU_EA2, end); + mmio_write_32(EMI_MPU_APC2, access_permission); + break; + + case 3: + mmio_write_32(EMI_MPU_APC3, 0); + mmio_write_32(EMI_MPU_SA3, start); + mmio_write_32(EMI_MPU_EA3, end); + mmio_write_32(EMI_MPU_APC3, access_permission); + break; + + case 4: + mmio_write_32(EMI_MPU_APC4, 0); + mmio_write_32(EMI_MPU_SA4, start); + mmio_write_32(EMI_MPU_EA4, end); + mmio_write_32(EMI_MPU_APC4, access_permission); + break; + + case 5: + mmio_write_32(EMI_MPU_APC5, 0); + mmio_write_32(EMI_MPU_SA5, start); + mmio_write_32(EMI_MPU_EA5, end); + mmio_write_32(EMI_MPU_APC5, access_permission); + break; + + case 6: + mmio_write_32(EMI_MPU_APC6, 0); + mmio_write_32(EMI_MPU_SA6, start); + mmio_write_32(EMI_MPU_EA6, end); + mmio_write_32(EMI_MPU_APC6, access_permission); + break; + + case 7: + mmio_write_32(EMI_MPU_APC7, 0); + mmio_write_32(EMI_MPU_SA7, start); + mmio_write_32(EMI_MPU_EA7, end); + mmio_write_32(EMI_MPU_APC7, access_permission); + break; + + default: + ret = -1; + break; + } + + return ret; +} + +void dump_emi_mpu_regions(void) +{ + unsigned int apc, sa, ea; + unsigned int apc_addr = EMI_MPU_APC0; + unsigned int sa_addr = EMI_MPU_SA0; + unsigned int ea_addr = EMI_MPU_EA0; + int i; + + for (i = 0; i < 8; ++i) { + apc = mmio_read_32(apc_addr + i * 4); + sa = mmio_read_32(sa_addr + i * 4); + ea = mmio_read_32(ea_addr + i * 4); + WARN("region %d:\n", i); + WARN("\tapc:0x%x, sa:0x%x, ea:0x%x\n", apc, sa, ea); + } +} + +void emi_mpu_init(void) +{ + /* Set permission */ + emi_mpu_set_region_protection(0x40000000UL, 0x4FFFFFFFUL, 0, + (FORBIDDEN << 3 | FORBIDDEN << 6)); + emi_mpu_set_region_protection(0x50000000UL, 0x528FFFFFUL, 1, + (FORBIDDEN << 6)); + emi_mpu_set_region_protection(0x52900000UL, 0x5FFFFFFFUL, 2, + (FORBIDDEN << 3 | FORBIDDEN << 6)); + emi_mpu_set_region_protection(0x60000000UL, 0xFFFFFFFFUL, 3, + (FORBIDDEN << 3 | FORBIDDEN << 6)); + emi_mpu_set_region_protection(0x100000000UL, 0x23FFFFFFFUL, 4, + (FORBIDDEN << 3 | FORBIDDEN << 6)); + dump_emi_mpu_regions(); +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..b67ea56 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __EMI_MPU_H +#define __EMI_MPU_H + +#include + +#define EMI_MPUP (EMI_BASE + 0x01D8) +#define EMI_MPUQ (EMI_BASE + 0x01E0) +#define EMI_MPUR (EMI_BASE + 0x01E8) +#define EMI_MPUS (EMI_BASE + 0x01F0) +#define EMI_MPUT (EMI_BASE + 0x01F8) +#define EMI_MPUY (EMI_BASE + 0x0220) +#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x0000) +#define EMI_MPUD0_ST (EMI_BASE + 0x0160) +#define EMI_MPUD1_ST (EMI_BASE + 0x0164) +#define EMI_MPUD2_ST (EMI_BASE + 0x0168) +#define EMI_MPUD3_ST (EMI_BASE + 0x016C) +#define EMI_MPUD0_ST2 (EMI_BASE + 0x0200) +#define EMI_MPUD1_ST2 (EMI_BASE + 0x0204) +#define EMI_MPUD2_ST2 (EMI_BASE + 0x0208) +#define EMI_MPUD3_ST2 (EMI_BASE + 0x020C) + +#define EMI_PHY_OFFSET (0x40000000UL) +#define EIGHT_DOMAIN + +#define NO_PROTECTION (0) +#define SEC_RW (1) +#define SEC_RW_NSEC_R (2) +#define SEC_RW_NSEC_W (3) +#define SEC_R_NSEC_R (4) +#define FORBIDDEN (5) +#define SEC_R_NSEC_RW (6) + +#define SECURE_OS_MPU_REGION_ID (0) +#define ATF_MPU_REGION_ID (1) + +#ifdef EIGHT_DOMAIN +#define SET_ACCESS_PERMISSON(d7, d6, d5, d4, d3, d2, d1, d0) \ + (((d7) << 21) | ((d6) << 18) | ((d5) << 15) | ((d4) << 12) \ + | ((d3) << 9) | ((d2) << 6) | ((d1) << 3) | (d0)) +#else +#define SET_ACCESS_PERMISSON(d3, d2, d1, d0) \ + (((d3) << 9) | ((d2) << 6) | ((d1) << 3) | (d0)) +#endif + +//#define EMI_MPU_BASE (0x1020E000U) + +#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100) +#define EMI_MPU_SA1 (EMI_MPU_BASE + 0x104) +#define EMI_MPU_SA2 (EMI_MPU_BASE + 0x108) +#define EMI_MPU_SA3 (EMI_MPU_BASE + 0x10C) +#define EMI_MPU_SA4 (EMI_MPU_BASE + 0x110) +#define EMI_MPU_SA5 (EMI_MPU_BASE + 0x114) +#define EMI_MPU_SA6 (EMI_MPU_BASE + 0x118) +#define EMI_MPU_SA7 (EMI_MPU_BASE + 0x11C) + +#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200) +#define EMI_MPU_EA1 (EMI_MPU_BASE + 0x204) +#define EMI_MPU_EA2 (EMI_MPU_BASE + 0x208) +#define EMI_MPU_EA3 (EMI_MPU_BASE + 0x20C) +#define EMI_MPU_EA4 (EMI_MPU_BASE + 0x210) +#define EMI_MPU_EA5 (EMI_MPU_BASE + 0x214) +#define EMI_MPU_EA6 (EMI_MPU_BASE + 0x218) +#define EMI_MPU_EA7 (EMI_MPU_BASE + 0x21C) + +#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300) +#define EMI_MPU_APC1 (EMI_MPU_BASE + 0x304) +#define EMI_MPU_APC2 (EMI_MPU_BASE + 0x308) +#define EMI_MPU_APC3 (EMI_MPU_BASE + 0x30C) +#define EMI_MPU_APC4 (EMI_MPU_BASE + 0x310) +#define EMI_MPU_APC5 (EMI_MPU_BASE + 0x314) +#define EMI_MPU_APC6 (EMI_MPU_BASE + 0x318) +#define EMI_MPU_APC7 (EMI_MPU_BASE + 0x31C) + +#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800) +#define EMI_MPU_CTRL_D1 (EMI_MPU_BASE + 0x804) +#define EMI_MPU_CTRL_D2 (EMI_MPU_BASE + 0x808) +#define EMI_MPU_CTRL_D3 (EMI_MPU_BASE + 0x80C) +#define EMI_MPU_CTRL_D4 (EMI_MPU_BASE + 0x810) +#define EMI_MPU_CTRL_D5 (EMI_MPU_BASE + 0x814) +#define EMI_MPU_CTRL_D6 (EMI_MPU_BASE + 0x818) +#define EMI_MPU_CTRL_D7 (EMI_MPU_BASE + 0x81C) + +#define EMI_MPU_MASK_D0 (EMI_MPU_BASE + 0x900) +#define EMI_MPU_MASK_D1 (EMI_MPU_BASE + 0x904) +#define EMI_MPU_MASK_D2 (EMI_MPU_BASE + 0x908) +#define EMI_MPU_MASK_D3 (EMI_MPU_BASE + 0x90C) +#define EMI_MPU_MASK_D4 (EMI_MPU_BASE + 0x910) +#define EMI_MPU_MASK_D5 (EMI_MPU_BASE + 0x914) +#define EMI_MPU_MASK_D6 (EMI_MPU_BASE + 0x918) +#define EMI_MPU_MASK_D7 (EMI_MPU_BASE + 0x91C) + +int emi_mpu_set_region_protection( + unsigned long start, unsigned long end, + int region, + unsigned int access_permission); + +void dump_emi_mpu_regions(void); +void emi_mpu_init(void); + +#endif /* __EMI_MPU_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c new file mode 100644 index 0000000..61aaeef --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + *Macro Definition + ******************************************************************************/ +#define GPIO_MODE_BITS 4 +#define MAX_GPIO_MODE_PER_REG 8 +#define MAX_GPIO_REG_BITS 32 +#define DIR_BASE (GPIO_BASE + 0x000) +#define DOUT_BASE (GPIO_BASE + 0x100) +#define DIN_BASE (GPIO_BASE + 0x200) +#define MODE_BASE (GPIO_BASE + 0x300) +#define SET 0x4 +#define CLR 0x8 +#define PULLEN_ADDR_OFFSET 0x060 +#define PULLSEL_ADDR_OFFSET 0x080 + +void mt_set_gpio_dir_chip(uint32_t pin, int dir) +{ + uint32_t pos, bit; + + assert(pin < MAX_GPIO_PIN); + assert(dir < GPIO_DIR_MAX); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + if (dir == GPIO_DIR_IN) + mmio_write_32(DIR_BASE + 0x10 * pos + CLR, 1U << bit); + else + mmio_write_32(DIR_BASE + 0x10 * pos + SET, 1U << bit); +} + +int mt_get_gpio_dir_chip(uint32_t pin) +{ + uint32_t pos, bit; + uint32_t reg; + + assert(pin < MAX_GPIO_PIN); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + reg = mmio_read_32(DIR_BASE + 0x10 * pos); + return (((reg & (1U << bit)) != 0) ? GPIO_DIR_OUT : GPIO_DIR_IN); +} + +void mt_set_gpio_out_chip(uint32_t pin, int output) +{ + uint32_t pos, bit; + + assert(pin < MAX_GPIO_PIN); + assert(output < GPIO_OUT_MAX); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + if (output == GPIO_OUT_ZERO) + mmio_write_32(DOUT_BASE + 0x10 * pos + CLR, 1U << bit); + else + mmio_write_32(DOUT_BASE + 0x10 * pos + SET, 1U << bit); +} + +int mt_get_gpio_out_chip(uint32_t pin) +{ + uint32_t pos, bit; + uint32_t reg; + + assert(pin < MAX_GPIO_PIN); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + reg = mmio_read_32(DOUT_BASE + 0x10 * pos); + return (((reg & (1U << bit)) != 0) ? 1 : 0); +} + +int mt_get_gpio_in_chip(uint32_t pin) +{ + uint32_t pos, bit; + uint32_t reg; + + assert(pin < MAX_GPIO_PIN); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + reg = mmio_read_32(DIN_BASE + 0x10 * pos); + return (((reg & (1U << bit)) != 0) ? 1 : 0); +} + +void mt_set_gpio_mode_chip(uint32_t pin, int mode) +{ + uint32_t pos, bit; + uint32_t data; + uint32_t mask; + + assert(pin < MAX_GPIO_PIN); + assert(mode < GPIO_MODE_MAX); + + mask = (1U << GPIO_MODE_BITS) - 1; + + mode = mode & mask; + pos = pin / MAX_GPIO_MODE_PER_REG; + bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS; + + data = mmio_read_32(MODE_BASE + 0x10 * pos); + data &= (~(mask << bit)); + data |= (mode << bit); + mmio_write_32(MODE_BASE + 0x10 * pos, data); +} + +int mt_get_gpio_mode_chip(uint32_t pin) +{ + uint32_t pos, bit; + uint32_t data; + uint32_t mask; + + assert(pin < MAX_GPIO_PIN); + + mask = (1U << GPIO_MODE_BITS) - 1; + + pos = pin / MAX_GPIO_MODE_PER_REG; + bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS; + + data = mmio_read_32(MODE_BASE + 0x10 * pos); + return (data >> bit) & mask; +} + +int32_t gpio_get_pull_iocfg(uint32_t pin) +{ + switch (pin) { + case 0 ... 10: + return IOCFG_5_BASE; + case 11 ... 12: + return IOCFG_0_BASE; + case 13 ... 28: + return IOCFG_1_BASE; + case 43 ... 49: + return IOCFG_2_BASE; + case 50 ... 60: + return IOCFG_3_BASE; + case 61 ... 88: + return IOCFG_4_BASE; + case 89 ... 90: + return IOCFG_5_BASE; + case 95 ... 106: + return IOCFG_5_BASE; + case 107 ... 121: + return IOCFG_6_BASE; + case 134 ... 160: + return IOCFG_0_BASE; + case 161 ... 166: + return IOCFG_1_BASE; + case 167 ... 176: + return IOCFG_3_BASE; + case 177 ... 179: + return IOCFG_5_BASE; + default: + return -1; + } +} + +int32_t gpio_get_pupd_iocfg(uint32_t pin) +{ + const int32_t offset = 0x0c0; + + switch (pin) { + case 29 ... 34: + return IOCFG_1_BASE + offset; + case 35 ... 42: + return IOCFG_2_BASE + offset; + case 91 ... 94: + return IOCFG_5_BASE + offset; + case 122 ... 133: + return IOCFG_7_BASE + offset; + default: + return -1; + } +} + +int gpio_get_pupd_offset(uint32_t pin) +{ + switch (pin) { + case 29 ... 34: + return (pin - 29) * 4 % 32; + case 35 ... 42: + return (pin - 35) * 4 % 32; + case 91 ... 94: + return (pin - 91) * 4 % 32; + case 122 ... 129: + return (pin - 122) * 4 % 32; + case 130 ... 133: + return (pin - 130) * 4 % 32; + default: + return -1; + } +} + +void mt_set_gpio_pull_enable_chip(uint32_t pin, int en) +{ + int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET; + int pupd_addr = gpio_get_pupd_iocfg(pin); + int pupd_offset = gpio_get_pupd_offset(pin); + + assert(pin < MAX_GPIO_PIN); + + assert(!((PULL_offset[pin].offset == (int8_t)-1) && + (pupd_offset == (int8_t)-1))); + + if (en == GPIO_PULL_DISABLE) { + if (PULL_offset[pin].offset == (int8_t)-1) + mmio_clrbits_32(pupd_addr, 3U << pupd_offset); + else + mmio_clrbits_32(pullen_addr, + 1U << PULL_offset[pin].offset); + } else if (en == GPIO_PULL_ENABLE) { + if (PULL_offset[pin].offset == (int8_t)-1) { + /* For PUPD+R0+R1 Type, mt_set_gpio_pull_enable + * does not know + * which one between PU and PD shall be enabled. + * Use R0 to guarantee at one resistor is set when lk + * apply default setting + */ + mmio_setbits_32(pupd_addr, 1U << pupd_offset); + mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1)); + } else { + /* For PULLEN + PULLSEL Type */ + mmio_setbits_32(pullen_addr, + 1U << PULL_offset[pin].offset); + } + } else if (en == GPIO_PULL_ENABLE_R0) { + assert(!(pupd_offset == (int8_t)-1)); + mmio_setbits_32(pupd_addr, 1U << pupd_offset); + mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1)); + } else if (en == GPIO_PULL_ENABLE_R1) { + assert(!(pupd_offset == (int8_t)-1)); + + mmio_clrbits_32(pupd_addr, 1U << pupd_offset); + mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 1)); + } else if (en == GPIO_PULL_ENABLE_R0R1) { + assert(!(pupd_offset == (int8_t)-1)); + mmio_setbits_32(pupd_addr, 3U << pupd_offset); + } +} + +int mt_get_gpio_pull_enable_chip(uint32_t pin) +{ + uint32_t reg; + + int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET; + int pupd_addr = gpio_get_pupd_iocfg(pin); + int pupd_offset = gpio_get_pupd_offset(pin); + + assert(pin < MAX_GPIO_PIN); + + assert(!((PULL_offset[pin].offset == (int8_t)-1) && + (pupd_offset == (int8_t)-1))); + + if (PULL_offset[pin].offset == (int8_t)-1) { + reg = mmio_read_32(pupd_addr); + return ((reg & (3U << pupd_offset)) ? 1 : 0); + } else if (pupd_offset == (int8_t)-1) { + reg = mmio_read_32(pullen_addr); + return ((reg & (1U << PULL_offset[pin].offset)) ? 1 : 0); + } + + return -ERINVAL; +} + +void mt_set_gpio_pull_select_chip(uint32_t pin, int sel) +{ + int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET; + int pupd_addr = gpio_get_pupd_iocfg(pin); + int pupd_offset = gpio_get_pupd_offset(pin); + + assert(pin < MAX_GPIO_PIN); + + assert(!((PULL_offset[pin].offset == (int8_t) -1) && + (pupd_offset == (int8_t)-1))); + + if (sel == GPIO_PULL_NONE) { + /* Regard No PULL as PULL disable + pull down */ + mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_DISABLE); + if (PULL_offset[pin].offset == (int8_t)-1) + mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2)); + else + mmio_clrbits_32(pullsel_addr, + 1U << PULL_offset[pin].offset); + } else if (sel == GPIO_PULL_UP) { + mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE); + if (PULL_offset[pin].offset == (int8_t)-1) + mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 2)); + else + mmio_setbits_32(pullsel_addr, + 1U << PULL_offset[pin].offset); + } else if (sel == GPIO_PULL_DOWN) { + mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE); + if (PULL_offset[pin].offset == -1) + mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2)); + else + mmio_clrbits_32(pullsel_addr, + 1U << PULL_offset[pin].offset); + } +} + +/* get pull-up or pull-down, regardless of resistor value */ +int mt_get_gpio_pull_select_chip(uint32_t pin) +{ + uint32_t reg; + + int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET; + int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET; + int pupd_addr = gpio_get_pupd_iocfg(pin); + int pupd_offset = gpio_get_pupd_offset(pin); + + assert(pin < MAX_GPIO_PIN); + + assert(!((PULL_offset[pin].offset == (int8_t)-1) && + (pupd_offset == (int8_t)-1))); + + if (PULL_offset[pin].offset == (int8_t)-1) { + reg = mmio_read_32(pupd_addr); + if (reg & (3U << pupd_offset)) { + reg = mmio_read_32(pupd_addr); + /* Reg value: 0 for PU, 1 for PD --> + * reverse return value */ + return ((reg & (1U << (pupd_offset + 2))) ? + GPIO_PULL_DOWN : GPIO_PULL_UP); + } else { + return GPIO_PULL_NONE; + } + } else if (pupd_offset == (int8_t)-1) { + reg = mmio_read_32(pullen_addr); + if ((reg & (1U << PULL_offset[pin].offset))) { + reg = mmio_read_32(pullsel_addr); + return ((reg & (1U << PULL_offset[pin].offset)) ? + GPIO_PULL_UP : GPIO_PULL_DOWN); + } else { + return GPIO_PULL_NONE; + } + } + + return -ERINVAL; +} + +void mt_set_gpio_dir(int gpio, int direction) +{ + mt_set_gpio_dir_chip((uint32_t)gpio, direction); +} + +int mt_get_gpio_dir(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_dir_chip(pin); +} + +void mt_set_gpio_pull(int gpio, int pull) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + mt_set_gpio_pull_select_chip(pin, pull); +} + +int mt_get_gpio_pull(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_pull_select_chip(pin); +} + +void mt_set_gpio_out(int gpio, int value) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + mt_set_gpio_out_chip(pin, value); +} + +int mt_get_gpio_out(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_out_chip(pin); +} + +int mt_get_gpio_in(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_in_chip(pin); +} + +void mt_set_gpio_mode(int gpio, int mode) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + mt_set_gpio_mode_chip(pin, mode); +} + +int mt_get_gpio_mode(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_mode_chip(pin); +} + +const gpio_ops_t mtgpio_ops = { + .get_direction = mt_get_gpio_dir, + .set_direction = mt_set_gpio_dir, + .get_value = mt_get_gpio_in, + .set_value = mt_set_gpio_out, + .set_pull = mt_set_gpio_pull, + .get_pull = mt_get_gpio_pull, +}; diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h new file mode 100644 index 0000000..9461c54 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_H +#define MT_GPIO_H + +#include +#include + +/* Error Code No. */ +#define RSUCCESS 0 +#define ERACCESS 1 +#define ERINVAL 2 +#define ERWRAPPER 3 +#define MAX_GPIO_PIN MT_GPIO_BASE_MAX + +/* Enumeration for GPIO pin */ +typedef enum GPIO_PIN { + GPIO_UNSUPPORTED = -1, + + GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, + GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15, + GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, + GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31, + GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39, + GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47, + GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55, + GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63, + GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71, + GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79, + GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87, + GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95, + GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103, + GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111, + GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119, + GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127, + GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135, + GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143, + GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151, + GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159, + GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167, + GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175, + GPIO176, GPIO177, GPIO178, GPIO179, + MT_GPIO_BASE_MAX +} GPIO_PIN; + +/* GPIO MODE CONTROL VALUE*/ +typedef enum { + GPIO_MODE_UNSUPPORTED = -1, + GPIO_MODE_GPIO = 0, + GPIO_MODE_00 = 0, + GPIO_MODE_01, + GPIO_MODE_02, + GPIO_MODE_03, + GPIO_MODE_04, + GPIO_MODE_05, + GPIO_MODE_06, + GPIO_MODE_07, + + GPIO_MODE_MAX, + GPIO_MODE_DEFAULT = GPIO_MODE_00, +} GPIO_MODE; + +/* GPIO DIRECTION */ +typedef enum { + GPIO_DIR_UNSUPPORTED = -1, + GPIO_DIR_OUT = 0, + GPIO_DIR_IN = 1, + GPIO_DIR_MAX, + GPIO_DIR_DEFAULT = GPIO_DIR_IN, +} GPIO_DIR; + +/* GPIO PULL ENABLE*/ +typedef enum { + GPIO_PULL_EN_UNSUPPORTED = -1, + GPIO_PULL_DISABLE = 0, + GPIO_PULL_ENABLE = 1, + GPIO_PULL_ENABLE_R0 = 2, + GPIO_PULL_ENABLE_R1 = 3, + GPIO_PULL_ENABLE_R0R1 = 4, + + GPIO_PULL_EN_MAX, + GPIO_PULL_EN_DEFAULT = GPIO_PULL_ENABLE, +} GPIO_PULL_EN; + +/* GPIO PULL-UP/PULL-DOWN*/ +typedef enum { + GPIO_PULL_UNSUPPORTED = -1, + GPIO_PULL_NONE = 0, + GPIO_PULL_UP = 1, + GPIO_PULL_DOWN = 2, + GPIO_PULL_MAX, + GPIO_PULL_DEFAULT = GPIO_PULL_DOWN +} GPIO_PULL; + +/* GPIO OUTPUT */ +typedef enum { + GPIO_OUT_UNSUPPORTED = -1, + GPIO_OUT_ZERO = 0, + GPIO_OUT_ONE = 1, + + GPIO_OUT_MAX, + GPIO_OUT_DEFAULT = GPIO_OUT_ZERO, + GPIO_DATA_OUT_DEFAULT = GPIO_OUT_ZERO, /*compatible with DCT*/ +} GPIO_OUT; + +/* GPIO INPUT */ +typedef enum { + GPIO_IN_UNSUPPORTED = -1, + GPIO_IN_ZERO = 0, + GPIO_IN_ONE = 1, + + GPIO_IN_MAX, +} GPIO_IN; + +typedef struct { + uint32_t val; + uint32_t set; + uint32_t rst; + uint32_t _align1; +} VAL_REGS; + +typedef struct { + VAL_REGS dir[6]; /*0x0000 ~ 0x005F: 96 bytes */ + uint8_t rsv00[160]; /*0x0060 ~ 0x00FF: 160 bytes */ + VAL_REGS dout[6]; /*0x0100 ~ 0x015F: 96 bytes */ + uint8_t rsv01[160]; /*0x0160 ~ 0x01FF: 160 bytes */ + VAL_REGS din[6]; /*0x0200 ~ 0x025F: 96 bytes */ + uint8_t rsv02[160]; /*0x0260 ~ 0x02FF: 160 bytes */ + VAL_REGS mode[23]; /*0x0300 ~ 0x046F: 368 bytes */ +} GPIO_REGS; + +/* GPIO Driver interface */ +/*direction*/ +void mt_set_gpio_dir(int gpio, int direction); +int mt_get_gpio_dir(int gpio); + +/*pull select*/ +void mt_set_gpio_pull(int gpio, int pull); +int mt_get_gpio_pull(int gpio); + +/*input/output*/ +void mt_set_gpio_out(int gpio, int value); +int mt_get_gpio_out(int gpio); +int mt_get_gpio_in(int gpio); + +/*mode control*/ +void mt_set_gpio_mode(int gpio, int mode); +int mt_get_gpio_mode(int gpio); + +#endif /* MT_GPIO_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h new file mode 100644 index 0000000..4e1fd2b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_CFG_H +#define MT_GPIO_CFG_H + +#include +#include + +#define IOCFG_0_BASE 0x11F20000 +#define IOCFG_1_BASE 0x11E80000 +#define IOCFG_2_BASE 0x11E70000 +#define IOCFG_3_BASE 0x11E90000 +#define IOCFG_4_BASE 0x11D30000 +#define IOCFG_5_BASE 0x11D20000 +#define IOCFG_6_BASE 0x11C50000 +#define IOCFG_7_BASE 0x11F30000 + +typedef struct { + int8_t offset; +} PIN_offset; + +PIN_offset PULL_offset[] = { + /* 0 */ {6}, + /* 1 */ {7}, + /* 2 */ {8}, + /* 3 */ {9}, + /* 4 */ {11}, + /* 5 */ {12}, + /* 6 */ {13}, + /* 7 */ {14}, + /* 8 */ {0}, + /* 9 */ {26}, + /* 10 */ {27}, + /* 11 */ {10}, + /* 12 */ {17}, + /* 13 */ {6}, + /* 14 */ {7}, + /* 15 */ {8}, + /* 16 */ {9}, + /* 17 */ {10}, + /* 18 */ {11}, + /* 19 */ {12}, + /* 20 */ {13}, + /* 21 */ {14}, + /* 22 */ {15}, + /* 23 */ {16}, + /* 24 */ {17}, + /* 25 */ {18}, + /* 26 */ {19}, + /* 27 */ {20}, + /* 28 */ {21}, + /* 29 */ {-1}, + /* 30 */ {-1}, + /* 31 */ {-1}, + /* 32 */ {-1}, + /* 33 */ {-1}, + /* 34 */ {-1}, + /* 35 */ {-1}, + /* 36 */ {-1}, + /* 37 */ {-1}, + /* 38 */ {-1}, + /* 39 */ {-1}, + /* 40 */ {-1}, + /* 41 */ {-1}, + /* 42 */ {-1}, + /* 43 */ {8}, + /* 44 */ {9}, + /* 45 */ {10}, + /* 46 */ {11}, + /* 47 */ {12}, + /* 48 */ {13}, + /* 49 */ {14}, + /* 50 */ {0}, + /* 51 */ {1}, + /* 52 */ {2}, + /* 53 */ {3}, + /* 54 */ {4}, + /* 55 */ {5}, + /* 56 */ {6}, + /* 57 */ {7}, + /* 58 */ {8}, + /* 59 */ {9}, + /* 60 */ {10}, + /* 61 */ {0}, + /* 62 */ {1}, + /* 63 */ {2}, + /* 64 */ {3}, + /* 65 */ {4}, + /* 66 */ {5}, + /* 67 */ {6}, + /* 68 */ {7}, + /* 69 */ {8}, + /* 70 */ {9}, + /* 71 */ {10}, + /* 72 */ {11}, + /* 73 */ {12}, + /* 74 */ {13}, + /* 75 */ {14}, + /* 76 */ {15}, + /* 77 */ {16}, + /* 78 */ {17}, + /* 79 */ {18}, + /* 80 */ {19}, + /* 81 */ {20}, + /* 82 */ {21}, + /* 83 */ {22}, + /* 84 */ {23}, + /* 85 */ {24}, + /* 86 */ {25}, + /* 87 */ {26}, + /* 88 */ {27}, + /* 89 */ {24}, + /* 90 */ {1}, + /* 91 */ {-1}, + /* 92 */ {-1}, + /* 93 */ {-1}, + /* 94 */ {-1}, + /* 95 */ {15}, + /* 96 */ {17}, + /* 97 */ {18}, + /* 98 */ {19}, + /* 99 */ {20}, + /* 100 */ {21}, + /* 101 */ {22}, + /* 102 */ {23}, + /* 103 */ {28}, + /* 104 */ {29}, + /* 105 */ {30}, + /* 106 */ {31}, + /* 107 */ {0}, + /* 108 */ {1}, + /* 109 */ {2}, + /* 110 */ {3}, + /* 111 */ {4}, + /* 112 */ {5}, + /* 113 */ {6}, + /* 114 */ {7}, + /* 115 */ {8}, + /* 116 */ {9}, + /* 117 */ {10}, + /* 118 */ {11}, + /* 119 */ {12}, + /* 120 */ {13}, + /* 121 */ {14}, + /* 122 */ {-1}, + /* 123 */ {-1}, + /* 124 */ {-1}, + /* 125 */ {-1}, + /* 126 */ {-1}, + /* 127 */ {-1}, + /* 128 */ {-1}, + /* 129 */ {-1}, + /* 130 */ {-1}, + /* 131 */ {-1}, + /* 132 */ {-1}, + /* 133 */ {-1}, + /* 134 */ {0}, + /* 135 */ {1}, + /* 136 */ {2}, + /* 137 */ {3}, + /* 138 */ {4}, + /* 139 */ {5}, + /* 140 */ {6}, + /* 141 */ {7}, + /* 142 */ {8}, + /* 143 */ {9}, + /* 144 */ {11}, + /* 145 */ {12}, + /* 146 */ {13}, + /* 147 */ {14}, + /* 148 */ {15}, + /* 149 */ {16}, + /* 150 */ {18}, + /* 151 */ {19}, + /* 152 */ {20}, + /* 153 */ {21}, + /* 154 */ {22}, + /* 155 */ {23}, + /* 156 */ {24}, + /* 157 */ {25}, + /* 158 */ {26}, + /* 159 */ {27}, + /* 160 */ {28}, + /* 161 */ {0}, + /* 162 */ {1}, + /* 163 */ {2}, + /* 164 */ {3}, + /* 165 */ {4}, + /* 166 */ {5}, + /* 167 */ {11}, + /* 168 */ {12}, + /* 169 */ {13}, + /* 170 */ {14}, + /* 171 */ {15}, + /* 172 */ {16}, + /* 173 */ {17}, + /* 174 */ {18}, + /* 175 */ {19}, + /* 176 */ {20}, + /* 177 */ {10}, + /* 178 */ {16}, + /* 179 */ {25} +}; +#endif /* MT_GPIO_CFG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c new file mode 100644 index 0000000..29eebcb --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static inline uint32_t mcdi_mbox_read(uint32_t id) +{ + return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2)); +} + +static inline void mcdi_mbox_write(uint32_t id, uint32_t val) +{ + mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val); +} + +void sspm_set_bootaddr(uint32_t bootaddr) +{ + mcdi_mbox_write(MCDI_MBOX_BOOTADDR, bootaddr); +} + +void sspm_cluster_pwr_off_notify(uint32_t cluster) +{ + mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 1); +} + +void sspm_cluster_pwr_on_notify(uint32_t cluster) +{ + mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 0); +} + +void sspm_standbywfi_irq_enable(uint32_t cpu_idx) +{ + mmio_write_32(SSPM_CFGREG_ACAO_INT_SET, STANDBYWFI_EN(cpu_idx)); +} + +uint32_t mcdi_avail_cpu_mask_read(void) +{ + return mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK); +} + +uint32_t mcdi_avail_cpu_mask_write(uint32_t mask) +{ + mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, mask); + + return mask; +} + +uint32_t mcdi_avail_cpu_mask_set(uint32_t mask) +{ + uint32_t m; + + m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK); + m |= mask; + mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m); + + return m; +} + +uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask) +{ + uint32_t m; + + m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK); + m &= ~mask; + mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m); + + return m; +} + +uint32_t mcdi_cpu_cluster_pwr_stat_read(void) +{ + return mcdi_mbox_read(MCDI_MBOX_CPU_CLUSTER_PWR_STAT); +} + +#define PAUSE_BIT 1 +#define CLUSTER_OFF_OFS 20 +#define CPU_OFF_OFS 24 +#define CLUSTER_ON_OFS 4 +#define CPU_ON_OFS 8 + +static uint32_t target_mask(int cluster, int cpu_idx, bool on) +{ + uint32_t t = 0; + + if (on) { + if (cluster >= 0) + t |= BIT(cluster + CLUSTER_ON_OFS); + + if (cpu_idx >= 0) + t |= BIT(cpu_idx + CPU_ON_OFS); + } else { + if (cluster >= 0) + t |= BIT(cluster + CLUSTER_OFF_OFS); + + if (cpu_idx >= 0) + t |= BIT(cpu_idx + CPU_OFF_OFS); + } + + return t; +} + +void mcdi_pause_clr(int cluster, int cpu_idx, bool on) +{ + uint32_t tgt = target_mask(cluster, cpu_idx, on); + uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION); + + m &= ~tgt; + mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m); +} + +void mcdi_pause_set(int cluster, int cpu_idx, bool on) +{ + uint32_t tgt = target_mask(cluster, cpu_idx, on); + uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION); + uint32_t tgtn = target_mask(-1, cpu_idx, !on); + + /* request on and off at the same time to ensure it can be paused */ + m |= tgt | tgtn; + mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m); + + /* wait pause_ack */ + while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK)) + ; + + /* clear non-requested operation */ + m &= ~tgtn; + mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m); +} + +void mcdi_pause(void) +{ + uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT); + + mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m); + + /* wait pause_ack */ + while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK)) + ; +} + +void mcdi_unpause(void) +{ + uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT); + + mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m); +} + +void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on) +{ + uint32_t tgt = target_mask(cluster, cpu_idx, on); + uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK); + + /* wait until ack */ + while (!(ack & tgt)) + ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK); +} + +void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on) +{ + uint32_t tgt = target_mask(cluster, cpu_idx, on); + uint32_t tgt_cpu = target_mask(-1, cpu_idx, on); + uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD); + uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK); + + if (!(cmd & tgt)) + return; + + /* wait until ack */ + while (!(ack & tgt_cpu)) + ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK); + + cmd &= ~tgt; + mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd); +} + +void mcdi_hotplug_set(int cluster, int cpu_idx, bool on) +{ + uint32_t tgt = target_mask(cluster, cpu_idx, on); + uint32_t tgt_cpu = target_mask(-1, cpu_idx, on); + uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD); + uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK); + + if ((cmd & tgt) == tgt) + return; + + /* wait until ack clear */ + while (ack & tgt_cpu) + ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK); + + cmd |= tgt; + mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd); +} + +bool check_mcdi_ctl_stat(void) +{ + uint32_t clk_regs[] = {0x100010ac, 0x100010c8}; + uint32_t clk_mask[] = {0x00028000, 0x00000018}; + uint32_t tgt = target_mask(0, 0, true); + uint32_t m; + int i; + + /* check clk status */ + for (i = 0; i < ARRAY_SIZE(clk_regs); i++) { + if (mmio_read_32(clk_regs[i]) & clk_mask[i]) { + WARN("mcdi: clk check fail.\n"); + return false; + } + } + + /* check mcdi cmd handling */ + m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT); + mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m); + + i = 500; + while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK) && --i > 0) + udelay(10); + + m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT); + mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m); + + if (i == 0) { + WARN("mcdi: pause_action fail.\n"); + return false; + } + + /* check mcdi cmd handling */ + if (mcdi_mbox_read(MCDI_MBOX_HP_CMD) || + mcdi_mbox_read(MCDI_MBOX_HP_ACK)) { + WARN("mcdi: hp_cmd fail.\n"); + return false; + } + + mcdi_mbox_write(MCDI_MBOX_HP_CMD, tgt); + + i = 500; + while ((mcdi_mbox_read(MCDI_MBOX_HP_ACK) & tgt) != tgt && --i > 0) + udelay(10); + + mcdi_mbox_write(MCDI_MBOX_HP_CMD, 0); + + if (i == 0) { + WARN("mcdi: hp_ack fail.\n"); + return false; + } + + return true; +} + +void mcdi_init(void) +{ + mcdi_avail_cpu_mask_write(0x01); /* cpu0 default on */ +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h new file mode 100644 index 0000000..9a40df1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MTK_MCDI_H__ +#define __MTK_MCDI_H__ + +#include + +void sspm_set_bootaddr(uint32_t bootaddr); +void sspm_standbywfi_irq_enable(uint32_t cpu_idx); +void sspm_cluster_pwr_off_notify(uint32_t cluster); +void sspm_cluster_pwr_on_notify(uint32_t cluster); + +uint32_t mcdi_avail_cpu_mask_read(void); +uint32_t mcdi_avail_cpu_mask_write(uint32_t mask); +uint32_t mcdi_avail_cpu_mask_set(uint32_t mask); +uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask); +uint32_t mcdi_cpu_cluster_pwr_stat_read(void); + +void mcdi_pause(void); +void mcdi_unpause(void); +void mcdi_pause_set(int cluster, int cpu_idx, bool on); +void mcdi_pause_clr(int cluster, int cpu_idx, bool on); +void mcdi_hotplug_set(int cluster, int cpu_idx, bool on); +void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on); +void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on); + +bool check_mcdi_ctl_stat(void); +void mcdi_init(void); + +#endif /* __MTK_MCDI_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c new file mode 100644 index 0000000..cbe7f0a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_CLUSTERS 5 + +static unsigned long cci_base_addr; +static unsigned int cci_cluster_ix_to_iface[MAX_CLUSTERS]; + +void mcsi_init(unsigned long cci_base, + unsigned int num_cci_masters) +{ + int i; + + assert(cci_base); + assert(num_cci_masters < MAX_CLUSTERS); + + cci_base_addr = cci_base; + + for (i = 0; i < num_cci_masters; i++) + cci_cluster_ix_to_iface[i] = SLAVE_IFACE_OFFSET(i); +} + +void mcsi_cache_flush(void) +{ + /* timeout is 10ms */ + int timeout = 10000; + + /* to make flush by SF safe, need to disable BIU DCM */ + mmio_clrbits_32(CCI_CLK_CTRL, 1 << 8); + mmio_write_32(cci_base_addr + FLUSH_SF, 0x1); + + for (; timeout; timeout--, udelay(1)) { + if ((mmio_read_32(cci_base_addr + FLUSH_SF) & 0x1) == 0x0) + break; + } + + if (!timeout) { + INFO("SF lush timeout\n"); + return; + } + + /* enable BIU DCM as it was */ + mmio_setbits_32(CCI_CLK_CTRL, 1 << 8); +} + +static inline unsigned long get_slave_iface_base(unsigned long mpidr) +{ + /* + * We assume the TF topology code allocates affinity instances + * consecutively from zero. + * It is a programming error if this is called without initializing + * the slave interface to use for this cluster. + */ + unsigned int cluster_id = + (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + + assert(cluster_id < MAX_CLUSTERS); + assert(cci_cluster_ix_to_iface[cluster_id] != 0); + + return cci_base_addr + cci_cluster_ix_to_iface[cluster_id]; +} + +void cci_enable_cluster_coherency(unsigned long mpidr) +{ + unsigned long slave_base; + unsigned int support_ability; + unsigned int config = 0; + unsigned int pending = 0; + + assert(cci_base_addr); + slave_base = get_slave_iface_base(mpidr); + support_ability = mmio_read_32(slave_base); + + pending = (mmio_read_32( + cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING; + while (pending) { + pending = (mmio_read_32( + cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING; + } + + if (support_ability & SNP_SUPPORT) + config |= SNOOP_EN_BIT; + if (support_ability & DVM_SUPPORT) + config |= DVM_EN_BIT; + + mmio_write_32(slave_base, support_ability | config); + + /* Wait for the dust to settle down */ + while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) + ; +} + +#if ERRATA_MCSIB_SW +#pragma weak mcsib_sw_workaround_main +#endif + +void cci_disable_cluster_coherency(unsigned long mpidr) +{ + unsigned long slave_base; + unsigned int config = 0; + + assert(cci_base_addr); + slave_base = get_slave_iface_base(mpidr); + + while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) + ; + + config = mmio_read_32(slave_base); + config &= ~(DVM_EN_BIT | SNOOP_EN_BIT); + + /* Disable Snoops and DVM messages */ + mmio_write_32(slave_base, config); + +#if ERRATA_MCSIB_SW + mcsib_sw_workaround_main(); +#endif + + /* Wait for the dust to settle down */ + while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) + ; +} + +void cci_secure_switch(unsigned int status) +{ + unsigned int config; + + config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG); + if (status == NS_ACC) + config |= SECURE_ACC_EN; + else + config &= ~SECURE_ACC_EN; + mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config); +} + +void cci_pmu_secure_switch(unsigned int status) +{ + unsigned int config; + + config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG); + if (status == NS_ACC) + config |= PMU_SECURE_ACC_EN; + else + config &= ~PMU_SECURE_ACC_EN; + mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config); +} + +void cci_init_sf(void) +{ + while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) + ; + /* init sf1 */ + mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF1_INIT); + while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF1_INIT) + ; + while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF1_INIT_DONE)) + ; + /* init sf2 */ + mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF2_INIT); + while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF2_INIT) + ; + while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF2_INIT_DONE)) + ; +} + +void cci_interrupt_en(void) +{ + mmio_setbits_32(cci_base_addr + CENTRAL_CTRL_REG, INT_EN); +} + +unsigned long cci_reg_access(unsigned int op, unsigned long offset, + unsigned long val) +{ + unsigned long ret = 0; + + if ((cci_base_addr == 0) || (offset > MSCI_MEMORY_SZ)) + panic(); + + switch (op) { + case MCSI_REG_ACCESS_READ: + ret = mmio_read_32(cci_base_addr + offset); + break; + case MCSI_REG_ACCESS_WRITE: + mmio_write_32(cci_base_addr + offset, val); + dsb(); + break; + case MCSI_REG_ACCESS_SET_BITMASK: + mmio_setbits_32(cci_base_addr + offset, val); + dsb(); + break; + case MCSI_REG_ACCESS_CLEAR_BITMASK: + mmio_clrbits_32(cci_base_addr + offset, val); + dsb(); + break; + default: + break; + } + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h new file mode 100644 index 0000000..863e7da --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCSI_H +#define MCSI_H + +#define SLAVE_IFACE7_OFFSET 0x1700 +#define SLAVE_IFACE6_OFFSET 0x1600 +#define SLAVE_IFACE5_OFFSET 0x1500 +#define SLAVE_IFACE4_OFFSET 0x1400 +#define SLAVE_IFACE3_OFFSET 0x1300 +#define SLAVE_IFACE2_OFFSET 0x1200 +#define SLAVE_IFACE1_OFFSET 0x1100 +#define SLAVE_IFACE0_OFFSET 0x1000 +#define SLAVE_IFACE_OFFSET(index) (SLAVE_IFACE0_OFFSET + \ + (0x100 * (index))) +/* Control and ID register offsets */ +#define CENTRAL_CTRL_REG 0x0 +#define ERR_FLAG_REG 0x4 +#define SF_INIT_REG 0x10 +#define SF_CTRL_REG 0x14 +#define DCM_CTRL_REG 0x18 +#define ERR_FLAG2_REG 0x20 +#define SNP_PENDING_REG 0x28 +#define ACP_PENDING_REG 0x2c +#define FLUSH_SF 0x500 +#define SYS_CCE_CTRL 0x2000 +#define MST1_CTRL 0x2100 +#define MTS2_CTRL 0x2200 +#define XBAR_ARAW_ARB 0x3000 +#define XBAR_R_ARB 0x3004 + +/* Slave interface register offsets */ +#define SNOOP_CTRL_REG 0x0 +#define QOS_CTRL_REG 0x4 +#define QOS_OVERRIDE_REG 0x8 +#define QOS_TARGET_REG 0xc +#define BD_CTRL_REG 0x40 + +/* Snoop Control register bit definitions */ +#define DVM_SUPPORT (1U << 31) +#define SNP_SUPPORT (1 << 30) +#define SHAREABLE_OVWRT (1 << 2) +#define DVM_EN_BIT (1 << 1) +#define SNOOP_EN_BIT (1 << 0) +#define SF2_INIT_DONE (1 << 17) +#define SF1_INIT_DONE (1 << 16) +#define TRIG_SF2_INIT (1 << 1) +#define TRIG_SF1_INIT (1 << 0) + +/* Status register bit definitions */ +#define SNP_PENDING 31 + +/* Status bit */ +#define NS_ACC 1 +#define S_ACC 0 + +/* Central control register bit definitions */ +#define PMU_SECURE_ACC_EN (1 << 4) +#define INT_EN (1 << 3) +#define SECURE_ACC_EN (1 << 2) +#define DVM_DIS (1 << 1) +#define SNOOP_DIS (1 << 0) + +#define MSCI_MEMORY_SZ (0x10000) + +#define MCSI_REG_ACCESS_READ (0x0) +#define MCSI_REG_ACCESS_WRITE (0x1) +#define MCSI_REG_ACCESS_SET_BITMASK (0x2) +#define MCSI_REG_ACCESS_CLEAR_BITMASK (0x3) + +#define NR_MAX_SLV (7) + +/* ICCS */ +#define CACHE_INSTR_EN (1 << 2) +#define IDLE_CACHE (1 << 3) +#define USE_SHARED_CACHE (1 << 4) +#define CACHE_SHARED_PRE_EN (1 << 5) +#define CACHE_SHARED_POST_EN (1 << 6) + +#define ACP_PENDING_MASK (0x1007f) + +#define CCI_CLK_CTRL (MCUCFG_BASE + 0x660) + +#ifndef __ASSEMBLER__ + +#include +#include + +/* Function declarations */ + +/* + * The MCSI driver must be initialized with the base address of the + * MCSI device in the platform memory map, and the cluster indices for + * the MCSI slave interfaces 3 and 4 respectively. These are the fully + * coherent ACE slave interfaces of MCSI. + * The cluster indices must either be 0 or 1, corresponding to the level 1 + * affinity instance of the mpidr representing the cluster. A negative cluster + * index indicates that no cluster is present on that slave interface. + */ +void mcsi_init(unsigned long cci_base, + unsigned int num_cci_masters); +void mcsi_cache_flush(void); + +void cci_enable_cluster_coherency(unsigned long mpidr); +void cci_disable_cluster_coherency(unsigned long mpidr); + +void cci_secure_switch(unsigned int ns); +void cci_init_sf(void); +unsigned long cci_reg_access(unsigned int op, unsigned long offset, unsigned long val); + +#endif /* __ASSEMBLER__ */ +#endif /* MCSI_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c new file mode 100644 index 0000000..b0f898e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void bcpu_enable(uint32_t en) +{ + pwrap_write(PMIC_VPROC11_OP_EN, 0x1); + if (en) + pwrap_write(PMIC_VPROC11_CON0, 1); + else + pwrap_write(PMIC_VPROC11_CON0, 0); +} + +void bcpu_sram_enable(uint32_t en) +{ + pwrap_write(PMIC_VSRAM_PROC11_OP_EN, 0x1); + if (en) + pwrap_write(PMIC_VSRAM_PROC11_CON0, 1); + else + pwrap_write(PMIC_VSRAM_PROC11_CON0, 0); +} + +void wk_pmic_enable_sdn_delay(void) +{ + uint32_t con; + + pwrap_write(PMIC_TMA_KEY, 0x9CA7); + pwrap_read(PMIC_PSEQ_ELR11, &con); + con &= ~PMIC_RG_SDN_DLY_ENB; + pwrap_write(PMIC_PSEQ_ELR11, con); + pwrap_write(PMIC_TMA_KEY, 0); +} + +void pmic_power_off(void) +{ + pwrap_write(PMIC_PWRHOLD, 0x0); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h new file mode 100644 index 0000000..f19f9f6 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_H +#define PMIC_H + +enum { + PMIC_TMA_KEY = 0x03a8, + PMIC_PWRHOLD = 0x0a08, + PMIC_PSEQ_ELR11 = 0x0a62, + PMIC_VPROC11_CON0 = 0x1388, + PMIC_VPROC11_OP_EN = 0x1390, + PMIC_VSRAM_PROC11_CON0 = 0x1b46, + PMIC_VSRAM_PROC11_OP_EN = 0x1b4e +}; + +enum { + PMIC_RG_SDN_DLY_ENB = 1U << 10 +}; + +/* external API */ +void bcpu_enable(uint32_t en); +void bcpu_sram_enable(uint32_t en); +void wk_pmic_enable_sdn_delay(void); +void pmic_power_off(void); + +#endif /* PMIC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..679c5e4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include +#include + +/* external API */ +int32_t pwrap_read(uint32_t adr, uint32_t *rdata); +int32_t pwrap_write(uint32_t adr, uint32_t wdata); + +static struct mt8183_pmic_wrap_regs *const mtk_pwrap = + (void *)PMIC_WRAP_BASE; + +/* timeout setting */ +enum { + TIMEOUT_READ = 255, /* us */ + TIMEOUT_WAIT_IDLE = 255 /* us */ +}; + +/* PMIC_WRAP registers */ +struct mt8183_pmic_wrap_regs { + uint32_t reserved[776]; + uint32_t wacs2_cmd; + uint32_t wacs2_rdata; + uint32_t wacs2_vldclr; + uint32_t reserved1[4]; +}; + +enum { + RDATA_WACS_RDATA_SHIFT = 0, + RDATA_WACS_FSM_SHIFT = 16, + RDATA_WACS_REQ_SHIFT = 19, + RDATA_SYNC_IDLE_SHIFT, + RDATA_INIT_DONE_SHIFT, + RDATA_SYS_IDLE_SHIFT, +}; + +enum { + RDATA_WACS_RDATA_MASK = 0xffff, + RDATA_WACS_FSM_MASK = 0x7, + RDATA_WACS_REQ_MASK = 0x1, + RDATA_SYNC_IDLE_MASK = 0x1, + RDATA_INIT_DONE_MASK = 0x1, + RDATA_SYS_IDLE_MASK = 0x1, +}; + +/* WACS_FSM */ +enum { + WACS_FSM_IDLE = 0x00, + WACS_FSM_REQ = 0x02, + WACS_FSM_WFDLE = 0x04, + WACS_FSM_WFVLDCLR = 0x06, + WACS_INIT_DONE = 0x01, + WACS_SYNC_IDLE = 0x01, + WACS_SYNC_BUSY = 0x00 +}; + +/* error information flag */ +enum { + E_PWR_INVALID_ARG = 1, + E_PWR_INVALID_RW = 2, + E_PWR_INVALID_ADDR = 3, + E_PWR_INVALID_WDAT = 4, + E_PWR_INVALID_OP_MANUAL = 5, + E_PWR_NOT_IDLE_STATE = 6, + E_PWR_NOT_INIT_DONE = 7, + E_PWR_NOT_INIT_DONE_READ = 8, + E_PWR_WAIT_IDLE_TIMEOUT = 9, + E_PWR_WAIT_IDLE_TIMEOUT_READ = 10, + E_PWR_INIT_SIDLY_FAIL = 11, + E_PWR_RESET_TIMEOUT = 12, + E_PWR_TIMEOUT = 13, + E_PWR_INIT_RESET_SPI = 20, + E_PWR_INIT_SIDLY = 21, + E_PWR_INIT_REG_CLOCK = 22, + E_PWR_INIT_ENABLE_PMIC = 23, + E_PWR_INIT_DIO = 24, + E_PWR_INIT_CIPHER = 25, + E_PWR_INIT_WRITE_TEST = 26, + E_PWR_INIT_ENABLE_CRC = 27, + E_PWR_INIT_ENABLE_DEWRAP = 28, + E_PWR_INIT_ENABLE_EVENT = 29, + E_PWR_READ_TEST_FAIL = 30, + E_PWR_WRITE_TEST_FAIL = 31, + E_PWR_SWITCH_DIO = 32 +}; + +#endif /* PMIC_WRAP_INIT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c new file mode 100644 index 0000000..a821c1b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static void RTC_Config_Interface(uint32_t addr, uint16_t data, + uint16_t MASK, uint16_t SHIFT) +{ + uint16_t pmic_reg = 0; + + pmic_reg = RTC_Read(addr); + + pmic_reg &= ~(MASK << SHIFT); + pmic_reg |= (data << SHIFT); + + RTC_Write(addr, pmic_reg); +} + +static void rtc_disable_2sec_reboot(void) +{ + uint16_t reboot; + + reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) & + ~RTC_BBPU_AUTO_PDN_SEL; + RTC_Write(RTC_AL_SEC, reboot); + RTC_Write_Trigger(); +} + +static void rtc_xosc_write(uint16_t val, bool reload) +{ + uint16_t bbpu; + + RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1); + rtc_busy_wait(); + RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2); + rtc_busy_wait(); + + RTC_Write(RTC_OSC32CON, val); + rtc_busy_wait(); + + if (reload) { + bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; + RTC_Write(RTC_BBPU, bbpu); + RTC_Write_Trigger(); + } +} + +static void rtc_enable_k_eosc(void) +{ + uint16_t osc32; + uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */ + + /* Truning on eosc cali mode clock */ + RTC_Config_Interface(PMIC_RG_TOP_CON, 1, + PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK, + PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT); + RTC_Config_Interface(PMIC_RG_TOP_CON, 1, + PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK, + PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT); + RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0, + PMIC_RG_RTC_EOSC32_CK_PDN_MASK, + PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT); + + switch (rtc_eosc_cali_td) { + case 1: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + case 2: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + case 4: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + case 16: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + default: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + } + /* Switch the DCXO from 32k-less mode to RTC mode, + * otherwise, EOSC cali will fail + */ + /* RTC mode will have only OFF mode and FPM */ + RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK, + PMIC_RG_XO_EN32K_MAN_SHIFT); + RTC_Write(RTC_BBPU, + RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD); + RTC_Write_Trigger(); + /* Enable K EOSC mode for normal power off and then plug out battery */ + RTC_Write(RTC_AL_YEA, ((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0) + & (~RTC_K_EOSC_RSV_1)) | RTC_K_EOSC_RSV_2); + RTC_Write_Trigger(); + + osc32 = RTC_Read(RTC_OSC32CON); + rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true); + INFO("[RTC] RTC_enable_k_eosc\n"); +} + +void rtc_power_off_sequence(void) +{ + uint16_t bbpu; + + rtc_disable_2sec_reboot(); + rtc_enable_k_eosc(); + + /* clear alarm */ + bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN; + if (Writeif_unlock()) { + RTC_Write(RTC_BBPU, bbpu); + + RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW); + RTC_Write_Trigger(); + mdelay(1); + + bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; + RTC_Write(RTC_BBPU, bbpu); + RTC_Write_Trigger(); + INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n", + RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN), + RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC)); + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h new file mode 100644 index 0000000..66686b4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RTC_H +#define RTC_H + +/* RTC registers */ +enum { + RTC_BBPU = 0x0588, + RTC_IRQ_STA = 0x058A, + RTC_IRQ_EN = 0x058C, + RTC_CII_EN = 0x058E +}; + +enum { + RTC_AL_SEC = 0x05A0, + RTC_AL_MIN = 0x05A2, + RTC_AL_HOU = 0x05A4, + RTC_AL_DOM = 0x05A6, + RTC_AL_DOW = 0x05A8, + RTC_AL_MTH = 0x05AA, + RTC_AL_YEA = 0x05AC, + RTC_AL_MASK = 0x0590 +}; + +enum { + RTC_OSC32CON = 0x05AE, + RTC_CON = 0x05C4, + RTC_WRTGR = 0x05C2 +}; + +enum { + RTC_PDN1 = 0x05B4, + RTC_PDN2 = 0x05B6, + RTC_SPAR0 = 0x05B8, + RTC_SPAR1 = 0x05BA, + RTC_PROT = 0x05BC, + RTC_DIFF = 0x05BE, + RTC_CALI = 0x05C0 +}; + +enum { + RTC_OSC32CON_UNLOCK1 = 0x1A57, + RTC_OSC32CON_UNLOCK2 = 0x2B68 +}; + +enum { + RTC_PROT_UNLOCK1 = 0x586A, + RTC_PROT_UNLOCK2 = 0x9136 +}; + +enum { + RTC_BBPU_PWREN = 1U << 0, + RTC_BBPU_CLR = 1U << 1, + RTC_BBPU_INIT = 1U << 2, + RTC_BBPU_AUTO = 1U << 3, + RTC_BBPU_CLRPKY = 1U << 4, + RTC_BBPU_RELOAD = 1U << 5, + RTC_BBPU_CBUSY = 1U << 6 +}; + +enum { + RTC_AL_MASK_SEC = 1U << 0, + RTC_AL_MASK_MIN = 1U << 1, + RTC_AL_MASK_HOU = 1U << 2, + RTC_AL_MASK_DOM = 1U << 3, + RTC_AL_MASK_DOW = 1U << 4, + RTC_AL_MASK_MTH = 1U << 5, + RTC_AL_MASK_YEA = 1U << 6 +}; + +enum { + RTC_BBPU_AUTO_PDN_SEL = 1U << 6, + RTC_BBPU_2SEC_CK_SEL = 1U << 7, + RTC_BBPU_2SEC_EN = 1U << 8, + RTC_BBPU_2SEC_MODE = 0x3 << 9, + RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11, + RTC_BBPU_2SEC_STAT_STA = 1U << 12 +}; + +enum { + RTC_BBPU_KEY = 0x43 << 8 +}; + +enum { + RTC_EMBCK_SRC_SEL = 1 << 8, + RTC_EMBCK_SEL_MODE = 3 << 6, + RTC_XOSC32_ENB = 1 << 5, + RTC_REG_XOSC32_ENB = 1 << 15 +}; + +enum { + RTC_K_EOSC_RSV_0 = 1 << 8, + RTC_K_EOSC_RSV_1 = 1 << 9, + RTC_K_EOSC_RSV_2 = 1 << 10 +}; + +/* PMIC TOP Register Definition */ +enum { + PMIC_RG_TOP_CON = 0x001E, + PMIC_RG_TOP_CKPDN_CON1 = 0x0112, + PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114, + PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116, + PMIC_RG_TOP_CKSEL_CON0 = 0x0118, + PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A, + PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C +}; + +/* PMIC SCK Register Definition */ +enum { + PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x051A, + PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x051C, + PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x051E, + PMIC_RG_EOSC_CALI_CON0 = 0x540 +}; + +/* PMIC DCXO Register Definition */ +enum { + PMIC_RG_DCXO_CW00 = 0x0788, + PMIC_RG_DCXO_CW02 = 0x0790 +}; + +enum { + PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1, + PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1, + PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1, + PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3, + PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1, + PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2, + PMIC_RG_EOSC_CALI_TD_MASK = 0x7, + PMIC_RG_EOSC_CALI_TD_SHIFT = 5, + PMIC_RG_XO_EN32K_MAN_MASK = 0x1, + PMIC_RG_XO_EN32K_MAN_SHIFT = 0 +}; + +/* external API */ +uint16_t RTC_Read(uint32_t addr); +void RTC_Write(uint32_t addr, uint16_t data); +int32_t rtc_busy_wait(void); +int32_t RTC_Write_Trigger(void); +int32_t Writeif_unlock(void); +void rtc_power_off_sequence(void); + +#endif /* RTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c new file mode 100644 index 0000000..d6d2344 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + +DEFINE_BAKERY_LOCK(spm_lock); + +/* SPM_DVS_LEVEL */ +#define SPM_VMODEM_LEVEL_MASK (0xff << 16) +#define SPM_VMODEM_LEVEL (1U << 18) +#define SPM_VCORE_LEVEL_MASK (0xff) +#define SPM_VCORE_LEVEL (1U << 1) + +/* CLK_SCP_CFG_0 */ +#define SPM_CK_OFF_CONTROL (0x3FF) + +/* CLK_SCP_CFG_1 */ +#define SPM_AXI_26M_SEL (0x1) + +/* AP_PLL_CON3 */ +#define SPM_PLL_CONTROL (0x7FAAAAF) + +/* AP_PLL_CON4 */ +#define SPM_PLL_OUT_OFF_CONTROL (0xFA0A) + +/* AP_PLL_CON6 */ +#define PLL_DLY (0x20000) + +const char *wakeup_src_str[32] = { + [0] = "R12_PCM_TIMER", + [1] = "R12_SSPM_WDT_EVENT_B", + [2] = "R12_KP_IRQ_B", + [3] = "R12_APWDT_EVENT_B", + [4] = "R12_APXGPT1_EVENT_B", + [5] = "R12_CONN2AP_SPM_WAKEUP_B", + [6] = "R12_EINT_EVENT_B", + [7] = "R12_CONN_WDT_IRQ_B", + [8] = "R12_CCIF0_EVENT_B", + [9] = "R12_LOWBATTERY_IRQ_B", + [10] = "R12_SSPM_SPM_IRQ_B", + [11] = "R12_SCP_SPM_IRQ_B", + [12] = "R12_SCP_WDT_EVENT_B", + [13] = "R12_PCM_WDT_WAKEUP_B", + [14] = "R12_USB_CDSC_B ", + [15] = "R12_USB_POWERDWN_B", + [16] = "R12_SYS_TIMER_EVENT_B", + [17] = "R12_EINT_EVENT_SECURE_B", + [18] = "R12_CCIF1_EVENT_B", + [19] = "R12_UART0_IRQ_B", + [20] = "R12_AFE_IRQ_MCU_B", + [21] = "R12_THERM_CTRL_EVENT_B", + [22] = "R12_SYS_CIRQ_IRQ_B", + [23] = "R12_MD2AP_PEER_EVENT_B", + [24] = "R12_CSYSPWREQ_B", + [25] = "R12_MD1_WDT_B ", + [26] = "R12_CLDMA_EVENT_B", + [27] = "R12_SEJ_WDT_GPT_B", + [28] = "R12_ALL_SSPM_WAKEUP_B", + [29] = "R12_CPU_IRQ_B", + [30] = "R12_CPU_WFI_AND_B" +}; + +const char *spm_get_firmware_version(void) +{ + return "DYNAMIC_SPM_FW_VERSION"; +} + +void spm_lock_init(void) +{ + bakery_lock_init(&spm_lock); +} + +void spm_lock_get(void) +{ + bakery_lock_get(&spm_lock); +} + +void spm_lock_release(void) +{ + bakery_lock_release(&spm_lock); +} + +void spm_set_bootaddr(unsigned long bootaddr) +{ + /* initialize core4~7 boot entry address */ + mmio_write_32(SW2SPM_MAILBOX_3, bootaddr); +} + +void spm_set_cpu_status(int cpu) +{ + if (cpu >= 0 && cpu < 4) { + mmio_write_32(ROOT_CPUTOP_ADDR, 0x10006204); + mmio_write_32(ROOT_CORE_ADDR, 0x10006208 + (cpu * 0x4)); + } else if (cpu >= 4 && cpu < 8) { + mmio_write_32(ROOT_CPUTOP_ADDR, 0x10006218); + mmio_write_32(ROOT_CORE_ADDR, 0x1000621c + ((cpu - 4) * 0x4)); + } else { + ERROR("%s: error cpu number %d\n", __func__, cpu); + } +} + +void spm_set_power_control(const struct pwr_ctrl *pwrctrl) +{ + mmio_write_32(SPM_AP_STANDBY_CON, + ((pwrctrl->wfi_op & 0x1) << 0) | + ((pwrctrl->mp0_cputop_idle_mask & 0x1) << 1) | + ((pwrctrl->mp1_cputop_idle_mask & 0x1) << 2) | + ((pwrctrl->mcusys_idle_mask & 0x1) << 4) | + ((pwrctrl->mm_mask_b & 0x3) << 16) | + ((pwrctrl->md_ddr_en_0_dbc_en & 0x1) << 18) | + ((pwrctrl->md_ddr_en_1_dbc_en & 0x1) << 19) | + ((pwrctrl->md_mask_b & 0x3) << 20) | + ((pwrctrl->sspm_mask_b & 0x1) << 22) | + ((pwrctrl->scp_mask_b & 0x1) << 23) | + ((pwrctrl->srcclkeni_mask_b & 0x1) << 24) | + ((pwrctrl->md_apsrc_1_sel & 0x1) << 25) | + ((pwrctrl->md_apsrc_0_sel & 0x1) << 26) | + ((pwrctrl->conn_ddr_en_dbc_en & 0x1) << 27) | + ((pwrctrl->conn_mask_b & 0x1) << 28) | + ((pwrctrl->conn_apsrc_sel & 0x1) << 29)); + + mmio_write_32(SPM_SRC_REQ, + ((pwrctrl->spm_apsrc_req & 0x1) << 0) | + ((pwrctrl->spm_f26m_req & 0x1) << 1) | + ((pwrctrl->spm_infra_req & 0x1) << 3) | + ((pwrctrl->spm_vrf18_req & 0x1) << 4) | + ((pwrctrl->spm_ddren_req & 0x1) << 7) | + ((pwrctrl->spm_rsv_src_req & 0x7) << 8) | + ((pwrctrl->spm_ddren_2_req & 0x1) << 11) | + ((pwrctrl->cpu_md_dvfs_sop_force_on & 0x1) << 16)); + + mmio_write_32(SPM_SRC_MASK, + ((pwrctrl->csyspwreq_mask & 0x1) << 0) | + ((pwrctrl->ccif0_md_event_mask_b & 0x1) << 1) | + ((pwrctrl->ccif0_ap_event_mask_b & 0x1) << 2) | + ((pwrctrl->ccif1_md_event_mask_b & 0x1) << 3) | + ((pwrctrl->ccif1_ap_event_mask_b & 0x1) << 4) | + ((pwrctrl->ccif2_md_event_mask_b & 0x1) << 5) | + ((pwrctrl->ccif2_ap_event_mask_b & 0x1) << 6) | + ((pwrctrl->ccif3_md_event_mask_b & 0x1) << 7) | + ((pwrctrl->ccif3_ap_event_mask_b & 0x1) << 8) | + ((pwrctrl->md_srcclkena_0_infra_mask_b & 0x1) << 9) | + ((pwrctrl->md_srcclkena_1_infra_mask_b & 0x1) << 10) | + ((pwrctrl->conn_srcclkena_infra_mask_b & 0x1) << 11) | + ((pwrctrl->ufs_infra_req_mask_b & 0x1) << 12) | + ((pwrctrl->srcclkeni_infra_mask_b & 0x1) << 13) | + ((pwrctrl->md_apsrc_req_0_infra_mask_b & 0x1) << 14) | + ((pwrctrl->md_apsrc_req_1_infra_mask_b & 0x1) << 15) | + ((pwrctrl->conn_apsrcreq_infra_mask_b & 0x1) << 16) | + ((pwrctrl->ufs_srcclkena_mask_b & 0x1) << 17) | + ((pwrctrl->md_vrf18_req_0_mask_b & 0x1) << 18) | + ((pwrctrl->md_vrf18_req_1_mask_b & 0x1) << 19) | + ((pwrctrl->ufs_vrf18_req_mask_b & 0x1) << 20) | + ((pwrctrl->gce_vrf18_req_mask_b & 0x1) << 21) | + ((pwrctrl->conn_infra_req_mask_b & 0x1) << 22) | + ((pwrctrl->gce_apsrc_req_mask_b & 0x1) << 23) | + ((pwrctrl->disp0_apsrc_req_mask_b & 0x1) << 24) | + ((pwrctrl->disp1_apsrc_req_mask_b & 0x1) << 25) | + ((pwrctrl->mfg_req_mask_b & 0x1) << 26) | + ((pwrctrl->vdec_req_mask_b & 0x1) << 27)); + + mmio_write_32(SPM_SRC2_MASK, + ((pwrctrl->md_ddr_en_0_mask_b & 0x1) << 0) | + ((pwrctrl->md_ddr_en_1_mask_b & 0x1) << 1) | + ((pwrctrl->conn_ddr_en_mask_b & 0x1) << 2) | + ((pwrctrl->ddren_sspm_apsrc_req_mask_b & 0x1) << 3) | + ((pwrctrl->ddren_scp_apsrc_req_mask_b & 0x1) << 4) | + ((pwrctrl->disp0_ddren_mask_b & 0x1) << 5) | + ((pwrctrl->disp1_ddren_mask_b & 0x1) << 6) | + ((pwrctrl->gce_ddren_mask_b & 0x1) << 7) | + ((pwrctrl->ddren_emi_self_refresh_ch0_mask_b & 0x1) + << 8) | + ((pwrctrl->ddren_emi_self_refresh_ch1_mask_b & 0x1) + << 9)); + + mmio_write_32(SPM_WAKEUP_EVENT_MASK, + ((pwrctrl->spm_wakeup_event_mask & 0xffffffff) << 0)); + + mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK, + ((pwrctrl->spm_wakeup_event_ext_mask & 0xffffffff) + << 0)); + + mmio_write_32(SPM_SRC3_MASK, + ((pwrctrl->md_ddr_en_2_0_mask_b & 0x1) << 0) | + ((pwrctrl->md_ddr_en_2_1_mask_b & 0x1) << 1) | + ((pwrctrl->conn_ddr_en_2_mask_b & 0x1) << 2) | + ((pwrctrl->ddren2_sspm_apsrc_req_mask_b & 0x1) << 3) | + ((pwrctrl->ddren2_scp_apsrc_req_mask_b & 0x1) << 4) | + ((pwrctrl->disp0_ddren2_mask_b & 0x1) << 5) | + ((pwrctrl->disp1_ddren2_mask_b & 0x1) << 6) | + ((pwrctrl->gce_ddren2_mask_b & 0x1) << 7) | + ((pwrctrl->ddren2_emi_self_refresh_ch0_mask_b & 0x1) + << 8) | + ((pwrctrl->ddren2_emi_self_refresh_ch1_mask_b & 0x1) + << 9)); + + mmio_write_32(MP0_CPU0_WFI_EN, + ((pwrctrl->mp0_cpu0_wfi_en & 0x1) << 0)); + mmio_write_32(MP0_CPU1_WFI_EN, + ((pwrctrl->mp0_cpu1_wfi_en & 0x1) << 0)); + mmio_write_32(MP0_CPU2_WFI_EN, + ((pwrctrl->mp0_cpu2_wfi_en & 0x1) << 0)); + mmio_write_32(MP0_CPU3_WFI_EN, + ((pwrctrl->mp0_cpu3_wfi_en & 0x1) << 0)); + + mmio_write_32(MP1_CPU0_WFI_EN, + ((pwrctrl->mp1_cpu0_wfi_en & 0x1) << 0)); + mmio_write_32(MP1_CPU1_WFI_EN, + ((pwrctrl->mp1_cpu1_wfi_en & 0x1) << 0)); + mmio_write_32(MP1_CPU2_WFI_EN, + ((pwrctrl->mp1_cpu2_wfi_en & 0x1) << 0)); + mmio_write_32(MP1_CPU3_WFI_EN, + ((pwrctrl->mp1_cpu3_wfi_en & 0x1) << 0)); +} + +void spm_disable_pcm_timer(void) +{ + mmio_clrsetbits_32(PCM_CON1, PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY); +} + +void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl) +{ + uint32_t val, mask, isr; + + val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX; + mmio_write_32(PCM_TIMER_VAL, val); + mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | PCM_TIMER_EN_LSB); + + mask = pwrctrl->wake_src; + + if (pwrctrl->csyspwreq_mask) + mask &= ~WAKE_SRC_R12_CSYSPWREQ_B; + + mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask); + + isr = mmio_read_32(SPM_IRQ_MASK) & SPM_TWAM_IRQ_MASK_LSB; + mmio_write_32(SPM_IRQ_MASK, isr | ISRM_RET_IRQ_AUX); +} + +void spm_set_pcm_flags(const struct pwr_ctrl *pwrctrl) +{ + mmio_write_32(SPM_SW_FLAG, pwrctrl->pcm_flags); + mmio_write_32(SPM_SW_RSV_2, pwrctrl->pcm_flags1); +} + +void spm_set_pcm_wdt(int en) +{ + if (en) { + mmio_clrsetbits_32(PCM_CON1, PCM_WDT_WAKE_MODE_LSB, + SPM_REGWR_CFG_KEY); + + if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) + mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX); + mmio_write_32(PCM_WDT_VAL, + mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT); + mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | PCM_WDT_EN_LSB); + } else { + mmio_clrsetbits_32(PCM_CON1, PCM_WDT_EN_LSB, + SPM_REGWR_CFG_KEY); + } +} + +void spm_send_cpu_wakeup_event(void) +{ + mmio_write_32(PCM_REG_DATA_INI, 0); + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1); +} + +void spm_get_wakeup_status(struct wake_status *wakesta) +{ + wakesta->assert_pc = mmio_read_32(PCM_REG_DATA_INI); + wakesta->r12 = mmio_read_32(SPM_SW_RSV_0); + wakesta->r12_ext = mmio_read_32(PCM_REG12_EXT_DATA); + wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA); + wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA); + wakesta->wake_misc = mmio_read_32(SPM_BSI_D0_SR); + wakesta->timer_out = mmio_read_32(SPM_BSI_D1_SR); + wakesta->r13 = mmio_read_32(PCM_REG13_DATA); + wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA); + wakesta->req_sta = mmio_read_32(SRC_REQ_STA); + wakesta->sw_flag = mmio_read_32(SPM_SW_FLAG); + wakesta->sw_flag1 = mmio_read_32(SPM_SW_RSV_2); + wakesta->r15 = mmio_read_32(PCM_REG15_DATA); + wakesta->debug_flag = mmio_read_32(SPM_SW_DEBUG); + wakesta->debug_flag1 = mmio_read_32(WDT_LATCH_SPARE0_FIX); + wakesta->event_reg = mmio_read_32(SPM_BSI_D2_SR); + wakesta->isr = mmio_read_32(SPM_IRQ_STA); +} + +void spm_clean_after_wakeup(void) +{ + mmio_write_32(SPM_SW_RSV_0, + mmio_read_32(SPM_WAKEUP_STA) | + mmio_read_32(SPM_SW_RSV_0)); + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0); + mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~0); + mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM); + mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM); + mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL); +} + +void spm_output_wake_reason(struct wake_status *wakesta, const char *scenario) +{ + uint32_t i; + + if (wakesta->assert_pc != 0) { + INFO("%s: PCM ASSERT AT %u, ULPOSC_CON = 0x%x\n", + scenario, wakesta->assert_pc, mmio_read_32(ULPOSC_CON)); + goto spm_debug_flags; + } + + for (i = 0; i <= 31; i++) { + if (wakesta->r12 & (1U << i)) { + INFO("%s: wake up by %s, timer_out = %u\n", + scenario, wakeup_src_str[i], wakesta->timer_out); + break; + } + } + +spm_debug_flags: + INFO("r15 = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n", + wakesta->r15, wakesta->r13, wakesta->debug_flag, + wakesta->debug_flag1); + INFO("sw_flag = 0x%x 0x%x, r12 = 0x%x, r12_ext = 0x%x\n", + wakesta->sw_flag, wakesta->sw_flag1, wakesta->r12, + wakesta->r12_ext); + INFO("idle_sta = 0x%x, req_sta = 0x%x, event_reg = 0x%x\n", + wakesta->idle_sta, wakesta->req_sta, wakesta->event_reg); + INFO("isr = 0x%x, raw_sta = 0x%x, raw_ext_sta = 0x%x\n", + wakesta->isr, wakesta->raw_sta, wakesta->raw_ext_sta); + INFO("wake_misc = 0x%x\n", wakesta->wake_misc); +} + +void spm_boot_init(void) +{ + NOTICE("%s() start\n", __func__); + + spm_lock_init(); + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE); + + /* Set Vmodem / Vcore DVS init level */ + mmio_clrsetbits_32(SPM_DVS_LEVEL, + SPM_VMODEM_LEVEL_MASK | SPM_VCORE_LEVEL_MASK, + SPM_VMODEM_LEVEL | SPM_VCORE_LEVEL); + + /* switch ck_off/axi_26m control to SPM */ + mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_OFF_CONTROL); + mmio_setbits_32(CLK_SCP_CFG_1, SPM_AXI_26M_SEL); + + /* switch PLL/CLKSQ control to SPM */ + mmio_clrbits_32(AP_PLL_CON3, SPM_PLL_CONTROL); + mmio_clrbits_32(AP_PLL_CON4, SPM_PLL_OUT_OFF_CONTROL); + mmio_clrbits_32(AP_PLL_CON6, PLL_DLY); + + NOTICE("%s() end\n", __func__); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h new file mode 100644 index 0000000..b2e83dc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h @@ -0,0 +1,2552 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_H +#define SPM_H + +/************************************** + * Define and Declare + **************************************/ + +#define POWERON_CONFIG_EN (SPM_BASE + 0x000) +#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004) +#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008) +#define SPM_CLK_CON (SPM_BASE + 0x00C) +#define SPM_CLK_SETTLE (SPM_BASE + 0x010) +#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014) +#define PCM_CON0 (SPM_BASE + 0x018) +#define PCM_CON1 (SPM_BASE + 0x01C) +#define PCM_IM_PTR (SPM_BASE + 0x020) +#define PCM_IM_LEN (SPM_BASE + 0x024) +#define PCM_REG_DATA_INI (SPM_BASE + 0x028) +#define PCM_PWR_IO_EN (SPM_BASE + 0x02C) +#define PCM_TIMER_VAL (SPM_BASE + 0x030) +#define PCM_WDT_VAL (SPM_BASE + 0x034) +#define PCM_IM_HOST_RW_PTR (SPM_BASE + 0x038) +#define PCM_IM_HOST_RW_DAT (SPM_BASE + 0x03C) +#define PCM_EVENT_VECTOR0 (SPM_BASE + 0x040) +#define PCM_EVENT_VECTOR1 (SPM_BASE + 0x044) +#define PCM_EVENT_VECTOR2 (SPM_BASE + 0x048) +#define PCM_EVENT_VECTOR3 (SPM_BASE + 0x04C) +#define PCM_EVENT_VECTOR4 (SPM_BASE + 0x050) +#define PCM_EVENT_VECTOR5 (SPM_BASE + 0x054) +#define PCM_EVENT_VECTOR6 (SPM_BASE + 0x058) +#define PCM_EVENT_VECTOR7 (SPM_BASE + 0x05C) +#define PCM_EVENT_VECTOR8 (SPM_BASE + 0x060) +#define PCM_EVENT_VECTOR9 (SPM_BASE + 0x064) +#define PCM_EVENT_VECTOR10 (SPM_BASE + 0x068) +#define PCM_EVENT_VECTOR11 (SPM_BASE + 0x06C) +#define PCM_EVENT_VECTOR12 (SPM_BASE + 0x070) +#define PCM_EVENT_VECTOR13 (SPM_BASE + 0x074) +#define PCM_EVENT_VECTOR14 (SPM_BASE + 0x078) +#define PCM_EVENT_VECTOR15 (SPM_BASE + 0x07C) +#define PCM_EVENT_VECTOR_EN (SPM_BASE + 0x080) +#define SPM_SRAM_RSV_CON (SPM_BASE + 0x088) +#define SPM_SWINT (SPM_BASE + 0x08C) +#define SPM_SWINT_SET (SPM_BASE + 0x090) +#define SPM_SWINT_CLR (SPM_BASE + 0x094) +#define SPM_SCP_MAILBOX (SPM_BASE + 0x098) +#define SCP_SPM_MAILBOX (SPM_BASE + 0x09C) +#define SPM_TWAM_CON (SPM_BASE + 0x0A0) +#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x0A4) +#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x0A8) +#define SPM_SCP_IRQ (SPM_BASE + 0x0AC) +#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x0B0) +#define SPM_IRQ_MASK (SPM_BASE + 0x0B4) +#define SPM_SRC_REQ (SPM_BASE + 0x0B8) +#define SPM_SRC_MASK (SPM_BASE + 0x0BC) +#define SPM_SRC2_MASK (SPM_BASE + 0x0C0) +#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x0C4) +#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0C8) +#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x0CC) +#define SCP_CLK_CON (SPM_BASE + 0x0D0) +#define PCM_DEBUG_CON (SPM_BASE + 0x0D4) +#define DDR_EN_DBC_LEN (SPM_BASE + 0x0D8) +#define AHB_BUS_CON (SPM_BASE + 0x0DC) +#define SPM_SRC3_MASK (SPM_BASE + 0x0E0) +#define DDR_EN_EMI_DBC_CON (SPM_BASE + 0x0E4) +#define SSPM_CLK_CON (SPM_BASE + 0x0E8) +#define PCM_REG0_DATA (SPM_BASE + 0x100) +#define PCM_REG1_DATA (SPM_BASE + 0x104) +#define PCM_REG2_DATA (SPM_BASE + 0x108) +#define PCM_REG3_DATA (SPM_BASE + 0x10C) +#define PCM_REG4_DATA (SPM_BASE + 0x110) +#define PCM_REG5_DATA (SPM_BASE + 0x114) +#define PCM_REG6_DATA (SPM_BASE + 0x118) +#define PCM_REG7_DATA (SPM_BASE + 0x11C) +#define PCM_REG8_DATA (SPM_BASE + 0x120) +#define PCM_REG9_DATA (SPM_BASE + 0x124) +#define PCM_REG10_DATA (SPM_BASE + 0x128) +#define PCM_REG11_DATA (SPM_BASE + 0x12C) +#define PCM_REG12_DATA (SPM_BASE + 0x130) +#define PCM_REG13_DATA (SPM_BASE + 0x134) +#define PCM_REG14_DATA (SPM_BASE + 0x138) +#define PCM_REG15_DATA (SPM_BASE + 0x13C) +#define PCM_REG12_MASK_B_STA (SPM_BASE + 0x140) +#define PCM_REG12_EXT_DATA (SPM_BASE + 0x144) +#define PCM_REG12_EXT_MASK_B_STA (SPM_BASE + 0x148) +#define PCM_EVENT_REG_STA (SPM_BASE + 0x14C) +#define PCM_TIMER_OUT (SPM_BASE + 0x150) +#define PCM_WDT_OUT (SPM_BASE + 0x154) +#define SPM_IRQ_STA (SPM_BASE + 0x158) +#define SPM_WAKEUP_STA (SPM_BASE + 0x15C) +#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x160) +#define SPM_WAKEUP_MISC (SPM_BASE + 0x164) +#define BUS_PROTECT_RDY (SPM_BASE + 0x168) +#define BUS_PROTECT2_RDY (SPM_BASE + 0x16C) +#define SUBSYS_IDLE_STA (SPM_BASE + 0x170) +#define CPU_IDLE_STA (SPM_BASE + 0x174) +#define PCM_FSM_STA (SPM_BASE + 0x178) +#define SRC_REQ_STA (SPM_BASE + 0x17C) +#define PWR_STATUS (SPM_BASE + 0x180) +#define PWR_STATUS_2ND (SPM_BASE + 0x184) +#define CPU_PWR_STATUS (SPM_BASE + 0x188) +#define CPU_PWR_STATUS_2ND (SPM_BASE + 0x18C) +#define MISC_STA (SPM_BASE + 0x190) +#define SPM_SRC_RDY_STA (SPM_BASE + 0x194) +#define DRAMC_DBG_LATCH (SPM_BASE + 0x19C) +#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1A0) +#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1A4) +#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1A8) +#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1AC) +#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1B0) +#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1B4) +#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1B8) +#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1BC) +#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1C0) +#define SPM_DVFS_STA (SPM_BASE + 0x1C8) +#define BUS_PROTECT3_RDY (SPM_BASE + 0x1CC) +#define SRC_DDREN_STA (SPM_BASE + 0x1E0) +#define MCU_PWR_CON (SPM_BASE + 0x200) +#define MP0_CPUTOP_PWR_CON (SPM_BASE + 0x204) +#define MP0_CPU0_PWR_CON (SPM_BASE + 0x208) +#define MP0_CPU1_PWR_CON (SPM_BASE + 0x20C) +#define MP0_CPU2_PWR_CON (SPM_BASE + 0x210) +#define MP0_CPU3_PWR_CON (SPM_BASE + 0x214) +#define MP1_CPUTOP_PWR_CON (SPM_BASE + 0x218) +#define MP1_CPU0_PWR_CON (SPM_BASE + 0x21C) +#define MP1_CPU1_PWR_CON (SPM_BASE + 0x220) +#define MP1_CPU2_PWR_CON (SPM_BASE + 0x224) +#define MP1_CPU3_PWR_CON (SPM_BASE + 0x228) +#define MP0_CPUTOP_L2_PDN (SPM_BASE + 0x240) +#define MP0_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x244) +#define MP0_CPU0_L1_PDN (SPM_BASE + 0x248) +#define MP0_CPU1_L1_PDN (SPM_BASE + 0x24C) +#define MP0_CPU2_L1_PDN (SPM_BASE + 0x250) +#define MP0_CPU3_L1_PDN (SPM_BASE + 0x254) +#define MP1_CPUTOP_L2_PDN (SPM_BASE + 0x258) +#define MP1_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x25C) +#define MP1_CPU0_L1_PDN (SPM_BASE + 0x260) +#define MP1_CPU1_L1_PDN (SPM_BASE + 0x264) +#define MP1_CPU2_L1_PDN (SPM_BASE + 0x268) +#define MP1_CPU3_L1_PDN (SPM_BASE + 0x26C) +#define CPU_EXT_BUCK_ISO (SPM_BASE + 0x290) +#define DUMMY1_PWR_CON (SPM_BASE + 0x2B0) +#define BYPASS_SPMC (SPM_BASE + 0x2B4) +#define SPMC_DORMANT_ENABLE (SPM_BASE + 0x2B8) +#define ARMPLL_CLK_CON (SPM_BASE + 0x2BC) +#define SPMC_IN_RET (SPM_BASE + 0x2C0) +#define VDE_PWR_CON (SPM_BASE + 0x300) +#define VEN_PWR_CON (SPM_BASE + 0x304) +#define ISP_PWR_CON (SPM_BASE + 0x308) +#define DIS_PWR_CON (SPM_BASE + 0x30C) +#define MFG_CORE1_PWR_CON (SPM_BASE + 0x310) +#define AUDIO_PWR_CON (SPM_BASE + 0x314) +#define IFR_PWR_CON (SPM_BASE + 0x318) +#define DPY_PWR_CON (SPM_BASE + 0x31C) +#define MD1_PWR_CON (SPM_BASE + 0x320) +#define VPU_TOP_PWR_CON (SPM_BASE + 0x324) +#define CONN_PWR_CON (SPM_BASE + 0x32C) +#define VPU_CORE2_PWR_CON (SPM_BASE + 0x330) +#define MFG_ASYNC_PWR_CON (SPM_BASE + 0x334) +#define MFG_PWR_CON (SPM_BASE + 0x338) +#define VPU_CORE0_PWR_CON (SPM_BASE + 0x33C) +#define VPU_CORE1_PWR_CON (SPM_BASE + 0x340) +#define CAM_PWR_CON (SPM_BASE + 0x344) +#define MFG_2D_PWR_CON (SPM_BASE + 0x348) +#define MFG_CORE0_PWR_CON (SPM_BASE + 0x34C) +#define SYSRAM_CON (SPM_BASE + 0x350) +#define SYSROM_CON (SPM_BASE + 0x354) +#define SSPM_SRAM_CON (SPM_BASE + 0x358) +#define SCP_SRAM_CON (SPM_BASE + 0x35C) +#define UFS_SRAM_CON (SPM_BASE + 0x36C) +#define DUMMY_SRAM_CON (SPM_BASE + 0x380) +#define MD_EXT_BUCK_ISO_CON (SPM_BASE + 0x390) +#define MD_SRAM_ISO_CON (SPM_BASE + 0x394) +#define MD_EXTRA_PWR_CON (SPM_BASE + 0x398) +#define EXT_BUCK_CON (SPM_BASE + 0x3A0) +#define MBIST_EFUSE_REPAIR_ACK_STA (SPM_BASE + 0x3D0) +#define SPM_DVFS_CON (SPM_BASE + 0x400) +#define SPM_MDBSI_CON (SPM_BASE + 0x404) +#define SPM_MAS_PAUSE_MASK_B (SPM_BASE + 0x408) +#define SPM_MAS_PAUSE2_MASK_B (SPM_BASE + 0x40C) +#define SPM_BSI_GEN (SPM_BASE + 0x410) +#define SPM_BSI_EN_SR (SPM_BASE + 0x414) +#define SPM_BSI_CLK_SR (SPM_BASE + 0x418) +#define SPM_BSI_D0_SR (SPM_BASE + 0x41C) +#define SPM_BSI_D1_SR (SPM_BASE + 0x420) +#define SPM_BSI_D2_SR (SPM_BASE + 0x424) +#define SPM_AP_SEMA (SPM_BASE + 0x428) +#define SPM_SPM_SEMA (SPM_BASE + 0x42C) +#define AP_MDSRC_REQ (SPM_BASE + 0x430) +#define SPM2MD_DVFS_CON (SPM_BASE + 0x438) +#define MD2SPM_DVFS_CON (SPM_BASE + 0x43C) +#define DRAMC_DPY_CLK_SW_CON_RSV (SPM_BASE + 0x440) +#define DPY_LP_CON (SPM_BASE + 0x444) +#define CPU_DVFS_REQ (SPM_BASE + 0x448) +#define SPM_PLL_CON (SPM_BASE + 0x44C) +#define SPM_EMI_BW_MODE (SPM_BASE + 0x450) +#define AP2MD_PEER_WAKEUP (SPM_BASE + 0x454) +#define ULPOSC_CON (SPM_BASE + 0x458) +#define SPM2MM_CON (SPM_BASE + 0x45C) +#define DRAMC_DPY_CLK_SW_CON_SEL (SPM_BASE + 0x460) +#define DRAMC_DPY_CLK_SW_CON (SPM_BASE + 0x464) +#define SPM_S1_MODE_CH (SPM_BASE + 0x468) +#define EMI_SELF_REFRESH_CH_STA (SPM_BASE + 0x46C) +#define DRAMC_DPY_CLK_SW_CON_SEL2 (SPM_BASE + 0x470) +#define DRAMC_DPY_CLK_SW_CON2 (SPM_BASE + 0x474) +#define DRAMC_DMYRD_CON (SPM_BASE + 0x478) +#define SPM_DRS_CON (SPM_BASE + 0x47C) +#define SPM_SEMA_M0 (SPM_BASE + 0x480) +#define SPM_SEMA_M1 (SPM_BASE + 0x484) +#define SPM_SEMA_M2 (SPM_BASE + 0x488) +#define SPM_SEMA_M3 (SPM_BASE + 0x48C) +#define SPM_SEMA_M4 (SPM_BASE + 0x490) +#define SPM_SEMA_M5 (SPM_BASE + 0x494) +#define SPM_SEMA_M6 (SPM_BASE + 0x498) +#define SPM_SEMA_M7 (SPM_BASE + 0x49C) +#define SPM_MAS_PAUSE_MM_MASK_B (SPM_BASE + 0x4A0) +#define SPM_MAS_PAUSE_MCU_MASK_B (SPM_BASE + 0x4A4) +#define SRAM_DREQ_ACK (SPM_BASE + 0x4AC) +#define SRAM_DREQ_CON (SPM_BASE + 0x4B0) +#define SRAM_DREQ_CON_SET (SPM_BASE + 0x4B4) +#define SRAM_DREQ_CON_CLR (SPM_BASE + 0x4B8) +#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x4BC) +#define SPM_SSPM_IRQ (SPM_BASE + 0x4C0) +#define SPM2PMCU_INT (SPM_BASE + 0x4C4) +#define SPM2PMCU_INT_SET (SPM_BASE + 0x4C8) +#define SPM2PMCU_INT_CLR (SPM_BASE + 0x4CC) +#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x4D0) +#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x4D4) +#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x4D8) +#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x4DC) +#define PMCU2SPM_INT (SPM_BASE + 0x4E0) +#define PMCU2SPM_INT_SET (SPM_BASE + 0x4E4) +#define PMCU2SPM_INT_CLR (SPM_BASE + 0x4E8) +#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x4EC) +#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x4F0) +#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x4F4) +#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x4F8) +#define PMCU2SPM_CFG (SPM_BASE + 0x4FC) +#define MP0_CPU0_IRQ_MASK (SPM_BASE + 0x500) +#define MP0_CPU1_IRQ_MASK (SPM_BASE + 0x504) +#define MP0_CPU2_IRQ_MASK (SPM_BASE + 0x508) +#define MP0_CPU3_IRQ_MASK (SPM_BASE + 0x50C) +#define MP1_CPU0_IRQ_MASK (SPM_BASE + 0x510) +#define MP1_CPU1_IRQ_MASK (SPM_BASE + 0x514) +#define MP1_CPU2_IRQ_MASK (SPM_BASE + 0x518) +#define MP1_CPU3_IRQ_MASK (SPM_BASE + 0x51C) +#define MP0_CPU0_WFI_EN (SPM_BASE + 0x530) +#define MP0_CPU1_WFI_EN (SPM_BASE + 0x534) +#define MP0_CPU2_WFI_EN (SPM_BASE + 0x538) +#define MP0_CPU3_WFI_EN (SPM_BASE + 0x53C) +#define MP1_CPU0_WFI_EN (SPM_BASE + 0x540) +#define MP1_CPU1_WFI_EN (SPM_BASE + 0x544) +#define MP1_CPU2_WFI_EN (SPM_BASE + 0x548) +#define MP1_CPU3_WFI_EN (SPM_BASE + 0x54C) +#define MP0_L2CFLUSH (SPM_BASE + 0x554) +#define MP1_L2CFLUSH (SPM_BASE + 0x558) +#define CPU_PTPOD2_CON (SPM_BASE + 0x560) +#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x570) +#define ROOT_CORE_ADDR (SPM_BASE + 0x574) +#define CPU_SPARE_CON (SPM_BASE + 0x580) +#define CPU_SPARE_CON_SET (SPM_BASE + 0x584) +#define CPU_SPARE_CON_CLR (SPM_BASE + 0x588) +#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x5D0) +#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x5D4) +#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x5D8) +#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x5DC) +#define SW2SPM_INT (SPM_BASE + 0x5E0) +#define SW2SPM_INT_SET (SPM_BASE + 0x5E4) +#define SW2SPM_INT_CLR (SPM_BASE + 0x5E8) +#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x5EC) +#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x5F0) +#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x5F4) +#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x5F8) +#define SW2SPM_CFG (SPM_BASE + 0x5FC) +#define SPM_SW_FLAG (SPM_BASE + 0x600) +#define SPM_SW_DEBUG (SPM_BASE + 0x604) +#define SPM_SW_RSV_0 (SPM_BASE + 0x608) +#define SPM_SW_RSV_1 (SPM_BASE + 0x60C) +#define SPM_SW_RSV_2 (SPM_BASE + 0x610) +#define SPM_SW_RSV_3 (SPM_BASE + 0x614) +#define SPM_SW_RSV_4 (SPM_BASE + 0x618) +#define SPM_SW_RSV_5 (SPM_BASE + 0x61C) +#define SPM_RSV_CON (SPM_BASE + 0x620) +#define SPM_RSV_STA (SPM_BASE + 0x624) +#define SPM_RSV_CON1 (SPM_BASE + 0x628) +#define SPM_RSV_STA1 (SPM_BASE + 0x62C) +#define SPM_PASR_DPD_0 (SPM_BASE + 0x630) +#define SPM_PASR_DPD_1 (SPM_BASE + 0x634) +#define SPM_PASR_DPD_2 (SPM_BASE + 0x638) +#define SPM_PASR_DPD_3 (SPM_BASE + 0x63C) +#define SPM_SPARE_CON (SPM_BASE + 0x640) +#define SPM_SPARE_CON_SET (SPM_BASE + 0x644) +#define SPM_SPARE_CON_CLR (SPM_BASE + 0x648) +#define SPM_SW_RSV_6 (SPM_BASE + 0x64C) +#define SPM_SW_RSV_7 (SPM_BASE + 0x650) +#define SPM_SW_RSV_8 (SPM_BASE + 0x654) +#define SPM_SW_RSV_9 (SPM_BASE + 0x658) +#define SPM_SW_RSV_10 (SPM_BASE + 0x65C) +#define SPM_SW_RSV_18 (SPM_BASE + 0x67C) +#define SPM_SW_RSV_19 (SPM_BASE + 0x680) +#define DVFSRC_EVENT_MASK_CON (SPM_BASE + 0x690) +#define DVFSRC_EVENT_FORCE_ON (SPM_BASE + 0x694) +#define DVFSRC_EVENT_SEL (SPM_BASE + 0x698) +#define SPM_DVFS_EVENT_STA (SPM_BASE + 0x69C) +#define SPM_DVFS_EVENT_STA1 (SPM_BASE + 0x6A0) +#define SPM_DVFS_LEVEL (SPM_BASE + 0x6A4) +#define DVFS_ABORT_STA (SPM_BASE + 0x6A8) +#define DVFS_ABORT_OTHERS_MASK (SPM_BASE + 0x6AC) +#define SPM_DFS_LEVEL (SPM_BASE + 0x6B0) +#define SPM_DVS_LEVEL (SPM_BASE + 0x6B4) +#define SPM_DVFS_MISC (SPM_BASE + 0x6B8) +#define SPARE_SRC_REQ_MASK (SPM_BASE + 0x6C0) +#define SCP_VCORE_LEVEL (SPM_BASE + 0x6C4) +#define SC_MM_CK_SEL_CON (SPM_BASE + 0x6C8) +#define SPARE_ACK_STA (SPM_BASE + 0x6F0) +#define SPARE_ACK_MASK (SPM_BASE + 0x6F4) +#define SPM_DVFS_CON1 (SPM_BASE + 0x700) +#define SPM_DVFS_CON1_STA (SPM_BASE + 0x704) +#define SPM_DVFS_CMD0 (SPM_BASE + 0x710) +#define SPM_DVFS_CMD1 (SPM_BASE + 0x714) +#define SPM_DVFS_CMD2 (SPM_BASE + 0x718) +#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C) +#define SPM_DVFS_CMD4 (SPM_BASE + 0x720) +#define SPM_DVFS_CMD5 (SPM_BASE + 0x724) +#define SPM_DVFS_CMD6 (SPM_BASE + 0x728) +#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C) +#define SPM_DVFS_CMD8 (SPM_BASE + 0x730) +#define SPM_DVFS_CMD9 (SPM_BASE + 0x734) +#define SPM_DVFS_CMD10 (SPM_BASE + 0x738) +#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C) +#define SPM_DVFS_CMD12 (SPM_BASE + 0x740) +#define SPM_DVFS_CMD13 (SPM_BASE + 0x744) +#define SPM_DVFS_CMD14 (SPM_BASE + 0x748) +#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C) +#define WDT_LATCH_SPARE0_FIX (SPM_BASE + 0x780) +#define WDT_LATCH_SPARE1_FIX (SPM_BASE + 0x784) +#define WDT_LATCH_SPARE2_FIX (SPM_BASE + 0x788) +#define WDT_LATCH_SPARE3_FIX (SPM_BASE + 0x78C) +#define SPARE_ACK_IN_FIX (SPM_BASE + 0x790) +#define DCHA_LATCH_RSV0_FIX (SPM_BASE + 0x794) +#define DCHB_LATCH_RSV0_FIX (SPM_BASE + 0x798) +#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800) +#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804) +#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808) +#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C) +#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810) +#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814) +#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818) +#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C) +#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820) +#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824) +#define WDT_LATCH_SPARE0 (SPM_BASE + 0x828) +#define WDT_LATCH_SPARE1 (SPM_BASE + 0x82C) +#define WDT_LATCH_SPARE2 (SPM_BASE + 0x830) +#define WDT_LATCH_SPARE3 (SPM_BASE + 0x834) +#define PCM_WDT_LATCH_10 (SPM_BASE + 0x838) +#define PCM_WDT_LATCH_11 (SPM_BASE + 0x83C) +#define DCHA_GATING_LATCH_0 (SPM_BASE + 0x840) +#define DCHA_GATING_LATCH_1 (SPM_BASE + 0x844) +#define DCHA_GATING_LATCH_2 (SPM_BASE + 0x848) +#define DCHA_GATING_LATCH_3 (SPM_BASE + 0x84C) +#define DCHA_GATING_LATCH_4 (SPM_BASE + 0x850) +#define DCHA_GATING_LATCH_5 (SPM_BASE + 0x854) +#define DCHA_GATING_LATCH_6 (SPM_BASE + 0x858) +#define DCHA_GATING_LATCH_7 (SPM_BASE + 0x85C) +#define DCHB_GATING_LATCH_0 (SPM_BASE + 0x860) +#define DCHB_GATING_LATCH_1 (SPM_BASE + 0x864) +#define DCHB_GATING_LATCH_2 (SPM_BASE + 0x868) +#define DCHB_GATING_LATCH_3 (SPM_BASE + 0x86C) +#define DCHB_GATING_LATCH_4 (SPM_BASE + 0x870) +#define DCHB_GATING_LATCH_5 (SPM_BASE + 0x874) +#define DCHB_GATING_LATCH_6 (SPM_BASE + 0x878) +#define DCHB_GATING_LATCH_7 (SPM_BASE + 0x87C) +#define DCHA_LATCH_RSV0 (SPM_BASE + 0x880) +#define DCHB_LATCH_RSV0 (SPM_BASE + 0x884) +#define PCM_WDT_LATCH_12 (SPM_BASE + 0x888) +#define PCM_WDT_LATCH_13 (SPM_BASE + 0x88C) +#define SPM_PC_TRACE_CON (SPM_BASE + 0x8C0) +#define SPM_PC_TRACE_G0 (SPM_BASE + 0x8C4) +#define SPM_PC_TRACE_G1 (SPM_BASE + 0x8C8) +#define SPM_PC_TRACE_G2 (SPM_BASE + 0x8CC) +#define SPM_PC_TRACE_G3 (SPM_BASE + 0x8D0) +#define SPM_PC_TRACE_G4 (SPM_BASE + 0x8D4) +#define SPM_PC_TRACE_G5 (SPM_BASE + 0x8D8) +#define SPM_PC_TRACE_G6 (SPM_BASE + 0x8DC) +#define SPM_PC_TRACE_G7 (SPM_BASE + 0x8E0) +#define SPM_ACK_CHK_CON (SPM_BASE + 0x900) +#define SPM_ACK_CHK_PC (SPM_BASE + 0x904) +#define SPM_ACK_CHK_SEL (SPM_BASE + 0x908) +#define SPM_ACK_CHK_TIMER (SPM_BASE + 0x90C) +#define SPM_ACK_CHK_STA (SPM_BASE + 0x910) +#define SPM_ACK_CHK_LATCH (SPM_BASE + 0x914) +#define SPM_ACK_CHK_CON2 (SPM_BASE + 0x920) +#define SPM_ACK_CHK_PC2 (SPM_BASE + 0x924) +#define SPM_ACK_CHK_SEL2 (SPM_BASE + 0x928) +#define SPM_ACK_CHK_TIMER2 (SPM_BASE + 0x92C) +#define SPM_ACK_CHK_STA2 (SPM_BASE + 0x930) +#define SPM_ACK_CHK_LATCH2 (SPM_BASE + 0x934) +#define SPM_ACK_CHK_CON3 (SPM_BASE + 0x940) +#define SPM_ACK_CHK_PC3 (SPM_BASE + 0x944) +#define SPM_ACK_CHK_SEL3 (SPM_BASE + 0x948) +#define SPM_ACK_CHK_TIMER3 (SPM_BASE + 0x94C) +#define SPM_ACK_CHK_STA3 (SPM_BASE + 0x950) +#define SPM_ACK_CHK_LATCH3 (SPM_BASE + 0x954) +#define SPM_ACK_CHK_CON4 (SPM_BASE + 0x960) +#define SPM_ACK_CHK_PC4 (SPM_BASE + 0x964) +#define SPM_ACK_CHK_SEL4 (SPM_BASE + 0x968) +#define SPM_ACK_CHK_TIMER4 (SPM_BASE + 0x96C) +#define SPM_ACK_CHK_STA4 (SPM_BASE + 0x970) +#define SPM_ACK_CHK_LATCH4 (SPM_BASE + 0x974) + +/* POWERON_CONFIG_EN (0x10006000+0x000) */ +#define BCLK_CG_EN_LSB (1U << 0) /* 1b */ +#define MD_BCLK_CG_EN_LSB (1U << 1) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_POWER_ON_VAL0 (0x10006000+0x004) */ +#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */ +/* SPM_POWER_ON_VAL1 (0x10006000+0x008) */ +#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */ +/* SPM_CLK_CON (0x10006000+0x00C) */ +#define SYSCLK0_EN_CTRL_LSB (1U << 0) /* 2b */ +#define SYSCLK1_EN_CTRL_LSB (1U << 2) /* 2b */ +#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */ +#define SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */ +#define EXT_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */ +#define CXO32K_REMOVE_EN_MD1_LSB (1U << 9) /* 1b */ +#define CXO32K_REMOVE_EN_MD2_LSB (1U << 10) /* 1b */ +#define CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */ +#define CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */ +#define SRCLKEN0_EN_LSB (1U << 13) /* 1b */ +#define SRCLKEN1_EN_LSB (1U << 14) /* 1b */ +#define SCP_DCM_EN_LSB (1U << 15) /* 1b */ +#define SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 7b */ +#define SYSCLK1_SRC_MASK_B_LSB (1U << 23) /* 7b */ +/* SPM_CLK_SETTLE (0x10006000+0x010) */ +#define SYSCLK_SETTLE_LSB (1U << 0) /* 28b */ +/* SPM_AP_STANDBY_CON (0x10006000+0x014) */ +#define WFI_OP_LSB (1U << 0) /* 1b */ +#define MP0_CPUTOP_IDLE_MASK_LSB (1U << 1) /* 1b */ +#define MP1_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */ +#define MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */ +#define MM_MASK_B_LSB (1U << 16) /* 2b */ +#define MD_DDR_EN_0_DBC_EN_LSB (1U << 18) /* 1b */ +#define MD_DDR_EN_1_DBC_EN_LSB (1U << 19) /* 1b */ +#define MD_MASK_B_LSB (1U << 20) /* 2b */ +#define SSPM_MASK_B_LSB (1U << 22) /* 1b */ +#define SCP_MASK_B_LSB (1U << 23) /* 1b */ +#define SRCCLKENI_MASK_B_LSB (1U << 24) /* 1b */ +#define MD_APSRC_1_SEL_LSB (1U << 25) /* 1b */ +#define MD_APSRC_0_SEL_LSB (1U << 26) /* 1b */ +#define CONN_DDR_EN_DBC_EN_LSB (1U << 27) /* 1b */ +#define CONN_MASK_B_LSB (1U << 28) /* 1b */ +#define CONN_APSRC_SEL_LSB (1U << 29) /* 1b */ +/* PCM_CON0 (0x10006000+0x018) */ +#define PCM_KICK_L_LSB (1U << 0) /* 1b */ +#define IM_KICK_L_LSB (1U << 1) /* 1b */ +#define PCM_CK_EN_LSB (1U << 2) /* 1b */ +#define EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */ +#define IM_AUTO_PDN_EN_LSB (1U << 4) /* 1b */ +#define PCM_SW_RESET_LSB (1U << 15) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* PCM_CON1 (0x10006000+0x01C) */ +#define IM_SLAVE_LSB (1U << 0) /* 1b */ +#define IM_SLEEP_LSB (1U << 1) /* 1b */ +#define MIF_APBEN_LSB (1U << 3) /* 1b */ +#define IM_PDN_LSB (1U << 4) /* 1b */ +#define PCM_TIMER_EN_LSB (1U << 5) /* 1b */ +#define IM_NONRP_EN_LSB (1U << 6) /* 1b */ +#define DIS_MIF_PROT_LSB (1U << 7) /* 1b */ +#define PCM_WDT_EN_LSB (1U << 8) /* 1b */ +#define PCM_WDT_WAKE_MODE_LSB (1U << 9) /* 1b */ +#define SPM_SRAM_SLEEP_B_LSB (1U << 10) /* 1b */ +#define SPM_SRAM_ISOINT_B_LSB (1U << 11) /* 1b */ +#define EVENT_LOCK_EN_LSB (1U << 12) /* 1b */ +#define SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */ +#define SCP_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* PCM_IM_PTR (0x10006000+0x020) */ +#define PCM_IM_PTR_LSB (1U << 0) /* 32b */ +/* PCM_IM_LEN (0x10006000+0x024) */ +#define PCM_IM_LEN_LSB (1U << 0) /* 13b */ +/* PCM_REG_DATA_INI (0x10006000+0x028) */ +#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */ +/* PCM_PWR_IO_EN (0x10006000+0x02C) */ +#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */ +#define PCM_RF_SYNC_EN_LSB (1U << 16) /* 8b */ +/* PCM_TIMER_VAL (0x10006000+0x030) */ +#define PCM_TIMER_VAL_LSB (1U << 0) /* 32b */ +/* PCM_WDT_VAL (0x10006000+0x034) */ +#define PCM_WDT_VAL_LSB (1U << 0) /* 32b */ +/* PCM_IM_HOST_RW_PTR (0x10006000+0x038) */ +#define PCM_IM_HOST_RW_PTR_LSB (1U << 0) /* 12b */ +#define PCM_IM_HOST_W_EN_LSB (1U << 30) /* 1b */ +#define PCM_IM_HOST_EN_LSB (1U << 31) /* 1b */ +/* PCM_IM_HOST_RW_DAT (0x10006000+0x03C) */ +#define PCM_IM_HOST_RW_DAT_LSB (1U << 0) /* 32b */ +/* PCM_EVENT_VECTOR0 (0x10006000+0x040) */ +#define PCM_EVENT_VECTOR_0_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_0_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_0_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_0_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR1 (0x10006000+0x044) */ +#define PCM_EVENT_VECTOR_1_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_1_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_1_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_1_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR2 (0x10006000+0x048) */ +#define PCM_EVENT_VECTOR_2_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_2_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_2_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_2_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR3 (0x10006000+0x04C) */ +#define PCM_EVENT_VECTOR_3_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_3_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_3_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_3_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR4 (0x10006000+0x050) */ +#define PCM_EVENT_VECTOR_4_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_4_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_4_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_4_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR5 (0x10006000+0x054) */ +#define PCM_EVENT_VECTOR_5_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_5_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_5_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_5_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR6 (0x10006000+0x058) */ +#define PCM_EVENT_VECTOR_6_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_6_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_6_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_6_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR7 (0x10006000+0x05C) */ +#define PCM_EVENT_VECTOR_7_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_7_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_7_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_7_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR8 (0x10006000+0x060) */ +#define PCM_EVENT_VECTOR_8_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_8_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_8_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_8_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR9 (0x10006000+0x064) */ +#define PCM_EVENT_VECTOR_9_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_9_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_9_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_9_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR10 (0x10006000+0x068) */ +#define PCM_EVENT_VECTOR_10_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_10_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_10_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_10_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR11 (0x10006000+0x06C) */ +#define PCM_EVENT_VECTOR_11_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_11_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_11_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_11_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR12 (0x10006000+0x070) */ +#define PCM_EVENT_VECTOR_12_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_12_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_12_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_12_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR13 (0x10006000+0x074) */ +#define PCM_EVENT_VECTOR_13_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_13_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_13_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_13_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR14 (0x10006000+0x078) */ +#define PCM_EVENT_VECTOR_14_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_14_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_14_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_14_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR15 (0x10006000+0x07C) */ +#define PCM_EVENT_VECTOR_15_LSB (1U << 0) /* 6b */ +#define PCM_EVENT_RESUME_15_LSB (1U << 6) /* 1b */ +#define PCM_EVENT_IMMEDIA_15_LSB (1U << 7) /* 1b */ +#define PCM_EVENT_VECTPC_15_LSB (1U << 16) /* 11b */ +/* PCM_EVENT_VECTOR_EN (0x10006000+0x080) */ +#define PCM_EVENT_VECTOR_EN_LSB (1U << 0) /* 16b */ +/* SPM_SRAM_RSV_CON (0x10006000+0x088) */ +#define SPM_SRAM_SLEEP_B_ECO_EN_LSB (1U << 0) /* 1b */ +/* SPM_SWINT (0x10006000+0x08C) */ +#define SPM_SWINT_LSB (1U << 0) /* 10b */ +/* SPM_SWINT_SET (0x10006000+0x090) */ +#define SPM_SWINT_SET_LSB (1U << 0) /* 10b */ +/* SPM_SWINT_CLR (0x10006000+0x094) */ +#define SPM_SWINT_CLR_LSB (1U << 0) /* 10b */ +/* SPM_SCP_MAILBOX (0x10006000+0x098) */ +#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */ +/* SCP_SPM_MAILBOX (0x10006000+0x09C) */ +#define SCP_SPM_MAILBOX_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CON (0x10006000+0x0A0) */ +#define TWAM_ENABLE_LSB (1U << 0) /* 1b */ +#define TWAM_SPEED_MODE_ENABLE_LSB (1U << 1) /* 1b */ +#define TWAM_SW_RST_LSB (1U << 2) /* 1b */ +#define TWAM_MON_TYPE0_LSB (1U << 4) /* 2b */ +#define TWAM_MON_TYPE1_LSB (1U << 6) /* 2b */ +#define TWAM_MON_TYPE2_LSB (1U << 8) /* 2b */ +#define TWAM_MON_TYPE3_LSB (1U << 10) /* 2b */ +#define TWAM_SIGNAL_SEL0_LSB (1U << 12) /* 5b */ +#define TWAM_SIGNAL_SEL1_LSB (1U << 17) /* 5b */ +#define TWAM_SIGNAL_SEL2_LSB (1U << 22) /* 5b */ +#define TWAM_SIGNAL_SEL3_LSB (1U << 27) /* 5b */ +/* SPM_TWAM_WINDOW_LEN (0x10006000+0x0A4) */ +#define TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_IDLE_SEL (0x10006000+0x0A8) */ +#define TWAM_IDLE_SEL_LSB (1U << 0) /* 5b */ +/* SPM_SCP_IRQ (0x10006000+0x0AC) */ +#define SPM_SCP_IRQ_LSB (1U << 0) /* 1b */ +#define SPM_SCP_IRQ_SEL_LSB (1U << 4) /* 1b */ +/* SPM_CPU_WAKEUP_EVENT (0x10006000+0x0B0) */ +#define SPM_CPU_WAKEUP_EVENT_LSB (1U << 0) /* 1b */ +/* SPM_IRQ_MASK (0x10006000+0x0B4) */ +#define SPM_TWAM_IRQ_MASK_LSB (1U << 2) /* 1b */ +#define PCM_IRQ_ROOT_MASK_LSB (1U << 3) /* 1b */ +#define SPM_IRQ_MASK_LSB (1U << 8) /* 10b */ +/* SPM_SRC_REQ (0x10006000+0x0B8) */ +#define SPM_APSRC_REQ_LSB (1U << 0) /* 1b */ +#define SPM_F26M_REQ_LSB (1U << 1) /* 1b */ +#define SPM_INFRA_REQ_LSB (1U << 3) /* 1b */ +#define SPM_VRF18_REQ_LSB (1U << 4) /* 1b */ +#define SPM_DDREN_REQ_LSB (1U << 7) /* 1b */ +#define SPM_RSV_SRC_REQ_LSB (1U << 8) /* 3b */ +#define SPM_DDREN_2_REQ_LSB (1U << 11) /* 1b */ +#define CPU_MD_DVFS_SOP_FORCE_ON_LSB (1U << 16) /* 1b */ +/* SPM_SRC_MASK (0x10006000+0x0BC) */ +#define CSYSPWREQ_MASK_LSB (1U << 0) /* 1b */ +#define CCIF0_MD_EVENT_MASK_B_LSB (1U << 1) /* 1b */ +#define CCIF0_AP_EVENT_MASK_B_LSB (1U << 2) /* 1b */ +#define CCIF1_MD_EVENT_MASK_B_LSB (1U << 3) /* 1b */ +#define CCIF1_AP_EVENT_MASK_B_LSB (1U << 4) /* 1b */ +#define CCIF2_MD_EVENT_MASK_B_LSB (1U << 5) /* 1b */ +#define CCIF2_AP_EVENT_MASK_B_LSB (1U << 6) /* 1b */ +#define CCIF3_MD_EVENT_MASK_B_LSB (1U << 7) /* 1b */ +#define CCIF3_AP_EVENT_MASK_B_LSB (1U << 8) /* 1b */ +#define MD_SRCCLKENA_0_INFRA_MASK_B_LSB (1U << 9) /* 1b */ +#define MD_SRCCLKENA_1_INFRA_MASK_B_LSB (1U << 10) /* 1b */ +#define CONN_SRCCLKENA_INFRA_MASK_B_LSB (1U << 11) /* 1b */ +#define UFS_INFRA_REQ_MASK_B_LSB (1U << 12) /* 1b */ +#define SRCCLKENI_INFRA_MASK_B_LSB (1U << 13) /* 1b */ +#define MD_APSRC_REQ_0_INFRA_MASK_B_LSB (1U << 14) /* 1b */ +#define MD_APSRC_REQ_1_INFRA_MASK_B_LSB (1U << 15) /* 1b */ +#define CONN_APSRCREQ_INFRA_MASK_B_LSB (1U << 16) /* 1b */ +#define UFS_SRCCLKENA_MASK_B_LSB (1U << 17) /* 1b */ +#define MD_VRF18_REQ_0_MASK_B_LSB (1U << 18) /* 1b */ +#define MD_VRF18_REQ_1_MASK_B_LSB (1U << 19) /* 1b */ +#define UFS_VRF18_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define GCE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define CONN_INFRA_REQ_MASK_B_LSB (1U << 22) /* 1b */ +#define GCE_APSRC_REQ_MASK_B_LSB (1U << 23) /* 1b */ +#define DISP0_APSRC_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define DISP1_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define MFG_REQ_MASK_B_LSB (1U << 26) /* 1b */ +#define VDEC_REQ_MASK_B_LSB (1U << 27) /* 1b */ +/* SPM_SRC2_MASK (0x10006000+0x0C0) */ +#define MD_DDR_EN_0_MASK_B_LSB (1U << 0) /* 1b */ +#define MD_DDR_EN_1_MASK_B_LSB (1U << 1) /* 1b */ +#define CONN_DDR_EN_MASK_B_LSB (1U << 2) /* 1b */ +#define DDREN_SSPM_APSRC_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define DDREN_SCP_APSRC_REQ_MASK_B_LSB (1U << 4) /* 1b */ +#define DISP0_DDREN_MASK_B_LSB (1U << 5) /* 1b */ +#define DISP1_DDREN_MASK_B_LSB (1U << 6) /* 1b */ +#define GCE_DDREN_MASK_B_LSB (1U << 7) /* 1b */ +#define DDREN_EMI_SELF_REFRESH_CH0_MASK_B_LSB (1U << 8) /* 1b */ +#define DDREN_EMI_SELF_REFRESH_CH1_MASK_B_LSB (1U << 9) /* 1b */ +/* SPM_WAKEUP_EVENT_MASK (0x10006000+0x0C4) */ +#define SPM_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000+0x0C8) */ +#define SPM_WAKEUP_EVENT_EXT_MASK_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_EVENT_CLEAR (0x10006000+0x0CC) */ +#define SPM_TWAM_EVENT_CLEAR_LSB (1U << 0) /* 1b */ +/* SCP_CLK_CON (0x10006000+0x0D0) */ +#define SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */ +#define SCP_SECURE_V_REQ_MASK_LSB (1U << 1) /* 1b */ +#define SCP_SLP_REQ_LSB (1U << 2) /* 1b */ +#define SCP_SLP_ACK_LSB (1U << 3) /* 1b */ +/* PCM_DEBUG_CON (0x10006000+0x0D4) */ +#define PCM_DEBUG_OUT_ENABLE_LSB (1U << 0) /* 1b */ +/* DDR_EN_DBC_LEN (0x10006000+0x0D8) */ +#define MD_DDR_EN_0_DBC_LEN_LSB (1U << 0) /* 10b */ +#define MD_DDR_EN_1_DBC_LEN_LSB (1U << 10) /* 10b */ +#define CONN_DDR_EN_DBC_LEN_LSB (1U << 20) /* 10b */ +/* AHB_BUS_CON (0x10006000+0x0DC) */ +#define AHB_HADDR_EXT_LSB (1U << 0) /* 2b */ +#define REG_AHB_LOCK_LSB (1U << 8) /* 1b */ +/* SPM_SRC3_MASK (0x10006000+0x0E0) */ +#define MD_DDR_EN_2_0_MASK_B_LSB (1U << 0) /* 1b */ +#define MD_DDR_EN_2_1_MASK_B_LSB (1U << 1) /* 1b */ +#define CONN_DDR_EN_2_MASK_B_LSB (1U << 2) /* 1b */ +#define DDREN2_SSPM_APSRC_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define DDREN2_SCP_APSRC_REQ_MASK_B_LSB (1U << 4) /* 1b */ +#define DISP0_DDREN2_MASK_B_LSB (1U << 5) /* 1b */ +#define DISP1_DDREN2_MASK_B_LSB (1U << 6) /* 1b */ +#define GCE_DDREN2_MASK_B_LSB (1U << 7) /* 1b */ +#define DDREN2_EMI_SELF_REFRESH_CH0_MASK_B_LSB (1U << 8) /* 1b */ +#define DDREN2_EMI_SELF_REFRESH_CH1_MASK_B_LSB (1U << 9) /* 1b */ +/* DDR_EN_EMI_DBC_CON (0x10006000+0x0E4) */ +#define EMI_SELF_REFRESH_CH0_DBC_LEN_LSB (1U << 0) /* 10b */ +#define EMI_SELF_REFRESH_CH0_DBC_EN_LSB (1U << 10) /* 1b */ +#define EMI_SELF_REFRESH_CH1_DBC_LEN_LSB (1U << 16) /* 10b */ +#define EMI_SELF_REFRESH_CH1_DBC_EN_LSB (1U << 26) /* 1b */ +/* SSPM_CLK_CON (0x10006000+0x0E8) */ +#define SSPM_26M_CK_SEL_LSB (1U << 0) /* 1b */ +/* PCM_REG0_DATA (0x10006000+0x100) */ +#define PCM_REG0_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG1_DATA (0x10006000+0x104) */ +#define PCM_REG1_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG2_DATA (0x10006000+0x108) */ +#define PCM_REG2_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG3_DATA (0x10006000+0x10C) */ +#define PCM_REG3_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG4_DATA (0x10006000+0x110) */ +#define PCM_REG4_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG5_DATA (0x10006000+0x114) */ +#define PCM_REG5_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG6_DATA (0x10006000+0x118) */ +#define PCM_REG6_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG7_DATA (0x10006000+0x11C) */ +#define PCM_REG7_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG8_DATA (0x10006000+0x120) */ +#define PCM_REG8_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG9_DATA (0x10006000+0x124) */ +#define PCM_REG9_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG10_DATA (0x10006000+0x128) */ +#define PCM_REG10_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG11_DATA (0x10006000+0x12C) */ +#define PCM_REG11_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG12_DATA (0x10006000+0x130) */ +#define PCM_REG12_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG13_DATA (0x10006000+0x134) */ +#define PCM_REG13_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG14_DATA (0x10006000+0x138) */ +#define PCM_REG14_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG15_DATA (0x10006000+0x13C) */ +#define PCM_REG15_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG12_MASK_B_STA (0x10006000+0x140) */ +#define PCM_REG12_MASK_B_STA_LSB (1U << 0) /* 32b */ +/* PCM_REG12_EXT_DATA (0x10006000+0x144) */ +#define PCM_REG12_EXT_DATA_LSB (1U << 0) /* 32b */ +/* PCM_REG12_EXT_MASK_B_STA (0x10006000+0x148) */ +#define PCM_REG12_EXT_MASK_B_STA_LSB (1U << 0) /* 32b */ +/* PCM_EVENT_REG_STA (0x10006000+0x14C) */ +#define PCM_EVENT_REG_STA_LSB (1U << 0) /* 32b */ +/* PCM_TIMER_OUT (0x10006000+0x150) */ +#define PCM_TIMER_OUT_LSB (1U << 0) /* 32b */ +/* PCM_WDT_OUT (0x10006000+0x154) */ +#define PCM_WDT_OUT_LSB (1U << 0) /* 32b */ +/* SPM_IRQ_STA (0x10006000+0x158) */ +#define SPM_ACK_CHK_WAKEUP_LSB (1U << 1) /* 1b */ +#define TWAM_IRQ_LSB (1U << 2) /* 1b */ +#define PCM_IRQ_LSB (1U << 3) /* 1b */ +/* #define SPM_SWINT_LSB (1U << 4) */ /* 10b */ +/* SPM_WAKEUP_STA (0x10006000+0x15C) */ +#define SPM_WAKEUP_EVENT_STA_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_EXT_STA (0x10006000+0x160) */ +#define SPM_WAKEUP_EVENT_EXT_STA_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_MISC (0x10006000+0x164) */ +#define SPM_WAKEUP_EVENT_MISC_LSB (1U << 0) /* 30b */ +#define SPM_PWRAP_IRQ_ACK_LSB (1U << 30) /* 1b */ +#define SPM_PWRAP_IRQ_LSB (1U << 31) /* 1b */ +/* BUS_PROTECT_RDY (0x10006000+0x168) */ +#define BUS_PROTECT_RDY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT2_RDY (0x10006000+0x16C) */ +#define BUS_PROTECT2_RDY_LSB (1U << 0) /* 32b */ +/* SUBSYS_IDLE_STA (0x10006000+0x170) */ +#define SUBSYS_IDLE_STA_LSB (1U << 0) /* 32b */ +/* CPU_IDLE_STA (0x10006000+0x174) */ +#define MP0_CPU0_STANDBYWFI_AFTER_SEL_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_STANDBYWFI_AFTER_SEL_LSB (1U << 1) /* 1b */ +#define MP0_CPU2_STANDBYWFI_AFTER_SEL_LSB (1U << 2) /* 1b */ +#define MP0_CPU3_STANDBYWFI_AFTER_SEL_LSB (1U << 3) /* 1b */ +#define MP1_CPU0_STANDBYWFI_AFTER_SEL_LSB (1U << 4) /* 1b */ +#define MP1_CPU1_STANDBYWFI_AFTER_SEL_LSB (1U << 5) /* 1b */ +#define MP1_CPU2_STANDBYWFI_AFTER_SEL_LSB (1U << 6) /* 1b */ +#define MP1_CPU3_STANDBYWFI_AFTER_SEL_LSB (1U << 7) /* 1b */ +#define MP0_CPU0_STANDBYWFI_LSB (1U << 10) /* 1b */ +#define MP0_CPU1_STANDBYWFI_LSB (1U << 11) /* 1b */ +#define MP0_CPU2_STANDBYWFI_LSB (1U << 12) /* 1b */ +#define MP0_CPU3_STANDBYWFI_LSB (1U << 13) /* 1b */ +#define MP1_CPU0_STANDBYWFI_LSB (1U << 14) /* 1b */ +#define MP1_CPU1_STANDBYWFI_LSB (1U << 15) /* 1b */ +#define MP1_CPU2_STANDBYWFI_LSB (1U << 16) /* 1b */ +#define MP1_CPU3_STANDBYWFI_LSB (1U << 17) /* 1b */ +#define MP0_CPUTOP_IDLE_LSB (1U << 20) /* 1b */ +#define MP1_CPUTOP_IDLE_LSB (1U << 21) /* 1b */ +#define MCU_BIU_IDLE_LSB (1U << 22) /* 1b */ +#define MCUSYS_IDLE_LSB (1U << 23) /* 1b */ +/* PCM_FSM_STA (0x10006000+0x178) */ +#define EXEC_INST_OP_LSB (1U << 0) /* 4b */ +#define PC_STATE_LSB (1U << 4) /* 3b */ +#define IM_STATE_LSB (1U << 7) /* 3b */ +#define MASTER_STATE_LSB (1U << 10) /* 5b */ +#define EVENT_FSM_LSB (1U << 15) /* 3b */ +#define PCM_CLK_SEL_STA_LSB (1U << 18) /* 3b */ +#define PCM_KICK_LSB (1U << 21) /* 1b */ +#define IM_KICK_LSB (1U << 22) /* 1b */ +#define EXT_SRCCLKEN_STA_LSB (1U << 23) /* 2b */ +#define EXT_SRCVOLTEN_STA_LSB (1U << 25) /* 1b */ +/* SRC_REQ_STA (0x10006000+0x17C) */ +#define SRC_REQ_STA_LSB (1U << 0) /* 32b */ +/* PWR_STATUS (0x10006000+0x180) */ +#define PWR_STATUS_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_2ND (0x10006000+0x184) */ +#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */ +/* CPU_PWR_STATUS (0x10006000+0x188) */ +#define CPU_PWR_STATUS_LSB (1U << 0) /* 32b */ +/* CPU_PWR_STATUS_2ND (0x10006000+0x18C) */ +#define CPU_PWR_STATUS_2ND_LSB (1U << 0) /* 32b */ +/* MISC_STA (0x10006000+0x190) */ +#define MM_DVFS_HALT_AF_MASK_LSB (1U << 0) /* 5b */ +/* SPM_SRC_RDY_STA (0x10006000+0x194) */ +#define SPM_INFRA_SRC_ACK_LSB (1U << 0) /* 1b */ +#define SPM_VRF18_SRC_ACK_LSB (1U << 1) /* 1b */ +/* DRAMC_DBG_LATCH (0x10006000+0x19C) */ +#define DRAMC_DEBUG_LATCH_STATUS_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA0 (0x10006000+0x1A0) */ +#define SPM_TWAM_LAST_STA0_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA1 (0x10006000+0x1A4) */ +#define SPM_TWAM_LAST_STA1_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA2 (0x10006000+0x1A8) */ +#define SPM_TWAM_LAST_STA2_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA3 (0x10006000+0x1AC) */ +#define SPM_TWAM_LAST_STA3_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA0 (0x10006000+0x1B0) */ +#define SPM_TWAM_CURR_STA0_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA1 (0x10006000+0x1B4) */ +#define SPM_TWAM_CURR_STA1_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA2 (0x10006000+0x1B8) */ +#define SPM_TWAM_CURR_STA2_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA3 (0x10006000+0x1BC) */ +#define SPM_TWAM_CURR_STA3_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_TIMER_OUT (0x10006000+0x1C0) */ +#define SPM_TWAM_TIMER_OUT_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_STA (0x10006000+0x1C8) */ +#define MD_DVFS_ERROR_STATUS_LSB (1U << 0) /* 1b */ +/* BUS_PROTECT3_RDY (0x10006000+0x1CC) */ +#define BUS_PROTECT_MM_RDY_LSB (1U << 0) /* 16b */ +#define BUS_PROTECT_MCU_RDY_LSB (1U << 16) /* 16b */ +/* SRC_DDREN_STA (0x10006000+0x1E0) */ +#define SRC_DDREN_STA_LSB (1U << 0) /* 32b */ +/* MCU_PWR_CON (0x10006000+0x200) */ +#define MCU_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MCU_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MCU_PWR_ON_LSB (1U << 2) /* 1b */ +#define MCU_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MCU_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MCU_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MCU_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MCU_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MCU_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MCU_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MCU_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MCU_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP0_CPUTOP_PWR_CON (0x10006000+0x204) */ +#define MP0_CPUTOP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPUTOP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPUTOP_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPUTOP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPUTOP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPUTOP_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPUTOP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP0_CPUTOP_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP0_CPUTOP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP0_CPUTOP_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP0_CPUTOP_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP0_CPUTOP_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP0_CPU0_PWR_CON (0x10006000+0x208) */ +#define MP0_CPU0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPU0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPU0_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPU0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPU0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPU0_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPU0_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP0_CPU0_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP0_CPU0_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP0_CPU0_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP0_CPU0_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP0_CPU0_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP0_CPU1_PWR_CON (0x10006000+0x20C) */ +#define MP0_CPU1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPU1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPU1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPU1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPU1_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPU1_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP0_CPU1_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP0_CPU1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP0_CPU1_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP0_CPU1_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP0_CPU1_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP0_CPU2_PWR_CON (0x10006000+0x210) */ +#define MP0_CPU2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPU2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPU2_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPU2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPU2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPU2_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPU2_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP0_CPU2_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP0_CPU2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP0_CPU2_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP0_CPU2_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP0_CPU2_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP0_CPU3_PWR_CON (0x10006000+0x214) */ +#define MP0_CPU3_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP0_CPU3_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP0_CPU3_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP0_CPU3_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP0_CPU3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP0_CPU3_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP0_CPU3_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP0_CPU3_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP0_CPU3_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP0_CPU3_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP0_CPU3_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP0_CPU3_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP1_CPUTOP_PWR_CON (0x10006000+0x218) */ +#define MP1_CPUTOP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPUTOP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPUTOP_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPUTOP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPUTOP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPUTOP_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPUTOP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP1_CPUTOP_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP1_CPUTOP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP1_CPUTOP_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP1_CPUTOP_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP1_CPUTOP_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP1_CPU0_PWR_CON (0x10006000+0x21C) */ +#define MP1_CPU0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPU0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPU0_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPU0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPU0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPU0_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPU0_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP1_CPU0_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP1_CPU0_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP1_CPU0_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP1_CPU0_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP1_CPU0_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP1_CPU1_PWR_CON (0x10006000+0x220) */ +#define MP1_CPU1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPU1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPU1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPU1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPU1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPU1_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPU1_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP1_CPU1_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP1_CPU1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP1_CPU1_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP1_CPU1_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP1_CPU1_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP1_CPU2_PWR_CON (0x10006000+0x224) */ +#define MP1_CPU2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPU2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPU2_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPU2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPU2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPU2_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPU2_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP1_CPU2_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP1_CPU2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP1_CPU2_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP1_CPU2_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP1_CPU2_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP1_CPU3_PWR_CON (0x10006000+0x228) */ +#define MP1_CPU3_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MP1_CPU3_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MP1_CPU3_PWR_ON_LSB (1U << 2) /* 1b */ +#define MP1_CPU3_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MP1_CPU3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MP1_CPU3_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MP1_CPU3_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MP1_CPU3_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */ +#define MP1_CPU3_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MP1_CPU3_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */ +#define SC_MP1_CPU3_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */ +#define SC_MP1_CPU3_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */ +/* MP0_CPUTOP_L2_PDN (0x10006000+0x240) */ +#define MP0_CPUTOP_L2_SRAM_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPUTOP_L2_SRAM_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPUTOP_L2_SLEEP_B (0x10006000+0x244) */ +#define MP0_CPUTOP_L2_SRAM_SLEEP_B_LSB (1U << 0) /* 1b */ +#define MP0_CPUTOP_L2_SRAM_SLEEP_B_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPU0_L1_PDN (0x10006000+0x248) */ +#define MP0_CPU0_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPU0_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPU1_L1_PDN (0x10006000+0x24C) */ +#define MP0_CPU1_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPU2_L1_PDN (0x10006000+0x250) */ +#define MP0_CPU2_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPU2_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP0_CPU3_L1_PDN (0x10006000+0x254) */ +#define MP0_CPU3_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP0_CPU3_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPUTOP_L2_PDN (0x10006000+0x258) */ +#define MP1_CPUTOP_L2_SRAM_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPUTOP_L2_SRAM_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPUTOP_L2_SLEEP_B (0x10006000+0x25C) */ +#define MP1_CPUTOP_L2_SRAM_SLEEP_B_LSB (1U << 0) /* 1b */ +#define MP1_CPUTOP_L2_SRAM_SLEEP_B_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPU0_L1_PDN (0x10006000+0x260) */ +#define MP1_CPU0_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPU0_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPU1_L1_PDN (0x10006000+0x264) */ +#define MP1_CPU1_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPU1_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPU2_L1_PDN (0x10006000+0x268) */ +#define MP1_CPU2_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPU2_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* MP1_CPU3_L1_PDN (0x10006000+0x26C) */ +#define MP1_CPU3_L1_PDN_LSB (1U << 0) /* 1b */ +#define MP1_CPU3_L1_PDN_ACK_LSB (1U << 8) /* 1b */ +/* CPU_EXT_BUCK_ISO (0x10006000+0x290) */ +#define MP0_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +#define MP1_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */ +#define MP_EXT_BUCK_ISO_LSB (1U << 2) /* 1b */ +/* DUMMY1_PWR_CON (0x10006000+0x2B0) */ +#define DUMMY1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DUMMY1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DUMMY1_PWR_ON_LSB (1U << 2) /* 1b */ +#define DUMMY1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DUMMY1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* BYPASS_SPMC (0x10006000+0x2B4) */ +#define BYPASS_CPU_SPMC_MODE_LSB (1U << 0) /* 1b */ +/* SPMC_DORMANT_ENABLE (0x10006000+0x2B8) */ +#define MP0_SPMC_SRAM_DORMANT_EN_LSB (1U << 0) /* 1b */ +#define MP1_SPMC_SRAM_DORMANT_EN_LSB (1U << 1) /* 1b */ +/* ARMPLL_CLK_CON (0x10006000+0x2BC) */ +#define REG_SC_ARM_FHC_PAUSE_LSB (1U << 0) /* 3b */ +#define REG_SC_ARM_CLK_OFF_LSB (1U << 3) /* 3b */ +#define REG_SC_ARMPLLOUT_OFF_LSB (1U << 6) /* 3b */ +#define REG_SC_ARMPLL_OFF_LSB (1U << 9) /* 3b */ +#define REG_SC_ARMPLL_S_OFF_LSB (1U << 12) /* 3b */ +/* SPMC_IN_RET (0x10006000+0x2C0) */ +#define SPMC_STATUS_LSB (1U << 0) /* 8b */ +/* VDE_PWR_CON (0x10006000+0x300) */ +#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VDE_PWR_ON_LSB (1U << 2) /* 1b */ +#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VDE_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* VEN_PWR_CON (0x10006000+0x304) */ +#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VEN_PWR_ON_LSB (1U << 2) /* 1b */ +#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VEN_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* ISP_PWR_CON (0x10006000+0x308) */ +#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ISP_PWR_ON_LSB (1U << 2) /* 1b */ +#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ISP_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* DIS_PWR_CON (0x10006000+0x30C) */ +#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DIS_PWR_ON_LSB (1U << 2) /* 1b */ +#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DIS_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* MFG_CORE1_PWR_CON (0x10006000+0x310) */ +#define MFG_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG_CORE1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG_CORE1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG_CORE1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG_CORE1_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define MFG_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* AUDIO_PWR_CON (0x10006000+0x314) */ +#define AUD_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define AUD_PWR_ISO_LSB (1U << 1) /* 1b */ +#define AUD_PWR_ON_LSB (1U << 2) /* 1b */ +#define AUD_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define AUD_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define AUD_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define AUD_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* IFR_PWR_CON (0x10006000+0x318) */ +#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IFR_PWR_ON_LSB (1U << 2) /* 1b */ +#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IFR_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* DPY_PWR_CON (0x10006000+0x31C) */ +#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DPY_PWR_ON_LSB (1U << 2) /* 1b */ +#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DPY_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define DPY_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* MD1_PWR_CON (0x10006000+0x320) */ +#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MD1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */ +/* VPU_TOP_PWR_CON (0x10006000+0x324) */ +#define VPU_TOP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VPU_TOP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VPU_TOP_PWR_ON_LSB (1U << 2) /* 1b */ +#define VPU_TOP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VPU_TOP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VPU_TOP_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define VPU_TOP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define VPU_TOP_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define VPU_TOP_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +#define VPU_TOP_SRAM_SLPB_LSB (1U << 16) /* 4b */ +#define VPU_TOP_SRAM_SLPB_ACK_LSB (1U << 28) /* 4b */ +/* CONN_PWR_CON (0x10006000+0x32C) */ +#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CONN_PWR_ON_LSB (1U << 2) /* 1b */ +#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CONN_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define CONN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VPU_CORE2_PWR_CON (0x10006000+0x330) */ +#define VPU_CORE2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VPU_CORE2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VPU_CORE2_PWR_ON_LSB (1U << 2) /* 1b */ +#define VPU_CORE2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VPU_CORE2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VPU_CORE2_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define VPU_CORE2_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define VPU_CORE2_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define VPU_CORE2_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +#define VPU_CORE2_SRAM_SLPB_LSB (1U << 16) /* 4b */ +#define VPU_CORE2_SRAM_SLPB_ACK_LSB (1U << 28) /* 4b */ +/* MFG_ASYNC_PWR_CON (0x10006000+0x334) */ +#define MFG_ASYNC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG_ASYNC_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG_ASYNC_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG_ASYNC_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG_ASYNC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG_ASYNC_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define MFG_ASYNC_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* MFG_PWR_CON (0x10006000+0x338) */ +#define MFG_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define MFG_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* VPU_CORE0_PWR_CON (0x10006000+0x33C) */ +#define VPU_CORE0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VPU_CORE0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VPU_CORE0_PWR_ON_LSB (1U << 2) /* 1b */ +#define VPU_CORE0_ON_2ND_LSB (1U << 3) /* 1b */ +#define VPU_CORE0_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VPU_CORE0_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define VPU_CORE0_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define VPU_CORE0_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define VPU_CORE0_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +#define VPU_CORE0_SRAM_SLPB_LSB (1U << 16) /* 4b */ +#define VPU_CORE0_SRAM_SLPB_ACK_LSB (1U << 28) /* 4b */ +/* VPU_CORE1_PWR_CON (0x10006000+0x340) */ +#define VPU_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VPU_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VPU_CORE1_PWR_ON_LSB (1U << 2) /* 1b */ +#define VPU_CORE1_ON_2ND_LSB (1U << 3) /* 1b */ +#define VPU_CORE1_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VPU_CORE1_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define VPU_CORE1_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define VPU_CORE1_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define VPU_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +#define VPU_CORE1_SRAM_SLPB_LSB (1U << 16) /* 4b */ +#define VPU_CORE1_SRAM_SLPB_ACK_LSB (1U << 28) /* 4b */ +/* CAM_PWR_CON (0x10006000+0x344) */ +#define CAM_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define CAM_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* MFG_2D_PWR_CON (0x10006000+0x348) */ +#define MFG_2D_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG_2D_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG_2D_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG_2D_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG_2D_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG_2D_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define MFG_2D_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* MFG_CORE0_PWR_CON (0x10006000+0x34C) */ +#define MFG_CORE0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG_CORE0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG_CORE0_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG_CORE0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG_CORE0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG_CORE0_SRAM_PDN_LSB (1U << 8) /* 4b */ +#define MFG_CORE0_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */ +/* SYSRAM_CON (0x10006000+0x350) */ +#define IFR_SRAMROM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define IFR_SRAMROM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define IFR_SRAMROM_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */ +#define IFR_SRAMROM_SRAM_PDN_LSB (1U << 16) /* 8b */ +/* SYSROM_CON (0x10006000+0x354) */ +#define IFR_SRAMROM_ROM_PDN_LSB (1U << 0) /* 6b */ +/* SSPM_SRAM_CON (0x10006000+0x358) */ +#define SSPM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SSPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SSPM_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SSPM_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* SCP_SRAM_CON (0x10006000+0x35C) */ +#define SCP_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SCP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SCP_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* UFS_SRAM_CON (0x10006000+0x36C) */ +#define UFS_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define UFS_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define UFS_SRAM_SLEEP_B_LSB (1U << 4) /* 5b */ +#define UFS_SRAM_PDN_LSB (1U << 16) /* 5b */ +/* DUMMY_SRAM_CON (0x10006000+0x380) */ +#define DUMMY_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DUMMY_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DUMMY_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */ +#define DUMMY_SRAM_PDN_LSB (1U << 16) /* 8b */ +/* MD_EXT_BUCK_ISO_CON (0x10006000+0x390) */ +#define VMODEM_BUCK_ELS_EN_LSB (1U << 0) /* 1b */ +#define VMD_BUCK_ELS_EN_LSB (1U << 1) /* 1b */ +/* MD_SRAM_ISO_CON (0x10006000+0x394) */ +#define MD1_SRAM_ISOINT_B_LSB (1U << 0) /* 1b */ +/* MD_EXTRA_PWR_CON (0x10006000+0x398) */ +#define MD1_PWR_PROT_REQ_STA_LSB (1U << 0) /* 1b */ +#define MD2_PWR_PROT_REQ_STA_LSB (1U << 1) /* 1b */ +/* EXT_BUCK_CON (0x10006000+0x3A0) */ +#define RG_VA09_ON_LSB (1U << 0) /* 1b */ +/* MBIST_EFUSE_REPAIR_ACK_STA (0x10006000+0x3D0) */ +#define MBIST_EFUSE_REPAIR_ACK_STA_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CON (0x10006000+0x400) */ +#define SPM_DVFS_CON_LSB (1U << 0) /* 4b */ +#define SPM_DVFS_ACK_LSB (1U << 30) /* 2b */ +/* SPM_MDBSI_CON (0x10006000+0x404) */ +#define SPM_MDBSI_CON_LSB (1U << 0) /* 3b */ +/* SPM_MAS_PAUSE_MASK_B (0x10006000+0x408) */ +#define SPM_MAS_PAUSE_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_MAS_PAUSE2_MASK_B (0x10006000+0x40C) */ +#define SPM_MAS_PAUSE2_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BSI_GEN (0x10006000+0x410) */ +#define SPM_BSI_START_LSB (1U << 0) /* 1b */ +/* SPM_BSI_EN_SR (0x10006000+0x414) */ +#define SPM_BSI_EN_SR_LSB (1U << 0) /* 32b */ +/* SPM_BSI_CLK_SR (0x10006000+0x418) */ +#define SPM_BSI_CLK_SR_LSB (1U << 0) /* 32b */ +/* SPM_BSI_D0_SR (0x10006000+0x41C) */ +#define SPM_BSI_D0_SR_LSB (1U << 0) /* 32b */ +/* SPM_BSI_D1_SR (0x10006000+0x420) */ +#define SPM_BSI_D1_SR_LSB (1U << 0) /* 32b */ +/* SPM_BSI_D2_SR (0x10006000+0x424) */ +#define SPM_BSI_D2_SR_LSB (1U << 0) /* 32b */ +/* SPM_AP_SEMA (0x10006000+0x428) */ +#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */ +/* SPM_SPM_SEMA (0x10006000+0x42C) */ +#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */ +/* AP_MDSRC_REQ (0x10006000+0x430) */ +#define AP_MDSMSRC_REQ_LSB (1U << 0) /* 1b */ +#define AP_L1SMSRC_REQ_LSB (1U << 1) /* 1b */ +#define AP_MD2SRC_REQ_LSB (1U << 2) /* 1b */ +#define AP_MDSMSRC_ACK_LSB (1U << 4) /* 1b */ +#define AP_L1SMSRC_ACK_LSB (1U << 5) /* 1b */ +#define AP_MD2SRC_ACK_LSB (1U << 6) /* 1b */ +/* SPM2MD_DVFS_CON (0x10006000+0x438) */ +#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 32b */ +/* MD2SPM_DVFS_CON (0x10006000+0x43C) */ +#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 32b */ +/* DRAMC_DPY_CLK_SW_CON_RSV (0x10006000+0x440) */ +#define SPM2DRAMC_SHUFFLE_START_LSB (1U << 0) /* 1b */ +#define SPM2DRAMC_SHUFFLE_SWITCH_LSB (1U << 1) /* 1b */ +#define SPM2DPY_DIV2_SYNC_LSB (1U << 2) /* 1b */ +#define SPM2DPY_1PLL_SWITCH_LSB (1U << 3) /* 1b */ +#define SPM2DPY_TEST_CK_MUX_LSB (1U << 4) /* 1b */ +#define SPM2DPY_ASYNC_MODE_LSB (1U << 5) /* 1b */ +#define SPM2TOP_ASYNC_MODE_LSB (1U << 6) /* 1b */ +/* DPY_LP_CON (0x10006000+0x444) */ +#define SC_DDRPHY_LP_SIGNALS_LSB (1U << 0) /* 3b */ +/* CPU_DVFS_REQ (0x10006000+0x448) */ +#define CPU_DVFS_REQ_LSB (1U << 0) /* 32b */ +/* SPM_PLL_CON (0x10006000+0x44C) */ +#define SC_MAINPLLOUT_OFF_LSB (1U << 0) /* 1b */ +#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */ +#define SC_MAINPLL_OFF_LSB (1U << 4) /* 1b */ +#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */ +#define SC_MAINPLL_S_OFF_LSB (1U << 8) /* 1b */ +#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */ +#define SC_SMI_CK_OFF_LSB (1U << 16) /* 1b */ +#define SC_SSPMK_CK_OFF_LSB (1U << 17) /* 1b */ +/* SPM_EMI_BW_MODE (0x10006000+0x450) */ +#define EMI_BW_MODE_LSB (1U << 0) /* 1b */ +#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */ +#define EMI_BW_MODE_2_LSB (1U << 2) /* 1b */ +#define EMI_BOOST_MODE_2_LSB (1U << 3) /* 1b */ +/* AP2MD_PEER_WAKEUP (0x10006000+0x454) */ +#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */ +/* ULPOSC_CON (0x10006000+0x458) */ +#define ULPOSC_EN_LSB (1U << 0) /* 1b */ +#define ULPOSC_RST_LSB (1U << 1) /* 1b */ +#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */ +#define ULPOSC_CLK_SEL_LSB (1U << 3) /* 1b */ +/* SPM2MM_CON (0x10006000+0x45C) */ +#define SPM2MM_FORCE_ULTRA_LSB (1U << 0) /* 1b */ +#define SPM2MM_DBL_OSTD_ACT_LSB (1U << 1) /* 1b */ +#define SPM2MM_ULTRAREQ_LSB (1U << 2) /* 1b */ +#define SPM2MD_ULTRAREQ_LSB (1U << 3) /* 1b */ +#define SPM2ISP_ULTRAREQ_LSB (1U << 4) /* 1b */ +#define MM2SPM_FORCE_ULTRA_ACK_LSB (1U << 16) /* 1b */ +#define MM2SPM_DBL_OSTD_ACT_ACK_LSB (1U << 17) /* 1b */ +#define SPM2ISP_ULTRAACK_D2T_LSB (1U << 18) /* 1b */ +#define SPM2MM_ULTRAACK_D2T_LSB (1U << 19) /* 1b */ +#define SPM2MD_ULTRAACK_D2T_LSB (1U << 20) /* 1b */ +/* DRAMC_DPY_CLK_SW_CON_SEL (0x10006000+0x460) */ +#define SW_DR_GATE_RETRY_EN_SEL_LSB (1U << 0) /* 2b */ +#define SW_EMI_CLK_OFF_SEL_LSB (1U << 2) /* 2b */ +#define SW_DPY_MODE_SW_SEL_LSB (1U << 4) /* 2b */ +#define SW_DMSUS_OFF_SEL_LSB (1U << 6) /* 2b */ +#define SW_MEM_CK_OFF_SEL_LSB (1U << 8) /* 2b */ +#define SW_DPY_2ND_DLL_EN_SEL_LSB (1U << 10) /* 2b */ +#define SW_DPY_DLL_EN_SEL_LSB (1U << 12) /* 2b */ +#define SW_DPY_DLL_CK_EN_SEL_LSB (1U << 14) /* 2b */ +#define SW_DPY_VREF_EN_SEL_LSB (1U << 16) /* 2b */ +#define SW_PHYPLL_EN_SEL_LSB (1U << 18) /* 2b */ +#define SW_DDRPHY_FB_CK_EN_SEL_LSB (1U << 20) /* 2b */ +#define SEPERATE_PHY_PWR_SEL_LSB (1U << 23) /* 1b */ +#define SW_DMDRAMCSHU_ACK_SEL_LSB (1U << 24) /* 2b */ +#define SW_EMI_CLK_OFF_ACK_SEL_LSB (1U << 26) /* 2b */ +#define SW_DR_SHORT_QUEUE_ACK_SEL_LSB (1U << 28) /* 2b */ +#define SW_DRAMC_DFS_STA_SEL_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_CON (0x10006000+0x464) */ +#define SW_DR_GATE_RETRY_EN_LSB (1U << 0) /* 2b */ +#define SW_EMI_CLK_OFF_LSB (1U << 2) /* 2b */ +#define SW_DPY_MODE_SW_LSB (1U << 4) /* 2b */ +#define SW_DMSUS_OFF_LSB (1U << 6) /* 2b */ +#define SW_MEM_CK_OFF_LSB (1U << 8) /* 2b */ +#define SW_DPY_2ND_DLL_EN_LSB (1U << 10) /* 2b */ +#define SW_DPY_DLL_EN_LSB (1U << 12) /* 2b */ +#define SW_DPY_DLL_CK_EN_LSB (1U << 14) /* 2b */ +#define SW_DPY_VREF_EN_LSB (1U << 16) /* 2b */ +#define SW_PHYPLL_EN_LSB (1U << 18) /* 2b */ +#define SW_DDRPHY_FB_CK_EN_LSB (1U << 20) /* 2b */ +#define SC_DR_SHU_EN_ACK_LSB (1U << 24) /* 2b */ +#define EMI_CLK_OFF_ACK_LSB (1U << 26) /* 2b */ +#define SC_DR_SHORT_QUEUE_ACK_LSB (1U << 28) /* 2b */ +#define SC_DRAMC_DFS_STA_LSB (1U << 30) /* 2b */ +/* SPM_S1_MODE_CH (0x10006000+0x468) */ +#define SPM_S1_MODE_CH_LSB (1U << 0) /* 2b */ +#define S1_EMI_CK_SWITCH_LSB (1U << 8) /* 2b */ +/* EMI_SELF_REFRESH_CH_STA (0x10006000+0x46C) */ +#define EMI_SELF_REFRESH_CH_LSB (1U << 0) /* 2b */ +/* DRAMC_DPY_CLK_SW_CON_SEL2 (0x10006000+0x470) */ +#define SW_PHYPLL_SHU_EN_SEL_LSB (1U << 0) /* 1b */ +#define SW_PHYPLL2_SHU_EN_SEL_LSB (1U << 1) /* 1b */ +#define SW_PHYPLL_MODE_SW_SEL_LSB (1U << 2) /* 1b */ +#define SW_PHYPLL2_MODE_SW_SEL_LSB (1U << 3) /* 1b */ +#define SW_DR_SHORT_QUEUE_SEL_LSB (1U << 4) /* 1b */ +#define SW_DR_SHU_EN_SEL_LSB (1U << 5) /* 1b */ +#define SW_DR_SHU_LEVEL_SEL_LSB (1U << 6) /* 1b */ +#define SW_DPY_BCLK_ENABLE_SEL_LSB (1U << 8) /* 2b */ +#define SW_SHU_RESTORE_SEL_LSB (1U << 10) /* 2b */ +#define SW_DPHY_PRECAL_UP_SEL_LSB (1U << 12) /* 2b */ +#define SW_DPHY_RXDLY_TRACK_EN_SEL_LSB (1U << 14) /* 2b */ +#define SW_TX_TRACKING_DIS_SEL_LSB (1U << 16) /* 2b */ +/* DRAMC_DPY_CLK_SW_CON2 (0x10006000+0x474) */ +#define SW_PHYPLL_SHU_EN_LSB (1U << 0) /* 1b */ +#define SW_PHYPLL2_SHU_EN_LSB (1U << 1) /* 1b */ +#define SW_PHYPLL_MODE_SW_LSB (1U << 2) /* 1b */ +#define SW_PHYPLL2_MODE_SW_LSB (1U << 3) /* 1b */ +#define SW_DR_SHORT_QUEUE_LSB (1U << 4) /* 1b */ +#define SW_DR_SHU_EN_LSB (1U << 5) /* 1b */ +#define SW_DR_SHU_LEVEL_LSB (1U << 6) /* 2b */ +#define SW_DPY_BCLK_ENABLE_LSB (1U << 8) /* 2b */ +#define SW_SHU_RESTORE_LSB (1U << 10) /* 2b */ +#define SW_DPHY_PRECAL_UP_LSB (1U << 12) /* 2b */ +#define SW_DPHY_RXDLY_TRACK_EN_LSB (1U << 14) /* 2b */ +#define SW_TX_TRACKING_DIS_LSB (1U << 16) /* 2b */ +/* DRAMC_DMYRD_CON (0x10006000+0x478) */ +#define DRAMC_DMYRD_EN_CH0_LSB (1U << 0) /* 1b */ +#define DRAMC_DMYRD_INTV_SEL_CH0_LSB (1U << 1) /* 1b */ +#define DRAMC_DMYRD_EN_MOD_SEL_CH0_LSB (1U << 2) /* 1b */ +#define DRAMC_DMYRD_EN_CH1_LSB (1U << 8) /* 1b */ +#define DRAMC_DMYRD_INTV_SEL_CH1_LSB (1U << 9) /* 1b */ +#define DRAMC_DMYRD_EN_MOD_SEL_CH1_LSB (1U << 10) /* 1b */ +/* SPM_DRS_CON (0x10006000+0x47C) */ +#define SPM_DRS_DIS_REQ_CH0_LSB (1U << 0) /* 1b */ +#define SPM_DRS_DIS_REQ_CH1_LSB (1U << 1) /* 1b */ +#define SPM_DRS_DIS_ACK_CH0_LSB (1U << 8) /* 1b */ +#define SPM_DRS_DIS_ACK_CH1_LSB (1U << 9) /* 1b */ +/* SPM_SEMA_M0 (0x10006000+0x480) */ +#define SPM_SEMA_M0_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M1 (0x10006000+0x484) */ +#define SPM_SEMA_M1_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M2 (0x10006000+0x488) */ +#define SPM_SEMA_M2_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M3 (0x10006000+0x48C) */ +#define SPM_SEMA_M3_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M4 (0x10006000+0x490) */ +#define SPM_SEMA_M4_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M5 (0x10006000+0x494) */ +#define SPM_SEMA_M5_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M6 (0x10006000+0x498) */ +#define SPM_SEMA_M6_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M7 (0x10006000+0x49C) */ +#define SPM_SEMA_M7_LSB (1U << 0) /* 8b */ +/* SPM_MAS_PAUSE_MM_MASK_B (0x10006000+0x4A0) */ +#define SPM_MAS_PAUSE_MM_MASK_B_LSB (1U << 0) /* 16b */ +/* SPM_MAS_PAUSE_MCU_MASK_B (0x10006000+0x4A4) */ +#define SPM_MAS_PAUSE_MCU_MASK_B_LSB (1U << 0) /* 16b */ +/* SRAM_DREQ_ACK (0x10006000+0x4AC) */ +#define SRAM_DREQ_ACK_LSB (1U << 0) /* 16b */ +/* SRAM_DREQ_CON (0x10006000+0x4B0) */ +#define SRAM_DREQ_CON_LSB (1U << 0) /* 16b */ +/* SRAM_DREQ_CON_SET (0x10006000+0x4B4) */ +#define SRAM_DREQ_CON_SET_LSB (1U << 0) /* 16b */ +/* SRAM_DREQ_CON_CLR (0x10006000+0x4B8) */ +#define SRAM_DREQ_CON_CLR_LSB (1U << 0) /* 16b */ +/* SPM2EMI_ENTER_ULPM (0x10006000+0x4BC) */ +#define SPM2EMI_ENTER_ULPM_LSB (1U << 0) /* 1b */ +/* SPM_SSPM_IRQ (0x10006000+0x4C0) */ +#define SPM_SSPM_IRQ_LSB (1U << 0) /* 1b */ +#define SPM_SSPM_IRQ_SEL_LSB (1U << 4) /* 1b */ +/* SPM2PMCU_INT (0x10006000+0x4C4) */ +#define SPM2PMCU_INT_LSB (1U << 0) /* 4b */ +/* SPM2PMCU_INT_SET (0x10006000+0x4C8) */ +#define SPM2PMCU_INT_SET_LSB (1U << 0) /* 4b */ +/* SPM2PMCU_INT_CLR (0x10006000+0x4CC) */ +#define SPM2PMCU_INT_CLR_LSB (1U << 0) /* 4b */ +/* SPM2PMCU_MAILBOX_0 (0x10006000+0x4D0) */ +#define SPM2PMCU_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_1 (0x10006000+0x4D4) */ +#define SPM2PMCU_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_2 (0x10006000+0x4D8) */ +#define SPM2PMCU_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_3 (0x10006000+0x4DC) */ +#define SPM2PMCU_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_INT (0x10006000+0x4E0) */ +#define PMCU2SPM_INT_LSB (1U << 0) /* 4b */ +/* PMCU2SPM_INT_SET (0x10006000+0x4E4) */ +#define PMCU2SPM_INT_SET_LSB (1U << 0) /* 4b */ +/* PMCU2SPM_INT_CLR (0x10006000+0x4E8) */ +#define PMCU2SPM_INT_CLR_LSB (1U << 0) /* 4b */ +/* PMCU2SPM_MAILBOX_0 (0x10006000+0x4EC) */ +#define PMCU2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_1 (0x10006000+0x4F0) */ +#define PMCU2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_2 (0x10006000+0x4F4) */ +#define PMCU2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_3 (0x10006000+0x4F8) */ +#define PMCU2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_CFG (0x10006000+0x4FC) */ +#define PMCU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */ +#define SPM_PMCU_MAILBOX_REQ_LSB (1U << 8) /* 1b */ +/* MP0_CPU0_IRQ_MASK (0x10006000+0x500) */ +#define MP0_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU0_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU1_IRQ_MASK (0x10006000+0x504) */ +#define MP0_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU2_IRQ_MASK (0x10006000+0x508) */ +#define MP0_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU2_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU3_IRQ_MASK (0x10006000+0x50C) */ +#define MP0_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU3_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU0_IRQ_MASK (0x10006000+0x510) */ +#define MP1_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU0_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU1_IRQ_MASK (0x10006000+0x514) */ +#define MP1_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU1_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU2_IRQ_MASK (0x10006000+0x518) */ +#define MP1_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU2_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU3_IRQ_MASK (0x10006000+0x51C) */ +#define MP1_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU3_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU0_WFI_EN (0x10006000+0x530) */ +#define MP0_CPU0_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU1_WFI_EN (0x10006000+0x534) */ +#define MP0_CPU1_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU2_WFI_EN (0x10006000+0x538) */ +#define MP0_CPU2_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU3_WFI_EN (0x10006000+0x53C) */ +#define MP0_CPU3_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP1_CPU0_WFI_EN (0x10006000+0x540) */ +#define MP1_CPU0_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP1_CPU1_WFI_EN (0x10006000+0x544) */ +#define MP1_CPU1_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP1_CPU2_WFI_EN (0x10006000+0x548) */ +#define MP1_CPU2_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP1_CPU3_WFI_EN (0x10006000+0x54C) */ +#define MP1_CPU3_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_L2CFLUSH (0x10006000+0x554) */ +#define MP0_L2CFLUSH_REQ_LSB (1U << 0) /* 1b */ +#define MP0_L2CFLUSH_DONE_LSB (1U << 4) /* 1b */ +/* MP1_L2CFLUSH (0x10006000+0x558) */ +#define MP1_L2CFLUSH_REQ_LSB (1U << 0) /* 1b */ +#define MP1_L2CFLUSH_DONE_LSB (1U << 4) /* 1b */ +/* CPU_PTPOD2_CON (0x10006000+0x560) */ +#define MP0_PTPOD2_FBB_EN_LSB (1U << 0) /* 1b */ +#define MP1_PTPOD2_FBB_EN_LSB (1U << 1) /* 1b */ +#define MP0_PTPOD2_SPARK_EN_LSB (1U << 2) /* 1b */ +#define MP1_PTPOD2_SPARK_EN_LSB (1U << 3) /* 1b */ +#define MP0_PTPOD2_FBB_ACK_LSB (1U << 4) /* 1b */ +#define MP1_PTPOD2_FBB_ACK_LSB (1U << 5) /* 1b */ +/* ROOT_CPUTOP_ADDR (0x10006000+0x570) */ +#define ROOT_CPUTOP_ADDR_LSB (1U << 0) /* 32b */ +/* ROOT_CORE_ADDR (0x10006000+0x574) */ +#define ROOT_CORE_ADDR_LSB (1U << 0) /* 32b */ +/* CPU_SPARE_CON (0x10006000+0x580) */ +#define CPU_SPARE_CON_LSB (1U << 0) /* 32b */ +/* CPU_SPARE_CON_SET (0x10006000+0x584) */ +#define CPU_SPARE_CON_SET_LSB (1U << 0) /* 32b */ +/* CPU_SPARE_CON_CLR (0x10006000+0x588) */ +#define CPU_SPARE_CON_CLR_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_0 (0x10006000+0x5D0) */ +#define SPM2SW_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_1 (0x10006000+0x5D4) */ +#define SPM2SW_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_2 (0x10006000+0x5D8) */ +#define SPM2SW_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_3 (0x10006000+0x5DC) */ +#define SPM2SW_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* SW2SPM_INT (0x10006000+0x5E0) */ +#define SW2SPM_INT_LSB (1U << 0) /* 4b */ +/* SW2SPM_INT_SET (0x10006000+0x5E4) */ +#define SW2SPM_INT_SET_LSB (1U << 0) /* 4b */ +/* SW2SPM_INT_CLR (0x10006000+0x5E8) */ +#define SW2SPM_INT_CLR_LSB (1U << 0) /* 4b */ +/* SW2SPM_MAILBOX_0 (0x10006000+0x5EC) */ +#define SW2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_1 (0x10006000+0x5F0) */ +#define SW2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_2 (0x10006000+0x5F4) */ +#define SW2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_3 (0x10006000+0x5F8) */ +#define SW2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* SW2SPM_CFG (0x10006000+0x5FC) */ +#define SWU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */ +#define SPM_SW_MAILBOX_REQ_LSB (1U << 8) /* 1b */ +/* SPM_SW_FLAG (0x10006000+0x600) */ +#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */ +/* SPM_SW_DEBUG (0x10006000+0x604) */ +#define SPM_SW_DEBUG_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_0 (0x10006000+0x608) */ +#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_1 (0x10006000+0x60C) */ +#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_2 (0x10006000+0x610) */ +#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_3 (0x10006000+0x614) */ +#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_4 (0x10006000+0x618) */ +#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_5 (0x10006000+0x61C) */ +#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */ +/* SPM_RSV_CON (0x10006000+0x620) */ +#define SPM_RSV_CON_LSB (1U << 0) /* 16b */ +/* SPM_RSV_STA (0x10006000+0x624) */ +#define SPM_RSV_STA_LSB (1U << 0) /* 16b */ +/* SPM_RSV_CON1 (0x10006000+0x628) */ +#define SPM_RSV_CON1_LSB (1U << 0) /* 16b */ +/* SPM_RSV_STA1 (0x10006000+0x62C) */ +#define SPM_RSV_STA1_LSB (1U << 0) /* 16b */ +/* SPM_PASR_DPD_0 (0x10006000+0x630) */ +#define SPM_PASR_DPD_0_LSB (1U << 0) /* 32b */ +/* SPM_PASR_DPD_1 (0x10006000+0x634) */ +#define SPM_PASR_DPD_1_LSB (1U << 0) /* 32b */ +/* SPM_PASR_DPD_2 (0x10006000+0x638) */ +#define SPM_PASR_DPD_2_LSB (1U << 0) /* 32b */ +/* SPM_PASR_DPD_3 (0x10006000+0x63C) */ +#define SPM_PASR_DPD_3_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON (0x10006000+0x640) */ +#define SPM_SPARE_CON_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON_SET (0x10006000+0x644) */ +#define SPM_SPARE_CON_SET_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON_CLR (0x10006000+0x648) */ +#define SPM_SPARE_CON_CLR_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_6 (0x10006000+0x64C) */ +#define SPM_SW_RSV_6_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_7 (0x10006000+0x650) */ +#define SPM_SW_RSV_7_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_8 (0x10006000+0x654) */ +#define SPM_SW_RSV_8_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_9 (0x10006000+0x658) */ +#define SPM_SW_RSV_9_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_10 (0x10006000+0x65C) */ +#define SPM_SW_RSV_10_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_18 (0x10006000+0x67C) */ +#define SPM_SW_RSV_18_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_19 (0x10006000+0x680) */ +#define SPM_SW_RSV_19_LSB (1U << 0) /* 32b */ +/* DVFSRC_EVENT_MASK_CON (0x10006000+0x690) */ +#define DVFSRC_EVENT_MASK_B_LSB (1U << 0) /* 16b */ +#define DVFSRC_EVENT_TRIGGER_MASK_B_LSB (1U << 16) /* 1b */ +/* DVFSRC_EVENT_FORCE_ON (0x10006000+0x694) */ +#define DVFSRC_EVENT_FORCE_ON_LSB (1U << 0) /* 16b */ +#define DVFSRC_EVENT_TRIGGER_FORCE_ON_LSB (1U << 16) /* 1b */ +/* DVFSRC_EVENT_SEL (0x10006000+0x698) */ +#define DVFSRC_EVENT_SEL_LSB (1U << 0) /* 16b */ +/* SPM_DVFS_EVENT_STA (0x10006000+0x69C) */ +#define SPM_DVFS_EVENT_STA_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_EVENT_STA1 (0x10006000+0x6A0) */ +#define SPM_DVFS_EVENT_STA1_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_LEVEL (0x10006000+0x6A4) */ +#define SPM_DVFS_LEVEL_LSB (1U << 0) /* 16b */ +/* DVFS_ABORT_STA (0x10006000+0x6A8) */ +#define RC2SPM_EVENT_ABORT_D2T_LSB (1U << 0) /* 16b */ +#define RC2SPM_EVENT_ABORT_MASK_OR_LSB (1U << 16) /* 1b */ +/* DVFS_ABORT_OTHERS_MASK (0x10006000+0x6AC) */ +#define DVFS_ABORT_OTHERS_MASK_B_LSB (1U << 0) /* 16b */ +/* SPM_DFS_LEVEL (0x10006000+0x6B0) */ +#define SPM_DFS_LEVEL_LSB (1U << 0) /* 4b */ +/* SPM_DVS_LEVEL (0x10006000+0x6B4) */ +#define SPM_VCORE_LEVEL_LSB (1U << 0) /* 8b */ +#define SPM_VSRAM_LEVEL_LSB (1U << 8) /* 8b */ +#define SPM_VMODEM_LEVEL_LSB (1U << 16) /* 8b */ +/* SPM_DVFS_MISC (0x10006000+0x6B8) */ +#define MSDC_DVFS_REQUEST_LSB (1U << 0) /* 1b */ +#define MSDC_DVFS_LEVEL_LSB (1U << 1) /* 4b */ +#define SDIO_READY_TO_SPM_LSB (1U << 7) /* 1b */ +#define MD2AP_CENTRAL_BUCK_GEAR_REQ_D2T_LSB (1U << 8) /* 1b */ +#define MD2AP_CENTRAL_BUCK_GEAR_RDY_D2T_LSB (1U << 9) /* 1b */ +/* SPARE_SRC_REQ_MASK (0x10006000+0x6C0) */ +#define SPARE1_DDREN_MASK_B_LSB (1U << 0) /* 1b */ +#define SPARE1_APSRC_REQ_MASK_B_LSB (1U << 1) /* 1b */ +#define SPARE1_VRF18_REQ_MASK_B_LSB (1U << 2) /* 1b */ +#define SPARE1_INFRA_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define SPARE1_SRCCLKENA_MASK_B_LSB (1U << 4) /* 1b */ +#define SPARE1_DDREN_2_MASK_B_LSB (1U << 5) /* 1b */ +#define SPARE2_DDREN_MASK_B_LSB (1U << 8) /* 1b */ +#define SPARE2_APSRC_REQ_MASK_B_LSB (1U << 9) /* 1b */ +#define SPARE2_VRF18_REQ_MASK_B_LSB (1U << 10) /* 1b */ +#define SPARE2_INFRA_REQ_MASK_B_LSB (1U << 11) /* 1b */ +#define SPARE2_SRCCLKENA_MASK_B_LSB (1U << 12) /* 1b */ +#define SPARE2_DDREN_2_MASK_B_LSB (1U << 13) /* 1b */ +/* SCP_VCORE_LEVEL (0x10006000+0x6C4) */ +#define SCP_VCORE_LEVEL_LSB (1U << 0) /* 8b */ +/* SC_MM_CK_SEL_CON (0x10006000+0x6C8) */ +#define SC_MM_CK_SEL_LSB (1U << 0) /* 4b */ +#define SC_MM_CK_SEL_EN_LSB (1U << 4) /* 1b */ +/* SPARE_ACK_STA (0x10006000+0x6F0) */ +#define SPARE_ACK_SYNC_LSB (1U << 0) /* 32b */ +/* SPARE_ACK_MASK (0x10006000+0x6F4) */ +#define SPARE_ACK_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CON1 (0x10006000+0x700) */ +#define SPM_DVFS_CON1_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CON1_STA (0x10006000+0x704) */ +#define SPM_DVFS_CON1_STA_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD0 (0x10006000+0x710) */ +#define SPM_DVFS_CMD0_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD1 (0x10006000+0x714) */ +#define SPM_DVFS_CMD1_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD2 (0x10006000+0x718) */ +#define SPM_DVFS_CMD2_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD3 (0x10006000+0x71C) */ +#define SPM_DVFS_CMD3_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD4 (0x10006000+0x720) */ +#define SPM_DVFS_CMD4_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD5 (0x10006000+0x724) */ +#define SPM_DVFS_CMD5_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD6 (0x10006000+0x728) */ +#define SPM_DVFS_CMD6_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD7 (0x10006000+0x72C) */ +#define SPM_DVFS_CMD7_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD8 (0x10006000+0x730) */ +#define SPM_DVFS_CMD8_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD9 (0x10006000+0x734) */ +#define SPM_DVFS_CMD9_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD10 (0x10006000+0x738) */ +#define SPM_DVFS_CMD10_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD11 (0x10006000+0x73C) */ +#define SPM_DVFS_CMD11_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD12 (0x10006000+0x740) */ +#define SPM_DVFS_CMD12_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD13 (0x10006000+0x744) */ +#define SPM_DVFS_CMD13_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD14 (0x10006000+0x748) */ +#define SPM_DVFS_CMD14_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD15 (0x10006000+0x74C) */ +#define SPM_DVFS_CMD15_LSB (1U << 0) /* 32b */ +/* WDT_LATCH_SPARE0_FIX (0x10006000+0x780) */ +#define WDT_LATCH_SPARE0_FIX_LSB (1U << 0) /* 32b */ +/* WDT_LATCH_SPARE1_FIX (0x10006000+0x784) */ +#define WDT_LATCH_SPARE1_FIX_LSB (1U << 0) /* 32b */ +/* WDT_LATCH_SPARE2_FIX (0x10006000+0x788) */ +#define WDT_LATCH_SPARE2_FIX_LSB (1U << 0) /* 32b */ +/* WDT_LATCH_SPARE3_FIX (0x10006000+0x78C) */ +#define WDT_LATCH_SPARE3_FIX_LSB (1U << 0) /* 32b */ +/* SPARE_ACK_IN_FIX (0x10006000+0x790) */ +#define SPARE_ACK_IN_FIX_LSB (1U << 0) /* 32b */ +/* DCHA_LATCH_RSV0_FIX (0x10006000+0x794) */ +#define DCHA_LATCH_RSV0_FIX_LSB (1U << 0) /* 32b */ +/* DCHB_LATCH_RSV0_FIX (0x10006000+0x798) */ +#define DCHB_LATCH_RSV0_FIX_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_0 (0x10006000+0x800) */ +#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_1 (0x10006000+0x804) */ +#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_2 (0x10006000+0x808) */ +#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_3 (0x10006000+0x80C) */ +#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_4 (0x10006000+0x810) */ +#define PCM_WDT_LATCH_4_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_5 (0x10006000+0x814) */ +#define PCM_WDT_LATCH_5_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_6 (0x10006000+0x818) */ +#define PCM_WDT_LATCH_6_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_7 (0x10006000+0x81C) */ +#define PCM_WDT_LATCH_7_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_8 (0x10006000+0x820) */ +#define PCM_WDT_LATCH_8_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_9 (0x10006000+0x824) */ +#define PCM_WDT_LATCH_9_LSB (1U << 0) /* 32b */ +/* WDT_LATCH_SPARE0 (0x10006000+0x828) */ +#define WDT_LATCH_SPARE0_LSB (1U << 0) /* 32b */ +/* WDT_LATCH_SPARE1 (0x10006000+0x82C) */ +#define WDT_LATCH_SPARE1_LSB (1U << 0) /* 32b */ +/* WDT_LATCH_SPARE2 (0x10006000+0x830) */ +#define WDT_LATCH_SPARE2_LSB (1U << 0) /* 32b */ +/* WDT_LATCH_SPARE3 (0x10006000+0x834) */ +#define WDT_LATCH_SPARE3_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_10 (0x10006000+0x838) */ +#define PCM_WDT_LATCH_10_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_11 (0x10006000+0x83C) */ +#define PCM_WDT_LATCH_11_LSB (1U << 0) /* 32b */ +/* DCHA_GATING_LATCH_0 (0x10006000+0x840) */ +#define DCHA_GATING_LATCH_0_LSB (1U << 0) /* 32b */ +/* DCHA_GATING_LATCH_1 (0x10006000+0x844) */ +#define DCHA_GATING_LATCH_1_LSB (1U << 0) /* 32b */ +/* DCHA_GATING_LATCH_2 (0x10006000+0x848) */ +#define DCHA_GATING_LATCH_2_LSB (1U << 0) /* 32b */ +/* DCHA_GATING_LATCH_3 (0x10006000+0x84C) */ +#define DCHA_GATING_LATCH_3_LSB (1U << 0) /* 32b */ +/* DCHA_GATING_LATCH_4 (0x10006000+0x850) */ +#define DCHA_GATING_LATCH_4_LSB (1U << 0) /* 32b */ +/* DCHA_GATING_LATCH_5 (0x10006000+0x854) */ +#define DCHA_GATING_LATCH_5_LSB (1U << 0) /* 32b */ +/* DCHA_GATING_LATCH_6 (0x10006000+0x858) */ +#define DCHA_GATING_LATCH_6_LSB (1U << 0) /* 32b */ +/* DCHA_GATING_LATCH_7 (0x10006000+0x85C) */ +#define DCHA_GATING_LATCH_7_LSB (1U << 0) /* 32b */ +/* DCHB_GATING_LATCH_0 (0x10006000+0x860) */ +#define DCHB_GATING_LATCH_0_LSB (1U << 0) /* 32b */ +/* DCHB_GATING_LATCH_1 (0x10006000+0x864) */ +#define DCHB_GATING_LATCH_1_LSB (1U << 0) /* 32b */ +/* DCHB_GATING_LATCH_2 (0x10006000+0x868) */ +#define DCHB_GATING_LATCH_2_LSB (1U << 0) /* 32b */ +/* DCHB_GATING_LATCH_3 (0x10006000+0x86C) */ +#define DCHB_GATING_LATCH_3_LSB (1U << 0) /* 32b */ +/* DCHB_GATING_LATCH_4 (0x10006000+0x870) */ +#define DCHB_GATING_LATCH_4_LSB (1U << 0) /* 32b */ +/* DCHB_GATING_LATCH_5 (0x10006000+0x874) */ +#define DCHB_GATING_LATCH_5_LSB (1U << 0) /* 32b */ +/* DCHB_GATING_LATCH_6 (0x10006000+0x878) */ +#define DCHB_GATING_LATCH_6_LSB (1U << 0) /* 32b */ +/* DCHB_GATING_LATCH_7 (0x10006000+0x87C) */ +#define DCHB_GATING_LATCH_7_LSB (1U << 0) /* 32b */ +/* DCHA_LATCH_RSV0 (0x10006000+0x880) */ +#define DCHA_LATCH_RSV0_LSB (1U << 0) /* 32b */ +/* DCHB_LATCH_RSV0 (0x10006000+0x884) */ +#define DCHB_LATCH_RSV0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_12 (0x10006000+0x888) */ +#define PCM_WDT_LATCH_12_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_13 (0x10006000+0x88C) */ +#define PCM_WDT_LATCH_13_LSB (1U << 0) /* 32b */ +/* SPM_PC_TRACE_CON (0x10006000+0x8C0) */ +#define SPM_PC_TRACE_OFFSET_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE_HW_EN_LSB (1U << 16) /* 1b */ +#define SPM_PC_TRACE_SW_LSB (1U << 17) /* 1b */ +/* SPM_PC_TRACE_G0 (0x10006000+0x8C4) */ +#define SPM_PC_TRACE0_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE1_LSB (1U << 16) /* 12b */ +/* SPM_PC_TRACE_G1 (0x10006000+0x8C8) */ +#define SPM_PC_TRACE2_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE3_LSB (1U << 16) /* 12b */ +/* SPM_PC_TRACE_G2 (0x10006000+0x8CC) */ +#define SPM_PC_TRACE4_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE5_LSB (1U << 16) /* 12b */ +/* SPM_PC_TRACE_G3 (0x10006000+0x8D0) */ +#define SPM_PC_TRACE6_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE7_LSB (1U << 16) /* 12b */ +/* SPM_PC_TRACE_G4 (0x10006000+0x8D4) */ +#define SPM_PC_TRACE8_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE9_LSB (1U << 16) /* 12b */ +/* SPM_PC_TRACE_G5 (0x10006000+0x8D8) */ +#define SPM_PC_TRACE10_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE11_LSB (1U << 16) /* 12b */ +/* SPM_PC_TRACE_G6 (0x10006000+0x8DC) */ +#define SPM_PC_TRACE12_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE13_LSB (1U << 16) /* 12b */ +/* SPM_PC_TRACE_G7 (0x10006000+0x8E0) */ +#define SPM_PC_TRACE14_LSB (1U << 0) /* 12b */ +#define SPM_PC_TRACE15_LSB (1U << 16) /* 12b */ +/* SPM_ACK_CHK_CON (0x10006000+0x900) */ +#define SPM_ACK_CHK_SW_EN_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_LSB (1U << 15) /* 1b */ +#define SPM_ACK_CHK_SWINT_EN_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_PC (0x10006000+0x904) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL (0x10006000+0x908) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER (0x10006000+0x90C) */ +#define SPM_ACK_CHK_TIMER_VAL_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA (0x10006000+0x910) */ +#define SPM_ACK_CHK_STA_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_LATCH (0x10006000+0x914) */ +#define SPM_ACK_CHK_LATCH_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON2 (0x10006000+0x920) */ +#define SPM_ACK_CHK_SW_EN2_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL2_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER2_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ2_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN2_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN2_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN2_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN2_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN2_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE2_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL2_LSB (1U << 15) /* 1b */ +#define SPM_ACK_CHK_SWINT_EN2_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_PC2 (0x10006000+0x924) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL2_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL2_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL2 (0x10006000+0x928) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL2_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL2_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL2_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL2_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER2 (0x10006000+0x92C) */ +#define SPM_ACK_CHK_TIMER_VAL2_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER2_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA2 (0x10006000+0x930) */ +#define SPM_ACK_CHK_STA2_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_LATCH2 (0x10006000+0x934) */ +#define SPM_ACK_CHK_LATCH2_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON3 (0x10006000+0x940) */ +#define SPM_ACK_CHK_SW_EN3_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL3_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER3_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ3_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN3_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN3_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN3_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN3_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN3_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE3_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL3_LSB (1U << 15) /* 1b */ +#define SPM_ACK_CHK_SWINT_EN3_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_PC3 (0x10006000+0x944) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL3_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL3_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL3 (0x10006000+0x948) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL3_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL3_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL3_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL3_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER3 (0x10006000+0x94C) */ +#define SPM_ACK_CHK_TIMER_VAL3_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER3_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA3 (0x10006000+0x950) */ +#define SPM_ACK_CHK_STA3_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_LATCH3 (0x10006000+0x954) */ +#define SPM_ACK_CHK_LATCH3_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON4 (0x10006000+0x960) */ +#define SPM_ACK_CHK_SW_EN4_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL4_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER4_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ4_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN4_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN4_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN4_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN4_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN4_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE4_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL4_LSB (1U << 15) /* 1b */ +#define SPM_ACK_CHK_SWINT_EN4_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_PC4 (0x10006000+0x964) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL4_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL4_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL4 (0x10006000+0x968) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL4_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL4_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL4_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL4_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER4 (0x10006000+0x96C) */ +#define SPM_ACK_CHK_TIMER_VAL4_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER4_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA4 (0x10006000+0x970) */ +#define SPM_ACK_CHK_STA4_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_LATCH4 (0x10006000+0x974) */ +#define SPM_ACK_CHK_LATCH4_LSB (1U << 0) /* 32b */ + +/* --- SPM Flag Define --- */ +#define SPM_FLAG_DIS_CPU_PDN (1U << 0) +#define SPM_FLAG_DIS_INFRA_PDN (1U << 1) +#define SPM_FLAG_DIS_DDRPHY_PDN (1U << 2) +#define SPM_FLAG_DIS_VCORE_DVS (1U << 3) +#define SPM_FLAG_DIS_VCORE_DFS (1U << 4) +#define SPM_FLAG_DIS_COMMON_SCENARIO (1U << 5) +#define SPM_FLAG_DIS_BUS_CLOCK_OFF (1U << 6) +#define SPM_FLAG_DIS_ATF_ABORT (1U << 7) +#define SPM_FLAG_KEEP_CSYSPWRUPACK_HIGH (1U << 8) +#define SPM_FLAG_DIS_VPROC_VSRAM_DVS (1U << 9) +#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10) +#define SPM_FLAG_EN_MET_DEBUG_USAGE (1U << 11) +#define SPM_FLAG_SODI_CG_MODE (1U << 12) +#define SPM_FLAG_SODI_NO_EVENT (1U << 13) +#define SPM_FLAG_ENABLE_SODI3 (1U << 14) +#define SPM_FLAG_DISABLE_MMSYS_DVFS (1U << 15) +#define SPM_FLAG_DIS_SYSRAM_SLEEP (1U << 16) +#define SPM_FLAG_DIS_SSPM_SRAM_SLEEP (1U << 17) +#define SPM_FLAG_DIS_VMODEM_DVS (1U << 18) +#define SPM_FLAG_SUSPEND_OPTION (1U << 19) +#define SPM_FLAG_DEEPIDLE_OPTION (1U << 20) +#define SPM_FLAG_SODI_OPTION (1U << 21) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT22 (1U << 22) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT23 (1U << 23) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT24 (1U << 24) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT25 (1U << 25) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT26 (1U << 26) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT27 (1U << 27) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT28 (1U << 28) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT29 (1U << 29) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT30 (1U << 30) +#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT31 (1U << 31) + +/* --- SPM Flag1 Define --- */ +#define SPM_FLAG1_RESERVED_BIT0 (1U << 0) +#define SPM_FLAG1_ENABLE_CPU_DORMANT (1U << 1) +#define SPM_FLAG1_ENABLE_CPU_SLEEP_VOLT (1U << 2) +#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH (1U << 3) +#define SPM_FLAG1_DISABLE_ULPOSC_OFF (1U << 4) +#define SPM_FLAG1_VCORE_LP_0P7V (1U << 5) +#define SPM_FLAG1_DISABLE_MCDSR (1U << 6) +#define SPM_FLAG1_DISABLE_NO_RESUME (1U << 7) +#define SPM_FLAG1_BIG_BUCK_OFF_ENABLE (1U << 8) +#define SPM_FLAG1_BIG_BUCK_ON_ENABLE (1U << 9) +#define SPM_FLAG1_RESERVED_BIT10 (1U << 10) +#define SPM_FLAG1_RESERVED_BIT11 (1U << 11) +#define SPM_FLAG1_RESERVED_BIT12 (1U << 12) +#define SPM_FLAG1_RESERVED_BIT13 (1U << 13) +#define SPM_FLAG1_RESERVED_BIT14 (1U << 14) +#define SPM_FLAG1_DIS_ARMPLL_OFF (1U << 15) +#define SPM_FLAG1_DIS_AXI_BUS_TO_26M (1U << 16) +#define SPM_FLAG1_DIS_IMP_DIS (1U << 17) +#define SPM_FLAG1_DIS_IMP_COPY (1U << 18) +#define SPM_FLAG1_DIS_EMI_TOGGLE_WORKAROUND (1U << 19) +#define SPM_FLAG1_DIS_DRAM_ENTER_SREF (1U << 20) +#define SPM_FLAG1_DIS_DRAM_DLL_OFF (1U << 21) +#define SPM_FLAG1_DIS_PHYPLL_OFF (1U << 22) +#define SPM_FLAG1_DIS_MPLL_OFF (1U << 23) +#define SPM_FLAG1_DIS_SYSPLL_OFF (1U << 24) +#define SPM_FLAG1_DIS_TOP_AXI_CLK_OFF (1U << 25) +#define SPM_FLAG1_DIS_PCM_26M_SWITCH (1U << 26) +#define SPM_FLAG1_DIS_CKSQ_OFF (1U << 27) +#define SPM_FLAG1_DIS_SRCVOLTEN_OFF (1U << 28) +#define SPM_FLAG1_DIS_CHB_CG_FREE_EN (1U << 29) +#define SPM_FLAG1_DIS_CHA_DCM_RES (1U << 30) +#define SPM_FLAG1_DIS_SW_MR4 (1U << 31) + +/* --- SPM DEBUG Define --- */ +#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0) +#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1) +#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2) +#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3) +#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4) +#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5) +#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6) +#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7) +#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8) +#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9) +#define SPM_DBG_DEBUG_IDX_NFC_CKBUF_ON (1U << 10) +#define SPM_DBG_DEBUG_IDX_NFC_CKBUF_OFF (1U << 11) +#define SPM_DBG_DEBUG_IDX_CPU_PDN (1U << 12) +#define SPM_DBG_DEBUG_IDX_DPD (1U << 13) +#define SPM_DBG_DEBUG_IDX_CONN_CKBUF_ON (1U << 14) +#define SPM_DBG_DEBUG_IDX_CONN_CKBUF_OFF (1U << 15) +#define SPM_DBG_DEBUG_IDX_VCORE_DVFS_START (1U << 16) +#define SPM_DBG_DEBUG_IDX_DDREN2_WAKE (1U << 17) +#define SPM_DBG_DEBUG_IDX_DDREN2_SLEEP (1U << 18) +#define SPM_DBG_DEBUG_IDX_SSPM_WFI (1U << 19) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP (1U << 20) +#define SPM_DBG_RESERVED_BIT21 (1U << 21) +#define SPM_DBG_RESERVED_BIT22 (1U << 22) +#define SPM_DBG_RESERVED_BIT23 (1U << 23) +#define SPM_DBG_RESERVED_BIT24 (1U << 24) +#define SPM_DBG_RESERVED_BIT25 (1U << 25) +#define SPM_DBG_RESERVED_BIT26 (1U << 26) +#define SPM_DBG_SODI1_FLAG (1U << 27) +#define SPM_DBG_SODI3_FLAG (1U << 28) +#define SPM_DBG_VCORE_DVFS_FLAG (1U << 29) +#define SPM_DBG_DEEPIDLE_FLAG (1U << 30) +#define SPM_DBG_SUSPEND_FLAG (1U << 31) + +/* --- SPM DEBUG1 Define --- */ +#define SPM_DBG1_DRAM_SREF_ACK_TO (1U << 0) +#define SPM_DBG1_PWRAP_SLEEP_ACK_TO (1U << 1) +#define SPM_DBG1_PWRAP_SPI_ACK_TO (1U << 2) +#define SPM_DBG1_DRAM_GATE_ERR_DDREN_WAKEUP (1U << 3) +#define SPM_DBG1_DRAM_GATE_ERR_LEAVE_LP_SCN (1U << 4) +#define SPM_DBG1_RESERVED_BIT5 (1U << 5) +#define SPM_DBG1_RESERVED_BIT6 (1U << 6) +#define SPM_DBG1_RESERVED_BIT7 (1U << 7) +#define SPM_DBG1_RESERVED_BIT8 (1U << 8) +#define SPM_DBG1_RESERVED_BIT9 (1U << 9) +#define SPM_DBG1_RESERVED_BIT10 (1U << 10) +#define SPM_DBG1_RESERVED_BIT11 (1U << 11) +#define SPM_DBG1_RESERVED_BIT12 (1U << 12) +#define SPM_DBG1_RESERVED_BIT13 (1U << 13) +#define SPM_DBG1_RESERVED_BIT14 (1U << 14) +#define SPM_DBG1_RESERVED_BIT15 (1U << 15) +#define SPM_DBG1_RESERVED_BIT16 (1U << 16) +#define SPM_DBG1_RESERVED_BIT17 (1U << 17) +#define SPM_DBG1_RESERVED_BIT18 (1U << 18) +#define SPM_DBG1_RESERVED_BIT19 (1U << 19) +#define SPM_DBG1_RESERVED_BIT20 (1U << 20) +#define SPM_DBG1_RESERVED_BIT21 (1U << 21) +#define SPM_DBG1_RESERVED_BIT22 (1U << 22) +#define SPM_DBG1_RESERVED_BIT23 (1U << 23) +#define SPM_DBG1_RESERVED_BIT24 (1U << 24) +#define SPM_DBG1_RESERVED_BIT25 (1U << 25) +#define SPM_DBG1_RESERVED_BIT26 (1U << 26) +#define SPM_DBG1_RESERVED_BIT27 (1U << 27) +#define SPM_DBG1_RESERVED_BIT28 (1U << 28) +#define SPM_DBG1_RESERVED_BIT29 (1U << 29) +#define SPM_DBG1_RESERVED_BIT30 (1U << 30) +#define SPM_DBG1_RESERVED_BIT31 (1U << 31) + +/* --- R0 Define --- */ +#define R0_SC_26M_CK_OFF (1U << 0) +#define R0_BIT1 (1U << 1) +#define R0_SC_MEM_CK_OFF (1U << 2) +#define R0_SC_AXI_CK_OFF (1U << 3) +#define R0_SC_DR_GATE_RETRY_EN_PCM (1U << 4) +#define R0_SC_MD26M_CK_OFF (1U << 5) +#define R0_SC_DPY_MODE_SW_PCM (1U << 6) +#define R0_SC_DMSUS_OFF_PCM (1U << 7) +#define R0_SC_DPY_2ND_DLL_EN_PCM (1U << 8) +#define R0_BIT9 (1U << 9) +#define R0_SC_MPLLOUT_OFF (1U << 10) +#define R0_SC_TX_TRACKING_DIS (1U << 11) +#define R0_SC_DPY_DLL_EN_PCM (1U << 12) +#define R0_SC_DPY_DLL_CK_EN_PCM (1U << 13) +#define R0_SC_DPY_VREF_EN_PCM (1U << 14) +#define R0_SC_PHYPLL_EN_PCM (1U << 15) +#define R0_SC_DDRPHY_FB_CK_EN_PCM (1U << 16) +#define R0_SC_DPY_BCLK_ENABLE (1U << 17) +#define R0_SC_MPLL_OFF (1U << 18) +#define R0_SC_SHU_RESTORE (1U << 19) +#define R0_SC_CKSQ0_OFF (1U << 20) +#define R0_SC_CKSQ1_OFF (1U << 21) +#define R0_SC_DR_SHU_EN_PCM (1U << 22) +#define R0_SC_DPHY_PRECAL_UP (1U << 23) +#define R0_SC_MPLL_S_OFF (1U << 24) +#define R0_SC_DPHY_RXDLY_TRACK_EN (1U << 25) +#define R0_SC_PHYPLL_SHU_EN_PCM (1U << 26) +#define R0_SC_PHYPLL2_SHU_EN_PCM (1U << 27) +#define R0_SC_PHYPLL_MODE_SW_PCM (1U << 28) +#define R0_SC_PHYPLL2_MODE_SW_PCM (1U << 29) +#define R0_SC_DR_SHU_LEVEL_PCM0 (1U << 30) +#define R0_SC_DR_SHU_LEVEL_PCM1 (1U << 31) + +/* --- R7 Define --- */ +#define R7_PWRAP_SLEEP_REQ (1U << 0) +#define R7_EMI_CLK_OFF_REQ (1U << 1) +#define R7_TOP_MAS_PAU_REQ (1U << 2) +#define R7_SPM2CKSYS_MEM_CK_MUX_UPDATE (1U << 3) +#define R7_PCM_CK_SEL0 (1U << 4) +#define R7_PCM_CK_SEL1 (1U << 5) +#define R7_SPM2RC_DVS_DONE (1U << 6) +#define R7_FREQH_PAUSE_MPLL (1U << 7) +#define R7_SC_26M_CK_SEL (1U << 8) +#define R7_PCM_TIMER_SET (1U << 9) +#define R7_PCM_TIMER_CLR (1U << 10) +#define R7_SRCVOLTEN (1U << 11) +#define R7_CSYSPWRUPACK (1U << 12) +#define R7_IM_SLEEP_ENABLE (1U << 13) +#define R7_SRCCLKENO_0 (1U << 14) +#define R7_SYSRST (1U << 15) +#define R7_MD_APSRC_ACK (1U << 16) +#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17) +#define R7_SC_AXI_DCM_DIS (1U << 18) +#define R7_FREQH_PAUSE_MAIN (1U << 19) +#define R7_FREQH_PAUSE_MEM (1U << 20) +#define R7_SRCCLKENO_1 (1U << 21) +#define R7_WDT_KICK_P (1U << 22) +#define R7_SPM2RC_EVENT_ABORT_ACK (1U << 23) +#define R7_WAKEUP_EXT_W_SEL (1U << 24) +#define R7_WAKEUP_EXT_R_SEL (1U << 25) +#define R7_PMIC_IRQ_REQ_EN (1U << 26) +#define R7_FORCE_26M_WAKE (1U << 27) +#define R7_FORCE_APSRC_WAKE (1U << 28) +#define R7_FORCE_INFRA_WAKE (1U << 29) +#define R7_FORCE_VRF18_WAKE (1U << 30) +#define R7_SC_DR_SHORT_QUEUE_PCM (1U << 31) + +/* --- R12 Define --- */ +#define R12_PCM_TIMER (1U << 0) +#define R12_SSPM_WDT_EVENT_B (1U << 1) +#define R12_KP_IRQ_B (1U << 2) +#define R12_APWDT_EVENT_B (1U << 3) +#define R12_APXGPT1_EVENT_B (1U << 4) +#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5) +#define R12_EINT_EVENT_B (1U << 6) +#define R12_CONN_WDT_IRQ_B (1U << 7) +#define R12_CCIF0_EVENT_B (1U << 8) +#define R12_LOWBATTERY_IRQ_B (1U << 9) +#define R12_SSPM_SPM_IRQ_B (1U << 10) +#define R12_SCP_SPM_IRQ_B (1U << 11) +#define R12_SCP_WDT_EVENT_B (1U << 12) +#define R12_PCM_WDT_WAKEUP_B (1U << 13) +#define R12_USB_CDSC_B (1U << 14) +#define R12_USB_POWERDWN_B (1U << 15) +#define R12_SYS_TIMER_EVENT_B (1U << 16) +#define R12_EINT_EVENT_SECURE_B (1U << 17) +#define R12_CCIF1_EVENT_B (1U << 18) +#define R12_UART0_IRQ_B (1U << 19) +#define R12_AFE_IRQ_MCU_B (1U << 20) +#define R12_THERM_CTRL_EVENT_B (1U << 21) +#define R12_SYS_CIRQ_IRQ_B (1U << 22) +#define R12_MD2AP_PEER_EVENT_B (1U << 23) +#define R12_CSYSPWREQ_B (1U << 24) +#define R12_MD1_WDT_B (1U << 25) +#define R12_CLDMA_EVENT_B (1U << 26) +#define R12_SEJ_WDT_GPT_B (1U << 27) +#define R12_ALL_SSPM_WAKEUP_B (1U << 28) +#define R12_CPU_IRQ_B (1U << 29) +#define R12_CPU_WFI_AND_B (1U << 30) +#define R12_MCUSYS_IDLE_TO_EMI_ALL_B (1U << 31) + +/* --- R12ext Define --- */ +#define R12EXT_26M_WAKE (1U << 0) +#define R12EXT_26M_SLEEP (1U << 1) +#define R12EXT_INFRA_WAKE (1U << 2) +#define R12EXT_INFRA_SLEEP (1U << 3) +#define R12EXT_APSRC_WAKE (1U << 4) +#define R12EXT_APSRC_SLEEP (1U << 5) +#define R12EXT_VRF18_WAKE (1U << 6) +#define R12EXT_VRF18_SLEEP (1U << 7) +#define R12EXT_DVFS_ALL_STATE (1U << 8) +#define R12EXT_DVFS_LEVEL_STATE0 (1U << 9) +#define R12EXT_DVFS_LEVEL_STATE1 (1U << 10) +#define R12EXT_DVFS_LEVEL_STATE2 (1U << 11) +#define R12EXT_DDREN_WAKE (1U << 12) +#define R12EXT_DDREN_SLEEP (1U << 13) +#define R12EXT_NFC_CLK_BUF_WAKE (1U << 14) +#define R12EXT_NFC_CLK_BUF_SLEEP (1U << 15) +#define R12EXT_CONN_CLK_BUF_WAKE (1U << 16) +#define R12EXT_CONN_CLK_BUF_SLEEP (1U << 17) +#define R12EXT_MD_DVFS_ERROR_STATUS (1U << 18) +#define R12EXT_DVFS_LEVEL_STATE3 (1U << 19) +#define R12EXT_DVFS_LEVEL_STATE4 (1U << 20) +#define R12EXT_DVFS_LEVEL_STATE5 (1U << 21) +#define R12EXT_DVFS_LEVEL_STATE6 (1U << 22) +#define R12EXT_DVFS_LEVEL_STATE7 (1U << 23) +#define R12EXT_DVFS_LEVEL_STATE8 (1U << 24) +#define R12EXT_DVFS_LEVEL_STATE9 (1U << 25) +#define R12EXT_DVFS_LEVEL_STATE_G0 (1U << 26) +#define R12EXT_DVFS_LEVEL_STATE_G1 (1U << 27) +#define R12EXT_DVFS_LEVEL_STATE_G2 (1U << 28) +#define R12EXT_DVFS_LEVEL_STATE_G3 (1U << 29) +#define R12EXT_HYBRID_DDREN_SLEEP (1U << 30) +#define R12EXT_HYBRID_DDREN_WAKE (1U << 31) + +/* --- R13 Define --- */ +#define R13_EXT_SRCCLKENI_0 (1U << 0) +#define R13_EXT_SRCCLKENI_1 (1U << 1) +#define R13_MD1_SRCCLKENA (1U << 2) +#define R13_MD1_APSRC_REQ (1U << 3) +#define R13_CONN_DDR_EN (1U << 4) +#define R13_MD2_SRCCLKENA (1U << 5) +#define R13_SSPM_SRCCLKENA (1U << 6) +#define R13_SSPM_APSRC_REQ (1U << 7) +#define R13_MD_STATE (1U << 8) +#define R13_EMI_CLK_OFF_2_ACK (1U << 9) +#define R13_MM_STATE (1U << 10) +#define R13_SSPM_STATE (1U << 11) +#define R13_MD_DDR_EN (1U << 12) +#define R13_CONN_STATE (1U << 13) +#define R13_CONN_SRCCLKENA (1U << 14) +#define R13_CONN_APSRC_REQ (1U << 15) +#define R13_SLEEP_EVENT_STA (1U << 16) +#define R13_WAKE_EVENT_STA (1U << 17) +#define R13_EMI_IDLE (1U << 18) +#define R13_CSYSPWRUPREQ (1U << 19) +#define R13_PWRAP_SLEEP_ACK (1U << 20) +#define R13_EMI_CLK_OFF_ACK_ALL (1U << 21) +#define R13_TOP_MAS_PAU_ACK (1U << 22) +#define R13_SW_DMDRAMCSHU_ACK_ALL (1U << 23) +#define R13_RC2SPM_EVENT_ABORT_MASK_OR (1U << 24) +#define R13_DR_SHORT_QUEUE_ACK_ALL (1U << 25) +#define R13_INFRA_AUX_IDLE (1U << 26) +#define R13_DVFS_ALL_STATE (1U << 27) +#define R13_RC2SPM_EVENT_ABORT_OR (1U << 28) +#define R13_DRAMC_SPCMD_APSRC_REQ (1U << 29) +#define R13_MD1_VRF18_REQ (1U << 30) +#define R13_C2K_VRF18_REQ (1U << 31) + +#define is_cpu_pdn(flags) (!((flags) & SPM_FLAG_DIS_CPU_PDN)) +#define is_infra_pdn(flags) (!((flags) & SPM_FLAG_DIS_INFRA_PDN)) +#define is_ddrphy_pdn(flags) (!((flags) & SPM_FLAG_DIS_DDRPHY_PDN)) + +#define MP0_SPMC_SRAM_DORMANT_EN (1<<0) +#define MP1_SPMC_SRAM_DORMANT_EN (1<<1) +#define MP2_SPMC_SRAM_DORMANT_EN (1<<2) + +#define EVENT_VEC(event, resume, imme, pc) \ + (((pc) << 16) | \ + (!!(imme) << 7) | \ + (!!(resume) << 6) | \ + ((event) & 0x3f)) + +#define SPM_PROJECT_CODE 0xb16 +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) + +/************************************** + * Config and Parameter + **************************************/ +#define POWER_ON_VAL1_DEF 0x00015800 +#define PCM_FSM_STA_DEF 0x00108490 +#define SPM_WAKEUP_EVENT_MASK_DEF 0xF0F92218 +#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */ +#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT) + +/************************************** + * Define and Declare + **************************************/ +/* PCM_PWR_IO_EN */ +#define PCM_PWRIO_EN_R0 (1U << 0) +#define PCM_PWRIO_EN_R7 (1U << 7) +#define PCM_RF_SYNC_R0 (1U << 16) +#define PCM_RF_SYNC_R6 (1U << 22) +#define PCM_RF_SYNC_R7 (1U << 23) + +/* SPM_SWINT */ +#define PCM_SW_INT0 (1U << 0) +#define PCM_SW_INT1 (1U << 1) +#define PCM_SW_INT2 (1U << 2) +#define PCM_SW_INT3 (1U << 3) +#define PCM_SW_INT4 (1U << 4) +#define PCM_SW_INT5 (1U << 5) +#define PCM_SW_INT6 (1U << 6) +#define PCM_SW_INT7 (1U << 7) +#define PCM_SW_INT8 (1U << 8) +#define PCM_SW_INT9 (1U << 9) +#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \ + PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \ + PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \ + PCM_SW_INT0) +/* SPM_IRQ_MASK */ +#define ISRM_TWAM (1U << 2) +#define ISRM_PCM_RETURN (1U << 3) +#define ISRM_RET_IRQ0 (1U << 8) +#define ISRM_RET_IRQ1 (1U << 9) +#define ISRM_RET_IRQ2 (1U << 10) +#define ISRM_RET_IRQ3 (1U << 11) +#define ISRM_RET_IRQ4 (1U << 12) +#define ISRM_RET_IRQ5 (1U << 13) +#define ISRM_RET_IRQ6 (1U << 14) +#define ISRM_RET_IRQ7 (1U << 15) +#define ISRM_RET_IRQ8 (1U << 16) +#define ISRM_RET_IRQ9 (1U << 17) +#define ISRM_RET_IRQ_AUX (ISRM_RET_IRQ9 | ISRM_RET_IRQ8 | \ + ISRM_RET_IRQ7 | ISRM_RET_IRQ6 | \ + ISRM_RET_IRQ5 | ISRM_RET_IRQ4 | \ + ISRM_RET_IRQ3 | ISRM_RET_IRQ2 | \ + ISRM_RET_IRQ1) +#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX) +#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM) + +/* SPM_IRQ_STA */ +#define ISRS_TWAM (1U << 2) +#define ISRS_PCM_RETURN (1U << 3) +#define ISRS_SW_INT0 (1U << 4) +#define ISRC_TWAM ISRS_TWAM +#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN +#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM) + +/* SPM_WAKEUP_MISC */ +#define WAKE_MISC_TWAM (1U << 18) +#define WAKE_MISC_PCM_TIMER (1U << 19) +#define WAKE_MISC_CPU_WAKE (1U << 20) + +enum SPM_WAKE_SRC_LIST { + WAKE_SRC_R12_PCM_TIMER = (1U << 0), + WAKE_SRC_R12_SSPM_WDT_EVENT_B = (1U << 1), + WAKE_SRC_R12_KP_IRQ_B = (1U << 2), + WAKE_SRC_R12_APWDT_EVENT_B = (1U << 3), + WAKE_SRC_R12_APXGPT1_EVENT_B = (1U << 4), + WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B = (1U << 5), + WAKE_SRC_R12_EINT_EVENT_B = (1U << 6), + WAKE_SRC_R12_CONN_WDT_IRQ_B = (1U << 7), + WAKE_SRC_R12_CCIF0_EVENT_B = (1U << 8), + WAKE_SRC_R12_LOWBATTERY_IRQ_B = (1U << 9), + WAKE_SRC_R12_SSPM_SPM_IRQ_B = (1U << 10), + WAKE_SRC_R12_SCP_SPM_IRQ_B = (1U << 11), + WAKE_SRC_R12_SCP_WDT_EVENT_B = (1U << 12), + WAKE_SRC_R12_PCM_WDT_WAKEUP_B = (1U << 13), + WAKE_SRC_R12_USB_CDSC_B = (1U << 14), + WAKE_SRC_R12_USB_POWERDWN_B = (1U << 15), + WAKE_SRC_R12_SYS_TIMER_EVENT_B = (1U << 16), + WAKE_SRC_R12_EINT_EVENT_SECURE_B = (1U << 17), + WAKE_SRC_R12_CCIF1_EVENT_B = (1U << 18), + WAKE_SRC_R12_UART0_IRQ_B = (1U << 19), + WAKE_SRC_R12_AFE_IRQ_MCU_B = (1U << 20), + WAKE_SRC_R12_THERM_CTRL_EVENT_B = (1U << 21), + WAKE_SRC_R12_SYS_CIRQ_IRQ_B = (1U << 22), + WAKE_SRC_R12_MD2AP_PEER_EVENT_B = (1U << 23), + WAKE_SRC_R12_CSYSPWREQ_B = (1U << 24), + WAKE_SRC_R12_MD1_WDT_B = (1U << 25), + WAKE_SRC_R12_CLDMA_EVENT_B = (1U << 26), + WAKE_SRC_R12_SEJ_WDT_GPT_B = (1U << 27), + WAKE_SRC_R12_ALL_SSPM_WAKEUP_B = (1U << 28), + WAKE_SRC_R12_CPU_IRQ_B = (1U << 29), + WAKE_SRC_R12_CPU_WFI_AND_B = (1U << 30), +}; + +struct pcm_desc { + const char *version; + const uint32_t *base; + const uint32_t base_dma; + const uint32_t size; + const uint32_t sess; + const uint32_t replace; + const uint32_t addr_2nd; + const uint32_t reserved; + + uint32_t vec0; + uint32_t vec1; + uint32_t vec2; + uint32_t vec3; + uint32_t vec4; + uint32_t vec5; + uint32_t vec6; + uint32_t vec7; + uint32_t vec8; + uint32_t vec9; + uint32_t vec10; + uint32_t vec11; + uint32_t vec12; + uint32_t vec13; + uint32_t vec14; + uint32_t vec15; +}; + +struct pwr_ctrl { + uint32_t pcm_flags; + uint32_t pcm_flags1; + uint32_t timer_val; + uint32_t wake_src; + + /* SPM_AP_STANDBY_CON */ + uint8_t wfi_op; + uint8_t mp0_cputop_idle_mask; + uint8_t mp1_cputop_idle_mask; + uint8_t mcusys_idle_mask; + uint8_t mm_mask_b; + uint8_t md_ddr_en_0_dbc_en; + uint8_t md_ddr_en_1_dbc_en; + uint8_t md_mask_b; + uint8_t sspm_mask_b; + uint8_t scp_mask_b; + uint8_t srcclkeni_mask_b; + uint8_t md_apsrc_1_sel; + uint8_t md_apsrc_0_sel; + uint8_t conn_ddr_en_dbc_en; + uint8_t conn_mask_b; + uint8_t conn_apsrc_sel; + + /* SPM_SRC_REQ */ + uint8_t spm_apsrc_req; + uint8_t spm_f26m_req; + uint8_t spm_infra_req; + uint8_t spm_vrf18_req; + uint8_t spm_ddren_req; + uint8_t spm_rsv_src_req; + uint8_t spm_ddren_2_req; + uint8_t cpu_md_dvfs_sop_force_on; + + /* SPM_SRC_MASK */ + uint8_t csyspwreq_mask; + uint8_t ccif0_md_event_mask_b; + uint8_t ccif0_ap_event_mask_b; + uint8_t ccif1_md_event_mask_b; + uint8_t ccif1_ap_event_mask_b; + uint8_t ccif2_md_event_mask_b; + uint8_t ccif2_ap_event_mask_b; + uint8_t ccif3_md_event_mask_b; + uint8_t ccif3_ap_event_mask_b; + uint8_t md_srcclkena_0_infra_mask_b; + uint8_t md_srcclkena_1_infra_mask_b; + uint8_t conn_srcclkena_infra_mask_b; + uint8_t ufs_infra_req_mask_b; + uint8_t srcclkeni_infra_mask_b; + uint8_t md_apsrc_req_0_infra_mask_b; + uint8_t md_apsrc_req_1_infra_mask_b; + uint8_t conn_apsrcreq_infra_mask_b; + uint8_t ufs_srcclkena_mask_b; + uint8_t md_vrf18_req_0_mask_b; + uint8_t md_vrf18_req_1_mask_b; + uint8_t ufs_vrf18_req_mask_b; + uint8_t gce_vrf18_req_mask_b; + uint8_t conn_infra_req_mask_b; + uint8_t gce_apsrc_req_mask_b; + uint8_t disp0_apsrc_req_mask_b; + uint8_t disp1_apsrc_req_mask_b; + uint8_t mfg_req_mask_b; + uint8_t vdec_req_mask_b; + + /* SPM_SRC2_MASK */ + uint8_t md_ddr_en_0_mask_b; + uint8_t md_ddr_en_1_mask_b; + uint8_t conn_ddr_en_mask_b; + uint8_t ddren_sspm_apsrc_req_mask_b; + uint8_t ddren_scp_apsrc_req_mask_b; + uint8_t disp0_ddren_mask_b; + uint8_t disp1_ddren_mask_b; + uint8_t gce_ddren_mask_b; + uint8_t ddren_emi_self_refresh_ch0_mask_b; + uint8_t ddren_emi_self_refresh_ch1_mask_b; + + /* SPM_WAKEUP_EVENT_MASK */ + uint32_t spm_wakeup_event_mask; + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + uint32_t spm_wakeup_event_ext_mask; + + /* SPM_SRC3_MASK */ + uint8_t md_ddr_en_2_0_mask_b; + uint8_t md_ddr_en_2_1_mask_b; + uint8_t conn_ddr_en_2_mask_b; + uint8_t ddren2_sspm_apsrc_req_mask_b; + uint8_t ddren2_scp_apsrc_req_mask_b; + uint8_t disp0_ddren2_mask_b; + uint8_t disp1_ddren2_mask_b; + uint8_t gce_ddren2_mask_b; + uint8_t ddren2_emi_self_refresh_ch0_mask_b; + uint8_t ddren2_emi_self_refresh_ch1_mask_b; + + uint8_t mp0_cpu0_wfi_en; + uint8_t mp0_cpu1_wfi_en; + uint8_t mp0_cpu2_wfi_en; + uint8_t mp0_cpu3_wfi_en; + + uint8_t mp1_cpu0_wfi_en; + uint8_t mp1_cpu1_wfi_en; + uint8_t mp1_cpu2_wfi_en; + uint8_t mp1_cpu3_wfi_en; +}; + +struct wake_status { + uint32_t assert_pc; + uint32_t r12; + uint32_t r12_ext; + uint32_t raw_sta; + uint32_t raw_ext_sta; + uint32_t wake_misc; + uint32_t timer_out; + uint32_t r13; + uint32_t r15; + uint32_t idle_sta; + uint32_t req_sta; + uint32_t debug_flag; + uint32_t debug_flag1; + uint32_t event_reg; + uint32_t isr; + uint32_t sw_flag; + uint32_t sw_flag1; + uint32_t log_index; +}; + +typedef struct spm_data { + unsigned int cmd; + union { + struct { + unsigned int sys_timestamp_l; + unsigned int sys_timestamp_h; + unsigned int sys_src_clk_l; + unsigned int sys_src_clk_h; + unsigned int spm_opt; + } suspend; + struct { + unsigned int args1; + unsigned int args2; + unsigned int args3; + unsigned int args4; + unsigned int args5; + unsigned int args6; + unsigned int args7; + } args; + } u; +} spm_data_t; + +enum { + SPM_SUSPEND, + SPM_RESUME +}; + +extern void spm_disable_pcm_timer(void); +extern void spm_set_bootaddr(unsigned long bootaddr); +extern void spm_set_cpu_status(int cpu); +extern void spm_set_power_control(const struct pwr_ctrl *pwrctrl); +extern void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl); +extern void spm_set_pcm_flags(const struct pwr_ctrl *pwrctrl); +extern void spm_send_cpu_wakeup_event(void); +extern void spm_get_wakeup_status(struct wake_status *wakesta); +extern void spm_clean_after_wakeup(void); +extern void spm_output_wake_reason(struct wake_status *wakesta, + const char *scenario); +extern void spm_set_pcm_wdt(int en); +extern void spm_lock_get(void); +extern void spm_lock_release(void); +extern void spm_boot_init(void); +extern const char *spm_get_firmware_version(void); + +#endif /* SPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c new file mode 100644 index 0000000..ce85272 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#define SLEEP_REG_MD_SPM_DVFS_CMD20 (SLEEP_REG_MD_BASE + 0x010) +#define SLEEP_REG_MD_SPM_DVFS_CMD21 (SLEEP_REG_MD_BASE + 0x014) +#define SLEEP_REG_MD_SPM_DVFS_CMD22 (SLEEP_REG_MD_BASE + 0x018) +#define SLEEP_REG_MD_SPM_DVFS_CMD23 (SLEEP_REG_MD_BASE + 0x01C) + +/* PMIC_WRAP -> PMIC MT6358 */ +#define VCORE_BASE_UV 50000 +#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625) +#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + VCORE_BASE_UV) + +#define DEFAULT_VOLT_VSRAM (100000) +#define DEFAULT_VOLT_VCORE (100000) +#define NR_PMIC_WRAP_CMD (NR_IDX_ALL) +#define MAX_RETRY_COUNT (100) +#define SPM_DATA_SHIFT (16) + +#define BUCK_VCORE_ELR0 0x14AA +#define BUCK_VPROC12_CON0 0x1408 +#define BUCK_VPROC11_CON0 0x1388 +#define TOP_SPI_CON0 0x044C +#define LDO_VSRAM_PROC12_CON0 0x1B88 +#define LDO_VSRAM_PROC11_CON0 0x1B46 +#define BUCK_VMODEM_ELR0 0x15A6 + +struct pmic_wrap_cmd { + unsigned long cmd_addr; + unsigned long cmd_wdata; +}; + +struct pmic_wrap_setting { + enum pmic_wrap_phase_id phase; + struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD]; + struct { + struct { + unsigned long cmd_addr; + unsigned long cmd_wdata; + } _[NR_PMIC_WRAP_CMD]; + const int nr_idx; + } set[NR_PMIC_WRAP_PHASE]; +}; + +static struct pmic_wrap_setting pw = { + .phase = NR_PMIC_WRAP_PHASE, + .addr = {{0, 0} }, + .set[PMIC_WRAP_PHASE_ALLINONE] = { + ._[CMD_0] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(70000),}, + ._[CMD_1] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(80000),}, + ._[CMD_2] = {BUCK_VPROC12_CON0, 0x3,}, + ._[CMD_3] = {BUCK_VPROC12_CON0, 0x1,}, + ._[CMD_4] = {BUCK_VPROC11_CON0, 0x3,}, + ._[CMD_5] = {BUCK_VPROC11_CON0, 0x1,}, + ._[CMD_6] = {TOP_SPI_CON0, 0x1,}, + ._[CMD_7] = {TOP_SPI_CON0, 0x0,}, + ._[CMD_8] = {BUCK_VPROC12_CON0, 0x0,}, + ._[CMD_9] = {BUCK_VPROC12_CON0, 0x1,}, + ._[CMD_10] = {BUCK_VPROC11_CON0, 0x0,}, + ._[CMD_11] = {BUCK_VPROC11_CON0, 0x1,}, + ._[CMD_12] = {LDO_VSRAM_PROC12_CON0, 0x0,}, + ._[CMD_13] = {LDO_VSRAM_PROC12_CON0, 0x1,}, + ._[CMD_14] = {LDO_VSRAM_PROC11_CON0, 0x0,}, + ._[CMD_15] = {LDO_VSRAM_PROC11_CON0, 0x1,}, + ._[CMD_20] = {BUCK_VMODEM_ELR0, VOLT_TO_PMIC_VAL(55000),}, + ._[CMD_21] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(60000),}, + ._[CMD_22] = {LDO_VSRAM_PROC11_CON0, 0x3,}, + ._[CMD_23] = {LDO_VSRAM_PROC11_CON0, 0x1,}, + .nr_idx = NR_IDX_ALL + } +}; + +void _mt_spm_pmic_table_init(void) +{ + struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = { + {(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,}, + {(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,}, + {(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,}, + {(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,}, + {(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,}, + {(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,}, + {(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,}, + {(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,}, + {(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,}, + {(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,}, + {(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,}, + {(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,}, + {(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,}, + {(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,}, + {(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,}, + {(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,}, + {(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20, + (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,}, + {(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21, + (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,}, + {(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22, + (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,}, + {(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23, + (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,} + }; + + memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default)); +} + +void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase) +{ + uint32_t idx, addr, data; + + if (phase >= NR_PMIC_WRAP_PHASE) + return; + + if (pw.phase == phase) + return; + + if (pw.addr[0].cmd_addr == 0) + _mt_spm_pmic_table_init(); + + pw.phase = phase; + + mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | + BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB); + for (idx = 0; idx < pw.set[phase].nr_idx; idx++) { + addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; + data = pw.set[phase]._[idx].cmd_wdata; + mmio_write_32(pw.addr[idx].cmd_addr, addr | data); + } +} + +void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx, + uint32_t cmd_wdata) +{ + uint32_t addr; + + if (phase >= NR_PMIC_WRAP_PHASE) + return; + + if (idx >= pw.set[phase].nr_idx) + return; + + pw.set[phase]._[idx].cmd_wdata = cmd_wdata; + + mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | + BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB); + if (pw.phase == phase) { + addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; + mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata); + } +} + +uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx) +{ + if (phase >= NR_PMIC_WRAP_PHASE) + return 0; + + if (idx >= pw.set[phase].nr_idx) + return 0; + + return pw.set[phase]._[idx].cmd_wdata; +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h new file mode 100644 index 0000000..194d347 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/**************************************************************** + * Auto generated by DE, please DO NOT modify this file directly. + *****************************************************************/ + +#ifndef SPM_PMIC_WRAP__H +#define SPM_PMIC_WRAP__H + +enum pmic_wrap_phase_id { + PMIC_WRAP_PHASE_ALLINONE, + NR_PMIC_WRAP_PHASE +}; + +/* IDX mapping */ +enum { + CMD_0, /* 0x0 *//* PMIC_WRAP_PHASE_ALLINONE */ + CMD_1, /* 0x1 */ + CMD_2, /* 0x2 */ + CMD_3, /* 0x3 */ + CMD_4, /* 0x4 */ + CMD_5, /* 0x5 */ + CMD_6, /* 0x6 */ + CMD_7, /* 0x7 */ + CMD_8, /* 0x8 */ + CMD_9, /* 0x9 */ + CMD_10, /* 0xA */ + CMD_11, /* 0xB */ + CMD_12, /* 0xC */ + CMD_13, /* 0xD */ + CMD_14, /* 0xE */ + CMD_15, /* 0xF */ + CMD_20, /* 0x14 */ + CMD_21, /* 0x15 */ + CMD_22, /* 0x16 */ + CMD_23, /* 0x17 */ + NR_IDX_ALL +}; + +/* APIs */ +void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase); +void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, + uint32_t idx, uint32_t cmd_wdata); +uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx); +#endif /* SPM_PMIC_WRAP__H */ + diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c new file mode 100644 index 0000000..b9ac19f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPM_SYSCLK_SETTLE 99 + +#define WAKE_SRC_FOR_SUSPEND \ + (WAKE_SRC_R12_PCM_TIMER | \ + WAKE_SRC_R12_SSPM_WDT_EVENT_B | \ + WAKE_SRC_R12_KP_IRQ_B | \ + WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B | \ + WAKE_SRC_R12_EINT_EVENT_B | \ + WAKE_SRC_R12_CONN_WDT_IRQ_B | \ + WAKE_SRC_R12_CCIF0_EVENT_B | \ + WAKE_SRC_R12_SSPM_SPM_IRQ_B | \ + WAKE_SRC_R12_SCP_SPM_IRQ_B | \ + WAKE_SRC_R12_SCP_WDT_EVENT_B | \ + WAKE_SRC_R12_USB_CDSC_B | \ + WAKE_SRC_R12_USB_POWERDWN_B | \ + WAKE_SRC_R12_SYS_TIMER_EVENT_B | \ + WAKE_SRC_R12_EINT_EVENT_SECURE_B | \ + WAKE_SRC_R12_CCIF1_EVENT_B | \ + WAKE_SRC_R12_MD2AP_PEER_EVENT_B | \ + WAKE_SRC_R12_MD1_WDT_B | \ + WAKE_SRC_R12_CLDMA_EVENT_B | \ + WAKE_SRC_R12_SEJ_WDT_GPT_B) + +#define SLP_PCM_FLAGS \ + (SPM_FLAG_DIS_VCORE_DVS | SPM_FLAG_DIS_VCORE_DFS | \ + SPM_FLAG_DIS_ATF_ABORT | SPM_FLAG_DISABLE_MMSYS_DVFS | \ + SPM_FLAG_DIS_INFRA_PDN | SPM_FLAG_SUSPEND_OPTION) + +#define SLP_PCM_FLAGS1 \ + (SPM_FLAG1_DISABLE_MCDSR) + +static const struct pwr_ctrl suspend_ctrl = { + .wake_src = WAKE_SRC_FOR_SUSPEND, + .pcm_flags = SLP_PCM_FLAGS, + .pcm_flags1 = SLP_PCM_FLAGS1, + + /* SPM_AP_STANDBY_CON */ + .wfi_op = 0x1, + .mp0_cputop_idle_mask = 0, + .mp1_cputop_idle_mask = 0, + .mcusys_idle_mask = 0, + .mm_mask_b = 0, + .md_ddr_en_0_dbc_en = 0x1, + .md_ddr_en_1_dbc_en = 0, + .md_mask_b = 0x1, + .sspm_mask_b = 0x1, + .scp_mask_b = 0x1, + .srcclkeni_mask_b = 0x1, + .md_apsrc_1_sel = 0, + .md_apsrc_0_sel = 0, + .conn_ddr_en_dbc_en = 0x1, + .conn_mask_b = 0x1, + .conn_apsrc_sel = 0, + + /* SPM_SRC_REQ */ + .spm_apsrc_req = 0, + .spm_f26m_req = 0, + .spm_infra_req = 0, + .spm_vrf18_req = 0, + .spm_ddren_req = 0, + .spm_rsv_src_req = 0, + .spm_ddren_2_req = 0, + .cpu_md_dvfs_sop_force_on = 0, + + /* SPM_SRC_MASK */ + .csyspwreq_mask = 0x1, + .ccif0_md_event_mask_b = 0x1, + .ccif0_ap_event_mask_b = 0x1, + .ccif1_md_event_mask_b = 0x1, + .ccif1_ap_event_mask_b = 0x1, + .ccif2_md_event_mask_b = 0x1, + .ccif2_ap_event_mask_b = 0x1, + .ccif3_md_event_mask_b = 0x1, + .ccif3_ap_event_mask_b = 0x1, + .md_srcclkena_0_infra_mask_b = 0x1, + .md_srcclkena_1_infra_mask_b = 0, + .conn_srcclkena_infra_mask_b = 0, + .ufs_infra_req_mask_b = 0, + .srcclkeni_infra_mask_b = 0, + .md_apsrc_req_0_infra_mask_b = 0x1, + .md_apsrc_req_1_infra_mask_b = 0x1, + .conn_apsrcreq_infra_mask_b = 0x1, + .ufs_srcclkena_mask_b = 0, + .md_vrf18_req_0_mask_b = 0, + .md_vrf18_req_1_mask_b = 0, + .ufs_vrf18_req_mask_b = 0, + .gce_vrf18_req_mask_b = 0, + .conn_infra_req_mask_b = 0x1, + .gce_apsrc_req_mask_b = 0, + .disp0_apsrc_req_mask_b = 0, + .disp1_apsrc_req_mask_b = 0, + .mfg_req_mask_b = 0, + .vdec_req_mask_b = 0, + + /* SPM_SRC2_MASK */ + .md_ddr_en_0_mask_b = 0x1, + .md_ddr_en_1_mask_b = 0, + .conn_ddr_en_mask_b = 0x1, + .ddren_sspm_apsrc_req_mask_b = 0x1, + .ddren_scp_apsrc_req_mask_b = 0x1, + .disp0_ddren_mask_b = 0x1, + .disp1_ddren_mask_b = 0x1, + .gce_ddren_mask_b = 0x1, + .ddren_emi_self_refresh_ch0_mask_b = 0, + .ddren_emi_self_refresh_ch1_mask_b = 0, + + /* SPM_WAKEUP_EVENT_MASK */ + .spm_wakeup_event_mask = 0xF1782218, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + .spm_wakeup_event_ext_mask = 0xFFFFFFFF, + + /* SPM_SRC3_MASK */ + .md_ddr_en_2_0_mask_b = 0x1, + .md_ddr_en_2_1_mask_b = 0, + .conn_ddr_en_2_mask_b = 0x1, + .ddren2_sspm_apsrc_req_mask_b = 0x1, + .ddren2_scp_apsrc_req_mask_b = 0x1, + .disp0_ddren2_mask_b = 0, + .disp1_ddren2_mask_b = 0, + .gce_ddren2_mask_b = 0, + .ddren2_emi_self_refresh_ch0_mask_b = 0, + .ddren2_emi_self_refresh_ch1_mask_b = 0, + + .mp0_cpu0_wfi_en = 0x1, + .mp0_cpu1_wfi_en = 0x1, + .mp0_cpu2_wfi_en = 0x1, + .mp0_cpu3_wfi_en = 0x1, + + .mp1_cpu0_wfi_en = 0x1, + .mp1_cpu1_wfi_en = 0x1, + .mp1_cpu2_wfi_en = 0x1, + .mp1_cpu3_wfi_en = 0x1 +}; + +static uint32_t spm_set_sysclk_settle(void) +{ + mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE); + return mmio_read_32(SPM_CLK_SETTLE); +} + +void go_to_sleep_before_wfi(void) +{ + int cpu = MPIDR_AFFLVL0_VAL(read_mpidr()); + uint32_t settle; + + settle = spm_set_sysclk_settle(); + spm_set_cpu_status(cpu); + spm_set_power_control(&suspend_ctrl); + spm_set_wakeup_event(&suspend_ctrl); + spm_set_pcm_flags(&suspend_ctrl); + spm_send_cpu_wakeup_event(); + spm_set_pcm_wdt(0); + spm_disable_pcm_timer(); + + if (is_infra_pdn(suspend_ctrl.pcm_flags)) + mt_uart_save(); + + if (!mt_console_uart_cg_status()) + console_switch_state(CONSOLE_FLAG_BOOT); + + INFO("cpu%d: \"%s\", wakesrc = 0x%x, pcm_con1 = 0x%x\n", + cpu, spm_get_firmware_version(), suspend_ctrl.wake_src, + mmio_read_32(PCM_CON1)); + INFO("settle = %u, sec = %u, sw_flag = 0x%x 0x%x, src_req = 0x%x\n", + settle, mmio_read_32(PCM_TIMER_VAL) / 32768, + suspend_ctrl.pcm_flags, suspend_ctrl.pcm_flags1, + mmio_read_32(SPM_SRC_REQ)); + + if (!mt_console_uart_cg_status()) + console_switch_state(CONSOLE_FLAG_RUNTIME); +} + +static void go_to_sleep_after_wfi(void) +{ + struct wake_status spm_wakesta; + + if (is_infra_pdn(suspend_ctrl.pcm_flags)) + mt_uart_restore(); + + spm_set_pcm_wdt(0); + spm_get_wakeup_status(&spm_wakesta); + spm_clean_after_wakeup(); + + if (!mt_console_uart_cg_status()) + console_switch_state(CONSOLE_FLAG_BOOT); + + spm_output_wake_reason(&spm_wakesta, "suspend"); + + if (!mt_console_uart_cg_status()) + console_switch_state(CONSOLE_FLAG_RUNTIME); +} + +static void spm_enable_armpll_l(void) +{ + /* power on */ + mmio_setbits_32(ARMPLL_L_PWR_CON0, 0x1); + + /* clear isolation */ + mmio_clrbits_32(ARMPLL_L_PWR_CON0, 0x2); + + /* enable pll */ + mmio_setbits_32(ARMPLL_L_CON0, 0x1); + + /* Add 20us delay for turning on PLL */ + udelay(20); +} + +static void spm_disable_armpll_l(void) +{ + /* disable pll */ + mmio_clrbits_32(ARMPLL_L_CON0, 0x1); + + /* isolation */ + mmio_setbits_32(ARMPLL_L_PWR_CON0, 0x2); + + /* power off */ + mmio_clrbits_32(ARMPLL_L_PWR_CON0, 0x1); +} + +void spm_system_suspend(void) +{ + spm_disable_armpll_l(); + bcpu_enable(0); + bcpu_sram_enable(0); + spm_lock_get(); + go_to_sleep_before_wfi(); + spm_lock_release(); +} + +void spm_system_suspend_finish(void) +{ + spm_lock_get(); + go_to_sleep_after_wfi(); + spm_lock_release(); + spm_enable_armpll_l(); + bcpu_sram_enable(1); + bcpu_enable(1); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h new file mode 100644 index 0000000..e127c2e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SPM_SUSPEND_H__ +#define __SPM_SUSPEND_H__ + +void spm_system_suspend(void); +void spm_system_suspend_finish(void); + +#endif /* __SPM_SUSPEND_H__*/ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c new file mode 100644 index 0000000..ac8e1b4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtspmc_private.h" + + +static void set_retention(int cluster, int tick) +{ + uint64_t cpuectlr; + + if (cluster) + cpuectlr = read_a73_cpuectlr_el1(); + else + cpuectlr = read_a53_cpuectlr_el1(); + + cpuectlr &= ~0x7ULL; + cpuectlr |= tick & 0x7; + + if (cluster) + write_a73_cpuectlr_el1(cpuectlr); + else + write_a53_cpuectlr_el1(cpuectlr); +} + +void spm_enable_cpu_auto_off(int cluster, int cpu) +{ + uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK); + + set_retention(cluster, 1); + mmio_clrbits_32(reg, SW_NO_WAIT_Q); +} + +void spm_disable_cpu_auto_off(int cluster, int cpu) +{ + uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK); + + mmio_setbits_32(reg, SW_NO_WAIT_Q); + set_retention(cluster, 0); +} + +void spm_set_cpu_power_off(int cluster, int cpu) +{ + mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON); +} + +void spm_enable_cluster_auto_off(int cluster) +{ + assert(cluster); + + mmio_clrbits_32(MCUCFG_MP2_SPMC, SW_NO_WAIT_Q); + mmio_clrbits_32(MCUCFG_MP2_COQ, BIT(0)); + + mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, MP1_SPMC_SRAM_DORMANT_EN); + + mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON); +} + +void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr) +{ + uintptr_t reg; + const uintptr_t mp2_bootreg[] = { + MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1, + MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 }; + + if (cluster) { + assert(cpu >= 0 && cpu < 4); + reg = mp2_bootreg[cpu]; + } else { + reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR); + } + + mmio_write_32(reg, bootaddr); +} + +uintptr_t mcucfg_get_bootaddr(int cluster, int cpu) +{ + uintptr_t reg; + const uintptr_t mp2_bootreg[] = { + MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1, + MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 }; + + if (cluster) { + assert(cpu >= 0 && cpu < 4); + reg = mp2_bootreg[cpu]; + } else { + reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR); + } + + return mmio_read_32(reg); +} + +void mcucfg_init_archstate(int cluster, int cpu, int arm64) +{ + uintptr_t reg; + int i; + + reg = per_cluster(cluster, MCUCFG_INITARCH); + i = cluster ? 16 : 12; + + mmio_setbits_32(reg, (arm64 & 1) << (i + cpu)); +} + +/** + * Return power state of specified subsystem + * + * @mask: mask to SPM_PWR_STATUS to query the power state + * of one subsystem. + * RETURNS: + * 0 (the subsys was powered off) + * 1 (the subsys was powered on) + */ +int spm_get_powerstate(uint32_t mask) +{ + return mmio_read_32(SPM_PWR_STATUS) & mask; +} + +int spm_get_cluster_powerstate(int cluster) +{ + uint32_t mask; + + mask = cluster ? PWR_STATUS_MP1_CPUTOP : PWR_STATUS_MP0_CPUTOP; + + return spm_get_powerstate(mask); +} + +int spm_get_cpu_powerstate(int cluster, int cpu) +{ + uint32_t i; + + /* + * a quick way to specify the mask of cpu[0-3]/cpu[4-7] in PWR_STATUS + * register which are the BITS[9:12](MP0_CPU0~3) and + * BITS[16:19](MP1_CPU0~3) + */ + i = (cluster) ? 16 : 9; + i = 1 << (i + cpu); + + return spm_get_powerstate(i); +} + +int spmc_init(void) +{ + /* enable SPM register control */ + mmio_write_32(SPM_POWERON_CONFIG_EN, + PROJECT_CODE | MD_BCLK_CG_EN | BCLK_CG_EN); + +#if SPMC_MODE == 1 + INFO("SPM: enable SPMC mode\n"); + + /* 0: SPMC mode 1: Legacy mode */ + mmio_write_32(SPM_BYPASS_SPMC, 0); + + mmio_clrbits_32(per_cluster(0, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND); + + mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + mmio_clrbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + mmio_clrbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + mmio_clrbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + + mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); + mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); + mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); +#endif + + mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND); + mmio_setbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_RST_B); + mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_CLK_DIS); + + mmio_clrbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + mmio_clrbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + mmio_clrbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + mmio_clrbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + + mmio_setbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); + mmio_setbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); + mmio_setbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); + mmio_setbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); + + return 0; +} + +/** + * Power on a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered on + * @cpu: the CPU ID of the CPU which to be powered on + */ +void spm_poweron_cpu(int cluster, int cpu) +{ + INFO("spmc: power on core %d.%d\n", cluster, cpu); + + /* STA_POWER_ON */ + /* Start to turn on MP0_CPU0 */ + + /* Set PWR_RST_B = 1 */ + mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); + + /* Set PWR_ON = 1 */ + mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON); + + /* Wait until MP0_CPU0_PWR_STA_MASK = 1 */ + while (!spm_get_cpu_powerstate(cluster, cpu)) + ; + + /* Finish to turn on MP0_CPU0 */ + INFO("spmc: power on core %d.%d successfully\n", cluster, cpu); +} + +/** + * Power off a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered off + * @cpu: the CPU ID of the CPU which to be powered off + */ +void spm_poweroff_cpu(int cluster, int cpu) +{ + INFO("spmc: power off core %d.%d\n", cluster, cpu); + + /* Start to turn off MP0_CPU0 */ + /* Set PWR_ON_2ND = 0 */ + mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); + + /* Set PWR_ON = 0 */ + mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON); + + /* Wait until MP0_CPU0_PWR_STA_MASK = 0 */ + while (spm_get_cpu_powerstate(cluster, cpu)) + ; + + /* Set PWR_RST_B = 0 */ + mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); + + /* Finish to turn off MP0_CPU0 */ + INFO("spmc: power off core %d.%d successfully\n", cluster, cpu); +} + +/** + * Power off a cluster with specified index + * + * @cluster: the cluster index which to be powered off + */ +void spm_poweroff_cluster(int cluster) +{ + uint32_t mask; + uint32_t pwr_rst_ctl; + + INFO("spmc: power off cluster %d\n", cluster); + + /* Start to turn off MP0_CPUTOP */ + /* Set bus protect - step1 : 0 */ + mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK : + MP0_CPUTOP_PROT_STEP1_0_MASK; + mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_SET, mask); + + while ((mmio_read_32(INFRA_TOPAXI_PROTECTEN_STA1_1) & mask) != mask) + ; + + /* Set PWR_ON_2ND = 0 */ + mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), + PWRCTRL_PWR_ON_2ND); + + /* SPMC_DORMANT_ENABLE[0]=0 */ + mask = (cluster) ? MP1_SPMC_SRAM_DORMANT_EN : MP0_SPMC_SRAM_DORMANT_EN; + mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, mask); + + /* Set PWR_ON = 0" */ + mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON); + + /* Wait until MP0_CPUTOP_PWR_STA_MASK = 0 */ + while (spm_get_cluster_powerstate(cluster)) + ; + + /* NOTE + * Following flow only for BIG core cluster. It was from + * application note but not covered in mtcmos_ctrl.c + */ + if (cluster) { + pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL); + mmio_write_32(MCUCFG_MP2_PWR_RST_CTL, + (pwr_rst_ctl & ~SW_RST_B) | TOPAON_APB_MASK); + } + + /* CPU_EXT_BUCK_ISO[0]=1 */ + if (cluster) + mmio_setbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO); + + /* Finish to turn off MP0_CPUTOP */ + INFO("spmc: power off cluster %d successfully\n", cluster); +} + +/** + * Power on a cluster with specified index + * + * @cluster: the cluster index which to be powered on + */ +void spm_poweron_cluster(int cluster) +{ + uint32_t mask; + uint32_t pwr_rst_ctl; + + INFO("spmc: power on cluster %d\n", cluster); + + /* Start to turn on MP1_CPUTOP */ + + /* NOTE + * Following flow only for BIG core cluster. It was from + * application note but not covered in mtcmos_ctrl.c + */ + if (cluster) { + mmio_clrbits_32(MCUCFG_MP2_PWR_RST_CTL, SW_RST_B); + + /* CPU_EXT_BUCK_ISO[1]=0 */ + /* Set mp_vproc_ext_off to 0 to release vproc isolation control */ + mmio_clrbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO); + + /* NOTE + * Following flow only for BIG core cluster. It was from + * application note but not covered in mtcmos_ctrl.c + */ + pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL); + mmio_write_32(MCUCFG_MP2_PWR_RST_CTL, + (pwr_rst_ctl | SW_RST_B) & ~TOPAON_APB_MASK); + } + + /* Set PWR_ON_2ND = 0 */ + mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), + PWRCTRL_PWR_ON_2ND); + + /* Set PWR_RST_B = 1 */ + mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), + PWRCTRL_PWR_RST_B); + + /* Set PWR_CLK_DIS = 0 */ + mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), + PWRCTRL_PWR_CLK_DIS); + + /* Set PWR_ON = 1 */ + mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON); + + /* Wait until MP1_CPUTOP_PWR_STA_MASK = 1 */ + while (!spm_get_cluster_powerstate(cluster)) + ; + + /* Release bus protect - step1 : 0 */ + mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK : + MP0_CPUTOP_PROT_STEP1_0_MASK; + mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_CLR, mask); + + /* Finish to turn on MP1_CPUTOP */ + INFO("spmc: power on cluster %d successfully\n", cluster); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h new file mode 100644 index 0000000..4cf3bcf --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_H +#define MTSPMC_H + +/* + * CONFIG_SPMC_MODE: Select CPU power control mode. + * + * 0: Legacy + * Control power flow from SW through SPM register (MP*_PWR_CON). + * 1: HW + * Control power flow from SPMC. Most control flow and timing are handled + * by SPMC. + */ +#define SPMC_MODE 1 + +int spmc_init(void); + +void spm_poweron_cpu(int cluster, int cpu); +void spm_poweroff_cpu(int cluster, int cpu); + +void spm_poweroff_cluster(int cluster); +void spm_poweron_cluster(int cluster); + +int spm_get_cpu_powerstate(int cluster, int cpu); +int spm_get_cluster_powerstate(int cluster); +int spm_get_powerstate(uint32_t mask); + +void spm_enable_cpu_auto_off(int cluster, int cpu); +void spm_disable_cpu_auto_off(int cluster, int cpu); +void spm_set_cpu_power_off(int cluster, int cpu); +void spm_enable_cluster_auto_off(int cluster); + +void mcucfg_init_archstate(int cluster, int cpu, int arm64); +void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr); +uintptr_t mcucfg_get_bootaddr(int cluster, int cpu); + +#endif /* MTSPMC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000..2228e63 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_PRIVATE_H +#define MTSPMC_PRIVATE_H + +/* + * per_cpu/cluster helper + */ +struct per_cpu_reg { + int cluster_addr; + int cpu_stride; +}; + +#define per_cpu(cluster, cpu, reg) (reg[cluster].cluster_addr + \ + (cpu << reg[cluster].cpu_stride)) +#define per_cluster(cluster, reg) (reg[cluster].cluster_addr) + +/* SPMC related registers */ +#define SPM_POWERON_CONFIG_EN (SPM_BASE + 0x000) +/* bit-fields of SPM_POWERON_CONFIG_EN */ +#define BCLK_CG_EN (1 << 0) +#define MD_BCLK_CG_EN (1 << 1) +#define PROJECT_CODE (0xb16 << 16) + +#define SPM_PWR_STATUS (SPM_BASE + 0x180) +#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x184) + +#define SPM_BYPASS_SPMC (SPM_BASE + 0x2b4) +#define SPM_SPMC_DORMANT_ENABLE (SPM_BASE + 0x2b8) + +#define SPM_MP0_CPUTOP_PWR_CON (SPM_BASE + 0x204) +#define SPM_MP0_CPU0_PWR_CON (SPM_BASE + 0x208) +#define SPM_MP0_CPU1_PWR_CON (SPM_BASE + 0x20C) +#define SPM_MP0_CPU2_PWR_CON (SPM_BASE + 0x210) +#define SPM_MP0_CPU3_PWR_CON (SPM_BASE + 0x214) +#define SPM_MP1_CPUTOP_PWR_CON (SPM_BASE + 0x218) +#define SPM_MP1_CPU0_PWR_CON (SPM_BASE + 0x21C) +#define SPM_MP1_CPU1_PWR_CON (SPM_BASE + 0x220) +#define SPM_MP1_CPU2_PWR_CON (SPM_BASE + 0x224) +#define SPM_MP1_CPU3_PWR_CON (SPM_BASE + 0x228) +#define SPM_MP0_CPUTOP_L2_PDN (SPM_BASE + 0x240) +#define SPM_MP0_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x244) +#define SPM_MP0_CPU0_L1_PDN (SPM_BASE + 0x248) +#define SPM_MP0_CPU1_L1_PDN (SPM_BASE + 0x24C) +#define SPM_MP0_CPU2_L1_PDN (SPM_BASE + 0x250) +#define SPM_MP0_CPU3_L1_PDN (SPM_BASE + 0x254) +#define SPM_MP1_CPUTOP_L2_PDN (SPM_BASE + 0x258) +#define SPM_MP1_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x25C) +#define SPM_MP1_CPU0_L1_PDN (SPM_BASE + 0x260) +#define SPM_MP1_CPU1_L1_PDN (SPM_BASE + 0x264) +#define SPM_MP1_CPU2_L1_PDN (SPM_BASE + 0x268) +#define SPM_MP1_CPU3_L1_PDN (SPM_BASE + 0x26C) + +#define SPM_CPU_EXT_BUCK_ISO (SPM_BASE + 0x290) +/* bit-fields of SPM_CPU_EXT_BUCK_ISO */ +#define MP0_EXT_BUCK_ISO (1 << 0) +#define MP1_EXT_BUCK_ISO (1 << 1) +#define MP_EXT_BUCK_ISO (1 << 2) + +/* bit-fields of SPM_PWR_STATUS */ +#define PWR_STATUS_MD (1 << 0) +#define PWR_STATUS_CONN (1 << 1) +#define PWR_STATUS_DDRPHY (1 << 2) +#define PWR_STATUS_DISP (1 << 3) +#define PWR_STATUS_MFG (1 << 4) +#define PWR_STATUS_ISP (1 << 5) +#define PWR_STATUS_INFRA (1 << 6) +#define PWR_STATUS_VDEC (1 << 7) +#define PWR_STATUS_MP0_CPUTOP (1 << 8) +#define PWR_STATUS_MP0_CPU0 (1 << 9) +#define PWR_STATUS_MP0_CPU1 (1 << 10) +#define PWR_STATUS_MP0_CPU2 (1 << 11) +#define PWR_STATUS_MP0_CPU3 (1 << 12) +#define PWR_STATUS_MCUSYS (1 << 14) +#define PWR_STATUS_MP1_CPUTOP (1 << 15) +#define PWR_STATUS_MP1_CPU0 (1 << 16) +#define PWR_STATUS_MP1_CPU1 (1 << 17) +#define PWR_STATUS_MP1_CPU2 (1 << 18) +#define PWR_STATUS_MP1_CPU3 (1 << 19) +#define PWR_STATUS_VEN (1 << 21) +#define PWR_STATUS_MFG_ASYNC (1 << 23) +#define PWR_STATUS_AUDIO (1 << 24) +#define PWR_STATUS_C2K (1 << 28) +#define PWR_STATUS_MD_INFRA (1 << 29) + + +/* bit-fields of SPM_*_PWR_CON */ +#define PWRCTRL_PWR_RST_B (1 << 0) +#define PWRCTRL_PWR_ISO (1 << 1) +#define PWRCTRL_PWR_ON (1 << 2) +#define PWRCTRL_PWR_ON_2ND (1 << 3) +#define PWRCTRL_PWR_CLK_DIS (1 << 4) +#define PWRCTRL_PWR_SRAM_CKISO (1 << 5) +#define PWRCTRL_PWR_SRAM_ISOINT_B (1 << 6) +#define PWRCTRL_PWR_SRAM_PD_SLPB_CLAMP (1 << 7) +#define PWRCTRL_PWR_SRAM_PDN (1 << 8) +#define PWRCTRL_PWR_SRAM_SLEEP_B (1 << 12) +#define PWRCTRL_PWR_SRAM_PDN_ACK (1 << 24) +#define PWRCTRL_PWR_SRAM_SLEEP_B_ACK (1 << 28) + +/* per_cpu registers for SPM_MP?_CPU?_PWR_CON */ +static const struct per_cpu_reg SPM_CPU_PWR[] = { + [0] = { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2 }, + [1] = { .cluster_addr = SPM_MP1_CPU0_PWR_CON, .cpu_stride = 2 }, +}; + +/* per_cluster registers for SPM_MP?_CPUTOP_PWR_CON */ +static const struct per_cpu_reg SPM_CLUSTER_PWR[] = { + [0] = { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON }, + [1] = { .cluster_addr = SPM_MP1_CPUTOP_PWR_CON }, +}; + +/* APB Module infracfg_ao */ +#define INFRA_TOPAXI_PROTECTEN_1 (INFRACFG_AO_BASE + 0x250) +#define INFRA_TOPAXI_PROTECTEN_STA1_1 (INFRACFG_AO_BASE + 0x258) +#define INFRA_TOPAXI_PROTECTEN_1_SET (INFRACFG_AO_BASE + 0x2A8) +#define INFRA_TOPAXI_PROTECTEN_1_CLR (INFRACFG_AO_BASE + 0x2AC) + +/* bit-fields of INFRA_TOPAXI_PROTECTEN_1_SET */ +#define MP0_CPUTOP_PROT_STEP1_0_MASK ((1 << 10)|(1 << 12)| \ + (1 << 13)|(1 << 26)) +#define MP1_CPUTOP_PROT_STEP1_0_MASK ((1 << 11)|(1 << 14)| \ + (1 << 15)|(1 << 27)) + +/* bit-fields of INFRA_TOPAXI_PROTECTEN_STA1_1 */ +#define MP0_CPUTOP_PROT_STEP1_0_ACK_MASK ((1 << 10)|(1 << 12)| \ + (1 << 13)|(1 << 26)) +#define MP1_CPUTOP_PROT_STEP1_0_ACK_MASK ((1 << 11)|(1 << 14)| \ + (1 << 15)|(1 << 27)) + + +/* + * MCU configuration registers + */ + +/* bit-fields of MCUCFG_MP?_AXI_CONFIG */ +#define MCUCFG_AXI_CONFIG_BROADCASTINNER (1 << 0) +#define MCUCFG_AXI_CONFIG_BROADCASTOUTER (1 << 1) +#define MCUCFG_AXI_CONFIG_BROADCASTCACHEMAINT (1 << 2) +#define MCUCFG_AXI_CONFIG_SYSBARDISABLE (1 << 3) +#define MCUCFG_AXI_CONFIG_ACINACTM (1 << 4) +#define MCUCFG_AXI_CONFIG_AINACTS (1 << 5) + + +#define MCUCFG_MP0_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[2]) +#define MCUCFG_MP0_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[3]) +#define MCUCFG_MP1_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp1_misc_config[2]) +#define MCUCFG_MP1_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp1_misc_config[3]) + +#define MCUCFG_CPUSYS0_SPARKVRETCNTRL (MCUCFG_BASE + 0x1c00) +/* bit-fields of MCUCFG_CPUSYS0_SPARKVRETCNTRL */ +#define CPU0_SPARK_VRET_CTRL (0x3f << 0) +#define CPU1_SPARK_VRET_CTRL (0x3f << 8) +#define CPU2_SPARK_VRET_CTRL (0x3f << 16) +#define CPU3_SPARK_VRET_CTRL (0x3f << 24) + +/* SPARK control in little cores */ +#define MCUCFG_CPUSYS0_CPU0_SPMC_CTL (MCUCFG_BASE + 0x1c30) +#define MCUCFG_CPUSYS0_CPU1_SPMC_CTL (MCUCFG_BASE + 0x1c34) +#define MCUCFG_CPUSYS0_CPU2_SPMC_CTL (MCUCFG_BASE + 0x1c38) +#define MCUCFG_CPUSYS0_CPU3_SPMC_CTL (MCUCFG_BASE + 0x1c3c) +/* bit-fields of MCUCFG_CPUSYS0_CPU?_SPMC_CTL */ +#define SW_SPARK_EN (1 << 0) +#define SW_NO_WAIT_Q (1 << 1) + +/* the MCUCFG which BIG cores used is at (MCUCFG_BASE + 0x2000) */ +#define MCUCFG_MP2_BASE (MCUCFG_BASE + 0x2000) +#define MCUCFG_MP2_PWR_RST_CTL (MCUCFG_MP2_BASE + 0x8) +/* bit-fields of MCUCFG_MP2_PWR_RST_CTL */ +#define SW_RST_B (1 << 0) +#define TOPAON_APB_MASK (1 << 1) + +#define MCUCFG_MP2_CPUCFG (MCUCFG_MP2_BASE + 0x208) + +#define MCUCFG_MP2_RVADDR0 (MCUCFG_MP2_BASE + 0x290) +#define MCUCFG_MP2_RVADDR1 (MCUCFG_MP2_BASE + 0x298) +#define MCUCFG_MP2_RVADDR2 (MCUCFG_MP2_BASE + 0x2c0) +#define MCUCFG_MP2_RVADDR3 (MCUCFG_MP2_BASE + 0x2c8) + +/* SPMC control */ +#define MCUCFG_MP0_SPMC (MCUCFG_BASE + 0x788) +#define MCUCFG_MP2_SPMC (MCUCFG_MP2_BASE + 0x2a0) +#define MCUCFG_MP2_COQ (MCUCFG_MP2_BASE + 0x2bC) + +/* per_cpu registers for MCUCFG_MP?_MISC_CONFIG2 */ +static const struct per_cpu_reg MCUCFG_BOOTADDR[] = { + [0] = { .cluster_addr = MCUCFG_MP0_MISC_CONFIG2, .cpu_stride = 3 }, +}; + +/* per_cpu registers for MCUCFG_MP?_MISC_CONFIG3 */ +static const struct per_cpu_reg MCUCFG_INITARCH[] = { + [0] = { .cluster_addr = MCUCFG_MP0_MISC_CONFIG3 }, + [1] = { .cluster_addr = MCUCFG_MP2_CPUCFG }, +}; + +/* SPARK control in BIG cores */ +#define MCUCFG_MP2_PTP3_CPU0_SPMC0 (MCUCFG_MP2_BASE + 0x430) +#define MCUCFG_MP2_PTP3_CPU0_SPMC1 (MCUCFG_MP2_BASE + 0x434) +#define MCUCFG_MP2_PTP3_CPU1_SPMC0 (MCUCFG_MP2_BASE + 0x438) +#define MCUCFG_MP2_PTP3_CPU1_SPMC1 (MCUCFG_MP2_BASE + 0x43c) +#define MCUCFG_MP2_PTP3_CPU2_SPMC0 (MCUCFG_MP2_BASE + 0x440) +#define MCUCFG_MP2_PTP3_CPU2_SPMC1 (MCUCFG_MP2_BASE + 0x444) +#define MCUCFG_MP2_PTP3_CPU3_SPMC0 (MCUCFG_MP2_BASE + 0x448) +#define MCUCFG_MP2_PTP3_CPU3_SPMC1 (MCUCFG_MP2_BASE + 0x44c) +/* bit-fields of MCUCFG_MP2_PTP3_CPU?_SPMC? */ +#define SW_SPARK_EN (1 << 0) +#define SW_NO_WAIT_Q (1 << 1) + +#define MCUCFG_MP2_SPARK2LDO (MCUCFG_MP2_BASE + 0x700) +/* bit-fields of MCUCFG_MP2_SPARK2LDO */ +#define SPARK_VRET_CTRL (0x3f << 0) +#define CPU0_SPARK_LDO_AMUXSEL (0xf << 6) +#define CPU1_SPARK_LDO_AMUXSEL (0xf << 10) +#define CPU2_SPARK_LDO_AMUXSEL (0xf << 14) +#define CPU3_SPARK_LDO_AMUXSEL (0xf << 18) + +/* per_cpu registers for SPARK */ +static const struct per_cpu_reg MCUCFG_SPARK[] = { + [0] = { .cluster_addr = MCUCFG_CPUSYS0_CPU0_SPMC_CTL, .cpu_stride = 2 }, + [1] = { .cluster_addr = MCUCFG_MP2_PTP3_CPU0_SPMC0, .cpu_stride = 3 }, +}; + +/* per_cpu registers for SPARK2LDO */ +static const struct per_cpu_reg MCUCFG_SPARK2LDO[] = { + [0] = { .cluster_addr = MCUCFG_CPUSYS0_SPARKVRETCNTRL }, + [1] = { .cluster_addr = MCUCFG_MP2_SPARK2LDO }, +}; + +#endif /* MTSPMC_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c new file mode 100644 index 0000000..6e76124 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + +static void memcpy_to_sspm(uint32_t dst, uint32_t *src, uint32_t len) +{ + while (len--) { + mmio_write_32(dst, *src); + dst += sizeof(uint32_t); + src++; + } +} + +static void memcpy_from_sspm(uint32_t *dst, uint32_t src, uint32_t len) +{ + while (len--) { + *dst = mmio_read_32(src); + dst++; + src += sizeof(uint32_t); + } +} + +int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len) +{ + if (slot >= 32) { + ERROR("%s:slot = %d\n", __func__, slot); + return -EINVAL; + } + + if (data) + memcpy_from_sspm(data, + MBOX3_BASE + slot * 4, + len); + + return 0; +} + +int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len) +{ + if (slot >= 32) { + ERROR("%s:slot = %d\n", __func__, slot); + return -EINVAL; + } + + if (data) + memcpy_to_sspm(MBOX3_BASE + slot * 4, + data, + len); + + return 0; +} + +static int sspm_ipi_check_ack(uint32_t id) +{ + int ret = 0; + + if (id == IPI_ID_PLATFORM) { + if ((mmio_read_32(MBOX0_BASE + MBOX_IN_IRQ_OFS) & 0x1) == 0x1) + ret = -EINPROGRESS; + } else if (id == IPI_ID_SUSPEND) { + if ((mmio_read_32(MBOX1_BASE + MBOX_IN_IRQ_OFS) & 0x2) == 0x2) + ret = -EINPROGRESS; + } else { + ERROR("%s: id = %d\n", __func__, id); + ret = -EINVAL; + } + + return ret; +} + +int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data) +{ + int ret = 0; + + ret = sspm_ipi_check_ack(id); + if (ret) + return ret; + + if (id == IPI_ID_PLATFORM) { + memcpy_to_sspm(MBOX0_BASE + PINR_OFFSET_PLATFORM * 4, + data, + PINR_SIZE_PLATFORM); + dsb(); + mmio_write_32(MBOX0_BASE + MBOX_OUT_IRQ_OFS, 0x1); + } else if (id == IPI_ID_SUSPEND) { + memcpy_to_sspm(MBOX1_BASE + PINR_OFFSET_SUSPEND * 4, + data, + PINR_SIZE_SUSPEND); + dsb(); + mmio_write_32(MBOX1_BASE + MBOX_OUT_IRQ_OFS, + 0x2); + } + + return 0; +} + +int sspm_ipi_recv_non_blocking(uint32_t id, uint32_t *data, uint32_t len) +{ + int ret = 0; + + ret = sspm_ipi_check_ack(id); + if (ret == -EINPROGRESS) { + if (id == IPI_ID_PLATFORM) { + memcpy_from_sspm(data, + MBOX0_BASE + PINR_OFFSET_PLATFORM * 4, + len); + dsb(); + /* clear interrupt bit*/ + mmio_write_32(MBOX0_BASE + MBOX_IN_IRQ_OFS, + 0x1); + ret = 0; + } else if (id == IPI_ID_SUSPEND) { + memcpy_from_sspm(data, + MBOX1_BASE + PINR_OFFSET_SUSPEND * 4, + len); + dsb(); + /* clear interrupt bit*/ + mmio_write_32(MBOX1_BASE + MBOX_IN_IRQ_OFS, + 0x2); + ret = 0; + } + } else if (ret == 0) { + ret = -EBUSY; + } + + return ret; +} + +int sspm_alive_show(void) +{ + uint32_t ipi_data, count; + int ret = 0; + + count = 5; + ipi_data = 0xdead; + + if (sspm_ipi_send_non_blocking(IPI_ID_PLATFORM, &ipi_data) != 0) { + ERROR("sspm init send fail! ret=%d\n", ret); + return -1; + } + + while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM, + &ipi_data, + sizeof(ipi_data) / sizeof(uint32_t)) + && count) { + mdelay(100); + count--; + } + + return (ipi_data == 1) ? 0 : -1; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h new file mode 100644 index 0000000..2c2cc10 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __SSPM_H__ +#define __SSPM_H__ +/* These should sync with sspm.bin */ +#define IPI_ID_PLATFORM 0 +#define IPI_ID_SUSPEND 6 +#define PINR_OFFSET_PLATFORM 0 +#define PINR_SIZE_PLATFORM 3 +#define PINR_OFFSET_SUSPEND 2 +#define PINR_SIZE_SUSPEND 8 + +#define MBOX0_BASE 0x10450000 +#define MBOX1_BASE 0x10460000 +#define MBOX3_BASE 0x10480000 +#define MBOX_OUT_IRQ_OFS 0x1000 +#define MBOX_IN_IRQ_OFS 0x1004 + +#define SHAREMBOX_OFFSET_MCDI 0 +#define SHAREMBOX_SIZE_MCDI 20 +#define SHAREMBOX_OFFSET_SUSPEND 26 +#define SHAREMBOX_SIZE_SUSPEND 6 + +int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len); +int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len); +int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data); +int sspm_ipi_recv_non_blocking(uint32_t slot, uint32_t *data, uint32_t len); +int sspm_alive_show(void); +#endif /* __SSPM_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c new file mode 100644 index 0000000..0da4815 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + +static void enable_systimer_compensation(void) +{ + unsigned int reg; + + reg = mmio_read_32(CNTCR_REG); + reg &= ~COMP_15_EN; + reg |= COMP_20_EN; + mmio_write_32(CNTCR_REG, reg); + + NOTICE("[systimer] CNTCR_REG(0x%x)\n", mmio_read_32(CNTCR_REG)); +} + +void mt_systimer_init(void) +{ + /* systimer is default on, so we only enable systimer compensation */ + enable_systimer_compensation(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h new file mode 100644 index 0000000..0b8edc5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_TIMER_H +#define MT_TIMER_H + + +#define SYSTIMER_BASE (0x10017000) +#define CNTCR_REG (SYSTIMER_BASE + 0x0) +#define CNTSR_REG (SYSTIMER_BASE + 0x4) + +#define COMP_15_EN (1 << 10) +#define COMP_20_EN (1 << 11) + +void mt_systimer_init(void); + +#endif /* MT_TIMER_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h new file mode 100644 index 0000000..6b03818 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT8183_MCUCFG_H +#define MT8183_MCUCFG_H + +#include +#include + +struct mt8183_mcucfg_regs { + uint32_t mp0_ca7l_cache_config; /* 0x0 */ + struct { + uint32_t mem_delsel0; + uint32_t mem_delsel1; + } mp0_cpu[4]; /* 0x4 */ + uint32_t mp0_cache_mem_delsel0; /* 0x24 */ + uint32_t mp0_cache_mem_delsel1; /* 0x28 */ + uint32_t mp0_axi_config; /* 0x2C */ + uint32_t mp0_misc_config[10]; /* 0x30 */ + uint32_t mp0_ca7l_cfg_dis; /* 0x58 */ + uint32_t mp0_ca7l_clken_ctrl; /* 0x5C */ + uint32_t mp0_ca7l_rst_ctrl; /* 0x60 */ + uint32_t mp0_ca7l_misc_config; /* 0x64 */ + uint32_t mp0_ca7l_dbg_pwr_ctrl; /* 0x68 */ + uint32_t mp0_rw_rsvd0; /* 0x6C */ + uint32_t mp0_rw_rsvd1; /* 0x70 */ + uint32_t mp0_ro_rsvd; /* 0x74 */ + uint32_t reserved0_0; /* 0x78 */ + uint32_t mp0_l2_cache_parity1_rdata; /* 0x7C */ + uint32_t mp0_l2_cache_parity2_rdata; /* 0x80 */ + uint32_t reserved0_1; /* 0x84 */ + uint32_t mp0_rgu_dcm_config; /* 0x88 */ + uint32_t mp0_ca53_specific_ctrl; /* 0x8C */ + uint32_t mp0_esr_case; /* 0x90 */ + uint32_t mp0_esr_mask; /* 0x94 */ + uint32_t mp0_esr_trig_en; /* 0x98 */ + uint32_t reserved_0_2; /* 0x9C */ + uint32_t mp0_ses_cg_en; /* 0xA0 */ + uint32_t reserved0_3[216]; /* 0xA4 */ + uint32_t mp_dbg_ctrl; /* 0x404 */ + uint32_t reserved0_4[34]; /* 0x408 */ + uint32_t mp_dfd_ctrl; /* 0x490 */ + uint32_t dfd_cnt_l; /* 0x494 */ + uint32_t dfd_cnt_h; /* 0x498 */ + uint32_t misccfg_ro_rsvd; /* 0x49C */ + uint32_t reserved0_5[24]; /* 0x4A0 */ + uint32_t mp1_rst_status; /* 0x500 */ + uint32_t mp1_dbg_ctrl; /* 0x504 */ + uint32_t mp1_dbg_flag; /* 0x508 */ + uint32_t mp1_ca7l_ir_mon; /* 0x50C */ + uint32_t reserved0_6[32]; /* 0x510 */ + uint32_t mcusys_dbg_mon_sel_a; /* 0x590 */ + uint32_t mcucys_dbg_mon; /* 0x594 */ + uint32_t misccfg_sec_voi_status0; /* 0x598 */ + uint32_t misccfg_sec_vio_status1; /* 0x59C */ + uint32_t reserved0_7[18]; /* 0x5A0 */ + uint32_t gic500_int_mask; /* 0x5E8 */ + uint32_t core_rst_en_latch; /* 0x5EC */ + uint32_t reserved0_8[3]; /* 0x5F0 */ + uint32_t dbg_core_ret; /* 0x5FC */ + uint32_t mcusys_config_a; /* 0x600 */ + uint32_t mcusys_config1_a; /* 0x604 */ + uint32_t mcusys_gic_prebase_a; /* 0x608 */ + uint32_t mcusys_pinmux; /* 0x60C */ + uint32_t sec_range0_start; /* 0x610 */ + uint32_t sec_range0_end; /* 0x614 */ + uint32_t sec_range_enable; /* 0x618 */ + uint32_t l2c_mm_base; /* 0x61C */ + uint32_t reserved0_9[8]; /* 0x620 */ + uint32_t aclken_div; /* 0x640 */ + uint32_t pclken_div; /* 0x644 */ + uint32_t l2c_sram_ctrl; /* 0x648 */ + uint32_t armpll_jit_ctrl; /* 0x64C */ + uint32_t cci_addrmap; /* 0x650 */ + uint32_t cci_config; /* 0x654 */ + uint32_t cci_periphbase; /* 0x658 */ + uint32_t cci_nevntcntovfl; /* 0x65C */ + uint32_t cci_clk_ctrl; /* 0x660 */ + uint32_t cci_acel_s1_ctrl; /* 0x664 */ + uint32_t mcusys_bus_fabric_dcm_ctrl; /* 0x668 */ + uint32_t mcu_misc_dcm_ctrl; /* 0x66C */ + uint32_t xgpt_ctl; /* 0x670 */ + uint32_t xgpt_idx; /* 0x674 */ + uint32_t reserved0_10[3]; /* 0x678 */ + uint32_t mcusys_rw_rsvd0; /* 0x684 */ + uint32_t mcusys_rw_rsvd1; /* 0x688 */ + uint32_t reserved0_11[13]; /* 0x68C */ + uint32_t gic_500_delsel_ctl; /* 0x6C0 */ + uint32_t etb_delsel_ctl; /* 0x6C4 */ + uint32_t etb_rst_ctl; /* 0x6C8 */ + uint32_t reserved0_12[29]; /* 0x6CC */ + uint32_t cci_adb400_dcm_config; /* 0x740 */ + uint32_t sync_dcm_config; /* 0x744 */ + uint32_t reserved0_13; /* 0x748 */ + uint32_t sync_dcm_cluster_config; /* 0x74C */ + uint32_t sw_udi; /* 0x750 */ + uint32_t reserved0_14; /* 0x754 */ + uint32_t gic_sync_dcm; /* 0x758 */ + uint32_t big_dbg_pwr_ctrl; /* 0x75C */ + uint32_t gic_cpu_periphbase; /* 0x760 */ + uint32_t axi_cpu_config; /* 0x764 */ + uint32_t reserved0_15[2]; /* 0x768 */ + uint32_t mcsib_sys_ctrl1; /* 0x770 */ + uint32_t mcsib_sys_ctrl2; /* 0x774 */ + uint32_t mcsib_sys_ctrl3; /* 0x778 */ + uint32_t mcsib_sys_ctrl4; /* 0x77C */ + uint32_t mcsib_dbg_ctrl1; /* 0x780 */ + uint32_t pwrmcu_apb2to1; /* 0x784 */ + uint32_t mp0_spmc; /* 0x788 */ + uint32_t reserved0_16; /* 0x78C */ + uint32_t mp0_spmc_sram_ctl; /* 0x790 */ + uint32_t reserved0_17; /* 0x794 */ + uint32_t mp0_sw_rst_wait_cycle; /* 0x798 */ + uint32_t reserved0_18; /* 0x79C */ + uint32_t mp0_pll_divider_cfg; /* 0x7A0 */ + uint32_t reserved0_19; /* 0x7A4 */ + uint32_t mp2_pll_divider_cfg; /* 0x7A8 */ + uint32_t reserved0_20[5]; /* 0x7AC */ + uint32_t bus_pll_divider_cfg; /* 0x7C0 */ + uint32_t reserved0_21[7]; /* 0x7C4 */ + uint32_t clusterid_aff1; /* 0x7E0 */ + uint32_t clusterid_aff2; /* 0x7E4 */ + uint32_t reserved0_22[2]; /* 0x7E8 */ + uint32_t l2_cfg_mp0; /* 0x7F0 */ + uint32_t l2_cfg_mp1; /* 0x7F4 */ + uint32_t reserved0_23[218]; /* 0x7F8 */ + uint32_t mscib_dcm_en; /* 0xB60 */ + uint32_t reserved0_24[1063]; /* 0xB64 */ + uint32_t cpusys0_sparkvretcntrl; /* 0x1C00 */ + uint32_t cpusys0_sparken; /* 0x1C04 */ + uint32_t cpusys0_amuxsel; /* 0x1C08 */ + uint32_t reserved0_25[9]; /* 0x1C0C */ + uint32_t cpusys0_cpu0_spmc_ctl; /* 0x1C30 */ + uint32_t cpusys0_cpu1_spmc_ctl; /* 0x1C34 */ + uint32_t cpusys0_cpu2_spmc_ctl; /* 0x1C38 */ + uint32_t cpusys0_cpu3_spmc_ctl; /* 0x1C3C */ + uint32_t reserved0_26[8]; /* 0x1C40 */ + uint32_t mp0_sync_dcm_cgavg_ctrl; /* 0x1C60 */ + uint32_t mp0_sync_dcm_cgavg_fact; /* 0x1C64 */ + uint32_t mp0_sync_dcm_cgavg_rfact; /* 0x1C68 */ + uint32_t mp0_sync_dcm_cgavg; /* 0x1C6C */ + uint32_t mp0_l2_parity_clr; /* 0x1C70 */ + uint32_t reserved0_27[357]; /* 0x1C74 */ + uint32_t mp2_cpucfg; /* 0x2208 */ + uint32_t mp2_axi_config; /* 0x220C */ + uint32_t reserved0_28[25]; /* 0x2210 */ + uint32_t mp2_sync_dcm; /* 0x2274 */ + uint32_t reserved0_29[10]; /* 0x2278 */ + uint32_t ptp3_cputop_spmc0; /* 0x22A0 */ + uint32_t ptp3_cputop_spmc1; /* 0x22A4 */ + uint32_t reserved0_30[98]; /* 0x22A8 */ + uint32_t ptp3_cpu0_spmc0; /* 0x2430 */ + uint32_t ptp3_cpu0_spmc1; /* 0x2434 */ + uint32_t ptp3_cpu1_spmc0; /* 0x2438 */ + uint32_t ptp3_cpu1_spmc1; /* 0x243C */ + uint32_t ptp3_cpu2_spmc0; /* 0x2440 */ + uint32_t ptp3_cpu2_spmc1; /* 0x2444 */ + uint32_t ptp3_cpu3_spmc0; /* 0x2448 */ + uint32_t ptp3_cpu3_spmc1; /* 0x244C */ + uint32_t ptp3_cpux_spmc; /* 0x2450 */ + uint32_t reserved0_31[171]; /* 0x2454 */ + uint32_t spark2ld0; /* 0x2700 */ +}; + +static struct mt8183_mcucfg_regs *const mt8183_mcucfg = (void *)MCUCFG_BASE; + +enum { + SW_SPARK_EN = 1 << 0, + SW_NO_WAIT_FOR_Q_CHANNEL = 1 << 1, + SW_FSM_OVERRIDE = 1 << 2, + SW_LOGIC_PRE1_PDB = 1 << 3, + SW_LOGIC_PRE2_PDB = 1 << 4, + SW_LOGIC_PDB = 1 << 5, + SW_ISO = 1 << 6, + SW_SRAM_SLEEPB = 0x3f << 7, + SW_SRAM_ISOINTB = 1 << 13, + SW_CLK_DIS = 1 << 14, + SW_CKISO = 1 << 15, + SW_PD = 0x3f << 16, + SW_HOT_PLUG_RESET = 1 << 22, + SW_PWR_ON_OVERRIDE_EN = 1 << 23, + SW_PWR_ON = 1 << 24, + SW_COQ_DIS = 1 << 25, + LOGIC_PDBO_ALL_OFF_ACK = 1 << 26, + LOGIC_PDBO_ALL_ON_ACK = 1 << 27, + LOGIC_PRE2_PDBO_ALL_ON_ACK = 1 << 28, + LOGIC_PRE1_PDBO_ALL_ON_ACK = 1 << 29 +}; + +enum { + CPU_SW_SPARK_EN = 1 << 0, + CPU_SW_NO_WAIT_FOR_Q_CHANNEL = 1 << 1, + CPU_SW_FSM_OVERRIDE = 1 << 2, + CPU_SW_LOGIC_PRE1_PDB = 1 << 3, + CPU_SW_LOGIC_PRE2_PDB = 1 << 4, + CPU_SW_LOGIC_PDB = 1 << 5, + CPU_SW_ISO = 1 << 6, + CPU_SW_SRAM_SLEEPB = 1 << 7, + CPU_SW_SRAM_ISOINTB = 1 << 8, + CPU_SW_CLK_DIS = 1 << 9, + CPU_SW_CKISO = 1 << 10, + CPU_SW_PD = 0x1f << 11, + CPU_SW_HOT_PLUG_RESET = 1 << 16, + CPU_SW_POWR_ON_OVERRIDE_EN = 1 << 17, + CPU_SW_PWR_ON = 1 << 18, + CPU_SPARK2LDO_ALLSWOFF = 1 << 19, + CPU_PDBO_ALL_ON_ACK = 1 << 20, + CPU_PRE2_PDBO_ALLON_ACK = 1 << 21, + CPU_PRE1_PDBO_ALLON_ACK = 1 << 22 +}; + +enum { + MP2_AXI_CONFIG_ACINACTM = 1 << 0, + MPx_AXI_CONFIG_ACINACTM = 1 << 4, + MPX_CA7_MISC_CONFIG_STANDBYWFIL2 = 1 << 28 +}; + +enum { + MP0_CPU0_STANDBYWFE = 1 << 20, + MP0_CPU1_STANDBYWFE = 1 << 21, + MP0_CPU2_STANDBYWFE = 1 << 22, + MP0_CPU3_STANDBYWFE = 1 << 23 +}; + +enum { + MP1_CPU0_STANDBYWFE = 1 << 20, + MP1_CPU1_STANDBYWFE = 1 << 21, + MP1_CPU2_STANDBYWFE = 1 << 22, + MP1_CPU3_STANDBYWFE = 1 << 23 +}; + +enum { + B_SW_HOT_PLUG_RESET = 1 << 30, + B_SW_PD_OFFSET = 18, + B_SW_PD = 0x3f << B_SW_PD_OFFSET, + B_SW_SRAM_SLEEPB_OFFSET = 12, + B_SW_SRAM_SLEEPB = 0x3f << B_SW_SRAM_SLEEPB_OFFSET +}; + +enum { + B_SW_SRAM_ISOINTB = 1 << 9, + B_SW_ISO = 1 << 8, + B_SW_LOGIC_PDB = 1 << 7, + B_SW_LOGIC_PRE2_PDB = 1 << 6, + B_SW_LOGIC_PRE1_PDB = 1 << 5, + B_SW_FSM_OVERRIDE = 1 << 4, + B_SW_PWR_ON = 1 << 3, + B_SW_PWR_ON_OVERRIDE_EN = 1 << 2 +}; + +enum { + B_FSM_STATE_OUT_OFFSET = 6, + B_FSM_STATE_OUT_MASK = 0x1f << B_FSM_STATE_OUT_OFFSET, + B_SW_LOGIC_PDBO_ALL_OFF_ACK = 1 << 5, + B_SW_LOGIC_PDBO_ALL_ON_ACK = 1 << 4, + B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK = 1 << 3, + B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK = 1 << 2, + B_FSM_OFF = 0 << B_FSM_STATE_OUT_OFFSET, + B_FSM_ON = 1 << B_FSM_STATE_OUT_OFFSET, + B_FSM_RET = 2 << B_FSM_STATE_OUT_OFFSET +}; + +/* APB Module infracfg_ao */ +enum { + INFRA_TOPAXI_PROTECTEN_1 = INFRACFG_AO_BASE + 0x250, + INFRA_TOPAXI_PROTECTSTA1_1 = INFRACFG_AO_BASE + 0x258, + INFRA_TOPAXI_PROTECTEN_1_SET = INFRACFG_AO_BASE + 0x2A8, + INFRA_TOPAXI_PROTECTEN_1_CLR = INFRACFG_AO_BASE + 0x2AC +}; + +enum { + IDX_PROTECT_MP0_CACTIVE = 10, + IDX_PROTECT_MP1_CACTIVE = 11, + IDX_PROTECT_ICC0_CACTIVE = 12, + IDX_PROTECT_ICD0_CACTIVE = 13, + IDX_PROTECT_ICC1_CACTIVE = 14, + IDX_PROTECT_ICD1_CACTIVE = 15, + IDX_PROTECT_L2C0_CACTIVE = 26, + IDX_PROTECT_L2C1_CACTIVE = 27 +}; + +/* cpu boot mode */ +enum { + MP0_CPUCFG_64BIT_SHIFT = 12, + MP1_CPUCFG_64BIT_SHIFT = 28, + MP0_CPUCFG_64BIT = 0xf << MP0_CPUCFG_64BIT_SHIFT, + MP1_CPUCFG_64BIT = 0xfu << MP1_CPUCFG_64BIT_SHIFT +}; + +/* scu related */ +enum { + MP0_ACINACTM_SHIFT = 4, + MP1_ACINACTM_SHIFT = 4, + MP2_ACINACTM_SHIFT = 0, + MP0_ACINACTM = 1 << MP0_ACINACTM_SHIFT, + MP1_ACINACTM = 1 << MP1_ACINACTM_SHIFT, + MP2_ACINACTM = 1 << MP2_ACINACTM_SHIFT +}; + +enum { + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16, + + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = + 0xf << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT +}; + +enum { + MP1_AINACTS_SHIFT = 4, + MP1_AINACTS = 1 << MP1_AINACTS_SHIFT +}; + +enum { + MP1_SW_CG_GEN_SHIFT = 12, + MP1_SW_CG_GEN = 1 << MP1_SW_CG_GEN_SHIFT +}; + +enum { + MP1_L2RSTDISABLE_SHIFT = 14, + MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT +}; + +/* bus pll divider dcm related */ +enum { + BUS_PLLDIVIDER_DCM_DBC_CNT_0_SHIFT = 11, + BUS_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24, + BUS_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25, + + BUS_PLLDIV_DCM = (1 << BUS_PLLDIVIDER_DCM_DBC_CNT_0_SHIFT) | + (1 << BUS_PLLDIV_ARMWFI_DCM_EN_SHIFT) | + (1 << BUS_PLLDIV_ARMWFE_DCM_EN_SHIFT) +}; + +/* mp0 pll divider dcm related */ +enum { + MP0_PLLDIV_DCM_DBC_CNT_0_SHIFT = 11, + MP0_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24, + MP0_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25, + MP0_PLLDIV_LASTCORE_IDLE_EN_SHIFT = 31, + MP0_PLLDIV_DCM = (1 << MP0_PLLDIV_DCM_DBC_CNT_0_SHIFT) | + (1 << MP0_PLLDIV_ARMWFI_DCM_EN_SHIFT) | + (1 << MP0_PLLDIV_ARMWFE_DCM_EN_SHIFT) | + (1u << MP0_PLLDIV_LASTCORE_IDLE_EN_SHIFT) +}; + +/* mp2 pll divider dcm related */ +enum { + MP2_PLLDIV_DCM_DBC_CNT_0_SHIFT = 11, + MP2_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24, + MP2_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25, + MP2_PLLDIV_LASTCORE_IDLE_EN_SHIFT = 31, + MP2_PLLDIV_DCM = (1 << MP2_PLLDIV_DCM_DBC_CNT_0_SHIFT) | + (1 << MP2_PLLDIV_ARMWFI_DCM_EN_SHIFT) | + (1 << MP2_PLLDIV_ARMWFE_DCM_EN_SHIFT) | + (1u << MP2_PLLDIV_LASTCORE_IDLE_EN_SHIFT) +}; + +/* mcsib dcm related */ +enum { + MCSIB_CACTIVE_SEL_SHIFT = 0, + MCSIB_DCM_EN_SHIFT = 16, + + MCSIB_CACTIVE_SEL_MASK = 0xffff << MCSIB_CACTIVE_SEL_SHIFT, + MCSIB_CACTIVE_SEL = 0xffff << MCSIB_CACTIVE_SEL_SHIFT, + + MCSIB_DCM_MASK = 0xffffu << MCSIB_DCM_EN_SHIFT, + MCSIB_DCM = 0xffffu << MCSIB_DCM_EN_SHIFT, +}; + +/* cci adb400 dcm related */ +enum { + CCI_M0_ADB400_DCM_EN_SHIFT = 0, + CCI_M1_ADB400_DCM_EN_SHIFT = 1, + CCI_M2_ADB400_DCM_EN_SHIFT = 2, + CCI_S2_ADB400_DCM_EN_SHIFT = 3, + CCI_S3_ADB400_DCM_EN_SHIFT = 4, + CCI_S4_ADB400_DCM_EN_SHIFT = 5, + CCI_S5_ADB400_DCM_EN_SHIFT = 6, + ACP_S3_ADB400_DCM_EN_SHIFT = 11, + + CCI_ADB400_DCM_MASK = (1 << CCI_M0_ADB400_DCM_EN_SHIFT) | + (1 << CCI_M1_ADB400_DCM_EN_SHIFT) | + (1 << CCI_M2_ADB400_DCM_EN_SHIFT) | + (1 << CCI_S2_ADB400_DCM_EN_SHIFT) | + (1 << CCI_S4_ADB400_DCM_EN_SHIFT) | + (1 << CCI_S4_ADB400_DCM_EN_SHIFT) | + (1 << CCI_S5_ADB400_DCM_EN_SHIFT) | + (1 << ACP_S3_ADB400_DCM_EN_SHIFT), + CCI_ADB400_DCM = (1 << CCI_M0_ADB400_DCM_EN_SHIFT) | + (1 << CCI_M1_ADB400_DCM_EN_SHIFT) | + (1 << CCI_M2_ADB400_DCM_EN_SHIFT) | + (0 << CCI_S2_ADB400_DCM_EN_SHIFT) | + (0 << CCI_S4_ADB400_DCM_EN_SHIFT) | + (0 << CCI_S4_ADB400_DCM_EN_SHIFT) | + (0 << CCI_S5_ADB400_DCM_EN_SHIFT) | + (1 << ACP_S3_ADB400_DCM_EN_SHIFT) +}; + +/* sync dcm related */ +enum { + CCI_SYNC_DCM_DIV_EN_SHIFT = 0, + CCI_SYNC_DCM_UPDATE_TOG_SHIFT = 1, + CCI_SYNC_DCM_DIV_SEL_SHIFT = 2, + MP0_SYNC_DCM_DIV_EN_SHIFT = 10, + MP0_SYNC_DCM_UPDATE_TOG_SHIFT = 11, + MP0_SYNC_DCM_DIV_SEL_SHIFT = 12, + + SYNC_DCM_MASK = (1 << CCI_SYNC_DCM_DIV_EN_SHIFT) | + (1 << CCI_SYNC_DCM_UPDATE_TOG_SHIFT) | + (0x7f << CCI_SYNC_DCM_DIV_SEL_SHIFT) | + (1 << MP0_SYNC_DCM_DIV_EN_SHIFT) | + (1 << MP0_SYNC_DCM_UPDATE_TOG_SHIFT) | + (0x7f << MP0_SYNC_DCM_DIV_SEL_SHIFT), + SYNC_DCM = (1 << CCI_SYNC_DCM_DIV_EN_SHIFT) | + (1 << CCI_SYNC_DCM_UPDATE_TOG_SHIFT) | + (0 << CCI_SYNC_DCM_DIV_SEL_SHIFT) | + (1 << MP0_SYNC_DCM_DIV_EN_SHIFT) | + (1 << MP0_SYNC_DCM_UPDATE_TOG_SHIFT) | + (0 << MP0_SYNC_DCM_DIV_SEL_SHIFT) +}; + +/* mcu bus dcm related */ +enum { + MCU_BUS_DCM_EN_SHIFT = 8, + MCU_BUS_DCM = 1 << MCU_BUS_DCM_EN_SHIFT +}; + +/* mcusys bus fabric dcm related */ +enum { + ACLK_INFRA_DYNAMIC_CG_EN_SHIFT = 0, + EMI2_ADB400_S_DCM_CTRL_SHIFT = 1, + ACLK_GPU_DYNAMIC_CG_EN_SHIFT = 2, + ACLK_PSYS_DYNAMIC_CG_EN_SHIFT = 3, + MP0_ADB400_S_DCM_CTRL_SHIFT = 4, + MP0_ADB400_M_DCM_CTRL_SHIFT = 5, + MP1_ADB400_S_DCM_CTRL_SHIFT = 6, + MP1_ADB400_M_DCM_CTRL_SHIFT = 7, + EMICLK_EMI_DYNAMIC_CG_EN_SHIFT = 8, + INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT = 9, + EMICLK_GPU_DYNAMIC_CG_EN_SHIFT = 10, + INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT = 11, + EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT = 12, + EMI1_ADB400_S_DCM_CTRL_SHIFT = 16, + MP2_ADB400_M_DCM_CTRL_SHIFT = 17, + MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT = 18, + MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT = 19, + MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT = 20, + L2_SHARE_ADB400_DCM_CTRL_SHIFT = 21, + MP1_AGGRESS_DCM_CTRL_SHIFT = 22, + MP0_AGGRESS_DCM_CTRL_SHIFT = 23, + MP0_ADB400_ACP_S_DCM_CTRL_SHIFT = 24, + MP0_ADB400_ACP_M_DCM_CTRL_SHIFT = 25, + MP1_ADB400_ACP_S_DCM_CTRL_SHIFT = 26, + MP1_ADB400_ACP_M_DCM_CTRL_SHIFT = 27, + MP3_ADB400_M_DCM_CTRL_SHIFT = 28, + MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT = 29, + + MCUSYS_BUS_FABRIC_DCM_MASK = (1 << ACLK_INFRA_DYNAMIC_CG_EN_SHIFT) | + (1 << EMI2_ADB400_S_DCM_CTRL_SHIFT) | + (1 << ACLK_GPU_DYNAMIC_CG_EN_SHIFT) | + (1 << ACLK_PSYS_DYNAMIC_CG_EN_SHIFT) | + (1 << MP0_ADB400_S_DCM_CTRL_SHIFT) | + (1 << MP0_ADB400_M_DCM_CTRL_SHIFT) | + (1 << MP1_ADB400_S_DCM_CTRL_SHIFT) | + (1 << MP1_ADB400_M_DCM_CTRL_SHIFT) | + (1 << EMICLK_EMI_DYNAMIC_CG_EN_SHIFT) | + (1 << INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT) | + (1 << EMICLK_GPU_DYNAMIC_CG_EN_SHIFT) | + (1 << INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT) | + (1 << EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT) | + (1 << EMI1_ADB400_S_DCM_CTRL_SHIFT) | + (1 << MP2_ADB400_M_DCM_CTRL_SHIFT) | + (1 << MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT) | + (1 << MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT) | + (1 << MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT) | + (1 << L2_SHARE_ADB400_DCM_CTRL_SHIFT) | + (1 << MP1_AGGRESS_DCM_CTRL_SHIFT) | + (1 << MP0_AGGRESS_DCM_CTRL_SHIFT) | + (1 << MP0_ADB400_ACP_S_DCM_CTRL_SHIFT) | + (1 << MP0_ADB400_ACP_M_DCM_CTRL_SHIFT) | + (1 << MP1_ADB400_ACP_S_DCM_CTRL_SHIFT) | + (1 << MP1_ADB400_ACP_M_DCM_CTRL_SHIFT) | + (1 << MP3_ADB400_M_DCM_CTRL_SHIFT) | + (1 << MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT), + + MCUSYS_BUS_FABRIC_DCM = (1 << ACLK_INFRA_DYNAMIC_CG_EN_SHIFT) | + (1 << EMI2_ADB400_S_DCM_CTRL_SHIFT) | + (1 << ACLK_GPU_DYNAMIC_CG_EN_SHIFT) | + (1 << ACLK_PSYS_DYNAMIC_CG_EN_SHIFT) | + (0 << MP0_ADB400_S_DCM_CTRL_SHIFT) | + (0 << MP0_ADB400_M_DCM_CTRL_SHIFT) | + (1 << MP1_ADB400_S_DCM_CTRL_SHIFT) | + (1 << MP1_ADB400_M_DCM_CTRL_SHIFT) | + (1 << EMICLK_EMI_DYNAMIC_CG_EN_SHIFT) | + (1 << INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT) | + (1 << EMICLK_GPU_DYNAMIC_CG_EN_SHIFT) | + (1 << INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT) | + (1 << EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT) | + (1 << EMI1_ADB400_S_DCM_CTRL_SHIFT) | + (0 << MP2_ADB400_M_DCM_CTRL_SHIFT) | + (1 << MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT) | + (1 << MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT) | + (1 << MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT) | + (1 << L2_SHARE_ADB400_DCM_CTRL_SHIFT) | + (1 << MP1_AGGRESS_DCM_CTRL_SHIFT) | + (1 << MP0_AGGRESS_DCM_CTRL_SHIFT) | + (1 << MP0_ADB400_ACP_S_DCM_CTRL_SHIFT) | + (1 << MP0_ADB400_ACP_M_DCM_CTRL_SHIFT) | + (1 << MP1_ADB400_ACP_S_DCM_CTRL_SHIFT) | + (1 << MP1_ADB400_ACP_M_DCM_CTRL_SHIFT) | + (1 << MP3_ADB400_M_DCM_CTRL_SHIFT) | + (1 << MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT) +}; + +/* l2c_sram dcm related */ +enum { + L2C_SRAM_DCM_EN_SHIFT = 0, + L2C_SRAM_DCM = 1 << L2C_SRAM_DCM_EN_SHIFT +}; + +/* mcu misc dcm related */ +enum { + MP0_CNTVALUEB_DCM_EN_SHIFT = 0, + MP_CNTVALUEB_DCM_EN = 8, + + CNTVALUEB_DCM = (1 << MP0_CNTVALUEB_DCM_EN_SHIFT) | + (1 << MP_CNTVALUEB_DCM_EN) +}; + +/* sync dcm cluster config related */ +enum { + MP0_SYNC_DCM_STALL_WR_EN_SHIFT = 7, + MCUSYS_MAX_ACCESS_LATENCY_SHIFT = 24, + + MCU0_SYNC_DCM_STALL_WR_EN = 1 << MP0_SYNC_DCM_STALL_WR_EN_SHIFT, + + MCUSYS_MAX_ACCESS_LATENCY_MASK = 0xf << MCUSYS_MAX_ACCESS_LATENCY_SHIFT, + MCUSYS_MAX_ACCESS_LATENCY = 0x5 << MCUSYS_MAX_ACCESS_LATENCY_SHIFT +}; + +/* cpusys rgu dcm related */ +enum { + CPUSYS_RGU_DCM_CONFIG_SHIFT = 0, + + CPUSYS_RGU_DCM_CINFIG = 1 << CPUSYS_RGU_DCM_CONFIG_SHIFT +}; + +/* mp2 sync dcm related */ +enum { + MP2_DCM_EN_SHIFT = 0, + + MP2_DCM_EN = 1 << MP2_DCM_EN_SHIFT +}; +#endif /* MT8183_MCUCFG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h new file mode 100644 index 0000000..b6fc29b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GIC_V3_H +#define MT_GIC_V3_H + +#include + +#define GIC_INT_MASK (MCUCFG_BASE + 0x5e8) +#define GIC500_ACTIVE_SEL_SHIFT 3 +#define GIC500_ACTIVE_SEL_MASK (0x7 << GIC500_ACTIVE_SEL_SHIFT) +#define GIC500_ACTIVE_CPU_SHIFT 16 +#define GIC500_ACTIVE_CPU_MASK (0xff << GIC500_ACTIVE_CPU_SHIFT) + +#define NR_INT_POL_CTL 20 + +void mt_gic_driver_init(void); +void mt_gic_init(void); +void mt_gic_set_pending(uint32_t irq); +uint32_t mt_gic_get_pending(uint32_t irq); +void mt_gic_cpuif_enable(void); +void mt_gic_cpuif_disable(void); +void mt_gic_rdistif_init(void); +void mt_gic_distif_save(void); +void mt_gic_distif_restore(void); +void mt_gic_rdistif_save(void); +void mt_gic_rdistif_restore(void); +void mt_gic_sync_dcm_enable(void); +void mt_gic_sync_dcm_disable(void); + +#endif /* MT_GIC_V3_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h new file mode 100644 index 0000000..afa9b63 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DCM_H +#define PLAT_DCM_H + +#define MP2_SYNC_DCM (MCUCFG_BASE + 0x2274) +#define MP2_SYNC_DCM_MASK (0x1 << 0) +#define MP2_SYNC_DCM_ON (0x1 << 0) +#define MP2_SYNC_DCM_OFF (0x0 << 0) + +extern uint64_t plat_dcm_mcsi_a_addr; +extern uint32_t plat_dcm_mcsi_a_val; +extern int plat_dcm_initiated; + +extern void plat_dcm_mcsi_a_backup(void); +extern void plat_dcm_mcsi_a_restore(void); +extern void plat_dcm_rgu_enable(void); +extern void plat_dcm_restore_cluster_on(unsigned long mpidr); +extern void plat_dcm_msg_handler(uint64_t x1); +extern unsigned long plat_dcm_get_enabled_cnt(uint64_t type); +extern void plat_dcm_init(void); + +#define ALL_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE \ + | STALL_DCM_TYPE | BIG_CORE_DCM_TYPE \ + | GIC_SYNC_DCM_TYPE | RGU_DCM_TYPE \ + | INFRA_DCM_TYPE \ + | DDRPHY_DCM_TYPE | EMI_DCM_TYPE | DRAMC_DCM_TYPE \ + | MCSI_DCM_TYPE) + +enum { + ARMCORE_DCM_TYPE = (1U << 0), + MCUSYS_DCM_TYPE = (1U << 1), + INFRA_DCM_TYPE = (1U << 2), + PERI_DCM_TYPE = (1U << 3), + EMI_DCM_TYPE = (1U << 4), + DRAMC_DCM_TYPE = (1U << 5), + DDRPHY_DCM_TYPE = (1U << 6), + STALL_DCM_TYPE = (1U << 7), + BIG_CORE_DCM_TYPE = (1U << 8), + GIC_SYNC_DCM_TYPE = (1U << 9), + LAST_CORE_DCM_TYPE = (1U << 10), + RGU_DCM_TYPE = (1U << 11), + TOPCKG_DCM_TYPE = (1U << 12), + LPDMA_DCM_TYPE = (1U << 13), + MCSI_DCM_TYPE = (1U << 14), + NR_DCM_TYPE = 15, +}; + +#endif /* PLAT_DCM_H */ \ No newline at end of file diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h new file mode 100644 index 0000000..c9d73cc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEBUG_H +#define PLATFORM_DEBUG_H + +#define sync_writel(addr, val) \ + do { mmio_write_32((addr), (val)); dsbsy(); } while (0) + +#define MCU_BIU_BASE 0x0c530000 +#define MISC1_CFG_BASE 0xb00 +#define CA15M_CFG_BASE 0x2000 +#define DFD_INTERNAL_CTL (MCU_BIU_BASE + MISC1_CFG_BASE + 0x00) +#define CA15M_DBG_CONTROL (MCU_BIU_BASE + CA15M_CFG_BASE + 0x728) +#define CA15M_PWR_RST_CTL (MCU_BIU_BASE + CA15M_CFG_BASE + 0x08) +#define VPROC_EXT_CTL 0x10006290 + +#define CFG_SF_CTRL 0x0c510014 +#define CFG_SF_INI 0x0c510010 + +#define BIT_CA15M_L2PARITY_EN (1 << 1) +#define BIT_CA15M_LASTPC_DIS (1 << 8) + +#define MCU_ALL_PWR_ON_CTRL 0x0c530b58 +#define PLAT_MTK_CIRCULAR_BUFFER_UNLOCK 0xefab4133 +#define PLAT_MTK_CIRCULAR_BUFFER_LOCK 0xefab4134 + +extern void circular_buffer_setup(void); +extern void l2c_parity_check_setup(void); +extern void clear_all_on_mux(void); +#endif /* PLATFORM_DEBUG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S new file mode 100644 index 0000000..cac7769 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* --------------------------------------------- + * The below macro prints out relevant GIC and + * CCI registers whenever an unhandled exception + * is taken in BL31. + * Clobbers: x0 - x10, x26, x27, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x26, BASE_GICD_BASE + mov_imm x27, BASE_GICC_BASE + /* 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, [x27, #GICC_HPPIR] + ldr w9, [x27, #GICC_AHPPIR] + ldr w10, [x27, #GICC_CTLR] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + + /* Print the GICD_ISPENDR regs */ + add x7, x26, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +gicd_ispendr_loop: + sub x4, x7, x26 + cmp x4, #0x280 + b.eq exit_print_gic_regs + bl asm_print_hex + + 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: + + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MT_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_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MT_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 diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h new file mode 100644 index 0000000..0853934 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit, + uintptr_t coh_start, + uintptr_t coh_limit); + +void plat_mtk_cci_init(void); +void plat_mtk_cci_enable(void); +void plat_mtk_cci_disable(void); +void plat_mtk_cci_init_sf(void); + +/* Declarations for plat_topology.c */ +int mt_setup_topology(void); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h new file mode 100644 index 0000000..25ccfbc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#define PLAT_PRIMARY_CPU 0x0 + +#define IO_PHYS 0x10000000 +#define INFRACFG_AO_BASE (IO_PHYS + 0x1000) +#define PERI_BASE (IO_PHYS + 0x3000) +#define GPIO_BASE (IO_PHYS + 0x5000) +#define SPM_BASE (IO_PHYS + 0x6000) +#define SLEEP_REG_MD_BASE (IO_PHYS + 0xf000) +#define RGU_BASE (IO_PHYS + 0x7000) +#define I2C4_BASE_SE (IO_PHYS + 0x1008000) +#define I2C2_BASE_SE (IO_PHYS + 0x1009000) +#define PMIC_WRAP_BASE (IO_PHYS + 0xd000) +#define MCUCFG_BASE 0x0c530000 +#define CFG_SF_CTRL 0x0c510014 +#define CFG_SF_INI 0x0c510010 +#define EMI_BASE (IO_PHYS + 0x219000) +#define EMI_MPU_BASE (IO_PHYS + 0x226000) +#define TRNG_base (IO_PHYS + 0x20f000) +#define MT_GIC_BASE 0x0c000000 +#define PLAT_MT_CCI_BASE 0x0c500000 +#define CCI_SIZE 0x00010000 +#define EINT_BASE 0x1000b000 +#define DVFSRC_BASE (IO_PHYS + 0x12000) + +#define SSPM_CFGREG_BASE (IO_PHYS + 0x440000) +#define SSPM_MBOX_3_BASE (IO_PHYS + 0x480000) + +#define INFRACFG_AO_BASE (IO_PHYS + 0x1000) + +#define TOPCKGEN_BASE (IO_PHYS + 0x0) +#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x200) +#define CLK_SCP_CFG_1 (TOPCKGEN_BASE + 0x204) + +#define APMIXEDSYS (IO_PHYS + 0xC000) +#define AP_PLL_CON3 (APMIXEDSYS + 0xC) +#define AP_PLL_CON4 (APMIXEDSYS + 0x10) +#define AP_PLL_CON6 (APMIXEDSYS + 0x18) +#define ARMPLL_LL_CON0 (APMIXEDSYS + 0x200) +#define ARMPLL_L_CON0 (APMIXEDSYS + 0x210) +#define ARMPLL_L_PWR_CON0 (APMIXEDSYS + 0x21c) +#define MAINPLL_CON0 (APMIXEDSYS + 0x220) +#define CCIPLL_CON0 (APMIXEDSYS + 0x290) + +#define TOP_CKMUXSEL (INFRACFG_AO_BASE + 0x0) + +#define armpll_mux1_sel_big_mask (0xf << 4) +#define armpll_mux1_sel_big_ARMSPLL (0x1 << 4) +#define armpll_mux1_sel_sml_mask (0xf << 8) +#define armpll_mux1_sel_sml_ARMSPLL (0x1 << 8) + + +/* Aggregate of all devices in the first GB */ +#define MTK_DEV_RNG0_BASE IO_PHYS +#define MTK_DEV_RNG0_SIZE 0x490000 +#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x1000000) +#define MTK_DEV_RNG1_SIZE 0x4000000 +#define MTK_DEV_RNG2_BASE 0x0c000000 +#define MTK_DEV_RNG2_SIZE 0x600000 +#define MT_MCUSYS_SIZE 0x90000 +#define RAM_CONSOLE_BASE 0x11d000 +#define RAM_CONSOLE_SIZE 0x1000 + +/******************************************************************************* + * MSDC + ******************************************************************************/ +#define MSDC0_BASE (IO_PHYS + 0x01230000) + +/******************************************************************************* + * MCUSYS related constants + ******************************************************************************/ +#define MT_L2_WRITE_ACCESS_RATE (MCUCFG_BASE + 0x604) +#define MP0_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f0) +#define MP1_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f4) +#define EMI_WFIFO (MCUCFG_BASE + 0x0b5c) + +/******************************************************************************* + * GIC related constants + ******************************************************************************/ +#define MT_POLARITY_LOW 0 +#define MT_POLARITY_HIGH 1 +#define MT_EDGE_SENSITIVE 1 +#define MT_LEVEL_SENSITIVE 0 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define UART0_BASE (IO_PHYS + 0x01002000) +#define UART1_BASE (IO_PHYS + 0x01003000) + +#define UART_BAUDRATE 115200 +#define UART_CLOCK 26000000 + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 13000000 +#define SYS_COUNTER_FREQ_IN_MHZ 13 + +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base MTK_platform compatible GIC memory map */ +#define BASE_GICD_BASE MT_GIC_BASE +#define BASE_GICC_BASE (MT_GIC_BASE + 0x400000) +#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x100000) +#define BASE_GICR_BASE (MT_GIC_BASE + 0x100000) +#define BASE_GICH_BASE (MT_GIC_BASE + 0x4000) +#define BASE_GICV_BASE (MT_GIC_BASE + 0x6000) +#define INT_POL_CTL0 (MCUCFG_BASE + 0xa80) +#define SEC_POL_CTL_EN0 (MCUCFG_BASE + 0xa00) +#define GIC_SYNC_DCM (MCUCFG_BASE + 0x758) +#define GIC_SYNC_DCM_MASK 0x3 +#define GIC_SYNC_DCM_ON 0x3 +#define GIC_SYNC_DCM_OFF 0x0 +#define GIC_PRIVATE_SIGNALS 32 + +#define PLAT_ARM_GICD_BASE BASE_GICD_BASE +#define PLAT_ARM_GICC_BASE BASE_GICC_BASE + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) ( \ +INTR_PROP_DESC(MT_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ +INTR_PROP_DESC(MT_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ +INTR_PROP_DESC(MT_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ +INTR_PROP_DESC(MT_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ +INTR_PROP_DESC(MT_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ +INTR_PROP_DESC(MT_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ +INTR_PROP_DESC(MT_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ +INTR_PROP_DESC(MT_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE)) \ + +#define PLAT_ARM_G0_IRQ_PROPS(grp) + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX 4 +#define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX 3 + +/******************************************************************************* + * WDT Registers + ******************************************************************************/ +#define MTK_WDT_BASE (IO_PHYS + 0x00007000) +#define MTK_WDT_SIZE 0x1000 +#define MTK_WDT_MODE (MTK_WDT_BASE + 0x0000) +#define MTK_WDT_LENGTH (MTK_WDT_BASE + 0x0004) +#define MTK_WDT_RESTART (MTK_WDT_BASE + 0x0008) +#define MTK_WDT_STATUS (MTK_WDT_BASE + 0x000C) +#define MTK_WDT_INTERVAL (MTK_WDT_BASE + 0x0010) +#define MTK_WDT_SWRST (MTK_WDT_BASE + 0x0014) +#define MTK_WDT_SWSYSRST (MTK_WDT_BASE + 0x0018) +#define MTK_WDT_NONRST_REG (MTK_WDT_BASE + 0x0020) +#define MTK_WDT_NONRST_REG2 (MTK_WDT_BASE + 0x0024) +#define MTK_WDT_REQ_MODE (MTK_WDT_BASE + 0x0030) +#define MTK_WDT_REQ_IRQ_EN (MTK_WDT_BASE + 0x0034) +#define MTK_WDT_EXT_REQ_CON (MTK_WDT_BASE + 0x0038) +#define MTK_WDT_DEBUG_CTL (MTK_WDT_BASE + 0x0040) +#define MTK_WDT_LATCH_CTL (MTK_WDT_BASE + 0x0044) +#define MTK_WDT_DEBUG_CTL2 (MTK_WDT_BASE + 0x00A0) +#define MTK_WDT_COUNTER (MTK_WDT_BASE + 0x0514) + +/* WDT_STATUS */ +#define MTK_WDT_STATUS_SPM_THERMAL_RST (1 << 0) +#define MTK_WDT_STATUS_SPM_RST (1 << 1) +#define MTK_WDT_STATUS_EINT_RST (1 << 2) +#define MTK_WDT_STATUS_SYSRST_RST (1 << 3) /* from PMIC */ +#define MTK_WDT_STATUS_DVFSP_RST (1 << 4) +#define MTK_WDT_STATUS_PMCU_RST (1 << 16) +#define MTK_WDT_STATUS_MDDBG_RST (1 << 17) +#define MTK_WDT_STATUS_THERMAL_DIRECT_RST (1 << 18) +#define MTK_WDT_STATUS_DEBUG_RST (1 << 19) +#define MTK_WDT_STATUS_SECURITY_RST (1 << 28) +#define MTK_WDT_STATUS_IRQ_ASSERT (1 << 29) +#define MTK_WDT_STATUS_SW_WDT_RST (1 << 30) +#define MTK_WDT_STATUS_HW_WDT_RST (1U << 31) + +/* RGU other related */ +#define MTK_WDT_MODE_DUAL_MODE 0x0040 +#define MTK_WDT_MODE_IRQ 0x0008 +#define MTK_WDT_MODE_KEY 0x22000000 +#define MTK_WDT_MODE_EXTEN 0x0004 +#define MTK_WDT_SWRST_KEY 0x1209 +#define MTK_WDT_RESTART_KEY 0x1971 + +/******************************************************************************* + * TRNG Registers + ******************************************************************************/ +#define TRNG_BASE_ADDR TRNG_base +#define TRNG_BASE_SIZE 0x1000 +#define TRNG_CTRL (TRNG_base + 0x0000) +#define TRNG_TIME (TRNG_base + 0x0004) +#define TRNG_DATA (TRNG_base + 0x0008) +#define TRNG_PDN_base 0x10001000 +#define TRNG_PDN_BASE_ADDR TRNG_PDN_BASE_ADDR +#define TRNG_PDN_BASE_SIZE 0x1000 +#define TRNG_PDN_SET (TRNG_PDN_base + 0x0088) +#define TRNG_PDN_CLR (TRNG_PDN_base + 0x008c) +#define TRNG_PDN_STATUS (TRNG_PDN_base + 0x0094) +#define TRNG_CTRL_RDY 0x80000000 +#define TRNG_CTRL_START 0x00000001 +#define TRNG_PDN_VALUE 0x200 + +/* FIQ platform related define */ +#define MT_IRQ_SEC_SGI_0 8 +#define MT_IRQ_SEC_SGI_1 9 +#define MT_IRQ_SEC_SGI_2 10 +#define MT_IRQ_SEC_SGI_3 11 +#define MT_IRQ_SEC_SGI_4 12 +#define MT_IRQ_SEC_SGI_5 13 +#define MT_IRQ_SEC_SGI_6 14 +#define MT_IRQ_SEC_SGI_7 15 + +#define FIQ_SMP_CALL_SGI 13 +#define WDT_IRQ_BIT_ID 174 +#define ATF_LOG_IRQ_ID 277 + +#define ATF_AMMS_IRQ_ID 338 +#define PCCIF1_IRQ0_BIT_ID 185 +#define PCCIF1_IRQ1_BIT_ID 186 + +#define DEBUG_XLAT_TABLE 0 + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if DEBUG_XLAT_TABLE +#define PLATFORM_STACK_SIZE 0x800 +#elif IMAGE_BL1 +#define PLATFORM_STACK_SIZE 0x440 +#elif IMAGE_BL2 +#define PLATFORM_STACK_SIZE 0x400 +#elif IMAGE_BL31 +#define PLATFORM_STACK_SIZE 0x800 +#elif IMAGE_BL32 +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define SOC_CHIP_ID U(0x8183) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ + +#define TZRAM_BASE 0x54600000 +#define TZRAM_SIZE 0x00030000 + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#define BL31_BASE (TZRAM_BASE + 0x1000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 16 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h new file mode 100644 index 0000000..c93be64 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POWER_TRACER_H +#define POWER_TRACER_H + +#define CPU_UP 0 +#define CPU_DOWN 1 +#define CPU_SUSPEND 2 +#define CLUSTER_UP 3 +#define CLUSTER_DOWN 4 +#define CLUSTER_SUSPEND 5 + +void trace_power_flow(u_register_t mpidr, unsigned char mode); + +#endif /* POWER_TRACER_H */ + diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h new file mode 100644 index 0000000..96b80c5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCU_H +#define SCU_H + +void disable_scu(u_register_t mpidr); +void enable_scu(u_register_t mpidr); + +#endif /* SCU_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h new file mode 100644 index 0000000..3f1ac86 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SSPM_REG_H__ +#define __SSPM_REG_H__ + +#include "platform_def.h" + +#define SSPM_CFGREG_RSV_RW_REG0 (SSPM_CFGREG_BASE + 0x0100) +#define SSPM_CFGREG_ACAO_INT_SET (SSPM_CFGREG_BASE + 0x00D8) +#define SSPM_CFGREG_ACAO_INT_CLR (SSPM_CFGREG_BASE + 0x00DC) +#define SSPM_CFGREG_ACAO_WAKEUP_EN (SSPM_CFGREG_BASE + 0x0204) + +#define STANDBYWFI_EN(n) (1 << (n + 8)) +#define GIC_IRQOUT_EN(n) (1 << (n + 0)) + +#define NF_MCDI_MBOX 19 +#define MCDI_MBOX_CLUSTER_0_CAN_POWER_OFF 0 +#define MCDI_MBOX_CLUSTER_1_CAN_POWER_OFF 1 +#define MCDI_MBOX_BUCK_POWER_OFF_MASK 2 +#define MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE 3 +#define MCDI_MBOX_CLUSTER_1_ATF_ACTION_DONE 4 +#define MCDI_MBOX_BOOTADDR 5 +#define MCDI_MBOX_PAUSE_ACTION 6 +#define MCDI_MBOX_AVAIL_CPU_MASK 7 +#define MCDI_MBOX_CPU_CLUSTER_PWR_STAT 8 +#define MCDI_MBOX_ACTION_STAT 9 +#define MCDI_MBOX_CLUSTER_0_CNT 10 +#define MCDI_MBOX_CLUSTER_1_CNT 11 +#define MCDI_MBOX_CPU_ISOLATION_MASK 12 +#define MCDI_MBOX_PAUSE_ACK 13 +#define MCDI_MBOX_PENDING_ON_EVENT 14 +#define MCDI_MBOX_PROF_CMD 15 +#define MCDI_MBOX_DRCC_CALI_DONE 16 +#define MCDI_MBOX_HP_CMD 17 +#define MCDI_MBOX_HP_ACK 18 + +#endif /* __SSPM_REG_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c new file mode 100644 index 0000000..8ee77f1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PWR_STATUS (SPM_BASE + 0x180) + +uint64_t plat_dcm_mcsi_a_addr; +uint32_t plat_dcm_mcsi_a_val; +static int plat_dcm_init_type; +static unsigned int dcm_big_core_cnt; +int plat_dcm_initiated; + +#define PWR_STA_BIG_MP_MASK (0x1 << 15) + +DEFINE_BAKERY_LOCK(dcm_lock); + +void dcm_lock_init(void) +{ + bakery_lock_init(&dcm_lock); +} + +void dcm_lock_get(void) +{ + bakery_lock_get(&dcm_lock); +} + +void dcm_lock_release(void) +{ + bakery_lock_release(&dcm_lock); +} + +void plat_dcm_mcsi_a_backup(void) +{ +} + +void plat_dcm_mcsi_a_restore(void) +{ +} + +void plat_dcm_rgu_enable(void) +{ +} + +void plat_dcm_big_core_sync(short on) +{ + /* Check if Big cluster power is existed */ + if (!(mmio_read_32(PWR_STATUS) & PWR_STA_BIG_MP_MASK)) + return; + + if (on) { + mmio_write_32(MP2_SYNC_DCM, + (mmio_read_32(MP2_SYNC_DCM) & ~MP2_SYNC_DCM_MASK) + | MP2_SYNC_DCM_ON); + dcm_big_core_cnt++; + } else + mmio_write_32(MP2_SYNC_DCM, + (mmio_read_32(MP2_SYNC_DCM) & ~MP2_SYNC_DCM_MASK) + | MP2_SYNC_DCM_OFF); +} + +void plat_dcm_restore_cluster_on(unsigned long mpidr) +{ + unsigned long cluster_id = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + switch (cluster_id) { + case 0x1: + dcm_lock_get(); + if (plat_dcm_init_type & BIG_CORE_DCM_TYPE) + plat_dcm_big_core_sync(1); + else + plat_dcm_big_core_sync(0); + dcm_lock_release(); + break; + default: + break; + } +} + +void plat_dcm_msg_handler(uint64_t x1) +{ + plat_dcm_init_type = x1 & ALL_DCM_TYPE; +} + +unsigned long plat_dcm_get_enabled_cnt(uint64_t type) +{ + switch (type) { + case BIG_CORE_DCM_TYPE: + return dcm_big_core_cnt; + default: + return 0; + } +} + +void plat_dcm_init(void) +{ + dcm_lock_init(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c new file mode 100644 index 0000000..2f0b67d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +void circular_buffer_setup(void) +{ + /* Clear DBG_CONTROL.lastpc_disable to enable circular buffer */ + sync_writel(CA15M_DBG_CONTROL, + mmio_read_32(CA15M_DBG_CONTROL) & ~(BIT_CA15M_LASTPC_DIS)); +} + +void circular_buffer_unlock(void) +{ + unsigned int i; + + /* Disable big vproc external off (set CPU_EXT_BUCK_ISO to 0x0) */ + sync_writel(VPROC_EXT_CTL, mmio_read_32(VPROC_EXT_CTL) & ~(0x1 << 1)); + + /* Release vproc apb mask (set 0x0C53_2008[1] to 0x0) */ + sync_writel(CA15M_PWR_RST_CTL, mmio_read_32(CA15M_PWR_RST_CTL) & ~(0x1 << 1)); + + for (i = 1; i <= 4; ++i) + sync_writel(MP1_CPUTOP_PWR_CON + i * 4, + (mmio_read_32(MP1_CPUTOP_PWR_CON + i * 4) & ~(0x4))|(0x4)); + + /* Set DFD.en */ + sync_writel(DFD_INTERNAL_CTL, 0x1); +} + +void circular_buffer_lock(void) +{ + /* Clear DFD.en */ + sync_writel(DFD_INTERNAL_CTL, 0x0); +} + +void clear_all_on_mux(void) +{ + sync_writel(MCU_ALL_PWR_ON_CTRL, + mmio_read_32(MCU_ALL_PWR_ON_CTRL) & ~(1 << 2)); + sync_writel(MCU_ALL_PWR_ON_CTRL, + mmio_read_32(MCU_ALL_PWR_ON_CTRL) & ~(1 << 1)); +} + +void l2c_parity_check_setup(void) +{ + /* Enable DBG_CONTROL.l2parity_en */ + sync_writel(CA15M_DBG_CONTROL, + mmio_read_32(CA15M_DBG_CONTROL) | BIT_CA15M_L2PARITY_EN); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c new file mode 100644 index 0000000..35792b2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include "../drivers/arm/gic/v3/gicv3_private.h" +#include "plat_private.h" +#include +#include +#include +#include + +uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; +static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT]; + +/* we save and restore the GICv3 context on system suspend */ +gicv3_dist_ctx_t dist_ctx; + +static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr) +{ + return plat_core_pos_by_mpidr(mpidr); +} + +gicv3_driver_data_t mt_gicv3_data = { + .gicd_base = MT_GIC_BASE, + .gicr_base = MT_GIC_RDIST_BASE, + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = mt_mpidr_to_core_pos, +}; + +struct gic_chip_data { + unsigned int saved_group; + unsigned int saved_enable; + unsigned int saved_conf0; + unsigned int saved_conf1; + unsigned int saved_grpmod; +}; + +static struct gic_chip_data gic_data; + +void clear_sec_pol_ctl_en(void) +{ + unsigned int i; + + /* total 19 polarity ctrl registers */ + for (i = 0; i <= NR_INT_POL_CTL - 1; i++) { + mmio_write_32((SEC_POL_CTL_EN0 + (i * 4)), 0); + } + dsb(); +} + +void mt_gic_driver_init(void) +{ + gicv3_driver_init(&mt_gicv3_data); +} + +void mt_gic_set_pending(uint32_t irq) +{ + gicv3_set_interrupt_pending(irq, plat_my_core_pos()); +} + +void mt_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void mt_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void mt_gic_rdistif_init(void) +{ + unsigned int proc_num; + unsigned int index; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + /* set all SGI/PPI as non-secure GROUP1 by default */ + mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U); + mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0); + + /* setup the default PPI/SGI priorities */ + for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U) + gicr_write_ipriorityr(gicr_base, index, + GICD_IPRIORITYR_DEF_VAL); +} + +void mt_gic_distif_save(void) +{ + gicv3_distif_save(&dist_ctx); +} + +void mt_gic_distif_restore(void) +{ + gicv3_distif_init_restore(&dist_ctx); +} + +void mt_gic_rdistif_save(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0); + gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0); + gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0); + gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1); + gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0); + + rdist_has_saved[proc_num] = 1; +} + +void mt_gic_rdistif_restore(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + if (rdist_has_saved[proc_num] == 1) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); + mmio_write_32(gicr_base + GICR_ISENABLER0, gic_data.saved_enable); + mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); + mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); + mmio_write_32(gicr_base + GICR_IGRPMODR0, gic_data.saved_grpmod); + } +} + +void mt_gic_sync_dcm_enable(void) +{ + mmio_clrsetbits_32(GIC_SYNC_DCM, GIC_SYNC_DCM_MASK, GIC_SYNC_DCM_ON); +} + +void mt_gic_sync_dcm_disable(void) +{ + mmio_clrsetbits_32(GIC_SYNC_DCM, GIC_SYNC_DCM_MASK, GIC_SYNC_DCM_OFF); +} + +void mt_gic_init(void) +{ + gicv3_distif_init(); + gicv3_cpuif_enable(plat_my_core_pos()); + mt_gic_rdistif_init(); + + clear_sec_pol_ctl_en(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c new file mode 100644 index 0000000..6094a17 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2019-2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* common headers */ +#include +#include +#include +#include +#include +#include + +/* mediatek platform specific headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Local power state for power domains in Run state. */ +#define MTK_LOCAL_STATE_RUN 0 +/* Local power state for retention. */ +#define MTK_LOCAL_STATE_RET 1 +/* Local power state for OFF/power-down. */ +#define MTK_LOCAL_STATE_OFF 2 + +#if PSCI_EXTENDED_STATE_ID +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define MTK_LOCAL_PSTATE_WIDTH 4 +#define MTK_LOCAL_PSTATE_MASK ((1 << MTK_LOCAL_PSTATE_WIDTH) - 1) + +/* Macros to construct the composite power state */ + +/* Make composite power state parameter till power level 0 */ + +#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT)) + +#else /* !PSCI_EXTENDED_STATE_ID */ + +#define mtk_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 mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << MTK_LOCAL_PSTATE_WIDTH) | \ + mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + +/* Make composite power state parameter till power level 2 */ +#define mtk_make_pwrstate_lvl2( \ + lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl2_state) << (MTK_LOCAL_PSTATE_WIDTH * 2)) | \ + mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type)) + +#define MTK_PWR_LVL0 0 +#define MTK_PWR_LVL1 1 +#define MTK_PWR_LVL2 2 + +/* Macros to read the MTK power domain state */ +#define MTK_CORE_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL0] +#define MTK_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL1] +#define MTK_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ? \ + (state)->pwr_domain_state[MTK_PWR_LVL2] : 0) + +#if PSCI_EXTENDED_STATE_ID +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +const unsigned int mtk_pm_idle_states[] = { + /* State-id - 0x001 */ + mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN, + MTK_LOCAL_STATE_RET, MTK_PWR_LVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x002 */ + mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN, + MTK_LOCAL_STATE_OFF, MTK_PWR_LVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x022 */ + mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_OFF, + MTK_LOCAL_STATE_OFF, MTK_PWR_LVL1, PSTATE_TYPE_POWERDOWN), +#if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1 + /* State-id - 0x222 */ + mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_OFF, MTK_LOCAL_STATE_OFF, + MTK_LOCAL_STATE_OFF, MTK_PWR_LVL2, PSTATE_TYPE_POWERDOWN), +#endif + 0, +}; +#endif + +#define CPU_IDX(cluster, cpu) ((cluster << 2) + cpu) +#define ON true +#define OFF false + +/* Pause MCDI when CPU hotplug */ +static bool HP_SSPM_PAUSE; +/* CPU Hotplug by SSPM */ +static bool HP_SSPM_CTRL = true; +/* Turn off cluster when CPU hotplug off */ +static bool HP_CLUSTER_OFF = true; +/* Turn off cluster when CPU MCDI off */ +static bool MCDI_C2 = true; +/* Enable MCDI */ +static bool MCDI_SSPM = true; + +static uintptr_t secure_entrypoint; + +static void mp1_L2_desel_config(void) +{ + mmio_write_64(MCUCFG_BASE + 0x2200, 0x2092c820); + + dsb(); +} + +static bool clst_single_pwr(int cluster, int cpu) +{ + uint32_t cpu_mask[2] = {0x00001e00, 0x000f0000}; + uint32_t cpu_pwr_bit[] = {9, 10, 11, 12, 16, 17, 18, 19}; + int my_idx = (cluster << 2) + cpu; + uint32_t pwr_stat = mmio_read_32(0x10006180); + + return !(pwr_stat & (cpu_mask[cluster] & ~BIT(cpu_pwr_bit[my_idx]))); +} + +static bool clst_single_on(int cluster, int cpu) +{ + uint32_t cpu_mask[2] = {0x0f, 0xf0}; + int my_idx = (cluster << 2) + cpu; + uint32_t on_stat = mcdi_avail_cpu_mask_read(); + + return !(on_stat & (cpu_mask[cluster] & ~BIT(my_idx))); +} + +static void plat_cpu_pwrdwn_common(void) +{ + /* Prevent interrupts from spuriously waking up this cpu */ + mt_gic_rdistif_save(); + mt_gic_cpuif_disable(); +} + +static void plat_cpu_pwron_common(void) +{ + /* Enable the gic cpu interface */ + mt_gic_cpuif_enable(); + mt_gic_rdistif_init(); + mt_gic_rdistif_restore(); +} + +static void plat_cluster_pwrdwn_common(uint64_t mpidr, int cluster) +{ + if (cluster > 0) + mt_gic_sync_dcm_enable(); + + /* Disable coherency */ + plat_mtk_cci_disable(); + disable_scu(mpidr); +} + +static void plat_cluster_pwron_common(uint64_t mpidr, int cluster) +{ + if (cluster > 0) { + l2c_parity_check_setup(); + circular_buffer_setup(); + mp1_L2_desel_config(); + mt_gic_sync_dcm_disable(); + } + + /* Enable coherency */ + enable_scu(mpidr); + plat_mtk_cci_enable(); + /* Enable big core dcm */ + plat_dcm_restore_cluster_on(mpidr); + /* Enable rgu dcm */ + plat_dcm_rgu_enable(); +} + +static void plat_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr; + + scr = read_scr_el3(); + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + isb(); + dsb(); + wfi(); + + write_scr_el3(scr); +} + +static void mcdi_ctrl_before_hotplug_on(int cluster, int cpu) +{ + if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM) { + mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), OFF); + mcdi_pause_set(cluster, CPU_IDX(cluster, cpu), ON); + } +} + +static void mcdi_ctrl_before_hotplug_off(int cluster, int cpu, bool cluster_off) +{ + if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM) + mcdi_pause_set(cluster_off ? cluster : -1, + CPU_IDX(cluster, cpu), OFF); +} + +static void mcdi_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off) +{ + if (MCDI_SSPM) { + sspm_set_bootaddr(secure_entrypoint); + + sspm_standbywfi_irq_enable(CPU_IDX(cluster, cpu)); + + if (cluster_off) + sspm_cluster_pwr_off_notify(cluster); + else + sspm_cluster_pwr_on_notify(cluster); + } +} + +static void mcdi_ctrl_suspend(void) +{ + if (MCDI_SSPM) + mcdi_pause(); +} + +static void mcdi_ctrl_resume(void) +{ + if (MCDI_SSPM) + mcdi_unpause(); +} + +static void hotplug_ctrl_cluster_on(int cluster, int cpu) +{ + if (HP_SSPM_CTRL && MCDI_SSPM) { + mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), OFF); + mcdi_hotplug_set(cluster, -1, ON); + mcdi_hotplug_wait_ack(cluster, -1, ON); + } else { + /* power on cluster */ + if (!spm_get_cluster_powerstate(cluster)) + spm_poweron_cluster(cluster); + } +} + +static void hotplug_ctrl_cpu_on(int cluster, int cpu) +{ + if (HP_SSPM_CTRL && MCDI_SSPM) + mcdi_hotplug_set(cluster, CPU_IDX(cluster, cpu), ON); + else + spm_poweron_cpu(cluster, cpu); +} + +static void hotplug_ctrl_cpu_on_finish(int cluster, int cpu) +{ + spm_disable_cpu_auto_off(cluster, cpu); + + if (HP_SSPM_CTRL && MCDI_SSPM) + mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), ON); + else if (HP_SSPM_PAUSE && MCDI_SSPM) + mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), ON); + + mcdi_avail_cpu_mask_set(BIT(CPU_IDX(cluster, cpu))); +} + +static void hotplug_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off) +{ + mcdi_avail_cpu_mask_clr(BIT(CPU_IDX(cluster, cpu))); + + if (HP_SSPM_CTRL && MCDI_SSPM) { + mcdi_hotplug_set(cluster_off ? cluster : -1, + CPU_IDX(cluster, cpu), OFF); + } else { + spm_enable_cpu_auto_off(cluster, cpu); + + if (cluster_off) + spm_enable_cluster_auto_off(cluster); + + spm_set_cpu_power_off(cluster, cpu); + } +} + +static int plat_mtk_power_domain_on(unsigned long mpidr) +{ + int cpu = MPIDR_AFFLVL0_VAL(mpidr); + int cluster = MPIDR_AFFLVL1_VAL(mpidr); + int clst_pwr = spm_get_cluster_powerstate(cluster); + unsigned int i; + + mcdi_ctrl_before_hotplug_on(cluster, cpu); + hotplug_ctrl_cluster_on(cluster, cpu); + + if (clst_pwr == 0) { + /* init cpu reset arch as AARCH64 of cluster */ + for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) { + mcucfg_init_archstate(cluster, i, 1); + mcucfg_set_bootaddr(cluster, i, secure_entrypoint); + } + } + + hotplug_ctrl_cpu_on(cluster, cpu); + + return PSCI_E_SUCCESS; +} + +static void plat_mtk_power_domain_off(const psci_power_state_t *state) +{ + uint64_t mpidr = read_mpidr(); + int cpu = MPIDR_AFFLVL0_VAL(mpidr); + int cluster = MPIDR_AFFLVL1_VAL(mpidr); + const plat_local_state_t *pds = state->pwr_domain_state; + bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF); + bool cluster_off = (HP_CLUSTER_OFF && afflvl1 && + clst_single_on(cluster, cpu)); + + plat_cpu_pwrdwn_common(); + + if (cluster_off) + plat_cluster_pwrdwn_common(mpidr, cluster); + + mcdi_ctrl_before_hotplug_off(cluster, cpu, cluster_off); + hotplug_ctrl_cluster_cpu_off(cluster, cpu, cluster_off); +} + +static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state) +{ + uint64_t mpidr = read_mpidr(); + int cpu = MPIDR_AFFLVL0_VAL(mpidr); + int cluster = MPIDR_AFFLVL1_VAL(mpidr); + const plat_local_state_t *pds = state->pwr_domain_state; + bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF); + + if (afflvl1) + plat_cluster_pwron_common(mpidr, cluster); + + plat_cpu_pwron_common(); + + hotplug_ctrl_cpu_on_finish(cluster, cpu); +} + +static void plat_mtk_power_domain_suspend(const psci_power_state_t *state) +{ + uint64_t mpidr = read_mpidr(); + int cpu = MPIDR_AFFLVL0_VAL(mpidr); + int cluster = MPIDR_AFFLVL1_VAL(mpidr); + const plat_local_state_t *pds = state->pwr_domain_state; + bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF); + bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF); + bool cluster_off = MCDI_C2 && afflvl1 && clst_single_pwr(cluster, cpu); + + plat_cpu_pwrdwn_common(); + + plat_dcm_mcsi_a_backup(); + + if (cluster_off || afflvl2) + plat_cluster_pwrdwn_common(mpidr, cluster); + + if (afflvl2) { + spm_data_t spm_d = { .cmd = SPM_SUSPEND }; + uint32_t *d = (uint32_t *)&spm_d; + uint32_t l = sizeof(spm_d) / sizeof(uint32_t); + + mcdi_ctrl_suspend(); + + spm_set_bootaddr(secure_entrypoint); + + if (MCDI_SSPM) + sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d); + + spm_system_suspend(); + + if (MCDI_SSPM) + while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l)) + ; + + mt_gic_distif_save(); + } else { + mcdi_ctrl_cluster_cpu_off(cluster, cpu, cluster_off); + } +} + +static void plat_mtk_power_domain_suspend_finish(const psci_power_state_t *state) +{ + uint64_t mpidr = read_mpidr(); + int cluster = MPIDR_AFFLVL1_VAL(mpidr); + const plat_local_state_t *pds = state->pwr_domain_state; + bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF); + + if (afflvl2) { + spm_data_t spm_d = { .cmd = SPM_RESUME }; + uint32_t *d = (uint32_t *)&spm_d; + uint32_t l = sizeof(spm_d) / sizeof(uint32_t); + + mt_gic_init(); + mt_gic_distif_restore(); + mt_gic_rdistif_restore(); + + mmio_write_32(EMI_WFIFO, 0xf); + + if (MCDI_SSPM) + sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d); + + spm_system_suspend_finish(); + + if (MCDI_SSPM) + while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l)) + ; + + mcdi_ctrl_resume(); + } else { + plat_cpu_pwron_common(); + } + + plat_cluster_pwron_common(mpidr, cluster); + + plat_dcm_mcsi_a_restore(); +} + +#if PSCI_EXTENDED_STATE_ID + +static int plat_mtk_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + assert(req_state); + + if (!MCDI_SSPM) + return PSCI_E_INVALID_PARAMS; + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; !!mtk_pm_idle_states[i]; i++) { + if (power_state == mtk_pm_idle_states[i]) + break; + } + + /* Return error if entry not found in the idle state array */ + if (!mtk_pm_idle_states[i]) + return PSCI_E_INVALID_PARAMS; + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + MTK_LOCAL_PSTATE_MASK; + state_id >>= MTK_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +#else /* if !PSCI_EXTENDED_STATE_ID */ + +static int plat_mtk_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pstate = psci_get_pstate_type(power_state); + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != 0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MTK_PWR_LVL0] = MTK_LOCAL_STATE_RET; + } else if (!MCDI_SSPM) { + return PSCI_E_INVALID_PARAMS; + } else { + for (i = 0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF; + } + + return PSCI_E_SUCCESS; +} + +#endif /* PSCI_EXTENDED_STATE_ID */ + +/******************************************************************************* + * MTK handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 plat_mtk_system_off(void) +{ + INFO("MTK System Off\n"); + + rtc_power_off_sequence(); + wk_pmic_enable_sdn_delay(); + pmic_power_off(); + + wfi(); + ERROR("MTK System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 plat_mtk_system_reset(void) +{ + struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset(); + + INFO("MTK System Reset\n"); + + mt_set_gpio_out(gpio_reset->index, gpio_reset->polarity); + + wfi(); + ERROR("MTK System Reset: operation not handled.\n"); + panic(); +} + +static void plat_mtk_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + assert(PLAT_MAX_PWR_LVL >= 2); + + for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF; +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to be turned + * on. The level and mpidr determine the affinity instance. + ******************************************************************************/ +static const plat_psci_ops_t plat_plat_pm_ops = { + .cpu_standby = plat_cpu_standby, + .pwr_domain_on = plat_mtk_power_domain_on, + .pwr_domain_on_finish = plat_mtk_power_domain_on_finish, + .pwr_domain_off = plat_mtk_power_domain_off, + .pwr_domain_suspend = plat_mtk_power_domain_suspend, + .pwr_domain_suspend_finish = plat_mtk_power_domain_suspend_finish, + .system_off = plat_mtk_system_off, + .system_reset = plat_mtk_system_reset, + .validate_power_state = plat_mtk_validate_power_state, + .get_sys_suspend_power_state = plat_mtk_get_sys_suspend_power_state +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + unsigned int i; + + *psci_ops = &plat_plat_pm_ops; + secure_entrypoint = sec_entrypoint; + + /* Init cpu reset arch as AARCH64 of cluster 0 */ + for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) { + mcucfg_init_archstate(0, i, 1); + mcucfg_set_bootaddr(0, i, secure_entrypoint); + } + + if (!check_mcdi_ctl_stat()) { + HP_SSPM_CTRL = false; + MCDI_SSPM = false; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c new file mode 100644 index 0000000..7b1dd03 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +const unsigned char mtk_power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* Number of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, + /* Number of children for the second cluster node */ + PLATFORM_CLUSTER1_CORE_COUNT +}; + +/******************************************************************************* + * This function returns the MT8173 default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return mtk_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8183/platform.mk new file mode 100644 index 0000000..1615cf9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/platform.mk @@ -0,0 +1,89 @@ +# +# Copyright (c) 2019, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MTK_PLAT := plat/mediatek +MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} + +PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT}/common/drivers/uart/ \ + -I${MTK_PLAT_SOC}/drivers/ \ + -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \ + -I${MTK_PLAT_SOC}/drivers/devapc/ \ + -I${MTK_PLAT_SOC}/drivers/mcdi/ \ + -I${MTK_PLAT_SOC}/drivers/spmc/ \ + -I${MTK_PLAT_SOC}/drivers/gpio/ \ + -I${MTK_PLAT_SOC}/drivers/timer/ \ + -I${MTK_PLAT_SOC}/drivers/pmic/ \ + -I${MTK_PLAT_SOC}/drivers/spm/ \ + -I${MTK_PLAT_SOC}/drivers/sspm/ \ + -I${MTK_PLAT_SOC}/drivers/rtc/ \ + -I${MTK_PLAT_SOC}/include/ + +PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/common/plat_psci_common.c \ + plat/common/aarch64/crash_console_helpers.S + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +BL31_SOURCES += common/desc_image_load.c \ + drivers/arm/cci/cci.c \ + ${GICV3_SOURCES} \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/bl_aux_params/bl_aux_params.c \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a73.S \ + plat/common/plat_gicv3.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/params_setup.c \ + ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ + ${MTK_PLAT_SOC}/aarch64/platform_common.c \ + ${MTK_PLAT_SOC}/drivers/devapc/devapc.c \ + ${MTK_PLAT_SOC}/drivers/mcsi/mcsi.c \ + ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \ + ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mtk_mcdi.c \ + ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \ + ${MTK_PLAT_SOC}/drivers/spm/spm.c \ + ${MTK_PLAT_SOC}/drivers/spm/spm_pmic_wrap.c \ + ${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \ + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ + ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c \ + ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \ + ${MTK_PLAT_SOC}/plat_pm.c \ + ${MTK_PLAT_SOC}/plat_topology.c \ + ${MTK_PLAT_SOC}/plat_mt_gic.c \ + ${MTK_PLAT_SOC}/plat_dcm.c \ + ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/plat_debug.c \ + ${MTK_PLAT_SOC}/scu.c \ + ${MTK_PLAT_SOC}/drivers/sspm/sspm.c + +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_826319 := 0 +ERRATA_A53_836870 := 1 +ERRATA_A53_855873 := 1 + +# indicate the reset vector address can be programmed +PROGRAMMABLE_RESET_ADDRESS := 1 + +COLD_BOOT_SINGLE_CPU := 1 + +MULTI_CONSOLE_API := 1 + +MACH_MT8183 := 1 +$(eval $(call add_define,MACH_MT8183)) + +include lib/coreboot/coreboot.mk + diff --git a/arm-trusted-firmware/plat/mediatek/mt8183/scu.c b/arm-trusted-firmware/plat/mediatek/mt8183/scu.c new file mode 100644 index 0000000..c4f1c3f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/scu.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void disable_scu(u_register_t mpidr) +{ + uintptr_t axi_config = 0; + uint32_t axi_value; + + switch (mpidr & MPIDR_CLUSTER_MASK) { + case 0x000: + axi_config = (uintptr_t)&mt8183_mcucfg->mp0_axi_config; + axi_value = MP0_ACINACTM; + break; + case 0x100: + axi_config = (uintptr_t)&mt8183_mcucfg->mp2_axi_config; + axi_value = MP2_ACINACTM; + break; + default: + ERROR("%s: mpidr does not exist\n", __func__); + panic(); + } + mmio_setbits_32(axi_config, axi_value); +} + +void enable_scu(u_register_t mpidr) +{ + uintptr_t axi_config = 0; + uint32_t axi_value; + + switch (mpidr & MPIDR_CLUSTER_MASK) { + case 0x000: + axi_config = (uintptr_t)&mt8183_mcucfg->mp0_axi_config; + axi_value = MP0_ACINACTM; + break; + case 0x100: + axi_config = (uintptr_t)&mt8183_mcucfg->mp2_axi_config; + axi_value = MP2_ACINACTM; + break; + default: + ERROR("%s: mpidr does not exist\n", __func__); + panic(); + } + mmio_clrbits_32(axi_config, axi_value); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S new file mode 100644 index 0000000..35b293f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_mediatek_calc_core_pos + +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_mediatek_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_mediatek_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr); + * + * With this function: CorePos = CoreID (AFF1) + * we do it with x0 = (x0 >> 8) & 0xff + * ----------------------------------------------------- + */ +func plat_mediatek_calc_core_pos + mov x1, #MPIDR_AFFLVL_MASK + and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT + ret +endfunc plat_mediatek_calc_core_pos diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c new file mode 100644 index 0000000..021cab7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_mmap[] = { + /* for TF text, RO, RW */ + MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_MCDI_SRAM_BASE, MTK_MCDI_SRAM_MAP_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit) +{ + mmap_add_region(total_base, total_base, total_size, + MT_RW_DATA | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + MT_CODE | MT_SECURE); + mmap_add(plat_mmap); + init_xlat_tables(); + enable_mmu_el3(0); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c new file mode 100644 index 0000000..5fc6b6e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* System Includes */ +#include + +/* Project Includes */ +#include +#include +#include +#include +#include +#include + +/* Platform Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + * BL2 has flushed this information to memory, so we are guaranteed to pick up + * good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + params_early_setup(arg1); + +#if COREBOOT + if (coreboot_serial.type) { + console_16550_register(coreboot_serial.baseaddr, + coreboot_serial.input_hertz, + coreboot_serial.baud, + &console); + } +#else + console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console); +#endif + + INFO("MT8186 bl31_setup\n"); + + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); +} + + +/******************************************************************************* + * Perform any BL31 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + dcm_set_default(); + + /* Initialize the GIC driver, CPU and distributor interfaces */ + mt_gic_driver_init(); + mt_gic_init(); + + mt_gpio_init(); + mt_systimer_init(); + generic_delay_timer_init(); + spm_boot_init(); + + emi_mpu_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + plat_configure_mmu_el3(BL31_START, + BL31_END - BL31_START, + BL_CODE_BASE, + BL_CODE_END); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c new file mode 100644 index 0000000..5dde5c5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static void dcm_armcore(bool mode) +{ + dcm_mp_cpusys_top_bus_pll_div_dcm(mode); + dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode); + dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode); +} + +static void dcm_mcusys(bool on) +{ + dcm_mp_cpusys_top_adb_dcm(on); + dcm_mp_cpusys_top_apb_dcm(on); + dcm_mp_cpusys_top_cpubiu_dcm(on); + dcm_mp_cpusys_top_cpubiu_dbg_cg(on); + dcm_mp_cpusys_top_misc_dcm(on); + dcm_mp_cpusys_top_mp0_qdcm(on); + dcm_cpccfg_reg_emi_wfifo(on); + dcm_mp_cpusys_top_last_cor_idle_dcm(on); +} + +static void dcm_stall(bool on) +{ + dcm_mp_cpusys_top_core_stall_dcm(on); + dcm_mp_cpusys_top_fcm_stall_dcm(on); +} + +static bool check_dcm_state(void) +{ + bool ret = true; + + ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(); + + ret &= dcm_mp_cpusys_top_adb_dcm_is_on(); + ret &= dcm_mp_cpusys_top_apb_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on(); + ret &= dcm_mp_cpusys_top_misc_dcm_is_on(); + ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on(); + ret &= dcm_cpccfg_reg_emi_wfifo_is_on(); + ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(); + + ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on(); + ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on(); + + return ret; +} + +void dcm_set_default(void) +{ + dcm_armcore(true); + dcm_mcusys(true); + dcm_stall(true); + + INFO("%s: %d", __func__, check_dcm_state()); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h new file mode 100644 index 0000000..6abcff4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_DCM_H +#define MTK_DCM_H + +#include + +void dcm_set_default(void); + +#endif /* #ifndef MTK_DCM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c new file mode 100644 index 0000000..ae0e964 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(16) | \ + BIT(17) | \ + BIT(18) | \ + BIT(21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(16) | \ + BIT(17) | \ + BIT(18)) +#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(16) | \ + BIT(17) | \ + BIT(18) | \ + BIT(21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(16) | \ + BIT(17) | \ + BIT(18)) +#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 16) | \ + (0x0 << 17) | \ + (0x0 << 18) | \ + (0x0 << 21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 16) | \ + (0x0 << 17) | \ + (0x0 << 18)) + +bool dcm_mp_cpusys_top_adb_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4) & + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON); + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) & + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) == + (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON); + + return ret; +} + +void dcm_mp_cpusys_top_adb_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4, + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG0_ON); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG1_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4, + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG0_OFF); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG1_OFF); + } +} + +#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16)) +#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16)) +#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16)) + +bool dcm_mp_cpusys_top_apb_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON); + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG1_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON); + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG2_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON); + + return ret; +} + +void dcm_mp_cpusys_top_apb_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG0_MASK, + MP_CPUSYS_TOP_APB_DCM_REG0_ON); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG1_MASK, + MP_CPUSYS_TOP_APB_DCM_REG1_ON); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG2_MASK, + MP_CPUSYS_TOP_APB_DCM_REG2_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG0_MASK, + MP_CPUSYS_TOP_APB_DCM_REG0_OFF); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG1_MASK, + MP_CPUSYS_TOP_APB_DCM_REG1_OFF); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG2_MASK, + MP_CPUSYS_TOP_APB_DCM_REG2_OFF); + } +} + +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11) | \ + BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) | \ + BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) | \ + (0x0 << 24) | \ + (0x0 << 25)) + +bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) & + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0)) +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0)) +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0)) + +bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) & + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_core_stall_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK (BIT(0)) +#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON ((0x0 << 0)) +#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_OFF (BIT(0)) + +bool dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSI_CFG2) & + MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpubiu_dbg_cg(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dbg_cg'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSI_CFG2, + MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK, + MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dbg_cg'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSI_CFG2, + MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK, + MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0)) +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0)) +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0)) + +bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSIC_DCM0) & + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpubiu_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(11) | \ + BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(11) | \ + BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 11) | \ + (0x0 << 24) | \ + (0x0 << 25)) + +bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0) & + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(11) | \ + BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(11) | \ + BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 11) | \ + (0x0 << 24) | \ + (0x0 << 25)) + +bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1) & + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4)) +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4)) +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4)) + +bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) & + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_fcm_stall_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK (BIT(31)) +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON (BIT(31)) +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0 << 31)) + +bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) & + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3) | \ + BIT(4)) +#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3) | \ + BIT(4)) +#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 0) | \ + (0x0 << 1) | \ + (0x0 << 2) | \ + (0x0 << 3) | \ + (0x0 << 4)) + +bool dcm_mp_cpusys_top_misc_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) & + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_misc_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK, + MP_CPUSYS_TOP_MISC_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK, + MP_CPUSYS_TOP_MISC_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 0) | \ + (0x0 << 1) | \ + (0x0 << 2) | \ + (0x0 << 3)) + +bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) & + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_mp0_qdcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF); + } +} + +#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | BIT(2)) +#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | BIT(2)) +#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | (0x0 << 2)) + +bool dcm_cpccfg_reg_emi_wfifo_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(CPCCFG_REG_EMI_WFIFO) & + CPCCFG_REG_EMI_WFIFO_REG0_MASK) == + (unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON); + + return ret; +} + +void dcm_cpccfg_reg_emi_wfifo(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */ + mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO, + CPCCFG_REG_EMI_WFIFO_REG0_MASK, + CPCCFG_REG_EMI_WFIFO_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */ + mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO, + CPCCFG_REG_EMI_WFIFO_REG0_MASK, + CPCCFG_REG_EMI_WFIFO_REG0_OFF); + } +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h new file mode 100644 index 0000000..ba76594 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_DCM_UTILS_H +#define MTK_DCM_UTILS_H + +#include + +#include +#include + +/* Base */ +#define MP_CPUSYS_TOP_BASE 0xc538000 +#define CPCCFG_REG_BASE 0xc53a800 + +/* Register Definition */ +#define CPCCFG_REG_EMI_WFIFO (CPCCFG_REG_BASE + 0x100) +#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0) +#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0) +#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4) +#define MP_CPUSYS_TOP_MCSIC_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440) +#define MP_CPUSYS_TOP_MCSI_CFG2 (MP_CPUSYS_TOP_BASE + 0x2418) +#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0) +#define MP_CPUSYS_TOP_MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880) +#define MP_CPUSYS_TOP_MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c) +#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510) +#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518) + +bool dcm_mp_cpusys_top_adb_dcm_is_on(void); +void dcm_mp_cpusys_top_adb_dcm(bool on); +bool dcm_mp_cpusys_top_apb_dcm_is_on(void); +void dcm_mp_cpusys_top_apb_dcm(bool on); +bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void); +void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on); +bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void); +void dcm_mp_cpusys_top_core_stall_dcm(bool on); +bool dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on(void); +void dcm_mp_cpusys_top_cpubiu_dbg_cg(bool on); +bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void); +void dcm_mp_cpusys_top_cpubiu_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on); +bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void); +void dcm_mp_cpusys_top_fcm_stall_dcm(bool on); +bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void); +void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on); +bool dcm_mp_cpusys_top_misc_dcm_is_on(void); +void dcm_mp_cpusys_top_misc_dcm(bool on); +bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void); +void dcm_mp_cpusys_top_mp0_qdcm(bool on); +bool dcm_cpccfg_reg_emi_wfifo_is_on(void); +void dcm_cpccfg_reg_emi_wfifo(bool on); +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c new file mode 100644 index 0000000..ade0837 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static bool dfd_enabled; +static uint64_t dfd_base_addr; +static uint64_t dfd_chain_length; +static uint64_t dfd_cache_dump; + +static void dfd_setup(uint64_t base_addr, uint64_t chain_length, + uint64_t cache_dump) +{ + mmio_write_32(MCUSYS_DFD_MAP, base_addr >> 24); + mmio_write_32(WDT_DEBUG_CTL, WDT_DEBUG_CTL_VAL_0); + + sync_writel(DFD_INTERNAL_CTL, (BIT(0) | BIT(2))); + + mmio_setbits_32(DFD_INTERNAL_CTL, BIT(13)); + mmio_setbits_32(DFD_INTERNAL_CTL, BIT(3)); + mmio_setbits_32(DFD_INTERNAL_CTL, (BIT(19) | BIT(20))); + mmio_write_32(DFD_INTERNAL_PWR_ON, (BIT(0) | BIT(1) | BIT(3))); + mmio_write_32(DFD_CHAIN_LENGTH0, chain_length); + mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0); + mmio_write_32(DFD_INTERNAL_TEST_SO_0, DFD_INTERNAL_TEST_SO_0_VAL); + mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 1); + + mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_VAL); + mmio_write_32(DFD_TEST_SI_1, DFD_TEST_SI_1_VAL); + + sync_writel(DFD_V30_CTL, 1); + + mmio_write_32(DFD_V30_BASE_ADDR, (base_addr & 0xFFF00000)); + + /* setup global variables for suspend and resume */ + dfd_enabled = true; + dfd_base_addr = base_addr; + dfd_chain_length = chain_length; + dfd_cache_dump = cache_dump; + + if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) { + mmio_write_32(WDT_DEBUG_CTL, WDT_DEBUG_CTL_VAL_1); + sync_writel(DFD_V35_ENALBE, 1); + sync_writel(DFD_V35_TAP_NUMBER, DFD_V35_TAP_NUMBER_VAL); + sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL); + sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL); + + if (cache_dump & DFD_PARITY_ERR_TRIGGER) { + sync_writel(DFD_HW_TRIGGER_MASK, DFD_HW_TRIGGER_MASK_VAL); + mmio_setbits_32(DFD_INTERNAL_CTL, BIT(4)); + } + } + dsbsy(); +} + +void dfd_resume(void) +{ + if (dfd_enabled == true) { + dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump); + } +} + +uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3) +{ + uint64_t ret = 0L; + + switch (arg0) { + case PLAT_MTK_DFD_SETUP_MAGIC: + INFO("[%s] DFD setup call from kernel\n", __func__); + dfd_setup(arg1, arg2, arg3); + break; + case PLAT_MTK_DFD_READ_MAGIC: + /* only allow to access DFD register base + 0x200 */ + if (arg1 <= 0x200) { + ret = mmio_read_32(MISC1_CFG_BASE + arg1); + } + break; + case PLAT_MTK_DFD_WRITE_MAGIC: + /* only allow to access DFD register base + 0x200 */ + if (arg1 <= 0x200) { + sync_writel(MISC1_CFG_BASE + arg1, arg2); + } + break; + default: + ret = MTK_SIP_E_INVALID_PARAM; + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h new file mode 100644 index 0000000..1901ec9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DFD_H +#define PLAT_DFD_H + +#include +#include +#include + +#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); \ + dsbsy(); \ + } while (0) + +#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150) +#define PLAT_MTK_DFD_READ_MAGIC (0x99716151) +#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152) + +#define MCU_BIU_BASE (MCUCFG_BASE) +#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xA040) + +#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00) +#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08) +#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C) +#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10) +#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28) +#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30) +#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48) +#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C) +#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58) +#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C) +#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC) + +#define DFD_V35_ENALBE (MCU_BIU_BASE + 0xA0A8) +#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xA0AC) +#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xA0B0) +#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xA0C0) +#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xA0C4) + +#define DFD_CACHE_DUMP_ENABLE (1U) +#define DFD_PARITY_ERR_TRIGGER (2U) + +#define MCUSYS_DFD_MAP (0x10001390) +#define WDT_DEBUG_CTL (0x10007048) + +#define WDT_DEBUG_CTL_VAL_0 (0x950603A0) +#define DFD_INTERNAL_TEST_SO_0_VAL (0x3B) +#define DFD_TEST_SI_0_VAL (0x108) +#define DFD_TEST_SI_1_VAL (0x20200000) + +#define WDT_DEBUG_CTL_VAL_1 (0x95063E80) +#define DFD_V35_TAP_NUMBER_VAL (0xA) +#define DFD_V35_TAP_EN_VAL (0x3FF) +#define DFD_V35_SEQ0_0_VAL (0x63668820) +#define DFD_HW_TRIGGER_MASK_VAL (0xC) + +void dfd_resume(void); +uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3); + +#endif /* PLAT_DFD_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c new file mode 100644 index 0000000..989ecf1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#if ENABLE_EMI_MPU_SW_LOCK +static unsigned char region_lock_state[EMI_MPU_REGION_NUM]; +#endif + +#define EMI_MPU_START_MASK (0x00FFFFFF) +#define EMI_MPU_END_MASK (0x00FFFFFF) +#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF) +#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF) + +static int _emi_mpu_set_protection(unsigned int start, unsigned int end, + unsigned int apc) +{ + unsigned int dgroup; + unsigned int region; + + region = (start >> 24) & 0xFF; + start &= EMI_MPU_START_MASK; + dgroup = (end >> 24) & 0xFF; + end &= EMI_MPU_END_MASK; + + if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) { + WARN("invalid region, domain\n"); + return -1; + } + +#if ENABLE_EMI_MPU_SW_LOCK + if (region_lock_state[region] == 1) { + WARN("invalid region\n"); + return -1; + } + + if ((dgroup == 0U) && ((apc >> 31) & 0x1)) { + region_lock_state[region] = 1; + } + + apc &= EMI_MPU_APC_SW_LOCK_MASK; +#else + apc &= EMI_MPU_APC_HW_LOCK_MASK; +#endif + + if ((start >= DRAM_OFFSET) && (end >= start)) { + start -= DRAM_OFFSET; + end -= DRAM_OFFSET; + } else { + WARN("invalid range\n"); + return -1; + } + + mmio_write_32(EMI_MPU_SA(region), start); + mmio_write_32(EMI_MPU_EA(region), end); + mmio_write_32(EMI_MPU_APC(region, dgroup), apc); + +#if defined(SUB_EMI_MPU_BASE) + mmio_write_32(SUB_EMI_MPU_SA(region), start); + mmio_write_32(SUB_EMI_MPU_EA(region), end); + mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc); +#endif + return 0; +} + +int emi_mpu_set_protection(struct emi_region_info_t *region_info) +{ + unsigned int start, end; + int i; + + if (region_info->region >= EMI_MPU_REGION_NUM) { + WARN("invalid region\n"); + return -1; + } + + start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) | + (region_info->region << 24); + + for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) { + end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24); + + if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) { + WARN("failed to set emi mpu protection(%d, %d, %d)\n", + start, end, region_info->apc[i]); + } + } + + return 0; +} + +void emi_mpu_init(void) +{ + /* TODO: more setting for EMI MPU. */ +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..415146e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMI_MPU_H +#define EMI_MPU_H + +#include + +#define ENABLE_EMI_MPU_SW_LOCK 1 + +#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x000) +#define EMI_MPU_DBG (EMI_MPU_BASE + 0x004) +#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100) +#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200) +#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region * 4)) +#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region * 4)) +#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300) +#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100)) +#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800) +#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + (domain * 4)) +#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900) +#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + (domain * 4)) +#define EMI_MPU_START (0x000) +#define EMI_MPU_END (0x93C) + +#define SUB_EMI_MPU_CTRL (SUB_EMI_MPU_BASE + 0x000) +#define SUB_EMI_MPU_DBG (SUB_EMI_MPU_BASE + 0x004) +#define SUB_EMI_MPU_SA0 (SUB_EMI_MPU_BASE + 0x100) +#define SUB_EMI_MPU_EA0 (SUB_EMI_MPU_BASE + 0x200) +#define SUB_EMI_MPU_SA(region) (SUB_EMI_MPU_SA0 + (region * 4)) +#define SUB_EMI_MPU_EA(region) (SUB_EMI_MPU_EA0 + (region * 4)) +#define SUB_EMI_MPU_APC0 (SUB_EMI_MPU_BASE + 0x300) +#define SUB_EMI_MPU_APC(region, dgroup) (SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100)) +#define SUB_EMI_MPU_CTRL_D0 (SUB_EMI_MPU_BASE + 0x800) +#define SUB_EMI_MPU_CTRL_D(domain) (SUB_EMI_MPU_CTRL_D0 + (domain * 4)) +#define SUB_EMI_RG_MASK_D0 (SUB_EMI_MPU_BASE + 0x900) +#define SUB_EMI_RG_MASK_D(domain) (SUB_EMI_RG_MASK_D0 + (domain * 4)) + +#define EMI_MPU_DOMAIN_NUM (16) +#define EMI_MPU_REGION_NUM (32) +#define EMI_MPU_ALIGN_BITS (16) +#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS) + +#define NO_PROTECTION 0 +#define SEC_RW 1 +#define SEC_RW_NSEC_R 2 +#define SEC_RW_NSEC_W 3 +#define SEC_R_NSEC_R 4 +#define FORBIDDEN 5 +#define SEC_R_NSEC_RW 6 + +#define LOCK 1 +#define UNLOCK 0 + +#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8) + +#if (EMI_MPU_DGROUP_NUM == 1) +#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \ +do { \ + apc_ary[1] = 0; \ + apc_ary[0] = \ + (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \ + (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \ + (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \ + (((unsigned int) d1) << 3) | ((unsigned int) d0) | \ + ((unsigned int) lock << 31); \ +} while (0) +#elif (EMI_MPU_DGROUP_NUM == 2) +#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \ + d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \ +do { \ + apc_ary[1] = \ + (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \ + (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \ + (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) | \ + (((unsigned int) d9) << 3) | ((unsigned int) d8); \ + apc_ary[0] = \ + (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \ + (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \ + (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \ + (((unsigned int) d1) << 3) | ((unsigned int) d0) | \ + ((unsigned int) lock << 31); \ +} while (0) +#endif + +struct emi_region_info_t { + unsigned long long start; + unsigned long long end; + unsigned int region; + unsigned int apc[EMI_MPU_DGROUP_NUM]; +}; + +void emi_mpu_init(void); + +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c new file mode 100644 index 0000000..134476a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uintptr_t mt_gpio_find_reg_addr(uint32_t pin) +{ + uintptr_t reg_addr = 0U; + struct mt_pin_info gpio_info; + + assert(pin < MAX_GPIO_PIN); + + gpio_info = mt_pin_infos[pin]; + + switch (gpio_info.base & 0x0f) { + case 0: + reg_addr = IOCFG_LT_BASE; + break; + case 1: + reg_addr = IOCFG_LM_BASE; + break; + case 2: + reg_addr = IOCFG_LB_BASE; + break; + case 3: + reg_addr = IOCFG_BL_BASE; + break; + case 4: + reg_addr = IOCFG_RB_BASE; + break; + case 5: + reg_addr = IOCFG_RT_BASE; + break; + default: + break; + } + + return reg_addr; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h new file mode 100644 index 0000000..4430a58 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_H +#define MT_GPIO_H + +#include + +/* Enumeration for GPIO pin */ +typedef enum GPIO_PIN { + GPIO_UNSUPPORTED = -1, + GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, + GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, + GPIO15, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, + GPIO23, GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, + GPIO31, GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, + GPIO39, GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, + GPIO47, GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, + GPIO55, GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, + GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, + GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, + GPIO79, GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, + GPIO87, GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, + GPIO95, GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, + GPIO103, GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, + GPIO111, GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, + GPIO119, GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, + GPIO127, GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, + GPIO135, GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, + GPIO143, GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, + GPIO151, GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, + GPIO159, GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, + GPIO167, GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, + GPIO175, GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182, + GPIO183, GPIO184, + MT_GPIO_BASE_MAX +} GPIO_PIN; + +static const struct mt_pin_info mt_pin_infos[] = { + PIN(0, 0, 13, 0x16, 0x40), + PIN(1, 0, 14, 0x16, 0x40), + PIN(2, 0, 17, 0x16, 0x40), + PIN(3, 0, 18, 0x16, 0x40), + PIN(4, 0, 19, 0x16, 0x40), + PIN(5, 0, 20, 0x16, 0x40), + PIN(6, 0, 19, 0x24, 0x40), + PIN(7, 0, 20, 0x24, 0x40), + PIN(8, 0, 21, 0x24, 0x40), + PIN(9, 0, 22, 0x24, 0x40), + PIN(10, 0, 16, 0x24, 0x40), + PIN(11, 0, 17, 0x24, 0x40), + PIN(12, 0, 18, 0x24, 0x40), + PIN(13, 0, 0, 0x23, 0x60), + PIN(14, 0, 1, 0x23, 0x60), + PIN(15, 0, 15, 0x16, 0x40), + PIN(16, 0, 16, 0x16, 0x40), + PIN(17, 0, 9, 0x25, 0x70), + PIN(18, 0, 10, 0x25, 0x70), + PIN(19, 0, 3, 0x25, 0x70), + PIN(20, 0, 6, 0x25, 0x70), + PIN(21, 0, 4, 0x25, 0x70), + PIN(22, 0, 7, 0x25, 0x70), + PIN(23, 0, 5, 0x25, 0x70), + PIN(24, 0, 8, 0x25, 0x70), + PIN(25, 0, 18, 0x25, 0x70), + PIN(26, 0, 15, 0x25, 0x70), + PIN(27, 0, 17, 0x25, 0x70), + PIN(28, 0, 16, 0x25, 0x70), + PIN(29, 0, 0, 0x16, 0x40), + PIN(30, 0, 1, 0x16, 0x40), + PIN(31, 0, 2, 0x16, 0x40), + PIN(32, 0, 25, 0x12, 0x50), + PIN(33, 0, 27, 0x12, 0x50), + PIN(34, 0, 26, 0x12, 0x50), + PIN(35, 0, 28, 0x12, 0x50), + PIN(36, 0, 9, 0x12, 0x50), + PIN(37, 0, 10, 0x12, 0x50), + PIN(38, 0, 12, 0x12, 0x50), + PIN(39, 0, 11, 0x12, 0x50), + PIN(40, 0, 13, 0x12, 0x50), + PIN(41, 0, 14, 0x12, 0x50), + PIN(42, 0, 16, 0x12, 0x50), + PIN(43, 0, 15, 0x12, 0x50), + PIN(44, 0, 28, 0x25, 0x70), + PIN(45, 0, 29, 0x25, 0x70), + PIN(46, 0, 31, 0x25, 0x70), + PIN(47, 0, 30, 0x25, 0x70), + PIN(48, 0, 17, 0x12, 0x50), + PIN(49, 0, 18, 0x12, 0x50), + PIN(50, 0, 20, 0x12, 0x50), + PIN(51, 0, 19, 0x12, 0x50), + PIN(52, 0, 12, 0x23, 0x60), + PIN(53, 0, 13, 0x23, 0x60), + PIN(54, 0, 15, 0x23, 0x60), + PIN(55, 0, 14, 0x23, 0x60), + PIN(56, 0, 12, 0x25, 0x70), + PIN(57, 0, 11, 0x25, 0x70), + PIN(58, 0, 13, 0x25, 0x70), + PIN(59, 0, 14, 0x25, 0x70), + PIN(60, 0, 21, 0x23, 0x60), + PIN(61, 0, 16, 0x23, 0x60), + PIN(62, 0, 22, 0x23, 0x60), + PIN(63, 0, 17, 0x23, 0x60), + PIN(64, 0, 18, 0x23, 0x60), + PIN(65, 0, 19, 0x23, 0x60), + PIN(66, 0, 20, 0x23, 0x60), + PIN(67, 1, 10, 0x21, 0x70), + PIN(68, 1, 0, 0x21, 0x70), + PIN(69, 1, 1, 0x21, 0x70), + PIN(70, 1, 11, 0x21, 0x70), + PIN(71, 1, 2, 0x21, 0x70), + PIN(72, 1, 3, 0x21, 0x70), + PIN(73, 1, 4, 0x21, 0x70), + PIN(74, 1, 5, 0x21, 0x70), + PIN(75, 1, 6, 0x21, 0x70), + PIN(76, 1, 7, 0x21, 0x70), + PIN(77, 1, 8, 0x21, 0x70), + PIN(78, 1, 9, 0x21, 0x70), + PIN(79, 1, 0, 0x25, 0x80), + PIN(80, 1, 1, 0x25, 0x80), + PIN(81, 1, 2, 0x25, 0x80), + PIN(82, 1, 3, 0x25, 0x80), + PIN(83, 0, 3, 0x16, 0x40), + PIN(84, 1, 0, 0x23, 0x70), + PIN(85, 1, 1, 0x23, 0x70), + PIN(86, 1, 2, 0x23, 0x70), + PIN(87, 1, 3, 0x23, 0x70), + PIN(88, 1, 4, 0x23, 0x70), + PIN(89, 1, 5, 0x23, 0x70), + PIN(90, 0, 2, 0x23, 0x60), + PIN(91, 0, 23, 0x23, 0x60), + PIN(92, 0, 25, 0x23, 0x60), + PIN(93, 0, 3, 0x23, 0x60), + PIN(94, 0, 24, 0x23, 0x60), + PIN(95, 0, 26, 0x23, 0x60), + PIN(96, 0, 1, 0x12, 0x50), + PIN(97, 0, 0, 0x12, 0x50), + PIN(98, 0, 2, 0x12, 0x50), + PIN(99, 0, 14, 0x24, 0x40), + PIN(100, 0, 15, 0x24, 0x40), + PIN(101, 0, 13, 0x24, 0x40), + PIN(102, 0, 12, 0x24, 0x40), + PIN(103, 0, 0, 0x24, 0x40), + PIN(104, 0, 1, 0x24, 0x40), + PIN(105, 0, 4, 0x24, 0x40), + PIN(106, 0, 5, 0x24, 0x40), + PIN(107, 0, 6, 0x24, 0x40), + PIN(108, 0, 7, 0x24, 0x40), + PIN(109, 0, 8, 0x24, 0x40), + PIN(110, 0, 9, 0x24, 0x40), + PIN(111, 0, 10, 0x24, 0x40), + PIN(112, 0, 11, 0x24, 0x40), + PIN(113, 0, 2, 0x24, 0x40), + PIN(114, 0, 3, 0x24, 0x40), + PIN(115, 0, 4, 0x23, 0x60), + PIN(116, 0, 7, 0x23, 0x60), + PIN(117, 0, 5, 0x23, 0x60), + PIN(118, 0, 6, 0x23, 0x60), + PIN(119, 0, 22, 0x25, 0x70), + PIN(120, 0, 19, 0x25, 0x70), + PIN(121, 0, 20, 0x25, 0x70), + PIN(122, 0, 21, 0x25, 0x70), + PIN(123, 0, 23, 0x25, 0x70), + PIN(124, 0, 0, 0x25, 0x70), + PIN(125, 0, 1, 0x25, 0x70), + PIN(126, 0, 2, 0x25, 0x70), + PIN(127, 0, 8, 0x23, 0x60), + PIN(128, 0, 10, 0x23, 0x60), + PIN(129, 0, 24, 0x25, 0x70), + PIN(130, 0, 26, 0x25, 0x70), + PIN(131, 0, 25, 0x25, 0x70), + PIN(132, 0, 27, 0x25, 0x70), + PIN(133, 0, 9, 0x21, 0x60), + PIN(134, 0, 12, 0x21, 0x60), + PIN(135, 0, 21, 0x16, 0x40), + PIN(136, 0, 24, 0x16, 0x40), + PIN(137, 0, 10, 0x21, 0x60), + PIN(138, 0, 13, 0x21, 0x60), + PIN(139, 0, 7, 0x12, 0x50), + PIN(140, 0, 8, 0x12, 0x50), + PIN(141, 0, 9, 0x23, 0x60), + PIN(142, 0, 11, 0x23, 0x60), + PIN(143, 0, 22, 0x16, 0x40), + PIN(144, 0, 25, 0x16, 0x40), + PIN(145, 0, 23, 0x16, 0x40), + PIN(146, 0, 26, 0x16, 0x40), + PIN(147, 0, 23, 0x24, 0x40), + PIN(148, 0, 24, 0x24, 0x40), + PIN(149, 0, 25, 0x24, 0x40), + PIN(150, 0, 26, 0x24, 0x40), + PIN(151, 0, 27, 0x24, 0x40), + PIN(152, 0, 28, 0x24, 0x40), + PIN(153, 0, 29, 0x24, 0x40), + PIN(154, 0, 30, 0x24, 0x40), + PIN(155, 0, 31, 0x24, 0x40), + PIN(156, 0, 0, 0x24, 0x50), + PIN(157, 0, 4, 0x12, 0x50), + PIN(158, 0, 3, 0x12, 0x50), + PIN(159, 0, 6, 0x12, 0x50), + PIN(160, 0, 5, 0x12, 0x50), + PIN(161, 0, 23, 0x12, 0x50), + PIN(162, 0, 24, 0x12, 0x50), + PIN(163, 0, 11, 0x21, 0x60), + PIN(164, 0, 8, 0x21, 0x60), + PIN(165, 0, 16, 0x21, 0x60), + PIN(166, 0, 1, 0x21, 0x60), + PIN(167, 0, 7, 0x21, 0x60), + PIN(168, 0, 4, 0x21, 0x60), + PIN(169, 0, 5, 0x21, 0x60), + PIN(170, 0, 0, 0x21, 0x60), + PIN(171, 0, 6, 0x21, 0x60), + PIN(172, 0, 2, 0x21, 0x60), + PIN(173, 0, 3, 0x21, 0x60), + PIN(174, 0, 7, 0x16, 0x40), + PIN(175, 0, 8, 0x16, 0x40), + PIN(176, 0, 4, 0x16, 0x40), + PIN(177, 0, 5, 0x16, 0x40), + PIN(178, 0, 6, 0x16, 0x40), + PIN(179, 0, 9, 0x16, 0x40), + PIN(180, 0, 10, 0x16, 0x40), + PIN(181, 0, 11, 0x16, 0x40), + PIN(182, 0, 12, 0x16, 0x40), + PIN(183, 0, 21, 0x12, 0x50), + PIN(184, 0, 22, 0x12, 0x50), +}; + +#endif /* MT_GPIO_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c new file mode 100644 index 0000000..8c012e7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1); + +static int plat_mt_lp_cpu_rc; + +static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state) +{ + mtk_cpc_core_on_hint_clr(cpu); + + if (IS_SYSTEM_SUSPEND_STATE(state)) { + mtk_cpc_time_sync(); + } + + return 0; +} + +static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + /* clear DBGPRCR.CORENPDRQ to allow CPU power down */ + write_dbgprcr_el1(0ULL); + + return 0; +} + +static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { + return -1; + } + + mtk_cpc_mcusys_off_reflect(); + + return 0; +} + +static int pwr_mcusys_pwron_finished(unsigned int cpu, + const psci_power_state_t *state) +{ + int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS]; + + if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { + return -1; + } + + mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id); + mt_lp_irqremain_release(); + + return 0; +} + +static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS]; + + if (!IS_MCUSYS_OFF_STATE(state)) { + goto mt_pwr_mcusysoff_break; + } + + if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */ + goto mt_pwr_mcusysoff_break; + } + + if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) { + goto mt_pwr_mcusysoff_break; + } + + plat_mt_lp_cpu_rc = + mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL); + + if (plat_mt_lp_cpu_rc < 0) { + goto mt_pwr_mcusysoff_reflect; + } + + mt_lp_irqremain_aquire(); + + return 0; + +mt_pwr_mcusysoff_reflect: + mtk_cpc_mcusys_off_reflect(); + +mt_pwr_mcusysoff_break: + plat_mt_lp_cpu_rc = -1; + + return -1; +} + +static const struct mt_lpm_tz plat_pm = { + .pwr_prompt = pwr_state_prompt, + .pwr_reflect = pwr_state_reflect, + .pwr_cpu_on = pwr_cpu_pwron, + .pwr_cpu_dwn = pwr_cpu_pwrdwn, + .pwr_cluster_on = pwr_cluster_pwron, + .pwr_cluster_dwn = pwr_cluster_pwrdwn, + .pwr_mcusys_dwn = pwr_mcusys_pwrdwn, + .pwr_mcusys_on = pwr_mcusys_pwron, + .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished +}; + +const struct mt_lpm_tz *mt_plat_cpu_pm_init(void) +{ + mtk_cpc_init(); + + if (mcdi_try_init() == 0) { + INFO("MCDI init done.\n"); + } + + mt_lp_irqremain_init(); + + return &plat_pm; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h new file mode 100644 index 0000000..83a7a53 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MT_CPU_PM_H__ +#define __MT_CPU_PM_H__ + +#define MCUSYS_STATUS_PDN (1 << 0UL) +#define MCUSYS_STATUS_CPUSYS_PROTECT (1 << 8UL) +#define MCUSYS_STATUS_MCUSYS_PROTECT (1 << 9UL) + +/* cpu_pm function ID*/ +enum mt_cpu_pm_user_id { + MCUSYS_STATUS, + CPC_COMMAND, + IRQ_REMAIN_LIST_ALLOC, + IRQ_REMAIN_IRQ_ADD, + IRQ_REMAIN_IRQ_SUBMIT, + MBOX_INFO, +}; + +/* cpu_pm lp function ID */ +enum mt_cpu_pm_lp_smc_id { + LP_CPC_COMMAND, + IRQS_REMAIN_ALLOC, + IRQS_REMAIN_CTRL, + IRQS_REMAIN_IRQ, + IRQS_REMAIN_WAKEUP_CAT, + IRQS_REMAIN_WAKEUP_SRC, +}; + +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c new file mode 100644 index 0000000..2b0f071 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +struct mtk_cpc_dev { + int auto_off; + unsigned int auto_thres_tick; +}; + +static struct mtk_cpc_dev cpc; + +static int mtk_cpc_last_core_prot(uint32_t prot_req, + uint32_t resp_reg, uint32_t resp_ofs) +{ + uint32_t sta, retry; + + retry = 0U; + + while (retry++ < RETRY_CNT_MAX) { + + mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req); + + udelay(1U); + + sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK; + + if (sta == PROT_SUCCESS) { + return CPC_SUCCESS; + } else if (sta == PROT_GIVEUP) { + return CPC_ERR_FAIL; + } + } + + return CPC_ERR_TIMEOUT; +} + +int mtk_cpu_pm_mcusys_prot_aquire(void) +{ + return mtk_cpc_last_core_prot( + MCUSYS_PROT_SET, + CPC_MCUSYS_LAST_CORE_RESP, + MCUSYS_RESP_OFS); +} + +void mtk_cpu_pm_mcusys_prot_release(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR); +} + +int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster) +{ + return mtk_cpc_last_core_prot( + CPUSYS_PROT_SET, + CPC_MCUSYS_MP_LAST_CORE_RESP, + CPUSYS_RESP_OFS); +} + +void mtk_cpu_pm_cluster_prot_release(unsigned int cluster) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR); +} + +static void mtk_cpc_cluster_cnt_backup(void) +{ + uint32_t backup_cnt; + uint32_t curr_cnt; + uint32_t cnt_mask = GENMASK(14, 0); + uint32_t clr_mask = GENMASK(1, 0); + + /* Single Cluster */ + backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP); + curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER); + + /* Get off count if dormant count is 0 */ + if ((curr_cnt & cnt_mask) == 0U) { + curr_cnt = (curr_cnt >> 16) & cnt_mask; + } else { + curr_cnt = curr_cnt & cnt_mask; + } + + mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt); + mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask); +} + +static inline void mtk_cpc_mcusys_off_en(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U); +} + +static inline void mtk_cpc_mcusys_off_dis(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U); +} + +void mtk_cpc_mcusys_off_reflect(void) +{ + mtk_cpc_mcusys_off_dis(); + mtk_cpu_pm_mcusys_prot_release(); +} + +int mtk_cpc_mcusys_off_prepare(void) +{ + if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) { + return CPC_ERR_FAIL; + } + + mtk_cpc_cluster_cnt_backup(); + mtk_cpc_mcusys_off_en(); + + return CPC_SUCCESS; +} + +void mtk_cpc_core_on_hint_set(unsigned int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu)); +} + +void mtk_cpc_core_on_hint_clr(unsigned int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); +} + +static void mtk_cpc_dump_timestamp(void) +{ + uint32_t id; + + for (id = 0U; id < CPC_TRACE_ID_NUM; id++) { + mmio_write_32(CPC_MCUSYS_TRACE_SEL, id); + + memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id), + (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA, + CPC_TRACE_SIZE); + } +} + +void mtk_cpc_time_sync(void) +{ + uint64_t kt; + uint32_t systime_l, systime_h; + + kt = sched_clock(); + systime_l = mmio_read_32(CNTSYS_L_REG); + systime_h = mmio_read_32(CNTSYS_H_REG); + + /* sync kernel timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt); + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32)); + /* sync system timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l); + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h); +} + +static void mtk_cpc_config(uint32_t cfg, uint32_t data) +{ + uint32_t val; + uint32_t reg = 0U; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + reg = CPC_MCUSYS_CPC_DBG_SETTING; + val = mmio_read_32(reg); + val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN); + break; + case CPC_SMC_CONFIG_AUTO_OFF: + reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG; + val = mmio_read_32(reg); + if (data != 0U) { + val |= CPC_AUTO_OFF_EN; + cpc.auto_off = 1; + } else { + val &= ~CPC_AUTO_OFF_EN; + cpc.auto_off = 0; + } + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + reg = CPC_MCUSYS_CPC_OFF_THRES; + cpc.auto_thres_tick = us_to_ticks(data); + val = cpc.auto_thres_tick; + break; + case CPC_SMC_CONFIG_CNT_CLR: + reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR; + val = GENMASK(1, 0); /* clr_mask */ + break; + case CPC_SMC_CONFIG_TIME_SYNC: + mtk_cpc_time_sync(); + break; + default: + break; + } + + if (reg != 0U) { + mmio_write_32(reg, val); + } +} + +static uint32_t mtk_cpc_read_config(uint32_t cfg) +{ + uint32_t res = 0U; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ? + 1U : 0U; + break; + case CPC_SMC_CONFIG_AUTO_OFF: + res = cpc.auto_off; + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + res = ticks_to_us(cpc.auto_thres_tick); + break; + case CPC_SMC_CONFIG_CNT_CLR: + break; + default: + break; + } + + return res; +} + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2) +{ + uint64_t res = 0ULL; + + switch (act) { + case CPC_SMC_EVENT_DUMP_TRACE_DATA: + mtk_cpc_dump_timestamp(); + break; + case CPC_SMC_EVENT_GIC_DPG_SET: + /* isolated_status = x2; */ + break; + case CPC_SMC_EVENT_CPC_CONFIG: + mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2); + break; + case CPC_SMC_EVENT_READ_CONFIG: + res = mtk_cpc_read_config((uint32_t)arg1); + break; + default: + break; + } + + return res; +} + +void mtk_cpc_init(void) +{ + mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING, + mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) + | CPC_DBG_EN + | CPC_CALC_EN); + + cpc.auto_off = 1; + cpc.auto_thres_tick = us_to_ticks(8000); + + mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, + mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG) + | CPC_OFF_PRE_EN + | (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U)); + + mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h new file mode 100644 index 0000000..488b1d1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_CPU_PM_CPC_H +#define MT_CPU_PM_CPC_H + +#include +#include +#include +#include + +#define NEED_CPUSYS_PROT_WORKAROUND 1 + +/* system sram registers */ +#define CPUIDLE_SRAM_REG(r) (0x11B000 + (r)) + +/* db dump */ +#define CPC_TRACE_SIZE U(0x20) +#define CPC_TRACE_ID_NUM U(10) +#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE) + +/* buckup off count */ +#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0) +#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4) + +/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */ +#define CPC_PWR_ON_SEQ_DIS BIT(1) +#define CPC_PWR_ON_PRIORITY BIT(2) +#define CPC_AUTO_OFF_EN BIT(5) +#define CPC_DORMANT_WAIT_EN BIT(14) +#define CPC_CTRL_EN BIT(16) +#define CPC_OFF_PRE_EN BIT(29) + +/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */ +#define CPUSYS_PROT_SET BIT(0) +#define MCUSYS_PROT_SET BIT(8) +#define CPUSYS_PROT_CLR BIT(8) +#define MCUSYS_PROT_CLR BIT(9) + +#define CPC_PROT_RESP_MASK U(0x3) +#define CPUSYS_RESP_OFS U(16) +#define MCUSYS_RESP_OFS U(30) + +#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK) +#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK) + +#define RETRY_CNT_MAX U(1000) + +#define PROT_RETRY U(0) +#define PROT_SUCCESS U(1) +#define PROT_GIVEUP U(2) + +/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */ +#define CPC_PROF_EN BIT(0) +#define CPC_DBG_EN BIT(1) +#define CPC_FREEZE BIT(2) +#define CPC_CALC_EN BIT(3) + +enum { + CPC_SUCCESS = 0U, + CPC_ERR_FAIL = 1U, + CPC_ERR_TIMEOUT = 2U, + NF_CPC_ERR = 3U, +}; + +enum { + CPC_SMC_EVENT_DUMP_TRACE_DATA = 0U, + CPC_SMC_EVENT_GIC_DPG_SET = 1U, + CPC_SMC_EVENT_CPC_CONFIG = 2U, + CPC_SMC_EVENT_READ_CONFIG = 3U, + NF_CPC_SMC_EVENT = 4U, +}; + +enum { + CPC_SMC_CONFIG_PROF = 0U, + CPC_SMC_CONFIG_AUTO_OFF = 1U, + CPC_SMC_CONFIG_AUTO_OFF_THRES = 2U, + CPC_SMC_CONFIG_CNT_CLR = 3U, + CPC_SMC_CONFIG_TIME_SYNC = 4U, + NF_CPC_SMC_CONFIG = 5U, +}; + +#define us_to_ticks(us) ((us) * 13) +#define ticks_to_us(tick) ((tick) / 13) + +int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster); +void mtk_cpu_pm_cluster_prot_release(unsigned int cluster); + +void mtk_cpc_mcusys_off_reflect(void); +int mtk_cpc_mcusys_off_prepare(void); + +void mtk_cpc_core_on_hint_set(unsigned int cpu); +void mtk_cpc_core_on_hint_clr(unsigned int cpu); +void mtk_cpc_time_sync(void); + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2); +void mtk_cpc_init(void); + +#endif /* MT_CPU_PM_CPC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c new file mode 100644 index 0000000..42b2808 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define KEYPAD_IRQ_ID U(138) +#define KEYPAD_WAKESRC (0x4U) + +static struct mt_irqremain remain_irqs; + +int mt_lp_irqremain_submit(void) +{ + int ret = 0; + + if (remain_irqs.count == 0) { + ret = -1; + } else { + set_wakeup_sources(remain_irqs.irqs, remain_irqs.count); + mt_lp_rm_do_update(-1, PLAT_RC_UPDATE_REMAIN_IRQS, &remain_irqs); + } + + return ret; +} + +int mt_lp_irqremain_aquire(void) +{ + int ret = 0; + + if (remain_irqs.count == 0) { + ret = -1; + } else { + mt_cirq_sw_reset(); + mt_cirq_clone_gic(); + mt_cirq_enable(); + } + + return ret; +} + +int mt_lp_irqremain_release(void) +{ + int ret = 0; + + if (remain_irqs.count == 0) { + ret = -1; + } else { + mt_cirq_flush(); + mt_cirq_disable(); + } + + return ret; +} + +void mt_lp_irqremain_init(void) +{ + uint32_t idx; + + remain_irqs.count = 0U; + + /*edge keypad*/ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = KEYPAD_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0U; + remain_irqs.wakeupsrc[idx] = KEYPAD_WAKESRC; + remain_irqs.count++; + + mt_lp_irqremain_submit(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h new file mode 100644 index 0000000..c313438 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_LP_IRQREMAIN_H +#define MT_LP_IRQREMAIN_H + +extern int mt_lp_irqremain_submit(void); +extern int mt_lp_irqremain_aquire(void); +extern int mt_lp_irqremain_release(void); +extern void mt_lp_irqremain_init(void); + +#endif /* MT_LP_IRQREMAIN_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c new file mode 100644 index 0000000..0103612 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* Read/Write */ +#define APMCU_MCUPM_MBOX_AP_READY U(0) +#define APMCU_MCUPM_MBOX_RESERVED_1 U(1) +#define APMCU_MCUPM_MBOX_RESERVED_2 U(2) +#define APMCU_MCUPM_MBOX_RESERVED_3 U(3) +#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4) +#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5) +#define APMCU_MCUPM_MBOX_BUCK_MODE U(6) +#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7) +/* Read only */ +#define APMCU_MCUPM_MBOX_TASK_STA U(8) +#define APMCU_MCUPM_MBOX_RESERVED_9 U(9) +#define APMCU_MCUPM_MBOX_RESERVED_10 U(10) +#define APMCU_MCUPM_MBOX_RESERVED_11 U(11) + +/* CPC mode - Read/Write */ +#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12) + +/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */ +#define MCUPM_MCUSYS_CTRL BIT(0) +#define MCUPM_BUCK_CTRL BIT(1) +#define MCUPM_ARMPLL_CTRL BIT(2) +#define MCUPM_CM_CTRL BIT(3) +#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0) + +/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */ +#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */ +#define MCUPM_BUCK_LP_MODE U(1) +#define MCUPM_BUCK_OFF_MODE U(2) +#define NF_MCUPM_BUCK_MODE U(3) + +/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */ +#define MCUPM_ARMPLL_ON U(0) /* default */ +#define MCUPM_ARMPLL_GATING U(1) +#define MCUPM_ARMPLL_OFF U(2) +#define NF_MCUPM_ARMPLL_MODE U(3) + +/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */ +#define MCUPM_TASK_UNINIT U(0) +#define MCUPM_TASK_INIT U(1) +#define MCUPM_TASK_INIT_FINISH U(2) +#define MCUPM_TASK_WAIT U(3) +#define MCUPM_TASK_RUN U(4) +#define MCUPM_TASK_PAUSE U(5) + +#define SSPM_MBOX_3_BASE U(0x10420000) + +#define MCDI_NOT_INIT U(0) +#define MCDI_INIT_1 U(1) +#define MCDI_INIT_2 U(2) +#define MCDI_INIT_DONE U(3) + +static int mcdi_init_status __section("tzfw_coherent_mem"); + +static inline uint32_t mcdi_mbox_read(uint32_t id) +{ + return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2)); +} + +static inline void mcdi_mbox_write(uint32_t id, uint32_t val) +{ + mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val); +} + +static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev) +{ + mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev); +} + +static void mtk_set_mcupm_pll_mode(uint32_t mode) +{ + if (mode < NF_MCUPM_ARMPLL_MODE) { + mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode); + } +} + +static void mtk_set_mcupm_buck_mode(uint32_t mode) +{ + if (mode < NF_MCUPM_BUCK_MODE) { + mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode); + } +} + +static int mtk_mcupm_is_ready(void) +{ + unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); + + return ((sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH)); +} + +static int mcdi_init_1(void) +{ + unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); + + if (sta != MCUPM_TASK_INIT) { + return -1; + } + + mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF); + mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE); + + mtk_mcupm_pwr_ctrl_setting( + MCUPM_MCUSYS_CTRL | + MCUPM_BUCK_CTRL | + MCUPM_ARMPLL_CTRL); + + mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1); + + return 0; +} + +static int mcdi_init_2(void) +{ + return mtk_mcupm_is_ready() ? 0 : -1; +} + +int mcdi_try_init(void) +{ + if (mcdi_init_status == MCDI_INIT_DONE) { + return 0; + } + + if (mcdi_init_status == MCDI_NOT_INIT) { + mcdi_init_status = MCDI_INIT_1; + } + + if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) { + mcdi_init_status = MCDI_INIT_2; + } + + if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) { + mcdi_init_status = MCDI_INIT_DONE; + } + + INFO("mcdi ready for mcusys-off-idle and system suspend\n"); + + return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h new file mode 100644 index 0000000..0e6444a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_MCDI_H +#define MT_MCDI_H + +int mcdi_try_init(void); + +#endif /* MT_MCDI_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c new file mode 100644 index 0000000..4f7ab13 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uint32_t pmic_get_hwcid(void) +{ + uint32_t val = 0; + + pwrap_read(PMIC_RG_HWCID_ADDR, &val); + + return val; +} + +void pmic_power_off(void) +{ + pwrap_write(PMIC_PWRHOLD, 0x0); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h new file mode 100644 index 0000000..91ccb19 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_H +#define PMIC_H + +#include + +#define PMIC_RG_HWCID_ADDR 0x8 +#define PMIC_PWRHOLD 0xa08 + +/* external API */ +uint32_t pmic_get_hwcid(void); +void pmic_power_off(void); + +#endif /* PMIC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..e837456 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include + +#include "platform_def.h" + +/* external API */ +int32_t pwrap_read(uint32_t adr, uint32_t *rdata); +int32_t pwrap_write(uint32_t adr, uint32_t wdata); + +static struct mt8186_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE; + +/* timeout setting */ +enum { + TIMEOUT_RESET = 50, /* us */ + TIMEOUT_READ = 50, /* us */ + TIMEOUT_WAIT_IDLE = 50 /* us */ +}; + +/* PMIC_WRAP registers */ +struct mt8186_pmic_wrap_regs { + uint32_t unused[776]; + uint32_t wacs2_cmd; + uint32_t wacs2_rdata; + uint32_t wacs2_vldclr; +}; + +enum { + RDATA_WACS_RDATA_SHIFT = 0, + RDATA_WACS_FSM_SHIFT = 16, + RDATA_WACS_REQ_SHIFT = 19, + RDATA_SYNC_IDLE_SHIFT = 20, + RDATA_INIT_DONE_SHIFT = 22, + RDATA_SYS_IDLE_SHIFT = 23, +}; + +enum { + RDATA_WACS_RDATA_MASK = 0xffff, + RDATA_WACS_FSM_MASK = 0x7, + RDATA_WACS_REQ_MASK = 0x1, + RDATA_SYNC_IDLE_MASK = 0x1, + RDATA_INIT_DONE_MASK = 0x1, + RDATA_SYS_IDLE_MASK = 0x1, +}; + +/* WACS_FSM */ +enum { + WACS_FSM_IDLE = 0x00, + WACS_FSM_REQ = 0x02, + WACS_FSM_WFDLE = 0x04, + WACS_FSM_WFVLDCLR = 0x06, + WACS_INIT_DONE = 0x01, + WACS_SYNC_IDLE = 0x01, + WACS_SYNC_BUSY = 0x00 +}; + +/* error information flag */ +enum { + E_PWR_INVALID_ARG = 1, + E_PWR_INVALID_RW = 2, + E_PWR_INVALID_ADDR = 3, + E_PWR_INVALID_WDAT = 4, + E_PWR_INVALID_OP_MANUAL = 5, + E_PWR_NOT_IDLE_STATE = 6, + E_PWR_NOT_INIT_DONE = 7, + E_PWR_NOT_INIT_DONE_READ = 8, + E_PWR_WAIT_IDLE_TIMEOUT = 9, + E_PWR_WAIT_IDLE_TIMEOUT_READ = 10, + E_PWR_INIT_SIDLY_FAIL = 11, + E_PWR_RESET_TIMEOUT = 12, + E_PWR_TIMEOUT = 13, + E_PWR_INIT_RESET_SPI = 20, + E_PWR_INIT_SIDLY = 21, + E_PWR_INIT_REG_CLOCK = 22, + E_PWR_INIT_ENABLE_PMIC = 23, + E_PWR_INIT_DIO = 24, + E_PWR_INIT_CIPHER = 25, + E_PWR_INIT_WRITE_TEST = 26, + E_PWR_INIT_ENABLE_CRC = 27, + E_PWR_INIT_ENABLE_DEWRAP = 28, + E_PWR_INIT_ENABLE_EVENT = 29, + E_PWR_READ_TEST_FAIL = 30, + E_PWR_WRITE_TEST_FAIL = 31, + E_PWR_SWITCH_DIO = 32 +}; + +#endif /* PMIC_WRAP_INIT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c new file mode 100644 index 0000000..4fcf58e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static void RTC_Config_Interface(uint32_t addr, uint16_t data, + uint16_t MASK, uint16_t SHIFT) +{ + uint16_t pmic_reg = 0; + + pmic_reg = RTC_Read(addr); + + pmic_reg &= ~(MASK << SHIFT); + pmic_reg |= (data << SHIFT); + + RTC_Write(addr, pmic_reg); +} + +static void rtc_disable_2sec_reboot(void) +{ + uint16_t reboot; + + reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) & + ~RTC_BBPU_AUTO_PDN_SEL; + RTC_Write(RTC_AL_SEC, reboot); + RTC_Write_Trigger(); +} + +static void rtc_xosc_write(uint16_t val, bool reload) +{ + uint16_t bbpu; + + RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1); + rtc_busy_wait(); + RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2); + rtc_busy_wait(); + + RTC_Write(RTC_OSC32CON, val); + rtc_busy_wait(); + + if (reload) { + bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; + RTC_Write(RTC_BBPU, bbpu); + RTC_Write_Trigger(); + } +} + +static void rtc_enable_k_eosc(void) +{ + uint16_t osc32; + uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */ + + /* Truning on eosc cali mode clock */ + RTC_Config_Interface(PMIC_RG_TOP_CON, 1, + PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK, + PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT); + RTC_Config_Interface(PMIC_RG_TOP_CON, 1, + PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK, + PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT); + RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0, + PMIC_RG_RTC_EOSC32_CK_PDN_MASK, + PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT); + + switch (rtc_eosc_cali_td) { + case 1: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + case 2: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + case 4: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + case 16: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + default: + RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6, + PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); + break; + } + /* Switch the DCXO from 32k-less mode to RTC mode, + * otherwise, EOSC cali will fail + */ + /* RTC mode will have only OFF mode and FPM */ + RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK, + PMIC_RG_XO_EN32K_MAN_SHIFT); + RTC_Write(RTC_BBPU, + RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD); + RTC_Write_Trigger(); + /* Enable K EOSC mode for normal power off and then plug out battery */ + RTC_Write(RTC_AL_YEA, ((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0) + & (~RTC_K_EOSC_RSV_1)) | RTC_K_EOSC_RSV_2); + RTC_Write_Trigger(); + + osc32 = RTC_Read(RTC_OSC32CON); + rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true); + INFO("[RTC] RTC_enable_k_eosc\n"); +} + +void rtc_power_off_sequence(void) +{ + uint16_t bbpu; + + rtc_disable_2sec_reboot(); + rtc_enable_k_eosc(); + + /* clear alarm */ + bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN; + if (Writeif_unlock()) { + RTC_Write(RTC_BBPU, bbpu); + + RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW); + RTC_Write_Trigger(); + mdelay(1); + + bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; + RTC_Write(RTC_BBPU, bbpu); + RTC_Write_Trigger(); + INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n", + RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN), + RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC)); + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h new file mode 100644 index 0000000..b48dbb9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RTC_H +#define RTC_H + +#define PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK (1U) +#define PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT (1U) +#define PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK (1U) +#define PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT (3U) +#define PMIC_RG_RTC_EOSC32_CK_PDN_MASK (1U) +#define PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT (2U) +#define PMIC_RG_EOSC_CALI_TD_MASK (7U) +#define PMIC_RG_EOSC_CALI_TD_SHIFT (5U) +#define PMIC_RG_XO_EN32K_MAN_MASK (1U) +#define PMIC_RG_XO_EN32K_MAN_SHIFT (0U) + +/* RTC registers */ +enum { + RTC_BBPU = 0x0588, + RTC_IRQ_STA = 0x058A, + RTC_IRQ_EN = 0x058C, + RTC_CII_EN = 0x058E +}; + +enum { + RTC_AL_SEC = 0x05A0, + RTC_AL_MIN = 0x05A2, + RTC_AL_HOU = 0x05A4, + RTC_AL_DOM = 0x05A6, + RTC_AL_DOW = 0x05A8, + RTC_AL_MTH = 0x05AA, + RTC_AL_YEA = 0x05AC, + RTC_AL_MASK = 0x0590 +}; + +enum { + RTC_OSC32CON = 0x05AE, + RTC_CON = 0x05C4, + RTC_WRTGR = 0x05C2 +}; + +enum { + RTC_PDN1 = 0x05B4, + RTC_PDN2 = 0x05B6, + RTC_SPAR0 = 0x05B8, + RTC_SPAR1 = 0x05BA, + RTC_PROT = 0x05BC, + RTC_DIFF = 0x05BE, + RTC_CALI = 0x05C0 +}; + +enum { + RTC_OSC32CON_UNLOCK1 = 0x1A57, + RTC_OSC32CON_UNLOCK2 = 0x2B68 +}; + +enum { + RTC_PROT_UNLOCK1 = 0x586A, + RTC_PROT_UNLOCK2 = 0x9136 +}; + +enum { + RTC_BBPU_PWREN = 1U << 0, + RTC_BBPU_CLR = 1U << 1, + RTC_BBPU_INIT = 1U << 2, + RTC_BBPU_AUTO = 1U << 3, + RTC_BBPU_CLRPKY = 1U << 4, + RTC_BBPU_RELOAD = 1U << 5, + RTC_BBPU_CBUSY = 1U << 6 +}; + +enum { + RTC_AL_MASK_SEC = 1U << 0, + RTC_AL_MASK_MIN = 1U << 1, + RTC_AL_MASK_HOU = 1U << 2, + RTC_AL_MASK_DOM = 1U << 3, + RTC_AL_MASK_DOW = 1U << 4, + RTC_AL_MASK_MTH = 1U << 5, + RTC_AL_MASK_YEA = 1U << 6 +}; + +enum { + RTC_BBPU_AUTO_PDN_SEL = 1U << 6, + RTC_BBPU_2SEC_CK_SEL = 1U << 7, + RTC_BBPU_2SEC_EN = 1U << 8, + RTC_BBPU_2SEC_MODE = 0x3 << 9, + RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11, + RTC_BBPU_2SEC_STAT_STA = 1U << 12 +}; + +enum { + RTC_BBPU_KEY = 0x43 << 8 +}; + +enum { + RTC_EMBCK_SRC_SEL = 1 << 8, + RTC_EMBCK_SEL_MODE = 3 << 6, + RTC_XOSC32_ENB = 1 << 5, + RTC_REG_XOSC32_ENB = 1 << 15 +}; + +enum { + RTC_K_EOSC_RSV_0 = 1 << 8, + RTC_K_EOSC_RSV_1 = 1 << 9, + RTC_K_EOSC_RSV_2 = 1 << 10 +}; + +/* PMIC TOP Register Definition */ +enum { + PMIC_RG_TOP_CON = 0x001E, + PMIC_RG_TOP_CKPDN_CON1 = 0x0112, + PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114, + PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116, + PMIC_RG_TOP_CKSEL_CON0 = 0x0118, + PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A, + PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C +}; + +/* PMIC SCK Register Definition */ +enum { + PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x051A, + PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x051C, + PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x051E, + PMIC_RG_EOSC_CALI_CON0 = 0x540 +}; + +/* PMIC DCXO Register Definition */ +enum { + PMIC_RG_DCXO_CW00 = 0x0788, + PMIC_RG_DCXO_CW02 = 0x0790 +}; + +/* external API */ +uint16_t RTC_Read(uint32_t addr); +void RTC_Write(uint32_t addr, uint16_t data); +int32_t rtc_busy_wait(void); +int32_t RTC_Write_Trigger(void); +int32_t Writeif_unlock(void); +void rtc_power_off_sequence(void); + +#endif /* RTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/build.mk b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/build.mk new file mode 100644 index 0000000..72a2b6b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/build.mk @@ -0,0 +1,78 @@ +# +# Copyright (c) 2022, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Enable or disable spm feature +MT_SPM_FEATURE_SUPPORT=yes + +# Enable or disable cirq restore +MT_SPM_CIRQ_FEATURE_SUPPORT=yes + +# sspm notifier support +MT_SPM_SSPM_NOTIFIER_SUPPORT=yes + +CUR_SPM_FOLDER = ${MTK_PLAT_SOC}/drivers/spm + +# spm common files +PLAT_SPM_SOURCE_FILES_COMMON += \ + ${CUR_SPM_FOLDER}/mt_spm.c \ + ${CUR_SPM_FOLDER}/mt_spm_internal.c \ + ${CUR_SPM_FOLDER}/mt_spm_pmic_wrap.c \ + ${CUR_SPM_FOLDER}/mt_spm_vcorefs.c \ + ${CUR_SPM_FOLDER}/mt_spm_conservation.c \ + ${CUR_SPM_FOLDER}/mt_spm_extern.c + +# spm platform dependcy files +PLAT_SPM_SOURCE_FILES += \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_bus26m.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_cpu_buck_ldo.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_dram.c \ + ${CUR_SPM_FOLDER}/mt_spm_cond.c \ + ${CUR_SPM_FOLDER}/mt_spm_suspend.c \ + ${CUR_SPM_FOLDER}/mt_spm_idle.c + +ifeq (${MT_SPM_FEATURE_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT + +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${PLAT_SPM_SOURCE_FILES_COMMON} +else +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \ + ${PLAT_SPM_SOURCE_FILES_COMMON} \ + ${PLAT_SPM_SOURCE_FILES} +endif + +ifeq (${MT_SPM_CIRQ_FEATURE_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_CIRQ_UNSUPPORT +endif + +ifeq (${MT_SPM_SSPM_NOTIFIER_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT +else +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${CUR_SPM_FOLDER}/notifier/mt_spm_sspm_notifier.c +endif + +ifeq (${MTK_VOLTAGE_BIN_VCORE}, yes) +PLAT_SPM_DEBUG_CFLAGS += -DATF_VOLTAGE_BIN_VCORE_SUPPORT +endif + +ifeq ($(MTK_SPM_EXTENSION_CONFIG), pmic6362) +MTK_SPM_EXTENSION_PMIC_CONTROL := 6362 +$(eval $(call add_define,MTK_SPM_EXTENSION_PMIC_CONTROL)) +endif + +$(info --------------------------------------) +$(info SPM build flags: ${PLAT_SPM_DEBUG_CFLAGS}) +$(info SPM build files: ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES}) +$(info --------------------------------------) + +# Common makefile for platform.mk +PLAT_INCLUDES += \ + ${PLAT_SPM_DEBUG_CFLAGS} \ + -I${CUR_SPM_FOLDER}/ \ + -I${CUR_SPM_FOLDER}/constraints/ \ + -I${CUR_SPM_FOLDER}/notifier/ + +PLAT_BL_COMMON_SOURCES += ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c new file mode 100644 index 0000000..66fbe91 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#ifndef ATF_PLAT_CIRQ_UNSUPPORT +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef ATF_PLAT_CIRQ_UNSUPPORT +#include +#endif + +#include +#include + +#define CONSTRAINT_BUS26M_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \ + MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \ + MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF) + +#define CONSTRAINT_BUS26M_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_ENABLE_TIA_WORKAROUND | \ + SPM_FLAG_ENABLE_LVTS_WORKAROUND | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH) + +#define CONSTRAINT_BUS26M_PCM_FLAG1 (0U) +#define CONSTRAINT_BUS26M_RESOURCE_REQ (0U) + +static unsigned int bus26m_ext_opand; +static struct mt_irqremain *refer2remain_irq; +static struct mt_spm_cond_tables cond_bus26m = { + .name = "bus26m", + .table_cg = { + 0x0385E03C, /* MTCMOS1 */ + 0x003F0100, /* INFRA0 */ + 0x0A040802, /* INFRA1 */ + 0x06017E51, /* INFRA2 */ + 0x08000000, /* INFRA3 */ + 0x00000000, /* INFRA4 */ + 0x00000000, /* INFRA5 */ + 0x03720820, /* MMSYS0 */ + 0x00000000, /* MMSYS1 */ + 0x00000000, /* MMSYS2 */ + 0x00015151, /* MMSYS3 */ + }, + .table_pll = (PLL_BIT_UNIVPLL | PLL_BIT_MFGPLL | + PLL_BIT_MSDCPLL | PLL_BIT_TVDPLL | + PLL_BIT_MMPLL), +}; + +static struct mt_spm_cond_tables cond_bus26m_res = { + .table_cg = {0U}, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_BUS26M, + .valid = (MT_SPM_RC_VALID_SW | MT_SPM_RC_VALID_COND_LATCH), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_bus26m_res, +}; + +/* + * Cirq will take the place of gic when gic is off. + * However, cirq cannot work if 26m clk is turned off when system idle/suspend. + * Therefore, we need to set irq pending for specific wakeup source. + */ +#ifdef ATF_PLAT_CIRQ_UNSUPPORT +#define do_irqs_delivery() +#else +static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs, + unsigned int irq_index, + struct wake_status *wakeup) +{ + INFO("[SPM] r12 = 0x%08x(0x%08x), flag = 0x%08x 0x%08x 0x%08x\n", + wakeup->tr.comm.r12, wakeup->md32pcm_wakeup_sta, + wakeup->tr.comm.debug_flag, wakeup->tr.comm.b_sw_flag0, + wakeup->tr.comm.b_sw_flag1); + + INFO("irq:%u(0x%08x) set pending\n", + irqs->wakeupsrc[irq_index], irqs->irqs[irq_index]); +} + +static void do_irqs_delivery(void) +{ + unsigned int idx; + int res = 0; + struct wake_status *wakeup = NULL; + struct mt_irqremain *irqs = refer2remain_irq; + + res = spm_conservation_get_result(&wakeup); + + if ((res != 0) && (irqs == NULL)) { + return; + } + + for (idx = 0; idx < irqs->count; ++idx) { + if (((wakeup->tr.comm.r12 & irqs->wakeupsrc[idx]) != 0U) || + ((wakeup->raw_sta & irqs->wakeupsrc[idx]) != 0U)) { + if ((irqs->wakeupsrc_cat[idx] & MT_IRQ_REMAIN_CAT_LOG) != 0U) { + mt_spm_irq_remain_dump(irqs, idx, wakeup); + } + + mt_irq_set_pending(irqs->irqs[idx]); + } + } +} +#endif + +static void spm_bus26m_conduct(struct spm_lp_scen *spm_lp, unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG1; + *resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ; +} + +bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return ((status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid)); +} + +int spm_update_rc_bus26m(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + res = MT_RM_STATUS_BAD; + } else { + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_bus26m; + + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + (&cond_bus26m_res) : (NULL)); + } else if (type == PLAT_RC_UPDATE_REMAIN_IRQS) { + refer2remain_irq = (struct mt_irqremain *)val; + } else { + res = MT_RM_STATUS_BAD; + } + } + + return res; +} + +unsigned int spm_allow_rc_bus26m(int state_id) +{ + (void)state_id; + + return CONSTRAINT_BUS26M_ALLOW; +} + +int spm_run_rc_bus26m(unsigned int cpu, int state_id) +{ + (void)cpu; + + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + +#ifdef ATF_VOLTAGE_BIN_VCORE_SUPPORT +#define SUSPEND_VB_MAGIC (0x5642) + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_SUSPEND_VCORE_VOLTAGE, + ((SUSPEND_VB_MAGIC << 16) | + spm_get_suspend_vcore_voltage_idx())); + } +#endif + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, CONSTRAINT_BUS26M_ALLOW | + (IS_PLAT_SUSPEND_ID(state_id) ? + (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U))); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_CLR_26M_RECORD | + MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT | + bus26m_ext_opand), + CONSTRAINT_BUS26M_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, ext_op, spm_bus26m_conduct); + } + + return 0; +} + +int spm_reset_rc_bus26m(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + ext_op |= (bus26m_ext_opand | MT_SPM_EX_OP_SET_WDT); + mt_spm_suspend_resume(state_id, ext_op, NULL); + bus26m_ext_opand = 0U; + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL); + status.enter_cnt++; + } + + do_irqs_delivery(); + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c new file mode 100644 index 0000000..c47cf1f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONSTRAINT_CPU_BUCK_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH) + +#define CONSTRAINT_CPU_BUCK_PCM_FLAG1 (0U) + +#define CONSTRAINT_CPU_BUCK_RESOURCE_REQ \ + (MT_SPM_DRAM_S1 | \ + MT_SPM_DRAM_S0 | \ + MT_SPM_SYSPLL | \ + MT_SPM_INFRA | \ + MT_SPM_26M | \ + MT_SPM_XO_FPM) + +static unsigned int cpubuckldo_status = MT_SPM_RC_VALID_SW; +static unsigned int cpubuckldo_enter_cnt; + +static void spm_cpu_bcuk_ldo_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1; + *resource_req |= CONSTRAINT_CPU_BUCK_RESOURCE_REQ; +} + +bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return IS_MT_RM_RC_READY(cpubuckldo_status); +} + +unsigned int spm_allow_rc_cpu_buck_ldo(int state_id) +{ + (void)state_id; + + return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF; +} + +int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + unsigned int ext_op = 0U; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, + (IS_PLAT_SUSPEND_ID(state_id) ? + (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U))); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + MT_SPM_EX_OP_SET_WDT, + CONSTRAINT_CPU_BUCK_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, ext_op, + spm_cpu_bcuk_ldo_conduct); + } + + cpubuckldo_enter_cnt++; + + return 0; +} + +int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + unsigned int ext_op = 0U; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL); + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL); + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c new file mode 100644 index 0000000..b281734 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2022, MediaTek Inc. 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 + +#define CONSTRAINT_DRAM_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF) + +#define CONSTRAINT_DRAM_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH) + +#define CONSTRAINT_DRAM_PCM_FLAG1 (0U) + +#define CONSTRAINT_DRAM_RESOURCE_REQ \ + (MT_SPM_SYSPLL | \ + MT_SPM_INFRA | \ + MT_SPM_26M) + +static struct mt_spm_cond_tables cond_dram = { + .name = "dram", + .table_cg = { + 0x0385E03C, /* MTCMOS1 */ + 0x003F0100, /* INFRA0 */ + 0x08040802, /* INFRA1 */ + 0x06015641, /* INFRA2 */ + 0x00000000, /* INFRA3 */ + 0x00000000, /* INFRA4 */ + 0x00000000, /* INFRA5 */ + 0x02300020, /* MMSYS0 */ + 0x00000000, /* MMSYS1 */ + 0x00000000, /* MMSYS2 */ + 0x00015111, /* MMSYS3 */ + }, + .table_pll = 0U, +}; + +static struct mt_spm_cond_tables cond_dram_res = { + .table_cg = {0U}, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_DRAM, + .valid = (MT_SPM_RC_VALID_SW | + MT_SPM_RC_VALID_COND_LATCH | + MT_SPM_RC_VALID_XSOC_BBLPM), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_dram_res, +}; + +static void spm_dram_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG1; + *resource_req |= CONSTRAINT_DRAM_RESOURCE_REQ; +} + +bool spm_is_valid_rc_dram(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return ((status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid)); +} + +int spm_update_rc_dram(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + res = MT_RM_STATUS_BAD; + } else { + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_dram; + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + (&cond_dram_res) : (NULL)); + } else { + res = MT_RM_STATUS_BAD; + } + } + + return res; +} + +unsigned int spm_allow_rc_dram(int state_id) +{ + (void)state_id; + + return CONSTRAINT_DRAM_ALLOW; +} + +int spm_run_rc_dram(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_DRAM_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | (IS_PLAT_SUSPEND_ID(state_id) ? + (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U))); +#else + (void)allows; +#endif + + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_SET_WDT | MT_SPM_EX_OP_HW_S1_DETECT), + CONSTRAINT_DRAM_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, ext_op, spm_dram_conduct); + } + + return 0; +} + +int spm_reset_rc_dram(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_DRAM_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows); +#else + (void)allows; +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, + (MT_SPM_EX_OP_SET_WDT | MT_SPM_EX_OP_HW_S1_DETECT), + NULL); + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL); + status.enter_cnt++; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h new file mode 100644 index 0000000..dfacba9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_RC_INTERNAL_H +#define MT_SPM_RC_INTERNAL_H + +#include + +#define SPM_SRAM_SLEEP_DEFAULT_FLAG (SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP) + +#define SPM_FLAG_SRAM_SLEEP_CTRL \ + (SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \ + SPM_FLAG_DISABLE_SYSRAM_SLEEP | \ + SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP | \ + SPM_FLAG_DISABLE_SRAM_EVENT) + +/* cpu buck/ldo constraint function */ +bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id); +unsigned int spm_allow_rc_cpu_buck_ldo(int state_id); +int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id); +int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id); + +/* spm resource dram constraint function */ +bool spm_is_valid_rc_dram(unsigned int cpu, int state_id); +int spm_update_rc_dram(int state_id, int type, const void *val); +unsigned int spm_allow_rc_dram(int state_id); +int spm_run_rc_dram(unsigned int cpu, int state_id); +int spm_reset_rc_dram(unsigned int cpu, int state_id); + +/* spm resource syspll constraint function */ +bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id); +int spm_update_rc_syspll(int state_id, int type, const void *val); +unsigned int spm_allow_rc_syspll(int state_id); +int spm_run_rc_syspll(unsigned int cpu, int state_id); +int spm_reset_rc_syspll(unsigned int cpu, int state_id); + +/* spm resource bus26m constraint function */ +bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id); +int spm_update_rc_bus26m(int state_id, int type, const void *val); +unsigned int spm_allow_rc_bus26m(int state_id); +int spm_run_rc_bus26m(unsigned int cpu, int state_id); +int spm_reset_rc_bus26m(unsigned int cpu, int state_id); + +#endif /* MT_SPM_RC_INTERNAL_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c new file mode 100644 index 0000000..4977de1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2022, MediaTek Inc. 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 + +#define CONSTRAINT_SYSPLL_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_VCORE_LP) + +#if (MTK_SPM_EXTENSION_PMIC_CONTROL == 6362) +#define SPM_FLAG_EXTRA_PMIC_CONTROL (SPM_FLAG_ENABLE_6362_CTRL) +#else +#define SPM_FLAG_EXTRA_PMIC_CONTROL (SPM_FLAG_ENABLE_6315_CTRL) +#endif + +#define CONSTRAINT_SYSPLL_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_USE_SRCCLKENO2 | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ + SPM_FLAG_USE_SRCCLKENO2) + +#define CONSTRAINT_SYSPLL_PCM_FLAG1 (0U) +#define CONSTRAINT_SYSPLL_RESOURCE_REQ (MT_SPM_26M) + +static struct mt_spm_cond_tables cond_syspll = { + .name = "syspll", + .table_cg = { + 0x0385E03C, /* MTCMOS1 */ + 0x003F0100, /* INFRA0 */ + 0x08040802, /* INFRA1 */ + 0x06015641, /* INFRA2 */ + 0x00000000, /* INFRA3 */ + 0x00000000, /* INFRA4 */ + 0x00000000, /* INFRA5 */ + 0x03720820, /* MMSYS0 */ + 0x00000000, /* MMSYS1 */ + 0x00000000, /* MMSYS2 */ + 0x00015151, /* MMSYS3 */ + }, + .table_pll = 0U, +}; + +static struct mt_spm_cond_tables cond_syspll_res = { + .table_cg = {0U}, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_SYSPLL, + .valid = (MT_SPM_RC_VALID_SW | + MT_SPM_RC_VALID_COND_LATCH | + MT_SPM_RC_VALID_XSOC_BBLPM), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_syspll_res, +}; + +static void spm_syspll_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG1; + + *resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ; +} + +bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return ((status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid)); +} + +int spm_update_rc_syspll(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + res = MT_RM_STATUS_BAD; + } else { + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_syspll; + + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + (&cond_syspll_res) : (NULL)); + } else { + res = MT_RM_STATUS_BAD; + } + } + + return res; +} + +unsigned int spm_allow_rc_syspll(int state_id) +{ + (void)state_id; + + return CONSTRAINT_SYSPLL_ALLOW; +} + +int spm_run_rc_syspll(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_SYSPLL_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | (IS_PLAT_SUSPEND_ID(state_id) ? + (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U))); +#else + (void)allows; +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT | + MT_SPM_EX_OP_SET_SUSPEND_MODE), + CONSTRAINT_SYSPLL_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct); + } + + return 0; +} + +int spm_reset_rc_syspll(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_SYSPLL_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows); +#else + (void)allows; +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, + (MT_SPM_EX_OP_SET_SUSPEND_MODE | + MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT), + NULL); + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL); + status.enter_cnt++; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c new file mode 100644 index 0000000..8ad50e2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt_spm_extern.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef MT_SPM_USING_BAKERY_LOCK +DEFINE_BAKERY_LOCK(spm_lock); +#define plat_spm_lock_init() bakery_lock_init(&spm_lock) +#else +spinlock_t spm_lock; +#define plat_spm_lock_init() +#endif + +/* CLK_SCP_CFG_0 */ +#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x200) +#define SPM_CK_CONTROL_EN (0x3FF) + +/* CLK_SCP_CFG_1 */ +#define CLK_SCP_CFG_1 (TOPCKGEN_BASE + 0x210) +#define CLK_SCP_CFG_1_MASK (0x100C) +#define CLK_SCP_CFG_1_SPM (0x3) + +#define MT_SPM_EX_OP_TIME_CHECK BIT(10) + +struct mt_resource_constraint plat_constraint_bus26m = { + .is_valid = spm_is_valid_rc_bus26m, + .update = spm_update_rc_bus26m, + .allow = spm_allow_rc_bus26m, + .run = spm_run_rc_bus26m, + .reset = spm_reset_rc_bus26m, +}; + +struct mt_resource_constraint plat_constraint_syspll = { + .is_valid = spm_is_valid_rc_syspll, + .update = spm_update_rc_syspll, + .allow = spm_allow_rc_syspll, + .run = spm_run_rc_syspll, + .reset = spm_reset_rc_syspll, +}; + +struct mt_resource_constraint plat_constraint_dram = { + .is_valid = spm_is_valid_rc_dram, + .update = spm_update_rc_dram, + .allow = spm_allow_rc_dram, + .run = spm_run_rc_dram, + .reset = spm_reset_rc_dram, +}; + +/* Maybe remove when the spm won't cpu power control aymore */ +struct mt_resource_constraint plat_constraint_cpu = { + .is_valid = spm_is_valid_rc_cpu_buck_ldo, + .update = NULL, + .allow = spm_allow_rc_cpu_buck_ldo, + .run = spm_run_rc_cpu_buck_ldo, + .reset = spm_reset_rc_cpu_buck_ldo, +}; + +struct mt_resource_constraint *plat_constraints[] = { + &plat_constraint_bus26m, + &plat_constraint_syspll, + &plat_constraint_dram, + &plat_constraint_cpu, + NULL, +}; + +struct mt_resource_manager plat_mt8186_rm = { + .update = mt_spm_cond_update, + .consts = plat_constraints, +}; + +void spm_boot_init(void) +{ + NOTICE("MT8186 %s\n", __func__); + + /* switch ck_off/axi_26m control to SPM */ + mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_CONTROL_EN); + mmio_clrsetbits_32(CLK_SCP_CFG_1, CLK_SCP_CFG_1_MASK, CLK_SCP_CFG_1_SPM); + + plat_spm_lock_init(); + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE); + mt_lp_rm_register(&plat_mt8186_rm); + mt_spm_idle_generic_init(); + mt_spm_suspend_init(); + spm_extern_initialize(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h new file mode 100644 index 0000000..0e21b5e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_H +#define MT_SPM_H + +#include +#include +#include + +/* + * ARM v8.2, the cache will turn off automatically when cpu + * power down. Therefore, there is no doubt to use the spin_lock here. + */ +#if !HW_ASSISTED_COHERENCY +#define MT_SPM_USING_BAKERY_LOCK +#endif + +#ifdef MT_SPM_USING_BAKERY_LOCK +DECLARE_BAKERY_LOCK(spm_lock); +#define plat_spm_lock() bakery_lock_get(&spm_lock) +#define plat_spm_unlock() bakery_lock_release(&spm_lock) +#else +extern spinlock_t spm_lock; +#define plat_spm_lock() spin_lock(&spm_lock) +#define plat_spm_unlock() spin_unlock(&spm_lock) +#endif + +#define MT_SPM_USING_SRCLKEN_RC + +/* spm extern operand definition */ +#define MT_SPM_EX_OP_CLR_26M_RECORD BIT(0) +#define MT_SPM_EX_OP_SET_WDT BIT(1) +#define MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ BIT(2) +#define MT_SPM_EX_OP_SET_SUSPEND_MODE BIT(3) +#define MT_SPM_EX_OP_SET_IS_ADSP BIT(4) +#define MT_SPM_EX_OP_SRCLKEN_RC_BBLPM BIT(5) +#define MT_SPM_EX_OP_HW_S1_DETECT BIT(6) +#define MT_SPM_EX_OP_TRACE_LP BIT(7) +#define MT_SPM_EX_OP_TRACE_SUSPEND BIT(8) +#define MT_SPM_EX_OP_TRACE_TIMESTAMP_EN BIT(9) +#define MT_SPM_EX_OP_TIME_CHECK BIT(10) +#define MT_SPM_EX_OP_TIME_OBS BIT(11) + +typedef enum { + WR_NONE = 0, + WR_UART_BUSY = 1, + WR_ABORT = 2, + WR_PCM_TIMER = 3, + WR_WAKE_SRC = 4, + WR_DVFSRC = 5, + WR_TWAM = 6, + WR_PMSR = 7, + WR_SPM_ACK_CHK = 8, + WR_UNKNOWN = 9, +} wake_reason_t; + +/* for suspend vol. bin settings */ +enum MT_PLAT_SUSPEND_VCORE { + SPM_SUSPEND_VCORE_5500 = 0, + SPM_SUSPEND_VCORE_5250 = 1, + SPM_SUSPEND_VCORE_5000 = 2, +}; + +extern void spm_boot_init(void); + +static inline void spm_lock_get(void) +{ + plat_spm_lock(); +} + +static inline void spm_lock_release(void) +{ + plat_spm_unlock(); +} + +unsigned int spm_get_suspend_vcore_voltage_idx(void); + +#endif /* MT_SPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c new file mode 100644 index 0000000..a420e16 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MT_LP_TZ_INFRA_REG(ofs) (INFRACFG_AO_BASE + ofs) +#define MT_LP_TZ_MM_REG(ofs) (MMSYS_BASE + ofs) +#define MT_LP_TZ_MDP_REG(ofs) (MDPSYS_BASE + ofs) +#define MT_LP_TZ_SPM_REG(ofs) (SPM_BASE + ofs) +#define MT_LP_TZ_TOPCK_REG(ofs) (TOPCKGEN_BASE + ofs) +#define MT_LP_TZ_APMIXEDSYS(ofs) (APMIXEDSYS + ofs) + +#define SPM_PWR_STATUS MT_LP_TZ_SPM_REG(0x016C) +#define SPM_PWR_STATUS_2ND MT_LP_TZ_SPM_REG(0x0170) +#define INFRA_SW_CG0 MT_LP_TZ_INFRA_REG(0x0090) +#define INFRA_SW_CG1 MT_LP_TZ_INFRA_REG(0x0094) +#define INFRA_SW_CG2 MT_LP_TZ_INFRA_REG(0x00AC) +#define INFRA_SW_CG3 MT_LP_TZ_INFRA_REG(0x00C8) +#define INFRA_SW_CG4 MT_LP_TZ_INFRA_REG(0x00E8) +#define INFRA_SW_CG5 MT_LP_TZ_INFRA_REG(0x00D8) +#define MMSYS_CG_CON0 MT_LP_TZ_MM_REG(0x100) +#define MMSYS_CG_CON1 MT_LP_TZ_MM_REG(0x110) +#define MMSYS_CG_CON2 MT_LP_TZ_MM_REG(0x1A0) +#define MMSYS_CG_CON3 MT_LP_TZ_MDP_REG(0x100) + +/* Check clkmux registers */ +#define CLK_CFG(id) MT_LP_TZ_TOPCK_REG(0xe0 + id * 0x10) +#define CLK_CHECK BIT(31) + +enum { + CLKMUX_DISP = 0, + CLKMUX_MDP = 1, + CLKMUX_IMG1 = 2, + CLKMUX_IMG2 = 3, + NF_CLKMUX = 4, +}; + +static bool is_clkmux_pdn(unsigned int clkmux_id) +{ + unsigned int reg, val, idx; + bool ret = false; + + if (clkmux_id & CLK_CHECK) { + clkmux_id = (clkmux_id & ~CLK_CHECK); + reg = clkmux_id / 4U; + val = mmio_read_32(CLK_CFG(reg)); + idx = clkmux_id % 4U; + ret = (((val >> (idx * 8U)) & 0x80) != 0U); + } + + return ret; +} + +static struct mt_spm_cond_tables spm_cond_t; + +struct idle_cond_info { + unsigned int subsys_mask; + uintptr_t addr; + bool bit_flip; + unsigned int clkmux_id; +}; + +#define IDLE_CG(mask, addr, bitflip, clkmux) \ + {mask, (uintptr_t)addr, bitflip, clkmux} + +static struct idle_cond_info idle_cg_info[PLAT_SPM_COND_MAX] = { + IDLE_CG(0xffffffff, SPM_PWR_STATUS, false, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG0, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG1, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG2, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG3, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG4, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG5, true, 0U), + IDLE_CG(0x00200000, MMSYS_CG_CON0, true, (CLK_CHECK | CLKMUX_DISP)), + IDLE_CG(0x00200000, MMSYS_CG_CON1, true, (CLK_CHECK | CLKMUX_DISP)), + IDLE_CG(0x00200000, MMSYS_CG_CON2, true, (CLK_CHECK | CLKMUX_DISP)), + IDLE_CG(0x00200000, MMSYS_CG_CON3, true, (CLK_CHECK | CLKMUX_MDP)), +}; + +/* Check pll idle condition */ +#define PLL_MFGPLL MT_LP_TZ_APMIXEDSYS(0x314) +#define PLL_MMPLL MT_LP_TZ_APMIXEDSYS(0x254) +#define PLL_UNIVPLL MT_LP_TZ_APMIXEDSYS(0x324) +#define PLL_MSDCPLL MT_LP_TZ_APMIXEDSYS(0x38c) +#define PLL_TVDPLL MT_LP_TZ_APMIXEDSYS(0x264) + +unsigned int mt_spm_cond_check(int state_id, + const struct mt_spm_cond_tables *src, + const struct mt_spm_cond_tables *dest, + struct mt_spm_cond_tables *res) +{ + unsigned int blocked = 0U; + unsigned int i; + bool is_system_suspend = IS_PLAT_SUSPEND_ID(state_id); + + if ((src == NULL) || (dest == NULL)) { + blocked = SPM_COND_CHECK_FAIL; + } else { + for (i = 0U; i < PLAT_SPM_COND_MAX; i++) { + if (res != NULL) { + res->table_cg[i] = (src->table_cg[i] & dest->table_cg[i]); + if (is_system_suspend && ((res->table_cg[i]) != 0U)) { + INFO("suspend: %s block[%u](0x%lx) = 0x%08x\n", + dest->name, i, idle_cg_info[i].addr, + res->table_cg[i]); + } + + if ((res->table_cg[i]) != 0U) { + blocked |= BIT(i); + } + } else if ((src->table_cg[i] & dest->table_cg[i]) != 0U) { + blocked |= BIT(i); + break; + } + } + + if (res != NULL) { + res->table_pll = (src->table_pll & dest->table_pll); + + if (res->table_pll != 0U) { + blocked |= (res->table_pll << SPM_COND_BLOCKED_PLL_IDX) | + SPM_COND_CHECK_BLOCKED_PLL; + } + } else if ((src->table_pll & dest->table_pll) != 0U) { + blocked |= SPM_COND_CHECK_BLOCKED_PLL; + } + + if (is_system_suspend && ((blocked) != 0U)) { + INFO("suspend: %s total blocked = 0x%08x\n", dest->name, blocked); + } + } + + return blocked; +} + +#define IS_MT_SPM_PWR_OFF(mask) \ + (((mmio_read_32(SPM_PWR_STATUS) & mask) == 0U) && \ + ((mmio_read_32(SPM_PWR_STATUS_2ND) & mask) == 0U)) + +int mt_spm_cond_update(struct mt_resource_constraint **con, int stateid, void *priv) +{ + int res; + uint32_t i; + struct mt_resource_constraint *const *rc; + + /* read all cg state */ + for (i = 0U; i < PLAT_SPM_COND_MAX; i++) { + spm_cond_t.table_cg[i] = 0U; + + /* check mtcmos, if off set idle_value and clk to 0 disable */ + if (IS_MT_SPM_PWR_OFF(idle_cg_info[i].subsys_mask)) { + continue; + } + + /* check clkmux */ + if (is_clkmux_pdn(idle_cg_info[i].clkmux_id)) { + continue; + } + + spm_cond_t.table_cg[i] = idle_cg_info[i].bit_flip ? + ~mmio_read_32(idle_cg_info[i].addr) : + mmio_read_32(idle_cg_info[i].addr); + } + + spm_cond_t.table_pll = 0U; + if ((mmio_read_32(PLL_MFGPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MFGPLL; + } + + if ((mmio_read_32(PLL_MMPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MMPLL; + } + + if ((mmio_read_32(PLL_UNIVPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_UNIVPLL; + } + + if ((mmio_read_32(PLL_MSDCPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MSDCPLL; + } + + if ((mmio_read_32(PLL_TVDPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_TVDPLL; + } + + spm_cond_t.priv = priv; + + for (rc = con; *rc != NULL; rc++) { + if (((*rc)->update) == NULL) { + continue; + } + + res = (*rc)->update(stateid, PLAT_RC_UPDATE_CONDITION, + (void const *)&spm_cond_t); + if (res != MT_RM_STATUS_OK) { + break; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h new file mode 100644 index 0000000..24c39ba --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONDIT_H +#define MT_SPM_CONDIT_H + +#include + +enum PLAT_SPM_COND { + PLAT_SPM_COND_MTCMOS1 = 0, + PLAT_SPM_COND_CG_INFRA_0 = 1, + PLAT_SPM_COND_CG_INFRA_1 = 2, + PLAT_SPM_COND_CG_INFRA_2 = 3, + PLAT_SPM_COND_CG_INFRA_3 = 4, + PLAT_SPM_COND_CG_INFRA_4 = 5, + PLAT_SPM_COND_CG_INFRA_5 = 6, + PLAT_SPM_COND_CG_MMSYS_0 = 7, + PLAT_SPM_COND_CG_MMSYS_1 = 8, + PLAT_SPM_COND_CG_MMSYS_2 = 9, + PLAT_SPM_COND_CG_MMSYS_3 = 10, + PLAT_SPM_COND_MAX = 11, +}; + +#define PLL_BIT_UNIVPLL BIT(0) +#define PLL_BIT_MFGPLL BIT(1) +#define PLL_BIT_MSDCPLL BIT(2) +#define PLL_BIT_TVDPLL BIT(3) +#define PLL_BIT_MMPLL BIT(4) + +/* + * Definition about SPM_COND_CHECK_BLOCKED + * bit [00 ~ 15]: cg blocking index + * bit [16 ~ 29]: pll blocking index + * bit [30] : pll blocking information + * bit [31] : idle condition check fail + */ +#define SPM_COND_BLOCKED_CG_IDX U(0) +#define SPM_COND_BLOCKED_PLL_IDX U(16) +#define SPM_COND_CHECK_BLOCKED_PLL BIT(30) +#define SPM_COND_CHECK_FAIL BIT(31) + +struct mt_spm_cond_tables { + char *name; + unsigned int table_cg[PLAT_SPM_COND_MAX]; + unsigned int table_pll; + void *priv; +}; + +extern unsigned int mt_spm_cond_check(int state_id, + const struct mt_spm_cond_tables *src, + const struct mt_spm_cond_tables *dest, + struct mt_spm_cond_tables *res); + +extern int mt_spm_cond_update(struct mt_resource_constraint **con, + int stateid, void *priv); + +#endif /* MT_SPM_CONDIT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c new file mode 100644 index 0000000..a6ea977 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MT_RESUMETIME_THRESHOLD_MAX (5U) /*ms*/ +#define IS_RESUME_OVERTIME(delta) (delta > MT_RESUMETIME_THRESHOLD_MAX) + +static struct wake_status spm_wakesta; /* record last wakesta */ + +static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + unsigned int resource_req) +{ + int ret = 0; + struct pwr_ctrl *pwrctrl; + uint32_t cpu = plat_my_core_pos(); + + pwrctrl = spm_lp->pwrctrl; + + __spm_set_cpu_status(cpu); + __spm_set_power_control(pwrctrl); + __spm_set_wakeup_event(pwrctrl); + __spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl); + __spm_set_pcm_flags(pwrctrl); + + __spm_src_req_update(pwrctrl, resource_req); + + if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) { + __spm_set_pcm_wdt(1); + } + + if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) { + __spm_xo_soc_bblpm(1); + } + + if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) { + spm_hw_s1_state_monitor_resume(); + } + + /* Disable auto resume by PCM in system suspend stage */ + if (IS_PLAT_SUSPEND_ID(state_id)) { + __spm_disable_pcm_timer(); + __spm_set_pcm_wdt(0); + } + + __spm_send_cpu_wakeup_event(); + + INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n", + cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE), + (mmio_read_32(PCM_TIMER_VAL) / 32768)); + INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n", + pwrctrl->pcm_flags, pwrctrl->pcm_flags1, + mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS), + mmio_read_32(PWR_STATUS_2ND)); + + return ret; +} + +static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status) +{ + unsigned int ext_status = 0U; + + spm_wakesta.tr.comm.resumetime = 0; + spm_wakesta.tr.comm.times_h = spm_wakesta.tr.comm.times_l = 0; + + /* system watchdog will be resumed at kernel stage */ + if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) { + __spm_set_pcm_wdt(0); + } + + if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) { + __spm_xo_soc_bblpm(0); + } + + if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) { + spm_hw_s1_state_monitor_pause(&ext_status); + } + + __spm_ext_int_wakeup_req_clr(); + + __spm_get_wakeup_status(&spm_wakesta, ext_status); + + if (status != NULL) { + *status = &spm_wakesta; + } + + __spm_clean_after_wakeup(); + + if (IS_PLAT_SUSPEND_ID(state_id)) { + __spm_output_wake_reason(state_id, &spm_wakesta); + } + +} + +int spm_conservation(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, unsigned int resource_req) +{ + int ret = 0; + + if (spm_lp == NULL) { + ret = -1; + } else { + spm_lock_get(); + go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req); + spm_lock_release(); + } + + return ret; +} + +void spm_conservation_finish(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status) +{ + spm_lock_get(); + go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status); + spm_lock_release(); +} + +int spm_conservation_get_result(struct wake_status **res) +{ + int ret = 0; + + if (res == NULL) { + ret = -1; + } else { + *res = &spm_wakesta; + } + return ret; +} + +#define GPIO_BANK (GPIO_BASE + 0x6F0) +#define TRAP_UFS_FIRST BIT(11) /* bit 11, 0: UFS, 1: eMMC */ + +void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl) +{ + if (pwrctrl != NULL) { + /* For ufs, emmc storage type */ + if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) { + /* If eMMC is used, mask UFS req */ + pwrctrl->reg_ufs_srcclkena_mask_b = 0; + pwrctrl->reg_ufs_infra_req_mask_b = 0; + pwrctrl->reg_ufs_apsrc_req_mask_b = 0; + pwrctrl->reg_ufs_vrf18_req_mask_b = 0; + pwrctrl->reg_ufs_ddren_req_mask_b = 0; + } + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h new file mode 100644 index 0000000..e7ef346 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONSERVATION_H +#define MT_SPM_CONSERVATION_H + +#include + +extern int spm_conservation(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + unsigned int resource_req); +extern void spm_conservation_finish(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status); +extern int spm_conservation_get_result(struct wake_status **res); +extern void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl); + +#endif /* MT_SPM_CONSERVATION_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h new file mode 100644 index 0000000..53be3b6 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONSTRAINT_H +#define MT_SPM_CONSTRAINT_H + +#include + +#define MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF BIT(0) +#define MT_RM_CONSTRAINT_ALLOW_DRAM_S0 BIT(1) +#define MT_RM_CONSTRAINT_ALLOW_DRAM_S1 BIT(2) +#define MT_RM_CONSTRAINT_ALLOW_VCORE_LP BIT(3) +#define MT_RM_CONSTRAINT_ALLOW_INFRA_PDN BIT(4) +#define MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF BIT(5) +#define MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND BIT(6) +#define MT_RM_CONSTRAINT_ALLOW_BBLPM BIT(7) +#define MT_RM_CONSTRAINT_ALLOW_XO_UFS BIT(8) +#define MT_RM_CONSTRAINT_ALLOW_GPS_STATE BIT(9) +#define MT_RM_CONSTRAINT_ALLOW_LVTS_STATE BIT(10) + +#define MT_SPM_RC_INVALID (0x0) +#define MT_SPM_RC_VALID_SW BIT(0) +#define MT_SPM_RC_VALID_FW BIT(1) +#define MT_SPM_RC_VALID_RESIDNECY BIT(2) +#define MT_SPM_RC_VALID_COND_CHECK BIT(3) +#define MT_SPM_RC_VALID_COND_LATCH BIT(4) +#define MT_SPM_RC_VALID_UFS_H8 BIT(5) +#define MT_SPM_RC_VALID_FLIGHTMODE BIT(6) +#define MT_SPM_RC_VALID_XSOC_BBLPM BIT(7) +#define MT_SPM_RC_VALID_TRACE_EVENT BIT(8) + +#define MT_SPM_RC_VALID (MT_SPM_RC_VALID_SW) + +#define IS_MT_RM_RC_READY(status) \ + ((status & MT_SPM_RC_VALID) == MT_SPM_RC_VALID) + +#define MT_SPM_RC_BBLPM_MODE \ + (MT_SPM_RC_VALID_UFS_H8 | \ + MT_SPM_RC_VALID_FLIGHTMODE | \ + MT_SPM_RC_VALID_XSOC_BBLPM) + +#define IS_MT_SPM_RC_BBLPM_MODE(st) \ + ((st & (MT_SPM_RC_BBLPM_MODE)) == MT_SPM_RC_BBLPM_MODE) + +struct constraint_status { + uint16_t id; + uint16_t valid; + uint32_t cond_block; + uint32_t enter_cnt; + struct mt_spm_cond_tables *cond_res; +}; + +enum MT_SPM_RM_RC_TYPE { + MT_RM_CONSTRAINT_ID_BUS26M = 0U, + MT_RM_CONSTRAINT_ID_SYSPLL = 1U, + MT_RM_CONSTRAINT_ID_DRAM = 2U, + MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO = 3U, + MT_RM_CONSTRAINT_ID_ALL = 4U, +}; + +#endif /* MT_SPM_CONSTRAINT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c new file mode 100644 index 0000000..608d9f9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) since 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define INFRA_AO_RES_CTRL_MASK (INFRACFG_AO_BASE + 0xB8) +#define INFRA_AO_RES_CTRL_MASK_EMI_IDLE BIT(18) +#define INFRA_AO_RES_CTRL_MASK_MPU_IDLE BIT(15) + +void spm_extern_initialize(void) +{ + unsigned int val; + + val = mmio_read_32(INFRA_AO_RES_CTRL_MASK); + + val |= (INFRA_AO_RES_CTRL_MASK_EMI_IDLE | INFRA_AO_RES_CTRL_MASK_MPU_IDLE); + mmio_write_32(INFRA_AO_RES_CTRL_MASK, val); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h new file mode 100644 index 0000000..5bcbaff --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) since 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_EXTERN_H +#define MT_SPM_EXTERN_H + +void spm_extern_initialize(void); + +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c new file mode 100644 index 0000000..04776c8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __WAKE_SRC_FOR_SUSPEND_COMMON__ \ + (R12_PCM_TIMER | \ + R12_KP_IRQ_B | \ + R12_APWDT_EVENT_B | \ + R12_APXGPT1_EVENT_B | \ + R12_CONN2AP_SPM_WAKEUP_B | \ + R12_EINT_EVENT_B | \ + R12_CONN_WDT_IRQ_B | \ + R12_SSPM2SPM_WAKEUP_B | \ + R12_SCP2SPM_WAKEUP_B | \ + R12_ADSP2SPM_WAKEUP_B | \ + R12_USBX_CDSC_B | \ + R12_USBX_POWERDWN_B | \ + R12_SYS_TIMER_EVENT_B | \ + R12_EINT_EVENT_SECURE_B | \ + R12_AFE_IRQ_MCU_B | \ + R12_SYS_CIRQ_IRQ_B | \ + R12_NNA_WAKEUP | \ + R12_SEJ_EVENT_B | \ + R12_REG_CPU_WAKEUP) + +#if defined(CFG_MICROTRUST_TEE_SUPPORT) +#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__) +#else +#define WAKE_SRC_FOR_SUSPEND \ + (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \ + R12_SEJ_EVENT_B) +#endif + +static struct pwr_ctrl idle_spm_pwr = { + .timer_val = 0x28000, + .wake_src = WAKE_SRC_FOR_SUSPEND, + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + .reg_wfi_op = 0, + .reg_wfi_type = 0, + .reg_mp0_cputop_idle_mask = 0, + .reg_mp1_cputop_idle_mask = 0, + .reg_mcusys_idle_mask = 0, + .reg_md_apsrc_1_sel = 0, + .reg_md_apsrc_0_sel = 0, + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC6_MASK */ + .reg_ccif_event_infra_req_mask_b = 0, + .reg_ccif_event_apsrc_req_mask_b = 0, + + /* SPM_SRC_REQ */ + .reg_spm_apsrc_req = 0, + .reg_spm_f26m_req = 0, + .reg_spm_infra_req = 0, + .reg_spm_vrf18_req = 0, + .reg_spm_ddren_req = 0, + .reg_spm_dvfs_req = 0, + .reg_spm_sw_mailbox_req = 0, + .reg_spm_sspm_mailbox_req = 0, + .reg_spm_adsp_mailbox_req = 0, + .reg_spm_scp_mailbox_req = 0, + + /* SPM_SRC_MASK */ + .reg_md_0_srcclkena_mask_b = 0, + .reg_md_0_infra_req_mask_b = 0, + .reg_md_0_apsrc_req_mask_b = 0, + .reg_md_0_vrf18_req_mask_b = 0, + .reg_md_0_ddren_req_mask_b = 0, + .reg_md_1_srcclkena_mask_b = 0, + .reg_md_1_infra_req_mask_b = 0, + .reg_md_1_apsrc_req_mask_b = 0, + .reg_md_1_vrf18_req_mask_b = 0, + .reg_md_1_ddren_req_mask_b = 0, + .reg_conn_srcclkena_mask_b = 1, + .reg_conn_srcclkenb_mask_b = 0, + .reg_conn_infra_req_mask_b = 1, + .reg_conn_apsrc_req_mask_b = 1, + .reg_conn_vrf18_req_mask_b = 1, + .reg_conn_ddren_req_mask_b = 1, + .reg_conn_vfe28_mask_b = 0, + .reg_srcclkeni_srcclkena_mask_b = 1, + .reg_srcclkeni_infra_req_mask_b = 1, + .reg_infrasys_apsrc_req_mask_b = 0, + .reg_infrasys_ddren_req_mask_b = 1, + .reg_sspm_srcclkena_mask_b = 1, + .reg_sspm_infra_req_mask_b = 1, + .reg_sspm_apsrc_req_mask_b = 1, + .reg_sspm_vrf18_req_mask_b = 1, + .reg_sspm_ddren_req_mask_b = 1, + + /* SPM_SRC2_MASK */ + .reg_scp_srcclkena_mask_b = 1, + .reg_scp_infra_req_mask_b = 1, + .reg_scp_apsrc_req_mask_b = 1, + .reg_scp_vrf18_req_mask_b = 1, + .reg_scp_ddren_req_mask_b = 1, + .reg_audio_dsp_srcclkena_mask_b = 1, + .reg_audio_dsp_infra_req_mask_b = 1, + .reg_audio_dsp_apsrc_req_mask_b = 1, + .reg_audio_dsp_vrf18_req_mask_b = 1, + .reg_audio_dsp_ddren_req_mask_b = 1, + .reg_ufs_srcclkena_mask_b = 1, + .reg_ufs_infra_req_mask_b = 1, + .reg_ufs_apsrc_req_mask_b = 1, + .reg_ufs_vrf18_req_mask_b = 1, + .reg_ufs_ddren_req_mask_b = 1, + .reg_disp0_apsrc_req_mask_b = 1, + .reg_disp0_ddren_req_mask_b = 1, + .reg_disp1_apsrc_req_mask_b = 1, + .reg_disp1_ddren_req_mask_b = 1, + .reg_gce_infra_req_mask_b = 1, + .reg_gce_apsrc_req_mask_b = 1, + .reg_gce_vrf18_req_mask_b = 1, + .reg_gce_ddren_req_mask_b = 1, + .reg_apu_srcclkena_mask_b = 0, + .reg_apu_infra_req_mask_b = 0, + .reg_apu_apsrc_req_mask_b = 0, + .reg_apu_vrf18_req_mask_b = 0, + .reg_apu_ddren_req_mask_b = 0, + .reg_cg_check_srcclkena_mask_b = 0, + .reg_cg_check_apsrc_req_mask_b = 0, + .reg_cg_check_vrf18_req_mask_b = 0, + .reg_cg_check_ddren_req_mask_b = 0, + + /* SPM_SRC3_MASK */ + .reg_dvfsrc_event_trigger_mask_b = 1, + .reg_sw2spm_wakeup_mask_b = 0, + .reg_adsp2spm_wakeup_mask_b = 0, + .reg_sspm2spm_wakeup_mask_b = 0, + .reg_scp2spm_wakeup_mask_b = 0, + .reg_csyspwrup_ack_mask = 1, + .reg_spm_reserved_srcclkena_mask_b = 0, + .reg_spm_reserved_infra_req_mask_b = 0, + .reg_spm_reserved_apsrc_req_mask_b = 0, + .reg_spm_reserved_vrf18_req_mask_b = 0, + .reg_spm_reserved_ddren_req_mask_b = 0, + .reg_mcupm_srcclkena_mask_b = 0, + .reg_mcupm_infra_req_mask_b = 0, + .reg_mcupm_apsrc_req_mask_b = 0, + .reg_mcupm_vrf18_req_mask_b = 0, + .reg_mcupm_ddren_req_mask_b = 0, + .reg_msdc0_srcclkena_mask_b = 1, + .reg_msdc0_infra_req_mask_b = 1, + .reg_msdc0_apsrc_req_mask_b = 1, + .reg_msdc0_vrf18_req_mask_b = 1, + .reg_msdc0_ddren_req_mask_b = 1, + .reg_msdc1_srcclkena_mask_b = 1, + .reg_msdc1_infra_req_mask_b = 1, + .reg_msdc1_apsrc_req_mask_b = 1, + .reg_msdc1_vrf18_req_mask_b = 1, + .reg_msdc1_ddren_req_mask_b = 1, + + /* SPM_SRC4_MASK */ + .reg_ccif_event_srcclkena_mask_b = 0, + .reg_bak_psri_srcclkena_mask_b = 0, + .reg_bak_psri_infra_req_mask_b = 0, + .reg_bak_psri_apsrc_req_mask_b = 0, + .reg_bak_psri_vrf18_req_mask_b = 0, + .reg_bak_psri_ddren_req_mask_b = 0, + .reg_dramc_md32_infra_req_mask_b = 0, + .reg_dramc_md32_vrf18_req_mask_b = 0, + .reg_conn_srcclkenb2pwrap_mask_b = 0, + .reg_dramc_md32_apsrc_req_mask_b = 0, + + /* SPM_SRC5_MASK */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x83, + .reg_mcusys_merge_ddren_req_mask_b = 0x83, + .reg_afe_srcclkena_mask_b = 1, + .reg_afe_infra_req_mask_b = 1, + .reg_afe_apsrc_req_mask_b = 1, + .reg_afe_vrf18_req_mask_b = 1, + .reg_afe_ddren_req_mask_b = 1, + .reg_msdc2_srcclkena_mask_b = 0, + .reg_msdc2_infra_req_mask_b = 0, + .reg_msdc2_apsrc_req_mask_b = 0, + .reg_msdc2_vrf18_req_mask_b = 0, + .reg_msdc2_ddren_req_mask_b = 0, + + /* SPM_WAKEUP_EVENT_MASK */ + .reg_wakeup_event_mask = 0xE1283203, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, + + /* SPM_SRC7_MASK */ + .reg_pcie_srcclkena_mask_b = 0, + .reg_pcie_infra_req_mask_b = 0, + .reg_pcie_apsrc_req_mask_b = 0, + .reg_pcie_vrf18_req_mask_b = 0, + .reg_pcie_ddren_req_mask_b = 0, + .reg_dpmaif_srcclkena_mask_b = 1, + .reg_dpmaif_infra_req_mask_b = 1, + .reg_dpmaif_apsrc_req_mask_b = 1, + .reg_dpmaif_vrf18_req_mask_b = 1, + .reg_dpmaif_ddren_req_mask_b = 1, + + /* Auto-gen End */ +}; + +struct spm_lp_scen idle_spm_lp = { + .pwrctrl = &idle_spm_pwr, +}; + +int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand, + spm_idle_conduct fn) +{ + unsigned int src_req = 0U; + + if (fn != NULL) { + fn(&idle_spm_lp, &src_req); + } + + return spm_conservation(state_id, ext_opand, &idle_spm_lp, src_req); +} +void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand, + struct wake_status **status, + spm_idle_conduct_restore fn) +{ + ext_opand |= (MT_SPM_EX_OP_TIME_CHECK | MT_SPM_EX_OP_TIME_OBS); + spm_conservation_finish(state_id, ext_opand, &idle_spm_lp, status); +} + +void mt_spm_idle_generic_init(void) +{ + spm_conservation_pwrctrl_init(idle_spm_lp.pwrctrl); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h new file mode 100644 index 0000000..7196190 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_IDLE_H +#define MT_SPM_IDLE_H + +typedef void (*spm_idle_conduct)(struct spm_lp_scen *spm_lp, unsigned int *resource_req); + +typedef int (*spm_idle_conduct_restore)(int state_id, + struct spm_lp_scen *spm_lp, + struct wake_status *status); + +int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand, spm_idle_conduct fn); + +void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand, + struct wake_status **status, + spm_idle_conduct_restore fn); + +void mt_spm_idle_generic_init(void); + +#endif /* MT_SPM_IDLE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c new file mode 100644 index 0000000..f228961 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Define and Declare */ +#define ROOT_CORE_ADDR_OFFSET (0x20000000) +#define SPM_WAKEUP_EVENT_MASK_CLEAN_MASK (0xefffffff) +#define SPM_INIT_DONE_US (20) + +static unsigned int mt_spm_bblpm_cnt; + +const char *wakeup_src_str[32] = { + [0] = "R12_PCM_TIMER", + [1] = "R12_RESERVED_DEBUG_B", + [2] = "R12_KP_IRQ_B", + [3] = "R12_APWDT_EVENT_B", + [4] = "R12_APXGPT1_EVENT_B", + [5] = "R12_CONN2AP_SPM_WAKEUP_B", + [6] = "R12_EINT_EVENT_B", + [7] = "R12_CONN_WDT_IRQ_B", + [8] = "R12_CCIF0_EVENT_B", + [9] = "R12_LOWBATTERY_IRQ_B", + [10] = "R12_SC_SSPM2SPM_WAKEUP_B", + [11] = "R12_SC_SCP2SPM_WAKEUP_B", + [12] = "R12_SC_ADSP2SPM_WAKEUP_B", + [13] = "R12_PCM_WDT_WAKEUP_B", + [14] = "R12_USB_CDSC_B", + [15] = "R12_USB_POWERDWN_B", + [16] = "R12_SYS_TIMER_EVENT_B", + [17] = "R12_EINT_EVENT_SECURE_B", + [18] = "R12_CCIF1_EVENT_B", + [19] = "R12_UART0_IRQ_B", + [20] = "R12_AFE_IRQ_MCU_B", + [21] = "R12_THERM_CTRL_EVENT_B", + [22] = "R12_SYS_CIRQ_IRQ_B", + [23] = "R12_MD2AP_PEER_EVENT_B", + [24] = "R12_CSYSPWREQ_B", + [25] = "R12_MD1_WDT_B", + [26] = "R12_AP2AP_PEER_WAKEUPEVENT_B", + [27] = "R12_SEJ_EVENT_B", + [28] = "R12_SPM_CPU_WAKEUPEVENT_B", + [29] = "R12_APUSYS", + [30] = "R12_PCIE_BRIDGE_IRQ", + [31] = "R12_PCIE_IRQ", +}; + +/* Function and API */ +wake_reason_t __spm_output_wake_reason(int state_id, const struct wake_status *wakesta) +{ + uint32_t i, bk_vtcxo_dur, spm_26m_off_pct = 0U; + wake_reason_t wr = WR_UNKNOWN; + + if (wakesta != NULL) { + if (wakesta->abort != 0U) { + ERROR("spmfw flow is aborted: 0x%x, timer_out = %u\n", + wakesta->abort, wakesta->timer_out); + } else { + for (i = 0U; i < 32U; i++) { + if ((wakesta->r12 & BIT(i)) != 0U) { + INFO("wake up by %s, timer_out = %u\n", + wakeup_src_str[i], wakesta->timer_out); + wr = WR_WAKE_SRC; + break; + } + } + } + + INFO("r12 = 0x%x, r12_ext = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n", + wakesta->r12, wakesta->r12_ext, wakesta->r13, wakesta->debug_flag, + wakesta->debug_flag1); + INFO("raw_sta = 0x%x 0x%x 0x%x, idle_sta = 0x%x, cg_check_sta = 0x%x\n", + wakesta->raw_sta, wakesta->md32pcm_wakeup_sta, + wakesta->md32pcm_event_sta, wakesta->idle_sta, + wakesta->cg_check_sta); + INFO("req_sta = 0x%x 0x%x 0x%x 0x%x 0x%x, isr = 0x%x\n", + wakesta->req_sta0, wakesta->req_sta1, wakesta->req_sta2, + wakesta->req_sta3, wakesta->req_sta4, wakesta->isr); + INFO("rt_req_sta0 = 0x%x, rt_req_sta1 = 0x%x, rt_req_sta2 = 0x%x\n", + wakesta->rt_req_sta0, wakesta->rt_req_sta1, wakesta->rt_req_sta2); + INFO("rt_req_sta3 = 0x%x, dram_sw_con_3 = 0x%x, raw_ext_sta = 0x%x\n", + wakesta->rt_req_sta3, wakesta->rt_req_sta4, wakesta->raw_ext_sta); + INFO("wake_misc = 0x%x, pcm_flag = 0x%x 0x%x 0x%x 0x%x, req = 0x%x\n", + wakesta->wake_misc, wakesta->sw_flag0, wakesta->sw_flag1, + wakesta->b_sw_flag0, wakesta->b_sw_flag1, wakesta->src_req); + INFO("clk_settle = 0x%x, wlk_cntcv_l = 0x%x, wlk_cntcv_h = 0x%x\n", + wakesta->clk_settle, mmio_read_32(SYS_TIMER_VALUE_L), + mmio_read_32(SYS_TIMER_VALUE_H)); + + if (wakesta->timer_out != 0U) { + bk_vtcxo_dur = mmio_read_32(SPM_BK_VTCXO_DUR); + spm_26m_off_pct = (100 * bk_vtcxo_dur) / wakesta->timer_out; + INFO("spm_26m_off_pct = %u\n", spm_26m_off_pct); + } + } + + return wr; +} + +void __spm_set_cpu_status(unsigned int cpu) +{ + uint32_t root_core_addr; + + if (cpu < 8U) { + mmio_write_32(ROOT_CPUTOP_ADDR, BIT(cpu)); + + root_core_addr = SPM_CPU0_PWR_CON + (cpu * 0x4); + root_core_addr += ROOT_CORE_ADDR_OFFSET; + mmio_write_32(ROOT_CORE_ADDR, root_core_addr); + + /* Notify SSPM that preferred cpu wakeup */ + mmio_write_32(MCUPM_MBOX_WAKEUP_CPU, cpu); + } else { + ERROR("%s: error cpu number %d\n", __func__, cpu); + } +} + +void __spm_src_req_update(const struct pwr_ctrl *pwrctrl, + unsigned int resource_usage) +{ + uint8_t apsrc_req = ((resource_usage & MT_SPM_DRAM_S0) != 0U) ? + 1 : pwrctrl->reg_spm_apsrc_req; + uint8_t ddr_en_req = ((resource_usage & MT_SPM_DRAM_S1) != 0U) ? + 1 : pwrctrl->reg_spm_ddren_req; + uint8_t vrf18_req = ((resource_usage & MT_SPM_SYSPLL) != 0U) ? + 1 : pwrctrl->reg_spm_vrf18_req; + uint8_t infra_req = ((resource_usage & MT_SPM_INFRA) != 0U) ? + 1 : pwrctrl->reg_spm_infra_req; + uint8_t f26m_req = ((resource_usage & (MT_SPM_26M | MT_SPM_XO_FPM)) != 0U) ? + 1 : pwrctrl->reg_spm_f26m_req; + + /* + * if SPM_FLAG_SSPM_INFRA_SLEEP_MODE set, + * clear sspm_srclkena_mask_b and sspm_infra_mask_b + */ + uint8_t reg_sspm_srcclkena_mask_b = + (pwrctrl->pcm_flags & SPM_FLAG_SSPM_INFRA_SLEEP_MODE) + ? 0U : pwrctrl->reg_sspm_srcclkena_mask_b; + + uint8_t reg_sspm_infra_req_mask_b = + (pwrctrl->pcm_flags & SPM_FLAG_SSPM_INFRA_SLEEP_MODE) + ? 0 : pwrctrl->reg_sspm_infra_req_mask_b; + + /* SPM_SRC_REQ */ + mmio_write_32(SPM_SRC_REQ, + ((apsrc_req & 0x1) << 0) | + ((f26m_req & 0x1) << 1) | + ((infra_req & 0x1) << 3) | + ((vrf18_req & 0x1) << 4) | + ((ddr_en_req & 0x1) << 7) | + ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) | + ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) | + ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) | + ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) | + ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12)); + + /* SPM_SRC_MASK */ + mmio_write_32(SPM_SRC_MASK, + ((pwrctrl->reg_md_0_srcclkena_mask_b & 0x1) << 0) | + ((pwrctrl->reg_md_0_infra_req_mask_b & 0x1) << 1) | + ((pwrctrl->reg_md_0_apsrc_req_mask_b & 0x1) << 2) | + ((pwrctrl->reg_md_0_vrf18_req_mask_b & 0x1) << 3) | + ((pwrctrl->reg_md_0_ddren_req_mask_b & 0x1) << 4) | + ((pwrctrl->reg_md_1_srcclkena_mask_b & 0x1) << 5) | + ((pwrctrl->reg_md_1_infra_req_mask_b & 0x1) << 6) | + ((pwrctrl->reg_md_1_apsrc_req_mask_b & 0x1) << 7) | + ((pwrctrl->reg_md_1_vrf18_req_mask_b & 0x1) << 8) | + ((pwrctrl->reg_md_1_ddren_req_mask_b & 0x1) << 9) | + ((pwrctrl->reg_conn_srcclkena_mask_b & 0x1) << 10) | + ((pwrctrl->reg_conn_srcclkenb_mask_b & 0x1) << 11) | + ((pwrctrl->reg_conn_infra_req_mask_b & 0x1) << 12) | + ((pwrctrl->reg_conn_apsrc_req_mask_b & 0x1) << 13) | + ((pwrctrl->reg_conn_vrf18_req_mask_b & 0x1) << 14) | + ((pwrctrl->reg_conn_ddren_req_mask_b & 0x1) << 15) | + ((pwrctrl->reg_conn_vfe28_mask_b & 0x1) << 16) | + ((pwrctrl->reg_srcclkeni_srcclkena_mask_b & 0x7) << 17) | + ((pwrctrl->reg_srcclkeni_infra_req_mask_b & 0x7) << 20) | + ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_infrasys_ddren_req_mask_b & 0x1) << 26) | + ((reg_sspm_srcclkena_mask_b & 0x1) << 27) | + ((reg_sspm_infra_req_mask_b & 0x1) << 28) | + ((pwrctrl->reg_sspm_apsrc_req_mask_b & 0x1) << 29) | + ((pwrctrl->reg_sspm_vrf18_req_mask_b & 0x1) << 30) | + ((pwrctrl->reg_sspm_ddren_req_mask_b & 0x1) << 31)); +} + +void __spm_set_power_control(const struct pwr_ctrl *pwrctrl) +{ + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + mmio_write_32(SPM_AP_STANDBY_CON, + ((pwrctrl->reg_wfi_op & 0x1) << 0) | + ((pwrctrl->reg_wfi_type & 0x1) << 1) | + ((pwrctrl->reg_mp0_cputop_idle_mask & 0x1) << 2) | + ((pwrctrl->reg_mp1_cputop_idle_mask & 0x1) << 3) | + ((pwrctrl->reg_mcusys_idle_mask & 0x1) << 4) | + ((pwrctrl->reg_md_apsrc_1_sel & 0x1) << 25) | + ((pwrctrl->reg_md_apsrc_0_sel & 0x1) << 26) | + ((pwrctrl->reg_conn_apsrc_sel & 0x1) << 29)); + + /* SPM_SRC6_MASK */ + mmio_write_32(SPM_SRC6_MASK, + ((pwrctrl->reg_ccif_event_infra_req_mask_b & 0xffff) << 0) | + ((pwrctrl->reg_ccif_event_apsrc_req_mask_b & 0xffff) << 16)); + + /* SPM_SRC_REQ */ + mmio_write_32(SPM_SRC_REQ, + ((pwrctrl->reg_spm_apsrc_req & 0x1) << 0) | + ((pwrctrl->reg_spm_f26m_req & 0x1) << 1) | + ((pwrctrl->reg_spm_infra_req & 0x1) << 3) | + ((pwrctrl->reg_spm_vrf18_req & 0x1) << 4) | + ((pwrctrl->reg_spm_ddren_req & 0x1) << 7) | + ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) | + ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) | + ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) | + ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) | + ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12)); + + /* SPM_SRC_MASK */ + mmio_write_32(SPM_SRC_MASK, + ((pwrctrl->reg_md_0_srcclkena_mask_b & 0x1) << 0) | + ((pwrctrl->reg_md_0_infra_req_mask_b & 0x1) << 1) | + ((pwrctrl->reg_md_0_apsrc_req_mask_b & 0x1) << 2) | + ((pwrctrl->reg_md_0_vrf18_req_mask_b & 0x1) << 3) | + ((pwrctrl->reg_md_0_ddren_req_mask_b & 0x1) << 4) | + ((pwrctrl->reg_md_1_srcclkena_mask_b & 0x1) << 5) | + ((pwrctrl->reg_md_1_infra_req_mask_b & 0x1) << 6) | + ((pwrctrl->reg_md_1_apsrc_req_mask_b & 0x1) << 7) | + ((pwrctrl->reg_md_1_vrf18_req_mask_b & 0x1) << 8) | + ((pwrctrl->reg_md_1_ddren_req_mask_b & 0x1) << 9) | + ((pwrctrl->reg_conn_srcclkena_mask_b & 0x1) << 10) | + ((pwrctrl->reg_conn_srcclkenb_mask_b & 0x1) << 11) | + ((pwrctrl->reg_conn_infra_req_mask_b & 0x1) << 12) | + ((pwrctrl->reg_conn_apsrc_req_mask_b & 0x1) << 13) | + ((pwrctrl->reg_conn_vrf18_req_mask_b & 0x1) << 14) | + ((pwrctrl->reg_conn_ddren_req_mask_b & 0x1) << 15) | + ((pwrctrl->reg_conn_vfe28_mask_b & 0x1) << 16) | + ((pwrctrl->reg_srcclkeni_srcclkena_mask_b & 0x7) << 17) | + ((pwrctrl->reg_srcclkeni_infra_req_mask_b & 0x7) << 20) | + ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_infrasys_ddren_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_sspm_srcclkena_mask_b & 0x1) << 27) | + ((pwrctrl->reg_sspm_infra_req_mask_b & 0x1) << 28) | + ((pwrctrl->reg_sspm_apsrc_req_mask_b & 0x1) << 29) | + ((pwrctrl->reg_sspm_vrf18_req_mask_b & 0x1) << 30) | + ((pwrctrl->reg_sspm_ddren_req_mask_b & 0x1) << 31)); + + /* SPM_SRC2_MASK */ + mmio_write_32(SPM_SRC2_MASK, + ((pwrctrl->reg_scp_srcclkena_mask_b & 0x1) << 0) | + ((pwrctrl->reg_scp_infra_req_mask_b & 0x1) << 1) | + ((pwrctrl->reg_scp_apsrc_req_mask_b & 0x1) << 2) | + ((pwrctrl->reg_scp_vrf18_req_mask_b & 0x1) << 3) | + ((pwrctrl->reg_scp_ddren_req_mask_b & 0x1) << 4) | + ((pwrctrl->reg_audio_dsp_srcclkena_mask_b & 0x1) << 5) | + ((pwrctrl->reg_audio_dsp_infra_req_mask_b & 0x1) << 6) | + ((pwrctrl->reg_audio_dsp_apsrc_req_mask_b & 0x1) << 7) | + ((pwrctrl->reg_audio_dsp_vrf18_req_mask_b & 0x1) << 8) | + ((pwrctrl->reg_audio_dsp_ddren_req_mask_b & 0x1) << 9) | + ((pwrctrl->reg_ufs_srcclkena_mask_b & 0x1) << 10) | + ((pwrctrl->reg_ufs_infra_req_mask_b & 0x1) << 11) | + ((pwrctrl->reg_ufs_apsrc_req_mask_b & 0x1) << 12) | + ((pwrctrl->reg_ufs_vrf18_req_mask_b & 0x1) << 13) | + ((pwrctrl->reg_ufs_ddren_req_mask_b & 0x1) << 14) | + ((pwrctrl->reg_disp0_apsrc_req_mask_b & 0x1) << 15) | + ((pwrctrl->reg_disp0_ddren_req_mask_b & 0x1) << 16) | + ((pwrctrl->reg_disp1_apsrc_req_mask_b & 0x1) << 17) | + ((pwrctrl->reg_disp1_ddren_req_mask_b & 0x1) << 18) | + ((pwrctrl->reg_gce_infra_req_mask_b & 0x1) << 19) | + ((pwrctrl->reg_gce_apsrc_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_gce_vrf18_req_mask_b & 0x1) << 21) | + ((pwrctrl->reg_gce_ddren_req_mask_b & 0x1) << 22) | + ((pwrctrl->reg_apu_srcclkena_mask_b & 0x1) << 23) | + ((pwrctrl->reg_apu_infra_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_apu_apsrc_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_apu_vrf18_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_apu_ddren_req_mask_b & 0x1) << 27) | + ((pwrctrl->reg_cg_check_srcclkena_mask_b & 0x1) << 28) | + ((pwrctrl->reg_cg_check_apsrc_req_mask_b & 0x1) << 29) | + ((pwrctrl->reg_cg_check_vrf18_req_mask_b & 0x1) << 30) | + ((pwrctrl->reg_cg_check_ddren_req_mask_b & 0x1) << 31)); + + /* SPM_SRC3_MASK */ + mmio_write_32(SPM_SRC3_MASK, + ((pwrctrl->reg_dvfsrc_event_trigger_mask_b & 0x1) << 0) | + ((pwrctrl->reg_sw2spm_wakeup_mask_b & 0xf) << 1) | + ((pwrctrl->reg_adsp2spm_wakeup_mask_b & 0x1) << 5) | + ((pwrctrl->reg_sspm2spm_wakeup_mask_b & 0xf) << 6) | + ((pwrctrl->reg_scp2spm_wakeup_mask_b & 0x1) << 10) | + ((pwrctrl->reg_csyspwrup_ack_mask & 0x1) << 11) | + ((pwrctrl->reg_spm_reserved_srcclkena_mask_b & 0x1) << 12) | + ((pwrctrl->reg_spm_reserved_infra_req_mask_b & 0x1) << 13) | + ((pwrctrl->reg_spm_reserved_apsrc_req_mask_b & 0x1) << 14) | + ((pwrctrl->reg_spm_reserved_vrf18_req_mask_b & 0x1) << 15) | + ((pwrctrl->reg_spm_reserved_ddren_req_mask_b & 0x1) << 16) | + ((pwrctrl->reg_mcupm_srcclkena_mask_b & 0x1) << 17) | + ((pwrctrl->reg_mcupm_infra_req_mask_b & 0x1) << 18) | + ((pwrctrl->reg_mcupm_apsrc_req_mask_b & 0x1) << 19) | + ((pwrctrl->reg_mcupm_vrf18_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_mcupm_ddren_req_mask_b & 0x1) << 21) | + ((pwrctrl->reg_msdc0_srcclkena_mask_b & 0x1) << 22) | + ((pwrctrl->reg_msdc0_infra_req_mask_b & 0x1) << 23) | + ((pwrctrl->reg_msdc0_apsrc_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_msdc0_vrf18_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_msdc0_ddren_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_msdc1_srcclkena_mask_b & 0x1) << 27) | + ((pwrctrl->reg_msdc1_infra_req_mask_b & 0x1) << 28) | + ((pwrctrl->reg_msdc1_apsrc_req_mask_b & 0x1) << 29) | + ((pwrctrl->reg_msdc1_vrf18_req_mask_b & 0x1) << 30) | + ((pwrctrl->reg_msdc1_ddren_req_mask_b & 0x1) << 31)); + + /* SPM_SRC4_MASK */ + mmio_write_32(SPM_SRC4_MASK, + ((pwrctrl->reg_ccif_event_srcclkena_mask_b & 0xffff) << 0) | + ((pwrctrl->reg_bak_psri_srcclkena_mask_b & 0x1) << 16) | + ((pwrctrl->reg_bak_psri_infra_req_mask_b & 0x1) << 17) | + ((pwrctrl->reg_bak_psri_apsrc_req_mask_b & 0x1) << 18) | + ((pwrctrl->reg_bak_psri_vrf18_req_mask_b & 0x1) << 19) | + ((pwrctrl->reg_bak_psri_ddren_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_dramc_md32_infra_req_mask_b & 0x3) << 21) | + ((pwrctrl->reg_dramc_md32_vrf18_req_mask_b & 0x3) << 23) | + ((pwrctrl->reg_conn_srcclkenb2pwrap_mask_b & 0x1) << 25) | + ((pwrctrl->reg_dramc_md32_apsrc_req_mask_b & 0x3) << 26)); + + /* SPM_SRC5_MASK */ + mmio_write_32(SPM_SRC5_MASK, + ((pwrctrl->reg_mcusys_merge_apsrc_req_mask_b & 0x1ff) << 0) | + ((pwrctrl->reg_mcusys_merge_ddren_req_mask_b & 0x1ff) << 9) | + ((pwrctrl->reg_afe_srcclkena_mask_b & 0x1) << 18) | + ((pwrctrl->reg_afe_infra_req_mask_b & 0x1) << 19) | + ((pwrctrl->reg_afe_apsrc_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_afe_vrf18_req_mask_b & 0x1) << 21) | + ((pwrctrl->reg_afe_ddren_req_mask_b & 0x1) << 22) | + ((pwrctrl->reg_msdc2_srcclkena_mask_b & 0x1) << 23) | + ((pwrctrl->reg_msdc2_infra_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_msdc2_apsrc_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_msdc2_vrf18_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_msdc2_ddren_req_mask_b & 0x1) << 27)); + + /* SPM_WAKEUP_EVENT_MASK */ + mmio_write_32(SPM_WAKEUP_EVENT_MASK, + ((pwrctrl->reg_wakeup_event_mask & 0xffffffff) << 0)); + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK, + ((pwrctrl->reg_ext_wakeup_event_mask & 0xffffffff) << 0)); + + /* SPM_SRC7_MASK */ + mmio_write_32(SPM_SRC7_MASK, + ((pwrctrl->reg_pcie_srcclkena_mask_b & 0x1) << 0) | + ((pwrctrl->reg_pcie_infra_req_mask_b & 0x1) << 1) | + ((pwrctrl->reg_pcie_apsrc_req_mask_b & 0x1) << 2) | + ((pwrctrl->reg_pcie_vrf18_req_mask_b & 0x1) << 3) | + ((pwrctrl->reg_pcie_ddren_req_mask_b & 0x1) << 4) | + ((pwrctrl->reg_dpmaif_srcclkena_mask_b & 0x1) << 5) | + ((pwrctrl->reg_dpmaif_infra_req_mask_b & 0x1) << 6) | + ((pwrctrl->reg_dpmaif_apsrc_req_mask_b & 0x1) << 7) | + ((pwrctrl->reg_dpmaif_vrf18_req_mask_b & 0x1) << 8) | + ((pwrctrl->reg_dpmaif_ddren_req_mask_b & 0x1) << 9)); + /* Auto-gen End */ +} + +void __spm_disable_pcm_timer(void) +{ + mmio_clrsetbits_32(PCM_CON1, RG_PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY); +} + + +void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl) +{ + uint32_t val, mask; + + /* toggle event counter clear */ + mmio_setbits_32(PCM_CON1, + SPM_REGWR_CFG_KEY | REG_SPM_EVENT_COUNTER_CLR_LSB); + + /* toggle for reset SYS TIMER start point */ + mmio_setbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB); + + if (pwrctrl->timer_val_cust == 0U) { + val = pwrctrl->timer_val ? (pwrctrl->timer_val) : (PCM_TIMER_MAX); + } else { + val = pwrctrl->timer_val_cust; + } + + mmio_write_32(PCM_TIMER_VAL, val); + mmio_setbits_32(PCM_CON1, (SPM_REGWR_CFG_KEY | RG_PCM_TIMER_EN_LSB)); + + /* unmask AP wakeup source */ + if (pwrctrl->wake_src_cust == 0U) { + mask = pwrctrl->wake_src; + } else { + mask = pwrctrl->wake_src_cust; + } + + if (pwrctrl->reg_csyspwrup_ack_mask != 0U) { + mask &= ~R12_CSYSPWREQ_B; + } + + mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask); + + /* unmask SPM ISR (keep TWAM setting) */ + mmio_setbits_32(SPM_IRQ_MASK, ISRM_RET_IRQ_AUX); + + /* toggle event counter clear */ + mmio_clrsetbits_32(PCM_CON1, REG_SPM_EVENT_COUNTER_CLR_LSB, + SPM_REGWR_CFG_KEY); + /* toggle for reset SYS TIMER start point */ + mmio_clrbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB); +} + +void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl) +{ + /* set PCM flags and data */ + if (pwrctrl->pcm_flags_cust_clr != 0U) { + pwrctrl->pcm_flags &= ~pwrctrl->pcm_flags_cust_clr; + } + + if (pwrctrl->pcm_flags_cust_set != 0U) { + pwrctrl->pcm_flags |= pwrctrl->pcm_flags_cust_set; + } + + if (pwrctrl->pcm_flags1_cust_clr != 0U) { + pwrctrl->pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr; + } + + if (pwrctrl->pcm_flags1_cust_set != 0U) { + pwrctrl->pcm_flags1 |= pwrctrl->pcm_flags1_cust_set; + } + + mmio_write_32(SPM_SW_FLAG_0, pwrctrl->pcm_flags); + + mmio_write_32(SPM_SW_FLAG_1, pwrctrl->pcm_flags1); + + mmio_write_32(SPM_SW_RSV_7, pwrctrl->pcm_flags); + + mmio_write_32(SPM_SW_RSV_8, pwrctrl->pcm_flags1); +} + +void __spm_get_wakeup_status(struct wake_status *wakesta, + unsigned int ext_status) +{ + wakesta->tr.comm.r12 = mmio_read_32(SPM_BK_WAKE_EVENT); + wakesta->tr.comm.timer_out = mmio_read_32(SPM_BK_PCM_TIMER); + wakesta->tr.comm.r13 = mmio_read_32(PCM_REG13_DATA); + wakesta->tr.comm.req_sta0 = mmio_read_32(SRC_REQ_STA_0); + wakesta->tr.comm.req_sta1 = mmio_read_32(SRC_REQ_STA_1); + wakesta->tr.comm.req_sta2 = mmio_read_32(SRC_REQ_STA_2); + wakesta->tr.comm.req_sta3 = mmio_read_32(SRC_REQ_STA_3); + wakesta->tr.comm.req_sta4 = mmio_read_32(SRC_REQ_STA_4); + + wakesta->tr.comm.debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0); + wakesta->tr.comm.debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1); + + if ((ext_status & SPM_INTERNAL_STATUS_HW_S1) != 0U) { + wakesta->tr.comm.debug_flag |= (SPM_DBG_DEBUG_IDX_DDREN_WAKE | + SPM_DBG_DEBUG_IDX_DDREN_SLEEP); + mmio_write_32(PCM_WDT_LATCH_SPARE_0, wakesta->tr.comm.debug_flag); + } + + wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); + wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); + + /* record below spm info for debug */ + wakesta->r12 = mmio_read_32(SPM_BK_WAKE_EVENT); + wakesta->r12_ext = mmio_read_32(SPM_WAKEUP_STA); + wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA); + wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA); + wakesta->md32pcm_wakeup_sta = mmio_read_32(MD32PCM_WAKEUP_STA); + wakesta->md32pcm_event_sta = mmio_read_32(MD32PCM_EVENT_STA); + wakesta->src_req = mmio_read_32(SPM_SRC_REQ); + + /* backup of SPM_WAKEUP_MISC */ + wakesta->wake_misc = mmio_read_32(SPM_BK_WAKE_MISC); + + /* get sleep time, backup of PCM_TIMER_OUT */ + wakesta->timer_out = mmio_read_32(SPM_BK_PCM_TIMER); + + /* get other SYS and co-clock status */ + wakesta->r13 = mmio_read_32(PCM_REG13_DATA); + wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA); + wakesta->req_sta0 = mmio_read_32(SRC_REQ_STA_0); + wakesta->req_sta1 = mmio_read_32(SRC_REQ_STA_1); + wakesta->req_sta2 = mmio_read_32(SRC_REQ_STA_2); + wakesta->req_sta3 = mmio_read_32(SRC_REQ_STA_3); + wakesta->req_sta4 = mmio_read_32(SRC_REQ_STA_4); + + /* get HW CG check status */ + wakesta->cg_check_sta = mmio_read_32(SPM_CG_CHECK_STA); + + /* get debug flag for PCM execution check */ + wakesta->debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0); + wakesta->debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1); + + /* get backup SW flag status */ + wakesta->b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); + wakesta->b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); + + wakesta->rt_req_sta0 = mmio_read_32(SPM_SW_RSV_2); + wakesta->rt_req_sta1 = mmio_read_32(SPM_SW_RSV_3); + wakesta->rt_req_sta2 = mmio_read_32(SPM_SW_RSV_4); + wakesta->rt_req_sta3 = mmio_read_32(SPM_SW_RSV_5); + wakesta->rt_req_sta4 = mmio_read_32(SPM_SW_RSV_6); + + /* get ISR status */ + wakesta->isr = mmio_read_32(SPM_IRQ_STA); + + /* get SW flag status */ + wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0); + wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1); + + /* get CLK SETTLE */ + wakesta->clk_settle = mmio_read_32(SPM_CLK_SETTLE); + + /* check abort */ + wakesta->abort = ((wakesta->debug_flag & DEBUG_ABORT_MASK) | + (wakesta->debug_flag1 & DEBUG_ABORT_MASK_1)); +} + +void __spm_clean_after_wakeup(void) +{ + mmio_write_32(SPM_BK_WAKE_EVENT, + (mmio_read_32(SPM_WAKEUP_STA) | + mmio_read_32(SPM_BK_WAKE_EVENT))); + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0U); + + /* + * clean wakeup event raw status (for edge trigger event) + * bit[28] for cpu wake up event + */ + mmio_write_32(SPM_WAKEUP_EVENT_MASK, SPM_WAKEUP_EVENT_MASK_CLEAN_MASK); + + /* clean ISR status (except TWAM) */ + mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM); + mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM); + mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL); +} + +void __spm_set_pcm_wdt(int en) +{ + mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_EN_LSB, + SPM_REGWR_CFG_KEY); + + if (en == 1) { + mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_WAKE_LSB, + SPM_REGWR_CFG_KEY); + + if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) { + mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX); + } + + mmio_write_32(PCM_WDT_VAL, + mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT); + mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | RG_PCM_WDT_EN_LSB); + } +} + +void __spm_send_cpu_wakeup_event(void) +{ + /* SPM will clear SPM_CPU_WAKEUP_EVENT */ + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1); +} + +void __spm_ext_int_wakeup_req_clr(void) +{ + unsigned int reg = mmio_read_32(SPM_MD32_IRQ) & (~(0x1U << 0)); + + mmio_write_32(EXT_INT_WAKEUP_REQ_CLR, mmio_read_32(ROOT_CPUTOP_ADDR)); + + /* Clear spm2mcupm wakeup interrupt status */ + mmio_write_32(SPM_MD32_IRQ, reg); +} + +void __spm_xo_soc_bblpm(int en) +{ + if (en == 1) { + mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG, + RC_SW_SRCCLKEN_FPM, RC_SW_SRCCLKEN_RC); + assert(mt_spm_bblpm_cnt == 0); + mt_spm_bblpm_cnt += 1; + } else { + mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG, + RC_SW_SRCCLKEN_RC, RC_SW_SRCCLKEN_FPM); + mt_spm_bblpm_cnt -= 1; + } +} + +void __spm_hw_s1_state_monitor(int en, unsigned int *status) +{ + unsigned int reg = mmio_read_32(SPM_ACK_CHK_CON_3); + + if (en == 1) { + reg = mmio_read_32(SPM_ACK_CHK_CON_3); + reg &= ~SPM_ACK_CHK_3_CON_CLR_ALL; + mmio_write_32(SPM_ACK_CHK_CON_3, reg); + reg |= SPM_ACK_CHK_3_CON_EN; + mmio_write_32(SPM_ACK_CHK_CON_3, reg); + } else { + if (((reg & SPM_ACK_CHK_3_CON_RESULT) != 0U) && + (status != NULL)) { + *status |= SPM_INTERNAL_STATUS_HW_S1; + } + + mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_EN, + SPM_ACK_CHK_3_CON_HW_MODE_TRIG | + SPM_ACK_CHK_3_CON_CLR_ALL); + } +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h new file mode 100644 index 0000000..8cf2062 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_INTERNAL +#define MT_SPM_INTERNAL + +#include "mt_spm.h" + +/* Config and Parameter */ +#define POWER_ON_VAL0_DEF (0x0000F100) +#define POWER_ON_VAL1_DEF (0x80015860) +#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */ +#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT) + +/* Define and Declare */ +/* PCM_PWR_IO_EN */ +#define PCM_PWRIO_EN_R0 BIT(0) +#define PCM_PWRIO_EN_R7 BIT(7) +#define PCM_RF_SYNC_R0 BIT(16) +#define PCM_RF_SYNC_R6 BIT(22) +#define PCM_RF_SYNC_R7 BIT(23) + +/* SPM_SWINT */ +#define PCM_SW_INT0 BIT(0) +#define PCM_SW_INT1 BIT(1) +#define PCM_SW_INT2 BIT(2) +#define PCM_SW_INT3 BIT(3) +#define PCM_SW_INT4 BIT(4) +#define PCM_SW_INT5 BIT(5) +#define PCM_SW_INT6 BIT(6) +#define PCM_SW_INT7 BIT(7) +#define PCM_SW_INT8 BIT(8) +#define PCM_SW_INT9 BIT(9) +#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \ + PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \ + PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \ + PCM_SW_INT0) + +/* SPM_AP_STANDBY_CON */ +#define WFI_OP_AND (1U) +#define WFI_OP_OR (0U) + +/* SPM_IRQ_MASK */ +#define ISRM_TWAM (1U << 2) +#define ISRM_PCM_RETURN (1U << 3) +#define ISRM_RET_IRQ0 (1U << 8) +#define ISRM_RET_IRQ1 (1U << 9) +#define ISRM_RET_IRQ2 (1U << 10) +#define ISRM_RET_IRQ3 (1U << 11) +#define ISRM_RET_IRQ4 (1U << 12) +#define ISRM_RET_IRQ5 (1U << 13) +#define ISRM_RET_IRQ6 (1U << 14) +#define ISRM_RET_IRQ7 (1U << 15) +#define ISRM_RET_IRQ8 (1U << 16) +#define ISRM_RET_IRQ9 (1U << 17) +#define ISRM_RET_IRQ_AUX ((ISRM_RET_IRQ9) | (ISRM_RET_IRQ8) | \ + (ISRM_RET_IRQ7) | (ISRM_RET_IRQ6) | \ + (ISRM_RET_IRQ5) | (ISRM_RET_IRQ4) | \ + (ISRM_RET_IRQ3) | (ISRM_RET_IRQ2) | \ + (ISRM_RET_IRQ1)) +#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX) +#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM) + +/* SPM_IRQ_STA */ +#define ISRS_TWAM BIT(2) +#define ISRS_PCM_RETURN BIT(3) +#define ISRC_TWAM ISRS_TWAM +#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN +#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM) + +/* SPM_WAKEUP_MISC */ +#define WAKE_MISC_GIC_WAKEUP (0x3FF) +#define WAKE_MISC_DVFSRC_IRQ DVFSRC_IRQ_LSB +#define WAKE_MISC_REG_CPU_WAKEUP SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB +#define WAKE_MISC_PCM_TIMER_EVENT PCM_TIMER_EVENT_LSB +#define WAKE_MISC_PMIC_OUT_B ((1U << 19) | (1U << 20)) +#define WAKE_MISC_TWAM_IRQ_B TWAM_IRQ_B_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_0 SPM_ACK_CHK_WAKEUP_0_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_1 SPM_ACK_CHK_WAKEUP_1_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_2 SPM_ACK_CHK_WAKEUP_2_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_3 SPM_ACK_CHK_WAKEUP_3_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_ALL SPM_ACK_CHK_WAKEUP_ALL_LSB +#define WAKE_MISC_PMIC_IRQ_ACK PMIC_IRQ_ACK_LSB +#define WAKE_MISC_PMIC_SCP_IRQ PMIC_SCP_IRQ_LSB + +/* ABORT MASK for DEBUG FOORTPRINT */ +#define DEBUG_ABORT_MASK \ + (SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC | \ + SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN) + +#define DEBUG_ABORT_MASK_1 \ + (SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT | \ + SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT | \ + SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT) + +#define MCUPM_MBOX_WAKEUP_CPU (0x0C55FD10) + +struct pwr_ctrl { + uint32_t pcm_flags; + uint32_t pcm_flags_cust; + uint32_t pcm_flags_cust_set; + uint32_t pcm_flags_cust_clr; + uint32_t pcm_flags1; + uint32_t pcm_flags1_cust; + uint32_t pcm_flags1_cust_set; + uint32_t pcm_flags1_cust_clr; + uint32_t timer_val; + uint32_t timer_val_cust; + uint32_t timer_val_ramp_en; + uint32_t timer_val_ramp_en_sec; + uint32_t wake_src; + uint32_t wake_src_cust; + uint32_t wakelock_timer_val; + uint8_t wdt_disable; + + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + uint8_t reg_wfi_op; + uint8_t reg_wfi_type; + uint8_t reg_mp0_cputop_idle_mask; + uint8_t reg_mp1_cputop_idle_mask; + uint8_t reg_mcusys_idle_mask; + uint8_t reg_md_apsrc_1_sel; + uint8_t reg_md_apsrc_0_sel; + uint8_t reg_conn_apsrc_sel; + + /* SPM_SRC6_MASK */ + uint32_t reg_ccif_event_infra_req_mask_b; + uint32_t reg_ccif_event_apsrc_req_mask_b; + + /* SPM_SRC_REQ */ + uint8_t reg_spm_apsrc_req; + uint8_t reg_spm_f26m_req; + uint8_t reg_spm_infra_req; + uint8_t reg_spm_vrf18_req; + uint8_t reg_spm_ddren_req; + uint8_t reg_spm_dvfs_req; + uint8_t reg_spm_sw_mailbox_req; + uint8_t reg_spm_sspm_mailbox_req; + uint8_t reg_spm_adsp_mailbox_req; + uint8_t reg_spm_scp_mailbox_req; + + /* SPM_SRC_MASK */ + uint8_t reg_md_0_srcclkena_mask_b; + uint8_t reg_md_0_infra_req_mask_b; + uint8_t reg_md_0_apsrc_req_mask_b; + uint8_t reg_md_0_vrf18_req_mask_b; + uint8_t reg_md_0_ddren_req_mask_b; + uint8_t reg_md_1_srcclkena_mask_b; + uint8_t reg_md_1_infra_req_mask_b; + uint8_t reg_md_1_apsrc_req_mask_b; + uint8_t reg_md_1_vrf18_req_mask_b; + uint8_t reg_md_1_ddren_req_mask_b; + uint8_t reg_conn_srcclkena_mask_b; + uint8_t reg_conn_srcclkenb_mask_b; + uint8_t reg_conn_infra_req_mask_b; + uint8_t reg_conn_apsrc_req_mask_b; + uint8_t reg_conn_vrf18_req_mask_b; + uint8_t reg_conn_ddren_req_mask_b; + uint8_t reg_conn_vfe28_mask_b; + uint8_t reg_srcclkeni_srcclkena_mask_b; + uint8_t reg_srcclkeni_infra_req_mask_b; + uint8_t reg_infrasys_apsrc_req_mask_b; + uint8_t reg_infrasys_ddren_req_mask_b; + uint8_t reg_sspm_srcclkena_mask_b; + uint8_t reg_sspm_infra_req_mask_b; + uint8_t reg_sspm_apsrc_req_mask_b; + uint8_t reg_sspm_vrf18_req_mask_b; + uint8_t reg_sspm_ddren_req_mask_b; + + /* SPM_SRC2_MASK */ + uint8_t reg_scp_srcclkena_mask_b; + uint8_t reg_scp_infra_req_mask_b; + uint8_t reg_scp_apsrc_req_mask_b; + uint8_t reg_scp_vrf18_req_mask_b; + uint8_t reg_scp_ddren_req_mask_b; + uint8_t reg_audio_dsp_srcclkena_mask_b; + uint8_t reg_audio_dsp_infra_req_mask_b; + uint8_t reg_audio_dsp_apsrc_req_mask_b; + uint8_t reg_audio_dsp_vrf18_req_mask_b; + uint8_t reg_audio_dsp_ddren_req_mask_b; + uint8_t reg_ufs_srcclkena_mask_b; + uint8_t reg_ufs_infra_req_mask_b; + uint8_t reg_ufs_apsrc_req_mask_b; + uint8_t reg_ufs_vrf18_req_mask_b; + uint8_t reg_ufs_ddren_req_mask_b; + uint8_t reg_disp0_apsrc_req_mask_b; + uint8_t reg_disp0_ddren_req_mask_b; + uint8_t reg_disp1_apsrc_req_mask_b; + uint8_t reg_disp1_ddren_req_mask_b; + uint8_t reg_gce_infra_req_mask_b; + uint8_t reg_gce_apsrc_req_mask_b; + uint8_t reg_gce_vrf18_req_mask_b; + uint8_t reg_gce_ddren_req_mask_b; + uint8_t reg_apu_srcclkena_mask_b; + uint8_t reg_apu_infra_req_mask_b; + uint8_t reg_apu_apsrc_req_mask_b; + uint8_t reg_apu_vrf18_req_mask_b; + uint8_t reg_apu_ddren_req_mask_b; + uint8_t reg_cg_check_srcclkena_mask_b; + uint8_t reg_cg_check_apsrc_req_mask_b; + uint8_t reg_cg_check_vrf18_req_mask_b; + uint8_t reg_cg_check_ddren_req_mask_b; + + /* SPM_SRC3_MASK */ + uint8_t reg_dvfsrc_event_trigger_mask_b; + uint8_t reg_sw2spm_wakeup_mask_b; + uint8_t reg_adsp2spm_wakeup_mask_b; + uint8_t reg_sspm2spm_wakeup_mask_b; + uint8_t reg_scp2spm_wakeup_mask_b; + uint8_t reg_csyspwrup_ack_mask; + uint8_t reg_spm_reserved_srcclkena_mask_b; + uint8_t reg_spm_reserved_infra_req_mask_b; + uint8_t reg_spm_reserved_apsrc_req_mask_b; + uint8_t reg_spm_reserved_vrf18_req_mask_b; + uint8_t reg_spm_reserved_ddren_req_mask_b; + uint8_t reg_mcupm_srcclkena_mask_b; + uint8_t reg_mcupm_infra_req_mask_b; + uint8_t reg_mcupm_apsrc_req_mask_b; + uint8_t reg_mcupm_vrf18_req_mask_b; + uint8_t reg_mcupm_ddren_req_mask_b; + uint8_t reg_msdc0_srcclkena_mask_b; + uint8_t reg_msdc0_infra_req_mask_b; + uint8_t reg_msdc0_apsrc_req_mask_b; + uint8_t reg_msdc0_vrf18_req_mask_b; + uint8_t reg_msdc0_ddren_req_mask_b; + uint8_t reg_msdc1_srcclkena_mask_b; + uint8_t reg_msdc1_infra_req_mask_b; + uint8_t reg_msdc1_apsrc_req_mask_b; + uint8_t reg_msdc1_vrf18_req_mask_b; + uint8_t reg_msdc1_ddren_req_mask_b; + + /* SPM_SRC4_MASK */ + uint32_t reg_ccif_event_srcclkena_mask_b; + uint8_t reg_bak_psri_srcclkena_mask_b; + uint8_t reg_bak_psri_infra_req_mask_b; + uint8_t reg_bak_psri_apsrc_req_mask_b; + uint8_t reg_bak_psri_vrf18_req_mask_b; + uint8_t reg_bak_psri_ddren_req_mask_b; + uint8_t reg_dramc_md32_infra_req_mask_b; + uint8_t reg_dramc_md32_vrf18_req_mask_b; + uint8_t reg_conn_srcclkenb2pwrap_mask_b; + uint8_t reg_dramc_md32_apsrc_req_mask_b; + + /* SPM_SRC5_MASK */ + uint32_t reg_mcusys_merge_apsrc_req_mask_b; + uint32_t reg_mcusys_merge_ddren_req_mask_b; + uint8_t reg_afe_srcclkena_mask_b; + uint8_t reg_afe_infra_req_mask_b; + uint8_t reg_afe_apsrc_req_mask_b; + uint8_t reg_afe_vrf18_req_mask_b; + uint8_t reg_afe_ddren_req_mask_b; + uint8_t reg_msdc2_srcclkena_mask_b; + uint8_t reg_msdc2_infra_req_mask_b; + uint8_t reg_msdc2_apsrc_req_mask_b; + uint8_t reg_msdc2_vrf18_req_mask_b; + uint8_t reg_msdc2_ddren_req_mask_b; + + /* SPM_WAKEUP_EVENT_MASK */ + uint32_t reg_wakeup_event_mask; + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + uint32_t reg_ext_wakeup_event_mask; + + /* SPM_SRC7_MASK */ + uint8_t reg_pcie_srcclkena_mask_b; + uint8_t reg_pcie_infra_req_mask_b; + uint8_t reg_pcie_apsrc_req_mask_b; + uint8_t reg_pcie_vrf18_req_mask_b; + uint8_t reg_pcie_ddren_req_mask_b; + uint8_t reg_dpmaif_srcclkena_mask_b; + uint8_t reg_dpmaif_infra_req_mask_b; + uint8_t reg_dpmaif_apsrc_req_mask_b; + uint8_t reg_dpmaif_vrf18_req_mask_b; + uint8_t reg_dpmaif_ddren_req_mask_b; + + /* Auto-gen End */ +}; + +/* code gen by spm_pwr_ctrl_atf.pl, need struct pwr_ctrl */ +enum pwr_ctrl_enum { + PW_PCM_FLAGS, + PW_PCM_FLAGS_CUST, + PW_PCM_FLAGS_CUST_SET, + PW_PCM_FLAGS_CUST_CLR, + PW_PCM_FLAGS1, + PW_PCM_FLAGS1_CUST, + PW_PCM_FLAGS1_CUST_SET, + PW_PCM_FLAGS1_CUST_CLR, + PW_TIMER_VAL, + PW_TIMER_VAL_CUST, + PW_TIMER_VAL_RAMP_EN, + PW_TIMER_VAL_RAMP_EN_SEC, + PW_WAKE_SRC, + PW_WAKE_SRC_CUST, + PW_WAKELOCK_TIMER_VAL, + PW_WDT_DISABLE, + + /* SPM_AP_STANDBY_CON */ + PW_REG_WFI_OP, + PW_REG_WFI_TYPE, + PW_REG_MP0_CPUTOP_IDLE_MASK, + PW_REG_MP1_CPUTOP_IDLE_MASK, + PW_REG_MCUSYS_IDLE_MASK, + PW_REG_MD_APSRC_1_SEL, + PW_REG_MD_APSRC_0_SEL, + PW_REG_CONN_APSRC_SEL, + + /* SPM_SRC6_MASK */ + PW_REG_CCIF_EVENT_INFRA_REQ_MASK_B, + PW_REG_CCIF_EVENT_APSRC_REQ_MASK_B, + + /* SPM_WAKEUP_EVENT_SENS */ + PW_REG_WAKEUP_EVENT_SENS, + + /* SPM_SRC_REQ */ + PW_REG_SPM_APSRC_REQ, + PW_REG_SPM_F26M_REQ, + PW_REG_SPM_INFRA_REQ, + PW_REG_SPM_VRF18_REQ, + PW_REG_SPM_DDREN_REQ, + PW_REG_SPM_DVFS_REQ, + PW_REG_SPM_SW_MAILBOX_REQ, + PW_REG_SPM_SSPM_MAILBOX_REQ, + PW_REG_SPM_ADSP_MAILBOX_REQ, + PW_REG_SPM_SCP_MAILBOX_REQ, + + /* SPM_SRC_MASK */ + PW_REG_MD_0_SRCCLKENA_MASK_B, + PW_REG_MD_0_INFRA_REQ_MASK_B, + PW_REG_MD_0_APSRC_REQ_MASK_B, + PW_REG_MD_0_VRF18_REQ_MASK_B, + PW_REG_MD_0_DDREN_REQ_MASK_B, + PW_REG_MD_1_SRCCLKENA_MASK_B, + PW_REG_MD_1_INFRA_REQ_MASK_B, + PW_REG_MD_1_APSRC_REQ_MASK_B, + PW_REG_MD_1_VRF18_REQ_MASK_B, + PW_REG_MD_1_DDREN_REQ_MASK_B, + PW_REG_CONN_SRCCLKENA_MASK_B, + PW_REG_CONN_SRCCLKENB_MASK_B, + PW_REG_CONN_INFRA_REQ_MASK_B, + PW_REG_CONN_APSRC_REQ_MASK_B, + PW_REG_CONN_VRF18_REQ_MASK_B, + PW_REG_CONN_DDREN_REQ_MASK_B, + PW_REG_CONN_VFE28_MASK_B, + PW_REG_SRCCLKENI_SRCCLKENA_MASK_B, + PW_REG_SRCCLKENI_INFRA_REQ_MASK_B, + PW_REG_INFRASYS_APSRC_REQ_MASK_B, + PW_REG_INFRASYS_DDREN_REQ_MASK_B, + PW_REG_SSPM_SRCCLKENA_MASK_B, + PW_REG_SSPM_INFRA_REQ_MASK_B, + PW_REG_SSPM_APSRC_REQ_MASK_B, + PW_REG_SSPM_VRF18_REQ_MASK_B, + PW_REG_SSPM_DDREN_REQ_MASK_B, + + /* SPM_SRC2_MASK */ + PW_REG_SCP_SRCCLKENA_MASK_B, + PW_REG_SCP_INFRA_REQ_MASK_B, + PW_REG_SCP_APSRC_REQ_MASK_B, + PW_REG_SCP_VRF18_REQ_MASK_B, + PW_REG_SCP_DDREN_REQ_MASK_B, + PW_REG_AUDIO_DSP_SRCCLKENA_MASK_B, + PW_REG_AUDIO_DSP_INFRA_REQ_MASK_B, + PW_REG_AUDIO_DSP_APSRC_REQ_MASK_B, + PW_REG_AUDIO_DSP_VRF18_REQ_MASK_B, + PW_REG_AUDIO_DSP_DDREN_REQ_MASK_B, + PW_REG_UFS_SRCCLKENA_MASK_B, + PW_REG_UFS_INFRA_REQ_MASK_B, + PW_REG_UFS_APSRC_REQ_MASK_B, + PW_REG_UFS_VRF18_REQ_MASK_B, + PW_REG_UFS_DDREN_REQ_MASK_B, + PW_REG_DISP0_APSRC_REQ_MASK_B, + PW_REG_DISP0_DDREN_REQ_MASK_B, + PW_REG_DISP1_APSRC_REQ_MASK_B, + PW_REG_DISP1_DDREN_REQ_MASK_B, + PW_REG_GCE_INFRA_REQ_MASK_B, + PW_REG_GCE_APSRC_REQ_MASK_B, + PW_REG_GCE_VRF18_REQ_MASK_B, + PW_REG_GCE_DDREN_REQ_MASK_B, + PW_REG_APU_SRCCLKENA_MASK_B, + PW_REG_APU_INFRA_REQ_MASK_B, + PW_REG_APU_APSRC_REQ_MASK_B, + PW_REG_APU_VRF18_REQ_MASK_B, + PW_REG_APU_DDREN_REQ_MASK_B, + PW_REG_CG_CHECK_SRCCLKENA_MASK_B, + PW_REG_CG_CHECK_APSRC_REQ_MASK_B, + PW_REG_CG_CHECK_VRF18_REQ_MASK_B, + PW_REG_CG_CHECK_DDREN_REQ_MASK_B, + + /* SPM_SRC3_MASK */ + PW_REG_DVFSRC_EVENT_TRIGGER_MASK_B, + PW_REG_SW2SPM_WAKEUP_MASK_B, + PW_REG_ADSP2SPM_WAKEUP_MASK_B, + PW_REG_SSPM2SPM_WAKEUP_MASK_B, + PW_REG_SCP2SPM_WAKEUP_MASK_B, + PW_REG_CSYSPWRUP_ACK_MASK, + PW_REG_SPM_RESERVED_SRCCLKENA_MASK_B, + PW_REG_SPM_RESERVED_INFRA_REQ_MASK_B, + PW_REG_SPM_RESERVED_APSRC_REQ_MASK_B, + PW_REG_SPM_RESERVED_VRF18_REQ_MASK_B, + PW_REG_SPM_RESERVED_DDREN_REQ_MASK_B, + PW_REG_MCUPM_SRCCLKENA_MASK_B, + PW_REG_MCUPM_INFRA_REQ_MASK_B, + PW_REG_MCUPM_APSRC_REQ_MASK_B, + PW_REG_MCUPM_VRF18_REQ_MASK_B, + PW_REG_MCUPM_DDREN_REQ_MASK_B, + PW_REG_MSDC0_SRCCLKENA_MASK_B, + PW_REG_MSDC0_INFRA_REQ_MASK_B, + PW_REG_MSDC0_APSRC_REQ_MASK_B, + PW_REG_MSDC0_VRF18_REQ_MASK_B, + PW_REG_MSDC0_DDREN_REQ_MASK_B, + PW_REG_MSDC1_SRCCLKENA_MASK_B, + PW_REG_MSDC1_INFRA_REQ_MASK_B, + PW_REG_MSDC1_APSRC_REQ_MASK_B, + PW_REG_MSDC1_VRF18_REQ_MASK_B, + PW_REG_MSDC1_DDREN_REQ_MASK_B, + + /* SPM_SRC4_MASK */ + PW_REG_CCIF_EVENT_SRCCLKENA_MASK_B, + PW_REG_BAK_PSRI_SRCCLKENA_MASK_B, + PW_REG_BAK_PSRI_INFRA_REQ_MASK_B, + PW_REG_BAK_PSRI_APSRC_REQ_MASK_B, + PW_REG_BAK_PSRI_VRF18_REQ_MASK_B, + PW_REG_BAK_PSRI_DDREN_REQ_MASK_B, + PW_REG_DRAMC_MD32_INFRA_REQ_MASK_B, + PW_REG_DRAMC_MD32_VRF18_REQ_MASK_B, + PW_REG_CONN_SRCCLKENB2PWRAP_MASK_B, + PW_REG_DRAMC_MD32_APSRC_REQ_MASK_B, + + /* SPM_SRC5_MASK */ + PW_REG_MCUSYS_MERGE_APSRC_REQ_MASK_B, + PW_REG_MCUSYS_MERGE_DDREN_REQ_MASK_B, + PW_REG_AFE_SRCCLKENA_MASK_B, + PW_REG_AFE_INFRA_REQ_MASK_B, + PW_REG_AFE_APSRC_REQ_MASK_B, + PW_REG_AFE_VRF18_REQ_MASK_B, + PW_REG_AFE_DDREN_REQ_MASK_B, + PW_REG_MSDC2_SRCCLKENA_MASK_B, + PW_REG_MSDC2_INFRA_REQ_MASK_B, + PW_REG_MSDC2_APSRC_REQ_MASK_B, + PW_REG_MSDC2_VRF18_REQ_MASK_B, + PW_REG_MSDC2_DDREN_REQ_MASK_B, + + /* SPM_WAKEUP_EVENT_MASK */ + PW_REG_WAKEUP_EVENT_MASK, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + PW_REG_EXT_WAKEUP_EVENT_MASK, + + /* SPM_SRC7_MASK */ + PW_REG_PCIE_SRCCLKENA_MASK_B, + PW_REG_PCIE_INFRA_REQ_MASK_B, + PW_REG_PCIE_APSRC_REQ_MASK_B, + PW_REG_PCIE_VRF18_REQ_MASK_B, + PW_REG_PCIE_DDREN_REQ_MASK_B, + PW_REG_DPMAIF_SRCCLKENA_MASK_B, + PW_REG_DPMAIF_INFRA_REQ_MASK_B, + PW_REG_DPMAIF_APSRC_REQ_MASK_B, + PW_REG_DPMAIF_VRF18_REQ_MASK_B, + PW_REG_DPMAIF_DDREN_REQ_MASK_B, + + PW_MAX_COUNT, +}; + +/* + * ACK HW MODE SETTING + * 0: trigger(1) + * 1: trigger(0) + * 2: trigger(1) and target(0) + * 3: trigger(0) and target(1) + * 4: trigger(1) and target(1) + * 5: trigger(0) and target(0) + */ +#define TRIG_H_TAR_L (2U) +#define TRIG_L_TAR_H (3U) +#define TRIG_H_TAR_H (4U) +#define TRIG_L_TAR_L (5U) + +#define SPM_INTERNAL_STATUS_HW_S1 (1U << 0) +#define SPM_ACK_CHK_3_SEL_HW_S1 (0x00350098) +#define SPM_ACK_CHK_3_HW_S1_CNT (1U) +#define SPM_ACK_CHK_3_CON_HW_MODE_TRIG (TRIG_L_TAR_H << 9u) +#define SPM_ACK_CHK_3_CON_EN (0x110) +#define SPM_ACK_CHK_3_CON_CLR_ALL (0x2) +#define SPM_ACK_CHK_3_CON_RESULT (0x8000) + +struct wake_status_trace_comm { + uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */ + uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */ + uint32_t timer_out; /* SPM_SW_RSV_6*/ + uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */ + uint32_t b_sw_flag1; /* SPM_SW_RSV_7 */ + uint32_t r12; /* SPM_SW_RSV_0 */ + uint32_t r13; /* PCM_REG13_DATA */ + uint32_t req_sta0; /* SRC_REQ_STA_0 */ + uint32_t req_sta1; /* SRC_REQ_STA_1 */ + uint32_t req_sta2; /* SRC_REQ_STA_2 */ + uint32_t req_sta3; /* SRC_REQ_STA_3 */ + uint32_t req_sta4; /* SRC_REQ_STA_4 */ + uint32_t raw_sta; /* SPM_WAKEUP_STA */ + uint32_t times_h; /* timestamp high bits */ + uint32_t times_l; /* timestamp low bits */ + uint32_t resumetime; /* timestamp low bits */ +}; + +struct wake_status_trace { + struct wake_status_trace_comm comm; +}; + +struct wake_status { + struct wake_status_trace tr; + uint32_t r12; /* SPM_BK_WAKE_EVENT */ + uint32_t r12_ext; /* SPM_WAKEUP_EXT_STA */ + uint32_t raw_sta; /* SPM_WAKEUP_STA */ + uint32_t raw_ext_sta; /* SPM_WAKEUP_EXT_STA */ + uint32_t md32pcm_wakeup_sta; /* MD32CPM_WAKEUP_STA */ + uint32_t md32pcm_event_sta; /* MD32PCM_EVENT_STA */ + uint32_t wake_misc; /* SPM_BK_WAKE_MISC */ + uint32_t timer_out; /* SPM_BK_PCM_TIMER */ + uint32_t r13; /* PCM_REG13_DATA */ + uint32_t idle_sta; /* SUBSYS_IDLE_STA */ + uint32_t req_sta0; /* SRC_REQ_STA_0 */ + uint32_t req_sta1; /* SRC_REQ_STA_1 */ + uint32_t req_sta2; /* SRC_REQ_STA_2 */ + uint32_t req_sta3; /* SRC_REQ_STA_3 */ + uint32_t req_sta4; /* SRC_REQ_STA_4 */ + uint32_t cg_check_sta; /* SPM_CG_CHECK_STA */ + uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */ + uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */ + uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */ + uint32_t b_sw_flag1; /* SPM_SW_RSV_8 */ + uint32_t isr; /* SPM_IRQ_STA */ + uint32_t sw_flag0; /* SPM_SW_FLAG_0 */ + uint32_t sw_flag1; /* SPM_SW_FLAG_1 */ + uint32_t clk_settle; /* SPM_CLK_SETTLE */ + uint32_t src_req; /* SPM_SRC_REQ */ + uint32_t log_index; + uint32_t abort; + uint32_t rt_req_sta0; /* SPM_SW_RSV_2 */ + uint32_t rt_req_sta1; /* SPM_SW_RSV_3 */ + uint32_t rt_req_sta2; /* SPM_SW_RSV_4 */ + uint32_t rt_req_sta3; /* SPM_SW_RSV_5 */ + uint32_t rt_req_sta4; /* SPM_SW_RSV_6 */ + uint32_t mcupm_req_sta; +}; + +struct spm_lp_scen { + struct pcm_desc *pcmdesc; + struct pwr_ctrl *pwrctrl; +}; + +extern struct spm_lp_scen __spm_vcorefs; + +extern void __spm_set_cpu_status(unsigned int cpu); +extern void __spm_reset_and_init_pcm(const struct pcm_desc *pcmdesc); +extern void __spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc); +extern void __spm_init_pcm_register(void); +extern void __spm_src_req_update(const struct pwr_ctrl *pwrctrl, + unsigned int resource_usage); +extern void __spm_set_power_control(const struct pwr_ctrl *pwrctrl); +extern void __spm_disable_pcm_timer(void); +extern void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl); +extern void __spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl); +extern void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl); +extern void __spm_send_cpu_wakeup_event(void); + +extern void __spm_get_wakeup_status(struct wake_status *wakesta, + unsigned int ext_status); +extern void __spm_clean_after_wakeup(void); +extern wake_reason_t __spm_output_wake_reason(int state_id, + const struct wake_status *wakesta); +extern void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl, + const struct pwr_ctrl *src_pwr_ctrl); +extern void __spm_set_pcm_wdt(int en); +extern uint32_t _spm_get_wake_period(int pwake_time, wake_reason_t last_wr); +extern void __spm_set_fw_resume_option(struct pwr_ctrl *pwrctrl); +extern void __spm_ext_int_wakeup_req_clr(void); +extern void __spm_xo_soc_bblpm(int en); + +static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl, + uint32_t flags) +{ + if (pwrctrl->pcm_flags_cust == 0U) { + pwrctrl->pcm_flags = flags; + } else { + pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust; + } +} + +static inline void set_pwrctrl_pcm_flags1(struct pwr_ctrl *pwrctrl, + uint32_t flags) +{ + if (pwrctrl->pcm_flags1_cust == 0U) { + pwrctrl->pcm_flags1 = flags; + } else { + pwrctrl->pcm_flags1 = pwrctrl->pcm_flags1_cust; + } +} + +extern void __spm_hw_s1_state_monitor(int en, unsigned int *status); + +static inline void spm_hw_s1_state_monitor_resume(void) +{ + __spm_hw_s1_state_monitor(1, NULL); +} + +static inline void spm_hw_s1_state_monitor_pause(unsigned int *status) +{ + __spm_hw_s1_state_monitor(0, status); +} + +#endif /* MT_SPM_INTERNAL_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c new file mode 100644 index 0000000..849ffb7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* PMIC_WRAP MT6359 */ +#define NR_PMIC_WRAP_CMD (NR_IDX_ALL) +#define SPM_DATA_SHIFT (16U) + +struct pmic_wrap_cmd { + unsigned long cmd_addr; + unsigned long cmd_wdata; +}; + +struct pmic_wrap_setting { + enum pmic_wrap_phase_id phase; + struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD]; + struct { + struct { + unsigned long cmd_addr; + unsigned long cmd_wdata; + } _[NR_PMIC_WRAP_CMD]; + const int nr_idx; + } set[NR_PMIC_WRAP_PHASE]; +}; + +struct set_vsram { + unsigned long cmd_addr; + unsigned long cmd_wdata; +}; + +/* MT6366 */ +#define VOLT_TO_PMIC_VAL_66(volt) (((volt) - 50000 + 625 - 1) / 625) +#define BUCK_VCORE_ELR0_66 (0x14AA) +#define TOP_SPI_CON0_66 (0x44C) + +static struct pmic_wrap_setting pw66 = { + .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */ + .addr = { {0UL, 0UL} }, + .set[PMIC_WRAP_PHASE_ALLINONE] = { + ._[CMD_0] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), }, + ._[CMD_1] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(75000), }, + ._[CMD_2] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(70000), }, + ._[CMD_3] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(65000), }, + ._[CMD_4] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(60000), }, + ._[CMD_5] = { TOP_SPI_CON0_66, 0x1, }, + ._[CMD_6] = { TOP_SPI_CON0_66, 0x0, }, + .nr_idx = NR_IDX_ALL, + }, +}; + +/* MT6357 */ +#define VOLT_TO_PMIC_VAL_57(volt) (((volt) - 51875 + 625 - 1) / 625) +#define BUCK_VCORE_ELR0_57 (0x152A) +#define TOP_SPI_CON0_57 (0x448) + +static struct pmic_wrap_setting pw57 = { + .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */ + .addr = { {0UL, 0UL} }, + .set[PMIC_WRAP_PHASE_ALLINONE] = { + ._[CMD_0] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(80000), }, + ._[CMD_1] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(75000), }, + ._[CMD_2] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(70000), }, + ._[CMD_3] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(65000), }, + ._[CMD_4] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(62500), }, + ._[CMD_5] = { TOP_SPI_CON0_57, 0x1, }, + ._[CMD_6] = { TOP_SPI_CON0_57, 0x0, }, + .nr_idx = NR_IDX_ALL, + }, +}; + +static struct pmic_wrap_setting *pw; + +#define IS_PMIC_57() ((pmic_get_hwcid() >> 8) == 0x57) + +void _mt_spm_pmic_table_init(void) +{ + struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = { + { (uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0, }, + { (uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1, }, + { (uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2, }, + { (uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3, }, + { (uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4, }, + { (uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5, }, + { (uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6, }, + { (uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7, }, + { (uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8, }, + }; + + if (IS_PMIC_57()) { + pw = &pw57; + } else { + pw = &pw66; + } + + memcpy(pw->addr, pwrap_cmd_default, sizeof(pwrap_cmd_default)); +} + +void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase) +{ + uint32_t idx, addr, data; + + if (phase < NR_PMIC_WRAP_PHASE) { + if (pw == NULL || pw->addr[0].cmd_addr == 0) { + _mt_spm_pmic_table_init(); + } + + if (pw->phase != phase) { + pw->phase = phase; + + mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); + + for (idx = 0; idx < pw->set[phase].nr_idx; idx++) { + addr = pw->set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; + data = pw->set[phase]._[idx].cmd_wdata; + mmio_write_32(pw->addr[idx].cmd_addr, addr | data); + } + } + } +} + +void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx, + uint32_t cmd_wdata) +{ + uint32_t addr; + + if (phase >= NR_PMIC_WRAP_PHASE) { + return; + } + + if (pw == NULL || idx >= pw->set[phase].nr_idx) { + return; + } + + pw->set[phase]._[idx].cmd_wdata = cmd_wdata; + + mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); + if (pw->phase == phase) { + addr = pw->set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; + mmio_write_32(pw->addr[idx].cmd_addr, addr | cmd_wdata); + } +} + +uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx) +{ + uint64_t ret = 0UL; + + if ((phase < NR_PMIC_WRAP_PHASE) && + (pw != NULL && idx < pw->set[phase].nr_idx)) { + ret = pw->set[phase]._[idx].cmd_wdata; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h new file mode 100644 index 0000000..219b8d3 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/**************************************************************** + * Auto generated by DE, please DO NOT modify this file directly. + *****************************************************************/ +#ifndef MT_SPM_PMIC_WRAP_H +#define MT_SPM_PMIC_WRAP_H + +enum pmic_wrap_phase_id { + PMIC_WRAP_PHASE_ALLINONE = 0U, + NR_PMIC_WRAP_PHASE = 1U, +}; + +/* IDX mapping, PMIC_WRAP_PHASE_ALLINONE */ +enum { + CMD_0 = 0U, /* 0x0 */ + CMD_1 = 1U, /* 0x1 */ + CMD_2 = 2U, /* 0x2 */ + CMD_3 = 3U, /* 0x3 */ + CMD_4 = 4U, /* 0x4 */ + CMD_5 = 5U, /* 0x5 */ + CMD_6 = 6U, /* 0x6 */ + CMD_7 = 7U, /* 0x7 */ + CMD_8 = 8U, /* 0x8 */ + NR_IDX_ALL = 9U, +}; + +/* APIs */ +extern void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase); +extern void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, + uint32_t idx, uint32_t cmd_wdata); +extern uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, + uint32_t idx); + +#endif /* MT_SPM_PMIC_WRAP_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h new file mode 100644 index 0000000..f85ee3b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h @@ -0,0 +1,2957 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_REG +#define MT_SPM_REG + +#include "pcm_def.h" +#include +#include "sleep_def.h" + +/* Define and Declare */ +#define POWERON_CONFIG_EN (SPM_BASE + 0x000) +#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004) +#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008) +#define SPM_CLK_CON (SPM_BASE + 0x00C) +#define SPM_CLK_SETTLE (SPM_BASE + 0x010) +#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014) +#define PCM_CON0 (SPM_BASE + 0x018) +#define PCM_CON1 (SPM_BASE + 0x01C) +#define SPM_POWER_ON_VAL2 (SPM_BASE + 0x020) +#define SPM_POWER_ON_VAL3 (SPM_BASE + 0x024) +#define PCM_REG_DATA_INI (SPM_BASE + 0x028) +#define PCM_PWR_IO_EN (SPM_BASE + 0x02C) +#define PCM_TIMER_VAL (SPM_BASE + 0x030) +#define PCM_WDT_VAL (SPM_BASE + 0x034) +#define SPM_SW_RST_CON (SPM_BASE + 0x040) +#define SPM_SW_RST_CON_SET (SPM_BASE + 0x044) +#define SPM_SW_RST_CON_CLR (SPM_BASE + 0x048) +#define SPM_SRC6_MASK (SPM_BASE + 0x04C) +#define MD32_CLK_CON (SPM_BASE + 0x084) +#define SPM_SRAM_RSV_CON (SPM_BASE + 0x088) +#define SPM_SWINT (SPM_BASE + 0x08C) +#define SPM_SWINT_SET (SPM_BASE + 0x090) +#define SPM_SWINT_CLR (SPM_BASE + 0x094) +#define SPM_SCP_MAILBOX (SPM_BASE + 0x098) +#define SCP_SPM_MAILBOX (SPM_BASE + 0x09C) +#define SPM_WAKEUP_EVENT_SENS (SPM_BASE + 0x0A0) +#define SPM_WAKEUP_EVENT_CLEAR (SPM_BASE + 0x0A4) +#define SPM_SCP_IRQ (SPM_BASE + 0x0AC) +#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x0B0) +#define SPM_IRQ_MASK (SPM_BASE + 0x0B4) +#define SPM_SRC_REQ (SPM_BASE + 0x0B8) +#define SPM_SRC_MASK (SPM_BASE + 0x0BC) +#define SPM_SRC2_MASK (SPM_BASE + 0x0C0) +#define SPM_SRC3_MASK (SPM_BASE + 0x0C4) +#define SPM_SRC4_MASK (SPM_BASE + 0x0C8) +#define SPM_SRC5_MASK (SPM_BASE + 0x0CC) +#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x0D0) +#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0D4) +#define SPM_SRC7_MASK (SPM_BASE + 0x0D8) +#define SCP_CLK_CON (SPM_BASE + 0x0DC) +#define PCM_DEBUG_CON (SPM_BASE + 0x0E0) +#define DDREN_DBC_CON (SPM_BASE + 0x0E8) +#define SPM_RESOURCE_ACK_CON4 (SPM_BASE + 0x0EC) +#define SPM_RESOURCE_ACK_CON0 (SPM_BASE + 0x0F0) +#define SPM_RESOURCE_ACK_CON1 (SPM_BASE + 0x0F4) +#define SPM_RESOURCE_ACK_CON2 (SPM_BASE + 0x0F8) +#define SPM_RESOURCE_ACK_CON3 (SPM_BASE + 0x0FC) +#define PCM_REG0_DATA (SPM_BASE + 0x100) +#define PCM_REG2_DATA (SPM_BASE + 0x104) +#define PCM_REG6_DATA (SPM_BASE + 0x108) +#define PCM_REG7_DATA (SPM_BASE + 0x10C) +#define PCM_REG13_DATA (SPM_BASE + 0x110) +#define SRC_REQ_STA_0 (SPM_BASE + 0x114) +#define SRC_REQ_STA_1 (SPM_BASE + 0x118) +#define SRC_REQ_STA_2 (SPM_BASE + 0x11C) +#define PCM_TIMER_OUT (SPM_BASE + 0x120) +#define PCM_WDT_OUT (SPM_BASE + 0x124) +#define SPM_IRQ_STA (SPM_BASE + 0x128) +#define SRC_REQ_STA_4 (SPM_BASE + 0x12C) +#define MD32PCM_WAKEUP_STA (SPM_BASE + 0x130) +#define MD32PCM_EVENT_STA (SPM_BASE + 0x134) +#define SPM_WAKEUP_STA (SPM_BASE + 0x138) +#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x13C) +#define SPM_WAKEUP_MISC (SPM_BASE + 0x140) +#define MM_DVFS_HALT (SPM_BASE + 0x144) +#define BUS_PROTECT_RDY (SPM_BASE + 0x150) +#define BUS_PROTECT1_RDY (SPM_BASE + 0x154) +#define BUS_PROTECT2_RDY (SPM_BASE + 0x158) +#define BUS_PROTECT3_RDY (SPM_BASE + 0x15C) +#define SUBSYS_IDLE_STA (SPM_BASE + 0x160) +#define PCM_STA (SPM_BASE + 0x164) +#define SRC_REQ_STA_3 (SPM_BASE + 0x168) +#define PWR_STATUS (SPM_BASE + 0x16C) +#define PWR_STATUS_2ND (SPM_BASE + 0x170) +#define CPU_PWR_STATUS (SPM_BASE + 0x174) +#define OTHER_PWR_STATUS (SPM_BASE + 0x178) +#define SPM_VTCXO_EVENT_COUNT_STA (SPM_BASE + 0x17C) +#define SPM_INFRA_EVENT_COUNT_STA (SPM_BASE + 0x180) +#define SPM_VRF18_EVENT_COUNT_STA (SPM_BASE + 0x184) +#define SPM_APSRC_EVENT_COUNT_STA (SPM_BASE + 0x188) +#define SPM_DDREN_EVENT_COUNT_STA (SPM_BASE + 0x18C) +#define MD32PCM_STA (SPM_BASE + 0x190) +#define MD32PCM_PC (SPM_BASE + 0x194) +#define DVFSRC_EVENT_STA (SPM_BASE + 0x1A4) +#define BUS_PROTECT4_RDY (SPM_BASE + 0x1A8) +#define BUS_PROTECT5_RDY (SPM_BASE + 0x1AC) +#define BUS_PROTECT6_RDY (SPM_BASE + 0x1B0) +#define BUS_PROTECT7_RDY (SPM_BASE + 0x1B4) +#define BUS_PROTECT8_RDY (SPM_BASE + 0x1B8) +#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1D0) +#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1D4) +#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1D8) +#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1DC) +#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1E0) +#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1E4) +#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1E8) +#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1EC) +#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1F0) +#define SPM_CG_CHECK_STA (SPM_BASE + 0x1F4) +#define SPM_DVFS_STA (SPM_BASE + 0x1F8) +#define SPM_DVFS_OPP_STA (SPM_BASE + 0x1FC) +#define SPM_MCUSYS_PWR_CON (SPM_BASE + 0x200) +#define SPM_CPUTOP_PWR_CON (SPM_BASE + 0x204) +#define SPM_CPU0_PWR_CON (SPM_BASE + 0x208) +#define SPM_CPU1_PWR_CON (SPM_BASE + 0x20C) +#define SPM_CPU2_PWR_CON (SPM_BASE + 0x210) +#define SPM_CPU3_PWR_CON (SPM_BASE + 0x214) +#define SPM_CPU4_PWR_CON (SPM_BASE + 0x218) +#define SPM_CPU5_PWR_CON (SPM_BASE + 0x21C) +#define SPM_CPU6_PWR_CON (SPM_BASE + 0x220) +#define SPM_CPU7_PWR_CON (SPM_BASE + 0x224) +#define ARMPLL_CLK_CON (SPM_BASE + 0x22C) +#define MCUSYS_IDLE_STA (SPM_BASE + 0x230) +#define GIC_WAKEUP_STA (SPM_BASE + 0x234) +#define CPU_SPARE_CON (SPM_BASE + 0x238) +#define CPU_SPARE_CON_SET (SPM_BASE + 0x23C) +#define CPU_SPARE_CON_CLR (SPM_BASE + 0x240) +#define ARMPLL_CLK_SEL (SPM_BASE + 0x244) +#define EXT_INT_WAKEUP_REQ (SPM_BASE + 0x248) +#define EXT_INT_WAKEUP_REQ_SET (SPM_BASE + 0x24C) +#define EXT_INT_WAKEUP_REQ_CLR (SPM_BASE + 0x250) +#define CPU_IRQ_MASK (SPM_BASE + 0x260) +#define CPU_IRQ_MASK_SET (SPM_BASE + 0x264) +#define CPU_IRQ_MASK_CLR (SPM_BASE + 0x268) +#define CPU_WFI_EN (SPM_BASE + 0x280) +#define CPU_WFI_EN_SET (SPM_BASE + 0x284) +#define CPU_WFI_EN_CLR (SPM_BASE + 0x288) +#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x2A0) +#define ROOT_CORE_ADDR (SPM_BASE + 0x2A4) +#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x2D0) +#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x2D4) +#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x2D8) +#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x2DC) +#define SW2SPM_WAKEUP (SPM_BASE + 0x2E0) +#define SW2SPM_WAKEUP_SET (SPM_BASE + 0x2E4) +#define SW2SPM_WAKEUP_CLR (SPM_BASE + 0x2E8) +#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x2EC) +#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x2F0) +#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x2F4) +#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x2F8) +#define SW2SPM_CFG (SPM_BASE + 0x2FC) +#define MD1_PWR_CON (SPM_BASE + 0x300) +#define CONN_PWR_CON (SPM_BASE + 0x304) +#define MFG0_PWR_CON (SPM_BASE + 0x308) +#define MFG1_PWR_CON (SPM_BASE + 0x30C) +#define MFG2_PWR_CON (SPM_BASE + 0x310) +#define MFG3_PWR_CON (SPM_BASE + 0x314) +#define MFG4_PWR_CON (SPM_BASE + 0x318) +#define MFG5_PWR_CON (SPM_BASE + 0x31C) +#define MFG6_PWR_CON (SPM_BASE + 0x320) +#define IFR_PWR_CON (SPM_BASE + 0x324) +#define IFR_SUB_PWR_CON (SPM_BASE + 0x328) +#define DPY_PWR_CON (SPM_BASE + 0x32C) +#define DRAMC_MD32_PWR_CON (SPM_BASE + 0x330) +#define ISP_PWR_CON (SPM_BASE + 0x334) +#define ISP2_PWR_CON (SPM_BASE + 0x338) +#define IPE_PWR_CON (SPM_BASE + 0x33C) +#define VDE_PWR_CON (SPM_BASE + 0x340) +#define VDE2_PWR_CON (SPM_BASE + 0x344) +#define VEN_PWR_CON (SPM_BASE + 0x348) +#define VEN_CORE1_PWR_CON (SPM_BASE + 0x34C) +#define MDP_PWR_CON (SPM_BASE + 0x350) +#define DIS_PWR_CON (SPM_BASE + 0x354) +#define AUDIO_PWR_CON (SPM_BASE + 0x358) +#define CAM_PWR_CON (SPM_BASE + 0x35C) +#define CAM_RAWA_PWR_CON (SPM_BASE + 0x360) +#define CAM_RAWB_PWR_CON (SPM_BASE + 0x364) +#define CAM_RAWC_PWR_CON (SPM_BASE + 0x368) +#define SYSRAM_CON (SPM_BASE + 0x36C) +#define SYSROM_CON (SPM_BASE + 0x370) +#define SSPM_SRAM_CON (SPM_BASE + 0x374) +#define SCP_SRAM_CON (SPM_BASE + 0x378) +#define DPY_SHU_SRAM_CON (SPM_BASE + 0x37C) +#define UFS_SRAM_CON (SPM_BASE + 0x380) +#define DEVAPC_IFR_SRAM_CON (SPM_BASE + 0x384) +#define DEVAPC_SUBIFR_SRAM_CON (SPM_BASE + 0x388) +#define DEVAPC_ACP_SRAM_CON (SPM_BASE + 0x38C) +#define USB_SRAM_CON (SPM_BASE + 0x390) +#define DUMMY_SRAM_CON (SPM_BASE + 0x394) +#define MD_EXT_BUCK_ISO_CON (SPM_BASE + 0x398) +#define EXT_BUCK_ISO (SPM_BASE + 0x39C) +#define DXCC_SRAM_CON (SPM_BASE + 0x3A0) +#define MSDC_PWR_CON (SPM_BASE + 0x3A4) +#define DEBUGTOP_SRAM_CON (SPM_BASE + 0x3A8) +#define DP_TX_PWR_CON (SPM_BASE + 0x3AC) +#define DPMAIF_SRAM_CON (SPM_BASE + 0x3B0) +#define DPY_SHU2_SRAM_CON (SPM_BASE + 0x3B4) +#define DRAMC_MCU2_SRAM_CON (SPM_BASE + 0x3B8) +#define DRAMC_MCU_SRAM_CON (SPM_BASE + 0x3BC) +#define MCUPM_PWR_CON (SPM_BASE + 0x3C0) +#define DPY2_PWR_CON (SPM_BASE + 0x3C4) +#define SPM_SRAM_CON (SPM_BASE + 0x3C8) +#define PERI_PWR_CON (SPM_BASE + 0x3D0) +#define NNA0_PWR_CON (SPM_BASE + 0x3D4) +#define NNA1_PWR_CON (SPM_BASE + 0x3D8) +#define NNA2_PWR_CON (SPM_BASE + 0x3DC) +#define NNA_PWR_CON (SPM_BASE + 0x3E0) +#define ADSP_PWR_CON (SPM_BASE + 0x3E4) +#define DPY_SRAM_CON (SPM_BASE + 0x3E8) +#define SPM_MEM_CK_SEL (SPM_BASE + 0x400) +#define SPM_BUS_PROTECT_MASK_B (SPM_BASE + 0x404) +#define SPM_BUS_PROTECT1_MASK_B (SPM_BASE + 0x408) +#define SPM_BUS_PROTECT2_MASK_B (SPM_BASE + 0x40C) +#define SPM_BUS_PROTECT3_MASK_B (SPM_BASE + 0x410) +#define SPM_BUS_PROTECT4_MASK_B (SPM_BASE + 0x414) +#define SPM_EMI_BW_MODE (SPM_BASE + 0x418) +#define AP2MD_PEER_WAKEUP (SPM_BASE + 0x41C) +#define ULPOSC_CON (SPM_BASE + 0x420) +#define SPM2MM_CON (SPM_BASE + 0x424) +#define SPM_BUS_PROTECT5_MASK_B (SPM_BASE + 0x428) +#define SPM2MCUPM_CON (SPM_BASE + 0x42C) +#define AP_MDSRC_REQ (SPM_BASE + 0x430) +#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x434) +#define SPM2MD_DVFS_CON (SPM_BASE + 0x438) +#define MD2SPM_DVFS_CON (SPM_BASE + 0x43C) +#define SPM_BUS_PROTECT6_MASK_B (SPM_BASE + 0x440) +#define SPM_BUS_PROTECT7_MASK_B (SPM_BASE + 0x444) +#define SPM_BUS_PROTECT8_MASK_B (SPM_BASE + 0x448) +#define SPM_PLL_CON (SPM_BASE + 0x44C) +#define RC_SPM_CTRL (SPM_BASE + 0x450) +#define SPM_DRAM_MCU_SW_CON_0 (SPM_BASE + 0x454) +#define SPM_DRAM_MCU_SW_CON_1 (SPM_BASE + 0x458) +#define SPM_DRAM_MCU_SW_CON_2 (SPM_BASE + 0x45C) +#define SPM_DRAM_MCU_SW_CON_3 (SPM_BASE + 0x460) +#define SPM_DRAM_MCU_SW_CON_4 (SPM_BASE + 0x464) +#define SPM_DRAM_MCU_STA_0 (SPM_BASE + 0x468) +#define SPM_DRAM_MCU_STA_1 (SPM_BASE + 0x46C) +#define SPM_DRAM_MCU_STA_2 (SPM_BASE + 0x470) +#define SPM_DRAM_MCU_SW_SEL_0 (SPM_BASE + 0x474) +#define RELAY_DVFS_LEVEL (SPM_BASE + 0x478) +#define DRAMC_DPY_CLK_SW_CON_0 (SPM_BASE + 0x480) +#define DRAMC_DPY_CLK_SW_CON_1 (SPM_BASE + 0x484) +#define DRAMC_DPY_CLK_SW_CON_2 (SPM_BASE + 0x488) +#define DRAMC_DPY_CLK_SW_CON_3 (SPM_BASE + 0x48C) +#define DRAMC_DPY_CLK_SW_SEL_0 (SPM_BASE + 0x490) +#define DRAMC_DPY_CLK_SW_SEL_1 (SPM_BASE + 0x494) +#define DRAMC_DPY_CLK_SW_SEL_2 (SPM_BASE + 0x498) +#define DRAMC_DPY_CLK_SW_SEL_3 (SPM_BASE + 0x49C) +#define DRAMC_DPY_CLK_SPM_CON (SPM_BASE + 0x4A0) +#define SPM_DVFS_LEVEL (SPM_BASE + 0x4A4) +#define SPM_CIRQ_CON (SPM_BASE + 0x4A8) +#define SPM_DVFS_MISC (SPM_BASE + 0x4AC) +#define RG_MODULE_SW_CG_0_MASK_REQ_0 (SPM_BASE + 0x4B4) +#define RG_MODULE_SW_CG_0_MASK_REQ_1 (SPM_BASE + 0x4B8) +#define RG_MODULE_SW_CG_0_MASK_REQ_2 (SPM_BASE + 0x4BC) +#define RG_MODULE_SW_CG_1_MASK_REQ_0 (SPM_BASE + 0x4C0) +#define RG_MODULE_SW_CG_1_MASK_REQ_1 (SPM_BASE + 0x4C4) +#define RG_MODULE_SW_CG_1_MASK_REQ_2 (SPM_BASE + 0x4C8) +#define RG_MODULE_SW_CG_2_MASK_REQ_0 (SPM_BASE + 0x4CC) +#define RG_MODULE_SW_CG_2_MASK_REQ_1 (SPM_BASE + 0x4D0) +#define RG_MODULE_SW_CG_2_MASK_REQ_2 (SPM_BASE + 0x4D4) +#define RG_MODULE_SW_CG_3_MASK_REQ_0 (SPM_BASE + 0x4D8) +#define RG_MODULE_SW_CG_3_MASK_REQ_1 (SPM_BASE + 0x4DC) +#define RG_MODULE_SW_CG_3_MASK_REQ_2 (SPM_BASE + 0x4E0) +#define PWR_STATUS_MASK_REQ_0 (SPM_BASE + 0x4E4) +#define PWR_STATUS_MASK_REQ_1 (SPM_BASE + 0x4E8) +#define PWR_STATUS_MASK_REQ_2 (SPM_BASE + 0x4EC) +#define SPM_CG_CHECK_CON (SPM_BASE + 0x4F0) +#define SPM_SRC_RDY_STA (SPM_BASE + 0x4F4) +#define SPM_DVS_DFS_LEVEL (SPM_BASE + 0x4F8) +#define SPM_FORCE_DVFS (SPM_BASE + 0x4FC) +#define RC_M00_SRCLKEN_CFG (SPM_BASE + 0x520) +#define SPM_SW_FLAG_0 (SPM_BASE + 0x600) +#define SPM_SW_DEBUG_0 (SPM_BASE + 0x604) +#define SPM_SW_FLAG_1 (SPM_BASE + 0x608) +#define SPM_SW_DEBUG_1 (SPM_BASE + 0x60C) +#define SPM_SW_RSV_0 (SPM_BASE + 0x610) +#define SPM_SW_RSV_1 (SPM_BASE + 0x614) +#define SPM_SW_RSV_2 (SPM_BASE + 0x618) +#define SPM_SW_RSV_3 (SPM_BASE + 0x61C) +#define SPM_SW_RSV_4 (SPM_BASE + 0x620) +#define SPM_SW_RSV_5 (SPM_BASE + 0x624) +#define SPM_SW_RSV_6 (SPM_BASE + 0x628) +#define SPM_SW_RSV_7 (SPM_BASE + 0x62C) +#define SPM_SW_RSV_8 (SPM_BASE + 0x630) +#define SPM_BK_WAKE_EVENT (SPM_BASE + 0x634) +#define SPM_BK_VTCXO_DUR (SPM_BASE + 0x638) +#define SPM_BK_WAKE_MISC (SPM_BASE + 0x63C) +#define SPM_BK_PCM_TIMER (SPM_BASE + 0x640) +#define SPM_RSV_CON_0 (SPM_BASE + 0x650) +#define SPM_RSV_CON_1 (SPM_BASE + 0x654) +#define SPM_RSV_STA_0 (SPM_BASE + 0x658) +#define SPM_RSV_STA_1 (SPM_BASE + 0x65C) +#define SPM_SPARE_CON (SPM_BASE + 0x660) +#define SPM_SPARE_CON_SET (SPM_BASE + 0x664) +#define SPM_SPARE_CON_CLR (SPM_BASE + 0x668) +#define SPM_CROSS_WAKE_M00_REQ (SPM_BASE + 0x66C) +#define SPM_CROSS_WAKE_M01_REQ (SPM_BASE + 0x670) +#define SPM_CROSS_WAKE_M02_REQ (SPM_BASE + 0x674) +#define SPM_CROSS_WAKE_M03_REQ (SPM_BASE + 0x678) +#define SCP_VCORE_LEVEL (SPM_BASE + 0x67C) +#define SC_MM_CK_SEL_CON (SPM_BASE + 0x680) +#define SPARE_ACK_MASK (SPM_BASE + 0x684) +#define SPM_SPARE_FUNCTION (SPM_BASE + 0x688) +#define SPM_DV_CON_0 (SPM_BASE + 0x68C) +#define SPM_DV_CON_1 (SPM_BASE + 0x690) +#define SPM_DV_STA (SPM_BASE + 0x694) +#define CONN_XOWCN_DEBUG_EN (SPM_BASE + 0x698) +#define SPM_SEMA_M0 (SPM_BASE + 0x69C) +#define SPM_SEMA_M1 (SPM_BASE + 0x6A0) +#define SPM_SEMA_M2 (SPM_BASE + 0x6A4) +#define SPM_SEMA_M3 (SPM_BASE + 0x6A8) +#define SPM_SEMA_M4 (SPM_BASE + 0x6AC) +#define SPM_SEMA_M5 (SPM_BASE + 0x6B0) +#define SPM_SEMA_M6 (SPM_BASE + 0x6B4) +#define SPM_SEMA_M7 (SPM_BASE + 0x6B8) +#define SPM2ADSP_MAILBOX (SPM_BASE + 0x6BC) +#define ADSP2SPM_MAILBOX (SPM_BASE + 0x6C0) +#define SPM_ADSP_IRQ (SPM_BASE + 0x6C4) +#define SPM_MD32_IRQ (SPM_BASE + 0x6C8) +#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x6CC) +#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x6D0) +#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x6D4) +#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x6D8) +#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x6DC) +#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x6E0) +#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x6E4) +#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x6E8) +#define UFS_PSRI_SW (SPM_BASE + 0x6EC) +#define UFS_PSRI_SW_SET (SPM_BASE + 0x6F0) +#define UFS_PSRI_SW_CLR (SPM_BASE + 0x6F4) +#define SPM_AP_SEMA (SPM_BASE + 0x6F8) +#define SPM_SPM_SEMA (SPM_BASE + 0x6FC) +#define SPM_DVFS_CON (SPM_BASE + 0x700) +#define SPM_DVFS_CON_STA (SPM_BASE + 0x704) +#define SPM_PMIC_SPMI_CON (SPM_BASE + 0x708) +#define SPM_DVFS_CMD0 (SPM_BASE + 0x710) +#define SPM_DVFS_CMD1 (SPM_BASE + 0x714) +#define SPM_DVFS_CMD2 (SPM_BASE + 0x718) +#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C) +#define SPM_DVFS_CMD4 (SPM_BASE + 0x720) +#define SPM_DVFS_CMD5 (SPM_BASE + 0x724) +#define SPM_DVFS_CMD6 (SPM_BASE + 0x728) +#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C) +#define SPM_DVFS_CMD8 (SPM_BASE + 0x730) +#define SPM_DVFS_CMD9 (SPM_BASE + 0x734) +#define SPM_DVFS_CMD10 (SPM_BASE + 0x738) +#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C) +#define SPM_DVFS_CMD12 (SPM_BASE + 0x740) +#define SPM_DVFS_CMD13 (SPM_BASE + 0x744) +#define SPM_DVFS_CMD14 (SPM_BASE + 0x748) +#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C) +#define SPM_DVFS_CMD16 (SPM_BASE + 0x750) +#define SPM_DVFS_CMD17 (SPM_BASE + 0x754) +#define SPM_DVFS_CMD18 (SPM_BASE + 0x758) +#define SPM_DVFS_CMD19 (SPM_BASE + 0x75C) +#define SPM_DVFS_CMD20 (SPM_BASE + 0x760) +#define SPM_DVFS_CMD21 (SPM_BASE + 0x764) +#define SPM_DVFS_CMD22 (SPM_BASE + 0x768) +#define SPM_DVFS_CMD23 (SPM_BASE + 0x76C) +#define SYS_TIMER_VALUE_L (SPM_BASE + 0x770) +#define SYS_TIMER_VALUE_H (SPM_BASE + 0x774) +#define SYS_TIMER_START_L (SPM_BASE + 0x778) +#define SYS_TIMER_START_H (SPM_BASE + 0x77C) +#define SYS_TIMER_LATCH_L_00 (SPM_BASE + 0x780) +#define SYS_TIMER_LATCH_H_00 (SPM_BASE + 0x784) +#define SYS_TIMER_LATCH_L_01 (SPM_BASE + 0x788) +#define SYS_TIMER_LATCH_H_01 (SPM_BASE + 0x78C) +#define SYS_TIMER_LATCH_L_02 (SPM_BASE + 0x790) +#define SYS_TIMER_LATCH_H_02 (SPM_BASE + 0x794) +#define SYS_TIMER_LATCH_L_03 (SPM_BASE + 0x798) +#define SYS_TIMER_LATCH_H_03 (SPM_BASE + 0x79C) +#define SYS_TIMER_LATCH_L_04 (SPM_BASE + 0x7A0) +#define SYS_TIMER_LATCH_H_04 (SPM_BASE + 0x7A4) +#define SYS_TIMER_LATCH_L_05 (SPM_BASE + 0x7A8) +#define SYS_TIMER_LATCH_H_05 (SPM_BASE + 0x7AC) +#define SYS_TIMER_LATCH_L_06 (SPM_BASE + 0x7B0) +#define SYS_TIMER_LATCH_H_06 (SPM_BASE + 0x7B4) +#define SYS_TIMER_LATCH_L_07 (SPM_BASE + 0x7B8) +#define SYS_TIMER_LATCH_H_07 (SPM_BASE + 0x7BC) +#define SYS_TIMER_LATCH_L_08 (SPM_BASE + 0x7C0) +#define SYS_TIMER_LATCH_H_08 (SPM_BASE + 0x7C4) +#define SYS_TIMER_LATCH_L_09 (SPM_BASE + 0x7C8) +#define SYS_TIMER_LATCH_H_09 (SPM_BASE + 0x7CC) +#define SYS_TIMER_LATCH_L_10 (SPM_BASE + 0x7D0) +#define SYS_TIMER_LATCH_H_10 (SPM_BASE + 0x7D4) +#define SYS_TIMER_LATCH_L_11 (SPM_BASE + 0x7D8) +#define SYS_TIMER_LATCH_H_11 (SPM_BASE + 0x7DC) +#define SYS_TIMER_LATCH_L_12 (SPM_BASE + 0x7E0) +#define SYS_TIMER_LATCH_H_12 (SPM_BASE + 0x7E4) +#define SYS_TIMER_LATCH_L_13 (SPM_BASE + 0x7E8) +#define SYS_TIMER_LATCH_H_13 (SPM_BASE + 0x7EC) +#define SYS_TIMER_LATCH_L_14 (SPM_BASE + 0x7F0) +#define SYS_TIMER_LATCH_H_14 (SPM_BASE + 0x7F4) +#define SYS_TIMER_LATCH_L_15 (SPM_BASE + 0x7F8) +#define SYS_TIMER_LATCH_H_15 (SPM_BASE + 0x7FC) +#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800) +#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804) +#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808) +#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C) +#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810) +#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814) +#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818) +#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C) +#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820) +#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824) +#define PCM_WDT_LATCH_10 (SPM_BASE + 0x828) +#define PCM_WDT_LATCH_11 (SPM_BASE + 0x82C) +#define PCM_WDT_LATCH_12 (SPM_BASE + 0x830) +#define PCM_WDT_LATCH_13 (SPM_BASE + 0x834) +#define PCM_WDT_LATCH_14 (SPM_BASE + 0x838) +#define PCM_WDT_LATCH_15 (SPM_BASE + 0x83C) +#define PCM_WDT_LATCH_16 (SPM_BASE + 0x840) +#define PCM_WDT_LATCH_17 (SPM_BASE + 0x844) +#define PCM_WDT_LATCH_18 (SPM_BASE + 0x848) +#define PCM_WDT_LATCH_SPARE_0 (SPM_BASE + 0x84C) +#define PCM_WDT_LATCH_SPARE_1 (SPM_BASE + 0x850) +#define PCM_WDT_LATCH_SPARE_2 (SPM_BASE + 0x854) +#define PCM_WDT_LATCH_CONN_0 (SPM_BASE + 0x870) +#define PCM_WDT_LATCH_CONN_1 (SPM_BASE + 0x874) +#define PCM_WDT_LATCH_CONN_2 (SPM_BASE + 0x878) +#define DRAMC_GATING_ERR_LATCH_CH0_0 (SPM_BASE + 0x8A0) +#define DRAMC_GATING_ERR_LATCH_CH0_1 (SPM_BASE + 0x8A4) +#define DRAMC_GATING_ERR_LATCH_CH0_2 (SPM_BASE + 0x8A8) +#define DRAMC_GATING_ERR_LATCH_CH0_3 (SPM_BASE + 0x8AC) +#define DRAMC_GATING_ERR_LATCH_CH0_4 (SPM_BASE + 0x8B0) +#define DRAMC_GATING_ERR_LATCH_CH0_5 (SPM_BASE + 0x8B4) +#define DRAMC_GATING_ERR_LATCH_CH0_6 (SPM_BASE + 0x8B8) +#define DRAMC_GATING_ERR_LATCH_SPARE_0 (SPM_BASE + 0x8F4) +#define SPM_ACK_CHK_CON_0 (SPM_BASE + 0x900) +#define SPM_ACK_CHK_PC_0 (SPM_BASE + 0x904) +#define SPM_ACK_CHK_SEL_0 (SPM_BASE + 0x908) +#define SPM_ACK_CHK_TIMER_0 (SPM_BASE + 0x90C) +#define SPM_ACK_CHK_STA_0 (SPM_BASE + 0x910) +#define SPM_ACK_CHK_SWINT_0 (SPM_BASE + 0x914) +#define SPM_ACK_CHK_CON_1 (SPM_BASE + 0x918) +#define SPM_ACK_CHK_PC_1 (SPM_BASE + 0x91C) +#define SPM_ACK_CHK_SEL_1 (SPM_BASE + 0x920) +#define SPM_ACK_CHK_TIMER_1 (SPM_BASE + 0x924) +#define SPM_ACK_CHK_STA_1 (SPM_BASE + 0x928) +#define SPM_ACK_CHK_SWINT_1 (SPM_BASE + 0x92C) +#define SPM_ACK_CHK_CON_2 (SPM_BASE + 0x930) +#define SPM_ACK_CHK_PC_2 (SPM_BASE + 0x934) +#define SPM_ACK_CHK_SEL_2 (SPM_BASE + 0x938) +#define SPM_ACK_CHK_TIMER_2 (SPM_BASE + 0x93C) +#define SPM_ACK_CHK_STA_2 (SPM_BASE + 0x940) +#define SPM_ACK_CHK_SWINT_2 (SPM_BASE + 0x944) +#define SPM_ACK_CHK_CON_3 (SPM_BASE + 0x948) +#define SPM_ACK_CHK_PC_3 (SPM_BASE + 0x94C) +#define SPM_ACK_CHK_SEL_3 (SPM_BASE + 0x950) +#define SPM_ACK_CHK_TIMER_3 (SPM_BASE + 0x954) +#define SPM_ACK_CHK_STA_3 (SPM_BASE + 0x958) +#define SPM_ACK_CHK_SWINT_3 (SPM_BASE + 0x95C) +#define SPM_COUNTER_0 (SPM_BASE + 0x960) +#define SPM_COUNTER_1 (SPM_BASE + 0x964) +#define SPM_COUNTER_2 (SPM_BASE + 0x968) +#define SYS_TIMER_CON (SPM_BASE + 0x96C) +#define SPM_TWAM_CON (SPM_BASE + 0x970) +#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x974) +#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x978) +#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x97C) +#define OPP0_TABLE (SPM_BASE + 0x980) +#define OPP1_TABLE (SPM_BASE + 0x984) +#define OPP2_TABLE (SPM_BASE + 0x988) +#define OPP3_TABLE (SPM_BASE + 0x98C) +#define OPP4_TABLE (SPM_BASE + 0x990) +#define OPP5_TABLE (SPM_BASE + 0x994) +#define OPP6_TABLE (SPM_BASE + 0x998) +#define OPP7_TABLE (SPM_BASE + 0x99C) +#define OPP8_TABLE (SPM_BASE + 0x9A0) +#define OPP9_TABLE (SPM_BASE + 0x9A4) +#define OPP10_TABLE (SPM_BASE + 0x9A8) +#define OPP11_TABLE (SPM_BASE + 0x9AC) +#define OPP12_TABLE (SPM_BASE + 0x9B0) +#define OPP13_TABLE (SPM_BASE + 0x9B4) +#define OPP14_TABLE (SPM_BASE + 0x9B8) +#define OPP15_TABLE (SPM_BASE + 0x9BC) +#define OPP16_TABLE (SPM_BASE + 0x9C0) +#define OPP17_TABLE (SPM_BASE + 0x9C4) +#define SHU0_ARRAY (SPM_BASE + 0x9C8) +#define SHU1_ARRAY (SPM_BASE + 0x9CC) +#define SHU2_ARRAY (SPM_BASE + 0x9D0) +#define SHU3_ARRAY (SPM_BASE + 0x9D4) +#define SHU4_ARRAY (SPM_BASE + 0x9D8) +#define SHU5_ARRAY (SPM_BASE + 0x9DC) +#define SHU6_ARRAY (SPM_BASE + 0x9E0) +#define SHU7_ARRAY (SPM_BASE + 0x9E4) +#define SHU8_ARRAY (SPM_BASE + 0x9E8) +#define SHU9_ARRAY (SPM_BASE + 0x9EC) + +/* POWERON_CONFIG_EN (0x10006000 + 0x000) */ +#define BCLK_CG_EN_LSB (1U << 0) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ + +/* SPM_POWER_ON_VAL0 (0x10006000 + 0x004) */ +#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */ + +/* SPM_POWER_ON_VAL1 (0x10006000 + 0x008) */ +#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */ + +/* SPM_CLK_CON (0x10006000 + 0x00C) */ +#define REG_SRCCLKEN0_CTL_LSB (1U << 0) /* 2b */ +#define REG_SRCCLKEN1_CTL_LSB (1U << 2) /* 2b */ +#define RC_SW_SRCCLKEN_RC (1U << 3) /* 1b */ +#define RC_SW_SRCCLKEN_FPM (1U << 4) /* 1b */ +#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */ +#define REG_SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */ +#define REG_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */ +#define REG_MD1_C32RM_EN_LSB (1U << 9) /* 1b */ +#define REG_MD2_C32RM_EN_LSB (1U << 10) /* 1b */ +#define REG_CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */ +#define REG_CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */ +#define REG_SRCCLKEN0_EN_LSB (1U << 13) /* 1b */ +#define REG_SRCCLKEN1_EN_LSB (1U << 14) /* 1b */ +#define SCP_DCM_EN_LSB (1U << 15) /* 1b */ +#define REG_SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 8b */ +#define REG_SYSCLK1_SRC_MASK_B_LSB (1U << 24) /* 8b */ + +/* SPM_CLK_SETTLE (0x10006000 + 0x010) */ +#define SYSCLK_SETTLE_LSB (1U << 0) /* 28b */ + +/* SPM_AP_STANDBY_CON (0x10006000 + 0x014) */ +#define REG_WFI_OP_LSB (1U << 0) /* 1b */ +#define REG_WFI_TYPE_LSB (1U << 1) /* 1b */ +#define REG_MP0_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */ +#define REG_MP1_CPUTOP_IDLE_MASK_LSB (1U << 3) /* 1b */ +#define REG_MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */ +#define REG_MD_APSRC_1_SEL_LSB (1U << 25) /* 1b */ +#define REG_MD_APSRC_0_SEL_LSB (1U << 26) /* 1b */ +#define REG_CONN_APSRC_SEL_LSB (1U << 29) /* 1b */ + +/* PCM_CON0 (0x10006000 + 0x018) */ +#define PCM_CK_EN_LSB (1U << 2) /* 1b */ +#define RG_EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */ +#define PCM_CK_FROM_CKSYS_LSB (1U << 4) /* 1b */ +#define PCM_SW_RESET_LSB (1U << 15) /* 1b */ +#define PCM_CON0_PROJECT_CODE_LSB (1U << 16) /* 16b */ + +/* PCM_CON1 (0x10006000 + 0x01C) */ +#define REG_IM_SLEEP_EN_LSB (1U << 1) /* 1b */ +#define REG_SPM_SRAM_CTRL_MUX_LSB (1U << 2) /* 1b */ +#define RG_AHBMIF_APBEN_LSB (1U << 3) /* 1b */ +#define RG_PCM_TIMER_EN_LSB (1U << 5) /* 1b */ +#define REG_SPM_EVENT_COUNTER_CLR_LSB (1U << 6) /* 1b */ +#define RG_DIS_MIF_PROT_LSB (1U << 7) /* 1b */ +#define RG_PCM_WDT_EN_LSB (1U << 8) /* 1b */ +#define RG_PCM_WDT_WAKE_LSB (1U << 9) /* 1b */ +#define SPM_LEAVE_SUSPEND_MERGE_MASK_LSB (1U << 10) /* 1b */ +#define REG_SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */ +#define REG_MD32_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */ +#define RG_PCM_IRQ_MSK_LSB (1U << 15) /* 1b */ +#define PCM_CON1_PROJECT_CODE_LSB (1U << 16) /* 16b */ + +/* SPM_POWER_ON_VAL2 (0x10006000 + 0x020) */ +#define POWER_ON_VAL2_LSB (1U << 0) /* 32b */ + +/* SPM_POWER_ON_VAL3 (0x10006000 + 0x024) */ +#define POWER_ON_VAL3_LSB (1U << 0) /* 32b */ + +/* PCM_REG_DATA_INI (0x10006000 + 0x028) */ +#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */ + +/* PCM_PWR_IO_EN (0x10006000 + 0x02C) */ +#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */ +#define RG_RF_SYNC_EN_LSB (1U << 16) /* 8b */ + +/* PCM_TIMER_VAL (0x10006000 + 0x030) */ +#define REG_PCM_TIMER_VAL_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_VAL (0x10006000 + 0x034) */ +#define RG_PCM_WDT_VAL_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RST_CON (0x10006000 + 0x040) */ +#define SPM_SW_RST_CON_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_PROJECT_CODE_LSB (1U << 16) /* 16b */ + +/* SPM_SW_RST_CON_SET (0x10006000 + 0x044) */ +#define SPM_SW_RST_CON_SET_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_SET_PROJECT_CODE_LSB (1U << 16) /* 16b */ + +/* SPM_SW_RST_CON_CLR (0x10006000 + 0x048) */ +#define SPM_SW_RST_CON_CLR_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_CLR_PROJECT_CODE_LSB (1U << 16) /* 16b */ + +/* SPM_SRC6_MASK (0x10006000 + 0x04C) */ +#define REG_CCIF_EVENT_INFRA_REQ_MASK_B_LSB (1U << 0) /* 16b */ +#define REG_CCIF_EVENT_APSRC_REQ_MASK_B_LSB (1U << 16) /* 16b */ + +/* MD32_CLK_CON (0x10006000 + 0x084) */ +#define REG_MD32_26M_CK_SEL_LSB (1U << 0) /* 1b */ +#define REG_MD32_DCM_EN_LSB (1U << 1) /* 1b */ + +/* SPM_SRAM_RSV_CON (0x10006000 + 0x088) */ +#define SPM_SRAM_SLEEP_B_ECO_EN_LSB (1U << 0) /* 1b */ + +/* SPM_SWINT (0x10006000 + 0x08C) */ +#define SPM_SWINT_LSB (1U << 0) /* 32b */ + +/* SPM_SWINT_SET (0x10006000 + 0x090) */ +#define SPM_SWINT_SET_LSB (1U << 0) /* 32b */ + +/* SPM_SWINT_CLR (0x10006000 + 0x094) */ +#define SPM_SWINT_CLR_LSB (1U << 0) /* 32b */ + +/* SPM_SCP_MAILBOX (0x10006000 + 0x098) */ +#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */ + +/* SCP_SPM_MAILBOX (0x10006000 + 0x09C) */ +#define SCP_SPM_MAILBOX_LSB (1U << 0) /* 32b */ + +/* SPM_WAKEUP_EVENT_SENS (0x10006000 + 0x0A0) */ +#define REG_WAKEUP_EVENT_SENS_LSB (1U << 0) /* 32b */ + +/* SPM_WAKEUP_EVENT_CLEAR (0x10006000 + 0x0A4) */ +#define REG_WAKEUP_EVENT_CLR_LSB (1U << 0) /* 32b */ + +/* SPM_SCP_IRQ (0x10006000 + 0x0AC) */ +#define SC_SPM2SCP_WAKEUP_LSB (1U << 0) /* 1b */ +#define SC_SCP2SPM_WAKEUP_LSB (1U << 4) /* 1b */ + +/* SPM_CPU_WAKEUP_EVENT (0x10006000 + 0x0B0) */ +#define REG_CPU_WAKEUP_LSB (1U << 0) /* 1b */ + +/* SPM_IRQ_MASK (0x10006000 + 0x0B4) */ +#define REG_SPM_IRQ_MASK_LSB (1U << 0) /* 32b */ + +/* SPM_SRC_REQ (0x10006000 + 0x0B8) */ +#define REG_SPM_APSRC_REQ_LSB (1U << 0) /* 1b */ +#define REG_SPM_F26M_REQ_LSB (1U << 1) /* 1b */ +#define REG_SPM_INFRA_REQ_LSB (1U << 3) /* 1b */ +#define REG_SPM_VRF18_REQ_LSB (1U << 4) /* 1b */ +#define REG_SPM_DDREN_REQ_LSB (1U << 7) /* 1b */ +#define REG_SPM_DVFS_REQ_LSB (1U << 8) /* 1b */ +#define REG_SPM_SW_MAILBOX_REQ_LSB (1U << 9) /* 1b */ +#define REG_SPM_SSPM_MAILBOX_REQ_LSB (1U << 10) /* 1b */ +#define REG_SPM_ADSP_MAILBOX_REQ_LSB (1U << 11) /* 1b */ +#define REG_SPM_SCP_MAILBOX_REQ_LSB (1U << 12) /* 1b */ + +/* SPM_SRC_MASK (0x10006000 + 0x0BC) */ +#define REG_MD_0_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_MD_0_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_MD_0_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_MD_0_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_MD_0_DDREN_REQ_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_MD_1_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_MD_1_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */ +#define REG_MD_1_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */ +#define REG_MD_1_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */ +#define REG_MD_1_DDREN_REQ_MASK_B_LSB (1U << 9) /* 1b */ +#define REG_CONN_SRCCLKENA_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_CONN_SRCCLKENB_MASK_B_LSB (1U << 11) /* 1b */ +#define REG_CONN_INFRA_REQ_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_CONN_APSRC_REQ_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_CONN_VRF18_REQ_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_CONN_DDREN_REQ_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_CONN_VFE28_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_SRCCLKENI_SRCCLKENA_MASK_B_LSB (1U << 17) /* 3b */ +#define REG_SRCCLKENI_INFRA_REQ_MASK_B_LSB (1U << 20) /* 3b */ +#define REG_INFRASYS_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_INFRASYS_DDREN_REQ_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_SSPM_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_SSPM_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_SSPM_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_SSPM_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_SSPM_DDREN_REQ_MASK_B_LSB (1U << 31) /* 1b */ + +/* SPM_SRC2_MASK (0x10006000 + 0x0C0) */ +#define REG_SCP_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_SCP_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_SCP_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_SCP_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_SCP_DDREN_REQ_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_AUDIO_DSP_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_AUDIO_DSP_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */ +#define REG_AUDIO_DSP_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */ +#define REG_AUDIO_DSP_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */ +#define REG_AUDIO_DSP_DDREN_REQ_MASK_B_LSB (1U << 9) /* 1b */ +#define REG_UFS_SRCCLKENA_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_UFS_INFRA_REQ_MASK_B_LSB (1U << 11) /* 1b */ +#define REG_UFS_APSRC_REQ_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_UFS_VRF18_REQ_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_UFS_DDREN_REQ_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_DISP0_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_DISP0_DDREN_REQ_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_DISP1_APSRC_REQ_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_DISP1_DDREN_REQ_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_GCE_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_GCE_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_GCE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_GCE_DDREN_REQ_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_APU_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_APU_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_APU_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_APU_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_APU_DDREN_REQ_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_CG_CHECK_SRCCLKENA_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_CG_CHECK_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_CG_CHECK_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_CG_CHECK_DDREN_REQ_MASK_B_LSB (1U << 31) /* 1b */ + +/* SPM_SRC3_MASK (0x10006000 + 0x0C4) */ +#define REG_DVFSRC_EVENT_TRIGGER_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_SW2SPM_WAKEUP_MASK_B_LSB (1U << 1) /* 4b */ +#define REG_ADSP2SPM_WAKEUP_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_SSPM2SPM_WAKEUP_MASK_B_LSB (1U << 6) /* 4b */ +#define REG_SCP2SPM_WAKEUP_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_CSYSPWRUP_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_SPM_RESERVED_SRCCLKENA_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_SPM_RESERVED_INFRA_REQ_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_SPM_RESERVED_APSRC_REQ_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_SPM_RESERVED_VRF18_REQ_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_SPM_RESERVED_DDREN_REQ_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_MCUPM_SRCCLKENA_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_MCUPM_INFRA_REQ_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_MCUPM_APSRC_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_MCUPM_VRF18_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_MCUPM_DDREN_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_MSDC0_SRCCLKENA_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_MSDC0_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_MSDC0_APSRC_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_MSDC0_VRF18_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_MSDC0_DDREN_REQ_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_MSDC1_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_MSDC1_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_MSDC1_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_MSDC1_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_MSDC1_DDREN_REQ_MASK_B_LSB (1U << 31) /* 1b */ + +/* SPM_SRC4_MASK (0x10006000 + 0x0C8) */ +#define REG_CCIF_EVENT_SRCCLKENA_MASK_B_LSB (1U << 0) /* 16b */ +#define REG_BAK_PSRI_SRCCLKENA_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_BAK_PSRI_INFRA_REQ_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_BAK_PSRI_APSRC_REQ_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_BAK_PSRI_VRF18_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_BAK_PSRI_DDREN_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_DRAMC_MD32_INFRA_REQ_MASK_B_LSB (1U << 21) /* 2b */ +#define REG_DRAMC_MD32_VRF18_REQ_MASK_B_LSB (1U << 23) /* 2b */ +#define REG_CONN_SRCCLKENB2PWRAP_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_DRAMC_MD32_APSRC_REQ_MASK_B_LSB (1U << 26) /* 2b */ + +/* SPM_SRC5_MASK (0x10006000 + 0x0CC) */ +#define REG_MCUSYS_MERGE_APSRC_REQ_MASK_B_LSB (1U << 0) /* 9b */ +#define REG_MCUSYS_MERGE_DDREN_REQ_MASK_B_LSB (1U << 9) /* 9b */ +#define REG_AFE_SRCCLKENA_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_AFE_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_AFE_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_AFE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_AFE_DDREN_REQ_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_MSDC2_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_MSDC2_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_MSDC2_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_MSDC2_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_MSDC2_DDREN_REQ_MASK_B_LSB (1U << 27) /* 1b */ +/* SPM_WAKEUP_EVENT_MASK (0x10006000 + 0x0D0) */ +#define REG_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */ + +/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000 + 0x0D4) */ +#define REG_EXT_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */ + +/* SPM_SRC7_MASK (0x10006000 + 0x0D8) */ +#define REG_PCIE_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_PCIE_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_PCIE_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_PCIE_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_PCIE_DDREN_REQ_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_DPMAIF_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_DPMAIF_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */ +#define REG_DPMAIF_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */ +#define REG_DPMAIF_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */ +#define REG_DPMAIF_DDREN_REQ_MASK_B_LSB (1U << 9) /* 1b */ + +/* SCP_CLK_CON (0x10006000 + 0x0DC) */ +#define REG_SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */ +#define REG_SCP_DCM_EN_LSB (1U << 1) /* 1b */ +#define SCP_SECURE_VREQ_MASK_LSB (1U << 2) /* 1b */ +#define SCP_SLP_REQ_LSB (1U << 3) /* 1b */ +#define SCP_SLP_ACK_LSB (1U << 4) /* 1b */ + +/* PCM_DEBUG_CON (0x10006000 + 0x0E0) */ +#define PCM_DEBUG_OUT_ENABLE_LSB (1U << 0) /* 1b */ + +/* DDREN_DBC_CON (0x10006000 + 0x0E8) */ +#define REG_DDREN_DBC_LEN_LSB (1U << 0) /* 10b */ +#define REG_DDREN_DBC_EN_LSB (1U << 16) /* 1b */ + +/* SPM_RESOURCE_ACK_CON4 (0x10006000 + 0x0EC) */ +#define REG_DPMAIF_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */ +#define REG_DPMAIF_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */ +#define REG_DPMAIF_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */ +#define REG_DPMAIF_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */ +#define REG_DPMAIF_DDREN_ACK_MASK_LSB (1U << 4) /* 1b */ + +/* SPM_RESOURCE_ACK_CON0 (0x10006000 + 0x0F0) */ +#define REG_MD_0_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */ +#define REG_MD_0_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */ +#define REG_MD_0_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */ +#define REG_MD_0_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */ +#define REG_MD_0_DDREN_ACK_MASK_LSB (1U << 4) /* 1b */ +#define REG_MD_1_SRCCLKENA_ACK_MASK_LSB (1U << 5) /* 1b */ +#define REG_MD_1_INFRA_ACK_MASK_LSB (1U << 6) /* 1b */ +#define REG_MD_1_APSRC_ACK_MASK_LSB (1U << 7) /* 1b */ +#define REG_MD_1_VRF18_ACK_MASK_LSB (1U << 8) /* 1b */ +#define REG_MD_1_DDREN_ACK_MASK_LSB (1U << 9) /* 1b */ +#define REG_CONN_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_CONN_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_CONN_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */ +#define REG_CONN_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */ +#define REG_CONN_DDREN_ACK_MASK_LSB (1U << 14) /* 1b */ +#define REG_SSPM_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */ +#define REG_SSPM_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */ +#define REG_SSPM_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */ +#define REG_SSPM_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */ +#define REG_SSPM_DDREN_ACK_MASK_LSB (1U << 19) /* 1b */ +#define REG_SCP_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */ +#define REG_SCP_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */ +#define REG_SCP_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */ +#define REG_SCP_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */ +#define REG_SCP_DDREN_ACK_MASK_LSB (1U << 24) /* 1b */ +#define REG_AUDIO_DSP_SRCCLKENA_ACK_MASK_LSB (1U << 25) /* 1b */ +#define REG_AUDIO_DSP_INFRA_ACK_MASK_LSB (1U << 26) /* 1b */ +#define REG_AUDIO_DSP_APSRC_ACK_MASK_LSB (1U << 27) /* 1b */ +#define REG_AUDIO_DSP_VRF18_ACK_MASK_LSB (1U << 28) /* 1b */ +#define REG_AUDIO_DSP_DDREN_ACK_MASK_LSB (1U << 29) /* 1b */ +#define REG_DISP0_DDREN_ACK_MASK_LSB (1U << 30) /* 1b */ +#define REG_DISP1_APSRC_ACK_MASK_LSB (1U << 31) /* 1b */ + +/* SPM_RESOURCE_ACK_CON1 (0x10006000 + 0x0F4) */ +#define REG_UFS_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */ +#define REG_UFS_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */ +#define REG_UFS_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */ +#define REG_UFS_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */ +#define REG_UFS_DDREN_ACK_MASK_LSB (1U << 4) /* 1b */ +#define REG_APU_SRCCLKENA_ACK_MASK_LSB (1U << 5) /* 1b */ +#define REG_APU_INFRA_ACK_MASK_LSB (1U << 6) /* 1b */ +#define REG_APU_APSRC_ACK_MASK_LSB (1U << 7) /* 1b */ +#define REG_APU_VRF18_ACK_MASK_LSB (1U << 8) /* 1b */ +#define REG_APU_DDREN_ACK_MASK_LSB (1U << 9) /* 1b */ +#define REG_MCUPM_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_MCUPM_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_MCUPM_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */ +#define REG_MCUPM_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */ +#define REG_MCUPM_DDREN_ACK_MASK_LSB (1U << 14) /* 1b */ +#define REG_MSDC0_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */ +#define REG_MSDC0_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */ +#define REG_MSDC0_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */ +#define REG_MSDC0_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */ +#define REG_MSDC0_DDREN_ACK_MASK_LSB (1U << 19) /* 1b */ +#define REG_MSDC1_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */ +#define REG_MSDC1_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */ +#define REG_MSDC1_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */ +#define REG_MSDC1_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */ +#define REG_MSDC1_DDREN_ACK_MASK_LSB (1U << 24) /* 1b */ +#define REG_DISP0_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */ +#define REG_DISP1_DDREN_ACK_MASK_LSB (1U << 26) /* 1b */ +#define REG_GCE_INFRA_ACK_MASK_LSB (1U << 27) /* 1b */ +#define REG_GCE_APSRC_ACK_MASK_LSB (1U << 28) /* 1b */ +#define REG_GCE_VRF18_ACK_MASK_LSB (1U << 29) /* 1b */ +#define REG_GCE_DDREN_ACK_MASK_LSB (1U << 30) /* 1b */ + +/* SPM_RESOURCE_ACK_CON2 (0x10006000 + 0x0F8) */ +#define SPM_SRCCLKENA_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */ +#define SPM_INFRA_ACK_WAIT_CYCLE_LSB (1U << 8) /* 8b */ +#define SPM_APSRC_ACK_WAIT_CYCLE_LSB (1U << 16) /* 8b */ +#define SPM_VRF18_ACK_WAIT_CYCLE_LSB (1U << 24) /* 8b */ + +/* SPM_RESOURCE_ACK_CON3 (0x10006000 + 0x0FC) */ +#define SPM_DDREN_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */ +#define REG_BAK_PSRI_SRCCLKENA_ACK_MASK_LSB (1U << 8) /* 1b */ +#define REG_BAK_PSRI_INFRA_ACK_MASK_LSB (1U << 9) /* 1b */ +#define REG_BAK_PSRI_APSRC_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_BAK_PSRI_VRF18_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_BAK_PSRI_DDREN_ACK_MASK_LSB (1U << 12) /* 1b */ +#define REG_AFE_SRCCLKENA_ACK_MASK_LSB (1U << 13) /* 1b */ +#define REG_AFE_INFRA_ACK_MASK_LSB (1U << 14) /* 1b */ +#define REG_AFE_APSRC_ACK_MASK_LSB (1U << 15) /* 1b */ +#define REG_AFE_VRF18_ACK_MASK_LSB (1U << 16) /* 1b */ +#define REG_AFE_DDREN_ACK_MASK_LSB (1U << 17) /* 1b */ +#define REG_MSDC2_SRCCLKENA_ACK_MASK_LSB (1U << 18) /* 1b */ +#define REG_MSDC2_INFRA_ACK_MASK_LSB (1U << 19) /* 1b */ +#define REG_MSDC2_APSRC_ACK_MASK_LSB (1U << 20) /* 1b */ +#define REG_MSDC2_VRF18_ACK_MASK_LSB (1U << 21) /* 1b */ +#define REG_MSDC2_DDREN_ACK_MASK_LSB (1U << 22) /* 1b */ +#define REG_PCIE_SRCCLKENA_ACK_MASK_LSB (1U << 23) /* 1b */ +#define REG_PCIE_INFRA_ACK_MASK_LSB (1U << 24) /* 1b */ +#define REG_PCIE_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */ +#define REG_PCIE_VRF18_ACK_MASK_LSB (1U << 26) /* 1b */ +#define REG_PCIE_DDREN_ACK_MASK_LSB (1U << 27) /* 1b */ + +/* PCM_REG0_DATA (0x10006000 + 0x100) */ +#define PCM_REG0_RF_LSB (1U << 0) /* 32b */ + +/* PCM_REG2_DATA (0x10006000 + 0x104) */ +#define PCM_REG2_RF_LSB (1U << 0) /* 32b */ + +/* PCM_REG6_DATA (0x10006000 + 0x108) */ +#define PCM_REG6_RF_LSB (1U << 0) /* 32b */ + +/* PCM_REG7_DATA (0x10006000 + 0x10C) */ +#define PCM_REG7_RF_LSB (1U << 0) /* 32b */ + +/* PCM_REG13_DATA (0x10006000 + 0x110) */ +#define PCM_REG13_RF_LSB (1U << 0) /* 32b */ + +/* SRC_REQ_STA_0 (0x10006000 + 0x114) */ +#define MD_0_SRCCLKENA_LSB (1U << 0) /* 1b */ +#define MD_0_INFRA_REQ_LSB (1U << 1) /* 1b */ +#define MD_0_APSRC_REQ_LSB (1U << 2) /* 1b */ +#define MD_0_VRF18_REQ_LSB (1U << 4) /* 1b */ +#define MD_0_DDREN_REQ_LSB (1U << 5) /* 1b */ +#define MD_1_SRCCLKENA_LSB (1U << 6) /* 1b */ +#define MD_1_INFRA_REQ_LSB (1U << 7) /* 1b */ +#define MD_1_APSRC_REQ_LSB (1U << 8) /* 1b */ +#define MD_1_VRF18_REQ_LSB (1U << 10) /* 1b */ +#define MD_1_DDREN_REQ_LSB (1U << 11) /* 1b */ +#define CONN_SRCCLKENA_LSB (1U << 12) /* 1b */ +#define CONN_SRCCLKENB_LSB (1U << 13) /* 1b */ +#define CONN_INFRA_REQ_LSB (1U << 14) /* 1b */ +#define CONN_APSRC_REQ_LSB (1U << 15) /* 1b */ +#define CONN_VRF18_REQ_LSB (1U << 16) /* 1b */ +#define CONN_DDREN_REQ_LSB (1U << 17) /* 1b */ +#define SRCCLKENI_LSB (1U << 18) /* 3b */ +#define SSPM_SRCCLKENA_LSB (1U << 21) /* 1b */ +#define SSPM_INFRA_REQ_LSB (1U << 22) /* 1b */ +#define SSPM_APSRC_REQ_LSB (1U << 23) /* 1b */ +#define SSPM_VRF18_REQ_LSB (1U << 24) /* 1b */ +#define SSPM_DDREN_REQ_LSB (1U << 25) /* 1b */ +#define DISP0_APSRC_REQ_LSB (1U << 26) /* 1b */ +#define DISP0_DDREN_REQ_LSB (1U << 27) /* 1b */ +#define DISP1_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define DISP1_DDREN_REQ_LSB (1U << 29) /* 1b */ +#define DVFSRC_EVENT_TRIGGER_LSB (1U << 30) /* 1b */ + +/* SRC_REQ_STA_1 (0x10006000 + 0x118) */ +#define SCP_SRCCLKENA_LSB (1U << 0) /* 1b */ +#define SCP_INFRA_REQ_LSB (1U << 1) /* 1b */ +#define SCP_APSRC_REQ_LSB (1U << 2) /* 1b */ +#define SCP_VRF18_REQ_LSB (1U << 3) /* 1b */ +#define SCP_DDREN_REQ_LSB (1U << 4) /* 1b */ +#define AUDIO_DSP_SRCCLKENA_LSB (1U << 5) /* 1b */ +#define AUDIO_DSP_INFRA_REQ_LSB (1U << 6) /* 1b */ +#define AUDIO_DSP_APSRC_REQ_LSB (1U << 7) /* 1b */ +#define AUDIO_DSP_VRF18_REQ_LSB (1U << 8) /* 1b */ +#define AUDIO_DSP_DDREN_REQ_LSB (1U << 9) /* 1b */ +#define UFS_SRCCLKENA_LSB (1U << 10) /* 1b */ +#define UFS_INFRA_REQ_LSB (1U << 11) /* 1b */ +#define UFS_APSRC_REQ_LSB (1U << 12) /* 1b */ +#define UFS_VRF18_REQ_LSB (1U << 13) /* 1b */ +#define UFS_DDREN_REQ_LSB (1U << 14) /* 1b */ +#define GCE_INFRA_REQ_LSB (1U << 15) /* 1b */ +#define GCE_APSRC_REQ_LSB (1U << 16) /* 1b */ +#define GCE_VRF18_REQ_LSB (1U << 17) /* 1b */ +#define GCE_DDREN_REQ_LSB (1U << 18) /* 1b */ +#define INFRASYS_APSRC_REQ_LSB (1U << 19) /* 1b */ +#define INFRASYS_DDREN_REQ_LSB (1U << 20) /* 1b */ +#define MSDC0_SRCCLKENA_LSB (1U << 21) /* 1b */ +#define MSDC0_INFRA_REQ_LSB (1U << 22) /* 1b */ +#define MSDC0_APSRC_REQ_LSB (1U << 23) /* 1b */ +#define MSDC0_VRF18_REQ_LSB (1U << 24) /* 1b */ +#define MSDC0_DDREN_REQ_LSB (1U << 25) /* 1b */ +#define MSDC1_SRCCLKENA_LSB (1U << 26) /* 1b */ +#define MSDC1_INFRA_REQ_LSB (1U << 27) /* 1b */ +#define MSDC1_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define MSDC1_VRF18_REQ_LSB (1U << 29) /* 1b */ +#define MSDC1_DDREN_REQ_LSB (1U << 30) /* 1b */ + +/* SRC_REQ_STA_2 (0x10006000 + 0x11C) */ +#define MCUSYS_MERGE_DDR_EN_LSB (1U << 0) /* 9b */ +#define EMI_SELF_REFRESH_CH_LSB (1U << 9) /* 2b */ +#define SW2SPM_WAKEUP_LSB (1U << 11) /* 4b */ +#define SC_ADSP2SPM_WAKEUP_LSB (1U << 15) /* 1b */ +#define SC_SSPM2SPM_WAKEUP_LSB (1U << 16) /* 4b */ +#define SRC_REQ_STA_2_SC_SCP2SPM_WAKEUP_LSB (1U << 20) /* 1b */ +#define SPM_RESERVED_SRCCLKENA_LSB (1U << 21) /* 1b */ +#define SPM_RESERVED_INFRA_REQ_LSB (1U << 22) /* 1b */ +#define SPM_RESERVED_APSRC_REQ_LSB (1U << 23) /* 1b */ +#define SPM_RESERVED_VRF18_REQ_LSB (1U << 24) /* 1b */ +#define SPM_RESERVED_DDREN_REQ_LSB (1U << 25) /* 1b */ +#define MCUPM_SRCCLKENA_LSB (1U << 26) /* 1b */ +#define MCUPM_INFRA_REQ_LSB (1U << 27) /* 1b */ +#define MCUPM_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define MCUPM_VRF18_REQ_LSB (1U << 29) /* 1b */ +#define MCUPM_DDREN_REQ_LSB (1U << 30) /* 1b */ + +/* PCM_TIMER_OUT (0x10006000 + 0x120) */ +#define PCM_TIMER_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_OUT (0x10006000 + 0x124) */ +#define PCM_WDT_TIMER_VAL_OUT_LSB (1U << 0) /* 32b */ + +/* SPM_IRQ_STA (0x10006000 + 0x128) */ +#define TWAM_IRQ_LSB (1U << 2) /* 1b */ +#define PCM_IRQ_LSB (1U << 3) /* 1b */ + +/* SRC_REQ_STA_4 (0x10006000 + 0x12C) */ +#define APU_SRCCLKENA_LSB (1U << 0) /* 1b */ +#define APU_INFRA_REQ_LSB (1U << 1) /* 1b */ +#define APU_APSRC_REQ_LSB (1U << 2) /* 1b */ +#define APU_VRF18_REQ_LSB (1U << 3) /* 1b */ +#define APU_DDREN_REQ_LSB (1U << 4) /* 1b */ +#define BAK_PSRI_SRCCLKENA_LSB (1U << 5) /* 1b */ +#define BAK_PSRI_INFRA_REQ_LSB (1U << 6) /* 1b */ +#define BAK_PSRI_APSRC_REQ_LSB (1U << 7) /* 1b */ +#define BAK_PSRI_VRF18_REQ_LSB (1U << 8) /* 1b */ +#define BAK_PSRI_DDREN_REQ_LSB (1U << 9) /* 1b */ +#define MSDC2_SRCCLKENA_LSB (1U << 10) /* 1b */ +#define MSDC2_INFRA_REQ_LSB (1U << 11) /* 1b */ +#define MSDC2_APSRC_REQ_LSB (1U << 12) /* 1b */ +#define MSDC2_VRF18_REQ_LSB (1U << 13) /* 1b */ +#define MSDC2_DDREN_REQ_LSB (1U << 14) /* 1b */ +#define PCIE_SRCCLKENA_LSB (1U << 15) /* 1b */ +#define PCIE_INFRA_REQ_LSB (1U << 16) /* 1b */ +#define PCIE_APSRC_REQ_LSB (1U << 17) /* 1b */ +#define PCIE_VRF18_REQ_LSB (1U << 18) /* 1b */ +#define PCIE_DDREN_REQ_LSB (1U << 19) /* 1b */ +#define DPMAIF_SRCCLKENA_LSB (1U << 20) /* 1b */ +#define DPMAIF_INFRA_REQ_LSB (1U << 21) /* 1b */ +#define DPMAIF_APSRC_REQ_LSB (1U << 22) /* 1b */ +#define DPMAIF_VRF18_REQ_LSB (1U << 23) /* 1b */ +#define DPMAIF_DDREN_REQ_LSB (1U << 24) /* 1b */ +#define AFE_SRCCLKENA_LSB (1U << 25) /* 1b */ +#define AFE_INFRA_REQ_LSB (1U << 26) /* 1b */ +#define AFE_APSRC_REQ_LSB (1U << 27) /* 1b */ +#define AFE_VRF18_REQ_LSB (1U << 28) /* 1b */ +#define AFE_DDREN_REQ_LSB (1U << 29) /* 1b */ + +/* MD32PCM_WAKEUP_STA (0x10006000 + 0x130) */ +#define MD32PCM_WAKEUP_STA_LSB (1U << 0) /* 32b */ + +/* MD32PCM_EVENT_STA (0x10006000 + 0x134) */ +#define MD32PCM_EVENT_STA_LSB (1U << 0) /* 32b */ + +/* SPM_WAKEUP_STA (0x10006000 + 0x138) */ +#define SPM_WAKEUP_EVENT_L_LSB (1U << 0) /* 32b */ + +/* SPM_WAKEUP_EXT_STA (0x10006000 + 0x13C) */ +#define EXT_WAKEUP_EVENT_LSB (1U << 0) /* 32b */ + +/* SPM_WAKEUP_MISC (0x10006000 + 0x140) */ +#define GIC_WAKEUP_LSB (1U << 0) /* 10b */ +#define DVFSRC_IRQ_LSB (1U << 16) /* 1b */ +#define SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB (1U << 17) /* 1b */ +#define PCM_TIMER_EVENT_LSB (1U << 18) /* 1b */ +#define PMIC_EINT_OUT_B_LSB (1U << 19) /* 2b */ +#define TWAM_IRQ_B_LSB (1U << 21) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_0_LSB (1U << 25) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_1_LSB (1U << 26) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_2_LSB (1U << 27) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_3_LSB (1U << 28) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_ALL_LSB (1U << 29) /* 1b */ +#define PMIC_IRQ_ACK_LSB (1U << 30) /* 1b */ +#define PMIC_SCP_IRQ_LSB (1U << 31) /* 1b */ + +/* MM_DVFS_HALT (0x10006000 + 0x144) */ +#define MM_DVFS_HALT_LSB (1U << 0) /* 5b */ + +/* BUS_PROTECT_RDY (0x10006000 + 0x150) */ +#define PROTECT_READY_LSB (1U << 0) /* 32b */ + +/* BUS_PROTECT1_RDY (0x10006000 + 0x154) */ +#define PROTECT1_READY_LSB (1U << 0) /* 32b */ + +/* BUS_PROTECT2_RDY (0x10006000 + 0x158) */ +#define PROTECT2_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT3_RDY (0x10006000 + 0x15C) */ + +#define PROTECT3_READY_LSB (1U << 0) /* 32b */ +/* SUBSYS_IDLE_STA (0x10006000 + 0x160) */ +#define SUBSYS_IDLE_SIGNALS_LSB (1U << 0) /* 32b */ +/* PCM_STA (0x10006000 + 0x164) */ + +#define PCM_CK_SEL_O_LSB (1U << 0) /* 4b */ +#define EXT_SRC_STA_LSB (1U << 4) /* 3b */ + +/* SRC_REQ_STA_3 (0x10006000 + 0x168) */ +#define CCIF_EVENT_STATE_LSB (1U << 0) /* 1b */ +#define F26M_STATE_LSB (1U << 16) /* 1b */ +#define INFRA_STATE_LSB (1U << 17) /* 1b */ +#define APSRC_STATE_LSB (1U << 18) /* 1b */ +#define VRF18_STATE_LSB (1U << 19) /* 1b */ +#define DDREN_STATE_LSB (1U << 20) /* 1b */ +#define DVFS_STATE_LSB (1U << 21) /* 1b */ +#define SW_MAILBOX_STATE_LSB (1U << 22) /* 1b */ +#define SSPM_MAILBOX_STATE_LSB (1U << 23) /* 1b */ +#define ADSP_MAILBOX_STATE_LSB (1U << 24) /* 1b */ +#define SCP_MAILBOX_STATE_LSB (1U << 25) /* 1b */ + +/* PWR_STATUS (0x10006000 + 0x16C) */ +#define PWR_STATUS_LSB (1U << 0) /* 32b */ + +/* PWR_STATUS_2ND (0x10006000 + 0x170) */ +#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */ + +/* CPU_PWR_STATUS (0x10006000 + 0x174) */ +#define MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 1) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 3) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 4) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 5) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 6) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 7) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 8) /* 1b */ +#define MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 9) /* 1b */ + +/* OTHER_PWR_STATUSi (0x10006000 + 0x178) */ +#define OTHER_PWR_STATUS_LSB (1U << 0) /* 32b */ + +/* SPM_VTCXO_EVENT_COUNT_STA (0x10006000 + 0x17C) */ +#define SPM_SRCCLKENA_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_SRCCLKENA_WAKE_COUNT_LSB (1U << 16) /* 16b */ + +/* SPM_INFRA_EVENT_COUNT_STA (0x10006000 + 0x180) */ +#define SPM_INFRA_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_INFRA_WAKE_COUNT_LSB (1U << 16) /* 16b */ + +/* SPM_VRF18_EVENT_COUNT_STA (0x10006000 + 0x184) */ +#define SPM_VRF18_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_VRF18_WAKE_COUNT_LSB (1U << 16) /* 16b */ + +/* SPM_APSRC_EVENT_COUNT_STA (0x10006000 + 0x188) */ +#define SPM_APSRC_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_APSRC_WAKE_COUNT_LSB (1U << 16) /* 16b */ + +/* SPM_DDREN_EVENT_COUNT_STA (0x10006000 + 0x18C) */ +#define SPM_DDREN_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_DDREN_WAKE_COUNT_LSB (1U << 16) /* 16b */ + +/* MD32PCM_STA (0x10006000 + 0x190) */ +#define MD32PCM_HALT_LSB (1U << 0) /* 1b */ +#define MD32PCM_GATED_LSB (1U << 1) /* 1b */ + +/* MD32PCM_PC (0x10006000 + 0x194) */ +#define MON_PC_LSB (1U << 0) /* 32b */ + +/* DVFSRC_EVENT_STA (0x10006000 + 0x1A4) */ +#define DVFSRC_EVENT_LSB (1U << 0) /* 32b */ + +/* BUS_PROTECT4_RDY (0x10006000 + 0x1A8) */ +#define PROTECT4_READY_LSB (1U << 0) /* 32b */ + +/* BUS_PROTECT5_RDY (0x10006000 + 0x1AC) */ +#define PROTECT5_READY_LSB (1U << 0) /* 32b */ + +/* BUS_PROTECT6_RDY (0x10006000 + 0x1B0) */ +#define PROTECT6_READY_LSB (1U << 0) /* 32b */ + +/* BUS_PROTECT7_RDY (0x10006000 + 0x1B4) */ +#define PROTECT7_READY_LSB (1U << 0) /* 32b */ + +/* BUS_PROTECT8_RDY (0x10006000 + 0x1B8) */ +#define PROTECT8_READY_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_LAST_STA0 (0x10006000 + 0x1D0) */ +#define LAST_IDLE_CNT_0_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_LAST_STA1 (0x10006000 + 0x1D4) */ +#define LAST_IDLE_CNT_1_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_LAST_STA2 (0x10006000 + 0x1D8) */ +#define LAST_IDLE_CNT_2_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_LAST_STA3 (0x10006000 + 0x1DC) */ +#define LAST_IDLE_CNT_3_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_CURR_STA0 (0x10006000 + 0x1E0) */ +#define CURRENT_IDLE_CNT_0_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_CURR_STA1 (0x10006000 + 0x1E4) */ +#define CURRENT_IDLE_CNT_1_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_CURR_STA2 (0x10006000 + 0x1E8) */ +#define CURRENT_IDLE_CNT_2_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_CURR_STA3 (0x10006000 + 0x1EC) */ +#define CURRENT_IDLE_CNT_3_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_TIMER_OUT (0x10006000 + 0x1F0) */ +#define TWAM_TIMER_LSB (1U << 0) /* 32b */ + +/* SPM_CG_CHECK_STA (0x10006000 + 0x1F4) */ +#define SPM_CG_CHECK_SLEEP_REQ_0_LSB (1U << 0) /* 1b */ +#define SPM_CG_CHECK_SLEEP_REQ_1_LSB (1U << 1) /* 1b */ +#define SPM_CG_CHECK_SLEEP_REQ_2_LSB (1U << 2) /* 1b */ + +/* SPM_DVFS_STA (0x10006000 + 0x1F8) */ +#define TARGET_DVFS_LEVEL_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_OPP_STA (0x10006000 + 0x1FC) */ +#define TARGET_DVFS_OPP_LSB (1U << 0) /* 5b */ +#define CURRENT_DVFS_OPP_LSB (1U << 5) /* 5b */ +#define RELAY_DVFS_OPP_LSB (1U << 10) /* 5b */ + +/* SPM_MCUSYS_PWR_CON (0x10006000 + 0x200) */ +#define MCUSYS_SPMC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MCUSYS_SPMC_PWR_ON_LSB (1U << 2) /* 1b */ +#define MCUSYS_SPMC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MCUSYS_SPMC_RESETPWRON_CONFIG_LSB (1U << 5) /* 1b */ +#define MCUSYS_SPMC_DORMANT_EN_LSB (1U << 6) /* 1b */ +#define MCUSYS_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */ +#define SPM_MCUSYS_PWR_CON_MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 31) /* 1b */ + +/* SPM_CPUTOP_PWR_CON (0x10006000 + 0x204) */ +#define MP0_SPMC_PWR_RST_B_CPUTOP_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPUTOP_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_PWR_CLK_DIS_CPUTOP_LSB (1U << 4) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPUTOP_LSB (1U << 5) /* 1b */ +#define MP0_SPMC_DORMANT_EN_CPUTOP_LSB (1U << 6) /* 1b */ +#define MP0_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */ +#define MP0_VSRAM_EXT_OFF_LSB (1U << 8) /* 1b */ +#define SPM_CPUTOP_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 31) /* 1b */ +/* SPM_CPU0_PWR_CON (0x10006000 + 0x208) */ +#define MP0_SPMC_PWR_RST_B_CPU0_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU0_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU0_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU0_LSB (1U << 7) /* 1b */ +#define SPM_CPU0_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 31) /* 1b */ + +/* SPM_CPU1_PWR_CON (0x10006000 + 0x20C) */ +#define MP0_SPMC_PWR_RST_B_CPU1_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU1_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU1_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU1_LSB (1U << 7) /* 1b */ +#define SPM_CPU1_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 31) /* 1b */ + +/* SPM_CPU2_PWR_CON (0x10006000 + 0x210) */ +#define MP0_SPMC_PWR_RST_B_CPU2_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU2_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU2_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU2_LSB (1U << 7) /* 1b */ +#define SPM_CPU2_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 31) /* 1b */ + +/* SPM_CPU3_PWR_CON (0x10006000 + 0x214) */ +#define MP0_SPMC_PWR_RST_B_CPU3_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU3_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU3_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU3_LSB (1U << 7) /* 1b */ +#define SPM_CPU3_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 31) /* 1b */ + +/* SPM_CPU4_PWR_CON (0x10006000 + 0x218) */ +#define MP0_SPMC_PWR_RST_B_CPU4_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU4_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU4_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU4_LSB (1U << 7) /* 1b */ +#define SPM_CPU4_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 31) /* 1b */ + +/* SPM_CPU5_PWR_CON (0x10006000 + 0x21C) */ +#define MP0_SPMC_PWR_RST_B_CPU5_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU5_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU5_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU5_LSB (1U << 7) /* 1b */ +#define SPM_CPU5_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 31) /* 1b */ + +/* SPM_CPU6_PWR_CON (0x10006000 + 0x220) */ +#define MP0_SPMC_PWR_RST_B_CPU6_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU6_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU6_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU6_LSB (1U << 7) /* 1b */ +#define SPM_CPU6_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 31) /* 1b */ + +/* SPM_CPU7_PWR_CON (0x10006000 + 0x224) */ +#define MP0_SPMC_PWR_RST_B_CPU7_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU7_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU7_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU7_LSB (1U << 7) /* 1b */ +#define SPM_CPU7_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 31) /* 1b */ + +/* ARMPLL_CLK_CON (0x10006000 + 0x22C) */ +#define SC_ARM_FHC_PAUSE_LSB (1U << 0) /* 6b */ +#define SC_ARM_CK_OFF_LSB (1U << 6) /* 6b */ +#define SC_ARMPLL_OFF_LSB (1U << 12) /* 1b */ +#define SC_ARMBPLL_OFF_LSB (1U << 13) /* 1b */ +#define SC_ARMBPLL1_OFF_LSB (1U << 14) /* 1b */ +#define SC_ARMBPLL2_OFF_LSB (1U << 15) /* 1b */ +#define SC_ARMBPLL3_OFF_LSB (1U << 16) /* 1b */ +#define SC_CCIPLL_CKOFF_LSB (1U << 17) /* 1b */ +#define SC_ARMDDS_OFF_LSB (1U << 18) /* 1b */ +#define SC_ARMBPLL_S_OFF_LSB (1U << 19) /* 1b */ +#define SC_ARMBPLL1_S_OFF_LSB (1U << 20) /* 1b */ +#define SC_ARMBPLL2_S_OFF_LSB (1U << 21) /* 1b */ +#define SC_ARMBPLL3_S_OFF_LSB (1U << 22) /* 1b */ +#define SC_CCIPLL_PWROFF_LSB (1U << 23) /* 1b */ +#define SC_ARMPLLOUT_OFF_LSB (1U << 24) /* 1b */ +#define SC_ARMBPLLOUT_OFF_LSB (1U << 25) /* 1b */ +#define SC_ARMBPLLOUT1_OFF_LSB (1U << 26) /* 1b */ +#define SC_ARMBPLLOUT2_OFF_LSB (1U << 27) /* 1b */ +#define SC_ARMBPLLOUT3_OFF_LSB (1U << 28) /* 1b */ +#define SC_CCIPLL_OUT_OFF_LSB (1U << 29) /* 1b */ + +/* MCUSYS_IDLE_STA (0x10006000 + 0x230) */ +#define ARMBUS_IDLE_TO_26M_LSB (1U << 0) /* 1b */ +#define MP0_CLUSTER_IDLE_TO_PWR_OFF_LSB (1U << 1) /* 1b */ +#define MCUSYS_DDR_EN_0_LSB (1U << 2) /* 1b */ +#define MCUSYS_DDR_EN_1_LSB (1U << 3) /* 1b */ +#define MCUSYS_DDR_EN_2_LSB (1U << 4) /* 1b */ +#define MCUSYS_DDR_EN_3_LSB (1U << 5) /* 1b */ +#define MCUSYS_DDR_EN_4_LSB (1U << 6) /* 1b */ +#define MCUSYS_DDR_EN_5_LSB (1U << 7) /* 1b */ +#define MCUSYS_DDR_EN_6_LSB (1U << 8) /* 1b */ +#define MCUSYS_DDR_EN_7_LSB (1U << 9) /* 1b */ +#define MP0_CPU_IDLE_TO_PWR_OFF_LSB (1U << 16) /* 8b */ +#define WFI_AF_SEL_LSB (1U << 24) /* 8b */ + +/* GIC_WAKEUP_STA (0x10006000 + 0x234) */ +#define GIC_WAKEUP_STA_GIC_WAKEUP_LSB (1U << 10) /* 10b */ + +/* CPU_SPARE_CON (0x10006000 + 0x238) */ +#define CPU_SPARE_CON_LSB (1U << 0) /* 32b */ + +/* CPU_SPARE_CON_SET (0x10006000 + 0x23C) */ +#define CPU_SPARE_CON_SET_LSB (1U << 0) /* 32b */ + +/* CPU_SPARE_CON_CLR (0x10006000 + 0x240) */ +#define CPU_SPARE_CON_CLR_LSB (1U << 0) /* 32b */ + +/* ARMPLL_CLK_SEL (0x10006000 + 0x244) */ +#define ARMPLL_CLK_SEL_LSB (1U << 0) /* 15b */ + +/* EXT_INT_WAKEUP_REQ (0x10006000 + 0x248) */ +#define EXT_INT_WAKEUP_REQ_LSB (1U << 0) /* 10b */ + +/* EXT_INT_WAKEUP_REQ_SET (0x10006000 + 0x24C) */ +#define EXT_INT_WAKEUP_REQ_SET_LSB (1U << 0) /* 10b */ + +/* EXT_INT_WAKEUP_REQ_CLR (0x10006000 + 0x250) */ +#define EXT_INT_WAKEUP_REQ_CLR_LSB (1U << 0) /* 10b */ + +/* CPU_IRQ_MASK (0x10006000 + 0x260) */ +#define CPU_IRQ_MASK_LSB (1U << 0) /* 8b */ + +/* CPU_IRQ_MASK_SET (0x10006000 + 0x264) */ +#define CPU_IRQ_MASK_SET_LSB (1U << 0) /* 8b */ + +/* CPU_IRQ_MASK_CLR (0x10006000 + 0x268) */ +#define CPU_IRQ_MASK_CLR_LSB (1U << 0) /* 8b */ + +/* CPU_WFI_EN (0x10006000 + 0x280) */ +#define CPU_WFI_EN_LSB (1U << 0) /* 8b */ + +/* CPU_WFI_EN_SET (0x10006000 + 0x284) */ +#define CPU_WFI_EN_SET_LSB (1U << 0) /* 8b */ + +/* CPU_WFI_EN_CLR (0x10006000 + 0x288) */ +#define CPU_WFI_EN_CLR_LSB (1U << 0) /* 8b */ + +/* ROOT_CPUTOP_ADDR (0x10006000 + 0x2A0) */ +#define ROOT_CPUTOP_ADDR_LSB (1U << 0) /* 32b */ + +/* ROOT_CORE_ADDR (0x10006000 + 0x2A4) */ +#define ROOT_CORE_ADDR_LSB (1U << 0) /* 32b */ + +/* SPM2SW_MAILBOX_0 (0x10006000 + 0x2D0) */ +#define SPM2SW_MAILBOX_0_LSB (1U << 0) /* 32b */ + +/* SPM2SW_MAILBOX_1 (0x10006000 + 0x2D4) */ +#define SPM2SW_MAILBOX_1_LSB (1U << 0) /* 32b */ + +/* SPM2SW_MAILBOX_2 (0x10006000 + 0x2D8) */ +#define SPM2SW_MAILBOX_2_LSB (1U << 0) /* 32b */ + +/* SPM2SW_MAILBOX_3 (0x10006000 + 0x2DC) */ +#define SPM2SW_MAILBOX_3_LSB (1U << 0) /* 32b */ + +/* SW2SPM_WAKEUP (0x10006000 + 0x2E0) */ +#define SW2SPM_WAKEUP_SW2SPM_WAKEUP_LSB (1U << 0) /* 4b */ + +/* SW2SPM_WAKEUP_SET (0x10006000 + 0x2E4) */ +#define SW2SPM_WAKEUP_SET_LSB (1U << 0) /* 4b */ + +/* SW2SPM_WAKEUP_CLR (0x10006000 + 0x2E8) */ +#define SW2SPM_WAKEUP_CLR_LSB (1U << 0) /* 4b */ + +/* SW2SPM_MAILBOX_0 (0x10006000 + 0x2EC) */ +#define SW2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */ + +/* SW2SPM_MAILBOX_1 (0x10006000 + 0x2F0) */ +#define SW2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */ + +/* SW2SPM_MAILBOX_2 (0x10006000 + 0x2F4) */ +#define SW2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */ + +/* SW2SPM_MAILBOX_3 (0x10006000 + 0x2F8) */ +#define SW2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */ + +/* SW2SPM_CFG (0x10006000 + 0x2FC) */ +#define SWU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */ + +/* MD1_PWR_CON (0x10006000 + 0x300) */ +#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MD1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MD1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* CONN_PWR_CON (0x10006000 + 0x304) */ +#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CONN_PWR_ON_LSB (1U << 2) /* 1b */ +#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ + +/* MFG0_PWR_CON (0x10006000 + 0x308) */ +#define MFG0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG0_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG0_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG0_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* MFG1_PWR_CON (0x10006000 + 0x30C) */ +#define MFG1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* MFG2_PWR_CON (0x10006000 + 0x310) */ +#define MFG2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG2_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* MFG3_PWR_CON (0x10006000 + 0x314) */ +#define MFG3_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG3_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG3_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG3_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG3_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG3_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* MFG4_PWR_CON (0x10006000 + 0x318) */ +#define MFG4_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG4_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG4_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG4_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG4_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG4_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG4_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* MFG5_PWR_CON (0x10006000 + 0x31C) */ +#define MFG5_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG5_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG5_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG5_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG5_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG5_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG5_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* MFG6_PWR_CON (0x10006000 + 0x320) */ +#define MFG6_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG6_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG6_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG6_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG6_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG6_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG6_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* IFR_PWR_CON (0x10006000 + 0x324) */ +#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IFR_PWR_ON_LSB (1U << 2) /* 1b */ +#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IFR_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* IFR_SUB_PWR_CON (0x10006000 + 0x328) */ +#define IFR_SUB_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IFR_SUB_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IFR_SUB_PWR_ON_LSB (1U << 2) /* 1b */ +#define IFR_SUB_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IFR_SUB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IFR_SUB_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IFR_SUB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* DPY_PWR_CON (0x10006000 + 0x32C) */ +#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DPY_PWR_ON_LSB (1U << 2) /* 1b */ +#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ + +/* DRAMC_MD32_PWR_CON (0x10006000 + 0x330) */ +#define DRAMC_MD32_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DRAMC_MD32_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DRAMC_MD32_PWR_ON_LSB (1U << 2) /* 1b */ +#define DRAMC_MD32_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DRAMC_MD32_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DRAMC_MD32_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DRAMC_MD32_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* ISP_PWR_CON (0x10006000 + 0x334) */ +#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ISP_PWR_ON_LSB (1U << 2) /* 1b */ +#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ISP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* ISP2_PWR_CON (0x10006000 + 0x338) */ +#define ISP2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ISP2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ISP2_PWR_ON_LSB (1U << 2) /* 1b */ +#define ISP2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ISP2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ISP2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_ISP2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* IPE_PWR_CON (0x10006000 + 0x33C) */ +#define IPE_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IPE_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IPE_PWR_ON_LSB (1U << 2) /* 1b */ +#define IPE_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IPE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IPE_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IPE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* VDE_PWR_CON (0x10006000 + 0x340) */ +#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VDE_PWR_ON_LSB (1U << 2) /* 1b */ +#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VDE_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* VDE2_PWR_CON (0x10006000 + 0x344) */ +#define VDE2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VDE2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VDE2_PWR_ON_LSB (1U << 2) /* 1b */ +#define VDE2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VDE2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VDE2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VDE2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* VEN_PWR_CON (0x10006000 + 0x348) */ +#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VEN_PWR_ON_LSB (1U << 2) /* 1b */ +#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VEN_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* VEN_CORE1_PWR_CON (0x10006000 + 0x34C) */ +#define VEN_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VEN_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VEN_CORE1_PWR_ON_LSB (1U << 2) /* 1b */ +#define VEN_CORE1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VEN_CORE1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VEN_CORE1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VEN_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* MDP_PWR_CON (0x10006000 + 0x350) */ +#define MDP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MDP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MDP_PWR_ON_LSB (1U << 2) /* 1b */ +#define MDP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MDP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MDP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MDP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* DIS_PWR_CON (0x10006000 + 0x354) */ +#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DIS_PWR_ON_LSB (1U << 2) /* 1b */ +#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DIS_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* AUDIO_PWR_CON (0x10006000 + 0x358) */ +#define AUDIO_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define AUDIO_PWR_ISO_LSB (1U << 1) /* 1b */ +#define AUDIO_PWR_ON_LSB (1U << 2) /* 1b */ +#define AUDIO_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define AUDIO_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define AUDIO_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_AUDIO_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* CAM_PWR_CON (0x10006000 + 0x35C) */ +#define CAM_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* CAM_RAWA_PWR_CON (0x10006000 + 0x360) */ +#define CAM_RAWA_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWA_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWA_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWA_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWA_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWA_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* CAM_RAWB_PWR_CON (0x10006000 + 0x364) */ +#define CAM_RAWB_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWB_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWB_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWB_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWB_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* CAM_RAWC_PWR_CON (0x10006000 + 0x368) */ +#define CAM_RAWC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWC_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWC_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWC_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWC_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWC_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* SYSRAM_CON (0x10006000 + 0x36C) */ +#define SYSRAM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SYSRAM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SYSRAM_SRAM_SLEEP_B_LSB (1U << 4) /* 4b */ +#define SYSRAM_SRAM_PDN_LSB (1U << 16) /* 4b */ + +/* SYSROM_CON (0x10006000 + 0x370) */ +#define SYSROM_SRAM_PDN_LSB (1U << 0) /* 8b */ + +/* SSPM_SRAM_CON (0x10006000 + 0x374) */ +#define SSPM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SSPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SSPM_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SSPM_SRAM_PDN_LSB (1U << 16) /* 1b */ + +/* SCP_SRAM_CON (0x10006000 + 0x378) */ +#define SCP_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SCP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SCP_SRAM_PDN_LSB (1U << 16) /* 1b */ + +/* DPY_SHU_SRAM_CON (0x10006000 + 0x37C) */ +#define DPY_SHU_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPY_SHU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPY_SHU_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */ +#define DPY_SHU_SRAM_PDN_LSB (1U << 16) /* 2b */ + +/* UFS_SRAM_CON (0x10006000 + 0x380) */ +#define UFS_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define UFS_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define UFS_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */ +#define UFS_SRAM_PDN_LSB (1U << 16) /* 8b */ + +/* DEVAPC_IFR_SRAM_CON (0x10006000 + 0x384) */ +#define DEVAPC_IFR_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_IFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_IFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */ +#define DEVAPC_IFR_SRAM_PDN_LSB (1U << 16) /* 6b */ + +/* DEVAPC_SUBIFR_SRAM_CON (0x10006000 + 0x388) */ +#define DEVAPC_SUBIFR_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_SUBIFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_SUBIFR_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */ +#define DEVAPC_SUBIFR_SRAM_PDN_LSB (1U << 16) /* 12b */ + +/* DEVAPC_ACP_SRAM_CON (0x10006000 + 0x38C) */ +#define DEVAPC_ACP_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_ACP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_ACP_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */ +#define DEVAPC_ACP_SRAM_PDN_LSB (1U << 16) /* 12b */ + +/* USB_SRAM_CON (0x10006000 + 0x390) */ +#define USB_SRAM_PDN_LSB (1U << 0) /* 9b */ + +/* DUMMY_SRAM_CONi (0x10006000 + 0x394) */ +#define DUMMY_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DUMMY_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DUMMY_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */ +#define DUMMY_SRAM_PDN_LSB (1U << 16) /* 12b */ + +/* MD_EXT_BUCK_ISO_CON (0x10006000 + 0x398) */ +#define VMODEM_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +#define VMD_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */ + +/* EXT_BUCK_ISO (0x10006000 + 0x39C) */ +#define VIMVO_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +#define GPU_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */ +#define ADSP_EXT_BUCK_ISO_LSB (1U << 2) /* 1b */ +#define IPU_EXT_BUCK_ISO_LSB (1U << 5) /* 3b */ + +/* DXCC_SRAM_CON (0x10006000 + 0x3A0) */ +#define DXCC_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DXCC_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DXCC_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */ +#define DXCC_SRAM_PDN_LSB (1U << 16) /* 8b */ + +/* MSDC_PWR_CON (0x10006000 + 0x3A4) */ +#define MSDC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MSDC_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MSDC_PWR_ON_LSB (1U << 2) /* 1b */ +#define MSDC_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MSDC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MSDC_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MSDC_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MSDC_SRAM_PDN_LSB (1U << 8) /* 5b */ +#define MSDC_SRAM_SLEEP_B_LSB (1U << 13) /* 5b */ +#define SC_MSDC_SRAM_PDN_ACK_LSB (1U << 18) /* 5b */ +#define SC_MSDC_SRAM_SLEEP_B_ACK_LSB (1U << 23) /* 5b */ + +/* DEBUGTOP_SRAM_CON (0x10006000 + 0x3A8) */ +#define DEBUGTOP_SRAM_PDN_LSB (1U << 0) /* 1b */ + +/* DP_TX_PWR_CON (0x10006000 + 0x3AC) */ +#define DP_TX_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DP_TX_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DP_TX_PWR_ON_LSB (1U << 2) /* 1b */ +#define DP_TX_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DP_TX_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DP_TX_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DP_TX_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* DPMAIF_SRAM_CON (0x10006000 + 0x3B0) */ +#define DPMAIF_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPMAIF_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPMAIF_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DPMAIF_SRAM_PDN_LSB (1U << 16) /* 1b */ + +/* DPY_SHU2_SRAM_CON (0x10006000 + 0x3B4) */ +#define DPY_SHU2_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPY_SHU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPY_SHU2_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */ +#define DPY_SHU2_SRAM_PDN_LSB (1U << 16) /* 12b */ + +/* DRAMC_MCU2_SRAM_CON (0x10006000 + 0x3B8) */ +#define DRAMC_MCU2_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DRAMC_MCU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DRAMC_MCU2_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */ +#define DRAMC_MCU2_SRAM_PDN_LSB (1U << 16) /* 12b */ + +/* DRAMC_MCU_SRAM_CON (0x10006000 + 0x3BC) */ +#define DRAMC_MCU_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DRAMC_MCU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DRAMC_MCU_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */ +#define DRAMC_MCU_SRAM_PDN_LSB (1U << 16) /* 12b */ + +/* MCUPM_PWR_CON (0x10006000 + 0x3C0) */ +#define MCUPM_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MCUPM_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MCUPM_PWR_ON_LSB (1U << 2) /* 1b */ +#define MCUPM_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MCUPM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MCUPM_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MCUPM_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MCUPM_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MCUPM_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */ +#define SC_MCUPM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +#define SC_MCUPM_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */ +#define MCUPM_WFI_LSB (1U << 14) /* 1b */ + +/* DPY2_PWR_CON (0x10006000 + 0x3C4) */ +#define DPY2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DPY2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DPY2_PWR_ON_LSB (1U << 2) /* 1b */ +#define DPY2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DPY2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DPY2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DPY2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* SPM_SRAM_CON (0x10006000 + 0x3C8) */ +#define SPM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define REG_SPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define REG_SPM_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */ +#define SPM_SRAM_PDN_LSB (1U << 16) /* 2b */ + +/* PERI_PWR_CON (0x10006000 + 0x3D0) */ +#define PERI_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define PERI_PWR_ISO_LSB (1U << 1) /* 1b */ +#define PERI_PWR_ON_LSB (1U << 2) /* 1b */ +#define PERI_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define PERI_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define PERI_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_PERI_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* NNA0_PWR_CON (0x10006000 + 0x3D4) */ +#define NNA0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define NNA0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define NNA0_PWR_ON_LSB (1U << 2) /* 1b */ +#define NNA0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define NNA0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define NNA0_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_NNA0_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* NNA1_PWR_CON (0x10006000 + 0x3D8) */ +#define NNA1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define NNA1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define NNA1_PWR_ON_LSB (1U << 2) /* 1b */ +#define NNA1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define NNA1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define NNA1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_NNA1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* NNA2_PWR_CON (0x10006000 + 0x3DC) */ +#define NNA2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define NNA2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define NNA2_PWR_ON_LSB (1U << 2) /* 1b */ +#define NNA2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define NNA2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define NNA2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_NNA2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* NNA_PWR_CON (0x10006000 + 0x3E0) */ +#define NNA_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define NNA_PWR_ISO_LSB (1U << 1) /* 1b */ +#define NNA_PWR_ON_LSB (1U << 2) /* 1b */ +#define NNA_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define NNA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define NNA_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_NNA_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ + +/* ADSP_PWR_CON (0x10006000 + 0x3E4) */ +#define ADSP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ADSP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ADSP_PWR_ON_LSB (1U << 2) /* 1b */ +#define ADSP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ADSP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ADSP_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define ADSP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define ADSP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define ADSP_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */ +#define SC_ADSP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +#define SC_ADSP_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */ + +/* DPY_SRAM_CON (0x10006000 + 0x3E8) */ +#define DPY_SRAM_PDN_LSB (1U << 16) /* 4b */ +#define SC_DPY_SRAM_PDN_ACK_LSB (1U << 24) /* 4b */ + +/* SPM_MEM_CK_SEL (0x10006000 + 0x400) */ +#define SC_MEM_CK_SEL_LSB (1U << 0) /* 1b */ +#define SPM2CKSYS_MEM_CK_MUX_UPDATE_LSB (1U << 1) /* 1b */ + +/* SPM_BUS_PROTECT_MASK_B (0x10006000 + 0X404) */ +#define SPM_BUS_PROTECT_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_BUS_PROTECT1_MASK_B (0x10006000 + 0x408) */ +#define SPM_BUS_PROTECT1_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_BUS_PROTECT2_MASK_B (0x10006000 + 0x40C) */ +#define SPM_BUS_PROTECT2_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_BUS_PROTECT3_MASK_B (0x10006000 + 0x410) */ +#define SPM_BUS_PROTECT3_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_BUS_PROTECT4_MASK_B (0x10006000 + 0x414) */ +#define SPM_BUS_PROTECT4_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_EMI_BW_MODE (0x10006000 + 0x418) */ +#define EMI_BW_MODE_LSB (1U << 0) /* 1b */ +#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */ +#define EMI_BW_MODE_2_LSB (1U << 2) /* 1b */ +#define EMI_BOOST_MODE_2_LSB (1U << 3) /* 1b */ +#define SPM_S1_MODE_CH_LSB (1U << 16) /* 2b */ + +/* AP2MD_PEER_WAKEUP (0x10006000 + 0x41C) */ +#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */ + +/* ULPOSC_CON (0x10006000 + 0x420) */ +#define ULPOSC_EN_LSB (1U << 0) /* 1b */ +#define ULPOSC_RST_LSB (1U << 1) /* 1b */ +#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */ +#define ULPOSC_CLK_SEL_LSB (1U << 3) /* 1b */ + +/* SPM2MM_CON (0x10006000 + 0x424) */ +#define SPM2MM_FORCE_ULTRA_LSB (1U << 0) /* 1b */ +#define SPM2MM_DBL_OSTD_ACT_LSB (1U << 1) /* 1b */ +#define SPM2MM_ULTRAREQ_LSB (1U << 2) /* 1b */ +#define SPM2MD_ULTRAREQ_LSB (1U << 3) /* 1b */ +#define SPM2ISP_ULTRAREQ_LSB (1U << 4) /* 1b */ +#define MM2SPM_FORCE_ULTRA_ACK_D2T_LSB (1U << 16) /* 1b */ +#define MM2SPM_DBL_OSTD_ACT_ACK_D2T_LSB (1U << 17) /* 1b */ +#define SPM2ISP_ULTRAACK_D2T_LSB (1U << 18) /* 1b */ +#define SPM2MM_ULTRAACK_D2T_LSB (1U << 19) /* 1b */ +#define SPM2MD_ULTRAACK_D2T_LSB (1U << 20) /* 1b */ + +/* SPM_BUS_PROTECT5_MASK_B (0x10006000 + 0x428) */ +#define SPM_BUS_PROTECT5_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM2MCUPM_CON (0x10006000 + 0x42C) */ +#define SPM2MCUPM_SW_RST_B_LSB (1U << 0) /* 1b */ +#define SPM2MCUPM_SW_INT_LSB (1U << 1) /* 1b */ + +/* AP_MDSRC_REQ (0x10006000 + 0x430) */ +#define AP_MDSMSRC_REQ_LSB (1U << 0) /* 1b */ +#define AP_L1SMSRC_REQ_LSB (1U << 1) /* 1b */ +#define AP_MD2SRC_REQ_LSB (1U << 2) /* 1b */ +#define AP_MDSMSRC_ACK_LSB (1U << 4) /* 1b */ +#define AP_L1SMSRC_ACK_LSB (1U << 5) /* 1b */ +#define AP_MD2SRC_ACK_LSB (1U << 6) /* 1b */ + +/* SPM2EMI_ENTER_ULPM (0x10006000 + 0x434) */ +#define SPM2EMI_ENTER_ULPM_LSB (1U << 0) /* 1b */ + +/* SPM2MD_DVFS_CON (0x10006000 + 0x438) */ +#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 32b */ + +/* MD2SPM_DVFS_CON (0x10006000 + 0x43C) */ +#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 32b */ + +/* SPM_BUS_PROTECT6_MASK_B (0x10006000 + 0X440) */ +#define SPM_BUS_PROTECT6_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_BUS_PROTECT7_MASK_B (0x10006000 + 0x444) */ +#define SPM_BUS_PROTECT7_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_BUS_PROTECT8_MASK_B (0x10006000 + 0x448) */ +#define SPM_BUS_PROTECT8_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_PLL_CON (0x10006000 + 0x44C) */ +#define SC_MAINPLLOUT_OFF_LSB (1U << 0) /* 1b */ +#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */ +#define SC_SPAREPLLOUT_OFF_LSB (1U << 2) /* 2b */ +#define SC_MAINPLL_OFF_LSB (1U << 4) /* 1b */ +#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */ +#define SC_SPAREPLL_OFF_LSB (1U << 6) /* 2b */ +#define SC_MAINPLL_S_OFF_LSB (1U << 8) /* 1b */ +#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */ +#define SC_SPAREPLL_S_OFF_LSB (1U << 10) /* 2b */ +#define SC_SPARE_CK_OFF_LSB (1U << 12) /* 4b */ +#define SC_SMI_CK_OFF_LSB (1U << 16) /* 1b */ +#define SC_MD32K_CK_OFF_LSB (1U << 17) /* 1b */ +#define SC_CKSQ1_OFF_LSB (1U << 18) /* 1b */ +#define SC_AXI_MEM_CK_OFF_LSB (1U << 19) /* 1b */ +#define SC_CLK_BACKUP_LSB (1U << 20) /* 12b */ + +/* RC_SPM_CTRL (0x10006000 + 0x450) */ +#define SPM_AP_26M_RDY_LSB (1U << 0) /* 1b */ +#define SPM2RC_DMY_CTRL_LSB (1U << 2) /* 6b */ +#define RC2SPM_SRCCLKENO_0_ACK_LSB (1U << 16) /* 1b */ + +/* SPM_DRAM_MCU_SW_CON_0 (0x10006000 + 0x454) */ +#define SW_DDR_PST_REQ_LSB (1U << 0) /* 2b */ +#define SW_DDR_PST_ABORT_REQ_LSB (1U << 2) /* 2b */ + +/* SPM_DRAM_MCU_SW_CON_1 (0x10006000 + 0x458) */ +#define SW_DDR_PST_CH0_LSB (1U << 0) /* 32b */ + +/* SPM_DRAM_MCU_SW_CON_2 (0x10006000 + 0x45C) */ +#define SW_DDR_PST_CH1_LSB (1U << 0) /* 32b */ + +/* SPM_DRAM_MCU_SW_CON_3 (0x10006000 + 0x460) */ +#define SW_DDR_RESERVED_CH0_LSB (1U << 0) /* 32b */ + +/* SPM_DRAM_MCU_SW_CON_4 (0x10006000 + 0x464) */ +#define SW_DDR_RESERVED_CH1_LSB (1U << 0) /* 32b */ + +/* SPM_DRAM_MCU_STA_0 (0x10006000 + 0x468) */ +#define SC_DDR_PST_ACK_LSB (1U << 0) /* 2b */ +#define SC_DDR_PST_ABORT_ACK_LSB (1U << 2) /* 2b */ + +/* SPM_DRAM_MCU_STA_1 (0x10006000 + 0x46C) */ +#define SC_DDR_CUR_PST_STA_CH0_LSB (1U << 0) /* 32b */ + +/* SPM_DRAM_MCU_STA_2 (0x10006000 + 0x470) */ +#define SC_DDR_CUR_PST_STA_CH1_LSB (1U << 0) /* 32b */ + +/* SPM_DRAM_MCU_SW_SEL_0 (0x10006000 + 0x474) */ +#define SW_DDR_PST_REQ_SEL_LSB (1U << 0) /* 2b */ +#define SW_DDR_PST_SEL_LSB (1U << 2) /* 2b */ +#define SW_DDR_PST_ABORT_REQ_SEL_LSB (1U << 4) /* 2b */ +#define SW_DDR_RESERVED_SEL_LSB (1U << 6) /* 2b */ +#define SW_DDR_PST_ACK_SEL_LSB (1U << 8) /* 2b */ +#define SW_DDR_PST_ABORT_ACK_SEL_LSB (1U << 10) /* 2b */ + +/* RELAY_DVFS_LEVEL (0x10006000 + 0x478) */ +#define RELAY_DVFS_LEVEL_LSB (1U << 0) /* 32b */ + +/* DRAMC_DPY_CLK_SW_CON_0 (0x10006000 + 0x480) */ +#define SW_PHYPLL_EN_LSB (1U << 0) /* 2b */ +#define SW_DPY_VREF_EN_LSB (1U << 2) /* 2b */ +#define SW_DPY_DLL_CK_EN_LSB (1U << 4) /* 2b */ +#define SW_DPY_DLL_EN_LSB (1U << 6) /* 2b */ +#define SW_DPY_2ND_DLL_EN_LSB (1U << 8) /* 2b */ +#define SW_MEM_CK_OFF_LSB (1U << 10) /* 2b */ +#define SW_DMSUS_OFF_LSB (1U << 12) /* 2b */ +#define SW_DPY_MODE_SW_LSB (1U << 14) /* 2b */ +#define SW_EMI_CLK_OFF_LSB (1U << 16) /* 2b */ +#define SW_DDRPHY_FB_CK_EN_LSB (1U << 18) /* 2b */ +#define SW_DR_GATE_RETRY_EN_LSB (1U << 20) /* 2b */ +#define SW_DPHY_PRECAL_UP_LSB (1U << 24) /* 2b */ +#define SW_DPY_BCLK_ENABLE_LSB (1U << 26) /* 2b */ +#define SW_TX_TRACKING_DIS_LSB (1U << 28) /* 2b */ +#define SW_DPHY_RXDLY_TRACKING_EN_LSB (1U << 30) /* 2b */ + +/* DRAMC_DPY_CLK_SW_CON_1 (0x10006000 + 0x484) */ +#define SW_SHU_RESTORE_LSB (1U << 0) /* 2b */ +#define SW_DMYRD_MOD_LSB (1U << 2) /* 2b */ +#define SW_DMYRD_INTV_LSB (1U << 4) /* 2b */ +#define SW_DMYRD_EN_LSB (1U << 6) /* 2b */ +#define SW_DRS_DIS_REQ_LSB (1U << 8) /* 2b */ +#define SW_DR_SRAM_LOAD_LSB (1U << 10) /* 2b */ +#define SW_DR_SRAM_RESTORE_LSB (1U << 12) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_LATCH_LSB (1U << 14) /* 2b */ +#define SW_TX_TRACK_RETRY_EN_LSB (1U << 16) /* 2b */ +#define SW_DPY_MIDPI_EN_LSB (1U << 18) /* 2b */ +#define SW_DPY_PI_RESETB_EN_LSB (1U << 20) /* 2b */ +#define SW_DPY_MCK8X_EN_LSB (1U << 22) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_CH0_LSB (1U << 24) /* 4b */ +#define SW_DR_SHU_LEVEL_SRAM_CH1_LSB (1U << 28) /* 4b */ + +/* DRAMC_DPY_CLK_SW_CON_2 (0x10006000 + 0x488) */ +#define SW_DR_SHU_LEVEL_LSB (1U << 0) /* 2b */ +#define SW_DR_SHU_EN_LSB (1U << 2) /* 1b */ +#define SW_DR_SHORT_QUEUE_LSB (1U << 3) /* 1b */ +#define SW_PHYPLL_MODE_SW_LSB (1U << 4) /* 1b */ +#define SW_PHYPLL2_MODE_SW_LSB (1U << 5) /* 1b */ +#define SW_PHYPLL_SHU_EN_LSB (1U << 6) /* 1b */ +#define SW_PHYPLL2_SHU_EN_LSB (1U << 7) /* 1b */ +#define SW_DR_RESERVED_0_LSB (1U << 24) /* 2b */ +#define SW_DR_RESERVED_1_LSB (1U << 26) /* 2b */ +#define SW_DR_RESERVED_2_LSB (1U << 28) /* 2b */ +#define SW_DR_RESERVED_3_LSB (1U << 30) /* 2b */ + +/* DRAMC_DPY_CLK_SW_CON_3 (0x10006000 + 0x48C) */ +#define SC_DR_SHU_EN_ACK_LSB (1U << 0) /* 4b */ +#define SC_EMI_CLK_OFF_ACK_LSB (1U << 4) /* 4b */ +#define SC_DR_SHORT_QUEUE_ACK_LSB (1U << 8) /* 4b */ +#define SC_DRAMC_DFS_STA_LSB (1U << 12) /* 4b */ +#define SC_DRS_DIS_ACK_LSB (1U << 16) /* 4b */ +#define SC_DR_SRAM_LOAD_ACK_LSB (1U << 20) /* 4b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_LSB (1U << 24) /* 4b */ +#define SC_DR_SRAM_RESTORE_ACK_LSB (1U << 28) /* 4b */ + +/* DRAMC_DPY_CLK_SW_SEL_0 (0x10006000 + 0x490) */ +#define SW_PHYPLL_EN_SEL_LSB (1U << 0) /* 2b */ +#define SW_DPY_VREF_EN_SEL_LSB (1U << 2) /* 2b */ +#define SW_DPY_DLL_CK_EN_SEL_LSB (1U << 4) /* 2b */ +#define SW_DPY_DLL_EN_SEL_LSB (1U << 6) /* 2b */ +#define SW_DPY_2ND_DLL_EN_SEL_LSB (1U << 8) /* 2b */ +#define SW_MEM_CK_OFF_SEL_LSB (1U << 10) /* 2b */ +#define SW_DMSUS_OFF_SEL_LSB (1U << 12) /* 2b */ +#define SW_DPY_MODE_SW_SEL_LSB (1U << 14) /* 2b */ +#define SW_EMI_CLK_OFF_SEL_LSB (1U << 16) /* 2b */ +#define SW_DDRPHY_FB_CK_EN_SEL_LSB (1U << 18) /* 2b */ +#define SW_DR_GATE_RETRY_EN_SEL_LSB (1U << 20) /* 2b */ +#define SW_DPHY_PRECAL_UP_SEL_LSB (1U << 24) /* 2b */ +#define SW_DPY_BCLK_ENABLE_SEL_LSB (1U << 26) /* 2b */ +#define SW_TX_TRACKING_DIS_SEL_LSB (1U << 28) /* 2b */ +#define SW_DPHY_RXDLY_TRACKING_EN_SEL_LSB (1U << 30) /* 2b */ + +/* DRAMC_DPY_CLK_SW_SEL_1 (0x10006000 + 0x494) */ +#define SW_SHU_RESTORE_SEL_LSB (1U << 0) /* 2b */ +#define SW_DMYRD_MOD_SEL_LSB (1U << 2) /* 2b */ +#define SW_DMYRD_INTV_SEL_LSB (1U << 4) /* 2b */ +#define SW_DMYRD_EN_SEL_LSB (1U << 6) /* 2b */ +#define SW_DRS_DIS_REQ_SEL_LSB (1U << 8) /* 2b */ +#define SW_DR_SRAM_LOAD_SEL_LSB (1U << 10) /* 2b */ +#define SW_DR_SRAM_RESTORE_SEL_LSB (1U << 12) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_LATCH_SEL_LSB (1U << 14) /* 2b */ +#define SW_TX_TRACK_RETRY_EN_SEL_LSB (1U << 16) /* 2b */ +#define SW_DPY_MIDPI_EN_SEL_LSB (1U << 18) /* 2b */ +#define SW_DPY_PI_RESETB_EN_SEL_LSB (1U << 20) /* 2b */ +#define SW_DPY_MCK8X_EN_SEL_LSB (1U << 22) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_SEL_LSB (1U << 24) /* 2b */ + +/* DRAMC_DPY_CLK_SW_SEL_2 (0x10006000 + 0x498) */ +#define SW_DR_SHU_LEVEL_SEL_LSB (1U << 0) /* 1b */ +#define SW_DR_SHU_EN_SEL_LSB (1U << 2) /* 1b */ +#define SW_DR_SHORT_QUEUE_SEL_LSB (1U << 3) /* 1b */ +#define SW_PHYPLL_MODE_SW_SEL_LSB (1U << 4) /* 1b */ +#define SW_PHYPLL2_MODE_SW_SEL_LSB (1U << 5) /* 1b */ +#define SW_PHYPLL_SHU_EN_SEL_LSB (1U << 6) /* 1b */ +#define SW_PHYPLL2_SHU_EN_SEL_LSB (1U << 7) /* 1b */ +#define SW_DR_RESERVED_0_SEL_LSB (1U << 24) /* 2b */ +#define SW_DR_RESERVED_1_SEL_LSB (1U << 26) /* 2b */ +#define SW_DR_RESERVED_2_SEL_LSB (1U << 28) /* 2b */ +#define SW_DR_RESERVED_3_SEL_LSB (1U << 30) /* 2b */ + +/* DRAMC_DPY_CLK_SW_SEL_3 (0x10006000 + 0x49C) */ +#define SC_DR_SHU_EN_ACK_SEL_LSB (1U << 0) /* 4b */ +#define SC_EMI_CLK_OFF_ACK_SEL_LSB (1U << 4) /* 4b */ +#define SC_DR_SHORT_QUEUE_ACK_SEL_LSB (1U << 8) /* 4b */ +#define SC_DRAMC_DFS_STA_SEL_LSB (1U << 12) /* 4b */ +#define SC_DRS_DIS_ACK_SEL_LSB (1U << 16) /* 4b */ +#define SC_DR_SRAM_LOAD_ACK_SEL_LSB (1U << 20) /* 4b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_SEL_LSB (1U << 24) /* 4b */ +#define SC_DR_SRAM_RESTORE_ACK_SEL_LSB (1U << 28) /* 4b */ + +/* DRAMC_DPY_CLK_SPM_CON (0x10006000 + 0x4A0) */ +#define SC_DMYRD_EN_MOD_SEL_PCM_LSB (1U << 0) /* 1b */ +#define SC_DMYRD_INTV_SEL_PCM_LSB (1U << 1) /* 1b */ +#define SC_DMYRD_EN_PCM_LSB (1U << 2) /* 1b */ +#define SC_DRS_DIS_REQ_PCM_LSB (1U << 3) /* 1b */ +#define SC_DR_SHU_LEVEL_SRAM_PCM_LSB (1U << 4) /* 4b */ +#define SC_DR_GATE_RETRY_EN_PCM_LSB (1U << 8) /* 1b */ +#define SC_DR_SHORT_QUEUE_PCM_LSB (1U << 9) /* 1b */ +#define SC_DPY_MIDPI_EN_PCM_LSB (1U << 10) /* 1b */ +#define SC_DPY_PI_RESETB_EN_PCM_LSB (1U << 11) /* 1b */ +#define SC_DPY_MCK8X_EN_PCM_LSB (1U << 12) /* 1b */ +#define SC_DR_RESERVED_0_PCM_LSB (1U << 13) /* 1b */ +#define SC_DR_RESERVED_1_PCM_LSB (1U << 14) /* 1b */ +#define SC_DR_RESERVED_2_PCM_LSB (1U << 15) /* 1b */ +#define SC_DR_RESERVED_3_PCM_LSB (1U << 16) /* 1b */ +#define SC_DMDRAMCSHU_ACK_ALL_LSB (1U << 24) /* 1b */ +#define SC_EMI_CLK_OFF_ACK_ALL_LSB (1U << 25) /* 1b */ +#define SC_DR_SHORT_QUEUE_ACK_ALL_LSB (1U << 26) /* 1b */ +#define SC_DRAMC_DFS_STA_ALL_LSB (1U << 27) /* 1b */ +#define SC_DRS_DIS_ACK_ALL_LSB (1U << 28) /* 1b */ +#define SC_DR_SRAM_LOAD_ACK_ALL_LSB (1U << 29) /* 1b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_ALL_LSB (1U << 30) /* 1b */ +#define SC_DR_SRAM_RESTORE_ACK_ALL_LSB (1U << 31) /* 1b */ + +/* SPM_DVFS_LEVEL (0x10006000 + 0x4A4) */ +#define SPM_DVFS_LEVEL_LSB (1U << 0) /* 32b */ + +/* SPM_CIRQ_CON (0x10006000 + 0x4A8) */ +#define CIRQ_CLK_SEL_LSB (1U << 0) /* 1b */ + +/* SPM_DVFS_MISC (0x10006000 + 0x4AC) */ +#define MSDC_DVFS_REQUEST_LSB (1U << 0) /* 1b */ +#define SPM2EMI_SLP_PROT_EN_LSB (1U << 1) /* 1b */ +#define SPM_DVFS_FORCE_ENABLE_LSB (1U << 2) /* 1b */ +#define FORCE_DVFS_WAKE_LSB (1U << 3) /* 1b */ +#define SPM_DVFSRC_ENABLE_LSB (1U << 4) /* 1b */ +#define SPM_DVFS_DONE_LSB (1U << 5) /* 1b */ +#define DVFSRC_IRQ_WAKEUP_EVENT_MASK_LSB (1U << 6) /* 1b */ +#define SPM2RC_EVENT_ABORT_LSB (1U << 7) /* 1b */ +#define EMI_SLP_IDLE_LSB (1U << 14) /* 1b */ +#define SDIO_READY_TO_SPM_LSB (1U << 15) /* 1b */ + +/* RG_MODULE_SW_CG_0_MASK_REQ_0 (0x10006000 + 0x4B4) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_0_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_0_MASK_REQ_1 (0x10006000 + 0x4B8) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_1_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_0_MASK_REQ_2 (0x10006000 + 0x4BC) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_2_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_1_MASK_REQ_0 (0x10006000 + 0x4C0) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_0_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_1_MASK_REQ_1 (0x10006000 + 0x4C4) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_1_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_1_MASK_REQ_2 (0x10006000 + 0x4C8) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_2_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_2_MASK_REQ_0 (0x10006000 + 0x4CC) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_0_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_2_MASK_REQ_1 (0x10006000 + 0x4D0) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_1_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_2_MASK_REQ_2 (0x10006000 + 0x4D4) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_2_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_3_MASK_REQ_0 (0x10006000 + 0x4D8) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_0_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_3_MASK_REQ_1 (0x10006000 + 0x4DC) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_1_LSB (1U << 0) /* 32b */ + +/* RG_MODULE_SW_CG_3_MASK_REQ_2 (0x10006000 + 0x4E0) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_2_LSB (1U << 0) /* 32b */ + +/* PWR_STATUS_MASK_REQ_0 (0x10006000 + 0x4E4) */ +#define PWR_STATUS_MASK_REQ_0_LSB (1U << 0) /* 32b */ + +/* PWR_STATUS_MASK_REQ_1 (0x10006000 + 0x4E8) */ +#define PWR_STATUS_MASK_REQ_1_LSB (1U << 0) /* 32b */ + +/* PWR_STATUS_MASK_REQ_2 (0x10006000 + 0x4EC) */ +#define PWR_STATUS_MASK_REQ_2_LSB (1U << 0) /* 32b */ + +/* SPM_CG_CHECK_CON (0x10006000 + 0x4F0) */ +#define APMIXEDSYS_BUSY_MASK_REQ_0_LSB (1U << 0) /* 5b */ +#define APMIXEDSYS_BUSY_MASK_REQ_1_LSB (1U << 8) /* 5b */ +#define APMIXEDSYS_BUSY_MASK_REQ_2_LSB (1U << 16) /* 5b */ +#define AUDIOSYS_BUSY_MASK_REQ_0_LSB (1U << 24) /* 1b */ +#define AUDIOSYS_BUSY_MASK_REQ_1_LSB (1U << 25) /* 1b */ +#define AUDIOSYS_BUSY_MASK_REQ_2_LSB (1U << 26) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_0_LSB (1U << 27) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_1_LSB (1U << 28) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_2_LSB (1U << 29) /* 1b */ + +/* SPM_SRC_RDY_STA (0x10006000 + 0x4F4) */ +#define SPM_INFRA_INTERNAL_ACK_LSB (1U << 0) /* 1b */ +#define SPM_VRF18_INTERNAL_ACK_LSB (1U << 1) /* 1b */ + +/* SPM_DVS_DFS_LEVEL (0x10006000 + 0x4F8) */ +#define SPM_DFS_LEVEL_LSB (1U << 0) /* 16b */ +#define SPM_DVS_LEVEL_LSB (1U << 16) /* 16b */ + +/* SPM_FORCE_DVFS (0x10006000 + 0x4FC) */ +#define FORCE_DVFS_LEVEL_LSB (1U << 0) /* 32b */ + +/* SPM_SW_FLAG_0 (0x10006000 + 0x600) */ +#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */ + +/* SPM_SW_DEBUG_0 (0x10006000 + 0x604) */ +#define SPM_SW_DEBUG_0_LSB (1U << 0) /* 32b */ + +/* SPM_SW_FLAG_1 (0x10006000 + 0x608) */ +#define SPM_SW_FLAG_1_LSB (1U << 0) /* 32b */ + +/* SPM_SW_DEBUG_1 (0x10006000 + 0x60C) */ +#define SPM_SW_DEBUG_1_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_0 (0x10006000 + 0x610) */ +#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_1 (0x10006000 + 0x614) */ +#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_2 (0x10006000 + 0x618) */ +#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_3 (0x10006000 + 0x61C) */ +#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_4 (0x10006000 + 0x620) */ +#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_5 (0x10006000 + 0x624) */ +#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_6 (0x10006000 + 0x628) */ +#define SPM_SW_RSV_6_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_7 (0x10006000 + 0x62C) */ +#define SPM_SW_RSV_7_LSB (1U << 0) /* 32b */ + +/* SPM_SW_RSV_8 (0x10006000 + 0x630) */ +#define SPM_SW_RSV_8_LSB (1U << 0) /* 32b */ + +/* SPM_BK_WAKE_EVENT (0x10006000 + 0x634) */ +#define SPM_BK_WAKE_EVENT_LSB (1U << 0) /* 32b */ + +/* SPM_BK_VTCXO_DUR (0x10006000 + 0x638) */ +#define SPM_BK_VTCXO_DUR_LSB (1U << 0) /* 32b */ + +/* SPM_BK_WAKE_MISC (0x10006000 + 0x63C) */ +#define SPM_BK_WAKE_MISC_LSB (1U << 0) /* 32b */ + +/* SPM_BK_PCM_TIMER (0x10006000 + 0x640) */ +#define SPM_BK_PCM_TIMER_LSB (1U << 0) /* 32b */ + +/* SPM_RSV_CON_0 (0x10006000 + 0x650) */ +#define SPM_RSV_CON_0_LSB (1U << 0) /* 32b */ + +/* SPM_RSV_CON_1 (0x10006000 + 0x654) */ +#define SPM_RSV_CON_1_LSB (1U << 0) /* 32b */ + +/* SPM_RSV_STA_0 (0x10006000 + 0x658) */ +#define SPM_RSV_STA_0_LSB (1U << 0) /* 32b */ + +/* SPM_RSV_STA_1 (0x10006000 + 0x65C) */ +#define SPM_RSV_STA_1_LSB (1U << 0) /* 32b */ + +/* SPM_SPARE_CON (0x10006000 + 0x660) */ +#define SPM_SPARE_CON_LSB (1U << 0) /* 32b */ + +/* SPM_SPARE_CON_SET (0x10006000 + 0x664) */ +#define SPM_SPARE_CON_SET_LSB (1U << 0) /* 32b */ + +/* SPM_SPARE_CON_CLR (0x10006000 + 0x668) */ +#define SPM_SPARE_CON_CLR_LSB (1U << 0) /* 32b */ + +/* SPM_CROSS_WAKE_M00_REQ (0x10006000 + 0x66C) */ +#define SPM_CROSS_WAKE_M00_REQ_LSB (1U << 0) /* 4b */ +#define SPM_CROSS_WAKE_M00_CHK_LSB (1U << 4) /* 4b */ + +/* SPM_CROSS_WAKE_M01_REQ (0x10006000 + 0x670) */ +#define SPM_CROSS_WAKE_M01_REQ_LSB (1U << 0) /* 4b */ +#define SPM_CROSS_WAKE_M01_CHK_LSB (1U << 4) /* 4b */ + +/* SPM_CROSS_WAKE_M02_REQ (0x10006000 + 0x674) */ +#define SPM_CROSS_WAKE_M02_REQ_LSB (1U << 0) /* 4b */ +#define SPM_CROSS_WAKE_M02_CHK_LSB (1U << 4) /* 4b */ + +/* SPM_CROSS_WAKE_M03_REQ (0x10006000 + 0x678) */ +#define SPM_CROSS_WAKE_M03_REQ_LSB (1U << 0) /* 4b */ +#define SPM_CROSS_WAKE_M03_CHK_LSB (1U << 4) /* 4b */ + +/* SCP_VCORE_LEVEL (0x10006000 + 0x67C) */ +#define SCP_VCORE_LEVEL_LSB (1U << 0) /* 16b */ + +/* SC_MM_CK_SEL_CON (0x10006000 + 0x680) */ +#define SC_MM_CK_SEL_LSB (1U << 0) /* 4b */ +#define SC_MM_CK_SEL_EN_LSB (1U << 4) /* 1b */ + +/* SPARE_ACK_MASK (0x10006000 + 0x684) */ +#define SPARE_ACK_MASK_B_LSB (1U << 0) /* 32b */ + +/* SPM_SPARE_FUNCTION (0x10006000 + 0x688) */ +#define SPM_SPARE_FUNCTION_LSB (1U << 0) /* 32b */ + +/* SPM_DV_CON_0 (0x10006000 + 0x68C) */ +#define SPM_DV_CON_0_LSB (1U << 0) /* 32b */ + +/* SPM_DV_CON_1 (0x10006000 + 0x690) */ +#define SPM_DV_CON_1_LSB (1U << 0) /* 32b */ + +/* SPM_DV_STA (0x10006000 + 0x694) */ +#define SPM_DV_STA_LSB (1U << 0) /* 32b */ + +/* CONN_XOWCN_DEBUG_EN (0x10006000 + 0x698) */ +#define CONN_XOWCN_DEBUG_EN_LSB (1U << 0) /* 1b */ + +/* SPM_SEMA_M0 (0x10006000 + 0x69C) */ +#define SPM_SEMA_M0_LSB (1U << 0) /* 8b */ + +/* SPM_SEMA_M1 (0x10006000 + 0x6A0) */ +#define SPM_SEMA_M1_LSB (1U << 0) /* 8b */ + +/* SPM_SEMA_M2 (0x10006000 + 0x6A4) */ +#define SPM_SEMA_M2_LSB (1U << 0) /* 8b */ + +/* SPM_SEMA_M3 (0x10006000 + 0x6A8) */ +#define SPM_SEMA_M3_LSB (1U << 0) /* 8b */ + +/* SPM_SEMA_M4 (0x10006000 + 0x6AC) */ +#define SPM_SEMA_M4_LSB (1U << 0) /* 8b */ + +/* SPM_SEMA_M5 (0x10006000 + 0x6B0) */ +#define SPM_SEMA_M5_LSB (1U << 0) /* 8b */ + +/* SPM_SEMA_M6 (0x10006000 + 0x6B4) */ +#define SPM_SEMA_M6_LSB (1U << 0) /* 8b */ + +/* SPM_SEMA_M7 (0x10006000 + 0x6B8) */ +#define SPM_SEMA_M7_LSB (1U << 0) /* 8b */ + +/* SPM2ADSP_MAILBOXi (0x10006000 + 0x6BC) */ +#define SPM2ADSP_MAILBOX_LSB (1U << 0) /* 32b */ + +/* ADSP2SPM_MAILBOX (0x10006000 + 0x6C0) */ +#define ADSP2SPM_MAILBOX_LSB (1U << 0) /* 32b */ + +/* SPM_ADSP_IRQ (0x10006000 + 0x6C4) */ +#define SC_SPM2ADSP_WAKEUP_LSB (1U << 0) /* 1b */ +#define SPM_ADSP_IRQ_SC_ADSP2SPM_WAKEUP_LSB (1U << 4) /* 1b */ + +/* SPM_MD32_IRQ (0x10006000 + 0x6C8) */ +#define SC_SPM2SSPM_WAKEUP_LSB (1U << 0) /* 4b */ +#define SPM_MD32_IRQ_SC_SSPM2SPM_WAKEUP_LSB (1U << 4) /* 4b */ + +/* SPM2PMCU_MAILBOX_0 (0x10006000 + 0x6CC) */ +#define SPM2PMCU_MAILBOX_0_LSB (1U << 0) /* 32b */ + +/* SPM2PMCU_MAILBOX_1 (0x10006000 + 0x6D0) */ +#define SPM2PMCU_MAILBOX_1_LSB (1U << 0) /* 32b */ + +/* SPM2PMCU_MAILBOX_2 (0x10006000 + 0x6D4) */ +#define SPM2PMCU_MAILBOX_2_LSB (1U << 0) /* 32b */ + +/* SPM2PMCU_MAILBOX_3 (0x10006000 + 0x6D8) */ +#define SPM2PMCU_MAILBOX_3_LSB (1U << 0) /* 32b */ + +/* PMCU2SPM_MAILBOX_0 (0x10006000 + 0x6DC) */ +#define PMCU2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */ + +/* PMCU2SPM_MAILBOX_1 (0x10006000 + 0x6E0) */ +#define PMCU2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */ + +/* PMCU2SPM_MAILBOX_2 (0x10006000 + 0x6E4) */ +#define PMCU2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */ + +/* PMCU2SPM_MAILBOX_3 (0x10006000 + 0x6E8) */ +#define PMCU2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */ + +/* UFS_PSRI_SW (0x10006000 + 0x6EC) */ +#define UFS_PSRI_SW_LSB (1U << 0) /* 1b */ + +/* UFS_PSRI_SW_SET (0x10006000 + 0x6F0) */ +#define UFS_PSRI_SW_SET_LSB (1U << 0) /* 1b */ + +/* UFS_PSRI_SW_CLR (0x10006000 + 0x6F4) */ +#define UFS_PSRI_SW_CLR_LSB (1U << 0) /* 1b */ + +/* SPM_AP_SEMA (0x10006000 + 0x6F8) */ +#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */ + +/* SPM_SPM_SEMA (0x10006000 + 0x6FC) */ +#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */ + +/* SPM_DVFS_CON (0x10006000 + 0x700) */ +#define SPM_DVFS_CON_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CON_STA (0x10006000 + 0x704) */ +#define SPM_DVFS_CON_STA_LSB (1U << 0) /* 32b */ + +/* SPM_PMIC_SPMI_CON (0x10006000 + 0x708) */ +#define SPM_PMIC_SPMI_CMD_LSB (1U << 0) /* 2b */ +#define SPM_PMIC_SPMI_SLAVEID_LSB (1U << 2) /* 4b */ +#define SPM_PMIC_SPMI_PMIFID_LSB (1U << 6) /* 1b */ +#define SPM_PMIC_SPMI_DBCNT_LSB (1U << 7) /* 1b */ + +/* SPM_DVFS_CMD0 (0x10006000 + 0x710) */ +#define SPM_DVFS_CMD0_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD1 (0x10006000 + 0x714) */ +#define SPM_DVFS_CMD1_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD2 (0x10006000 + 0x718) */ +#define SPM_DVFS_CMD2_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD3 (0x10006000 + 0x71C) */ +#define SPM_DVFS_CMD3_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD4 (0x10006000 + 0x720) */ +#define SPM_DVFS_CMD4_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD5 (0x10006000 + 0x724) */ +#define SPM_DVFS_CMD5_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD6 (0x10006000 + 0x728) */ +#define SPM_DVFS_CMD6_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD7 (0x10006000 + 0x72C) */ +#define SPM_DVFS_CMD7_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD8 (0x10006000 + 0x730) */ +#define SPM_DVFS_CMD8_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD9 (0x10006000 + 0x734) */ +#define SPM_DVFS_CMD9_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD10 (0x10006000 + 0x738) */ +#define SPM_DVFS_CMD10_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD11 (0x10006000 + 0x73C) */ +#define SPM_DVFS_CMD11_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD12 (0x10006000 + 0x740) */ +#define SPM_DVFS_CMD12_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD13 (0x10006000 + 0x744) */ +#define SPM_DVFS_CMD13_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD14 (0x10006000 + 0x748) */ +#define SPM_DVFS_CMD14_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD15 (0x10006000 + 0x74C) */ +#define SPM_DVFS_CMD15_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD16i (0x10006000 + 0x750) */ +#define SPM_DVFS_CMD16_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD17 (0x10006000 + 0x754) */ +#define SPM_DVFS_CMD17_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD18 (0x10006000 + 0x758) */ +#define SPM_DVFS_CMD18_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD19 (0x10006000 + 0x75C) */ +#define SPM_DVFS_CMD19_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD20 (0x10006000 + 0x760) */ +#define SPM_DVFS_CMD20_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD21 (0x10006000 + 0x764) */ +#define SPM_DVFS_CMD21_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD22 (0x10006000 + 0x768) */ +#define SPM_DVFS_CMD22_LSB (1U << 0) /* 32b */ + +/* SPM_DVFS_CMD23 (0x10006000 + 0x76C) */ +#define SPM_DVFS_CMD23_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_VALUE_L (0x10006000 + 0x770) */ +#define SYS_TIMER_VALUE_L_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_VALUE_H (0x10006000 + 0x774) */ +#define SYS_TIMER_VALUE_H_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_START_L (0x10006000 + 0x778) */ +#define SYS_TIMER_START_L_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_START_H (0x10006000 + 0x77C) */ +#define SYS_TIMER_START_H_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_00 (0x10006000 + 0x780) */ +#define SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_00 (0x10006000 + 0x784) */ +#define SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_01 (0x10006000 + 0x788) */ +#define SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_01 (0x10006000 + 0x78C) */ +#define SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_02 (0x10006000 + 0x790) */ +#define SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_02 (0x10006000 + 0x794) */ +#define SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_03 (0x10006000 + 0x798) */ +#define SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_03 (0x10006000 + 0x79C) */ +#define SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_04 (0x10006000 + 0x7A0) */ +#define SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_04 (0x10006000 + 0x7A4) */ +#define SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_05 (0x10006000 + 0x7A8) */ +#define SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_05 (0x10006000 + 0x7AC) */ +#define SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_06 (0x10006000 + 0x7B0) */ +#define SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_06 (0x10006000 + 0x7B4) */ +#define SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_07 (0x10006000 + 0x7B8) */ +#define SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_07 (0x10006000 + 0x7BC) */ +#define SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_08 (0x10006000 + 0x7C0) */ +#define SYS_TIMER_LATCH_L_08_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_08 (0x10006000 + 0x7C4) */ +#define SYS_TIMER_LATCH_H_08_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_09 (0x10006000 + 0x7C8) */ +#define SYS_TIMER_LATCH_L_09_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_09 (0x10006000 + 0x7CC) */ +#define SYS_TIMER_LATCH_H_09_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_10 (0x10006000 + 0x7D0) */ +#define SYS_TIMER_LATCH_L_10_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_10 (0x10006000 + 0x7D4) */ +#define SYS_TIMER_LATCH_H_10_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_11 (0x10006000 + 0x7D8) */ +#define SYS_TIMER_LATCH_L_11_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_11 (0x10006000 + 0x7DC) */ +#define SYS_TIMER_LATCH_H_11_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_12 (0x10006000 + 0x7E0) */ +#define SYS_TIMER_LATCH_L_12_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_12 (0x10006000 + 0x7E4) */ +#define SYS_TIMER_LATCH_H_12_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_13 (0x10006000 + 0x7E8) */ +#define SYS_TIMER_LATCH_L_13_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_13 (0x10006000 + 0x7EC) */ +#define SYS_TIMER_LATCH_H_13_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_14 (0x10006000 + 0x7F0) */ +#define SYS_TIMER_LATCH_L_14_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_14 (0x10006000 + 0x7F4) */ +#define SYS_TIMER_LATCH_H_14_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_L_15 (0x10006000 + 0x7F8) */ +#define SYS_TIMER_LATCH_L_15_LSB (1U << 0) /* 32b */ + +/* SYS_TIMER_LATCH_H_15 (0x10006000 + 0x7FC) */ +#define SYS_TIMER_LATCH_H_15_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_0 (0x10006000 + 0x800) */ +#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_1 (0x10006000 + 0x804) */ +#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_2 (0x10006000 + 0x808) */ +#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_3 (0x10006000 + 0x80C) */ +#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_4 (0x10006000 + 0x810) */ +#define PCM_WDT_LATCH_4_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_5 (0x10006000 + 0x814) */ +#define PCM_WDT_LATCH_5_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_6 (0x10006000 + 0x818) */ +#define PCM_WDT_LATCH_6_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_7 (0x10006000 + 0x81C) */ +#define PCM_WDT_LATCH_7_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_8 (0x10006000 + 0x820) */ +#define PCM_WDT_LATCH_8_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_9 (0x10006000 + 0x824) */ +#define PCM_WDT_LATCH_9_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_10 (0x10006000 + 0x828) */ +#define PCM_WDT_LATCH_10_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_11 (0x10006000 + 0x82C) */ +#define PCM_WDT_LATCH_11_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_12 (0x10006000 + 0x830) */ +#define PCM_WDT_LATCH_12_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_13 (0x10006000 + 0x834) */ +#define PCM_WDT_LATCH_13_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_14 (0x10006000 + 0x838) */ +#define PCM_WDT_LATCH_14_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_15 (0x10006000 + 0x83C) */ +#define PCM_WDT_LATCH_15_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_16 (0x10006000 + 0x840) */ +#define PCM_WDT_LATCH_16_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_17 (0x10006000 + 0x844) */ +#define PCM_WDT_LATCH_17_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_18 (0x10006000 + 0x848) */ +#define PCM_WDT_LATCH_18_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_SPARE_0 (0x10006000 + 0x84C) */ +#define PCM_WDT_LATCH_SPARE_0_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_SPARE_1 (0x10006000 + 0x850) */ +#define PCM_WDT_LATCH_SPARE_1_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_SPARE_2 (0x10006000 + 0x854) */ +#define PCM_WDT_LATCH_SPARE_2_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_CONN_0 (0x10006000 + 0x870) */ +#define PCM_WDT_LATCH_CONN_0_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_CONN_1 (0x10006000 + 0x874) */ +#define PCM_WDT_LATCH_CONN_1_LSB (1U << 0) /* 32b */ + +/* PCM_WDT_LATCH_CONN_2 (0x10006000 + 0x878) */ +#define PCM_WDT_LATCH_CONN_2_LSB (1U << 0) /* 32b */ + +/* DRAMC_GATING_ERR_LATCH_CH0_0 (0x10006000 + 0x8A0) */ +#define DRAMC_GATING_ERR_LATCH_CH0_0_LSB (1U << 0) /* 32b */ + +/* DRAMC_GATING_ERR_LATCH_CH0_1 (0x10006000 + 0x8A4) */ +#define DRAMC_GATING_ERR_LATCH_CH0_1_LSB (1U << 0) /* 32b */ + +/* DRAMC_GATING_ERR_LATCH_CH0_2 (0x10006000 + 0x8A8) */ +#define DRAMC_GATING_ERR_LATCH_CH0_2_LSB (1U << 0) /* 32b */ + +/* DRAMC_GATING_ERR_LATCH_CH0_3 (0x10006000 + 0x8AC) */ +#define DRAMC_GATING_ERR_LATCH_CH0_3_LSB (1U << 0) /* 32b */ + +/* DRAMC_GATING_ERR_LATCH_CH0_4 (0x10006000 + 0x8B0) */ +#define DRAMC_GATING_ERR_LATCH_CH0_4_LSB (1U << 0) /* 32b */ + +/* DRAMC_GATING_ERR_LATCH_CH0_5 (0x10006000 + 0x8B4) */ +#define DRAMC_GATING_ERR_LATCH_CH0_5_LSB (1U << 0) /* 32b */ + +/* DRAMC_GATING_ERR_LATCH_CH0_6 (0x10006000 + 0x8B8) */ +#define DRAMC_GATING_ERR_LATCH_CH0_6_LSB (1U << 0) /* 32b */ + +/* DRAMC_GATING_ERR_LATCH_SPARE_0 (0x10006000 + 0x8F4) */ +#define DRAMC_GATING_ERR_LATCH_SPARE_0_LSB (1U << 0) /* 32b */ + +/* SPM_ACK_CHK_CON_0 (0x10006000 + 0x900) */ +#define SPM_ACK_CHK_SW_EN_0_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_0_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_0_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_0_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_0_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_0_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_0_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_0_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_0_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_0_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_0_LSB (1U << 15) /* 1b */ + +/* SPM_ACK_CHK_PC_0 (0x10006000 + 0x904) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_0_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_0_LSB (1U << 16) /* 16b */ + +/* SPM_ACK_CHK_SEL_0 (0x10006000 + 0x908) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_0_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_0_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_0_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_0_LSB (1U << 21) /* 3b */ + +/* SPM_ACK_CHK_TIMER_0 (0x10006000 + 0x90C) */ +#define SPM_ACK_CHK_TIMER_VAL_0_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_0_LSB (1U << 16) /* 16b */ + +/* SPM_ACK_CHK_STA_0 (0x10006000 + 0x910) */ +#define SPM_ACK_CHK_STA_0_LSB (1U << 0) /* 32b */ + +/* SPM_ACK_CHK_SWINT_0 (0x10006000 + 0x914) */ +#define SPM_ACK_CHK_SWINT_EN_0_LSB (1U << 0) /* 32b */ + +/* SPM_ACK_CHK_CON_1 (0x10006000 + 0x918) */ +#define SPM_ACK_CHK_SW_EN_1_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_1_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_1_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_1_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_1_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_1_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_1_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_1_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_1_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_1_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_1_LSB (1U << 15) /* 1b */ + +/* SPM_ACK_CHK_PC_1 (0x10006000 + 0x91C) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_1_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_1_LSB (1U << 16) /* 16b */ + +/* SPM_ACK_CHK_SEL_1 (0x10006000 + 0x920) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_1_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_1_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_1_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_1_LSB (1U << 21) /* 3b */ + +/* SPM_ACK_CHK_TIMER_1 (0x10006000 + 0x924) */ +#define SPM_ACK_CHK_TIMER_VAL_1_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_1_LSB (1U << 16) /* 16b */ + +/* SPM_ACK_CHK_STA_1 (0x10006000 + 0x928) */ +#define SPM_ACK_CHK_STA_1_LSB (1U << 0) /* 32b */ + +/* SPM_ACK_CHK_SWINT_1 (0x10006000 + 0x92C) */ +#define SPM_ACK_CHK_SWINT_EN_1_LSB (1U << 0) /* 32b */ + +/* SPM_ACK_CHK_CON_2 (0x10006000 + 0x930) */ +#define SPM_ACK_CHK_SW_EN_2_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_2_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_2_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_2_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_2_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_2_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_2_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_2_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_2_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_2_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_2_LSB (1U << 15) /* 1b */ + +/* SPM_ACK_CHK_PC_2 (0x10006000 + 0x934) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_2_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_2_LSB (1U << 16) /* 16b */ + +/* SPM_ACK_CHK_SEL_2 (0x10006000 + 0x938) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_2_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_2_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_2_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_2_LSB (1U << 21) /* 3b */ + +/* SPM_ACK_CHK_TIMER_2 (0x10006000 + 0x93C) */ +#define SPM_ACK_CHK_TIMER_VAL_2_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_2_LSB (1U << 16) /* 16b */ + +/* SPM_ACK_CHK_STA_2 (0x10006000 + 0x940) */ +#define SPM_ACK_CHK_STA_2_LSB (1U << 0) /* 32b */ + +/* SPM_ACK_CHK_SWINT_2 (0x10006000 + 0x944) */ +#define SPM_ACK_CHK_SWINT_EN_2_LSB (1U << 0) /* 32b */ + +/* SPM_ACK_CHK_CON_3 (0x10006000 + 0x948) */ +#define SPM_ACK_CHK_SW_EN_3_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_3_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_3_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_3_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_3_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_3_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_3_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_3_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_3_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_3_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_3_LSB (1U << 15) /* 1b */ + +/* SPM_ACK_CHK_PC_3 (0x10006000 + 0x94C) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_3_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_3_LSB (1U << 16) /* 16b */ + +/* SPM_ACK_CHK_SEL_3 (0x10006000 + 0x950) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_3_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_3_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_3_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_3_LSB (1U << 21) /* 3b */ + +/* SPM_ACK_CHK_TIMER_3 (0x10006000 + 0x954) */ +#define SPM_ACK_CHK_TIMER_VAL_3_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_3_LSB (1U << 16) /* 16b */ + +/* SPM_ACK_CHK_STA_3 (0x10006000 + 0x958) */ +#define SPM_ACK_CHK_STA_3_LSB (1U << 0) /* 32b */ + +/* SPM_ACK_CHK_SWINT_3 (0x10006000 + 0x95C) */ +#define SPM_ACK_CHK_SWINT_EN_3_LSB (1U << 0) /* 32b */ + +/* SPM_COUNTER_0 (0x10006000 + 0x960) */ +#define SPM_COUNTER_VAL_0_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_0_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_0_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_0_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_0_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_0_LSB (1U << 31) /* 1b */ + +/* SPM_COUNTER_1 (0x10006000 + 0x964) */ +#define SPM_COUNTER_VAL_1_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_1_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_1_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_1_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_1_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_1_LSB (1U << 31) /* 1b */ + +/* SPM_COUNTER_2 (0x10006000 + 0x968) */ +#define SPM_COUNTER_VAL_2_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_2_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_2_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_2_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_2_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_2_LSB (1U << 31) /* 1b */ + +/* SYS_TIMER_CON (0x10006000 + 0x96C) */ +#define SYS_TIMER_START_EN_LSB (1U << 0) /* 1b */ +#define SYS_TIMER_LATCH_EN_LSB (1U << 1) /* 1b */ +#define SYS_TIMER_ID_LSB (1U << 8) /* 8b */ +#define SYS_TIMER_VALID_LSB (1U << 31) /* 1b */ + +/* SPM_TWAM_CON (0x10006000 + 0x970) */ +#define REG_TWAM_ENABLE_LSB (1U << 0) /* 1b */ +#define REG_TWAM_SPEED_MODE_EN_LSB (1U << 1) /* 1b */ +#define REG_TWAM_SW_RST_LSB (1U << 2) /* 1b */ +#define REG_TWAM_IRQ_MASK_LSB (1U << 3) /* 1b */ +#define REG_TWAM_MON_TYPE_0_LSB (1U << 4) /* 2b */ +#define REG_TWAM_MON_TYPE_1_LSB (1U << 6) /* 2b */ +#define REG_TWAM_MON_TYPE_2_LSB (1U << 8) /* 2b */ +#define REG_TWAM_MON_TYPE_3_LSB (1U << 10) /* 2b */ + +/* SPM_TWAM_WINDOW_LEN (0x10006000 + 0x974) */ +#define REG_TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */ + +/* SPM_TWAM_IDLE_SEL (0x10006000 + 0x978) */ +#define REG_TWAM_SIG_SEL_0_LSB (1U << 0) /* 7b */ +#define REG_TWAM_SIG_SEL_1_LSB (1U << 8) /* 7b */ +#define REG_TWAM_SIG_SEL_2_LSB (1U << 16) /* 7b */ +#define REG_TWAM_SIG_SEL_3_LSB (1U << 24) /* 7b */ + +/* SPM_TWAM_EVENT_CLEAR (0x10006000 + 0x97C) */ +#define SPM_TWAM_EVENT_CLEAR_LSB (1U << 0) /* 1b */ + +/* OPP0_TABLE (0x10006000 + 0x980) */ +#define OPP0_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP1_TABLE (0x10006000 + 0x984) */ +#define OPP1_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP2_TABLE (0x10006000 + 0x988) */ +#define OPP2_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP3_TABLE (0x10006000 + 0x98C) */ +#define OPP3_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP4_TABLE (0x10006000 + 0x990) */ +#define OPP4_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP5_TABLE (0x10006000 + 0x994) */ +#define OPP5_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP6_TABLE (0x10006000 + 0x998) */ +#define OPP6_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP7_TABLE (0x10006000 + 0x99C) */ +#define OPP7_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP8_TABLE (0x10006000 + 0x9A0) */ +#define OPP8_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP9_TABLE (0x10006000 + 0x9A4) */ +#define OPP9_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP10_TABLE (0x10006000 + 0x9A8) */ +#define OPP10_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP11_TABLE (0x10006000 + 0x9AC) */ +#define OPP11_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP12_TABLE (0x10006000 + 0x9B0) */ +#define OPP12_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP13_TABLE (0x10006000 + 0x9B4) */ +#define OPP13_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP14_TABLE (0x10006000 + 0x9B8) */ +#define OPP14_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP15_TABLE (0x10006000 + 0x9BC) */ +#define OPP15_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP16_TABLE (0x10006000 + 0x9C0) */ +#define OPP16_TABLE_LSB (1U << 0) /* 32b */ + +/* OPP17_TABLE (0x10006000 + 0x9C4) */ +#define OPP17_TABLE_LSB (1U << 0) /* 32b */ + +/* SHU0_ARRAY (0x10006000 + 0x9C8) */ +#define SHU0_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU1_ARRAY (0x10006000 + 0x9CC) */ +#define SHU1_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU2_ARRAY (0x10006000 + 0x9D0) */ +#define SHU2_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU3_ARRAY (0x10006000 + 0x9D4) */ +#define SHU3_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU4_ARRAY (0x10006000 + 0x9D8) */ +#define SHU4_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU5_ARRAY (0x10006000 + 0x9DC) */ +#define SHU5_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU6_ARRAY (0x10006000 + 0x9E0) */ +#define SHU6_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU7_ARRAY (0x10006000 + 0x9E4) */ +#define SHU7_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU8_ARRAY (0x10006000 + 0x9E8) */ +#define SHU8_ARRAY_LSB (1U << 0) /* 32b */ + +/* SHU9_ARRAY (0x10006000 + 0x9EC) */ +#define SHU9_ARRAY_LSB (1U << 0) /* 32b */ + +#define SPM_PROJECT_CODE (0xb16) +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) + +#endif /* MT_SPM_REG */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h new file mode 100644 index 0000000..d370daf --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_RESOURCE_REQ_H +#define MT_SPM_RESOURCE_REQ_H + +/* SPM resource request internal bit */ +#define MT_SPM_BIT_XO_FPM 0U +#define MT_SPM_BIT_26M 1U +#define MT_SPM_BIT_INFRA 2U +#define MT_SPM_BIT_SYSPLL 3U +#define MT_SPM_BIT_DRAM_S0 4U +#define MT_SPM_BIT_DRAM_S1 5U + +/* SPM resource request internal bit_mask */ +#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM) +#define MT_SPM_26M BIT(MT_SPM_BIT_26M) +#define MT_SPM_INFRA BIT(MT_SPM_BIT_INFRA) +#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL) +#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0) +#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1) + +#endif /* MT_SPM_RESOURCE_REQ_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c new file mode 100644 index 0000000..df533a6 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPM_SUSPEND_SLEEP_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_USE_SRCCLKENO2) + +#define SPM_SUSPEND_SLEEP_PCM_FLAG1 (0U) + +#define SPM_SUSPEND_PCM_FLAG \ + (SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS) + +#define SPM_SUSPEND_PCM_FLAG1 (0U) + +#define __WAKE_SRC_FOR_SUSPEND_COMMON__ \ + (R12_PCM_TIMER | \ + R12_KP_IRQ_B | \ + R12_APWDT_EVENT_B | \ + R12_CONN2AP_SPM_WAKEUP_B | \ + R12_EINT_EVENT_B | \ + R12_CONN_WDT_IRQ_B | \ + R12_SSPM2SPM_WAKEUP_B | \ + R12_SCP2SPM_WAKEUP_B | \ + R12_ADSP2SPM_WAKEUP_B | \ + R12_USBX_CDSC_B | \ + R12_USBX_POWERDWN_B | \ + R12_SYS_TIMER_EVENT_B | \ + R12_EINT_EVENT_SECURE_B | \ + R12_SYS_CIRQ_IRQ_B | \ + R12_NNA_WAKEUP | \ + R12_REG_CPU_WAKEUP) + +#if defined(CFG_MICROTRUST_TEE_SUPPORT) +#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__) +#else +#define WAKE_SRC_FOR_SUSPEND \ + (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \ + R12_SEJ_EVENT_B) +#endif + +static struct pwr_ctrl suspend_ctrl = { + .wake_src = WAKE_SRC_FOR_SUSPEND, + + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + .reg_wfi_op = 0, + .reg_wfi_type = 0, + .reg_mp0_cputop_idle_mask = 0, + .reg_mp1_cputop_idle_mask = 0, + .reg_mcusys_idle_mask = 0, + .reg_md_apsrc_1_sel = 0, + .reg_md_apsrc_0_sel = 0, + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC6_MASK */ + .reg_ccif_event_infra_req_mask_b = 0, + .reg_ccif_event_apsrc_req_mask_b = 0, + + /* SPM_SRC_REQ */ + .reg_spm_apsrc_req = 0, + .reg_spm_f26m_req = 0, + .reg_spm_infra_req = 0, + .reg_spm_vrf18_req = 0, + .reg_spm_ddren_req = 0, + .reg_spm_dvfs_req = 0, + .reg_spm_sw_mailbox_req = 0, + .reg_spm_sspm_mailbox_req = 0, + .reg_spm_adsp_mailbox_req = 0, + .reg_spm_scp_mailbox_req = 0, + + /* SPM_SRC_MASK */ + .reg_md_0_srcclkena_mask_b = 0, + .reg_md_0_infra_req_mask_b = 0, + .reg_md_0_apsrc_req_mask_b = 0, + .reg_md_0_vrf18_req_mask_b = 0, + .reg_md_0_ddren_req_mask_b = 0, + .reg_md_1_srcclkena_mask_b = 0, + .reg_md_1_infra_req_mask_b = 0, + .reg_md_1_apsrc_req_mask_b = 0, + .reg_md_1_vrf18_req_mask_b = 0, + .reg_md_1_ddren_req_mask_b = 0, + .reg_conn_srcclkena_mask_b = 1, + .reg_conn_srcclkenb_mask_b = 0, + .reg_conn_infra_req_mask_b = 1, + .reg_conn_apsrc_req_mask_b = 1, + .reg_conn_vrf18_req_mask_b = 1, + .reg_conn_ddren_req_mask_b = 1, + .reg_conn_vfe28_mask_b = 0, + .reg_srcclkeni_srcclkena_mask_b = 1, + .reg_srcclkeni_infra_req_mask_b = 1, + .reg_infrasys_apsrc_req_mask_b = 0, + .reg_infrasys_ddren_req_mask_b = 1, + .reg_sspm_srcclkena_mask_b = 1, + .reg_sspm_infra_req_mask_b = 1, + .reg_sspm_apsrc_req_mask_b = 1, + .reg_sspm_vrf18_req_mask_b = 1, + .reg_sspm_ddren_req_mask_b = 1, + + /* SPM_SRC2_MASK */ + .reg_scp_srcclkena_mask_b = 1, + .reg_scp_infra_req_mask_b = 1, + .reg_scp_apsrc_req_mask_b = 1, + .reg_scp_vrf18_req_mask_b = 1, + .reg_scp_ddren_req_mask_b = 1, + .reg_audio_dsp_srcclkena_mask_b = 1, + .reg_audio_dsp_infra_req_mask_b = 1, + .reg_audio_dsp_apsrc_req_mask_b = 1, + .reg_audio_dsp_vrf18_req_mask_b = 1, + .reg_audio_dsp_ddren_req_mask_b = 1, + .reg_ufs_srcclkena_mask_b = 1, + .reg_ufs_infra_req_mask_b = 1, + .reg_ufs_apsrc_req_mask_b = 1, + .reg_ufs_vrf18_req_mask_b = 1, + .reg_ufs_ddren_req_mask_b = 1, + .reg_disp0_apsrc_req_mask_b = 1, + .reg_disp0_ddren_req_mask_b = 1, + .reg_disp1_apsrc_req_mask_b = 1, + .reg_disp1_ddren_req_mask_b = 1, + .reg_gce_infra_req_mask_b = 1, + .reg_gce_apsrc_req_mask_b = 1, + .reg_gce_vrf18_req_mask_b = 1, + .reg_gce_ddren_req_mask_b = 1, + .reg_apu_srcclkena_mask_b = 0, + .reg_apu_infra_req_mask_b = 0, + .reg_apu_apsrc_req_mask_b = 0, + .reg_apu_vrf18_req_mask_b = 0, + .reg_apu_ddren_req_mask_b = 0, + .reg_cg_check_srcclkena_mask_b = 0, + .reg_cg_check_apsrc_req_mask_b = 0, + .reg_cg_check_vrf18_req_mask_b = 0, + .reg_cg_check_ddren_req_mask_b = 0, + + /* SPM_SRC3_MASK */ + .reg_dvfsrc_event_trigger_mask_b = 1, + .reg_sw2spm_wakeup_mask_b = 0, + .reg_adsp2spm_wakeup_mask_b = 0, + .reg_sspm2spm_wakeup_mask_b = 0, + .reg_scp2spm_wakeup_mask_b = 0, + .reg_csyspwrup_ack_mask = 1, + .reg_spm_reserved_srcclkena_mask_b = 0, + .reg_spm_reserved_infra_req_mask_b = 0, + .reg_spm_reserved_apsrc_req_mask_b = 0, + .reg_spm_reserved_vrf18_req_mask_b = 0, + .reg_spm_reserved_ddren_req_mask_b = 0, + .reg_mcupm_srcclkena_mask_b = 0, + .reg_mcupm_infra_req_mask_b = 0, + .reg_mcupm_apsrc_req_mask_b = 0, + .reg_mcupm_vrf18_req_mask_b = 0, + .reg_mcupm_ddren_req_mask_b = 0, + .reg_msdc0_srcclkena_mask_b = 1, + .reg_msdc0_infra_req_mask_b = 1, + .reg_msdc0_apsrc_req_mask_b = 1, + .reg_msdc0_vrf18_req_mask_b = 1, + .reg_msdc0_ddren_req_mask_b = 1, + .reg_msdc1_srcclkena_mask_b = 1, + .reg_msdc1_infra_req_mask_b = 1, + .reg_msdc1_apsrc_req_mask_b = 1, + .reg_msdc1_vrf18_req_mask_b = 1, + .reg_msdc1_ddren_req_mask_b = 1, + + /* SPM_SRC4_MASK */ + .reg_ccif_event_srcclkena_mask_b = 0, + .reg_bak_psri_srcclkena_mask_b = 0, + .reg_bak_psri_infra_req_mask_b = 0, + .reg_bak_psri_apsrc_req_mask_b = 0, + .reg_bak_psri_vrf18_req_mask_b = 0, + .reg_bak_psri_ddren_req_mask_b = 0, + .reg_dramc_md32_infra_req_mask_b = 0, + .reg_dramc_md32_vrf18_req_mask_b = 0, + .reg_conn_srcclkenb2pwrap_mask_b = 0, + .reg_dramc_md32_apsrc_req_mask_b = 0, + + /* SPM_SRC5_MASK */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x83, + .reg_mcusys_merge_ddren_req_mask_b = 0x83, + .reg_afe_srcclkena_mask_b = 1, + .reg_afe_infra_req_mask_b = 1, + .reg_afe_apsrc_req_mask_b = 1, + .reg_afe_vrf18_req_mask_b = 1, + .reg_afe_ddren_req_mask_b = 1, + .reg_msdc2_srcclkena_mask_b = 0, + .reg_msdc2_infra_req_mask_b = 0, + .reg_msdc2_apsrc_req_mask_b = 0, + .reg_msdc2_vrf18_req_mask_b = 0, + .reg_msdc2_ddren_req_mask_b = 0, + + /* SPM_WAKEUP_EVENT_MASK */ + .reg_wakeup_event_mask = 0x1383213, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, + + /* SPM_SRC7_MASK */ + .reg_pcie_srcclkena_mask_b = 0, + .reg_pcie_infra_req_mask_b = 0, + .reg_pcie_apsrc_req_mask_b = 0, + .reg_pcie_vrf18_req_mask_b = 0, + .reg_pcie_ddren_req_mask_b = 0, + .reg_dpmaif_srcclkena_mask_b = 1, + .reg_dpmaif_infra_req_mask_b = 1, + .reg_dpmaif_apsrc_req_mask_b = 1, + .reg_dpmaif_vrf18_req_mask_b = 1, + .reg_dpmaif_ddren_req_mask_b = 1, + + /* Auto-gen End */ + + /*sw flag setting */ + .pcm_flags = SPM_SUSPEND_PCM_FLAG, + .pcm_flags1 = SPM_SUSPEND_PCM_FLAG1, +}; + +struct spm_lp_scen __spm_suspend = { + .pwrctrl = &suspend_ctrl, +}; + +int mt_spm_suspend_mode_set(int mode) +{ + if (mode == MT_SPM_SUSPEND_SLEEP) { + suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG; + suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1; + } else { + suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG; + suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1; + } + + return 0; +} + +int mt_spm_suspend_enter(int state_id, unsigned int ext_opand, + unsigned int resource_req) +{ + /* If FMAudio / ADSP is active, change to sleep suspend mode */ + if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) { + mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP); + } + + /* Notify MCUPM that device is going suspend flow */ + mmio_write_32(MCUPM_MBOX_OFFSET_PDN, MCUPM_POWER_DOWN); + + /* Notify UART to sleep */ + mt_uart_save(); + + return spm_conservation(state_id, ext_opand, + &__spm_suspend, resource_req); +} + +void mt_spm_suspend_resume(int state_id, unsigned int ext_opand, + struct wake_status **status) +{ + spm_conservation_finish(state_id, ext_opand, &__spm_suspend, status); + + /* Notify UART to wakeup */ + mt_uart_restore(); + + /* Notify MCUPM that device leave suspend */ + mmio_write_32(MCUPM_MBOX_OFFSET_PDN, 0); + + /* If FMAudio / ADSP is active, change back to suspend mode */ + if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) { + mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN); + } +} + +void mt_spm_suspend_init(void) +{ + spm_conservation_pwrctrl_init(__spm_suspend.pwrctrl); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h new file mode 100644 index 0000000..f7c066a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef MT_SPM_SUSPEDN_H +#define MT_SPM_SUSPEDN_H + +#include + +#define MCUPM_MBOX_OFFSET_PDN (0x0C55FDA8) +#define MCUPM_POWER_DOWN (0x4D50444E) + +enum MT_SPM_SUSPEND_MODE { + MT_SPM_SUSPEND_SYSTEM_PDN = 0U, + MT_SPM_SUSPEND_SLEEP = 1U, +}; + +extern int mt_spm_suspend_mode_set(int mode); +extern int mt_spm_suspend_enter(int state_id, unsigned int ext_opand, + unsigned int reosuce_req); +extern void mt_spm_suspend_resume(int state_id, unsigned int ext_opand, + struct wake_status **status); +extern void mt_spm_suspend_init(void); + +#endif /* MT_SPM_SUSPEND_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c new file mode 100644 index 0000000..fb51e69 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c @@ -0,0 +1,533 @@ +/* + * Copyright(C)2022, MediaTek Inc. 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 + +#define VCORE_CT_ENABLE BIT(5) +#define VCORE_DRM_ENABLE BIT(31) +#define VCORE_PTPOD_SHIFT (8) +#define VCORE_POWER_SHIFT (2) + +#define VCORE_MAX_OPP (3) +#define DRAM_MAX_OPP (6) + +#define SW_REQ5_INIT_VAL (6U << 12) +#define V_VMODE_SHIFT (0) +#define VCORE_HV (105) +#define VCORE_LV (95) +#define PMIC_STEP_UV (6250) + +static int vcore_opp_0_uv = 800000; +static int vcore_opp_1_uv = 700000; +static int vcore_opp_2_uv = 650000; + +static struct pwr_ctrl vcorefs_ctrl = { + .wake_src = R12_REG_CPU_WAKEUP, + + /* default VCORE DVFS is disabled */ + .pcm_flags = (SPM_FLAG_RUN_COMMON_SCENARIO | + SPM_FLAG_DISABLE_VCORE_DVS | + SPM_FLAG_DISABLE_VCORE_DFS), + + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + .reg_wfi_op = 0, + .reg_wfi_type = 0, + .reg_mp0_cputop_idle_mask = 0, + .reg_mp1_cputop_idle_mask = 0, + .reg_mcusys_idle_mask = 0, + .reg_md_apsrc_1_sel = 0, + .reg_md_apsrc_0_sel = 0, + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC6_MASK */ + .reg_ccif_event_infra_req_mask_b = 0xFFFF, + .reg_ccif_event_apsrc_req_mask_b = 0xFFFF, + + /* SPM_SRC_REQ */ + .reg_spm_apsrc_req = 1, + .reg_spm_f26m_req = 1, + .reg_spm_infra_req = 1, + .reg_spm_vrf18_req = 1, + .reg_spm_ddren_req = 1, + .reg_spm_dvfs_req = 0, + .reg_spm_sw_mailbox_req = 0, + .reg_spm_sspm_mailbox_req = 0, + .reg_spm_adsp_mailbox_req = 0, + .reg_spm_scp_mailbox_req = 0, + + /* SPM_SRC_MASK */ + .reg_md_0_srcclkena_mask_b = 1, + .reg_md_0_infra_req_mask_b = 1, + .reg_md_0_apsrc_req_mask_b = 1, + .reg_md_0_vrf18_req_mask_b = 1, + .reg_md_0_ddren_req_mask_b = 1, + .reg_md_1_srcclkena_mask_b = 0, + .reg_md_1_infra_req_mask_b = 0, + .reg_md_1_apsrc_req_mask_b = 0, + .reg_md_1_vrf18_req_mask_b = 0, + .reg_md_1_ddren_req_mask_b = 0, + .reg_conn_srcclkena_mask_b = 1, + .reg_conn_srcclkenb_mask_b = 0, + .reg_conn_infra_req_mask_b = 1, + .reg_conn_apsrc_req_mask_b = 1, + .reg_conn_vrf18_req_mask_b = 1, + .reg_conn_ddren_req_mask_b = 1, + .reg_conn_vfe28_mask_b = 0, + .reg_srcclkeni_srcclkena_mask_b = 1, + .reg_srcclkeni_infra_req_mask_b = 1, + .reg_infrasys_apsrc_req_mask_b = 0, + .reg_infrasys_ddren_req_mask_b = 1, + .reg_sspm_srcclkena_mask_b = 1, + .reg_sspm_infra_req_mask_b = 1, + .reg_sspm_apsrc_req_mask_b = 1, + .reg_sspm_vrf18_req_mask_b = 1, + .reg_sspm_ddren_req_mask_b = 1, + + /* SPM_SRC2_MASK */ + .reg_scp_srcclkena_mask_b = 1, + .reg_scp_infra_req_mask_b = 1, + .reg_scp_apsrc_req_mask_b = 1, + .reg_scp_vrf18_req_mask_b = 1, + .reg_scp_ddren_req_mask_b = 1, + .reg_audio_dsp_srcclkena_mask_b = 1, + .reg_audio_dsp_infra_req_mask_b = 1, + .reg_audio_dsp_apsrc_req_mask_b = 1, + .reg_audio_dsp_vrf18_req_mask_b = 1, + .reg_audio_dsp_ddren_req_mask_b = 1, + .reg_ufs_srcclkena_mask_b = 1, + .reg_ufs_infra_req_mask_b = 1, + .reg_ufs_apsrc_req_mask_b = 1, + .reg_ufs_vrf18_req_mask_b = 1, + .reg_ufs_ddren_req_mask_b = 1, + .reg_disp0_apsrc_req_mask_b = 1, + .reg_disp0_ddren_req_mask_b = 1, + .reg_disp1_apsrc_req_mask_b = 1, + .reg_disp1_ddren_req_mask_b = 1, + .reg_gce_infra_req_mask_b = 1, + .reg_gce_apsrc_req_mask_b = 1, + .reg_gce_vrf18_req_mask_b = 1, + .reg_gce_ddren_req_mask_b = 1, + .reg_apu_srcclkena_mask_b = 0, + .reg_apu_infra_req_mask_b = 0, + .reg_apu_apsrc_req_mask_b = 0, + .reg_apu_vrf18_req_mask_b = 0, + .reg_apu_ddren_req_mask_b = 0, + .reg_cg_check_srcclkena_mask_b = 0, + .reg_cg_check_apsrc_req_mask_b = 0, + .reg_cg_check_vrf18_req_mask_b = 0, + .reg_cg_check_ddren_req_mask_b = 0, + + /* SPM_SRC3_MASK */ + .reg_dvfsrc_event_trigger_mask_b = 1, + .reg_sw2spm_wakeup_mask_b = 0, + .reg_adsp2spm_wakeup_mask_b = 0, + .reg_sspm2spm_wakeup_mask_b = 0, + .reg_scp2spm_wakeup_mask_b = 0, + .reg_csyspwrup_ack_mask = 1, + .reg_spm_reserved_srcclkena_mask_b = 0, + .reg_spm_reserved_infra_req_mask_b = 0, + .reg_spm_reserved_apsrc_req_mask_b = 0, + .reg_spm_reserved_vrf18_req_mask_b = 0, + .reg_spm_reserved_ddren_req_mask_b = 0, + .reg_mcupm_srcclkena_mask_b = 1, + .reg_mcupm_infra_req_mask_b = 1, + .reg_mcupm_apsrc_req_mask_b = 1, + .reg_mcupm_vrf18_req_mask_b = 1, + .reg_mcupm_ddren_req_mask_b = 1, + .reg_msdc0_srcclkena_mask_b = 1, + .reg_msdc0_infra_req_mask_b = 1, + .reg_msdc0_apsrc_req_mask_b = 1, + .reg_msdc0_vrf18_req_mask_b = 1, + .reg_msdc0_ddren_req_mask_b = 1, + .reg_msdc1_srcclkena_mask_b = 1, + .reg_msdc1_infra_req_mask_b = 1, + .reg_msdc1_apsrc_req_mask_b = 1, + .reg_msdc1_vrf18_req_mask_b = 1, + .reg_msdc1_ddren_req_mask_b = 1, + + /* SPM_SRC4_MASK */ + .reg_ccif_event_srcclkena_mask_b = 0x3FF, + .reg_bak_psri_srcclkena_mask_b = 0, + .reg_bak_psri_infra_req_mask_b = 0, + .reg_bak_psri_apsrc_req_mask_b = 0, + .reg_bak_psri_vrf18_req_mask_b = 0, + .reg_bak_psri_ddren_req_mask_b = 0, + .reg_dramc_md32_infra_req_mask_b = 1, + .reg_dramc_md32_vrf18_req_mask_b = 0, + .reg_conn_srcclkenb2pwrap_mask_b = 0, + .reg_dramc_md32_apsrc_req_mask_b = 0, + + /* SPM_SRC5_MASK */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x14, + .reg_mcusys_merge_ddren_req_mask_b = 0x14, + .reg_afe_srcclkena_mask_b = 0, + .reg_afe_infra_req_mask_b = 0, + .reg_afe_apsrc_req_mask_b = 0, + .reg_afe_vrf18_req_mask_b = 0, + .reg_afe_ddren_req_mask_b = 0, + .reg_msdc2_srcclkena_mask_b = 0, + .reg_msdc2_infra_req_mask_b = 0, + .reg_msdc2_apsrc_req_mask_b = 0, + .reg_msdc2_vrf18_req_mask_b = 0, + .reg_msdc2_ddren_req_mask_b = 0, + + /* SPM_WAKEUP_EVENT_MASK */ + .reg_wakeup_event_mask = 0xEFFFFFFF, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, + + /* SPM_SRC7_MASK */ + .reg_pcie_srcclkena_mask_b = 1, + .reg_pcie_infra_req_mask_b = 1, + .reg_pcie_apsrc_req_mask_b = 1, + .reg_pcie_vrf18_req_mask_b = 1, + .reg_pcie_ddren_req_mask_b = 1, + .reg_dpmaif_srcclkena_mask_b = 1, + .reg_dpmaif_infra_req_mask_b = 1, + .reg_dpmaif_apsrc_req_mask_b = 1, + .reg_dpmaif_vrf18_req_mask_b = 1, + .reg_dpmaif_ddren_req_mask_b = 1, + + /* Auto-gen End */ +}; + +struct spm_lp_scen __spm_vcorefs = { + .pwrctrl = &vcorefs_ctrl, +}; + +static struct reg_config dvfsrc_init_configs[] = { + {DVFSRC_HRT_REQ_UNIT, 0x0000001E}, + {DVFSRC_DEBOUNCE_TIME, 0x00001965}, + {DVFSRC_TIMEOUT_NEXTREQ, 0x00000015}, + {DVFSRC_VCORE_REQUEST4, 0x22211100}, + {DVFSRC_DDR_QOS0, 0x00000019}, + {DVFSRC_DDR_QOS1, 0x00000026}, + {DVFSRC_DDR_QOS2, 0x00000033}, + {DVFSRC_DDR_QOS3, 0x0000004C}, + {DVFSRC_DDR_QOS4, 0x00000066}, + {DVFSRC_DDR_QOS5, 0x00000077}, + {DVFSRC_DDR_QOS6, 0x00770077}, + {DVFSRC_LEVEL_LABEL_0_1, 0x40225032}, + {DVFSRC_LEVEL_LABEL_2_3, 0x20223012}, + {DVFSRC_LEVEL_LABEL_4_5, 0x40211012}, + {DVFSRC_LEVEL_LABEL_6_7, 0x20213011}, + {DVFSRC_LEVEL_LABEL_8_9, 0x30101011}, + {DVFSRC_LEVEL_LABEL_10_11, 0x10102000}, + {DVFSRC_LEVEL_LABEL_12_13, 0x00000000}, + {DVFSRC_LEVEL_LABEL_14_15, 0x00000000}, + {DVFSRC_LEVEL_LABEL_16_17, 0x00000000}, + {DVFSRC_LEVEL_LABEL_18_19, 0x00000000}, + {DVFSRC_LEVEL_LABEL_20_21, 0x00000000}, + {DVFSRC_LEVEL_MASK, 0x00000000}, + {DVFSRC_MD_LATENCY_IMPROVE, 0x00000020}, + {DVFSRC_HRT_BW_BASE, 0x00000004}, + {DVSFRC_HRT_REQ_MD_URG, 0x000D50D5}, + {DVFSRC_HRT_REQ_MD_BW_0, 0x00200802}, + {DVFSRC_HRT_REQ_MD_BW_1, 0x00200802}, + {DVFSRC_HRT_REQ_MD_BW_2, 0x00200800}, + {DVFSRC_HRT_REQ_MD_BW_3, 0x00400802}, + {DVFSRC_HRT_REQ_MD_BW_4, 0x00601404}, + {DVFSRC_HRT_REQ_MD_BW_5, 0x00D02C09}, + {DVFSRC_HRT_REQ_MD_BW_6, 0x00000012}, + {DVFSRC_HRT_REQ_MD_BW_7, 0x00000024}, + {DVFSRC_HRT_REQ_MD_BW_8, 0x00000000}, + {DVFSRC_HRT_REQ_MD_BW_9, 0x00000000}, + {DVFSRC_HRT_REQ_MD_BW_10, 0x00035400}, + {DVFSRC_HRT1_REQ_MD_BW_0, 0x04B12C4B}, + {DVFSRC_HRT1_REQ_MD_BW_1, 0x04B12C4B}, + {DVFSRC_HRT1_REQ_MD_BW_2, 0x04B12C00}, + {DVFSRC_HRT1_REQ_MD_BW_3, 0x04B12C4B}, + {DVFSRC_HRT1_REQ_MD_BW_4, 0x04B12C4B}, + {DVFSRC_HRT1_REQ_MD_BW_5, 0x04B12C4B}, + {DVFSRC_HRT1_REQ_MD_BW_6, 0x0000004B}, + {DVFSRC_HRT1_REQ_MD_BW_7, 0x0000005C}, + {DVFSRC_HRT1_REQ_MD_BW_8, 0x00000000}, + {DVFSRC_HRT1_REQ_MD_BW_9, 0x00000000}, + {DVFSRC_HRT1_REQ_MD_BW_10, 0x00035400}, + {DVFSRC_95MD_SCEN_BW0_T, 0x22222220}, + {DVFSRC_95MD_SCEN_BW1_T, 0x22222222}, + {DVFSRC_95MD_SCEN_BW2_T, 0x22222222}, + {DVFSRC_95MD_SCEN_BW3_T, 0x52222222}, + {DVFSRC_95MD_SCEN_BW4, 0x00000005}, + {DVFSRC_RSRV_5, 0x00000001}, +#ifdef DVFSRC_1600_FLOOR + {DVFSRC_DDR_REQUEST, 0x00000022}, +#else + {DVFSRC_DDR_REQUEST, 0x00000021}, +#endif + {DVFSRC_DDR_REQUEST3, 0x00554300}, + {DVFSRC_DDR_ADD_REQUEST, 0x55543210}, +#ifdef DVFSRC_1600_FLOOR + {DVFSRC_DDR_REQUEST5, 0x54322000}, +#else + {DVFSRC_DDR_REQUEST5, 0x54321000}, +#endif + {DVFSRC_DDR_REQUEST6, 0x53143130}, + {DVFSRC_DDR_REQUEST7, 0x55000000}, + {DVFSRC_DDR_REQUEST8, 0x05000000}, + {DVFSRC_EMI_MON_DEBOUNCE_TIME, 0x4C2D0000}, + {DVFSRC_EMI_ADD_REQUEST, 0x55543210}, + {DVFSRC_VCORE_USER_REQ, 0x00010A29}, + {DVFSRC_HRT_HIGH, 0x0E100960}, + {DVFSRC_HRT_HIGH_1, 0x1AD21700}, + {DVFSRC_HRT_HIGH_2, 0x314C2306}, + {DVFSRC_HRT_HIGH_3, 0x314C314C}, + {DVFSRC_HRT_LOW, 0x0E0F095F}, + {DVFSRC_HRT_LOW_1, 0x1AD116FF}, + {DVFSRC_HRT_LOW_2, 0x314B2305}, + {DVFSRC_HRT_LOW_3, 0x314B314B}, +#ifdef DVFSRC_1600_FLOOR + {DVFSRC_HRT_REQUEST, 0x55554322}, +#else + {DVFSRC_HRT_REQUEST, 0x55554321}, +#endif + {DVFSRC_BASIC_CONTROL_3, 0x0000000E}, + {DVFSRC_INT_EN, 0x00000002}, + {DVFSRC_QOS_EN, 0x001e407C}, + {DVFSRC_CURRENT_FORCE, 0x00000001}, + {DVFSRC_BASIC_CONTROL, 0x0180004B}, + {DVFSRC_BASIC_CONTROL, 0X0180404B}, + {DVFSRC_BASIC_CONTROL, 0X0180014B}, + {DVFSRC_CURRENT_FORCE, 0x00000000}, +}; + +#define IS_PMIC_57() ((pmic_get_hwcid() >> 8) == 0x57) + +static inline unsigned int vcore_base_uv(void) +{ + static unsigned int vb; + + if (vb == 0) { + vb = IS_PMIC_57() ? 518750 : 500000; + } + + return vb; +} + +#define _VCORE_STEP_UV (6250) + +#define __vcore_uv_to_pmic(uv) /* pmic >= uv */ \ + ((((uv) - vcore_base_uv()) + (_VCORE_STEP_UV - 1)) / _VCORE_STEP_UV) + +static int devinfo_table[] = { + 3539, 492, 1038, 106, 231, 17, 46, 2179, + 4, 481, 1014, 103, 225, 17, 45, 2129, + 3, 516, 1087, 111, 242, 19, 49, 2282, + 4, 504, 1063, 108, 236, 18, 47, 2230, + 4, 448, 946, 96, 210, 15, 41, 1986, + 2, 438, 924, 93, 205, 14, 40, 1941, + 2, 470, 991, 101, 220, 16, 43, 2080, + 3, 459, 968, 98, 215, 16, 42, 2033, + 3, 594, 1250, 129, 279, 23, 57, 2621, + 6, 580, 1221, 126, 273, 22, 56, 2561, + 6, 622, 1309, 136, 293, 24, 60, 2745, + 7, 608, 1279, 132, 286, 23, 59, 2683, + 6, 541, 1139, 117, 254, 20, 51, 2390, + 5, 528, 1113, 114, 248, 19, 50, 2335, + 4, 566, 1193, 123, 266, 21, 54, 2503, + 5, 553, 1166, 120, 260, 21, 53, 2446, + 5, 338, 715, 70, 157, 9, 29, 1505, + 3153, 330, 699, 69, 153, 9, 28, 1470, + 3081, 354, 750, 74, 165, 10, 31, 1576, + 3302, 346, 732, 72, 161, 10, 30, 1540, + 3227, 307, 652, 63, 142, 8, 26, 1371, + 2875, 300, 637, 62, 139, 7, 25, 1340, + 2809, 322, 683, 67, 149, 8, 27, 1436, + 3011, 315, 667, 65, 146, 8, 26, 1404, + 2942, 408, 862, 86, 191, 13, 37, 1811, + 1, 398, 842, 84, 186, 12, 36, 1769, + 1, 428, 903, 91, 200, 14, 39, 1896, + 2, 418, 882, 89, 195, 13, 38, 1853, + 2, 371, 785, 78, 173, 11, 33, 1651, + 3458, 363, 767, 76, 169, 10, 32, 1613, + 3379, 389, 823, 82, 182, 12, 35, 1729, + 1, 380, 804, 80, 177, 11, 34, 1689, +}; + +static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val) +{ + if (cmd < NR_IDX_ALL) { + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val); + } else { + INFO("cmd out of range!\n"); + } +} + +void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue) +{ + mmio_write_32(OPP0_TABLE, 0xFFFF0000); + mmio_write_32(OPP1_TABLE, 0xFFFF0100); + mmio_write_32(OPP2_TABLE, 0xFFFF0300); + mmio_write_32(OPP3_TABLE, 0xFFFF0500); + mmio_write_32(OPP4_TABLE, 0xFFFF0700); + mmio_write_32(OPP5_TABLE, 0xFFFF0202); + mmio_write_32(OPP6_TABLE, 0xFFFF0302); + mmio_write_32(OPP7_TABLE, 0xFFFF0502); + mmio_write_32(OPP8_TABLE, 0xFFFF0702); + mmio_write_32(OPP9_TABLE, 0xFFFF0403); + mmio_write_32(OPP10_TABLE, 0xFFFF0603); + mmio_write_32(OPP11_TABLE, 0xFFFF0803); + mmio_write_32(OPP12_TABLE, 0xFFFF0903); + mmio_write_32(OPP13_TABLE, 0xFFFFFFFF); + mmio_write_32(OPP14_TABLE, 0xFFFFFFFF); + mmio_write_32(OPP15_TABLE, 0xFFFFFFFF); + mmio_write_32(OPP16_TABLE, 0xFFFFFFFF); + mmio_write_32(OPP17_TABLE, 0xFFFFFFFF); + mmio_write_32(SHU0_ARRAY, 0xFFFFFF00); + mmio_write_32(SHU1_ARRAY, 0xFFFFEE01); + mmio_write_32(SHU2_ARRAY, 0xFF05EEFF); + mmio_write_32(SHU3_ARRAY, 0xFF06EE02); + mmio_write_32(SHU4_ARRAY, 0x0906FFFF); + mmio_write_32(SHU5_ARRAY, 0xFF07EE03); + mmio_write_32(SHU6_ARRAY, 0x0A07FFFF); + mmio_write_32(SHU7_ARRAY, 0xFF08EE04); + mmio_write_32(SHU8_ARRAY, 0x0B08FFFF); + mmio_write_32(SHU9_ARRAY, 0x0CFFFFFF); + + mmio_clrsetbits_32(SPM_DVFS_MISC, SPM_DVFS_FORCE_ENABLE_LSB, + SPM_DVFSRC_ENABLE_LSB); + + mmio_write_32(SPM_DVFS_LEVEL, 0x00000001); + mmio_write_32(SPM_DVS_DFS_LEVEL, 0x00010001); +} + +void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl, + const struct pwr_ctrl *src_pwr_ctrl) +{ + uint32_t dvfs_mask = SPM_FLAG_DISABLE_VCORE_DVS | + SPM_FLAG_DISABLE_VCORE_DFS | + SPM_FLAG_ENABLE_VOLTAGE_BIN; + + dest_pwr_ctrl->pcm_flags = (dest_pwr_ctrl->pcm_flags & (~dvfs_mask)) | + (src_pwr_ctrl->pcm_flags & dvfs_mask); + + if (dest_pwr_ctrl->pcm_flags_cust > 0U) { + dest_pwr_ctrl->pcm_flags_cust = + ((dest_pwr_ctrl->pcm_flags_cust) & (~dvfs_mask)) | + ((src_pwr_ctrl->pcm_flags) & (dvfs_mask)); + } +} + +static void spm_go_to_vcorefs(void) +{ + __spm_set_power_control(__spm_vcorefs.pwrctrl); + __spm_set_wakeup_event(__spm_vcorefs.pwrctrl); + __spm_set_pcm_flags(__spm_vcorefs.pwrctrl); + __spm_send_cpu_wakeup_event(); +} + +static void dvfsrc_init(void) +{ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(dvfsrc_init_configs); i++) { + mmio_write_32(dvfsrc_init_configs[i].offset, + dvfsrc_init_configs[i].val); + } +} + +static void spm_vcorefs_vcore_setting(uint64_t flag) +{ + int idx, ptpod, rsv4; + int power = 0; + + switch (flag) { + case 1: /*HV*/ + vcore_opp_0_uv = 840000; + vcore_opp_1_uv = 725000; + vcore_opp_2_uv = 682500; + break; + case 2: /*LV*/ + vcore_opp_0_uv = 760000; + vcore_opp_1_uv = 665000; + vcore_opp_2_uv = 617500; + break; + default: + break; + } + + rsv4 = mmio_read_32(DVFSRC_RSRV_4); + ptpod = (rsv4 >> VCORE_PTPOD_SHIFT) & 0xF; + idx = (rsv4 >> VCORE_POWER_SHIFT) & 0xFF; + + if (idx != 0) { + power = (int)devinfo_table[idx]; + } + + if (power > 0 && power <= 40) { + idx = ptpod & 0xF; + if (idx == 1) { + vcore_opp_2_uv = 700000; + } else if (idx > 1 && idx < 10) { + vcore_opp_2_uv = 675000; + } + } + + spm_vcorefs_pwarp_cmd(3, __vcore_uv_to_pmic(vcore_opp_2_uv)); + spm_vcorefs_pwarp_cmd(2, __vcore_uv_to_pmic(vcore_opp_1_uv)); + spm_vcorefs_pwarp_cmd(0, __vcore_uv_to_pmic(vcore_opp_0_uv)); +} + +uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t *x4) +{ + uint64_t cmd = x1; + uint64_t spm_flags; + + switch (cmd) { + case VCOREFS_SMC_CMD_INIT: + /* vcore_dvfs init + kick */ + mmio_write_32(DVFSRC_SW_REQ5, SW_REQ5_INIT_VAL); + spm_dvfsfw_init(0ULL, 0ULL); + spm_vcorefs_vcore_setting(x3 & 0xF); + spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO; + if ((x2 & 0x1) > 0U) { + spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS; + } + + if ((x2 & 0x2) > 0U) { + spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS; + } + + if ((mmio_read_32(DVFSRC_RSRV_4) & VCORE_CT_ENABLE) > 0U) { + spm_flags |= SPM_FLAG_ENABLE_VOLTAGE_BIN; + } + + set_pwrctrl_pcm_flags(__spm_vcorefs.pwrctrl, spm_flags); + spm_go_to_vcorefs(); + dvfsrc_init(); + + *x4 = 0U; + mmio_write_32(DVFSRC_SW_REQ5, 0U); + break; + case VCOREFS_SMC_CMD_KICK: + mmio_write_32(DVFSRC_SW_REQ5, 0U); + break; + default: + break; + } + + return 0ULL; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h new file mode 100644 index 0000000..4fe1b12 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h @@ -0,0 +1,316 @@ +/* + * Copyright(C)2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_VCOREFS_H +#define MT_SPM_VCOREFS_H + +uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t *x4); + +enum vcorefs_smc_cmd { + VCOREFS_SMC_CMD_0 = 0U, + VCOREFS_SMC_CMD_1 = 1U, + VCOREFS_SMC_CMD_2 = 2U, + VCOREFS_SMC_CMD_3 = 3U, + VCOREFS_SMC_CMD_4 = 4U, + /* check spmfw status */ + VCOREFS_SMC_CMD_5 = 5U, + + /* get spmfw type */ + VCOREFS_SMC_CMD_6 = 6U, + + /* get spm reg status */ + VCOREFS_SMC_CMD_7 = 7U, + + NUM_VCOREFS_SMC_CMD = 8U, +}; + +enum vcorefs_smc_cmd_new { + VCOREFS_SMC_CMD_INIT = 0U, + VCOREFS_SMC_CMD_KICK = 1U, + VCOREFS_SMC_CMD_OPP_TYPE = 2U, + VCOREFS_SMC_CMD_FW_TYPE = 3U, + VCOREFS_SMC_CMD_GET_UV = 4U, + VCOREFS_SMC_CMD_GET_FREQ = 5U, + VCOREFS_SMC_CMD_GET_NUM_V = 6U, + VCOREFS_SMC_CMD_GET_NUM_F = 7U, + VCOREFS_SMC_CMD_FB_ACTION = 8U, + /*chip specific setting */ + VCOREFS_SMC_CMD_SET_FREQ = 16U, + VCOREFS_SMC_CMD_SET_EFUSE = 17U, + VCOREFS_SMC_CMD_GET_EFUSE = 18U, + VCOREFS_SMC_CMD_DVFS_HOPPING = 19U, + VCOREFS_SMC_CMD_DVFS_HOPPING_STATE = 20U, +}; + +enum dvfsrc_channel { + DVFSRC_CHANNEL_1 = 1U, + DVFSRC_CHANNEL_2 = 2U, + DVFSRC_CHANNEL_3 = 3U, + DVFSRC_CHANNEL_4 = 4U, + NUM_DVFSRC_CHANNEL = 5U, +}; + +struct reg_config { + uint32_t offset; + uint32_t val; +}; + +#define DVFSRC_BASIC_CONTROL (DVFSRC_BASE + 0x0) +#define DVFSRC_SW_REQ1 (DVFSRC_BASE + 0x4) +#define DVFSRC_SW_REQ2 (DVFSRC_BASE + 0x8) +#define DVFSRC_SW_REQ3 (DVFSRC_BASE + 0xC) +#define DVFSRC_SW_REQ4 (DVFSRC_BASE + 0x10) +#define DVFSRC_SW_REQ5 (DVFSRC_BASE + 0x14) +#define DVFSRC_SW_REQ6 (DVFSRC_BASE + 0x18) +#define DVFSRC_SW_REQ7 (DVFSRC_BASE + 0x1C) +#define DVFSRC_SW_REQ8 (DVFSRC_BASE + 0x20) +#define DVFSRC_EMI_REQUEST (DVFSRC_BASE + 0x24) +#define DVFSRC_EMI_REQUEST2 (DVFSRC_BASE + 0x28) +#define DVFSRC_EMI_REQUEST3 (DVFSRC_BASE + 0x2C) +#define DVFSRC_EMI_REQUEST4 (DVFSRC_BASE + 0x30) +#define DVFSRC_EMI_REQUEST5 (DVFSRC_BASE + 0x34) +#define DVFSRC_EMI_REQUEST6 (DVFSRC_BASE + 0x38) +#define DVFSRC_EMI_HRT (DVFSRC_BASE + 0x3C) +#define DVFSRC_EMI_HRT2 (DVFSRC_BASE + 0x40) +#define DVFSRC_EMI_HRT3 (DVFSRC_BASE + 0x44) +#define DVFSRC_EMI_QOS0 (DVFSRC_BASE + 0x48) +#define DVFSRC_EMI_QOS1 (DVFSRC_BASE + 0x4C) +#define DVFSRC_EMI_QOS2 (DVFSRC_BASE + 0x50) +#define DVFSRC_EMI_MD2SPM0 (DVFSRC_BASE + 0x54) +#define DVFSRC_EMI_MD2SPM1 (DVFSRC_BASE + 0x58) +#define DVFSRC_EMI_MD2SPM2 (DVFSRC_BASE + 0x5C) +#define DVFSRC_EMI_MD2SPM0_T (DVFSRC_BASE + 0x60) +#define DVFSRC_EMI_MD2SPM1_T (DVFSRC_BASE + 0x64) +#define DVFSRC_EMI_MD2SPM2_T (DVFSRC_BASE + 0x68) +#define DVFSRC_VCORE_REQUEST (DVFSRC_BASE + 0x6C) +#define DVFSRC_VCORE_REQUEST2 (DVFSRC_BASE + 0x70) +#define DVFSRC_VCORE_REQUEST3 (DVFSRC_BASE + 0x74) +#define DVFSRC_VCORE_REQUEST4 (DVFSRC_BASE + 0x78) +#define DVFSRC_VCORE_HRT (DVFSRC_BASE + 0x7C) +#define DVFSRC_VCORE_HRT2 (DVFSRC_BASE + 0x80) +#define DVFSRC_VCORE_HRT3 (DVFSRC_BASE + 0x84) +#define DVFSRC_VCORE_QOS0 (DVFSRC_BASE + 0x88) +#define DVFSRC_VCORE_QOS1 (DVFSRC_BASE + 0x8C) +#define DVFSRC_VCORE_QOS2 (DVFSRC_BASE + 0x90) +#define DVFSRC_VCORE_MD2SPM0 (DVFSRC_BASE + 0x94) +#define DVFSRC_VCORE_MD2SPM1 (DVFSRC_BASE + 0x98) +#define DVFSRC_VCORE_MD2SPM2 (DVFSRC_BASE + 0x9C) +#define DVFSRC_VCORE_MD2SPM0_T (DVFSRC_BASE + 0xA0) +#define DVFSRC_VCORE_MD2SPM1_T (DVFSRC_BASE + 0xA4) +#define DVFSRC_VCORE_MD2SPM2_T (DVFSRC_BASE + 0xA8) +#define DVFSRC_MD_VSRAM_REMAP (DVFSRC_BASE + 0xBC) +#define DVFSRC_HALT_SW_CONTROL (DVFSRC_BASE + 0xC0) +#define DVFSRC_INT (DVFSRC_BASE + 0xC4) +#define DVFSRC_INT_EN (DVFSRC_BASE + 0xC8) +#define DVFSRC_INT_CLR (DVFSRC_BASE + 0xCC) +#define DVFSRC_BW_MON_WINDOW (DVFSRC_BASE + 0xD0) +#define DVFSRC_BW_MON_THRES_1 (DVFSRC_BASE + 0xD4) +#define DVFSRC_BW_MON_THRES_2 (DVFSRC_BASE + 0xD8) +#define DVFSRC_MD_TURBO (DVFSRC_BASE + 0xDC) +#define DVFSRC_VCORE_USER_REQ (DVFSRC_BASE + 0xE4) +#define DVFSRC_DEBOUNCE_FOUR (DVFSRC_BASE + 0xF0) +#define DVFSRC_DEBOUNCE_RISE_FALL (DVFSRC_BASE + 0xF4) +#define DVFSRC_TIMEOUT_NEXTREQ (DVFSRC_BASE + 0xF8) +#define DVFSRC_LEVEL_LABEL_0_1 (DVFSRC_BASE + 0x100) +#define DVFSRC_LEVEL_LABEL_2_3 (DVFSRC_BASE + 0x104) +#define DVFSRC_LEVEL_LABEL_4_5 (DVFSRC_BASE + 0x108) +#define DVFSRC_LEVEL_LABEL_6_7 (DVFSRC_BASE + 0x10C) +#define DVFSRC_LEVEL_LABEL_8_9 (DVFSRC_BASE + 0x110) +#define DVFSRC_LEVEL_LABEL_10_11 (DVFSRC_BASE + 0x114) +#define DVFSRC_LEVEL_LABEL_12_13 (DVFSRC_BASE + 0x118) +#define DVFSRC_LEVEL_LABEL_14_15 (DVFSRC_BASE + 0x11C) +#define DVFSRC_MM_BW_0 (DVFSRC_BASE + 0x200) +#define DVFSRC_MM_BW_1 (DVFSRC_BASE + 0x204) +#define DVFSRC_MM_BW_2 (DVFSRC_BASE + 0x208) +#define DVFSRC_MM_BW_3 (DVFSRC_BASE + 0x20C) +#define DVFSRC_MM_BW_4 (DVFSRC_BASE + 0x210) +#define DVFSRC_MM_BW_5 (DVFSRC_BASE + 0x214) +#define DVFSRC_MM_BW_6 (DVFSRC_BASE + 0x218) +#define DVFSRC_MM_BW_7 (DVFSRC_BASE + 0x21C) +#define DVFSRC_MM_BW_8 (DVFSRC_BASE + 0x220) +#define DVFSRC_MM_BW_9 (DVFSRC_BASE + 0x224) +#define DVFSRC_MM_BW_10 (DVFSRC_BASE + 0x228) +#define DVFSRC_MM_BW_11 (DVFSRC_BASE + 0x22C) +#define DVFSRC_MM_BW_12 (DVFSRC_BASE + 0x230) +#define DVFSRC_MM_BW_13 (DVFSRC_BASE + 0x234) +#define DVFSRC_MM_BW_14 (DVFSRC_BASE + 0x238) +#define DVFSRC_MM_BW_15 (DVFSRC_BASE + 0x23C) +#define DVFSRC_MD_BW_0 (DVFSRC_BASE + 0x240) +#define DVFSRC_MD_BW_1 (DVFSRC_BASE + 0x244) +#define DVFSRC_MD_BW_2 (DVFSRC_BASE + 0x248) +#define DVFSRC_MD_BW_3 (DVFSRC_BASE + 0x24C) +#define DVFSRC_MD_BW_4 (DVFSRC_BASE + 0x250) +#define DVFSRC_MD_BW_5 (DVFSRC_BASE + 0x254) +#define DVFSRC_MD_BW_6 (DVFSRC_BASE + 0x258) +#define DVFSRC_MD_BW_7 (DVFSRC_BASE + 0x25C) +#define DVFSRC_SW_BW_0 (DVFSRC_BASE + 0x260) +#define DVFSRC_SW_BW_1 (DVFSRC_BASE + 0x264) +#define DVFSRC_SW_BW_2 (DVFSRC_BASE + 0x268) +#define DVFSRC_SW_BW_3 (DVFSRC_BASE + 0x26C) +#define DVFSRC_SW_BW_4 (DVFSRC_BASE + 0x270) +#define DVFSRC_SW_BW_5 (DVFSRC_BASE + 0x274) +#define DVFSRC_SW_BW_6 (DVFSRC_BASE + 0x278) +#define DVFSRC_QOS_EN (DVFSRC_BASE + 0x280) +#define DVFSRC_MD_BW_URG (DVFSRC_BASE + 0x284) +#define DVFSRC_ISP_HRT (DVFSRC_BASE + 0x290) +#define DVFSRC_HRT_BW_BASE (DVFSRC_BASE + 0x294) +#define DVFSRC_SEC_SW_REQ (DVFSRC_BASE + 0x304) +#define DVFSRC_EMI_MON_DEBOUNCE_TIME (DVFSRC_BASE + 0x308) +#define DVFSRC_MD_LATENCY_IMPROVE (DVFSRC_BASE + 0x30C) +#define DVFSRC_BASIC_CONTROL_3 (DVFSRC_BASE + 0x310) +#define DVFSRC_DEBOUNCE_TIME (DVFSRC_BASE + 0x314) +#define DVFSRC_LEVEL_MASK (DVFSRC_BASE + 0x318) +#define DVFSRC_95MD_SCEN_EMI0 (DVFSRC_BASE + 0x500) +#define DVFSRC_95MD_SCEN_EMI1 (DVFSRC_BASE + 0x504) +#define DVFSRC_95MD_SCEN_EMI2 (DVFSRC_BASE + 0x508) +#define DVFSRC_95MD_SCEN_EMI3 (DVFSRC_BASE + 0x50C) +#define DVFSRC_95MD_SCEN_EMI0_T (DVFSRC_BASE + 0x510) +#define DVFSRC_95MD_SCEN_EMI1_T (DVFSRC_BASE + 0x514) +#define DVFSRC_95MD_SCEN_EMI2_T (DVFSRC_BASE + 0x518) +#define DVFSRC_95MD_SCEN_EMI3_T (DVFSRC_BASE + 0x51C) +#define DVFSRC_95MD_SCEN_EMI4 (DVFSRC_BASE + 0x520) +#define DVFSRC_95MD_SCEN_BW0 (DVFSRC_BASE + 0x524) +#define DVFSRC_95MD_SCEN_BW1 (DVFSRC_BASE + 0x528) +#define DVFSRC_95MD_SCEN_BW2 (DVFSRC_BASE + 0x52C) +#define DVFSRC_95MD_SCEN_BW3 (DVFSRC_BASE + 0x530) +#define DVFSRC_95MD_SCEN_BW0_T (DVFSRC_BASE + 0x534) +#define DVFSRC_95MD_SCEN_BW1_T (DVFSRC_BASE + 0x538) +#define DVFSRC_95MD_SCEN_BW2_T (DVFSRC_BASE + 0x53C) +#define DVFSRC_95MD_SCEN_BW3_T (DVFSRC_BASE + 0x540) +#define DVFSRC_95MD_SCEN_BW4 (DVFSRC_BASE + 0x544) +#define DVFSRC_MD_LEVEL_SW_REG (DVFSRC_BASE + 0x548) +#define DVFSRC_RSRV_0 (DVFSRC_BASE + 0x600) +#define DVFSRC_RSRV_1 (DVFSRC_BASE + 0x604) +#define DVFSRC_RSRV_2 (DVFSRC_BASE + 0x608) +#define DVFSRC_RSRV_3 (DVFSRC_BASE + 0x60C) +#define DVFSRC_RSRV_4 (DVFSRC_BASE + 0x610) +#define DVFSRC_RSRV_5 (DVFSRC_BASE + 0x614) +#define DVFSRC_SPM_RESEND (DVFSRC_BASE + 0x630) +#define DVFSRC_DEBUG_STA_0 (DVFSRC_BASE + 0x700) +#define DVFSRC_DEBUG_STA_1 (DVFSRC_BASE + 0x704) +#define DVFSRC_DEBUG_STA_2 (DVFSRC_BASE + 0x708) +#define DVFSRC_DEBUG_STA_3 (DVFSRC_BASE + 0x70C) +#define DVFSRC_DEBUG_STA_4 (DVFSRC_BASE + 0x710) +#define DVFSRC_EMI_REQUEST7 (DVFSRC_BASE + 0x800) +#define DVFSRC_EMI_HRT_1 (DVFSRC_BASE + 0x804) +#define DVFSRC_EMI_HRT2_1 (DVFSRC_BASE + 0x808) +#define DVFSRC_EMI_HRT3_1 (DVFSRC_BASE + 0x80C) +#define DVFSRC_EMI_QOS3 (DVFSRC_BASE + 0x810) +#define DVFSRC_EMI_QOS4 (DVFSRC_BASE + 0x814) +#define DVFSRC_DDR_REQUEST (DVFSRC_BASE + 0xA00) +#define DVFSRC_DDR_REQUEST2 (DVFSRC_BASE + 0xA04) +#define DVFSRC_DDR_REQUEST3 (DVFSRC_BASE + 0xA08) +#define DVFSRC_DDR_REQUEST4 (DVFSRC_BASE + 0xA0C) +#define DVFSRC_DDR_REQUEST5 (DVFSRC_BASE + 0xA10) +#define DVFSRC_DDR_REQUEST6 (DVFSRC_BASE + 0xA14) +#define DVFSRC_DDR_REQUEST7 (DVFSRC_BASE + 0xA18) +#define DVFSRC_DDR_HRT (DVFSRC_BASE + 0xA1C) +#define DVFSRC_DDR_HRT2 (DVFSRC_BASE + 0xA20) +#define DVFSRC_DDR_HRT3 (DVFSRC_BASE + 0xA24) +#define DVFSRC_DDR_HRT_1 (DVFSRC_BASE + 0xA28) +#define DVFSRC_DDR_HRT2_1 (DVFSRC_BASE + 0xA2C) +#define DVFSRC_DDR_HRT3_1 (DVFSRC_BASE + 0xA30) +#define DVFSRC_DDR_QOS0 (DVFSRC_BASE + 0xA34) +#define DVFSRC_DDR_QOS1 (DVFSRC_BASE + 0xA38) +#define DVFSRC_DDR_QOS2 (DVFSRC_BASE + 0xA3C) +#define DVFSRC_DDR_QOS3 (DVFSRC_BASE + 0xA40) +#define DVFSRC_DDR_QOS4 (DVFSRC_BASE + 0xA44) +#define DVFSRC_DDR_MD2SPM0 (DVFSRC_BASE + 0xA48) +#define DVFSRC_DDR_MD2SPM1 (DVFSRC_BASE + 0xA4C) +#define DVFSRC_DDR_MD2SPM2 (DVFSRC_BASE + 0xA50) +#define DVFSRC_DDR_MD2SPM0_T (DVFSRC_BASE + 0xA54) +#define DVFSRC_DDR_MD2SPM1_T (DVFSRC_BASE + 0xA58) +#define DVFSRC_DDR_MD2SPM2_T (DVFSRC_BASE + 0xA5C) +#define DVFSRC_HRT_REQ_UNIT (DVFSRC_BASE + 0xA60) +#define DVSFRC_HRT_REQ_MD_URG (DVFSRC_BASE + 0xA64) +#define DVFSRC_HRT_REQ_MD_BW_0 (DVFSRC_BASE + 0xA68) +#define DVFSRC_HRT_REQ_MD_BW_1 (DVFSRC_BASE + 0xA6C) +#define DVFSRC_HRT_REQ_MD_BW_2 (DVFSRC_BASE + 0xA70) +#define DVFSRC_HRT_REQ_MD_BW_3 (DVFSRC_BASE + 0xA74) +#define DVFSRC_HRT_REQ_MD_BW_4 (DVFSRC_BASE + 0xA78) +#define DVFSRC_HRT_REQ_MD_BW_5 (DVFSRC_BASE + 0xA7C) +#define DVFSRC_HRT_REQ_MD_BW_6 (DVFSRC_BASE + 0xA80) +#define DVFSRC_HRT_REQ_MD_BW_7 (DVFSRC_BASE + 0xA84) +#define DVFSRC_HRT1_REQ_MD_BW_0 (DVFSRC_BASE + 0xA88) +#define DVFSRC_HRT1_REQ_MD_BW_1 (DVFSRC_BASE + 0xA8C) +#define DVFSRC_HRT1_REQ_MD_BW_2 (DVFSRC_BASE + 0xA90) +#define DVFSRC_HRT1_REQ_MD_BW_3 (DVFSRC_BASE + 0xA94) +#define DVFSRC_HRT1_REQ_MD_BW_4 (DVFSRC_BASE + 0xA98) +#define DVFSRC_HRT1_REQ_MD_BW_5 (DVFSRC_BASE + 0xA9C) +#define DVFSRC_HRT1_REQ_MD_BW_6 (DVFSRC_BASE + 0xAA0) +#define DVFSRC_HRT1_REQ_MD_BW_7 (DVFSRC_BASE + 0xAA4) +#define DVFSRC_HRT_REQ_MD_BW_8 (DVFSRC_BASE + 0xAA8) +#define DVFSRC_HRT_REQ_MD_BW_9 (DVFSRC_BASE + 0xAAC) +#define DVFSRC_HRT_REQ_MD_BW_10 (DVFSRC_BASE + 0xAB0) +#define DVFSRC_HRT1_REQ_MD_BW_8 (DVFSRC_BASE + 0xAB4) +#define DVFSRC_HRT1_REQ_MD_BW_9 (DVFSRC_BASE + 0xAB8) +#define DVFSRC_HRT1_REQ_MD_BW_10 (DVFSRC_BASE + 0xABC) +#define DVFSRC_HRT_REQ_BW_SW_REG (DVFSRC_BASE + 0xAC0) +#define DVFSRC_HRT_REQUEST (DVFSRC_BASE + 0xAC4) +#define DVFSRC_HRT_HIGH_2 (DVFSRC_BASE + 0xAC8) +#define DVFSRC_HRT_HIGH_1 (DVFSRC_BASE + 0xACC) +#define DVFSRC_HRT_HIGH (DVFSRC_BASE + 0xAD0) +#define DVFSRC_HRT_LOW_2 (DVFSRC_BASE + 0xAD4) +#define DVFSRC_HRT_LOW_1 (DVFSRC_BASE + 0xAD8) +#define DVFSRC_HRT_LOW (DVFSRC_BASE + 0xADC) +#define DVFSRC_DDR_ADD_REQUEST (DVFSRC_BASE + 0xAE0) +#define DVFSRC_LAST (DVFSRC_BASE + 0xAE4) +#define DVFSRC_LAST_L (DVFSRC_BASE + 0xAE8) +#define DVFSRC_MD_SCENARIO (DVFSRC_BASE + 0xAEC) +#define DVFSRC_RECORD_0_0 (DVFSRC_BASE + 0xAF0) +#define DVFSRC_RECORD_0_1 (DVFSRC_BASE + 0xAF4) +#define DVFSRC_RECORD_0_2 (DVFSRC_BASE + 0xAF8) +#define DVFSRC_RECORD_0_3 (DVFSRC_BASE + 0xAFC) +#define DVFSRC_RECORD_0_4 (DVFSRC_BASE + 0xB00) +#define DVFSRC_RECORD_0_5 (DVFSRC_BASE + 0xB04) +#define DVFSRC_RECORD_0_6 (DVFSRC_BASE + 0xB08) +#define DVFSRC_RECORD_0_7 (DVFSRC_BASE + 0xB0C) +#define DVFSRC_RECORD_0_L_0 (DVFSRC_BASE + 0xBF0) +#define DVFSRC_RECORD_0_L_1 (DVFSRC_BASE + 0xBF4) +#define DVFSRC_RECORD_0_L_2 (DVFSRC_BASE + 0xBF8) +#define DVFSRC_RECORD_0_L_3 (DVFSRC_BASE + 0xBFC) +#define DVFSRC_RECORD_0_L_4 (DVFSRC_BASE + 0xC00) +#define DVFSRC_RECORD_0_L_5 (DVFSRC_BASE + 0xC04) +#define DVFSRC_RECORD_0_L_6 (DVFSRC_BASE + 0xC08) +#define DVFSRC_RECORD_0_L_7 (DVFSRC_BASE + 0xC0C) +#define DVFSRC_EMI_REQUEST8 (DVFSRC_BASE + 0xCF0) +#define DVFSRC_DDR_REQUEST8 (DVFSRC_BASE + 0xCF4) +#define DVFSRC_EMI_HRT_2 (DVFSRC_BASE + 0xCF8) +#define DVFSRC_EMI_HRT2_2 (DVFSRC_BASE + 0xCFC) +#define DVFSRC_EMI_HRT3_2 (DVFSRC_BASE + 0xD00) +#define DVFSRC_EMI_QOS5 (DVFSRC_BASE + 0xD04) +#define DVFSRC_EMI_QOS6 (DVFSRC_BASE + 0xD08) +#define DVFSRC_DDR_HRT_2 (DVFSRC_BASE + 0xD0C) +#define DVFSRC_DDR_HRT2_2 (DVFSRC_BASE + 0xD10) +#define DVFSRC_DDR_HRT3_2 (DVFSRC_BASE + 0xD14) +#define DVFSRC_DDR_QOS5 (DVFSRC_BASE + 0xD18) +#define DVFSRC_DDR_QOS6 (DVFSRC_BASE + 0xD1C) +#define DVFSRC_VCORE_REQUEST5 (DVFSRC_BASE + 0xD20) +#define DVFSRC_VCORE_HRT_1 (DVFSRC_BASE + 0xD24) +#define DVFSRC_VCORE_HRT2_1 (DVFSRC_BASE + 0xD28) +#define DVFSRC_VCORE_HRT3_1 (DVFSRC_BASE + 0xD2C) +#define DVFSRC_VCORE_QOS3 (DVFSRC_BASE + 0xD30) +#define DVFSRC_VCORE_QOS4 (DVFSRC_BASE + 0xD34) +#define DVFSRC_HRT_HIGH_3 (DVFSRC_BASE + 0xD38) +#define DVFSRC_HRT_LOW_3 (DVFSRC_BASE + 0xD3C) +#define DVFSRC_BASIC_CONTROL_2 (DVFSRC_BASE + 0xD40) +#define DVFSRC_CURRENT_LEVEL (DVFSRC_BASE + 0xD44) +#define DVFSRC_TARGET_LEVEL (DVFSRC_BASE + 0xD48) +#define DVFSRC_LEVEL_LABEL_16_17 (DVFSRC_BASE + 0xD4C) +#define DVFSRC_LEVEL_LABEL_18_19 (DVFSRC_BASE + 0xD50) +#define DVFSRC_LEVEL_LABEL_20_21 (DVFSRC_BASE + 0xD54) +#define DVFSRC_LEVEL_LABEL_22_23 (DVFSRC_BASE + 0xD58) +#define DVFSRC_LEVEL_LABEL_24_25 (DVFSRC_BASE + 0xD5C) +#define DVFSRC_LEVEL_LABEL_26_27 (DVFSRC_BASE + 0xD60) +#define DVFSRC_LEVEL_LABEL_28_29 (DVFSRC_BASE + 0xD64) +#define DVFSRC_LEVEL_LABEL_30_31 (DVFSRC_BASE + 0xD68) +#define DVFSRC_CURRENT_FORCE (DVFSRC_BASE + 0xD6C) +#define DVFSRC_TARGET_FORCE (DVFSRC_BASE + 0xD70) +#define DVFSRC_EMI_ADD_REQUEST (DVFSRC_BASE + 0xD74) + +#define VCORE_VB_EFUSE (0x11C105E8) + +#endif /* MT_SPM_VCOREFS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h new file mode 100644 index 0000000..89aa163 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SSPM_NOTIFIER_H +#define MT_SPM_SSPM_NOTIFIER_H + +enum MT_SPM_SSPM_NOTIFY_ID { + MT_SPM_NOTIFY_LP_ENTER = 0U, + MT_SPM_NOTIFY_LP_LEAVE = 1U, + MT_SPM_NOTIFY_SUSPEND_VCORE_VOLTAGE = 2U, +}; + +int mt_spm_sspm_notify(int type, unsigned int lp_mode); + +static inline int mt_spm_sspm_notify_u32(int type, unsigned int lp_mode) +{ + return mt_spm_sspm_notify(type, lp_mode); +} + +#endif /* MT_SPM_SSPM_NOTIFIER_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h new file mode 100644 index 0000000..0b85c60 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SSPM_INTC_H +#define MT_SPM_SSPM_INTC_H + +#include + +#define MT_SPM_SSPM_INTC_SEL_0 (0x10) +#define MT_SPM_SSPM_INTC_SEL_1 (0x20) +#define MT_SPM_SSPM_INTC_SEL_2 (0x40) +#define MT_SPM_SSPM_INTC_SEL_3 (0x80) + +#define MT_SPM_SSPM_INTC_TRIGGER(id, sg) \ + (((0x10 << id) | (sg << id)) & 0xff) + +#define MT_SPM_SSPM_INTC0_HIGH MT_SPM_SSPM_INTC_TRIGGER(0, 1) +#define MT_SPM_SSPM_INTC0_LOW MT_SPM_SSPM_INTC_TRIGGER(0, 0) +#define MT_SPM_SSPM_INTC1_HIGH MT_SPM_SSPM_INTC_TRIGGER(1, 1) +#define MT_SPM_SSPM_INTC1_LOW MT_SPM_SSPM_INTC_TRIGGER(1, 0) +#define MT_SPM_SSPM_INTC2_HIGH MT_SPM_SSPM_INTC_TRIGGER(2, 1) +#define MT_SPM_SSPM_INTC2_LOW MT_SPM_SSPM_INTC_TRIGGER(2, 0) +#define MT_SPM_SSPM_INTC3_HIGH MT_SPM_SSPM_INTC_TRIGGER(3, 1) +#define MT_SPM_SSPM_INTC3_LOW MT_SPM_SSPM_INTC_TRIGGER(3, 0) + +/* + * mt8186 use cpc pbi as notify. + * Therefore, it won't need be notified by spm driver. + */ +#define DO_SPM_SSPM_LP_SUSPEND() +#define DO_SPM_SSPM_LP_RESUME() + +#endif /* MT_SPM_SSPM_INTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c new file mode 100644 index 0000000..198bac5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#define MT_SPM_SSPM_MBOX_OFF(x) (SSPM_MBOX_3_BASE + x) +#define MT_SPM_MBOX(slot) MT_SPM_SSPM_MBOX_OFF((slot << 2UL)) + +#define SSPM_MBOX_SPM_LP_LOOKUP1 MT_SPM_MBOX(0) +#define SSPM_MBOX_SPM_LP_LOOKUP2 MT_SPM_MBOX(1) +#define SSPM_MBOX_SPM_LP1 MT_SPM_MBOX(2) +#define SSPM_MBOX_SPM_LP2 MT_SPM_MBOX(3) + +int mt_spm_sspm_notify(int type, unsigned int lp_mode) +{ + switch (type) { + case MT_SPM_NOTIFY_LP_ENTER: + mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode); + DO_SPM_SSPM_LP_SUSPEND(); + break; + case MT_SPM_NOTIFY_LP_LEAVE: + mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode); + DO_SPM_SSPM_LP_RESUME(); + break; + case MT_SPM_NOTIFY_SUSPEND_VCORE_VOLTAGE: + mmio_write_32(SSPM_MBOX_SPM_LP2, lp_mode); + break; + default: + break; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h new file mode 100644 index 0000000..eb2db33 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PCM_DEF_H +#define PCM_DEF_H + +/* + * Auto generated by DE, please DO NOT modify this file directly. + */ + +/* --- R0 Define --- */ +#define R0_SC_26M_CK_OFF (1U << 0) +#define R0_SC_TX_TRACK_RETRY_EN (1U << 1) +#define R0_SC_MEM_CK_OFF (1U << 2) +#define R0_SC_AXI_CK_OFF (1U << 3) +#define R0_SC_DR_SRAM_LOAD (1U << 4) +#define R0_SC_MD26M_CK_OFF (1U << 5) +#define R0_SC_DPY_MODE_SW (1U << 6) +#define R0_SC_DMSUS_OFF (1U << 7) +#define R0_SC_DPY_2ND_DLL_EN (1U << 8) +#define R0_SC_DR_SRAM_RESTORE (1U << 9) +#define R0_SC_MPLLOUT_OFF (1U << 10) +#define R0_SC_TX_TRACKING_DIS (1U << 11) +#define R0_SC_DPY_DLL_EN (1U << 12) +#define R0_SC_DPY_DLL_CK_EN (1U << 13) +#define R0_SC_DPY_VREF_EN (1U << 14) +#define R0_SC_PHYPLL_EN (1U << 15) +#define R0_SC_DDRPHY_FB_CK_EN (1U << 16) +#define R0_SC_DPY_BCLK_ENABLE (1U << 17) +#define R0_SC_MPLL_OFF (1U << 18) +#define R0_SC_SHU_RESTORE (1U << 19) +#define R0_SC_CKSQ0_OFF (1U << 20) +#define R0_SC_DR_SHU_LEVEL_SRAM_LATCH (1U << 21) +#define R0_SC_DR_SHU_EN (1U << 22) +#define R0_SC_DPHY_PRECAL_UP (1U << 23) +#define R0_SC_MPLL_S_OFF (1U << 24) +#define R0_SC_DPHY_RXDLY_TRACKING_EN (1U << 25) +#define R0_SC_PHYPLL_SHU_EN (1U << 26) +#define R0_SC_PHYPLL2_SHU_EN (1U << 27) +#define R0_SC_PHYPLL_MODE_SW (1U << 28) +#define R0_SC_PHYPLL2_MODE_SW (1U << 29) +#define R0_SC_DR0_SHU_LEVEL (1U << 30) +#define R0_SC_DR1_SHU_LEVEL (1U << 31) +/* --- R7 Define --- */ +#define R7_PWRAP_SLEEP_REQ (1U << 0) +#define R7_EMI_CLK_OFF_REQ_PCM (1U << 1) +#define R7_PCM_BUS_PROTECT_REQ (1U << 2) +#define R7_SPM_CK_UPDATE (1U << 3) +#define R7_SPM_CK_SEL0 (1U << 4) +#define R7_SPM_CK_SEL1 (1U << 5) +#define R7_SPM_LEAVE_DEEPIDLE_REQ (1U << 6) +#define R7_SC_FHC_PAUSE_MPLL (1U << 7) +#define R7_SC_26M_CK_SEL (1U << 8) +#define R7_PCM_TIMER_SET (1U << 9) +#define R7_PCM_TIMER_CLR (1U << 10) +#define R7_SPM_LEAVE_SUSPEND_REQ (1U << 11) +#define R7_CSYSPWRUPACK (1U << 12) +#define R7_PCM_IM_SLP_EN (1U << 13) +#define R7_SRCCLKENO0 (1U << 14) +#define R7_FORCE_DDR_EN_WAKE (1U << 15) +#define R7_SPM_APSRC_INTERNAL_ACK (1U << 16) +#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17) +#define R7_SC_AXI_DCM_DIS (1U << 18) +#define R7_SC_FHC_PAUSE_MEM (1U << 19) +#define R7_SC_FHC_PAUSE_MAIN (1U << 20) +#define R7_SRCCLKENO1 (1U << 21) +#define R7_PCM_WDT_KICK_P (1U << 22) +#define R7_SPM2EMI_S1_MODE_ASYNC (1U << 23) +#define R7_SC_DDR_PST_REQ_PCM (1U << 24) +#define R7_SC_DDR_PST_ABORT_REQ_PCM (1U << 25) +#define R7_PMIC_IRQ_REQ_EN (1U << 26) +#define R7_FORCE_F26M_WAKE (1U << 27) +#define R7_FORCE_APSRC_WAKE (1U << 28) +#define R7_FORCE_INFRA_WAKE (1U << 29) +#define R7_FORCE_VRF18_WAKE (1U << 30) +#define R7_SPM_DDR_EN_INTERNAL_ACK (1U << 31) +/* --- R12 Define --- */ +#define R12_PCM_TIMER (1U << 0) +#define R12_TWAM_IRQ_B (1U << 1) +#define R12_KP_IRQ_B (1U << 2) +#define R12_APWDT_EVENT_B (1U << 3) +#define R12_APXGPT1_EVENT_B (1U << 4) +#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5) +#define R12_EINT_EVENT_B (1U << 6) +#define R12_CONN_WDT_IRQ_B (1U << 7) +#define R12_CCIF0_EVENT_B (1U << 8) +#define R12_LOWBATTERY_IRQ_B (1U << 9) +#define R12_SSPM2SPM_WAKEUP_B (1U << 10) +#define R12_SCP2SPM_WAKEUP_B (1U << 11) +#define R12_ADSP2SPM_WAKEUP_B (1U << 12) +#define R12_PCM_WDT_WAKEUP_B (1U << 13) +#define R12_USBX_CDSC_B (1U << 14) +#define R12_USBX_POWERDWN_B (1U << 15) +#define R12_SYS_TIMER_EVENT_B (1U << 16) +#define R12_EINT_EVENT_SECURE_B (1U << 17) +#define R12_CCIF1_EVENT_B (1U << 18) +#define R12_UART0_IRQ_B (1U << 19) +#define R12_AFE_IRQ_MCU_B (1U << 20) +#define R12_THERM_CTRL_EVENT_B (1U << 21) +#define R12_SYS_CIRQ_IRQ_B (1U << 22) +#define R12_MD2AP_PEER_EVENT_B (1U << 23) +#define R12_CSYSPWREQ_B (1U << 24) +#define R12_NNA_WAKEUP (1U << 25) +#define R12_CLDMA_EVENT_B (1U << 26) +#define R12_SEJ_EVENT_B (1U << 27) +#define R12_REG_CPU_WAKEUP (1U << 28) +#define R12_CPU_IRQOUT (1U << 29) +#define R12_CPU_WFI (1U << 30) +#define R12_MCUSYS_IDLE (1U << 31) +/* --- R12ext Define --- */ +#define R12EXT_26M_WAKE (1U << 0) +#define R12EXT_26M_SLEEP (1U << 1) +#define R12EXT_INFRA_WAKE (1U << 2) +#define R12EXT_INFRA_SLEEP (1U << 3) +#define R12EXT_APSRC_WAKE (1U << 4) +#define R12EXT_APSRC_SLEEP (1U << 5) +#define R12EXT_VRF18_WAKE (1U << 6) +#define R12EXT_VRF18_SLEEP (1U << 7) +#define R12EXT_DVFS_WAKE (1U << 8) +#define R12EXT_DDREN_WAKE (1U << 9) +#define R12EXT_DDREN_SLEEP (1U << 10) +#define R12EXT_MCU_PM_WFI (1U << 11) +#define R12EXT_SSPM_IDLE (1U << 12) +#define R12EXT_CONN_SRCCLKENB (1U << 13) +#define R12EXT_DRAMC_MD32_WFI_MERGE (1U << 14) +#define R12EXT_SW_MAILBOX_WAKE (1U << 15) +#define R12EXT_SSPM_MAILBOX_WAKE (1U << 16) +#define R12EXT_ADSP_MAILBOX_WAKE (1U << 17) +#define R12EXT_SCP_MAILBOX_WAKE (1U << 18) +#define R12EXT_SPM_LEAVE_SUSPEND_ACK (1U << 19) +#define R12EXT_SPM_LEAVE_DEEPIDLE_ACK (1U << 20) +#define R12EXT_BIT21 (1U << 21) +#define R12EXT_BIT22 (1U << 22) +#define R12EXT_BIT23 (1U << 23) +#define R12EXT_BIT24 (1U << 24) +#define R12EXT_BIT25 (1U << 25) +#define R12EXT_BIT26 (1U << 26) +#define R12EXT_BIT27 (1U << 27) +#define R12EXT_BIT28 (1U << 28) +#define R12EXT_BIT29 (1U << 29) +#define R12EXT_BIT30 (1U << 30) +#define R12EXT_BIT31 (1U << 31) +/* --- R13 Define --- */ +#define R13_SRCCLKENI0 (1U << 0) +#define R13_SRCCLKENI1 (1U << 1) +#define R13_MD_0_SRCCLKENA (1U << 2) +#define R13_MD_0_APSRC_REQ (1U << 3) +#define R13_CONN_DDREN (1U << 4) +#define R13_MD_1_SRCCLKENA (1U << 5) +#define R13_SSPM_SRCCLKENA (1U << 6) +#define R13_SSPM_APSRC_REQ (1U << 7) +#define R13_MD_1_STATE (1U << 8) +#define R13_RC_SRCCLKENO_ACK (1U << 9) +#define R13_MM_STATE (1U << 10) +#define R13_SSPM_STATE (1U << 11) +#define R13_MD_0_DDREN (1U << 12) +#define R13_CONN_STATE (1U << 13) +#define R13_CONN_SRCCLKENA (1U << 14) +#define R13_CONN_APSRC_REQ (1U << 15) +#define R13_SC_DDR_PST_ACK_ALL (1U << 16) +#define R13_SC_DDR_PST_ABORT_ACK_ALL (1U << 17) +#define R13_SCP_STATE (1U << 18) +#define R13_CSYSPWRUPREQ (1U << 19) +#define R13_PWRAP_SLEEP_ACK (1U << 20) +#define R13_SC_EMI_CLK_OFF_ACK_ALL (1U << 21) +#define R13_AUDIO_DSP_STATE (1U << 22) +#define R13_SC_DMDRAMCSHU_ACK_ALL (1U << 23) +#define R13_CONN_SRCCLKENB (1U << 24) +#define R13_SC_DR_SRAM_LOAD_ACK_ALL (1U << 25) +#define R13_SUBSYS_IDLE_SIGNALS0 (1U << 26) +#define R13_DVFS_STATE (1U << 27) +#define R13_SC_DR_SRAM_PLL_LOAD_ACK_ALL (1U << 28) +#define R13_SC_DR_SRAM_RESTORE_ACK_ALL (1U << 29) +#define R13_MD_0_VRF18_REQ (1U << 30) +#define R13_DDR_EN_STATE (1U << 31) + +#endif /* PCM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h new file mode 100644 index 0000000..d007939 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SLEEP_DEF_H +#define SLEEP_DEF_H + +/* + * Auto generated by DE, please DO NOT modify this file directly. + */ + +/* --- SPM Flag Define --- */ +#define SPM_FLAG_DISABLE_CPU_PDN (1U << 0) +#define SPM_FLAG_DISABLE_INFRA_PDN (1U << 1) +#define SPM_FLAG_DISABLE_DDRPHY_PDN (1U << 2) +#define SPM_FLAG_DISABLE_VCORE_DVS (1U << 3) +#define SPM_FLAG_DISABLE_VCORE_DFS (1U << 4) +#define SPM_FLAG_DISABLE_COMMON_SCENARIO (1U << 5) +#define SPM_FLAG_DISABLE_BUS_CLK_OFF (1U << 6) +#define SPM_FLAG_DISABLE_ARMPLL_OFF (1U << 7) +#define SPM_FLAG_KEEP_CSYSPWRACK_HIGH (1U << 8) +#define SPM_FLAG_ENABLE_LVTS_WORKAROUND (1U << 9) +#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10) +#define SPM_FLAG_SSPM_INFRA_SLEEP_MODE (1U << 11) +#define SPM_FLAG_ENABLE_SPM_DBG_WDT_DUMP (1U << 12) +#define SPM_FLAG_USE_SRCCLKENO2 (1U << 13) +#define SPM_FLAG_RESERVED_BIT14 (1U << 14) +#define SPM_FLAG_ENABLE_TIA_WORKAROUND (1U << 15) +#define SPM_FLAG_DISABLE_SYSRAM_SLEEP (1U << 16) +#define SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP (1U << 17) +#define SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP (1U << 18) +#define SPM_FLAG_RESERVED_BIT19 (1U << 19) +#define SPM_FLAG_ENABLE_VOLTAGE_BIN (1U << 20) +#define SPM_FLAG_RESERVED_BIT21 (1U << 21) +#define SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP (1U << 22) +#define SPM_FLAG_DISABLE_SRAM_EVENT (1U << 23) +#define SPM_FLAG_RESERVED_BIT24 (1U << 24) +#define SPM_FLAG_RESERVED_BIT25 (1U << 25) +#define SPM_FLAG_RESERVED_BIT26 (1U << 26) +#define SPM_FLAG_DDREN_STATE (1U << 27) +#define SPM_FLAG_VTCXO_STATE (1U << 28) +#define SPM_FLAG_INFRA_STATE (1U << 29) +#define SPM_FLAG_VRF18_STATE (1U << 30) +#define SPM_FLAG_APSRC_STATE (1U << 31) +#define SPM_FLAG_SYSTEM_POWER_STATE (1U << 28) +/* --- SPM Flag1 Define --- */ +#define SPM_FLAG1_DISABLE_AXI_BUS_TO_26M (1U << 0) +#define SPM_FLAG1_DISABLE_SYSPLL_OFF (1U << 1) +#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH (1U << 2) +#define SPM_FLAG1_DISABLE_ULPOSC_OFF (1U << 3) +#define SPM_FLAG1_FW_SET_ULPOSC_ON (1U << 4) +#define SPM_FLAG1_RESERVED_BIT5 (1U << 5) +#define SPM_FLAG1_ENABLE_REKICK (1U << 6) +#define SPM_FLAG1_RESERVED_BIT7 (1U << 7) +#define SPM_FLAG1_RESERVED_BIT8 (1U << 8) +#define SPM_FLAG1_RESERVED_BIT9 (1U << 9) +#define SPM_FLAG1_DISABLE_SRCLKEN_LOW (1U << 10) +#define SPM_FLAG1_DISABLE_SCP_CLK_SWITCH (1U << 11) +#define SPM_FLAG1_RESERVED_BIT12 (1U << 12) +#define SPM_FLAG1_RESERVED_BIT13 (1U << 13) +#define SPM_FLAG1_RESERVED_BIT14 (1U << 14) +#define SPM_FLAG1_RESERVED_BIT15 (1U << 15) +#define SPM_FLAG1_RESERVED_BIT16 (1U << 16) +#define SPM_FLAG1_RESERVED_BIT17 (1U << 17) +#define SPM_FLAG1_RESERVED_BIT18 (1U << 18) +#define SPM_FLAG1_RESERVED_BIT19 (1U << 19) +#define SPM_FLAG1_DISABLE_DEVAPC_SRAM_SLEEP (1U << 20) +#define SPM_FLAG1_RESERVED_BIT21 (1U << 21) +#define SPM_FLAG1_RESERVED_BIT22 (1U << 22) +#define SPM_FLAG1_RESERVED_BIT23 (1U << 23) +#define SPM_FLAG1_DISABLE_SCP_VREQ_MASK_CONTROL (1U << 24) +#define SPM_FLAG1_RESERVED_BIT25 (1U << 25) +#define SPM_FLAG1_RESERVED_BIT26 (1U << 26) +#define SPM_FLAG1_RESERVED_BIT27 (1U << 27) +#define SPM_FLAG1_RESERVED_BIT28 (1U << 28) +#define SPM_FLAG1_RESERVED_BIT29 (1U << 29) +#define SPM_FLAG1_RESERVED_BIT30 (1U << 30) +#define SPM_FLAG1_ENABLE_MCUPM_OFF (1U << 31) +/* --- SPM DEBUG Define --- */ +#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0) +#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1) +#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2) +#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3) +#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4) +#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5) +#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6) +#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7) +#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8) +#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9) +#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC (1U << 10) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_STATE (1U << 11) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_STATE (1U << 12) +#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN (1U << 13) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_STATE (1U << 14) +#define SPM_DBG_DEBUG_IDX_SYSRAM_SLP (1U << 15) +#define SPM_DBG_DEBUG_IDX_SYSRAM_ON (1U << 16) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_SLP (1U << 17) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_ON (1U << 18) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP (1U << 19) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_ON (1U << 20) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_SLP (1U << 21) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_ON (1U << 22) +#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP_ABORT (1U << 23) +#define SPM_DBG_DEBUG_IDX_SPM_GO_WAKEUP_NOW (1U << 27) +#define SPM_DBG_DEBUG_IDX_VTCXO_STATE (1U << 28) +#define SPM_DBG_DEBUG_IDX_INFRA_STATE (1U << 29) +#define SPM_DBG_DEBUG_IDX_VRR18_STATE (1U << 30) +#define SPM_DBG_DEBUG_IDX_APSRC_STATE (1U << 31) +/* --- SPM DEBUG1 Define --- */ +#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_LP (1U << 0) +#define SPM_DBG1_DEBUG_IDX_VCORE_DVFS_START (1U << 1) +#define SPM_DBG1_DEBUG_IDX_SYSPLL_OFF (1U << 2) +#define SPM_DBG1_DEBUG_IDX_SYSPLL_ON (1U << 3) +#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_VCORE_DVFS (1U << 4) +#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_OFF (1U << 5) +#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_ON (1U << 6) +#define SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT (1U << 7) +#define SPM_DBG1_RESERVED_BIT8 (1U << 8) +#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_ULPOSC (1U << 11) +#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_26M (1U << 12) +#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_32K (1U << 13) +#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_26M (1U << 14) +#define SPM_DBG1_DEBUG_IDX_BUS_CLK_OFF (1U << 15) +#define SPM_DBG1_DEBUG_IDX_BUS_CLK_ON (1U << 16) +#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_LOW (1U << 17) +#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_HIGH (1U << 18) +#define SPM_DBG1_DEBUG_IDX_MCUPM_WAKE_IRQ (1U << 19) +#define SPM_DBG1_DEBUG_IDX_ULPOSC_IS_OFF_BUT_SHOULD_ON (1U << 20) +#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT (1U << 23) +#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT (1U << 24) +#define SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT (1U << 25) +#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT (1U << 26) +#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT (1U << 27) +#define SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT (1U << 28) +#define SPM_DBG1_DEBUG_IDX_SPM_TIMER_RST_DVFS (1U << 29) +#define SPM_DBG1_DEBUG_IDX_SPM_DISABLE_DDREN_EVENT (1U << 30) +#define MCUPM_RESTORE (1U << 31) + +/* Macro and Inline */ +#define is_cpu_pdn(flags) (((flags) & SPM_FLAG_DISABLE_CPU_PDN) == 0U) +#define is_infra_pdn(flags) (((flags) & SPM_FLAG_DISABLE_INFRA_PDN) == 0U) +#define is_ddrphy_pdn(flags) (((flags) & SPM_FLAG_DISABLE_DDRPHY_PDN) == 0U) + +#endif /* SLEEP_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c new file mode 100644 index 0000000..91ef096 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu) +{ + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); +} + +void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu) +{ + mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); + /* Clear cpu's cpc sw hint */ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); +} + +void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr) +{ + assert(cluster == 0U); + + mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr); +} + +uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu) +{ + assert(cluster == 0U); + + return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR)); +} + +void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64) +{ + uint32_t reg; + + assert(cluster == 0U); + + reg = per_cluster(cluster, MCUCFG_INITARCH); + + if (arm64) { + mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); + } else { + mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); + } +} + +/* + * Return subsystem's power state. + * + * @mask: mask to SPM_CPU_PWR_STATUS to query the power state + * of one subsystem. + * RETURNS: + * 0 (the subsys was powered off) + * 1 (the subsys was powered on) + */ +bool spm_get_powerstate(uint32_t mask) +{ + return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask); +} + +bool spm_get_cluster_powerstate(unsigned int cluster) +{ + assert(cluster == 0U); + + return spm_get_powerstate(MP0_CPUTOP); +} + +bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu) +{ + uint32_t mask = BIT(cpu); + + assert(cluster == 0U); + + return spm_get_powerstate(mask); +} + +int spmc_init(void) +{ + unsigned int cpu = plat_my_core_pos(); + + + INFO("SPM: enable CPC mode\n"); + + mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN); + + mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B); + + mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); + mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); + mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); + + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); + + /* Clear bootup cpu's cpc sw hint */ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); + + return 0; +} + +/* + * Power on a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered on + * @cpu: the CPU ID of the CPU which to be powered on + */ +void spm_poweron_cpu(unsigned int cluster, unsigned int cpu) +{ + /* info CPC that CPU hotplug on */ + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); + + /* Set mp0_spmc_pwr_on_cpuX = 1 */ + mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); + + /* wait for power on ack */ + while (!spm_get_cpu_powerstate(cluster, cpu)) + ; + + /* info CPC that CPU hotplug off */ + mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); +} + +/* + * Power off a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered off + * @cpu: the CPU ID of the CPU which to be powered off + */ +void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu) +{ + /* Set mp0_spmc_pwr_on_cpuX = 0 */ + mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); +} + +/* + * Power off a cluster with specified index + * + * @cluster: the cluster index which to be powered off + */ +void spm_poweroff_cluster(unsigned int cluster) +{ + /* No need to power on/off cluster on single cluster platform */ + assert(false); +} + +/* + * Power on a cluster with specified index + * + * @cluster: the cluster index which to be powered on + */ +void spm_poweron_cluster(unsigned int cluster) +{ + /* No need to power on/off cluster on single cluster platform */ + assert(false); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h new file mode 100644 index 0000000..768599b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_H +#define MTSPMC_H + +#include + +int spmc_init(void); + +void spm_poweron_cpu(unsigned int cluster, unsigned int cpu); +void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu); + +void spm_poweroff_cluster(unsigned int cluster); +void spm_poweron_cluster(unsigned int cluster); + +bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu); +bool spm_get_cluster_powerstate(unsigned int cluster); +bool spm_get_powerstate(uint32_t mask); + +void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64); +void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr); +uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu); + +void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu); +void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu); + +#endif /* MTSPMC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000..472b54c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_PRIVATE_H +#define MTSPMC_PRIVATE_H + +#include +#include + +unsigned long read_cpuectlr(void); +void write_cpuectlr(unsigned long cpuectlr); + +unsigned long read_cpupwrctlr_el1(void); +void write_cpupwrctlr_el1(unsigned long cpuectlr); + +/* per_cpu/cluster helper */ +struct per_cpu_reg { + unsigned int cluster_addr; + unsigned int cpu_stride; +}; + +#define per_cpu(cluster, cpu, reg) \ + (reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride)) + +#define per_cluster(cluster, reg) (reg[cluster].cluster_addr) + +#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs)) +#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs)) +#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs)) + +/* SPMC related registers */ +#define SPM_POWERON_CONFIG_EN SPM_REG(0x000) +/* bit-fields of SPM_POWERON_CONFIG_EN */ +#define PROJECT_CODE (U(0xb16) << 16) +#define BCLK_CG_EN BIT(0) + +#define SPM_PWR_STATUS SPM_REG(0x16c) +#define SPM_PWR_STATUS_2ND SPM_REG(0x170) +#define SPM_CPU_PWR_STATUS SPM_REG(0x174) + +/* bit-fields of SPM_PWR_STATUS */ +#define MD BIT(0) +#define CONN BIT(1) +#define DDRPHY BIT(2) +#define DISP BIT(3) +#define MFG BIT(4) +#define ISP BIT(5) +#define INFRA BIT(6) +#define VDEC BIT(7) +#define MP0_CPUTOP BIT(8) +#define MP0_CPU0 BIT(9) +#define MP0_CPU1 BIT(10) +#define MP0_CPU2 BIT(11) +#define MP0_CPU3 BIT(12) +#define MCUSYS BIT(14) +#define MP0_CPU4 BIT(15) +#define MP0_CPU5 BIT(16) +#define MP0_CPU6 BIT(17) +#define MP0_CPU7 BIT(18) +#define VEN BIT(21) + +/* SPMC related registers */ +#define SPM_MCUSYS_PWR_CON SPM_REG(0x200) +#define SPM_MP0_CPUTOP_PWR_CON SPM_REG(0x204) +#define SPM_MP0_CPU0_PWR_CON SPM_REG(0x208) +#define SPM_MP0_CPU1_PWR_CON SPM_REG(0x20c) +#define SPM_MP0_CPU2_PWR_CON SPM_REG(0x210) +#define SPM_MP0_CPU3_PWR_CON SPM_REG(0x214) +#define SPM_MP0_CPU4_PWR_CON SPM_REG(0x218) +#define SPM_MP0_CPU5_PWR_CON SPM_REG(0x21c) +#define SPM_MP0_CPU6_PWR_CON SPM_REG(0x220) +#define SPM_MP0_CPU7_PWR_CON SPM_REG(0x224) + +/* bit-fields of SPM_*_PWR_CON */ +#define PWR_ON_ACK BIT(31) +#define VPROC_EXT_OFF BIT(7) +#define DORMANT_EN BIT(6) +#define RESETPWRON_CONFIG BIT(5) +#define PWR_CLK_DIS BIT(4) +#define PWR_ON BIT(2) +#define PWR_RST_B BIT(0) + +/* per_cpu registers for SPM_MP0_CPU_PWR_CON */ +static const struct per_cpu_reg SPM_CPU_PWR[] = { + { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U } +}; + +/* per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */ +static const struct per_cpu_reg SPM_CLUSTER_PWR[] = { + { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U } +}; + +/* MCUCFG related registers */ +#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4) +/* reset vectors */ +#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900) +#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908) +#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910) +#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918) +#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920) +#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928) +#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930) +#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938) + +/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG */ +static const struct per_cpu_reg MCUCFG_BOOTADDR[] = { + { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U } +}; + +/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */ +static const struct per_cpu_reg MCUCFG_INITARCH[] = { + { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U } +}; + +#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu) +/* CPC control */ +#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) +#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840) + +/* bit-fields of CPC_FLOW_CTRL_CFG */ +#define CPC_CTRL_ENABLE BIT(16) +#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */ +#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu) + +/* bit-fields of CPC_SPMC_PWR_STATUS */ +#define CORE_SPMC_PWR_ON_ACK GENMASK(11, 0) + +/* APB module infracfg_ao */ +#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220) +#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224) +#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228) +#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0) +#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4) +#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250) +#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254) +#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258) +#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8) +#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac) + +/* bit-fields of INFRA_TOPAXI_PROTECTEN */ +#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12) +#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12)) + +/* SPARK */ +#define VOLTAGE_04 U(0x40) +#define VOLTAGE_05 U(0x60) + +#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200) +#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334) +#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340) + +/* bit-fields of CPU0_ILDO_CONTROL5 */ +#define ILDO_RET_VOSEL GENMASK(7, 0) + +/* bit-fields of PTP3_CPU_SPMC_SW_CFG */ +#define SW_SPARK_EN BIT(0) + +/* bit-fields of CPU0_ILDO_CONTROL8 */ +#define ILDO_BYPASS_B BIT(0) + +static const struct per_cpu_reg MCUCFG_SPARK[] = { + { .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U } +}; + +static const struct per_cpu_reg ILDO_CONTROL5[] = { + { .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U } +}; + +static const struct per_cpu_reg ILDO_CONTROL8[] = { + { .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U } +}; + +#endif /* MTSPMC_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h new file mode 100644 index 0000000..78a01a8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCUCFG_H +#define MCUCFG_H + +#ifndef __ASSEMBLER__ +#include +#endif /* __ASSEMBLER__ */ + +#include + +#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs)) + +#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8)) +#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8)) + +#define MP2_CPUCFG MCUCFG_REG(0x2208) + +#define MP2_CPU0_STANDBYWFE BIT(4) +#define MP2_CPU1_STANDBYWFE BIT(5) + +#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788) +#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C) +#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790) + +#define sw_spark_en BIT(0) +#define sw_no_wait_for_q_channel BIT(1) +#define sw_fsm_override BIT(2) +#define sw_logic_pre1_pdb BIT(3) +#define sw_logic_pre2_pdb BIT(4) +#define sw_logic_pdb BIT(5) +#define sw_iso BIT(6) +#define sw_sram_sleepb (U(0x3F) << 7) +#define sw_sram_isointb BIT(13) +#define sw_clk_dis BIT(14) +#define sw_ckiso BIT(15) +#define sw_pd (U(0x3F) << 16) +#define sw_hot_plug_reset BIT(22) +#define sw_pwr_on_override_en BIT(23) +#define sw_pwr_on BIT(24) +#define sw_coq_dis BIT(25) +#define logic_pdbo_all_off_ack BIT(26) +#define logic_pdbo_all_on_ack BIT(27) +#define logic_pre2_pdbo_all_on_ack BIT(28) +#define logic_pre1_pdbo_all_on_ack BIT(29) + + +#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \ + (MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4) + +#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30) +#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34) +#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38) +#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C) + +#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30) +#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34) +#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38) +#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C) + +#define cpu_sw_spark_en BIT(0) +#define cpu_sw_no_wait_for_q_channel BIT(1) +#define cpu_sw_fsm_override BIT(2) +#define cpu_sw_logic_pre1_pdb BIT(3) +#define cpu_sw_logic_pre2_pdb BIT(4) +#define cpu_sw_logic_pdb BIT(5) +#define cpu_sw_iso BIT(6) +#define cpu_sw_sram_sleepb BIT(7) +#define cpu_sw_sram_isointb BIT(8) +#define cpu_sw_clk_dis BIT(9) +#define cpu_sw_ckiso BIT(10) +#define cpu_sw_pd (U(0x1F) << 11) +#define cpu_sw_hot_plug_reset BIT(16) +#define cpu_sw_powr_on_override_en BIT(17) +#define cpu_sw_pwr_on BIT(18) +#define cpu_spark2ldo_allswoff BIT(19) +#define cpu_pdbo_all_on_ack BIT(20) +#define cpu_pre2_pdbo_allon_ack BIT(21) +#define cpu_pre1_pdbo_allon_ack BIT(22) + +/* CPC related registers */ +#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714) +#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804) +#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) +#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818) +#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c) +#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824) +#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828) +#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8) +#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac) +#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00) +#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04) +#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08) +#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c) +#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10) +#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14) +#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20) +#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70) +#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74) +#define SPARK2LDO MCUCFG_REG(0x2700) +/* APB module mcucfg */ +#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000) +#define MP0_AXI_CONFIG MCUCFG_REG(0x02C) +#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030) +#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034) +#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038) +#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8)) +#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C) +#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054) +#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064) + +#define MP0_RW_RSVD0 MCUCFG_REG(0x06C) + + +#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200) +#define MP1_AXI_CONFIG MCUCFG_REG(0x22C) +#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230) +#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234) +#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238) +#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8)) +#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C) +#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254) +#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264) + +#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740) +#define SYNC_DCM_CONFIG MCUCFG_REG(0x744) + +#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0) + +#define MP0_SPMC MCUCFG_REG(0x788) +#define MP1_SPMC MCUCFG_REG(0x78C) +#define MP2_AXI_CONFIG MCUCFG_REG(0x220C) +#define MP2_AXI_CONFIG_ACINACTM BIT(0) +#define MP2_AXI_CONFIG_AINACTS BIT(4) + +#define MPx_AXI_CONFIG_ACINACTM BIT(4) +#define MPx_AXI_CONFIG_AINACTS BIT(5) +#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28) + +#define MP0_CPU0_STANDBYWFE BIT(20) +#define MP0_CPU1_STANDBYWFE BIT(21) +#define MP0_CPU2_STANDBYWFE BIT(22) +#define MP0_CPU3_STANDBYWFE BIT(23) + +#define MP1_CPU0_STANDBYWFE BIT(20) +#define MP1_CPU1_STANDBYWFE BIT(21) +#define MP1_CPU2_STANDBYWFE BIT(22) +#define MP1_CPU3_STANDBYWFE BIT(23) + +#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00) +#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04) +#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08) +#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00) +#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04) +#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08) + +#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008) +#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0) +#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4) + +#define MP2_COQ MCUCFG_REG(0x22BC) +#define MP2_COQ_SW_DIS BIT(0) + +#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400) +#define MP2_CA15M_MON_L MCUCFG_REG(0x2404) + +#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430) +#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438) +#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434) +#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C) + +#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068) +#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268) +#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C) + +#define MP2_SW_RST_B BIT(0) +#define MP2_TOPAON_APB_MASK BIT(1) + +#define B_SW_HOT_PLUG_RESET BIT(30) + +#define B_SW_PD_OFFSET (18U) +#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET) + +#define B_SW_SRAM_SLEEPB_OFFSET (12U) +#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET) + +#define B_SW_SRAM_ISOINTB BIT(9) +#define B_SW_ISO BIT(8) +#define B_SW_LOGIC_PDB BIT(7) +#define B_SW_LOGIC_PRE2_PDB BIT(6) +#define B_SW_LOGIC_PRE1_PDB BIT(5) +#define B_SW_FSM_OVERRIDE BIT(4) +#define B_SW_PWR_ON BIT(3) +#define B_SW_PWR_ON_OVERRIDE_EN BIT(2) + +#define B_FSM_STATE_OUT_OFFSET (6U) +#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET) +#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5) +#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4) +#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3) +#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2) + +#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET) +#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET) +#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET) + +#ifndef __ASSEMBLER__ +/* cpu boot mode */ +enum { + MP0_CPUCFG_64BIT_SHIFT = 12U, + MP1_CPUCFG_64BIT_SHIFT = 28U, + MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT, + MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT +}; + +enum { + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U, + + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT +}; + +enum { + MP1_AINACTS_SHIFT = 4U, + MP1_AINACTS = 1U << MP1_AINACTS_SHIFT +}; + +enum { + MP1_SW_CG_GEN_SHIFT = 12U, + MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT +}; + +enum { + MP1_L2RSTDISABLE_SHIFT = 14U, + MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT +}; +#endif /* __ASSEMBLER__ */ + +#endif /* MCUCFG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h new file mode 100644 index 0000000..9761e79 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_RESOURCE_REQ_H +#define MT_SPM_RESOURCE_REQ_H + +/* SPM resource request internal bit */ +#define MT_SPM_BIT_XO_FPM (0U) +#define MT_SPM_BIT_26M (1U) +#define MT_SPM_BIT_INFRA (2U) +#define MT_SPM_BIT_SYSPLL (3U) +#define MT_SPM_BIT_DRAM_S0 (4U) +#define MT_SPM_BIT_DRAM_S1 (5U) + +/* SPM resource request internal bit_mask */ +#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM) +#define MT_SPM_26M BIT(MT_SPM_BIT_26M) +#define MT_SPM_INFRA BIT(MT_SPM_BIT_INFRA) +#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL) +#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0) +#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1) + +char spm_resource_req(unsigned int user, unsigned int req_mask); + +#define IS_PLAT_SUSPEND_ID(stateid)\ + ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE)\ + || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND)) + +#endif /* MT_SPM_RESOURCE_REQ_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h new file mode 100644 index 0000000..ebc9fa0 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_HELPERS_H__ +#define __PLAT_HELPERS_H__ + +unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr); + +#endif /* __PLAT_HELPERS_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S new file mode 100644 index 0000000..39727ea --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception + * is taken in BL31. + * Clobbers: x0 - x10, x26, x27, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + /* TODO: leave implementation to GIC owner */ + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h new file mode 100644 index 0000000..12ea9d7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MTK_LPM_H +#define PLAT_MTK_LPM_H + +#include +#include + +#define MT_IRQ_REMAIN_MAX U(32) +#define MT_IRQ_REMAIN_CAT_LOG BIT(31) + +struct mt_irqremain { + unsigned int count; + unsigned int irqs[MT_IRQ_REMAIN_MAX]; + unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX]; + unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX]; +}; + +#define PLAT_RC_STATUS_READY BIT(0) +#define PLAT_RC_STATUS_FEATURE_EN BIT(1) +#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31) + +struct mt_lpm_tz { + int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state); + + int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state); + + int (*pwr_cluster_on)(unsigned int cpu, + const psci_power_state_t *state); + int (*pwr_cluster_dwn)(unsigned int cpu, + const psci_power_state_t *state); + + int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_mcusys_on_finished)(unsigned int cpu, + const psci_power_state_t *state); + int (*pwr_mcusys_dwn)(unsigned int cpu, + const psci_power_state_t *state); +}; + +const struct mt_lpm_tz *mt_plat_cpu_pm_init(void); +int plat_mt_pm_register(struct mt_lpm_tz *mt_pm); + +#endif /* PLAT_MTK_LPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h new file mode 100644 index 0000000..ec70e4b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PM_H +#define PLAT_PM_H + +#include + +#ifndef __ASSEMBLY__ +extern uintptr_t mtk_suspend_footprint_addr; +extern uintptr_t mtk_suspend_timestamp_addr; + +#define MT_PLAT_PWR_STATE_CPU U(1) +#define MT_PLAT_PWR_STATE_CLUSTER U(2) +#define MT_PLAT_PWR_STATE_MCUSYS U(3) +#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8) +#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9) + +#define MTK_LOCAL_STATE_RUN U(0) +#define MTK_LOCAL_STATE_RET U(1) +#define MTK_LOCAL_STATE_OFF U(2) + +#define MTK_AFFLVL_CPU U(0) +#define MTK_AFFLVL_CLUSTER U(1) +#define MTK_AFFLVL_MCUSYS U(2) +#define MTK_AFFLVL_SYSTEM U(3) + +void mtk_suspend_footprint_log(int idx); +void mtk_suspend_timestamp_log(int idx); + +int mt_cluster_ops(int cputop_mpx, int mode, int state); +int mt_core_ops(int cpux, int state); + +#define IS_CLUSTER_OFF_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER]) +#define IS_MCUSYS_OFF_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS]) +#define IS_SYSTEM_SUSPEND_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM]) + +/* SMC secure magic number */ +#define SPM_LP_SMC_MAGIC (0xDAF10000) + +#define IS_SPM_LP_SMC(_type, _id) (_id == (SPM_LP_SMC_MAGIC | _type)) + +enum mtk_suspend_mode { + MTK_MCDI_MODE = 1U, + MTK_IDLEDRAM_MODE = 2U, + MTK_IDLESYSPLL_MODE = 3U, + MTK_IDLEBUS26M_MODE = 4U, + MTK_SUSPEND_MODE = 5U, +}; +#endif + +enum mt8169_idle_model { + IDLE_MODEL_START = 0U, + IDLE_MODEL_RESOURCE_HEAD = IDLE_MODEL_START, + IDLE_MODEL_BUS26M = IDLE_MODEL_RESOURCE_HEAD, + IDLE_MODEL_SYSPLL = 1U, + IDLE_MODEL_DRAM = 2U, + IDLE_MODEL_NUM = 3U, +}; + +#define footprint_addr(cpu) (mtk_suspend_footprint_addr + (cpu << 2)) +#define timestamp_addr(cpu, idx) (mtk_suspend_timestamp_addr + \ + ((cpu * MTK_SUSPEND_TIMESTAMP_MAX + idx) << 3)) + +#define MTK_SUSPEND_FOOTPRINT_ENTER_CPUIDLE (0U) +#define MTK_SUSPEND_FOOTPRINT_BEFORE_ATF (1U) +#define MTK_SUSPEND_FOOTPRINT_ENTER_ATF (2U) +#define MTK_SUSPEND_FOOTPRINT_RESERVE_P1 (3U) +#define MTK_SUSPEND_FOOTPRINT_RESERVE_P2 (4U) +#define MTK_SUSPEND_FOOTPRINT_ENTER_SPM_SUSPEND (5U) +#define MTK_SUSPEND_FOOTPRINT_LEAVE_SPM_SUSPEND (6U) +#define MTK_SUSPEND_FOOTPRINT_BEFORE_WFI (7U) +#define MTK_SUSPEND_FOOTPRINT_AFTER_WFI (8U) +#define MTK_SUSPEND_FOOTPRINT_BEFORE_MMU (9U) +#define MTK_SUSPEND_FOOTPRINT_AFTER_MMU (10U) +#define MTK_SUSPEND_FOOTPRINT_ENTER_SPM_SUSPEND_FINISH (11U) +#define MTK_SUSPEND_FOOTPRINT_LEAVE_SPM_SUSPEND_FINISH (12U) +#define MTK_SUSPEND_FOOTPRINT_LEAVE_ATF (13U) +#define MTK_SUSPEND_FOOTPRINT_AFTER_ATF (14U) +#define MTK_SUSPEND_FOOTPRINT_LEAVE_CPUIDLE (15U) + +#define MTK_SUSPEND_TIMESTAMP_ENTER_CPUIDLE (0U) +#define MTK_SUSPEND_TIMESTAMP_BEFORE_ATF (1U) +#define MTK_SUSPEND_TIMESTAMP_ENTER_ATF (2U) +#define MTK_SUSPEND_TIMESTAMP_BEFORE_L2_FLUSH (3U) +#define MTK_SUSPEND_TIMESTAMP_AFTER_L2_FLUSH (4U) +#define MTK_SUSPEND_TIMESTAMP_ENTER_SPM_SUSPEND (5U) +#define MTK_SUSPEND_TIMESTAMP_LEAVE_SPM_SUSPEND (6U) +#define MTK_SUSPEND_TIMESTAMP_GIC_P1 (7U) +#define MTK_SUSPEND_TIMESTAMP_GIC_P2 (8U) +#define MTK_SUSPEND_TIMESTAMP_BEFORE_WFI (9U) +#define MTK_SUSPEND_TIMESTAMP_AFTER_WFI (10U) +#define MTK_SUSPEND_TIMESTAMP_RESERVE_P1 (11U) +#define MTK_SUSPEND_TIMESTAMP_RESERVE_P2 (12U) +#define MTK_SUSPEND_TIMESTAMP_GIC_P3 (13U) +#define MTK_SUSPEND_TIMESTAMP_GIC_P4 (14U) +#define MTK_SUSPEND_TIMESTAMP_ENTER_SPM_SUSPEND_FINISH (15U) +#define MTK_SUSPEND_TIMESTAMP_LEAVE_SPM_SUSPEND_FINISH (16U) +#define MTK_SUSPEND_TIMESTAMP_LEAVE_ATF (17U) +#define MTK_SUSPEND_TIMESTAMP_AFTER_ATF (18U) +#define MTK_SUSPEND_TIMESTAMP_LEAVE_CPUIDLE (19U) +#define MTK_SUSPEND_TIMESTAMP_MAX (20U) + +/* + * definition platform power state menas. + * PLAT_MT_SYSTEM_SUSPEND - system suspend pwr level + * PLAT_MT_CPU_SUSPEND_CLUSTER - cluster off pwr level + */ +#define PLAT_MT_SYSTEM_SUSPEND PLAT_MAX_OFF_STATE +#define PLAT_MT_CPU_SUSPEND_CLUSTER PLAT_MAX_RET_STATE + +#define IS_PLAT_SYSTEM_SUSPEND(aff) (aff == PLAT_MT_SYSTEM_SUSPEND) +#define IS_PLAT_SYSTEM_RETENTION(aff) (aff >= PLAT_MAX_RET_STATE) + +#define IS_PLAT_SUSPEND2IDLE_ID(stateid)\ + (stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) + +#define IS_PLAT_SUSPEND_ID(stateid) \ + ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \ + || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND)) + +#endif /* PLAT_PM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h new file mode 100644 index 0000000..7ef2b85 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h new file mode 100644 index 0000000..9e3726b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +/******************************************************************************* + * Plat SiP function constants + ******************************************************************************/ +#define MTK_PLAT_SIP_NUM_CALLS (2) + +/* DFD */ +#define MTK_SIP_KERNEL_DFD_AARCH32 (0x82000205) +#define MTK_SIP_KERNEL_DFD_AARCH64 (0xC2000205) + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h new file mode 100644 index 0000000..f0fb442 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_UART_H__ +#define __PLAT_UART_H__ + +/* UART error code */ +#define UART_DONE U(0) +#define UART_PM_ERROR U(1) + +/* UART HW information */ +#ifndef HW_SUPPORT_UART_PORTS +#define HW_SUPPORT_UART_PORTS (2U) /* the UART PORTs current HW have */ +#endif +#define MTK_UART_SEND_SLEEP_REQ (1U) /* Request uart to sleep */ +#define MTK_UART_SLEEP_ACK_IDLE (1U) /* uart in idle state */ +#define MTK_UART_WAIT_ACK_TIMES (50U) + +#define UART_BASE0 (0x11002000) +#define UART_BASE1 (0x11003000) + +#endif /* __PLAT_UART_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h new file mode 100644 index 0000000..b8b877a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#define PLAT_PRIMARY_CPU (0x0) + +#define MT_GIC_BASE (0x0C000000) +#define MCUCFG_BASE (0x0C530000) +#define IO_PHYS (0x10000000) + +/* Aggregate of all devices for MMU mapping */ +#define MTK_DEV_RNG0_BASE IO_PHYS +#define MTK_DEV_RNG0_SIZE (0x10000000) +#define MTK_DEV_RNG2_BASE MT_GIC_BASE +#define MTK_DEV_RNG2_SIZE (0x600000) +#define MTK_MCDI_SRAM_BASE (0x11B000) +#define MTK_MCDI_SRAM_MAP_SIZE (0x1000) + +#define TOPCKGEN_BASE (IO_PHYS + 0x00000000) +#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000) +#define SPM_BASE (IO_PHYS + 0x00006000) +#define APMIXEDSYS (IO_PHYS + 0x0000C000) +#define SSPM_MBOX_BASE (IO_PHYS + 0x00480000) +#define PERICFG_AO_BASE (IO_PHYS + 0x01003000) +#define VPPSYS0_BASE (IO_PHYS + 0x04000000) +#define VPPSYS1_BASE (IO_PHYS + 0x04f00000) +#define VDOSYS0_BASE (IO_PHYS + 0x0C01A000) +#define VDOSYS1_BASE (IO_PHYS + 0x0C100000) + +/******************************************************************************* + * GPIO related constants + ******************************************************************************/ +#define TOPCKGEN_BASE (IO_PHYS + 0x00000000) +#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000) +#define GPIO_BASE (IO_PHYS + 0x00005000) +#define SPM_BASE (IO_PHYS + 0x00006000) +#define IOCFG_LT_BASE (IO_PHYS + 0x00002000) +#define IOCFG_LM_BASE (IO_PHYS + 0x00002200) +#define IOCFG_LB_BASE (IO_PHYS + 0x00002400) +#define IOCFG_BL_BASE (IO_PHYS + 0x00002600) +#define IOCFG_RB_BASE (IO_PHYS + 0x00002A00) +#define IOCFG_RT_BASE (IO_PHYS + 0x00002C00) +#define APMIXEDSYS (IO_PHYS + 0x0000C000) +#define DVFSRC_BASE (IO_PHYS + 0x00012000) +#define MMSYS_BASE (IO_PHYS + 0x04000000) +#define MDPSYS_BASE (IO_PHYS + 0x0B000000) + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define UART0_BASE (IO_PHYS + 0x01002000) +#define UART1_BASE (IO_PHYS + 0x01003000) + +#define UART_BAUDRATE (115200) + +/******************************************************************************* + * PWRAP related constants + ******************************************************************************/ +#define PMIC_WRAP_BASE (IO_PHYS + 0x0000D000) + +/******************************************************************************* + * EMI MPU related constants + ******************************************************************************/ +#define EMI_MPU_BASE (IO_PHYS + 0x0021B000) + +/******************************************************************************* + * GIC-600 & interrupt handling related constants + ******************************************************************************/ +/* Base MTK_platform compatible GIC memory map */ +#define BASE_GICD_BASE MT_GIC_BASE +#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000) + +#define SYS_CIRQ_BASE (IO_PHYS + 0x204000) +#define CIRQ_REG_NUM (11) +#define CIRQ_IRQ_NUM (326) +#define CIRQ_SPI_START (64) +#define MD_WDT_IRQ_BIT_ID (107) +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS (13000000) +#define SYS_COUNTER_FREQ_IN_MHZ (13) + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ +#define PLATFORM_STACK_SIZE 0x800 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLAT_MAX_PWR_LVL U(3) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(9) + +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_MCUSYS_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(8) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) + +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8) + +#define SOC_CHIP_ID U(0x8186) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +#define TZRAM_BASE (0x54600000) +#define TZRAM_SIZE (0x00030000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL3-1 debug size plus a + * little space for growth. + */ +#define BL31_BASE (TZRAM_BASE + 0x1000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES (16) +#define MAX_MMAP_REGIONS (16) + +/******************************************************************************* + * 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 (6) +#define CACHE_WRITEBACK_GRANULE BIT(CACHE_WRITEBACK_SHIFT) +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h new file mode 100644 index 0000000..3e8c3e2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SSPM_REG_H__ +#define __SSPM_REG_H__ + +#include "platform_def.h" + +#define SSPM_CFGREG_BASE (IO_PHYS + 0x440000) /* SSPM view: 0x30040000 */ +#define SSPM_CFGREG_ADDR(ofs) (SSPM_CFGREG_BASE + (ofs)) + +#define SSPM_MCDI_SHARE_SRAM (IO_PHYS + 0x420000) +#define SSPM_MBOX_3_BASE (IO_PHYS + 0x480000) + +#define SSPM_HW_SEM SSPM_CFGREG_ADDR(0x0048) +#define SSPM_ACAO_INT_SET SSPM_CFGREG_ADDR(0x00D8) +#define SSPM_ACAO_INT_CLR SSPM_CFGREG_ADDR(0x00DC) + +#define STANDBYWFI_EN(n) (1 << (n + 8)) +#define GIC_IRQOUT_EN(n) (1 << (n + 0)) + +#endif /* __SSPM_REG_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c new file mode 100644 index 0000000..e125c99 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Cluster state request: + * [0] : The CPU requires cluster power down + * [1] : The CPU requires cluster power on + */ +#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff) +#define coordinate_cluster_pwron() coordinate_cluster(1) +#define coordinate_cluster_pwroff() coordinate_cluster(0) + +/* platform secure entry point */ +static uintptr_t secure_entrypoint; +/* per-CPU power state */ +static unsigned int plat_power_state[PLATFORM_CORE_COUNT]; + +/* platform CPU power domain - ops */ +static const struct mt_lpm_tz *plat_mt_pm; + +static inline int plat_mt_pm_invoke(int (*func)(unsigned int cpu, + const psci_power_state_t *state), + int cpu, const psci_power_state_t *state) +{ + int ret = -1; + + if (func != NULL) { + ret = func(cpu, state); + } + return ret; +} + +/* + * Common MTK_platform operations to power on/off a + * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ +static void plat_cpu_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + assert(plat_mt_pm != NULL); + + (void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_dwn, cpu, state); + + if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) || + (req_pstate == 0U)) { /* hotplug off */ + coordinate_cluster_pwroff(); + } + + /* Prevent interrupts from spuriously waking up this CPU */ + mt_gic_rdistif_save(); + gicv3_cpuif_disable(cpu); + gicv3_rdistif_off(cpu); +} + +static void plat_cpu_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + assert(plat_mt_pm != NULL); + + (void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_on, cpu, state); + + coordinate_cluster_pwron(); + + /* + * If mcusys does power down before then restore + * all CPUs' GIC Redistributors + */ + if (IS_MCUSYS_OFF_STATE(state)) { + mt_gic_rdistif_restore_all(); + } else { + gicv3_rdistif_on(cpu); + gicv3_cpuif_enable(cpu); + mt_gic_rdistif_init(); + mt_gic_rdistif_restore(); + } +} + +/* + * Common MTK_platform operations to power on/off a + * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ +static void plat_cluster_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + assert(plat_mt_pm != NULL); + + if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_dwn, cpu, state) != 0) { + coordinate_cluster_pwron(); + + /* + * TODO: + * Return on fail and add a 'return' here before + * adding any code following the if-block. + */ + } +} + +static void plat_cluster_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + assert(plat_mt_pm != NULL); + + if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_on, cpu, state) != 0) { + /* + * TODO: + * return on fail and add a 'return' here before + * adding any code following the if-block. + */ + } +} + +/* + * Common MTK_platform operations to power on/off a + * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ +static void plat_mcusys_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + assert(plat_mt_pm != NULL); + + if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_dwn, cpu, state) != 0) { + return; /* return on fail */ + } + + mt_gic_distif_save(); + gic_sgi_save_all(); +} + +static void plat_mcusys_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + assert(plat_mt_pm != NULL); + + if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on, cpu, state) != 0) { + /* return on fail */ + return; + } + + mt_gic_init(); + mt_gic_distif_restore(); + gic_sgi_restore_all(); + + dfd_resume(); + + (void)plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on_finished, cpu, state); +} + +/* plat_psci_ops implementation */ +static void plat_cpu_standby(plat_local_state_t cpu_state) +{ + uint64_t scr; + + scr = read_scr_el3(); + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + isb(); + dsb(); + wfi(); + + write_scr_el3(scr); +} + +static int plat_power_domain_on(u_register_t mpidr) +{ + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + unsigned int cluster = 0U; + + if (cpu >= PLATFORM_CORE_COUNT) { + return PSCI_E_INVALID_PARAMS; + } + + if (!spm_get_cluster_powerstate(cluster)) { + spm_poweron_cluster(cluster); + } + + /* init CPU reset arch as AARCH64 */ + mcucfg_init_archstate(cluster, cpu, true); + mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint); + spm_poweron_cpu(cluster, cpu); + + return PSCI_E_SUCCESS; +} + +static void plat_power_domain_on_finish(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + + assert(cpu < PLATFORM_CORE_COUNT); + + /* Allow IRQs to wakeup this core in IDLE flow */ + mcucfg_enable_gic_wakeup(0U, cpu); + + if (IS_CLUSTER_OFF_STATE(state)) { + plat_cluster_pwron_common(cpu, state, 0U); + } + + plat_cpu_pwron_common(cpu, state, 0U); +} + +static void plat_power_domain_off(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + + assert(cpu < PLATFORM_CORE_COUNT); + + plat_cpu_pwrdwn_common(cpu, state, 0U); + spm_poweroff_cpu(0U, cpu); + + /* prevent unintended IRQs from waking up the hot-unplugged core */ + mcucfg_disable_gic_wakeup(0U, cpu); + + if (IS_CLUSTER_OFF_STATE(state)) { + plat_cluster_pwrdwn_common(cpu, state, 0U); + } +} + +static void plat_power_domain_suspend(const psci_power_state_t *state) +{ + unsigned int cpu = plat_my_core_pos(); + + assert(cpu < PLATFORM_CORE_COUNT); + assert(plat_mt_pm != NULL); + + (void)plat_mt_pm_invoke(plat_mt_pm->pwr_prompt, cpu, state); + + /* Perform the common CPU specific operations */ + plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]); + + if (IS_CLUSTER_OFF_STATE(state)) { + /* Perform the common cluster specific operations */ + plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]); + } + + if (IS_MCUSYS_OFF_STATE(state)) { + /* Perform the common mcusys specific operations */ + plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]); + } +} + +static void plat_power_domain_suspend_finish(const psci_power_state_t *state) +{ + unsigned int cpu = plat_my_core_pos(); + + assert(cpu < PLATFORM_CORE_COUNT); + assert(plat_mt_pm != NULL); + + if (IS_MCUSYS_OFF_STATE(state)) { + /* Perform the common mcusys specific operations */ + plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]); + } + + if (IS_CLUSTER_OFF_STATE(state)) { + /* Perform the common cluster specific operations */ + plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]); + } + + /* Perform the common CPU specific operations */ + plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]); + + (void)plat_mt_pm_invoke(plat_mt_pm->pwr_reflect, cpu, state); +} + +static int plat_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int pstate = psci_get_pstate_type(power_state); + unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state); + unsigned int cpu = plat_my_core_pos(); + + if (aff_lvl > PLAT_MAX_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + + if (pstate == PSTATE_TYPE_STANDBY) { + req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE; + } else { + unsigned int i; + unsigned int pstate_id = psci_get_pstate_id(power_state); + plat_local_state_t s = MTK_LOCAL_STATE_OFF; + + /* Use pstate_id to be power domain state */ + if (pstate_id > s) { + s = (plat_local_state_t)pstate_id; + } + + for (i = 0U; i <= aff_lvl; i++) { + req_state->pwr_domain_state[i] = s; + } + } + + plat_power_state[cpu] = power_state; + return PSCI_E_SUCCESS; +} + +static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int lv; + unsigned int cpu = plat_my_core_pos(); + + for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) { + req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE; + } + + plat_power_state[cpu] = + psci_make_powerstate( + MT_PLAT_PWR_STATE_SYSTEM_SUSPEND, + PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL); + + flush_dcache_range((uintptr_t) + &plat_power_state[cpu], + sizeof(plat_power_state[cpu])); +} + +/******************************************************************************* + * MTK handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 plat_mtk_system_reset(void) +{ + struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset(); + + INFO("MTK System Reset\n"); + + gpio_set_value(gpio_reset->index, gpio_reset->polarity); + + wfi(); + ERROR("MTK System Reset: operation not handled.\n"); + panic(); +} + +static void __dead2 plat_mtk_system_off(void) +{ + INFO("MTK System Off\n"); + + rtc_power_off_sequence(); + pmic_power_off(); + + wfi(); + ERROR("MTK System Off: operation not handled.\n"); + panic(); +} + +static const plat_psci_ops_t plat_psci_ops = { + .cpu_standby = plat_cpu_standby, + .pwr_domain_on = plat_power_domain_on, + .pwr_domain_on_finish = plat_power_domain_on_finish, + .pwr_domain_off = plat_power_domain_off, + .pwr_domain_suspend = plat_power_domain_suspend, + .pwr_domain_suspend_finish = plat_power_domain_suspend_finish, + .validate_power_state = plat_validate_power_state, + .get_sys_suspend_power_state = plat_get_sys_suspend_power_state, + .system_off = plat_mtk_system_off, + .system_reset = plat_mtk_system_reset, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &plat_psci_ops; + secure_entrypoint = sec_entrypoint; + + /* + * init the warm reset config for boot CPU + * reset arch as AARCH64 + * reset addr as function bl31_warm_entrypoint() + */ + mcucfg_init_archstate(0U, 0U, true); + mcucfg_set_bootaddr(0U, 0U, secure_entrypoint); + + spmc_init(); + plat_mt_pm = mt_plat_cpu_pm_init(); + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c b/arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c new file mode 100644 index 0000000..cb66218 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "plat_sip_calls.h" + +uintptr_t mediatek_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) +{ + uint64_t ret; + + switch (smc_fid) { + case MTK_SIP_VCORE_CONTROL_ARCH32: + case MTK_SIP_VCORE_CONTROL_ARCH64: + ret = spm_vcorefs_args(x1, x2, x3, (uint64_t *)&x4); + SMC_RET2(handle, ret, x4); + break; + case MTK_SIP_KERNEL_DFD_AARCH32: + case MTK_SIP_KERNEL_DFD_AARCH64: + ret = dfd_smc_dispatcher(x1, x2, x3, x4); + SMC_RET1(handle, ret); + break; + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c new file mode 100644 index 0000000..bc95c64 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +const unsigned char mtk_power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* Number of children for the root node */ + PLATFORM_MCUSYS_COUNT, + /* Number of children for the mcusys node */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return mtk_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + if ((read_mpidr() & MPIDR_MT_MASK) != 0) { + /* ARMv8.2 arch */ + if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0) { + return -1; + } + return plat_mediatek_calc_core_pos(mpidr); + } + + mpidr &= MPIDR_AFFINITY_MASK; + + if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) { + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return (cpu_id + (cluster_id * 8)); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8186/platform.mk new file mode 100644 index 0000000..b6d9ca8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/platform.mk @@ -0,0 +1,104 @@ +# +# Copyright (c) 2021-2022, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MTK_PLAT := plat/mediatek +MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} + +PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT}/common/drivers/gic600/ \ + -I${MTK_PLAT}/common/drivers/gpio/ \ + -I${MTK_PLAT}/common/drivers/uart/ \ + -I${MTK_PLAT}/common/drivers/timer/ \ + -I${MTK_PLAT}/common/lpm/ \ + -I${MTK_PLAT_SOC}/drivers/spm/ \ + -I${MTK_PLAT_SOC}/drivers/dcm/ \ + -I${MTK_PLAT_SOC}/drivers/dfd/ \ + -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \ + -I${MTK_PLAT_SOC}/drivers/gpio/ \ + -I${MTK_PLAT_SOC}/drivers/mcdi/ \ + -I${MTK_PLAT_SOC}/drivers/pmic/ \ + -I${MTK_PLAT_SOC}/drivers/rtc/ \ + -I${MTK_PLAT_SOC}/drivers/spmc/ \ + -I${MTK_PLAT_SOC}/include/ + +GICV3_SUPPORT_GIC600 := 1 +include drivers/arm/gic/v3/gicv3.mk +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} \ + plat/common/aarch64/crash_console_helpers.S \ + plat/common/plat_psci_common.c + + +BL31_SOURCES += common/desc_image_load.c \ + drivers/delay_timer/delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/bl_aux_params/bl_aux_params.c \ + lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a76.S \ + plat/common/plat_gicv3.c \ + ${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c \ + ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/params_setup.c \ + ${MTK_PLAT}/common/drivers/timer/mt_timer.c \ + ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/mtk_cirq.c \ + ${MTK_PLAT}/common/lpm/mt_lp_rm.c \ + ${MTK_PLAT_SOC}/aarch64/platform_common.c \ + ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ + ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \ + ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \ + ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \ + ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \ + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_lp_irqremain.c \ + ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \ + ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \ + ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \ + ${MTK_PLAT_SOC}/plat_pm.c \ + ${MTK_PLAT_SOC}/plat_sip_calls.c \ + ${MTK_PLAT_SOC}/plat_topology.c + +# Build SPM drivers +include ${MTK_PLAT_SOC}/drivers/spm/build.mk + +# Configs for A76 and A55 +HW_ASSISTED_COHERENCY := 1 +USE_COHERENT_MEM := 0 +CTX_INCLUDE_AARCH32_REGS := 0 +ERRATA_A55_1530923 := 1 +ERRATA_A55_1221012 := 1 + +ERRATA_A76_1257314 := 1 +ERRATA_A76_1262606 := 1 +ERRATA_A76_1262888 := 1 +ERRATA_A76_1275112 := 1 +ERRATA_A76_1286807 := 1 +ERRATA_A76_1791580 := 1 +ERRATA_A76_1165522 := 1 +ERRATA_A76_1868343 := 1 +ERRATA_A76_1946160 := 1 + +# indicate the reset vector address can be programmed +PROGRAMMABLE_RESET_ADDRESS := 1 + +COLD_BOOT_SINGLE_CPU := 1 + +MACH_MT8186 := 1 +$(eval $(call add_define,MACH_MT8186)) + +include lib/coreboot/coreboot.mk diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S new file mode 100644 index 0000000..99274de --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_mediatek_calc_core_pos + +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_mediatek_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_mediatek_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr); + * + * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and + * AFF0 is thread id. There is only one cluster in ARMv8.2 + * and one thread in current implementation. + * + * With this function: CorePos = CoreID (AFF1) + * we do it with x0 = (x0 >> 8) & 0xff + * ----------------------------------------------------- + */ +func plat_mediatek_calc_core_pos + mov x1, #MPIDR_AFFLVL_MASK + and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT + ret +endfunc plat_mediatek_calc_core_pos diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c new file mode 100644 index 0000000..fc98871 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Project Includes */ +#include + +/* Platform Includes */ +#include + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_mmap[] = { + /* for TF text, RO, RW */ + MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_MCDI_SRAM_BASE, MTK_MCDI_SRAM_MAP_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(APUSYS_SCTRL_REVISER_BASE, APUSYS_SCTRL_REVISER_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(APUSYS_APU_S_S_4_BASE, APUSYS_APU_S_S_4_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(APUSYS_APC_AO_WRAPPER_BASE, APUSYS_APC_AO_WRAPPER_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(APUSYS_NOC_DAPC_AO_BASE, APUSYS_NOC_DAPC_AO_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit) +{ + mmap_add_region(total_base, total_base, total_size, + MT_RW_DATA | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + MT_CODE | MT_SECURE); + mmap_add(plat_mmap); + init_xlat_tables(); + enable_mmu_el3(0); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c new file mode 100644 index 0000000..c3cb9a5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* System Includes */ +#include + +/* Project Includes */ +#include +#include +#include +#include +#include +#include + +/* Platform Includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + * BL2 has flushed this information to memory, so we are guaranteed to pick up + * good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + params_early_setup(arg1); + +#if COREBOOT + if (coreboot_serial.type) { + console_16550_register(coreboot_serial.baseaddr, + coreboot_serial.input_hertz, + coreboot_serial.baud, + &console); + } +#else + console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console); +#endif + + NOTICE("MT8192 bl31_setup\n"); + + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); +} + + +/******************************************************************************* + * Perform any BL31 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + /* Set dcm on */ + if (!dcm_set_default()) { + ERROR("Failed to set default dcm on!!\n"); + } + + /* MPU Init */ + emi_mpu_init(); + + /* DAPC Init */ + devapc_init(); + + /* Initialize the GIC driver, CPU and distributor interfaces */ + mt_gic_driver_init(); + mt_gic_init(); + + mt_gpio_init(); + mt_systimer_init(); + generic_delay_timer_init(); + spm_boot_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + plat_configure_mmu_el3(BL31_START, + BL31_END - BL31_START, + BL_CODE_BASE, + BL_CODE_END); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c new file mode 100644 index 0000000..782aa5f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +uint64_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, + uint32_t *ret1) +{ + uint32_t request_ops; + + request_ops = (uint32_t)x1; + INFO("[APUSYS] ops=0x%x\n", request_ops); + + switch (request_ops) { + case MTK_SIP_APU_START_MCU: + /* setup addr[33:32] in reviser */ + mmio_write_32(REVISER_SECUREFW_CTXT, 0U); + mmio_write_32(REVISER_USDRFW_CTXT, 0U); + + /* setup secure sideband */ + mmio_write_32(AO_SEC_FW, + (SEC_FW_NON_SECURE << SEC_FW_SHIFT_NS) | + (0U << SEC_FW_DOMAIN_SHIFT)); + + /* setup boot address */ + mmio_write_32(AO_MD32_BOOT_CTRL, 0U); + + /* setup pre-define region */ + mmio_write_32(AO_MD32_PRE_DEFINE, + (PRE_DEFINE_CACHE_TCM << PRE_DEFINE_SHIFT_0G) | + (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_1G) | + (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_2G) | + (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_3G)); + + /* release runstall */ + mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_RUN); + + INFO("[APUSYS] reviser_ctxt=%x,%x\n", + mmio_read_32(REVISER_SECUREFW_CTXT), + mmio_read_32(REVISER_USDRFW_CTXT)); + INFO("[APUSYS]fw=0x%08x,boot=0x%08x,def=0x%08x,sys=0x%08x\n", + mmio_read_32(AO_SEC_FW), + mmio_read_32(AO_MD32_BOOT_CTRL), + mmio_read_32(AO_MD32_PRE_DEFINE), + mmio_read_32(AO_MD32_SYS_CTRL)); + break; + case MTK_SIP_APU_STOP_MCU: + /* hold runstall */ + mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_STALL); + + INFO("[APUSYS] md32_boot_ctrl=0x%08x,runstall=0x%08x\n", + mmio_read_32(AO_MD32_BOOT_CTRL), + mmio_read_32(AO_MD32_SYS_CTRL)); + break; + default: + ERROR("%s, unknown request_ops = %x\n", __func__, request_ops); + break; + } + + return 0UL; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h new file mode 100644 index 0000000..95fac4a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MTK_APUSYS_H__ +#define __MTK_APUSYS_H__ + +#include + +/* setup the SMC command ops */ +#define MTK_SIP_APU_START_MCU 0x00U +#define MTK_SIP_APU_STOP_MCU 0x01U + +/* AO Register */ +#define AO_MD32_PRE_DEFINE (APUSYS_APU_S_S_4_BASE + 0x00) +#define AO_MD32_BOOT_CTRL (APUSYS_APU_S_S_4_BASE + 0x04) +#define AO_MD32_SYS_CTRL (APUSYS_APU_S_S_4_BASE + 0x08) +#define AO_SEC_FW (APUSYS_APU_S_S_4_BASE + 0x10) + +#define PRE_DEFINE_CACHE_TCM 0x3U +#define PRE_DEFINE_CACHE 0x2U +#define PRE_DEFINE_SHIFT_0G 0U +#define PRE_DEFINE_SHIFT_1G 2U +#define PRE_DEFINE_SHIFT_2G 4U +#define PRE_DEFINE_SHIFT_3G 6U + +#define SEC_FW_NON_SECURE 1U +#define SEC_FW_SHIFT_NS 4U +#define SEC_FW_DOMAIN_SHIFT 0U + +#define SYS_CTRL_RUN 0U +#define SYS_CTRL_STALL 1U + +/* Reviser Register */ +#define REVISER_SECUREFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x300) +#define REVISER_USDRFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x304) + +uint64_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, + uint32_t *ret1); +#endif /* __MTK_APUSYS_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c new file mode 100644 index 0000000..245d512 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static const struct APC_DOM_16 APUSYS_NOC_DAPC_AO[] = { +/* 0~3 */ +APUSYS_APC_AO_ATTR("slv07-0", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), +APUSYS_APC_AO_ATTR("slv07-1", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), +APUSYS_APC_AO_ATTR("slv07-2", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), +APUSYS_APC_AO_ATTR("slv07-3", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), + +/* 16~18 */ +APUSYS_APC_AO_ATTR("slv01-0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("slv01-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("slv01-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 19~21 */ +APUSYS_APC_AO_ATTR("slv00-0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("slv00-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("slv00-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 22~26 */ +APUSYS_APC_AO_ATTR("slv02-0", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), +APUSYS_APC_AO_ATTR("slv02-1", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), +APUSYS_APC_AO_ATTR("slv02-2", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), +APUSYS_APC_AO_ATTR("slv02-3", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), +APUSYS_APC_AO_ATTR("slv02-4", + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION), +}; + +static int32_t set_slave_noc_dapc(uint32_t slave, + enum APUSYS_APC_DOMAIN_ID domain_id, + enum APUSYS_APC_PERM_TYPE perm) +{ + uint32_t apc_register_index; + uint32_t apc_set_index; + uintptr_t base; + uint32_t clr_bit; + uint32_t set_bit; + int32_t ret; + + if (perm >= PERM_NUM) { + ERROR("[NOC_DAPC] perm type:0x%x is not supported!\n", perm); + ret = APUSYS_APC_ERR_PERMISSION_NOT_SUPPORTED; + goto exit; + } + + apc_register_index = slave / APUSYS_NOC_DAPC_AO_SLAVE_NUM_IN_1_DOM; + apc_set_index = slave % APUSYS_NOC_DAPC_AO_SLAVE_NUM_IN_1_DOM; + + clr_bit = 0xFFFFFFFF ^ (0x3U << (apc_set_index * 2)); + set_bit = perm << (apc_set_index * 2); + + if ((slave < APUSYS_NOC_DAPC_AO_SLAVE_NUM) && + (domain_id < APUSYS_NOC_DAPC_AO_DOM_NUM)) { + base = APUSYS_NOC_DAPC_AO_BASE + + (domain_id * 0x40) + (apc_register_index * 4); + apuapc_writel(apuapc_readl(base) & clr_bit, base); + apuapc_writel(apuapc_readl(base) | set_bit, base); + ret = APUSYS_APC_OK; + } else { + ERROR("[NOC_DAPC] %s: %s, %s:0x%x, %s:0x%x\n", + __func__, "out of boundary", + "slave", slave, + "domain_id", domain_id); + ret = APUSYS_APC_ERR_OUT_OF_BOUNDARY; + } + +exit: + return ret; +} + +static void dump_apusys_noc_dapc(void) +{ + uint32_t reg_num; + uint32_t d, i; + + reg_num = APUSYS_NOC_DAPC_AO_SLAVE_NUM / + APUSYS_NOC_DAPC_AO_SLAVE_NUM_IN_1_DOM; + for (d = 0U; d < APUSYS_NOC_DAPC_AO_DOM_NUM; d++) { + for (i = 0U; i <= reg_num; i++) { + INFO("[NOCDAPC] D%d_APC_%d: 0x%x\n", d, i, + apuapc_readl(APUSYS_NOC_DAPC_AO_BASE + + (d * 0x40) + (i * 4))); + } + } + + INFO("[NOCDAPC] APC_CON: 0x%x\n", apuapc_readl(APUSYS_NOC_DAPC_CON)); +} + +static const struct APC_DOM_16 APUSYS_AO_Devices[] = { + +/* 0 */ +APUSYS_APC_AO_ATTR("apusys_ao-0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apusys_ao-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apusys_ao-2", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apusys_ao-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apusys_ao-4", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apusys_ao-5", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("md32_apb_s-0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("md32_apb_s-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("md32_apb_s-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("md32_debug_apb", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 10 */ +APUSYS_APC_AO_ATTR("apu_conn_config", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_sctrl_reviser", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_sema_stimer", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_emi_config", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_adl", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_edma_lite0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_edma_lite1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_edma0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_edma0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_dapc_ao", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 20 */ +APUSYS_APC_AO_ATTR("apu_dapc", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("infra_bcrm", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apb_dbg_ctl", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("noc_dapc", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_noc_bcrm", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_noc_config", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("vpu_core0_config-0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("vpu_core0_config-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("vpu_core1_config-0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("vpu_core1_config-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 30 */ +APUSYS_APC_AO_ATTR("mdla0_apb-0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("mdla0_apb-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("mdla0_apb-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("mdla0_apb-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_iommu0_r0", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_iommu0_r1", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_iommu0_r2", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_iommu0_r3", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_iommu0_r4", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("apu_rsi2_config", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 40 */ +APUSYS_APC_AO_ATTR("apu_ssc2_config", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("vp6_core0_debug_apb", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +APUSYS_APC_AO_ATTR("vp6_core1_debug_apb", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +}; + +static int32_t set_slave_apc(uint32_t slave, + enum APUSYS_APC_DOMAIN_ID domain_id, + enum APUSYS_APC_PERM_TYPE perm) +{ + uint32_t apc_register_index; + uint32_t apc_set_index; + uintptr_t base; + uint32_t clr_bit; + uint32_t set_bit; + int32_t ret; + + if (perm >= PERM_NUM) { + ERROR("[APUAPC] perm type:0x%x is not supported!\n", perm); + ret = APUSYS_APC_ERR_PERMISSION_NOT_SUPPORTED; + goto exit; + } + + apc_register_index = slave / APUSYS_APC_SYS0_AO_SLAVE_NUM_IN_1_DOM; + apc_set_index = slave % APUSYS_APC_SYS0_AO_SLAVE_NUM_IN_1_DOM; + + clr_bit = 0xFFFFFFFF ^ (0x3U << (apc_set_index * 2)); + set_bit = perm << (apc_set_index * 2); + + if ((slave < APUSYS_APC_SYS0_AO_SLAVE_NUM) && + (domain_id < APUSYS_APC_SYS0_AO_DOM_NUM)) { + base = APUSYS_APC_AO_BASE + + (domain_id * 0x40) + (apc_register_index * 4); + apuapc_writel(apuapc_readl(base) & clr_bit, base); + apuapc_writel(apuapc_readl(base) | set_bit, base); + ret = APUSYS_APC_OK; + } else { + ERROR("[APUAPC] %s: %s, %s:0x%x, %s:0x%x\n", + __func__, "out of boundary", + "slave", slave, + "domain_id", domain_id); + ret = APUSYS_APC_ERR_OUT_OF_BOUNDARY; + } + +exit: + return ret; +} + +static void dump_apusys_ao_apc(void) +{ + uint32_t reg_num; + uint32_t d, i; + + reg_num = APUSYS_APC_SYS0_AO_SLAVE_NUM / + APUSYS_APC_SYS0_AO_SLAVE_NUM_IN_1_DOM; + for (d = 0U; d < APUSYS_APC_SYS0_AO_DOM_NUM; d++) { + for (i = 0U; i <= reg_num; i++) { + INFO("[APUAPC] D%d_APC_%d: 0x%x\n", d, i, + apuapc_readl(APUSYS_APC_AO_BASE + + (d * 0x40) + (i * 4))); + } + } + INFO("[APUAPC] APC_CON: 0x%x\n", apuapc_readl(APUSYS_APC_CON)); +} + +static int32_t set_apusys_noc_dapc(void) +{ + int32_t ret = 0; + uint32_t i; + uint32_t index; + + for (i = 0U; i < ARRAY_SIZE(APUSYS_NOC_DAPC_AO); i++) { + if (i < APUSYS_NOC_DAPC_GAP_BOUNDARY) { + index = i; + } else { + index = i + APUSYS_NOC_DAPC_JUMP_GAP; + } + ret += set_slave_noc_dapc(index, DOMAIN_0, + APUSYS_NOC_DAPC_AO[i].d0_permission); + ret += set_slave_noc_dapc(index, DOMAIN_1, + APUSYS_NOC_DAPC_AO[i].d1_permission); + ret += set_slave_noc_dapc(index, DOMAIN_2, + APUSYS_NOC_DAPC_AO[i].d2_permission); + ret += set_slave_noc_dapc(index, DOMAIN_3, + APUSYS_NOC_DAPC_AO[i].d3_permission); + ret += set_slave_noc_dapc(index, DOMAIN_4, + APUSYS_NOC_DAPC_AO[i].d4_permission); + ret += set_slave_noc_dapc(index, DOMAIN_5, + APUSYS_NOC_DAPC_AO[i].d5_permission); + ret += set_slave_noc_dapc(index, DOMAIN_6, + APUSYS_NOC_DAPC_AO[i].d6_permission); + ret += set_slave_noc_dapc(index, DOMAIN_7, + APUSYS_NOC_DAPC_AO[i].d7_permission); + ret += set_slave_noc_dapc(index, DOMAIN_8, + APUSYS_NOC_DAPC_AO[i].d8_permission); + ret += set_slave_noc_dapc(index, DOMAIN_9, + APUSYS_NOC_DAPC_AO[i].d9_permission); + ret += set_slave_noc_dapc(index, DOMAIN_10, + APUSYS_NOC_DAPC_AO[i].d10_permission); + ret += set_slave_noc_dapc(index, DOMAIN_11, + APUSYS_NOC_DAPC_AO[i].d11_permission); + ret += set_slave_noc_dapc(index, DOMAIN_12, + APUSYS_NOC_DAPC_AO[i].d12_permission); + ret += set_slave_noc_dapc(index, DOMAIN_13, + APUSYS_NOC_DAPC_AO[i].d13_permission); + ret += set_slave_noc_dapc(index, DOMAIN_14, + APUSYS_NOC_DAPC_AO[i].d14_permission); + ret += set_slave_noc_dapc(index, DOMAIN_15, + APUSYS_NOC_DAPC_AO[i].d15_permission); + } + + return ret; +} + +static int32_t set_apusys_ao_apc(void) +{ + int32_t ret = 0; + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(APUSYS_AO_Devices); i++) { + ret += set_slave_apc(i, DOMAIN_0, + APUSYS_AO_Devices[i].d0_permission); + ret += set_slave_apc(i, DOMAIN_1, + APUSYS_AO_Devices[i].d1_permission); + ret += set_slave_apc(i, DOMAIN_2, + APUSYS_AO_Devices[i].d2_permission); + ret += set_slave_apc(i, DOMAIN_3, + APUSYS_AO_Devices[i].d3_permission); + ret += set_slave_apc(i, DOMAIN_4, + APUSYS_AO_Devices[i].d4_permission); + ret += set_slave_apc(i, DOMAIN_5, + APUSYS_AO_Devices[i].d5_permission); + ret += set_slave_apc(i, DOMAIN_6, + APUSYS_AO_Devices[i].d6_permission); + ret += set_slave_apc(i, DOMAIN_7, + APUSYS_AO_Devices[i].d7_permission); + ret += set_slave_apc(i, DOMAIN_8, + APUSYS_AO_Devices[i].d8_permission); + ret += set_slave_apc(i, DOMAIN_9, + APUSYS_AO_Devices[i].d9_permission); + ret += set_slave_apc(i, DOMAIN_10, + APUSYS_AO_Devices[i].d10_permission); + ret += set_slave_apc(i, DOMAIN_11, + APUSYS_AO_Devices[i].d11_permission); + ret += set_slave_apc(i, DOMAIN_12, + APUSYS_AO_Devices[i].d12_permission); + ret += set_slave_apc(i, DOMAIN_13, + APUSYS_AO_Devices[i].d13_permission); + ret += set_slave_apc(i, DOMAIN_14, + APUSYS_AO_Devices[i].d14_permission); + ret += set_slave_apc(i, DOMAIN_15, + APUSYS_AO_Devices[i].d15_permission); + } + + return ret; +} + +static void set_apusys_apc_lock(void) +{ + uint32_t set_bit = 1U << APUSYS_APC_SYS0_LOCK_BIT_APU_SCTRL_REVISER; + + /* Lock apu_sctrl_reviser */ + set_bit = set_bit | (1U << APUSYS_APC_SYS0_LOCK_BIT_APUSYS_AO_5); + apuapc_writel(set_bit, APUSYS_SYS0_APC_LOCK_0); +} + +void set_apusys_apc(void) +{ + int32_t ret = 0; + + /* Check violation status */ + INFO("[APUAPC] vio %d\n", apuapc_readl(APUSYS_APC_CON) & 0x80000000); + + /* Initial Permission */ + ret = set_apusys_ao_apc(); + INFO("[APUAPC] %s - %s!\n", "set_apusys_ao_apc", + ret ? "FAILED" : "SUCCESS"); + + /* Lock */ + set_apusys_apc_lock(); + + /* Initial NoC Permission */ + ret = set_apusys_noc_dapc(); + INFO("[APUAPC] %s - %s!\n", "set_apusys_noc_dapc", + ret ? "FAILED" : "SUCCESS"); + + /* Dump Permission */ + dump_apusys_ao_apc(); + dump_apusys_noc_dapc(); + + INFO("[APUAPC] %s done\n", __func__); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h new file mode 100644 index 0000000..ff7a9fa --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MTK_APUSYS_APC_H__ +#define __MTK_APUSYS_APC_H__ + +void set_apusys_apc(void); + +#endif /* __MTK_APUSYS_APC_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h new file mode 100644 index 0000000..b392d6a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MTK_APUSYS_APC_DEF_H__ +#define __MTK_APUSYS_APC_DEF_H__ + +#include + +enum APUSYS_APC_ERR_STATUS { + APUSYS_APC_OK = 0x0, + + APUSYS_APC_ERR_GENERIC = 0x1000, + APUSYS_APC_ERR_INVALID_CMD = 0x1001, + APUSYS_APC_ERR_SLAVE_TYPE_NOT_SUPPORTED = 0x1002, + APUSYS_APC_ERR_SLAVE_IDX_NOT_SUPPORTED = 0x1003, + APUSYS_APC_ERR_DOMAIN_NOT_SUPPORTED = 0x1004, + APUSYS_APC_ERR_PERMISSION_NOT_SUPPORTED = 0x1005, + APUSYS_APC_ERR_OUT_OF_BOUNDARY = 0x1006, + APUSYS_APC_ERR_REQ_TYPE_NOT_SUPPORTED = 0x1007, +}; + +enum APUSYS_APC_PERM_TYPE { + NO_PROTECTION = 0U, + SEC_RW_ONLY = 1U, + SEC_RW_NS_R = 2U, + FORBIDDEN = 3U, + PERM_NUM = 4U, +}; + +enum APUSYS_APC_DOMAIN_ID { + DOMAIN_0 = 0U, + DOMAIN_1 = 1U, + DOMAIN_2 = 2U, + DOMAIN_3 = 3U, + DOMAIN_4 = 4U, + DOMAIN_5 = 5U, + DOMAIN_6 = 6U, + DOMAIN_7 = 7U, + DOMAIN_8 = 8U, + DOMAIN_9 = 9U, + DOMAIN_10 = 10U, + DOMAIN_11 = 11U, + DOMAIN_12 = 12U, + DOMAIN_13 = 13U, + DOMAIN_14 = 14U, + DOMAIN_15 = 15U, +}; + +struct APC_DOM_16 { + unsigned char d0_permission; + unsigned char d1_permission; + unsigned char d2_permission; + unsigned char d3_permission; + unsigned char d4_permission; + unsigned char d5_permission; + unsigned char d6_permission; + unsigned char d7_permission; + unsigned char d8_permission; + unsigned char d9_permission; + unsigned char d10_permission; + unsigned char d11_permission; + unsigned char d12_permission; + unsigned char d13_permission; + unsigned char d14_permission; + unsigned char d15_permission; +}; + +#define APUSYS_APC_AO_ATTR(DEV_NAME, PERM_ATTR0, PERM_ATTR1, \ + PERM_ATTR2, PERM_ATTR3, PERM_ATTR4, PERM_ATTR5, \ + PERM_ATTR6, PERM_ATTR7, PERM_ATTR8, PERM_ATTR9, \ + PERM_ATTR10, PERM_ATTR11, PERM_ATTR12, PERM_ATTR13, \ + PERM_ATTR14, PERM_ATTR15) \ + {(unsigned char)PERM_ATTR0, (unsigned char)PERM_ATTR1, \ + (unsigned char)PERM_ATTR2, (unsigned char)PERM_ATTR3, \ + (unsigned char)PERM_ATTR4, (unsigned char)PERM_ATTR5, \ + (unsigned char)PERM_ATTR6, (unsigned char)PERM_ATTR7, \ + (unsigned char)PERM_ATTR8, (unsigned char)PERM_ATTR9, \ + (unsigned char)PERM_ATTR10, (unsigned char)PERM_ATTR11, \ + (unsigned char)PERM_ATTR12, (unsigned char)PERM_ATTR13, \ + (unsigned char)PERM_ATTR14, (unsigned char)PERM_ATTR15} + +#define apuapc_writel(VAL, REG) mmio_write_32((uintptr_t)REG, VAL) +#define apuapc_readl(REG) mmio_read_32((uintptr_t)REG) + +/* APUSYS APC AO Registers */ +#define APUSYS_APC_AO_BASE APUSYS_APC_AO_WRAPPER_BASE +#define APUSYS_APC_CON (APUSYS_APC_AO_BASE + 0x00F00) +#define APUSYS_SYS0_APC_LOCK_0 (APUSYS_APC_AO_BASE + 0x00700) + +/* APUSYS NOC_DPAC_AO Registers */ +#define APUSYS_NOC_DAPC_CON (APUSYS_NOC_DAPC_AO_BASE + 0x00F00) + +#define APUSYS_NOC_DAPC_GAP_BOUNDARY 4U +#define APUSYS_NOC_DAPC_JUMP_GAP 12U + +#define APUSYS_APC_SYS0_AO_SLAVE_NUM_IN_1_DOM 16U +#define APUSYS_APC_SYS0_AO_DOM_NUM 16U +#define APUSYS_APC_SYS0_AO_SLAVE_NUM 59U + +#define APUSYS_APC_SYS0_LOCK_BIT_APU_SCTRL_REVISER 11U +#define APUSYS_APC_SYS0_LOCK_BIT_APUSYS_AO_5 5U + +#define APUSYS_NOC_DAPC_AO_SLAVE_NUM_IN_1_DOM 16U +#define APUSYS_NOC_DAPC_AO_DOM_NUM 16U +#define APUSYS_NOC_DAPC_AO_SLAVE_NUM 27U + +#endif /* __MTK_APUSYS_APC_DEF_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c new file mode 100644 index 0000000..dd8bf4e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +static void dcm_armcore(bool mode) +{ + dcm_mp_cpusys_top_bus_pll_div_dcm(mode); + dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode); + dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode); +} + +static void dcm_mcusys(bool on) +{ + dcm_mp_cpusys_top_adb_dcm(on); + dcm_mp_cpusys_top_apb_dcm(on); + dcm_mp_cpusys_top_cpubiu_dcm(on); + dcm_mp_cpusys_top_misc_dcm(on); + dcm_mp_cpusys_top_mp0_qdcm(on); + dcm_cpccfg_reg_emi_wfifo(on); + dcm_mp_cpusys_top_last_cor_idle_dcm(on); +} + +static void dcm_stall(bool on) +{ + dcm_mp_cpusys_top_core_stall_dcm(on); + dcm_mp_cpusys_top_fcm_stall_dcm(on); +} + +static bool check_dcm_state(void) +{ + bool ret = true; + + ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(); + + ret &= dcm_mp_cpusys_top_adb_dcm_is_on(); + ret &= dcm_mp_cpusys_top_apb_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on(); + ret &= dcm_mp_cpusys_top_misc_dcm_is_on(); + ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on(); + ret &= dcm_cpccfg_reg_emi_wfifo_is_on(); + ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(); + + ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on(); + ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on(); + + return ret; +} + +bool dcm_set_default(void) +{ + dcm_armcore(true); + dcm_mcusys(true); + dcm_stall(true); + + return check_dcm_state(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h new file mode 100644 index 0000000..ee98d0e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_DCM_H +#define MTK_DCM_H + +#include + +bool dcm_set_default(void); + +#endif /* #ifndef MTK_DCM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c new file mode 100644 index 0000000..15a700c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(17)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | \ + BIT(16) | \ + BIT(17) | \ + BIT(18) | \ + BIT(21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | \ + BIT(16) | \ + BIT(17) | \ + BIT(18)) +#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(17)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | \ + BIT(16) | \ + BIT(17) | \ + BIT(18) | \ + BIT(21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | \ + BIT(16) | \ + BIT(17) | \ + BIT(18)) +#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 17)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | \ + (0x0 << 16) | \ + (0x0 << 17) | \ + (0x0 << 18) | \ + (0x0 << 21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | \ + (0x0 << 16) | \ + (0x0 << 17) | \ + (0x0 << 18)) + +bool dcm_mp_cpusys_top_adb_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_ADB_DCM_CFG0) & + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON); + ret &= ((mmio_read_32(MP_ADB_DCM_CFG4) & + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) == + (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON); + ret &= ((mmio_read_32(MCUSYS_DCM_CFG0) & + MP_CPUSYS_TOP_ADB_DCM_REG2_MASK) == + (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG2_ON); + + return ret; +} + +void dcm_mp_cpusys_top_adb_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */ + mmio_clrsetbits_32(MP_ADB_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG0_ON); + mmio_clrsetbits_32(MP_ADB_DCM_CFG4, + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG1_ON); + mmio_clrsetbits_32(MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG2_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG2_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */ + mmio_clrsetbits_32(MP_ADB_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG0_OFF); + mmio_clrsetbits_32(MP_ADB_DCM_CFG4, + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG1_OFF); + mmio_clrsetbits_32(MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG2_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG2_OFF); + } +} + +#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16)) +#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16)) +#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16)) + +bool dcm_mp_cpusys_top_apb_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON); + ret &= ((mmio_read_32(MCUSYS_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG1_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON); + ret &= ((mmio_read_32(MP0_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG2_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON); + + return ret; +} + +void dcm_mp_cpusys_top_apb_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */ + mmio_clrsetbits_32(MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG0_MASK, + MP_CPUSYS_TOP_APB_DCM_REG0_ON); + mmio_clrsetbits_32(MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG1_MASK, + MP_CPUSYS_TOP_APB_DCM_REG1_ON); + mmio_clrsetbits_32(MP0_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG2_MASK, + MP_CPUSYS_TOP_APB_DCM_REG2_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */ + mmio_clrsetbits_32(MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG0_MASK, + MP_CPUSYS_TOP_APB_DCM_REG0_OFF); + mmio_clrsetbits_32(MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG1_MASK, + MP_CPUSYS_TOP_APB_DCM_REG1_OFF); + mmio_clrsetbits_32(MP0_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG2_MASK, + MP_CPUSYS_TOP_APB_DCM_REG2_OFF); + } +} + +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11)) +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11)) +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11)) + +bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(BUS_PLLDIV_CFG) & + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */ + mmio_clrsetbits_32(BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */ + mmio_clrsetbits_32(BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0)) +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0)) +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0)) + +bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP0_DCM_CFG7) & + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_core_stall_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */ + mmio_clrsetbits_32(MP0_DCM_CFG7, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */ + mmio_clrsetbits_32(MP0_DCM_CFG7, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0)) +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0)) +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0)) + +bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MCSI_DCM0) & + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpubiu_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */ + mmio_clrsetbits_32(MCSI_DCM0, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */ + mmio_clrsetbits_32(MCSI_DCM0, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 11)) + +bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(CPU_PLLDIV_CFG0) & + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG0, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG0, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 11)) + +bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(CPU_PLLDIV_CFG1) & + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG1, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG1, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_OFF ((0x0 << 11)) + +bool dcm_mp_cpusys_top_cpu_pll_div_2_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(CPU_PLLDIV_CFG2) & + MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_2_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_2_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG2, + MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_2_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG2, + MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_OFF ((0x0 << 11)) + +bool dcm_mp_cpusys_top_cpu_pll_div_3_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(CPU_PLLDIV_CFG3) & + MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_3_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_3_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG3, + MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_3_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG3, + MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON (BIT(11)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_OFF ((0x0 << 11)) + +bool dcm_mp_cpusys_top_cpu_pll_div_4_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(CPU_PLLDIV_CFG4) & + MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_4_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_4_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG4, + MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_4_dcm'" */ + mmio_clrsetbits_32(CPU_PLLDIV_CFG4, + MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4)) +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4)) +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4)) + +bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP0_DCM_CFG7) & + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_fcm_stall_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */ + mmio_clrsetbits_32(MP0_DCM_CFG7, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */ + mmio_clrsetbits_32(MP0_DCM_CFG7, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK ((0x1U << 31)) +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON ((0x1U << 31)) +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0U << 31)) + +bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(BUS_PLLDIV_CFG) & + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */ + mmio_clrsetbits_32(BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */ + mmio_clrsetbits_32(BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | \ + BIT(4)) +#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | \ + BIT(4)) +#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | \ + (0x0 << 4)) + +bool dcm_mp_cpusys_top_misc_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) & + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_misc_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */ + mmio_clrsetbits_32(MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK, + MP_CPUSYS_TOP_MISC_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */ + mmio_clrsetbits_32(MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK, + MP_CPUSYS_TOP_MISC_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | \ + (0x0 << 1) | \ + (0x0 << 2) | \ + (0x0 << 3)) + +bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) & + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON); + ret &= ((mmio_read_32(MP0_DCM_CFG0) & + MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK) == + (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG1_ON); + + return ret; +} + +void dcm_mp_cpusys_top_mp0_qdcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */ + mmio_clrsetbits_32(MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG0_ON); + mmio_clrsetbits_32(MP0_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG1_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */ + mmio_clrsetbits_32(MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF); + mmio_clrsetbits_32(MP0_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF); + } +} + +#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | \ + (0x0 << 1) | \ + (0x0 << 2) | \ + (0x0 << 3)) + +bool dcm_cpccfg_reg_emi_wfifo_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(EMI_WFIFO) & + CPCCFG_REG_EMI_WFIFO_REG0_MASK) == + (unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON); + + return ret; +} + +void dcm_cpccfg_reg_emi_wfifo(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */ + mmio_clrsetbits_32(EMI_WFIFO, + CPCCFG_REG_EMI_WFIFO_REG0_MASK, + CPCCFG_REG_EMI_WFIFO_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */ + mmio_clrsetbits_32(EMI_WFIFO, + CPCCFG_REG_EMI_WFIFO_REG0_MASK, + CPCCFG_REG_EMI_WFIFO_REG0_OFF); + } +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h new file mode 100644 index 0000000..1cf7834 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_DCM_UTILS_H +#define MTK_DCM_UTILS_H + +#include + +#include +#include + +/* Base */ +#define MP_CPUSYS_TOP_BASE (MCUCFG_BASE + 0x8000) +#define CPCCFG_REG_BASE (MCUCFG_BASE + 0xA800) + +/* Register Definition */ +#define CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0) +#define CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4) +#define CPU_PLLDIV_CFG2 (MP_CPUSYS_TOP_BASE + 0x22a8) +#define CPU_PLLDIV_CFG3 (MP_CPUSYS_TOP_BASE + 0x22ac) +#define CPU_PLLDIV_CFG4 (MP_CPUSYS_TOP_BASE + 0x22b0) +#define BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0) +#define MCSI_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440) +#define MP_ADB_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2500) +#define MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510) +#define MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518) +#define MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0) +#define EMI_WFIFO (CPCCFG_REG_BASE + 0x100) +#define MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880) +#define MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c) + +/* MP_CPUSYS_TOP */ +bool dcm_mp_cpusys_top_adb_dcm_is_on(void); +void dcm_mp_cpusys_top_adb_dcm(bool on); +bool dcm_mp_cpusys_top_apb_dcm_is_on(void); +void dcm_mp_cpusys_top_apb_dcm(bool on); +bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void); +void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on); +bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void); +void dcm_mp_cpusys_top_core_stall_dcm(bool on); +bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void); +void dcm_mp_cpusys_top_cpubiu_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_2_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_2_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_3_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_3_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_4_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_4_dcm(bool on); +bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void); +void dcm_mp_cpusys_top_fcm_stall_dcm(bool on); +bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void); +void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on); +bool dcm_mp_cpusys_top_misc_dcm_is_on(void); +void dcm_mp_cpusys_top_misc_dcm(bool on); +bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void); +void dcm_mp_cpusys_top_mp0_qdcm(bool on); +/* CPCCFG_REG */ +bool dcm_cpccfg_reg_emi_wfifo_is_on(void); +void dcm_cpccfg_reg_emi_wfifo(bool on); + +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c new file mode 100644 index 0000000..b11f272 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c @@ -0,0 +1,2847 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/* Infra_ao */ +static const struct APC_INFRA_PERI_DOM_16 INFRA_AO_SYS0_Devices[] = { + +/* 0 */ +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-4", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-5", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-6", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-7", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-8", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("APU_S_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 10 */ +DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-4", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-5", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S-1", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S-2", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S-3", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S-4", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 20 */ +DAPC_INFRA_AO_SYS0_ATTR("L3C_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("L3C_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS0_ATTR("PCIE_AXI_S", + NO_PROTECTION, NO_PROTECTION, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +}; + +static const struct APC_INFRA_PERI_DOM_4 INFRA_AO_SYS1_Devices[] = { + +/* 0 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-4", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-5", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-6", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-7", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-8", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-9", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 10 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-10", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-11", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-12", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-13", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-14", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-15", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-16", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-17", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-18", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-19", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 20 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-20", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-21", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-22", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-23", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-24", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-25", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-26", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-27", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-28", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-29", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 30 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-30", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-31", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-32", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-33", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-34", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-35", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-36", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-37", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-38", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-39", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 40 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-100", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-101", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-102", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-103", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-104", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-105", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-106", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-107", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-108", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-109", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 50 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-110", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-111", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-112", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-113", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-114", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-115", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-116", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-117", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-118", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-119", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 60 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-120", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-121", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-122", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-123", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-124", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-125", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-126", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-127", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-128", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-129", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 70 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-130", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-131", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-132", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-133", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-134", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-135", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-136", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-137", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-138", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-139", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 80 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-140", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-141", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-142", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-143", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-200", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-201", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-202", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-203", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-204", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-205", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 90 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-206", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-207", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-300", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-301", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-302", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-303", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-304", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-305", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-306", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-307", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 100 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-400", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-401", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-402", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-403", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-404", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-405", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-406", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-407", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-408", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-409", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 110 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-410", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-411", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-412", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-413", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-414", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-415", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-416", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-417", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-418", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-419", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 120 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-420", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-421", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-422", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-423", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-424", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-425", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-426", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-427", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-428", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-429", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 130 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-430", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-431", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-432", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-433", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-434", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-435", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-436", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-437", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-438", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-439", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 140 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-440", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-441", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-442", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-443", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-444", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-445", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-446", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-447", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-448", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-449", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 150 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-450", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-451", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-452", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-453", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-454", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-455", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-456", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-457", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-458", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-459", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 160 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-460", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-461", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-462", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-463", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-464", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-465", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-466", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-467", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-468", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-469", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 170 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-470", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-471", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-472", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-473", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-474", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-475", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-476", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-477", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-478", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-479", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 180 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-480", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-481", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-482", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-483", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-484", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-485", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-486", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-487", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-488", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-489", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 190 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-490", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-491", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-492", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-493", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-494", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-495", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-496", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-497", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-498", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-499", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 200 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-500", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-501", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-502", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-503", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-504", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-505", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-506", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-507", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-508", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-509", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 210 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-510", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-511", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-512", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-513", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-514", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-515", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-516", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-517", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-518", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-519", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 220 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-520", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-521", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-522", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-523", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-524", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-525", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-526", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-527", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-528", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-529", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 230 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-530", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-531", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-532", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-533", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-534", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-535", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-536", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-537", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-538", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-539", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 240 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-540", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-541", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-542", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-543", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-544", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-545", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-546", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-547", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-548", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-549", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 250 */ +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-550", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-551", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-552", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-553", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-554", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-555", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +}; + +static const struct APC_INFRA_PERI_DOM_4 INFRA_AO_SYS2_Devices[] = { + +/* 0 */ +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-556", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-557", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-558", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-559", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-560", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-561", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-562", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-563", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-564", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-565", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 10 */ +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-566", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-567", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-568", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-569", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-570", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-571", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-572", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-573", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-574", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-575", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 20 */ +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-576", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-577", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-578", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-579", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-580", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-581", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-582", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-583", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-584", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-585", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 30 */ +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-586", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-587", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-588", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-589", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-590", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-591", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-592", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-593", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-594", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-595", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 40 */ +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-600", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-601", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-602", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-603", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-604", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-605", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-606", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-607", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-608", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-609", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 50 */ +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-610", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-611", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-700", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-701", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-702", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-703", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-704", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-705", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-706", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-707", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 60 */ +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-708", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-709", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-710", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-711", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-712", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-713", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-714", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-715", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-716", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-717", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +}; + +/* Peri_ao */ +static const struct APC_INFRA_PERI_DOM_16 PERI_AO_SYS0_Devices[] = { + +/* 0 */ +DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S-4", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("APMIXEDSYS_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, NO_PROTECTION, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("APMIXEDSYS_APB_S-1", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("TOPCKGEN_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, NO_PROTECTION, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("INFRACFG_AO_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("INFRACFG_AO_MEM_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 10 */ +DAPC_PERI_AO_SYS0_ATTR("PERICFG_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("GPIO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("TOPRGU_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("RESERVED_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEVICE_APC_INFRA_AO_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("BCRM_INFRA_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEBUG_CTRL_INFRA_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEVICE_APC_PERI_AO_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("BCRM_PERI_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEBUG_CTRL_PERI_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 20 */ +DAPC_PERI_AO_SYS0_ATTR("AP_CIRQ_EINT_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PMIC_WRAP_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEVICE_APC_AO_MM_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("KP_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("TOP_MISC_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DVFSRC_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("MBIST_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DPMAIF_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEVICE_MPU_AO_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SYS_TIMER_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 30 */ +DAPC_PERI_AO_SYS0_ATTR("MODEM_TEMP_SHARE_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEVICE_APC_AO_MD_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PMIF1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PMICSPI_MST_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("TIA_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("TOPCKGEN_INFRA_CFG_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRM_DEBUG_TOP_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 40 */ +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-3", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-4", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-5", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-6", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-7", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-8", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-9", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-10", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("AUDIO_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("AUDIO_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 50 */ +DAPC_PERI_AO_SYS0_ATTR("SSUSB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SSUSB_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SSUSB_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("UFS_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("UFS_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("UFS_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("UFS_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEBUGSYS_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_MD32_S0_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_MD32_S0_APB_S-1", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 60 */ +DAPC_PERI_AO_SYS0_ATTR("DRAMC_MD32_S1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_MD32_S1_APB_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("NOR_AXI_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("PCIE_AHB_S", + NO_PROTECTION, NO_PROTECTION, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP0_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP3_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP4_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP5_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 70 */ +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP6_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP0_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP3_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP4_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP5_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP6_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP0_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 80 */ +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP3_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP4_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP5_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP6_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP0_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP3_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP4_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 90 */ +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP5_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP6_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("CCIF2_AP_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("CCIF2_MD_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("CCIF3_AP_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("CCIF3_MD_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("CCIF4_AP_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("CCIF4_MD_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("INFRA_BUS_TRACE_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("CCIF5_AP_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 100 */ +DAPC_PERI_AO_SYS0_ATTR("CCIF5_MD_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SSC_INFRA_APB0_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SSC_INFRA_APB1_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("SSC_INFRA_APB2_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS0_ATTR("DEVICE_MPU_ACP_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +}; + +static const struct APC_INFRA_PERI_DOM_8 PERI_AO_SYS1_Devices[] = { + +/* 0 */ +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-4", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-5", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-6", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-7", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-8", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-9", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 10 */ +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-10", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-11", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-12", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-13", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-14", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-15", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-16", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-17", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-18", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-19", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 20 */ +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-20", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-21", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-22", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-4", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-5", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-6", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 30 */ +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-7", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-8", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-9", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-10", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-11", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-12", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-13", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-14", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-15", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-16", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 40 */ +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-17", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-18", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-19", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-20", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-21", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-22", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-23", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-24", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-25", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-26", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 50 */ +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-27", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-28", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-29", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-30", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-31", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-32", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-33", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-34", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-35", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-36", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 60 */ +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-37", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-38", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-39", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-40", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-41", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-42", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +}; + +static const struct APC_INFRA_PERI_DOM_4 PERI_AO_SYS2_Devices[] = { + +/* 0 */ +DAPC_PERI_AO_SYS2_ATTR("CONN_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +}; + +/* Peri_ao2 */ +static const struct APC_INFRA_PERI_DOM_16 PERI_AO2_SYS0_Devices[] = { + +/* 0 */ +DAPC_PERI_AO2_SYS0_ATTR("EFUSE_DEBUG_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("APXGPT_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("SEJ_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("AES_TOP0_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("SECURITY_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_PERI_AO2_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BCRM_PERI_AO2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEBUG_CTRL_PERI_AO2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("SPMI_MST_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEBUG_CTRL_FMEM_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 10 */ +DAPC_PERI_AO2_SYS0_ATTR("BCRM_FMEM_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_FMEM_AO_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("PWM_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("GCE_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("GCE_APB_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("GCE_APB_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("GCE_APB_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DPMAIF_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DPMAIF_PDN_APB_S-1", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DPMAIF_PDN_APB_S-2", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 20 */ +DAPC_PERI_AO2_SYS0_ATTR("DPMAIF_PDN_APB_S-3", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB0_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB1_S", + NO_PROTECTION, FORBIDDEN, SEC_RW_NS_R, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB2_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB3_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB4_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB5_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB6_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB7_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB8_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 30 */ +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB9_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB10_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB11_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB12_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB13_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB14_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB15_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB0_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB1_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB2_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 40 */ +DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB3_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB4_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB5_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB6_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB7_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB0_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB1_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB2_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB3_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB4_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 50 */ +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB5_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB6_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB7_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB8_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB9_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB10_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB11_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB12_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB13_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB14_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 60 */ +DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB15_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB0_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB1_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB2_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB3_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB4_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB5_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB6_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB7_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB8_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 70 */ +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB9_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB10_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB11_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB12_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB13_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB14_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB15_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB0_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB1_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB2_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 80 */ +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB3_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB4_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB5_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB6_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB7_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("SYS_CIRQ_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("EFUSE_DEBUG_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_INFRA_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEBUG_TRACKER_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("CCIF0_AP_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 90 */ +DAPC_PERI_AO2_SYS0_ATTR("CCIF0_MD_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("CCIF1_AP_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("CCIF1_MD_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("MBIST_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("INFRACFG_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("TRNG_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DX_CC_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("CQ_DMA_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("SRAMROM_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("INFRACFG_MEM_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 100 */ +DAPC_PERI_AO2_SYS0_ATTR("RESERVED_DVFS_PROC_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("SYS_CIRQ1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("SYS_CIRQ2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEBUG_TRACKER_APB1_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("EMI_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("EMI_MPU_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEVICE_MPU_PDN_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("APDMA_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEBUG_TRACKER_APB2_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BCRM_INFRA_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 110 */ +DAPC_PERI_AO2_SYS0_ATTR("BCRM_PERI_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BCRM_PERI_PDN2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_PERI_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_PERI_PDN2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_AO2_SYS0_ATTR("BCRM_FMEM_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +}; + +/* Peri_par_ao */ +static const struct APC_INFRA_PERI_DOM_16 PERI_PAR_AO_SYS0_Devices[] = { + +/* 0 */ +DAPC_PERI_PAR_AO_SYS0_ATTR("AUXADC_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("UART0_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("UART1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("UART2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB4_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("SPI0_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("PTP_THERM_CTRL_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("BTIF_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("DISP_PWM_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("SPI1_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 10 */ +DAPC_PERI_PAR_AO_SYS0_ATTR("SPI2_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("SPI3_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB0_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB1_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("SPI4_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("SPI5_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB2_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB3_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("SPI6_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("SPI7_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +/* 20 */ +DAPC_PERI_PAR_AO_SYS0_ATTR("BCRM_PERI_PAR_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("DEVICE_APC_PERI_PAR_PDN_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("PTP_THERM_CTRL2_APB_S", + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("NOR_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("DEVICE_APC_PERI_PAR_AO_APB_S", + SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("DEBUG_CTRL_PERI_PAR_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), +DAPC_PERI_PAR_AO_SYS0_ATTR("BCRM_PERI_PAR_AO_APB_S", + NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN), + +}; + +static void set_module_apc(enum DEVAPC_SLAVE_TYPE slave_type, + uint32_t module, enum DOMAIN_ID domain_id, + enum DEVAPC_PERM_TYPE perm) +{ + uint32_t apc_register_index; + uint32_t apc_set_index; + uintptr_t base = 0, reg; + uint32_t clr_bit; + uint32_t set_bit; + + apc_register_index = module / MOD_NO_IN_1_DEVAPC; + apc_set_index = module % MOD_NO_IN_1_DEVAPC; + + clr_bit = (0x3U << (apc_set_index * 2)); + set_bit = (uint32_t)perm << (apc_set_index * 2); + + /* infra_ao */ + if ((slave_type == SLAVE_TYPE_INFRA_AO_SYS0) && + (module < SLAVE_NUM_INFRA_AO_SYS0) && + (domain_id < (uint32_t)DOM_NUM_INFRA_AO_SYS0)) { + base = DEVAPC_INFRA_AO_SYS0_D0_APC_0; + + } else if ((slave_type == SLAVE_TYPE_INFRA_AO_SYS1) && + (module < SLAVE_NUM_INFRA_AO_SYS1) && + (domain_id < (uint32_t)DOM_NUM_INFRA_AO_SYS1)) { + base = DEVAPC_INFRA_AO_SYS1_D0_APC_0; + + } else if ((slave_type == SLAVE_TYPE_INFRA_AO_SYS2) && + (module < SLAVE_NUM_INFRA_AO_SYS2) && + (domain_id < (uint32_t)DOM_NUM_INFRA_AO_SYS2)) { + base = DEVAPC_INFRA_AO_SYS2_D0_APC_0; + /* peri_ao */ + } else if ((slave_type == SLAVE_TYPE_PERI_AO_SYS0) && + (module < SLAVE_NUM_PERI_AO_SYS0) && + (domain_id < (uint32_t)DOM_NUM_PERI_AO_SYS0)) { + base = DEVAPC_PERI_AO_SYS0_D0_APC_0; + + } else if ((slave_type == SLAVE_TYPE_PERI_AO_SYS1) && + (module < SLAVE_NUM_PERI_AO_SYS1) && + (domain_id <= (uint32_t)DOM_NUM_PERI_AO_SYS1)) { + base = DEVAPC_PERI_AO_SYS1_D0_APC_0; + + } else if ((slave_type == SLAVE_TYPE_PERI_AO_SYS2) && + (module < SLAVE_NUM_PERI_AO_SYS2) && + (domain_id < (uint32_t)DOM_NUM_PERI_AO_SYS2)) { + base = DEVAPC_PERI_AO_SYS2_D0_APC_0; + /* peri_ao2 */ + } else if ((slave_type == SLAVE_TYPE_PERI_AO2_SYS0) && + (module < SLAVE_NUM_PERI_AO2_SYS0) && + (domain_id < (uint32_t)DOM_NUM_PERI_AO2_SYS0)) { + base = DEVAPC_PERI_AO2_SYS0_D0_APC_0; + + /* peri_par_ao */ + } else if ((slave_type == SLAVE_TYPE_PERI_PAR_AO_SYS0) && + (module < SLAVE_NUM_PERI_PAR_AO_SYS0) && + (domain_id < (uint32_t)DOM_NUM_PERI_PAR_AO_SYS0)) { + base = DEVAPC_PERI_PAR_AO_SYS0_D0_APC_0; + + } else { + ERROR("[DEVAPC] %s: %s, %s:0x%x, %s:0x%x, %s:0x%x\n", + __func__, "out of boundary", + "slave_type", slave_type, + "module", module, + "domain_id", domain_id); + } + + if (base != 0U) { + reg = base + domain_id * 0x40 + apc_register_index * 4; + mmio_clrsetbits_32(reg, clr_bit, set_bit); + } +} + +static void dump_infra_ao_apc(void) +{ + int reg_num; + int d, i; + + reg_num = (SLAVE_NUM_INFRA_AO_SYS0 - 1) / MOD_NO_IN_1_DEVAPC; + for (d = 0; d < DOM_NUM_INFRA_AO_SYS0; d++) { + for (i = 0; i <= reg_num; i++) { + INFO("[DEVAPC] (INFRA_AO_SYS0)D%d_APC_%d: 0x%x\n", + d, i, devapc_readl( + DEVAPC_INFRA_AO_SYS0_D0_APC_0 + + d * 0x40 + i * 4) + ); + } + } + + reg_num = (SLAVE_NUM_INFRA_AO_SYS1 - 1) / MOD_NO_IN_1_DEVAPC; + for (d = 0; d < DOM_NUM_INFRA_AO_SYS1; d++) { + for (i = 0; i <= reg_num; i++) { + INFO("[DEVAPC] (INFRA_AO_SYS1)D%d_APC_%d: 0x%x\n", + d, i, devapc_readl( + DEVAPC_INFRA_AO_SYS1_D0_APC_0 + + d * 0x40 + i * 4) + ); + } + } + + reg_num = (SLAVE_NUM_INFRA_AO_SYS2 - 1) / MOD_NO_IN_1_DEVAPC; + for (d = 0; d < DOM_NUM_INFRA_AO_SYS2; d++) { + for (i = 0; i <= reg_num; i++) { + INFO("[DEVAPC] (INFRA_AO_SYS2)D%d_APC_%d: 0x%x\n", + d, i, devapc_readl( + DEVAPC_INFRA_AO_SYS2_D0_APC_0 + + d * 0x40 + i * 4) + ); + } + } + + INFO("[DEVAPC] (INFRA_AO)MAS_SEC_0: 0x%x\n", + devapc_readl(DEVAPC_INFRA_AO_MAS_SEC_0)); +} + +static void dump_peri_ao_apc(void) +{ + int reg_num; + int d, i; + + reg_num = (SLAVE_NUM_PERI_AO_SYS0 - 1) / MOD_NO_IN_1_DEVAPC; + for (d = 0; d < DOM_NUM_PERI_AO_SYS0; d++) { + for (i = 0; i <= reg_num; i++) { + INFO("[DEVAPC] (PERI_AO_SYS0)D%d_APC_%d: 0x%x\n", + d, i, devapc_readl( + DEVAPC_PERI_AO_SYS0_D0_APC_0 + + d * 0x40 + i * 4) + ); + } + } + + reg_num = (SLAVE_NUM_PERI_AO_SYS1 - 1) / MOD_NO_IN_1_DEVAPC; + for (d = 0; d < DOM_NUM_PERI_AO_SYS1; d++) { + for (i = 0; i <= reg_num; i++) { + INFO("[DEVAPC] (PERI_AO_SYS1)D%d_APC_%d: 0x%x\n", + d, i, devapc_readl( + DEVAPC_PERI_AO_SYS1_D0_APC_0 + + d * 0x40 + i * 4) + ); + } + } + + reg_num = (SLAVE_NUM_PERI_AO_SYS2 - 1) / MOD_NO_IN_1_DEVAPC; + for (d = 0; d < DOM_NUM_PERI_AO_SYS2; d++) { + for (i = 0; i <= reg_num; i++) { + INFO("[DEVAPC] (PERI_AO_SYS2)D%d_APC_%d: 0x%x\n", + d, i, devapc_readl( + DEVAPC_PERI_AO_SYS2_D0_APC_0 + + d * 0x40 + i * 4) + ); + } + } + + INFO("[DEVAPC] (PERI_AO)MAS_SEC_0: 0x%x\n", + devapc_readl(DEVAPC_PERI_AO_MAS_SEC_0)); +} + +static void dump_peri_ao2_apc(void) +{ + int reg_num; + int d, i; + + reg_num = (SLAVE_NUM_PERI_AO2_SYS0 - 1) / MOD_NO_IN_1_DEVAPC; + for (d = 0; d < DOM_NUM_PERI_AO2_SYS0; d++) { + for (i = 0; i <= reg_num; i++) { + INFO("[DEVAPC] (PERI_AO2_SYS0)D%d_APC_%d: 0x%x\n", + d, i, devapc_readl( + DEVAPC_PERI_AO2_SYS0_D0_APC_0 + + d * 0x40 + i * 4) + ); + } + } +} + +static void dump_peri_par_ao_apc(void) +{ + int reg_num; + int d, i; + + reg_num = (SLAVE_NUM_PERI_PAR_AO_SYS0 - 1) / MOD_NO_IN_1_DEVAPC; + for (d = 0; d < DOM_NUM_PERI_PAR_AO_SYS0; d++) { + for (i = 0; i <= reg_num; i++) { + INFO("[DEVAPC] (PERI_PAR_AO_SYS0)D%d_APC_%d: 0x%x\n", + d, i, devapc_readl( + DEVAPC_PERI_PAR_AO_SYS0_D0_APC_0 + + d * 0x40 + i * 4) + ); + } + } + + INFO("[DEVAPC] (PERI_PAR_AO)MAS_SEC_0: 0x%x\n", + devapc_readl(DEVAPC_PERI_PAR_AO_MAS_SEC_0)); +} + +static void set_infra_ao_apc(void) +{ + uint32_t infra_ao_size; + uint32_t i; + + infra_ao_size = ARRAY_SIZE(INFRA_AO_SYS0_Devices); + + for (i = 0; i < infra_ao_size; i++) { + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_0, + INFRA_AO_SYS0_Devices[i].d0_permission); /* APMCU */ + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_1, + INFRA_AO_SYS0_Devices[i].d1_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_2, + INFRA_AO_SYS0_Devices[i].d2_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_3, + INFRA_AO_SYS0_Devices[i].d3_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_4, + INFRA_AO_SYS0_Devices[i].d4_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_5, + INFRA_AO_SYS0_Devices[i].d5_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_6, + INFRA_AO_SYS0_Devices[i].d6_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_7, + INFRA_AO_SYS0_Devices[i].d7_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_8, + INFRA_AO_SYS0_Devices[i].d8_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_9, + INFRA_AO_SYS0_Devices[i].d9_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_10, + INFRA_AO_SYS0_Devices[i].d10_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_11, + INFRA_AO_SYS0_Devices[i].d11_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_12, + INFRA_AO_SYS0_Devices[i].d12_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_13, + INFRA_AO_SYS0_Devices[i].d13_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_14, + INFRA_AO_SYS0_Devices[i].d14_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_15, + INFRA_AO_SYS0_Devices[i].d15_permission); + } + + infra_ao_size = ARRAY_SIZE(INFRA_AO_SYS1_Devices); + + for (i = 0; i < infra_ao_size; i++) { + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS1, i, DOMAIN_0, + INFRA_AO_SYS1_Devices[i].d0_permission); /* APMCU */ + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS1, i, DOMAIN_1, + INFRA_AO_SYS1_Devices[i].d1_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS1, i, DOMAIN_2, + INFRA_AO_SYS1_Devices[i].d2_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS1, i, DOMAIN_3, + INFRA_AO_SYS1_Devices[i].d3_permission); + } + + infra_ao_size = ARRAY_SIZE(INFRA_AO_SYS2_Devices); + + for (i = 0; i < infra_ao_size; i++) { + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS2, i, DOMAIN_0, + INFRA_AO_SYS2_Devices[i].d0_permission); /* APMCU */ + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS2, i, DOMAIN_1, + INFRA_AO_SYS2_Devices[i].d1_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS2, i, DOMAIN_2, + INFRA_AO_SYS2_Devices[i].d2_permission); + set_module_apc(SLAVE_TYPE_INFRA_AO_SYS2, i, DOMAIN_3, + INFRA_AO_SYS2_Devices[i].d3_permission); + } +} + +static void set_peri_ao_apc(void) +{ + uint32_t peri_ao_size; + uint32_t i; + + peri_ao_size = ARRAY_SIZE(PERI_AO_SYS0_Devices); + + for (i = 0; i < peri_ao_size; i++) { + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_0, + PERI_AO_SYS0_Devices[i].d0_permission); /* APMCU */ + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_1, + PERI_AO_SYS0_Devices[i].d1_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_2, + PERI_AO_SYS0_Devices[i].d2_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_3, + PERI_AO_SYS0_Devices[i].d3_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_4, + PERI_AO_SYS0_Devices[i].d4_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_5, + PERI_AO_SYS0_Devices[i].d5_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_6, + PERI_AO_SYS0_Devices[i].d6_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_7, + PERI_AO_SYS0_Devices[i].d7_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_8, + PERI_AO_SYS0_Devices[i].d8_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_9, + PERI_AO_SYS0_Devices[i].d9_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_10, + PERI_AO_SYS0_Devices[i].d10_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_11, + PERI_AO_SYS0_Devices[i].d11_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_12, + PERI_AO_SYS0_Devices[i].d12_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_13, + PERI_AO_SYS0_Devices[i].d13_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_14, + PERI_AO_SYS0_Devices[i].d14_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_15, + PERI_AO_SYS0_Devices[i].d15_permission); + } + + peri_ao_size = ARRAY_SIZE(PERI_AO_SYS1_Devices); + + for (i = 0; i < peri_ao_size; i++) { + set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_0, + PERI_AO_SYS1_Devices[i].d0_permission); /* APMCU */ + set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_1, + PERI_AO_SYS1_Devices[i].d1_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_2, + PERI_AO_SYS1_Devices[i].d2_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_3, + PERI_AO_SYS1_Devices[i].d3_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_4, + PERI_AO_SYS1_Devices[i].d4_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_5, + PERI_AO_SYS1_Devices[i].d5_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_6, + PERI_AO_SYS1_Devices[i].d6_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_7, + PERI_AO_SYS1_Devices[i].d7_permission); + } + + peri_ao_size = ARRAY_SIZE(PERI_AO_SYS2_Devices); + + for (i = 0; i < peri_ao_size; i++) { + set_module_apc(SLAVE_TYPE_PERI_AO_SYS2, i, DOMAIN_0, + PERI_AO_SYS2_Devices[i].d0_permission); /* APMCU */ + set_module_apc(SLAVE_TYPE_PERI_AO_SYS2, i, DOMAIN_1, + PERI_AO_SYS2_Devices[i].d1_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS2, i, DOMAIN_2, + PERI_AO_SYS2_Devices[i].d2_permission); + set_module_apc(SLAVE_TYPE_PERI_AO_SYS2, i, DOMAIN_3, + PERI_AO_SYS2_Devices[i].d3_permission); + } +} + +static void set_peri_ao2_apc(void) +{ + uint32_t peri_ao2_size; + uint32_t i; + + peri_ao2_size = ARRAY_SIZE(PERI_AO2_SYS0_Devices); + + for (i = 0; i < peri_ao2_size; i++) { + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_0, + PERI_AO2_SYS0_Devices[i].d0_permission); /* APMCU */ + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_1, + PERI_AO2_SYS0_Devices[i].d1_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_2, + PERI_AO2_SYS0_Devices[i].d2_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_3, + PERI_AO2_SYS0_Devices[i].d3_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_4, + PERI_AO2_SYS0_Devices[i].d4_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_5, + PERI_AO2_SYS0_Devices[i].d5_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_6, + PERI_AO2_SYS0_Devices[i].d6_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_7, + PERI_AO2_SYS0_Devices[i].d7_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_8, + PERI_AO2_SYS0_Devices[i].d8_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_9, + PERI_AO2_SYS0_Devices[i].d9_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_10, + PERI_AO2_SYS0_Devices[i].d10_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_11, + PERI_AO2_SYS0_Devices[i].d11_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_12, + PERI_AO2_SYS0_Devices[i].d12_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_13, + PERI_AO2_SYS0_Devices[i].d13_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_14, + PERI_AO2_SYS0_Devices[i].d14_permission); + set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_15, + PERI_AO2_SYS0_Devices[i].d15_permission); + } +} + +static void set_peri_par_ao_apc(void) +{ + uint32_t peri_par_ao_size; + uint32_t i; + + peri_par_ao_size = ARRAY_SIZE(PERI_PAR_AO_SYS0_Devices); + + for (i = 0; i < peri_par_ao_size; i++) { + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_0, + PERI_PAR_AO_SYS0_Devices[i].d0_permission); /* APMCU */ + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_1, + PERI_PAR_AO_SYS0_Devices[i].d1_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_2, + PERI_PAR_AO_SYS0_Devices[i].d2_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_3, + PERI_PAR_AO_SYS0_Devices[i].d3_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_4, + PERI_PAR_AO_SYS0_Devices[i].d4_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_5, + PERI_PAR_AO_SYS0_Devices[i].d5_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_6, + PERI_PAR_AO_SYS0_Devices[i].d6_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_7, + PERI_PAR_AO_SYS0_Devices[i].d7_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_8, + PERI_PAR_AO_SYS0_Devices[i].d8_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_9, + PERI_PAR_AO_SYS0_Devices[i].d9_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_10, + PERI_PAR_AO_SYS0_Devices[i].d10_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_11, + PERI_PAR_AO_SYS0_Devices[i].d11_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_12, + PERI_PAR_AO_SYS0_Devices[i].d12_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_13, + PERI_PAR_AO_SYS0_Devices[i].d13_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_14, + PERI_PAR_AO_SYS0_Devices[i].d14_permission); + set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_15, + PERI_PAR_AO_SYS0_Devices[i].d15_permission); + } +} + +static void set_extra_apc(void) +{ +#ifdef MTK_DEBUGSYS_LOCK + /* Block debugsys to avoid privilege escalation (user load only) */ + set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, DEVAPC_DEBUGSYS_INDEX, + DOMAIN_0, SEC_RW_NS_R); +#endif +} + +void devapc_init(void) +{ + /* Initial Permission */ + set_infra_ao_apc(); + set_peri_ao_apc(); + set_peri_ao2_apc(); + set_peri_par_ao_apc(); + + /* Extra Permission */ + set_extra_apc(); + + /* Dump Permission */ + dump_infra_ao_apc(); + dump_peri_ao_apc(); + dump_peri_ao2_apc(); + dump_peri_par_ao_apc(); + + /* Setup APUSYS Permission */ + set_apusys_apc(); + + INFO("[DEVAPC] %s done\n", __func__); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h new file mode 100644 index 0000000..9033a0f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEVAPC_H +#define DEVAPC_H + +#include +#include + +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ +void devapc_init(void); + +/****************************************************************************** + * STRUCTURE DEFINITION + ******************************************************************************/ +enum DEVAPC_PERM_TYPE { + NO_PROTECTION = 0, + SEC_RW_ONLY, + SEC_RW_NS_R, + FORBIDDEN, + PERM_NUM, +}; + +enum DOMAIN_ID { + DOMAIN_0 = 0, + DOMAIN_1, + DOMAIN_2, + DOMAIN_3, + DOMAIN_4, + DOMAIN_5, + DOMAIN_6, + DOMAIN_7, + DOMAIN_8, + DOMAIN_9, + DOMAIN_10, + DOMAIN_11, + DOMAIN_12, + DOMAIN_13, + DOMAIN_14, + DOMAIN_15, +}; + +/* Slave Type */ +enum DEVAPC_SLAVE_TYPE_SIMPLE { + SLAVE_TYPE_INFRA = 0, + SLAVE_TYPE_PERI, + SLAVE_TYPE_PERI2, + SLAVE_TYPE_PERI_PAR, +}; + +enum DEVAPC_SYS_INDEX { + DEVAPC_SYS0 = 0, + DEVAPC_SYS1, + DEVAPC_SYS2, +}; + +enum DEVAPC_SLAVE_TYPE { + SLAVE_TYPE_INFRA_AO_SYS0 = 0, + SLAVE_TYPE_INFRA_AO_SYS1, + SLAVE_TYPE_INFRA_AO_SYS2, + SLAVE_TYPE_PERI_AO_SYS0, + SLAVE_TYPE_PERI_AO_SYS1, + SLAVE_TYPE_PERI_AO_SYS2, + SLAVE_TYPE_PERI_AO2_SYS0, + SLAVE_TYPE_PERI_PAR_AO_SYS0, +}; + +/* Slave Num */ +enum DEVAPC_SLAVE_NUM { + SLAVE_NUM_INFRA_AO_SYS0 = 23, + SLAVE_NUM_INFRA_AO_SYS1 = 256, + SLAVE_NUM_INFRA_AO_SYS2 = 70, + SLAVE_NUM_PERI_AO_SYS0 = 105, + SLAVE_NUM_PERI_AO_SYS1 = 66, + SLAVE_NUM_PERI_AO_SYS2 = 1, + SLAVE_NUM_PERI_AO2_SYS0 = 115, + SLAVE_NUM_PERI_PAR_AO_SYS0 = 27, +}; + +enum DEVAPC_SYS_DOM_NUM { + DOM_NUM_INFRA_AO_SYS0 = 16, + DOM_NUM_INFRA_AO_SYS1 = 4, + DOM_NUM_INFRA_AO_SYS2 = 4, + DOM_NUM_PERI_AO_SYS0 = 16, + DOM_NUM_PERI_AO_SYS1 = 8, + DOM_NUM_PERI_AO_SYS2 = 4, + DOM_NUM_PERI_AO2_SYS0 = 16, + DOM_NUM_PERI_PAR_AO_SYS0 = 16, +}; + +enum DEVAPC_CFG_INDEX { + DEVAPC_DEBUGSYS_INDEX = 57, +}; + +struct APC_INFRA_PERI_DOM_16 { + unsigned char d0_permission; + unsigned char d1_permission; + unsigned char d2_permission; + unsigned char d3_permission; + unsigned char d4_permission; + unsigned char d5_permission; + unsigned char d6_permission; + unsigned char d7_permission; + unsigned char d8_permission; + unsigned char d9_permission; + unsigned char d10_permission; + unsigned char d11_permission; + unsigned char d12_permission; + unsigned char d13_permission; + unsigned char d14_permission; + unsigned char d15_permission; +}; + +struct APC_INFRA_PERI_DOM_8 { + unsigned char d0_permission; + unsigned char d1_permission; + unsigned char d2_permission; + unsigned char d3_permission; + unsigned char d4_permission; + unsigned char d5_permission; + unsigned char d6_permission; + unsigned char d7_permission; +}; + +struct APC_INFRA_PERI_DOM_4 { + unsigned char d0_permission; + unsigned char d1_permission; + unsigned char d2_permission; + unsigned char d3_permission; +}; + +#define DAPC_INFRA_AO_SYS0_ATTR(DEV_NAME, PERM_ATTR0, PERM_ATTR1, \ + PERM_ATTR2, PERM_ATTR3, PERM_ATTR4, PERM_ATTR5, \ + PERM_ATTR6, PERM_ATTR7, PERM_ATTR8, PERM_ATTR9, \ + PERM_ATTR10, PERM_ATTR11, PERM_ATTR12, PERM_ATTR13, \ + PERM_ATTR14, PERM_ATTR15) \ + {(unsigned char)PERM_ATTR0, (unsigned char)PERM_ATTR1, \ + (unsigned char)PERM_ATTR2, (unsigned char)PERM_ATTR3, \ + (unsigned char)PERM_ATTR4, (unsigned char)PERM_ATTR5, \ + (unsigned char)PERM_ATTR6, (unsigned char)PERM_ATTR7, \ + (unsigned char)PERM_ATTR8, (unsigned char)PERM_ATTR9, \ + (unsigned char)PERM_ATTR10, (unsigned char)PERM_ATTR11, \ + (unsigned char)PERM_ATTR12, (unsigned char)PERM_ATTR13, \ + (unsigned char)PERM_ATTR14, (unsigned char)PERM_ATTR15} + +#define DAPC_INFRA_AO_SYS1_ATTR(DEV_NAME, PERM_ATTR0, PERM_ATTR1, \ + PERM_ATTR2, PERM_ATTR3) \ + {(unsigned char)PERM_ATTR0, (unsigned char)PERM_ATTR1, \ + (unsigned char)PERM_ATTR2, (unsigned char)PERM_ATTR3} + +#define DAPC_PERI_AO_SYS1_ATTR(DEV_NAME, PERM_ATTR0, PERM_ATTR1, \ + PERM_ATTR2, PERM_ATTR3, PERM_ATTR4, PERM_ATTR5, \ + PERM_ATTR6, PERM_ATTR7) \ + {(unsigned char)PERM_ATTR0, (unsigned char)PERM_ATTR1, \ + (unsigned char)PERM_ATTR2, (unsigned char)PERM_ATTR3, \ + (unsigned char)PERM_ATTR4, (unsigned char)PERM_ATTR5, \ + (unsigned char)PERM_ATTR6, (unsigned char)PERM_ATTR7} + +#define DAPC_INFRA_AO_SYS2_ATTR(...) DAPC_INFRA_AO_SYS1_ATTR(__VA_ARGS__) +#define DAPC_PERI_AO_SYS0_ATTR(...) DAPC_INFRA_AO_SYS0_ATTR(__VA_ARGS__) +#define DAPC_PERI_AO_SYS2_ATTR(...) DAPC_INFRA_AO_SYS1_ATTR(__VA_ARGS__) +#define DAPC_PERI_AO2_SYS0_ATTR(...) DAPC_INFRA_AO_SYS0_ATTR(__VA_ARGS__) +#define DAPC_PERI_PAR_AO_SYS0_ATTR(...) DAPC_INFRA_AO_SYS0_ATTR(__VA_ARGS__) + +/****************************************************************************** + * UTILITY DEFINITION + ******************************************************************************/ +#define devapc_writel(VAL, REG) mmio_write_32((uintptr_t)REG, VAL) +#define devapc_readl(REG) mmio_read_32((uintptr_t)REG) + +/******************************************************************************/ +/* Device APC AO for INFRA AO */ +#define DEVAPC_INFRA_AO_SYS0_D0_APC_0 (DEVAPC_INFRA_AO_BASE + 0x0000) +#define DEVAPC_INFRA_AO_SYS1_D0_APC_0 (DEVAPC_INFRA_AO_BASE + 0x1000) +#define DEVAPC_INFRA_AO_SYS2_D0_APC_0 (DEVAPC_INFRA_AO_BASE + 0x2000) + +#define DEVAPC_INFRA_AO_MAS_SEC_0 (DEVAPC_INFRA_AO_BASE + 0x0A00) + +/******************************************************************************/ +/* Device APC AO for PERI AO */ +#define DEVAPC_PERI_AO_SYS0_D0_APC_0 (DEVAPC_PERI_AO_BASE + 0x0000) +#define DEVAPC_PERI_AO_SYS1_D0_APC_0 (DEVAPC_PERI_AO_BASE + 0x1000) +#define DEVAPC_PERI_AO_SYS2_D0_APC_0 (DEVAPC_PERI_AO_BASE + 0x2000) + +#define DEVAPC_PERI_AO_MAS_SEC_0 (DEVAPC_PERI_AO_BASE + 0x0A00) + +/******************************************************************************/ +/* Device APC AO for PERI AO2 */ +#define DEVAPC_PERI_AO2_SYS0_D0_APC_0 (DEVAPC_PERI_AO2_BASE + 0x0000) + +/******************************************************************************/ +/* Device APC AO for PERI PAR AO */ +#define DEVAPC_PERI_PAR_AO_SYS0_D0_APC_0 (DEVAPC_PERI_PAR_AO_BASE + 0x0000) + +#define DEVAPC_PERI_PAR_AO_MAS_SEC_0 (DEVAPC_PERI_PAR_AO_BASE + 0x0A00) + +/******************************************************************************/ + + +/****************************************************************************** + * Variable DEFINITION + ******************************************************************************/ +#define MOD_NO_IN_1_DEVAPC 16 + +#endif /* DEVAPC_H */ + diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c new file mode 100644 index 0000000..69c395e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +static bool dfd_enabled; +static uint64_t dfd_base_addr; +static uint64_t dfd_chain_length; +static uint64_t dfd_cache_dump; + +static void dfd_setup(uint64_t base_addr, uint64_t chain_length, + uint64_t cache_dump) +{ + /* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */ + /* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */ + sync_writel(DFD_INTERNAL_CTL, 0x5); + + /* bit[13]: xreset_b_update_disable */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13); + + /* + * bit[10:3]: DFD trigger selection mask + * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger) + * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger) + * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger) + * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger) + * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger) + */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 3); + + /* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19); + + /* + * bit[0]: rg_rw_dfd_auto_power_on = 1 + * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us) + * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us) + */ + mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB); + + /* longest scan chain length */ + mmio_write_32(DFD_CHAIN_LENGTH0, chain_length); + + /* bit[1:0]: rg_rw_dfd_shift_clock_ratio */ + mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0); + + /* rg_dfd_test_so_over_64 */ + mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1); + + /* DFD3.0 */ + mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_DIS_VAL); + mmio_write_32(DFD_TEST_SI_1, DFD_TEST_SI_1_VAL); + mmio_write_32(DFD_TEST_SI_2, DFD_TEST_SI_2_VAL); + mmio_write_32(DFD_TEST_SI_3, DFD_TEST_SI_3_VAL); + + /* for iLDO feature */ + sync_writel(DFD_POWER_CTL, 0xF9); + + /* set base address */ + mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24); + + /* + * disable sleep protect of DFD + * 10001220[8]: protect_en_reg[8] + * 10001a3c[2]: infra_mcu_pwr_ctl_mask[2] + */ + mmio_clrbits_32(DFD_O_PROTECT_EN_REG, 1 << 8); + mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 1 << 2); + + /* clean DFD trigger status */ + sync_writel(DFD_CLEAN_STATUS, 0x1); + sync_writel(DFD_CLEAN_STATUS, 0x0); + + /* DFD-3.0 */ + sync_writel(DFD_V30_CTL, 0x1); + + /* setup global variables for suspend and resume */ + dfd_enabled = true; + dfd_base_addr = base_addr; + dfd_chain_length = chain_length; + dfd_cache_dump = cache_dump; + + if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) { + /* DFD3.5 */ + mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_EN_VAL); + sync_writel(DFD_V35_ENALBE, 0x1); + sync_writel(DFD_V35_TAP_NUMBER, 0xB); + sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL); + sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL); + + if (cache_dump & DFD_PARITY_ERR_TRIGGER) { + sync_writel(DFD_HW_TRIGGER_MASK, 0xC); + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4); + } + } + dsbsy(); +} + +void dfd_resume(void) +{ + if (dfd_enabled == true) { + dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump); + } +} + +uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3) +{ + uint64_t ret = 0L; + + switch (arg0) { + case PLAT_MTK_DFD_SETUP_MAGIC: + dfd_setup(arg1, arg2, arg3); + break; + case PLAT_MTK_DFD_READ_MAGIC: + /* only allow to access DFD register base + 0x200 */ + if (arg1 <= 0x200) { + ret = mmio_read_32(MISC1_CFG_BASE + arg1); + } + break; + case PLAT_MTK_DFD_WRITE_MAGIC: + /* only allow to access DFD register base + 0x200 */ + if (arg1 <= 0x200) { + sync_writel(MISC1_CFG_BASE + arg1, arg2); + } + break; + default: + ret = MTK_SIP_E_INVALID_PARAM; + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h new file mode 100644 index 0000000..7f0f4b5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DFD_H +#define PLAT_DFD_H + +#include +#include +#include + +#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); \ + dsbsy(); \ + } while (0) + +#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150) +#define PLAT_MTK_DFD_READ_MAGIC (0x99716151) +#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152) + +#define MCU_BIU_BASE (MCUCFG_BASE) +#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xE040) +#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00) +#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08) +#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C) +#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10) +#define DFD_CHAIN_LENGTH1 (MISC1_CFG_BASE + 0x1C) +#define DFD_CHAIN_LENGTH2 (MISC1_CFG_BASE + 0x20) +#define DFD_CHAIN_LENGTH3 (MISC1_CFG_BASE + 0x24) +#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28) +#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30) +#define DFD_INTERNAL_TEST_SO_OVER_64 (MISC1_CFG_BASE + 0x34) +#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48) +#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C) +#define DFD_POWER_CTL (MISC1_CFG_BASE + 0x50) +#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58) +#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C) +#define DFD_CLEAN_STATUS (MISC1_CFG_BASE + 0x60) +#define DFD_TEST_SI_2 (MISC1_CFG_BASE + 0x1D8) +#define DFD_TEST_SI_3 (MISC1_CFG_BASE + 0x1DC) +#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC) + +#define DFD_V35_ENALBE (MCU_BIU_BASE + 0xE0A8) +#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xE0AC) +#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xE0B0) +#define DFD_V35_CTL (MCU_BIU_BASE + 0xE0B4) +#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xE0C0) +#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xE0C4) + +#define DFD_O_PROTECT_EN_REG (0x10001220) +#define DFD_O_INTRF_MCU_PWR_CTL_MASK (0x10001A3C) +#define DFD_O_SET_BASEADDR_REG (0x10043034) + +#define DFD_CACHE_DUMP_ENABLE 1U +#define DFD_PARITY_ERR_TRIGGER 2U + +#define DFD_TEST_SI_0_CACHE_DIS_VAL (0x1E000202) +#define DFD_TEST_SI_0_CACHE_EN_VAL (0x1E000002) +#define DFD_TEST_SI_1_VAL (0x20408100) +#define DFD_TEST_SI_2_VAL (0x10101000) +#define DFD_TEST_SI_3_VAL (0x00000010) +#define DFD_V35_TAP_EN_VAL (0x43FF) +#define DFD_V35_SEQ0_0_VAL (0x63668820) + +void dfd_resume(void); +uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3); + +#endif /* PLAT_DFD_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c new file mode 100644 index 0000000..26bed29 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* + * emi_mpu_set_region_protection: protect a region. + * @start: start address of the region + * @end: end address of the region + * @access_permission: EMI MPU access permission + * Return 0 for success, otherwise negative status code. + */ +static int _emi_mpu_set_protection( + unsigned long start, unsigned long end, + unsigned int apc) +{ + unsigned int dgroup; + unsigned int region; + + region = (start >> 24) & 0xFF; + start &= 0x00FFFFFF; + dgroup = (end >> 24) & 0xFF; + end &= 0x00FFFFFF; + + if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) { + WARN("Region:%u or dgroup:%u is wrong!\n", region, dgroup); + return -1; + } + + apc &= 0x80FFFFFF; + + if ((start >= DRAM_OFFSET) && (end >= start)) { + start -= DRAM_OFFSET; + end -= DRAM_OFFSET; + } else { + WARN("start:0x%lx or end:0x%lx address is wrong!\n", + start, end); + return -2; + } + + mmio_write_32(EMI_MPU_SA(region), start); + mmio_write_32(EMI_MPU_EA(region), end); + mmio_write_32(EMI_MPU_APC(region, dgroup), apc); + + return 0; +} + +void dump_emi_mpu_regions(void) +{ + unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea; + + int region, i; + + /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */ + for (region = 0; region < 8; ++region) { + for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) + apc[i] = mmio_read_32(EMI_MPU_APC(region, i)); + sa = mmio_read_32(EMI_MPU_SA(region)); + ea = mmio_read_32(EMI_MPU_EA(region)); + + WARN("region %d:\n", region); + WARN("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n", + sa, ea, apc[0], apc[1]); + } +} + +int emi_mpu_set_protection(struct emi_region_info_t *region_info) +{ + unsigned long start, end; + int i; + + if (region_info->region >= EMI_MPU_REGION_NUM) + return -1; + + start = (unsigned long)(region_info->start >> EMI_MPU_ALIGN_BITS) | + (region_info->region << 24); + + for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) { + end = (unsigned long)(region_info->end >> EMI_MPU_ALIGN_BITS) | + (i << 24); + _emi_mpu_set_protection(start, end, region_info->apc[i]); + } + + return 0; +} + +void emi_mpu_init(void) +{ + struct emi_region_info_t region_info; + + /* reserve region 0 for future use */ + + /* PCI-e protect address(64MB) */ + region_info.start = 0xC0000000ULL; + region_info.end = 0xC3FF0000ULL; + region_info.region = 1; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, NO_PROT, NO_PROT); + emi_mpu_set_protection(®ion_info); + + /* SCP protect address */ + region_info.start = 0x50000000ULL; + region_info.end = 0x513F0000ULL; + region_info.region = 2; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + NO_PROT, FORBIDDEN, FORBIDDEN, NO_PROT); + emi_mpu_set_protection(®ion_info); + + /* DSP protect address */ + region_info.start = 0x40000000ULL; /* dram base addr */ + region_info.end = 0x1FFFF0000ULL; + region_info.region = 3; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROT); + emi_mpu_set_protection(®ion_info); + + /* Forbidden All */ + region_info.start = 0x40000000ULL; /* dram base addr */ + region_info.end = 0x1FFFF0000ULL; + region_info.region = 4; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROT); + emi_mpu_set_protection(®ion_info); + + dump_emi_mpu_regions(); +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..0b15431 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMI_MPU_H +#define EMI_MPU_H + +#include + +#define EMI_MPUP (EMI_BASE + 0x01D8) +#define EMI_MPUQ (EMI_BASE + 0x01E0) +#define EMI_MPUR (EMI_BASE + 0x01E8) +#define EMI_MPUS (EMI_BASE + 0x01F0) +#define EMI_MPUT (EMI_BASE + 0x01F8) +#define EMI_MPUY (EMI_BASE + 0x0220) +#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x0000) +#define EMI_MPUD0_ST (EMI_BASE + 0x0160) +#define EMI_MPUD1_ST (EMI_BASE + 0x0164) +#define EMI_MPUD2_ST (EMI_BASE + 0x0168) +#define EMI_MPUD3_ST (EMI_BASE + 0x016C) +#define EMI_MPUD0_ST2 (EMI_BASE + 0x0200) +#define EMI_MPUD1_ST2 (EMI_BASE + 0x0204) +#define EMI_MPUD2_ST2 (EMI_BASE + 0x0208) +#define EMI_MPUD3_ST2 (EMI_BASE + 0x020C) + +#define EMI_PHY_OFFSET (0x40000000UL) + +#define NO_PROT (0) +#define SEC_RW (1) +#define SEC_RW_NSEC_R (2) +#define SEC_RW_NSEC_W (3) +#define SEC_R_NSEC_R (4) +#define FORBIDDEN (5) +#define SEC_R_NSEC_RW (6) + +#define SECURE_OS_MPU_REGION_ID (0) +#define ATF_MPU_REGION_ID (1) + +#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100) +#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200) +#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region) * 4) +#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region) * 4) + +#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300) +#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region) * 4 + \ + (dgroup) * 0x100) + +#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800) +#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + domain * 4) +#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900) +#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + domain * 4) + +#define EMI_MPU_DOMAIN_NUM 16 +#define EMI_MPU_REGION_NUM 32 +#define EMI_MPU_ALIGN_BITS 16 +#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS) + +#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8) + +#if (EMI_MPU_DGROUP_NUM == 1) +#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \ +do { \ + apc_ary[0] = 0; \ + apc_ary[0] = \ + (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) \ + | (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) \ + | (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) \ + | (((unsigned int) d1) << 3) | ((unsigned int) d0) \ + | (((unsigned int) lock) << 31); \ +} while (0) +#elif (EMI_MPU_DGROUP_NUM == 2) +#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \ + d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \ +do { \ + apc_ary[1] = \ + (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) \ + | (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) \ + | (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) \ + | (((unsigned int) d9) << 3) | ((unsigned int) d8); \ + apc_ary[0] = \ + (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) \ + | (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) \ + | (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) \ + | (((unsigned int) d1) << 3) | ((unsigned int) d0) \ + | (((unsigned int) lock) << 31); \ +} while (0) +#endif + +struct emi_region_info_t { + unsigned long long start; + unsigned long long end; + unsigned int region; + unsigned long apc[EMI_MPU_DGROUP_NUM]; +}; + +void emi_mpu_init(void); +int emi_mpu_set_protection(struct emi_region_info_t *region_info); +void dump_emi_mpu_regions(void); + +#endif /* __EMI_MPU_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c new file mode 100644 index 0000000..c78332d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uintptr_t mt_gpio_find_reg_addr(uint32_t pin) +{ + uintptr_t reg_addr = 0U; + struct mt_pin_info gpio_info; + + assert(pin < MAX_GPIO_PIN); + + gpio_info = mt_pin_infos[pin]; + + switch (gpio_info.base & 0x0f) { + case 0: + reg_addr = IOCFG_RM_BASE; + break; + case 1: + reg_addr = IOCFG_BM_BASE; + break; + case 2: + reg_addr = IOCFG_BL_BASE; + break; + case 3: + reg_addr = IOCFG_BR_BASE; + break; + case 4: + reg_addr = IOCFG_LM_BASE; + break; + case 5: + reg_addr = IOCFG_LB_BASE; + break; + case 6: + reg_addr = IOCFG_RT_BASE; + break; + case 7: + reg_addr = IOCFG_LT_BASE; + break; + case 8: + reg_addr = IOCFG_TL_BASE; + break; + default: + break; + } + + return reg_addr; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h new file mode 100644 index 0000000..d3aa24d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_H +#define MT_GPIO_H + +#include + +/* Enumeration for GPIO pin */ +typedef enum GPIO_PIN { + GPIO_UNSUPPORTED = -1, + + GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, + GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15, + GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, + GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31, + GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39, + GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47, + GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55, + GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63, + GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71, + GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79, + GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87, + GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95, + GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103, + GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111, + GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119, + GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127, + GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135, + GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143, + GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151, + GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159, + GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167, + GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175, + GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182, GPIO183, + GPIO184, GPIO185, GPIO186, GPIO187, GPIO188, GPIO189, GPIO190, GPIO191, + GPIO192, GPIO193, GPIO194, GPIO195, GPIO196, GPIO197, GPIO198, GPIO199, + GPIO200, GPIO201, GPIO202, GPIO203, GPIO204, GPIO205, GPIO206, GPIO207, + GPIO208, GPIO209, GPIO210, GPIO211, GPIO212, GPIO213, GPIO214, GPIO215, + GPIO216, GPIO217, GPIO218, GPIO219, + MT_GPIO_BASE_MAX +} GPIO_PIN; + +static const struct mt_pin_info mt_pin_infos[] = { + PIN(0, 0, 9, 0x23, 0xb0), + PIN(1, 0, 10, 0x23, 0xb0), + PIN(2, 0, 11, 0x23, 0xb0), + PIN(3, 0, 12, 0x23, 0xb0), + PIN(4, 0, 13, 0x23, 0xb0), + PIN(5, 0, 14, 0x23, 0xb0), + PIN(6, 0, 15, 0x23, 0xb0), + PIN(7, 0, 16, 0x23, 0xb0), + PIN(8, 0, 17, 0x23, 0xb0), + PIN(9, 0, 18, 0x23, 0xb0), + PIN(10, 1, 0, 0x15, 0x20), + PIN(11, 1, 1, 0x15, 0x20), + PIN(12, 1, 2, 0x15, 0x20), + PIN(13, 1, 3, 0x15, 0x20), + PIN(14, 1, 4, 0x15, 0x20), + PIN(15, 1, 5, 0x15, 0x20), + PIN(16, 0, 2, 0x17, 0x50), + PIN(17, 0, 3, 0x17, 0x50), + PIN(18, 0, 21, 0x36, 0xa0), + PIN(19, 0, 22, 0x36, 0xa0), + PIN(20, 0, 23, 0x36, 0xa0), + PIN(21, 0, 24, 0x36, 0xa0), + PIN(22, 0, 3, 0x21, 0x90), + PIN(23, 0, 4, 0x21, 0x90), + PIN(24, 0, 5, 0x21, 0x90), + PIN(25, 0, 6, 0x21, 0x90), + PIN(26, 0, 5, 0x22, 0x80), + PIN(27, 0, 6, 0x22, 0x80), + PIN(28, 0, 7, 0x22, 0x80), + PIN(29, 0, 8, 0x22, 0x80), + PIN(30, 0, 9, 0x22, 0x80), + PIN(31, 0, 27, 0x22, 0x70), + PIN(32, 0, 24, 0x22, 0x70), + PIN(33, 0, 26, 0x22, 0x70), + PIN(34, 0, 23, 0x22, 0x70), + PIN(35, 0, 25, 0x22, 0x70), + PIN(36, 0, 20, 0x21, 0x90), + PIN(37, 0, 21, 0x21, 0x90), + PIN(38, 0, 22, 0x21, 0x90), + PIN(39, 0, 23, 0x21, 0x90), + PIN(40, 0, 0, 0x17, 0x50), + PIN(41, 0, 1, 0x17, 0x50), + PIN(42, 0, 4, 0x17, 0x50), + PIN(43, 0, 25, 0x36, 0xa0), + PIN(44, 0, 26, 0x36, 0xa0), + PIN(45, 1, 9, 0x20, 0x60), + PIN(46, 1, 11, 0x20, 0x60), + PIN(47, 1, 10, 0x20, 0x60), + PIN(48, 1, 7, 0x20, 0x60), + PIN(49, 1, 8, 0x20, 0x60), + PIN(50, 1, 6, 0x20, 0x60), + PIN(51, 1, 0, 0x20, 0x60), + PIN(52, 1, 1, 0x20, 0x60), + PIN(53, 1, 5, 0x20, 0x60), + PIN(54, 1, 2, 0x20, 0x60), + PIN(55, 1, 4, 0x20, 0x60), + PIN(56, 1, 3, 0x20, 0x60), + PIN(57, 0, 1, 0x22, 0x80), + PIN(58, 0, 2, 0x22, 0x80), + PIN(59, 0, 3, 0x22, 0x80), + PIN(60, 0, 4, 0x22, 0x80), + PIN(61, 0, 28, 0x22, 0x70), + PIN(62, 0, 22, 0x22, 0x70), + PIN(63, 0, 0, 0x22, 0x70), + PIN(64, 0, 1, 0x22, 0x70), + PIN(65, 0, 12, 0x22, 0x70), + PIN(66, 0, 15, 0x22, 0x70), + PIN(67, 0, 16, 0x22, 0x70), + PIN(68, 0, 17, 0x22, 0x70), + PIN(69, 0, 18, 0x22, 0x70), + PIN(70, 0, 19, 0x22, 0x70), + PIN(71, 0, 20, 0x22, 0x70), + PIN(72, 0, 21, 0x22, 0x70), + PIN(73, 0, 2, 0x22, 0x70), + PIN(74, 0, 3, 0x22, 0x70), + PIN(75, 0, 4, 0x22, 0x70), + PIN(76, 0, 5, 0x22, 0x70), + PIN(77, 0, 6, 0x22, 0x70), + PIN(78, 0, 7, 0x22, 0x70), + PIN(79, 0, 8, 0x22, 0x70), + PIN(80, 0, 9, 0x22, 0x70), + PIN(81, 0, 10, 0x22, 0x70), + PIN(82, 0, 11, 0x22, 0x70), + PIN(83, 0, 13, 0x22, 0x70), + PIN(84, 0, 14, 0x22, 0x70), + PIN(85, 0, 31, 0x22, 0x70), + PIN(86, 0, 0, 0x22, 0x80), + PIN(87, 0, 29, 0x22, 0x70), + PIN(88, 0, 30, 0x22, 0x70), + PIN(89, 0, 24, 0x21, 0x90), + PIN(90, 0, 25, 0x21, 0x90), + PIN(91, 0, 0, 0x21, 0x90), + PIN(92, 0, 2, 0x21, 0xa0), + PIN(93, 0, 4, 0x21, 0xa0), + PIN(94, 0, 3, 0x21, 0xa0), + PIN(95, 0, 5, 0x21, 0xa0), + PIN(96, 0, 31, 0x21, 0x90), + PIN(97, 0, 26, 0x21, 0x90), + PIN(98, 0, 0, 0x21, 0xa0), + PIN(99, 0, 27, 0x21, 0x90), + PIN(100, 0, 28, 0x21, 0x90), + PIN(101, 0, 29, 0x21, 0x90), + PIN(102, 0, 30, 0x21, 0x90), + PIN(103, 0, 18, 0x21, 0x90), + PIN(104, 0, 17, 0x21, 0x90), + PIN(105, 0, 19, 0x21, 0x90), + PIN(106, 0, 16, 0x21, 0x90), + PIN(107, 0, 1, 0x21, 0x90), + PIN(108, 0, 2, 0x21, 0x90), + PIN(109, 0, 10, 0x21, 0x90), + PIN(110, 0, 7, 0x21, 0x90), + PIN(111, 0, 9, 0x21, 0x90), + PIN(112, 0, 11, 0x21, 0x90), + PIN(113, 0, 8, 0x21, 0x90), + PIN(114, 0, 14, 0x21, 0x90), + PIN(115, 0, 13, 0x21, 0x90), + PIN(116, 0, 15, 0x21, 0x90), + PIN(117, 0, 12, 0x21, 0x90), + PIN(118, 0, 23, 0x23, 0xb0), + PIN(119, 0, 29, 0x23, 0xb0), + PIN(120, 0, 28, 0x23, 0xb0), + PIN(121, 0, 2, 0x23, 0xc0), + PIN(122, 0, 27, 0x23, 0xb0), + PIN(123, 0, 1, 0x23, 0xc0), + PIN(124, 0, 26, 0x23, 0xb0), + PIN(125, 0, 0, 0x23, 0xc0), + PIN(126, 0, 19, 0x23, 0xb0), + PIN(127, 0, 20, 0x23, 0xb0), + PIN(128, 0, 21, 0x23, 0xb0), + PIN(129, 0, 22, 0x23, 0xb0), + PIN(130, 0, 6, 0x23, 0xb0), + PIN(131, 0, 7, 0x23, 0xb0), + PIN(132, 0, 8, 0x23, 0xb0), + PIN(133, 0, 3, 0x23, 0xb0), + PIN(134, 0, 4, 0x23, 0xb0), + PIN(135, 0, 5, 0x23, 0xb0), + PIN(136, 0, 0, 0x23, 0xb0), + PIN(137, 0, 1, 0x23, 0xb0), + PIN(138, 0, 2, 0x23, 0xb0), + PIN(139, 0, 25, 0x23, 0xb0), + PIN(140, 0, 31, 0x23, 0xb0), + PIN(141, 0, 24, 0x23, 0xb0), + PIN(142, 0, 30, 0x23, 0xb0), + PIN(143, 0, 6, 0x20, 0x70), + PIN(144, 0, 7, 0x20, 0x70), + PIN(145, 0, 8, 0x20, 0x70), + PIN(146, 0, 3, 0x20, 0x70), + PIN(147, 0, 4, 0x20, 0x70), + PIN(148, 0, 5, 0x20, 0x70), + PIN(149, 0, 0, 0x20, 0x70), + PIN(150, 0, 1, 0x20, 0x70), + PIN(151, 0, 2, 0x20, 0x70), + PIN(152, 1, 3, 0x36, 0x90), + PIN(153, 1, 2, 0x36, 0x90), + PIN(154, 1, 0, 0x36, 0x906), + PIN(155, 1, 1, 0x36, 0x90), + PIN(156, 0, 29, 0x36, 0xa0), + PIN(157, 0, 30, 0x36, 0xa0), + PIN(158, 0, 31, 0x36, 0xa0), + PIN(159, 0, 0, 0x36, 0xb0), + PIN(160, 0, 27, 0x36, 0xa04), + PIN(161, 0, 28, 0x36, 0xa0), + PIN(162, 0, 0, 0x36, 0xa0), + PIN(163, 0, 1, 0x36, 0xa0), + PIN(164, 0, 2, 0x36, 0xa0), + PIN(165, 0, 3, 0x36, 0xa0), + PIN(166, 0, 4, 0x36, 0xa0), + PIN(167, 0, 5, 0x36, 0xa0), + PIN(168, 0, 6, 0x36, 0xa0), + PIN(169, 0, 7, 0x36, 0xa0), + PIN(170, 0, 8, 0x36, 0xa0), + PIN(171, 0, 9, 0x36, 0xa0), + PIN(172, 0, 13, 0x36, 0xa0), + PIN(173, 0, 14, 0x36, 0xa0), + PIN(174, 0, 12, 0x36, 0xa0), + PIN(175, 0, 15, 0x36, 0xa0), + PIN(176, 0, 10, 0x36, 0xa0), + PIN(177, 0, 11, 0x36, 0xa0), + PIN(178, 0, 16, 0x36, 0xa0), + PIN(179, 0, 17, 0x36, 0xa0), + PIN(180, 0, 18, 0x36, 0xa0), + PIN(181, 0, 19, 0x36, 0xa0), + PIN(182, 0, 20, 0x36, 0xa0), + PIN(183, 1, 1, 0x18, 0x30), + PIN(184, 1, 2, 0x18, 0x30), + PIN(185, 1, 4, 0x18, 0x30), + PIN(186, 1, 6, 0x18, 0x30), + PIN(187, 1, 8, 0x18, 0x30), + PIN(188, 1, 3, 0x18, 0x30), + PIN(189, 1, 7, 0x18, 0x30), + PIN(190, 1, 9, 0x18, 0x30), + PIN(191, 1, 10, 0x18, 0x30), + PIN(192, 1, 0, 0x18, 0x30), + PIN(193, 1, 5, 0x18, 0x30), + PIN(194, 1, 11, 0x18, 0x30), + PIN(195, 0, 16, 0x14, 0x50), + PIN(196, 0, 6, 0x14, 0x50), + PIN(197, 0, 8, 0x14, 0x50), + PIN(198, 0, 7, 0x14, 0x50), + PIN(199, 0, 3, 0x14, 0x50), + PIN(200, 0, 6, 0x17, 0x50), + PIN(201, 0, 8, 0x17, 0x50), + PIN(202, 0, 15, 0x14, 0x50), + PIN(203, 0, 17, 0x14, 0x50), + PIN(204, 0, 5, 0x17, 0x50), + PIN(205, 0, 7, 0x17, 0x50), + PIN(206, 0, 18, 0x14, 0x50), + PIN(207, 0, 19, 0x14, 0x50), + PIN(208, 0, 20, 0x14, 0x50), + PIN(209, 0, 12, 0x14, 0x50), + PIN(210, 0, 11, 0x14, 0x50), + PIN(211, 0, 13, 0x14, 0x50), + PIN(212, 0, 10, 0x14, 0x50), + PIN(213, 0, 14, 0x14, 0x50), + PIN(214, 0, 0, 0x14, 0x50), + PIN(215, 0, 9, 0x14, 0x50), + PIN(216, 0, 4, 0x14, 0x50), + PIN(217, 0, 5, 0x14, 0x50), + PIN(218, 0, 1, 0x14, 0x50), + PIN(219, 0, 2, 0x14, 0x50), +}; +#endif /* MT_GPIO_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c new file mode 100644 index 0000000..b483c36 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1); + +static int plat_mt_lp_cpu_rc; + +static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state) +{ + mtk_cpc_core_on_hint_clr(cpu); + + if (IS_SYSTEM_SUSPEND_STATE(state)) { + mtk_cpc_time_sync(); + } + + return 0; +} + +static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + /* clear DBGPRCR.CORENPDRQ to allow CPU power down */ + write_dbgprcr_el1(0ULL); + + return 0; +} + +static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { + return -1; + } + + mtk_cpc_mcusys_off_reflect(); + + return 0; +} + +static int pwr_mcusys_pwron_finished(unsigned int cpu, + const psci_power_state_t *state) +{ + int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS]; + + if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { + return -1; + } + + mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id); + mt_lp_irqremain_release(); + + return 0; +} + +static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS]; + + if (!IS_MCUSYS_OFF_STATE(state)) { + goto mt_pwr_mcusysoff_break; + } + + if (mcdi_try_init() != 0) { + goto mt_pwr_mcusysoff_break; + } + + if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) { + goto mt_pwr_mcusysoff_break; + } + + plat_mt_lp_cpu_rc = + mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL); + + if (plat_mt_lp_cpu_rc < 0) { + goto mt_pwr_mcusysoff_reflect; + } + + mt_lp_irqremain_aquire(); + + return 0; + +mt_pwr_mcusysoff_reflect: + mtk_cpc_mcusys_off_reflect(); + +mt_pwr_mcusysoff_break: + plat_mt_lp_cpu_rc = -1; + + return -1; +} + +static const struct mt_lpm_tz plat_pm = { + .pwr_prompt = pwr_state_prompt, + .pwr_reflect = pwr_state_reflect, + .pwr_cpu_on = pwr_cpu_pwron, + .pwr_cpu_dwn = pwr_cpu_pwrdwn, + .pwr_cluster_on = pwr_cluster_pwron, + .pwr_cluster_dwn = pwr_cluster_pwrdwn, + .pwr_mcusys_dwn = pwr_mcusys_pwrdwn, + .pwr_mcusys_on = pwr_mcusys_pwron, + .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished +}; + +const struct mt_lpm_tz *mt_plat_cpu_pm_init(void) +{ + mtk_cpc_init(); + + if (mcdi_try_init() == 0) { + INFO("MCDI init done.\n"); + } + + mt_lp_irqremain_init(); + + return &plat_pm; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c new file mode 100644 index 0000000..f8c51a1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +struct mtk_cpc_dev { + int auto_off; + unsigned int auto_thres_tick; +}; + +static struct mtk_cpc_dev cpc; + +static int mtk_cpc_last_core_prot(uint32_t prot_req, + uint32_t resp_reg, uint32_t resp_ofs) +{ + uint32_t sta, retry; + + retry = 0U; + + while (retry++ < RETRY_CNT_MAX) { + + mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req); + + udelay(1U); + + sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK; + + if (sta == PROT_SUCCESS) { + return CPC_SUCCESS; + } else if (sta == PROT_GIVEUP) { + return CPC_ERR_FAIL; + } + } + + return CPC_ERR_TIMEOUT; +} + +int mtk_cpu_pm_mcusys_prot_aquire(void) +{ + return mtk_cpc_last_core_prot( + MCUSYS_PROT_SET, + CPC_MCUSYS_LAST_CORE_RESP, + MCUSYS_RESP_OFS); +} + +void mtk_cpu_pm_mcusys_prot_release(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR); +} + +int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster) +{ + return mtk_cpc_last_core_prot( + CPUSYS_PROT_SET, + CPC_MCUSYS_MP_LAST_CORE_RESP, + CPUSYS_RESP_OFS); +} + +void mtk_cpu_pm_cluster_prot_release(unsigned int cluster) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR); +} + +static void mtk_cpc_cluster_cnt_backup(void) +{ + uint32_t backup_cnt; + uint32_t curr_cnt; + uint32_t cnt_mask = GENMASK(14, 0); + uint32_t clr_mask = GENMASK(1, 0); + + /* Single Cluster */ + backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP); + curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER); + + /* Get off count if dormant count is 0 */ + if ((curr_cnt & cnt_mask) == 0U) { + curr_cnt = (curr_cnt >> 16) & cnt_mask; + } else { + curr_cnt = curr_cnt & cnt_mask; + } + + mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt); + mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask); +} + +static inline void mtk_cpc_mcusys_off_en(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U); +} + +static inline void mtk_cpc_mcusys_off_dis(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U); +} + +void mtk_cpc_mcusys_off_reflect(void) +{ + mtk_cpc_mcusys_off_dis(); + mtk_cpu_pm_mcusys_prot_release(); +} + +int mtk_cpc_mcusys_off_prepare(void) +{ + if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) { + return CPC_ERR_FAIL; + } + + mtk_cpc_cluster_cnt_backup(); + mtk_cpc_mcusys_off_en(); + + return CPC_SUCCESS; +} + +void mtk_cpc_core_on_hint_set(unsigned int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu)); +} + +void mtk_cpc_core_on_hint_clr(unsigned int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); +} + +static void mtk_cpc_dump_timestamp(void) +{ + uint32_t id; + + for (id = 0U; id < CPC_TRACE_ID_NUM; id++) { + mmio_write_32(CPC_MCUSYS_TRACE_SEL, id); + + memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id), + (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA, + CPC_TRACE_SIZE); + } +} + +void mtk_cpc_time_sync(void) +{ + uint64_t kt; + uint32_t systime_l, systime_h; + + kt = sched_clock(); + systime_l = mmio_read_32(CNTSYS_L_REG); + systime_h = mmio_read_32(CNTSYS_H_REG); + + /* sync kernel timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt); + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32)); + /* sync system timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l); + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h); +} + +static void mtk_cpc_config(uint32_t cfg, uint32_t data) +{ + uint32_t val; + uint32_t reg = 0U; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + reg = CPC_MCUSYS_CPC_DBG_SETTING; + val = mmio_read_32(reg); + val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN); + break; + case CPC_SMC_CONFIG_AUTO_OFF: + reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG; + val = mmio_read_32(reg); + if (data != 0U) { + val |= CPC_AUTO_OFF_EN; + cpc.auto_off = 1; + } else { + val &= ~CPC_AUTO_OFF_EN; + cpc.auto_off = 0; + } + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + reg = CPC_MCUSYS_CPC_OFF_THRES; + cpc.auto_thres_tick = us_to_ticks(data); + val = cpc.auto_thres_tick; + break; + case CPC_SMC_CONFIG_CNT_CLR: + reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR; + val = GENMASK(1, 0); /* clr_mask */ + break; + case CPC_SMC_CONFIG_TIME_SYNC: + mtk_cpc_time_sync(); + break; + default: + break; + } + + if (reg != 0U) { + mmio_write_32(reg, val); + } +} + +static uint32_t mtk_cpc_read_config(uint32_t cfg) +{ + uint32_t res = 0U; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ? + 1U : 0U; + break; + case CPC_SMC_CONFIG_AUTO_OFF: + res = cpc.auto_off; + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + res = ticks_to_us(cpc.auto_thres_tick); + break; + case CPC_SMC_CONFIG_CNT_CLR: + break; + default: + break; + } + + return res; +} + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2) +{ + uint64_t res = 0ULL; + + switch (act) { + case CPC_SMC_EVENT_DUMP_TRACE_DATA: + mtk_cpc_dump_timestamp(); + break; + case CPC_SMC_EVENT_GIC_DPG_SET: + /* isolated_status = x2; */ + break; + case CPC_SMC_EVENT_CPC_CONFIG: + mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2); + break; + case CPC_SMC_EVENT_READ_CONFIG: + res = mtk_cpc_read_config((uint32_t)arg1); + break; + default: + break; + } + + return res; +} + +void mtk_cpc_init(void) +{ + mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING, + mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) + | CPC_DBG_EN + | CPC_CALC_EN); + + cpc.auto_off = 1; + cpc.auto_thres_tick = us_to_ticks(8000); + + mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, + mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG) + | CPC_OFF_PRE_EN + | (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U)); + + mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h new file mode 100644 index 0000000..19dd6a2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_CPU_PM_CPC_H +#define MT_CPU_PM_CPC_H + +#include +#include +#include +#include + +#define NEED_CPUSYS_PROT_WORKAROUND 1 + +/* system sram registers */ +#define CPUIDLE_SRAM_REG(r) (uint32_t)(MTK_MCDI_SRAM_BASE + (r)) + +/* db dump */ +#define CPC_TRACE_SIZE U(0x20) +#define CPC_TRACE_ID_NUM U(10) +#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE) + +/* buckup off count */ +#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0) +#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4) + +/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */ +#define CPC_PWR_ON_SEQ_DIS BIT(1) +#define CPC_PWR_ON_PRIORITY BIT(2) +#define CPC_AUTO_OFF_EN BIT(5) +#define CPC_DORMANT_WAIT_EN BIT(14) +#define CPC_CTRL_EN BIT(16) +#define CPC_OFF_PRE_EN BIT(29) + +/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */ +#define CPUSYS_PROT_SET BIT(0) +#define MCUSYS_PROT_SET BIT(8) +#define CPUSYS_PROT_CLR BIT(8) +#define MCUSYS_PROT_CLR BIT(9) + +#define CPC_PROT_RESP_MASK U(0x3) +#define CPUSYS_RESP_OFS U(16) +#define MCUSYS_RESP_OFS U(30) + +#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK) +#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK) + +#define RETRY_CNT_MAX U(1000) + +#define PROT_RETRY U(0) +#define PROT_SUCCESS U(1) +#define PROT_GIVEUP U(2) + +/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */ +#define CPC_PROF_EN BIT(0) +#define CPC_DBG_EN BIT(1) +#define CPC_FREEZE BIT(2) +#define CPC_CALC_EN BIT(3) + +enum { + CPC_SUCCESS = 0, + + CPC_ERR_FAIL, + CPC_ERR_TIMEOUT, + + NF_CPC_ERR +}; + +enum { + CPC_SMC_EVENT_DUMP_TRACE_DATA, + CPC_SMC_EVENT_GIC_DPG_SET, + CPC_SMC_EVENT_CPC_CONFIG, + CPC_SMC_EVENT_READ_CONFIG, + + NF_CPC_SMC_EVENT +}; + +enum { + CPC_SMC_CONFIG_PROF, + CPC_SMC_CONFIG_AUTO_OFF, + CPC_SMC_CONFIG_AUTO_OFF_THRES, + CPC_SMC_CONFIG_CNT_CLR, + CPC_SMC_CONFIG_TIME_SYNC, + + NF_CPC_SMC_CONFIG +}; + +#define us_to_ticks(us) ((us) * 13) +#define ticks_to_us(tick) ((tick) / 13) + +int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster); +void mtk_cpu_pm_cluster_prot_release(unsigned int cluster); + +void mtk_cpc_mcusys_off_reflect(void); +int mtk_cpc_mcusys_off_prepare(void); + +void mtk_cpc_core_on_hint_set(unsigned int cpu); +void mtk_cpc_core_on_hint_clr(unsigned int cpu); +void mtk_cpc_time_sync(void); + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2); +void mtk_cpc_init(void); + +#endif /* MT_CPU_PM_CPC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c new file mode 100644 index 0000000..e74d3e7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define EDMA0_IRQ_ID U(448) +#define MDLA_IRQ_ID U(446) +#define MALI4_IRQ_ID U(399) +#define MALI3_IRQ_ID U(398) +#define MALI2_IRQ_ID U(397) +#define MALI1_IRQ_ID U(396) +#define MALI0_IRQ_ID U(395) +#define VPU_CORE1_IRQ_ID U(453) +#define VPU_CORE0_IRQ_ID U(452) +#define MD_WDT_IRQ_ID U(110) +#define KEYPAD_IRQ_ID U(106) + +#define MD_WDT_WAKESRC 0x2000000 +#define KEYPAD_WAKESRC 0x4 + +static struct mt_irqremain remain_irqs; + +int mt_lp_irqremain_submit(void) +{ + if (remain_irqs.count == 0) { + return -1; + } + + set_wakeup_sources(remain_irqs.irqs, remain_irqs.count); + mt_lp_rm_do_update(-1, PLAT_RC_UPDATE_REMAIN_IRQS, &remain_irqs); + + return 0; +} + +int mt_lp_irqremain_aquire(void) +{ + if (remain_irqs.count == 0) { + return -1; + } + + mt_cirq_sw_reset(); + mt_cirq_clone_gic(); + mt_cirq_enable(); + + return 0; +} + +int mt_lp_irqremain_release(void) +{ + if (remain_irqs.count == 0) { + return -1; + } + + mt_cirq_flush(); + mt_cirq_disable(); + + return 0; +} + +void mt_lp_irqremain_init(void) +{ + uint32_t idx; + + remain_irqs.count = 0; + + /* level edma0 */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = EDMA0_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* level mdla */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = MDLA_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* level mali4 */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = MALI4_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* level mali3 */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = MALI3_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* level mali2 */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = MALI2_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* level mali1 */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = MALI1_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* level mali0 */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = MALI0_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* level vpu core1 */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = VPU_CORE1_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* level vpu core0 */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = VPU_CORE0_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = 0; + remain_irqs.count++; + + /* edge mdwdt */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = MD_WDT_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = MD_WDT_WAKESRC; + remain_irqs.count++; + + /* edge keypad */ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = KEYPAD_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = KEYPAD_WAKESRC; + remain_irqs.count++; + + mt_lp_irqremain_submit(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h new file mode 100644 index 0000000..cbed967 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_LP_IRQREMAIN_H +#define MT_LP_IRQREMAIN_H + +extern int mt_lp_irqremain_submit(void); +extern int mt_lp_irqremain_aquire(void); +extern int mt_lp_irqremain_release(void); +extern void mt_lp_irqremain_init(void); +#endif /* MT_LP_IRQREMAIN_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c new file mode 100644 index 0000000..1635b67 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +/* Read/Write */ +#define APMCU_MCUPM_MBOX_AP_READY U(0) +#define APMCU_MCUPM_MBOX_RESERVED_1 U(1) +#define APMCU_MCUPM_MBOX_RESERVED_2 U(2) +#define APMCU_MCUPM_MBOX_RESERVED_3 U(3) +#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4) +#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5) +#define APMCU_MCUPM_MBOX_BUCK_MODE U(6) +#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7) +/* Read only */ +#define APMCU_MCUPM_MBOX_TASK_STA U(8) +#define APMCU_MCUPM_MBOX_RESERVED_9 U(9) +#define APMCU_MCUPM_MBOX_RESERVED_10 U(10) +#define APMCU_MCUPM_MBOX_RESERVED_11 U(11) + +/* CPC mode - Read/Write */ +#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12) + +/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */ +#define MCUPM_MCUSYS_CTRL BIT(0) +#define MCUPM_BUCK_CTRL BIT(1) +#define MCUPM_ARMPLL_CTRL BIT(2) +#define MCUPM_CM_CTRL BIT(3) +#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0) + +/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */ +#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */ +#define MCUPM_BUCK_LP_MODE U(1) +#define MCUPM_BUCK_OFF_MODE U(2) +#define NF_MCUPM_BUCK_MODE U(3) + +/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */ +#define MCUPM_ARMPLL_ON U(0) /* default */ +#define MCUPM_ARMPLL_GATING U(1) +#define MCUPM_ARMPLL_OFF U(2) +#define NF_MCUPM_ARMPLL_MODE U(3) + +/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */ +#define MCUPM_TASK_UNINIT U(0) +#define MCUPM_TASK_INIT U(1) +#define MCUPM_TASK_INIT_FINISH U(2) +#define MCUPM_TASK_WAIT U(3) +#define MCUPM_TASK_RUN U(4) +#define MCUPM_TASK_PAUSE U(5) + +#define SSPM_MBOX_3_BASE U(0x0c55fce0) + +#define MCDI_NOT_INIT 0 +#define MCDI_INIT_1 1 +#define MCDI_INIT_2 2 +#define MCDI_INIT_DONE 3 + +static int mcdi_init_status __section("tzfw_coherent_mem"); + +static inline uint32_t mcdi_mbox_read(uint32_t id) +{ + return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2)); +} + +static inline void mcdi_mbox_write(uint32_t id, uint32_t val) +{ + mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val); +} + +static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev) +{ + mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev); +} + +static void mtk_set_mcupm_pll_mode(uint32_t mode) +{ + if (mode < NF_MCUPM_ARMPLL_MODE) { + mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode); + } +} + +static void mtk_set_mcupm_buck_mode(uint32_t mode) +{ + if (mode < NF_MCUPM_BUCK_MODE) { + mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode); + } +} + +static int mtk_mcupm_is_ready(void) +{ + unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); + + return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH); +} + +static int mcdi_init_1(void) +{ + unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); + + if (sta != MCUPM_TASK_INIT) { + return -1; + } + + mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF); + mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE); + + mtk_mcupm_pwr_ctrl_setting( + MCUPM_MCUSYS_CTRL | + MCUPM_BUCK_CTRL | + MCUPM_ARMPLL_CTRL); + + mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1); + + return 0; +} + +static int mcdi_init_2(void) +{ + return mtk_mcupm_is_ready() ? 0 : -1; +} + +int mcdi_try_init(void) +{ + if (mcdi_init_status == MCDI_INIT_DONE) { + return 0; + } + + if (mcdi_init_status == MCDI_NOT_INIT) { + mcdi_init_status = MCDI_INIT_1; + } + + if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) { + mcdi_init_status = MCDI_INIT_2; + } + + if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) { + mcdi_init_status = MCDI_INIT_DONE; + } + + INFO("mcdi ready for mcusys-off-idle and system suspend\n"); + + return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h new file mode 100644 index 0000000..f3545aa --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_MCDI_H +#define MT_MCDI_H + +int mcdi_try_init(void); + +#endif /* MT_MCDI_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c new file mode 100644 index 0000000..cca4413 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void pmic_power_off(void) +{ + pwrap_write(PMIC_PWRHOLD, 0x0); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h new file mode 100644 index 0000000..aac22af --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_H +#define PMIC_H + +#define PMIC_PWRHOLD 0xa08 + +/* external API */ +void pmic_power_off(void); + +#endif /* PMIC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..ae892ed --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include + +#include "platform_def.h" + +/* external API */ +int32_t pwrap_read(uint32_t adr, uint32_t *rdata); +int32_t pwrap_write(uint32_t adr, uint32_t wdata); + +static struct mt8192_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE; + +/* PMIC_WRAP registers */ +struct mt8192_pmic_wrap_regs { + uint32_t init_done; + uint32_t reserved[799]; + uint32_t wacs2_cmd; + uint32_t wacs2_wdata; + uint32_t reserved1[3]; + uint32_t wacs2_rdata; + uint32_t reserved2[3]; + uint32_t wacs2_vldclr; + uint32_t wacs2_sta; +}; + +#define GET_WACS_FSM(x) ((x >> 1) & 0x7) + +/* macro for SWINF_FSM */ +#define SWINF_FSM_IDLE (0x00) +#define SWINF_FSM_REQ (0x02) +#define SWINF_FSM_WFDLE (0x04) +#define SWINF_FSM_WFVLDCLR (0x06) +#define SWINF_INIT_DONE (0x01) + +/* timeout setting */ +#define PWRAP_READ_US 1000 +#define PWRAP_WAIT_IDLE_US 1000 + +/* error information flag */ +enum pwrap_errno { + E_PWR_INVALID_ARG = 1, + E_PWR_INVALID_RW = 2, + E_PWR_INVALID_ADDR = 3, + E_PWR_INVALID_WDAT = 4, + E_PWR_INVALID_OP_MANUAL = 5, + E_PWR_NOT_IDLE_STATE = 6, + E_PWR_NOT_INIT_DONE = 7, + E_PWR_NOT_INIT_DONE_READ = 8, + E_PWR_WAIT_IDLE_TIMEOUT = 9, + E_PWR_WAIT_IDLE_TIMEOUT_READ = 10, + E_PWR_INIT_SIDLY_FAIL = 11, + E_PWR_RESET_TIMEOUT = 12, + E_PWR_TIMEOUT = 13, + E_PWR_INIT_RESET_SPI = 20, + E_PWR_INIT_SIDLY = 21, + E_PWR_INIT_REG_CLOCK = 22, + E_PWR_INIT_ENABLE_PMIC = 23, + E_PWR_INIT_DIO = 24, + E_PWR_INIT_CIPHER = 25, + E_PWR_INIT_WRITE_TEST = 26, + E_PWR_INIT_ENABLE_CRC = 27, + E_PWR_INIT_ENABLE_DEWRAP = 28, + E_PWR_INIT_ENABLE_EVENT = 29, + E_PWR_READ_TEST_FAIL = 30, + E_PWR_WRITE_TEST_FAIL = 31, + E_PWR_SWITCH_DIO = 32 +}; + +#endif /* PMIC_WRAP_INIT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h new file mode 100644 index 0000000..92c71bc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_PTP3_H +#define MTK_PTP3_H + +#include +#include + +/************************************************ + * BIT Operation and REG r/w + ************************************************/ +#define ptp3_read(addr) mmio_read_32((uintptr_t)addr) +#define ptp3_write(addr, val) mmio_write_32((uintptr_t)addr, val) + +/************************************************ + * CPU info + ************************************************/ +#define NR_PTP3_CFG1_CPU U(8) +#define PTP3_CFG1_CPU_START_ID U(0) +#define PTP3_CFG1_MASK 0x00100000 + +#define NR_PTP3_CFG2_CPU U(4) +#define PTP3_CFG2_CPU_START_ID U(4) + +#define NR_PTP3_CFG3_CPU U(4) +#define PTP3_CFG3_CPU_START_ID U(4) + +/************************************************ + * config enum + ************************************************/ +enum PTP3_CFG { + PTP3_CFG_ADDR, + PTP3_CFG_VALUE, + NR_PTP3_CFG, +}; + +/************************************ + * prototype + ************************************/ +/* init trigger for ptp3 feature */ +extern void ptp3_init(unsigned int core); +extern void ptp3_deinit(unsigned int core); + +#endif /* MTK_PTP3_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c new file mode 100644 index 0000000..f1d8493 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. \ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "mtk_ptp3_common.h" + +/************************************************ + * Central control: turn on sysPi protection + ************************************************/ +static unsigned int ptp3_cfg1[NR_PTP3_CFG1_CPU][NR_PTP3_CFG] = { + {0x0C530610, 0x110842}, + {0x0C530E10, 0x110842}, + {0x0C531610, 0x110842}, + {0x0C531E10, 0x110842}, + {0x0C532610, 0x110842}, + {0x0C532E10, 0x110842}, + {0x0C533610, 0x110842}, + {0x0C533E10, 0x110842} +}; +static unsigned int ptp3_cfg2[NR_PTP3_CFG2_CPU][NR_PTP3_CFG] = { + {0x0C53B830, 0x68000}, + {0x0C53BA30, 0x68000}, + {0x0C53BC30, 0x68000}, + {0x0C53BE30, 0x68000} +}; +static unsigned int ptp3_cfg3[NR_PTP3_CFG3_CPU][NR_PTP3_CFG] = { + {0x0C532480, 0x7C607C6}, + {0x0C532C80, 0x7C607C6}, + {0x0C533480, 0x7C607C6}, + {0x0C533C80, 0x7C607C6} +}; + +/************************************************ + * API + ************************************************/ +void ptp3_init(unsigned int core) +{ + unsigned int _core; + + /* Apply ptp3_cfg1 for core 0 to 7 */ + if (core < NR_PTP3_CFG1_CPU) { + /* update ptp3_cfg1 */ + ptp3_write( + ptp3_cfg1[core][PTP3_CFG_ADDR], + ptp3_cfg1[core][PTP3_CFG_VALUE]); + } + + /* Apply ptp3_cfg2 for core 4 to 7 */ + if (core >= PTP3_CFG2_CPU_START_ID) { + _core = core - PTP3_CFG2_CPU_START_ID; + + if (_core < NR_PTP3_CFG2_CPU) { + /* update ptp3_cfg2 */ + ptp3_write( + ptp3_cfg2[_core][PTP3_CFG_ADDR], + ptp3_cfg2[_core][PTP3_CFG_VALUE]); + } + } + + /* Apply ptp3_cfg3 for core 4 to 7 */ + if (core >= PTP3_CFG3_CPU_START_ID) { + _core = core - PTP3_CFG3_CPU_START_ID; + + if (_core < NR_PTP3_CFG3_CPU) { + /* update ptp3_cfg3 */ + ptp3_write( + ptp3_cfg3[_core][PTP3_CFG_ADDR], + ptp3_cfg3[_core][PTP3_CFG_VALUE]); + } + } +} + +void ptp3_deinit(unsigned int core) +{ + if (core < NR_PTP3_CFG1_CPU) { + /* update ptp3_cfg1 */ + ptp3_write( + ptp3_cfg1[core][PTP3_CFG_ADDR], + ptp3_cfg1[core][PTP3_CFG_VALUE] & + ~PTP3_CFG1_MASK); + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/build.mk b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/build.mk new file mode 100644 index 0000000..4153603 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/build.mk @@ -0,0 +1,68 @@ +# +# Copyright (c) 2020, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Enable or disable spm feature +MT_SPM_FEATURE_SUPPORT = yes + +# Enable or disable cirq restore +MT_SPM_CIRQ_FEATURE_SUPPORT = yes + +# sspm notifier support +MT_SPM_SSPM_NOTIFIER_SUPPORT = yes + +CUR_SPM_FOLDER = ${MTK_PLAT_SOC}/drivers/spm + +# spm common files +PLAT_SPM_SOURCE_FILES_COMMON += \ + ${CUR_SPM_FOLDER}/mt_spm.c \ + ${CUR_SPM_FOLDER}/mt_spm_conservation.c \ + ${CUR_SPM_FOLDER}/mt_spm_internal.c \ + ${CUR_SPM_FOLDER}/mt_spm_pmic_wrap.c \ + ${CUR_SPM_FOLDER}/mt_spm_vcorefs.c + +# spm platform dependcy files +PLAT_SPM_SOURCE_FILES += \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_bus26m.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_cpu_buck_ldo.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_dram.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c \ + ${CUR_SPM_FOLDER}/mt_spm_cond.c \ + ${CUR_SPM_FOLDER}/mt_spm_suspend.c \ + ${CUR_SPM_FOLDER}/mt_spm_idle.c + +ifeq (${MT_SPM_FEATURE_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${PLAT_SPM_SOURCE_FILES_COMMON} +else +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \ + ${PLAT_SPM_SOURCE_FILES_COMMON} \ + ${PLAT_SPM_SOURCE_FILES} +endif + +ifeq (${MT_SPM_CIRQ_FEATURE_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_CIRQ_UNSUPPORT +endif + +ifeq (${MT_SPM_SSPM_NOTIFIER_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT +else +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \ + ${CUR_SPM_FOLDER}/notifier/mt_spm_sspm_notifier.c +endif + +$(info --------------------------------------) +$(info SPM build flags: ${PLAT_SPM_DEBUG_CFLAGS}) +$(info SPM build files: ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES}) +$(info --------------------------------------) + +# Common makefile for platform.mk +PLAT_INCLUDES += \ + ${PLAT_SPM_DEBUG_CFLAGS} \ + -I${CUR_SPM_FOLDER}/ \ + -I${CUR_SPM_FOLDER}/constraints/ \ + -I${CUR_SPM_FOLDER}/notifier/ + +PLAT_BL_COMMON_SOURCES += ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c new file mode 100644 index 0000000..f66b8ec --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, MediaTek Inc. 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 + +#ifndef ATF_PLAT_CIRQ_UNSUPPORT +#include +#include +#endif + +#define CONSTRAINT_BUS26M_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \ + MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \ + MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF) + +#define CONSTRAINT_BUS26M_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_ENABLE_TIA_WORKAROUND | \ + SPM_FLAG_ENABLE_LVTS_WORKAROUND | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH) + +#define CONSTRAINT_BUS26M_PCM_FLAG1 \ + (SPM_FLAG1_DISABLE_MD26M_CK_OFF) + +#define CONSTRAINT_BUS26M_RESOURCE_REQ 0U + +static unsigned int bus26m_ext_opand; +static struct mt_irqremain *refer2remain_irq; +static struct mt_spm_cond_tables cond_bus26m = { + .name = "bus26m", + .table_cg = { + 0x07CBF1FC, /* MTCMOS1 */ + 0x0A0D8856, /* INFRA0 */ + 0x03AF9A00, /* INFRA1 */ + 0x86000650, /* INFRA2 */ + 0xC800C000, /* INFRA3 */ + 0x00000000, /* INFRA4 */ + 0x4000007C, /* INFRA5 */ + 0x280E0800, /* MMSYS0 */ + 0x00000001, /* MMSYS1 */ + 0x00000000, /* MMSYS2 */ + }, + .table_pll = (PLL_BIT_UNIVPLL | PLL_BIT_MFGPLL | + PLL_BIT_MSDCPLL | PLL_BIT_TVDPLL | + PLL_BIT_MMPLL), +}; + +static struct mt_spm_cond_tables cond_bus26m_res = { + .table_cg = { 0U }, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_BUS26M, + .valid = (MT_SPM_RC_VALID_SW | + MT_SPM_RC_VALID_COND_LATCH), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_bus26m_res, +}; + +/* + * Cirq will take the place of gic when gic is off. + * However, cirq cannot work if 26m clk is turned off when system idle/suspend. + * Therefore, we need to set irq pending for specific wakeup source. + */ +#ifdef ATF_PLAT_CIRQ_UNSUPPORT +#define do_irqs_delivery() +#else +static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs, + unsigned int irq_index, + struct wake_status *wakeup) +{ + INFO("[SPM] r12 = 0x%08x(0x%08x), flag = 0x%08x 0x%08x 0x%08x\n", + wakeup->tr.comm.r12, wakeup->md32pcm_wakeup_sta, + wakeup->tr.comm.debug_flag, wakeup->tr.comm.b_sw_flag0, + wakeup->tr.comm.b_sw_flag1); + + INFO("irq:%u(0x%08x) set pending\n", + irqs->wakeupsrc[irq_index], irqs->irqs[irq_index]); +} + +static void do_irqs_delivery(void) +{ + unsigned int idx; + int res = 0; + struct wake_status *wakeup = NULL; + struct mt_irqremain *irqs = refer2remain_irq; + + res = spm_conservation_get_result(&wakeup); + + if ((res != 0) && (irqs == NULL)) { + return; + } + + for (idx = 0U; idx < irqs->count; ++idx) { + if (((wakeup->tr.comm.r12 & irqs->wakeupsrc[idx]) != 0U) || + ((wakeup->raw_sta & irqs->wakeupsrc[idx]) != 0U)) { + if ((irqs->wakeupsrc_cat[idx] & + MT_IRQ_REMAIN_CAT_LOG) != 0U) { + mt_spm_irq_remain_dump(irqs, idx, wakeup); + } + + mt_irq_set_pending(irqs->irqs[idx]); + } + } +} +#endif + +static void spm_bus26m_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG1; + *resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ; +} + +bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid); +} + +int spm_update_rc_bus26m(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + return MT_RM_STATUS_BAD; + } + + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_bus26m; + + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + &cond_bus26m_res : NULL); + } else if (type == PLAT_RC_UPDATE_REMAIN_IRQS) { + refer2remain_irq = (struct mt_irqremain *)val; + } else { + res = MT_RM_STATUS_BAD; + } + + return res; +} + +unsigned int spm_allow_rc_bus26m(int state_id) +{ + (void)state_id; + + return CONSTRAINT_BUS26M_ALLOW; +} + +int spm_run_rc_bus26m(unsigned int cpu, int state_id) +{ + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, CONSTRAINT_BUS26M_ALLOW | + (IS_PLAT_SUSPEND_ID(state_id) ? + MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U)); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT | + bus26m_ext_opand), + CONSTRAINT_BUS26M_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, MT_SPM_EX_OP_HW_S1_DETECT, + spm_bus26m_conduct); + } + + return 0; +} + +int spm_reset_rc_bus26m(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + ext_op |= (bus26m_ext_opand | MT_SPM_EX_OP_SET_WDT); + mt_spm_suspend_resume(state_id, ext_op, NULL); + bus26m_ext_opand = 0U; + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL); + status.enter_cnt++; + } + + do_irqs_delivery(); + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c new file mode 100644 index 0000000..9618f3b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONSTRAINT_CPU_BUCK_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH) + +#define CONSTRAINT_CPU_BUCK_PCM_FLAG1 0U + +#define CONSTRAINT_CPU_BUCK_RESOURCE_REQ \ + (MT_SPM_DRAM_S1 | \ + MT_SPM_DRAM_S0 | \ + MT_SPM_SYSPLL | \ + MT_SPM_INFRA | \ + MT_SPM_26M | \ + MT_SPM_XO_FPM) + + +static unsigned int cpubuckldo_status = MT_SPM_RC_VALID_SW; +static unsigned int cpubuckldo_enter_cnt; + +static void spm_cpu_bcuk_ldo_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1; + *resource_req |= CONSTRAINT_CPU_BUCK_RESOURCE_REQ; +} + +bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return IS_MT_RM_RC_READY(cpubuckldo_status); +} + +unsigned int spm_allow_rc_cpu_buck_ldo(int state_id) +{ + (void)state_id; + + return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF; +} + +int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, + (IS_PLAT_SUSPEND_ID(state_id) ? + MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U)); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + MT_SPM_EX_OP_SET_WDT, + CONSTRAINT_CPU_BUCK_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, 0U, + spm_cpu_bcuk_ldo_conduct); + } + + cpubuckldo_enter_cnt++; + + return 0; +} + +int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL); + } else { + mt_spm_idle_generic_resume(state_id, 0U, NULL); + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c new file mode 100644 index 0000000..34293c4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2020, MediaTek Inc. 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 + +#define CONSTRAINT_DRAM_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF) + +#define CONSTRAINT_DRAM_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH) + +#define CONSTRAINT_DRAM_PCM_FLAG1 0U + +#define CONSTRAINT_DRAM_RESOURCE_REQ \ + (MT_SPM_SYSPLL | \ + MT_SPM_INFRA | \ + MT_SPM_26M) + +static struct mt_spm_cond_tables cond_dram = { + .name = "dram", + .table_cg = { + 0x078BF1FC, /* MTCMOS1 */ + 0x080D8856, /* INFRA0 */ + 0x03AF9A00, /* INFRA1 */ + 0x86000640, /* INFRA2 */ + 0xC800C000, /* INFRA3 */ + 0x00000000, /* INFRA4 */ + 0x00000000, /* INFRA5 */ + 0x200C0000, /* MMSYS0 */ + 0x00000000, /* MMSYS1 */ + 0x00000000, /* MMSYS2 */ + }, + .table_pll = 0U, +}; + +static struct mt_spm_cond_tables cond_dram_res = { + .table_cg = { 0U }, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_DRAM, + .valid = (MT_SPM_RC_VALID_SW | + MT_SPM_RC_VALID_COND_LATCH | + MT_SPM_RC_VALID_XSOC_BBLPM), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_dram_res, +}; + +static void spm_dram_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG1; + *resource_req |= CONSTRAINT_DRAM_RESOURCE_REQ; +} + +bool spm_is_valid_rc_dram(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid); +} + +int spm_update_rc_dram(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + return MT_RM_STATUS_BAD; + } + + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_dram; + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + &cond_dram_res : NULL); + } else { + res = MT_RM_STATUS_BAD; + } + + return res; +} + +unsigned int spm_allow_rc_dram(int state_id) +{ + (void)state_id; + + return CONSTRAINT_DRAM_ALLOW; +} + +int spm_run_rc_dram(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_DRAM_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | + (IS_PLAT_SUSPEND_ID(state_id) ? + MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U)); +#else + (void)allows; +#endif + + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT), + CONSTRAINT_DRAM_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, ext_op, spm_dram_conduct); + } + + return 0; +} + +int spm_reset_rc_dram(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_DRAM_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows); +#else + (void)allows; +#endif + + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT), + NULL); + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL); + status.enter_cnt++; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h new file mode 100644 index 0000000..aeb778a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_RC_INTERNAL_H +#define MT_SPM_RC_INTERNAL_H + +#include + +#define SPM_FLAG_SRAM_SLEEP_CTRL \ + (SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \ + SPM_FLAG_DISABLE_SYSRAM_SLEEP | \ + SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP | \ + SPM_FLAG_DISABLE_SRAM_EVENT) + +/* cpu buck/ldo constraint function */ +bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id); +unsigned int spm_allow_rc_cpu_buck_ldo(int state_id); +int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id); +int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id); + +/* spm resource dram constraint function */ +bool spm_is_valid_rc_dram(unsigned int cpu, int state_id); +int spm_update_rc_dram(int state_id, int type, const void *val); +unsigned int spm_allow_rc_dram(int state_id); +int spm_run_rc_dram(unsigned int cpu, int state_id); +int spm_reset_rc_dram(unsigned int cpu, int state_id); + +/* spm resource syspll constraint function */ +bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id); +int spm_update_rc_syspll(int state_id, int type, const void *val); +unsigned int spm_allow_rc_syspll(int state_id); +int spm_run_rc_syspll(unsigned int cpu, int state_id); +int spm_reset_rc_syspll(unsigned int cpu, int state_id); + +/* spm resource bus26m constraint function */ +bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id); +int spm_update_rc_bus26m(int state_id, int type, const void *val); +unsigned int spm_allow_rc_bus26m(int state_id); +int spm_run_rc_bus26m(unsigned int cpu, int state_id); +int spm_reset_rc_bus26m(unsigned int cpu, int state_id); +#endif /* MT_SPM_RC_INTERNAL_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c new file mode 100644 index 0000000..8d76d63 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONSTRAINT_SYSPLL_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_VCORE_LP) + +#define CONSTRAINT_SYSPLL_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ + SPM_FLAG_ENABLE_6315_CTRL | \ + SPM_FLAG_USE_SRCCLKENO2) + +#define CONSTRAINT_SYSPLL_PCM_FLAG1 0U +#define CONSTRAINT_SYSPLL_RESOURCE_REQ \ + (MT_SPM_26M) + +static struct mt_spm_cond_tables cond_syspll = { + .name = "syspll", + .table_cg = { + 0x078BF1FC, /* MTCMOS1 */ + 0x080D8856, /* INFRA0 */ + 0x03AF9A00, /* INFRA1 */ + 0x86000640, /* INFRA2 */ + 0xC800C000, /* INFRA3 */ + 0x00000000, /* INFRA4 */ + 0x0000007C, /* INFRA5 */ + 0x280E0800, /* MMSYS0 */ + 0x00000001, /* MMSYS1 */ + 0x00000000, /* MMSYS2 */ + }, + .table_pll = 0U, +}; + +static struct mt_spm_cond_tables cond_syspll_res = { + .table_cg = { 0U }, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_SYSPLL, + .valid = (MT_SPM_RC_VALID_SW | + MT_SPM_RC_VALID_COND_LATCH | + MT_SPM_RC_VALID_XSOC_BBLPM), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_syspll_res, +}; + +static void spm_syspll_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG1; + *resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ; +} + +bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid); +} + +int spm_update_rc_syspll(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + return MT_RM_STATUS_BAD; + } + + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_syspll; + + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + &cond_syspll_res : NULL); + } else { + res = MT_RM_STATUS_BAD; + } + + return res; +} + +unsigned int spm_allow_rc_syspll(int state_id) +{ + (void)state_id; + + return CONSTRAINT_SYSPLL_ALLOW; +} + +int spm_run_rc_syspll(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_SYSPLL_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | + (IS_PLAT_SUSPEND_ID(state_id) ? + MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U)); +#else + (void)allows; +#endif + + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT | + MT_SPM_EX_OP_SET_SUSPEND_MODE), + CONSTRAINT_SYSPLL_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct); + } + + return 0; +} + +int spm_reset_rc_syspll(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_SYSPLL_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows); +#else + (void)allows; +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, + (MT_SPM_EX_OP_SET_SUSPEND_MODE | + MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT), + NULL); + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL); + status.enter_cnt++; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c new file mode 100644 index 0000000..f4505b6 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020, MediaTek Inc. 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 + +#ifdef MT_SPM_USING_BAKERY_LOCK +DEFINE_BAKERY_LOCK(spm_lock); +#define plat_spm_lock_init() bakery_lock_init(&spm_lock) +#else +spinlock_t spm_lock; +#define plat_spm_lock_init() +#endif + +/* CLK_SCP_CFG_0 */ +#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x200) +#define SPM_CK_CONTROL_EN 0x3FF + +/* CLK_SCP_CFG_1 */ +#define CLK_SCP_CFG_1 (TOPCKGEN_BASE + 0x210) +#define CLK_SCP_CFG_1_MASK 0x100C +#define CLK_SCP_CFG_1_SPM 0x3 + +struct mt_resource_constraint plat_constraint_bus26m = { + .is_valid = spm_is_valid_rc_bus26m, + .update = spm_update_rc_bus26m, + .allow = spm_allow_rc_bus26m, + .run = spm_run_rc_bus26m, + .reset = spm_reset_rc_bus26m, +}; + +struct mt_resource_constraint plat_constraint_syspll = { + .is_valid = spm_is_valid_rc_syspll, + .update = spm_update_rc_syspll, + .allow = spm_allow_rc_syspll, + .run = spm_run_rc_syspll, + .reset = spm_reset_rc_syspll, +}; + +struct mt_resource_constraint plat_constraint_dram = { + .is_valid = spm_is_valid_rc_dram, + .update = spm_update_rc_dram, + .allow = spm_allow_rc_dram, + .run = spm_run_rc_dram, + .reset = spm_reset_rc_dram, +}; + +struct mt_resource_constraint plat_constraint_cpu = { + .is_valid = spm_is_valid_rc_cpu_buck_ldo, + .update = NULL, + .allow = spm_allow_rc_cpu_buck_ldo, + .run = spm_run_rc_cpu_buck_ldo, + .reset = spm_reset_rc_cpu_buck_ldo, +}; + +struct mt_resource_constraint *plat_constraints[] = { + &plat_constraint_bus26m, + &plat_constraint_syspll, + &plat_constraint_dram, + &plat_constraint_cpu, + NULL, +}; + +struct mt_resource_manager plat_mt8192_rm = { + .update = mt_spm_cond_update, + .consts = plat_constraints, +}; + +void spm_boot_init(void) +{ + /* switch ck_off/axi_26m control to SPM */ + mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_CONTROL_EN); + mmio_clrsetbits_32(CLK_SCP_CFG_1, CLK_SCP_CFG_1_MASK, + CLK_SCP_CFG_1_SPM); + + plat_spm_lock_init(); + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE); + mt_lp_rm_register(&plat_mt8192_rm); + mt_spm_idle_generic_init(); + mt_spm_suspend_init(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h new file mode 100644 index 0000000..b147fe2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_H +#define MT_SPM_H + +#include +#include + +#include + +/* + * ARM v8.2, the cache will turn off automatically when cpu + * power down. So, there is no doubt to use the spin_lock here + */ +#if !HW_ASSISTED_COHERENCY +#define MT_SPM_USING_BAKERY_LOCK +#endif + +#ifdef MT_SPM_USING_BAKERY_LOCK +DECLARE_BAKERY_LOCK(spm_lock); +#define plat_spm_lock() bakery_lock_get(&spm_lock) +#define plat_spm_unlock() bakery_lock_release(&spm_lock) +#else +extern spinlock_t spm_lock; +#define plat_spm_lock() spin_lock(&spm_lock) +#define plat_spm_unlock() spin_unlock(&spm_lock) +#endif + +#define MT_SPM_USING_SRCLKEN_RC + +/* spm extern operand definition */ +#define MT_SPM_EX_OP_CLR_26M_RECORD (1U << 0) +#define MT_SPM_EX_OP_SET_WDT (1U << 1) +#define MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ (1U << 2) +#define MT_SPM_EX_OP_SET_SUSPEND_MODE (1U << 3) +#define MT_SPM_EX_OP_SET_IS_ADSP (1U << 4) +#define MT_SPM_EX_OP_SRCLKEN_RC_BBLPM (1U << 5) +#define MT_SPM_EX_OP_HW_S1_DETECT (1U << 6) + +typedef enum { + WR_NONE = 0, + WR_UART_BUSY = 1, + WR_ABORT = 2, + WR_PCM_TIMER = 3, + WR_WAKE_SRC = 4, + WR_DVFSRC = 5, + WR_TWAM = 6, + WR_PMSR = 7, + WR_SPM_ACK_CHK = 8, + WR_UNKNOWN = 9, +} wake_reason_t; + +static inline void spm_lock_get(void) +{ + plat_spm_lock(); +} + +static inline void spm_lock_release(void) +{ + plat_spm_unlock(); +} + +extern void spm_boot_init(void); +#endif /* MT_SPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c new file mode 100644 index 0000000..2d67fdf --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define MT_LP_TZ_INFRA_REG(ofs) (INFRACFG_AO_BASE + ofs) +#define MT_LP_TZ_MM_REG(ofs) (MMSYS_BASE + ofs) +#define MT_LP_TZ_SPM_REG(ofs) (SPM_BASE + ofs) +#define MT_LP_TZ_TOPCK_REG(ofs) (TOPCKGEN_BASE + ofs) +#define MT_LP_TZ_APMIXEDSYS(ofs) (APMIXEDSYS + ofs) + +#define SPM_PWR_STATUS MT_LP_TZ_SPM_REG(0x016C) +#define SPM_PWR_STATUS_2ND MT_LP_TZ_SPM_REG(0x0170) +#define INFRA_SW_CG0 MT_LP_TZ_INFRA_REG(0x0094) +#define INFRA_SW_CG1 MT_LP_TZ_INFRA_REG(0x0090) +#define INFRA_SW_CG2 MT_LP_TZ_INFRA_REG(0x00AC) +#define INFRA_SW_CG3 MT_LP_TZ_INFRA_REG(0x00C8) +#define INFRA_SW_CG4 MT_LP_TZ_INFRA_REG(0x00D8) +#define INFRA_SW_CG5 MT_LP_TZ_INFRA_REG(0x00E8) +#define MMSYS_CG_CON0 MT_LP_TZ_MM_REG(0x100) +#define MMSYS_CG_CON1 MT_LP_TZ_MM_REG(0x110) +#define MMSYS_CG_CON2 MT_LP_TZ_MM_REG(0x1A0) + +/*********************************************************** + * Check clkmux registers + ***********************************************************/ +#define CLK_CFG(id) MT_LP_TZ_TOPCK_REG(0x20 + id * 0x10) +#define PDN_CHECK BIT(7) +#define CLK_CHECK BIT(31) + +enum { + CLKMUX_DISP = 0, + CLKMUX_MDP = 1, + CLKMUX_IMG1 = 2, + CLKMUX_IMG2 = 3, + NF_CLKMUX, +}; + +static bool is_clkmux_pdn(unsigned int clkmux_id) +{ + unsigned int reg, val, idx; + + if ((clkmux_id & CLK_CHECK) != 0U) { + clkmux_id = (clkmux_id & ~CLK_CHECK); + reg = clkmux_id / 4U; + val = mmio_read_32(CLK_CFG(reg)); + idx = clkmux_id % 4U; + val = (val >> (idx * 8U)) & PDN_CHECK; + return (val != 0U); + } + + return false; +} + +static struct mt_spm_cond_tables spm_cond_t; + +struct idle_cond_info { + unsigned int subsys_mask; + uintptr_t addr; + bool bBitflip; + unsigned int clkmux_id; +}; + +#define IDLE_CG(mask, addr, bitflip, clkmux) \ + {mask, (uintptr_t)addr, bitflip, clkmux} + +static struct idle_cond_info idle_cg_info[PLAT_SPM_COND_MAX] = { + IDLE_CG(0xffffffff, SPM_PWR_STATUS, false, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG0, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG1, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG2, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG3, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG4, true, 0U), + IDLE_CG(0x00000200, INFRA_SW_CG5, true, 0U), + IDLE_CG(0x00100000, MMSYS_CG_CON0, true, (CLK_CHECK | CLKMUX_DISP)), + IDLE_CG(0x00100000, MMSYS_CG_CON1, true, (CLK_CHECK | CLKMUX_DISP)), + IDLE_CG(0x00100000, MMSYS_CG_CON2, true, (CLK_CHECK | CLKMUX_DISP)), +}; + +/*********************************************************** + * Check pll idle condition + ***********************************************************/ +#define PLL_MFGPLL MT_LP_TZ_APMIXEDSYS(0x268) +#define PLL_MMPLL MT_LP_TZ_APMIXEDSYS(0x360) +#define PLL_UNIVPLL MT_LP_TZ_APMIXEDSYS(0x308) +#define PLL_MSDCPLL MT_LP_TZ_APMIXEDSYS(0x350) +#define PLL_TVDPLL MT_LP_TZ_APMIXEDSYS(0x380) + +unsigned int mt_spm_cond_check(int state_id, + const struct mt_spm_cond_tables *src, + const struct mt_spm_cond_tables *dest, + struct mt_spm_cond_tables *res) +{ + unsigned int blocked = 0U, i; + bool is_system_suspend = IS_PLAT_SUSPEND_ID(state_id); + + if ((src == NULL) || (dest == NULL)) { + return SPM_COND_CHECK_FAIL; + } + + for (i = 0U; i < PLAT_SPM_COND_MAX; i++) { + if (res != NULL) { + res->table_cg[i] = + (src->table_cg[i] & dest->table_cg[i]); + + if (is_system_suspend && (res->table_cg[i] != 0U)) { + INFO("suspend: %s block[%u](0x%lx) = 0x%08x\n", + dest->name, i, idle_cg_info[i].addr, + res->table_cg[i]); + } + + if (res->table_cg[i] != 0U) { + blocked |= (1U << i); + } + } else if ((src->table_cg[i] & dest->table_cg[i]) != 0U) { + blocked |= (1U << i); + break; + } + } + + if (res != NULL) { + res->table_pll = (src->table_pll & dest->table_pll); + + if (res->table_pll != 0U) { + blocked |= + (res->table_pll << SPM_COND_BLOCKED_PLL_IDX) | + SPM_COND_CHECK_BLOCKED_PLL; + } + } else if ((src->table_pll & dest->table_pll) != 0U) { + blocked |= SPM_COND_CHECK_BLOCKED_PLL; + } + + if (is_system_suspend && (blocked != 0U)) { + INFO("suspend: %s total blocked = 0x%08x\n", + dest->name, blocked); + } + + return blocked; +} + +#define IS_MT_SPM_PWR_OFF(mask) \ + (((mmio_read_32(SPM_PWR_STATUS) & mask) == 0U) && \ + ((mmio_read_32(SPM_PWR_STATUS_2ND) & mask) == 0U)) + +int mt_spm_cond_update(struct mt_resource_constraint **con, + int stateid, void *priv) +{ + int res; + uint32_t i; + struct mt_resource_constraint *const *rc; + + /* read all cg state */ + for (i = 0U; i < PLAT_SPM_COND_MAX; i++) { + spm_cond_t.table_cg[i] = 0U; + + /* check mtcmos, if off set idle_value and clk to 0 disable */ + if (IS_MT_SPM_PWR_OFF(idle_cg_info[i].subsys_mask)) { + continue; + } + + /* check clkmux */ + if (is_clkmux_pdn(idle_cg_info[i].clkmux_id)) { + continue; + } + + spm_cond_t.table_cg[i] = idle_cg_info[i].bBitflip ? + ~mmio_read_32(idle_cg_info[i].addr) : + mmio_read_32(idle_cg_info[i].addr); + } + + spm_cond_t.table_pll = 0U; + if ((mmio_read_32(PLL_MFGPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MFGPLL; + } + + if ((mmio_read_32(PLL_MMPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MMPLL; + } + + if ((mmio_read_32(PLL_UNIVPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_UNIVPLL; + } + + if ((mmio_read_32(PLL_MSDCPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MSDCPLL; + } + + if ((mmio_read_32(PLL_TVDPLL) & 0x1) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_TVDPLL; + } + + spm_cond_t.priv = priv; + for (rc = con; *rc != NULL; rc++) { + if (((*rc)->update) == NULL) { + continue; + } + + res = (*rc)->update(stateid, PLAT_RC_UPDATE_CONDITION, + (void const *)&spm_cond_t); + if (res != MT_RM_STATUS_OK) { + break; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h new file mode 100644 index 0000000..91ebdd9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONDIT_H +#define MT_SPM_CONDIT_H + +#include + +enum PLAT_SPM_COND { + PLAT_SPM_COND_MTCMOS1 = 0, + PLAT_SPM_COND_CG_INFRA_0, + PLAT_SPM_COND_CG_INFRA_1, + PLAT_SPM_COND_CG_INFRA_2, + PLAT_SPM_COND_CG_INFRA_3, + PLAT_SPM_COND_CG_INFRA_4, + PLAT_SPM_COND_CG_INFRA_5, + PLAT_SPM_COND_CG_MMSYS_0, + PLAT_SPM_COND_CG_MMSYS_1, + PLAT_SPM_COND_CG_MMSYS_2, + PLAT_SPM_COND_MAX, +}; + +#define PLL_BIT_UNIVPLL BIT(0) +#define PLL_BIT_MFGPLL BIT(1) +#define PLL_BIT_MSDCPLL BIT(2) +#define PLL_BIT_TVDPLL BIT(3) +#define PLL_BIT_MMPLL BIT(4) + +/* Definition about SPM_COND_CHECK_BLOCKED + * bit [00 ~ 15]: cg blocking index + * bit [16 ~ 29]: pll blocking index + * bit [30] : pll blocking information + * bit [31] : idle condition check fail + */ +#define SPM_COND_BLOCKED_CG_IDX U(0) +#define SPM_COND_BLOCKED_PLL_IDX U(16) +#define SPM_COND_CHECK_BLOCKED_PLL BIT(30) +#define SPM_COND_CHECK_FAIL BIT(31) + +struct mt_spm_cond_tables { + char *name; + unsigned int table_cg[PLAT_SPM_COND_MAX]; + unsigned int table_pll; + void *priv; +}; + +extern unsigned int mt_spm_cond_check(int state_id, + const struct mt_spm_cond_tables *src, + const struct mt_spm_cond_tables *dest, + struct mt_spm_cond_tables *res); +extern int mt_spm_cond_update(struct mt_resource_constraint **con, + int stateid, void *priv); +#endif /* MT_SPM_CONDIT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c new file mode 100644 index 0000000..f9e6654 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct wake_status spm_wakesta; /* record last wakesta */ + +static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + unsigned int resource_req) +{ + int ret = 0; + struct pwr_ctrl *pwrctrl; + uint32_t cpu = plat_my_core_pos(); + + pwrctrl = spm_lp->pwrctrl; + + __spm_set_cpu_status(cpu); + __spm_set_power_control(pwrctrl); + __spm_set_wakeup_event(pwrctrl); + __spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl); + __spm_set_pcm_flags(pwrctrl); + __spm_src_req_update(pwrctrl, resource_req); + + if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) { + __spm_set_pcm_wdt(1); + } + + if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) { + __spm_xo_soc_bblpm(1); + } + + if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) { + spm_hw_s1_state_monitor_resume(); + } + + /* Disable auto resume by PCM in system suspend stage */ + if (IS_PLAT_SUSPEND_ID(state_id)) { + __spm_disable_pcm_timer(); + __spm_set_pcm_wdt(0); + } + + __spm_send_cpu_wakeup_event(); + + INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n", + cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE), + mmio_read_32(PCM_TIMER_VAL) / 32768); + INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n", + pwrctrl->pcm_flags, pwrctrl->pcm_flags1, + mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS), + mmio_read_32(PWR_STATUS_2ND)); + + return ret; +} + +static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status) +{ + unsigned int ext_status = 0U; + + /* system watchdog will be resumed at kernel stage */ + if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) { + __spm_set_pcm_wdt(0); + } + + if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) { + __spm_xo_soc_bblpm(0); + } + + if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) { + spm_hw_s1_state_monitor_pause(&ext_status); + } + + __spm_ext_int_wakeup_req_clr(); + __spm_get_wakeup_status(&spm_wakesta, ext_status); + + if (status != NULL) { + *status = &spm_wakesta; + } + + __spm_clean_after_wakeup(); + + if (IS_PLAT_SUSPEND_ID(state_id)) { + __spm_output_wake_reason(state_id, &spm_wakesta); + } +} + +int spm_conservation(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, unsigned int resource_req) +{ + if (spm_lp == NULL) { + return -1; + } + + spm_lock_get(); + go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req); + spm_lock_release(); + + return 0; +} + +void spm_conservation_finish(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status) +{ + spm_lock_get(); + go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status); + spm_lock_release(); +} + +int spm_conservation_get_result(struct wake_status **res) +{ + if (res == NULL) { + return -1; + } + + *res = &spm_wakesta; + + return 0; +} + +#define GPIO_BANK (GPIO_BASE + 0x6F0) +#define TRAP_UFS_FIRST BIT(11) /* bit 11, 0: UFS, 1: eMMC */ + +void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl) +{ + if (pwrctrl == NULL) { + return; + } + + /* For ufs, emmc storage type */ + if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) { + /* If eMMC is used, mask UFS req */ + pwrctrl->reg_ufs_srcclkena_mask_b = 0; + pwrctrl->reg_ufs_infra_req_mask_b = 0; + pwrctrl->reg_ufs_apsrc_req_mask_b = 0; + pwrctrl->reg_ufs_vrf18_req_mask_b = 0; + pwrctrl->reg_ufs_ddr_en_mask_b = 0; + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h new file mode 100644 index 0000000..c5e97db --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONSERVATION_H +#define MT_SPM_CONSERVATION_H + +#include + +extern int spm_conservation(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + unsigned int resource_req); +extern void spm_conservation_finish(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status); +extern int spm_conservation_get_result(struct wake_status **res); +extern void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl); +#endif /* MT_SPM_CONSERVATION_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h new file mode 100644 index 0000000..a3409f7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONSTRAINT_H +#define MT_SPM_CONSTRAINT_H + +#include + +#define MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF (1U << 0) +#define MT_RM_CONSTRAINT_ALLOW_DRAM_S0 (1U << 1) +#define MT_RM_CONSTRAINT_ALLOW_DRAM_S1 (1U << 2) +#define MT_RM_CONSTRAINT_ALLOW_VCORE_LP (1U << 3) +#define MT_RM_CONSTRAINT_ALLOW_INFRA_PDN (1U << 4) +#define MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF (1U << 5) +#define MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND (1U << 6) +#define MT_RM_CONSTRAINT_ALLOW_BBLPM (1U << 7) +#define MT_RM_CONSTRAINT_ALLOW_XO_UFS (1U << 8) +#define MT_RM_CONSTRAINT_ALLOW_GPS_STATE (1U << 9) +#define MT_RM_CONSTRAINT_ALLOW_LVTS_STATE (1U << 10) + +#define MT_SPM_RC_INVALID 0x0 +#define MT_SPM_RC_VALID_SW (1U << 0) +#define MT_SPM_RC_VALID_FW (1U << 1) +#define MT_SPM_RC_VALID_RESIDNECY (1U << 2) +#define MT_SPM_RC_VALID_COND_CHECK (1U << 3) +#define MT_SPM_RC_VALID_COND_LATCH (1U << 4) +#define MT_SPM_RC_VALID_UFS_H8 (1U << 5) +#define MT_SPM_RC_VALID_FLIGHTMODE (1U << 6) +#define MT_SPM_RC_VALID_XSOC_BBLPM (1U << 7) +#define MT_SPM_RC_VALID_TRACE_EVENT (1U << 8) + +#define MT_SPM_RC_VALID (MT_SPM_RC_VALID_SW) + +#define IS_MT_RM_RC_READY(status) \ + ((status & MT_SPM_RC_VALID) == MT_SPM_RC_VALID) + +#define MT_SPM_RC_BBLPM_MODE \ + (MT_SPM_RC_VALID_UFS_H8 | \ + MT_SPM_RC_VALID_FLIGHTMODE | \ + MT_SPM_RC_VALID_XSOC_BBLPM) + +#define IS_MT_SPM_RC_BBLPM_MODE(st) \ + ((st & (MT_SPM_RC_BBLPM_MODE)) == MT_SPM_RC_BBLPM_MODE) + +struct constraint_status { + uint16_t id; + uint16_t valid; + uint32_t cond_block; + uint32_t enter_cnt; + struct mt_spm_cond_tables *cond_res; +}; + +enum MT_SPM_RM_RC_TYPE { + MT_RM_CONSTRAINT_ID_BUS26M, + MT_RM_CONSTRAINT_ID_SYSPLL, + MT_RM_CONSTRAINT_ID_DRAM, + MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO, + MT_RM_CONSTRAINT_ID_ALL, +}; +#endif /* MT_SPM_CONSTRAINT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c new file mode 100644 index 0000000..3540ec2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define __WAKE_SRC_FOR_IDLE_COMMON__ \ + (R12_PCM_TIMER | \ + R12_KP_IRQ_B | \ + R12_APWDT_EVENT_B | \ + R12_APXGPT1_EVENT_B | \ + R12_CONN2AP_SPM_WAKEUP_B | \ + R12_EINT_EVENT_B | \ + R12_CONN_WDT_IRQ_B | \ + R12_CCIF0_EVENT_B | \ + R12_SSPM2SPM_WAKEUP_B | \ + R12_SCP2SPM_WAKEUP_B | \ + R12_ADSP2SPM_WAKEUP_B | \ + R12_USBX_CDSC_B | \ + R12_USBX_POWERDWN_B | \ + R12_SYS_TIMER_EVENT_B | \ + R12_EINT_EVENT_SECURE_B | \ + R12_CCIF1_EVENT_B | \ + R12_AFE_IRQ_MCU_B | \ + R12_SYS_CIRQ_IRQ_B | \ + R12_MD2AP_PEER_EVENT_B | \ + R12_MD1_WDT_B | \ + R12_CLDMA_EVENT_B | \ + R12_REG_CPU_WAKEUP | \ + R12_APUSYS_WAKE_HOST_B | \ + R12_PCIE_BRIDGE_IRQ | \ + R12_PCIE_IRQ) + +#if defined(CFG_MICROTRUST_TEE_SUPPORT) +#define WAKE_SRC_FOR_IDLE (__WAKE_SRC_FOR_IDLE_COMMON__) +#else +#define WAKE_SRC_FOR_IDLE \ + (__WAKE_SRC_FOR_IDLE_COMMON__ | \ + R12_SEJ_EVENT_B) +#endif + +static struct pwr_ctrl idle_spm_pwr = { + .timer_val = 0x28000, + .wake_src = WAKE_SRC_FOR_IDLE, + + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + .reg_wfi_op = 0, + .reg_wfi_type = 0, + .reg_mp0_cputop_idle_mask = 0, + .reg_mp1_cputop_idle_mask = 0, + .reg_mcusys_idle_mask = 0, + .reg_md_apsrc_1_sel = 0, + .reg_md_apsrc_0_sel = 0, + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC6_MASK */ + .reg_dpmaif_srcclkena_mask_b = 1, + .reg_dpmaif_infra_req_mask_b = 1, + .reg_dpmaif_apsrc_req_mask_b = 1, + .reg_dpmaif_vrf18_req_mask_b = 1, + .reg_dpmaif_ddr_en_mask_b = 1, + + /* SPM_SRC_REQ */ + .reg_spm_apsrc_req = 1, + .reg_spm_f26m_req = 1, + .reg_spm_infra_req = 1, + .reg_spm_vrf18_req = 1, + .reg_spm_ddr_en_req = 1, + .reg_spm_dvfs_req = 0, + .reg_spm_sw_mailbox_req = 0, + .reg_spm_sspm_mailbox_req = 0, + .reg_spm_adsp_mailbox_req = 0, + .reg_spm_scp_mailbox_req = 0, + + /* SPM_SRC_MASK */ + .reg_md_srcclkena_0_mask_b = 1, + .reg_md_srcclkena2infra_req_0_mask_b = 0, + .reg_md_apsrc2infra_req_0_mask_b = 1, + .reg_md_apsrc_req_0_mask_b = 1, + .reg_md_vrf18_req_0_mask_b = 1, + .reg_md_ddr_en_0_mask_b = 1, + .reg_md_srcclkena_1_mask_b = 0, + .reg_md_srcclkena2infra_req_1_mask_b = 0, + .reg_md_apsrc2infra_req_1_mask_b = 0, + .reg_md_apsrc_req_1_mask_b = 0, + .reg_md_vrf18_req_1_mask_b = 0, + .reg_md_ddr_en_1_mask_b = 0, + .reg_conn_srcclkena_mask_b = 1, + .reg_conn_srcclkenb_mask_b = 0, + .reg_conn_infra_req_mask_b = 1, + .reg_conn_apsrc_req_mask_b = 1, + .reg_conn_vrf18_req_mask_b = 1, + .reg_conn_ddr_en_mask_b = 1, + .reg_conn_vfe28_mask_b = 0, + .reg_srcclkeni0_srcclkena_mask_b = 1, + .reg_srcclkeni0_infra_req_mask_b = 1, + .reg_srcclkeni1_srcclkena_mask_b = 0, + .reg_srcclkeni1_infra_req_mask_b = 0, + .reg_srcclkeni2_srcclkena_mask_b = 0, + .reg_srcclkeni2_infra_req_mask_b = 0, + .reg_infrasys_apsrc_req_mask_b = 0, + .reg_infrasys_ddr_en_mask_b = 1, + .reg_md32_srcclkena_mask_b = 1, + .reg_md32_infra_req_mask_b = 1, + .reg_md32_apsrc_req_mask_b = 1, + .reg_md32_vrf18_req_mask_b = 1, + .reg_md32_ddr_en_mask_b = 1, + + /* SPM_SRC2_MASK */ + .reg_scp_srcclkena_mask_b = 1, + .reg_scp_infra_req_mask_b = 1, + .reg_scp_apsrc_req_mask_b = 1, + .reg_scp_vrf18_req_mask_b = 1, + .reg_scp_ddr_en_mask_b = 1, + .reg_audio_dsp_srcclkena_mask_b = 1, + .reg_audio_dsp_infra_req_mask_b = 1, + .reg_audio_dsp_apsrc_req_mask_b = 1, + .reg_audio_dsp_vrf18_req_mask_b = 1, + .reg_audio_dsp_ddr_en_mask_b = 1, + .reg_ufs_srcclkena_mask_b = 1, + .reg_ufs_infra_req_mask_b = 1, + .reg_ufs_apsrc_req_mask_b = 1, + .reg_ufs_vrf18_req_mask_b = 1, + .reg_ufs_ddr_en_mask_b = 1, + .reg_disp0_apsrc_req_mask_b = 1, + .reg_disp0_ddr_en_mask_b = 1, + .reg_disp1_apsrc_req_mask_b = 1, + .reg_disp1_ddr_en_mask_b = 1, + .reg_gce_infra_req_mask_b = 1, + .reg_gce_apsrc_req_mask_b = 1, + .reg_gce_vrf18_req_mask_b = 1, + .reg_gce_ddr_en_mask_b = 1, + .reg_apu_srcclkena_mask_b = 1, + .reg_apu_infra_req_mask_b = 1, + .reg_apu_apsrc_req_mask_b = 1, + .reg_apu_vrf18_req_mask_b = 1, + .reg_apu_ddr_en_mask_b = 1, + .reg_cg_check_srcclkena_mask_b = 0, + .reg_cg_check_apsrc_req_mask_b = 0, + .reg_cg_check_vrf18_req_mask_b = 0, + .reg_cg_check_ddr_en_mask_b = 0, + + /* SPM_SRC3_MASK */ + .reg_dvfsrc_event_trigger_mask_b = 1, + .reg_sw2spm_int0_mask_b = 0, + .reg_sw2spm_int1_mask_b = 0, + .reg_sw2spm_int2_mask_b = 0, + .reg_sw2spm_int3_mask_b = 0, + .reg_sc_adsp2spm_wakeup_mask_b = 0, + .reg_sc_sspm2spm_wakeup_mask_b = 0, + .reg_sc_scp2spm_wakeup_mask_b = 0, + .reg_csyspwrreq_mask = 1, + .reg_spm_srcclkena_reserved_mask_b = 0, + .reg_spm_infra_req_reserved_mask_b = 0, + .reg_spm_apsrc_req_reserved_mask_b = 0, + .reg_spm_vrf18_req_reserved_mask_b = 0, + .reg_spm_ddr_en_reserved_mask_b = 0, + .reg_mcupm_srcclkena_mask_b = 1, + .reg_mcupm_infra_req_mask_b = 1, + .reg_mcupm_apsrc_req_mask_b = 1, + .reg_mcupm_vrf18_req_mask_b = 1, + .reg_mcupm_ddr_en_mask_b = 1, + .reg_msdc0_srcclkena_mask_b = 1, + .reg_msdc0_infra_req_mask_b = 1, + .reg_msdc0_apsrc_req_mask_b = 1, + .reg_msdc0_vrf18_req_mask_b = 1, + .reg_msdc0_ddr_en_mask_b = 1, + .reg_msdc1_srcclkena_mask_b = 1, + .reg_msdc1_infra_req_mask_b = 1, + .reg_msdc1_apsrc_req_mask_b = 1, + .reg_msdc1_vrf18_req_mask_b = 1, + .reg_msdc1_ddr_en_mask_b = 1, + + /* SPM_SRC4_MASK */ + .ccif_event_mask_b = 0xFFF, + .reg_bak_psri_srcclkena_mask_b = 0, + .reg_bak_psri_infra_req_mask_b = 0, + .reg_bak_psri_apsrc_req_mask_b = 0, + .reg_bak_psri_vrf18_req_mask_b = 0, + .reg_bak_psri_ddr_en_mask_b = 0, + .reg_dramc0_md32_infra_req_mask_b = 1, + .reg_dramc0_md32_vrf18_req_mask_b = 0, + .reg_dramc1_md32_infra_req_mask_b = 1, + .reg_dramc1_md32_vrf18_req_mask_b = 0, + .reg_conn_srcclkenb2pwrap_mask_b = 0, + .reg_dramc0_md32_wakeup_mask = 1, + .reg_dramc1_md32_wakeup_mask = 1, + + /* SPM_SRC5_MASK */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x11, + .reg_mcusys_merge_ddr_en_mask_b = 0x11, + .reg_msdc2_srcclkena_mask_b = 1, + .reg_msdc2_infra_req_mask_b = 1, + .reg_msdc2_apsrc_req_mask_b = 1, + .reg_msdc2_vrf18_req_mask_b = 1, + .reg_msdc2_ddr_en_mask_b = 1, + .reg_pcie_srcclkena_mask_b = 1, + .reg_pcie_infra_req_mask_b = 1, + .reg_pcie_apsrc_req_mask_b = 1, + .reg_pcie_vrf18_req_mask_b = 1, + .reg_pcie_ddr_en_mask_b = 1, + + /* SPM_WAKEUP_EVENT_MASK */ + .reg_wakeup_event_mask = 0x01282202, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, + + /* Auto-gen End */ +}; + +struct spm_lp_scen idle_spm_lp = { + .pwrctrl = &idle_spm_pwr, +}; + +int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand, + spm_idle_conduct fn) +{ + unsigned int src_req = 0; + + if (fn != NULL) { + fn(&idle_spm_lp, &src_req); + } + + return spm_conservation(state_id, ext_opand, &idle_spm_lp, src_req); +} +void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand, + struct wake_status **status) +{ + spm_conservation_finish(state_id, ext_opand, &idle_spm_lp, status); +} + +void mt_spm_idle_generic_init(void) +{ + spm_conservation_pwrctrl_init(idle_spm_lp.pwrctrl); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h new file mode 100644 index 0000000..3d42cf1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_IDLE_H +#define MT_SPM_IDLE_H + +typedef void (*spm_idle_conduct)(struct spm_lp_scen *spm_lp, + unsigned int *resource_req); +int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand, + spm_idle_conduct fn); +void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand, + struct wake_status **status); +void mt_spm_idle_generic_init(void); +#endif /* MT_SPM_IDLE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c new file mode 100644 index 0000000..40be027 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c @@ -0,0 +1,588 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/************************************** + * Define and Declare + **************************************/ +#define ROOT_CORE_ADDR_OFFSET 0x20000000 +#define SPM_WAKEUP_EVENT_MASK_CLEAN_MASK 0xefffffff +#define SPM_INIT_DONE_US 20 + +static unsigned int mt_spm_bblpm_cnt; + +const char *wakeup_src_str[32] = { + [0] = "R12_PCM_TIMER", + [1] = "R12_RESERVED_DEBUG_B", + [2] = "R12_KP_IRQ_B", + [3] = "R12_APWDT_EVENT_B", + [4] = "R12_APXGPT1_EVENT_B", + [5] = "R12_CONN2AP_SPM_WAKEUP_B", + [6] = "R12_EINT_EVENT_B", + [7] = "R12_CONN_WDT_IRQ_B", + [8] = "R12_CCIF0_EVENT_B", + [9] = "R12_LOWBATTERY_IRQ_B", + [10] = "R12_SC_SSPM2SPM_WAKEUP_B", + [11] = "R12_SC_SCP2SPM_WAKEUP_B", + [12] = "R12_SC_ADSP2SPM_WAKEUP_B", + [13] = "R12_PCM_WDT_WAKEUP_B", + [14] = "R12_USB_CDSC_B", + [15] = "R12_USB_POWERDWN_B", + [16] = "R12_SYS_TIMER_EVENT_B", + [17] = "R12_EINT_EVENT_SECURE_B", + [18] = "R12_CCIF1_EVENT_B", + [19] = "R12_UART0_IRQ_B", + [20] = "R12_AFE_IRQ_MCU_B", + [21] = "R12_THERM_CTRL_EVENT_B", + [22] = "R12_SYS_CIRQ_IRQ_B", + [23] = "R12_MD2AP_PEER_EVENT_B", + [24] = "R12_CSYSPWREQ_B", + [25] = "R12_MD1_WDT_B", + [26] = "R12_AP2AP_PEER_WAKEUPEVENT_B", + [27] = "R12_SEJ_EVENT_B", + [28] = "R12_SPM_CPU_WAKEUPEVENT_B", + [29] = "R12_APUSYS", + [30] = "R12_PCIE_BRIDGE_IRQ", + [31] = "R12_PCIE_IRQ", +}; + +/************************************** + * Function and API + **************************************/ + +wake_reason_t __spm_output_wake_reason(int state_id, + const struct wake_status *wakesta) +{ + uint32_t i, bk_vtcxo_dur, spm_26m_off_pct = 0U; + wake_reason_t wr = WR_UNKNOWN; + + if (wakesta == NULL) { + return WR_UNKNOWN; + } + + if (wakesta->abort != 0U) { + ERROR("spmfw flow is aborted: 0x%x, timer_out = %u\n", + wakesta->abort, wakesta->timer_out); + } else { + for (i = 0U; i < 32U; i++) { + if ((wakesta->r12 & (1U << i)) != 0U) { + INFO("wake up by %s, timer_out = %u\n", + wakeup_src_str[i], wakesta->timer_out); + wr = WR_WAKE_SRC; + break; + } + } + } + + INFO("r12 = 0x%x, r12_ext = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n", + wakesta->r12, wakesta->r12_ext, wakesta->r13, wakesta->debug_flag, + wakesta->debug_flag1); + INFO("raw_sta = 0x%x 0x%x 0x%x, idle_sta = 0x%x, cg_check_sta = 0x%x\n", + wakesta->raw_sta, wakesta->md32pcm_wakeup_sta, + wakesta->md32pcm_event_sta, wakesta->idle_sta, + wakesta->cg_check_sta); + INFO("req_sta = 0x%x 0x%x 0x%x 0x%x 0x%x, isr = 0x%x\n", + wakesta->req_sta0, wakesta->req_sta1, wakesta->req_sta2, + wakesta->req_sta3, wakesta->req_sta4, wakesta->isr); + INFO("rt_req_sta0 = 0x%x, rt_req_sta1 = 0x%x, rt_req_sta2 = 0x%x\n", + wakesta->rt_req_sta0, wakesta->rt_req_sta1, wakesta->rt_req_sta2); + INFO("rt_req_sta3 = 0x%x, dram_sw_con_3 = 0x%x, raw_ext_sta = 0x%x\n", + wakesta->rt_req_sta3, wakesta->rt_req_sta4, wakesta->raw_ext_sta); + INFO("wake_misc = 0x%x, pcm_flag = 0x%x 0x%x 0x%x 0x%x, req = 0x%x\n", + wakesta->wake_misc, wakesta->sw_flag0, wakesta->sw_flag1, + wakesta->b_sw_flag0, wakesta->b_sw_flag1, wakesta->src_req); + INFO("clk_settle = 0x%x, wlk_cntcv_l = 0x%x, wlk_cntcv_h = 0x%x\n", + wakesta->clk_settle, mmio_read_32(SYS_TIMER_VALUE_L), + mmio_read_32(SYS_TIMER_VALUE_H)); + + if (wakesta->timer_out != 0U) { + bk_vtcxo_dur = mmio_read_32(SPM_BK_VTCXO_DUR); + spm_26m_off_pct = (100 * bk_vtcxo_dur) / wakesta->timer_out; + INFO("spm_26m_off_pct = %u\n", spm_26m_off_pct); + } + + return wr; +} + +void __spm_set_cpu_status(unsigned int cpu) +{ + uint32_t root_core_addr; + + if (cpu < 8U) { + mmio_write_32(ROOT_CPUTOP_ADDR, (1U << cpu)); + root_core_addr = SPM_CPU0_PWR_CON + (cpu * 0x4); + root_core_addr += ROOT_CORE_ADDR_OFFSET; + mmio_write_32(ROOT_CORE_ADDR, root_core_addr); + /* Notify MCUPM that preferred cpu wakeup */ + mmio_write_32(MCUPM_MBOX_WAKEUP_CPU, cpu); + } else { + ERROR("%s: error cpu number %d\n", __func__, cpu); + } +} + +void __spm_src_req_update(const struct pwr_ctrl *pwrctrl, + unsigned int resource_usage) +{ + uint8_t apsrc_req = ((resource_usage & MT_SPM_DRAM_S0) != 0U) ? + 1 : pwrctrl->reg_spm_apsrc_req; + uint8_t ddr_en_req = ((resource_usage & MT_SPM_DRAM_S1) != 0U) ? + 1 : pwrctrl->reg_spm_ddr_en_req; + uint8_t vrf18_req = ((resource_usage & MT_SPM_SYSPLL) != 0U) ? + 1 : pwrctrl->reg_spm_vrf18_req; + uint8_t infra_req = ((resource_usage & MT_SPM_INFRA) != 0U) ? + 1 : pwrctrl->reg_spm_infra_req; + uint8_t f26m_req = ((resource_usage & + (MT_SPM_26M | MT_SPM_XO_FPM)) != 0U) ? + 1 : pwrctrl->reg_spm_f26m_req; + + mmio_write_32(SPM_SRC_REQ, + ((apsrc_req & 0x1) << 0) | + ((f26m_req & 0x1) << 1) | + ((infra_req & 0x1) << 3) | + ((vrf18_req & 0x1) << 4) | + ((ddr_en_req & 0x1) << 7) | + ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) | + ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) | + ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) | + ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) | + ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12)); +} + +void __spm_set_power_control(const struct pwr_ctrl *pwrctrl) +{ + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + mmio_write_32(SPM_AP_STANDBY_CON, + ((pwrctrl->reg_wfi_op & 0x1) << 0) | + ((pwrctrl->reg_wfi_type & 0x1) << 1) | + ((pwrctrl->reg_mp0_cputop_idle_mask & 0x1) << 2) | + ((pwrctrl->reg_mp1_cputop_idle_mask & 0x1) << 3) | + ((pwrctrl->reg_mcusys_idle_mask & 0x1) << 4) | + ((pwrctrl->reg_md_apsrc_1_sel & 0x1) << 25) | + ((pwrctrl->reg_md_apsrc_0_sel & 0x1) << 26) | + ((pwrctrl->reg_conn_apsrc_sel & 0x1) << 29)); + + /* SPM_SRC6_MASK */ + mmio_write_32(SPM_SRC6_MASK, + ((pwrctrl->reg_dpmaif_srcclkena_mask_b & 0x1) << 0) | + ((pwrctrl->reg_dpmaif_infra_req_mask_b & 0x1) << 1) | + ((pwrctrl->reg_dpmaif_apsrc_req_mask_b & 0x1) << 2) | + ((pwrctrl->reg_dpmaif_vrf18_req_mask_b & 0x1) << 3) | + ((pwrctrl->reg_dpmaif_ddr_en_mask_b & 0x1) << 4)); + + /* SPM_SRC_REQ */ + mmio_write_32(SPM_SRC_REQ, + ((pwrctrl->reg_spm_apsrc_req & 0x1) << 0) | + ((pwrctrl->reg_spm_f26m_req & 0x1) << 1) | + ((pwrctrl->reg_spm_infra_req & 0x1) << 3) | + ((pwrctrl->reg_spm_vrf18_req & 0x1) << 4) | + ((pwrctrl->reg_spm_ddr_en_req & 0x1) << 7) | + ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) | + ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) | + ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) | + ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) | + ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12)); + + /* SPM_SRC_MASK */ + mmio_write_32(SPM_SRC_MASK, + ((pwrctrl->reg_md_srcclkena_0_mask_b & 0x1) << 0) | + ((pwrctrl->reg_md_srcclkena2infra_req_0_mask_b & 0x1) << 1) | + ((pwrctrl->reg_md_apsrc2infra_req_0_mask_b & 0x1) << 2) | + ((pwrctrl->reg_md_apsrc_req_0_mask_b & 0x1) << 3) | + ((pwrctrl->reg_md_vrf18_req_0_mask_b & 0x1) << 4) | + ((pwrctrl->reg_md_ddr_en_0_mask_b & 0x1) << 5) | + ((pwrctrl->reg_md_srcclkena_1_mask_b & 0x1) << 6) | + ((pwrctrl->reg_md_srcclkena2infra_req_1_mask_b & 0x1) << 7) | + ((pwrctrl->reg_md_apsrc2infra_req_1_mask_b & 0x1) << 8) | + ((pwrctrl->reg_md_apsrc_req_1_mask_b & 0x1) << 9) | + ((pwrctrl->reg_md_vrf18_req_1_mask_b & 0x1) << 10) | + ((pwrctrl->reg_md_ddr_en_1_mask_b & 0x1) << 11) | + ((pwrctrl->reg_conn_srcclkena_mask_b & 0x1) << 12) | + ((pwrctrl->reg_conn_srcclkenb_mask_b & 0x1) << 13) | + ((pwrctrl->reg_conn_infra_req_mask_b & 0x1) << 14) | + ((pwrctrl->reg_conn_apsrc_req_mask_b & 0x1) << 15) | + ((pwrctrl->reg_conn_vrf18_req_mask_b & 0x1) << 16) | + ((pwrctrl->reg_conn_ddr_en_mask_b & 0x1) << 17) | + ((pwrctrl->reg_conn_vfe28_mask_b & 0x1) << 18) | + ((pwrctrl->reg_srcclkeni0_srcclkena_mask_b & 0x1) << 19) | + ((pwrctrl->reg_srcclkeni0_infra_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_srcclkeni1_srcclkena_mask_b & 0x1) << 21) | + ((pwrctrl->reg_srcclkeni1_infra_req_mask_b & 0x1) << 22) | + ((pwrctrl->reg_srcclkeni2_srcclkena_mask_b & 0x1) << 23) | + ((pwrctrl->reg_srcclkeni2_infra_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_infrasys_ddr_en_mask_b & 0x1) << 26) | + ((pwrctrl->reg_md32_srcclkena_mask_b & 0x1) << 27) | + ((pwrctrl->reg_md32_infra_req_mask_b & 0x1) << 28) | + ((pwrctrl->reg_md32_apsrc_req_mask_b & 0x1) << 29) | + ((pwrctrl->reg_md32_vrf18_req_mask_b & 0x1) << 30) | + ((pwrctrl->reg_md32_ddr_en_mask_b & 0x1) << 31)); + + /* SPM_SRC2_MASK */ + mmio_write_32(SPM_SRC2_MASK, + ((pwrctrl->reg_scp_srcclkena_mask_b & 0x1) << 0) | + ((pwrctrl->reg_scp_infra_req_mask_b & 0x1) << 1) | + ((pwrctrl->reg_scp_apsrc_req_mask_b & 0x1) << 2) | + ((pwrctrl->reg_scp_vrf18_req_mask_b & 0x1) << 3) | + ((pwrctrl->reg_scp_ddr_en_mask_b & 0x1) << 4) | + ((pwrctrl->reg_audio_dsp_srcclkena_mask_b & 0x1) << 5) | + ((pwrctrl->reg_audio_dsp_infra_req_mask_b & 0x1) << 6) | + ((pwrctrl->reg_audio_dsp_apsrc_req_mask_b & 0x1) << 7) | + ((pwrctrl->reg_audio_dsp_vrf18_req_mask_b & 0x1) << 8) | + ((pwrctrl->reg_audio_dsp_ddr_en_mask_b & 0x1) << 9) | + ((pwrctrl->reg_ufs_srcclkena_mask_b & 0x1) << 10) | + ((pwrctrl->reg_ufs_infra_req_mask_b & 0x1) << 11) | + ((pwrctrl->reg_ufs_apsrc_req_mask_b & 0x1) << 12) | + ((pwrctrl->reg_ufs_vrf18_req_mask_b & 0x1) << 13) | + ((pwrctrl->reg_ufs_ddr_en_mask_b & 0x1) << 14) | + ((pwrctrl->reg_disp0_apsrc_req_mask_b & 0x1) << 15) | + ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 16) | + ((pwrctrl->reg_disp1_apsrc_req_mask_b & 0x1) << 17) | + ((pwrctrl->reg_disp1_ddr_en_mask_b & 0x1) << 18) | + ((pwrctrl->reg_gce_infra_req_mask_b & 0x1) << 19) | + ((pwrctrl->reg_gce_apsrc_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_gce_vrf18_req_mask_b & 0x1) << 21) | + ((pwrctrl->reg_gce_ddr_en_mask_b & 0x1) << 22) | + ((pwrctrl->reg_apu_srcclkena_mask_b & 0x1) << 23) | + ((pwrctrl->reg_apu_infra_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_apu_apsrc_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_apu_vrf18_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_apu_ddr_en_mask_b & 0x1) << 27) | + ((pwrctrl->reg_cg_check_srcclkena_mask_b & 0x1) << 28) | + ((pwrctrl->reg_cg_check_apsrc_req_mask_b & 0x1) << 29) | + ((pwrctrl->reg_cg_check_vrf18_req_mask_b & 0x1) << 30) | + ((pwrctrl->reg_cg_check_ddr_en_mask_b & 0x1) << 31)); + + /* SPM_SRC3_MASK */ + mmio_write_32(SPM_SRC3_MASK, + ((pwrctrl->reg_dvfsrc_event_trigger_mask_b & 0x1) << 0) | + ((pwrctrl->reg_sw2spm_int0_mask_b & 0x1) << 1) | + ((pwrctrl->reg_sw2spm_int1_mask_b & 0x1) << 2) | + ((pwrctrl->reg_sw2spm_int2_mask_b & 0x1) << 3) | + ((pwrctrl->reg_sw2spm_int3_mask_b & 0x1) << 4) | + ((pwrctrl->reg_sc_adsp2spm_wakeup_mask_b & 0x1) << 5) | + ((pwrctrl->reg_sc_sspm2spm_wakeup_mask_b & 0xf) << 6) | + ((pwrctrl->reg_sc_scp2spm_wakeup_mask_b & 0x1) << 10) | + ((pwrctrl->reg_csyspwrreq_mask & 0x1) << 11) | + ((pwrctrl->reg_spm_srcclkena_reserved_mask_b & 0x1) << 12) | + ((pwrctrl->reg_spm_infra_req_reserved_mask_b & 0x1) << 13) | + ((pwrctrl->reg_spm_apsrc_req_reserved_mask_b & 0x1) << 14) | + ((pwrctrl->reg_spm_vrf18_req_reserved_mask_b & 0x1) << 15) | + ((pwrctrl->reg_spm_ddr_en_reserved_mask_b & 0x1) << 16) | + ((pwrctrl->reg_mcupm_srcclkena_mask_b & 0x1) << 17) | + ((pwrctrl->reg_mcupm_infra_req_mask_b & 0x1) << 18) | + ((pwrctrl->reg_mcupm_apsrc_req_mask_b & 0x1) << 19) | + ((pwrctrl->reg_mcupm_vrf18_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_mcupm_ddr_en_mask_b & 0x1) << 21) | + ((pwrctrl->reg_msdc0_srcclkena_mask_b & 0x1) << 22) | + ((pwrctrl->reg_msdc0_infra_req_mask_b & 0x1) << 23) | + ((pwrctrl->reg_msdc0_apsrc_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_msdc0_vrf18_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_msdc0_ddr_en_mask_b & 0x1) << 26) | + ((pwrctrl->reg_msdc1_srcclkena_mask_b & 0x1) << 27) | + ((pwrctrl->reg_msdc1_infra_req_mask_b & 0x1) << 28) | + ((pwrctrl->reg_msdc1_apsrc_req_mask_b & 0x1) << 29) | + ((pwrctrl->reg_msdc1_vrf18_req_mask_b & 0x1) << 30) | + ((pwrctrl->reg_msdc1_ddr_en_mask_b & 0x1) << 31)); + + /* SPM_SRC4_MASK */ + mmio_write_32(SPM_SRC4_MASK, + ((pwrctrl->ccif_event_mask_b & 0xffff) << 0) | + ((pwrctrl->reg_bak_psri_srcclkena_mask_b & 0x1) << 16) | + ((pwrctrl->reg_bak_psri_infra_req_mask_b & 0x1) << 17) | + ((pwrctrl->reg_bak_psri_apsrc_req_mask_b & 0x1) << 18) | + ((pwrctrl->reg_bak_psri_vrf18_req_mask_b & 0x1) << 19) | + ((pwrctrl->reg_bak_psri_ddr_en_mask_b & 0x1) << 20) | + ((pwrctrl->reg_dramc0_md32_infra_req_mask_b & 0x1) << 21) | + ((pwrctrl->reg_dramc0_md32_vrf18_req_mask_b & 0x1) << 22) | + ((pwrctrl->reg_dramc1_md32_infra_req_mask_b & 0x1) << 23) | + ((pwrctrl->reg_dramc1_md32_vrf18_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_conn_srcclkenb2pwrap_mask_b & 0x1) << 25) | + ((pwrctrl->reg_dramc0_md32_wakeup_mask & 0x1) << 26) | + ((pwrctrl->reg_dramc1_md32_wakeup_mask & 0x1) << 27)); + + /* SPM_SRC5_MASK */ + mmio_write_32(SPM_SRC5_MASK, + ((pwrctrl->reg_mcusys_merge_apsrc_req_mask_b & 0x1ff) << 0) | + ((pwrctrl->reg_mcusys_merge_ddr_en_mask_b & 0x1ff) << 9) | + ((pwrctrl->reg_msdc2_srcclkena_mask_b & 0x1) << 18) | + ((pwrctrl->reg_msdc2_infra_req_mask_b & 0x1) << 19) | + ((pwrctrl->reg_msdc2_apsrc_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_msdc2_vrf18_req_mask_b & 0x1) << 21) | + ((pwrctrl->reg_msdc2_ddr_en_mask_b & 0x1) << 22) | + ((pwrctrl->reg_pcie_srcclkena_mask_b & 0x1) << 23) | + ((pwrctrl->reg_pcie_infra_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_pcie_apsrc_req_mask_b & 0x1) << 25) | + ((pwrctrl->reg_pcie_vrf18_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_pcie_ddr_en_mask_b & 0x1) << 27)); + + /* SPM_WAKEUP_EVENT_MASK */ + mmio_write_32(SPM_WAKEUP_EVENT_MASK, + ((pwrctrl->reg_wakeup_event_mask & 0xffffffff) << 0)); + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK, + ((pwrctrl->reg_ext_wakeup_event_mask & 0xffffffff) << 0)); + + /* Auto-gen End */ +} + +void __spm_disable_pcm_timer(void) +{ + mmio_clrsetbits_32(PCM_CON1, RG_PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY); +} + +void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl) +{ + uint32_t val, mask; + + /* toggle event counter clear */ + mmio_setbits_32(PCM_CON1, + SPM_REGWR_CFG_KEY | SPM_EVENT_COUNTER_CLR_LSB); + + /* toggle for reset SYS TIMER start point */ + mmio_setbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB); + + if (pwrctrl->timer_val_cust == 0U) { + val = pwrctrl->timer_val; + } else { + val = pwrctrl->timer_val_cust; + } + + mmio_write_32(PCM_TIMER_VAL, val); + mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | RG_PCM_TIMER_EN_LSB); + + /* unmask AP wakeup source */ + if (pwrctrl->wake_src_cust == 0U) { + mask = pwrctrl->wake_src; + } else { + mask = pwrctrl->wake_src_cust; + } + + if (pwrctrl->reg_csyspwrreq_mask != 0U) { + mask &= ~R12_CSYSPWREQ_B; + } + + mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask); + + /* unmask SPM ISR (keep TWAM setting) */ + mmio_setbits_32(SPM_IRQ_MASK, ISRM_RET_IRQ_AUX); + + /* toggle event counter clear */ + mmio_clrsetbits_32(PCM_CON1, SPM_EVENT_COUNTER_CLR_LSB, + SPM_REGWR_CFG_KEY); + /* toggle for reset SYS TIMER start point */ + mmio_clrbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB); +} + +void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl) +{ + /* set PCM flags and data */ + if (pwrctrl->pcm_flags_cust_clr != 0U) { + pwrctrl->pcm_flags &= ~pwrctrl->pcm_flags_cust_clr; + } + + if (pwrctrl->pcm_flags_cust_set != 0U) { + pwrctrl->pcm_flags |= pwrctrl->pcm_flags_cust_set; + } + + if (pwrctrl->pcm_flags1_cust_clr != 0U) { + pwrctrl->pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr; + } + + if (pwrctrl->pcm_flags1_cust_set != 0U) { + pwrctrl->pcm_flags1 |= pwrctrl->pcm_flags1_cust_set; + } + + mmio_write_32(SPM_SW_FLAG_0, pwrctrl->pcm_flags); + mmio_write_32(SPM_SW_FLAG_1, pwrctrl->pcm_flags1); + mmio_write_32(SPM_SW_RSV_7, pwrctrl->pcm_flags); + mmio_write_32(SPM_SW_RSV_8, pwrctrl->pcm_flags1); +} + +void __spm_get_wakeup_status(struct wake_status *wakesta, + unsigned int ext_status) +{ + wakesta->tr.comm.r12 = mmio_read_32(SPM_BK_WAKE_EVENT); + wakesta->tr.comm.timer_out = mmio_read_32(SPM_BK_PCM_TIMER); + wakesta->tr.comm.r13 = mmio_read_32(PCM_REG13_DATA); + wakesta->tr.comm.req_sta0 = mmio_read_32(SRC_REQ_STA_0); + wakesta->tr.comm.req_sta1 = mmio_read_32(SRC_REQ_STA_1); + wakesta->tr.comm.req_sta2 = mmio_read_32(SRC_REQ_STA_2); + wakesta->tr.comm.req_sta3 = mmio_read_32(SRC_REQ_STA_3); + wakesta->tr.comm.req_sta4 = mmio_read_32(SRC_REQ_STA_4); + wakesta->tr.comm.debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0); + wakesta->tr.comm.debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1); + + if ((ext_status & SPM_INTERNAL_STATUS_HW_S1) != 0U) { + wakesta->tr.comm.debug_flag |= (SPM_DBG_DEBUG_IDX_DDREN_WAKE | + SPM_DBG_DEBUG_IDX_DDREN_SLEEP); + mmio_write_32(PCM_WDT_LATCH_SPARE_0, + wakesta->tr.comm.debug_flag); + } + + wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); + wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); + + /* record below spm info for debug */ + wakesta->r12 = mmio_read_32(SPM_BK_WAKE_EVENT); + wakesta->r12_ext = mmio_read_32(SPM_WAKEUP_STA); + wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA); + wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA); + wakesta->md32pcm_wakeup_sta = mmio_read_32(MD32PCM_WAKEUP_STA); + wakesta->md32pcm_event_sta = mmio_read_32(MD32PCM_EVENT_STA); + wakesta->src_req = mmio_read_32(SPM_SRC_REQ); + + /* backup of SPM_WAKEUP_MISC */ + wakesta->wake_misc = mmio_read_32(SPM_BK_WAKE_MISC); + + /* get sleep time, backup of PCM_TIMER_OUT */ + wakesta->timer_out = mmio_read_32(SPM_BK_PCM_TIMER); + + /* get other SYS and co-clock status */ + wakesta->r13 = mmio_read_32(PCM_REG13_DATA); + wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA); + wakesta->req_sta0 = mmio_read_32(SRC_REQ_STA_0); + wakesta->req_sta1 = mmio_read_32(SRC_REQ_STA_1); + wakesta->req_sta2 = mmio_read_32(SRC_REQ_STA_2); + wakesta->req_sta3 = mmio_read_32(SRC_REQ_STA_3); + wakesta->req_sta4 = mmio_read_32(SRC_REQ_STA_4); + + /* get HW CG check status */ + wakesta->cg_check_sta = mmio_read_32(SPM_CG_CHECK_STA); + + /* get debug flag for PCM execution check */ + wakesta->debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0); + wakesta->debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1); + + /* get backup SW flag status */ + wakesta->b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); + wakesta->b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); + + wakesta->rt_req_sta0 = mmio_read_32(SPM_SW_RSV_2); + wakesta->rt_req_sta1 = mmio_read_32(SPM_SW_RSV_3); + wakesta->rt_req_sta2 = mmio_read_32(SPM_SW_RSV_4); + wakesta->rt_req_sta3 = mmio_read_32(SPM_SW_RSV_5); + wakesta->rt_req_sta4 = mmio_read_32(SPM_SW_RSV_6); + + /* get ISR status */ + wakesta->isr = mmio_read_32(SPM_IRQ_STA); + + /* get SW flag status */ + wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0); + wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1); + + /* get CLK SETTLE */ + wakesta->clk_settle = mmio_read_32(SPM_CLK_SETTLE); + + /* check abort */ + wakesta->abort = (wakesta->debug_flag & DEBUG_ABORT_MASK) | + (wakesta->debug_flag1 & DEBUG_ABORT_MASK_1); +} + +void __spm_clean_after_wakeup(void) +{ + mmio_write_32(SPM_BK_WAKE_EVENT, + mmio_read_32(SPM_WAKEUP_STA) | + mmio_read_32(SPM_BK_WAKE_EVENT)); + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0); + + /* + * clean wakeup event raw status (for edge trigger event) + * bit[28] for cpu wake up event + */ + mmio_write_32(SPM_WAKEUP_EVENT_MASK, SPM_WAKEUP_EVENT_MASK_CLEAN_MASK); + + /* clean ISR status (except TWAM) */ + mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM); + mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM); + mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL); +} + +void __spm_set_pcm_wdt(int en) +{ + mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_EN_LSB, + SPM_REGWR_CFG_KEY); + + if (en == 1) { + mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_WAKE_LSB, + SPM_REGWR_CFG_KEY); + + if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) { + mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX); + } + + mmio_write_32(PCM_WDT_VAL, + mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT); + mmio_setbits_32(PCM_CON1, + SPM_REGWR_CFG_KEY | RG_PCM_WDT_EN_LSB); + } +} + +void __spm_send_cpu_wakeup_event(void) +{ + /* SPM will clear SPM_CPU_WAKEUP_EVENT */ + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1); +} + +void __spm_ext_int_wakeup_req_clr(void) +{ + mmio_write_32(EXT_INT_WAKEUP_REQ_CLR, mmio_read_32(ROOT_CPUTOP_ADDR)); + + /* Clear spm2mcupm wakeup interrupt status */ + mmio_write_32(SPM2MCUPM_CON, 0); +} + +void __spm_xo_soc_bblpm(int en) +{ + if (en == 1) { + mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG, + RC_SW_SRCLKEN_FPM, RC_SW_SRCLKEN_RC); + assert(mt_spm_bblpm_cnt == 0); + mt_spm_bblpm_cnt += 1; + } else { + mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG, + RC_SW_SRCLKEN_RC, RC_SW_SRCLKEN_FPM); + mt_spm_bblpm_cnt -= 1; + } +} + +void __spm_hw_s1_state_monitor(int en, unsigned int *status) +{ + unsigned int reg; + + reg = mmio_read_32(SPM_ACK_CHK_CON_3); + + if (en == 1) { + reg &= ~SPM_ACK_CHK_3_CON_CLR_ALL; + mmio_write_32(SPM_ACK_CHK_CON_3, reg); + reg |= SPM_ACK_CHK_3_CON_EN; + mmio_write_32(SPM_ACK_CHK_CON_3, reg); + } else { + if (((reg & SPM_ACK_CHK_3_CON_RESULT) != 0U) && + (status != NULL)) { + *status |= SPM_INTERNAL_STATUS_HW_S1; + } + + mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_EN, + SPM_ACK_CHK_3_CON_HW_MODE_TRIG | + SPM_ACK_CHK_3_CON_CLR_ALL); + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h new file mode 100644 index 0000000..1d0f783 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_INTERNAL_H +#define MT_SPM_INTERNAL_H + +#include "mt_spm.h" + +/************************************** + * Config and Parameter + **************************************/ +#define POWER_ON_VAL0_DEF 0x0000F100 +#define POWER_ON_VAL1_DEF 0x80015860 +#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */ +#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT) + +/************************************** + * Define and Declare + **************************************/ +/* PCM_PWR_IO_EN */ +#define PCM_PWRIO_EN_R0 (1U << 0) +#define PCM_PWRIO_EN_R7 (1U << 7) +#define PCM_RF_SYNC_R0 (1U << 16) +#define PCM_RF_SYNC_R6 (1U << 22) +#define PCM_RF_SYNC_R7 (1U << 23) + +/* SPM_SWINT */ +#define PCM_SW_INT0 (1U << 0) +#define PCM_SW_INT1 (1U << 1) +#define PCM_SW_INT2 (1U << 2) +#define PCM_SW_INT3 (1U << 3) +#define PCM_SW_INT4 (1U << 4) +#define PCM_SW_INT5 (1U << 5) +#define PCM_SW_INT6 (1U << 6) +#define PCM_SW_INT7 (1U << 7) +#define PCM_SW_INT8 (1U << 8) +#define PCM_SW_INT9 (1U << 9) +#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \ + PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \ + PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \ + PCM_SW_INT0) + +/* SPM_AP_STANDBY_CON */ +#define WFI_OP_AND 1 +#define WFI_OP_OR 0 + +/* SPM_IRQ_MASK */ +#define ISRM_TWAM (1U << 2) +#define ISRM_PCM_RETURN (1U << 3) +#define ISRM_RET_IRQ0 (1U << 8) +#define ISRM_RET_IRQ1 (1U << 9) +#define ISRM_RET_IRQ2 (1U << 10) +#define ISRM_RET_IRQ3 (1U << 11) +#define ISRM_RET_IRQ4 (1U << 12) +#define ISRM_RET_IRQ5 (1U << 13) +#define ISRM_RET_IRQ6 (1U << 14) +#define ISRM_RET_IRQ7 (1U << 15) +#define ISRM_RET_IRQ8 (1U << 16) +#define ISRM_RET_IRQ9 (1U << 17) +#define ISRM_RET_IRQ_AUX ((ISRM_RET_IRQ9) | (ISRM_RET_IRQ8) | \ + (ISRM_RET_IRQ7) | (ISRM_RET_IRQ6) | \ + (ISRM_RET_IRQ5) | (ISRM_RET_IRQ4) | \ + (ISRM_RET_IRQ3) | (ISRM_RET_IRQ2) | \ + (ISRM_RET_IRQ1)) +#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX) +#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM) + +/* SPM_IRQ_STA */ +#define ISRS_TWAM (1U << 2) +#define ISRS_PCM_RETURN (1U << 3) +#define ISRC_TWAM ISRS_TWAM +#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN +#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM) + +/* SPM_WAKEUP_MISC */ +#define WAKE_MISC_GIC_WAKEUP 0x3FF +#define WAKE_MISC_DVFSRC_IRQ DVFSRC_IRQ_LSB +#define WAKE_MISC_REG_CPU_WAKEUP SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB +#define WAKE_MISC_PCM_TIMER_EVENT PCM_TIMER_EVENT_LSB +#define WAKE_MISC_PMIC_OUT_B ((1U << 19) | (1U << 20)) +#define WAKE_MISC_TWAM_IRQ_B TWAM_IRQ_B_LSB +#define WAKE_MISC_PMSR_IRQ_B_SET0 PMSR_IRQ_B_SET0_LSB +#define WAKE_MISC_PMSR_IRQ_B_SET1 PMSR_IRQ_B_SET1_LSB +#define WAKE_MISC_PMSR_IRQ_B_SET2 PMSR_IRQ_B_SET2_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_0 SPM_ACK_CHK_WAKEUP_0_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_1 SPM_ACK_CHK_WAKEUP_1_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_2 SPM_ACK_CHK_WAKEUP_2_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_3 SPM_ACK_CHK_WAKEUP_3_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_ALL SPM_ACK_CHK_WAKEUP_ALL_LSB +#define WAKE_MISC_PMIC_IRQ_ACK PMIC_IRQ_ACK_LSB +#define WAKE_MISC_PMIC_SCP_IRQ PMIC_SCP_IRQ_LSB + +/* ABORT MASK for DEBUG FOORTPRINT */ +#define DEBUG_ABORT_MASK \ + (SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC | \ + SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN) + +#define DEBUG_ABORT_MASK_1 \ + (SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT | \ + SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT | \ + SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT) + +#define MCUPM_MBOX_WAKEUP_CPU 0x0C55FD10 + +struct pwr_ctrl { + uint32_t pcm_flags; + uint32_t pcm_flags_cust; + uint32_t pcm_flags_cust_set; + uint32_t pcm_flags_cust_clr; + uint32_t pcm_flags1; + uint32_t pcm_flags1_cust; + uint32_t pcm_flags1_cust_set; + uint32_t pcm_flags1_cust_clr; + uint32_t timer_val; + uint32_t timer_val_cust; + uint32_t timer_val_ramp_en; + uint32_t timer_val_ramp_en_sec; + uint32_t wake_src; + uint32_t wake_src_cust; + uint32_t wakelock_timer_val; + uint8_t wdt_disable; + + /* Auto-gen Start */ + + /* SPM_CLK_CON */ + uint8_t reg_srcclken0_ctl; + uint8_t reg_srcclken1_ctl; + uint8_t reg_spm_lock_infra_dcm; + uint8_t reg_srcclken_mask; + uint8_t reg_md1_c32rm_en; + uint8_t reg_md2_c32rm_en; + uint8_t reg_clksq0_sel_ctrl; + uint8_t reg_clksq1_sel_ctrl; + uint8_t reg_srcclken0_en; + uint8_t reg_srcclken1_en; + uint32_t reg_sysclk0_src_mask_b; + uint32_t reg_sysclk1_src_mask_b; + + /* SPM_AP_STANDBY_CON */ + uint8_t reg_wfi_op; + uint8_t reg_wfi_type; + uint8_t reg_mp0_cputop_idle_mask; + uint8_t reg_mp1_cputop_idle_mask; + uint8_t reg_mcusys_idle_mask; + uint8_t reg_md_apsrc_1_sel; + uint8_t reg_md_apsrc_0_sel; + uint8_t reg_conn_apsrc_sel; + + /* SPM_SRC6_MASK */ + uint8_t reg_dpmaif_srcclkena_mask_b; + uint8_t reg_dpmaif_infra_req_mask_b; + uint8_t reg_dpmaif_apsrc_req_mask_b; + uint8_t reg_dpmaif_vrf18_req_mask_b; + uint8_t reg_dpmaif_ddr_en_mask_b; + /* SPM_SRC_REQ */ + uint8_t reg_spm_apsrc_req; + uint8_t reg_spm_f26m_req; + uint8_t reg_spm_infra_req; + uint8_t reg_spm_vrf18_req; + uint8_t reg_spm_ddr_en_req; + uint8_t reg_spm_dvfs_req; + uint8_t reg_spm_sw_mailbox_req; + uint8_t reg_spm_sspm_mailbox_req; + uint8_t reg_spm_adsp_mailbox_req; + uint8_t reg_spm_scp_mailbox_req; + + /* SPM_SRC_MASK */ + uint8_t reg_md_srcclkena_0_mask_b; + uint8_t reg_md_srcclkena2infra_req_0_mask_b; + uint8_t reg_md_apsrc2infra_req_0_mask_b; + uint8_t reg_md_apsrc_req_0_mask_b; + uint8_t reg_md_vrf18_req_0_mask_b; + uint8_t reg_md_ddr_en_0_mask_b; + uint8_t reg_md_srcclkena_1_mask_b; + uint8_t reg_md_srcclkena2infra_req_1_mask_b; + uint8_t reg_md_apsrc2infra_req_1_mask_b; + uint8_t reg_md_apsrc_req_1_mask_b; + uint8_t reg_md_vrf18_req_1_mask_b; + uint8_t reg_md_ddr_en_1_mask_b; + uint8_t reg_conn_srcclkena_mask_b; + uint8_t reg_conn_srcclkenb_mask_b; + uint8_t reg_conn_infra_req_mask_b; + uint8_t reg_conn_apsrc_req_mask_b; + uint8_t reg_conn_vrf18_req_mask_b; + uint8_t reg_conn_ddr_en_mask_b; + uint8_t reg_conn_vfe28_mask_b; + uint8_t reg_srcclkeni0_srcclkena_mask_b; + uint8_t reg_srcclkeni0_infra_req_mask_b; + uint8_t reg_srcclkeni1_srcclkena_mask_b; + uint8_t reg_srcclkeni1_infra_req_mask_b; + uint8_t reg_srcclkeni2_srcclkena_mask_b; + uint8_t reg_srcclkeni2_infra_req_mask_b; + uint8_t reg_infrasys_apsrc_req_mask_b; + uint8_t reg_infrasys_ddr_en_mask_b; + uint8_t reg_md32_srcclkena_mask_b; + uint8_t reg_md32_infra_req_mask_b; + uint8_t reg_md32_apsrc_req_mask_b; + uint8_t reg_md32_vrf18_req_mask_b; + uint8_t reg_md32_ddr_en_mask_b; + + /* SPM_SRC2_MASK */ + uint8_t reg_scp_srcclkena_mask_b; + uint8_t reg_scp_infra_req_mask_b; + uint8_t reg_scp_apsrc_req_mask_b; + uint8_t reg_scp_vrf18_req_mask_b; + uint8_t reg_scp_ddr_en_mask_b; + uint8_t reg_audio_dsp_srcclkena_mask_b; + uint8_t reg_audio_dsp_infra_req_mask_b; + uint8_t reg_audio_dsp_apsrc_req_mask_b; + uint8_t reg_audio_dsp_vrf18_req_mask_b; + uint8_t reg_audio_dsp_ddr_en_mask_b; + uint8_t reg_ufs_srcclkena_mask_b; + uint8_t reg_ufs_infra_req_mask_b; + uint8_t reg_ufs_apsrc_req_mask_b; + uint8_t reg_ufs_vrf18_req_mask_b; + uint8_t reg_ufs_ddr_en_mask_b; + uint8_t reg_disp0_apsrc_req_mask_b; + uint8_t reg_disp0_ddr_en_mask_b; + uint8_t reg_disp1_apsrc_req_mask_b; + uint8_t reg_disp1_ddr_en_mask_b; + uint8_t reg_gce_infra_req_mask_b; + uint8_t reg_gce_apsrc_req_mask_b; + uint8_t reg_gce_vrf18_req_mask_b; + uint8_t reg_gce_ddr_en_mask_b; + uint8_t reg_apu_srcclkena_mask_b; + uint8_t reg_apu_infra_req_mask_b; + uint8_t reg_apu_apsrc_req_mask_b; + uint8_t reg_apu_vrf18_req_mask_b; + uint8_t reg_apu_ddr_en_mask_b; + uint8_t reg_cg_check_srcclkena_mask_b; + uint8_t reg_cg_check_apsrc_req_mask_b; + uint8_t reg_cg_check_vrf18_req_mask_b; + uint8_t reg_cg_check_ddr_en_mask_b; + + /* SPM_SRC3_MASK */ + uint8_t reg_dvfsrc_event_trigger_mask_b; + uint8_t reg_sw2spm_int0_mask_b; + uint8_t reg_sw2spm_int1_mask_b; + uint8_t reg_sw2spm_int2_mask_b; + uint8_t reg_sw2spm_int3_mask_b; + uint8_t reg_sc_adsp2spm_wakeup_mask_b; + uint8_t reg_sc_sspm2spm_wakeup_mask_b; + uint8_t reg_sc_scp2spm_wakeup_mask_b; + uint8_t reg_csyspwrreq_mask; + uint8_t reg_spm_srcclkena_reserved_mask_b; + uint8_t reg_spm_infra_req_reserved_mask_b; + uint8_t reg_spm_apsrc_req_reserved_mask_b; + uint8_t reg_spm_vrf18_req_reserved_mask_b; + uint8_t reg_spm_ddr_en_reserved_mask_b; + uint8_t reg_mcupm_srcclkena_mask_b; + uint8_t reg_mcupm_infra_req_mask_b; + uint8_t reg_mcupm_apsrc_req_mask_b; + uint8_t reg_mcupm_vrf18_req_mask_b; + uint8_t reg_mcupm_ddr_en_mask_b; + uint8_t reg_msdc0_srcclkena_mask_b; + uint8_t reg_msdc0_infra_req_mask_b; + uint8_t reg_msdc0_apsrc_req_mask_b; + uint8_t reg_msdc0_vrf18_req_mask_b; + uint8_t reg_msdc0_ddr_en_mask_b; + uint8_t reg_msdc1_srcclkena_mask_b; + uint8_t reg_msdc1_infra_req_mask_b; + uint8_t reg_msdc1_apsrc_req_mask_b; + uint8_t reg_msdc1_vrf18_req_mask_b; + uint8_t reg_msdc1_ddr_en_mask_b; + + /* SPM_SRC4_MASK */ + uint32_t ccif_event_mask_b; + uint8_t reg_bak_psri_srcclkena_mask_b; + uint8_t reg_bak_psri_infra_req_mask_b; + uint8_t reg_bak_psri_apsrc_req_mask_b; + uint8_t reg_bak_psri_vrf18_req_mask_b; + uint8_t reg_bak_psri_ddr_en_mask_b; + uint8_t reg_dramc0_md32_infra_req_mask_b; + uint8_t reg_dramc0_md32_vrf18_req_mask_b; + uint8_t reg_dramc1_md32_infra_req_mask_b; + uint8_t reg_dramc1_md32_vrf18_req_mask_b; + uint8_t reg_conn_srcclkenb2pwrap_mask_b; + uint8_t reg_dramc0_md32_wakeup_mask; + uint8_t reg_dramc1_md32_wakeup_mask; + + /* SPM_SRC5_MASK */ + uint32_t reg_mcusys_merge_apsrc_req_mask_b; + uint32_t reg_mcusys_merge_ddr_en_mask_b; + uint8_t reg_msdc2_srcclkena_mask_b; + uint8_t reg_msdc2_infra_req_mask_b; + uint8_t reg_msdc2_apsrc_req_mask_b; + uint8_t reg_msdc2_vrf18_req_mask_b; + uint8_t reg_msdc2_ddr_en_mask_b; + uint8_t reg_pcie_srcclkena_mask_b; + uint8_t reg_pcie_infra_req_mask_b; + uint8_t reg_pcie_apsrc_req_mask_b; + uint8_t reg_pcie_vrf18_req_mask_b; + uint8_t reg_pcie_ddr_en_mask_b; + + /* SPM_WAKEUP_EVENT_MASK */ + uint32_t reg_wakeup_event_mask; + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + uint32_t reg_ext_wakeup_event_mask; + + /* Auto-gen End */ +}; + +/* code gen by spm_pwr_ctrl_atf.pl, need struct pwr_ctrl */ +enum pwr_ctrl_enum { + PW_PCM_FLAGS, + PW_PCM_FLAGS_CUST, + PW_PCM_FLAGS_CUST_SET, + PW_PCM_FLAGS_CUST_CLR, + PW_PCM_FLAGS1, + PW_PCM_FLAGS1_CUST, + PW_PCM_FLAGS1_CUST_SET, + PW_PCM_FLAGS1_CUST_CLR, + PW_TIMER_VAL, + PW_TIMER_VAL_CUST, + PW_TIMER_VAL_RAMP_EN, + PW_TIMER_VAL_RAMP_EN_SEC, + PW_WAKE_SRC, + PW_WAKE_SRC_CUST, + PW_WAKELOCK_TIMER_VAL, + PW_WDT_DISABLE, + + /* SPM_CLK_CON */ + PW_REG_SRCCLKEN0_CTL, + PW_REG_SRCCLKEN1_CTL, + PW_REG_SPM_LOCK_INFRA_DCM, + PW_REG_SRCCLKEN_MASK, + PW_REG_MD1_C32RM_EN, + PW_REG_MD2_C32RM_EN, + PW_REG_CLKSQ0_SEL_CTRL, + PW_REG_CLKSQ1_SEL_CTRL, + PW_REG_SRCCLKEN0_EN, + PW_REG_SRCCLKEN1_EN, + PW_REG_SYSCLK0_SRC_MASK_B, + PW_REG_SYSCLK1_SRC_MASK_B, + + /* SPM_AP_STANDBY_CON */ + PW_REG_WFI_OP, + PW_REG_WFI_TYPE, + PW_REG_MP0_CPUTOP_IDLE_MASK, + PW_REG_MP1_CPUTOP_IDLE_MASK, + PW_REG_MCUSYS_IDLE_MASK, + PW_REG_MD_APSRC_1_SEL, + PW_REG_MD_APSRC_0_SEL, + PW_REG_CONN_APSRC_SEL, + + /* SPM_SRC6_MASK */ + PW_REG_DPMAIF_SRCCLKENA_MASK_B, + PW_REG_DPMAIF_INFRA_REQ_MASK_B, + PW_REG_DPMAIF_APSRC_REQ_MASK_B, + PW_REG_DPMAIF_VRF18_REQ_MASK_B, + PW_REG_DPMAIF_DDR_EN_MASK_B, + + /* SPM_SRC_REQ */ + PW_REG_SPM_APSRC_REQ, + PW_REG_SPM_F26M_REQ, + PW_REG_SPM_INFRA_REQ, + PW_REG_SPM_VRF18_REQ, + PW_REG_SPM_DDR_EN_REQ, + PW_REG_SPM_DVFS_REQ, + PW_REG_SPM_SW_MAILBOX_REQ, + PW_REG_SPM_SSPM_MAILBOX_REQ, + PW_REG_SPM_ADSP_MAILBOX_REQ, + PW_REG_SPM_SCP_MAILBOX_REQ, + + /* SPM_SRC_MASK */ + PW_REG_MD_SRCCLKENA_0_MASK_B, + PW_REG_MD_SRCCLKENA2INFRA_REQ_0_MASK_B, + PW_REG_MD_APSRC2INFRA_REQ_0_MASK_B, + PW_REG_MD_APSRC_REQ_0_MASK_B, + PW_REG_MD_VRF18_REQ_0_MASK_B, + PW_REG_MD_DDR_EN_0_MASK_B, + PW_REG_MD_SRCCLKENA_1_MASK_B, + PW_REG_MD_SRCCLKENA2INFRA_REQ_1_MASK_B, + PW_REG_MD_APSRC2INFRA_REQ_1_MASK_B, + PW_REG_MD_APSRC_REQ_1_MASK_B, + PW_REG_MD_VRF18_REQ_1_MASK_B, + PW_REG_MD_DDR_EN_1_MASK_B, + PW_REG_CONN_SRCCLKENA_MASK_B, + PW_REG_CONN_SRCCLKENB_MASK_B, + PW_REG_CONN_INFRA_REQ_MASK_B, + PW_REG_CONN_APSRC_REQ_MASK_B, + PW_REG_CONN_VRF18_REQ_MASK_B, + PW_REG_CONN_DDR_EN_MASK_B, + PW_REG_CONN_VFE28_MASK_B, + PW_REG_SRCCLKENI0_SRCCLKENA_MASK_B, + PW_REG_SRCCLKENI0_INFRA_REQ_MASK_B, + PW_REG_SRCCLKENI1_SRCCLKENA_MASK_B, + PW_REG_SRCCLKENI1_INFRA_REQ_MASK_B, + PW_REG_SRCCLKENI2_SRCCLKENA_MASK_B, + PW_REG_SRCCLKENI2_INFRA_REQ_MASK_B, + PW_REG_INFRASYS_APSRC_REQ_MASK_B, + PW_REG_INFRASYS_DDR_EN_MASK_B, + PW_REG_MD32_SRCCLKENA_MASK_B, + PW_REG_MD32_INFRA_REQ_MASK_B, + PW_REG_MD32_APSRC_REQ_MASK_B, + PW_REG_MD32_VRF18_REQ_MASK_B, + PW_REG_MD32_DDR_EN_MASK_B, + + /* SPM_SRC2_MASK */ + PW_REG_SCP_SRCCLKENA_MASK_B, + PW_REG_SCP_INFRA_REQ_MASK_B, + PW_REG_SCP_APSRC_REQ_MASK_B, + PW_REG_SCP_VRF18_REQ_MASK_B, + PW_REG_SCP_DDR_EN_MASK_B, + PW_REG_AUDIO_DSP_SRCCLKENA_MASK_B, + PW_REG_AUDIO_DSP_INFRA_REQ_MASK_B, + PW_REG_AUDIO_DSP_APSRC_REQ_MASK_B, + PW_REG_AUDIO_DSP_VRF18_REQ_MASK_B, + PW_REG_AUDIO_DSP_DDR_EN_MASK_B, + PW_REG_UFS_SRCCLKENA_MASK_B, + PW_REG_UFS_INFRA_REQ_MASK_B, + PW_REG_UFS_APSRC_REQ_MASK_B, + PW_REG_UFS_VRF18_REQ_MASK_B, + PW_REG_UFS_DDR_EN_MASK_B, + PW_REG_DISP0_APSRC_REQ_MASK_B, + PW_REG_DISP0_DDR_EN_MASK_B, + PW_REG_DISP1_APSRC_REQ_MASK_B, + PW_REG_DISP1_DDR_EN_MASK_B, + PW_REG_GCE_INFRA_REQ_MASK_B, + PW_REG_GCE_APSRC_REQ_MASK_B, + PW_REG_GCE_VRF18_REQ_MASK_B, + PW_REG_GCE_DDR_EN_MASK_B, + PW_REG_APU_SRCCLKENA_MASK_B, + PW_REG_APU_INFRA_REQ_MASK_B, + PW_REG_APU_APSRC_REQ_MASK_B, + PW_REG_APU_VRF18_REQ_MASK_B, + PW_REG_APU_DDR_EN_MASK_B, + PW_REG_CG_CHECK_SRCCLKENA_MASK_B, + PW_REG_CG_CHECK_APSRC_REQ_MASK_B, + PW_REG_CG_CHECK_VRF18_REQ_MASK_B, + PW_REG_CG_CHECK_DDR_EN_MASK_B, + + /* SPM_SRC3_MASK */ + PW_REG_DVFSRC_EVENT_TRIGGER_MASK_B, + PW_REG_SW2SPM_INT0_MASK_B, + PW_REG_SW2SPM_INT1_MASK_B, + PW_REG_SW2SPM_INT2_MASK_B, + PW_REG_SW2SPM_INT3_MASK_B, + PW_REG_SC_ADSP2SPM_WAKEUP_MASK_B, + PW_REG_SC_SSPM2SPM_WAKEUP_MASK_B, + PW_REG_SC_SCP2SPM_WAKEUP_MASK_B, + PW_REG_CSYSPWRREQ_MASK, + PW_REG_SPM_SRCCLKENA_RESERVED_MASK_B, + PW_REG_SPM_INFRA_REQ_RESERVED_MASK_B, + PW_REG_SPM_APSRC_REQ_RESERVED_MASK_B, + PW_REG_SPM_VRF18_REQ_RESERVED_MASK_B, + PW_REG_SPM_DDR_EN_RESERVED_MASK_B, + PW_REG_MCUPM_SRCCLKENA_MASK_B, + PW_REG_MCUPM_INFRA_REQ_MASK_B, + PW_REG_MCUPM_APSRC_REQ_MASK_B, + PW_REG_MCUPM_VRF18_REQ_MASK_B, + PW_REG_MCUPM_DDR_EN_MASK_B, + PW_REG_MSDC0_SRCCLKENA_MASK_B, + PW_REG_MSDC0_INFRA_REQ_MASK_B, + PW_REG_MSDC0_APSRC_REQ_MASK_B, + PW_REG_MSDC0_VRF18_REQ_MASK_B, + PW_REG_MSDC0_DDR_EN_MASK_B, + PW_REG_MSDC1_SRCCLKENA_MASK_B, + PW_REG_MSDC1_INFRA_REQ_MASK_B, + PW_REG_MSDC1_APSRC_REQ_MASK_B, + PW_REG_MSDC1_VRF18_REQ_MASK_B, + PW_REG_MSDC1_DDR_EN_MASK_B, + + /* SPM_SRC4_MASK */ + PW_CCIF_EVENT_MASK_B, + PW_REG_BAK_PSRI_SRCCLKENA_MASK_B, + PW_REG_BAK_PSRI_INFRA_REQ_MASK_B, + PW_REG_BAK_PSRI_APSRC_REQ_MASK_B, + PW_REG_BAK_PSRI_VRF18_REQ_MASK_B, + PW_REG_BAK_PSRI_DDR_EN_MASK_B, + PW_REG_DRAMC0_MD32_INFRA_REQ_MASK_B, + PW_REG_DRAMC0_MD32_VRF18_REQ_MASK_B, + PW_REG_DRAMC1_MD32_INFRA_REQ_MASK_B, + PW_REG_DRAMC1_MD32_VRF18_REQ_MASK_B, + PW_REG_CONN_SRCCLKENB2PWRAP_MASK_B, + PW_REG_DRAMC0_MD32_WAKEUP_MASK, + PW_REG_DRAMC1_MD32_WAKEUP_MASK, + + /* SPM_SRC5_MASK */ + PW_REG_MCUSYS_MERGE_APSRC_REQ_MASK_B, + PW_REG_MCUSYS_MERGE_DDR_EN_MASK_B, + PW_REG_MSDC2_SRCCLKENA_MASK_B, + PW_REG_MSDC2_INFRA_REQ_MASK_B, + PW_REG_MSDC2_APSRC_REQ_MASK_B, + PW_REG_MSDC2_VRF18_REQ_MASK_B, + PW_REG_MSDC2_DDR_EN_MASK_B, + PW_REG_PCIE_SRCCLKENA_MASK_B, + PW_REG_PCIE_INFRA_REQ_MASK_B, + PW_REG_PCIE_APSRC_REQ_MASK_B, + PW_REG_PCIE_VRF18_REQ_MASK_B, + PW_REG_PCIE_DDR_EN_MASK_B, + + /* SPM_WAKEUP_EVENT_MASK */ + PW_REG_WAKEUP_EVENT_MASK, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + PW_REG_EXT_WAKEUP_EVENT_MASK, + + PW_MAX_COUNT, +}; + +#define SPM_INTERNAL_STATUS_HW_S1 (1U << 0) +#define SPM_ACK_CHK_3_SEL_HW_S1 0x00350098 +#define SPM_ACK_CHK_3_HW_S1_CNT 1 +#define SPM_ACK_CHK_3_CON_HW_MODE_TRIG 0x800 +#define SPM_ACK_CHK_3_CON_EN 0x110 +#define SPM_ACK_CHK_3_CON_CLR_ALL 0x2 +#define SPM_ACK_CHK_3_CON_RESULT 0x8000 + +struct wake_status_trace_comm { + uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */ + uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */ + uint32_t timer_out; /* SPM_SW_RSV_6*/ + uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */ + uint32_t b_sw_flag1; /* SPM_SW_RSV_7 */ + uint32_t r12; /* SPM_SW_RSV_0 */ + uint32_t r13; /* PCM_REG13_DATA */ + uint32_t req_sta0; /* SRC_REQ_STA_0 */ + uint32_t req_sta1; /* SRC_REQ_STA_1 */ + uint32_t req_sta2; /* SRC_REQ_STA_2 */ + uint32_t req_sta3; /* SRC_REQ_STA_3 */ + uint32_t req_sta4; /* SRC_REQ_STA_4 */ +}; + +struct wake_status_trace { + struct wake_status_trace_comm comm; +}; + +struct wake_status { + struct wake_status_trace tr; + uint32_t r12; /* SPM_BK_WAKE_EVENT */ + uint32_t r12_ext; /* SPM_WAKEUP_EXT_STA */ + uint32_t raw_sta; /* SPM_WAKEUP_STA */ + uint32_t raw_ext_sta; /* SPM_WAKEUP_EXT_STA */ + uint32_t md32pcm_wakeup_sta; /* MD32CPM_WAKEUP_STA */ + uint32_t md32pcm_event_sta; /* MD32PCM_EVENT_STA */ + uint32_t wake_misc; /* SPM_BK_WAKE_MISC */ + uint32_t timer_out; /* SPM_BK_PCM_TIMER */ + uint32_t r13; /* PCM_REG13_DATA */ + uint32_t idle_sta; /* SUBSYS_IDLE_STA */ + uint32_t req_sta0; /* SRC_REQ_STA_0 */ + uint32_t req_sta1; /* SRC_REQ_STA_1 */ + uint32_t req_sta2; /* SRC_REQ_STA_2 */ + uint32_t req_sta3; /* SRC_REQ_STA_3 */ + uint32_t req_sta4; /* SRC_REQ_STA_4 */ + uint32_t cg_check_sta; /* SPM_CG_CHECK_STA */ + uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */ + uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */ + uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */ + uint32_t b_sw_flag1; /* SPM_SW_RSV_8 */ + uint32_t isr; /* SPM_IRQ_STA */ + uint32_t sw_flag0; /* SPM_SW_FLAG_0 */ + uint32_t sw_flag1; /* SPM_SW_FLAG_1 */ + uint32_t clk_settle; /* SPM_CLK_SETTLE */ + uint32_t src_req; /* SPM_SRC_REQ */ + uint32_t log_index; + uint32_t abort; + uint32_t rt_req_sta0; /* SPM_SW_RSV_2 */ + uint32_t rt_req_sta1; /* SPM_SW_RSV_3 */ + uint32_t rt_req_sta2; /* SPM_SW_RSV_4 */ + uint32_t rt_req_sta3; /* SPM_SW_RSV_5 */ + uint32_t rt_req_sta4; /* SPM_SW_RSV_6 */ + uint32_t mcupm_req_sta; +}; + +struct spm_lp_scen { + struct pcm_desc *pcmdesc; + struct pwr_ctrl *pwrctrl; +}; + +extern struct spm_lp_scen __spm_vcorefs; +extern void __spm_set_cpu_status(unsigned int cpu); +extern void __spm_reset_and_init_pcm(const struct pcm_desc *pcmdesc); +extern void __spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc); +extern void __spm_init_pcm_register(void); +extern void __spm_src_req_update(const struct pwr_ctrl *pwrctrl, + unsigned int resource_usage); +extern void __spm_set_power_control(const struct pwr_ctrl *pwrctrl); +extern void __spm_disable_pcm_timer(void); +extern void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl); +extern void __spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl); +extern void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl); +extern void __spm_send_cpu_wakeup_event(void); +extern void __spm_get_wakeup_status(struct wake_status *wakesta, + unsigned int ext_status); +extern void __spm_clean_after_wakeup(void); +extern wake_reason_t +__spm_output_wake_reason(int state_id, const struct wake_status *wakesta); +extern void +__spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl, + const struct pwr_ctrl *src_pwr_ctrl); +extern void __spm_set_pcm_wdt(int en); +extern uint32_t _spm_get_wake_period(int pwake_time, wake_reason_t last_wr); +extern void __spm_set_fw_resume_option(struct pwr_ctrl *pwrctrl); +extern void __spm_ext_int_wakeup_req_clr(void); +extern void __spm_xo_soc_bblpm(int en); + +static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl, + uint32_t flags) +{ + if (pwrctrl->pcm_flags_cust == 0U) { + pwrctrl->pcm_flags = flags; + } else { + pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust; + } +} + +static inline void set_pwrctrl_pcm_flags1(struct pwr_ctrl *pwrctrl, + uint32_t flags) +{ + if (pwrctrl->pcm_flags1_cust == 0U) { + pwrctrl->pcm_flags1 = flags; + } else { + pwrctrl->pcm_flags1 = pwrctrl->pcm_flags1_cust; + } +} + +extern void __spm_hw_s1_state_monitor(int en, unsigned int *status); + +static inline void spm_hw_s1_state_monitor_resume(void) +{ + __spm_hw_s1_state_monitor(1, NULL); +} + +static inline void spm_hw_s1_state_monitor_pause(unsigned int *status) +{ + __spm_hw_s1_state_monitor(0, status); +} +#endif /* MT_SPM_INTERNAL_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c new file mode 100644 index 0000000..4e5f6a0 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* PMIC_WRAP MT6359 */ +#define VCORE_BASE_UV 40000 +#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625) +#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + VCORE_BASE_UV) + +#define NR_PMIC_WRAP_CMD (NR_IDX_ALL) +#define SPM_DATA_SHIFT 16 + +#define BUCK_VGPU11_ELR0 0x15B4 +#define TOP_SPI_CON0 0x0456 +#define BUCK_TOP_CON1 0x1443 +#define TOP_CON 0x0013 +#define TOP_DIG_WPK 0x03a9 +#define TOP_CON_LOCK 0x03a8 +#define TOP_CLK_CON0 0x0134 + +struct pmic_wrap_cmd { + unsigned long cmd_addr; + unsigned long cmd_wdata; +}; + +struct pmic_wrap_setting { + enum pmic_wrap_phase_id phase; + struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD]; + struct { + struct { + unsigned long cmd_addr; + unsigned long cmd_wdata; + } _[NR_PMIC_WRAP_CMD]; + const int nr_idx; + } set[NR_PMIC_WRAP_PHASE]; +}; + +static struct pmic_wrap_setting pw = { + .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */ + .addr = { {0UL, 0UL} }, + .set[PMIC_WRAP_PHASE_ALLINONE] = { + ._[CMD_0] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(72500),}, + ._[CMD_1] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(65000),}, + ._[CMD_2] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(60000),}, + ._[CMD_3] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(57500),}, + ._[CMD_4] = {TOP_SPI_CON0, 0x1,}, + ._[CMD_5] = {TOP_SPI_CON0, 0x0,}, + ._[CMD_6] = {BUCK_TOP_CON1, 0x0,}, + ._[CMD_7] = {BUCK_TOP_CON1, 0xf,}, + ._[CMD_8] = {TOP_CON, 0x3,}, + ._[CMD_9] = {TOP_CON, 0x0,}, + ._[CMD_10] = {TOP_DIG_WPK, 0x63,}, + ._[CMD_11] = {TOP_CON_LOCK, 0x15,}, + ._[CMD_12] = {TOP_DIG_WPK, 0x0,}, + ._[CMD_13] = {TOP_CON_LOCK, 0x0,}, + ._[CMD_14] = {TOP_CLK_CON0, 0x40,}, + ._[CMD_15] = {TOP_CLK_CON0, 0x0,}, + .nr_idx = NR_IDX_ALL, + }, +}; + +void _mt_spm_pmic_table_init(void) +{ + struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = { + {(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,}, + {(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,}, + {(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,}, + {(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,}, + {(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,}, + {(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,}, + {(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,}, + {(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,}, + {(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,}, + {(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,}, + {(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,}, + {(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,}, + {(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,}, + {(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,}, + {(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,}, + {(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,}, + }; + + memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default)); +} + +void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase) +{ + uint32_t idx, addr, data; + + if (phase >= NR_PMIC_WRAP_PHASE) { + return; + } + + if (pw.phase == phase) { + return; + } + + if (pw.addr[0].cmd_addr == 0UL) { + _mt_spm_pmic_table_init(); + } + + pw.phase = phase; + mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); + + for (idx = 0U; idx < pw.set[phase].nr_idx; idx++) { + addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; + data = pw.set[phase]._[idx].cmd_wdata; + mmio_write_32(pw.addr[idx].cmd_addr, addr | data); + } +} + +void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx, + uint32_t cmd_wdata) +{ + uint32_t addr; + + if (phase >= NR_PMIC_WRAP_PHASE) { + return; + } + + if (idx >= pw.set[phase].nr_idx) { + return; + } + + pw.set[phase]._[idx].cmd_wdata = cmd_wdata; + mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); + + if (pw.phase == phase) { + addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; + mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata); + } +} + +uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx) +{ + if (phase >= NR_PMIC_WRAP_PHASE) { + return 0UL; + } + + if (idx >= pw.set[phase].nr_idx) { + return 0UL; + } + + return pw.set[phase]._[idx].cmd_wdata; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h new file mode 100644 index 0000000..6e20916 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/**************************************************************** + * Auto generated by DE, please DO NOT modify this file directly. + *****************************************************************/ +#ifndef MT_SPM_PMIC_WRAP_H +#define MT_SPM_PMIC_WRAP_H + +enum pmic_wrap_phase_id { + PMIC_WRAP_PHASE_ALLINONE, + NR_PMIC_WRAP_PHASE, +}; + +/* IDX mapping, PMIC_WRAP_PHASE_ALLINONE */ +enum { + CMD_0, /* 0x0 */ + CMD_1, /* 0x1 */ + CMD_2, /* 0x2 */ + CMD_3, /* 0x3 */ + CMD_4, /* 0x4 */ + CMD_5, /* 0x5 */ + CMD_6, /* 0x6 */ + CMD_7, /* 0x7 */ + CMD_8, /* 0x8 */ + CMD_9, /* 0x9 */ + CMD_10, /* 0xA */ + CMD_11, /* 0xB */ + CMD_12, /* 0xC */ + CMD_13, /* 0xD */ + CMD_14, /* 0xE */ + CMD_15, /* 0xF */ + NR_IDX_ALL, +}; + +/* APIs */ +extern void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase); +extern void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, + uint32_t idx, uint32_t cmd_wdata); +extern uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, + uint32_t idx); +#endif /* MT_SPM_PMIC_WRAP_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h new file mode 100644 index 0000000..fba011d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h @@ -0,0 +1,2919 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/**************************************************************** + * Auto generated by DE, please DO NOT modify this file directly. + *****************************************************************/ +#ifndef MT_SPM_REG +#define MT_SPM_REG + +#include "pcm_def.h" +#include +#include "sleep_def.h" + +/************************************** + * Define and Declare + **************************************/ +#define POWERON_CONFIG_EN (SPM_BASE + 0x000) +#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004) +#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008) +#define SPM_CLK_CON (SPM_BASE + 0x00C) +#define SPM_CLK_SETTLE (SPM_BASE + 0x010) +#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014) +#define PCM_CON0 (SPM_BASE + 0x018) +#define PCM_CON1 (SPM_BASE + 0x01C) +#define SPM_POWER_ON_VAL2 (SPM_BASE + 0x020) +#define SPM_POWER_ON_VAL3 (SPM_BASE + 0x024) +#define PCM_REG_DATA_INI (SPM_BASE + 0x028) +#define PCM_PWR_IO_EN (SPM_BASE + 0x02C) +#define PCM_TIMER_VAL (SPM_BASE + 0x030) +#define PCM_WDT_VAL (SPM_BASE + 0x034) +#define SPM_SRC6_MASK (SPM_BASE + 0x038) +#define SPM_SW_RST_CON (SPM_BASE + 0x040) +#define SPM_SW_RST_CON_SET (SPM_BASE + 0x044) +#define SPM_SW_RST_CON_CLR (SPM_BASE + 0x048) +#define VS1_PSR_MASK_B (SPM_BASE + 0x04C) +#define VS2_PSR_MASK_B (SPM_BASE + 0x050) +#define MD32_CLK_CON (SPM_BASE + 0x084) +#define SPM_SRAM_RSV_CON (SPM_BASE + 0x088) +#define SPM_SWINT (SPM_BASE + 0x08C) +#define SPM_SWINT_SET (SPM_BASE + 0x090) +#define SPM_SWINT_CLR (SPM_BASE + 0x094) +#define SPM_SCP_MAILBOX (SPM_BASE + 0x098) +#define SCP_SPM_MAILBOX (SPM_BASE + 0x09C) +#define SPM_TWAM_CON (SPM_BASE + 0x0A0) +#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x0A4) +#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x0A8) +#define SPM_SCP_IRQ (SPM_BASE + 0x0AC) +#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x0B0) +#define SPM_IRQ_MASK (SPM_BASE + 0x0B4) +#define SPM_SRC_REQ (SPM_BASE + 0x0B8) +#define SPM_SRC_MASK (SPM_BASE + 0x0BC) +#define SPM_SRC2_MASK (SPM_BASE + 0x0C0) +#define SPM_SRC3_MASK (SPM_BASE + 0x0C4) +#define SPM_SRC4_MASK (SPM_BASE + 0x0C8) +#define SPM_SRC5_MASK (SPM_BASE + 0x0CC) +#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x0D0) +#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0D4) +#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x0D8) +#define SCP_CLK_CON (SPM_BASE + 0x0DC) +#define PCM_DEBUG_CON (SPM_BASE + 0x0E0) +#define AHB_BUS_CON (SPM_BASE + 0x0E4) +#define DDR_EN_DBC_CON0 (SPM_BASE + 0x0E8) +#define DDR_EN_DBC_CON1 (SPM_BASE + 0x0EC) +#define SPM_RESOURCE_ACK_CON0 (SPM_BASE + 0x0F0) +#define SPM_RESOURCE_ACK_CON1 (SPM_BASE + 0x0F4) +#define SPM_RESOURCE_ACK_CON2 (SPM_BASE + 0x0F8) +#define SPM_RESOURCE_ACK_CON3 (SPM_BASE + 0x0FC) +#define PCM_REG0_DATA (SPM_BASE + 0x100) +#define PCM_REG2_DATA (SPM_BASE + 0x104) +#define PCM_REG6_DATA (SPM_BASE + 0x108) +#define PCM_REG7_DATA (SPM_BASE + 0x10C) +#define PCM_REG13_DATA (SPM_BASE + 0x110) +#define SRC_REQ_STA_0 (SPM_BASE + 0x114) +#define SRC_REQ_STA_1 (SPM_BASE + 0x118) +#define SRC_REQ_STA_2 (SPM_BASE + 0x11C) +#define PCM_TIMER_OUT (SPM_BASE + 0x120) +#define PCM_WDT_OUT (SPM_BASE + 0x124) +#define SPM_IRQ_STA (SPM_BASE + 0x128) +#define SRC_REQ_STA_4 (SPM_BASE + 0x12C) +#define MD32PCM_WAKEUP_STA (SPM_BASE + 0x130) +#define MD32PCM_EVENT_STA (SPM_BASE + 0x134) +#define SPM_WAKEUP_STA (SPM_BASE + 0x138) +#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x13C) +#define SPM_WAKEUP_MISC (SPM_BASE + 0x140) +#define MM_DVFS_HALT (SPM_BASE + 0x144) +#define BUS_PROTECT_RDY (SPM_BASE + 0x150) +#define BUS_PROTECT1_RDY (SPM_BASE + 0x154) +#define BUS_PROTECT2_RDY (SPM_BASE + 0x158) +#define BUS_PROTECT3_RDY (SPM_BASE + 0x15C) +#define SUBSYS_IDLE_STA (SPM_BASE + 0x160) +#define PCM_STA (SPM_BASE + 0x164) +#define SRC_REQ_STA_3 (SPM_BASE + 0x168) +#define PWR_STATUS (SPM_BASE + 0x16C) +#define PWR_STATUS_2ND (SPM_BASE + 0x170) +#define CPU_PWR_STATUS (SPM_BASE + 0x174) +#define OTHER_PWR_STATUS (SPM_BASE + 0x178) +#define SPM_VTCXO_EVENT_COUNT_STA (SPM_BASE + 0x17C) +#define SPM_INFRA_EVENT_COUNT_STA (SPM_BASE + 0x180) +#define SPM_VRF18_EVENT_COUNT_STA (SPM_BASE + 0x184) +#define SPM_APSRC_EVENT_COUNT_STA (SPM_BASE + 0x188) +#define SPM_DDREN_EVENT_COUNT_STA (SPM_BASE + 0x18C) +#define MD32PCM_STA (SPM_BASE + 0x190) +#define MD32PCM_PC (SPM_BASE + 0x194) +#define DVFSRC_EVENT_STA (SPM_BASE + 0x1A4) +#define BUS_PROTECT4_RDY (SPM_BASE + 0x1A8) +#define BUS_PROTECT5_RDY (SPM_BASE + 0x1AC) +#define BUS_PROTECT6_RDY (SPM_BASE + 0x1B0) +#define BUS_PROTECT7_RDY (SPM_BASE + 0x1B4) +#define BUS_PROTECT8_RDY (SPM_BASE + 0x1B8) +#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1D0) +#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1D4) +#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1D8) +#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1DC) +#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1E0) +#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1E4) +#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1E8) +#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1EC) +#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1F0) +#define SPM_CG_CHECK_STA (SPM_BASE + 0x1F4) +#define SPM_DVFS_STA (SPM_BASE + 0x1F8) +#define SPM_DVFS_OPP_STA (SPM_BASE + 0x1FC) +#define SPM_MCUSYS_PWR_CON (SPM_BASE + 0x200) +#define SPM_CPUTOP_PWR_CON (SPM_BASE + 0x204) +#define SPM_CPU0_PWR_CON (SPM_BASE + 0x208) +#define SPM_CPU1_PWR_CON (SPM_BASE + 0x20C) +#define SPM_CPU2_PWR_CON (SPM_BASE + 0x210) +#define SPM_CPU3_PWR_CON (SPM_BASE + 0x214) +#define SPM_CPU4_PWR_CON (SPM_BASE + 0x218) +#define SPM_CPU5_PWR_CON (SPM_BASE + 0x21C) +#define SPM_CPU6_PWR_CON (SPM_BASE + 0x220) +#define SPM_CPU7_PWR_CON (SPM_BASE + 0x224) +#define ARMPLL_CLK_CON (SPM_BASE + 0x22C) +#define MCUSYS_IDLE_STA (SPM_BASE + 0x230) +#define GIC_WAKEUP_STA (SPM_BASE + 0x234) +#define CPU_SPARE_CON (SPM_BASE + 0x238) +#define CPU_SPARE_CON_SET (SPM_BASE + 0x23C) +#define CPU_SPARE_CON_CLR (SPM_BASE + 0x240) +#define ARMPLL_CLK_SEL (SPM_BASE + 0x244) +#define EXT_INT_WAKEUP_REQ (SPM_BASE + 0x248) +#define EXT_INT_WAKEUP_REQ_SET (SPM_BASE + 0x24C) +#define EXT_INT_WAKEUP_REQ_CLR (SPM_BASE + 0x250) +#define MP0_CPU0_IRQ_MASK (SPM_BASE + 0x260) +#define MP0_CPU1_IRQ_MASK (SPM_BASE + 0x264) +#define MP0_CPU2_IRQ_MASK (SPM_BASE + 0x268) +#define MP0_CPU3_IRQ_MASK (SPM_BASE + 0x26C) +#define MP1_CPU0_IRQ_MASK (SPM_BASE + 0x270) +#define MP1_CPU1_IRQ_MASK (SPM_BASE + 0x274) +#define MP1_CPU2_IRQ_MASK (SPM_BASE + 0x278) +#define MP1_CPU3_IRQ_MASK (SPM_BASE + 0x27C) +#define MP0_CPU0_WFI_EN (SPM_BASE + 0x280) +#define MP0_CPU1_WFI_EN (SPM_BASE + 0x284) +#define MP0_CPU2_WFI_EN (SPM_BASE + 0x288) +#define MP0_CPU3_WFI_EN (SPM_BASE + 0x28C) +#define MP0_CPU4_WFI_EN (SPM_BASE + 0x290) +#define MP0_CPU5_WFI_EN (SPM_BASE + 0x294) +#define MP0_CPU6_WFI_EN (SPM_BASE + 0x298) +#define MP0_CPU7_WFI_EN (SPM_BASE + 0x29C) +#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x2A0) +#define ROOT_CORE_ADDR (SPM_BASE + 0x2A4) +#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x2D0) +#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x2D4) +#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x2D8) +#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x2DC) +#define SW2SPM_INT (SPM_BASE + 0x2E0) +#define SW2SPM_INT_SET (SPM_BASE + 0x2E4) +#define SW2SPM_INT_CLR (SPM_BASE + 0x2E8) +#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x2EC) +#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x2F0) +#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x2F4) +#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x2F8) +#define SW2SPM_CFG (SPM_BASE + 0x2FC) +#define MD1_PWR_CON (SPM_BASE + 0x300) +#define CONN_PWR_CON (SPM_BASE + 0x304) +#define MFG0_PWR_CON (SPM_BASE + 0x308) +#define MFG1_PWR_CON (SPM_BASE + 0x30C) +#define MFG2_PWR_CON (SPM_BASE + 0x310) +#define MFG3_PWR_CON (SPM_BASE + 0x314) +#define MFG4_PWR_CON (SPM_BASE + 0x318) +#define MFG5_PWR_CON (SPM_BASE + 0x31C) +#define MFG6_PWR_CON (SPM_BASE + 0x320) +#define IFR_PWR_CON (SPM_BASE + 0x324) +#define IFR_SUB_PWR_CON (SPM_BASE + 0x328) +#define DPY_PWR_CON (SPM_BASE + 0x32C) +#define ISP_PWR_CON (SPM_BASE + 0x330) +#define ISP2_PWR_CON (SPM_BASE + 0x334) +#define IPE_PWR_CON (SPM_BASE + 0x338) +#define VDE_PWR_CON (SPM_BASE + 0x33C) +#define VDE2_PWR_CON (SPM_BASE + 0x340) +#define VEN_PWR_CON (SPM_BASE + 0x344) +#define VEN_CORE1_PWR_CON (SPM_BASE + 0x348) +#define MDP_PWR_CON (SPM_BASE + 0x34C) +#define DIS_PWR_CON (SPM_BASE + 0x350) +#define AUDIO_PWR_CON (SPM_BASE + 0x354) +#define ADSP_PWR_CON (SPM_BASE + 0x358) +#define CAM_PWR_CON (SPM_BASE + 0x35C) +#define CAM_RAWA_PWR_CON (SPM_BASE + 0x360) +#define CAM_RAWB_PWR_CON (SPM_BASE + 0x364) +#define CAM_RAWC_PWR_CON (SPM_BASE + 0x368) +#define SYSRAM_CON (SPM_BASE + 0x36C) +#define SYSROM_CON (SPM_BASE + 0x370) +#define SSPM_SRAM_CON (SPM_BASE + 0x374) +#define SCP_SRAM_CON (SPM_BASE + 0x378) +#define DPY_SHU_SRAM_CON (SPM_BASE + 0x37C) +#define UFS_SRAM_CON (SPM_BASE + 0x380) +#define DEVAPC_IFR_SRAM_CON (SPM_BASE + 0x384) +#define DEVAPC_SUBIFR_SRAM_CON (SPM_BASE + 0x388) +#define DEVAPC_ACP_SRAM_CON (SPM_BASE + 0x38C) +#define USB_SRAM_CON (SPM_BASE + 0x390) +#define DUMMY_SRAM_CON (SPM_BASE + 0x394) +#define MD_EXT_BUCK_ISO_CON (SPM_BASE + 0x398) +#define EXT_BUCK_ISO (SPM_BASE + 0x39C) +#define DXCC_SRAM_CON (SPM_BASE + 0x3A0) +#define MSDC_SRAM_CON (SPM_BASE + 0x3A4) +#define DEBUGTOP_SRAM_CON (SPM_BASE + 0x3A8) +#define DP_TX_PWR_CON (SPM_BASE + 0x3AC) +#define DPMAIF_SRAM_CON (SPM_BASE + 0x3B0) +#define DPY_SHU2_SRAM_CON (SPM_BASE + 0x3B4) +#define DRAMC_MCU2_SRAM_CON (SPM_BASE + 0x3B8) +#define DRAMC_MCU_SRAM_CON (SPM_BASE + 0x3BC) +#define MCUPM_SRAM_CON (SPM_BASE + 0x3C0) +#define DPY2_PWR_CON (SPM_BASE + 0x3C4) +#define PERI_PWR_CON (SPM_BASE + 0x3C8) +#define SPM_MEM_CK_SEL (SPM_BASE + 0x400) +#define SPM_BUS_PROTECT_MASK_B (SPM_BASE + 0x404) +#define SPM_BUS_PROTECT1_MASK_B (SPM_BASE + 0x408) +#define SPM_BUS_PROTECT2_MASK_B (SPM_BASE + 0x40C) +#define SPM_BUS_PROTECT3_MASK_B (SPM_BASE + 0x410) +#define SPM_BUS_PROTECT4_MASK_B (SPM_BASE + 0x414) +#define SPM_EMI_BW_MODE (SPM_BASE + 0x418) +#define AP2MD_PEER_WAKEUP (SPM_BASE + 0x41C) +#define ULPOSC_CON (SPM_BASE + 0x420) +#define SPM2MM_CON (SPM_BASE + 0x424) +#define SPM_BUS_PROTECT5_MASK_B (SPM_BASE + 0x428) +#define SPM2MCUPM_CON (SPM_BASE + 0x42C) +#define AP_MDSRC_REQ (SPM_BASE + 0x430) +#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x434) +#define SPM2MD_DVFS_CON (SPM_BASE + 0x438) +#define MD2SPM_DVFS_CON (SPM_BASE + 0x43C) +#define SPM_BUS_PROTECT6_MASK_B (SPM_BASE + 0x440) +#define SPM_BUS_PROTECT7_MASK_B (SPM_BASE + 0x444) +#define SPM_BUS_PROTECT8_MASK_B (SPM_BASE + 0x448) +#define SPM_PLL_CON (SPM_BASE + 0x44C) +#define CPU_DVFS_REQ (SPM_BASE + 0x450) +#define SPM_DRAM_MCU_SW_CON_0 (SPM_BASE + 0x454) +#define SPM_DRAM_MCU_SW_CON_1 (SPM_BASE + 0x458) +#define SPM_DRAM_MCU_SW_CON_2 (SPM_BASE + 0x45C) +#define SPM_DRAM_MCU_SW_CON_3 (SPM_BASE + 0x460) +#define SPM_DRAM_MCU_SW_CON_4 (SPM_BASE + 0x464) +#define SPM_DRAM_MCU_STA_0 (SPM_BASE + 0x468) +#define SPM_DRAM_MCU_STA_1 (SPM_BASE + 0x46C) +#define SPM_DRAM_MCU_STA_2 (SPM_BASE + 0x470) +#define SPM_DRAM_MCU_SW_SEL_0 (SPM_BASE + 0x474) +#define RELAY_DVFS_LEVEL (SPM_BASE + 0x478) +#define DRAMC_DPY_CLK_SW_CON_0 (SPM_BASE + 0x480) +#define DRAMC_DPY_CLK_SW_CON_1 (SPM_BASE + 0x484) +#define DRAMC_DPY_CLK_SW_CON_2 (SPM_BASE + 0x488) +#define DRAMC_DPY_CLK_SW_CON_3 (SPM_BASE + 0x48C) +#define DRAMC_DPY_CLK_SW_SEL_0 (SPM_BASE + 0x490) +#define DRAMC_DPY_CLK_SW_SEL_1 (SPM_BASE + 0x494) +#define DRAMC_DPY_CLK_SW_SEL_2 (SPM_BASE + 0x498) +#define DRAMC_DPY_CLK_SW_SEL_3 (SPM_BASE + 0x49C) +#define DRAMC_DPY_CLK_SPM_CON (SPM_BASE + 0x4A0) +#define SPM_DVFS_LEVEL (SPM_BASE + 0x4A4) +#define SPM_CIRQ_CON (SPM_BASE + 0x4A8) +#define SPM_DVFS_MISC (SPM_BASE + 0x4AC) +#define SPM_VS1_VS2_RC_CON (SPM_BASE + 0x4B0) +#define RG_MODULE_SW_CG_0_MASK_REQ_0 (SPM_BASE + 0x4B4) +#define RG_MODULE_SW_CG_0_MASK_REQ_1 (SPM_BASE + 0x4B8) +#define RG_MODULE_SW_CG_0_MASK_REQ_2 (SPM_BASE + 0x4BC) +#define RG_MODULE_SW_CG_1_MASK_REQ_0 (SPM_BASE + 0x4C0) +#define RG_MODULE_SW_CG_1_MASK_REQ_1 (SPM_BASE + 0x4C4) +#define RG_MODULE_SW_CG_1_MASK_REQ_2 (SPM_BASE + 0x4C8) +#define RG_MODULE_SW_CG_2_MASK_REQ_0 (SPM_BASE + 0x4CC) +#define RG_MODULE_SW_CG_2_MASK_REQ_1 (SPM_BASE + 0x4D0) +#define RG_MODULE_SW_CG_2_MASK_REQ_2 (SPM_BASE + 0x4D4) +#define RG_MODULE_SW_CG_3_MASK_REQ_0 (SPM_BASE + 0x4D8) +#define RG_MODULE_SW_CG_3_MASK_REQ_1 (SPM_BASE + 0x4DC) +#define RG_MODULE_SW_CG_3_MASK_REQ_2 (SPM_BASE + 0x4E0) +#define PWR_STATUS_MASK_REQ_0 (SPM_BASE + 0x4E4) +#define PWR_STATUS_MASK_REQ_1 (SPM_BASE + 0x4E8) +#define PWR_STATUS_MASK_REQ_2 (SPM_BASE + 0x4EC) +#define SPM_CG_CHECK_CON (SPM_BASE + 0x4F0) +#define SPM_SRC_RDY_STA (SPM_BASE + 0x4F4) +#define SPM_DVS_DFS_LEVEL (SPM_BASE + 0x4F8) +#define SPM_FORCE_DVFS (SPM_BASE + 0x4FC) +#define SRCLKEN_RC_CFG (SPM_BASE + 0x500) +#define RC_CENTRAL_CFG1 (SPM_BASE + 0x504) +#define RC_CENTRAL_CFG2 (SPM_BASE + 0x508) +#define RC_CMD_ARB_CFG (SPM_BASE + 0x50C) +#define RC_PMIC_RCEN_ADDR (SPM_BASE + 0x510) +#define RC_PMIC_RCEN_SET_CLR_ADDR (SPM_BASE + 0x514) +#define RC_DCXO_FPM_CFG (SPM_BASE + 0x518) +#define RC_CENTRAL_CFG3 (SPM_BASE + 0x51C) +#define RC_M00_SRCLKEN_CFG (SPM_BASE + 0x520) +#define RC_M01_SRCLKEN_CFG (SPM_BASE + 0x524) +#define RC_M02_SRCLKEN_CFG (SPM_BASE + 0x528) +#define RC_M03_SRCLKEN_CFG (SPM_BASE + 0x52C) +#define RC_M04_SRCLKEN_CFG (SPM_BASE + 0x530) +#define RC_M05_SRCLKEN_CFG (SPM_BASE + 0x534) +#define RC_M06_SRCLKEN_CFG (SPM_BASE + 0x538) +#define RC_M07_SRCLKEN_CFG (SPM_BASE + 0x53C) +#define RC_M08_SRCLKEN_CFG (SPM_BASE + 0x540) +#define RC_M09_SRCLKEN_CFG (SPM_BASE + 0x544) +#define RC_M10_SRCLKEN_CFG (SPM_BASE + 0x548) +#define RC_M11_SRCLKEN_CFG (SPM_BASE + 0x54C) +#define RC_M12_SRCLKEN_CFG (SPM_BASE + 0x550) +#define RC_SRCLKEN_SW_CON_CFG (SPM_BASE + 0x554) +#define RC_CENTRAL_CFG4 (SPM_BASE + 0x558) +#define RC_PROTOCOL_CHK_CFG (SPM_BASE + 0x560) +#define RC_DEBUG_CFG (SPM_BASE + 0x564) +#define RC_MISC_0 (SPM_BASE + 0x5B4) +#define RC_SPM_CTRL (SPM_BASE + 0x5B8) +#define SUBSYS_INTF_CFG (SPM_BASE + 0x5BC) +#define PCM_WDT_LATCH_25 (SPM_BASE + 0x5C0) +#define PCM_WDT_LATCH_26 (SPM_BASE + 0x5C4) +#define PCM_WDT_LATCH_27 (SPM_BASE + 0x5C8) +#define PCM_WDT_LATCH_28 (SPM_BASE + 0x5CC) +#define PCM_WDT_LATCH_29 (SPM_BASE + 0x5D0) +#define PCM_WDT_LATCH_30 (SPM_BASE + 0x5D4) +#define PCM_WDT_LATCH_31 (SPM_BASE + 0x5D8) +#define PCM_WDT_LATCH_32 (SPM_BASE + 0x5DC) +#define PCM_WDT_LATCH_33 (SPM_BASE + 0x5E0) +#define PCM_WDT_LATCH_34 (SPM_BASE + 0x5E4) +#define PCM_WDT_LATCH_35 (SPM_BASE + 0x5EC) +#define PCM_WDT_LATCH_36 (SPM_BASE + 0x5F0) +#define PCM_WDT_LATCH_37 (SPM_BASE + 0x5F4) +#define PCM_WDT_LATCH_38 (SPM_BASE + 0x5F8) +#define PCM_WDT_LATCH_39 (SPM_BASE + 0x5FC) +#define SPM_SW_FLAG_0 (SPM_BASE + 0x600) +#define SPM_SW_DEBUG_0 (SPM_BASE + 0x604) +#define SPM_SW_FLAG_1 (SPM_BASE + 0x608) +#define SPM_SW_DEBUG_1 (SPM_BASE + 0x60C) +#define SPM_SW_RSV_0 (SPM_BASE + 0x610) +#define SPM_SW_RSV_1 (SPM_BASE + 0x614) +#define SPM_SW_RSV_2 (SPM_BASE + 0x618) +#define SPM_SW_RSV_3 (SPM_BASE + 0x61C) +#define SPM_SW_RSV_4 (SPM_BASE + 0x620) +#define SPM_SW_RSV_5 (SPM_BASE + 0x624) +#define SPM_SW_RSV_6 (SPM_BASE + 0x628) +#define SPM_SW_RSV_7 (SPM_BASE + 0x62C) +#define SPM_SW_RSV_8 (SPM_BASE + 0x630) +#define SPM_BK_WAKE_EVENT (SPM_BASE + 0x634) +#define SPM_BK_VTCXO_DUR (SPM_BASE + 0x638) +#define SPM_BK_WAKE_MISC (SPM_BASE + 0x63C) +#define SPM_BK_PCM_TIMER (SPM_BASE + 0x640) +#define SPM_RSV_CON_0 (SPM_BASE + 0x650) +#define SPM_RSV_CON_1 (SPM_BASE + 0x654) +#define SPM_RSV_STA_0 (SPM_BASE + 0x658) +#define SPM_RSV_STA_1 (SPM_BASE + 0x65C) +#define SPM_SPARE_CON (SPM_BASE + 0x660) +#define SPM_SPARE_CON_SET (SPM_BASE + 0x664) +#define SPM_SPARE_CON_CLR (SPM_BASE + 0x668) +#define SPM_CROSS_WAKE_M00_REQ (SPM_BASE + 0x66C) +#define SPM_CROSS_WAKE_M01_REQ (SPM_BASE + 0x670) +#define SPM_CROSS_WAKE_M02_REQ (SPM_BASE + 0x674) +#define SPM_CROSS_WAKE_M03_REQ (SPM_BASE + 0x678) +#define SCP_VCORE_LEVEL (SPM_BASE + 0x67C) +#define SC_MM_CK_SEL_CON (SPM_BASE + 0x680) +#define SPARE_ACK_MASK (SPM_BASE + 0x684) +#define SPM_CROSS_WAKE_M04_REQ (SPM_BASE + 0x688) +#define SPM_DV_CON_0 (SPM_BASE + 0x68C) +#define SPM_DV_CON_1 (SPM_BASE + 0x690) +#define SPM_DV_STA (SPM_BASE + 0x694) +#define CONN_XOWCN_DEBUG_EN (SPM_BASE + 0x698) +#define SPM_SEMA_M0 (SPM_BASE + 0x69C) +#define SPM_SEMA_M1 (SPM_BASE + 0x6A0) +#define SPM_SEMA_M2 (SPM_BASE + 0x6A4) +#define SPM_SEMA_M3 (SPM_BASE + 0x6A8) +#define SPM_SEMA_M4 (SPM_BASE + 0x6AC) +#define SPM_SEMA_M5 (SPM_BASE + 0x6B0) +#define SPM_SEMA_M6 (SPM_BASE + 0x6B4) +#define SPM_SEMA_M7 (SPM_BASE + 0x6B8) +#define SPM2ADSP_MAILBOX (SPM_BASE + 0x6BC) +#define ADSP2SPM_MAILBOX (SPM_BASE + 0x6C0) +#define SPM_ADSP_IRQ (SPM_BASE + 0x6C4) +#define SPM_MD32_IRQ (SPM_BASE + 0x6C8) +#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x6CC) +#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x6D0) +#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x6D4) +#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x6D8) +#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x6DC) +#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x6E0) +#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x6E4) +#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x6E8) +#define UFS_PSRI_SW (SPM_BASE + 0x6EC) +#define UFS_PSRI_SW_SET (SPM_BASE + 0x6F0) +#define UFS_PSRI_SW_CLR (SPM_BASE + 0x6F4) +#define SPM_AP_SEMA (SPM_BASE + 0x6F8) +#define SPM_SPM_SEMA (SPM_BASE + 0x6FC) +#define SPM_DVFS_CON (SPM_BASE + 0x700) +#define SPM_DVFS_CON_STA (SPM_BASE + 0x704) +#define SPM_PMIC_SPMI_CON (SPM_BASE + 0x708) +#define SPM_DVFS_CMD0 (SPM_BASE + 0x710) +#define SPM_DVFS_CMD1 (SPM_BASE + 0x714) +#define SPM_DVFS_CMD2 (SPM_BASE + 0x718) +#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C) +#define SPM_DVFS_CMD4 (SPM_BASE + 0x720) +#define SPM_DVFS_CMD5 (SPM_BASE + 0x724) +#define SPM_DVFS_CMD6 (SPM_BASE + 0x728) +#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C) +#define SPM_DVFS_CMD8 (SPM_BASE + 0x730) +#define SPM_DVFS_CMD9 (SPM_BASE + 0x734) +#define SPM_DVFS_CMD10 (SPM_BASE + 0x738) +#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C) +#define SPM_DVFS_CMD12 (SPM_BASE + 0x740) +#define SPM_DVFS_CMD13 (SPM_BASE + 0x744) +#define SPM_DVFS_CMD14 (SPM_BASE + 0x748) +#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C) +#define SPM_DVFS_CMD16 (SPM_BASE + 0x750) +#define SPM_DVFS_CMD17 (SPM_BASE + 0x754) +#define SPM_DVFS_CMD18 (SPM_BASE + 0x758) +#define SPM_DVFS_CMD19 (SPM_BASE + 0x75C) +#define SPM_DVFS_CMD20 (SPM_BASE + 0x760) +#define SPM_DVFS_CMD21 (SPM_BASE + 0x764) +#define SPM_DVFS_CMD22 (SPM_BASE + 0x768) +#define SPM_DVFS_CMD23 (SPM_BASE + 0x76C) +#define SYS_TIMER_VALUE_L (SPM_BASE + 0x770) +#define SYS_TIMER_VALUE_H (SPM_BASE + 0x774) +#define SYS_TIMER_START_L (SPM_BASE + 0x778) +#define SYS_TIMER_START_H (SPM_BASE + 0x77C) +#define SYS_TIMER_LATCH_L_00 (SPM_BASE + 0x780) +#define SYS_TIMER_LATCH_H_00 (SPM_BASE + 0x784) +#define SYS_TIMER_LATCH_L_01 (SPM_BASE + 0x788) +#define SYS_TIMER_LATCH_H_01 (SPM_BASE + 0x78C) +#define SYS_TIMER_LATCH_L_02 (SPM_BASE + 0x790) +#define SYS_TIMER_LATCH_H_02 (SPM_BASE + 0x794) +#define SYS_TIMER_LATCH_L_03 (SPM_BASE + 0x798) +#define SYS_TIMER_LATCH_H_03 (SPM_BASE + 0x79C) +#define SYS_TIMER_LATCH_L_04 (SPM_BASE + 0x7A0) +#define SYS_TIMER_LATCH_H_04 (SPM_BASE + 0x7A4) +#define SYS_TIMER_LATCH_L_05 (SPM_BASE + 0x7A8) +#define SYS_TIMER_LATCH_H_05 (SPM_BASE + 0x7AC) +#define SYS_TIMER_LATCH_L_06 (SPM_BASE + 0x7B0) +#define SYS_TIMER_LATCH_H_06 (SPM_BASE + 0x7B4) +#define SYS_TIMER_LATCH_L_07 (SPM_BASE + 0x7B8) +#define SYS_TIMER_LATCH_H_07 (SPM_BASE + 0x7BC) +#define SYS_TIMER_LATCH_L_08 (SPM_BASE + 0x7C0) +#define SYS_TIMER_LATCH_H_08 (SPM_BASE + 0x7C4) +#define SYS_TIMER_LATCH_L_09 (SPM_BASE + 0x7C8) +#define SYS_TIMER_LATCH_H_09 (SPM_BASE + 0x7CC) +#define SYS_TIMER_LATCH_L_10 (SPM_BASE + 0x7D0) +#define SYS_TIMER_LATCH_H_10 (SPM_BASE + 0x7D4) +#define SYS_TIMER_LATCH_L_11 (SPM_BASE + 0x7D8) +#define SYS_TIMER_LATCH_H_11 (SPM_BASE + 0x7DC) +#define SYS_TIMER_LATCH_L_12 (SPM_BASE + 0x7E0) +#define SYS_TIMER_LATCH_H_12 (SPM_BASE + 0x7E4) +#define SYS_TIMER_LATCH_L_13 (SPM_BASE + 0x7E8) +#define SYS_TIMER_LATCH_H_13 (SPM_BASE + 0x7EC) +#define SYS_TIMER_LATCH_L_14 (SPM_BASE + 0x7F0) +#define SYS_TIMER_LATCH_H_14 (SPM_BASE + 0x7F4) +#define SYS_TIMER_LATCH_L_15 (SPM_BASE + 0x7F8) +#define SYS_TIMER_LATCH_H_15 (SPM_BASE + 0x7FC) +#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800) +#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804) +#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808) +#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C) +#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810) +#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814) +#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818) +#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C) +#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820) +#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824) +#define PCM_WDT_LATCH_10 (SPM_BASE + 0x828) +#define PCM_WDT_LATCH_11 (SPM_BASE + 0x82C) +#define PCM_WDT_LATCH_12 (SPM_BASE + 0x830) +#define PCM_WDT_LATCH_13 (SPM_BASE + 0x834) +#define PCM_WDT_LATCH_14 (SPM_BASE + 0x838) +#define PCM_WDT_LATCH_15 (SPM_BASE + 0x83C) +#define PCM_WDT_LATCH_16 (SPM_BASE + 0x840) +#define PCM_WDT_LATCH_17 (SPM_BASE + 0x844) +#define PCM_WDT_LATCH_18 (SPM_BASE + 0x848) +#define PCM_WDT_LATCH_SPARE_0 (SPM_BASE + 0x84C) +#define PCM_WDT_LATCH_SPARE_1 (SPM_BASE + 0x850) +#define PCM_WDT_LATCH_SPARE_2 (SPM_BASE + 0x854) +#define PCM_WDT_LATCH_CONN_0 (SPM_BASE + 0x870) +#define PCM_WDT_LATCH_CONN_1 (SPM_BASE + 0x874) +#define PCM_WDT_LATCH_CONN_2 (SPM_BASE + 0x878) +#define DRAMC_GATING_ERR_LATCH_CH0_0 (SPM_BASE + 0x8A0) +#define DRAMC_GATING_ERR_LATCH_CH0_1 (SPM_BASE + 0x8A4) +#define DRAMC_GATING_ERR_LATCH_CH0_2 (SPM_BASE + 0x8A8) +#define DRAMC_GATING_ERR_LATCH_CH0_3 (SPM_BASE + 0x8AC) +#define DRAMC_GATING_ERR_LATCH_CH0_4 (SPM_BASE + 0x8B0) +#define DRAMC_GATING_ERR_LATCH_CH0_5 (SPM_BASE + 0x8B4) +#define DRAMC_GATING_ERR_LATCH_CH0_6 (SPM_BASE + 0x8B8) +#define DRAMC_GATING_ERR_LATCH_SPARE_0 (SPM_BASE + 0x8F4) +#define SPM_ACK_CHK_CON_0 (SPM_BASE + 0x900) +#define SPM_ACK_CHK_PC_0 (SPM_BASE + 0x904) +#define SPM_ACK_CHK_SEL_0 (SPM_BASE + 0x908) +#define SPM_ACK_CHK_TIMER_0 (SPM_BASE + 0x90C) +#define SPM_ACK_CHK_STA_0 (SPM_BASE + 0x910) +#define SPM_ACK_CHK_SWINT_0 (SPM_BASE + 0x914) +#define SPM_ACK_CHK_CON_1 (SPM_BASE + 0x920) +#define SPM_ACK_CHK_PC_1 (SPM_BASE + 0x924) +#define SPM_ACK_CHK_SEL_1 (SPM_BASE + 0x928) +#define SPM_ACK_CHK_TIMER_1 (SPM_BASE + 0x92C) +#define SPM_ACK_CHK_STA_1 (SPM_BASE + 0x930) +#define SPM_ACK_CHK_SWINT_1 (SPM_BASE + 0x934) +#define SPM_ACK_CHK_CON_2 (SPM_BASE + 0x940) +#define SPM_ACK_CHK_PC_2 (SPM_BASE + 0x944) +#define SPM_ACK_CHK_SEL_2 (SPM_BASE + 0x948) +#define SPM_ACK_CHK_TIMER_2 (SPM_BASE + 0x94C) +#define SPM_ACK_CHK_STA_2 (SPM_BASE + 0x950) +#define SPM_ACK_CHK_SWINT_2 (SPM_BASE + 0x954) +#define SPM_ACK_CHK_CON_3 (SPM_BASE + 0x960) +#define SPM_ACK_CHK_PC_3 (SPM_BASE + 0x964) +#define SPM_ACK_CHK_SEL_3 (SPM_BASE + 0x968) +#define SPM_ACK_CHK_TIMER_3 (SPM_BASE + 0x96C) +#define SPM_ACK_CHK_STA_3 (SPM_BASE + 0x970) +#define SPM_ACK_CHK_SWINT_3 (SPM_BASE + 0x974) +#define SPM_COUNTER_0 (SPM_BASE + 0x978) +#define SPM_COUNTER_1 (SPM_BASE + 0x97C) +#define SPM_COUNTER_2 (SPM_BASE + 0x980) +#define SYS_TIMER_CON (SPM_BASE + 0x98C) +#define RC_FSM_STA_0 (SPM_BASE + 0xE00) +#define RC_CMD_STA_0 (SPM_BASE + 0xE04) +#define RC_CMD_STA_1 (SPM_BASE + 0xE08) +#define RC_SPI_STA_0 (SPM_BASE + 0xE0C) +#define RC_PI_PO_STA_0 (SPM_BASE + 0xE10) +#define RC_M00_REQ_STA_0 (SPM_BASE + 0xE14) +#define RC_M01_REQ_STA_0 (SPM_BASE + 0xE1C) +#define RC_M02_REQ_STA_0 (SPM_BASE + 0xE20) +#define RC_M03_REQ_STA_0 (SPM_BASE + 0xE24) +#define RC_M04_REQ_STA_0 (SPM_BASE + 0xE28) +#define RC_M05_REQ_STA_0 (SPM_BASE + 0xE2C) +#define RC_M06_REQ_STA_0 (SPM_BASE + 0xE30) +#define RC_M07_REQ_STA_0 (SPM_BASE + 0xE34) +#define RC_M08_REQ_STA_0 (SPM_BASE + 0xE38) +#define RC_M09_REQ_STA_0 (SPM_BASE + 0xE3C) +#define RC_M10_REQ_STA_0 (SPM_BASE + 0xE40) +#define RC_M11_REQ_STA_0 (SPM_BASE + 0xE44) +#define RC_M12_REQ_STA_0 (SPM_BASE + 0xE48) +#define RC_DEBUG_STA_0 (SPM_BASE + 0xE4C) +#define RC_DEBUG_TRACE_0_LSB (SPM_BASE + 0xE50) +#define RC_DEBUG_TRACE_0_MSB (SPM_BASE + 0xE54) +#define RC_DEBUG_TRACE_1_LSB (SPM_BASE + 0xE5C) +#define RC_DEBUG_TRACE_1_MSB (SPM_BASE + 0xE60) +#define RC_DEBUG_TRACE_2_LSB (SPM_BASE + 0xE64) +#define RC_DEBUG_TRACE_2_MSB (SPM_BASE + 0xE6C) +#define RC_DEBUG_TRACE_3_LSB (SPM_BASE + 0xE70) +#define RC_DEBUG_TRACE_3_MSB (SPM_BASE + 0xE74) +#define RC_DEBUG_TRACE_4_LSB (SPM_BASE + 0xE78) +#define RC_DEBUG_TRACE_4_MSB (SPM_BASE + 0xE7C) +#define RC_DEBUG_TRACE_5_LSB (SPM_BASE + 0xE80) +#define RC_DEBUG_TRACE_5_MSB (SPM_BASE + 0xE84) +#define RC_DEBUG_TRACE_6_LSB (SPM_BASE + 0xE88) +#define RC_DEBUG_TRACE_6_MSB (SPM_BASE + 0xE8C) +#define RC_DEBUG_TRACE_7_LSB (SPM_BASE + 0xE90) +#define RC_DEBUG_TRACE_7_MSB (SPM_BASE + 0xE94) +#define RC_SYS_TIMER_LATCH_0_LSB (SPM_BASE + 0xE98) +#define RC_SYS_TIMER_LATCH_0_MSB (SPM_BASE + 0xE9C) +#define RC_SYS_TIMER_LATCH_1_LSB (SPM_BASE + 0xEA0) +#define RC_SYS_TIMER_LATCH_1_MSB (SPM_BASE + 0xEA4) +#define RC_SYS_TIMER_LATCH_2_LSB (SPM_BASE + 0xEA8) +#define RC_SYS_TIMER_LATCH_2_MSB (SPM_BASE + 0xEAC) +#define RC_SYS_TIMER_LATCH_3_LSB (SPM_BASE + 0xEB0) +#define RC_SYS_TIMER_LATCH_3_MSB (SPM_BASE + 0xEB4) +#define RC_SYS_TIMER_LATCH_4_LSB (SPM_BASE + 0xEB8) +#define RC_SYS_TIMER_LATCH_4_MSB (SPM_BASE + 0xEBC) +#define RC_SYS_TIMER_LATCH_5_LSB (SPM_BASE + 0xEC0) +#define RC_SYS_TIMER_LATCH_5_MSB (SPM_BASE + 0xEC4) +#define RC_SYS_TIMER_LATCH_6_LSB (SPM_BASE + 0xEC8) +#define RC_SYS_TIMER_LATCH_6_MSB (SPM_BASE + 0xECC) +#define RC_SYS_TIMER_LATCH_7_LSB (SPM_BASE + 0xED0) +#define RC_SYS_TIMER_LATCH_7_MSB (SPM_BASE + 0xED4) +#define PCM_WDT_LATCH_19 (SPM_BASE + 0xED8) +#define PCM_WDT_LATCH_20 (SPM_BASE + 0xEDC) +#define PCM_WDT_LATCH_21 (SPM_BASE + 0xEE0) +#define PCM_WDT_LATCH_22 (SPM_BASE + 0xEE4) +#define PCM_WDT_LATCH_23 (SPM_BASE + 0xEE8) +#define PCM_WDT_LATCH_24 (SPM_BASE + 0xEEC) +#define PMSR_LAST_DAT (SPM_BASE + 0xF00) +#define PMSR_LAST_CNT (SPM_BASE + 0xF04) +#define PMSR_LAST_ACK (SPM_BASE + 0xF08) +#define SPM_PMSR_SEL_CON0 (SPM_BASE + 0xF10) +#define SPM_PMSR_SEL_CON1 (SPM_BASE + 0xF14) +#define SPM_PMSR_SEL_CON2 (SPM_BASE + 0xF18) +#define SPM_PMSR_SEL_CON3 (SPM_BASE + 0xF1C) +#define SPM_PMSR_SEL_CON4 (SPM_BASE + 0xF20) +#define SPM_PMSR_SEL_CON5 (SPM_BASE + 0xF24) +#define SPM_PMSR_SEL_CON6 (SPM_BASE + 0xF28) +#define SPM_PMSR_SEL_CON7 (SPM_BASE + 0xF2C) +#define SPM_PMSR_SEL_CON8 (SPM_BASE + 0xF30) +#define SPM_PMSR_SEL_CON9 (SPM_BASE + 0xF34) +#define SPM_PMSR_SEL_CON10 (SPM_BASE + 0xF3C) +#define SPM_PMSR_SEL_CON11 (SPM_BASE + 0xF40) +#define SPM_PMSR_TIEMR_STA0 (SPM_BASE + 0xFB8) +#define SPM_PMSR_TIEMR_STA1 (SPM_BASE + 0xFBC) +#define SPM_PMSR_TIEMR_STA2 (SPM_BASE + 0xFC0) +#define SPM_PMSR_GENERAL_CON0 (SPM_BASE + 0xFC4) +#define SPM_PMSR_GENERAL_CON1 (SPM_BASE + 0xFC8) +#define SPM_PMSR_GENERAL_CON2 (SPM_BASE + 0xFCC) +#define SPM_PMSR_GENERAL_CON3 (SPM_BASE + 0xFD0) +#define SPM_PMSR_GENERAL_CON4 (SPM_BASE + 0xFD4) +#define SPM_PMSR_GENERAL_CON5 (SPM_BASE + 0xFD8) +#define SPM_PMSR_SW_RESET (SPM_BASE + 0xFDC) +#define SPM_PMSR_MON_CON0 (SPM_BASE + 0xFE0) +#define SPM_PMSR_MON_CON1 (SPM_BASE + 0xFE4) +#define SPM_PMSR_MON_CON2 (SPM_BASE + 0xFE8) +#define SPM_PMSR_LEN_CON0 (SPM_BASE + 0xFEC) +#define SPM_PMSR_LEN_CON1 (SPM_BASE + 0xFF0) +#define SPM_PMSR_LEN_CON2 (SPM_BASE + 0xFF4) + +/* POWERON_CONFIG_EN (0x10006000+0x000) */ +#define BCLK_CG_EN_LSB (1U << 0) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_POWER_ON_VAL0 (0x10006000+0x004) */ +#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */ +/* SPM_POWER_ON_VAL1 (0x10006000+0x008) */ +#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */ +/* SPM_CLK_CON (0x10006000+0x00C) */ +#define REG_SRCCLKEN0_CTL_LSB (1U << 0) /* 2b */ +#define REG_SRCCLKEN1_CTL_LSB (1U << 2) /* 2b */ +#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */ +#define REG_SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */ +#define REG_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */ +#define REG_MD1_C32RM_EN_LSB (1U << 9) /* 1b */ +#define REG_MD2_C32RM_EN_LSB (1U << 10) /* 1b */ +#define REG_CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */ +#define REG_CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */ +#define REG_SRCCLKEN0_EN_LSB (1U << 13) /* 1b */ +#define REG_SRCCLKEN1_EN_LSB (1U << 14) /* 1b */ +#define SCP_DCM_EN_LSB (1U << 15) /* 1b */ +#define REG_SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 8b */ +#define REG_SYSCLK1_SRC_MASK_B_LSB (1U << 24) /* 8b */ +/* SPM_CLK_SETTLE (0x10006000+0x010) */ +#define SYSCLK_SETTLE_LSB (1U << 0) /* 28b */ +/* SPM_AP_STANDBY_CON (0x10006000+0x014) */ +#define REG_WFI_OP_LSB (1U << 0) /* 1b */ +#define REG_WFI_TYPE_LSB (1U << 1) /* 1b */ +#define REG_MP0_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */ +#define REG_MP1_CPUTOP_IDLE_MASK_LSB (1U << 3) /* 1b */ +#define REG_MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */ +#define REG_MD_APSRC_1_SEL_LSB (1U << 25) /* 1b */ +#define REG_MD_APSRC_0_SEL_LSB (1U << 26) /* 1b */ +#define REG_CONN_APSRC_SEL_LSB (1U << 29) /* 1b */ +/* PCM_CON0 (0x10006000+0x018) */ +#define PCM_CK_EN_LSB (1U << 2) /* 1b */ +#define RG_EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */ +#define PCM_CK_FROM_CKSYS_LSB (1U << 4) /* 1b */ +#define PCM_SW_RESET_LSB (1U << 15) /* 1b */ +#define PCM_CON0_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* PCM_CON1 (0x10006000+0x01C) */ +#define RG_IM_SLAVE_LSB (1U << 0) /* 1b */ +#define RG_IM_SLEEP_LSB (1U << 1) /* 1b */ +#define REG_SPM_SRAM_CTRL_MUX_LSB (1U << 2) /* 1b */ +#define RG_AHBMIF_APBEN_LSB (1U << 3) /* 1b */ +#define RG_IM_PDN_LSB (1U << 4) /* 1b */ +#define RG_PCM_TIMER_EN_LSB (1U << 5) /* 1b */ +#define SPM_EVENT_COUNTER_CLR_LSB (1U << 6) /* 1b */ +#define RG_DIS_MIF_PROT_LSB (1U << 7) /* 1b */ +#define RG_PCM_WDT_EN_LSB (1U << 8) /* 1b */ +#define RG_PCM_WDT_WAKE_LSB (1U << 9) /* 1b */ +#define REG_SPM_SRAM_SLEEP_B_LSB (1U << 10) /* 1b */ +#define REG_SPM_SRAM_ISOINT_B_LSB (1U << 11) /* 1b */ +#define REG_EVENT_LOCK_EN_LSB (1U << 12) /* 1b */ +#define REG_SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */ +#define REG_MD32_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */ +#define RG_PCM_IRQ_MSK_LSB (1U << 15) /* 1b */ +#define PCM_CON1_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_POWER_ON_VAL2 (0x10006000+0x020) */ +#define POWER_ON_VAL2_LSB (1U << 0) /* 32b */ +/* SPM_POWER_ON_VAL3 (0x10006000+0x024) */ +#define POWER_ON_VAL3_LSB (1U << 0) /* 32b */ +/* PCM_REG_DATA_INI (0x10006000+0x028) */ +#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */ +/* PCM_PWR_IO_EN (0x10006000+0x02C) */ +#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */ +#define RG_RF_SYNC_EN_LSB (1U << 16) /* 8b */ +/* PCM_TIMER_VAL (0x10006000+0x030) */ +#define REG_PCM_TIMER_VAL_LSB (1U << 0) /* 32b */ +/* PCM_WDT_VAL (0x10006000+0x034) */ +#define RG_PCM_WDT_VAL_LSB (1U << 0) /* 32b */ +/* SPM_SRC6_MASK (0x10006000+0x038) */ +#define REG_DPMAIF_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_DPMAIF_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_DPMAIF_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_DPMAIF_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_DPMAIF_DDR_EN_MASK_B_LSB (1U << 4) /* 1b */ +/* SPM_SW_RST_CON (0x10006000+0x040) */ +#define SPM_SW_RST_CON_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_SW_RST_CON_SET (0x10006000+0x044) */ +#define SPM_SW_RST_CON_SET_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_SET_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_SW_RST_CON_CLR (0x10006000+0x048) */ +#define SPM_SW_RST_CON_CLR_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_CLR_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* VS1_PSR_MASK_B (0x10006000+0x04C) */ +#define VS1_OPP0_PSR_MASK_B_LSB (1U << 0) /* 8b */ +#define VS1_OPP1_PSR_MASK_B_LSB (1U << 8) /* 8b */ +/* VS2_PSR_MASK_B (0x10006000+0x050) */ +#define VS2_OPP0_PSR_MASK_B_LSB (1U << 0) /* 8b */ +#define VS2_OPP1_PSR_MASK_B_LSB (1U << 8) /* 8b */ +#define VS2_OPP2_PSR_MASK_B_LSB (1U << 16) /* 8b */ +/* MD32_CLK_CON (0x10006000+0x084) */ +#define REG_MD32_26M_CK_SEL_LSB (1U << 0) /* 1b */ +#define REG_MD32_DCM_EN_LSB (1U << 1) /* 1b */ +/* SPM_SRAM_RSV_CON (0x10006000+0x088) */ +#define SPM_SRAM_SLEEP_B_ECO_EN_LSB (1U << 0) /* 1b */ +/* SPM_SWINT (0x10006000+0x08C) */ +#define SPM_SWINT_LSB (1U << 0) /* 32b */ +/* SPM_SWINT_SET (0x10006000+0x090) */ +#define SPM_SWINT_SET_LSB (1U << 0) /* 32b */ +/* SPM_SWINT_CLR (0x10006000+0x094) */ +#define SPM_SWINT_CLR_LSB (1U << 0) /* 32b */ +/* SPM_SCP_MAILBOX (0x10006000+0x098) */ +#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */ +/* SCP_SPM_MAILBOX (0x10006000+0x09C) */ +#define SCP_SPM_MAILBOX_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CON (0x10006000+0x0A0) */ +#define REG_TWAM_ENABLE_LSB (1U << 0) /* 1b */ +#define REG_TWAM_SPEED_MODE_EN_LSB (1U << 1) /* 1b */ +#define REG_TWAM_SW_RST_LSB (1U << 2) /* 1b */ +#define REG_TWAM_IRQ_MASK_LSB (1U << 3) /* 1b */ +#define REG_TWAM_MON_TYPE_0_LSB (1U << 4) /* 2b */ +#define REG_TWAM_MON_TYPE_1_LSB (1U << 6) /* 2b */ +#define REG_TWAM_MON_TYPE_2_LSB (1U << 8) /* 2b */ +#define REG_TWAM_MON_TYPE_3_LSB (1U << 10) /* 2b */ +/* SPM_TWAM_WINDOW_LEN (0x10006000+0x0A4) */ +#define REG_TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_IDLE_SEL (0x10006000+0x0A8) */ +#define REG_TWAM_SIG_SEL_0_LSB (1U << 0) /* 7b */ +#define REG_TWAM_SIG_SEL_1_LSB (1U << 8) /* 7b */ +#define REG_TWAM_SIG_SEL_2_LSB (1U << 16) /* 7b */ +#define REG_TWAM_SIG_SEL_3_LSB (1U << 24) /* 7b */ +/* SPM_SCP_IRQ (0x10006000+0x0AC) */ +#define SC_SPM2SCP_WAKEUP_LSB (1U << 0) /* 1b */ +#define SC_SCP2SPM_WAKEUP_LSB (1U << 4) /* 1b */ +/* SPM_CPU_WAKEUP_EVENT (0x10006000+0x0B0) */ +#define REG_CPU_WAKEUP_LSB (1U << 0) /* 1b */ +/* SPM_IRQ_MASK (0x10006000+0x0B4) */ +#define REG_SPM_IRQ_MASK_LSB (1U << 0) /* 32b */ +/* SPM_SRC_REQ (0x10006000+0x0B8) */ +#define REG_SPM_APSRC_REQ_LSB (1U << 0) /* 1b */ +#define REG_SPM_F26M_REQ_LSB (1U << 1) /* 1b */ +#define REG_SPM_INFRA_REQ_LSB (1U << 3) /* 1b */ +#define REG_SPM_VRF18_REQ_LSB (1U << 4) /* 1b */ +#define REG_SPM_DDR_EN_REQ_LSB (1U << 7) /* 1b */ +#define REG_SPM_DVFS_REQ_LSB (1U << 8) /* 1b */ +#define REG_SPM_SW_MAILBOX_REQ_LSB (1U << 9) /* 1b */ +#define REG_SPM_SSPM_MAILBOX_REQ_LSB (1U << 10) /* 1b */ +#define REG_SPM_ADSP_MAILBOX_REQ_LSB (1U << 11) /* 1b */ +#define REG_SPM_SCP_MAILBOX_REQ_LSB (1U << 12) /* 1b */ +/* SPM_SRC_MASK (0x10006000+0x0BC) */ +#define REG_MD_SRCCLKENA_0_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_MD_SRCCLKENA2INFRA_REQ_0_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_MD_APSRC2INFRA_REQ_0_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_MD_APSRC_REQ_0_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_MD_VRF18_REQ_0_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_MD_DDR_EN_0_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_MD_SRCCLKENA_1_MASK_B_LSB (1U << 6) /* 1b */ +#define REG_MD_SRCCLKENA2INFRA_REQ_1_MASK_B_LSB (1U << 7) /* 1b */ +#define REG_MD_APSRC2INFRA_REQ_1_MASK_B_LSB (1U << 8) /* 1b */ +#define REG_MD_APSRC_REQ_1_MASK_B_LSB (1U << 9) /* 1b */ +#define REG_MD_VRF18_REQ_1_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_MD_DDR_EN_1_MASK_B_LSB (1U << 11) /* 1b */ +#define REG_CONN_SRCCLKENA_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_CONN_SRCCLKENB_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_CONN_INFRA_REQ_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_CONN_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_CONN_VRF18_REQ_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_CONN_DDR_EN_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_CONN_VFE28_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_SRCCLKENI0_SRCCLKENA_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_SRCCLKENI0_INFRA_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_SRCCLKENI1_SRCCLKENA_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_SRCCLKENI1_INFRA_REQ_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_SRCCLKENI2_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_SRCCLKENI2_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_INFRASYS_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_INFRASYS_DDR_EN_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_MD32_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_MD32_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_MD32_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_MD32_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_MD32_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */ +/* SPM_SRC2_MASK (0x10006000+0x0C0) */ +#define REG_SCP_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_SCP_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_SCP_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_SCP_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_SCP_DDR_EN_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_AUDIO_DSP_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_AUDIO_DSP_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */ +#define REG_AUDIO_DSP_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */ +#define REG_AUDIO_DSP_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */ +#define REG_AUDIO_DSP_DDR_EN_MASK_B_LSB (1U << 9) /* 1b */ +#define REG_UFS_SRCCLKENA_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_UFS_INFRA_REQ_MASK_B_LSB (1U << 11) /* 1b */ +#define REG_UFS_APSRC_REQ_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_UFS_VRF18_REQ_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_UFS_DDR_EN_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_DISP0_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_DISP0_DDR_EN_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_DISP1_APSRC_REQ_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_DISP1_DDR_EN_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_GCE_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_GCE_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_GCE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_GCE_DDR_EN_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_APU_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_APU_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_APU_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_APU_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_APU_DDR_EN_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_CG_CHECK_SRCCLKENA_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_CG_CHECK_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_CG_CHECK_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_CG_CHECK_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */ +/* SPM_SRC3_MASK (0x10006000+0x0C4) */ +#define REG_DVFSRC_EVENT_TRIGGER_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_SW2SPM_INT0_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_SW2SPM_INT1_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_SW2SPM_INT2_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_SW2SPM_INT3_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_SC_ADSP2SPM_WAKEUP_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_SC_SSPM2SPM_WAKEUP_MASK_B_LSB (1U << 6) /* 4b */ +#define REG_SC_SCP2SPM_WAKEUP_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_CSYSPWRREQ_MASK_LSB (1U << 11) /* 1b */ +#define REG_SPM_SRCCLKENA_RESERVED_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_SPM_INFRA_REQ_RESERVED_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_SPM_APSRC_REQ_RESERVED_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_SPM_VRF18_REQ_RESERVED_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_SPM_DDR_EN_RESERVED_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_MCUPM_SRCCLKENA_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_MCUPM_INFRA_REQ_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_MCUPM_APSRC_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_MCUPM_VRF18_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_MCUPM_DDR_EN_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_MSDC0_SRCCLKENA_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_MSDC0_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_MSDC0_APSRC_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_MSDC0_VRF18_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_MSDC0_DDR_EN_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_MSDC1_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_MSDC1_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_MSDC1_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_MSDC1_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_MSDC1_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */ +/* SPM_SRC4_MASK (0x10006000+0x0C8) */ +#define CCIF_EVENT_MASK_B_LSB (1U << 0) /* 16b */ +#define REG_BAK_PSRI_SRCCLKENA_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_BAK_PSRI_INFRA_REQ_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_BAK_PSRI_APSRC_REQ_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_BAK_PSRI_VRF18_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_BAK_PSRI_DDR_EN_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_DRAMC0_MD32_INFRA_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_DRAMC0_MD32_VRF18_REQ_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_DRAMC1_MD32_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_DRAMC1_MD32_VRF18_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_CONN_SRCCLKENB2PWRAP_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_DRAMC0_MD32_WAKEUP_MASK_LSB (1U << 26) /* 1b */ +#define REG_DRAMC1_MD32_WAKEUP_MASK_LSB (1U << 27) /* 1b */ +/* SPM_SRC5_MASK (0x10006000+0x0CC) */ +#define REG_MCUSYS_MERGE_APSRC_REQ_MASK_B_LSB (1U << 0) /* 9b */ +#define REG_MCUSYS_MERGE_DDR_EN_MASK_B_LSB (1U << 9) /* 9b */ +#define REG_MSDC2_SRCCLKENA_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_MSDC2_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_MSDC2_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_MSDC2_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_MSDC2_DDR_EN_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_PCIE_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_PCIE_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_PCIE_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_PCIE_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_PCIE_DDR_EN_MASK_B_LSB (1U << 27) /* 1b */ +/* SPM_WAKEUP_EVENT_MASK (0x10006000+0x0D0) */ +#define REG_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000+0x0D4) */ +#define REG_EXT_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_EVENT_CLEAR (0x10006000+0x0D8) */ +#define SPM_TWAM_EVENT_CLEAR_LSB (1U << 0) /* 1b */ +/* SCP_CLK_CON (0x10006000+0x0DC) */ +#define REG_SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */ +#define REG_SCP_DCM_EN_LSB (1U << 1) /* 1b */ +#define SCP_SECURE_V_REQ_MASK_LSB (1U << 2) /* 1b */ +#define SCP_SLP_REQ_LSB (1U << 3) /* 1b */ +#define SCP_SLP_ACK_LSB (1U << 4) /* 1b */ +/* PCM_DEBUG_CON (0x10006000+0x0E0) */ +#define PCM_DEBUG_OUT_ENABLE_LSB (1U << 0) /* 1b */ +/* AHB_BUS_CON (0x10006000+0x0E4) */ +#define AHB_HADDR_EXT_LSB (1U << 0) /* 2b */ +#define REG_AHB_LOCK_LSB (1U << 8) /* 1b */ +/* DDR_EN_DBC_CON0 (0x10006000+0x0E8) */ +#define REG_ALL_DDR_EN_DBC_LEN_LSB (1U << 0) /* 10b */ +#define REG_MD_DDR_EN_0_DBC_LEN_LSB (1U << 10) /* 10b */ +#define REG_HW_S1_DBC_LEN_LSB (1U << 20) /* 10b */ +/* DDR_EN_DBC_CON1 (0x10006000+0x0EC) */ +#define REG_ALL_DDR_EN_DBC_EN_LSB (1U << 0) /* 1b */ +#define REG_MD_DDR_EN_0_DBC_EN_LSB (1U << 1) /* 1b */ +#define REG_HW_S1_DBC_EN_LSB (1U << 2) /* 1b */ +/* SPM_RESOURCE_ACK_CON0 (0x10006000+0x0F0) */ +#define REG_MD_SRCCLKENA_ACK_0_MASK_LSB (1U << 0) /* 1b */ +#define REG_MD_INFRA_ACK_0_MASK_LSB (1U << 1) /* 1b */ +#define REG_MD_APSRC_ACK_0_MASK_LSB (1U << 2) /* 1b */ +#define REG_MD_VRF18_ACK_0_MASK_LSB (1U << 3) /* 1b */ +#define REG_MD_DDR_EN_ACK_0_MASK_LSB (1U << 4) /* 1b */ +#define REG_MD_SRCCLKENA_ACK_1_MASK_LSB (1U << 5) /* 1b */ +#define REG_MD_INFRA_ACK_1_MASK_LSB (1U << 6) /* 1b */ +#define REG_MD_APSRC_ACK_1_MASK_LSB (1U << 7) /* 1b */ +#define REG_MD_VRF18_ACK_1_MASK_LSB (1U << 8) /* 1b */ +#define REG_MD_DDR_EN_ACK_1_MASK_LSB (1U << 9) /* 1b */ +#define REG_CONN_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_CONN_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_CONN_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */ +#define REG_CONN_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */ +#define REG_CONN_DDR_EN_ACK_MASK_LSB (1U << 14) /* 1b */ +#define REG_MD32_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */ +#define REG_MD32_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */ +#define REG_MD32_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */ +#define REG_MD32_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */ +#define REG_MD32_DDR_EN_ACK_MASK_LSB (1U << 19) /* 1b */ +#define REG_SCP_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */ +#define REG_SCP_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */ +#define REG_SCP_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */ +#define REG_SCP_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */ +#define REG_SCP_DDR_EN_ACK_MASK_LSB (1U << 24) /* 1b */ +#define REG_AUDIO_DSP_SRCCLKENA_ACK_MASK_LSB (1U << 25) /* 1b */ +#define REG_AUDIO_DSP_INFRA_ACK_MASK_LSB (1U << 26) /* 1b */ +#define REG_AUDIO_DSP_APSRC_ACK_MASK_LSB (1U << 27) /* 1b */ +#define REG_AUDIO_DSP_VRF18_ACK_MASK_LSB (1U << 28) /* 1b */ +#define REG_AUDIO_DSP_DDR_EN_ACK_MASK_LSB (1U << 29) /* 1b */ +#define REG_DISP0_DDR_EN_ACK_MASK_LSB (1U << 30) /* 1b */ +#define REG_DISP1_APSRC_ACK_MASK_LSB (1U << 31) /* 1b */ +/* SPM_RESOURCE_ACK_CON1 (0x10006000+0x0F4) */ +#define REG_UFS_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */ +#define REG_UFS_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */ +#define REG_UFS_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */ +#define REG_UFS_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */ +#define REG_UFS_DDR_EN_ACK_MASK_LSB (1U << 4) /* 1b */ +#define REG_APU_SRCCLKENA_ACK_MASK_LSB (1U << 5) /* 1b */ +#define REG_APU_INFRA_ACK_MASK_LSB (1U << 6) /* 1b */ +#define REG_APU_APSRC_ACK_MASK_LSB (1U << 7) /* 1b */ +#define REG_APU_VRF18_ACK_MASK_LSB (1U << 8) /* 1b */ +#define REG_APU_DDR_EN_ACK_MASK_LSB (1U << 9) /* 1b */ +#define REG_MCUPM_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_MCUPM_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_MCUPM_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */ +#define REG_MCUPM_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */ +#define REG_MCUPM_DDR_EN_ACK_MASK_LSB (1U << 14) /* 1b */ +#define REG_MSDC0_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */ +#define REG_MSDC0_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */ +#define REG_MSDC0_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */ +#define REG_MSDC0_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */ +#define REG_MSDC0_DDR_EN_ACK_MASK_LSB (1U << 19) /* 1b */ +#define REG_MSDC1_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */ +#define REG_MSDC1_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */ +#define REG_MSDC1_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */ +#define REG_MSDC1_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */ +#define REG_MSDC1_DDR_EN_ACK_MASK_LSB (1U << 24) /* 1b */ +#define REG_DISP0_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */ +#define REG_DISP1_DDR_EN_ACK_MASK_LSB (1U << 26) /* 1b */ +#define REG_GCE_INFRA_ACK_MASK_LSB (1U << 27) /* 1b */ +#define REG_GCE_APSRC_ACK_MASK_LSB (1U << 28) /* 1b */ +#define REG_GCE_VRF18_ACK_MASK_LSB (1U << 29) /* 1b */ +#define REG_GCE_DDR_EN_ACK_MASK_LSB (1U << 30) /* 1b */ +/* SPM_RESOURCE_ACK_CON2 (0x10006000+0x0F8) */ +#define SPM_F26M_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */ +#define SPM_INFRA_ACK_WAIT_CYCLE_LSB (1U << 8) /* 8b */ +#define SPM_APSRC_ACK_WAIT_CYCLE_LSB (1U << 16) /* 8b */ +#define SPM_VRF18_ACK_WAIT_CYCLE_LSB (1U << 24) /* 8b */ +/* SPM_RESOURCE_ACK_CON3 (0x10006000+0x0FC) */ +#define SPM_DDR_EN_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */ +#define REG_BAK_PSRI_SRCCLKENA_ACK_MASK_LSB (1U << 8) /* 1b */ +#define REG_BAK_PSRI_INFRA_ACK_MASK_LSB (1U << 9) /* 1b */ +#define REG_BAK_PSRI_APSRC_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_BAK_PSRI_VRF18_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_BAK_PSRI_DDR_EN_ACK_MASK_LSB (1U << 12) /* 1b */ +#define REG_MSDC2_SRCCLKENA_ACK_MASK_LSB (1U << 13) /* 1b */ +#define REG_MSDC2_INFRA_ACK_MASK_LSB (1U << 14) /* 1b */ +#define REG_MSDC2_APSRC_ACK_MASK_LSB (1U << 15) /* 1b */ +#define REG_MSDC2_VRF18_ACK_MASK_LSB (1U << 16) /* 1b */ +#define REG_MSDC2_DDR_EN_ACK_MASK_LSB (1U << 17) /* 1b */ +#define REG_PCIE_SRCCLKENA_ACK_MASK_LSB (1U << 18) /* 1b */ +#define REG_PCIE_INFRA_ACK_MASK_LSB (1U << 19) /* 1b */ +#define REG_PCIE_APSRC_ACK_MASK_LSB (1U << 20) /* 1b */ +#define REG_PCIE_VRF18_ACK_MASK_LSB (1U << 21) /* 1b */ +#define REG_PCIE_DDR_EN_ACK_MASK_LSB (1U << 22) /* 1b */ +#define REG_DPMAIF_SRCCLKENA_ACK_MASK_LSB (1U << 23) /* 1b */ +#define REG_DPMAIF_INFRA_ACK_MASK_LSB (1U << 24) /* 1b */ +#define REG_DPMAIF_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */ +#define REG_DPMAIF_VRF18_ACK_MASK_LSB (1U << 26) /* 1b */ +#define REG_DPMAIF_DDR_EN_ACK_MASK_LSB (1U << 27) /* 1b */ +/* PCM_REG0_DATA (0x10006000+0x100) */ +#define PCM_REG0_RF_LSB (1U << 0) /* 32b */ +/* PCM_REG2_DATA (0x10006000+0x104) */ +#define PCM_REG2_RF_LSB (1U << 0) /* 32b */ +/* PCM_REG6_DATA (0x10006000+0x108) */ +#define PCM_REG6_RF_LSB (1U << 0) /* 32b */ +/* PCM_REG7_DATA (0x10006000+0x10C) */ +#define PCM_REG7_RF_LSB (1U << 0) /* 32b */ +/* PCM_REG13_DATA (0x10006000+0x110) */ +#define PCM_REG13_RF_LSB (1U << 0) /* 32b */ +/* SRC_REQ_STA_0 (0x10006000+0x114) */ +#define MD_SRCCLKENA_0_LSB (1U << 0) /* 1b */ +#define MD_SRCCLKENA2INFRA_REQ_0_LSB (1U << 1) /* 1b */ +#define MD_APSRC2INFRA_REQ_0_LSB (1U << 2) /* 1b */ +#define MD_APSRC_REQ_0_LSB (1U << 3) /* 1b */ +#define MD_VRF18_REQ_0_LSB (1U << 4) /* 1b */ +#define MD_DDR_EN_0_LSB (1U << 5) /* 1b */ +#define MD_SRCCLKENA_1_LSB (1U << 6) /* 1b */ +#define MD_SRCCLKENA2INFRA_REQ_1_LSB (1U << 7) /* 1b */ +#define MD_APSRC2INFRA_REQ_1_LSB (1U << 8) /* 1b */ +#define MD_APSRC_REQ_1_LSB (1U << 9) /* 1b */ +#define MD_VRF18_REQ_1_LSB (1U << 10) /* 1b */ +#define MD_DDR_EN_1_LSB (1U << 11) /* 1b */ +#define CONN_SRCCLKENA_LSB (1U << 12) /* 1b */ +#define CONN_SRCCLKENB_LSB (1U << 13) /* 1b */ +#define CONN_INFRA_REQ_LSB (1U << 14) /* 1b */ +#define CONN_APSRC_REQ_LSB (1U << 15) /* 1b */ +#define CONN_VRF18_REQ_LSB (1U << 16) /* 1b */ +#define CONN_DDR_EN_LSB (1U << 17) /* 1b */ +#define SRCCLKENI_LSB (1U << 18) /* 3b */ +#define MD32_SRCCLKENA_LSB (1U << 21) /* 1b */ +#define MD32_INFRA_REQ_LSB (1U << 22) /* 1b */ +#define MD32_APSRC_REQ_LSB (1U << 23) /* 1b */ +#define MD32_VRF18_REQ_LSB (1U << 24) /* 1b */ +#define MD32_DDR_EN_LSB (1U << 25) /* 1b */ +#define DISP0_APSRC_REQ_LSB (1U << 26) /* 1b */ +#define DISP0_DDR_EN_LSB (1U << 27) /* 1b */ +#define DISP1_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define DISP1_DDR_EN_LSB (1U << 29) /* 1b */ +#define DVFSRC_EVENT_TRIGGER_LSB (1U << 30) /* 1b */ +/* SRC_REQ_STA_1 (0x10006000+0x118) */ +#define SCP_SRCCLKENA_LSB (1U << 0) /* 1b */ +#define SCP_INFRA_REQ_LSB (1U << 1) /* 1b */ +#define SCP_APSRC_REQ_LSB (1U << 2) /* 1b */ +#define SCP_VRF18_REQ_LSB (1U << 3) /* 1b */ +#define SCP_DDR_EN_LSB (1U << 4) /* 1b */ +#define AUDIO_DSP_SRCCLKENA_LSB (1U << 5) /* 1b */ +#define AUDIO_DSP_INFRA_REQ_LSB (1U << 6) /* 1b */ +#define AUDIO_DSP_APSRC_REQ_LSB (1U << 7) /* 1b */ +#define AUDIO_DSP_VRF18_REQ_LSB (1U << 8) /* 1b */ +#define AUDIO_DSP_DDR_EN_LSB (1U << 9) /* 1b */ +#define UFS_SRCCLKENA_LSB (1U << 10) /* 1b */ +#define UFS_INFRA_REQ_LSB (1U << 11) /* 1b */ +#define UFS_APSRC_REQ_LSB (1U << 12) /* 1b */ +#define UFS_VRF18_REQ_LSB (1U << 13) /* 1b */ +#define UFS_DDR_EN_LSB (1U << 14) /* 1b */ +#define GCE_INFRA_REQ_LSB (1U << 15) /* 1b */ +#define GCE_APSRC_REQ_LSB (1U << 16) /* 1b */ +#define GCE_VRF18_REQ_LSB (1U << 17) /* 1b */ +#define GCE_DDR_EN_LSB (1U << 18) /* 1b */ +#define INFRASYS_APSRC_REQ_LSB (1U << 19) /* 1b */ +#define INFRASYS_DDR_EN_LSB (1U << 20) /* 1b */ +#define MSDC0_SRCCLKENA_LSB (1U << 21) /* 1b */ +#define MSDC0_INFRA_REQ_LSB (1U << 22) /* 1b */ +#define MSDC0_APSRC_REQ_LSB (1U << 23) /* 1b */ +#define MSDC0_VRF18_REQ_LSB (1U << 24) /* 1b */ +#define MSDC0_DDR_EN_LSB (1U << 25) /* 1b */ +#define MSDC1_SRCCLKENA_LSB (1U << 26) /* 1b */ +#define MSDC1_INFRA_REQ_LSB (1U << 27) /* 1b */ +#define MSDC1_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define MSDC1_VRF18_REQ_LSB (1U << 29) /* 1b */ +#define MSDC1_DDR_EN_LSB (1U << 30) /* 1b */ +/* SRC_REQ_STA_2 (0x10006000+0x11C) */ +#define MCUSYS_MERGE_DDR_EN_LSB (1U << 0) /* 9b */ +#define EMI_SELF_REFRESH_CH_LSB (1U << 9) /* 2b */ +#define SW2SPM_INT_LSB (1U << 11) /* 4b */ +#define SC_ADSP2SPM_WAKEUP_LSB (1U << 15) /* 1b */ +#define SC_SSPM2SPM_WAKEUP_LSB (1U << 16) /* 4b */ +#define SRC_REQ_STA_2_SC_SCP2SPM_WAKEUP_LSB (1U << 20) /* 1b */ +#define SPM_SRCCLKENA_RESERVED_LSB (1U << 21) /* 1b */ +#define SPM_INFRA_REQ_RESERVED_LSB (1U << 22) /* 1b */ +#define SPM_APSRC_REQ_RESERVED_LSB (1U << 23) /* 1b */ +#define SPM_VRF18_REQ_RESERVED_LSB (1U << 24) /* 1b */ +#define SPM_DDR_EN_RESERVED_LSB (1U << 25) /* 1b */ +#define MCUPM_SRCCLKENA_LSB (1U << 26) /* 1b */ +#define MCUPM_INFRA_REQ_LSB (1U << 27) /* 1b */ +#define MCUPM_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define MCUPM_VRF18_REQ_LSB (1U << 29) /* 1b */ +#define MCUPM_DDR_EN_LSB (1U << 30) /* 1b */ +/* PCM_TIMER_OUT (0x10006000+0x120) */ +#define PCM_TIMER_LSB (1U << 0) /* 32b */ +/* PCM_WDT_OUT (0x10006000+0x124) */ +#define PCM_WDT_TIMER_VAL_OUT_LSB (1U << 0) /* 32b */ +/* SPM_IRQ_STA (0x10006000+0x128) */ +#define TWAM_IRQ_LSB (1U << 2) /* 1b */ +#define PCM_IRQ_LSB (1U << 3) /* 1b */ +/* SRC_REQ_STA_4 (0x10006000+0x12C) */ +#define APU_SRCCLKENA_LSB (1U << 0) /* 1b */ +#define APU_INFRA_REQ_LSB (1U << 1) /* 1b */ +#define APU_APSRC_REQ_LSB (1U << 2) /* 1b */ +#define APU_VRF18_REQ_LSB (1U << 3) /* 1b */ +#define APU_DDR_EN_LSB (1U << 4) /* 1b */ +#define BAK_PSRI_SRCCLKENA_LSB (1U << 5) /* 1b */ +#define BAK_PSRI_INFRA_REQ_LSB (1U << 6) /* 1b */ +#define BAK_PSRI_APSRC_REQ_LSB (1U << 7) /* 1b */ +#define BAK_PSRI_VRF18_REQ_LSB (1U << 8) /* 1b */ +#define BAK_PSRI_DDR_EN_LSB (1U << 9) /* 1b */ +#define MSDC2_SRCCLKENA_LSB (1U << 10) /* 1b */ +#define MSDC2_INFRA_REQ_LSB (1U << 11) /* 1b */ +#define MSDC2_APSRC_REQ_LSB (1U << 12) /* 1b */ +#define MSDC2_VRF18_REQ_LSB (1U << 13) /* 1b */ +#define MSDC2_DDR_EN_LSB (1U << 14) /* 1b */ +#define PCIE_SRCCLKENA_LSB (1U << 15) /* 1b */ +#define PCIE_INFRA_REQ_LSB (1U << 16) /* 1b */ +#define PCIE_APSRC_REQ_LSB (1U << 17) /* 1b */ +#define PCIE_VRF18_REQ_LSB (1U << 18) /* 1b */ +#define PCIE_DDR_EN_LSB (1U << 19) /* 1b */ +#define DPMAIF_SRCCLKENA_LSB (1U << 20) /* 1b */ +#define DPMAIF_INFRA_REQ_LSB (1U << 21) /* 1b */ +#define DPMAIF_APSRC_REQ_LSB (1U << 22) /* 1b */ +#define DPMAIF_VRF18_REQ_LSB (1U << 23) /* 1b */ +#define DPMAIF_DDR_EN_LSB (1U << 24) /* 1b */ +/* MD32PCM_WAKEUP_STA (0x10006000+0x130) */ +#define MD32PCM_WAKEUP_STA_LSB (1U << 0) /* 32b */ +/* MD32PCM_EVENT_STA (0x10006000+0x134) */ +#define MD32PCM_EVENT_STA_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_STA (0x10006000+0x138) */ +#define F32K_WAKEUP_EVENT_L_LSB (1U << 0) /* 16b */ +#define ASYN_WAKEUP_EVENT_L_LSB (1U << 16) /* 16b */ +/* SPM_WAKEUP_EXT_STA (0x10006000+0x13C) */ +#define EXT_WAKEUP_EVENT_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_MISC (0x10006000+0x140) */ +#define GIC_WAKEUP_LSB (1U << 0) /* 10b */ +#define DVFSRC_IRQ_LSB (1U << 16) /* 1b */ +#define SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB (1U << 17) /* 1b */ +#define PCM_TIMER_EVENT_LSB (1U << 18) /* 1b */ +#define PMIC_EINT_OUT_B_LSB (1U << 19) /* 2b */ +#define TWAM_IRQ_B_LSB (1U << 21) /* 1b */ +#define PMSR_IRQ_B_SET0_LSB (1U << 22) /* 1b */ +#define PMSR_IRQ_B_SET1_LSB (1U << 23) /* 1b */ +#define PMSR_IRQ_B_SET2_LSB (1U << 24) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_0_LSB (1U << 25) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_1_LSB (1U << 26) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_2_LSB (1U << 27) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_3_LSB (1U << 28) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_ALL_LSB (1U << 29) /* 1b */ +#define PMIC_IRQ_ACK_LSB (1U << 30) /* 1b */ +#define PMIC_SCP_IRQ_LSB (1U << 31) /* 1b */ +/* MM_DVFS_HALT (0x10006000+0x144) */ +#define MM_DVFS_HALT_LSB (1U << 0) /* 5b */ +/* BUS_PROTECT_RDY (0x10006000+0x150) */ +#define PROTECT_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT1_RDY (0x10006000+0x154) */ +#define PROTECT1_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT2_RDY (0x10006000+0x158) */ +#define PROTECT2_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT3_RDY (0x10006000+0x15C) */ +#define PROTECT3_READY_LSB (1U << 0) /* 32b */ +/* SUBSYS_IDLE_STA (0x10006000+0x160) */ +#define SUBSYS_IDLE_SIGNALS_LSB (1U << 0) /* 32b */ +/* PCM_STA (0x10006000+0x164) */ +#define PCM_CK_SEL_O_LSB (1U << 0) /* 4b */ +#define EXT_SRC_STA_LSB (1U << 4) /* 3b */ +/* SRC_REQ_STA_3 (0x10006000+0x168) */ +#define CCIF_EVENT_RAW_STATUS_LSB (1U << 0) /* 16b */ +#define F26M_STATE_LSB (1U << 16) /* 1b */ +#define INFRA_STATE_LSB (1U << 17) /* 1b */ +#define APSRC_STATE_LSB (1U << 18) /* 1b */ +#define VRF18_STATE_LSB (1U << 19) /* 1b */ +#define DDR_EN_STATE_LSB (1U << 20) /* 1b */ +#define DVFS_STATE_LSB (1U << 21) /* 1b */ +#define SW_MAILBOX_STATE_LSB (1U << 22) /* 1b */ +#define SSPM_MAILBOX_STATE_LSB (1U << 23) /* 1b */ +#define ADSP_MAILBOX_STATE_LSB (1U << 24) /* 1b */ +#define SCP_MAILBOX_STATE_LSB (1U << 25) /* 1b */ +/* PWR_STATUS (0x10006000+0x16C) */ +#define PWR_STATUS_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_2ND (0x10006000+0x170) */ +#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */ +/* CPU_PWR_STATUS (0x10006000+0x174) */ +#define MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 1) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 3) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 4) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 5) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 6) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 7) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 8) /* 1b */ +#define MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 9) /* 1b */ +/* OTHER_PWR_STATUS (0x10006000+0x178) */ +#define OTHER_PWR_STATUS_LSB (1U << 0) /* 32b */ +/* SPM_VTCXO_EVENT_COUNT_STA (0x10006000+0x17C) */ +#define SPM_VTCXO_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_VTCXO_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* SPM_INFRA_EVENT_COUNT_STA (0x10006000+0x180) */ +#define SPM_INFRA_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_INFRA_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* SPM_VRF18_EVENT_COUNT_STA (0x10006000+0x184) */ +#define SPM_VRF18_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_VRF18_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* SPM_APSRC_EVENT_COUNT_STA (0x10006000+0x188) */ +#define SPM_APSRC_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_APSRC_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* SPM_DDREN_EVENT_COUNT_STA (0x10006000+0x18C) */ +#define SPM_DDREN_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_DDREN_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* MD32PCM_STA (0x10006000+0x190) */ +#define MD32PCM_HALT_LSB (1U << 0) /* 1b */ +#define MD32PCM_GATED_LSB (1U << 1) /* 1b */ +/* MD32PCM_PC (0x10006000+0x194) */ +#define MON_PC_LSB (1U << 0) /* 32b */ +/* DVFSRC_EVENT_STA (0x10006000+0x1A4) */ +#define DVFSRC_EVENT_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT4_RDY (0x10006000+0x1A8) */ +#define PROTECT4_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT5_RDY (0x10006000+0x1AC) */ +#define PROTECT5_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT6_RDY (0x10006000+0x1B0) */ +#define PROTECT6_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT7_RDY (0x10006000+0x1B4) */ +#define PROTECT7_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT8_RDY (0x10006000+0x1B8) */ +#define PROTECT8_READY_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA0 (0x10006000+0x1D0) */ +#define LAST_IDLE_CNT_0_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA1 (0x10006000+0x1D4) */ +#define LAST_IDLE_CNT_1_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA2 (0x10006000+0x1D8) */ +#define LAST_IDLE_CNT_2_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA3 (0x10006000+0x1DC) */ +#define LAST_IDLE_CNT_3_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA0 (0x10006000+0x1E0) */ +#define CURRENT_IDLE_CNT_0_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA1 (0x10006000+0x1E4) */ +#define CURRENT_IDLE_CNT_1_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA2 (0x10006000+0x1E8) */ +#define CURRENT_IDLE_CNT_2_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA3 (0x10006000+0x1EC) */ +#define CURRENT_IDLE_CNT_3_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_TIMER_OUT (0x10006000+0x1F0) */ +#define TWAM_TIMER_LSB (1U << 0) /* 32b */ +/* SPM_CG_CHECK_STA (0x10006000+0x1F4) */ +#define SPM_CG_CHECK_SLEEP_REQ_0_LSB (1U << 0) /* 1b */ +#define SPM_CG_CHECK_SLEEP_REQ_1_LSB (1U << 1) /* 1b */ +#define SPM_CG_CHECK_SLEEP_REQ_2_LSB (1U << 2) /* 1b */ +/* SPM_DVFS_STA (0x10006000+0x1F8) */ +#define TARGET_DVFS_LEVEL_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_OPP_STA (0x10006000+0x1FC) */ +#define TARGET_DVFS_OPP_LSB (1U << 0) /* 5b */ +#define CURRENT_DVFS_OPP_LSB (1U << 5) /* 5b */ +#define RELAY_DVFS_OPP_LSB (1U << 10) /* 5b */ +/* SPM_MCUSYS_PWR_CON (0x10006000+0x200) */ +#define MCUSYS_SPMC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MCUSYS_SPMC_PWR_ON_LSB (1U << 2) /* 1b */ +#define MCUSYS_SPMC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MCUSYS_SPMC_RESETPWRON_CONFIG_LSB (1U << 5) /* 1b */ +#define MCUSYS_SPMC_DORMANT_EN_LSB (1U << 6) /* 1b */ +#define MCUSYS_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */ +#define SPM_MCUSYS_PWR_CON_MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 31) /* 1b */ +/* SPM_CPUTOP_PWR_CON (0x10006000+0x204) */ +#define MP0_SPMC_PWR_RST_B_CPUTOP_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPUTOP_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_PWR_CLK_DIS_CPUTOP_LSB (1U << 4) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPUTOP_LSB (1U << 5) /* 1b */ +#define MP0_SPMC_DORMANT_EN_CPUTOP_LSB (1U << 6) /* 1b */ +#define MP0_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */ +#define MP0_VSRAM_EXT_OFF_LSB (1U << 8) /* 1b */ +#define SPM_CPUTOP_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 31) /* 1b */ +/* SPM_CPU0_PWR_CON (0x10006000+0x208) */ +#define MP0_SPMC_PWR_RST_B_CPU0_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU0_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU0_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU0_LSB (1U << 7) /* 1b */ +#define SPM_CPU0_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 31) /* 1b */ +/* SPM_CPU1_PWR_CON (0x10006000+0x20C) */ +#define MP0_SPMC_PWR_RST_B_CPU1_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU1_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU1_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU1_LSB (1U << 7) /* 1b */ +#define SPM_CPU1_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 31) /* 1b */ +/* SPM_CPU2_PWR_CON (0x10006000+0x210) */ +#define MP0_SPMC_PWR_RST_B_CPU2_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU2_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU2_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU2_LSB (1U << 7) /* 1b */ +#define SPM_CPU2_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 31) /* 1b */ +/* SPM_CPU3_PWR_CON (0x10006000+0x214) */ +#define MP0_SPMC_PWR_RST_B_CPU3_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU3_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU3_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU3_LSB (1U << 7) /* 1b */ +#define SPM_CPU3_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 31) /* 1b */ +/* SPM_CPU4_PWR_CON (0x10006000+0x218) */ +#define MP0_SPMC_PWR_RST_B_CPU4_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU4_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU4_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU4_LSB (1U << 7) /* 1b */ +#define SPM_CPU4_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 31) /* 1b */ +/* SPM_CPU5_PWR_CON (0x10006000+0x21C) */ +#define MP0_SPMC_PWR_RST_B_CPU5_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU5_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU5_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU5_LSB (1U << 7) /* 1b */ +#define SPM_CPU5_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 31) /* 1b */ +/* SPM_CPU6_PWR_CON (0x10006000+0x220) */ +#define MP0_SPMC_PWR_RST_B_CPU6_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU6_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU6_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU6_LSB (1U << 7) /* 1b */ +#define SPM_CPU6_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 31) /* 1b */ +/* SPM_CPU7_PWR_CON (0x10006000+0x224) */ +#define MP0_SPMC_PWR_RST_B_CPU7_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU7_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU7_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU7_LSB (1U << 7) /* 1b */ +#define SPM_CPU7_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 31) /* 1b */ +/* ARMPLL_CLK_CON (0x10006000+0x22C) */ +#define SC_ARM_FHC_PAUSE_LSB (1U << 0) /* 6b */ +#define SC_ARM_CK_OFF_LSB (1U << 6) /* 6b */ +#define SC_ARMPLL_OFF_LSB (1U << 12) /* 1b */ +#define SC_ARMBPLL_OFF_LSB (1U << 13) /* 1b */ +#define SC_ARMBPLL1_OFF_LSB (1U << 14) /* 1b */ +#define SC_ARMBPLL2_OFF_LSB (1U << 15) /* 1b */ +#define SC_ARMBPLL3_OFF_LSB (1U << 16) /* 1b */ +#define SC_CCIPLL_CKOFF_LSB (1U << 17) /* 1b */ +#define SC_ARMDDS_OFF_LSB (1U << 18) /* 1b */ +#define SC_ARMBPLL_S_OFF_LSB (1U << 19) /* 1b */ +#define SC_ARMBPLL1_S_OFF_LSB (1U << 20) /* 1b */ +#define SC_ARMBPLL2_S_OFF_LSB (1U << 21) /* 1b */ +#define SC_ARMBPLL3_S_OFF_LSB (1U << 22) /* 1b */ +#define SC_CCIPLL_PWROFF_LSB (1U << 23) /* 1b */ +#define SC_ARMPLLOUT_OFF_LSB (1U << 24) /* 1b */ +#define SC_ARMBPLLOUT_OFF_LSB (1U << 25) /* 1b */ +#define SC_ARMBPLLOUT1_OFF_LSB (1U << 26) /* 1b */ +#define SC_ARMBPLLOUT2_OFF_LSB (1U << 27) /* 1b */ +#define SC_ARMBPLLOUT3_OFF_LSB (1U << 28) /* 1b */ +#define SC_CCIPLL_OUT_OFF_LSB (1U << 29) /* 1b */ +/* MCUSYS_IDLE_STA (0x10006000+0x230) */ +#define ARMBUS_IDLE_TO_26M_LSB (1U << 0) /* 1b */ +#define MP0_CLUSTER_IDLE_TO_PWR_OFF_LSB (1U << 1) /* 1b */ +#define MCUSYS_DDR_EN_0_LSB (1U << 2) /* 1b */ +#define MCUSYS_DDR_EN_1_LSB (1U << 3) /* 1b */ +#define MCUSYS_DDR_EN_2_LSB (1U << 4) /* 1b */ +#define MCUSYS_DDR_EN_3_LSB (1U << 5) /* 1b */ +#define MCUSYS_DDR_EN_4_LSB (1U << 6) /* 1b */ +#define MCUSYS_DDR_EN_5_LSB (1U << 7) /* 1b */ +#define MCUSYS_DDR_EN_6_LSB (1U << 8) /* 1b */ +#define MCUSYS_DDR_EN_7_LSB (1U << 9) /* 1b */ +#define MP0_CPU_IDLE_TO_PWR_OFF_LSB (1U << 16) /* 8b */ +#define WFI_AF_SEL_LSB (1U << 24) /* 8b */ +/* GIC_WAKEUP_STA (0x10006000+0x234) */ +#define GIC_WAKEUP_STA_GIC_WAKEUP_LSB (1U << 10) /* 10b */ +/* CPU_SPARE_CON (0x10006000+0x238) */ +#define CPU_SPARE_CON_LSB (1U << 0) /* 32b */ +/* CPU_SPARE_CON_SET (0x10006000+0x23C) */ +#define CPU_SPARE_CON_SET_LSB (1U << 0) /* 32b */ +/* CPU_SPARE_CON_CLR (0x10006000+0x240) */ +#define CPU_SPARE_CON_CLR_LSB (1U << 0) /* 32b */ +/* ARMPLL_CLK_SEL (0x10006000+0x244) */ +#define ARMPLL_CLK_SEL_LSB (1U << 0) /* 15b */ +/* EXT_INT_WAKEUP_REQ (0x10006000+0x248) */ +#define EXT_INT_WAKEUP_REQ_LSB (1U << 0) /* 10b */ +/* EXT_INT_WAKEUP_REQ_SET (0x10006000+0x24C) */ +#define EXT_INT_WAKEUP_REQ_SET_LSB (1U << 0) /* 10b */ +/* EXT_INT_WAKEUP_REQ_CLR (0x10006000+0x250) */ +#define EXT_INT_WAKEUP_REQ_CLR_LSB (1U << 0) /* 10b */ +/* MP0_CPU0_IRQ_MASK (0x10006000+0x260) */ +#define MP0_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU0_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU1_IRQ_MASK (0x10006000+0x264) */ +#define MP0_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU2_IRQ_MASK (0x10006000+0x268) */ +#define MP0_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU2_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU3_IRQ_MASK (0x10006000+0x26C) */ +#define MP0_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU3_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU0_IRQ_MASK (0x10006000+0x270) */ +#define MP1_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU0_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU1_IRQ_MASK (0x10006000+0x274) */ +#define MP1_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU1_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU2_IRQ_MASK (0x10006000+0x278) */ +#define MP1_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU2_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU3_IRQ_MASK (0x10006000+0x27C) */ +#define MP1_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU3_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU0_WFI_EN (0x10006000+0x280) */ +#define MP0_CPU0_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU1_WFI_EN (0x10006000+0x284) */ +#define MP0_CPU1_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU2_WFI_EN (0x10006000+0x288) */ +#define MP0_CPU2_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU3_WFI_EN (0x10006000+0x28C) */ +#define MP0_CPU3_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU4_WFI_EN (0x10006000+0x290) */ +#define MP0_CPU4_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU5_WFI_EN (0x10006000+0x294) */ +#define MP0_CPU5_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU6_WFI_EN (0x10006000+0x298) */ +#define MP0_CPU6_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU7_WFI_EN (0x10006000+0x29C) */ +#define MP0_CPU7_WFI_EN_LSB (1U << 0) /* 1b */ +/* ROOT_CPUTOP_ADDR (0x10006000+0x2A0) */ +#define ROOT_CPUTOP_ADDR_LSB (1U << 0) /* 32b */ +/* ROOT_CORE_ADDR (0x10006000+0x2A4) */ +#define ROOT_CORE_ADDR_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_0 (0x10006000+0x2D0) */ +#define SPM2SW_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_1 (0x10006000+0x2D4) */ +#define SPM2SW_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_2 (0x10006000+0x2D8) */ +#define SPM2SW_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_3 (0x10006000+0x2DC) */ +#define SPM2SW_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* SW2SPM_INT (0x10006000+0x2E0) */ +#define SW2SPM_INT_SW2SPM_INT_LSB (1U << 0) /* 4b */ +/* SW2SPM_INT_SET (0x10006000+0x2E4) */ +#define SW2SPM_INT_SET_LSB (1U << 0) /* 4b */ +/* SW2SPM_INT_CLR (0x10006000+0x2E8) */ +#define SW2SPM_INT_CLR_LSB (1U << 0) /* 4b */ +/* SW2SPM_MAILBOX_0 (0x10006000+0x2EC) */ +#define SW2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_1 (0x10006000+0x2F0) */ +#define SW2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_2 (0x10006000+0x2F4) */ +#define SW2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_3 (0x10006000+0x2F8) */ +#define SW2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* SW2SPM_CFG (0x10006000+0x2FC) */ +#define SWU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */ +/* MD1_PWR_CON (0x10006000+0x300) */ +#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MD1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MD1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* CONN_PWR_CON (0x10006000+0x304) */ +#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CONN_PWR_ON_LSB (1U << 2) /* 1b */ +#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* MFG0_PWR_CON (0x10006000+0x308) */ +#define MFG0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG0_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG0_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG0_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG1_PWR_CON (0x10006000+0x30C) */ +#define MFG1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG2_PWR_CON (0x10006000+0x310) */ +#define MFG2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG2_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG3_PWR_CON (0x10006000+0x314) */ +#define MFG3_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG3_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG3_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG3_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG3_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG3_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG4_PWR_CON (0x10006000+0x318) */ +#define MFG4_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG4_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG4_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG4_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG4_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG4_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG4_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG5_PWR_CON (0x10006000+0x31C) */ +#define MFG5_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG5_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG5_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG5_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG5_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG5_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG5_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG6_PWR_CON (0x10006000+0x320) */ +#define MFG6_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG6_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG6_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG6_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG6_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG6_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG6_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* IFR_PWR_CON (0x10006000+0x324) */ +#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IFR_PWR_ON_LSB (1U << 2) /* 1b */ +#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IFR_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* IFR_SUB_PWR_CON (0x10006000+0x328) */ +#define IFR_SUB_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IFR_SUB_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IFR_SUB_PWR_ON_LSB (1U << 2) /* 1b */ +#define IFR_SUB_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IFR_SUB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IFR_SUB_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IFR_SUB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* DPY_PWR_CON (0x10006000+0x32C) */ +#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DPY_PWR_ON_LSB (1U << 2) /* 1b */ +#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DPY_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DPY_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* ISP_PWR_CON (0x10006000+0x330) */ +#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ISP_PWR_ON_LSB (1U << 2) /* 1b */ +#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ISP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* ISP2_PWR_CON (0x10006000+0x334) */ +#define ISP2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ISP2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ISP2_PWR_ON_LSB (1U << 2) /* 1b */ +#define ISP2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ISP2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ISP2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_ISP2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* IPE_PWR_CON (0x10006000+0x338) */ +#define IPE_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IPE_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IPE_PWR_ON_LSB (1U << 2) /* 1b */ +#define IPE_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IPE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IPE_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IPE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VDE_PWR_CON (0x10006000+0x33C) */ +#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VDE_PWR_ON_LSB (1U << 2) /* 1b */ +#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VDE_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VDE2_PWR_CON (0x10006000+0x340) */ +#define VDE2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VDE2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VDE2_PWR_ON_LSB (1U << 2) /* 1b */ +#define VDE2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VDE2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VDE2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VDE2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VEN_PWR_CON (0x10006000+0x344) */ +#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VEN_PWR_ON_LSB (1U << 2) /* 1b */ +#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VEN_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VEN_CORE1_PWR_CON (0x10006000+0x348) */ +#define VEN_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VEN_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VEN_CORE1_PWR_ON_LSB (1U << 2) /* 1b */ +#define VEN_CORE1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VEN_CORE1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VEN_CORE1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VEN_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MDP_PWR_CON (0x10006000+0x34C) */ +#define MDP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MDP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MDP_PWR_ON_LSB (1U << 2) /* 1b */ +#define MDP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MDP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MDP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MDP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* DIS_PWR_CON (0x10006000+0x350) */ +#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DIS_PWR_ON_LSB (1U << 2) /* 1b */ +#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DIS_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* AUDIO_PWR_CON (0x10006000+0x354) */ +#define AUDIO_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define AUDIO_PWR_ISO_LSB (1U << 1) /* 1b */ +#define AUDIO_PWR_ON_LSB (1U << 2) /* 1b */ +#define AUDIO_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define AUDIO_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define AUDIO_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_AUDIO_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* ADSP_PWR_CON (0x10006000+0x358) */ +#define ADSP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ADSP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ADSP_PWR_ON_LSB (1U << 2) /* 1b */ +#define ADSP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ADSP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ADSP_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define ADSP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define ADSP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define ADSP_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */ +#define SC_ADSP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +#define SC_ADSP_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */ +/* CAM_PWR_CON (0x10006000+0x35C) */ +#define CAM_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* CAM_RAWA_PWR_CON (0x10006000+0x360) */ +#define CAM_RAWA_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWA_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWA_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWA_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWA_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWA_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* CAM_RAWB_PWR_CON (0x10006000+0x364) */ +#define CAM_RAWB_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWB_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWB_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWB_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWB_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* CAM_RAWC_PWR_CON (0x10006000+0x368) */ +#define CAM_RAWC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWC_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWC_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWC_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWC_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWC_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* SYSRAM_CON (0x10006000+0x36C) */ +#define SYSRAM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SYSRAM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SYSRAM_SRAM_SLEEP_B_LSB (1U << 4) /* 4b */ +#define SYSRAM_SRAM_PDN_LSB (1U << 16) /* 4b */ +/* SYSROM_CON (0x10006000+0x370) */ +#define SYSROM_SRAM_PDN_LSB (1U << 0) /* 6b */ +/* SSPM_SRAM_CON (0x10006000+0x374) */ +#define SSPM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SSPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SSPM_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SSPM_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* SCP_SRAM_CON (0x10006000+0x378) */ +#define SCP_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SCP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SCP_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* DPY_SHU_SRAM_CON (0x10006000+0x37C) */ +#define DPY_SHU_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPY_SHU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPY_SHU_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */ +#define DPY_SHU_SRAM_PDN_LSB (1U << 16) /* 2b */ +/* UFS_SRAM_CON (0x10006000+0x380) */ +#define UFS_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define UFS_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define UFS_SRAM_SLEEP_B_LSB (1U << 4) /* 5b */ +#define UFS_SRAM_PDN_LSB (1U << 16) /* 5b */ +/* DEVAPC_IFR_SRAM_CON (0x10006000+0x384) */ +#define DEVAPC_IFR_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_IFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_IFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */ +#define DEVAPC_IFR_SRAM_PDN_LSB (1U << 16) /* 6b */ +/* DEVAPC_SUBIFR_SRAM_CON (0x10006000+0x388) */ +#define DEVAPC_SUBIFR_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_SUBIFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_SUBIFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */ +#define DEVAPC_SUBIFR_SRAM_PDN_LSB (1U << 16) /* 6b */ +/* DEVAPC_ACP_SRAM_CON (0x10006000+0x38C) */ +#define DEVAPC_ACP_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_ACP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_ACP_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */ +#define DEVAPC_ACP_SRAM_PDN_LSB (1U << 16) /* 6b */ +/* USB_SRAM_CON (0x10006000+0x390) */ +#define USB_SRAM_PDN_LSB (1U << 0) /* 7b */ +/* DUMMY_SRAM_CON (0x10006000+0x394) */ +#define DUMMY_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DUMMY_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DUMMY_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */ +#define DUMMY_SRAM_PDN_LSB (1U << 16) /* 8b */ +/* MD_EXT_BUCK_ISO_CON (0x10006000+0x398) */ +#define VMODEM_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +#define VMD_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */ +/* EXT_BUCK_ISO (0x10006000+0x39C) */ +#define VIMVO_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +#define GPU_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */ +#define ADSP_EXT_BUCK_ISO_LSB (1U << 2) /* 1b */ +#define IPU_EXT_BUCK_ISO_LSB (1U << 5) /* 3b */ +/* DXCC_SRAM_CON (0x10006000+0x3A0) */ +#define DXCC_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DXCC_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DXCC_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DXCC_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* MSDC_SRAM_CON (0x10006000+0x3A4) */ +#define MSDC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MSDC_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MSDC_PWR_ON_LSB (1U << 2) /* 1b */ +#define MSDC_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MSDC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MSDC_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MSDC_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MSDC_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MSDC_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */ +#define SC_MSDC_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +#define SC_MSDC_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */ +/* DEBUGTOP_SRAM_CON (0x10006000+0x3A8) */ +#define DEBUGTOP_SRAM_PDN_LSB (1U << 0) /* 1b */ +/* DP_TX_PWR_CON (0x10006000+0x3AC) */ +#define DP_TX_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DP_TX_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DP_TX_PWR_ON_LSB (1U << 2) /* 1b */ +#define DP_TX_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DP_TX_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DP_TX_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DP_TX_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* DPMAIF_SRAM_CON (0x10006000+0x3B0) */ +#define DPMAIF_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPMAIF_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPMAIF_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DPMAIF_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* DPY_SHU2_SRAM_CON (0x10006000+0x3B4) */ +#define DPY_SHU2_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPY_SHU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPY_SHU2_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */ +#define DPY_SHU2_SRAM_PDN_LSB (1U << 16) /* 2b */ +/* DRAMC_MCU2_SRAM_CON (0x10006000+0x3B8) */ +#define DRAMC_MCU2_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DRAMC_MCU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DRAMC_MCU2_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DRAMC_MCU2_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* DRAMC_MCU_SRAM_CON (0x10006000+0x3BC) */ +#define DRAMC_MCU_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DRAMC_MCU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DRAMC_MCU_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DRAMC_MCU_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* MCUPM_SRAM_CON (0x10006000+0x3C0) */ +#define MCUPM_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MCUPM_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MCUPM_PWR_ON_LSB (1U << 2) /* 1b */ +#define MCUPM_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MCUPM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MCUPM_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define MCUPM_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define MCUPM_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define MCUPM_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */ +#define SC_MCUPM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +#define SC_MCUPM_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */ +/* DPY2_PWR_CON (0x10006000+0x3C4) */ +#define DPY2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DPY2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DPY2_PWR_ON_LSB (1U << 2) /* 1b */ +#define DPY2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DPY2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DPY2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DPY2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* PERI_PWR_CON (0x10006000+0x3C8) */ +#define PERI_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define PERI_PWR_ISO_LSB (1U << 1) /* 1b */ +#define PERI_PWR_ON_LSB (1U << 2) /* 1b */ +#define PERI_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define PERI_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define PERI_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_PERI_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* SPM_MEM_CK_SEL (0x10006000+0x400) */ +#define SC_MEM_CK_SEL_LSB (1U << 0) /* 1b */ +#define SPM2CKSYS_MEM_CK_MUX_UPDATE_LSB (1U << 1) /* 1b */ +/* SPM_BUS_PROTECT_MASK_B (0x10006000+0X404) */ +#define SPM_BUS_PROTECT_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT1_MASK_B (0x10006000+0x408) */ +#define SPM_BUS_PROTECT1_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT2_MASK_B (0x10006000+0x40C) */ +#define SPM_BUS_PROTECT2_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT3_MASK_B (0x10006000+0x410) */ +#define SPM_BUS_PROTECT3_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT4_MASK_B (0x10006000+0x414) */ +#define SPM_BUS_PROTECT4_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_EMI_BW_MODE (0x10006000+0x418) */ +#define EMI_BW_MODE_LSB (1U << 0) /* 1b */ +#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */ +#define EMI_BW_MODE_2_LSB (1U << 2) /* 1b */ +#define EMI_BOOST_MODE_2_LSB (1U << 3) /* 1b */ +/* AP2MD_PEER_WAKEUP (0x10006000+0x41C) */ +#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */ +/* ULPOSC_CON (0x10006000+0x420) */ +#define ULPOSC_EN_LSB (1U << 0) /* 1b */ +#define ULPOSC_RST_LSB (1U << 1) /* 1b */ +#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */ +#define ULPOSC_CLK_SEL_LSB (1U << 3) /* 1b */ +/* SPM2MM_CON (0x10006000+0x424) */ +#define SPM2MM_FORCE_ULTRA_LSB (1U << 0) /* 1b */ +#define SPM2MM_DBL_OSTD_ACT_LSB (1U << 1) /* 1b */ +#define SPM2MM_ULTRAREQ_LSB (1U << 2) /* 1b */ +#define SPM2MD_ULTRAREQ_LSB (1U << 3) /* 1b */ +#define SPM2ISP_ULTRAREQ_LSB (1U << 4) /* 1b */ +#define MM2SPM_FORCE_ULTRA_ACK_D2T_LSB (1U << 16) /* 1b */ +#define MM2SPM_DBL_OSTD_ACT_ACK_D2T_LSB (1U << 17) /* 1b */ +#define SPM2ISP_ULTRAACK_D2T_LSB (1U << 18) /* 1b */ +#define SPM2MM_ULTRAACK_D2T_LSB (1U << 19) /* 1b */ +#define SPM2MD_ULTRAACK_D2T_LSB (1U << 20) /* 1b */ +/* SPM_BUS_PROTECT5_MASK_B (0x10006000+0x428) */ +#define SPM_BUS_PROTECT5_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM2MCUPM_CON (0x10006000+0x42C) */ +#define SPM2MCUPM_SW_RST_B_LSB (1U << 0) /* 1b */ +#define SPM2MCUPM_SW_INT_LSB (1U << 1) /* 1b */ +/* AP_MDSRC_REQ (0x10006000+0x430) */ +#define AP_MDSMSRC_REQ_LSB (1U << 0) /* 1b */ +#define AP_L1SMSRC_REQ_LSB (1U << 1) /* 1b */ +#define AP_MD2SRC_REQ_LSB (1U << 2) /* 1b */ +#define AP_MDSMSRC_ACK_LSB (1U << 4) /* 1b */ +#define AP_L1SMSRC_ACK_LSB (1U << 5) /* 1b */ +#define AP_MD2SRC_ACK_LSB (1U << 6) /* 1b */ +/* SPM2EMI_ENTER_ULPM (0x10006000+0x434) */ +#define SPM2EMI_ENTER_ULPM_LSB (1U << 0) /* 1b */ +/* SPM2MD_DVFS_CON (0x10006000+0x438) */ +#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 32b */ +/* MD2SPM_DVFS_CON (0x10006000+0x43C) */ +#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT6_MASK_B (0x10006000+0X440) */ +#define SPM_BUS_PROTECT6_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT7_MASK_B (0x10006000+0x444) */ +#define SPM_BUS_PROTECT7_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT8_MASK_B (0x10006000+0x448) */ +#define SPM_BUS_PROTECT8_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PLL_CON (0x10006000+0x44C) */ +#define SC_MAINPLLOUT_OFF_LSB (1U << 0) /* 1b */ +#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */ +#define SC_MAINPLL_OFF_LSB (1U << 4) /* 1b */ +#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */ +#define SC_MAINPLL_S_OFF_LSB (1U << 8) /* 1b */ +#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */ +#define SC_SMI_CK_OFF_LSB (1U << 16) /* 1b */ +#define SC_MD32K_CK_OFF_LSB (1U << 17) /* 1b */ +#define SC_CKSQ1_OFF_LSB (1U << 18) /* 1b */ +#define SC_AXI_MEM_CK_OFF_LSB (1U << 19) /* 1b */ +/* CPU_DVFS_REQ (0x10006000+0x450) */ +#define CPU_DVFS_REQ_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_CON_0 (0x10006000+0x454) */ +#define SW_DDR_PST_REQ_LSB (1U << 0) /* 2b */ +#define SW_DDR_PST_ABORT_REQ_LSB (1U << 2) /* 2b */ +/* SPM_DRAM_MCU_SW_CON_1 (0x10006000+0x458) */ +#define SW_DDR_PST_CH0_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_CON_2 (0x10006000+0x45C) */ +#define SW_DDR_PST_CH1_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_CON_3 (0x10006000+0x460) */ +#define SW_DDR_RESERVED_CH0_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_CON_4 (0x10006000+0x464) */ +#define SW_DDR_RESERVED_CH1_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_STA_0 (0x10006000+0x468) */ +#define SC_DDR_PST_ACK_LSB (1U << 0) /* 2b */ +#define SC_DDR_PST_ABORT_ACK_LSB (1U << 2) /* 2b */ +/* SPM_DRAM_MCU_STA_1 (0x10006000+0x46C) */ +#define SC_DDR_CUR_PST_STA_CH0_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_STA_2 (0x10006000+0x470) */ +#define SC_DDR_CUR_PST_STA_CH1_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_SEL_0 (0x10006000+0x474) */ +#define SW_DDR_PST_REQ_SEL_LSB (1U << 0) /* 2b */ +#define SW_DDR_PST_SEL_LSB (1U << 2) /* 2b */ +#define SW_DDR_PST_ABORT_REQ_SEL_LSB (1U << 4) /* 2b */ +#define SW_DDR_RESERVED_SEL_LSB (1U << 6) /* 2b */ +#define SW_DDR_PST_ACK_SEL_LSB (1U << 8) /* 2b */ +#define SW_DDR_PST_ABORT_ACK_SEL_LSB (1U << 10) /* 2b */ +/* RELAY_DVFS_LEVEL (0x10006000+0x478) */ +#define RELAY_DVFS_LEVEL_LSB (1U << 0) /* 32b */ +/* DRAMC_DPY_CLK_SW_CON_0 (0x10006000+0x480) */ +#define SW_PHYPLL_EN_LSB (1U << 0) /* 2b */ +#define SW_DPY_VREF_EN_LSB (1U << 2) /* 2b */ +#define SW_DPY_DLL_CK_EN_LSB (1U << 4) /* 2b */ +#define SW_DPY_DLL_EN_LSB (1U << 6) /* 2b */ +#define SW_DPY_2ND_DLL_EN_LSB (1U << 8) /* 2b */ +#define SW_MEM_CK_OFF_LSB (1U << 10) /* 2b */ +#define SW_DMSUS_OFF_LSB (1U << 12) /* 2b */ +#define SW_DPY_MODE_SW_LSB (1U << 14) /* 2b */ +#define SW_EMI_CLK_OFF_LSB (1U << 16) /* 2b */ +#define SW_DDRPHY_FB_CK_EN_LSB (1U << 18) /* 2b */ +#define SW_DR_GATE_RETRY_EN_LSB (1U << 20) /* 2b */ +#define SW_DPHY_PRECAL_UP_LSB (1U << 24) /* 2b */ +#define SW_DPY_BCLK_ENABLE_LSB (1U << 26) /* 2b */ +#define SW_TX_TRACKING_DIS_LSB (1U << 28) /* 2b */ +#define SW_DPHY_RXDLY_TRACKING_EN_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_CON_1 (0x10006000+0x484) */ +#define SW_SHU_RESTORE_LSB (1U << 0) /* 2b */ +#define SW_DMYRD_MOD_LSB (1U << 2) /* 2b */ +#define SW_DMYRD_INTV_LSB (1U << 4) /* 2b */ +#define SW_DMYRD_EN_LSB (1U << 6) /* 2b */ +#define SW_DRS_DIS_REQ_LSB (1U << 8) /* 2b */ +#define SW_DR_SRAM_LOAD_LSB (1U << 10) /* 2b */ +#define SW_DR_SRAM_RESTORE_LSB (1U << 12) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_LATCH_LSB (1U << 14) /* 2b */ +#define SW_TX_TRACK_RETRY_EN_LSB (1U << 16) /* 2b */ +#define SW_DPY_MIDPI_EN_LSB (1U << 18) /* 2b */ +#define SW_DPY_PI_RESETB_EN_LSB (1U << 20) /* 2b */ +#define SW_DPY_MCK8X_EN_LSB (1U << 22) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_CH0_LSB (1U << 24) /* 4b */ +#define SW_DR_SHU_LEVEL_SRAM_CH1_LSB (1U << 28) /* 4b */ +/* DRAMC_DPY_CLK_SW_CON_2 (0x10006000+0x488) */ +#define SW_DR_SHU_LEVEL_LSB (1U << 0) /* 2b */ +#define SW_DR_SHU_EN_LSB (1U << 2) /* 1b */ +#define SW_DR_SHORT_QUEUE_LSB (1U << 3) /* 1b */ +#define SW_PHYPLL_MODE_SW_LSB (1U << 4) /* 1b */ +#define SW_PHYPLL2_MODE_SW_LSB (1U << 5) /* 1b */ +#define SW_PHYPLL_SHU_EN_LSB (1U << 6) /* 1b */ +#define SW_PHYPLL2_SHU_EN_LSB (1U << 7) /* 1b */ +#define SW_DR_RESERVED_0_LSB (1U << 24) /* 2b */ +#define SW_DR_RESERVED_1_LSB (1U << 26) /* 2b */ +#define SW_DR_RESERVED_2_LSB (1U << 28) /* 2b */ +#define SW_DR_RESERVED_3_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_CON_3 (0x10006000+0x48C) */ +#define SC_DR_SHU_EN_ACK_LSB (1U << 0) /* 4b */ +#define SC_EMI_CLK_OFF_ACK_LSB (1U << 4) /* 4b */ +#define SC_DR_SHORT_QUEUE_ACK_LSB (1U << 8) /* 4b */ +#define SC_DRAMC_DFS_STA_LSB (1U << 12) /* 4b */ +#define SC_DRS_DIS_ACK_LSB (1U << 16) /* 4b */ +#define SC_DR_SRAM_LOAD_ACK_LSB (1U << 20) /* 4b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_LSB (1U << 24) /* 4b */ +#define SC_DR_SRAM_RESTORE_ACK_LSB (1U << 28) /* 4b */ +/* DRAMC_DPY_CLK_SW_SEL_0 (0x10006000+0x490) */ +#define SW_PHYPLL_EN_SEL_LSB (1U << 0) /* 2b */ +#define SW_DPY_VREF_EN_SEL_LSB (1U << 2) /* 2b */ +#define SW_DPY_DLL_CK_EN_SEL_LSB (1U << 4) /* 2b */ +#define SW_DPY_DLL_EN_SEL_LSB (1U << 6) /* 2b */ +#define SW_DPY_2ND_DLL_EN_SEL_LSB (1U << 8) /* 2b */ +#define SW_MEM_CK_OFF_SEL_LSB (1U << 10) /* 2b */ +#define SW_DMSUS_OFF_SEL_LSB (1U << 12) /* 2b */ +#define SW_DPY_MODE_SW_SEL_LSB (1U << 14) /* 2b */ +#define SW_EMI_CLK_OFF_SEL_LSB (1U << 16) /* 2b */ +#define SW_DDRPHY_FB_CK_EN_SEL_LSB (1U << 18) /* 2b */ +#define SW_DR_GATE_RETRY_EN_SEL_LSB (1U << 20) /* 2b */ +#define SW_DPHY_PRECAL_UP_SEL_LSB (1U << 24) /* 2b */ +#define SW_DPY_BCLK_ENABLE_SEL_LSB (1U << 26) /* 2b */ +#define SW_TX_TRACKING_DIS_SEL_LSB (1U << 28) /* 2b */ +#define SW_DPHY_RXDLY_TRACKING_EN_SEL_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_SEL_1 (0x10006000+0x494) */ +#define SW_SHU_RESTORE_SEL_LSB (1U << 0) /* 2b */ +#define SW_DMYRD_MOD_SEL_LSB (1U << 2) /* 2b */ +#define SW_DMYRD_INTV_SEL_LSB (1U << 4) /* 2b */ +#define SW_DMYRD_EN_SEL_LSB (1U << 6) /* 2b */ +#define SW_DRS_DIS_REQ_SEL_LSB (1U << 8) /* 2b */ +#define SW_DR_SRAM_LOAD_SEL_LSB (1U << 10) /* 2b */ +#define SW_DR_SRAM_RESTORE_SEL_LSB (1U << 12) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_LATCH_SEL_LSB (1U << 14) /* 2b */ +#define SW_TX_TRACK_RETRY_EN_SEL_LSB (1U << 16) /* 2b */ +#define SW_DPY_MIDPI_EN_SEL_LSB (1U << 18) /* 2b */ +#define SW_DPY_PI_RESETB_EN_SEL_LSB (1U << 20) /* 2b */ +#define SW_DPY_MCK8X_EN_SEL_LSB (1U << 22) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_SEL_LSB (1U << 24) /* 2b */ +/* DRAMC_DPY_CLK_SW_SEL_2 (0x10006000+0x498) */ +#define SW_DR_SHU_LEVEL_SEL_LSB (1U << 0) /* 1b */ +#define SW_DR_SHU_EN_SEL_LSB (1U << 2) /* 1b */ +#define SW_DR_SHORT_QUEUE_SEL_LSB (1U << 3) /* 1b */ +#define SW_PHYPLL_MODE_SW_SEL_LSB (1U << 4) /* 1b */ +#define SW_PHYPLL2_MODE_SW_SEL_LSB (1U << 5) /* 1b */ +#define SW_PHYPLL_SHU_EN_SEL_LSB (1U << 6) /* 1b */ +#define SW_PHYPLL2_SHU_EN_SEL_LSB (1U << 7) /* 1b */ +#define SW_DR_RESERVED_0_SEL_LSB (1U << 24) /* 2b */ +#define SW_DR_RESERVED_1_SEL_LSB (1U << 26) /* 2b */ +#define SW_DR_RESERVED_2_SEL_LSB (1U << 28) /* 2b */ +#define SW_DR_RESERVED_3_SEL_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_SEL_3 (0x10006000+0x49C) */ +#define SC_DR_SHU_EN_ACK_SEL_LSB (1U << 0) /* 4b */ +#define SC_EMI_CLK_OFF_ACK_SEL_LSB (1U << 4) /* 4b */ +#define SC_DR_SHORT_QUEUE_ACK_SEL_LSB (1U << 8) /* 4b */ +#define SC_DRAMC_DFS_STA_SEL_LSB (1U << 12) /* 4b */ +#define SC_DRS_DIS_ACK_SEL_LSB (1U << 16) /* 4b */ +#define SC_DR_SRAM_LOAD_ACK_SEL_LSB (1U << 20) /* 4b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_SEL_LSB (1U << 24) /* 4b */ +#define SC_DR_SRAM_RESTORE_ACK_SEL_LSB (1U << 28) /* 4b */ +/* DRAMC_DPY_CLK_SPM_CON (0x10006000+0x4A0) */ +#define SC_DMYRD_EN_MOD_SEL_PCM_LSB (1U << 0) /* 1b */ +#define SC_DMYRD_INTV_SEL_PCM_LSB (1U << 1) /* 1b */ +#define SC_DMYRD_EN_PCM_LSB (1U << 2) /* 1b */ +#define SC_DRS_DIS_REQ_PCM_LSB (1U << 3) /* 1b */ +#define SC_DR_SHU_LEVEL_SRAM_PCM_LSB (1U << 4) /* 4b */ +#define SC_DR_GATE_RETRY_EN_PCM_LSB (1U << 8) /* 1b */ +#define SC_DR_SHORT_QUEUE_PCM_LSB (1U << 9) /* 1b */ +#define SC_DPY_MIDPI_EN_PCM_LSB (1U << 10) /* 1b */ +#define SC_DPY_PI_RESETB_EN_PCM_LSB (1U << 11) /* 1b */ +#define SC_DPY_MCK8X_EN_PCM_LSB (1U << 12) /* 1b */ +#define SC_DR_RESERVED_0_PCM_LSB (1U << 13) /* 1b */ +#define SC_DR_RESERVED_1_PCM_LSB (1U << 14) /* 1b */ +#define SC_DR_RESERVED_2_PCM_LSB (1U << 15) /* 1b */ +#define SC_DR_RESERVED_3_PCM_LSB (1U << 16) /* 1b */ +#define SC_DMDRAMCSHU_ACK_ALL_LSB (1U << 24) /* 1b */ +#define SC_EMI_CLK_OFF_ACK_ALL_LSB (1U << 25) /* 1b */ +#define SC_DR_SHORT_QUEUE_ACK_ALL_LSB (1U << 26) /* 1b */ +#define SC_DRAMC_DFS_STA_ALL_LSB (1U << 27) /* 1b */ +#define SC_DRS_DIS_ACK_ALL_LSB (1U << 28) /* 1b */ +#define SC_DR_SRAM_LOAD_ACK_ALL_LSB (1U << 29) /* 1b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_ALL_LSB (1U << 30) /* 1b */ +#define SC_DR_SRAM_RESTORE_ACK_ALL_LSB (1U << 31) /* 1b */ +/* SPM_DVFS_LEVEL (0x10006000+0x4A4) */ +#define SPM_DVFS_LEVEL_LSB (1U << 0) /* 32b */ +/* SPM_CIRQ_CON (0x10006000+0x4A8) */ +#define CIRQ_CLK_SEL_LSB (1U << 0) /* 1b */ +/* SPM_DVFS_MISC (0x10006000+0x4AC) */ +#define MSDC_DVFS_REQUEST_LSB (1U << 0) /* 1b */ +#define SPM2EMI_SLP_PROT_EN_LSB (1U << 1) /* 1b */ +#define SPM_DVFS_FORCE_ENABLE_LSB (1U << 2) /* 1b */ +#define FORCE_DVFS_WAKE_LSB (1U << 3) /* 1b */ +#define SPM_DVFSRC_ENABLE_LSB (1U << 4) /* 1b */ +#define SPM_DVFS_DONE_LSB (1U << 5) /* 1b */ +#define DVFSRC_IRQ_WAKEUP_EVENT_MASK_LSB (1U << 6) /* 1b */ +#define SPM2RC_EVENT_ABORT_LSB (1U << 7) /* 1b */ +#define EMI_SLP_IDLE_LSB (1U << 14) /* 1b */ +#define SDIO_READY_TO_SPM_LSB (1U << 15) /* 1b */ +/* SPM_VS1_VS2_RC_CON (0x10006000+0x4B0) */ +#define VS1_INIT_LEVEL_LSB (1U << 0) /* 2b */ +#define VS1_INIT_LSB (1U << 2) /* 1b */ +#define VS1_CURR_LEVEL_LSB (1U << 3) /* 2b */ +#define VS1_NEXT_LEVEL_LSB (1U << 5) /* 2b */ +#define VS1_VOTE_LEVEL_LSB (1U << 7) /* 2b */ +#define VS1_TRIGGER_LSB (1U << 9) /* 1b */ +#define VS2_INIT_LEVEL_LSB (1U << 10) /* 3b */ +#define VS2_INIT_LSB (1U << 13) /* 1b */ +#define VS2_CURR_LEVEL_LSB (1U << 14) /* 3b */ +#define VS2_NEXT_LEVEL_LSB (1U << 17) /* 3b */ +#define VS2_VOTE_LEVEL_LSB (1U << 20) /* 3b */ +#define VS2_TRIGGER_LSB (1U << 23) /* 1b */ +#define VS1_FORCE_LSB (1U << 24) /* 1b */ +#define VS2_FORCE_LSB (1U << 25) /* 1b */ +#define VS1_VOTE_LEVEL_FORCE_LSB (1U << 26) /* 2b */ +#define VS2_VOTE_LEVEL_FORCE_LSB (1U << 28) /* 3b */ +/* RG_MODULE_SW_CG_0_MASK_REQ_0 (0x10006000+0x4B4) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_0_MASK_REQ_1 (0x10006000+0x4B8) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_0_MASK_REQ_2 (0x10006000+0x4BC) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_1_MASK_REQ_0 (0x10006000+0x4C0) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_1_MASK_REQ_1 (0x10006000+0x4C4) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_1_MASK_REQ_2 (0x10006000+0x4C8) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_2_MASK_REQ_0 (0x10006000+0x4CC) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_2_MASK_REQ_1 (0x10006000+0x4D0) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_2_MASK_REQ_2 (0x10006000+0x4D4) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_3_MASK_REQ_0 (0x10006000+0x4D8) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_3_MASK_REQ_1 (0x10006000+0x4DC) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_3_MASK_REQ_2 (0x10006000+0x4E0) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_MASK_REQ_0 (0x10006000+0x4E4) */ +#define PWR_STATUS_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_MASK_REQ_1 (0x10006000+0x4E8) */ +#define PWR_STATUS_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_MASK_REQ_2 (0x10006000+0x4EC) */ +#define PWR_STATUS_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* SPM_CG_CHECK_CON (0x10006000+0x4F0) */ +#define APMIXEDSYS_BUSY_MASK_REQ_0_LSB (1U << 0) /* 5b */ +#define APMIXEDSYS_BUSY_MASK_REQ_1_LSB (1U << 8) /* 5b */ +#define APMIXEDSYS_BUSY_MASK_REQ_2_LSB (1U << 16) /* 5b */ +#define AUDIOSYS_BUSY_MASK_REQ_0_LSB (1U << 24) /* 1b */ +#define AUDIOSYS_BUSY_MASK_REQ_1_LSB (1U << 25) /* 1b */ +#define AUDIOSYS_BUSY_MASK_REQ_2_LSB (1U << 26) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_0_LSB (1U << 27) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_1_LSB (1U << 28) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_2_LSB (1U << 29) /* 1b */ +/* SPM_SRC_RDY_STA (0x10006000+0x4F4) */ +#define SPM_INFRA_INTERNAL_ACK_LSB (1U << 0) /* 1b */ +#define SPM_VRF18_INTERNAL_ACK_LSB (1U << 1) /* 1b */ +/* SPM_DVS_DFS_LEVEL (0x10006000+0x4F8) */ +#define SPM_DFS_LEVEL_LSB (1U << 0) /* 16b */ +#define SPM_DVS_LEVEL_LSB (1U << 16) /* 16b */ +/* SPM_FORCE_DVFS (0x10006000+0x4FC) */ +#define FORCE_DVFS_LEVEL_LSB (1U << 0) /* 32b */ +/* SRCLKEN_RC_CFG (0x10006000+0x500) */ +#define SRCLKEN_RC_CFG_LSB (1U << 0) /* 32b */ +/* RC_CENTRAL_CFG1 (0x10006000+0x504) */ +#define RC_CENTRAL_CFG1_LSB (1U << 0) /* 32b */ +/* RC_CENTRAL_CFG2 (0x10006000+0x508) */ +#define RC_CENTRAL_CFG2_LSB (1U << 0) /* 32b */ +/* RC_CMD_ARB_CFG (0x10006000+0x50C) */ +#define RC_CMD_ARB_CFG_LSB (1U << 0) /* 32b */ +/* RC_PMIC_RCEN_ADDR (0x10006000+0x510) */ +#define RC_PMIC_RCEN_ADDR_LSB (1U << 0) /* 16b */ +#define RC_PMIC_RCEN_RESERVE_LSB (1U << 16) /* 16b */ +/* RC_PMIC_RCEN_SET_CLR_ADDR (0x10006000+0x514) */ +#define RC_PMIC_RCEN_SET_ADDR_LSB (1U << 0) /* 16b */ +#define RC_PMIC_RCEN_CLR_ADDR_LSB (1U << 16) /* 16b */ +/* RC_DCXO_FPM_CFG (0x10006000+0x518) */ +#define RC_DCXO_FPM_CFG_LSB (1U << 0) /* 32b */ +/* RC_CENTRAL_CFG3 (0x10006000+0x51C) */ +#define RC_CENTRAL_CFG3_LSB (1U << 0) /* 32b */ +/* RC_M00_SRCLKEN_CFG (0x10006000+0x520) */ +#define RC_M00_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +#define RC_SW_SRCLKEN_RC (1U << 3) /* 1b */ +#define RC_SW_SRCLKEN_FPM (1U << 4) /* 1b */ +/* RC_M01_SRCLKEN_CFG (0x10006000+0x524) */ +#define RC_M01_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M02_SRCLKEN_CFG (0x10006000+0x528) */ +#define RC_M02_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M03_SRCLKEN_CFG (0x10006000+0x52C) */ +#define RC_M03_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M04_SRCLKEN_CFG (0x10006000+0x530) */ +#define RC_M04_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M05_SRCLKEN_CFG (0x10006000+0x534) */ +#define RC_M05_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M06_SRCLKEN_CFG (0x10006000+0x538) */ +#define RC_M06_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M07_SRCLKEN_CFG (0x10006000+0x53C) */ +#define RC_M07_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M08_SRCLKEN_CFG (0x10006000+0x540) */ +#define RC_M08_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M09_SRCLKEN_CFG (0x10006000+0x544) */ +#define RC_M09_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M10_SRCLKEN_CFG (0x10006000+0x548) */ +#define RC_M10_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M11_SRCLKEN_CFG (0x10006000+0x54C) */ +#define RC_M11_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M12_SRCLKEN_CFG (0x10006000+0x550) */ +#define RC_M12_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_SRCLKEN_SW_CON_CFG (0x10006000+0x554) */ +#define RC_SRCLKEN_SW_CON_CFG_LSB (1U << 0) /* 32b */ +/* RC_CENTRAL_CFG4 (0x10006000+0x558) */ +#define RC_CENTRAL_CFG4_LSB (1U << 0) /* 32b */ +/* RC_PROTOCOL_CHK_CFG (0x10006000+0x560) */ +#define RC_PROTOCOL_CHK_CFG_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_CFG (0x10006000+0x564) */ +#define RC_DEBUG_CFG_LSB (1U << 0) /* 32b */ +/* RC_MISC_0 (0x10006000+0x5B4) */ +#define SRCCLKENO_LSB (1U << 0) /* 2b */ +#define PCM_SRCCLKENO_LSB (1U << 3) /* 2b */ +#define RC_VREQ_LSB (1U << 5) /* 1b */ +#define RC_SPM_SRCCLKENO_0_ACK_LSB (1U << 6) /* 1b */ +/* RC_SPM_CTRL (0x10006000+0x5B8) */ +#define SPM_AP_26M_RDY_LSB (1U << 0) /* 1b */ +#define KEEP_RC_SPI_ACTIVE_LSB (1U << 1) /* 1b */ +#define SPM2RC_DMY_CTRL_LSB (1U << 2) /* 6b */ +/* SUBSYS_INTF_CFG (0x10006000+0x5BC) */ +#define SRCLKEN_FPM_MASK_B_LSB (1U << 0) /* 13b */ +#define SRCLKEN_BBLPM_MASK_B_LSB (1U << 16) /* 13b */ +/* PCM_WDT_LATCH_25 (0x10006000+0x5C0) */ +#define PCM_WDT_LATCH_25_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_26 (0x10006000+0x5C4) */ +#define PCM_WDT_LATCH_26_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_27 (0x10006000+0x5C8) */ +#define PCM_WDT_LATCH_27_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_28 (0x10006000+0x5CC) */ +#define PCM_WDT_LATCH_28_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_29 (0x10006000+0x5D0) */ +#define PCM_WDT_LATCH_29_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_30 (0x10006000+0x5D4) */ +#define PCM_WDT_LATCH_30_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_31 (0x10006000+0x5D8) */ +#define PCM_WDT_LATCH_31_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_32 (0x10006000+0x5DC) */ +#define PCM_WDT_LATCH_32_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_33 (0x10006000+0x5E0) */ +#define PCM_WDT_LATCH_33_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_34 (0x10006000+0x5E4) */ +#define PCM_WDT_LATCH_34_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_35 (0x10006000+0x5EC) */ +#define PCM_WDT_LATCH_35_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_36 (0x10006000+0x5F0) */ +#define PCM_WDT_LATCH_36_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_37 (0x10006000+0x5F4) */ +#define PCM_WDT_LATCH_37_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_38 (0x10006000+0x5F8) */ +#define PCM_WDT_LATCH_38_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_39 (0x10006000+0x5FC) */ +#define PCM_WDT_LATCH_39_LSB (1U << 0) /* 32b */ +/* SPM_SW_FLAG_0 (0x10006000+0x600) */ +#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */ +/* SPM_SW_DEBUG_0 (0x10006000+0x604) */ +#define SPM_SW_DEBUG_0_LSB (1U << 0) /* 32b */ +/* SPM_SW_FLAG_1 (0x10006000+0x608) */ +#define SPM_SW_FLAG_1_LSB (1U << 0) /* 32b */ +/* SPM_SW_DEBUG_1 (0x10006000+0x60C) */ +#define SPM_SW_DEBUG_1_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_0 (0x10006000+0x610) */ +#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_1 (0x10006000+0x614) */ +#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_2 (0x10006000+0x618) */ +#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_3 (0x10006000+0x61C) */ +#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_4 (0x10006000+0x620) */ +#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_5 (0x10006000+0x624) */ +#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_6 (0x10006000+0x628) */ +#define SPM_SW_RSV_6_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_7 (0x10006000+0x62C) */ +#define SPM_SW_RSV_7_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_8 (0x10006000+0x630) */ +#define SPM_SW_RSV_8_LSB (1U << 0) /* 32b */ +/* SPM_BK_WAKE_EVENT (0x10006000+0x634) */ +#define SPM_BK_WAKE_EVENT_LSB (1U << 0) /* 32b */ +/* SPM_BK_VTCXO_DUR (0x10006000+0x638) */ +#define SPM_BK_VTCXO_DUR_LSB (1U << 0) /* 32b */ +/* SPM_BK_WAKE_MISC (0x10006000+0x63C) */ +#define SPM_BK_WAKE_MISC_LSB (1U << 0) /* 32b */ +/* SPM_BK_PCM_TIMER (0x10006000+0x640) */ +#define SPM_BK_PCM_TIMER_LSB (1U << 0) /* 32b */ +/* SPM_RSV_CON_0 (0x10006000+0x650) */ +#define SPM_RSV_CON_0_LSB (1U << 0) /* 32b */ +/* SPM_RSV_CON_1 (0x10006000+0x654) */ +#define SPM_RSV_CON_1_LSB (1U << 0) /* 32b */ +/* SPM_RSV_STA_0 (0x10006000+0x658) */ +#define SPM_RSV_STA_0_LSB (1U << 0) /* 32b */ +/* SPM_RSV_STA_1 (0x10006000+0x65C) */ +#define SPM_RSV_STA_1_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON (0x10006000+0x660) */ +#define SPM_SPARE_CON_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON_SET (0x10006000+0x664) */ +#define SPM_SPARE_CON_SET_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON_CLR (0x10006000+0x668) */ +#define SPM_SPARE_CON_CLR_LSB (1U << 0) /* 32b */ +/* SPM_CROSS_WAKE_M00_REQ (0x10006000+0x66C) */ +#define SPM_CROSS_WAKE_M00_REQ_LSB (1U << 0) /* 5b */ +#define SPM_CROSS_WAKE_M00_CHK_LSB (1U << 8) /* 5b */ +/* SPM_CROSS_WAKE_M01_REQ (0x10006000+0x670) */ +#define SPM_CROSS_WAKE_M01_REQ_LSB (1U << 0) /* 5b */ +#define SPM_CROSS_WAKE_M01_CHK_LSB (1U << 8) /* 5b */ +/* SPM_CROSS_WAKE_M02_REQ (0x10006000+0x674) */ +#define SPM_CROSS_WAKE_M02_REQ_LSB (1U << 0) /* 5b */ +#define SPM_CROSS_WAKE_M02_CHK_LSB (1U << 8) /* 5b */ +/* SPM_CROSS_WAKE_M03_REQ (0x10006000+0x678) */ +#define SPM_CROSS_WAKE_M03_REQ_LSB (1U << 0) /* 5b */ +#define SPM_CROSS_WAKE_M03_CHK_LSB (1U << 8) /* 5b */ +/* SCP_VCORE_LEVEL (0x10006000+0x67C) */ +#define SCP_VCORE_LEVEL_LSB (1U << 0) /* 16b */ +/* SC_MM_CK_SEL_CON (0x10006000+0x680) */ +#define SC_MM_CK_SEL_LSB (1U << 0) /* 4b */ +#define SC_MM_CK_SEL_EN_LSB (1U << 4) /* 1b */ +/* SPARE_ACK_MASK (0x10006000+0x684) */ +#define SPARE_ACK_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_CROSS_WAKE_M04_REQ (0x10006000+0x688) */ +#define SPM_CROSS_WAKE_M04_REQ_LSB (1U << 0) /* 5b */ +#define SPM_CROSS_WAKE_M04_CHK_LSB (1U << 8) /* 5b */ +/* SPM_DV_CON_0 (0x10006000+0x68C) */ +#define SPM_DV_CON_0_LSB (1U << 0) /* 32b */ +/* SPM_DV_CON_1 (0x10006000+0x690) */ +#define SPM_DV_CON_1_LSB (1U << 0) /* 32b */ +/* SPM_DV_STA (0x10006000+0x694) */ +#define SPM_DV_STA_LSB (1U << 0) /* 32b */ +/* CONN_XOWCN_DEBUG_EN (0x10006000+0x698) */ +#define CONN_XOWCN_DEBUG_EN_LSB (1U << 0) /* 1b */ +/* SPM_SEMA_M0 (0x10006000+0x69C) */ +#define SPM_SEMA_M0_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M1 (0x10006000+0x6A0) */ +#define SPM_SEMA_M1_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M2 (0x10006000+0x6A4) */ +#define SPM_SEMA_M2_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M3 (0x10006000+0x6A8) */ +#define SPM_SEMA_M3_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M4 (0x10006000+0x6AC) */ +#define SPM_SEMA_M4_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M5 (0x10006000+0x6B0) */ +#define SPM_SEMA_M5_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M6 (0x10006000+0x6B4) */ +#define SPM_SEMA_M6_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M7 (0x10006000+0x6B8) */ +#define SPM_SEMA_M7_LSB (1U << 0) /* 8b */ +/* SPM2ADSP_MAILBOX (0x10006000+0x6BC) */ +#define SPM2ADSP_MAILBOX_LSB (1U << 0) /* 32b */ +/* ADSP2SPM_MAILBOX (0x10006000+0x6C0) */ +#define ADSP2SPM_MAILBOX_LSB (1U << 0) /* 32b */ +/* SPM_ADSP_IRQ (0x10006000+0x6C4) */ +#define SC_SPM2ADSP_WAKEUP_LSB (1U << 0) /* 1b */ +#define SPM_ADSP_IRQ_SC_ADSP2SPM_WAKEUP_LSB (1U << 4) /* 1b */ +/* SPM_MD32_IRQ (0x10006000+0x6C8) */ +#define SC_SPM2SSPM_WAKEUP_LSB (1U << 0) /* 4b */ +#define SPM_MD32_IRQ_SC_SSPM2SPM_WAKEUP_LSB (1U << 4) /* 4b */ +/* SPM2PMCU_MAILBOX_0 (0x10006000+0x6CC) */ +#define SPM2PMCU_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_1 (0x10006000+0x6D0) */ +#define SPM2PMCU_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_2 (0x10006000+0x6D4) */ +#define SPM2PMCU_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_3 (0x10006000+0x6D8) */ +#define SPM2PMCU_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_0 (0x10006000+0x6DC) */ +#define PMCU2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_1 (0x10006000+0x6E0) */ +#define PMCU2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_2 (0x10006000+0x6E4) */ +#define PMCU2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_3 (0x10006000+0x6E8) */ +#define PMCU2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* UFS_PSRI_SW (0x10006000+0x6EC) */ +#define UFS_PSRI_SW_LSB (1U << 0) /* 1b */ +/* UFS_PSRI_SW_SET (0x10006000+0x6F0) */ +#define UFS_PSRI_SW_SET_LSB (1U << 0) /* 1b */ +/* UFS_PSRI_SW_CLR (0x10006000+0x6F4) */ +#define UFS_PSRI_SW_CLR_LSB (1U << 0) /* 1b */ +/* SPM_AP_SEMA (0x10006000+0x6F8) */ +#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */ +/* SPM_SPM_SEMA (0x10006000+0x6FC) */ +#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */ +/* SPM_DVFS_CON (0x10006000+0x700) */ +#define SPM_DVFS_CON_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CON_STA (0x10006000+0x704) */ +#define SPM_DVFS_CON_STA_LSB (1U << 0) /* 32b */ +/* SPM_PMIC_SPMI_CON (0x10006000+0x708) */ +#define SPM_PMIC_SPMI_CMD_LSB (1U << 0) /* 2b */ +#define SPM_PMIC_SPMI_SLAVEID_LSB (1U << 2) /* 4b */ +#define SPM_PMIC_SPMI_PMIFID_LSB (1U << 6) /* 1b */ +#define SPM_PMIC_SPMI_DBCNT_LSB (1U << 7) /* 1b */ +/* SPM_DVFS_CMD0 (0x10006000+0x710) */ +#define SPM_DVFS_CMD0_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD1 (0x10006000+0x714) */ +#define SPM_DVFS_CMD1_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD2 (0x10006000+0x718) */ +#define SPM_DVFS_CMD2_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD3 (0x10006000+0x71C) */ +#define SPM_DVFS_CMD3_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD4 (0x10006000+0x720) */ +#define SPM_DVFS_CMD4_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD5 (0x10006000+0x724) */ +#define SPM_DVFS_CMD5_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD6 (0x10006000+0x728) */ +#define SPM_DVFS_CMD6_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD7 (0x10006000+0x72C) */ +#define SPM_DVFS_CMD7_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD8 (0x10006000+0x730) */ +#define SPM_DVFS_CMD8_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD9 (0x10006000+0x734) */ +#define SPM_DVFS_CMD9_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD10 (0x10006000+0x738) */ +#define SPM_DVFS_CMD10_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD11 (0x10006000+0x73C) */ +#define SPM_DVFS_CMD11_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD12 (0x10006000+0x740) */ +#define SPM_DVFS_CMD12_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD13 (0x10006000+0x744) */ +#define SPM_DVFS_CMD13_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD14 (0x10006000+0x748) */ +#define SPM_DVFS_CMD14_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD15 (0x10006000+0x74C) */ +#define SPM_DVFS_CMD15_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD16 (0x10006000+0x750) */ +#define SPM_DVFS_CMD16_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD17 (0x10006000+0x754) */ +#define SPM_DVFS_CMD17_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD18 (0x10006000+0x758) */ +#define SPM_DVFS_CMD18_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD19 (0x10006000+0x75C) */ +#define SPM_DVFS_CMD19_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD20 (0x10006000+0x760) */ +#define SPM_DVFS_CMD20_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD21 (0x10006000+0x764) */ +#define SPM_DVFS_CMD21_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD22 (0x10006000+0x768) */ +#define SPM_DVFS_CMD22_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD23 (0x10006000+0x76C) */ +#define SPM_DVFS_CMD23_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_VALUE_L (0x10006000+0x770) */ +#define SYS_TIMER_VALUE_L_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_VALUE_H (0x10006000+0x774) */ +#define SYS_TIMER_VALUE_H_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_START_L (0x10006000+0x778) */ +#define SYS_TIMER_START_L_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_START_H (0x10006000+0x77C) */ +#define SYS_TIMER_START_H_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_00 (0x10006000+0x780) */ +#define SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_00 (0x10006000+0x784) */ +#define SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_01 (0x10006000+0x788) */ +#define SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_01 (0x10006000+0x78C) */ +#define SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_02 (0x10006000+0x790) */ +#define SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_02 (0x10006000+0x794) */ +#define SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_03 (0x10006000+0x798) */ +#define SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_03 (0x10006000+0x79C) */ +#define SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_04 (0x10006000+0x7A0) */ +#define SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_04 (0x10006000+0x7A4) */ +#define SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_05 (0x10006000+0x7A8) */ +#define SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_05 (0x10006000+0x7AC) */ +#define SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_06 (0x10006000+0x7B0) */ +#define SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_06 (0x10006000+0x7B4) */ +#define SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_07 (0x10006000+0x7B8) */ +#define SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_07 (0x10006000+0x7BC) */ +#define SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_08 (0x10006000+0x7C0) */ +#define SYS_TIMER_LATCH_L_08_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_08 (0x10006000+0x7C4) */ +#define SYS_TIMER_LATCH_H_08_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_09 (0x10006000+0x7C8) */ +#define SYS_TIMER_LATCH_L_09_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_09 (0x10006000+0x7CC) */ +#define SYS_TIMER_LATCH_H_09_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_10 (0x10006000+0x7D0) */ +#define SYS_TIMER_LATCH_L_10_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_10 (0x10006000+0x7D4) */ +#define SYS_TIMER_LATCH_H_10_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_11 (0x10006000+0x7D8) */ +#define SYS_TIMER_LATCH_L_11_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_11 (0x10006000+0x7DC) */ +#define SYS_TIMER_LATCH_H_11_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_12 (0x10006000+0x7E0) */ +#define SYS_TIMER_LATCH_L_12_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_12 (0x10006000+0x7E4) */ +#define SYS_TIMER_LATCH_H_12_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_13 (0x10006000+0x7E8) */ +#define SYS_TIMER_LATCH_L_13_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_13 (0x10006000+0x7EC) */ +#define SYS_TIMER_LATCH_H_13_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_14 (0x10006000+0x7F0) */ +#define SYS_TIMER_LATCH_L_14_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_14 (0x10006000+0x7F4) */ +#define SYS_TIMER_LATCH_H_14_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_15 (0x10006000+0x7F8) */ +#define SYS_TIMER_LATCH_L_15_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_15 (0x10006000+0x7FC) */ +#define SYS_TIMER_LATCH_H_15_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_0 (0x10006000+0x800) */ +#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_1 (0x10006000+0x804) */ +#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_2 (0x10006000+0x808) */ +#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_3 (0x10006000+0x80C) */ +#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_4 (0x10006000+0x810) */ +#define PCM_WDT_LATCH_4_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_5 (0x10006000+0x814) */ +#define PCM_WDT_LATCH_5_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_6 (0x10006000+0x818) */ +#define PCM_WDT_LATCH_6_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_7 (0x10006000+0x81C) */ +#define PCM_WDT_LATCH_7_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_8 (0x10006000+0x820) */ +#define PCM_WDT_LATCH_8_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_9 (0x10006000+0x824) */ +#define PCM_WDT_LATCH_9_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_10 (0x10006000+0x828) */ +#define PCM_WDT_LATCH_10_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_11 (0x10006000+0x82C) */ +#define PCM_WDT_LATCH_11_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_12 (0x10006000+0x830) */ +#define PCM_WDT_LATCH_12_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_13 (0x10006000+0x834) */ +#define PCM_WDT_LATCH_13_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_14 (0x10006000+0x838) */ +#define PCM_WDT_LATCH_14_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_15 (0x10006000+0x83C) */ +#define PCM_WDT_LATCH_15_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_16 (0x10006000+0x840) */ +#define PCM_WDT_LATCH_16_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_17 (0x10006000+0x844) */ +#define PCM_WDT_LATCH_17_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_18 (0x10006000+0x848) */ +#define PCM_WDT_LATCH_18_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_SPARE_0 (0x10006000+0x84C) */ +#define PCM_WDT_LATCH_SPARE_0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_SPARE_1 (0x10006000+0x850) */ +#define PCM_WDT_LATCH_SPARE_1_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_SPARE_2 (0x10006000+0x854) */ +#define PCM_WDT_LATCH_SPARE_2_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_CONN_0 (0x10006000+0x870) */ +#define PCM_WDT_LATCH_CONN_0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_CONN_1 (0x10006000+0x874) */ +#define PCM_WDT_LATCH_CONN_1_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_CONN_2 (0x10006000+0x878) */ +#define PCM_WDT_LATCH_CONN_2_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_0 (0x10006000+0x8A0) */ +#define DRAMC_GATING_ERR_LATCH_CH0_0_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_1 (0x10006000+0x8A4) */ +#define DRAMC_GATING_ERR_LATCH_CH0_1_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_2 (0x10006000+0x8A8) */ +#define DRAMC_GATING_ERR_LATCH_CH0_2_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_3 (0x10006000+0x8AC) */ +#define DRAMC_GATING_ERR_LATCH_CH0_3_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_4 (0x10006000+0x8B0) */ +#define DRAMC_GATING_ERR_LATCH_CH0_4_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_5 (0x10006000+0x8B4) */ +#define DRAMC_GATING_ERR_LATCH_CH0_5_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_6 (0x10006000+0x8B8) */ +#define DRAMC_GATING_ERR_LATCH_CH0_6_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_SPARE_0 (0x10006000+0x8F4) */ +#define DRAMC_GATING_ERR_LATCH_SPARE_0_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON_0 (0x10006000+0x900) */ +#define SPM_ACK_CHK_SW_EN_0_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_0_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_0_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_0_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_0_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_0_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_0_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_0_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_0_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_0_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_0_LSB (1U << 15) /* 1b */ +/* SPM_ACK_CHK_PC_0 (0x10006000+0x904) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_0_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_0_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL_0 (0x10006000+0x908) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_0_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_0_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_0_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_0_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER_0 (0x10006000+0x90C) */ +#define SPM_ACK_CHK_TIMER_VAL_0_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_0_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA_0 (0x10006000+0x910) */ +#define SPM_ACK_CHK_STA_0_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_SWINT_0 (0x10006000+0x914) */ +#define SPM_ACK_CHK_SWINT_EN_0_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON_1 (0x10006000+0x920) */ +#define SPM_ACK_CHK_SW_EN_1_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_1_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_1_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_1_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_1_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_1_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_1_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_1_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_1_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_1_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_1_LSB (1U << 15) /* 1b */ +/* SPM_ACK_CHK_PC_1 (0x10006000+0x924) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_1_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_1_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL_1 (0x10006000+0x928) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_1_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_1_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_1_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_1_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER_1 (0x10006000+0x92C) */ +#define SPM_ACK_CHK_TIMER_VAL_1_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_1_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA_1 (0x10006000+0x930) */ +#define SPM_ACK_CHK_STA_1_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_SWINT_1 (0x10006000+0x934) */ +#define SPM_ACK_CHK_SWINT_EN_1_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON_2 (0x10006000+0x940) */ +#define SPM_ACK_CHK_SW_EN_2_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_2_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_2_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_2_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_2_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_2_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_2_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_2_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_2_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_2_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_2_LSB (1U << 15) /* 1b */ +/* SPM_ACK_CHK_PC_2 (0x10006000+0x944) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_2_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_2_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL_2 (0x10006000+0x948) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_2_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_2_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_2_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_2_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER_2 (0x10006000+0x94C) */ +#define SPM_ACK_CHK_TIMER_VAL_2_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_2_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA_2 (0x10006000+0x950) */ +#define SPM_ACK_CHK_STA_2_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_SWINT_2 (0x10006000+0x954) */ +#define SPM_ACK_CHK_SWINT_EN_2_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON_3 (0x10006000+0x960) */ +#define SPM_ACK_CHK_SW_EN_3_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_3_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_3_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_3_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_3_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_3_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_3_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_3_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_3_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_3_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_3_LSB (1U << 15) /* 1b */ +/* SPM_ACK_CHK_PC_3 (0x10006000+0x964) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_3_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_3_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL_3 (0x10006000+0x968) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_3_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_3_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_3_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_3_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER_3 (0x10006000+0x96C) */ +#define SPM_ACK_CHK_TIMER_VAL_3_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_3_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA_3 (0x10006000+0x970) */ +#define SPM_ACK_CHK_STA_3_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_SWINT_3 (0x10006000+0x974) */ +#define SPM_ACK_CHK_SWINT_EN_3_LSB (1U << 0) /* 32b */ +/* SPM_COUNTER_0 (0x10006000+0x978) */ +#define SPM_COUNTER_VAL_0_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_0_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_0_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_0_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_0_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_0_LSB (1U << 31) /* 1b */ +/* SPM_COUNTER_1 (0x10006000+0x97C) */ +#define SPM_COUNTER_VAL_1_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_1_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_1_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_1_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_1_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_1_LSB (1U << 31) /* 1b */ +/* SPM_COUNTER_2 (0x10006000+0x980) */ +#define SPM_COUNTER_VAL_2_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_2_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_2_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_2_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_2_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_2_LSB (1U << 31) /* 1b */ +/* SYS_TIMER_CON (0x10006000+0x98C) */ +#define SYS_TIMER_START_EN_LSB (1U << 0) /* 1b */ +#define SYS_TIMER_LATCH_EN_LSB (1U << 1) /* 1b */ +#define SYS_TIMER_ID_LSB (1U << 8) /* 8b */ +#define SYS_TIMER_VALID_LSB (1U << 31) /* 1b */ +/* RC_FSM_STA_0 (0x10006000+0xE00) */ +#define RC_FSM_STA_0_LSB (1U << 0) /* 32b */ +/* RC_CMD_STA_0 (0x10006000+0xE04) */ +#define RC_CMD_STA_0_LSB (1U << 0) /* 32b */ +/* RC_CMD_STA_1 (0x10006000+0xE08) */ +#define RC_CMD_STA_1_LSB (1U << 0) /* 32b */ +/* RC_SPI_STA_0 (0x10006000+0xE0C) */ +#define RC_SPI_STA_0_LSB (1U << 0) /* 32b */ +/* RC_PI_PO_STA_0 (0x10006000+0xE10) */ +#define RC_PI_PO_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M00_REQ_STA_0 (0x10006000+0xE14) */ +#define RC_M00_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M01_REQ_STA_0 (0x10006000+0xE1C) */ +#define RC_M01_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M02_REQ_STA_0 (0x10006000+0xE20) */ +#define RC_M02_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M03_REQ_STA_0 (0x10006000+0xE24) */ +#define RC_M03_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M04_REQ_STA_0 (0x10006000+0xE28) */ +#define RC_M04_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M05_REQ_STA_0 (0x10006000+0xE2C) */ +#define RC_M05_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M06_REQ_STA_0 (0x10006000+0xE30) */ +#define RC_M06_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M07_REQ_STA_0 (0x10006000+0xE34) */ +#define RC_M07_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M08_REQ_STA_0 (0x10006000+0xE38) */ +#define RC_M08_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M09_REQ_STA_0 (0x10006000+0xE3C) */ +#define RC_M09_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M10_REQ_STA_0 (0x10006000+0xE40) */ +#define RC_M10_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M11_REQ_STA_0 (0x10006000+0xE44) */ +#define RC_M11_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M12_REQ_STA_0 (0x10006000+0xE48) */ +#define RC_M12_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_STA_0 (0x10006000+0xE4C) */ +#define RC_DEBUG_STA_0_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_0_LSB (0x10006000+0xE50) */ +#define RO_PMRC_TRACE_00_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_0_MSB (0x10006000+0xE54) */ +#define RO_PMRC_TRACE_00_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_1_LSB (0x10006000+0xE5C) */ +#define RO_PMRC_TRACE_01_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_1_MSB (0x10006000+0xE60) */ +#define RO_PMRC_TRACE_01_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_2_LSB (0x10006000+0xE64) */ +#define RO_PMRC_TRACE_02_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_2_MSB (0x10006000+0xE6C) */ +#define RO_PMRC_TRACE_02_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_3_LSB (0x10006000+0xE70) */ +#define RO_PMRC_TRACE_03_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_3_MSB (0x10006000+0xE74) */ +#define RO_PMRC_TRACE_03_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_4_LSB (0x10006000+0xE78) */ +#define RO_PMRC_TRACE_04_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_4_MSB (0x10006000+0xE7C) */ +#define RO_PMRC_TRACE_04_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_5_LSB (0x10006000+0xE80) */ +#define RO_PMRC_TRACE_05_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_5_MSB (0x10006000+0xE84) */ +#define RO_PMRC_TRACE_05_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_6_LSB (0x10006000+0xE88) */ +#define RO_PMRC_TRACE_06_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_6_MSB (0x10006000+0xE8C) */ +#define RO_PMRC_TRACE_06_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_7_LSB (0x10006000+0xE90) */ +#define RO_PMRC_TRACE_07_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_7_MSB (0x10006000+0xE94) */ +#define RO_PMRC_TRACE_07_MSB_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_0_LSB (0x10006000+0xE98) */ +#define RC_SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_0_MSB (0x10006000+0xE9C) */ +#define RC_SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_1_LSB (0x10006000+0xEA0) */ +#define RC_SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_1_MSB (0x10006000+0xEA4) */ +#define RC_SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_2_LSB (0x10006000+0xEA8) */ +#define RC_SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_2_MSB (0x10006000+0xEAC) */ +#define RC_SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_3_LSB (0x10006000+0xEB0) */ +#define RC_SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_3_MSB (0x10006000+0xEB4) */ +#define RC_SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_4_LSB (0x10006000+0xEB8) */ +#define RC_SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_4_MSB (0x10006000+0xEBC) */ +#define RC_SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_5_LSB (0x10006000+0xEC0) */ +#define RC_SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_5_MSB (0x10006000+0xEC4) */ +#define RC_SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_6_LSB (0x10006000+0xEC8) */ +#define RC_SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_6_MSB (0x10006000+0xECC) */ +#define RC_SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_7_LSB (0x10006000+0xED0) */ +#define RC_SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_7_MSB (0x10006000+0xED4) */ +#define RC_SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_19 (0x10006000+0xED8) */ +#define PCM_WDT_LATCH_19_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_20 (0x10006000+0xEDC) */ +#define PCM_WDT_LATCH_20_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_21 (0x10006000+0xEE0) */ +#define PCM_WDT_LATCH_21_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_22 (0x10006000+0xEE4) */ +#define PCM_WDT_LATCH_22_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_23 (0x10006000+0xEE8) */ +#define PCM_WDT_LATCH_23_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_24 (0x10006000+0xEEC) */ +#define PCM_WDT_LATCH_24_LSB (1U << 0) /* 32b */ +/* PMSR_LAST_DAT (0x10006000+0xF00) */ +#define PMSR_LAST_DAT_LSB (1U << 0) /* 32b */ +/* PMSR_LAST_CNT (0x10006000+0xF04) */ +#define PMSR_LAST_CMD_LSB (1U << 0) /* 30b */ +#define PMSR_LAST_REQ_LSB (1U << 30) /* 1b */ +/* PMSR_LAST_ACK (0x10006000+0xF08) */ +#define PMSR_LAST_ACK_LSB (1U << 0) /* 1b */ +/* SPM_PMSR_SEL_CON0 (0x10006000+0xF10) */ +#define REG_PMSR_SIG_SEL_0_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_1_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_2_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_3_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON1 (0x10006000+0xF14) */ +#define REG_PMSR_SIG_SEL_4_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_5_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_6_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_7_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON2 (0x10006000+0xF18) */ +#define REG_PMSR_SIG_SEL_8_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_9_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_10_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_11_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON3 (0x10006000+0xF1C) */ +#define REG_PMSR_SIG_SEL_12_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_13_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_14_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_15_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON4 (0x10006000+0xF20) */ +#define REG_PMSR_SIG_SEL_16_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_17_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_18_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_19_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON5 (0x10006000+0xF24) */ +#define REG_PMSR_SIG_SEL_20_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_21_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_22_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_23_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON6 (0x10006000+0xF28) */ +#define REG_PMSR_SIG_SEL_24_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_25_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_26_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_27_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON7 (0x10006000+0xF2C) */ +#define REG_PMSR_SIG_SEL_28_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_29_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_30_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_31_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON8 (0x10006000+0xF30) */ +#define REG_PMSR_SIG_SEL_32_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_33_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_34_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_35_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON9 (0x10006000+0xF34) */ +#define REG_PMSR_SIG_SEL_36_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_37_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_38_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_39_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON10 (0x10006000+0xF3C) */ +#define REG_PMSR_SIG_SEL_40_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_41_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_42_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_43_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON11 (0x10006000+0xF40) */ +#define REG_PMSR_SIG_SEL_44_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_45_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_46_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_47_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_TIEMR_STA0 (0x10006000+0xFB8) */ +#define PMSR_TIMER_SET0_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_TIEMR_STA1 (0x10006000+0xFBC) */ +#define PMSR_TIMER_SET1_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_TIEMR_STA2 (0x10006000+0xFC0) */ +#define PMSR_TIMER_SET2_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON0 (0x10006000+0xFC4) */ +#define PMSR_ENABLE_SET0_LSB (1U << 0) /* 1b */ +#define PMSR_ENABLE_SET1_LSB (1U << 1) /* 1b */ +#define PMSR_ENABLE_SET2_LSB (1U << 2) /* 1b */ +#define PMSR_IRQ_CLR_SET0_LSB (1U << 3) /* 1b */ +#define PMSR_IRQ_CLR_SET1_LSB (1U << 4) /* 1b */ +#define PMSR_IRQ_CLR_SET2_LSB (1U << 5) /* 1b */ +#define PMSR_SPEED_MODE_EN_SET0_LSB (1U << 6) /* 1b */ +#define PMSR_SPEED_MODE_EN_SET1_LSB (1U << 7) /* 1b */ +#define PMSR_SPEED_MODE_EN_SET2_LSB (1U << 8) /* 1b */ +#define PMSR_EVENT_CLR_SET0_LSB (1U << 9) /* 1b */ +#define PMSR_EVENT_CLR_SET1_LSB (1U << 10) /* 1b */ +#define PMSR_EVENT_CLR_SET2_LSB (1U << 11) /* 1b */ +#define REG_PMSR_IRQ_MASK_SET0_LSB (1U << 12) /* 1b */ +#define REG_PMSR_IRQ_MASK_SET1_LSB (1U << 13) /* 1b */ +#define REG_PMSR_IRQ_MASK_SET2_LSB (1U << 14) /* 1b */ +#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET0_LSB (1U << 15) /* 1b */ +#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET1_LSB (1U << 16) /* 1b */ +#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET2_LSB (1U << 17) /* 1b */ +#define PMSR_GEN_SW_RST_EN_LSB (1U << 18) /* 1b */ +#define PMSR_MODULE_ENABLE_LSB (1U << 19) /* 1b */ +#define PMSR_MODE_LSB (1U << 20) /* 2b */ +#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET0_LSB (1U << 29) /* 1b */ +#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET1_LSB (1U << 30) /* 1b */ +#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET2_LSB (1U << 31) /* 1b */ +/* SPM_PMSR_GENERAL_CON1 (0x10006000+0xFC8) */ +#define PMSR_COUNTER_THRES_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON2 (0x10006000+0xFCC) */ +#define PMSR_DEBUG_IN_0_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON3 (0x10006000+0xFD0) */ +#define PMSR_DEBUG_IN_1_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON4 (0x10006000+0xFD4) */ +#define PMSR_DEBUG_IN_2_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON5 (0x10006000+0xFD8) */ +#define PMSR_DEBUG_IN_3_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_SW_RESET (0x10006000+0xFDC) */ +#define PMSR_SW_RST_EN_SET0_LSB (1U << 0) /* 1b */ +#define PMSR_SW_RST_EN_SET1_LSB (1U << 1) /* 1b */ +#define PMSR_SW_RST_EN_SET2_LSB (1U << 2) /* 1b */ +/* SPM_PMSR_MON_CON0 (0x10006000+0xFE0) */ +#define REG_PMSR_MON_TYPE_0_LSB (1U << 0) /* 2b */ +#define REG_PMSR_MON_TYPE_1_LSB (1U << 2) /* 2b */ +#define REG_PMSR_MON_TYPE_2_LSB (1U << 4) /* 2b */ +#define REG_PMSR_MON_TYPE_3_LSB (1U << 6) /* 2b */ +#define REG_PMSR_MON_TYPE_4_LSB (1U << 8) /* 2b */ +#define REG_PMSR_MON_TYPE_5_LSB (1U << 10) /* 2b */ +#define REG_PMSR_MON_TYPE_6_LSB (1U << 12) /* 2b */ +#define REG_PMSR_MON_TYPE_7_LSB (1U << 14) /* 2b */ +#define REG_PMSR_MON_TYPE_8_LSB (1U << 16) /* 2b */ +#define REG_PMSR_MON_TYPE_9_LSB (1U << 18) /* 2b */ +#define REG_PMSR_MON_TYPE_10_LSB (1U << 20) /* 2b */ +#define REG_PMSR_MON_TYPE_11_LSB (1U << 22) /* 2b */ +#define REG_PMSR_MON_TYPE_12_LSB (1U << 24) /* 2b */ +#define REG_PMSR_MON_TYPE_13_LSB (1U << 26) /* 2b */ +#define REG_PMSR_MON_TYPE_14_LSB (1U << 28) /* 2b */ +#define REG_PMSR_MON_TYPE_15_LSB (1U << 30) /* 2b */ +/* SPM_PMSR_MON_CON1 (0x10006000+0xFE4) */ +#define REG_PMSR_MON_TYPE_16_LSB (1U << 0) /* 2b */ +#define REG_PMSR_MON_TYPE_17_LSB (1U << 2) /* 2b */ +#define REG_PMSR_MON_TYPE_18_LSB (1U << 4) /* 2b */ +#define REG_PMSR_MON_TYPE_19_LSB (1U << 6) /* 2b */ +#define REG_PMSR_MON_TYPE_20_LSB (1U << 8) /* 2b */ +#define REG_PMSR_MON_TYPE_21_LSB (1U << 10) /* 2b */ +#define REG_PMSR_MON_TYPE_22_LSB (1U << 12) /* 2b */ +#define REG_PMSR_MON_TYPE_23_LSB (1U << 14) /* 2b */ +#define REG_PMSR_MON_TYPE_24_LSB (1U << 16) /* 2b */ +#define REG_PMSR_MON_TYPE_25_LSB (1U << 18) /* 2b */ +#define REG_PMSR_MON_TYPE_26_LSB (1U << 20) /* 2b */ +#define REG_PMSR_MON_TYPE_27_LSB (1U << 22) /* 2b */ +#define REG_PMSR_MON_TYPE_28_LSB (1U << 24) /* 2b */ +#define REG_PMSR_MON_TYPE_29_LSB (1U << 26) /* 2b */ +#define REG_PMSR_MON_TYPE_30_LSB (1U << 28) /* 2b */ +#define REG_PMSR_MON_TYPE_31_LSB (1U << 30) /* 2b */ +/* SPM_PMSR_MON_CON2 (0x10006000+0xFE8) */ +#define REG_PMSR_MON_TYPE_32_LSB (1U << 0) /* 2b */ +#define REG_PMSR_MON_TYPE_33_LSB (1U << 2) /* 2b */ +#define REG_PMSR_MON_TYPE_34_LSB (1U << 4) /* 2b */ +#define REG_PMSR_MON_TYPE_35_LSB (1U << 6) /* 2b */ +#define REG_PMSR_MON_TYPE_36_LSB (1U << 8) /* 2b */ +#define REG_PMSR_MON_TYPE_37_LSB (1U << 10) /* 2b */ +#define REG_PMSR_MON_TYPE_38_LSB (1U << 12) /* 2b */ +#define REG_PMSR_MON_TYPE_39_LSB (1U << 14) /* 2b */ +#define REG_PMSR_MON_TYPE_40_LSB (1U << 16) /* 2b */ +#define REG_PMSR_MON_TYPE_41_LSB (1U << 18) /* 2b */ +#define REG_PMSR_MON_TYPE_42_LSB (1U << 20) /* 2b */ +#define REG_PMSR_MON_TYPE_43_LSB (1U << 22) /* 2b */ +#define REG_PMSR_MON_TYPE_44_LSB (1U << 24) /* 2b */ +#define REG_PMSR_MON_TYPE_45_LSB (1U << 26) /* 2b */ +#define REG_PMSR_MON_TYPE_46_LSB (1U << 28) /* 2b */ +#define REG_PMSR_MON_TYPE_47_LSB (1U << 30) /* 2b */ +/* SPM_PMSR_LEN_CON0 (0x10006000+0xFEC) */ +#define REG_PMSR_WINDOW_LEN_SET0_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_LEN_CON1 (0x10006000+0xFF0) */ +#define REG_PMSR_WINDOW_LEN_SET1_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_LEN_CON2 (0x10006000+0xFF4) */ +#define REG_PMSR_WINDOW_LEN_SET2_LSB (1U << 0) /* 32b */ + +#define SPM_PROJECT_CODE 0xb16 +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) +#endif /* MT_SPM_REG */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h new file mode 100644 index 0000000..30194eb --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_RESOURCE_REQ_H +#define MT_SPM_RESOURCE_REQ_H + +/* SPM resource request internal bit */ +#define MT_SPM_BIT_XO_FPM 0 +#define MT_SPM_BIT_26M 1 +#define MT_SPM_BIT_INFRA 2 +#define MT_SPM_BIT_SYSPLL 3 +#define MT_SPM_BIT_DRAM_S0 4 +#define MT_SPM_BIT_DRAM_S1 5 + +/* SPM resource request internal bit_mask */ +#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM) +#define MT_SPM_26M BIT(MT_SPM_BIT_26M) +#define MT_SPM_INFRA BIT(MT_SPM_BIT_INFRA) +#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL) +#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0) +#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1) +#endif /* MT_SPM_RESOURCE_REQ_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c new file mode 100644 index 0000000..3eb73d4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPM_SUSPEND_SLEEP_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ + SPM_FLAG_USE_SRCCLKENO2 | \ + SPM_FLAG_ENABLE_MD_MUMTAS | \ + SPM_FLAG_SRAM_SLEEP_CTRL) + +#define SPM_SUSPEND_SLEEP_PCM_FLAG1 \ + (SPM_FLAG1_DISABLE_MD26M_CK_OFF) + +#define SPM_SUSPEND_PCM_FLAG \ + (SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_ENABLE_TIA_WORKAROUND | \ + SPM_FLAG_ENABLE_MD_MUMTAS | \ + SPM_FLAG_SRAM_SLEEP_CTRL) + +#define SPM_SUSPEND_PCM_FLAG1 \ + (SPM_FLAG1_DISABLE_MD26M_CK_OFF) + +#define __WAKE_SRC_FOR_SUSPEND_COMMON__ \ + (R12_PCM_TIMER | \ + R12_KP_IRQ_B | \ + R12_APWDT_EVENT_B | \ + R12_APXGPT1_EVENT_B | \ + R12_CONN2AP_SPM_WAKEUP_B | \ + R12_EINT_EVENT_B | \ + R12_CONN_WDT_IRQ_B | \ + R12_CCIF0_EVENT_B | \ + R12_SSPM2SPM_WAKEUP_B | \ + R12_SCP2SPM_WAKEUP_B | \ + R12_ADSP2SPM_WAKEUP_B | \ + R12_USBX_CDSC_B | \ + R12_USBX_POWERDWN_B | \ + R12_SYS_TIMER_EVENT_B | \ + R12_EINT_EVENT_SECURE_B | \ + R12_CCIF1_EVENT_B | \ + R12_SYS_CIRQ_IRQ_B | \ + R12_MD2AP_PEER_EVENT_B | \ + R12_MD1_WDT_B | \ + R12_CLDMA_EVENT_B | \ + R12_REG_CPU_WAKEUP | \ + R12_APUSYS_WAKE_HOST_B | \ + R12_PCIE_BRIDGE_IRQ | \ + R12_PCIE_IRQ) + +#if defined(CFG_MICROTRUST_TEE_SUPPORT) +#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__) +#else +#define WAKE_SRC_FOR_SUSPEND \ + (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \ + R12_SEJ_EVENT_B) +#endif + +static struct pwr_ctrl suspend_ctrl = { + .wake_src = WAKE_SRC_FOR_SUSPEND, + .pcm_flags = SPM_SUSPEND_PCM_FLAG | SPM_FLAG_DISABLE_INFRA_PDN, + .pcm_flags1 = SPM_SUSPEND_PCM_FLAG1, + + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + .reg_wfi_op = 0, + .reg_wfi_type = 0, + .reg_mp0_cputop_idle_mask = 0, + .reg_mp1_cputop_idle_mask = 0, + .reg_mcusys_idle_mask = 0, + .reg_md_apsrc_1_sel = 0, + .reg_md_apsrc_0_sel = 0, + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC6_MASK */ + .reg_dpmaif_srcclkena_mask_b = 1, + .reg_dpmaif_infra_req_mask_b = 1, + .reg_dpmaif_apsrc_req_mask_b = 1, + .reg_dpmaif_vrf18_req_mask_b = 1, + .reg_dpmaif_ddr_en_mask_b = 1, + + /* SPM_SRC_REQ */ + .reg_spm_apsrc_req = 0, + .reg_spm_f26m_req = 0, + .reg_spm_infra_req = 0, + .reg_spm_vrf18_req = 0, + .reg_spm_ddr_en_req = 0, + .reg_spm_dvfs_req = 0, + .reg_spm_sw_mailbox_req = 0, + .reg_spm_sspm_mailbox_req = 0, + .reg_spm_adsp_mailbox_req = 0, + .reg_spm_scp_mailbox_req = 0, + + /* SPM_SRC_MASK */ + .reg_md_srcclkena_0_mask_b = 1, + .reg_md_srcclkena2infra_req_0_mask_b = 0, + .reg_md_apsrc2infra_req_0_mask_b = 1, + .reg_md_apsrc_req_0_mask_b = 1, + .reg_md_vrf18_req_0_mask_b = 1, + .reg_md_ddr_en_0_mask_b = 1, + .reg_md_srcclkena_1_mask_b = 0, + .reg_md_srcclkena2infra_req_1_mask_b = 0, + .reg_md_apsrc2infra_req_1_mask_b = 0, + .reg_md_apsrc_req_1_mask_b = 0, + .reg_md_vrf18_req_1_mask_b = 0, + .reg_md_ddr_en_1_mask_b = 0, + .reg_conn_srcclkena_mask_b = 1, + .reg_conn_srcclkenb_mask_b = 0, + .reg_conn_infra_req_mask_b = 1, + .reg_conn_apsrc_req_mask_b = 1, + .reg_conn_vrf18_req_mask_b = 1, + .reg_conn_ddr_en_mask_b = 1, + .reg_conn_vfe28_mask_b = 0, + .reg_srcclkeni0_srcclkena_mask_b = 1, + .reg_srcclkeni0_infra_req_mask_b = 1, + .reg_srcclkeni1_srcclkena_mask_b = 0, + .reg_srcclkeni1_infra_req_mask_b = 0, + .reg_srcclkeni2_srcclkena_mask_b = 0, + .reg_srcclkeni2_infra_req_mask_b = 0, + .reg_infrasys_apsrc_req_mask_b = 0, + .reg_infrasys_ddr_en_mask_b = 1, + .reg_md32_srcclkena_mask_b = 1, + .reg_md32_infra_req_mask_b = 1, + .reg_md32_apsrc_req_mask_b = 1, + .reg_md32_vrf18_req_mask_b = 1, + .reg_md32_ddr_en_mask_b = 1, + + /* SPM_SRC2_MASK */ + .reg_scp_srcclkena_mask_b = 1, + .reg_scp_infra_req_mask_b = 1, + .reg_scp_apsrc_req_mask_b = 1, + .reg_scp_vrf18_req_mask_b = 1, + .reg_scp_ddr_en_mask_b = 1, + .reg_audio_dsp_srcclkena_mask_b = 1, + .reg_audio_dsp_infra_req_mask_b = 1, + .reg_audio_dsp_apsrc_req_mask_b = 1, + .reg_audio_dsp_vrf18_req_mask_b = 1, + .reg_audio_dsp_ddr_en_mask_b = 1, + .reg_ufs_srcclkena_mask_b = 1, + .reg_ufs_infra_req_mask_b = 1, + .reg_ufs_apsrc_req_mask_b = 1, + .reg_ufs_vrf18_req_mask_b = 1, + .reg_ufs_ddr_en_mask_b = 1, + .reg_disp0_apsrc_req_mask_b = 1, + .reg_disp0_ddr_en_mask_b = 1, + .reg_disp1_apsrc_req_mask_b = 1, + .reg_disp1_ddr_en_mask_b = 1, + .reg_gce_infra_req_mask_b = 1, + .reg_gce_apsrc_req_mask_b = 1, + .reg_gce_vrf18_req_mask_b = 1, + .reg_gce_ddr_en_mask_b = 1, + .reg_apu_srcclkena_mask_b = 1, + .reg_apu_infra_req_mask_b = 1, + .reg_apu_apsrc_req_mask_b = 1, + .reg_apu_vrf18_req_mask_b = 1, + .reg_apu_ddr_en_mask_b = 1, + .reg_cg_check_srcclkena_mask_b = 0, + .reg_cg_check_apsrc_req_mask_b = 0, + .reg_cg_check_vrf18_req_mask_b = 0, + .reg_cg_check_ddr_en_mask_b = 0, + + /* SPM_SRC3_MASK */ + .reg_dvfsrc_event_trigger_mask_b = 1, + .reg_sw2spm_int0_mask_b = 0, + .reg_sw2spm_int1_mask_b = 0, + .reg_sw2spm_int2_mask_b = 0, + .reg_sw2spm_int3_mask_b = 0, + .reg_sc_adsp2spm_wakeup_mask_b = 0, + .reg_sc_sspm2spm_wakeup_mask_b = 0, + .reg_sc_scp2spm_wakeup_mask_b = 0, + .reg_csyspwrreq_mask = 1, + .reg_spm_srcclkena_reserved_mask_b = 0, + .reg_spm_infra_req_reserved_mask_b = 0, + .reg_spm_apsrc_req_reserved_mask_b = 0, + .reg_spm_vrf18_req_reserved_mask_b = 0, + .reg_spm_ddr_en_reserved_mask_b = 0, + .reg_mcupm_srcclkena_mask_b = 1, + .reg_mcupm_infra_req_mask_b = 1, + .reg_mcupm_apsrc_req_mask_b = 1, + .reg_mcupm_vrf18_req_mask_b = 1, + .reg_mcupm_ddr_en_mask_b = 1, + .reg_msdc0_srcclkena_mask_b = 1, + .reg_msdc0_infra_req_mask_b = 1, + .reg_msdc0_apsrc_req_mask_b = 1, + .reg_msdc0_vrf18_req_mask_b = 1, + .reg_msdc0_ddr_en_mask_b = 1, + .reg_msdc1_srcclkena_mask_b = 1, + .reg_msdc1_infra_req_mask_b = 1, + .reg_msdc1_apsrc_req_mask_b = 1, + .reg_msdc1_vrf18_req_mask_b = 1, + .reg_msdc1_ddr_en_mask_b = 1, + + /* SPM_SRC4_MASK */ + .ccif_event_mask_b = 0xFFF, + .reg_bak_psri_srcclkena_mask_b = 0, + .reg_bak_psri_infra_req_mask_b = 0, + .reg_bak_psri_apsrc_req_mask_b = 0, + .reg_bak_psri_vrf18_req_mask_b = 0, + .reg_bak_psri_ddr_en_mask_b = 0, + .reg_dramc0_md32_infra_req_mask_b = 1, + .reg_dramc0_md32_vrf18_req_mask_b = 0, + .reg_dramc1_md32_infra_req_mask_b = 1, + .reg_dramc1_md32_vrf18_req_mask_b = 0, + .reg_conn_srcclkenb2pwrap_mask_b = 0, + .reg_dramc0_md32_wakeup_mask = 1, + .reg_dramc1_md32_wakeup_mask = 1, + + /* SPM_SRC5_MASK */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x11, + .reg_mcusys_merge_ddr_en_mask_b = 0x11, + .reg_msdc2_srcclkena_mask_b = 1, + .reg_msdc2_infra_req_mask_b = 1, + .reg_msdc2_apsrc_req_mask_b = 1, + .reg_msdc2_vrf18_req_mask_b = 1, + .reg_msdc2_ddr_en_mask_b = 1, + .reg_pcie_srcclkena_mask_b = 1, + .reg_pcie_infra_req_mask_b = 1, + .reg_pcie_apsrc_req_mask_b = 1, + .reg_pcie_vrf18_req_mask_b = 1, + .reg_pcie_ddr_en_mask_b = 1, + + /* SPM_WAKEUP_EVENT_MASK */ + .reg_wakeup_event_mask = 0x01382202, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, + + /* Auto-gen End */ +}; + +struct spm_lp_scen __spm_suspend = { + .pwrctrl = &suspend_ctrl, +}; + +int mt_spm_suspend_mode_set(int mode) +{ + if (mode == MT_SPM_SUSPEND_SLEEP) { + suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG; + suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1; + } else { + suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG; + suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1; + } + + return 0; +} + +int mt_spm_suspend_enter(int state_id, unsigned int ext_opand, + unsigned int resource_req) +{ + /* If FMAudio / ADSP is active, change to sleep suspend mode */ + if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) { + mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP); + } + + /* Notify MCUPM that device is going suspend flow */ + mmio_write_32(MCUPM_MBOX_OFFSET_PDN, MCUPM_POWER_DOWN); + + /* Notify UART to sleep */ + mt_uart_save(); + + return spm_conservation(state_id, ext_opand, + &__spm_suspend, resource_req); +} + +void mt_spm_suspend_resume(int state_id, unsigned int ext_opand, + struct wake_status **status) +{ + spm_conservation_finish(state_id, ext_opand, &__spm_suspend, status); + + /* Notify UART to wakeup */ + mt_uart_restore(); + + /* Notify MCUPM that device leave suspend */ + mmio_write_32(MCUPM_MBOX_OFFSET_PDN, 0); + + /* If FMAudio / ADSP is active, change back to suspend mode */ + if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) { + mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN); + } +} + +void mt_spm_suspend_init(void) +{ + spm_conservation_pwrctrl_init(__spm_suspend.pwrctrl); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h new file mode 100644 index 0000000..08bbad2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SUSPEND_H +#define MT_SPM_SUSPEND_H + +#include + +#define MCUPM_MBOX_OFFSET_PDN 0x0C55FDA8 +#define MCUPM_POWER_DOWN 0x4D50444E + +enum MT_SPM_SUSPEND_MODE { + MT_SPM_SUSPEND_SYSTEM_PDN, + MT_SPM_SUSPEND_SLEEP, +}; + +extern int mt_spm_suspend_mode_set(int mode); +extern int mt_spm_suspend_enter(int state_id, unsigned int ext_opand, + unsigned int reosuce_req); +extern void mt_spm_suspend_resume(int state_id, unsigned int ext_opand, + struct wake_status **status); +extern void mt_spm_suspend_init(void); +#endif /* MT_SPM_SUSPEND_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c new file mode 100644 index 0000000..f74ea80 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c @@ -0,0 +1,405 @@ +/* + * Copyright(C)2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mt_spm.h" +#include "mt_spm_internal.h" +#include "mt_spm_reg.h" +#include "mt_spm_vcorefs.h" +#include "mt_spm_pmic_wrap.h" + +#define VCORE_CT_ENABLE (1U << 5) +#define SW_REQ5_INIT_VAL (6U << 12) +#define V_VMODE_SHIFT 0 +#define VCORE_HV 105 +#define VCORE_LV 95 +#define PMIC_STEP_UV 6250 + +static const struct reg_config dvfsrc_init_configs[] = { + /* Setup opp table */ + { DVFSRC_LEVEL_LABEL_0_1, 0x50436053 }, + { DVFSRC_LEVEL_LABEL_2_3, 0x40335042 }, + { DVFSRC_LEVEL_LABEL_4_5, 0x40314032 }, + { DVFSRC_LEVEL_LABEL_6_7, 0x30223023 }, + { DVFSRC_LEVEL_LABEL_8_9, 0x20133021 }, + { DVFSRC_LEVEL_LABEL_10_11, 0x20112012 }, + { DVFSRC_LEVEL_LABEL_12_13, 0x10032010 }, + { DVFSRC_LEVEL_LABEL_14_15, 0x10011002 }, + { DVFSRC_LEVEL_LABEL_16_17, 0x00131000 }, + { DVFSRC_LEVEL_LABEL_18_19, 0x00110012 }, + { DVFSRC_LEVEL_LABEL_20_21, 0x00000010 }, + + /* Setup hw emi qos policy */ + { DVFSRC_DDR_REQUEST, 0x00004321 }, + { DVFSRC_DDR_REQUEST3, 0x00000065 }, + + /* Setup up for PCIe */ + { DVFSRC_PCIE_VCORE_REQ, 0x0A298001 }, + + /* Setup up HRT QOS policy */ + { DVFSRC_HRT_BW_BASE, 0x00000004 }, + { DVFSRC_HRT_REQ_UNIT, 0x0000001E }, + { DVFSRC_HRT_HIGH_3, 0x18A618A6 }, + { DVFSRC_HRT_HIGH_2, 0x18A61183 }, + { DVFSRC_HRT_HIGH_1, 0x0D690B80 }, + { DVFSRC_HRT_HIGH, 0x070804B0 }, + { DVFSRC_HRT_LOW_3, 0x18A518A5 }, + { DVFSRC_HRT_LOW_2, 0x18A51182 }, + { DVFSRC_HRT_LOW_1, 0x0D680B7F }, + { DVFSRC_HRT_LOW, 0x070704AF }, + { DVFSRC_HRT_REQUEST, 0x66654321 }, + /* Setup up SRT QOS policy */ + { DVFSRC_QOS_EN, 0x0011007C }, + { DVFSRC_DDR_QOS0, 0x00000019 }, + { DVFSRC_DDR_QOS1, 0x00000026 }, + { DVFSRC_DDR_QOS2, 0x00000033 }, + { DVFSRC_DDR_QOS3, 0x0000003B }, + { DVFSRC_DDR_QOS4, 0x0000004C }, + { DVFSRC_DDR_QOS5, 0x00000066 }, + { DVFSRC_DDR_QOS6, 0x00000066 }, + { DVFSRC_DDR_REQUEST5, 0x54321000 }, + { DVFSRC_DDR_REQUEST7, 0x66000000 }, + /* Setup up hifi request policy */ + { DVFSRC_DDR_REQUEST6, 0x66543210 }, + /* Setup up hw request vcore policy */ + { DVFSRC_VCORE_USER_REQ, 0x00010A29 }, + + /* Setup misc*/ + { DVFSRC_TIMEOUT_NEXTREQ, 0x00000015 }, + { DVFSRC_RSRV_5, 0x00000001 }, + { DVFSRC_INT_EN, 0x00000002 }, + /* Init opp and enable dvfsrc*/ + { DVFSRC_CURRENT_FORCE, 0x00000001 }, + { DVFSRC_BASIC_CONTROL, 0x0298444B }, + { DVFSRC_BASIC_CONTROL, 0x0298054B }, + { DVFSRC_CURRENT_FORCE, 0x00000000 }, +}; + +static struct pwr_ctrl vcorefs_ctrl = { + .wake_src = R12_REG_CPU_WAKEUP, + + /* default VCORE DVFS is disabled */ + .pcm_flags = (SPM_FLAG_RUN_COMMON_SCENARIO | + SPM_FLAG_DISABLE_VCORE_DVS | + SPM_FLAG_DISABLE_VCORE_DFS), + + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + .reg_wfi_op = 0, + .reg_wfi_type = 0, + .reg_mp0_cputop_idle_mask = 0, + .reg_mp1_cputop_idle_mask = 0, + .reg_mcusys_idle_mask = 0, + .reg_md_apsrc_1_sel = 0, + .reg_md_apsrc_0_sel = 0, + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC_REQ */ + .reg_spm_apsrc_req = 0, + .reg_spm_f26m_req = 0, + .reg_spm_infra_req = 0, + .reg_spm_vrf18_req = 0, + .reg_spm_ddr_en_req = 1, + .reg_spm_dvfs_req = 0, + .reg_spm_sw_mailbox_req = 0, + .reg_spm_sspm_mailbox_req = 0, + .reg_spm_adsp_mailbox_req = 0, + .reg_spm_scp_mailbox_req = 0, + + /* SPM_SRC6_MASK */ + .reg_dpmaif_srcclkena_mask_b = 1, + .reg_dpmaif_infra_req_mask_b = 1, + .reg_dpmaif_apsrc_req_mask_b = 1, + .reg_dpmaif_vrf18_req_mask_b = 1, + .reg_dpmaif_ddr_en_mask_b = 1, + + /* SPM_SRC_MASK */ + .reg_md_srcclkena_0_mask_b = 1, + .reg_md_srcclkena2infra_req_0_mask_b = 0, + .reg_md_apsrc2infra_req_0_mask_b = 1, + .reg_md_apsrc_req_0_mask_b = 1, + .reg_md_vrf18_req_0_mask_b = 1, + .reg_md_ddr_en_0_mask_b = 1, + .reg_md_srcclkena_1_mask_b = 0, + .reg_md_srcclkena2infra_req_1_mask_b = 0, + .reg_md_apsrc2infra_req_1_mask_b = 0, + .reg_md_apsrc_req_1_mask_b = 0, + .reg_md_vrf18_req_1_mask_b = 0, + .reg_md_ddr_en_1_mask_b = 0, + .reg_conn_srcclkena_mask_b = 1, + .reg_conn_srcclkenb_mask_b = 0, + .reg_conn_infra_req_mask_b = 1, + .reg_conn_apsrc_req_mask_b = 1, + .reg_conn_vrf18_req_mask_b = 1, + .reg_conn_ddr_en_mask_b = 1, + .reg_conn_vfe28_mask_b = 0, + .reg_srcclkeni0_srcclkena_mask_b = 1, + .reg_srcclkeni0_infra_req_mask_b = 1, + .reg_srcclkeni1_srcclkena_mask_b = 0, + .reg_srcclkeni1_infra_req_mask_b = 0, + .reg_srcclkeni2_srcclkena_mask_b = 0, + .reg_srcclkeni2_infra_req_mask_b = 0, + .reg_infrasys_apsrc_req_mask_b = 0, + .reg_infrasys_ddr_en_mask_b = 1, + .reg_md32_srcclkena_mask_b = 1, + .reg_md32_infra_req_mask_b = 1, + .reg_md32_apsrc_req_mask_b = 1, + .reg_md32_vrf18_req_mask_b = 1, + .reg_md32_ddr_en_mask_b = 1, + + /* SPM_SRC2_MASK */ + .reg_scp_srcclkena_mask_b = 1, + .reg_scp_infra_req_mask_b = 1, + .reg_scp_apsrc_req_mask_b = 1, + .reg_scp_vrf18_req_mask_b = 1, + .reg_scp_ddr_en_mask_b = 1, + .reg_audio_dsp_srcclkena_mask_b = 1, + .reg_audio_dsp_infra_req_mask_b = 1, + .reg_audio_dsp_apsrc_req_mask_b = 1, + .reg_audio_dsp_vrf18_req_mask_b = 1, + .reg_audio_dsp_ddr_en_mask_b = 1, + .reg_ufs_srcclkena_mask_b = 1, + .reg_ufs_infra_req_mask_b = 1, + .reg_ufs_apsrc_req_mask_b = 1, + .reg_ufs_vrf18_req_mask_b = 1, + .reg_ufs_ddr_en_mask_b = 1, + .reg_disp0_apsrc_req_mask_b = 1, + .reg_disp0_ddr_en_mask_b = 1, + .reg_disp1_apsrc_req_mask_b = 1, + .reg_disp1_ddr_en_mask_b = 1, + .reg_gce_infra_req_mask_b = 1, + .reg_gce_apsrc_req_mask_b = 1, + .reg_gce_vrf18_req_mask_b = 1, + .reg_gce_ddr_en_mask_b = 1, + .reg_apu_srcclkena_mask_b = 1, + .reg_apu_infra_req_mask_b = 1, + .reg_apu_apsrc_req_mask_b = 1, + .reg_apu_vrf18_req_mask_b = 1, + .reg_apu_ddr_en_mask_b = 1, + .reg_cg_check_srcclkena_mask_b = 0, + .reg_cg_check_apsrc_req_mask_b = 0, + .reg_cg_check_vrf18_req_mask_b = 0, + .reg_cg_check_ddr_en_mask_b = 0, + + /* SPM_SRC3_MASK */ + .reg_dvfsrc_event_trigger_mask_b = 1, + .reg_sw2spm_int0_mask_b = 0, + .reg_sw2spm_int1_mask_b = 0, + .reg_sw2spm_int2_mask_b = 0, + .reg_sw2spm_int3_mask_b = 0, + .reg_sc_adsp2spm_wakeup_mask_b = 0, + .reg_sc_sspm2spm_wakeup_mask_b = 0, + .reg_sc_scp2spm_wakeup_mask_b = 0, + .reg_csyspwrreq_mask = 1, + .reg_spm_srcclkena_reserved_mask_b = 0, + .reg_spm_infra_req_reserved_mask_b = 0, + .reg_spm_apsrc_req_reserved_mask_b = 0, + .reg_spm_vrf18_req_reserved_mask_b = 0, + .reg_spm_ddr_en_reserved_mask_b = 0, + .reg_mcupm_srcclkena_mask_b = 1, + .reg_mcupm_infra_req_mask_b = 1, + .reg_mcupm_apsrc_req_mask_b = 1, + .reg_mcupm_vrf18_req_mask_b = 1, + .reg_mcupm_ddr_en_mask_b = 1, + .reg_msdc0_srcclkena_mask_b = 1, + .reg_msdc0_infra_req_mask_b = 1, + .reg_msdc0_apsrc_req_mask_b = 1, + .reg_msdc0_vrf18_req_mask_b = 1, + .reg_msdc0_ddr_en_mask_b = 1, + .reg_msdc1_srcclkena_mask_b = 1, + .reg_msdc1_infra_req_mask_b = 1, + .reg_msdc1_apsrc_req_mask_b = 1, + .reg_msdc1_vrf18_req_mask_b = 1, + .reg_msdc1_ddr_en_mask_b = 1, + + /* SPM_SRC4_MASK */ + .ccif_event_mask_b = 0xFFF, + .reg_bak_psri_srcclkena_mask_b = 0, + .reg_bak_psri_infra_req_mask_b = 0, + .reg_bak_psri_apsrc_req_mask_b = 0, + .reg_bak_psri_vrf18_req_mask_b = 0, + .reg_bak_psri_ddr_en_mask_b = 0, + .reg_dramc0_md32_infra_req_mask_b = 1, + .reg_dramc0_md32_vrf18_req_mask_b = 0, + .reg_dramc1_md32_infra_req_mask_b = 1, + .reg_dramc1_md32_vrf18_req_mask_b = 0, + .reg_conn_srcclkenb2pwrap_mask_b = 0, + .reg_dramc0_md32_wakeup_mask = 1, + .reg_dramc1_md32_wakeup_mask = 1, + + /* SPM_SRC5_MASK */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x11, + .reg_mcusys_merge_ddr_en_mask_b = 0x11, + .reg_msdc2_srcclkena_mask_b = 1, + .reg_msdc2_infra_req_mask_b = 1, + .reg_msdc2_apsrc_req_mask_b = 1, + .reg_msdc2_vrf18_req_mask_b = 1, + .reg_msdc2_ddr_en_mask_b = 1, + .reg_pcie_srcclkena_mask_b = 1, + .reg_pcie_infra_req_mask_b = 1, + .reg_pcie_apsrc_req_mask_b = 1, + .reg_pcie_vrf18_req_mask_b = 1, + .reg_pcie_ddr_en_mask_b = 1, + + /* SPM_WAKEUP_EVENT_MASK */ + .reg_wakeup_event_mask = 0xEFFFFFFF, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, + + /* Auto-gen End */ +}; + +struct spm_lp_scen __spm_vcorefs = { + .pwrctrl = &vcorefs_ctrl, +}; + +static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val) +{ + if (cmd < NR_IDX_ALL) { + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val); + } else { + INFO("cmd out of range!\n"); + } +} + +void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue) +{ + mmio_clrsetbits_32(SPM_DVFS_MISC, SPM_DVFS_FORCE_ENABLE_LSB, + SPM_DVFSRC_ENABLE_LSB); + + mmio_write_32(SPM_DVFS_LEVEL, 0x00000001); + mmio_write_32(SPM_DVS_DFS_LEVEL, 0x00010001); +} + +void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl, + const struct pwr_ctrl *src_pwr_ctrl) +{ + uint32_t dvfs_mask = SPM_FLAG_DISABLE_VCORE_DVS | + SPM_FLAG_DISABLE_VCORE_DFS | + SPM_FLAG_ENABLE_VOLTAGE_BIN; + + dest_pwr_ctrl->pcm_flags = (dest_pwr_ctrl->pcm_flags & (~dvfs_mask)) | + (src_pwr_ctrl->pcm_flags & dvfs_mask); + + if (dest_pwr_ctrl->pcm_flags_cust > 0U) { + dest_pwr_ctrl->pcm_flags_cust = + (dest_pwr_ctrl->pcm_flags_cust & (~dvfs_mask)) | + (src_pwr_ctrl->pcm_flags & dvfs_mask); + } +} + +static void spm_go_to_vcorefs(void) +{ + __spm_set_power_control(__spm_vcorefs.pwrctrl); + __spm_set_wakeup_event(__spm_vcorefs.pwrctrl); + __spm_set_pcm_flags(__spm_vcorefs.pwrctrl); + __spm_send_cpu_wakeup_event(); +} + +static void dvfsrc_init(void) +{ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(dvfsrc_init_configs); i++) { + mmio_write_32(dvfsrc_init_configs[i].offset, + dvfsrc_init_configs[i].val); + } +} + +static uint32_t spm_vcorefs_get_efuse_data(void) +{ + return mmio_read_32(VCORE_VB_EFUSE); +} + +static uint32_t is_rising_need(void) +{ + return ((spm_vcorefs_get_efuse_data() & 0xF) == 11U) ? 1U : 0U; +} + +static void spm_vcorefs_vcore_setting(uint64_t flag) +{ + uint32_t dvfs_v_mode, dvfsrc_rsrv, i; + uint32_t opp_uv[] = {725000U, 650000U, 600000U, 575000U}; + + dvfsrc_rsrv = mmio_read_32(DVFSRC_RSRV_4); + + dvfs_v_mode = (dvfsrc_rsrv >> V_VMODE_SHIFT) & 0x3; + + if (is_rising_need() != 0U) { + opp_uv[2] = 625000U; + opp_uv[3] = 600000U; + } + + for (i = 0; i < ARRAY_SIZE(opp_uv); i++) { + if (dvfs_v_mode == 3U) { + /* LV */ + opp_uv[i] = round_down((opp_uv[i] * VCORE_LV) / 100U, + PMIC_STEP_UV); + } else if (dvfs_v_mode == 1U) { + /* HV */ + opp_uv[i] = round_up((opp_uv[i] * VCORE_HV) / 100U, + PMIC_STEP_UV); + } + spm_vcorefs_pwarp_cmd(i, __vcore_uv_to_pmic(opp_uv[i])); + } +} + +uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t *x4) +{ + uint64_t cmd = x1; + uint64_t spm_flags; + + switch (cmd) { + case VCOREFS_SMC_CMD_INIT: + /* vcore_dvfs init + kick */ + mmio_write_32(DVFSRC_SW_REQ5, SW_REQ5_INIT_VAL); + spm_dvfsfw_init(0ULL, 0ULL); + spm_vcorefs_vcore_setting(x3 & 0xF); + spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO; + if ((x2 & 0x1) > 0U) { + spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS; + } + + if ((x2 & 0x2) > 0U) { + spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS; + } + + if ((mmio_read_32(DVFSRC_RSRV_4) & VCORE_CT_ENABLE) > 0U) { + spm_flags |= SPM_FLAG_ENABLE_VOLTAGE_BIN; + } + + set_pwrctrl_pcm_flags(__spm_vcorefs.pwrctrl, spm_flags); + spm_go_to_vcorefs(); + dvfsrc_init(); + + *x4 = 0U; + mmio_write_32(DVFSRC_SW_REQ5, 0U); + break; + case VCOREFS_SMC_CMD_KICK: + mmio_write_32(DVFSRC_SW_REQ5, 0U); + break; + default: + break; + } + + return 0ULL; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h new file mode 100644 index 0000000..f4e0c48 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h @@ -0,0 +1,135 @@ +/* + * Copyright(C)2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_VCOREFS_H +#define MT_SPM_VCOREFS_H + +uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t *x4); + +enum vcorefs_smc_cmd { + VCOREFS_SMC_CMD_0, + VCOREFS_SMC_CMD_1, + VCOREFS_SMC_CMD_2, + VCOREFS_SMC_CMD_3, + VCOREFS_SMC_CMD_4, + /* check spmfw status */ + VCOREFS_SMC_CMD_5, + + /* get spmfw type */ + VCOREFS_SMC_CMD_6, + + /* get spm reg status */ + VCOREFS_SMC_CMD_7, + + NUM_VCOREFS_SMC_CMD, +}; + +enum vcorefs_smc_cmd_new { + VCOREFS_SMC_CMD_INIT = 0, + VCOREFS_SMC_CMD_KICK = 1, +}; + +#define _VCORE_BASE_UV 400000 +#define _VCORE_STEP_UV 6250 + +/* PMIC */ +#define __vcore_pmic_to_uv(pmic) \ + (((pmic) * _VCORE_STEP_UV) + _VCORE_BASE_UV) + +#define __vcore_uv_to_pmic(uv) /* pmic >= uv */ \ + ((((uv) - _VCORE_BASE_UV) + (_VCORE_STEP_UV - 1)) / _VCORE_STEP_UV) + +struct reg_config { + uint32_t offset; + uint32_t val; +}; + +#define DVFSRC_BASIC_CONTROL (DVFSRC_BASE + 0x0) +#define DVFSRC_SW_REQ5 (DVFSRC_BASE + 0x14) +#define DVFSRC_INT_EN (DVFSRC_BASE + 0xC8) +#define DVFSRC_MD_TURBO (DVFSRC_BASE + 0xDC) +#define DVFSRC_PCIE_VCORE_REQ (DVFSRC_BASE + 0xE0) +#define DVFSRC_VCORE_USER_REQ (DVFSRC_BASE + 0xE4) +#define DVFSRC_TIMEOUT_NEXTREQ (DVFSRC_BASE + 0xF8) +#define DVFSRC_LEVEL_LABEL_0_1 (DVFSRC_BASE + 0x100) +#define DVFSRC_LEVEL_LABEL_2_3 (DVFSRC_BASE + 0x104) +#define DVFSRC_LEVEL_LABEL_4_5 (DVFSRC_BASE + 0x108) +#define DVFSRC_LEVEL_LABEL_6_7 (DVFSRC_BASE + 0x10C) +#define DVFSRC_LEVEL_LABEL_8_9 (DVFSRC_BASE + 0x110) +#define DVFSRC_LEVEL_LABEL_10_11 (DVFSRC_BASE + 0x114) +#define DVFSRC_LEVEL_LABEL_12_13 (DVFSRC_BASE + 0x118) +#define DVFSRC_LEVEL_LABEL_14_15 (DVFSRC_BASE + 0x11C) +#define DVFSRC_QOS_EN (DVFSRC_BASE + 0x280) +#define DVFSRC_HRT_BW_BASE (DVFSRC_BASE + 0x294) +#define DVFSRC_RSRV_4 (DVFSRC_BASE + 0x610) +#define DVFSRC_RSRV_5 (DVFSRC_BASE + 0x614) +#define DVFSRC_DDR_REQUEST (DVFSRC_BASE + 0xA00) +#define DVFSRC_DDR_REQUEST2 (DVFSRC_BASE + 0xA04) +#define DVFSRC_DDR_REQUEST3 (DVFSRC_BASE + 0xA08) +#define DVFSRC_DDR_REQUEST4 (DVFSRC_BASE + 0xA0C) +#define DVFSRC_DDR_REQUEST5 (DVFSRC_BASE + 0xA10) +#define DVFSRC_DDR_REQUEST6 (DVFSRC_BASE + 0xA14) +#define DVFSRC_DDR_REQUEST7 (DVFSRC_BASE + 0xA18) +#define DVFSRC_DDR_QOS0 (DVFSRC_BASE + 0xA34) +#define DVFSRC_DDR_QOS1 (DVFSRC_BASE + 0xA38) +#define DVFSRC_DDR_QOS2 (DVFSRC_BASE + 0xA3C) +#define DVFSRC_DDR_QOS3 (DVFSRC_BASE + 0xA40) +#define DVFSRC_DDR_QOS4 (DVFSRC_BASE + 0xA44) +#define DVFSRC_HRT_REQ_UNIT (DVFSRC_BASE + 0xA60) +#define DVFSRC_HRT_REQUEST (DVFSRC_BASE + 0xAC4) +#define DVFSRC_HRT_HIGH_2 (DVFSRC_BASE + 0xAC8) +#define DVFSRC_HRT_HIGH_1 (DVFSRC_BASE + 0xACC) +#define DVFSRC_HRT_HIGH (DVFSRC_BASE + 0xAD0) +#define DVFSRC_HRT_LOW_2 (DVFSRC_BASE + 0xAD4) +#define DVFSRC_HRT_LOW_1 (DVFSRC_BASE + 0xAD8) +#define DVFSRC_HRT_LOW (DVFSRC_BASE + 0xADC) +#define DVFSRC_DDR_ADD_REQUEST (DVFSRC_BASE + 0xAE0) +#define DVFSRC_LAST (DVFSRC_BASE + 0xAE4) +#define DVFSRC_LAST_L (DVFSRC_BASE + 0xAE8) +#define DVFSRC_MD_SCENARIO (DVFSRC_BASE + 0xAEC) +#define DVFSRC_RECORD_0_0 (DVFSRC_BASE + 0xAF0) +#define DVFSRC_RECORD_0_1 (DVFSRC_BASE + 0xAF4) +#define DVFSRC_RECORD_0_2 (DVFSRC_BASE + 0xAF8) +#define DVFSRC_RECORD_0_3 (DVFSRC_BASE + 0xAFC) +#define DVFSRC_RECORD_0_4 (DVFSRC_BASE + 0xB00) +#define DVFSRC_RECORD_0_5 (DVFSRC_BASE + 0xB04) +#define DVFSRC_RECORD_0_6 (DVFSRC_BASE + 0xB08) +#define DVFSRC_RECORD_0_7 (DVFSRC_BASE + 0xB0C) +#define DVFSRC_RECORD_0_L_0 (DVFSRC_BASE + 0xBF0) +#define DVFSRC_RECORD_0_L_1 (DVFSRC_BASE + 0xBF4) +#define DVFSRC_RECORD_0_L_2 (DVFSRC_BASE + 0xBF8) +#define DVFSRC_RECORD_0_L_3 (DVFSRC_BASE + 0xBFC) +#define DVFSRC_RECORD_0_L_4 (DVFSRC_BASE + 0xC00) +#define DVFSRC_RECORD_0_L_5 (DVFSRC_BASE + 0xC04) +#define DVFSRC_RECORD_0_L_6 (DVFSRC_BASE + 0xC08) +#define DVFSRC_RECORD_0_L_7 (DVFSRC_BASE + 0xC0C) +#define DVFSRC_EMI_REQUEST8 (DVFSRC_BASE + 0xCF0) +#define DVFSRC_DDR_REQUEST8 (DVFSRC_BASE + 0xCF4) +#define DVFSRC_EMI_HRT_2 (DVFSRC_BASE + 0xCF8) +#define DVFSRC_EMI_HRT2_2 (DVFSRC_BASE + 0xCFC) +#define DVFSRC_EMI_HRT3_2 (DVFSRC_BASE + 0xD00) +#define DVFSRC_EMI_QOS5 (DVFSRC_BASE + 0xD04) +#define DVFSRC_EMI_QOS6 (DVFSRC_BASE + 0xD08) +#define DVFSRC_DDR_HRT_2 (DVFSRC_BASE + 0xD0C) +#define DVFSRC_DDR_HRT2_2 (DVFSRC_BASE + 0xD10) +#define DVFSRC_DDR_HRT3_2 (DVFSRC_BASE + 0xD14) +#define DVFSRC_DDR_QOS5 (DVFSRC_BASE + 0xD18) +#define DVFSRC_DDR_QOS6 (DVFSRC_BASE + 0xD1C) +#define DVFSRC_HRT_HIGH_3 (DVFSRC_BASE + 0xD38) +#define DVFSRC_HRT_LOW_3 (DVFSRC_BASE + 0xD3C) +#define DVFSRC_LEVEL_LABEL_16_17 (DVFSRC_BASE + 0xD4C) +#define DVFSRC_LEVEL_LABEL_18_19 (DVFSRC_BASE + 0xD50) +#define DVFSRC_LEVEL_LABEL_20_21 (DVFSRC_BASE + 0xD54) +#define DVFSRC_LEVEL_LABEL_22_23 (DVFSRC_BASE + 0xD58) +#define DVFSRC_LEVEL_LABEL_24_25 (DVFSRC_BASE + 0xD5C) +#define DVFSRC_LEVEL_LABEL_26_27 (DVFSRC_BASE + 0xD60) +#define DVFSRC_LEVEL_LABEL_28_29 (DVFSRC_BASE + 0xD64) +#define DVFSRC_LEVEL_LABEL_30_31 (DVFSRC_BASE + 0xD68) +#define DVFSRC_CURRENT_FORCE (DVFSRC_BASE + 0xD6C) + +#define VCORE_VB_EFUSE (0x11C105E8) + +#endif /* MT_SPM_VCOREFS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h new file mode 100644 index 0000000..66be7ee --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SSPM_NOTIFIER_H +#define MT_SPM_SSPM_NOTIFIER_H + +enum MT_SPM_SSPM_NOTIFY_ID { + MT_SPM_NOTIFY_LP_ENTER, + MT_SPM_NOTIFY_LP_LEAVE, +}; + +int mt_spm_sspm_notify(int type, unsigned int lp_mode); + +static inline int mt_spm_sspm_notify_u32(int type, unsigned int lp_mode) +{ + return mt_spm_sspm_notify(type, lp_mode); +} +#endif /* MT_SPM_SSPM_NOTIFIER_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h new file mode 100644 index 0000000..452ae90 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SSPM_INTC_H +#define MT_SPM_SSPM_INTC_H + +#include + +#define MT_SPM_SSPM_INTC_SEL_0 0x10 +#define MT_SPM_SSPM_INTC_SEL_1 0x20 +#define MT_SPM_SSPM_INTC_SEL_2 0x40 +#define MT_SPM_SSPM_INTC_SEL_3 0x80 + +#define MT_SPM_SSPM_INTC_TRIGGER(id, sg) \ + (((0x10 << id) | (sg << id)) & 0xff) + +#define MT_SPM_SSPM_INTC0_HIGH MT_SPM_SSPM_INTC_TRIGGER(0, 1) +#define MT_SPM_SSPM_INTC0_LOW MT_SPM_SSPM_INTC_TRIGGER(0, 0) +#define MT_SPM_SSPM_INTC1_HIGH MT_SPM_SSPM_INTC_TRIGGER(1, 1) +#define MT_SPM_SSPM_INTC1_LOW MT_SPM_SSPM_INTC_TRIGGER(1, 0) +#define MT_SPM_SSPM_INTC2_HIGH MT_SPM_SSPM_INTC_TRIGGER(2, 1) +#define MT_SPM_SSPM_INTC2_LOW MT_SPM_SSPM_INTC_TRIGGER(2, 0) +#define MT_SPM_SSPM_INTC3_HIGH MT_SPM_SSPM_INTC_TRIGGER(3, 1) +#define MT_SPM_SSPM_INTC3_LOW MT_SPM_SSPM_INTC_TRIGGER(3, 0) + +#define DO_SPM_SSPM_LP_SUSPEND() \ + mmio_write_32(SPM_MD32_IRQ, MT_SPM_SSPM_INTC0_HIGH) +#define DO_SPM_SSPM_LP_RESUME() \ + mmio_write_32(SPM_MD32_IRQ, MT_SPM_SSPM_INTC0_LOW) +#endif /* MT_SPM_SSPM_INTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c new file mode 100644 index 0000000..e0ba037 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#define MT_SPM_SSPM_MBOX_OFF(x) (SSPM_MBOX_BASE + x) +#define MT_SPM_MBOX(slot) MT_SPM_SSPM_MBOX_OFF((slot << 2UL)) + +#define SSPM_MBOX_SPM_LP_LOOKUP1 MT_SPM_MBOX(0) +#define SSPM_MBOX_SPM_LP_LOOKUP2 MT_SPM_MBOX(1) +#define SSPM_MBOX_SPM_LP1 MT_SPM_MBOX(2) +#define SSPM_MBOX_SPM_LP2 MT_SPM_MBOX(3) + +#define MCUPM_MBOX_OFFSET_LP 0x0C55FDA4 +#define MCUPM_MBOX_ENTER_LP 0x454e0000 +#define MCUPM_MBOX_LEAVE_LP 0x4c450000 +#define MCUPM_MBOX_SLEEP_MASK 0x0000FFFF + +int mt_spm_sspm_notify(int type, unsigned int lp_mode) +{ + switch (type) { + case MT_SPM_NOTIFY_LP_ENTER: + mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode); + mmio_write_32(MCUPM_MBOX_OFFSET_LP, MCUPM_MBOX_ENTER_LP | + (lp_mode & MCUPM_MBOX_SLEEP_MASK)); + DO_SPM_SSPM_LP_SUSPEND(); + break; + case MT_SPM_NOTIFY_LP_LEAVE: + mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode); + mmio_write_32(MCUPM_MBOX_OFFSET_LP, MCUPM_MBOX_LEAVE_LP | + (lp_mode & MCUPM_MBOX_SLEEP_MASK)); + DO_SPM_SSPM_LP_RESUME(); + break; + default: + break; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h new file mode 100644 index 0000000..ab46b86 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PCM_DEF_H +#define PCM_DEF_H + +/* + * Auto generated by DE, please DO NOT modify this file directly. + */ + +/* --- R0 Define --- */ +#define R0_SC_26M_CK_OFF (1U << 0) +#define R0_SC_TX_TRACK_RETRY_EN (1U << 1) +#define R0_SC_MEM_CK_OFF (1U << 2) +#define R0_SC_AXI_CK_OFF (1U << 3) +#define R0_SC_DR_SRAM_LOAD (1U << 4) +#define R0_SC_MD26M_CK_OFF (1U << 5) +#define R0_SC_DPY_MODE_SW (1U << 6) +#define R0_SC_DMSUS_OFF (1U << 7) +#define R0_SC_DPY_2ND_DLL_EN (1U << 8) +#define R0_SC_DR_SRAM_RESTORE (1U << 9) +#define R0_SC_MPLLOUT_OFF (1U << 10) +#define R0_SC_TX_TRACKING_DIS (1U << 11) +#define R0_SC_DPY_DLL_EN (1U << 12) +#define R0_SC_DPY_DLL_CK_EN (1U << 13) +#define R0_SC_DPY_VREF_EN (1U << 14) +#define R0_SC_PHYPLL_EN (1U << 15) +#define R0_SC_DDRPHY_FB_CK_EN (1U << 16) +#define R0_SC_DPY_BCLK_ENABLE (1U << 17) +#define R0_SC_MPLL_OFF (1U << 18) +#define R0_SC_SHU_RESTORE (1U << 19) +#define R0_SC_CKSQ0_OFF (1U << 20) +#define R0_SC_DR_SHU_LEVEL_SRAM_LATCH (1U << 21) +#define R0_SC_DR_SHU_EN (1U << 22) +#define R0_SC_DPHY_PRECAL_UP (1U << 23) +#define R0_SC_MPLL_S_OFF (1U << 24) +#define R0_SC_DPHY_RXDLY_TRACKING_EN (1U << 25) +#define R0_SC_PHYPLL_SHU_EN (1U << 26) +#define R0_SC_PHYPLL2_SHU_EN (1U << 27) +#define R0_SC_PHYPLL_MODE_SW (1U << 28) +#define R0_SC_PHYPLL2_MODE_SW (1U << 29) +#define R0_SC_DR_SHU_LEVEL0 (1U << 30) +#define R0_SC_DR_SHU_LEVEL1 (1U << 31) +/* --- R7 Define --- */ +#define R7_PWRAP_SLEEP_REQ (1U << 0) +#define R7_EMI_CLK_OFF_REQ (1U << 1) +#define R7_PCM_BUS_PROTECT_REQ (1U << 2) +#define R7_SPM_CK_UPDATE (1U << 3) +#define R7_SPM_CK_SEL0 (1U << 4) +#define R7_SPM_CK_SEL1 (1U << 5) +#define R7_SPM_LEAVE_DEEPIDLE_REQ (1U << 6) +#define R7_SC_FHC_PAUSE_MPLL (1U << 7) +#define R7_SC_26M_CK_SEL (1U << 8) +#define R7_PCM_TIMER_SET (1U << 9) +#define R7_PCM_TIMER_CLR (1U << 10) +#define R7_SPM_LEAVE_SUSPEND_REQ (1U << 11) +#define R7_CSYSPWRUPACK (1U << 12) +#define R7_PCM_IM_SLP_EN (1U << 13) +#define R7_SRCCLKENO0 (1U << 14) +#define R7_FORCE_DDR_EN_WAKE (1U << 15) +#define R7_SPM_APSRC_INTERNAL_ACK (1U << 16) +#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17) +#define R7_SC_AXI_DCM_DIS (1U << 18) +#define R7_SC_FHC_PAUSE_MEM (1U << 19) +#define R7_SC_FHC_PAUSE_MAIN (1U << 20) +#define R7_SRCCLKENO1 (1U << 21) +#define R7_PCM_WDT_KICK_P (1U << 22) +#define R7_SPM2EMI_S1_MODE_ASYNC (1U << 23) +#define R7_SC_DDR_PST_REQ_PCM (1U << 24) +#define R7_SC_DDR_PST_ABORT_REQ_PCM (1U << 25) +#define R7_PMIC_IRQ_REQ_EN (1U << 26) +#define R7_FORCE_F26M_WAKE (1U << 27) +#define R7_FORCE_APSRC_WAKE (1U << 28) +#define R7_FORCE_INFRA_WAKE (1U << 29) +#define R7_FORCE_VRF18_WAKE (1U << 30) +#define R7_SPM_DDR_EN_INTERNAL_ACK (1U << 31) +/* --- R12 Define --- */ +#define R12_PCM_TIMER (1U << 0) +#define R12_TWAM_IRQ_B (1U << 1) +#define R12_KP_IRQ_B (1U << 2) +#define R12_APWDT_EVENT_B (1U << 3) +#define R12_APXGPT1_EVENT_B (1U << 4) +#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5) +#define R12_EINT_EVENT_B (1U << 6) +#define R12_CONN_WDT_IRQ_B (1U << 7) +#define R12_CCIF0_EVENT_B (1U << 8) +#define R12_LOWBATTERY_IRQ_B (1U << 9) +#define R12_SSPM2SPM_WAKEUP_B (1U << 10) +#define R12_SCP2SPM_WAKEUP_B (1U << 11) +#define R12_ADSP2SPM_WAKEUP_B (1U << 12) +#define R12_PCM_WDT_WAKEUP_B (1U << 13) +#define R12_USBX_CDSC_B (1U << 14) +#define R12_USBX_POWERDWN_B (1U << 15) +#define R12_SYS_TIMER_EVENT_B (1U << 16) +#define R12_EINT_EVENT_SECURE_B (1U << 17) +#define R12_CCIF1_EVENT_B (1U << 18) +#define R12_UART0_IRQ_B (1U << 19) +#define R12_AFE_IRQ_MCU_B (1U << 20) +#define R12_THERM_CTRL_EVENT_B (1U << 21) +#define R12_SYS_CIRQ_IRQ_B (1U << 22) +#define R12_MD2AP_PEER_EVENT_B (1U << 23) +#define R12_CSYSPWREQ_B (1U << 24) +#define R12_MD1_WDT_B (1U << 25) +#define R12_CLDMA_EVENT_B (1U << 26) +#define R12_SEJ_EVENT_B (1U << 27) +#define R12_REG_CPU_WAKEUP (1U << 28) +#define R12_APUSYS_WAKE_HOST_B (1U << 29) +#define R12_PCIE_BRIDGE_IRQ (1U << 30) +#define R12_PCIE_IRQ (1U << 31) +/* --- R12ext Define --- */ +#define R12EXT_26M_WAKE (1U << 0) +#define R12EXT_26M_SLEEP (1U << 1) +#define R12EXT_INFRA_WAKE (1U << 2) +#define R12EXT_INFRA_SLEEP (1U << 3) +#define R12EXT_APSRC_WAKE (1U << 4) +#define R12EXT_APSRC_SLEEP (1U << 5) +#define R12EXT_VRF18_WAKE (1U << 6) +#define R12EXT_VRF18_SLEEP (1U << 7) +#define R12EXT_DVFS_WAKE (1U << 8) +#define R12EXT_DDREN_WAKE (1U << 9) +#define R12EXT_DDREN_SLEEP (1U << 10) +#define R12EXT_MCU_PM_WFI (1U << 11) +#define R12EXT_SSPM_IDLE (1U << 12) +#define R12EXT_CONN_SRCCLKENB (1U << 13) +#define R12EXT_DRAMC_SSPM_WFI_MERGE (1U << 14) +#define R12EXT_SW_MAILBOX_WAKE (1U << 15) +#define R12EXT_SSPM_MAILBOX_WAKE (1U << 16) +#define R12EXT_ADSP_MAILBOX_WAKE (1U << 17) +#define R12EXT_SCP_MAILBOX_WAKE (1U << 18) +#define R12EXT_SPM_LEAVE_SUSPEND_ACK (1U << 19) +#define R12EXT_SPM_LEAVE_DEEPIDLE_ACK (1U << 20) +#define R12EXT_VS1_TRIGGER (1U << 21) +#define R12EXT_VS2_TRIGGER (1U << 22) +#define R12EXT_COROSS_REQ_APU (1U << 23) +#define R12EXT_CROSS_REQ_L3 (1U << 24) +#define R12EXT_DDR_PST_ACK (1U << 25) +#define R12EXT_BIT26 (1U << 26) +#define R12EXT_BIT27 (1U << 27) +#define R12EXT_BIT28 (1U << 28) +#define R12EXT_BIT29 (1U << 29) +#define R12EXT_BIT30 (1U << 30) +#define R12EXT_BIT31 (1U << 31) +/* --- R13 Define --- */ +#define R13_SRCCLKENI0 (1U << 0) +#define R13_SRCCLKENI1 (1U << 1) +#define R13_MD_SRCCLKENA_0 (1U << 2) +#define R13_MD_APSRC_REQ_0 (1U << 3) +#define R13_CONN_DDR_EN (1U << 4) +#define R13_MD_SRCCLKENA_1 (1U << 5) +#define R13_SSPM_SRCCLKENA (1U << 6) +#define R13_SSPM_APSRC_REQ (1U << 7) +#define R13_MD1_STATE (1U << 8) +#define R13_BIT9 (1U << 9) +#define R13_MM_STATE (1U << 10) +#define R13_SSPM_STATE (1U << 11) +#define R13_MD_DDR_EN_0 (1U << 12) +#define R13_CONN_STATE (1U << 13) +#define R13_CONN_SRCCLKENA (1U << 14) +#define R13_CONN_APSRC_REQ (1U << 15) +#define R13_SC_DDR_PST_ACK_ALL (1U << 16) +#define R13_SC_DDR_PST_ABORT_ACK_ALL (1U << 17) +#define R13_SCP_STATE (1U << 18) +#define R13_CSYSPWRUPREQ (1U << 19) +#define R13_PWRAP_SLEEP_ACK (1U << 20) +#define R13_SC_EMI_CLK_OFF_ACK_ALL (1U << 21) +#define R13_AUDIO_DSP_STATE (1U << 22) +#define R13_SC_DMDRAMCSHU_ACK_ALL (1U << 23) +#define R13_CONN_SRCCLKENB (1U << 24) +#define R13_SC_DR_SRAM_LOAD_ACK_ALL (1U << 25) +#define R13_SUBSYS_IDLE_SIGNALS0 (1U << 26) +#define R13_DVFS_STATE (1U << 27) +#define R13_SC_DR_SRAM_PLL_LOAD_ACK_ALL (1U << 28) +#define R13_SC_DR_SRAM_RESTORE_ACK_ALL (1U << 29) +#define R13_MD_VRF18_REQ_0 (1U << 30) +#define R13_DDR_EN_STATE (1U << 31) +#endif /* PCM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h new file mode 100644 index 0000000..6c5cbed --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SLEEP_DEF_H +#define SLEEP_DEF_H + +/* + * Auto generated by DE, please DO NOT modify this file directly. + */ + +/* --- SPM Flag Define --- */ +#define SPM_FLAG_DISABLE_CPU_PDN (1U << 0) +#define SPM_FLAG_DISABLE_INFRA_PDN (1U << 1) +#define SPM_FLAG_DISABLE_DDRPHY_PDN (1U << 2) +#define SPM_FLAG_DISABLE_VCORE_DVS (1U << 3) +#define SPM_FLAG_DISABLE_VCORE_DFS (1U << 4) +#define SPM_FLAG_DISABLE_COMMON_SCENARIO (1U << 5) +#define SPM_FLAG_DISABLE_BUS_CLK_OFF (1U << 6) +#define SPM_FLAG_DISABLE_ARMPLL_OFF (1U << 7) +#define SPM_FLAG_KEEP_CSYSPWRACK_HIGH (1U << 8) +#define SPM_FLAG_ENABLE_LVTS_WORKAROUND (1U << 9) +#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10) +#define SPM_FLAG_RESERVED_BIT11 (1U << 11) +#define SPM_FLAG_ENABLE_SPM_DBG_WDT_DUMP (1U << 12) +#define SPM_FLAG_USE_SRCCLKENO2 (1U << 13) +#define SPM_FLAG_ENABLE_6315_CTRL (1U << 14) +#define SPM_FLAG_ENABLE_TIA_WORKAROUND (1U << 15) +#define SPM_FLAG_DISABLE_SYSRAM_SLEEP (1U << 16) +#define SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP (1U << 17) +#define SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP (1U << 18) +#define SPM_FLAG_ENABLE_MD_MUMTAS (1U << 19) +#define SPM_FLAG_ENABLE_VOLTAGE_BIN (1U << 20) +#define SPM_FLAG_RESERVED_BIT21 (1U << 21) +#define SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP (1U << 22) +#define SPM_FLAG_DISABLE_SRAM_EVENT (1U << 23) +#define SPM_FLAG_RESERVED_BIT24 (1U << 24) +#define SPM_FLAG_RESERVED_BIT25 (1U << 25) +#define SPM_FLAG_RESERVED_BIT26 (1U << 26) +#define SPM_FLAG_VTCXO_STATE (1U << 27) +#define SPM_FLAG_INFRA_STATE (1U << 28) +#define SPM_FLAG_APSRC_STATE (1U << 29) +#define SPM_FLAG_VRF18_STATE (1U << 30) +#define SPM_FLAG_DDREN_STATE (1U << 31) +/* --- SPM Flag1 Define --- */ +#define SPM_FLAG1_DISABLE_AXI_BUS_TO_26M (1U << 0) +#define SPM_FLAG1_DISABLE_SYSPLL_OFF (1U << 1) +#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH (1U << 2) +#define SPM_FLAG1_DISABLE_ULPOSC_OFF (1U << 3) +#define SPM_FLAG1_FW_SET_ULPOSC_ON (1U << 4) +#define SPM_FLAG1_RESERVED_BIT5 (1U << 5) +#define SPM_FLAG1_ENABLE_REKICK (1U << 6) +#define SPM_FLAG1_DISABLE_MD26M_CK_OFF (1U << 7) +#define SPM_FLAG1_RESERVED_BIT8 (1U << 8) +#define SPM_FLAG1_RESERVED_BIT9 (1U << 9) +#define SPM_FLAG1_DISABLE_SRCLKEN_LOW (1U << 10) +#define SPM_FLAG1_DISABLE_SCP_CLK_SWITCH (1U << 11) +#define SPM_FLAG1_RESERVED_BIT12 (1U << 12) +#define SPM_FLAG1_RESERVED_BIT13 (1U << 13) +#define SPM_FLAG1_RESERVED_BIT14 (1U << 14) +#define SPM_FLAG1_RESERVED_BIT15 (1U << 15) +#define SPM_FLAG1_RESERVED_BIT16 (1U << 16) +#define SPM_FLAG1_RESERVED_BIT17 (1U << 17) +#define SPM_FLAG1_RESERVED_BIT18 (1U << 18) +#define SPM_FLAG1_RESERVED_BIT19 (1U << 19) +#define SPM_FLAG1_DISABLE_DEVAPC_SRAM_SLEEP (1U << 20) +#define SPM_FLAG1_RESERVED_BIT21 (1U << 21) +#define SPM_FLAG1_ENABLE_VS1_VOTER (1U << 22) +#define SPM_FLAG1_ENABLE_VS2_VOTER (1U << 23) +#define SPM_FLAG1_DISABLE_SCP_VREQ_MASK_CONTROL (1U << 24) +#define SPM_FLAG1_RESERVED_BIT25 (1U << 25) +#define SPM_FLAG1_RESERVED_BIT26 (1U << 26) +#define SPM_FLAG1_RESERVED_BIT27 (1U << 27) +#define SPM_FLAG1_RESERVED_BIT28 (1U << 28) +#define SPM_FLAG1_RESERVED_BIT29 (1U << 29) +#define SPM_FLAG1_RESERVED_BIT30 (1U << 30) +#define SPM_FLAG1_DISABLE_CPUEB_OFF (1U << 31) +/* --- SPM DEBUG Define --- */ +#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0) +#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1) +#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2) +#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3) +#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4) +#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5) +#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6) +#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7) +#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8) +#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9) +#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC (1U << 10) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_STATE (1U << 11) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_STATE (1U << 12) +#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN (1U << 13) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_STATE (1U << 14) +#define SPM_DBG_DEBUG_IDX_SYSRAM_SLP (1U << 15) +#define SPM_DBG_DEBUG_IDX_SYSRAM_ON (1U << 16) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_SLP (1U << 17) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_ON (1U << 18) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP (1U << 19) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_ON (1U << 20) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_SLP (1U << 21) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_ON (1U << 22) +#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P575V (1U << 23) +#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P600V (1U << 24) +#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P650V (1U << 25) +#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P725V (1U << 26) +#define SPM_DBG_DEBUG_IDX_SPM_GO_WAKEUP_NOW (1U << 27) +#define SPM_DBG_DEBUG_IDX_VTCXO_STATE (1U << 28) +#define SPM_DBG_DEBUG_IDX_INFRA_STATE (1U << 29) +#define SPM_DBG_DEBUG_IDX_VRR18_STATE (1U << 30) +#define SPM_DBG_DEBUG_IDX_APSRC_STATE (1U << 31) +/* --- SPM DEBUG1 Define --- */ +#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_LP (1U << 0) +#define SPM_DBG1_DEBUG_IDX_VCORE_DVFS_START (1U << 1) +#define SPM_DBG1_DEBUG_IDX_SYSPLL_OFF (1U << 2) +#define SPM_DBG1_DEBUG_IDX_SYSPLL_ON (1U << 3) +#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_VCORE_DVFS (1U << 4) +#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_OFF (1U << 5) +#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_ON (1U << 6) +#define SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT (1U << 7) +#define SPM_DBG1_RESERVED_BIT8 (1U << 8) +#define SPM_DBG1_DEBUG_IDX_INFRA_SUB_MTCMOS_OFF (1U << 9) +#define SPM_DBG1_DEBUG_IDX_INFRA_SUB_MTCMOS_ON (1U << 10) +#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_ULPOSC (1U << 11) +#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_26M (1U << 12) +#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_32K (1U << 13) +#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_26M (1U << 14) +#define SPM_DBG1_DEBUG_IDX_BUS_CLK_OFF (1U << 15) +#define SPM_DBG1_DEBUG_IDX_BUS_CLK_ON (1U << 16) +#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_LOW (1U << 17) +#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_HIGH (1U << 18) +#define SPM_DBG1_RESERVED_BIT19 (1U << 19) +#define SPM_DBG1_DEBUG_IDX_ULPOSC_IS_OFF_BUT_SHOULD_ON (1U << 20) +#define SPM_DBG1_DEBUG_IDX_6315_LOW (1U << 21) +#define SPM_DBG1_DEBUG_IDX_6315_HIGH (1U << 22) +#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT (1U << 23) +#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT (1U << 24) +#define SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT (1U << 25) +#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT (1U << 26) +#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT (1U << 27) +#define SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT (1U << 28) +#define SPM_DBG1_RESERVED_BIT29 (1U << 29) +#define SPM_DBG1_RESERVED_BIT30 (1U << 30) +#define SPM_DBG1_DEBUG_DISABLE_CPUEB_OFF (1U << 31) + + /* Macro and Inline */ +#define is_cpu_pdn(flags) (((flags) & SPM_FLAG_DISABLE_CPU_PDN) == 0U) +#define is_infra_pdn(flags) (((flags) & SPM_FLAG_DISABLE_INFRA_PDN) == 0U) +#define is_ddrphy_pdn(flags) (((flags) & SPM_FLAG_DISABLE_DDRPHY_PDN) == 0U) +#endif /* SLEEP_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c new file mode 100644 index 0000000..7ccebd6 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + + +void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu) +{ + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); +} + +void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu) +{ + mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); +} + +void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr) +{ + assert(cluster == 0U); + + mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr); +} + +uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu) +{ + assert(cluster == 0U); + + return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR)); +} + +void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64) +{ + uint32_t reg; + + assert(cluster == 0U); + + reg = per_cluster(cluster, MCUCFG_INITARCH); + + if (arm64) { + mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); + } else { + mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); + } +} + +/** + * Return subsystem's power state. + * + * @mask: mask to SPM_CPU_PWR_STATUS to query the power state + * of one subsystem. + * RETURNS: + * 0 (the subsys was powered off) + * 1 (the subsys was powered on) + */ +bool spm_get_powerstate(uint32_t mask) +{ + return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask) != 0U; +} + +bool spm_get_cluster_powerstate(uint32_t cluster) +{ + assert(cluster == 0U); + + return spm_get_powerstate(MP0_CPUTOP); +} + +bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu) +{ + uint32_t mask = BIT(cpu); + + assert(cluster == 0U); + + return spm_get_powerstate(mask); +} + +int spmc_init(void) +{ + INFO("SPM: enable CPC mode\n"); + + mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN); + + mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B); + + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(1)); + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(2)); + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(3)); + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(4)); + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(5)); + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(6)); + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(7)); + + mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); + mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); + mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); + + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); + + return 0; +} + +/** + * Power on a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered on + * @cpu: the CPU ID of the CPU which to be powered on + */ +void spm_poweron_cpu(uint32_t cluster, uint32_t cpu) +{ + /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */ + if (cpu >= 4U) { + mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U); + } + + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); + mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); + + while (!spm_get_cpu_powerstate(cluster, cpu)) { + } + + mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); + + /* Enable Big CPU Last PC */ + if (cpu >= 4U) { + mmio_clrbits_32(LAST_PC_REG(cpu), BIT(3)); + } +} + +/** + * Power off a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered off + * @cpu: the CPU ID of the CPU which to be powered off + */ +void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu) +{ + /* Set mp0_spmc_pwr_on_cpuX = 0 */ + mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); +} + +/** + * Power off a cluster with specified index + * + * @cluster: the cluster index which to be powered off + */ +void spm_poweroff_cluster(uint32_t cluster) +{ + /* No need to power on/off cluster on single cluster platform */ + assert(false); +} + +/** + * Power on a cluster with specified index + * + * @cluster: the cluster index which to be powered on + */ +void spm_poweron_cluster(uint32_t cluster) +{ + /* No need to power on/off cluster on single cluster platform */ + assert(false); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h new file mode 100644 index 0000000..7ed2e62 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_H +#define MTSPMC_H + +#include + +int spmc_init(void); + +void spm_poweron_cpu(uint32_t cluster, uint32_t cpu); +void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu); + +void spm_poweroff_cluster(uint32_t cluster); +void spm_poweron_cluster(uint32_t cluster); + +bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu); +bool spm_get_cluster_powerstate(uint32_t cluster); +bool spm_get_powerstate(uint32_t mask); + +void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64); +void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr); +uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu); + +void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu); +void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu); + +#endif /* MTSPMC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000..ad78295 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_PRIVATE_H +#define MTSPMC_PRIVATE_H + +#include +#include + +unsigned long read_cpuectlr(void); +void write_cpuectlr(unsigned long cpuectlr); + +unsigned long read_cpupwrctlr_el1(void); +void write_cpupwrctlr_el1(unsigned long cpuectlr); + +/* + * per_cpu/cluster helper + */ +struct per_cpu_reg { + unsigned int cluster_addr; + unsigned int cpu_stride; +}; + +#define per_cpu(cluster, cpu, reg) \ + (reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride)) + +#define per_cluster(cluster, reg) (reg[cluster].cluster_addr) + +#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs)) +#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs)) +#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs)) + +/* === SPMC related registers */ +#define SPM_POWERON_CONFIG_EN SPM_REG(0x000) +/* bit-fields of SPM_POWERON_CONFIG_EN */ +#define PROJECT_CODE (U(0xb16) << 16) +#define BCLK_CG_EN BIT(0) + +#define SPM_PWR_STATUS SPM_REG(0x16c) +#define SPM_PWR_STATUS_2ND SPM_REG(0x170) +#define SPM_CPU_PWR_STATUS SPM_REG(0x174) + +/* bit-fields of SPM_PWR_STATUS */ +#define MD BIT(0) +#define CONN BIT(1) +#define DDRPHY BIT(2) +#define DISP BIT(3) +#define MFG BIT(4) +#define ISP BIT(5) +#define INFRA BIT(6) +#define VDEC BIT(7) +#define MP0_CPUTOP BIT(8) +#define MP0_CPU0 BIT(9) +#define MP0_CPU1 BIT(10) +#define MP0_CPU2 BIT(11) +#define MP0_CPU3 BIT(12) +#define MCUSYS BIT(14) +#define MP0_CPU4 BIT(15) +#define MP0_CPU5 BIT(16) +#define MP0_CPU6 BIT(17) +#define MP0_CPU7 BIT(18) +#define VEN BIT(21) + +/* === SPMC related registers */ +#define SPM_MCUSYS_PWR_CON MCUCFG_REG(0xd200) +#define SPM_MP0_CPUTOP_PWR_CON MCUCFG_REG(0xd204) +#define SPM_MP0_CPU0_PWR_CON MCUCFG_REG(0xd208) +#define SPM_MP0_CPU1_PWR_CON MCUCFG_REG(0xd20c) +#define SPM_MP0_CPU2_PWR_CON MCUCFG_REG(0xd210) +#define SPM_MP0_CPU3_PWR_CON MCUCFG_REG(0xd214) +#define SPM_MP0_CPU4_PWR_CON MCUCFG_REG(0xd218) +#define SPM_MP0_CPU5_PWR_CON MCUCFG_REG(0xd21c) +#define SPM_MP0_CPU6_PWR_CON MCUCFG_REG(0xd220) +#define SPM_MP0_CPU7_PWR_CON MCUCFG_REG(0xd224) + +/* bit fields of SPM_*_PWR_CON */ +#define PWR_ON_ACK BIT(31) +#define VPROC_EXT_OFF BIT(7) +#define DORMANT_EN BIT(6) +#define RESETPWRON_CONFIG BIT(5) +#define PWR_CLK_DIS BIT(4) +#define PWR_ON BIT(2) +#define PWR_RST_B BIT(0) + +/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */ +static const struct per_cpu_reg SPM_CPU_PWR[] = { + { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U } +}; + +/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */ +static const struct per_cpu_reg SPM_CLUSTER_PWR[] = { + { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U } +}; + +/* === MCUCFG related registers */ +/* aa64naa32 */ +#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4) +/* reset vectors */ +#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900) +#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908) +#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910) +#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918) +#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920) +#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928) +#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930) +#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938) + +/* MCUSYS DREQ BIG VPROC ISO control */ +#define DREQ20_BIG_VPROC_ISO MCUCFG_REG(0xad8c) + +/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */ +static const struct per_cpu_reg MCUCFG_BOOTADDR[] = { + { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U } +}; + +/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */ +static const struct per_cpu_reg MCUCFG_INITARCH[] = { + { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U } +}; + +#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu) +#define LAST_PC_REG(cpu) (MCUCFG_REG(0x308) + (cpu * 0x800)) + +/* === CPC control */ +#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) +#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840) + +/* bit fields of CPC_FLOW_CTRL_CFG */ +#define CPC_CTRL_ENABLE BIT(16) +#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */ +#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu) + +/* bit fields of CPC_SPMC_PWR_STATUS */ +#define CORE_SPMC_PWR_ON_ACK GENMASK(15, 0) + +/* === APB Module infracfg_ao */ +#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220) +#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224) +#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228) +#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0) +#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4) +#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250) +#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254) +#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258) +#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8) +#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac) + +/* bit fields of INFRA_TOPAXI_PROTECTEN */ +#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12) +#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12)) + +/* === SPARK */ +#define VOLTAGE_04 U(0x40) +#define VOLTAGE_05 U(0x60) + +#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200) +#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334) +#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340) + +/* bit fields of CPU0_ILDO_CONTROL5 */ +#define ILDO_RET_VOSEL GENMASK(7, 0) + +/* bit fields of PTP3_CPU_SPMC_SW_CFG */ +#define SW_SPARK_EN BIT(0) + +/* bit fields of CPU0_ILDO_CONTROL8 */ +#define ILDO_BYPASS_B BIT(0) + +static const struct per_cpu_reg MCUCFG_SPARK[] = { + { .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U } +}; + +static const struct per_cpu_reg ILDO_CONTROL5[] = { + { .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U } +}; + +static const struct per_cpu_reg ILDO_CONTROL8[] = { + { .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U } +}; + +#endif /* MTSPMC_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h new file mode 100644 index 0000000..046cf73 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCUCFG_H +#define MCUCFG_H + +#ifndef __ASSEMBLER__ +#include +#endif /* __ASSEMBLER__ */ + +#include + +#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs)) + +#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8)) +#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8)) + +#define MP2_CPUCFG MCUCFG_REG(0x2208) + +#define MP2_CPU0_STANDBYWFE BIT(4) +#define MP2_CPU1_STANDBYWFE BIT(5) + +#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788) +#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C) +#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790) + +#define sw_spark_en BIT(0) +#define sw_no_wait_for_q_channel BIT(1) +#define sw_fsm_override BIT(2) +#define sw_logic_pre1_pdb BIT(3) +#define sw_logic_pre2_pdb BIT(4) +#define sw_logic_pdb BIT(5) +#define sw_iso BIT(6) +#define sw_sram_sleepb (U(0x3F) << 7) +#define sw_sram_isointb BIT(13) +#define sw_clk_dis BIT(14) +#define sw_ckiso BIT(15) +#define sw_pd (U(0x3F) << 16) +#define sw_hot_plug_reset BIT(22) +#define sw_pwr_on_override_en BIT(23) +#define sw_pwr_on BIT(24) +#define sw_coq_dis BIT(25) +#define logic_pdbo_all_off_ack BIT(26) +#define logic_pdbo_all_on_ack BIT(27) +#define logic_pre2_pdbo_all_on_ack BIT(28) +#define logic_pre1_pdbo_all_on_ack BIT(29) + + +#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \ + (MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4) + +#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30) +#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34) +#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38) +#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C) + +#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30) +#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34) +#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38) +#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C) + +#define cpu_sw_spark_en BIT(0) +#define cpu_sw_no_wait_for_q_channel BIT(1) +#define cpu_sw_fsm_override BIT(2) +#define cpu_sw_logic_pre1_pdb BIT(3) +#define cpu_sw_logic_pre2_pdb BIT(4) +#define cpu_sw_logic_pdb BIT(5) +#define cpu_sw_iso BIT(6) +#define cpu_sw_sram_sleepb BIT(7) +#define cpu_sw_sram_isointb BIT(8) +#define cpu_sw_clk_dis BIT(9) +#define cpu_sw_ckiso BIT(10) +#define cpu_sw_pd (U(0x1F) << 11) +#define cpu_sw_hot_plug_reset BIT(16) +#define cpu_sw_powr_on_override_en BIT(17) +#define cpu_sw_pwr_on BIT(18) +#define cpu_spark2ldo_allswoff BIT(19) +#define cpu_pdbo_all_on_ack BIT(20) +#define cpu_pre2_pdbo_allon_ack BIT(21) +#define cpu_pre1_pdbo_allon_ack BIT(22) + +/* CPC related registers */ +#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714) +#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804) +#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) +#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818) +#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c) +#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824) +#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828) +#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8) +#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac) +#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00) +#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04) +#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08) +#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c) +#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10) +#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14) +#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20) +#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70) +#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74) + +#define SPARK2LDO MCUCFG_REG(0x2700) +/* APB Module mcucfg */ +#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000) +#define MP0_AXI_CONFIG MCUCFG_REG(0x02C) +#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030) +#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034) +#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038) +#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8)) +#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C) +#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054) +#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064) + +#define MP0_RW_RSVD0 MCUCFG_REG(0x06C) + + +#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200) +#define MP1_AXI_CONFIG MCUCFG_REG(0x22C) +#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230) +#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234) +#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238) +#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8)) +#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C) +#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254) +#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264) + +#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740) +#define SYNC_DCM_CONFIG MCUCFG_REG(0x744) + +#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0) + +#define MP0_SPMC MCUCFG_REG(0x788) +#define MP1_SPMC MCUCFG_REG(0x78C) +#define MP2_AXI_CONFIG MCUCFG_REG(0x220C) +#define MP2_AXI_CONFIG_ACINACTM BIT(0) +#define MP2_AXI_CONFIG_AINACTS BIT(4) + +#define MPx_AXI_CONFIG_ACINACTM BIT(4) +#define MPx_AXI_CONFIG_AINACTS BIT(5) + +#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28) + +#define MP0_CPU0_STANDBYWFE BIT(20) +#define MP0_CPU1_STANDBYWFE BIT(21) +#define MP0_CPU2_STANDBYWFE BIT(22) +#define MP0_CPU3_STANDBYWFE BIT(23) + +#define MP1_CPU0_STANDBYWFE BIT(20) +#define MP1_CPU1_STANDBYWFE BIT(21) +#define MP1_CPU2_STANDBYWFE BIT(22) +#define MP1_CPU3_STANDBYWFE BIT(23) + +#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00) +#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04) +#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08) +#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00) +#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04) +#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08) + +#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008) +#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0) +#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4) + +#define MP2_COQ MCUCFG_REG(0x22BC) +#define MP2_COQ_SW_DIS BIT(0) + +#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400) +#define MP2_CA15M_MON_L MCUCFG_REG(0x2404) + +#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430) +#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438) +#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434) +#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C) + +#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068) +#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268) +#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C) + +#define MP2_SW_RST_B BIT(0) +#define MP2_TOPAON_APB_MASK BIT(1) + +#define B_SW_HOT_PLUG_RESET BIT(30) + +#define B_SW_PD_OFFSET 18U +#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET) + +#define B_SW_SRAM_SLEEPB_OFFSET 12U +#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET) + +#define B_SW_SRAM_ISOINTB BIT(9) +#define B_SW_ISO BIT(8) +#define B_SW_LOGIC_PDB BIT(7) +#define B_SW_LOGIC_PRE2_PDB BIT(6) +#define B_SW_LOGIC_PRE1_PDB BIT(5) +#define B_SW_FSM_OVERRIDE BIT(4) +#define B_SW_PWR_ON BIT(3) +#define B_SW_PWR_ON_OVERRIDE_EN BIT(2) + +#define B_FSM_STATE_OUT_OFFSET (6U) +#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET) +#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5) +#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4) +#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3) +#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2) + +#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET) +#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET) +#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET) + +#ifndef __ASSEMBLER__ +/* cpu boot mode */ +enum { + MP0_CPUCFG_64BIT_SHIFT = 12U, + MP1_CPUCFG_64BIT_SHIFT = 28U, + MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT, + MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT +}; + +enum { + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U, + + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT +}; + +enum { + MP1_AINACTS_SHIFT = 4U, + MP1_AINACTS = 1U << MP1_AINACTS_SHIFT +}; + +enum { + MP1_SW_CG_GEN_SHIFT = 12U, + MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT +}; + +enum { + MP1_L2RSTDISABLE_SHIFT = 14U, + MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT +}; +#endif /* __ASSEMBLER__ */ + +#endif /* MCUCFG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h new file mode 100644 index 0000000..9b550ee --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_HELPERS_H__ +#define __PLAT_HELPERS_H__ + +unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr); + +#endif /* __PLAT_HELPERS_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S new file mode 100644 index 0000000..7d17e36 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception + * is taken in BL31. + * Clobbers: x0 - x10, x26, x27, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + /* To-do: GIC owner */ + /* To-do: CCI owner */ + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h new file mode 100644 index 0000000..deaac97 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MTK_LPM_H +#define PLAT_MTK_LPM_H + +#include +#include + +#define MT_IRQ_REMAIN_MAX U(32) +#define MT_IRQ_REMAIN_CAT_LOG BIT(31) + +struct mt_irqremain { + unsigned int count; + unsigned int irqs[MT_IRQ_REMAIN_MAX]; + unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX]; + unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX]; +}; + +#define PLAT_RC_STATUS_READY BIT(0) +#define PLAT_RC_STATUS_FEATURE_EN BIT(1) +#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31) + +struct mt_lpm_tz { + int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state); + + int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state); + + int (*pwr_cluster_on)(unsigned int cpu, + const psci_power_state_t *state); + int (*pwr_cluster_dwn)(unsigned int cpu, + const psci_power_state_t *state); + + int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_mcusys_on_finished)(unsigned int cpu, + const psci_power_state_t *state); + int (*pwr_mcusys_dwn)(unsigned int cpu, + const psci_power_state_t *state); +}; + +const struct mt_lpm_tz *mt_plat_cpu_pm_init(void); + +#endif /* PLAT_MTK_LPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h new file mode 100644 index 0000000..a2881ce --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PM_H +#define PLAT_PM_H + +#include + +#define MT_PLAT_PWR_STATE_CPU U(1) +#define MT_PLAT_PWR_STATE_CLUSTER U(2) +#define MT_PLAT_PWR_STATE_MCUSYS U(3) +#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8) +#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9) + +#define MTK_LOCAL_STATE_RUN U(0) +#define MTK_LOCAL_STATE_RET U(1) +#define MTK_LOCAL_STATE_OFF U(2) + +#define MTK_AFFLVL_CPU U(0) +#define MTK_AFFLVL_CLUSTER U(1) +#define MTK_AFFLVL_MCUSYS U(2) +#define MTK_AFFLVL_SYSTEM U(3) + +#define IS_CLUSTER_OFF_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER]) +#define IS_MCUSYS_OFF_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS]) +#define IS_SYSTEM_SUSPEND_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM]) + +#define IS_PLAT_SUSPEND_ID(stateid)\ + ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \ + || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND)) + +#endif /* PLAT_PM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h new file mode 100644 index 0000000..42ca415 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h new file mode 100644 index 0000000..f68a4ea --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +/******************************************************************************* + * Plat SiP function constants + ******************************************************************************/ +#define MTK_PLAT_SIP_NUM_CALLS 2 + +/* DFD */ +#define MTK_SIP_KERNEL_DFD_AARCH32 0x82000205 +#define MTK_SIP_KERNEL_DFD_AARCH64 0xC2000205 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h new file mode 100644 index 0000000..ec377b5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + + +#define PLAT_PRIMARY_CPU 0x0 + +#define MT_GIC_BASE 0x0c000000 +#define PLAT_MT_CCI_BASE 0x0c500000 +#define MCUCFG_BASE 0x0c530000 + +#define IO_PHYS 0x10000000 + +/* Aggregate of all devices for MMU mapping */ +#define MTK_DEV_RNG0_BASE IO_PHYS +#define MTK_DEV_RNG0_SIZE 0x10000000 +#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x10000000) +#define MTK_DEV_RNG1_SIZE 0x10000000 +#define MTK_DEV_RNG2_BASE 0x0c000000 +#define MTK_DEV_RNG2_SIZE 0x600000 +#define MTK_MCDI_SRAM_BASE 0x11B000 +#define MTK_MCDI_SRAM_MAP_SIZE 0x1000 + +#define APUSYS_BASE 0x19000000 +#define APUSYS_SCTRL_REVISER_BASE 0x19021000 +#define APUSYS_SCTRL_REVISER_SIZE 0x1000 +#define APUSYS_APU_S_S_4_BASE 0x190F2000 +#define APUSYS_APU_S_S_4_SIZE 0x1000 +#define APUSYS_APC_AO_WRAPPER_BASE 0x190F8000 +#define APUSYS_APC_AO_WRAPPER_SIZE 0x1000 +#define APUSYS_NOC_DAPC_AO_BASE 0x190FC000 +#define APUSYS_NOC_DAPC_AO_SIZE 0x1000 + +#define TOPCKGEN_BASE (IO_PHYS + 0x00000000) +#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000) +#define GPIO_BASE (IO_PHYS + 0x00005000) +#define SPM_BASE (IO_PHYS + 0x00006000) +#define APMIXEDSYS (IO_PHYS + 0x0000C000) +#define DVFSRC_BASE (IO_PHYS + 0x00012000) +#define PMIC_WRAP_BASE (IO_PHYS + 0x00026000) +#define DEVAPC_INFRA_AO_BASE (IO_PHYS + 0x00030000) +#define DEVAPC_PERI_AO_BASE (IO_PHYS + 0x00034000) +#define DEVAPC_PERI_AO2_BASE (IO_PHYS + 0x00038000) +#define DEVAPC_PERI_PAR_AO_BASE (IO_PHYS + 0x0003C000) +#define EMI_BASE (IO_PHYS + 0x00219000) +#define EMI_MPU_BASE (IO_PHYS + 0x00226000) +#define SSPM_MBOX_BASE (IO_PHYS + 0x00480000) +#define IOCFG_RM_BASE (IO_PHYS + 0x01C20000) +#define IOCFG_BM_BASE (IO_PHYS + 0x01D10000) +#define IOCFG_BL_BASE (IO_PHYS + 0x01D30000) +#define IOCFG_BR_BASE (IO_PHYS + 0x01D40000) +#define IOCFG_LM_BASE (IO_PHYS + 0x01E20000) +#define IOCFG_LB_BASE (IO_PHYS + 0x01E70000) +#define IOCFG_RT_BASE (IO_PHYS + 0x01EA0000) +#define IOCFG_LT_BASE (IO_PHYS + 0x01F20000) +#define IOCFG_TL_BASE (IO_PHYS + 0x01F30000) +#define MMSYS_BASE (IO_PHYS + 0x04000000) +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define UART0_BASE (IO_PHYS + 0x01002000) +#define UART1_BASE (IO_PHYS + 0x01003000) + +#define UART_BAUDRATE 115200 + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 13000000 +#define SYS_COUNTER_FREQ_IN_MHZ 13 + +/******************************************************************************* + * GIC-600 & interrupt handling related constants + ******************************************************************************/ + +/* Base MTK_platform compatible GIC memory map */ +#define BASE_GICD_BASE MT_GIC_BASE +#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000) + +#define SYS_CIRQ_BASE (IO_PHYS + 0x204000) +#define CIRQ_REG_NUM 14 +#define CIRQ_IRQ_NUM 439 +#define CIRQ_SPI_START 64 +#define MD_WDT_IRQ_BIT_ID 110 + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ +#define PLATFORM_STACK_SIZE 0x800 + +#define PLAT_MAX_PWR_LVL U(3) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(9) + +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_MCUSYS_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(8) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8) + +#define SOC_CHIP_ID U(0x8192) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +#define TZRAM_BASE 0x54600000 +#define TZRAM_SIZE 0x00030000 + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#define BL31_BASE (TZRAM_BASE + 0x1000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 16 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h new file mode 100644 index 0000000..a9c7bc8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RTC_H +#define RTC_H + +#include + +#endif /* RTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c new file mode 100644 index 0000000..018e418 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* common headers */ +#include + +#include +#include +#include +#include + +/* platform specific headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Cluster state request: + * [0] : The CPU requires cluster power down + * [1] : The CPU requires cluster power on + */ +#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff) +#define coordinate_cluster_pwron() coordinate_cluster(1) +#define coordinate_cluster_pwroff() coordinate_cluster(0) + +/* platform secure entry point */ +static uintptr_t secure_entrypoint; +/* per-CPU power state */ +static unsigned int plat_power_state[PLATFORM_CORE_COUNT]; + +/* platform CPU power domain - ops */ +static const struct mt_lpm_tz *plat_mt_pm; + +#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \ + int ret = -1; \ + if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \ + ret = plat_mt_pm->_name(_cpu, _state); \ + } \ + ret; }) + +#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \ + if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \ + (void) plat_mt_pm->_name(_cpu, _state); \ + } \ + }) + +/* + * Common MTK_platform operations to power on/off a + * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_cpu_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state); + + if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) || + (req_pstate == 0U)) { /* hotplug off */ + coordinate_cluster_pwroff(); + } + + /* Prevent interrupts from spuriously waking up this CPU */ + mt_gic_rdistif_save(); + gicv3_cpuif_disable(cpu); + gicv3_rdistif_off(cpu); + /* PTP3 config */ + ptp3_deinit(cpu); +} + +static void plat_cpu_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state); + + coordinate_cluster_pwron(); + + /* + * If mcusys does power down before then restore + * all CPUs' GIC Redistributors + */ + if (IS_MCUSYS_OFF_STATE(state)) { + mt_gic_rdistif_restore_all(); + } else { + gicv3_rdistif_on(cpu); + gicv3_cpuif_enable(cpu); + mt_gic_rdistif_init(); + mt_gic_rdistif_restore(); + } + + /* PTP3 config */ + ptp3_init(cpu); +} + +/* + * Common MTK_platform operations to power on/off a + * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_cluster_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) { + coordinate_cluster_pwron(); + + /* TODO: return on fail. + * Add a 'return' here before adding any code following + * the if-block. + */ + } +} + +static void plat_cluster_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) { + /* TODO: return on fail. + * Add a 'return' here before adding any code following + * the if-block. + */ + } +} + +/* + * Common MTK_platform operations to power on/off a + * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_mcusys_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) { + return; /* return on fail */ + } + + mt_gic_distif_save(); + gic_sgi_save_all(); +} + +static void plat_mcusys_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) { + return; /* return on fail */ + } + + mt_gic_init(); + mt_gic_distif_restore(); + gic_sgi_restore_all(); + + dfd_resume(); + + plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state); +} + +/* + * plat_psci_ops implementation + */ + +static void plat_cpu_standby(plat_local_state_t cpu_state) +{ + uint64_t scr; + + scr = read_scr_el3(); + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + isb(); + dsb(); + wfi(); + + write_scr_el3(scr); +} + +static int plat_power_domain_on(u_register_t mpidr) +{ + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + unsigned int cluster = 0U; + + if (cpu >= PLATFORM_CORE_COUNT) { + return PSCI_E_INVALID_PARAMS; + } + + if (!spm_get_cluster_powerstate(cluster)) { + spm_poweron_cluster(cluster); + } + + /* init CPU reset arch as AARCH64 */ + mcucfg_init_archstate(cluster, cpu, true); + mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint); + spm_poweron_cpu(cluster, cpu); + + return PSCI_E_SUCCESS; +} + +static void plat_power_domain_on_finish(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + + assert(cpu < PLATFORM_CORE_COUNT); + + /* Allow IRQs to wakeup this core in IDLE flow */ + mcucfg_enable_gic_wakeup(0U, cpu); + + if (IS_CLUSTER_OFF_STATE(state)) { + plat_cluster_pwron_common(cpu, state, 0U); + } + + plat_cpu_pwron_common(cpu, state, 0U); +} + +static void plat_power_domain_off(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + + assert(cpu < PLATFORM_CORE_COUNT); + + plat_cpu_pwrdwn_common(cpu, state, 0U); + spm_poweroff_cpu(0U, cpu); + + /* prevent unintended IRQs from waking up the hot-unplugged core */ + mcucfg_disable_gic_wakeup(0U, cpu); + + if (IS_CLUSTER_OFF_STATE(state)) { + plat_cluster_pwrdwn_common(cpu, state, 0U); + } +} + +static void plat_power_domain_suspend(const psci_power_state_t *state) +{ + unsigned int cpu = plat_my_core_pos(); + + assert(cpu < PLATFORM_CORE_COUNT); + + plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state); + + /* Perform the common CPU specific operations */ + plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]); + + if (IS_CLUSTER_OFF_STATE(state)) { + /* Perform the common cluster specific operations */ + plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]); + } + + if (IS_MCUSYS_OFF_STATE(state)) { + /* Perform the common mcusys specific operations */ + plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]); + } +} + +static void plat_power_domain_suspend_finish(const psci_power_state_t *state) +{ + unsigned int cpu = plat_my_core_pos(); + + assert(cpu < PLATFORM_CORE_COUNT); + + if (IS_MCUSYS_OFF_STATE(state)) { + /* Perform the common mcusys specific operations */ + plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]); + } + + if (IS_CLUSTER_OFF_STATE(state)) { + /* Perform the common cluster specific operations */ + plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]); + } + + /* Perform the common CPU specific operations */ + plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]); + + plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state); +} + +static int plat_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int pstate = psci_get_pstate_type(power_state); + unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state); + unsigned int cpu = plat_my_core_pos(); + + if (pstate == PSTATE_TYPE_STANDBY) { + req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE; + } else { + unsigned int i; + unsigned int pstate_id = psci_get_pstate_id(power_state); + plat_local_state_t s = MTK_LOCAL_STATE_OFF; + + /* Use pstate_id to be power domain state */ + if (pstate_id > s) { + s = (plat_local_state_t)pstate_id; + } + + for (i = 0U; i <= aff_lvl; i++) { + req_state->pwr_domain_state[i] = s; + } + } + + plat_power_state[cpu] = power_state; + return PSCI_E_SUCCESS; +} + +static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int lv; + unsigned int cpu = plat_my_core_pos(); + + for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) { + req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE; + } + + plat_power_state[cpu] = + psci_make_powerstate( + MT_PLAT_PWR_STATE_SYSTEM_SUSPEND, + PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL); + + flush_dcache_range((uintptr_t) + &plat_power_state[cpu], + sizeof(plat_power_state[cpu])); +} + +static void __dead2 plat_mtk_system_off(void) +{ + INFO("MTK System Off\n"); + + rtc_power_off_sequence(); + pmic_power_off(); + + wfi(); + ERROR("MTK System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 plat_mtk_system_reset(void) +{ + struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset(); + + INFO("MTK System Reset\n"); + + gpio_set_value(gpio_reset->index, gpio_reset->polarity); + + wfi(); + ERROR("MTK System Reset: operation not handled.\n"); + panic(); +} + +static const plat_psci_ops_t plat_psci_ops = { + .system_reset = plat_mtk_system_reset, + .cpu_standby = plat_cpu_standby, + .pwr_domain_on = plat_power_domain_on, + .pwr_domain_on_finish = plat_power_domain_on_finish, + .pwr_domain_off = plat_power_domain_off, + .pwr_domain_suspend = plat_power_domain_suspend, + .pwr_domain_suspend_finish = plat_power_domain_suspend_finish, + .system_off = plat_mtk_system_off, + .validate_power_state = plat_validate_power_state, + .get_sys_suspend_power_state = plat_get_sys_suspend_power_state +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &plat_psci_ops; + secure_entrypoint = sec_entrypoint; + + /* + * init the warm reset config for boot CPU + * reset arch as AARCH64 + * reset addr as function bl31_warm_entrypoint() + */ + mcucfg_init_archstate(0U, 0U, true); + mcucfg_set_bootaddr(0U, 0U, secure_entrypoint); + + spmc_init(); + plat_mt_pm = mt_plat_cpu_pm_init(); + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c b/arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c new file mode 100644 index 0000000..353faf8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "plat_sip_calls.h" + +uintptr_t mediatek_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) +{ + uint64_t ret; + uint32_t rnd_val0 = 0U; + + switch (smc_fid) { + case MTK_SIP_VCORE_CONTROL_ARCH32: + case MTK_SIP_VCORE_CONTROL_ARCH64: + ret = spm_vcorefs_args(x1, x2, x3, (uint64_t *)&x4); + SMC_RET2(handle, ret, x4); + break; + case MTK_SIP_APUSYS_CONTROL_AARCH32: + case MTK_SIP_APUSYS_CONTROL_AARCH64: + ret = apusys_kernel_ctrl(x1, x2, x3, x4, &rnd_val0); + SMC_RET2(handle, ret, rnd_val0); + break; + case MTK_SIP_KERNEL_DFD_AARCH32: + case MTK_SIP_KERNEL_DFD_AARCH64: + ret = dfd_smc_dispatcher(x1, x2, x3, x4); + SMC_RET1(handle, ret); + break; + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c new file mode 100644 index 0000000..8c1231a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Project Includes */ +#include +#include +#include + +/* Platform Includes */ +#include +#include + +const unsigned char mtk_power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* Number of children for the root node */ + PLATFORM_MCUSYS_COUNT, + /* Number of children for the mcusys node */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the MT8192 default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return mtk_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + if (read_mpidr() & MPIDR_MT_MASK) { + /* ARMv8.2 arch */ + if (mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) { + return -1; + } + return plat_mediatek_calc_core_pos(mpidr); + } + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) { + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return (cpu_id + (cluster_id * 8)); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8192/platform.mk new file mode 100644 index 0000000..cbdaadd --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/platform.mk @@ -0,0 +1,99 @@ +# +# Copyright (c) 2020, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MTK_PLAT := plat/mediatek +MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} + +PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT}/common/drivers/gic600/ \ + -I${MTK_PLAT}/common/drivers/gpio/ \ + -I${MTK_PLAT}/common/drivers/rtc/ \ + -I${MTK_PLAT}/common/drivers/timer/ \ + -I${MTK_PLAT}/common/drivers/uart/ \ + -I${MTK_PLAT}/common/lpm/ \ + -I${MTK_PLAT_SOC}/include/ \ + -I${MTK_PLAT_SOC}/drivers/ \ + -I${MTK_PLAT_SOC}/drivers/apusys/ \ + -I${MTK_PLAT_SOC}/drivers/dcm \ + -I${MTK_PLAT_SOC}/drivers/devapc \ + -I${MTK_PLAT_SOC}/drivers/dfd \ + -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \ + -I${MTK_PLAT_SOC}/drivers/gpio/ \ + -I${MTK_PLAT_SOC}/drivers/mcdi/ \ + -I${MTK_PLAT_SOC}/drivers/pmic/ \ + -I${MTK_PLAT_SOC}/drivers/ptp3/ \ + -I${MTK_PLAT_SOC}/drivers/spmc/ + +GICV3_SUPPORT_GIC600 := 1 +include drivers/arm/gic/v3/gicv3.mk +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} \ + plat/common/aarch64/crash_console_helpers.S \ + plat/common/plat_psci_common.c + +BL31_SOURCES += common/desc_image_load.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + drivers/gpio/gpio.c \ + lib/bl_aux_params/bl_aux_params.c \ + lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a76.S \ + plat/common/plat_gicv3.c \ + ${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c \ + ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_mt6359p.c \ + ${MTK_PLAT}/common/drivers/timer/mt_timer.c \ + ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/lpm/mt_lp_rm.c \ + ${MTK_PLAT}/common/mtk_cirq.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/params_setup.c \ + ${MTK_PLAT_SOC}/aarch64/platform_common.c \ + ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ + ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \ + ${MTK_PLAT_SOC}/plat_pm.c \ + ${MTK_PLAT_SOC}/plat_topology.c \ + ${MTK_PLAT_SOC}/plat_sip_calls.c \ + ${MTK_PLAT_SOC}/drivers/apusys/mtk_apusys.c \ + ${MTK_PLAT_SOC}/drivers/apusys/mtk_apusys_apc.c \ + ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \ + ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \ + ${MTK_PLAT_SOC}/drivers/devapc/devapc.c \ + ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \ + ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \ + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_lp_irqremain.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \ + ${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.c \ + ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c + +# Build SPM drivers +include ${MTK_PLAT_SOC}/drivers/spm/build.mk + +# Configs for A76 and A55 +HW_ASSISTED_COHERENCY := 1 +USE_COHERENT_MEM := 0 +CTX_INCLUDE_AARCH32_REGS := 0 + +# indicate the reset vector address can be programmed +PROGRAMMABLE_RESET_ADDRESS := 1 + +COLD_BOOT_SINGLE_CPU := 1 + +MACH_MT8192 := 1 +$(eval $(call add_define,MACH_MT8192)) + +include lib/coreboot/coreboot.mk + diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S new file mode 100644 index 0000000..a973f4d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_mediatek_calc_core_pos + +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_mediatek_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_mediatek_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr); + * + * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and + * AFF0 is thread id. There is only one cluster in ARMv8.2 + * and one thread in current implementation. + * + * With this function: CorePos = CoreID (AFF1) + * we do it with x0 = (x0 >> 8) & 0xff + * ----------------------------------------------------- + */ +func plat_mediatek_calc_core_pos + mov x1, #MPIDR_AFFLVL_MASK + and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT + ret +endfunc plat_mediatek_calc_core_pos diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c new file mode 100644 index 0000000..2b95171 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_mmap[] = { + /* for TF text, RO, RW */ + MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_MCDI_SRAM_BASE, MTK_MCDI_SRAM_MAP_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DP_SEC_BASE, DP_SEC_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(eDP_SEC_BASE, eDP_SEC_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(APUSYS_SCTRL_REVISER_BASE, APUSYS_SCTRL_REVISER_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(APUSYS_APU_S_S_4_BASE, APUSYS_APU_S_S_4_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(APUSYS_APU_PLL_BASE, APUSYS_APU_PLL_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(APUSYS_APU_ACC_BASE, APUSYS_APU_ACC_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit) +{ + mmap_add_region(total_base, total_base, total_size, + MT_RW_DATA | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + MT_CODE | MT_SECURE); + mmap_add(plat_mmap); + init_xlat_tables(); + enable_mmu_el3(0); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c new file mode 100644 index 0000000..dff6670 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* System Includes */ +#include + +/* Project Includes */ +#include +#include +#include +#include +#include +#include + +/* Platform Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + * BL2 has flushed this information to memory, so we are guaranteed to pick up + * good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + params_early_setup(arg1); + +#if COREBOOT + if (coreboot_serial.type) { + console_16550_register(coreboot_serial.baseaddr, + coreboot_serial.input_hertz, + coreboot_serial.baud, + &console); + } +#else + console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console); +#endif + + NOTICE("MT8195 bl31_setup\n"); + + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); +} + + +/******************************************************************************* + * Perform any BL31 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + /* Set dcm on */ + if (!dcm_set_default()) { + ERROR("Failed to set default dcm on!!\n"); + } + + /* Initialize EMI MPU */ + emi_mpu_init(); + + /* Initialize the GIC driver, CPU and distributor interfaces */ + mt_gic_driver_init(); + mt_gic_init(); + + mt_gpio_init(); + mt_systimer_init(); + generic_delay_timer_init(); + spm_boot_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + plat_configure_mmu_el3(BL31_START, + BL31_END - BL31_START, + BL_CODE_BASE, + BL_CODE_END); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c new file mode 100644 index 0000000..0eb8d4a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +uint32_t mixed_con0_addr[APUPLL_MAX] = { + APU_PLL4H_PLL1_CON0, + APU_PLL4H_PLL2_CON0, + APU_PLL4H_PLL3_CON0, + APU_PLL4H_PLL4_CON0, +}; + +uint32_t mixed_con1_addr[APUPLL_MAX] = { + APU_PLL4H_PLL1_CON1, + APU_PLL4H_PLL2_CON1, + APU_PLL4H_PLL3_CON1, + APU_PLL4H_PLL4_CON1, +}; + +uint32_t mixed_con3_addr[APUPLL_MAX] = { + APU_PLL4H_PLL1_CON3, + APU_PLL4H_PLL2_CON3, + APU_PLL4H_PLL3_CON3, + APU_PLL4H_PLL4_CON3, +}; + +uint32_t fhctl_dds_addr[APUPLL_MAX] = { + APU_PLL4H_FHCTL0_DDS, + APU_PLL4H_FHCTL1_DDS, + APU_PLL4H_FHCTL2_DDS, + APU_PLL4H_FHCTL3_DDS, +}; + +uint32_t fhctl_dvfs_addr[APUPLL_MAX] = { + APU_PLL4H_FHCTL0_DVFS, + APU_PLL4H_FHCTL1_DVFS, + APU_PLL4H_FHCTL2_DVFS, + APU_PLL4H_FHCTL3_DVFS, +}; + +uint32_t fhctl_mon_addr[APUPLL_MAX] = { + APU_PLL4H_FHCTL0_MON, + APU_PLL4H_FHCTL1_MON, + APU_PLL4H_FHCTL2_MON, + APU_PLL4H_FHCTL3_MON, +}; + +uint32_t fhctl_cfg_addr[APUPLL_MAX] = { + APU_PLL4H_FHCTL0_CFG, + APU_PLL4H_FHCTL1_CFG, + APU_PLL4H_FHCTL2_CFG, + APU_PLL4H_FHCTL3_CFG, +}; + +static spinlock_t apupll_lock; +static spinlock_t npupll_lock; +static spinlock_t apupll_1_lock; +static spinlock_t apupll_2_lock; +static uint32_t pll_cnt[APUPLL_MAX]; +/** + * vd2pllidx() - voltage domain to pll idx. + * @domain: the voltage domain for getting pll index. + * + * Caller will get correspond pll index by different voltage domain. + * pll_idx[0] --> APUPLL (MDLA0/1) + * pll_idx[1] --> NPUPLL (VPU0/1) + * pll_idx[2] --> APUPLL1(CONN) + * pll_idx[3] --> APUPLL2(IOMMU) + * The longer description may have multiple paragraphs. + * + * Context: Any context. + * Return: + * * 0 ~ 3 - return the corresponding pll index + * * -EEXIST - cannot find pll idex of the specific voltage domain + * + */ +static int32_t vd2pllidx(enum dvfs_voltage_domain domain) +{ + int32_t ret; + + switch (domain) { + case V_VPU0: + case V_VPU1: + ret = NPUPLL; + break; + case V_MDLA0: + case V_MDLA1: + ret = APUPLL; + break; + case V_TOP_IOMMU: + ret = APUPLL2; + break; + case V_APU_CONN: + ret = APUPLL1; + break; + default: + ERROR("%s wrong voltage domain: %d\n", __func__, domain); + ret = -EEXIST; /* non-exist */ + break; + } + + return ret; +} + +/** + * pllidx2name() - return names of specific pll index. + * @pll_idx: input for specific pll index. + * + * Given pll index, this function will return name of it. + * + * Context: Any context. + * Return: Names of pll_idx, if found, otherwise will return "NULL" + */ +static const char *pllidx2name(int32_t pll_idx) +{ + static const char *const names[] = { + [APUPLL] = "PLL4H_PLL1", + [NPUPLL] = "PLL4H_PLL2", + [APUPLL1] = "PLL4H_PLL3", + [APUPLL2] = "PLL4H_PLL4", + [APUPLL_MAX] = "NULL", + }; + + if (pll_idx >= APUPLL_MAX) { + pll_idx = APUPLL_MAX; + } + + return names[pll_idx]; +} + +/** + * _fhctl_mon_done() - poll whether fhctl HW mode is done. + * @pll_idx: input for specific pll index. + * @tar_dds: target dds for fhctl_mon to be. + * + * Given pll index, this function will continue to poll whether fhctl_mon + * has reached the expected value within 80us. + * + * Context: Any context. + * Return: + * * 0 - OK for fhctl_mon == tar_dds + * * -ETIMEDOUT - fhctl_mon not reach tar_dds + */ +static int32_t _fhctl_mon_done(uint32_t pll_idx, unsigned long tar_dds) +{ + unsigned long mon_dds; + uint64_t timeout = timeout_init_us(PLL_READY_TIME_20US); + int32_t ret = 0; + + tar_dds &= DDS_MASK; + do { + mon_dds = apupwr_readl(fhctl_mon_addr[pll_idx]) & DDS_MASK; + if (mon_dds == tar_dds) { + break; + } + + if (timeout_elapsed(timeout)) { + ERROR("%s monitor DDS 0x%08lx != expect 0x%08lx\n", + pllidx2name(pll_idx), mon_dds, tar_dds); + ret = -ETIMEDOUT; + break; + } + } while (mon_dds != tar_dds); + + return ret; +} + +/** + * _pll_get_postdiv_reg() - return current post dividor of pll_idx + * @pll_idx: input for specific pll index. + * + * Given pll index, this function will return its current post dividor. + * + * Context: Any context. + * Return: post dividor of current pll_idx. + * + */ +static uint32_t _pll_get_postdiv_reg(uint32_t pll_idx) +{ + int32_t pll_postdiv_reg = 0; + uint32_t val; + + val = apupwr_readl(mixed_con1_addr[pll_idx]); + pll_postdiv_reg = (val >> POSDIV_SHIFT) & POSDIV_MASK; + return pll_postdiv_reg; +} + +/** + * _set_postdiv_reg() - set pll_idx's post dividor. + * @pll_idx: Which PLL to enable/disable + * @post_div: the register value of post dividor to be wrtten. + * + * Below are lists of post dividor register value and its meaning: + * [31] APUPLL_SDM_PCW_CHG + * [26:24] APUPLL_POSDIV + * [21:0] APUPLL_SDM_PCW (8bit integer + 14bit fraction) + * expected freq range ----- divider-------post divider in reg: + * >1500M (1500/ 1) -> 1 -> 0(2 to the zero power) + * > 750M (1500/ 2) -> 2 -> 1(2 to the 1st power) + * > 375M (1500/ 4) -> 4 -> 2(2 to the 2nd power) + * > 187.5M (1500/ 8) -> 8 -> 3(2 to the 3rd power) + * > 93.75M (1500/16) -> 16 -> 4(2 to the 4th power) + * + * Context: Any context. + */ +static void _set_postdiv_reg(uint32_t pll_idx, uint32_t post_div) +{ + apupwr_clrbits(POSDIV_MASK << POSDIV_SHIFT, mixed_con1_addr[pll_idx]); + apupwr_setbits((post_div & POSDIV_MASK) << POSDIV_SHIFT, + mixed_con1_addr[pll_idx]); +} + +/** + * _cal_pll_data() - input freq, calculate correspond post dividor and dds. + * @pd: address of output post dividor. + * @dds: address of output dds. + * @freq: input frequency. + * + * Given freq, this function will calculate correspond post dividor and dds. + * + * Context: Any context. + * Return: + * * 0 - done for calculating post dividor and dds. + */ +static int32_t _cal_pll_data(uint32_t *pd, uint32_t *dds, uint32_t freq) +{ + uint32_t vco, postdiv_val = 1, postdiv_reg = 0; + uint32_t pcw_val; + + vco = freq; + postdiv_val = 1; + postdiv_reg = 0; + while (vco <= FREQ_VCO_MIN) { + postdiv_val = postdiv_val << 1; + postdiv_reg = postdiv_reg + 1; + vco = vco << 1; + } + + pcw_val = vco * (1 << PCW_FRACTIONAL_SHIFT); + pcw_val = pcw_val / FREQ_FIN; + + if (postdiv_reg == 0) { /* Fvco * 2 with post_divider = 2 */ + pcw_val = pcw_val * 2; + postdiv_val = postdiv_val << 1; + postdiv_reg = postdiv_reg + 1; + } /* Post divider is 1 is not available */ + *pd = postdiv_reg; + *dds = pcw_val | RG_PLL_SDM_PCW_CHG; + + return 0; +} + +/** + * _pll_en() - enable/disable RG_PLL_EN of CON1 for pll[pll_idx] + * @pll_idx: Which PLL to enable/disable + * @on: 1 -> enable, 0 -> disable. + * + * This funciton will only change RG_PLL_EN of CON1 for pll[pll_idx]. + * + * Context: Any context. + */ +static void _pll_en(uint32_t pll_idx, bool on) +{ + if (on) { + apupwr_setbits(RG_PLL_EN, mixed_con0_addr[pll_idx]); + } else { + apupwr_clrbits(RG_PLL_EN, mixed_con0_addr[pll_idx]); + } +} + +/** + * _pll_pwr() - enable/disable PLL_SDM_PWR_ON of CON3 for pll[pll_idx] + * @pll_idx: Which PLL to enable/disable + * @on: 1 -> enable, 0 -> disable. + * + * This funciton will only change PLL_SDM_PWR_ON of CON3 for pll[pll_idx]. + * + * Context: Any context. + */ +static void _pll_pwr(uint32_t pll_idx, bool on) +{ + if (on) { + apupwr_setbits(DA_PLL_SDM_PWR_ON, mixed_con3_addr[pll_idx]); + } else { + apupwr_clrbits(DA_PLL_SDM_PWR_ON, mixed_con3_addr[pll_idx]); + } +} + +/** + * _pll_iso() - enable/disable PLL_SDM_ISO_EN of CON3 for pll[pll_idx] + * @pll_idx: Which PLL to enable/disable + * @enable: 1 -> turn on isolation, 0 -> turn off isolation. + * + * This funciton will turn on/off pll isolation by + * changing PLL_SDM_PWR_ON of CON3 for pll[pll_idx]. + * + * Context: Any context. + */ +static void _pll_iso(uint32_t pll_idx, bool enable) +{ + if (enable) { + apupwr_setbits(DA_PLL_SDM_ISO_EN, mixed_con3_addr[pll_idx]); + } else { + apupwr_clrbits(DA_PLL_SDM_ISO_EN, mixed_con3_addr[pll_idx]); + } +} + +/** + * _pll_switch() - entry point to turn whole PLL on/off + * @pll_idx: Which PLL to enable/disable + * @on: 1 -> enable, 0 -> disable. + * @fhctl_en: enable or disable fhctl function + * + * This is the entry poing for controlling pll and fhctl funciton on/off. + * Caller can chose only enable pll instead of fhctl function. + * + * Context: Any context. + * Return: + * * 0 - done for enable pll or fhctl as well. + */ +static int32_t _pll_switch(uint32_t pll_idx, bool on, bool fhctl_en) +{ + int32_t ret = 0; + + if (pll_idx >= APUPLL_MAX) { + ERROR("%s wrong pll_idx: %d\n", __func__, pll_idx); + ret = -EINVAL; + goto err; + } + + if (on) { + _pll_pwr(pll_idx, true); + udelay(PLL_CMD_READY_TIME_1US); + _pll_iso(pll_idx, false); + udelay(PLL_CMD_READY_TIME_1US); + _pll_en(pll_idx, true); + udelay(PLL_READY_TIME_20US); + } else { + _pll_en(pll_idx, false); + _pll_iso(pll_idx, true); + _pll_pwr(pll_idx, false); + } + +err: + return ret; +} + +/** + * apu_pll_enable() - API for smc function to enable/disable pll + * @pll_idx: Which pll to enable/disable. + * @enable: 1 -> enable, 0 -> disable. + * @fhctl_en: enable or disable fhctl function + * + * pll_idx[0] --> APUPLL (MDLA0/1) + * pll_idx[1] --> NPUPLL (VPU0/1) + * pll_idx[2] --> APUPLL1(CONN) + * pll_idx[3] --> APUPLL2(IOMMU) + * The differences between _pll_switch are: + * 1. Atomic update pll reference cnt to protect double enable pll & + * close pll during user is not zero. + * + * Context: Any context. + * Return: + * * 0 - done for enable pll or fhctl as well. + */ +int32_t apu_pll_enable(int32_t pll_idx, bool enable, bool fhctl_en) +{ + int32_t ret = 0; + + if (pll_idx >= APUPLL_MAX) { + ERROR("%s wrong pll_idx: %d\n", __func__, pll_idx); + ret = -EINVAL; + goto err; + } + + if (enable) { + switch (pll_idx) { + case APUPLL: + spin_lock(&apupll_lock); + if (pll_cnt[APUPLL] == 0) { + _pll_switch(pll_idx, enable, fhctl_en); + } + pll_cnt[APUPLL]++; + spin_unlock(&apupll_lock); + break; + case NPUPLL: + spin_lock(&npupll_lock); + if (pll_cnt[NPUPLL] == 0) { + _pll_switch(pll_idx, enable, fhctl_en); + } + pll_cnt[NPUPLL]++; + spin_unlock(&npupll_lock); + break; + case APUPLL1: + spin_lock(&apupll_1_lock); + if (pll_cnt[APUPLL1] == 0) { + _pll_switch(pll_idx, enable, fhctl_en); + } + pll_cnt[APUPLL1]++; + spin_unlock(&apupll_1_lock); + break; + case APUPLL2: + spin_lock(&apupll_2_lock); + if (pll_cnt[APUPLL2] == 0) { + _pll_switch(pll_idx, enable, fhctl_en); + } + pll_cnt[APUPLL2]++; + spin_unlock(&apupll_2_lock); + break; + default: + ERROR("%s invalid pll_idx: %d\n", __func__, pll_idx); + ret = -EINVAL; + break; + } + } else { + switch (pll_idx) { + case APUPLL: + spin_lock(&apupll_lock); + if (pll_cnt[APUPLL]) { + pll_cnt[APUPLL]--; + } + if (pll_cnt[APUPLL] == 0) { + _pll_switch(pll_idx, enable, fhctl_en); + } + spin_unlock(&apupll_lock); + break; + case NPUPLL: + spin_lock(&npupll_lock); + if (pll_cnt[NPUPLL]) { + pll_cnt[NPUPLL]--; + } + if (pll_cnt[NPUPLL] == 0) { + _pll_switch(pll_idx, enable, fhctl_en); + } + spin_unlock(&npupll_lock); + break; + case APUPLL1: + spin_lock(&apupll_1_lock); + if (pll_cnt[APUPLL1]) { + pll_cnt[APUPLL1]--; + } + if (pll_cnt[APUPLL1] == 0) { + _pll_switch(pll_idx, enable, fhctl_en); + } + spin_unlock(&apupll_1_lock); + break; + case APUPLL2: + spin_lock(&apupll_2_lock); + if (pll_cnt[APUPLL2]) { + pll_cnt[APUPLL2]--; + } + if (pll_cnt[APUPLL2] == 0) { + _pll_switch(pll_idx, enable, fhctl_en); + } + spin_unlock(&apupll_2_lock); + break; + default: + ERROR("%s invalid pll_idx: %d\n", __func__, pll_idx); + ret = -EINVAL; + break; + } + } + +err: + return ret; +} + +/** + * anpu_pll_set_rate() - API for smc function to set rate of voltage domain. + * @domain: Which pll of correspond voltage domain to change rate. + * @mode: which mode to use when set_rate + * @freq: which frequency to set. + * + * For V_VPU0/1, it will only allow 1 of them to modify NPUPLL + * such that there will be no race condition happen. + * + * For V_MDLA0/1, it will only allow 1 of them to modify APUPLL1 + * such that there will be no race condition happen. + * + * There are 3 kinds of modes to set pll's rate. + * 1. pure sw mode: (CON0_PCW) + * fhctl function is off and change rate by programming CON1_PCW. + * 2. fhctl sw mode: (FHCTL_SW) + * fhctl function is on and change rate by programming fhctl_dds. + * (post dividor is still need to program CON1_PCW) + * 3. fhctl hw mode: (FHCTL_HW) + * fhctl function is on and change rate by programming fhctl_dvfs. + * (post dividor is still need to program CON1_PCW) + * + * Context: Any context. + * Return: + * * 0 - done for set rate of voltage domain. + */ +int32_t anpu_pll_set_rate(enum dvfs_voltage_domain domain, + enum pll_set_rate_mode mode, int32_t freq) +{ + uint32_t pd, old_pd, dds; + int32_t pll_idx, ret = 0; + + pll_idx = vd2pllidx(domain); + if (pll_idx < 0) { + ret = pll_idx; + goto err; + } + + _cal_pll_data(&pd, &dds, freq / 1000); + + INFO("%s %s new post_div=%d, target dds=0x%08x(%dMhz) mode = %d\n", + __func__, pllidx2name(pll_idx), pd, dds, freq / 1000, mode); + + /* spin_lock for NPULL, since vpu0/1 share npupll */ + if (domain == V_VPU0 || domain == V_VPU1) { + spin_lock(&npupll_lock); + } + + /* spin_lock for APUPLL, since mdla0/1 shate apupll */ + if (domain == V_MDLA0 || domain == V_MDLA1) { + spin_lock(&apupll_lock); + } + + switch (mode) { + case CON0_PCW: + pd = RG_PLL_SDM_PCW_CHG | + (pd & POSDIV_MASK) << POSDIV_SHIFT | dds; + apupwr_writel(pd, mixed_con1_addr[pll_idx]); + udelay(PLL_READY_TIME_20US); + break; + case FHCTL_SW: + /* pll con0 disable */ + _pll_en(pll_idx, false); + apupwr_writel(dds, fhctl_dds_addr[pll_idx]); + _set_postdiv_reg(pll_idx, pd); + apupwr_setbits(PLL_TGL_ORG, fhctl_dds_addr[pll_idx]); + udelay(PLL_CMD_READY_TIME_1US); + /* pll con0 enable */ + _pll_en(pll_idx, true); + udelay(PLL_READY_TIME_20US); + break; + case FHCTL_HW: + old_pd = _pll_get_postdiv_reg(pll_idx); + if (pd > old_pd) { + _set_postdiv_reg(pll_idx, pd); + apupwr_writel(dds, fhctl_dvfs_addr[pll_idx]); + } else { + apupwr_writel(dds, fhctl_dvfs_addr[pll_idx]); + _set_postdiv_reg(pll_idx, pd); + } + ret = _fhctl_mon_done(pll_idx, dds); + break; + default: + ERROR("%s input wrong mode: %d\n", __func__, mode); + ret = -EINVAL; + break; + } + + /* spin_lock for NPULL, since vpu0/1 share npupll */ + if (domain == V_VPU0 || domain == V_VPU1) { + spin_unlock(&npupll_lock); + } + + /* spin_lock for APUPLL, since mdla0/1 share apupll */ + if (domain == V_MDLA0 || domain == V_MDLA1) { + spin_unlock(&apupll_lock); + } + +err: + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c new file mode 100644 index 0000000..465054d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* 8195 use PCW mode to change freq directly */ +enum pll_set_rate_mode PLL_MODE = CON0_PCW; + +char *buck_domain_str[APUSYS_BUCK_DOMAIN_NUM] = { + "V_VPU0", + "V_VPU1", + "V_MDLA0", + "V_MDLA1", + "V_APU_CONN", + "V_TOP_IOMMU", + "V_VCORE", +}; + +uint32_t aacc_set[APUSYS_BUCK_DOMAIN_NUM] = { + APU_ACC_CONFG_SET1, APU_ACC_CONFG_SET2, + APU_ACC_CONFG_SET4, APU_ACC_CONFG_SET5, + APU_ACC_CONFG_SET0, APU_ACC_CONFG_SET7 +}; + +uint32_t aacc_clr[APUSYS_BUCK_DOMAIN_NUM] = { + APU_ACC_CONFG_CLR1, APU_ACC_CONFG_CLR2, + APU_ACC_CONFG_CLR4, APU_ACC_CONFG_CLR5, + APU_ACC_CONFG_CLR0, APU_ACC_CONFG_CLR7 +}; + +struct reg_seq { + uint32_t address; + uint32_t val; +}; + +static const struct reg_seq init_acc_cfg[] = { + { APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU) }, + { APU_ACC_CONFG_CLR0, BIT(BIT_CGEN_SOC) }, + { APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU_DIV2) }, + { APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU) }, + { APU_ACC_CONFG_CLR7, BIT(BIT_CGEN_SOC) }, + { APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU_DIV2) }, + { APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU) }, + { APU_ACC_CONFG_CLR1, BIT(BIT_CGEN_SOC) }, + { APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU_DIV2) }, + { APU_ACC_CONFG_SET2, BIT(BIT_INVEN_OUT) }, + { APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU) }, + { APU_ACC_CONFG_CLR2, BIT(BIT_CGEN_SOC) }, + { APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU_DIV2) }, + { APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU) }, + { APU_ACC_CONFG_CLR4, BIT(BIT_CGEN_SOC) }, + { APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU_DIV2) }, + { APU_ACC_CONFG_SET5, BIT(BIT_INVEN_OUT) }, + { APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU) }, + { APU_ACC_CONFG_CLR5, BIT(BIT_CGEN_SOC) }, + { APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU_DIV2) }, +}; + +int32_t apupwr_smc_acc_init_all(void) +{ + int32_t i; + + for (i = 0; i < ARRAY_SIZE(init_acc_cfg); i++) { + apupwr_writel(init_acc_cfg[i].val, + init_acc_cfg[i].address); + } + + /* Deault ACC will raise APU_DIV_2 */ + apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ, + true, V_APU_CONN); + + apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ, + true, V_TOP_IOMMU); + + apupwr_smc_pll_set_rate(BUCK_VVPU_DOMAIN_DEFAULT_FREQ, + true, V_VPU0); + + apupwr_smc_pll_set_rate(BUCK_VMDLA_DOMAIN_DEFAULT_FREQ, + true, V_MDLA0); + + return 0; +} + +void apupwr_smc_acc_top(bool enable) +{ + if (enable) { + apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_APU_CONN]); + apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_TOP_IOMMU]); + } else { + apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_APU_CONN]); + apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_TOP_IOMMU]); + } +} + +/* + * acc_clk_set_parent:ACC MUX select + * 0. freq parameters here, only ACC clksrc is valid + * 1. Switch between APUPLL <=> Parking (F26M, PARK) + * 2. Turn on/off CG_F26M, CG_PARK, CG_SOC, but no CG_APU + * 3. Clear APU Div2 while Parking + * 4. Only use clksrc of APUPLL while ACC CG_APU is on + */ +int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain) +{ + uint32_t acc_set = 0; + uint32_t acc_clr = 0; + int32_t ret = 0; + + if (freq > DVFS_FREQ_ACC_APUPLL) { + ERROR("%s wrong clksrc: %d\n", __func__, freq); + ret = -EIO; + goto err; + } + + switch (domain) { + case V_VPU1: + case V_VPU0: + case V_MDLA1: + case V_MDLA0: + case V_APU_CONN: + case V_TOP_IOMMU: + acc_set = aacc_set[domain]; + acc_clr = aacc_clr[domain]; + break; + default: + ret = -EIO; + break; + } + + /* Select park source */ + switch (freq) { + case DVFS_FREQ_ACC_PARKING: + /* Select park source */ + apupwr_writel(BIT(BIT_SEL_PARK), acc_set); + apupwr_writel(BIT(BIT_SEL_F26M), acc_clr); + /* Enable park cg */ + apupwr_writel(BIT(BIT_CGEN_PARK), acc_set); + apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_SOC), acc_clr); + /* Select park path */ + apupwr_writel(BIT(BIT_SEL_APU), acc_clr); + /* clear apu div 2 */ + apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr); + break; + + case DVFS_FREQ_ACC_APUPLL: + /* Select park path */ + apupwr_writel(BIT(BIT_SEL_APU), acc_set); + /* Clear park cg */ + apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_F26M) | + BIT(BIT_CGEN_SOC), acc_clr); + break; + + case DVFS_FREQ_ACC_SOC: + /* Select park source */ + apupwr_writel(BIT(BIT_SEL_PARK), acc_clr); + apupwr_writel(BIT(BIT_SEL_F26M), acc_clr); + /* Enable park cg */ + apupwr_writel(BIT(BIT_CGEN_SOC), acc_set); + apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_PARK), acc_clr); + /* Select park path */ + apupwr_writel(BIT(BIT_SEL_APU), acc_clr); + /* clear apu div 2 */ + apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr); + break; + + case DVFS_FREQ_ACC_26M: + case DVFS_FREQ_NOT_SUPPORT: + default: + /* Select park source */ + apupwr_writel(BIT(BIT_SEL_F26M), acc_set); + apupwr_writel(BIT(BIT_SEL_PARK), acc_clr); + /* Enable park cg */ + apupwr_writel(BIT(BIT_CGEN_F26M), acc_set); + apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_SOC), acc_clr); + /* Select park path */ + apupwr_writel(BIT(BIT_SEL_APU), acc_clr); + /* clear apu div 2 */ + apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr); + ERROR("[APUPWR] %s wrong ACC clksrc : %d, force assign 26M\n", + __func__, freq); + break; + } + +err: + return ret; +} + +int32_t apupwr_smc_pll_set_rate(uint32_t freq, bool div2, uint32_t domain) +{ + int32_t ret = 0; + uint32_t acc_set0 = 0, acc_set1 = 0; + + if (freq > DVFS_FREQ_MAX) { + ERROR("%s wrong freq: %d\n", __func__, freq); + ret = -EIO; + goto err; + } + + /* + * Switch to Parking src + * 1. Need to switch out all ACCs sharing the same apupll + */ + switch (domain) { + case V_MDLA0: + case V_MDLA1: + acc_set0 = APU_ACC_CONFG_SET4; + acc_set1 = APU_ACC_CONFG_SET5; + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, + V_MDLA0); + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, + V_MDLA1); + break; + case V_VPU0: + case V_VPU1: + acc_set0 = APU_ACC_CONFG_SET1; + acc_set1 = APU_ACC_CONFG_SET2; + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, + V_VPU0); + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, + V_VPU1); + break; + case V_APU_CONN: + acc_set0 = APU_ACC_CONFG_SET0; + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, + V_APU_CONN); + break; + case V_TOP_IOMMU: + acc_set0 = APU_ACC_CONFG_SET7; + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING, + V_TOP_IOMMU); + break; + default: + ERROR("[APUPWR] %s %d invalid domain (%d)\n", + __func__, __LINE__, domain); + ret = -EIO; + goto err; + } + + anpu_pll_set_rate(domain, PLL_MODE, (div2) ? (freq * 2) : freq); + + if (div2) { + apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set0); + if (acc_set1) { + apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set1); + } + } + + /* + * Switch back to APUPLL + * Only switch back to APUPLL while CG_APU on + * And clksrc is not APUPLL + */ + switch (domain) { + case V_VPU0: + case V_VPU1: + if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) && + !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) { + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, + V_VPU0); + } + if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) && + !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) { + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, + V_VPU1); + } + break; + case V_MDLA0: + case V_MDLA1: + if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) && + !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) { + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, + V_MDLA0); + } + if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) && + !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) { + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, + V_MDLA1); + } + break; + case V_APU_CONN: + case V_TOP_IOMMU: + if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) && + !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) { + ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL, + domain); + } + break; + default: + ERROR("[APUPWR] %s %d invalid domain (%d)\n", + __func__, __LINE__, domain); + ret = -EIO; + break; + } + INFO("[%s][%d] set domain %d to freq %d\n", + __func__, __LINE__, domain, (div2) ? (freq * 2) : freq); + +err: + return ret; +} + +int32_t apupwr_smc_bulk_pll(bool enable) +{ + int32_t ret = 0; + int32_t pll_idx; + + if (enable) { + for (pll_idx = APUPLL; pll_idx < APUPLL_MAX; pll_idx++) { + ret = apu_pll_enable(pll_idx, enable, false); + if (ret != 0) { + goto err; + } + } + } else { + for (pll_idx = APUPLL2; pll_idx >= APUPLL; pll_idx--) { + ret = apu_pll_enable(pll_idx, enable, false); + if (ret != 0) { + goto err; + } + } + } + +err: + return ret; +} + +void apupwr_smc_bus_prot_cg_on(void) +{ + apupwr_clrbits(AO_MD32_MNOC_MASK, APU_CSR_DUMMY_0); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h new file mode 100644 index 0000000..3b27c1b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef APUPWR_CLKCTL_H +#define APUPWR_CLKCTL_H + +#include +#include + +int32_t apupwr_smc_acc_init_all(void); +void apupwr_smc_acc_top(bool enable); +int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain); +int32_t apupwr_smc_pll_set_rate(uint32_t pll, bool div2, uint32_t domain); +int32_t apupwr_smc_bulk_pll(bool enable); +void apupwr_smc_bus_prot_cg_on(void); + +int32_t apu_pll_enable(int32_t pll_idx, bool enable, bool fhctl_en); +int32_t anpu_pll_set_rate(enum dvfs_voltage_domain domain, + enum pll_set_rate_mode mode, int32_t freq); +#endif /* APUPWR_CLKCTL_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h new file mode 100644 index 0000000..6663ad9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef APUPWR_CLKCTL_DEF_H +#define APUPWR_CLKCTL_DEF_H + +#include + +enum dvfs_voltage_domain { + V_VPU0 = 0, + V_VPU1 = 1, + V_MDLA0 = 2, + V_MDLA1 = 3, + V_APU_CONN = 4, + V_TOP_IOMMU = 5, + V_VCORE = 6, + APUSYS_BUCK_DOMAIN_NUM = 7, +}; + +enum dvfs_freq { + DVFS_FREQ_NOT_SUPPORT = 0, + DVFS_FREQ_ACC_26M = 1, + DVFS_FREQ_ACC_PARKING = 2, + DVFS_FREQ_ACC_SOC = 3, + DVFS_FREQ_ACC_APUPLL = 4, + DVFS_FREQ_00_026000_F = 26000, + DVFS_FREQ_00_208000_F = 208000, + DVFS_FREQ_00_238000_F = 238000, + DVFS_FREQ_00_273000_F = 273000, + DVFS_FREQ_00_312000_F = 312000, + DVFS_FREQ_00_358000_F = 358000, + DVFS_FREQ_00_385000_F = 385000, + DVFS_FREQ_00_499200_F = 499200, + DVFS_FREQ_00_500000_F = 500000, + DVFS_FREQ_00_525000_F = 525000, + DVFS_FREQ_00_546000_F = 546000, + DVFS_FREQ_00_594000_F = 594000, + DVFS_FREQ_00_624000_F = 624000, + DVFS_FREQ_00_688000_F = 688000, + DVFS_FREQ_00_687500_F = 687500, + DVFS_FREQ_00_728000_F = 728000, + DVFS_FREQ_00_800000_F = 800000, + DVFS_FREQ_00_832000_F = 832000, + DVFS_FREQ_00_960000_F = 960000, + DVFS_FREQ_00_1100000_F = 1100000, +}; +#define DVFS_FREQ_MAX (DVFS_FREQ_00_1100000_F) + +enum pll_set_rate_mode { + CON0_PCW = 0, + FHCTL_SW = 1, + FHCTL_HW = 2, + PLL_SET_RATE_MODE_MAX = 3, +}; + +enum apupll { + APUPLL = 0, + NPUPLL = 1, + APUPLL1 = 2, + APUPLL2 = 3, + APUPLL_MAX = 4, +}; + +#define BUCK_VVPU_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_273000_F) +#define BUCK_VMDLA_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_312000_F) +#define BUCK_VCONN_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_208000_F) + +#define apupwr_writel(VAL, REG) mmio_write_32((uintptr_t)REG, VAL) +#define apupwr_writel_relax(VAL, REG) mmio_write_32_relax((uintptr_t)REG, VAL) +#define apupwr_readl(REG) mmio_read_32((uintptr_t)REG) +#define apupwr_clrbits(VAL, REG) mmio_clrbits_32((uintptr_t)REG, VAL) +#define apupwr_setbits(VAL, REG) mmio_setbits_32((uintptr_t)REG, VAL) +#define apupwr_clrsetbits(CLR_VAL, SET_VAL, REG) \ + mmio_clrsetbits_32((uintptr_t)REG, CLR_VAL, SET_VAL) + +/* PLL and related register */ +#define APU_PLL_BASE (APUSYS_APU_PLL_BASE) +#define APU_PLL4H_PLL1_CON0 (APU_PLL_BASE + 0x008) +#define APU_PLL4H_PLL1_CON1 (APU_PLL_BASE + 0x00C) +#define APU_PLL4H_PLL1_CON3 (APU_PLL_BASE + 0x014) + +#define APU_PLL4H_PLL2_CON0 (APU_PLL_BASE + 0x018) +#define APU_PLL4H_PLL2_CON1 (APU_PLL_BASE + 0x01C) +#define APU_PLL4H_PLL2_CON3 (APU_PLL_BASE + 0x024) + +#define APU_PLL4H_PLL3_CON0 (APU_PLL_BASE + 0x028) +#define APU_PLL4H_PLL3_CON1 (APU_PLL_BASE + 0x02C) +#define APU_PLL4H_PLL3_CON3 (APU_PLL_BASE + 0x034) + +#define APU_PLL4H_PLL4_CON0 (APU_PLL_BASE + 0x038) +#define APU_PLL4H_PLL4_CON1 (APU_PLL_BASE + 0x03C) +#define APU_PLL4H_PLL4_CON3 (APU_PLL_BASE + 0x044) + +#define APU_PLL4H_FHCTL_HP_EN (APU_PLL_BASE + 0x0E00) +#define APU_PLL4H_FHCTL_UNITSLOPE_EN (APU_PLL_BASE + 0x0E04) +#define APU_PLL4H_FHCTL_CLK_CON (APU_PLL_BASE + 0x0E08) +#define APU_PLL4H_FHCTL_RST_CON (APU_PLL_BASE + 0x0E0C) +#define APU_PLL4H_FHCTL_SLOPE0 (APU_PLL_BASE + 0x0E10) +#define APU_PLL4H_FHCTL_SLOPE1 (APU_PLL_BASE + 0x0E14) +#define APU_PLL4H_FHCTL_DSSC_CFG (APU_PLL_BASE + 0x0E18) +#define APU_PLL4H_FHCTL_DSSC0_CON (APU_PLL_BASE + 0x0E1C) +#define APU_PLL4H_FHCTL_DSSC1_CON (APU_PLL_BASE + 0x0E20) +#define APU_PLL4H_FHCTL_DSSC2_CON (APU_PLL_BASE + 0x0E24) +#define APU_PLL4H_FHCTL_DSSC3_CON (APU_PLL_BASE + 0x0E28) +#define APU_PLL4H_FHCTL_DSSC4_CON (APU_PLL_BASE + 0x0E2C) +#define APU_PLL4H_FHCTL_DSSC5_CON (APU_PLL_BASE + 0x0E30) +#define APU_PLL4H_FHCTL_DSSC6_CON (APU_PLL_BASE + 0x0E34) +#define APU_PLL4H_FHCTL_DSSC7_CON (APU_PLL_BASE + 0x0E38) +#define APU_PLL4H_FHCTL0_CFG (APU_PLL_BASE + 0x0E3C) +#define APU_PLL4H_FHCTL0_UPDNLMT (APU_PLL_BASE + 0x0E40) +#define APU_PLL4H_FHCTL0_DDS (APU_PLL_BASE + 0x0E44) +#define APU_PLL4H_FHCTL0_DVFS (APU_PLL_BASE + 0x0E48) +#define APU_PLL4H_FHCTL0_MON (APU_PLL_BASE + 0x0E4C) +#define APU_PLL4H_FHCTL1_CFG (APU_PLL_BASE + 0x0E50) +#define APU_PLL4H_FHCTL1_UPDNLMT (APU_PLL_BASE + 0x0E54) +#define APU_PLL4H_FHCTL1_DDS (APU_PLL_BASE + 0x0E58) +#define APU_PLL4H_FHCTL1_DVFS (APU_PLL_BASE + 0x0E5C) +#define APU_PLL4H_FHCTL1_MON (APU_PLL_BASE + 0x0E60) +#define APU_PLL4H_FHCTL2_CFG (APU_PLL_BASE + 0x0E64) +#define APU_PLL4H_FHCTL2_UPDNLMT (APU_PLL_BASE + 0x0E68) +#define APU_PLL4H_FHCTL2_DDS (APU_PLL_BASE + 0x0E6C) +#define APU_PLL4H_FHCTL2_DVFS (APU_PLL_BASE + 0x0E70) +#define APU_PLL4H_FHCTL2_MON (APU_PLL_BASE + 0x0E74) +#define APU_PLL4H_FHCTL3_CFG (APU_PLL_BASE + 0x0E78) +#define APU_PLL4H_FHCTL3_UPDNLMT (APU_PLL_BASE + 0x0E7C) +#define APU_PLL4H_FHCTL3_DDS (APU_PLL_BASE + 0x0E80) +#define APU_PLL4H_FHCTL3_DVFS (APU_PLL_BASE + 0x0E84) +#define APU_PLL4H_FHCTL3_MON (APU_PLL_BASE + 0x0E88) + +/* PLL4H_PLLx_CON0 */ +#define RG_PLL_EN BIT(0) + +/* PLL4H_PLLx_CON1 */ +#define RG_PLL_SDM_PCW_CHG BIT(31) +#define POSDIV_SHIFT (24U) +#define POSDIV_MASK (0x7) + +/* PLL4H_PLLx_CON3 */ +#define DA_PLL_SDM_PWR_ON BIT(0) +#define DA_PLL_SDM_ISO_EN BIT(1) + +/* FHCTLx_DDS */ +#define DDS_MASK GENMASK_32(21, 0) +#define PCW_FRACTIONAL_SHIFT 14U +#define PLL_TGL_ORG BIT(31) + +#define PLL_READY_TIME_20US (20U) +#define PLL_CMD_READY_TIME_1US (1U) + +#define FREQ_VCO_MIN (1500U) /* 1500MHz*/ +#define FREQ_FIN (26U) /* 26M*/ + +/* ACC and related register */ +#define APU_ACC_BASE (APUSYS_APU_ACC_BASE) +#define APU_ACC_CONFG_SET0 (APU_ACC_BASE + 0x000) +#define APU_ACC_CONFG_SET1 (APU_ACC_BASE + 0x004) +#define APU_ACC_CONFG_SET2 (APU_ACC_BASE + 0x008) +#define APU_ACC_CONFG_SET4 (APU_ACC_BASE + 0x010) +#define APU_ACC_CONFG_SET5 (APU_ACC_BASE + 0x014) +#define APU_ACC_CONFG_SET7 (APU_ACC_BASE + 0x01C) + +#define APU_ACC_CONFG_CLR0 (APU_ACC_BASE + 0x040) +#define APU_ACC_CONFG_CLR1 (APU_ACC_BASE + 0x044) +#define APU_ACC_CONFG_CLR2 (APU_ACC_BASE + 0x048) +#define APU_ACC_CONFG_CLR4 (APU_ACC_BASE + 0x050) +#define APU_ACC_CONFG_CLR5 (APU_ACC_BASE + 0x054) +#define APU_ACC_CONFG_CLR7 (APU_ACC_BASE + 0x05C) + +#define APU_ACC_FM_CONFG_SET (APU_ACC_BASE + 0x0C0) +#define APU_ACC_FM_CONFG_CLR (APU_ACC_BASE + 0x0C4) +#define APU_ACC_FM_SEL (APU_ACC_BASE + 0x0C8) +#define APU_ACC_FM_CNT (APU_ACC_BASE + 0x0CC) + +/* APU AO control */ +#define APU_AO_CTRL_BASE (APUSYS_APU_S_S_4_BASE) +#define APU_CSR_DUMMY_0 (APU_AO_CTRL_BASE + 0x24) + +#define AO_MD32_MNOC_MASK (BIT(1) | BIT(0)) + +#define BIT_CGEN_F26M (0) +#define BIT_CGEN_PARK (1) +#define BIT_CGEN_SOC (2) +#define BIT_CGEN_APU (3) +#define BIT_CGEN_OUT (4) +#define BIT_SEL_PARK (8) +#define BIT_SEL_F26M (9) +#define BIT_SEL_APU_DIV2 (10) +#define BIT_SEL_APU (11) +#define BIT_SEL_PARK_SRC_OUT (12) +#define BIT_INVEN_OUT (15) + +#endif /* APUPWR_CLKCTL_DEF_H*/ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c new file mode 100644 index 0000000..3ed26a1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +int32_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, + uint32_t *ret1) +{ + int32_t ret = 0L; + uint32_t request_ops; + + request_ops = (uint32_t)x1; + + switch (request_ops) { + case MTK_SIP_APU_START_MCU: + /* setup addr[33:32] in reviser */ + mmio_write_32(REVISER_SECUREFW_CTXT, 0U); + mmio_write_32(REVISER_USDRFW_CTXT, 0U); + + /* setup secure sideband */ + mmio_write_32(AO_SEC_FW, + (SEC_FW_NON_SECURE << SEC_FW_SHIFT_NS) | + (0U << SEC_FW_DOMAIN_SHIFT)); + + /* setup boot address */ + mmio_write_32(AO_MD32_BOOT_CTRL, 0U); + + /* setup pre-define region */ + mmio_write_32(AO_MD32_PRE_DEFINE, + (PRE_DEFINE_CACHE_TCM << PRE_DEFINE_SHIFT_0G) | + (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_1G) | + (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_2G) | + (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_3G)); + + /* release runstall */ + mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_RUN); + + INFO("[APUSYS] rev(0x%08x,0x%08x)\n", + mmio_read_32(REVISER_SECUREFW_CTXT), + mmio_read_32(REVISER_USDRFW_CTXT)); + INFO("[APUSYS] ao(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x)\n", + mmio_read_32(AO_SEC_FW), + mmio_read_32(AO_SEC_USR_FW), + mmio_read_32(AO_MD32_BOOT_CTRL), + mmio_read_32(AO_MD32_PRE_DEFINE), + mmio_read_32(AO_MD32_SYS_CTRL)); + break; + case MTK_SIP_APU_STOP_MCU: + /* hold runstall */ + mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_STALL); + + INFO("[APUSYS] md32_boot_ctrl=0x%08x,runstall=0x%08x\n", + mmio_read_32(AO_MD32_BOOT_CTRL), + mmio_read_32(AO_MD32_SYS_CTRL)); + break; + case MTK_SIP_APUPWR_BUS_PROT_CG_ON: + apupwr_smc_bus_prot_cg_on(); + break; + case MTK_SIP_APUPWR_BULK_PLL: + ret = apupwr_smc_bulk_pll((bool)x2); + break; + case MTK_SIP_APUPWR_ACC_INIT_ALL: + ret = apupwr_smc_acc_init_all(); + break; + case MTK_SIP_APUPWR_ACC_TOP: + apupwr_smc_acc_top((bool)x2); + break; + default: + ERROR("%s, unknown request_ops=0x%x\n", __func__, request_ops); + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h new file mode 100644 index 0000000..639abd3 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_APUSYS_H +#define MTK_APUSYS_H + +#include + +/* setup the SMC command ops */ +#define MTK_SIP_APU_START_MCU (0x00U) +#define MTK_SIP_APU_STOP_MCU (0x01U) +#define MTK_SIP_APUPWR_BUS_PROT_CG_ON (0x02U) +#define MTK_SIP_APUPWR_BULK_PLL (0x03U) +#define MTK_SIP_APUPWR_ACC_INIT_ALL (0x04U) +#define MTK_SIP_APUPWR_ACC_TOP (0x05U) + +/* AO Register */ +#define AO_MD32_PRE_DEFINE (APUSYS_APU_S_S_4_BASE + 0x00) +#define AO_MD32_BOOT_CTRL (APUSYS_APU_S_S_4_BASE + 0x04) +#define AO_MD32_SYS_CTRL (APUSYS_APU_S_S_4_BASE + 0x08) +#define AO_SEC_FW (APUSYS_APU_S_S_4_BASE + 0x10) +#define AO_SEC_USR_FW (APUSYS_APU_S_S_4_BASE + 0x14) + +#define PRE_DEFINE_CACHE_TCM (0x3U) +#define PRE_DEFINE_CACHE (0x2U) +#define PRE_DEFINE_SHIFT_0G (0U) +#define PRE_DEFINE_SHIFT_1G (2U) +#define PRE_DEFINE_SHIFT_2G (4U) +#define PRE_DEFINE_SHIFT_3G (6U) + +#define SEC_FW_NON_SECURE (1U) +#define SEC_FW_SHIFT_NS (4U) +#define SEC_FW_DOMAIN_SHIFT (0U) + +#define SEC_USR_FW_NON_SECURE (1U) +#define SEC_USR_FW_SHIFT_NS (4U) +#define SEC_USR_FW_DOMAIN_SHIFT (0U) + +#define SYS_CTRL_RUN (0U) +#define SYS_CTRL_STALL (1U) + +/* Reviser Register */ +#define REVISER_SECUREFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x100) +#define REVISER_USDRFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x104) + +int32_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, + uint32_t *ret1); +#endif /* MTK_APUSYS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c new file mode 100644 index 0000000..aed0833 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +static void dcm_armcore(bool mode) +{ + dcm_mp_cpusys_top_bus_pll_div_dcm(mode); + dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode); + dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode); +} + +static void dcm_mcusys(bool on) +{ + dcm_mp_cpusys_top_adb_dcm(on); + dcm_mp_cpusys_top_apb_dcm(on); + dcm_mp_cpusys_top_cpubiu_dcm(on); + dcm_mp_cpusys_top_misc_dcm(on); + dcm_mp_cpusys_top_mp0_qdcm(on); + dcm_cpccfg_reg_emi_wfifo(on); + dcm_mp_cpusys_top_last_cor_idle_dcm(on); +} + +static void dcm_stall(bool on) +{ + dcm_mp_cpusys_top_core_stall_dcm(on); + dcm_mp_cpusys_top_fcm_stall_dcm(on); +} + +static bool check_dcm_state(void) +{ + bool ret = true; + + ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(); + + ret &= dcm_mp_cpusys_top_adb_dcm_is_on(); + ret &= dcm_mp_cpusys_top_apb_dcm_is_on(); + ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on(); + ret &= dcm_mp_cpusys_top_misc_dcm_is_on(); + ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on(); + ret &= dcm_cpccfg_reg_emi_wfifo_is_on(); + ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(); + + ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on(); + ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on(); + + return ret; +} + +bool dcm_set_default(void) +{ + dcm_armcore(true); + dcm_mcusys(true); + dcm_stall(true); + + return check_dcm_state(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h new file mode 100644 index 0000000..cb65b85 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_DCM_H +#define MTK_DCM_H + +#include + +bool dcm_set_default(void); + +#endif /* #ifndef MTK_DCM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c new file mode 100644 index 0000000..a1a3720 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(17)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | \ + BIT(16) | \ + BIT(17) | \ + BIT(18) | \ + BIT(21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | \ + BIT(16) | \ + BIT(17) | \ + BIT(18)) +#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(17)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | \ + BIT(16) | \ + BIT(17) | \ + BIT(18) | \ + BIT(21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | \ + BIT(16) | \ + BIT(17) | \ + BIT(18)) +#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 17)) +#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | \ + (0x0 << 16) | \ + (0x0 << 17) | \ + (0x0 << 18) | \ + (0x0 << 21)) +#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | \ + (0x0 << 16) | \ + (0x0 << 17) | \ + (0x0 << 18)) + +bool dcm_mp_cpusys_top_adb_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0) & + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON); + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4) & + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) == + (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON); + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) & + MP_CPUSYS_TOP_ADB_DCM_REG2_MASK) == + (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG2_ON); + + return ret; +} + +void dcm_mp_cpusys_top_adb_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG0_ON); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4, + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG1_ON); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG2_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG2_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG0_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG0_OFF); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4, + MP_CPUSYS_TOP_ADB_DCM_REG1_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG1_OFF); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_ADB_DCM_REG2_MASK, + MP_CPUSYS_TOP_ADB_DCM_REG2_OFF); + } +} + +#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16)) +#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16)) +#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5)) +#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8)) +#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16)) + +bool dcm_mp_cpusys_top_apb_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON); + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG1_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON); + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) & + MP_CPUSYS_TOP_APB_DCM_REG2_MASK) == + (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON); + + return ret; +} + +void dcm_mp_cpusys_top_apb_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG0_MASK, + MP_CPUSYS_TOP_APB_DCM_REG0_ON); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG1_MASK, + MP_CPUSYS_TOP_APB_DCM_REG1_ON); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG2_MASK, + MP_CPUSYS_TOP_APB_DCM_REG2_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG0_MASK, + MP_CPUSYS_TOP_APB_DCM_REG0_OFF); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG1_MASK, + MP_CPUSYS_TOP_APB_DCM_REG1_OFF); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0, + MP_CPUSYS_TOP_APB_DCM_REG2_MASK, + MP_CPUSYS_TOP_APB_DCM_REG2_OFF); + } +} + +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11) | \ + BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) | \ + BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) | \ + (0x0 << 24) | \ + (0x0 << 25)) + +bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) & + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK, + MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0)) +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0)) +#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0)) + +bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) & + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_core_stall_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0)) +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0)) +#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0)) + +bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSIC_DCM0) & + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpubiu_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 24) | \ + (0x0 << 25)) + +bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0) & + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(24) | \ + BIT(25)) +#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 24) | \ + (0x0 << 25)) + +bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1) & + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK, + MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4)) +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4)) +#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4)) + +bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) & + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_fcm_stall_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK, + MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK ((0x1U << 31)) +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON ((0x1U << 31)) +#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0U << 31)) + +bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) & + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK, + MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | \ + BIT(4)) +#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | \ + BIT(4)) +#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | \ + (0x0 << 4)) + +bool dcm_mp_cpusys_top_misc_dcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) & + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON); + + return ret; +} + +void dcm_mp_cpusys_top_misc_dcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK, + MP_CPUSYS_TOP_MISC_DCM_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MISC_DCM_REG0_MASK, + MP_CPUSYS_TOP_MISC_DCM_REG0_OFF); + } +} + +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3)) +#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | \ + (0x0 << 1) | \ + (0x0 << 2) | \ + (0x0 << 3)) + +bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) & + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) == + (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON); + ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) & + MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK) == + (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG1_ON); + + return ret; +} + +void dcm_mp_cpusys_top_mp0_qdcm(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG0_ON); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG1_ON); + } else { + /* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */ + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF); + mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0, + MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK, + MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF); + } +} + +#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | \ + BIT(1) | \ + BIT(2) | \ + BIT(3)) +#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | \ + (0x0 << 1) | \ + (0x0 << 2) | \ + (0x0 << 3)) + +bool dcm_cpccfg_reg_emi_wfifo_is_on(void) +{ + bool ret = true; + + ret &= ((mmio_read_32(CPCCFG_REG_EMI_WFIFO) & + CPCCFG_REG_EMI_WFIFO_REG0_MASK) == + (unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON); + + return ret; +} + +void dcm_cpccfg_reg_emi_wfifo(bool on) +{ + if (on) { + /* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */ + mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO, + CPCCFG_REG_EMI_WFIFO_REG0_MASK, + CPCCFG_REG_EMI_WFIFO_REG0_ON); + } else { + /* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */ + mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO, + CPCCFG_REG_EMI_WFIFO_REG0_MASK, + CPCCFG_REG_EMI_WFIFO_REG0_OFF); + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h new file mode 100644 index 0000000..e5743af --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_DCM_UTILS_H +#define MTK_DCM_UTILS_H + +#include + +#include +#include + +/* Base */ +#define MP_CPUSYS_TOP_BASE (MCUCFG_BASE + 0x8000) +#define CPCCFG_REG_BASE (MCUCFG_BASE + 0xA800) + +/* Register Definition */ +#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0) +#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4) +#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0) +#define MP_CPUSYS_TOP_MCSIC_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440) +#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2500) +#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510) +#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518) +#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0) +#define CPCCFG_REG_EMI_WFIFO (CPCCFG_REG_BASE + 0x100) +#define MP_CPUSYS_TOP_MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880) +#define MP_CPUSYS_TOP_MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c) + +/* MP_CPUSYS_TOP */ +bool dcm_mp_cpusys_top_adb_dcm_is_on(void); +void dcm_mp_cpusys_top_adb_dcm(bool on); +bool dcm_mp_cpusys_top_apb_dcm_is_on(void); +void dcm_mp_cpusys_top_apb_dcm(bool on); +bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void); +void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on); +bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void); +void dcm_mp_cpusys_top_core_stall_dcm(bool on); +bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void); +void dcm_mp_cpusys_top_cpubiu_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on); +bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void); +void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on); +bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void); +void dcm_mp_cpusys_top_fcm_stall_dcm(bool on); +bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void); +void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on); +bool dcm_mp_cpusys_top_misc_dcm_is_on(void); +void dcm_mp_cpusys_top_misc_dcm(bool on); +bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void); +void dcm_mp_cpusys_top_mp0_qdcm(bool on); +/* CPCCFG_REG */ +bool dcm_cpccfg_reg_emi_wfifo_is_on(void); +void dcm_cpccfg_reg_emi_wfifo(bool on); + +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c new file mode 100644 index 0000000..c083318 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +static bool dfd_enabled; +static uint64_t dfd_base_addr; +static uint64_t dfd_chain_length; +static uint64_t dfd_cache_dump; + +static void dfd_setup(uint64_t base_addr, uint64_t chain_length, + uint64_t cache_dump) +{ + mmio_write_32(MTK_WDT_LATCH_CTL2, MTK_WDT_LATCH_CTL2_VAL); + mmio_write_32(MTK_WDT_INTERVAL, MTK_WDT_INTERVAL_VAL); + mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_VAL); + mmio_write_32(MTK_DRM_LATCH_CTL1, MTK_DRM_LATCH_CTL1_VAL); + + /* Bit[2] = 0 (default=1), disable dfd apb bus protect_en */ + mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 0x1 << 2); + + /* Bit[0] : enable?mcusys_vproc?external_off?dfd?trigger -> 1 */ + mmio_setbits_32(DFD_V50_GROUP_0_63_DIFF, 0x1); + + /* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */ + /* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */ + sync_writel(DFD_INTERNAL_CTL, 0x5); + + /* bit[13]: xreset_b_update_disable */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13); + + /* + * bit[10:3]: DFD trigger selection mask + * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger) + * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger) + * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger) + * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger) + * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger) + */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1F << 3); + + /* + * bit[9] : rg_rw_dfd_trigger_sel[6] = 1(cpu_eb_sw_dfd_trigger) + * bit[10] : rg_rw_dfd_trigger_sel[7] = 1(cpu_eb_wdt_dfd_trigger) + */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 9); + + /* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19); + + /* + * bit[0]: rg_rw_dfd_auto_power_on = 1 + * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us) + * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us) + */ + mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB); + + /* longest scan chain length */ + mmio_write_32(DFD_CHAIN_LENGTH0, chain_length); + + /* bit[1:0]: rg_rw_dfd_shift_clock_ratio */ + mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0); + + /* rg_dfd_test_so_over_64 */ + mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1); + + /* DFD3.0 */ + mmio_write_32(DFD_TEST_SI_0, 0x0); + mmio_write_32(DFD_TEST_SI_1, 0x0); + mmio_write_32(DFD_TEST_SI_2, 0x0); + mmio_write_32(DFD_TEST_SI_3, 0x0); + + /* for iLDO feature */ + sync_writel(DFD_POWER_CTL, 0xF9); + + /* read offset */ + sync_writel(DFD_READ_ADDR, DFD_READ_ADDR_VAL); + + /* for DFD-3.0 setup */ + sync_writel(DFD_V30_CTL, 0xD); + + /* set base address */ + mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24); + mmio_write_32(DFD_O_REG_0, 0); + + /* setup global variables for suspend and resume */ + dfd_enabled = true; + dfd_base_addr = base_addr; + dfd_chain_length = chain_length; + dfd_cache_dump = cache_dump; + + if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) { + mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_CACHE_VAL); + sync_writel(DFD_V35_ENABLE, 0x1); + sync_writel(DFD_V35_TAP_NUMBER, 0xB); + sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL); + sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL); + + /* Cache dump only mode */ + sync_writel(DFD_V35_CTL, 0x1); + mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 0xF); + mmio_write_32(DFD_CHAIN_LENGTH0, DFD_CHAIN_LENGTH_VAL); + mmio_write_32(DFD_CHAIN_LENGTH1, DFD_CHAIN_LENGTH_VAL); + mmio_write_32(DFD_CHAIN_LENGTH2, DFD_CHAIN_LENGTH_VAL); + mmio_write_32(DFD_CHAIN_LENGTH3, DFD_CHAIN_LENGTH_VAL); + + if ((cache_dump & DFD_PARITY_ERR_TRIGGER) != 0UL) { + sync_writel(DFD_HW_TRIGGER_MASK, 0xC); + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4); + } + } + dsbsy(); +} + +void dfd_resume(void) +{ + if (dfd_enabled == true) { + dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump); + } +} + +uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3) +{ + uint64_t ret = 0L; + + switch (arg0) { + case PLAT_MTK_DFD_SETUP_MAGIC: + INFO("[%s] DFD setup call from kernel\n", __func__); + dfd_setup(arg1, arg2, arg3); + break; + case PLAT_MTK_DFD_READ_MAGIC: + /* only allow to access DFD register base + 0x200 */ + if (arg1 <= 0x200) { + ret = mmio_read_32(MISC1_CFG_BASE + arg1); + } + break; + case PLAT_MTK_DFD_WRITE_MAGIC: + /* only allow to access DFD register base + 0x200 */ + if (arg1 <= 0x200) { + sync_writel(MISC1_CFG_BASE + arg1, arg2); + } + break; + default: + ret = MTK_SIP_E_INVALID_PARAM; + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h new file mode 100644 index 0000000..2a7e979 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DFD_H +#define PLAT_DFD_H + +#include +#include +#include + +#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); \ + dsbsy(); \ + } while (0) + +#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150) +#define PLAT_MTK_DFD_READ_MAGIC (0x99716151) +#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152) + +#define MTK_DRM_LATCH_CTL1 (DRM_BASE + 0x40) +#define MTK_DRM_LATCH_CTL2 (DRM_BASE + 0x44) + +#define MTK_WDT_BASE (RGU_BASE) +#define MTK_WDT_INTERVAL (MTK_WDT_BASE + 0x10) +#define MTK_WDT_LATCH_CTL2 (MTK_WDT_BASE + 0x48) + +#define MCU_BIU_BASE (MCUCFG_BASE) +#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xE040) +#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00) +#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08) +#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C) +#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10) +#define DFD_CHAIN_LENGTH1 (MISC1_CFG_BASE + 0x1C) +#define DFD_CHAIN_LENGTH2 (MISC1_CFG_BASE + 0x20) +#define DFD_CHAIN_LENGTH3 (MISC1_CFG_BASE + 0x24) +#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28) +#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30) +#define DFD_INTERNAL_TEST_SO_OVER_64 (MISC1_CFG_BASE + 0x34) +#define DFD_INTERNAL_SW_NS_TRIGGER (MISC1_CFG_BASE + 0x3c) +#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48) +#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C) +#define DFD_POWER_CTL (MISC1_CFG_BASE + 0x50) +#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58) +#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C) +#define DFD_CLEAN_STATUS (MISC1_CFG_BASE + 0x60) +#define DFD_TEST_SI_2 (MISC1_CFG_BASE + 0x1D8) +#define DFD_TEST_SI_3 (MISC1_CFG_BASE + 0x1DC) +#define DFD_READ_ADDR (MISC1_CFG_BASE + 0x1E8) +#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC) + +#define DFD_V35_ENABLE (MCU_BIU_BASE + 0xE0A8) +#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xE0AC) +#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xE0B0) +#define DFD_V35_CTL (MCU_BIU_BASE + 0xE0B4) +#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xE0C0) +#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xE0C4) +#define DFD_V50_GROUP_0_63_DIFF (MCU_BIU_BASE + 0xE2AC) + +#define DFD_O_PROTECT_EN_REG (0x10001220) +#define DFD_O_INTRF_MCU_PWR_CTL_MASK (0x10001A3C) +#define DFD_O_SET_BASEADDR_REG (0x10043000) +#define DFD_O_REG_0 (0x10001390) + +#define DFD_CACHE_DUMP_ENABLE 1U +#define DFD_PARITY_ERR_TRIGGER 2U + +#define DFD_V35_TAP_EN_VAL (0x43FF) +#define DFD_V35_SEQ0_0_VAL (0x63668820) +#define DFD_READ_ADDR_VAL (0x40000008) +#define DFD_CHAIN_LENGTH_VAL (0xFFFFFFFF) + +#define MTK_WDT_LATCH_CTL2_VAL (0x9507FFFF) +#define MTK_WDT_INTERVAL_VAL (0x6600000A) +#define MTK_DRM_LATCH_CTL2_VAL (0x950600C8) +#define MTK_DRM_LATCH_CTL2_CACHE_VAL (0x95065DC0) + +#define MTK_DRM_LATCH_CTL1_VAL (0x95000013) + +void dfd_resume(void); +uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3); + +#endif /* PLAT_DFD_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c new file mode 100644 index 0000000..5930cd5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +static uint32_t dp_write_sec_reg(uint32_t is_edp, uint32_t offset, + uint32_t value, uint32_t mask) +{ + uint32_t reg = (is_edp != 0U) ? eDP_SEC_BASE : DP_SEC_BASE; + + mmio_clrsetbits_32(reg + offset, mask, value); + + return mmio_read_32(reg + offset); +} + +int32_t dp_secure_handler(uint64_t cmd, uint64_t para, uint32_t *val) +{ + int32_t ret = 0L; + uint32_t is_edp = 0UL; + uint32_t regval = 0UL; + uint32_t regmsk = 0UL; + uint32_t fldmask = 0UL; + + if ((cmd > DP_ATF_CMD_COUNT) || (val == NULL)) { + INFO("dp_secure_handler error cmd 0x%" PRIx64 "\n", cmd); + return MTK_SIP_E_INVALID_PARAM; + } + + switch (cmd) { + case DP_ATF_DP_VIDEO_UNMUTE: + INFO("[%s] DP_ATF_DP_VIDEO_UNMUTE\n", __func__); + is_edp = DP_ATF_TYPE_DP; + ret = MTK_SIP_E_SUCCESS; + break; + case DP_ATF_EDP_VIDEO_UNMUTE: + INFO("[%s] DP_ATF_EDP_VIDEO_UNMUTE\n", __func__); + is_edp = DP_ATF_TYPE_EDP; + ret = MTK_SIP_E_SUCCESS; + break; + default: + ret = MTK_SIP_E_INVALID_PARAM; + break; + } + + if (ret == MTK_SIP_E_SUCCESS) { + regmsk = (VIDEO_MUTE_SEL_SECURE_FLDMASK | + VIDEO_MUTE_SW_SECURE_FLDMASK); + if (para > 0U) { + fldmask = VIDEO_MUTE_SW_SECURE_FLDMASK; + } else { + fldmask = 0; + } + + regval = (VIDEO_MUTE_SEL_SECURE_FLDMASK | fldmask); + *val = dp_write_sec_reg(is_edp, DP_TX_SECURE_REG11, + regval, regmsk); + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h new file mode 100644 index 0000000..8157598 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_DP_H +#define MT_DP_H + +#define DP_TX_SECURE_REG11 (0x2c) + +#define VIDEO_MUTE_SEL_SECURE_FLDMASK (0x10) +#define VIDEO_MUTE_SW_SECURE_FLDMASK (0x8) + +enum DP_ATF_HW_TYPE { + DP_ATF_TYPE_DP = 0, + DP_ATF_TYPE_EDP = 1 +}; + +enum DP_ATF_CMD { + DP_ATF_DP_VIDEO_UNMUTE = 0x20, + DP_ATF_EDP_VIDEO_UNMUTE, + DP_ATF_CMD_COUNT +}; + +int32_t dp_secure_handler(uint64_t cmd, uint64_t para, uint32_t *val); + +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c new file mode 100644 index 0000000..794e21e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#if ENABLE_EMI_MPU_SW_LOCK +static unsigned char region_lock_state[EMI_MPU_REGION_NUM]; +#endif + +#define EMI_MPU_START_MASK (0x00FFFFFF) +#define EMI_MPU_END_MASK (0x00FFFFFF) +#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF) +#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF) + +static int _emi_mpu_set_protection(unsigned int start, unsigned int end, + unsigned int apc) +{ + unsigned int dgroup; + unsigned int region; + + region = (start >> 24) & 0xFF; + start &= EMI_MPU_START_MASK; + dgroup = (end >> 24) & 0xFF; + end &= EMI_MPU_END_MASK; + + if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) { + WARN("invalid region, domain\n"); + return -1; + } + +#if ENABLE_EMI_MPU_SW_LOCK + if (region_lock_state[region] == 1) { + WARN("invalid region\n"); + return -1; + } + + if ((dgroup == 0) && ((apc >> 31) & 0x1)) { + region_lock_state[region] = 1; + } + + apc &= EMI_MPU_APC_SW_LOCK_MASK; +#else + apc &= EMI_MPU_APC_HW_LOCK_MASK; +#endif + + if ((start >= DRAM_OFFSET) && (end >= start)) { + start -= DRAM_OFFSET; + end -= DRAM_OFFSET; + } else { + WARN("invalid range\n"); + return -1; + } + + mmio_write_32(EMI_MPU_SA(region), start); + mmio_write_32(EMI_MPU_EA(region), end); + mmio_write_32(EMI_MPU_APC(region, dgroup), apc); + +#if defined(SUB_EMI_MPU_BASE) + mmio_write_32(SUB_EMI_MPU_SA(region), start); + mmio_write_32(SUB_EMI_MPU_EA(region), end); + mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc); +#endif + return 1; +} + +int emi_mpu_set_protection(struct emi_region_info_t *region_info) +{ + unsigned int start, end; + int i; + + if (region_info->region >= EMI_MPU_REGION_NUM) { + WARN("invalid region\n"); + return -1; + } + + start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) | + (region_info->region << 24); + + for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) { + end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | + (i << 24); + _emi_mpu_set_protection(start, end, region_info->apc[i]); + } + + return 0; +} + +void dump_emi_mpu_regions(void) +{ + unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea; + + int region, i; + + /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */ + for (region = 0; region < 8; ++region) { + for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) + apc[i] = mmio_read_32(EMI_MPU_APC(region, i)); + sa = mmio_read_32(EMI_MPU_SA(region)); + ea = mmio_read_32(EMI_MPU_EA(region)); + + INFO("region %d:\n", region); + INFO("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n", + sa, ea, apc[0], apc[1]); + } +} + +void emi_mpu_init(void) +{ + struct emi_region_info_t region_info; + + /* SCP DRAM */ + region_info.start = 0x50000000ULL; + region_info.end = 0x51400000ULL; + region_info.region = 2; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION); + emi_mpu_set_protection(®ion_info); + + /* DSP protect address */ + region_info.start = 0x60000000ULL; /* dram base addr */ + region_info.end = 0x610FFFFFULL; + region_info.region = 3; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION); + emi_mpu_set_protection(®ion_info); + + /* Forbidden All */ + region_info.start = 0x40000000ULL; /* dram base addr */ + region_info.end = 0x1FFFF0000ULL; + region_info.region = 4; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION); + emi_mpu_set_protection(®ion_info); + + dump_emi_mpu_regions(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..415146e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMI_MPU_H +#define EMI_MPU_H + +#include + +#define ENABLE_EMI_MPU_SW_LOCK 1 + +#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x000) +#define EMI_MPU_DBG (EMI_MPU_BASE + 0x004) +#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100) +#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200) +#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region * 4)) +#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region * 4)) +#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300) +#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100)) +#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800) +#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + (domain * 4)) +#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900) +#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + (domain * 4)) +#define EMI_MPU_START (0x000) +#define EMI_MPU_END (0x93C) + +#define SUB_EMI_MPU_CTRL (SUB_EMI_MPU_BASE + 0x000) +#define SUB_EMI_MPU_DBG (SUB_EMI_MPU_BASE + 0x004) +#define SUB_EMI_MPU_SA0 (SUB_EMI_MPU_BASE + 0x100) +#define SUB_EMI_MPU_EA0 (SUB_EMI_MPU_BASE + 0x200) +#define SUB_EMI_MPU_SA(region) (SUB_EMI_MPU_SA0 + (region * 4)) +#define SUB_EMI_MPU_EA(region) (SUB_EMI_MPU_EA0 + (region * 4)) +#define SUB_EMI_MPU_APC0 (SUB_EMI_MPU_BASE + 0x300) +#define SUB_EMI_MPU_APC(region, dgroup) (SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100)) +#define SUB_EMI_MPU_CTRL_D0 (SUB_EMI_MPU_BASE + 0x800) +#define SUB_EMI_MPU_CTRL_D(domain) (SUB_EMI_MPU_CTRL_D0 + (domain * 4)) +#define SUB_EMI_RG_MASK_D0 (SUB_EMI_MPU_BASE + 0x900) +#define SUB_EMI_RG_MASK_D(domain) (SUB_EMI_RG_MASK_D0 + (domain * 4)) + +#define EMI_MPU_DOMAIN_NUM (16) +#define EMI_MPU_REGION_NUM (32) +#define EMI_MPU_ALIGN_BITS (16) +#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS) + +#define NO_PROTECTION 0 +#define SEC_RW 1 +#define SEC_RW_NSEC_R 2 +#define SEC_RW_NSEC_W 3 +#define SEC_R_NSEC_R 4 +#define FORBIDDEN 5 +#define SEC_R_NSEC_RW 6 + +#define LOCK 1 +#define UNLOCK 0 + +#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8) + +#if (EMI_MPU_DGROUP_NUM == 1) +#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \ +do { \ + apc_ary[1] = 0; \ + apc_ary[0] = \ + (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \ + (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \ + (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \ + (((unsigned int) d1) << 3) | ((unsigned int) d0) | \ + ((unsigned int) lock << 31); \ +} while (0) +#elif (EMI_MPU_DGROUP_NUM == 2) +#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \ + d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \ +do { \ + apc_ary[1] = \ + (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \ + (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \ + (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) | \ + (((unsigned int) d9) << 3) | ((unsigned int) d8); \ + apc_ary[0] = \ + (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \ + (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \ + (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \ + (((unsigned int) d1) << 3) | ((unsigned int) d0) | \ + ((unsigned int) lock << 31); \ +} while (0) +#endif + +struct emi_region_info_t { + unsigned long long start; + unsigned long long end; + unsigned int region; + unsigned int apc[EMI_MPU_DGROUP_NUM]; +}; + +void emi_mpu_init(void); + +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c new file mode 100644 index 0000000..daab84c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uintptr_t mt_gpio_find_reg_addr(uint32_t pin) +{ + uintptr_t reg_addr = 0U; + struct mt_pin_info gpio_info; + + assert(pin < MAX_GPIO_PIN); + + gpio_info = mt_pin_infos[pin]; + + switch (gpio_info.base & 0x0f) { + case 0: + reg_addr = IOCFG_BM_BASE; + break; + case 1: + reg_addr = IOCFG_BL_BASE; + break; + case 2: + reg_addr = IOCFG_BR_BASE; + break; + case 3: + reg_addr = IOCFG_LM_BASE; + break; + case 4: + reg_addr = IOCFG_RB_BASE; + break; + case 5: + reg_addr = IOCFG_TL_BASE; + break; + default: + break; + } + + return reg_addr; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h new file mode 100644 index 0000000..88b4706 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_H +#define MT_GPIO_H + +#include + +/* Enumeration for GPIO pin */ +typedef enum GPIO_PIN { + GPIO_UNSUPPORTED = -1, + + GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, + GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15, + GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, + GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31, + GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39, + GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47, + GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55, + GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63, + GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71, + GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79, + GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87, + GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95, + GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103, + GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111, + GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119, + GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127, + GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135, + GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143, + MT_GPIO_BASE_MAX +} GPIO_PIN; + +static const struct mt_pin_info mt_pin_infos[] = { + PIN(0, 1, 0, 0x23, 0x60), + PIN(1, 1, 1, 0x23, 0x60), + PIN(2, 1, 2, 0x23, 0x60), + PIN(3, 1, 3, 0x23, 0x60), + PIN(4, 1, 4, 0x23, 0x60), + PIN(5, 1, 5, 0x23, 0x60), + PIN(6, 0, 6, 0x23, 0x70), + PIN(7, 0, 7, 0x23, 0x70), + PIN(8, 0, 13, 0x23, 0x70), + PIN(9, 0, 8, 0x23, 0x70), + PIN(10, 0, 14, 0x23, 0x70), + PIN(11, 0, 9, 0x23, 0x70), + PIN(12, 0, 15, 0x23, 0x70), + PIN(13, 0, 10, 0x23, 0x70), + PIN(14, 0, 16, 0x23, 0x70), + PIN(15, 0, 11, 0x23, 0x70), + PIN(16, 0, 17, 0x23, 0x70), + PIN(17, 0, 12, 0x23, 0x70), + PIN(18, 0, 5, 0x10, 0x60), + PIN(19, 0, 12, 0x10, 0x60), + PIN(20, 0, 11, 0x10, 0x60), + PIN(21, 0, 10, 0x10, 0x60), + PIN(22, 0, 0, 0x10, 0x60), + PIN(23, 0, 1, 0x10, 0x60), + PIN(24, 0, 2, 0x10, 0x60), + PIN(25, 0, 4, 0x10, 0x60), + PIN(26, 0, 3, 0x10, 0x60), + PIN(27, 0, 6, 0x10, 0x60), + PIN(28, 0, 7, 0x10, 0x60), + PIN(29, 0, 8, 0x10, 0x60), + PIN(30, 0, 9, 0x10, 0x60), + PIN(31, 0, 13, 0x21, 0xa0), + PIN(32, 0, 12, 0x21, 0xa0), + PIN(33, 0, 11, 0x21, 0xa0), + PIN(34, 0, 14, 0x21, 0xa0), + PIN(35, 0, 15, 0x21, 0xa0), + PIN(36, 0, 3, 0x21, 0xb0), + PIN(37, 0, 6, 0x21, 0xb0), + PIN(38, 0, 4, 0x21, 0xb0), + PIN(39, 0, 5, 0x21, 0xb0), + PIN(40, 0, 8, 0x21, 0xb0), + PIN(41, 0, 7, 0x21, 0xb0), + PIN(42, 0, 10, 0x21, 0xb0), + PIN(43, 0, 9, 0x21, 0xb0), + PIN(44, 0, 20, 0x21, 0xb0), + PIN(45, 0, 21, 0x21, 0xb0), + PIN(46, 0, 18, 0x21, 0xa0), + PIN(47, 0, 16, 0x21, 0xa0), + PIN(48, 0, 19, 0x21, 0xa0), + PIN(49, 0, 17, 0x21, 0xa0), + PIN(50, 0, 25, 0x21, 0xa0), + PIN(51, 0, 20, 0x21, 0xa0), + PIN(52, 0, 26, 0x21, 0xa0), + PIN(53, 0, 21, 0x21, 0xa0), + PIN(54, 0, 22, 0x21, 0xa0), + PIN(55, 0, 23, 0x21, 0xa0), + PIN(56, 0, 24, 0x21, 0xa0), + PIN(57, 0, 29, 0x21, 0xa0), + PIN(58, 0, 27, 0x21, 0xa0), + PIN(59, 0, 30, 0x21, 0xa0), + PIN(60, 0, 28, 0x21, 0xa0), + PIN(61, 0, 8, 0x21, 0xa0), + PIN(62, 0, 7, 0x21, 0xa0), + PIN(63, 0, 10, 0x21, 0xa0), + PIN(64, 0, 9, 0x21, 0xa0), + PIN(65, 0, 1, 0x21, 0xb0), + PIN(66, 0, 31, 0x21, 0xa0), + PIN(67, 0, 0, 0x21, 0xb0), + PIN(68, 0, 2, 0x21, 0xb0), + PIN(69, 0, 0, 0x21, 0xa0), + PIN(70, 0, 6, 0x21, 0xa0), + PIN(71, 0, 4, 0x21, 0xa0), + PIN(72, 0, 5, 0x21, 0xa0), + PIN(73, 0, 1, 0x21, 0xa0), + PIN(74, 0, 2, 0x21, 0xa0), + PIN(75, 0, 3, 0x21, 0xa0), + PIN(76, 0, 11, 0x21, 0xb0), + PIN(77, 1, 1, 0x22, 0x60), + PIN(78, 1, 2, 0x22, 0x60), + PIN(79, 1, 9, 0x22, 0x60), + PIN(80, 1, 10, 0x22, 0x60), + PIN(81, 1, 11, 0x22, 0x60), + PIN(82, 1, 12, 0x22, 0x60), + PIN(83, 1, 13, 0x22, 0x60), + PIN(84, 1, 14, 0x22, 0x60), + PIN(85, 1, 15, 0x22, 0x60), + PIN(86, 1, 16, 0x22, 0x60), + PIN(87, 1, 3, 0x22, 0x60), + PIN(88, 1, 4, 0x22, 0x60), + PIN(89, 1, 5, 0x22, 0x60), + PIN(90, 1, 6, 0x22, 0x60), + PIN(91, 1, 7, 0x22, 0x60), + PIN(92, 1, 8, 0x22, 0x60), + PIN(93, 1, 18, 0x22, 0x60), + PIN(94, 1, 19, 0x22, 0x60), + PIN(95, 1, 17, 0x22, 0x60), + PIN(96, 1, 0, 0x22, 0x60), + PIN(97, 0, 20, 0x22, 0x70), + PIN(98, 0, 28, 0x22, 0x70), + PIN(99, 0, 27, 0x22, 0x70), + PIN(100, 0, 30, 0x22, 0x70), + PIN(101, 0, 29, 0x22, 0x70), + PIN(102, 0, 0, 0x22, 0x70), + PIN(103, 0, 31, 0x22, 0x70), + PIN(104, 1, 25, 0x22, 0x60), + PIN(105, 1, 26, 0x22, 0x60), + PIN(106, 1, 23, 0x22, 0x60), + PIN(107, 1, 24, 0x22, 0x60), + PIN(108, 0, 22, 0x22, 0x70), + PIN(109, 0, 21, 0x22, 0x70), + PIN(110, 1, 1, 0x14, 0x20), + PIN(111, 1, 0, 0x14, 0x20), + PIN(112, 1, 2, 0x14, 0x20), + PIN(113, 1, 3, 0x14, 0x20), + PIN(114, 1, 4, 0x14, 0x20), + PIN(115, 1, 5, 0x14, 0x20), + PIN(116, 1, 9, 0x25, 0x50), + PIN(117, 1, 8, 0x25, 0x50), + PIN(118, 1, 7, 0x25, 0x50), + PIN(119, 1, 6, 0x25, 0x50), + PIN(120, 1, 11, 0x25, 0x50), + PIN(121, 1, 1, 0x25, 0x50), + PIN(122, 1, 0, 0x25, 0x50), + PIN(123, 1, 5, 0x25, 0x50), + PIN(124, 1, 4, 0x25, 0x50), + PIN(125, 1, 3, 0x25, 0x50), + PIN(126, 1, 2, 0x25, 0x50), + PIN(127, 1, 10, 0x25, 0x50), + PIN(128, 0, 3, 0x22, 0x70), + PIN(129, 0, 1, 0x22, 0x70), + PIN(130, 0, 4, 0x22, 0x70), + PIN(131, 0, 2, 0x22, 0x70), + PIN(132, 0, 13, 0x25, 0x60), + PIN(133, 0, 12, 0x25, 0x60), + PIN(134, 0, 15, 0x25, 0x60), + PIN(135, 0, 14, 0x25, 0x60), + PIN(136, 0, 13, 0x21, 0xb0), + PIN(137, 0, 12, 0x21, 0xb0), + PIN(138, 0, 15, 0x21, 0xb0), + PIN(139, 0, 14, 0x21, 0xb0), + PIN(140, 0, 17, 0x21, 0xb0), + PIN(141, 0, 16, 0x21, 0xb0), + PIN(142, 0, 19, 0x21, 0xb0), + PIN(143, 0, 18, 0x21, 0xb0), +}; +#endif /* MT_GPIO_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c new file mode 100644 index 0000000..5a80d95 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1); + +static int plat_mt_lp_cpu_rc; + +static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state) +{ + mtk_cpc_core_on_hint_clr(cpu); + + if (IS_SYSTEM_SUSPEND_STATE(state)) { + mtk_cpc_time_sync(); + } + + return 0; +} + +static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + /* clear DBGPRCR.CORENPDRQ to allow CPU power down */ + write_dbgprcr_el1(0ULL); + + return 0; +} + +static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { + return -1; + } + + mtk_cpc_mcusys_off_reflect(); + + return 0; +} + +static int pwr_mcusys_pwron_finished(unsigned int cpu, + const psci_power_state_t *state) +{ + int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS]; + + if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { + return -1; + } + + mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id); + mt_lp_irqremain_release(); + + return 0; +} + +static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS]; + + if (!IS_MCUSYS_OFF_STATE(state)) { + goto mt_pwr_mcusysoff_break; + } + + if (mcdi_try_init() != 0) { + goto mt_pwr_mcusysoff_break; + } + + if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) { + goto mt_pwr_mcusysoff_break; + } + + plat_mt_lp_cpu_rc = + mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL); + + if (plat_mt_lp_cpu_rc < 0) { + goto mt_pwr_mcusysoff_reflect; + } + + mt_lp_irqremain_aquire(); + + return 0; + +mt_pwr_mcusysoff_reflect: + mtk_cpc_mcusys_off_reflect(); + +mt_pwr_mcusysoff_break: + + plat_mt_lp_cpu_rc = -1; + + return -1; +} + +static const struct mt_lpm_tz plat_pm = { + .pwr_prompt = pwr_state_prompt, + .pwr_reflect = pwr_state_reflect, + .pwr_cpu_on = pwr_cpu_pwron, + .pwr_cpu_dwn = pwr_cpu_pwrdwn, + .pwr_cluster_on = pwr_cluster_pwron, + .pwr_cluster_dwn = pwr_cluster_pwrdwn, + .pwr_mcusys_dwn = pwr_mcusys_pwrdwn, + .pwr_mcusys_on = pwr_mcusys_pwron, + .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished +}; + +const struct mt_lpm_tz *mt_plat_cpu_pm_init(void) +{ + mtk_cpc_init(); + + if (mcdi_try_init() == 0) { + INFO("MCDI init done.\n"); + } + + mt_lp_irqremain_init(); + + return &plat_pm; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c new file mode 100644 index 0000000..f8c51a1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +struct mtk_cpc_dev { + int auto_off; + unsigned int auto_thres_tick; +}; + +static struct mtk_cpc_dev cpc; + +static int mtk_cpc_last_core_prot(uint32_t prot_req, + uint32_t resp_reg, uint32_t resp_ofs) +{ + uint32_t sta, retry; + + retry = 0U; + + while (retry++ < RETRY_CNT_MAX) { + + mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req); + + udelay(1U); + + sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK; + + if (sta == PROT_SUCCESS) { + return CPC_SUCCESS; + } else if (sta == PROT_GIVEUP) { + return CPC_ERR_FAIL; + } + } + + return CPC_ERR_TIMEOUT; +} + +int mtk_cpu_pm_mcusys_prot_aquire(void) +{ + return mtk_cpc_last_core_prot( + MCUSYS_PROT_SET, + CPC_MCUSYS_LAST_CORE_RESP, + MCUSYS_RESP_OFS); +} + +void mtk_cpu_pm_mcusys_prot_release(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR); +} + +int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster) +{ + return mtk_cpc_last_core_prot( + CPUSYS_PROT_SET, + CPC_MCUSYS_MP_LAST_CORE_RESP, + CPUSYS_RESP_OFS); +} + +void mtk_cpu_pm_cluster_prot_release(unsigned int cluster) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR); +} + +static void mtk_cpc_cluster_cnt_backup(void) +{ + uint32_t backup_cnt; + uint32_t curr_cnt; + uint32_t cnt_mask = GENMASK(14, 0); + uint32_t clr_mask = GENMASK(1, 0); + + /* Single Cluster */ + backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP); + curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER); + + /* Get off count if dormant count is 0 */ + if ((curr_cnt & cnt_mask) == 0U) { + curr_cnt = (curr_cnt >> 16) & cnt_mask; + } else { + curr_cnt = curr_cnt & cnt_mask; + } + + mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt); + mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask); +} + +static inline void mtk_cpc_mcusys_off_en(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U); +} + +static inline void mtk_cpc_mcusys_off_dis(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U); +} + +void mtk_cpc_mcusys_off_reflect(void) +{ + mtk_cpc_mcusys_off_dis(); + mtk_cpu_pm_mcusys_prot_release(); +} + +int mtk_cpc_mcusys_off_prepare(void) +{ + if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) { + return CPC_ERR_FAIL; + } + + mtk_cpc_cluster_cnt_backup(); + mtk_cpc_mcusys_off_en(); + + return CPC_SUCCESS; +} + +void mtk_cpc_core_on_hint_set(unsigned int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu)); +} + +void mtk_cpc_core_on_hint_clr(unsigned int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); +} + +static void mtk_cpc_dump_timestamp(void) +{ + uint32_t id; + + for (id = 0U; id < CPC_TRACE_ID_NUM; id++) { + mmio_write_32(CPC_MCUSYS_TRACE_SEL, id); + + memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id), + (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA, + CPC_TRACE_SIZE); + } +} + +void mtk_cpc_time_sync(void) +{ + uint64_t kt; + uint32_t systime_l, systime_h; + + kt = sched_clock(); + systime_l = mmio_read_32(CNTSYS_L_REG); + systime_h = mmio_read_32(CNTSYS_H_REG); + + /* sync kernel timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt); + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32)); + /* sync system timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l); + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h); +} + +static void mtk_cpc_config(uint32_t cfg, uint32_t data) +{ + uint32_t val; + uint32_t reg = 0U; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + reg = CPC_MCUSYS_CPC_DBG_SETTING; + val = mmio_read_32(reg); + val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN); + break; + case CPC_SMC_CONFIG_AUTO_OFF: + reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG; + val = mmio_read_32(reg); + if (data != 0U) { + val |= CPC_AUTO_OFF_EN; + cpc.auto_off = 1; + } else { + val &= ~CPC_AUTO_OFF_EN; + cpc.auto_off = 0; + } + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + reg = CPC_MCUSYS_CPC_OFF_THRES; + cpc.auto_thres_tick = us_to_ticks(data); + val = cpc.auto_thres_tick; + break; + case CPC_SMC_CONFIG_CNT_CLR: + reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR; + val = GENMASK(1, 0); /* clr_mask */ + break; + case CPC_SMC_CONFIG_TIME_SYNC: + mtk_cpc_time_sync(); + break; + default: + break; + } + + if (reg != 0U) { + mmio_write_32(reg, val); + } +} + +static uint32_t mtk_cpc_read_config(uint32_t cfg) +{ + uint32_t res = 0U; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ? + 1U : 0U; + break; + case CPC_SMC_CONFIG_AUTO_OFF: + res = cpc.auto_off; + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + res = ticks_to_us(cpc.auto_thres_tick); + break; + case CPC_SMC_CONFIG_CNT_CLR: + break; + default: + break; + } + + return res; +} + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2) +{ + uint64_t res = 0ULL; + + switch (act) { + case CPC_SMC_EVENT_DUMP_TRACE_DATA: + mtk_cpc_dump_timestamp(); + break; + case CPC_SMC_EVENT_GIC_DPG_SET: + /* isolated_status = x2; */ + break; + case CPC_SMC_EVENT_CPC_CONFIG: + mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2); + break; + case CPC_SMC_EVENT_READ_CONFIG: + res = mtk_cpc_read_config((uint32_t)arg1); + break; + default: + break; + } + + return res; +} + +void mtk_cpc_init(void) +{ + mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING, + mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) + | CPC_DBG_EN + | CPC_CALC_EN); + + cpc.auto_off = 1; + cpc.auto_thres_tick = us_to_ticks(8000); + + mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, + mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG) + | CPC_OFF_PRE_EN + | (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U)); + + mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h new file mode 100644 index 0000000..19dd6a2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_CPU_PM_CPC_H +#define MT_CPU_PM_CPC_H + +#include +#include +#include +#include + +#define NEED_CPUSYS_PROT_WORKAROUND 1 + +/* system sram registers */ +#define CPUIDLE_SRAM_REG(r) (uint32_t)(MTK_MCDI_SRAM_BASE + (r)) + +/* db dump */ +#define CPC_TRACE_SIZE U(0x20) +#define CPC_TRACE_ID_NUM U(10) +#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE) + +/* buckup off count */ +#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0) +#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4) + +/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */ +#define CPC_PWR_ON_SEQ_DIS BIT(1) +#define CPC_PWR_ON_PRIORITY BIT(2) +#define CPC_AUTO_OFF_EN BIT(5) +#define CPC_DORMANT_WAIT_EN BIT(14) +#define CPC_CTRL_EN BIT(16) +#define CPC_OFF_PRE_EN BIT(29) + +/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */ +#define CPUSYS_PROT_SET BIT(0) +#define MCUSYS_PROT_SET BIT(8) +#define CPUSYS_PROT_CLR BIT(8) +#define MCUSYS_PROT_CLR BIT(9) + +#define CPC_PROT_RESP_MASK U(0x3) +#define CPUSYS_RESP_OFS U(16) +#define MCUSYS_RESP_OFS U(30) + +#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK) +#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK) + +#define RETRY_CNT_MAX U(1000) + +#define PROT_RETRY U(0) +#define PROT_SUCCESS U(1) +#define PROT_GIVEUP U(2) + +/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */ +#define CPC_PROF_EN BIT(0) +#define CPC_DBG_EN BIT(1) +#define CPC_FREEZE BIT(2) +#define CPC_CALC_EN BIT(3) + +enum { + CPC_SUCCESS = 0, + + CPC_ERR_FAIL, + CPC_ERR_TIMEOUT, + + NF_CPC_ERR +}; + +enum { + CPC_SMC_EVENT_DUMP_TRACE_DATA, + CPC_SMC_EVENT_GIC_DPG_SET, + CPC_SMC_EVENT_CPC_CONFIG, + CPC_SMC_EVENT_READ_CONFIG, + + NF_CPC_SMC_EVENT +}; + +enum { + CPC_SMC_CONFIG_PROF, + CPC_SMC_CONFIG_AUTO_OFF, + CPC_SMC_CONFIG_AUTO_OFF_THRES, + CPC_SMC_CONFIG_CNT_CLR, + CPC_SMC_CONFIG_TIME_SYNC, + + NF_CPC_SMC_CONFIG +}; + +#define us_to_ticks(us) ((us) * 13) +#define ticks_to_us(tick) ((tick) / 13) + +int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster); +void mtk_cpu_pm_cluster_prot_release(unsigned int cluster); + +void mtk_cpc_mcusys_off_reflect(void); +int mtk_cpc_mcusys_off_prepare(void); + +void mtk_cpc_core_on_hint_set(unsigned int cpu); +void mtk_cpc_core_on_hint_clr(unsigned int cpu); +void mtk_cpc_time_sync(void); + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2); +void mtk_cpc_init(void); + +#endif /* MT_CPU_PM_CPC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c new file mode 100644 index 0000000..4147184 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + +#define KEYPAD_IRQ_ID U(138) + +#define KEYPAD_WAKESRC 0x4 + +static struct mt_irqremain remain_irqs; + +int mt_lp_irqremain_submit(void) +{ + if (remain_irqs.count == 0) { + return -1; + } + + set_wakeup_sources(remain_irqs.irqs, remain_irqs.count); + mt_lp_rm_do_update(-1, PLAT_RC_UPDATE_REMAIN_IRQS, &remain_irqs); + + return 0; +} + +int mt_lp_irqremain_aquire(void) +{ + if (remain_irqs.count == 0) { + return -1; + } + + mt_cirq_sw_reset(); + mt_cirq_clone_gic(); + mt_cirq_enable(); + + return 0; +} + +int mt_lp_irqremain_release(void) +{ + if (remain_irqs.count == 0) { + return -1; + } + + mt_cirq_flush(); + mt_cirq_disable(); + + return 0; +} + +void mt_lp_irqremain_init(void) +{ + uint32_t idx; + + remain_irqs.count = 0; + + /*edge keypad*/ + idx = remain_irqs.count; + remain_irqs.irqs[idx] = KEYPAD_IRQ_ID; + remain_irqs.wakeupsrc_cat[idx] = 0; + remain_irqs.wakeupsrc[idx] = KEYPAD_WAKESRC; + remain_irqs.count++; + + mt_lp_irqremain_submit(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h new file mode 100644 index 0000000..b86e17e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_LP_IRQREMAIN_H +#define MT_LP_IRQREMAIN_H + +extern int mt_lp_irqremain_submit(void); +extern int mt_lp_irqremain_aquire(void); +extern int mt_lp_irqremain_release(void); +extern void mt_lp_irqremain_init(void); +#endif /* MT_LP_IRQREMAIN_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c new file mode 100644 index 0000000..c14e83b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +/* Read/Write */ +#define APMCU_MCUPM_MBOX_AP_READY U(0) +#define APMCU_MCUPM_MBOX_RESERVED_1 U(1) +#define APMCU_MCUPM_MBOX_RESERVED_2 U(2) +#define APMCU_MCUPM_MBOX_RESERVED_3 U(3) +#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4) +#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5) +#define APMCU_MCUPM_MBOX_BUCK_MODE U(6) +#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7) +/* Read only */ +#define APMCU_MCUPM_MBOX_TASK_STA U(8) +#define APMCU_MCUPM_MBOX_RESERVED_9 U(9) +#define APMCU_MCUPM_MBOX_RESERVED_10 U(10) +#define APMCU_MCUPM_MBOX_RESERVED_11 U(11) + +/* CPC mode - Read/Write */ +#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12) + +/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */ +#define MCUPM_MCUSYS_CTRL BIT(0) +#define MCUPM_BUCK_CTRL BIT(1) +#define MCUPM_ARMPLL_CTRL BIT(2) +#define MCUPM_CM_CTRL BIT(3) +#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0) + +/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */ +#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */ +#define MCUPM_BUCK_LP_MODE U(1) +#define MCUPM_BUCK_OFF_MODE U(2) +#define NF_MCUPM_BUCK_MODE U(3) + +/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */ +#define MCUPM_ARMPLL_ON U(0) /* default */ +#define MCUPM_ARMPLL_GATING U(1) +#define MCUPM_ARMPLL_OFF U(2) +#define NF_MCUPM_ARMPLL_MODE U(3) + +/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */ +#define MCUPM_TASK_UNINIT U(0) +#define MCUPM_TASK_INIT U(1) +#define MCUPM_TASK_INIT_FINISH U(2) +#define MCUPM_TASK_WAIT U(3) +#define MCUPM_TASK_RUN U(4) +#define MCUPM_TASK_PAUSE U(5) + +#define SSPM_MBOX_3_BASE U(0x0c55fce0) + +#define MCDI_NOT_INIT 0 +#define MCDI_INIT_1 1 +#define MCDI_INIT_2 2 +#define MCDI_INIT_DONE 3 + +static int mcdi_init_status __section("tzfw_coherent_mem"); + +static inline uint32_t mcdi_mbox_read(uint32_t id) +{ + return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2)); +} + +static inline void mcdi_mbox_write(uint32_t id, uint32_t val) +{ + mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val); +} + +static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev) +{ + mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev); +} + +static void mtk_set_mcupm_pll_mode(uint32_t mode) +{ + if (mode < NF_MCUPM_ARMPLL_MODE) { + mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode); + } +} + +static void mtk_set_mcupm_buck_mode(uint32_t mode) +{ + if (mode < NF_MCUPM_BUCK_MODE) { + mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode); + } +} + +static int mtk_mcupm_is_ready(void) +{ + unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); + + return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH); +} + +static int mcdi_init_1(void) +{ + unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); + + if (sta != MCUPM_TASK_INIT) { + return -1; + } + + mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF); + mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE); + + mtk_mcupm_pwr_ctrl_setting( + MCUPM_MCUSYS_CTRL | + MCUPM_BUCK_CTRL | + MCUPM_ARMPLL_CTRL); + + mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1); + + return 0; +} + +static int mcdi_init_2(void) +{ + return mtk_mcupm_is_ready() ? 0 : -1; +} + +int mcdi_try_init(void) +{ + if (mcdi_init_status == MCDI_INIT_DONE) { + return 0; + } + + if (mcdi_init_status == MCDI_NOT_INIT) { + mcdi_init_status = MCDI_INIT_1; + } + + if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) { + mcdi_init_status = MCDI_INIT_2; + } + + if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) { + mcdi_init_status = MCDI_INIT_DONE; + } + + INFO("mcdi ready for mcusys-off-idle and system suspend\n"); + + return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h new file mode 100644 index 0000000..f3545aa --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_MCDI_H +#define MT_MCDI_H + +int mcdi_try_init(void); + +#endif /* MT_MCDI_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c new file mode 100644 index 0000000..cca4413 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void pmic_power_off(void) +{ + pwrap_write(PMIC_PWRHOLD, 0x0); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h new file mode 100644 index 0000000..aac22af --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_H +#define PMIC_H + +#define PMIC_PWRHOLD 0xa08 + +/* external API */ +void pmic_power_off(void); + +#endif /* PMIC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..39e78f5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include + +#include "platform_def.h" + +/* external API */ +int32_t pwrap_read(uint32_t adr, uint32_t *rdata); +int32_t pwrap_write(uint32_t adr, uint32_t wdata); + +static struct mt8195_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE; + +/* PMIC_WRAP registers */ +struct mt8195_pmic_wrap_regs { + uint32_t init_done; + uint32_t reserved[543]; + uint32_t wacs2_cmd; + uint32_t wacs2_wdata; + uint32_t reserved1[3]; + uint32_t wacs2_rdata; + uint32_t reserved2[3]; + uint32_t wacs2_vldclr; + uint32_t wacs2_sta; +}; + +#define GET_WACS_FSM(x) ((x >> 1) & 0x7) + +/* macro for SWINF_FSM */ +#define SWINF_FSM_IDLE (0x00) +#define SWINF_FSM_REQ (0x02) +#define SWINF_FSM_WFDLE (0x04) +#define SWINF_FSM_WFVLDCLR (0x06) +#define SWINF_INIT_DONE (0x01) + +/* timeout setting */ +#define PWRAP_READ_US 1000 +#define PWRAP_WAIT_IDLE_US 1000 + +/* error information flag */ +enum pwrap_errno { + E_PWR_INVALID_ARG = 1, + E_PWR_INVALID_RW = 2, + E_PWR_INVALID_ADDR = 3, + E_PWR_INVALID_WDAT = 4, + E_PWR_INVALID_OP_MANUAL = 5, + E_PWR_NOT_IDLE_STATE = 6, + E_PWR_NOT_INIT_DONE = 7, + E_PWR_NOT_INIT_DONE_READ = 8, + E_PWR_WAIT_IDLE_TIMEOUT = 9, + E_PWR_WAIT_IDLE_TIMEOUT_READ = 10, + E_PWR_INIT_SIDLY_FAIL = 11, + E_PWR_RESET_TIMEOUT = 12, + E_PWR_TIMEOUT = 13, + E_PWR_INIT_RESET_SPI = 20, + E_PWR_INIT_SIDLY = 21, + E_PWR_INIT_REG_CLOCK = 22, + E_PWR_INIT_ENABLE_PMIC = 23, + E_PWR_INIT_DIO = 24, + E_PWR_INIT_CIPHER = 25, + E_PWR_INIT_WRITE_TEST = 26, + E_PWR_INIT_ENABLE_CRC = 27, + E_PWR_INIT_ENABLE_DEWRAP = 28, + E_PWR_INIT_ENABLE_EVENT = 29, + E_PWR_READ_TEST_FAIL = 30, + E_PWR_WRITE_TEST_FAIL = 31, + E_PWR_SWITCH_DIO = 32 +}; + +#endif /* PMIC_WRAP_INIT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h new file mode 100644 index 0000000..341cf86 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_PTP3_COMMON_H +#define MTK_PTP3_COMMON_H + +#include +#include + +/************************************************ + * CPU info + ************************************************/ +#define NR_PTP3_CFG_CPU U(8) +#define PTP3_CFG_CPU_START_ID_L U(0) +#define PTP3_CFG_CPU_START_ID_B U(4) +#define PTP3_CFG_CPU_END_ID U(7) + +#define NR_PTP3_CFG1_DATA U(2) +#define PTP3_CFG1_MASK 0x3000 + +#define NR_PTP3_CFG2_DATA U(5) + +#define PTP3_CFG3_MASK1 0x1180 +#define PTP3_CFG3_MASK2 0x35C0 +#define PTP3_CFG3_MASK3 0x3DC0 + +/************************************************ + * register read/write + ************************************************/ +#define ptp3_write(addr, val) mmio_write_32((uintptr_t)addr, val) +#define ptp3_clrsetbits(addr, clear, set) \ + mmio_clrsetbits_32((uintptr_t)addr, clear, set) + +/************************************************ + * config enum + ************************************************/ +enum PTP3_CFG { + PTP3_CFG_ADDR, + PTP3_CFG_VALUE, + NR_PTP3_CFG, +}; + +/************************************ + * prototype + ************************************/ +extern void ptp3_core_init(unsigned int core); +extern void ptp3_core_unInit(unsigned int core); + +#endif /* MTK_PTP3_COMMON_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c new file mode 100644 index 0000000..540cb33 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. \ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define PTP3_CORE_OFT(core) (0x800 * (core)) + +/************************************************ + * Central control + ************************************************/ +static unsigned int ptp3_cfg1[NR_PTP3_CFG1_DATA][NR_PTP3_CFG] = { + {0x0C53A2A0, 0x1000}, + {0x0C53A2A4, 0x1000} +}; + +static unsigned int ptp3_cfg2[NR_PTP3_CFG2_DATA][NR_PTP3_CFG] = { + {0x0C530404, 0x3A1000}, + {0x0C530428, 0x13E0408}, + {0x0C530434, 0xB22800}, + {0x0C53043C, 0x750}, + {0x0C530440, 0x0222c4cc} +}; + +static unsigned int ptp3_cfg3[NR_PTP3_CFG] = {0x0C530400, 0x2D80}; +static unsigned int ptp3_cfg3_ext[NR_PTP3_CFG] = {0x0C530400, 0xC00}; + +static void ptp3_init(unsigned int core) +{ + unsigned int i, addr, value; + + if (core < PTP3_CFG_CPU_START_ID_B) { + ptp3_clrsetbits(ptp3_cfg1[0][PTP3_CFG_ADDR], PTP3_CFG1_MASK, + ptp3_cfg1[0][PTP3_CFG_VALUE]); + } else { + ptp3_clrsetbits(ptp3_cfg1[1][PTP3_CFG_ADDR], PTP3_CFG1_MASK, + ptp3_cfg1[1][PTP3_CFG_VALUE]); + } + + if (core < PTP3_CFG_CPU_START_ID_B) { + for (i = 0; i < NR_PTP3_CFG2_DATA; i++) { + addr = ptp3_cfg2[i][PTP3_CFG_ADDR] + + PTP3_CORE_OFT(core); + value = ptp3_cfg2[i][PTP3_CFG_VALUE]; + + ptp3_write(addr, value); + } + } else { + for (i = 0; i < NR_PTP3_CFG2_DATA; i++) { + addr = ptp3_cfg2[i][PTP3_CFG_ADDR] + + PTP3_CORE_OFT(core); + + if (i == 2) { + value = ptp3_cfg2[i][PTP3_CFG_VALUE] + 0x5E0; + } else { + value = ptp3_cfg2[i][PTP3_CFG_VALUE]; + } + ptp3_write(addr, value); + } + } + + if (core < PTP3_CFG_CPU_START_ID_B) { + addr = ptp3_cfg3[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core); + value = ptp3_cfg3[PTP3_CFG_VALUE]; + + ptp3_write(addr, value & PTP3_CFG3_MASK1); + ptp3_write(addr, value & PTP3_CFG3_MASK2); + ptp3_write(addr, value & PTP3_CFG3_MASK3); + } else { + addr = ptp3_cfg3_ext[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core); + value = ptp3_cfg3_ext[PTP3_CFG_VALUE]; + + ptp3_write(addr, value & PTP3_CFG3_MASK1); + ptp3_write(addr, value & PTP3_CFG3_MASK2); + ptp3_write(addr, value & PTP3_CFG3_MASK3); + } +} + +void pdp_proc_ARM_write(unsigned int pdp_n) +{ + unsigned long v = 0; + + dsb(); + __asm__ volatile ("mrs %0, S3_6_C15_C2_0" : "=r" (v)); + v |= (UL(0x0) << 52); + v |= (UL(0x1) << 53); + v |= (UL(0x0) << 54); + v |= (UL(0x0) << 48); + v |= (UL(0x1) << 49); + __asm__ volatile ("msr S3_6_C15_C2_0, %0" : : "r" (v)); + dsb(); +} + +void pdp_init(unsigned int pdp_cpu, unsigned int en) +{ + if ((pdp_cpu >= PTP3_CFG_CPU_START_ID_B) && + (pdp_cpu < NR_PTP3_CFG_CPU)) { + pdp_proc_ARM_write(pdp_cpu); + } +} + +static void dt_proc_ARM_write(unsigned int dt_n) +{ + unsigned long v = 0; + + dsb(); + __asm__ volatile ("mrs %0, S3_6_C15_C2_0" : "=r" (v)); + v |= (UL(0x0) << 33); + v |= (UL(0x0) << 32); + __asm__ volatile ("msr S3_6_C15_C2_0, %0" : : "r" (v)); + dsb(); +} + +void dt_init(unsigned int dt_cpu, unsigned int en) +{ + if ((dt_cpu >= PTP3_CFG_CPU_START_ID_B) && + (dt_cpu < NR_PTP3_CFG_CPU)) { + dt_proc_ARM_write(dt_cpu); + } +} +void ptp3_core_init(unsigned int core) +{ + /* init for ptp3 */ + ptp3_init(core); + /* init for pdp */ + pdp_init(core, 1); + /* init for dt */ + dt_init(core, 1); +} + +void ptp3_core_unInit(unsigned int core) +{ + /* TBD */ +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/build.mk b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/build.mk new file mode 100644 index 0000000..28b2d07 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/build.mk @@ -0,0 +1,68 @@ +# +# Copyright (c) 2021, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Enable or disable spm feature +MT_SPM_FEATURE_SUPPORT = yes + +# Enable or disable cirq restore +MT_SPM_CIRQ_FEATURE_SUPPORT = yes + +# sspm notifier support +MT_SPM_SSPM_NOTIFIER_SUPPORT = yes + +CUR_SPM_FOLDER = ${MTK_PLAT_SOC}/drivers/spm + +# spm common files +PLAT_SPM_SOURCE_FILES_COMMON += \ + ${CUR_SPM_FOLDER}/mt_spm.c \ + ${CUR_SPM_FOLDER}/mt_spm_conservation.c \ + ${CUR_SPM_FOLDER}/mt_spm_internal.c \ + ${CUR_SPM_FOLDER}/mt_spm_pmic_wrap.c + +# spm platform dependcy files +PLAT_SPM_SOURCE_FILES += \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_bus26m.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_cpu_buck_ldo.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_dram.c \ + ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c \ + ${CUR_SPM_FOLDER}/mt_spm_cond.c \ + ${CUR_SPM_FOLDER}/mt_spm_suspend.c \ + ${CUR_SPM_FOLDER}/mt_spm_idle.c \ + ${CUR_SPM_FOLDER}/mt_spm_vcorefs.c + +ifeq (${MT_SPM_FEATURE_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${PLAT_SPM_SOURCE_FILES_COMMON} +else +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \ + ${PLAT_SPM_SOURCE_FILES_COMMON} \ + ${PLAT_SPM_SOURCE_FILES} +endif + +ifeq (${MT_SPM_CIRQ_FEATURE_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_CIRQ_UNSUPPORT +endif + +ifeq (${MT_SPM_SSPM_NOTIFIER_SUPPORT}, no) +PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT +else +BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \ + ${CUR_SPM_FOLDER}/notifier/mt_spm_sspm_notifier.c +endif + +$(info --------------------------------------) +$(info SPM build flags: ${PLAT_SPM_DEBUG_CFLAGS}) +$(info SPM build files: ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES}) +$(info --------------------------------------) + +# Common makefile for platform.mk +PLAT_INCLUDES += \ + ${PLAT_SPM_DEBUG_CFLAGS} \ + -I${CUR_SPM_FOLDER}/ \ + -I${CUR_SPM_FOLDER}/constraints/ \ + -I${CUR_SPM_FOLDER}/notifier/ + +PLAT_BL_COMMON_SOURCES += ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c new file mode 100644 index 0000000..d2ad282 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2021, MediaTek Inc. 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 + +#ifndef ATF_PLAT_CIRQ_UNSUPPORT +#include +#include +#endif + +#define CONSTRAINT_BUS26M_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \ + MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \ + MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF) + +#define CONSTRAINT_BUS26M_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_ENABLE_TIA_WORKAROUND | \ + SPM_FLAG_ENABLE_LVTS_WORKAROUND | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP) + +#define CONSTRAINT_BUS26M_PCM_FLAG1 0U + +#define CONSTRAINT_BUS26M_RESOURCE_REQ 0U + +static unsigned int bus26m_ext_opand; +static struct mt_irqremain *refer2remain_irq; +static struct mt_spm_cond_tables cond_bus26m = { + .name = "bus26m", + .table_cg = { + 0xFFFFD408, /* MTCMOS1 */ + 0x2284C802, /* INFRA0 */ + 0x27AF8000, /* INFRA1 */ + 0x86040650, /* INFRA2 */ + 0x30038020, /* INFRA3 */ + 0x80000000, /* INFRA4 */ + 0x00080ABB, /* PERI0 */ + 0x00004000, /* VPPSYS0_0 */ + 0x08803000, /* VPPSYS0_1 */ + 0x00000000, /* VPPSYS0_2 */ + 0x80005555, /* VPPSYS1_0 */ + 0x00009008, /* VPPSYS1_1 */ + 0x60060000, /* VDOSYS0_0 */ + 0x00000000, /* VDOSYS0_1 */ + 0x201E01F8, /* VDOSYS1_0 */ + 0x00800000, /* VDOSYS1_1 */ + 0x00000000, /* VDOSYS1_2 */ + 0x00000080, /* I2C */ + }, + .table_pll = (PLL_BIT_UNIVPLL | + PLL_BIT_MFGPLL | + PLL_BIT_MSDCPLL | + PLL_BIT_TVDPLL | + PLL_BIT_MMPLL), +}; + +static struct mt_spm_cond_tables cond_bus26m_res = { + .table_cg = { 0U }, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_BUS26M, + .valid = (MT_SPM_RC_VALID_SW | + MT_SPM_RC_VALID_COND_LATCH), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_bus26m_res, +}; + +/* + * Cirq will take the place of gic when gic is off. + * However, cirq cannot work if 26m clk is turned off when system idle/suspend. + * Therefore, we need to set irq pending for specific wakeup source. + */ +#ifdef ATF_PLAT_CIRQ_UNSUPPORT +#define do_irqs_delivery() +#else +static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs, + unsigned int irq_index, + struct wake_status *wakeup) +{ + INFO("[SPM] r12 = 0x%08x(0x%08x), flag = 0x%08x 0x%08x 0x%08x\n", + wakeup->tr.comm.r12, wakeup->md32pcm_wakeup_sta, + wakeup->tr.comm.debug_flag, wakeup->tr.comm.b_sw_flag0, + wakeup->tr.comm.b_sw_flag1); + + INFO("irq:%u(0x%08x) set pending\n", + irqs->wakeupsrc[irq_index], irqs->irqs[irq_index]); +} + +static void do_irqs_delivery(void) +{ + unsigned int idx; + int res = 0; + struct wake_status *wakeup = NULL; + struct mt_irqremain *irqs = refer2remain_irq; + + res = spm_conservation_get_result(&wakeup); + + if ((res != 0) && (irqs == NULL)) { + return; + } + + for (idx = 0U; idx < irqs->count; ++idx) { + if (((wakeup->tr.comm.r12 & irqs->wakeupsrc[idx]) != 0U) || + ((wakeup->raw_sta & irqs->wakeupsrc[idx]) != 0U)) { + if ((irqs->wakeupsrc_cat[idx] & + MT_IRQ_REMAIN_CAT_LOG) != 0U) { + mt_spm_irq_remain_dump(irqs, idx, wakeup); + } + + mt_irq_set_pending(irqs->irqs[idx]); + } + } +} +#endif + +static void spm_bus26m_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG1; + *resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ; +} + +bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid); +} + +int spm_update_rc_bus26m(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + return MT_RM_STATUS_BAD; + } + + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_bus26m; + + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + &cond_bus26m_res : NULL); + } else if (type == PLAT_RC_UPDATE_REMAIN_IRQS) { + refer2remain_irq = (struct mt_irqremain *)val; + } else { + res = MT_RM_STATUS_BAD; + } + + return res; +} + +unsigned int spm_allow_rc_bus26m(int state_id) +{ + (void)state_id; + + return CONSTRAINT_BUS26M_ALLOW; +} + +int spm_run_rc_bus26m(unsigned int cpu, int state_id) +{ + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, CONSTRAINT_BUS26M_ALLOW | + (IS_PLAT_SUSPEND_ID(state_id) ? + MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U)); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT | + MT_SPM_EX_OP_SET_SUSPEND_MODE | + bus26m_ext_opand), + CONSTRAINT_BUS26M_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, MT_SPM_EX_OP_HW_S1_DETECT, + spm_bus26m_conduct); + } + + return 0; +} + +int spm_reset_rc_bus26m(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + ext_op |= (bus26m_ext_opand | MT_SPM_EX_OP_SET_WDT); + mt_spm_suspend_resume(state_id, ext_op, NULL); + bus26m_ext_opand = 0U; + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL); + status.enter_cnt++; + } + + do_irqs_delivery(); + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c new file mode 100644 index 0000000..cf71350 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONSTRAINT_CPU_BUCK_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP |\ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH) + +#define CONSTRAINT_CPU_BUCK_PCM_FLAG1 0U + +#define CONSTRAINT_CPU_BUCK_RESOURCE_REQ \ + (MT_SPM_DRAM_S1 | \ + MT_SPM_DRAM_S0 | \ + MT_SPM_SYSPLL | \ + MT_SPM_INFRA | \ + MT_SPM_26M | \ + MT_SPM_XO_FPM) + + +static unsigned int cpubuckldo_status = MT_SPM_RC_VALID_SW; +static unsigned int cpubuckldo_enter_cnt; + +static void spm_cpu_bcuk_ldo_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1; + *resource_req |= CONSTRAINT_CPU_BUCK_RESOURCE_REQ; +} + +bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return IS_MT_RM_RC_READY(cpubuckldo_status); +} + +unsigned int spm_allow_rc_cpu_buck_ldo(int state_id) +{ + (void)state_id; + + return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF; +} + +int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, + (IS_PLAT_SUSPEND_ID(state_id) ? + MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U)); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + MT_SPM_EX_OP_SET_SUSPEND_MODE | + MT_SPM_EX_OP_SET_WDT, + CONSTRAINT_CPU_BUCK_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, 0U, + spm_cpu_bcuk_ldo_conduct); + } + + cpubuckldo_enter_cnt++; + + return 0; +} + +int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id) +{ + (void)cpu; + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U); +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL); + } else { + mt_spm_idle_generic_resume(state_id, 0U, NULL); + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c new file mode 100644 index 0000000..bd24ddd --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2021, MediaTek Inc. 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 + +#define CONSTRAINT_DRAM_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF) + +#define CONSTRAINT_DRAM_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP) + +#define CONSTRAINT_DRAM_PCM_FLAG1 0U + +#define CONSTRAINT_DRAM_RESOURCE_REQ \ + (MT_SPM_SYSPLL | \ + MT_SPM_INFRA | \ + MT_SPM_26M) + +static struct mt_spm_cond_tables cond_dram = { + .name = "dram", + .table_cg = { + 0xFFFDD008, /* MTCMOS1 */ + 0x20040802, /* INFRA0 */ + 0x27AF8000, /* INFRA1 */ + 0x86040640, /* INFRA2 */ + 0x00000000, /* INFRA3 */ + 0x80000000, /* INFRA4 */ + 0x00000000, /* PERI0 */ + 0x00004000, /* VPPSYS0_0 */ + 0x08803000, /* VPPSYS0_1 */ + 0x00000000, /* VPPSYS0_2 */ + 0x80005555, /* VPPSYS1_0 */ + 0x00009008, /* VPPSYS1_1 */ + 0x60060000, /* VDOSYS0_0 */ + 0x00000000, /* VDOSYS0_1 */ + 0x201E01F8, /* VDOSYS1_0 */ + 0x00800000, /* VDOSYS1_1 */ + 0x00000000, /* VDOSYS1_2 */ + 0x00000080, /* I2C */ + }, + .table_pll = 0U, +}; + +static struct mt_spm_cond_tables cond_dram_res = { + .table_cg = { 0U }, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_DRAM, + .valid = (MT_SPM_RC_VALID_SW | + MT_SPM_RC_VALID_COND_LATCH | + MT_SPM_RC_VALID_XSOC_BBLPM), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_dram_res, +}; + +static void spm_dram_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG1; + *resource_req |= CONSTRAINT_DRAM_RESOURCE_REQ; +} + +bool spm_is_valid_rc_dram(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid); +} + +int spm_update_rc_dram(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + return MT_RM_STATUS_BAD; + } + + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_dram; + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + &cond_dram_res : NULL); + } else { + res = MT_RM_STATUS_BAD; + } + + return res; +} + +unsigned int spm_allow_rc_dram(int state_id) +{ + (void)state_id; + + return CONSTRAINT_DRAM_ALLOW; +} + +int spm_run_rc_dram(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_DRAM_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | + (IS_PLAT_SUSPEND_ID(state_id) ? + MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U)); +#else + (void)allows; +#endif + + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_SET_SUSPEND_MODE | + MT_SPM_EX_OP_HW_S1_DETECT), + CONSTRAINT_DRAM_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, ext_op, spm_dram_conduct); + } + + return 0; +} + +int spm_reset_rc_dram(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_DRAM_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows); +#else + (void)allows; +#endif + + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT), + NULL); + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL); + status.enter_cnt++; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h new file mode 100644 index 0000000..9e74ace --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_RC_INTERNAL_H +#define MT_SPM_RC_INTERNAL_H + +#include + +#define SPM_FLAG_SRAM_SLEEP_CTRL \ + (SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \ + SPM_FLAG_DISABLE_SYSRAM_SLEEP) + +/* cpu buck/ldo constraint function */ +bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id); +unsigned int spm_allow_rc_cpu_buck_ldo(int state_id); +int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id); +int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id); + +/* spm resource dram constraint function */ +bool spm_is_valid_rc_dram(unsigned int cpu, int state_id); +int spm_update_rc_dram(int state_id, int type, const void *val); +unsigned int spm_allow_rc_dram(int state_id); +int spm_run_rc_dram(unsigned int cpu, int state_id); +int spm_reset_rc_dram(unsigned int cpu, int state_id); + +/* spm resource syspll constraint function */ +bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id); +int spm_update_rc_syspll(int state_id, int type, const void *val); +unsigned int spm_allow_rc_syspll(int state_id); +int spm_run_rc_syspll(unsigned int cpu, int state_id); +int spm_reset_rc_syspll(unsigned int cpu, int state_id); + +/* spm resource bus26m constraint function */ +bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id); +int spm_update_rc_bus26m(int state_id, int type, const void *val); +unsigned int spm_allow_rc_bus26m(int state_id); +int spm_run_rc_bus26m(unsigned int cpu, int state_id); +int spm_reset_rc_bus26m(unsigned int cpu, int state_id); +#endif /* MT_SPM_RC_INTERNAL_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c new file mode 100644 index 0000000..662f85e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONSTRAINT_SYSPLL_ALLOW \ + (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ + MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ + MT_RM_CONSTRAINT_ALLOW_VCORE_LP) + +#define CONSTRAINT_SYSPLL_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_SRAM_SLEEP_CTRL | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ + SPM_FLAG_ENABLE_6315_CTRL | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP |\ + SPM_FLAG_USE_SRCCLKENO2) + +#define CONSTRAINT_SYSPLL_PCM_FLAG1 0U +#define CONSTRAINT_SYSPLL_RESOURCE_REQ (MT_SPM_26M) + +static struct mt_spm_cond_tables cond_syspll = { + .name = "syspll", + .table_cg = { + 0xFFFFD008, /* MTCMOS1 */ + 0x20844802, /* INFRA0 */ + 0x27AF8000, /* INFRA1 */ + 0x86040640, /* INFRA2 */ + 0x30038020, /* INFRA3 */ + 0x80000000, /* INFRA4 */ + 0x00080A8B, /* PERI0 */ + 0x00004000, /* VPPSYS0_0 */ + 0x08803000, /* VPPSYS0_1 */ + 0x00000000, /* VPPSYS0_2 */ + 0x80005555, /* VPPSYS1_0 */ + 0x00009008, /* VPPSYS1_1 */ + 0x60060000, /* VDOSYS0_0 */ + 0x00000000, /* VDOSYS0_1 */ + 0x201E01F8, /* VDOSYS1_0 */ + 0x00800000, /* VDOSYS1_1 */ + 0x00000000, /* VDOSYS1_2 */ + 0x00000080, /* I2C */ + }, + .table_pll = 0U, +}; + +static struct mt_spm_cond_tables cond_syspll_res = { + .table_cg = { 0U }, + .table_pll = 0U, +}; + +static struct constraint_status status = { + .id = MT_RM_CONSTRAINT_ID_SYSPLL, + .valid = (MT_SPM_RC_VALID_SW | + MT_SPM_RC_VALID_COND_LATCH | + MT_SPM_RC_VALID_XSOC_BBLPM), + .cond_block = 0U, + .enter_cnt = 0U, + .cond_res = &cond_syspll_res, +}; + +static void spm_syspll_conduct(struct spm_lp_scen *spm_lp, + unsigned int *resource_req) +{ + spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG; + spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG1; + *resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ; +} + +bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id) +{ + (void)cpu; + (void)state_id; + + return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid); +} + +int spm_update_rc_syspll(int state_id, int type, const void *val) +{ + const struct mt_spm_cond_tables *tlb; + const struct mt_spm_cond_tables *tlb_check; + int res = MT_RM_STATUS_OK; + + if (val == NULL) { + return MT_RM_STATUS_BAD; + } + + if (type == PLAT_RC_UPDATE_CONDITION) { + tlb = (const struct mt_spm_cond_tables *)val; + tlb_check = (const struct mt_spm_cond_tables *)&cond_syspll; + + status.cond_block = + mt_spm_cond_check(state_id, tlb, tlb_check, + ((status.valid & + MT_SPM_RC_VALID_COND_LATCH) != 0U) ? + &cond_syspll_res : NULL); + } else { + res = MT_RM_STATUS_BAD; + } + + return res; +} + +unsigned int spm_allow_rc_syspll(int state_id) +{ + (void)state_id; + + return CONSTRAINT_SYSPLL_ALLOW; +} + +int spm_run_rc_syspll(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_SYSPLL_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | + (IS_PLAT_SUSPEND_ID(state_id) ? + MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U)); +#else + (void)allows; +#endif + + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_enter(state_id, + (MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT | + MT_SPM_EX_OP_SET_SUSPEND_MODE), + CONSTRAINT_SYSPLL_RESOURCE_REQ); + } else { + mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct); + } + + return 0; +} + +int spm_reset_rc_syspll(unsigned int cpu, int state_id) +{ + unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; + unsigned int allows = CONSTRAINT_SYSPLL_ALLOW; + + (void)cpu; + + if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { +#ifdef MT_SPM_USING_SRCLKEN_RC + ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; +#else + allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; +#endif + } + +#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT + mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows); +#else + (void)allows; +#endif + if (IS_PLAT_SUSPEND_ID(state_id)) { + mt_spm_suspend_resume(state_id, + (MT_SPM_EX_OP_SET_SUSPEND_MODE | + MT_SPM_EX_OP_SET_WDT | + MT_SPM_EX_OP_HW_S1_DETECT), + NULL); + } else { + mt_spm_idle_generic_resume(state_id, ext_op, NULL); + status.enter_cnt++; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c new file mode 100644 index 0000000..f708bf5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021, MediaTek Inc. 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 + +#ifdef MT_SPM_USING_BAKERY_LOCK +DEFINE_BAKERY_LOCK(spm_lock); +#define plat_spm_lock_init() bakery_lock_init(&spm_lock) +#else +spinlock_t spm_lock; +#define plat_spm_lock_init() +#endif + +/* CLK_SCP_CFG_0 */ +#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x264) +#define SPM_CK_CONTROL_EN 0x7FF + +struct mt_resource_constraint plat_constraint_bus26m = { + .is_valid = spm_is_valid_rc_bus26m, + .update = spm_update_rc_bus26m, + .allow = spm_allow_rc_bus26m, + .run = spm_run_rc_bus26m, + .reset = spm_reset_rc_bus26m, +}; + +struct mt_resource_constraint plat_constraint_syspll = { + .is_valid = spm_is_valid_rc_syspll, + .update = spm_update_rc_syspll, + .allow = spm_allow_rc_syspll, + .run = spm_run_rc_syspll, + .reset = spm_reset_rc_syspll, +}; + +struct mt_resource_constraint plat_constraint_dram = { + .is_valid = spm_is_valid_rc_dram, + .update = spm_update_rc_dram, + .allow = spm_allow_rc_dram, + .run = spm_run_rc_dram, + .reset = spm_reset_rc_dram, +}; + +struct mt_resource_constraint plat_constraint_cpu = { + .is_valid = spm_is_valid_rc_cpu_buck_ldo, + .update = NULL, + .allow = spm_allow_rc_cpu_buck_ldo, + .run = spm_run_rc_cpu_buck_ldo, + .reset = spm_reset_rc_cpu_buck_ldo, +}; + +struct mt_resource_constraint *plat_constraints[] = { + &plat_constraint_bus26m, + &plat_constraint_syspll, + &plat_constraint_dram, + &plat_constraint_cpu, + NULL, +}; + +struct mt_resource_manager plat_mt8195_rm = { + .update = mt_spm_cond_update, + .consts = plat_constraints, +}; + +void spm_boot_init(void) +{ + NOTICE("MT8195 %s\n", __func__); + /* switch ck_off/axi_26m control to SPM */ + mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_CONTROL_EN); + + plat_spm_lock_init(); + mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE); + mt_lp_rm_register(&plat_mt8195_rm); + mt_spm_idle_generic_init(); + mt_spm_suspend_init(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h new file mode 100644 index 0000000..bc57b61 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_H +#define MT_SPM_H + +#include +#include + +#include + +/* + * ARM v8.2, the cache will turn off automatically when cpu + * power down. So, there is no doubt to use the spin_lock here + */ +#if !HW_ASSISTED_COHERENCY +#define MT_SPM_USING_BAKERY_LOCK +#endif + +#ifdef MT_SPM_USING_BAKERY_LOCK +DECLARE_BAKERY_LOCK(spm_lock); +#define plat_spm_lock() bakery_lock_get(&spm_lock) +#define plat_spm_unlock() bakery_lock_release(&spm_lock) +#else +extern spinlock_t spm_lock; +#define plat_spm_lock() spin_lock(&spm_lock) +#define plat_spm_unlock() spin_unlock(&spm_lock) +#endif + +#define MT_SPM_USING_SRCLKEN_RC + +/* spm extern operand definition */ +#define MT_SPM_EX_OP_CLR_26M_RECORD (1U << 0) +#define MT_SPM_EX_OP_SET_WDT (1U << 1) +#define MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ (1U << 2) +#define MT_SPM_EX_OP_SET_SUSPEND_MODE (1U << 3) +#define MT_SPM_EX_OP_SET_IS_ADSP (1U << 4) +#define MT_SPM_EX_OP_SRCLKEN_RC_BBLPM (1U << 5) +#define MT_SPM_EX_OP_HW_S1_DETECT (1U << 6) + +typedef enum { + WR_NONE = 0, + WR_UART_BUSY = 1, + WR_ABORT = 2, + WR_PCM_TIMER = 3, + WR_WAKE_SRC = 4, + WR_DVFSRC = 5, + WR_TWAM = 6, + WR_PMSR = 7, + WR_SPM_ACK_CHK = 8, + WR_UNKNOWN = 9, +} wake_reason_t; + +static inline void spm_lock_get(void) +{ + plat_spm_lock(); +} + +static inline void spm_lock_release(void) +{ + plat_spm_unlock(); +} + +extern void spm_boot_init(void); +#endif /* MT_SPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c new file mode 100644 index 0000000..c80faf5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define MT_LP_TZ_INFRA_REG(ofs) (INFRACFG_AO_BASE + ofs) +#define MT_LP_TZ_SPM_REG(ofs) (SPM_BASE + ofs) +#define MT_LP_TZ_TOPCK_REG(ofs) (TOPCKGEN_BASE + ofs) +#define MT_LP_TZ_APMIXEDSYS(ofs) (APMIXEDSYS + ofs) +#define MT_LP_TZ_VPPSYS0_REG(ofs) (VPPSYS0_BASE + ofs) +#define MT_LP_TZ_VPPSYS1_REG(ofs) (VPPSYS1_BASE + ofs) +#define MT_LP_TZ_VDOSYS0_REG(ofs) (VDOSYS0_BASE + ofs) +#define MT_LP_TZ_VDOSYS1_REG(ofs) (VDOSYS1_BASE + ofs) +#define MT_LP_TZ_PERI_AO_REG(ofs) (PERICFG_AO_BASE + ofs) + +#define SPM_PWR_STATUS MT_LP_TZ_SPM_REG(0x016C) +#define SPM_PWR_STATUS_2ND MT_LP_TZ_SPM_REG(0x0170) +#define INFRA_SW_CG0 MT_LP_TZ_INFRA_REG(0x0094) +#define INFRA_SW_CG1 MT_LP_TZ_INFRA_REG(0x0090) +#define INFRA_SW_CG2 MT_LP_TZ_INFRA_REG(0x00AC) +#define INFRA_SW_CG3 MT_LP_TZ_INFRA_REG(0x00C8) +#define INFRA_SW_CG4 MT_LP_TZ_INFRA_REG(0x00E8) +#define TOP_SW_I2C_CG MT_LP_TZ_TOPCK_REG(0x00BC) +#define PERI_SW_CG0 MT_LP_TZ_PERI_AO_REG(0x0018) +#define VPPSYS0_SW_CG0 MT_LP_TZ_VPPSYS0_REG(0x0020) +#define VPPSYS0_SW_CG1 MT_LP_TZ_VPPSYS0_REG(0x002C) +#define VPPSYS0_SW_CG2 MT_LP_TZ_VPPSYS0_REG(0x0038) +#define VPPSYS1_SW_CG0 MT_LP_TZ_VPPSYS1_REG(0x0100) +#define VPPSYS1_SW_CG1 MT_LP_TZ_VPPSYS1_REG(0x0110) +#define VDOSYS0_SW_CG0 MT_LP_TZ_VDOSYS0_REG(0x0100) +#define VDOSYS0_SW_CG1 MT_LP_TZ_VDOSYS0_REG(0x0110) +#define VDOSYS1_SW_CG0 MT_LP_TZ_VDOSYS1_REG(0x0100) +#define VDOSYS1_SW_CG1 MT_LP_TZ_VDOSYS1_REG(0x0120) +#define VDOSYS1_SW_CG2 MT_LP_TZ_VDOSYS1_REG(0x0130) + +/*********************************************************** + * Check clkmux registers + ***********************************************************/ +#define CLK_CFG(id) MT_LP_TZ_TOPCK_REG(0x98 + id * 0x10) +#define PDN_CHECK BIT(7) +#define CLK_CHECK BIT(31) + +enum { + CLKMUX_DISP = 0, + NF_CLKMUX, +}; + +static bool is_clkmux_pdn(unsigned int clkmux_id) +{ + unsigned int reg, val, idx; + + if ((clkmux_id & CLK_CHECK) != 0U) { + clkmux_id = (clkmux_id & ~CLK_CHECK); + reg = clkmux_id / 4U; + val = mmio_read_32(CLK_CFG(reg)); + idx = clkmux_id % 4U; + val = (val >> (idx * 8U)) & PDN_CHECK; + return (val != 0U); + } + + return false; +} + +static struct mt_spm_cond_tables spm_cond_t; + +struct idle_cond_info { + unsigned int subsys_mask; + uintptr_t addr; + bool bBitflip; + unsigned int clkmux_id; +}; + +#define IDLE_CG(mask, addr, bitflip, clkmux) \ + {mask, (uintptr_t)addr, bitflip, clkmux} + +static struct idle_cond_info idle_cg_info[PLAT_SPM_COND_MAX] = { + IDLE_CG(0xffffffff, SPM_PWR_STATUS, false, 0U), + IDLE_CG(0xffffffff, INFRA_SW_CG0, true, 0U), + IDLE_CG(0xffffffff, INFRA_SW_CG1, true, 0U), + IDLE_CG(0xffffffff, INFRA_SW_CG2, true, 0U), + IDLE_CG(0xffffffff, INFRA_SW_CG3, true, 0U), + IDLE_CG(0xffffffff, INFRA_SW_CG4, true, 0U), + IDLE_CG(0xffffffff, PERI_SW_CG0, true, 0U), + IDLE_CG(0x00000800, VPPSYS0_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00000800, VPPSYS0_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00000800, VPPSYS0_SW_CG2, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00001000, VPPSYS1_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00001000, VPPSYS1_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00002000, VDOSYS0_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00002000, VDOSYS0_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00004000, VDOSYS1_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00004000, VDOSYS1_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00004000, VDOSYS1_SW_CG2, true, (CLK_CHECK|CLKMUX_DISP)), + IDLE_CG(0x00000080, TOP_SW_I2C_CG, true, (CLK_CHECK|CLKMUX_DISP)), +}; + +/*********************************************************** + * Check pll idle condition + ***********************************************************/ +#define PLL_MFGPLL MT_LP_TZ_APMIXEDSYS(0x340) +#define PLL_MMPLL MT_LP_TZ_APMIXEDSYS(0x0E0) +#define PLL_UNIVPLL MT_LP_TZ_APMIXEDSYS(0x1F0) +#define PLL_MSDCPLL MT_LP_TZ_APMIXEDSYS(0x710) +#define PLL_TVDPLL MT_LP_TZ_APMIXEDSYS(0x380) + +unsigned int mt_spm_cond_check(int state_id, + const struct mt_spm_cond_tables *src, + const struct mt_spm_cond_tables *dest, + struct mt_spm_cond_tables *res) +{ + unsigned int blocked = 0U, i; + bool is_system_suspend = IS_PLAT_SUSPEND_ID(state_id); + + if ((src == NULL) || (dest == NULL)) { + return SPM_COND_CHECK_FAIL; + } + + for (i = 0U; i < PLAT_SPM_COND_MAX; i++) { + if (res != NULL) { + res->table_cg[i] = + (src->table_cg[i] & dest->table_cg[i]); + + if (is_system_suspend && (res->table_cg[i] != 0U)) { + INFO("suspend: %s block[%u](0x%lx) = 0x%08x\n", + dest->name, i, idle_cg_info[i].addr, + res->table_cg[i]); + } + + if (res->table_cg[i] != 0U) { + blocked |= (1U << i); + } + } else if ((src->table_cg[i] & dest->table_cg[i]) != 0U) { + blocked |= (1U << i); + break; + } + } + + if (res != NULL) { + res->table_pll = (src->table_pll & dest->table_pll); + + if (res->table_pll != 0U) { + blocked |= + (res->table_pll << SPM_COND_BLOCKED_PLL_IDX) | + SPM_COND_CHECK_BLOCKED_PLL; + } + } else if ((src->table_pll & dest->table_pll) != 0U) { + blocked |= SPM_COND_CHECK_BLOCKED_PLL; + } + + if (is_system_suspend && (blocked != 0U)) { + INFO("suspend: %s blocked=0x%08x\n", dest->name, blocked); + } + + return blocked; +} + +#define IS_MT_SPM_PWR_OFF(mask) \ + (((mmio_read_32(SPM_PWR_STATUS) & mask) == 0U) && \ + ((mmio_read_32(SPM_PWR_STATUS_2ND) & mask) == 0U)) + +int mt_spm_cond_update(struct mt_resource_constraint **con, + int stateid, void *priv) +{ + int res; + uint32_t i; + struct mt_resource_constraint *const *rc; + + /* read all cg state */ + for (i = 0U; i < PLAT_SPM_COND_MAX; i++) { + spm_cond_t.table_cg[i] = 0U; + + /* check mtcmos, if off set idle_value and clk to 0 disable */ + if (IS_MT_SPM_PWR_OFF(idle_cg_info[i].subsys_mask)) { + continue; + } + + /* check clkmux */ + if (is_clkmux_pdn(idle_cg_info[i].clkmux_id)) { + continue; + } + + spm_cond_t.table_cg[i] = idle_cg_info[i].bBitflip ? + ~mmio_read_32(idle_cg_info[i].addr) : + mmio_read_32(idle_cg_info[i].addr); + } + + spm_cond_t.table_pll = 0U; + if ((mmio_read_32(PLL_MFGPLL) & 0x200) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MFGPLL; + } + + if ((mmio_read_32(PLL_MMPLL) & 0x200) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MMPLL; + } + + if ((mmio_read_32(PLL_UNIVPLL) & 0x200) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_UNIVPLL; + } + + if ((mmio_read_32(PLL_MSDCPLL) & 0x200) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_MSDCPLL; + } + + if ((mmio_read_32(PLL_TVDPLL) & 0x200) != 0U) { + spm_cond_t.table_pll |= PLL_BIT_TVDPLL; + } + + spm_cond_t.priv = priv; + for (rc = con; *rc != NULL; rc++) { + if (((*rc)->update) == NULL) { + continue; + } + + res = (*rc)->update(stateid, PLAT_RC_UPDATE_CONDITION, + (void const *)&spm_cond_t); + if (res != MT_RM_STATUS_OK) { + break; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h new file mode 100644 index 0000000..e471b55 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONDIT_H +#define MT_SPM_CONDIT_H + +#include + +enum PLAT_SPM_COND { + PLAT_SPM_COND_MTCMOS1 = 0, + PLAT_SPM_COND_CG_INFRA_0, + PLAT_SPM_COND_CG_INFRA_1, + PLAT_SPM_COND_CG_INFRA_2, + PLAT_SPM_COND_CG_INFRA_3, + PLAT_SPM_COND_CG_INFRA_4, + PLAT_SPM_COND_CG_PERI_SW_0, + PLAT_SPM_COND_CG_VPPSYS0_SW_CG_0, + PLAT_SPM_COND_CG_VPPSYS0_SW_CG_1, + PLAT_SPM_COND_CG_VPPSYS0_SW_CG_2, + PLAT_SPM_COND_CG_VPPSYS1_SW_CG_0, + PLAT_SPM_COND_CG_VPPSYS1_SW_CG_1, + PLAT_SPM_COND_CG_VDOSYS0_SW_CG_0, + PLAT_SPM_COND_CG_VDOSYS0_SW_CG_1, + PLAT_SPM_COND_CG_VDOSYS1_SW_CG_0, + PLAT_SPM_COND_CG_VDOSYS1_SW_CG_1, + PLAT_SPM_COND_CG_VDOSYS1_SW_CG_2, + PLAT_SPM_COND_CG_I2C_SW_CG, + PLAT_SPM_COND_MAX, +}; + +enum PLAT_SPM_COND_PLL { + PLAT_SPM_COND_PLL_UNIVPLL = 0, + PLAT_SPM_COND_PLL_MFGPLL, + PLAT_SPM_COND_PLL_MSDCPLL, + PLAT_SPM_COND_PLL_TVDPLL, + PLAT_SPM_COND_PLL_MMPLL, + PLAT_SPM_COND_PLL_MAX, +}; + +#define PLL_BIT_MFGPLL BIT(PLAT_SPM_COND_PLL_MFGPLL) +#define PLL_BIT_MMPLL BIT(PLAT_SPM_COND_PLL_MMPLL) +#define PLL_BIT_UNIVPLL BIT(PLAT_SPM_COND_PLL_UNIVPLL) +#define PLL_BIT_MSDCPLL BIT(PLAT_SPM_COND_PLL_MSDCPLL) +#define PLL_BIT_TVDPLL BIT(PLAT_SPM_COND_PLL_TVDPLL) + +/* Definition about SPM_COND_CHECK_BLOCKED + * bit [00 ~ 17]: cg blocking index + * bit [18 ~ 29]: pll blocking index + * bit [30] : pll blocking information + * bit [31] : idle condition check fail + */ +#define SPM_COND_BLOCKED_CG_IDX U(0) +#define SPM_COND_BLOCKED_PLL_IDX U(18) +#define SPM_COND_CHECK_BLOCKED_PLL BIT(30) +#define SPM_COND_CHECK_FAIL BIT(31) + +struct mt_spm_cond_tables { + char *name; + unsigned int table_cg[PLAT_SPM_COND_MAX]; + unsigned int table_pll; + void *priv; +}; + +extern unsigned int mt_spm_cond_check(int state_id, + const struct mt_spm_cond_tables *src, + const struct mt_spm_cond_tables *dest, + struct mt_spm_cond_tables *res); +extern int mt_spm_cond_update(struct mt_resource_constraint **con, + int stateid, void *priv); +#endif /* MT_SPM_CONDIT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c new file mode 100644 index 0000000..7f33408 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct wake_status spm_wakesta; /* record last wakesta */ + +static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + unsigned int resource_req) +{ + int ret = 0; + struct pwr_ctrl *pwrctrl; + uint32_t cpu = plat_my_core_pos(); + + pwrctrl = spm_lp->pwrctrl; + + __spm_set_cpu_status(cpu); + __spm_set_power_control(pwrctrl); + __spm_set_wakeup_event(pwrctrl); + __spm_set_pcm_flags(pwrctrl); + __spm_src_req_update(pwrctrl, resource_req); + + if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) { + __spm_set_pcm_wdt(1); + } + + if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) { + __spm_xo_soc_bblpm(1); + } + + if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) { + spm_hw_s1_state_monitor_resume(); + } + + /* Disable auto resume by PCM in system suspend stage */ + if (IS_PLAT_SUSPEND_ID(state_id)) { + __spm_disable_pcm_timer(); + __spm_set_pcm_wdt(0); + } + + __spm_send_cpu_wakeup_event(); + + INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n", + cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE), + mmio_read_32(PCM_TIMER_VAL) / 32768); + INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n", + pwrctrl->pcm_flags, pwrctrl->pcm_flags1, + mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS), + mmio_read_32(PWR_STATUS_2ND)); + INFO("cpu_pwr = 0x%x 0x%x\n", mmio_read_32(CPU_PWR_STATUS), + mmio_read_32(CPU_PWR_STATUS_2ND)); + + return ret; +} + +static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status) +{ + unsigned int ext_status = 0U; + + /* system watchdog will be resumed at kernel stage */ + if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) { + __spm_set_pcm_wdt(0); + } + + if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) { + __spm_xo_soc_bblpm(0); + } + + if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) { + spm_hw_s1_state_monitor_pause(&ext_status); + } + + __spm_ext_int_wakeup_req_clr(); + __spm_get_wakeup_status(&spm_wakesta, ext_status); + + if (status != NULL) { + *status = &spm_wakesta; + } + + __spm_clean_after_wakeup(); + + if (IS_PLAT_SUSPEND_ID(state_id)) { + __spm_output_wake_reason(state_id, &spm_wakesta); + } +} + +int spm_conservation(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, unsigned int resource_req) +{ + if (spm_lp == NULL) { + return -1; + } + + spm_lock_get(); + go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req); + spm_lock_release(); + + return 0; +} + +void spm_conservation_finish(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status) +{ + spm_lock_get(); + go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status); + spm_lock_release(); +} + +int spm_conservation_get_result(struct wake_status **res) +{ + if (res == NULL) { + return -1; + } + + *res = &spm_wakesta; + + return 0; +} + +#define GPIO_BANK (GPIO_BASE + 0x6F0) +#define TRAP_UFS_FIRST BIT(11) /* bit 11, 0: UFS, 1: eMMC */ + +void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl) +{ + if (pwrctrl == NULL) { + return; + } + + /* For ufs, emmc storage type */ + if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) { + /* If eMMC is used, mask UFS req */ + pwrctrl->reg_ufs_srcclkena_mask_b = 0; + pwrctrl->reg_ufs_infra_req_mask_b = 0; + pwrctrl->reg_ufs_apsrc_req_mask_b = 0; + pwrctrl->reg_ufs_vrf18_req_mask_b = 0; + pwrctrl->reg_ufs_ddr_en_mask_b = 0; + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h new file mode 100644 index 0000000..aa627e7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONSERVATION_H +#define MT_SPM_CONSERVATION_H + +#include + +extern int spm_conservation(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + unsigned int resource_req); +extern void spm_conservation_finish(int state_id, unsigned int ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status); +extern int spm_conservation_get_result(struct wake_status **res); +extern void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl); +#endif /* MT_SPM_CONSERVATION_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h new file mode 100644 index 0000000..944c227 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONSTRAINT_H +#define MT_SPM_CONSTRAINT_H + +#include + +#define MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF (1U << 0) +#define MT_RM_CONSTRAINT_ALLOW_DRAM_S0 (1U << 1) +#define MT_RM_CONSTRAINT_ALLOW_DRAM_S1 (1U << 2) +#define MT_RM_CONSTRAINT_ALLOW_VCORE_LP (1U << 3) +#define MT_RM_CONSTRAINT_ALLOW_INFRA_PDN (1U << 4) +#define MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF (1U << 5) +#define MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND (1U << 6) +#define MT_RM_CONSTRAINT_ALLOW_BBLPM (1U << 7) +#define MT_RM_CONSTRAINT_ALLOW_XO_UFS (1U << 8) +#define MT_RM_CONSTRAINT_ALLOW_GPS_STATE (1U << 9) +#define MT_RM_CONSTRAINT_ALLOW_LVTS_STATE (1U << 10) + +#define MT_SPM_RC_INVALID 0x0 +#define MT_SPM_RC_VALID_SW (1U << 0) +#define MT_SPM_RC_VALID_FW (1U << 1) +#define MT_SPM_RC_VALID_RESIDNECY (1U << 2) +#define MT_SPM_RC_VALID_COND_CHECK (1U << 3) +#define MT_SPM_RC_VALID_COND_LATCH (1U << 4) +#define MT_SPM_RC_VALID_UFS_H8 (1U << 5) +#define MT_SPM_RC_VALID_FLIGHTMODE (1U << 6) +#define MT_SPM_RC_VALID_XSOC_BBLPM (1U << 7) +#define MT_SPM_RC_VALID_TRACE_EVENT (1U << 8) + +#define MT_SPM_RC_VALID (MT_SPM_RC_VALID_SW) + +#define IS_MT_RM_RC_READY(status) \ + ((status & MT_SPM_RC_VALID) == MT_SPM_RC_VALID) + +#define MT_SPM_RC_BBLPM_MODE \ + (MT_SPM_RC_VALID_UFS_H8 | \ + MT_SPM_RC_VALID_FLIGHTMODE | \ + MT_SPM_RC_VALID_XSOC_BBLPM) + +#define IS_MT_SPM_RC_BBLPM_MODE(st) \ + ((st & (MT_SPM_RC_BBLPM_MODE)) == MT_SPM_RC_BBLPM_MODE) + +struct constraint_status { + uint16_t id; + uint16_t valid; + uint32_t cond_block; + uint32_t enter_cnt; + struct mt_spm_cond_tables *cond_res; +}; + +enum MT_SPM_RM_RC_TYPE { + MT_RM_CONSTRAINT_ID_BUS26M, + MT_RM_CONSTRAINT_ID_SYSPLL, + MT_RM_CONSTRAINT_ID_DRAM, + MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO, + MT_RM_CONSTRAINT_ID_ALL, +}; +#endif /* MT_SPM_CONSTRAINT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c new file mode 100644 index 0000000..4bafe95 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define __WAKE_SRC_FOR_IDLE_COMMON__ \ + (R12_PCM_TIMER | \ + R12_KP_IRQ_B | \ + R12_APWDT_EVENT_B | \ + R12_APXGPT1_EVENT_B | \ + R12_CONN2AP_SPM_WAKEUP_B | \ + R12_EINT_EVENT_B | \ + R12_CONN_WDT_IRQ_B | \ + R12_CCIF0_EVENT_B | \ + R12_SSPM2SPM_WAKEUP_B | \ + R12_SCP2SPM_WAKEUP_B | \ + R12_ADSP2SPM_WAKEUP_B | \ + R12_USBX_CDSC_B | \ + R12_USBX_POWERDWN_B | \ + R12_SYS_TIMER_EVENT_B | \ + R12_EINT_EVENT_SECURE_B | \ + R12_AFE_IRQ_MCU_B | \ + R12_SYS_CIRQ_IRQ_B | \ + R12_MD2AP_PEER_EVENT_B | \ + R12_MD1_WDT_B | \ + R12_CLDMA_EVENT_B | \ + R12_REG_CPU_WAKEUP | \ + R12_APUSYS_WAKE_HOST_B) + +#if defined(CFG_MICROTRUST_TEE_SUPPORT) +#define WAKE_SRC_FOR_IDLE (__WAKE_SRC_FOR_IDLE_COMMON__) +#else +#define WAKE_SRC_FOR_IDLE \ + (__WAKE_SRC_FOR_IDLE_COMMON__ | \ + R12_SEJ_EVENT_B) +#endif + +static struct pwr_ctrl idle_spm_pwr = { + .wake_src = WAKE_SRC_FOR_IDLE, + + /* SPM_AP_STANDBY_CON */ + /* [0] */ + .reg_wfi_op = 0, + /* [1] */ + .reg_wfi_type = 0, + /* [2] */ + .reg_mp0_cputop_idle_mask = 0, + /* [3] */ + .reg_mp1_cputop_idle_mask = 0, + /* [4] */ + .reg_mcusys_idle_mask = 0, + /* [25] */ + .reg_md_apsrc_1_sel = 0, + /* [26] */ + .reg_md_apsrc_0_sel = 0, + /* [29] */ + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC_REQ */ + /* [0] */ + .reg_spm_apsrc_req = 0, + /* [1] */ + .reg_spm_f26m_req = 1, + /* [3] */ + .reg_spm_infra_req = 1, + /* [4] */ + .reg_spm_vrf18_req = 0, + /* [7] FIXME: default disable HW Auto S1 */ + .reg_spm_ddr_en_req = 1, + /* [8] */ + .reg_spm_dvfs_req = 0, + /* [9] */ + .reg_spm_sw_mailbox_req = 0, + /* [10] */ + .reg_spm_sspm_mailbox_req = 0, + /* [11] */ + .reg_spm_adsp_mailbox_req = 0, + /* [12] */ + .reg_spm_scp_mailbox_req = 0, + + + /* SPM_SRC_MASK */ + /* [0] */ + .reg_sspm_srcclkena_0_mask_b = 1, + /* [1] */ + .reg_sspm_infra_req_0_mask_b = 1, + /* [2] */ + .reg_sspm_apsrc_req_0_mask_b = 1, + /* [3] */ + .reg_sspm_vrf18_req_0_mask_b = 1, + /* [4] */ + .reg_sspm_ddr_en_0_mask_b = 1, + /* [5] */ + .reg_scp_srcclkena_mask_b = 1, + /* [6] */ + .reg_scp_infra_req_mask_b = 1, + /* [7] */ + .reg_scp_apsrc_req_mask_b = 1, + /* [8] */ + .reg_scp_vrf18_req_mask_b = 1, + /* [9] */ + .reg_scp_ddr_en_mask_b = 1, + /* [10] */ + .reg_audio_dsp_srcclkena_mask_b = 1, + /* [11] */ + .reg_audio_dsp_infra_req_mask_b = 1, + /* [12] */ + .reg_audio_dsp_apsrc_req_mask_b = 1, + /* [13] */ + .reg_audio_dsp_vrf18_req_mask_b = 1, + /* [14] */ + .reg_audio_dsp_ddr_en_mask_b = 1, + /* [15] */ + .reg_apu_srcclkena_mask_b = 1, + /* [16] */ + .reg_apu_infra_req_mask_b = 1, + /* [17] */ + .reg_apu_apsrc_req_mask_b = 1, + /* [18] */ + .reg_apu_vrf18_req_mask_b = 1, + /* [19] */ + .reg_apu_ddr_en_mask_b = 1, + /* [20] */ + .reg_cpueb_srcclkena_mask_b = 1, + /* [21] */ + .reg_cpueb_infra_req_mask_b = 1, + /* [22] */ + .reg_cpueb_apsrc_req_mask_b = 1, + /* [23] */ + .reg_cpueb_vrf18_req_mask_b = 1, + /* [24] */ + .reg_cpueb_ddr_en_mask_b = 1, + /* [25] */ + .reg_bak_psri_srcclkena_mask_b = 0, + /* [26] */ + .reg_bak_psri_infra_req_mask_b = 0, + /* [27] */ + .reg_bak_psri_apsrc_req_mask_b = 0, + /* [28] */ + .reg_bak_psri_vrf18_req_mask_b = 0, + /* [29] */ + .reg_bak_psri_ddr_en_mask_b = 0, + + /* SPM_SRC2_MASK */ + /* [0] */ + .reg_msdc0_srcclkena_mask_b = 1, + /* [1] */ + .reg_msdc0_infra_req_mask_b = 1, + /* [2] */ + .reg_msdc0_apsrc_req_mask_b = 1, + /* [3] */ + .reg_msdc0_vrf18_req_mask_b = 1, + /* [4] */ + .reg_msdc0_ddr_en_mask_b = 1, + /* [5] */ + .reg_msdc1_srcclkena_mask_b = 1, + /* [6] */ + .reg_msdc1_infra_req_mask_b = 1, + /* [7] */ + .reg_msdc1_apsrc_req_mask_b = 1, + /* [8] */ + .reg_msdc1_vrf18_req_mask_b = 1, + /* [9] */ + .reg_msdc1_ddr_en_mask_b = 1, + /* [10] */ + .reg_msdc2_srcclkena_mask_b = 1, + /* [11] */ + .reg_msdc2_infra_req_mask_b = 1, + /* [12] */ + .reg_msdc2_apsrc_req_mask_b = 1, + /* [13] */ + .reg_msdc2_vrf18_req_mask_b = 1, + /* [14] */ + .reg_msdc2_ddr_en_mask_b = 1, + /* [15] */ + .reg_ufs_srcclkena_mask_b = 1, + /* [16] */ + .reg_ufs_infra_req_mask_b = 1, + /* [17] */ + .reg_ufs_apsrc_req_mask_b = 1, + /* [18] */ + .reg_ufs_vrf18_req_mask_b = 1, + /* [19] */ + .reg_ufs_ddr_en_mask_b = 1, + /* [20] */ + .reg_usb_srcclkena_mask_b = 1, + /* [21] */ + .reg_usb_infra_req_mask_b = 1, + /* [22] */ + .reg_usb_apsrc_req_mask_b = 1, + /* [23] */ + .reg_usb_vrf18_req_mask_b = 1, + /* [24] */ + .reg_usb_ddr_en_mask_b = 1, + /* [25] */ + .reg_pextp_p0_srcclkena_mask_b = 1, + /* [26] */ + .reg_pextp_p0_infra_req_mask_b = 1, + /* [27] */ + .reg_pextp_p0_apsrc_req_mask_b = 1, + /* [28] */ + .reg_pextp_p0_vrf18_req_mask_b = 1, + /* [29] */ + .reg_pextp_p0_ddr_en_mask_b = 1, + + /* SPM_SRC3_MASK */ + /* [0] */ + .reg_pextp_p1_srcclkena_mask_b = 1, + /* [1] */ + .reg_pextp_p1_infra_req_mask_b = 1, + /* [2] */ + .reg_pextp_p1_apsrc_req_mask_b = 1, + /* [3] */ + .reg_pextp_p1_vrf18_req_mask_b = 1, + /* [4] */ + .reg_pextp_p1_ddr_en_mask_b = 1, + /* [5] */ + .reg_gce0_infra_req_mask_b = 1, + /* [6] */ + .reg_gce0_apsrc_req_mask_b = 1, + /* [7] */ + .reg_gce0_vrf18_req_mask_b = 1, + /* [8] */ + .reg_gce0_ddr_en_mask_b = 1, + /* [9] */ + .reg_gce1_infra_req_mask_b = 1, + /* [10] */ + .reg_gce1_apsrc_req_mask_b = 1, + /* [11] */ + .reg_gce1_vrf18_req_mask_b = 1, + /* [12] */ + .reg_gce1_ddr_en_mask_b = 1, + /* [13] */ + .reg_spm_srcclkena_reserved_mask_b = 1, + /* [14] */ + .reg_spm_infra_req_reserved_mask_b = 1, + /* [15] */ + .reg_spm_apsrc_req_reserved_mask_b = 1, + /* [16] */ + .reg_spm_vrf18_req_reserved_mask_b = 1, + /* [17] */ + .reg_spm_ddr_en_reserved_mask_b = 1, + /* [18] */ + .reg_disp0_apsrc_req_mask_b = 1, + /* [19] */ + .reg_disp0_ddr_en_mask_b = 1, + /* [20] */ + .reg_disp1_apsrc_req_mask_b = 1, + /* [21] */ + .reg_disp1_ddr_en_mask_b = 1, + /* [22] */ + .reg_disp2_apsrc_req_mask_b = 1, + /* [23] */ + .reg_disp2_ddr_en_mask_b = 1, + /* [24] */ + .reg_disp3_apsrc_req_mask_b = 1, + /* [25] */ + .reg_disp3_ddr_en_mask_b = 1, + /* [26] */ + .reg_infrasys_apsrc_req_mask_b = 0, + /* [27] */ + .reg_infrasys_ddr_en_mask_b = 1, + + /* [28] */ + .reg_cg_check_srcclkena_mask_b = 1, + /* [29] */ + .reg_cg_check_apsrc_req_mask_b = 1, + /* [30] */ + .reg_cg_check_vrf18_req_mask_b = 1, + /* [31] */ + .reg_cg_check_ddr_en_mask_b = 1, + + /* SPM_SRC4_MASK */ + /* [8:0] */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x17, + /* [17:9] */ + .reg_mcusys_merge_ddr_en_mask_b = 0x17, + /* [19:18] */ + .reg_dramc_md32_infra_req_mask_b = 0, + /* [21:20] */ + .reg_dramc_md32_vrf18_req_mask_b = 0, + /* [23:22] */ + .reg_dramc_md32_ddr_en_mask_b = 0, + /* [24] */ + .reg_dvfsrc_event_trigger_mask_b = 1, + + /* SPM_WAKEUP_EVENT_MASK2 */ + /* [3:0] */ + .reg_sc_sw2spm_wakeup_mask_b = 0, + /* [4] */ + .reg_sc_adsp2spm_wakeup_mask_b = 0, + /* [8:5] */ + .reg_sc_sspm2spm_wakeup_mask_b = 0, + /* [9] */ + .reg_sc_scp2spm_wakeup_mask_b = 0, + /* [10] */ + .reg_csyspwrup_ack_mask = 0, + /* [11] */ + .reg_csyspwrup_req_mask = 1, + + /* SPM_WAKEUP_EVENT_MASK */ + /* [31:0] */ + .reg_wakeup_event_mask = 0xC1282203, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + /* [31:0] */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, +}; + +struct spm_lp_scen idle_spm_lp = { + .pwrctrl = &idle_spm_pwr, +}; + +int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand, + spm_idle_conduct fn) +{ + unsigned int src_req = 0; + + if (fn != NULL) { + fn(&idle_spm_lp, &src_req); + } + + return spm_conservation(state_id, ext_opand, &idle_spm_lp, src_req); +} +void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand, + struct wake_status **status) +{ + spm_conservation_finish(state_id, ext_opand, &idle_spm_lp, status); +} + +void mt_spm_idle_generic_init(void) +{ + spm_conservation_pwrctrl_init(idle_spm_lp.pwrctrl); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h new file mode 100644 index 0000000..7f6fb0c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_IDLE_H +#define MT_SPM_IDLE_H + +typedef void (*spm_idle_conduct)(struct spm_lp_scen *spm_lp, + unsigned int *resource_req); +int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand, + spm_idle_conduct fn); +void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand, + struct wake_status **status); +void mt_spm_idle_generic_init(void); +#endif /* MT_SPM_IDLE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c new file mode 100644 index 0000000..2647d9f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/************************************** + * Define and Declare + **************************************/ +#define ROOT_CORE_ADDR_OFFSET 0x20000000 +#define SPM_WAKEUP_EVENT_MASK_CLEAN_MASK 0xefffffff +#define SPM_INIT_DONE_US 20 +#define SPM_WAKEUP_REASON_MISSING 0xdeaddead + +static unsigned int mt_spm_bblpm_cnt; + +const char *wakeup_src_str[32] = { + [0] = "PCM_TIMER", + [1] = "RESERVED_DEBUG_B", + [2] = "KEYPAD", + [3] = "APWDT", + [4] = "APXGPT", + [5] = "MSDC", + [6] = "EINT", + [7] = "IRRX", + [8] = "ETHERNET_QOS", + [9] = "RESERVE0", + [10] = "SSPM", + [11] = "SCP", + [12] = "ADSP", + [13] = "SPM_WDT", + [14] = "USB_U2", + [15] = "USB_TOP", + [16] = "SYS_TIMER", + [17] = "EINT_SECURE", + [18] = "HDMI", + [19] = "RESERVE1", + [20] = "AFE", + [21] = "THERMAL", + [22] = "SYS_CIRQ", + [23] = "NNA2INFRA", + [24] = "CSYSPWREQ", + [25] = "RESERVE2", + [26] = "PCIE", + [27] = "SEJ", + [28] = "SPM_CPU_WAKEUPEVENT", + [29] = "APUSYS", + [30] = "RESERVE3", + [31] = "RESERVE4", +}; + +/************************************** + * Function and API + **************************************/ + +wake_reason_t __spm_output_wake_reason(int state_id, + const struct wake_status *wakesta) +{ + uint32_t i, bk_vtcxo_dur, spm_26m_off_pct = 0U; + char *spm_26m_sta = NULL; + wake_reason_t wr = WR_UNKNOWN; + + if (wakesta == NULL) { + return WR_UNKNOWN; + } + + spm_26m_sta = ((wakesta->debug_flag & SPM_DBG_DEBUG_IDX_26M_SLEEP) == 0U) ? "on" : "off"; + + if (wakesta->abort != 0U) { + ERROR("spmfw flow is aborted: 0x%x, timer_out = %u, 26M(%s)\n", + wakesta->abort, wakesta->timer_out, spm_26m_sta); + } else if (wakesta->r12 == SPM_WAKEUP_REASON_MISSING) { + WARN("cannot find wake up reason, timer_out = %u, 26M(%s)\n", + wakesta->timer_out, spm_26m_sta); + } else { + for (i = 0U; i < 32U; i++) { + if ((wakesta->r12 & (1U << i)) != 0U) { + INFO("wake up by %s, timer_out = %u, 26M(%s)\n", + wakeup_src_str[i], wakesta->timer_out, spm_26m_sta); + wr = WR_WAKE_SRC; + break; + } + } + } + + INFO("r12 = 0x%x, r12_ext = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n", + wakesta->r12, wakesta->r12_ext, wakesta->r13, wakesta->debug_flag, + wakesta->debug_flag1); + INFO("raw_sta = 0x%x 0x%x 0x%x, idle_sta = 0x%x, cg_check_sta = 0x%x\n", + wakesta->raw_sta, wakesta->md32pcm_wakeup_sta, + wakesta->md32pcm_event_sta, wakesta->idle_sta, + wakesta->cg_check_sta); + INFO("req_sta = 0x%x 0x%x 0x%x 0x%x 0x%x, isr = 0x%x\n", + wakesta->req_sta0, wakesta->req_sta1, wakesta->req_sta2, + wakesta->req_sta3, wakesta->req_sta4, wakesta->isr); + INFO("rt_req_sta0 = 0x%x, rt_req_sta1 = 0x%x, rt_req_sta2 = 0x%x\n", + wakesta->rt_req_sta0, wakesta->rt_req_sta1, wakesta->rt_req_sta2); + INFO("rt_req_sta3 = 0x%x, dram_sw_con_3 = 0x%x, raw_ext_sta = 0x%x\n", + wakesta->rt_req_sta3, wakesta->rt_req_sta4, wakesta->raw_ext_sta); + INFO("wake_misc = 0x%x, pcm_flag = 0x%x 0x%x 0x%x 0x%x, req = 0x%x\n", + wakesta->wake_misc, wakesta->sw_flag0, wakesta->sw_flag1, + wakesta->b_sw_flag0, wakesta->b_sw_flag1, wakesta->src_req); + INFO("clk_settle = 0x%x, wlk_cntcv_l = 0x%x, wlk_cntcv_h = 0x%x\n", + wakesta->clk_settle, mmio_read_32(SYS_TIMER_VALUE_L), + mmio_read_32(SYS_TIMER_VALUE_H)); + + if (wakesta->timer_out != 0U) { + bk_vtcxo_dur = mmio_read_32(SPM_BK_VTCXO_DUR); + spm_26m_off_pct = (100 * bk_vtcxo_dur) / wakesta->timer_out; + INFO("spm_26m_off_pct = %u\n", spm_26m_off_pct); + } + + return wr; +} + +void __spm_set_cpu_status(unsigned int cpu) +{ + uint32_t root_core_addr; + + if (cpu < 8U) { + mmio_write_32(ROOT_CPUTOP_ADDR, (1U << cpu)); + root_core_addr = SPM_CPU0_PWR_CON + (cpu * 0x4); + root_core_addr += ROOT_CORE_ADDR_OFFSET; + mmio_write_32(ROOT_CORE_ADDR, root_core_addr); + /* Notify MCUPM that preferred cpu wakeup */ + mmio_write_32(MCUPM_MBOX_WAKEUP_CPU, cpu); + } else { + ERROR("%s: error cpu number %d\n", __func__, cpu); + } +} + +void __spm_src_req_update(const struct pwr_ctrl *pwrctrl, + unsigned int resource_usage) +{ + uint8_t apsrc_req = ((resource_usage & MT_SPM_DRAM_S0) != 0U) ? + 1 : pwrctrl->reg_spm_apsrc_req; + uint8_t ddr_en_req = ((resource_usage & MT_SPM_DRAM_S1) != 0U) ? + 1 : pwrctrl->reg_spm_ddr_en_req; + uint8_t vrf18_req = ((resource_usage & MT_SPM_SYSPLL) != 0U) ? + 1 : pwrctrl->reg_spm_vrf18_req; + uint8_t infra_req = ((resource_usage & MT_SPM_INFRA) != 0U) ? + 1 : pwrctrl->reg_spm_infra_req; + uint8_t f26m_req = ((resource_usage & + (MT_SPM_26M | MT_SPM_XO_FPM)) != 0U) ? + 1 : pwrctrl->reg_spm_f26m_req; + + mmio_write_32(SPM_SRC_REQ, + ((apsrc_req & 0x1) << 0) | + ((f26m_req & 0x1) << 1) | + ((infra_req & 0x1) << 3) | + ((vrf18_req & 0x1) << 4) | + ((ddr_en_req & 0x1) << 7) | + ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) | + ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) | + ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) | + ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) | + ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12)); +} + +void __spm_set_power_control(const struct pwr_ctrl *pwrctrl) +{ + /* Auto-gen Start */ + + /* SPM_AP_STANDBY_CON */ + mmio_write_32(SPM_AP_STANDBY_CON, + ((pwrctrl->reg_wfi_op & 0x1) << 0) | + ((pwrctrl->reg_wfi_type & 0x1) << 1) | + ((pwrctrl->reg_mp0_cputop_idle_mask & 0x1) << 2) | + ((pwrctrl->reg_mp1_cputop_idle_mask & 0x1) << 3) | + ((pwrctrl->reg_mcusys_idle_mask & 0x1) << 4) | + ((pwrctrl->reg_md_apsrc_1_sel & 0x1) << 25) | + ((pwrctrl->reg_md_apsrc_0_sel & 0x1) << 26) | + ((pwrctrl->reg_conn_apsrc_sel & 0x1) << 29)); + + /* SPM_SRC_REQ */ + mmio_write_32(SPM_SRC_REQ, + ((pwrctrl->reg_spm_apsrc_req & 0x1) << 0) | + ((pwrctrl->reg_spm_f26m_req & 0x1) << 1) | + ((pwrctrl->reg_spm_infra_req & 0x1) << 3) | + ((pwrctrl->reg_spm_vrf18_req & 0x1) << 4) | + ((pwrctrl->reg_spm_ddr_en_req & 0x1) << 7) | + ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) | + ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) | + ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) | + ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) | + ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12)); + + /* SPM_SRC_MASK */ + mmio_write_32(SPM_SRC_MASK, + ((pwrctrl->reg_sspm_srcclkena_0_mask_b & 0x1) << 0) | + ((pwrctrl->reg_sspm_infra_req_0_mask_b & 0x1) << 1) | + ((pwrctrl->reg_sspm_apsrc_req_0_mask_b & 0x1) << 2) | + ((pwrctrl->reg_sspm_vrf18_req_0_mask_b & 0x1) << 3) | + ((pwrctrl->reg_sspm_ddr_en_0_mask_b & 0x1) << 4) | + ((pwrctrl->reg_scp_srcclkena_mask_b & 0x1) << 5) | + ((pwrctrl->reg_scp_infra_req_mask_b & 0x1) << 6) | + ((pwrctrl->reg_scp_apsrc_req_mask_b & 0x1) << 7) | + ((pwrctrl->reg_scp_vrf18_req_mask_b & 0x1) << 8) | + ((pwrctrl->reg_scp_ddr_en_mask_b & 0x1) << 9) | + ((pwrctrl->reg_audio_dsp_srcclkena_mask_b & 0x1) << 10) | + ((pwrctrl->reg_audio_dsp_infra_req_mask_b & 0x1) << 11) | + ((pwrctrl->reg_audio_dsp_apsrc_req_mask_b & 0x1) << 12) | + ((pwrctrl->reg_audio_dsp_vrf18_req_mask_b & 0x1) << 13) | + ((pwrctrl->reg_audio_dsp_ddr_en_mask_b & 0x1) << 14) | + ((pwrctrl->reg_apu_srcclkena_mask_b & 0x1) << 15) | + ((pwrctrl->reg_apu_infra_req_mask_b & 0x1) << 16) | + ((pwrctrl->reg_apu_apsrc_req_mask_b & 0x1) << 17) | + ((pwrctrl->reg_apu_vrf18_req_mask_b & 0x1) << 18) | + ((pwrctrl->reg_apu_ddr_en_mask_b & 0x1) << 19) | + ((pwrctrl->reg_cpueb_srcclkena_mask_b & 0x1) << 20) | + ((pwrctrl->reg_cpueb_infra_req_mask_b & 0x1) << 21) | + ((pwrctrl->reg_cpueb_apsrc_req_mask_b & 0x1) << 22) | + ((pwrctrl->reg_cpueb_vrf18_req_mask_b & 0x1) << 23) | + ((pwrctrl->reg_cpueb_ddr_en_mask_b & 0x1) << 24) | + ((pwrctrl->reg_bak_psri_srcclkena_mask_b & 0x1) << 25) | + ((pwrctrl->reg_bak_psri_infra_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_bak_psri_apsrc_req_mask_b & 0x1) << 27) | + ((pwrctrl->reg_bak_psri_vrf18_req_mask_b & 0x1) << 28) | + ((pwrctrl->reg_bak_psri_ddr_en_mask_b & 0x1) << 29)); + + /* SPM_SRC2_MASK */ + mmio_write_32(SPM_SRC2_MASK, + ((pwrctrl->reg_msdc0_srcclkena_mask_b & 0x1) << 0) | + ((pwrctrl->reg_msdc0_infra_req_mask_b & 0x1) << 1) | + ((pwrctrl->reg_msdc0_apsrc_req_mask_b & 0x1) << 2) | + ((pwrctrl->reg_msdc0_vrf18_req_mask_b & 0x1) << 3) | + ((pwrctrl->reg_msdc0_ddr_en_mask_b & 0x1) << 4) | + ((pwrctrl->reg_msdc1_srcclkena_mask_b & 0x1) << 5) | + ((pwrctrl->reg_msdc1_infra_req_mask_b & 0x1) << 6) | + ((pwrctrl->reg_msdc1_apsrc_req_mask_b & 0x1) << 7) | + ((pwrctrl->reg_msdc1_vrf18_req_mask_b & 0x1) << 8) | + ((pwrctrl->reg_msdc1_ddr_en_mask_b & 0x1) << 9) | + ((pwrctrl->reg_msdc2_srcclkena_mask_b & 0x1) << 10) | + ((pwrctrl->reg_msdc2_infra_req_mask_b & 0x1) << 11) | + ((pwrctrl->reg_msdc2_apsrc_req_mask_b & 0x1) << 12) | + ((pwrctrl->reg_msdc2_vrf18_req_mask_b & 0x1) << 13) | + ((pwrctrl->reg_msdc2_ddr_en_mask_b & 0x1) << 14) | + ((pwrctrl->reg_ufs_srcclkena_mask_b & 0x1) << 15) | + ((pwrctrl->reg_ufs_infra_req_mask_b & 0x1) << 16) | + ((pwrctrl->reg_ufs_apsrc_req_mask_b & 0x1) << 17) | + ((pwrctrl->reg_ufs_vrf18_req_mask_b & 0x1) << 18) | + ((pwrctrl->reg_ufs_ddr_en_mask_b & 0x1) << 19) | + ((pwrctrl->reg_usb_srcclkena_mask_b & 0x1) << 20) | + ((pwrctrl->reg_usb_infra_req_mask_b & 0x1) << 21) | + ((pwrctrl->reg_usb_apsrc_req_mask_b & 0x1) << 22) | + ((pwrctrl->reg_usb_vrf18_req_mask_b & 0x1) << 23) | + ((pwrctrl->reg_usb_ddr_en_mask_b & 0x1) << 24) | + ((pwrctrl->reg_pextp_p0_srcclkena_mask_b & 0x1) << 25) | + ((pwrctrl->reg_pextp_p0_infra_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_pextp_p0_apsrc_req_mask_b & 0x1) << 27) | + ((pwrctrl->reg_pextp_p0_vrf18_req_mask_b & 0x1) << 28) | + ((pwrctrl->reg_pextp_p0_ddr_en_mask_b & 0x1) << 29)); + + /* SPM_SRC3_MASK */ + mmio_write_32(SPM_SRC3_MASK, + ((pwrctrl->reg_pextp_p1_srcclkena_mask_b & 0x1) << 0) | + ((pwrctrl->reg_pextp_p1_infra_req_mask_b & 0x1) << 1) | + ((pwrctrl->reg_pextp_p1_apsrc_req_mask_b & 0x1) << 2) | + ((pwrctrl->reg_pextp_p1_vrf18_req_mask_b & 0x1) << 3) | + ((pwrctrl->reg_pextp_p1_ddr_en_mask_b & 0x1) << 4) | + ((pwrctrl->reg_gce0_infra_req_mask_b & 0x1) << 5) | + ((pwrctrl->reg_gce0_apsrc_req_mask_b & 0x1) << 6) | + ((pwrctrl->reg_gce0_vrf18_req_mask_b & 0x1) << 7) | + ((pwrctrl->reg_gce0_ddr_en_mask_b & 0x1) << 8) | + ((pwrctrl->reg_gce1_infra_req_mask_b & 0x1) << 9) | + ((pwrctrl->reg_gce1_apsrc_req_mask_b & 0x1) << 10) | + ((pwrctrl->reg_gce1_vrf18_req_mask_b & 0x1) << 11) | + ((pwrctrl->reg_gce1_ddr_en_mask_b & 0x1) << 12) | + ((pwrctrl->reg_spm_srcclkena_reserved_mask_b & 0x1) << 13) | + ((pwrctrl->reg_spm_infra_req_reserved_mask_b & 0x1) << 14) | + ((pwrctrl->reg_spm_apsrc_req_reserved_mask_b & 0x1) << 15) | + ((pwrctrl->reg_spm_vrf18_req_reserved_mask_b & 0x1) << 16) | + ((pwrctrl->reg_spm_ddr_en_reserved_mask_b & 0x1) << 17) | + ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 18) | + ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 19) | + ((pwrctrl->reg_disp1_apsrc_req_mask_b & 0x1) << 20) | + ((pwrctrl->reg_disp1_ddr_en_mask_b & 0x1) << 21) | + ((pwrctrl->reg_disp2_apsrc_req_mask_b & 0x1) << 22) | + ((pwrctrl->reg_disp2_ddr_en_mask_b & 0x1) << 23) | + ((pwrctrl->reg_disp3_apsrc_req_mask_b & 0x1) << 24) | + ((pwrctrl->reg_disp3_ddr_en_mask_b & 0x1) << 25) | + ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 26) | + ((pwrctrl->reg_infrasys_ddr_en_mask_b & 0x1) << 27)); + + /* Mask MCUSYS request since SOC HW would check it */ + mmio_write_32(SPM_SRC4_MASK, 0x1fc0000); + + /* SPM_WAKEUP_EVENT_MASK */ + mmio_write_32(SPM_WAKEUP_EVENT_MASK, + ((pwrctrl->reg_wakeup_event_mask & 0xffffffff) << 0)); + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK, + ((pwrctrl->reg_ext_wakeup_event_mask & 0xffffffff) << 0)); + + /* Auto-gen End */ +} + +void __spm_disable_pcm_timer(void) +{ + mmio_clrsetbits_32(PCM_CON1, RG_PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY); +} + +void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl) +{ + uint32_t val, mask; + + /* toggle event counter clear */ + mmio_setbits_32(PCM_CON1, + SPM_REGWR_CFG_KEY | SPM_EVENT_COUNTER_CLR_LSB); + + /* toggle for reset SYS TIMER start point */ + mmio_setbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB); + + if (pwrctrl->timer_val_cust == 0U) { + val = pwrctrl->timer_val; + } else { + val = pwrctrl->timer_val_cust; + } + + mmio_write_32(PCM_TIMER_VAL, val); + mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | RG_PCM_TIMER_EN_LSB); + + /* unmask AP wakeup source */ + if (pwrctrl->wake_src_cust == 0U) { + mask = pwrctrl->wake_src; + } else { + mask = pwrctrl->wake_src_cust; + } + + mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask); + + /* unmask SPM ISR (keep TWAM setting) */ + mmio_setbits_32(SPM_IRQ_MASK, ISRM_RET_IRQ_AUX); + + /* toggle event counter clear */ + mmio_clrsetbits_32(PCM_CON1, SPM_EVENT_COUNTER_CLR_LSB, + SPM_REGWR_CFG_KEY); + /* toggle for reset SYS TIMER start point */ + mmio_clrbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB); +} + +void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl) +{ + /* set PCM flags and data */ + if (pwrctrl->pcm_flags_cust_clr != 0U) { + pwrctrl->pcm_flags &= ~pwrctrl->pcm_flags_cust_clr; + } + + if (pwrctrl->pcm_flags_cust_set != 0U) { + pwrctrl->pcm_flags |= pwrctrl->pcm_flags_cust_set; + } + + if (pwrctrl->pcm_flags1_cust_clr != 0U) { + pwrctrl->pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr; + } + + if (pwrctrl->pcm_flags1_cust_set != 0U) { + pwrctrl->pcm_flags1 |= pwrctrl->pcm_flags1_cust_set; + } + + mmio_write_32(SPM_SW_FLAG_0, pwrctrl->pcm_flags); + mmio_write_32(SPM_SW_FLAG_1, pwrctrl->pcm_flags1); + mmio_write_32(SPM_SW_RSV_7, pwrctrl->pcm_flags); + mmio_write_32(SPM_SW_RSV_8, pwrctrl->pcm_flags1); +} + +void __spm_get_wakeup_status(struct wake_status *wakesta, + unsigned int ext_status) +{ + wakesta->tr.comm.r12 = mmio_read_32(SPM_BK_WAKE_EVENT); + wakesta->tr.comm.timer_out = mmio_read_32(SPM_BK_PCM_TIMER); + wakesta->tr.comm.r13 = mmio_read_32(PCM_REG13_DATA); + wakesta->tr.comm.req_sta0 = mmio_read_32(SRC_REQ_STA_0); + wakesta->tr.comm.req_sta1 = mmio_read_32(SRC_REQ_STA_1); + wakesta->tr.comm.req_sta2 = mmio_read_32(SRC_REQ_STA_2); + wakesta->tr.comm.req_sta3 = mmio_read_32(SRC_REQ_STA_3); + wakesta->tr.comm.req_sta4 = mmio_read_32(SRC_REQ_STA_4); + wakesta->tr.comm.debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0); + wakesta->tr.comm.debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1); + + if ((ext_status & SPM_INTERNAL_STATUS_HW_S1) != 0U) { + wakesta->tr.comm.debug_flag |= (SPM_DBG_DEBUG_IDX_DDREN_WAKE | + SPM_DBG_DEBUG_IDX_DDREN_SLEEP); + mmio_write_32(PCM_WDT_LATCH_SPARE_0, + wakesta->tr.comm.debug_flag); + } + + wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); + wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); + + /* record below spm info for debug */ + wakesta->r12 = mmio_read_32(SPM_BK_WAKE_EVENT); + wakesta->r12_ext = mmio_read_32(SPM_WAKEUP_STA); + wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA); + wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA); + wakesta->md32pcm_wakeup_sta = mmio_read_32(MD32PCM_WAKEUP_STA); + wakesta->md32pcm_event_sta = mmio_read_32(MD32PCM_EVENT_STA); + wakesta->src_req = mmio_read_32(SPM_SRC_REQ); + + /* backup of SPM_WAKEUP_MISC */ + wakesta->wake_misc = mmio_read_32(SPM_BK_WAKE_MISC); + + /* get sleep time, backup of PCM_TIMER_OUT */ + wakesta->timer_out = mmio_read_32(SPM_BK_PCM_TIMER); + + /* get other SYS and co-clock status */ + wakesta->r13 = mmio_read_32(PCM_REG13_DATA); + wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA); + wakesta->req_sta0 = mmio_read_32(SRC_REQ_STA_0); + wakesta->req_sta1 = mmio_read_32(SRC_REQ_STA_1); + wakesta->req_sta2 = mmio_read_32(SRC_REQ_STA_2); + wakesta->req_sta3 = mmio_read_32(SRC_REQ_STA_3); + wakesta->req_sta4 = mmio_read_32(SRC_REQ_STA_4); + + /* get HW CG check status */ + wakesta->cg_check_sta = mmio_read_32(SPM_CG_CHECK_STA); + + /* get debug flag for PCM execution check */ + wakesta->debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0); + wakesta->debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1); + + /* get backup SW flag status */ + wakesta->b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); + wakesta->b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); + + wakesta->rt_req_sta0 = mmio_read_32(SPM_SW_RSV_2); + wakesta->rt_req_sta1 = mmio_read_32(SPM_SW_RSV_3); + wakesta->rt_req_sta2 = mmio_read_32(SPM_SW_RSV_4); + wakesta->rt_req_sta3 = mmio_read_32(SPM_SW_RSV_5); + wakesta->rt_req_sta4 = mmio_read_32(SPM_SW_RSV_6); + + /* get ISR status */ + wakesta->isr = mmio_read_32(SPM_IRQ_STA); + + /* get SW flag status */ + wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0); + wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1); + + /* get CLK SETTLE */ + wakesta->clk_settle = mmio_read_32(SPM_CLK_SETTLE); + + /* check abort */ + wakesta->abort = (wakesta->debug_flag & DEBUG_ABORT_MASK) | + (wakesta->debug_flag1 & DEBUG_ABORT_MASK_1); +} + +void __spm_clean_after_wakeup(void) +{ + mmio_write_32(SPM_BK_WAKE_EVENT, + mmio_read_32(SPM_WAKEUP_STA) | + mmio_read_32(SPM_BK_WAKE_EVENT)); + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0); + + /* + * clean wakeup event raw status (for edge trigger event) + * bit[28] for cpu wake up event + */ + mmio_write_32(SPM_WAKEUP_EVENT_MASK, SPM_WAKEUP_EVENT_MASK_CLEAN_MASK); + + /* clean ISR status (except TWAM) */ + mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM); + mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM); + mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL); +} + +void __spm_set_pcm_wdt(int en) +{ + mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_EN_LSB, + SPM_REGWR_CFG_KEY); + + if (en == 1) { + mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_WAKE_LSB, + SPM_REGWR_CFG_KEY); + + if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) { + mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX); + } + + mmio_write_32(PCM_WDT_VAL, + mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT); + mmio_setbits_32(PCM_CON1, + SPM_REGWR_CFG_KEY | RG_PCM_WDT_EN_LSB); + } +} + +void __spm_send_cpu_wakeup_event(void) +{ + /* SPM will clear SPM_CPU_WAKEUP_EVENT */ + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1); +} + +void __spm_ext_int_wakeup_req_clr(void) +{ + mmio_write_32(EXT_INT_WAKEUP_REQ_CLR, mmio_read_32(ROOT_CPUTOP_ADDR)); + + /* Clear spm2mcupm wakeup interrupt status */ + mmio_write_32(SPM2CPUEB_CON, 0); +} + +void __spm_xo_soc_bblpm(int en) +{ + if (en == 1) { + mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG, + RC_SW_SRCLKEN_FPM, RC_SW_SRCLKEN_RC); + assert(mt_spm_bblpm_cnt == 0); + mt_spm_bblpm_cnt += 1; + } else { + mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG, + RC_SW_SRCLKEN_RC, RC_SW_SRCLKEN_FPM); + mt_spm_bblpm_cnt -= 1; + } +} + +void __spm_hw_s1_state_monitor(int en, unsigned int *status) +{ + unsigned int reg; + + reg = mmio_read_32(SPM_ACK_CHK_CON_3); + + if (en == 1) { + reg &= ~SPM_ACK_CHK_3_CON_CLR_ALL; + mmio_write_32(SPM_ACK_CHK_CON_3, reg); + reg |= SPM_ACK_CHK_3_CON_EN; + mmio_write_32(SPM_ACK_CHK_CON_3, reg); + } else { + if (((reg & SPM_ACK_CHK_3_CON_RESULT) != 0U) && + (status != NULL)) { + *status |= SPM_INTERNAL_STATUS_HW_S1; + } + + mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_EN, + SPM_ACK_CHK_3_CON_HW_MODE_TRIG | + SPM_ACK_CHK_3_CON_CLR_ALL); + } +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h new file mode 100644 index 0000000..5ac7c91 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_INTERNAL_H +#define MT_SPM_INTERNAL_H + +#include "mt_spm.h" + +/************************************** + * Config and Parameter + **************************************/ +#define POWER_ON_VAL0_DEF 0x0000F100 +#define POWER_ON_VAL1_DEF 0x80015860 +#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */ +#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT) + +/************************************** + * Define and Declare + **************************************/ +/* PCM_PWR_IO_EN */ +#define PCM_PWRIO_EN_R0 (1U << 0) +#define PCM_PWRIO_EN_R7 (1U << 7) +#define PCM_RF_SYNC_R0 (1U << 16) +#define PCM_RF_SYNC_R6 (1U << 22) +#define PCM_RF_SYNC_R7 (1U << 23) + +/* SPM_SWINT */ +#define PCM_SW_INT0 (1U << 0) +#define PCM_SW_INT1 (1U << 1) +#define PCM_SW_INT2 (1U << 2) +#define PCM_SW_INT3 (1U << 3) +#define PCM_SW_INT4 (1U << 4) +#define PCM_SW_INT5 (1U << 5) +#define PCM_SW_INT6 (1U << 6) +#define PCM_SW_INT7 (1U << 7) +#define PCM_SW_INT8 (1U << 8) +#define PCM_SW_INT9 (1U << 9) +#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \ + PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \ + PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \ + PCM_SW_INT0) + +/* SPM_AP_STANDBY_CON */ +#define WFI_OP_AND 1 +#define WFI_OP_OR 0 + +/* SPM_IRQ_MASK */ +#define ISRM_TWAM (1U << 2) +#define ISRM_PCM_RETURN (1U << 3) +#define ISRM_RET_IRQ0 (1U << 8) +#define ISRM_RET_IRQ1 (1U << 9) +#define ISRM_RET_IRQ2 (1U << 10) +#define ISRM_RET_IRQ3 (1U << 11) +#define ISRM_RET_IRQ4 (1U << 12) +#define ISRM_RET_IRQ5 (1U << 13) +#define ISRM_RET_IRQ6 (1U << 14) +#define ISRM_RET_IRQ7 (1U << 15) +#define ISRM_RET_IRQ8 (1U << 16) +#define ISRM_RET_IRQ9 (1U << 17) +#define ISRM_RET_IRQ_AUX ((ISRM_RET_IRQ9) | (ISRM_RET_IRQ8) | \ + (ISRM_RET_IRQ7) | (ISRM_RET_IRQ6) | \ + (ISRM_RET_IRQ5) | (ISRM_RET_IRQ4) | \ + (ISRM_RET_IRQ3) | (ISRM_RET_IRQ2) | \ + (ISRM_RET_IRQ1)) +#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX) +#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM) + +/* SPM_IRQ_STA */ +#define ISRS_TWAM (1U << 2) +#define ISRS_PCM_RETURN (1U << 3) +#define ISRC_TWAM ISRS_TWAM +#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN +#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM) + +/* SPM_WAKEUP_MISC */ +#define WAKE_MISC_GIC_WAKEUP 0x3FF +#define WAKE_MISC_DVFSRC_IRQ DVFSRC_IRQ_LSB +#define WAKE_MISC_REG_CPU_WAKEUP SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB +#define WAKE_MISC_PCM_TIMER_EVENT PCM_TIMER_EVENT_LSB +#define WAKE_MISC_PMIC_OUT_B ((1U << 19) | (1U << 20)) +#define WAKE_MISC_TWAM_IRQ_B TWAM_IRQ_B_LSB +#define WAKE_MISC_PMSR_IRQ_B_SET0 PMSR_IRQ_B_SET0_LSB +#define WAKE_MISC_PMSR_IRQ_B_SET1 PMSR_IRQ_B_SET1_LSB +#define WAKE_MISC_PMSR_IRQ_B_SET2 PMSR_IRQ_B_SET2_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_0 SPM_ACK_CHK_WAKEUP_0_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_1 SPM_ACK_CHK_WAKEUP_1_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_2 SPM_ACK_CHK_WAKEUP_2_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_3 SPM_ACK_CHK_WAKEUP_3_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_ALL SPM_ACK_CHK_WAKEUP_ALL_LSB +#define WAKE_MISC_PMIC_IRQ_ACK PMIC_IRQ_ACK_LSB +#define WAKE_MISC_PMIC_SCP_IRQ PMIC_SCP_IRQ_LSB + +/* ABORT MASK for DEBUG FOORTPRINT */ +#define DEBUG_ABORT_MASK \ + (SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC | \ + SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN) + +#define DEBUG_ABORT_MASK_1 \ + (SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT | \ + SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT | \ + SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT) + +#define MCUPM_MBOX_WAKEUP_CPU 0x0C55FD10 + +struct pwr_ctrl { + uint32_t pcm_flags; + uint32_t pcm_flags_cust; + uint32_t pcm_flags_cust_set; + uint32_t pcm_flags_cust_clr; + uint32_t pcm_flags1; + uint32_t pcm_flags1_cust; + uint32_t pcm_flags1_cust_set; + uint32_t pcm_flags1_cust_clr; + uint32_t timer_val; + uint32_t timer_val_cust; + uint32_t timer_val_ramp_en; + uint32_t timer_val_ramp_en_sec; + uint32_t wake_src; + uint32_t wake_src_cust; + uint8_t wdt_disable; + + /* SPM_AP_STANDBY_CON */ + uint8_t reg_wfi_op; + uint8_t reg_wfi_type; + uint8_t reg_mp0_cputop_idle_mask; + uint8_t reg_mp1_cputop_idle_mask; + uint8_t reg_mcusys_idle_mask; + uint8_t reg_md_apsrc_1_sel; + uint8_t reg_md_apsrc_0_sel; + uint8_t reg_conn_apsrc_sel; + + /* SPM_SRC_REQ */ + uint8_t reg_spm_apsrc_req; + uint8_t reg_spm_f26m_req; + uint8_t reg_spm_infra_req; + uint8_t reg_spm_vrf18_req; + uint8_t reg_spm_ddr_en_req; + uint8_t reg_spm_dvfs_req; + uint8_t reg_spm_sw_mailbox_req; + uint8_t reg_spm_sspm_mailbox_req; + uint8_t reg_spm_adsp_mailbox_req; + uint8_t reg_spm_scp_mailbox_req; + + /* SPM_SRC_MASK */ + uint8_t reg_sspm_srcclkena_0_mask_b; + uint8_t reg_sspm_infra_req_0_mask_b; + uint8_t reg_sspm_apsrc_req_0_mask_b; + uint8_t reg_sspm_vrf18_req_0_mask_b; + uint8_t reg_sspm_ddr_en_0_mask_b; + uint8_t reg_scp_srcclkena_mask_b; + uint8_t reg_scp_infra_req_mask_b; + uint8_t reg_scp_apsrc_req_mask_b; + uint8_t reg_scp_vrf18_req_mask_b; + uint8_t reg_scp_ddr_en_mask_b; + uint8_t reg_audio_dsp_srcclkena_mask_b; + uint8_t reg_audio_dsp_infra_req_mask_b; + uint8_t reg_audio_dsp_apsrc_req_mask_b; + uint8_t reg_audio_dsp_vrf18_req_mask_b; + uint8_t reg_audio_dsp_ddr_en_mask_b; + uint8_t reg_apu_srcclkena_mask_b; + uint8_t reg_apu_infra_req_mask_b; + uint8_t reg_apu_apsrc_req_mask_b; + uint8_t reg_apu_vrf18_req_mask_b; + uint8_t reg_apu_ddr_en_mask_b; + uint8_t reg_cpueb_srcclkena_mask_b; + uint8_t reg_cpueb_infra_req_mask_b; + uint8_t reg_cpueb_apsrc_req_mask_b; + uint8_t reg_cpueb_vrf18_req_mask_b; + uint8_t reg_cpueb_ddr_en_mask_b; + uint8_t reg_bak_psri_srcclkena_mask_b; + uint8_t reg_bak_psri_infra_req_mask_b; + uint8_t reg_bak_psri_apsrc_req_mask_b; + uint8_t reg_bak_psri_vrf18_req_mask_b; + uint8_t reg_bak_psri_ddr_en_mask_b; + + /* SPM_SRC2_MASK */ + uint8_t reg_msdc0_srcclkena_mask_b; + uint8_t reg_msdc0_infra_req_mask_b; + uint8_t reg_msdc0_apsrc_req_mask_b; + uint8_t reg_msdc0_vrf18_req_mask_b; + uint8_t reg_msdc0_ddr_en_mask_b; + uint8_t reg_msdc1_srcclkena_mask_b; + uint8_t reg_msdc1_infra_req_mask_b; + uint8_t reg_msdc1_apsrc_req_mask_b; + uint8_t reg_msdc1_vrf18_req_mask_b; + uint8_t reg_msdc1_ddr_en_mask_b; + uint8_t reg_msdc2_srcclkena_mask_b; + uint8_t reg_msdc2_infra_req_mask_b; + uint8_t reg_msdc2_apsrc_req_mask_b; + uint8_t reg_msdc2_vrf18_req_mask_b; + uint8_t reg_msdc2_ddr_en_mask_b; + uint8_t reg_ufs_srcclkena_mask_b; + uint8_t reg_ufs_infra_req_mask_b; + uint8_t reg_ufs_apsrc_req_mask_b; + uint8_t reg_ufs_vrf18_req_mask_b; + uint8_t reg_ufs_ddr_en_mask_b; + uint8_t reg_usb_srcclkena_mask_b; + uint8_t reg_usb_infra_req_mask_b; + uint8_t reg_usb_apsrc_req_mask_b; + uint8_t reg_usb_vrf18_req_mask_b; + uint8_t reg_usb_ddr_en_mask_b; + uint8_t reg_pextp_p0_srcclkena_mask_b; + uint8_t reg_pextp_p0_infra_req_mask_b; + uint8_t reg_pextp_p0_apsrc_req_mask_b; + uint8_t reg_pextp_p0_vrf18_req_mask_b; + uint8_t reg_pextp_p0_ddr_en_mask_b; + + /* SPM_SRC3_MASK */ + uint8_t reg_pextp_p1_srcclkena_mask_b; + uint8_t reg_pextp_p1_infra_req_mask_b; + uint8_t reg_pextp_p1_apsrc_req_mask_b; + uint8_t reg_pextp_p1_vrf18_req_mask_b; + uint8_t reg_pextp_p1_ddr_en_mask_b; + uint8_t reg_gce0_infra_req_mask_b; + uint8_t reg_gce0_apsrc_req_mask_b; + uint8_t reg_gce0_vrf18_req_mask_b; + uint8_t reg_gce0_ddr_en_mask_b; + uint8_t reg_gce1_infra_req_mask_b; + uint8_t reg_gce1_apsrc_req_mask_b; + uint8_t reg_gce1_vrf18_req_mask_b; + uint8_t reg_gce1_ddr_en_mask_b; + uint8_t reg_spm_srcclkena_reserved_mask_b; + uint8_t reg_spm_infra_req_reserved_mask_b; + uint8_t reg_spm_apsrc_req_reserved_mask_b; + uint8_t reg_spm_vrf18_req_reserved_mask_b; + uint8_t reg_spm_ddr_en_reserved_mask_b; + uint8_t reg_disp0_apsrc_req_mask_b; + uint8_t reg_disp0_ddr_en_mask_b; + uint8_t reg_disp1_apsrc_req_mask_b; + uint8_t reg_disp1_ddr_en_mask_b; + uint8_t reg_disp2_apsrc_req_mask_b; + uint8_t reg_disp2_ddr_en_mask_b; + uint8_t reg_disp3_apsrc_req_mask_b; + uint8_t reg_disp3_ddr_en_mask_b; + uint8_t reg_infrasys_apsrc_req_mask_b; + uint8_t reg_infrasys_ddr_en_mask_b; + uint8_t reg_cg_check_srcclkena_mask_b; + uint8_t reg_cg_check_apsrc_req_mask_b; + uint8_t reg_cg_check_vrf18_req_mask_b; + uint8_t reg_cg_check_ddr_en_mask_b; + + /* SPM_SRC4_MASK */ + uint32_t reg_mcusys_merge_apsrc_req_mask_b; + uint32_t reg_mcusys_merge_ddr_en_mask_b; + uint8_t reg_dramc_md32_infra_req_mask_b; + uint8_t reg_dramc_md32_vrf18_req_mask_b; + uint8_t reg_dramc_md32_ddr_en_mask_b; + uint8_t reg_dvfsrc_event_trigger_mask_b; + + /* SPM_WAKEUP_EVENT_MASK2 */ + uint8_t reg_sc_sw2spm_wakeup_mask_b; + uint8_t reg_sc_adsp2spm_wakeup_mask_b; + uint8_t reg_sc_sspm2spm_wakeup_mask_b; + uint8_t reg_sc_scp2spm_wakeup_mask_b; + uint8_t reg_csyspwrup_ack_mask; + uint8_t reg_csyspwrup_req_mask; + + /* SPM_WAKEUP_EVENT_MASK */ + uint32_t reg_wakeup_event_mask; + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + uint32_t reg_ext_wakeup_event_mask; +}; + +/* code gen by spm_pwr_ctrl_atf.pl, need struct pwr_ctrl */ +enum pwr_ctrl_enum { + PW_PCM_FLAGS, + PW_PCM_FLAGS_CUST, + PW_PCM_FLAGS_CUST_SET, + PW_PCM_FLAGS_CUST_CLR, + PW_PCM_FLAGS1, + PW_PCM_FLAGS1_CUST, + PW_PCM_FLAGS1_CUST_SET, + PW_PCM_FLAGS1_CUST_CLR, + PW_TIMER_VAL, + PW_TIMER_VAL_CUST, + PW_TIMER_VAL_RAMP_EN, + PW_TIMER_VAL_RAMP_EN_SEC, + PW_WAKE_SRC, + PW_WAKE_SRC_CUST, + PW_WAKELOCK_TIMER_VAL, + PW_WDT_DISABLE, + + /* SPM_CLK_CON */ + PW_REG_SRCCLKEN0_CTL, + PW_REG_SRCCLKEN1_CTL, + PW_REG_SPM_LOCK_INFRA_DCM, + PW_REG_SRCCLKEN_MASK, + PW_REG_MD1_C32RM_EN, + PW_REG_MD2_C32RM_EN, + PW_REG_CLKSQ0_SEL_CTRL, + PW_REG_CLKSQ1_SEL_CTRL, + PW_REG_SRCCLKEN0_EN, + PW_REG_SRCCLKEN1_EN, + PW_REG_SYSCLK0_SRC_MASK_B, + PW_REG_SYSCLK1_SRC_MASK_B, + + /* SPM_AP_STANDBY_CON */ + PW_REG_WFI_OP, + PW_REG_WFI_TYPE, + PW_REG_MP0_CPUTOP_IDLE_MASK, + PW_REG_MP1_CPUTOP_IDLE_MASK, + PW_REG_MCUSYS_IDLE_MASK, + PW_REG_MD_APSRC_1_SEL, + PW_REG_MD_APSRC_0_SEL, + PW_REG_CONN_APSRC_SEL, + + /* SPM_SRC_REQ */ + PW_REG_SPM_APSRC_REQ, + PW_REG_SPM_F26M_REQ, + PW_REG_SPM_INFRA_REQ, + PW_REG_SPM_VRF18_REQ, + PW_REG_SPM_DDR_EN_REQ, + PW_REG_SPM_DVFS_REQ, + PW_REG_SPM_SW_MAILBOX_REQ, + PW_REG_SPM_SSPM_MAILBOX_REQ, + PW_REG_SPM_ADSP_MAILBOX_REQ, + PW_REG_SPM_SCP_MAILBOX_REQ, + + /* SPM_SRC_MASK */ + PW_REG_MD_SRCCLKENA_0_MASK_B, + PW_REG_MD_SRCCLKENA2INFRA_REQ_0_MASK_B, + PW_REG_MD_APSRC2INFRA_REQ_0_MASK_B, + PW_REG_MD_APSRC_REQ_0_MASK_B, + PW_REG_MD_VRF18_REQ_0_MASK_B, + PW_REG_MD_DDR_EN_0_MASK_B, + PW_REG_MD_SRCCLKENA_1_MASK_B, + PW_REG_MD_SRCCLKENA2INFRA_REQ_1_MASK_B, + PW_REG_MD_APSRC2INFRA_REQ_1_MASK_B, + PW_REG_MD_APSRC_REQ_1_MASK_B, + PW_REG_MD_VRF18_REQ_1_MASK_B, + PW_REG_MD_DDR_EN_1_MASK_B, + PW_REG_CONN_SRCCLKENA_MASK_B, + PW_REG_CONN_SRCCLKENB_MASK_B, + PW_REG_CONN_INFRA_REQ_MASK_B, + PW_REG_CONN_APSRC_REQ_MASK_B, + PW_REG_CONN_VRF18_REQ_MASK_B, + PW_REG_CONN_DDR_EN_MASK_B, + PW_REG_CONN_VFE28_MASK_B, + PW_REG_SRCCLKENI0_SRCCLKENA_MASK_B, + PW_REG_SRCCLKENI0_INFRA_REQ_MASK_B, + PW_REG_SRCCLKENI1_SRCCLKENA_MASK_B, + PW_REG_SRCCLKENI1_INFRA_REQ_MASK_B, + PW_REG_SRCCLKENI2_SRCCLKENA_MASK_B, + PW_REG_SRCCLKENI2_INFRA_REQ_MASK_B, + PW_REG_INFRASYS_APSRC_REQ_MASK_B, + PW_REG_INFRASYS_DDR_EN_MASK_B, + PW_REG_MD32_SRCCLKENA_MASK_B, + PW_REG_MD32_INFRA_REQ_MASK_B, + PW_REG_MD32_APSRC_REQ_MASK_B, + PW_REG_MD32_VRF18_REQ_MASK_B, + PW_REG_MD32_DDR_EN_MASK_B, + + /* SPM_SRC2_MASK */ + PW_REG_SCP_SRCCLKENA_MASK_B, + PW_REG_SCP_INFRA_REQ_MASK_B, + PW_REG_SCP_APSRC_REQ_MASK_B, + PW_REG_SCP_VRF18_REQ_MASK_B, + PW_REG_SCP_DDR_EN_MASK_B, + PW_REG_AUDIO_DSP_SRCCLKENA_MASK_B, + PW_REG_AUDIO_DSP_INFRA_REQ_MASK_B, + PW_REG_AUDIO_DSP_APSRC_REQ_MASK_B, + PW_REG_AUDIO_DSP_VRF18_REQ_MASK_B, + PW_REG_AUDIO_DSP_DDR_EN_MASK_B, + PW_REG_UFS_SRCCLKENA_MASK_B, + PW_REG_UFS_INFRA_REQ_MASK_B, + PW_REG_UFS_APSRC_REQ_MASK_B, + PW_REG_UFS_VRF18_REQ_MASK_B, + PW_REG_UFS_DDR_EN_MASK_B, + PW_REG_DISP0_APSRC_REQ_MASK_B, + PW_REG_DISP0_DDR_EN_MASK_B, + PW_REG_DISP1_APSRC_REQ_MASK_B, + PW_REG_DISP1_DDR_EN_MASK_B, + PW_REG_GCE_INFRA_REQ_MASK_B, + PW_REG_GCE_APSRC_REQ_MASK_B, + PW_REG_GCE_VRF18_REQ_MASK_B, + PW_REG_GCE_DDR_EN_MASK_B, + PW_REG_APU_SRCCLKENA_MASK_B, + PW_REG_APU_INFRA_REQ_MASK_B, + PW_REG_APU_APSRC_REQ_MASK_B, + PW_REG_APU_VRF18_REQ_MASK_B, + PW_REG_APU_DDR_EN_MASK_B, + PW_REG_CG_CHECK_SRCCLKENA_MASK_B, + PW_REG_CG_CHECK_APSRC_REQ_MASK_B, + PW_REG_CG_CHECK_VRF18_REQ_MASK_B, + PW_REG_CG_CHECK_DDR_EN_MASK_B, + + /* SPM_SRC3_MASK */ + PW_REG_DVFSRC_EVENT_TRIGGER_MASK_B, + PW_REG_SW2SPM_INT0_MASK_B, + PW_REG_SW2SPM_INT1_MASK_B, + PW_REG_SW2SPM_INT2_MASK_B, + PW_REG_SW2SPM_INT3_MASK_B, + PW_REG_SC_ADSP2SPM_WAKEUP_MASK_B, + PW_REG_SC_SSPM2SPM_WAKEUP_MASK_B, + PW_REG_SC_SCP2SPM_WAKEUP_MASK_B, + PW_REG_CSYSPWRREQ_MASK, + PW_REG_SPM_SRCCLKENA_RESERVED_MASK_B, + PW_REG_SPM_INFRA_REQ_RESERVED_MASK_B, + PW_REG_SPM_APSRC_REQ_RESERVED_MASK_B, + PW_REG_SPM_VRF18_REQ_RESERVED_MASK_B, + PW_REG_SPM_DDR_EN_RESERVED_MASK_B, + PW_REG_MCUPM_SRCCLKENA_MASK_B, + PW_REG_MCUPM_INFRA_REQ_MASK_B, + PW_REG_MCUPM_APSRC_REQ_MASK_B, + PW_REG_MCUPM_VRF18_REQ_MASK_B, + PW_REG_MCUPM_DDR_EN_MASK_B, + PW_REG_MSDC0_SRCCLKENA_MASK_B, + PW_REG_MSDC0_INFRA_REQ_MASK_B, + PW_REG_MSDC0_APSRC_REQ_MASK_B, + PW_REG_MSDC0_VRF18_REQ_MASK_B, + PW_REG_MSDC0_DDR_EN_MASK_B, + PW_REG_MSDC1_SRCCLKENA_MASK_B, + PW_REG_MSDC1_INFRA_REQ_MASK_B, + PW_REG_MSDC1_APSRC_REQ_MASK_B, + PW_REG_MSDC1_VRF18_REQ_MASK_B, + PW_REG_MSDC1_DDR_EN_MASK_B, + + /* SPM_SRC4_MASK */ + PW_CCIF_EVENT_MASK_B, + PW_REG_BAK_PSRI_SRCCLKENA_MASK_B, + PW_REG_BAK_PSRI_INFRA_REQ_MASK_B, + PW_REG_BAK_PSRI_APSRC_REQ_MASK_B, + PW_REG_BAK_PSRI_VRF18_REQ_MASK_B, + PW_REG_BAK_PSRI_DDR_EN_MASK_B, + PW_REG_DRAMC0_MD32_INFRA_REQ_MASK_B, + PW_REG_DRAMC0_MD32_VRF18_REQ_MASK_B, + PW_REG_DRAMC1_MD32_INFRA_REQ_MASK_B, + PW_REG_DRAMC1_MD32_VRF18_REQ_MASK_B, + PW_REG_CONN_SRCCLKENB2PWRAP_MASK_B, + PW_REG_DRAMC0_MD32_WAKEUP_MASK, + PW_REG_DRAMC1_MD32_WAKEUP_MASK, + + /* SPM_SRC5_MASK */ + PW_REG_MCUSYS_MERGE_APSRC_REQ_MASK_B, + PW_REG_MCUSYS_MERGE_DDR_EN_MASK_B, + + /* SPM_WAKEUP_EVENT_MASK */ + PW_REG_WAKEUP_EVENT_MASK, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + PW_REG_EXT_WAKEUP_EVENT_MASK, + + PW_MAX_COUNT, +}; + +#define SPM_INTERNAL_STATUS_HW_S1 (1U << 0) +#define SPM_ACK_CHK_3_SEL_HW_S1 0x00350098 +#define SPM_ACK_CHK_3_HW_S1_CNT 1 +#define SPM_ACK_CHK_3_CON_HW_MODE_TRIG 0x800 +#define SPM_ACK_CHK_3_CON_EN 0x110 +#define SPM_ACK_CHK_3_CON_CLR_ALL 0x2 +#define SPM_ACK_CHK_3_CON_RESULT 0x8000 + +struct wake_status_trace_comm { + uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */ + uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */ + uint32_t timer_out; /* SPM_BK_PCM_TIMER */ + uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */ + uint32_t b_sw_flag1; /* SPM_SW_RSV_8 */ + uint32_t r12; /* SPM_SW_RSV_0 */ + uint32_t r13; /* PCM_REG13_DATA */ + uint32_t req_sta0; /* SRC_REQ_STA_0 */ + uint32_t req_sta1; /* SRC_REQ_STA_1 */ + uint32_t req_sta2; /* SRC_REQ_STA_2 */ + uint32_t req_sta3; /* SRC_REQ_STA_3 */ + uint32_t req_sta4; /* SRC_REQ_STA_4 */ + uint32_t raw_sta; /* SPM_WAKEUP_STA */ + uint32_t times_h; /* timestamp high bits */ + uint32_t times_l; /* timestamp low bits */ + uint32_t resumetime; /* timestamp low bits */ +}; + +struct wake_status_trace { + struct wake_status_trace_comm comm; +}; + +struct wake_status { + struct wake_status_trace tr; + uint32_t r12; /* SPM_BK_WAKE_EVENT */ + uint32_t r12_ext; /* SPM_WAKEUP_STA */ + uint32_t raw_sta; /* SPM_WAKEUP_STA */ + uint32_t raw_ext_sta; /* SPM_WAKEUP_EXT_STA */ + uint32_t md32pcm_wakeup_sta; /* MD32PCM_WAKEUP_STA */ + uint32_t md32pcm_event_sta; /* MD32PCM_EVENT_STA */ + uint32_t src_req; /* SPM_SRC_REQ */ + uint32_t wake_misc; /* SPM_BK_WAKE_MISC */ + uint32_t timer_out; /* SPM_BK_PCM_TIMER */ + uint32_t r13; /* PCM_REG13_DATA */ + uint32_t idle_sta; /* SUBSYS_IDLE_STA */ + uint32_t req_sta0; /* SRC_REQ_STA_0 */ + uint32_t req_sta1; /* SRC_REQ_STA_1 */ + uint32_t req_sta2; /* SRC_REQ_STA_2 */ + uint32_t req_sta3; /* SRC_REQ_STA_3 */ + uint32_t req_sta4; /* SRC_REQ_STA_4 */ + uint32_t cg_check_sta; /* SPM_CG_CHECK_STA */ + uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */ + uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */ + uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */ + uint32_t b_sw_flag1; /* SPM_SW_RSV_8 */ + uint32_t rt_req_sta0; /* SPM_SW_RSV_2 */ + uint32_t rt_req_sta1; /* SPM_SW_RSV_3 */ + uint32_t rt_req_sta2; /* SPM_SW_RSV_4 */ + uint32_t rt_req_sta3; /* SPM_SW_RSV_5 */ + uint32_t rt_req_sta4; /* SPM_SW_RSV_6 */ + uint32_t isr; /* SPM_IRQ_STA */ + uint32_t sw_flag0; /* SPM_SW_FLAG_0 */ + uint32_t sw_flag1; /* SPM_SW_FLAG_1 */ + uint32_t clk_settle; /* SPM_CLK_SETTLE */ + uint32_t abort; +}; + +struct spm_lp_scen { + struct pcm_desc *pcmdesc; + struct pwr_ctrl *pwrctrl; +}; + +extern struct spm_lp_scen __spm_vcorefs; +extern void __spm_set_cpu_status(unsigned int cpu); +extern void __spm_reset_and_init_pcm(const struct pcm_desc *pcmdesc); +extern void __spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc); +extern void __spm_init_pcm_register(void); +extern void __spm_src_req_update(const struct pwr_ctrl *pwrctrl, + unsigned int resource_usage); +extern void __spm_set_power_control(const struct pwr_ctrl *pwrctrl); +extern void __spm_disable_pcm_timer(void); +extern void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl); +extern void __spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl); +extern void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl); +extern void __spm_send_cpu_wakeup_event(void); +extern void __spm_get_wakeup_status(struct wake_status *wakesta, + unsigned int ext_status); +extern void __spm_clean_after_wakeup(void); +extern wake_reason_t +__spm_output_wake_reason(int state_id, const struct wake_status *wakesta); +extern void +__spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl, + const struct pwr_ctrl *src_pwr_ctrl); +extern void __spm_set_pcm_wdt(int en); +extern uint32_t _spm_get_wake_period(int pwake_time, wake_reason_t last_wr); +extern void __spm_set_fw_resume_option(struct pwr_ctrl *pwrctrl); +extern void __spm_ext_int_wakeup_req_clr(void); +extern void __spm_xo_soc_bblpm(int en); + +static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl, + uint32_t flags) +{ + if (pwrctrl->pcm_flags_cust == 0U) { + pwrctrl->pcm_flags = flags; + } else { + pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust; + } +} + +static inline void set_pwrctrl_pcm_flags1(struct pwr_ctrl *pwrctrl, + uint32_t flags) +{ + if (pwrctrl->pcm_flags1_cust == 0U) { + pwrctrl->pcm_flags1 = flags; + } else { + pwrctrl->pcm_flags1 = pwrctrl->pcm_flags1_cust; + } +} + +extern void __spm_hw_s1_state_monitor(int en, unsigned int *status); + +static inline void spm_hw_s1_state_monitor_resume(void) +{ + __spm_hw_s1_state_monitor(1, NULL); +} + +static inline void spm_hw_s1_state_monitor_pause(unsigned int *status) +{ + __spm_hw_s1_state_monitor(0, status); +} +#endif /* MT_SPM_INTERNAL_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c new file mode 100644 index 0000000..9da644c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* PMIC_WRAP MT6359 */ +#define VCORE_BASE_UV 40000 +#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625) +#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + VCORE_BASE_UV) + +#define NR_PMIC_WRAP_CMD (NR_IDX_ALL) +#define SPM_DATA_SHIFT 16 + +#define BUCK_VGPU11_ELR0 0x15B4 +#define TOP_SPI_CON0 0x0456 +#define BUCK_TOP_CON1 0x1443 +#define TOP_CON 0x0013 +#define TOP_DIG_WPK 0x03a9 +#define TOP_CON_LOCK 0x03a8 +#define TOP_CLK_CON0 0x0134 + +struct pmic_wrap_cmd { + unsigned long cmd_addr; + unsigned long cmd_wdata; +}; + +struct pmic_wrap_setting { + enum pmic_wrap_phase_id phase; + struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD]; + struct { + struct { + unsigned long cmd_addr; + unsigned long cmd_wdata; + } _[NR_PMIC_WRAP_CMD]; + const int nr_idx; + } set[NR_PMIC_WRAP_PHASE]; +}; + +static struct pmic_wrap_setting pw = { + .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */ + .addr = { {0UL, 0UL} }, + .set[PMIC_WRAP_PHASE_ALLINONE] = { + ._[CMD_0] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(75000),}, + ._[CMD_1] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(65000),}, + ._[CMD_2] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(60000),}, + ._[CMD_3] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(55000),}, + ._[CMD_4] = {TOP_SPI_CON0, 0x1,}, + ._[CMD_5] = {TOP_SPI_CON0, 0x0,}, + ._[CMD_6] = {BUCK_TOP_CON1, 0x0,}, + ._[CMD_7] = {BUCK_TOP_CON1, 0xf,}, + ._[CMD_8] = {TOP_CON, 0x3,}, + ._[CMD_9] = {TOP_CON, 0x0,}, + ._[CMD_10] = {TOP_DIG_WPK, 0x63,}, + ._[CMD_11] = {TOP_CON_LOCK, 0x15,}, + ._[CMD_12] = {TOP_DIG_WPK, 0x0,}, + ._[CMD_13] = {TOP_CON_LOCK, 0x0,}, + ._[CMD_14] = {TOP_CLK_CON0, 0x40,}, + ._[CMD_15] = {TOP_CLK_CON0, 0x0,}, + .nr_idx = NR_IDX_ALL, + }, +}; + +void _mt_spm_pmic_table_init(void) +{ + struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = { + {(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,}, + {(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,}, + {(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,}, + {(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,}, + {(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,}, + {(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,}, + {(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,}, + {(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,}, + {(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,}, + {(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,}, + {(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,}, + {(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,}, + {(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,}, + {(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,}, + {(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,}, + {(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,}, + }; + + memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default)); +} + +void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase) +{ + uint32_t idx, addr, data; + + if (phase >= NR_PMIC_WRAP_PHASE) { + return; + } + + if (pw.phase == phase) { + return; + } + + if (pw.addr[0].cmd_addr == 0UL) { + _mt_spm_pmic_table_init(); + } + + pw.phase = phase; + mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); + + for (idx = 0U; idx < pw.set[phase].nr_idx; idx++) { + addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; + data = pw.set[phase]._[idx].cmd_wdata; + mmio_write_32(pw.addr[idx].cmd_addr, addr | data); + } +} + +void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx, + uint32_t cmd_wdata) +{ + uint32_t addr; + + if (phase >= NR_PMIC_WRAP_PHASE) { + return; + } + + if (idx >= pw.set[phase].nr_idx) { + return; + } + + pw.set[phase]._[idx].cmd_wdata = cmd_wdata; + mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); + + if (pw.phase == phase) { + addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; + mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata); + } +} + +uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx) +{ + if (phase >= NR_PMIC_WRAP_PHASE) { + return 0UL; + } + + if (idx >= pw.set[phase].nr_idx) { + return 0UL; + } + + return pw.set[phase]._[idx].cmd_wdata; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h new file mode 100644 index 0000000..53fdda2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/**************************************************************** + * Auto generated by DE, please DO NOT modify this file directly. + *****************************************************************/ +#ifndef MT_SPM_PMIC_WRAP_H +#define MT_SPM_PMIC_WRAP_H + +enum pmic_wrap_phase_id { + PMIC_WRAP_PHASE_ALLINONE, + NR_PMIC_WRAP_PHASE, +}; + +/* IDX mapping, PMIC_WRAP_PHASE_ALLINONE */ +enum { + CMD_0, /* 0x0 */ + CMD_1, /* 0x1 */ + CMD_2, /* 0x2 */ + CMD_3, /* 0x3 */ + CMD_4, /* 0x4 */ + CMD_5, /* 0x5 */ + CMD_6, /* 0x6 */ + CMD_7, /* 0x7 */ + CMD_8, /* 0x8 */ + CMD_9, /* 0x9 */ + CMD_10, /* 0xA */ + CMD_11, /* 0xB */ + CMD_12, /* 0xC */ + CMD_13, /* 0xD */ + CMD_14, /* 0xE */ + CMD_15, /* 0xF */ + NR_IDX_ALL, +}; + +/* APIs */ +extern void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase); +extern void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, + uint32_t idx, uint32_t cmd_wdata); +extern uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, + uint32_t idx); +#endif /* MT_SPM_PMIC_WRAP_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h new file mode 100644 index 0000000..d8b9b29 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h @@ -0,0 +1,2859 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/**************************************************************** + * Auto generated by DE, please DO NOT modify this file directly. + *****************************************************************/ + +#ifndef MT_SPM_REG +#define MT_SPM_REG + +#include "sleep_def.h" +#include +#include "pcm_def.h" + +/************************************** + * Define and Declare + **************************************/ + +/*******Register_SPM_CFG*************************************************/ +#define POWERON_CONFIG_EN (SPM_BASE + 0x000) +#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004) +#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008) +#define SPM_CLK_CON (SPM_BASE + 0x00C) +#define SPM_CLK_SETTLE (SPM_BASE + 0x010) +#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014) +#define PCM_CON0 (SPM_BASE + 0x018) +#define PCM_CON1 (SPM_BASE + 0x01C) +#define SPM_POWER_ON_VAL2 (SPM_BASE + 0x020) +#define SPM_POWER_ON_VAL3 (SPM_BASE + 0x024) +#define PCM_REG_DATA_INI (SPM_BASE + 0x028) +#define PCM_PWR_IO_EN (SPM_BASE + 0x02C) +#define PCM_TIMER_VAL (SPM_BASE + 0x030) +#define PCM_WDT_VAL (SPM_BASE + 0x034) +#define SPM_SW_RST_CON (SPM_BASE + 0x040) +#define SPM_SW_RST_CON_SET (SPM_BASE + 0x044) +#define SPM_SW_RST_CON_CLR (SPM_BASE + 0x048) +#define VS1_PSR_MASK_B (SPM_BASE + 0x04C) +#define SPM_ARBITER_EN (SPM_BASE + 0x050) +#define SCPSYS_CLK_CON (SPM_BASE + 0x054) +#define SPM_SRAM_RSV_CON (SPM_BASE + 0x058) +#define SPM_SWINT (SPM_BASE + 0x05C) +#define SPM_SWINT_SET (SPM_BASE + 0x060) +#define SPM_SWINT_CLR (SPM_BASE + 0x064) +#define SPM_SCP_MAILBOX (SPM_BASE + 0x068) +#define SCP_SPM_MAILBOX (SPM_BASE + 0x06C) +#define SPM_SCP_IRQ (SPM_BASE + 0x070) +#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x074) +#define SPM_IRQ_MASK (SPM_BASE + 0x078) +#define SPM_SRC_REQ (SPM_BASE + 0x080) +#define SPM_SRC_MASK (SPM_BASE + 0x084) +#define SPM_SRC2_MASK (SPM_BASE + 0x088) +#define SPM_SRC3_MASK (SPM_BASE + 0x090) +#define SPM_SRC4_MASK (SPM_BASE + 0x094) +#define SPM_WAKEUP_EVENT_MASK2 (SPM_BASE + 0x098) +#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x09C) +#define SPM_WAKEUP_EVENT_SENS (SPM_BASE + 0x0A0) +#define SPM_WAKEUP_EVENT_CLEAR (SPM_BASE + 0x0A4) +#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0A8) +#define SCP_CLK_CON (SPM_BASE + 0x0AC) +#define PCM_DEBUG_CON (SPM_BASE + 0x0B0) +#define DDREN_DBC_CON (SPM_BASE + 0x0B4) +#define SPM_RESOURCE_ACK_CON0 (SPM_BASE + 0x0B8) +#define SPM_RESOURCE_ACK_CON1 (SPM_BASE + 0x0BC) +#define SPM_RESOURCE_ACK_CON2 (SPM_BASE + 0x0C0) +#define SPM_RESOURCE_ACK_CON3 (SPM_BASE + 0x0C4) +#define SPM_RESOURCE_ACK_CON4 (SPM_BASE + 0x0C8) +#define SPM_SRAM_CON (SPM_BASE + 0x0CC) +/*******Register_SPM_STA*************************************************/ +#define PCM_REG0_DATA (SPM_BASE + 0x100) +#define PCM_REG2_DATA (SPM_BASE + 0x104) +#define PCM_REG6_DATA (SPM_BASE + 0x108) +#define PCM_REG7_DATA (SPM_BASE + 0x10C) +#define PCM_REG13_DATA (SPM_BASE + 0x110) +#define SRC_REQ_STA_0 (SPM_BASE + 0x114) +#define SRC_REQ_STA_1 (SPM_BASE + 0x118) +#define SRC_REQ_STA_2 (SPM_BASE + 0x120) +#define SRC_REQ_STA_3 (SPM_BASE + 0x124) +#define SRC_REQ_STA_4 (SPM_BASE + 0x128) +#define PCM_TIMER_OUT (SPM_BASE + 0x130) +#define PCM_WDT_OUT (SPM_BASE + 0x134) +#define SPM_IRQ_STA (SPM_BASE + 0x138) +#define MD32PCM_WAKEUP_STA (SPM_BASE + 0x13C) +#define MD32PCM_EVENT_STA (SPM_BASE + 0x140) +#define SPM_WAKEUP_STA (SPM_BASE + 0x144) +#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x148) +#define SPM_WAKEUP_MISC (SPM_BASE + 0x14C) +#define MM_DVFS_HALT (SPM_BASE + 0x150) +#define SUBSYS_IDLE_STA (SPM_BASE + 0x164) +#define PCM_STA (SPM_BASE + 0x168) +#define PWR_STATUS (SPM_BASE + 0x16C) +#define PWR_STATUS_2ND (SPM_BASE + 0x170) +#define CPU_PWR_STATUS (SPM_BASE + 0x174) +#define CPU_PWR_STATUS_2ND (SPM_BASE + 0x178) +#define SPM_VTCXO_EVENT_COUNT_STA (SPM_BASE + 0x17C) +#define SPM_INFRA_EVENT_COUNT_STA (SPM_BASE + 0x180) +#define SPM_VRF18_EVENT_COUNT_STA (SPM_BASE + 0x184) +#define SPM_APSRC_EVENT_COUNT_STA (SPM_BASE + 0x188) +#define SPM_DDREN_EVENT_COUNT_STA (SPM_BASE + 0x18C) +#define MD32PCM_STA (SPM_BASE + 0x190) +#define MD32PCM_PC (SPM_BASE + 0x194) +#define OTHER_PWR_STATUS (SPM_BASE + 0x198) +#define DVFSRC_EVENT_STA (SPM_BASE + 0x19C) +#define BUS_PROTECT_RDY (SPM_BASE + 0x1A0) +#define BUS_PROTECT1_RDY (SPM_BASE + 0x1A4) +#define BUS_PROTECT2_RDY (SPM_BASE + 0x1A8) +#define BUS_PROTECT3_RDY (SPM_BASE + 0x1AC) +#define BUS_PROTECT4_RDY (SPM_BASE + 0x1B0) +#define BUS_PROTECT5_RDY (SPM_BASE + 0x1B4) +#define BUS_PROTECT6_RDY (SPM_BASE + 0x1B8) +#define BUS_PROTECT7_RDY (SPM_BASE + 0x1BC) +#define BUS_PROTECT8_RDY (SPM_BASE + 0x1C0) +#define BUS_PROTECT9_RDY (SPM_BASE + 0x1C4) +#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1D0) +#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1D4) +#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1D8) +#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1DC) +#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1E0) +#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1E4) +#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1E8) +#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1EC) +#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1F0) +#define SPM_CG_CHECK_STA (SPM_BASE + 0x1F4) +#define SPM_DVFS_STA (SPM_BASE + 0x1F8) +#define SPM_DVFS_OPP_STA (SPM_BASE + 0x1FC) +/*******Register_CPU_MT*************************************************/ +#define CPUEB_PWR_CON (SPM_BASE + 0x200) +#define SPM_MCUSYS_PWR_CON (SPM_BASE + 0x204) +#define SPM_CPUTOP_PWR_CON (SPM_BASE + 0x208) +#define SPM_CPU0_PWR_CON (SPM_BASE + 0x20C) +#define SPM_CPU1_PWR_CON (SPM_BASE + 0x210) +#define SPM_CPU2_PWR_CON (SPM_BASE + 0x214) +#define SPM_CPU3_PWR_CON (SPM_BASE + 0x218) +#define SPM_CPU4_PWR_CON (SPM_BASE + 0x21C) +#define SPM_CPU5_PWR_CON (SPM_BASE + 0x220) +#define SPM_CPU6_PWR_CON (SPM_BASE + 0x224) +#define SPM_CPU7_PWR_CON (SPM_BASE + 0x228) +#define ARMPLL_CLK_CON (SPM_BASE + 0x22C) +#define MCUSYS_IDLE_STA (SPM_BASE + 0x230) +#define GIC_WAKEUP_STA (SPM_BASE + 0x234) +#define CPU_SPARE_CON (SPM_BASE + 0x238) +#define CPU_SPARE_CON_SET (SPM_BASE + 0x23C) +#define CPU_SPARE_CON_CLR (SPM_BASE + 0x240) +#define ARMPLL_CLK_SEL (SPM_BASE + 0x244) +#define EXT_INT_WAKEUP_REQ (SPM_BASE + 0x248) +#define EXT_INT_WAKEUP_REQ_SET (SPM_BASE + 0x24C) +#define EXT_INT_WAKEUP_REQ_CLR (SPM_BASE + 0x250) +#define CPU0_IRQ_MASK (SPM_BASE + 0x260) +#define CPU_IRQ_MASK_SET (SPM_BASE + 0x264) +#define CPU_IRQ_MASK_CLR (SPM_BASE + 0x268) +#define CPU_WFI_EN (SPM_BASE + 0x280) +#define CPU_WFI_EN_SET (SPM_BASE + 0x284) +#define CPU_WFI_EN_CLR (SPM_BASE + 0x288) +#define SYSRAM_CON (SPM_BASE + 0x290) +#define SYSROM_CON (SPM_BASE + 0x294) +#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x2A0) +#define ROOT_CORE_ADDR (SPM_BASE + 0x2A4) +#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x2D0) +#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x2D4) +#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x2D8) +#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x2DC) +#define SW2SPM_INT (SPM_BASE + 0x2E0) +#define SW2SPM_INT_SET (SPM_BASE + 0x2E4) +#define SW2SPM_INT_CLR (SPM_BASE + 0x2E8) +#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x2EC) +#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x2F0) +#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x2F4) +#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x2F8) +#define SW2SPM_CFG (SPM_BASE + 0x2FC) +/*******Register_NONCPU_MT*************************************************/ +#define MFG0_PWR_CON (SPM_BASE + 0x300) +#define MFG1_PWR_CON (SPM_BASE + 0x304) +#define MFG2_PWR_CON (SPM_BASE + 0x308) +#define MFG3_PWR_CON (SPM_BASE + 0x30C) +#define MFG4_PWR_CON (SPM_BASE + 0x310) +#define MFG5_PWR_CON (SPM_BASE + 0x314) +#define MFG6_PWR_CON (SPM_BASE + 0x318) +#define IFR_PWR_CON (SPM_BASE + 0x31C) +#define IFR_SUB_PWR_CON (SPM_BASE + 0x320) +#define PERI_PWR_CON (SPM_BASE + 0x324) +#define PEXTP_MAC_TOP_P0_PWR_CON (SPM_BASE + 0x328) +#define PEXTP_MAC_TOP_P1_PWR_CON (SPM_BASE + 0x32C) +#define PCIE_PHY_PWR_CON (SPM_BASE + 0x330) +#define SSUSB_PCIE_PHY_PWR_CON (SPM_BASE + 0x334) +#define SSUSB_TOP_P1_PWR_CON (SPM_BASE + 0x338) +#define SSUSB_TOP_P2_PWR_CON (SPM_BASE + 0x33C) +#define SSUSB_TOP_P3_PWR_CON (SPM_BASE + 0x340) +#define ETHER_PWR_CON (SPM_BASE + 0x344) +#define DPY0_PWR_CON (SPM_BASE + 0x348) +#define DPY1_PWR_CON (SPM_BASE + 0x34C) +#define DPM0_PWR_CON (SPM_BASE + 0x350) +#define DPM1_PWR_CON (SPM_BASE + 0x354) +#define AUDIO_PWR_CON (SPM_BASE + 0x358) +#define AUDIO_ASRC_PWR_CON (SPM_BASE + 0x35C) +#define ADSP_PWR_CON (SPM_BASE + 0x360) +#define VPPSYS0_PWR_CON (SPM_BASE + 0x364) +#define VPPSYS1_PWR_CON (SPM_BASE + 0x368) +#define VDOSYS0_PWR_CON (SPM_BASE + 0x36C) +#define VDOSYS1_PWR_CON (SPM_BASE + 0x370) +#define WPESYS_PWR_CON (SPM_BASE + 0x374) +#define DP_TX_PWR_CON (SPM_BASE + 0x378) +#define EDP_TX_PWR_CON (SPM_BASE + 0x37C) +#define HDMI_TX_PWR_CON (SPM_BASE + 0x380) +#define HDMI_RX_PWR_CON (SPM_BASE + 0x384) +#define VDE0_PWR_CON (SPM_BASE + 0x388) +#define VDE1_PWR_CON (SPM_BASE + 0x38C) +#define VDE2_PWR_CON (SPM_BASE + 0x390) +#define VEN_PWR_CON (SPM_BASE + 0x394) +#define VEN_CORE1_PWR_CON (SPM_BASE + 0x398) +#define CAM_PWR_CON (SPM_BASE + 0x39C) +#define CAM_RAWA_PWR_CON (SPM_BASE + 0x3A0) +#define CAM_RAWB_PWR_CON (SPM_BASE + 0x3A4) +#define CAM_RAWC_PWR_CON (SPM_BASE + 0x3A8) +#define IMG_M_PWR_CON (SPM_BASE + 0x3AC) +#define IMG_D_PWR_CON (SPM_BASE + 0x3B0) +#define IPE_PWR_CON (SPM_BASE + 0x3B4) +#define NNA0_PWR_CON (SPM_BASE + 0x3B8) +#define NNA1_PWR_CON (SPM_BASE + 0x3BC) +#define IPNNA_PWR_CON (SPM_BASE + 0x3C0) +#define CSI_RX_TOP_PWR_CON (SPM_BASE + 0x3C4) +#define SSPM_SRAM_CON (SPM_BASE + 0x3C4) +#define SCP_SRAM_CON (SPM_BASE + 0x3D0) +#define UFS_SRAM_CON (SPM_BASE + 0x3D4) +#define DEVAPC_IFR_SRAM_CON (SPM_BASE + 0x3D8) +#define DEVAPC_SUBIFR_SRAM_CON (SPM_BASE + 0x3DC) +#define DEVAPC_ACP_SRAM_CON (SPM_BASE + 0x3E0) +#define USB_SRAM_CON (SPM_BASE + 0x3E4) +#define DUMMY_SRAM_CO (SPM_BASE + 0x3E8) +#define EXT_BUCK_ISO (SPM_BASE + 0x3EC) +#define MSDC_SRAM_CON (SPM_BASE + 0x3F0) +#define DEBUGTOP_SRAM (SPM_BASE + 0x3F4) +#define DPMAIF_SRAM_C (SPM_BASE + 0x3F8) +#define GCPU_SRAM_CON (SPM_BASE + 0x3FC) +/*******Register_DIRC_IF*************************************************/ +#define SPM_MEM_CK_SEL (SPM_BASE + 0x400) +#define SPM_BUS_PROTECT_MASK_B (SPM_BASE + 0x404) +#define SPM_BUS_PROTECT1_MASK_B (SPM_BASE + 0x408) +#define SPM_BUS_PROTECT2_MASK_B (SPM_BASE + 0x40C) +#define SPM_BUS_PROTECT3_MASK_B (SPM_BASE + 0x410) +#define SPM_BUS_PROTECT4_MASK_B (SPM_BASE + 0x414) +#define SPM_BUS_PROTECT5_MASK_B (SPM_BASE + 0x418) +#define SPM_BUS_PROTECT6_MASK_B (SPM_BASE + 0x41C) +#define SPM_BUS_PROTECT7_MASK_B (SPM_BASE + 0x420) +#define SPM_BUS_PROTECT8_MASK_B (SPM_BASE + 0x424) +#define SPM_BUS_PROTECT9_MASK_B (SPM_BASE + 0x428) +#define SPM_EMI_BW_MODE (SPM_BASE + 0x42C) +#define SPM2MM_CON (SPM_BASE + 0x434) +#define SPM2CPUEB_CON (SPM_BASE + 0x438) +#define AP_MDSRC_REQ (SPM_BASE + 0x43C) +#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x440) +#define SPM_PLL_CON (SPM_BASE + 0x444) +#define RC_SPM_CTRL (SPM_BASE + 0x448) +#define SPM_DRAM_MCU_SW_CON_0 (SPM_BASE + 0x44C) +#define SPM_DRAM_MCU_SW_CON_1 (SPM_BASE + 0x450) +#define SPM_DRAM_MCU_SW_CON_2 (SPM_BASE + 0x454) +#define SPM_DRAM_MCU_SW_CON_3 (SPM_BASE + 0x458) +#define SPM_DRAM_MCU_SW_CON_4 (SPM_BASE + 0x45C) +#define SPM_DRAM_MCU_STA_0 (SPM_BASE + 0x460) +#define SPM_DRAM_MCU_STA_1 (SPM_BASE + 0x464) +#define SPM_DRAM_MCU_STA_2 (SPM_BASE + 0x468) +#define SPM_DRAM_MCU_SW_SEL_0 (SPM_BASE + 0x46C) +#define RELAY_DVFS_LEVEL (SPM_BASE + 0x470) +#define DRAMC_DPY_CLK_SW_CON_0 (SPM_BASE + 0x474) +#define DRAMC_DPY_CLK_SW_CON_1 (SPM_BASE + 0x478) +#define DRAMC_DPY_CLK_SW_CON_2 (SPM_BASE + 0x47C) +#define DRAMC_DPY_CLK_SW_CON_3 (SPM_BASE + 0x480) +#define DRAMC_DPY_CLK_SW_SEL_0 (SPM_BASE + 0x484) +#define DRAMC_DPY_CLK_SW_SEL_1 (SPM_BASE + 0x488) +#define DRAMC_DPY_CLK_SW_SEL_2 (SPM_BASE + 0x48C) +#define DRAMC_DPY_CLK_SW_SEL_3 (SPM_BASE + 0x490) +#define DRAMC_DPY_CLK_SPM_CON (SPM_BASE + 0x494) +#define SPM_DVFS_LEVEL (SPM_BASE + 0x498) +#define SPM_CIRQ_CON (SPM_BASE + 0x49C) +#define SPM_DVFS_MISC (SPM_BASE + 0x4A0) +#define RG_MODULE_SW_CG_0_MASK_REQ_0 (SPM_BASE + 0x4A4) +#define RG_MODULE_SW_CG_0_MASK_REQ_1 (SPM_BASE + 0x4A8) +#define RG_MODULE_SW_CG_0_MASK_REQ_2 (SPM_BASE + 0x4AC) +#define RG_MODULE_SW_CG_1_MASK_REQ_0 (SPM_BASE + 0x4B0) +#define RG_MODULE_SW_CG_1_MASK_REQ_1 (SPM_BASE + 0x4B4) +#define RG_MODULE_SW_CG_1_MASK_REQ_2 (SPM_BASE + 0x4B8) +#define RG_MODULE_SW_CG_2_MASK_REQ_0 (SPM_BASE + 0x4BC) +#define RG_MODULE_SW_CG_2_MASK_REQ_1 (SPM_BASE + 0x4C0) +#define RG_MODULE_SW_CG_2_MASK_REQ_2 (SPM_BASE + 0x4C4) +#define RG_MODULE_SW_CG_3_MASK_REQ_0 (SPM_BASE + 0x4C8) +#define RG_MODULE_SW_CG_3_MASK_REQ_1 (SPM_BASE + 0x4CC) +#define RG_MODULE_SW_CG_3_MASK_REQ_2 (SPM_BASE + 0x4D0) +#define PWR_STATUS_MASK_REQ_0 (SPM_BASE + 0x4D4) +#define PWR_STATUS_MASK_REQ_1 (SPM_BASE + 0x4D8) +#define PWR_STATUS_MASK_REQ_2 (SPM_BASE + 0x4DC) +#define SPM_CG_CHECK_CON (SPM_BASE + 0x4E0) +#define SPM_SRC_RDY_STA (SPM_BASE + 0x4E4) +#define SPM_DVS_DFS_LEVEL (SPM_BASE + 0x4E8) +#define SPM_FORCE_DVFS (SPM_BASE + 0x4EC) +#define DRAMC_MCU_SRAM_CON (SPM_BASE + 0x4F0) +#define DRAMC_MCU2_SRAM_CON (SPM_BASE + 0x4F4) +#define DPY_SHU_SRAM_CON (SPM_BASE + 0x4F8) +#define DPY_SHU2_SRAM_CON (SPM_BASE + 0x4FC) +/*******The Others*************************************************/ +#define SRCLKEN_RC_CFG (SPM_BASE + 0x500) +#define RC_CENTRAL_CFG1 (SPM_BASE + 0x504) +#define RC_CENTRAL_CFG2 (SPM_BASE + 0x508) +#define RC_CMD_ARB_CFG (SPM_BASE + 0x50C) +#define RC_PMIC_RCEN_ADDR (SPM_BASE + 0x510) +#define RC_PMIC_RCEN_SET_CLR_ADDR (SPM_BASE + 0x514) +#define RC_DCXO_FPM_CFG (SPM_BASE + 0x518) +#define RC_CENTRAL_CFG3 (SPM_BASE + 0x51C) +#define RC_M00_SRCLKEN_CFG (SPM_BASE + 0x520) +#define RC_M01_SRCLKEN_CFG (SPM_BASE + 0x524) +#define RC_M02_SRCLKEN_CFG (SPM_BASE + 0x528) +#define RC_M03_SRCLKEN_CFG (SPM_BASE + 0x52C) +#define RC_M04_SRCLKEN_CFG (SPM_BASE + 0x530) +#define RC_M05_SRCLKEN_CFG (SPM_BASE + 0x534) +#define RC_M06_SRCLKEN_CFG (SPM_BASE + 0x538) +#define RC_M07_SRCLKEN_CFG (SPM_BASE + 0x53C) +#define RC_M08_SRCLKEN_CFG (SPM_BASE + 0x540) +#define RC_M09_SRCLKEN_CFG (SPM_BASE + 0x544) +#define RC_M10_SRCLKEN_CFG (SPM_BASE + 0x548) +#define RC_M11_SRCLKEN_CFG (SPM_BASE + 0x54C) +#define RC_M12_SRCLKEN_CFG (SPM_BASE + 0x550) +#define RC_SRCLKEN_SW_CON_CFG (SPM_BASE + 0x554) +#define RC_CENTRAL_CFG4 (SPM_BASE + 0x558) +#define RC_PROTOCOL_CHK_CFG (SPM_BASE + 0x560) +#define RC_DEBUG_CFG (SPM_BASE + 0x564) +#define RC_MISC_0 (SPM_BASE + 0x5B4) + +#define SUBSYS_INTF_CFG (SPM_BASE + 0x5BC) +#define PCM_WDT_LATCH_25 (SPM_BASE + 0x5C0) +#define PCM_WDT_LATCH_26 (SPM_BASE + 0x5C4) +#define PCM_WDT_LATCH_27 (SPM_BASE + 0x5C8) +#define PCM_WDT_LATCH_28 (SPM_BASE + 0x5CC) +#define PCM_WDT_LATCH_29 (SPM_BASE + 0x5D0) +#define PCM_WDT_LATCH_30 (SPM_BASE + 0x5D4) +#define PCM_WDT_LATCH_31 (SPM_BASE + 0x5D8) +#define PCM_WDT_LATCH_32 (SPM_BASE + 0x5DC) +#define PCM_WDT_LATCH_33 (SPM_BASE + 0x5E0) +#define PCM_WDT_LATCH_34 (SPM_BASE + 0x5E4) +#define PCM_WDT_LATCH_35 (SPM_BASE + 0x5EC) +#define PCM_WDT_LATCH_36 (SPM_BASE + 0x5F0) +#define PCM_WDT_LATCH_37 (SPM_BASE + 0x5F4) +#define PCM_WDT_LATCH_38 (SPM_BASE + 0x5F8) +#define PCM_WDT_LATCH_39 (SPM_BASE + 0x5FC) +/*******Register_RSV*************************************************/ +#define SPM_SW_FLAG_0 (SPM_BASE + 0x600) +#define SPM_SW_DEBUG_0 (SPM_BASE + 0x604) +#define SPM_SW_FLAG_1 (SPM_BASE + 0x608) +#define SPM_SW_DEBUG_1 (SPM_BASE + 0x60C) +#define SPM_SW_RSV_0 (SPM_BASE + 0x610) +#define SPM_SW_RSV_1 (SPM_BASE + 0x614) +#define SPM_SW_RSV_2 (SPM_BASE + 0x618) +#define SPM_SW_RSV_3 (SPM_BASE + 0x61C) +#define SPM_SW_RSV_4 (SPM_BASE + 0x620) +#define SPM_SW_RSV_5 (SPM_BASE + 0x624) +#define SPM_SW_RSV_6 (SPM_BASE + 0x628) +#define SPM_SW_RSV_7 (SPM_BASE + 0x62C) +#define SPM_SW_RSV_8 (SPM_BASE + 0x630) +#define SPM_BK_WAKE_EVENT (SPM_BASE + 0x634) +#define SPM_BK_VTCXO_DUR (SPM_BASE + 0x638) +#define SPM_BK_WAKE_MISC (SPM_BASE + 0x63C) +#define SPM_BK_PCM_TIMER (SPM_BASE + 0x640) +#define ULPOSC_CON (SPM_BASE + 0x644) +#define SPM_RSV_CON_0 (SPM_BASE + 0x650) +#define SPM_RSV_CON_1 (SPM_BASE + 0x654) +#define SPM_RSV_STA_0 (SPM_BASE + 0x658) +#define SPM_RSV_STA_1 (SPM_BASE + 0x65C) +#define SPM_SPARE_CON (SPM_BASE + 0x660) +#define SPM_SPARE_CON_SET (SPM_BASE + 0x664) +#define SPM_SPARE_CON_CLR (SPM_BASE + 0x668) +#define SPM_CROSS_WAKE_M00_REQ (SPM_BASE + 0x66C) +#define SPM_CROSS_WAKE_M01_REQ (SPM_BASE + 0x670) +#define SPM_CROSS_WAKE_M02_REQ (SPM_BASE + 0x674) +#define SPM_CROSS_WAKE_M03_REQ (SPM_BASE + 0x678) +#define SCP_VCORE_LEVEL (SPM_BASE + 0x67C) +#define SC_MM_CK_SEL_CON (SPM_BASE + 0x680) +#define SPARE_ACK_MASK (SPM_BASE + 0x684) +#define SPM_DV_CON_0 (SPM_BASE + 0x68C) +#define SPM_DV_CON_1 (SPM_BASE + 0x690) +#define SPM_DV_STA (SPM_BASE + 0x694) +#define CONN_XOWCN_DEBUG_EN (SPM_BASE + 0x698) +#define SPM_SEMA_M0 (SPM_BASE + 0x69C) +#define SPM_SEMA_M1 (SPM_BASE + 0x6A0) +#define SPM_SEMA_M2 (SPM_BASE + 0x6A4) +#define SPM_SEMA_M3 (SPM_BASE + 0x6A8) +#define SPM_SEMA_M4 (SPM_BASE + 0x6AC) +#define SPM_SEMA_M5 (SPM_BASE + 0x6B0) +#define SPM_SEMA_M6 (SPM_BASE + 0x6B4) +#define SPM_SEMA_M7 (SPM_BASE + 0x6B8) +#define SPM2ADSP_MAILBOX (SPM_BASE + 0x6BC) +#define ADSP2SPM_MAILBOX (SPM_BASE + 0x6C0) +#define SPM_ADSP_IRQ (SPM_BASE + 0x6C4) +#define SPM_MD32_IRQ (SPM_BASE + 0x6C8) +#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x6CC) +#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x6D0) +#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x6D4) +#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x6D8) +#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x6DC) +#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x6E0) +#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x6E4) +#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x6E8) +#define UFS_PSRI_SW (SPM_BASE + 0x6EC) +#define UFS_PSRI_SW_SET (SPM_BASE + 0x6F0) +#define UFS_PSRI_SW_CLR (SPM_BASE + 0x6F4) +#define SPM_AP_SEMA (SPM_BASE + 0x6F8) +#define SPM_SPM_SEMA (SPM_BASE + 0x6FC) +/*******Register_DVFS_TAB*************************************************/ +#define SPM_DVFS_CON (SPM_BASE + 0x700) +#define SPM_DVFS_CON_STA (SPM_BASE + 0x704) +#define SPM_PMIC_SPMI_CON (SPM_BASE + 0x708) +#define SPM_DVFS_CMD0 (SPM_BASE + 0x710) +#define SPM_DVFS_CMD1 (SPM_BASE + 0x714) +#define SPM_DVFS_CMD2 (SPM_BASE + 0x718) +#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C) +#define SPM_DVFS_CMD4 (SPM_BASE + 0x720) +#define SPM_DVFS_CMD5 (SPM_BASE + 0x724) +#define SPM_DVFS_CMD6 (SPM_BASE + 0x728) +#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C) +#define SPM_DVFS_CMD8 (SPM_BASE + 0x730) +#define SPM_DVFS_CMD9 (SPM_BASE + 0x734) +#define SPM_DVFS_CMD10 (SPM_BASE + 0x738) +#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C) +#define SPM_DVFS_CMD12 (SPM_BASE + 0x740) +#define SPM_DVFS_CMD13 (SPM_BASE + 0x744) +#define SPM_DVFS_CMD14 (SPM_BASE + 0x748) +#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C) +#define SPM_DVFS_CMD16 (SPM_BASE + 0x750) +#define SPM_DVFS_CMD17 (SPM_BASE + 0x754) +#define SPM_DVFS_CMD18 (SPM_BASE + 0x758) +#define SPM_DVFS_CMD19 (SPM_BASE + 0x75C) +#define SPM_DVFS_CMD20 (SPM_BASE + 0x760) +#define SPM_DVFS_CMD21 (SPM_BASE + 0x764) +#define SPM_DVFS_CMD22 (SPM_BASE + 0x768) +#define SPM_DVFS_CMD23 (SPM_BASE + 0x76C) +#define SYS_TIMER_VALUE_L (SPM_BASE + 0x770) +#define SYS_TIMER_VALUE_H (SPM_BASE + 0x774) +#define SYS_TIMER_START_L (SPM_BASE + 0x778) +#define SYS_TIMER_START_H (SPM_BASE + 0x77C) +#define SYS_TIMER_LATCH_L_00 (SPM_BASE + 0x780) +#define SYS_TIMER_LATCH_H_00 (SPM_BASE + 0x784) +#define SYS_TIMER_LATCH_L_01 (SPM_BASE + 0x788) +#define SYS_TIMER_LATCH_H_01 (SPM_BASE + 0x78C) +#define SYS_TIMER_LATCH_L_02 (SPM_BASE + 0x790) +#define SYS_TIMER_LATCH_H_02 (SPM_BASE + 0x794) +#define SYS_TIMER_LATCH_L_03 (SPM_BASE + 0x798) +#define SYS_TIMER_LATCH_H_03 (SPM_BASE + 0x79C) +#define SYS_TIMER_LATCH_L_04 (SPM_BASE + 0x7A0) +#define SYS_TIMER_LATCH_H_04 (SPM_BASE + 0x7A4) +#define SYS_TIMER_LATCH_L_05 (SPM_BASE + 0x7A8) +#define SYS_TIMER_LATCH_H_05 (SPM_BASE + 0x7AC) +#define SYS_TIMER_LATCH_L_06 (SPM_BASE + 0x7B0) +#define SYS_TIMER_LATCH_H_06 (SPM_BASE + 0x7B4) +#define SYS_TIMER_LATCH_L_07 (SPM_BASE + 0x7B8) +#define SYS_TIMER_LATCH_H_07 (SPM_BASE + 0x7BC) +#define SYS_TIMER_LATCH_L_08 (SPM_BASE + 0x7C0) +#define SYS_TIMER_LATCH_H_08 (SPM_BASE + 0x7C4) +#define SYS_TIMER_LATCH_L_09 (SPM_BASE + 0x7C8) +#define SYS_TIMER_LATCH_H_09 (SPM_BASE + 0x7CC) +#define SYS_TIMER_LATCH_L_10 (SPM_BASE + 0x7D0) +#define SYS_TIMER_LATCH_H_10 (SPM_BASE + 0x7D4) +#define SYS_TIMER_LATCH_L_11 (SPM_BASE + 0x7D8) +#define SYS_TIMER_LATCH_H_11 (SPM_BASE + 0x7DC) +#define SYS_TIMER_LATCH_L_12 (SPM_BASE + 0x7E0) +#define SYS_TIMER_LATCH_H_12 (SPM_BASE + 0x7E4) +#define SYS_TIMER_LATCH_L_13 (SPM_BASE + 0x7E8) +#define SYS_TIMER_LATCH_H_13 (SPM_BASE + 0x7EC) +#define SYS_TIMER_LATCH_L_14 (SPM_BASE + 0x7F0) +#define SYS_TIMER_LATCH_H_14 (SPM_BASE + 0x7F4) +#define SYS_TIMER_LATCH_L_15 (SPM_BASE + 0x7F8) +#define SYS_TIMER_LATCH_H_15 (SPM_BASE + 0x7FC) +/*******Register_LAT_STA*************************************************/ +#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800) +#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804) +#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808) +#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C) +#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810) +#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814) +#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818) +#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C) +#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820) +#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824) +#define PCM_WDT_LATCH_10 (SPM_BASE + 0x828) +#define PCM_WDT_LATCH_11 (SPM_BASE + 0x82C) +#define PCM_WDT_LATCH_12 (SPM_BASE + 0x830) +#define PCM_WDT_LATCH_13 (SPM_BASE + 0x834) +#define PCM_WDT_LATCH_14 (SPM_BASE + 0x838) +#define PCM_WDT_LATCH_15 (SPM_BASE + 0x83C) +#define PCM_WDT_LATCH_16 (SPM_BASE + 0x840) +#define PCM_WDT_LATCH_17 (SPM_BASE + 0x844) +#define PCM_WDT_LATCH_18 (SPM_BASE + 0x848) +#define PCM_WDT_LATCH_SPARE_0 (SPM_BASE + 0x84C) +#define PCM_WDT_LATCH_SPARE_1 (SPM_BASE + 0x850) +#define PCM_WDT_LATCH_SPARE_2 (SPM_BASE + 0x854) +#define PCM_WDT_LATCH_CONN_0 (SPM_BASE + 0x870) +#define PCM_WDT_LATCH_CONN_1 (SPM_BASE + 0x874) +#define PCM_WDT_LATCH_CONN_2 (SPM_BASE + 0x878) +#define DRAMC_GATING_ERR_LATCH_CH0_0 (SPM_BASE + 0x8A0) +#define DRAMC_GATING_ERR_LATCH_CH0_1 (SPM_BASE + 0x8A4) +#define DRAMC_GATING_ERR_LATCH_CH0_2 (SPM_BASE + 0x8A8) +#define DRAMC_GATING_ERR_LATCH_CH0_3 (SPM_BASE + 0x8AC) +#define DRAMC_GATING_ERR_LATCH_CH0_4 (SPM_BASE + 0x8B0) +#define DRAMC_GATING_ERR_LATCH_CH0_5 (SPM_BASE + 0x8B4) +#define DRAMC_GATING_ERR_LATCH_CH0_6 (SPM_BASE + 0x8B8) +#define DRAMC_GATING_ERR_LATCH_SPARE_0 (SPM_BASE + 0x8F4) +/*******Register_SPM_ACK_CHK*************************************************/ +#define SPM_ACK_CHK_CON_0 (SPM_BASE + 0x900) +#define SPM_ACK_CHK_PC_0 (SPM_BASE + 0x904) +#define SPM_ACK_CHK_SEL_0 (SPM_BASE + 0x908) +#define SPM_ACK_CHK_TIMER_0 (SPM_BASE + 0x90C) +#define SPM_ACK_CHK_STA_0 (SPM_BASE + 0x910) +#define SPM_ACK_CHK_SWINT_0 (SPM_BASE + 0x914) +#define SPM_ACK_CHK_CON_1 (SPM_BASE + 0x920) +#define SPM_ACK_CHK_PC_1 (SPM_BASE + 0x924) +#define SPM_ACK_CHK_SEL_1 (SPM_BASE + 0x928) +#define SPM_ACK_CHK_TIMER_1 (SPM_BASE + 0x92C) +#define SPM_ACK_CHK_STA_1 (SPM_BASE + 0x930) +#define SPM_ACK_CHK_SWINT_1 (SPM_BASE + 0x934) +#define SPM_ACK_CHK_CON_2 (SPM_BASE + 0x940) +#define SPM_ACK_CHK_PC_2 (SPM_BASE + 0x944) +#define SPM_ACK_CHK_SEL_2 (SPM_BASE + 0x948) +#define SPM_ACK_CHK_TIMER_2 (SPM_BASE + 0x94C) +#define SPM_ACK_CHK_STA_2 (SPM_BASE + 0x950) +#define SPM_ACK_CHK_SWINT_2 (SPM_BASE + 0x954) +#define SPM_ACK_CHK_CON_3 (SPM_BASE + 0x960) +#define SPM_ACK_CHK_PC_3 (SPM_BASE + 0x964) +#define SPM_ACK_CHK_SEL_3 (SPM_BASE + 0x968) +#define SPM_ACK_CHK_TIMER_3 (SPM_BASE + 0x96C) +#define SPM_ACK_CHK_STA_3 (SPM_BASE + 0x970) +#define SPM_ACK_CHK_SWINT_3 (SPM_BASE + 0x974) +#define SPM_COUNTER_0 (SPM_BASE + 0x978) +#define SPM_COUNTER_1 (SPM_BASE + 0x97C) +#define SPM_COUNTER_2 (SPM_BASE + 0x980) +#define SYS_TIMER_CON (SPM_BASE + 0x98C) +#define SPM_TWAM_CON (SPM_BASE + 0x990) +#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x994) +#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x998) +#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x99C) +/*******The OTHERS*************************************************/ +#define RC_FSM_STA_0 (SPM_BASE + 0xE00) +#define RC_CMD_STA_0 (SPM_BASE + 0xE04) +#define RC_CMD_STA_1 (SPM_BASE + 0xE08) +#define RC_SPI_STA_0 (SPM_BASE + 0xE0C) +#define RC_PI_PO_STA_0 (SPM_BASE + 0xE10) +#define RC_M00_REQ_STA_0 (SPM_BASE + 0xE14) +#define RC_M01_REQ_STA_0 (SPM_BASE + 0xE1C) +#define RC_M02_REQ_STA_0 (SPM_BASE + 0xE20) +#define RC_M03_REQ_STA_0 (SPM_BASE + 0xE24) +#define RC_M04_REQ_STA_0 (SPM_BASE + 0xE28) +#define RC_M05_REQ_STA_0 (SPM_BASE + 0xE2C) +#define RC_M06_REQ_STA_0 (SPM_BASE + 0xE30) +#define RC_M07_REQ_STA_0 (SPM_BASE + 0xE34) +#define RC_M08_REQ_STA_0 (SPM_BASE + 0xE38) +#define RC_M09_REQ_STA_0 (SPM_BASE + 0xE3C) +#define RC_M10_REQ_STA_0 (SPM_BASE + 0xE40) +#define RC_M11_REQ_STA_0 (SPM_BASE + 0xE44) +#define RC_M12_REQ_STA_0 (SPM_BASE + 0xE48) +#define RC_DEBUG_STA_0 (SPM_BASE + 0xE4C) +#define RC_DEBUG_TRACE_0_LSB (SPM_BASE + 0xE50) +#define RC_DEBUG_TRACE_0_MSB (SPM_BASE + 0xE54) +#define RC_DEBUG_TRACE_1_LSB (SPM_BASE + 0xE5C) +#define RC_DEBUG_TRACE_1_MSB (SPM_BASE + 0xE60) +#define RC_DEBUG_TRACE_2_LSB (SPM_BASE + 0xE64) +#define RC_DEBUG_TRACE_2_MSB (SPM_BASE + 0xE6C) +#define RC_DEBUG_TRACE_3_LSB (SPM_BASE + 0xE70) +#define RC_DEBUG_TRACE_3_MSB (SPM_BASE + 0xE74) +#define RC_DEBUG_TRACE_4_LSB (SPM_BASE + 0xE78) +#define RC_DEBUG_TRACE_4_MSB (SPM_BASE + 0xE7C) +#define RC_DEBUG_TRACE_5_LSB (SPM_BASE + 0xE80) +#define RC_DEBUG_TRACE_5_MSB (SPM_BASE + 0xE84) +#define RC_DEBUG_TRACE_6_LSB (SPM_BASE + 0xE88) +#define RC_DEBUG_TRACE_6_MSB (SPM_BASE + 0xE8C) +#define RC_DEBUG_TRACE_7_LSB (SPM_BASE + 0xE90) +#define RC_DEBUG_TRACE_7_MSB (SPM_BASE + 0xE94) +#define RC_SYS_TIMER_LATCH_0_LSB (SPM_BASE + 0xE98) +#define RC_SYS_TIMER_LATCH_0_MSB (SPM_BASE + 0xE9C) +#define RC_SYS_TIMER_LATCH_1_LSB (SPM_BASE + 0xEA0) +#define RC_SYS_TIMER_LATCH_1_MSB (SPM_BASE + 0xEA4) +#define RC_SYS_TIMER_LATCH_2_LSB (SPM_BASE + 0xEA8) +#define RC_SYS_TIMER_LATCH_2_MSB (SPM_BASE + 0xEAC) +#define RC_SYS_TIMER_LATCH_3_LSB (SPM_BASE + 0xEB0) +#define RC_SYS_TIMER_LATCH_3_MSB (SPM_BASE + 0xEB4) +#define RC_SYS_TIMER_LATCH_4_LSB (SPM_BASE + 0xEB8) +#define RC_SYS_TIMER_LATCH_4_MSB (SPM_BASE + 0xEBC) +#define RC_SYS_TIMER_LATCH_5_LSB (SPM_BASE + 0xEC0) +#define RC_SYS_TIMER_LATCH_5_MSB (SPM_BASE + 0xEC4) +#define RC_SYS_TIMER_LATCH_6_LSB (SPM_BASE + 0xEC8) +#define RC_SYS_TIMER_LATCH_6_MSB (SPM_BASE + 0xECC) +#define RC_SYS_TIMER_LATCH_7_LSB (SPM_BASE + 0xED0) +#define RC_SYS_TIMER_LATCH_7_MSB (SPM_BASE + 0xED4) +#define PCM_WDT_LATCH_19 (SPM_BASE + 0xED8) +#define PCM_WDT_LATCH_20 (SPM_BASE + 0xEDC) +#define PCM_WDT_LATCH_21 (SPM_BASE + 0xEE0) +#define PCM_WDT_LATCH_22 (SPM_BASE + 0xEE4) +#define PCM_WDT_LATCH_23 (SPM_BASE + 0xEE8) +#define PCM_WDT_LATCH_24 (SPM_BASE + 0xEEC) +/*******Register_PMSR*************************************************/ +#define PMSR_LAST_DAT (SPM_BASE + 0xF00) +#define PMSR_LAST_CNT (SPM_BASE + 0xF04) +#define PMSR_LAST_ACK (SPM_BASE + 0xF08) +#define SPM_PMSR_SEL_CON0 (SPM_BASE + 0xF10) +#define SPM_PMSR_SEL_CON1 (SPM_BASE + 0xF14) +#define SPM_PMSR_SEL_CON2 (SPM_BASE + 0xF18) +#define SPM_PMSR_SEL_CON3 (SPM_BASE + 0xF1C) +#define SPM_PMSR_SEL_CON4 (SPM_BASE + 0xF20) +#define SPM_PMSR_SEL_CON5 (SPM_BASE + 0xF24) +#define SPM_PMSR_SEL_CON6 (SPM_BASE + 0xF28) +#define SPM_PMSR_SEL_CON7 (SPM_BASE + 0xF2C) +#define SPM_PMSR_SEL_CON8 (SPM_BASE + 0xF30) +#define SPM_PMSR_SEL_CON9 (SPM_BASE + 0xF34) +#define SPM_PMSR_SEL_CON10 (SPM_BASE + 0xF3C) +#define SPM_PMSR_SEL_CON11 (SPM_BASE + 0xF40) +#define SPM_PMSR_TIEMR_STA0 (SPM_BASE + 0xFB8) +#define SPM_PMSR_TIEMR_STA1 (SPM_BASE + 0xFBC) +#define SPM_PMSR_TIEMR_STA2 (SPM_BASE + 0xFC0) +#define SPM_PMSR_GENERAL_CON0 (SPM_BASE + 0xFC4) +#define SPM_PMSR_GENERAL_CON1 (SPM_BASE + 0xFC8) +#define SPM_PMSR_GENERAL_CON2 (SPM_BASE + 0xFCC) +#define SPM_PMSR_GENERAL_CON3 (SPM_BASE + 0xFD0) +#define SPM_PMSR_GENERAL_CON4 (SPM_BASE + 0xFD4) +#define SPM_PMSR_GENERAL_CON5 (SPM_BASE + 0xFD8) +#define SPM_PMSR_SW_RESET (SPM_BASE + 0xFDC) +#define SPM_PMSR_MON_CON0 (SPM_BASE + 0xFE0) +#define SPM_PMSR_MON_CON1 (SPM_BASE + 0xFE4) +#define SPM_PMSR_MON_CON2 (SPM_BASE + 0xFE8) +#define SPM_PMSR_LEN_CON0 (SPM_BASE + 0xFEC) +#define SPM_PMSR_LEN_CON1 (SPM_BASE + 0xFF0) +#define SPM_PMSR_LEN_CON2 (SPM_BASE + 0xFF4) +/*******Register End*************************************************/ + +/* POWERON_CONFIG_EN (0x10006000+0x000) */ +#define BCLK_CG_EN_LSB (1U << 0) /* 1b */ +#define PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_POWER_ON_VAL0 (0x10006000+0x004) */ +#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */ +/* SPM_POWER_ON_VAL1 (0x10006000+0x008) */ +#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */ +/* SPM_CLK_CON (0x10006000+0x00C) */ +#define REG_SRCCLKEN0_CTL_LSB (1U << 0) /* 2b */ +#define REG_SRCCLKEN1_CTL_LSB (1U << 2) /* 2b */ +#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */ +#define REG_SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */ +#define REG_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */ +#define REG_MD1_C32RM_EN_LSB (1U << 9) /* 1b */ +#define REG_MD2_C32RM_EN_LSB (1U << 10) /* 1b */ +#define REG_CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */ +#define REG_CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */ +#define REG_SRCCLKEN0_EN_LSB (1U << 13) /* 1b */ +#define REG_SRCCLKEN1_EN_LSB (1U << 14) /* 1b */ +#define SCP_DCM_EN_LSB (1U << 15) /* 1b */ +#define REG_SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 8b */ +#define REG_SYSCLK1_SRC_MASK_B_LSB (1U << 24) /* 8b */ +/* SPM_CLK_SETTLE (0x10006000+0x010) */ +#define SYSCLK_SETTLE_LSB (1U << 0) /* 28b */ +/* SPM_AP_STANDBY_CON (0x10006000+0x014) */ +#define REG_WFI_OP_LSB (1U << 0) /* 1b */ +#define REG_WFI_TYPE_LSB (1U << 1) /* 1b */ +#define REG_MP0_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */ +#define REG_MP1_CPUTOP_IDLE_MASK_LSB (1U << 3) /* 1b */ +#define REG_MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */ +#define REG_MD_APSRC_1_SEL_LSB (1U << 25) /* 1b */ +#define REG_MD_APSRC_0_SEL_LSB (1U << 26) /* 1b */ +#define REG_CONN_APSRC_SEL_LSB (1U << 29) /* 1b */ +/* PCM_CON0 (0x10006000+0x018) */ +#define PCM_CK_EN_LSB (1U << 2) /* 1b */ +#define RG_EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */ +#define PCM_CK_FROM_CKSYS_LSB (1U << 4) /* 1b */ +#define PCM_SW_RESET_LSB (1U << 15) /* 1b */ +#define PCM_CON0_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* PCM_CON1 (0x10006000+0x01C) */ +#define RG_IM_SLAVE_LSB (1U << 0) /* 1b */ +#define RG_IM_SLEEP_LSB (1U << 1) /* 1b */ +#define REG_SPM_SRAM_CTRL_MUX_LSB (1U << 2) /* 1b */ +#define RG_AHBMIF_APBEN_LSB (1U << 3) /* 1b */ +#define RG_IM_PDN_LSB (1U << 4) /* 1b */ +#define RG_PCM_TIMER_EN_LSB (1U << 5) /* 1b */ +#define SPM_EVENT_COUNTER_CLR_LSB (1U << 6) /* 1b */ +#define RG_DIS_MIF_PROT_LSB (1U << 7) /* 1b */ +#define RG_PCM_WDT_EN_LSB (1U << 8) /* 1b */ +#define RG_PCM_WDT_WAKE_LSB (1U << 9) /* 1b */ +#define REG_SPM_SRAM_SLEEP_B_LSB (1U << 10) /* 1b */ +#define REG_SPM_SRAM_ISOINT_B_LSB (1U << 11) /* 1b */ +#define REG_EVENT_LOCK_EN_LSB (1U << 12) /* 1b */ +#define REG_SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */ +#define REG_MD32_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */ +#define RG_PCM_IRQ_MSK_LSB (1U << 15) /* 1b */ +#define PCM_CON1_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_POWER_ON_VAL2 (0x10006000+0x020) */ +#define POWER_ON_VAL2_LSB (1U << 0) /* 32b */ +/* SPM_POWER_ON_VAL3 (0x10006000+0x024) */ +#define POWER_ON_VAL3_LSB (1U << 0) /* 32b */ +/* PCM_REG_DATA_INI (0x10006000+0x028) */ +#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */ +/* PCM_PWR_IO_EN (0x10006000+0x02C) */ +#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */ +#define RG_RF_SYNC_EN_LSB (1U << 16) /* 8b */ +/* PCM_TIMER_VAL (0x10006000+0x030) */ +#define REG_PCM_TIMER_VAL_LSB (1U << 0) /* 32b */ +/* PCM_WDT_VAL (0x10006000+0x034) */ +#define RG_PCM_WDT_VAL_LSB (1U << 0) /* 32b */ +/* SPM_SW_RST_CON (0x10006000+0x040) */ +#define SPM_SW_RST_CON_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_SW_RST_CON_SET (0x10006000+0x044) */ +#define SPM_SW_RST_CON_SET_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_SET_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* SPM_SW_RST_CON_CLR (0x10006000+0x048) */ +#define SPM_SW_RST_CON_CLR_LSB (1U << 0) /* 16b */ +#define SPM_SW_RST_CON_CLR_PROJECT_CODE_LSB (1U << 16) /* 16b */ +/* VS1_PSR_MASK_B (0x10006000+0x04C) */ +#define VS1_OPP0_PSR_MASK_B_LSB (1U << 0) /* 8b */ +#define VS1_OPP1_PSR_MASK_B_LSB (1U << 8) /* 8b */ +/* VS2_PSR_MASK_B (0x10006000+0x050) */ +#define VS2_OPP0_PSR_MASK_B_LSB (1U << 0) /* 8b */ +#define VS2_OPP1_PSR_MASK_B_LSB (1U << 8) /* 8b */ +#define VS2_OPP2_PSR_MASK_B_LSB (1U << 16) /* 8b */ +/* MD32_CLK_CON (0x10006000+0x084) */ +#define REG_MD32_26M_CK_SEL_LSB (1U << 0) /* 1b */ +#define REG_MD32_DCM_EN_LSB (1U << 1) /* 1b */ +/* SPM_SRAM_RSV_CON (0x10006000+0x088) */ +#define SPM_SRAM_SLEEP_B_ECO_EN_LSB (1U << 0) /* 1b */ +/* SPM_SWINT (0x10006000+0x08C) */ +#define SPM_SWINT_LSB (1U << 0) /* 32b */ +/* SPM_SWINT_SET (0x10006000+0x090) */ +#define SPM_SWINT_SET_LSB (1U << 0) /* 32b */ +/* SPM_SWINT_CLR (0x10006000+0x094) */ +#define SPM_SWINT_CLR_LSB (1U << 0) /* 32b */ +/* SPM_SCP_MAILBOX (0x10006000+0x098) */ +#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */ +/* SCP_SPM_MAILBOX (0x10006000+0x09C) */ +#define SCP_SPM_MAILBOX_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CON (0x10006000+0x0A0) */ +#define REG_TWAM_ENABLE_LSB (1U << 0) /* 1b */ +#define REG_TWAM_SPEED_MODE_EN_LSB (1U << 1) /* 1b */ +#define REG_TWAM_SW_RST_LSB (1U << 2) /* 1b */ +#define REG_TWAM_IRQ_MASK_LSB (1U << 3) /* 1b */ +#define REG_TWAM_MON_TYPE_0_LSB (1U << 4) /* 2b */ +#define REG_TWAM_MON_TYPE_1_LSB (1U << 6) /* 2b */ +#define REG_TWAM_MON_TYPE_2_LSB (1U << 8) /* 2b */ +#define REG_TWAM_MON_TYPE_3_LSB (1U << 10) /* 2b */ +/* SPM_TWAM_WINDOW_LEN (0x10006000+0x0A4) */ +#define REG_TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_IDLE_SEL (0x10006000+0x0A8) */ +#define REG_TWAM_SIG_SEL_0_LSB (1U << 0) /* 7b */ +#define REG_TWAM_SIG_SEL_1_LSB (1U << 8) /* 7b */ +#define REG_TWAM_SIG_SEL_2_LSB (1U << 16) /* 7b */ +#define REG_TWAM_SIG_SEL_3_LSB (1U << 24) /* 7b */ +/* SPM_SCP_IRQ (0x10006000+0x0AC) */ +#define SC_SPM2SCP_WAKEUP_LSB (1U << 0) /* 1b */ +#define SC_SCP2SPM_WAKEUP_LSB (1U << 4) /* 1b */ +/* SPM_CPU_WAKEUP_EVENT (0x10006000+0x0B0) */ +#define REG_CPU_WAKEUP_LSB (1U << 0) /* 1b */ +/* SPM_IRQ_MASK (0x10006000+0x0B4) */ +#define REG_SPM_IRQ_MASK_LSB (1U << 0) /* 32b */ +/* DDR_EN_DBC (0x10006000+0x0B4) */ +#define REG_ALL_DDR_EN_DBC_EN_LSB (1U << 16) /* 1b */ +/* SPM_SRC_REQ (0x10006000+0x0B8) */ +#define REG_SPM_APSRC_REQ_LSB (1U << 0) /* 1b */ +#define REG_SPM_F26M_REQ_LSB (1U << 1) /* 1b */ +#define REG_SPM_INFRA_REQ_LSB (1U << 3) /* 1b */ +#define REG_SPM_VRF18_REQ_LSB (1U << 4) /* 1b */ +#define REG_SPM_DDR_EN_REQ_LSB (1U << 7) /* 1b */ +#define REG_SPM_DVFS_REQ_LSB (1U << 8) /* 1b */ +#define REG_SPM_SW_MAILBOX_REQ_LSB (1U << 9) /* 1b */ +#define REG_SPM_SSPM_MAILBOX_REQ_LSB (1U << 10) /* 1b */ +#define REG_SPM_ADSP_MAILBOX_REQ_LSB (1U << 11) /* 1b */ +#define REG_SPM_SCP_MAILBOX_REQ_LSB (1U << 12) /* 1b */ +/* SPM_SRC_MASK (0x10006000+0x0BC) */ +#define REG_MD_SRCCLKENA_0_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_MD_SRCCLKENA2INFRA_REQ_0_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_MD_APSRC2INFRA_REQ_0_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_MD_APSRC_REQ_0_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_MD_VRF18_REQ_0_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_MD_DDR_EN_0_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_MD_SRCCLKENA_1_MASK_B_LSB (1U << 6) /* 1b */ +#define REG_MD_SRCCLKENA2INFRA_REQ_1_MASK_B_LSB (1U << 7) /* 1b */ +#define REG_MD_APSRC2INFRA_REQ_1_MASK_B_LSB (1U << 8) /* 1b */ +#define REG_MD_APSRC_REQ_1_MASK_B_LSB (1U << 9) /* 1b */ +#define REG_MD_VRF18_REQ_1_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_MD_DDR_EN_1_MASK_B_LSB (1U << 11) /* 1b */ +#define REG_CONN_SRCCLKENA_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_CONN_SRCCLKENB_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_CONN_INFRA_REQ_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_CONN_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_CONN_VRF18_REQ_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_CONN_DDR_EN_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_CONN_VFE28_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_SRCCLKENI0_SRCCLKENA_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_SRCCLKENI0_INFRA_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_SRCCLKENI1_SRCCLKENA_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_SRCCLKENI1_INFRA_REQ_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_SRCCLKENI2_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_SRCCLKENI2_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_INFRASYS_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_INFRASYS_DDR_EN_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_MD32_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_MD32_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_MD32_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_MD32_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_MD32_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */ +/* SPM_SRC2_MASK (0x10006000+0x0C0) */ +#define REG_SCP_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_SCP_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_SCP_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_SCP_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_SCP_DDR_EN_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_AUDIO_DSP_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_AUDIO_DSP_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */ +#define REG_AUDIO_DSP_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */ +#define REG_AUDIO_DSP_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */ +#define REG_AUDIO_DSP_DDR_EN_MASK_B_LSB (1U << 9) /* 1b */ +#define REG_UFS_SRCCLKENA_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_UFS_INFRA_REQ_MASK_B_LSB (1U << 11) /* 1b */ +#define REG_UFS_APSRC_REQ_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_UFS_VRF18_REQ_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_UFS_DDR_EN_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_DISP0_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_DISP0_DDR_EN_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_DISP1_APSRC_REQ_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_DISP1_DDR_EN_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_GCE_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_GCE_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_GCE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_GCE_DDR_EN_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_APU_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_APU_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_APU_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_APU_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_APU_DDR_EN_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_CG_CHECK_SRCCLKENA_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_CG_CHECK_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_CG_CHECK_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_CG_CHECK_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */ +/* SPM_SRC3_MASK (0x10006000+0x0C4) */ +#define REG_DVFSRC_EVENT_TRIGGER_MASK_B_LSB (1U << 0) /* 1b */ +#define REG_SW2SPM_INT0_MASK_B_LSB (1U << 1) /* 1b */ +#define REG_SW2SPM_INT1_MASK_B_LSB (1U << 2) /* 1b */ +#define REG_SW2SPM_INT2_MASK_B_LSB (1U << 3) /* 1b */ +#define REG_SW2SPM_INT3_MASK_B_LSB (1U << 4) /* 1b */ +#define REG_SC_ADSP2SPM_WAKEUP_MASK_B_LSB (1U << 5) /* 1b */ +#define REG_SC_SSPM2SPM_WAKEUP_MASK_B_LSB (1U << 6) /* 4b */ +#define REG_SC_SCP2SPM_WAKEUP_MASK_B_LSB (1U << 10) /* 1b */ +#define REG_CSYSPWRREQ_MASK_LSB (1U << 11) /* 1b */ +#define REG_SPM_SRCCLKENA_RESERVED_MASK_B_LSB (1U << 12) /* 1b */ +#define REG_SPM_INFRA_REQ_RESERVED_MASK_B_LSB (1U << 13) /* 1b */ +#define REG_SPM_APSRC_REQ_RESERVED_MASK_B_LSB (1U << 14) /* 1b */ +#define REG_SPM_VRF18_REQ_RESERVED_MASK_B_LSB (1U << 15) /* 1b */ +#define REG_SPM_DDR_EN_RESERVED_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_MCUPM_SRCCLKENA_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_MCUPM_INFRA_REQ_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_MCUPM_APSRC_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_MCUPM_VRF18_REQ_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_MCUPM_DDR_EN_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_MSDC0_SRCCLKENA_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_MSDC0_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_MSDC0_APSRC_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_MSDC0_VRF18_REQ_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_MSDC0_DDR_EN_MASK_B_LSB (1U << 26) /* 1b */ +#define REG_MSDC1_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */ +#define REG_MSDC1_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */ +#define REG_MSDC1_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */ +#define REG_MSDC1_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */ +#define REG_MSDC1_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */ +/* SPM_SRC4_MASK (0x10006000+0x0C8) */ +#define CCIF_EVENT_MASK_B_LSB (1U << 0) /* 16b */ +#define REG_BAK_PSRI_SRCCLKENA_MASK_B_LSB (1U << 16) /* 1b */ +#define REG_BAK_PSRI_INFRA_REQ_MASK_B_LSB (1U << 17) /* 1b */ +#define REG_BAK_PSRI_APSRC_REQ_MASK_B_LSB (1U << 18) /* 1b */ +#define REG_BAK_PSRI_VRF18_REQ_MASK_B_LSB (1U << 19) /* 1b */ +#define REG_BAK_PSRI_DDR_EN_MASK_B_LSB (1U << 20) /* 1b */ +#define REG_DRAMC0_MD32_INFRA_REQ_MASK_B_LSB (1U << 21) /* 1b */ +#define REG_DRAMC0_MD32_VRF18_REQ_MASK_B_LSB (1U << 22) /* 1b */ +#define REG_DRAMC1_MD32_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */ +#define REG_DRAMC1_MD32_VRF18_REQ_MASK_B_LSB (1U << 24) /* 1b */ +#define REG_CONN_SRCCLKENB2PWRAP_MASK_B_LSB (1U << 25) /* 1b */ +#define REG_DRAMC0_MD32_WAKEUP_MASK_LSB (1U << 26) /* 1b */ +#define REG_DRAMC1_MD32_WAKEUP_MASK_LSB (1U << 27) /* 1b */ +/* SPM_SRC5_MASK (0x10006000+0x0CC) */ +#define REG_MCUSYS_MERGE_APSRC_REQ_MASK_B_LSB (1U << 0) /* 9b */ +#define REG_MCUSYS_MERGE_DDR_EN_MASK_B_LSB (1U << 9) /* 9b */ +/* SPM_WAKEUP_EVENT_MASK (0x10006000+0x0D0) */ +#define REG_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000+0x0D4) */ +#define REG_EXT_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_EVENT_CLEAR (0x10006000+0x0D8) */ +#define SPM_TWAM_EVENT_CLEAR_LSB (1U << 0) /* 1b */ +/* SCP_CLK_CON (0x10006000+0x0DC) */ +#define REG_SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */ +#define REG_SCP_DCM_EN_LSB (1U << 1) /* 1b */ +#define SCP_SECURE_V_REQ_MASK_LSB (1U << 2) /* 1b */ +#define SCP_SLP_REQ_LSB (1U << 3) /* 1b */ +#define SCP_SLP_ACK_LSB (1U << 4) /* 1b */ +/* SPM_RESOURCE_ACK_CON0 (0x10006000+0x0F0) */ +#define REG_MD_SRCCLKENA_ACK_0_MASK_LSB (1U << 0) /* 1b */ +#define REG_MD_INFRA_ACK_0_MASK_LSB (1U << 1) /* 1b */ +#define REG_MD_APSRC_ACK_0_MASK_LSB (1U << 2) /* 1b */ +#define REG_MD_VRF18_ACK_0_MASK_LSB (1U << 3) /* 1b */ +#define REG_MD_DDR_EN_ACK_0_MASK_LSB (1U << 4) /* 1b */ +#define REG_MD_SRCCLKENA_ACK_1_MASK_LSB (1U << 5) /* 1b */ +#define REG_MD_INFRA_ACK_1_MASK_LSB (1U << 6) /* 1b */ +#define REG_MD_APSRC_ACK_1_MASK_LSB (1U << 7) /* 1b */ +#define REG_MD_VRF18_ACK_1_MASK_LSB (1U << 8) /* 1b */ +#define REG_MD_DDR_EN_ACK_1_MASK_LSB (1U << 9) /* 1b */ +#define REG_CONN_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_CONN_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_CONN_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */ +#define REG_CONN_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */ +#define REG_CONN_DDR_EN_ACK_MASK_LSB (1U << 14) /* 1b */ +#define REG_MD32_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */ +#define REG_MD32_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */ +#define REG_MD32_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */ +#define REG_MD32_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */ +#define REG_MD32_DDR_EN_ACK_MASK_LSB (1U << 19) /* 1b */ +#define REG_SCP_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */ +#define REG_SCP_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */ +#define REG_SCP_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */ +#define REG_SCP_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */ +#define REG_SCP_DDR_EN_ACK_MASK_LSB (1U << 24) /* 1b */ +#define REG_AUDIO_DSP_SRCCLKENA_ACK_MASK_LSB (1U << 25) /* 1b */ +#define REG_AUDIO_DSP_INFRA_ACK_MASK_LSB (1U << 26) /* 1b */ +#define REG_AUDIO_DSP_APSRC_ACK_MASK_LSB (1U << 27) /* 1b */ +#define REG_AUDIO_DSP_VRF18_ACK_MASK_LSB (1U << 28) /* 1b */ +#define REG_AUDIO_DSP_DDR_EN_ACK_MASK_LSB (1U << 29) /* 1b */ +#define REG_DISP0_DDR_EN_ACK_MASK_LSB (1U << 30) /* 1b */ +#define REG_DISP1_APSRC_ACK_MASK_LSB (1U << 31) /* 1b */ +/* SPM_RESOURCE_ACK_CON1 (0x10006000+0x0F4) */ +#define REG_UFS_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */ +#define REG_UFS_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */ +#define REG_UFS_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */ +#define REG_UFS_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */ +#define REG_UFS_DDR_EN_ACK_MASK_LSB (1U << 4) /* 1b */ +#define REG_APU_SRCCLKENA_ACK_MASK_LSB (1U << 5) /* 1b */ +#define REG_APU_INFRA_ACK_MASK_LSB (1U << 6) /* 1b */ +#define REG_APU_APSRC_ACK_MASK_LSB (1U << 7) /* 1b */ +#define REG_APU_VRF18_ACK_MASK_LSB (1U << 8) /* 1b */ +#define REG_APU_DDR_EN_ACK_MASK_LSB (1U << 9) /* 1b */ +#define REG_MCUPM_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_MCUPM_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_MCUPM_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */ +#define REG_MCUPM_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */ +#define REG_MCUPM_DDR_EN_ACK_MASK_LSB (1U << 14) /* 1b */ +#define REG_MSDC0_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */ +#define REG_MSDC0_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */ +#define REG_MSDC0_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */ +#define REG_MSDC0_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */ +#define REG_MSDC0_DDR_EN_ACK_MASK_LSB (1U << 19) /* 1b */ +#define REG_MSDC1_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */ +#define REG_MSDC1_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */ +#define REG_MSDC1_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */ +#define REG_MSDC1_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */ +#define REG_MSDC1_DDR_EN_ACK_MASK_LSB (1U << 24) /* 1b */ +#define REG_DISP0_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */ +#define REG_DISP1_DDR_EN_ACK_MASK_LSB (1U << 26) /* 1b */ +#define REG_GCE_INFRA_ACK_MASK_LSB (1U << 27) /* 1b */ +#define REG_GCE_APSRC_ACK_MASK_LSB (1U << 28) /* 1b */ +#define REG_GCE_VRF18_ACK_MASK_LSB (1U << 29) /* 1b */ +#define REG_GCE_DDR_EN_ACK_MASK_LSB (1U << 30) /* 1b */ +/* SPM_RESOURCE_ACK_CON2 (0x10006000+0x0F8) */ +#define SPM_F26M_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */ +#define SPM_INFRA_ACK_WAIT_CYCLE_LSB (1U << 8) /* 8b */ +#define SPM_APSRC_ACK_WAIT_CYCLE_LSB (1U << 16) /* 8b */ +#define SPM_VRF18_ACK_WAIT_CYCLE_LSB (1U << 24) /* 8b */ +/* SPM_RESOURCE_ACK_CON3 (0x10006000+0x0FC) */ +#define SPM_DDR_EN_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */ +#define REG_BAK_PSRI_SRCCLKENA_ACK_MASK_LSB (1U << 8) /* 1b */ +#define REG_BAK_PSRI_INFRA_ACK_MASK_LSB (1U << 9) /* 1b */ +#define REG_BAK_PSRI_APSRC_ACK_MASK_LSB (1U << 10) /* 1b */ +#define REG_BAK_PSRI_VRF18_ACK_MASK_LSB (1U << 11) /* 1b */ +#define REG_BAK_PSRI_DDR_EN_ACK_MASK_LSB (1U << 12) /* 1b */ +/* PCM_REG0_DATA (0x10006000+0x100) */ +#define PCM_REG0_RF_LSB (1U << 0) /* 32b */ +/* PCM_REG2_DATA (0x10006000+0x104) */ +#define PCM_REG2_RF_LSB (1U << 0) /* 32b */ +/* PCM_REG6_DATA (0x10006000+0x108) */ +#define PCM_REG6_RF_LSB (1U << 0) /* 32b */ +/* PCM_REG7_DATA (0x10006000+0x10C) */ +#define PCM_REG7_RF_LSB (1U << 0) /* 32b */ +/* PCM_REG13_DATA (0x10006000+0x110) */ +#define PCM_REG13_RF_LSB (1U << 0) /* 32b */ +/* SRC_REQ_STA_0 (0x10006000+0x114) */ +#define MD_SRCCLKENA_0_LSB (1U << 0) /* 1b */ +#define MD_SRCCLKENA2INFRA_REQ_0_LSB (1U << 1) /* 1b */ +#define MD_APSRC2INFRA_REQ_0_LSB (1U << 2) /* 1b */ +#define MD_APSRC_REQ_0_LSB (1U << 3) /* 1b */ +#define MD_VRF18_REQ_0_LSB (1U << 4) /* 1b */ +#define MD_DDR_EN_0_LSB (1U << 5) /* 1b */ +#define MD_SRCCLKENA_1_LSB (1U << 6) /* 1b */ +#define MD_SRCCLKENA2INFRA_REQ_1_LSB (1U << 7) /* 1b */ +#define MD_APSRC2INFRA_REQ_1_LSB (1U << 8) /* 1b */ +#define MD_APSRC_REQ_1_LSB (1U << 9) /* 1b */ +#define MD_VRF18_REQ_1_LSB (1U << 10) /* 1b */ +#define MD_DDR_EN_1_LSB (1U << 11) /* 1b */ +#define CONN_SRCCLKENA_LSB (1U << 12) /* 1b */ +#define CONN_SRCCLKENB_LSB (1U << 13) /* 1b */ +#define CONN_INFRA_REQ_LSB (1U << 14) /* 1b */ +#define CONN_APSRC_REQ_LSB (1U << 15) /* 1b */ +#define CONN_VRF18_REQ_LSB (1U << 16) /* 1b */ +#define CONN_DDR_EN_LSB (1U << 17) /* 1b */ +#define SRCCLKENI_LSB (1U << 18) /* 3b */ +#define MD32_SRCCLKENA_LSB (1U << 21) /* 1b */ +#define MD32_INFRA_REQ_LSB (1U << 22) /* 1b */ +#define MD32_APSRC_REQ_LSB (1U << 23) /* 1b */ +#define MD32_VRF18_REQ_LSB (1U << 24) /* 1b */ +#define MD32_DDR_EN_LSB (1U << 25) /* 1b */ +#define DISP0_APSRC_REQ_LSB (1U << 26) /* 1b */ +#define DISP0_DDR_EN_LSB (1U << 27) /* 1b */ +#define DISP1_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define DISP1_DDR_EN_LSB (1U << 29) /* 1b */ +#define DVFSRC_EVENT_TRIGGER_LSB (1U << 30) /* 1b */ +/* SRC_REQ_STA_1 (0x10006000+0x118) */ +#define SCP_SRCCLKENA_LSB (1U << 0) /* 1b */ +#define SCP_INFRA_REQ_LSB (1U << 1) /* 1b */ +#define SCP_APSRC_REQ_LSB (1U << 2) /* 1b */ +#define SCP_VRF18_REQ_LSB (1U << 3) /* 1b */ +#define SCP_DDR_EN_LSB (1U << 4) /* 1b */ +#define AUDIO_DSP_SRCCLKENA_LSB (1U << 5) /* 1b */ +#define AUDIO_DSP_INFRA_REQ_LSB (1U << 6) /* 1b */ +#define AUDIO_DSP_APSRC_REQ_LSB (1U << 7) /* 1b */ +#define AUDIO_DSP_VRF18_REQ_LSB (1U << 8) /* 1b */ +#define AUDIO_DSP_DDR_EN_LSB (1U << 9) /* 1b */ +#define UFS_SRCCLKENA_LSB (1U << 10) /* 1b */ +#define UFS_INFRA_REQ_LSB (1U << 11) /* 1b */ +#define UFS_APSRC_REQ_LSB (1U << 12) /* 1b */ +#define UFS_VRF18_REQ_LSB (1U << 13) /* 1b */ +#define UFS_DDR_EN_LSB (1U << 14) /* 1b */ +#define GCE_INFRA_REQ_LSB (1U << 15) /* 1b */ +#define GCE_APSRC_REQ_LSB (1U << 16) /* 1b */ +#define GCE_VRF18_REQ_LSB (1U << 17) /* 1b */ +#define GCE_DDR_EN_LSB (1U << 18) /* 1b */ +#define INFRASYS_APSRC_REQ_LSB (1U << 19) /* 1b */ +#define INFRASYS_DDR_EN_LSB (1U << 20) /* 1b */ +#define MSDC0_SRCCLKENA_LSB (1U << 21) /* 1b */ +#define MSDC0_INFRA_REQ_LSB (1U << 22) /* 1b */ +#define MSDC0_APSRC_REQ_LSB (1U << 23) /* 1b */ +#define MSDC0_VRF18_REQ_LSB (1U << 24) /* 1b */ +#define MSDC0_DDR_EN_LSB (1U << 25) /* 1b */ +#define MSDC1_SRCCLKENA_LSB (1U << 26) /* 1b */ +#define MSDC1_INFRA_REQ_LSB (1U << 27) /* 1b */ +#define MSDC1_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define MSDC1_VRF18_REQ_LSB (1U << 29) /* 1b */ +#define MSDC1_DDR_EN_LSB (1U << 30) /* 1b */ +/* SRC_REQ_STA_2 (0x10006000+0x11C) */ +#define MCUSYS_MERGE_DDR_EN_LSB (1U << 0) /* 9b */ +#define EMI_SELF_REFRESH_CH_LSB (1U << 9) /* 2b */ +#define SW2SPM_INT_LSB (1U << 11) /* 4b */ +#define SC_ADSP2SPM_WAKEUP_LSB (1U << 15) /* 1b */ +#define SC_SSPM2SPM_WAKEUP_LSB (1U << 16) /* 4b */ +#define SRC_REQ_STA_2_SC_SCP2SPM_WAKEUP_LSB (1U << 20) /* 1b */ +#define SPM_SRCCLKENA_RESERVED_LSB (1U << 21) /* 1b */ +#define SPM_INFRA_REQ_RESERVED_LSB (1U << 22) /* 1b */ +#define SPM_APSRC_REQ_RESERVED_LSB (1U << 23) /* 1b */ +#define SPM_VRF18_REQ_RESERVED_LSB (1U << 24) /* 1b */ +#define SPM_DDR_EN_RESERVED_LSB (1U << 25) /* 1b */ +#define MCUPM_SRCCLKENA_LSB (1U << 26) /* 1b */ +#define MCUPM_INFRA_REQ_LSB (1U << 27) /* 1b */ +#define MCUPM_APSRC_REQ_LSB (1U << 28) /* 1b */ +#define MCUPM_VRF18_REQ_LSB (1U << 29) /* 1b */ +#define MCUPM_DDR_EN_LSB (1U << 30) /* 1b */ +/* PCM_TIMER_OUT (0x10006000+0x120) */ +#define PCM_TIMER_LSB (1U << 0) /* 32b */ +/* PCM_WDT_OUT (0x10006000+0x124) */ +#define PCM_WDT_TIMER_VAL_OUT_LSB (1U << 0) /* 32b */ +/* SPM_IRQ_STA (0x10006000+0x128) */ +#define TWAM_IRQ_LSB (1U << 2) /* 1b */ +#define PCM_IRQ_LSB (1U << 3) /* 1b */ +/* SRC_REQ_STA_4 (0x10006000+0x12C) */ +#define APU_SRCCLKENA_LSB (1U << 0) /* 1b */ +#define APU_INFRA_REQ_LSB (1U << 1) /* 1b */ +#define APU_APSRC_REQ_LSB (1U << 2) /* 1b */ +#define APU_VRF18_REQ_LSB (1U << 3) /* 1b */ +#define APU_DDR_EN_LSB (1U << 4) /* 1b */ +#define BAK_PSRI_SRCCLKENA_LSB (1U << 5) /* 1b */ +#define BAK_PSRI_INFRA_REQ_LSB (1U << 6) /* 1b */ +#define BAK_PSRI_APSRC_REQ_LSB (1U << 7) /* 1b */ +#define BAK_PSRI_VRF18_REQ_LSB (1U << 8) /* 1b */ +#define BAK_PSRI_DDR_EN_LSB (1U << 9) /* 1b */ +/* MD32PCM_WAKEUP_STA (0x10006000+0x130) */ +#define MD32PCM_WAKEUP_STA_LSB (1U << 0) /* 32b */ +/* MD32PCM_EVENT_STA (0x10006000+0x134) */ +#define MD32PCM_EVENT_STA_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_STA (0x10006000+0x138) */ +#define F32K_WAKEUP_EVENT_L_LSB (1U << 0) /* 16b */ +#define ASYN_WAKEUP_EVENT_L_LSB (1U << 16) /* 16b */ +/* SPM_WAKEUP_EXT_STA (0x10006000+0x13C) */ +#define EXT_WAKEUP_EVENT_LSB (1U << 0) /* 32b */ +/* SPM_WAKEUP_MISC (0x10006000+0x140) */ +#define GIC_WAKEUP_LSB (1U << 0) /* 10b */ +#define DVFSRC_IRQ_LSB (1U << 16) /* 1b */ +#define SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB (1U << 17) /* 1b */ +#define PCM_TIMER_EVENT_LSB (1U << 18) /* 1b */ +#define PMIC_EINT_OUT_B_LSB (1U << 19) /* 2b */ +#define TWAM_IRQ_B_LSB (1U << 21) /* 1b */ +#define PMSR_IRQ_B_SET0_LSB (1U << 22) /* 1b */ +#define PMSR_IRQ_B_SET1_LSB (1U << 23) /* 1b */ +#define PMSR_IRQ_B_SET2_LSB (1U << 24) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_0_LSB (1U << 25) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_1_LSB (1U << 26) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_2_LSB (1U << 27) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_3_LSB (1U << 28) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_ALL_LSB (1U << 29) /* 1b */ +#define PMIC_IRQ_ACK_LSB (1U << 30) /* 1b */ +#define PMIC_SCP_IRQ_LSB (1U << 31) /* 1b */ +/* MM_DVFS_HALT (0x10006000+0x144) */ +#define MM_DVFS_HALT_LSB (1U << 0) /* 5b */ +/* BUS_PROTECT_RDY (0x10006000+0x150) */ +#define PROTECT_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT1_RDY (0x10006000+0x154) */ +#define PROTECT1_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT2_RDY (0x10006000+0x158) */ +#define PROTECT2_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT3_RDY (0x10006000+0x15C) */ +#define PROTECT3_READY_LSB (1U << 0) /* 32b */ +/* SUBSYS_IDLE_STA (0x10006000+0x160) */ +#define SUBSYS_IDLE_SIGNALS_LSB (1U << 0) /* 32b */ +/* PCM_STA (0x10006000+0x164) */ +#define PCM_CK_SEL_O_LSB (1U << 0) /* 4b */ +#define EXT_SRC_STA_LSB (1U << 4) /* 3b */ +/* SRC_REQ_STA_3 (0x10006000+0x168) */ +#define CCIF_EVENT_RAW_STATUS_LSB (1U << 0) /* 16b */ +#define F26M_STATE_LSB (1U << 16) /* 1b */ +#define INFRA_STATE_LSB (1U << 17) /* 1b */ +#define APSRC_STATE_LSB (1U << 18) /* 1b */ +#define VRF18_STATE_LSB (1U << 19) /* 1b */ +#define DDR_EN_STATE_LSB (1U << 20) /* 1b */ +#define DVFS_STATE_LSB (1U << 21) /* 1b */ +#define SW_MAILBOX_STATE_LSB (1U << 22) /* 1b */ +#define SSPM_MAILBOX_STATE_LSB (1U << 23) /* 1b */ +#define ADSP_MAILBOX_STATE_LSB (1U << 24) /* 1b */ +#define SCP_MAILBOX_STATE_LSB (1U << 25) /* 1b */ +/* PWR_STATUS (0x10006000+0x16C) */ +#define PWR_STATUS_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_2ND (0x10006000+0x170) */ +#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */ +/* CPU_PWR_STATUS (0x10006000+0x174) */ +#define MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 1) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 3) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 4) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 5) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 6) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 7) /* 1b */ +#define MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 8) /* 1b */ +#define MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 9) /* 1b */ +/* OTHER_PWR_STATUS (0x10006000+0x178) */ +#define OTHER_PWR_STATUS_LSB (1U << 0) /* 32b */ +/* SPM_VTCXO_EVENT_COUNT_STA (0x10006000+0x17C) */ +#define SPM_VTCXO_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_VTCXO_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* SPM_INFRA_EVENT_COUNT_STA (0x10006000+0x180) */ +#define SPM_INFRA_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_INFRA_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* SPM_VRF18_EVENT_COUNT_STA (0x10006000+0x184) */ +#define SPM_VRF18_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_VRF18_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* SPM_APSRC_EVENT_COUNT_STA (0x10006000+0x188) */ +#define SPM_APSRC_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_APSRC_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* SPM_DDREN_EVENT_COUNT_STA (0x10006000+0x18C) */ +#define SPM_DDREN_SLEEP_COUNT_LSB (1U << 0) /* 16b */ +#define SPM_DDREN_WAKE_COUNT_LSB (1U << 16) /* 16b */ +/* MD32PCM_STA (0x10006000+0x190) */ +#define MD32PCM_HALT_LSB (1U << 0) /* 1b */ +#define MD32PCM_GATED_LSB (1U << 1) /* 1b */ +/* MD32PCM_PC (0x10006000+0x194) */ +#define MON_PC_LSB (1U << 0) /* 32b */ +/* DVFSRC_EVENT_STA (0x10006000+0x1A4) */ +#define DVFSRC_EVENT_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT4_RDY (0x10006000+0x1A8) */ +#define PROTECT4_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT5_RDY (0x10006000+0x1AC) */ +#define PROTECT5_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT6_RDY (0x10006000+0x1B0) */ +#define PROTECT6_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT7_RDY (0x10006000+0x1B4) */ +#define PROTECT7_READY_LSB (1U << 0) /* 32b */ +/* BUS_PROTECT8_RDY (0x10006000+0x1B8) */ +#define PROTECT8_READY_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA0 (0x10006000+0x1D0) */ +#define LAST_IDLE_CNT_0_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA1 (0x10006000+0x1D4) */ +#define LAST_IDLE_CNT_1_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA2 (0x10006000+0x1D8) */ +#define LAST_IDLE_CNT_2_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_LAST_STA3 (0x10006000+0x1DC) */ +#define LAST_IDLE_CNT_3_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA0 (0x10006000+0x1E0) */ +#define CURRENT_IDLE_CNT_0_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA1 (0x10006000+0x1E4) */ +#define CURRENT_IDLE_CNT_1_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA2 (0x10006000+0x1E8) */ +#define CURRENT_IDLE_CNT_2_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_CURR_STA3 (0x10006000+0x1EC) */ +#define CURRENT_IDLE_CNT_3_LSB (1U << 0) /* 32b */ +/* SPM_TWAM_TIMER_OUT (0x10006000+0x1F0) */ +#define TWAM_TIMER_LSB (1U << 0) /* 32b */ +/* SPM_CG_CHECK_STA (0x10006000+0x1F4) */ +#define SPM_CG_CHECK_SLEEP_REQ_0_LSB (1U << 0) /* 1b */ +#define SPM_CG_CHECK_SLEEP_REQ_1_LSB (1U << 1) /* 1b */ +#define SPM_CG_CHECK_SLEEP_REQ_2_LSB (1U << 2) /* 1b */ +/* SPM_DVFS_STA (0x10006000+0x1F8) */ +#define TARGET_DVFS_LEVEL_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_OPP_STA (0x10006000+0x1FC) */ +#define TARGET_DVFS_OPP_LSB (1U << 0) /* 5b */ +#define CURRENT_DVFS_OPP_LSB (1U << 5) /* 5b */ +#define RELAY_DVFS_OPP_LSB (1U << 10) /* 5b */ +/* SPM_MCUSYS_PWR_CON (0x10006000+0x200) */ +#define MCUSYS_SPMC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MCUSYS_SPMC_PWR_ON_LSB (1U << 2) /* 1b */ +#define MCUSYS_SPMC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MCUSYS_SPMC_RESETPWRON_CONFIG_LSB (1U << 5) /* 1b */ +#define MCUSYS_SPMC_DORMANT_EN_LSB (1U << 6) /* 1b */ +#define MCUSYS_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */ +#define SPM_MCUSYS_PWR_CON_MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 31) /* 1b */ +/* SPM_CPUTOP_PWR_CON (0x10006000+0x204) */ +#define MP0_SPMC_PWR_RST_B_CPUTOP_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPUTOP_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_PWR_CLK_DIS_CPUTOP_LSB (1U << 4) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPUTOP_LSB (1U << 5) /* 1b */ +#define MP0_SPMC_DORMANT_EN_CPUTOP_LSB (1U << 6) /* 1b */ +#define MP0_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */ +#define MP0_VSRAM_EXT_OFF_LSB (1U << 8) /* 1b */ +#define SPM_CPUTOP_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 31) /* 1b */ +/* SPM_CPU0_PWR_CON (0x10006000+0x208) */ +#define MP0_SPMC_PWR_RST_B_CPU0_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU0_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU0_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU0_LSB (1U << 7) /* 1b */ +#define SPM_CPU0_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 31) /* 1b */ +/* SPM_CPU1_PWR_CON (0x10006000+0x20C) */ +#define MP0_SPMC_PWR_RST_B_CPU1_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU1_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU1_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU1_LSB (1U << 7) /* 1b */ +#define SPM_CPU1_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 31) /* 1b */ +/* SPM_CPU2_PWR_CON (0x10006000+0x210) */ +#define MP0_SPMC_PWR_RST_B_CPU2_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU2_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU2_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU2_LSB (1U << 7) /* 1b */ +#define SPM_CPU2_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 31) /* 1b */ +/* SPM_CPU3_PWR_CON (0x10006000+0x214) */ +#define MP0_SPMC_PWR_RST_B_CPU3_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU3_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU3_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU3_LSB (1U << 7) /* 1b */ +#define SPM_CPU3_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 31) /* 1b */ +/* SPM_CPU4_PWR_CON (0x10006000+0x218) */ +#define MP0_SPMC_PWR_RST_B_CPU4_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU4_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU4_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU4_LSB (1U << 7) /* 1b */ +#define SPM_CPU4_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 31) /* 1b */ +/* SPM_CPU5_PWR_CON (0x10006000+0x21C) */ +#define MP0_SPMC_PWR_RST_B_CPU5_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU5_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU5_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU5_LSB (1U << 7) /* 1b */ +#define SPM_CPU5_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 31) /* 1b */ +/* SPM_CPU6_PWR_CON (0x10006000+0x220) */ +#define MP0_SPMC_PWR_RST_B_CPU6_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU6_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU6_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU6_LSB (1U << 7) /* 1b */ +#define SPM_CPU6_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 31) /* 1b */ +/* SPM_CPU7_PWR_CON (0x10006000+0x224) */ +#define MP0_SPMC_PWR_RST_B_CPU7_LSB (1U << 0) /* 1b */ +#define MP0_SPMC_PWR_ON_CPU7_LSB (1U << 2) /* 1b */ +#define MP0_SPMC_RESETPWRON_CONFIG_CPU7_LSB (1U << 5) /* 1b */ +#define MP0_VPROC_EXT_OFF_CPU7_LSB (1U << 7) /* 1b */ +#define SPM_CPU7_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 31) /* 1b */ +/* ARMPLL_CLK_CON (0x10006000+0x22C) */ +#define SC_ARM_FHC_PAUSE_LSB (1U << 0) /* 6b */ +#define SC_ARM_CK_OFF_LSB (1U << 6) /* 6b */ +#define SC_ARMPLL_OFF_LSB (1U << 12) /* 1b */ +#define SC_ARMBPLL_OFF_LSB (1U << 13) /* 1b */ +#define SC_ARMBPLL1_OFF_LSB (1U << 14) /* 1b */ +#define SC_ARMBPLL2_OFF_LSB (1U << 15) /* 1b */ +#define SC_ARMBPLL3_OFF_LSB (1U << 16) /* 1b */ +#define SC_CCIPLL_CKOFF_LSB (1U << 17) /* 1b */ +#define SC_ARMDDS_OFF_LSB (1U << 18) /* 1b */ +#define SC_ARMBPLL_S_OFF_LSB (1U << 19) /* 1b */ +#define SC_ARMBPLL1_S_OFF_LSB (1U << 20) /* 1b */ +#define SC_ARMBPLL2_S_OFF_LSB (1U << 21) /* 1b */ +#define SC_ARMBPLL3_S_OFF_LSB (1U << 22) /* 1b */ +#define SC_CCIPLL_PWROFF_LSB (1U << 23) /* 1b */ +#define SC_ARMPLLOUT_OFF_LSB (1U << 24) /* 1b */ +#define SC_ARMBPLLOUT_OFF_LSB (1U << 25) /* 1b */ +#define SC_ARMBPLLOUT1_OFF_LSB (1U << 26) /* 1b */ +#define SC_ARMBPLLOUT2_OFF_LSB (1U << 27) /* 1b */ +#define SC_ARMBPLLOUT3_OFF_LSB (1U << 28) /* 1b */ +#define SC_CCIPLL_OUT_OFF_LSB (1U << 29) /* 1b */ +/* MCUSYS_IDLE_STA (0x10006000+0x230) */ +#define ARMBUS_IDLE_TO_26M_LSB (1U << 0) /* 1b */ +#define MP0_CLUSTER_IDLE_TO_PWR_OFF_LSB (1U << 1) /* 1b */ +#define MCUSYS_DDR_EN_0_LSB (1U << 2) /* 1b */ +#define MCUSYS_DDR_EN_1_LSB (1U << 3) /* 1b */ +#define MCUSYS_DDR_EN_2_LSB (1U << 4) /* 1b */ +#define MCUSYS_DDR_EN_3_LSB (1U << 5) /* 1b */ +#define MCUSYS_DDR_EN_4_LSB (1U << 6) /* 1b */ +#define MCUSYS_DDR_EN_5_LSB (1U << 7) /* 1b */ +#define MCUSYS_DDR_EN_6_LSB (1U << 8) /* 1b */ +#define MCUSYS_DDR_EN_7_LSB (1U << 9) /* 1b */ +#define MP0_CPU_IDLE_TO_PWR_OFF_LSB (1U << 16) /* 8b */ +#define WFI_AF_SEL_LSB (1U << 24) /* 8b */ +/* GIC_WAKEUP_STA (0x10006000+0x234) */ +#define GIC_WAKEUP_STA_GIC_WAKEUP_LSB (1U << 10) /* 10b */ +/* CPU_SPARE_CON (0x10006000+0x238) */ +#define CPU_SPARE_CON_LSB (1U << 0) /* 32b */ +/* CPU_SPARE_CON_SET (0x10006000+0x23C) */ +#define CPU_SPARE_CON_SET_LSB (1U << 0) /* 32b */ +/* CPU_SPARE_CON_CLR (0x10006000+0x240) */ +#define CPU_SPARE_CON_CLR_LSB (1U << 0) /* 32b */ +/* ARMPLL_CLK_SEL (0x10006000+0x244) */ +#define ARMPLL_CLK_SEL_LSB (1U << 0) /* 15b */ +/* EXT_INT_WAKEUP_REQ (0x10006000+0x248) */ +#define EXT_INT_WAKEUP_REQ_LSB (1U << 0) /* 10b */ +/* EXT_INT_WAKEUP_REQ_SET (0x10006000+0x24C) */ +#define EXT_INT_WAKEUP_REQ_SET_LSB (1U << 0) /* 10b */ +/* EXT_INT_WAKEUP_REQ_CLR (0x10006000+0x250) */ +#define EXT_INT_WAKEUP_REQ_CLR_LSB (1U << 0) /* 10b */ +/* MP0_CPU0_IRQ_MASK (0x10006000+0x260) */ +#define MP0_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU0_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU1_IRQ_MASK (0x10006000+0x264) */ +#define MP0_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU1_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU2_IRQ_MASK (0x10006000+0x268) */ +#define MP0_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU2_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU3_IRQ_MASK (0x10006000+0x26C) */ +#define MP0_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP0_CPU3_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU0_IRQ_MASK (0x10006000+0x270) */ +#define MP1_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU0_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU1_IRQ_MASK (0x10006000+0x274) */ +#define MP1_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU1_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU2_IRQ_MASK (0x10006000+0x278) */ +#define MP1_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU2_AUX_LSB (1U << 8) /* 11b */ +/* MP1_CPU3_IRQ_MASK (0x10006000+0x27C) */ +#define MP1_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */ +#define MP1_CPU3_AUX_LSB (1U << 8) /* 11b */ +/* MP0_CPU0_WFI_EN (0x10006000+0x280) */ +#define MP0_CPU0_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU1_WFI_EN (0x10006000+0x284) */ +#define MP0_CPU1_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU2_WFI_EN (0x10006000+0x288) */ +#define MP0_CPU2_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU3_WFI_EN (0x10006000+0x28C) */ +#define MP0_CPU3_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU4_WFI_EN (0x10006000+0x290) */ +#define MP0_CPU4_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU5_WFI_EN (0x10006000+0x294) */ +#define MP0_CPU5_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU6_WFI_EN (0x10006000+0x298) */ +#define MP0_CPU6_WFI_EN_LSB (1U << 0) /* 1b */ +/* MP0_CPU7_WFI_EN (0x10006000+0x29C) */ +#define MP0_CPU7_WFI_EN_LSB (1U << 0) /* 1b */ +/* ROOT_CPUTOP_ADDR (0x10006000+0x2A0) */ +#define ROOT_CPUTOP_ADDR_LSB (1U << 0) /* 32b */ +/* ROOT_CORE_ADDR (0x10006000+0x2A4) */ +#define ROOT_CORE_ADDR_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_0 (0x10006000+0x2D0) */ +#define SPM2SW_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_1 (0x10006000+0x2D4) */ +#define SPM2SW_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_2 (0x10006000+0x2D8) */ +#define SPM2SW_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SPM2SW_MAILBOX_3 (0x10006000+0x2DC) */ +#define SPM2SW_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* SW2SPM_INT (0x10006000+0x2E0) */ +#define SW2SPM_INT_SW2SPM_INT_LSB (1U << 0) /* 4b */ +/* SW2SPM_INT_SET (0x10006000+0x2E4) */ +#define SW2SPM_INT_SET_LSB (1U << 0) /* 4b */ +/* SW2SPM_INT_CLR (0x10006000+0x2E8) */ +#define SW2SPM_INT_CLR_LSB (1U << 0) /* 4b */ +/* SW2SPM_MAILBOX_0 (0x10006000+0x2EC) */ +#define SW2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_1 (0x10006000+0x2F0) */ +#define SW2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_2 (0x10006000+0x2F4) */ +#define SW2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SW2SPM_MAILBOX_3 (0x10006000+0x2F8) */ +#define SW2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* SW2SPM_CFG (0x10006000+0x2FC) */ +#define SWU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */ +/* MD1_PWR_CON (0x10006000+0x300) */ +#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MD1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MD1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* CONN_PWR_CON (0x10006000+0x304) */ +#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CONN_PWR_ON_LSB (1U << 2) /* 1b */ +#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +/* MFG0_PWR_CON (0x10006000+0x308) */ +#define MFG0_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG0_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG0_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG0_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG0_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG0_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG1_PWR_CON (0x10006000+0x30C) */ +#define MFG1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG1_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG2_PWR_CON (0x10006000+0x310) */ +#define MFG2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG2_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG3_PWR_CON (0x10006000+0x314) */ +#define MFG3_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG3_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG3_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG3_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG3_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG3_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG4_PWR_CON (0x10006000+0x318) */ +#define MFG4_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG4_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG4_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG4_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG4_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG4_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG4_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG5_PWR_CON (0x10006000+0x31C) */ +#define MFG5_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG5_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG5_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG5_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG5_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG5_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG5_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MFG6_PWR_CON (0x10006000+0x320) */ +#define MFG6_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MFG6_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MFG6_PWR_ON_LSB (1U << 2) /* 1b */ +#define MFG6_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MFG6_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MFG6_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MFG6_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* IFR_PWR_CON (0x10006000+0x324) */ +#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IFR_PWR_ON_LSB (1U << 2) /* 1b */ +#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IFR_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* IFR_SUB_PWR_CON (0x10006000+0x328) */ +#define IFR_SUB_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IFR_SUB_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IFR_SUB_PWR_ON_LSB (1U << 2) /* 1b */ +#define IFR_SUB_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IFR_SUB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IFR_SUB_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IFR_SUB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* DPY_PWR_CON (0x10006000+0x32C) */ +#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DPY_PWR_ON_LSB (1U << 2) /* 1b */ +#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DPY_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DPY_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* ISP_PWR_CON (0x10006000+0x330) */ +#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ISP_PWR_ON_LSB (1U << 2) /* 1b */ +#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ISP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* ISP2_PWR_CON (0x10006000+0x334) */ +#define ISP2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ISP2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ISP2_PWR_ON_LSB (1U << 2) /* 1b */ +#define ISP2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ISP2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ISP2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_ISP2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* IPE_PWR_CON (0x10006000+0x338) */ +#define IPE_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define IPE_PWR_ISO_LSB (1U << 1) /* 1b */ +#define IPE_PWR_ON_LSB (1U << 2) /* 1b */ +#define IPE_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define IPE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define IPE_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_IPE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VDE_PWR_CON (0x10006000+0x33C) */ +#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VDE_PWR_ON_LSB (1U << 2) /* 1b */ +#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VDE_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VDE2_PWR_CON (0x10006000+0x340) */ +#define VDE2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VDE2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VDE2_PWR_ON_LSB (1U << 2) /* 1b */ +#define VDE2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VDE2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VDE2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VDE2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VEN_PWR_CON (0x10006000+0x344) */ +#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VEN_PWR_ON_LSB (1U << 2) /* 1b */ +#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VEN_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* VEN_CORE1_PWR_CON (0x10006000+0x348) */ +#define VEN_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define VEN_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */ +#define VEN_CORE1_PWR_ON_LSB (1U << 2) /* 1b */ +#define VEN_CORE1_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define VEN_CORE1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define VEN_CORE1_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_VEN_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* MDP_PWR_CON (0x10006000+0x34C) */ +#define MDP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define MDP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define MDP_PWR_ON_LSB (1U << 2) /* 1b */ +#define MDP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define MDP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define MDP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_MDP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* DIS_PWR_CON (0x10006000+0x350) */ +#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DIS_PWR_ON_LSB (1U << 2) /* 1b */ +#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DIS_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* AUDIO_PWR_CON (0x10006000+0x354) */ +#define AUDIO_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define AUDIO_PWR_ISO_LSB (1U << 1) /* 1b */ +#define AUDIO_PWR_ON_LSB (1U << 2) /* 1b */ +#define AUDIO_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define AUDIO_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define AUDIO_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_AUDIO_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* ADSP_PWR_CON (0x10006000+0x358) */ +#define ADSP_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define ADSP_PWR_ISO_LSB (1U << 1) /* 1b */ +#define ADSP_PWR_ON_LSB (1U << 2) /* 1b */ +#define ADSP_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define ADSP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define ADSP_SRAM_CKISO_LSB (1U << 5) /* 1b */ +#define ADSP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */ +#define ADSP_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define ADSP_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */ +#define SC_ADSP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +#define SC_ADSP_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */ +/* CAM_PWR_CON (0x10006000+0x35C) */ +#define CAM_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* CAM_RAWA_PWR_CON (0x10006000+0x360) */ +#define CAM_RAWA_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWA_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWA_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWA_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWA_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWA_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* CAM_RAWB_PWR_CON (0x10006000+0x364) */ +#define CAM_RAWB_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWB_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWB_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWB_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWB_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* CAM_RAWC_PWR_CON (0x10006000+0x368) */ +#define CAM_RAWC_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define CAM_RAWC_PWR_ISO_LSB (1U << 1) /* 1b */ +#define CAM_RAWC_PWR_ON_LSB (1U << 2) /* 1b */ +#define CAM_RAWC_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define CAM_RAWC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define CAM_RAWC_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_CAM_RAWC_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* SYSRAM_CON (0x10006000+0x36C) */ +#define SYSRAM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SYSRAM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SYSRAM_SRAM_SLEEP_B_LSB (1U << 4) /* 4b */ +#define SYSRAM_SRAM_PDN_LSB (1U << 16) /* 4b */ +/* SYSROM_CON (0x10006000+0x370) */ +#define SYSROM_SRAM_PDN_LSB (1U << 0) /* 6b */ +/* SSPM_SRAM_CON (0x10006000+0x374) */ +#define SSPM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SSPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SSPM_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SSPM_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* SCP_SRAM_CON (0x10006000+0x378) */ +#define SCP_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define SCP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define SCP_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* DPY_SHU_SRAM_CON (0x10006000+0x37C) */ +#define DPY_SHU_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPY_SHU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPY_SHU_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */ +#define DPY_SHU_SRAM_PDN_LSB (1U << 16) /* 2b */ +/* UFS_SRAM_CON (0x10006000+0x380) */ +#define UFS_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define UFS_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define UFS_SRAM_SLEEP_B_LSB (1U << 4) /* 5b */ +#define UFS_SRAM_PDN_LSB (1U << 16) /* 5b */ +/* DEVAPC_IFR_SRAM_CON (0x10006000+0x384) */ +#define DEVAPC_IFR_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_IFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_IFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */ +#define DEVAPC_IFR_SRAM_PDN_LSB (1U << 16) /* 6b */ +/* DEVAPC_SUBIFR_SRAM_CON (0x10006000+0x388) */ +#define DEVAPC_SUBIFR_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_SUBIFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_SUBIFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */ +#define DEVAPC_SUBIFR_SRAM_PDN_LSB (1U << 16) /* 6b */ +/* DEVAPC_ACP_SRAM_CON (0x10006000+0x38C) */ +#define DEVAPC_ACP_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DEVAPC_ACP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DEVAPC_ACP_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */ +#define DEVAPC_ACP_SRAM_PDN_LSB (1U << 16) /* 6b */ +/* USB_SRAM_CON (0x10006000+0x390) */ +#define USB_SRAM_PDN_LSB (1U << 0) /* 7b */ +/* DUMMY_SRAM_CON (0x10006000+0x394) */ +#define DUMMY_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DUMMY_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DUMMY_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */ +#define DUMMY_SRAM_PDN_LSB (1U << 16) /* 8b */ +/* MD_EXT_BUCK_ISO_CON (0x10006000+0x398) */ +#define VMODEM_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +#define VMD_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */ +/* EXT_BUCK_ISO (0x10006000+0x39C) */ +#define VIMVO_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */ +#define GPU_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */ +#define IPU_EXT_BUCK_ISO_LSB (1U << 5) /* 3b */ +/* DXCC_SRAM_CON (0x10006000+0x3A0) */ +#define DXCC_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DXCC_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DXCC_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DXCC_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* MSDC_SRAM_CON (0x10006000+0x3A4) */ +#define MSDC_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define MSDC_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define MSDC_SRAM_SLEEP_B_LSB (1U << 4) /* 5b */ +#define MSDC_SRAM_PDN_LSB (1U << 16) /* 5b */ +/* DEBUGTOP_SRAM_CON (0x10006000+0x3A8) */ +#define DEBUGTOP_SRAM_PDN_LSB (1U << 0) /* 1b */ +/* DP_TX_PWR_CON (0x10006000+0x3AC) */ +#define DP_TX_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DP_TX_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DP_TX_PWR_ON_LSB (1U << 2) /* 1b */ +#define DP_TX_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DP_TX_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DP_TX_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DP_TX_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* DPMAIF_SRAM_CON (0x10006000+0x3B0) */ +#define DPMAIF_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPMAIF_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPMAIF_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DPMAIF_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* DPY_SHU2_SRAM_CON (0x10006000+0x3B4) */ +#define DPY_SHU2_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DPY_SHU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DPY_SHU2_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */ +#define DPY_SHU2_SRAM_PDN_LSB (1U << 16) /* 2b */ +/* DRAMC_MCU2_SRAM_CON (0x10006000+0x3B8) */ +#define DRAMC_MCU2_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DRAMC_MCU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DRAMC_MCU2_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DRAMC_MCU2_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* DRAMC_MCU_SRAM_CON (0x10006000+0x3BC) */ +#define DRAMC_MCU_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define DRAMC_MCU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define DRAMC_MCU_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */ +#define DRAMC_MCU_SRAM_PDN_LSB (1U << 16) /* 1b */ +/* MCUPM_SRAM_CON (0x10006000+0x3C0) */ +#define MCUPM_SRAM_CKISO_LSB (1U << 0) /* 1b */ +#define MCUPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */ +#define MCUPM_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */ +#define MCUPM_SRAM_PDN_LSB (1U << 16) /* 8b */ +/* DPY2_PWR_CON (0x10006000+0x3C4) */ +#define DPY2_PWR_RST_B_LSB (1U << 0) /* 1b */ +#define DPY2_PWR_ISO_LSB (1U << 1) /* 1b */ +#define DPY2_PWR_ON_LSB (1U << 2) /* 1b */ +#define DPY2_PWR_ON_2ND_LSB (1U << 3) /* 1b */ +#define DPY2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */ +#define DPY2_SRAM_PDN_LSB (1U << 8) /* 1b */ +#define SC_DPY2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */ +/* SPM_MEM_CK_SEL (0x10006000+0x400) */ +#define SC_MEM_CK_SEL_LSB (1U << 0) /* 1b */ +#define SPM2CKSYS_MEM_CK_MUX_UPDATE_LSB (1U << 1) /* 1b */ +/* SPM_BUS_PROTECT_MASK_B (0x10006000+0X404) */ +#define SPM_BUS_PROTECT_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT1_MASK_B (0x10006000+0x408) */ +#define SPM_BUS_PROTECT1_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT2_MASK_B (0x10006000+0x40C) */ +#define SPM_BUS_PROTECT2_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT3_MASK_B (0x10006000+0x410) */ +#define SPM_BUS_PROTECT3_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT4_MASK_B (0x10006000+0x414) */ +#define SPM_BUS_PROTECT4_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_EMI_BW_MODE (0x10006000+0x418) */ +#define EMI_BW_MODE_LSB (1U << 0) /* 1b */ +#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */ +#define EMI_BW_MODE_2_LSB (1U << 2) /* 1b */ +#define EMI_BOOST_MODE_2_LSB (1U << 3) /* 1b */ +/* AP2MD_PEER_WAKEUP (0x10006000+0x41C) */ +#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */ +/* ULPOSC_CON (0x10006000+0x420) */ +#define ULPOSC_EN_LSB (1U << 0) /* 1b */ +#define ULPOSC_RST_LSB (1U << 1) /* 1b */ +#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */ +#define ULPOSC_CLK_SEL_LSB (1U << 3) /* 1b */ +/* SPM2MM_CON (0x10006000+0x424) */ +#define SPM2MM_FORCE_ULTRA_LSB (1U << 0) /* 1b */ +#define SPM2MM_DBL_OSTD_ACT_LSB (1U << 1) /* 1b */ +#define SPM2MM_ULTRAREQ_LSB (1U << 2) /* 1b */ +#define SPM2MD_ULTRAREQ_LSB (1U << 3) /* 1b */ +#define SPM2ISP_ULTRAREQ_LSB (1U << 4) /* 1b */ +#define MM2SPM_FORCE_ULTRA_ACK_D2T_LSB (1U << 16) /* 1b */ +#define MM2SPM_DBL_OSTD_ACT_ACK_D2T_LSB (1U << 17) /* 1b */ +#define SPM2ISP_ULTRAACK_D2T_LSB (1U << 18) /* 1b */ +#define SPM2MM_ULTRAACK_D2T_LSB (1U << 19) /* 1b */ +#define SPM2MD_ULTRAACK_D2T_LSB (1U << 20) /* 1b */ +/* SPM_BUS_PROTECT5_MASK_B (0x10006000+0x428) */ +#define SPM_BUS_PROTECT5_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM2MCUPM_CON (0x10006000+0x42C) */ +#define SPM2MCUPM_SW_RST_B_LSB (1U << 0) /* 1b */ +#define SPM2MCUPM_SW_INT_LSB (1U << 1) /* 1b */ +/* AP_MDSRC_REQ (0x10006000+0x430) */ +#define AP_MDSMSRC_REQ_LSB (1U << 0) /* 1b */ +#define AP_L1SMSRC_REQ_LSB (1U << 1) /* 1b */ +#define AP_MD2SRC_REQ_LSB (1U << 2) /* 1b */ +#define AP_MDSMSRC_ACK_LSB (1U << 4) /* 1b */ +#define AP_L1SMSRC_ACK_LSB (1U << 5) /* 1b */ +#define AP_MD2SRC_ACK_LSB (1U << 6) /* 1b */ +/* SPM2EMI_ENTER_ULPM (0x10006000+0x434) */ +#define SPM2EMI_ENTER_ULPM_LSB (1U << 0) /* 1b */ +/* SPM2MD_DVFS_CON (0x10006000+0x438) */ +#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 32b */ +/* MD2SPM_DVFS_CON (0x10006000+0x43C) */ +#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT6_MASK_B (0x10006000+0X440) */ +#define SPM_BUS_PROTECT6_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT7_MASK_B (0x10006000+0x444) */ +#define SPM_BUS_PROTECT7_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_BUS_PROTECT8_MASK_B (0x10006000+0x448) */ +#define SPM_BUS_PROTECT8_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PLL_CON (0x10006000+0x44C) */ +#define SC_MAINPLLOUT_OFF_LSB (1U << 0) /* 1b */ +#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */ +#define SC_MAINPLL_OFF_LSB (1U << 4) /* 1b */ +#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */ +#define SC_MAINPLL_S_OFF_LSB (1U << 8) /* 1b */ +#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */ +#define SC_SMI_CK_OFF_LSB (1U << 16) /* 1b */ +#define SC_MD32K_CK_OFF_LSB (1U << 17) /* 1b */ +#define SC_CKSQ1_OFF_LSB (1U << 18) /* 1b */ +#define SC_AXI_MEM_CK_OFF_LSB (1U << 19) /* 1b */ +/* CPU_DVFS_REQ (0x10006000+0x450) */ +#define CPU_DVFS_REQ_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_CON_0 (0x10006000+0x454) */ +#define SW_DDR_PST_REQ_LSB (1U << 0) /* 2b */ +#define SW_DDR_PST_ABORT_REQ_LSB (1U << 2) /* 2b */ +/* SPM_DRAM_MCU_SW_CON_1 (0x10006000+0x458) */ +#define SW_DDR_PST_CH0_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_CON_2 (0x10006000+0x45C) */ +#define SW_DDR_PST_CH1_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_CON_3 (0x10006000+0x460) */ +#define SW_DDR_RESERVED_CH0_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_CON_4 (0x10006000+0x464) */ +#define SW_DDR_RESERVED_CH1_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_STA_0 (0x10006000+0x468) */ +#define SC_DDR_PST_ACK_LSB (1U << 0) /* 2b */ +#define SC_DDR_PST_ABORT_ACK_LSB (1U << 2) /* 2b */ +/* SPM_DRAM_MCU_STA_1 (0x10006000+0x46C) */ +#define SC_DDR_CUR_PST_STA_CH0_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_STA_2 (0x10006000+0x470) */ +#define SC_DDR_CUR_PST_STA_CH1_LSB (1U << 0) /* 32b */ +/* SPM_DRAM_MCU_SW_SEL_0 (0x10006000+0x474) */ +#define SW_DDR_PST_REQ_SEL_LSB (1U << 0) /* 2b */ +#define SW_DDR_PST_SEL_LSB (1U << 2) /* 2b */ +#define SW_DDR_PST_ABORT_REQ_SEL_LSB (1U << 4) /* 2b */ +#define SW_DDR_RESERVED_SEL_LSB (1U << 6) /* 2b */ +#define SW_DDR_PST_ACK_SEL_LSB (1U << 8) /* 2b */ +#define SW_DDR_PST_ABORT_ACK_SEL_LSB (1U << 10) /* 2b */ +/* RELAY_DVFS_LEVEL (0x10006000+0x478) */ +#define RELAY_DVFS_LEVEL_LSB (1U << 0) /* 32b */ +/* DRAMC_DPY_CLK_SW_CON_0 (0x10006000+0x480) */ +#define SW_PHYPLL_EN_LSB (1U << 0) /* 2b */ +#define SW_DPY_VREF_EN_LSB (1U << 2) /* 2b */ +#define SW_DPY_DLL_CK_EN_LSB (1U << 4) /* 2b */ +#define SW_DPY_DLL_EN_LSB (1U << 6) /* 2b */ +#define SW_DPY_2ND_DLL_EN_LSB (1U << 8) /* 2b */ +#define SW_MEM_CK_OFF_LSB (1U << 10) /* 2b */ +#define SW_DMSUS_OFF_LSB (1U << 12) /* 2b */ +#define SW_DPY_MODE_SW_LSB (1U << 14) /* 2b */ +#define SW_EMI_CLK_OFF_LSB (1U << 16) /* 2b */ +#define SW_DDRPHY_FB_CK_EN_LSB (1U << 18) /* 2b */ +#define SW_DR_GATE_RETRY_EN_LSB (1U << 20) /* 2b */ +#define SW_DPHY_PRECAL_UP_LSB (1U << 24) /* 2b */ +#define SW_DPY_BCLK_ENABLE_LSB (1U << 26) /* 2b */ +#define SW_TX_TRACKING_DIS_LSB (1U << 28) /* 2b */ +#define SW_DPHY_RXDLY_TRACKING_EN_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_CON_1 (0x10006000+0x484) */ +#define SW_SHU_RESTORE_LSB (1U << 0) /* 2b */ +#define SW_DMYRD_MOD_LSB (1U << 2) /* 2b */ +#define SW_DMYRD_INTV_LSB (1U << 4) /* 2b */ +#define SW_DMYRD_EN_LSB (1U << 6) /* 2b */ +#define SW_DRS_DIS_REQ_LSB (1U << 8) /* 2b */ +#define SW_DR_SRAM_LOAD_LSB (1U << 10) /* 2b */ +#define SW_DR_SRAM_RESTORE_LSB (1U << 12) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_LATCH_LSB (1U << 14) /* 2b */ +#define SW_TX_TRACK_RETRY_EN_LSB (1U << 16) /* 2b */ +#define SW_DPY_MIDPI_EN_LSB (1U << 18) /* 2b */ +#define SW_DPY_PI_RESETB_EN_LSB (1U << 20) /* 2b */ +#define SW_DPY_MCK8X_EN_LSB (1U << 22) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_CH0_LSB (1U << 24) /* 4b */ +#define SW_DR_SHU_LEVEL_SRAM_CH1_LSB (1U << 28) /* 4b */ +/* DRAMC_DPY_CLK_SW_CON_2 (0x10006000+0x488) */ +#define SW_DR_SHU_LEVEL_LSB (1U << 0) /* 2b */ +#define SW_DR_SHU_EN_LSB (1U << 2) /* 1b */ +#define SW_DR_SHORT_QUEUE_LSB (1U << 3) /* 1b */ +#define SW_PHYPLL_MODE_SW_LSB (1U << 4) /* 1b */ +#define SW_PHYPLL2_MODE_SW_LSB (1U << 5) /* 1b */ +#define SW_PHYPLL_SHU_EN_LSB (1U << 6) /* 1b */ +#define SW_PHYPLL2_SHU_EN_LSB (1U << 7) /* 1b */ +#define SW_DR_RESERVED_0_LSB (1U << 24) /* 2b */ +#define SW_DR_RESERVED_1_LSB (1U << 26) /* 2b */ +#define SW_DR_RESERVED_2_LSB (1U << 28) /* 2b */ +#define SW_DR_RESERVED_3_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_CON_3 (0x10006000+0x48C) */ +#define SC_DR_SHU_EN_ACK_LSB (1U << 0) /* 4b */ +#define SC_EMI_CLK_OFF_ACK_LSB (1U << 4) /* 4b */ +#define SC_DR_SHORT_QUEUE_ACK_LSB (1U << 8) /* 4b */ +#define SC_DRAMC_DFS_STA_LSB (1U << 12) /* 4b */ +#define SC_DRS_DIS_ACK_LSB (1U << 16) /* 4b */ +#define SC_DR_SRAM_LOAD_ACK_LSB (1U << 20) /* 4b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_LSB (1U << 24) /* 4b */ +#define SC_DR_SRAM_RESTORE_ACK_LSB (1U << 28) /* 4b */ +/* DRAMC_DPY_CLK_SW_SEL_0 (0x10006000+0x490) */ +#define SW_PHYPLL_EN_SEL_LSB (1U << 0) /* 2b */ +#define SW_DPY_VREF_EN_SEL_LSB (1U << 2) /* 2b */ +#define SW_DPY_DLL_CK_EN_SEL_LSB (1U << 4) /* 2b */ +#define SW_DPY_DLL_EN_SEL_LSB (1U << 6) /* 2b */ +#define SW_DPY_2ND_DLL_EN_SEL_LSB (1U << 8) /* 2b */ +#define SW_MEM_CK_OFF_SEL_LSB (1U << 10) /* 2b */ +#define SW_DMSUS_OFF_SEL_LSB (1U << 12) /* 2b */ +#define SW_DPY_MODE_SW_SEL_LSB (1U << 14) /* 2b */ +#define SW_EMI_CLK_OFF_SEL_LSB (1U << 16) /* 2b */ +#define SW_DDRPHY_FB_CK_EN_SEL_LSB (1U << 18) /* 2b */ +#define SW_DR_GATE_RETRY_EN_SEL_LSB (1U << 20) /* 2b */ +#define SW_DPHY_PRECAL_UP_SEL_LSB (1U << 24) /* 2b */ +#define SW_DPY_BCLK_ENABLE_SEL_LSB (1U << 26) /* 2b */ +#define SW_TX_TRACKING_DIS_SEL_LSB (1U << 28) /* 2b */ +#define SW_DPHY_RXDLY_TRACKING_EN_SEL_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_SEL_1 (0x10006000+0x494) */ +#define SW_SHU_RESTORE_SEL_LSB (1U << 0) /* 2b */ +#define SW_DMYRD_MOD_SEL_LSB (1U << 2) /* 2b */ +#define SW_DMYRD_INTV_SEL_LSB (1U << 4) /* 2b */ +#define SW_DMYRD_EN_SEL_LSB (1U << 6) /* 2b */ +#define SW_DRS_DIS_REQ_SEL_LSB (1U << 8) /* 2b */ +#define SW_DR_SRAM_LOAD_SEL_LSB (1U << 10) /* 2b */ +#define SW_DR_SRAM_RESTORE_SEL_LSB (1U << 12) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_LATCH_SEL_LSB (1U << 14) /* 2b */ +#define SW_TX_TRACK_RETRY_EN_SEL_LSB (1U << 16) /* 2b */ +#define SW_DPY_MIDPI_EN_SEL_LSB (1U << 18) /* 2b */ +#define SW_DPY_PI_RESETB_EN_SEL_LSB (1U << 20) /* 2b */ +#define SW_DPY_MCK8X_EN_SEL_LSB (1U << 22) /* 2b */ +#define SW_DR_SHU_LEVEL_SRAM_SEL_LSB (1U << 24) /* 2b */ +/* DRAMC_DPY_CLK_SW_SEL_2 (0x10006000+0x498) */ +#define SW_DR_SHU_LEVEL_SEL_LSB (1U << 0) /* 1b */ +#define SW_DR_SHU_EN_SEL_LSB (1U << 2) /* 1b */ +#define SW_DR_SHORT_QUEUE_SEL_LSB (1U << 3) /* 1b */ +#define SW_PHYPLL_MODE_SW_SEL_LSB (1U << 4) /* 1b */ +#define SW_PHYPLL2_MODE_SW_SEL_LSB (1U << 5) /* 1b */ +#define SW_PHYPLL_SHU_EN_SEL_LSB (1U << 6) /* 1b */ +#define SW_PHYPLL2_SHU_EN_SEL_LSB (1U << 7) /* 1b */ +#define SW_DR_RESERVED_0_SEL_LSB (1U << 24) /* 2b */ +#define SW_DR_RESERVED_1_SEL_LSB (1U << 26) /* 2b */ +#define SW_DR_RESERVED_2_SEL_LSB (1U << 28) /* 2b */ +#define SW_DR_RESERVED_3_SEL_LSB (1U << 30) /* 2b */ +/* DRAMC_DPY_CLK_SW_SEL_3 (0x10006000+0x49C) */ +#define SC_DR_SHU_EN_ACK_SEL_LSB (1U << 0) /* 4b */ +#define SC_EMI_CLK_OFF_ACK_SEL_LSB (1U << 4) /* 4b */ +#define SC_DR_SHORT_QUEUE_ACK_SEL_LSB (1U << 8) /* 4b */ +#define SC_DRAMC_DFS_STA_SEL_LSB (1U << 12) /* 4b */ +#define SC_DRS_DIS_ACK_SEL_LSB (1U << 16) /* 4b */ +#define SC_DR_SRAM_LOAD_ACK_SEL_LSB (1U << 20) /* 4b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_SEL_LSB (1U << 24) /* 4b */ +#define SC_DR_SRAM_RESTORE_ACK_SEL_LSB (1U << 28) /* 4b */ +/* DRAMC_DPY_CLK_SPM_CON (0x10006000+0x4A0) */ +#define SC_DMYRD_EN_MOD_SEL_PCM_LSB (1U << 0) /* 1b */ +#define SC_DMYRD_INTV_SEL_PCM_LSB (1U << 1) /* 1b */ +#define SC_DMYRD_EN_PCM_LSB (1U << 2) /* 1b */ +#define SC_DRS_DIS_REQ_PCM_LSB (1U << 3) /* 1b */ +#define SC_DR_SHU_LEVEL_SRAM_PCM_LSB (1U << 4) /* 4b */ +#define SC_DR_GATE_RETRY_EN_PCM_LSB (1U << 8) /* 1b */ +#define SC_DR_SHORT_QUEUE_PCM_LSB (1U << 9) /* 1b */ +#define SC_DPY_MIDPI_EN_PCM_LSB (1U << 10) /* 1b */ +#define SC_DPY_PI_RESETB_EN_PCM_LSB (1U << 11) /* 1b */ +#define SC_DPY_MCK8X_EN_PCM_LSB (1U << 12) /* 1b */ +#define SC_DR_RESERVED_0_PCM_LSB (1U << 13) /* 1b */ +#define SC_DR_RESERVED_1_PCM_LSB (1U << 14) /* 1b */ +#define SC_DR_RESERVED_2_PCM_LSB (1U << 15) /* 1b */ +#define SC_DR_RESERVED_3_PCM_LSB (1U << 16) /* 1b */ +#define SC_DMDRAMCSHU_ACK_ALL_LSB (1U << 24) /* 1b */ +#define SC_EMI_CLK_OFF_ACK_ALL_LSB (1U << 25) /* 1b */ +#define SC_DR_SHORT_QUEUE_ACK_ALL_LSB (1U << 26) /* 1b */ +#define SC_DRAMC_DFS_STA_ALL_LSB (1U << 27) /* 1b */ +#define SC_DRS_DIS_ACK_ALL_LSB (1U << 28) /* 1b */ +#define SC_DR_SRAM_LOAD_ACK_ALL_LSB (1U << 29) /* 1b */ +#define SC_DR_SRAM_PLL_LOAD_ACK_ALL_LSB (1U << 30) /* 1b */ +#define SC_DR_SRAM_RESTORE_ACK_ALL_LSB (1U << 31) /* 1b */ +/* SPM_DVFS_LEVEL (0x10006000+0x4A4) */ +#define SPM_DVFS_LEVEL_LSB (1U << 0) /* 32b */ +/* SPM_CIRQ_CON (0x10006000+0x4A8) */ +#define CIRQ_CLK_SEL_LSB (1U << 0) /* 1b */ +/* SPM_DVFS_MISC (0x10006000+0x4AC) */ +#define MSDC_DVFS_REQUEST_LSB (1U << 0) /* 1b */ +#define SPM2EMI_SLP_PROT_EN_LSB (1U << 1) /* 1b */ +#define SPM_DVFS_FORCE_ENABLE_LSB (1U << 2) /* 1b */ +#define FORCE_DVFS_WAKE_LSB (1U << 3) /* 1b */ +#define SPM_DVFSRC_ENABLE_LSB (1U << 4) /* 1b */ +#define SPM_DVFS_DONE_LSB (1U << 5) /* 1b */ +#define DVFSRC_IRQ_WAKEUP_EVENT_MASK_LSB (1U << 6) /* 1b */ +#define SPM2RC_EVENT_ABORT_LSB (1U << 7) /* 1b */ +#define EMI_SLP_IDLE_LSB (1U << 14) /* 1b */ +#define SDIO_READY_TO_SPM_LSB (1U << 15) /* 1b */ +/* SPM_VS1_VS2_RC_CON (0x10006000+0x4B0) */ +#define VS1_INIT_LEVEL_LSB (1U << 0) /* 2b */ +#define VS1_INIT_LSB (1U << 2) /* 1b */ +#define VS1_CURR_LEVEL_LSB (1U << 3) /* 2b */ +#define VS1_NEXT_LEVEL_LSB (1U << 5) /* 2b */ +#define VS1_VOTE_LEVEL_LSB (1U << 7) /* 2b */ +#define VS1_TRIGGER_LSB (1U << 9) /* 1b */ +#define VS2_INIT_LEVEL_LSB (1U << 10) /* 3b */ +#define VS2_INIT_LSB (1U << 13) /* 1b */ +#define VS2_CURR_LEVEL_LSB (1U << 14) /* 3b */ +#define VS2_NEXT_LEVEL_LSB (1U << 17) /* 3b */ +#define VS2_VOTE_LEVEL_LSB (1U << 20) /* 3b */ +#define VS2_TRIGGER_LSB (1U << 23) /* 1b */ +#define VS1_FORCE_LSB (1U << 24) /* 1b */ +#define VS2_FORCE_LSB (1U << 25) /* 1b */ +#define VS1_VOTE_LEVEL_FORCE_LSB (1U << 26) /* 2b */ +#define VS2_VOTE_LEVEL_FORCE_LSB (1U << 28) /* 3b */ +/* RG_MODULE_SW_CG_0_MASK_REQ_0 (0x10006000+0x4B4) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_0_MASK_REQ_1 (0x10006000+0x4B8) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_0_MASK_REQ_2 (0x10006000+0x4BC) */ +#define RG_MODULE_SW_CG_0_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_1_MASK_REQ_0 (0x10006000+0x4C0) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_1_MASK_REQ_1 (0x10006000+0x4C4) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_1_MASK_REQ_2 (0x10006000+0x4C8) */ +#define RG_MODULE_SW_CG_1_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_2_MASK_REQ_0 (0x10006000+0x4CC) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_2_MASK_REQ_1 (0x10006000+0x4D0) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_2_MASK_REQ_2 (0x10006000+0x4D4) */ +#define RG_MODULE_SW_CG_2_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_3_MASK_REQ_0 (0x10006000+0x4D8) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_3_MASK_REQ_1 (0x10006000+0x4DC) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* RG_MODULE_SW_CG_3_MASK_REQ_2 (0x10006000+0x4E0) */ +#define RG_MODULE_SW_CG_3_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_MASK_REQ_0 (0x10006000+0x4E4) */ +#define PWR_STATUS_MASK_REQ_0_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_MASK_REQ_1 (0x10006000+0x4E8) */ +#define PWR_STATUS_MASK_REQ_1_LSB (1U << 0) /* 32b */ +/* PWR_STATUS_MASK_REQ_2 (0x10006000+0x4EC) */ +#define PWR_STATUS_MASK_REQ_2_LSB (1U << 0) /* 32b */ +/* SPM_CG_CHECK_CON (0x10006000+0x4F0) */ +#define APMIXEDSYS_BUSY_MASK_REQ_0_LSB (1U << 0) /* 5b */ +#define APMIXEDSYS_BUSY_MASK_REQ_1_LSB (1U << 8) /* 5b */ +#define APMIXEDSYS_BUSY_MASK_REQ_2_LSB (1U << 16) /* 5b */ +#define AUDIOSYS_BUSY_MASK_REQ_0_LSB (1U << 24) /* 1b */ +#define AUDIOSYS_BUSY_MASK_REQ_1_LSB (1U << 25) /* 1b */ +#define AUDIOSYS_BUSY_MASK_REQ_2_LSB (1U << 26) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_0_LSB (1U << 27) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_1_LSB (1U << 28) /* 1b */ +#define SSUSB_BUSY_MASK_REQ_2_LSB (1U << 29) /* 1b */ +/* SPM_SRC_RDY_STA (0x10006000+0x4F4) */ +#define SPM_INFRA_INTERNAL_ACK_LSB (1U << 0) /* 1b */ +#define SPM_VRF18_INTERNAL_ACK_LSB (1U << 1) /* 1b */ +/* SPM_DVS_DFS_LEVEL (0x10006000+0x4F8) */ +#define SPM_DFS_LEVEL_LSB (1U << 0) /* 16b */ +#define SPM_DVS_LEVEL_LSB (1U << 16) /* 16b */ +/* SPM_FORCE_DVFS (0x10006000+0x4FC) */ +#define FORCE_DVFS_LEVEL_LSB (1U << 0) /* 32b */ +/* SRCLKEN_RC_CFG (0x10006000+0x500) */ +#define SRCLKEN_RC_CFG_LSB (1U << 0) /* 32b */ +/* RC_CENTRAL_CFG1 (0x10006000+0x504) */ +#define RC_CENTRAL_CFG1_LSB (1U << 0) /* 32b */ +/* RC_CENTRAL_CFG2 (0x10006000+0x508) */ +#define RC_CENTRAL_CFG2_LSB (1U << 0) /* 32b */ +/* RC_CMD_ARB_CFG (0x10006000+0x50C) */ +#define RC_CMD_ARB_CFG_LSB (1U << 0) /* 32b */ +/* RC_PMIC_RCEN_ADDR (0x10006000+0x510) */ +#define RC_PMIC_RCEN_ADDR_LSB (1U << 0) /* 16b */ +#define RC_PMIC_RCEN_RESERVE_LSB (1U << 16) /* 16b */ +/* RC_PMIC_RCEN_SET_CLR_ADDR (0x10006000+0x514) */ +#define RC_PMIC_RCEN_SET_ADDR_LSB (1U << 0) /* 16b */ +#define RC_PMIC_RCEN_CLR_ADDR_LSB (1U << 16) /* 16b */ +/* RC_DCXO_FPM_CFG (0x10006000+0x518) */ +#define RC_DCXO_FPM_CFG_LSB (1U << 0) /* 32b */ +/* RC_CENTRAL_CFG3 (0x10006000+0x51C) */ +#define RC_CENTRAL_CFG3_LSB (1U << 0) /* 32b */ +/* RC_M00_SRCLKEN_CFG (0x10006000+0x520) */ +#define RC_M00_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +#define RC_SW_SRCLKEN_RC (1U << 3) /* 1b */ +#define RC_SW_SRCLKEN_FPM (1U << 4) /* 1b */ +/* RC_M01_SRCLKEN_CFG (0x10006000+0x524) */ +#define RC_M01_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M02_SRCLKEN_CFG (0x10006000+0x528) */ +#define RC_M02_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M03_SRCLKEN_CFG (0x10006000+0x52C) */ +#define RC_M03_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M04_SRCLKEN_CFG (0x10006000+0x530) */ +#define RC_M04_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M05_SRCLKEN_CFG (0x10006000+0x534) */ +#define RC_M05_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M06_SRCLKEN_CFG (0x10006000+0x538) */ +#define RC_M06_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M07_SRCLKEN_CFG (0x10006000+0x53C) */ +#define RC_M07_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M08_SRCLKEN_CFG (0x10006000+0x540) */ +#define RC_M08_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M09_SRCLKEN_CFG (0x10006000+0x544) */ +#define RC_M09_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M10_SRCLKEN_CFG (0x10006000+0x548) */ +#define RC_M10_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M11_SRCLKEN_CFG (0x10006000+0x54C) */ +#define RC_M11_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_M12_SRCLKEN_CFG (0x10006000+0x550) */ +#define RC_M12_SRCLKEN_CFG_LSB (1U << 0) /* 32b */ +/* RC_SRCLKEN_SW_CON_CFG (0x10006000+0x554) */ +#define RC_SRCLKEN_SW_CON_CFG_LSB (1U << 0) /* 32b */ +/* RC_CENTRAL_CFG4 (0x10006000+0x558) */ +#define RC_CENTRAL_CFG4_LSB (1U << 0) /* 32b */ +/* RC_PROTOCOL_CHK_CFG (0x10006000+0x560) */ +#define RC_PROTOCOL_CHK_CFG_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_CFG (0x10006000+0x564) */ +#define RC_DEBUG_CFG_LSB (1U << 0) /* 32b */ +/* RC_MISC_0 (0x10006000+0x5B4) */ +#define SRCCLKENO_LSB (1U << 0) /* 2b */ +#define PCM_SRCCLKENO_LSB (1U << 3) /* 2b */ +#define RC_VREQ_LSB (1U << 5) /* 1b */ +#define RC_SPM_SRCCLKENO_0_ACK_LSB (1U << 6) /* 1b */ +/* RC_SPM_CTRL (0x10006000+0x448) */ +#define SPM_AP_26M_RDY_LSB (1U << 0) /* 1b */ +#define KEEP_RC_SPI_ACTIVE_LSB (1U << 1) /* 1b */ +#define SPM2RC_DMY_CTRL_LSB (1U << 2) /* 6b */ +/* SUBSYS_INTF_CFG (0x10006000+0x5BC) */ +#define SRCLKEN_FPM_MASK_B_LSB (1U << 0) /* 13b */ +#define SRCLKEN_BBLPM_MASK_B_LSB (1U << 16) /* 13b */ +/* PCM_WDT_LATCH_25 (0x10006000+0x5C0) */ +#define PCM_WDT_LATCH_25_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_26 (0x10006000+0x5C4) */ +#define PCM_WDT_LATCH_26_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_27 (0x10006000+0x5C8) */ +#define PCM_WDT_LATCH_27_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_28 (0x10006000+0x5CC) */ +#define PCM_WDT_LATCH_28_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_29 (0x10006000+0x5D0) */ +#define PCM_WDT_LATCH_29_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_30 (0x10006000+0x5D4) */ +#define PCM_WDT_LATCH_30_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_31 (0x10006000+0x5D8) */ +#define PCM_WDT_LATCH_31_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_32 (0x10006000+0x5DC) */ +#define PCM_WDT_LATCH_32_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_33 (0x10006000+0x5E0) */ +#define PCM_WDT_LATCH_33_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_34 (0x10006000+0x5E4) */ +#define PCM_WDT_LATCH_34_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_35 (0x10006000+0x5EC) */ +#define PCM_WDT_LATCH_35_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_36 (0x10006000+0x5F0) */ +#define PCM_WDT_LATCH_36_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_37 (0x10006000+0x5F4) */ +#define PCM_WDT_LATCH_37_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_38 (0x10006000+0x5F8) */ +#define PCM_WDT_LATCH_38_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_39 (0x10006000+0x5FC) */ +#define PCM_WDT_LATCH_39_LSB (1U << 0) /* 32b */ +/* SPM_SW_FLAG_0 (0x10006000+0x600) */ +#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */ +/* SPM_SW_DEBUG_0 (0x10006000+0x604) */ +#define SPM_SW_DEBUG_0_LSB (1U << 0) /* 32b */ +/* SPM_SW_FLAG_1 (0x10006000+0x608) */ +#define SPM_SW_FLAG_1_LSB (1U << 0) /* 32b */ +/* SPM_SW_DEBUG_1 (0x10006000+0x60C) */ +#define SPM_SW_DEBUG_1_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_0 (0x10006000+0x610) */ +#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_1 (0x10006000+0x614) */ +#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_2 (0x10006000+0x618) */ +#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_3 (0x10006000+0x61C) */ +#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_4 (0x10006000+0x620) */ +#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_5 (0x10006000+0x624) */ +#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_6 (0x10006000+0x628) */ +#define SPM_SW_RSV_6_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_7 (0x10006000+0x62C) */ +#define SPM_SW_RSV_7_LSB (1U << 0) /* 32b */ +/* SPM_SW_RSV_8 (0x10006000+0x630) */ +#define SPM_SW_RSV_8_LSB (1U << 0) /* 32b */ +/* SPM_BK_WAKE_EVENT (0x10006000+0x634) */ +#define SPM_BK_WAKE_EVENT_LSB (1U << 0) /* 32b */ +/* SPM_BK_VTCXO_DUR (0x10006000+0x638) */ +#define SPM_BK_VTCXO_DUR_LSB (1U << 0) /* 32b */ +/* SPM_BK_WAKE_MISC (0x10006000+0x63C) */ +#define SPM_BK_WAKE_MISC_LSB (1U << 0) /* 32b */ +/* SPM_BK_PCM_TIMER (0x10006000+0x640) */ +#define SPM_BK_PCM_TIMER_LSB (1U << 0) /* 32b */ +/* SPM_RSV_CON_0 (0x10006000+0x650) */ +#define SPM_RSV_CON_0_LSB (1U << 0) /* 32b */ +/* SPM_RSV_CON_1 (0x10006000+0x654) */ +#define SPM_RSV_CON_1_LSB (1U << 0) /* 32b */ +/* SPM_RSV_STA_0 (0x10006000+0x658) */ +#define SPM_RSV_STA_0_LSB (1U << 0) /* 32b */ +/* SPM_RSV_STA_1 (0x10006000+0x65C) */ +#define SPM_RSV_STA_1_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON (0x10006000+0x660) */ +#define SPM_SPARE_CON_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON_SET (0x10006000+0x664) */ +#define SPM_SPARE_CON_SET_LSB (1U << 0) /* 32b */ +/* SPM_SPARE_CON_CLR (0x10006000+0x668) */ +#define SPM_SPARE_CON_CLR_LSB (1U << 0) /* 32b */ +/* SPM_CROSS_WAKE_M00_REQ (0x10006000+0x66C) */ +#define SPM_CROSS_WAKE_M00_REQ_LSB (1U << 0) /* 4b */ +#define SPM_CROSS_WAKE_M00_CHK_LSB (1U << 4) /* 4b */ +/* SPM_CROSS_WAKE_M01_REQ (0x10006000+0x670) */ +#define SPM_CROSS_WAKE_M01_REQ_LSB (1U << 0) /* 4b */ +#define SPM_CROSS_WAKE_M01_CHK_LSB (1U << 4) /* 4b */ +/* SPM_CROSS_WAKE_M02_REQ (0x10006000+0x674) */ +#define SPM_CROSS_WAKE_M02_REQ_LSB (1U << 0) /* 4b */ +#define SPM_CROSS_WAKE_M02_CHK_LSB (1U << 4) /* 4b */ +/* SPM_CROSS_WAKE_M03_REQ (0x10006000+0x678) */ +#define SPM_CROSS_WAKE_M03_REQ_LSB (1U << 0) /* 4b */ +#define SPM_CROSS_WAKE_M03_CHK_LSB (1U << 4) /* 4b */ +/* SCP_VCORE_LEVEL (0x10006000+0x67C) */ +#define SCP_VCORE_LEVEL_LSB (1U << 0) /* 16b */ +/* SC_MM_CK_SEL_CON (0x10006000+0x680) */ +#define SC_MM_CK_SEL_LSB (1U << 0) /* 4b */ +#define SC_MM_CK_SEL_EN_LSB (1U << 4) /* 1b */ +/* SPARE_ACK_MASK (0x10006000+0x684) */ +#define SPARE_ACK_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_DV_CON_0 (0x10006000+0x68C) */ +#define SPM_DV_CON_0_LSB (1U << 0) /* 32b */ +/* SPM_DV_CON_1 (0x10006000+0x690) */ +#define SPM_DV_CON_1_LSB (1U << 0) /* 32b */ +/* SPM_DV_STA (0x10006000+0x694) */ +#define SPM_DV_STA_LSB (1U << 0) /* 32b */ +/* CONN_XOWCN_DEBUG_EN (0x10006000+0x698) */ +#define CONN_XOWCN_DEBUG_EN_LSB (1U << 0) /* 1b */ +/* SPM_SEMA_M0 (0x10006000+0x69C) */ +#define SPM_SEMA_M0_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M1 (0x10006000+0x6A0) */ +#define SPM_SEMA_M1_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M2 (0x10006000+0x6A4) */ +#define SPM_SEMA_M2_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M3 (0x10006000+0x6A8) */ +#define SPM_SEMA_M3_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M4 (0x10006000+0x6AC) */ +#define SPM_SEMA_M4_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M5 (0x10006000+0x6B0) */ +#define SPM_SEMA_M5_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M6 (0x10006000+0x6B4) */ +#define SPM_SEMA_M6_LSB (1U << 0) /* 8b */ +/* SPM_SEMA_M7 (0x10006000+0x6B8) */ +#define SPM_SEMA_M7_LSB (1U << 0) /* 8b */ +/* SPM2ADSP_MAILBOX (0x10006000+0x6BC) */ +#define SPM2ADSP_MAILBOX_LSB (1U << 0) /* 32b */ +/* ADSP2SPM_MAILBOX (0x10006000+0x6C0) */ +#define ADSP2SPM_MAILBOX_LSB (1U << 0) /* 32b */ +/* SPM_ADSP_IRQ (0x10006000+0x6C4) */ +#define SC_SPM2ADSP_WAKEUP_LSB (1U << 0) /* 1b */ +#define SPM_ADSP_IRQ_SC_ADSP2SPM_WAKEUP_LSB (1U << 4) /* 1b */ +/* SPM_MD32_IRQ (0x10006000+0x6C8) */ +#define SC_SPM2SSPM_WAKEUP_LSB (1U << 0) /* 4b */ +#define SPM_MD32_IRQ_SC_SSPM2SPM_WAKEUP_LSB (1U << 4) /* 4b */ +/* SPM2PMCU_MAILBOX_0 (0x10006000+0x6CC) */ +#define SPM2PMCU_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_1 (0x10006000+0x6D0) */ +#define SPM2PMCU_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_2 (0x10006000+0x6D4) */ +#define SPM2PMCU_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* SPM2PMCU_MAILBOX_3 (0x10006000+0x6D8) */ +#define SPM2PMCU_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_0 (0x10006000+0x6DC) */ +#define PMCU2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_1 (0x10006000+0x6E0) */ +#define PMCU2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_2 (0x10006000+0x6E4) */ +#define PMCU2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */ +/* PMCU2SPM_MAILBOX_3 (0x10006000+0x6E8) */ +#define PMCU2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */ +/* UFS_PSRI_SW (0x10006000+0x6EC) */ +#define UFS_PSRI_SW_LSB (1U << 0) /* 1b */ +/* UFS_PSRI_SW_SET (0x10006000+0x6F0) */ +#define UFS_PSRI_SW_SET_LSB (1U << 0) /* 1b */ +/* UFS_PSRI_SW_CLR (0x10006000+0x6F4) */ +#define UFS_PSRI_SW_CLR_LSB (1U << 0) /* 1b */ +/* SPM_AP_SEMA (0x10006000+0x6F8) */ +#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */ +/* SPM_SPM_SEMA (0x10006000+0x6FC) */ +#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */ +/* SPM_DVFS_CON (0x10006000+0x700) */ +#define SPM_DVFS_CON_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CON_STA (0x10006000+0x704) */ +#define SPM_DVFS_CON_STA_LSB (1U << 0) /* 32b */ +/* SPM_PMIC_SPMI_CON (0x10006000+0x708) */ +#define SPM_PMIC_SPMI_CMD_LSB (1U << 0) /* 2b */ +#define SPM_PMIC_SPMI_SLAVEID_LSB (1U << 2) /* 4b */ +#define SPM_PMIC_SPMI_PMIFID_LSB (1U << 6) /* 1b */ +#define SPM_PMIC_SPMI_DBCNT_LSB (1U << 7) /* 1b */ +/* SPM_DVFS_CMD0 (0x10006000+0x710) */ +#define SPM_DVFS_CMD0_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD1 (0x10006000+0x714) */ +#define SPM_DVFS_CMD1_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD2 (0x10006000+0x718) */ +#define SPM_DVFS_CMD2_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD3 (0x10006000+0x71C) */ +#define SPM_DVFS_CMD3_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD4 (0x10006000+0x720) */ +#define SPM_DVFS_CMD4_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD5 (0x10006000+0x724) */ +#define SPM_DVFS_CMD5_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD6 (0x10006000+0x728) */ +#define SPM_DVFS_CMD6_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD7 (0x10006000+0x72C) */ +#define SPM_DVFS_CMD7_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD8 (0x10006000+0x730) */ +#define SPM_DVFS_CMD8_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD9 (0x10006000+0x734) */ +#define SPM_DVFS_CMD9_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD10 (0x10006000+0x738) */ +#define SPM_DVFS_CMD10_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD11 (0x10006000+0x73C) */ +#define SPM_DVFS_CMD11_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD12 (0x10006000+0x740) */ +#define SPM_DVFS_CMD12_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD13 (0x10006000+0x744) */ +#define SPM_DVFS_CMD13_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD14 (0x10006000+0x748) */ +#define SPM_DVFS_CMD14_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD15 (0x10006000+0x74C) */ +#define SPM_DVFS_CMD15_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD16 (0x10006000+0x750) */ +#define SPM_DVFS_CMD16_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD17 (0x10006000+0x754) */ +#define SPM_DVFS_CMD17_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD18 (0x10006000+0x758) */ +#define SPM_DVFS_CMD18_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD19 (0x10006000+0x75C) */ +#define SPM_DVFS_CMD19_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD20 (0x10006000+0x760) */ +#define SPM_DVFS_CMD20_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD21 (0x10006000+0x764) */ +#define SPM_DVFS_CMD21_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD22 (0x10006000+0x768) */ +#define SPM_DVFS_CMD22_LSB (1U << 0) /* 32b */ +/* SPM_DVFS_CMD23 (0x10006000+0x76C) */ +#define SPM_DVFS_CMD23_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_VALUE_L (0x10006000+0x770) */ +#define SYS_TIMER_VALUE_L_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_VALUE_H (0x10006000+0x774) */ +#define SYS_TIMER_VALUE_H_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_START_L (0x10006000+0x778) */ +#define SYS_TIMER_START_L_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_START_H (0x10006000+0x77C) */ +#define SYS_TIMER_START_H_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_00 (0x10006000+0x780) */ +#define SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_00 (0x10006000+0x784) */ +#define SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_01 (0x10006000+0x788) */ +#define SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_01 (0x10006000+0x78C) */ +#define SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_02 (0x10006000+0x790) */ +#define SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_02 (0x10006000+0x794) */ +#define SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_03 (0x10006000+0x798) */ +#define SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_03 (0x10006000+0x79C) */ +#define SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_04 (0x10006000+0x7A0) */ +#define SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_04 (0x10006000+0x7A4) */ +#define SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_05 (0x10006000+0x7A8) */ +#define SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_05 (0x10006000+0x7AC) */ +#define SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_06 (0x10006000+0x7B0) */ +#define SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_06 (0x10006000+0x7B4) */ +#define SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_07 (0x10006000+0x7B8) */ +#define SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_07 (0x10006000+0x7BC) */ +#define SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_08 (0x10006000+0x7C0) */ +#define SYS_TIMER_LATCH_L_08_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_08 (0x10006000+0x7C4) */ +#define SYS_TIMER_LATCH_H_08_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_09 (0x10006000+0x7C8) */ +#define SYS_TIMER_LATCH_L_09_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_09 (0x10006000+0x7CC) */ +#define SYS_TIMER_LATCH_H_09_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_10 (0x10006000+0x7D0) */ +#define SYS_TIMER_LATCH_L_10_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_10 (0x10006000+0x7D4) */ +#define SYS_TIMER_LATCH_H_10_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_11 (0x10006000+0x7D8) */ +#define SYS_TIMER_LATCH_L_11_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_11 (0x10006000+0x7DC) */ +#define SYS_TIMER_LATCH_H_11_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_12 (0x10006000+0x7E0) */ +#define SYS_TIMER_LATCH_L_12_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_12 (0x10006000+0x7E4) */ +#define SYS_TIMER_LATCH_H_12_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_13 (0x10006000+0x7E8) */ +#define SYS_TIMER_LATCH_L_13_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_13 (0x10006000+0x7EC) */ +#define SYS_TIMER_LATCH_H_13_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_14 (0x10006000+0x7F0) */ +#define SYS_TIMER_LATCH_L_14_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_14 (0x10006000+0x7F4) */ +#define SYS_TIMER_LATCH_H_14_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_L_15 (0x10006000+0x7F8) */ +#define SYS_TIMER_LATCH_L_15_LSB (1U << 0) /* 32b */ +/* SYS_TIMER_LATCH_H_15 (0x10006000+0x7FC) */ +#define SYS_TIMER_LATCH_H_15_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_0 (0x10006000+0x800) */ +#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_1 (0x10006000+0x804) */ +#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_2 (0x10006000+0x808) */ +#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_3 (0x10006000+0x80C) */ +#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_4 (0x10006000+0x810) */ +#define PCM_WDT_LATCH_4_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_5 (0x10006000+0x814) */ +#define PCM_WDT_LATCH_5_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_6 (0x10006000+0x818) */ +#define PCM_WDT_LATCH_6_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_7 (0x10006000+0x81C) */ +#define PCM_WDT_LATCH_7_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_8 (0x10006000+0x820) */ +#define PCM_WDT_LATCH_8_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_9 (0x10006000+0x824) */ +#define PCM_WDT_LATCH_9_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_10 (0x10006000+0x828) */ +#define PCM_WDT_LATCH_10_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_11 (0x10006000+0x82C) */ +#define PCM_WDT_LATCH_11_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_12 (0x10006000+0x830) */ +#define PCM_WDT_LATCH_12_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_13 (0x10006000+0x834) */ +#define PCM_WDT_LATCH_13_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_14 (0x10006000+0x838) */ +#define PCM_WDT_LATCH_14_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_15 (0x10006000+0x83C) */ +#define PCM_WDT_LATCH_15_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_16 (0x10006000+0x840) */ +#define PCM_WDT_LATCH_16_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_17 (0x10006000+0x844) */ +#define PCM_WDT_LATCH_17_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_18 (0x10006000+0x848) */ +#define PCM_WDT_LATCH_18_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_SPARE_0 (0x10006000+0x84C) */ +#define PCM_WDT_LATCH_SPARE_0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_SPARE_1 (0x10006000+0x850) */ +#define PCM_WDT_LATCH_SPARE_1_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_SPARE_2 (0x10006000+0x854) */ +#define PCM_WDT_LATCH_SPARE_2_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_CONN_0 (0x10006000+0x870) */ +#define PCM_WDT_LATCH_CONN_0_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_CONN_1 (0x10006000+0x874) */ +#define PCM_WDT_LATCH_CONN_1_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_CONN_2 (0x10006000+0x878) */ +#define PCM_WDT_LATCH_CONN_2_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_0 (0x10006000+0x8A0) */ +#define DRAMC_GATING_ERR_LATCH_CH0_0_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_1 (0x10006000+0x8A4) */ +#define DRAMC_GATING_ERR_LATCH_CH0_1_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_2 (0x10006000+0x8A8) */ +#define DRAMC_GATING_ERR_LATCH_CH0_2_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_3 (0x10006000+0x8AC) */ +#define DRAMC_GATING_ERR_LATCH_CH0_3_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_4 (0x10006000+0x8B0) */ +#define DRAMC_GATING_ERR_LATCH_CH0_4_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_5 (0x10006000+0x8B4) */ +#define DRAMC_GATING_ERR_LATCH_CH0_5_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_CH0_6 (0x10006000+0x8B8) */ +#define DRAMC_GATING_ERR_LATCH_CH0_6_LSB (1U << 0) /* 32b */ +/* DRAMC_GATING_ERR_LATCH_SPARE_0 (0x10006000+0x8F4) */ +#define DRAMC_GATING_ERR_LATCH_SPARE_0_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON_0 (0x10006000+0x900) */ +#define SPM_ACK_CHK_SW_EN_0_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_0_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_0_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_0_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_0_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_0_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_0_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_0_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_0_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_0_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_0_LSB (1U << 15) /* 1b */ +/* SPM_ACK_CHK_PC_0 (0x10006000+0x904) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_0_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_0_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL_0 (0x10006000+0x908) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_0_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_0_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_0_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_0_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER_0 (0x10006000+0x90C) */ +#define SPM_ACK_CHK_TIMER_VAL_0_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_0_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA_0 (0x10006000+0x910) */ +#define SPM_ACK_CHK_STA_0_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_SWINT_0 (0x10006000+0x914) */ +#define SPM_ACK_CHK_SWINT_EN_0_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON_1 (0x10006000+0x920) */ +#define SPM_ACK_CHK_SW_EN_1_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_1_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_1_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_1_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_1_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_1_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_1_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_1_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_1_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_1_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_1_LSB (1U << 15) /* 1b */ +/* SPM_ACK_CHK_PC_1 (0x10006000+0x924) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_1_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_1_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL_1 (0x10006000+0x928) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_1_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_1_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_1_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_1_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER_1 (0x10006000+0x92C) */ +#define SPM_ACK_CHK_TIMER_VAL_1_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_1_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA_1 (0x10006000+0x930) */ +#define SPM_ACK_CHK_STA_1_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_SWINT_1 (0x10006000+0x934) */ +#define SPM_ACK_CHK_SWINT_EN_1_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON_2 (0x10006000+0x940) */ +#define SPM_ACK_CHK_SW_EN_2_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_2_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_2_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_2_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_2_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_2_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_2_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_2_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_2_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_2_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_2_LSB (1U << 15) /* 1b */ +/* SPM_ACK_CHK_PC_2 (0x10006000+0x944) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_2_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_2_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL_2 (0x10006000+0x948) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_2_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_2_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_2_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_2_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER_2 (0x10006000+0x94C) */ +#define SPM_ACK_CHK_TIMER_VAL_2_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_2_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA_2 (0x10006000+0x950) */ +#define SPM_ACK_CHK_STA_2_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_SWINT_2 (0x10006000+0x954) */ +#define SPM_ACK_CHK_SWINT_EN_2_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_CON_3 (0x10006000+0x960) */ +#define SPM_ACK_CHK_SW_EN_3_LSB (1U << 0) /* 1b */ +#define SPM_ACK_CHK_CLR_ALL_3_LSB (1U << 1) /* 1b */ +#define SPM_ACK_CHK_CLR_TIMER_3_LSB (1U << 2) /* 1b */ +#define SPM_ACK_CHK_CLR_IRQ_3_LSB (1U << 3) /* 1b */ +#define SPM_ACK_CHK_STA_EN_3_LSB (1U << 4) /* 1b */ +#define SPM_ACK_CHK_WAKEUP_EN_3_LSB (1U << 5) /* 1b */ +#define SPM_ACK_CHK_WDT_EN_3_LSB (1U << 6) /* 1b */ +#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_3_LSB (1U << 7) /* 1b */ +#define SPM_ACK_CHK_HW_EN_3_LSB (1U << 8) /* 1b */ +#define SPM_ACK_CHK_HW_MODE_3_LSB (1U << 9) /* 3b */ +#define SPM_ACK_CHK_FAIL_3_LSB (1U << 15) /* 1b */ +/* SPM_ACK_CHK_PC_3 (0x10006000+0x964) */ +#define SPM_ACK_CHK_HW_TRIG_PC_VAL_3_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_HW_TARG_PC_VAL_3_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_SEL_3 (0x10006000+0x968) */ +#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_3_LSB (1U << 0) /* 5b */ +#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_3_LSB (1U << 5) /* 3b */ +#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_3_LSB (1U << 16) /* 5b */ +#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_3_LSB (1U << 21) /* 3b */ +/* SPM_ACK_CHK_TIMER_3 (0x10006000+0x96C) */ +#define SPM_ACK_CHK_TIMER_VAL_3_LSB (1U << 0) /* 16b */ +#define SPM_ACK_CHK_TIMER_3_LSB (1U << 16) /* 16b */ +/* SPM_ACK_CHK_STA_3 (0x10006000+0x970) */ +#define SPM_ACK_CHK_STA_3_LSB (1U << 0) /* 32b */ +/* SPM_ACK_CHK_SWINT_3 (0x10006000+0x974) */ +#define SPM_ACK_CHK_SWINT_EN_3_LSB (1U << 0) /* 32b */ +/* SPM_COUNTER_0 (0x10006000+0x978) */ +#define SPM_COUNTER_VAL_0_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_0_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_0_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_0_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_0_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_0_LSB (1U << 31) /* 1b */ +/* SPM_COUNTER_1 (0x10006000+0x97C) */ +#define SPM_COUNTER_VAL_1_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_1_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_1_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_1_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_1_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_1_LSB (1U << 31) /* 1b */ +/* SPM_COUNTER_2 (0x10006000+0x980) */ +#define SPM_COUNTER_VAL_2_LSB (1U << 0) /* 14b */ +#define SPM_COUNTER_OUT_2_LSB (1U << 14) /* 14b */ +#define SPM_COUNTER_EN_2_LSB (1U << 28) /* 1b */ +#define SPM_COUNTER_CLR_2_LSB (1U << 29) /* 1b */ +#define SPM_COUNTER_TIMEOUT_2_LSB (1U << 30) /* 1b */ +#define SPM_COUNTER_WAKEUP_EN_2_LSB (1U << 31) /* 1b */ +/* SYS_TIMER_CON (0x10006000+0x98C) */ +#define SYS_TIMER_START_EN_LSB (1U << 0) /* 1b */ +#define SYS_TIMER_LATCH_EN_LSB (1U << 1) /* 1b */ +#define SYS_TIMER_ID_LSB (1U << 8) /* 8b */ +#define SYS_TIMER_VALID_LSB (1U << 31) /* 1b */ +/* RC_FSM_STA_0 (0x10006000+0xE00) */ +#define RC_FSM_STA_0_LSB (1U << 0) /* 32b */ +/* RC_CMD_STA_0 (0x10006000+0xE04) */ +#define RC_CMD_STA_0_LSB (1U << 0) /* 32b */ +/* RC_CMD_STA_1 (0x10006000+0xE08) */ +#define RC_CMD_STA_1_LSB (1U << 0) /* 32b */ +/* RC_SPI_STA_0 (0x10006000+0xE0C) */ +#define RC_SPI_STA_0_LSB (1U << 0) /* 32b */ +/* RC_PI_PO_STA_0 (0x10006000+0xE10) */ +#define RC_PI_PO_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M00_REQ_STA_0 (0x10006000+0xE14) */ +#define RC_M00_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M01_REQ_STA_0 (0x10006000+0xE1C) */ +#define RC_M01_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M02_REQ_STA_0 (0x10006000+0xE20) */ +#define RC_M02_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M03_REQ_STA_0 (0x10006000+0xE24) */ +#define RC_M03_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M04_REQ_STA_0 (0x10006000+0xE28) */ +#define RC_M04_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M05_REQ_STA_0 (0x10006000+0xE2C) */ +#define RC_M05_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M06_REQ_STA_0 (0x10006000+0xE30) */ +#define RC_M06_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M07_REQ_STA_0 (0x10006000+0xE34) */ +#define RC_M07_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M08_REQ_STA_0 (0x10006000+0xE38) */ +#define RC_M08_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M09_REQ_STA_0 (0x10006000+0xE3C) */ +#define RC_M09_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M10_REQ_STA_0 (0x10006000+0xE40) */ +#define RC_M10_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M11_REQ_STA_0 (0x10006000+0xE44) */ +#define RC_M11_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_M12_REQ_STA_0 (0x10006000+0xE48) */ +#define RC_M12_REQ_STA_0_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_STA_0 (0x10006000+0xE4C) */ +#define RC_DEBUG_STA_0_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_0_LSB (0x10006000+0xE50) */ +#define RO_PMRC_TRACE_00_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_0_MSB (0x10006000+0xE54) */ +#define RO_PMRC_TRACE_00_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_1_LSB (0x10006000+0xE5C) */ +#define RO_PMRC_TRACE_01_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_1_MSB (0x10006000+0xE60) */ +#define RO_PMRC_TRACE_01_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_2_LSB (0x10006000+0xE64) */ +#define RO_PMRC_TRACE_02_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_2_MSB (0x10006000+0xE6C) */ +#define RO_PMRC_TRACE_02_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_3_LSB (0x10006000+0xE70) */ +#define RO_PMRC_TRACE_03_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_3_MSB (0x10006000+0xE74) */ +#define RO_PMRC_TRACE_03_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_4_LSB (0x10006000+0xE78) */ +#define RO_PMRC_TRACE_04_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_4_MSB (0x10006000+0xE7C) */ +#define RO_PMRC_TRACE_04_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_5_LSB (0x10006000+0xE80) */ +#define RO_PMRC_TRACE_05_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_5_MSB (0x10006000+0xE84) */ +#define RO_PMRC_TRACE_05_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_6_LSB (0x10006000+0xE88) */ +#define RO_PMRC_TRACE_06_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_6_MSB (0x10006000+0xE8C) */ +#define RO_PMRC_TRACE_06_MSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_7_LSB (0x10006000+0xE90) */ +#define RO_PMRC_TRACE_07_LSB_LSB (1U << 0) /* 32b */ +/* RC_DEBUG_TRACE_7_MSB (0x10006000+0xE94) */ +#define RO_PMRC_TRACE_07_MSB_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_0_LSB (0x10006000+0xE98) */ +#define RC_SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_0_MSB (0x10006000+0xE9C) */ +#define RC_SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_1_LSB (0x10006000+0xEA0) */ +#define RC_SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_1_MSB (0x10006000+0xEA4) */ +#define RC_SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_2_LSB (0x10006000+0xEA8) */ +#define RC_SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_2_MSB (0x10006000+0xEAC) */ +#define RC_SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_3_LSB (0x10006000+0xEB0) */ +#define RC_SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_3_MSB (0x10006000+0xEB4) */ +#define RC_SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_4_LSB (0x10006000+0xEB8) */ +#define RC_SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_4_MSB (0x10006000+0xEBC) */ +#define RC_SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_5_LSB (0x10006000+0xEC0) */ +#define RC_SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_5_MSB (0x10006000+0xEC4) */ +#define RC_SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_6_LSB (0x10006000+0xEC8) */ +#define RC_SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_6_MSB (0x10006000+0xECC) */ +#define RC_SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_7_LSB (0x10006000+0xED0) */ +#define RC_SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */ +/* RC_SYS_TIMER_LATCH_7_MSB (0x10006000+0xED4) */ +#define RC_SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_19 (0x10006000+0xED8) */ +#define PCM_WDT_LATCH_19_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_20 (0x10006000+0xEDC) */ +#define PCM_WDT_LATCH_20_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_21 (0x10006000+0xEE0) */ +#define PCM_WDT_LATCH_21_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_22 (0x10006000+0xEE4) */ +#define PCM_WDT_LATCH_22_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_23 (0x10006000+0xEE8) */ +#define PCM_WDT_LATCH_23_LSB (1U << 0) /* 32b */ +/* PCM_WDT_LATCH_24 (0x10006000+0xEEC) */ +#define PCM_WDT_LATCH_24_LSB (1U << 0) /* 32b */ +/* PMSR_LAST_DAT (0x10006000+0xF00) */ +#define PMSR_LAST_DAT_LSB (1U << 0) /* 32b */ +/* PMSR_LAST_CNT (0x10006000+0xF04) */ +#define PMSR_LAST_CMD_LSB (1U << 0) /* 30b */ +#define PMSR_LAST_REQ_LSB (1U << 30) /* 1b */ +/* PMSR_LAST_ACK (0x10006000+0xF08) */ +#define PMSR_LAST_ACK_LSB (1U << 0) /* 1b */ +/* SPM_PMSR_SEL_CON0 (0x10006000+0xF10) */ +#define REG_PMSR_SIG_SEL_0_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_1_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_2_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_3_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON1 (0x10006000+0xF14) */ +#define REG_PMSR_SIG_SEL_4_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_5_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_6_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_7_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON2 (0x10006000+0xF18) */ +#define REG_PMSR_SIG_SEL_8_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_9_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_10_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_11_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON3 (0x10006000+0xF1C) */ +#define REG_PMSR_SIG_SEL_12_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_13_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_14_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_15_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON4 (0x10006000+0xF20) */ +#define REG_PMSR_SIG_SEL_16_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_17_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_18_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_19_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON5 (0x10006000+0xF24) */ +#define REG_PMSR_SIG_SEL_20_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_21_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_22_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_23_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON6 (0x10006000+0xF28) */ +#define REG_PMSR_SIG_SEL_24_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_25_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_26_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_27_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON7 (0x10006000+0xF2C) */ +#define REG_PMSR_SIG_SEL_28_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_29_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_30_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_31_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON8 (0x10006000+0xF30) */ +#define REG_PMSR_SIG_SEL_32_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_33_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_34_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_35_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON9 (0x10006000+0xF34) */ +#define REG_PMSR_SIG_SEL_36_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_37_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_38_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_39_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON10 (0x10006000+0xF3C) */ +#define REG_PMSR_SIG_SEL_40_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_41_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_42_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_43_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_SEL_CON11 (0x10006000+0xF40) */ +#define REG_PMSR_SIG_SEL_44_LSB (1U << 0) /* 8b */ +#define REG_PMSR_SIG_SEL_45_LSB (1U << 8) /* 8b */ +#define REG_PMSR_SIG_SEL_46_LSB (1U << 16) /* 8b */ +#define REG_PMSR_SIG_SEL_47_LSB (1U << 24) /* 8b */ +/* SPM_PMSR_TIEMR_STA0 (0x10006000+0xFB8) */ +#define PMSR_TIMER_SET0_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_TIEMR_STA1 (0x10006000+0xFBC) */ +#define PMSR_TIMER_SET1_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_TIEMR_STA2 (0x10006000+0xFC0) */ +#define PMSR_TIMER_SET2_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON0 (0x10006000+0xFC4) */ +#define PMSR_ENABLE_SET0_LSB (1U << 0) /* 1b */ +#define PMSR_ENABLE_SET1_LSB (1U << 1) /* 1b */ +#define PMSR_ENABLE_SET2_LSB (1U << 2) /* 1b */ +#define PMSR_IRQ_CLR_SET0_LSB (1U << 3) /* 1b */ +#define PMSR_IRQ_CLR_SET1_LSB (1U << 4) /* 1b */ +#define PMSR_IRQ_CLR_SET2_LSB (1U << 5) /* 1b */ +#define PMSR_SPEED_MODE_EN_SET0_LSB (1U << 6) /* 1b */ +#define PMSR_SPEED_MODE_EN_SET1_LSB (1U << 7) /* 1b */ +#define PMSR_SPEED_MODE_EN_SET2_LSB (1U << 8) /* 1b */ +#define PMSR_EVENT_CLR_SET0_LSB (1U << 9) /* 1b */ +#define PMSR_EVENT_CLR_SET1_LSB (1U << 10) /* 1b */ +#define PMSR_EVENT_CLR_SET2_LSB (1U << 11) /* 1b */ +#define REG_PMSR_IRQ_MASK_SET0_LSB (1U << 12) /* 1b */ +#define REG_PMSR_IRQ_MASK_SET1_LSB (1U << 13) /* 1b */ +#define REG_PMSR_IRQ_MASK_SET2_LSB (1U << 14) /* 1b */ +#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET0_LSB (1U << 15) /* 1b */ +#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET1_LSB (1U << 16) /* 1b */ +#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET2_LSB (1U << 17) /* 1b */ +#define PMSR_GEN_SW_RST_EN_LSB (1U << 18) /* 1b */ +#define PMSR_MODULE_ENABLE_LSB (1U << 19) /* 1b */ +#define PMSR_MODE_LSB (1U << 20) /* 2b */ +#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET0_LSB (1U << 29) /* 1b */ +#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET1_LSB (1U << 30) /* 1b */ +#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET2_LSB (1U << 31) /* 1b */ +/* SPM_PMSR_GENERAL_CON1 (0x10006000+0xFC8) */ +#define PMSR_COUNTER_THRES_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON2 (0x10006000+0xFCC) */ +#define PMSR_DEBUG_IN_0_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON3 (0x10006000+0xFD0) */ +#define PMSR_DEBUG_IN_1_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON4 (0x10006000+0xFD4) */ +#define PMSR_DEBUG_IN_2_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_GENERAL_CON5 (0x10006000+0xFD8) */ +#define PMSR_DEBUG_IN_3_MASK_B_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_SW_RESET (0x10006000+0xFDC) */ +#define PMSR_SW_RST_EN_SET0_LSB (1U << 0) /* 1b */ +#define PMSR_SW_RST_EN_SET1_LSB (1U << 1) /* 1b */ +#define PMSR_SW_RST_EN_SET2_LSB (1U << 2) /* 1b */ +/* SPM_PMSR_MON_CON0 (0x10006000+0xFE0) */ +#define REG_PMSR_MON_TYPE_0_LSB (1U << 0) /* 2b */ +#define REG_PMSR_MON_TYPE_1_LSB (1U << 2) /* 2b */ +#define REG_PMSR_MON_TYPE_2_LSB (1U << 4) /* 2b */ +#define REG_PMSR_MON_TYPE_3_LSB (1U << 6) /* 2b */ +#define REG_PMSR_MON_TYPE_4_LSB (1U << 8) /* 2b */ +#define REG_PMSR_MON_TYPE_5_LSB (1U << 10) /* 2b */ +#define REG_PMSR_MON_TYPE_6_LSB (1U << 12) /* 2b */ +#define REG_PMSR_MON_TYPE_7_LSB (1U << 14) /* 2b */ +#define REG_PMSR_MON_TYPE_8_LSB (1U << 16) /* 2b */ +#define REG_PMSR_MON_TYPE_9_LSB (1U << 18) /* 2b */ +#define REG_PMSR_MON_TYPE_10_LSB (1U << 20) /* 2b */ +#define REG_PMSR_MON_TYPE_11_LSB (1U << 22) /* 2b */ +#define REG_PMSR_MON_TYPE_12_LSB (1U << 24) /* 2b */ +#define REG_PMSR_MON_TYPE_13_LSB (1U << 26) /* 2b */ +#define REG_PMSR_MON_TYPE_14_LSB (1U << 28) /* 2b */ +#define REG_PMSR_MON_TYPE_15_LSB (1U << 30) /* 2b */ +/* SPM_PMSR_MON_CON1 (0x10006000+0xFE4) */ +#define REG_PMSR_MON_TYPE_16_LSB (1U << 0) /* 2b */ +#define REG_PMSR_MON_TYPE_17_LSB (1U << 2) /* 2b */ +#define REG_PMSR_MON_TYPE_18_LSB (1U << 4) /* 2b */ +#define REG_PMSR_MON_TYPE_19_LSB (1U << 6) /* 2b */ +#define REG_PMSR_MON_TYPE_20_LSB (1U << 8) /* 2b */ +#define REG_PMSR_MON_TYPE_21_LSB (1U << 10) /* 2b */ +#define REG_PMSR_MON_TYPE_22_LSB (1U << 12) /* 2b */ +#define REG_PMSR_MON_TYPE_23_LSB (1U << 14) /* 2b */ +#define REG_PMSR_MON_TYPE_24_LSB (1U << 16) /* 2b */ +#define REG_PMSR_MON_TYPE_25_LSB (1U << 18) /* 2b */ +#define REG_PMSR_MON_TYPE_26_LSB (1U << 20) /* 2b */ +#define REG_PMSR_MON_TYPE_27_LSB (1U << 22) /* 2b */ +#define REG_PMSR_MON_TYPE_28_LSB (1U << 24) /* 2b */ +#define REG_PMSR_MON_TYPE_29_LSB (1U << 26) /* 2b */ +#define REG_PMSR_MON_TYPE_30_LSB (1U << 28) /* 2b */ +#define REG_PMSR_MON_TYPE_31_LSB (1U << 30) /* 2b */ +/* SPM_PMSR_MON_CON2 (0x10006000+0xFE8) */ +#define REG_PMSR_MON_TYPE_32_LSB (1U << 0) /* 2b */ +#define REG_PMSR_MON_TYPE_33_LSB (1U << 2) /* 2b */ +#define REG_PMSR_MON_TYPE_34_LSB (1U << 4) /* 2b */ +#define REG_PMSR_MON_TYPE_35_LSB (1U << 6) /* 2b */ +#define REG_PMSR_MON_TYPE_36_LSB (1U << 8) /* 2b */ +#define REG_PMSR_MON_TYPE_37_LSB (1U << 10) /* 2b */ +#define REG_PMSR_MON_TYPE_38_LSB (1U << 12) /* 2b */ +#define REG_PMSR_MON_TYPE_39_LSB (1U << 14) /* 2b */ +#define REG_PMSR_MON_TYPE_40_LSB (1U << 16) /* 2b */ +#define REG_PMSR_MON_TYPE_41_LSB (1U << 18) /* 2b */ +#define REG_PMSR_MON_TYPE_42_LSB (1U << 20) /* 2b */ +#define REG_PMSR_MON_TYPE_43_LSB (1U << 22) /* 2b */ +#define REG_PMSR_MON_TYPE_44_LSB (1U << 24) /* 2b */ +#define REG_PMSR_MON_TYPE_45_LSB (1U << 26) /* 2b */ +#define REG_PMSR_MON_TYPE_46_LSB (1U << 28) /* 2b */ +#define REG_PMSR_MON_TYPE_47_LSB (1U << 30) /* 2b */ +/* SPM_PMSR_LEN_CON0 (0x10006000+0xFEC) */ +#define REG_PMSR_WINDOW_LEN_SET0_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_LEN_CON1 (0x10006000+0xFF0) */ +#define REG_PMSR_WINDOW_LEN_SET1_LSB (1U << 0) /* 32b */ +/* SPM_PMSR_LEN_CON2 (0x10006000+0xFF4) */ +#define REG_PMSR_WINDOW_LEN_SET2_LSB (1U << 0) /* 32b */ + +#define SPM_PROJECT_CODE 0xb16 +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) +#endif diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h new file mode 100644 index 0000000..26250ba --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_RESOURCE_REQ_H +#define MT_SPM_RESOURCE_REQ_H + +/* SPM resource request internal bit */ +#define MT_SPM_BIT_XO_FPM 0 +#define MT_SPM_BIT_26M 1 +#define MT_SPM_BIT_INFRA 2 +#define MT_SPM_BIT_SYSPLL 3 +#define MT_SPM_BIT_DRAM_S0 4 +#define MT_SPM_BIT_DRAM_S1 5 + +/* SPM resource request internal bit_mask */ +#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM) +#define MT_SPM_26M BIT(MT_SPM_BIT_26M) +#define MT_SPM_INFRA BIT(MT_SPM_BIT_INFRA) +#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL) +#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0) +#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1) +#endif /* MT_SPM_RESOURCE_REQ_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c new file mode 100644 index 0000000..d018953 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPM_SUSPEND_SLEEP_PCM_FLAG \ + (SPM_FLAG_DISABLE_INFRA_PDN | \ + SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \ + SPM_FLAG_SRAM_SLEEP_CTRL) + +#define SPM_SUSPEND_SLEEP_PCM_FLAG1 0 + +#define SPM_SUSPEND_PCM_FLAG \ + (SPM_FLAG_DISABLE_VCORE_DVS | \ + SPM_FLAG_DISABLE_VCORE_DFS | \ + SPM_FLAG_ENABLE_TIA_WORKAROUND | \ + SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \ + SPM_FLAG_SRAM_SLEEP_CTRL) + +#define SPM_SUSPEND_PCM_FLAG1 0 + +/* Suspend spm power control */ +#define __WAKE_SRC_FOR_SUSPEND_COMMON__ \ + (R12_PCM_TIMER | \ + R12_KP_IRQ_B | \ + R12_APWDT_EVENT_B | \ + R12_CONN2AP_SPM_WAKEUP_B | \ + R12_EINT_EVENT_B | \ + R12_CONN_WDT_IRQ_B | \ + R12_CCIF0_EVENT_B | \ + R12_SSPM2SPM_WAKEUP_B | \ + R12_SCP2SPM_WAKEUP_B | \ + R12_USBX_CDSC_B | \ + R12_USBX_POWERDWN_B | \ + R12_SYS_TIMER_EVENT_B | \ + R12_EINT_EVENT_SECURE_B | \ + R12_SYS_CIRQ_IRQ_B | \ + R12_MD2AP_PEER_EVENT_B | \ + R12_MD1_WDT_B | \ + R12_CLDMA_EVENT_B | \ + R12_REG_CPU_WAKEUP | \ + R12_APUSYS_WAKE_HOST_B) + +#if defined(CFG_MICROTRUST_TEE_SUPPORT) +#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__) +#else +#define WAKE_SRC_FOR_SUSPEND \ + (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \ + R12_SEJ_EVENT_B) +#endif + +static struct pwr_ctrl suspend_ctrl = { + .wake_src = WAKE_SRC_FOR_SUSPEND, + + /* SPM_AP_STANDBY_CON */ + /* [0] */ + .reg_wfi_op = 0, + /* [1] */ + .reg_wfi_type = 0, + /* [2] */ + .reg_mp0_cputop_idle_mask = 0, + /* [3] */ + .reg_mp1_cputop_idle_mask = 0, + /* [4] */ + .reg_mcusys_idle_mask = 0, + /* [25] */ + .reg_md_apsrc_1_sel = 0, + /* [26] */ + .reg_md_apsrc_0_sel = 0, + /* [29] */ + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC_REQ */ + /* [0] */ + .reg_spm_apsrc_req = 0, + /* [1] */ + .reg_spm_f26m_req = 0, + /* [3] */ + .reg_spm_infra_req = 0, + /* [4] */ + .reg_spm_vrf18_req = 0, + /* [7] FIXME: default disable HW Auto S1*/ + .reg_spm_ddr_en_req = 1, + /* [8] */ + .reg_spm_dvfs_req = 0, + /* [9] */ + .reg_spm_sw_mailbox_req = 0, + /* [10] */ + .reg_spm_sspm_mailbox_req = 0, + /* [11] */ + .reg_spm_adsp_mailbox_req = 0, + /* [12] */ + .reg_spm_scp_mailbox_req = 0, + + /* SPM_SRC_MASK */ + /* [0] */ + .reg_sspm_srcclkena_0_mask_b = 1, + /* [1] */ + .reg_sspm_infra_req_0_mask_b = 1, + /* [2] */ + .reg_sspm_apsrc_req_0_mask_b = 1, + /* [3] */ + .reg_sspm_vrf18_req_0_mask_b = 1, + /* [4] */ + .reg_sspm_ddr_en_0_mask_b = 1, + /* [5] */ + .reg_scp_srcclkena_mask_b = 1, + /* [6] */ + .reg_scp_infra_req_mask_b = 1, + /* [7] */ + .reg_scp_apsrc_req_mask_b = 1, + /* [8] */ + .reg_scp_vrf18_req_mask_b = 1, + /* [9] */ + .reg_scp_ddr_en_mask_b = 1, + /* [10] */ + .reg_audio_dsp_srcclkena_mask_b = 1, + /* [11] */ + .reg_audio_dsp_infra_req_mask_b = 1, + /* [12] */ + .reg_audio_dsp_apsrc_req_mask_b = 1, + /* [13] */ + .reg_audio_dsp_vrf18_req_mask_b = 1, + /* [14] */ + .reg_audio_dsp_ddr_en_mask_b = 1, + /* [15] */ + .reg_apu_srcclkena_mask_b = 1, + /* [16] */ + .reg_apu_infra_req_mask_b = 1, + /* [17] */ + .reg_apu_apsrc_req_mask_b = 1, + /* [18] */ + .reg_apu_vrf18_req_mask_b = 1, + /* [19] */ + .reg_apu_ddr_en_mask_b = 1, + /* [20] */ + .reg_cpueb_srcclkena_mask_b = 1, + /* [21] */ + .reg_cpueb_infra_req_mask_b = 1, + /* [22] */ + .reg_cpueb_apsrc_req_mask_b = 1, + /* [23] */ + .reg_cpueb_vrf18_req_mask_b = 1, + /* [24] */ + .reg_cpueb_ddr_en_mask_b = 1, + /* [25] */ + .reg_bak_psri_srcclkena_mask_b = 0, + /* [26] */ + .reg_bak_psri_infra_req_mask_b = 0, + /* [27] */ + .reg_bak_psri_apsrc_req_mask_b = 0, + /* [28] */ + .reg_bak_psri_vrf18_req_mask_b = 0, + /* [29] */ + .reg_bak_psri_ddr_en_mask_b = 0, + + /* SPM_SRC2_MASK */ + /* [0] */ + .reg_msdc0_srcclkena_mask_b = 1, + /* [1] */ + .reg_msdc0_infra_req_mask_b = 1, + /* [2] */ + .reg_msdc0_apsrc_req_mask_b = 1, + /* [3] */ + .reg_msdc0_vrf18_req_mask_b = 1, + /* [4] */ + .reg_msdc0_ddr_en_mask_b = 1, + /* [5] */ + .reg_msdc1_srcclkena_mask_b = 1, + /* [6] */ + .reg_msdc1_infra_req_mask_b = 1, + /* [7] */ + .reg_msdc1_apsrc_req_mask_b = 1, + /* [8] */ + .reg_msdc1_vrf18_req_mask_b = 1, + /* [9] */ + .reg_msdc1_ddr_en_mask_b = 1, + /* [10] */ + .reg_msdc2_srcclkena_mask_b = 1, + /* [11] */ + .reg_msdc2_infra_req_mask_b = 1, + /* [12] */ + .reg_msdc2_apsrc_req_mask_b = 1, + /* [13] */ + .reg_msdc2_vrf18_req_mask_b = 1, + /* [14] */ + .reg_msdc2_ddr_en_mask_b = 1, + /* [15] */ + .reg_ufs_srcclkena_mask_b = 0, + /* [16] */ + .reg_ufs_infra_req_mask_b = 0, + /* [17] */ + .reg_ufs_apsrc_req_mask_b = 0, + /* [18] */ + .reg_ufs_vrf18_req_mask_b = 0, + /* [19] */ + .reg_ufs_ddr_en_mask_b = 0, + /* [20] */ + .reg_usb_srcclkena_mask_b = 1, + /* [21] */ + .reg_usb_infra_req_mask_b = 1, + /* [22] */ + .reg_usb_apsrc_req_mask_b = 1, + /* [23] */ + .reg_usb_vrf18_req_mask_b = 1, + /* [24] */ + .reg_usb_ddr_en_mask_b = 1, + /* [25] */ + .reg_pextp_p0_srcclkena_mask_b = 1, + /* [26] */ + .reg_pextp_p0_infra_req_mask_b = 1, + /* [27] */ + .reg_pextp_p0_apsrc_req_mask_b = 1, + /* [28] */ + .reg_pextp_p0_vrf18_req_mask_b = 1, + /* [29] */ + .reg_pextp_p0_ddr_en_mask_b = 1, + + /* SPM_SRC3_MASK */ + /* [0] */ + .reg_pextp_p1_srcclkena_mask_b = 1, + /* [1] */ + .reg_pextp_p1_infra_req_mask_b = 1, + /* [2] */ + .reg_pextp_p1_apsrc_req_mask_b = 1, + /* [3] */ + .reg_pextp_p1_vrf18_req_mask_b = 1, + /* [4] */ + .reg_pextp_p1_ddr_en_mask_b = 1, + /* [5] */ + .reg_gce0_infra_req_mask_b = 1, + /* [6] */ + .reg_gce0_apsrc_req_mask_b = 1, + /* [7] */ + .reg_gce0_vrf18_req_mask_b = 1, + /* [8] */ + .reg_gce0_ddr_en_mask_b = 1, + /* [9] */ + .reg_gce1_infra_req_mask_b = 1, + /* [10] */ + .reg_gce1_apsrc_req_mask_b = 1, + /* [11] */ + .reg_gce1_vrf18_req_mask_b = 1, + /* [12] */ + .reg_gce1_ddr_en_mask_b = 1, + /* [13] */ + .reg_spm_srcclkena_reserved_mask_b = 1, + /* [14] */ + .reg_spm_infra_req_reserved_mask_b = 1, + /* [15] */ + .reg_spm_apsrc_req_reserved_mask_b = 1, + /* [16] */ + .reg_spm_vrf18_req_reserved_mask_b = 1, + /* [17] */ + .reg_spm_ddr_en_reserved_mask_b = 1, + /* [18] */ + .reg_disp0_apsrc_req_mask_b = 1, + /* [19] */ + .reg_disp0_ddr_en_mask_b = 1, + /* [20] */ + .reg_disp1_apsrc_req_mask_b = 1, + /* [21] */ + .reg_disp1_ddr_en_mask_b = 1, + /* [22] */ + .reg_disp2_apsrc_req_mask_b = 1, + /* [23] */ + .reg_disp2_ddr_en_mask_b = 1, + /* [24] */ + .reg_disp3_apsrc_req_mask_b = 1, + /* [25] */ + .reg_disp3_ddr_en_mask_b = 1, + /* [26] */ + .reg_infrasys_apsrc_req_mask_b = 0, + /* [27] */ + .reg_infrasys_ddr_en_mask_b = 1, + + /* [28] */ + .reg_cg_check_srcclkena_mask_b = 1, + /* [29] */ + .reg_cg_check_apsrc_req_mask_b = 1, + /* [30] */ + .reg_cg_check_vrf18_req_mask_b = 1, + /* [31] */ + .reg_cg_check_ddr_en_mask_b = 1, + + /* SPM_SRC4_MASK */ + /* [8:0] */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x17, + /* [17:9] */ + .reg_mcusys_merge_ddr_en_mask_b = 0x17, + /* [19:18] */ + .reg_dramc_md32_infra_req_mask_b = 0, + /* [21:20] */ + .reg_dramc_md32_vrf18_req_mask_b = 0, + /* [23:22] */ + .reg_dramc_md32_ddr_en_mask_b = 0, + /* [24] */ + .reg_dvfsrc_event_trigger_mask_b = 1, + + /* SPM_WAKEUP_EVENT_MASK2 */ + /* [3:0] */ + .reg_sc_sw2spm_wakeup_mask_b = 0, + /* [4] */ + .reg_sc_adsp2spm_wakeup_mask_b = 0, + /* [8:5] */ + .reg_sc_sspm2spm_wakeup_mask_b = 0, + /* [9] */ + .reg_sc_scp2spm_wakeup_mask_b = 0, + /* [10] */ + .reg_csyspwrup_ack_mask = 0, + /* [11] */ + .reg_csyspwrup_req_mask = 1, + + /* SPM_WAKEUP_EVENT_MASK */ + /* [31:0] */ + .reg_wakeup_event_mask = 0xC1382213, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + /* [31:0] */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, +}; + +struct spm_lp_scen __spm_suspend = { + .pwrctrl = &suspend_ctrl, +}; + +int mt_spm_suspend_mode_set(int mode) +{ + if (mode == MT_SPM_SUSPEND_SLEEP) { + suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG; + suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1; + } else { + suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG; + suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1; + } + + return 0; +} + +int mt_spm_suspend_enter(int state_id, unsigned int ext_opand, + unsigned int resource_req) +{ + /* If FMAudio / ADSP is active, change to sleep suspend mode */ + if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) { + mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP); + } + + /* Notify MCUPM that device is going suspend flow */ + mmio_write_32(MCUPM_MBOX_OFFSET_PDN, MCUPM_POWER_DOWN); + + /* Notify UART to sleep */ + mt_uart_save(); + + return spm_conservation(state_id, ext_opand, + &__spm_suspend, resource_req); +} + +void mt_spm_suspend_resume(int state_id, unsigned int ext_opand, + struct wake_status **status) +{ + spm_conservation_finish(state_id, ext_opand, &__spm_suspend, status); + + /* Notify UART to wakeup */ + mt_uart_restore(); + + /* Notify MCUPM that device leave suspend */ + mmio_write_32(MCUPM_MBOX_OFFSET_PDN, 0); + + /* If FMAudio / ADSP is active, change back to suspend mode */ + if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) { + mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN); + } +} + +void mt_spm_suspend_init(void) +{ + spm_conservation_pwrctrl_init(__spm_suspend.pwrctrl); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h new file mode 100644 index 0000000..69c5230 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SUSPEND_H +#define MT_SPM_SUSPEND_H + +#include + +#define MCUPM_MBOX_OFFSET_PDN 0x1031FF88 +#define MCUPM_POWER_DOWN 0x4D50444E + +enum MT_SPM_SUSPEND_MODE { + MT_SPM_SUSPEND_SYSTEM_PDN, + MT_SPM_SUSPEND_SLEEP, +}; + +extern int mt_spm_suspend_mode_set(int mode); +extern int mt_spm_suspend_enter(int state_id, unsigned int ext_opand, + unsigned int reosuce_req); +extern void mt_spm_suspend_resume(int state_id, unsigned int ext_opand, + struct wake_status **status); +extern void mt_spm_suspend_init(void); +#endif /* MT_SPM_SUSPEND_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c new file mode 100644 index 0000000..6a85b5c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VCORE_MAX_OPP 4 +#define DRAM_MAX_OPP 7 + +static bool spm_dvfs_init_done; +static bool dvfs_enable_done; +static int vcore_opp_0_uv = 750000; +static int vcore_opp_1_uv = 650000; +static int vcore_opp_2_uv = 600000; +static int vcore_opp_3_uv = 550000; + +static struct reg_config dvfsrc_init_configs[] = { + { DVFSRC_HRT_REQ_UNIT, 0x0000001E }, + { DVFSRC_DEBOUNCE_TIME, 0x19651965 }, + { DVFSRC_TIMEOUT_NEXTREQ, 0x00000015 }, + { DVFSRC_LEVEL_MASK, 0x000EE000 }, + { DVFSRC_DDR_QOS0, 0x00000019 }, + { DVFSRC_DDR_QOS1, 0x00000026 }, + { DVFSRC_DDR_QOS2, 0x00000033 }, + { DVFSRC_DDR_QOS3, 0x0000003B }, + { DVFSRC_DDR_QOS4, 0x0000004C }, + { DVFSRC_DDR_QOS5, 0x00000066 }, + { DVFSRC_DDR_QOS6, 0x00660066 }, + { DVFSRC_LEVEL_LABEL_0_1, 0x50436053 }, + { DVFSRC_LEVEL_LABEL_2_3, 0x40335042 }, + { DVFSRC_LEVEL_LABEL_4_5, 0x40314032 }, + { DVFSRC_LEVEL_LABEL_6_7, 0x30223023 }, + { DVFSRC_LEVEL_LABEL_8_9, 0x20133021 }, + { DVFSRC_LEVEL_LABEL_10_11, 0x20112012 }, + { DVFSRC_LEVEL_LABEL_12_13, 0x10032010 }, + { DVFSRC_LEVEL_LABEL_14_15, 0x10011002 }, + { DVFSRC_LEVEL_LABEL_16_17, 0x00131000 }, + { DVFSRC_LEVEL_LABEL_18_19, 0x00110012 }, + { DVFSRC_LEVEL_LABEL_20_21, 0x00000010 }, + { DVFSRC_MD_LATENCY_IMPROVE, 0x00000040 }, + { DVFSRC_DDR_REQUEST, 0x00004321 }, + { DVFSRC_DDR_REQUEST3, 0x00000065 }, + { DVFSRC_DDR_ADD_REQUEST, 0x66543210 }, + { DVFSRC_HRT_REQUEST, 0x66654321 }, + { DVFSRC_DDR_REQUEST5, 0x54321000 }, + { DVFSRC_DDR_REQUEST7, 0x66000000 }, + { DVFSRC_VCORE_USER_REQ, 0x00010A29 }, + { DVFSRC_HRT_HIGH_3, 0x18A618A6 }, + { DVFSRC_HRT_HIGH_2, 0x18A61183 }, + { DVFSRC_HRT_HIGH_1, 0x0D690B80 }, + { DVFSRC_HRT_HIGH, 0x070804B0 }, + { DVFSRC_HRT_LOW_3, 0x18A518A5 }, + { DVFSRC_HRT_LOW_2, 0x18A51182 }, + { DVFSRC_HRT_LOW_1, 0x0D680B7F }, + { DVFSRC_HRT_LOW, 0x070704AF }, + { DVFSRC_BASIC_CONTROL_3, 0x00000006 }, + { DVFSRC_INT_EN, 0x00000002 }, + { DVFSRC_QOS_EN, 0x0000407C }, + { DVFSRC_HRT_BW_BASE, 0x00000004 }, + { DVFSRC_PCIE_VCORE_REQ, 0x65908101 }, + { DVFSRC_CURRENT_FORCE, 0x00000001 }, + { DVFSRC_BASIC_CONTROL, 0x6698444B }, + { DVFSRC_BASIC_CONTROL, 0x6698054B }, + { DVFSRC_CURRENT_FORCE, 0x00000000 }, +}; + +static struct pwr_ctrl vcorefs_ctrl = { + .wake_src = R12_REG_CPU_WAKEUP, + + /* default VCORE DVFS is disabled */ + .pcm_flags = (SPM_FLAG_RUN_COMMON_SCENARIO | + SPM_FLAG_DISABLE_VCORE_DVS | SPM_FLAG_DISABLE_VCORE_DFS), + + /* SPM_AP_STANDBY_CON */ + /* [0] */ + .reg_wfi_op = 0, + /* [1] */ + .reg_wfi_type = 0, + /* [2] */ + .reg_mp0_cputop_idle_mask = 0, + /* [3] */ + .reg_mp1_cputop_idle_mask = 0, + /* [4] */ + .reg_mcusys_idle_mask = 0, + /* [25] */ + .reg_md_apsrc_1_sel = 0, + /* [26] */ + .reg_md_apsrc_0_sel = 0, + /* [29] */ + .reg_conn_apsrc_sel = 0, + + /* SPM_SRC_REQ */ + /* [0] */ + .reg_spm_apsrc_req = 0, + /* [1] */ + .reg_spm_f26m_req = 0, + /* [3] */ + .reg_spm_infra_req = 0, + /* [4] */ + .reg_spm_vrf18_req = 0, + /* [7] FIXME: default disable HW Auto S1*/ + .reg_spm_ddr_en_req = 1, + /* [8] */ + .reg_spm_dvfs_req = 0, + /* [9] */ + .reg_spm_sw_mailbox_req = 0, + /* [10] */ + .reg_spm_sspm_mailbox_req = 0, + /* [11] */ + .reg_spm_adsp_mailbox_req = 0, + /* [12] */ + .reg_spm_scp_mailbox_req = 0, + + /* SPM_SRC_MASK */ + /* [0] */ + .reg_sspm_srcclkena_0_mask_b = 1, + /* [1] */ + .reg_sspm_infra_req_0_mask_b = 1, + /* [2] */ + .reg_sspm_apsrc_req_0_mask_b = 1, + /* [3] */ + .reg_sspm_vrf18_req_0_mask_b = 1, + /* [4] */ + .reg_sspm_ddr_en_0_mask_b = 1, + /* [5] */ + .reg_scp_srcclkena_mask_b = 1, + /* [6] */ + .reg_scp_infra_req_mask_b = 1, + /* [7] */ + .reg_scp_apsrc_req_mask_b = 1, + /* [8] */ + .reg_scp_vrf18_req_mask_b = 1, + /* [9] */ + .reg_scp_ddr_en_mask_b = 1, + /* [10] */ + .reg_audio_dsp_srcclkena_mask_b = 1, + /* [11] */ + .reg_audio_dsp_infra_req_mask_b = 1, + /* [12] */ + .reg_audio_dsp_apsrc_req_mask_b = 1, + /* [13] */ + .reg_audio_dsp_vrf18_req_mask_b = 1, + /* [14] */ + .reg_audio_dsp_ddr_en_mask_b = 1, + /* [15] */ + .reg_apu_srcclkena_mask_b = 1, + /* [16] */ + .reg_apu_infra_req_mask_b = 1, + /* [17] */ + .reg_apu_apsrc_req_mask_b = 1, + /* [18] */ + .reg_apu_vrf18_req_mask_b = 1, + /* [19] */ + .reg_apu_ddr_en_mask_b = 1, + /* [20] */ + .reg_cpueb_srcclkena_mask_b = 1, + /* [21] */ + .reg_cpueb_infra_req_mask_b = 1, + /* [22] */ + .reg_cpueb_apsrc_req_mask_b = 1, + /* [23] */ + .reg_cpueb_vrf18_req_mask_b = 1, + /* [24] */ + .reg_cpueb_ddr_en_mask_b = 1, + /* [25] */ + .reg_bak_psri_srcclkena_mask_b = 0, + /* [26] */ + .reg_bak_psri_infra_req_mask_b = 0, + /* [27] */ + .reg_bak_psri_apsrc_req_mask_b = 0, + /* [28] */ + .reg_bak_psri_vrf18_req_mask_b = 0, + /* [29] */ + .reg_bak_psri_ddr_en_mask_b = 0, + + /* SPM_SRC2_MASK */ + /* [0] */ + .reg_msdc0_srcclkena_mask_b = 1, + /* [1] */ + .reg_msdc0_infra_req_mask_b = 1, + /* [2] */ + .reg_msdc0_apsrc_req_mask_b = 1, + /* [3] */ + .reg_msdc0_vrf18_req_mask_b = 1, + /* [4] */ + .reg_msdc0_ddr_en_mask_b = 1, + /* [5] */ + .reg_msdc1_srcclkena_mask_b = 1, + /* [6] */ + .reg_msdc1_infra_req_mask_b = 1, + /* [7] */ + .reg_msdc1_apsrc_req_mask_b = 1, + /* [8] */ + .reg_msdc1_vrf18_req_mask_b = 1, + /* [9] */ + .reg_msdc1_ddr_en_mask_b = 1, + /* [10] */ + .reg_msdc2_srcclkena_mask_b = 1, + /* [11] */ + .reg_msdc2_infra_req_mask_b = 1, + /* [12] */ + .reg_msdc2_apsrc_req_mask_b = 1, + /* [13] */ + .reg_msdc2_vrf18_req_mask_b = 1, + /* [14] */ + .reg_msdc2_ddr_en_mask_b = 1, + /* [15] */ + .reg_ufs_srcclkena_mask_b = 1, + /* [16] */ + .reg_ufs_infra_req_mask_b = 1, + /* [17] */ + .reg_ufs_apsrc_req_mask_b = 1, + /* [18] */ + .reg_ufs_vrf18_req_mask_b = 1, + /* [19] */ + .reg_ufs_ddr_en_mask_b = 1, + /* [20] */ + .reg_usb_srcclkena_mask_b = 1, + /* [21] */ + .reg_usb_infra_req_mask_b = 1, + /* [22] */ + .reg_usb_apsrc_req_mask_b = 1, + /* [23] */ + .reg_usb_vrf18_req_mask_b = 1, + /* [24] */ + .reg_usb_ddr_en_mask_b = 1, + /* [25] */ + .reg_pextp_p0_srcclkena_mask_b = 1, + /* [26] */ + .reg_pextp_p0_infra_req_mask_b = 1, + /* [27] */ + .reg_pextp_p0_apsrc_req_mask_b = 1, + /* [28] */ + .reg_pextp_p0_vrf18_req_mask_b = 1, + /* [29] */ + .reg_pextp_p0_ddr_en_mask_b = 1, + + /* SPM_SRC3_MASK */ + /* [0] */ + .reg_pextp_p1_srcclkena_mask_b = 1, + /* [1] */ + .reg_pextp_p1_infra_req_mask_b = 1, + /* [2] */ + .reg_pextp_p1_apsrc_req_mask_b = 1, + /* [3] */ + .reg_pextp_p1_vrf18_req_mask_b = 1, + /* [4] */ + .reg_pextp_p1_ddr_en_mask_b = 1, + /* [5] */ + .reg_gce0_infra_req_mask_b = 1, + /* [6] */ + .reg_gce0_apsrc_req_mask_b = 1, + /* [7] */ + .reg_gce0_vrf18_req_mask_b = 1, + /* [8] */ + .reg_gce0_ddr_en_mask_b = 1, + /* [9] */ + .reg_gce1_infra_req_mask_b = 1, + /* [10] */ + .reg_gce1_apsrc_req_mask_b = 1, + /* [11] */ + .reg_gce1_vrf18_req_mask_b = 1, + /* [12] */ + .reg_gce1_ddr_en_mask_b = 1, + /* [13] */ + .reg_spm_srcclkena_reserved_mask_b = 1, + /* [14] */ + .reg_spm_infra_req_reserved_mask_b = 1, + /* [15] */ + .reg_spm_apsrc_req_reserved_mask_b = 1, + /* [16] */ + .reg_spm_vrf18_req_reserved_mask_b = 1, + /* [17] */ + .reg_spm_ddr_en_reserved_mask_b = 1, + /* [18] */ + .reg_disp0_apsrc_req_mask_b = 1, + /* [19] */ + .reg_disp0_ddr_en_mask_b = 1, + /* [20] */ + .reg_disp1_apsrc_req_mask_b = 1, + /* [21] */ + .reg_disp1_ddr_en_mask_b = 1, + /* [22] */ + .reg_disp2_apsrc_req_mask_b = 1, + /* [23] */ + .reg_disp2_ddr_en_mask_b = 1, + /* [24] */ + .reg_disp3_apsrc_req_mask_b = 1, + /* [25] */ + .reg_disp3_ddr_en_mask_b = 1, + /* [26] */ + .reg_infrasys_apsrc_req_mask_b = 0, + /* [27] */ + .reg_infrasys_ddr_en_mask_b = 1, + + /* [28] */ + .reg_cg_check_srcclkena_mask_b = 1, + /* [29] */ + .reg_cg_check_apsrc_req_mask_b = 1, + /* [30] */ + .reg_cg_check_vrf18_req_mask_b = 1, + /* [31] */ + .reg_cg_check_ddr_en_mask_b = 1, + + /* SPM_SRC4_MASK */ + /* [8:0] */ + .reg_mcusys_merge_apsrc_req_mask_b = 0x11, + /* [17:9] */ + .reg_mcusys_merge_ddr_en_mask_b = 0x11, + /* [19:18] */ + .reg_dramc_md32_infra_req_mask_b = 0, + /* [21:20] */ + .reg_dramc_md32_vrf18_req_mask_b = 0, + /* [23:22] */ + .reg_dramc_md32_ddr_en_mask_b = 0, + /* [24] */ + .reg_dvfsrc_event_trigger_mask_b = 1, + + /* SPM_WAKEUP_EVENT_MASK2 */ + /* [3:0] */ + .reg_sc_sw2spm_wakeup_mask_b = 0, + /* [4] */ + .reg_sc_adsp2spm_wakeup_mask_b = 0, + /* [8:5] */ + .reg_sc_sspm2spm_wakeup_mask_b = 0, + /* [9] */ + .reg_sc_scp2spm_wakeup_mask_b = 0, + /* [10] */ + .reg_csyspwrup_ack_mask = 0, + /* [11] */ + .reg_csyspwrup_req_mask = 1, + + /* SPM_WAKEUP_EVENT_MASK */ + /* [31:0] */ + .reg_wakeup_event_mask = 0xEFFFFFFF, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + /* [31:0] */ + .reg_ext_wakeup_event_mask = 0xFFFFFFFF, +}; + +struct spm_lp_scen __spm_vcorefs = { + .pwrctrl = &vcorefs_ctrl, +}; + +static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val) +{ + if (cmd < NR_IDX_ALL) { + mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val); + } else { + INFO("cmd out of range!\n"); + } +} + +void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue) +{ + if (spm_dvfs_init_done == false) { + mmio_write_32(SPM_DVFS_MISC, (mmio_read_32(SPM_DVFS_MISC) & + ~(SPM_DVFS_FORCE_ENABLE_LSB)) | (SPM_DVFSRC_ENABLE_LSB)); + + mmio_write_32(SPM_DVFS_LEVEL, 0x00000001); + mmio_write_32(SPM_DVS_DFS_LEVEL, 0x00010001); + + spm_dvfs_init_done = true; + } +} + +void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl, + const struct pwr_ctrl *src_pwr_ctrl) +{ + uint32_t dvfs_mask = SPM_FLAG_DISABLE_VCORE_DVS | + SPM_FLAG_DISABLE_VCORE_DFS | + SPM_FLAG_ENABLE_VOLTAGE_BIN; + + dest_pwr_ctrl->pcm_flags = (dest_pwr_ctrl->pcm_flags & (~dvfs_mask)) | + (src_pwr_ctrl->pcm_flags & dvfs_mask); + + if (dest_pwr_ctrl->pcm_flags_cust) { + dest_pwr_ctrl->pcm_flags_cust = (dest_pwr_ctrl->pcm_flags_cust & (~dvfs_mask)) | + (src_pwr_ctrl->pcm_flags & dvfs_mask); + } +} + +void spm_go_to_vcorefs(uint64_t spm_flags) +{ + __spm_set_power_control(__spm_vcorefs.pwrctrl); + __spm_set_wakeup_event(__spm_vcorefs.pwrctrl); + __spm_set_pcm_flags(__spm_vcorefs.pwrctrl); + __spm_send_cpu_wakeup_event(); +} + +uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3) +{ + uint64_t ret = 0U; + uint64_t cmd = x1; + uint64_t spm_flags; + + switch (cmd) { + case VCOREFS_SMC_CMD_0: + spm_dvfsfw_init(x2, x3); + break; + case VCOREFS_SMC_CMD_1: + spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO; + if (x2 & SPM_FLAG_DISABLE_VCORE_DVS) + spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS; + if (x2 & SPM_FLAG_DISABLE_VCORE_DFS) + spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS; + spm_go_to_vcorefs(spm_flags); + break; + case VCOREFS_SMC_CMD_3: + spm_vcorefs_pwarp_cmd(x2, x3); + break; + case VCOREFS_SMC_CMD_2: + case VCOREFS_SMC_CMD_4: + case VCOREFS_SMC_CMD_5: + case VCOREFS_SMC_CMD_7: + default: + break; + } + return ret; +} + +static void dvfsrc_init(void) +{ + int i; + int count = ARRAY_SIZE(dvfsrc_init_configs); + + if (dvfs_enable_done == false) { + for (i = 0; i < count; i++) { + mmio_write_32(dvfsrc_init_configs[i].offset, + dvfsrc_init_configs[i].val); + } + + mmio_write_32(DVFSRC_QOS_EN, 0x0011007C); + + dvfs_enable_done = true; + } +} + +static void spm_vcorefs_vcore_setting(uint64_t flag) +{ + spm_vcorefs_pwarp_cmd(3, __vcore_uv_to_pmic(vcore_opp_3_uv)); + spm_vcorefs_pwarp_cmd(2, __vcore_uv_to_pmic(vcore_opp_2_uv)); + spm_vcorefs_pwarp_cmd(1, __vcore_uv_to_pmic(vcore_opp_1_uv)); + spm_vcorefs_pwarp_cmd(0, __vcore_uv_to_pmic(vcore_opp_0_uv)); +} + +int spm_vcorefs_get_vcore(unsigned int gear) +{ + int ret_val; + + switch (gear) { + case 3: + ret_val = vcore_opp_0_uv; + break; + case 2: + ret_val = vcore_opp_1_uv; + break; + case 1: + ret_val = vcore_opp_2_uv; + break; + case 0: + default: + ret_val = vcore_opp_3_uv; + break; + } + return ret_val; +} + +uint64_t spm_vcorefs_v2_args(u_register_t x1, u_register_t x2, u_register_t x3, u_register_t *x4) +{ + uint64_t ret = 0U; + uint64_t cmd = x1; + uint64_t spm_flags; + + switch (cmd) { + case VCOREFS_SMC_CMD_INIT: + /* vcore_dvfs init + kick */ + spm_dvfsfw_init(0, 0); + spm_vcorefs_vcore_setting(x3 & 0xF); + spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO; + if (x2 & 0x1) { + spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS; + } + if (x2 & 0x2) { + spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS; + } + spm_go_to_vcorefs(spm_flags); + dvfsrc_init(); + *x4 = 0U; + break; + case VCOREFS_SMC_CMD_OPP_TYPE: + /* get dram type */ + *x4 = 0U; + break; + case VCOREFS_SMC_CMD_FW_TYPE: + *x4 = 0U; + break; + case VCOREFS_SMC_CMD_GET_UV: + *x4 = spm_vcorefs_get_vcore(x2); + break; + case VCOREFS_SMC_CMD_GET_NUM_V: + *x4 = VCORE_MAX_OPP; + break; + case VCOREFS_SMC_CMD_GET_NUM_F: + *x4 = DRAM_MAX_OPP; + break; + default: + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h new file mode 100644 index 0000000..b08fcce --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __MT_SPM_VCOREFS__H__ +#define __MT_SPM_VCOREFS__H__ + +int spm_vcorefs_get_vcore(unsigned int gear); +uint64_t spm_vcorefs_v2_args(u_register_t x1, u_register_t x2, u_register_t x3, + u_register_t *x4); + +enum vcorefs_smc_cmd { + VCOREFS_SMC_CMD_0 = 0, + VCOREFS_SMC_CMD_1, + VCOREFS_SMC_CMD_2, + VCOREFS_SMC_CMD_3, + VCOREFS_SMC_CMD_4, + /* check spmfw status */ + VCOREFS_SMC_CMD_5, + + /* get spmfw type */ + VCOREFS_SMC_CMD_6, + + /* get spm reg status */ + VCOREFS_SMC_CMD_7, + + NUM_VCOREFS_SMC_CMD, +}; + +enum vcorefs_smc_cmd_new { + VCOREFS_SMC_CMD_INIT = 0, + VCOREFS_SMC_CMD_KICK = 1, + VCOREFS_SMC_CMD_OPP_TYPE = 2, + VCOREFS_SMC_CMD_FW_TYPE = 3, + VCOREFS_SMC_CMD_GET_UV = 4, + VCOREFS_SMC_CMD_GET_FREQ = 5, + VCOREFS_SMC_CMD_GET_NUM_V = 6, + VCOREFS_SMC_CMD_GET_NUM_F = 7, + VCOREFS_SMC_CMD_FB_ACTION = 8, + /*chip specific setting */ + VCOREFS_SMC_CMD_SET_FREQ = 16, + VCOREFS_SMC_CMD_SET_EFUSE = 17, + VCOREFS_SMC_CMD_GET_EFUSE = 18, + VCOREFS_SMC_CMD_DVFS_HOPPING = 19, + VCOREFS_SMC_CMD_DVFS_HOPPING_STATE = 20, +}; + +enum dvfsrc_channel { + DVFSRC_CHANNEL_1 = 1, + DVFSRC_CHANNEL_2, + DVFSRC_CHANNEL_3, + DVFSRC_CHANNEL_4, + NUM_DVFSRC_CHANNEL, +}; + +#define _VCORE_BASE_UV 400000 +#define _VCORE_STEP_UV 6250 + +/* PMIC */ +#define __vcore_pmic_to_uv(pmic) \ + (((pmic) * _VCORE_STEP_UV) + _VCORE_BASE_UV) + +#define __vcore_uv_to_pmic(uv) /* pmic >= uv */ \ + ((((uv) - _VCORE_BASE_UV) + (_VCORE_STEP_UV - 1)) / _VCORE_STEP_UV) + +struct reg_config { + uint32_t offset; + uint32_t val; +}; + +#define DVFSRC_BASIC_CONTROL (DVFSRC_BASE + 0x0) +#define DVFSRC_SW_REQ1 (DVFSRC_BASE + 0x4) +#define DVFSRC_SW_REQ2 (DVFSRC_BASE + 0x8) +#define DVFSRC_SW_REQ3 (DVFSRC_BASE + 0xC) +#define DVFSRC_SW_REQ4 (DVFSRC_BASE + 0x10) +#define DVFSRC_SW_REQ5 (DVFSRC_BASE + 0x14) +#define DVFSRC_SW_REQ6 (DVFSRC_BASE + 0x18) +#define DVFSRC_SW_REQ7 (DVFSRC_BASE + 0x1C) +#define DVFSRC_SW_REQ8 (DVFSRC_BASE + 0x20) +#define DVFSRC_EMI_REQUEST (DVFSRC_BASE + 0x24) +#define DVFSRC_EMI_REQUEST2 (DVFSRC_BASE + 0x28) +#define DVFSRC_EMI_REQUEST3 (DVFSRC_BASE + 0x2C) +#define DVFSRC_EMI_REQUEST4 (DVFSRC_BASE + 0x30) +#define DVFSRC_EMI_REQUEST5 (DVFSRC_BASE + 0x34) +#define DVFSRC_EMI_REQUEST6 (DVFSRC_BASE + 0x38) +#define DVFSRC_EMI_HRT (DVFSRC_BASE + 0x3C) +#define DVFSRC_EMI_HRT2 (DVFSRC_BASE + 0x40) +#define DVFSRC_EMI_HRT3 (DVFSRC_BASE + 0x44) +#define DVFSRC_EMI_QOS0 (DVFSRC_BASE + 0x48) +#define DVFSRC_EMI_QOS1 (DVFSRC_BASE + 0x4C) +#define DVFSRC_EMI_QOS2 (DVFSRC_BASE + 0x50) +#define DVFSRC_EMI_MD2SPM0 (DVFSRC_BASE + 0x54) +#define DVFSRC_EMI_MD2SPM1 (DVFSRC_BASE + 0x58) +#define DVFSRC_EMI_MD2SPM2 (DVFSRC_BASE + 0x5C) +#define DVFSRC_EMI_MD2SPM0_T (DVFSRC_BASE + 0x60) +#define DVFSRC_EMI_MD2SPM1_T (DVFSRC_BASE + 0x64) +#define DVFSRC_EMI_MD2SPM2_T (DVFSRC_BASE + 0x68) +#define DVFSRC_VCORE_REQUEST (DVFSRC_BASE + 0x6C) +#define DVFSRC_VCORE_REQUEST2 (DVFSRC_BASE + 0x70) +#define DVFSRC_VCORE_REQUEST3 (DVFSRC_BASE + 0x74) +#define DVFSRC_VCORE_REQUEST4 (DVFSRC_BASE + 0x78) +#define DVFSRC_VCORE_HRT (DVFSRC_BASE + 0x7C) +#define DVFSRC_VCORE_HRT2 (DVFSRC_BASE + 0x80) +#define DVFSRC_VCORE_HRT3 (DVFSRC_BASE + 0x84) +#define DVFSRC_VCORE_QOS0 (DVFSRC_BASE + 0x88) +#define DVFSRC_VCORE_QOS1 (DVFSRC_BASE + 0x8C) +#define DVFSRC_VCORE_QOS2 (DVFSRC_BASE + 0x90) +#define DVFSRC_VCORE_MD2SPM0 (DVFSRC_BASE + 0x94) +#define DVFSRC_VCORE_MD2SPM1 (DVFSRC_BASE + 0x98) +#define DVFSRC_VCORE_MD2SPM2 (DVFSRC_BASE + 0x9C) +#define DVFSRC_VCORE_MD2SPM0_T (DVFSRC_BASE + 0xA0) +#define DVFSRC_VCORE_MD2SPM1_T (DVFSRC_BASE + 0xA4) +#define DVFSRC_VCORE_MD2SPM2_T (DVFSRC_BASE + 0xA8) +#define DVFSRC_MD_VSRAM_REMAP (DVFSRC_BASE + 0xBC) +#define DVFSRC_HALT_SW_CONTROL (DVFSRC_BASE + 0xC0) +#define DVFSRC_INT (DVFSRC_BASE + 0xC4) +#define DVFSRC_INT_EN (DVFSRC_BASE + 0xC8) +#define DVFSRC_INT_CLR (DVFSRC_BASE + 0xCC) +#define DVFSRC_BW_MON_WINDOW (DVFSRC_BASE + 0xD0) +#define DVFSRC_BW_MON_THRES_1 (DVFSRC_BASE + 0xD4) +#define DVFSRC_BW_MON_THRES_2 (DVFSRC_BASE + 0xD8) +#define DVFSRC_MD_TURBO (DVFSRC_BASE + 0xDC) +#define DVFSRC_PCIE_VCORE_REQ (DVFSRC_BASE + 0xE0) +#define DVFSRC_VCORE_USER_REQ (DVFSRC_BASE + 0xE4) +#define DVFSRC_DEBOUNCE_FOUR (DVFSRC_BASE + 0xF0) +#define DVFSRC_DEBOUNCE_RISE_FALL (DVFSRC_BASE + 0xF4) +#define DVFSRC_TIMEOUT_NEXTREQ (DVFSRC_BASE + 0xF8) +#define DVFSRC_LEVEL_LABEL_0_1 (DVFSRC_BASE + 0x100) +#define DVFSRC_LEVEL_LABEL_2_3 (DVFSRC_BASE + 0x104) +#define DVFSRC_LEVEL_LABEL_4_5 (DVFSRC_BASE + 0x108) +#define DVFSRC_LEVEL_LABEL_6_7 (DVFSRC_BASE + 0x10C) +#define DVFSRC_LEVEL_LABEL_8_9 (DVFSRC_BASE + 0x110) +#define DVFSRC_LEVEL_LABEL_10_11 (DVFSRC_BASE + 0x114) +#define DVFSRC_LEVEL_LABEL_12_13 (DVFSRC_BASE + 0x118) +#define DVFSRC_LEVEL_LABEL_14_15 (DVFSRC_BASE + 0x11C) +#define DVFSRC_MM_BW_0 (DVFSRC_BASE + 0x200) +#define DVFSRC_MM_BW_1 (DVFSRC_BASE + 0x204) +#define DVFSRC_MM_BW_2 (DVFSRC_BASE + 0x208) +#define DVFSRC_MM_BW_3 (DVFSRC_BASE + 0x20C) +#define DVFSRC_MM_BW_4 (DVFSRC_BASE + 0x210) +#define DVFSRC_MM_BW_5 (DVFSRC_BASE + 0x214) +#define DVFSRC_MM_BW_6 (DVFSRC_BASE + 0x218) +#define DVFSRC_MM_BW_7 (DVFSRC_BASE + 0x21C) +#define DVFSRC_MM_BW_8 (DVFSRC_BASE + 0x220) +#define DVFSRC_MM_BW_9 (DVFSRC_BASE + 0x224) +#define DVFSRC_MM_BW_10 (DVFSRC_BASE + 0x228) +#define DVFSRC_MM_BW_11 (DVFSRC_BASE + 0x22C) +#define DVFSRC_MM_BW_12 (DVFSRC_BASE + 0x230) +#define DVFSRC_MM_BW_13 (DVFSRC_BASE + 0x234) +#define DVFSRC_MM_BW_14 (DVFSRC_BASE + 0x238) +#define DVFSRC_MM_BW_15 (DVFSRC_BASE + 0x23C) +#define DVFSRC_MD_BW_0 (DVFSRC_BASE + 0x240) +#define DVFSRC_MD_BW_1 (DVFSRC_BASE + 0x244) +#define DVFSRC_MD_BW_2 (DVFSRC_BASE + 0x248) +#define DVFSRC_MD_BW_3 (DVFSRC_BASE + 0x24C) +#define DVFSRC_MD_BW_4 (DVFSRC_BASE + 0x250) +#define DVFSRC_MD_BW_5 (DVFSRC_BASE + 0x254) +#define DVFSRC_MD_BW_6 (DVFSRC_BASE + 0x258) +#define DVFSRC_MD_BW_7 (DVFSRC_BASE + 0x25C) +#define DVFSRC_SW_BW_0 (DVFSRC_BASE + 0x260) +#define DVFSRC_SW_BW_1 (DVFSRC_BASE + 0x264) +#define DVFSRC_SW_BW_2 (DVFSRC_BASE + 0x268) +#define DVFSRC_SW_BW_3 (DVFSRC_BASE + 0x26C) +#define DVFSRC_SW_BW_4 (DVFSRC_BASE + 0x270) +#define DVFSRC_SW_BW_5 (DVFSRC_BASE + 0x274) +#define DVFSRC_SW_BW_6 (DVFSRC_BASE + 0x278) +#define DVFSRC_QOS_EN (DVFSRC_BASE + 0x280) +#define DVFSRC_MD_BW_URG (DVFSRC_BASE + 0x284) +#define DVFSRC_ISP_HRT (DVFSRC_BASE + 0x290) +#define DVFSRC_HRT_BW_BASE (DVFSRC_BASE + 0x294) +#define DVFSRC_SEC_SW_REQ (DVFSRC_BASE + 0x304) +#define DVFSRC_EMI_MON_DEBOUNCE_TIME (DVFSRC_BASE + 0x308) +#define DVFSRC_MD_LATENCY_IMPROVE (DVFSRC_BASE + 0x30C) +#define DVFSRC_BASIC_CONTROL_3 (DVFSRC_BASE + 0x310) +#define DVFSRC_DEBOUNCE_TIME (DVFSRC_BASE + 0x314) +#define DVFSRC_LEVEL_MASK (DVFSRC_BASE + 0x318) +#define DVFSRC_DEFAULT_OPP (DVFSRC_BASE + 0x31C) +#define DVFSRC_95MD_SCEN_EMI0 (DVFSRC_BASE + 0x500) +#define DVFSRC_95MD_SCEN_EMI1 (DVFSRC_BASE + 0x504) +#define DVFSRC_95MD_SCEN_EMI2 (DVFSRC_BASE + 0x508) +#define DVFSRC_95MD_SCEN_EMI3 (DVFSRC_BASE + 0x50C) +#define DVFSRC_95MD_SCEN_EMI0_T (DVFSRC_BASE + 0x510) +#define DVFSRC_95MD_SCEN_EMI1_T (DVFSRC_BASE + 0x514) +#define DVFSRC_95MD_SCEN_EMI2_T (DVFSRC_BASE + 0x518) +#define DVFSRC_95MD_SCEN_EMI3_T (DVFSRC_BASE + 0x51C) +#define DVFSRC_95MD_SCEN_EMI4 (DVFSRC_BASE + 0x520) +#define DVFSRC_95MD_SCEN_BW0 (DVFSRC_BASE + 0x524) +#define DVFSRC_95MD_SCEN_BW1 (DVFSRC_BASE + 0x528) +#define DVFSRC_95MD_SCEN_BW2 (DVFSRC_BASE + 0x52C) +#define DVFSRC_95MD_SCEN_BW3 (DVFSRC_BASE + 0x530) +#define DVFSRC_95MD_SCEN_BW0_T (DVFSRC_BASE + 0x534) +#define DVFSRC_95MD_SCEN_BW1_T (DVFSRC_BASE + 0x538) +#define DVFSRC_95MD_SCEN_BW2_T (DVFSRC_BASE + 0x53C) +#define DVFSRC_95MD_SCEN_BW3_T (DVFSRC_BASE + 0x540) +#define DVFSRC_95MD_SCEN_BW4 (DVFSRC_BASE + 0x544) +#define DVFSRC_MD_LEVEL_SW_REG (DVFSRC_BASE + 0x548) +#define DVFSRC_RSRV_0 (DVFSRC_BASE + 0x600) +#define DVFSRC_RSRV_1 (DVFSRC_BASE + 0x604) +#define DVFSRC_RSRV_2 (DVFSRC_BASE + 0x608) +#define DVFSRC_RSRV_3 (DVFSRC_BASE + 0x60C) +#define DVFSRC_RSRV_4 (DVFSRC_BASE + 0x610) +#define DVFSRC_RSRV_5 (DVFSRC_BASE + 0x614) +#define DVFSRC_SPM_RESEND (DVFSRC_BASE + 0x630) +#define DVFSRC_DEBUG_STA_0 (DVFSRC_BASE + 0x700) +#define DVFSRC_DEBUG_STA_1 (DVFSRC_BASE + 0x704) +#define DVFSRC_DEBUG_STA_2 (DVFSRC_BASE + 0x708) +#define DVFSRC_DEBUG_STA_3 (DVFSRC_BASE + 0x70C) +#define DVFSRC_DEBUG_STA_4 (DVFSRC_BASE + 0x710) +#define DVFSRC_DEBUG_STA_5 (DVFSRC_BASE + 0x714) +#define DVFSRC_EMI_REQUEST7 (DVFSRC_BASE + 0x800) +#define DVFSRC_EMI_HRT_1 (DVFSRC_BASE + 0x804) +#define DVFSRC_EMI_HRT2_1 (DVFSRC_BASE + 0x808) +#define DVFSRC_EMI_HRT3_1 (DVFSRC_BASE + 0x80C) +#define DVFSRC_EMI_QOS3 (DVFSRC_BASE + 0x810) +#define DVFSRC_EMI_QOS4 (DVFSRC_BASE + 0x814) +#define DVFSRC_DDR_REQUEST (DVFSRC_BASE + 0xA00) +#define DVFSRC_DDR_REQUEST2 (DVFSRC_BASE + 0xA04) +#define DVFSRC_DDR_REQUEST3 (DVFSRC_BASE + 0xA08) +#define DVFSRC_DDR_REQUEST4 (DVFSRC_BASE + 0xA0C) +#define DVFSRC_DDR_REQUEST5 (DVFSRC_BASE + 0xA10) +#define DVFSRC_DDR_REQUEST6 (DVFSRC_BASE + 0xA14) +#define DVFSRC_DDR_REQUEST7 (DVFSRC_BASE + 0xA18) +#define DVFSRC_DDR_HRT (DVFSRC_BASE + 0xA1C) +#define DVFSRC_DDR_HRT2 (DVFSRC_BASE + 0xA20) +#define DVFSRC_DDR_HRT3 (DVFSRC_BASE + 0xA24) +#define DVFSRC_DDR_HRT_1 (DVFSRC_BASE + 0xA28) +#define DVFSRC_DDR_HRT2_1 (DVFSRC_BASE + 0xA2C) +#define DVFSRC_DDR_HRT3_1 (DVFSRC_BASE + 0xA30) +#define DVFSRC_DDR_QOS0 (DVFSRC_BASE + 0xA34) +#define DVFSRC_DDR_QOS1 (DVFSRC_BASE + 0xA38) +#define DVFSRC_DDR_QOS2 (DVFSRC_BASE + 0xA3C) +#define DVFSRC_DDR_QOS3 (DVFSRC_BASE + 0xA40) +#define DVFSRC_DDR_QOS4 (DVFSRC_BASE + 0xA44) +#define DVFSRC_DDR_MD2SPM0 (DVFSRC_BASE + 0xA48) +#define DVFSRC_DDR_MD2SPM1 (DVFSRC_BASE + 0xA4C) +#define DVFSRC_DDR_MD2SPM2 (DVFSRC_BASE + 0xA50) +#define DVFSRC_DDR_MD2SPM0_T (DVFSRC_BASE + 0xA54) +#define DVFSRC_DDR_MD2SPM1_T (DVFSRC_BASE + 0xA58) +#define DVFSRC_DDR_MD2SPM2_T (DVFSRC_BASE + 0xA5C) +#define DVFSRC_HRT_REQ_UNIT (DVFSRC_BASE + 0xA60) +#define DVSFRC_HRT_REQ_MD_URG (DVFSRC_BASE + 0xA64) +#define DVFSRC_HRT_REQ_MD_BW_0 (DVFSRC_BASE + 0xA68) +#define DVFSRC_HRT_REQ_MD_BW_1 (DVFSRC_BASE + 0xA6C) +#define DVFSRC_HRT_REQ_MD_BW_2 (DVFSRC_BASE + 0xA70) +#define DVFSRC_HRT_REQ_MD_BW_3 (DVFSRC_BASE + 0xA74) +#define DVFSRC_HRT_REQ_MD_BW_4 (DVFSRC_BASE + 0xA78) +#define DVFSRC_HRT_REQ_MD_BW_5 (DVFSRC_BASE + 0xA7C) +#define DVFSRC_HRT_REQ_MD_BW_6 (DVFSRC_BASE + 0xA80) +#define DVFSRC_HRT_REQ_MD_BW_7 (DVFSRC_BASE + 0xA84) +#define DVFSRC_HRT1_REQ_MD_BW_0 (DVFSRC_BASE + 0xA88) +#define DVFSRC_HRT1_REQ_MD_BW_1 (DVFSRC_BASE + 0xA8C) +#define DVFSRC_HRT1_REQ_MD_BW_2 (DVFSRC_BASE + 0xA90) +#define DVFSRC_HRT1_REQ_MD_BW_3 (DVFSRC_BASE + 0xA94) +#define DVFSRC_HRT1_REQ_MD_BW_4 (DVFSRC_BASE + 0xA98) +#define DVFSRC_HRT1_REQ_MD_BW_5 (DVFSRC_BASE + 0xA9C) +#define DVFSRC_HRT1_REQ_MD_BW_6 (DVFSRC_BASE + 0xAA0) +#define DVFSRC_HRT1_REQ_MD_BW_7 (DVFSRC_BASE + 0xAA4) +#define DVFSRC_HRT_REQ_MD_BW_8 (DVFSRC_BASE + 0xAA8) +#define DVFSRC_HRT_REQ_MD_BW_9 (DVFSRC_BASE + 0xAAC) +#define DVFSRC_HRT_REQ_MD_BW_10 (DVFSRC_BASE + 0xAB0) +#define DVFSRC_HRT1_REQ_MD_BW_8 (DVFSRC_BASE + 0xAB4) +#define DVFSRC_HRT1_REQ_MD_BW_9 (DVFSRC_BASE + 0xAB8) +#define DVFSRC_HRT1_REQ_MD_BW_10 (DVFSRC_BASE + 0xABC) +#define DVFSRC_HRT_REQ_BW_SW_REG (DVFSRC_BASE + 0xAC0) +#define DVFSRC_HRT_REQUEST (DVFSRC_BASE + 0xAC4) +#define DVFSRC_HRT_HIGH_2 (DVFSRC_BASE + 0xAC8) +#define DVFSRC_HRT_HIGH_1 (DVFSRC_BASE + 0xACC) +#define DVFSRC_HRT_HIGH (DVFSRC_BASE + 0xAD0) +#define DVFSRC_HRT_LOW_2 (DVFSRC_BASE + 0xAD4) +#define DVFSRC_HRT_LOW_1 (DVFSRC_BASE + 0xAD8) +#define DVFSRC_HRT_LOW (DVFSRC_BASE + 0xADC) +#define DVFSRC_DDR_ADD_REQUEST (DVFSRC_BASE + 0xAE0) +#define DVFSRC_LAST (DVFSRC_BASE + 0xAE4) +#define DVFSRC_LAST_L (DVFSRC_BASE + 0xAE8) +#define DVFSRC_MD_SCENARIO (DVFSRC_BASE + 0xAEC) +#define DVFSRC_RECORD_0_0 (DVFSRC_BASE + 0xAF0) +#define DVFSRC_RECORD_0_1 (DVFSRC_BASE + 0xAF4) +#define DVFSRC_RECORD_0_2 (DVFSRC_BASE + 0xAF8) +#define DVFSRC_RECORD_0_3 (DVFSRC_BASE + 0xAFC) +#define DVFSRC_RECORD_0_4 (DVFSRC_BASE + 0xB00) +#define DVFSRC_RECORD_0_5 (DVFSRC_BASE + 0xB04) +#define DVFSRC_RECORD_0_6 (DVFSRC_BASE + 0xB08) +#define DVFSRC_RECORD_0_7 (DVFSRC_BASE + 0xB0C) +#define DVFSRC_RECORD_0_L_0 (DVFSRC_BASE + 0xBF0) +#define DVFSRC_RECORD_0_L_1 (DVFSRC_BASE + 0xBF4) +#define DVFSRC_RECORD_0_L_2 (DVFSRC_BASE + 0xBF8) +#define DVFSRC_RECORD_0_L_3 (DVFSRC_BASE + 0xBFC) +#define DVFSRC_RECORD_0_L_4 (DVFSRC_BASE + 0xC00) +#define DVFSRC_RECORD_0_L_5 (DVFSRC_BASE + 0xC04) +#define DVFSRC_RECORD_0_L_6 (DVFSRC_BASE + 0xC08) +#define DVFSRC_RECORD_0_L_7 (DVFSRC_BASE + 0xC0C) +#define DVFSRC_EMI_REQUEST8 (DVFSRC_BASE + 0xCF0) +#define DVFSRC_DDR_REQUEST8 (DVFSRC_BASE + 0xCF4) +#define DVFSRC_EMI_HRT_2 (DVFSRC_BASE + 0xCF8) +#define DVFSRC_EMI_HRT2_2 (DVFSRC_BASE + 0xCFC) +#define DVFSRC_EMI_HRT3_2 (DVFSRC_BASE + 0xD00) +#define DVFSRC_EMI_QOS5 (DVFSRC_BASE + 0xD04) +#define DVFSRC_EMI_QOS6 (DVFSRC_BASE + 0xD08) +#define DVFSRC_DDR_HRT_2 (DVFSRC_BASE + 0xD0C) +#define DVFSRC_DDR_HRT2_2 (DVFSRC_BASE + 0xD10) +#define DVFSRC_DDR_HRT3_2 (DVFSRC_BASE + 0xD14) +#define DVFSRC_DDR_QOS5 (DVFSRC_BASE + 0xD18) +#define DVFSRC_DDR_QOS6 (DVFSRC_BASE + 0xD1C) +#define DVFSRC_VCORE_REQUEST5 (DVFSRC_BASE + 0xD20) +#define DVFSRC_VCORE_HRT_1 (DVFSRC_BASE + 0xD24) +#define DVFSRC_VCORE_HRT2_1 (DVFSRC_BASE + 0xD28) +#define DVFSRC_VCORE_HRT3_1 (DVFSRC_BASE + 0xD2C) +#define DVFSRC_VCORE_QOS3 (DVFSRC_BASE + 0xD30) +#define DVFSRC_VCORE_QOS4 (DVFSRC_BASE + 0xD34) +#define DVFSRC_HRT_HIGH_3 (DVFSRC_BASE + 0xD38) +#define DVFSRC_HRT_LOW_3 (DVFSRC_BASE + 0xD3C) +#define DVFSRC_BASIC_CONTROL_2 (DVFSRC_BASE + 0xD40) +#define DVFSRC_CURRENT_LEVEL (DVFSRC_BASE + 0xD44) +#define DVFSRC_TARGET_LEVEL (DVFSRC_BASE + 0xD48) +#define DVFSRC_LEVEL_LABEL_16_17 (DVFSRC_BASE + 0xD4C) +#define DVFSRC_LEVEL_LABEL_18_19 (DVFSRC_BASE + 0xD50) +#define DVFSRC_LEVEL_LABEL_20_21 (DVFSRC_BASE + 0xD54) +#define DVFSRC_LEVEL_LABEL_22_23 (DVFSRC_BASE + 0xD58) +#define DVFSRC_LEVEL_LABEL_24_25 (DVFSRC_BASE + 0xD5C) +#define DVFSRC_LEVEL_LABEL_26_27 (DVFSRC_BASE + 0xD60) +#define DVFSRC_LEVEL_LABEL_28_29 (DVFSRC_BASE + 0xD64) +#define DVFSRC_LEVEL_LABEL_30_31 (DVFSRC_BASE + 0xD68) +#define DVFSRC_CURRENT_FORCE (DVFSRC_BASE + 0xD6C) +#define DVFSRC_TARGET_FORCE (DVFSRC_BASE + 0xD70) +#define DVFSRC_EMI_ADD_REQUEST (DVFSRC_BASE + 0xD74) + +#endif /* __MT_SPM_VCOREFS__H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h new file mode 100644 index 0000000..ee3738d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SSPM_NOTIFIER_H +#define MT_SPM_SSPM_NOTIFIER_H + +enum MT_SPM_SSPM_NOTIFY_ID { + MT_SPM_NOTIFY_LP_ENTER, + MT_SPM_NOTIFY_LP_LEAVE, +}; + +int mt_spm_sspm_notify(int type, unsigned int lp_mode); + +static inline int mt_spm_sspm_notify_u32(int type, unsigned int lp_mode) +{ + return mt_spm_sspm_notify(type, lp_mode); +} +#endif /* MT_SPM_SSPM_NOTIFIER_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h new file mode 100644 index 0000000..6847e77 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SSPM_INTC_H +#define MT_SPM_SSPM_INTC_H + +#include + +#define MT_SPM_SSPM_INTC_SEL_0 0x10 +#define MT_SPM_SSPM_INTC_SEL_1 0x20 +#define MT_SPM_SSPM_INTC_SEL_2 0x40 +#define MT_SPM_SSPM_INTC_SEL_3 0x80 + +#define MT_SPM_SSPM_INTC_TRIGGER(id, sg) \ + (((0x10 << id) | (sg << id)) & 0xff) + +#define MT_SPM_SSPM_INTC0_HIGH MT_SPM_SSPM_INTC_TRIGGER(0, 1) +#define MT_SPM_SSPM_INTC0_LOW MT_SPM_SSPM_INTC_TRIGGER(0, 0) +#define MT_SPM_SSPM_INTC1_HIGH MT_SPM_SSPM_INTC_TRIGGER(1, 1) +#define MT_SPM_SSPM_INTC1_LOW MT_SPM_SSPM_INTC_TRIGGER(1, 0) +#define MT_SPM_SSPM_INTC2_HIGH MT_SPM_SSPM_INTC_TRIGGER(2, 1) +#define MT_SPM_SSPM_INTC2_LOW MT_SPM_SSPM_INTC_TRIGGER(2, 0) +#define MT_SPM_SSPM_INTC3_HIGH MT_SPM_SSPM_INTC_TRIGGER(3, 1) +#define MT_SPM_SSPM_INTC3_LOW MT_SPM_SSPM_INTC_TRIGGER(3, 0) + +#define DO_SPM_SSPM_LP_SUSPEND() \ + mmio_write_32(SPM_MD32_IRQ, MT_SPM_SSPM_INTC0_HIGH) +#define DO_SPM_SSPM_LP_RESUME() \ + mmio_write_32(SPM_MD32_IRQ, MT_SPM_SSPM_INTC0_LOW) +#endif /* MT_SPM_SSPM_INTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c new file mode 100644 index 0000000..a755a38 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#define MT_SPM_SSPM_MBOX_OFF(x) (SSPM_MBOX_BASE + x) +#define MT_SPM_MBOX(slot) MT_SPM_SSPM_MBOX_OFF((slot << 2UL)) + +#define SSPM_MBOX_SPM_LP_LOOKUP1 MT_SPM_MBOX(0) +#define SSPM_MBOX_SPM_LP_LOOKUP2 MT_SPM_MBOX(1) +#define SSPM_MBOX_SPM_LP1 MT_SPM_MBOX(2) +#define SSPM_MBOX_SPM_LP2 MT_SPM_MBOX(3) + +int mt_spm_sspm_notify(int type, unsigned int lp_mode) +{ + switch (type) { + case MT_SPM_NOTIFY_LP_ENTER: + mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode); + DO_SPM_SSPM_LP_SUSPEND(); + break; + case MT_SPM_NOTIFY_LP_LEAVE: + mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode); + DO_SPM_SSPM_LP_RESUME(); + break; + default: + break; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h new file mode 100644 index 0000000..fa77b95 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PCM_DEF_H +#define PCM_DEF_H + +/* + * Auto generated by DE, please DO NOT modify this file directly. + */ + +/* --- R0 Define --- */ +#define R0_SC_26M_CK_OFF (1U << 0) +#define R0_SC_TX_TRACK_RETRY_EN (1U << 1) +#define R0_SC_MEM_CK_OFF (1U << 2) +#define R0_SC_AXI_CK_OFF (1U << 3) +#define R0_SC_DR_SRAM_LOAD (1U << 4) +#define R0_SC_MD26M_CK_OFF (1U << 5) +#define R0_SC_DPY_MODE_SW (1U << 6) +#define R0_SC_DMSUS_OFF (1U << 7) +#define R0_SC_DPY_2ND_DLL_EN (1U << 8) +#define R0_SC_DR_SRAM_RESTORE (1U << 9) +#define R0_SC_MPLLOUT_OFF (1U << 10) +#define R0_SC_TX_TRACKING_DIS (1U << 11) +#define R0_SC_DPY_DLL_EN (1U << 12) +#define R0_SC_DPY_DLL_CK_EN (1U << 13) +#define R0_SC_DPY_VREF_EN (1U << 14) +#define R0_SC_PHYPLL_EN (1U << 15) +#define R0_SC_DDRPHY_FB_CK_EN (1U << 16) +#define R0_SC_DPY_BCLK_ENABLE (1U << 17) +#define R0_SC_MPLL_OFF (1U << 18) +#define R0_SC_SHU_RESTORE (1U << 19) +#define R0_SC_CKSQ0_OFF (1U << 20) +#define R0_SC_DR_SHU_LEVEL_SRAM_LATCH (1U << 21) +#define R0_SC_DR_SHU_EN (1U << 22) +#define R0_SC_DPHY_PRECAL_UP (1U << 23) +#define R0_SC_MPLL_S_OFF (1U << 24) +#define R0_SC_DPHY_RXDLY_TRACKING_EN (1U << 25) +#define R0_SC_PHYPLL_SHU_EN (1U << 26) +#define R0_SC_PHYPLL2_SHU_EN (1U << 27) +#define R0_SC_PHYPLL_MODE_SW (1U << 28) +#define R0_SC_PHYPLL2_MODE_SW (1U << 29) +#define R0_SC_DR_SHU_LEVEL0 (1U << 30) +#define R0_SC_DR_SHU_LEVEL1 (1U << 31) +/* --- R7 Define --- */ +#define R7_PWRAP_SLEEP_REQ (1U << 0) +#define R7_EMI_CLK_OFF_REQ (1U << 1) +#define R7_PCM_BUS_PROTECT_REQ (1U << 2) +#define R7_SPM_CK_UPDATE (1U << 3) +#define R7_SPM_CK_SEL0 (1U << 4) +#define R7_SPM_CK_SEL1 (1U << 5) +#define R7_SPM_LEAVE_DEEPIDLE_REQ (1U << 6) +#define R7_SC_FHC_PAUSE_MPLL (1U << 7) +#define R7_SC_26M_CK_SEL (1U << 8) +#define R7_PCM_TIMER_SET (1U << 9) +#define R7_PCM_TIMER_CLR (1U << 10) +#define R7_SPM_LEAVE_SUSPEND_REQ (1U << 11) +#define R7_CSYSPWRUPACK (1U << 12) +#define R7_PCM_IM_SLP_EN (1U << 13) +#define R7_SRCCLKENO0 (1U << 14) +#define R7_FORCE_DDR_EN_WAKE (1U << 15) +#define R7_SPM_APSRC_INTERNAL_ACK (1U << 16) +#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17) +#define R7_SC_AXI_DCM_DIS (1U << 18) +#define R7_SC_FHC_PAUSE_MEM (1U << 19) +#define R7_SC_FHC_PAUSE_MAIN (1U << 20) +#define R7_SRCCLKENO1 (1U << 21) +#define R7_PCM_WDT_KICK_P (1U << 22) +#define R7_SPM2EMI_S1_MODE_ASYNC (1U << 23) +#define R7_SC_DDR_PST_REQ_PCM (1U << 24) +#define R7_SC_DDR_PST_ABORT_REQ_PCM (1U << 25) +#define R7_PMIC_IRQ_REQ_EN (1U << 26) +#define R7_FORCE_F26M_WAKE (1U << 27) +#define R7_FORCE_APSRC_WAKE (1U << 28) +#define R7_FORCE_INFRA_WAKE (1U << 29) +#define R7_FORCE_VRF18_WAKE (1U << 30) +#define R7_SPM_DDR_EN_INTERNAL_ACK (1U << 31) +/* --- R12 Define --- */ +#define R12_PCM_TIMER (1U << 0) +#define R12_TWAM_IRQ_B (1U << 1) +#define R12_KP_IRQ_B (1U << 2) +#define R12_APWDT_EVENT_B (1U << 3) +#define R12_APXGPT1_EVENT_B (1U << 4) +#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5) +#define R12_EINT_EVENT_B (1U << 6) +#define R12_CONN_WDT_IRQ_B (1U << 7) +#define R12_CCIF0_EVENT_B (1U << 8) +#define R12_LOWBATTERY_IRQ_B (1U << 9) +#define R12_SSPM2SPM_WAKEUP_B (1U << 10) +#define R12_SCP2SPM_WAKEUP_B (1U << 11) +#define R12_ADSP2SPM_WAKEUP_B (1U << 12) +#define R12_PCM_WDT_WAKEUP_B (1U << 13) +#define R12_USBX_CDSC_B (1U << 14) +#define R12_USBX_POWERDWN_B (1U << 15) +#define R12_SYS_TIMER_EVENT_B (1U << 16) +#define R12_EINT_EVENT_SECURE_B (1U << 17) +#define R12_CCIF1_EVENT_B (1U << 18) +#define R12_UART0_IRQ_B (1U << 19) +#define R12_AFE_IRQ_MCU_B (1U << 20) +#define R12_THERM_CTRL_EVENT_B (1U << 21) +#define R12_SYS_CIRQ_IRQ_B (1U << 22) +#define R12_MD2AP_PEER_EVENT_B (1U << 23) +#define R12_CSYSPWREQ_B (1U << 24) +#define R12_MD1_WDT_B (1U << 25) +#define R12_CLDMA_EVENT_B (1U << 26) +#define R12_SEJ_EVENT_B (1U << 27) +#define R12_REG_CPU_WAKEUP (1U << 28) +#define R12_APUSYS_WAKE_HOST_B (1U << 29) +#define R12_NOT_USED1 (1U << 30) +#define R12_NOT_USED2 (1U << 31) +/* --- R12ext Define --- */ +#define R12EXT_26M_WAKE (1U << 0) +#define R12EXT_26M_SLEEP (1U << 1) +#define R12EXT_INFRA_WAKE (1U << 2) +#define R12EXT_INFRA_SLEEP (1U << 3) +#define R12EXT_APSRC_WAKE (1U << 4) +#define R12EXT_APSRC_SLEEP (1U << 5) +#define R12EXT_VRF18_WAKE (1U << 6) +#define R12EXT_VRF18_SLEEP (1U << 7) +#define R12EXT_DVFS_WAKE (1U << 8) +#define R12EXT_DDREN_WAKE (1U << 9) +#define R12EXT_DDREN_SLEEP (1U << 10) +#define R12EXT_MCU_PM_WFI (1U << 11) +#define R12EXT_SSPM_IDLE (1U << 12) +#define R12EXT_CONN_SRCCLKENB (1U << 13) +#define R12EXT_DRAMC_SSPM_WFI_MERGE (1U << 14) +#define R12EXT_SW_MAILBOX_WAKE (1U << 15) +#define R12EXT_SSPM_MAILBOX_WAKE (1U << 16) +#define R12EXT_ADSP_MAILBOX_WAKE (1U << 17) +#define R12EXT_SCP_MAILBOX_WAKE (1U << 18) +#define R12EXT_SPM_LEAVE_SUSPEND_ACK (1U << 19) +#define R12EXT_SPM_LEAVE_DEEPIDLE_ACK (1U << 20) +#define R12EXT_VS1_TRIGGER (1U << 21) +#define R12EXT_VS2_TRIGGER (1U << 22) +#define R12EXT_COROSS_REQ_APU (1U << 23) +#define R12EXT_CROSS_REQ_L3 (1U << 24) +#define R12EXT_DDR_PST_ACK (1U << 25) +#define R12EXT_BIT26 (1U << 26) +#define R12EXT_BIT27 (1U << 27) +#define R12EXT_BIT28 (1U << 28) +#define R12EXT_BIT29 (1U << 29) +#define R12EXT_BIT30 (1U << 30) +#define R12EXT_BIT31 (1U << 31) +/* --- R13 Define --- */ +#define R13_SRCCLKENI0 (1U << 0) +#define R13_SRCCLKENI1 (1U << 1) +#define R13_MD_SRCCLKENA_0 (1U << 2) +#define R13_MD_APSRC_REQ_0 (1U << 3) +#define R13_CONN_DDR_EN (1U << 4) +#define R13_MD_SRCCLKENA_1 (1U << 5) +#define R13_SSPM_SRCCLKENA (1U << 6) +#define R13_SSPM_APSRC_REQ (1U << 7) +#define R13_MD1_STATE (1U << 8) +#define R13_BIT9 (1U << 9) +#define R13_MM_STATE (1U << 10) +#define R13_SSPM_STATE (1U << 11) +#define R13_MD_DDR_EN_0 (1U << 12) +#define R13_CONN_STATE (1U << 13) +#define R13_CONN_SRCCLKENA (1U << 14) +#define R13_CONN_APSRC_REQ (1U << 15) +#define R13_SC_DDR_PST_ACK_ALL (1U << 16) +#define R13_SC_DDR_PST_ABORT_ACK_ALL (1U << 17) +#define R13_SCP_STATE (1U << 18) +#define R13_CSYSPWRUPREQ (1U << 19) +#define R13_PWRAP_SLEEP_ACK (1U << 20) +#define R13_SC_EMI_CLK_OFF_ACK_ALL (1U << 21) +#define R13_AUDIO_DSP_STATE (1U << 22) +#define R13_SC_DMDRAMCSHU_ACK_ALL (1U << 23) +#define R13_CONN_SRCCLKENB (1U << 24) +#define R13_SC_DR_SRAM_LOAD_ACK_ALL (1U << 25) +#define R13_SUBSYS_IDLE_SIGNALS0 (1U << 26) +#define R13_DVFS_STATE (1U << 27) +#define R13_SC_DR_SRAM_PLL_LOAD_ACK_ALL (1U << 28) +#define R13_SC_DR_SRAM_RESTORE_ACK_ALL (1U << 29) +#define R13_MD_VRF18_REQ_0 (1U << 30) +#define R13_DDR_EN_STATE (1U << 31) +#endif /* PCM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h new file mode 100644 index 0000000..2639b7e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SLEEP_DEF_H +#define SLEEP_DEF_H + +/* + * Auto generated by DE, please DO NOT modify this file directly. + */ + +/* --- SPM Flag Define --- */ +#define SPM_FLAG_DISABLE_CPU_PDN (1U << 0) +#define SPM_FLAG_DISABLE_INFRA_PDN (1U << 1) +#define SPM_FLAG_DISABLE_DDRPHY_PDN (1U << 2) +#define SPM_FLAG_DISABLE_VCORE_DVS (1U << 3) +#define SPM_FLAG_DISABLE_VCORE_DFS (1U << 4) +#define SPM_FLAG_DISABLE_COMMON_SCENARIO (1U << 5) +#define SPM_FLAG_DISABLE_BUS_CLK_OFF (1U << 6) +#define SPM_FLAG_DISABLE_ARMPLL_OFF (1U << 7) +#define SPM_FLAG_KEEP_CSYSPWRACK_HIGH (1U << 8) +#define SPM_FLAG_ENABLE_LVTS_WORKAROUND (1U << 9) +#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10) +#define SPM_FLAG_RESERVED_BIT11 (1U << 11) +#define SPM_FLAG_ENABLE_SPM_DBG_WDT_DUMP (1U << 12) +#define SPM_FLAG_USE_SRCCLKENO2 (1U << 13) +#define SPM_FLAG_ENABLE_6315_CTRL (1U << 14) +#define SPM_FLAG_ENABLE_TIA_WORKAROUND (1U << 15) +#define SPM_FLAG_DISABLE_SYSRAM_SLEEP (1U << 16) +#define SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP (1U << 17) +#define SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP (1U << 18) +#define SPM_FLAG_DISABLE_DRAMC_ISSUE_CMD (1U << 19) +#define SPM_FLAG_ENABLE_VOLTAGE_BIN (1U << 20) +#define SPM_FLAG_RESERVED_BIT21 (1U << 21) +#define SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP (1U << 22) +#define SPM_FLAG_DISABLE_DRAMC_MD32_BACKUP (1U << 23) +#define SPM_FLAG_RESERVED_BIT24 (1U << 24) +#define SPM_FLAG_RESERVED_BIT25 (1U << 25) +#define SPM_FLAG_RESERVED_BIT26 (1U << 26) +#define SPM_FLAG_VTCXO_STATE (1U << 27) +#define SPM_FLAG_INFRA_STATE (1U << 28) +#define SPM_FLAG_APSRC_STATE (1U << 29) +#define SPM_FLAG_VRF18_STATE (1U << 30) +#define SPM_FLAG_DDREN_STATE (1U << 31) +/* --- SPM Flag1 Define --- */ +#define SPM_FLAG1_DISABLE_AXI_BUS_TO_26M (1U << 0) +#define SPM_FLAG1_DISABLE_SYSPLL_OFF (1U << 1) +#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH (1U << 2) +#define SPM_FLAG1_DISABLE_ULPOSC_OFF (1U << 3) +#define SPM_FLAG1_FW_SET_ULPOSC_ON (1U << 4) +#define SPM_FLAG1_RESERVED_BIT5 (1U << 5) +#define SPM_FLAG1_ENABLE_REKICK (1U << 6) +#define SPM_FLAG1_RESERVED_BIT7 (1U << 7) +#define SPM_FLAG1_RESERVED_BIT8 (1U << 8) +#define SPM_FLAG1_RESERVED_BIT9 (1U << 9) +#define SPM_FLAG1_DISABLE_SRCLKEN_LOW (1U << 10) +#define SPM_FLAG1_DISABLE_SCP_CLK_SWITCH (1U << 11) +#define SPM_FLAG1_RESERVED_BIT12 (1U << 12) +#define SPM_FLAG1_RESERVED_BIT13 (1U << 13) +#define SPM_FLAG1_RESERVED_BIT14 (1U << 14) +#define SPM_FLAG1_RESERVED_BIT15 (1U << 15) +#define SPM_FLAG1_RESERVED_BIT16 (1U << 16) +#define SPM_FLAG1_RESERVED_BIT17 (1U << 17) +#define SPM_FLAG1_RESERVED_BIT18 (1U << 18) +#define SPM_FLAG1_RESERVED_BIT19 (1U << 19) +#define SPM_FLAG1_DISABLE_DEVAPC_SRAM_SLEEP (1U << 20) +#define SPM_FLAG1_RESERVED_BIT21 (1U << 21) +#define SPM_FLAG1_ENABLE_VS1_VOTER (1U << 22) +#define SPM_FLAG1_ENABLE_VS2_VOTER (1U << 23) +#define SPM_FLAG1_DISABLE_SCP_VREQ_MASK_CONTROL (1U << 24) +#define SPM_FLAG1_RESERVED_BIT25 (1U << 25) +#define SPM_FLAG1_RESERVED_BIT26 (1U << 26) +#define SPM_FLAG1_RESERVED_BIT27 (1U << 27) +#define SPM_FLAG1_RESERVED_BIT28 (1U << 28) +#define SPM_FLAG1_RESERVED_BIT29 (1U << 29) +#define SPM_FLAG1_RESERVED_BIT30 (1U << 30) +#define SPM_FLAG1_RESERVED_BIT31 (1U << 31) +/* --- SPM DEBUG Define --- */ +#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0) +#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1) +#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2) +#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3) +#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4) +#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5) +#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6) +#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7) +#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8) +#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9) +#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC (1U << 10) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_STATE (1U << 11) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_STATE (1U << 12) +#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN (1U << 13) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_STATE (1U << 14) +#define SPM_DBG_DEBUG_IDX_SYSRAM_SLP (1U << 15) +#define SPM_DBG_DEBUG_IDX_SYSRAM_ON (1U << 16) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_SLP (1U << 17) +#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_ON (1U << 18) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP (1U << 19) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_ON (1U << 20) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_SLP (1U << 21) +#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_ON (1U << 22) +#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P575V (1U << 23) +#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P600V (1U << 24) +#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P650V (1U << 25) +#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P725V (1U << 26) +#define SPM_DBG_DEBUG_IDX_SPM_GO_WAKEUP_NOW (1U << 27) +#define SPM_DBG_DEBUG_IDX_VTCXO_STATE (1U << 28) +#define SPM_DBG_DEBUG_IDX_INFRA_STATE (1U << 29) +#define SPM_DBG_DEBUG_IDX_VRR18_STATE (1U << 30) +#define SPM_DBG_DEBUG_IDX_APSRC_STATE (1U << 31) +/* --- SPM DEBUG1 Define --- */ +#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_LP (1U << 0) +#define SPM_DBG1_DEBUG_IDX_VCORE_DVFS_START (1U << 1) +#define SPM_DBG1_DEBUG_IDX_SYSPLL_OFF (1U << 2) +#define SPM_DBG1_DEBUG_IDX_SYSPLL_ON (1U << 3) +#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_VCORE_DVFS (1U << 4) +#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_OFF (1U << 5) +#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_ON (1U << 6) +#define SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT (1U << 7) +#define SPM_DBG1_RESERVED_BIT8 (1U << 8) +#define SPM_DBG1_DEBUG_IDX_INFRA_SUB_MTCMOS_OFF (1U << 9) +#define SPM_DBG1_DEBUG_IDX_INFRA_SUB_MTCMOS_ON (1U << 10) +#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_ULPOSC (1U << 11) +#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_26M (1U << 12) +#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_32K (1U << 13) +#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_26M (1U << 14) +#define SPM_DBG1_DEBUG_IDX_BUS_CLK_OFF (1U << 15) +#define SPM_DBG1_DEBUG_IDX_BUS_CLK_ON (1U << 16) +#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_LOW (1U << 17) +#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_HIGH (1U << 18) +#define SPM_DBG1_RESERVED_BIT19 (1U << 19) +#define SPM_DBG1_DEBUG_IDX_ULPOSC_IS_OFF_BUT_SHOULD_ON (1U << 20) +#define SPM_DBG1_DEBUG_IDX_6315_LOW (1U << 21) +#define SPM_DBG1_DEBUG_IDX_6315_HIGH (1U << 22) +#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT (1U << 23) +#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT (1U << 24) +#define SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT (1U << 25) +#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT (1U << 26) +#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT (1U << 27) +#define SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT (1U << 28) +#define SPM_DBG1_RESERVED_BIT29 (1U << 29) +#define SPM_DBG1_RESERVED_BIT30 (1U << 30) +#define SPM_DBG1_RESERVED_BIT31 (1U << 31) + + /* Macro and Inline */ +#define is_cpu_pdn(flags) (((flags) & SPM_FLAG_DISABLE_CPU_PDN) == 0U) +#define is_infra_pdn(flags) (((flags) & SPM_FLAG_DISABLE_INFRA_PDN) == 0U) +#define is_ddrphy_pdn(flags) (((flags) & SPM_FLAG_DISABLE_DDRPHY_PDN) == 0U) +#endif /* SLEEP_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c new file mode 100644 index 0000000..9b332a0 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + + +void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu) +{ + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); +} + +void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu) +{ + mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); +} + +void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr) +{ + assert(cluster == 0U); + + mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr); +} + +uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu) +{ + assert(cluster == 0U); + + return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR)); +} + +void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64) +{ + uint32_t reg; + + assert(cluster == 0U); + + reg = per_cluster(cluster, MCUCFG_INITARCH); + + if (arm64) { + mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); + } else { + mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); + } +} + +/** + * Return subsystem's power state. + * + * @mask: mask to MCUCFG_CPC_SPMC_PWR_STATUS to query the power state + * of one subsystem. + * RETURNS: + * 0 (the subsys was powered off) + * 1 (the subsys was powered on) + */ +bool spm_get_powerstate(uint32_t mask) +{ + return (mmio_read_32(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U; +} + +bool spm_get_cluster_powerstate(unsigned int cluster) +{ + assert(cluster == 0U); + + return spm_get_powerstate(BIT(14)); +} + +bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu) +{ + uint32_t mask = BIT(cpu); + + assert(cluster == 0U); + + return spm_get_powerstate(mask); +} + +int spmc_init(void) +{ + INFO("SPM: enable CPC mode\n"); + + mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN); + + mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B); + + mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); + mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); + mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); + + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN); + + return 0; +} + +/** + * Power on a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered on + * @cpu: the CPU ID of the CPU which to be powered on + */ +void spm_poweron_cpu(unsigned int cluster, unsigned int cpu) +{ + uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR); + + /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */ + if (cpu >= 4U) { + mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U); + } + + mmio_setbits_32(cpu_pwr_con, PWR_ON); + + while (!spm_get_cpu_powerstate(cluster, cpu)) { + mmio_clrbits_32(cpu_pwr_con, PWR_ON); + mmio_setbits_32(cpu_pwr_con, PWR_ON); + } +} + +/** + * Power off a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered off + * @cpu: the CPU ID of the CPU which to be powered off + */ +void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu) +{ + /* Set mp0_spmc_pwr_on_cpuX = 0 */ + mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); +} + +/** + * Power off a cluster with specified index + * + * @cluster: the cluster index which to be powered off + */ +void spm_poweroff_cluster(unsigned int cluster) +{ + /* No need to power on/off cluster on single cluster platform */ + assert(false); +} + +/** + * Power on a cluster with specified index + * + * @cluster: the cluster index which to be powered on + */ +void spm_poweron_cluster(unsigned int cluster) +{ + /* No need to power on/off cluster on single cluster platform */ + assert(false); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h new file mode 100644 index 0000000..34e93d0 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_H +#define MTSPMC_H + +#include + +int spmc_init(void); + +void spm_poweron_cpu(unsigned int cluster, unsigned int cpu); +void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu); + +void spm_poweroff_cluster(unsigned int cluster); +void spm_poweron_cluster(unsigned int cluster); + +bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu); +bool spm_get_cluster_powerstate(unsigned int cluster); +bool spm_get_powerstate(uint32_t mask); + +void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64); +void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr); +uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu); + +void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu); +void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu); + +#endif /* MTSPMC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000..bf4092e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_PRIVATE_H +#define MTSPMC_PRIVATE_H + +#include +#include + +unsigned long read_cpuectlr(void); +void write_cpuectlr(unsigned long cpuectlr); + +unsigned long read_cpupwrctlr_el1(void); +void write_cpupwrctlr_el1(unsigned long cpuectlr); + +/* + * per_cpu/cluster helper + */ +struct per_cpu_reg { + unsigned int cluster_addr; + unsigned int cpu_stride; +}; + +#define per_cpu(cluster, cpu, reg) \ + (reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride)) + +#define per_cluster(cluster, reg) (reg[cluster].cluster_addr) + +#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs)) +#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs)) +#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs)) + +/* === SPMC related registers */ +#define SPM_POWERON_CONFIG_EN SPM_REG(0x000) +/* bit-fields of SPM_POWERON_CONFIG_EN */ +#define PROJECT_CODE (U(0xb16) << 16) +#define BCLK_CG_EN BIT(0) + +#define SPM_PWR_STATUS SPM_REG(0x16c) +#define SPM_PWR_STATUS_2ND SPM_REG(0x170) +#define SPM_CPU_PWR_STATUS SPM_REG(0x174) + +/* bit-fields of SPM_PWR_STATUS */ +#define MD BIT(0) +#define CONN BIT(1) +#define DDRPHY BIT(2) +#define DISP BIT(3) +#define MFG BIT(4) +#define ISP BIT(5) +#define INFRA BIT(6) +#define VDEC BIT(7) +#define MP0_CPUTOP BIT(8) +#define MP0_CPU0 BIT(9) +#define MP0_CPU1 BIT(10) +#define MP0_CPU2 BIT(11) +#define MP0_CPU3 BIT(12) +#define MCUSYS BIT(14) +#define MP0_CPU4 BIT(15) +#define MP0_CPU5 BIT(16) +#define MP0_CPU6 BIT(17) +#define MP0_CPU7 BIT(18) +#define VEN BIT(21) + +/* === SPMC related registers */ +#define SPM_MCUSYS_PWR_CON MCUCFG_REG(0xd200) +#define SPM_MP0_CPUTOP_PWR_CON MCUCFG_REG(0xd204) +#define SPM_MP0_CPU0_PWR_CON MCUCFG_REG(0xd208) +#define SPM_MP0_CPU1_PWR_CON MCUCFG_REG(0xd20c) +#define SPM_MP0_CPU2_PWR_CON MCUCFG_REG(0xd210) +#define SPM_MP0_CPU3_PWR_CON MCUCFG_REG(0xd214) +#define SPM_MP0_CPU4_PWR_CON MCUCFG_REG(0xd218) +#define SPM_MP0_CPU5_PWR_CON MCUCFG_REG(0xd21c) +#define SPM_MP0_CPU6_PWR_CON MCUCFG_REG(0xd220) +#define SPM_MP0_CPU7_PWR_CON MCUCFG_REG(0xd224) + +/* bit fields of SPM_*_PWR_CON */ +#define PWR_ON_ACK BIT(31) +#define VPROC_EXT_OFF BIT(7) +#define DORMANT_EN BIT(6) +#define RESETPWRON_CONFIG BIT(5) +#define PWR_CLK_DIS BIT(4) +#define PWR_ON BIT(2) +#define PWR_RST_B BIT(0) + +/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */ +static const struct per_cpu_reg SPM_CPU_PWR[] = { + { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U } +}; + +/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */ +static const struct per_cpu_reg SPM_CLUSTER_PWR[] = { + { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U } +}; + +/* === MCUCFG related registers */ +/* aa64naa32 */ +#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4) +/* reset vectors */ +#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900) +#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908) +#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910) +#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918) +#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920) +#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928) +#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930) +#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938) + +/* MCUSYS DREQ BIG VPROC ISO control */ +#define DREQ20_BIG_VPROC_ISO MCUCFG_REG(0xad8c) + +/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */ +static const struct per_cpu_reg MCUCFG_BOOTADDR[] = { + { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U } +}; + +/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */ +static const struct per_cpu_reg MCUCFG_INITARCH[] = { + { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U } +}; + +#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu) +/* === CPC control */ +#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) +#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840) + +/* bit fields of CPC_FLOW_CTRL_CFG */ +#define CPC_CTRL_ENABLE BIT(16) +#define SSPM_CORE_PWR_ON_EN BIT(7) /* for cpu-hotplug */ +#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */ +#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu) + +/* bit fields of CPC_SPMC_PWR_STATUS */ +#define CORE_SPMC_PWR_ON_ACK GENMASK(11, 0) + +/* === APB Module infracfg_ao */ +#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220) +#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224) +#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228) +#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0) +#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4) +#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250) +#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254) +#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258) +#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8) +#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac) + +/* bit fields of INFRA_TOPAXI_PROTECTEN */ +#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12) +#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12)) + +/* === SPARK */ +#define VOLTAGE_04 U(0x40) +#define VOLTAGE_05 U(0x60) + +#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200) +#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334) +#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340) + +/* bit fields of CPU0_ILDO_CONTROL5 */ +#define ILDO_RET_VOSEL GENMASK(7, 0) + +/* bit fields of PTP3_CPU_SPMC_SW_CFG */ +#define SW_SPARK_EN BIT(0) + +/* bit fields of CPU0_ILDO_CONTROL8 */ +#define ILDO_BYPASS_B BIT(0) + +static const struct per_cpu_reg MCUCFG_SPARK[] = { + { .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U } +}; + +static const struct per_cpu_reg ILDO_CONTROL5[] = { + { .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U } +}; + +static const struct per_cpu_reg ILDO_CONTROL8[] = { + { .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U } +}; + +#endif /* MTSPMC_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h new file mode 100644 index 0000000..046cf73 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCUCFG_H +#define MCUCFG_H + +#ifndef __ASSEMBLER__ +#include +#endif /* __ASSEMBLER__ */ + +#include + +#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs)) + +#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8)) +#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8)) + +#define MP2_CPUCFG MCUCFG_REG(0x2208) + +#define MP2_CPU0_STANDBYWFE BIT(4) +#define MP2_CPU1_STANDBYWFE BIT(5) + +#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788) +#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C) +#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790) + +#define sw_spark_en BIT(0) +#define sw_no_wait_for_q_channel BIT(1) +#define sw_fsm_override BIT(2) +#define sw_logic_pre1_pdb BIT(3) +#define sw_logic_pre2_pdb BIT(4) +#define sw_logic_pdb BIT(5) +#define sw_iso BIT(6) +#define sw_sram_sleepb (U(0x3F) << 7) +#define sw_sram_isointb BIT(13) +#define sw_clk_dis BIT(14) +#define sw_ckiso BIT(15) +#define sw_pd (U(0x3F) << 16) +#define sw_hot_plug_reset BIT(22) +#define sw_pwr_on_override_en BIT(23) +#define sw_pwr_on BIT(24) +#define sw_coq_dis BIT(25) +#define logic_pdbo_all_off_ack BIT(26) +#define logic_pdbo_all_on_ack BIT(27) +#define logic_pre2_pdbo_all_on_ack BIT(28) +#define logic_pre1_pdbo_all_on_ack BIT(29) + + +#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \ + (MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4) + +#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30) +#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34) +#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38) +#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C) + +#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30) +#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34) +#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38) +#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C) + +#define cpu_sw_spark_en BIT(0) +#define cpu_sw_no_wait_for_q_channel BIT(1) +#define cpu_sw_fsm_override BIT(2) +#define cpu_sw_logic_pre1_pdb BIT(3) +#define cpu_sw_logic_pre2_pdb BIT(4) +#define cpu_sw_logic_pdb BIT(5) +#define cpu_sw_iso BIT(6) +#define cpu_sw_sram_sleepb BIT(7) +#define cpu_sw_sram_isointb BIT(8) +#define cpu_sw_clk_dis BIT(9) +#define cpu_sw_ckiso BIT(10) +#define cpu_sw_pd (U(0x1F) << 11) +#define cpu_sw_hot_plug_reset BIT(16) +#define cpu_sw_powr_on_override_en BIT(17) +#define cpu_sw_pwr_on BIT(18) +#define cpu_spark2ldo_allswoff BIT(19) +#define cpu_pdbo_all_on_ack BIT(20) +#define cpu_pre2_pdbo_allon_ack BIT(21) +#define cpu_pre1_pdbo_allon_ack BIT(22) + +/* CPC related registers */ +#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714) +#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804) +#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) +#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818) +#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c) +#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824) +#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828) +#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8) +#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac) +#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00) +#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04) +#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08) +#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c) +#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10) +#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14) +#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20) +#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70) +#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74) + +#define SPARK2LDO MCUCFG_REG(0x2700) +/* APB Module mcucfg */ +#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000) +#define MP0_AXI_CONFIG MCUCFG_REG(0x02C) +#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030) +#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034) +#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038) +#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8)) +#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C) +#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054) +#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064) + +#define MP0_RW_RSVD0 MCUCFG_REG(0x06C) + + +#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200) +#define MP1_AXI_CONFIG MCUCFG_REG(0x22C) +#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230) +#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234) +#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238) +#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8)) +#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C) +#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254) +#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264) + +#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740) +#define SYNC_DCM_CONFIG MCUCFG_REG(0x744) + +#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0) + +#define MP0_SPMC MCUCFG_REG(0x788) +#define MP1_SPMC MCUCFG_REG(0x78C) +#define MP2_AXI_CONFIG MCUCFG_REG(0x220C) +#define MP2_AXI_CONFIG_ACINACTM BIT(0) +#define MP2_AXI_CONFIG_AINACTS BIT(4) + +#define MPx_AXI_CONFIG_ACINACTM BIT(4) +#define MPx_AXI_CONFIG_AINACTS BIT(5) + +#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28) + +#define MP0_CPU0_STANDBYWFE BIT(20) +#define MP0_CPU1_STANDBYWFE BIT(21) +#define MP0_CPU2_STANDBYWFE BIT(22) +#define MP0_CPU3_STANDBYWFE BIT(23) + +#define MP1_CPU0_STANDBYWFE BIT(20) +#define MP1_CPU1_STANDBYWFE BIT(21) +#define MP1_CPU2_STANDBYWFE BIT(22) +#define MP1_CPU3_STANDBYWFE BIT(23) + +#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00) +#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04) +#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08) +#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00) +#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04) +#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08) + +#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008) +#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0) +#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4) + +#define MP2_COQ MCUCFG_REG(0x22BC) +#define MP2_COQ_SW_DIS BIT(0) + +#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400) +#define MP2_CA15M_MON_L MCUCFG_REG(0x2404) + +#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430) +#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438) +#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434) +#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C) + +#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068) +#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268) +#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C) + +#define MP2_SW_RST_B BIT(0) +#define MP2_TOPAON_APB_MASK BIT(1) + +#define B_SW_HOT_PLUG_RESET BIT(30) + +#define B_SW_PD_OFFSET 18U +#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET) + +#define B_SW_SRAM_SLEEPB_OFFSET 12U +#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET) + +#define B_SW_SRAM_ISOINTB BIT(9) +#define B_SW_ISO BIT(8) +#define B_SW_LOGIC_PDB BIT(7) +#define B_SW_LOGIC_PRE2_PDB BIT(6) +#define B_SW_LOGIC_PRE1_PDB BIT(5) +#define B_SW_FSM_OVERRIDE BIT(4) +#define B_SW_PWR_ON BIT(3) +#define B_SW_PWR_ON_OVERRIDE_EN BIT(2) + +#define B_FSM_STATE_OUT_OFFSET (6U) +#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET) +#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5) +#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4) +#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3) +#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2) + +#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET) +#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET) +#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET) + +#ifndef __ASSEMBLER__ +/* cpu boot mode */ +enum { + MP0_CPUCFG_64BIT_SHIFT = 12U, + MP1_CPUCFG_64BIT_SHIFT = 28U, + MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT, + MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT +}; + +enum { + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U, + + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT +}; + +enum { + MP1_AINACTS_SHIFT = 4U, + MP1_AINACTS = 1U << MP1_AINACTS_SHIFT +}; + +enum { + MP1_SW_CG_GEN_SHIFT = 12U, + MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT +}; + +enum { + MP1_L2RSTDISABLE_SHIFT = 14U, + MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT +}; +#endif /* __ASSEMBLER__ */ + +#endif /* MCUCFG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h new file mode 100644 index 0000000..ebc9fa0 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_HELPERS_H__ +#define __PLAT_HELPERS_H__ + +unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr); + +#endif /* __PLAT_HELPERS_H__ */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S new file mode 100644 index 0000000..39727ea --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception + * is taken in BL31. + * Clobbers: x0 - x10, x26, x27, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + /* TODO: leave implementation to GIC owner */ + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h new file mode 100644 index 0000000..347f358 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MTK_LPM_H +#define PLAT_MTK_LPM_H + +#include +#include + +#define MT_IRQ_REMAIN_MAX U(32) +#define MT_IRQ_REMAIN_CAT_LOG BIT(31) + +struct mt_irqremain { + unsigned int count; + unsigned int irqs[MT_IRQ_REMAIN_MAX]; + unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX]; + unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX]; +}; + +#define PLAT_RC_STATUS_READY BIT(0) +#define PLAT_RC_STATUS_FEATURE_EN BIT(1) +#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31) + +struct mt_lpm_tz { + int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state); + + int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state); + + int (*pwr_cluster_on)(unsigned int cpu, + const psci_power_state_t *state); + int (*pwr_cluster_dwn)(unsigned int cpu, + const psci_power_state_t *state); + + int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_mcusys_on_finished)(unsigned int cpu, + const psci_power_state_t *state); + int (*pwr_mcusys_dwn)(unsigned int cpu, + const psci_power_state_t *state); +}; + +const struct mt_lpm_tz *mt_plat_cpu_pm_init(void); + +#endif /* PLAT_MTK_LPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h new file mode 100644 index 0000000..a2881ce --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PM_H +#define PLAT_PM_H + +#include + +#define MT_PLAT_PWR_STATE_CPU U(1) +#define MT_PLAT_PWR_STATE_CLUSTER U(2) +#define MT_PLAT_PWR_STATE_MCUSYS U(3) +#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8) +#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9) + +#define MTK_LOCAL_STATE_RUN U(0) +#define MTK_LOCAL_STATE_RET U(1) +#define MTK_LOCAL_STATE_OFF U(2) + +#define MTK_AFFLVL_CPU U(0) +#define MTK_AFFLVL_CLUSTER U(1) +#define MTK_AFFLVL_MCUSYS U(2) +#define MTK_AFFLVL_SYSTEM U(3) + +#define IS_CLUSTER_OFF_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER]) +#define IS_MCUSYS_OFF_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS]) +#define IS_SYSTEM_SUSPEND_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM]) + +#define IS_PLAT_SUSPEND_ID(stateid)\ + ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \ + || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND)) + +#endif /* PLAT_PM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h new file mode 100644 index 0000000..7ef2b85 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h new file mode 100644 index 0000000..5562a67 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +/******************************************************************************* + * Plat SiP function constants + ******************************************************************************/ +#define MTK_PLAT_SIP_NUM_CALLS 6 + +/* DFD */ +#define MTK_SIP_KERNEL_DFD_AARCH32 0x82000205 +#define MTK_SIP_KERNEL_DFD_AARCH64 0xC2000205 + +/* DP/eDP */ +#define MTK_SIP_DP_CONTROL_AARCH32 0x82000523 +#define MTK_SIP_DP_CONTROL_AARCH64 0xC2000523 + +/* APUSYS SMC call */ +#define MTK_SIP_APUSYS_CONTROL_AARCH32 0x8200051E +#define MTK_SIP_APUSYS_CONTROL_AARCH64 0xC200051E + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h new file mode 100644 index 0000000..d4f2f83 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#define PLAT_PRIMARY_CPU 0x0 + +#define MT_GIC_BASE (0x0C000000) +#define MCUCFG_BASE (0x0C530000) +#define IO_PHYS (0x10000000) + +/* Aggregate of all devices for MMU mapping */ +#define MTK_DEV_RNG0_BASE IO_PHYS +#define MTK_DEV_RNG0_SIZE 0x10000000 +#define MTK_DEV_RNG2_BASE MT_GIC_BASE +#define MTK_DEV_RNG2_SIZE 0x600000 +#define MTK_MCDI_SRAM_BASE 0x11B000 +#define MTK_MCDI_SRAM_MAP_SIZE 0x1000 + +#define APUSYS_BASE 0x19000000 +#define APUSYS_SCTRL_REVISER_BASE 0x19021000 +#define APUSYS_SCTRL_REVISER_SIZE 0x1000 +#define APUSYS_APU_S_S_4_BASE 0x190F2000 +#define APUSYS_APU_S_S_4_SIZE 0x1000 +#define APUSYS_APU_PLL_BASE 0x190F3000 +#define APUSYS_APU_PLL_SIZE 0x1000 +#define APUSYS_APU_ACC_BASE 0x190F4000 +#define APUSYS_APU_ACC_SIZE 0x1000 + +#define TOPCKGEN_BASE (IO_PHYS + 0x00000000) +#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000) +#define SPM_BASE (IO_PHYS + 0x00006000) +#define RGU_BASE (IO_PHYS + 0x00007000) +#define APMIXEDSYS (IO_PHYS + 0x0000C000) +#define DRM_BASE (IO_PHYS + 0x0000D000) +#define SSPM_MBOX_BASE (IO_PHYS + 0x00480000) +#define PERICFG_AO_BASE (IO_PHYS + 0x01003000) +#define VPPSYS0_BASE (IO_PHYS + 0x04000000) +#define VPPSYS1_BASE (IO_PHYS + 0x04f00000) +#define VDOSYS0_BASE (IO_PHYS + 0x0C01A000) +#define VDOSYS1_BASE (IO_PHYS + 0x0C100000) +#define DVFSRC_BASE (IO_PHYS + 0x00012000) + +/******************************************************************************* + * DP/eDP related constants + ******************************************************************************/ +#define eDP_SEC_BASE (IO_PHYS + 0x0C504000) +#define DP_SEC_BASE (IO_PHYS + 0x0C604000) +#define eDP_SEC_SIZE 0x1000 +#define DP_SEC_SIZE 0x1000 + +/******************************************************************************* + * GPIO related constants + ******************************************************************************/ +#define GPIO_BASE (IO_PHYS + 0x00005000) +#define IOCFG_BM_BASE (IO_PHYS + 0x01D10000) +#define IOCFG_BL_BASE (IO_PHYS + 0x01D30000) +#define IOCFG_BR_BASE (IO_PHYS + 0x01D40000) +#define IOCFG_LM_BASE (IO_PHYS + 0x01E20000) +#define IOCFG_RB_BASE (IO_PHYS + 0x01EB0000) +#define IOCFG_TL_BASE (IO_PHYS + 0x01F40000) + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define UART0_BASE (IO_PHYS + 0x01001100) +#define UART1_BASE (IO_PHYS + 0x01001200) + +#define UART_BAUDRATE 115200 + +/******************************************************************************* + * PMIC related constants + ******************************************************************************/ +#define PMIC_WRAP_BASE (IO_PHYS + 0x00024000) + +/******************************************************************************* + * EMI MPU related constants + ******************************************************************************/ +#define EMI_MPU_BASE (IO_PHYS + 0x00226000) +#define SUB_EMI_MPU_BASE (IO_PHYS + 0x00225000) + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 13000000 +#define SYS_COUNTER_FREQ_IN_MHZ 13 + +/******************************************************************************* + * GIC-600 & interrupt handling related constants + ******************************************************************************/ +/* Base MTK_platform compatible GIC memory map */ +#define BASE_GICD_BASE MT_GIC_BASE +#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000) + +#define SYS_CIRQ_BASE (IO_PHYS + 0x204000) +#define CIRQ_REG_NUM 23 +#define CIRQ_IRQ_NUM 730 +#define CIRQ_SPI_START 96 +#define MD_WDT_IRQ_BIT_ID 141 +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ +#define PLATFORM_STACK_SIZE 0x800 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLAT_MAX_PWR_LVL U(3) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(9) + +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_MCUSYS_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(8) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) + +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8) + +#define SOC_CHIP_ID U(0x8195) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +#define TZRAM_BASE 0x54600000 +#define TZRAM_SIZE 0x00030000 + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL3-1 debug size plus a + * little space for growth. + */ +#define BL31_BASE (TZRAM_BASE + 0x1000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 16 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h new file mode 100644 index 0000000..a9c7bc8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RTC_H +#define RTC_H + +#include + +#endif /* RTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c new file mode 100644 index 0000000..b77ab27 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* common headers */ +#include + +#include +#include +#include +#include + +/* platform specific headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Cluster state request: + * [0] : The CPU requires cluster power down + * [1] : The CPU requires cluster power on + */ +#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff) +#define coordinate_cluster_pwron() coordinate_cluster(1) +#define coordinate_cluster_pwroff() coordinate_cluster(0) + +/* platform secure entry point */ +static uintptr_t secure_entrypoint; +/* per-CPU power state */ +static unsigned int plat_power_state[PLATFORM_CORE_COUNT]; + +/* platform CPU power domain - ops */ +static const struct mt_lpm_tz *plat_mt_pm; + +#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \ + int ret = -1; \ + if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \ + ret = plat_mt_pm->_name(_cpu, _state); \ + } \ + ret; }) + +#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \ + if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \ + (void) plat_mt_pm->_name(_cpu, _state); \ + } \ + }) + +/* + * Common MTK_platform operations to power on/off a + * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_cpu_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state); + + if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) || + (req_pstate == 0U)) { /* hotplug off */ + coordinate_cluster_pwroff(); + } + + /* Prevent interrupts from spuriously waking up this CPU */ + mt_gic_rdistif_save(); + gicv3_cpuif_disable(cpu); + gicv3_rdistif_off(cpu); +} + +static void plat_cpu_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state); + + coordinate_cluster_pwron(); + + /* PTP3 config */ + ptp3_core_init(cpu); + + /* + * If mcusys does power down before then restore + * all CPUs' GIC Redistributors + */ + if (IS_MCUSYS_OFF_STATE(state)) { + mt_gic_rdistif_restore_all(); + } else { + gicv3_rdistif_on(cpu); + gicv3_cpuif_enable(cpu); + mt_gic_rdistif_init(); + mt_gic_rdistif_restore(); + } +} + +/* + * Common MTK_platform operations to power on/off a + * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_cluster_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) { + coordinate_cluster_pwron(); + + /* TODO: return on fail. + * Add a 'return' here before adding any code following + * the if-block. + */ + } +} + +static void plat_cluster_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) { + /* TODO: return on fail. + * Add a 'return' here before adding any code following + * the if-block. + */ + } +} + +/* + * Common MTK_platform operations to power on/off a + * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_mcusys_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) { + return; /* return on fail */ + } + + mt_gic_distif_save(); + gic_sgi_save_all(); +} + +static void plat_mcusys_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) { + return; /* return on fail */ + } + + mt_gic_init(); + mt_gic_distif_restore(); + gic_sgi_restore_all(); + + dfd_resume(); + + plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state); +} + +/* + * plat_psci_ops implementation + */ + +static void plat_cpu_standby(plat_local_state_t cpu_state) +{ + uint64_t scr; + + scr = read_scr_el3(); + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + isb(); + dsb(); + wfi(); + + write_scr_el3(scr); +} + +static int plat_power_domain_on(u_register_t mpidr) +{ + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + unsigned int cluster = 0U; + + if (cpu >= PLATFORM_CORE_COUNT) { + return PSCI_E_INVALID_PARAMS; + } + + if (!spm_get_cluster_powerstate(cluster)) { + spm_poweron_cluster(cluster); + } + + /* init CPU reset arch as AARCH64 */ + mcucfg_init_archstate(cluster, cpu, true); + mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint); + spm_poweron_cpu(cluster, cpu); + + return PSCI_E_SUCCESS; +} + +static void plat_power_domain_on_finish(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + + assert(cpu < PLATFORM_CORE_COUNT); + + /* Allow IRQs to wakeup this core in IDLE flow */ + mcucfg_enable_gic_wakeup(0U, cpu); + + if (IS_CLUSTER_OFF_STATE(state)) { + plat_cluster_pwron_common(cpu, state, 0U); + } + + plat_cpu_pwron_common(cpu, state, 0U); +} + +static void plat_power_domain_off(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + + assert(cpu < PLATFORM_CORE_COUNT); + + plat_cpu_pwrdwn_common(cpu, state, 0U); + spm_poweroff_cpu(0U, cpu); + + /* prevent unintended IRQs from waking up the hot-unplugged core */ + mcucfg_disable_gic_wakeup(0U, cpu); + + if (IS_CLUSTER_OFF_STATE(state)) { + plat_cluster_pwrdwn_common(cpu, state, 0U); + } +} + +static void plat_power_domain_suspend(const psci_power_state_t *state) +{ + unsigned int cpu = plat_my_core_pos(); + + assert(cpu < PLATFORM_CORE_COUNT); + + plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state); + + /* Perform the common CPU specific operations */ + plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]); + + if (IS_CLUSTER_OFF_STATE(state)) { + /* Perform the common cluster specific operations */ + plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]); + } + + if (IS_MCUSYS_OFF_STATE(state)) { + /* Perform the common mcusys specific operations */ + plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]); + } +} + +static void plat_power_domain_suspend_finish(const psci_power_state_t *state) +{ + unsigned int cpu = plat_my_core_pos(); + + assert(cpu < PLATFORM_CORE_COUNT); + + if (IS_MCUSYS_OFF_STATE(state)) { + /* Perform the common mcusys specific operations */ + plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]); + } + + if (IS_CLUSTER_OFF_STATE(state)) { + /* Perform the common cluster specific operations */ + plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]); + } + + /* Perform the common CPU specific operations */ + plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]); + + plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state); +} + +static int plat_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int pstate = psci_get_pstate_type(power_state); + unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state); + unsigned int cpu = plat_my_core_pos(); + + if (aff_lvl > PLAT_MAX_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + + if (pstate == PSTATE_TYPE_STANDBY) { + req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE; + } else { + unsigned int i; + unsigned int pstate_id = psci_get_pstate_id(power_state); + plat_local_state_t s = MTK_LOCAL_STATE_OFF; + + /* Use pstate_id to be power domain state */ + if (pstate_id > s) { + s = (plat_local_state_t)pstate_id; + } + + for (i = 0U; i <= aff_lvl; i++) { + req_state->pwr_domain_state[i] = s; + } + } + + plat_power_state[cpu] = power_state; + return PSCI_E_SUCCESS; +} + +static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int lv; + unsigned int cpu = plat_my_core_pos(); + + for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) { + req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE; + } + + plat_power_state[cpu] = + psci_make_powerstate( + MT_PLAT_PWR_STATE_SYSTEM_SUSPEND, + PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL); + + flush_dcache_range((uintptr_t) + &plat_power_state[cpu], + sizeof(plat_power_state[cpu])); +} + +/******************************************************************************* + * MTK handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 plat_mtk_system_reset(void) +{ + struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset(); + + INFO("MTK System Reset\n"); + + gpio_set_value(gpio_reset->index, gpio_reset->polarity); + + wfi(); + ERROR("MTK System Reset: operation not handled.\n"); + panic(); +} + +static void __dead2 plat_mtk_system_off(void) +{ + INFO("MTK System Off\n"); + + rtc_power_off_sequence(); + pmic_power_off(); + + wfi(); + ERROR("MTK System Off: operation not handled.\n"); + panic(); +} + +static const plat_psci_ops_t plat_psci_ops = { + .system_reset = plat_mtk_system_reset, + .system_off = plat_mtk_system_off, + .cpu_standby = plat_cpu_standby, + .pwr_domain_on = plat_power_domain_on, + .pwr_domain_on_finish = plat_power_domain_on_finish, + .pwr_domain_off = plat_power_domain_off, + .pwr_domain_suspend = plat_power_domain_suspend, + .pwr_domain_suspend_finish = plat_power_domain_suspend_finish, + .validate_power_state = plat_validate_power_state, + .get_sys_suspend_power_state = plat_get_sys_suspend_power_state +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &plat_psci_ops; + secure_entrypoint = sec_entrypoint; + + /* + * init the warm reset config for boot CPU + * reset arch as AARCH64 + * reset addr as function bl31_warm_entrypoint() + */ + mcucfg_init_archstate(0U, 0U, true); + mcucfg_set_bootaddr(0U, 0U, secure_entrypoint); + + spmc_init(); + plat_mt_pm = mt_plat_cpu_pm_init(); + + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c b/arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c new file mode 100644 index 0000000..7d3c512 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "plat_sip_calls.h" + +uintptr_t mediatek_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) +{ + int32_t ret; + uint32_t ret_val; + + switch (smc_fid) { + case MTK_SIP_DP_CONTROL_AARCH32: + case MTK_SIP_DP_CONTROL_AARCH64: + ret = dp_secure_handler(x1, x2, &ret_val); + SMC_RET2(handle, ret, ret_val); + break; + case MTK_SIP_VCORE_CONTROL_ARCH32: + case MTK_SIP_VCORE_CONTROL_ARCH64: + ret = spm_vcorefs_v2_args(x1, x2, x3, &x4); + SMC_RET2(handle, ret, x4); + break; + case MTK_SIP_KERNEL_DFD_AARCH32: + case MTK_SIP_KERNEL_DFD_AARCH64: + ret = dfd_smc_dispatcher(x1, x2, x3, x4); + SMC_RET1(handle, ret); + break; + case MTK_SIP_APUSYS_CONTROL_AARCH32: + case MTK_SIP_APUSYS_CONTROL_AARCH64: + ret = apusys_kernel_ctrl(x1, x2, x3, x4, &ret_val); + SMC_RET2(handle, ret, ret_val); + break; + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c new file mode 100644 index 0000000..bc95c64 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +const unsigned char mtk_power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* Number of children for the root node */ + PLATFORM_MCUSYS_COUNT, + /* Number of children for the mcusys node */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return mtk_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + if ((read_mpidr() & MPIDR_MT_MASK) != 0) { + /* ARMv8.2 arch */ + if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0) { + return -1; + } + return plat_mediatek_calc_core_pos(mpidr); + } + + mpidr &= MPIDR_AFFINITY_MASK; + + if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) { + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return (cpu_id + (cluster_id * 8)); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8195/platform.mk new file mode 100644 index 0000000..a81c093 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/platform.mk @@ -0,0 +1,108 @@ +# +# Copyright (c) 2021, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MTK_PLAT := plat/mediatek +MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} + +PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT}/common/drivers/gic600/ \ + -I${MTK_PLAT}/common/drivers/gpio/ \ + -I${MTK_PLAT}/common/drivers/rtc/ \ + -I${MTK_PLAT}/common/drivers/timer/ \ + -I${MTK_PLAT}/common/drivers/uart/ \ + -I${MTK_PLAT}/common/lpm/ \ + -I${MTK_PLAT_SOC}/drivers/apusys/ \ + -I${MTK_PLAT_SOC}/drivers/dcm \ + -I${MTK_PLAT_SOC}/drivers/dfd \ + -I${MTK_PLAT_SOC}/drivers/dp/ \ + -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \ + -I${MTK_PLAT_SOC}/drivers/gpio/ \ + -I${MTK_PLAT_SOC}/drivers/mcdi/ \ + -I${MTK_PLAT_SOC}/drivers/pmic/ \ + -I${MTK_PLAT_SOC}/drivers/spmc/ \ + -I${MTK_PLAT_SOC}/drivers/ptp3/ \ + -I${MTK_PLAT_SOC}/include/ + +GICV3_SUPPORT_GIC600 := 1 +include drivers/arm/gic/v3/gicv3.mk +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} \ + plat/common/aarch64/crash_console_helpers.S \ + plat/common/plat_psci_common.c + + +BL31_SOURCES += common/desc_image_load.c \ + drivers/delay_timer/delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/bl_aux_params/bl_aux_params.c \ + lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a78.S \ + plat/common/plat_gicv3.c \ + ${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c \ + ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_mt6359p.c \ + ${MTK_PLAT}/common/drivers/timer/mt_timer.c \ + ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/lpm/mt_lp_rm.c \ + ${MTK_PLAT}/common/mtk_cirq.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/params_setup.c \ + ${MTK_PLAT_SOC}/aarch64/platform_common.c \ + ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ + ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/drivers/apusys/apupll.c \ + ${MTK_PLAT_SOC}/drivers/apusys/apupwr_clkctl.c \ + ${MTK_PLAT_SOC}/drivers/apusys/mtk_apusys.c \ + ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \ + ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \ + ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \ + ${MTK_PLAT_SOC}/drivers/dp/mt_dp.c \ + ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \ + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_lp_irqremain.c \ + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ + ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \ + ${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.c \ + ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \ + ${MTK_PLAT_SOC}/plat_pm.c \ + ${MTK_PLAT_SOC}/plat_sip_calls.c \ + ${MTK_PLAT_SOC}/plat_topology.c + +# Build SPM drivers +include ${MTK_PLAT_SOC}/drivers/spm/build.mk + +# Configs for A78 and A55 +HW_ASSISTED_COHERENCY := 1 +USE_COHERENT_MEM := 0 +CTX_INCLUDE_AARCH32_REGS := 0 +ERRATA_A55_1530923 := 1 + +ERRATA_A78_1688305 := 1 +ERRATA_A78_1941498 := 1 +ERRATA_A78_1951500 := 1 +ERRATA_A78_1821534 := 1 +ERRATA_A78_2132060 := 1 +ERRATA_A78_2242635 := 1 + +# indicate the reset vector address can be programmed +PROGRAMMABLE_RESET_ADDRESS := 1 + +COLD_BOOT_SINGLE_CPU := 1 + +MACH_MT8195 := 1 +$(eval $(call add_define,MACH_MT8195)) + +include lib/coreboot/coreboot.mk diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S new file mode 100644 index 0000000..d630f1f --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MIDR_PN_CORTEX_A57 0xD07 + + +/******************************************************************************* + * Implementation defined ACTLR_EL3 bit definitions + ******************************************************************************/ +#define ACTLR_ELx_L2ACTLR_BIT (U(1) << 6) +#define ACTLR_ELx_L2ECTLR_BIT (U(1) << 5) +#define ACTLR_ELx_L2CTLR_BIT (U(1) << 4) +#define ACTLR_ELx_CPUECTLR_BIT (U(1) << 1) +#define ACTLR_ELx_CPUACTLR_BIT (U(1) << 0) +#define ACTLR_ELx_ENABLE_ALL_ACCESS (ACTLR_ELx_L2ACTLR_BIT | \ + ACTLR_ELx_L2ECTLR_BIT | \ + ACTLR_ELx_L2CTLR_BIT | \ + ACTLR_ELx_CPUECTLR_BIT | \ + ACTLR_ELx_CPUACTLR_BIT) + + /* Global functions */ + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .globl platform_mem_init + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .weak plat_core_pos_by_mpidr + .globl tegra_secure_entrypoint + .globl plat_reset_handler + + /* Global variables */ + .globl tegra_sec_entry_point + .globl ns_image_entrypoint + .globl tegra_bl31_phys_base + .globl tegra_console_base + + /* --------------------- + * Common CPU init code + * --------------------- + */ +.macro cpu_init_common + + /* ------------------------------------------------ + * We enable procesor retention, L2/CPUECTLR NS + * access and ECC/Parity protection for A57 CPUs + * ------------------------------------------------ + */ + mrs x0, midr_el1 + mov x1, #(MIDR_PN_MASK << MIDR_PN_SHIFT) + and x0, x0, x1 + lsr x0, x0, #MIDR_PN_SHIFT + cmp x0, #MIDR_PN_CORTEX_A57 + b.ne 1f + + /* --------------------------- + * Enable processor retention + * --------------------------- + */ + mrs x0, CORTEX_A57_L2ECTLR_EL1 + mov x1, #RETENTION_ENTRY_TICKS_512 + bic x0, x0, #CORTEX_A57_L2ECTLR_RET_CTRL_MASK + orr x0, x0, x1 + msr CORTEX_A57_L2ECTLR_EL1, x0 + isb + + mrs x0, CORTEX_A57_ECTLR_EL1 + mov x1, #RETENTION_ENTRY_TICKS_512 + bic x0, x0, #CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK + orr x0, x0, x1 + msr CORTEX_A57_ECTLR_EL1, x0 + isb + + /* ------------------------------------------------------- + * Enable L2 and CPU ECTLR RW access from non-secure world + * ------------------------------------------------------- + */ + mrs x0, actlr_el3 + mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS + orr x0, x0, x1 + msr actlr_el3, x0 + mrs x0, actlr_el2 + mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS + orr x0, x0, x1 + msr actlr_el2, x0 + isb + + /* -------------------------------- + * Enable the cycle count register + * -------------------------------- + */ +1: mrs x0, pmcr_el0 + ubfx x0, x0, #11, #5 // read PMCR.N field + mov x1, #1 + lsl x0, x1, x0 + sub x0, x0, #1 // mask of event counters + orr x0, x0, #0x80000000 // disable overflow intrs + msr pmintenclr_el1, x0 + msr pmuserenr_el0, x1 // enable user mode access + + /* ---------------------------------------------------------------- + * Allow non-privileged access to CNTVCT: Set CNTKCTL (Kernel Count + * register), bit 1 (EL0VCTEN) to enable access to CNTVCT/CNTFRQ + * registers from EL0. + * ---------------------------------------------------------------- + */ + mrs x0, cntkctl_el1 + orr x0, x0, #EL0VCTEN_BIT + msr cntkctl_el1, x0 +.endm + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary(void); + * + * This function checks if this is the Primary CPU + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #TEGRA_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ---------------------------------------------------------- + * unsigned int plat_my_core_pos(void); + * + * result: CorePos = CoreId + (ClusterId * cpus per cluster) + * Registers clobbered: x0, x8 + * ---------------------------------------------------------- + */ +func plat_my_core_pos + mov x8, x30 + mrs x0, mpidr_el1 + bl plat_core_pos_by_mpidr + ret x8 +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between + * a cold and warm boot. If the tegra_sec_entry_point for + * this CPU is present, then it's a warm boot. + * + * ----------------------------------------------------- + */ +func plat_get_my_entrypoint + adr x1, tegra_sec_entry_point + ldr x0, [x1] + ret +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset. Right + * now this is a stub function. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + mov x0, #0 + ret +endfunc plat_secondary_cold_boot_setup + + /* -------------------------------------------------------- + * void platform_mem_init (void); + * + * Any memory init, relocation to be done before the + * platform boots. Called very early in the boot process. + * -------------------------------------------------------- + */ +func platform_mem_init + mov x0, #0 + ret +endfunc platform_mem_init + + /* --------------------------------------------------- + * Function to handle a platform reset and store + * input parameters passed by BL2. + * --------------------------------------------------- + */ +func plat_reset_handler + +#if !ENABLE_PIE + /* ---------------------------------------------------- + * Verify if we are running from BL31_BASE address + * ---------------------------------------------------- + */ + adr x18, bl31_entrypoint + mov x17, #BL31_BASE + cmp x18, x17 + b.eq 1f + + /* ---------------------------------------------------- + * Copy the entire BL31 code to BL31_BASE if we are not + * running from it already + * ---------------------------------------------------- + */ + mov x0, x17 + mov x1, x18 + adr x2, __STACKS_END__ + sub x2, x2, x18 + +_loop16: + cmp x2, #16 + b.lo _loop1 + ldp x3, x4, [x1], #16 + stp x3, x4, [x0], #16 + sub x2, x2, #16 + b _loop16 + /* copy byte per byte */ +_loop1: + cbz x2, _end + ldrb w3, [x1], #1 + strb w3, [x0], #1 + subs x2, x2, #1 + b.ne _loop1 + + /* ---------------------------------------------------- + * Jump to BL31_BASE and start execution again + * ---------------------------------------------------- + */ +_end: mov x0, x20 + mov x1, x21 + br x17 +1: +#endif + + /* ----------------------------------- + * derive and save the phys_base addr + * ----------------------------------- + */ + adr x17, tegra_bl31_phys_base + ldr x18, [x17] + cbnz x18, 1f + adr x18, bl31_entrypoint + str x18, [x17] + +1: cpu_init_common + + ret +endfunc plat_reset_handler + +/* Helper macro for CoreId calculation */ +#define PLATFORM_MAX_CPUS_PER_SOCKET (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) + + /* ------------------------------------------------------ + * int32_t plat_core_pos_by_mpidr(u_register_t mpidr) + * + * This function implements a part of the critical + * interface between the psci generic layer and the + * platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error + * code (-1) is returned in case the MPIDR is invalid. + * + * Clobbers: x0-x4 + * ------------------------------------------------------ + */ +func plat_core_pos_by_mpidr + lsr x1, x0, #TEGRA_CORE_AFFINITY + and x1, x1, #MPIDR_AFFLVL_MASK /* core id */ + lsr x2, x0, #TEGRA_CLUSTER_AFFINITY + and x2, x2, #MPIDR_AFFLVL_MASK /* cluster id */ +#ifdef PLATFORM_SOCKET_COUNT + lsr x3, x0, #TEGRA_SOCKET_AFFINITY + and x3, x3, #MPIDR_AFFLVL_MASK /* socket id */ +#endif + /* core_id >= PLATFORM_MAX_CPUS_PER_CLUSTER */ + mov x0, #-1 + cmp x1, #(PLATFORM_MAX_CPUS_PER_CLUSTER - 1) + b.gt 1f + + /* cluster_id >= PLATFORM_CLUSTER_COUNT */ + cmp x2, #(PLATFORM_CLUSTER_COUNT - 1) + b.gt 1f + +#ifdef PLATFORM_SOCKET_COUNT + /* socket_id >= PLATFORM_SOCKET_COUNT */ + cmp x3, #(PLATFORM_SOCKET_COUNT - 1) + b.gt 1f +#endif + + /* CorePos = CoreId + (ClusterId * cpus per cluster) */ + mov x4, #PLATFORM_MAX_CPUS_PER_CLUSTER + mul x4, x4, x2 + add x0, x1, x4 + +#ifdef PLATFORM_SOCKET_COUNT + /* CorePos = CoreId + (SocketId * cpus per socket) */ + mov x1, #PLATFORM_MAX_CPUS_PER_SOCKET + mov x1, #84 + mul x3, x3, x1 + add x0, x0, x3 +#endif + +1: + ret +endfunc plat_core_pos_by_mpidr + + /* ---------------------------------------- + * Secure entrypoint function for CPU boot + * ---------------------------------------- + */ +func tegra_secure_entrypoint _align=6 + +#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT + + /* -------------------------------------------------------- + * Skip the invalidate BTB workaround for Tegra210B01 SKUs. + * -------------------------------------------------------- + */ + mov x0, #TEGRA_MISC_BASE + add x0, x0, #HARDWARE_REVISION_OFFSET + ldr w1, [x0] + lsr w1, w1, #CHIP_ID_SHIFT + and w1, w1, #CHIP_ID_MASK + cmp w1, #TEGRA_CHIPID_TEGRA21 /* T210? */ + b.ne 2f + ldr w1, [x0] + lsr w1, w1, #MAJOR_VERSION_SHIFT + and w1, w1, #MAJOR_VERSION_MASK + cmp w1, #0x02 /* T210 B01? */ + b.eq 2f + + /* ------------------------------------------------------- + * Invalidate BTB along with I$ to remove any stale + * entries from the branch predictor array. + * ------------------------------------------------------- + */ + mrs x0, CORTEX_A57_CPUACTLR_EL1 + orr x0, x0, #1 + msr CORTEX_A57_CPUACTLR_EL1, x0 /* invalidate BTB and I$ together */ + dsb sy + isb + ic iallu /* actual invalidate */ + dsb sy + isb + + mrs x0, CORTEX_A57_CPUACTLR_EL1 + bic x0, x0, #1 + msr CORTEX_A57_CPUACTLR_EL1, X0 /* restore original CPUACTLR_EL1 */ + dsb sy + isb + + .rept 7 + nop /* wait */ + .endr + + /* ----------------------------------------------- + * Extract OSLK bit and check if it is '1'. This + * bit remains '0' for A53 on warm-resets. If '1', + * turn off regional clock gating and request warm + * reset. + * ----------------------------------------------- + */ + mrs x0, oslsr_el1 + and x0, x0, #2 + mrs x1, mpidr_el1 + bics xzr, x0, x1, lsr #7 /* 0 = slow cluster or warm reset */ + b.eq restore_oslock + mov x0, xzr + msr oslar_el1, x0 /* os lock stays 0 across warm reset */ + mov x3, #3 + movz x4, #0x8000, lsl #48 + msr CORTEX_A57_CPUACTLR_EL1, x4 /* turn off RCG */ + isb + msr rmr_el3, x3 /* request warm reset */ + isb + dsb sy +1: wfi + b 1b + + /* -------------------------------------------------- + * These nops are here so that speculative execution + * won't harm us before we are done with warm reset. + * -------------------------------------------------- + */ + .rept 65 + nop + .endr +2: + /* -------------------------------------------------- + * Do not insert instructions here + * -------------------------------------------------- + */ +#endif + + /* -------------------------------------------------- + * Restore OS Lock bit + * -------------------------------------------------- + */ +restore_oslock: + mov x0, #1 + msr oslar_el1, x0 + + /* -------------------------------------------------- + * Get secure world's entry point and jump to it + * -------------------------------------------------- + */ + bl plat_get_my_entrypoint + br x0 +endfunc tegra_secure_entrypoint + + .data + .align 3 + + /* -------------------------------------------------- + * CPU Secure entry point - resume from suspend + * -------------------------------------------------- + */ +tegra_sec_entry_point: + .quad 0 + + /* -------------------------------------------------- + * NS world's cold boot entry point + * -------------------------------------------------- + */ +ns_image_entrypoint: + .quad 0 + + /* -------------------------------------------------- + * BL31's physical base address + * -------------------------------------------------- + */ +tegra_bl31_phys_base: + .quad 0 + + /* -------------------------------------------------- + * UART controller base for console init + * -------------------------------------------------- + */ +tegra_console_base: + .quad 0 diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c new file mode 100644 index 0000000..431e685 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2015-2020, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* length of Trusty's input parameters (in bytes) */ +#define TRUSTY_PARAMS_LEN_BYTES (4096*2) + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted SRAM + ******************************************************************************/ +IMPORT_SYM(uint64_t, __RW_START__, BL31_RW_START); + +extern uint64_t tegra_bl31_phys_base; + +static entry_point_info_t bl33_image_ep_info, bl32_image_ep_info; +static plat_params_from_bl2_t plat_bl31_params_from_bl2 = { + .tzdram_size = TZDRAM_SIZE +}; +#ifdef SPD_trusty +static aapcs64_params_t bl32_args; +#endif + +/******************************************************************************* + * This variable holds the non-secure image entry address + ******************************************************************************/ +extern uint64_t ns_image_entrypoint; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *ep = NULL; + + /* return BL32 entry point info if it is valid */ + if (type == NON_SECURE) { + ep = &bl33_image_ep_info; + } else if ((type == SECURE) && (bl32_image_ep_info.pc != 0U)) { + ep = &bl32_image_ep_info; + } + + return ep; +} + +/******************************************************************************* + * Return a pointer to the 'plat_params_from_bl2_t' structure. The BL2 image + * passes this platform specific information. + ******************************************************************************/ +plat_params_from_bl2_t *bl31_get_plat_params(void) +{ + return &plat_bl31_params_from_bl2; +} + +/******************************************************************************* + * Perform any BL31 specific platform actions. Populate the BL33 and BL32 image + * info. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct tegra_bl31_params *arg_from_bl2 = (struct tegra_bl31_params *) arg0; + plat_params_from_bl2_t *plat_params = (plat_params_from_bl2_t *)arg1; + int32_t ret; + + /* + * For RESET_TO_BL31 systems, BL31 is the first bootloader to run so + * there's no argument to relay from a previous bootloader. Platforms + * might use custom ways to get arguments. + */ + if (arg_from_bl2 == NULL) { + arg_from_bl2 = plat_get_bl31_params(); + } + if (plat_params == NULL) { + plat_params = plat_get_bl31_plat_params(); + } + + /* + * Copy BL3-3, BL3-2 entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + assert(arg_from_bl2 != NULL); + assert(arg_from_bl2->bl33_ep_info != NULL); + bl33_image_ep_info = *arg_from_bl2->bl33_ep_info; + + if (arg_from_bl2->bl32_ep_info != NULL) { + bl32_image_ep_info = *arg_from_bl2->bl32_ep_info; +#ifdef SPD_trusty + /* save BL32 boot parameters */ + memcpy(&bl32_args, &arg_from_bl2->bl32_ep_info->args, sizeof(bl32_args)); +#endif + } + + /* + * Parse platform specific parameters + */ + assert(plat_params != NULL); + plat_bl31_params_from_bl2.tzdram_base = plat_params->tzdram_base; + plat_bl31_params_from_bl2.tzdram_size = plat_params->tzdram_size; + plat_bl31_params_from_bl2.uart_id = plat_params->uart_id; + plat_bl31_params_from_bl2.l2_ecc_parity_prot_dis = plat_params->l2_ecc_parity_prot_dis; + plat_bl31_params_from_bl2.sc7entry_fw_size = plat_params->sc7entry_fw_size; + plat_bl31_params_from_bl2.sc7entry_fw_base = plat_params->sc7entry_fw_base; + + /* + * Enable console for the platform + */ + plat_enable_console(plat_params->uart_id); + + /* + * The previous bootloader passes the base address of the shared memory + * location to store the boot profiler logs. Sanity check the + * address and initialise the profiler library, if it looks ok. + */ + ret = bl31_check_ns_address(plat_params->boot_profiler_shmem_base, + PROFILER_SIZE_BYTES); + if (ret == (int32_t)0) { + + /* store the membase for the profiler lib */ + plat_bl31_params_from_bl2.boot_profiler_shmem_base = + plat_params->boot_profiler_shmem_base; + + /* initialise the profiler library */ + boot_profiler_init(plat_params->boot_profiler_shmem_base, + TEGRA_TMRUS_BASE); + } + + /* + * Add timestamp for platform early setup entry. + */ + boot_profiler_add_record("[TF] early setup entry"); + + /* + * Initialize delay timer + */ + tegra_delay_timer_init(); + + /* Early platform setup for Tegra SoCs */ + plat_early_platform_setup(); + + /* + * Add timestamp for platform early setup exit. + */ + boot_profiler_add_record("[TF] early setup exit"); + + INFO("BL3-1: Boot CPU: %s Processor [%lx]\n", + (((read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK) + == DENVER_IMPL) ? "Denver" : "ARM", read_mpidr()); +} + +#ifdef SPD_trusty +void plat_trusty_set_boot_args(aapcs64_params_t *args) +{ + /* + * arg0 = TZDRAM aperture available for BL32 + * arg1 = BL32 boot params + * arg2 = EKS Blob Length + * arg3 = Boot Profiler Carveout Base + */ + args->arg0 = bl32_args.arg0; + args->arg1 = bl32_args.arg2; + + /* update EKS size */ + args->arg2 = bl32_args.arg4; + + /* Profiler Carveout Base */ + args->arg3 = bl32_args.arg5; +} +#endif + +/******************************************************************************* + * Initialize the gic, configure the SCR. + ******************************************************************************/ +void bl31_platform_setup(void) +{ + /* + * Add timestamp for platform setup entry. + */ + boot_profiler_add_record("[TF] plat setup entry"); + + /* Initialize the gic cpu and distributor interfaces */ + plat_gic_setup(); + + /* + * Setup secondary CPU POR infrastructure. + */ + plat_secondary_setup(); + + /* + * Initial Memory Controller configuration. + */ + tegra_memctrl_setup(); + + /* + * Late setup handler to allow platforms to performs additional + * functionality. + * This handler gets called with MMU enabled. + */ + plat_late_platform_setup(); + + /* + * Add timestamp for platform setup exit. + */ + boot_profiler_add_record("[TF] plat setup exit"); + + INFO("BL3-1: Tegra platform setup complete\n"); +} + +/******************************************************************************* + * Perform any BL3-1 platform runtime setup prior to BL3-1 cold boot exit + ******************************************************************************/ +void bl31_plat_runtime_setup(void) +{ + /* + * Platform specific runtime setup + */ + plat_runtime_setup(); + + /* + * Add final timestamp before exiting BL31. + */ + boot_profiler_add_record("[TF] bl31 exit"); + boot_profiler_deinit(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + uint64_t rw_start = BL31_RW_START; + uint64_t rw_size = BL_END - BL31_RW_START; + uint64_t rodata_start = BL_RO_DATA_BASE; + uint64_t rodata_size = BL_RO_DATA_END - BL_RO_DATA_BASE; + uint64_t code_base = BL_CODE_BASE; + uint64_t code_size = BL_CODE_END - BL_CODE_BASE; + const mmap_region_t *plat_mmio_map = NULL; + + /* + * Add timestamp for arch setup entry. + */ + boot_profiler_add_record("[TF] arch setup entry"); + + /* add MMIO space */ + plat_mmio_map = plat_get_mmio_map(); + if (plat_mmio_map != NULL) { + mmap_add(plat_mmio_map); + } else { + WARN("MMIO map not available\n"); + } + + /* add memory regions */ + mmap_add_region(rw_start, rw_start, + rw_size, + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(rodata_start, rodata_start, + rodata_size, + MT_RO_DATA | MT_SECURE); + mmap_add_region(code_base, code_base, + code_size, + MT_CODE | MT_SECURE); + + /* set up translation tables */ + init_xlat_tables(); + + /* enable the MMU */ + enable_mmu_el3(0); + + /* + * Add timestamp for arch setup exit. + */ + boot_profiler_add_record("[TF] arch setup exit"); + + INFO("BL3-1: Tegra: MMU enabled\n"); +} + +/******************************************************************************* + * Check if the given NS DRAM range is valid + ******************************************************************************/ +int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes) +{ + uint64_t end = base + size_in_bytes - U(1); + + /* + * Sanity check the input values + */ + if ((base == 0U) || (size_in_bytes == 0U)) { + ERROR("NS address 0x%" PRIx64 " (%" PRId64 " bytes) is invalid\n", + base, size_in_bytes); + return -EINVAL; + } + + /* + * Check if the NS DRAM address is valid + */ + if ((base < TEGRA_DRAM_BASE) || (base >= TEGRA_DRAM_END) || + (end > TEGRA_DRAM_END)) { + + ERROR("NS address 0x%" PRIx64 " is out-of-bounds!\n", base); + return -EFAULT; + } + + /* + * TZDRAM aperture contains the BL31 and BL32 images, so we need + * to check if the NS DRAM range overlaps the TZDRAM aperture. + */ + if ((base < (uint64_t)TZDRAM_END) && (end > tegra_bl31_phys_base)) { + ERROR("NS address 0x%" PRIx64 " overlaps TZDRAM!\n", base); + return -ENOTSUP; + } + + /* valid NS address */ + return 0; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_common.mk b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_common.mk new file mode 100644 index 0000000..2607a06 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_common.mk @@ -0,0 +1,55 @@ +# +# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020, NVIDIA Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/nvidia/tegra/include/drivers \ + -Iplat/nvidia/tegra/include/lib \ + -Iplat/nvidia/tegra/include + +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +TEGRA_COMMON := plat/nvidia/tegra/common +TEGRA_DRIVERS := plat/nvidia/tegra/drivers +TEGRA_LIBS := plat/nvidia/tegra/lib + +# Enable support for GIC600 +GICV3_SUPPORT_GIC600 := 1 +GICV3_OVERRIDE_DISTIF_PWR_OPS := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk +TEGRA_GICv3_SOURCES := $(GICV3_SOURCES) \ + plat/common/plat_gicv3.c \ + ${TEGRA_COMMON}/tegra_gicv3.c + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +TEGRA_GICv2_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + ${TEGRA_COMMON}/tegra_gicv2.c + +BL31_SOURCES += drivers/delay_timer/delay_timer.c \ + drivers/io/io_storage.c \ + plat/common/aarch64/crash_console_helpers.S \ + ${TEGRA_COMMON}/aarch64/tegra_helpers.S \ + ${TEGRA_LIBS}/debug/profiler.c \ + ${TEGRA_COMMON}/tegra_bl31_setup.c \ + ${TEGRA_COMMON}/tegra_delay_timer.c \ + ${TEGRA_COMMON}/tegra_fiq_glue.c \ + ${TEGRA_COMMON}/tegra_io_storage.c \ + ${TEGRA_COMMON}/tegra_platform.c \ + ${TEGRA_COMMON}/tegra_pm.c \ + ${TEGRA_COMMON}/tegra_sip_calls.c \ + ${TEGRA_COMMON}/tegra_sdei.c + +ifneq ($(ENABLE_STACK_PROTECTOR), 0) +BL31_SOURCES += ${TEGRA_COMMON}/tegra_stack_protector.c +endif +ifeq (${EL3_EXCEPTION_HANDLING},1) +BL31_SOURCES += plat/common/aarch64/plat_ehf.c +endif diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c new file mode 100644 index 0000000..d9547c4 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2017, 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 + +static uint32_t tegra_timer_get_value(void) +{ + /* enable cntps_tval_el1 timer, mask interrupt */ + write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT); + + /* + * Generic delay timer implementation expects the timer to be a down + * counter. The value is clipped from 64 to 32 bits. + */ + return (uint32_t)(read_cntps_tval_el1()); +} + +/* + * Initialise the architecture provided counter as the delay timer. + */ +void tegra_delay_timer_init(void) +{ + static timer_ops_t tegra_timer_ops; + + /* Value in ticks */ + uint32_t multiplier = MHZ_TICKS_PER_SEC; + + /* Value in ticks per second (Hz) */ + uint32_t divider = plat_get_syscnt_freq2(); + + /* Reduce multiplier and divider by dividing them repeatedly by 10 */ + while (((multiplier % 10U) == 0U) && ((divider % 10U) == 0U)) { + multiplier /= 10U; + divider /= 10U; + } + + /* enable cntps_tval_el1 timer, mask interrupt */ + write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT); + + /* register the timer */ + tegra_timer_ops.get_timer_value = tegra_timer_get_value; + tegra_timer_ops.clk_mult = multiplier; + tegra_timer_ops.clk_div = divider; + timer_init(&tegra_timer_ops); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c new file mode 100644 index 0000000..5309d98 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c @@ -0,0 +1,149 @@ +/* + * 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 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if ENABLE_WDT_LEGACY_FIQ_HANDLING +#include +#endif +#include +#include + +/* Legacy FIQ used by earlier Tegra platforms */ +#define LEGACY_FIQ_PPI_WDT 28U + +/******************************************************************************* + * Static variables + ******************************************************************************/ +static uint64_t ns_fiq_handler_addr; +static uint32_t fiq_handler_active; +static pcpu_fiq_state_t fiq_state[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Handler for FIQ interrupts + ******************************************************************************/ +static int tegra_fiq_interrupt_handler(unsigned int id, unsigned int flags, + void *handle, void *cookie) +{ + cpu_context_t *ctx = cm_get_context(NON_SECURE); + el3_state_t *el3state_ctx = get_el3state_ctx(ctx); + uint32_t cpu = plat_my_core_pos(); + + (void)flags; + (void)handle; + (void)cookie; + + /* + * Jump to NS world only if the NS world's FIQ handler has + * been registered + */ + if (ns_fiq_handler_addr != 0U) { + + /* + * The FIQ was generated when the execution was in the non-secure + * world. Save the context registers to start with. + */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * Save elr_el3 and spsr_el3 from the saved context, and overwrite + * the context with the NS fiq_handler_addr and SPSR value. + */ + fiq_state[cpu].elr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3)); + fiq_state[cpu].spsr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_SPSR_EL3)); + + /* + * Set the new ELR to continue execution in the NS world using the + * FIQ handler registered earlier. + */ + cm_set_elr_el3(NON_SECURE, ns_fiq_handler_addr); + } + +#if ENABLE_WDT_LEGACY_FIQ_HANDLING + /* + * Tegra platforms that use LEGACY_FIQ as the watchdog timer FIQ + * need to issue an IPI to other CPUs, to allow them to handle + * the "system hung" scenario. This interrupt is passed to the GICD + * via the Flow Controller. So, once we receive this interrupt, + * disable the routing so that we can mark it as "complete" in the + * GIC later. + */ + if (id == LEGACY_FIQ_PPI_WDT) { + tegra_fc_disable_fiq_to_ccplex_routing(); + } +#endif + + /* + * Mark this interrupt as complete to avoid a FIQ storm. + */ + plat_ic_end_of_interrupt(id); + + return 0; +} + +/******************************************************************************* + * Setup handler for FIQ interrupts + ******************************************************************************/ +void tegra_fiq_handler_setup(void) +{ + /* return if already registered */ + if (fiq_handler_active == 0U) { + /* + * Register an interrupt handler for FIQ interrupts generated for + * NS interrupt sources + */ + ehf_register_priority_handler(PLAT_TEGRA_WDT_PRIO, tegra_fiq_interrupt_handler); + + /* handler is now active */ + fiq_handler_active = 1; + } +} + +/******************************************************************************* + * Validate and store NS world's entrypoint for FIQ interrupts + ******************************************************************************/ +void tegra_fiq_set_ns_entrypoint(uint64_t entrypoint) +{ + ns_fiq_handler_addr = entrypoint; +} + +/******************************************************************************* + * Handler to return the NS EL1/EL0 CPU context + ******************************************************************************/ +int32_t tegra_fiq_get_intr_context(void) +{ + cpu_context_t *ctx = cm_get_context(NON_SECURE); + gp_regs_t *gpregs_ctx = get_gpregs_ctx(ctx); + const el1_sysregs_t *el1state_ctx = get_el1_sysregs_ctx(ctx); + uint32_t cpu = plat_my_core_pos(); + uint64_t val; + + /* + * We store the ELR_EL3, SPSR_EL3, SP_EL0 and SP_EL1 registers so + * that el3_exit() sends these values back to the NS world. + */ + write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X0), (fiq_state[cpu].elr_el3)); + write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X1), (fiq_state[cpu].spsr_el3)); + + val = read_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_SP_EL0)); + write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X2), (val)); + + val = read_ctx_reg((el1state_ctx), (uint32_t)(CTX_SP_EL1)); + write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X3), (val)); + + return 0; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c new file mode 100644 index 0000000..7ff0954 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include + +static unsigned int tegra_target_masks[PLATFORM_CORE_COUNT]; + +/* Help function to register platform specific structure base address */ +void tegra_gic_register_ctx_ptr(uintptr_t *redist_ptr, uintptr_t *dist_ptr) +{ + ; /* do nohting */ +} + +/****************************************************************************** + * Tegra common helper to setup the GICv2 driver data. + *****************************************************************************/ +void tegra_gic_setup(const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + /* + * Tegra GIC configuration settings + */ + static gicv2_driver_data_t tegra_gic_data; + + /* + * Register Tegra GICv2 driver + */ + tegra_gic_data.gicd_base = TEGRA_GICD_BASE; + tegra_gic_data.gicc_base = TEGRA_GICC_BASE; + tegra_gic_data.interrupt_props = interrupt_props; + tegra_gic_data.interrupt_props_num = interrupt_props_num; + tegra_gic_data.target_masks = tegra_target_masks; + tegra_gic_data.target_masks_num = ARRAY_SIZE(tegra_target_masks); + gicv2_driver_init(&tegra_gic_data); +} + +/****************************************************************************** + * Tegra common helper to initialize the GICv2 only driver. + *****************************************************************************/ +void tegra_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Tegra common helper to disable the GICv2 CPU interface + *****************************************************************************/ +void tegra_gic_cpuif_deactivate(void) +{ + gicv2_cpuif_disable(); +} + +/****************************************************************************** + * Tegra common helper to initialize the per cpu distributor interface + * in GICv2 + *****************************************************************************/ +void tegra_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Tegra helper to save & restore the GICv2 on resume from CPU or system suspend + *****************************************************************************/ +void tegra_gic_save(uint32_t pstate_id) +{ + ; /* do nohting */ +} + +void tegra_gic_restore(uint32_t pstate_id) +{ + if (pstate_id == PSTATE_ID_SOC_POWERDN) { + gicv2_distif_init(); + } + tegra_gic_pcpu_init(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c new file mode 100644 index 0000000..31d7ef5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +/* Default GICR base address to be used for GICR probe. */ +static const uintptr_t gicr_base_addrs[2] = { + TEGRA_GICR_BASE, /* GICR Base address of the primary CPU */ + 0U /* Zero Termination */ +}; + +/* List of zero terminated GICR frame addresses which CPUs will probe */ +static const uintptr_t *tegra_gicr_frames = gicr_base_addrs; + +/* + * We save and restore the GICv3 context on CPU suspend and system suspend. + */ +static gicv3_redist_ctx_t rdist_ctx; +static gicv3_dist_ctx_t dist_ctx; + +/* Pointers to platform specific structs to save the context */ +static gicv3_redist_ctx_t *plat_redist_ctx; +static gicv3_dist_ctx_t *plat_dist_ctx; + +/* Help function to register platform specific structure base address */ +void tegra_gic_register_ctx_ptr(uintptr_t *redist_ptr, uintptr_t *dist_ptr) +{ + assert(redist_ptr != NULL); + assert(dist_ptr != NULL); + plat_redist_ctx = (gicv3_redist_ctx_t *)redist_ptr; + plat_dist_ctx = (gicv3_dist_ctx_t *)dist_ptr; +} + +/* + * Override default implementation of 'arm_gicv3_distif_pre_save' + * and 'arm_gicv3_distif_post_restore' functions. + */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) +{ + ; /* do nothing */ +} + +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) +{ + ; /* do nothing */ +} + +static unsigned int plat_tegra_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +/* + * By default, gicr_frames will be pointing to gicr_base_addrs. If + * the platform supports a non-contiguous GICR frames (GICR frames located + * at uneven offset), plat_arm_override_gicr_frames function can be used by + * such platform to override the gicr_frames. + */ +void tegra_gicv3_override_gicr_frames(const uintptr_t *plat_gicr_frames) +{ + assert(plat_gicr_frames != NULL); + tegra_gicr_frames = plat_gicr_frames; +} + +/****************************************************************************** + * Tegra common helper to setup the GICv3 driver data. + *****************************************************************************/ +void tegra_gic_setup(const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + /* + * Tegra GIC configuration settings + */ + static gicv3_driver_data_t tegra_gic_data; + + /* + * Register Tegra GICv3 driver + */ + tegra_gic_data.gicd_base = TEGRA_GICD_BASE; + tegra_gic_data.gicr_base = 0U; + tegra_gic_data.rdistif_num = PLATFORM_CORE_COUNT; + tegra_gic_data.rdistif_base_addrs = rdistif_base_addrs; + tegra_gic_data.mpidr_to_core_pos = plat_tegra_mpidr_to_core_pos; + tegra_gic_data.interrupt_props = interrupt_props; + tegra_gic_data.interrupt_props_num = interrupt_props_num; + gicv3_driver_init(&tegra_gic_data); + + if (gicv3_rdistif_probe(tegra_gicr_frames[0]) == -1) { + ERROR("No GICR base frame found for Primary CPU\n"); + panic(); + } +} + +/****************************************************************************** + * Tegra common helper to initialize the GICv3 only driver. + *****************************************************************************/ +void tegra_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Tegra common helper to disable the GICv3 CPU interface + *****************************************************************************/ +void tegra_gic_cpuif_deactivate(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/****************************************************************************** + * Tegra common helper to initialize the per cpu distributor interface + * in GICv3 + *****************************************************************************/ +void tegra_gic_pcpu_init(void) +{ + int result; + const uintptr_t *gicr_frames = tegra_gicr_frames; + + do { + result = gicv3_rdistif_probe(*gicr_frames); + + /* If the probe is successful, no need to proceed further */ + if (result == 0) { + break; + } + + gicr_frames++; + } while (*gicr_frames != 0U); + + if (result == -1) { + ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); + panic(); + } + + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Tegra helper to save & restore the GICv3 on resume from CPU or system suspend + *****************************************************************************/ +void tegra_gic_save(uint32_t pstate_id) +{ + gicv3_redist_ctx_t *local_rdist_base; + gicv3_dist_ctx_t *local_dist_base; + + /* + * Check the platform redist and dist ctx, + * if they are not NULL, use platform specific + * structures to do the save. + */ + local_rdist_base = (plat_redist_ctx == NULL) ? &rdist_ctx : plat_redist_ctx; + local_dist_base = (plat_dist_ctx == NULL) ? &dist_ctx : plat_dist_ctx; + + if (pstate_id == PSTATE_ID_SOC_POWERDN) { + /* + * Save the GIC Redistributors and ITS contexts before the + * Distributor context. we only need to save the context of the CPU + * that is issuing the CPU or SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_save(plat_my_core_pos(), local_rdist_base); + + /* Save the GIC Distributor context */ + gicv3_distif_save(local_dist_base); + } + + /* + * From here, all the components of the GIC can be safely powered down + * as long as there is an alternate way to handle wakeup interrupt + * sources. + */ +} + +void tegra_gic_restore(uint32_t pstate_id) +{ + gicv3_redist_ctx_t *local_rdist_base; + gicv3_dist_ctx_t *local_dist_base; + + /* + * Check the platform redist and dist ctx, + * if they are not NULL, use platform specific + * structures to do the restore. + */ + local_rdist_base = (plat_redist_ctx == NULL) ? &rdist_ctx : plat_redist_ctx; + local_dist_base = (plat_dist_ctx == NULL) ? &dist_ctx : plat_dist_ctx; + + if (pstate_id == PSTATE_ID_SOC_POWERDN) { + /* Restore the GIC Distributor context */ + gicv3_distif_init_restore(local_dist_base); + + /* + * Restore the GIC Redistributor and ITS contexts after the + * Distributor context. we only need to restore the context of the CPU + * that is issuing the CPU or SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_init_restore(plat_my_core_pos(), local_rdist_base); + } + + /* Re-enable the GIC CPU interface*/ + gicv3_cpuif_enable(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c new file mode 100644 index 0000000..21641aa --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy. + * + * This function is not supported at this time + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + return -ENOTSUP; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c new file mode 100644 index 0000000..bd7d871 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define TEGRA_APKEY_FIXED_PATTERN U(0x55AAAA5555AAAA55) + +/* + * This is only a toy implementation to generate a fixed 128-bit key + * from sp, x30 and fix values. + * + * A production system must re-implement this function to generate + * keys from a reliable randomness source. + */ +uint128_t plat_init_apkey(void) +{ + uint64_t return_addr = (uint64_t)__builtin_return_address(0U); + uint64_t frame_addr = (uint64_t)__builtin_frame_address(0U); + uint64_t fixed_pattern = TEGRA_APKEY_FIXED_PATTERN; + + /* Generate 128-bit key */ + uint64_t key_lo = (return_addr << 13) ^ frame_addr ^ fixed_pattern; + uint64_t key_hi = (frame_addr << 15) ^ return_addr ^ fixed_pattern; + + return ((uint128_t)(key_hi) << 64) | key_lo; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c new file mode 100644 index 0000000..2888ee2 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Tegra platforms + ******************************************************************************/ +typedef enum tegra_platform { + TEGRA_PLATFORM_SILICON = 0U, + TEGRA_PLATFORM_QT, + TEGRA_PLATFORM_FPGA, + TEGRA_PLATFORM_EMULATION, + TEGRA_PLATFORM_LINSIM, + TEGRA_PLATFORM_UNIT_FPGA, + TEGRA_PLATFORM_VIRT_DEV_KIT, + TEGRA_PLATFORM_VSP, + TEGRA_PLATFORM_MAX, +} tegra_platform_t; + +/******************************************************************************* + * Tegra macros defining all the SoC minor versions + ******************************************************************************/ +#define TEGRA_MINOR_QT U(0) +#define TEGRA_MINOR_FPGA U(1) +#define TEGRA_MINOR_ASIM_QT U(2) +#define TEGRA_MINOR_ASIM_LINSIM U(3) +#define TEGRA_MINOR_DSIM_ASIM_LINSIM U(4) +#define TEGRA_MINOR_UNIT_FPGA U(5) +#define TEGRA_MINOR_VIRT_DEV_KIT U(6) + +/******************************************************************************* + * Tegra macros defining all the SoC pre_si_platform + ******************************************************************************/ +#define TEGRA_PRE_SI_QT U(1) +#define TEGRA_PRE_SI_FPGA U(2) +#define TEGRA_PRE_SI_UNIT_FPGA U(3) +#define TEGRA_PRE_SI_ASIM_QT U(4) +#define TEGRA_PRE_SI_ASIM_LINSIM U(5) +#define TEGRA_PRE_SI_DSIM_ASIM_LINSIM U(6) +#define TEGRA_PRE_SI_VDK U(8) +#define TEGRA_PRE_SI_VSP U(9) + +/* + * Read the chip ID value + */ +static uint32_t tegra_get_chipid(void) +{ + return mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET); +} + +/* + * Read the chip's major version from chip ID value + */ +uint32_t tegra_get_chipid_major(void) +{ + return (tegra_get_chipid() >> MAJOR_VERSION_SHIFT) & MAJOR_VERSION_MASK; +} + +/* + * Read the chip's minor version from the chip ID value + */ +uint32_t tegra_get_chipid_minor(void) +{ + return (tegra_get_chipid() >> MINOR_VERSION_SHIFT) & MINOR_VERSION_MASK; +} + +/* + * Read the chip's pre_si_platform valus from the chip ID value + */ +static uint32_t tegra_get_chipid_pre_si_platform(void) +{ + return (tegra_get_chipid() >> PRE_SI_PLATFORM_SHIFT) & PRE_SI_PLATFORM_MASK; +} + +bool tegra_chipid_is_t186(void) +{ + uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK; + + return (chip_id == TEGRA_CHIPID_TEGRA18); +} + +bool tegra_chipid_is_t210(void) +{ + uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK; + + return (chip_id == TEGRA_CHIPID_TEGRA21); +} + +bool tegra_chipid_is_t210_b01(void) +{ + return (tegra_chipid_is_t210() && (tegra_get_chipid_major() == 0x2U)); +} + +bool tegra_chipid_is_t194(void) +{ + uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK; + + return (chip_id == TEGRA_CHIPID_TEGRA19); +} + +bool tegra_chipid_is_t239(void) +{ + uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK; + + return ((chip_id == TEGRA_CHIPID_TEGRA23) && + (tegra_get_chipid_major() == 0x9U)); +} + +/* + * Read platform type from HIDREV major and minor bits. + */ + +static tegra_platform_t from_hidrev_major_minor_rev(void) +{ + uint32_t major = tegra_get_chipid_major(); + uint32_t minor = tegra_get_chipid_minor(); + tegra_platform_t ret; + + if (major == 0U) { + /* + * The minor version number is used by simulation platforms + */ + switch (minor) { + /* + * Cadence's QuickTurn emulation system is a Solaris-based + * chip emulation system + */ + case TEGRA_MINOR_QT: + case TEGRA_MINOR_ASIM_QT: + ret = TEGRA_PLATFORM_QT; + break; + + /* + * FPGAs are used during early software/hardware development + */ + case TEGRA_MINOR_FPGA: + ret = TEGRA_PLATFORM_FPGA; + break; + /* + * Linsim is a reconfigurable, clock-driven, mixed RTL/cmodel + * simulation framework. + */ + case TEGRA_MINOR_ASIM_LINSIM: + case TEGRA_MINOR_DSIM_ASIM_LINSIM: + ret = TEGRA_PLATFORM_LINSIM; + break; + + /* + * Unit FPGAs run the actual hardware block IP on the FPGA with + * the other parts of the system using Linsim. + */ + case TEGRA_MINOR_UNIT_FPGA: + ret = TEGRA_PLATFORM_UNIT_FPGA; + break; + /* + * The Virtualizer Development Kit (VDK) is the standard chip + * development from Synopsis. + */ + case TEGRA_MINOR_VIRT_DEV_KIT: + ret = TEGRA_PLATFORM_VIRT_DEV_KIT; + break; + + default: + ret = TEGRA_PLATFORM_MAX; + break; + } + } else { + /* Actual silicon platforms have a non-zero major version */ + ret = TEGRA_PLATFORM_SILICON; + } + + return ret; +} + +/* + * Read platform type from HIDREV pre_si bits. + */ + +static tegra_platform_t from_hidrev_pre_si_platform(void) +{ + uint32_t pre_si_platform = tegra_get_chipid_pre_si_platform(); + tegra_platform_t ret; + + if (pre_si_platform > 0U) { + switch (pre_si_platform) { + /* + * Cadence's QuickTurn emulation system is a Solaris-based + * chip emulation system + */ + case TEGRA_PRE_SI_QT: + case TEGRA_PRE_SI_ASIM_QT: + ret = TEGRA_PLATFORM_QT; + break; + + /* + * FPGAs are used during early software/hardware development + */ + case TEGRA_PRE_SI_FPGA: + ret = TEGRA_PLATFORM_FPGA; + break; + /* + * Linsim is a reconfigurable, clock-driven, mixed RTL/cmodel + * simulation framework. + */ + case TEGRA_PRE_SI_ASIM_LINSIM: + case TEGRA_PRE_SI_DSIM_ASIM_LINSIM: + ret = TEGRA_PLATFORM_LINSIM; + break; + + /* + * Unit FPGAs run the actual hardware block IP on the FPGA with + * the other parts of the system using Linsim. + */ + case TEGRA_PRE_SI_UNIT_FPGA: + ret = TEGRA_PLATFORM_UNIT_FPGA; + break; + /* + * The Virtualizer Development Kit (VDK) is the standard chip + * development from Synopsis. + */ + case TEGRA_PRE_SI_VDK: + ret = TEGRA_PLATFORM_VIRT_DEV_KIT; + break; + + /* + * The VSP pre-si development platform. + */ + case TEGRA_PRE_SI_VSP: + ret = TEGRA_PLATFORM_VSP; + break; + + default: + ret = TEGRA_PLATFORM_MAX; + break; + } + } else { + /* Actual silicon platforms have a non-zero major version */ + ret = TEGRA_PLATFORM_SILICON; + } + + return ret; +} + +/* + * Read the chip ID value and derive the platform + */ +static tegra_platform_t tegra_get_platform(void) +{ + tegra_platform_t ret; + uint32_t chip_id; + + /* get the chip_id/major/minor chip ID values */ + chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK; + + switch (chip_id) { + case TEGRA_CHIPID_TEGRA13: + case TEGRA_CHIPID_TEGRA18: + case TEGRA_CHIPID_TEGRA21: + ret = from_hidrev_major_minor_rev(); + break; + + /* For chip id T194 and later */ + default: + ret = from_hidrev_pre_si_platform(); + break; + } + + return ret; +} + +bool tegra_platform_is_silicon(void) +{ + return ((tegra_get_platform() == TEGRA_PLATFORM_SILICON) ? true : false); +} + +bool tegra_platform_is_qt(void) +{ + return ((tegra_get_platform() == TEGRA_PLATFORM_QT) ? true : false); +} + +bool tegra_platform_is_linsim(void) +{ + tegra_platform_t plat = tegra_get_platform(); + + return (((plat == TEGRA_PLATFORM_LINSIM) || + (plat == TEGRA_PLATFORM_UNIT_FPGA)) ? true : false); +} + +bool tegra_platform_is_fpga(void) +{ + return ((tegra_get_platform() == TEGRA_PLATFORM_FPGA) ? true : false); +} + +bool tegra_platform_is_emulation(void) +{ + return (tegra_get_platform() == TEGRA_PLATFORM_EMULATION); +} + +bool tegra_platform_is_unit_fpga(void) +{ + return ((tegra_get_platform() == TEGRA_PLATFORM_UNIT_FPGA) ? true : false); +} + +bool tegra_platform_is_virt_dev_kit(void) +{ + return ((tegra_get_platform() == TEGRA_PLATFORM_VIRT_DEV_KIT) ? true : false); +} + +bool tegra_platform_is_vsp(void) +{ + return ((tegra_get_platform() == TEGRA_PLATFORM_VSP) ? true : false); +} + +/* + * This function returns soc version which mainly consist of below fields + * + * soc_version[30:24] = JEP-106 continuation code for the SiP + * soc_version[23:16] = JEP-106 identification code with parity bit for the SiP + * soc_version[0:15] = chip identification + */ +int32_t plat_get_soc_version(void) +{ + uint32_t chip_id = ((tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK); + uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_NVIDIA_BKID, JEDEC_NVIDIA_MFID); + + return (int32_t)(manfid | (chip_id & SOC_ID_IMPL_DEF_MASK)); +} + +/* + * This function returns soc revision in below format + * + * soc_revision[8:15] = major version number + * soc_revision[0:7] = minor version number + */ +int32_t plat_get_soc_revision(void) +{ + return (int32_t)(((tegra_get_chipid_major() << 8) | tegra_get_chipid_minor()) & + SOC_ID_REV_MASK); +} + +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC feature + * is availabile for the platform or not. + * @fid: SMCCC function id + * + * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and + * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c new file mode 100644 index 0000000..4a15019 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2015-2020, 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 +#include +#include + +#include +#include +#include +#include +#include + +extern uint64_t tegra_bl31_phys_base; +extern uint64_t tegra_sec_entry_point; + +/******************************************************************************* + * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND` + * call to get the `power_state` parameter. This allows the platform to encode + * the appropriate State-ID field within the `power_state` parameter which can + * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. +******************************************************************************/ +static void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + /* all affinities use system suspend state id */ + for (uint32_t i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) { + req_state->pwr_domain_state[i] = PSTATE_ID_SOC_POWERDN; + } +} + +/******************************************************************************* + * Handler called when an affinity instance is about to enter standby. + ******************************************************************************/ +static void tegra_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t saved_scr_el3; + + (void)cpu_state; + + /* Tegra SoC specific handler */ + if (tegra_soc_cpu_standby(cpu_state) != PSCI_E_SUCCESS) + ERROR("%s failed\n", __func__); + + saved_scr_el3 = read_scr_el3(); + + /* + * As per ARM ARM D1.17.2, any physical IRQ interrupt received by the + * PE will be treated as a wake-up event, if SCR_EL3.IRQ is set to '1', + * irrespective of the value of the PSTATE.I bit value. + */ + write_scr_el3(saved_scr_el3 | SCR_IRQ_BIT); + + /* + * Enter standby state + * + * dsb & isb is good practice before using wfi to enter low power states + */ + dsb(); + isb(); + wfi(); + + /* + * Restore saved scr_el3 that has IRQ bit cleared as we don't want EL3 + * handling any further interrupts + */ + write_scr_el3(saved_scr_el3); +} + +/******************************************************************************* + * Handler called when an affinity instance is about to be turned on. The + * level and mpidr determine the affinity instance. + ******************************************************************************/ +static int32_t tegra_pwr_domain_on(u_register_t mpidr) +{ + return tegra_soc_pwr_domain_on(mpidr); +} + +/******************************************************************************* + * Handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void tegra_pwr_domain_off(const psci_power_state_t *target_state) +{ + (void)tegra_soc_pwr_domain_off(target_state); + + /* disable GICC */ + tegra_gic_cpuif_deactivate(); +} + +/******************************************************************************* + * Handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + * This handler is called with SMP and data cache enabled, when + * HW_ASSISTED_COHERENCY = 0 + ******************************************************************************/ +void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) +{ + tegra_soc_pwr_domain_suspend_pwrdown_early(target_state); +} + +/******************************************************************************* + * Handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + (void)tegra_soc_pwr_domain_suspend(target_state); + + /* disable GICC */ + tegra_gic_cpuif_deactivate(); + + /* save GIC Re-distributor and Distributor context */ + tegra_gic_save(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]); +} + +/******************************************************************************* + * Handler called at the end of the power domain suspend sequence. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t + *target_state) +{ + /* call the chip's power down handler */ + (void)tegra_soc_pwr_domain_power_down_wfi(target_state); + + /* Disable console if we are entering deep sleep. */ + if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == + PSTATE_ID_SOC_POWERDN) { + INFO("%s: complete. Entering System Suspend...\n", __func__); + console_flush(); + console_switch_state(0); + } + + wfi(); + panic(); +} + +/******************************************************************************* + * Handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +static void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + const plat_params_from_bl2_t *plat_params; + + /* + * Check if we are exiting from deep sleep. + */ + if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == + PSTATE_ID_SOC_POWERDN) { + + /* + * On entering System Suspend state, the GIC loses power + * completely. Restore the GIC global distributor and + * GIC cpu interfaces. + */ + tegra_gic_restore(PSTATE_ID_SOC_POWERDN); + + /* Restart console output. */ + console_switch_state(CONSOLE_FLAG_RUNTIME); + + /* + * Restore Memory Controller settings as it loses state + * during system suspend. + */ + tegra_memctrl_restore_settings(); + + /* + * Security configuration to allow DRAM/device access. + */ + plat_params = bl31_get_plat_params(); + tegra_memctrl_tzdram_setup(plat_params->tzdram_base, + (uint32_t)plat_params->tzdram_size); + + } else if (target_state->pwr_domain_state[MPIDR_AFFLVL0] == PSTATE_ID_CORE_POWERDN) { + /* + * Restore the GIC cpu and distributor interfaces + */ + tegra_gic_restore(PSTATE_ID_CORE_POWERDN); + } else { + /* Initialize the GIC cpu and distributor interfaces */ + tegra_gic_pcpu_init(); + } + + /* + * Reset hardware settings. + */ + (void)tegra_soc_pwr_domain_on_finish(target_state); +} + +/******************************************************************************* + * Handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + ******************************************************************************/ +static void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + tegra_pwr_domain_on_finish(target_state); +} + +/******************************************************************************* + * Handler called when the system wants to be powered off + ******************************************************************************/ +static __dead2 void tegra_system_off(void) +{ + INFO("Powering down system...\n"); + + tegra_soc_prepare_system_off(); +} + +/******************************************************************************* + * Handler called when the system wants to be restarted. + ******************************************************************************/ +static __dead2 void tegra_system_reset(void) +{ + INFO("Restarting system...\n"); + + /* per-SoC system reset handler */ + (void)tegra_soc_prepare_system_reset(); + + /* wait for the system to reset */ + for (;;) { + ; + } +} + +/******************************************************************************* + * Handler called to check the validity of the power state parameter. + ******************************************************************************/ +static int32_t tegra_validate_power_state(uint32_t power_state, + psci_power_state_t *req_state) +{ + assert(req_state != NULL); + + return tegra_soc_validate_power_state(power_state, req_state); +} + +/******************************************************************************* + * Platform handler called to check the validity of the non secure entrypoint. + ******************************************************************************/ +static int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) +{ + int32_t ret = PSCI_E_INVALID_ADDRESS; + + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) { + ret = PSCI_E_SUCCESS; + } + + return ret; +} + +/******************************************************************************* + * Export the platform handlers to enable psci to invoke them + ******************************************************************************/ +static plat_psci_ops_t tegra_plat_psci_ops = { + .cpu_standby = tegra_cpu_standby, + .pwr_domain_on = tegra_pwr_domain_on, + .pwr_domain_off = tegra_pwr_domain_off, + .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early, + .pwr_domain_suspend = tegra_pwr_domain_suspend, + .pwr_domain_on_finish = tegra_pwr_domain_on_finish, + .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi, + .system_off = tegra_system_off, + .system_reset = tegra_system_reset, + .validate_power_state = tegra_validate_power_state, + .validate_ns_entrypoint = tegra_validate_ns_entrypoint, + .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state, +}; + +/******************************************************************************* + * Export the platform specific power ops and initialize Power Controller + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } }; + + /* + * Flush entrypoint variable to PoC since it will be + * accessed after a reset with the caches turned off. + */ + tegra_sec_entry_point = sec_entrypoint; + flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t)); + + /* + * Reset hardware settings. + */ + (void)tegra_soc_pwr_domain_on_finish(&target_state); + + /* + * Disable System Suspend if the platform does not + * support it + */ + if (!plat_supports_system_suspend()) { + tegra_plat_psci_ops.get_sys_suspend_power_state = NULL; + } + + /* + * Initialize PSCI ops struct + */ + *psci_ops = &tegra_plat_psci_ops; + + return 0; +} + +/******************************************************************************* + * Platform handler to calculate the proper target power level at the + * specified affinity level + ******************************************************************************/ +plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, + const plat_local_state_t *states, + unsigned int ncpu) +{ + return tegra_soc_get_target_pwr_state(lvl, states, ncpu); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c new file mode 100644 index 0000000..9241b81 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* SDEI configuration for Tegra platforms */ + +#include + +#include +#include +#include +#include +#include + +/* Private event mappings */ +static sdei_ev_map_t tegra_sdei_private[] = { + /* Event 0 definition */ + SDEI_DEFINE_EVENT_0(TEGRA_SDEI_SGI_PRIVATE), + + /* Dynamic private events */ + SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + + /* General purpose explicit events */ + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_0, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_1, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_2, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_3, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_4, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_5, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_6, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_7, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_8, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_9, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_10, SDEI_MAPF_CRITICAL), + SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_11, SDEI_MAPF_CRITICAL) +}; + +/* Shared event mappings */ +static sdei_ev_map_t tegra_sdei_shared[] = { + /* Dynamic shared events */ + SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) +}; + +void plat_sdei_setup(void) +{ + INFO("SDEI platform setup\n"); +} + +/* Export Tegra SDEI events */ +REGISTER_SDEI_MAP(tegra_sdei_private, tegra_sdei_shared); diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c new file mode 100644 index 0000000..80a2c4d --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015-2017, 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 +#include +#include + +/******************************************************************************* + * Common Tegra SiP SMCs + ******************************************************************************/ +#define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003 +#define TEGRA_SIP_FIQ_NS_ENTRYPOINT 0x82000005 +#define TEGRA_SIP_FIQ_NS_GET_CONTEXT 0x82000006 + +/******************************************************************************* + * This function is responsible for handling all SiP calls + ******************************************************************************/ +uintptr_t tegra_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) +{ + uint32_t regval, local_x2_32 = (uint32_t)x2; + int32_t err; + + /* Check if this is a SoC specific SiP */ + err = plat_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); + if (err == 0) { + + SMC_RET1(handle, (uint64_t)err); + + } else { + + switch (smc_fid) { + + case TEGRA_SIP_NEW_VIDEOMEM_REGION: + /* Check whether Video memory resize is enabled */ + if (mmio_read_32(TEGRA_MC_BASE + MC_VIDEO_PROTECT_REG_CTRL) + != MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED) { + ERROR("Video Memory Resize isn't enabled! \n"); + SMC_RET1(handle, (uint64_t)-ENOTSUP); + } + + /* + * Check if Video Memory overlaps TZDRAM (contains bl31/bl32) + * or falls outside of the valid DRAM range + */ + err = bl31_check_ns_address(x1, local_x2_32); + if (err != 0) { + SMC_RET1(handle, (uint64_t)err); + } + + /* + * Check if Video Memory is aligned to 1MB. + */ + if (((x1 & 0xFFFFFU) != 0U) || ((local_x2_32 & 0xFFFFFU) != 0U)) { + ERROR("Unaligned Video Memory base address!\n"); + SMC_RET1(handle, (uint64_t)-ENOTSUP); + } + + /* + * The GPU is the user of the Video Memory region. In order to + * transition to the new memory region smoothly, we program the + * new base/size ONLY if the GPU is in reset mode. + */ + regval = mmio_read_32(TEGRA_CAR_RESET_BASE + + TEGRA_GPU_RESET_REG_OFFSET); + if ((regval & GPU_RESET_BIT) == 0U) { + ERROR("GPU not in reset! Video Memory setup failed\n"); + SMC_RET1(handle, (uint64_t)-ENOTSUP); + } + + /* new video memory carveout settings */ + tegra_memctrl_videomem_setup(x1, local_x2_32); + + /* + * Ensure again that GPU is still in reset after VPR resize + */ + regval = mmio_read_32(TEGRA_CAR_RESET_BASE + + TEGRA_GPU_RESET_REG_OFFSET); + if ((regval & GPU_RESET_BIT) == 0U) { + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_GPU_SET_OFFSET, + GPU_SET_BIT); + } + + SMC_RET1(handle, 0); + + /* + * The NS world registers the address of its handler to be + * used for processing the FIQ. This is normally used by the + * NS FIQ debugger driver to detect system hangs by programming + * a watchdog timer to fire a FIQ interrupt. + */ + case TEGRA_SIP_FIQ_NS_ENTRYPOINT: + + if (x1 == 0U) { + SMC_RET1(handle, SMC_UNK); + } + + /* + * TODO: Check if x1 contains a valid DRAM address + */ + + /* store the NS world's entrypoint */ + tegra_fiq_set_ns_entrypoint(x1); + + SMC_RET1(handle, 0); + + /* + * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0 + * CPU context when the FIQ interrupt was triggered. This allows the + * NS world to understand the CPU state when the watchdog interrupt + * triggered. + */ + case TEGRA_SIP_FIQ_NS_GET_CONTEXT: + + /* retrieve context registers when FIQ triggered */ + (void)tegra_fiq_get_intr_context(); + + SMC_RET0(handle); + + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + } + + SMC_RET1(handle, SMC_UNK); +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tegra_sip_fast, + + (OEN_SIP_START), + (OEN_SIP_END), + (SMC_TYPE_FAST), + (NULL), + (tegra_sip_handler) +); diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c new file mode 100644 index 0000000..f6c459a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +u_register_t plat_get_stack_protector_canary(void) +{ + u_register_t seed; + + /* + * Ideally, a random number should be returned instead. As the + * platform does not have any random number generator, this is + * better than nothing, but not really secure. + */ + seed = mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET); + seed <<= 32; + seed |= mmio_read_32(TEGRA_TMRUS_BASE); + + return seed ^ read_cntpct_el0(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c new file mode 100644 index 0000000..d7db604 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 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 + +#define BPMP_TIMEOUT 500 /* 500ms */ + +static uint32_t channel_base[NR_CHANNELS]; +static uint32_t bpmp_init_state = BPMP_INIT_PENDING; + +static uint32_t channel_field(unsigned int ch) +{ + return mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET) & CH_MASK(ch); +} + +static bool master_free(unsigned int ch) +{ + return channel_field(ch) == MA_FREE(ch); +} + +static bool master_acked(unsigned int ch) +{ + return channel_field(ch) == MA_ACKD(ch); +} + +static void signal_slave(unsigned int ch) +{ + mmio_write_32(TEGRA_RES_SEMA_BASE + CLR_OFFSET, CH_MASK(ch)); +} + +static void free_master(unsigned int ch) +{ + mmio_write_32(TEGRA_RES_SEMA_BASE + CLR_OFFSET, + MA_ACKD(ch) ^ MA_FREE(ch)); +} + +/* should be called with local irqs disabled */ +int32_t tegra_bpmp_send_receive_atomic(int mrq, const void *ob_data, int ob_sz, + void *ib_data, int ib_sz) +{ + unsigned int ch = (unsigned int)plat_my_core_pos(); + mb_data_t *p = (mb_data_t *)(uintptr_t)channel_base[ch]; + int32_t ret = -ETIMEDOUT, timeout = 0; + + if (bpmp_init_state == BPMP_INIT_COMPLETE) { + + /* loop until BPMP is free */ + for (timeout = 0; timeout < BPMP_TIMEOUT; timeout++) { + if (master_free(ch) == true) { + break; + } + + mdelay(1); + } + + if (timeout != BPMP_TIMEOUT) { + + /* generate the command struct */ + p->code = mrq; + p->flags = DO_ACK; + (void)memcpy((void *)p->data, ob_data, (size_t)ob_sz); + + /* signal command ready to the BPMP */ + signal_slave(ch); + mmio_write_32(TEGRA_PRI_ICTLR_BASE + CPU_IEP_FIR_SET, + (1U << INT_SHR_SEM_OUTBOX_FULL)); + + /* loop until the command is executed */ + for (timeout = 0; timeout < BPMP_TIMEOUT; timeout++) { + if (master_acked(ch) == true) { + break; + } + + mdelay(1); + } + + if (timeout != BPMP_TIMEOUT) { + + /* get the command response */ + (void)memcpy(ib_data, (const void *)p->data, + (size_t)ib_sz); + + /* return error code */ + ret = p->code; + + /* free this channel */ + free_master(ch); + } + } + + } else { + /* return error code */ + ret = -EINVAL; + } + + if (timeout == BPMP_TIMEOUT) { + ERROR("Timed out waiting for bpmp's response\n"); + } + + return ret; +} + +int tegra_bpmp_init(void) +{ + uint32_t val, base, timeout = BPMP_TIMEOUT; + unsigned int ch; + int ret = 0; + + if (bpmp_init_state == BPMP_INIT_PENDING) { + + /* check if the bpmp processor is alive. */ + do { + val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET); + if (val != SIGN_OF_LIFE) { + mdelay(1); + timeout--; + } + + } while ((val != SIGN_OF_LIFE) && (timeout > 0U)); + + if (val == SIGN_OF_LIFE) { + + /* check if clock for the atomics block is enabled */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V); + if ((val & CAR_ENABLE_ATOMICS) == 0) { + ERROR("Clock to the atomics block is disabled\n"); + } + + /* check if the atomics block is out of reset */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V); + if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) { + ERROR("Reset to the atomics block is asserted\n"); + } + + /* base address to get the result from Atomics */ + base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET; + + /* channel area is setup by BPMP before signaling handshake */ + for (ch = 0; ch < NR_CHANNELS; ch++) { + + /* issue command to get the channel base address */ + mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) | + ATOMIC_CMD_GET); + + /* get the base address for the channel */ + channel_base[ch] = mmio_read_32(base); + + /* increment result register offset */ + base += 4U; + } + + /* mark state as "initialized" */ + bpmp_init_state = BPMP_INIT_COMPLETE; + + /* the channel values have to be visible across all cpus */ + flush_dcache_range((uint64_t)channel_base, + sizeof(channel_base)); + flush_dcache_range((uint64_t)&bpmp_init_state, + sizeof(bpmp_init_state)); + + INFO("%s: done\n", __func__); + + } else { + ERROR("BPMP not powered on\n"); + + /* bpmp is not present in the system */ + bpmp_init_state = BPMP_NOT_PRESENT; + + /* communication timed out */ + ret = -ETIMEDOUT; + } + } + + return ret; +} + +void tegra_bpmp_suspend(void) +{ + /* freeze the interface */ + if (bpmp_init_state == BPMP_INIT_COMPLETE) { + bpmp_init_state = BPMP_SUSPEND_ENTRY; + flush_dcache_range((uint64_t)&bpmp_init_state, + sizeof(bpmp_init_state)); + } +} + +void tegra_bpmp_resume(void) +{ + uint32_t val, timeout = 0; + + if (bpmp_init_state == BPMP_SUSPEND_ENTRY) { + + /* check if the bpmp processor is alive. */ + do { + + val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET); + if (val != SIGN_OF_LIFE) { + mdelay(1); + timeout++; + } + + } while ((val != SIGN_OF_LIFE) && (timeout < BPMP_TIMEOUT)); + + if (val == SIGN_OF_LIFE) { + + INFO("%s: BPMP took %d ms to resume\n", __func__, timeout); + + /* mark state as "initialized" */ + bpmp_init_state = BPMP_INIT_COMPLETE; + + /* state has to be visible across all cpus */ + flush_dcache_range((uint64_t)&bpmp_init_state, + sizeof(bpmp_init_state)); + } else { + ERROR("BPMP not powered on\n"); + } + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c new file mode 100644 index 0000000..f1ed1e4 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "intf.h" +#include "ivc.h" + +/** + * Holds IVC channel data + */ +struct ccplex_bpmp_channel_data { + /* Buffer for incoming data */ + struct frame_data *ib; + + /* Buffer for outgoing data */ + struct frame_data *ob; +}; + +static struct ccplex_bpmp_channel_data s_channel; +static struct ivc ivc_ccplex_bpmp_channel; + +/* + * Helper functions to access the HSP doorbell registers + */ +static inline uint32_t hsp_db_read(uint32_t reg) +{ + return mmio_read_32((uint32_t)(TEGRA_HSP_DBELL_BASE + reg)); +} + +static inline void hsp_db_write(uint32_t reg, uint32_t val) +{ + mmio_write_32((uint32_t)(TEGRA_HSP_DBELL_BASE + reg), val); +} + +/******************************************************************************* + * IVC wrappers for CCPLEX <-> BPMP communication. + ******************************************************************************/ + +static void tegra_bpmp_ring_bpmp_doorbell(void); + +/* + * Get the next frame where data can be written. + */ +static struct frame_data *tegra_bpmp_get_next_out_frame(void) +{ + struct frame_data *frame; + const struct ivc *ch = &ivc_ccplex_bpmp_channel; + + frame = (struct frame_data *)tegra_ivc_write_get_next_frame(ch); + if (frame == NULL) { + ERROR("%s: Error in getting next frame, exiting\n", __func__); + } else { + s_channel.ob = frame; + } + + return frame; +} + +static void tegra_bpmp_signal_slave(void) +{ + (void)tegra_ivc_write_advance(&ivc_ccplex_bpmp_channel); + tegra_bpmp_ring_bpmp_doorbell(); +} + +static int32_t tegra_bpmp_free_master(void) +{ + return tegra_ivc_read_advance(&ivc_ccplex_bpmp_channel); +} + +static bool tegra_bpmp_slave_acked(void) +{ + struct frame_data *frame; + bool ret = true; + + frame = (struct frame_data *)tegra_ivc_read_get_next_frame(&ivc_ccplex_bpmp_channel); + if (frame == NULL) { + ret = false; + } else { + s_channel.ib = frame; + } + + return ret; +} + +static struct frame_data *tegra_bpmp_get_cur_in_frame(void) +{ + return s_channel.ib; +} + +/* + * Enables BPMP to ring CCPlex doorbell + */ +static void tegra_bpmp_enable_ccplex_doorbell(void) +{ + uint32_t reg; + + reg = hsp_db_read(HSP_DBELL_1_ENABLE); + reg |= HSP_MASTER_BPMP_BIT; + hsp_db_write(HSP_DBELL_1_ENABLE, reg); +} + +/* + * CCPlex rings the BPMP doorbell + */ +static void tegra_bpmp_ring_bpmp_doorbell(void) +{ + /* + * Any writes to this register has the same effect, + * uses master ID of the write transaction and set + * corresponding flag. + */ + hsp_db_write(HSP_DBELL_3_TRIGGER, HSP_MASTER_CCPLEX_BIT); +} + +/* + * Returns true if CCPLex can ring BPMP doorbell, otherwise false. + * This also signals that BPMP is up and ready. + */ +static bool tegra_bpmp_can_ccplex_ring_doorbell(void) +{ + uint32_t reg; + + /* check if ccplex can communicate with bpmp */ + reg = hsp_db_read(HSP_DBELL_3_ENABLE); + + return ((reg & HSP_MASTER_CCPLEX_BIT) != 0U); +} + +static int32_t tegra_bpmp_wait_for_slave_ack(void) +{ + uint32_t timeout = TIMEOUT_RESPONSE_FROM_BPMP_US; + + while (!tegra_bpmp_slave_acked() && (timeout != 0U)) { + udelay(1); + timeout--; + }; + + return ((timeout == 0U) ? -ETIMEDOUT : 0); +} + +/* + * Notification from the ivc layer + */ +static void tegra_bpmp_ivc_notify(const struct ivc *ivc) +{ + (void)(ivc); + + tegra_bpmp_ring_bpmp_doorbell(); +} + +/* + * Atomic send/receive API, which means it waits until slave acks + */ +static int32_t tegra_bpmp_ipc_send_req_atomic(uint32_t mrq, void *p_out, + uint32_t size_out, void *p_in, uint32_t size_in) +{ + struct frame_data *frame = tegra_bpmp_get_next_out_frame(); + struct frame_data *f_in = NULL; + int32_t ret = 0; + void *p_fdata; + + if ((p_out == NULL) || (size_out > IVC_DATA_SZ_BYTES) || + (frame == NULL)) { + ERROR("%s: invalid parameters, exiting\n", __func__); + return -EINVAL; + } + + /* prepare the command frame */ + frame->mrq = mrq; + frame->flags = FLAG_DO_ACK; + p_fdata = frame->data; + (void)memcpy(p_fdata, p_out, (size_t)size_out); + dsbsy(); + assert(memcmp(p_fdata, p_out, (size_t)size_out) == 0); + + /* signal the slave */ + tegra_bpmp_signal_slave(); + + /* wait for slave to ack */ + ret = tegra_bpmp_wait_for_slave_ack(); + if (ret < 0) { + ERROR("%s: wait for slave failed (%d)\n", __func__, ret); + return ret; + } + + /* retrieve the response frame */ + if ((size_in <= IVC_DATA_SZ_BYTES) && (p_in != NULL)) { + + f_in = tegra_bpmp_get_cur_in_frame(); + if (f_in == NULL) { + ERROR("Failed to get next input frame!\n"); + } else { + p_fdata = f_in->data; + (void)memcpy(p_in, p_fdata, (size_t)size_in); + } + } + + ret = tegra_bpmp_free_master(); + if (ret < 0) { + ERROR("%s: free master failed (%d)\n", __func__, ret); + } + + return ret; +} + +/* + * Initializes the BPMP<--->CCPlex communication path. + */ +int32_t tegra_bpmp_ipc_init(void) +{ + size_t msg_size; + uint32_t frame_size, timeout; + int32_t error = 0; + struct bpmp_ipc_platform_data *bpmp_ipc; + + /* allow bpmp to ring CCPLEX's doorbell */ + tegra_bpmp_enable_ccplex_doorbell(); + + /* wait for BPMP to actually ring the doorbell */ + timeout = TIMEOUT_RESPONSE_FROM_BPMP_US; + while ((timeout != 0U) && !tegra_bpmp_can_ccplex_ring_doorbell()) { + udelay(1); /* bpmp turn-around time */ + timeout--; + } + + if (timeout == 0U) { + ERROR("%s: BPMP firmware is not ready\n", __func__); + return -ENOTSUP; + } + + INFO("%s: BPMP handshake completed\n", __func__); + + /* get bpmp_ipc data */ + bpmp_ipc = plat_get_bpmp_ipc_data(); + if (bpmp_ipc == NULL) { + ERROR("%s: bpmp_ipc interface is not supported\n", __func__); + return -ENOTSUP; + } + + msg_size = tegra_ivc_align(IVC_CMD_SZ_BYTES); + frame_size = (uint32_t)tegra_ivc_total_queue_size(msg_size); + if (frame_size > bpmp_ipc->bpmp_ipc_map_size) { + ERROR("%s: carveout size is not sufficient\n", __func__); + return -EINVAL; + } + + error = tegra_ivc_init(&ivc_ccplex_bpmp_channel, + (uint32_t)bpmp_ipc->bpmp_ipc_rx_base, + (uint32_t)bpmp_ipc->bpmp_ipc_tx_base, + 1U, frame_size, tegra_bpmp_ivc_notify); + if (error != 0) { + + ERROR("%s: IVC init failed (%d)\n", __func__, error); + + } else { + + /* reset channel */ + tegra_ivc_channel_reset(&ivc_ccplex_bpmp_channel); + + /* wait for notification from BPMP */ + while (tegra_ivc_channel_notified(&ivc_ccplex_bpmp_channel) != 0) { + /* + * Interrupt BPMP with doorbell each time after + * tegra_ivc_channel_notified() returns non zero + * value. + */ + tegra_bpmp_ring_bpmp_doorbell(); + } + + INFO("%s: All communication channels initialized\n", __func__); + } + + return error; +} + +/* Handler to reset a hardware module */ +int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id) +{ + int32_t ret; + struct mrq_reset_request req = { + .cmd = (uint32_t)CMD_RESET_MODULE, + .reset_id = rst_id + }; + + /* only GPCDMA/XUSB_PADCTL resets are supported */ + assert((rst_id == TEGRA_RESET_ID_XUSB_PADCTL) || + (rst_id == TEGRA_RESET_ID_GPCDMA)); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_RESET, &req, + (uint32_t)sizeof(req), NULL, 0); + if (ret != 0) { + ERROR("%s: failed for module %d with error %d\n", __func__, + rst_id, ret); + } + + return ret; +} + +int tegra_bpmp_ipc_enable_clock(uint32_t clk_id) +{ + int ret; + struct mrq_clk_request req; + struct cmd_clk_is_en_resp resp = { 0 }; + + /* only SE clocks are supported */ + if (clk_id != TEGRA_CLK_SE) { + return -ENOTSUP; + } + + /* prepare the MRQ_CLK command */ + req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_ENABLE, clk_id); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, (uint32_t)sizeof(req), + NULL, 0); + if (ret != 0) { + ERROR("%s: failed for module %d with error %d\n", __func__, + clk_id, ret); + } + + /* prepare the MRQ_CLK command to check if clk is actually enabled */ + req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_IS_ENABLED, clk_id); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, (uint32_t)sizeof(req), + &resp, (uint32_t)sizeof(resp)); + if (resp.state == 0) { + ERROR("%s: clock enable failed for module %d with error %d\n", __func__, + clk_id, ret); + } + + return ret; +} + +int tegra_bpmp_ipc_disable_clock(uint32_t clk_id) +{ + int ret; + struct mrq_clk_request req; + + /* only SE clocks are supported */ + if (clk_id != TEGRA_CLK_SE) { + return -ENOTSUP; + } + + /* prepare the MRQ_CLK command */ + req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_DISABLE, clk_id); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, (uint32_t)sizeof(req), + NULL, 0); + if (ret != 0) { + ERROR("%s: failed for module %d with error %d\n", __func__, + clk_id, ret); + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h new file mode 100644 index 0000000..e02c508 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BPMP_INTF_H +#define BPMP_INTF_H + +/** + * Flags used in IPC req + */ +#define FLAG_DO_ACK (U(1) << 0) +#define FLAG_RING_DOORBELL (U(1) << 1) + +/* Bit 1 is designated for CCPlex in secure world */ +#define HSP_MASTER_CCPLEX_BIT (U(1) << 1) +/* Bit 19 is designated for BPMP in non-secure world */ +#define HSP_MASTER_BPMP_BIT (U(1) << 19) +/* Timeout to receive response from BPMP is 1 sec */ +#define TIMEOUT_RESPONSE_FROM_BPMP_US U(1000000) /* in microseconds */ + +/** + * IVC protocol defines and command/response frame + */ + +/** + * IVC specific defines + */ +#define IVC_CMD_SZ_BYTES U(128) +#define IVC_DATA_SZ_BYTES U(120) + +/** + * Holds frame data for an IPC request + */ +struct frame_data { + /* Identification as to what kind of data is being transmitted */ + uint32_t mrq; + + /* Flags for slave as to how to respond back */ + uint32_t flags; + + /* Actual data being sent */ + uint8_t data[IVC_DATA_SZ_BYTES]; +}; + +/** + * Commands send to the BPMP firmware + */ + +/** + * MRQ command codes + */ +#define MRQ_RESET U(20) +#define MRQ_CLK U(22) + +/** + * Reset sub-commands + */ +#define CMD_RESET_ASSERT U(1) +#define CMD_RESET_DEASSERT U(2) +#define CMD_RESET_MODULE U(3) + +/** + * Used by the sender of an #MRQ_RESET message to request BPMP to + * assert or deassert a given reset line. + */ +struct __attribute__((packed)) mrq_reset_request { + /* reset action to perform (mrq_reset_commands) */ + uint32_t cmd; + /* id of the reset to affected */ + uint32_t reset_id; +}; + +struct __attribute__((packed)) cmd_clk_is_en_resp { + /** + * @brief The state of the clock that has been succesfully + * requested with CMD_CLK_ENABLE or CMD_CLK_DISABLE by the + * master invoking the command earlier. + * + * The state may not reflect the physical state of the clock + * if there are some other masters requesting it to be + * enabled. + * + * Value 0 is disabled, all other values indicate enabled. + */ + int32_t state; +}; + +/** + * MRQ_CLK sub-commands + * + */ +enum { + CMD_CLK_GET_RATE = U(1), + CMD_CLK_SET_RATE = U(2), + CMD_CLK_ROUND_RATE = U(3), + CMD_CLK_GET_PARENT = U(4), + CMD_CLK_SET_PARENT = U(5), + CMD_CLK_IS_ENABLED = U(6), + CMD_CLK_ENABLE = U(7), + CMD_CLK_DISABLE = U(8), + CMD_CLK_GET_ALL_INFO = U(14), + CMD_CLK_GET_MAX_CLK_ID = U(15), + CMD_CLK_MAX, +}; + +/** + * Used by the sender of an #MRQ_CLK message to control clocks. The + * clk_request is split into several sub-commands. Some sub-commands + * require no additional data. Others have a sub-command specific + * payload + * + * |sub-command |payload | + * |----------------------------|-----------------------| + * |CMD_CLK_GET_RATE |- | + * |CMD_CLK_SET_RATE |clk_set_rate | + * |CMD_CLK_ROUND_RATE |clk_round_rate | + * |CMD_CLK_GET_PARENT |- | + * |CMD_CLK_SET_PARENT |clk_set_parent | + * |CMD_CLK_IS_ENABLED |- | + * |CMD_CLK_ENABLE |- | + * |CMD_CLK_DISABLE |- | + * |CMD_CLK_GET_ALL_INFO |- | + * |CMD_CLK_GET_MAX_CLK_ID |- | + * + */ +struct mrq_clk_request { + /** + * sub-command and clock id concatenated to 32-bit word. + * - bits[31..24] is the sub-cmd. + * - bits[23..0] is the clock id + */ + uint32_t cmd_and_id; +}; + +/** + * Macro to prepare the MRQ_CLK sub-command + */ +#define make_mrq_clk_cmd(cmd, id) (((cmd) << 24) | (id & 0xFFFFFF)) + +#endif /* BPMP_INTF_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c new file mode 100644 index 0000000..d964fc0 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c @@ -0,0 +1,654 @@ +/* + * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ivc.h" + +/* + * IVC channel reset protocol. + * + * Each end uses its tx_channel.state to indicate its synchronization state. + */ +enum { + /* + * This value is zero for backwards compatibility with services that + * assume channels to be initially zeroed. Such channels are in an + * initially valid state, but cannot be asynchronously reset, and must + * maintain a valid state at all times. + * + * The transmitting end can enter the established state from the sync or + * ack state when it observes the receiving endpoint in the ack or + * established state, indicating that has cleared the counters in our + * rx_channel. + */ + ivc_state_established = U(0), + + /* + * If an endpoint is observed in the sync state, the remote endpoint is + * allowed to clear the counters it owns asynchronously with respect to + * the current endpoint. Therefore, the current endpoint is no longer + * allowed to communicate. + */ + ivc_state_sync = U(1), + + /* + * When the transmitting end observes the receiving end in the sync + * state, it can clear the w_count and r_count and transition to the ack + * state. If the remote endpoint observes us in the ack state, it can + * return to the established state once it has cleared its counters. + */ + ivc_state_ack = U(2) +}; + +/* + * This structure is divided into two-cache aligned parts, the first is only + * written through the tx_channel pointer, while the second is only written + * through the rx_channel pointer. This delineates ownership of the cache lines, + * which is critical to performance and necessary in non-cache coherent + * implementations. + */ +struct ivc_channel_header { + struct { + /* fields owned by the transmitting end */ + uint32_t w_count; + uint32_t state; + uint32_t w_rsvd[IVC_CHHDR_TX_FIELDS - 2]; + }; + struct { + /* fields owned by the receiving end */ + uint32_t r_count; + uint32_t r_rsvd[IVC_CHHDR_RX_FIELDS - 1]; + }; +}; + +static inline bool ivc_channel_empty(const struct ivc *ivc, + volatile const struct ivc_channel_header *ch) +{ + /* + * This function performs multiple checks on the same values with + * security implications, so sample the counters' current values in + * shared memory to ensure that these checks use the same values. + */ + uint32_t wr_count = ch->w_count; + uint32_t rd_count = ch->r_count; + bool ret = false; + + (void)ivc; + + /* + * Perform an over-full check to prevent denial of service attacks where + * a server could be easily fooled into believing that there's an + * extremely large number of frames ready, since receivers are not + * expected to check for full or over-full conditions. + * + * Although the channel isn't empty, this is an invalid case caused by + * a potentially malicious peer, so returning empty is safer, because it + * gives the impression that the channel has gone silent. + */ + if (((wr_count - rd_count) > ivc->nframes) || (wr_count == rd_count)) { + ret = true; + } + + return ret; +} + +static inline bool ivc_channel_full(const struct ivc *ivc, + volatile const struct ivc_channel_header *ch) +{ + uint32_t wr_count = ch->w_count; + uint32_t rd_count = ch->r_count; + + (void)ivc; + + /* + * Invalid cases where the counters indicate that the queue is over + * capacity also appear full. + */ + return ((wr_count - rd_count) >= ivc->nframes); +} + +static inline uint32_t ivc_channel_avail_count(const struct ivc *ivc, + volatile const struct ivc_channel_header *ch) +{ + uint32_t wr_count = ch->w_count; + uint32_t rd_count = ch->r_count; + + (void)ivc; + + /* + * This function isn't expected to be used in scenarios where an + * over-full situation can lead to denial of service attacks. See the + * comment in ivc_channel_empty() for an explanation about special + * over-full considerations. + */ + return (wr_count - rd_count); +} + +static inline void ivc_advance_tx(struct ivc *ivc) +{ + ivc->tx_channel->w_count++; + + if (ivc->w_pos == (ivc->nframes - (uint32_t)1U)) { + ivc->w_pos = 0U; + } else { + ivc->w_pos++; + } +} + +static inline void ivc_advance_rx(struct ivc *ivc) +{ + ivc->rx_channel->r_count++; + + if (ivc->r_pos == (ivc->nframes - (uint32_t)1U)) { + ivc->r_pos = 0U; + } else { + ivc->r_pos++; + } +} + +static inline int32_t ivc_check_read(const struct ivc *ivc) +{ + /* + * tx_channel->state is set locally, so it is not synchronized with + * state from the remote peer. The remote peer cannot reset its + * transmit counters until we've acknowledged its synchronization + * request, so no additional synchronization is required because an + * asynchronous transition of rx_channel->state to ivc_state_ack is not + * allowed. + */ + if (ivc->tx_channel->state != ivc_state_established) { + return -ECONNRESET; + } + + /* + * Avoid unnecessary invalidations when performing repeated accesses to + * an IVC channel by checking the old queue pointers first. + * Synchronization is only necessary when these pointers indicate empty + * or full. + */ + if (!ivc_channel_empty(ivc, ivc->rx_channel)) { + return 0; + } + + return ivc_channel_empty(ivc, ivc->rx_channel) ? -ENOMEM : 0; +} + +static inline int32_t ivc_check_write(const struct ivc *ivc) +{ + if (ivc->tx_channel->state != ivc_state_established) { + return -ECONNRESET; + } + + if (!ivc_channel_full(ivc, ivc->tx_channel)) { + return 0; + } + + return ivc_channel_full(ivc, ivc->tx_channel) ? -ENOMEM : 0; +} + +bool tegra_ivc_can_read(const struct ivc *ivc) +{ + return ivc_check_read(ivc) == 0; +} + +bool tegra_ivc_can_write(const struct ivc *ivc) +{ + return ivc_check_write(ivc) == 0; +} + +bool tegra_ivc_tx_empty(const struct ivc *ivc) +{ + return ivc_channel_empty(ivc, ivc->tx_channel); +} + +static inline uintptr_t calc_frame_offset(uint32_t frame_index, + uint32_t frame_size, uint32_t frame_offset) +{ + return ((uintptr_t)frame_index * (uintptr_t)frame_size) + + (uintptr_t)frame_offset; +} + +static void *ivc_frame_pointer(const struct ivc *ivc, + volatile const struct ivc_channel_header *ch, + uint32_t frame) +{ + assert(frame < ivc->nframes); + return (void *)((uintptr_t)(&ch[1]) + + calc_frame_offset(frame, ivc->frame_size, 0)); +} + +int32_t tegra_ivc_read(struct ivc *ivc, void *buf, size_t max_read) +{ + const void *src; + int32_t result; + + if (buf == NULL) { + return -EINVAL; + } + + if (max_read > ivc->frame_size) { + return -E2BIG; + } + + result = ivc_check_read(ivc); + if (result != 0) { + return result; + } + + /* + * Order observation of w_pos potentially indicating new data before + * data read. + */ + dmbish(); + + src = ivc_frame_pointer(ivc, ivc->rx_channel, ivc->r_pos); + + (void)memcpy(buf, src, max_read); + + ivc_advance_rx(ivc); + + /* + * Ensure our write to r_pos occurs before our read from w_pos. + */ + dmbish(); + + /* + * Notify only upon transition from full to non-full. + * The available count can only asynchronously increase, so the + * worst possible side-effect will be a spurious notification. + */ + if (ivc_channel_avail_count(ivc, ivc->rx_channel) == (ivc->nframes - (uint32_t)1U)) { + ivc->notify(ivc); + } + + return (int32_t)max_read; +} + +/* directly peek at the next frame rx'ed */ +void *tegra_ivc_read_get_next_frame(const struct ivc *ivc) +{ + if (ivc_check_read(ivc) != 0) { + return NULL; + } + + /* + * Order observation of w_pos potentially indicating new data before + * data read. + */ + dmbld(); + + return ivc_frame_pointer(ivc, ivc->rx_channel, ivc->r_pos); +} + +int32_t tegra_ivc_read_advance(struct ivc *ivc) +{ + /* + * No read barriers or synchronization here: the caller is expected to + * have already observed the channel non-empty. This check is just to + * catch programming errors. + */ + int32_t result = ivc_check_read(ivc); + if (result != 0) { + return result; + } + + ivc_advance_rx(ivc); + + /* + * Ensure our write to r_pos occurs before our read from w_pos. + */ + dmbish(); + + /* + * Notify only upon transition from full to non-full. + * The available count can only asynchronously increase, so the + * worst possible side-effect will be a spurious notification. + */ + if (ivc_channel_avail_count(ivc, ivc->rx_channel) == (ivc->nframes - (uint32_t)1U)) { + ivc->notify(ivc); + } + + return 0; +} + +int32_t tegra_ivc_write(struct ivc *ivc, const void *buf, size_t size) +{ + void *p; + int32_t result; + + if ((buf == NULL) || (ivc == NULL)) { + return -EINVAL; + } + + if (size > ivc->frame_size) { + return -E2BIG; + } + + result = ivc_check_write(ivc); + if (result != 0) { + return result; + } + + p = ivc_frame_pointer(ivc, ivc->tx_channel, ivc->w_pos); + + (void)memset(p, 0, ivc->frame_size); + (void)memcpy(p, buf, size); + + /* + * Ensure that updated data is visible before the w_pos counter + * indicates that it is ready. + */ + dmbst(); + + ivc_advance_tx(ivc); + + /* + * Ensure our write to w_pos occurs before our read from r_pos. + */ + dmbish(); + + /* + * Notify only upon transition from empty to non-empty. + * The available count can only asynchronously decrease, so the + * worst possible side-effect will be a spurious notification. + */ + if (ivc_channel_avail_count(ivc, ivc->tx_channel) == 1U) { + ivc->notify(ivc); + } + + return (int32_t)size; +} + +/* directly poke at the next frame to be tx'ed */ +void *tegra_ivc_write_get_next_frame(const struct ivc *ivc) +{ + if (ivc_check_write(ivc) != 0) { + return NULL; + } + + return ivc_frame_pointer(ivc, ivc->tx_channel, ivc->w_pos); +} + +/* advance the tx buffer */ +int32_t tegra_ivc_write_advance(struct ivc *ivc) +{ + int32_t result = ivc_check_write(ivc); + + if (result != 0) { + return result; + } + + /* + * Order any possible stores to the frame before update of w_pos. + */ + dmbst(); + + ivc_advance_tx(ivc); + + /* + * Ensure our write to w_pos occurs before our read from r_pos. + */ + dmbish(); + + /* + * Notify only upon transition from empty to non-empty. + * The available count can only asynchronously decrease, so the + * worst possible side-effect will be a spurious notification. + */ + if (ivc_channel_avail_count(ivc, ivc->tx_channel) == (uint32_t)1U) { + ivc->notify(ivc); + } + + return 0; +} + +void tegra_ivc_channel_reset(const struct ivc *ivc) +{ + ivc->tx_channel->state = ivc_state_sync; + ivc->notify(ivc); +} + +/* + * =============================================================== + * IVC State Transition Table - see tegra_ivc_channel_notified() + * =============================================================== + * + * local remote action + * ----- ------ ----------------------------------- + * SYNC EST + * SYNC ACK reset counters; move to EST; notify + * SYNC SYNC reset counters; move to ACK; notify + * ACK EST move to EST; notify + * ACK ACK move to EST; notify + * ACK SYNC reset counters; move to ACK; notify + * EST EST + * EST ACK + * EST SYNC reset counters; move to ACK; notify + * + * =============================================================== + */ +int32_t tegra_ivc_channel_notified(struct ivc *ivc) +{ + uint32_t peer_state; + + /* Copy the receiver's state out of shared memory. */ + peer_state = ivc->rx_channel->state; + + if (peer_state == (uint32_t)ivc_state_sync) { + /* + * Order observation of ivc_state_sync before stores clearing + * tx_channel. + */ + dmbld(); + + /* + * Reset tx_channel counters. The remote end is in the SYNC + * state and won't make progress until we change our state, + * so the counters are not in use at this time. + */ + ivc->tx_channel->w_count = 0U; + ivc->rx_channel->r_count = 0U; + + ivc->w_pos = 0U; + ivc->r_pos = 0U; + + /* + * Ensure that counters appear cleared before new state can be + * observed. + */ + dmbst(); + + /* + * Move to ACK state. We have just cleared our counters, so it + * is now safe for the remote end to start using these values. + */ + ivc->tx_channel->state = ivc_state_ack; + + /* + * Notify remote end to observe state transition. + */ + ivc->notify(ivc); + + } else if ((ivc->tx_channel->state == (uint32_t)ivc_state_sync) && + (peer_state == (uint32_t)ivc_state_ack)) { + /* + * Order observation of ivc_state_sync before stores clearing + * tx_channel. + */ + dmbld(); + + /* + * Reset tx_channel counters. The remote end is in the ACK + * state and won't make progress until we change our state, + * so the counters are not in use at this time. + */ + ivc->tx_channel->w_count = 0U; + ivc->rx_channel->r_count = 0U; + + ivc->w_pos = 0U; + ivc->r_pos = 0U; + + /* + * Ensure that counters appear cleared before new state can be + * observed. + */ + dmbst(); + + /* + * Move to ESTABLISHED state. We know that the remote end has + * already cleared its counters, so it is safe to start + * writing/reading on this channel. + */ + ivc->tx_channel->state = ivc_state_established; + + /* + * Notify remote end to observe state transition. + */ + ivc->notify(ivc); + + } else if (ivc->tx_channel->state == (uint32_t)ivc_state_ack) { + /* + * At this point, we have observed the peer to be in either + * the ACK or ESTABLISHED state. Next, order observation of + * peer state before storing to tx_channel. + */ + dmbld(); + + /* + * Move to ESTABLISHED state. We know that we have previously + * cleared our counters, and we know that the remote end has + * cleared its counters, so it is safe to start writing/reading + * on this channel. + */ + ivc->tx_channel->state = ivc_state_established; + + /* + * Notify remote end to observe state transition. + */ + ivc->notify(ivc); + + } else { + /* + * There is no need to handle any further action. Either the + * channel is already fully established, or we are waiting for + * the remote end to catch up with our current state. Refer + * to the diagram in "IVC State Transition Table" above. + */ + } + + return ((ivc->tx_channel->state == (uint32_t)ivc_state_established) ? 0 : -EAGAIN); +} + +size_t tegra_ivc_align(size_t size) +{ + return (size + (IVC_ALIGN - 1U)) & ~(IVC_ALIGN - 1U); +} + +size_t tegra_ivc_total_queue_size(size_t queue_size) +{ + if ((queue_size & (IVC_ALIGN - 1U)) != 0U) { + ERROR("queue_size (%d) must be %d-byte aligned\n", + (int32_t)queue_size, IVC_ALIGN); + return 0; + } + return queue_size + sizeof(struct ivc_channel_header); +} + +static int32_t check_ivc_params(uintptr_t queue_base1, uintptr_t queue_base2, + uint32_t nframes, uint32_t frame_size) +{ + assert((offsetof(struct ivc_channel_header, w_count) + & (IVC_ALIGN - 1U)) == 0U); + assert((offsetof(struct ivc_channel_header, r_count) + & (IVC_ALIGN - 1U)) == 0U); + assert((sizeof(struct ivc_channel_header) & (IVC_ALIGN - 1U)) == 0U); + + if (((uint64_t)nframes * (uint64_t)frame_size) >= 0x100000000ULL) { + ERROR("nframes * frame_size overflows\n"); + return -EINVAL; + } + + /* + * The headers must at least be aligned enough for counters + * to be accessed atomically. + */ + if ((queue_base1 & (IVC_ALIGN - 1U)) != 0U) { + ERROR("ivc channel start not aligned: %lx\n", queue_base1); + return -EINVAL; + } + if ((queue_base2 & (IVC_ALIGN - 1U)) != 0U) { + ERROR("ivc channel start not aligned: %lx\n", queue_base2); + return -EINVAL; + } + + if ((frame_size & (IVC_ALIGN - 1U)) != 0U) { + ERROR("frame size not adequately aligned: %u\n", + frame_size); + return -EINVAL; + } + + if (queue_base1 < queue_base2) { + if ((queue_base1 + ((uint64_t)frame_size * nframes)) > queue_base2) { + ERROR("queue regions overlap: %lx + %x, %x\n", + queue_base1, frame_size, + frame_size * nframes); + return -EINVAL; + } + } else { + if ((queue_base2 + ((uint64_t)frame_size * nframes)) > queue_base1) { + ERROR("queue regions overlap: %lx + %x, %x\n", + queue_base2, frame_size, + frame_size * nframes); + return -EINVAL; + } + } + + return 0; +} + +int32_t tegra_ivc_init(struct ivc *ivc, uintptr_t rx_base, uintptr_t tx_base, + uint32_t nframes, uint32_t frame_size, + ivc_notify_function notify) +{ + int32_t result; + + /* sanity check input params */ + if ((ivc == NULL) || (notify == NULL)) { + return -EINVAL; + } + + result = check_ivc_params(rx_base, tx_base, nframes, frame_size); + if (result != 0) { + return result; + } + + /* + * All sizes that can be returned by communication functions should + * fit in a 32-bit integer. + */ + if (frame_size > (1u << 31)) { + return -E2BIG; + } + + ivc->rx_channel = (struct ivc_channel_header *)rx_base; + ivc->tx_channel = (struct ivc_channel_header *)tx_base; + ivc->notify = notify; + ivc->frame_size = frame_size; + ivc->nframes = nframes; + ivc->w_pos = 0U; + ivc->r_pos = 0U; + + INFO("%s: done\n", __func__); + + return 0; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h new file mode 100644 index 0000000..1b31821 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BPMP_IVC_H +#define BPMP_IVC_H + +#include +#include +#include + +#define IVC_ALIGN U(64) +#define IVC_CHHDR_TX_FIELDS U(16) +#define IVC_CHHDR_RX_FIELDS U(16) + +struct ivc_channel_header; + +struct ivc { + struct ivc_channel_header *rx_channel; + struct ivc_channel_header *tx_channel; + uint32_t w_pos; + uint32_t r_pos; + void (*notify)(const struct ivc *); + uint32_t nframes; + uint32_t frame_size; +}; + +/* callback handler for notify on receiving a response */ +typedef void (* ivc_notify_function)(const struct ivc *); + +int32_t tegra_ivc_init(struct ivc *ivc, uintptr_t rx_base, uintptr_t tx_base, + uint32_t nframes, uint32_t frame_size, + ivc_notify_function notify); +size_t tegra_ivc_total_queue_size(size_t queue_size); +size_t tegra_ivc_align(size_t size); +int32_t tegra_ivc_channel_notified(struct ivc *ivc); +void tegra_ivc_channel_reset(const struct ivc *ivc); +int32_t tegra_ivc_write_advance(struct ivc *ivc); +void *tegra_ivc_write_get_next_frame(const struct ivc *ivc); +int32_t tegra_ivc_write(struct ivc *ivc, const void *buf, size_t size); +int32_t tegra_ivc_read_advance(struct ivc *ivc); +void *tegra_ivc_read_get_next_frame(const struct ivc *ivc); +int32_t tegra_ivc_read(struct ivc *ivc, void *buf, size_t max_read); +bool tegra_ivc_tx_empty(const struct ivc *ivc); +bool tegra_ivc_can_write(const struct ivc *ivc); +bool tegra_ivc_can_read(const struct ivc *ivc); + +#endif /* BPMP_IVC_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c new file mode 100644 index 0000000..8f55554 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define CLK_RST_DEV_L_SET 0x300 +#define CLK_RST_DEV_L_CLR 0x304 +#define CLK_BPMP_RST (1 << 1) + +#define EVP_BPMP_RESET_VECTOR 0x200 + +static const uint64_t flowctrl_offset_cpu_csr[4] = { + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU0_CSR), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 8), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 16) +}; + +static const uint64_t flowctrl_offset_halt_cpu[4] = { + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU0_EVENTS), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 8), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 16) +}; + +static const uint64_t flowctrl_offset_cc4_ctrl[4] = { + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 4), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 8), + (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 12) +}; + +static inline void tegra_fc_cc4_ctrl(int cpu_id, uint32_t val) +{ + mmio_write_32(flowctrl_offset_cc4_ctrl[cpu_id], val); + val = mmio_read_32(flowctrl_offset_cc4_ctrl[cpu_id]); +} + +static inline void tegra_fc_cpu_csr(int cpu_id, uint32_t val) +{ + mmio_write_32(flowctrl_offset_cpu_csr[cpu_id], val); + val = mmio_read_32(flowctrl_offset_cpu_csr[cpu_id]); +} + +static inline void tegra_fc_halt_cpu(int cpu_id, uint32_t val) +{ + mmio_write_32(flowctrl_offset_halt_cpu[cpu_id], val); + val = mmio_read_32(flowctrl_offset_halt_cpu[cpu_id]); +} + +static void tegra_fc_prepare_suspend(int cpu_id, uint32_t csr) +{ + uint32_t val; + + val = FLOWCTRL_HALT_GIC_IRQ | FLOWCTRL_HALT_GIC_FIQ | + FLOWCTRL_HALT_LIC_IRQ | FLOWCTRL_HALT_LIC_FIQ | + FLOWCTRL_WAITEVENT; + tegra_fc_halt_cpu(cpu_id, val); + + val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG | + FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu_id); + tegra_fc_cpu_csr(cpu_id, val | csr); +} + +/******************************************************************************* + * After this, no core can wake from C7 until the action is reverted. + * If a wake up event is asserted, the FC state machine will stall until + * the action is reverted. + ******************************************************************************/ +void tegra_fc_ccplex_pgexit_lock(void) +{ + unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK; + uint32_t flags = tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT) & ~INTERCEPT_IRQ_PENDING;; + uint32_t icept_cpu_flags[] = { + INTERCEPT_EXIT_PG_CORE0, + INTERCEPT_EXIT_PG_CORE1, + INTERCEPT_EXIT_PG_CORE2, + INTERCEPT_EXIT_PG_CORE3 + }; + + /* set the intercept flags */ + for (i = 0; i < ARRAY_SIZE(icept_cpu_flags); i++) { + + /* skip current CPU */ + if (i == cpu) + continue; + + /* enable power gate exit intercept locks */ + flags |= icept_cpu_flags[i]; + } + + tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, flags); + (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT); +} + +/******************************************************************************* + * Revert the ccplex powergate exit locks + ******************************************************************************/ +void tegra_fc_ccplex_pgexit_unlock(void) +{ + /* clear lock bits, clear pending interrupts */ + tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, INTERCEPT_IRQ_PENDING); + (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT); +} + +/******************************************************************************* + * Powerdn the current CPU + ******************************************************************************/ +void tegra_fc_cpu_powerdn(uint32_t mpidr) +{ + int cpu = mpidr & MPIDR_CPU_MASK; + + VERBOSE("CPU%d powering down...\n", cpu); + tegra_fc_prepare_suspend(cpu, 0); +} + +/******************************************************************************* + * Suspend the current CPU cluster + ******************************************************************************/ +void tegra_fc_cluster_idle(uint32_t mpidr) +{ + int cpu = mpidr & MPIDR_CPU_MASK; + uint32_t val; + + VERBOSE("Entering cluster idle state...\n"); + + tegra_fc_cc4_ctrl(cpu, 0); + + /* hardware L2 flush is faster for A53 only */ + tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, + !!MPIDR_AFFLVL1_VAL(mpidr)); + + /* suspend the CPU cluster */ + val = FLOWCTRL_PG_CPU_NONCPU << FLOWCTRL_ENABLE_EXT; + tegra_fc_prepare_suspend(cpu, val); +} + +/******************************************************************************* + * Power down the current CPU cluster + ******************************************************************************/ +void tegra_fc_cluster_powerdn(uint32_t mpidr) +{ + int cpu = mpidr & MPIDR_CPU_MASK; + uint32_t val; + + VERBOSE("Entering cluster powerdn state...\n"); + + tegra_fc_cc4_ctrl(cpu, 0); + + /* hardware L2 flush is faster for A53 only */ + tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, + read_midr() == CORTEX_A53_MIDR); + + /* power down the CPU cluster */ + val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT; + tegra_fc_prepare_suspend(cpu, val); +} + +/******************************************************************************* + * Check if cluster idle or power down state is allowed from this CPU + ******************************************************************************/ +bool tegra_fc_is_ccx_allowed(void) +{ + unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK; + uint32_t val; + bool ccx_allowed = true; + + for (i = 0; i < ARRAY_SIZE(flowctrl_offset_cpu_csr); i++) { + + /* skip current CPU */ + if (i == cpu) + continue; + + /* check if all other CPUs are already halted */ + val = mmio_read_32(flowctrl_offset_cpu_csr[i]); + if ((val & FLOWCTRL_CSR_HALT_MASK) == 0U) { + ccx_allowed = false; + } + } + + return ccx_allowed; +} + +/******************************************************************************* + * Suspend the entire SoC + ******************************************************************************/ +void tegra_fc_soc_powerdn(uint32_t mpidr) +{ + int cpu = mpidr & MPIDR_CPU_MASK; + uint32_t val; + + VERBOSE("Entering SoC powerdn state...\n"); + + tegra_fc_cc4_ctrl(cpu, 0); + + tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, 1); + + val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT; + tegra_fc_prepare_suspend(cpu, val); + + /* overwrite HALT register */ + tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT); +} + +/******************************************************************************* + * Power up the CPU + ******************************************************************************/ +void tegra_fc_cpu_on(int cpu) +{ + tegra_fc_cpu_csr(cpu, FLOWCTRL_CSR_ENABLE); + tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT | FLOWCTRL_HALT_SCLK); +} + +/******************************************************************************* + * Power down the CPU + ******************************************************************************/ +void tegra_fc_cpu_off(int cpu) +{ + uint32_t val; + + /* + * Flow controller powers down the CPU during wfi. The CPU would be + * powered on when it receives any interrupt. + */ + val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG | + FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu); + tegra_fc_cpu_csr(cpu, val); + tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT); + tegra_fc_cc4_ctrl(cpu, 0); +} + +/******************************************************************************* + * Inform the BPMP that we have completed the cluster power up + ******************************************************************************/ +void tegra_fc_lock_active_cluster(void) +{ + uint32_t val; + + val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL); + val |= FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK; + tegra_fc_write_32(FLOWCTRL_BPMP_CLUSTER_CONTROL, val); + val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL); +} + +/******************************************************************************* + * Power ON BPMP processor + ******************************************************************************/ +void tegra_fc_bpmp_on(uint32_t entrypoint) +{ + /* halt BPMP */ + tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT); + + /* Assert BPMP reset */ + mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST); + + /* Set reset address (stored in PMC_SCRATCH39) */ + mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, entrypoint); + while (entrypoint != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR)) + ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */ + + /* Wait for 2us before de-asserting the reset signal. */ + udelay(2); + + /* De-assert BPMP reset */ + mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_CLR, CLK_BPMP_RST); + + /* Un-halt BPMP */ + tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0); +} + +/******************************************************************************* + * Power OFF BPMP processor + ******************************************************************************/ +void tegra_fc_bpmp_off(void) +{ + /* halt BPMP */ + tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT); + + /* Assert BPMP reset */ + mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST); + + /* Clear reset address */ + mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, 0); + while (0 != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR)) + ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */ +} + +/******************************************************************************* + * Route legacy FIQ to the GICD + ******************************************************************************/ +void tegra_fc_enable_fiq_to_ccplex_routing(void) +{ + uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL); + + /* set the bit to pass FIQs to the GICD */ + tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val | FLOWCTRL_FIQ2CCPLEX_ENABLE); +} + +/******************************************************************************* + * Disable routing legacy FIQ to the GICD + ******************************************************************************/ +void tegra_fc_disable_fiq_to_ccplex_routing(void) +{ + uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL); + + /* clear the bit to pass FIQs to the GICD */ + tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val & ~FLOWCTRL_FIQ2CCPLEX_ENABLE); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c new file mode 100644 index 0000000..d68cdfd --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* DMA channel registers */ +#define DMA_CH_CSR U(0x0) +#define DMA_CH_CSR_WEIGHT_SHIFT U(10) +#define DMA_CH_CSR_XFER_MODE_SHIFT U(21) +#define DMA_CH_CSR_DMA_MODE_MEM2MEM U(4) +#define DMA_CH_CSR_DMA_MODE_FIXEDPATTERN U(6) +#define DMA_CH_CSR_IRQ_MASK_ENABLE (U(1) << 15) +#define DMA_CH_CSR_RUN_ONCE (U(1) << 27) +#define DMA_CH_CSR_ENABLE (U(1) << 31) + +#define DMA_CH_STAT U(0x4) +#define DMA_CH_STAT_BUSY (U(1) << 31) + +#define DMA_CH_SRC_PTR U(0xC) + +#define DMA_CH_DST_PTR U(0x10) + +#define DMA_CH_HI_ADR_PTR U(0x14) +#define DMA_CH_HI_ADR_PTR_SRC_MASK U(0xFF) +#define DMA_CH_HI_ADR_PTR_DST_SHIFT U(16) +#define DMA_CH_HI_ADR_PTR_DST_MASK U(0xFF) + +#define DMA_CH_MC_SEQ U(0x18) +#define DMA_CH_MC_SEQ_REQ_CNT_SHIFT U(25) +#define DMA_CH_MC_SEQ_REQ_CNT_VAL U(0x10) +#define DMA_CH_MC_SEQ_BURST_SHIFT U(23) +#define DMA_CH_MC_SEQ_BURST_16_WORDS U(0x3) + +#define DMA_CH_WORD_COUNT U(0x20) +#define DMA_CH_FIXED_PATTERN U(0x34) +#define DMA_CH_TZ U(0x38) +#define DMA_CH_TZ_ACCESS_ENABLE U(0) +#define DMA_CH_TZ_ACCESS_DISABLE U(3) + +#define MAX_TRANSFER_SIZE (1U*1024U*1024U*1024U) /* 1GB */ +#define GPCDMA_TIMEOUT_MS U(100) +#define GPCDMA_RESET_BIT (U(1) << 1) + +static bool init_done; + +static void tegra_gpcdma_write32(uint32_t offset, uint32_t val) +{ + mmio_write_32(TEGRA_GPCDMA_BASE + offset, val); +} + +static uint32_t tegra_gpcdma_read32(uint32_t offset) +{ + return mmio_read_32(TEGRA_GPCDMA_BASE + offset); +} + +static void tegra_gpcdma_init(void) +{ + /* assert reset for DMA engine */ + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPCDMA_RST_SET_REG_OFFSET, + GPCDMA_RESET_BIT); + + udelay(2); + + /* de-assert reset for DMA engine */ + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPCDMA_RST_CLR_REG_OFFSET, + GPCDMA_RESET_BIT); +} + +static void tegra_gpcdma_memcpy_priv(uint64_t dst_addr, uint64_t src_addr, + uint32_t num_bytes, uint32_t mode) +{ + uint32_t val, timeout = 0; + int32_t ret = 0; + + /* sanity check byte count */ + if ((num_bytes > MAX_TRANSFER_SIZE) || ((num_bytes & 0x3U) != U(0))) { + ret = -EINVAL; + } + + /* initialise GPCDMA block */ + if (!init_done) { + tegra_gpcdma_init(); + init_done = true; + } + + /* make sure channel isn't busy */ + val = tegra_gpcdma_read32(DMA_CH_STAT); + if ((val & DMA_CH_STAT_BUSY) == DMA_CH_STAT_BUSY) { + ERROR("DMA channel is busy\n"); + ret = -EBUSY; + } + + if (ret == 0) { + + /* disable any DMA transfers */ + tegra_gpcdma_write32(DMA_CH_CSR, 0); + + /* enable DMA access to TZDRAM */ + tegra_gpcdma_write32(DMA_CH_TZ, DMA_CH_TZ_ACCESS_ENABLE); + + /* configure MC sequencer */ + val = (DMA_CH_MC_SEQ_REQ_CNT_VAL << DMA_CH_MC_SEQ_REQ_CNT_SHIFT) | + (DMA_CH_MC_SEQ_BURST_16_WORDS << DMA_CH_MC_SEQ_BURST_SHIFT); + tegra_gpcdma_write32(DMA_CH_MC_SEQ, val); + + /* reset fixed pattern */ + tegra_gpcdma_write32(DMA_CH_FIXED_PATTERN, 0); + + /* populate src and dst address registers */ + tegra_gpcdma_write32(DMA_CH_SRC_PTR, (uint32_t)src_addr); + tegra_gpcdma_write32(DMA_CH_DST_PTR, (uint32_t)dst_addr); + + val = (uint32_t)((src_addr >> 32) & DMA_CH_HI_ADR_PTR_SRC_MASK); + val |= (uint32_t)(((dst_addr >> 32) & DMA_CH_HI_ADR_PTR_DST_MASK) << + DMA_CH_HI_ADR_PTR_DST_SHIFT); + tegra_gpcdma_write32(DMA_CH_HI_ADR_PTR, val); + + /* transfer size (in words) */ + tegra_gpcdma_write32(DMA_CH_WORD_COUNT, ((num_bytes >> 2) - 1U)); + + /* populate value for CSR */ + val = (mode << DMA_CH_CSR_XFER_MODE_SHIFT) | + DMA_CH_CSR_RUN_ONCE | (U(1) << DMA_CH_CSR_WEIGHT_SHIFT) | + DMA_CH_CSR_IRQ_MASK_ENABLE; + tegra_gpcdma_write32(DMA_CH_CSR, val); + + /* enable transfer */ + val = tegra_gpcdma_read32(DMA_CH_CSR); + val |= DMA_CH_CSR_ENABLE; + tegra_gpcdma_write32(DMA_CH_CSR, val); + + /* wait till transfer completes */ + do { + + /* read the status */ + val = tegra_gpcdma_read32(DMA_CH_STAT); + if ((val & DMA_CH_STAT_BUSY) != DMA_CH_STAT_BUSY) { + break; + } + + mdelay(1); + timeout++; + + } while (timeout < GPCDMA_TIMEOUT_MS); + + /* flag timeout error */ + if (timeout == GPCDMA_TIMEOUT_MS) { + ERROR("DMA transfer timed out\n"); + } + + dsbsy(); + + /* disable DMA access to TZDRAM */ + tegra_gpcdma_write32(DMA_CH_TZ, DMA_CH_TZ_ACCESS_DISABLE); + isb(); + } +} + +/******************************************************************************* + * Memcpy using GPCDMA block (Mem2Mem copy) + ******************************************************************************/ +void tegra_gpcdma_memcpy(uint64_t dst_addr, uint64_t src_addr, + uint32_t num_bytes) +{ + tegra_gpcdma_memcpy_priv(dst_addr, src_addr, num_bytes, + DMA_CH_CSR_DMA_MODE_MEM2MEM); +} + +/******************************************************************************* + * Memset using GPCDMA block (Fixed pattern write) + ******************************************************************************/ +void tegra_gpcdma_zeromem(uint64_t dst_addr, uint32_t num_bytes) +{ + tegra_gpcdma_memcpy_priv(dst_addr, 0, num_bytes, + DMA_CH_CSR_DMA_MODE_FIXEDPATTERN); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c new file mode 100644 index 0000000..b3dcd2a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2015-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 +#include + +/* Video Memory base and size (live values) */ +static uint64_t video_mem_base; +static uint64_t video_mem_size; + +/* + * Init SMMU. + */ +void tegra_memctrl_setup(void) +{ + /* + * Setup the Memory controller to allow only secure accesses to + * the TZDRAM carveout + */ + INFO("Tegra Memory Controller (v1)\n"); + + /* allow translations for all MC engines */ + tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_0_0, + (unsigned int)MC_SMMU_TRANSLATION_ENABLE); + tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_1_0, + (unsigned int)MC_SMMU_TRANSLATION_ENABLE); + tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_2_0, + (unsigned int)MC_SMMU_TRANSLATION_ENABLE); + tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_3_0, + (unsigned int)MC_SMMU_TRANSLATION_ENABLE); + tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_4_0, + (unsigned int)MC_SMMU_TRANSLATION_ENABLE); + + tegra_mc_write_32(MC_SMMU_ASID_SECURITY_0, MC_SMMU_ASID_SECURITY); + + tegra_mc_write_32(MC_SMMU_TLB_CONFIG_0, MC_SMMU_TLB_CONFIG_0_RESET_VAL); + tegra_mc_write_32(MC_SMMU_PTC_CONFIG_0, MC_SMMU_PTC_CONFIG_0_RESET_VAL); + + /* flush PTC and TLB */ + tegra_mc_write_32(MC_SMMU_PTC_FLUSH_0, MC_SMMU_PTC_FLUSH_ALL); + (void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */ + tegra_mc_write_32(MC_SMMU_TLB_FLUSH_0, MC_SMMU_TLB_FLUSH_ALL); + + /* enable SMMU */ + tegra_mc_write_32(MC_SMMU_CONFIG_0, + MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE); + (void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */ + + /* video memory carveout */ + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, + (uint32_t)(video_mem_base >> 32)); + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)video_mem_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size); +} + +/* + * Restore Memory Controller settings after "System Suspend" + */ +void tegra_memctrl_restore_settings(void) +{ + tegra_memctrl_setup(); +} + +/* + * Secure the BL31 DRAM aperture. + * + * phys_base = physical base of TZDRAM aperture + * size_in_bytes = size of aperture in bytes + */ +void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) +{ + /* + * Setup the Memory controller to allow only secure accesses to + * the TZDRAM carveout + */ + INFO("Configuring TrustZone DRAM Memory Carveout\n"); + + tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base); + tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20); +} + +static void tegra_clear_videomem(uintptr_t non_overlap_area_start, + unsigned long long non_overlap_area_size) +{ + int ret; + + /* + * Map the NS memory first, clean it and then unmap it. + */ + ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */ + non_overlap_area_start, /* VA */ + non_overlap_area_size, /* size */ + MT_NS | MT_RW | MT_EXECUTE_NEVER | + MT_NON_CACHEABLE); /* attrs */ + assert(ret == 0); + + zeromem((void *)non_overlap_area_start, non_overlap_area_size); + flush_dcache_range(non_overlap_area_start, non_overlap_area_size); + + mmap_remove_dynamic_region(non_overlap_area_start, + non_overlap_area_size); +} + +/* + * Program the Video Memory carveout region + * + * phys_base = physical base of aperture + * size_in_bytes = size of aperture in bytes + */ +void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) +{ + uintptr_t vmem_end_old = video_mem_base + (video_mem_size << 20); + uintptr_t vmem_end_new = phys_base + size_in_bytes; + unsigned long long non_overlap_area_size; + + /* + * Setup the Memory controller to restrict CPU accesses to the Video + * Memory region + */ + INFO("Configuring Video Memory Carveout\n"); + + /* + * Configure Memory Controller directly for the first time. + */ + if (video_mem_base == 0) + goto done; + + /* + * Clear the old regions now being exposed. The following cases + * can occur - + * + * 1. clear whole old region (no overlap with new region) + * 2. clear old sub-region below new base + * 3. clear old sub-region above new end + */ + INFO("Cleaning previous Video Memory Carveout\n"); + + if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) { + tegra_clear_videomem(video_mem_base, video_mem_size << 20); + } else { + if (video_mem_base < phys_base) { + non_overlap_area_size = phys_base - video_mem_base; + tegra_clear_videomem(video_mem_base, non_overlap_area_size); + } + if (vmem_end_old > vmem_end_new) { + non_overlap_area_size = vmem_end_old - vmem_end_new; + tegra_clear_videomem(vmem_end_new, non_overlap_area_size); + } + } + +done: + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, (uint32_t)(phys_base >> 32)); + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); + + /* store new values */ + video_mem_base = phys_base; + video_mem_size = size_in_bytes >> 20; +} + +/* + * During boot, USB3 and flash media (SDMMC/SATA) devices need access to + * IRAM. Because these clients connect to the MC and do not have a direct + * path to the IRAM, the MC implements AHB redirection during boot to allow + * path to IRAM. In this mode, accesses to a programmed memory address aperture + * are directed to the AHB bus, allowing access to the IRAM. The AHB aperture + * is defined by the IRAM_BASE_LO and IRAM_BASE_HI registers, which are + * initialized to disable this aperture. + * + * Once bootup is complete, we must program IRAM base to 0xffffffff and + * IRAM top to 0x00000000, thus disabling access to IRAM. DRAM is then + * potentially accessible in this address range. These aperture registers + * also have an access_control/lock bit. After disabling the aperture, the + * access_control register should be programmed to lock the registers. + */ +void tegra_memctrl_disable_ahb_redirection(void) +{ + /* program the aperture registers */ + tegra_mc_write_32(MC_IRAM_BASE_LO, 0xFFFFFFFF); + tegra_mc_write_32(MC_IRAM_TOP_LO, 0); + tegra_mc_write_32(MC_IRAM_BASE_TOP_HI, 0); + + /* lock the aperture registers */ + tegra_mc_write_32(MC_IRAM_REG_CTRL, MC_DISABLE_IRAM_CFG_WRITES); +} + +void tegra_memctrl_clear_pending_interrupts(void) +{ + uint32_t mcerr; + + /* check if there are any pending interrupts */ + mcerr = mmio_read_32(TEGRA_MC_BASE + MC_INTSTATUS); + + if (mcerr != (uint32_t)0U) { /* should not see error here */ + WARN("MC_INTSTATUS = 0x%x (should be zero)\n", mcerr); + mmio_write_32((TEGRA_MC_BASE + MC_INTSTATUS), mcerr); + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c new file mode 100644 index 0000000..4c38b56 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Video Memory base and size (live values) */ +static uint64_t video_mem_base; +static uint64_t video_mem_size_mb; + +/* + * Init Memory controller during boot. + */ +void tegra_memctrl_setup(void) +{ + INFO("Tegra Memory Controller (v2)\n"); + + /* allow platforms to program custom memory controller settings */ + plat_memctrl_setup(); +} + +/* + * Restore Memory Controller settings after "System Suspend" + */ +void tegra_memctrl_restore_settings(void) +{ + /* restore platform's memory controller settings */ + plat_memctrl_restore(); + + /* video memory carveout region */ + if (video_mem_base != 0ULL) { + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, + (uint32_t)video_mem_base); + assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_LO) + == (uint32_t)video_mem_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, + (uint32_t)(video_mem_base >> 32)); + assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_HI) + == (uint32_t)(video_mem_base >> 32)); + tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, + (uint32_t)video_mem_size_mb); + assert(tegra_mc_read_32(MC_VIDEO_PROTECT_SIZE_MB) + == (uint32_t)video_mem_size_mb); + + /* + * MCE propagates the VideoMem configuration values across the + * CCPLEX. + */ + mce_update_gsc_videomem(); + } +} + +/* + * Secure the BL31 DRAM aperture. + * + * phys_base = physical base of TZDRAM aperture + * size_in_bytes = size of aperture in bytes + */ +void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) +{ + /* + * Perform platform specific steps. + */ + plat_memctrl_tzdram_setup(phys_base, size_in_bytes); +} + +/* + * Secure the BL31 TZRAM aperture. + * + * phys_base = physical base of TZRAM aperture + * size_in_bytes = size of aperture in bytes + */ +void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) +{ + ; /* do nothing */ +} + +/* + * Save MC settings before "System Suspend" to TZDRAM + */ +void tegra_mc_save_context(uint64_t mc_ctx_addr) +{ + uint32_t i, num_entries = 0; + mc_regs_t *mc_ctx_regs; + const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + uint64_t tzdram_base = params_from_bl2->tzdram_base; + uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size; + + assert((mc_ctx_addr >= tzdram_base) && (mc_ctx_addr <= tzdram_end)); + + /* get MC context table */ + mc_ctx_regs = plat_memctrl_get_sys_suspend_ctx(); + assert(mc_ctx_regs != NULL); + + /* + * mc_ctx_regs[0].val contains the size of the context table minus + * the last entry. Sanity check the table size before we start with + * the context save operation. + */ + while (mc_ctx_regs[num_entries].reg != 0xFFFFFFFFU) { + num_entries++; + } + + /* panic if the sizes do not match */ + if (num_entries != mc_ctx_regs[0].val) { + ERROR("MC context size mismatch!"); + panic(); + } + + /* save MC register values */ + for (i = 1U; i < num_entries; i++) { + mc_ctx_regs[i].val = mmio_read_32(mc_ctx_regs[i].reg); + } + + /* increment by 1 to take care of the last entry */ + num_entries++; + + /* Save MC config settings */ + (void)memcpy((void *)mc_ctx_addr, mc_ctx_regs, + sizeof(mc_regs_t) * num_entries); + + /* save the MC table address */ + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO, + (uint32_t)mc_ctx_addr); + assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO) + == (uint32_t)mc_ctx_addr); + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI, + (uint32_t)(mc_ctx_addr >> 32)); + assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI) + == (uint32_t)(mc_ctx_addr >> 32)); +} + +static void tegra_lock_videomem_nonoverlap(uint64_t phys_base, + uint64_t size_in_bytes) +{ + uint32_t index; + uint64_t total_128kb_blocks = size_in_bytes >> 17; + uint64_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12; + uint64_t val; + + /* + * Reset the access configuration registers to restrict access to + * old Videomem aperture + */ + for (index = MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0; + index < ((uint32_t)MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 + (uint32_t)MC_GSC_CONFIG_REGS_SIZE); + index += 4U) { + tegra_mc_write_32(index, 0); + } + + /* + * Set the base. It must be 4k aligned, at least. + */ + assert((phys_base & (uint64_t)0xFFF) == 0U); + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, (uint32_t)phys_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, + (uint32_t)(phys_base >> 32) & (uint32_t)MC_GSC_BASE_HI_MASK); + + /* + * Set the aperture size + * + * total size = (number of 128KB blocks) + (number of remaining 4KB + * blocks) + * + */ + val = (uint32_t)((residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) | + total_128kb_blocks); + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, (uint32_t)val); + + /* + * Lock the configuration settings by enabling TZ-only lock and + * locking the configuration against any future changes from NS + * world. + */ + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_CFG, + (uint32_t)MC_GSC_ENABLE_TZ_LOCK_BIT); + + /* + * MCE propagates the GSC configuration values across the + * CCPLEX. + */ +} + +static void tegra_unlock_videomem_nonoverlap(void) +{ + /* Clear the base */ + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, 0); + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 0); + + /* Clear the size */ + tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, 0); +} + +static void tegra_clear_videomem(uintptr_t non_overlap_area_start, + unsigned long long non_overlap_area_size) +{ + int ret; + + INFO("Cleaning previous Video Memory Carveout\n"); + + /* + * Map the NS memory first, clean it and then unmap it. + */ + ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */ + non_overlap_area_start, /* VA */ + non_overlap_area_size, /* size */ + MT_DEVICE | MT_RW | MT_NS); /* attrs */ + assert(ret == 0); + + zeromem((void *)non_overlap_area_start, non_overlap_area_size); + flush_dcache_range(non_overlap_area_start, non_overlap_area_size); + + ret = mmap_remove_dynamic_region(non_overlap_area_start, + non_overlap_area_size); + assert(ret == 0); +} + +static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base, + unsigned long size_in_bytes) +{ + uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20); + uintptr_t vmem_end_new = phys_base + size_in_bytes; + unsigned long long non_overlap_area_size; + + /* + * Clear the old regions now being exposed. The following cases + * can occur - + * + * 1. clear whole old region (no overlap with new region) + * 2. clear old sub-region below new base + * 3. clear old sub-region above new end + */ + if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) { + tegra_clear_videomem(video_mem_base, + video_mem_size_mb << 20U); + } else { + if (video_mem_base < phys_base) { + non_overlap_area_size = phys_base - video_mem_base; + tegra_clear_videomem(video_mem_base, non_overlap_area_size); + } + if (vmem_end_old > vmem_end_new) { + non_overlap_area_size = vmem_end_old - vmem_end_new; + tegra_clear_videomem(vmem_end_new, non_overlap_area_size); + } + } +} + +/* + * Program the Video Memory carveout region + * + * phys_base = physical base of aperture + * size_in_bytes = size of aperture in bytes + */ +void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) +{ + /* + * Setup the Memory controller to restrict CPU accesses to the Video + * Memory region + */ + + INFO("Configuring Video Memory Carveout\n"); + + if (video_mem_base != 0U) { + /* + * Lock the non overlapping memory being cleared so that + * other masters do not accidently write to it. The memory + * would be unlocked once the non overlapping region is + * cleared and the new memory settings take effect. + */ + tegra_lock_videomem_nonoverlap(video_mem_base, + video_mem_size_mb << 20); + } + + /* program the Videomem aperture */ + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, + (uint32_t)(phys_base >> 32)); + tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); + + /* Redundancy check for Video Protect setting */ + assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_LO) + == (uint32_t)phys_base); + assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_HI) + == (uint32_t)(phys_base >> 32)); + assert(tegra_mc_read_32(MC_VIDEO_PROTECT_SIZE_MB) + == (size_in_bytes >> 20)); + + /* + * MCE propagates the VideoMem configuration values across the + * CCPLEX. + */ + (void)mce_update_gsc_videomem(); + + /* Clear the non-overlapping memory */ + if (video_mem_base != 0U) { + tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes); + tegra_unlock_videomem_nonoverlap(); + } + + /* store new values */ + video_mem_base = phys_base; + video_mem_size_mb = (uint64_t)size_in_bytes >> 20; +} + +/* + * This feature exists only for v1 of the Tegra Memory Controller. + */ +void tegra_memctrl_disable_ahb_redirection(void) +{ + ; /* do nothing */ +} + +void tegra_memctrl_clear_pending_interrupts(void) +{ + ; /* do nothing */ +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c new file mode 100644 index 0000000..6c5a73b --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#define RESET_ENABLE 0x10U + +/* Module IDs used during power ungate procedure */ +static const uint32_t pmc_cpu_powergate_id[4] = { + 14, /* CPU 0 */ + 9, /* CPU 1 */ + 10, /* CPU 2 */ + 11 /* CPU 3 */ +}; + +/******************************************************************************* + * Power ungate CPU to start the boot process. CPU reset vectors must be + * populated before calling this function. + ******************************************************************************/ +void tegra_pmc_cpu_on(int32_t cpu) +{ + uint32_t val; + + /* + * Check if CPU is already power ungated + */ + val = tegra_pmc_read_32(PMC_PWRGATE_STATUS); + if ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U) { + /* + * The PMC deasserts the START bit when it starts the power + * ungate process. Loop till no power toggle is in progress. + */ + do { + val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE); + } while ((val & PMC_TOGGLE_START) != 0U); + + /* + * Start the power ungate procedure + */ + val = pmc_cpu_powergate_id[cpu] | PMC_TOGGLE_START; + tegra_pmc_write_32(PMC_PWRGATE_TOGGLE, val); + + /* + * The PMC deasserts the START bit when it starts the power + * ungate process. Loop till powergate START bit is asserted. + */ + do { + val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE); + } while ((val & (1U << 8)) != 0U); + + /* loop till the CPU is power ungated */ + do { + val = tegra_pmc_read_32(PMC_PWRGATE_STATUS); + } while ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U); + } +} + +/******************************************************************************* + * Setup CPU vectors for resume from deep sleep + ******************************************************************************/ +void tegra_pmc_cpu_setup(uint64_t reset_addr) +{ + uint32_t val; + + tegra_pmc_write_32(PMC_SECURE_SCRATCH34, + ((uint32_t)reset_addr & 0xFFFFFFFFU) | 1U); + val = (uint32_t)(reset_addr >> 32U); + tegra_pmc_write_32(PMC_SECURE_SCRATCH35, val & 0x7FFU); +} + +/******************************************************************************* + * Lock CPU vectors to restrict further writes + ******************************************************************************/ +void tegra_pmc_lock_cpu_vectors(void) +{ + uint32_t val; + + /* lock PMC_SECURE_SCRATCH22 */ + val = tegra_pmc_read_32(PMC_SECURE_DISABLE2); + val |= PMC_SECURE_DISABLE2_WRITE22_ON; + tegra_pmc_write_32(PMC_SECURE_DISABLE2, val); + + /* lock PMC_SECURE_SCRATCH34/35 */ + val = tegra_pmc_read_32(PMC_SECURE_DISABLE3); + val |= (PMC_SECURE_DISABLE3_WRITE34_ON | + PMC_SECURE_DISABLE3_WRITE35_ON); + tegra_pmc_write_32(PMC_SECURE_DISABLE3, val); +} + +/******************************************************************************* + * Find out if this is the last standing CPU + ******************************************************************************/ +bool tegra_pmc_is_last_on_cpu(void) +{ + int i, cpu = read_mpidr() & MPIDR_CPU_MASK; + uint32_t val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);; + bool status = true; + + /* check if this is the last standing CPU */ + for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) { + + /* skip the current CPU */ + if (i == cpu) + continue; + + /* are other CPUs already power gated? */ + if ((val & ((uint32_t)1 << pmc_cpu_powergate_id[i])) != 0U) { + status = false; + } + } + + return status; +} + +/******************************************************************************* + * Handler to be called on exiting System suspend. Right now only DPD registers + * are cleared. + ******************************************************************************/ +void tegra_pmc_resume(void) +{ + + /* Clear DPD sample */ + mmio_write_32((TEGRA_PMC_BASE + PMC_IO_DPD_SAMPLE), 0x0); + + /* Clear DPD Enable */ + mmio_write_32((TEGRA_PMC_BASE + PMC_DPD_ENABLE_0), 0x0); +} + +/******************************************************************************* + * Restart the system + ******************************************************************************/ +__dead2 void tegra_pmc_system_reset(void) +{ + uint32_t reg; + + reg = tegra_pmc_read_32(PMC_CONFIG); + reg |= RESET_ENABLE; /* restart */ + tegra_pmc_write_32(PMC_CONFIG, reg); + wfi(); + + ERROR("Tegra System Reset: operation not handled.\n"); + panic(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c new file mode 100644 index 0000000..53f47e0 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* + * This function writes SC7 entry opcode to notify PSC from CCPLEX. + * The protocol is to write the command to the MBOX and then trigger + * a doorbell. + */ +void tegra_psc_notify_sc7_entry(void) +{ + INFO("%s: send SC7 opcode to PSC\n", __func__); + mmio_write_32((TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_IN), + PSC_MBOX_TZ_OPCODE_ENTER_SC7); + + mmio_write_32((TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_EXT_CTRL), + (PSC_MBOX_OUT_DONE | PSC_MBOX_IN_VALID)); +} + +/* + * This funciton read back the ACKs from PSC mailbox and verify their values. + * The PSC mailbox should return the OPCODE in out0 and return 0 in out1 for + * PSC operation done. + */ +void tegra_psc_wait_for_ack(void) +{ + uint32_t timeout_count = PSC_MBOX_ACK_TIMEOUT_MAX_USEC; + uint32_t val, out_valid; + + do { + if (timeout_count-- == 0U) { + ERROR("!! %s: PSC handshake fail !!", __func__); + panic(); + } + + udelay(1U); + + out_valid = mmio_read_32(TEGRA_PSC_MBOX_TZ_BASE + + PSC_MBOX_TZ_PSC_CTRL); + + } while (PSC_MBOX_OUT_VALID != (out_valid & PSC_MBOX_OUT_VALID)); + + INFO("%s: PSC handshake done\n", __func__); + + /* Get first ACK from PSC_MBOX_TZ_OUT_0 */ + val = mmio_read_32(TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_OUT_0); + assert(val == PSC_MBOX_TZ_OPCODE_ENTER_SC7); + + /* Get second ACK from PSC_MBOX_TZ_OUT_1 */ + val = mmio_read_32(TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_OUT_1); + assert(val == PSC_MBOX_SC7_ENTRY_PASS); + + /* Trigger MBOX_OUT_DONE, notify PSC handshake finish */ + mmio_write_32((TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_EXT_CTRL), + PSC_MBOX_OUT_DONE); +} + diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c new file mode 100644 index 0000000..4189b00 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016-2018, 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 + +extern void memcpy16(void *dest, const void *src, unsigned int length); + +#define SMMU_NUM_CONTEXTS 64U +#define SMMU_CONTEXT_BANK_MAX_IDX 64U + +#define MISMATCH_DETECTED 0x55AA55AAU + +/* + * Init SMMU during boot or "System Suspend" exit + */ +void tegra_smmu_init(void) +{ + uint32_t val, cb_idx, smmu_id, ctx_base; + uint32_t num_smmu_devices = plat_get_num_smmu_devices(); + + for (smmu_id = 0U; smmu_id < num_smmu_devices; smmu_id++) { + /* Program the SMMU pagesize and reset CACHE_LOCK bit */ + val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR); + val |= SMMU_GSR0_PGSIZE_64K; + val &= (uint32_t)~SMMU_ACR_CACHE_LOCK_ENABLE_BIT; + tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val); + + /* reset CACHE LOCK bit for NS Aux. Config. Register */ + val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR); + val &= (uint32_t)~SMMU_ACR_CACHE_LOCK_ENABLE_BIT; + tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val); + + /* disable TCU prefetch for all contexts */ + ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS) + + SMMU_CBn_ACTLR; + for (cb_idx = 0U; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) { + val = tegra_smmu_read_32(smmu_id, + ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx)); + val &= (uint32_t)~SMMU_CBn_ACTLR_CPRE_BIT; + tegra_smmu_write_32(smmu_id, ctx_base + + (SMMU_GSR0_PGSIZE_64K * cb_idx), val); + } + + /* set CACHE LOCK bit for NS Aux. Config. Register */ + val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR); + val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT; + tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val); + + /* set CACHE LOCK bit for S Aux. Config. Register */ + val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR); + val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT; + tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val); + } +} + +/* + * Verify SMMU settings have not been altered during boot + */ +void tegra_smmu_verify(void) +{ + uint32_t cb_idx, ctx_base, smmu_id, val; + uint32_t num_smmu_devices = plat_get_num_smmu_devices(); + uint32_t mismatch = 0U; + + for (smmu_id = 0U; smmu_id < num_smmu_devices; smmu_id++) { + /* check PGSIZE_64K bit inr S Aux. Config. Register */ + val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR); + if (0U == (val & SMMU_GSR0_PGSIZE_64K)) { + ERROR("%s: PGSIZE_64K Mismatch - smmu_id=%d, GSR0_SECURE_ACR=%x\n", + __func__, smmu_id, val); + mismatch = MISMATCH_DETECTED; + } + + /* check CACHE LOCK bit in S Aux. Config. Register */ + if (0U == (val & SMMU_ACR_CACHE_LOCK_ENABLE_BIT)) { + ERROR("%s: CACHE_LOCK Mismatch - smmu_id=%d, GSR0_SECURE_ACR=%x\n", + __func__, smmu_id, val); + mismatch = MISMATCH_DETECTED; + } + + /* check CACHE LOCK bit in NS Aux. Config. Register */ + val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR); + if (0U == (val & SMMU_ACR_CACHE_LOCK_ENABLE_BIT)) { + ERROR("%s: Mismatch - smmu_id=%d, GNSR_ACR=%x\n", + __func__, smmu_id, val); + mismatch = MISMATCH_DETECTED; + } + + /* verify TCU prefetch for all contexts is disabled */ + ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS) + + SMMU_CBn_ACTLR; + for (cb_idx = 0U; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) { + val = tegra_smmu_read_32(smmu_id, + ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx)); + if (0U != (val & SMMU_CBn_ACTLR_CPRE_BIT)) { + ERROR("%s: Mismatch - smmu_id=%d, cb_idx=%d, GSR0_PGSIZE_64K=%x\n", + __func__, smmu_id, cb_idx, val); + mismatch = MISMATCH_DETECTED; + } + } + } + + /* Treat configuration mismatch as fatal */ + if ((mismatch == MISMATCH_DETECTED) && tegra_platform_is_silicon()) { + panic(); + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S b/arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S new file mode 100644 index 0000000..7040386 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + +#define CONSOLE_NUM_BYTES_SHIFT 24 +#define CONSOLE_FLUSH_DATA_TO_PORT (1 << 26) +#define CONSOLE_RING_DOORBELL (1 << 31) +#define CONSOLE_IS_BUSY (1 << 31) +#define CONSOLE_TIMEOUT 0xC000 /* 50 ms */ + + /* + * This file contains a driver implementation to make use of the + * real console implementation provided by the SPE firmware running + * SoCs after Tegra186. + * + * This console is shared by multiple components and the SPE firmware + * finally displays everything on the UART port. + */ + + .globl console_spe_core_init + .globl console_spe_core_putc + .globl console_spe_core_getc + .globl console_spe_core_flush + .globl console_spe_putc + .globl console_spe_getc + .globl console_spe_flush + .globl console_spe_register + +.macro check_if_console_is_ready base, tmp1, tmp2, label + /* wait until spe is ready or timeout expires */ + mrs \tmp2, cntps_tval_el1 +1: ldr \tmp1, [\base] + and \tmp1, \tmp1, #CONSOLE_IS_BUSY + cbz \tmp1, 2f + mrs \tmp1, cntps_tval_el1 + sub \tmp1, \tmp2, \tmp1 + cmp \tmp1, #CONSOLE_TIMEOUT + b.lt 1b + b \label +2: +.endm + + /* ------------------------------------------------- + * int console_spe_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new spe + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ------------------------------------------------- + */ +func console_spe_register + /* Check the input base address */ + cbz x0, register_fail + + /* Dont use clock or baud rate, so ok to overwrite them */ + check_if_console_is_ready x0, x1, x2, register_fail + + cbz x3, register_fail + str x0, [x3, #CONSOLE_T_BASE] + mov x0, x3 + finish_console_register spe putc=1, getc=1, flush=1 + +register_fail: + mov w0, wzr + ret +endfunc console_spe_register + + /* -------------------------------------------------------- + * int console_spe_core_putc(int c, uintptr_t base_addr) + * 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 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2, x3 + * -------------------------------------------------------- + */ +func console_spe_core_putc + /* save x3 as it will get clobbered */ + adr x2, spe_console_stack + str x3, [x2] + + /* Check the input parameter */ + cbz x1, putc_error + + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne not_eol + + check_if_console_is_ready x1, x2, x3, putc_error + + /* spe is ready */ + mov w2, #0xD /* '\r' */ + and w2, w2, #0xFF + mov w3, #(CONSOLE_RING_DOORBELL | (1 << CONSOLE_NUM_BYTES_SHIFT)) + orr w2, w2, w3 + str w2, [x1] + +not_eol: + check_if_console_is_ready x1, x2, x3, putc_error + + /* spe is ready */ + mov w2, w0 + and w2, w2, #0xFF + mov w3, #(CONSOLE_RING_DOORBELL | (1 << CONSOLE_NUM_BYTES_SHIFT)) + orr w2, w2, w3 + str w2, [x1] + + /* restore x3 */ + adr x2, spe_console_stack + ldr x3, [x2] + mov x2, #0 + ret +putc_error: + mov w0, #-1 + + /* restore x3 */ + adr x2, spe_console_stack + ldr x3, [x2] + mov x2, #0 + ret +endfunc console_spe_core_putc + + /* -------------------------------------------------------- + * int console_spe_putc(int c, console_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 structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_spe_putc + ldr x1, [x1, #CONSOLE_T_BASE] + b console_spe_core_putc +endfunc console_spe_putc + + /* --------------------------------------------- + * int console_spe_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - pointer to console_t structure + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_spe_getc + mov w0, #-1 + ret +endfunc console_spe_getc + + /* ------------------------------------------------- + * void console_spe_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : void. + * Clobber list : x0, x1 + * ------------------------------------------------- + */ +func console_spe_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* flush console */ + mov w1, #(CONSOLE_RING_DOORBELL | CONSOLE_FLUSH_DATA_TO_PORT) + str w1, [x0] + ret +endfunc console_spe_core_flush + + /* --------------------------------------------- + * void console_spe_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_spe_flush + ldr x0, [x0, #CONSOLE_T_BASE] + b console_spe_core_flush +endfunc console_spe_flush + + /* scratch space to store x3 register from console_core_putc */ + .data + .align 3 +spe_console_stack: + .quad 0 diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h new file mode 100644 index 0000000..dc3fb6b --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BPMP_H +#define BPMP_H + +#include + +/* macro to enable clock to the Atomics block */ +#define CAR_ENABLE_ATOMICS (1U << 16) + +/* command to get the channel base addresses from bpmp */ +#define ATOMIC_CMD_GET 4U + +/* Hardware IRQ # used to signal bpmp of an incoming command */ +#define INT_SHR_SEM_OUTBOX_FULL 6U + +/* macros to decode the bpmp's state */ +#define CH_MASK(ch) ((uint32_t)0x3 << ((ch) * 2U)) +#define MA_FREE(ch) ((uint32_t)0x2 << ((ch) * 2U)) +#define MA_ACKD(ch) ((uint32_t)0x3 << ((ch) * 2U)) + +/* response from bpmp to indicate it has powered up */ +#define SIGN_OF_LIFE 0xAAAAAAAAU + +/* flags to indicate bpmp driver's state */ +#define BPMP_NOT_PRESENT 0xF00DBEEFU +#define BPMP_INIT_COMPLETE 0xBEEFF00DU +#define BPMP_INIT_PENDING 0xDEADBEEFU +#define BPMP_SUSPEND_ENTRY 0xF00DCAFEU + +/* requests serviced by the bpmp */ +#define MRQ_PING 0 +#define MRQ_QUERY_TAG 1 +#define MRQ_DO_IDLE 2 +#define MRQ_TOLERATE_IDLE 3 +#define MRQ_MODULE_LOAD 4 +#define MRQ_MODULE_UNLOAD 5 +#define MRQ_SWITCH_CLUSTER 6 +#define MRQ_TRACE_MODIFY 7 +#define MRQ_WRITE_TRACE 8 +#define MRQ_THREADED_PING 9 +#define MRQ_CPUIDLE_USAGE 10 +#define MRQ_MODULE_MAIL 11 +#define MRQ_SCX_ENABLE 12 +#define MRQ_BPMPIDLE_USAGE 14 +#define MRQ_HEAP_USAGE 15 +#define MRQ_SCLK_SKIP_SET_RATE 16 +#define MRQ_ENABLE_SUSPEND 17 +#define MRQ_PASR_MASK 18 +#define MRQ_DEBUGFS 19 +#define MRQ_THERMAL 27 + +/* Tegra PM states as known to BPMP */ +#define TEGRA_PM_CC1 9 +#define TEGRA_PM_CC4 12 +#define TEGRA_PM_CC6 14 +#define TEGRA_PM_CC7 15 +#define TEGRA_PM_SC1 17 +#define TEGRA_PM_SC2 18 +#define TEGRA_PM_SC3 19 +#define TEGRA_PM_SC4 20 +#define TEGRA_PM_SC7 23 + +/* flag to indicate if entry into a CCx power state is allowed */ +#define BPMP_CCx_ALLOWED 0U + +/* number of communication channels to interact with the bpmp */ +#define NR_CHANNELS 4U + +/* flag to ask bpmp to acknowledge command packet */ +#define NO_ACK (0U << 0U) +#define DO_ACK (1U << 0U) + +/* size of the command/response data */ +#define MSG_DATA_MAX_SZ 120U + +/** + * command/response packet to/from the bpmp + * + * command + * ------- + * code: MRQ_* command + * flags: DO_ACK or NO_ACK + * data: + * [0] = cpu # + * [1] = cluster power state (TEGRA_PM_CCx) + * [2] = system power state (TEGRA_PM_SCx) + * + * response + * --------- + * code: error code + * flags: not used + * data: + * [0-3] = response value + */ +typedef struct mb_data { + int32_t code; + uint32_t flags; + uint8_t data[MSG_DATA_MAX_SZ]; +} mb_data_t; + +/** + * Function to initialise the interface with the bpmp + */ +int tegra_bpmp_init(void); + +/** + * Function to suspend the interface with the bpmp + */ +void tegra_bpmp_suspend(void); + +/** + * Function to resume the interface with the bpmp + */ +void tegra_bpmp_resume(void); + +/** + * Handler to send a MRQ_* command to the bpmp + */ +int32_t tegra_bpmp_send_receive_atomic(int mrq, const void *ob_data, int ob_sz, + void *ib_data, int ib_sz); + +#endif /* BPMP_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h new file mode 100644 index 0000000..0595a29 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BPMP_IPC_H +#define BPMP_IPC_H + +#include +#include +#include + + +/* + * Struct describing bpmp_ipc channel info + */ +struct bpmp_ipc_platform_data { + uint64_t bpmp_ipc_tx_base; + uint64_t bpmp_ipc_rx_base; + uint32_t bpmp_ipc_map_size; +}; + +/** + * Currently supported reset identifiers + */ +#define TEGRA_RESET_ID_XUSB_PADCTL U(114) +#define TEGRA_RESET_ID_GPCDMA U(70) + +/** + * Function to initialise the IPC with the bpmp + */ +int32_t tegra_bpmp_ipc_init(void); + +/** + * Handler to reset a module + */ +int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id); + +/** + * Handler to enable clock to a module. Only SE device is + * supported for now. + */ +int tegra_bpmp_ipc_enable_clock(uint32_t clk_id); + +/** + * Handler to disable clock to a module. Only SE device is + * supported for now. + */ +int tegra_bpmp_ipc_disable_clock(uint32_t clk_id); + +/** + * Handler to get bpmp_ipc channel info. + */ +struct bpmp_ipc_platform_data *plat_get_bpmp_ipc_data(void); + +#endif /* BPMP_IPC_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h new file mode 100644 index 0000000..e5ab600 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FLOWCTRL_H +#define FLOWCTRL_H + +#include + +#include + +#include + +#define FLOWCTRL_HALT_CPU0_EVENTS (0x0U) +#define FLOWCTRL_WAITEVENT (2U << 29) +#define FLOWCTRL_WAIT_FOR_INTERRUPT (4U << 29) +#define FLOWCTRL_JTAG_RESUME (1U << 28) +#define FLOWCTRL_HALT_SCLK (1U << 27) +#define FLOWCTRL_HALT_LIC_IRQ (1U << 11) +#define FLOWCTRL_HALT_LIC_FIQ (1U << 10) +#define FLOWCTRL_HALT_GIC_IRQ (1U << 9) +#define FLOWCTRL_HALT_GIC_FIQ (1U << 8) +#define FLOWCTRL_HALT_BPMP_EVENTS (0x4U) +#define FLOWCTRL_CPU0_CSR (0x8U) +#define FLOWCTRL_CSR_HALT_MASK (1U << 22) +#define FLOWCTRL_CSR_PWR_OFF_STS (1U << 16) +#define FLOWCTRL_CSR_INTR_FLAG (1U << 15) +#define FLOWCTRL_CSR_EVENT_FLAG (1U << 14) +#define FLOWCTRL_CSR_IMMEDIATE_WAKE (1U << 3) +#define FLOWCTRL_CSR_ENABLE (1U << 0) +#define FLOWCTRL_HALT_CPU1_EVENTS (0x14U) +#define FLOWCTRL_CPU1_CSR (0x18U) +#define FLOW_CTLR_FLOW_DBG_QUAL (0x50U) +#define FLOWCTRL_FIQ2CCPLEX_ENABLE (1U << 28) +#define FLOWCTRL_FC_SEQ_INTERCEPT (0x5cU) +#define INTERCEPT_IRQ_PENDING (0xffU) +#define INTERCEPT_HVC (U(1) << 21) +#define INTERCEPT_ENTRY_CC4 (U(1) << 20) +#define INTERCEPT_ENTRY_PG_NONCPU (U(1) << 19) +#define INTERCEPT_EXIT_PG_NONCPU (U(1) << 18) +#define INTERCEPT_ENTRY_RG_CPU (U(1) << 17) +#define INTERCEPT_EXIT_RG_CPU (U(1) << 16) +#define INTERCEPT_ENTRY_PG_CORE0 (U(1) << 15) +#define INTERCEPT_EXIT_PG_CORE0 (U(1) << 14) +#define INTERCEPT_ENTRY_PG_CORE1 (U(1) << 13) +#define INTERCEPT_EXIT_PG_CORE1 (U(1) << 12) +#define INTERCEPT_ENTRY_PG_CORE2 (U(1) << 11) +#define INTERCEPT_EXIT_PG_CORE2 (U(1) << 10) +#define INTERCEPT_ENTRY_PG_CORE3 (U(1) << 9) +#define INTERCEPT_EXIT_PG_CORE3 (U(1) << 8) +#define INTERRUPT_PENDING_NONCPU (U(1) << 7) +#define INTERRUPT_PENDING_CRAIL (U(1) << 6) +#define INTERRUPT_PENDING_CORE0 (U(1) << 5) +#define INTERRUPT_PENDING_CORE1 (U(1) << 4) +#define INTERRUPT_PENDING_CORE2 (U(1) << 3) +#define INTERRUPT_PENDING_CORE3 (U(1) << 2) +#define CC4_INTERRUPT_PENDING (U(1) << 1) +#define HVC_INTERRUPT_PENDING (U(1) << 0) +#define FLOWCTRL_CC4_CORE0_CTRL (0x6cU) +#define FLOWCTRL_WAIT_WFI_BITMAP (0x100U) +#define FLOWCTRL_L2_FLUSH_CONTROL (0x94U) +#define FLOWCTRL_BPMP_CLUSTER_CONTROL (0x98U) +#define FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK (1U << 2) + +#define FLOWCTRL_ENABLE_EXT 12U +#define FLOWCTRL_ENABLE_EXT_MASK 3U +#define FLOWCTRL_PG_CPU_NONCPU 0x1U +#define FLOWCTRL_TURNOFF_CPURAIL 0x2U + +static inline uint32_t tegra_fc_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_FLOWCTRL_BASE + off); +} + +static inline void tegra_fc_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_FLOWCTRL_BASE + off, val); +} + +void tegra_fc_bpmp_on(uint32_t entrypoint); +void tegra_fc_bpmp_off(void); +void tegra_fc_ccplex_pgexit_lock(void); +void tegra_fc_ccplex_pgexit_unlock(void); +void tegra_fc_cluster_idle(uint32_t midr); +void tegra_fc_cpu_powerdn(uint32_t mpidr); +void tegra_fc_cluster_powerdn(uint32_t midr); +void tegra_fc_cpu_on(int cpu); +void tegra_fc_cpu_off(int cpu); +void tegra_fc_disable_fiq_to_ccplex_routing(void); +void tegra_fc_enable_fiq_to_ccplex_routing(void); +bool tegra_fc_is_ccx_allowed(void); +void tegra_fc_lock_active_cluster(void); +void tegra_fc_soc_powerdn(uint32_t midr); + +#endif /* FLOWCTRL_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h new file mode 100644 index 0000000..a59df37 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPCDMA_H +#define GPCDMA_H + +#include + +void tegra_gpcdma_memcpy(uint64_t dst_addr, uint64_t src_addr, + uint32_t num_bytes); +void tegra_gpcdma_zeromem(uint64_t dst_addr, uint32_t num_bytes); + +#endif /* GPCDMA_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h new file mode 100644 index 0000000..5f1bb4f --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCE_H +#define MCE_H + +#include + +#include + +/******************************************************************************* + * MCE commands + ******************************************************************************/ +typedef enum mce_cmd { + MCE_CMD_ENTER_CSTATE = 0U, + MCE_CMD_UPDATE_CSTATE_INFO = 1U, + MCE_CMD_UPDATE_CROSSOVER_TIME = 2U, + MCE_CMD_READ_CSTATE_STATS = 3U, + MCE_CMD_WRITE_CSTATE_STATS = 4U, + MCE_CMD_IS_SC7_ALLOWED = 5U, + MCE_CMD_ONLINE_CORE = 6U, + MCE_CMD_CC3_CTRL = 7U, + MCE_CMD_ECHO_DATA = 8U, + MCE_CMD_READ_VERSIONS = 9U, + MCE_CMD_ENUM_FEATURES = 10U, + MCE_CMD_ROC_FLUSH_CACHE_TRBITS = 11U, + MCE_CMD_ENUM_READ_MCA = 12U, + MCE_CMD_ENUM_WRITE_MCA = 13U, + MCE_CMD_ROC_FLUSH_CACHE = 14U, + MCE_CMD_ROC_CLEAN_CACHE = 15U, + MCE_CMD_ENABLE_LATIC = 16U, + MCE_CMD_UNCORE_PERFMON_REQ = 17U, + MCE_CMD_MISC_CCPLEX = 18U, + MCE_CMD_IS_CCX_ALLOWED = 0xFEU, + MCE_CMD_MAX = 0xFFU, +} mce_cmd_t; + +#define MCE_CMD_MASK 0xFFU + +/******************************************************************************* + * Timeout value used to powerdown a core + ******************************************************************************/ +#define MCE_CORE_SLEEP_TIME_INFINITE 0xFFFFFFFFU + +/******************************************************************************* + * Struct to prepare UPDATE_CSTATE_INFO request + ******************************************************************************/ +typedef struct mce_cstate_info { + /* cluster cstate value */ + uint32_t cluster; + /* ccplex cstate value */ + uint32_t ccplex; + /* system cstate value */ + uint32_t system; + /* force system state? */ + uint8_t system_state_force; + /* wake mask value */ + uint32_t wake_mask; + /* update the wake mask? */ + uint8_t update_wake_mask; +} mce_cstate_info_t; + +/* public interfaces */ +int mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1, + uint64_t arg2); +int mce_update_reset_vector(void); +int mce_update_gsc_videomem(void); +int mce_update_gsc_tzdram(void); +__dead2 void mce_enter_ccplex_state(uint32_t state_idx); +void mce_update_cstate_info(const mce_cstate_info_t *cstate); +void mce_verify_firmware_version(void); + +#endif /* MCE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h new file mode 100644 index 0000000..cc85095 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MEMCTRL_H +#define MEMCTRL_H + +void tegra_memctrl_setup(void); +void tegra_memctrl_restore_settings(void); +void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes); +void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes); +void tegra_memctrl_disable_ahb_redirection(void); +void tegra_memctrl_clear_pending_interrupts(void); + +#endif /* MEMCTRL_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h new file mode 100644 index 0000000..8e9f198 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MEMCTRL_V1_H +#define MEMCTRL_V1_H + +#include + +#include + +/* SMMU registers */ +#define MC_SMMU_CONFIG_0 0x10U +#define MC_SMMU_CONFIG_0_SMMU_ENABLE_DISABLE 0U +#define MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE 1U +#define MC_SMMU_TLB_CONFIG_0 0x14U +#define MC_SMMU_TLB_CONFIG_0_RESET_VAL 0x20000010U +#define MC_SMMU_PTC_CONFIG_0 0x18U +#define MC_SMMU_PTC_CONFIG_0_RESET_VAL 0x2000003fU +#define MC_SMMU_TLB_FLUSH_0 0x30U +#define TLB_FLUSH_VA_MATCH_ALL 0U +#define TLB_FLUSH_ASID_MATCH_DISABLE 0U +#define TLB_FLUSH_ASID_MATCH_SHIFT 31U +#define MC_SMMU_TLB_FLUSH_ALL \ + (TLB_FLUSH_VA_MATCH_ALL | \ + (TLB_FLUSH_ASID_MATCH_DISABLE << TLB_FLUSH_ASID_MATCH_SHIFT)) +#define MC_SMMU_PTC_FLUSH_0 0x34U +#define MC_SMMU_PTC_FLUSH_ALL 0U +#define MC_SMMU_ASID_SECURITY_0 0x38U +#define MC_SMMU_ASID_SECURITY 0U +#define MC_SMMU_TRANSLATION_ENABLE_0_0 0x228U +#define MC_SMMU_TRANSLATION_ENABLE_1_0 0x22cU +#define MC_SMMU_TRANSLATION_ENABLE_2_0 0x230U +#define MC_SMMU_TRANSLATION_ENABLE_3_0 0x234U +#define MC_SMMU_TRANSLATION_ENABLE_4_0 0xb98U +#define MC_SMMU_TRANSLATION_ENABLE (~0) + +/* MC IRAM aperture registers */ +#define MC_IRAM_BASE_LO 0x65CU +#define MC_IRAM_TOP_LO 0x660U +#define MC_IRAM_BASE_TOP_HI 0x980U +#define MC_IRAM_REG_CTRL 0x964U +#define MC_DISABLE_IRAM_CFG_WRITES 1U + +static inline uint32_t tegra_mc_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_MC_BASE + off); +} + +static inline void tegra_mc_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_MC_BASE + off, val); +} + +#endif /* MEMCTRL_V1_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h new file mode 100644 index 0000000..9af3027 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MEMCTRL_V2_H +#define MEMCTRL_V2_H + +#include + +#include + +/******************************************************************************* + * Memory Controller SMMU Bypass config register + ******************************************************************************/ +#define MC_SMMU_BYPASS_CONFIG 0x1820U +#define MC_SMMU_BYPASS_CTRL_MASK 0x3U +#define MC_SMMU_BYPASS_CTRL_SHIFT 0U +#define MC_SMMU_CTRL_TBU_BYPASS_ALL (0U << MC_SMMU_BYPASS_CTRL_SHIFT) +#define MC_SMMU_CTRL_TBU_RSVD (1U << MC_SMMU_BYPASS_CTRL_SHIFT) +#define MC_SMMU_CTRL_TBU_BYPASS_SPL_STREAMID (2U << MC_SMMU_BYPASS_CTRL_SHIFT) +#define MC_SMMU_CTRL_TBU_BYPASS_NONE (3U << MC_SMMU_BYPASS_CTRL_SHIFT) +#define MC_SMMU_BYPASS_CONFIG_WRITE_ACCESS_BIT (1U << 31) +#define MC_SMMU_BYPASS_CONFIG_SETTINGS (MC_SMMU_BYPASS_CONFIG_WRITE_ACCESS_BIT | \ + MC_SMMU_CTRL_TBU_BYPASS_SPL_STREAMID) + +#ifndef __ASSEMBLER__ + +#include + +typedef struct mc_regs { + uint32_t reg; + uint32_t val; +} mc_regs_t; + +#define mc_smmu_bypass_cfg \ + { \ + .reg = TEGRA_MC_BASE + MC_SMMU_BYPASS_CONFIG, \ + .val = 0x00000000U, \ + } + +#define _START_OF_TABLE_ \ + { \ + .reg = 0xCAFE05C7U, \ + .val = 0x00000000U, \ + } + +#define _END_OF_TABLE_ \ + { \ + .reg = 0xFFFFFFFFU, \ + .val = 0xFFFFFFFFU, \ + } + +#endif /* __ASSEMBLER__ */ + +#ifndef __ASSEMBLER__ + +#include + +static inline uint32_t tegra_mc_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_MC_BASE + off); +} + +static inline void tegra_mc_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_MC_BASE + off, val); +} + +#if defined(TEGRA_MC_STREAMID_BASE) +static inline uint32_t tegra_mc_streamid_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_MC_STREAMID_BASE + off); +} + +static inline void tegra_mc_streamid_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_MC_STREAMID_BASE + off, val); + assert(mmio_read_32(TEGRA_MC_STREAMID_BASE + off) == val); +} +#endif + +void plat_memctrl_setup(void); + +void plat_memctrl_restore(void); +mc_regs_t *plat_memctrl_get_sys_suspend_ctx(void); + +/******************************************************************************* + * Handler to save MC settings before "System Suspend" to TZDRAM + * + * Implemented by Tegra common memctrl_v2 driver under common/drivers/memctrl + ******************************************************************************/ +void tegra_mc_save_context(uint64_t mc_ctx_addr); + +/******************************************************************************* + * Handler to program the scratch registers with TZDRAM settings for the + * resume firmware. + * + * Implemented by SoCs under tegra/soc/txxx + ******************************************************************************/ +void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes); + +#endif /* __ASSEMBLER__ */ + +#endif /* MEMCTRL_V2_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h new file mode 100644 index 0000000..8752b84 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMC_H +#define PMC_H + +#include +#include +#include + +#include + +#define PMC_CONFIG U(0x0) +#define PMC_IO_DPD_SAMPLE U(0x20) +#define PMC_DPD_ENABLE_0 U(0x24) +#define PMC_PWRGATE_STATUS U(0x38) +#define PMC_PWRGATE_TOGGLE U(0x30) +#define PMC_SCRATCH1 U(0x54) +#define PMC_CRYPTO_OP_0 U(0xf4) +#define PMC_TOGGLE_START U(0x100) +#define PMC_SCRATCH31 U(0x118) +#define PMC_SCRATCH32 U(0x11C) +#define PMC_SCRATCH33 U(0x120) +#define PMC_SCRATCH39 U(0x138) +#define PMC_SCRATCH40 U(0x13C) +#define PMC_SCRATCH41 U(0x140) +#define PMC_SCRATCH42 U(0x144) +#define PMC_SCRATCH43 U(0x22C) +#define PMC_SCRATCH44 U(0x230) +#define PMC_SCRATCH45 U(0x234) +#define PMC_SCRATCH46 U(0x238) +#define PMC_SCRATCH47 U(0x23C) +#define PMC_SCRATCH48 U(0x240) +#define PMC_SCRATCH50 U(0x248) +#define PMC_SCRATCH51 U(0x24C) +#define PMC_TSC_MULT_0 U(0x2B4) +#define PMC_STICKY_BIT U(0x2C0) +#define PMC_SECURE_DISABLE2 U(0x2C4) +#define PMC_SECURE_DISABLE2_WRITE22_ON (U(1) << 28) +#define PMC_FUSE_CONTROL_0 U(0x450) +#define PMC_SECURE_DISABLE3 U(0x2D8) +#define PMC_SECURE_DISABLE3_WRITE34_ON (U(1) << 20) +#define PMC_SECURE_DISABLE3_WRITE35_ON (U(1) << 22) +#define PMC_SECURE_SCRATCH22 U(0x338) +#define PMC_SECURE_SCRATCH34 U(0x368) +#define PMC_SECURE_SCRATCH35 U(0x36c) +#define PMC_SCRATCH56 U(0x600) +#define PMC_SCRATCH57 U(0x604) +#define PMC_SCRATCH201 U(0x844) + +static inline uint32_t tegra_pmc_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_PMC_BASE + off); +} + +static inline void tegra_pmc_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_PMC_BASE + off, val); +} + +void tegra_pmc_cpu_on(int32_t cpu); +void tegra_pmc_cpu_setup(uint64_t reset_addr); +bool tegra_pmc_is_last_on_cpu(void); +void tegra_pmc_lock_cpu_vectors(void); +void tegra_pmc_resume(void); +__dead2 void tegra_pmc_system_reset(void); + +#endif /* PMC_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h new file mode 100644 index 0000000..87a0194 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PSC_MAILBOX_H +#define PSC_MAILBOX_H + +void tegra_psc_notify_sc7_entry(void); +void tegra_psc_wait_for_ack(void); + +#endif diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h new file mode 100644 index 0000000..5ae6257 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SECURITY_ENGINE_H +#define SECURITY_ENGINE_H + +/******************************************************************************* + * Structure definition + ******************************************************************************/ + +/* Security Engine Linked List */ +struct tegra_se_ll { + /* DMA buffer address */ + uint32_t addr; + /* Data length in DMA buffer */ + uint32_t data_len; +}; + +#define SE_LL_MAX_BUFFER_NUM 4 +typedef struct tegra_se_io_lst { + volatile uint32_t last_buff_num; + volatile struct tegra_se_ll buffer[SE_LL_MAX_BUFFER_NUM]; +} tegra_se_io_lst_t __attribute__((aligned(4))); + +/* SE device structure */ +typedef struct tegra_se_dev { + /* Security Engine ID */ + const int se_num; + /* SE base address */ + const uint64_t se_base; + /* SE context size in AES blocks */ + const uint32_t ctx_size_blks; + /* pointer to source linked list buffer */ + tegra_se_io_lst_t *src_ll_buf; + /* pointer to destination linked list buffer */ + tegra_se_io_lst_t *dst_ll_buf; + /* LP context buffer pointer */ + uint32_t *ctx_save_buf; +} tegra_se_dev_t; + +/* PKA1 device structure */ +typedef struct tegra_pka_dev { + /* PKA1 base address */ + uint64_t pka_base; +} tegra_pka_dev_t; + +/******************************************************************************* + * Public interface + ******************************************************************************/ +void tegra_se_init(void); +int tegra_se_suspend(void); +void tegra_se_resume(void); +int tegra_se_save_tzram(void); +int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte); + +#endif /* SECURITY_ENGINE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h new file mode 100644 index 0000000..32fc6f9 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMMU_H +#define SMMU_H + +#include + +#include +#include + +#define SMMU_CBn_ACTLR (0x4U) + +/******************************************************************************* + * SMMU Global Secure Aux. Configuration Register + ******************************************************************************/ +#define SMMU_GSR0_SECURE_ACR 0x10U +#define SMMU_GNSR_ACR (SMMU_GSR0_SECURE_ACR + 0x400U) +#define SMMU_GSR0_PGSIZE_SHIFT 16U +#define SMMU_GSR0_PGSIZE_4K (0U << SMMU_GSR0_PGSIZE_SHIFT) +#define SMMU_GSR0_PGSIZE_64K (1U << SMMU_GSR0_PGSIZE_SHIFT) +#define SMMU_ACR_CACHE_LOCK_ENABLE_BIT (1ULL << 26U) +#define SMMU_GSR0_PER (0x20200U) + +/******************************************************************************* + * SMMU Global Aux. Control Register + ******************************************************************************/ +#define SMMU_CBn_ACTLR_CPRE_BIT (1ULL << 1U) + +/* SMMU IDs currently supported by the driver */ +#define TEGRA_SMMU0 0U +#define TEGRA_SMMU1 1U +#define TEGRA_SMMU2 2U + +static inline uint32_t tegra_smmu_read_32(uint32_t smmu_id, uint32_t off) +{ + uint32_t ret = 0U; + +#if defined(TEGRA_SMMU0_BASE) + if (smmu_id == TEGRA_SMMU0) { + ret = mmio_read_32(TEGRA_SMMU0_BASE + (uint64_t)off); + } +#endif + +#if defined(TEGRA_SMMU1_BASE) + if (smmu_id == TEGRA_SMMU1) { + ret = mmio_read_32(TEGRA_SMMU1_BASE + (uint64_t)off); + } +#endif + +#if defined(TEGRA_SMMU2_BASE) + if (smmu_id == TEGRA_SMMU2) { + ret = mmio_read_32(TEGRA_SMMU2_BASE + (uint64_t)off); + } +#endif + + return ret; +} + +static inline void tegra_smmu_write_32(uint32_t smmu_id, + uint32_t off, uint32_t val) +{ +#if defined(TEGRA_SMMU0_BASE) + if (smmu_id == TEGRA_SMMU0) { + mmio_write_32(TEGRA_SMMU0_BASE + (uint64_t)off, val); + } +#endif + +#if defined(TEGRA_SMMU1_BASE) + if (smmu_id == TEGRA_SMMU1) { + mmio_write_32(TEGRA_SMMU1_BASE + (uint64_t)off, val); + } +#endif + +#if defined(TEGRA_SMMU2_BASE) + if (smmu_id == TEGRA_SMMU2) { + mmio_write_32(TEGRA_SMMU2_BASE + (uint64_t)off, val); + } +#endif +} + +void tegra_smmu_init(void); +void tegra_smmu_verify(void); +uint32_t plat_get_num_smmu_devices(void); + +#endif /* SMMU_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h new file mode 100644 index 0000000..e0f8714 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPE_H +#define SPE_H + +#include + +#include + +/* + * Initialize a new spe 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_spe_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /* SPE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h new file mode 100644 index 0000000..22923d6 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_GIC_H +#define TEGRA_GIC_H + +#include + +/******************************************************************************* + * Per-CPU struct describing FIQ state to be stored + ******************************************************************************/ +typedef struct pcpu_fiq_state { + uint64_t elr_el3; + uint64_t spsr_el3; +} pcpu_fiq_state_t; + +/******************************************************************************* + * Function declarations + ******************************************************************************/ +void tegra_gic_cpuif_deactivate(void); +void tegra_gic_init(void); +void tegra_gic_pcpu_init(void); +void tegra_gic_setup(const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +void tegra_gic_save(uint32_t pstate_id); +void tegra_gic_restore(uint32_t pstate_id); +void tegra_gic_register_ctx_ptr(uintptr_t *redist_ptr, uintptr_t *dist_ptr); + +/* Tegra GICv3 function declarations */ +void tegra_gicv3_override_gicr_frames(const uintptr_t *plat_gicr_frames); + +#endif /* TEGRA_GIC_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h b/arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h new file mode 100644 index 0000000..684c872 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PROFILER_H +#define PROFILER_H + +/******************************************************************************* + * Number of bytes of memory used by the profiler on Tegra + ******************************************************************************/ +#define PROFILER_SIZE_BYTES U(0x1000) + +void boot_profiler_init(uint64_t shmem_base, uint32_t tmr_base); +void boot_profiler_add_record(const char *str); +void boot_profiler_deinit(void); + +#endif /* PROFILER_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S b/arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S new file mode 100644 index 0000000..2dc3b41 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +/* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs +#ifdef TEGRA_GICC_BASE + mov_imm x16, TEGRA_GICC_BASE + + /* gicc base address is now in x16 */ + adr x6, gicc_regs /* Load the gicc reg list to x6 */ + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x16, #GICC_HPPIR] + ldr w9, [x16, #GICC_AHPPIR] + ldr w10, [x16, #GICC_CTLR] + /* Store to the crash buf and print to cosole */ + bl str_in_crash_buf_print +#endif + /* Print the GICD_ISPENDR regs */ + mov_imm x16, TEGRA_GICD_BASE + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +2: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq 1f + bl asm_print_hex + adr x4, spacer + bl asm_print_str + ldr w4, [x7], #4 + bl asm_print_hex + adr x4, newline + bl asm_print_str + b 2b +1: +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h new file mode 100644 index 0000000..6672683 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include + +/******************************************************************************* + * Check and error if SEPARATE_CODE_AND_RODATA is not set to 1 + ******************************************************************************/ +#if !SEPARATE_CODE_AND_RODATA +#error "SEPARATE_CODE_AND_RODATA should be set to 1" +#endif + +/* + * Platform binary types for linking + */ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/* + * Platform binary types for linking + */ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#ifdef IMAGE_BL31 +#ifndef PLATFORM_STACK_SIZE +#define PLATFORM_STACK_SIZE U(0x400) +#endif +#endif + +#define TEGRA_PRIMARY_CPU U(0x0) + +/******************************************************************************* + * Platform console related constants + ******************************************************************************/ +#define TEGRA_CONSOLE_BAUDRATE U(115200) +#define TEGRA_BOOT_UART_CLK_13_MHZ U(13000000) +#define TEGRA_BOOT_UART_CLK_408_MHZ U(408000000) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* Size of trusted dram */ +#define TZDRAM_SIZE U(0x00400000) +#define TZDRAM_END (PLAT_BL31_BASE + TZDRAM_SIZE) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +#define BL31_BASE PLAT_BL31_BASE +#define BL31_LIMIT (PLAT_BL31_BASE + BL31_SIZE) +#define BL32_BASE (PLAT_BL31_BASE + BL31_SIZE) +#define BL32_LIMIT TZDRAM_END + +/******************************************************************************* + * 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_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (0x40) /* (U(1) << CACHE_WRITEBACK_SHIFT) */ + +/******************************************************************************* + * Dummy macros to compile io_storage support + ******************************************************************************/ +#define MAX_IO_DEVICES U(0) +#define MAX_IO_HANDLES U(0) + +/******************************************************************************* + * Platforms macros to support SDEI + ******************************************************************************/ +#define TEGRA_SDEI_SGI_PRIVATE U(8) + +/******************************************************************************* + * Platform macros to support exception handling framework + ******************************************************************************/ +#define PLAT_PRI_BITS U(3) +#define PLAT_RAS_PRI U(0x10) +#define PLAT_SDEI_CRITICAL_PRI U(0x20) +#define PLAT_SDEI_NORMAL_PRI U(0x30) +#define PLAT_TEGRA_WDT_PRIO U(0x40) + +#define PLAT_EHF_DESC EHF_PRI_DESC(PLAT_PRI_BITS,\ + PLAT_TEGRA_WDT_PRIO) + +/******************************************************************************* + * SDEI events + ******************************************************************************/ +/* SDEI dynamic private event numbers */ +#define TEGRA_SDEI_DP_EVENT_0 U(100) +#define TEGRA_SDEI_DP_EVENT_1 U(101) +#define TEGRA_SDEI_DP_EVENT_2 U(102) + +/* SDEI dynamic shared event numbers */ +#define TEGRA_SDEI_DS_EVENT_0 U(200) +#define TEGRA_SDEI_DS_EVENT_1 U(201) +#define TEGRA_SDEI_DS_EVENT_2 U(202) + +/* SDEI explicit events */ +#define TEGRA_SDEI_EP_EVENT_0 U(300) +#define TEGRA_SDEI_EP_EVENT_1 U(301) +#define TEGRA_SDEI_EP_EVENT_2 U(302) +#define TEGRA_SDEI_EP_EVENT_3 U(303) +#define TEGRA_SDEI_EP_EVENT_4 U(304) +#define TEGRA_SDEI_EP_EVENT_5 U(305) +#define TEGRA_SDEI_EP_EVENT_6 U(306) +#define TEGRA_SDEI_EP_EVENT_7 U(307) +#define TEGRA_SDEI_EP_EVENT_8 U(308) +#define TEGRA_SDEI_EP_EVENT_9 U(309) +#define TEGRA_SDEI_EP_EVENT_10 U(310) +#define TEGRA_SDEI_EP_EVENT_11 U(311) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h new file mode 100644 index 0000000..4514e14 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA186_PRIVATE_H +#define TEGRA186_PRIVATE_H + +uint64_t tegra186_get_mc_ctx_size(void); + +#endif /* TEGRA186_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h new file mode 100644 index 0000000..06cecc5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_DEF_H +#define TEGRA_DEF_H + +#include + +/******************************************************************************* + * Platform specific macros. + ******************************************************************************/ +#define BL31_SIZE U(0x40000) + +/* Platform power domain constants */ +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + U(1)) + + /* Tegra CORE and CLUSTER affinity values */ +#define TEGRA_CORE_AFFINITY MPIDR_AFF0_SHIFT +#define TEGRA_CLUSTER_AFFINITY MPIDR_AFF1_SHIFT + +/******************************************************************************* + * MCE apertures used by the ARI interface + * + * Aperture 0 - Cpu0 (ARM Cortex A-57) + * Aperture 1 - Cpu1 (ARM Cortex A-57) + * Aperture 2 - Cpu2 (ARM Cortex A-57) + * Aperture 3 - Cpu3 (ARM Cortex A-57) + * Aperture 4 - Cpu4 (Denver15) + * Aperture 5 - Cpu5 (Denver15) + ******************************************************************************/ +#define MCE_ARI_APERTURE_0_OFFSET U(0x0) +#define MCE_ARI_APERTURE_1_OFFSET U(0x10000) +#define MCE_ARI_APERTURE_2_OFFSET U(0x20000) +#define MCE_ARI_APERTURE_3_OFFSET U(0x30000) +#define MCE_ARI_APERTURE_4_OFFSET U(0x40000) +#define MCE_ARI_APERTURE_5_OFFSET U(0x50000) +#define MCE_ARI_APERTURE_OFFSET_MAX MCE_APERTURE_5_OFFSET + +/* number of apertures */ +#define MCE_ARI_APERTURES_MAX U(6) + +/* each ARI aperture is 64KB */ +#define MCE_ARI_APERTURE_SIZE U(0x10000) + +/******************************************************************************* + * CPU core id macros for the MCE_ONLINE_CORE ARI + ******************************************************************************/ +#define MCE_CORE_ID_MAX U(8) +#define MCE_CORE_ID_MASK U(0x7) + +/******************************************************************************* + * These values are used by the PSCI implementation during the `CPU_SUSPEND` + * and `SYSTEM_SUSPEND` calls as the `state-id` field in the 'power state' + * parameter. + ******************************************************************************/ +#define PSTATE_ID_CORE_IDLE U(6) +#define PSTATE_ID_CORE_POWERDN U(7) +#define PSTATE_ID_SOC_POWERDN U(2) + +/******************************************************************************* + * Platform power states (used by PSCI framework) + * + * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID + * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID + ******************************************************************************/ +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(8) + +/******************************************************************************* + * Chip specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 35) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 35) + +/******************************************************************************* + * Secure IRQ definitions + ******************************************************************************/ +#define TEGRA186_TOP_WDT_IRQ U(49) +#define TEGRA186_AON_WDT_IRQ U(50) + +#define TEGRA186_SEC_IRQ_TARGET_MASK U(0xF3) /* 4 A57 - 2 Denver */ + +/******************************************************************************* + * Clock identifier for the SE device + ******************************************************************************/ +#define TEGRA186_CLK_SE U(103) +#define TEGRA_CLK_SE TEGRA186_CLK_SE + +/******************************************************************************* + * Tegra Miscellanous register constants + ******************************************************************************/ +#define TEGRA_MISC_BASE U(0x00100000) +#define HARDWARE_REVISION_OFFSET U(0x4) + +#define MISCREG_PFCFG U(0x200C) + +/******************************************************************************* + * Tegra TSA Controller constants + ******************************************************************************/ +#define TEGRA_TSA_BASE U(0x02400000) + +/******************************************************************************* + * TSA configuration registers + ******************************************************************************/ +#define TSA_CONFIG_STATIC0_CSW_SESWR U(0x4010) +#define TSA_CONFIG_STATIC0_CSW_SESWR_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_ETRW U(0x4038) +#define TSA_CONFIG_STATIC0_CSW_ETRW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_SDMMCWAB U(0x5010) +#define TSA_CONFIG_STATIC0_CSW_SDMMCWAB_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_AXISW U(0x7008) +#define TSA_CONFIG_STATIC0_CSW_AXISW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_HDAW U(0xA008) +#define TSA_CONFIG_STATIC0_CSW_HDAW_RESET U(0x100) +#define TSA_CONFIG_STATIC0_CSW_AONDMAW U(0xB018) +#define TSA_CONFIG_STATIC0_CSW_AONDMAW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_SCEDMAW U(0xD018) +#define TSA_CONFIG_STATIC0_CSW_SCEDMAW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_BPMPDMAW U(0xD028) +#define TSA_CONFIG_STATIC0_CSW_BPMPDMAW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_APEDMAW U(0x12018) +#define TSA_CONFIG_STATIC0_CSW_APEDMAW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_UFSHCW U(0x13008) +#define TSA_CONFIG_STATIC0_CSW_UFSHCW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_AFIW U(0x13018) +#define TSA_CONFIG_STATIC0_CSW_AFIW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_SATAW U(0x13028) +#define TSA_CONFIG_STATIC0_CSW_SATAW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_EQOSW U(0x13038) +#define TSA_CONFIG_STATIC0_CSW_EQOSW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_XUSB_DEVW U(0x15008) +#define TSA_CONFIG_STATIC0_CSW_XUSB_DEVW_RESET U(0x1100) +#define TSA_CONFIG_STATIC0_CSW_XUSB_HOSTW U(0x15018) +#define TSA_CONFIG_STATIC0_CSW_XUSB_HOSTW_RESET U(0x1100) + +#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK (ULL(0x3) << 11) +#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU (ULL(0) << 11) + +/******************************************************************************* + * Tegra General Purpose Centralised DMA constants + ******************************************************************************/ +#define TEGRA_GPCDMA_BASE ULL(0x2610000) + +/******************************************************************************* + * Tegra Memory Controller constants + ******************************************************************************/ +#define TEGRA_MC_STREAMID_BASE U(0x02C00000) +#define TEGRA_MC_BASE U(0x02C10000) + +/* General Security Carveout register macros */ +#define MC_GSC_CONFIG_REGS_SIZE U(0x40) +#define MC_GSC_LOCK_CFG_SETTINGS_BIT (U(1) << 1) +#define MC_GSC_ENABLE_TZ_LOCK_BIT (ULL(1) << 0) +#define MC_GSC_SIZE_RANGE_4KB_SHIFT U(27) +#define MC_GSC_BASE_LO_SHIFT U(12) +#define MC_GSC_BASE_LO_MASK U(0xFFFFF) +#define MC_GSC_BASE_HI_SHIFT U(0) +#define MC_GSC_BASE_HI_MASK U(3) +#define MC_GSC_ENABLE_CPU_SECURE_BIT (U(1) << 31) + +/* TZDRAM carveout configuration registers */ +#define MC_SECURITY_CFG0_0 U(0x70) +#define MC_SECURITY_CFG1_0 U(0x74) +#define MC_SECURITY_CFG3_0 U(0x9BC) + +#define MC_SECURITY_BOM_MASK (U(0xFFF) << 20) +#define MC_SECURITY_SIZE_MB_MASK (U(0x1FFF) << 0) +#define MC_SECURITY_BOM_HI_MASK (U(0x3) << 0) + +/* Video Memory carveout configuration registers */ +#define MC_VIDEO_PROTECT_BASE_HI U(0x978) +#define MC_VIDEO_PROTECT_BASE_LO U(0x648) +#define MC_VIDEO_PROTECT_SIZE_MB U(0x64C) +#define MC_VIDEO_PROTECT_REG_CTRL U(0x650) +#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED U(3) + +/* + * Carveout (MC_SECURITY_CARVEOUT24) registers used to clear the + * non-overlapping Video memory region + */ +#define MC_VIDEO_PROTECT_CLEAR_CFG U(0x25A0) +#define MC_VIDEO_PROTECT_CLEAR_BASE_LO U(0x25A4) +#define MC_VIDEO_PROTECT_CLEAR_BASE_HI U(0x25A8) +#define MC_VIDEO_PROTECT_CLEAR_SIZE U(0x25AC) +#define MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 U(0x25B0) + +/* TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers */ +#define MC_TZRAM_CARVEOUT_CFG U(0x2190) +#define MC_TZRAM_BASE_LO U(0x2194) +#define MC_TZRAM_BASE_HI U(0x2198) +#define MC_TZRAM_SIZE U(0x219C) +#define MC_TZRAM_CLIENT_ACCESS0_CFG0 U(0x21A0) +#define MC_TZRAM_CLIENT_ACCESS1_CFG0 U(0x21A4) +#define TZRAM_ALLOW_MPCORER (U(1) << 7) +#define TZRAM_ALLOW_MPCOREW (U(1) << 25) + +/******************************************************************************* + * Tegra UART Controller constants + ******************************************************************************/ +#define TEGRA_UARTA_BASE U(0x03100000) +#define TEGRA_UARTB_BASE U(0x03110000) +#define TEGRA_UARTC_BASE U(0x0C280000) +#define TEGRA_UARTD_BASE U(0x03130000) +#define TEGRA_UARTE_BASE U(0x03140000) +#define TEGRA_UARTF_BASE U(0x03150000) +#define TEGRA_UARTG_BASE U(0x0C290000) + +/******************************************************************************* + * Tegra Fuse Controller related constants + ******************************************************************************/ +#define TEGRA_FUSE_BASE U(0x03820000) +#define OPT_SUBREVISION U(0x248) +#define SUBREVISION_MASK U(0xFF) + +/******************************************************************************* + * GICv2 & interrupt handling related constants + ******************************************************************************/ +#define TEGRA_GICD_BASE U(0x03881000) +#define TEGRA_GICC_BASE U(0x03882000) + +/******************************************************************************* + * Security Engine related constants + ******************************************************************************/ +#define TEGRA_SE0_BASE U(0x03AC0000) +#define SE_MUTEX_WATCHDOG_NS_LIMIT U(0x6C) +#define TEGRA_PKA1_BASE U(0x03AD0000) +#define PKA_MUTEX_WATCHDOG_NS_LIMIT U(0x8144) +#define TEGRA_RNG1_BASE U(0x03AE0000) +#define RNG_MUTEX_WATCHDOG_NS_LIMIT U(0xFE0) + +/******************************************************************************* + * Tegra HSP doorbell #0 constants + ******************************************************************************/ +#define TEGRA_HSP_DBELL_BASE U(0x03C90000) +#define HSP_DBELL_1_ENABLE U(0x104) +#define HSP_DBELL_3_TRIGGER U(0x300) +#define HSP_DBELL_3_ENABLE U(0x304) + +/******************************************************************************* + * Tegra Clock and Reset Controller constants + ******************************************************************************/ +#define TEGRA_CAR_RESET_BASE U(0x05000000) +#define TEGRA_GPU_RESET_REG_OFFSET U(0x30) +#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x34) +#define GPU_RESET_BIT (U(1) << 0) +#define GPU_SET_BIT (U(1) << 0) +#define TEGRA_GPCDMA_RST_SET_REG_OFFSET U(0x6A0004) +#define TEGRA_GPCDMA_RST_CLR_REG_OFFSET U(0x6A0008) + +/******************************************************************************* + * Tegra micro-seconds timer constants + ******************************************************************************/ +#define TEGRA_TMRUS_BASE U(0x0C2E0000) +#define TEGRA_TMRUS_SIZE U(0x1000) + +/******************************************************************************* + * Tegra Power Mgmt Controller constants + ******************************************************************************/ +#define TEGRA_PMC_BASE U(0x0C360000) + +/******************************************************************************* + * Tegra scratch registers constants + ******************************************************************************/ +#define TEGRA_SCRATCH_BASE U(0x0C390000) +#define SECURE_SCRATCH_RSV0_HI U(0x654) +#define SECURE_SCRATCH_RSV1_LO U(0x658) +#define SECURE_SCRATCH_RSV1_HI U(0x65C) +#define SECURE_SCRATCH_RSV6 U(0x680) +#define SECURE_SCRATCH_RSV11_LO U(0x6A8) +#define SECURE_SCRATCH_RSV11_HI U(0x6AC) +#define SECURE_SCRATCH_RSV53_LO U(0x7F8) +#define SECURE_SCRATCH_RSV53_HI U(0x7FC) +#define SECURE_SCRATCH_RSV55_LO U(0x808) +#define SECURE_SCRATCH_RSV55_HI U(0x80C) +#define SECURE_SCRATCH_RSV63_LO U(0x848) +#define SECURE_SCRATCH_RSV63_HI U(0x84C) +#define SECURE_SCRATCH_RSV64_LO U(0x850) +#define SECURE_SCRATCH_RSV64_HI U(0x854) +#define SECURE_SCRATCH_RSV65_LO U(0x858) +#define SECURE_SCRATCH_RSV65_HI U(0x85c) +#define SECURE_SCRATCH_RSV66_LO U(0x860) +#define SECURE_SCRATCH_RSV66_HI U(0x864) +#define SECURE_SCRATCH_RSV68_LO U(0x870) + +#define SCRATCH_RESET_VECTOR_LO SECURE_SCRATCH_RSV1_LO +#define SCRATCH_RESET_VECTOR_HI SECURE_SCRATCH_RSV1_HI +#define SCRATCH_SECURE_BOOTP_FCFG SECURE_SCRATCH_RSV6 +#define SCRATCH_MC_TABLE_ADDR_LO SECURE_SCRATCH_RSV11_LO +#define SCRATCH_MC_TABLE_ADDR_HI SECURE_SCRATCH_RSV11_HI +#define SCRATCH_BL31_PARAMS_ADDR SECURE_SCRATCH_RSV53_LO +#define SCRATCH_BL31_PLAT_PARAMS_ADDR SECURE_SCRATCH_RSV53_HI +#define SCRATCH_TZDRAM_ADDR_LO SECURE_SCRATCH_RSV55_LO +#define SCRATCH_TZDRAM_ADDR_HI SECURE_SCRATCH_RSV55_HI + +/******************************************************************************* + * Tegra Memory Mapped Control Register Access constants + ******************************************************************************/ +#define TEGRA_MMCRAB_BASE U(0x0E000000) + +/******************************************************************************* + * Tegra Memory Mapped Activity Monitor Register Access constants + ******************************************************************************/ +#define TEGRA_ARM_ACTMON_CTR_BASE U(0x0E060000) +#define TEGRA_DENVER_ACTMON_CTR_BASE U(0x0E070000) + +/******************************************************************************* + * Tegra SMMU Controller constants + ******************************************************************************/ +#define TEGRA_SMMU0_BASE U(0x12000000) + +/******************************************************************************* + * Tegra TZRAM constants + ******************************************************************************/ +#define TEGRA_TZRAM_BASE U(0x30000000) +#define TEGRA_TZRAM_SIZE U(0x40000) + +/******************************************************************************* + * Tegra CCPLEX-BPMP IPC constants + ******************************************************************************/ +#define TEGRA_BPMP_IPC_TX_PHYS_BASE U(0x3004C000) +#define TEGRA_BPMP_IPC_RX_PHYS_BASE U(0x3004D000) +#define TEGRA_BPMP_IPC_CH_MAP_SIZE U(0x1000) /* 4KB */ + +/******************************************************************************* + * Tegra DRAM memory base address + ******************************************************************************/ +#define TEGRA_DRAM_BASE ULL(0x80000000) +#define TEGRA_DRAM_END ULL(0x27FFFFFFF) + +#endif /* TEGRA_DEF_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h new file mode 100644 index 0000000..fa44772 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_MC_DEF_H +#define TEGRA_MC_DEF_H + +/******************************************************************************* + * Memory Controller's PCFIFO client configuration registers + ******************************************************************************/ +#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0U + +#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4U +#define MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL 0x20000U +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_AFIW_UNORDERED (0U << 17) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_AFIW_MASK (1U << 17) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_HDAW_UNORDERED (0U << 21) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_HDAW_MASK (1U << 21) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_UNORDERED (0U << 29) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_MASK (1U << 29) + +#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8U +#define MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL 0x20000U +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_HOSTW_UNORDERED (0U << 11) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_HOSTW_MASK (1U << 11) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_UNORDERED (0U << 13) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_MASK (1U << 13) + +#define MC_PCFIFO_CLIENT_CONFIG3 0xddcU +#define MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL 0U +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_UNORDERED (0U << 7) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_MASK (1U << 7) + +#define MC_PCFIFO_CLIENT_CONFIG4 0xde0U +#define MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL 0U +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SESWR_UNORDERED (0U << 1) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SESWR_MASK (1U << 1) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_ETRW_UNORDERED (0U << 5) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_ETRW_MASK (1U << 5) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AXISW_UNORDERED (0U << 13) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AXISW_MASK (1U << 13) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_UNORDERED (0U << 15) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_ORDERED (1U << 15) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_MASK (1U << 15) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_UFSHCW_UNORDERED (0U << 17) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_UFSHCW_MASK (1U << 17) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPDMAW_UNORDERED (0U << 22) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPDMAW_MASK (1U << 22) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONDMAW_UNORDERED (0U << 26) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONDMAW_MASK (1U << 26) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEDMAW_UNORDERED (0U << 30) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEDMAW_MASK (1U << 30) + +#define MC_PCFIFO_CLIENT_CONFIG5 0xbf4U +#define MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL 0U +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_UNORDERED (0U << 0) +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_MASK (1U << 0) + +/******************************************************************************* + * Stream ID Override Config registers + ******************************************************************************/ +#define MC_STREAMID_OVERRIDE_CFG_PTCR 0x000U +#define MC_STREAMID_OVERRIDE_CFG_AFIR 0x070U +#define MC_STREAMID_OVERRIDE_CFG_HDAR 0x0A8U +#define MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR 0x0B0U +#define MC_STREAMID_OVERRIDE_CFG_NVENCSRD 0x0E0U +#define MC_STREAMID_OVERRIDE_CFG_SATAR 0x0F8U +#define MC_STREAMID_OVERRIDE_CFG_MPCORER 0x138U +#define MC_STREAMID_OVERRIDE_CFG_NVENCSWR 0x158U +#define MC_STREAMID_OVERRIDE_CFG_AFIW 0x188U +#define MC_STREAMID_OVERRIDE_CFG_HDAW 0x1A8U +#define MC_STREAMID_OVERRIDE_CFG_MPCOREW 0x1C8U +#define MC_STREAMID_OVERRIDE_CFG_SATAW 0x1E8U +#define MC_STREAMID_OVERRIDE_CFG_ISPRA 0x220U +#define MC_STREAMID_OVERRIDE_CFG_ISPWA 0x230U +#define MC_STREAMID_OVERRIDE_CFG_ISPWB 0x238U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTR 0x250U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTW 0x258U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVR 0x260U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVW 0x268U +#define MC_STREAMID_OVERRIDE_CFG_TSECSRD 0x2A0U +#define MC_STREAMID_OVERRIDE_CFG_TSECSWR 0x2A8U +#define MC_STREAMID_OVERRIDE_CFG_GPUSRD 0x2C0U +#define MC_STREAMID_OVERRIDE_CFG_GPUSWR 0x2C8U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCRA 0x300U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCRAA 0x308U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCR 0x310U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCRAB 0x318U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCWA 0x320U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCWAA 0x328U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCW 0x330U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCWAB 0x338U +#define MC_STREAMID_OVERRIDE_CFG_VICSRD 0x360U +#define MC_STREAMID_OVERRIDE_CFG_VICSWR 0x368U +#define MC_STREAMID_OVERRIDE_CFG_VIW 0x390U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD 0x3C0U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSWR 0x3C8U +#define MC_STREAMID_OVERRIDE_CFG_APER 0x3D0U +#define MC_STREAMID_OVERRIDE_CFG_APEW 0x3D8U +#define MC_STREAMID_OVERRIDE_CFG_NVJPGSRD 0x3F0U +#define MC_STREAMID_OVERRIDE_CFG_NVJPGSWR 0x3F8U +#define MC_STREAMID_OVERRIDE_CFG_SESRD 0x400U +#define MC_STREAMID_OVERRIDE_CFG_SESWR 0x408U +#define MC_STREAMID_OVERRIDE_CFG_ETRR 0x420U +#define MC_STREAMID_OVERRIDE_CFG_ETRW 0x428U +#define MC_STREAMID_OVERRIDE_CFG_TSECSRDB 0x430U +#define MC_STREAMID_OVERRIDE_CFG_TSECSWRB 0x438U +#define MC_STREAMID_OVERRIDE_CFG_GPUSRD2 0x440U +#define MC_STREAMID_OVERRIDE_CFG_GPUSWR2 0x448U +#define MC_STREAMID_OVERRIDE_CFG_AXISR 0x460U +#define MC_STREAMID_OVERRIDE_CFG_AXISW 0x468U +#define MC_STREAMID_OVERRIDE_CFG_EQOSR 0x470U +#define MC_STREAMID_OVERRIDE_CFG_EQOSW 0x478U +#define MC_STREAMID_OVERRIDE_CFG_UFSHCR 0x480U +#define MC_STREAMID_OVERRIDE_CFG_UFSHCW 0x488U +#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR 0x490U +#define MC_STREAMID_OVERRIDE_CFG_BPMPR 0x498U +#define MC_STREAMID_OVERRIDE_CFG_BPMPW 0x4A0U +#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAR 0x4A8U +#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAW 0x4B0U +#define MC_STREAMID_OVERRIDE_CFG_AONR 0x4B8U +#define MC_STREAMID_OVERRIDE_CFG_AONW 0x4C0U +#define MC_STREAMID_OVERRIDE_CFG_AONDMAR 0x4C8U +#define MC_STREAMID_OVERRIDE_CFG_AONDMAW 0x4D0U +#define MC_STREAMID_OVERRIDE_CFG_SCER 0x4D8U +#define MC_STREAMID_OVERRIDE_CFG_SCEW 0x4E0U +#define MC_STREAMID_OVERRIDE_CFG_SCEDMAR 0x4E8U +#define MC_STREAMID_OVERRIDE_CFG_SCEDMAW 0x4F0U +#define MC_STREAMID_OVERRIDE_CFG_APEDMAR 0x4F8U +#define MC_STREAMID_OVERRIDE_CFG_APEDMAW 0x500U +#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR1 0x508U +#define MC_STREAMID_OVERRIDE_CFG_VICSRD1 0x510U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD1 0x518U + +/******************************************************************************* + * Macro to calculate Security cfg register addr from StreamID Override register + ******************************************************************************/ +#define MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(addr) ((addr) + (uint32_t)sizeof(uint32_t)) + +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_NO_OVERRIDE_SO_DEV (0U << 4) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_NON_COHERENT_SO_DEV (1U << 4) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SO_DEV (2U << 4) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SNOOP_SO_DEV (3U << 4) + +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_NO_OVERRIDE_NORMAL (0U << 8) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_NON_COHERENT_NORMAL (1U << 8) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_NORMAL (2U << 8) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SNOOP_NORMAL (3U << 8) + +#define MC_TXN_OVERRIDE_CONFIG_CGID_SO_DEV_ZERO (0U << 12) +#define MC_TXN_OVERRIDE_CONFIG_CGID_SO_DEV_CLIENT_AXI_ID (1U << 12) + +/******************************************************************************* + * Memory Controller transaction override config registers + ******************************************************************************/ +#define MC_TXN_OVERRIDE_CONFIG_HDAR 0x10a8U +#define MC_TXN_OVERRIDE_CONFIG_BPMPW 0x14a0U +#define MC_TXN_OVERRIDE_CONFIG_PTCR 0x1000U +#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR 0x1490U +#define MC_TXN_OVERRIDE_CONFIG_EQOSW 0x1478U +#define MC_TXN_OVERRIDE_CONFIG_NVJPGSWR 0x13f8U +#define MC_TXN_OVERRIDE_CONFIG_ISPRA 0x1220U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAA 0x1328U +#define MC_TXN_OVERRIDE_CONFIG_VICSRD 0x1360U +#define MC_TXN_OVERRIDE_CONFIG_MPCOREW 0x11c8U +#define MC_TXN_OVERRIDE_CONFIG_GPUSRD 0x12c0U +#define MC_TXN_OVERRIDE_CONFIG_AXISR 0x1460U +#define MC_TXN_OVERRIDE_CONFIG_SCEDMAW 0x14f0U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCW 0x1330U +#define MC_TXN_OVERRIDE_CONFIG_EQOSR 0x1470U +#define MC_TXN_OVERRIDE_CONFIG_APEDMAR 0x14f8U +#define MC_TXN_OVERRIDE_CONFIG_NVENCSRD 0x10e0U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAB 0x1318U +#define MC_TXN_OVERRIDE_CONFIG_VICSRD1 0x1510U +#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAR 0x14a8U +#define MC_TXN_OVERRIDE_CONFIG_VIW 0x1390U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAA 0x1308U +#define MC_TXN_OVERRIDE_CONFIG_AXISW 0x1468U +#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVR 0x1260U +#define MC_TXN_OVERRIDE_CONFIG_UFSHCR 0x1480U +#define MC_TXN_OVERRIDE_CONFIG_TSECSWR 0x12a8U +#define MC_TXN_OVERRIDE_CONFIG_GPUSWR 0x12c8U +#define MC_TXN_OVERRIDE_CONFIG_SATAR 0x10f8U +#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTW 0x1258U +#define MC_TXN_OVERRIDE_CONFIG_TSECSWRB 0x1438U +#define MC_TXN_OVERRIDE_CONFIG_GPUSRD2 0x1440U +#define MC_TXN_OVERRIDE_CONFIG_SCEDMAR 0x14e8U +#define MC_TXN_OVERRIDE_CONFIG_GPUSWR2 0x1448U +#define MC_TXN_OVERRIDE_CONFIG_AONDMAW 0x14d0U +#define MC_TXN_OVERRIDE_CONFIG_APEDMAW 0x1500U +#define MC_TXN_OVERRIDE_CONFIG_AONW 0x14c0U +#define MC_TXN_OVERRIDE_CONFIG_HOST1XDMAR 0x10b0U +#define MC_TXN_OVERRIDE_CONFIG_ETRR 0x1420U +#define MC_TXN_OVERRIDE_CONFIG_SESWR 0x1408U +#define MC_TXN_OVERRIDE_CONFIG_NVJPGSRD 0x13f0U +#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD 0x13c0U +#define MC_TXN_OVERRIDE_CONFIG_TSECSRDB 0x1430U +#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAW 0x14b0U +#define MC_TXN_OVERRIDE_CONFIG_APER 0x13d0U +#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD1 0x1518U +#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTR 0x1250U +#define MC_TXN_OVERRIDE_CONFIG_ISPWA 0x1230U +#define MC_TXN_OVERRIDE_CONFIG_SESRD 0x1400U +#define MC_TXN_OVERRIDE_CONFIG_SCER 0x14d8U +#define MC_TXN_OVERRIDE_CONFIG_AONR 0x14b8U +#define MC_TXN_OVERRIDE_CONFIG_MPCORER 0x1138U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCWA 0x1320U +#define MC_TXN_OVERRIDE_CONFIG_HDAW 0x11a8U +#define MC_TXN_OVERRIDE_CONFIG_NVDECSWR 0x13c8U +#define MC_TXN_OVERRIDE_CONFIG_UFSHCW 0x1488U +#define MC_TXN_OVERRIDE_CONFIG_AONDMAR 0x14c8U +#define MC_TXN_OVERRIDE_CONFIG_SATAW 0x11e8U +#define MC_TXN_OVERRIDE_CONFIG_ETRW 0x1428U +#define MC_TXN_OVERRIDE_CONFIG_VICSWR 0x1368U +#define MC_TXN_OVERRIDE_CONFIG_NVENCSWR 0x1158U +#define MC_TXN_OVERRIDE_CONFIG_AFIR 0x1070U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAB 0x1338U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCRA 0x1300U +#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR1 0x1508U +#define MC_TXN_OVERRIDE_CONFIG_ISPWB 0x1238U +#define MC_TXN_OVERRIDE_CONFIG_BPMPR 0x1498U +#define MC_TXN_OVERRIDE_CONFIG_APEW 0x13d8U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCR 0x1310U +#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVW 0x1268U +#define MC_TXN_OVERRIDE_CONFIG_TSECSRD 0x12a0U +#define MC_TXN_OVERRIDE_CONFIG_AFIW 0x1188U +#define MC_TXN_OVERRIDE_CONFIG_SCEW 0x14e0U + +#define MC_TXN_OVERRIDE_CONFIG_AXID_OVERRIDE_CGID (1U << 0) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_OVERRIDE_SO_DEV (2U << 4) +#define MC_TXN_OVERRIDE_CONFIG_AXID_OVERRIDE_SO_DEV_CGID_SO_DEV_CLIENT (1U << 12) + +/******************************************************************************* + * Non-SO_DEV transactions override values for CGID_TAG bitfield for the + * MC_TXN_OVERRIDE_CONFIG_{module} registers + ******************************************************************************/ +#define MC_TXN_OVERRIDE_CGID_TAG_DEFAULT 0U +#define MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID 1U +#define MC_TXN_OVERRIDE_CGID_TAG_ZERO 2U +#define MC_TXN_OVERRIDE_CGID_TAG_ADR 3U +#define MC_TXN_OVERRIDE_CGID_TAG_MASK 3ULL + +/******************************************************************************* + * Memory Controller Reset Control registers + ******************************************************************************/ +#define MC_CLIENT_HOTRESET_CTRL0 0x200U +#define MC_CLIENT_HOTRESET_CTRL0_RESET_VAL 0U +#define MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB (1U << 0) +#define MC_CLIENT_HOTRESET_CTRL0_HC_FLUSH_ENB (1U << 6) +#define MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB (1U << 7) +#define MC_CLIENT_HOTRESET_CTRL0_ISP2_FLUSH_ENB (1U << 8) +#define MC_CLIENT_HOTRESET_CTRL0_MPCORE_FLUSH_ENB (1U << 9) +#define MC_CLIENT_HOTRESET_CTRL0_NVENC_FLUSH_ENB (1U << 11) +#define MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB (1U << 15) +#define MC_CLIENT_HOTRESET_CTRL0_VI_FLUSH_ENB (1U << 17) +#define MC_CLIENT_HOTRESET_CTRL0_VIC_FLUSH_ENB (1U << 18) +#define MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB (1U << 19) +#define MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB (1U << 20) +#define MC_CLIENT_HOTRESET_CTRL0_TSEC_FLUSH_ENB (1U << 22) +#define MC_CLIENT_HOTRESET_CTRL0_SDMMC1A_FLUSH_ENB (1U << 29) +#define MC_CLIENT_HOTRESET_CTRL0_SDMMC2A_FLUSH_ENB (1U << 30) +#define MC_CLIENT_HOTRESET_CTRL0_SDMMC3A_FLUSH_ENB (1U << 31) +#define MC_CLIENT_HOTRESET_STATUS0 0x204U +#define MC_CLIENT_HOTRESET_CTRL1 0x970U +#define MC_CLIENT_HOTRESET_CTRL1_RESET_VAL 0U +#define MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB (1U << 0) +#define MC_CLIENT_HOTRESET_CTRL1_GPU_FLUSH_ENB (1U << 2) +#define MC_CLIENT_HOTRESET_CTRL1_NVDEC_FLUSH_ENB (1U << 5) +#define MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB (1U << 6) +#define MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB (1U << 7) +#define MC_CLIENT_HOTRESET_CTRL1_NVJPG_FLUSH_ENB (1U << 8) +#define MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB (1U << 12) +#define MC_CLIENT_HOTRESET_CTRL1_TSECB_FLUSH_ENB (1U << 13) +#define MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB (1U << 18) +#define MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB (1U << 19) +#define MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB (1U << 20) +#define MC_CLIENT_HOTRESET_CTRL1_NVDISPLAY_FLUSH_ENB (1U << 21) +#define MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB (1U << 22) +#define MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB (1U << 23) +#define MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB (1U << 24) +#define MC_CLIENT_HOTRESET_STATUS1 0x974U + +#ifndef __ASSEMBLER__ + +/******************************************************************************* + * Structure to hold the transaction override settings to use to override + * client inputs + ******************************************************************************/ +typedef struct mc_txn_override_cfg { + uint32_t offset; + uint8_t cgid_tag; +} mc_txn_override_cfg_t; + +#define mc_make_txn_override_cfg(off, val) \ + { \ + .offset = MC_TXN_OVERRIDE_CONFIG_ ## off, \ + .cgid_tag = MC_TXN_OVERRIDE_ ## val \ + } + +/******************************************************************************* + * Structure to hold the Stream ID to use to override client inputs + ******************************************************************************/ +typedef struct mc_streamid_override_cfg { + uint32_t offset; + uint8_t stream_id; +} mc_streamid_override_cfg_t; + +/******************************************************************************* + * Structure to hold the Stream ID Security Configuration settings + ******************************************************************************/ +typedef struct mc_streamid_security_cfg { + char *name; + uint32_t offset; + uint32_t override_enable; + uint32_t override_client_inputs; + uint32_t override_client_ns_flag; +} mc_streamid_security_cfg_t; + +#define OVERRIDE_DISABLE 1U +#define OVERRIDE_ENABLE 0U +#define CLIENT_FLAG_SECURE 0U +#define CLIENT_FLAG_NON_SECURE 1U +#define CLIENT_INPUTS_OVERRIDE 1U +#define CLIENT_INPUTS_NO_OVERRIDE 0U + +/******************************************************************************* + * StreamID to indicate no SMMU translations (requests to be steered on the + * SMMU bypass path) + ******************************************************************************/ +#define MC_STREAM_ID_MAX 0x7FU + +#define mc_make_sec_cfg(off, ns, ovrrd, access) \ + { \ + .name = # off, \ + .offset = MC_STREAMID_OVERRIDE_TO_SECURITY_CFG( \ + MC_STREAMID_OVERRIDE_CFG_ ## off), \ + .override_client_ns_flag = CLIENT_FLAG_ ## ns, \ + .override_client_inputs = CLIENT_INPUTS_ ## ovrrd, \ + .override_enable = OVERRIDE_ ## access \ + } + +#define mc_make_sid_override_cfg(name) \ + { \ + .reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_CFG_ ## name, \ + .val = 0x00000000U, \ + } + +#define mc_make_sid_security_cfg(name) \ + { \ + .reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(MC_STREAMID_OVERRIDE_CFG_ ## name), \ + .val = 0x00000000U, \ + } + +#define mc_set_pcfifo_unordered_boot_so_mss(id, client) \ + ((uint32_t)~MC_PCFIFO_CLIENT_CONFIG##id##_PCFIFO_##client##_MASK | \ + MC_PCFIFO_CLIENT_CONFIG##id##_PCFIFO_##client##_UNORDERED) + +#define mc_set_pcfifo_ordered_boot_so_mss(id, client) \ + MC_PCFIFO_CLIENT_CONFIG##id##_PCFIFO_##client##_ORDERED + +#define mc_set_tsa_passthrough(client) \ + do { \ + mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \ + (TSA_CONFIG_STATIC0_CSW_##client##_RESET & \ + (uint32_t)~TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK) | \ + (uint32_t)TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU); \ + } while (0) + +#define mc_set_tsa_w_passthrough(client) \ + do { \ + mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \ + (TSA_CONFIG_STATIC0_CSW_RESET_W & \ + (uint32_t)~TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK) | \ + (uint32_t)TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU); \ + } while (0) + +#define mc_set_tsa_r_passthrough(client) \ + { \ + mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSR_##client, \ + (TSA_CONFIG_STATIC0_CSR_RESET_R & \ + (uint32_t)~TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK) | \ + (uint32_t)TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU); \ + } while (0) + +#define mc_set_txn_override(client, normal_axi_id, so_dev_axi_id, normal_override, so_dev_override) \ + do { \ + tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_##client, \ + MC_TXN_OVERRIDE_##normal_axi_id | \ + MC_TXN_OVERRIDE_CONFIG_COH_PATH_##so_dev_override##_SO_DEV | \ + MC_TXN_OVERRIDE_CONFIG_COH_PATH_##normal_override##_NORMAL | \ + MC_TXN_OVERRIDE_CONFIG_CGID_##so_dev_axi_id); \ + } while (0) + +#endif /* __ASSEMBLER__ */ + +#endif /* TEGRA_MC_DEF_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h new file mode 100644 index 0000000..c5a51e9 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA194_PRIVATE_H +#define TEGRA194_PRIVATE_H + +void tegra194_cpu_reset_handler(void); +uint64_t tegra194_get_cpu_reset_handler_base(void); +uint64_t tegra194_get_cpu_reset_handler_size(void); +uint64_t tegra194_get_mc_ctx_offset(void); +void tegra194_set_system_suspend_entry(void); + +#endif /* TEGRA194_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h new file mode 100644 index 0000000..336461a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA194_RAS_PRIVATE +#define TEGRA194_RAS_PRIVATE + +#include + +/* Implementation defined RAS error and corresponding error message */ +struct ras_error { + const char *error_msg; + /* IERR(bits[15:8]) from ERRSTATUS */ + uint8_t error_code; +}; + +/* RAS error node-specific auxiliary data */ +struct ras_aux_data { + /* name for current RAS node. */ + const char *name; + /* point to null-terminated ras_error array to convert error code to msg. */ + const struct ras_error *error_records; + /* + * function to return an value which needs to be programmed into ERXCTLR_EL1 + * to enable all specified RAS errors for current node. + */ + uint64_t (*err_ctrl)(void); +}; + +/* IFU Uncorrectable RAS ERROR */ +#define IFU_UNCORR_RAS_ERROR_LIST(X) + +/* JSR_RET Uncorrectable RAS ERROR */ +#define JSR_RET_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(JSR_RET, 35, 0x13, "Floating Point Register File Parity Error") \ + X(JSR_RET, 34, 0x12, "Integer Register File Parity Error") \ + X(JSR_RET, 33, 0x11, "Garbage Bundle") \ + X(JSR_RET, 32, 0x10, "Bundle Completion Timeout") + +/* JSR_MTS Uncorrectable RAS ERROR */ +#define JSR_MTS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(JSR_MTS, 40, 0x28, "CoreSight Access Error") \ + X(JSR_MTS, 39, 0x27, "Dual Execution Uncorrectable Error") \ + X(JSR_MTS, 37, 0x25, "CTU MMIO Region") \ + X(JSR_MTS, 36, 0x24, "MTS MMCRAB Region Access") \ + X(JSR_MTS, 35, 0x23, "MTS_CARVEOUT Access from ARM SW") \ + X(JSR_MTS, 34, 0x22, "NAFLL PLL Failure to Lock") \ + X(JSR_MTS, 32, 0x20, "Internal Uncorrectable MTS Error") + +/* LSD_STQ Uncorrectable RAS ERROR */ +#define LSD_STQ_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(LSD_STQ, 41, 0x39, "Coherent Cache Data Store Multi-Line ECC Error") \ + X(LSD_STQ, 40, 0x38, "Coherent Cache Data Store Uncorrectable ECC Error") \ + X(LSD_STQ, 38, 0x36, "Coherent Cache Data Load Uncorrectable ECC Error") \ + X(LSD_STQ, 33, 0x31, "Coherent Cache Tag Store Parity Error") \ + X(LSD_STQ, 32, 0x30, "Coherent Cache Tag Load Parity Error") + +/* LSD_DCC Uncorrectable RAS ERROR */ +#define LSD_DCC_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(LSD_DCC, 41, 0x49, "BTU Copy Mini-Cache PPN Multi-Hit Error") \ + X(LSD_DCC, 39, 0x47, "Coherent Cache Data Uncorrectable ECC Error") \ + X(LSD_DCC, 37, 0x45, "Version Cache Byte-Enable Parity Error") \ + X(LSD_DCC, 36, 0x44, "Version Cache Data Uncorrectable ECC Error") \ + X(LSD_DCC, 33, 0x41, "BTU Copy Coherent Cache PPN Parity Error") \ + X(LSD_DCC, 32, 0x40, "BTU Copy Coherent Cache VPN Parity Error") + +/* LSD_L1HPF Uncorrectable RAS ERROR */ +#define LSD_L1HPF_UNCORR_RAS_ERROR_LIST(X) + +/* L2 Uncorrectable RAS ERROR */ +#define L2_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(L2, 56, 0x68, "URT Timeout") \ + X(L2, 55, 0x67, "L2 Protocol Violation") \ + X(L2, 54, 0x66, "SCF to L2 Slave Error Read") \ + X(L2, 53, 0x65, "SCF to L2 Slave Error Write") \ + X(L2, 52, 0x64, "SCF to L2 Decode Error Read") \ + X(L2, 51, 0x63, "SCF to L2 Decode Error Write") \ + X(L2, 50, 0x62, "SCF to L2 Request Response Interface Parity Errors") \ + X(L2, 49, 0x61, "SCF to L2 Advance notice interface parity errors") \ + X(L2, 48, 0x60, "SCF to L2 Filldata Parity Errors") \ + X(L2, 47, 0x5F, "SCF to L2 UnCorrectable ECC Data Error on interface") \ + X(L2, 45, 0x5D, "Core 1 to L2 Parity Error") \ + X(L2, 44, 0x5C, "Core 0 to L2 Parity Error") \ + X(L2, 43, 0x5B, "L2 Multi-Hit") \ + X(L2, 42, 0x5A, "L2 URT Tag Parity Error") \ + X(L2, 41, 0x59, "L2 NTT Tag Parity Error") \ + X(L2, 40, 0x58, "L2 MLT Tag Parity Error") \ + X(L2, 39, 0x57, "L2 URD Data") \ + X(L2, 38, 0x56, "L2 NTP Data") \ + X(L2, 36, 0x54, "L2 MLC Uncorrectable Clean") \ + X(L2, 35, 0x53, "L2 URD Uncorrectable Dirty") \ + X(L2, 34, 0x52, "L2 MLC Uncorrectable Dirty") + +/* CLUSTER_CLOCKS Uncorrectable RAS ERROR */ +#define CLUSTER_CLOCKS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CLUSTER_CLOCKS, 32, 0xE4, "Frequency Monitor Error") + +/* MMU Uncorrectable RAS ERROR */ +#define MMU_UNCORR_RAS_ERROR_LIST(X) + +/* L3 Uncorrectable RAS ERROR */ +#define L3_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(L3, 43, 0x7B, "SNOC Interface Parity Error") \ + X(L3, 42, 0x7A, "MCF Interface Parity Error") \ + X(L3, 41, 0x79, "L3 Tag Parity Error") \ + X(L3, 40, 0x78, "L3 Dir Parity Error") \ + X(L3, 39, 0x77, "L3 Uncorrectable ECC Error") \ + X(L3, 37, 0x75, "Multi-Hit CAM Error") \ + X(L3, 36, 0x74, "Multi-Hit Tag Error") \ + X(L3, 35, 0x73, "Unrecognized Command Error") \ + X(L3, 34, 0x72, "L3 Protocol Error") + +/* CCPMU Uncorrectable RAS ERROR */ +#define CCPMU_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CCPMU, 40, 0x87, "CoreSight Access Error") \ + X(CCPMU, 36, 0x84, "MCE Ucode Error") \ + X(CCPMU, 35, 0x83, "MCE IL1 Parity Error") \ + X(CCPMU, 34, 0x82, "MCE Timeout Error") \ + X(CCPMU, 33, 0x81, "CRAB Access Error") \ + X(CCPMU, 32, 0x80, "MCE Memory Access Error") + +/* SCF_IOB Uncorrectable RAS ERROR */ +#define SCF_IOB_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SCF_IOB, 41, 0x99, "Request parity error") \ + X(SCF_IOB, 40, 0x98, "Putdata parity error") \ + X(SCF_IOB, 39, 0x97, "Uncorrectable ECC on Putdata") \ + X(SCF_IOB, 38, 0x96, "CBB Interface Error") \ + X(SCF_IOB, 37, 0x95, "MMCRAB Error") \ + X(SCF_IOB, 36, 0x94, "IHI Interface Error") \ + X(SCF_IOB, 35, 0x93, "CRI Error") \ + X(SCF_IOB, 34, 0x92, "TBX Interface Error") \ + X(SCF_IOB, 33, 0x91, "EVP Interface Error") + +/* SCF_SNOC Uncorrectable RAS ERROR */ +#define SCF_SNOC_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SCF_SNOC, 42, 0xAA, "Misc Client Parity Error") \ + X(SCF_SNOC, 41, 0xA9, "Misc Filldata Parity Error") \ + X(SCF_SNOC, 40, 0xA8, "Uncorrectable ECC Misc Client") \ + X(SCF_SNOC, 39, 0xA7, "DVMU Interface Parity Error") \ + X(SCF_SNOC, 38, 0xA6, "DVMU Interface Timeout Error") \ + X(SCF_SNOC, 37, 0xA5, "CPE Request Error") \ + X(SCF_SNOC, 36, 0xA4, "CPE Response Error") \ + X(SCF_SNOC, 35, 0xA3, "CPE Timeout Error") \ + X(SCF_SNOC, 34, 0xA2, "Uncorrectable Carveout Error") + +/* SCF_CTU Uncorrectable RAS ERROR */ +#define SCF_CTU_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SCF_CTU, 39, 0xB7, "Timeout error for TRC_DMA request") \ + X(SCF_CTU, 38, 0xB6, "Timeout error for CTU Snp") \ + X(SCF_CTU, 37, 0xB5, "Parity error in CTU TAG RAM") \ + X(SCF_CTU, 36, 0xB3, "Parity error in CTU DATA RAM") \ + X(SCF_CTU, 35, 0xB4, "Parity error for Cluster Rsp") \ + X(SCF_CTU, 34, 0xB2, "Parity error for TRL requests from 9 agents") \ + X(SCF_CTU, 33, 0xB1, "Parity error for MCF request") \ + X(SCF_CTU, 32, 0xB0, "TRC DMA fillsnoop parity error") + +/* CMU_CLOCKS Uncorrectable RAS ERROR */ +#define CMU_CLOCKS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CMU_CLOCKS, 39, 0xC7, "Cluster 3 frequency monitor error") \ + X(CMU_CLOCKS, 38, 0xC6, "Cluster 2 frequency monitor error") \ + X(CMU_CLOCKS, 37, 0xC5, "Cluster 1 frequency monitor error") \ + X(CMU_CLOCKS, 36, 0xC3, "Cluster 0 frequency monitor error") \ + X(CMU_CLOCKS, 35, 0xC4, "Voltage error on ADC1 Monitored Logic") \ + X(CMU_CLOCKS, 34, 0xC2, "Voltage error on ADC0 Monitored Logic") \ + X(CMU_CLOCKS, 33, 0xC1, "Lookup Table 1 Parity Error") \ + X(CMU_CLOCKS, 32, 0xC0, "Lookup Table 0 Parity Error") + +/* + * Define one ras_error entry. + * + * This macro wille be used to to generate ras_error records for each node + * defined by _UNCORR_RAS_ERROR_LIST macro. + */ +#define DEFINE_ONE_RAS_ERROR_MSG(unit, ras_bit, ierr, msg) \ + { \ + .error_msg = (msg), \ + .error_code = (ierr) \ + }, + +/* + * Set one implementation defined bit in ERRCTLR + * + * This macro will be used to collect all defined ERR_CTRL bits for each node + * defined by _UNCORR_RAS_ERROR_LIST macro. + */ +#define DEFINE_ENABLE_RAS_BIT(unit, ras_bit, ierr, msg) \ + do { \ + val |= (1ULL << ras_bit##U); \ + } while (0); + +/* Represent one RAS node with 0 or more error bits (ERR_CTLR) enabled */ +#define DEFINE_ONE_RAS_NODE(node) \ +static const struct ras_error node##_uncorr_ras_errors[] = { \ + node##_UNCORR_RAS_ERROR_LIST(DEFINE_ONE_RAS_ERROR_MSG) \ + { \ + NULL, \ + 0U \ + }, \ +}; \ +static inline uint64_t node##_err_ctrl(void) \ +{ \ + uint64_t val = 0ULL; \ + node##_UNCORR_RAS_ERROR_LIST(DEFINE_ENABLE_RAS_BIT) \ + return val; \ +} + +#define DEFINE_ONE_RAS_AUX_DATA(node) \ + { \ + .name = #node, \ + .error_records = node##_uncorr_ras_errors, \ + .err_ctrl = &node##_err_ctrl \ + }, + +#define PER_CORE_RAS_NODE_LIST(X) \ + X(IFU) \ + X(JSR_RET) \ + X(JSR_MTS) \ + X(LSD_STQ) \ + X(LSD_DCC) \ + X(LSD_L1HPF) + +#define PER_CORE_RAS_GROUP_NODES PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) + +#define PER_CLUSTER_RAS_NODE_LIST(X) \ + X(L2) \ + X(CLUSTER_CLOCKS) \ + X(MMU) + +#define PER_CLUSTER_RAS_GROUP_NODES PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) + +#define SCF_L3_BANK_RAS_NODE_LIST(X) X(L3) + +/* we have 4 SCF_L3 nodes:3*256 + L3_Bank_ID(0-3) */ +#define SCF_L3_BANK_RAS_GROUP_NODES \ + SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \ + SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \ + SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \ + SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) + +#define CCPLEX_RAS_NODE_LIST(X) \ + X(CCPMU) \ + X(SCF_IOB) \ + X(SCF_SNOC) \ + X(SCF_CTU) \ + X(CMU_CLOCKS) + +#define CCPLEX_RAS_GROUP_NODES CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) + +#endif /* TEGRA194_RAS_PRIVATE */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h new file mode 100644 index 0000000..795d07d --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_DEF_H +#define TEGRA_DEF_H + +#include + +/******************************************************************************* + * Platform BL31 specific defines. + ******************************************************************************/ +#define BL31_SIZE U(0x40000) + +/******************************************************************************* + * Chip specific cluster and cpu numbers + ******************************************************************************/ +#define PLATFORM_CLUSTER_COUNT U(4) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(2) + +/* Platform power domain constants */ +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + U(1)) + + /* Tegra CORE and CLUSTER affinity values */ +#define TEGRA_CORE_AFFINITY MPIDR_AFF0_SHIFT +#define TEGRA_CLUSTER_AFFINITY MPIDR_AFF1_SHIFT + +/******************************************************************************* + * Chip specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 40) + +/******************************************************************************* + * These values are used by the PSCI implementation during the `CPU_SUSPEND` + * and `SYSTEM_SUSPEND` calls as the `state-id` field in the 'power state' + * parameter. + ******************************************************************************/ +#define PSTATE_ID_CORE_IDLE U(6) +#define PSTATE_ID_CORE_POWERDN U(7) +#define PSTATE_ID_SOC_POWERDN U(2) + +/******************************************************************************* + * Platform power states (used by PSCI framework) + * + * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID + * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID + ******************************************************************************/ +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(8) + +/******************************************************************************* + * Secure IRQ definitions + ******************************************************************************/ +#define TEGRA194_MAX_SEC_IRQS U(2) +#define TEGRA194_TOP_WDT_IRQ U(49) +#define TEGRA194_AON_WDT_IRQ U(50) + +#define TEGRA194_SEC_IRQ_TARGET_MASK U(0xFF) /* 8 Carmel */ + +/******************************************************************************* + * Clock identifier for the SE device + ******************************************************************************/ +#define TEGRA194_CLK_SE U(124) +#define TEGRA_CLK_SE TEGRA194_CLK_SE + +/******************************************************************************* + * Tegra Miscellanous register constants + ******************************************************************************/ +#define TEGRA_MISC_BASE U(0x00100000) + +#define HARDWARE_REVISION_OFFSET U(0x4) +#define MISCREG_EMU_REVID U(0x3160) +#define BOARD_MASK_BITS U(0xFF) +#define BOARD_SHIFT_BITS U(24) +#define MISCREG_PFCFG U(0x200C) + +/******************************************************************************* + * Tegra General Purpose Centralised DMA constants + ******************************************************************************/ +#define TEGRA_GPCDMA_BASE U(0x02610000) + +/******************************************************************************* + * Tegra Memory Controller constants + ******************************************************************************/ +#define TEGRA_MC_STREAMID_BASE U(0x02C00000) +#define TEGRA_MC_BASE U(0x02C10000) + +/* General Security Carveout register macros */ +#define MC_GSC_CONFIG_REGS_SIZE U(0x40) +#define MC_GSC_LOCK_CFG_SETTINGS_BIT (U(1) << 1) +#define MC_GSC_ENABLE_TZ_LOCK_BIT (U(1) << 0) +#define MC_GSC_SIZE_RANGE_4KB_SHIFT U(27) +#define MC_GSC_BASE_LO_SHIFT U(12) +#define MC_GSC_BASE_LO_MASK U(0xFFFFF) +#define MC_GSC_BASE_HI_SHIFT U(0) +#define MC_GSC_BASE_HI_MASK U(3) +#define MC_GSC_ENABLE_CPU_SECURE_BIT (U(1) << 31) + +/* TZDRAM carveout configuration registers */ +#define MC_SECURITY_CFG0_0 U(0x70) +#define MC_SECURITY_CFG1_0 U(0x74) +#define MC_SECURITY_CFG3_0 U(0x9BC) + +#define MC_SECURITY_BOM_MASK (U(0xFFF) << 20) +#define MC_SECURITY_SIZE_MB_MASK (U(0x1FFF) << 0) +#define MC_SECURITY_BOM_HI_MASK (U(0x3) << 0) + +#define MC_SECURITY_CFG_REG_CTRL_0 U(0x154) +#define SECURITY_CFG_WRITE_ACCESS_BIT (U(0x1) << 0) +#define SECURITY_CFG_WRITE_ACCESS_ENABLE U(0x0) +#define SECURITY_CFG_WRITE_ACCESS_DISABLE U(0x1) + +/* Video Memory carveout configuration registers */ +#define MC_VIDEO_PROTECT_BASE_HI U(0x978) +#define MC_VIDEO_PROTECT_BASE_LO U(0x648) +#define MC_VIDEO_PROTECT_SIZE_MB U(0x64c) +#define MC_VIDEO_PROTECT_REG_CTRL U(0x650) +#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED U(3) + +/* + * Carveout (MC_SECURITY_CARVEOUT24) registers used to clear the + * non-overlapping Video memory region + */ +#define MC_VIDEO_PROTECT_CLEAR_CFG U(0x25A0) +#define MC_VIDEO_PROTECT_CLEAR_BASE_LO U(0x25A4) +#define MC_VIDEO_PROTECT_CLEAR_BASE_HI U(0x25A8) +#define MC_VIDEO_PROTECT_CLEAR_SIZE U(0x25AC) +#define MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 U(0x25B0) + +/* TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers */ +#define MC_TZRAM_CARVEOUT_CFG U(0x2190) +#define MC_TZRAM_BASE_LO U(0x2194) +#define MC_TZRAM_BASE_HI U(0x2198) +#define MC_TZRAM_SIZE U(0x219C) +#define MC_TZRAM_CLIENT_ACCESS0_CFG0 U(0x21A0) +#define MC_TZRAM_CLIENT_ACCESS1_CFG0 U(0x21A4) +#define TZRAM_ALLOW_MPCORER (U(1) << 7) +#define TZRAM_ALLOW_MPCOREW (U(1) << 25) + +/* Memory Controller Reset Control registers */ +#define MC_CLIENT_HOTRESET_CTRL1_DLAA_FLUSH_ENB (U(1) << 28) +#define MC_CLIENT_HOTRESET_CTRL1_DLA1A_FLUSH_ENB (U(1) << 29) +#define MC_CLIENT_HOTRESET_CTRL1_PVA0A_FLUSH_ENB (U(1) << 30) +#define MC_CLIENT_HOTRESET_CTRL1_PVA1A_FLUSH_ENB (U(1) << 31) + +/******************************************************************************* + * Tegra UART Controller constants + ******************************************************************************/ +#define TEGRA_UARTA_BASE U(0x03100000) +#define TEGRA_UARTB_BASE U(0x03110000) +#define TEGRA_UARTC_BASE U(0x0C280000) +#define TEGRA_UARTD_BASE U(0x03130000) +#define TEGRA_UARTE_BASE U(0x03140000) +#define TEGRA_UARTF_BASE U(0x03150000) +#define TEGRA_UARTG_BASE U(0x0C290000) + +/******************************************************************************* + * XUSB PADCTL + ******************************************************************************/ +#define TEGRA_XUSB_PADCTL_BASE U(0x03520000) +#define TEGRA_XUSB_PADCTL_SIZE U(0x10000) +#define XUSB_PADCTL_HOST_AXI_STREAMID_PF_0 U(0x136c) +#define XUSB_PADCTL_HOST_AXI_STREAMID_VF_0 U(0x1370) +#define XUSB_PADCTL_HOST_AXI_STREAMID_VF_1 U(0x1374) +#define XUSB_PADCTL_HOST_AXI_STREAMID_VF_2 U(0x1378) +#define XUSB_PADCTL_HOST_AXI_STREAMID_VF_3 U(0x137c) +#define XUSB_PADCTL_DEV_AXI_STREAMID_PF_0 U(0x139c) + +/******************************************************************************* + * Tegra Fuse Controller related constants + ******************************************************************************/ +#define TEGRA_FUSE_BASE U(0x03820000) +#define OPT_SUBREVISION U(0x248) +#define SUBREVISION_MASK U(0xF) + +/******************************************************************************* + * GICv2 & interrupt handling related constants + ******************************************************************************/ +#define TEGRA_GICD_BASE U(0x03881000) +#define TEGRA_GICC_BASE U(0x03882000) + +/******************************************************************************* + * Security Engine related constants + ******************************************************************************/ +#define TEGRA_SE0_BASE U(0x03AC0000) +#define SE0_MUTEX_WATCHDOG_NS_LIMIT U(0x6C) +#define SE0_AES0_ENTROPY_SRC_AGE_CTRL U(0x2FC) +#define TEGRA_PKA1_BASE U(0x03AD0000) +#define SE_PKA1_CTRL_SE_MUTEX_TMOUT_DFTVAL U(0x144) +#define PKA1_MUTEX_WATCHDOG_NS_LIMIT SE_PKA1_CTRL_SE_MUTEX_TMOUT_DFTVAL +#define TEGRA_RNG1_BASE U(0x03AE0000) +#define RNG1_MUTEX_WATCHDOG_NS_LIMIT U(0xFE0) + +/******************************************************************************* + * Tegra HSP doorbell #0 constants + ******************************************************************************/ +#define TEGRA_HSP_DBELL_BASE U(0x03C90000) +#define HSP_DBELL_1_ENABLE U(0x104) +#define HSP_DBELL_3_TRIGGER U(0x300) +#define HSP_DBELL_3_ENABLE U(0x304) + +/******************************************************************************* + * Tegra hardware synchronization primitives for the SPE engine + ******************************************************************************/ +#define TEGRA_AON_HSP_SM_6_7_BASE U(0x0c190000) +#define TEGRA_CONSOLE_SPE_BASE (TEGRA_AON_HSP_SM_6_7_BASE + U(0x8000)) + +/******************************************************************************* + * Tegra micro-seconds timer constants + ******************************************************************************/ +#define TEGRA_TMRUS_BASE U(0x0C2E0000) +#define TEGRA_TMRUS_SIZE U(0x10000) + +/******************************************************************************* + * Tegra Power Mgmt Controller constants + ******************************************************************************/ +#define TEGRA_PMC_BASE U(0x0C360000) + +/******************************************************************************* + * Tegra scratch registers constants + ******************************************************************************/ +#define TEGRA_SCRATCH_BASE U(0x0C390000) +#define SECURE_SCRATCH_RSV68_LO U(0x284) +#define SECURE_SCRATCH_RSV68_HI U(0x288) +#define SECURE_SCRATCH_RSV69_LO U(0x28C) +#define SECURE_SCRATCH_RSV69_HI U(0x290) +#define SECURE_SCRATCH_RSV70_LO U(0x294) +#define SECURE_SCRATCH_RSV70_HI U(0x298) +#define SECURE_SCRATCH_RSV71_LO U(0x29C) +#define SECURE_SCRATCH_RSV71_HI U(0x2A0) +#define SECURE_SCRATCH_RSV72_LO U(0x2A4) +#define SECURE_SCRATCH_RSV72_HI U(0x2A8) +#define SECURE_SCRATCH_RSV75 U(0x2BC) +#define SECURE_SCRATCH_RSV81_LO U(0x2EC) +#define SECURE_SCRATCH_RSV81_HI U(0x2F0) +#define SECURE_SCRATCH_RSV97 U(0x36C) +#define SECURE_SCRATCH_RSV99_LO U(0x37C) +#define SECURE_SCRATCH_RSV99_HI U(0x380) +#define SECURE_SCRATCH_RSV109_LO U(0x3CC) +#define SECURE_SCRATCH_RSV109_HI U(0x3D0) + +#define SCRATCH_BL31_PARAMS_HI_ADDR SECURE_SCRATCH_RSV75 +#define SCRATCH_BL31_PARAMS_HI_ADDR_MASK U(0xFFFF) +#define SCRATCH_BL31_PARAMS_HI_ADDR_SHIFT U(0) +#define SCRATCH_BL31_PARAMS_LO_ADDR SECURE_SCRATCH_RSV81_LO +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR SECURE_SCRATCH_RSV75 +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_MASK U(0xFFFF0000) +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT U(16) +#define SCRATCH_BL31_PLAT_PARAMS_LO_ADDR SECURE_SCRATCH_RSV81_HI +#define SCRATCH_SECURE_BOOTP_FCFG SECURE_SCRATCH_RSV97 +#define SCRATCH_MC_TABLE_ADDR_LO SECURE_SCRATCH_RSV99_LO +#define SCRATCH_MC_TABLE_ADDR_HI SECURE_SCRATCH_RSV99_HI +#define SCRATCH_RESET_VECTOR_LO SECURE_SCRATCH_RSV109_LO +#define SCRATCH_RESET_VECTOR_HI SECURE_SCRATCH_RSV109_HI + +/******************************************************************************* + * Tegra Memory Mapped Control Register Access Bus constants + ******************************************************************************/ +#define TEGRA_MMCRAB_BASE U(0x0E000000) + +/******************************************************************************* + * Tegra SMMU Controller constants + ******************************************************************************/ +#define TEGRA_SMMU0_BASE U(0x12000000) +#define TEGRA_SMMU1_BASE U(0x11000000) +#define TEGRA_SMMU2_BASE U(0x10000000) + +/******************************************************************************* + * Tegra TZRAM constants + ******************************************************************************/ +#define TEGRA_TZRAM_BASE U(0x40000000) +#define TEGRA_TZRAM_SIZE U(0x40000) + +/******************************************************************************* + * Tegra CCPLEX-BPMP IPC constants + ******************************************************************************/ +#define TEGRA_BPMP_IPC_TX_PHYS_BASE U(0x4004C000) +#define TEGRA_BPMP_IPC_RX_PHYS_BASE U(0x4004D000) +#define TEGRA_BPMP_IPC_CH_MAP_SIZE U(0x1000) /* 4KB */ + +/******************************************************************************* + * Tegra Clock and Reset Controller constants + ******************************************************************************/ +#define TEGRA_CAR_RESET_BASE U(0x20000000) +#define TEGRA_GPU_RESET_REG_OFFSET U(0x18) +#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x1C) +#define GPU_RESET_BIT (U(1) << 0) +#define GPU_SET_BIT (U(1) << 0) +#define TEGRA_GPCDMA_RST_SET_REG_OFFSET U(0x6A0004) +#define TEGRA_GPCDMA_RST_CLR_REG_OFFSET U(0x6A0008) + +/******************************************************************************* + * Tegra DRAM memory base address + ******************************************************************************/ +#define TEGRA_DRAM_BASE ULL(0x80000000) +#define TEGRA_DRAM_END ULL(0xFFFFFFFFF) + +/******************************************************************************* + * XUSB STREAMIDs + ******************************************************************************/ +#define TEGRA_SID_XUSB_HOST U(0x1b) +#define TEGRA_SID_XUSB_DEV U(0x1c) +#define TEGRA_SID_XUSB_VF0 U(0x5d) +#define TEGRA_SID_XUSB_VF1 U(0x5e) +#define TEGRA_SID_XUSB_VF2 U(0x5f) +#define TEGRA_SID_XUSB_VF3 U(0x60) + +/******************************************************************************* + * SCR addresses and expected settings + ******************************************************************************/ +#define SCRATCH_RSV68_SCR U(0x0C398110) +#define SCRATCH_RSV68_SCR_VAL U(0x38000101) +#define SCRATCH_RSV71_SCR U(0x0C39811C) +#define SCRATCH_RSV71_SCR_VAL U(0x38000101) +#define SCRATCH_RSV72_SCR U(0x0C398120) +#define SCRATCH_RSV72_SCR_VAL U(0x38000101) +#define SCRATCH_RSV75_SCR U(0x0C39812C) +#define SCRATCH_RSV75_SCR_VAL U(0x3A000005) +#define SCRATCH_RSV81_SCR U(0x0C398144) +#define SCRATCH_RSV81_SCR_VAL U(0x3A000105) +#define SCRATCH_RSV97_SCR U(0x0C398184) +#define SCRATCH_RSV97_SCR_VAL U(0x38000101) +#define SCRATCH_RSV99_SCR U(0x0C39818C) +#define SCRATCH_RSV99_SCR_VAL U(0x38000101) +#define SCRATCH_RSV109_SCR U(0x0C3981B4) +#define SCRATCH_RSV109_SCR_VAL U(0x38000101) +#define MISCREG_SCR_SCRTZWELCK U(0x00109000) +#define MISCREG_SCR_SCRTZWELCK_VAL U(0x30000100) + +#endif /* TEGRA_DEF_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h new file mode 100644 index 0000000..a351321 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_DEF_H +#define TEGRA_DEF_H + +#include + +/******************************************************************************* + * Platform BL31 specific defines. + ******************************************************************************/ +#define BL31_SIZE U(0x40000) + +/******************************************************************************* + * Power down state IDs + ******************************************************************************/ +#define PSTATE_ID_CORE_POWERDN U(7) +#define PSTATE_ID_CLUSTER_IDLE U(16) +#define PSTATE_ID_SOC_POWERDN U(27) + +/******************************************************************************* + * Platform power domain constants + ******************************************************************************/ +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + U(1)) + + /* Tegra CORE and CLUSTER affinity values */ +#define TEGRA_CORE_AFFINITY MPIDR_AFF0_SHIFT +#define TEGRA_CLUSTER_AFFINITY MPIDR_AFF1_SHIFT + +/******************************************************************************* + * This value is used by the PSCI implementation during the `SYSTEM_SUSPEND` + * call as the `state-id` field in the 'power state' parameter. + ******************************************************************************/ +#define PLAT_SYS_SUSPEND_STATE_ID PSTATE_ID_SOC_POWERDN + +/******************************************************************************* + * Platform power states (used by PSCI framework) + * + * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID + * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID + ******************************************************************************/ +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE (PSTATE_ID_SOC_POWERDN + U(1)) + +/******************************************************************************* + * Chip specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 35) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 35) + +/******************************************************************************* + * SC7 entry firmware's header size + ******************************************************************************/ +#define SC7ENTRY_FW_HEADER_SIZE_BYTES U(0x400) + +/******************************************************************************* + * Counter-timer physical secure timer PPI + ******************************************************************************/ +#define TEGRA210_TIMER1_IRQ 32 + +/******************************************************************************* + * iRAM memory constants + ******************************************************************************/ +#define TEGRA_IRAM_BASE U(0x40000000) +#define TEGRA_IRAM_A_SIZE U(0x10000) /* 64KB */ +#define TEGRA_IRAM_SIZE U(40000) /* 256KB */ + +/******************************************************************************* + * GIC memory map + ******************************************************************************/ +#define TEGRA_GICD_BASE U(0x50041000) +#define TEGRA_GICC_BASE U(0x50042000) + +/******************************************************************************* + * Secure IRQ definitions + ******************************************************************************/ +#define TEGRA210_WDT_CPU_LEGACY_FIQ U(28) + +/******************************************************************************* + * Tegra Memory Select Switch Controller constants + ******************************************************************************/ +#define TEGRA_MSELECT_BASE U(0x50060000) + +#define MSELECT_CONFIG U(0x0) +#define ENABLE_WRAP_INCR_MASTER2_BIT (U(1) << U(29)) +#define ENABLE_WRAP_INCR_MASTER1_BIT (U(1) << U(28)) +#define ENABLE_WRAP_INCR_MASTER0_BIT (U(1) << U(27)) +#define UNSUPPORTED_TX_ERR_MASTER2_BIT (U(1) << U(25)) +#define UNSUPPORTED_TX_ERR_MASTER1_BIT (U(1) << U(24)) +#define ENABLE_UNSUP_TX_ERRORS (UNSUPPORTED_TX_ERR_MASTER2_BIT | \ + UNSUPPORTED_TX_ERR_MASTER1_BIT) +#define ENABLE_WRAP_TO_INCR_BURSTS (ENABLE_WRAP_INCR_MASTER2_BIT | \ + ENABLE_WRAP_INCR_MASTER1_BIT | \ + ENABLE_WRAP_INCR_MASTER0_BIT) + +/******************************************************************************* + * Tegra Resource Semaphore constants + ******************************************************************************/ +#define TEGRA_RES_SEMA_BASE 0x60001000UL +#define STA_OFFSET 0UL +#define SET_OFFSET 4UL +#define CLR_OFFSET 8UL + +/******************************************************************************* + * Tegra Primary Interrupt Controller constants + ******************************************************************************/ +#define TEGRA_PRI_ICTLR_BASE 0x60004000UL +#define CPU_IEP_FIR_SET 0x18UL + +/******************************************************************************* + * Tegra micro-seconds timer constants + ******************************************************************************/ +#define TEGRA_TMRUS_BASE U(0x60005010) +#define TEGRA_TMRUS_SIZE U(0x1000) + +/******************************************************************************* + * Tegra Clock and Reset Controller constants + ******************************************************************************/ +#define TEGRA_CAR_RESET_BASE U(0x60006000) +#define TEGRA_BOND_OUT_H U(0x74) +#define APB_DMA_LOCK_BIT (U(1) << 2) +#define AHB_DMA_LOCK_BIT (U(1) << 1) +#define TEGRA_BOND_OUT_U U(0x78) +#define IRAM_D_LOCK_BIT (U(1) << 23) +#define IRAM_C_LOCK_BIT (U(1) << 22) +#define IRAM_B_LOCK_BIT (U(1) << 21) +#define TEGRA_GPU_RESET_REG_OFFSET U(0x28C) +#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x290) +#define GPU_RESET_BIT (U(1) << 24) +#define GPU_SET_BIT (U(1) << 24) +#define TEGRA_RST_DEV_SET_Y U(0x2a8) +#define NVENC_RESET_BIT (U(1) << 27) +#define TSECB_RESET_BIT (U(1) << 14) +#define APE_RESET_BIT (U(1) << 6) +#define NVJPG_RESET_BIT (U(1) << 3) +#define NVDEC_RESET_BIT (U(1) << 2) +#define TEGRA_RST_DEV_SET_L U(0x300) +#define HOST1X_RESET_BIT (U(1) << 28) +#define ISP_RESET_BIT (U(1) << 23) +#define USBD_RESET_BIT (U(1) << 22) +#define VI_RESET_BIT (U(1) << 20) +#define SDMMC4_RESET_BIT (U(1) << 15) +#define SDMMC1_RESET_BIT (U(1) << 14) +#define SDMMC2_RESET_BIT (U(1) << 9) +#define TEGRA_RST_DEV_SET_H U(0x308) +#define USB2_RESET_BIT (U(1) << 26) +#define APBDMA_RESET_BIT (U(1) << 2) +#define AHBDMA_RESET_BIT (U(1) << 1) +#define TEGRA_RST_DEV_SET_U U(0x310) +#define XUSB_DEV_RESET_BIT (U(1) << 31) +#define XUSB_HOST_RESET_BIT (U(1) << 25) +#define TSEC_RESET_BIT (U(1) << 19) +#define PCIE_RESET_BIT (U(1) << 6) +#define SDMMC3_RESET_BIT (U(1) << 5) +#define TEGRA_RST_DEVICES_V U(0x358) +#define TEGRA_RST_DEVICES_W U(0x35C) +#define ENTROPY_CLK_ENB_BIT (U(1) << 21) +#define TEGRA_CLK_OUT_ENB_V U(0x360) +#define SE_CLK_ENB_BIT (U(1) << 31) +#define TEGRA_CLK_OUT_ENB_W U(0x364) +#define ENTROPY_RESET_BIT (U(1) << 21) +#define TEGRA_CLK_RST_CTL_CLK_SRC_SE U(0x42C) +#define SE_CLK_SRC_MASK (U(7) << 29) +#define SE_CLK_SRC_CLK_M (U(6) << 29) +#define TEGRA_RST_DEV_SET_V U(0x430) +#define SE_RESET_BIT (U(1) << 31) +#define HDA_RESET_BIT (U(1) << 29) +#define SATA_RESET_BIT (U(1) << 28) +#define TEGRA_RST_DEV_CLR_V U(0x434) +#define TEGRA_CLK_ENB_V U(0x440) + +/******************************************************************************* + * Tegra Flow Controller constants + ******************************************************************************/ +#define TEGRA_FLOWCTRL_BASE U(0x60007000) + +/******************************************************************************* + * Tegra AHB arbitration controller + ******************************************************************************/ +#define TEGRA_AHB_ARB_BASE 0x6000C000UL + +/******************************************************************************* + * Tegra Secure Boot Controller constants + ******************************************************************************/ +#define TEGRA_SB_BASE U(0x6000C200) + +/******************************************************************************* + * Tegra Exception Vectors constants + ******************************************************************************/ +#define TEGRA_EVP_BASE U(0x6000F000) + +/******************************************************************************* + * Tegra Miscellaneous register constants + ******************************************************************************/ +#define TEGRA_MISC_BASE U(0x70000000) +#define HARDWARE_REVISION_OFFSET U(0x804) +#define APB_SLAVE_SECURITY_ENABLE U(0xC00) +#define PMC_SECURITY_EN_BIT (U(1) << 13) +#define PINMUX_AUX_DVFS_PWM U(0x3184) +#define PINMUX_PWM_TRISTATE (U(1) << 4) + +/******************************************************************************* + * Tegra UART controller base addresses + ******************************************************************************/ +#define TEGRA_UARTA_BASE U(0x70006000) +#define TEGRA_UARTB_BASE U(0x70006040) +#define TEGRA_UARTC_BASE U(0x70006200) +#define TEGRA_UARTD_BASE U(0x70006300) +#define TEGRA_UARTE_BASE U(0x70006400) + +/******************************************************************************* + * Tegra Fuse Controller related constants + ******************************************************************************/ +#define TEGRA_FUSE_BASE 0x7000F800UL +#define FUSE_BOOT_SECURITY_INFO 0x268UL +#define FUSE_ATOMIC_SAVE_CARVEOUT_EN (0x1U << 7) +#define FUSE_JTAG_SECUREID_VALID (0x104UL) +#define ECID_VALID (0x1UL) + + +/******************************************************************************* + * Tegra Power Mgmt Controller constants + ******************************************************************************/ +#define TEGRA_PMC_BASE U(0x7000E400) +#define TEGRA_PMC_SIZE U(0xC00) /* 3k */ + +/******************************************************************************* + * Tegra Atomics constants + ******************************************************************************/ +#define TEGRA_ATOMICS_BASE 0x70016000UL +#define TRIGGER0_REG_OFFSET 0UL +#define TRIGGER_WIDTH_SHIFT 4UL +#define TRIGGER_ID_SHIFT 16UL +#define RESULT0_REG_OFFSET 0xC00UL + +/******************************************************************************* + * Tegra Memory Controller constants + ******************************************************************************/ +#define TEGRA_MC_BASE U(0x70019000) + +/* Memory Controller Interrupt Status */ +#define MC_INTSTATUS 0x00U + +/* TZDRAM carveout configuration registers */ +#define MC_SECURITY_CFG0_0 U(0x70) +#define MC_SECURITY_CFG1_0 U(0x74) +#define MC_SECURITY_CFG3_0 U(0x9BC) + +/* Video Memory carveout configuration registers */ +#define MC_VIDEO_PROTECT_BASE_HI U(0x978) +#define MC_VIDEO_PROTECT_BASE_LO U(0x648) +#define MC_VIDEO_PROTECT_SIZE_MB U(0x64c) +#define MC_VIDEO_PROTECT_REG_CTRL U(0x650) +#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED U(3) + +/* SMMU configuration registers*/ +#define MC_SMMU_PPCS_ASID_0 0x270U +#define PPCS_SMMU_ENABLE (0x1U << 31) + +/******************************************************************************* + * Tegra CLDVFS constants + ******************************************************************************/ +#define TEGRA_CL_DVFS_BASE U(0x70110000) +#define DVFS_DFLL_CTRL U(0x00) +#define ENABLE_OPEN_LOOP U(1) +#define ENABLE_CLOSED_LOOP U(2) +#define DVFS_DFLL_OUTPUT_CFG U(0x20) +#define DFLL_OUTPUT_CFG_I2C_EN_BIT (U(1) << 30) +#define DFLL_OUTPUT_CFG_CLK_EN_BIT (U(1) << 6) + +/******************************************************************************* + * Tegra SE constants + ******************************************************************************/ +#define TEGRA_SE1_BASE U(0x70012000) +#define TEGRA_SE2_BASE U(0x70412000) +#define TEGRA_PKA1_BASE U(0x70420000) +#define TEGRA_SE2_RANGE_SIZE U(0x2000) +#define SE_TZRAM_SECURITY U(0x4) + +/******************************************************************************* + * Tegra TZRAM constants + ******************************************************************************/ +#define TEGRA_TZRAM_BASE U(0x7C010000) +#define TEGRA_TZRAM_SIZE U(0x10000) + +/******************************************************************************* + * Tegra TZRAM carveout constants + ******************************************************************************/ +#define TEGRA_TZRAM_CARVEOUT_BASE U(0x7C04C000) +#define TEGRA_TZRAM_CARVEOUT_SIZE U(0x4000) + +/******************************************************************************* + * Tegra DRAM memory base address + ******************************************************************************/ +#define TEGRA_DRAM_BASE ULL(0x80000000) +#define TEGRA_DRAM_END ULL(0x27FFFFFFF) + +#endif /* TEGRA_DEF_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h new file mode 100644 index 0000000..168ba5b --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA234_PRIVATE +#define TEGRA234_PRIVATE + +void tegra234_ras_init_common(void); +void tegra234_ras_init_my_cluster(void); +int tegra234_ras_inject_fault(uint64_t base, uint64_t pfgcdn, uint64_t pfgctl); + +#endif /* TEGRA234_PRIVATE */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h new file mode 100644 index 0000000..fb4b0f1 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA234_RAS_PRIVATE +#define TEGRA234_RAS_PRIVATE + +#include + +/* RAS error record base addresses */ +#define TEGRA234_RAS_CCPMU_BASE U(0x0E001000) +#define TEGRA234_RAS_CMU_CLOCKS_BASE U(0x0E003000) +#define TEGRA234_RAS_IH_BASE U(0x0E006000) +#define TEGRA234_RAS_IST_CLUSTER0_BASE U(0x0E009000) +#define TEGRA234_RAS_IST_CLUSTER1_BASE U(0x0E00A000) +#define TEGRA234_RAS_IST_CLUSTER2_BASE U(0x0E00B000) +#define TEGRA234_RAS_IOB_BASE U(0x0E010000) +#define TEGRA234_RAS_SNOC_BASE U(0x0E011000) +#define TEGRA234_RAS_SCC_SLICE0_BASE U(0x0E012000) +#define TEGRA234_RAS_SCC_SLICE1_BASE U(0x0E013000) +#define TEGRA234_RAS_SCC_SLICE2_BASE U(0x0E014000) +#define TEGRA234_RAS_SCC_SLICE3_BASE U(0x0E015000) +#define TEGRA234_RAS_SCC_SLICE4_BASE U(0x0E016000) +#define TEGRA234_RAS_SCC_SLICE5_BASE U(0x0E017000) +#define TEGRA234_RAS_SCC_SLICE6_BASE U(0x0E018000) +#define TEGRA234_RAS_SCC_SLICE7_BASE U(0x0E019000) +#define TEGRA234_RAS_ACI_CLUSTER0_BASE U(0x0E01A000) +#define TEGRA234_RAS_ACI_CLUSTER1_BASE U(0x0E01B000) +#define TEGRA234_RAS_ACI_CLUSTER2_BASE U(0x0E01C000) +#define TEGRA234_RAS_CL0_CORE0_BASE U(0x0E030000) +#define TEGRA234_RAS_CL0_CORE1_BASE U(0x0E031000) +#define TEGRA234_RAS_CL0_CORE2_BASE U(0x0E032000) +#define TEGRA234_RAS_CL0_CORE3_BASE U(0x0E033000) +#define TEGRA234_RAS_CL0_CORE_LS_PAIR1_BASE U(0x0E034000) +#define TEGRA234_RAS_CL0_CORE_LS_PAIR2_BASE U(0x0E035000) +#define TEGRA234_RAS_CL0_DSU_LS_PRIMARY_BASE U(0x0E036000) +#define TEGRA234_RAS_CL0_DSU_LS_SECONDARY_BASE U(0x0E037000) +#define TEGRA234_RAS_CL0_DSU_IFP_BASE U(0x0E038000) +#define TEGRA234_RAS_CL1_CORE0_BASE U(0x0E040000) +#define TEGRA234_RAS_CL1_CORE1_BASE U(0x0E041000) +#define TEGRA234_RAS_CL1_CORE2_BASE U(0x0E042000) +#define TEGRA234_RAS_CL1_CORE3_BASE U(0x0E043000) +#define TEGRA234_RAS_CL1_CORE_LS_PAIR1_BASE U(0x0E044000) +#define TEGRA234_RAS_CL1_CORE_LS_PAIR2_BASE U(0x0E045000) +#define TEGRA234_RAS_CL1_DSU_LS_PRIMARY_BASE U(0x0E046000) +#define TEGRA234_RAS_CL1_DSU_LS_SECONDARY_BASE U(0x0E047000) +#define TEGRA234_RAS_CL1_DSU_IFP_BASE U(0x0E048000) +#define TEGRA234_RAS_CL2_CORE0_BASE U(0x0E050000) +#define TEGRA234_RAS_CL2_CORE1_BASE U(0x0E051000) +#define TEGRA234_RAS_CL2_CORE2_BASE U(0x0E052000) +#define TEGRA234_RAS_CL2_CORE3_BASE U(0x0E053000) +#define TEGRA234_RAS_CL2_CORE_LS_PAIR1_BASE U(0x0E054000) +#define TEGRA234_RAS_CL2_CORE_LS_PAIR2_BASE U(0x0E055000) +#define TEGRA234_RAS_CL2_DSU_LS_PRIMARY_BASE U(0x0E056000) +#define TEGRA234_RAS_CL2_DSU_LS_SECONDARY_BASE U(0x0E057000) +#define TEGRA234_RAS_CL2_DSU_IFP_BASE U(0x0E058000) + +/* IH RAS status masks */ +#define TEGRA234_IH_STATUS_MASK_CMU (BIT(1) | BIT(0)) +#define TEGRA234_IH_STATUS_MASK_SCF (BIT(3) | BIT(2)) +#define TEGRA234_IH_STATUS_MASK_CL0 (BIT(4) | BIT(8) | BIT(9) | \ + BIT(16) | BIT(17) | \ + (ULL(0xFF) << 24)) +#define TEGRA234_IH_STATUS_MASK_CL1 (BIT(5) | BIT(10) | BIT(11) | \ + BIT(18) | BIT(19) | \ + (ULL(0xFF) << 32)) +#define TEGRA234_IH_STATUS_MASK_CL2 (BIT(6) | BIT(12) | BIT(13) | \ + BIT(20) | BIT(21) | \ + (ULL(0xFF) << 40)) + +/* Implementation defined RAS error and corresponding error message */ +struct ras_error { + const char *error_msg; + /* IERR(bits[15:8]) from ERRSTATUS */ + uint8_t error_code; +}; + +/* RAS error node-specific auxiliary data */ +struct ras_aux_data { + /* name of the current RAS node */ + const char *name; + /* + * pointer to null-terminated ras_error array to convert error + * code to msg + */ + const struct ras_error *error_records; + /* + * Number of error records + */ + unsigned int num_err_records; + /* + * function to return value which needs to be programmed into + * ERRCTLR to enable uncorrectable RAS errors for current + * node + */ + uint64_t (*get_ue_mask)(void); + /* + * function to return value which needs to be programmed into + * ERRCTLR to enable corrected RAS errors for the current + * node + */ + uint64_t (*get_ce_mask)(void); +}; + +/* CCPMU Uncorrectable RAS ERROR */ +#define CCPMU_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CCPMU, 42, 0x0A, "IL1 Parity Error") \ + X(CCPMU, 41, 0x09, "Invalid uOp Error") \ + X(CCPMU, 40, 0x08, "MCE Request Error") \ + X(CCPMU, 39, 0x07, "MCE Request Timeout Error") \ + X(CCPMU, 38, 0x06, "CRAB Master Error") \ + X(CCPMU, 37, 0x05, "uCode Error") \ + X(CCPMU, 36, 0x04, "ARI Request NS Error") \ + X(CCPMU, 35, 0x03, "CCPMU unit Lockable CREG Error") \ + X(CCPMU, 34, 0x02, "CCPMU RAS Lockable CREG Error") \ + X(CCPMU, 33, 0x01, "DC Lockable CREG Error") \ + X(CCPMU, 32, 0x00, "CMULA lockable CREG Error") + +/* Empty CCPMU Corrected RAS ERROR */ +#define CCPMU_CORR_RAS_ERROR_LIST(X) + +/* CMU Clocks Uncorrectable RAS ERROR */ +#define CMU_CLOCKS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CMU_CLOCKS, 41, 0x09, "Cluster2 FMON Error") \ + X(CMU_CLOCKS, 40, 0x08, "Cluster2 Core FMON Error") \ + X(CMU_CLOCKS, 39, 0x07, "Cluster1 FMON Error") \ + X(CMU_CLOCKS, 38, 0x06, "Cluster1 Core FMON Error") \ + X(CMU_CLOCKS, 37, 0x05, "Cluster0 FMON Error") \ + X(CMU_CLOCKS, 36, 0x04, "Cluster0 Core FMON Error") \ + X(CMU_CLOCKS, 35, 0x03, "LUT0 Parity Error") \ + X(CMU_CLOCKS, 34, 0x02, "LUT1 Parity Error") \ + X(CMU_CLOCKS, 33, 0x01, "ADC0 VMON Error") \ + X(CMU_CLOCKS, 32, 0x00, "Lock Error") + +/* Empty CMU Clocks Corrected RAS ERROR */ +#define CMU_CLOCKS_CORR_RAS_ERROR_LIST(X) + +/* IH Uncorrectable RAS ERROR */ +#define IH_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IH, 35, 0x03, "RAS MUX Error") \ + X(IH, 34, 0x02, "GIC FMU Error") \ + X(IH, 33, 0x01, "Unit lockable CREG Error") \ + X(IH, 32, 0x00, "RAS lockable CREG Error") + +/* Empty IH Corrected RAS ERROR */ +#define IH_CORR_RAS_ERROR_LIST(X) + +/* IST Uncorrectable RAS ERROR */ +#define IST_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IST, 50, 0x12, "Lock Error") \ + X(IST, 49, 0x11, "MCE Error") \ + X(IST, 48, 0x10, "MISR Mismatch Error") \ + X(IST, 47, 0x0F, "Security Error") \ + X(IST, 46, 0x0E, "RAM Data Error") \ + X(IST, 45, 0x0D, "JTAG Controller Error") \ + X(IST, 44, 0x0C, "Timeout Error") \ + X(IST, 43, 0x0B, "LBIST Controller Error") \ + X(IST, 42, 0x0A, "DMA Error") \ + X(IST, 41, 0x09, "ECC Security Error") + +/* IST Corrected RAS ERROR */ +#define IST_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IST, 40, 0x08, "MCE Error") \ + X(IST, 39, 0x07, "MISR Mismatch Error") \ + X(IST, 38, 0x06, "Security Error") \ + X(IST, 37, 0x05, "RAM Data Error") \ + X(IST, 36, 0x04, "JTAG Controller Error") \ + X(IST, 35, 0x03, "Timeout Error") \ + X(IST, 34, 0x02, "LBIST Controller Error") \ + X(IST, 33, 0x01, "DMA Error") \ + X(IST, 32, 0x00, "ECC Security Error") + +/* IOB Uncorrectable RAS ERROR */ +#define IOB_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IOB, 47, 0x0F, "APB Response Parity Error") \ + X(IOB, 46, 0x0E, "IHI Write Data Ready Error") \ + X(IOB, 45, 0x0D, "IHI Write Address Ready Error") \ + X(IOB, 44, 0x0C, "IHI Read Address Ready Error") \ + X(IOB, 43, 0x0B, "IHI Write Response Parity Error") \ + X(IOB, 42, 0x0A, "IHI Read Data Parity Error") \ + X(IOB, 41, 0x09, "Request Parity Error") \ + X(IOB, 40, 0x08, "PutData Parity Error") \ + X(IOB, 39, 0x07, "PutData Uncorrectable ECC Error") \ + X(IOB, 38, 0x06, "CBB Interface Error") \ + X(IOB, 37, 0x05, "ARM MMCRAB Access Error") \ + X(IOB, 36, 0x04, "APB Interface Error") \ + X(IOB, 35, 0x03, "IHI (GIC ACE-Lite) Interface Error") \ + X(IOB, 34, 0x02, "Trickbox Interface Error") \ + X(IOB, 33, 0x01, "Lock Error") + +/* IOB Corrected RAS ERROR */ +#define IOB_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IOB, 32, 0x00, "Putdata Corrected ECC Error") + +/* SNOC Uncorrectable RAS ERROR */ +#define SNOC_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SNOC, 47, 0x0F, "MCF MSI Error") \ + X(SNOC, 46, 0x0E, "MISC IST CPE Access Error") \ + X(SNOC, 45, 0x0D, "MISC MMIO Access Error") \ + X(SNOC, 44, 0x0C, "MISC MMP Access Error") \ + X(SNOC, 43, 0x0B, "MISC Response Parity Error") \ + X(SNOC, 42, 0x0A, "MISC FillData Parity Error") \ + X(SNOC, 41, 0x09, "MISC FillData Uncorrectable ECC Error") \ + X(SNOC, 40, 0x08, "DVMU Parity Error") \ + X(SNOC, 39, 0x07, "DVMU Timeout Error") \ + X(SNOC, 38, 0x06, "CPE Request Error") \ + X(SNOC, 37, 0x05, "CPE Response Error") \ + X(SNOC, 36, 0x04, "CPE Timeout Error") \ + X(SNOC, 35, 0x03, "Carveout Uncorrectable Error") \ + X(SNOC, 34, 0x02, "Lockable CREG Error") + +/* SNOC Corrected RAS ERROR */ +#define SNOC_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SNOC, 33, 0x01, "MISC FillData Corrected ECC Error") \ + X(SNOC, 32, 0x00, "Carveout Corrected Error") + +/* SCC Uncorrectable RAS ERROR */ +#define SCC_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SCC, 51, 0x13, "SNOC Interface Parity Error") \ + X(SCC, 50, 0x12, "MCF Interface Parity Error") \ + X(SCC, 49, 0x11, "L3 Tag Parity Error") \ + X(SCC, 48, 0x10, "L2 Dir Parity Error") \ + X(SCC, 47, 0x0F, "URT Parity Error") \ + X(SCC, 46, 0x0E, "SWAT Parity Error") \ + X(SCC, 45, 0x0D, "L3 Data Parity Error") \ + X(SCC, 44, 0x0C, "URT FC Error") \ + X(SCC, 43, 0x0B, "SWAT FC Error") \ + X(SCC, 42, 0x0A, "Uncorrected ECC Error") \ + X(SCC, 41, 0x09, "Address Range Error") \ + X(SCC, 40, 0x08, "Unsupported Request Error") \ + X(SCC, 39, 0x07, "Multiple Hit CAM Error") \ + X(SCC, 38, 0x06, "Multiple Hit Tag Error") \ + X(SCC, 37, 0x05, "Protocol Error") \ + X(SCC, 36, 0x04, "Timeout Error") \ + X(SCC, 35, 0x03, "Destination Error") \ + X(SCC, 34, 0x02, "URT FC Timeout Error") \ + X(SCC, 33, 0x01, "SWAT FC Timeout Error") \ + X(SCC, 32, 0x00, "Lock Error") + +/* SCC Corrected RAS ERROR */ +#define SCC_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SCC, 52, 0x14, "Corrected ECC Error") + +/* ACI Uncorrectable RAS ERROR */ +#define ACI_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(ACI, 49, 0x11, "Uncorrectable ECC Error") \ + X(ACI, 48, 0x10, "MST ADB error") \ + X(ACI, 47, 0x0F, "AXI FuSa Error") \ + X(ACI, 46, 0x0E, "AXI Parity Error") \ + X(ACI, 45, 0x0D, "SNOC Write Error") \ + X(ACI, 44, 0x0C, "ACE AW Decode Error") \ + X(ACI, 43, 0x0B, "Unexpected WU Error") \ + X(ACI, 42, 0x0A, "Snoop Error") \ + X(ACI, 41, 0x09, "FillWrite Error") \ + X(ACI, 40, 0x08, "DVM Error") \ + X(ACI, 39, 0x07, "ACE Parity Error") \ + X(ACI, 38, 0x06, "Internal ACI parity Error") \ + X(ACI, 37, 0x05, "AR decode Error") \ + X(ACI, 36, 0x04, "SNOC Protocol Error") \ + X(ACI, 35, 0x03, "Internal ACI FIFO Error") \ + X(ACI, 34, 0x02, "SNOC Parity Error") \ + X(ACI, 33, 0x01, "Lockable CREG Error") + +/* ACI Corrected RAS ERROR */ +#define ACI_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(ACI, 32, 0x00, "SNOC Corrected ECC Error") + +/* CORE DCLS Uncorrectable RAS ERROR */ +#define CORE_DCLS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CORE_DCLS, 48, 0x10, "Redundant Clock, Power and Reset logic error") \ + X(CORE_DCLS, 47, 0x0F, "Redundant System Register Timer logic error") \ + X(CORE_DCLS, 46, 0x0E, "Redundant EVENT logic error") \ + X(CORE_DCLS, 45, 0x0D, "Redundant Timestamp logic error") \ + X(CORE_DCLS, 44, 0x0C, "Redundant APB group error") \ + X(CORE_DCLS, 42, 0x0A, "Redundant GIC group error") \ + X(CORE_DCLS, 41, 0x09, "Redundant CHI logic error") \ + X(CORE_DCLS, 40, 0x08, "Primary Clock, Power and Reset logic error") \ + X(CORE_DCLS, 39, 0x07, "Primary System Register Timer logic error") \ + X(CORE_DCLS, 38, 0x06, "Primary Event logic error") \ + X(CORE_DCLS, 37, 0x05, "Primary Timestamp logic error") \ + X(CORE_DCLS, 36, 0x04, "Primary APB group error") \ + X(CORE_DCLS, 35, 0x03, "Primary ATB group error") \ + X(CORE_DCLS, 34, 0x02, "Primary GIC group error") \ + X(CORE_DCLS, 33, 0x01, "Primary CHI logic error") \ + X(CORE_DCLS, 32, 0x00, "Lock error") + +/* Empty CORE DCLS Corrected RAS ERROR */ +#define CORE_DCLS_CORR_RAS_ERROR_LIST(X) + +/* DSU DCLS Uncorrectable RAS ERROR */ +#define DSU_DCLS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(DSU_DCLS, 57, 0x19, "Illegal mode (CEMODE=0) error") \ + X(DSU_DCLS, 56, 0x18, "Core3 HM DCLS error") \ + X(DSU_DCLS, 55, 0x17, "Core2 HM DCLS error") \ + X(DSU_DCLS, 54, 0x16, "Core1 HM DCLS error") \ + X(DSU_DCLS, 53, 0x15, "Core0 HM DCLS error") \ + X(DSU_DCLS, 52, 0x14, "SB DBG group in DCLSFAULT vector") \ + X(DSU_DCLS, 51, 0x13, "SB GIC group in DCLSFAULT vector") \ + X(DSU_DCLS, 50, 0x12, "SB ATB group in DCLSFAULT vector") \ + X(DSU_DCLS, 49, 0x11, "SB EVENT group in DCLSFAULT vector") \ + X(DSU_DCLS, 48, 0x10, "SB CPM PERIPHCLK in DCLSFAULT vector") \ + X(DSU_DCLS, 47, 0x0F, "SB CPM SCLK in DCLSFAULT vector") \ + X(DSU_DCLS, 46, 0x0E, "SB slice in DCLSFAULT vector") \ + X(DSU_DCLS, 45, 0x0D, "SCU LTDB RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 44, 0x0C, "SCU VICTIM RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 43, 0x0B, "SCU DATA RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 42, 0x0A, "SCU SF RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 41, 0x09, "SCU TAG RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 37, 0x05, "SCU MISC group in DCLSFAULT vector") \ + X(DSU_DCLS, 34, 0x02, "ACE Master 1 in DCLSFAULT vector") \ + X(DSU_DCLS, 33, 0x01, "ACE Master 0 in DCLSFAULT vector") \ + X(DSU_DCLS, 32, 0x00, "Lock Error") + +/* Empty DSU DCLS Corrected RAS ERROR */ +#define DSU_DCLS_CORR_RAS_ERROR_LIST(X) + +/* DSU_IFP Uncorrectable RAS ERROR */ +#define DSU_IFP_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(DSU_IFP, 60, 0x1C, "Errors on POD reset output - it raises error if POD asserts the reset") \ + X(DSU_IFP, 59, 0x1B, "Errors on AXI4 Stream. Flagged for ADB, parity and redundancy errors") \ + X(DSU_IFP, 58, 0x1A, "NV defined core RAS pinned out interface error") \ + X(DSU_IFP, 57, 0x19, "NV defined cluster RAS interrupt interface error") \ + X(DSU_IFP, 56, 0x18, "NV defined cluster reqack interface error") \ + X(DSU_IFP, 55, 0x17, "NV defined core status interface error") \ + X(DSU_IFP, 54, 0x16, "NV defined cluster config interface error") \ + X(DSU_IFP, 53, 0x15, "NV defined cluster power management interface error") \ + X(DSU_IFP, 52, 0x14, "Miscellaneous interface parity error") \ + X(DSU_IFP, 51, 0x13, "Clock/Power related interface parity error") \ + X(DSU_IFP, 49, 0x11, "GIC interface parity error") \ + X(DSU_IFP, 44, 0x0C, "ACE Master 1 interface parity error") \ + X(DSU_IFP, 43, 0x0B, "ACE Master 0 interface parity error") \ + X(DSU_IFP, 42, 0x0A, "Miscellaneous interface parity error") \ + X(DSU_IFP, 41, 0x09, "Clock/Power related interface parity error") \ + X(DSU_IFP, 39, 0x07, "GIC interface parity error") \ + X(DSU_IFP, 34, 0x02, "ACE Master 1 interface parity error") \ + X(DSU_IFP, 33, 0x01, "ACE Master 0 interface parity error") \ + X(DSU_IFP, 32, 0x00, "Lock error") + +/* Empty DSU_IFP Corrected RAS ERROR */ +#define DSU_IFP_CORR_RAS_ERROR_LIST(X) + +/* Empty GIC600_FMU Uncorrected RAS ERROR */ +#define GIC600_FMU_UNCORR_RAS_ERROR_LIST(X) + +/* Empty GIC600_FMU Corrected RAS ERROR */ +#define GIC600_FMU_CORR_RAS_ERROR_LIST(X) + +/* + * Define one ras_error entry. + * + * This macro wille be used to to generate ras_error records for each node + * defined by _UNCORR_RAS_ERROR_LIST macro. + */ +#define DEFINE_ONE_RAS_ERROR_MSG(unit, err_ctrl_bit, ierr, msg) \ + { \ + .error_msg = (msg), \ + .error_code = (ierr) \ + }, + +/* + * Set one implementation defined bit in ERRCTLR + * + * This macro will be used to collect all defined ERR_CTRL bits for each node + * defined by _UNCORR_RAS_ERROR_LIST macro. + */ +#define DEFINE_ENABLE_BIT(unit, err_ctrl_bit, ierr, msg) \ + do { \ + val |= (1ULL << err_ctrl_bit##U); \ + } while (0); + +/* Represent one RAS node with 0 or more error bits (ERR_CTLR) enabled */ +#define DEFINE_ONE_RAS_NODE(node) \ +static struct ras_error node##_uncorr_ras_errors[] = { \ + node##_UNCORR_RAS_ERROR_LIST(DEFINE_ONE_RAS_ERROR_MSG) \ +}; \ +static inline uint64_t node##_get_ue_mask(void) \ +{ \ + uint64_t val = 0ULL; \ + node##_UNCORR_RAS_ERROR_LIST(DEFINE_ENABLE_BIT) \ + return val; \ +}; \ +static inline uint64_t node##_get_ce_mask(void) \ +{ \ + uint64_t val = 0ULL; \ + node##_CORR_RAS_ERROR_LIST(DEFINE_ENABLE_BIT) \ + return val; \ +} + +#define DEFINE_ONE_RAS_AUX_DATA(node) \ +static struct ras_aux_data node##_aux_data = { \ + .name = #node, \ + .error_records = node##_uncorr_ras_errors, \ + .num_err_records = ARRAY_SIZE(node##_uncorr_ras_errors), \ + .get_ue_mask = &node##_get_ue_mask, \ + .get_ce_mask = &node##_get_ce_mask \ + } + +/* + * ERRFR bits[63:32], it indicates supported RAS errors which can be enabled + * by setting corresponding bits in ERRCTLR + */ +#define ERR_FR_EN_BITS_MASK U(0xFFFFFFFF00000000) + +/* IH RAS MUX registers */ +#define IH_RAS_MUX_BASE U(0x0E005000) +#define CORE0_RAS_GENERAL_MASK U(0x000) +#define CORE0_RAS_GENERAL_ENABLE U(0x008) +#define CORE0_RAS_INSTATUS U(0x010) +#define CORE0_RAS_INSTATUS_CLR U(0x018) +#define RAS_GLOBAL_EN U(0x820) + +/* IH RAS MUX register settings */ +#define ENB_ALL_INTR_SOURCES U(0x0000FFFFFF3F3F7F) +#define IH_INTR_ROUTING_ENABLED (BIT(17) | BIT(16)| U(0xFFF)) + +/* Per core offset to get to the core's IH registers */ +#define PER_CORE_IH_OFFSET U(0x28) + +static inline uint64_t ih_read_ras_intstatus(int core) +{ + uint32_t offset = (PER_CORE_IH_OFFSET * core) + CORE0_RAS_INSTATUS; + return mmio_read_64(IH_RAS_MUX_BASE + offset); +} + +static inline void ih_write_intstatus_clr(int core, uint64_t val) +{ + uint32_t offset = (PER_CORE_IH_OFFSET * core) + CORE0_RAS_INSTATUS_CLR; + mmio_write_64(IH_RAS_MUX_BASE + offset, val); +} + +static inline void ih_write_ras_general_mask(int core, uint64_t val) +{ + uint32_t offset = (PER_CORE_IH_OFFSET * core) + CORE0_RAS_GENERAL_MASK; + mmio_write_64(IH_RAS_MUX_BASE + offset, val); + assert(mmio_read_64(IH_RAS_MUX_BASE + offset) == val); +} + +static inline void ih_write_ras_general_enb(int core, uint64_t val) +{ + uint32_t offset = (PER_CORE_IH_OFFSET * core) + CORE0_RAS_GENERAL_ENABLE; + mmio_write_64(IH_RAS_MUX_BASE + offset, val); + assert(mmio_read_64(IH_RAS_MUX_BASE + offset) == val); +} + +#endif /* TEGRA234_RAS_PRIVATE */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h new file mode 100644 index 0000000..4c3d308 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TEGRA_DEF_H__ +#define __TEGRA_DEF_H__ + +#include + +/******************************************************************************* + * Platform BL31 specific defines. + ******************************************************************************/ +#define BL31_SIZE U(0x80000) + +/* Platform power domain constants*/ +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + U(1)) + +/* Tegra CORE and CLUSTER affinity values */ +#define TEGRA_CORE_AFFINITY MPIDR_AFF1_SHIFT +#define TEGRA_CLUSTER_AFFINITY MPIDR_AFF2_SHIFT + +/******************************************************************************* + * Chip specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 40) + +/******************************************************************************* + * These values are used by the PSCI implementation during the `CPU_SUSPEND` + * and `SYSTEM_SUSPEND` calls as the `state-id` field in the 'power state' + * parameter. + ******************************************************************************/ +#define PSTATE_ID_CORE_IDLE U(6) +#define PSTATE_ID_CORE_POWERDN U(7) +#define PSTATE_ID_SOC_POWERDN U(2) + +/******************************************************************************* + * Platform power states (used by PSCI framework) + * + * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID + * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID + ******************************************************************************/ +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(8) + +/******************************************************************************* + * Secure IRQ definitions + ******************************************************************************/ +#define TEGRA234_RAS_PPI_ERI U(16) +#define TEGRA234_RAS_PPI_FHI U(17) +#define TEGRA234_TOP_WDT_IRQ U(49) +#define TEGRA234_AON_WDT_IRQ U(50) +#define PLATFORM_FIQ_PPI_WDT TEGRA234_TOP_WDT_IRQ + +/******************************************************************************* + * Clock identifier for the SE device + ******************************************************************************/ +#define TEGRA234_CLK_SEU1 U(336) +#define TEGRA_CLK_SE TEGRA234_CLK_SEU1 + +/******************************************************************************* + * Tegra Miscellanous register constants + ******************************************************************************/ +#define TEGRA_MISC_BASE U(0x00100000) + +#define HARDWARE_REVISION_OFFSET U(0x4) +#define MISCREG_EMU_REVID U(0x3160) +#define BOARD_MASK_BITS U(0xFF) +#define BOARD_SHIFT_BITS U(24) + +/******************************************************************************* + * Tegra General Purpose Centralised DMA constants + ******************************************************************************/ +#define TEGRA_GPCDMA_BASE U(0x02600000) + +/******************************************************************************* + * Tegra Memory Controller constants + ******************************************************************************/ +#define TEGRA_MC_STREAMID_BASE U(0x02C00000) +#define TEGRA_MC_STREAMID_LIMIT U(0x02C0FFFF) +#define TEGRA_MC_BASE U(0x02C10000) +#define TEGRA_MC_LIMIT U(0x02C1FFFF) + +/* General Security Carveout register macros */ +#define MC_GSC_CONFIG_REGS_SIZE U(0x40) +#define MC_GSC_LOCK_CFG_SETTINGS_BIT (U(1) << 1) +#define MC_GSC_ENABLE_TZ_LOCK_BIT (U(1) << 0) +#define MC_GSC_SIZE_RANGE_4KB_SHIFT U(27) +#define MC_GSC_BASE_LO_SHIFT U(12) +#define MC_GSC_BASE_LO_MASK U(0xFFFFF) +#define MC_GSC_BASE_HI_SHIFT U(0) +#define MC_GSC_BASE_HI_MASK U(3) +#define MC_GSC_ENABLE_CPU_SECURE_BIT (U(1) << 31) + +/* TZDRAM carveout configuration registers */ +#define MC_SECURITY_CFG0_0 U(0x70) +#define MC_SECURITY_CFG1_0 U(0x74) +#define MC_SECURITY_CFG3_0 U(0x9BC) + +#define MC_SECURITY_BOM_MASK (U(0xFFF) << 20) +#define MC_SECURITY_SIZE_MB_MASK (U(0x1FFF) << 0) +#define MC_SECURITY_BOM_HI_MASK (U(0x3) << 0) + +#define MC_SECURITY_CFG_REG_CTRL_0 U(0x154) +#define SECURITY_CFG_WRITE_ACCESS_BIT (U(0x1) << 0) +#define SECURITY_CFG_WRITE_ACCESS_ENABLE U(0x0) +#define SECURITY_CFG_WRITE_ACCESS_DISABLE U(0x1) + +/* Video Memory carveout configuration registers */ +#define MC_VIDEO_PROTECT_BASE_HI U(0x978) +#define MC_VIDEO_PROTECT_BASE_LO U(0x648) +#define MC_VIDEO_PROTECT_SIZE_MB U(0x64c) +#define MC_VIDEO_PROTECT_REG_CTRL U(0x650) +#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED U(3) + +/* + * Carveout (MC_SECURITY_CARVEOUT24) registers used to clear the + * non-overlapping Video memory region + */ +#define MC_VIDEO_PROTECT_CLEAR_CFG U(0x25A0) +#define MC_VIDEO_PROTECT_CLEAR_BASE_LO U(0x25A4) +#define MC_VIDEO_PROTECT_CLEAR_BASE_HI U(0x25A8) +#define MC_VIDEO_PROTECT_CLEAR_SIZE U(0x25AC) +#define MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 U(0x25B0) + +/* TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers */ +#define MC_TZRAM_CARVEOUT_CFG U(0x2190) +#define MC_TZRAM_BASE_LO U(0x2194) +#define MC_TZRAM_BASE_HI U(0x2198) +#define MC_TZRAM_SIZE U(0x219C) +#define MC_TZRAM_CLIENT_ACCESS0_CFG0 U(0x21A0) +#define MC_TZRAM_CLIENT_ACCESS1_CFG0 U(0x21A4) +#define TZRAM_ALLOW_MPCORER (U(1) << 7) +#define TZRAM_ALLOW_MPCOREW (U(1) << 25) + +/* CCPLEX-BPMP IPC carveout (MC_SECURITY_CARVEOUT18) configuration registers */ +#define MC_CCPLEX_BPMP_IPC_BASE_LO U(0x23c4) +#define MC_CCPLEX_BPMP_IPC_BASE_HI U(0x23c8) + +/* Memory Controller Reset Control registers */ +#define MC_CLIENT_HOTRESET_CTRL1_DLAA_FLUSH_ENB (U(1) << 28) +#define MC_CLIENT_HOTRESET_CTRL1_DLA1A_FLUSH_ENB (U(1) << 29) +#define MC_CLIENT_HOTRESET_CTRL1_PVA0A_FLUSH_ENB (U(1) << 30) +#define MC_CLIENT_HOTRESET_CTRL1_PVA1A_FLUSH_ENB (U(1) << 31) + +/******************************************************************************* + * Tegra UART Controller constants + ******************************************************************************/ +#define TEGRA_UARTA_BASE U(0x03100000) +#define TEGRA_UARTB_BASE U(0x03110000) +#define TEGRA_UARTC_BASE U(0x0C280000) +#define TEGRA_UARTD_BASE U(0x03130000) +#define TEGRA_UARTE_BASE U(0x03140000) +#define TEGRA_UARTF_BASE U(0x03150000) + +/******************************************************************************* + * Tegra Fuse Controller related constants + ******************************************************************************/ +#define TEGRA_FUSE_BASE U(0x03810000) +#define SECURITY_MODE U(0x1A0) +#define OPT_SUBREVISION U(0x248) +#define SUBREVISION_MASK U(0xF) + +/******************************************************************************* + * Security Engine related constants + ******************************************************************************/ +#define TEGRA_RNG1_BASE U(0x03B70000) +#define NV_NVRNG_R_CTRL U(0x8C) +#define SW_ENGINE_ENABLED BIT_32(2) + +#define TEGRA_SE0_BASE U(0x03B50000) +#define TEGRA_PKA1_BASE U(0x03AD0000) + +/******************************************************************************* + * Tegra HSP doorbell #0 constants + ******************************************************************************/ +#define TEGRA_HSP_DBELL_BASE U(0x03C90000) +#define HSP_DBELL_1_ENABLE U(0x104) +#define HSP_DBELL_3_TRIGGER U(0x300) +#define HSP_DBELL_3_ENABLE U(0x304) + +/******************************************************************************* + * Tegra hardware synchronization primitives for the SPE engine + ******************************************************************************/ +#define TEGRA_AON_HSP_SM_6_7_BASE U(0x0c190000) +#define TEGRA_CONSOLE_SPE_BASE (TEGRA_AON_HSP_SM_6_7_BASE + U(0x8000)) + +/******************************************************************************* + * Tegra micro-seconds timer constants + ******************************************************************************/ +#define TEGRA_TMRUS_BASE U(0x0C6B0000) +#define TEGRA_TMRUS_SIZE U(0x10000) + +/******************************************************************************* + * Tegra Power Mgmt Controller constants + ******************************************************************************/ +#define TEGRA_PMC_BASE U(0x0C360000) +#define TEGRA_PMC_SIZE U(0x1000) + +/******************************************************************************* + * Tegra scratch registers constants + ******************************************************************************/ +#define TEGRA_SCRATCH_BASE U(0x0C390000) +#define SECURE_SCRATCH_RSV28_LO U(0x144) +#define SECURE_SCRATCH_RSV28_HI U(0x148) +#define SECURE_SCRATCH_RSV33_LO U(0x16C) +#define SECURE_SCRATCH_RSV33_HI U(0x170) +#define SECURE_SCRATCH_RSV34_LO U(0x174) +#define SECURE_SCRATCH_RSV34_HI U(0x178) +#define SECURE_SCRATCH_RSV41_LO U(0x1AC) +#define SECURE_SCRATCH_RSV97 U(0x36C) +#define SECURE_SCRATCH_RSV99_LO U(0x37C) +#define SECURE_SCRATCH_RSV99_HI U(0x380) + +#define SCRATCH_BL31_PARAMS_HI_ADDR SECURE_SCRATCH_RSV33_HI +#define SCRATCH_BL31_PARAMS_HI_ADDR_MASK U(0xFFFF) +#define SCRATCH_BL31_PARAMS_HI_ADDR_SHIFT U(0) +#define SCRATCH_BL31_PARAMS_LO_ADDR SECURE_SCRATCH_RSV33_LO +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR SECURE_SCRATCH_RSV34_HI +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_MASK U(0xFFFF) +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT U(0) +#define SCRATCH_BL31_PLAT_PARAMS_LO_ADDR SECURE_SCRATCH_RSV34_LO +#define SCRATCH_IST_CLK_ENABLE SECURE_SCRATCH_RSV41_LO +#define SCRATCH_MC_TABLE_ADDR_LO SECURE_SCRATCH_RSV99_LO +#define SCRATCH_MC_TABLE_ADDR_HI SECURE_SCRATCH_RSV99_HI +#define SCRATCH_RESET_VECTOR_LO SECURE_SCRATCH_RSV28_LO +#define SCRATCH_RESET_VECTOR_HI SECURE_SCRATCH_RSV28_HI + +/******************************************************************************* + * Tegra AON Fabric constants + ******************************************************************************/ +#define TEGRA_AON_FABRIC_FIREWALL_BASE U(0x0C630000) +#define AON_FIREWALL_ARF_0_WRITE_CTL U(0x8) +#define WRITE_CTL_MSTRID_TZ_BIT BIT(0) +#define WRITE_CTL_MSTRID_BPMP_FW_BIT BIT(3) +#define AON_FIREWALL_ARF_0_CTL U(0x10) +#define ARF_CTL_OWNER_BPMP_FW U(3) + +/******************************************************************************* + * Tegra Memory Mapped Control Register Access Bus constants + ******************************************************************************/ +#define TEGRA_MMCRAB_BASE U(0x0E000000) + +/******************************************************************************* + * MCE apertures used by the ARI interface + * + * Aperture 0 - cluster0 Cpu0 + * Aperture 1 - cluster0 Cpu1 + * Aperture 2 - cluster0 Cpu2 + * Aperture 3 - cluster0 Cpu3 + * Aperture 4 - cluster1 Cpu0 + * Aperture 5 - cluster1 Cpu1 + * Aperture 6 - cluster1 Cpu2 + * Aperture 7 - cluster1 Cpu3 + * Aperture 8 - cluster2 Cpu0 + * Aperture 9 - cluster2 Cpu1 + * Aperture 10 - cluster2 Cpu2 + * Aperture 11 - cluster2 Cpu3 + ******************************************************************************/ +#define MCE_ARI_APERTURE_0_OFFSET U(0x200000) +#define MCE_ARI_APERTURE_1_OFFSET U(0x210000) +#define MCE_ARI_APERTURE_2_OFFSET U(0x220000) +#define MCE_ARI_APERTURE_3_OFFSET U(0x230000) +#define MCE_ARI_APERTURE_4_OFFSET U(0x240000) +#define MCE_ARI_APERTURE_5_OFFSET U(0x250000) +#define MCE_ARI_APERTURE_6_OFFSET U(0x260000) +#define MCE_ARI_APERTURE_7_OFFSET U(0x270000) +#define MCE_ARI_APERTURE_8_OFFSET U(0x280000) +#define MCE_ARI_APERTURE_9_OFFSET U(0x290000) +#define MCE_ARI_APERTURE_10_OFFSET U(0x2A0000) +#define MCE_ARI_APERTURE_11_OFFSET U(0x2B0000) + +/******************************************************************************* + * GICv3 constants + ******************************************************************************/ +#define TEGRA_GICD_BASE U(0x0F400000) +#define TEGRA_GICR_BASE U(0x0F440000) +#define TEGRA_GICFMU_BASE U(0x0F7F0000) + +/******************************************************************************* + * Tegra SMMU Controller constants + ******************************************************************************/ +#define TEGRA_SMMU0_BASE U(0x12000000) +#define TEGRA_SMMU1_BASE U(0x11000000) +#define TEGRA_SMMU2_BASE U(0x10000000) +#define TEGRA_SMMU3_BASE U(0x07000000) +#define TEGRA_SMMU4_BASE U(0x08000000) + +/******************************************************************************* + * Tegra PSC mailbox + ******************************************************************************/ +#define TEGRA_PSC_MBOX_TZ_BASE U(0x0E830000) +#define PSC_MBOX_TZ_EXT_CTRL U(0x0004) +#define PSC_MBOX_TZ_PSC_CTRL U(0x0008) +#define PSC_MBOX_TZ_IN U(0x0800) +#define PSC_MBOX_TZ_OUT_0 U(0x1000) +#define PSC_MBOX_TZ_OUT_1 U(0x1004) +#define PSC_MBOX_OUT_DONE U(0x10) +#define PSC_MBOX_IN_VALID U(0x1) +#define PSC_MBOX_IN_DONE U(0x10) +#define PSC_MBOX_OUT_VALID U(0x1) +#define PSC_MBOX_TZ_OPCODE_ENTER_SC7 U(0x53433745) +#define PSC_MBOX_SC7_ENTRY_PASS U(0x0) +#define PSC_MBOX_ACK_TIMEOUT_MAX_USEC U(50) + + +/******************************************************************************* + * RAS records + ******************************************************************************/ +#define TEGRA_CCPMU_RAS_BASE U(0x0E001000) +#define TEGRA_RAS_CL0_CORE0_BASE U(0x0E030000) +#define TEGRA_RAS_CL1_CORE0_BASE U(0x0E040000) +#define TEGRA_RAS_CL2_CORE0_BASE U(0x0E050000) + +/******************************************************************************* + * Tegra TZRAM constants + ******************************************************************************/ +#define TEGRA_TZRAM_BASE U(0x50000000) +#define TEGRA_TZRAM_SIZE U(0x40000) + +/******************************************************************************* + * Tegra CCPLEX-BPMP IPC constants + ******************************************************************************/ +#define TEGRA_BPMP_IPC_CH_MAP_SIZE U(0x1000) /* 4KB */ + +/******************************************************************************* + * Tegra Clock and Reset Controller constants + ******************************************************************************/ +#define TEGRA_CAR_RESET_BASE U(0x20000000) +#define TEGRA_GPU_RESET_REG_OFFSET U(0x0) +#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x4) +#define GPU_RESET_BIT (U(1) << 0) +#define GPU_SET_BIT (U(1) << 0) +#define TEGRA_GPCDMA_RST_SET_REG_OFFSET U(0x6A0004) +#define TEGRA_GPCDMA_RST_CLR_REG_OFFSET U(0x6A0008) + +/******************************************************************************* + * Tegra DRAM memory base address + ******************************************************************************/ +#define TEGRA_DRAM_BASE ULL(0x80000000) +#define TEGRA_DRAM_END ULL(0x207FFFFFFF) + +/******************************************************************************* + * XUSB STREAMIDs + ******************************************************************************/ +#define TEGRA_SID_XUSB_HOST U(0x1b) +#define TEGRA_SID_XUSB_DEV U(0x1c) +#define TEGRA_SID_XUSB_VF0 U(0x5d) +#define TEGRA_SID_XUSB_VF1 U(0x5e) +#define TEGRA_SID_XUSB_VF2 U(0x5f) +#define TEGRA_SID_XUSB_VF3 U(0x60) + +/******************************************************************************* + * Tegra SYSRAM base and limit. + ******************************************************************************/ +#define TEGRA_SYSRAM_BASE U(0x40000000) +#define TEGRA_SYSRAM_SIZE U(0x10000000) + +/******************************************************************************* + * Tegra Debug APB base address and ETM related constants + ******************************************************************************/ +#define TEGRA_DBGAPB_BASE ULL(0x209F0000) +#define TEGRA_TRCPRGCTLR_OFFSET U(0x4) +#define TRCPRGCTLR_EN_BIT BIT_32(0) + +#endif /* __TEGRA_DEF_H__ */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h new file mode 100644 index 0000000..8dc5603 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h @@ -0,0 +1,685 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TEGRA_MC_DEF_H__ +#define __TEGRA_MC_DEF_H__ + +/******************************************************************************* + * Memory Controller Order_id registers + ******************************************************************************/ +#define MC_CLIENT_ORDER_ID_9 U(0x2a24) +#define MC_CLIENT_ORDER_ID_9_RESET_VAL 0x00000000U +#define MC_CLIENT_ORDER_ID_9_XUSB_HOSTW_MASK (0x3U << 12) +#define MC_CLIENT_ORDER_ID_9_XUSB_HOSTW_ORDER_ID (3U << 12) + +#define MC_CLIENT_ORDER_ID_27 U(0x2a6c) +#define MC_CLIENT_ORDER_ID_27_RESET_VAL 0x00000000U +#define MC_CLIENT_ORDER_ID_27_PCIE0W_MASK (0x3U << 4) +#define MC_CLIENT_ORDER_ID_27_PCIE0W_ORDER_ID (2U << 4) + +#define MC_CLIENT_ORDER_ID_28 U(0x2a70) +#define MC_CLIENT_ORDER_ID_28_RESET_VAL 0x00000000U +#define MC_CLIENT_ORDER_ID_28_PCIE4W_MASK (0x3U << 4) +#define MC_CLIENT_ORDER_ID_28_PCIE4W_ORDER_ID (3U << 4) +#define MC_CLIENT_ORDER_ID_28_PCIE5W_MASK (0x3U << 12) +#define MC_CLIENT_ORDER_ID_28_PCIE5W_ORDER_ID (1U << 12) + +#define mc_client_order_id(val, id, client) \ + ((val & ~MC_CLIENT_ORDER_ID_##id##_##client##_MASK) | \ + MC_CLIENT_ORDER_ID_##id##_##client##_ORDER_ID) + +/******************************************************************************* + * Memory Controller's VC ID configuration registers + ******************************************************************************/ +#define VC_NISO 0U +#define VC_SISO 1U +#define VC_ISO 2U + +#define MC_HUB_PC_VC_ID_0 U(0x2a78) +#define MC_HUB_PC_VC_ID_0_RESET_VAL 0x00020100U +#define MC_HUB_PC_VC_ID_0_APB_VC_ID_MASK (0x3U << 8) +#define MC_HUB_PC_VC_ID_0_APB_VC_ID (VC_NISO << 8) + +#define MC_HUB_PC_VC_ID_2 U(0x2a80) +#define MC_HUB_PC_VC_ID_2_RESET_VAL 0x10001000U +#define MC_HUB_PC_VC_ID_2_SD_VC_ID_MASK (0x3U << 28) +#define MC_HUB_PC_VC_ID_2_SD_VC_ID (VC_NISO << 28) + +#define MC_HUB_PC_VC_ID_4 U(0x2a88) +#define MC_HUB_PC_VC_ID_4_RESET_VAL 0x10020011U +#define MC_HUB_PC_VC_ID_4_NIC_VC_ID_MASK (0x3U << 28) +#define MC_HUB_PC_VC_ID_4_NIC_VC_ID (VC_NISO << 28) + +#define MC_HUB_PC_VC_ID_12 U(0x2aa8) +#define MC_HUB_PC_VC_ID_12_RESET_VAL 0x11001011U +#define MC_HUB_PC_VC_ID_12_UFSHCPC2_VC_ID_MASK (0x3U << 12) +#define MC_HUB_PC_VC_ID_12_UFSHCPC2_VC_ID (VC_NISO << 12) + +#define mc_hub_vc_id(val, id, client) \ + ((val & ~MC_HUB_PC_VC_ID_##id##_##client##_VC_ID_MASK) | \ + MC_HUB_PC_VC_ID_##id##_##client##_VC_ID) + +/******************************************************************************* + * Memory Controller's PCFIFO client configuration registers + ******************************************************************************/ +#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0U + +#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4U +#define MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL 0x20200000U +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_AFIW_UNORDERED (0U << 17) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_AFIW_MASK (1U << 17) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_HDAW_UNORDERED (0U << 21) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_HDAW_MASK (1U << 21) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_UNORDERED (0U << 29) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_ORDERED (1U << 29) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_MASK (1U << 29) + +#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8U +#define MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL 0x00002800U +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_HOSTW_UNORDERED (0U << 11) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_HOSTW_MASK (1U << 11) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_UNORDERED (0U << 13) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_ORDERED (1U << 13) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_MASK (1U << 13) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_TSECSWR_UNORDERED (0U << 21) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_TSECSWR_MASK (1U << 21) + +#define MC_PCFIFO_CLIENT_CONFIG3 0xddcU +#define MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL 0x08000080U +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWA_UNORDERED (0U << 4) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWA_MASK (1U << 4) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCW_UNORDERED (0U << 6) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCW_MASK (1U << 6) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_UNORDERED (0U << 7) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_MASK (1U << 7) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_VICSWR_UNORDERED (0U << 13) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_VICSWR_MASK (1U << 13) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_APEW_UNORDERED (0U << 27) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_APEW_MASK (1U << 27) + +#define MC_PCFIFO_CLIENT_CONFIG4 0xde0U +#define MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL 0x5552a022U +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SESWR_UNORDERED (0U << 1) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SESWR_MASK (1U << 1) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_ETRW_UNORDERED (0U << 5) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_ETRW_MASK (1U << 5) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_TSECSWRB_UNORDERED (0U << 7) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_TSECSWRB_MASK (1U << 7) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AXISW_UNORDERED (0U << 13) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AXISW_MASK (1U << 13) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_UNORDERED (0U << 15) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_MASK (1U << 15) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_UFSHCW_UNORDERED (0U << 17) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_UFSHCW_MASK (1U << 17) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPW_UNORDERED (0U << 20) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPW_MASK (1U << 20) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPDMAW_UNORDERED (0U << 22) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPDMAW_MASK (1U << 22) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONW_UNORDERED (0U << 24) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONW_MASK (1U << 24) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONDMAW_UNORDERED (0U << 26) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONDMAW_MASK (1U << 26) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEW_UNORDERED (0U << 28) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEW_MASK (1U << 28) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEDMAW_UNORDERED (0U << 30) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEDMAW_MASK (1U << 30) + +#define MC_PCFIFO_CLIENT_CONFIG5 0xbf4U +#define MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL 0x20000001U +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_UNORDERED (0U << 0) +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_MASK (1U << 0) +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_VIFALW_UNORDERED (0U << 30) +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_VIFALW_MASK (1U << 30) + +#define MC_PCFIFO_CLIENT_CONFIG6 0xb90U +#define MC_PCFIFO_CLIENT_CONFIG6_RESET_VAL 0xaa280000U +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_RCEW_UNORDERED (0U << 19) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_RCEW_MASK (1U << 19) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_RCEDMAW_UNORDERED (0U << 21) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_RCEDMAW_MASK (1U << 21) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE0W_UNORDERED (0U << 25) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE0W_MASK (1U << 25) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE1W_ORDERED (1U << 27) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE1W_MASK (1U << 27) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE2W_ORDERED (1U << 29) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE2W_MASK (1U << 29) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE3W_ORDERED (1U << 31) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE3W_MASK (1U << 31) + +#define MC_PCFIFO_CLIENT_CONFIG7 0xaccU +#define MC_PCFIFO_CLIENT_CONFIG7_RESET_VAL 0x0000000aU +#define MC_PCFIFO_CLIENT_CONFIG7_PCFIFO_PCIE4W_UNORDERED (0U << 1) +#define MC_PCFIFO_CLIENT_CONFIG7_PCFIFO_PCIE4W_MASK (1U << 1) +#define MC_PCFIFO_CLIENT_CONFIG7_PCFIFO_PCIE5W_UNORDERED (0U << 3) +#define MC_PCFIFO_CLIENT_CONFIG7_PCFIFO_PCIE5W_MASK (1U << 3) + +/******************************************************************************* + * StreamID to indicate no SMMU translations (requests to be steered on the + * SMMU bypass path) + ******************************************************************************/ +#define MC_STREAM_ID_MAX 0x7FU + +/******************************************************************************* + * Stream ID Override Config registers + ******************************************************************************/ +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDA 0x660U +#define MC_STREAMID_OVERRIDE_CFG_NVENCSRD 0xe0U +#define MC_STREAMID_OVERRIDE_CFG_NVJPGSWR 0x3f8U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDA1 0x758U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDC 0x640U +#define MC_STREAMID_OVERRIDE_CFG_DLA0RDA 0x5f0U +#define MC_STREAMID_OVERRIDE_CFG_BPMPR 0x498U +#define MC_STREAMID_OVERRIDE_CFG_APEDMAR 0x4f8U +#define MC_STREAMID_OVERRIDE_CFG_AXISR 0x460U +#define MC_STREAMID_OVERRIDE_CFG_TSECSRD 0x2a0U +#define MC_STREAMID_OVERRIDE_CFG_DLA0FALRDB 0x5f8U +#define MC_STREAMID_OVERRIDE_CFG_NVENC1SRD1 0x788U +#define MC_STREAMID_OVERRIDE_CFG_MPCOREW 0x1c8U +#define MC_STREAMID_OVERRIDE_CFG_NVENCSRD1 0x780U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTR 0x250U +#define MC_STREAMID_OVERRIDE_CFG_MIU1R 0x540U +#define MC_STREAMID_OVERRIDE_CFG_MIU0R 0x530U +#define MC_STREAMID_OVERRIDE_CFG_PCIE1W 0x6d8U +#define MC_STREAMID_OVERRIDE_CFG_PVA1WRA 0x678U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTW 0x258U +#define MC_STREAMID_OVERRIDE_CFG_AXIAPW 0x418U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCWAB 0x338U +#define MC_STREAMID_OVERRIDE_CFG_SATAW 0x1e8U +#define MC_STREAMID_OVERRIDE_CFG_DLA0WRA 0x600U +#define MC_STREAMID_OVERRIDE_CFG_PCIE3R 0x6f0U +#define MC_STREAMID_OVERRIDE_CFG_MIU3W 0x588U +#define MC_STREAMID_OVERRIDE_CFG_SCEDMAR 0x4e8U +#define MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR 0xb0U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCWA 0x320U +#define MC_STREAMID_OVERRIDE_CFG_MIU2R 0x570U +#define MC_STREAMID_OVERRIDE_CFG_APEDMAW 0x500U +#define MC_STREAMID_OVERRIDE_CFG_PCIE2AW 0x6e8U +#define MC_STREAMID_OVERRIDE_CFG_SESWR 0x408U +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDB1 0x770U +#define MC_STREAMID_OVERRIDE_CFG_AXISW 0x468U +#define MC_STREAMID_OVERRIDE_CFG_DLA1FALRDB 0x618U +#define MC_STREAMID_OVERRIDE_CFG_AONDMAW 0x4d0U +#define MC_STREAMID_OVERRIDE_CFG_TSECSWRB 0x438U +#define MC_STREAMID_OVERRIDE_CFG_ISPWB 0x238U +#define MC_STREAMID_OVERRIDE_CFG_HDAR 0xa8U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCRA 0x300U +#define MC_STREAMID_OVERRIDE_CFG_ETRW 0x428U +#define MC_STREAMID_OVERRIDE_CFG_RCEDMAW 0x6a8U +#define MC_STREAMID_OVERRIDE_CFG_TSECSWR 0x2a8U +#define MC_STREAMID_OVERRIDE_CFG_ETRR 0x420U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCR 0x310U +#define MC_STREAMID_OVERRIDE_CFG_NVJPGSRD 0x3f0U +#define MC_STREAMID_OVERRIDE_CFG_AONDMAR 0x4c8U +#define MC_STREAMID_OVERRIDE_CFG_SCER 0x4d8U +#define MC_STREAMID_OVERRIDE_CFG_MIU5W 0x7e8U +#define MC_STREAMID_OVERRIDE_CFG_NVENC1SRD 0x6b0U +#define MC_STREAMID_OVERRIDE_CFG_PCIE4R 0x700U +#define MC_STREAMID_OVERRIDE_CFG_ISPWA 0x230U +#define MC_STREAMID_OVERRIDE_CFG_PCIE0W 0x6c8U +#define MC_STREAMID_OVERRIDE_CFG_PCIE5R1 0x778U +#define MC_STREAMID_OVERRIDE_CFG_DLA1RDA 0x610U +#define MC_STREAMID_OVERRIDE_CFG_VICSWR 0x368U +#define MC_STREAMID_OVERRIDE_CFG_SESRD 0x400U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCW 0x330U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCRAB 0x318U +#define MC_STREAMID_OVERRIDE_CFG_ISPFALW 0x720U +#define MC_STREAMID_OVERRIDE_CFG_EQOSW 0x478U +#define MC_STREAMID_OVERRIDE_CFG_RCEDMAR 0x6a0U +#define MC_STREAMID_OVERRIDE_CFG_RCER 0x690U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSWR 0x3c8U +#define MC_STREAMID_OVERRIDE_CFG_UFSHCR 0x480U +#define MC_STREAMID_OVERRIDE_CFG_PCIE4W 0x708U +#define MC_STREAMID_OVERRIDE_CFG_VICSRD 0x360U +#define MC_STREAMID_OVERRIDE_CFG_APER 0x3d0U +#define MC_STREAMID_OVERRIDE_CFG_MIU7R 0x8U +#define MC_STREAMID_OVERRIDE_CFG_NVDEC1SRD 0x7c8U +#define MC_STREAMID_OVERRIDE_CFG_MIU7W 0x10U +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDA1 0x768U +#define MC_STREAMID_OVERRIDE_CFG_PVA1WRC 0x688U +#define MC_STREAMID_OVERRIDE_CFG_AONW 0x4c0U +#define MC_STREAMID_OVERRIDE_CFG_MIU4W 0x598U +#define MC_STREAMID_OVERRIDE_CFG_HDAW 0x1a8U +#define MC_STREAMID_OVERRIDE_CFG_BPMPW 0x4a0U +#define MC_STREAMID_OVERRIDE_CFG_DLA1WRA 0x620U +#define MC_STREAMID_OVERRIDE_CFG_DLA0RDA1 0x748U +#define MC_STREAMID_OVERRIDE_CFG_MIU1W 0x548U +#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR1 0x508U +#define MC_STREAMID_OVERRIDE_CFG_VICSRD1 0x510U +#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAW 0x4b0U +#define MC_STREAMID_OVERRIDE_CFG_NVDEC1SWR 0x7d8U +#define MC_STREAMID_OVERRIDE_CFG_PVA0WRC 0x658U +#define MC_STREAMID_OVERRIDE_CFG_PCIE5R 0x710U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVR 0x260U +#define MC_STREAMID_OVERRIDE_CFG_UFSHCW 0x488U +#define MC_STREAMID_OVERRIDE_CFG_PVA1WRB 0x680U +#define MC_STREAMID_OVERRIDE_CFG_PVA0WRB 0x650U +#define MC_STREAMID_OVERRIDE_CFG_DLA1FALWRB 0x628U +#define MC_STREAMID_OVERRIDE_CFG_NVENC1SWR 0x6b8U +#define MC_STREAMID_OVERRIDE_CFG_PCIE0R 0x6c0U +#define MC_STREAMID_OVERRIDE_CFG_PCIE3W 0x6f8U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDA 0x630U +#define MC_STREAMID_OVERRIDE_CFG_MIU6W 0x7f8U +#define MC_STREAMID_OVERRIDE_CFG_PCIE1R 0x6d0U +#define MC_STREAMID_OVERRIDE_CFG_NVDEC1SRD1 0x7d0U +#define MC_STREAMID_OVERRIDE_CFG_DLA0FALWRB 0x608U +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDC 0x670U +#define MC_STREAMID_OVERRIDE_CFG_MIU0W 0x538U +#define MC_STREAMID_OVERRIDE_CFG_MIU2W 0x578U +#define MC_STREAMID_OVERRIDE_CFG_MPCORER 0x138U +#define MC_STREAMID_OVERRIDE_CFG_AXIAPR 0x410U +#define MC_STREAMID_OVERRIDE_CFG_AONR 0x4b8U +#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAR 0x4a8U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDB 0x638U +#define MC_STREAMID_OVERRIDE_CFG_VIFALW 0x5e8U +#define MC_STREAMID_OVERRIDE_CFG_MIU6R 0x7f0U +#define MC_STREAMID_OVERRIDE_CFG_EQOSR 0x470U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD 0x3c0U +#define MC_STREAMID_OVERRIDE_CFG_TSECSRDB 0x430U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD1 0x518U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDB1 0x760U +#define MC_STREAMID_OVERRIDE_CFG_PCIE0R1 0x798U +#define MC_STREAMID_OVERRIDE_CFG_SCEDMAW 0x4f0U +#define MC_STREAMID_OVERRIDE_CFG_APEW 0x3d8U +#define MC_STREAMID_OVERRIDE_CFG_MIU5R 0x7e0U +#define MC_STREAMID_OVERRIDE_CFG_DLA1RDA1 0x750U +#define MC_STREAMID_OVERRIDE_CFG_PVA0WRA 0x648U +#define MC_STREAMID_OVERRIDE_CFG_ISPFALR 0x228U +#define MC_STREAMID_OVERRIDE_CFG_PTCR 0x0U +#define MC_STREAMID_OVERRIDE_CFG_MIU4R 0x590U +#define MC_STREAMID_OVERRIDE_CFG_ISPRA 0x220U +#define MC_STREAMID_OVERRIDE_CFG_VIFALR 0x5e0U +#define MC_STREAMID_OVERRIDE_CFG_PCIE2AR 0x6e0U +#define MC_STREAMID_OVERRIDE_CFG_RCEW 0x698U +#define MC_STREAMID_OVERRIDE_CFG_ISPRA1 0x790U +#define MC_STREAMID_OVERRIDE_CFG_SCEW 0x4e0U +#define MC_STREAMID_OVERRIDE_CFG_MIU3R 0x580U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVW 0x268U +#define MC_STREAMID_OVERRIDE_CFG_SATAR 0xf8U +#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR 0x490U +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDB 0x668U +#define MC_STREAMID_OVERRIDE_CFG_VIW 0x390U +#define MC_STREAMID_OVERRIDE_CFG_NVENCSWR 0x158U +#define MC_STREAMID_OVERRIDE_CFG_PCIE5W 0x718U + +/******************************************************************************* + * Macro to calculate Security cfg register addr from StreamID Override register + ******************************************************************************/ +#define MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(addr) ((addr) + (uint32_t)sizeof(uint32_t)) + +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_NO_OVERRIDE_SO_DEV (0U << 4) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_NON_COHERENT_SO_DEV (1U << 4) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SO_DEV (2U << 4) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SNOOP_SO_DEV (3U << 4) + +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_NO_OVERRIDE_NORMAL (0U << 8) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_NON_COHERENT_NORMAL (1U << 8) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_NORMAL (2U << 8) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SNOOP_NORMAL (3U << 8) + +#define MC_TXN_OVERRIDE_CONFIG_CGID_SO_DEV_ZERO (0U << 12) +#define MC_TXN_OVERRIDE_CONFIG_CGID_SO_DEV_CLIENT_AXI_ID (1U << 12) + +/******************************************************************************* + * Memory Controller transaction override config registers + ******************************************************************************/ +#define MC_TXN_OVERRIDE_CONFIG_HDAR 0x10a8U +#define MC_TXN_OVERRIDE_CONFIG_DLA1WRA 0x1624U +#define MC_TXN_OVERRIDE_CONFIG_PCIE1W 0x16dcU +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDC 0x1644U +#define MC_TXN_OVERRIDE_CONFIG_PTCR 0x1000U +#define MC_TXN_OVERRIDE_CONFIG_EQOSW 0x1478U +#define MC_TXN_OVERRIDE_CONFIG_MPCOREW 0x11c8U +#define MC_TXN_OVERRIDE_CONFIG_DLA1FALWRB 0x162cU +#define MC_TXN_OVERRIDE_CONFIG_AXISR 0x1460U +#define MC_TXN_OVERRIDE_CONFIG_PVA0WRB 0x1654U +#define MC_TXN_OVERRIDE_CONFIG_MIU6R 0x17f4U +#define MC_TXN_OVERRIDE_CONFIG_MIU5R 0x17e4U +#define MC_TXN_OVERRIDE_CONFIG_NVENCSRD1 0x1784U +#define MC_TXN_OVERRIDE_CONFIG_PCIE0R 0x16c4U +#define MC_TXN_OVERRIDE_CONFIG_EQOSR 0x1470U +#define MC_TXN_OVERRIDE_CONFIG_NVENCSRD 0x10e0U +#define MC_TXN_OVERRIDE_CONFIG_NVENC1SRD1 0x178cU +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDB1 0x1774U +#define MC_TXN_OVERRIDE_CONFIG_NVENC1SWR 0x16bcU +#define MC_TXN_OVERRIDE_CONFIG_VICSRD1 0x1510U +#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAR 0x14a8U +#define MC_TXN_OVERRIDE_CONFIG_VIW 0x1390U +#define MC_TXN_OVERRIDE_CONFIG_PCIE5R 0x1714U +#define MC_TXN_OVERRIDE_CONFIG_AXISW 0x1468U +#define MC_TXN_OVERRIDE_CONFIG_MIU6W 0x17fcU +#define MC_TXN_OVERRIDE_CONFIG_UFSHCR 0x1480U +#define MC_TXN_OVERRIDE_CONFIG_PCIE0R1 0x179cU +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDB1 0x1764U +#define MC_TXN_OVERRIDE_CONFIG_TSECSWR 0x12a8U +#define MC_TXN_OVERRIDE_CONFIG_MIU7R 0x1008U +#define MC_TXN_OVERRIDE_CONFIG_SATAR 0x10f8U +#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTW 0x1258U +#define MC_TXN_OVERRIDE_CONFIG_DLA0RDA 0x15f4U +#define MC_TXN_OVERRIDE_CONFIG_TSECSWRB 0x1438U +#define MC_TXN_OVERRIDE_CONFIG_NVDEC1SWR 0x17dcU +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDA1 0x176cU +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDB 0x166cU +#define MC_TXN_OVERRIDE_CONFIG_AONDMAW 0x14d0U +#define MC_TXN_OVERRIDE_CONFIG_AONW 0x14c0U +#define MC_TXN_OVERRIDE_CONFIG_ETRR 0x1420U +#define MC_TXN_OVERRIDE_CONFIG_PCIE2AW 0x16ecU +#define MC_TXN_OVERRIDE_CONFIG_PCIE1R 0x16d4U +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDC 0x1674U +#define MC_TXN_OVERRIDE_CONFIG_PVA0WRA 0x164cU +#define MC_TXN_OVERRIDE_CONFIG_TSECSRDB 0x1430U +#define MC_TXN_OVERRIDE_CONFIG_MIU1W 0x1548U +#define MC_TXN_OVERRIDE_CONFIG_PCIE0W 0x16ccU +#define MC_TXN_OVERRIDE_CONFIG_NVDEC1SRD 0x17ccU +#define MC_TXN_OVERRIDE_CONFIG_MIU7W 0x1010U +#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD1 0x1518U +#define MC_TXN_OVERRIDE_CONFIG_MIU3R 0x1580U +#define MC_TXN_OVERRIDE_CONFIG_MIU3W 0x158cU +#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTR 0x1250U +#define MC_TXN_OVERRIDE_CONFIG_SESRD 0x1400U +#define MC_TXN_OVERRIDE_CONFIG_SCER 0x14d8U +#define MC_TXN_OVERRIDE_CONFIG_MPCORER 0x1138U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCWA 0x1320U +#define MC_TXN_OVERRIDE_CONFIG_HDAW 0x11a8U +#define MC_TXN_OVERRIDE_CONFIG_NVDECSWR 0x13c8U +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDA 0x1634U +#define MC_TXN_OVERRIDE_CONFIG_AONDMAR 0x14c8U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAB 0x1338U +#define MC_TXN_OVERRIDE_CONFIG_ISPFALR 0x1228U +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDA1 0x175cU +#define MC_TXN_OVERRIDE_CONFIG_NVENC1SRD 0x16b4U +#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR1 0x1508U +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDA 0x1664U +#define MC_TXN_OVERRIDE_CONFIG_DLA0RDA1 0x174cU +#define MC_TXN_OVERRIDE_CONFIG_ISPWB 0x1238U +#define MC_TXN_OVERRIDE_CONFIG_APEW 0x13d8U +#define MC_TXN_OVERRIDE_CONFIG_AXIAPR 0x1410U +#define MC_TXN_OVERRIDE_CONFIG_PCIE2AR 0x16e4U +#define MC_TXN_OVERRIDE_CONFIG_ISPFALW 0x1724U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCR 0x1310U +#define MC_TXN_OVERRIDE_CONFIG_MIU2W 0x1578U +#define MC_TXN_OVERRIDE_CONFIG_RCER 0x1694U +#define MC_TXN_OVERRIDE_CONFIG_PCIE4W 0x170cU +#define MC_TXN_OVERRIDE_CONFIG_BPMPW 0x14a0U +#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR 0x1490U +#define MC_TXN_OVERRIDE_CONFIG_ISPRA 0x1220U +#define MC_TXN_OVERRIDE_CONFIG_NVJPGSWR 0x13f8U +#define MC_TXN_OVERRIDE_CONFIG_VICSRD 0x1360U +#define MC_TXN_OVERRIDE_CONFIG_NVDEC1SRD1 0x17d4U +#define MC_TXN_OVERRIDE_CONFIG_DLA1RDA 0x1614U +#define MC_TXN_OVERRIDE_CONFIG_SCEDMAW 0x14f0U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCW 0x1330U +#define MC_TXN_OVERRIDE_CONFIG_DLA1FALRDB 0x161cU +#define MC_TXN_OVERRIDE_CONFIG_APEDMAR 0x14f8U +#define MC_TXN_OVERRIDE_CONFIG_RCEW 0x169cU +#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAB 0x1318U +#define MC_TXN_OVERRIDE_CONFIG_DLA0WRA 0x1604U +#define MC_TXN_OVERRIDE_CONFIG_VIFALR 0x15e4U +#define MC_TXN_OVERRIDE_CONFIG_PCIE3R 0x16f4U +#define MC_TXN_OVERRIDE_CONFIG_MIU1R 0x1540U +#define MC_TXN_OVERRIDE_CONFIG_PCIE5W 0x171cU +#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVR 0x1260U +#define MC_TXN_OVERRIDE_CONFIG_MIU0W 0x1538U +#define MC_TXN_OVERRIDE_CONFIG_DLA0FALWRB 0x160cU +#define MC_TXN_OVERRIDE_CONFIG_VIFALW 0x15ecU +#define MC_TXN_OVERRIDE_CONFIG_DLA0FALRDB 0x15fcU +#define MC_TXN_OVERRIDE_CONFIG_PCIE3W 0x16fcU +#define MC_TXN_OVERRIDE_CONFIG_MIU0R 0x1530U +#define MC_TXN_OVERRIDE_CONFIG_PVA0WRC 0x165cU +#define MC_TXN_OVERRIDE_CONFIG_SCEDMAR 0x14e8U +#define MC_TXN_OVERRIDE_CONFIG_APEDMAW 0x1500U +#define MC_TXN_OVERRIDE_CONFIG_HOST1XDMAR 0x10b0U +#define MC_TXN_OVERRIDE_CONFIG_SESWR 0x1408U +#define MC_TXN_OVERRIDE_CONFIG_AXIAPW 0x1418U +#define MC_TXN_OVERRIDE_CONFIG_MIU4R 0x1594U +#define MC_TXN_OVERRIDE_CONFIG_MIU4W 0x159cU +#define MC_TXN_OVERRIDE_CONFIG_NVJPGSRD 0x13f0U +#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD 0x13c0U +#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAW 0x14b0U +#define MC_TXN_OVERRIDE_CONFIG_APER 0x13d0U +#define MC_TXN_OVERRIDE_CONFIG_DLA1RDA1 0x1754U +#define MC_TXN_OVERRIDE_CONFIG_PVA1WRB 0x1684U +#define MC_TXN_OVERRIDE_CONFIG_ISPWA 0x1230U +#define MC_TXN_OVERRIDE_CONFIG_PVA1WRC 0x168cU +#define MC_TXN_OVERRIDE_CONFIG_RCEDMAR 0x16a4U +#define MC_TXN_OVERRIDE_CONFIG_ISPRA1 0x1794U +#define MC_TXN_OVERRIDE_CONFIG_AONR 0x14b8U +#define MC_TXN_OVERRIDE_CONFIG_RCEDMAW 0x16acU +#define MC_TXN_OVERRIDE_CONFIG_UFSHCW 0x1488U +#define MC_TXN_OVERRIDE_CONFIG_ETRW 0x1428U +#define MC_TXN_OVERRIDE_CONFIG_SATAW 0x11e8U +#define MC_TXN_OVERRIDE_CONFIG_VICSWR 0x1368U +#define MC_TXN_OVERRIDE_CONFIG_NVENCSWR 0x1158U +#define MC_TXN_OVERRIDE_CONFIG_PCIE5R1 0x177cU +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDB 0x163cU +#define MC_TXN_OVERRIDE_CONFIG_SDMMCRA 0x1300U +#define MC_TXN_OVERRIDE_CONFIG_PVA1WRA 0x167cU +#define MC_TXN_OVERRIDE_CONFIG_MIU5W 0x17ecU +#define MC_TXN_OVERRIDE_CONFIG_BPMPR 0x1498U +#define MC_TXN_OVERRIDE_CONFIG_MIU2R 0x1570U +#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVW 0x1268U +#define MC_TXN_OVERRIDE_CONFIG_TSECSRD 0x12a0U +#define MC_TXN_OVERRIDE_CONFIG_PCIE4R 0x1704U +#define MC_TXN_OVERRIDE_CONFIG_SCEW 0x14e0U + +#define MC_TXN_OVERRIDE_CONFIG_AXID_OVERRIDE_CGID (1U << 0) +#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_OVERRIDE_SO_DEV (2U << 4) +#define MC_TXN_OVERRIDE_CONFIG_AXID_OVERRIDE_SO_DEV_CGID_SO_DEV_CLIENT (1U << 12) + +/******************************************************************************* + * Non-SO_DEV transactions override values for CGID_TAG bitfield for the + * MC_TXN_OVERRIDE_CONFIG_{module} registers + ******************************************************************************/ +#define MC_TXN_OVERRIDE_CGID_TAG_DEFAULT 0U +#define MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID 1U +#define MC_TXN_OVERRIDE_CGID_TAG_ZERO 2U +#define MC_TXN_OVERRIDE_CGID_TAG_ADR 3U +#define MC_TXN_OVERRIDE_CGID_TAG_MASK 3ULL + +/******************************************************************************* + * Memory Controller Reset Control registers + ******************************************************************************/ +#define MC_CLIENT_HOTRESET_CTRL0 0x200U +#define MC_CLIENT_HOTRESET_CTRL0_RESET_VAL 0U +#define MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB (1U << 0) +#define MC_CLIENT_HOTRESET_CTRL0_HC_FLUSH_ENB (1U << 6) +#define MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB (1U << 7) +#define MC_CLIENT_HOTRESET_CTRL0_ISP2_FLUSH_ENB (1U << 8) +#define MC_CLIENT_HOTRESET_CTRL0_MPCORE_FLUSH_ENB (1U << 9) +#define MC_CLIENT_HOTRESET_CTRL0_NVENC_FLUSH_ENB (1U << 11) +#define MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB (1U << 15) +#define MC_CLIENT_HOTRESET_CTRL0_VI_FLUSH_ENB (1U << 17) +#define MC_CLIENT_HOTRESET_CTRL0_VIC_FLUSH_ENB (1U << 18) +#define MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB (1U << 19) +#define MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB (1U << 20) +#define MC_CLIENT_HOTRESET_CTRL0_TSEC_FLUSH_ENB (1U << 22) +#define MC_CLIENT_HOTRESET_CTRL0_SDMMC1A_FLUSH_ENB (1U << 29) +#define MC_CLIENT_HOTRESET_CTRL0_SDMMC2A_FLUSH_ENB (1U << 30) +#define MC_CLIENT_HOTRESET_CTRL0_SDMMC3A_FLUSH_ENB (1U << 31) +#define MC_CLIENT_HOTRESET_STATUS0 0x204U +#define MC_CLIENT_HOTRESET_CTRL1 0x970U +#define MC_CLIENT_HOTRESET_CTRL1_RESET_VAL 0U +#define MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB (1U << 0) +#define MC_CLIENT_HOTRESET_CTRL1_GPU_FLUSH_ENB (1U << 2) +#define MC_CLIENT_HOTRESET_CTRL1_NVDEC_FLUSH_ENB (1U << 5) +#define MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB (1U << 6) +#define MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB (1U << 7) +#define MC_CLIENT_HOTRESET_CTRL1_NVJPG_FLUSH_ENB (1U << 8) +#define MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB (1U << 12) +#define MC_CLIENT_HOTRESET_CTRL1_TSECB_FLUSH_ENB (1U << 13) +#define MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB (1U << 17) +#define MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB (1U << 18) +#define MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB (1U << 19) +#define MC_CLIENT_HOTRESET_CTRL1_NVDISPLAY_FLUSH_ENB (1U << 20) +#define MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB (1U << 21) +#define MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB (1U << 22) +#define MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB (1U << 23) +#define MC_CLIENT_HOTRESET_CTRL1_VIFAL_FLUSH_ENB (1U << 26) +#define MC_CLIENT_HOTRESET_CTRL1_RCE_FLUSH_ENB (1U << 31) +#define MC_CLIENT_HOTRESET_STATUS1 0x974U +#define MC_CLIENT_HOTRESET_CTRL2 0x97cU +#define MC_CLIENT_HOTRESET_CTRL2_RESET_VAL 0U +#define MC_CLIENT_HOTRESET_CTRL2_RCEDMA_FLUSH_ENB (1U << 0) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE_FLUSH_ENB (1U << 2) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE5A_FLUSH_ENB (1U << 4) +#define MC_CLIENT_HOTRESET_CTRL2_AONDMA_FLUSH_ENB (1U << 9) +#define MC_CLIENT_HOTRESET_CTRL2_BPMPDMA_FLUSH_ENB (1U << 10) +#define MC_CLIENT_HOTRESET_CTRL2_SCEDMA_FLUSH_ENB (1U << 11) +#define MC_CLIENT_HOTRESET_CTRL2_APEDMA_FLUSH_ENB (1U << 14) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE3A_FLUSH_ENB (1U << 16) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE3_FLUSH_ENB (1U << 17) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE0A_FLUSH_ENB (1U << 22) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE0A2_FLUSH_ENB (1U << 23) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE4A_FLUSH_ENB (1U << 25) +#define MC_CLIENT_HOTRESET_STATUS2 0x1898U + +#define MC_COALESCE_CTRL 0x2930U +#define MC_COALESCE_CTRL_COALESCER_ENABLE (1U << 31) +#define MC_COALESCE_CONFIG_6_0 0x294cU +#define MC_COALESCE_CONFIG_6_0_PVA0RDC_COALESCER_ENABLED (1U << 8) +#define MC_COALESCE_CONFIG_6_0_PVA1RDC_COALESCER_ENABLED (1U << 14) + +/******************************************************************************* + * Tegra TSA Controller constants + ******************************************************************************/ +#define TEGRA_TSA_BASE U(0x02000000) + +#define TSA_CONFIG_STATIC0_CSR_RESET_R 0x20000000U +#define TSA_CONFIG_STATIC0_CSW_RESET_W 0x20001000U +#define TSA_CONFIG_STATIC0_CSW_RESET_SO_DEV 0x20001000U + +#define TSA_CONFIG_STATIC0_CSW_PCIE1W 0x1004U +#define TSA_CONFIG_STATIC0_CSW_PCIE2AW 0x1008U +#define TSA_CONFIG_STATIC0_CSW_PCIE3W 0x100cU +#define TSA_CONFIG_STATIC0_CSW_PCIE4W 0x1028U +#define TSA_CONFIG_STATIC0_CSW_XUSB_DEVW 0x2004U +#define TSA_CONFIG_STATIC0_CSR_SATAR 0x2010U +#define TSA_CONFIG_STATIC0_CSW_SATAW 0x2014U +#define TSA_CONFIG_STATIC0_CSW_PCIE0W 0x2020U +#define TSA_CONFIG_STATIC0_CSW_XUSB_HOSTW 0x202cU +#define TSA_CONFIG_STATIC0_CSW_NVENC1SWR 0x3004U +#define TSA_CONFIG_STATIC0_CSW_NVENCSWR 0x3010U +#define TSA_CONFIG_STATIC0_CSW_NVDEC1SWR 0x4004U +#define TSA_CONFIG_STATIC0_CSR_ISPFALR 0x4010U +#define TSA_CONFIG_STATIC0_CSW_ISPWA 0x4014U +#define TSA_CONFIG_STATIC0_CSW_ISPWB 0x4018U +#define TSA_CONFIG_STATIC0_CSW_ISPFALW 0x401cU +#define TSA_CONFIG_STATIC0_CSW_NVDECSWR 0x5004U +#define TSA_CONFIG_STATIC0_CSR_EQOSR 0x5010U +#define TSA_CONFIG_STATIC0_CSW_EQOSW 0x5014U +#define TSA_CONFIG_STATIC0_CSR_SDMMCRAB 0x5020U +#define TSA_CONFIG_STATIC0_CSW_SDMMCWAB 0x5024U +#define TSA_CONFIG_STATIC0_CSW_UFSHCW 0x6004U +#define TSA_CONFIG_STATIC0_CSR_SDMMCR 0x6010U +#define TSA_CONFIG_STATIC0_CSR_SDMMCRA 0x6014U +#define TSA_CONFIG_STATIC0_CSW_SDMMCW 0x6018U +#define TSA_CONFIG_STATIC0_CSW_SDMMCWA 0x601cU +#define TSA_CONFIG_STATIC0_CSR_RCER 0x6030U +#define TSA_CONFIG_STATIC0_CSR_RCEDMAR 0x6034U +#define TSA_CONFIG_STATIC0_CSW_RCEW 0x6038U +#define TSA_CONFIG_STATIC0_CSW_RCEDMAW 0x603cU +#define TSA_CONFIG_STATIC0_CSR_SCER 0x6050U +#define TSA_CONFIG_STATIC0_CSR_SCEDMAR 0x6054U +#define TSA_CONFIG_STATIC0_CSW_SCEW 0x6058U +#define TSA_CONFIG_STATIC0_CSW_SCEDMAW 0x605cU +#define TSA_CONFIG_STATIC0_CSR_AXIAPR 0x7004U +#define TSA_CONFIG_STATIC0_CSR_ETRR 0x7008U +#define TSA_CONFIG_STATIC0_CSR_HOST1XDMAR 0x700cU +#define TSA_CONFIG_STATIC0_CSW_AXIAPW 0x7010U +#define TSA_CONFIG_STATIC0_CSW_ETRW 0x7014U +#define TSA_CONFIG_STATIC0_CSR_NVJPGSRD 0x8004U +#define TSA_CONFIG_STATIC0_CSW_NVJPGSWR 0x8008U +#define TSA_CONFIG_STATIC0_CSR_AXISR 0x8014U +#define TSA_CONFIG_STATIC0_CSW_AXISW 0x8018U +#define TSA_CONFIG_STATIC0_CSR_BPMPR 0x9004U +#define TSA_CONFIG_STATIC0_CSR_BPMPDMAR 0x9008U +#define TSA_CONFIG_STATIC0_CSW_BPMPW 0x900cU +#define TSA_CONFIG_STATIC0_CSW_BPMPDMAW 0x9010U +#define TSA_CONFIG_STATIC0_CSR_SESRD 0x9024U +#define TSA_CONFIG_STATIC0_CSR_TSECSRD 0x9028U +#define TSA_CONFIG_STATIC0_CSR_TSECSRDB 0x902cU +#define TSA_CONFIG_STATIC0_CSW_SESWR 0x9030U +#define TSA_CONFIG_STATIC0_CSW_TSECSWR 0x9034U +#define TSA_CONFIG_STATIC0_CSW_TSECSWRB 0x9038U +#define TSA_CONFIG_STATIC0_CSW_PCIE5W 0xb004U +#define TSA_CONFIG_STATIC0_CSW_VICSWR 0xc004U +#define TSA_CONFIG_STATIC0_CSR_APER 0xd004U +#define TSA_CONFIG_STATIC0_CSR_APEDMAR 0xd008U +#define TSA_CONFIG_STATIC0_CSW_APEW 0xd00cU +#define TSA_CONFIG_STATIC0_CSW_APEDMAW 0xd010U +#define TSA_CONFIG_STATIC0_CSR_HDAR 0xf004U +#define TSA_CONFIG_STATIC0_CSW_HDAW 0xf008U +#define TSA_CONFIG_STATIC0_CSR_NVDISPLAYR 0xf014U +#define TSA_CONFIG_STATIC0_CSR_VIFALR 0x10004U +#define TSA_CONFIG_STATIC0_CSW_VIW 0x10008U +#define TSA_CONFIG_STATIC0_CSW_VIFALW 0x1000cU +#define TSA_CONFIG_STATIC0_CSR_AONR 0x12004U +#define TSA_CONFIG_STATIC0_CSR_AONDMAR 0x12008U +#define TSA_CONFIG_STATIC0_CSW_AONW 0x1200cU +#define TSA_CONFIG_STATIC0_CSW_AONDMAW 0x12010U +#define TSA_CONFIG_STATIC0_CSR_PCIE1R 0x14004U +#define TSA_CONFIG_STATIC0_CSR_PCIE2AR 0x14008U +#define TSA_CONFIG_STATIC0_CSR_PCIE3R 0x1400cU +#define TSA_CONFIG_STATIC0_CSR_PCIE4R 0x14028U +#define TSA_CONFIG_STATIC0_CSR_XUSB_DEVR 0x15004U +#define TSA_CONFIG_STATIC0_CSR_XUSB_HOSTR 0x15010U +#define TSA_CONFIG_STATIC0_CSR_UFSHCR 0x16004U +#define TSA_CONFIG_STATIC0_CSW_DLA1WRA 0x18004U +#define TSA_CONFIG_STATIC0_CSR_DLA1FALRDB 0x18010U +#define TSA_CONFIG_STATIC0_CSW_DLA1FALWRB 0x18014U +#define TSA_CONFIG_STATIC0_CSW_DLA0WRA 0x19004U +#define TSA_CONFIG_STATIC0_CSR_DLA0FALRDB 0x19010U +#define TSA_CONFIG_STATIC0_CSW_DLA0FALWRB 0x19014U +#define TSA_CONFIG_STATIC0_CSR_PVA1RDC 0x1a004U +#define TSA_CONFIG_STATIC0_CSW_PVA1WRC 0x1a008U +#define TSA_CONFIG_STATIC0_CSW_PVA1WRA 0x1a014U +#define TSA_CONFIG_STATIC0_CSW_PVA1WRB 0x1a020U +#define TSA_CONFIG_STATIC0_CSW_PVA0WRB 0x1b004U +#define TSA_CONFIG_STATIC0_CSR_PVA0RDC 0x1b010U +#define TSA_CONFIG_STATIC0_CSW_PVA0WRC 0x1b014U +#define TSA_CONFIG_STATIC0_CSW_PVA0WRA 0x1b020U +#define TSA_CONFIG_STATIC0_CSR_NVENC1SRD 0x1d004U +#define TSA_CONFIG_STATIC0_CSR_NVENCSRD 0x1d010U +#define TSA_CONFIG_STATIC0_CSR_NVDEC1SRD 0x1e004U +#define TSA_CONFIG_STATIC0_CSR_ISPRA 0x1e010U +#define TSA_CONFIG_STATIC0_CSR_NVDECSRD 0x1f004U +#define TSA_CONFIG_STATIC0_CSR_PCIE0R 0x21004U +#define TSA_CONFIG_STATIC0_CSR_PCIE5R 0x23004U +#define TSA_CONFIG_STATIC0_CSR_VICSRD 0x24004U +#define TSA_CONFIG_STATIC0_CSR_DLA1RDA 0x26004U +#define TSA_CONFIG_STATIC0_CSR_DLA0RDA 0x27004U +#define TSA_CONFIG_STATIC0_CSR_PVA1RDA 0x28004U +#define TSA_CONFIG_STATIC0_CSR_PVA1RDB 0x28010U +#define TSA_CONFIG_STATIC0_CSR_PVA0RDB 0x29004U +#define TSA_CONFIG_STATIC0_CSR_PVA0RDA 0x29010U + +#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK (ULL(0x3) << 11) +#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU (ULL(0) << 11) + +#define TSA_CONFIG_CSW_SO_DEV_HUBID_MASK (ULL(0x3) << 15) +#define TSA_CONFIG_CSW_SO_DEV_HUB2 (ULL(2) << 15) + +#define REORDER_DEPTH_LIMIT 16 +#define TSA_CONFIG_CSW_REORDER_DEPTH_LIMIT_MASK (ULL(0x7FF) << 21) +#define reorder_depth_limit(limit) (ULL(limit) << 21) + +#define tsa_read_32(client) \ + mmio_read_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client) + +#define mc_set_tsa_hub2(val, client) \ + { \ + mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \ + ((val & ~TSA_CONFIG_CSW_SO_DEV_HUBID_MASK) | \ + TSA_CONFIG_CSW_SO_DEV_HUB2)); \ + } + +#define mc_set_tsa_depth_limit(limit, client) \ + { \ + uint32_t val = mmio_read_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client); \ + mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \ + ((val & ~TSA_CONFIG_CSW_REORDER_DEPTH_LIMIT_MASK) | \ + reorder_depth_limit(limit))); \ + } +#endif /* __TEGRA_MC_DEF_H__ */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h b/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h new file mode 100644 index 0000000..2cf375a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_PLATFORM_H +#define TEGRA_PLATFORM_H + +#include +#include +#include + +/******************************************************************************* + * Tegra major, minor version helper macros + ******************************************************************************/ +#define MAJOR_VERSION_SHIFT U(0x4) +#define MAJOR_VERSION_MASK U(0xF) +#define MINOR_VERSION_SHIFT U(0x10) +#define MINOR_VERSION_MASK U(0xF) +#define CHIP_ID_SHIFT U(8) +#define CHIP_ID_MASK U(0xFF) +#define PRE_SI_PLATFORM_SHIFT U(0x14) +#define PRE_SI_PLATFORM_MASK U(0xF) + +/******************************************************************************* + * Tegra chip ID values + ******************************************************************************/ +#define TEGRA_CHIPID_TEGRA13 U(0x13) +#define TEGRA_CHIPID_TEGRA21 U(0x21) +#define TEGRA_CHIPID_TEGRA18 U(0x18) +#define TEGRA_CHIPID_TEGRA19 U(0x19) +#define TEGRA_CHIPID_TEGRA23 U(0x23) + +/******************************************************************************* + * JEDEC Standard Manufacturer's Identification Code and Bank ID + ******************************************************************************/ +#define JEDEC_NVIDIA_MFID U(0x6B) +#define JEDEC_NVIDIA_BKID U(3) + +#ifndef __ASSEMBLER__ + +/* + * Tegra chip ID major/minor identifiers + */ +uint32_t tegra_get_chipid_major(void); +uint32_t tegra_get_chipid_minor(void); + +/* + * Tegra chip ID identifiers + */ +bool tegra_chipid_is_t186(void); +bool tegra_chipid_is_t210(void); +bool tegra_chipid_is_t210_b01(void); +bool tegra_chipid_is_t194(void); +bool tegra_chipid_is_t239(void); + +/* + * Tegra platform identifiers + */ +bool tegra_platform_is_silicon(void); +bool tegra_platform_is_qt(void); +bool tegra_platform_is_emulation(void); +bool tegra_platform_is_linsim(void); +bool tegra_platform_is_fpga(void); +bool tegra_platform_is_unit_fpga(void); +bool tegra_platform_is_virt_dev_kit(void); +bool tegra_platform_is_vsp(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* TEGRA_PLATFORM_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h new file mode 100644 index 0000000..2fe4ffd --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_PRIVATE_H +#define TEGRA_PRIVATE_H + +#include +#include + +#include +#include +#include +#include +#include + +#include + +/******************************************************************************* + * Implementation defined ACTLR_EL1 bit definitions + ******************************************************************************/ +#define ACTLR_EL1_PMSTATE_MASK (ULL(0xF) << 0) + +/******************************************************************************* + * Implementation defined ACTLR_EL2 bit definitions + ******************************************************************************/ +#define ACTLR_EL2_PMSTATE_MASK (ULL(0xF) << 0) + +/******************************************************************************* + * Struct for parameters received from BL2 + ******************************************************************************/ +typedef struct plat_params_from_bl2 { + /* TZ memory size */ + uint64_t tzdram_size; + /* TZ memory base */ + uint64_t tzdram_base; + /* UART port ID */ + int32_t uart_id; + /* L2 ECC parity protection disable flag */ + int32_t l2_ecc_parity_prot_dis; + /* SHMEM base address for storing the boot logs */ + uint64_t boot_profiler_shmem_base; + /* System Suspend Entry Firmware size */ + uint64_t sc7entry_fw_size; + /* System Suspend Entry Firmware base address */ + uint64_t sc7entry_fw_base; + /* Enable dual execution */ + uint8_t enable_ccplex_lock_step; +} plat_params_from_bl2_t; + +/******************************************************************************* + * Helper function to access l2ctlr_el1 register on Cortex-A57 CPUs + ******************************************************************************/ +DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, CORTEX_A57_L2CTLR_EL1) + +/******************************************************************************* + * Struct describing parameters passed to bl31 + ******************************************************************************/ +struct tegra_bl31_params { + 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; +}; + +/******************************************************************************* +* To suppress Coverity MISRA C-2012 Rule 2.2 violations +*******************************************************************************/ +#define UNUSED_FUNC_NOP() asm("nop") + +/* Declarations for plat_psci_handlers.c */ +int32_t tegra_soc_validate_power_state(uint32_t power_state, + psci_power_state_t *req_state); + +/* Declarations for plat_setup.c */ +const mmap_region_t *plat_get_mmio_map(void); +void plat_enable_console(int32_t id); +void plat_gic_setup(void); +struct tegra_bl31_params *plat_get_bl31_params(void); +plat_params_from_bl2_t *plat_get_bl31_plat_params(void); +void plat_early_platform_setup(void); +void plat_late_platform_setup(void); +void plat_relocate_bl32_image(const image_info_t *bl32_img_info); +bool plat_supports_system_suspend(void); +void plat_runtime_setup(void); + +/* Declarations for plat_secondary.c */ +bool plat_is_secondary_present(u_register_t mpidr); +void plat_secondary_setup(void); +int32_t plat_lock_cpu_vectors(void); + +/* Declarations for tegra_fiq_glue.c */ +void tegra_fiq_handler_setup(void); +int32_t tegra_fiq_get_intr_context(void); +void tegra_fiq_set_ns_entrypoint(uint64_t entrypoint); + +/* Declarations for tegra_security.c */ +void tegra_security_setup(void); +void tegra_security_setup_videomem(uintptr_t base, uint64_t size); + +/* Declarations for tegra_pm.c */ +void tegra_pm_system_suspend_entry(void); +void tegra_pm_system_suspend_exit(void); +int32_t tegra_system_suspended(void); +int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state); +int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state); +int32_t tegra_soc_pwr_domain_on(u_register_t mpidr); +int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state); +int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state); +int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state); +int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state); +int32_t tegra_soc_prepare_system_reset(void); +__dead2 void tegra_soc_prepare_system_off(void); +plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, + const plat_local_state_t *states, + uint32_t ncpu); + +/* Declarations for tegraXXX_pm.c */ +int tegra_prepare_cpu_suspend(unsigned int id, unsigned int afflvl); +int tegra_prepare_cpu_on_finish(unsigned long mpidr); + +/* Declarations for tegra_bl31_setup.c */ +plat_params_from_bl2_t *bl31_get_plat_params(void); +int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes); + +/* Declarations for tegra_delay_timer.c */ +void tegra_delay_timer_init(void); + +void tegra_secure_entrypoint(void); + +/* Declarations for tegra_sip_calls.c */ +uintptr_t tegra_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); +int plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + const void *cookie, + void *handle, + uint64_t flags); + +#if RAS_EXTENSION +void tegra194_ras_enable(void); +void tegra194_ras_corrected_err_clear(uint64_t *cookie); +#endif + +#endif /* TEGRA_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c b/arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c new file mode 100644 index 0000000..dd76a4e --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/******************************************************************************* + * The profiler stores the timestamps captured during cold boot to the shared + * memory for the non-secure world. The non-secure world driver parses the + * shared memory block and writes the contents to a file on the device, which + * can be later extracted for analysis. + * + * Profiler memory map + * + * TOP --------------------------- --- + * Trusted OS timestamps 3KB + * --------------------------- --- + * Trusted Firmware timestamps 1KB + * BASE --------------------------- --- + * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static uint64_t shmem_base_addr; + +#define MAX_PROFILER_RECORDS U(16) +#define TAG_LEN_BYTES U(56) + +/******************************************************************************* + * Profiler entry format + ******************************************************************************/ +typedef struct { + /* text explaining the timestamp location in code */ + uint8_t tag[TAG_LEN_BYTES]; + /* timestamp value */ + uint64_t timestamp; +} profiler_rec_t; + +static profiler_rec_t *head, *cur, *tail; +static uint32_t tmr; +static bool is_shmem_buf_mapped; + +/******************************************************************************* + * Initialise the profiling library + ******************************************************************************/ +void boot_profiler_init(uint64_t shmem_base, uint32_t tmr_base) +{ + uint64_t shmem_end_base; + + assert(shmem_base != ULL(0)); + assert(tmr_base != U(0)); + + /* store the buffer address */ + shmem_base_addr = shmem_base; + + /* calculate the base address of the last record */ + shmem_end_base = shmem_base + (sizeof(profiler_rec_t) * + (MAX_PROFILER_RECORDS - U(1))); + + /* calculate the head, tail and cur values */ + head = (profiler_rec_t *)shmem_base; + tail = (profiler_rec_t *)shmem_end_base; + cur = head; + + /* timer used to get the current timestamp */ + tmr = tmr_base; +} + +/******************************************************************************* + * Add tag and timestamp to profiler + ******************************************************************************/ +void boot_profiler_add_record(const char *str) +{ + unsigned int len; + + /* calculate the length of the tag */ + if (((unsigned int)strlen(str) + U(1)) > TAG_LEN_BYTES) { + len = TAG_LEN_BYTES; + } else { + len = (unsigned int)strlen(str) + U(1); + } + + if (head != NULL) { + + /* + * The profiler runs with/without MMU enabled. Check + * if MMU is enabled and memmap the shmem buffer, in + * case it is. + */ + if ((!is_shmem_buf_mapped) && + ((read_sctlr_el3() & SCTLR_M_BIT) != U(0))) { + + (void)mmap_add_dynamic_region(shmem_base_addr, + shmem_base_addr, + PROFILER_SIZE_BYTES, + (MT_NS | MT_RW | MT_EXECUTE_NEVER)); + + is_shmem_buf_mapped = true; + } + + /* write the tag and timestamp to buffer */ + (void)snprintf((char *)cur->tag, len, "%s", str); + cur->timestamp = mmio_read_32(tmr); + + /* start from head if we reached the end */ + if (cur == tail) { + cur = head; + } else { + cur++; + } + } +} + +/******************************************************************************* + * Deinint the profiler + ******************************************************************************/ +void boot_profiler_deinit(void) +{ + if (shmem_base_addr != ULL(0)) { + + /* clean up resources */ + cur = NULL; + head = NULL; + tail = NULL; + + /* flush the shmem for it to be visible to the NS world */ + flush_dcache_range(shmem_base_addr, PROFILER_SIZE_BYTES); + + /* unmap the shmem buffer */ + if (is_shmem_buf_mapped) { + (void)mmap_remove_dynamic_region(shmem_base_addr, + PROFILER_SIZE_BYTES); + } + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/platform.mk b/arm-trusted-firmware/plat/nvidia/tegra/platform.mk new file mode 100644 index 0000000..804c20f --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/platform.mk @@ -0,0 +1,111 @@ +# +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +SOC_DIR := plat/nvidia/tegra/soc/${TARGET_SOC} + +# dump the state on crash console +CRASH_REPORTING := 1 +$(eval $(call add_define,CRASH_REPORTING)) + +# enable assert() for release/debug builds +ENABLE_ASSERTIONS := 1 +PLAT_LOG_LEVEL_ASSERT := 50 +$(eval $(call add_define,PLAT_LOG_LEVEL_ASSERT)) + +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 +$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) + +# Enable exception handling at EL3 +EL3_EXCEPTION_HANDLING := 1 +GICV2_G0_FOR_EL3 := 1 + +# Enable PSCI v1.0 extended state ID format +PSCI_EXTENDED_STATE_ID := 1 + +# code and read-only data should be put on separate memory pages +SEPARATE_CODE_AND_RODATA := 1 + +# do not use coherent memory +USE_COHERENT_MEM := 0 + +# enable D-cache early during CPU warmboot +WARMBOOT_ENABLE_DCACHE_EARLY := 1 + +# remove the standard libc +OVERRIDE_LIBC := 1 + +# Flag to enable WDT FIQ interrupt handling for Tegra SoCs +# prior to Tegra186 +ENABLE_TEGRA_WDT_LEGACY_FIQ_HANDLING ?= 0 + +# Flag to allow relocation of BL32 image to TZDRAM during boot +RELOCATE_BL32_IMAGE ?= 0 + +# Do not trap accesses to Error System registers from EL1 or EL2. +TEGRA_TRAP_LOWER_EL_ERR_ACCESS ?= 0 + +# Enable stack protection +ENABLE_STACK_PROTECTOR := strong + +# Enable SDEI +SDEI_SUPPORT := 1 + +# modify BUILD_PLAT to point to SoC specific build directory +BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_SOC}/${BUILD_TYPE} + +include ${SOC_DIR}/platform_${TARGET_SOC}.mk + +# SPM dispatcher +ifeq (${SPD},spmd) +# include device tree helper library +include lib/libfdt/libfdt.mk +# sources to support spmd +BL31_SOURCES += plat/common/plat_spmd_manifest.c \ + common/fdt_wrappers.c \ + ${LIBFDT_SRCS} +endif + +$(eval $(call add_define,ENABLE_TEGRA_WDT_LEGACY_FIQ_HANDLING)) +$(eval $(call add_define,RELOCATE_BL32_IMAGE)) +$(eval $(call add_define,TEGRA_TRAP_LOWER_EL_ERR_ACCESS)) + +# platform cflags (enable signed comparisons, disable stdlib) +TF_CFLAGS += -nostdlib + +# override with necessary libc files for the Tegra platform +override LIBC_SRCS := $(addprefix lib/libc/, \ + aarch64/setjmp.S \ + assert.c \ + memchr.c \ + memcmp.c \ + memcpy.c \ + memmove.c \ + memset.c \ + printf.c \ + putchar.c \ + strncmp.c \ + strrchr.c \ + strlen.c \ + snprintf.c) + +INCLUDES += -Iinclude/lib/libc \ + -Iinclude/lib/libc/$(ARCH) \ + +ifneq ($(findstring armlink,$(notdir $(LD))),) +# o suppress warnings for section mismatches, undefined symbols +# o use only those libraries that are specified in the input file +# list to resolve references +# o create a static callgraph of functions +# o resolve undefined symbols to el3_panic +# o include only required sections +TF_LDFLAGS += --diag_suppress=L6314,L6332 --no_scanlib --callgraph +TF_LDFLAGS += --keep="*(__pubsub*)" --keep="*(rt_svc_descs*)" --keep="*(*cpu_ops)" +ifeq (${ENABLE_PMF},1) +TF_LDFLAGS += --keep="*(*pmf_svc_descs*)" +endif +endif diff --git a/arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat b/arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat new file mode 100644 index 0000000..2d6d2b3 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat @@ -0,0 +1,284 @@ +#! armclang -E -x c + +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#define PAGE_SIZE (1024 * 4) + +LR_START BL31_BASE +{ + __BL31_START__ +0 FIXED EMPTY 0 + { + /* placeholder */ + } + + /* BL31_BASE address must be aligned on a page boundary. */ + ScatterAssert((ImageBase(__BL31_START__) AND 0xFFF) == 0) +} + +LR_TEXT BL31_BASE +{ + __TEXT__ +0 FIXED + { + *(:gdef:bl31_entrypoint, +FIRST) + *(.text*) + *(.vectors) + .ANY1(+RO-CODE) + } + + __TEXT_EPILOGUE__ AlignExpr(+0, PAGE_SIZE) FIXED EMPTY 0 + { + /* section delimiter */ + } +} + +LR_RO_DATA +0 +{ + __RODATA__ AlignExpr(ImageLimit(LR_TEXT), 0) FIXED + { + *(.rodata*) + .ANY2(+RO-DATA) + } + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + __RT_SVC_DESCS__ AlignExpr(ImageLimit(__RODATA__), 8) FIXED + { + *(rt_svc_descs) + } + +#if ENABLE_PMF + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + __PMF_SVC_DESCS__ AlignExpr(ImageLimit(__RT_SVC_DESCS__), 8) FIXED + { + *(pmf_svc_descs) + } +#endif /* ENABLE_PMF */ + + /* + * Ensure 8-byte alignment for cpu_ops so that its fields are also + * aligned. + */ + __CPU_OPS__ AlignExpr(+0, 8) FIXED + { + *(cpu_ops) + } + + /* + * 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 8-byte alignment. + */ + __GOT__ AlignExpr(ImageLimit(__CPU_OPS__), 8) FIXED + { + *(.got) + } + + /* Place pubsub sections for events */ + __PUBSUB_EVENTS__ AlignExpr(+0, 8) EMPTY 0 + { + /* placeholder */ + } + +#include + + __RODATA_EPILOGUE__ AlignExpr(+0, PAGE_SIZE) FIXED EMPTY 0 + { + /* section delimiter */ + } +} + + /* cpu_ops must always be defined */ + ScatterAssert(ImageLength(__CPU_OPS__) > 0) + +#if SPM_MM +LR_SPM +0 +{ + /* + * Exception vectors of the SPM shim layer. They must be aligned to a 2K + * address, but we need to place them in a separate page so that we can set + * individual permissions to them, so the actual alignment needed is 4K. + * + * There's no need to include this into the RO section of BL31 because it + * doesn't need to be accessed by BL31. + */ + __SPM_SHIM_EXCEPTIONS__ AlignExpr(ImageLimit(LR_RO_DATA), PAGE_SIZE) FIXED + { + *(.spm_shim_exceptions) + } + + __SPM_SHIM_EXCEPTIONS_EPILOGUE__ AlignExpr(ImageLimit(__SPM_SHIM_EXCEPTIONS__), PAGE_SIZE) FIXED + { + /* placeholder */ + } +} +#endif + +LR_RW_DATA +0 +{ + __DATA__ AlignExpr(+0, 16) FIXED + { + *(.data*) + *(.constdata) + *(locale$$data) + } +} + +LR_RELA +0 +{ + /* + * .rela.dyn needs to come after .data for the read-elf utility to parse + * this section correctly. Ensure 8-byte alignment so that the fields of + * RELA data structure are aligned. + */ + __RELA__ AlignExpr(ImageLimit(LR_RW_DATA), 8) FIXED + { + *(.rela.dyn) + } +} + +#ifdef BL31_PROGBITS_LIMIT + /* BL31 progbits has exceeded its limit. */ + ScatterAssert(ImageLimit(LR_RELA) <= BL31_PROGBITS_LIMIT) +#endif + +LR_STACKS +0 +{ + __STACKS__ AlignExpr(+0, 64) FIXED + { + *(tzfw_normal_stacks) + } +} + +#define __BAKERY_LOCK_SIZE__ (ImageLimit(__BAKERY_LOCKS_EPILOGUE__) - \ + ImageBase(__BAKERY_LOCKS__)) +#define BAKERY_LOCK_SIZE (__BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1)) +#define __PMF_TIMESTAMP_SIZE__ (ImageLimit(__PMF_TIMESTAMP__) - \ + ImageBase(__PMF_TIMESTAMP__)) +#define PER_CPU_TIMESTAMP_SIZE (__PMF_TIMESTAMP_SIZE__ * (PLATFORM_CORE_COUNT - 1)) + +LR_BSS +0 +{ + __BSS__ AlignExpr(ImageLimit(LR_STACKS), 256) FIXED + { + *(.bss*) + *(COMDAT) + } + +#if !USE_COHERENT_MEM + /* + * 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 + */ + __BAKERY_LOCKS__ AlignExpr(ImageLimit(__BSS__), CACHE_WRITEBACK_GRANULE) FIXED + { + *(bakery_lock) + } + + __BAKERY_LOCKS_EPILOGUE__ AlignExpr(ImageLimit(__BAKERY_LOCKS__), CACHE_WRITEBACK_GRANULE) FIXED EMPTY 0 + { + /* section delimiter */ + } + + __PER_CPU_BAKERY_LOCKS__ ImageLimit(__BAKERY_LOCKS_EPILOGUE__) FIXED FILL 0 BAKERY_LOCK_SIZE + { + /* padded memory section to store per cpu bakery locks */ + } + +#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE + /* PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements */ + ScatterAssert(__PER_CPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE) +#endif +#endif + +#if ENABLE_PMF + /* + * 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 CPU's is allocated by the + * linker script + */ + __PMF_TIMESTAMP__ AlignExpr(+0, CACHE_WRITEBACK_GRANULE) FIXED EMPTY CACHE_WRITEBACK_GRANULE + { + /* store timestamps in this carved out memory */ + } + + __PMF_TIMESTAMP_EPILOGUE__ AlignExpr(ImageLimit(__PMF_TIMESTAMP__), CACHE_WRITEBACK_GRANULE) FIXED EMPTY 0 + { + /* + * placeholder to make __PMF_TIMESTAMP_START__ end on a + * CACHE_WRITEBACK_GRANULE boundary + */ + } + + __PER_CPU_TIMESTAMPS__ +0 FIXED FILL 0 PER_CPU_TIMESTAMP_SIZE + { + /* padded memory section to store per cpu timestamps */ + } +#endif /* ENABLE_PMF */ +} + +LR_XLAT_TABLE +0 +{ + xlat_table +0 FIXED + { + *(xlat_table) + } +} + +#if USE_COHERENT_MEM +LR_COHERENT_RAM +0 +{ + /* + * 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__ AlignExpr(+0, PAGE_SIZE) FIXED + { + /* + * Bakery locks are stored in coherent memory + * + * Each lock's data is contiguous and fully allocated by the compiler + */ + *(bakery_lock) + *(tzfw_coherent_mem) + } + + __COHERENT_RAM_EPILOGUE_UNALIGNED__ +0 FIXED EMPTY 0 + { + /* section delimiter */ + } + + /* + * 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. + */ + __COHERENT_RAM_EPILOGUE__ AlignExpr(ImageLimit(__COHERENT_RAM_START__), PAGE_SIZE) FIXED EMPTY 0 + { + /* section delimiter */ + } +} +#endif + +LR_END +0 +{ + __BL31_END__ +0 FIXED EMPTY 0 + { + /* placeholder */ + } + + /* BL31 image has exceeded its limit. */ + ScatterAssert(ImageLimit(__BL31_END__) <= BL31_LIMIT) +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h new file mode 100644 index 0000000..203f61a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCE_PRIVATE_H +#define MCE_PRIVATE_H + +#include + +#include + +/******************************************************************************* + * Macros to prepare CSTATE info request + ******************************************************************************/ +/* Description of the parameters for UPDATE_CSTATE_INFO request */ +#define CLUSTER_CSTATE_MASK ULL(0x7) +#define CLUSTER_CSTATE_SHIFT U(0) +#define CLUSTER_CSTATE_UPDATE_BIT (ULL(1) << 7) +#define CCPLEX_CSTATE_MASK ULL(0x3) +#define CCPLEX_CSTATE_SHIFT ULL(8) +#define CCPLEX_CSTATE_UPDATE_BIT (ULL(1) << 15) +#define SYSTEM_CSTATE_MASK ULL(0xF) +#define SYSTEM_CSTATE_SHIFT ULL(16) +#define SYSTEM_CSTATE_FORCE_UPDATE_SHIFT ULL(22) +#define SYSTEM_CSTATE_FORCE_UPDATE_BIT (ULL(1) << 22) +#define SYSTEM_CSTATE_UPDATE_BIT (ULL(1) << 23) +#define CSTATE_WAKE_MASK_UPDATE_BIT (ULL(1) << 31) +#define CSTATE_WAKE_MASK_SHIFT ULL(32) +#define CSTATE_WAKE_MASK_CLEAR U(0xFFFFFFFF) + +/******************************************************************************* + * Auto-CC3 control macros + ******************************************************************************/ +#define MCE_AUTO_CC3_FREQ_MASK U(0x1FF) +#define MCE_AUTO_CC3_FREQ_SHIFT U(0) +#define MCE_AUTO_CC3_VTG_MASK U(0x7F) +#define MCE_AUTO_CC3_VTG_SHIFT U(16) +#define MCE_AUTO_CC3_ENABLE_BIT (U(1) << 31) + +/******************************************************************************* + * Macros for the 'IS_SC7_ALLOWED' command + ******************************************************************************/ +#define MCE_SC7_ALLOWED_MASK U(0x7) +#define MCE_SC7_WAKE_TIME_SHIFT U(32) + +/******************************************************************************* + * Macros for 'read/write ctats' commands + ******************************************************************************/ +#define MCE_CSTATE_STATS_TYPE_SHIFT ULL(32) +#define MCE_CSTATE_WRITE_DATA_LO_MASK U(0xF) + +/******************************************************************************* + * Macros for 'update crossover threshold' command + ******************************************************************************/ +#define MCE_CROSSOVER_THRESHOLD_TIME_SHIFT U(32) + +/******************************************************************************* + * MCA argument macros + ******************************************************************************/ +#define MCA_ARG_ERROR_MASK U(0xFF) +#define MCA_ARG_FINISH_SHIFT U(24) +#define MCA_ARG_FINISH_MASK U(0xFF) + +/******************************************************************************* + * Uncore PERFMON ARI macros + ******************************************************************************/ +#define UNCORE_PERFMON_CMD_READ U(0) +#define UNCORE_PERFMON_CMD_WRITE U(1) + +#define UNCORE_PERFMON_CMD_MASK U(0xFF) +#define UNCORE_PERFMON_UNIT_GRP_MASK U(0xF) +#define UNCORE_PERFMON_SELECTOR_MASK U(0xF) +#define UNCORE_PERFMON_REG_MASK U(0xFF) +#define UNCORE_PERFMON_CTR_MASK U(0xFF) +#define UNCORE_PERFMON_RESP_STATUS_MASK U(0xFF) + +/******************************************************************************* + * Structure populated by arch specific code to export routines which perform + * common low level MCE functions + ******************************************************************************/ +typedef struct arch_mce_ops { + /* + * This ARI request sets up the MCE to start execution on assertion + * of STANDBYWFI, update the core power state and expected wake time, + * then determine the proper power state to enter. + */ + int32_t (*enter_cstate)(uint32_t ari_base, uint32_t state, + uint32_t wake_time); + /* + * This ARI request allows updating of the CLUSTER_CSTATE, + * CCPLEX_CSTATE, and SYSTEM_CSTATE register values. + */ + int32_t (*update_cstate_info)(uint32_t ari_base, + uint32_t cluster, + uint32_t ccplex, + uint32_t system, + uint8_t sys_state_force, + uint32_t wake_mask, + uint8_t update_wake_mask); + /* + * This ARI request allows updating of power state crossover + * threshold times. An index value specifies which crossover + * state is being updated. + */ + int32_t (*update_crossover_time)(uint32_t ari_base, + uint32_t type, + uint32_t time); + /* + * This ARI request allows read access to statistical information + * related to power states. + */ + uint64_t (*read_cstate_stats)(uint32_t ari_base, + uint32_t state); + /* + * This ARI request allows write access to statistical information + * related to power states. + */ + int32_t (*write_cstate_stats)(uint32_t ari_base, + uint32_t state, + uint32_t stats); + /* + * This ARI request allows the CPU to understand the features + * supported by the MCE firmware. + */ + uint64_t (*call_enum_misc)(uint32_t ari_base, uint32_t cmd, + uint32_t data); + /* + * This ARI request allows querying the CCPLEX to determine if + * the CCx state is allowed given a target core C-state and wake + * time. If the CCx state is allowed, the response indicates CCx + * must be entered. If the CCx state is not allowed, the response + * indicates CC6/CC7 can't be entered + */ + int32_t (*is_ccx_allowed)(uint32_t ari_base, uint32_t state, + uint32_t wake_time); + /* + * This ARI request allows querying the CCPLEX to determine if + * the SC7 state is allowed given a target core C-state and wake + * time. If the SC7 state is allowed, all cores but the associated + * core are offlined (WAKE_EVENTS are set to 0) and the response + * indicates SC7 must be entered. If the SC7 state is not allowed, + * the response indicates SC7 can't be entered + */ + int32_t (*is_sc7_allowed)(uint32_t ari_base, uint32_t state, + uint32_t wake_time); + /* + * This ARI request allows a core to bring another offlined core + * back online to the C0 state. Note that a core is offlined by + * entering a C-state where the WAKE_MASK is all 0. + */ + int32_t (*online_core)(uint32_t ari_base, uint32_t cpuid); + /* + * This ARI request allows the CPU to enable/disable Auto-CC3 idle + * state. + */ + int32_t (*cc3_ctrl)(uint32_t ari_base, + uint32_t freq, + uint32_t volt, + uint8_t enable); + /* + * This ARI request allows updating the reset vector register for + * D15 and A57 CPUs. + */ + int32_t (*update_reset_vector)(uint32_t ari_base); + /* + * This ARI request instructs the ROC to flush A57 data caches in + * order to maintain coherency with the Denver cluster. + */ + int32_t (*roc_flush_cache)(uint32_t ari_base); + /* + * This ARI request instructs the ROC to flush A57 data caches along + * with the caches covering ARM code in order to maintain coherency + * with the Denver cluster. + */ + int32_t (*roc_flush_cache_trbits)(uint32_t ari_base); + /* + * This ARI request instructs the ROC to clean A57 data caches along + * with the caches covering ARM code in order to maintain coherency + * with the Denver cluster. + */ + int32_t (*roc_clean_cache)(uint32_t ari_base); + /* + * This ARI request reads/writes the Machine Check Arch. (MCA) + * registers. + */ + uint64_t (*read_write_mca)(uint32_t ari_base, + uint64_t cmd, + uint64_t *data); + /* + * Some MC GSC (General Security Carveout) register values are + * expected to be changed by TrustZone secure ARM code after boot. + * Since there is no hardware mechanism for the CCPLEX to know + * that an MC GSC register has changed to allow it to update its + * own internal GSC register, there needs to be a mechanism that + * can be used by ARM code to cause the CCPLEX to update its GSC + * register value. This ARI request allows updating the GSC register + * value for a certain carveout in the CCPLEX. + */ + int32_t (*update_ccplex_gsc)(uint32_t ari_base, uint32_t gsc_idx); + /* + * This ARI request instructs the CCPLEX to either shutdown or + * reset the entire system + */ + void (*enter_ccplex_state)(uint32_t ari_base, uint32_t state_idx); + /* + * This ARI request reads/writes data from/to Uncore PERFMON + * registers + */ + int32_t (*read_write_uncore_perfmon)(uint32_t ari_base, + uint64_t req, uint64_t *data); + /* + * This ARI implements ARI_MISC_CCPLEX commands. This can be + * used to enable/disable coresight clock gating. + */ + void (*misc_ccplex)(uint32_t ari_base, uint32_t index, + uint32_t value); +} arch_mce_ops_t; + +/* declarations for ARI/NVG handler functions */ +int32_t ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, + uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, + uint8_t update_wake_mask); +int32_t ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time); +uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state); +int32_t ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats); +uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data); +int32_t ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int32_t ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int32_t ari_online_core(uint32_t ari_base, uint32_t core); +int32_t ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable); +int32_t ari_reset_vector_update(uint32_t ari_base); +int32_t ari_roc_flush_cache_trbits(uint32_t ari_base); +int32_t ari_roc_flush_cache(uint32_t ari_base); +int32_t ari_roc_clean_cache(uint32_t ari_base); +uint64_t ari_read_write_mca(uint32_t ari_base, uint64_t cmd, uint64_t *data); +int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx); +void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx); +int32_t ari_read_write_uncore_perfmon(uint32_t ari_base, + uint64_t req, uint64_t *data); +void ari_misc_ccplex(uint32_t ari_base, uint32_t index, uint32_t value); + +int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int32_t nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, + uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, + uint8_t update_wake_mask); +int32_t nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time); +uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state); +int32_t nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats); +int32_t nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int32_t nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int32_t nvg_online_core(uint32_t ari_base, uint32_t core); +int32_t nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable); + +extern void nvg_set_request_data(uint64_t req, uint64_t data); +extern void nvg_set_request(uint64_t req); +extern uint64_t nvg_get_result(void); +#endif /* MCE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h new file mode 100644 index 0000000..ecfb3f4 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef T18X_ARI_H +#define T18X_ARI_H + +/* + * ---------------------------------------------------------------------------- + * t18x_ari.h + * + * Global ARI definitions. + * ---------------------------------------------------------------------------- + */ + +enum { + TEGRA_ARI_VERSION_MAJOR = 3U, + TEGRA_ARI_VERSION_MINOR = 1U, +}; + +typedef enum { + /* indexes below get the core lock */ + TEGRA_ARI_MISC = 0U, + /* index 1 is deprecated */ + /* index 2 is deprecated */ + /* index 3 is deprecated */ + TEGRA_ARI_ONLINE_CORE = 4U, + + /* indexes below need cluster lock */ + TEGRA_ARI_MISC_CLUSTER = 41U, + TEGRA_ARI_IS_CCX_ALLOWED = 42U, + TEGRA_ARI_CC3_CTRL = 43U, + + /* indexes below need ccplex lock */ + TEGRA_ARI_ENTER_CSTATE = 80U, + TEGRA_ARI_UPDATE_CSTATE_INFO = 81U, + TEGRA_ARI_IS_SC7_ALLOWED = 82U, + /* index 83 is deprecated */ + TEGRA_ARI_PERFMON = 84U, + TEGRA_ARI_UPDATE_CCPLEX_GSC = 85U, + /* index 86 is depracated */ + /* index 87 is deprecated */ + TEGRA_ARI_ROC_FLUSH_CACHE_ONLY = 88U, + TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS = 89U, + TEGRA_ARI_MISC_CCPLEX = 90U, + TEGRA_ARI_MCA = 91U, + TEGRA_ARI_UPDATE_CROSSOVER = 92U, + TEGRA_ARI_CSTATE_STATS = 93U, + TEGRA_ARI_WRITE_CSTATE_STATS = 94U, + TEGRA_ARI_COPY_MISCREG_AA64_RST = 95U, + TEGRA_ARI_ROC_CLEAN_CACHE_ONLY = 96U, +} tegra_ari_req_id_t; + +typedef enum { + TEGRA_ARI_MISC_ECHO = 0U, + TEGRA_ARI_MISC_VERSION = 1U, + TEGRA_ARI_MISC_FEATURE_LEAF_0 = 2U, +} tegra_ari_misc_index_t; + +typedef enum { + TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF = 0U, + TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT = 1U, + TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL = 2U, + TEGRA_ARI_MISC_CCPLEX_EDBGREQ = 3U, +} tegra_ari_misc_ccplex_index_t; + +typedef enum { + TEGRA_ARI_CORE_C0 = 0U, + TEGRA_ARI_CORE_C1 = 1U, + TEGRA_ARI_CORE_C6 = 6U, + TEGRA_ARI_CORE_C7 = 7U, + TEGRA_ARI_CORE_WARMRSTREQ = 8U, +} tegra_ari_core_sleep_state_t; + +typedef enum { + TEGRA_ARI_CLUSTER_CC0 = 0U, + TEGRA_ARI_CLUSTER_CC1 = 1U, + TEGRA_ARI_CLUSTER_CC6 = 6U, + TEGRA_ARI_CLUSTER_CC7 = 7U, +} tegra_ari_cluster_sleep_state_t; + +typedef enum { + TEGRA_ARI_CCPLEX_CCP0 = 0U, + TEGRA_ARI_CCPLEX_CCP1 = 1U, + TEGRA_ARI_CCPLEX_CCP3 = 3U, /* obsoleted */ +} tegra_ari_ccplex_sleep_state_t; + +typedef enum { + TEGRA_ARI_SYSTEM_SC0 = 0U, + TEGRA_ARI_SYSTEM_SC1 = 1U, /* obsoleted */ + TEGRA_ARI_SYSTEM_SC2 = 2U, /* obsoleted */ + TEGRA_ARI_SYSTEM_SC3 = 3U, /* obsoleted */ + TEGRA_ARI_SYSTEM_SC4 = 4U, /* obsoleted */ + TEGRA_ARI_SYSTEM_SC7 = 7U, + TEGRA_ARI_SYSTEM_SC8 = 8U, +} tegra_ari_system_sleep_state_t; + +typedef enum { + TEGRA_ARI_CROSSOVER_C1_C6 = 0U, + TEGRA_ARI_CROSSOVER_CC1_CC6 = 1U, + TEGRA_ARI_CROSSOVER_CC1_CC7 = 2U, + TEGRA_ARI_CROSSOVER_CCP1_CCP3 = 3U, /* obsoleted */ + TEGRA_ARI_CROSSOVER_CCP3_SC2 = 4U, /* obsoleted */ + TEGRA_ARI_CROSSOVER_CCP3_SC3 = 5U, /* obsoleted */ + TEGRA_ARI_CROSSOVER_CCP3_SC4 = 6U, /* obsoleted */ + TEGRA_ARI_CROSSOVER_CCP3_SC7 = 7U, /* obsoleted */ + TEGRA_ARI_CROSSOVER_SC0_SC7 = 7U, + TEGRA_ARI_CROSSOVER_CCP3_SC1 = 8U, /* obsoleted */ +} tegra_ari_crossover_index_t; + +typedef enum { + TEGRA_ARI_CSTATE_STATS_CLEAR = 0U, + TEGRA_ARI_CSTATE_STATS_SC7_ENTRIES = 1U, + TEGRA_ARI_CSTATE_STATS_SC4_ENTRIES, /* obsoleted */ + TEGRA_ARI_CSTATE_STATS_SC3_ENTRIES, /* obsoleted */ + TEGRA_ARI_CSTATE_STATS_SC2_ENTRIES, /* obsoleted */ + TEGRA_ARI_CSTATE_STATS_CCP3_ENTRIES, /* obsoleted */ + TEGRA_ARI_CSTATE_STATS_A57_CC6_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_CC7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_CC6_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_CC7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_0_C6_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_1_C6_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_0_C7_ENTRIES = 14U, + TEGRA_ARI_CSTATE_STATS_D15_1_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_0_C7_ENTRIES = 18U, + TEGRA_ARI_CSTATE_STATS_A57_1_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_2_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_3_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 26U, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3, +} tegra_ari_cstate_stats_index_t; + +typedef enum { + TEGRA_ARI_GSC_ALL = 0U, + TEGRA_ARI_GSC_BPMP = 6U, + TEGRA_ARI_GSC_APE = 7U, + TEGRA_ARI_GSC_SPE = 8U, + TEGRA_ARI_GSC_SCE = 9U, + TEGRA_ARI_GSC_APR = 10U, + TEGRA_ARI_GSC_TZRAM = 11U, + TEGRA_ARI_GSC_SE = 12U, + TEGRA_ARI_GSC_BPMP_TO_SPE = 16U, + TEGRA_ARI_GSC_SPE_TO_BPMP = 17U, + TEGRA_ARI_GSC_CPU_TZ_TO_BPMP = 18U, + TEGRA_ARI_GSC_BPMP_TO_CPU_TZ = 19U, + TEGRA_ARI_GSC_CPU_NS_TO_BPMP = 20U, + TEGRA_ARI_GSC_BPMP_TO_CPU_NS = 21U, + TEGRA_ARI_GSC_IPC_SE_SPE_SCE_BPMP = 22U, + TEGRA_ARI_GSC_SC7_RESUME_FW = 23U, + TEGRA_ARI_GSC_TZ_DRAM_IDX = 34U, + TEGRA_ARI_GSC_VPR_IDX = 35U, +} tegra_ari_gsc_index_t; + +/* This macro will produce enums for __name##_LSB, __name##_MSB and __name##_MSK */ +#define TEGRA_ARI_ENUM_MASK_LSB_MSB(__name, __lsb, __msb) __name##_LSB = __lsb, __name##_MSB = __msb + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE, 0U, 2U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE_PRESENT, 7U, 7U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE, 8U, 9U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE_PRESENT, 15U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE, 16U, 19U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__IGNORE_CROSSOVERS, 22U, 22U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE_PRESENT, 23U, 23U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__WAKE_MASK_PRESENT, 31U, 31U), +} tegra_ari_update_cstate_info_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL__EN, 0U, 0U), +} tegra_ari_misc_ccplex_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_FREQ, 0U, 8U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_VOLT, 16U, 23U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__ENABLE, 31U, 31U), +} tegra_ari_cc3_ctrl_bitmasks_t; + +typedef enum { + TEGRA_ARI_MCA_NOP = 0U, + TEGRA_ARI_MCA_READ_SERR = 1U, + TEGRA_ARI_MCA_WRITE_SERR = 2U, + TEGRA_ARI_MCA_CLEAR_SERR = 4U, + TEGRA_ARI_MCA_REPORT_SERR = 5U, + TEGRA_ARI_MCA_READ_INTSTS = 6U, + TEGRA_ARI_MCA_WRITE_INTSTS = 7U, + TEGRA_ARI_MCA_READ_PREBOOT_SERR = 8U, +} tegra_ari_mca_commands_t; + +typedef enum { + TEGRA_ARI_MCA_RD_WR_DPMU = 0U, + TEGRA_ARI_MCA_RD_WR_IOB = 1U, + TEGRA_ARI_MCA_RD_WR_MCB = 2U, + TEGRA_ARI_MCA_RD_WR_CCE = 3U, + TEGRA_ARI_MCA_RD_WR_CQX = 4U, + TEGRA_ARI_MCA_RD_WR_CTU = 5U, + TEGRA_ARI_MCA_RD_WR_JSR_MTS = 7U, + TEGRA_ARI_MCA_RD_BANK_INFO = 0x0fU, + TEGRA_ARI_MCA_RD_BANK_TEMPLATE = 0x10U, + TEGRA_ARI_MCA_RD_WR_SECURE_ACCESS_REGISTER = 0x11U, + TEGRA_ARI_MCA_RD_WR_GLOBAL_CONFIG_REGISTER = 0x12U, +} tegra_ari_mca_rd_wr_indexes_t; + +typedef enum { + TEGRA_ARI_MCA_RD_WR_ASERRX_CTRL = 0U, + TEGRA_ARI_MCA_RD_WR_ASERRX_STATUS = 1U, + TEGRA_ARI_MCA_RD_WR_ASERRX_ADDR = 2U, + TEGRA_ARI_MCA_RD_WR_ASERRX_MISC1 = 3U, + TEGRA_ARI_MCA_RD_WR_ASERRX_MISC2 = 4U, +} tegra_ari_mca_read_asserx_subindexes_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_SETTING_ENABLES_NS_PERMITTED, 0U, 0U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_READING_STATUS_NS_PERMITTED, 1U, 1U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_PENDING_MCA_ERRORS_NS_PERMITTED, 2U, 2U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_CLEARING_MCA_INTERRUPTS_NS_PERMITTED, 3U, 3U), +} tegra_ari_mca_secure_register_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_SERR_ERR_CODE, 0U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM_ERR, 16U, 16U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_CRAB_ERR, 17U, 17U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_RD_WR_N, 18U, 18U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UCODE_ERR, 19U, 19U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM, 20U, 23U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_AV, 58U, 58U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_MV, 59U, 59U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_EN, 60U, 60U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UC, 61U, 61U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_OVF, 62U, 62U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_VAL, 63U, 63U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_ADDR, 0U, 41U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_UCODE_ERRCD, 42U, 52U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_PWM_ERR, 0U, 0U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_CRAB_ERR, 1U, 1U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_UCODE_ERR, 3U, 3U), +} tegra_ari_mca_aserr0_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_SERR_ERR_CODE, 0U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MSI_ERR, 16U, 16U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_IHI_ERR, 17U, 17U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CRI_ERR, 18U, 18U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MMCRAB_ERR, 19U, 19U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CSI_ERR, 20U, 20U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RD_WR_N, 21U, 21U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_REQ_ERRT, 22U, 23U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RESP_ERRT, 24U, 25U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AV, 58U, 58U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MV, 59U, 59U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_EN, 60U, 60U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_UC, 61U, 61U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_OVF, 62U, 62U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_VAL, 63U, 63U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AXI_ID, 0U, 7U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_ID, 8U, 27U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CID, 28U, 31U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CMD, 32U, 35U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MSI_ERR, 0U, 0U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_IHI_ERR, 1U, 1U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CRI_ERR, 2U, 2U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MMCRAB_ERR, 3U, 3U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CSI_ERR, 4U, 4U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_MISC_ADDR, 0U, 41U), +} tegra_ari_mca_aserr1_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SERR_ERR_CODE, 0U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MC_ERR, 16U, 16U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SYSRAM_ERR, 17U, 17U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_CLIENT_ID, 18U, 19U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_AV, 58U, 58U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MV, 59U, 59U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_EN, 60U, 60U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_UC, 61U, 61U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_OVF, 62U, 62U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_VAL, 63U, 63U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ID, 0U, 17U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_CMD, 18U, 21U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ADDR, 22U, 53U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_CTRL_EN_MC_ERR, 0U, 0U), +} tegra_ari_mca_aserr2_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_SERR_ERR_CODE, 0U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_TO_ERR, 16U, 16U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_STAT_ERR, 17U, 17U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_DST_ERR, 18U, 18U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UNC_ERR, 19U, 19U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MH_ERR, 20U, 20U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PERR, 21U, 21U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PSN_ERR, 22U, 22U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_AV, 58U, 58U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MV, 59U, 59U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_EN, 60U, 60U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UC, 61U, 61U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_OVF, 62U, 62U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_VAL, 63U, 63U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_CMD, 0U, 5U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_ADDR, 6U, 47U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TO, 0U, 0U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_DIV4, 1U, 1U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TLIMIT, 2U, 11U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_PSN_ERR_CORR_MSK, 12U, 25U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_MORE_INFO, 0U, 17U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TO_INFO, 18U, 43U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_SRC, 44U, 45U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TID, 46U, 52U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_TO_ERR, 0U, 0U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_STAT_ERR, 1U, 1U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_DST_ERR, 2U, 2U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_UNC_ERR, 3U, 3U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_MH_ERR, 4U, 4U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PERR, 5U, 5U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PSN_ERR, 6U, 19U), +} tegra_ari_mca_aserr3_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SERR_ERR_CODE, 0U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SRC_ERR, 16U, 16U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_DST_ERR, 17U, 17U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_REQ_ERR, 18U, 18U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_RSP_ERR, 19U, 19U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_AV, 58U, 58U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_MV, 59U, 59U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_EN, 60U, 60U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_UC, 61U, 61U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_OVF, 62U, 62U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_VAL, 63U, 63U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_CTRL_EN_CPE_ERR, 0U, 0U), +} tegra_ari_mca_aserr4_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_SERR_ERR_CODE, 0U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_CTUPAR, 16U, 16U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MULTI, 17U, 17U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_AV, 58U, 58U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MV, 59U, 59U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_EN, 60U, 60U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_UC, 61U, 61U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_OVF, 62U, 62U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_VAL, 63U, 63U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_SRC, 0U, 7U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ID, 8U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_DATA, 16U, 26U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_CMD, 32U, 35U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ADDR, 36U, 45U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_CTRL_EN_CTUPAR, 0U, 0U), +} tegra_ari_mca_aserr5_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_SERR_ERR_CODE, 0U, 15U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_AV, 58U, 58U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_MV, 59U, 59U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_EN, 60U, 60U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_UC, 61U, 61U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_OVF, 62U, 62U), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_VAL, 63U, 63U), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_ADDR_TBD_INFO, 0U, 63U), +} tegra_ari_mca_serr1_bitmasks_t; + +#undef TEGRA_ARI_ENUM_MASK_LSB_MSB + +typedef enum { + TEGRA_NVG_CHANNEL_PMIC = 0U, + TEGRA_NVG_CHANNEL_POWER_PERF = 1U, + TEGRA_NVG_CHANNEL_POWER_MODES = 2U, + TEGRA_NVG_CHANNEL_WAKE_TIME = 3U, + TEGRA_NVG_CHANNEL_CSTATE_INFO = 4U, + TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 = 5U, + TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC6 = 6U, + TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC7 = 7U, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP1_CCP3 = 8U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC2 = 9U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC3 = 10U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC4 = 11U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC7 = 12U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CROSSOVER_SC0_SC7 = 12U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR = 13U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC7_ENTRIES = 14U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC4_ENTRIES = 15U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC3_ENTRIES = 16U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC2_ENTRIES = 17U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_CCP3_ENTRIES = 18U, /* obsoleted */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC6_ENTRIES = 19U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC7_ENTRIES = 20U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC6_ENTRIES = 21U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC7_ENTRIES = 22U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C6_ENTRIES = 23U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C6_ENTRIES = 24U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C6_ENTRIES = 25U, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C6_ENTRIES = 26U, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C7_ENTRIES = 27U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C7_ENTRIES = 28U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C7_ENTRIES = 29U, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C7_ENTRIES = 30U, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_0_C7_ENTRIES = 31U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_1_C7_ENTRIES = 32U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_2_C7_ENTRIES = 33U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_3_C7_ENTRIES = 34U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0 = 35U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1 = 36U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_2 = 37U, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_3 = 38U, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 39U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1 = 40U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2 = 41U, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3 = 42U, + TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED = 43U, + TEGRA_NVG_CHANNEL_ONLINE_CORE = 44U, + TEGRA_NVG_CHANNEL_CC3_CTRL = 45U, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC1 = 46U, /* obsoleted */ + TEGRA_NVG_CHANNEL_LAST_INDEX, +} tegra_nvg_channel_id_t; + +#endif /* T18X_ARI_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S new file mode 100644 index 0000000..e3591ce --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl nvg_set_request_data + .globl nvg_set_request + .globl nvg_get_result + +/* void nvg_set_request_data(uint64_t req, uint64_t data) */ +func nvg_set_request_data + msr s3_0_c15_c1_2, x0 + msr s3_0_c15_c1_3, x1 + ret +endfunc nvg_set_request_data + +/* void nvg_set_request(uint64_t req) */ +func nvg_set_request + msr s3_0_c15_c1_2, x0 + ret +endfunc nvg_set_request + +/* uint64_t nvg_get_result(void) */ +func nvg_get_result + mrs x0, s3_0_c15_c1_3 + ret +endfunc nvg_get_result diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c new file mode 100644 index 0000000..a57bc11 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c @@ -0,0 +1,564 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/******************************************************************************* + * Register offsets for ARI request/results + ******************************************************************************/ +#define ARI_REQUEST 0x0U +#define ARI_REQUEST_EVENT_MASK 0x4U +#define ARI_STATUS 0x8U +#define ARI_REQUEST_DATA_LO 0xCU +#define ARI_REQUEST_DATA_HI 0x10U +#define ARI_RESPONSE_DATA_LO 0x14U +#define ARI_RESPONSE_DATA_HI 0x18U + +/* Status values for the current request */ +#define ARI_REQ_PENDING 1U +#define ARI_REQ_ONGOING 3U +#define ARI_REQUEST_VALID_BIT (1U << 8) +#define ARI_EVT_MASK_STANDBYWFI_BIT (1U << 7) + +/* default timeout (us) to wait for ARI completion */ +#define ARI_MAX_RETRY_COUNT U(2000000) + +/******************************************************************************* + * ARI helper functions + ******************************************************************************/ +static inline uint32_t ari_read_32(uint32_t ari_base, uint32_t reg) +{ + return mmio_read_32((uint64_t)ari_base + (uint64_t)reg); +} + +static inline void ari_write_32(uint32_t ari_base, uint32_t val, uint32_t reg) +{ + mmio_write_32((uint64_t)ari_base + (uint64_t)reg, val); +} + +static inline uint32_t ari_get_request_low(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_REQUEST_DATA_LO); +} + +static inline uint32_t ari_get_request_high(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_REQUEST_DATA_HI); +} + +static inline uint32_t ari_get_response_low(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_RESPONSE_DATA_LO); +} + +static inline uint32_t ari_get_response_high(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_RESPONSE_DATA_HI); +} + +static inline void ari_clobber_response(uint32_t ari_base) +{ + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO); + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI); +} + +static int32_t ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req, + uint32_t lo, uint32_t hi) +{ + uint32_t retries = (uint32_t)ARI_MAX_RETRY_COUNT; + uint32_t status; + int32_t ret = 0; + + /* program the request, event_mask, hi and lo registers */ + ari_write_32(ari_base, lo, ARI_REQUEST_DATA_LO); + ari_write_32(ari_base, hi, ARI_REQUEST_DATA_HI); + ari_write_32(ari_base, evt_mask, ARI_REQUEST_EVENT_MASK); + ari_write_32(ari_base, req | ARI_REQUEST_VALID_BIT, ARI_REQUEST); + + /* + * For commands that have an event trigger, we should bypass + * ARI_STATUS polling, since MCE is waiting for SW to trigger + * the event. + */ + if (evt_mask != 0U) { + ret = 0; + } else { + /* For shutdown/reboot commands, we dont have to check for timeouts */ + if ((req == TEGRA_ARI_MISC_CCPLEX) && + ((lo == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) || + (lo == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT))) { + ret = 0; + } else { + /* + * Wait for the command response for not more than the timeout + */ + while (retries != 0U) { + + /* read the command status */ + status = ari_read_32(ari_base, ARI_STATUS); + if ((status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) == 0U) { + break; + } + + /* delay 1 us */ + udelay(1); + + /* decrement the retry count */ + retries--; + } + + /* assert if the command timed out */ + if (retries == 0U) { + ERROR("ARI request timed out: req %d on CPU %d\n", + req, plat_my_core_pos()); + assert(retries != 0U); + } + } + } + + return ret; +} + +int32_t ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + int32_t ret = 0; + + /* check for allowed power state */ + if ((state != TEGRA_ARI_CORE_C0) && + (state != TEGRA_ARI_CORE_C1) && + (state != TEGRA_ARI_CORE_C6) && + (state != TEGRA_ARI_CORE_C7)) { + ERROR("%s: unknown cstate (%d)\n", __func__, state); + ret = EINVAL; + } else { + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* Enter the cstate, to be woken up after wake_time (TSC ticks) */ + ret = ari_request_wait(ari_base, ARI_EVT_MASK_STANDBYWFI_BIT, + (uint32_t)TEGRA_ARI_ENTER_CSTATE, state, wake_time); + } + + return ret; +} + +int32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, + uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, + uint8_t update_wake_mask) +{ + uint64_t val = 0U; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* update CLUSTER_CSTATE? */ + if (cluster != 0U) { + val |= (cluster & CLUSTER_CSTATE_MASK) | + CLUSTER_CSTATE_UPDATE_BIT; + } + + /* update CCPLEX_CSTATE? */ + if (ccplex != 0U) { + val |= ((ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) | + CCPLEX_CSTATE_UPDATE_BIT; + } + + /* update SYSTEM_CSTATE? */ + if (system != 0U) { + val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + (((uint64_t)sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | + SYSTEM_CSTATE_UPDATE_BIT); + } + + /* update wake mask value? */ + if (update_wake_mask != 0U) { + val |= CSTATE_WAKE_MASK_UPDATE_BIT; + } + + /* set the updated cstate info */ + return ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_UPDATE_CSTATE_INFO, + (uint32_t)val, wake_mask); +} + +int32_t ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) +{ + int32_t ret = 0; + + /* sanity check crossover type */ + if ((type == TEGRA_ARI_CROSSOVER_C1_C6) || + (type > TEGRA_ARI_CROSSOVER_CCP3_SC1)) { + ret = EINVAL; + } else { + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* update crossover threshold time */ + ret = ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_UPDATE_CROSSOVER, type, time); + } + + return ret; +} + +uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state) +{ + int32_t ret; + uint64_t result; + + /* sanity check crossover type */ + if (state == 0U) { + result = EINVAL; + } else { + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_CSTATE_STATS, state, 0U); + if (ret != 0) { + result = EINVAL; + } else { + result = (uint64_t)ari_get_response_low(ari_base); + } + } + return result; +} + +int32_t ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* write the cstate stats */ + return ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_WRITE_CSTATE_STATS, + state, stats); +} + +uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data) +{ + uint64_t resp; + int32_t ret; + uint32_t local_data = data; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* ARI_REQUEST_DATA_HI is reserved for commands other than 'ECHO' */ + if (cmd != TEGRA_ARI_MISC_ECHO) { + local_data = 0U; + } + + ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_MISC, cmd, local_data); + if (ret != 0) { + resp = (uint64_t)ret; + } else { + /* get the command response */ + resp = ari_get_response_low(ari_base); + resp |= ((uint64_t)ari_get_response_high(ari_base) << 32); + } + + return resp; +} + +int32_t ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + int32_t ret; + uint32_t result; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_IS_CCX_ALLOWED, + state & 0x7U, wake_time); + if (ret != 0) { + ERROR("%s: failed (%d)\n", __func__, ret); + result = 0U; + } else { + result = ari_get_response_low(ari_base) & 0x1U; + } + + /* 1 = CCx allowed, 0 = CCx not allowed */ + return (int32_t)result; +} + +int32_t ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + int32_t ret, result; + + /* check for allowed power state */ + if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) && + (state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) { + ERROR("%s: unknown cstate (%d)\n", __func__, state); + result = EINVAL; + } else { + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_IS_SC7_ALLOWED, state, wake_time); + if (ret != 0) { + ERROR("%s: failed (%d)\n", __func__, ret); + result = 0; + } else { + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + result = (ari_get_response_low(ari_base) != 0U) ? 1 : 0; + } + } + + return result; +} + +int32_t ari_online_core(uint32_t ari_base, uint32_t core) +{ + uint64_t cpu = read_mpidr() & (MPIDR_CPU_MASK); + uint64_t cluster = (read_mpidr() & (MPIDR_CLUSTER_MASK)) >> + (MPIDR_AFFINITY_BITS); + uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + int32_t ret; + + /* construct the current CPU # */ + cpu |= (cluster << 2); + + /* sanity check target core id */ + if ((core >= MCE_CORE_ID_MAX) || (cpu == (uint64_t)core)) { + ERROR("%s: unsupported core id (%d)\n", __func__, core); + ret = EINVAL; + } else { + /* + * The Denver cluster has 2 CPUs only - 0, 1. + */ + if ((impl == DENVER_IMPL) && ((core == 2U) || (core == 3U))) { + ERROR("%s: unknown core id (%d)\n", __func__, core); + ret = EINVAL; + } else { + /* clean the previous response state */ + ari_clobber_response(ari_base); + ret = ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_ONLINE_CORE, core, 0U); + } + } + + return ret; +} + +int32_t ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) +{ + uint32_t val; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* + * If the enable bit is cleared, Auto-CC3 will be disabled by setting + * the SW visible voltage/frequency request registers for all non + * floorswept cores valid independent of StandbyWFI and disabling + * the IDLE voltage/frequency request register. If set, Auto-CC3 + * will be enabled by setting the ARM SW visible voltage/frequency + * request registers for all non floorswept cores to be enabled by + * StandbyWFI or the equivalent signal, and always keeping the IDLE + * voltage/frequency request register enabled. + */ + val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\ + ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\ + ((enable != 0U) ? MCE_AUTO_CC3_ENABLE_BIT : 0U)); + + return ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_CC3_CTRL, val, 0U); +} + +int32_t ari_reset_vector_update(uint32_t ari_base) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* + * Need to program the CPU reset vector one time during cold boot + * and SC7 exit + */ + (void)ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_COPY_MISCREG_AA64_RST, 0U, 0U); + + return 0; +} + +int32_t ari_roc_flush_cache_trbits(uint32_t ari_base) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS, 0U, 0U); +} + +int32_t ari_roc_flush_cache(uint32_t ari_base) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_ROC_FLUSH_CACHE_ONLY, 0U, 0U); +} + +int32_t ari_roc_clean_cache(uint32_t ari_base) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_ROC_CLEAN_CACHE_ONLY, 0U, 0U); +} + +uint64_t ari_read_write_mca(uint32_t ari_base, uint64_t cmd, uint64_t *data) +{ + uint64_t mca_arg_data, result = 0; + uint32_t resp_lo, resp_hi; + uint32_t mca_arg_err, mca_arg_finish; + int32_t ret; + + /* Set data (write) */ + mca_arg_data = (data != NULL) ? *data : 0ULL; + + /* Set command */ + ari_write_32(ari_base, (uint32_t)cmd, ARI_RESPONSE_DATA_LO); + ari_write_32(ari_base, (uint32_t)(cmd >> 32U), ARI_RESPONSE_DATA_HI); + + ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_MCA, + (uint32_t)mca_arg_data, + (uint32_t)(mca_arg_data >> 32U)); + if (ret == 0) { + resp_lo = ari_get_response_low(ari_base); + resp_hi = ari_get_response_high(ari_base); + + mca_arg_err = resp_lo & MCA_ARG_ERROR_MASK; + mca_arg_finish = (resp_hi >> MCA_ARG_FINISH_SHIFT) & + MCA_ARG_FINISH_MASK; + + if (mca_arg_finish == 0U) { + result = (uint64_t)mca_arg_err; + } else { + if (data != NULL) { + resp_lo = ari_get_request_low(ari_base); + resp_hi = ari_get_request_high(ari_base); + *data = ((uint64_t)resp_hi << 32U) | + (uint64_t)resp_lo; + } + } + } + + return result; +} + +int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx) +{ + int32_t ret = 0; + /* sanity check GSC ID */ + if (gsc_idx > TEGRA_ARI_GSC_VPR_IDX) { + ret = EINVAL; + } else { + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* + * The MCE code will read the GSC carveout value, corrseponding to + * the ID, from the MC registers and update the internal GSC registers + * of the CCPLEX. + */ + (void)ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0U); + } + + return ret; +} + +void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* + * The MCE will shutdown or restart the entire system + */ + (void)ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_MISC_CCPLEX, state_idx, 0U); +} + +int32_t ari_read_write_uncore_perfmon(uint32_t ari_base, uint64_t req, + uint64_t *data) +{ + int32_t ret, result; + uint32_t val, req_status; + uint8_t req_cmd; + + req_cmd = (uint8_t)(req & UNCORE_PERFMON_CMD_MASK); + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* sanity check input parameters */ + if ((req_cmd == UNCORE_PERFMON_CMD_READ) && (data == NULL)) { + ERROR("invalid parameters\n"); + result = EINVAL; + } else { + /* + * For "write" commands get the value that has to be written + * to the uncore perfmon registers + */ + val = (req_cmd == UNCORE_PERFMON_CMD_WRITE) ? + (uint32_t)*data : 0U; + + ret = ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_PERFMON, val, (uint32_t)req); + if (ret != 0) { + result = ret; + } else { + /* read the command status value */ + req_status = ari_get_response_high(ari_base) & + UNCORE_PERFMON_RESP_STATUS_MASK; + + /* + * For "read" commands get the data from the uncore + * perfmon registers + */ + req_status &= UNCORE_PERFMON_RESP_STATUS_MASK; + if ((req_status == 0U) && (req_cmd == UNCORE_PERFMON_CMD_READ)) { + *data = ari_get_response_low(ari_base); + } + result = (int32_t)req_status; + } + } + + return result; +} + +void ari_misc_ccplex(uint32_t ari_base, uint32_t index, uint32_t value) +{ + /* + * This invokes the ARI_MISC_CCPLEX commands. This can be + * used to enable/disable coresight clock gating. + */ + + if ((index > TEGRA_ARI_MISC_CCPLEX_EDBGREQ) || + ((index == TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL) && + (value > 1U))) { + ERROR("%s: invalid parameters \n", __func__); + } else { + /* clean the previous response state */ + ari_clobber_response(ari_base); + (void)ari_request_wait(ari_base, 0U, + (uint32_t)TEGRA_ARI_MISC_CCPLEX, index, value); + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c new file mode 100644 index 0000000..aebaceb --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2015-2018, 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* NVG functions handlers */ +static arch_mce_ops_t nvg_mce_ops = { + .enter_cstate = nvg_enter_cstate, + .update_cstate_info = nvg_update_cstate_info, + .update_crossover_time = nvg_update_crossover_time, + .read_cstate_stats = nvg_read_cstate_stats, + .write_cstate_stats = nvg_write_cstate_stats, + .call_enum_misc = ari_enumeration_misc, + .is_ccx_allowed = nvg_is_ccx_allowed, + .is_sc7_allowed = nvg_is_sc7_allowed, + .online_core = nvg_online_core, + .cc3_ctrl = nvg_cc3_ctrl, + .update_reset_vector = ari_reset_vector_update, + .roc_flush_cache = ari_roc_flush_cache, + .roc_flush_cache_trbits = ari_roc_flush_cache_trbits, + .roc_clean_cache = ari_roc_clean_cache, + .read_write_mca = ari_read_write_mca, + .update_ccplex_gsc = ari_update_ccplex_gsc, + .enter_ccplex_state = ari_enter_ccplex_state, + .read_write_uncore_perfmon = ari_read_write_uncore_perfmon, + .misc_ccplex = ari_misc_ccplex +}; + +/* ARI functions handlers */ +static arch_mce_ops_t ari_mce_ops = { + .enter_cstate = ari_enter_cstate, + .update_cstate_info = ari_update_cstate_info, + .update_crossover_time = ari_update_crossover_time, + .read_cstate_stats = ari_read_cstate_stats, + .write_cstate_stats = ari_write_cstate_stats, + .call_enum_misc = ari_enumeration_misc, + .is_ccx_allowed = ari_is_ccx_allowed, + .is_sc7_allowed = ari_is_sc7_allowed, + .online_core = ari_online_core, + .cc3_ctrl = ari_cc3_ctrl, + .update_reset_vector = ari_reset_vector_update, + .roc_flush_cache = ari_roc_flush_cache, + .roc_flush_cache_trbits = ari_roc_flush_cache_trbits, + .roc_clean_cache = ari_roc_clean_cache, + .read_write_mca = ari_read_write_mca, + .update_ccplex_gsc = ari_update_ccplex_gsc, + .enter_ccplex_state = ari_enter_ccplex_state, + .read_write_uncore_perfmon = ari_read_write_uncore_perfmon, + .misc_ccplex = ari_misc_ccplex +}; + +typedef struct { + uint32_t ari_base; + arch_mce_ops_t *ops; +} mce_config_t; + +/* Table to hold the per-CPU ARI base address and function handlers */ +static mce_config_t mce_cfg_table[MCE_ARI_APERTURES_MAX] = { + { + /* A57 Core 0 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET, + .ops = &ari_mce_ops, + }, + { + /* A57 Core 1 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET, + .ops = &ari_mce_ops, + }, + { + /* A57 Core 2 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET, + .ops = &ari_mce_ops, + }, + { + /* A57 Core 3 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET, + .ops = &ari_mce_ops, + }, + { + /* D15 Core 0 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET, + .ops = &nvg_mce_ops, + }, + { + /* D15 Core 1 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET, + .ops = &nvg_mce_ops, + } +}; + +static uint32_t mce_get_curr_cpu_ari_base(void) +{ + uint64_t mpidr = read_mpidr(); + uint64_t cpuid = mpidr & MPIDR_CPU_MASK; + uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* + * T186 has 2 CPU clusters, one with Denver CPUs and the other with + * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU + * numbers start from 0. In order to get the proper arch_mce_ops_t + * struct, we have to convert the Denver CPU ids to the corresponding + * indices in the mce_ops_table array. + */ + if (impl == DENVER_IMPL) { + cpuid |= 0x4U; + } + + return mce_cfg_table[cpuid].ari_base; +} + +static arch_mce_ops_t *mce_get_curr_cpu_ops(void) +{ + uint64_t mpidr = read_mpidr(); + uint64_t cpuid = mpidr & MPIDR_CPU_MASK; + uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & + MIDR_IMPL_MASK; + + /* + * T186 has 2 CPU clusters, one with Denver CPUs and the other with + * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU + * numbers start from 0. In order to get the proper arch_mce_ops_t + * struct, we have to convert the Denver CPU ids to the corresponding + * indices in the mce_ops_table array. + */ + if (impl == DENVER_IMPL) { + cpuid |= 0x4U; + } + + return mce_cfg_table[cpuid].ops; +} + +/******************************************************************************* + * Common handler for all MCE commands + ******************************************************************************/ +int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1, + uint64_t arg2) +{ + const arch_mce_ops_t *ops; + gp_regs_t *gp_regs = get_gpregs_ctx(cm_get_context(NON_SECURE)); + uint32_t cpu_ari_base; + uint64_t ret64 = 0, arg3, arg4, arg5; + int32_t ret = 0; + + assert(gp_regs != NULL); + + /* get a pointer to the CPU's arch_mce_ops_t struct */ + ops = mce_get_curr_cpu_ops(); + + /* get the CPU's ARI base address */ + cpu_ari_base = mce_get_curr_cpu_ari_base(); + + switch (cmd) { + case (uint64_t)MCE_CMD_ENTER_CSTATE: + ret = ops->enter_cstate(cpu_ari_base, arg0, arg1); + + break; + + case (uint64_t)MCE_CMD_UPDATE_CSTATE_INFO: + /* + * get the parameters required for the update cstate info + * command + */ + arg3 = read_ctx_reg(gp_regs, CTX_GPREG_X4); + arg4 = read_ctx_reg(gp_regs, CTX_GPREG_X5); + arg5 = read_ctx_reg(gp_regs, CTX_GPREG_X6); + + ret = ops->update_cstate_info(cpu_ari_base, (uint32_t)arg0, + (uint32_t)arg1, (uint32_t)arg2, (uint8_t)arg3, + (uint32_t)arg4, (uint8_t)arg5); + + write_ctx_reg(gp_regs, CTX_GPREG_X4, (0ULL)); + write_ctx_reg(gp_regs, CTX_GPREG_X5, (0ULL)); + write_ctx_reg(gp_regs, CTX_GPREG_X6, (0ULL)); + + break; + + case (uint64_t)MCE_CMD_UPDATE_CROSSOVER_TIME: + ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1); + + break; + + case (uint64_t)MCE_CMD_READ_CSTATE_STATS: + ret64 = ops->read_cstate_stats(cpu_ari_base, arg0); + + /* update context to return cstate stats value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); + write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64)); + + break; + + case (uint64_t)MCE_CMD_WRITE_CSTATE_STATS: + ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1); + + break; + + case (uint64_t)MCE_CMD_IS_CCX_ALLOWED: + ret = ops->is_ccx_allowed(cpu_ari_base, arg0, arg1); + + /* update context to return CCx status value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret)); + + break; + + case (uint64_t)MCE_CMD_IS_SC7_ALLOWED: + ret = ops->is_sc7_allowed(cpu_ari_base, arg0, arg1); + + /* update context to return SC7 status value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret)); + write_ctx_reg(gp_regs, CTX_GPREG_X3, (uint64_t)(ret)); + + break; + + case (uint64_t)MCE_CMD_ONLINE_CORE: + ret = ops->online_core(cpu_ari_base, arg0); + + break; + + case (uint64_t)MCE_CMD_CC3_CTRL: + ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2); + + break; + + case (uint64_t)MCE_CMD_ECHO_DATA: + ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_ECHO, + arg0); + + /* update context to return if echo'd data matched source */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ((ret64 == arg0) ? + 1ULL : 0ULL)); + write_ctx_reg(gp_regs, CTX_GPREG_X2, ((ret64 == arg0) ? + 1ULL : 0ULL)); + + break; + + case (uint64_t)MCE_CMD_READ_VERSIONS: + ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, + arg0); + + /* + * version = minor(63:32) | major(31:0). Update context + * to return major and minor version number. + */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); + write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64 >> 32ULL)); + + break; + + case (uint64_t)MCE_CMD_ENUM_FEATURES: + ret64 = ops->call_enum_misc(cpu_ari_base, + TEGRA_ARI_MISC_FEATURE_LEAF_0, arg0); + + /* update context to return features value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); + + break; + + case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE_TRBITS: + ret = ops->roc_flush_cache_trbits(cpu_ari_base); + + break; + + case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE: + ret = ops->roc_flush_cache(cpu_ari_base); + + break; + + case (uint64_t)MCE_CMD_ROC_CLEAN_CACHE: + ret = ops->roc_clean_cache(cpu_ari_base); + + break; + + case (uint64_t)MCE_CMD_ENUM_READ_MCA: + ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1); + + /* update context to return MCA data/error */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); + write_ctx_reg(gp_regs, CTX_GPREG_X2, (arg1)); + write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64)); + + break; + + case (uint64_t)MCE_CMD_ENUM_WRITE_MCA: + ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1); + + /* update context to return MCA error */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); + write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64)); + + break; + +#if ENABLE_CHIP_VERIFICATION_HARNESS + case (uint64_t)MCE_CMD_ENABLE_LATIC: + /* + * This call is not for production use. The constant value, + * 0xFFFF0000, is specific to allowing for enabling LATIC on + * pre-production parts for the chip verification harness. + * + * Enabling LATIC allows S/W to read the MINI ISPs in the + * CCPLEX. The ISMs are used for various measurements relevant + * to particular locations in the Silicon. They are small + * counters which can be polled to determine how fast a + * particular location in the Silicon is. + */ + ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), + 0xFFFF0000); + + break; +#endif + + case (uint64_t)MCE_CMD_UNCORE_PERFMON_REQ: + ret = ops->read_write_uncore_perfmon(cpu_ari_base, arg0, &arg1); + + /* update context to return data */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (arg1)); + break; + + case (uint64_t)MCE_CMD_MISC_CCPLEX: + ops->misc_ccplex(cpu_ari_base, arg0, arg1); + + break; + + default: + ERROR("unknown MCE command (%" PRIu64 ")\n", cmd); + ret = EINVAL; + break; + } + + return ret; +} + +/******************************************************************************* + * Handler to update the reset vector for CPUs + ******************************************************************************/ +int32_t mce_update_reset_vector(void) +{ + const arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); + + ops->update_reset_vector(mce_get_curr_cpu_ari_base()); + + return 0; +} + +static int32_t mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx) +{ + const arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); + + ops->update_ccplex_gsc(mce_get_curr_cpu_ari_base(), gsc_idx); + + return 0; +} + +/******************************************************************************* + * Handler to update carveout values for Video Memory Carveout region + ******************************************************************************/ +int32_t mce_update_gsc_videomem(void) +{ + return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX); +} + +/******************************************************************************* + * Handler to update carveout values for TZDRAM aperture + ******************************************************************************/ +int32_t mce_update_gsc_tzdram(void) +{ + return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX); +} + +/******************************************************************************* + * Handler to shutdown/reset the entire system + ******************************************************************************/ +__dead2 void mce_enter_ccplex_state(uint32_t state_idx) +{ + const arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); + + /* sanity check state value */ + if ((state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) && + (state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT)) { + panic(); + } + + ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), state_idx); + + /* wait till the CCPLEX powers down */ + for (;;) { + ; + } + +} + +/******************************************************************************* + * Handler to issue the UPDATE_CSTATE_INFO request + ******************************************************************************/ +void mce_update_cstate_info(const mce_cstate_info_t *cstate) +{ + const arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); + + /* issue the UPDATE_CSTATE_INFO request */ + ops->update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster, + cstate->ccplex, cstate->system, cstate->system_state_force, + cstate->wake_mask, cstate->update_wake_mask); +} + +/******************************************************************************* + * Handler to read the MCE firmware version and check if it is compatible + * with interface header the BL3-1 was compiled against + ******************************************************************************/ +void mce_verify_firmware_version(void) +{ + const arch_mce_ops_t *ops; + uint32_t cpu_ari_base; + uint64_t version; + uint32_t major, minor; + + /* + * MCE firmware is not supported on simulation platforms. + */ + if (tegra_platform_is_emulation()) { + + INFO("MCE firmware is not supported\n"); + + } else { + /* get a pointer to the CPU's arch_mce_ops_t struct */ + ops = mce_get_curr_cpu_ops(); + + /* get the CPU's ARI base address */ + cpu_ari_base = mce_get_curr_cpu_ari_base(); + + /* + * Read the MCE firmware version and extract the major and minor + * version fields + */ + version = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, 0); + major = (uint32_t)version; + minor = (uint32_t)(version >> 32); + + INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor, + TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR); + + /* + * Verify that the MCE firmware version and the interface header + * match + */ + if (major != TEGRA_ARI_VERSION_MAJOR) { + ERROR("ARI major version mismatch\n"); + panic(); + } + + if (minor < TEGRA_ARI_VERSION_MINOR) { + ERROR("ARI minor version mismatch\n"); + panic(); + } + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c new file mode 100644 index 0000000..cbc9aa3 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + int32_t ret = 0; + uint64_t val = 0ULL; + + (void)ari_base; + + /* check for allowed power state */ + if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) && + (state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) { + ERROR("%s: unknown cstate (%d)\n", __func__, state); + ret = EINVAL; + } else { + /* time (TSC ticks) until the core is expected to get a wake event */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time); + + /* set the core cstate */ + val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK; + write_actlr_el1(val | (uint64_t)state); + } + + return ret; +} + +/* + * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and + * SYSTEM_CSTATE values. + */ +int32_t nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, + uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, + uint8_t update_wake_mask) +{ + uint64_t val = 0ULL; + + (void)ari_base; + + /* update CLUSTER_CSTATE? */ + if (cluster != 0U) { + val |= ((uint64_t)cluster & CLUSTER_CSTATE_MASK) | + CLUSTER_CSTATE_UPDATE_BIT; + } + + /* update CCPLEX_CSTATE? */ + if (ccplex != 0U) { + val |= (((uint64_t)ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) | + CCPLEX_CSTATE_UPDATE_BIT; + } + + /* update SYSTEM_CSTATE? */ + if (system != 0U) { + val |= (((uint64_t)system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + (((uint64_t)sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | + SYSTEM_CSTATE_UPDATE_BIT); + } + + /* update wake mask value? */ + if (update_wake_mask != 0U) { + val |= CSTATE_WAKE_MASK_UPDATE_BIT; + } + + /* set the wake mask */ + val &= CSTATE_WAKE_MASK_CLEAR; + val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT); + + /* set the updated cstate info */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CSTATE_INFO, val); + + return 0; +} + +int32_t nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) +{ + int32_t ret = 0; + + (void)ari_base; + + /* sanity check crossover type */ + if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1) { + ret = EINVAL; + } else { + /* + * The crossover threshold limit types start from + * TEGRA_CROSSOVER_TYPE_C1_C6 to TEGRA_CROSSOVER_TYPE_CCP3_SC7. + * The command indices for updating the threshold be generated + * by adding the type to the NVG_SET_THRESHOLD_CROSSOVER_C1_C6 + * command index. + */ + nvg_set_request_data((TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 + + (uint64_t)type), (uint64_t)time); + } + + return ret; +} + +uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state) +{ + uint64_t ret; + + (void)ari_base; + + /* sanity check state */ + if (state == 0U) { + ret = EINVAL; + } else { + /* + * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES + * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for + * reading the threshold can be generated by adding the type to + * the NVG_CLEAR_CSTATE_STATS command index. + */ + nvg_set_request((TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + + (uint64_t)state)); + ret = nvg_get_result(); + } + + return ret; +} + +int32_t nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) +{ + uint64_t val; + + (void)ari_base; + + /* + * The only difference between a CSTATE_STATS_WRITE and + * CSTATE_STATS_READ is the usage of the 63:32 in the request. + * 63:32 are set to '0' for a read, while a write contains the + * actual stats value to be written. + */ + val = ((uint64_t)stats << MCE_CSTATE_STATS_TYPE_SHIFT) | state; + + /* + * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES + * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for + * reading the threshold can be generated by adding the type to + * the NVG_CLEAR_CSTATE_STATS command index. + */ + nvg_set_request_data((TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + + (uint64_t)state), val); + + return 0; +} + +int32_t nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + (void)ari_base; + (void)state; + (void)wake_time; + + /* This does not apply to the Denver cluster */ + return 0; +} + +int32_t nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + uint64_t val; + int32_t ret; + + (void)ari_base; + + /* check for allowed power state */ + if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) && + (state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) { + ERROR("%s: unknown cstate (%d)\n", __func__, state); + ret = EINVAL; + } else { + /* + * Request format - + * 63:32 = wake time + * 31:0 = C-state for this core + */ + val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) | + ((uint64_t)state & MCE_SC7_ALLOWED_MASK); + + /* issue command to check if SC7 is allowed */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val); + + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + ret = (nvg_get_result() != 0ULL) ? 1 : 0; + } + + return ret; +} + +int32_t nvg_online_core(uint32_t ari_base, uint32_t core) +{ + uint64_t cpu = read_mpidr() & MPIDR_CPU_MASK; + uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + int32_t ret = 0; + + (void)ari_base; + + /* sanity check code id */ + if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { + ERROR("%s: unsupported core id (%d)\n", __func__, core); + ret = EINVAL; + } else { + /* + * The Denver cluster has 2 CPUs only - 0, 1. + */ + if ((impl == DENVER_IMPL) && ((core == 2U) || (core == 3U))) { + ERROR("%s: unknown core id (%d)\n", __func__, core); + ret = EINVAL; + } else { + /* get a core online */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_ONLINE_CORE, + ((uint64_t)core & MCE_CORE_ID_MASK)); + } + } + + return ret; +} + +int32_t nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) +{ + uint32_t val; + + (void)ari_base; + + /* + * If the enable bit is cleared, Auto-CC3 will be disabled by setting + * the SW visible voltage/frequency request registers for all non + * floorswept cores valid independent of StandbyWFI and disabling + * the IDLE voltage/frequency request register. If set, Auto-CC3 + * will be enabled by setting the ARM SW visible voltage/frequency + * request registers for all non floorswept cores to be enabled by + * StandbyWFI or the equivalent signal, and always keeping the IDLE + * voltage/frequency request register enabled. + */ + val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\ + ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\ + ((enable != 0U) ? MCE_AUTO_CC3_ENABLE_BIT : 0U)); + + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CC3_CTRL, (uint64_t)val); + + return 0; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c new file mode 100644 index 0000000..dad94fd --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "se_private.h" + +/******************************************************************************* + * Constants and Macros + ******************************************************************************/ +#define SE0_MAX_BUSY_TIMEOUT_MS U(100) /* 100ms */ +#define BYTES_IN_WORD U(4) +#define SHA256_MAX_HASH_RESULT U(7) +#define SHA256_DST_SIZE U(32) +#define SHA_FIRST_OP U(1) +#define MAX_SHA_ENGINE_CHUNK_SIZE U(0xFFFFFF) +#define SHA256_MSG_LENGTH_ONETIME U(0xffff) + +/* + * Check that SE operation has completed after kickoff + * This function is invoked after an SE operation has been started, + * and it checks the following conditions: + * 1. SE0_INT_STATUS = SE0_OP_DONE + * 2. SE0_STATUS = IDLE + * 3. SE0_ERR_STATUS is clean. + */ +static int32_t tegra_se_operation_complete(void) +{ + uint32_t val = 0U; + + /* Read SE0 interrupt register to ensure H/W operation complete */ + val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET); + if (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) { + ERROR("%s: Engine busy state too many times! val = 0x%x\n", + __func__, val); + return -ETIMEDOUT; + } + + /* Read SE0 status idle to ensure H/W operation complete */ + val = tegra_se_read_32(SE0_SHA_STATUS_0); + if (val != SE0_SHA_STATUS_IDLE) { + ERROR("%s: Idle state timeout! val = 0x%x\n", __func__, + val); + return -ETIMEDOUT; + } + + /* Ensure that no errors are thrown during operation */ + val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET); + if (val != SE0_ERR_STATUS_CLEAR) { + ERROR("%s: Error during SE operation! val = 0x%x", + __func__, val); + return -ENOTSUP; + } + + return 0; +} + +/* + * Security engine primitive normal operations + */ +static int32_t tegra_se_start_normal_operation(uint64_t src_addr, + uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes) +{ + int32_t ret = 0; + uint32_t val = 0U; + uint32_t src_in_lo; + uint32_t src_in_msb; + uint32_t src_in_hi; + + if ((src_addr == 0UL) || (nbytes == 0U)) + return -EINVAL; + + src_in_lo = (uint32_t)src_addr; + src_in_msb = ((uint32_t)(src_addr >> 32U) & 0xffU); + src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) | + (nbytes & 0xffffffU)); + + /* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/ + tegra_se_write_32(SE0_IN_ADDR, src_in_lo); + tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi); + + val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET); + if (val > 0U) { + tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x00000U); + } + + /* Enable SHA interrupt for SE0 Operation */ + tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU); + + /* flush to DRAM for SE to use the updated contents */ + flush_dcache_range(src_addr, src_len_inbytes); + + /* Start SHA256 operation */ + if (last_buf == 1U) { + tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START | + SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD); + } else { + tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START); + } + + /* Wait for SE-operation to finish */ + udelay(SE0_MAX_BUSY_TIMEOUT_MS * 100U); + + /* Check SE0 operation status */ + ret = tegra_se_operation_complete(); + if (ret != 0) { + ERROR("SE operation complete Failed! 0x%x", ret); + return ret; + } + + return 0; +} + +static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr, + uint32_t src_len_inbyte) +{ + uint32_t val, last_buf, i; + int32_t ret = 0; + uint32_t operations; + uint64_t src_len_inbits; + uint32_t len_bits_msb; + uint32_t len_bits_lsb; + uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes; + + if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) { + ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte); + return -EINVAL; + } + + if (src_addr == 0UL) { + return -EINVAL; + } + + /* number of bytes per operation */ + max_bytes = SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME; + + src_len_inbits = src_len_inbyte * 8U; + len_bits_msb = (uint32_t)(src_len_inbits >> 32U); + len_bits_lsb = (uint32_t)(src_len_inbits & 0xFFFFFFFF); + + /* program SE0_CONFIG for SHA256 operation */ + val = SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 | + SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG; + tegra_se_write_32(SE0_SHA_CONFIG, val); + + /* set SE0_SHA_MSG_LENGTH registers */ + tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb); + tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb); + tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb); + + /* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */ + tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U); + tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U); + tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U); + tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U); + tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U); + + number_of_operations = src_len_inbyte / max_bytes; + remaining_bytes = src_len_inbyte % max_bytes; + if (remaining_bytes > 0U) { + number_of_operations += 1U; + } + + /* + * 1. Operations == 1: program SE0_SHA_TASK register to initiate SHA256 + * hash generation by setting + * 1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK + * and start SHA256-normal operation. + * 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to + * 0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load + * intermediate SHA256 digest result from + * HASH_RESULT register to continue SHA256 + * generation and start SHA256-normal operation. + * 3. Operations == number_of_operations: continue with step 2 and set + * max_bytes to bytes_left to process final + * hash-result generation and + * start SHA256-normal operation. + */ + bytes_left = src_len_inbyte; + for (operations = 1U; operations <= number_of_operations; + operations++) { + if (operations == SHA_FIRST_OP) { + val = SE0_SHA_CONFIG_HW_INIT_HASH; + } else { + /* Load intermediate SHA digest result to + * SHA:HASH_RESULT(0..7) to continue the SHA + * calculation and tell the SHA engine to use it. + */ + for (i = 0U; (i / BYTES_IN_WORD) <= + SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) { + val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + + i); + tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i, + val); + } + val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE; + if (len_bits_lsb <= (max_bytes * 8U)) { + len_bits_lsb = (remaining_bytes * 8U); + } else { + len_bits_lsb -= (max_bytes * 8U); + } + tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb); + } + tegra_se_write_32(SE0_SHA_TASK_CONFIG, val); + + max_bytes = (SHA256_HASH_SIZE_BYTES * + SHA256_MSG_LENGTH_ONETIME); + if (bytes_left < max_bytes) { + max_bytes = bytes_left; + last_buf = 1U; + } else { + bytes_left = bytes_left - max_bytes; + last_buf = 0U; + } + /* start operation */ + ret = tegra_se_start_normal_operation(src_addr, max_bytes, + last_buf, src_len_inbyte); + if (ret != 0) { + ERROR("Error during SE operation! 0x%x", ret); + return -EINVAL; + } + } + + return ret; +} + +/* + * Handler to generate SHA256 and save SHA256 hash to PMC-Scratch register. + */ +int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte) +{ + int32_t ret = 0; + uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U, security; + + /* + * Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE + * registers. + */ + security = tegra_se_read_32(SE0_SECURITY); + tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING); + + ret = tegra_se_calculate_sha256_hash(bl31_base, src_len_inbyte); + if (ret != 0L) { + ERROR("%s: SHA256 generation failed\n", __func__); + return ret; + } + + /* + * Reset SE_SECURE to previous value. + */ + tegra_se_write_32(SE0_SECURITY, security); + + /* read SHA256_HASH_RESULT and save to PMC Scratch registers */ + scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START; + while (scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END) { + + val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset); + mmio_write_32(TEGRA_SCRATCH_BASE + scratch_offset, val); + + hash_offset += BYTES_IN_WORD; + scratch_offset += BYTES_IN_WORD; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h new file mode 100644 index 0000000..7aa0dd6 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SE_PRIVATE_H +#define SE_PRIVATE_H + +#include + +/* SE0 security register */ +#define SE0_SECURITY U(0x18) +#define SE0_SECURITY_SE_SOFT_SETTING (((uint32_t)1) << 16U) + +/* SE0 config register */ +#define SE0_SHA_CONFIG U(0x104) +#define SE0_SHA_TASK_CONFIG U(0x108) +#define SE0_SHA_CONFIG_HW_INIT_HASH ((1U) << 0U) +#define SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE U(0) + +#define SE0_CONFIG_ENC_ALG_SHIFT U(12) +#define SE0_CONFIG_ENC_ALG_SHA \ + (((uint32_t)3) << SE0_CONFIG_ENC_ALG_SHIFT) +#define SE0_CONFIG_DEC_ALG_SHIFT U(8) +#define SE0_CONFIG_DEC_ALG_NOP \ + (((uint32_t)0) << SE0_CONFIG_DEC_ALG_SHIFT) +#define SE0_CONFIG_DST_SHIFT U(2) +#define SE0_CONFIG_DST_HASHREG \ + (((uint32_t)1) << SE0_CONFIG_DST_SHIFT) +#define SHA256_HASH_SIZE_BYTES U(256) + +#define SE0_CONFIG_ENC_MODE_SHIFT U(24) +#define SE0_CONFIG_ENC_MODE_SHA256 \ + (((uint32_t)5) << SE0_CONFIG_ENC_MODE_SHIFT) + +/* SHA input message length */ +#define SE0_SHA_MSG_LENGTH_0 U(0x11c) +#define SE0_SHA_MSG_LENGTH_1 U(0x120) +#define SE0_SHA_MSG_LENGTH_2 U(0x124) +#define SE0_SHA_MSG_LENGTH_3 U(0x128) + +/* SHA input message left */ +#define SE0_SHA_MSG_LEFT_0 U(0x12c) +#define SE0_SHA_MSG_LEFT_1 U(0x130) +#define SE0_SHA_MSG_LEFT_2 U(0x134) +#define SE0_SHA_MSG_LEFT_3 U(0x138) + +/* SE Hash Result */ +#define SE0_SHA_HASH_RESULT_0 U(0x13c) + +/* SE OPERATION */ +#define SE0_OPERATION_REG_OFFSET U(0x17c) +#define SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT U(16) +#define SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD \ + (((uint32_t)0x1) << SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT) +#define SE0_OPERATION_SHIFT U(0) +#define SE0_OP_START \ + (((uint32_t)0x1) << SE0_OPERATION_SHIFT) + +/* SE Interrupt */ +#define SE0_SHA_INT_ENABLE U(0x180) + +#define SE0_INT_STATUS_REG_OFFSET U(0x184) +#define SE0_INT_OP_DONE_SHIFT U(4) +#define SE0_INT_OP_DONE_CLEAR \ + (((uint32_t)0) << SE0_INT_OP_DONE_SHIFT) +#define SE0_INT_OP_DONE(x) \ + ((x) & (((uint32_t)0x1) << SE0_INT_OP_DONE_SHIFT)) + +/* SE SHA status */ +#define SE0_SHA_STATUS_0 U(0x188) +#define SE0_SHA_STATUS_IDLE U(0) + +/* SE error status */ +#define SE0_ERR_STATUS_REG_OFFSET U(0x18c) +#define SE0_ERR_STATUS_CLEAR U(0) +#define SE0_IN_ADDR U(0x10c) +#define SE0_IN_HI_ADDR_HI U(0x110) +#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT U(24) + +/* SE error status */ +#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START SECURE_SCRATCH_RSV63_LO +#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END SECURE_SCRATCH_RSV66_HI + +/******************************************************************************* + * Inline functions definition + ******************************************************************************/ + +static inline uint32_t tegra_se_read_32(uint32_t offset) +{ + return mmio_read_32((uint32_t)(TEGRA_SE0_BASE + offset)); +} + +static inline void tegra_se_write_32(uint32_t offset, uint32_t val) +{ + mmio_write_32(((uint32_t)(TEGRA_SE0_BASE + offset)), val); +} + +#endif /* SE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c new file mode 100644 index 0000000..a104f33 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c @@ -0,0 +1,715 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +extern uint64_t tegra_bl31_phys_base; + +/******************************************************************************* + * Array to hold stream_id override config register offsets + ******************************************************************************/ +const static uint32_t tegra186_streamid_override_regs[] = { + MC_STREAMID_OVERRIDE_CFG_SDMMCRA, + MC_STREAMID_OVERRIDE_CFG_SDMMCRAA, + MC_STREAMID_OVERRIDE_CFG_SDMMCR, + MC_STREAMID_OVERRIDE_CFG_SDMMCRAB, + MC_STREAMID_OVERRIDE_CFG_SDMMCWA, + MC_STREAMID_OVERRIDE_CFG_SDMMCWAA, + MC_STREAMID_OVERRIDE_CFG_SDMMCW, + MC_STREAMID_OVERRIDE_CFG_SDMMCWAB, +}; + +/******************************************************************************* + * Array to hold the security configs for stream IDs + ******************************************************************************/ +const static mc_streamid_security_cfg_t tegra186_streamid_sec_cfgs[] = { + mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(AFIR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(AFIW, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(XUSB_DEVR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(VICSRD1, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(NVENCSWR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(TSECSRDB, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(AXISW, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCWAB, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(AONDMAW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(GPUSWR2, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCWAA, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(SESWR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(GPUSRD, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(ISPWA, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(XUSB_HOSTW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(TSECSWR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCRAA, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(VIW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(AXISR, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(ISPRA, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDECSWR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(XUSB_DEVW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(MPCOREW, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(NVDISPLAYR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(NVJPGSWR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(XUSB_HOSTR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(AONDMAR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(AONW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCRA, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(EQOSR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, DISABLE), + mc_make_sec_cfg(AONR, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SESRD, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(GPUSWR, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(TSECSWRB, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(ISPWB, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(GPUSRD2, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE), +}; + +/******************************************************************************* + * Array to hold the transaction override configs + ******************************************************************************/ +const static mc_txn_override_cfg_t tegra186_txn_override_cfgs[] = { + mc_make_txn_override_cfg(BPMPW, CGID_TAG_ADR), + mc_make_txn_override_cfg(EQOSW, CGID_TAG_ADR), + mc_make_txn_override_cfg(NVJPGSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(SDMMCWAA, CGID_TAG_ADR), + mc_make_txn_override_cfg(MPCOREW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SCEDMAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SDMMCW, CGID_TAG_ADR), + mc_make_txn_override_cfg(AXISW, CGID_TAG_ADR), + mc_make_txn_override_cfg(TSECSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(GPUSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(XUSB_HOSTW, CGID_TAG_ADR), + mc_make_txn_override_cfg(TSECSWRB, CGID_TAG_ADR), + mc_make_txn_override_cfg(GPUSWR2, CGID_TAG_ADR), + mc_make_txn_override_cfg(AONDMAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(AONW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SESWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(BPMPDMAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SDMMCWA, CGID_TAG_ADR), + mc_make_txn_override_cfg(HDAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(NVDECSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(UFSHCW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SATAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(ETRW, CGID_TAG_ADR), + mc_make_txn_override_cfg(VICSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(NVENCSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(SDMMCWAB, CGID_TAG_ADR), + mc_make_txn_override_cfg(ISPWB, CGID_TAG_ADR), + mc_make_txn_override_cfg(APEW, CGID_TAG_ADR), + mc_make_txn_override_cfg(XUSB_DEVW, CGID_TAG_ADR), + mc_make_txn_override_cfg(AFIW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SCEW, CGID_TAG_ADR), +}; + +static void tegra186_memctrl_reconfig_mss_clients(void) +{ +#if ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS + uint32_t val, wdata_0, wdata_1; + + /* + * Assert Memory Controller's HOTRESET_FLUSH_ENABLE signal for + * boot and strongly ordered MSS clients to flush existing memory + * traffic and stall future requests. + */ + val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL0); + assert(val == MC_CLIENT_HOTRESET_CTRL0_RESET_VAL); + + wdata_0 = MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB; + tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0); + + /* Wait for HOTRESET STATUS to indicate FLUSH_DONE */ + do { + val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS0); + } while ((val & wdata_0) != wdata_0); + + /* Wait one more time due to SW WAR for known legacy issue */ + do { + val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS0); + } while ((val & wdata_0) != wdata_0); + + val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL1); + assert(val == MC_CLIENT_HOTRESET_CTRL1_RESET_VAL); + + wdata_1 = MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB | + MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB; + tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1); + + /* Wait for HOTRESET STATUS to indicate FLUSH_DONE */ + do { + val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS1); + } while ((val & wdata_1) != wdata_1); + + /* Wait one more time due to SW WAR for known legacy issue */ + do { + val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS1); + } while ((val & wdata_1) != wdata_1); + + /* + * Change MEMTYPE_OVERRIDE from SO_DEV -> PASSTHRU for boot and + * strongly ordered MSS clients. ROC needs to be single point + * of control on overriding the memory type. So, remove TSA's + * memtype override. + * + * MC clients with default SO_DEV override still enabled at TSA: + * AONW, BPMPW, SCEW, APEW + */ + mc_set_tsa_passthrough(AFIW); + mc_set_tsa_passthrough(HDAW); + mc_set_tsa_passthrough(SATAW); + mc_set_tsa_passthrough(XUSB_HOSTW); + mc_set_tsa_passthrough(XUSB_DEVW); + mc_set_tsa_passthrough(SDMMCWAB); + mc_set_tsa_passthrough(APEDMAW); + mc_set_tsa_passthrough(SESWR); + mc_set_tsa_passthrough(ETRW); + mc_set_tsa_passthrough(AXISW); + mc_set_tsa_passthrough(EQOSW); + mc_set_tsa_passthrough(UFSHCW); + mc_set_tsa_passthrough(BPMPDMAW); + mc_set_tsa_passthrough(AONDMAW); + mc_set_tsa_passthrough(SCEDMAW); + + /* Parker has no IO Coherency support and need the following: + * Ordered MC Clients on Parker are AFI, EQOS, SATA, XUSB. + * ISO clients(DISP, VI, EQOS) should never snoop caches and + * don't need ROC/PCFIFO ordering. + * ISO clients(EQOS) that need ordering should use PCFIFO ordering + * and bypass ROC ordering by using FORCE_NON_COHERENT path. + * FORCE_NON_COHERENT/FORCE_COHERENT config take precedence + * over SMMU attributes. + * Force all Normal memory transactions from ISO and non-ISO to be + * non-coherent(bypass ROC, avoid cache snoop to avoid perf hit). + * Force the SO_DEV transactions from ordered ISO clients(EQOS) to + * non-coherent path and enable MC PCFIFO interlock for ordering. + * Force the SO_DEV transactions from ordered non-ISO clients (PCIe, + * XUSB, SATA) to coherent so that the transactions are + * ordered by ROC. + * PCFIFO ensure write ordering. + * Read after Write ordering is maintained/enforced by MC clients. + * Clients that need PCIe type write ordering must + * go through ROC ordering. + * Ordering enable for Read clients is not necessary. + * R5's and A9 would get necessary ordering from AXI and + * don't need ROC ordering enable: + * - MMIO ordering is through dev mapping and MMIO + * accesses bypass SMMU. + * - Normal memory is accessed through SMMU and ordering is + * ensured by client and AXI. + * - Ack point for Normal memory is WCAM in MC. + * - MMIO's can be early acked and AXI ensures dev memory ordering, + * Client ensures read/write direction change ordering. + * - See Bug 200312466 for more details. + * + * CGID_TAG_ADR is only present from T186 A02. As this code is common + * between A01 and A02, tegra_memctrl_set_overrides() programs + * CGID_TAG_ADR for the necessary clients on A02. + */ + mc_set_txn_override(HDAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(BPMPW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(PTCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVDISPLAYR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(EQOSW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVJPGSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(ISPRA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SDMMCWAA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(VICSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(MPCOREW, CGID_TAG_DEFAULT, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE); + mc_set_txn_override(GPUSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(AXISR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SCEDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SDMMCW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(EQOSR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + /* See bug 200131110 comment #35*/ + mc_set_txn_override(APEDMAR, CGID_TAG_CLIENT_AXI_ID, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVENCSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SDMMCRAB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(VICSRD1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(BPMPDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(VIW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SDMMCRAA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(AXISW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(XUSB_DEVR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(UFSHCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(TSECSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(GPUSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SATAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(XUSB_HOSTW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT); + mc_set_txn_override(TSECSWRB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(GPUSRD2, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SCEDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(GPUSWR2, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(AONDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + /* See bug 200131110 comment #35*/ + mc_set_txn_override(APEDMAW, CGID_TAG_CLIENT_AXI_ID, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(AONW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(HOST1XDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(ETRR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SESWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVJPGSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVDECSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(TSECSRDB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(BPMPDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(APER, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVDECSRD1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(XUSB_HOSTR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(ISPWA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SESRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SCER, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(AONR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(MPCORER, CGID_TAG_DEFAULT, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE); + mc_set_txn_override(SDMMCWA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(HDAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVDECSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(UFSHCW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(AONDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SATAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT); + mc_set_txn_override(ETRW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(VICSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVENCSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + /* See bug 200131110 comment #35 */ + mc_set_txn_override(AFIR, CGID_TAG_DEFAULT, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SDMMCWAB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SDMMCRA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(NVDISPLAYR1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(ISPWB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(BPMPR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(APEW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(SDMMCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + mc_set_txn_override(XUSB_DEVW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT); + mc_set_txn_override(TSECSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + /* + * See bug 200131110 comment #35 - there are no normal requests + * and AWID for SO/DEV requests is hardcoded in RTL for a + * particular PCIE controller + */ + mc_set_txn_override(AFIW, CGID_TAG_DEFAULT, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_COHERENT); + mc_set_txn_override(SCEW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT); + + /* + * At this point, ordering can occur at ROC. So, remove PCFIFO's + * control over ordering requests. + * + * Change PCFIFO_*_ORDERED_CLIENT from ORDERED -> UNORDERED for + * boot and strongly ordered MSS clients + */ + val = MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL & + mc_set_pcfifo_unordered_boot_so_mss(1, AFIW) & + mc_set_pcfifo_unordered_boot_so_mss(1, HDAW) & + mc_set_pcfifo_unordered_boot_so_mss(1, SATAW); + tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG1, val); + + val = MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL & + mc_set_pcfifo_unordered_boot_so_mss(2, XUSB_HOSTW) & + mc_set_pcfifo_unordered_boot_so_mss(2, XUSB_DEVW); + tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG2, val); + + val = MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL & + mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCWAB); + tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG3, val); + + val = MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL & + mc_set_pcfifo_unordered_boot_so_mss(4, SESWR) & + mc_set_pcfifo_unordered_boot_so_mss(4, ETRW) & + mc_set_pcfifo_unordered_boot_so_mss(4, AXISW) & + mc_set_pcfifo_unordered_boot_so_mss(4, UFSHCW) & + mc_set_pcfifo_unordered_boot_so_mss(4, BPMPDMAW) & + mc_set_pcfifo_unordered_boot_so_mss(4, AONDMAW) & + mc_set_pcfifo_unordered_boot_so_mss(4, SCEDMAW); + /* EQOSW is the only client that has PCFIFO order enabled. */ + val |= mc_set_pcfifo_ordered_boot_so_mss(4, EQOSW); + tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG4, val); + + val = MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL & + mc_set_pcfifo_unordered_boot_so_mss(5, APEDMAW); + tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG5, val); + + /* + * Deassert HOTRESET FLUSH_ENABLE for boot and strongly ordered MSS + * clients to allow memory traffic from all clients to start passing + * through ROC + */ + val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL0); + assert(val == wdata_0); + + wdata_0 = MC_CLIENT_HOTRESET_CTRL0_RESET_VAL; + tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0); + + val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL1); + assert(val == wdata_1); + + wdata_1 = MC_CLIENT_HOTRESET_CTRL1_RESET_VAL; + tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1); + +#endif +} + +static void tegra186_memctrl_set_overrides(void) +{ + uint32_t i, val; + + /* + * Set the MC_TXN_OVERRIDE registers for write clients. + */ + if ((tegra_chipid_is_t186()) && + (!tegra_platform_is_silicon() || + (tegra_platform_is_silicon() && (tegra_get_chipid_minor() == 1U)))) { + + /* + * GPU and NVENC settings for Tegra186 simulation and + * Silicon rev. A01 + */ + val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR); + val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK; + tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR, + val | MC_TXN_OVERRIDE_CGID_TAG_ZERO); + + val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR2); + val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK; + tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR2, + val | MC_TXN_OVERRIDE_CGID_TAG_ZERO); + + val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_NVENCSWR); + val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK; + tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_NVENCSWR, + val | MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID); + + } else { + + /* + * Settings for Tegra186 silicon rev. A02 and onwards. + */ + for (i = 0; i < ARRAY_SIZE(tegra186_txn_override_cfgs); i++) { + val = tegra_mc_read_32(tegra186_txn_override_cfgs[i].offset); + val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK; + tegra_mc_write_32(tegra186_txn_override_cfgs[i].offset, + val | tegra186_txn_override_cfgs[i].cgid_tag); + } + } +} + +/******************************************************************************* + * Array to hold MC context for Tegra186 + ******************************************************************************/ +static __attribute__((aligned(16))) mc_regs_t tegra186_mc_context[] = { + _START_OF_TABLE_, + mc_make_sid_security_cfg(SCEW), + mc_make_sid_security_cfg(AFIR), + mc_make_sid_security_cfg(NVDISPLAYR1), + mc_make_sid_security_cfg(XUSB_DEVR), + mc_make_sid_security_cfg(VICSRD1), + mc_make_sid_security_cfg(NVENCSWR), + mc_make_sid_security_cfg(TSECSRDB), + mc_make_sid_security_cfg(AXISW), + mc_make_sid_security_cfg(SDMMCWAB), + mc_make_sid_security_cfg(AONDMAW), + mc_make_sid_security_cfg(GPUSWR2), + mc_make_sid_security_cfg(SATAW), + mc_make_sid_security_cfg(UFSHCW), + mc_make_sid_security_cfg(AFIW), + mc_make_sid_security_cfg(SDMMCR), + mc_make_sid_security_cfg(SCEDMAW), + mc_make_sid_security_cfg(UFSHCR), + mc_make_sid_security_cfg(SDMMCWAA), + mc_make_sid_security_cfg(APEDMAW), + mc_make_sid_security_cfg(SESWR), + mc_make_sid_security_cfg(MPCORER), + mc_make_sid_security_cfg(PTCR), + mc_make_sid_security_cfg(BPMPW), + mc_make_sid_security_cfg(ETRW), + mc_make_sid_security_cfg(GPUSRD), + mc_make_sid_security_cfg(VICSWR), + mc_make_sid_security_cfg(SCEDMAR), + mc_make_sid_security_cfg(HDAW), + mc_make_sid_security_cfg(ISPWA), + mc_make_sid_security_cfg(EQOSW), + mc_make_sid_security_cfg(XUSB_HOSTW), + mc_make_sid_security_cfg(TSECSWR), + mc_make_sid_security_cfg(SDMMCRAA), + mc_make_sid_security_cfg(APER), + mc_make_sid_security_cfg(VIW), + mc_make_sid_security_cfg(APEW), + mc_make_sid_security_cfg(AXISR), + mc_make_sid_security_cfg(SDMMCW), + mc_make_sid_security_cfg(BPMPDMAW), + mc_make_sid_security_cfg(ISPRA), + mc_make_sid_security_cfg(NVDECSWR), + mc_make_sid_security_cfg(XUSB_DEVW), + mc_make_sid_security_cfg(NVDECSRD), + mc_make_sid_security_cfg(MPCOREW), + mc_make_sid_security_cfg(NVDISPLAYR), + mc_make_sid_security_cfg(BPMPDMAR), + mc_make_sid_security_cfg(NVJPGSWR), + mc_make_sid_security_cfg(NVDECSRD1), + mc_make_sid_security_cfg(TSECSRD), + mc_make_sid_security_cfg(NVJPGSRD), + mc_make_sid_security_cfg(SDMMCWA), + mc_make_sid_security_cfg(SCER), + mc_make_sid_security_cfg(XUSB_HOSTR), + mc_make_sid_security_cfg(VICSRD), + mc_make_sid_security_cfg(AONDMAR), + mc_make_sid_security_cfg(AONW), + mc_make_sid_security_cfg(SDMMCRA), + mc_make_sid_security_cfg(HOST1XDMAR), + mc_make_sid_security_cfg(EQOSR), + mc_make_sid_security_cfg(SATAR), + mc_make_sid_security_cfg(BPMPR), + mc_make_sid_security_cfg(HDAR), + mc_make_sid_security_cfg(SDMMCRAB), + mc_make_sid_security_cfg(ETRR), + mc_make_sid_security_cfg(AONR), + mc_make_sid_security_cfg(APEDMAR), + mc_make_sid_security_cfg(SESRD), + mc_make_sid_security_cfg(NVENCSRD), + mc_make_sid_security_cfg(GPUSWR), + mc_make_sid_security_cfg(TSECSWRB), + mc_make_sid_security_cfg(ISPWB), + mc_make_sid_security_cfg(GPUSRD2), + mc_make_sid_override_cfg(APER), + mc_make_sid_override_cfg(VICSRD), + mc_make_sid_override_cfg(NVENCSRD), + mc_make_sid_override_cfg(NVJPGSWR), + mc_make_sid_override_cfg(AONW), + mc_make_sid_override_cfg(BPMPR), + mc_make_sid_override_cfg(BPMPW), + mc_make_sid_override_cfg(HDAW), + mc_make_sid_override_cfg(NVDISPLAYR1), + mc_make_sid_override_cfg(APEDMAR), + mc_make_sid_override_cfg(AFIR), + mc_make_sid_override_cfg(AXISR), + mc_make_sid_override_cfg(VICSRD1), + mc_make_sid_override_cfg(TSECSRD), + mc_make_sid_override_cfg(BPMPDMAW), + mc_make_sid_override_cfg(MPCOREW), + mc_make_sid_override_cfg(XUSB_HOSTR), + mc_make_sid_override_cfg(GPUSWR), + mc_make_sid_override_cfg(XUSB_DEVR), + mc_make_sid_override_cfg(UFSHCW), + mc_make_sid_override_cfg(XUSB_HOSTW), + mc_make_sid_override_cfg(SDMMCWAB), + mc_make_sid_override_cfg(SATAW), + mc_make_sid_override_cfg(SCEDMAR), + mc_make_sid_override_cfg(HOST1XDMAR), + mc_make_sid_override_cfg(SDMMCWA), + mc_make_sid_override_cfg(APEDMAW), + mc_make_sid_override_cfg(SESWR), + mc_make_sid_override_cfg(AXISW), + mc_make_sid_override_cfg(AONDMAW), + mc_make_sid_override_cfg(TSECSWRB), + mc_make_sid_override_cfg(MPCORER), + mc_make_sid_override_cfg(ISPWB), + mc_make_sid_override_cfg(AONR), + mc_make_sid_override_cfg(BPMPDMAR), + mc_make_sid_override_cfg(HDAR), + mc_make_sid_override_cfg(SDMMCRA), + mc_make_sid_override_cfg(ETRW), + mc_make_sid_override_cfg(GPUSWR2), + mc_make_sid_override_cfg(EQOSR), + mc_make_sid_override_cfg(TSECSWR), + mc_make_sid_override_cfg(ETRR), + mc_make_sid_override_cfg(NVDECSRD), + mc_make_sid_override_cfg(TSECSRDB), + mc_make_sid_override_cfg(SDMMCRAA), + mc_make_sid_override_cfg(NVDECSRD1), + mc_make_sid_override_cfg(SDMMCR), + mc_make_sid_override_cfg(NVJPGSRD), + mc_make_sid_override_cfg(SCEDMAW), + mc_make_sid_override_cfg(SDMMCWAA), + mc_make_sid_override_cfg(APEW), + mc_make_sid_override_cfg(AONDMAR), + mc_make_sid_override_cfg(PTCR), + mc_make_sid_override_cfg(SCER), + mc_make_sid_override_cfg(ISPRA), + mc_make_sid_override_cfg(ISPWA), + mc_make_sid_override_cfg(VICSWR), + mc_make_sid_override_cfg(SESRD), + mc_make_sid_override_cfg(SDMMCW), + mc_make_sid_override_cfg(SDMMCRAB), + mc_make_sid_override_cfg(EQOSW), + mc_make_sid_override_cfg(GPUSRD2), + mc_make_sid_override_cfg(SCEW), + mc_make_sid_override_cfg(GPUSRD), + mc_make_sid_override_cfg(NVDECSWR), + mc_make_sid_override_cfg(XUSB_DEVW), + mc_make_sid_override_cfg(SATAR), + mc_make_sid_override_cfg(NVDISPLAYR), + mc_make_sid_override_cfg(VIW), + mc_make_sid_override_cfg(UFSHCR), + mc_make_sid_override_cfg(NVENCSWR), + mc_make_sid_override_cfg(AFIW), + mc_smmu_bypass_cfg, /* TBU settings */ + _END_OF_TABLE_, +}; + +/******************************************************************************* + * Handler to return the pointer to the MC's context struct + ******************************************************************************/ +mc_regs_t *plat_memctrl_get_sys_suspend_ctx(void) +{ + /* index of _END_OF_TABLE_ */ + tegra186_mc_context[0].val = (uint32_t)(ARRAY_SIZE(tegra186_mc_context)) - 1U; + + return tegra186_mc_context; +} + +void plat_memctrl_setup(void) +{ + uint32_t val; + unsigned int i; + + /* Program all the Stream ID overrides */ + for (i = 0U; i < ARRAY_SIZE(tegra186_streamid_override_regs); i++) { + tegra_mc_streamid_write_32(tegra186_streamid_override_regs[i], + MC_STREAM_ID_MAX); + } + + /* Program the security config settings for all Stream IDs */ + for (i = 0U; i < ARRAY_SIZE(tegra186_streamid_sec_cfgs); i++) { + val = (tegra186_streamid_sec_cfgs[i].override_enable << 16) | + (tegra186_streamid_sec_cfgs[i].override_client_inputs << 8) | + (tegra186_streamid_sec_cfgs[i].override_client_ns_flag << 0); + tegra_mc_streamid_write_32(tegra186_streamid_sec_cfgs[i].offset, val); + } + + /* + * All requests at boot time, and certain requests during + * normal run time, are physically addressed and must bypass + * the SMMU. The client hub logic implements a hardware bypass + * path around the Translation Buffer Units (TBU). During + * boot-time, the SMMU_BYPASS_CTRL register (which defaults to + * TBU_BYPASS mode) will be used to steer all requests around + * the uninitialized TBUs. During normal operation, this register + * is locked into TBU_BYPASS_SID config, which routes requests + * with special StreamID 0x7f on the bypass path and all others + * through the selected TBU. This is done to disable SMMU Bypass + * mode, as it could be used to circumvent SMMU security checks. + */ + tegra_mc_write_32(MC_SMMU_BYPASS_CONFIG, + MC_SMMU_BYPASS_CONFIG_SETTINGS); + + /* + * Re-configure MSS to allow ROC to deal with ordering of the + * Memory Controller traffic. This is needed as the Memory Controller + * boots with MSS having all control, but ROC provides a performance + * boost as compared to MSS. + */ + tegra186_memctrl_reconfig_mss_clients(); + + /* Program overrides for MC transactions */ + tegra186_memctrl_set_overrides(); +} + +/******************************************************************************* + * Handler to restore platform specific settings to the memory controller + ******************************************************************************/ +void plat_memctrl_restore(void) +{ + /* + * Re-configure MSS to allow ROC to deal with ordering of the + * Memory Controller traffic. This is needed as the Memory Controller + * boots with MSS having all control, but ROC provides a performance + * boost as compared to MSS. + */ + tegra186_memctrl_reconfig_mss_clients(); + + /* Program overrides for MC transactions */ + tegra186_memctrl_set_overrides(); +} + +/******************************************************************************* + * Handler to program the scratch registers with TZDRAM settings for the + * resume firmware + ******************************************************************************/ +void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes) +{ + uint32_t val; + + /* + * Setup the Memory controller to allow only secure accesses to + * the TZDRAM carveout + */ + INFO("Configuring TrustZone DRAM Memory Carveout\n"); + + tegra_mc_write_32(MC_SECURITY_CFG0_0, (uint32_t)phys_base); + tegra_mc_write_32(MC_SECURITY_CFG3_0, (uint32_t)(phys_base >> 32)); + tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20); + + /* + * When TZ encryption is enabled, we need to setup TZDRAM + * before CPU accesses TZ Carveout, else CPU will fetch + * non-decrypted data. So save TZDRAM setting for SC7 resume + * FW to restore. + * + * Scratch registers map: + * RSV55_0 = CFG1[12:0] | CFG0[31:20] + * RSV55_1 = CFG3[1:0] + */ + val = tegra_mc_read_32(MC_SECURITY_CFG1_0) & MC_SECURITY_SIZE_MB_MASK; + val |= tegra_mc_read_32(MC_SECURITY_CFG0_0) & MC_SECURITY_BOM_MASK; + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_TZDRAM_ADDR_LO, val); + + val = tegra_mc_read_32(MC_SECURITY_CFG3_0) & MC_SECURITY_BOM_HI_MASK; + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_TZDRAM_ADDR_HI, val); + + /* + * MCE propagates the security configuration values across the + * CCPLEX. + */ + (void)mce_update_gsc_tzdram(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c new file mode 100644 index 0000000..af4182e --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2015-2018, 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +extern void memcpy16(void *dest, const void *src, unsigned int length); + +/* state id mask */ +#define TEGRA186_STATE_ID_MASK 0xFU +/* constants to get power state's wake time */ +#define TEGRA186_WAKE_TIME_MASK 0x0FFFFFF0U +#define TEGRA186_WAKE_TIME_SHIFT 4U +/* default core wake mask for CPU_SUSPEND */ +#define TEGRA186_CORE_WAKE_MASK 0x180cU +/* context size to save during system suspend */ +#define TEGRA186_SE_CONTEXT_SIZE 3U + +static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE]; +static struct tegra_psci_percpu_data { + uint32_t wake_time; +} __aligned(CACHE_WRITEBACK_GRANULE) tegra_percpu_data[PLATFORM_CORE_COUNT]; + +int32_t tegra_soc_validate_power_state(uint32_t power_state, + psci_power_state_t *req_state) +{ + uint8_t state_id = (uint8_t)psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK; + uint32_t cpu = plat_my_core_pos(); + int32_t ret = PSCI_E_SUCCESS; + + /* save the core wake time (in TSC ticks)*/ + tegra_percpu_data[cpu].wake_time = (power_state & TEGRA186_WAKE_TIME_MASK) + << TEGRA186_WAKE_TIME_SHIFT; + + /* + * Clean percpu_data[cpu] to DRAM. This needs to be done to ensure that + * the correct value is read in tegra_soc_pwr_domain_suspend(), which + * is called with caches disabled. It is possible to read a stale value + * from DRAM in that function, because the L2 cache is not flushed + * unless the cluster is entering CC6/CC7. + */ + clean_dcache_range((uint64_t)&tegra_percpu_data[cpu], + sizeof(tegra_percpu_data[cpu])); + + /* Sanity check the requested state id */ + switch (state_id) { + case PSTATE_ID_CORE_IDLE: + case PSTATE_ID_CORE_POWERDN: + + if (psci_get_pstate_type(power_state) != PSTATE_TYPE_POWERDOWN) { + ret = PSCI_E_INVALID_PARAMS; + break; + } + + /* Core powerdown request */ + req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id; + req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id; + + break; + + default: + ERROR("%s: unsupported state id (%d)\n", __func__, state_id); + ret = PSCI_E_INVALID_PARAMS; + break; + } + + return ret; +} + +int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) +{ + (void)cpu_state; + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + const plat_local_state_t *pwr_domain_state; + uint8_t stateid_afflvl0, stateid_afflvl2; + uint32_t cpu = plat_my_core_pos(); + const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + mce_cstate_info_t cstate_info = { 0 }; + uint64_t mc_ctx_base; + uint32_t val; + + /* get the state ID */ + pwr_domain_state = target_state->pwr_domain_state; + stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] & + TEGRA186_STATE_ID_MASK; + stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA186_STATE_ID_MASK; + + if ((stateid_afflvl0 == PSTATE_ID_CORE_IDLE) || + (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) { + + /* Enter CPU idle/powerdown */ + val = (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ? + (uint32_t)TEGRA_ARI_CORE_C6 : (uint32_t)TEGRA_ARI_CORE_C7; + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, (uint64_t)val, + tegra_percpu_data[cpu].wake_time, 0U); + + } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + + /* save SE registers */ + se_regs[0] = mmio_read_32(TEGRA_SE0_BASE + + SE_MUTEX_WATCHDOG_NS_LIMIT); + se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE + + RNG_MUTEX_WATCHDOG_NS_LIMIT); + se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE + + PKA_MUTEX_WATCHDOG_NS_LIMIT); + + /* save 'Secure Boot' Processor Feature Config Register */ + val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG); + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val); + + /* save MC context to TZDRAM */ + mc_ctx_base = params_from_bl2->tzdram_base; + tegra_mc_save_context((uintptr_t)mc_ctx_base); + + /* Prepare for system suspend */ + cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7; + cstate_info.system = (uint32_t)TEGRA_ARI_SYSTEM_SC7; + cstate_info.system_state_force = 1; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + + /* Loop until system suspend is allowed */ + do { + val = (uint32_t)mce_command_handler( + (uint64_t)MCE_CMD_IS_SC7_ALLOWED, + (uint64_t)TEGRA_ARI_CORE_C7, + MCE_CORE_SLEEP_TIME_INFINITE, + 0U); + } while (val == 0U); + + /* Instruct the MCE to enter system suspend state */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + (uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U); + + } else { + ; /* do nothing */ + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Helper function to check if this is the last ON CPU in the cluster + ******************************************************************************/ +static bool tegra_last_cpu_in_cluster(const plat_local_state_t *states, + uint32_t ncpu) +{ + plat_local_state_t target; + bool last_on_cpu = true; + uint32_t num_cpus = ncpu, pos = 0; + + do { + target = states[pos]; + if (target != PLAT_MAX_OFF_STATE) { + last_on_cpu = false; + } + --num_cpus; + pos++; + } while (num_cpus != 0U); + + return last_on_cpu; +} + +/******************************************************************************* + * Helper function to get target power state for the cluster + ******************************************************************************/ +static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states, + uint32_t ncpu) +{ + uint32_t core_pos = (uint32_t)read_mpidr() & (uint32_t)MPIDR_CPU_MASK; + uint32_t cpu = plat_my_core_pos(); + int32_t ret; + plat_local_state_t target = states[core_pos]; + mce_cstate_info_t cstate_info = { 0 }; + + /* CPU suspend */ + if (target == PSTATE_ID_CORE_POWERDN) { + /* Program default wake mask */ + cstate_info.wake_mask = TEGRA186_CORE_WAKE_MASK; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + + /* Check if CCx state is allowed. */ + ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED, + (uint64_t)TEGRA_ARI_CORE_C7, + tegra_percpu_data[cpu].wake_time, + 0U); + if (ret == 0) { + target = PSCI_LOCAL_STATE_RUN; + } + } + + /* CPU off */ + if (target == PLAT_MAX_OFF_STATE) { + /* Enable cluster powerdn from last CPU in the cluster */ + if (tegra_last_cpu_in_cluster(states, ncpu)) { + /* Enable CC7 state and turn off wake mask */ + cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + + /* Check if CCx state is allowed. */ + ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED, + (uint64_t)TEGRA_ARI_CORE_C7, + MCE_CORE_SLEEP_TIME_INFINITE, + 0U); + if (ret == 0) { + target = PSCI_LOCAL_STATE_RUN; + } + + } else { + + /* Turn off wake_mask */ + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + target = PSCI_LOCAL_STATE_RUN; + } + } + + return target; +} + +/******************************************************************************* + * Platform handler to calculate the proper target power level at the + * specified affinity level + ******************************************************************************/ +plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, + const plat_local_state_t *states, + uint32_t ncpu) +{ + plat_local_state_t target = PSCI_LOCAL_STATE_RUN; + uint32_t cpu = plat_my_core_pos(); + + /* System Suspend */ + if ((lvl == (uint32_t)MPIDR_AFFLVL2) && + (states[cpu] == PSTATE_ID_SOC_POWERDN)) { + target = PSTATE_ID_SOC_POWERDN; + } + + /* CPU off, CPU suspend */ + if (lvl == (uint32_t)MPIDR_AFFLVL1) { + target = tegra_get_afflvl1_pwr_state(states, ncpu); + } + + /* target cluster/system state */ + return target; +} + +int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) +{ + const plat_local_state_t *pwr_domain_state = + target_state->pwr_domain_state; + const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA186_STATE_ID_MASK; + uint64_t val; + uint64_t src_len_in_bytes = (uint64_t)(((uintptr_t)(&__BL31_END__) - + (uintptr_t)BL31_BASE)); + int32_t ret; + + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + val = params_from_bl2->tzdram_base + + tegra186_get_mc_ctx_size(); + + /* Initialise communication channel with BPMP */ + assert(tegra_bpmp_ipc_init() == 0); + + /* Enable SE clock */ + ret = tegra_bpmp_ipc_enable_clock(TEGRA186_CLK_SE); + if (ret != 0) { + ERROR("Failed to enable clock\n"); + return ret; + } + + /* + * Generate/save SHA256 of ATF during SC7 entry + */ + if (tegra_se_save_sha256_hash(BL31_BASE, + (uint32_t)src_len_in_bytes) != 0) { + ERROR("Hash calculation failed. Reboot\n"); + (void)tegra_soc_prepare_system_reset(); + } + + /* + * The TZRAM loses power when we enter system suspend. To + * allow graceful exit from system suspend, we need to copy + * BL3-1 over to TZDRAM. + */ + val = params_from_bl2->tzdram_base + + tegra186_get_mc_ctx_size(); + memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE, + (uintptr_t)BL31_END - (uintptr_t)BL31_BASE); + + /* + * Save code base and size; this would be used by SC7-RF to + * verify binary + */ + mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV68_LO, + (uint32_t)val); + mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV0_HI, + (uint32_t)src_len_in_bytes); + + ret = tegra_bpmp_ipc_disable_clock(TEGRA186_CLK_SE); + if (ret != 0) { + ERROR("Failed to disable clock\n"); + return ret; + } + } + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) +{ + int32_t ret = PSCI_E_SUCCESS; + uint64_t target_cpu = mpidr & MPIDR_CPU_MASK; + uint64_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >> + MPIDR_AFFINITY_BITS; + + if (target_cluster > ((uint32_t)PLATFORM_CLUSTER_COUNT - 1U)) { + + ERROR("%s: unsupported CPU (0x%lx)\n", __func__, mpidr); + ret = PSCI_E_NOT_PRESENT; + + } else { + /* construct the target CPU # */ + target_cpu |= (target_cluster << 2); + + (void)mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U); + } + + return ret; +} + +int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + uint8_t stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; + uint8_t stateid_afflvl0 = target_state->pwr_domain_state[MPIDR_AFFLVL0]; + mce_cstate_info_t cstate_info = { 0 }; + uint64_t impl, val; + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + + impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* + * Enable ECC and Parity Protection for Cortex-A57 CPUs (Tegra186 + * A02p and beyond). + */ + if ((plat_params->l2_ecc_parity_prot_dis != 1) && (impl != DENVER_IMPL)) { + + val = read_l2ctlr_el1(); + val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT; + write_l2ctlr_el1(val); + } + + /* + * Reset power state info for CPUs when onlining, we set + * deepest power when offlining a core but that may not be + * requested by non-secure sw which controls idle states. It + * will re-init this info from non-secure software when the + * core come online. + */ + if (stateid_afflvl0 == PLAT_MAX_OFF_STATE) { + + cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC1; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + } + + /* + * Check if we are exiting from deep sleep and restore SE + * context if we are. + */ + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + + mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT, + se_regs[0]); + mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT, + se_regs[1]); + mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT, + se_regs[2]); + + /* Init SMMU */ + tegra_smmu_init(); + + /* + * Reset power state info for the last core doing SC7 + * entry and exit, we set deepest power state as CC7 + * and SC7 for SC7 entry which may not be requested by + * non-secure SW which controls idle states. + */ + cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7; + cstate_info.system = (uint32_t)TEGRA_ARI_SYSTEM_SC1; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + } + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) +{ + uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK; + + (void)target_state; + + /* Disable Denver's DCO operations */ + if (impl == DENVER_IMPL) { + denver_disable_dco(); + } + + /* Turn off CPU */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + (uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U); + + return PSCI_E_SUCCESS; +} + +__dead2 void tegra_soc_prepare_system_off(void) +{ + /* power off the entire system */ + mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF); + + wfi(); + + /* wait for the system to power down */ + for (;;) { + ; + } +} + +int32_t tegra_soc_prepare_system_reset(void) +{ + mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT); + + return PSCI_E_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c new file mode 100644 index 0000000..fbb550a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015-2018, 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 + +#define SCRATCH_SECURE_RSV1_SCRATCH_0 0x658U +#define SCRATCH_SECURE_RSV1_SCRATCH_1 0x65CU + +#define CPU_RESET_MODE_AA64 1U + +/******************************************************************************* + * Setup secondary CPU vectors + ******************************************************************************/ +void plat_secondary_setup(void) +{ + uint32_t addr_low, addr_high; + + INFO("Setting up secondary CPU boot\n"); + + /* TZDRAM base will be used as the "resume" address */ + addr_low = (uintptr_t)&tegra_secure_entrypoint | CPU_RESET_MODE_AA64; + addr_high = (uintptr_t)(((uintptr_t)&tegra_secure_entrypoint >> 32U) & 0x7ffU); + + /* save reset vector to be used during SYSTEM_SUSPEND exit */ + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO, + addr_low); + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI, + addr_high); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c new file mode 100644 index 0000000..78613e5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2015-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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern void memcpy16(void *dest, const void *src, unsigned int length); + +/******************************************************************************* + * Tegra186 CPU numbers in cluster #0 + ******************************************************************************* + */ +#define TEGRA186_CLUSTER0_CORE2 2U +#define TEGRA186_CLUSTER0_CORE3 3U + +/******************************************************************************* + * The Tegra power domain tree has a single system level power domain i.e. a + * single root node. The first entry in the power domain descriptor specifies + * the number of power domains at the highest power level. + ******************************************************************************* + */ +static const uint8_t tegra_power_domain_tree_desc[] = { + /* No of root nodes */ + 1, + /* No of clusters */ + PLATFORM_CLUSTER_COUNT, + /* No of CPU cores - cluster0 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster1 */ + PLATFORM_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the Tegra default topology tree information. + ******************************************************************************/ +const uint8_t *plat_get_power_domain_tree_desc(void) +{ + return tegra_power_domain_tree_desc; +} + +/* + * Table of regions to map using the MMU. + */ +static const mmap_region_t tegra_mmap[] = { + MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_TSA_BASE, 0x20000U, /* 128KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000U, /* 128KB - UART A, B*/ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000U, /* 128KB - UART C, G */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000U, /* 192KB - UART D, E, F */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000U, /* 128KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000U, /* 256KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_TMRUS_BASE, 0x1000U, /* 4KB */ + MT_DEVICE | MT_RO | MT_SECURE), + MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000U, /* 384KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_ARM_ACTMON_CTR_BASE, 0x20000U, /* 128KB - ARM/Denver */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x1000000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_HSP_DBELL_BASE, 0x10000U, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_BPMP_IPC_TX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_BPMP_IPC_RX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */ + MT_DEVICE | MT_RW | MT_SECURE), + {0} +}; + +/******************************************************************************* + * Set up the pagetables as per the platform memory map & initialize the MMU + ******************************************************************************/ +const mmap_region_t *plat_get_mmio_map(void) +{ + /* MMIO space */ + return tegra_mmap; +} + +/******************************************************************************* + * Handler to get the System Counter Frequency + ******************************************************************************/ +uint32_t plat_get_syscnt_freq2(void) +{ + return 31250000; +} + +/******************************************************************************* + * Maximum supported UART controllers + ******************************************************************************/ +#define TEGRA186_MAX_UART_PORTS 7 + +/******************************************************************************* + * This variable holds the UART port base addresses + ******************************************************************************/ +static uint32_t tegra186_uart_addresses[TEGRA186_MAX_UART_PORTS + 1] = { + 0, /* undefined - treated as an error case */ + TEGRA_UARTA_BASE, + TEGRA_UARTB_BASE, + TEGRA_UARTC_BASE, + TEGRA_UARTD_BASE, + TEGRA_UARTE_BASE, + TEGRA_UARTF_BASE, + TEGRA_UARTG_BASE, +}; + +/******************************************************************************* + * Enable console corresponding to the console ID + ******************************************************************************/ +void plat_enable_console(int32_t id) +{ + static console_t uart_console; + uint32_t console_clock; + + if ((id > 0) && (id < TEGRA186_MAX_UART_PORTS)) { + /* + * Reference clock used by the FPGAs is a lot slower. + */ + if (tegra_platform_is_fpga()) { + console_clock = TEGRA_BOOT_UART_CLK_13_MHZ; + } else { + console_clock = TEGRA_BOOT_UART_CLK_408_MHZ; + } + + (void)console_16550_register(tegra186_uart_addresses[id], + console_clock, + TEGRA_CONSOLE_BAUDRATE, + &uart_console); + console_set_scope(&uart_console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH); + } +} + +/******************************************************************************* + * Handler for early platform setup + ******************************************************************************/ +void plat_early_platform_setup(void) +{ + uint64_t impl, val; + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + const struct tegra_bl31_params *arg_from_bl2 = plat_get_bl31_params(); + + /* Verify chip id is t186 */ + assert(tegra_chipid_is_t186()); + + /* sanity check MCE firmware compatibility */ + mce_verify_firmware_version(); + + /* + * Do initial security configuration to allow DRAM/device access. + */ + tegra_memctrl_tzdram_setup(plat_params->tzdram_base, + (uint32_t)plat_params->tzdram_size); + + impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK; + + /* + * Enable ECC and Parity Protection for Cortex-A57 CPUs (Tegra186 + * A02p and beyond). + */ + if ((plat_params->l2_ecc_parity_prot_dis != 1) && + (impl != (uint64_t)DENVER_IMPL)) { + + val = read_l2ctlr_el1(); + val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT; + write_l2ctlr_el1(val); + } + + /* + * The previous bootloader might not have placed the BL32 image + * inside the TZDRAM. Platform handler to allow relocation of BL32 + * image to TZDRAM memory. This behavior might change per platform. + */ + plat_relocate_bl32_image(arg_from_bl2->bl32_image_info); +} + +/******************************************************************************* + * Handler for late platform setup + ******************************************************************************/ +void plat_late_platform_setup(void) +{ + const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + int ret; + + /* Initialize SMMU registers */ + tegra_smmu_init(); + + /* map TZDRAM used by BL31 as coherent memory */ + ret = mmap_add_dynamic_region(params_from_bl2->tzdram_base, + params_from_bl2->tzdram_base, + BL31_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + assert(ret == 0); +} + +/* Secure IRQs for Tegra186 */ +static const interrupt_prop_t tegra186_interrupt_props[] = { + INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(TEGRA186_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(TEGRA186_AON_WDT_IRQ, PLAT_TEGRA_WDT_PRIO, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE) +}; + +/******************************************************************************* + * Initialize the GIC and SGIs + ******************************************************************************/ +void plat_gic_setup(void) +{ + tegra_gic_setup(tegra186_interrupt_props, ARRAY_SIZE(tegra186_interrupt_props)); + tegra_gic_init(); + + /* + * Initialize the FIQ handler only if the platform supports any + * FIQ interrupt sources. + */ + tegra_fiq_handler_setup(); +} + +/******************************************************************************* + * Return pointer to the BL31 params from previous bootloader + ******************************************************************************/ +struct tegra_bl31_params *plat_get_bl31_params(void) +{ + uint32_t val; + + val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_ADDR); + + return (struct tegra_bl31_params *)(uintptr_t)val; +} + +/******************************************************************************* + * Return pointer to the BL31 platform params from previous bootloader + ******************************************************************************/ +plat_params_from_bl2_t *plat_get_bl31_plat_params(void) +{ + uint32_t val; + + val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_ADDR); + + return (plat_params_from_bl2_t *)(uintptr_t)val; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int32_t plat_core_pos_by_mpidr(u_register_t mpidr) +{ + u_register_t cluster_id, cpu_id, pos; + int32_t ret; + + cluster_id = (mpidr >> (u_register_t)MPIDR_AFF1_SHIFT) & (u_register_t)MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> (u_register_t)MPIDR_AFF0_SHIFT) & (u_register_t)MPIDR_AFFLVL_MASK; + + /* + * Validate cluster_id by checking whether it represents + * one of the two clusters present on the platform. + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if ((cluster_id >= (u_register_t)PLATFORM_CLUSTER_COUNT) || + (cpu_id >= (u_register_t)PLATFORM_MAX_CPUS_PER_CLUSTER)) { + ret = PSCI_E_NOT_PRESENT; + } else { + /* calculate the core position */ + pos = cpu_id + (cluster_id << 2U); + + /* check for non-existent CPUs */ + if ((pos == TEGRA186_CLUSTER0_CORE2) || (pos == TEGRA186_CLUSTER0_CORE3)) { + ret = PSCI_E_NOT_PRESENT; + } else { + ret = (int32_t)pos; + } + } + + return ret; +} + +/******************************************************************************* + * Handler to relocate BL32 image to TZDRAM + ******************************************************************************/ +void plat_relocate_bl32_image(const image_info_t *bl32_img_info) +{ + const plat_params_from_bl2_t *plat_bl31_params = plat_get_bl31_plat_params(); + const entry_point_info_t *bl32_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end; + + if ((bl32_img_info != NULL) && (bl32_ep_info != NULL)) { + + /* Relocate BL32 if it resides outside of the TZDRAM */ + tzdram_start = plat_bl31_params->tzdram_base; + tzdram_end = plat_bl31_params->tzdram_base + + plat_bl31_params->tzdram_size; + bl32_start = bl32_img_info->image_base; + bl32_end = bl32_img_info->image_base + bl32_img_info->image_size; + + assert(tzdram_end > tzdram_start); + assert(bl32_end > bl32_start); + assert(bl32_ep_info->pc > tzdram_start); + assert(bl32_ep_info->pc < tzdram_end); + + /* relocate BL32 */ + if ((bl32_start >= tzdram_end) || (bl32_end <= tzdram_start)) { + + INFO("Relocate BL32 to TZDRAM\n"); + + (void)memcpy16((void *)(uintptr_t)bl32_ep_info->pc, + (void *)(uintptr_t)bl32_start, + bl32_img_info->image_size); + + /* clean up non-secure intermediate buffer */ + zeromem((void *)(uintptr_t)bl32_start, + bl32_img_info->image_size); + } + } +} + +/******************************************************************************* + * Handler to indicate support for System Suspend + ******************************************************************************/ +bool plat_supports_system_suspend(void) +{ + return true; +} +/******************************************************************************* + * Platform specific runtime setup. + ******************************************************************************/ +void plat_runtime_setup(void) +{ + /* + * During cold boot, it is observed that the arbitration + * bit is set in the Memory controller leading to false + * error interrupts in the non-secure world. To avoid + * this, clean the interrupt status register before + * booting into the non-secure world + */ + tegra_memctrl_clear_pending_interrupts(); + + /* + * During boot, USB3 and flash media (SDMMC/SATA) devices need + * access to IRAM. Because these clients connect to the MC and + * do not have a direct path to the IRAM, the MC implements AHB + * redirection during boot to allow path to IRAM. In this mode + * accesses to a programmed memory address aperture are directed + * to the AHB bus, allowing access to the IRAM. This mode must be + * disabled before we jump to the non-secure world. + */ + tegra_memctrl_disable_ahb_redirection(); + + /* + * Verify the integrity of the previously configured SMMU(s) + * settings + */ + tegra_smmu_verify(); +} + +/******************************************************************************* + * Return pointer to the bpmp_ipc_data + ******************************************************************************/ +static struct bpmp_ipc_platform_data bpmp_ipc; +struct bpmp_ipc_platform_data *plat_get_bpmp_ipc_data(void) +{ + bpmp_ipc.bpmp_ipc_tx_base = TEGRA_BPMP_IPC_TX_PHYS_BASE; + bpmp_ipc.bpmp_ipc_rx_base = TEGRA_BPMP_IPC_RX_PHYS_BASE; + bpmp_ipc.bpmp_ipc_map_size = TEGRA_BPMP_IPC_CH_MAP_SIZE; + + return &bpmp_ipc; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c new file mode 100644 index 0000000..4de8a9e --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015-2016, 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 + +/******************************************************************************* + * Offset to read the ref_clk counter value + ******************************************************************************/ +#define REF_CLK_OFFSET 4ULL + +/******************************************************************************* + * Tegra186 SiP SMCs + ******************************************************************************/ +#define TEGRA_SIP_GET_ACTMON_CLK_COUNTERS 0xC2FFFE02 +#define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0xC2FFFF00 +#define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0xC2FFFF01 +#define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0xC2FFFF02 +#define TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS 0xC2FFFF03 +#define TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS 0xC2FFFF04 +#define TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED 0xC2FFFF05 + +#define TEGRA_SIP_MCE_CMD_CC3_CTRL 0xC2FFFF07 +#define TEGRA_SIP_MCE_CMD_ECHO_DATA 0xC2FFFF08 +#define TEGRA_SIP_MCE_CMD_READ_VERSIONS 0xC2FFFF09 +#define TEGRA_SIP_MCE_CMD_ENUM_FEATURES 0xC2FFFF0A +#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS 0xC2FFFF0B +#define TEGRA_SIP_MCE_CMD_ENUM_READ_MCA 0xC2FFFF0C +#define TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA 0xC2FFFF0D +#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE 0xC2FFFF0E +#define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE 0xC2FFFF0F +#define TEGRA_SIP_MCE_CMD_ENABLE_LATIC 0xC2FFFF10 +#define TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ 0xC2FFFF11 +#define TEGRA_SIP_MCE_CMD_MISC_CCPLEX 0xC2FFFF12 + +/******************************************************************************* + * This function is responsible for handling all T186 SiP calls + ******************************************************************************/ +int32_t plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + const void *cookie, + void *handle, + uint64_t flags) +{ + int32_t mce_ret, ret = 0; + uint32_t impl, cpu; + uint32_t base, core_clk_ctr, ref_clk_ctr; + uint32_t local_smc_fid = smc_fid; + uint64_t local_x1 = x1, local_x2 = x2, local_x3 = x3; + + (void)x4; + (void)cookie; + (void)flags; + + if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { + /* 32-bit function, clear top parameter bits */ + + local_x1 = (uint32_t)x1; + local_x2 = (uint32_t)x2; + local_x3 = (uint32_t)x3; + } + + /* + * Convert SMC FID to SMC64, to support SMC32/SMC64 configurations + */ + local_smc_fid |= (SMC_64 << FUNCID_CC_SHIFT); + + switch (local_smc_fid) { + /* + * Micro Coded Engine (MCE) commands reside in the 0x82FFFF00 - + * 0x82FFFFFF SiP SMC space + */ + case TEGRA_SIP_MCE_CMD_ENTER_CSTATE: + case TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO: + case TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME: + case TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS: + case TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS: + case TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED: + case TEGRA_SIP_MCE_CMD_CC3_CTRL: + case TEGRA_SIP_MCE_CMD_ECHO_DATA: + case TEGRA_SIP_MCE_CMD_READ_VERSIONS: + case TEGRA_SIP_MCE_CMD_ENUM_FEATURES: + case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS: + case TEGRA_SIP_MCE_CMD_ENUM_READ_MCA: + case TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA: + case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE: + case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE: + case TEGRA_SIP_MCE_CMD_ENABLE_LATIC: + case TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ: + case TEGRA_SIP_MCE_CMD_MISC_CCPLEX: + + /* clean up the high bits */ + local_smc_fid &= MCE_CMD_MASK; + + /* execute the command and store the result */ + mce_ret = mce_command_handler(local_smc_fid, local_x1, local_x2, local_x3); + write_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X0, (uint64_t)(mce_ret)); + break; + + /* + * This function ID reads the Activity monitor's core/ref clock + * counter values for a core/cluster. + * + * x1 = MPIDR of the target core + * x2 = MIDR of the target core + */ + case TEGRA_SIP_GET_ACTMON_CLK_COUNTERS: + + cpu = (uint32_t)x1 & MPIDR_CPU_MASK; + impl = ((uint32_t)x2 >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* sanity check target CPU number */ + if (cpu > (uint32_t)PLATFORM_MAX_CPUS_PER_CLUSTER) { + ret = -EINVAL; + } else { + /* get the base address for the current CPU */ + base = (impl == DENVER_IMPL) ? TEGRA_DENVER_ACTMON_CTR_BASE : + TEGRA_ARM_ACTMON_CTR_BASE; + + /* read the clock counter values */ + core_clk_ctr = mmio_read_32(base + (8ULL * cpu)); + ref_clk_ctr = mmio_read_32(base + (8ULL * cpu) + REF_CLK_OFFSET); + + /* return the counter values as two different parameters */ + write_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X1, (core_clk_ctr)); + write_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X2, (ref_clk_ctr)); + } + + break; + + default: + ret = -ENOTSUP; + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c new file mode 100644 index 0000000..f1bc235 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017, 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 + +#define MAX_NUM_SMMU_DEVICES U(1) + +/******************************************************************************* + * Handler to return the support SMMU devices number + ******************************************************************************/ +uint32_t plat_get_num_smmu_devices(void) +{ + return MAX_NUM_SMMU_DEVICES; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S new file mode 100644 index 0000000..2fc2046 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S @@ -0,0 +1,41 @@ +/* + * 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 + +#define TEGRA186_MC_CTX_SIZE 0x93 + + .globl tegra186_get_mc_ctx_size + + /* + * Tegra186 reset data (offset 0x0 - 0x420) + * + * 0x000: MC context start + * 0x420: MC context end + */ + + .align 4 +__tegra186_mc_context: + .rept TEGRA186_MC_CTX_SIZE + .quad 0 + .endr + + .align 4 +__tegra186_mc_context_end: + +/* return the size of the MC context */ +func tegra186_get_mc_ctx_size + adr x0, __tegra186_mc_context_end + adr x1, __tegra186_mc_context + sub x0, x0, x1 + ret +endfunc tegra186_get_mc_ctx_size diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/platform_t186.mk b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/platform_t186.mk new file mode 100644 index 0000000..4ad02a7 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -0,0 +1,80 @@ +# +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# platform configs +ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS := 1 +$(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS)) + +ENABLE_CHIP_VERIFICATION_HARNESS := 0 +$(eval $(call add_define,ENABLE_CHIP_VERIFICATION_HARNESS)) + +RESET_TO_BL31 := 1 + +PROGRAMMABLE_RESET_ADDRESS := 0 + +COLD_BOOT_SINGLE_CPU := 1 + +RELOCATE_BL32_IMAGE := 1 + +# platform settings +PLAT_BL31_BASE := 0x30000000 +$(eval $(call add_define,PLAT_BL31_BASE)) + +PLATFORM_CLUSTER_COUNT := 2 +$(eval $(call add_define,PLATFORM_CLUSTER_COUNT)) + +PLATFORM_MAX_CPUS_PER_CLUSTER := 4 +$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER)) + +MAX_XLAT_TABLES := 25 +$(eval $(call add_define,MAX_XLAT_TABLES)) + +MAX_MMAP_REGIONS := 30 +$(eval $(call add_define,MAX_MMAP_REGIONS)) + +# include common makefiles +include plat/nvidia/tegra/common/tegra_common.mk + +# platform files +PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t186 \ + -I${SOC_DIR}/drivers/include + +BL31_SOURCES += ${TEGRA_GICv2_SOURCES} \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/cpus/aarch64/denver.S \ + lib/cpus/aarch64/cortex_a57.S \ + ${TEGRA_DRIVERS}/bpmp_ipc/intf.c \ + ${TEGRA_DRIVERS}/bpmp_ipc/ivc.c \ + ${TEGRA_DRIVERS}/gpcdma/gpcdma.c \ + ${TEGRA_DRIVERS}/memctrl/memctrl_v2.c \ + ${TEGRA_DRIVERS}/smmu/smmu.c \ + ${SOC_DIR}/drivers/mce/mce.c \ + ${SOC_DIR}/drivers/mce/ari.c \ + ${SOC_DIR}/drivers/mce/nvg.c \ + ${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \ + $(SOC_DIR)/drivers/se/se.c \ + ${SOC_DIR}/plat_memctrl.c \ + ${SOC_DIR}/plat_psci_handlers.c \ + ${SOC_DIR}/plat_setup.c \ + ${SOC_DIR}/plat_secondary.c \ + ${SOC_DIR}/plat_sip_calls.c \ + ${SOC_DIR}/plat_smmu.c \ + ${SOC_DIR}/plat_trampoline.S + +# Enable workarounds for selected Cortex-A57 erratas. +A57_DISABLE_NON_TEMPORAL_HINT := 1 +ERRATA_A57_806969 := 1 +ERRATA_A57_813419 := 1 +ERRATA_A57_813420 := 1 +ERRATA_A57_826974 := 1 +ERRATA_A57_826977 := 1 +ERRATA_A57_828024 := 1 +ERRATA_A57_829520 := 1 +ERRATA_A57_833471 := 1 + +# Enable higher performance Non-cacheable load forwarding +A57_ENABLE_NONCACHEABLE_LOAD_FWD := 1 diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h new file mode 100644 index 0000000..ef16980 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCE_PRIVATE_H +#define MCE_PRIVATE_H + +#include +#include + +/******************************************************************************* + * Macros to prepare CSTATE info request + ******************************************************************************/ +/* Description of the parameters for UPDATE_CSTATE_INFO request */ +#define CLUSTER_CSTATE_MASK 0x7U +#define CLUSTER_CSTATE_SHIFT 0X0U +#define CLUSTER_CSTATE_UPDATE_BIT (1U << 7) +#define CCPLEX_CSTATE_MASK 0x7U +#define CCPLEX_CSTATE_SHIFT 8U +#define CCPLEX_CSTATE_UPDATE_BIT (1U << 15) +#define SYSTEM_CSTATE_MASK 0xFU +#define SYSTEM_CSTATE_SHIFT 16U +#define SYSTEM_CSTATE_UPDATE_BIT (1U << 23) +#define CSTATE_WAKE_MASK_UPDATE_BIT (1U << 31) +#define CSTATE_WAKE_MASK_SHIFT 32U +#define CSTATE_WAKE_MASK_CLEAR 0xFFFFFFFFU + +/******************************************************************************* + * Core ID mask (bits 3:0 in the online request) + ******************************************************************************/ +#define MCE_CORE_ID_MASK 0xFU + +/******************************************************************************* + * C-state statistics macros + ******************************************************************************/ +#define MCE_STAT_ID_SHIFT 16U + +/******************************************************************************* + * Security config macros + ******************************************************************************/ +#define STRICT_CHECKING_ENABLED_SET (1UL << 0) +#define STRICT_CHECKING_LOCKED_SET (1UL << 1) + +/* declarations for NVG handler functions */ +uint64_t nvg_get_version(void); +void nvg_set_wake_time(uint32_t wake_time); +void nvg_update_cstate_info(uint32_t cluster, uint32_t ccplex, + uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask); +int32_t nvg_set_cstate_stat_query_value(uint64_t data); +uint64_t nvg_get_cstate_stat_query_value(void); +int32_t nvg_is_sc7_allowed(void); +int32_t nvg_online_core(uint32_t core); +int32_t nvg_update_ccplex_gsc(uint32_t gsc_idx); +int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time); +int32_t nvg_roc_clean_cache_trbits(void); +void nvg_enable_strict_checking_mode(void); +void nvg_verify_strict_checking_mode(void); +void nvg_system_shutdown(void); +void nvg_system_reboot(void); +void nvg_clear_hsm_corr_status(void); + +/* declarations for assembly functions */ +void nvg_set_request_data(uint64_t req, uint64_t data); +void nvg_set_request(uint64_t req); +uint64_t nvg_get_result(void); +uint64_t nvg_cache_clean(void); +uint64_t nvg_cache_clean_inval(void); +uint64_t nvg_cache_inval_all(void); + +/* MCE helper functions */ +void mce_enable_strict_checking(void); +void mce_verify_strict_checking(void); +void mce_system_shutdown(void); +void mce_system_reboot(void); +void mce_clear_hsm_corr_status(void); + +#endif /* MCE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h new file mode 100644 index 0000000..7de55a7 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SE_H +#define SE_H + +int32_t tegra_se_calculate_save_sha256(uint64_t src_addr, + uint32_t src_len_inbyte); +int32_t tegra_se_suspend(void); +void tegra_se_resume(void); + +#endif /* SE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h new file mode 100644 index 0000000..7a68a43 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef T194_NVG_H +#define T194_NVG_H + +#include + +/** + * t194_nvg.h - Header for the NVIDIA Generic interface (NVG). + * Official documentation for this interface is included as part + * of the T194 TRM. + */ + +/** + * Current version - Major version increments may break backwards + * compatiblity and binary compatibility. Minor version increments + * occur when there is only new functionality. + */ +enum { + TEGRA_NVG_VERSION_MAJOR = U(6), + TEGRA_NVG_VERSION_MINOR = U(7) +}; + +typedef enum { + TEGRA_NVG_CHANNEL_VERSION = U(0), + TEGRA_NVG_CHANNEL_POWER_PERF = U(1), + TEGRA_NVG_CHANNEL_POWER_MODES = U(2), + TEGRA_NVG_CHANNEL_WAKE_TIME = U(3), + TEGRA_NVG_CHANNEL_CSTATE_INFO = U(4), + TEGRA_NVG_CHANNEL_CROSSOVER_C6_LOWER_BOUND = U(5), + TEGRA_NVG_CHANNEL_CROSSOVER_CC6_LOWER_BOUND = U(6), + TEGRA_NVG_CHANNEL_CROSSOVER_CG7_LOWER_BOUND = U(8), + TEGRA_NVG_CHANNEL_CSTATE_STAT_QUERY_REQUEST = U(10), + TEGRA_NVG_CHANNEL_CSTATE_STAT_QUERY_VALUE = U(11), + TEGRA_NVG_CHANNEL_NUM_CORES = U(20), + TEGRA_NVG_CHANNEL_UNIQUE_LOGICAL_ID = U(21), + TEGRA_NVG_CHANNEL_LOGICAL_TO_PHYSICAL_MAPPING = U(22), + TEGRA_NVG_CHANNEL_LOGICAL_TO_MPIDR = U(23), + TEGRA_NVG_CHANNEL_SHUTDOWN = U(42), + TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED = U(43), + TEGRA_NVG_CHANNEL_ONLINE_CORE = U(44), + TEGRA_NVG_CHANNEL_CC3_CTRL = U(45), + TEGRA_NVG_CHANNEL_CCPLEX_CACHE_CONTROL = U(49), + TEGRA_NVG_CHANNEL_UPDATE_CCPLEX_GSC = U(50), + TEGRA_NVG_CHANNEL_HSM_ERROR_CTRL = U(53), + TEGRA_NVG_CHANNEL_SECURITY_CONFIG = U(54), + TEGRA_NVG_CHANNEL_DEBUG_CONFIG = U(55), + TEGRA_NVG_CHANNEL_DDA_SNOC_MCF = U(56), + TEGRA_NVG_CHANNEL_DDA_MCF_ORD1 = U(57), + TEGRA_NVG_CHANNEL_DDA_MCF_ORD2 = U(58), + TEGRA_NVG_CHANNEL_DDA_MCF_ORD3 = U(59), + TEGRA_NVG_CHANNEL_DDA_MCF_ISO = U(60), + TEGRA_NVG_CHANNEL_DDA_MCF_SISO = U(61), + TEGRA_NVG_CHANNEL_DDA_MCF_NISO = U(62), + TEGRA_NVG_CHANNEL_DDA_MCF_NISO_REMOTE = U(63), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_ISO = U(64), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_SISO = U(65), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_NISO = U(66), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_NISO_REMOTE = U(67), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3FILL = U(68), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3WR = U(69), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_RSP_L3RD_DMA = U(70), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_RSP_MCFRD_DMA = U(71), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_GLOBAL = U(72), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_LL = U(73), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3D = U(74), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_FCM_RD = U(75), + TEGRA_NVG_CHANNEL_DDA_L3CTRL_FCM_WR = U(76), + TEGRA_NVG_CHANNEL_DDA_SNOC_GLOBAL_CTRL = U(77), + TEGRA_NVG_CHANNEL_DDA_SNOC_CLIENT_REQ_CTRL = U(78), + TEGRA_NVG_CHANNEL_DDA_SNOC_CLIENT_REPLENTISH_CTRL = U(79), + TEGRA_NVG_CHANNEL_RT_SAFE_MASK = U(80), + TEGRA_NVG_CHANNEL_RT_WINDOW_US = U(81), + TEGRA_NVG_CHANNEL_RT_FWD_PROGRESS_US = U(82), + + TEGRA_NVG_CHANNEL_LAST_INDEX +} tegra_nvg_channel_id_t; + +typedef enum { + NVG_STAT_QUERY_SC7_ENTRIES = U(1), + NVG_STAT_QUERY_CC6_ENTRIES = U(6), + NVG_STAT_QUERY_CG7_ENTRIES = U(7), + NVG_STAT_QUERY_C6_ENTRIES = U(10), + NVG_STAT_QUERY_C7_ENTRIES = U(14), + NVG_STAT_QUERY_SC7_RESIDENCY_SUM = U(32), + NVG_STAT_QUERY_CC6_RESIDENCY_SUM = U(41), + NVG_STAT_QUERY_CG7_RESIDENCY_SUM = U(46), + NVG_STAT_QUERY_C6_RESIDENCY_SUM = U(51), + NVG_STAT_QUERY_C7_RESIDENCY_SUM = U(56), + NVG_STAT_QUERY_SC7_ENTRY_TIME_SUM = U(60), + NVG_STAT_QUERY_CC6_ENTRY_TIME_SUM = U(61), + NVG_STAT_QUERY_CG7_ENTRY_TIME_SUM = U(62), + NVG_STAT_QUERY_C6_ENTRY_TIME_SUM = U(63), + NVG_STAT_QUERY_C7_ENTRY_TIME_SUM = U(64), + NVG_STAT_QUERY_SC7_EXIT_TIME_SUM = U(70), + NVG_STAT_QUERY_CC6_EXIT_TIME_SUM = U(71), + NVG_STAT_QUERY_CG7_EXIT_TIME_SUM = U(72), + NVG_STAT_QUERY_C6_EXIT_TIME_SUM = U(73), + NVG_STAT_QUERY_C7_EXIT_TIME_SUM = U(74), + NVG_STAT_QUERY_SC7_ENTRY_LAST = U(80), + NVG_STAT_QUERY_CC6_ENTRY_LAST = U(81), + NVG_STAT_QUERY_CG7_ENTRY_LAST = U(82), + NVG_STAT_QUERY_C6_ENTRY_LAST = U(83), + NVG_STAT_QUERY_C7_ENTRY_LAST = U(84), + NVG_STAT_QUERY_SC7_EXIT_LAST = U(90), + NVG_STAT_QUERY_CC6_EXIT_LAST = U(91), + NVG_STAT_QUERY_CG7_EXIT_LAST = U(92), + NVG_STAT_QUERY_C6_EXIT_LAST = U(93), + NVG_STAT_QUERY_C7_EXIT_LAST = U(94) + +} tegra_nvg_stat_query_t; + +typedef enum { + TEGRA_NVG_CORE_C0 = U(0), + TEGRA_NVG_CORE_C1 = U(1), + TEGRA_NVG_CORE_C6 = U(6), + TEGRA_NVG_CORE_C7 = U(7), + TEGRA_NVG_CORE_WARMRSTREQ = U(8) +} tegra_nvg_core_sleep_state_t; + +typedef enum { + TEGRA_NVG_SHUTDOWN = U(0), + TEGRA_NVG_REBOOT = U(1) +} tegra_nvg_shutdown_reboot_state_t; + +typedef enum { + TEGRA_NVG_CLUSTER_CC0 = U(0), + TEGRA_NVG_CLUSTER_AUTO_CC1 = U(1), + TEGRA_NVG_CLUSTER_CC6 = U(6) +} tegra_nvg_cluster_sleep_state_t; + +typedef enum { + TEGRA_NVG_CG_CG0 = U(0), + TEGRA_NVG_CG_CG7 = U(7) +} tegra_nvg_cluster_group_sleep_state_t; + +typedef enum { + TEGRA_NVG_SYSTEM_SC0 = U(0), + TEGRA_NVG_SYSTEM_SC7 = U(7), + TEGRA_NVG_SYSTEM_SC8 = U(8) +} tegra_nvg_system_sleep_state_t; + +// --------------------------------------------------------------------------- +// NVG Data subformats +// --------------------------------------------------------------------------- + +typedef union { + uint64_t flat; + struct nvg_version_channel_t { + uint32_t minor_version : U(32); + uint32_t major_version : U(32); + } bits; +} nvg_version_data_t; + +typedef union { + uint64_t flat; + struct { + uint32_t perf_per_watt : U(1); + uint32_t reserved_31_1 : U(31); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_power_perf_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t low_battery : U(1); + uint32_t reserved_1_1 : U(1); + uint32_t battery_save : U(1); + uint32_t reserved_31_3 : U(29); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_power_modes_channel_t; + +typedef union nvg_channel_1_data_u { + uint64_t flat; + struct nvg_channel_1_data_s { + uint32_t perf_per_watt_mode : U(1); + uint32_t reserved_31_1 : U(31); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_channel_1_data_t; + +typedef union { + uint64_t flat; + struct { + uint32_t gpu_ways : U(5); + uint32_t reserved_7_5 : U(3); + uint32_t gpu_only_ways : U(5); + uint32_t reserved_31_13 : U(19); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_ccplex_cache_control_channel_t; + +typedef union nvg_channel_2_data_u { + uint64_t flat; + struct nvg_channel_2_data_s { + uint32_t reserved_1_0 : U(2); + uint32_t battery_saver_mode : U(1); + uint32_t reserved_31_3 : U(29); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_channel_2_data_t; + +typedef union { + uint64_t flat; + struct { + uint32_t wake_time : U(32); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_wake_time_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t cluster_state : U(3); + uint32_t reserved_6_3 : U(4); + uint32_t update_cluster : U(1); + uint32_t cg_cstate : U(3); + uint32_t reserved_14_11 : U(4); + uint32_t update_cg : U(1); + uint32_t system_cstate : U(4); + uint32_t reserved_22_20 : U(3); + uint32_t update_system : U(1); + uint32_t reserved_30_24 : U(7); + uint32_t update_wake_mask : U(1); + union { + uint32_t flat : U(32); + struct { + uint32_t vfiq : U(1); + uint32_t virq : U(1); + uint32_t fiq : U(1); + uint32_t irq : U(1); + uint32_t serror : U(1); + uint32_t reserved_10_5 : U(6); + uint32_t fiqout : U(1); + uint32_t irqout : U(1); + uint32_t reserved_31_13 : U(19); + } carmel; + } wake_mask; + } bits; +} nvg_cstate_info_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t crossover_value : U(32); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_lower_bound_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t unit_id : U(4); + uint32_t reserved_15_4 : U(12); + uint32_t stat_id : U(16); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_cstate_stat_query_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t num_cores : U(4); + uint32_t reserved_31_4 : U(28); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_num_cores_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t unique_core_id : U(3); + uint32_t reserved_31_3 : U(29); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_unique_logical_id_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t lcore0_pcore_id : U(4); + uint32_t lcore1_pcore_id : U(4); + uint32_t lcore2_pcore_id : U(4); + uint32_t lcore3_pcore_id : U(4); + uint32_t lcore4_pcore_id : U(4); + uint32_t lcore5_pcore_id : U(4); + uint32_t lcore6_pcore_id : U(4); + uint32_t lcore7_pcore_id : U(4); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_logical_to_physical_mappings_channel_t; + +typedef union { + uint64_t flat; + struct nvg_logical_to_mpidr_channel_write_t { + uint32_t lcore_id : U(3); + uint32_t reserved_31_3 : U(29); + uint32_t reserved_63_32 : U(32); + } write; + struct nvg_logical_to_mpidr_channel_read_t { + uint32_t mpidr : U(32); + uint32_t reserved_63_32 : U(32); + } read; +} nvg_logical_to_mpidr_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t is_sc7_allowed : U(1); + uint32_t reserved_31_1 : U(31); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_is_sc7_allowed_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t core_id : U(4); + uint32_t reserved_31_4 : U(28); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_core_online_channel_t; + +typedef union { + uint64_t flat; + struct { + uint32_t freq_req : U(9); + uint32_t reserved_30_9 : U(22); + uint32_t enable : U(1); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_cc3_control_channel_t; + +typedef enum { + TEGRA_NVG_CHANNEL_UPDATE_GSC_ALL = U(0), + TEGRA_NVG_CHANNEL_UPDATE_GSC_NVDEC = U(1), + TEGRA_NVG_CHANNEL_UPDATE_GSC_WPR1 = U(2), + TEGRA_NVG_CHANNEL_UPDATE_GSC_WPR2 = U(3), + TEGRA_NVG_CHANNEL_UPDATE_GSC_TSECA = U(4), + TEGRA_NVG_CHANNEL_UPDATE_GSC_TSECB = U(5), + TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP = U(6), + TEGRA_NVG_CHANNEL_UPDATE_GSC_APE = U(7), + TEGRA_NVG_CHANNEL_UPDATE_GSC_SPE = U(8), + TEGRA_NVG_CHANNEL_UPDATE_GSC_SCE = U(9), + TEGRA_NVG_CHANNEL_UPDATE_GSC_APR = U(10), + TEGRA_NVG_CHANNEL_UPDATE_GSC_TZRAM = U(11), + TEGRA_NVG_CHANNEL_UPDATE_GSC_IPC_SE_TSEC = U(12), + TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_RCE = U(13), + TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_MCE = U(14), + TEGRA_NVG_CHANNEL_UPDATE_GSC_SE_SC7 = U(15), + TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_SPE = U(16), + TEGRA_NVG_CHANNEL_UPDATE_GSC_RCE = U(17), + TEGRA_NVG_CHANNEL_UPDATE_GSC_CPU_TZ_TO_BPMP = U(18), + TEGRA_NVG_CHANNEL_UPDATE_GSC_VM_ENCR1 = U(19), + TEGRA_NVG_CHANNEL_UPDATE_GSC_CPU_NS_TO_BPMP = U(20), + TEGRA_NVG_CHANNEL_UPDATE_GSC_OEM_SC7 = U(21), + TEGRA_NVG_CHANNEL_UPDATE_GSC_IPC_SE_SPE_SCE_BPMP = U(22), + TEGRA_NVG_CHANNEL_UPDATE_GSC_SC7_RESUME_FW = U(23), + TEGRA_NVG_CHANNEL_UPDATE_GSC_CAMERA_TASKLIST = U(24), + TEGRA_NVG_CHANNEL_UPDATE_GSC_XUSB = U(25), + TEGRA_NVG_CHANNEL_UPDATE_GSC_CV = U(26), + TEGRA_NVG_CHANNEL_UPDATE_GSC_VM_ENCR2 = U(27), + TEGRA_NVG_CHANNEL_UPDATE_GSC_HYPERVISOR_SW = U(28), + TEGRA_NVG_CHANNEL_UPDATE_GSC_SMMU_PAGETABLES = U(29), + TEGRA_NVG_CHANNEL_UPDATE_GSC_30 = U(30), + TEGRA_NVG_CHANNEL_UPDATE_GSC_31 = U(31), + TEGRA_NVG_CHANNEL_UPDATE_GSC_TZ_DRAM = U(32), + TEGRA_NVG_CHANNEL_UPDATE_GSC_NVLINK = U(33), + TEGRA_NVG_CHANNEL_UPDATE_GSC_SBS = U(34), + TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR = U(35), + TEGRA_NVG_CHANNEL_UPDATE_GSC_LAST_INDEX +} tegra_nvg_channel_update_gsc_gsc_enum_t; + +typedef union { + uint64_t flat; + struct { + uint32_t gsc_enum : U(16); + uint32_t reserved_31_16 : U(16); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_update_ccplex_gsc_channel_t; + +typedef union { + uint64_t flat; + struct nvg_security_config_channel_t { + uint32_t strict_checking_enabled : U(1); + uint32_t strict_checking_locked : U(1); + uint32_t reserved_31_2 : U(30); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_security_config_t; + +typedef union { + uint64_t flat; + struct nvg_shutdown_channel_t { + uint32_t reboot : U(1); + uint32_t reserved_31_1 : U(31); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_shutdown_t; + +typedef union { + uint64_t flat; + struct nvg_debug_config_channel_t { + uint32_t enter_debug_state_on_mca : U(1); + uint32_t reserved_31_1 : U(31); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_debug_config_t; + +typedef union { + uint64_t flat; + struct { + uint32_t uncorr : U(1); + uint32_t corr : U(1); + uint32_t reserved_31_2 : U(30); + uint32_t reserved_63_32 : U(32); + } bits; +} nvg_hsm_error_ctrl_channel_t; + +extern nvg_debug_config_t nvg_debug_config; + +#endif /* T194_NVG_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S new file mode 100644 index 0000000..3c47208 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl nvg_set_request_data + .globl nvg_set_request + .globl nvg_get_result + .globl nvg_cache_clean + .globl nvg_cache_clean_inval + .globl nvg_cache_inval_all + +/* void nvg_set_request_data(uint64_t req, uint64_t data) */ +func nvg_set_request_data + msr s3_0_c15_c1_2, x0 + msr s3_0_c15_c1_3, x1 + ret +endfunc nvg_set_request_data + +/* void nvg_set_request(uint64_t req) */ +func nvg_set_request + msr s3_0_c15_c1_2, x0 + ret +endfunc nvg_set_request + +/* uint64_t nvg_get_result(void) */ +func nvg_get_result + mrs x0, s3_0_c15_c1_3 + ret +endfunc nvg_get_result + +/* uint64_t nvg_cache_clean(void) */ +func nvg_cache_clean + mrs x0, s3_0_c15_c3_5 + ret +endfunc nvg_cache_clean + +/* uint64_t nvg_cache_clean_inval(void) */ +func nvg_cache_clean_inval + mrs x0, s3_0_c15_c3_6 + ret +endfunc nvg_cache_clean_inval + +/* uint64_t nvg_cache_inval_all(void) */ +func nvg_cache_inval_all + mrs x0, s3_0_c15_c3_7 + ret +endfunc nvg_cache_inval_all \ No newline at end of file diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c new file mode 100644 index 0000000..af1c0aa --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2019-2020, NVIDIA 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 + +/* Handler to check if MCE firmware is supported */ +static bool mce_firmware_not_supported(void) +{ + bool status; + + /* these platforms do not load MCE firmware */ + status = tegra_platform_is_linsim() || tegra_platform_is_qt() || + tegra_platform_is_virt_dev_kit(); + + return status; +} + +/******************************************************************************* + * Common handler for all MCE commands + ******************************************************************************/ +int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1, + uint64_t arg2) +{ + int32_t ret = 0; + + switch (cmd) { + case (uint64_t)MCE_CMD_ENTER_CSTATE: + ret = nvg_enter_cstate((uint32_t)arg0, (uint32_t)arg1); + if (ret < 0) { + ERROR("%s: enter_cstate failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_IS_SC7_ALLOWED: + ret = nvg_is_sc7_allowed(); + if (ret < 0) { + ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_ONLINE_CORE: + ret = nvg_online_core((uint32_t)arg0); + if (ret < 0) { + ERROR("%s: online_core failed(%d)\n", __func__, ret); + } + + break; + + default: + ERROR("unknown MCE command (%" PRIu64 ")\n", cmd); + ret = -EINVAL; + break; + } + + return ret; +} + +/******************************************************************************* + * Handler to update carveout values for Video Memory Carveout region + ******************************************************************************/ +int32_t mce_update_gsc_videomem(void) +{ + int32_t ret; + + /* + * MCE firmware is not running on simulation platforms. + */ + if (mce_firmware_not_supported()) { + ret = -EINVAL; + } else { + ret = nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR); + } + + return ret; +} + +/******************************************************************************* + * Handler to update carveout values for TZDRAM aperture + ******************************************************************************/ +int32_t mce_update_gsc_tzdram(void) +{ + int32_t ret; + + /* + * MCE firmware is not running on simulation platforms. + */ + if (mce_firmware_not_supported()) { + ret = -EINVAL; + } else { + ret = nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_TZ_DRAM); + } + + return ret; +} + +/******************************************************************************* + * Handler to issue the UPDATE_CSTATE_INFO request + ******************************************************************************/ +void mce_update_cstate_info(const mce_cstate_info_t *cstate) +{ + /* issue the UPDATE_CSTATE_INFO request */ + nvg_update_cstate_info(cstate->cluster, cstate->ccplex, cstate->system, + cstate->wake_mask, cstate->update_wake_mask); +} + +/******************************************************************************* + * Handler to read the MCE firmware version and check if it is compatible + * with interface header the BL3-1 was compiled against + ******************************************************************************/ +void mce_verify_firmware_version(void) +{ + uint64_t version; + uint32_t major, minor; + + /* + * MCE firmware is not running on simulation platforms. + */ + if (mce_firmware_not_supported()) { + return; + } + + /* + * Read the MCE firmware version and extract the major and minor + * version fields + */ + version = nvg_get_version(); + minor = (uint32_t)version; + major = (uint32_t)(version >> 32); + + INFO("MCE Version - HW=%u:%u, SW=%u:%u\n", major, minor, + TEGRA_NVG_VERSION_MAJOR, TEGRA_NVG_VERSION_MINOR); + + /* + * Verify that the MCE firmware version and the interface header + * match + */ + if (major != (uint32_t)TEGRA_NVG_VERSION_MAJOR) { + ERROR("MCE major version mismatch\n"); + panic(); + } + + if (minor < (uint32_t)TEGRA_NVG_VERSION_MINOR) { + ERROR("MCE minor version mismatch\n"); + panic(); + } +} + +#if ENABLE_STRICT_CHECKING_MODE +/******************************************************************************* + * Handler to enable the strict checking mode + ******************************************************************************/ +void mce_enable_strict_checking(void) +{ + uint64_t sctlr = read_sctlr_el3(); + int32_t ret = 0; + + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + /* + * Step1: TZ-DRAM and TZRAM should be setup before the MMU is + * enabled. + * + * The common code makes sure that TZDRAM/TZRAM are already + * enabled before calling into this handler. If this is not the + * case, the following sequence must be executed before moving + * on to step 2. + * + * tlbialle1is(); + * tlbialle3is(); + * dsbsy(); + * isb(); + * + */ + if ((sctlr & (uint64_t)SCTLR_M_BIT) == (uint64_t)SCTLR_M_BIT) { + tlbialle1is(); + tlbialle3is(); + dsbsy(); + isb(); + } + + /* + * Step2: SCF flush - Clean and invalidate caches and clear the + * TR-bits + */ + ret = nvg_roc_clean_cache_trbits(); + if (ret < 0) { + ERROR("%s: flush cache_trbits failed(%d)\n", __func__, + ret); + return; + } + + /* + * Step3: Issue the SECURITY_CONFIG request to MCE to enable + * strict checking mode. + */ + nvg_enable_strict_checking_mode(); + } +} +void mce_verify_strict_checking(void) +{ + bool is_silicon = tegra_platform_is_silicon(); + bool is_fpga = tegra_platform_is_fpga(); + + if (is_silicon || is_fpga) { + nvg_verify_strict_checking_mode(); + } +} +#endif + +/******************************************************************************* + * Handler to power down the entire system + ******************************************************************************/ +void mce_system_shutdown(void) +{ + nvg_system_shutdown(); +} + +/******************************************************************************* + * Handler to reboot the entire system + ******************************************************************************/ +void mce_system_reboot(void) +{ + nvg_system_reboot(); +} + +/******************************************************************************* + * Handler to clear CCPLEX->HSM correctable RAS error signal. + ******************************************************************************/ +void mce_clear_hsm_corr_status(void) +{ + nvg_clear_hsm_corr_status(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c new file mode 100644 index 0000000..f76ab14 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define ID_AFR0_EL1_CACHE_OPS_SHIFT U(12) +#define ID_AFR0_EL1_CACHE_OPS_MASK U(0xF) +/* + * Reports the major and minor version of this interface. + * + * NVGDATA[0:31]: SW(R) Minor Version + * NVGDATA[32:63]: SW(R) Major Version + */ +uint64_t nvg_get_version(void) +{ + nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_VERSION); + + return (uint64_t)nvg_get_result(); +} + +/* + * Set the expected wake time in TSC ticks for the next low-power state the + * core enters. + * + * NVGDATA[0:31]: SW(RW), WAKE_TIME + */ +void nvg_set_wake_time(uint32_t wake_time) +{ + /* time (TSC ticks) until the core is expected to get a wake event */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_WAKE_TIME, (uint64_t)wake_time); +} + +/* + * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and + * SYSTEM_CSTATE values. + * + * NVGDATA[0:2]: SW(RW), CLUSTER_CSTATE + * NVGDATA[7]: SW(W), update cluster flag + * NVGDATA[8:10]: SW(RW), CG_CSTATE + * NVGDATA[15]: SW(W), update ccplex flag + * NVGDATA[16:19]: SW(RW), SYSTEM_CSTATE + * NVGDATA[23]: SW(W), update system flag + * NVGDATA[31]: SW(W), update wake mask flag + * NVGDATA[32:63]: SW(RW), WAKE_MASK + */ +void nvg_update_cstate_info(uint32_t cluster, uint32_t ccplex, + uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask) +{ + uint64_t val = 0; + + /* update CLUSTER_CSTATE? */ + if (cluster != 0U) { + val |= ((uint64_t)cluster & CLUSTER_CSTATE_MASK) | + CLUSTER_CSTATE_UPDATE_BIT; + } + + /* update CCPLEX_CSTATE? */ + if (ccplex != 0U) { + val |= (((uint64_t)ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) | + CCPLEX_CSTATE_UPDATE_BIT; + } + + /* update SYSTEM_CSTATE? */ + if (system != 0U) { + val |= (((uint64_t)system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + SYSTEM_CSTATE_UPDATE_BIT; + } + + /* update wake mask value? */ + if (update_wake_mask != 0U) { + val |= CSTATE_WAKE_MASK_UPDATE_BIT; + } + + /* set the wake mask */ + val |= ((uint64_t)wake_mask & CSTATE_WAKE_MASK_CLEAR) << CSTATE_WAKE_MASK_SHIFT; + + /* set the updated cstate info */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CSTATE_INFO, val); +} + +/* + * Return a non-zero value if the CCPLEX is able to enter SC7 + * + * NVGDATA[0]: SW(R), Is allowed result + */ +int32_t nvg_is_sc7_allowed(void) +{ + /* issue command to check if SC7 is allowed */ + nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED); + + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + return (int32_t)nvg_get_result(); +} + +/* + * Wake an offlined logical core. Note that a core is offlined by entering + * a C-state where the WAKE_MASK is all 0. + * + * NVGDATA[0:3]: SW(W) logical core to online + */ +int32_t nvg_online_core(uint32_t core) +{ + int32_t ret = 0; + + /* sanity check the core ID value */ + if (core > (uint32_t)PLATFORM_CORE_COUNT) { + ERROR("%s: unknown core id (%d)\n", __func__, core); + ret = -EINVAL; + } else { + /* get a core online */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_ONLINE_CORE, + (uint64_t)core & MCE_CORE_ID_MASK); + } + + return ret; +} + +/* + * MC GSC (General Security Carveout) register values are expected to be + * changed by TrustZone ARM code after boot. + * + * NVGDATA[0:15] SW(R) GSC enun + */ +int32_t nvg_update_ccplex_gsc(uint32_t gsc_idx) +{ + int32_t ret = 0; + + /* sanity check GSC ID */ + if (gsc_idx > (uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR) { + ERROR("%s: unknown gsc_idx (%u)\n", __func__, gsc_idx); + ret = -EINVAL; + } else { + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_UPDATE_CCPLEX_GSC, + (uint64_t)gsc_idx); + } + + return ret; +} + +/* + * Cache clean and invalidate, clear TR-bit operation for all CCPLEX caches. + */ +int32_t nvg_roc_clean_cache_trbits(void) +{ + int32_t ret = 0; + + /* check if cache flush through mts is supported */ + if (((read_id_afr0_el1() >> ID_AFR0_EL1_CACHE_OPS_SHIFT) & + ID_AFR0_EL1_CACHE_OPS_MASK) == 1U) { + if (nvg_cache_inval_all() == 0U) { + ERROR("%s: failed\n", __func__); + ret = -ENODEV; + } + } else { + ret = -ENOTSUP; + } + + return ret; +} + +/* + * Set the power state for a core + */ +int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time) +{ + int32_t ret = 0; + uint64_t val = 0ULL; + + /* check for allowed power state */ + if ((state != (uint32_t)TEGRA_NVG_CORE_C0) && + (state != (uint32_t)TEGRA_NVG_CORE_C1) && + (state != (uint32_t)TEGRA_NVG_CORE_C6) && + (state != (uint32_t)TEGRA_NVG_CORE_C7)) + { + ERROR("%s: unknown cstate (%u)\n", __func__, state); + ret = -EINVAL; + } else { + /* time (TSC ticks) until the core is expected to get a wake event */ + nvg_set_wake_time(wake_time); + + /* set the core cstate */ + val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK; + write_actlr_el1(val | (uint64_t)state); + } + + return ret; +} + +#if ENABLE_STRICT_CHECKING_MODE +/* + * Enable strict checking mode + * + * NVGDATA[3] strict_check ON + lock + */ +void nvg_enable_strict_checking_mode(void) +{ + uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET | + STRICT_CHECKING_LOCKED_SET); + + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SECURITY_CONFIG, params); +} + +void nvg_verify_strict_checking_mode(void) +{ + uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET | + STRICT_CHECKING_LOCKED_SET); + + nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_SECURITY_CONFIG); + assert(params == (uint64_t)nvg_get_result()); +} +#endif + +/* + * Request a reboot + * + * NVGDATA[0]: reboot command + */ +void nvg_system_reboot(void) +{ + /* issue command for reboot */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN, + (uint64_t)TEGRA_NVG_REBOOT); +} + +/* + * Request a shutdown + * + * NVGDATA[0]: shutdown command + */ +void nvg_system_shutdown(void) +{ + /* issue command for shutdown */ + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN, + (uint64_t)TEGRA_NVG_SHUTDOWN); +} + +/* + * Request to clear CCPLEX->HSM correctable error signal. + * NVGDATA[1]: A write of 1 clears the CCPLEX->HSM correctable error signal, + * A write of 0 has no effect. + */ +void nvg_clear_hsm_corr_status(void) +{ + nvg_hsm_error_ctrl_channel_t status = { .bits = { .corr = 1U, }, }; + + nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_HSM_ERROR_CTRL, status.flat); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c new file mode 100644 index 0000000..31b0e26 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "se_private.h" + +/******************************************************************************* + * Constants and Macros + ******************************************************************************/ +#define ERR_STATUS_SW_CLEAR U(0xFFFFFFFF) +#define INT_STATUS_SW_CLEAR U(0xFFFFFFFF) +#define MAX_TIMEOUT_MS U(1000) /* Max. timeout of 1s */ +#define NUM_SE_REGS_TO_SAVE U(4) + +#define BYTES_IN_WORD U(4) +#define SHA256_MAX_HASH_RESULT U(7) +#define SHA256_DST_SIZE U(32) +#define SHA_FIRST_OP U(1) +#define MAX_SHA_ENGINE_CHUNK_SIZE U(0xFFFFFF) +#define SHA256_MSG_LENGTH_ONETIME U(0xFFFF) + +/******************************************************************************* + * Data structure and global variables + ******************************************************************************/ +static uint32_t se_regs[NUM_SE_REGS_TO_SAVE]; + +/* + * Check that SE operation has completed after kickoff. + * + * This function is invoked after an SE operation has been started, + * and it checks the following conditions: + * + * 1. SE_STATUS = IDLE + * 2. AHB bus data transfer is complete. + * 3. SE_ERR_STATUS is clean. + */ +static bool tegra_se_is_operation_complete(void) +{ + uint32_t val = 0, timeout = 0, sha_status, aes_status; + int32_t ret = 0; + bool se_is_busy, txn_has_errors, txn_successful; + + /* + * Poll the status register to check if the operation + * completed. + */ + do { + val = tegra_se_read_32(CTX_SAVE_AUTO_STATUS); + se_is_busy = ((val & CTX_SAVE_AUTO_SE_BUSY) != 0U); + + /* sleep until SE finishes */ + if (se_is_busy) { + mdelay(1); + timeout++; + } + + } while (se_is_busy && (timeout < MAX_TIMEOUT_MS)); + + /* any transaction errors? */ + txn_has_errors = (tegra_se_read_32(SHA_ERR_STATUS) != 0U) || + (tegra_se_read_32(AES0_ERR_STATUS) != 0U); + + /* transaction successful? */ + sha_status = tegra_se_read_32(SHA_INT_STATUS) & SHA_SE_OP_DONE; + aes_status = tegra_se_read_32(AES0_INT_STATUS) & AES0_SE_OP_DONE; + txn_successful = (sha_status == SHA_SE_OP_DONE) && + (aes_status == AES0_SE_OP_DONE); + + if ((timeout == MAX_TIMEOUT_MS) || txn_has_errors || !txn_successful) { + ERROR("%s: Atomic context save operation failed!\n", + __func__); + ret = -ECANCELED; + } + + return (ret == 0); +} + +/* + * Wait for SE engine to be idle and clear any pending interrupts, before + * starting the next SE operation. + */ +static bool tegra_se_is_ready(void) +{ + int32_t ret = 0; + uint32_t val = 0, timeout = 0; + bool se_is_ready; + + /* Wait for previous operation to finish */ + do { + val = tegra_se_read_32(CTX_SAVE_AUTO_STATUS); + se_is_ready = (val == CTX_SAVE_AUTO_SE_READY); + + /* sleep until SE is ready */ + if (!se_is_ready) { + mdelay(1); + timeout++; + } + + } while (!se_is_ready && (timeout < MAX_TIMEOUT_MS)); + + if (timeout == MAX_TIMEOUT_MS) { + ERROR("%s: SE is not ready!\n", __func__); + ret = -ETIMEDOUT; + } + + /* Clear any pending interrupts from previous operation */ + tegra_se_write_32(AES0_INT_STATUS, INT_STATUS_SW_CLEAR); + tegra_se_write_32(AES1_INT_STATUS, INT_STATUS_SW_CLEAR); + tegra_se_write_32(RSA_INT_STATUS, INT_STATUS_SW_CLEAR); + tegra_se_write_32(SHA_INT_STATUS, INT_STATUS_SW_CLEAR); + + /* Clear error status for each engine seen from current port */ + tegra_se_write_32(AES0_ERR_STATUS, ERR_STATUS_SW_CLEAR); + tegra_se_write_32(AES1_ERR_STATUS, ERR_STATUS_SW_CLEAR); + tegra_se_write_32(RSA_ERR_STATUS, ERR_STATUS_SW_CLEAR); + tegra_se_write_32(SHA_ERR_STATUS, ERR_STATUS_SW_CLEAR); + + return (ret == 0); +} + +/* + * During System Suspend, this handler triggers the hardware context + * save operation. + */ +static int32_t tegra_se_save_context(void) +{ + int32_t ret = -ECANCELED; + + /* + * 1. Ensure all SE Driver including RNG1/PKA1 are shut down. + * TSEC/R5s are powergated/idle. All tasks on SE1~SE4, RNG1, + * PKA1 are wrapped up. SE0 is ready for use. + * 2. Clear interrupt/error in SE0 status register. + * 3. Scrub SE0 register to avoid false failure for illegal + * configuration. Probably not needed, dependent on HW + * implementation. + * 4. Check SE is ready for HW CTX_SAVE by polling + * SE_CTX_SAVE_AUTO_STATUS.SE_READY. + * + * Steps 1-4 are executed by tegra_se_is_ready(). + * + * 5. Issue context save command. + * 6. Check SE is busy with CTX_SAVE, the command in step5 was not + * dropped for ongoing traffic in any of SE port/engine. + * 7. Poll SE register or wait for SE APB interrupt for task completion + * a. Polling: Read SE_CTX_SAVE_AUTO_STATUS.BUSY till it reports IDLE + * b. Interrupt: After receiving interrupt from SE APB, read + * SE_CTX_SAVE_AUTO_STATUS.BUSY till it reports IDLE. + * 8. Check AES0 and SHA ERR_STATUS to ensure no error case. + * 9. Check AES0 and SHA INT_STATUS to ensure operation has successfully + * completed. + * + * Steps 6-9 are executed by tegra_se_is_operation_complete(). + */ + if (tegra_se_is_ready()) { + + /* Issue context save command */ + tegra_se_write_32(AES0_OPERATION, SE_OP_CTX_SAVE); + + /* Wait for operation to finish */ + if (tegra_se_is_operation_complete()) { + ret = 0; + } + } + + return ret; +} + +/* + * Check that SE operation has completed after kickoff + * This function is invoked after an SE operation has been started, + * and it checks the following conditions: + * 1. SE0_INT_STATUS = SE0_OP_DONE + * 2. SE0_STATUS = IDLE + * 3. SE0_ERR_STATUS is clean. + */ +static int32_t tegra_se_sha256_hash_operation_complete(void) +{ + uint32_t val = 0U; + + /* Poll the SE interrupt register to ensure H/W operation complete */ + val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET); + while (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) { + val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET); + if (SE0_INT_OP_DONE(val) != SE0_INT_OP_DONE_CLEAR) { + break; + } + } + + /* Poll the SE status idle to ensure H/W operation complete */ + val = tegra_se_read_32(SE0_SHA_STATUS_0); + while (val != SE0_SHA_STATUS_IDLE) { + val = tegra_se_read_32(SE0_SHA_STATUS_0); + if (val == SE0_SHA_STATUS_IDLE) { + break; + } + } + + /* Ensure that no errors are thrown during operation */ + val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET); + if (val != 0U) { + ERROR("%s: error during SE operation! 0x%x", __func__, + val); + return -ENOTSUP; + } + + return 0; +} + +/* + * Security engine primitive normal operations + */ +static int32_t tegra_se_start_normal_operation(uint64_t src_addr, + uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes) +{ + uint32_t val = 0U; + uint32_t src_in_lo; + uint32_t src_in_msb; + uint32_t src_in_hi; + int32_t ret = 0; + + if ((src_addr == 0ULL) || (nbytes == 0U)) + return -EINVAL; + + src_in_lo = (uint32_t)src_addr; + src_in_msb = (uint32_t)((src_addr >> 32U) & 0xFFU); + src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) | + (nbytes & MAX_SHA_ENGINE_CHUNK_SIZE)); + + /* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/ + tegra_se_write_32(SE0_IN_ADDR, src_in_lo); + tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi); + + val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET); + if (val > 0U) { + tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x0U); + } + + /* Enable SHA interrupt for SE0 Operation */ + tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU); + + /* flush to DRAM for SE to use the updated contents */ + flush_dcache_range(src_addr, src_len_inbytes); + + /* Start SHA256 operation */ + if (last_buf == 1U) { + tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START | + SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD); + } else { + tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START); + } + + return ret; +} + +static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr, + uint32_t src_len_inbyte) +{ + uint32_t val, last_buf, i; + int32_t ret = 0; + uint32_t operations; + uint64_t src_len_inbits; + uint32_t len_bits_msb; + uint32_t len_bits_lsb; + uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes; + + if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) { + ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte); + return -EINVAL; + } + + if (src_addr == 0ULL) { + return -EINVAL; + } + + /* number of bytes per operation */ + max_bytes = (SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME); + + src_len_inbits = (uint32_t)(src_len_inbyte * 8U); + len_bits_msb = (uint32_t)(src_len_inbits >> 32U); + len_bits_lsb = (uint32_t)src_len_inbits; + + /* program SE0_CONFIG for SHA256 operation */ + val = (uint32_t)(SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 | + SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG); + tegra_se_write_32(SE0_SHA_CONFIG, val); + + /* set SE0_SHA_MSG_LENGTH registers */ + tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb); + tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb); + tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb); + + /* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */ + tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U); + tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U); + tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U); + tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U); + tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U); + + number_of_operations = (src_len_inbyte / max_bytes); + remaining_bytes = (src_len_inbyte % max_bytes); + if (remaining_bytes > 0U) { + number_of_operations += 1U; + } + + /* + * 1. Operations == 1: program SE0_SHA_TASK register to initiate SHA256 + * hash generation by setting + * 1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK + * and start SHA256-normal operation. + * 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to + * 0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load + * intermediate SHA256 digest result from + * HASH_RESULT register to continue SHA256 + * generation and start SHA256-normal operation. + * 3. Operations == number_of_operations: continue with step 2 and set + * max_bytes to bytes_left to process final + * hash-result generation and start SHA256-normal + * operation. + */ + bytes_left = src_len_inbyte; + for (operations = 1U; operations <= number_of_operations; + operations++) { + if (operations == SHA_FIRST_OP) { + val = SE0_SHA_CONFIG_HW_INIT_HASH; + } else { + /* Load intermediate SHA digest result to + * SHA:HASH_RESULT(0..7) to continue the SHA + * calculation and tell the SHA engine to use it. + */ + for (i = 0U; (i / BYTES_IN_WORD) <= + SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) { + val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + + i); + tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i, + val); + } + val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE; + if (len_bits_lsb <= (max_bytes * 8U)) { + len_bits_lsb = (remaining_bytes * 8U); + } else { + len_bits_lsb -= (max_bytes * 8U); + } + tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb); + } + tegra_se_write_32(SE0_SHA_TASK_CONFIG, val); + + max_bytes = (SHA256_HASH_SIZE_BYTES * + SHA256_MSG_LENGTH_ONETIME); + if (bytes_left < max_bytes) { + max_bytes = bytes_left; + last_buf = 1U; + } else { + bytes_left = bytes_left - max_bytes; + last_buf = 0U; + } + /* start operation */ + ret = tegra_se_start_normal_operation(src_addr, max_bytes, + last_buf, src_len_inbyte); + if (ret != 0) { + ERROR("Error during SE operation! 0x%x", ret); + return -EINVAL; + } + } + + return ret; +} + +static int32_t tegra_se_save_sha256_pmc_scratch(void) +{ + uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U; + int32_t ret; + + /* Check SE0 operation status */ + ret = tegra_se_sha256_hash_operation_complete(); + if (ret != 0) { + ERROR("SE operation complete Failed! 0x%x", ret); + return ret; + } + + for (scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START; + scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END; + scratch_offset += BYTES_IN_WORD) { + val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset); + mmio_write_32((uint32_t)(TEGRA_SCRATCH_BASE + scratch_offset), + val); + hash_offset += BYTES_IN_WORD; + } + return 0; +} + +/* + * Handler to generate SHA256 and save HASH-result to pmc-scratch register + */ +int32_t tegra_se_calculate_save_sha256(uint64_t src_addr, + uint32_t src_len_inbyte) +{ + uint32_t security; + int32_t val = 0; + + /* Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE + * registers. + */ + security = tegra_se_read_32(SE0_SECURITY); + tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING); + + /* Bootrom enable IN_ID bit in SE0_SHA_GSCID_0 register during SC7-exit, causing + * SE0 ignores SE0 operation, and therefore failure of 2nd iteration of SC7 cycle. + */ + tegra_se_write_32(SE0_SHA_GSCID_0, 0x0U); + + /* Calculate SHA256 of BL31 */ + val = tegra_se_calculate_sha256_hash(src_addr, src_len_inbyte); + if (val != 0) { + ERROR("%s: SHA256 generation failed\n", __func__); + return val; + } + + /* + * Reset SE_SECURE to previous value. + */ + tegra_se_write_32(SE0_SECURITY, security); + + /* copy sha256_dst to PMC Scratch register */ + val = tegra_se_save_sha256_pmc_scratch(); + if (val != 0) { + ERROR("%s: SE0 status Error.\n", __func__); + } + + return val; +} + +/* + * Handler to power down the SE hardware blocks - SE, RNG1 and PKA1. This + * needs to be called only during System Suspend. + */ +int32_t tegra_se_suspend(void) +{ + int32_t ret = 0; + + /* initialise communication channel with BPMP */ + assert(tegra_bpmp_ipc_init() == 0); + + /* Enable SE clock before SE context save */ + ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE); + assert(ret == 0); + + /* save SE registers */ + se_regs[0] = mmio_read_32(TEGRA_SE0_BASE + SE0_MUTEX_WATCHDOG_NS_LIMIT); + se_regs[1] = mmio_read_32(TEGRA_SE0_BASE + SE0_AES0_ENTROPY_SRC_AGE_CTRL); + se_regs[2] = mmio_read_32(TEGRA_RNG1_BASE + RNG1_MUTEX_WATCHDOG_NS_LIMIT); + se_regs[3] = mmio_read_32(TEGRA_PKA1_BASE + PKA1_MUTEX_WATCHDOG_NS_LIMIT); + + /* Save SE context. The BootROM restores it during System Resume */ + ret = tegra_se_save_context(); + if (ret != 0) { + ERROR("%s: context save failed (%d)\n", __func__, ret); + } + + /* Disable SE clock after SE context save */ + ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE); + assert(ret == 0); + + return ret; +} + +/* + * Handler to power up the SE hardware block(s) during System Resume. + */ +void tegra_se_resume(void) +{ + int32_t ret = 0; + + /* initialise communication channel with BPMP */ + assert(tegra_bpmp_ipc_init() == 0); + + /* Enable SE clock before SE context restore */ + ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE); + assert(ret == 0); + + /* + * When TZ takes over after System Resume, TZ should first reconfigure + * SE_MUTEX_WATCHDOG_NS_LIMIT, PKA1_MUTEX_WATCHDOG_NS_LIMIT, + * RNG1_MUTEX_WATCHDOG_NS_LIMIT and SE_ENTROPY_SRC_AGE_CTRL before + * other operations. + */ + mmio_write_32(TEGRA_SE0_BASE + SE0_MUTEX_WATCHDOG_NS_LIMIT, se_regs[0]); + mmio_write_32(TEGRA_SE0_BASE + SE0_AES0_ENTROPY_SRC_AGE_CTRL, se_regs[1]); + mmio_write_32(TEGRA_RNG1_BASE + RNG1_MUTEX_WATCHDOG_NS_LIMIT, se_regs[2]); + mmio_write_32(TEGRA_PKA1_BASE + PKA1_MUTEX_WATCHDOG_NS_LIMIT, se_regs[3]); + + /* Disable SE clock after SE context restore */ + ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE); + assert(ret == 0); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h new file mode 100644 index 0000000..fc118aa --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SE_PRIVATE_H +#define SE_PRIVATE_H + +#include +#include + +/* SE0 security register */ +#define SE0_SECURITY U(0x18) +#define SE0_SECURITY_SE_SOFT_SETTING (((uint32_t)1) << 16U) + +/* SE0 SHA GSCID register */ +#define SE0_SHA_GSCID_0 U(0x100) + +/* SE0 config register */ +#define SE0_SHA_CONFIG U(0x104) +#define SE0_SHA_TASK_CONFIG U(0x108) +#define SE0_SHA_CONFIG_HW_INIT_HASH (((uint32_t)1) << 0U) +#define SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE U(0) + +#define SE0_CONFIG_ENC_ALG_SHIFT U(12) +#define SE0_CONFIG_ENC_ALG_SHA \ + (((uint32_t)3) << SE0_CONFIG_ENC_ALG_SHIFT) +#define SE0_CONFIG_DEC_ALG_SHIFT U(8) +#define SE0_CONFIG_DEC_ALG_NOP \ + (((uint32_t)0) << SE0_CONFIG_DEC_ALG_SHIFT) +#define SE0_CONFIG_DST_SHIFT U(2) +#define SE0_CONFIG_DST_HASHREG \ + (((uint32_t)1) << SE0_CONFIG_DST_SHIFT) +#define SHA256_HASH_SIZE_BYTES U(256) + +#define SE0_CONFIG_ENC_MODE_SHIFT U(24) +#define SE0_CONFIG_ENC_MODE_SHA256 \ + (((uint32_t)5) << SE0_CONFIG_ENC_MODE_SHIFT) + +/* SHA input message length */ +#define SE0_IN_ADDR U(0x10c) +#define SE0_IN_HI_ADDR_HI U(0x110) +#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT U(24) + +/* SHA input message length */ +#define SE0_SHA_MSG_LENGTH_0 U(0x11c) +#define SE0_SHA_MSG_LENGTH_1 U(0x120) +#define SE0_SHA_MSG_LENGTH_2 U(0x124) +#define SE0_SHA_MSG_LENGTH_3 U(0x128) + +/* SHA input message left */ +#define SE0_SHA_MSG_LEFT_0 U(0x12c) +#define SE0_SHA_MSG_LEFT_1 U(0x130) +#define SE0_SHA_MSG_LEFT_2 U(0x134) +#define SE0_SHA_MSG_LEFT_3 U(0x138) + +/* SE HASH-RESULT */ +#define SE0_SHA_HASH_RESULT_0 U(0x13c) + +/* SE OPERATION */ +#define SE0_OPERATION_REG_OFFSET U(0x17c) +#define SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT U(16) +#define SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD \ + ((uint32_t)0x1 << SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT) +#define SE0_OPERATION_SHIFT U(0) +#define SE0_OP_START \ + (((uint32_t)0x1) << SE0_OPERATION_SHIFT) + +/* SE Interrupt */ +#define SE0_SHA_INT_ENABLE U(0x180) + +#define SE0_INT_STATUS_REG_OFFSET U(0x184) +#define SE0_INT_OP_DONE_SHIFT U(4) +#define SE0_INT_OP_DONE_CLEAR \ + (((uint32_t)0U) << SE0_INT_OP_DONE_SHIFT) +#define SE0_INT_OP_DONE(x) \ + ((x) & (((uint32_t)0x1U) << SE0_INT_OP_DONE_SHIFT)) + +/* SE SHA Status */ +#define SE0_SHA_STATUS_0 U(0x188) +#define SE0_SHA_STATUS_IDLE U(0) + +/* SE error status */ +#define SE0_ERR_STATUS_REG_OFFSET U(0x18c) +#define SE0_ERR_STATUS_CLEAR U(0) + +/* SE error status */ +#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START SECURE_SCRATCH_RSV68_LO +#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END SECURE_SCRATCH_RSV71_HI + +/* SE0_INT_ENABLE_0 */ +#define SE0_INT_ENABLE U(0x88) +#define SE0_DISABLE_ALL_INT U(0x0) + +/* SE0_INT_STATUS_0 */ +#define SE0_INT_STATUS U(0x8C) +#define SE0_CLEAR_ALL_INT_STATUS U(0x3F) + +/* SE0_SHA_INT_STATUS_0 */ +#define SHA_INT_STATUS U(0x184) +#define SHA_SE_OP_DONE (U(1) << 4) + +/* SE0_SHA_ERR_STATUS_0 */ +#define SHA_ERR_STATUS U(0x18C) + +/* SE0_AES0_INT_STATUS_0 */ +#define AES0_INT_STATUS U(0x2F0) +#define AES0_SE_OP_DONE (U(1) << 4) + +/* SE0_AES0_ERR_STATUS_0 */ +#define AES0_ERR_STATUS U(0x2F8) + +/* SE0_AES1_INT_STATUS_0 */ +#define AES1_INT_STATUS U(0x4F0) + +/* SE0_AES1_ERR_STATUS_0 */ +#define AES1_ERR_STATUS U(0x4F8) + +/* SE0_RSA_INT_STATUS_0 */ +#define RSA_INT_STATUS U(0x758) + +/* SE0_RSA_ERR_STATUS_0 */ +#define RSA_ERR_STATUS U(0x760) + +/* SE0_AES0_OPERATION_0 */ +#define AES0_OPERATION U(0x238) +#define OP_MASK_BITS U(0x7) +#define SE_OP_CTX_SAVE U(0x3) + +/* SE0_AES0_CTX_SAVE_CONFIG_0 */ +#define CTX_SAVE_CONFIG U(0x2D4) + +/* SE0_AES0_CTX_SAVE_AUTO_STATUS_0 */ +#define CTX_SAVE_AUTO_STATUS U(0x300) +#define CTX_SAVE_AUTO_SE_READY U(0xFF) +#define CTX_SAVE_AUTO_SE_BUSY (U(0x1) << 31) + +/* SE0_AES0_CTX_SAVE_AUTO_CTRL_0 */ +#define CTX_SAVE_AUTO_CTRL U(0x304) +#define SE_CTX_SAVE_AUTO_EN (U(0x1) << 0) +#define SE_CTX_SAVE_AUTO_LOCK_EN (U(0x1) << 1) + +/* SE0_AES0_CTX_SAVE_AUTO_START_ADDR_0 */ +#define CTX_SAVE_AUTO_START_ADDR U(0x308) + +/* SE0_AES0_CTX_SAVE_AUTO_START_ADDR_HI_0 */ +#define CTX_SAVE_AUTO_START_ADDR_HI U(0x30C) + +/******************************************************************************* + * Inline functions definition + ******************************************************************************/ + +static inline uint32_t tegra_se_read_32(uint32_t offset) +{ + return mmio_read_32((uint32_t)(TEGRA_SE0_BASE + offset)); +} + +static inline void tegra_se_write_32(uint32_t offset, uint32_t val) +{ + mmio_write_32((uint32_t)(TEGRA_SE0_BASE + offset), val); +} + +#endif /* SE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c new file mode 100644 index 0000000..2182699 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Array to hold MC context for Tegra194 + ******************************************************************************/ +static __attribute__((aligned(16))) mc_regs_t tegra194_mc_context[] = { + _START_OF_TABLE_, + mc_smmu_bypass_cfg, /* TBU settings */ + _END_OF_TABLE_, +}; + +/******************************************************************************* + * Handler to return the pointer to the MC's context struct + ******************************************************************************/ +mc_regs_t *plat_memctrl_get_sys_suspend_ctx(void) +{ + /* index of _END_OF_TABLE_ */ + tegra194_mc_context[0].val = (uint32_t)ARRAY_SIZE(tegra194_mc_context) - 1U; + + return tegra194_mc_context; +} + +/******************************************************************************* + * Handler to restore platform specific settings to the memory controller + ******************************************************************************/ +void plat_memctrl_restore(void) +{ + UNUSED_FUNC_NOP(); /* do nothing */ +} + +/******************************************************************************* + * Handler to program platform specific settings to the memory controller + ******************************************************************************/ +void plat_memctrl_setup(void) +{ + /* + * All requests at boot time, and certain requests during + * normal run time, are physically addressed and must bypass + * the SMMU. The client hub logic implements a hardware bypass + * path around the Translation Buffer Units (TBU). During + * boot-time, the SMMU_BYPASS_CTRL register (which defaults to + * TBU_BYPASS mode) will be used to steer all requests around + * the uninitialized TBUs. During normal operation, this register + * is locked into TBU_BYPASS_SID config, which routes requests + * with special StreamID 0x7f on the bypass path and all others + * through the selected TBU. This is done to disable SMMU Bypass + * mode, as it could be used to circumvent SMMU security checks. + */ + tegra_mc_write_32(MC_SMMU_BYPASS_CONFIG, + MC_SMMU_BYPASS_CONFIG_SETTINGS); +} + +/******************************************************************************* + * Handler to program the scratch registers with TZDRAM settings for the + * resume firmware + ******************************************************************************/ +void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes) +{ + uint32_t sec_reg_ctrl = tegra_mc_read_32(MC_SECURITY_CFG_REG_CTRL_0); + uint32_t phys_base_lo = (uint32_t)phys_base & 0xFFF00000; + uint32_t phys_base_hi = (uint32_t)(phys_base >> 32); + + /* + * Check TZDRAM carveout register access status. Setup TZDRAM fence + * only if access is enabled. + */ + if ((sec_reg_ctrl & SECURITY_CFG_WRITE_ACCESS_BIT) == + SECURITY_CFG_WRITE_ACCESS_ENABLE) { + + /* + * Setup the Memory controller to allow only secure accesses to + * the TZDRAM carveout + */ + INFO("Configuring TrustZone DRAM Memory Carveout\n"); + + tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base_lo); + tegra_mc_write_32(MC_SECURITY_CFG3_0, phys_base_hi); + tegra_mc_write_32(MC_SECURITY_CFG1_0, (uint32_t)(size_in_bytes >> 20)); + + /* + * MCE propagates the security configuration values across the + * CCPLEX. + */ + (void)mce_update_gsc_tzdram(); + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c new file mode 100644 index 0000000..60cd4a9 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2019-2020, NVIDIA 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 + +extern uint32_t __tegra194_cpu_reset_handler_data, + __tegra194_cpu_reset_handler_end; + +/* TZDRAM offset for saving SMMU context */ +#define TEGRA194_SMMU_CTX_OFFSET 16U + +/* state id mask */ +#define TEGRA194_STATE_ID_MASK 0xFU +/* constants to get power state's wake time */ +#define TEGRA194_WAKE_TIME_MASK 0x0FFFFFF0U +#define TEGRA194_WAKE_TIME_SHIFT 4U +/* default core wake mask for CPU_SUSPEND */ +#define TEGRA194_CORE_WAKE_MASK 0x180cU + +static struct t19x_psci_percpu_data { + uint32_t wake_time; +} __aligned(CACHE_WRITEBACK_GRANULE) t19x_percpu_data[PLATFORM_CORE_COUNT]; + +int32_t tegra_soc_validate_power_state(uint32_t power_state, + psci_power_state_t *req_state) +{ + uint8_t state_id = (uint8_t)psci_get_pstate_id(power_state) & + TEGRA194_STATE_ID_MASK; + uint32_t cpu = plat_my_core_pos(); + int32_t ret = PSCI_E_SUCCESS; + + /* save the core wake time (in TSC ticks)*/ + t19x_percpu_data[cpu].wake_time = (power_state & TEGRA194_WAKE_TIME_MASK) + << TEGRA194_WAKE_TIME_SHIFT; + + /* + * Clean t19x_percpu_data[cpu] to DRAM. This needs to be done to ensure + * that the correct value is read in tegra_soc_pwr_domain_suspend(), + * which is called with caches disabled. It is possible to read a stale + * value from DRAM in that function, because the L2 cache is not flushed + * unless the cluster is entering CC6/CC7. + */ + clean_dcache_range((uint64_t)&t19x_percpu_data[cpu], + sizeof(t19x_percpu_data[cpu])); + + /* Sanity check the requested state id */ + switch (state_id) { + case PSTATE_ID_CORE_IDLE: + + if (psci_get_pstate_type(power_state) != PSTATE_TYPE_STANDBY) { + ret = PSCI_E_INVALID_PARAMS; + break; + } + + /* Core idle request */ + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + req_state->pwr_domain_state[MPIDR_AFFLVL1] = PSCI_LOCAL_STATE_RUN; + break; + + default: + ERROR("%s: unsupported state id (%d)\n", __func__, state_id); + ret = PSCI_E_INVALID_PARAMS; + break; + } + + return ret; +} + +int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) +{ + uint32_t cpu = plat_my_core_pos(); + mce_cstate_info_t cstate_info = { 0 }; + + /* Program default wake mask */ + cstate_info.wake_mask = TEGRA194_CORE_WAKE_MASK; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + + /* Enter CPU idle */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + (uint64_t)TEGRA_NVG_CORE_C6, + t19x_percpu_data[cpu].wake_time, + 0U); + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + const plat_local_state_t *pwr_domain_state; + uint8_t stateid_afflvl2; + plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + uint64_t mc_ctx_base; + uint32_t val; + mce_cstate_info_t sc7_cstate_info = { + .cluster = (uint32_t)TEGRA_NVG_CLUSTER_CC6, + .ccplex = (uint32_t)TEGRA_NVG_CG_CG7, + .system = (uint32_t)TEGRA_NVG_SYSTEM_SC7, + .system_state_force = 1U, + .update_wake_mask = 1U, + }; + int32_t ret = 0; + + /* get the state ID */ + pwr_domain_state = target_state->pwr_domain_state; + stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA194_STATE_ID_MASK; + + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + + /* save 'Secure Boot' Processor Feature Config Register */ + val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG); + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val); + + /* save MC context */ + mc_ctx_base = params_from_bl2->tzdram_base + + tegra194_get_mc_ctx_offset(); + tegra_mc_save_context((uintptr_t)mc_ctx_base); + + /* + * Suspend SE, RNG1 and PKA1 only on silcon and fpga, + * since VDK does not support atomic se ctx save + */ + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + ret = tegra_se_suspend(); + assert(ret == 0); + } + + /* Prepare for system suspend */ + mce_update_cstate_info(&sc7_cstate_info); + + do { + val = (uint32_t)mce_command_handler( + (uint32_t)MCE_CMD_IS_SC7_ALLOWED, + (uint32_t)TEGRA_NVG_CORE_C7, + MCE_CORE_SLEEP_TIME_INFINITE, + 0U); + } while (val == 0U); + + /* Instruct the MCE to enter system suspend state */ + ret = mce_command_handler( + (uint64_t)MCE_CMD_ENTER_CSTATE, + (uint64_t)TEGRA_NVG_CORE_C7, + MCE_CORE_SLEEP_TIME_INFINITE, + 0U); + assert(ret == 0); + + /* set system suspend state for house-keeping */ + tegra194_set_system_suspend_entry(); + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Helper function to check if this is the last ON CPU in the cluster + ******************************************************************************/ +static bool tegra_last_on_cpu_in_cluster(const plat_local_state_t *states, + uint32_t ncpu) +{ + plat_local_state_t target; + bool last_on_cpu = true; + uint32_t num_cpus = ncpu, pos = 0; + + do { + target = states[pos]; + if (target != PLAT_MAX_OFF_STATE) { + last_on_cpu = false; + } + --num_cpus; + pos++; + } while (num_cpus != 0U); + + return last_on_cpu; +} + +/******************************************************************************* + * Helper function to get target power state for the cluster + ******************************************************************************/ +static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states, + uint32_t ncpu) +{ + uint32_t core_pos = (uint32_t)read_mpidr() & (uint32_t)MPIDR_CPU_MASK; + plat_local_state_t target = states[core_pos]; + mce_cstate_info_t cstate_info = { 0 }; + + /* CPU off */ + if (target == PLAT_MAX_OFF_STATE) { + + /* Enable cluster powerdn from last CPU in the cluster */ + if (tegra_last_on_cpu_in_cluster(states, ncpu)) { + + /* Enable CC6 state and turn off wake mask */ + cstate_info.cluster = (uint32_t)TEGRA_NVG_CLUSTER_CC6; + cstate_info.ccplex = (uint32_t)TEGRA_NVG_CG_CG7; + cstate_info.system_state_force = 1; + cstate_info.update_wake_mask = 1U; + mce_update_cstate_info(&cstate_info); + + } else { + + /* Turn off wake_mask */ + cstate_info.update_wake_mask = 1U; + mce_update_cstate_info(&cstate_info); + target = PSCI_LOCAL_STATE_RUN; + } + } + + return target; +} + +/******************************************************************************* + * Platform handler to calculate the proper target power level at the + * specified affinity level + ******************************************************************************/ +plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, + const plat_local_state_t *states, + uint32_t ncpu) +{ + plat_local_state_t target = PSCI_LOCAL_STATE_RUN; + uint32_t cpu = plat_my_core_pos(); + + /* System Suspend */ + if ((lvl == (uint32_t)MPIDR_AFFLVL2) && (states[cpu] == PSTATE_ID_SOC_POWERDN)) { + target = PSTATE_ID_SOC_POWERDN; + } + + /* CPU off, CPU suspend */ + if (lvl == (uint32_t)MPIDR_AFFLVL1) { + target = tegra_get_afflvl1_pwr_state(states, ncpu); + } + + /* target cluster/system state */ + return target; +} + +int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) +{ + const plat_local_state_t *pwr_domain_state = + target_state->pwr_domain_state; + plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA194_STATE_ID_MASK; + uint64_t src_len_in_bytes = (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE; + uint64_t val; + int32_t ret = PSCI_E_SUCCESS; + + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + val = params_from_bl2->tzdram_base + + tegra194_get_cpu_reset_handler_size(); + + /* initialise communication channel with BPMP */ + ret = tegra_bpmp_ipc_init(); + assert(ret == 0); + + /* Enable SE clock before SE context save */ + ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE); + assert(ret == 0); + + /* + * It is very unlikely that the BL31 image would be + * bigger than 2^32 bytes + */ + assert(src_len_in_bytes < UINT32_MAX); + + if (tegra_se_calculate_save_sha256(BL31_BASE, + (uint32_t)src_len_in_bytes) != 0) { + ERROR("Hash calculation failed. Reboot\n"); + (void)tegra_soc_prepare_system_reset(); + } + + /* + * The TZRAM loses power when we enter system suspend. To + * allow graceful exit from system suspend, we need to copy + * BL3-1 over to TZDRAM. + */ + val = params_from_bl2->tzdram_base + + tegra194_get_cpu_reset_handler_size(); + memcpy((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE, + src_len_in_bytes); + + /* Disable SE clock after SE context save */ + ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE); + assert(ret == 0); + } + + return ret; +} + +int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) +{ + uint64_t target_cpu = mpidr & MPIDR_CPU_MASK; + uint64_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >> + MPIDR_AFFINITY_BITS; + int32_t ret = 0; + + if (target_cluster > ((uint32_t)PLATFORM_CLUSTER_COUNT - 1U)) { + ERROR("%s: unsupported CPU (0x%lx)\n", __func__ , mpidr); + return PSCI_E_NOT_PRESENT; + } + + /* construct the target CPU # */ + target_cpu += (target_cluster << 1U); + + ret = mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U); + if (ret < 0) { + return PSCI_E_DENIED; + } + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + uint8_t enable_ccplex_lock_step = params_from_bl2->enable_ccplex_lock_step; + uint8_t stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + uint64_t actlr_elx; + + /* + * Reset power state info for CPUs when onlining, we set + * deepest power when offlining a core but that may not be + * requested by non-secure sw which controls idle states. It + * will re-init this info from non-secure software when the + * core come online. + */ + actlr_elx = read_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1)); + actlr_elx &= ~DENVER_CPU_PMSTATE_MASK; + actlr_elx |= DENVER_CPU_PMSTATE_C1; + write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx)); + + /* + * Check if we are exiting from deep sleep and restore SE + * context if we are. + */ + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + +#if ENABLE_STRICT_CHECKING_MODE + /* + * Enable strict checking after programming the GSC for + * enabling TZSRAM and TZDRAM + */ + mce_enable_strict_checking(); +#endif + + /* Init SMMU */ + tegra_smmu_init(); + + /* Resume SE, RNG1 and PKA1 */ + tegra_se_resume(); + + /* + * Program XUSB STREAMIDs + * ====================== + * T19x XUSB has support for XUSB virtualization. It will + * have one physical function (PF) and four Virtual functions + * (VF) + * + * There were below two SIDs for XUSB until T186. + * 1) #define TEGRA_SID_XUSB_HOST 0x1bU + * 2) #define TEGRA_SID_XUSB_DEV 0x1cU + * + * We have below four new SIDs added for VF(s) + * 3) #define TEGRA_SID_XUSB_VF0 0x5dU + * 4) #define TEGRA_SID_XUSB_VF1 0x5eU + * 5) #define TEGRA_SID_XUSB_VF2 0x5fU + * 6) #define TEGRA_SID_XUSB_VF3 0x60U + * + * When virtualization is enabled then we have to disable SID + * override and program above SIDs in below newly added SID + * registers in XUSB PADCTL MMIO space. These registers are + * TZ protected and so need to be done in ATF. + * + * a) #define XUSB_PADCTL_HOST_AXI_STREAMID_PF_0 (0x136cU) + * b) #define XUSB_PADCTL_DEV_AXI_STREAMID_PF_0 (0x139cU) + * c) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_0 (0x1370U) + * d) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_1 (0x1374U) + * e) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_2 (0x1378U) + * f) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_3 (0x137cU) + * + * This change disables SID override and programs XUSB SIDs + * in above registers to support both virtualization and + * non-virtualization platforms + */ + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_HOST); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_HOST); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_0, TEGRA_SID_XUSB_VF0); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_0) == TEGRA_SID_XUSB_VF0); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_1, TEGRA_SID_XUSB_VF1); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_1) == TEGRA_SID_XUSB_VF1); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_2, TEGRA_SID_XUSB_VF2); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_2) == TEGRA_SID_XUSB_VF2); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_3, TEGRA_SID_XUSB_VF3); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_3) == TEGRA_SID_XUSB_VF3); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_DEV_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_DEV); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_DEV_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_DEV); + } + } + + /* + * Enable dual execution optimized translations for all ELx. + */ + if (enable_ccplex_lock_step != 0U) { + actlr_elx = read_actlr_el3(); + actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL3; + write_actlr_el3(actlr_elx); + + actlr_elx = read_actlr_el2(); + actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL2; + write_actlr_el2(actlr_elx); + + actlr_elx = read_actlr_el1(); + actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL1; + write_actlr_el1(actlr_elx); + } + +#if TEGRA_TRAP_LOWER_EL_ERR_ACCESS + /* + * SCR_EL3.TERR: Error register(ER*_EL1) accesses from EL1 or EL2 + * generate a Trap exception to EL3. + */ + scr_el3 = (uint32_t)read_scr(); + scr_el3 |= SCR_TERR_BIT; + write_scr(scr_el3); +#endif + +#if ENABLE_TEGRA_PERFMON + /* + * Enable Uncore Perfmon counters to aid in debugging. + * + * When set, events are allowed to be counted in the NVIDIA-specific + * Performance Monitors extension. + */ + actlr_elx = read_actlr_el3(); + actlr_elx |= DENVER_CPU_ENABLE_SPME; + write_actlr_el3(actlr_elx); +#endif + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) +{ + uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + int32_t ret = 0; + + (void)target_state; + + /* Disable Denver's DCO operations */ + if (impl == DENVER_IMPL) { + denver_disable_dco(); + } + + /* Turn off CPU */ + ret = mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + (uint64_t)TEGRA_NVG_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U); + assert(ret == 0); + + return PSCI_E_SUCCESS; +} + +__dead2 void tegra_soc_prepare_system_off(void) +{ + /* System power off */ + mce_system_shutdown(); + + wfi(); + + /* wait for the system to power down */ + for (;;) { + ; + } +} + +int32_t tegra_soc_prepare_system_reset(void) +{ + /* System reboot */ + mce_system_reboot(); + + return PSCI_E_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c new file mode 100644 index 0000000..ec9d86c --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2020-2021, NVIDIA 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 + +/* + * ERRFR bits[63:32], it indicates supported RAS errors which can be enabled + * by setting corresponding bits in ERRCTLR + */ +#define ERR_FR_EN_BITS_MASK 0xFFFFFFFF00000000ULL + +/* + * Number of RAS errors will be cleared per 'tegra194_ras_corrected_err_clear' + * function call. + */ +#define RAS_ERRORS_PER_CALL 8 + +/* + * the max possible RAS node index value. + */ +#define RAS_NODE_INDEX_MAX 0x1FFFFFFFU + +/* bakery lock for platform RAS handler. */ +static DEFINE_BAKERY_LOCK(ras_handler_lock); +#define ras_lock() bakery_lock_get(&ras_handler_lock) +#define ras_unlock() bakery_lock_release(&ras_handler_lock) + +/* + * Function to handle an External Abort received at EL3. + * This function is invoked by RAS framework. + */ +static void tegra194_ea_handler(unsigned int ea_reason, uint64_t syndrome, + void *cookie, void *handle, uint64_t flags) +{ + int32_t ret; + + ras_lock(); + + ERROR("MPIDR 0x%lx: exception reason=%u syndrome=0x%" PRIx64 "\n", + read_mpidr(), ea_reason, syndrome); + + /* Call RAS EA handler */ + ret = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags); + if (ret != 0) { + ERROR("RAS error handled!\n"); + ret = sdei_dispatch_event(TEGRA_SDEI_EP_EVENT_0 + + plat_my_core_pos()); + if (ret != 0) + ERROR("sdei_dispatch_event returned %d\n", ret); + } else { + ERROR("Not a RAS error!\n"); + } + + ras_unlock(); +} + +/* + * Function to enable all supported RAS error report. + * + * Uncorrected errors are set to report as External abort (SError) + * Corrected errors are set to report as interrupt. + */ +void tegra194_ras_enable(void) +{ + VERBOSE("%s\n", __func__); + + /* skip RAS enablement if not a silicon platform. */ + if (!tegra_platform_is_silicon()) { + return; + } + + /* + * Iterate for each group(num_idx ERRSELRs starting from idx_start) + * use normal for loop instead of for_each_err_record_info to get rid + * of MISRA noise.. + */ + for (uint32_t i = 0U; i < err_record_mappings.num_err_records; i++) { + + const struct err_record_info *info = &err_record_mappings.err_records[i]; + + uint32_t idx_start = info->sysreg.idx_start; + uint32_t num_idx = info->sysreg.num_idx; + const struct ras_aux_data *aux_data = (const struct ras_aux_data *)info->aux_data; + + assert(aux_data != NULL); + + for (uint32_t j = 0; j < num_idx; j++) { + + /* ERRCTLR register value. */ + uint64_t err_ctrl = 0ULL; + /* all supported errors for this node. */ + uint64_t err_fr; + /* uncorrectable errors */ + uint64_t uncorr_errs; + /* correctable errors */ + uint64_t corr_errs; + + /* + * Catch error if something wrong with the RAS aux data + * record table. + */ + assert(aux_data[j].err_ctrl != NULL); + + /* + * Write to ERRSELR_EL1 to select the RAS error node. + * Always program this at first to select corresponding + * RAS node before any other RAS register r/w. + */ + ser_sys_select_record(idx_start + j); + + err_fr = read_erxfr_el1() & ERR_FR_EN_BITS_MASK; + uncorr_errs = aux_data[j].err_ctrl(); + corr_errs = ~uncorr_errs & err_fr; + + /* enable error reporting */ + ERR_CTLR_ENABLE_FIELD(err_ctrl, ED); + + /* enable SError reporting for uncorrectable errors */ + if ((uncorr_errs & err_fr) != 0ULL) { + ERR_CTLR_ENABLE_FIELD(err_ctrl, UE); + } + + /* generate interrupt for corrected errors. */ + if (corr_errs != 0ULL) { + ERR_CTLR_ENABLE_FIELD(err_ctrl, CFI); + } + + /* enable the supported errors */ + err_ctrl |= err_fr; + + VERBOSE("errselr_el1:0x%x, erxfr:0x%" PRIx64 ", err_ctrl:0x%" PRIx64 "\n", + idx_start + j, err_fr, err_ctrl); + + /* enable specified errors, or set to 0 if no supported error */ + write_erxctlr_el1(err_ctrl); + } + } +} + +/* + * Function to clear RAS ERRSTATUS for corrected RAS error. + * + * This function clears number of 'RAS_ERRORS_PER_CALL' RAS errors at most. + * 'cookie' - in/out cookie parameter to specify/store last visited RAS + * error record index. it is set to '0' to indicate no more RAS + * error record to clear. + */ +void tegra194_ras_corrected_err_clear(uint64_t *cookie) +{ + /* + * 'last_node' and 'last_idx' represent last visited RAS node index from + * previous function call. they are set to 0 when first smc call is made + * or all RAS error are visited by followed multipile smc calls. + */ + union prev_record { + struct record { + uint32_t last_node; + uint32_t last_idx; + } rec; + uint64_t value; + } prev; + + uint64_t clear_ce_status = 0ULL; + int32_t nerrs_per_call = RAS_ERRORS_PER_CALL; + uint32_t i; + + if (cookie == NULL) { + return; + } + + prev.value = *cookie; + + if ((prev.rec.last_node >= RAS_NODE_INDEX_MAX) || + (prev.rec.last_idx >= RAS_NODE_INDEX_MAX)) { + return; + } + + ERR_STATUS_SET_FIELD(clear_ce_status, AV, 0x1UL); + ERR_STATUS_SET_FIELD(clear_ce_status, V, 0x1UL); + ERR_STATUS_SET_FIELD(clear_ce_status, OF, 0x1UL); + ERR_STATUS_SET_FIELD(clear_ce_status, MV, 0x1UL); + ERR_STATUS_SET_FIELD(clear_ce_status, CE, 0x3UL); + + + for (i = prev.rec.last_node; i < err_record_mappings.num_err_records; i++) { + + const struct err_record_info *info = &err_record_mappings.err_records[i]; + uint32_t idx_start = info->sysreg.idx_start; + uint32_t num_idx = info->sysreg.num_idx; + + uint32_t j; + + j = (i == prev.rec.last_node && prev.value != 0UL) ? + (prev.rec.last_idx + 1U) : 0U; + + for (; j < num_idx; j++) { + + uint64_t status; + uint32_t err_idx = idx_start + j; + + if (err_idx >= RAS_NODE_INDEX_MAX) { + return; + } + + write_errselr_el1(err_idx); + status = read_erxstatus_el1(); + + if (ERR_STATUS_GET_FIELD(status, CE) != 0U) { + write_erxstatus_el1(clear_ce_status); + } + + --nerrs_per_call; + + /* only clear 'nerrs_per_call' errors each time. */ + if (nerrs_per_call <= 0) { + prev.rec.last_idx = j; + prev.rec.last_node = i; + /* save last visited error record index + * into cookie. + */ + *cookie = prev.value; + + return; + } + } + } + + /* + * finish if all ras error records are checked or provided index is out + * of range. + */ + *cookie = 0ULL; + return; +} + +/* Function to probe an error from error record group. */ +static int32_t tegra194_ras_record_probe(const struct err_record_info *info, + int *probe_data) +{ + /* Skip probing if not a silicon platform */ + if (!tegra_platform_is_silicon()) { + return 0; + } + + return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, probe_data); +} + +/* Function to handle error from one given node */ +static int32_t tegra194_ras_node_handler(uint32_t errselr, const char *name, + const struct ras_error *errors, uint64_t status) +{ + bool found = false; + uint32_t ierr = (uint32_t)ERR_STATUS_GET_FIELD(status, IERR); + uint32_t serr = (uint32_t)ERR_STATUS_GET_FIELD(status, SERR); + uint64_t val = 0; + + /* not a valid error. */ + if (ERR_STATUS_GET_FIELD(status, V) == 0U) { + return 0; + } + + ERR_STATUS_SET_FIELD(val, V, 1); + + /* keep the log print same as linux arm64_ras driver. */ + ERROR("**************************************\n"); + ERROR("RAS Error in %s, ERRSELR_EL1=0x%x:\n", name, errselr); + ERROR("\tStatus = 0x%" PRIx64 "\n", status); + + /* Print uncorrectable errror information. */ + if (ERR_STATUS_GET_FIELD(status, UE) != 0U) { + + ERR_STATUS_SET_FIELD(val, UE, 1); + ERR_STATUS_SET_FIELD(val, UET, 1); + + /* IERR to error message */ + for (uint32_t i = 0; errors[i].error_msg != NULL; i++) { + if (ierr == errors[i].error_code) { + ERROR("\tIERR = %s: 0x%x\n", + errors[i].error_msg, ierr); + + found = true; + break; + } + } + + if (!found) { + ERROR("\tUnknown IERR: 0x%x\n", ierr); + } + + ERROR("SERR = %s: 0x%x\n", ras_serr_to_str(serr), serr); + + /* Overflow, multiple errors have been detected. */ + if (ERR_STATUS_GET_FIELD(status, OF) != 0U) { + ERROR("\tOverflow (there may be more errors) - " + "Uncorrectable\n"); + ERR_STATUS_SET_FIELD(val, OF, 1); + } + + ERROR("\tUncorrectable (this is fatal)\n"); + + /* Miscellaneous Register Valid. */ + if (ERR_STATUS_GET_FIELD(status, MV) != 0U) { + ERROR("\tMISC0 = 0x%lx\n", read_erxmisc0_el1()); + ERROR("\tMISC1 = 0x%lx\n", read_erxmisc1_el1()); + ERR_STATUS_SET_FIELD(val, MV, 1); + } + + /* Address Valid. */ + if (ERR_STATUS_GET_FIELD(status, AV) != 0U) { + ERROR("\tADDR = 0x%lx\n", read_erxaddr_el1()); + ERR_STATUS_SET_FIELD(val, AV, 1); + } + + /* Deferred error */ + if (ERR_STATUS_GET_FIELD(status, DE) != 0U) { + ERROR("\tDeferred error\n"); + ERR_STATUS_SET_FIELD(val, DE, 1); + } + + } else { + /* For corrected error, simply clear it. */ + VERBOSE("corrected RAS error is cleared: ERRSELR_EL1:0x%x, " + "IERR:0x%x, SERR:0x%x\n", errselr, ierr, serr); + ERR_STATUS_SET_FIELD(val, CE, 1); + } + + ERROR("**************************************\n"); + + /* Write to clear reported errors. */ + write_erxstatus_el1(val); + + /* error handled */ + return 0; +} + +/* Function to handle one error node from an error record group. */ +static int32_t tegra194_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data __unused) +{ + uint32_t num_idx = info->sysreg.num_idx; + uint32_t idx_start = info->sysreg.idx_start; + const struct ras_aux_data *aux_data = info->aux_data; + const struct ras_error *errors; + uint32_t offset; + const char *node_name; + + uint64_t status = 0ULL; + + VERBOSE("%s\n", __func__); + + assert(probe_data >= 0); + assert((uint32_t)probe_data < num_idx); + + offset = (uint32_t)probe_data; + errors = aux_data[offset].error_records; + node_name = aux_data[offset].name; + + assert(errors != NULL); + + /* Write to ERRSELR_EL1 to select the error record */ + ser_sys_select_record(idx_start + offset); + + /* Retrieve status register from the error record */ + status = read_erxstatus_el1(); + + return tegra194_ras_node_handler(idx_start + offset, node_name, + errors, status); +} + +/* Instantiate RAS nodes */ +PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE) +PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE) +SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE) +CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE) + +/* Instantiate RAS node groups */ +static struct ras_aux_data per_core_ras_group[] = { + PER_CORE_RAS_GROUP_NODES +}; +CASSERT(ARRAY_SIZE(per_core_ras_group) < RAS_NODE_INDEX_MAX, + assert_max_per_core_ras_group_size); + +static struct ras_aux_data per_cluster_ras_group[] = { + PER_CLUSTER_RAS_GROUP_NODES +}; +CASSERT(ARRAY_SIZE(per_cluster_ras_group) < RAS_NODE_INDEX_MAX, + assert_max_per_cluster_ras_group_size); + +static struct ras_aux_data scf_l3_ras_group[] = { + SCF_L3_BANK_RAS_GROUP_NODES +}; +CASSERT(ARRAY_SIZE(scf_l3_ras_group) < RAS_NODE_INDEX_MAX, + assert_max_scf_l3_ras_group_size); + +static struct ras_aux_data ccplex_ras_group[] = { + CCPLEX_RAS_GROUP_NODES +}; +CASSERT(ARRAY_SIZE(ccplex_ras_group) < RAS_NODE_INDEX_MAX, + assert_max_ccplex_ras_group_size); + +/* + * We have same probe and handler for each error record group, use a macro to + * simply the record definition. + */ +#define ADD_ONE_ERR_GROUP(errselr_start, group) \ + ERR_RECORD_SYSREG_V1((errselr_start), (uint32_t)ARRAY_SIZE((group)), \ + &tegra194_ras_record_probe, \ + &tegra194_ras_record_handler, (group)) + +/* RAS error record group information */ +static struct err_record_info carmel_ras_records[] = { + /* + * Per core ras error records + * ERRSELR starts from 0*256 + Logical_CPU_ID*16 + 0 to + * 0*256 + Logical_CPU_ID*16 + 5 for each group. + * 8 cores/groups, 6 * 8 nodes in total. + */ + ADD_ONE_ERR_GROUP(0x000, per_core_ras_group), + ADD_ONE_ERR_GROUP(0x010, per_core_ras_group), + ADD_ONE_ERR_GROUP(0x020, per_core_ras_group), + ADD_ONE_ERR_GROUP(0x030, per_core_ras_group), + ADD_ONE_ERR_GROUP(0x040, per_core_ras_group), + ADD_ONE_ERR_GROUP(0x050, per_core_ras_group), + ADD_ONE_ERR_GROUP(0x060, per_core_ras_group), + ADD_ONE_ERR_GROUP(0x070, per_core_ras_group), + + /* + * Per cluster ras error records + * ERRSELR starts from 2*256 + Logical_Cluster_ID*16 + 0 to + * 2*256 + Logical_Cluster_ID*16 + 3. + * 4 clusters/groups, 3 * 4 nodes in total. + */ + ADD_ONE_ERR_GROUP(0x200, per_cluster_ras_group), + ADD_ONE_ERR_GROUP(0x210, per_cluster_ras_group), + ADD_ONE_ERR_GROUP(0x220, per_cluster_ras_group), + ADD_ONE_ERR_GROUP(0x230, per_cluster_ras_group), + + /* + * SCF L3_Bank ras error records + * ERRSELR: 3*256 + L3_Bank_ID, L3_Bank_ID: 0-3 + * 1 groups, 4 nodes in total. + */ + ADD_ONE_ERR_GROUP(0x300, scf_l3_ras_group), + + /* + * CCPLEX ras error records + * ERRSELR: 4*256 + Unit_ID, Unit_ID: 0 - 4 + * 1 groups, 5 nodes in total. + */ + ADD_ONE_ERR_GROUP(0x400, ccplex_ras_group), +}; + +CASSERT(ARRAY_SIZE(carmel_ras_records) < RAS_NODE_INDEX_MAX, + assert_max_carmel_ras_records_size); + +REGISTER_ERR_RECORD_INFO(carmel_ras_records); + +/* dummy RAS interrupt */ +static struct ras_interrupt carmel_ras_interrupts[] = {}; +REGISTER_RAS_INTERRUPTS(carmel_ras_interrupts); + +/******************************************************************************* + * RAS handler for the platform + ******************************************************************************/ +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ +#if RAS_EXTENSION + tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags); +#else + plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags); +#endif +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c new file mode 100644 index 0000000..9e33cfb --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +extern uint64_t tegra_bl31_phys_base; + +#define MISCREG_AA64_RST_LOW 0x2004U +#define MISCREG_AA64_RST_HIGH 0x2008U + +#define CPU_RESET_MODE_AA64 1U + +/******************************************************************************* + * Setup secondary CPU vectors + ******************************************************************************/ +void plat_secondary_setup(void) +{ + uint32_t addr_low, addr_high; + plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + uint64_t cpu_reset_handler_base, cpu_reset_handler_size, tzdram_addr; + uint64_t src_len_bytes = BL_END - tegra_bl31_phys_base; + int ret; + + INFO("Setting up secondary CPU boot\n"); + + /* map TZDRAM used by BL31 as coherent memory */ + ret = mmap_add_dynamic_region(params_from_bl2->tzdram_base, + params_from_bl2->tzdram_base, + BL31_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + assert(ret == 0); + + tzdram_addr = params_from_bl2->tzdram_base + + tegra194_get_cpu_reset_handler_size(); + + /* + * The BL31 code resides in the TZSRAM which loses state + * when we enter System Suspend. Copy the wakeup trampoline + * code to TZDRAM to help us exit from System Suspend. + */ + cpu_reset_handler_base = tegra194_get_cpu_reset_handler_base(); + cpu_reset_handler_size = tegra194_get_cpu_reset_handler_size(); + memcpy((void *)((uintptr_t)params_from_bl2->tzdram_base), + (void *)((uintptr_t)cpu_reset_handler_base), + cpu_reset_handler_size); + + /* TZDRAM base will be used as the "resume" address */ + addr_low = (uint32_t)params_from_bl2->tzdram_base | CPU_RESET_MODE_AA64; + addr_high = (uint32_t)((params_from_bl2->tzdram_base >> 32U) & 0x7ffU); + + /* write lower 32 bits first, then the upper 11 bits */ + mmio_write_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_LOW, addr_low); + assert(mmio_read_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_LOW) == addr_low); + mmio_write_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_HIGH, addr_high); + assert(mmio_read_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_HIGH) == addr_high); + + /* save reset vector to be used during SYSTEM_SUSPEND exit */ + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO, + addr_low); + assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO) == addr_low); + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI, + addr_high); + assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI) == addr_high); + mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_LO, + (uint32_t)tzdram_addr); + assert(mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_LO) == (uint32_t)tzdram_addr); + mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_HI, + (uint32_t)src_len_bytes); + assert(mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_HI) == (uint32_t)src_len_bytes); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c new file mode 100644 index 0000000..af5cf70 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2019-2020, NVIDIA 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 +#include +#include + +/* ID for spe-console */ +#define TEGRA_CONSOLE_SPE_ID 0xFE + +/******************************************************************************* + * Structure to store the SCR addresses and its expected settings. + ******************************************************************************* + */ +typedef struct { + uint32_t scr_addr; + uint32_t scr_val; +} scr_settings_t; + +static const scr_settings_t t194_scr_settings[] = { + { SCRATCH_RSV68_SCR, SCRATCH_RSV68_SCR_VAL }, + { SCRATCH_RSV71_SCR, SCRATCH_RSV71_SCR_VAL }, + { SCRATCH_RSV72_SCR, SCRATCH_RSV72_SCR_VAL }, + { SCRATCH_RSV75_SCR, SCRATCH_RSV75_SCR_VAL }, + { SCRATCH_RSV81_SCR, SCRATCH_RSV81_SCR_VAL }, + { SCRATCH_RSV97_SCR, SCRATCH_RSV97_SCR_VAL }, + { SCRATCH_RSV99_SCR, SCRATCH_RSV99_SCR_VAL }, + { SCRATCH_RSV109_SCR, SCRATCH_RSV109_SCR_VAL }, + { MISCREG_SCR_SCRTZWELCK, MISCREG_SCR_SCRTZWELCK_VAL } +}; + +/******************************************************************************* + * The Tegra power domain tree has a single system level power domain i.e. a + * single root node. The first entry in the power domain descriptor specifies + * the number of power domains at the highest power level. + ******************************************************************************* + */ +static const uint8_t tegra_power_domain_tree_desc[] = { + /* No of root nodes */ + 1, + /* No of clusters */ + PLATFORM_CLUSTER_COUNT, + /* No of CPU cores - cluster0 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster1 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster2 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster3 */ + PLATFORM_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the Tegra default topology tree information. + ******************************************************************************/ +const uint8_t *plat_get_power_domain_tree_desc(void) +{ + return tegra_power_domain_tree_desc; +} + +/* + * Table of regions to map using the MMU. + */ +static const mmap_region_t tegra_mmap[] = { + MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x4000U, /* 16KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_GPCDMA_BASE, 0x10000U, /* 64KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x8000U, /* 32KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_MC_BASE, 0x8000U, /* 32KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#if !ENABLE_CONSOLE_SPE + MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000U, /* 128KB - UART A, B*/ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000U, /* 128KB - UART C, G */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000U, /* 192KB - UART D, E, F */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#endif + MAP_REGION_FLAT(TEGRA_XUSB_PADCTL_BASE, 0x2000U, /* 8KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x1000, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_GICC_BASE, 0x1000, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_HSP_DBELL_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#if ENABLE_CONSOLE_SPE + MAP_REGION_FLAT(TEGRA_CONSOLE_SPE_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#endif + MAP_REGION_FLAT(TEGRA_TMRUS_BASE, TEGRA_TMRUS_SIZE, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_SMMU2_BASE, 0x800000U, /* 8MB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_SMMU1_BASE, 0x800000U, /* 8MB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x800000U, /* 8MB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_BPMP_IPC_TX_PHYS_BASE, 0x10000U, /* 64KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000U, /* 64KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + {0} +}; + +/******************************************************************************* + * Set up the pagetables as per the platform memory map & initialize the MMU + ******************************************************************************/ +const mmap_region_t *plat_get_mmio_map(void) +{ + /* MMIO space */ + return tegra_mmap; +} + +/******************************************************************************* + * Handler to get the System Counter Frequency + ******************************************************************************/ +uint32_t plat_get_syscnt_freq2(void) +{ + return 31250000; +} + +#if !ENABLE_CONSOLE_SPE +/******************************************************************************* + * Maximum supported UART controllers + ******************************************************************************/ +#define TEGRA194_MAX_UART_PORTS 7 + +/******************************************************************************* + * This variable holds the UART port base addresses + ******************************************************************************/ +static uint32_t tegra194_uart_addresses[TEGRA194_MAX_UART_PORTS + 1] = { + 0, /* undefined - treated as an error case */ + TEGRA_UARTA_BASE, + TEGRA_UARTB_BASE, + TEGRA_UARTC_BASE, + TEGRA_UARTD_BASE, + TEGRA_UARTE_BASE, + TEGRA_UARTF_BASE, + TEGRA_UARTG_BASE +}; +#endif + +/******************************************************************************* + * Enable console corresponding to the console ID + ******************************************************************************/ +void plat_enable_console(int32_t id) +{ + uint32_t console_clock = 0U; + +#if ENABLE_CONSOLE_SPE + static console_t spe_console; + + if (id == TEGRA_CONSOLE_SPE_ID) { + (void)console_spe_register(TEGRA_CONSOLE_SPE_BASE, + console_clock, + TEGRA_CONSOLE_BAUDRATE, + &spe_console); + console_set_scope(&spe_console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH); + } +#else + static console_t uart_console; + + if ((id > 0) && (id < TEGRA194_MAX_UART_PORTS)) { + /* + * Reference clock used by the FPGAs is a lot slower. + */ + if (tegra_platform_is_fpga()) { + console_clock = TEGRA_BOOT_UART_CLK_13_MHZ; + } else { + console_clock = TEGRA_BOOT_UART_CLK_408_MHZ; + } + + (void)console_16550_register(tegra194_uart_addresses[id], + console_clock, + TEGRA_CONSOLE_BAUDRATE, + &uart_console); + console_set_scope(&uart_console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH); + } +#endif +} + +/******************************************************************************* + * Verify SCR settings + ******************************************************************************/ +static inline bool tegra194_is_scr_valid(void) +{ + uint32_t scr_val; + bool ret = true; + + for (uint8_t i = 0U; i < ARRAY_SIZE(t194_scr_settings); i++) { + scr_val = mmio_read_32((uintptr_t)t194_scr_settings[i].scr_addr); + if (scr_val != t194_scr_settings[i].scr_val) { + ERROR("Mismatch at SCR addr = 0x%x\n", t194_scr_settings[i].scr_addr); + ret = false; + } + } + return ret; +} + +/******************************************************************************* + * Handler for early platform setup + ******************************************************************************/ +void plat_early_platform_setup(void) +{ + const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + uint8_t enable_ccplex_lock_step = params_from_bl2->enable_ccplex_lock_step; + uint64_t actlr_elx; + + /* Verify chip id is t194 */ + assert(tegra_chipid_is_t194()); + + /* Verify SCR settings */ + if (tegra_platform_is_silicon()) { + assert(tegra194_is_scr_valid()); + } + + /* sanity check MCE firmware compatibility */ + mce_verify_firmware_version(); + +#if RAS_EXTENSION + /* Enable Uncorrectable RAS error */ + tegra194_ras_enable(); +#endif + + /* + * Program XUSB STREAMIDs + * ====================== + * T19x XUSB has support for XUSB virtualization. It will have one + * physical function (PF) and four Virtual function (VF) + * + * There were below two SIDs for XUSB until T186. + * 1) #define TEGRA_SID_XUSB_HOST 0x1bU + * 2) #define TEGRA_SID_XUSB_DEV 0x1cU + * + * We have below four new SIDs added for VF(s) + * 3) #define TEGRA_SID_XUSB_VF0 0x5dU + * 4) #define TEGRA_SID_XUSB_VF1 0x5eU + * 5) #define TEGRA_SID_XUSB_VF2 0x5fU + * 6) #define TEGRA_SID_XUSB_VF3 0x60U + * + * When virtualization is enabled then we have to disable SID override + * and program above SIDs in below newly added SID registers in XUSB + * PADCTL MMIO space. These registers are TZ protected and so need to + * be done in ATF. + * a) #define XUSB_PADCTL_HOST_AXI_STREAMID_PF_0 (0x136cU) + * b) #define XUSB_PADCTL_DEV_AXI_STREAMID_PF_0 (0x139cU) + * c) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_0 (0x1370U) + * d) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_1 (0x1374U) + * e) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_2 (0x1378U) + * f) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_3 (0x137cU) + * + * This change disables SID override and programs XUSB SIDs in + * above registers to support both virtualization and + * non-virtualization platforms + */ + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_HOST); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_HOST); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_0, TEGRA_SID_XUSB_VF0); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_0) == TEGRA_SID_XUSB_VF0); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_1, TEGRA_SID_XUSB_VF1); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_1) == TEGRA_SID_XUSB_VF1); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_2, TEGRA_SID_XUSB_VF2); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_2) == TEGRA_SID_XUSB_VF2); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_3, TEGRA_SID_XUSB_VF3); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_HOST_AXI_STREAMID_VF_3) == TEGRA_SID_XUSB_VF3); + mmio_write_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_DEV_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_DEV); + assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + + XUSB_PADCTL_DEV_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_DEV); + } + + /* + * Enable dual execution optimized translations for all ELx. + */ + if (enable_ccplex_lock_step != 0U) { + actlr_elx = read_actlr_el3(); + actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL3; + write_actlr_el3(actlr_elx); + /* check if the bit is actually set */ + assert((read_actlr_el3() & DENVER_CPU_ENABLE_DUAL_EXEC_EL3) != 0ULL); + + actlr_elx = read_actlr_el2(); + actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL2; + write_actlr_el2(actlr_elx); + /* check if the bit is actually set */ + assert((read_actlr_el2() & DENVER_CPU_ENABLE_DUAL_EXEC_EL2) != 0ULL); + + actlr_elx = read_actlr_el1(); + actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL1; + write_actlr_el1(actlr_elx); + /* check if the bit is actually set */ + assert((read_actlr_el1() & DENVER_CPU_ENABLE_DUAL_EXEC_EL1) != 0ULL); + } + +#if TRAP_LOWER_EL_ERR_ACCESS + /* + * SCR_EL3.TERR: Error register(ER*_EL1) accesses from EL1 or EL2 + * generate a Trap exception to EL3. + */ + scr_el3 = (uint32_t)read_scr(); + scr_el3 |= SCR_TERR_BIT; + write_scr(scr_el3); +#endif + +#if ENABLE_TEGRA_PERFMON + /* + * Enable Uncore Perfmon counters to aid in debugging. + * + * When set, events are allowed to be counted in the NVIDIA-specific + * Performance Monitors extension. + */ + actlr_elx = read_actlr_el3(); + actlr_elx |= DENVER_CPU_ENABLE_SPME; + write_actlr_el3(actlr_elx); +#endif +} + +/* Secure IRQs for Tegra194 */ +static const interrupt_prop_t tegra194_interrupt_props[] = { + INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(TEGRA194_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE) +}; + +/******************************************************************************* + * Initialize the GIC and SGIs + ******************************************************************************/ +void plat_gic_setup(void) +{ + tegra_gic_setup(tegra194_interrupt_props, ARRAY_SIZE(tegra194_interrupt_props)); + tegra_gic_init(); + + /* + * Initialize the FIQ handler + */ + tegra_fiq_handler_setup(); +} + +/******************************************************************************* + * Return pointer to the BL31 params from previous bootloader + ******************************************************************************/ +struct tegra_bl31_params *plat_get_bl31_params(void) +{ + uint64_t val; + + val = (mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_HI_ADDR) & + SCRATCH_BL31_PARAMS_HI_ADDR_MASK) >> SCRATCH_BL31_PARAMS_HI_ADDR_SHIFT; + val <<= 32; + val |= mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_LO_ADDR); + + return (struct tegra_bl31_params *)(uintptr_t)val; +} + +/******************************************************************************* + * Return pointer to the BL31 platform params from previous bootloader + ******************************************************************************/ +plat_params_from_bl2_t *plat_get_bl31_plat_params(void) +{ + uint64_t val; + + val = (mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_HI_ADDR) & + SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_MASK) >> SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT; + val <<= 32; + val |= mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_LO_ADDR); + + return (plat_params_from_bl2_t *)(uintptr_t)val; +} + +/******************************************************************************* + * Handler for late platform setup + ******************************************************************************/ +void plat_late_platform_setup(void) +{ + /* Initialize SMMU registers */ + tegra_smmu_init(); + +#if ENABLE_STRICT_CHECKING_MODE + /* + * Enable strict checking after programming the GSC for + * enabling TZSRAM and TZDRAM + */ + mce_enable_strict_checking(); + mce_verify_strict_checking(); +#endif +} + +/******************************************************************************* + * Handler to indicate support for System Suspend + ******************************************************************************/ +bool plat_supports_system_suspend(void) +{ + return true; +} + +/******************************************************************************* + * Platform specific runtime setup. + ******************************************************************************/ +void plat_runtime_setup(void) +{ + /* + * During cold boot, it is observed that the arbitration + * bit is set in the Memory controller leading to false + * error interrupts in the non-secure world. To avoid + * this, clean the interrupt status register before + * booting into the non-secure world + */ + tegra_memctrl_clear_pending_interrupts(); + + /* + * During boot, USB3 and flash media (SDMMC/SATA) devices need + * access to IRAM. Because these clients connect to the MC and + * do not have a direct path to the IRAM, the MC implements AHB + * redirection during boot to allow path to IRAM. In this mode + * accesses to a programmed memory address aperture are directed + * to the AHB bus, allowing access to the IRAM. This mode must be + * disabled before we jump to the non-secure world. + */ + tegra_memctrl_disable_ahb_redirection(); + + /* + * Verify the integrity of the previously configured SMMU(s) settings + */ + tegra_smmu_verify(); +} + +/******************************************************************************* + * Return pointer to the bpmp_ipc_data + ******************************************************************************/ +static struct bpmp_ipc_platform_data bpmp_ipc; +struct bpmp_ipc_platform_data *plat_get_bpmp_ipc_data(void) +{ + bpmp_ipc.bpmp_ipc_tx_base = TEGRA_BPMP_IPC_TX_PHYS_BASE; + bpmp_ipc.bpmp_ipc_rx_base = TEGRA_BPMP_IPC_RX_PHYS_BASE; + bpmp_ipc.bpmp_ipc_map_size = TEGRA_BPMP_IPC_CH_MAP_SIZE; + + return &bpmp_ipc; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c new file mode 100644 index 0000000..35f7302 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2019-2020, NVIDIA 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 + +/******************************************************************************* + * Tegra194 SiP SMCs + ******************************************************************************/ +#define TEGRA_SIP_GET_SMMU_PER 0xC200FF00U +#define TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS 0xC200FF01U + +/******************************************************************************* + * This function is responsible for handling all T194 SiP calls + ******************************************************************************/ +int32_t plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + const void *cookie, + void *handle, + uint64_t flags) +{ + int32_t ret = 0; + uint32_t i, smmu_per[6] = {0}; + uint32_t num_smmu_devices = plat_get_num_smmu_devices(); + uint64_t per[3] = {0ULL}; + + (void)x1; + (void)x4; + (void)cookie; + (void)flags; + + switch (smc_fid) { + case TEGRA_SIP_GET_SMMU_PER: + + /* make sure we dont go past the array length */ + assert(num_smmu_devices <= ARRAY_SIZE(smmu_per)); + + /* read all supported SMMU_PER records */ + for (i = 0U; i < num_smmu_devices; i++) { + smmu_per[i] = tegra_smmu_read_32(i, SMMU_GSR0_PER); + } + + /* pack results into 3 64bit variables. */ + per[0] = smmu_per[0] | ((uint64_t)smmu_per[1] << 32U); + per[1] = smmu_per[2] | ((uint64_t)smmu_per[3] << 32U); + per[2] = smmu_per[4] | ((uint64_t)smmu_per[5] << 32U); + + /* provide the results via X1-X3 CPU registers */ + write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, per[0]); + write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X2, per[1]); + write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X3, per[2]); + + break; + +#if RAS_EXTENSION + case TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS: + { + /* + * clear all RAS error records for corrected errors at first. + * x1 shall be 0 for first SMC call after FHI is asserted. + * */ + uint64_t local_x1 = x1; + + tegra194_ras_corrected_err_clear(&local_x1); + if (local_x1 == 0ULL) { + /* clear HSM corrected error status after all corrected + * RAS errors are cleared. + */ + mce_clear_hsm_corr_status(); + } + + write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, local_x1); + + break; + } +#endif + + default: + ret = -ENOTSUP; + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c new file mode 100644 index 0000000..310e951 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define BOARD_SYSTEM_FPGA_BASE U(1) +#define BASE_CONFIG_SMMU_DEVICES U(2) +#define MAX_NUM_SMMU_DEVICES U(3) + +static uint32_t tegra_misc_read_32(uint32_t off) +{ + return mmio_read_32((uintptr_t)TEGRA_MISC_BASE + off); +} + +/******************************************************************************* + * Handler to return the support SMMU devices number + ******************************************************************************/ +uint32_t plat_get_num_smmu_devices(void) +{ + uint32_t ret_num = MAX_NUM_SMMU_DEVICES; + uint32_t board_revid = ((tegra_misc_read_32(MISCREG_EMU_REVID) >> \ + BOARD_SHIFT_BITS) & BOARD_MASK_BITS); + + if (board_revid == BOARD_SYSTEM_FPGA_BASE) { + ret_num = BASE_CONFIG_SMMU_DEVICES; + } + + return ret_num; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S new file mode 100644 index 0000000..0ff5407 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#define TEGRA194_STATE_SYSTEM_SUSPEND 0x5C7 +#define TEGRA194_STATE_SYSTEM_RESUME 0x600D +#define TEGRA194_MC_CTX_SIZE 0xFB + + .align 4 + .globl tegra194_cpu_reset_handler + +/* CPU reset handler routine */ +func tegra194_cpu_reset_handler + /* check if we are exiting system suspend state */ + adr x0, __tegra194_system_suspend_state + ldr x1, [x0] + mov x2, #TEGRA194_STATE_SYSTEM_SUSPEND + lsl x2, x2, #16 + add x2, x2, #TEGRA194_STATE_SYSTEM_SUSPEND + cmp x1, x2 + bne boot_cpu + + /* set system resume state */ + mov x1, #TEGRA194_STATE_SYSTEM_RESUME + lsl x1, x1, #16 + mov x2, #TEGRA194_STATE_SYSTEM_RESUME + add x1, x1, x2 + str x1, [x0] + dsb sy + + /* prepare to relocate to TZSRAM */ + mov x0, #BL31_BASE + adr x1, __tegra194_cpu_reset_handler_end + adr x2, __tegra194_cpu_reset_handler_data + ldr x2, [x2, #8] + + /* memcpy16 */ +m_loop16: + cmp x2, #16 + b.lt 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, boot_cpu + ldrb w3, [x1], #1 + strb w3, [x0], #1 + subs x2, x2, #1 + b.ne m_loop1 + + /* + * Synchronization barriers to make sure that memory is flushed out + * before we start execution in SysRAM. + */ + dsb sy + isb + +boot_cpu: + adr x0, __tegra194_cpu_reset_handler_data + ldr x0, [x0] + br x0 +endfunc tegra194_cpu_reset_handler + + /* + * Tegra194 reset data (offset 0x0 - 0x2490) + * + * 0x0000: secure world's entrypoint + * 0x0008: BL31 size (RO + RW) + * 0x0010: MC context start + * 0x2490: MC context end + */ + + .align 4 + .type __tegra194_cpu_reset_handler_data, %object + .globl __tegra194_cpu_reset_handler_data +__tegra194_cpu_reset_handler_data: + .quad tegra_secure_entrypoint + .quad __BL31_END__ - BL31_BASE + .globl __tegra194_system_suspend_state +__tegra194_system_suspend_state: + .quad 0 + + .align 4 +__tegra194_mc_context: + .rept TEGRA194_MC_CTX_SIZE + .quad 0 + .endr + .size __tegra194_cpu_reset_handler_data, \ + . - __tegra194_cpu_reset_handler_data + + .align 4 + .globl __tegra194_cpu_reset_handler_end +__tegra194_cpu_reset_handler_end: + + .globl tegra194_get_cpu_reset_handler_size + .globl tegra194_get_cpu_reset_handler_base + .globl tegra194_get_mc_ctx_offset + .globl tegra194_set_system_suspend_entry + +/* return size of the CPU reset handler */ +func tegra194_get_cpu_reset_handler_size + adr x0, __tegra194_cpu_reset_handler_end + adr x1, tegra194_cpu_reset_handler + sub x0, x0, x1 + ret +endfunc tegra194_get_cpu_reset_handler_size + +/* return the start address of the CPU reset handler */ +func tegra194_get_cpu_reset_handler_base + adr x0, tegra194_cpu_reset_handler + ret +endfunc tegra194_get_cpu_reset_handler_base + +/* return the size of the MC context */ +func tegra194_get_mc_ctx_offset + adr x0, __tegra194_mc_context + adr x1, tegra194_cpu_reset_handler + sub x0, x0, x1 + ret +endfunc tegra194_get_mc_ctx_offset + +/* set system suspend state before SC7 entry */ +func tegra194_set_system_suspend_entry + mov x0, #TEGRA_MC_BASE + mov x3, #MC_SECURITY_CFG3_0 + ldr w1, [x0, x3] + lsl x1, x1, #32 + mov x3, #MC_SECURITY_CFG0_0 + ldr w2, [x0, x3] + orr x3, x1, x2 /* TZDRAM base */ + adr x0, __tegra194_system_suspend_state + adr x1, tegra194_cpu_reset_handler + sub x2, x0, x1 /* offset in TZDRAM */ + mov x0, #TEGRA194_STATE_SYSTEM_SUSPEND + lsl x0, x0, #16 + add x0, x0, #TEGRA194_STATE_SYSTEM_SUSPEND + str x0, [x3, x2] /* set value in TZDRAM */ + dsb sy + ret +endfunc tegra194_set_system_suspend_entry diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/platform_t194.mk b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/platform_t194.mk new file mode 100644 index 0000000..a184b4a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/platform_t194.mk @@ -0,0 +1,91 @@ +# +# Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +# platform configs +ENABLE_CONSOLE_SPE := 1 +$(eval $(call add_define,ENABLE_CONSOLE_SPE)) + +ENABLE_TEGRA_PERFMON ?= 1 +$(eval $(call add_define,ENABLE_TEGRA_PERFMON)) + +ENABLE_STRICT_CHECKING_MODE := 1 +$(eval $(call add_define,ENABLE_STRICT_CHECKING_MODE)) + +USE_GPC_DMA := 1 +$(eval $(call add_define,USE_GPC_DMA)) + +RESET_TO_BL31 := 1 + +PROGRAMMABLE_RESET_ADDRESS := 1 + +COLD_BOOT_SINGLE_CPU := 1 + +# platform settings +PLAT_BL31_BASE := 0x40000000 +$(eval $(call add_define,PLAT_BL31_BASE)) + +MAX_XLAT_TABLES := 25 +$(eval $(call add_define,MAX_XLAT_TABLES)) + +MAX_MMAP_REGIONS := 30 +$(eval $(call add_define,MAX_MMAP_REGIONS)) + +# enable RAS handling +HANDLE_EA_EL3_FIRST := 1 +RAS_EXTENSION := 1 + +# include common makefiles +include plat/nvidia/tegra/common/tegra_common.mk + +# platform files +PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t194 \ + -I${SOC_DIR}/drivers/include + +BL31_SOURCES += ${TEGRA_GICv2_SOURCES} \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/cpus/aarch64/denver.S \ + ${TEGRA_DRIVERS}/bpmp_ipc/intf.c \ + ${TEGRA_DRIVERS}/bpmp_ipc/ivc.c \ + ${TEGRA_DRIVERS}/memctrl/memctrl_v2.c \ + ${TEGRA_DRIVERS}/smmu/smmu.c \ + ${SOC_DIR}/drivers/mce/mce.c \ + ${SOC_DIR}/drivers/mce/nvg.c \ + ${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \ + ${SOC_DIR}/drivers/se/se.c \ + ${SOC_DIR}/plat_memctrl.c \ + ${SOC_DIR}/plat_psci_handlers.c \ + ${SOC_DIR}/plat_setup.c \ + ${SOC_DIR}/plat_secondary.c \ + ${SOC_DIR}/plat_sip_calls.c \ + ${SOC_DIR}/plat_smmu.c \ + ${SOC_DIR}/plat_trampoline.S + +ifeq (${USE_GPC_DMA}, 1) +BL31_SOURCES += ${TEGRA_DRIVERS}/gpcdma/gpcdma.c +endif + +ifeq (${ENABLE_CONSOLE_SPE},1) +BL31_SOURCES += ${TEGRA_DRIVERS}/spe/shared_console.S +endif + +# RAS sources +ifeq (${RAS_EXTENSION},1) +BL31_SOURCES += lib/extensions/ras/std_err_record.c \ + lib/extensions/ras/ras_common.c \ + ${SOC_DIR}/plat_ras.c +endif + +# SPM dispatcher +ifeq (${SPD},spmd) +include lib/libfdt/libfdt.mk +# sources to support spmd +BL31_SOURCES += plat/common/plat_spmd_manifest.c \ + ${LIBFDT_SRCS} + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} +endif diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h new file mode 100644 index 0000000..c44b0fc --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h @@ -0,0 +1,663 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SE_PRIVATE_H +#define SE_PRIVATE_H + +#include +#include + +/* + * PMC registers + */ + +/* SC7 context save scratch register for T210 */ +#define PMC_SCRATCH43_REG_OFFSET U(0x22C) + +/* Secure scratch registers */ +#define PMC_SECURE_SCRATCH4_OFFSET 0xC0U +#define PMC_SECURE_SCRATCH5_OFFSET 0xC4U +#define PMC_SECURE_SCRATCH6_OFFSET 0x224U +#define PMC_SECURE_SCRATCH7_OFFSET 0x228U +#define PMC_SECURE_SCRATCH116_OFFSET 0xB28U +#define PMC_SECURE_SCRATCH117_OFFSET 0xB2CU +#define PMC_SECURE_SCRATCH120_OFFSET 0xB38U +#define PMC_SECURE_SCRATCH121_OFFSET 0xB3CU +#define PMC_SECURE_SCRATCH122_OFFSET 0xB40U +#define PMC_SECURE_SCRATCH123_OFFSET 0xB44U + +/* + * AHB arbitration memory write queue + */ +#define ARAHB_MEM_WRQUE_MST_ID_OFFSET 0xFCU +#define ARAHB_MST_ID_SE2_MASK (0x1U << 13) +#define ARAHB_MST_ID_SE_MASK (0x1U << 14) + +/** + * SE registers + */ +#define TEGRA_SE_AES_KEYSLOT_COUNT 16 +#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF + +/* SE Status register */ +#define SE_STATUS_OFFSET 0x800U +#define SE_STATUS_SHIFT 0 +#define SE_STATUS_IDLE \ + ((0U) << SE_STATUS_SHIFT) +#define SE_STATUS_BUSY \ + ((1U) << SE_STATUS_SHIFT) +#define SE_STATUS(x) \ + ((x) & ((0x3U) << SE_STATUS_SHIFT)) + +#define SE_MEM_INTERFACE_SHIFT 2 +#define SE_MEM_INTERFACE_IDLE 0 +#define SE_MEM_INTERFACE_BUSY 1 +#define SE_MEM_INTERFACE(x) ((x) << SE_STATUS_SHIFT) + +/* SE register definitions */ +#define SE_SECURITY_REG_OFFSET 0x0 +#define SE_SECURITY_TZ_LOCK_SOFT_SHIFT 5 +#define SE_SECURE 0x0 +#define SE_SECURITY_TZ_LOCK_SOFT(x) ((x) << SE_SECURITY_TZ_LOCK_SOFT_SHIFT) + +#define SE_SEC_ENG_DIS_SHIFT 1 +#define SE_DISABLE_FALSE 0 +#define SE_DISABLE_TRUE 1 +#define SE_SEC_ENG_DISABLE(x)((x) << SE_SEC_ENG_DIS_SHIFT) + +/* SE config register */ +#define SE_CONFIG_REG_OFFSET 0x14U +#define SE_CONFIG_ENC_ALG_SHIFT 12 +#define SE_CONFIG_ENC_ALG_AES_ENC \ + ((1U) << SE_CONFIG_ENC_ALG_SHIFT) +#define SE_CONFIG_ENC_ALG_RNG \ + ((2U) << SE_CONFIG_ENC_ALG_SHIFT) +#define SE_CONFIG_ENC_ALG_SHA \ + ((3U) << SE_CONFIG_ENC_ALG_SHIFT) +#define SE_CONFIG_ENC_ALG_RSA \ + ((4U) << SE_CONFIG_ENC_ALG_SHIFT) +#define SE_CONFIG_ENC_ALG_NOP \ + ((0U) << SE_CONFIG_ENC_ALG_SHIFT) +#define SE_CONFIG_ENC_ALG(x) \ + ((x) & ((0xFU) << SE_CONFIG_ENC_ALG_SHIFT)) + +#define SE_CONFIG_DEC_ALG_SHIFT 8 +#define SE_CONFIG_DEC_ALG_AES \ + ((1U) << SE_CONFIG_DEC_ALG_SHIFT) +#define SE_CONFIG_DEC_ALG_NOP \ + ((0U) << SE_CONFIG_DEC_ALG_SHIFT) +#define SE_CONFIG_DEC_ALG(x) \ + ((x) & ((0xFU) << SE_CONFIG_DEC_ALG_SHIFT)) + +#define SE_CONFIG_DST_SHIFT 2 +#define SE_CONFIG_DST_MEMORY \ + ((0U) << SE_CONFIG_DST_SHIFT) +#define SE_CONFIG_DST_HASHREG \ + ((1U) << SE_CONFIG_DST_SHIFT) +#define SE_CONFIG_DST_KEYTAB \ + ((2U) << SE_CONFIG_DST_SHIFT) +#define SE_CONFIG_DST_SRK \ + ((3U) << SE_CONFIG_DST_SHIFT) +#define SE_CONFIG_DST_RSAREG \ + ((4U) << SE_CONFIG_DST_SHIFT) +#define SE_CONFIG_DST(x) \ + ((x) & ((0x7U) << SE_CONFIG_DST_SHIFT)) + +#define SE_CONFIG_ENC_MODE_SHIFT 24 +#define SE_CONFIG_ENC_MODE_KEY128 \ + ((0UL) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE_KEY192 \ + ((1UL) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE_KEY256 \ + ((2UL) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE_SHA1 \ + ((0UL) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE_SHA224 \ + ((4UL) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE_SHA256 \ + ((5UL) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE_SHA384 \ + ((6UL) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE_SHA512 \ + ((7UL) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE(x)\ + ((x) & ((0xFFUL) << SE_CONFIG_ENC_MODE_SHIFT)) + +#define SE_CONFIG_DEC_MODE_SHIFT 16 +#define SE_CONFIG_DEC_MODE_KEY128 \ + ((0UL) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE_KEY192 \ + ((1UL) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE_KEY256 \ + ((2UL) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE_SHA1 \ + ((0UL) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE_SHA224 \ + ((4UL) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE_SHA256 \ + ((5UL) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE_SHA384 \ + ((6UL) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE_SHA512 \ + ((7UL) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE(x)\ + ((x) & ((0xFFUL) << SE_CONFIG_DEC_MODE_SHIFT)) + + +/* DRBG random number generator config */ +#define SE_RNG_CONFIG_REG_OFFSET 0x340 + +#define DRBG_MODE_SHIFT 0 +#define DRBG_MODE_NORMAL \ + ((0U) << DRBG_MODE_SHIFT) +#define DRBG_MODE_FORCE_INSTANTION \ + ((1U) << DRBG_MODE_SHIFT) +#define DRBG_MODE_FORCE_RESEED \ + ((2U) << DRBG_MODE_SHIFT) +#define SE_RNG_CONFIG_MODE(x) \ + ((x) & ((0x3U) << DRBG_MODE_SHIFT)) + +#define DRBG_SRC_SHIFT 2 +#define DRBG_SRC_NONE \ + ((0U) << DRBG_SRC_SHIFT) +#define DRBG_SRC_ENTROPY \ + ((1U) << DRBG_SRC_SHIFT) +#define DRBG_SRC_LFSR \ + ((2U) << DRBG_SRC_SHIFT) +#define SE_RNG_SRC_CONFIG_MODE(x) \ + ((x) & ((0x3U) << DRBG_SRC_SHIFT)) + +/* DRBG random number generator entropy config */ + +#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344U + +#define DRBG_RO_ENT_SRC_SHIFT 1 +#define DRBG_RO_ENT_SRC_ENABLE \ + ((1U) << DRBG_RO_ENT_SRC_SHIFT) +#define DRBG_RO_ENT_SRC_DISABLE \ + ((0U) << DRBG_RO_ENT_SRC_SHIFT) +#define SE_RNG_SRC_CONFIG_RO_ENT_SRC(x) \ + ((x) & ((0x1U) << DRBG_RO_ENT_SRC_SHIFT)) + +#define DRBG_RO_ENT_SRC_LOCK_SHIFT 0 +#define DRBG_RO_ENT_SRC_LOCK_ENABLE \ + ((1U) << DRBG_RO_ENT_SRC_LOCK_SHIFT) +#define DRBG_RO_ENT_SRC_LOCK_DISABLE \ + ((0U) << DRBG_RO_ENT_SRC_LOCK_SHIFT) +#define SE_RNG_SRC_CONFIG_RO_ENT_SRC_LOCK(x) \ + ((x) & ((0x1U) << DRBG_RO_ENT_SRC_LOCK_SHIFT)) + +#define DRBG_RO_ENT_IGNORE_MEM_SHIFT 12 +#define DRBG_RO_ENT_IGNORE_MEM_ENABLE \ + ((1U) << DRBG_RO_ENT_IGNORE_MEM_SHIFT) +#define DRBG_RO_ENT_IGNORE_MEM_DISABLE \ + ((0U) << DRBG_RO_ENT_IGNORE_MEM_SHIFT) +#define SE_RNG_SRC_CONFIG_RO_ENT_IGNORE_MEM(x) \ + ((x) & ((0x1U) << DRBG_RO_ENT_IGNORE_MEM_SHIFT)) + +#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348 + +/* SE CRYPTO */ +#define SE_CRYPTO_REG_OFFSET 0x304 +#define SE_CRYPTO_HASH_SHIFT 0 +#define SE_CRYPTO_HASH_DISABLE \ + ((0U) << SE_CRYPTO_HASH_SHIFT) +#define SE_CRYPTO_HASH_ENABLE \ + ((1U) << SE_CRYPTO_HASH_SHIFT) + +#define SE_CRYPTO_XOR_POS_SHIFT 1 +#define SE_CRYPTO_XOR_BYPASS \ + ((0U) << SE_CRYPTO_XOR_POS_SHIFT) +#define SE_CRYPTO_XOR_TOP \ + ((2U) << SE_CRYPTO_XOR_POS_SHIFT) +#define SE_CRYPTO_XOR_BOTTOM \ + ((3U) << SE_CRYPTO_XOR_POS_SHIFT) + +#define SE_CRYPTO_INPUT_SEL_SHIFT 3 +#define SE_CRYPTO_INPUT_AHB \ + ((0U) << SE_CRYPTO_INPUT_SEL_SHIFT) +#define SE_CRYPTO_INPUT_RANDOM \ + ((1U) << SE_CRYPTO_INPUT_SEL_SHIFT) +#define SE_CRYPTO_INPUT_AESOUT \ + ((2U) << SE_CRYPTO_INPUT_SEL_SHIFT) +#define SE_CRYPTO_INPUT_LNR_CTR \ + ((3U) << SE_CRYPTO_INPUT_SEL_SHIFT) + +#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5 +#define SE_CRYPTO_VCTRAM_AHB \ + ((0U) << SE_CRYPTO_VCTRAM_SEL_SHIFT) +#define SE_CRYPTO_VCTRAM_AESOUT \ + ((2U) << SE_CRYPTO_VCTRAM_SEL_SHIFT) +#define SE_CRYPTO_VCTRAM_PREVAHB \ + ((3U) << SE_CRYPTO_VCTRAM_SEL_SHIFT) + +#define SE_CRYPTO_IV_SEL_SHIFT 7 +#define SE_CRYPTO_IV_ORIGINAL \ + ((0U) << SE_CRYPTO_IV_SEL_SHIFT) +#define SE_CRYPTO_IV_UPDATED \ + ((1U) << SE_CRYPTO_IV_SEL_SHIFT) + +#define SE_CRYPTO_CORE_SEL_SHIFT 8 +#define SE_CRYPTO_CORE_DECRYPT \ + ((0U) << SE_CRYPTO_CORE_SEL_SHIFT) +#define SE_CRYPTO_CORE_ENCRYPT \ + ((1U) << SE_CRYPTO_CORE_SEL_SHIFT) + +#define SE_CRYPTO_KEY_INDEX_SHIFT 24 +#define SE_CRYPTO_KEY_INDEX(x) (x << SE_CRYPTO_KEY_INDEX_SHIFT) + +#define SE_CRYPTO_MEMIF_AHB \ + ((0U) << SE_CRYPTO_MEMIF_SHIFT) +#define SE_CRYPTO_MEMIF_MCCIF \ + ((1U) << SE_CRYPTO_MEMIF_SHIFT) +#define SE_CRYPTO_MEMIF_SHIFT 31 + +/* KEY TABLE */ +#define SE_KEYTABLE_REG_OFFSET 0x31C + +/* KEYIV PKT - key slot */ +#define SE_KEYTABLE_SLOT_SHIFT 4 +#define SE_KEYTABLE_SLOT(x) (x << SE_KEYTABLE_SLOT_SHIFT) + +/* KEYIV PKT - KEYIV select */ +#define SE_KEYIV_PKT_KEYIV_SEL_SHIFT 3 +#define SE_CRYPTO_KEYIV_KEY \ + ((0U) << SE_KEYIV_PKT_KEYIV_SEL_SHIFT) +#define SE_CRYPTO_KEYIV_IVS \ + ((1U) << SE_KEYIV_PKT_KEYIV_SEL_SHIFT) + +/* KEYIV PKT - IV select */ +#define SE_KEYIV_PKT_IV_SEL_SHIFT 2 +#define SE_CRYPTO_KEYIV_IVS_OIV \ + ((0U) << SE_KEYIV_PKT_IV_SEL_SHIFT) +#define SE_CRYPTO_KEYIV_IVS_UIV \ + ((1U) << SE_KEYIV_PKT_IV_SEL_SHIFT) + +/* KEYIV PKT - key word */ +#define SE_KEYIV_PKT_KEY_WORD_SHIFT 0 +#define SE_KEYIV_PKT_KEY_WORD(x) \ + ((x) << SE_KEYIV_PKT_KEY_WORD_SHIFT) + +/* KEYIV PKT - iv word */ +#define SE_KEYIV_PKT_IV_WORD_SHIFT 0 +#define SE_KEYIV_PKT_IV_WORD(x) \ + ((x) << SE_KEYIV_PKT_IV_WORD_SHIFT) + +/* SE OPERATION */ +#define SE_OPERATION_REG_OFFSET 0x8U +#define SE_OPERATION_SHIFT 0 +#define SE_OP_ABORT \ + ((0x0U) << SE_OPERATION_SHIFT) +#define SE_OP_START \ + ((0x1U) << SE_OPERATION_SHIFT) +#define SE_OP_RESTART \ + ((0x2U) << SE_OPERATION_SHIFT) +#define SE_OP_CTX_SAVE \ + ((0x3U) << SE_OPERATION_SHIFT) +#define SE_OP_RESTART_IN \ + ((0x4U) << SE_OPERATION_SHIFT) +#define SE_OPERATION(x) \ + ((x) & ((0x7U) << SE_OPERATION_SHIFT)) + +/* SE CONTEXT */ +#define SE_CTX_SAVE_CONFIG_REG_OFFSET 0x70 +#define SE_CTX_SAVE_WORD_QUAD_SHIFT 0 +#define SE_CTX_SAVE_WORD_QUAD(x) \ + (x << SE_CTX_SAVE_WORD_QUAD_SHIFT) +#define SE_CTX_SAVE_WORD_QUAD_KEYS_0_3 \ + ((0U) << SE_CTX_SAVE_WORD_QUAD_SHIFT) +#define SE_CTX_SAVE_WORD_QUAD_KEYS_4_7 \ + ((1U) << SE_CTX_SAVE_WORD_QUAD_SHIFT) +#define SE_CTX_SAVE_WORD_QUAD_ORIG_IV \ + ((2U) << SE_CTX_SAVE_WORD_QUAD_SHIFT) +#define SE_CTX_SAVE_WORD_QUAD_UPD_IV \ + ((3U) << SE_CTX_SAVE_WORD_QUAD_SHIFT) + +#define SE_CTX_SAVE_KEY_INDEX_SHIFT 8 +#define SE_CTX_SAVE_KEY_INDEX(x) (x << SE_CTX_SAVE_KEY_INDEX_SHIFT) + +#define SE_CTX_SAVE_STICKY_WORD_QUAD_SHIFT 24 +#define SE_CTX_SAVE_STICKY_WORD_QUAD_STICKY_0_3 \ + ((0U) << SE_CTX_SAVE_STICKY_WORD_QUAD_SHIFT) +#define SE_CTX_SAVE_STICKY_WORD_QUAD_STICKY_4_7 \ + ((1U) << SE_CTX_SAVE_STICKY_WORD_QUAD_SHIFT) +#define SE_CTX_SAVE_STICKY_WORD_QUAD(x) \ + (x << SE_CTX_SAVE_STICKY_WORD_QUAD_SHIFT) + +#define SE_CTX_SAVE_SRC_SHIFT 29 +#define SE_CTX_SAVE_SRC_STICKY_BITS \ + ((0U) << SE_CTX_SAVE_SRC_SHIFT) +#define SE_CTX_SAVE_SRC_RSA_KEYTABLE \ + ((1U) << SE_CTX_SAVE_SRC_SHIFT) +#define SE_CTX_SAVE_SRC_AES_KEYTABLE \ + ((2U) << SE_CTX_SAVE_SRC_SHIFT) +#define SE_CTX_SAVE_SRC_PKA1_STICKY_BITS \ + ((3U) << SE_CTX_SAVE_SRC_SHIFT) +#define SE_CTX_SAVE_SRC_MEM \ + ((4U) << SE_CTX_SAVE_SRC_SHIFT) +#define SE_CTX_SAVE_SRC_SRK \ + ((6U) << SE_CTX_SAVE_SRC_SHIFT) +#define SE_CTX_SAVE_SRC_PKA1_KEYTABLE \ + ((7U) << SE_CTX_SAVE_SRC_SHIFT) + +#define SE_CTX_STICKY_WORD_QUAD_SHIFT 24 +#define SE_CTX_STICKY_WORD_QUAD_WORDS_0_3 \ + ((0U) << SE_CTX_STICKY_WORD_QUAD_SHIFT) +#define SE_CTX_STICKY_WORD_QUAD_WORDS_4_7 \ + ((1U) << SE_CTX_STICKY_WORD_QUAD_SHIFT) +#define SE_CTX_STICKY_WORD_QUAD(x) (x << SE_CTX_STICKY_WORD_QUAD_SHIFT) + +#define SE_CTX_SAVE_RSA_KEY_INDEX_SHIFT 16 +#define SE_CTX_SAVE_RSA_KEY_INDEX(x) \ + (x << SE_CTX_SAVE_RSA_KEY_INDEX_SHIFT) + +#define SE_CTX_RSA_WORD_QUAD_SHIFT 12 +#define SE_CTX_RSA_WORD_QUAD(x) \ + (x << SE_CTX_RSA_WORD_QUAD_SHIFT) + +#define SE_CTX_PKA1_WORD_QUAD_L_SHIFT 0 +#define SE_CTX_PKA1_WORD_QUAD_L_SIZE \ + ((true ? 4:0) - \ + (false ? 4:0) + 1) +#define SE_CTX_PKA1_WORD_QUAD_L(x)\ + (((x) << SE_CTX_PKA1_WORD_QUAD_L_SHIFT) & 0x1f) + +#define SE_CTX_PKA1_WORD_QUAD_H_SHIFT 12 +#define SE_CTX_PKA1_WORD_QUAD_H(x)\ + ((((x) >> SE_CTX_PKA1_WORD_QUAD_L_SIZE) & 0xf) \ + << SE_CTX_PKA1_WORD_QUAD_H_SHIFT) + +#define SE_RSA_KEY_INDEX_SLOT0_EXP 0 +#define SE_RSA_KEY_INDEX_SLOT0_MOD 1 +#define SE_RSA_KEY_INDEX_SLOT1_EXP 2 +#define SE_RSA_KEY_INDEX_SLOT1_MOD 3 + + +/* SE_CTX_SAVE_AUTO */ +#define SE_CTX_SAVE_AUTO_REG_OFFSET 0x74U + +/* Enable */ +#define SE_CTX_SAVE_AUTO_ENABLE_SHIFT 0 +#define SE_CTX_SAVE_AUTO_DIS \ + ((0U) << SE_CTX_SAVE_AUTO_ENABLE_SHIFT) +#define SE_CTX_SAVE_AUTO_EN \ + ((1U) << SE_CTX_SAVE_AUTO_ENABLE_SHIFT) +#define SE_CTX_SAVE_AUTO_ENABLE(x) \ + ((x) & ((0x1U) << SE_CTX_SAVE_AUTO_ENABLE_SHIFT)) + +/* Lock */ +#define SE_CTX_SAVE_AUTO_LOCK_SHIFT 8 +#define SE_CTX_SAVE_AUTO_LOCK_EN \ + ((1U) << SE_CTX_SAVE_AUTO_LOCK_SHIFT) +#define SE_CTX_SAVE_AUTO_LOCK_DIS \ + ((0U) << SE_CTX_SAVE_AUTO_LOCK_SHIFT) +#define SE_CTX_SAVE_AUTO_LOCK(x) \ + ((x) & ((0x1U) << SE_CTX_SAVE_AUTO_LOCK_SHIFT)) + +/* Current context save number of blocks*/ +#define SE_CTX_SAVE_AUTO_CURR_CNT_SHIFT 16 +#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK 0x3FFU +#define SE_CTX_SAVE_GET_BLK_COUNT(x) \ + (((x) >> SE_CTX_SAVE_AUTO_CURR_CNT_SHIFT) & \ + SE_CTX_SAVE_AUTO_CURR_CNT_MASK) + +#define SE_CTX_SAVE_SIZE_BLOCKS_SE1 133 +#define SE_CTX_SAVE_SIZE_BLOCKS_SE2 646 + +/* SE TZRAM OPERATION - only for SE1 */ +#define SE_TZRAM_OPERATION 0x540U + +#define SE_TZRAM_OP_MODE_SHIFT 1 +#define SE_TZRAM_OP_COMMAND_INIT 1 +#define SE_TZRAM_OP_COMMAND_SHIFT 0 +#define SE_TZRAM_OP_MODE_SAVE \ + ((0U) << SE_TZRAM_OP_MODE_SHIFT) +#define SE_TZRAM_OP_MODE_RESTORE \ + ((1U) << SE_TZRAM_OP_MODE_SHIFT) +#define SE_TZRAM_OP_MODE(x) \ + ((x) & ((0x1U) << SE_TZRAM_OP_MODE_SHIFT)) + +#define SE_TZRAM_OP_BUSY_SHIFT 2 +#define SE_TZRAM_OP_BUSY_OFF \ + ((0U) << SE_TZRAM_OP_BUSY_SHIFT) +#define SE_TZRAM_OP_BUSY_ON \ + ((1U) << SE_TZRAM_OP_BUSY_SHIFT) +#define SE_TZRAM_OP_BUSY(x) \ + ((x) & ((0x1U) << SE_TZRAM_OP_BUSY_SHIFT)) + +#define SE_TZRAM_OP_REQ_SHIFT 0 +#define SE_TZRAM_OP_REQ_IDLE \ + ((0U) << SE_TZRAM_OP_REQ_SHIFT) +#define SE_TZRAM_OP_REQ_INIT \ + ((1U) << SE_TZRAM_OP_REQ_SHIFT) +#define SE_TZRAM_OP_REQ(x) \ + ((x) & ((0x1U) << SE_TZRAM_OP_REQ_SHIFT)) + +/* SE Interrupt */ +#define SE_INT_ENABLE_REG_OFFSET U(0xC) +#define SE_INT_STATUS_REG_OFFSET 0x10U +#define SE_INT_OP_DONE_SHIFT 4 +#define SE_INT_OP_DONE_CLEAR \ + ((0U) << SE_INT_OP_DONE_SHIFT) +#define SE_INT_OP_DONE_ACTIVE \ + ((1U) << SE_INT_OP_DONE_SHIFT) +#define SE_INT_OP_DONE(x) \ + ((x) & ((0x1U) << SE_INT_OP_DONE_SHIFT)) + +/* SE TZRAM SECURITY */ +#define SE_TZRAM_SEC_REG_OFFSET 0x4 + +#define SE_TZRAM_SEC_SETTING_SHIFT 0 +#define SE_TZRAM_SECURE \ + ((0UL) << SE_TZRAM_SEC_SETTING_SHIFT) +#define SE_TZRAM_NONSECURE \ + ((1UL) << SE_TZRAM_SEC_SETTING_SHIFT) +#define SE_TZRAM_SEC_SETTING(x) \ + ((x) & ((0x1UL) << SE_TZRAM_SEC_SETTING_SHIFT)) + +/* PKA1 KEY SLOTS */ +#define TEGRA_SE_PKA1_KEYSLOT_COUNT 4 + + +/* SE error status */ +#define SE_ERR_STATUS_REG_OFFSET 0x804U +#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0x330 +#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0 +#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \ + (x << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT) + +#define SE_KEY_INDEX_SHIFT 8 +#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) (x << SE_KEY_INDEX_SHIFT) + + +/* SE linked list (LL) register */ +#define SE_IN_LL_ADDR_REG_OFFSET 0x18U +#define SE_OUT_LL_ADDR_REG_OFFSET 0x24U +#define SE_BLOCK_COUNT_REG_OFFSET 0x318U + +/* AES data sizes */ +#define TEGRA_SE_KEY_256_SIZE 32 +#define TEGRA_SE_KEY_192_SIZE 24 +#define TEGRA_SE_KEY_128_SIZE 16 +#define TEGRA_SE_AES_BLOCK_SIZE 16 +#define TEGRA_SE_AES_MIN_KEY_SIZE 16 +#define TEGRA_SE_AES_MAX_KEY_SIZE 32 +#define TEGRA_SE_AES_IV_SIZE 16 + +#define TEGRA_SE_RNG_IV_SIZE 16 +#define TEGRA_SE_RNG_DT_SIZE 16 +#define TEGRA_SE_RNG_KEY_SIZE 16 +#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \ + TEGRA_SE_RNG_KEY_SIZE + \ + TEGRA_SE_RNG_DT_SIZE) +#define TEGRA_SE_RSA512_DIGEST_SIZE 64 +#define TEGRA_SE_RSA1024_DIGEST_SIZE 128 +#define TEGRA_SE_RSA1536_DIGEST_SIZE 192 +#define TEGRA_SE_RSA2048_DIGEST_SIZE 256 + +#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 +#define SE_KEY_READ_DISABLE_SHIFT 0 + +#define SE_CTX_BUFER_SIZE 1072 +#define SE_CTX_DRBG_BUFER_SIZE 2112 + +/* SE blobs size in bytes */ +#define SE_CTX_SAVE_RSA_KEY_LENGTH 1024 +#define SE_CTX_SAVE_RANDOM_DATA_SIZE 16 +#define SE_CTX_SAVE_STICKY_BITS_SIZE 16 +#define SE2_CONTEXT_SAVE_PKA1_STICKY_BITS_LENGTH 16 +#define SE2_CONTEXT_SAVE_PKA1_KEYS_LENGTH 8192 +#define SE_CTX_KNOWN_PATTERN_SIZE 16 +#define SE_CTX_KNOWN_PATTERN_SIZE_WORDS (SE_CTX_KNOWN_PATTERN_SIZE/4) + +/* SE RSA */ +#define TEGRA_SE_RSA_KEYSLOT_COUNT 2 +#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404 +#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408 +#define SE_RSA_MAX_EXP_BIT_SIZE 2048 +#define SE_RSA_MAX_EXP_SIZE32 \ + (SE_RSA_MAX_EXP_BIT_SIZE >> 5) +#define SE_RSA_MAX_MOD_BIT_SIZE 2048 +#define SE_RSA_MAX_MOD_SIZE32 \ + (SE_RSA_MAX_MOD_BIT_SIZE >> 5) + +/* SE_RSA_KEYTABLE_ADDR */ +#define SE_RSA_KEYTABLE_ADDR 0x420 +#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0 +#define RSA_KEY_PKT_EXPMOD_SEL_SHIFT \ + ((6U) << RSA_KEY_PKT_WORD_ADDR_SHIFT) +#define RSA_KEY_MOD \ + ((1U) << RSA_KEY_PKT_EXPMOD_SEL_SHIFT) +#define RSA_KEY_EXP \ + ((0U) << RSA_KEY_PKT_EXPMOD_SEL_SHIFT) +#define RSA_KEY_PKT_SLOT_SHIFT 7 +#define RSA_KEY_SLOT_1 \ + ((0U) << RSA_KEY_PKT_SLOT_SHIFT) +#define RSA_KEY_SLOT_2 \ + ((1U) << RSA_KEY_PKT_SLOT_SHIFT) +#define RSA_KEY_PKT_INPUT_MODE_SHIFT 8 +#define RSA_KEY_REG_INPUT \ + ((0U) << RSA_KEY_PKT_INPUT_MODE_SHIFT) +#define RSA_KEY_DMA_INPUT \ + ((1U) << RSA_KEY_PKT_INPUT_MODE_SHIFT) + +/* SE_RSA_KEYTABLE_DATA */ +#define SE_RSA_KEYTABLE_DATA 0x424 + +/* SE_RSA_CONFIG register */ +#define SE_RSA_CONFIG 0x400 +#define RSA_KEY_SLOT_SHIFT 24 +#define RSA_KEY_SLOT(x) \ + ((x) << RSA_KEY_SLOT_SHIFT) + +/******************************************************************************* + * Structure definition + ******************************************************************************/ + +/* SE context blob */ +#pragma pack(push, 1) +typedef struct tegra_aes_key_slot { + /* 0 - 7 AES key */ + uint32_t key[8]; + /* 8 - 11 Original IV */ + uint32_t oiv[4]; + /* 12 - 15 Updated IV */ + uint32_t uiv[4]; +} tegra_se_aes_key_slot_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct tegra_se_context { + /* random number */ + unsigned char rand_data[SE_CTX_SAVE_RANDOM_DATA_SIZE]; + /* Sticky bits */ + unsigned char sticky_bits[SE_CTX_SAVE_STICKY_BITS_SIZE * 2]; + /* AES key slots */ + tegra_se_aes_key_slot_t key_slots[TEGRA_SE_AES_KEYSLOT_COUNT]; + /* RSA key slots */ + unsigned char rsa_keys[SE_CTX_SAVE_RSA_KEY_LENGTH]; +} tegra_se_context_t; +#pragma pack(pop) + +/* PKA context blob */ +#pragma pack(push, 1) +typedef struct tegra_pka_context { + unsigned char sticky_bits[SE2_CONTEXT_SAVE_PKA1_STICKY_BITS_LENGTH]; + unsigned char pka_keys[SE2_CONTEXT_SAVE_PKA1_KEYS_LENGTH]; +} tegra_pka_context_t; +#pragma pack(pop) + +/* SE context blob */ +#pragma pack(push, 1) +typedef struct tegra_se_context_blob { + /* SE context */ + tegra_se_context_t se_ctx; + /* Known Pattern */ + unsigned char known_pattern[SE_CTX_KNOWN_PATTERN_SIZE]; +} tegra_se_context_blob_t; +#pragma pack(pop) + +/* SE2 and PKA1 context blob */ +#pragma pack(push, 1) +typedef struct tegra_se2_context_blob { + /* SE2 context */ + tegra_se_context_t se_ctx; + /* PKA1 context */ + tegra_pka_context_t pka_ctx; + /* Known Pattern */ + unsigned char known_pattern[SE_CTX_KNOWN_PATTERN_SIZE]; +} tegra_se2_context_blob_t; +#pragma pack(pop) + +/* SE AES key type 128bit, 192bit, 256bit */ +typedef enum { + SE_AES_KEY128, + SE_AES_KEY192, + SE_AES_KEY256, +} tegra_se_aes_key_type_t; + +/* SE RSA key slot */ +typedef struct tegra_se_rsa_key_slot { + /* 0 - 63 exponent key */ + uint32_t exponent[SE_RSA_MAX_EXP_SIZE32]; + /* 64 - 127 modulus key */ + uint32_t modulus[SE_RSA_MAX_MOD_SIZE32]; +} tegra_se_rsa_key_slot_t; + + +/******************************************************************************* + * Inline functions definition + ******************************************************************************/ + +static inline uint32_t tegra_se_read_32(const tegra_se_dev_t *dev, uint32_t offset) +{ + return mmio_read_32(dev->se_base + offset); +} + +static inline void tegra_se_write_32(const tegra_se_dev_t *dev, uint32_t offset, uint32_t val) +{ + mmio_write_32(dev->se_base + offset, val); +} + +static inline uint32_t tegra_pka_read_32(tegra_pka_dev_t *dev, uint32_t offset) +{ + return mmio_read_32(dev->pka_base + offset); +} + +static inline void tegra_pka_write_32(tegra_pka_dev_t *dev, uint32_t offset, +uint32_t val) +{ + mmio_write_32(dev->pka_base + offset, val); +} + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +int tegra_se_start_normal_operation(const tegra_se_dev_t *, uint32_t); +int tegra_se_start_ctx_save_operation(const tegra_se_dev_t *, uint32_t); + +#endif /* SE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c new file mode 100644 index 0000000..4860858 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c @@ -0,0 +1,1071 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Constants and Macros + ******************************************************************************/ + +#define TIMEOUT_100MS 100U /* Timeout in 100ms */ +#define RNG_AES_KEY_INDEX 1 + +/******************************************************************************* + * Data structure and global variables + ******************************************************************************/ + +/* The security engine contexts are formatted as follows: + * + * SE1 CONTEXT: + * #--------------------------------# + * | Random Data 1 Block | + * #--------------------------------# + * | Sticky Bits 2 Blocks | + * #--------------------------------# + * | Key Table 64 Blocks | + * | For each Key (x16): | + * | Key: 2 Blocks | + * | Original-IV: 1 Block | + * | Updated-IV: 1 Block | + * #--------------------------------# + * | RSA Keys 64 Blocks | + * #--------------------------------# + * | Known Pattern 1 Block | + * #--------------------------------# + * + * SE2/PKA1 CONTEXT: + * #--------------------------------# + * | Random Data 1 Block | + * #--------------------------------# + * | Sticky Bits 2 Blocks | + * #--------------------------------# + * | Key Table 64 Blocks | + * | For each Key (x16): | + * | Key: 2 Blocks | + * | Original-IV: 1 Block | + * | Updated-IV: 1 Block | + * #--------------------------------# + * | RSA Keys 64 Blocks | + * #--------------------------------# + * | PKA sticky bits 1 Block | + * #--------------------------------# + * | PKA keys 512 Blocks | + * #--------------------------------# + * | Known Pattern 1 Block | + * #--------------------------------# + */ + +/* Known pattern data for T210 */ +static const uint8_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE] = { + /* 128 bit AES block */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + +/* SE input and output linked list buffers */ +static tegra_se_io_lst_t se1_src_ll_buf; +static tegra_se_io_lst_t se1_dst_ll_buf; + +/* SE2 input and output linked list buffers */ +static tegra_se_io_lst_t se2_src_ll_buf; +static tegra_se_io_lst_t se2_dst_ll_buf; + +/* SE1 context buffer, 132 blocks */ +static __aligned(64) uint8_t se1_ctx_buf[SE_CTX_DRBG_BUFER_SIZE]; + +/* SE1 security engine device handle */ +static tegra_se_dev_t se_dev_1 = { + .se_num = 1, + /* Setup base address for se */ + .se_base = TEGRA_SE1_BASE, + /* Setup context size in AES blocks */ + .ctx_size_blks = SE_CTX_SAVE_SIZE_BLOCKS_SE1, + /* Setup SRC buffers for SE operations */ + .src_ll_buf = &se1_src_ll_buf, + /* Setup DST buffers for SE operations */ + .dst_ll_buf = &se1_dst_ll_buf, + /* Setup context save destination */ + .ctx_save_buf = (uint32_t *)&se1_ctx_buf +}; + +/* SE2 security engine device handle (T210B01 only) */ +static tegra_se_dev_t se_dev_2 = { + .se_num = 2, + /* Setup base address for se */ + .se_base = TEGRA_SE2_BASE, + /* Setup context size in AES blocks */ + .ctx_size_blks = SE_CTX_SAVE_SIZE_BLOCKS_SE2, + /* Setup SRC buffers for SE operations */ + .src_ll_buf = &se2_src_ll_buf, + /* Setup DST buffers for SE operations */ + .dst_ll_buf = &se2_dst_ll_buf, + /* Setup context save destination */ + .ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE + 0x1000) +}; + +static bool ecid_valid; + +/******************************************************************************* + * Functions Definition + ******************************************************************************/ + +static void tegra_se_make_data_coherent(const tegra_se_dev_t *se_dev) +{ + flush_dcache_range(((uint64_t)(se_dev->src_ll_buf)), + sizeof(tegra_se_io_lst_t)); + flush_dcache_range(((uint64_t)(se_dev->dst_ll_buf)), + sizeof(tegra_se_io_lst_t)); +} + +/* + * Check that SE operation has completed after kickoff + * This function is invoked after an SE operation has been started, + * and it checks the following conditions: + * 1. SE_INT_STATUS = SE_OP_DONE + * 2. SE_STATUS = IDLE + * 3. AHB bus data transfer complete. + * 4. SE_ERR_STATUS is clean. + */ +static int32_t tegra_se_operation_complete(const tegra_se_dev_t *se_dev) +{ + uint32_t val = 0; + int32_t ret = 0; + uint32_t timeout; + + /* Poll the SE interrupt register to ensure H/W operation complete */ + val = tegra_se_read_32(se_dev, SE_INT_STATUS_REG_OFFSET); + for (timeout = 0; (SE_INT_OP_DONE(val) == SE_INT_OP_DONE_CLEAR) && + (timeout < TIMEOUT_100MS); timeout++) { + mdelay(1); + val = tegra_se_read_32(se_dev, SE_INT_STATUS_REG_OFFSET); + } + + if (timeout == TIMEOUT_100MS) { + ERROR("%s: ERR: Atomic context save operation timeout!\n", + __func__); + ret = -ETIMEDOUT; + } + + /* Poll the SE status idle to ensure H/W operation complete */ + if (ret == 0) { + val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET); + for (timeout = 0; (val != 0U) && (timeout < TIMEOUT_100MS); + timeout++) { + mdelay(1); + val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET); + } + + if (timeout == TIMEOUT_100MS) { + ERROR("%s: ERR: MEM_INTERFACE and SE state " + "idle state timeout.\n", __func__); + ret = -ETIMEDOUT; + } + } + + /* Check AHB bus transfer complete */ + if (ret == 0) { + val = mmio_read_32(TEGRA_AHB_ARB_BASE + ARAHB_MEM_WRQUE_MST_ID_OFFSET); + for (timeout = 0; ((val & (ARAHB_MST_ID_SE_MASK | ARAHB_MST_ID_SE2_MASK)) != 0U) && + (timeout < TIMEOUT_100MS); timeout++) { + mdelay(1); + val = mmio_read_32(TEGRA_AHB_ARB_BASE + ARAHB_MEM_WRQUE_MST_ID_OFFSET); + } + + if (timeout == TIMEOUT_100MS) { + ERROR("%s: SE write over AHB timeout.\n", __func__); + ret = -ETIMEDOUT; + } + } + + /* Ensure that no errors are thrown during operation */ + if (ret == 0) { + val = tegra_se_read_32(se_dev, SE_ERR_STATUS_REG_OFFSET); + if (val != 0U) { + ERROR("%s: error during SE operation! 0x%x", __func__, val); + ret = -ENOTSUP; + } + } + + return ret; +} + +/* + * Wait for SE engine to be idle and clear pending interrupts before + * starting the next SE operation. + */ +static int32_t tegra_se_operation_prepare(const tegra_se_dev_t *se_dev) +{ + int32_t ret = 0; + uint32_t val = 0; + uint32_t timeout; + + /* disable SE interrupt to prevent interrupt issued by SE operation */ + tegra_se_write_32(se_dev, SE_INT_ENABLE_REG_OFFSET, 0U); + + /* Wait for previous operation to finish */ + val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET); + for (timeout = 0; (val != 0U) && (timeout < TIMEOUT_100MS); timeout++) { + mdelay(1); + val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET); + } + + if (timeout == TIMEOUT_100MS) { + ERROR("%s: ERR: SE status is not idle!\n", __func__); + ret = -ETIMEDOUT; + } + + /* Clear any pending interrupts from previous operation */ + val = tegra_se_read_32(se_dev, SE_INT_STATUS_REG_OFFSET); + tegra_se_write_32(se_dev, SE_INT_STATUS_REG_OFFSET, val); + return ret; +} + +/* + * SE atomic context save. At SC7 entry, SE driver triggers the + * hardware automatically performs the context save operation. + */ +static int32_t tegra_se_context_save_atomic(const tegra_se_dev_t *se_dev) +{ + int32_t ret = 0; + uint32_t val = 0; + uint32_t blk_count_limit = 0; + uint32_t block_count; + + /* Check that previous operation is finalized */ + ret = tegra_se_operation_prepare(se_dev); + + /* Read the context save progress counter: block_count + * Ensure no previous context save has been triggered + * SE_CTX_SAVE_AUTO.CURR_CNT == 0 + */ + if (ret == 0) { + val = tegra_se_read_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET); + block_count = SE_CTX_SAVE_GET_BLK_COUNT(val); + if (block_count != 0U) { + ERROR("%s: ctx_save triggered multiple times\n", + __func__); + ret = -EALREADY; + } + } + + /* Set the destination block count when the context save complete */ + if (ret == 0) { + blk_count_limit = block_count + se_dev->ctx_size_blks; + } + + /* Program SE_CONFIG register as for RNG operation + * SE_CONFIG.ENC_ALG = RNG + * SE_CONFIG.DEC_ALG = NOP + * SE_CONFIG.ENC_MODE is ignored + * SE_CONFIG.DEC_MODE is ignored + * SE_CONFIG.DST = MEMORY + */ + if (ret == 0) { + val = (SE_CONFIG_ENC_ALG_RNG | + SE_CONFIG_DEC_ALG_NOP | + SE_CONFIG_DST_MEMORY); + tegra_se_write_32(se_dev, SE_CONFIG_REG_OFFSET, val); + + tegra_se_make_data_coherent(se_dev); + + /* SE_CTX_SAVE operation */ + tegra_se_write_32(se_dev, SE_OPERATION_REG_OFFSET, + SE_OP_CTX_SAVE); + + ret = tegra_se_operation_complete(se_dev); + } + + /* Check that context has written the correct number of blocks */ + if (ret == 0) { + val = tegra_se_read_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET); + if (SE_CTX_SAVE_GET_BLK_COUNT(val) != blk_count_limit) { + ERROR("%s: expected %d blocks but %d were written\n", + __func__, blk_count_limit, val); + ret = -ECANCELED; + } + } + + return ret; +} + +/* + * Security engine primitive operations, including normal operation + * and the context save operation. + */ +static int tegra_se_perform_operation(const tegra_se_dev_t *se_dev, uint32_t nbytes, + bool context_save) +{ + uint32_t nblocks = nbytes / TEGRA_SE_AES_BLOCK_SIZE; + int ret = 0; + + assert(se_dev); + + /* Use device buffers for in and out */ + tegra_se_write_32(se_dev, SE_OUT_LL_ADDR_REG_OFFSET, ((uint64_t)(se_dev->dst_ll_buf))); + tegra_se_write_32(se_dev, SE_IN_LL_ADDR_REG_OFFSET, ((uint64_t)(se_dev->src_ll_buf))); + + /* Check that previous operation is finalized */ + ret = tegra_se_operation_prepare(se_dev); + if (ret != 0) { + goto op_error; + } + + /* Program SE operation size */ + if (nblocks) { + tegra_se_write_32(se_dev, SE_BLOCK_COUNT_REG_OFFSET, nblocks - 1); + } + + /* Make SE LL data coherent before the SE operation */ + tegra_se_make_data_coherent(se_dev); + + /* Start hardware operation */ + if (context_save) + tegra_se_write_32(se_dev, SE_OPERATION_REG_OFFSET, SE_OP_CTX_SAVE); + else + tegra_se_write_32(se_dev, SE_OPERATION_REG_OFFSET, SE_OP_START); + + /* Wait for operation to finish */ + ret = tegra_se_operation_complete(se_dev); + +op_error: + return ret; +} + +/* + * Normal security engine operations other than the context save + */ +int tegra_se_start_normal_operation(const tegra_se_dev_t *se_dev, uint32_t nbytes) +{ + return tegra_se_perform_operation(se_dev, nbytes, false); +} + +/* + * Security engine context save operation + */ +int tegra_se_start_ctx_save_operation(const tegra_se_dev_t *se_dev, uint32_t nbytes) +{ + return tegra_se_perform_operation(se_dev, nbytes, true); +} + +/* + * Security Engine sequence to generat SRK + * SE and SE2 will generate different SRK by different + * entropy seeds. + */ +static int tegra_se_generate_srk(const tegra_se_dev_t *se_dev) +{ + int ret = PSCI_E_INTERN_FAIL; + uint32_t val; + + /* Confgure the following hardware register settings: + * SE_CONFIG.DEC_ALG = NOP + * SE_CONFIG.ENC_ALG = RNG + * SE_CONFIG.DST = SRK + * SE_OPERATION.OP = START + * SE_CRYPTO_LAST_BLOCK = 0 + */ + se_dev->src_ll_buf->last_buff_num = 0; + se_dev->dst_ll_buf->last_buff_num = 0; + + /* Configure random number generator */ + if (ecid_valid) + val = (DRBG_MODE_FORCE_INSTANTION | DRBG_SRC_ENTROPY); + else + val = (DRBG_MODE_FORCE_RESEED | DRBG_SRC_ENTROPY); + tegra_se_write_32(se_dev, SE_RNG_CONFIG_REG_OFFSET, val); + + /* Configure output destination = SRK */ + val = (SE_CONFIG_ENC_ALG_RNG | + SE_CONFIG_DEC_ALG_NOP | + SE_CONFIG_DST_SRK); + tegra_se_write_32(se_dev, SE_CONFIG_REG_OFFSET, val); + + /* Perform hardware operation */ + ret = tegra_se_start_normal_operation(se_dev, 0); + + return ret; +} + +/* + * Generate plain text random data to some memory location using + * SE/SE2's SP800-90 random number generator. The random data size + * must be some multiple of the AES block size (16 bytes). + */ +static int tegra_se_lp_generate_random_data(tegra_se_dev_t *se_dev) +{ + int ret = 0; + uint32_t val; + + /* Set some arbitrary memory location to store the random data */ + se_dev->dst_ll_buf->last_buff_num = 0; + if (!se_dev->ctx_save_buf) { + ERROR("%s: ERR: context save buffer NULL pointer!\n", __func__); + return PSCI_E_NOT_PRESENT; + } + se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(((tegra_se_context_t *) + se_dev->ctx_save_buf)->rand_data))); + se_dev->dst_ll_buf->buffer[0].data_len = SE_CTX_SAVE_RANDOM_DATA_SIZE; + + + /* Confgure the following hardware register settings: + * SE_CONFIG.DEC_ALG = NOP + * SE_CONFIG.ENC_ALG = RNG + * SE_CONFIG.ENC_MODE = KEY192 + * SE_CONFIG.DST = MEMORY + */ + val = (SE_CONFIG_ENC_ALG_RNG | + SE_CONFIG_DEC_ALG_NOP | + SE_CONFIG_ENC_MODE_KEY192 | + SE_CONFIG_DST_MEMORY); + tegra_se_write_32(se_dev, SE_CONFIG_REG_OFFSET, val); + + /* Program the RNG options in SE_CRYPTO_CONFIG as follows: + * XOR_POS = BYPASS + * INPUT_SEL = RANDOM (Entropy or LFSR) + * HASH_ENB = DISABLE + */ + val = (SE_CRYPTO_INPUT_RANDOM | + SE_CRYPTO_XOR_BYPASS | + SE_CRYPTO_CORE_ENCRYPT | + SE_CRYPTO_HASH_DISABLE | + SE_CRYPTO_KEY_INDEX(RNG_AES_KEY_INDEX) | + SE_CRYPTO_IV_ORIGINAL); + tegra_se_write_32(se_dev, SE_CRYPTO_REG_OFFSET, val); + + /* Configure RNG */ + if (ecid_valid) + val = (DRBG_MODE_FORCE_INSTANTION | DRBG_SRC_LFSR); + else + val = (DRBG_MODE_FORCE_RESEED | DRBG_SRC_LFSR); + tegra_se_write_32(se_dev, SE_RNG_CONFIG_REG_OFFSET, val); + + /* SE normal operation */ + ret = tegra_se_start_normal_operation(se_dev, SE_CTX_SAVE_RANDOM_DATA_SIZE); + + return ret; +} + +/* + * Encrypt memory blocks with SRK as part of the security engine context. + * The data blocks include: random data and the known pattern data, where + * the random data is the first block and known pattern is the last block. + */ +static int tegra_se_lp_data_context_save(tegra_se_dev_t *se_dev, + uint64_t src_addr, uint64_t dst_addr, uint32_t data_size) +{ + int ret = 0; + + se_dev->src_ll_buf->last_buff_num = 0; + se_dev->dst_ll_buf->last_buff_num = 0; + se_dev->src_ll_buf->buffer[0].addr = src_addr; + se_dev->src_ll_buf->buffer[0].data_len = data_size; + se_dev->dst_ll_buf->buffer[0].addr = dst_addr; + se_dev->dst_ll_buf->buffer[0].data_len = data_size; + + /* By setting the context source from memory and calling the context save + * operation, the SE encrypts the memory data with SRK. + */ + tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, SE_CTX_SAVE_SRC_MEM); + + ret = tegra_se_start_ctx_save_operation(se_dev, data_size); + + return ret; +} + +/* + * Context save the key table access control sticky bits and + * security status of each key-slot. The encrypted sticky-bits are + * 32 bytes (2 AES blocks) and formatted as the following structure: + * { bit in registers bit in context save + * SECURITY_0[4] 158 + * SE_RSA_KEYTABLE_ACCE4SS_1[2:0] 157:155 + * SE_RSA_KEYTABLE_ACCE4SS_0[2:0] 154:152 + * SE_RSA_SECURITY_PERKEY_0[1:0] 151:150 + * SE_CRYPTO_KEYTABLE_ACCESS_15[7:0] 149:142 + * ..., + * SE_CRYPTO_KEYTABLE_ACCESS_0[7:0] 29:22 + * SE_CRYPTO_SECURITY_PERKEY_0[15:0] 21:6 + * SE_TZRAM_SECURITY_0[1:0] 5:4 + * SE_SECURITY_0[16] 3:3 + * SE_SECURITY_0[2:0] } 2:0 + */ +static int tegra_se_lp_sticky_bits_context_save(tegra_se_dev_t *se_dev) +{ + int ret = PSCI_E_INTERN_FAIL; + uint32_t val = 0; + + se_dev->dst_ll_buf->last_buff_num = 0; + if (!se_dev->ctx_save_buf) { + ERROR("%s: ERR: context save buffer NULL pointer!\n", __func__); + return PSCI_E_NOT_PRESENT; + } + se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(((tegra_se_context_t *) + se_dev->ctx_save_buf)->sticky_bits))); + se_dev->dst_ll_buf->buffer[0].data_len = SE_CTX_SAVE_STICKY_BITS_SIZE; + + /* + * The 1st AES block save the sticky-bits context 1 - 16 bytes (0 - 3 words). + * The 2nd AES block save the sticky-bits context 17 - 32 bytes (4 - 7 words). + */ + for (int i = 0; i < 2; i++) { + val = SE_CTX_SAVE_SRC_STICKY_BITS | + SE_CTX_SAVE_STICKY_WORD_QUAD(i); + tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, val); + + /* SE context save operation */ + ret = tegra_se_start_ctx_save_operation(se_dev, + SE_CTX_SAVE_STICKY_BITS_SIZE); + if (ret) + break; + se_dev->dst_ll_buf->buffer[0].addr += SE_CTX_SAVE_STICKY_BITS_SIZE; + } + + return ret; +} + +static int tegra_se_aeskeytable_context_save(tegra_se_dev_t *se_dev) +{ + uint32_t val = 0; + int ret = 0; + + se_dev->dst_ll_buf->last_buff_num = 0; + if (!se_dev->ctx_save_buf) { + ERROR("%s: ERR: context save buffer NULL pointer!\n", __func__); + ret = -EINVAL; + goto aes_keytable_save_err; + } + + /* AES key context save */ + for (int slot = 0; slot < TEGRA_SE_AES_KEYSLOT_COUNT; slot++) { + se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&( + ((tegra_se_context_t *)se_dev-> + ctx_save_buf)->key_slots[slot].key))); + se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_KEY_128_SIZE; + for (int i = 0; i < 2; i++) { + val = SE_CTX_SAVE_SRC_AES_KEYTABLE | + SE_CTX_SAVE_KEY_INDEX(slot) | + SE_CTX_SAVE_WORD_QUAD(i); + tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, val); + + /* SE context save operation */ + ret = tegra_se_start_ctx_save_operation(se_dev, + TEGRA_SE_KEY_128_SIZE); + if (ret) { + ERROR("%s: ERR: AES key CTX_SAVE OP failed, " + "slot=%d, word_quad=%d.\n", + __func__, slot, i); + goto aes_keytable_save_err; + } + se_dev->dst_ll_buf->buffer[0].addr += TEGRA_SE_KEY_128_SIZE; + } + + /* OIV context save */ + se_dev->dst_ll_buf->last_buff_num = 0; + se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&( + ((tegra_se_context_t *)se_dev-> + ctx_save_buf)->key_slots[slot].oiv))); + se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_AES_IV_SIZE; + + val = SE_CTX_SAVE_SRC_AES_KEYTABLE | + SE_CTX_SAVE_KEY_INDEX(slot) | + SE_CTX_SAVE_WORD_QUAD_ORIG_IV; + tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, val); + + /* SE context save operation */ + ret = tegra_se_start_ctx_save_operation(se_dev, TEGRA_SE_AES_IV_SIZE); + if (ret) { + ERROR("%s: ERR: OIV CTX_SAVE OP failed, slot=%d.\n", + __func__, slot); + goto aes_keytable_save_err; + } + + /* UIV context save */ + se_dev->dst_ll_buf->last_buff_num = 0; + se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&( + ((tegra_se_context_t *)se_dev-> + ctx_save_buf)->key_slots[slot].uiv))); + se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_AES_IV_SIZE; + + val = SE_CTX_SAVE_SRC_AES_KEYTABLE | + SE_CTX_SAVE_KEY_INDEX(slot) | + SE_CTX_SAVE_WORD_QUAD_UPD_IV; + tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, val); + + /* SE context save operation */ + ret = tegra_se_start_ctx_save_operation(se_dev, TEGRA_SE_AES_IV_SIZE); + if (ret) { + ERROR("%s: ERR: UIV CTX_SAVE OP failed, slot=%d\n", + __func__, slot); + goto aes_keytable_save_err; + } + } + +aes_keytable_save_err: + return ret; +} + +static int tegra_se_lp_rsakeytable_context_save(tegra_se_dev_t *se_dev) +{ + uint32_t val = 0; + int ret = 0; + /* For T210, First the modulus and then exponent must be + * encrypted and saved. This is repeated for SLOT 0 + * and SLOT 1. Hence the order: + * SLOT 0 modulus : RSA_KEY_INDEX : 1 + * SLOT 0 exponent : RSA_KEY_INDEX : 0 + * SLOT 1 modulus : RSA_KEY_INDEX : 3 + * SLOT 1 exponent : RSA_KEY_INDEX : 2 + */ + const unsigned int key_index_mod[TEGRA_SE_RSA_KEYSLOT_COUNT][2] = { + /* RSA key slot 0 */ + {SE_RSA_KEY_INDEX_SLOT0_MOD, SE_RSA_KEY_INDEX_SLOT0_EXP}, + /* RSA key slot 1 */ + {SE_RSA_KEY_INDEX_SLOT1_MOD, SE_RSA_KEY_INDEX_SLOT1_EXP}, + }; + + se_dev->dst_ll_buf->last_buff_num = 0; + se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&( + ((tegra_se_context_t *)se_dev-> + ctx_save_buf)->rsa_keys))); + se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_KEY_128_SIZE; + + for (int slot = 0; slot < TEGRA_SE_RSA_KEYSLOT_COUNT; slot++) { + /* loop for modulus and exponent */ + for (int index = 0; index < 2; index++) { + for (int word_quad = 0; word_quad < 16; word_quad++) { + val = SE_CTX_SAVE_SRC_RSA_KEYTABLE | + SE_CTX_SAVE_RSA_KEY_INDEX( + key_index_mod[slot][index]) | + SE_CTX_RSA_WORD_QUAD(word_quad); + tegra_se_write_32(se_dev, + SE_CTX_SAVE_CONFIG_REG_OFFSET, val); + + /* SE context save operation */ + ret = tegra_se_start_ctx_save_operation(se_dev, + TEGRA_SE_KEY_128_SIZE); + if (ret) { + ERROR("%s: ERR: slot=%d.\n", + __func__, slot); + goto rsa_keytable_save_err; + } + + /* Update the pointer to the next word quad */ + se_dev->dst_ll_buf->buffer[0].addr += + TEGRA_SE_KEY_128_SIZE; + } + } + } + +rsa_keytable_save_err: + return ret; +} + +static int tegra_se_pkakeytable_sticky_bits_save(tegra_se_dev_t *se_dev) +{ + int ret = 0; + + se_dev->dst_ll_buf->last_buff_num = 0; + se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&( + ((tegra_se2_context_blob_t *)se_dev-> + ctx_save_buf)->pka_ctx.sticky_bits))); + se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_AES_BLOCK_SIZE; + + /* PKA1 sticky bits are 1 AES block (16 bytes) */ + tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, + SE_CTX_SAVE_SRC_PKA1_STICKY_BITS | + SE_CTX_STICKY_WORD_QUAD_WORDS_0_3); + + /* SE context save operation */ + ret = tegra_se_start_ctx_save_operation(se_dev, 0); + if (ret) { + ERROR("%s: ERR: PKA1 sticky bits CTX_SAVE OP failed\n", + __func__); + goto pka_sticky_bits_save_err; + } + +pka_sticky_bits_save_err: + return ret; +} + +static int tegra_se_pkakeytable_context_save(tegra_se_dev_t *se_dev) +{ + uint32_t val = 0; + int ret = 0; + + se_dev->dst_ll_buf->last_buff_num = 0; + se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&( + ((tegra_se2_context_blob_t *)se_dev-> + ctx_save_buf)->pka_ctx.pka_keys))); + se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_KEY_128_SIZE; + + /* for each slot, save word quad 0-127 */ + for (int slot = 0; slot < TEGRA_SE_PKA1_KEYSLOT_COUNT; slot++) { + for (int word_quad = 0; word_quad < 512/4; word_quad++) { + val = SE_CTX_SAVE_SRC_PKA1_KEYTABLE | + SE_CTX_PKA1_WORD_QUAD_L((slot * 128) + + word_quad) | + SE_CTX_PKA1_WORD_QUAD_H((slot * 128) + + word_quad); + tegra_se_write_32(se_dev, + SE_CTX_SAVE_CONFIG_REG_OFFSET, val); + + /* SE context save operation */ + ret = tegra_se_start_ctx_save_operation(se_dev, + TEGRA_SE_KEY_128_SIZE); + if (ret) { + ERROR("%s: ERR: pka1 keytable ctx save error\n", + __func__); + goto pka_keytable_save_err; + } + + /* Update the pointer to the next word quad */ + se_dev->dst_ll_buf->buffer[0].addr += + TEGRA_SE_KEY_128_SIZE; + } + } + +pka_keytable_save_err: + return ret; +} + +static int tegra_se_save_SRK(tegra_se_dev_t *se_dev) +{ + tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, + SE_CTX_SAVE_SRC_SRK); + + /* SE context save operation */ + return tegra_se_start_ctx_save_operation(se_dev, 0); +} + +/* + * Lock both SE from non-TZ clients. + */ +static inline void tegra_se_lock(tegra_se_dev_t *se_dev) +{ + uint32_t val; + + assert(se_dev); + val = tegra_se_read_32(se_dev, SE_SECURITY_REG_OFFSET); + val |= SE_SECURITY_TZ_LOCK_SOFT(SE_SECURE); + tegra_se_write_32(se_dev, SE_SECURITY_REG_OFFSET, val); +} + +/* + * Use SRK to encrypt SE state and save to TZRAM carveout + */ +static int tegra_se_context_save_sw(tegra_se_dev_t *se_dev) +{ + int err = 0; + + assert(se_dev); + + /* Lock entire SE/SE2 as TZ protected */ + tegra_se_lock(se_dev); + + INFO("%s: generate SRK\n", __func__); + /* Generate SRK */ + err = tegra_se_generate_srk(se_dev); + if (err) { + ERROR("%s: ERR: SRK generation failed\n", __func__); + return err; + } + + INFO("%s: generate random data\n", __func__); + /* Generate random data */ + err = tegra_se_lp_generate_random_data(se_dev); + if (err) { + ERROR("%s: ERR: LP random pattern generation failed\n", __func__); + return err; + } + + INFO("%s: encrypt random data\n", __func__); + /* Encrypt the random data block */ + err = tegra_se_lp_data_context_save(se_dev, + ((uint64_t)(&(((tegra_se_context_t *)se_dev-> + ctx_save_buf)->rand_data))), + ((uint64_t)(&(((tegra_se_context_t *)se_dev-> + ctx_save_buf)->rand_data))), + SE_CTX_SAVE_RANDOM_DATA_SIZE); + if (err) { + ERROR("%s: ERR: random pattern encryption failed\n", __func__); + return err; + } + + INFO("%s: save SE sticky bits\n", __func__); + /* Save AES sticky bits context */ + err = tegra_se_lp_sticky_bits_context_save(se_dev); + if (err) { + ERROR("%s: ERR: sticky bits context save failed\n", __func__); + return err; + } + + INFO("%s: save AES keytables\n", __func__); + /* Save AES key table context */ + err = tegra_se_aeskeytable_context_save(se_dev); + if (err) { + ERROR("%s: ERR: LP keytable save failed\n", __func__); + return err; + } + + /* RSA key slot table context save */ + INFO("%s: save RSA keytables\n", __func__); + err = tegra_se_lp_rsakeytable_context_save(se_dev); + if (err) { + ERROR("%s: ERR: rsa key table context save failed\n", __func__); + return err; + } + + /* Only SE2 has an interface with PKA1; thus, PKA1's context is saved + * via SE2. + */ + if (se_dev->se_num == 2) { + /* Encrypt PKA1 sticky bits on SE2 only */ + INFO("%s: save PKA sticky bits\n", __func__); + err = tegra_se_pkakeytable_sticky_bits_save(se_dev); + if (err) { + ERROR("%s: ERR: PKA sticky bits context save failed\n", __func__); + return err; + } + + /* Encrypt PKA1 keyslots on SE2 only */ + INFO("%s: save PKA keytables\n", __func__); + err = tegra_se_pkakeytable_context_save(se_dev); + if (err) { + ERROR("%s: ERR: PKA key table context save failed\n", __func__); + return err; + } + } + + /* Encrypt known pattern */ + if (se_dev->se_num == 1) { + err = tegra_se_lp_data_context_save(se_dev, + ((uint64_t)(&se_ctx_known_pattern_data)), + ((uint64_t)(&(((tegra_se_context_blob_t *)se_dev->ctx_save_buf)->known_pattern))), + SE_CTX_KNOWN_PATTERN_SIZE); + } else if (se_dev->se_num == 2) { + err = tegra_se_lp_data_context_save(se_dev, + ((uint64_t)(&se_ctx_known_pattern_data)), + ((uint64_t)(&(((tegra_se2_context_blob_t *)se_dev->ctx_save_buf)->known_pattern))), + SE_CTX_KNOWN_PATTERN_SIZE); + } + if (err) { + ERROR("%s: ERR: save LP known pattern failure\n", __func__); + return err; + } + + /* Write lp context buffer address into PMC scratch register */ + if (se_dev->se_num == 1) { + /* SE context address, support T210 only */ + mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SCRATCH43_REG_OFFSET, + ((uint64_t)(se_dev->ctx_save_buf))); + } else if (se_dev->se_num == 2) { + /* SE2 & PKA1 context address */ + mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SECURE_SCRATCH116_OFFSET, + ((uint64_t)(se_dev->ctx_save_buf))); + } + + /* Saves SRK to PMC secure scratch registers for BootROM, which + * verifies and restores the security engine context on warm boot. + */ + err = tegra_se_save_SRK(se_dev); + if (err < 0) { + ERROR("%s: ERR: LP SRK save failure\n", __func__); + return err; + } + + INFO("%s: SE context save done \n", __func__); + + return err; +} + +/* + * Initialize the SE engine handle + */ +void tegra_se_init(void) +{ + uint32_t val = 0; + INFO("%s: start SE init\n", __func__); + + /* Generate random SRK to initialize DRBG */ + tegra_se_generate_srk(&se_dev_1); + + if (tegra_chipid_is_t210_b01()) { + tegra_se_generate_srk(&se_dev_2); + } + + /* determine if ECID is valid */ + val = mmio_read_32(TEGRA_FUSE_BASE + FUSE_JTAG_SECUREID_VALID); + ecid_valid = (val == ECID_VALID); + + INFO("%s: SE init done\n", __func__); +} + +static void tegra_se_enable_clocks(void) +{ + uint32_t val = 0; + + /* Enable entropy clock */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_W); + val |= ENTROPY_CLK_ENB_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_W, val); + + /* De-Assert Entropy Reset */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_W); + val &= ~ENTROPY_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_W, val); + + /* + * Switch SE clock source to CLK_M, to make sure SE clock + * is on when saving SE context + */ + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_RST_CTL_CLK_SRC_SE, + SE_CLK_SRC_CLK_M); + + /* Enable SE clock */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V); + val |= SE_CLK_ENB_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V, val); + + /* De-Assert SE Reset */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_V); + val &= ~SE_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_V, val); +} + +static void tegra_se_disable_clocks(void) +{ + uint32_t val = 0; + + /* Disable entropy clock */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_W); + val &= ~ENTROPY_CLK_ENB_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_W, val); + + /* Disable SE clock */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V); + val &= ~SE_CLK_ENB_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V, val); +} + +/* + * Security engine power suspend entry point. + * This function is invoked from PSCI power domain suspend handler. + */ +int32_t tegra_se_suspend(void) +{ + int32_t ret = 0; + uint32_t val = 0; + + /* SE does not use SMMU in EL3, disable SMMU. + * This will be re-enabled by kernel on resume */ + val = mmio_read_32(TEGRA_MC_BASE + MC_SMMU_PPCS_ASID_0); + val &= ~PPCS_SMMU_ENABLE; + mmio_write_32(TEGRA_MC_BASE + MC_SMMU_PPCS_ASID_0, val); + + tegra_se_enable_clocks(); + + if (tegra_chipid_is_t210_b01()) { + /* It is T210 B01, Atomic context save se2 and pka1 */ + INFO("%s: SE2/PKA1 atomic context save\n", __func__); + ret = tegra_se_context_save_atomic(&se_dev_2); + if (ret != 0) { + ERROR("%s: SE2 ctx save failed (%d)\n", __func__, ret); + } + + ret = tegra_se_context_save_atomic(&se_dev_1); + if (ret != 0) { + ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret); + } + } else { + /* It is T210, SW context save se */ + INFO("%s: SE1 legacy(SW) context save\n", __func__); + ret = tegra_se_context_save_sw(&se_dev_1); + if (ret != 0) { + ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret); + } + } + + tegra_se_disable_clocks(); + + return ret; +} + +/* + * Save TZRAM to shadow TZRAM in AON + */ +int32_t tegra_se_save_tzram(void) +{ + uint32_t val = 0; + int32_t ret = 0; + uint32_t timeout; + + INFO("%s: SE TZRAM save start\n", __func__); + tegra_se_enable_clocks(); + + val = (SE_TZRAM_OP_REQ_INIT | SE_TZRAM_OP_MODE_SAVE); + tegra_se_write_32(&se_dev_1, SE_TZRAM_OPERATION, val); + + val = tegra_se_read_32(&se_dev_1, SE_TZRAM_OPERATION); + for (timeout = 0; (SE_TZRAM_OP_BUSY(val) == SE_TZRAM_OP_BUSY_ON) && + (timeout < TIMEOUT_100MS); timeout++) { + mdelay(1); + val = tegra_se_read_32(&se_dev_1, SE_TZRAM_OPERATION); + } + + if (timeout == TIMEOUT_100MS) { + ERROR("%s: ERR: TZRAM save timeout!\n", __func__); + ret = -ETIMEDOUT; + } + + if (ret == 0) { + INFO("%s: SE TZRAM save done!\n", __func__); + } + + tegra_se_disable_clocks(); + + return ret; +} + +/* + * The function is invoked by SE resume + */ +static void tegra_se_warm_boot_resume(const tegra_se_dev_t *se_dev) +{ + uint32_t val; + + assert(se_dev); + + /* Lock RNG source to ENTROPY on resume */ + val = DRBG_RO_ENT_IGNORE_MEM_ENABLE | + DRBG_RO_ENT_SRC_LOCK_ENABLE | + DRBG_RO_ENT_SRC_ENABLE; + tegra_se_write_32(se_dev, SE_RNG_SRC_CONFIG_REG_OFFSET, val); + + /* Set a random value to SRK to initialize DRBG */ + tegra_se_generate_srk(se_dev); +} + +/* + * The function is invoked on SC7 resume + */ +void tegra_se_resume(void) +{ + tegra_se_warm_boot_resume(&se_dev_1); + + if (tegra_chipid_is_t210_b01()) { + tegra_se_warm_boot_resume(&se_dev_2); + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c new file mode 100644 index 0000000..7f73ea5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2015-2018, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Register used to clear CPU reset signals. Each CPU has two reset + * signals: CPU reset (3:0) and Core reset (19:16). + */ +#define CPU_CMPLX_RESET_CLR 0x454 +#define CPU_CORE_RESET_MASK 0x10001 + +/* Clock and Reset controller registers for system clock's settings */ +#define SCLK_RATE 0x30 +#define SCLK_BURST_POLICY 0x28 +#define SCLK_BURST_POLICY_DEFAULT 0x10000000 + +static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER]; +static bool tegra_bpmp_available = true; + +int32_t tegra_soc_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int state_id = psci_get_pstate_id(power_state); + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + + /* Sanity check the requested state id */ + switch (state_id) { + case PSTATE_ID_CORE_POWERDN: + /* + * Core powerdown request only for afflvl 0 + */ + req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id & 0xff; + + break; + + case PSTATE_ID_CLUSTER_IDLE: + + /* + * Cluster idle request for afflvl 0 + */ + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PSTATE_ID_CORE_POWERDN; + req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id; + break; + + case PSTATE_ID_SOC_POWERDN: + + /* + * sc7entry-fw must be present in the system when the bpmp + * firmware is not present, for a successful System Suspend + * entry. + */ + if (!tegra_bpmp_init() && !plat_params->sc7entry_fw_base) + return PSCI_E_NOT_SUPPORTED; + + /* + * System powerdown request only for afflvl 2 + */ + for (uint32_t i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + + req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = + PLAT_SYS_SUSPEND_STATE_ID; + + break; + + default: + ERROR("%s: unsupported state id (%d)\n", __func__, state_id); + return PSCI_E_INVALID_PARAMS; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler to calculate the proper target power level at the + * specified affinity level. + ******************************************************************************/ +plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl, + const plat_local_state_t *states, + unsigned int ncpu) +{ + plat_local_state_t target = PSCI_LOCAL_STATE_RUN; + int cpu = plat_my_core_pos(); + int core_pos = read_mpidr() & MPIDR_CPU_MASK; + uint32_t bpmp_reply, data[3], val; + int ret; + + /* get the power state at this level */ + if (lvl == MPIDR_AFFLVL1) + target = *(states + core_pos); + if (lvl == MPIDR_AFFLVL2) + target = *(states + cpu); + + if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_IDLE)) { + + /* initialize the bpmp interface */ + ret = tegra_bpmp_init(); + if (ret != 0U) { + + /* + * flag to indicate that BPMP firmware is not + * available and the CPU has to handle entry/exit + * for all power states + */ + tegra_bpmp_available = false; + + /* Cluster idle not allowed */ + target = PSCI_LOCAL_STATE_RUN; + + /******************************************* + * BPMP is not present, so handle CC6 entry + * from the CPU + ******************************************/ + + /* check if cluster idle state has been enabled */ + val = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL); + if (val == ENABLE_CLOSED_LOOP) { + /* + * Acquire the cluster idle lock to stop + * other CPUs from powering up. + */ + tegra_fc_ccplex_pgexit_lock(); + + /* Cluster idle only from the last standing CPU */ + if (tegra_pmc_is_last_on_cpu() && tegra_fc_is_ccx_allowed()) { + /* Cluster idle allowed */ + target = PSTATE_ID_CLUSTER_IDLE; + } else { + /* release cluster idle lock */ + tegra_fc_ccplex_pgexit_unlock(); + } + } + } else { + + /* Cluster power-down */ + data[0] = (uint32_t)cpu; + data[1] = TEGRA_PM_CC6; + data[2] = TEGRA_PM_SC1; + ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE, + (void *)&data, (int)sizeof(data), + (void *)&bpmp_reply, + (int)sizeof(bpmp_reply)); + + /* check if cluster power down is allowed */ + if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) { + + /* Cluster power down not allowed */ + target = PSCI_LOCAL_STATE_RUN; + } + } + + } else if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) && + (target == PSTATE_ID_SOC_POWERDN)) { + + /* System Suspend */ + target = PSTATE_ID_SOC_POWERDN; + + } else { + ; /* do nothing */ + } + + return target; +} + +int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) +{ + (void)cpu_state; + return PSCI_E_SUCCESS; +} + +int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr(); + const plat_local_state_t *pwr_domain_state = + target_state->pwr_domain_state; + unsigned int stateid_afflvl2 = pwr_domain_state[MPIDR_AFFLVL2]; + unsigned int stateid_afflvl1 = pwr_domain_state[MPIDR_AFFLVL1]; + unsigned int stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0]; + uint32_t cfg; + int ret = PSCI_E_SUCCESS; + uint32_t val; + + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + + assert((stateid_afflvl0 == PLAT_MAX_OFF_STATE) || + (stateid_afflvl0 == PSTATE_ID_SOC_POWERDN)); + assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) || + (stateid_afflvl1 == PSTATE_ID_SOC_POWERDN)); + + /* Suspend se/se2 and pka1 for T210 B01 and se for T210 */ + if (tegra_se_suspend() != 0) { + ret = PSCI_E_INTERN_FAIL; + } + + } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) { + + assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN); + + if (!tegra_bpmp_available) { + + /* + * When disabled, DFLL loses its state. Enable + * open loop state for the DFLL as we dont want + * garbage values being written to the pmic + * when we enter cluster idle state. + */ + mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL, + ENABLE_OPEN_LOOP); + + /* Find if the platform uses OVR2/MAX77621 PMIC */ + cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG); + if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) { + /* OVR2 */ + + /* PWM tristate */ + val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); + val |= PINMUX_PWM_TRISTATE; + mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val); + + /* + * SCRATCH201[1] is being used to identify CPU + * PMIC in warmboot code. + * 0 : OVR2 + * 1 : MAX77621 + */ + tegra_pmc_write_32(PMC_SCRATCH201, 0x0); + } else { + /* MAX77621 */ + tegra_pmc_write_32(PMC_SCRATCH201, 0x2); + } + } + + /* Prepare for cluster idle */ + tegra_fc_cluster_idle(mpidr); + + } else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) { + + /* Prepare for cpu powerdn */ + tegra_fc_cpu_powerdn(mpidr); + + } else { + ERROR("%s: Unknown state id (%d, %d, %d)\n", __func__, + stateid_afflvl2, stateid_afflvl1, stateid_afflvl0); + ret = PSCI_E_NOT_SUPPORTED; + } + + return ret; +} + +static void tegra_reset_all_dma_masters(void) +{ + uint32_t val, mask; + + /* + * Reset all possible DMA masters in the system. + */ + val = GPU_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET, val); + + val = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT | + NVJPG_RESET_BIT | NVDEC_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y, val); + + val = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT | + VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT | + SDMMC2_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L, val); + + val = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H, val); + + val = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT | + PCIE_RESET_BIT | SDMMC3_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U, val); + + val = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT; + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V, val); + + /* + * If any of the DMA masters are still alive, assume + * that the system has been compromised and reboot. + */ + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET); + mask = GPU_RESET_BIT; + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + mask = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT | + NVJPG_RESET_BIT | NVDEC_RESET_BIT; + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y); + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + mask = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT | + VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT | + SDMMC2_RESET_BIT; + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L); + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + mask = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT; + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H); + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + mask = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT | + PCIE_RESET_BIT | SDMMC3_RESET_BIT; + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U); + if ((val & mask) != mask) + tegra_pmc_system_reset(); + + val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V); + mask = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT; + if ((val & mask) != mask) + tegra_pmc_system_reset(); +} + +int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr(); + const plat_local_state_t *pwr_domain_state = + target_state->pwr_domain_state; + unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL]; + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + uint32_t val; + + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + + if (tegra_chipid_is_t210_b01()) { + /* Save tzram contents */ + tegra_se_save_tzram(); + } + + /* de-init the interface */ + tegra_bpmp_suspend(); + + /* + * The CPU needs to load the System suspend entry firmware + * if nothing is running on the BPMP. + */ + if (!tegra_bpmp_available) { + + /* + * BPMP firmware is not running on the co-processor, so + * we need to explicitly load the firmware to enable + * entry/exit to/from System Suspend and set the BPMP + * on its way. + */ + + /* Power off BPMP before we proceed */ + tegra_fc_bpmp_off(); + + /* bond out IRAM banks B, C and D */ + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_U, + IRAM_B_LOCK_BIT | IRAM_C_LOCK_BIT | + IRAM_D_LOCK_BIT); + + /* bond out APB/AHB DMAs */ + mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_H, + APB_DMA_LOCK_BIT | AHB_DMA_LOCK_BIT); + + /* Power off BPMP before we proceed */ + tegra_fc_bpmp_off(); + + /* + * Reset all the hardware blocks that can act as DMA + * masters on the bus. + */ + tegra_reset_all_dma_masters(); + + /* + * Mark PMC as accessible to the non-secure world + * to allow the COP to execute System Suspend + * sequence + */ + val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE); + val &= ~PMC_SECURITY_EN_BIT; + mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val); + + /* clean up IRAM of any cruft */ + zeromem((void *)(uintptr_t)TEGRA_IRAM_BASE, + TEGRA_IRAM_A_SIZE); + + /* Copy the firmware to BPMP's internal RAM */ + (void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE, + (const void *)(plat_params->sc7entry_fw_base + SC7ENTRY_FW_HEADER_SIZE_BYTES), + plat_params->sc7entry_fw_size - SC7ENTRY_FW_HEADER_SIZE_BYTES); + + /* Power on the BPMP and execute from IRAM base */ + tegra_fc_bpmp_on(TEGRA_IRAM_BASE); + + /* Wait until BPMP powers up */ + do { + val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET); + } while (val != SIGN_OF_LIFE); + } + + /* enter system suspend */ + tegra_fc_soc_powerdn(mpidr); + } + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + uint32_t cfg; + uint32_t val, entrypoint = 0; + uint64_t offset; + + /* platform parameter passed by the previous bootloader */ + if (plat_params->l2_ecc_parity_prot_dis != 1) { + /* Enable ECC Parity Protection for Cortex-A57 CPUs */ + val = read_l2ctlr_el1(); + val |= (uint64_t)CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT; + write_l2ctlr_el1(val); + } + + /* + * Check if we are exiting from SOC_POWERDN. + */ + if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == + PLAT_SYS_SUSPEND_STATE_ID) { + + /* + * Security engine resume + */ + if (tegra_chipid_is_t210_b01()) { + tegra_se_resume(); + } + + /* + * Lock scratch registers which hold the CPU vectors + */ + tegra_pmc_lock_cpu_vectors(); + + /* + * Enable WRAP to INCR burst type conversions for + * incoming requests on the AXI slave ports. + */ + val = mmio_read_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG); + val &= ~ENABLE_UNSUP_TX_ERRORS; + val |= ENABLE_WRAP_TO_INCR_BURSTS; + mmio_write_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG, val); + + /* + * Restore Boot and Power Management Processor (BPMP) reset + * address and reset it, if it is supported by the platform. + */ + if (!tegra_bpmp_available) { + tegra_fc_bpmp_off(); + } else { + entrypoint = tegra_pmc_read_32(PMC_SCRATCH39); + tegra_fc_bpmp_on(entrypoint); + + /* initialise the interface */ + tegra_bpmp_resume(); + } + + if (plat_params->sc7entry_fw_base != 0U) { + /* sc7entry-fw is part of TZDRAM area */ + offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base; + tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base, + plat_params->tzdram_size + offset); + } + + if (!tegra_chipid_is_t210_b01()) { + /* restrict PMC access to secure world */ + val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE); + val |= PMC_SECURITY_EN_BIT; + mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val); + } + } + + /* + * Check if we are exiting cluster idle state + */ + if (target_state->pwr_domain_state[MPIDR_AFFLVL1] == + PSTATE_ID_CLUSTER_IDLE) { + + if (!tegra_bpmp_available) { + + /* PWM un-tristate */ + cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG); + if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) { + val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); + val &= ~PINMUX_PWM_TRISTATE; + mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val); + + /* make sure the setting took effect */ + val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); + assert((val & PINMUX_PWM_TRISTATE) == 0U); + } + + /* + * Restore operation mode for the DFLL ring + * oscillator + */ + mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL, + ENABLE_CLOSED_LOOP); + + /* release cluster idle lock */ + tegra_fc_ccplex_pgexit_unlock(); + } + } + + /* + * Mark this CPU as ON in the cpu_powergate_mask[], + * so that we use Flow Controller for all subsequent + * power ups. + */ + cpu_powergate_mask[plat_my_core_pos()] = 1; + + /* + * T210 has a dedicated ARMv7 boot and power mgmt processor, BPMP. It's + * used for power management and boot purposes. Inform the BPMP that + * we have completed the cluster power up. + */ + tegra_fc_lock_active_cluster(); + + /* + * Resume PMC hardware block for Tegra210 platforms + */ + if (!tegra_chipid_is_t210_b01()) { + tegra_pmc_resume(); + } + + return PSCI_E_SUCCESS; +} + +int tegra_soc_pwr_domain_on(u_register_t mpidr) +{ + int cpu = mpidr & MPIDR_CPU_MASK; + uint32_t mask = CPU_CORE_RESET_MASK << cpu; + + /* Deassert CPU reset signals */ + mmio_write_32(TEGRA_CAR_RESET_BASE + CPU_CMPLX_RESET_CLR, mask); + + /* Turn on CPU using flow controller or PMC */ + if (cpu_powergate_mask[cpu] == 0) { + tegra_pmc_cpu_on(cpu); + } else { + tegra_fc_cpu_on(cpu); + } + + return PSCI_E_SUCCESS; +} + +int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) +{ + tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK); + return PSCI_E_SUCCESS; +} + +int tegra_soc_prepare_system_reset(void) +{ + /* + * Set System Clock (SCLK) to POR default so that the clock source + * for the PMC APB clock would not be changed due to system reset. + */ + mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY, + SCLK_BURST_POLICY_DEFAULT); + mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0); + + /* Wait 1 ms to make sure clock source/device logic is stabilized. */ + mdelay(1); + + /* + * Program the PMC in order to restart the system. + */ + tegra_pmc_system_reset(); + + return PSCI_E_SUCCESS; +} + +__dead2 void tegra_soc_prepare_system_off(void) +{ + ERROR("Tegra System Off: operation not handled.\n"); + panic(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c new file mode 100644 index 0000000..e0242cf --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#define SB_CSR 0x0 +#define SB_CSR_NS_RST_VEC_WR_DIS (1 << 1) + +/* CPU reset vector */ +#define SB_AA64_RESET_LOW 0x30 /* width = 31:0 */ +#define SB_AA64_RESET_HI 0x34 /* width = 11:0 */ + +extern void tegra_secure_entrypoint(void); + +/******************************************************************************* + * Setup secondary CPU vectors + ******************************************************************************/ +void plat_secondary_setup(void) +{ + uint32_t val; + uint64_t reset_addr = (uint64_t)tegra_secure_entrypoint; + + INFO("Setting up secondary CPU boot\n"); + + /* setup secondary CPU vector */ + mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_LOW, + (reset_addr & 0xFFFFFFFF) | 1); + val = reset_addr >> 32; + mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_HI, val & 0x7FF); + + /* configure PMC */ + tegra_pmc_cpu_setup(reset_addr); + tegra_pmc_lock_cpu_vectors(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c new file mode 100644 index 0000000..19b41ed --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2015-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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* sets of MMIO ranges setup */ +#define MMIO_RANGE_0_ADDR 0x50000000 +#define MMIO_RANGE_1_ADDR 0x60000000 +#define MMIO_RANGE_2_ADDR 0x70000000 +#define MMIO_RANGE_SIZE 0x200000 + +/* + * Table of regions to map using the MMU. + */ +static const mmap_region_t tegra_mmap[] = { + MAP_REGION_FLAT(TEGRA_IRAM_BASE, 0x40000, /* 256KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MMIO_RANGE_0_ADDR, MMIO_RANGE_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MMIO_RANGE_1_ADDR, MMIO_RANGE_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MMIO_RANGE_2_ADDR, MMIO_RANGE_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + {0} +}; + +/******************************************************************************* + * Set up the pagetables as per the platform memory map & initialize the MMU + ******************************************************************************/ +const mmap_region_t *plat_get_mmio_map(void) +{ + /* Add the map region for security engine SE2 */ + if (tegra_chipid_is_t210_b01()) { + mmap_add_region((uint64_t)TEGRA_SE2_BASE, + (uint64_t)TEGRA_SE2_BASE, + (uint64_t)TEGRA_SE2_RANGE_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + } + + /* MMIO space */ + return tegra_mmap; +} + +/******************************************************************************* + * The Tegra power domain tree has a single system level power domain i.e. a + * single root node. The first entry in the power domain descriptor specifies + * the number of power domains at the highest power level. + ******************************************************************************* + */ +const unsigned char tegra_power_domain_tree_desc[] = { + /* No of root nodes */ + 1, + /* No of clusters */ + PLATFORM_CLUSTER_COUNT, + /* No of CPU cores - cluster0 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster1 */ + PLATFORM_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the Tegra default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return tegra_power_domain_tree_desc; +} + +/******************************************************************************* + * Handler to get the System Counter Frequency + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + return 19200000; +} + +/******************************************************************************* + * Maximum supported UART controllers + ******************************************************************************/ +#define TEGRA210_MAX_UART_PORTS 5 + +/******************************************************************************* + * This variable holds the UART port base addresses + ******************************************************************************/ +static uint32_t tegra210_uart_addresses[TEGRA210_MAX_UART_PORTS + 1] = { + 0, /* undefined - treated as an error case */ + TEGRA_UARTA_BASE, + TEGRA_UARTB_BASE, + TEGRA_UARTC_BASE, + TEGRA_UARTD_BASE, + TEGRA_UARTE_BASE, +}; + +/******************************************************************************* + * Enable console corresponding to the console ID + ******************************************************************************/ +void plat_enable_console(int32_t id) +{ + static console_t uart_console; + uint32_t console_clock; + + if ((id > 0) && (id < TEGRA210_MAX_UART_PORTS)) { + /* + * Reference clock used by the FPGAs is a lot slower. + */ + if (tegra_platform_is_fpga()) { + console_clock = TEGRA_BOOT_UART_CLK_13_MHZ; + } else { + console_clock = TEGRA_BOOT_UART_CLK_408_MHZ; + } + + (void)console_16550_register(tegra210_uart_addresses[id], + console_clock, + TEGRA_CONSOLE_BAUDRATE, + &uart_console); + console_set_scope(&uart_console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH); + } +} + +/******************************************************************************* + * Return pointer to the BL31 params from previous bootloader + ******************************************************************************/ +struct tegra_bl31_params *plat_get_bl31_params(void) +{ + return NULL; +} + +/******************************************************************************* + * Return pointer to the BL31 platform params from previous bootloader + ******************************************************************************/ +plat_params_from_bl2_t *plat_get_bl31_plat_params(void) +{ + return NULL; +} + +/******************************************************************************* + * Handler for early platform setup + ******************************************************************************/ +void plat_early_platform_setup(void) +{ + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + uint64_t val; + + /* Verify chip id is t210 */ + assert(tegra_chipid_is_t210()); + + /* + * Do initial security configuration to allow DRAM/device access. + */ + tegra_memctrl_tzdram_setup(plat_params->tzdram_base, + (uint32_t)plat_params->tzdram_size); + + /* platform parameter passed by the previous bootloader */ + if (plat_params->l2_ecc_parity_prot_dis != 1) { + /* Enable ECC Parity Protection for Cortex-A57 CPUs */ + val = read_l2ctlr_el1(); + val |= (uint64_t)CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT; + write_l2ctlr_el1(val); + } + + /* Initialize security engine driver */ + tegra_se_init(); +} + +/* Secure IRQs for Tegra186 */ +static const interrupt_prop_t tegra210_interrupt_props[] = { + INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(TEGRA210_TIMER1_IRQ, PLAT_TEGRA_WDT_PRIO, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(TEGRA210_WDT_CPU_LEGACY_FIQ, PLAT_TEGRA_WDT_PRIO, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), +}; + +/******************************************************************************* + * Handler for late platform setup + ******************************************************************************/ +void plat_late_platform_setup(void) +{ + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + uint64_t sc7entry_end, offset; + int ret; + uint32_t val; + + /* memmap TZDRAM area containing the SC7 Entry Firmware */ + if (plat_params->sc7entry_fw_base && plat_params->sc7entry_fw_size) { + + assert(plat_params->sc7entry_fw_size <= TEGRA_IRAM_A_SIZE); + + /* + * Verify that the SC7 entry firmware resides inside the TZDRAM + * aperture, _before_ the BL31 code and the start address is + * exactly 1MB from BL31 base. + */ + + /* sc7entry-fw must be _before_ BL31 base */ + assert(plat_params->tzdram_base > plat_params->sc7entry_fw_base); + + sc7entry_end = plat_params->sc7entry_fw_base + + plat_params->sc7entry_fw_size; + assert(sc7entry_end < plat_params->tzdram_base); + + /* sc7entry-fw start must be exactly 1MB behind BL31 base */ + offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base; + assert(offset == 0x100000); + + /* secure TZDRAM area */ + tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base, + plat_params->tzdram_size + offset); + + /* power off BPMP processor until SC7 entry */ + tegra_fc_bpmp_off(); + + /* memmap SC7 entry firmware code */ + ret = mmap_add_dynamic_region(plat_params->sc7entry_fw_base, + plat_params->sc7entry_fw_base, + plat_params->sc7entry_fw_size, + MT_SECURE | MT_RO_DATA); + assert(ret == 0); + + /* restrict PMC access to secure world */ + val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE); + val |= PMC_SECURITY_EN_BIT; + mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val); + } + + if (!tegra_chipid_is_t210_b01()) { + /* restrict PMC access to secure world */ + val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE); + val |= PMC_SECURITY_EN_BIT; + mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val); + } + + if (tegra_chipid_is_t210_b01()) { + /* map TZDRAM used by BL31 as coherent memory */ + ret = mmap_add_dynamic_region(plat_params->tzdram_base, + plat_params->tzdram_base, + BL31_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + assert(ret == 0); + } +} + +/******************************************************************************* + * Initialize the GIC and SGIs + ******************************************************************************/ +void plat_gic_setup(void) +{ + tegra_gic_setup(tegra210_interrupt_props, ARRAY_SIZE(tegra210_interrupt_props)); + tegra_gic_init(); + + /* Enable handling for FIQs */ + tegra_fiq_handler_setup(); + + /* + * Enable routing watchdog FIQs from the flow controller to + * the GICD. + */ + tegra_fc_enable_fiq_to_ccplex_routing(); +} +/******************************************************************************* + * Handler to indicate support for System Suspend + ******************************************************************************/ +bool plat_supports_system_suspend(void) +{ + const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); + + /* + * sc7entry-fw is only supported by Tegra210 SoCs. + */ + if (!tegra_chipid_is_t210_b01() && (plat_params->sc7entry_fw_base != 0U)) { + return true; + } else if (tegra_chipid_is_t210_b01()) { + return true; + } else { + return false; + } +} +/******************************************************************************* + * Platform specific runtime setup. + ******************************************************************************/ +void plat_runtime_setup(void) +{ + /* + * During cold boot, it is observed that the arbitration + * bit is set in the Memory controller leading to false + * error interrupts in the non-secure world. To avoid + * this, clean the interrupt status register before + * booting into the non-secure world + */ + tegra_memctrl_clear_pending_interrupts(); + + /* + * During boot, USB3 and flash media (SDMMC/SATA) devices need + * access to IRAM. Because these clients connect to the MC and + * do not have a direct path to the IRAM, the MC implements AHB + * redirection during boot to allow path to IRAM. In this mode + * accesses to a programmed memory address aperture are directed + * to the AHB bus, allowing access to the IRAM. This mode must be + * disabled before we jump to the non-secure world. + */ + tegra_memctrl_disable_ahb_redirection(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c new file mode 100644 index 0000000..e3484be --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, 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 +#include +#include + +#include +#include +#include +#include +#include + +/******************************************************************************* + * PMC parameters + ******************************************************************************/ +#define PMC_READ U(0xaa) +#define PMC_WRITE U(0xbb) + +/******************************************************************************* + * Tegra210 SiP SMCs + ******************************************************************************/ +#define TEGRA_SIP_PMC_COMMANDS U(0xC2FFFE00) + +/******************************************************************************* + * This function is responsible for handling all T210 SiP calls + ******************************************************************************/ +int plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + const void *cookie, + void *handle, + uint64_t flags) +{ + uint32_t val, ns; + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + if (!ns) + SMC_RET1(handle, SMC_UNK); + + if (smc_fid == TEGRA_SIP_PMC_COMMANDS) { + /* check the address is within PMC range and is 4byte aligned */ + if ((x2 >= TEGRA_PMC_SIZE) || (x2 & 0x3)) + return -EINVAL; + + switch (x2) { + /* Black listed PMC registers */ + case PMC_SCRATCH1: + case PMC_SCRATCH31 ... PMC_SCRATCH33: + case PMC_SCRATCH40: + case PMC_SCRATCH42: + case PMC_SCRATCH43 ... PMC_SCRATCH48: + case PMC_SCRATCH50 ... PMC_SCRATCH51: + case PMC_SCRATCH56 ... PMC_SCRATCH57: + /* PMC secure-only registers are not accessible */ + case PMC_DPD_ENABLE_0: + case PMC_FUSE_CONTROL_0: + case PMC_CRYPTO_OP_0: + case PMC_TSC_MULT_0: + case PMC_STICKY_BIT: + ERROR("%s: error offset=0x%" PRIx64 "\n", __func__, x2); + return -EFAULT; + default: + /* Valid register */ + break; + } + + /* Perform PMC read/write */ + if (x1 == PMC_READ) { + val = mmio_read_32((uint32_t)(TEGRA_PMC_BASE + x2)); + write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, val); + } else if (x1 == PMC_WRITE) { + mmio_write_32((uint32_t)(TEGRA_PMC_BASE + x2), (uint32_t)x3); + } else { + return -EINVAL; + } + } else { + return -ENOTSUP; + } + return 0; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/platform_t210.mk b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/platform_t210.mk new file mode 100644 index 0000000..9770eb1 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/platform_t210.mk @@ -0,0 +1,65 @@ +# +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_BL31_BASE := 0xFF800000 +$(eval $(call add_define,PLAT_BL31_BASE)) + +ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT := 1 +$(eval $(call add_define,ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT)) + +PLATFORM_CLUSTER_COUNT := 2 +$(eval $(call add_define,PLATFORM_CLUSTER_COUNT)) + +PLATFORM_MAX_CPUS_PER_CLUSTER := 4 +$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER)) + +MAX_XLAT_TABLES := 10 +$(eval $(call add_define,MAX_XLAT_TABLES)) + +MAX_MMAP_REGIONS := 16 +$(eval $(call add_define,MAX_MMAP_REGIONS)) + +ENABLE_TEGRA_WDT_LEGACY_FIQ_HANDLING := 1 + +# include common makefiles +include plat/nvidia/tegra/common/tegra_common.mk + +PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t210 \ + -I${SOC_DIR}/drivers/se + +BL31_SOURCES += ${TEGRA_GICv2_SOURCES} \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + ${TEGRA_DRIVERS}/bpmp/bpmp.c \ + ${TEGRA_DRIVERS}/flowctrl/flowctrl.c \ + ${TEGRA_DRIVERS}/memctrl/memctrl_v1.c \ + ${TEGRA_DRIVERS}/pmc/pmc.c \ + ${SOC_DIR}/plat_psci_handlers.c \ + ${SOC_DIR}/plat_setup.c \ + ${SOC_DIR}/drivers/se/security_engine.c \ + ${SOC_DIR}/plat_secondary.c \ + ${SOC_DIR}/plat_sip_calls.c + +# Enable workarounds for selected Cortex-A57 erratas. +A57_DISABLE_NON_TEMPORAL_HINT := 1 +ERRATA_A57_826974 := 1 +ERRATA_A57_826977 := 1 +ERRATA_A57_828024 := 1 +ERRATA_A57_833471 := 1 + +# Enable workarounds for selected Cortex-A53 erratas. +A53_DISABLE_NON_TEMPORAL_HINT := 1 +ERRATA_A53_826319 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_855873 := 1 + +# Skip L1 $ flush when powering down Cortex-A57 CPUs +SKIP_A57_L1_FLUSH_PWR_DWN := 1 + +# Enable higher performance Non-cacheable load forwarding +A57_ENABLE_NONCACHEABLE_LOAD_FWD := 1 diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h new file mode 100644 index 0000000..6a4a716 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MCE_PRIVATE_H__ +#define __MCE_PRIVATE_H__ + +#include +#include + +/******************************************************************************* + * Macros to prepare CSTATE info request + ******************************************************************************/ +/* Description of the parameters for UPDATE_CSTATE_INFO request */ +#define CLUSTER_CSTATE_MASK 0x7U +#define CLUSTER_CSTATE_SHIFT 0X0U +#define SYSTEM_CSTATE_MASK 0xFU +#define SYSTEM_CSTATE_SHIFT 16U + +/******************************************************************************* + * Core ID mask (bits 3:0 in the online request) + ******************************************************************************/ +#define MCE_CORE_ID_MASK 0xFU + +/******************************************************************************* + * C-state statistics macros + ******************************************************************************/ +#define MCE_STAT_ID_SHIFT 16U + +/******************************************************************************* + * Uncore PERFMON ARI macros + ******************************************************************************/ +#define UNCORE_PERFMON_CMD_READ U(0) +#define UNCORE_PERFMON_CMD_WRITE U(1) + +#define UNCORE_PERFMON_CMD_MASK U(0xFF) +#define UNCORE_PERFMON_UNIT_GRP_MASK U(0xF) +#define UNCORE_PERFMON_SELECTOR_MASK U(0xF) +#define UNCORE_PERFMON_REG_MASK U(0xFF) +#define UNCORE_PERFMON_CTR_MASK U(0xFF) +#define UNCORE_PERFMON_RESP_STATUS_MASK U(0xFF) + +/******************************************************************************* + * CLUSTER_CONFIG ARI macros + ******************************************************************************/ +#define CLUSTER_MODE_SHIFT(cluster) ((cluster) << 1U) +#define CLUSTER_MODE_MASK 0x3U +#define CLUSTER_MODE_DISABLED 0U +#define CLUSTER_MODE_SPLIT 1U +#define CLUSTER_MODE_HYBRID 2U +#define CLUSTER_MODE_LOCK 3U + +/* declarations for ARI handler functions */ +/* Function from NS world */ +uint64_t ari_get_version(uint32_t ari_base); +uint32_t ari_num_cores(uint32_t ari_base); +uint32_t ari_cluster_present_map(uint32_t ari_base); +uint32_t ari_ccplex_cache_clean(uint32_t ari_base); +uint32_t ari_ccplex_cache_clean_and_invalidate(uint32_t ari_base); +/* Function for secure world */ +#if DEBUG +uint32_t ari_core_debug_recovery(uint32_t ari_base, uint32_t core_id, bool core_warm_reset); +uint32_t ari_dsu_debug_recovery(uint32_t ari_base, uint32_t cluster_id, bool cluster_warm_reset); +uint32_t ari_ccplex_latic_on(uint32_t ari_base); +#endif +uint32_t ari_online_core(uint32_t ari_base, uint32_t core); +uint32_t ari_enter_cstate(uint32_t ari_base, uint32_t wake_time); +uint32_t ari_trigger_online_ist(uint32_t ari_base, uint32_t slice_id); +uint32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, + uint32_t system, uint32_t wake_mask, uint8_t update_wake_mas); +bool ari_is_sc7_allowed(uint32_t ari_base); +void ari_enable_strict_checking_mode(uint32_t ari_base); +int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx); + +void ari_system_shutdown(uint32_t ari_base); +void ari_system_reboot(uint32_t ari_base); + +/* MCE helper functions */ +void mce_clean_and_invalidate_caches(void); +void mce_enable_strict_checking(void); +uint32_t mce_enter_debug_recovery_mode(uint32_t core_id); +void mce_system_shutdown(void); +void mce_system_reboot(void); +uint32_t mce_num_cores(void); +bool mce_is_cluster_present(unsigned int id); +bool mce_is_cluster_in_lock_mode(unsigned int id); +bool mce_is_cluster_in_split_mode(unsigned int id); +bool mce_is_cluster_in_hybrid_mode(unsigned int id); + +#endif /* __MCE_PRIVATE_H__ */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h new file mode 100644 index 0000000..c0df0e4 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SE_H__ +#define __SE_H__ + +int32_t tegra_se_suspend(void); +void tegra_se_resume(void); + +#endif /* __SE_H__ */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h new file mode 100644 index 0000000..db91da5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h @@ -0,0 +1,265 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) 2019-2021 NVIDIA Corporation - All Rights Reserved +// +// This source module contains confidential and proprietary information +// of NVIDIA Corporation. It is not to be disclosed or used except +// in accordance with applicable agreements. This copyright notice does +// not evidence any actual or intended publication of such source code. +// +// ----------------------------------------------------------------------- +#ifndef T234_ARI_H +#define T234_ARI_H +/* ARI Version numbers */ +#define TEGRA_ARI_VERSION_MAJOR 8UL +#define TEGRA_ARI_VERSION_MINOR 1UL + +/* + * ARI Request IDs + * + * TODO: RENUMBER range before finalization + * NOTE: for documentation purposes, only documenting gaps + * in ranges, to indicate that we know about the missing ids + * + * Require NO LAB Locks + * range from 0 - 31 + */ +#define TEGRA_ARI_VERSION 0UL +#define TEGRA_ARI_ECHO 1UL +#define TEGRA_ARI_NUM_CORES 2UL +#define TEGRA_ARI_CSTATE_STAT_QUERY 3UL +#define TEGRA_ARI_CLUSTER_CONFIG 4UL +/* Undefined 5 - 28 */ +/* + * Debug Only ARIs at the end of the NO LAB Lock Range + */ +#define TEGRA_ARI_CORE_DEBUG_RECOVERY 29UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY 30UL +#define TEGRA_ARI_CLUSTER_WARM_RESET 31UL +/* + * Require CORE LAB Lock -- obtained by MTM from ARI + * range from 32 - 63 + */ +/* UNDEFINED 32 */ +/* UNDEFINED 33 */ +#define TEGRA_ARI_ONLINE_CORE 34UL +#define TEGRA_ARI_ENTER_CSTATE 35UL +#define TEGRA_ARI_PRETRIGGER_ONLINE_IST 36UL +#define TEGRA_ARI_TRIGGER_ONLINE_IST 37UL +#define TEGRA_ARI_ONLINE_IST_STATUS 38UL +#define TEGRA_ARI_ONLINE_IST_DMA_STATUS 39UL +/* + * Require CLUSTER and CORE LAB Lock -- obtained by MTM from ARI + * range from 64 - 95 + */ +/* UNDEFINED 64 */ +#define TEGRA_ARI_NVFREQ_REQ 65UL +#define TEGRA_ARI_NVFREQ_FEEDBACK 66UL +#define TEGRA_ARI_CLUSTER_ATCLKEN 67UL +/* + * Require CCPLEX, CLUSTER and CORE LAB Lock -- obtained by MTM from ARI + * range from 96 - 127 + */ +#define TEGRA_ARI_CCPLEX_CACHE_CONTROL 96UL +#define TEGRA_ARI_CCPLEX_CACHE_CLEAN 97UL +/* UNDEFINED 98 */ +#define TEGRA_ARI_CCPLEX_LATIC_ON 99UL +#define TEGRA_ARI_UPDATE_CROSSOVER 100UL +#define TEGRA_ARI_VALIDATE_ONLINE_IST 101UL +#define TEGRA_ARI_CCPLEX_SHUTDOWN 102UL +/* UNDEFINED 103 */ +#define TEGRA_ARI_CSTATE_INFO 104UL +#define TEGRA_ARI_IS_SC7_ALLOWED 105UL +/* UNDEFINED 106 */ +/* UNDEFINED 107 */ +#define TEGRA_ARI_SECURITY_CONFIG 108UL +#define TEGRA_ARI_UPDATE_CCPLEX_CARVEOUTS 109UL +#define TEGRA_ARI_DDA_CONTROL 110UL +#define TEGRA_ARI_PERFMON 111UL +#define TEGRA_ARI_DEBUG_CONFIG 112UL +#define TEGRA_ARI_CCPLEX_ERROR_RECOVERY_RESET 114UL + +/* EVENT MASKS */ +#define TEGRA_ARI_EVENT_CORE_OFF_MASK (1UL<<0) +#define TEGRA_ARI_EVENT_CORE_OFF_EMU_MASK (1UL<<1) +#define TEGRA_ARI_EVENT_WAKE_REQUEST_MASK (1UL<<2) + +//////////////////////////////////////////////////// +// +// Defines for ARI Parameters +// +// TEGRA_ARI_VERSION NONE +// TEGRA_ARI_ECHO NONE +// TEGRA_ARI_NUM_CORES NONE +// TEGRA_ARI_CLUSTER_CONFIG +#define TEGRA_ARI_CLUSTER0_CONFIG_FLOORSWEPT 0UL +#define TEGRA_ARI_CLUSTER0_CONFIG_SPLIT 1UL +#define TEGRA_ARI_CLUSTER0_CONFIG_HYBRID 2UL +#define TEGRA_ARI_CLUSTER0_CONFIG_LOCK 3UL +#define TEGRA_ARI_CLUSTER1_CONFIG_FLOORSWEPT (0UL<<2) +#define TEGRA_ARI_CLUSTER1_CONFIG_SPLIT (1UL<<2) +#define TEGRA_ARI_CLUSTER1_CONFIG_HYBRID (2UL<<2) +#define TEGRA_ARI_CLUSTER1_CONFIG_LOCK (3UL<<2) +#define TEGRA_ARI_CLUSTER2_CONFIG_FLOORSWEPT (0UL<<4) +#define TEGRA_ARI_CLUSTER2_CONFIG_SPLIT (1UL<<4) +#define TEGRA_ARI_CLUSTER2_CONFIG_HYBRID (2UL<<4) +#define TEGRA_ARI_CLUSTER2_CONFIG_LOCK (3UL<<4) +// TEGRA_ARI_CSTATE_STAT_QUERY +#define TEGRA_ARI_STAT_QUERY_SC7_ENTRIES 1UL +#define TEGRA_ARI_STAT_QUERY_CC7_ENTRIES 6UL +#define TEGRA_ARI_STAT_QUERY_C7_ENTRIES 14UL +#define TEGRA_ARI_STAT_QUERY_SC7_ENTRY_TIME_SUM 60UL +#define TEGRA_ARI_STAT_QUERY_CC7_ENTRY_TIME_SUM 61UL +#define TEGRA_ARI_STAT_QUERY_C7_ENTRY_TIME_SUM 64UL +#define TEGRA_ARI_STAT_QUERY_SC7_EXIT_TIME_SUM 70UL +#define TEGRA_ARI_STAT_QUERY_CC7_EXIT_TIME_SUM 71UL +#define TEGRA_ARI_STAT_QUERY_C7_EXIT_TIME_SUM 74UL + +// TEGRA_ARI_CORE_DEBUG_RECOVERY +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RCWR_NONE 0UL +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RCWR_WARM_RESET (1UL<<4) + +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RESULT_SUCCESS 0UL +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RESULT_DENIED 1UL +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RESULT_BUSY 2UL +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RESULT_OFF 3UL + +// TEGRA_ARI_DSU_DEBUG_RECOVERY +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RCWR_NONE 0UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RCWR_WARM_RESET (1UL<<2) + +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RESULT_SUCCESS 0UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RESULT_DENIED 1UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RESULT_BUSY 2UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RESULT_OFF 3UL + +// TEGRA_ARI_CLUSTER_WARM_RESET NONE +// TEGRA_ARI_ONLINE_CORE NONE +// TEGRA_ARI_ENTER_CSTATE +#define TEGRA_ARI_ENTER_CSTATE_WAKE_TIME_NO_WAKE (0xffffffffUL) + +// TEGRA_ARI_TRIGGER_ONLINE_IST +#define TEGRA_ARI_TRIGGER_ONLINE_IST_SELECT_PLL_NAFLL 0UL +#define TEGRA_ARI_TRIGGER_ONLINE_IST_SELECT_PLL_PLLX1 1UL + +// TEGRA_ARI_ONLINE_IST_STATUS +#define TEGRA_ARI_ONLINE_IST_STATUS_RESET 0UL +#define TEGRA_ARI_ONLINE_IST_STATUS_TEST_PASS 1UL +#define TEGRA_ARI_ONLINE_IST_STATUS_TEST_FAIL 2UL + +// TEGRA_ARI_ONLINE_IST_DMA_STATUS +#define TEGRA_ARI_ONLINE_IST_DMA_STATUS_PENDING_TRANSACTIONS_FALSE 0UL +#define TEGRA_ARI_ONLINE_IST_DMA_STATUS_PENDING_TRANSACTIONS_TRUE 1UL + +// TEGRA_ARI_NVFREQ_REQ +#define TEGRA_ARI_NVFREQ_REQ_CORE_NDIV_WRITE_EN (1UL<<15) +#define TEGRA_ARI_NVFREQ_REQ_DSU_NDIV_WRITE_EN (1UL<<15) + +// TEGRA_ARI_NVFREQ_FEEDBACK NONE +// TEGRA_ARI_CLUSTER_ATCLKEN +#define TEGRA_ARI_CLUSTER_ATCLKEN_DISABLE 0UL +#define TEGRA_ARI_CLUSTER_ATCLKEN_ENABLE 1UL +#define TEGRA_ARI_CLUSTER_ATCLKEN_RESULT_SUCCESS 0UL +#define TEGRA_ARI_CLUSTER_ATCLKEN_RESULT_FAILURE 1UL +#define TEGRA_ARI_CLUSTER_ATCLKEN_RESULT_NONE 2UL + +// TEGRA_ARI_CCPLEX_CACHE_CONTROL +#define TEGRA_ARI_CCPLEX_CACHE_CONTROL_WRITE_EN (1UL<<15) + +// TEGRA_ARI_CCPLEX_CACHE_CLEAN +#define TEGRA_ARI_CCPLEX_CACHE_CLEAN_NO_INVAL 0UL +#define TEGRA_ARI_CCPLEX_CACHE_CLEAN_INVAL 1UL + +// TEGRA_ARI_CCPLEX_LATIC_ON NONE +// TEGRA_ARI_UPDATE_CROSSOVER +#define TEGRA_ARI_CROSSOVER_C7_LOWER_BOUND 0UL +#define TEGRA_ARI_CROSSOVER_CC7_LOWER_BOUND 1UL +// TEGRA_ARI_VALIDATE_ONLINE_IST +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER0_SUCCESS 0UL +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER0_INELIGIBLE 1UL +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER0_FAILED 2UL +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER1_SUCCESS (0UL<<2) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER1_INELIGIBLE (1UL<<2) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER1_FAILED (2UL<<2) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER2_SUCCESS (0UL<<4) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER2_INELIGIBLE (1UL<<4) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER2_FAILED (2UL<<4) +// TEGRA_ARI_CCPLEX_SHUTDOWN +#define TEGRA_ARI_CCPLEX_SHUTDOWN_POWER_OFF 0UL +#define TEGRA_ARI_CCPLEX_SHUTDOWN_REBOOT 1UL + +// TEGRA_ARI_CSTATE_INFO +#define TEGRA_ARI_CSTATE_INFO_CLUSTER_CC1 1UL +#define TEGRA_ARI_CSTATE_INFO_CLUSTER_CC7 7UL +#define TEGRA_ARI_CSTATE_INFO_SYSTEM_SC0 (0UL<<16) +#define TEGRA_ARI_CSTATE_INFO_SYSTEM_SC7 (7UL<<16) +#define TEGRA_ARI_CSTATE_INFO_UPDATE_CLUSTER (1UL<<7) +#define TEGRA_ARI_CSTATE_INFO_UPDATE_SYSTEM (1UL<<23) +#define TEGRA_ARI_CSTATE_INFO_UPDATE_WAKE_MASK (1UL<<31) + +// TEGRA_ARI_IS_SC7_ALLOWED +#define TEGRA_ARI_IS_SC7_ALLOWED_FALSE 0UL +#define TEGRA_ARI_IS_SC7_ALLOWED_TRUE 1UL + +// TEGRA_ARI_SECURITY_CONFIG +#define TEGRA_ARI_SECURITY_CONFIG_STRICT_EN_DISABLE 0UL +#define TEGRA_ARI_SECURITY_CONFIG_STRICT_EN_ENABLE 1UL +#define TEGRA_ARI_SECURITY_CONFIG_STRICT_LOCK (1UL<<1) +#define TEGRA_ARI_SECURITY_CONFIG_WRITE_EN (1UL<<2) + +// TEGRA_ARI_UPDATE_CCPLEX_CARVEOUTS +#define TEGRA_ARI_CARVEOUT_ALL 0UL +#define TEGRA_ARI_CARVEOUT_GSC_NONE 0xFFFFUL +#define TEGRA_ARI_CARVEOUT_GSC_IST 31UL +#define TEGRA_ARI_CARVEOUT_SBS (1UL<<16) +#define TEGRA_ARI_CARVEOUT_VPR (1UL<<17) +// TEGRA_ARI_DDA_CONTROL +#define DDA_SNOC_MCF 0U +#define DDA_MCF_ORD1 1U +#define DDA_MCF_ORD2 2U +#define DDA_MCF_ORD3 3U +#define DDA_MCF_ISO 4U +#define DDA_MCF_SISO 5U +#define DDA_MCF_NISO 6U +#define DDA_MCF_NISO_REMOTE 7U +#define DDA_L3CTRL_ISO 8U +#define DDA_L3CTRL_SISO 9U +#define DDA_L3CTRL_NISO 10U +#define DDA_L3CTRL_NISO_REMOTE 11U +#define DDA_L3CTRL_L3FILL 12U +#define DDA_L3CTRL_L3WR 13U +#define DDA_L3CTRL_RSP_L3RD_DMA 14U +#define DDA_L3CTRL_RSP_MCFRD_DMA 15U +#define DDA_L3CTRL_GLOBAL 16U +#define DDA_L3CTRL_LL 17U +#define DDA_L3CTRL_L3D 18U +#define DDA_L3CTRL_FCM_RD 19U +#define DDA_L3CTRL_FCM_WR 20U +#define DDA_SNOC_GLOBAL_CTRL 21U +#define DDA_SNOC_CLIENT_REQ_CTRL 22U +#define DDA_SNOC_CLIENT_REPLENTISH_CTRL 23U + +#define TEGRA_ARI_DDA_CONTROL_DDA_REG_WRITE_EN (1UL<<15) + +// TEGRA_ARI_PERFMON NONE +// TEGRA_ARI_DEBUG_CONFIG +#define TEGRA_ARI_DEBUG_CONFIG_NOTIFY_ON_DCLS_FAULT_CP0 (0UL<<2) +#define TEGRA_ARI_DEBUG_CONFIG_NOTIFY_ON_DCLS_FAULT_CP1 (1UL<<2) +#define TEGRA_ARI_DEBUG_CONFIG_NOTIFY_ON_DCLS_FAULT_CP0CP1 (2UL<<2) +#define TEGRA_ARI_DEBUG_CONFIG_NOTIFY_ON_DCLS_FAULT_DISABLE (3UL<<2) + +// TEGRA_ARI_CCPLEX_ERROR_RECOVERY_RESET NONE +// Primary ERROR CODES - valid in RSP_LO +#define TEGRA_ARI_ERROR_SW 1UL +// not defined 2UL +// not defined 3UL +// not defined 4UL +// not defined 5UL +// not defined 6UL +#define TEGRA_ARI_ERROR_RESERVED 7UL +#define TEGRA_ARI_ERROR_OUT_OF_RANGE 8UL +#define TEGRA_ARI_ERROR_RESTRICTED 9UL +#define TEGRA_ARI_ERROR_NONSECURE 10UL +// Secondary ERROR CODES - valid in RSP_HI +// none currently defined +#endif /* T234_ARI_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c new file mode 100644 index 0000000..12007f4 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * Custom macros + *****************************************************************************/ +#define ID_AFR0_EL1_CACHE_OPS_SHIFT 12U +#define ID_AFR0_EL1_CACHE_OPS_MASK 0xFU + +#define CORE_WARM_RESET_SHIFT 4U +#define CLUSTER_WARM_RESET_SHIFT 2U + +#define CLUSTER_CONFIG_MASK 0x3FU + +/****************************************************************************** + * Globals + *****************************************************************************/ +static uint32_t cluster_bitmap = U(0xDEADF00D); + +/****************************************************************************** + * Register offsets for ARI request/results + *****************************************************************************/ +#define ARI_REQUEST 0x0U +#define ARI_REQUEST_EVENT_MASK 0x8U +#define ARI_STATUS 0x10U +#define ARI_REQUEST_DATA_LO 0x18U +#define ARI_REQUEST_DATA_HI 0x20U +#define ARI_RESPONSE_DATA_LO 0x28U +#define ARI_RESPONSE_DATA_HI 0x30U + +/* Status values for the current request */ +#define ARI_REQ_PENDING 1U +#define ARI_REQ_ONGOING 2U +/* Request status */ +#define ARI_REQ_STATUS_MASK 0xFCU +#define ARI_REQ_NO_ERROR 0U +#define ARI_REQ_REQUEST_KILLED 1U +#define ARI_REQ_NS_ERROR 2U +#define ARI_REQ_EXECUTION_ERROR 0x3FU +/* Request control bits */ +#define ARI_REQUEST_VALID_BIT (1U << 8) +#define ARI_REQUEST_KILL_BIT (1U << 9) +#define ARI_REQUEST_NS_BIT (1U << 31) + +/* default timeout (us) to wait for ARI completion */ +#define ARI_MAX_RETRY_COUNT U(2000000) + +/****************************************************************************** + * ARI helper functions + *****************************************************************************/ +static inline uint32_t ari_read_32(uint32_t ari_base, uint32_t reg) +{ + return mmio_read_32((uint64_t)ari_base + (uint64_t)reg); +} + +static inline void ari_write_32(uint32_t ari_base, uint32_t val, uint32_t reg) +{ + mmio_write_32((uint64_t)ari_base + (uint64_t)reg, val); +} + +static inline uint32_t ari_get_response_low(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_RESPONSE_DATA_LO); +} + +static inline uint32_t ari_get_response_high(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_RESPONSE_DATA_HI); +} + +static inline void ari_clobber_response(uint32_t ari_base) +{ + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO); + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI); +} + +static void ari_request_send_command(uint32_t ari_base, uint32_t evt_mask, + uint32_t req, uint32_t lo, uint32_t hi) +{ + ari_write_32(ari_base, lo, ARI_REQUEST_DATA_LO); + ari_write_32(ari_base, hi, ARI_REQUEST_DATA_HI); + ari_write_32(ari_base, evt_mask, ARI_REQUEST_EVENT_MASK); + ari_write_32(ari_base, req | ARI_REQUEST_VALID_BIT, ARI_REQUEST); +} + +static uint32_t ari_request_wait(uint32_t ari_base, uint32_t evt_mask, + uint32_t req, uint32_t lo, uint32_t hi) +{ + uint32_t retries = ARI_MAX_RETRY_COUNT; + uint32_t status; + uint32_t ret = 0U; + + /* + * For each ARI command, the registers that are not used are listed + * as "Must be set to 0", MCE firmware enforce a check for it. + * Clear response lo/hi data before sending out command. + */ + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO); + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI); + + /* program the request, event_mask, hi and lo registers */ + ari_request_send_command(ari_base, evt_mask, req, lo, hi); + + /* + * For commands that have an event trigger, we should stop + * ARI_STATUS polling, since MCE is waiting for SW to trigger + * the event. + */ + /* For shutdown/reboot commands, use function ari_request_send_command() */ + if (evt_mask == 0U) { + /* + * Wait for the command response for not more than the timeout + */ + while (retries != 0U) { + /* read the command status */ + status = ari_read_32(ari_base, ARI_STATUS); + if ((status & (ARI_REQ_ONGOING | ARI_REQ_PENDING | + ARI_REQ_STATUS_MASK)) == 0U) { + break; + } + + if ((status & ARI_REQ_STATUS_MASK) != 0U) { + ret = ((status & ARI_REQ_STATUS_MASK) >> 2); + ERROR("ARI request get error: 0x%x\n", ret); + return ret; + } + + /* delay 1 us */ + udelay(1); + + /* decrement the retry count */ + retries--; + } + + /* assert if the command timed out */ + if (retries == 0U) { + ERROR("ARI request timed out: req %d\n", req); + assert(retries != 0U); + } + } + + return 0; +} + +/* + * Reports the major and minor version of this interface. + * ari_base: ari base for current CPU. + * version: [63:32] Major version, [31:0] Minor version. + */ +uint64_t ari_get_version(uint32_t ari_base) +{ + uint64_t ret; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_VERSION, 0, 0); + + if (ret == 0U) { + ret = ari_get_response_low(ari_base); + ret |= ((uint64_t)ari_get_response_high(ari_base) << 32); + } else { + ERROR("ARI request %s fail!\n", __func__); + } + + return ret; +} + +/* + * return a bit-vector indicating which cores on the ccplex are enabled or + * non-floorswept. + * ari_base: ari base for current CPU. + * num_cores: [15:0] bit-vector indicating which cores on the ccplex are enabled. + */ +uint32_t ari_num_cores(uint32_t ari_base) +{ + uint32_t ret; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_NUM_CORES, 0, 0); + + if (ret == 0U) { + ret = ari_get_response_low(ari_base); + } else { + ERROR("ARI request %s fail!\n", __func__); + } + + return (ret & 0xFFFFU); +} + +/* + * Return a bit-vector indicating which clusters on the ccplex are enabled or + * non-floorswept. + * + * ari_base: ari base for current CPU. + * + * Return bit-vector indicating which clusters on the ccplex are enabled. + */ +uint32_t ari_cluster_present_map(uint32_t ari_base) +{ + uint32_t ret; + + if (cluster_bitmap != U(0xDEADF00D)) { + return cluster_bitmap; + } + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_CLUSTER_CONFIG, 0U, 0U); + if (ret == 0U) { + cluster_bitmap = ari_get_response_low(ari_base); + cluster_bitmap &= (CLUSTER_CONFIG_MASK); + } else { + ERROR("ARI request %s failed\n", __func__); + } + + return cluster_bitmap; +} + +#if DEBUG +/* + * MCE SW will initiate the warm reset sequence to Warm Reset the requested + * cluster. This ARI call is intended to be used in conjunction with + * TEGRA_ARI_CORE_DEBUG_RECOVERY and TEGRA_ARI_DSU_DEBUG_RECOVERY to allow + * the debugger to enable the DBGRM mode for the entire cluster. + * ari_base: ari base for current CPU. + * cluster_id: Cluster ID for the target cluster. Valid values are 0-2. + * ret: error status, 0 indicate no error. + */ +static uint32_t ari_cluster_warm_reset(uint32_t ari_base, uint32_t cluster_id) +{ + uint32_t ret; + + assert(cluster_id < PLATFORM_CLUSTER_COUNT); + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_CLUSTER_WARM_RESET, + cluster_id, 0); + + if (ret != 0U) { + ERROR("ARI request %s fail!\n", __func__); + if (ret == ARI_REQ_EXECUTION_ERROR) { + ret = ari_get_response_low(ari_base); + } + } + + return ret; +} + +/* + * attempt to transition the specified core into the DEBUG_RECOVERY Mode (DBGRM) + * ari_base: ari base for current CPU. + * core_id: Core ID of Target Core to put into DBRGM + * core_warm_reset: Request Cluster Warm Reset + * 0 – No Cluster Warm Reset + * 1 – Warm Reset Cluster after successful transition of core to DBGRM + * ret: [1:0] + * 0 – Success. P-Channel returned ACCEPT. + * 1 – Deny. P-Channel returned Deny. + * 2 – Busy. P-Channel for core is currently in a handshake. + * 3 – Off. DSU is unpowered and cannot accept P-Channel requests. + * if the ARI Request register Status field has been set to 0x3f, + * the ret value will be + * ret: [31:0] + * error code indicate information about the error + */ +uint32_t ari_core_debug_recovery(uint32_t ari_base, uint32_t core_id, + bool core_warm_reset) +{ + uint32_t request, ret; + + assert(core_id < + (PLATFORM_CLUSTER_COUNT * PLATFORM_MAX_CPUS_PER_CLUSTER)); + + request = ((uint32_t)core_warm_reset << CORE_WARM_RESET_SHIFT) + | core_id; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_CORE_DEBUG_RECOVERY, + request, 0); + + if (ret == 0U) { + ret = ari_get_response_low(ari_base); + if (core_warm_reset && (ret == 0)) { + ret = ari_cluster_warm_reset(ari_base, + (core_id / PLATFORM_MAX_CPUS_PER_CLUSTER)); + } + } else { + ERROR("ARI request %s fail!\n", __func__); + if (ret == ARI_REQ_EXECUTION_ERROR) { + ret = ari_get_response_low(ari_base); + } + } + + return ret; +} + +/* + * attempt to transition the specified DSU into the DEBUG_RECOVERY Mode (DBGRM). + * ari_base: ari base for current CPU. + * cluster_id: Cluster ID for the target DSU. Valid values are 0-2. + * cluster_warm_reset: Request Cluster Warm Reset + * 0 – No Cluster Warm Reset + * 1 – Warm Reset Cluster after successful transition of core to DBGRM + * ret: [1:0] + * 0 – Success. P-Channel returned ACCEPT. + * 1 – Deny. P-Channel returned Deny. + * 2 – Busy. P-Channel for core is currently in a handshake. + * 3 – Off. DSU is unpowered and cannot accept P-Channel requests. + * if the ARI Request register Status field has been set to 0x3f, + * the ret value will be + * ret: [31:0] + * error code indicate information about the error + */ +uint32_t ari_dsu_debug_recovery(uint32_t ari_base, uint32_t cluster_id, + bool cluster_warm_reset) +{ + uint32_t request, ret; + + assert(cluster_id < PLATFORM_CLUSTER_COUNT); + + request = ((uint32_t)cluster_warm_reset << CLUSTER_WARM_RESET_SHIFT) + | cluster_id; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_DSU_DEBUG_RECOVERY, + request, 0); + + if (ret == 0U) { + ret = ari_get_response_low(ari_base); + if (cluster_warm_reset && (ret == 0)) { + ret = ari_cluster_warm_reset(ari_base, cluster_id); + } + } else { + ERROR("ARI request %s fail!\n", __func__); + if (ret == ARI_REQ_EXECUTION_ERROR) { + ret = ari_get_response_low(ari_base); + } + } + + return ret; +} + +/* + * MCE SW will enable the CCLA for internal debugging. This will cause an MCE + * assert if used on a production fused part. + * ari_base: ari base for current CPU. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_ccplex_latic_on(uint32_t ari_base) +{ + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, TEGRA_ARI_CCPLEX_LATIC_ON, 0, 0); + +} +#endif + +/* + * Initiate an SCF level Cache Clean + * ari_base: ari base for current CPU. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_ccplex_cache_clean(uint32_t ari_base) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, TEGRA_ARI_CCPLEX_CACHE_CLEAN, + TEGRA_ARI_CCPLEX_CACHE_CLEAN_NO_INVAL, 0); +} + +/* + * Initiate an SCF level Cache invalidate and Clean + * ari_base: ari base for current CPU. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_ccplex_cache_clean_and_invalidate(uint32_t ari_base) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, TEGRA_ARI_CCPLEX_CACHE_CLEAN, + TEGRA_ARI_CCPLEX_CACHE_CLEAN_INVAL, 0); +} + +/* + * This function will request for the BPMP to power down the CCPLEX. + * This can be used to either reboot or power off the system. + * ari_base: ari base for current CPU. + * type: 0 — Power Off SOC + * 1 — Reboot SOC + */ +static void ari_ccplex_shutdown(uint32_t ari_base, uint32_t type) +{ + /* sanity check for type */ + assert(type <= TEGRA_ARI_CCPLEX_SHUTDOWN_REBOOT); + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ari_request_send_command(ari_base, 0U, TEGRA_ARI_CCPLEX_SHUTDOWN, + type, 0); +} + +/* + * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and + * SYSTEM_CSTATE values. + * ari_base: ari base for current CPU. + * cluster: cluster CSTATE + * 1 — Auto-CC1 (reset value) + * 7 — CC7 + * update_cluster: 0 — Ignore value in Cluster CSTATE field + * 1 — Value in Cluster CSTATE field is valid and + * should be updated + * system: system CSTATE + * 0 << 16 — SC0 (reset value) + * 7 << 16 — SC7 + * update_system: 0 — Ignore value in system CSTATE field + * 1 — Value in system CSTATE field is valid and + * should be updated + * wake_mask: Mask of events to wake from low power states. + * update_wake_mask: 0 — Ignore value in Wake Mask field + * 1 — Value in Wake Mask Field is valid and should be updated + * ret: error status, 0 indicate no error. + */ +uint32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, + uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask) +{ + uint32_t val = 0; + + /* update CLUSTER_CSTATE? */ + if (cluster != 0U) { + val |= (cluster & CLUSTER_CSTATE_MASK) | + TEGRA_ARI_CSTATE_INFO_UPDATE_CLUSTER; + } + + /* update SYSTEM_CSTATE? */ + if (system != 0U) { + val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + TEGRA_ARI_CSTATE_INFO_UPDATE_SYSTEM ; + } + + /* update wake mask value? */ + if (update_wake_mask != 0U) { + val |= TEGRA_ARI_CSTATE_INFO_UPDATE_WAKE_MASK; + } + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* set the updated cstate info */ + return ari_request_wait(ari_base, 0U, TEGRA_ARI_CSTATE_INFO, + val, wake_mask); +} + +/* + * Return a non-zero value if the CCPLEX is able to enter SC7 + * ari_base: ari base for current CPU. + * result: 0 — System is not allowed to enter SC7 and may reenter running state. + * 1 – System may enter SC7 and is committed to proceed to enter SC7. + */ +bool ari_is_sc7_allowed(uint32_t ari_base) +{ + bool result; + uint32_t ret; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* issue command to check if SC7 is allowed */ + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_IS_SC7_ALLOWED, 0, 0); + if (ret != 0) { + ERROR("%s: failed (%d)\n", __func__, ret); + result = false; + } else { + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + result = (bool)ari_get_response_low(ari_base); + } + + return result; +} + +/* + * Wake an offlined logical core. Note that a core is offlined by entering + * a C-state where the WAKE_MASK is all 0. + * ari_base: ari base for current CPU. + * core: MPIDR Linear Core ID of the core to bring online. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_online_core(uint32_t ari_base, uint32_t core) +{ + assert(core < + (PLATFORM_CLUSTER_COUNT * PLATFORM_MAX_CPUS_PER_CLUSTER)); + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* get a core online */ + return ari_request_wait(ari_base, 0U, TEGRA_ARI_ONLINE_CORE, core, 0U); +} + +/* + * MC GSC (General Security Carveout) register values are expected to be + * changed by TrustZone ARM code after boot. + * ari_base: ari base for current CPU. + * gsc_idx: The enumerated GSC value to be copied from the SOC into the CCPLEX + * !! only support GSC_VPR now !! + * ret: error status, 0 indicate no error. + */ +int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx) +{ + /* sanity check GSC ID */ + if (gsc_idx != TEGRA_ARI_CARVEOUT_VPR) { + return -EINVAL; + } + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* + * The MCE code will read the GSC carveout value, corrseponding + * to the ID, from the MC registers and update the internal GSC + * registers of the CCPLEX. + */ + return ari_request_wait(ari_base, 0U, + TEGRA_ARI_UPDATE_CCPLEX_CARVEOUTS, gsc_idx, 0U); +} + + +/* + * Set the power state for a core + * ari_base: ari base for current CPU. + * wake_time: Time in TSC ticks until the core is expected to get a wake event. + * 0 indicates the core is expected to wake immediately. + * 0xffffffff indicates that the core is not expected + * to get a wake event. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_enter_cstate(uint32_t ari_base, uint32_t wake_time) +{ +/* + * should have C1 state according CCPLEX_Power_Management_GFD + * but only wake_time as input parameter in MCE_ISS. + */ + + /* time (TSC ticks) until the core is expected to get a wake event */ + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* send the command and do not wait for the ARI to complete*/ + ari_request_send_command(ari_base, TEGRA_ARI_EVENT_CORE_OFF_MASK, + TEGRA_ARI_ENTER_CSTATE, wake_time, 0); + + return 0; +} + +#if ENABLE_STRICT_CHECKING_MODE +/* + * Enable strict checking mode and verify the result. + * ari_base: ari base for current CPU. + */ +void ari_enable_strict_checking_mode(uint32_t ari_base) +{ + uint32_t params; + uint32_t ret = 0U; + + /* Clean the previous response state */ + ari_clobber_response(ari_base); + + /* Enable the strict checking mode + * Lock the strict enable bit. + * Once the bit is set, write to strict_en bit will be ignored + */ + params = TEGRA_ARI_SECURITY_CONFIG_STRICT_EN_ENABLE + | TEGRA_ARI_SECURITY_CONFIG_STRICT_LOCK + | TEGRA_ARI_SECURITY_CONFIG_WRITE_EN; + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_SECURITY_CONFIG, + params, 0); + if (ret == 0) { + params = ari_get_response_low(ari_base); + } + + assert(params == (TEGRA_ARI_SECURITY_CONFIG_STRICT_EN_ENABLE + | TEGRA_ARI_SECURITY_CONFIG_STRICT_LOCK)); +} +#endif + +/* + * Request a reboot + */ +void ari_system_reboot(uint32_t ari_base) +{ + ari_ccplex_shutdown(ari_base, TEGRA_ARI_CCPLEX_SHUTDOWN_REBOOT); +} + +/* + * Request a shutdown + */ +void ari_system_shutdown(uint32_t ari_base) +{ + ari_ccplex_shutdown(ari_base, TEGRA_ARI_CCPLEX_SHUTDOWN_POWER_OFF); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c new file mode 100644 index 0000000..11236dd --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2021-2022, NVIDIA 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 + +/* Global variable to save the cluster bitmap */ +static uint32_t cluster_present_bitmap = 0xDEADFEED; + +/* Global variable to save the core present bitmap */ +static uint32_t core_present_bitmap = 0xDEADFEED; + +/* Global variable to save the unsupported platform list */ +static uint32_t tegra_unsupported_platform_bitmap = U(0xDEADBEEF); + +/* Table to hold the per-CPU ARI base address and function handlers */ +static uint32_t mce_cfg_table[PLATFORM_CLUSTER_COUNT][PLATFORM_MAX_CPUS_PER_CLUSTER] = { + { + /* cluster 0 */ + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET), + }, + { + /* cluster 1 */ + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_6_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_7_OFFSET), + }, + { + /* cluster 2 */ + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_8_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_9_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_10_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_11_OFFSET), + } + +}; + +static uint32_t mce_get_curr_cpu_ari_base(void) +{ + u_register_t mpidr = read_mpidr(); + u_register_t cpu_id, cluster_id; + + cluster_id = (mpidr >> (u_register_t)MPIDR_AFF2_SHIFT) & + (u_register_t)MPIDR_AFFLVL_MASK; + + assert(cluster_id <= PLATFORM_CLUSTER_COUNT); + + cpu_id = (mpidr >> (u_register_t)MPIDR_AFF1_SHIFT) & + (u_register_t)MPIDR_AFFLVL_MASK; + + assert(cpu_id <= PLATFORM_MAX_CPUS_PER_CLUSTER); + + return mce_cfg_table[cluster_id][cpu_id]; +} + +/* Handler to check if MCE firmware is supported */ +static bool mce_firmware_not_supported(void) +{ + /* Check if this platform is supported */ + if (tegra_unsupported_platform_bitmap != U(0xDEADBEEF)) { + return !(tegra_unsupported_platform_bitmap == 0U); + } + + /* + * If the current platform is one of the unsupported ones, + * add it to the bitmap + */ + tegra_unsupported_platform_bitmap = tegra_platform_is_linsim() | + (tegra_platform_is_virt_dev_kit() << 1U) | + (tegra_platform_is_vsp() << 2U); + + return !(tegra_unsupported_platform_bitmap == 0U); +} + +/****************************************************************************** + * Common handler for all MCE commands + *****************************************************************************/ +int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1, + uint64_t arg2) +{ + int32_t ret = 0; + uint32_t cpu_ari_base; + + /* get the CPU's ARI base address */ + cpu_ari_base = mce_get_curr_cpu_ari_base(); + + switch (cmd) { + case (uint64_t)MCE_CMD_ENTER_CSTATE: + ret = ari_enter_cstate(cpu_ari_base, (uint32_t)arg0); + if (ret < 0) { + ERROR("%s: enter_cstate failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_IS_SC7_ALLOWED: + ret = ari_is_sc7_allowed((uint32_t)cpu_ari_base); + if (ret < 0) { + ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_ONLINE_CORE: + ret = ari_online_core(cpu_ari_base, (uint32_t)arg0); + if (ret < 0) { + ERROR("%s: online_core failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE: + ret = ari_ccplex_cache_clean_and_invalidate(cpu_ari_base); + if (ret < 0) { + ERROR("%s: flush cache failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_ROC_CLEAN_CACHE: + ret = ari_ccplex_cache_clean(cpu_ari_base); + if (ret < 0) { + ERROR("%s: clean cache failed(%d)\n", __func__, ret); + } + + break; + +#if ENABLE_CHIP_VERIFICATION_HARNESS + case (uint64_t)MCE_CMD_ENABLE_LATIC: + /* + * This call is not for production use. The constant value, + * 0xFFFF0000, is specific to allowing for enabling LATIC on + * pre-production parts for the chip verification harness. + * + * Enabling LATIC allows S/W to read the MINI ISPs in the + * CCPLEX. The ISMs are used for various measurements relevant + * to particular locations in the Silicon. They are small + * counters which can be polled to determine how fast a + * particular location in the Silicon is. + */ + ari_ccplex_latic_on(cpu_ari_base); + + break; +#endif + + default: + ERROR("unknown MCE command (%" PRIu64 ")\n", cmd); + ret = -EINVAL; + break; + } + + return ret; +} + +/****************************************************************************** + * Handler to update carveout values for Video Memory Carveout region + *****************************************************************************/ +int32_t mce_update_gsc_videomem(void) +{ + int32_t ret = 0; + + /* + * MCE firmware is not running on simulation platforms. + */ + if (mce_firmware_not_supported()) { + ret = -EINVAL; + } else { + ret = ari_update_ccplex_gsc(mce_get_curr_cpu_ari_base(), + TEGRA_ARI_CARVEOUT_VPR); + } + + return ret; +} + +/****************************************************************************** + * Handler to update carveout values for TZDRAM aperture + *****************************************************************************/ +int32_t mce_update_gsc_tzdram(void) +{ + /* This function is not required for T23x. + * Return 0 to avoid compile error. + */ + return 0; +} + +/****************************************************************************** + * Handler to issue the UPDATE_CSTATE_INFO request + *****************************************************************************/ +void mce_update_cstate_info(const mce_cstate_info_t *cstate) +{ + /* issue the UPDATE_CSTATE_INFO request */ + ari_update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster, + cstate->system, cstate->wake_mask, cstate->update_wake_mask); +} + +/****************************************************************************** + * Handler to read the MCE firmware version and check if it is compatible + * with interface header the BL3-1 was compiled against + *****************************************************************************/ +void mce_verify_firmware_version(void) +{ + uint64_t version; + uint32_t major, minor; + + /* + * MCE firmware is not running on simulation platforms. + */ + if (mce_firmware_not_supported()) { + return; + } + + /* + * Read the MCE firmware version and extract the major and minor + * version fields + */ + version = ari_get_version(mce_get_curr_cpu_ari_base()); + major = (uint32_t)version; + minor = (uint32_t)(version >> 32); + + INFO("MCE Version - HW=%d:%d, SW=%ld:%ld\n", major, minor, + TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR); + + /* + * Verify that the MCE firmware version and the interface header + * match + */ + if (major != (uint32_t)TEGRA_ARI_VERSION_MAJOR) { + ERROR("MCE major version mismatch\n"); + panic(); + } + + if (minor < (uint32_t)TEGRA_ARI_VERSION_MINOR) { + ERROR("MCE minor version mismatch\n"); + panic(); + } +} + +/****************************************************************************** + * Handler to issue SCF flush - Clean and invalidate caches + *****************************************************************************/ +void mce_clean_and_invalidate_caches(void) +{ + int32_t ret = 0; + + /* + * MCE firmware is not running on simulation platforms. + */ + if (mce_firmware_not_supported()) { + return; + } + + ret = ari_ccplex_cache_clean_and_invalidate(mce_get_curr_cpu_ari_base()); + if (ret < 0) { + ERROR("%s: flush cache_trbits failed(%d)\n", __func__, + ret); + } +} + +#if ENABLE_STRICT_CHECKING_MODE +/****************************************************************************** + * Handler to enable the strict checking mode + *****************************************************************************/ +void mce_enable_strict_checking(void) +{ + uint64_t sctlr = read_sctlr_el3(); + int32_t ret = 0; + + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + /* + * Step1: TZ-DRAM and TZRAM should be setup before the MMU is + * enabled. + * + * The common code makes sure that TZDRAM/TZRAM are already + * enabled before calling into this handler. If this is not the + * case, the following sequence must be executed before moving + * on to step 2. + * + * tlbialle1is(); + * tlbialle3is(); + * dsbsy(); + * + */ + if ((sctlr & (uint64_t)SCTLR_M_BIT) == (uint64_t)SCTLR_M_BIT) { + tlbialle1is(); + tlbialle3is(); + dsbsy(); + } + + /* + * Step2: SCF flush - Clean and invalidate caches and clear the + * TR-bits + */ + ret = ari_ccplex_cache_clean_and_invalidate(mce_get_curr_cpu_ari_base()); + if (ret < 0) { + ERROR("%s: flush cache_trbits failed(%d)\n", __func__, + ret); + return; + } + + /* + * Step3: Issue the SECURITY_CONFIG request to MCE to enable + * strict checking mode. + */ + ari_enable_strict_checking_mode(mce_get_curr_cpu_ari_base()); + } +} +#endif + +#if DEBUG +/* + * attempt to transition the specified core into the DEBUG_RECOVERY Mode (DBGRM) + * core_id: Core ID of Target Core to put into DBRGM + * ret: [1:0] + * 0 – Success. P-Channel returned ACCEPT. + * 1 – Deny. P-Channel returned Deny. + * 2 – Busy. P-Channel for core is currently in a handshake. + * 3 – Off. DSU is unpowered and cannot accept P-Channel requests. + */ +uint32_t mce_enter_debug_recovery_mode(uint32_t core_id) +{ + uint32_t ret; + uint32_t ari_base = mce_get_curr_cpu_ari_base(); + + /* transition the specified core into the DEBUG_RECOVERY Mode */ + ret = ari_core_debug_recovery(ari_base, core_id, false); + if (ret == 0U) { + /* transition the specified DSU into the DEBUG_RECOVERY + * and Warm Reset the requested cluster + */ + ret = ari_dsu_debug_recovery(ari_base, + (core_id / PLATFORM_MAX_CPUS_PER_CLUSTER), true); + } + + return ret; +} +#endif + +/****************************************************************************** + * Handler to power down the entire system + *****************************************************************************/ +void mce_system_shutdown(void) +{ + ari_system_shutdown(mce_get_curr_cpu_ari_base()); +} + +/****************************************************************************** + * Handler to reboot the entire system + *****************************************************************************/ +void mce_system_reboot(void) +{ + ari_system_reboot(mce_get_curr_cpu_ari_base()); +} + +/****************************************************************************** + * Return number of CPU cores + *****************************************************************************/ +uint32_t mce_num_cores(void) +{ + uint32_t num_cores = 1U; + + if (mce_firmware_not_supported()) + return num_cores; + + /* Issue ARI if bitmap is uninitialized */ + if (core_present_bitmap == 0xDEADFEED) { + core_present_bitmap = ari_num_cores(mce_get_curr_cpu_ari_base()); + } + + for (int i = 1; i < PLATFORM_CORE_COUNT; i++) { + if (core_present_bitmap & BIT(i)) + num_cores++; + } + + return num_cores; +} + +/****************************************************************************** + * Return true if a cluster is present + *****************************************************************************/ +bool mce_is_cluster_present(unsigned int id) +{ + unsigned int mode; + + /* Sanity check cluster id */ + if (id >= PLATFORM_CLUSTER_COUNT) { + return false; + } + + /* Cluster 0 is always present */ + if (mce_firmware_not_supported() && (id == 0U)) { + return true; + } + + /* Without MCE support we cannot assume the presence of other clusters */ + if (mce_firmware_not_supported() && (id != 0U)) { + return false; + } + + /* Issue ARI if the bitmap is uninitialized */ + if (cluster_present_bitmap == 0xDEADFEED) { + cluster_present_bitmap = ari_cluster_present_map(mce_get_curr_cpu_ari_base()); + } + + /* Extract the mode */ + mode = (cluster_present_bitmap >> CLUSTER_MODE_SHIFT(id)) & CLUSTER_MODE_MASK; + + /* Any mode other than "disabled" means the cluster is present */ + return (mode != CLUSTER_MODE_DISABLED); +} + +/****************************************************************************** + * Return true if a cluster is configured to run in lock mode + *****************************************************************************/ +bool mce_is_cluster_in_lock_mode(unsigned int id) +{ + unsigned int mode; + + /* Sanity checks */ + if ((id >= PLATFORM_CLUSTER_COUNT) || mce_firmware_not_supported()) { + return false; + } + + /* Issue ARI if the bitmap is uninitialized */ + if (cluster_present_bitmap == 0xDEADFEED) { + cluster_present_bitmap = ari_cluster_present_map(mce_get_curr_cpu_ari_base()); + } + + /* Extract the mode */ + mode = (cluster_present_bitmap >> CLUSTER_MODE_SHIFT(id)) & CLUSTER_MODE_MASK; + + return (mode != CLUSTER_MODE_LOCK); +} + +/****************************************************************************** + * Return true if a cluster is configured to run in split mode + *****************************************************************************/ +bool mce_is_cluster_in_split_mode(unsigned int id) +{ + unsigned int mode; + + /* Sanity checks */ + if ((id >= PLATFORM_CLUSTER_COUNT) || mce_firmware_not_supported()) { + return false; + } + + /* Issue ARI if the bitmap is uninitialized */ + if (cluster_present_bitmap == 0xDEADFEED) { + cluster_present_bitmap = ari_cluster_present_map(mce_get_curr_cpu_ari_base()); + } + + /* Extract the mode */ + mode = (cluster_present_bitmap >> CLUSTER_MODE_SHIFT(id)) & CLUSTER_MODE_MASK; + + return (mode != CLUSTER_MODE_SPLIT); +} + +/****************************************************************************** + * Return true if a cluster is configured to run in hybrid mode + *****************************************************************************/ +bool mce_is_cluster_in_hybrid_mode(unsigned int id) +{ + unsigned int mode; + + /* Sanity checks */ + if ((id >= PLATFORM_CLUSTER_COUNT) || mce_firmware_not_supported()) { + return false; + } + + /* Issue ARI if the bitmap is uninitialized */ + if (cluster_present_bitmap == 0xDEADFEED) { + cluster_present_bitmap = ari_cluster_present_map(mce_get_curr_cpu_ari_base()); + } + + /* Extract the mode */ + mode = (cluster_present_bitmap >> CLUSTER_MODE_SHIFT(id)) & CLUSTER_MODE_MASK; + + return (mode != CLUSTER_MODE_HYBRID); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c new file mode 100644 index 0000000..00a8df2 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "se_private.h" + +/******************************************************************************* + * Constants and Macros + ******************************************************************************/ +#define MAX_TIMEOUT_MS U(100) /* Timeout in 100ms */ +#define SE_CTX_SAVE 0U /* Macro for save ctx operation */ +#define SE_CTX_RESTORE 1U /* Macro for restore ctx operation */ +#define SE_SC7_STATUS_ALL_ENGINE_RDY U(0x5F) /* SC7_STATUS value to denote all engine ready */ + +/* + * Check that SE operation has completed after kickoff. + * + * This function is invoked after an SE operation has been started, + * and it checks SE_SC7_STATUS = IDLE + */ +static bool tegra_se_is_operation_complete(void) +{ + uint32_t val = 0U, timeout = 0U; + int32_t ret = 0; + bool se_is_busy = false; + + /* + * Poll the status register to check if the operation + * completed. + */ + do { + val = tegra_se_read_32(SE0_SC7_STATUS); + + se_is_busy = ((val & SE0_SC7_STATUS_BUSY) != 0U); + + /* sleep until SE finishes */ + if (se_is_busy) { + mdelay(1); + timeout++; + } + + } while (se_is_busy && (timeout < MAX_TIMEOUT_MS)); + + if (timeout == MAX_TIMEOUT_MS) { + ERROR("%s: Atomic context save operation failed!\n", + __func__); + ret = -ECANCELED; + } + + /* check for context save/restore errors - START_ERROR/INTEGRITY_ERROR */ + val = tegra_se_read_32(SE0_INT_STATUS); + + if ((val & SE0_SC7_CTX_START_ERROR) || (val & SE0_SC7_CTX_INTEGRITY_ERROR)) { + ERROR("CTX START_ERROR/INTEGRITY_ERROR 0x%x\n", val); + ret = -ECANCELED; + } + + return (ret == 0); +} + +/* + * Wait for SE engine to be idle and clear any pending interrupts, before + * starting the next SE operation. + */ +static bool tegra_se_is_ready(void) +{ + int32_t ret = 0; + uint32_t val = 0, timeout = 0; + bool se_is_ready = false; + + /* Wait for previous operation to finish */ + do { + val = tegra_se_read_32(SE0_SC7_STATUS); + se_is_ready = (val == SE_SC7_STATUS_ALL_ENGINE_RDY); + + /* sleep until SE is ready */ + if (!se_is_ready) { + mdelay(1); + timeout++; + } + + } while (!se_is_ready && (timeout < MAX_TIMEOUT_MS)); + + if (timeout == MAX_TIMEOUT_MS) { + ERROR("%s: SE is not ready!\n", __func__); + ret = -ETIMEDOUT; + } + return (ret == 0); +} + +/* + * do softreset for SE0 engine to clear the HW flag before the context save. + */ +static void tegra_se_softreset(void) +{ + uint32_t val = SE0_SOFTRESET_TRUE, timeout = 0U; + + /* trigger SE0 softreset */ + tegra_se_write_32(SE0_SOFTRESET, SE0_SOFTRESET_TRUE); + + /* Wait for softreset to finish */ + do { + val = tegra_se_read_32(SE0_SOFTRESET); + + /* sleep until SE is ready */ + mdelay(1); + timeout++; + + } while ((val != SE0_SOFTRESET_FALSE) && (timeout < MAX_TIMEOUT_MS)); + + if (timeout == MAX_TIMEOUT_MS) { + ERROR("%s: SE softreset fail !\n", __func__); + } +} + +/* Function to perform the context save/restore sequence */ +static int32_t tegra_se_program_ctx_ops(uint32_t ctx_op) +{ + int32_t ret = -ECANCELED; + uint32_t se_int_state, val; + + /* Sequence for context save is as below - + * 0. set SE0_SOFTRESET to true and polling it until it change to false. + * This will clear the HW flag to default + * 1. Start NVRNG engine by setting SW_ENGINE_ENABLED in NV_NVRNG_R_CTRL0_0 + * 2. Check if all SE engine is ready by checking SE0_SC7_STATUS_0==0x5F, + * if not by 100ms report timeout. + * 3. Enable SC7_CTX_START_ERROR and SC7_CTX_INTEGRITY_ERROR in SE0_INT_ENABLE register. + * 4. Issue CTX_SAVE by setting SE0_SC7_CTRL bit 0 to 0. + * 5. Check if SE0_SC7_STATUS_0.bit31 shows busy (or) + * SE0_INT_STATUS.SC7_CTX_START_ERROR (or) + * SE0_INT_STATUS.C7_CTX_INTEGRITY_ERROR then report error. + * 6. Clear SE0_INT_STATUS and restore SE0_INT_ENABLE settings. + * Sequence for context restore is same as above but in set#4, + * issue CTX_RESTORE by setting SE0_SC7_CTRL bit 0 to 1 + */ + + if (ctx_op == SE_CTX_SAVE) { + tegra_se_softreset(); + } + + /* Start NVRNG engine */ + val = tegra_rng1_read_32(NV_NVRNG_R_CTRL); + tegra_rng_write_32(NV_NVRNG_R_CTRL, (val | SW_ENGINE_ENABLED)); + + /* Check if SE is in idle state */ + if (!tegra_se_is_ready()) + return ret; + + /* Save SE0_INT_ENABLE and enable SC7 ctx related error report */ + se_int_state = tegra_se_read_32(SE0_INT_ENABLE); + val = SE0_SC7_CTX_START_ERROR | SE0_SC7_CTX_INTEGRITY_ERROR; + tegra_se_write_32(SE0_INT_ENABLE, val); + + /* Perform ctx save/restore */ + if (ctx_op == SE_CTX_SAVE) { + /* Issue context save command */ + tegra_se_write_32(SE0_SC7_CTRL, SE0_SC7_CMD_START_CTX_SAVE); + } else { + /* Issue context restore command */ + tegra_se_write_32(SE0_SC7_CTRL, SE0_SC7_CMD_START_CTX_RESTORE); + } + + /* Check if operation complete and for errors*/ + if (tegra_se_is_operation_complete()) { + INFO("%s: context save/restore done.\n", __func__); + ret = 0; + } else { + ERROR("%s: context save/restore failed.\n", __func__); + } + + /* Clear SE0_INT_STATUS and restore SE0_INT_ENABLE */ + tegra_se_write_32(SE0_INT_STATUS, 0); + tegra_se_write_32(SE0_INT_ENABLE, se_int_state); + + return ret; +} + +static int32_t tegra_se_save_context(void) +{ + return tegra_se_program_ctx_ops(SE_CTX_SAVE); +} + +static int32_t tegra_se_restore_context(void) +{ + return tegra_se_program_ctx_ops(SE_CTX_RESTORE); +} + +/* + * Handler to power down the SE hardware blocks. This + * needs to be called only during System Suspend. + */ +int32_t tegra_se_suspend(void) +{ + int32_t ret = 0; + + /* initialise communication channel with BPMP */ + assert(tegra_bpmp_ipc_init() == 0); + + /* Enable SE clock before SE context save */ + ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE); + assert(ret == 0); + + /* Issue SE context save */ + ret = tegra_se_save_context(); + assert(ret == 0); + + /* Disable SE clock after SE context save */ + ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE); + assert(ret == 0); + + return ret; +} + +/* + * Handler to power up the SE hardware block(s) during System Resume. + */ +void tegra_se_resume(void) +{ + int32_t ret = 0; + + /* initialise communication channel with BPMP */ + assert(tegra_bpmp_ipc_init() == 0); + + /* Enable SE clock before SE context restore */ + ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE); + assert(ret == 0); + + /* Issue SE context restore */ + ret = tegra_se_restore_context(); + assert(ret == 0); + + /* Disable SE clock after SE context restore */ + ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE); + assert(ret == 0); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h new file mode 100644 index 0000000..5f4c57c --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SE_PRIVATE_H +#define SE_PRIVATE_H + +#include + +/* Control register to trigger SC7 context save/restore operation */ +#define SE0_SC7_CTRL U(0xBC) +#define SE0_SC7_CTRL_OP_BIT BIT_32(0) +#define SE0_SC7_CMD_START_CTX_SAVE (U(0) << 0) +#define SE0_SC7_CMD_START_CTX_RESTORE (U(1) << 0) + +/* Status register to report SC7 context-save/restore status */ +#define SE0_SC7_STATUS U(0xC0) +#define SE0_SC7_STATUS_BUSY BIT_32(31) +#define SE0_SC7_STATE_SAVE_CTX_VAL (U(0x2) << 7) +#define SE0_SC7_STATE_RESTORE_CTX_VAL (U(0x6) << 7) + +/* Interrupt register to enable/disable for SE engine */ +#define SE0_INT_ENABLE U(0x88) +#define SE0_SC7_CTX_START_ERROR BIT_32(6) +#define SE0_SC7_CTX_INTEGRITY_ERROR BIT_32(7) + +/* Interrupt status register */ +#define SE0_INT_STATUS U(0x8C) + +/* Software reset register to reset SE engine */ +#define SE0_SOFTRESET U(0x60) +#define SE0_SOFTRESET_FALSE U(0) +#define SE0_SOFTRESET_TRUE U(1) + +/******************************************************************************* + * Inline functions definition + ******************************************************************************/ + +static inline uint32_t tegra_se_read_32(uint32_t offset) +{ + return mmio_read_32((uint32_t)(TEGRA_SE0_BASE + offset)); +} + +static inline void tegra_se_write_32(uint32_t offset, uint32_t val) +{ + mmio_write_32((uint32_t)(TEGRA_SE0_BASE + offset), val); +} + +static inline uint32_t tegra_rng1_read_32(uint32_t offset) +{ + return mmio_read_32((uint32_t)(TEGRA_RNG1_BASE + offset)); +} + +static inline void tegra_rng_write_32(uint32_t offset, uint32_t val) +{ + mmio_write_32((uint32_t)(TEGRA_RNG1_BASE + offset), val); +} + +#endif /* SE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c new file mode 100644 index 0000000..78c66a9 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Handler to restore platform specific settings to the memory controller + ******************************************************************************/ +void plat_memctrl_restore(void) +{ + ; /* do nothing */ +} + +/******************************************************************************* + * Handler to program platform specific settings to the memory controller + ******************************************************************************/ +void plat_memctrl_setup(void) +{ + ; /* do nothing */ +} + +/******************************************************************************* + * Handler to program the scratch registers with TZDRAM settings for the + * resume firmware + ******************************************************************************/ +void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes) +{ + uint32_t sec_reg_ctrl = tegra_mc_read_32(MC_SECURITY_CFG_REG_CTRL_0); + uint32_t phys_base_lo = (uint32_t)phys_base & 0xFFF00000; + uint32_t phys_base_hi = (uint32_t)(phys_base >> 32); + + /* + * Check TZDRAM carveout register access status. Setup TZDRAM fence + * only if access is enabled. + */ + if ((sec_reg_ctrl & SECURITY_CFG_WRITE_ACCESS_BIT) == + SECURITY_CFG_WRITE_ACCESS_ENABLE) { + + /* + * Setup the Memory controller to allow only secure accesses to + * the TZDRAM carveout + */ + INFO("Configuring TrustZone DRAM Memory Carveout\n"); + + tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base_lo); + tegra_mc_write_32(MC_SECURITY_CFG3_0, phys_base_hi); + tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20); + + /* + * MCE propagates the security configuration values across the + * CCPLEX. + */ + (void)mce_update_gsc_tzdram(); + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c new file mode 100644 index 0000000..6a5649a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2021-2022, NVIDIA 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 + +/* state id mask */ +#define TEGRA234_STATE_ID_MASK 0xFU +/* constants to get power state's wake time */ +#define TEGRA234_WAKE_TIME_MASK 0x0FFFFFF0U +#define TEGRA234_WAKE_TIME_SHIFT 4U +/* default core wake mask for CPU_SUSPEND + * WAKE_REQUEST 2:2 Per Core (GIC provides a wake request interface that + * is used to indicate when an interrupt is received that + * is required to wake a core from a low power state.) + */ +#define TEGRA234_CORE_WAKE_MASK 0x4U + +extern bool tegra234_fake_system_suspend; + +static struct t234_psci_percpu_data { + uint32_t wake_time; +} __aligned(CACHE_WRITEBACK_GRANULE) t234_percpu_data[PLATFORM_CORE_COUNT]; + +int32_t tegra_soc_validate_power_state(uint32_t power_state, + psci_power_state_t *req_state) +{ + uint8_t state_id = (uint8_t)psci_get_pstate_id(power_state) & TEGRA234_STATE_ID_MASK; + uint32_t cpu = plat_my_core_pos(); + int32_t ret = PSCI_E_SUCCESS; + + /* save the core wake time (in TSC ticks)*/ + t234_percpu_data[cpu].wake_time = (power_state & TEGRA234_WAKE_TIME_MASK) + << TEGRA234_WAKE_TIME_SHIFT; + + /* + * Clean percpu_data[cpu] to DRAM. This needs to be done to ensure that + * the correct value is read in tegra_soc_pwr_domain_suspend(), which + * is called with caches disabled. It is possible to read a stale value + * from DRAM in that function, because the L2 cache is not flushed + * unless the cluster is entering CC7. + */ + clean_dcache_range((uint64_t)&t234_percpu_data[cpu], + sizeof(t234_percpu_data[cpu])); + + /* Sanity check the requested state id */ + switch (state_id) { + case PSTATE_ID_CORE_POWERDN: + + /* Core powerdown request */ + req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id; + req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id; + + break; + + default: + ERROR("%s: unsupported state id (%d)\n", __func__, state_id); + ret = PSCI_E_INVALID_PARAMS; + break; + } + + return ret; +} + +int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) +{ + (void)cpu_state; + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + const plat_local_state_t *pwr_domain_state; + uint8_t stateid_afflvl0, stateid_afflvl2; + uint32_t val; + uint32_t cpu = plat_my_core_pos(); + int32_t ret; + + /* get the state ID */ + pwr_domain_state = target_state->pwr_domain_state; + stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] & + TEGRA234_STATE_ID_MASK; + stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA234_STATE_ID_MASK; + + if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) { + + /* Enter CPU powerdown */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + t234_percpu_data[cpu].wake_time, + 0U, 0U); + + } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + if (!tegra234_fake_system_suspend) { + /* + * Before entering SC7 state, the ARM Trusted Firmware shall issue + * a SC7 entry request to the PSC. + */ + tegra_psc_notify_sc7_entry(); + + /* + * Suspend SE, RNG1 and PKA1 only on silcon and fpga, + * since VDK does not support atomic se ctx save + */ + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + ret = tegra_se_suspend(); + assert(ret == 0); + } + + /* Allow BPMP write access to AOTZRAM powergate controls */ + val = mmio_read_32(TEGRA_AON_FABRIC_FIREWALL_BASE + AON_FIREWALL_ARF_0_WRITE_CTL); + val |= (WRITE_CTL_MSTRID_BPMP_FW_BIT | WRITE_CTL_MSTRID_TZ_BIT); + mmio_write_32(TEGRA_AON_FABRIC_FIREWALL_BASE + AON_FIREWALL_ARF_0_WRITE_CTL, + val); + val = mmio_read_32(TEGRA_AON_FABRIC_FIREWALL_BASE + AON_FIREWALL_ARF_0_CTL); + val |= ARF_CTL_OWNER_BPMP_FW; + mmio_write_32(TEGRA_AON_FABRIC_FIREWALL_BASE + AON_FIREWALL_ARF_0_CTL, + val); + } + + } else { + ; /* do nothing */ + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Helper function to check if this is the last ON CPU in the cluster + ******************************************************************************/ +static bool tegra_last_on_cpu_in_cluster(const plat_local_state_t *states, + uint32_t ncpu) +{ + plat_local_state_t target; + bool last_on_cpu = true; + uint32_t num_cpus = ncpu, pos = 0; + + do { + target = states[pos]; + if (target != PLAT_MAX_OFF_STATE) { + last_on_cpu = false; + } + --num_cpus; + pos++; + } while (num_cpus != 0U); + + return last_on_cpu; +} + +/******************************************************************************* + * Helper function to get target power state for the cluster + ******************************************************************************/ +static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states, + uint32_t ncpu) +{ + uint32_t core_pos = plat_my_core_pos() % PLATFORM_MAX_CPUS_PER_CLUSTER; + plat_local_state_t target = states[core_pos]; + mce_cstate_info_t cstate_info = { 0 }; + + /* CPU suspend */ + if (target == PSTATE_ID_CORE_POWERDN) { + + /* Program default wake mask */ + cstate_info.wake_mask = TEGRA234_CORE_WAKE_MASK; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + } + + /* CPU off */ + if (target == PLAT_MAX_OFF_STATE) { + + /* Enable cluster powerdn from last CPU in the cluster */ + if (tegra_last_on_cpu_in_cluster(states, ncpu)) { + + /* Enable CC7 state and turn off wake mask */ + cstate_info.cluster = TEGRA_ARI_CSTATE_INFO_CLUSTER_CC7; + mce_update_cstate_info(&cstate_info); + + } else { + + /* Turn off wake_mask */ + cstate_info.wake_mask = 0; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + target = PSCI_LOCAL_STATE_RUN; + } + } + + return target; +} + +/******************************************************************************* + * Platform handler to calculate the proper target power level at the + * specified affinity level + ******************************************************************************/ +plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, + const plat_local_state_t *states, + uint32_t ncpu) +{ + plat_local_state_t target = PSCI_LOCAL_STATE_RUN; + uint32_t cpu = plat_my_core_pos(); + + /* System Suspend */ + if ((lvl == (uint32_t)MPIDR_AFFLVL2) && (states[cpu] == PSTATE_ID_SOC_POWERDN)) { + target = PSTATE_ID_SOC_POWERDN; + } + + /* CPU off, CPU suspend */ + if (lvl == (uint32_t)MPIDR_AFFLVL1) { + target = tegra_get_afflvl1_pwr_state(states, ncpu); + } + + /* target cluster/system state */ + return target; +} + +int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) +{ + uint32_t rmr_el3; + uint8_t stateid_afflvl2; + uint32_t val; + mce_cstate_info_t cstate_info = { 0 }; + + /* get the state ID */ + stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA234_STATE_ID_MASK; + + /* + * If we are in fake system suspend mode, ensure we start doing + * procedures that help in looping back towards system suspend exit + * instead of calling WFI by requesting a warm reset. + */ + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + if (tegra234_fake_system_suspend) { + rmr_el3 = read_rmr_el3(); + write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU); + wfi(); + panic(); + } + + /* + * Before executing wfi instruction to enter SC7 state, + * the ARM Trusted Firmware shall confirm that the PSC + * has completed its SC7 entry sequence. + */ + tegra_psc_wait_for_ack(); + + /* SCF flush - Clean and invalidate caches */ + mce_clean_and_invalidate_caches(); + + /* Prepare for system suspend */ + cstate_info.cluster = PSTATE_ID_CORE_POWERDN; + cstate_info.system = PSTATE_ID_CORE_POWERDN; + mce_update_cstate_info(&cstate_info); + + do { + val = (uint32_t)mce_command_handler( + (uint32_t)MCE_CMD_IS_SC7_ALLOWED, + 0U, 0U, 0U); + } while (val == 0U); + + /* Instruct the MCE to enter system suspend state */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + MCE_CORE_SLEEP_TIME_INFINITE, 0U, 0U); + } + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) +{ + uint64_t target_cpu = plat_core_pos_by_mpidr(mpidr); + + if (target_cpu >= PLATFORM_CORE_COUNT) { + ERROR("%s: unsupported CPU (0x%x)\n", __func__ , (uint32_t)target_cpu); + return PSCI_E_NOT_PRESENT; + } + + (void)mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Enable write access to cluster PMU register + ******************************************************************************/ +static void tegra_enable_cluster_pmu_writes(void) +{ + uint64_t actlr_elx; + + /** + * ARM DSU PMU driver in linux kernel requires write access to CLUSTERPM* + * registers. These registers are protected by CLUSTERPMUEN bit in ACTLR + * register. Linux kernel is in EL2, so ACTLR_EL3.CLUSTERPMUEN bit needs to + * be set, which will allow writes in EL2/EL1secure. + */ + + /* Enable write in EL2 */ + actlr_elx = read_actlr_el3(); + actlr_elx |= CORTEX_A78_AE_ACTLR_CLUSTERPMUEN_BIT; + write_actlr_el3(actlr_elx); +} + +int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + uint8_t stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; + uint8_t stateid_afflvl0 = target_state->pwr_domain_state[MPIDR_AFFLVL0]; + mce_cstate_info_t cstate_info = { 0 }; + uint32_t val = 0U; + uint32_t __unused cluster_id = ((uint32_t)read_mpidr() >> + MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK; + uint32_t __unused smen; + +#if RAS_EXTENSION + /* Enable RAS handling for the cluster specific nodes */ + tegra234_ras_init_my_cluster(); +#endif + + /* + * Program the following bits to '1'. + * + * Bit 0: Enable interleaving normal Non-cacheable transactions between + * master interfaces like Cacheable transactions. + * Bit 14: Enables sending WriteEvict transactions on the ACE or CHI + * master for UniqueClean evictions. + */ + val = read_clusterectlr_el1(); + write_clusterectlr_el1(val | DSU_WRITEEVICT_BIT | DSU_NC_CTRL_BIT); + + /* + * Reset power state info for CPUs when onlining. We set + * deepest power when offlining or suspending a core, so + * reset the power state when the CPU powers back on. + */ + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + cstate_info.cluster = TEGRA_ARI_CSTATE_INFO_CLUSTER_CC1; + mce_update_cstate_info(&cstate_info); + } + + /* + * Enable write access to cluster PMU register if ODM_PRODUCTION + * fuse is 0. + */ + if (mmio_read_32(TEGRA_FUSE_BASE + SECURITY_MODE) == 0U) { + tegra_enable_cluster_pmu_writes(); + } + + /* + * Check if we are exiting from deep sleep and restore SE + * context if we are. + */ + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + +#if ENABLE_STRICT_CHECKING_MODE + /* + * Enable strict checking after programming the GSC for + * enabling TZSRAM and TZDRAM + */ + mce_enable_strict_checking(); +#endif + + if (!tegra234_fake_system_suspend) { + /* Resume SE, RNG1 and PKA1 */ + tegra_se_resume(); + } + +#if RAS_EXTENSION + /* Enable RAS handling for all the common nodes */ + tegra234_ras_init_common(); +#endif + NOTICE("%s: exited SC7 successfully. Entering normal world.\n", __func__); + } + +#if GICV3_SUPPORT_GIC600AE_FMU + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + /* disable the GICFMU SMID 0xB after cluster power on */ + if (stateid_afflvl0 != PSTATE_ID_CORE_POWERDN) { + smen = ((FMU_BLK_PPI0 + cluster_id) << FMU_SMEN_BLK_SHIFT) | + (0xb << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(TEGRA_GICFMU_BASE, smen); + } + } +#endif + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) +{ + (void)target_state; + + /* Turn off CPU */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + MCE_CORE_SLEEP_TIME_INFINITE, 0U, 0U); + + return PSCI_E_SUCCESS; +} + +__dead2 void tegra_soc_prepare_system_off(void) +{ + /* System power off */ + mce_system_shutdown(); + + wfi(); + + /* wait for the system to power down */ + for (;;) { + ; + } +} + +int32_t tegra_soc_prepare_system_reset(void) +{ + /* System reboot */ + mce_system_reboot(); + + return PSCI_E_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c new file mode 100644 index 0000000..596f47b --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2020-2022, NVIDIA 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 + +DEFINE_BAKERY_LOCK(tegra234_ras_lock); + +/* Forward declarations */ +static int32_t tegra234_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data __unused); +static int32_t tegra234_ras_record_probe(const struct err_record_info *info, + int *probe_data); +static int32_t tegra234_gic_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data __unused); +static int32_t tegra234_gic_ras_record_probe(const struct err_record_info *info, + int *probe_data); + +/* Global variables */ +static bool ehf_handler_registered; + +/******************************************************************************* + * Tegra234 RAS nodes + ******************************************************************************/ +DEFINE_ONE_RAS_NODE(CCPMU); +DEFINE_ONE_RAS_AUX_DATA(CCPMU); +DEFINE_ONE_RAS_NODE(CMU_CLOCKS); +DEFINE_ONE_RAS_AUX_DATA(CMU_CLOCKS); +DEFINE_ONE_RAS_NODE(IH); +DEFINE_ONE_RAS_AUX_DATA(IH); +DEFINE_ONE_RAS_NODE(IST); +DEFINE_ONE_RAS_AUX_DATA(IST); +DEFINE_ONE_RAS_NODE(IOB); +DEFINE_ONE_RAS_AUX_DATA(IOB); +DEFINE_ONE_RAS_NODE(SNOC); +DEFINE_ONE_RAS_AUX_DATA(SNOC); +DEFINE_ONE_RAS_NODE(SCC); +DEFINE_ONE_RAS_AUX_DATA(SCC); +DEFINE_ONE_RAS_NODE(ACI); +DEFINE_ONE_RAS_AUX_DATA(ACI); +DEFINE_ONE_RAS_NODE(CORE_DCLS); +DEFINE_ONE_RAS_AUX_DATA(CORE_DCLS); +DEFINE_ONE_RAS_NODE(GIC600_FMU); +DEFINE_ONE_RAS_AUX_DATA(GIC600_FMU); + +/* + * We have same probe and handler for each error record group, use a macro to + * simply the record definition. + */ +#define ADD_ONE_ERR_GROUP(base_addr, size_num_k, aux_data) \ + ERR_RECORD_MEMMAP_V1((base_addr), (size_num_k), \ + &tegra234_ras_record_probe, \ + &tegra234_ras_record_handler, \ + aux_data) + +#define ADD_GICFMU_ERR_GROUP(base_addr, size_num_k, aux_data) \ + ERR_RECORD_MEMMAP_V1(TEGRA_GICFMU_BASE, 4, \ + &tegra234_gic_ras_record_probe, \ + &tegra234_gic_ras_record_handler, \ + aux_data) + +static struct err_record_info tegra234_ras_records_common[] = { + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CCPMU_BASE, 4, &CCPMU_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CMU_CLOCKS_BASE, 4, &CMU_CLOCKS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IH_BASE, 4, &IH_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IOB_BASE, 4, &IOB_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SNOC_BASE, 4, &SNOC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE0_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE1_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE2_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE3_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE4_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE5_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE6_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE7_BASE, 4, &SCC_aux_data), + ADD_GICFMU_ERR_GROUP(TEGRA_GICFMU_BASE, 4, &GIC600_FMU_aux_data) +}; + +static struct err_record_info tegra234_ras_records_cluster0[] = { + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IST_CLUSTER0_BASE, 4, &IST_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_ACI_CLUSTER0_BASE, 4, &ACI_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE0_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE2_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE3_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE_LS_PAIR1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE_LS_PAIR2_BASE, 4, &CORE_DCLS_aux_data) +}; + +static struct err_record_info tegra234_ras_records_cluster1[] = { + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IST_CLUSTER1_BASE, 4, &IST_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_ACI_CLUSTER1_BASE, 4, &ACI_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE0_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE2_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE3_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE_LS_PAIR1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE_LS_PAIR2_BASE, 4, &CORE_DCLS_aux_data) +}; + +static struct err_record_info tegra234_ras_records_cluster2[] = { + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IST_CLUSTER2_BASE, 4, &IST_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_ACI_CLUSTER2_BASE, 4, &ACI_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE0_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE2_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE3_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE_LS_PAIR1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE_LS_PAIR2_BASE, 4, &CORE_DCLS_aux_data) +}; + +/* Register the common error record to get past RAS driver compilation */ +REGISTER_ERR_RECORD_INFO(tegra234_ras_records_common); + +/******************************************************************************* + * Helper functions + ******************************************************************************/ + +/* Check if IST is enabled for the platform */ +static bool is_ist_enabled(void) +{ + uint32_t val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_IST_CLK_ENABLE); + return ((val & BIT(0)) == 1U); +} + +/* + * Helper function to check if the given error record is supported by + * the platform + */ +static bool is_err_record_supported(struct err_record_info *record) +{ + const struct ras_aux_data *aux_data = + (const struct ras_aux_data *)record->aux_data; + + /* + * Skip IST, if it is disabled for the platform + */ + if (!is_ist_enabled() && !strncmp(aux_data->name, "IST", strlen("IST"))) { + return false; + } + + /* + * Skip CORE_DCLS nodes if the cluster is running in split + * or hybrid mode + */ + if ((mce_is_cluster_in_split_mode(0) || mce_is_cluster_in_hybrid_mode(0)) && + (!strncmp(aux_data->name, "CORE_DCLS", strlen("CORE_DCLS")))) { + return false; + } + if ((mce_is_cluster_in_split_mode(1) || mce_is_cluster_in_hybrid_mode(1)) && + (!strncmp(aux_data->name, "CORE_DCLS", strlen("CORE_DCLS")))) { + return false; + } + if ((mce_is_cluster_in_split_mode(2) || mce_is_cluster_in_hybrid_mode(2)) && + (!strncmp(aux_data->name, "CORE_DCLS", strlen("CORE_DCLS")))) { + return false; + } + + return true; +} + +/******************************************************************************* + * Error handling functions + ******************************************************************************/ +/* Function to handle error from one given node */ +static int32_t tegra234_ras_node_handler(uint32_t base, const char *name, + const struct ras_error *errors, unsigned int num_errors) +{ + bool found = false; + uint64_t val = 0U; + uint32_t ierr = 0U, serr = 0U; + uint64_t status = mmio_read_64(base + ERR_STATUS(0)); + uint64_t addr = mmio_read_64(base + ERR_ADDR(0)); + uint64_t misc0 = mmio_read_64(base + ERR_MISC0(0)); + uint64_t misc1 = mmio_read_64(base + ERR_MISC1(0)); + uint64_t misc2 = mmio_read_64(base + ERR_MISC2(0)); + uint64_t misc3 = mmio_read_64(base + ERR_MISC3(0)); + + /* + * repeat until we have ERRSTATUS value consistent with + * the syndrome recorded for that error + */ + while (mmio_read_64(base + ERR_STATUS(0)) != status) { + status = mmio_read_64(base + ERR_STATUS(0)); + addr = mmio_read_64(base + ERR_ADDR(0)); + misc0 = mmio_read_64(base + ERR_MISC0(0)); + misc1 = mmio_read_64(base + ERR_MISC1(0)); + misc2 = mmio_read_64(base + ERR_MISC2(0)); + misc3 = mmio_read_64(base + ERR_MISC3(0)); + } + + /* not a valid error. */ + if (ERR_STATUS_GET_FIELD(status, V) == 0U) { + return 0; + } + + /* extract IERR and SERR from ERRSTATUS */ + ierr = (uint32_t)ERR_STATUS_GET_FIELD(status, IERR); + serr = (uint32_t)ERR_STATUS_GET_FIELD(status, SERR); + + /* + * POD Reset SERR value should be a 1 indicating an + * "implementation defined" error. But it incorrectly + * reports 8'd14, which indicates "illegal access (s/w + * faults)". + * + * If IERR = 28, SERR = 14 change the SERR to 1 as a + * work around. + */ + if (!strncmp(name, "DSU_IFP", strlen("DSU_IFP")) && + ((ierr == U(28)) && (serr == U(14)))) { + serr = U(1); + } + + /* + * Ideally, IST CREG lock errors should have a SERR value + * of 14, but it is incorrectly reported as 1. + * + * If IERR = 18, SERR = 1 change the SERR to 14 as a + * work around. + */ + if (!strncmp(name, "IST", strlen("IST")) && + ((ierr == U(18)) && (serr == U(1)))) { + serr = U(14); + } + + ERR_STATUS_SET_FIELD(val, V, 1); + + ERROR("**************************************\n"); + ERROR("RAS %s Error in %s, base=0x%x:\n", + (ERR_STATUS_GET_FIELD(status, UE) != 0U) ? "Uncorrectable" : + "Corrected", name, base); + ERROR("\tStatus = 0x%" PRIx64 "\n", status); + + ERROR("SERR = %s: 0x%x\n", ras_serr_to_str(serr), serr); + + /* Print uncorrectable errror information. */ + if (ERR_STATUS_GET_FIELD(status, UE) != 0U) { + + ERR_STATUS_SET_FIELD(val, UE, 1); + ERR_STATUS_SET_FIELD(val, UET, 1); + + /* IERR to error message */ + for (uint32_t i = 0; i < num_errors; i++) { + if (ierr == errors[i].error_code) { + ERROR("\tIERR = %s: 0x%x\n", + errors[i].error_msg, ierr); + + found = true; + break; + } + } + + if (!found) { + ERROR("\tUnknown IERR: 0x%x\n", ierr); + } + + /* Overflow, multiple errors have been detected. */ + if (ERR_STATUS_GET_FIELD(status, OF) != 0U) { + ERROR("\tOverflow (there may be more errors) - " + "Uncorrectable\n"); + ERR_STATUS_SET_FIELD(val, OF, 1); + } + + } else { + /* For corrected error, simply clear it. */ + ERR_STATUS_SET_FIELD(val, CE, 1); + } + + /* Miscellaneous Register Valid. */ + if (ERR_STATUS_GET_FIELD(status, MV) != 0U) { + ERROR("\tMISC0 = 0x%" PRIx64 "\n", misc0); + ERROR("\tMISC1 = 0x%" PRIx64 "\n", misc1); + ERROR("\tMISC2 = 0x%" PRIx64 "\n", misc2); + ERROR("\tMISC3 = 0x%" PRIx64 "\n", misc3); + ERR_STATUS_SET_FIELD(val, MV, 1); + } + + /* Address Valid. */ + if (ERR_STATUS_GET_FIELD(status, AV) != 0U) { + ERROR("\tADDR = 0x%" PRIx64 "\n", addr); + ERR_STATUS_SET_FIELD(val, AV, 1); + } + + /* Deferred error */ + if (ERR_STATUS_GET_FIELD(status, DE) != 0U) { + ERROR("\tDeferred error\n"); + ERR_STATUS_SET_FIELD(val, DE, 1); + } + + ERROR("**************************************\n"); + + /* Write to clear reported error records */ + mmio_write_64(base + ERR_STATUS(0), val); + mmio_write_64(base + ERR_MISC0(0), 0); + mmio_write_64(base + ERR_MISC1(0), 0); + mmio_write_64(base + ERR_ADDR(0), 0); + + /* error handled */ + return 0; +} + +/* Function to handle one error node from an error record group. */ +static int32_t tegra234_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *data __unused) +{ + const struct ras_aux_data *aux_data = info->aux_data; + uint32_t base = info->memmap.base_addr; + + /* make sure that we have valid error record info */ + assert(aux_data->error_records != NULL); + + return tegra234_ras_node_handler(base, aux_data->name, + aux_data->error_records, aux_data->num_err_records); +} + +/* Function to probe an error from error record group. */ +static int32_t tegra234_ras_record_probe(const struct err_record_info *info, + int *probe_data) +{ + return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k, probe_data); +} + +/* Function to handle one error node from an error record group. */ +static int32_t tegra234_gic_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *data __unused) +{ + return gic600_fmu_ras_handler(info->memmap.base_addr, probe_data); +} + +/* Function to probe an error from error record group. */ +static int32_t tegra234_gic_ras_record_probe(const struct err_record_info *info, + int *probe_data) +{ + return gic600_fmu_probe(info->memmap.base_addr, probe_data); +} + +/* + * Given an RAS interrupt number, locate the registered handler and call it. If + * no handler was found for the interrupt number, this function panics. + */ +static int tegra234_ras_handler(uint32_t intr_raw, uint32_t flags, + void *handle, void *cookie) +{ + uint64_t intr_status = ih_read_ras_intstatus(plat_my_core_pos()); + struct err_record_info *selected = NULL; + int probe_data = 0; + int ret; + uint32_t num_records = 0U; + + const struct err_handler_data err_data = { + .version = ERR_HANDLER_VERSION, + .interrupt = intr_raw, + .flags = flags, + .cookie = cookie, + .handle = handle + }; + + VERBOSE("%s: irq=%d, intr_status=0x%" PRIx64 "\n", __func__, intr_raw, intr_status); + + /* INTR_STATUS will be '0' for secondary cores */ + if (intr_status == 0) + return 0; + + if ((intr_status & TEGRA234_IH_STATUS_MASK_CMU) != 0U) { + selected = tegra234_ras_records_common; + num_records = ARRAY_SIZE(tegra234_ras_records_common); + } else if ((intr_status & TEGRA234_IH_STATUS_MASK_SCF) != 0U) { + selected = tegra234_ras_records_common; + num_records = ARRAY_SIZE(tegra234_ras_records_common); + } else if ((intr_status & TEGRA234_IH_STATUS_MASK_CL0) != 0U) { + selected = tegra234_ras_records_cluster0; + num_records = ARRAY_SIZE(tegra234_ras_records_cluster0); + } else if ((intr_status & TEGRA234_IH_STATUS_MASK_CL1) != 0U) { + selected = tegra234_ras_records_cluster1; + num_records = ARRAY_SIZE(tegra234_ras_records_cluster1); + } else if ((intr_status & TEGRA234_IH_STATUS_MASK_CL2) != 0U) { + selected = tegra234_ras_records_cluster2; + num_records = ARRAY_SIZE(tegra234_ras_records_cluster2); + } + + assert(selected != NULL); + + /* check all the error records */ + while (num_records-- > 0U) { + + /* Check if the platform supports this error record */ + if (!is_err_record_supported(selected)) { + /* next error record */ + selected++; + continue; + } + + /* Is this record valid? */ + ret = selected->probe(selected, &probe_data); + + /* Call error handler for the record group */ + if (ret != 0) { + + /* serialize RAS record accesses across CPUs */ + bakery_lock_get(&tegra234_ras_lock); + + /* Invoke handler for the RAS node */ + selected->handler(selected, probe_data, &err_data); + + bakery_lock_release(&tegra234_ras_lock); + + /* Clear interrupt status */ + ih_write_intstatus_clr(plat_my_core_pos(), intr_status); + + /* + * Do an EOI of the RAS interrupt. This allows + * the sdei event to be dispatched at the SDEI + * event's priority. + */ + plat_ic_end_of_interrupt(intr_raw); + + ret = sdei_dispatch_event(TEGRA_SDEI_EP_EVENT_0 + + plat_my_core_pos()); + if (ret != 0) + ERROR("sdei_dispatch_event returned %d\n", ret); + } + + /* next error record */ + selected++; + } + + return 0; +} + +/******************************************************************************* + * This function is invoked by the RAS framework for the platform to handle an + * External Abort received at EL3. + ******************************************************************************/ +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ + ERROR("Exception reason=%u syndrome=0x%" PRIx64 "\n", ea_reason, syndrome); + +#if RAS_EXTENSION + tegra234_ras_handler(0, flags, handle, cookie); +#else + ERROR("Unhandled External Abort received on 0x%lx at EL3!\n", + read_mpidr_el1()); + panic(); +#endif +} + +/******************************************************************************* + * This function is invoked when an External Abort is received while executing + * in EL3. + ******************************************************************************/ +void plat_handle_el3_ea(void) +{ + uint64_t syndrome = read_esr_el3(); + uint32_t flags = read_scr_el3() & SCR_NS_BIT; + + ERROR("Exception reason=%u syndrome=0x%" PRIx64 "\n", ERROR_EA_ASYNC, syndrome); + +#if RAS_EXTENSION + tegra234_ras_handler(0, flags, NULL, NULL); +#else + ERROR("Unhandled External Abort received on 0x%lx at EL3!\n", + read_mpidr_el1()); + panic(); +#endif +} + +static void enable_error_detection_for_group(struct err_record_info *group, + uint32_t num_of_entries) +{ + struct err_record_info *info; + + for (info = group; num_of_entries > 0; num_of_entries--, info++) { + + /* Check if the platform supports this error record */ + if (!is_err_record_supported(info)) { + continue; + } + + uint32_t base = info->memmap.base_addr; + const struct ras_aux_data *aux_data = (const struct ras_aux_data *)info->aux_data; + /* ERRCTLR register value. */ + uint64_t err_ctlr = 0ULL; + /* all supported errors for this node. */ + uint64_t err_fr; + /* uncorrectable errors */ + uint64_t uncorr_errs; + /* correctable errors */ + uint64_t corr_errs; + + /* + * Skip GIC600_FMU init here, as it is done later by + * the platform + */ + if (!strncmp(aux_data->name, "GIC600_FMU", strlen("GIC600_FMU"))) { + continue; + } + + /* + * Catch error if something is wrong with the RAS aux data + * record table. + */ + assert(aux_data != NULL); + assert(aux_data->get_ue_mask != NULL); + assert(aux_data->get_ce_mask != NULL); + + /* Read the errors supported by the node */ + err_fr = mmio_read_64(base + ERR_FR(0)) & ERR_FR_EN_BITS_MASK; + uncorr_errs = aux_data->get_ue_mask(); + corr_errs = aux_data->get_ce_mask(); + + VERBOSE("[%s] ERRFR=0x%" PRIx64 ", expected=0x%" PRIx64 "\n", aux_data->name, + err_fr, uncorr_errs | corr_errs); + + /* enable error reporting and logging */ + ERR_CTLR_ENABLE_FIELD(err_ctlr, ED); + + /* uncorrected error recovery interrupt enable */ + if ((uncorr_errs & err_fr) != 0ULL) { + ERR_CTLR_ENABLE_FIELD(err_ctlr, UI); + } + + /* fault handling interrupt for corrected errors enable */ + if ((corr_errs & err_fr) != 0ULL) { + ERR_CTLR_ENABLE_FIELD(err_ctlr, CFI); + } + + /* enable all the supported errors */ + err_ctlr |= (err_fr & (uncorr_errs | corr_errs)); + + /* enable specified errors, or set to 0 if no supported error */ + VERBOSE("[%s] ERRCTLR=0x%" PRIx64 "\n", aux_data->name, err_ctlr); + mmio_write_64(base + ERR_CTLR(0), err_ctlr); + + /* Assert if all errors have not been enabled */ + err_ctlr &= ERR_FR_EN_BITS_MASK; + assert((mmio_read_64(base + ERR_CTLR(0)) & ERR_FR_EN_BITS_MASK) == err_ctlr); + } +} + +/* + * Function to enable reporting for RAS error records common to all clusters + * + * Uncorrectable and correctged errors are set to report as interrupts. + */ +void tegra234_ras_init_common(void) +{ + uint32_t i; + + /* RAS is only supported by limited platforms */ + if (!tegra_platform_is_fpga() && !tegra_platform_is_silicon()) { + return; + } + + /* all FHI/ERI bits must be enabled for all cores */ + for (i = 0; i < PLATFORM_CORE_COUNT; i++) { + ih_write_ras_general_enb(i, ENB_ALL_INTR_SOURCES); + ih_write_ras_general_mask(i, 0); + } + + /* Enable RAS error detection and reporting for common group */ + enable_error_detection_for_group(tegra234_ras_records_common, + ARRAY_SIZE(tegra234_ras_records_common)); + + /* install common interrupt handler */ + if (!ehf_handler_registered) { + ehf_register_priority_handler(PLAT_RAS_PRI, tegra234_ras_handler); + ehf_handler_registered = true; + } + + VERBOSE("RAS handling enabled for common nodes\n"); +} + +/* Struct to describe the RAS error records for CPU clusters */ +typedef struct err_record_desc { + struct err_record_info *record; + uint32_t num_entries; +} err_record_desc_t; + +/* + * Function to enable reporting for RAS error records for a given cluster + * + * Uncorrectable and correctged errors are set to report as interrupts. + */ +void tegra234_ras_init_my_cluster(void) +{ + int id = MPIDR_AFFLVL2_VAL(read_mpidr()); + err_record_desc_t list[] = { + { + .record = tegra234_ras_records_cluster0, + .num_entries = ARRAY_SIZE(tegra234_ras_records_cluster0) + }, + { + .record = tegra234_ras_records_cluster1, + .num_entries = ARRAY_SIZE(tegra234_ras_records_cluster1) + }, + { + .record = tegra234_ras_records_cluster2, + .num_entries = ARRAY_SIZE(tegra234_ras_records_cluster2) + } + }; + + assert(id < ARRAY_SIZE(list)); + + /* RAS is only supported by limited platforms */ + if (!tegra_platform_is_fpga() && !tegra_platform_is_silicon()) { + return; + } + + /* Enable RAS error detection and reporting for the cluster */ + if (mce_is_cluster_present(id)) { + enable_error_detection_for_group(list[id].record, list[id].num_entries); + } + + VERBOSE("RAS handling enabled for cluster%d\n", id); +} + +#if DEBUG + +#define ERR_MISC0_CEC_SHIFT U(32) +#define ERR_MISC0_CEC_VALUE ULL(0x7F7F) +#define ERR_PFGCTL U(0x808) +#define ERR_PFGCDN U(0x810) + +int tegra234_ras_inject_fault(uint64_t base, uint64_t pfgcdn, uint64_t pfgctl) +{ + uint64_t errctlr, val; + + if ((base < TEGRA234_RAS_CCPMU_BASE) || + (base > TEGRA234_RAS_CL2_DSU_IFP_BASE)) { + /* No record found */ + return -EINVAL; + } + + /* Set ERRMISC0.CEC bits */ + val = mmio_read_64(base + ERR_MISC0(0)); + val |= (ERR_MISC0_CEC_VALUE << ERR_MISC0_CEC_SHIFT); + mmio_write_64(base + ERR_MISC0(0), val); + + errctlr = mmio_read_64(base + ERR_CTLR(0)); + errctlr &= ERR_FR_EN_BITS_MASK; + + if ((pfgctl & errctlr) == 0U) + return -ENOTSUP; + + VERBOSE("%s: PFGCDN=0x%" PRIx64 ", PFGCTL=0x%" PRIx64 "\n", __func__, + pfgcdn, pfgctl); + mmio_write_64(base + ERR_PFGCDN, pfgcdn); + mmio_write_64(base + ERR_PFGCTL, pfgctl); + + return 0; +} +#endif diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c new file mode 100644 index 0000000..2022bce --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/******************************************************************************* + * Setup secondary CPU vectors + ******************************************************************************/ +void plat_secondary_setup(void) +{ + uint64_t reset_addr = (uint64_t)tegra_secure_entrypoint; + + INFO("Setting up secondary CPU boot\n"); + + /* save reset vector to be used during SYSTEM_SUSPEND exit */ + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO, + (uint32_t)reset_addr); + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI, + (uint32_t)(reset_addr >> 32)); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c new file mode 100644 index 0000000..a62659b --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2021-2022, NVIDIA 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 +#include +#include +#include + +/* ID for spe-console */ +#define TEGRA_CONSOLE_SPE_ID 0xFE +/* MCE aperture start address */ +#define TEGRA_MCE_ARI0_BASE TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET + +/* CPU Extended control EL1 register */ +DEFINE_RENAME_SYSREG_READ_FUNC(cpuectlr_el1, CORTEX_A76_CPUECTLR_EL1) + +/******************************************************************************* + * The Tegra power domain tree has a single system level power domain i.e. a + * single root node. The first entry in the power domain descriptor specifies + * the number of power domains at the highest power level. + ******************************************************************************* + */ +static const uint8_t tegra_power_domain_tree_desc[] = { + /* No of root nodes */ + 1, + /* No of clusters */ + PLATFORM_CLUSTER_COUNT, + /* No of CPU cores - cluster0 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster1 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster2 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster3 */ + PLATFORM_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the Tegra default topology tree information. + ******************************************************************************/ +const uint8_t *plat_get_power_domain_tree_desc(void) +{ + return tegra_power_domain_tree_desc; +} + +/* + * Table of regions to map using the MMU. + */ +static const mmap_region_t tegra_mmap[] = { + MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x4000U, /* 16KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_TSA_BASE, 0x20000U, /* 128KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_GPCDMA_BASE, 0x10000U, /* 64KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x8000U, /* 32KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_MC_BASE, 0x8000U, /* 32KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#if !ENABLE_CONSOLE_SPE + MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000U, /* 128KB - UART A, B*/ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000U, /* 192KB - UART D, E, F */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#endif + MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_HSP_DBELL_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#if ENABLE_CONSOLE_SPE + MAP_REGION_FLAT(TEGRA_CONSOLE_SPE_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#endif +#if !ENABLE_CONSOLE_SPE + MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000U, /* 128KB - UART C, G */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#endif + MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_AON_FABRIC_FIREWALL_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_TMRUS_BASE, TEGRA_TMRUS_SIZE, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_MCE_ARI0_BASE, 0xc0000U, /* 64KB*12 */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x10000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_GICR_BASE, 0x200000U, /* 2MB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#if GICV3_SUPPORT_GIC600AE_FMU + MAP_REGION_FLAT(TEGRA_GICFMU_BASE, 0x10000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#endif + MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000U, /* 64KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_CCPMU_RAS_BASE, 0x1D000U, /* 116KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_RAS_CL0_CORE0_BASE, 0x9000U, /* 36KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_RAS_CL1_CORE0_BASE, 0x9000U, /* 36KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_RAS_CL2_CORE0_BASE, 0x9000U, /* 36KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_PSC_MBOX_TZ_BASE, 0x2000U, /* 8KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + {0} +}; + +/******************************************************************************* + * Set up the pagetables as per the platform memory map & initialize the MMU + ******************************************************************************/ +const mmap_region_t *plat_get_mmio_map(void) +{ + /* MMIO space */ + return tegra_mmap; +} + +/******************************************************************************* + * Handler to get the System Counter Frequency + ******************************************************************************/ +uint32_t plat_get_syscnt_freq2(void) +{ + return 31250000; +} + +#if !ENABLE_CONSOLE_SPE +/******************************************************************************* + * Maximum supported UART controllers + ******************************************************************************/ +#define TEGRA234_MAX_UART_PORTS 6 + +/******************************************************************************* + * This variable holds the UART port base addresses + ******************************************************************************/ +static uint32_t tegra234_uart_addresses[TEGRA234_MAX_UART_PORTS + 1] = { + 0, /* undefined - treated as an error case */ + TEGRA_UARTA_BASE, + TEGRA_UARTB_BASE, + TEGRA_UARTC_BASE, + TEGRA_UARTD_BASE, + TEGRA_UARTE_BASE, + TEGRA_UARTF_BASE, +}; +#endif + +/******************************************************************************* + * Enable console corresponding to the console ID + ******************************************************************************/ +void plat_enable_console(int32_t id) +{ + uint32_t console_clock = 0U; + +#if ENABLE_CONSOLE_SPE + static console_t spe_console; + + if (id == TEGRA_CONSOLE_SPE_ID) { + (void)console_spe_register(TEGRA_CONSOLE_SPE_BASE, + console_clock, + TEGRA_CONSOLE_BAUDRATE, + &spe_console); + console_set_scope(&spe_console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH); + } +#else + static console_t uart_console; + + if ((id > 0) && (id < TEGRA234_MAX_UART_PORTS)) { + /* + * Reference clock used by the FPGAs is a lot slower. + */ + if (tegra_platform_is_fpga()) { + console_clock = TEGRA_BOOT_UART_CLK_13_MHZ; + } else { + console_clock = TEGRA_BOOT_UART_CLK_408_MHZ; + } + + (void)console_16550_register(tegra234_uart_addresses[id], + console_clock, + TEGRA_CONSOLE_BAUDRATE, + &uart_console); + console_set_scope(&uart_console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH); + } +#endif +} + +/******************************************************************************* + * Handler for early platform setup + ******************************************************************************/ +void plat_early_platform_setup(void) +{ + uint32_t __unused val; + + /* sanity check MCE firmware compatibility */ + mce_verify_firmware_version(); + + /* SCF flush - Clean and invalidate caches */ + mce_clean_and_invalidate_caches(); + +#if RAS_EXTENSION + /* Enable RAS handling for all the common nodes */ + tegra234_ras_init_common(); +#endif + + /* + * Number of physical cores should be less than PLATFOM_CORE_COUNT + */ + assert(PLATFORM_CORE_COUNT >= mce_num_cores()); + +#if !DEBUG + /* + * check ETM settings + * Assert if the TRCPRGCTLR.EN bit is not set. + */ + val = mmio_read_32(TEGRA_DBGAPB_BASE + TEGRA_TRCPRGCTLR_OFFSET); + assert((val & TRCPRGCTLR_EN_BIT) == TRCPRGCTLR_EN_BIT); +#endif + + /* + * Program the following bits to '1'. + * + * Bit 0: Enable interleaving normal Non-cacheable transactions between + * master interfaces like Cacheable transactions. + * Bit 14: Enables sending WriteEvict transactions on the ACE or CHI + * master for UniqueClean evictions. + */ + val = read_clusterectlr_el1(); + write_clusterectlr_el1(val | DSU_WRITEEVICT_BIT | DSU_NC_CTRL_BIT); +} + +/****************************************************************************** + * On a GICv3 system, use Group0 interrupts as secure interrupts + *****************************************************************************/ +static const interrupt_prop_t tegra234_interrupt_props[] = { + INTR_PROP_DESC(TEGRA234_RAS_PPI_ERI, PLAT_RAS_PRI, + INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(TEGRA234_RAS_PPI_FHI, PLAT_RAS_PRI, + INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI, + INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(TEGRA234_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO, + INTR_GROUP0, GIC_INTR_CFG_EDGE) +}; + +/******************************************************************************* + * Initialize the GIC and SGIs + ******************************************************************************/ +void plat_gic_setup(void) +{ + /* Tegra234 contains GICD, SPI Collator, Wake Request, PPI0-PPI2 blocks */ + uint64_t tegra234_gic600_fmu_blks = BIT(FMU_BLK_GICD) | BIT(FMU_BLK_SPICOL) | + BIT(FMU_BLK_WAKERQ) | BIT(FMU_BLK_PPI0) | BIT(FMU_BLK_PPI1) | + BIT(FMU_BLK_PPI2); + uint32_t smen; + + tegra_gic_setup(tegra234_interrupt_props, ARRAY_SIZE(tegra234_interrupt_props)); + + /* initialize the GICD and GICR */ + tegra_gic_init(); + +#if GICV3_SUPPORT_GIC600AE_FMU + /* initialize the Fault Management Unit */ + if (tegra_platform_is_fpga() || tegra_platform_is_silicon()) { + gic600_fmu_init(TEGRA_GICFMU_BASE, tegra234_gic600_fmu_blks, + true, true); + + /* + * The PPI0/1/2 block SMID 0xB causes spurious RAS errors. + * As a workaround, disable the SMID for these blocks. + */ + smen = (FMU_BLK_PPI0 << FMU_SMEN_BLK_SHIFT) | + (0xb << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(TEGRA_GICFMU_BASE, smen); + + smen = (FMU_BLK_PPI1 << FMU_SMEN_BLK_SHIFT) | + (0xb << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(TEGRA_GICFMU_BASE, smen); + + smen = (FMU_BLK_PPI2 << FMU_SMEN_BLK_SHIFT) | + (0xb << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(TEGRA_GICFMU_BASE, smen); + } +#endif + /* + * Initialize the FIQ handler only if the platform supports any + * FIQ interrupt sources. + */ + tegra_fiq_handler_setup(); +} + +/******************************************************************************* + * Return pointer to the BL31 params from previous bootloader + ******************************************************************************/ +struct tegra_bl31_params *plat_get_bl31_params(void) +{ + uint32_t reg; + uint64_t val; + + reg = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_HI_ADDR); + val = ((uint64_t)reg & SCRATCH_BL31_PARAMS_HI_ADDR_MASK) >> + SCRATCH_BL31_PARAMS_HI_ADDR_SHIFT; + val <<= 32; + val |= (uint64_t)mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_LO_ADDR); + + return (struct tegra_bl31_params *)(uintptr_t)val; +} + +/******************************************************************************* + * Return pointer to the BL31 platform params from previous bootloader + ******************************************************************************/ +plat_params_from_bl2_t *plat_get_bl31_plat_params(void) +{ + uint32_t reg; + uint64_t val; + + reg = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_HI_ADDR); + val = ((uint64_t)reg & SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_MASK) >> + SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT; + val <<= 32; + val |= (uint64_t)mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_LO_ADDR); + + return (plat_params_from_bl2_t *)(uintptr_t)val; +} + +/******************************************************************************* + * Handler for late platform setup + ******************************************************************************/ +void plat_late_platform_setup(void) +{ + uint32_t ret; + struct bpmp_ipc_platform_data *bpmp_ipc_data = plat_get_bpmp_ipc_data(); + +#if ENABLE_STRICT_CHECKING_MODE + /* + * Enable strict checking after programming the GSC for + * enabling TZSRAM and TZDRAM + */ + mce_enable_strict_checking(); +#endif + + /* memmap bpmp_ipc_tz addr */ + if (bpmp_ipc_data != NULL) { + ret = mmap_add_dynamic_region(bpmp_ipc_data->bpmp_ipc_tx_base, /* PA */ + bpmp_ipc_data->bpmp_ipc_tx_base, /* VA */ + (TEGRA_BPMP_IPC_CH_MAP_SIZE * 2), /* 8KB size */ + MT_DEVICE | MT_RW | MT_SECURE); /* attrs */ + assert(ret == 0); + } +} + +/******************************************************************************* + * Handler to indicate support for System Suspend + ******************************************************************************/ +bool plat_supports_system_suspend(void) +{ + return true; +} + +/******************************************************************************* + * Platform specific FIQ handler. + * Return true if `irq_num` number is handled by this function. + ******************************************************************************/ +bool plat_fiq_handler(uint32_t irq_num) +{ + return false; +} + +/******************************************************************************* + * Platform handler to verify system regsiter settings before completing + * boot + ******************************************************************************/ +void plat_verify_sysreg_settings(void) +{ + uint64_t mask, val; + + /* + * Check SCTLR_EL3 settings + * Assert for the below incorrect settings + * 1. WXN bit is not '1'. + * 2. EE bit is not '0'. + * 3. SA bit is not '1'. + * 4. A bit is not '1'. + * 5. SSBS is not '0'. + */ + mask = SCTLR_WXN_BIT | SCTLR_EE_BIT | SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT; + val = read_sctlr_el3() & mask; + assert(val == (SCTLR_WXN_BIT | SCTLR_SA_BIT | SCTLR_A_BIT)); + + /* + * Check SCR_EL3 settings + * Assert for the below incorrect settings + * 1. TWE bit is not '0'. + * 2. TWI bit is not '0'. + * 3. SIF bit is not '1'. + * 4. SMD bit is not '0'. + * 5. EA bit is not '1'. + */ + mask = SCR_SIF_BIT | SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT; + val = read_scr() & mask; + assert(val == SCR_SIF_BIT); +#if HANDLE_EA_EL3_FIRST + mask = SCR_EA_BIT; + val = read_scr() & mask; + assert(val == SCR_EA_BIT); +#endif + + /* + * Check MDCR_EL3 settings + * Assert for the below incorrect settings + * 1. SDD bit is not '1'. + * 2. TDOSA bit is not '0'. + * 3. TDA bit is not '0' + * 4. TPM bit nis ot '0'. + */ + mask = MDCR_SDD_BIT | MDCR_TDOSA_BIT | MDCR_TDA_BIT | MDCR_TPM_BIT; + val = read_mdcr_el3() & mask; + assert(val == MDCR_SDD_BIT); + + /* + * Check CPTR_EL3 settings + * Assert for the below incorrect settings + * 1. TCPAC bit is not '0'. + * 2. TTA bit is not '0'. + * 3. TFP bit is not '0'. + */ + mask = TCPAC_BIT | TTA_BIT | TFP_BIT; + assert((read_cptr_el3() & mask) == 0U); + + /* + * Check CPTR_read_cntfrq_el0 settings + * Assert for incorrect value. + */ + assert(read_cntfrq_el0() == plat_get_syscnt_freq2()); + + /* + * Check PMCR_EL0 settings + * Assert for the below incorrect settings + * 1. LC is not '1' + * 2. DP is not '1' + * 3. X is not '0' + * 4. D is not '0' + */ + mask = PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT | PMCR_EL0_X_BIT | PMCR_EL0_D_BIT; + val = read_pmcr_el0() & mask; + assert(val == (PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT)); + + /* + * Check daif settings + * Assert if External Aborts and SError Interrupts + * in 'daif' register are disabled. + */ + assert((read_daif() & DAIF_ABT_BIT) == 0U); + + /* + * Check Write streaming settings + * Assert if the write streaming is disabled + * NOTE:WS_THR_XX = b11 indicates write stream disable + */ + val = (uint64_t)read_cpuectlr_el1(); + assert((val & WS_THR_DISABLE_ALL) != WS_THR_DISABLE_ALL); +} + +/******************************************************************************* + * Platform specific runtime setup. + ******************************************************************************/ +void plat_runtime_setup(void) +{ + /* + * During cold boot, it is observed that the arbitration + * bit is set in the Memory controller leading to false + * error interrupts in the non-secure world. To avoid + * this, clean the interrupt status register before + * booting into the non-secure world + */ + tegra_memctrl_clear_pending_interrupts(); + + /* + * During boot, USB3 and flash media (SDMMC/SATA) devices need + * access to IRAM. Because these clients connect to the MC and + * do not have a direct path to the IRAM, the MC implements AHB + * redirection during boot to allow path to IRAM. In this mode + * accesses to a programmed memory address aperture are directed + * to the AHB bus, allowing access to the IRAM. This mode must be + * disabled before we jump to the non-secure world. + */ + tegra_memctrl_disable_ahb_redirection(); + + /* Verify system register settings */ + plat_verify_sysreg_settings(); + + /* + * SCF flush - Clean and invalidate caches before jumping to the + * non-secure world payload. + */ + mce_clean_and_invalidate_caches(); +} + +/******************************************************************************* + * Return pointer to the bpmp_ipc_data + ******************************************************************************/ +static struct bpmp_ipc_platform_data bpmp_ipc; +struct bpmp_ipc_platform_data *plat_get_bpmp_ipc_data(void) +{ + uint64_t rx_end_addr; + uint64_t sysram_end_addr; + + /* + * BPMP FW is not supported on QT/VSP platforms. Disable BPMP_IPC + * interface. + */ + if (tegra_platform_is_qt() || tegra_platform_is_vsp()) { + return NULL; + } + + bpmp_ipc.bpmp_ipc_tx_base = (((uint64_t)mmio_read_32(TEGRA_MC_BASE + + MC_CCPLEX_BPMP_IPC_BASE_HI) << 32) + | mmio_read_32(TEGRA_MC_BASE + MC_CCPLEX_BPMP_IPC_BASE_LO)); + bpmp_ipc.bpmp_ipc_rx_base = bpmp_ipc.bpmp_ipc_tx_base + TEGRA_BPMP_IPC_CH_MAP_SIZE; + bpmp_ipc.bpmp_ipc_map_size = TEGRA_BPMP_IPC_CH_MAP_SIZE; + + /* + * Disable BPMP_IPC interface if TX/RX shared memory is not present. + */ + if ((bpmp_ipc.bpmp_ipc_tx_base == 0U) || (bpmp_ipc.bpmp_ipc_rx_base == 0U) || + (bpmp_ipc.bpmp_ipc_map_size == 0U)) { + WARN("BPMP_IPC TX/RX memory is uninitialized\n"); + return NULL; + } + + /* + * Assert with the tx_base (or) rx end address is not with in sysram range. + */ + rx_end_addr = bpmp_ipc.bpmp_ipc_rx_base + TEGRA_BPMP_IPC_CH_MAP_SIZE; + sysram_end_addr = TEGRA_SYSRAM_BASE + TEGRA_SYSRAM_SIZE; + assert((bpmp_ipc.bpmp_ipc_tx_base >= TEGRA_SYSRAM_BASE) && (rx_end_addr < sysram_end_addr)); + + return &bpmp_ipc; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c new file mode 100644 index 0000000..0bb3779 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* + * tegra_fake_system_suspend acts as a boolean variable controlling whether + * we are going to take fake system suspend code or normal system suspend code + * path. This variable is set inside the sip call handlers, when the kernel + * requests a SIP call to set the suspend debug flags. + */ +bool tegra234_fake_system_suspend = false; + +/******************************************************************************* + * Tegra234 SiP SMCs + ******************************************************************************/ +#define TEGRA_SIP_WRITE_PFG_REGS 0xC200FF01 +#define TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND 0xC2FFFE03 + +/******************************************************************************* + * This function is responsible for handling all T194 SiP calls + ******************************************************************************/ +int32_t plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + const void *cookie, + void *handle, + uint64_t flags) +{ + int32_t ret = 0; + + (void)x1; + (void)x4; + (void)cookie; + (void)flags; + + switch (smc_fid) { +#if RAS_EXTENSION && DEBUG + case TEGRA_SIP_WRITE_PFG_REGS: + ret = tegra234_ras_inject_fault(x1, x2, x3); + break; +#endif + case TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND: + /* + * System suspend fake mode is set if we are on FPGA and we make + * a debug SIP call. This mode ensures that we exercise debug + * path instead of the regular code path to suit the pre-silicon + * platform needs. These include replacing the call to WFI by + * a warm reset request. + */ + if (tegra_platform_is_fpga() || tegra_platform_is_virt_dev_kit()) { + tegra234_fake_system_suspend = true; + } else { + /* + * Set to not support if we are not on FPGA or VDK. + */ + ret = -ENOTSUP; + } + + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/platform_t234.mk b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/platform_t234.mk new file mode 100644 index 0000000..88bf019 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/platform_t234.mk @@ -0,0 +1,97 @@ +# +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# platform configs +ENABLE_CONSOLE_SPE := 1 +$(eval $(call add_define,ENABLE_CONSOLE_SPE)) + +ENABLE_STRICT_CHECKING_MODE := 0 +$(eval $(call add_define,ENABLE_STRICT_CHECKING_MODE)) + +USE_GPC_DMA := 0 +$(eval $(call add_define,USE_GPC_DMA)) + +RESET_TO_BL31 := 1 + +COLD_BOOT_SINGLE_CPU := 1 + +# platform settings +PLAT_BL31_BASE := 0x50000000 +$(eval $(call add_define,PLAT_BL31_BASE)) + +PLATFORM_CLUSTER_COUNT := 3 +$(eval $(call add_define,PLATFORM_CLUSTER_COUNT)) + +PLATFORM_MAX_CPUS_PER_CLUSTER := 4 +$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER)) + +MAX_XLAT_TABLES := 25 +$(eval $(call add_define,MAX_XLAT_TABLES)) + +MAX_MMAP_REGIONS := 30 +$(eval $(call add_define,MAX_MMAP_REGIONS)) + +WORKAROUND_CVE_2017_5715 := 0 + +DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 + +CTX_INCLUDE_AARCH32_REGS := 0 + +HW_ASSISTED_COHERENCY := 1 + +# Keep RAS disabled until latest DSIM support is released +RAS_EXTENSION := 1 +HANDLE_EA_EL3_FIRST := 1 + +# Enable secure only access to GICT and GICP registers. +GICV3_RESTRICT_GICT_GICP_ACCESS := 1 +$(eval $(call add_define,GICV3_RESTRICT_GICT_GICP_ACCESS)) + +# Enable GIC600AE Fault Management Unit +GICV3_SUPPORT_GIC600AE_FMU := 1 + +# include common makefiles +include plat/nvidia/tegra/common/tegra_common.mk + +# platform files +PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t234 \ + -I${SOC_DIR}/drivers/include + +BL31_SOURCES += ${TEGRA_GICv3_SOURCES} \ + lib/cpus/aarch64/cortex_a78_ae.S \ + ${TEGRA_DRIVERS}/bpmp_ipc/intf.c \ + ${TEGRA_DRIVERS}/bpmp_ipc/ivc.c \ + ${TEGRA_DRIVERS}/gpcdma/gpcdma.c \ + ${TEGRA_DRIVERS}/memctrl/memctrl_v2.c \ + ${TEGRA_DRIVERS}/psc/psc_mailbox.c \ + ${SOC_DIR}/drivers/mce/mce.c \ + ${SOC_DIR}/drivers/mce/ari.c \ + ${SOC_DIR}/drivers/se/se.c \ + ${SOC_DIR}/plat_memctrl.c \ + ${SOC_DIR}/plat_psci_handlers.c \ + ${SOC_DIR}/plat_setup.c \ + ${SOC_DIR}/plat_secondary.c \ + ${SOC_DIR}/plat_sip_calls.c + +ifeq (${ENABLE_CONSOLE_SPE}, 1) +BL31_SOURCES += ${TEGRA_DRIVERS}/spe/shared_console.S +else +BL31_SOURCES += drivers/ti/uart/aarch64/16550_console.S +endif + +# Pointer Authentication sources +ifeq (${ENABLE_PAUTH},1) +CTX_INCLUDE_PAUTH_REGS := 1 +BL31_SOURCES += plat/nvidia/tegra/common/tegra_pauth.c \ + lib/extensions/pauth/pauth_helpers.S +endif + +# RAS sources +ifeq (${RAS_EXTENSION},1) +BL31_SOURCES += lib/extensions/ras/std_err_record.c \ + lib/extensions/ras/ras_common.c \ + ${SOC_DIR}/plat_ras.c +endif diff --git a/arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S b/arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S new file mode 100644 index 0000000..cc91540 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S @@ -0,0 +1,558 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include "bl31_data.h" +#include "plat_psci.h" +#include "platform_def.h" + +.global _getCoreData +.global _setCoreData +.global _getCoreState +.global _setCoreState +.global _init_global_data +.global _get_global_data +.global _set_global_data +.global _initialize_psci +.global _init_task_flags +.global _set_task1_start +.global _set_task1_done + + +/* Function returns the specified data field value from the specified cpu + * core data area + * in: x0 = core mask lsb + * x1 = data field name/offset + * out: x0 = data value + * uses x0, x1, x2, [x13, x14, x15] + */ +func _getCoreData + + /* generate a 0-based core number from the input mask */ + clz x2, x0 + mov x0, #63 + sub x0, x0, x2 + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + + /* determine if this is bootcore or secondary core */ + cbnz x0, 1f + + /* get base address for bootcore data */ + ldr x2, =BC_PSCI_BASE + add x2, x2, x1 + b 2f + +1: /* get base address for secondary core data */ + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + + /* generate number of regions to offset */ + mov x2, #SEC_REGION_SIZE + mul x2, x2, x0 + + /* x1 = field offset */ + /* x2 = region offset */ + + /* generate the total offset to data element */ + sub x1, x2, x1 + + /* x1 = total offset to data element */ + + /* get the base address */ + ldr x2, =SECONDARY_TOP + + /* apply offset to base addr */ + sub x2, x2, x1 +2: + /* x2 = data element address */ + + dc ivac, x2 + dsb sy + isb + /* read data */ + ldr x0, [x2] + + ret +endfunc _getCoreData + + +/* Function returns the SoC-specific state of the specified cpu + * in: x0 = core mask lsb + * out: x0 = data value + * uses x0, x1, x2, [x13, x14, x15] + */ +func _getCoreState + + mov x1, #CORE_STATE_DATA + + /* generate a 0-based core number from the input mask */ + clz x2, x0 + mov x0, #63 + sub x0, x0, x2 + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + + /* determine if this is bootcore or secondary core */ + cbnz x0, 1f + + /* get base address for bootcore data */ + ldr x2, =BC_PSCI_BASE + add x2, x2, x1 + b 2f + +1: /* get base address for secondary core data */ + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + + /* generate number of regions to offset */ + mov x2, #SEC_REGION_SIZE + mul x2, x2, x0 + + /* x1 = field offset */ + /* x2 = region offset */ + + /* generate the total offset to data element */ + sub x1, x2, x1 + + /* x1 = total offset to data element */ + + /* get the base address */ + ldr x2, =SECONDARY_TOP + + /* apply offset to base addr */ + sub x2, x2, x1 +2: + /* x2 = data element address */ + + dc ivac, x2 + dsb sy + isb + + /* read data */ + ldr x0, [x2] + + ret +endfunc _getCoreState + + +/* Function writes the specified data value into the specified cpu + * core data area + * in: x0 = core mask lsb + * x1 = data field offset + * x2 = data value to write/store + * out: none + * uses x0, x1, x2, x3, [x13, x14, x15] + */ +func _setCoreData + /* x0 = core mask */ + /* x1 = field offset */ + /* x2 = data value */ + + clz x3, x0 + mov x0, #63 + sub x0, x0, x3 + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + /* x2 = data value */ + + /* determine if this is bootcore or secondary core */ + cbnz x0, 1f + + /* get base address for bootcore data */ + ldr x3, =BC_PSCI_BASE + add x3, x3, x1 + b 2f + +1: /* get base address for secondary core data */ + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + /* x2 = data value */ + + /* generate number of regions to offset */ + mov x3, #SEC_REGION_SIZE + mul x3, x3, x0 + + /* x1 = field offset */ + /* x2 = data value */ + /* x3 = region offset */ + + /* generate the total offset to data element */ + sub x1, x3, x1 + + /* x1 = total offset to data element */ + /* x2 = data value */ + + ldr x3, =SECONDARY_TOP + + /* apply offset to base addr */ + sub x3, x3, x1 + +2: + /* x2 = data value */ + /* x3 = data element address */ + + str x2, [x3] + + dc cvac, x3 + dsb sy + isb + ret +endfunc _setCoreData + + +/* Function stores the specified core state + * in: x0 = core mask lsb + * x1 = data value to write/store + * out: none + * uses x0, x1, x2, x3, [x13, x14, x15] + */ +func _setCoreState + mov x2, #CORE_STATE_DATA + + clz x3, x0 + mov x0, #63 + sub x0, x0, x3 + + /* x0 = core number (0-based) */ + /* x1 = data value */ + /* x2 = field offset */ + + /* determine if this is bootcore or secondary core */ + cbnz x0, 1f + + /* get base address for bootcore data */ + ldr x3, =BC_PSCI_BASE + add x3, x3, x2 + b 2f + +1: /* get base address for secondary core data */ + + /* x0 = core number (0-based) */ + /* x1 = data value */ + /* x2 = field offset */ + + /* generate number of regions to offset */ + mov x3, #SEC_REGION_SIZE + mul x3, x3, x0 + + /* x1 = data value */ + /* x2 = field offset */ + /* x3 = region offset */ + + /* generate the total offset to data element */ + sub x2, x3, x2 + + /* x1 = data value */ + /* x2 = total offset to data element */ + + ldr x3, =SECONDARY_TOP + + /* apply offset to base addr */ + sub x3, x3, x2 + +2: + /* x1 = data value */ + /* x3 = data element address */ + + str x1, [x3] + + dc civac, x3 + dsb sy + isb + ret +endfunc _setCoreState + + +/* Function sets the task1 start + * in: w0 = value to set flag to + * out: none + * uses x0, x1 + */ +func _set_task1_start + + ldr x1, =SMC_TASK1_BASE + + add x1, x1, #TSK_START_OFFSET + str w0, [x1] + dc cvac, x1 + dsb sy + isb + ret +endfunc _set_task1_start + + +/* Function sets the state of the task 1 done flag + * in: w0 = value to set flag to + * out: none + * uses x0, x1 + */ +func _set_task1_done + + ldr x1, =SMC_TASK1_BASE + + add x1, x1, #TSK_DONE_OFFSET + str w0, [x1] + dc cvac, x1 + dsb sy + isb + ret +endfunc _set_task1_done + + +/* Function initializes the smc global data entries + * Note: the constant LAST_SMC_GLBL_OFFSET must reference the last entry in the + * smc global region + * in: none + * out: none + * uses x0, x1, x2 + */ +func _init_global_data + + ldr x1, =SMC_GLBL_BASE + + /* x1 = SMC_GLBL_BASE */ + + mov x2, #LAST_SMC_GLBL_OFFSET + add x2, x2, x1 +1: + str xzr, [x1] + dc cvac, x1 + cmp x2, x1 + add x1, x1, #8 + b.hi 1b + + dsb sy + isb + ret +endfunc _init_global_data + + +/* Function gets the value of the specified global data element + * in: x0 = offset of data element + * out: x0 = requested data element + * uses x0, x1 + */ +func _get_global_data + + ldr x1, =SMC_GLBL_BASE + add x1, x1, x0 + dc ivac, x1 + isb + + ldr x0, [x1] + ret +endfunc _get_global_data + + +/* Function sets the value of the specified global data element + * in: x0 = offset of data element + * x1 = value to write + * out: none + * uses x0, x1, x2 + */ +func _set_global_data + + ldr x2, =SMC_GLBL_BASE + add x0, x0, x2 + str x1, [x0] + dc cvac, x0 + + dsb sy + isb + ret +endfunc _set_global_data + + +/* Function initializes the core data areas + * only executed by the boot core + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6, x7, [x13, x14, x15] + */ +func _initialize_psci + mov x7, x30 + + /* initialize the bootcore psci data */ + ldr x5, =BC_PSCI_BASE + mov x6, #CORE_RELEASED + + str x6, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5] + dc cvac, x5 + dsb sy + isb + + /* see if we have any secondary cores */ + mov x4, #PLATFORM_CORE_COUNT + sub x4, x4, #1 + cbz x4, 3f + + /* initialize the secondary core's psci data */ + ldr x5, =SECONDARY_TOP + /* core mask lsb for core 1 */ + mov x3, #2 + sub x5, x5, #SEC_REGION_SIZE + + /* x3 = core1 mask lsb */ + /* x4 = number of secondary cores */ + /* x5 = core1 psci data base address */ +2: + /* set core state in x6 */ + mov x0, x3 + mov x6, #CORE_IN_RESET + bl _soc_ck_disabled + cbz x0, 1f + mov x6, #CORE_DISABLED +1: + add x2, x5, #CORE_STATE_DATA + str x6, [x2] + dc cvac, x2 + add x2, x5, #SPSR_EL3_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #CNTXT_ID_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #START_ADDR_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #LINK_REG_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #GICC_CTLR_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #ABORT_FLAG_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #SCTLR_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #CPUECTLR_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_01_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_02_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_03_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_04_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_05_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #SCR_EL3_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #HCR_EL2_DATA + str xzr, [x2] + dc cvac, x2 + dsb sy + isb + + sub x4, x4, #1 + cbz x4, 3f + + /* generate next core mask */ + lsl x3, x3, #1 + + /* decrement base address to next data area */ + sub x5, x5, #SEC_REGION_SIZE + b 2b +3: + mov x30, x7 + ret +endfunc _initialize_psci + + +/* Function initializes the soc init task flags + * in: none + * out: none + * uses x0, x1, [x13, x14, x15] + */ +func _init_task_flags + + /* get the base address of the first task structure */ + ldr x0, =SMC_TASK1_BASE + + /* x0 = task1 base address */ + + str wzr, [x0, #TSK_START_OFFSET] + str wzr, [x0, #TSK_DONE_OFFSET] + str wzr, [x0, #TSK_CORE_OFFSET] + dc cvac, x0 + + /* move to task2 structure */ + add x0, x0, #SMC_TASK_OFFSET + + str wzr, [x0, #TSK_START_OFFSET] + str wzr, [x0, #TSK_DONE_OFFSET] + str wzr, [x0, #TSK_CORE_OFFSET] + dc cvac, x0 + + /* move to task3 structure */ + add x0, x0, #SMC_TASK_OFFSET + + str wzr, [x0, #TSK_START_OFFSET] + str wzr, [x0, #TSK_DONE_OFFSET] + str wzr, [x0, #TSK_CORE_OFFSET] + dc cvac, x0 + + /* move to task4 structure */ + add x0, x0, #SMC_TASK_OFFSET + + str wzr, [x0, #TSK_START_OFFSET] + str wzr, [x0, #TSK_DONE_OFFSET] + str wzr, [x0, #TSK_CORE_OFFSET] + dc cvac, x0 + + dsb sy + isb + ret +endfunc _init_task_flags diff --git a/arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S b/arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S new file mode 100644 index 0000000..311dce1 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S @@ -0,0 +1,220 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include + + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_core_pos + .globl plat_my_core_pos + .globl plat_core_mask + .globl plat_my_core_mask + .globl plat_core_pos_by_mpidr + .globl _disable_ldstr_pfetch_A53 + .globl _disable_ldstr_pfetch_A72 + .global _set_smmu_pagesz_64 + + /* int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + */ + + /* int plat_crash_console_init(void) + * Use normal console by default. Switch it to crash + * mode so serial consoles become active again. + * NOTE: This default implementation will only work for + * crashes that occur after a normal console (marked + * valid for the crash state) has been registered with + * the console framework. To debug crashes that occur + * earlier, the platform has to override these functions + * with an implementation that initializes a console + * driver with hardcoded parameters. See + * docs/porting-guide.rst for more information. + */ +func plat_crash_console_init + mov x3, x30 + mov x0, #CONSOLE_FLAG_CRASH + bl console_switch_state + mov x0, #1 + ret x3 +endfunc plat_crash_console_init + + /* void plat_crash_console_putc(int character) + * Output through the normal console by default. + */ +func plat_crash_console_putc + b console_putc +endfunc plat_crash_console_putc + + /* void plat_crash_console_flush(void) + * Flush normal console by default. + */ +func plat_crash_console_flush + b console_flush +endfunc plat_crash_console_flush + +/* This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + */ +func plat_core_pos_by_mpidr + + b plat_core_pos + +endfunc plat_core_pos_by_mpidr + +#if (SYMMETRICAL_CLUSTERS) +/* unsigned int plat_my_core_mask(void) + * generate a mask bit for this core + */ +func plat_my_core_mask + mrs x0, MPIDR_EL1 + b plat_core_mask +endfunc plat_my_core_mask + +/* unsigned int plat_core_mask(u_register_t mpidr) + * generate a lsb-based mask bit for the core specified by mpidr in x0. + * + * SoC core = ((cluster * cpu_per_cluster) + core) + * mask = (1 << SoC core) + */ +func plat_core_mask + mov w1, wzr + mov w2, wzr + + /* extract cluster */ + bfxil w1, w0, #8, #8 + /* extract cpu # */ + bfxil w2, w0, #0, #8 + + mov w0, wzr + + /* error checking */ + cmp w1, #NUMBER_OF_CLUSTERS + b.ge 1f + cmp w2, #CORES_PER_CLUSTER + b.ge 1f + + mov w0, #CORES_PER_CLUSTER + mul w1, w1, w0 + add w1, w1, w2 + mov w2, #0x1 + lsl w0, w2, w1 +1: + ret +endfunc plat_core_mask + +/* + * unsigned int plat_my_core_pos(void) + * generate a linear core number for this core + */ +func plat_my_core_pos + mrs x0, MPIDR_EL1 + b plat_core_pos +endfunc plat_my_core_pos + +/* + * unsigned int plat_core_pos(u_register_t mpidr) + * Generate a linear core number for the core specified by mpidr. + * + * SoC core = ((cluster * cpu_per_cluster) + core) + * Returns -1 if mpidr invalid + */ +func plat_core_pos + mov w1, wzr + mov w2, wzr + bfxil w1, w0, #8, #8 /* extract cluster */ + bfxil w2, w0, #0, #8 /* extract cpu # */ + + mov w0, #-1 + + /* error checking */ + cmp w1, #NUMBER_OF_CLUSTERS + b.ge 1f + cmp w2, #CORES_PER_CLUSTER + b.ge 1f + + mov w0, #CORES_PER_CLUSTER + mul w1, w1, w0 + add w0, w1, w2 +1: + ret +endfunc plat_core_pos + +#endif + +/* this function disables the load-store prefetch of the calling core + * Note: this function is for A53 cores ONLY + * in: none + * out: none + * uses x0 + */ +func _disable_ldstr_pfetch_A53 + mrs x0, CORTEX_A53_CPUACTLR_EL1 + tst x0, #CORTEX_A53_CPUACTLR_EL1_L1PCTL + b.ne 1f + b 2f + +.align 6 +1: + dsb sy + isb + bic x0, x0, #CORTEX_A53_CPUACTLR_EL1_L1PCTL + msr CORTEX_A53_CPUACTLR_EL1, x0 + isb + +2: + ret +endfunc _disable_ldstr_pfetch_A53 + + +/* this function disables the load-store prefetch of the calling core + * Note: this function is for A72 cores ONLY + * in: none + * out: none + * uses x0 + */ +func _disable_ldstr_pfetch_A72 + + mrs x0, CORTEX_A72_CPUACTLR_EL1 + tst x0, #CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH + b.eq 1f + b 2f + +.align 6 +1: + dsb sy + isb + orr x0, x0, #CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH + msr CORTEX_A72_CPUACTLR_EL1, x0 + isb + +2: + ret +endfunc _disable_ldstr_pfetch_A72 + +/* + * Function sets the SACR pagesize to 64k + */ +func _set_smmu_pagesz_64 + + ldr x1, =NXP_SMMU_ADDR + ldr w0, [x1, #0x10] + orr w0, w0, #1 << 16 /* setting to 64K page */ + str w0, [x1, #0x10] + + ret +endfunc _set_smmu_pagesz_64 diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h new file mode 100644 index 0000000..65aef14 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h @@ -0,0 +1,51 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEF_FIP_UUID_H +#define PLAT_DEF_FIP_UUID_H + +/* PHy images configs */ +#define UUID_DDR_IMEM_UDIMM_1D \ + {{0x5b, 0xdb, 0xe3, 0x83}, {0xd1, 0x9f}, {0xc7, 0x06}, 0xd4, 0x91, {0x76, 0x4f, 0x9d, 0x23, 0x2d, 0x2d} } + +#define UUID_DDR_IMEM_UDIMM_2D \ + {{0xfa, 0x0e, 0xeb, 0x21}, {0xe0, 0x7f}, {0x8e, 0x65}, 0x95, 0xd8, {0x2b, 0x94, 0xf6, 0xb8, 0x28, 0x0a} } + +#define UUID_DDR_DMEM_UDIMM_1D \ + {{0xba, 0xbb, 0xfd, 0x7e}, {0x5b, 0xf0}, {0xeb, 0xb8}, 0xeb, 0x71, {0xb1, 0x85, 0x07, 0xdd, 0xe1, 0x32} } + +#define UUID_DDR_DMEM_UDIMM_2D \ + {{0xb6, 0x99, 0x61, 0xda}, {0xf9, 0x92}, {0x4b, 0x9e}, 0x0c, 0x49, {0x74, 0xa5, 0xe0, 0x5c, 0xbe, 0xc3} } + +#define UUID_DDR_IMEM_RDIMM_1D \ + {{0x42, 0x33, 0x66, 0x52}, {0xd8, 0x94}, {0x4d, 0xc1}, 0x91, 0xcc, {0x26, 0x8f, 0x7a, 0x67, 0xf1, 0xa2} } + +#define UUID_DDR_IMEM_RDIMM_2D \ + {{0x2e, 0x95, 0x73, 0xba}, {0xb5, 0xca}, {0x7c, 0xc7}, 0xef, 0xc9, {0x5e, 0xb0, 0x42, 0xec, 0x08, 0x7a} } + +#define UUID_DDR_DMEM_RDIMM_1D \ + {{0x1c, 0x51, 0x17, 0xed}, {0x30, 0x0d}, {0xae, 0xba}, 0x87, 0x03, {0x1f, 0x37, 0x85, 0xec, 0xe1, 0x44} } + +#define UUID_DDR_DMEM_RDIMM_2D \ + {{0xe9, 0x0a, 0x90, 0x78}, {0x11, 0xd6}, {0x8b, 0xba}, 0x24, 0x35, {0xec, 0x10, 0x75, 0x4f, 0x56, 0xa5} } + +#define UUID_DDR_FW_KEY_CERT \ + {{0xac, 0x4b, 0xb8, 0x9c}, {0x8f, 0xb9}, {0x11, 0xea}, 0xbc, 0x55, {0x02, 0x42, 0xac, 0x12, 0x00, 0x03} } + +#define UUID_DDR_UDIMM_FW_CONTENT_CERT \ + {{0x2c, 0x7f, 0x52, 0x54}, {0x70, 0x92}, {0x48, 0x40}, 0x8c, 0x34, {0x87, 0x4b, 0xbf, 0xbd, 0x9d, 0x89} } + +#define UUID_DDR_RDIMM_FW_CONTENT_CERT \ + {{0x94, 0xc3, 0x63, 0x30}, {0x7c, 0xf7}, {0x4f, 0x1d}, 0xaa, 0xcd, {0xb5, 0x80, 0xb2, 0xc2, 0x40, 0xa5} } + +#define UUID_FUSE_PROV \ + {{0xec, 0x45, 0x90, 0x42}, {0x30, 0x0d}, {0xae, 0xba}, 0x87, 0x03, {0x1f, 0x37, 0x85, 0xec, 0xe1, 0x44} } + +#define UUID_FUSE_UP \ + {{0x89, 0x46, 0xef, 0x78}, {0x11, 0xd6}, {0x8b, 0xba}, 0x24, 0x35, {0xec, 0x10, 0x75, 0x4f, 0x56, 0xa5} } + +#endif /* PLAT_DEF_FIP_UUID_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h new file mode 100644 index 0000000..9856f70 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h @@ -0,0 +1,53 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef NXP_IMG_DEF_H +#define NXP_IMG_DEF_H + +#include + +#ifdef CONFIG_DDR_FIP_IMAGE +/* DDR FIP IMAGE ID */ +#define DDR_FIP_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + +#define DDR_IMEM_UDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 1 +#define DDR_IMEM_UDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 2 + +#define DDR_DMEM_UDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 3 +#define DDR_DMEM_UDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 4 + +#define DDR_IMEM_RDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 5 +#define DDR_IMEM_RDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 6 + +#define DDR_DMEM_RDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 7 +#define DDR_DMEM_RDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 8 + +#define DDR_FW_KEY_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 9 +#define DDR_UDIMM_FW_CONTENT_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 10 +#define DDR_RDIMM_FW_CONTENT_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 11 +/* Max Images */ +#define MAX_IMG_WITH_DDR_IDS MAX_IMG_IDS_WITH_SPMDS + 12 +#else +#define MAX_IMG_WITH_DDR_IDS MAX_IMG_IDS_WITH_SPMDS +#endif + +#ifdef POLICY_FUSE_PROVISION +/* FUSE FIP IMAGE ID */ +#define FUSE_FIP_IMAGE_ID MAX_IMG_WITH_DDR_IDS + +#define FUSE_PROV_IMAGE_ID MAX_IMG_WITH_DDR_IDS + 1 + +#define FUSE_UP_IMAGE_ID MAX_IMG_WITH_DDR_IDS + 2 + +#define MAX_IMG_WITH_FIMG_IDS MAX_IMG_WITH_DDR_IDS + 3 +#else +#define MAX_IMG_WITH_FIMG_IDS MAX_IMG_WITH_DDR_IDS +#endif + +#define MAX_NUMBER_IDS MAX_IMG_WITH_FIMG_IDS + +#endif /* NXP_IMG_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h new file mode 100644 index 0000000..bbd6041 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h @@ -0,0 +1,16 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#define DDR_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2200.1" +#define DDR_IMEM_UDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.2" +#define DDR_IMEM_UDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.3" +#define DDR_DMEM_UDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.4" +#define DDR_DMEM_UDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.5" +#define DDR_IMEM_RDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.6" +#define DDR_IMEM_RDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.7" +#define DDR_DMEM_RDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.8" +#define DDR_DMEM_RDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.9" diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk new file mode 100644 index 0000000..7d673ba --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk @@ -0,0 +1,38 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${DDR_FIP_IO_STORAGE_ADDED},) + +$(eval $(call add_define, PLAT_DEF_FIP_UUID)) +$(eval $(call add_define, PLAT_TBBR_IMG_DEF)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +DDR_FIP_IO_STORAGE_ADDED := 1 +$(eval $(call add_define,CONFIG_DDR_FIP_IMAGE)) + +FIP_HANDLER_PATH := ${PLAT_COMMON_PATH}/fip_handler +FIP_HANDLER_COMMON_PATH := ${FIP_HANDLER_PATH}/common +DDR_FIP_IO_STORAGE_PATH := ${FIP_HANDLER_PATH}/ddr_fip + +PLAT_INCLUDES += -I${FIP_HANDLER_COMMON_PATH}\ + -I$(DDR_FIP_IO_STORAGE_PATH) + +DDR_FIP_IO_SOURCES += $(DDR_FIP_IO_STORAGE_PATH)/ddr_io_storage.c + +$(shell cp tools/nxp/plat_fiptool/plat_fiptool.mk ${PLAT_DIR}) + +ifeq (${BL_COMM_DDR_FIP_IO_NEEDED},yes) +BL_COMMON_SOURCES += ${DDR_FIP_IO_SOURCES} +else +ifeq (${BL2_DDR_FIP_IO_NEEDED},yes) +BL2_SOURCES += ${DDR_FIP_IO_SOURCES} +endif +ifeq (${BL31_DDR_FIP_IO_NEEDED},yes) +BL31_SOURCES += ${DDR_FIP_IO_SOURCES} +endif +endif +endif +#------------------------------------------------ diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c new file mode 100644 index 0000000..fc3c4a4 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c @@ -0,0 +1,232 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "ddr_io_storage.h" +#include "plat_common.h" +#include "platform_def.h" + + +/* TBD - Move these defined to the platform_def.h file. + * Keeping them for reference here + */ +extern uintptr_t backend_dev_handle; + +static uint32_t ddr_fip; + +static uintptr_t ddr_fip_dev_handle; + +static io_block_spec_t ddr_fip_block_spec = { + .offset = PLAT_DDR_FIP_OFFSET, + .length = PLAT_DDR_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t ddr_imem_udimm_1d_uuid_spec = { + .uuid = UUID_DDR_IMEM_UDIMM_1D, +}; + +static const io_uuid_spec_t ddr_imem_udimm_2d_uuid_spec = { + .uuid = UUID_DDR_IMEM_UDIMM_2D, +}; + +static const io_uuid_spec_t ddr_dmem_udimm_1d_uuid_spec = { + .uuid = UUID_DDR_DMEM_UDIMM_1D, +}; + +static const io_uuid_spec_t ddr_dmem_udimm_2d_uuid_spec = { + .uuid = UUID_DDR_DMEM_UDIMM_2D, +}; + +static const io_uuid_spec_t ddr_imem_rdimm_1d_uuid_spec = { + .uuid = UUID_DDR_IMEM_RDIMM_1D, +}; + +static const io_uuid_spec_t ddr_imem_rdimm_2d_uuid_spec = { + .uuid = UUID_DDR_IMEM_RDIMM_2D, +}; + +static const io_uuid_spec_t ddr_dmem_rdimm_1d_uuid_spec = { + .uuid = UUID_DDR_DMEM_RDIMM_1D, +}; + +static const io_uuid_spec_t ddr_dmem_rdimm_2d_uuid_spec = { + .uuid = UUID_DDR_DMEM_RDIMM_2D, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t ddr_fw_key_cert_uuid_spec = { + .uuid = UUID_DDR_FW_KEY_CERT, +}; +static const io_uuid_spec_t ddr_udimm_fw_cert_uuid_spec = { + .uuid = UUID_DDR_UDIMM_FW_CONTENT_CERT, +}; +static const io_uuid_spec_t ddr_rdimm_fw_cert_uuid_spec = { + .uuid = UUID_DDR_RDIMM_FW_CONTENT_CERT, +}; +#endif + +static int open_ddr_fip(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, ARM platforms load images from the FIP */ +static const struct plat_io_policy ddr_policies[] = { + [DDR_FIP_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &backend_dev_handle, + (uintptr_t)&ddr_fip_block_spec, + NULL + }, + [DDR_IMEM_UDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_imem_udimm_1d_uuid_spec, + open_ddr_fip + }, + [DDR_IMEM_UDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_imem_udimm_2d_uuid_spec, + open_ddr_fip + }, + [DDR_DMEM_UDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_dmem_udimm_1d_uuid_spec, + open_ddr_fip + }, + [DDR_DMEM_UDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_dmem_udimm_2d_uuid_spec, + open_ddr_fip + }, + [DDR_IMEM_RDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_imem_rdimm_1d_uuid_spec, + open_ddr_fip + }, + [DDR_IMEM_RDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_imem_rdimm_2d_uuid_spec, + open_ddr_fip + }, + [DDR_DMEM_RDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_dmem_rdimm_1d_uuid_spec, + open_ddr_fip + }, + [DDR_DMEM_RDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_dmem_rdimm_2d_uuid_spec, + open_ddr_fip + }, +#if TRUSTED_BOARD_BOOT + [DDR_FW_KEY_CERT_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_fw_key_cert_uuid_spec, + open_ddr_fip + }, + [DDR_UDIMM_FW_CONTENT_CERT_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_udimm_fw_cert_uuid_spec, + open_ddr_fip + }, + [DDR_RDIMM_FW_CONTENT_CERT_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_rdimm_fw_cert_uuid_spec, + open_ddr_fip + }, +#endif +}; + +static int open_ddr_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(ddr_fip_dev_handle, (uintptr_t)DDR_FIP_IMAGE_ID); + if (result == 0) { + result = io_open(ddr_fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +/* The image can be one of the DDR PHY images, which can be sleected via DDR + * policies + */ +int plat_get_ddr_fip_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec, + int (*check)(const uintptr_t spec)) +{ + int result = -1; + const struct plat_io_policy *policy; + + if (image_id >= (DDR_FIP_IMAGE_ID + ARRAY_SIZE(ddr_policies))) { + return result; + } + + policy = &ddr_policies[image_id - DDR_FIP_IMAGE_ID]; + if (image_id == DDR_FIP_IMAGE_ID) { + result = check(policy->image_spec); + } else { + result = policy->check(policy->image_spec); + } + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + return result; +} + +int ddr_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev) +{ + int io_result; + size_t ddr_fip_offset = PLAT_DDR_FIP_OFFSET; + + /* Open connections to ddr fip and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)&ddr_fip, + &ddr_fip_dev_handle); + assert(io_result == 0); + + switch (boot_dev) { +#if QSPI_BOOT + case BOOT_DEVICE_QSPI: + ddr_fip_offset += NXP_QSPI_FLASH_ADDR; + break; +#endif +#if NOR_BOOT + case BOOT_DEVICE_IFC_NOR: + ddr_fip_offset += NXP_NOR_FLASH_ADDR; + break; +#endif +#if FLEXSPI_NOR_BOOT + case BOOT_DEVICE_FLEXSPI_NOR: + ddr_fip_offset += NXP_FLEXSPI_FLASH_ADDR; + break; +#endif + default: + break; + } + + ddr_fip_block_spec.offset = ddr_fip_offset; + + return io_result; +} diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h new file mode 100644 index 0000000..6df3902 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h @@ -0,0 +1,26 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_IO_STORAGE_H +#define DDR_IO_STORAGE_H + +#include + +#ifndef PLAT_DDR_FIP_OFFSET +#define PLAT_DDR_FIP_OFFSET 0x800000 +#endif + +#ifndef PLAT_DDR_FIP_MAX_SIZE +#define PLAT_DDR_FIP_MAX_SIZE 0x32000 +#endif + +int ddr_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev); +int plat_get_ddr_fip_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec, + int (*check)(const uintptr_t spec)); + +#endif /* DDR_IO_STORAGE_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse.mk b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse.mk new file mode 100644 index 0000000..d8f5ae6 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse.mk @@ -0,0 +1,100 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +NEED_FUSE := yes + +$(eval $(call add_define, PLAT_DEF_FIP_UUID)) +$(eval $(call add_define, POLICY_FUSE_PROVISION)) +$(eval $(call add_define, PLAT_TBBR_IMG_DEF)) + +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,GPIO_NEEDED,BL2)) + +FIP_HANDLER_PATH := ${PLAT_COMMON_PATH}/fip_handler +FIP_HANDLER_COMMON_PATH := ${FIP_HANDLER_PATH}/common + +FUSE_SOURCES := ${FIP_HANDLER_PATH}/fuse_fip/fuse_io_storage.c + +PLAT_INCLUDES += -I${FIP_HANDLER_COMMON_PATH}\ + -I${FIP_HANDLER_PATH}/fuse_fip + +FUSE_FIP_NAME := fuse_fip.bin + +fip_fuse: ${BUILD_PLAT}/${FUSE_FIP_NAME} + +ifeq (${FUSE_PROV_FILE},) + +$(shell cp tools/nxp/plat_fiptool/plat_fiptool.mk ${PLAT_DIR}) + +else +ifeq (${TRUSTED_BOARD_BOOT},1) +FUSE_PROV_FILE_SB = $(notdir ${FUSE_PROV_FILE})_prov.sb +FUSE_FIP_ARGS += --fuse-prov ${BUILD_PLAT}/${FUSE_PROV_FILE_SB} +FUSE_FIP_DEPS += ${BUILD_PLAT}/${FUSE_PROV_FILE_SB} +else +FUSE_FIP_ARGS += --fuse-prov ${FUSE_PROV_FILE} +FUSE_FIP_DEPS += ${FUSE_PROV_FILE} +endif +endif + +ifeq (${FUSE_UP_FILE},) +else +ifeq (${TRUSTED_BOARD_BOOT},1) +FUSE_UP_FILE_SB = $(notdir ${FUSE_UP_FILE})_up.sb +FUSE_FIP_ARGS += --fuse-up ${BUILD_PLAT}/${FUSE_UP_FILE_SB} +FUSE_FIP_DEPS += ${BUILD_PLAT}/${FUSE_UP_FILE_SB} +else +FUSE_FIP_ARGS += --fuse-up ${FUSE_UP_FILE} +FUSE_FIP_DEPS += ${FUSE_UP_FILE} +endif +endif + +ifeq (${TRUSTED_BOARD_BOOT},1) + +ifeq (${MBEDTLS_DIR},) +else + $(error Error: Trusted Board Boot with X509 certificates not supported with FUSE_PROG build option) +endif + +# Path to CST directory is required to generate the CSF header +# and prepend it to image before fip image gets generated +ifeq (${CST_DIR},) + $(error Error: CST_DIR not set) +endif + +ifeq (${FUSE_INPUT_FILE},) +FUSE_INPUT_FILE := $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/${CSF_FILE} +endif + +ifeq (${FUSE_PROV_FILE},) +else +${BUILD_PLAT}/${FUSE_PROV_FILE_SB}: ${FUSE_PROV_FILE} + @echo " Generating CSF Header for $@ $<" + $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \ + --app $< ${FUSE_INPUT_FILE} +endif + +ifeq (${FUSE_UP_FILE},) +else +${BUILD_PLAT}/${FUSE_UP_FILE_SB}: ${FUSE_UP_FILE} + @echo " Generating CSF Header for $@ $<" + $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \ + --app $< ${FUSE_INPUT_FILE} +endif + +endif + +${BUILD_PLAT}/${FUSE_FIP_NAME}: fiptool ${FUSE_FIP_DEPS} +ifeq (${FUSE_FIP_DEPS},) + $(error "Error: FUSE_PROV_FILE or/and FUSE_UP_FILE needs to point to the right file") +endif + ${FIPTOOL} create ${FUSE_FIP_ARGS} $@ + ${FIPTOOL} info $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h new file mode 100644 index 0000000..e8775d0 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h @@ -0,0 +1,27 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef FUSE_IO_H +#define FUSE_IO_H + +#include + +/* Can be overridden from platform_def.h file. + */ +#ifndef PLAT_FUSE_FIP_OFFSET +#define PLAT_FUSE_FIP_OFFSET 0x880000 +#endif +#ifndef PLAT_FUSE_FIP_MAX_SIZE +#define PLAT_FUSE_FIP_MAX_SIZE 0x80000 +#endif + +int fip_fuse_provisioning(uintptr_t image_buf, uint32_t size); +int fuse_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev); +int plat_get_fuse_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec, + int (*check)(const uintptr_t spec)); +#endif /* FUSE_IO_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c new file mode 100644 index 0000000..017ffcf --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c @@ -0,0 +1,223 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fuse_io.h" +#include +#include +#include "plat_common.h" +#include "platform_def.h" + +extern uintptr_t backend_dev_handle; + +static uint32_t fuse_fip; + +static uintptr_t fuse_fip_dev_handle; + +static io_block_spec_t fuse_fip_block_spec = { + .offset = PLAT_FUSE_FIP_OFFSET, + .length = PLAT_FUSE_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t fuse_prov_uuid_spec = { + .uuid = UUID_FUSE_PROV, +}; + +static const io_uuid_spec_t fuse_up_uuid_spec = { + .uuid = UUID_FUSE_UP, +}; + +static int open_fuse_fip(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, ARM platforms load images from the FIP */ +static const struct plat_io_policy fuse_policies[] = { + [FUSE_FIP_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { + &backend_dev_handle, + (uintptr_t)&fuse_fip_block_spec, + NULL + }, + [FUSE_PROV_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { + &fuse_fip_dev_handle, + (uintptr_t)&fuse_prov_uuid_spec, + open_fuse_fip + }, + [FUSE_UP_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { + &fuse_fip_dev_handle, + (uintptr_t)&fuse_up_uuid_spec, + open_fuse_fip + } +}; + +static int open_fuse_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fuse_fip_dev_handle, (uintptr_t)FUSE_FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fuse_fip_dev_handle, + spec, + &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +/* The image can be one of the DDR PHY images, which can be sleected via DDR + * policies + */ +int plat_get_fuse_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec, + int (*check)(const uintptr_t spec)) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < (FUSE_FIP_IMAGE_ID + ARRAY_SIZE(fuse_policies))); + + policy = &fuse_policies[image_id - FUSE_FIP_IMAGE_ID]; + + if (image_id == FUSE_FIP_IMAGE_ID) { + result = check(policy->image_spec); + } else { + result = policy->check(policy->image_spec); + } + + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + return result; +} + +int fuse_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev) +{ + int io_result; + size_t fuse_fip_offset = PLAT_FUSE_FIP_OFFSET; + + /* Open connections to fuse fip and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)&fuse_fip, + &fuse_fip_dev_handle); + + assert(io_result == 0); + + switch (boot_dev) { +#if QSPI_BOOT + case BOOT_DEVICE_QSPI: + fuse_fip_offset += NXP_QSPI_FLASH_ADDR; + break; +#endif +#if NOR_BOOT + case BOOT_DEVICE_IFC_NOR: + fuse_fip_offset += NXP_NOR_FLASH_ADDR; + break; +#endif +#if FLEXSPI_NOR_BOOT + case BOOT_DEVICE_FLEXSPI_NOR: + fuse_fip_offset += NXP_FLEXSPI_FLASH_ADDR; + break; +#endif + default: + break; + } + + fuse_fip_block_spec.offset = fuse_fip_offset; + + return io_result; +} + +int fip_fuse_provisioning(uintptr_t image_buf, uint32_t size) +{ + uint32_t bit_num; + uint32_t *gpio_base_addr = NULL; + struct fuse_hdr_t *fuse_hdr = NULL; + uint8_t barker[] = {0x68U, 0x39U, 0x27U, 0x81U}; + int ret = -1; + + if (sfp_check_oem_wp() == 0) { + ret = load_img(FUSE_PROV_IMAGE_ID, &image_buf, &size); + if (ret != 0) { + ERROR("Failed to load FUSE PRIV image\n"); + assert(ret == 0); + } + fuse_hdr = (struct fuse_hdr_t *)image_buf; + + /* Check barker code */ + if (memcmp(fuse_hdr->barker, barker, sizeof(barker)) != 0) { + ERROR("FUSE Barker code mismatch.\n"); + error_handler(ERROR_FUSE_BARKER); + return 1; + } + + /* Check if GPIO pin to be set for POVDD */ + if (((fuse_hdr->flags >> FLAG_POVDD_SHIFT) & 0x1) != 0) { + gpio_base_addr = + select_gpio_n_bitnum(fuse_hdr->povdd_gpio, + &bit_num); + /* + * Add delay so that Efuse gets the power + * when GPIO is enabled. + */ + ret = set_gpio_bit(gpio_base_addr, bit_num); + mdelay(EFUSE_POWERUP_DELAY_mSec); + } else { + ret = (board_enable_povdd() == true) ? 0 : PLAT_ERROR_ENABLE_POVDD; + } + if (ret != 0) { + ERROR("Error enabling board POVDD: %d\n", ret); + ERROR("Only SFP mirror register will be set.\n"); + } + + provision_fuses(image_buf, ret == 0); + + /* Check if GPIO pin to be reset for POVDD */ + if (((fuse_hdr->flags >> FLAG_POVDD_SHIFT) & 0x1) != 0) { + if (gpio_base_addr == NULL) { + gpio_base_addr = + select_gpio_n_bitnum( + fuse_hdr->povdd_gpio, + &bit_num); + } + ret = clr_gpio_bit(gpio_base_addr, bit_num); + } else { + ret = board_disable_povdd() ? 0 : PLAT_ERROR_DISABLE_POVDD; + } + + if (ret != 0) { + ERROR("Error disabling board POVDD: %d\n", ret); + } + } + return 0; +} diff --git a/arm-trusted-firmware/plat/nxp/common/img_loadr/img_loadr.mk b/arm-trusted-firmware/plat/nxp/common/img_loadr/img_loadr.mk new file mode 100644 index 0000000..f64b1fa --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/img_loadr/img_loadr.mk @@ -0,0 +1,21 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +IMG_LOADR_DRIVERS_PATH := ${PLAT_COMMON_PATH}/img_loadr + +IMG_LOADR_SOURCES := $(IMG_LOADR_DRIVERS_PATH)/load_img.c +PLAT_INCLUDES += -I$(IMG_LOADR_DRIVERS_PATH) + +ifeq (${BL_COMM_IMG_LOADR_NEEDED},yes) +BL_COMMON_SOURCES += ${IMG_LOADR_SOURCES} +else +ifeq (${BL2_IMG_LOADR_NEEDED},yes) +BL2_SOURCES += ${IMG_LOADR_SOURCES} +endif +ifeq (${BL31_IMG_LOADR_NEEDED},yes) +BL31_SOURCES += ${IMG_LOADR_SOURCES} +endif +endif diff --git a/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c b/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c new file mode 100644 index 0000000..c185c36 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include + +#include "load_img.h" + +/****************************************************************************** + * This function can be used to load DDR PHY/FUSE Images + * + * @param [in] image_id Image ID to be loaded + * + * @param [in,out] image_base Location at which the image should be loaded + * In case image is prepended by a CSF header, + * image_base is pointer to actual image after + * the header + * + * @param [in,out] image_size User should pass the maximum size of the image + * possible.(Buffer size starting from image_base) + * Actual size of the image loaded is returned + * back. + *****************************************************************************/ +int load_img(unsigned int image_id, uintptr_t *image_base, + uint32_t *image_size) +{ + int err = 0; + + image_desc_t img_info = { + .image_id = image_id, + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), +#ifdef CSF_HEADER_PREPENDED + .image_info.image_base = *image_base - CSF_HDR_SZ, + .image_info.image_max_size = *image_size + CSF_HDR_SZ, +#else + .image_info.image_base = *image_base, + .image_info.image_max_size = *image_size, +#endif + }; + + /* Create MMU entry for the CSF header */ +#if PLAT_XLAT_TABLES_DYNAMIC +#ifdef CSF_HEADER_PREPENDED + mmap_add_dynamic_region(img_info.image_info.image_base, + img_info.image_info.image_base, + CSF_HDR_SZ, + MT_MEMORY | MT_RW | MT_SECURE); +#endif +#endif + + VERBOSE("BL2: Loading IMG %d\n", image_id); + err = load_auth_image(image_id, &img_info.image_info); + if (err != 0) { + VERBOSE("Failed to load IMG %d\n", image_id); + return err; + } + +#ifdef CSF_HEADER_PREPENDED + *image_base = img_info.image_info.image_base + CSF_HDR_SZ; + *image_size = img_info.image_info.image_size - CSF_HDR_SZ; +#if PLAT_XLAT_TABLES_DYNAMIC + mmap_remove_dynamic_region(img_info.image_info.image_base, + CSF_HDR_SZ); +#endif +#else + *image_base = img_info.image_info.image_base; + *image_size = img_info.image_info.image_size; +#endif + + return err; +} diff --git a/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h b/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h new file mode 100644 index 0000000..6f9de32 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef LOAD_IMAGE_H +#define LOAD_IMAGE_H + +int load_img(unsigned int image_id, uintptr_t *image_base, + uint32_t *image_size); + +#endif /* LOAD_IMAGE_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h new file mode 100644 index 0000000..6296aef --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h @@ -0,0 +1,70 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_BASE_ADDR_H +#define SOC_DEFAULT_BASE_ADDR_H + +/* CCSR mmu_def.h */ +#define NXP_CCSR_ADDR 0x01000000 +#define NXP_CCSR_SIZE 0x0F000000 + +#define NXP_DCSR_ADDR 0x20000000 +#define NXP_DCSR_SIZE 0x4000000 + +/* Flex-SPI controller address */ +#define NXP_FLEXSPI_ADDR 0x020C0000 +/* QSPI Flash Start address */ +#define NXP_QSPI_FLASH_ADDR 0x40000000 +/* NOR Flash Start address */ +#define NXP_IFC_REGION_ADDR 0x60000000 +#define NXP_NOR_FLASH_ADDR NXP_IFC_REGION_ADDR + +/* MMU 500 soc.c*/ +#define NXP_SMMU_ADDR 0x09000000 + +#define NXP_SNVS_ADDR 0x01E90000 + +#define NXP_DCFG_ADDR 0x01EE0000 +#define NXP_SFP_ADDR 0x01E80000 +#define NXP_RCPM_ADDR 0x01EE2000 +#define NXP_CSU_ADDR 0x01510000 +#define NXP_IFC_ADDR 0x01530000 +#define NXP_SCFG_ADDR 0x01570000 +#define NXP_DCSR_ADDR 0x20000000 +#define NXP_DCSR_DCFG_ADDR (NXP_DCSR_ADDR + 0x00140000) +#define NXP_I2C_ADDR 0x02180000 +#define NXP_ESDHC_ADDR 0x01560000 +#define NXP_UART_ADDR 0x021C0500 +#define NXP_UART1_ADDR 0x021C0600 + +#define NXP_GPIO1_ADDR 0x02300000 +#define NXP_GPIO2_ADDR 0x02310000 +#define NXP_GPIO3_ADDR 0x02320000 +#define NXP_GPIO4_ADDR 0x02330000 + +#define NXP_WDOG1_NS_ADDR 0x02390000 +#define NXP_WDOG2_NS_ADDR 0x023A0000 +#define NXP_WDOG1_TZ_ADDR 0x023B0000 +#define NXP_WDOG2_TZ_ADDR 0x023C0000 + +#define NXP_TIMER_STATUS_ADDR 0x023F0000 + +#define NXP_GICD_4K_ADDR 0x01401000 +#define NXP_GICC_4K_ADDR 0x01402000 +#define NXP_GICD_64K_ADDR 0x01410000 +#define NXP_GICC_64K_ADDR 0x01420000 + +#define NXP_CAAM_ADDR 0x01700000 + +#define NXP_TZC_ADDR 0x01500000 +#define NXP_DDR_ADDR 0x01080000 + +#define NXP_TIMER_ADDR 0x02B00000 +#define NXP_CCI_ADDR 0x01180000 +#define NXP_RESET_ADDR 0x01E60000 +#define NXP_SEC_REGFILE_ADDR 0x01E88000 +#endif /* SOC_DEFAULT_BASE_ADDR_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h new file mode 100644 index 0000000..928ac05 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h @@ -0,0 +1,83 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_HELPER_MACROS_H +#define SOC_DEFAULT_HELPER_MACROS_H + +#ifdef NXP_OCRAM_TZPC_ADDR + +/* 0x1: means 4 KB + * 0x2: means 8 KB + */ +#define TZPC_BLOCK_SIZE 0x1000 +#endif + +/* DDR controller offsets and defines */ +#ifdef NXP_DDR_ADDR + +#define DDR_CFG_2_OFFSET 0x114 +#define CFG_2_FORCE_REFRESH 0x80000000 + +#endif /* NXP_DDR_ADDR */ + + /* Reset block register offsets */ +#ifdef NXP_RESET_ADDR + +/* Register Offset */ +#define RST_RSTCR_OFFSET 0x0 +#define RST_RSTRQMR1_OFFSET 0x10 +#define RST_RSTRQSR1_OFFSET 0x18 +#define BRR_OFFSET 0x60 + +/* helper macros */ +#define RSTRQSR1_SWRR 0x800 +#define RSTRQMR_RPTOE_MASK (1 << 19) + +#endif /* NXP_RESET_ADDR */ + +/* Secure-Register-File register offsets and bit masks */ +#ifdef NXP_RST_ADDR +/* Register Offset */ +#define CORE_HOLD_OFFSET 0x140 +#define RSTCNTL_OFFSET 0x180 + +/* Helper macros */ +#define SW_RST_REQ_INIT 0x1 +#endif + +#ifdef NXP_RCPM_ADDR +/* RCPM Register Offsets */ +#define RCPM_PCPH20SETR_OFFSET 0x0D4 +#define RCPM_PCPH20CLRR_OFFSET 0x0D8 +#define RCPM_POWMGTCSR_OFFSET 0x130 +#define RCPM_IPPDEXPCR0_OFFSET 0x140 +#define RCPM_POWMGTCSR_LPM20_REQ 0x00100000 + +#define RCPM2_IPSTPCR0_OFFSET 0x8 +#define RCPM2_IPSTPCR1_OFFSET 0xC +#define RCPM2_IPSTPCR2_OFFSET 0x10 +#define RCPM2_IPSTPCR3_OFFSET 0x14 +#define RCPM2_IPSTPCR4_OFFSET 0x28 + +#define RCPM2_IPSTPACKR0_OFFSET 0x18 +#define RCPM2_IPSTPACKR1_OFFSET 0x1C +#define RCPM2_IPSTPACKR2_OFFSET 0x20 +#define RCPM2_IPSTPACKR3_OFFSET 0x24 +#define RCPM2_IPSTPACKR4_OFFSET 0x2C +#define RCPM2_POWMGTDCR_OFFSET 0x0 + +/* bitfield masks */ +#define POWMGTDCR_OVRD_EN 0x80000000 + +#endif /* NXP_RCPM_ADDR */ + +#define DCFG_SBEESR2_ADDR 0x20140534 +#define DCFG_MBEESR2_ADDR 0x20140544 +/* SBEESR and MBEESR bit mask */ +#define OCRAM_EESR_MASK 0x00000060 + +#endif /* SOC_DEFAULT_HELPER_MACROS_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h new file mode 100644 index 0000000..8d64f04 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h @@ -0,0 +1,100 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_BASE_ADDR_H +#define SOC_DEFAULT_BASE_ADDR_H + +/* CCSR mmu_def.h */ +#define NXP_CCSR_ADDR 0x1000000 +#define NXP_CCSR_SIZE 0xF000000 + +#define NXP_DCSR_ADDR 0x700000000 +#define NXP_DCSR_SIZE 0x40000000 + +/* Quad SPI Region #1 base address */ +#define NXP_QSPI_FLASH_ADDR 0x20000000 + +/* IFC Region #1 base address */ +#define NXP_NOR_FLASH_ADDR 0x30000000 + +/* MMU 500 */ +#define NXP_SMMU_ADDR 0x05000000 + +#define NXP_SNVS_ADDR 0x01E90000 + +#define NXP_DCFG_ADDR 0x01E00000 +#define NXP_PMU_CCSR_ADDR 0x01E30000 +#define NXP_PMU_DCSR_ADDR 0x700123000 +#define NXP_PMU_ADDR NXP_PMU_CCSR_ADDR +#define NXP_SFP_ADDR 0x01E80000 +#define NXP_SCFG_ADDR 0x01FC0000 +#define NXP_I2C_ADDR 0x02000000 +#define NXP_ESDHC_ADDR 0x02140000 +#define NXP_ESDHC2_ADDR 0x02150000 +#ifndef NXP_UART_ADDR +#define NXP_UART_ADDR 0x021C0500 +#endif +#ifndef NXP_UART1_ADDR +#define NXP_UART1_ADDR 0x021C0600 +#endif + +#define NXP_GPIO1_ADDR 0x02300000 +#define NXP_GPIO2_ADDR 0x02310000 +#define NXP_GPIO3_ADDR 0x02320000 +#define NXP_GPIO4_ADDR 0x02330000 + +#define NXP_WDOG1_NS_ADDR 0x02390000 +#define NXP_WDOG2_NS_ADDR 0x023A0000 +#define NXP_WDOG1_TZ_ADDR 0x023B0000 +#define NXP_WDOG2_TZ_ADDR 0x023C0000 + +#define NXP_TIMER_STATUS_ADDR 0x023F0000 + +#define NXP_GICD_ADDR 0x06000000 +#define NXP_GICR_ADDR 0x06100000 +#define NXP_GICR_SGI_ADDR 0x06110000 + +#define NXP_CAAM_ADDR 0x08000000 + +#define NXP_TZC_ADDR 0x01100000 +#define NXP_TZC2_ADDR 0x01110000 +#define NXP_TZC3_ADDR 0x01120000 + +#define NXP_RESET_ADDR 0x01E60000 +#define NXP_SEC_REGFILE_ADDR 0x01E88000 + +#define NXP_RST_ADDR 0x01E88000 + +/* DDR memory Map */ +#define NXP_DDR_ADDR 0x01080000 +#define NXP_DDR2_ADDR 0x01090000 +#define NXP_DDR3_ADDR 0x08210000 + +/* QuadSPI base address */ +#define NXP_QSPI_ADDR 0x020C0000 +/* IFC base address */ +#define NXP_IFC_ADDR 0x02240000 + +/* CCI400 base address */ +#define NXP_CCI_ADDR 0x04090000 + +/* Global Generic Reference Timer base address */ +#define NXP_TIMER_ADDR 0x023E0000 + +/* OCRAM TZPC base address */ +#define NXP_OCRAM_TZPC_ADDR 0x02200000 + +#define NXP_EPU_ADDR 0x700060000 + +#define NXP_CCN_ADDR 0x04000000 +#define NXP_CCN_HNI_ADDR 0x04080000 +#define NXP_CCN_HN_F_0_ADDR 0x04200000 +#define NXP_CCN_HN_F_1_ADDR 0x04210000 + +#define TPMWAKEMR0_ADDR 0x700123c50 + +#endif /* SOC_DEFAULT_BASE_ADDR_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h new file mode 100644 index 0000000..8e68367 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h @@ -0,0 +1,98 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SOC_DEFAULT_HELPER_MACROS_H +#define SOC_DEFAULT_HELPER_MACROS_H + +#ifdef NXP_OCRAM_TZPC_ADDR +#define TZPC_BLOCK_SIZE 0x1000 +#endif + +/* Reset block register offsets */ +#ifdef NXP_RESET_ADDR + +/* Register Offset */ +#define RST_RSTCR_OFFSET 0x0 +#define RST_RSTRQMR1_OFFSET 0x10 +#define RST_RSTRQSR1_OFFSET 0x18 +#define BRR_OFFSET 0x60 + +/* helper macros */ +#define RSTRQMR_RPTOE_MASK (1 << 19) +#endif /* NXP_RESET_ADDR */ + +#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8 +#define PoS_CONTROL_REG_OFFSET 0x0 +#define POS_EARLY_WR_COMP_EN 0x20 +#define HNI_POS_EN 0x01 +#define POS_TERMINATE_BARRIERS 0x10 +#define SERIALIZE_DEV_nGnRnE_WRITES 0x200 +#define ENABLE_ERR_SIGNAL_TO_MN 0x4 +#define ENABLE_RESERVE_BIT53 0x400 +#define ENABLE_WUO 0x10 + +#define PORT_S0_CTRL_REG_RNI 0x010 +#define PORT_S1_CTRL_REG_RNI 0x110 +#define PORT_S2_CTRL_REG_RNI 0x210 +#define ENABLE_FORCE_RD_QUO 0x20 +#define QOS_SETTING 0x00FF000C + +/* epu register offsets and values */ +#define EPU_EPGCR_OFFSET 0x0 +#define EPU_EPIMCR10_OFFSET 0x128 +#define EPU_EPCTR10_OFFSET 0xa28 +#define EPU_EPCCR10_OFFSET 0x828 +#ifndef EPU_EPCCR10_VAL +#define EPU_EPCCR10_VAL 0xb2800000 +#endif +#define EPU_EPIMCR10_VAL 0xba000000 +#define EPU_EPCTR10_VAL 0x0 +#define EPU_EPGCR_VAL (1 << 31) + +#ifdef NXP_CCN_ADDR +#define NXP_CCN_HN_F_1_ADDR 0x04210000 + +#define CCN_HN_F_SAM_NODEID_MASK 0x7f +#define CCN_HN_F_SNP_DMN_CTL_OFFSET 0x200 +#define CCN_HN_F_SNP_DMN_CTL_SET_OFFSET 0x210 +#define CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET 0x220 +#define CCN_HN_F_SNP_DMN_CTL_MASK 0x80a00 +#define CCN_HNF_NODE_COUNT 8 +#define CCN_HNF_OFFSET 0x10000 + +#define SA_AUX_CTRL_REG_OFFSET 0x500 +#define NUM_HNI_NODE 2 +#define CCN_HNI_MEMORY_MAP_SIZE 0x10000 + +#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8 +#define PoS_CONTROL_REG_OFFSET 0x0 +#define POS_EARLY_WR_COMP_EN 0x20 +#define HNI_POS_EN 0x01 +#define POS_TERMINATE_BARRIERS 0x10 +#define SERIALIZE_DEV_nGnRnE_WRITES 0x200 +#define ENABLE_ERR_SIGNAL_TO_MN 0x4 +#define ENABLE_RESERVE_BIT53 0x400 +#define ENABLE_WUO 0x10 +#endif + +/* reset register bit */ +#define RSTRQMR_RPTOE_MASK (1 << 19) + +/* secmon register offsets and bitfields */ +#define SECMON_HPCOMR_OFFSET 0x4 +#define SECMON_HPCOMR_NPSWAEN 0x80000000 + +/* Secure-Register-File register offsets and bit masks */ +#ifdef NXP_RST_ADDR +/* Register Offset */ +#define CORE_HOLD_OFFSET 0x140 +#endif + +#define DCFG_SBEESR2_ADDR 0x00100534 +#define DCFG_MBEESR2_ADDR 0x00100544 +/* SBEESR and MBEESR bit mask */ +#define OCRAM_EESR_MASK 0x00000008 + +#endif /* SOC_DEFAULT_HELPER_MACROS_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h new file mode 100644 index 0000000..0a4228b --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h @@ -0,0 +1,88 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_BASE_ADDR_H +#define SOC_DEFAULT_BASE_ADDR_H + +/* CCSR mmu_def.h */ +#define NXP_CCSR_ADDR 0x1000000 +#define NXP_CCSR_SIZE 0xF000000 + +#define NXP_DCSR_ADDR 0x700000000 +#define NXP_DCSR_SIZE 0x40000000 + +/* Flex-SPI controller address */ +#define NXP_FLEXSPI_ADDR 0x020C0000 +/* Flex-SPI Flash Start address */ +#define NXP_FLEXSPI_FLASH_ADDR 0x20000000 + +/* MMU 500 soc.c*/ +#define NXP_SMMU_ADDR 0x05000000 + +/* CCI400 base address */ +#define NXP_CCI_ADDR 0x04090000 + +#define NXP_SNVS_ADDR 0x01E90000 + +#define NXP_DCFG_ADDR 0x01E00000 +#define NXP_PMU_CCSR_ADDR 0x01E30000 +#define NXP_PMU_DCSR_ADDR 0x700123000 +#define NXP_PMU_ADDR NXP_PMU_CCSR_ADDR +#define NXP_SFP_ADDR 0x01E80000 +#define NXP_SCFG_ADDR 0x01FC0000 +#define NXP_I2C_ADDR 0x02000000 +#define NXP_ESDHC_ADDR 0x02140000 +#define NXP_ESDHC2_ADDR 0x02150000 +#define NXP_UART_ADDR 0x021C0000 +#define NXP_UART1_ADDR 0x021D0000 + +#define NXP_GPIO1_ADDR 0x02300000 +#define NXP_GPIO2_ADDR 0x02310000 +#define NXP_GPIO3_ADDR 0x02320000 +#define NXP_GPIO4_ADDR 0x02330000 + +#define NXP_WDOG1_NS_ADDR 0x02390000 +#define NXP_WDOG2_NS_ADDR 0x023A0000 +#define NXP_WDOG1_TZ_ADDR 0x023B0000 +#define NXP_WDOG2_TZ_ADDR 0x023C0000 + +#define NXP_TIMER_STATUS_ADDR 0x023F0000 + +#define NXP_GICD_ADDR 0x06000000 +#define NXP_GICR_ADDR 0x06200000 +#define NXP_GICR_SGI_ADDR 0x06210000 + +#define NXP_CAAM_ADDR 0x08000000 + +#define NXP_TZC_ADDR 0x01100000 +#define NXP_TZC2_ADDR 0x01110000 +#define NXP_TZC3_ADDR 0x01120000 + +#define NXP_TIMER_ADDR 0x023E0000 + +#define NXP_RESET_ADDR 0x01E60000 +#define NXP_SEC_REGFILE_ADDR 0x01E88000 +#define NXP_RST_ADDR 0x01E88000 + +#define TPMWAKEMR0_ADDR 0x700123c50 +#define TZPC_BLOCK_SIZE 0x1000 + +#define NXP_TZC_ADDR 0x01100000 +#define NXP_TZC2_ADDR 0x01110000 +#define NXP_TZC3_ADDR 0x01120000 +#define NXP_TZC4_ADDR 0x01130000 +#define NXP_DDR_ADDR 0x01080000 +#define NXP_DDR2_ADDR 0x01090000 + +#define NXP_OCRAM_TZPC_ADDR 0x02200000 + +#define NXP_CCN_ADDR 0x04000000 +#define NXP_CCN_HNI_ADDR 0x04080000 +#define NXP_CCN_HN_F_0_ADDR 0x04200000 + +#define NXP_EPU_ADDR 0x700060000 +#endif /* SOC_DEFAULT_BASE_ADDR_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h new file mode 100644 index 0000000..1edd28d --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h @@ -0,0 +1,87 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_HELPER_MACROS_H +#define SOC_DEFAULT_HELPER_MACROS_H + +#ifdef NXP_OCRAM_TZPC_ADDR + +/* 0x1: means 4 KB + * 0x2: means 8 KB + */ +#define TZPC_BLOCK_SIZE 0x1000 +#endif + +/* DDR controller offsets and defines */ +#ifdef NXP_DDR_ADDR + +#define DDR_CFG_2_OFFSET 0x114 +#define CFG_2_FORCE_REFRESH 0x80000000 + +#endif /* NXP_DDR_ADDR */ + + /* Reset block register offsets */ +#ifdef NXP_RESET_ADDR + +/* Register Offset */ +#define RST_RSTCR_OFFSET 0x0 +#define RST_RSTRQMR1_OFFSET 0x10 +#define RST_RSTRQSR1_OFFSET 0x18 +#define BRR_OFFSET 0x60 + +/* helper macros */ +#define RSTRQSR1_SWRR 0x800 +#define RSTRQMR_RPTOE_MASK (1 << 19) + +#endif /* NXP_RESET_ADDR */ + +/* secmon register offsets and bitfields */ +#define SECMON_HPCOMR_OFFSET 0x4 +#define SECMON_HPCOMR_NPSWAEN 0x80000000 + +/* Secure-Register-File register offsets and bit masks */ +#ifdef NXP_RST_ADDR +/* Register Offset */ +#define CORE_HOLD_OFFSET 0x140 +#define RSTCNTL_OFFSET 0x180 + +/* Helper macros */ +#define SW_RST_REQ_INIT 0x1 +#endif + +#ifdef NXP_CCN_ADDR +#define NXP_CCN_HN_F_1_ADDR 0x04210000 + +#define CCN_HN_F_SAM_NODEID_MASK 0x7f +#define CCN_HN_F_SNP_DMN_CTL_OFFSET 0x200 +#define CCN_HN_F_SNP_DMN_CTL_SET_OFFSET 0x210 +#define CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET 0x220 +#define CCN_HN_F_SNP_DMN_CTL_MASK 0x80a00 +#define CCN_HNF_NODE_COUNT 8 +#define CCN_HNF_OFFSET 0x10000 + +#define SA_AUX_CTRL_REG_OFFSET 0x500 +#define NUM_HNI_NODE 2 +#define CCN_HNI_MEMORY_MAP_SIZE 0x10000 + +#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8 +#define PoS_CONTROL_REG_OFFSET 0x0 +#define POS_EARLY_WR_COMP_EN 0x20 +#define HNI_POS_EN 0x01 +#define POS_TERMINATE_BARRIERS 0x10 +#define SERIALIZE_DEV_nGnRnE_WRITES 0x200 +#define ENABLE_ERR_SIGNAL_TO_MN 0x4 +#define ENABLE_RESERVE_BIT53 0x400 +#define ENABLE_WUO 0x10 +#endif /* NXP_CCN_ADDR */ + +#define DCFG_SBEESR2_ADDR 0x00100534 +#define DCFG_MBEESR2_ADDR 0x00100544 +/* SBEESR and MBEESR bit mask */ +#define OCRAM_EESR_MASK 0x00000008 + +#endif /* SOC_DEFAULT_HELPER_MACROS_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h b/arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h new file mode 100644 index 0000000..43320bb --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h @@ -0,0 +1,172 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEFAULT_DEF_H +#define PLAT_DEFAULT_DEF_H + +/* + * 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__ */ + +#define LS_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/* NXP Platforms have DRAM divided into banks. + * DRAM0 Bank: Maximum size of this bank is fixed to 2GB + * DRAM1 Bank: Greater than 2GB belongs to bank1 and size of bank1 varies from + * one platform to other platform. + * DRAMn Bank: + * + * Except a few, all the platforms have 2GB size as DRAM0 BANK. + * Hence common for all the platforms. + * For platforms where DRAM0 Size is < 2GB, it is defined in platform_def.h + */ +#ifndef PLAT_DEF_DRAM0_SIZE +#define PLAT_DEF_DRAM0_SIZE 0x80000000 /* 2G */ +#endif + +/* This is common for all platforms where: */ +#ifndef NXP_NS_DRAM_ADDR +#define NXP_NS_DRAM_ADDR NXP_DRAM0_ADDR +#endif + +/* 1 MB is reserved for dma of sd */ +#ifndef NXP_SD_BLOCK_BUF_SIZE +#define NXP_SD_BLOCK_BUF_SIZE (1 * 1024 * 1024) +#endif + +/* 64MB is reserved for Secure memory */ +#ifndef NXP_SECURE_DRAM_SIZE +#define NXP_SECURE_DRAM_SIZE (64 * 1024 * 1024) +#endif + +/* 2M Secure EL1 Payload Shared Memory */ +#ifndef NXP_SP_SHRD_DRAM_SIZE +#define NXP_SP_SHRD_DRAM_SIZE (2 * 1024 * 1024) +#endif + +#ifndef NXP_NS_DRAM_SIZE +/* Non secure memory */ +#define NXP_NS_DRAM_SIZE (PLAT_DEF_DRAM0_SIZE - \ + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) +#endif + +#ifndef NXP_SD_BLOCK_BUF_ADDR +#define NXP_SD_BLOCK_BUF_ADDR (NXP_NS_DRAM_ADDR) +#endif + +#ifndef NXP_SECURE_DRAM_ADDR +#ifdef TEST_BL31 +#define NXP_SECURE_DRAM_ADDR 0 +#else +#define NXP_SECURE_DRAM_ADDR (NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE - \ + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) +#endif +#endif + +#ifndef NXP_SP_SHRD_DRAM_ADDR +#define NXP_SP_SHRD_DRAM_ADDR (NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE - \ + NXP_SP_SHRD_DRAM_SIZE) +#endif + +#ifndef BL31_BASE +/* 2 MB reserved in secure memory for DDR */ +#define BL31_BASE NXP_SECURE_DRAM_ADDR +#endif + +#ifndef BL31_SIZE +#define BL31_SIZE (0x200000) +#endif + +#ifndef BL31_LIMIT +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) +#endif + +/* Put BL32 in secure memory */ +#ifndef BL32_BASE +#define BL32_BASE (NXP_SECURE_DRAM_ADDR + BL31_SIZE) +#endif + +#ifndef BL32_LIMIT +#define BL32_LIMIT (NXP_SECURE_DRAM_ADDR + \ + NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE) +#endif + +/* BL33 memory region */ +/* Hardcoded based on current address in u-boot */ +#ifndef BL33_BASE +#define BL33_BASE 0x82000000 +#endif + +#ifndef BL33_LIMIT +#define BL33_LIMIT (NXP_NS_DRAM_ADDR + NXP_NS_DRAM_SIZE) +#endif + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#ifndef FUSE_BUF +#define FUSE_BUF ULL(0x81000000) +#endif + +#ifndef FUSE_SZ +#define FUSE_SZ 0x80000 +#endif +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef PLAT_FIP_OFFSET +#define PLAT_FIP_OFFSET 0x100000 +#endif + +#ifndef PLAT_FIP_MAX_SIZE +#define PLAT_FIP_MAX_SIZE 0x400000 +#endif + +/* Check if this size can be determined from array size */ +#if defined(IMAGE_BL2) +#ifndef MAX_MMAP_REGIONS +#define MAX_MMAP_REGIONS 8 +#endif +#ifndef MAX_XLAT_TABLES +#define MAX_XLAT_TABLES 6 +#endif +#elif defined(IMAGE_BL31) +#ifndef MAX_MMAP_REGIONS +#define MAX_MMAP_REGIONS 9 +#endif +#ifndef MAX_XLAT_TABLES +#define MAX_XLAT_TABLES 9 +#endif +#elif defined(IMAGE_BL32) +#ifndef MAX_MMAP_REGIONS +#define MAX_MMAP_REGIONS 8 +#endif +#ifndef MAX_XLAT_TABLES +#define MAX_XLAT_TABLES 9 +#endif +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#ifndef BL32_IRQ_SEC_PHY_TIMER +#define BL32_IRQ_SEC_PHY_TIMER 29 +#endif + +#endif /* PLAT_DEFAULT_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/nv_storage/nv_storage.mk b/arm-trusted-firmware/plat/nxp/common/nv_storage/nv_storage.mk new file mode 100644 index 0000000..dddba5f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/nv_storage/nv_storage.mk @@ -0,0 +1,29 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# NXP Non-Volatile data flag storage used and then cleared by SW on boot-up + +$(eval $(call add_define,NXP_NV_SW_MAINT_LAST_EXEC_DATA)) + +ifeq ($(NXP_COINED_BB),yes) +$(eval $(call add_define,NXP_COINED_BB)) +# BL2 : To read the reset cause from LP SECMON GPR register +# BL31: To write the reset cause to LP SECMON GPR register +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL_COMM)) + +# BL2: DDR training data is stored on Flexspi NOR. +ifneq (${BOOT_MODE},flexspi_nor) +$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2)) +endif + +else +$(eval $(call add_define_val,DEFAULT_NV_STORAGE_BASE_ADDR,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - 2 * ${NXP_XSPI_NOR_UNIT_SIZE}')) +$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL_COMM)) +endif + +NV_STORAGE_INCLUDES += -I${PLAT_COMMON_PATH}/nv_storage + +NV_STORAGE_SOURCES += ${PLAT_COMMON_PATH}/nv_storage/plat_nv_storage.c diff --git a/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c b/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c new file mode 100644 index 0000000..7ec4fdb --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c @@ -0,0 +1,120 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef NXP_COINED_BB +#include +#include +#include +#endif +#include +#ifdef NXP_COINED_BB +#include +#else +#include +#endif + +#include + +/*This structure will be a static structure and + * will be populated as first step of BL2 booting-up. + * fspi_strorage.c . To be located in the fspi driver folder. + */ + +static nv_app_data_t nv_app_data; + +int read_nv_app_data(void) +{ + int ret = 0; + +#ifdef NXP_COINED_BB + uint8_t *nv_app_data_array = (uint8_t *) &nv_app_data; + uint8_t offset = 0U; + + ret = snvs_read_app_data(); + do { + nv_app_data_array[offset] = snvs_read_app_data_bit(offset); + offset++; + + } while (offset < APP_DATA_MAX_OFFSET); + snvs_clear_app_data(); +#else + uintptr_t nv_base_addr = NV_STORAGE_BASE_ADDR; + + ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR); + + if (ret != XSPI_SUCCESS) { + ERROR("Failed to initialized driver flexspi-nor.\n"); + ERROR("exiting warm-reset request.\n"); + return -ENODEV; + } + + xspi_read(nv_base_addr, + (uint32_t *)&nv_app_data, sizeof(nv_app_data_t)); + xspi_sector_erase((uint32_t) nv_base_addr, + F_SECTOR_ERASE_SZ); +#endif + return ret; +} + +int wr_nv_app_data(int data_offset, + uint8_t *data, + int data_size) +{ + int ret = 0; +#ifdef NXP_COINED_BB +#if !TRUSTED_BOARD_BOOT + snvs_disable_zeroize_lp_gpr(); +#endif + /* In case LP SecMon General purpose register, + * only 1 bit flags can be saved. + */ + if ((data_size > 1) || (*data != DEFAULT_SET_VALUE)) { + ERROR("Only binary value is allowed to be written.\n"); + ERROR("Use flash instead of SNVS GPR as NV location.\n"); + return -ENODEV; + } + snvs_write_app_data_bit(data_offset); +#else + uint8_t read_val[sizeof(nv_app_data_t)]; + uint8_t ready_to_write_val[sizeof(nv_app_data_t)]; + uintptr_t nv_base_addr = NV_STORAGE_BASE_ADDR; + + assert((nv_base_addr + data_offset + data_size) > (nv_base_addr + F_SECTOR_ERASE_SZ)); + + ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR); + + if (ret != XSPI_SUCCESS) { + ERROR("Failed to initialized driver flexspi-nor.\n"); + ERROR("exiting warm-reset request.\n"); + return -ENODEV; + } + + ret = xspi_read(nv_base_addr + data_offset, (uint32_t *)read_val, data_size); + + memset(ready_to_write_val, READY_TO_WRITE_VALUE, ARRAY_SIZE(ready_to_write_val)); + + if (memcmp(read_val, ready_to_write_val, data_size) == 0) { + xspi_write(nv_base_addr + data_offset, data, data_size); + } +#endif + + return ret; +} + +const nv_app_data_t *get_nv_data(void) +{ + return (const nv_app_data_t *) &nv_app_data; +} diff --git a/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h b/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h new file mode 100644 index 0000000..1f5264a --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h @@ -0,0 +1,40 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_NV_STRG_H +#define PLAT_NV_STRG_H + +#define DEFAULT_SET_VALUE 0xA1 +#define READY_TO_WRITE_VALUE 0xFF + +#ifndef NV_STORAGE_BASE_ADDR +#define NV_STORAGE_BASE_ADDR DEFAULT_NV_STORAGE_BASE_ADDR +#endif + +typedef struct { +uint8_t warm_rst_flag; +uint8_t wdt_rst_flag; +uint8_t dummy[2]; +} nv_app_data_t; + + +/*below enum and above structure should be in-sync. */ +enum app_data_offset { + WARM_RESET_FLAG_OFFSET, + WDT_RESET_FLAG_OFFSET, + APP_DATA_MAX_OFFSET, +}; + +int read_nv_app_data(void); + +int wr_nv_app_data(int data_offset, + uint8_t *data, + int data_size); + +const nv_app_data_t *get_nv_data(void); + +#endif /* PLAT_NV_STRG_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S b/arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S new file mode 100644 index 0000000..ec53341 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S @@ -0,0 +1,71 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +.global ocram_init + +/* + * void ocram_init(uintptr_t start_addr, size_t size) + * + * This function will do OCRAM ECC. + * OCRAM is initialized with 64-bit writes and then a write + * performed to address 0x0010_0534 with the value 0x0000_0008. + * + * x0: start_addr + * x1: size in bytes + * Called from C + */ + +func ocram_init + /* save the aarch32/64 non-volatile registers */ + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + /* convert bytes to 64-byte chunks */ + lsr x1, x1, #6 +1: + /* for each location, read and write-back */ + dc ivac, x0 + dsb sy + ldp x4, x5, [x0] + ldp x6, x7, [x0, #16] + ldp x8, x9, [x0, #32] + ldp x10, x11, [x0, #48] + stp x4, x5, [x0] + stp x6, x7, [x0, #16] + stp x8, x9, [x0, #32] + stp x10, x11, [x0, #48] + dc cvac, x0 + + sub x1, x1, #1 + cbz x1, 2f + add x0, x0, #64 + b 1b +2: + /* Clear OCRAM ECC status bit in SBEESR2 and MBEESR2 */ + ldr w1, =OCRAM_EESR_MASK + ldr x0, =DCFG_SBEESR2_ADDR + str w1, [x0] + ldr x0, =DCFG_MBEESR2_ADDR + str w1, [x0] + + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + ret +endfunc ocram_init diff --git a/arm-trusted-firmware/plat/nxp/common/ocram/ocram.h b/arm-trusted-firmware/plat/nxp/common/ocram/ocram.h new file mode 100644 index 0000000..479de61 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/ocram/ocram.h @@ -0,0 +1,13 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef OCRAM_H +#define OCRAM_H + +void ocram_init(uintptr_t start_addr, size_t size); + +#endif /* OCRAM_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/ocram/ocram.mk b/arm-trusted-firmware/plat/nxp/common/ocram/ocram.mk new file mode 100644 index 0000000..c77bd4a --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/ocram/ocram.mk @@ -0,0 +1,14 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +PLAT_OCRAM_PATH := $(PLAT_COMMON_PATH)/ocram + +OCRAM_SOURCES := ${PLAT_OCRAM_PATH}/$(ARCH)/ocram.S + +BL2_SOURCES += ${OCRAM_SOURCES} + +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/ocram diff --git a/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_build_macros.mk b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_build_macros.mk new file mode 100644 index 0000000..bba5e36 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_build_macros.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2020, NXP. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +define SET_NXP_MAKE_FLAG +$1 := yes +$2_$1 := yes +endef diff --git a/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_common_def.mk b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_common_def.mk new file mode 100644 index 0000000..86dacf8 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_common_def.mk @@ -0,0 +1,103 @@ +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Include build macros, for example: SET_NXP_MAKE_FLAG +include plat/nxp/common/plat_make_helper/plat_build_macros.mk + +# Adding platform specific defines + +$(eval $(call add_define_val,BOARD,'"${BOARD}"')) + +ifeq (${POVDD_ENABLE},yes) +$(eval $(call add_define,CONFIG_POVDD_ENABLE)) +endif + +ifneq (${FLASH_TYPE},) +$(eval $(call add_define,CONFIG_${FLASH_TYPE})) +endif + +ifneq (${XSPI_FLASH_SZ},) +$(eval $(call add_define_val,NXP_FLEXSPI_FLASH_SIZE,${XSPI_FLASH_SZ})) +endif + +ifneq (${QSPI_FLASH_SZ},) +$(eval $(call add_define_val,NXP_QSPI_FLASH_SIZE,${QSPI_FLASH_SZ})) +endif + +ifneq (${NOR_FLASH_SZ},) +$(eval $(call add_define_val,NXP_NOR_FLASH_SIZE,${NOR_FLASH_SZ})) +endif + + +ifneq (${FSPI_ERASE_4K},) +$(eval $(call add_define_val,CONFIG_FSPI_ERASE_4K,${FSPI_ERASE_4K})) +endif + +ifneq (${NUM_OF_DDRC},) +$(eval $(call add_define_val,NUM_OF_DDRC,${NUM_OF_DDRC})) +endif + +ifeq (${CONFIG_DDR_NODIMM},1) +$(eval $(call add_define,CONFIG_DDR_NODIMM)) +DDRC_NUM_DIMM := 1 +endif + +ifneq (${DDRC_NUM_DIMM},) +$(eval $(call add_define_val,DDRC_NUM_DIMM,${DDRC_NUM_DIMM})) +endif + +ifneq (${DDRC_NUM_CS},) +$(eval $(call add_define_val,DDRC_NUM_CS,${DDRC_NUM_CS})) +endif + +ifeq (${DDR_ADDR_DEC},yes) +$(eval $(call add_define,CONFIG_DDR_ADDR_DEC)) +endif + +ifeq (${DDR_ECC_EN},yes) +$(eval $(call add_define,CONFIG_DDR_ECC_EN)) +endif + +ifeq (${CONFIG_STATIC_DDR},1) +$(eval $(call add_define,CONFIG_STATIC_DDR)) +endif + +# Platform can control the base address for non-volatile storage. +#$(eval $(call add_define_val,NV_STORAGE_BASE_ADDR,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - 2 * ${NXP_XSPI_NOR_UNIT_SIZE}')) + +ifeq (${WARM_BOOT},yes) +$(eval $(call add_define_val,PHY_TRAINING_REGS_ON_FLASH,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - ${NXP_XSPI_NOR_UNIT_SIZE}')) +endif + +# Selecting Boot Source for the TFA images. +define add_boot_mode_define + ifeq ($(1),qspi) + $$(eval $$(call SET_NXP_MAKE_FLAG,QSPI_NEEDED,BL2)) + $$(eval $$(call add_define,QSPI_BOOT)) + else ifeq ($(1),sd) + $$(eval $$(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2)) + $$(eval $$(call add_define,SD_BOOT)) + else ifeq ($(1),emmc) + $$(eval $$(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2)) + $$(eval $$(call add_define,EMMC_BOOT)) + else ifeq ($(1),nor) + $$(eval $$(call SET_NXP_MAKE_FLAG,IFC_NOR_NEEDED,BL2)) + $$(eval $$(call add_define,NOR_BOOT)) + else ifeq ($(1),nand) + $$(eval $$(call SET_NXP_MAKE_FLAG,IFC_NAND_NEEDED,BL2)) + $$(eval $$(call add_define,NAND_BOOT)) + else ifeq ($(1),flexspi_nor) + $$(eval $$(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2)) + $$(eval $$(call add_define,FLEXSPI_NOR_BOOT)) + else + $$(error $(PLAT) Cannot Support Boot Mode: $(BOOT_MODE)) + endif +endef + +ifneq (,$(findstring $(BOOT_MODE),$(SUPPORTED_BOOT_MODE))) + $(eval $(call add_boot_mode_define,$(strip $(BOOT_MODE)))) +else + $(error $(PLAT) Un-supported Boot Mode = $(BOOT_MODE)) +endif diff --git a/arm-trusted-firmware/plat/nxp/common/plat_make_helper/soc_common_def.mk b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/soc_common_def.mk new file mode 100644 index 0000000..52f2867 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/soc_common_def.mk @@ -0,0 +1,117 @@ +# Copyright 2020-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Adding SoC specific defines + +ifneq (${CACHE_LINE},) +$(eval $(call add_define_val,PLATFORM_CACHE_LINE_SHIFT,${CACHE_LINE})) +$(eval CACHE_WRITEBACK_GRANULE=$(shell echo $$((1 << $(CACHE_LINE))))) +$(eval $(call add_define_val,CACHE_WRITEBACK_GRANULE,$(CACHE_WRITEBACK_GRANULE))) +endif + +ifneq (${INTERCONNECT},) +$(eval $(call add_define,NXP_HAS_${INTERCONNECT})) +ifeq (${INTERCONNECT}, CCI400) +ICNNCT_ID := 0x420 +$(eval $(call add_define,ICNNCT_ID)) +endif +endif + +ifneq (${CHASSIS},) +$(eval $(call add_define,CONFIG_CHASSIS_${CHASSIS})) +endif + +ifneq (${PLAT_DDR_PHY},) +$(eval $(call add_define,NXP_DDR_${PLAT_DDR_PHY})) +endif + +ifneq (${PHYS_SYS},) +$(eval $(call add_define,CONFIG_PHYS_64BIT)) +endif + +ifneq (${CSF_HDR_SZ},) +$(eval $(call add_define_val,CSF_HDR_SZ,${CSF_HDR_SZ})) +endif + +ifneq (${OCRAM_START_ADDR},) +$(eval $(call add_define_val,NXP_OCRAM_ADDR,${OCRAM_START_ADDR})) +endif + +ifneq (${OCRAM_SIZE},) +$(eval $(call add_define_val,NXP_OCRAM_SIZE,${OCRAM_SIZE})) +endif + +ifneq (${NXP_ROM_RSVD},) +$(eval $(call add_define_val,NXP_ROM_RSVD,${NXP_ROM_RSVD})) +endif + +ifneq (${BL2_BASE},) +$(eval $(call add_define_val,BL2_BASE,${BL2_BASE})) +endif + +ifeq (${SEC_MEM_NON_COHERENT},yes) +$(eval $(call add_define,SEC_MEM_NON_COHERENT)) +endif + +ifneq (${NXP_ESDHC_ENDIANNESS},) +$(eval $(call add_define,NXP_ESDHC_${NXP_ESDHC_ENDIANNESS})) +endif + +ifneq (${NXP_SFP_VER},) +$(eval $(call add_define,NXP_SFP_VER_${NXP_SFP_VER})) +endif + +ifneq (${NXP_SFP_ENDIANNESS},) +$(eval $(call add_define,NXP_SFP_${NXP_SFP_ENDIANNESS})) +endif + +ifneq (${NXP_GPIO_ENDIANNESS},) +$(eval $(call add_define,NXP_GPIO_${NXP_GPIO_ENDIANNESS})) +endif + +ifneq (${NXP_SNVS_ENDIANNESS},) +$(eval $(call add_define,NXP_SNVS_${NXP_SNVS_ENDIANNESS})) +endif + +ifneq (${NXP_GUR_ENDIANNESS},) +$(eval $(call add_define,NXP_GUR_${NXP_GUR_ENDIANNESS})) +endif + +ifneq (${NXP_FSPI_ENDIANNESS},) +$(eval $(call add_define,NXP_FSPI_${NXP_FSPI_ENDIANNESS})) +endif + +ifneq (${NXP_SEC_ENDIANNESS},) +$(eval $(call add_define,NXP_SEC_${NXP_SEC_ENDIANNESS})) +endif + +ifneq (${NXP_DDR_ENDIANNESS},) +$(eval $(call add_define,NXP_DDR_${NXP_DDR_ENDIANNESS})) +endif + +ifneq (${NXP_QSPI_ENDIANNESS},) +$(eval $(call add_define,NXP_QSPI_${NXP_QSPI_ENDIANNESS})) +endif + +ifneq (${NXP_SCFG_ENDIANNESS},) +$(eval $(call add_define,NXP_SCFG_${NXP_SCFG_ENDIANNESS})) +endif + +ifneq (${NXP_IFC_ENDIANNESS},) +$(eval $(call add_define,NXP_IFC_${NXP_IFC_ENDIANNESS})) +endif + +ifneq (${NXP_DDR_INTLV_256B},) +$(eval $(call add_define,NXP_DDR_INTLV_256B)) +endif + +ifneq (${PLAT_XLAT_TABLES_DYNAMIC},) +$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) +endif + +ifeq (${OCRAM_ECC_EN},yes) +$(eval $(call add_define,CONFIG_OCRAM_ECC_EN)) +include ${PLAT_COMMON_PATH}/ocram/ocram.mk +endif diff --git a/arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S b/arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S new file mode 100644 index 0000000..ec69aea --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S @@ -0,0 +1,1155 @@ + +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + +#include +#include + + +#define RESET_RETRY_CNT 800 +#define PSCI_ABORT_CNT 100 + +#if (SOC_CORE_RELEASE) + +.global _psci_cpu_on + +/* + * int _psci_cpu_on(u_register_t core_mask) + * x0 = target cpu core mask + * + * Called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + * + */ + +func _psci_cpu_on + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x6, x0 + + /* x0 = core mask (lsb) + * x6 = core mask (lsb) + */ + + /* check if core disabled */ + bl _soc_ck_disabled /* 0-2 */ + cbnz w0, psci_disabled + + /* check core data area to see if core cannot be turned on + * read the core state + */ + mov x0, x6 + bl _getCoreState /* 0-5 */ + mov x9, x0 + + /* x6 = core mask (lsb) + * x9 = core state (from data area) + */ + + cmp x9, #CORE_DISABLED + mov x0, #PSCI_E_DISABLED + b.eq cpu_on_done + + cmp x9, #CORE_PENDING + mov x0, #PSCI_E_ON_PENDING + b.eq cpu_on_done + + cmp x9, #CORE_RELEASED + mov x0, #PSCI_E_ALREADY_ON + b.eq cpu_on_done + +8: + /* x6 = core mask (lsb) + * x9 = core state (from data area) + */ + + cmp x9, #CORE_WFE + b.eq core_in_wfe + cmp x9, #CORE_IN_RESET + b.eq core_in_reset + cmp x9, #CORE_OFF + b.eq core_is_off + cmp x9, #CORE_OFF_PENDING + + /* if state == CORE_OFF_PENDING, set abort */ + mov x0, x6 + mov x1, #ABORT_FLAG_DATA + mov x2, #CORE_ABORT_OP + bl _setCoreData /* 0-3, [13-15] */ + + ldr x3, =PSCI_ABORT_CNT +7: + /* watch for abort to take effect */ + mov x0, x6 + bl _getCoreState /* 0-5 */ + cmp x0, #CORE_OFF + b.eq core_is_off + cmp x0, #CORE_PENDING + mov x0, #PSCI_E_SUCCESS + b.eq cpu_on_done + + /* loop til finished */ + sub x3, x3, #1 + cbnz x3, 7b + + /* if we didn't see either CORE_OFF or CORE_PENDING, then this + * core is in CORE_OFF_PENDING - exit with success, as the core will + * respond to the abort request + */ + mov x0, #PSCI_E_SUCCESS + b cpu_on_done + +/* this is where we start up a core out of reset */ +core_in_reset: + /* see if the soc-specific module supports this op */ + ldr x7, =SOC_CORE_RELEASE + cbnz x7, 3f + + mov x0, #PSCI_E_NOT_SUPPORTED + b cpu_on_done + + /* x6 = core mask (lsb) */ +3: + /* set core state in data area */ + mov x0, x6 + mov x1, #CORE_PENDING + bl _setCoreState /* 0-3, [13-15] */ + + /* release the core from reset */ + mov x0, x6 + bl _soc_core_release /* 0-3 */ + mov x0, #PSCI_E_SUCCESS + b cpu_on_done + + /* Start up the core that has been powered-down via CPU_OFF + */ +core_is_off: + /* see if the soc-specific module supports this op + */ + ldr x7, =SOC_CORE_RESTART + cbnz x7, 2f + + mov x0, #PSCI_E_NOT_SUPPORTED + b cpu_on_done + + /* x6 = core mask (lsb) */ +2: + /* set core state in data area */ + mov x0, x6 + mov x1, #CORE_WAKEUP + bl _setCoreState /* 0-3, [13-15] */ + + /* put the core back into service */ + mov x0, x6 +#if (SOC_CORE_RESTART) + bl _soc_core_restart /* 0-5 */ +#endif + mov x0, #PSCI_E_SUCCESS + b cpu_on_done + +/* this is where we release a core that is being held in wfe */ +core_in_wfe: + /* x6 = core mask (lsb) */ + + /* set core state in data area */ + mov x0, x6 + mov x1, #CORE_PENDING + bl _setCoreState /* 0-3, [13-15] */ + dsb sy + isb + + /* put the core back into service */ + sev + sev + isb + mov x0, #PSCI_E_SUCCESS + +cpu_on_done: + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_cpu_on + +#endif + + +#if (SOC_CORE_OFF) + +.global _psci_cpu_prep_off +.global _psci_cpu_off_wfi + +/* + * void _psci_cpu_prep_off(u_register_t core_mask) + * this function performs the SoC-specific programming prior + * to shutting the core down + * x0 = core_mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_cpu_prep_off + + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x10, x0 /* x10 = core_mask */ + + /* the core does not return from cpu_off, so no need + * to save/restore non-volatile registers + */ + + /* mask interrupts by setting DAIF[7:4] to 'b1111 */ + msr DAIFSet, #0xF + + /* read cpuectlr and save current value */ + mrs x4, CPUECTLR_EL1 + mov x1, #CPUECTLR_DATA + mov x2, x4 + mov x0, x10 + bl _setCoreData + + /* remove the core from coherency */ + bic x4, x4, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x4 + + /* save scr_el3 */ + mov x0, x10 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* x4 = scr_el3 */ + + /* secure SGI (FIQ) taken to EL3, set SCR_EL3[FIQ] */ + orr x4, x4, #SCR_FIQ_MASK + msr scr_el3, x4 + + /* x10 = core_mask */ + + /* prep the core for shutdown */ + mov x0, x10 + bl _soc_core_prep_off + + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_cpu_prep_off + +/* + * void _psci_cpu_off_wfi(u_register_t core_mask, u_register_t resume_addr) + * - this function shuts down the core + * - this function does not return!! + */ + +func _psci_cpu_off_wfi + /* save the wakeup address */ + mov x29, x1 + + /* x0 = core_mask */ + + /* shutdown the core */ + bl _soc_core_entr_off + + /* branch to resume execution */ + br x29 +endfunc _psci_cpu_off_wfi + +#endif + + +#if (SOC_CORE_RESTART) + +.global _psci_wakeup + +/* + * void _psci_wakeup(u_register_t core_mask) + * this function performs the SoC-specific programming + * after a core wakes up from OFF + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_wakeup + + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x4, x0 /* x4 = core mask */ + + /* restore scr_el3 */ + mov x0, x4 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x4 = core mask */ + + /* restore CPUECTLR */ + mov x0, x4 + mov x1, #CPUECTLR_DATA + bl _getCoreData + orr x0, x0, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x0 + + /* x4 = core mask */ + + /* start the core back up */ + mov x0, x4 + bl _soc_core_exit_off + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_wakeup + +#endif + + +#if (SOC_SYSTEM_RESET) + +.global _psci_system_reset + +func _psci_system_reset + + /* system reset is mandatory + * system reset is soc-specific + * Note: under no circumstances do we return from this call + */ + bl _soc_sys_reset +endfunc _psci_system_reset + +#endif + + +#if (SOC_SYSTEM_OFF) + +.global _psci_system_off + +func _psci_system_off + + /* system off is mandatory + * system off is soc-specific + * Note: under no circumstances do we return from this call */ + b _soc_sys_off +endfunc _psci_system_off + +#endif + + +#if (SOC_CORE_STANDBY) + +.global _psci_core_entr_stdby +.global _psci_core_prep_stdby +.global _psci_core_exit_stdby + +/* + * void _psci_core_entr_stdby(u_register_t core_mask) - this + * is the fast-path for simple core standby + */ + +func _psci_core_entr_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 /* x5 = core mask */ + + /* save scr_el3 */ + mov x0, x5 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* x4 = SCR_EL3 + * x5 = core mask + */ + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* x5 = core mask */ + + /* put the core into standby */ + mov x0, x5 + bl _soc_core_entr_stdby + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_core_entr_stdby + +/* + * void _psci_core_prep_stdby(u_register_t core_mask) - this + * sets up the core to enter standby state thru the normal path + */ + +func _psci_core_prep_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 + + /* x5 = core mask */ + + /* save scr_el3 */ + mov x0, x5 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* x5 = core mask */ + + /* call for any SoC-specific programming */ + mov x0, x5 + bl _soc_core_prep_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_core_prep_stdby + +/* + * void _psci_core_exit_stdby(u_register_t core_mask) - this + * exits the core from standby state thru the normal path + */ + +func _psci_core_exit_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 + + /* x5 = core mask */ + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x5 = core mask */ + + /* perform any SoC-specific programming after standby state */ + mov x0, x5 + bl _soc_core_exit_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_core_exit_stdby + +#endif + + +#if (SOC_CORE_PWR_DWN) + +.global _psci_core_prep_pwrdn +.global _psci_cpu_pwrdn_wfi +.global _psci_core_exit_pwrdn + +/* + * void _psci_core_prep_pwrdn_(u_register_t core_mask) + * this function prepares the core for power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_core_prep_pwrdn + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x6, x0 + + /* x6 = core mask */ + + /* mask interrupts by setting DAIF[7:4] to 'b1111 */ + msr DAIFSet, #0xF + + /* save scr_el3 */ + mov x0, x6 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* save cpuectlr */ + mov x0, x6 + mov x1, #CPUECTLR_DATA + mrs x2, CPUECTLR_EL1 + bl _setCoreData + + /* x6 = core mask */ + + /* SoC-specific programming for power-down */ + mov x0, x6 + bl _soc_core_prep_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_core_prep_pwrdn + +/* + * void _psci_cpu_pwrdn_wfi(u_register_t core_mask, u_register_t resume_addr) + * this function powers down the core + */ + +func _psci_cpu_pwrdn_wfi + /* save the wakeup address */ + mov x29, x1 + + /* x0 = core mask */ + + /* shutdown the core */ + bl _soc_core_entr_pwrdn + + /* branch to resume execution */ + br x29 +endfunc _psci_cpu_pwrdn_wfi + +/* + * void _psci_core_exit_pwrdn_(u_register_t core_mask) + * this function cleans up after a core power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_core_exit_pwrdn + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x5, x0 /* x5 = core mask */ + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x5 = core mask */ + + /* restore cpuectlr */ + mov x0, x5 + mov x1, #CPUECTLR_DATA + bl _getCoreData + /* make sure smp is set */ + orr x0, x0, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x0 + + /* x5 = core mask */ + + /* SoC-specific cleanup */ + mov x0, x5 + bl _soc_core_exit_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_core_exit_pwrdn + +#endif + +#if (SOC_CLUSTER_STANDBY) + +.global _psci_clstr_prep_stdby +.global _psci_clstr_exit_stdby + +/* + * void _psci_clstr_prep_stdby(u_register_t core_mask) - this + * sets up the clstr to enter standby state thru the normal path + */ + +func _psci_clstr_prep_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 + + /* x5 = core mask */ + + /* save scr_el3 */ + mov x0, x5 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* x5 = core mask */ + + /* call for any SoC-specific programming */ + mov x0, x5 + bl _soc_clstr_prep_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_clstr_prep_stdby + +/* + * void _psci_clstr_exit_stdby(u_register_t core_mask) - this + * exits the clstr from standby state thru the normal path + */ + +func _psci_clstr_exit_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 /* x5 = core mask */ + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x5 = core mask */ + + /* perform any SoC-specific programming after standby state */ + mov x0, x5 + bl _soc_clstr_exit_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_clstr_exit_stdby + +#endif + +#if (SOC_CLUSTER_PWR_DWN) + +.global _psci_clstr_prep_pwrdn +.global _psci_clstr_exit_pwrdn + +/* + * void _psci_clstr_prep_pwrdn_(u_register_t core_mask) + * this function prepares the cluster+core for power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_clstr_prep_pwrdn + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x6, x0 /* x6 = core mask */ + + /* mask interrupts by setting DAIF[7:4] to 'b1111 */ + msr DAIFSet, #0xF + + /* save scr_el3 */ + mov x0, x6 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* save cpuectlr */ + mov x0, x6 + mov x1, #CPUECTLR_DATA + mrs x2, CPUECTLR_EL1 + mov x4, x2 + bl _setCoreData + + /* remove core from coherency */ + bic x4, x4, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x4 + + /* x6 = core mask */ + + /* SoC-specific programming for power-down */ + mov x0, x6 + bl _soc_clstr_prep_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_clstr_prep_pwrdn + +/* + * void _psci_clstr_exit_pwrdn_(u_register_t core_mask) + * this function cleans up after a cluster power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_clstr_exit_pwrdn + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x4, x0 /* x4 = core mask */ + + /* restore scr_el3 */ + mov x0, x4 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x4 = core mask */ + + /* restore cpuectlr */ + mov x0, x4 + mov x1, #CPUECTLR_DATA + bl _getCoreData + /* make sure smp is set */ + orr x0, x0, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x0 + + /* x4 = core mask */ + + /* SoC-specific cleanup */ + mov x0, x4 + bl _soc_clstr_exit_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_clstr_exit_pwrdn + +#endif + +#if (SOC_SYSTEM_STANDBY) + +.global _psci_sys_prep_stdby +.global _psci_sys_exit_stdby + +/* + * void _psci_sys_prep_stdby(u_register_t core_mask) - this + * sets up the system to enter standby state thru the normal path + */ + +func _psci_sys_prep_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 /* x5 = core mask */ + + /* save scr_el3 */ + mov x0, x5 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* x5 = core mask */ + + /* call for any SoC-specific programming */ + mov x0, x5 + bl _soc_sys_prep_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_sys_prep_stdby + +/* + * void _psci_sys_exit_stdby(u_register_t core_mask) - this + * exits the system from standby state thru the normal path + */ + +func _psci_sys_exit_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 + + /* x5 = core mask */ + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x5 = core mask */ + + /* perform any SoC-specific programming after standby state */ + mov x0, x5 + bl _soc_sys_exit_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_sys_exit_stdby + +#endif + +#if (SOC_SYSTEM_PWR_DWN) + +.global _psci_sys_prep_pwrdn +.global _psci_sys_pwrdn_wfi +.global _psci_sys_exit_pwrdn + +/* + * void _psci_sys_prep_pwrdn_(u_register_t core_mask) + * this function prepares the system+core for power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_sys_prep_pwrdn + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x6, x0 /* x6 = core mask */ + + /* mask interrupts by setting DAIF[7:4] to 'b1111 */ + msr DAIFSet, #0xF + + /* save scr_el3 */ + mov x0, x6 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* save cpuectlr */ + mov x0, x6 + mov x1, #CPUECTLR_DATA + mrs x2, CPUECTLR_EL1 + mov x4, x2 + bl _setCoreData + + /* remove core from coherency */ + bic x4, x4, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x4 + + /* x6 = core mask */ + + /* SoC-specific programming for power-down */ + mov x0, x6 + bl _soc_sys_prep_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_sys_prep_pwrdn + + +/* + * void _psci_sys_pwrdn_wfi(u_register_t core_mask, u_register_t resume_addr) + * this function powers down the system + */ + +func _psci_sys_pwrdn_wfi + /* save the wakeup address */ + mov x29, x1 + + /* x0 = core mask */ + + /* shutdown the system */ + bl _soc_sys_pwrdn_wfi + + /* branch to resume execution */ + br x29 +endfunc _psci_sys_pwrdn_wfi + +/* + * void _psci_sys_exit_pwrdn_(u_register_t core_mask) + * this function cleans up after a system power-down + * x0 = core mask + * + * Called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_sys_exit_pwrdn + + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x4, x0 /* x4 = core mask */ + + /* restore scr_el3 */ + mov x0, x4 + mov x1, #SCR_EL3_DATA + bl _getCoreData + + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x4 = core mask */ + + /* restore cpuectlr */ + mov x0, x4 + mov x1, #CPUECTLR_DATA + bl _getCoreData + + /* make sure smp is set */ + orr x0, x0, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x0 + + /* x4 = core mask */ + + /* SoC-specific cleanup */ + mov x0, x4 + bl _soc_sys_exit_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + b psci_completed +endfunc _psci_sys_exit_pwrdn + +#endif + + +/* psci std returns */ +func psci_disabled + ldr w0, =PSCI_E_DISABLED + b psci_completed +endfunc psci_disabled + + +func psci_not_present + ldr w0, =PSCI_E_NOT_PRESENT + b psci_completed +endfunc psci_not_present + + +func psci_on_pending + ldr w0, =PSCI_E_ON_PENDING + b psci_completed +endfunc psci_on_pending + + +func psci_already_on + ldr w0, =PSCI_E_ALREADY_ON + b psci_completed +endfunc psci_already_on + + +func psci_failure + ldr w0, =PSCI_E_INTERN_FAIL + b psci_completed +endfunc psci_failure + + +func psci_unimplemented + ldr w0, =PSCI_E_NOT_SUPPORTED + b psci_completed +endfunc psci_unimplemented + + +func psci_denied + ldr w0, =PSCI_E_DENIED + b psci_completed +endfunc psci_denied + + +func psci_invalid + ldr w0, =PSCI_E_INVALID_PARAMS + b psci_completed +endfunc psci_invalid + + +func psci_success + mov x0, #PSCI_E_SUCCESS +endfunc psci_success + + +func psci_completed + /* x0 = status code */ + ret +endfunc psci_completed diff --git a/arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h b/arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h new file mode 100644 index 0000000..7fc48fb --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h @@ -0,0 +1,145 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_PSCI_H +#define PLAT_PSCI_H +#include +#include + + /* core abort current op */ +#define CORE_ABORT_OP 0x1 + + /* psci power levels - these are actually affinity levels + * in the psci_power_state_t array + */ +#define PLAT_CORE_LVL PSCI_CPU_PWR_LVL +#define PLAT_CLSTR_LVL U(1) +#define PLAT_SYS_LVL U(2) +#define PLAT_MAX_LVL PLAT_SYS_LVL + + /* core state */ + /* OFF states 0x0 - 0xF */ +#define CORE_IN_RESET 0x0 +#define CORE_DISABLED 0x1 +#define CORE_OFF 0x2 +#define CORE_STANDBY 0x3 +#define CORE_PWR_DOWN 0x4 +#define CORE_WFE 0x6 +#define CORE_WFI 0x7 +#define CORE_LAST 0x8 +#define CORE_OFF_PENDING 0x9 +#define CORE_WORKING_INIT 0xA +#define SYS_OFF_PENDING 0xB +#define SYS_OFF 0xC + + /* ON states 0x10 - 0x1F */ +#define CORE_PENDING 0x10 +#define CORE_RELEASED 0x11 +#define CORE_WAKEUP 0x12 + /* highest off state */ +#define CORE_OFF_MAX 0xF + /* lowest on state */ +#define CORE_ON_MIN CORE_PENDING + +#define DAIF_SET_MASK 0x3C0 +#define SCTLR_I_C_M_MASK 0x00001005 +#define SCTLR_C_MASK 0x00000004 +#define SCTLR_I_MASK 0x00001000 +#define CPUACTLR_L1PCTL_MASK 0x0000E000 +#define DCSR_RCPM2_BASE 0x20170000 +#define CPUECTLR_SMPEN_MASK 0x40 +#define CPUECTLR_SMPEN_EN 0x40 +#define CPUECTLR_RET_MASK 0x7 +#define CPUECTLR_RET_SET 0x2 +#define CPUECTLR_TIMER_MASK 0x7 +#define CPUECTLR_TIMER_8TICKS 0x2 +#define CPUECTLR_TIMER_2TICKS 0x1 +#define SCR_IRQ_MASK 0x2 +#define SCR_FIQ_MASK 0x4 + +/* pwr mgmt features supported in the soc-specific code: + * value == 0x0, the soc code does not support this feature + * value != 0x0, the soc code supports this feature + */ +#ifndef SOC_CORE_RELEASE +#define SOC_CORE_RELEASE 0x1 +#endif + +#ifndef SOC_CORE_RESTART +#define SOC_CORE_RESTART 0x1 +#endif + +#ifndef SOC_CORE_OFF +#define SOC_CORE_OFF 0x1 +#endif + +#ifndef SOC_CORE_STANDBY +#define SOC_CORE_STANDBY 0x1 +#endif + +#ifndef SOC_CORE_PWR_DWN +#define SOC_CORE_PWR_DWN 0x1 +#endif + +#ifndef SOC_CLUSTER_STANDBY +#define SOC_CLUSTER_STANDBY 0x1 +#endif + +#ifndef SOC_CLUSTER_PWR_DWN +#define SOC_CLUSTER_PWR_DWN 0x1 +#endif + +#ifndef SOC_SYSTEM_STANDBY +#define SOC_SYSTEM_STANDBY 0x1 +#endif + +#ifndef SOC_SYSTEM_PWR_DWN +#define SOC_SYSTEM_PWR_DWN 0x1 +#endif + +#ifndef SOC_SYSTEM_OFF +#define SOC_SYSTEM_OFF 0x1 +#endif + +#ifndef SOC_SYSTEM_RESET +#define SOC_SYSTEM_RESET 0x1 +#endif + +#ifndef SOC_SYSTEM_RESET2 +#define SOC_SYSTEM_RESET2 0x1 +#endif + +#ifndef __ASSEMBLER__ + +void __dead2 _psci_system_reset(void); +void __dead2 _psci_system_off(void); +int _psci_cpu_on(u_register_t core_mask); +void _psci_cpu_prep_off(u_register_t core_mask); +void __dead2 _psci_cpu_off_wfi(u_register_t core_mask, + u_register_t wakeup_address); +void __dead2 _psci_cpu_pwrdn_wfi(u_register_t core_mask, + u_register_t wakeup_address); +void __dead2 _psci_sys_pwrdn_wfi(u_register_t core_mask, + u_register_t wakeup_address); +void _psci_wakeup(u_register_t core_mask); +void _psci_core_entr_stdby(u_register_t core_mask); +void _psci_core_prep_stdby(u_register_t core_mask); +void _psci_core_exit_stdby(u_register_t core_mask); +void _psci_core_prep_pwrdn(u_register_t core_mask); +void _psci_core_exit_pwrdn(u_register_t core_mask); +void _psci_clstr_prep_stdby(u_register_t core_mask); +void _psci_clstr_exit_stdby(u_register_t core_mask); +void _psci_clstr_prep_pwrdn(u_register_t core_mask); +void _psci_clstr_exit_pwrdn(u_register_t core_mask); +void _psci_sys_prep_stdby(u_register_t core_mask); +void _psci_sys_exit_stdby(u_register_t core_mask); +void _psci_sys_prep_pwrdn(u_register_t core_mask); +void _psci_sys_exit_pwrdn(u_register_t core_mask); + +#endif + +#endif /* __PLAT_PSCI_H__ */ diff --git a/arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c b/arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c new file mode 100644 index 0000000..9281e97 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c @@ -0,0 +1,475 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#ifdef NXP_WARM_BOOT +#include +#endif + +#include + +#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN) +static void __dead2 _no_return_wfi(void) +{ +_bl31_dead_wfi: + wfi(); + goto _bl31_dead_wfi; +} +#endif + +#if (SOC_CORE_RELEASE || SOC_CORE_PWR_DWN) + /* the entry for core warm boot */ +static uintptr_t warmboot_entry = (uintptr_t) NULL; +#endif + +#if (SOC_CORE_RELEASE) +static int _pwr_domain_on(u_register_t mpidr) +{ + int core_pos = plat_core_pos(mpidr); + int rc = PSCI_E_INVALID_PARAMS; + u_register_t core_mask; + + if (core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT) { + + _soc_set_start_addr(warmboot_entry); + + dsb(); + isb(); + + core_mask = (1 << core_pos); + rc = _psci_cpu_on(core_mask); + } + + return (rc); +} +#endif + +#if (SOC_CORE_OFF) +static void _pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state = _getCoreState(core_mask); + + /* set core state in internal data */ + core_state = CORE_OFF_PENDING; + _setCoreState(core_mask, core_state); + + _psci_cpu_prep_off(core_mask); +} +#endif + +#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN) +static void __dead2 _pwr_down_wfi(const psci_power_state_t *target_state) +{ + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state = _getCoreState(core_mask); + + switch (core_state) { +#if (SOC_CORE_OFF) + case CORE_OFF_PENDING: + /* set core state in internal data */ + core_state = CORE_OFF; + _setCoreState(core_mask, core_state); + + /* turn the core off */ + _psci_cpu_off_wfi(core_mask, warmboot_entry); + break; +#endif +#if (SOC_CORE_PWR_DWN) + case CORE_PWR_DOWN: + /* power-down the core */ + _psci_cpu_pwrdn_wfi(core_mask, warmboot_entry); + break; +#endif +#if (SOC_SYSTEM_PWR_DWN) + case SYS_OFF_PENDING: + /* set core state in internal data */ + core_state = SYS_OFF; + _setCoreState(core_mask, core_state); + + /* power-down the system */ + _psci_sys_pwrdn_wfi(core_mask, warmboot_entry); + break; +#endif + default: + _no_return_wfi(); + break; + } +} +#endif + +#if (SOC_CORE_RELEASE || SOC_CORE_RESTART) +static void _pwr_domain_wakeup(const psci_power_state_t *target_state) +{ + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state = _getCoreState(core_mask); + + switch (core_state) { + case CORE_PENDING: /* this core is coming out of reset */ + + /* soc per cpu setup */ + soc_init_percpu(); + + /* gic per cpu setup */ + plat_gic_pcpu_init(); + + /* set core state in internal data */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); + break; + +#if (SOC_CORE_RESTART) + case CORE_WAKEUP: + + /* this core is waking up from OFF */ + _psci_wakeup(core_mask); + + /* set core state in internal data */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); + + break; +#endif + } +} +#endif + +#if (SOC_CORE_STANDBY) +static void _pwr_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state; + + if (cpu_state == PLAT_MAX_RET_STATE) { + + /* set core state to standby */ + core_state = CORE_STANDBY; + _setCoreState(core_mask, core_state); + + _psci_core_entr_stdby(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); + } +} +#endif + +#if (SOC_CORE_PWR_DWN) +static void _pwr_suspend(const psci_power_state_t *state) +{ + + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state; + + if (state->pwr_domain_state[PLAT_MAX_LVL] == PLAT_MAX_OFF_STATE) { +#if (SOC_SYSTEM_PWR_DWN) + _psci_sys_prep_pwrdn(core_mask); + + /* set core state */ + core_state = SYS_OFF_PENDING; + _setCoreState(core_mask, core_state); +#endif + } else if (state->pwr_domain_state[PLAT_MAX_LVL] + == PLAT_MAX_RET_STATE) { +#if (SOC_SYSTEM_STANDBY) + _psci_sys_prep_stdby(core_mask); + + /* set core state */ + core_state = CORE_STANDBY; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CLSTR_LVL] == + PLAT_MAX_OFF_STATE) { +#if (SOC_CLUSTER_PWR_DWN) + _psci_clstr_prep_pwrdn(core_mask); + + /* set core state */ + core_state = CORE_PWR_DOWN; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CLSTR_LVL] == + PLAT_MAX_RET_STATE) { +#if (SOC_CLUSTER_STANDBY) + _psci_clstr_prep_stdby(core_mask); + + /* set core state */ + core_state = CORE_STANDBY; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_OFF_STATE) { +#if (SOC_CORE_PWR_DWN) + /* prep the core for power-down */ + _psci_core_prep_pwrdn(core_mask); + + /* set core state */ + core_state = CORE_PWR_DOWN; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_RET_STATE) { +#if (SOC_CORE_STANDBY) + _psci_core_prep_stdby(core_mask); + + /* set core state */ + core_state = CORE_STANDBY; + _setCoreState(core_mask, core_state); +#endif + } + +} +#endif + +#if (SOC_CORE_PWR_DWN) +static void _pwr_suspend_finish(const psci_power_state_t *state) +{ + + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state; + + + if (state->pwr_domain_state[PLAT_MAX_LVL] == PLAT_MAX_OFF_STATE) { +#if (SOC_SYSTEM_PWR_DWN) + _psci_sys_exit_pwrdn(core_mask); + + /* when we are here, the core is back up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } else if (state->pwr_domain_state[PLAT_MAX_LVL] + == PLAT_MAX_RET_STATE) { +#if (SOC_SYSTEM_STANDBY) + _psci_sys_exit_stdby(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CLSTR_LVL] == + PLAT_MAX_OFF_STATE) { +#if (SOC_CLUSTER_PWR_DWN) + _psci_clstr_exit_pwrdn(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CLSTR_LVL] == + PLAT_MAX_RET_STATE) { +#if (SOC_CLUSTER_STANDBY) + _psci_clstr_exit_stdby(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_OFF_STATE) { +#if (SOC_CORE_PWR_DWN) + _psci_core_exit_pwrdn(core_mask); + + /* when we are here, the core is back up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_RET_STATE) { +#if (SOC_CORE_STANDBY) + _psci_core_exit_stdby(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + +} +#endif + +#if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN) + +#define PWR_STATE_TYPE_MASK 0x00010000 +#define PWR_STATE_TYPE_STNDBY 0x0 +#define PWR_STATE_TYPE_PWRDWN 0x00010000 +#define PWR_STATE_LVL_MASK 0x03000000 +#define PWR_STATE_LVL_CORE 0x0 +#define PWR_STATE_LVL_CLSTR 0x01000000 +#define PWR_STATE_LVL_SYS 0x02000000 +#define PWR_STATE_LVL_MAX 0x03000000 + + /* turns a requested power state into a target power state + * based on SoC capabilities + */ +static int _pwr_state_validate(uint32_t pwr_state, + psci_power_state_t *state) +{ + int stat = PSCI_E_INVALID_PARAMS; + int pwrdn = (pwr_state & PWR_STATE_TYPE_MASK); + int lvl = (pwr_state & PWR_STATE_LVL_MASK); + + switch (lvl) { + case PWR_STATE_LVL_MAX: + if (pwrdn && SOC_SYSTEM_PWR_DWN) + state->pwr_domain_state[PLAT_MAX_LVL] = + PLAT_MAX_OFF_STATE; + else if (SOC_SYSTEM_STANDBY) + state->pwr_domain_state[PLAT_MAX_LVL] = + PLAT_MAX_RET_STATE; + /* intentional fall-thru condition */ + case PWR_STATE_LVL_SYS: + if (pwrdn && SOC_SYSTEM_PWR_DWN) + state->pwr_domain_state[PLAT_SYS_LVL] = + PLAT_MAX_OFF_STATE; + else if (SOC_SYSTEM_STANDBY) + state->pwr_domain_state[PLAT_SYS_LVL] = + PLAT_MAX_RET_STATE; + /* intentional fall-thru condition */ + case PWR_STATE_LVL_CLSTR: + if (pwrdn && SOC_CLUSTER_PWR_DWN) + state->pwr_domain_state[PLAT_CLSTR_LVL] = + PLAT_MAX_OFF_STATE; + else if (SOC_CLUSTER_STANDBY) + state->pwr_domain_state[PLAT_CLSTR_LVL] = + PLAT_MAX_RET_STATE; + /* intentional fall-thru condition */ + case PWR_STATE_LVL_CORE: + stat = PSCI_E_SUCCESS; + + if (pwrdn && SOC_CORE_PWR_DWN) + state->pwr_domain_state[PLAT_CORE_LVL] = + PLAT_MAX_OFF_STATE; + else if (SOC_CORE_STANDBY) + state->pwr_domain_state[PLAT_CORE_LVL] = + PLAT_MAX_RET_STATE; + break; + } + return (stat); +} + +#endif + +#if (SOC_SYSTEM_PWR_DWN) +static void _pwr_state_sys_suspend(psci_power_state_t *req_state) +{ + + /* if we need to have per-SoC settings, then we need to + * extend this by calling into psci_utils.S and from there + * on down to the SoC.S files + */ + + req_state->pwr_domain_state[PLAT_MAX_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[PLAT_SYS_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[PLAT_CLSTR_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[PLAT_CORE_LVL] = PLAT_MAX_OFF_STATE; + +} +#endif + +#if defined(NXP_WARM_BOOT) && (SOC_SYSTEM_RESET2) +static int psci_system_reset2(int is_vendor, + int reset_type, + u_register_t cookie) +{ + int ret = 0; + + INFO("Executing the sequence of warm reset.\n"); + ret = prep_n_execute_warm_reset(); + + return ret; +} +#endif + +static plat_psci_ops_t _psci_pm_ops = { +#if (SOC_SYSTEM_OFF) + .system_off = _psci_system_off, +#endif +#if (SOC_SYSTEM_RESET) + .system_reset = _psci_system_reset, +#endif +#if defined(NXP_WARM_BOOT) && (SOC_SYSTEM_RESET2) + .system_reset2 = psci_system_reset2, +#endif +#if (SOC_CORE_RELEASE || SOC_CORE_RESTART) + /* core released or restarted */ + .pwr_domain_on_finish = _pwr_domain_wakeup, +#endif +#if (SOC_CORE_OFF) + /* core shutting down */ + .pwr_domain_off = _pwr_domain_off, +#endif +#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN) + .pwr_domain_pwr_down_wfi = _pwr_down_wfi, +#endif +#if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN) + /* cpu_suspend */ + .validate_power_state = _pwr_state_validate, +#if (SOC_CORE_STANDBY) + .cpu_standby = _pwr_cpu_standby, +#endif +#if (SOC_CORE_PWR_DWN) + .pwr_domain_suspend = _pwr_suspend, + .pwr_domain_suspend_finish = _pwr_suspend_finish, +#endif +#endif +#if (SOC_SYSTEM_PWR_DWN) + .get_sys_suspend_power_state = _pwr_state_sys_suspend, +#endif +#if (SOC_CORE_RELEASE) + /* core executing psci_cpu_on */ + .pwr_domain_on = _pwr_domain_on +#endif +}; + +#if (SOC_CORE_RELEASE || SOC_CORE_PWR_DWN) +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + warmboot_entry = sec_entrypoint; + *psci_ops = &_psci_pm_ops; + return 0; +} + +#else + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &_psci_pm_ops; + return 0; +} +#endif diff --git a/arm-trusted-firmware/plat/nxp/common/psci/psci.mk b/arm-trusted-firmware/plat/nxp/common/psci/psci.mk new file mode 100644 index 0000000..a2791c2 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/psci/psci.mk @@ -0,0 +1,35 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the PSCI files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_PSCI},) + +ADD_PSCI := 1 +PLAT_PSCI_PATH := $(PLAT_COMMON_PATH)/psci + +PSCI_SOURCES := ${PLAT_PSCI_PATH}/plat_psci.c \ + ${PLAT_PSCI_PATH}/$(ARCH)/psci_utils.S \ + plat/common/plat_psci_common.c + +PLAT_INCLUDES += -I${PLAT_PSCI_PATH}/include + +ifeq (${BL_COMM_PSCI_NEEDED},yes) +BL_COMMON_SOURCES += ${PSCI_SOURCES} +else +ifeq (${BL2_PSCI_NEEDED},yes) +BL2_SOURCES += ${PSCI_SOURCES} +endif +ifeq (${BL31_PSCI_NEEDED},yes) +BL31_SOURCES += ${PSCI_SOURCES} +endif +endif +endif +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c new file mode 100644 index 0000000..7463d47 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c @@ -0,0 +1,103 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#ifdef CSF_HEADER_PREPENDED +#include +#endif +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = LS_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), +#ifdef CSF_HEADER_PREPENDED + .image_info.image_base = BL31_BASE - CSF_HDR_SZ, + .image_info.image_max_size = (BL31_LIMIT - BL31_BASE) + + CSF_HDR_SZ, +#else + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = (BL31_LIMIT - BL31_BASE), +#endif + +# ifdef NXP_LOAD_BL32 + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, +# ifdef NXP_LOAD_BL32 + /* Fill BL32 related information */ + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), +#ifdef CSF_HEADER_PREPENDED + .image_info.image_base = BL32_BASE - CSF_HDR_SZ, + .image_info.image_max_size = (BL32_LIMIT - BL32_BASE) + + CSF_HDR_SZ, +#else + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = (BL32_LIMIT - BL32_BASE), +#endif + .next_handoff_image_id = BL33_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), + .ep_info.pc = BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), +#ifdef CSF_HEADER_PREPENDED + .image_info.image_base = BL33_BASE - CSF_HDR_SZ, + .image_info.image_max_size = (BL33_LIMIT - BL33_BASE) + + CSF_HDR_SZ, +#else + .image_info.image_base = BL33_BASE, + .image_info.image_max_size = BL33_LIMIT - BL33_BASE, +#endif + .ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/nxp/common/setup/common.mk b/arm-trusted-firmware/plat/nxp/common/setup/common.mk new file mode 100644 index 0000000..1fcf1d0 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/common.mk @@ -0,0 +1,105 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +############################################################################### +# Flow begins in BL2 at EL3 mode +BL2_AT_EL3 := 1 + +# Though one core is powered up by default, there are +# platform specific ways to release more than one core +COLD_BOOT_SINGLE_CPU := 0 + +PROGRAMMABLE_RESET_ADDRESS := 1 + +USE_COHERENT_MEM := 0 + +# Use generic OID definition (tbbr_oid.h) +USE_TBBR_DEFS := 1 + +PLAT_XLAT_TABLES_DYNAMIC := 0 + +ENABLE_SVE_FOR_NS := 0 + +ENABLE_STACK_PROTECTOR := 0 + +ERROR_DEPRECATED := 0 + +LS_DISABLE_TRUSTED_WDOG := 1 + +# On ARM platforms, separate the code and read-only data sections to allow +# mapping the former as executable and the latter as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# Enable new version of image loading on ARM platforms +LOAD_IMAGE_V2 := 1 + +RCW := "" + +ifneq (${SPD},none) +$(eval $(call add_define, NXP_LOAD_BL32)) +endif + +############################################################################### + +PLAT_TOOL_PATH := tools/nxp +CREATE_PBL_TOOL_PATH := ${PLAT_TOOL_PATH}/create_pbl +PLAT_SETUP_PATH := ${PLAT_PATH}/common/setup + +PLAT_INCLUDES += -I${PLAT_SETUP_PATH}/include \ + -Iinclude/plat/arm/common \ + -Iinclude/drivers/arm \ + -Iinclude/lib \ + -Iinclude/drivers/io \ + -Ilib/psci + +# Required without TBBR. +# To include the defines for DDR PHY Images. +PLAT_INCLUDES += -Iinclude/common/tbbr + +include ${PLAT_SETUP_PATH}/core.mk +PLAT_BL_COMMON_SOURCES += ${CPU_LIBS} \ + plat/nxp/common/setup/ls_err.c \ + plat/nxp/common/setup/ls_common.c + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${PLAT_SETUP_PATH}/ls_stack_protector.c +endif + +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +BL2_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + common/desc_image_load.c \ + plat/nxp/common/setup/ls_image_load.c \ + plat/nxp/common/setup/ls_io_storage.c \ + plat/nxp/common/setup/ls_bl2_el3_setup.c \ + plat/nxp/common/setup/${ARCH}/ls_bl2_mem_params_desc.c + +BL31_SOURCES += plat/nxp/common/setup/ls_bl31_setup.c \ + +ifeq (${LS_EL3_INTERRUPT_HANDLER}, yes) +$(eval $(call add_define, LS_EL3_INTERRUPT_HANDLER)) +BL31_SOURCES += plat/nxp/common/setup/ls_interrupt_mgmt.c +endif + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${TEST_SOURCES} +endif + +# Verify build config +# ------------------- + +ifneq (${LOAD_IMAGE_V2}, 1) + $(error Error: Layerscape needs LOAD_IMAGE_V2=1) +else +$(eval $(call add_define,LOAD_IMAGE_V2)) +endif + +include $(CREATE_PBL_TOOL_PATH)/create_pbl.mk diff --git a/arm-trusted-firmware/plat/nxp/common/setup/core.mk b/arm-trusted-firmware/plat/nxp/common/setup/core.mk new file mode 100644 index 0000000..82ce30e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/core.mk @@ -0,0 +1,22 @@ +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the CORE files +# +# ----------------------------------------------------------------------------- + +CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +ifeq (,$(filter $(CORE_TYPE),a53 a72)) +$(error "CORE_TYPE not specified or incorrect") +else +UPPER_CORE_TYPE=$(shell echo $(CORE_TYPE) | tr a-z A-Z) +$(eval $(call add_define_val,CPUECTLR_EL1,CORTEX_$(UPPER_CORE_TYPE)_ECTLR_EL1)) +CPU_LIBS += lib/cpus/${ARCH}/cortex_$(CORE_TYPE).S +endif + +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h b/arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h new file mode 100644 index 0000000..dd20d43 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h @@ -0,0 +1,61 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef BL31_DATA_H +#define BL31_DATA_H + +#define SECURE_DATA_BASE NXP_OCRAM_ADDR +#define SECURE_DATA_SIZE NXP_OCRAM_SIZE +#define SECURE_DATA_TOP (SECURE_DATA_BASE + SECURE_DATA_SIZE) +#define SMC_REGION_SIZE 0x80 +#define SMC_GLBL_BASE (SECURE_DATA_TOP - SMC_REGION_SIZE) +#define BC_PSCI_DATA_SIZE 0xC0 +#define BC_PSCI_BASE (SMC_GLBL_BASE - BC_PSCI_DATA_SIZE) +#define SECONDARY_TOP BC_PSCI_BASE + +#define SEC_PSCI_DATA_SIZE 0xC0 +#define SEC_REGION_SIZE SEC_PSCI_DATA_SIZE + +/* SMC global data */ +#define BOOTLOC_OFFSET 0x0 +#define BOOT_SVCS_OSET 0x8 + +/* offset to prefetch disable mask */ +#define PREFETCH_DIS_OFFSET 0x10 +/* must reference last smc global entry */ +#define LAST_SMC_GLBL_OFFSET 0x18 + +#define SMC_TASK_OFFSET 0xC +#define TSK_START_OFFSET 0x0 +#define TSK_DONE_OFFSET 0x4 +#define TSK_CORE_OFFSET 0x8 +#define SMC_TASK1_BASE (SMC_GLBL_BASE + 32) +#define SMC_TASK2_BASE (SMC_TASK1_BASE + SMC_TASK_OFFSET) +#define SMC_TASK3_BASE (SMC_TASK2_BASE + SMC_TASK_OFFSET) +#define SMC_TASK4_BASE (SMC_TASK3_BASE + SMC_TASK_OFFSET) + +/* psci data area offsets */ +#define CORE_STATE_DATA 0x0 +#define SPSR_EL3_DATA 0x8 +#define CNTXT_ID_DATA 0x10 +#define START_ADDR_DATA 0x18 +#define LINK_REG_DATA 0x20 +#define GICC_CTLR_DATA 0x28 +#define ABORT_FLAG_DATA 0x30 +#define SCTLR_DATA 0x38 +#define CPUECTLR_DATA 0x40 +#define AUX_01_DATA 0x48 /* usage defined per SoC */ +#define AUX_02_DATA 0x50 /* usage defined per SoC */ +#define AUX_03_DATA 0x58 /* usage defined per SoC */ +#define AUX_04_DATA 0x60 /* usage defined per SoC */ +#define AUX_05_DATA 0x68 /* usage defined per SoC */ +#define AUX_06_DATA 0x70 /* usage defined per SoC */ +#define AUX_07_DATA 0x78 /* usage defined per SoC */ +#define SCR_EL3_DATA 0x80 +#define HCR_EL2_DATA 0x88 + +#endif /* BL31_DATA_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h b/arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h new file mode 100644 index 0000000..7dbddfb --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h @@ -0,0 +1,23 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef LS_EL3_INTRPT_MGMT_H +#define LS_EL3_INTRPT_MGMT_H + +#include + +#define MAX_INTR_EL3 128 + +/* + * Register handler to specific GIC entrance + * for INTR_TYPE_EL3 type of interrupt + */ +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler); + +void ls_el3_interrupt_config(void); + +#endif /* LS_EL3_INTRPT_MGMT_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h b/arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h new file mode 100644 index 0000000..2a7771b --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef MMU_MAP_DEF_H +#define MMU_MAP_DEF_H + +#include + +#include + + +#define LS_MAP_CCSR MAP_REGION_FLAT(NXP_CCSR_ADDR, \ + NXP_CCSR_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef NXP_DCSR_ADDR +#define LS_MAP_DCSR MAP_REGION_FLAT(NXP_DCSR_ADDR, \ + NXP_DCSR_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#define LS_MAP_CONSOLE MAP_REGION_FLAT(NXP_DUART1_ADDR, \ + NXP_DUART_SIZE, \ + MT_DEVICE | MT_RW | MT_NS) + +#define LS_MAP_OCRAM MAP_REGION_FLAT(NXP_OCRAM_ADDR, \ + NXP_OCRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#endif /* MMU_MAP_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h b/arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h new file mode 100644 index 0000000..e13f45c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h @@ -0,0 +1,152 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_COMMON_H +#define PLAT_COMMON_H + +#include + +#include +#include + +#include + +#ifdef IMAGE_BL31 + +#define BL31_END (uintptr_t)(&__BL31_END__) + +/******************************************************************************* + * This structure represents the superset of information that can be passed to + * BL31 e.g. while passing control to it from BL2. The BL32 parameters will be + * populated only if BL2 detects its presence. A pointer to a structure of this + * type should be passed in X0 to BL31's cold boot entrypoint. + * + * Use of this structure and the X0 parameter is not mandatory: the BL31 + * platform code can use other mechanisms to provide the necessary information + * about BL32 and BL33 to the common and SPD code. + * + * BL31 image information is mandatory if this structure is used. If either of + * the optional BL32 and BL33 image information is not provided, this is + * indicated by the respective image_info pointers being zero. + ******************************************************************************/ +typedef struct bl31_params { + 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; +} bl31_params_t; + +/* BL3 utility functions */ +void ls_bl31_early_platform_setup(void *from_bl2, + void *plat_params_from_bl2); +/* LS Helper functions */ +unsigned int plat_my_core_mask(void); +unsigned int plat_core_mask(u_register_t mpidr); +unsigned int plat_core_pos(u_register_t mpidr); +//unsigned int plat_my_core_pos(void); + +/* BL31 Data API(s) */ +void _init_global_data(void); +void _initialize_psci(void); +uint32_t _getCoreState(u_register_t core_mask); +void _setCoreState(u_register_t core_mask, u_register_t core_state); + +/* SoC defined structure and API(s) */ +void soc_runtime_setup(void); +void soc_init(void); +void soc_platform_setup(void); +void soc_early_platform_setup2(void); +#endif /* IMAGE_BL31 */ + +#ifdef IMAGE_BL2 +void soc_early_init(void); +void soc_mem_access(void); +void soc_preload_setup(void); +void soc_bl2_prepare_exit(void); + +/* IO storage utility functions */ +int plat_io_setup(void); +int open_backend(const uintptr_t spec); + +void ls_bl2_plat_arch_setup(void); +void ls_bl2_el3_plat_arch_setup(void); + +enum boot_device { + BOOT_DEVICE_IFC_NOR, + BOOT_DEVICE_IFC_NAND, + BOOT_DEVICE_QSPI, + BOOT_DEVICE_EMMC, + BOOT_DEVICE_SDHC2_EMMC, + BOOT_DEVICE_FLEXSPI_NOR, + BOOT_DEVICE_FLEXSPI_NAND, + BOOT_DEVICE_NONE +}; + +enum boot_device get_boot_dev(void); + +/* DDR Related functions */ +#if DDR_INIT +#ifdef NXP_WARM_BOOT +long long init_ddr(uint32_t wrm_bt_flg); +#else +long long init_ddr(void); +#endif +#endif + +/* Board specific weak functions */ +bool board_enable_povdd(void); +bool board_disable_povdd(void); + +void mmap_add_ddr_region_dynamically(void); +#endif /* IMAGE_BL2 */ + +typedef struct { + uint64_t addr; + uint64_t size; +} region_info_t; + +typedef struct { + uint64_t num_dram_regions; + int64_t total_dram_size; + region_info_t region[NUM_DRAM_REGIONS]; +} dram_regions_info_t; + +dram_regions_info_t *get_dram_regions_info(void); + +void ls_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, + uintptr_t coh_limit +#endif +); + +#define SOC_NAME_MAX_LEN (20) + +/* Structure to define SoC personality */ +struct soc_type { + char name[SOC_NAME_MAX_LEN]; + uint32_t version; + uint8_t num_clusters; + uint8_t cores_per_cluster; +}; +void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count, + uint8_t *num_clusters, uint8_t *cores_per_cluster); + +#define SOC_ENTRY(n, v, ncl, nc) { \ + .name = #n, \ + .version = SVR_##v, \ + .num_clusters = (ncl), \ + .cores_per_cluster = (nc)} + +#endif /* PLAT_COMMON_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S b/arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S new file mode 100644 index 0000000..69a3b08 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c new file mode 100644 index 0000000..a4cbaef --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c @@ -0,0 +1,303 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#include +#include +#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA +#include +#endif + +#pragma weak bl2_el3_early_platform_setup +#pragma weak bl2_el3_plat_arch_setup +#pragma weak bl2_el3_plat_prepare_exit + +static dram_regions_info_t dram_regions_info = {0}; + +/******************************************************************************* + * Return the pointer to the 'dram_regions_info structure of the DRAM. + * This structure is populated after init_ddr(). + ******************************************************************************/ +dram_regions_info_t *get_dram_regions_info(void) +{ + return &dram_regions_info; +} + +#ifdef DDR_INIT +static void populate_dram_regions_info(void) +{ + long long dram_remain_size = dram_regions_info.total_dram_size; + uint8_t reg_id = 0U; + + dram_regions_info.region[reg_id].addr = NXP_DRAM0_ADDR; + dram_regions_info.region[reg_id].size = + dram_remain_size > NXP_DRAM0_MAX_SIZE ? + NXP_DRAM0_MAX_SIZE : dram_remain_size; + + if (dram_regions_info.region[reg_id].size != NXP_DRAM0_SIZE) { + ERROR("Incorrect DRAM0 size is defined in platform_def.h\n"); + } + + dram_remain_size -= dram_regions_info.region[reg_id].size; + dram_regions_info.region[reg_id].size -= (NXP_SECURE_DRAM_SIZE + + NXP_SP_SHRD_DRAM_SIZE); + + assert(dram_regions_info.region[reg_id].size > 0); + + /* Reducing total dram size by 66MB */ + dram_regions_info.total_dram_size -= (NXP_SECURE_DRAM_SIZE + + NXP_SP_SHRD_DRAM_SIZE); + +#if defined(NXP_DRAM1_ADDR) && defined(NXP_DRAM1_MAX_SIZE) + if (dram_remain_size > 0) { + reg_id++; + dram_regions_info.region[reg_id].addr = NXP_DRAM1_ADDR; + dram_regions_info.region[reg_id].size = + dram_remain_size > NXP_DRAM1_MAX_SIZE ? + NXP_DRAM1_MAX_SIZE : dram_remain_size; + dram_remain_size -= dram_regions_info.region[reg_id].size; + } +#endif +#if defined(NXP_DRAM2_ADDR) && defined(NXP_DRAM2_MAX_SIZE) + if (dram_remain_size > 0) { + reg_id++; + dram_regions_info.region[reg_id].addr = NXP_DRAM1_ADDR; + dram_regions_info.region[reg_id].size = + dram_remain_size > NXP_DRAM1_MAX_SIZE ? + NXP_DRAM1_MAX_SIZE : dram_remain_size; + dram_remain_size -= dram_regions_info.region[reg_id].size; + } +#endif + reg_id++; + dram_regions_info.num_dram_regions = reg_id; +} +#endif + +#ifdef IMAGE_BL32 +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +static uint32_t ls_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0U; +} +#endif + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifndef AARCH32 +static uint32_t ls_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +static uint32_t ls_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* AARCH32 */ + +void bl2_el3_early_platform_setup(u_register_t arg0 __unused, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) +{ + /* + * SoC specific early init + * Any errata handling or SoC specific early initialization can + * be done here + * Set Counter Base Frequency in CNTFID0 and in cntfrq_el0. + * Initialize the interconnect. + * Enable coherency for primary CPU cluster + */ + soc_early_init(); + + /* Initialise the IO layer and register platform IO devices */ + plat_io_setup(); + + if (dram_regions_info.total_dram_size > 0) { + populate_dram_regions_info(); + } + +#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA + read_nv_app_data(); +#if DEBUG + const nv_app_data_t *nv_app_data = get_nv_data(); + + INFO("Value of warm_reset flag = 0x%x\n", nv_app_data->warm_rst_flag); + INFO("Value of WDT flag = 0x%x\n", nv_app_data->wdt_rst_flag); +#endif +#endif +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only initializes the mmu in a quick and dirty way. + ******************************************************************************/ +void ls_bl2_el3_plat_arch_setup(void) +{ + unsigned int flags = 0U; + /* Initialise the IO layer and register platform IO devices */ + ls_setup_page_tables( +#if SEPARATE_BL2_NOLOAD_REGION + BL2_START, + BL2_LIMIT - BL2_START, +#else + BL2_BASE, + (unsigned long)(&__BL2_END__) - BL2_BASE, +#endif + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END +#endif + ); + + if ((dram_regions_info.region[0].addr == 0) + && (dram_regions_info.total_dram_size == 0)) { + flags = XLAT_TABLE_NC; + } + +#ifdef AARCH32 + enable_mmu_secure(0); +#else + enable_mmu_el3(flags); +#endif +} + +void bl2_el3_plat_arch_setup(void) +{ + ls_bl2_el3_plat_arch_setup(); +} + +void bl2_platform_setup(void) +{ + /* + * Perform platform setup before loading the image. + */ +} + +/* Handling image information by platform. */ +int ls_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + assert(bl_mem_params); + + switch (image_id) { + case BL31_IMAGE_ID: + bl_mem_params->ep_info.args.arg3 = + (u_register_t) &dram_regions_info; + + /* Pass the value of PORSR1 register in Argument 4 */ + bl_mem_params->ep_info.args.arg4 = + (u_register_t)read_reg_porsr1(); + flush_dcache_range((uintptr_t)&dram_regions_info, + sizeof(dram_regions_info)); + break; +#if defined(AARCH64) && defined(IMAGE_BL32) + case BL32_IMAGE_ID: + bl_mem_params->ep_info.spsr = ls_get_spsr_for_bl32_entry(); + break; +#endif + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = ls_get_spsr_for_bl33_entry(); + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return ls_bl2_handle_post_image_load(image_id); +} + +void bl2_el3_plat_prepare_exit(void) +{ + return soc_bl2_prepare_exit(); +} + +/* Called to do the dynamic initialization required + * before loading the next image. + */ +void bl2_plat_preload_setup(void) +{ + + soc_preload_setup(); + +#ifdef DDR_INIT + if (dram_regions_info.total_dram_size <= 0) { + ERROR("Asserting as the DDR is not initialized yet."); + assert(false); + } +#endif + + if ((dram_regions_info.region[0].addr == 0) + && (dram_regions_info.total_dram_size > 0)) { + populate_dram_regions_info(); +#ifdef PLAT_XLAT_TABLES_DYNAMIC + mmap_add_ddr_region_dynamically(); +#endif + } + + /* setup the memory region access permissions */ + soc_mem_access(); + +#ifdef POLICY_FUSE_PROVISION + fip_fuse_provisioning((uintptr_t)FUSE_BUF, FUSE_SZ); +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c new file mode 100644 index 0000000..bd0ab4f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c @@ -0,0 +1,212 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#ifdef LS_EL3_INTERRUPT_HANDLER +#include +#endif +#include +#include + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +#ifdef TEST_BL31 +#define SPSR_FOR_EL2H 0x3C9 +#define SPSR_FOR_EL1H 0x3C5 +#else +static entry_point_info_t bl31_image_ep_info; +#endif + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +static dram_regions_info_t dram_regions_info = {0}; +static uint64_t rcw_porsr1; + +/* Return the pointer to the 'dram_regions_info structure of the DRAM. + * This structure is populated after init_ddr(). + */ +dram_regions_info_t *get_dram_regions_info(void) +{ + return &dram_regions_info; +} + +/* Return the RCW.PORSR1 value which was passed in from BL2 + */ +uint64_t bl31_get_porsr1(void) +{ + return rcw_porsr1; +} + +/* + * Return pointer to the 'entry_point_info' structure of the next image for the + * security state specified: + * - BL33 corresponds to the non-secure image type; while + * - BL32 corresponds to the secure image type. + * - A NULL pointer is returned, if the image does not exist. + */ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + +#ifdef TEST_BL31 + next_image_info->pc = _get_test_entry(); + next_image_info->spsr = SPSR_FOR_EL2H; + next_image_info->h.attr = NON_SECURE; +#endif + + if (next_image_info->pc != 0U) { + return next_image_info; + } else { + return NULL; + } +} + +/* + * Perform any BL31 early platform setup common to NXP platforms. + * - Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & S-EL3 in BL1) before they are lost (potentially). + * - This needs to be done before the MMU is initialized so that the + * memory layout can be used while creating page tables. + * - BL2 has flushed this information to memory, in order to fetch latest data. + */ + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ +#ifndef TEST_BL31 + int i = 0; + void *from_bl2 = (void *)arg0; +#endif + soc_early_platform_setup2(); + +#ifdef TEST_BL31 + dram_regions_info.num_dram_regions = 2; + dram_regions_info.total_dram_size = 0x100000000; + dram_regions_info.region[0].addr = 0x80000000; + dram_regions_info.region[0].size = 0x80000000; + dram_regions_info.region[1].addr = 0x880000000; + dram_regions_info.region[1].size = 0x80000000; + + bl33_image_ep_info.pc = _get_test_entry(); +#else + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params != NULL) { + if (bl_params->image_id == BL31_IMAGE_ID) { + bl31_image_ep_info = *bl_params->ep_info; + dram_regions_info_t *loc_dram_regions_info = + (dram_regions_info_t *) bl31_image_ep_info.args.arg3; + + dram_regions_info.num_dram_regions = + loc_dram_regions_info->num_dram_regions; + dram_regions_info.total_dram_size = + loc_dram_regions_info->total_dram_size; + VERBOSE("Number of DRAM Regions = %" PRIx64 "\n", + dram_regions_info.num_dram_regions); + + for (i = 0; i < dram_regions_info.num_dram_regions; + i++) { + dram_regions_info.region[i].addr = + loc_dram_regions_info->region[i].addr; + dram_regions_info.region[i].size = + loc_dram_regions_info->region[i].size; + VERBOSE("DRAM%d Size = %" PRIx64 "\n", i, + dram_regions_info.region[i].size); + } + rcw_porsr1 = bl31_image_ep_info.args.arg4; + } + + if (bl_params->image_id == BL32_IMAGE_ID) { + bl32_image_ep_info = *bl_params->ep_info; + } + + if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + } + + bl_params = bl_params->next_params_info; + } +#endif /* TEST_BL31 */ + + if (bl33_image_ep_info.pc == 0) { + panic(); + } + + /* + * perform basic initialization on the soc + */ + soc_init(); +} + +/******************************************************************************* + * Perform any BL31 platform setup common to ARM standard platforms + ******************************************************************************/ +void bl31_platform_setup(void) +{ + NOTICE("Welcome to %s BL31 Phase\n", BOARD); + soc_platform_setup(); + + /* Console logs gone missing as part going to + * EL1 for initilizing Bl32 if present. + * console flush is necessary to avoid it. + */ + (void)console_flush(); +} + +void bl31_plat_runtime_setup(void) +{ +#ifdef LS_EL3_INTERRUPT_HANDLER + ls_el3_interrupt_config(); +#endif + soc_runtime_setup(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup shared between + * ARM standard platforms. This only does basic initialization. Later + * architectural setup (bl31_arch_setup()) does not do anything platform + * specific. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + + ls_setup_page_tables(BL31_BASE, + BL31_END - BL31_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END +#endif + ); + enable_mmu_el3(0); +} diff --git a/arm-trusted-firmware/plat/nxp/common/setup/ls_common.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_common.c new file mode 100644 index 0000000..e7ae060 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_common.c @@ -0,0 +1,264 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "plat_common.h" +#include "platform_def.h" + +const mmap_region_t *plat_ls_get_mmap(void); + +/* + * Table of memory regions for various BL stages to map using the MMU. + * This doesn't include Trusted SRAM as arm_setup_page_tables() already + * takes care of mapping it. + * + * The flash needs to be mapped as writable in order to erase the FIP's Table of + * Contents in case of unrecoverable error (see plat_error_handler()). + */ +#ifdef IMAGE_BL2 +const mmap_region_t plat_ls_mmap[] = { + LS_MAP_CCSR, + {0} +}; +#endif + +#ifdef IMAGE_BL31 +const mmap_region_t plat_ls_mmap[] = { + LS_MAP_CCSR, +#ifdef NXP_DCSR_ADDR + LS_MAP_DCSR, +#endif + LS_MAP_OCRAM, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_ls_mmap[] = { + LS_MAP_CCSR, + LS_MAP_BL32_SEC_MEM, + {0} +}; +#endif + +/* Weak definitions may be overridden in specific NXP SoC */ +#pragma weak plat_get_ns_image_entrypoint +#pragma weak plat_ls_get_mmap + +#if defined(IMAGE_BL31) || !defined(CONFIG_DDR_FIP_IMAGE) +static void mmap_add_ddr_regions_statically(void) +{ + int i = 0; + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + /* MMU map for Non-Secure DRAM Regions */ + VERBOSE("DRAM Region %d: %p - %p\n", i, + (void *) info_dram_regions->region[i].addr, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + - 1)); + mmap_add_region(info_dram_regions->region[i].addr, + info_dram_regions->region[i].addr, + info_dram_regions->region[i].size, + MT_MEMORY | MT_RW | MT_NS); + + /* MMU map for Secure DDR Region on DRAM-0 */ + if (info_dram_regions->region[i].size > + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) { + VERBOSE("Secure DRAM Region %d: %p - %p\n", i, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + + NXP_SECURE_DRAM_SIZE + + NXP_SP_SHRD_DRAM_SIZE + - 1)); + mmap_add_region((info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE), + MT_MEMORY | MT_RW | MT_SECURE); + } + +#ifdef IMAGE_BL31 + for (i = 1; i < info_dram_regions->num_dram_regions; i++) { + if (info_dram_regions->region[i].size == 0) + break; + VERBOSE("DRAM Region %d: %p - %p\n", i, + (void *) info_dram_regions->region[i].addr, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + - 1)); + mmap_add_region(info_dram_regions->region[i].addr, + info_dram_regions->region[i].addr, + info_dram_regions->region[i].size, + MT_MEMORY | MT_RW | MT_NS); + } +#endif +} +#endif + +#if defined(PLAT_XLAT_TABLES_DYNAMIC) +void mmap_add_ddr_region_dynamically(void) +{ + int i = 0; + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + /* MMU map for Non-Secure DRAM Regions */ + VERBOSE("DRAM Region %d: %p - %p\n", i, + (void *) info_dram_regions->region[i].addr, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + - 1)); + mmap_add_dynamic_region(info_dram_regions->region[i].addr, + info_dram_regions->region[i].addr, + info_dram_regions->region[i].size, + MT_MEMORY | MT_RW | MT_NS); + + /* MMU map for Secure DDR Region on DRAM-0 */ + if (info_dram_regions->region[i].size > + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) { + VERBOSE("Secure DRAM Region %d: %p - %p\n", i, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + + NXP_SECURE_DRAM_SIZE + + NXP_SP_SHRD_DRAM_SIZE + - 1)); + mmap_add_dynamic_region((info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE), + MT_MEMORY | MT_RW | MT_SECURE); + } + +#ifdef IMAGE_BL31 + for (i = 1; i < info_dram_regions->num_dram_regions; i++) { + if (info_dram_regions->region[i].size == 0) { + break; + } + VERBOSE("DRAM Region %d: %p - %p\n", i, + (void *) info_dram_regions->region[i].addr, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + - 1)); + mmap_add_dynamic_region(info_dram_regions->region[i].addr, + info_dram_regions->region[i].addr, + info_dram_regions->region[i].size, + MT_MEMORY | MT_RW | MT_NS); + } +#endif +} +#endif + +/* + * Set up the page tables for the generic and platform-specific memory regions. + * The extents of the generic memory regions are specified by the function + * arguments and consist of: + * - Trusted SRAM seen by the BL image; + * - Code section; + * - Read-only data section; + * - Coherent memory region, if applicable. + */ +void ls_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit +#if USE_COHERENT_MEM + , + uintptr_t coh_start, + uintptr_t coh_limit +#endif + ) +{ + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + VERBOSE("Memory seen by this BL image: %p - %p\n", + (void *) total_base, (void *) (total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, + MT_MEMORY | MT_RW | MT_SECURE); + + /* Re-map the code section */ + VERBOSE("Code region: %p - %p\n", + (void *) code_start, (void *) code_limit); + mmap_add_region(code_start, code_start, + code_limit - code_start, + MT_CODE | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *) rodata_start, (void *) rodata_limit); + mmap_add_region(rodata_start, rodata_start, + rodata_limit - rodata_start, + MT_RO_DATA | MT_SECURE); + +#if USE_COHERENT_MEM + /* Re-map the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *) coh_start, (void *) coh_limit); + mmap_add_region(coh_start, coh_start, + coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + /* Now (re-)map the platform-specific memory regions */ + mmap_add(plat_ls_get_mmap()); + + +#if defined(IMAGE_BL31) || !defined(CONFIG_DDR_FIP_IMAGE) + mmap_add_ddr_regions_statically(); +#endif + + /* Create the page tables to reflect the above mappings */ + init_xlat_tables(); +} + +/******************************************************************************* + * Returns NXP platform specific memory map regions. + ******************************************************************************/ +const mmap_region_t *plat_ls_get_mmap(void) +{ + return plat_ls_mmap; +} + +/* + * This function get the number of clusters and cores count per cluster + * in the SoC. + */ +void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count, + uint8_t *num_clusters, uint8_t *cores_per_cluster) +{ + const soc_info_t *soc_info = get_soc_info(); + *num_clusters = NUMBER_OF_CLUSTERS; + *cores_per_cluster = CORES_PER_CLUSTER; + unsigned int i; + + for (i = 0U; i < ps_count; i++) { + if (soc_list[i].version == soc_info->svr_reg.bf_ver.version) { + *num_clusters = soc_list[i].num_clusters; + *cores_per_cluster = soc_list[i].cores_per_cluster; + break; + } + } + + VERBOSE("NUM of cluster = 0x%x, Cores per cluster = 0x%x\n", + *num_clusters, *cores_per_cluster); +} diff --git a/arm-trusted-firmware/plat/nxp/common/setup/ls_err.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_err.c new file mode 100644 index 0000000..845cd15 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_err.c @@ -0,0 +1,55 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#include +#include + +#if TRUSTED_BOARD_BOOT +#include +#include +#endif + +#include "plat_common.h" + +/* + * Error handler + */ +void plat_error_handler(int err) +{ +#if TRUSTED_BOARD_BOOT + uint32_t mode; + bool sb = check_boot_mode_secure(&mode); +#endif + + switch (err) { + case -ENOENT: + case -EAUTH: + printf("Authentication failure\n"); +#if TRUSTED_BOARD_BOOT + /* For SB production mode i.e ITS = 1 */ + if (sb == true) { + if (mode == 1U) { + transition_snvs_soft_fail(); + } else { + transition_snvs_non_secure(); + } + } +#endif + break; + default: + /* Unexpected error */ + break; + } + + /* Loop until the watchdog resets the system */ + for (;;) + wfi(); +} diff --git a/arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c new file mode 100644 index 0000000..259ab31 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c @@ -0,0 +1,33 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c new file mode 100644 index 0000000..a81cb2b --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c @@ -0,0 +1,66 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3]; + +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler) +{ + /* Validate 'handler' and 'id' parameters */ + if (!handler || id >= MAX_INTR_EL3) { + return -EINVAL; + } + + /* Check if a handler has already been registered */ + if (type_el3_interrupt_table[id] != NULL) { + return -EALREADY; + } + + type_el3_interrupt_table[id] = handler; + + return 0; +} + +static uint64_t ls_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint32_t intr_id; + interrupt_type_handler_t handler; + + intr_id = plat_ic_get_pending_interrupt_id(); + + INFO("Interrupt recvd is %d\n", intr_id); + + handler = type_el3_interrupt_table[intr_id]; + if (handler != NULL) { + handler(intr_id, flags, handle, cookie); + } + + /* + * Mark this interrupt as complete to avoid a interrupt storm. + */ + plat_ic_end_of_interrupt(intr_id); + + return 0U; +} + +void ls_el3_interrupt_config(void) +{ + uint64_t flags = 0U; + uint64_t rc; + + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_EL3, + ls_el3_interrupt_handler, flags); + if (rc != 0U) { + panic(); + } +} diff --git a/arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c new file mode 100644 index 0000000..7f01e72 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c @@ -0,0 +1,556 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef FLEXSPI_NOR_BOOT +#include +#endif +#if defined(NAND_BOOT) +#include +#endif +#if defined(NOR_BOOT) +#include +#endif +#if defined(QSPI_BOOT) +#include +#endif +#if defined(SD_BOOT) || defined(EMMC_BOOT) +#include +#endif +#include + +#ifdef CONFIG_DDR_FIP_IMAGE +#include +#endif +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#include "plat_common.h" +#include "platform_def.h" + +uint32_t fip_device; +/* IO devices */ +uintptr_t backend_dev_handle; + +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *backend_dev_con; + +static io_block_spec_t fip_block_spec = { + .offset = PLAT_FIP_OFFSET, + .length = PLAT_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t fuse_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +static const io_uuid_spec_t tb_fw_config_uuid_spec = { + .uuid = UUID_TB_FW_CONFIG, +}; + +static const io_uuid_spec_t hw_config_uuid_spec = { + .uuid = UUID_HW_CONFIG, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t tb_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FW_CERT, +}; + +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t fuse_key_cert_uuid_spec = { + .uuid = UUID_SCP_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t fuse_cert_uuid_spec = { + .uuid = UUID_SCP_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static int open_fip(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, ARM platforms load images from the FIP */ +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &backend_dev_handle, + (uintptr_t)&fip_block_spec, + open_backend + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&fuse_bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, + [TB_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_config_uuid_spec, + open_fip + }, + [HW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&hw_config_uuid_spec, + open_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + open_fip + }, + [SCP_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&fuse_key_cert_uuid_spec, + open_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + open_fip + }, + [SCP_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&fuse_cert_uuid_spec, + open_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + open_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak plat_io_setup + +/* + * Return an IO device handle and specification which can be used to access + */ +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + + +int open_backend(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(backend_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(backend_dev_handle, spec, &local_image_handle); + if (result == 0) { + io_close(local_image_handle); + } + } + return result; +} + +#if defined(SD_BOOT) || defined(EMMC_BOOT) || defined(NAND_BOOT) +static int plat_io_block_setup(size_t fip_offset, uintptr_t block_dev_spec) +{ + int io_result; + + fip_block_spec.offset = fip_offset; + + io_result = register_io_dev_block(&backend_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(backend_dev_con, block_dev_spec, + &backend_dev_handle); + assert(io_result == 0); + + return io_result; +} +#endif + +#if defined(FLEXSPI_NOR_BOOT) || defined(QSPI_BOOT) || defined(NOR_BOOT) +static int plat_io_memmap_setup(size_t fip_offset) +{ + int io_result; + + fip_block_spec.offset = fip_offset; + + io_result = register_io_dev_memmap(&backend_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(backend_dev_con, (uintptr_t)NULL, + &backend_dev_handle); + assert(io_result == 0); + + return io_result; +} +#endif + +static int ls_io_fip_setup(unsigned int boot_dev) +{ + int io_result; + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)&fip_device, + &fip_dev_handle); + assert(io_result == 0); + +#ifdef CONFIG_DDR_FIP_IMAGE + /* Open connection to DDR FIP image if available */ + io_result = ddr_fip_setup(fip_dev_con, boot_dev); + + assert(io_result == 0); +#endif + +#ifdef POLICY_FUSE_PROVISION + /* Open connection to FUSE FIP image if available */ + io_result = fuse_fip_setup(fip_dev_con, boot_dev); + + assert(io_result == 0); +#endif + + return io_result; +} + +int ls_qspi_io_setup(void) +{ +#ifdef QSPI_BOOT + qspi_io_setup(NXP_QSPI_FLASH_ADDR, + NXP_QSPI_FLASH_SIZE, + PLAT_FIP_OFFSET); + return plat_io_memmap_setup(NXP_QSPI_FLASH_ADDR + PLAT_FIP_OFFSET); +#else + ERROR("QSPI driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int emmc_sdhc2_io_setup(void) +{ +#if defined(EMMC_BOOT) && defined(NXP_ESDHC2_ADDR) + uintptr_t block_dev_spec; + int ret; + + ret = sd_emmc_init(&block_dev_spec, + NXP_ESDHC2_ADDR, + NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + false); + if (ret != 0) { + return ret; + } + + return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec); +#else + ERROR("EMMC driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int emmc_io_setup(void) +{ +/* On the platforms which only has one ESDHC controller, + * eMMC-boot will use the first ESDHC controller. + */ +#if defined(SD_BOOT) || defined(EMMC_BOOT) + uintptr_t block_dev_spec; + int ret; + + ret = sd_emmc_init(&block_dev_spec, + NXP_ESDHC_ADDR, + NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + true); + if (ret != 0) { + return ret; + } + + return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec); +#else + ERROR("SD driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int ifc_nor_io_setup(void) +{ +#if defined(NOR_BOOT) + int ret; + + ret = ifc_nor_init(NXP_NOR_FLASH_ADDR, + NXP_NOR_FLASH_SIZE); + + if (ret != 0) { + return ret; + } + + return plat_io_memmap_setup(NXP_NOR_FLASH_ADDR + PLAT_FIP_OFFSET); +#else + ERROR("NOR driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int ifc_nand_io_setup(void) +{ +#if defined(NAND_BOOT) + uintptr_t block_dev_spec; + int ret; + + ret = ifc_nand_init(&block_dev_spec, + NXP_IFC_REGION_ADDR, + NXP_IFC_ADDR, + NXP_IFC_SRAM_BUFFER_SIZE, + NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE); + if (ret != 0) { + return ret; + } + + return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec); +#else + + ERROR("NAND driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int ls_flexspi_nor_io_setup(void) +{ +#ifdef FLEXSPI_NOR_BOOT + int ret = 0; + + ret = flexspi_nor_io_setup(NXP_FLEXSPI_FLASH_ADDR, + NXP_FLEXSPI_FLASH_SIZE, + NXP_FLEXSPI_ADDR); + + if (ret != 0) { + ERROR("FlexSPI NOR driver initialization error.\n"); + /* Should never reach here */ + assert(0); + panic(); + return -1; + } + + return plat_io_memmap_setup(NXP_FLEXSPI_FLASH_ADDR + PLAT_FIP_OFFSET); +#else + ERROR("FlexSPI NOR driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +static int (* const ls_io_setup_table[])(void) = { + [BOOT_DEVICE_IFC_NOR] = ifc_nor_io_setup, + [BOOT_DEVICE_IFC_NAND] = ifc_nand_io_setup, + [BOOT_DEVICE_QSPI] = ls_qspi_io_setup, + [BOOT_DEVICE_EMMC] = emmc_io_setup, + [BOOT_DEVICE_SDHC2_EMMC] = emmc_sdhc2_io_setup, + [BOOT_DEVICE_FLEXSPI_NOR] = ls_flexspi_nor_io_setup, + [BOOT_DEVICE_FLEXSPI_NAND] = ls_flexspi_nor_io_setup, +}; + + +int plat_io_setup(void) +{ + int (*io_setup)(void); + unsigned int boot_dev = BOOT_DEVICE_NONE; + int ret; + + boot_dev = get_boot_dev(); + if (boot_dev == BOOT_DEVICE_NONE) { + ERROR("Boot Device detection failed, Check RCW_SRC\n"); + return -EINVAL; + } + + io_setup = ls_io_setup_table[boot_dev]; + ret = io_setup(); + if (ret != 0) { + return ret; + } + + ret = ls_io_fip_setup(boot_dev); + if (ret != 0) { + return ret; + } + + return 0; +} + + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = -1; + const struct plat_io_policy *policy; + + if (image_id < ARRAY_SIZE(policies)) { + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + } +#ifdef CONFIG_DDR_FIP_IMAGE + else { + VERBOSE("Trying alternative IO\n"); + result = plat_get_ddr_fip_image_source(image_id, dev_handle, + image_spec, open_backend); + } +#endif +#ifdef POLICY_FUSE_PROVISION + if (result != 0) { + VERBOSE("Trying FUSE IO\n"); + result = plat_get_fuse_image_source(image_id, dev_handle, + image_spec, open_backend); + } +#endif + + return result; +} diff --git a/arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c new file mode 100644 index 0000000..ab78f88 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include + +#include + +#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * TBD: Generate Random Number from NXP CAAM Block. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} diff --git a/arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S b/arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S new file mode 100644 index 0000000..6a47cbf --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S @@ -0,0 +1,152 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +.global el2_2_aarch32 +.global prefetch_disable + +#define SPSR_EL3_M4 0x10 +#define SPSR_EL_MASK 0xC +#define SPSR_EL2 0x8 +#define SCR_EL3_4_EL2_AARCH32 0x131 +#define SPSR32_EL2_LE 0x1DA + +#define MIDR_PARTNUM_START 4 +#define MIDR_PARTNUM_WIDTH 12 +#define MIDR_PARTNUM_A53 0xD03 +#define MIDR_PARTNUM_A57 0xD07 +#define MIDR_PARTNUM_A72 0xD08 + +/* + * uint64_t el2_2_aarch32(u_register_t smc_id, + * u_register_t start_addr, + * u_register_t parm1, + * u_register_t parm2) + * this function allows changing the execution width of EL2 from Aarch64 + * to Aarch32 + * Note: MUST be called from EL2 @ Aarch64 + * in: x0 = smc function id + * x1 = start address for EL2 @ Aarch32 + * x2 = first parameter to pass to EL2 @ Aarch32 + * x3 = second parameter to pass to EL2 @ Aarch32 + * out: x0 = 0, on success + * x0 = -1, on failure + * uses x0, x1, x2, x3 + */ +func el2_2_aarch32 + + /* check that caller is EL2 @ Aarch64 - err return if not */ + mrs x0, spsr_el3 + /* see if we were called from Aarch32 */ + tst x0, #SPSR_EL3_M4 + b.ne 2f + + /* see if we were called from EL2 */ + and x0, x0, SPSR_EL_MASK + cmp x0, SPSR_EL2 + b.ne 2f + + /* set ELR_EL3 */ + msr elr_el3, x1 + + /* set scr_el3 */ + mov x0, #SCR_EL3_4_EL2_AARCH32 + msr scr_el3, x0 + + /* set sctlr_el2 */ + ldr x1, =SCTLR_EL2_RES1 + msr sctlr_el2, x1 + + /* set spsr_el3 */ + ldr x0, =SPSR32_EL2_LE + msr spsr_el3, x0 + + /* x2 = parm 1 + * x3 = parm2 + */ + + /* set the parameters to be passed-thru to EL2 @ Aarch32 */ + mov x1, x2 + mov x2, x3 + + /* x1 = parm 1 + * x2 = parm2 + */ + + mov x0, xzr + /* invalidate the icache */ + ic iallu + dsb sy + isb + b 1f +2: + /* error return */ + mvn x0, xzr + ret +1: + eret +endfunc el2_2_aarch32 + +/* + * int prefetch_disable(u_register_t smc_id, u_register_t mask) + * this function marks cores which need to have the prefetch disabled - + * secondary cores have prefetch disabled when they are released from reset - + * the bootcore has prefetch disabled when this call is made + * in: x0 = function id + * x1 = core mask, where bit[0]=core0, bit[1]=core1, etc + * if a bit in the mask is set, then prefetch is disabled for that + * core + * out: x0 = SMC_SUCCESS + */ +func prefetch_disable + stp x4, x30, [sp, #-16]! + + mov x3, x1 + + /* x1 = core prefetch disable mask */ + /* x3 = core prefetch disable mask */ + + /* store the mask */ + mov x0, #PREFETCH_DIS_OFFSET + bl _set_global_data + + /* x3 = core prefetch disable mask */ + + /* see if we need to disable prefetch on THIS core */ + bl plat_my_core_mask + + /* x0 = core mask lsb */ + /* x3 = core prefetch disable mask */ + + tst x3, x0 + b.eq 1f + + /* read midr_el1 */ + mrs x1, midr_el1 + + /* x1 = midr_el1 */ + + mov x0, xzr + bfxil x0, x1, #MIDR_PARTNUM_START, #MIDR_PARTNUM_WIDTH + + /* x0 = part number (a53, a57, a72, etc) */ + + /* branch on cpu-specific */ + cmp x0, #MIDR_PARTNUM_A57 + b.eq 1f + cmp x0, #MIDR_PARTNUM_A72 + b.ne 1f + + bl _disable_ldstr_pfetch_A72 + b 1f +1: + ldp x4, x30, [sp], #16 + mov x0, xzr + ret +endfunc prefetch_disable diff --git a/arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h b/arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h new file mode 100644 index 0000000..d9e61e9 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h @@ -0,0 +1,80 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SIPSVC_H +#define SIPSVC_H + +#include + +#define SMC_FUNC_MASK 0x0000ffff +#define SMC32_PARAM_MASK 0xffffffff + +/* SMC function IDs for SiP Service queries */ +#define SIP_SVC_CALL_COUNT 0xff00 +#define SIP_SVC_UID 0xff01 +#define SIP_SVC_VERSION 0xff03 +#define SIP_SVC_PRNG 0xff10 +#define SIP_SVC_RNG 0xff11 +#define SIP_SVC_MEM_BANK 0xff12 +#define SIP_SVC_PREFETCH_DIS 0xff13 +#define SIP_SVC_HUK 0xff14 +#define SIP_SVC_ALLOW_L1L2_ERR 0xff15 +#define SIP_SVC_ALLOW_L2_CLR 0xff16 +#define SIP_SVC_2_AARCH32 0xff17 +#define SIP_SVC_PORSR1 0xff18 + +/* Layerscape SiP Service Calls version numbers */ +#define LS_SIP_SVC_VERSION_MAJOR 0x0 +#define LS_SIP_SVC_VERSION_MINOR 0x1 + +/* Number of Layerscape SiP Calls implemented */ +#define LS_COMMON_SIP_NUM_CALLS 10 + +/* Parameter Type Constants */ +#define SIP_PARAM_TYPE_NONE 0x0 +#define SIP_PARAM_TYPE_VALUE_INPUT 0x1 +#define SIP_PARAM_TYPE_VALUE_OUTPUT 0x2 +#define SIP_PARAM_TYPE_VALUE_INOUT 0x3 +#define SIP_PARAM_TYPE_MEMREF_INPUT 0x5 +#define SIP_PARAM_TYPE_MEMREF_OUTPUT 0x6 +#define SIP_PARAM_TYPE_MEMREF_INOUT 0x7 + +#define SIP_PARAM_TYPE_MASK 0xF + +/* + * The macro SIP_PARAM_TYPES can be used to construct a value that you can + * compare against an incoming paramTypes to check the type of all the + * parameters in one comparison. + */ +#define SIP_PARAM_TYPES(t0, t1, t2, t3) \ + ((t0) | ((t1) << 4) | ((t2) << 8) | ((t3) << 12)) + +/* + * The macro SIP_PARAM_TYPE_GET can be used to extract the type of a given + * parameter from paramTypes if you need more fine-grained type checking. + */ +#define SIP_PARAM_TYPE_GET(t, i) ((((uint32_t)(t)) >> ((i) * 4)) & 0xF) + +/* + * The macro SIP_PARAM_TYPE_SET can be used to load the type of a given + * parameter from paramTypes without specifying all types (SIP_PARAM_TYPES) + */ +#define SIP_PARAM_TYPE_SET(t, i) (((uint32_t)(t) & 0xF) << ((i) * 4)) + +#define SIP_SVC_RNG_PARAMS (SIP_PARAM_TYPE_VALUE_INPUT, \ + SIP_PARAM_TYPE_MEMREF_OUTPUT, \ + SIP_PARAM_TYPE_NONE, \ + SIP_PARAM_TYPE_NONE) + +/* Layerscape SiP Calls error code */ +enum { + LS_SIP_SUCCESS = 0, + LS_SIP_INVALID_PARAM = -1, + LS_SIP_NOT_SUPPORTED = -2, +}; + +#endif /* SIPSVC_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c b/arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c new file mode 100644 index 0000000..1c8668e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c @@ -0,0 +1,194 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +/* Layerscape SiP Service UUID */ +DEFINE_SVC_UUID2(nxp_sip_svc_uid, + 0x871de4ef, 0xedfc, 0x4209, 0xa4, 0x23, + 0x8d, 0x23, 0x75, 0x9d, 0x3b, 0x9f); + +#pragma weak nxp_plat_sip_handler +static uintptr_t nxp_plat_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) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +uint64_t el2_2_aarch32(u_register_t smc_id, u_register_t start_addr, + u_register_t parm1, u_register_t parm2); + +uint64_t prefetch_disable(u_register_t smc_id, u_register_t mask); +uint64_t bl31_get_porsr1(void); + +static void clean_top_32b_of_param(uint32_t smc_fid, + u_register_t *px1, + u_register_t *px2, + u_register_t *px3, + u_register_t *px4) +{ + /* if parameters from SMC32. Clean top 32 bits */ + if (GET_SMC_CC(smc_fid) == SMC_32) { + *px1 = *px1 & SMC32_PARAM_MASK; + *px2 = *px2 & SMC32_PARAM_MASK; + *px3 = *px3 & SMC32_PARAM_MASK; + *px4 = *px4 & SMC32_PARAM_MASK; + } +} + +/* This function handles Layerscape defined SiP Calls */ +static uintptr_t nxp_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) +{ + uint32_t ns; + uint64_t ret; + dram_regions_info_t *info_dram_regions; + + /* if parameter is sent from SMC32. Clean top 32 bits */ + clean_top_32b_of_param(smc_fid, &x1, &x2, &x3, &x4); + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + if (ns == 0) { + /* SiP SMC service secure world's call */ + ; + } else { + /* SiP SMC service normal world's call */ + ; + } + + switch (smc_fid & SMC_FUNC_MASK) { + case SIP_SVC_RNG: + if (is_sec_enabled() == false) { + NOTICE("SEC is disabled.\n"); + SMC_RET1(handle, SMC_UNK); + } + + /* Return zero on failure */ + ret = get_random((int)x1); + if (ret != 0) { + SMC_RET2(handle, SMC_OK, ret); + } else { + SMC_RET1(handle, SMC_UNK); + } + /* break is not required as SMC_RETx return */ + case SIP_SVC_HUK: + if (is_sec_enabled() == false) { + NOTICE("SEC is disabled.\n"); + SMC_RET1(handle, SMC_UNK); + } + ret = get_hw_unq_key_blob_hw((uint8_t *) x1, (uint32_t) x2); + + if (ret == SMC_OK) { + SMC_RET1(handle, SMC_OK); + } else { + SMC_RET1(handle, SMC_UNK); + } + /* break is not required as SMC_RETx return */ + case SIP_SVC_MEM_BANK: + VERBOSE("Handling SMC SIP_SVC_MEM_BANK.\n"); + info_dram_regions = get_dram_regions_info(); + + if (x1 == -1) { + SMC_RET2(handle, SMC_OK, + info_dram_regions->total_dram_size); + } else if (x1 >= info_dram_regions->num_dram_regions) { + SMC_RET1(handle, SMC_UNK); + } else { + SMC_RET3(handle, SMC_OK, + info_dram_regions->region[x1].addr, + info_dram_regions->region[x1].size); + } + /* break is not required as SMC_RETx return */ + case SIP_SVC_PREFETCH_DIS: + VERBOSE("In SIP_SVC_PREFETCH_DIS call\n"); + ret = prefetch_disable(smc_fid, x1); + if (ret == SMC_OK) { + SMC_RET1(handle, SMC_OK); + } else { + SMC_RET1(handle, SMC_UNK); + } + /* break is not required as SMC_RETx return */ + case SIP_SVC_2_AARCH32: + ret = el2_2_aarch32(smc_fid, x1, x2, x3); + + /* In success case, control should not reach here. */ + NOTICE("SMC: SIP_SVC_2_AARCH32 Failed.\n"); + SMC_RET1(handle, SMC_UNK); + /* break is not required as SMC_RETx return */ + case SIP_SVC_PORSR1: + ret = bl31_get_porsr1(); + SMC_RET2(handle, SMC_OK, ret); + /* break is not required as SMC_RETx return */ + default: + return nxp_plat_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + } +} + +/* This function is responsible for handling all SiP calls */ +static uintptr_t sip_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, + u_register_t flags) +{ + switch (smc_fid & SMC_FUNC_MASK) { + case SIP_SVC_CALL_COUNT: + /* Return the number of Layerscape SiP Service Calls. */ + SMC_RET1(handle, LS_COMMON_SIP_NUM_CALLS); + break; + case SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, nxp_sip_svc_uid); + break; + case SIP_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, LS_SIP_SVC_VERSION_MAJOR, + LS_SIP_SVC_VERSION_MINOR); + break; + default: + return nxp_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + } +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + nxp_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + sip_smc_handler +); diff --git a/arm-trusted-firmware/plat/nxp/common/sip_svc/sipsvc.mk b/arm-trusted-firmware/plat/nxp/common/sip_svc/sipsvc.mk new file mode 100644 index 0000000..c3a57de --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/sip_svc/sipsvc.mk @@ -0,0 +1,35 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the SIP SVC files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_SIPSVC},) + +ADD_SIPSVC := 1 + +PLAT_SIPSVC_PATH := $(PLAT_COMMON_PATH)/sip_svc + +SIPSVC_SOURCES := ${PLAT_SIPSVC_PATH}/sip_svc.c \ + ${PLAT_SIPSVC_PATH}/$(ARCH)/sipsvc.S + +PLAT_INCLUDES += -I${PLAT_SIPSVC_PATH}/include + +ifeq (${BL_COMM_SIPSVC_NEEDED},yes) +BL_COMMON_SOURCES += ${SIPSVC_SOURCES} +else +ifeq (${BL2_SIPSVC_NEEDED},yes) +BL2_SOURCES += ${SIPSVC_SOURCES} +endif +ifeq (${BL31_SIPSVC_NEEDED},yes) +BL31_SOURCES += ${SIPSVC_SOURCES} +endif +endif +endif +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c new file mode 100644 index 0000000..55ef604 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c @@ -0,0 +1,59 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include "errata_list.h" + +void soc_errata(void) +{ +#ifdef ERRATA_SOC_A050426 + INFO("SoC workaround for Errata A050426 was applied\n"); + erratum_a050426(); +#endif +#ifdef ERRATA_SOC_A008850 + INFO("SoC workaround for Errata A008850 Early-Phase was applied\n"); + erratum_a008850_early(); +#endif +#if ERRATA_SOC_A009660 + INFO("SoC workaround for Errata A009660 was applied\n"); + erratum_a009660(); +#endif +#if ERRATA_SOC_A010539 + INFO("SoC workaround for Errata A010539 was applied\n"); + erratum_a010539(); +#endif + + /* + * The following DDR Erratas workaround are implemented in DDR driver, + * but print information here. + */ +#if ERRATA_DDR_A011396 + INFO("SoC workaround for DDR Errata A011396 was applied\n"); +#endif +#if ERRATA_DDR_A050450 + INFO("SoC workaround for DDR Errata A050450 was applied\n"); +#endif +#if ERRATA_DDR_A050958 + INFO("SoC workaround for DDR Errata A050958 was applied\n"); +#endif +#if ERRATA_DDR_A008511 + INFO("SoC workaround for DDR Errata A008511 was applied\n"); +#endif +#if ERRATA_DDR_A009803 + INFO("SoC workaround for DDR Errata A009803 was applied\n"); +#endif +#if ERRATA_DDR_A009942 + INFO("SoC workaround for DDR Errata A009942 was applied\n"); +#endif +#if ERRATA_DDR_A010165 + INFO("SoC workaround for DDR Errata A010165 was applied\n"); +#endif +#if ERRATA_DDR_A009663 + INFO("SoC workaround for DDR Errata A009663 was applied\n"); +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h new file mode 100644 index 0000000..ab67995 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h @@ -0,0 +1,15 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef ERRATA_H +#define ERRATA_H + +#include "errata_list.h" + +void soc_errata(void); + +#endif /* ERRATA_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.mk b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.mk new file mode 100644 index 0000000..3deef3d --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Platform Errata Build flags. +# These should be enabled by the platform if the erratum workaround needs to be +# applied. + +ERRATA := \ + ERRATA_SOC_A050426 \ + ERRATA_SOC_A008850 \ + ERRATA_SOC_A009660 \ + ERRATA_SOC_A010539 + +define enable_errata + $(1) ?= 0 + ifeq ($$($(1)),1) + $$(eval $$(call add_define,$(1))) + BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata_a$(shell echo $(1)|awk -F '_A' '{print $$NF}').c + endif +endef + +$(foreach e,$(ERRATA),$(eval $(call enable_errata,$(strip $(e))))) + +BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata.c diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c new file mode 100644 index 0000000..e8c0f64 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c @@ -0,0 +1,42 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include +#include +#include +#include + +#include + +void erratum_a008850_early(void) +{ + /* part 1 of 2 */ + uintptr_t cci_base = NXP_CCI_ADDR; + uint32_t val = mmio_read_32(cci_base + CTRL_OVERRIDE_REG); + + /* enabling forced barrier termination on CCI400 */ + mmio_write_32(cci_base + CTRL_OVERRIDE_REG, + (val | CCI_TERMINATE_BARRIER_TX)); + +} + +void erratum_a008850_post(void) +{ + /* part 2 of 2 */ + uintptr_t cci_base = NXP_CCI_ADDR; + uint32_t val = mmio_read_32(cci_base + CTRL_OVERRIDE_REG); + + /* Clear the BARRIER_TX bit */ + val = val & ~(CCI_TERMINATE_BARRIER_TX); + + /* + * Disable barrier termination on CCI400, allowing + * barriers to propagate across CCI + */ + mmio_write_32(cci_base + CTRL_OVERRIDE_REG, val); + + INFO("SoC workaround for Errata A008850 Post-Phase was applied\n"); +} diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c new file mode 100644 index 0000000..d31a4d7 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c @@ -0,0 +1,14 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +void erratum_a009660(void) +{ + mmio_write_32(NXP_SCFG_ADDR + 0x20c, 0x63b20042); +} diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c new file mode 100644 index 0000000..3dcbdc8 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c @@ -0,0 +1,26 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include + +void erratum_a010539(void) +{ + if (get_boot_dev() == BOOT_DEVICE_QSPI) { + unsigned int *porsr1 = (void *)(NXP_DCFG_ADDR + + DCFG_PORSR1_OFFSET); + uint32_t val; + + val = (gur_in32(porsr1) & ~PORSR1_RCW_MASK); + mmio_write_32((uint32_t)(NXP_DCSR_DCFG_ADDR + + DCFG_DCSR_PORCR1_OFFSET), htobe32(val)); + /* Erratum need to set '1' to all bits for reserved SCFG register 0x1a8 */ + mmio_write_32((uint32_t)(NXP_SCFG_ADDR + 0x1a8), + htobe32(0xffffffff)); + } +} diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c new file mode 100644 index 0000000..ba4f71f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c @@ -0,0 +1,201 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +void erratum_a050426(void) +{ + uint32_t i, val3, val4; + + /* + * Part of this Errata is implemented in RCW and SCRATCHRW5 + * register is updated to hold Errata number. + * Validate whether RCW has already included required changes + */ + if (mmio_read_32(0x01e00210) != 0x00050426) { + ERROR("%s: Invalid RCW : ERR050426 not implemented\n", __func__); + } + + /* Enable BIST to access Internal memory locations */ + val3 = mmio_read_32(0x700117E60); + mmio_write_32(0x700117E60, (val3 | 0x80000001)); + val4 = mmio_read_32(0x700117E90); + mmio_write_32(0x700117E90, (val4 & 0xFFDFFFFF)); + + /* wriop Internal Memory.*/ + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706312000 + (i * 4), 0x55555555); + mmio_write_32(0x706312400 + (i * 4), 0x55555555); + mmio_write_32(0x706312800 + (i * 4), 0x55555555); + mmio_write_32(0x706314000 + (i * 4), 0x55555555); + mmio_write_32(0x706314400 + (i * 4), 0x55555555); + mmio_write_32(0x706314800 + (i * 4), 0x55555555); + mmio_write_32(0x706314c00 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x706316000 + (i * 4), 0x55555555); + mmio_write_32(0x706320000 + (i * 4), 0x55555555); + mmio_write_32(0x706320400 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x70640a000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x706518000 + (i * 4), 0x55555555); + mmio_write_32(0x706519000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706522000 + (i * 4), 0x55555555); + mmio_write_32(0x706522800 + (i * 4), 0x55555555); + mmio_write_32(0x706523000 + (i * 4), 0x55555555); + mmio_write_32(0x706523800 + (i * 4), 0x55555555); + mmio_write_32(0x706524000 + (i * 4), 0x55555555); + mmio_write_32(0x706524800 + (i * 4), 0x55555555); + mmio_write_32(0x706608000 + (i * 4), 0x55555555); + mmio_write_32(0x706608800 + (i * 4), 0x55555555); + mmio_write_32(0x706609000 + (i * 4), 0x55555555); + mmio_write_32(0x706609800 + (i * 4), 0x55555555); + mmio_write_32(0x70660a000 + (i * 4), 0x55555555); + mmio_write_32(0x70660a800 + (i * 4), 0x55555555); + mmio_write_32(0x70660b000 + (i * 4), 0x55555555); + mmio_write_32(0x70660b800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x70660c000 + (i * 4), 0x55555555); + mmio_write_32(0x70660c800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x706718000 + (i * 4), 0x55555555); + mmio_write_32(0x706718800 + (i * 4), 0x55555555); + } + mmio_write_32(0x706b0a000, 0x55555555); + + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706b0e000 + (i * 4), 0x55555555); + mmio_write_32(0x706b0e800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x706b10000 + (i * 4), 0x55555555); + mmio_write_32(0x706b10400 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706b14000 + (i * 4), 0x55555555); + mmio_write_32(0x706b14800 + (i * 4), 0x55555555); + mmio_write_32(0x706b15000 + (i * 4), 0x55555555); + mmio_write_32(0x706b15800 + (i * 4), 0x55555555); + } + mmio_write_32(0x706e12000, 0x55555555); + + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706e14000 + (i * 4), 0x55555555); + mmio_write_32(0x706e14800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x706e16000 + (i * 4), 0x55555555); + mmio_write_32(0x706e16400 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x706e1a000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1a800 + (i * 4), 0x55555555); + mmio_write_32(0x706e1b000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1b800 + (i * 4), 0x55555555); + mmio_write_32(0x706e1c000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1c800 + (i * 4), 0x55555555); + mmio_write_32(0x706e1e000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1e800 + (i * 4), 0x55555555); + mmio_write_32(0x706e1f000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1f800 + (i * 4), 0x55555555); + mmio_write_32(0x706e20000 + (i * 4), 0x55555555); + mmio_write_32(0x706e20800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x707108000 + (i * 4), 0x55555555); + mmio_write_32(0x707109000 + (i * 4), 0x55555555); + mmio_write_32(0x70710a000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x70711c000 + (i * 4), 0x55555555); + mmio_write_32(0x70711c800 + (i * 4), 0x55555555); + mmio_write_32(0x70711d000 + (i * 4), 0x55555555); + mmio_write_32(0x70711d800 + (i * 4), 0x55555555); + mmio_write_32(0x70711e000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x707120000 + (i * 4), 0x55555555); + mmio_write_32(0x707121000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x707122000 + (i * 4), 0x55555555); + mmio_write_32(0x70725a000 + (i * 4), 0x55555555); + mmio_write_32(0x70725b000 + (i * 4), 0x55555555); + mmio_write_32(0x70725c000 + (i * 4), 0x55555555); + mmio_write_32(0x70725e000 + (i * 4), 0x55555555); + mmio_write_32(0x70725e400 + (i * 4), 0x55555555); + mmio_write_32(0x70725e800 + (i * 4), 0x55555555); + mmio_write_32(0x70725ec00 + (i * 4), 0x55555555); + mmio_write_32(0x70725f000 + (i * 4), 0x55555555); + mmio_write_32(0x70725f400 + (i * 4), 0x55555555); + mmio_write_32(0x707340000 + (i * 4), 0x55555555); + mmio_write_32(0x707346000 + (i * 4), 0x55555555); + mmio_write_32(0x707484000 + (i * 4), 0x55555555); + mmio_write_32(0x70748a000 + (i * 4), 0x55555555); + mmio_write_32(0x70748b000 + (i * 4), 0x55555555); + mmio_write_32(0x70748c000 + (i * 4), 0x55555555); + mmio_write_32(0x70748d000 + (i * 4), 0x55555555); + } + + /* EDMA Internal Memory.*/ + for (i = 0U; i < 5U; i++) { + mmio_write_32(0x70a208000 + (i * 4), 0x55555555); + mmio_write_32(0x70a208800 + (i * 4), 0x55555555); + mmio_write_32(0x70a209000 + (i * 4), 0x55555555); + mmio_write_32(0x70a209800 + (i * 4), 0x55555555); + } + + /* QDMA Internal Memory.*/ + for (i = 0U; i < 5U; i++) { + mmio_write_32(0x70b008000 + (i * 4), 0x55555555); + mmio_write_32(0x70b00c000 + (i * 4), 0x55555555); + mmio_write_32(0x70b010000 + (i * 4), 0x55555555); + mmio_write_32(0x70b014000 + (i * 4), 0x55555555); + mmio_write_32(0x70b018000 + (i * 4), 0x55555555); + mmio_write_32(0x70b018400 + (i * 4), 0x55555555); + mmio_write_32(0x70b01a000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01a400 + (i * 4), 0x55555555); + mmio_write_32(0x70b01c000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01d000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01e000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01e800 + (i * 4), 0x55555555); + mmio_write_32(0x70b01f000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01f800 + (i * 4), 0x55555555); + mmio_write_32(0x70b020000 + (i * 4), 0x55555555); + mmio_write_32(0x70b020400 + (i * 4), 0x55555555); + mmio_write_32(0x70b020800 + (i * 4), 0x55555555); + mmio_write_32(0x70b020c00 + (i * 4), 0x55555555); + mmio_write_32(0x70b022000 + (i * 4), 0x55555555); + mmio_write_32(0x70b022400 + (i * 4), 0x55555555); + mmio_write_32(0x70b024000 + (i * 4), 0x55555555); + mmio_write_32(0x70b024800 + (i * 4), 0x55555555); + mmio_write_32(0x70b025000 + (i * 4), 0x55555555); + mmio_write_32(0x70b025800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x70b026000 + (i * 4), 0x55555555); + mmio_write_32(0x70b026200 + (i * 4), 0x55555555); + } + for (i = 0U; i < 5U; i++) { + mmio_write_32(0x70b028000 + (i * 4), 0x55555555); + mmio_write_32(0x70b028800 + (i * 4), 0x55555555); + mmio_write_32(0x70b029000 + (i * 4), 0x55555555); + mmio_write_32(0x70b029800 + (i * 4), 0x55555555); + } + + /* Disable BIST */ + mmio_write_32(0x700117E60, val3); + mmio_write_32(0x700117E90, val4); +} diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h new file mode 100644 index 0000000..f6741e2 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h @@ -0,0 +1,28 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef ERRATA_LIST_H +#define ERRATA_LIST_H + +#ifdef ERRATA_SOC_A050426 +void erratum_a050426(void); +#endif + +#ifdef ERRATA_SOC_A008850 +void erratum_a008850_early(void); +void erratum_a008850_post(void); +#endif + +#ifdef ERRATA_SOC_A009660 +void erratum_a009660(void); +#endif + +#ifdef ERRATA_SOC_A010539 +void erratum_a010539(void); +#endif + +#endif /* ERRATA_LIST_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c b/arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c new file mode 100644 index 0000000..8f38f3e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c @@ -0,0 +1,81 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include "plat_common.h" + +extern bool rotpk_not_dpld; +extern uint8_t rotpk_hash_table[MAX_KEY_ENTRIES][SHA256_BYTES]; +extern uint32_t num_rotpk_hash_entries; + +/* + * In case of secure boot, return ptr of rotpk_hash table in key_ptr and + * number of hashes in key_len + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + uint32_t mode = 0U; + *flags = ROTPK_NOT_DEPLOYED; + + /* ROTPK hash table must be available for secure boot */ + if (rotpk_not_dpld == true) { + if (check_boot_mode_secure(&mode) == true) { + /* Production mode, don;t continue further */ + if (mode == 1U) { + return -EAUTH; + } + + /* For development mode, rotpk flag false + * indicates that SRK hash comparison might + * have failed. This is not fatal error. + * Continue in this case but transition SNVS + * to non-secure state + */ + transition_snvs_non_secure(); + return 0; + } else { + return 0; + } + } + + /* + * We return the complete hash table and number of entries in + * table for NXP platform specific implementation. + * Here hash is always assume as SHA-256 + */ + *key_ptr = rotpk_hash_table; + *key_len = num_rotpk_hash_entries; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + /* + * No support for non-volatile counter. Update the ROT key to protect + * the system against rollback. + */ + *nv_ctr = 0U; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 0; +} diff --git a/arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S b/arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S new file mode 100644 index 0000000..8e084d1 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S @@ -0,0 +1,21 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + */ + +#ifndef _CSF_HDR_H_ + + .global nxp_rotpk_hash + .global nxp_rotpk_hash_end + .section .rodata.nxp_rotpk_hash, "a" +nxp_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +nxp_rotpk_hash_end: +#endif diff --git a/arm-trusted-firmware/plat/nxp/common/tbbr/tbbr.mk b/arm-trusted-firmware/plat/nxp/common/tbbr/tbbr.mk new file mode 100644 index 0000000..7edcfbc --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/tbbr/tbbr.mk @@ -0,0 +1,162 @@ +# +# Copyright 2020-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# For TRUSTED_BOARD_BOOT platforms need to include this makefile +# Following definations are to be provided by platform.mk file or +# by user - BL33_INPUT_FILE, BL32_INPUT_FILE, BL31_INPUT_FILE + +ifeq ($(CHASSIS), 2) +include $(PLAT_DRIVERS_PATH)/csu/csu.mk +CSF_FILE := input_blx_ch${CHASSIS} +BL2_CSF_FILE := input_bl2_ch${CHASSIS} +else +ifeq ($(CHASSIS), 3) +CSF_FILE := input_blx_ch${CHASSIS} +BL2_CSF_FILE := input_bl2_ch${CHASSIS} +PBI_CSF_FILE := input_pbi_ch${CHASSIS} +$(eval $(call add_define, CSF_HDR_CH3)) +else +ifeq ($(CHASSIS), 3_2) +CSF_FILE := input_blx_ch3 +BL2_CSF_FILE := input_bl2_ch${CHASSIS} +PBI_CSF_FILE := input_pbi_ch${CHASSIS} +$(eval $(call add_define, CSF_HDR_CH3)) +else + $(error -> CHASSIS not set!) +endif +endif +endif + +PLAT_AUTH_PATH := $(PLAT_DRIVERS_PATH)/auth + + +ifeq (${BL2_INPUT_FILE},) + BL2_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${BL2_CSF_FILE} +endif + +ifeq (${PBI_INPUT_FILE},) + PBI_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${PBI_CSF_FILE} +endif + +# If MBEDTLS_DIR is not specified, use CSF Header option +ifeq (${MBEDTLS_DIR},) + # Generic image processing filters to prepend CSF header + ifeq (${BL33_INPUT_FILE},) + BL33_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE} + endif + + ifeq (${BL31_INPUT_FILE},) + BL31_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE} + endif + + ifeq (${BL32_INPUT_FILE},) + BL32_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE} + endif + + ifeq (${FUSE_INPUT_FILE},) + FUSE_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE} + endif + + PLAT_INCLUDES += -I$(PLAT_DRIVERS_PATH)/sfp + PLAT_TBBR_SOURCES += $(PLAT_AUTH_PATH)/csf_hdr_parser/cot.c \ + $(PLAT_COMMON_PATH)/tbbr/csf_tbbr.c + # IMG PARSER here is CSF header parser + include $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/csf_hdr.mk + PLAT_TBBR_SOURCES += $(CSF_HDR_SOURCES) + + SCP_BL2_PRE_TOOL_FILTER := CST_SCP_BL2 + BL31_PRE_TOOL_FILTER := CST_BL31 + BL32_PRE_TOOL_FILTER := CST_BL32 + BL33_PRE_TOOL_FILTER := CST_BL33 +else + + ifeq (${DISABLE_FUSE_WRITE}, 1) + $(eval $(call add_define,DISABLE_FUSE_WRITE)) + endif + + # For Mbedtls currently crypto is not supported via CAAM + # enable it when that support is there + CAAM_INTEG := 0 + KEY_ALG := rsa + KEY_SIZE := 2048 + + $(eval $(call add_define,MBEDTLS_X509)) + ifeq (${PLAT_DDR_PHY},PHY_GEN2) + $(eval $(call add_define,PLAT_DEF_OID)) + endif + include drivers/auth/mbedtls/mbedtls_x509.mk + + + PLAT_TBBR_SOURCES += $(PLAT_AUTH_PATH)/tbbr/tbbr_cot.c \ + $(PLAT_COMMON_PATH)/tbbr/nxp_rotpk.S \ + $(PLAT_COMMON_PATH)/tbbr/x509_tbbr.c + + #ROTPK key is embedded in BL2 image + ifeq (${ROT_KEY},) + ROT_KEY = $(BUILD_PLAT)/rot_key.pem + endif + + ifeq (${SAVE_KEYS},1) + + ifeq (${TRUSTED_WORLD_KEY},) + TRUSTED_WORLD_KEY = ${BUILD_PLAT}/trusted.pem + endif + + ifeq (${NON_TRUSTED_WORLD_KEY},) + NON_TRUSTED_WORLD_KEY = ${BUILD_PLAT}/non-trusted.pem + endif + + ifeq (${BL31_KEY},) + BL31_KEY = ${BUILD_PLAT}/soc.pem + endif + + ifeq (${BL32_KEY},) + BL32_KEY = ${BUILD_PLAT}/trusted_os.pem + endif + + ifeq (${BL33_KEY},) + BL33_KEY = ${BUILD_PLAT}/non-trusted_os.pem + endif + + endif + + ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + + $(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) + + $(BUILD_PLAT)/bl2/nxp_rotpk.o: $(ROTPK_HASH) + + certificates: $(ROT_KEY) + $(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + @if [ ! -f $(ROT_KEY) ]; then \ + openssl genrsa 2048 > $@ 2>/dev/null; \ + fi + + $(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null + +endif #MBEDTLS_DIR + +PLAT_INCLUDES += -Iinclude/common/tbbr + +# Generic files for authentication framework +TBBR_SOURCES += drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + plat/common/tbbr/plat_tbbr.c \ + ${PLAT_TBBR_SOURCES} + +# If CAAM_INTEG is not defined (would be scenario with MBED TLS) +# include mbedtls_crypto +ifeq (${CAAM_INTEG},0) + include drivers/auth/mbedtls/mbedtls_crypto.mk +else + include $(PLAT_DRIVERS_PATH)/crypto/caam/src/auth/auth.mk + TBBR_SOURCES += ${AUTH_SOURCES} +endif diff --git a/arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c b/arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c new file mode 100644 index 0000000..ec87674 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c @@ -0,0 +1,105 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include "plat_common.h" + +extern char nxp_rotpk_hash[], nxp_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = nxp_rotpk_hash; + *key_len = nxp_rotpk_hash_end - nxp_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + const char *oid; + uint32_t uid_num; + uint32_t val = 0U; + + assert(cookie != NULL); + assert(nv_ctr != NULL); + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + uid_num = 3U; + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + uid_num = 4U; + } else { + return 1; + } + + val = sfp_read_oem_uid(uid_num); + + INFO("SFP Value read is %x from UID %d\n", val, uid_num); + if (val == 0U) { + *nv_ctr = 0U; + } else { + *nv_ctr = (32U - __builtin_clz(val)); + } + + INFO("NV Counter value for UID %d is %d\n", uid_num, *nv_ctr); + return 0; + +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + const char *oid; + uint32_t uid_num, sfp_val; + + assert(cookie != NULL); + + /* Counter values upto 32 are supported */ + if (nv_ctr > 32U) { + return 1; + } + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + uid_num = 3U; + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + uid_num = 4U; + } else { + return 1; + } + sfp_val = (1U << (nv_ctr - 1)); + + if (sfp_write_oem_uid(uid_num, sfp_val) == 1) { + /* Enable POVDD on board */ + if (board_enable_povdd()) { + sfp_program_fuses(); + } + + /* Disable POVDD on board */ + board_disable_povdd(); + } else { + ERROR("Invalid OEM UID sent.\n"); + return 1; + } + + return 0; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c b/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c new file mode 100644 index 0000000..966a73c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c @@ -0,0 +1,121 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#ifndef NXP_COINED_BB +#include +#include +#include +#endif +#include +#include +#ifdef NXP_COINED_BB +#include +#endif + +#include +#include "plat_warm_rst.h" +#include "platform_def.h" + +#if defined(IMAGE_BL2) + +uint32_t is_warm_boot(void) +{ + uint32_t ret = mmio_read_32(NXP_RESET_ADDR + RST_RSTRQSR1_OFFSET) + & ~(RSTRQSR1_SWRR); + + const nv_app_data_t *nv_app_data = get_nv_data(); + + if (ret == 0U) { + INFO("Not a SW(Warm) triggered reset.\n"); + return 0U; + } + + ret = (nv_app_data->warm_rst_flag == WARM_BOOT_SUCCESS) ? 1 : 0; + + if (ret != 0U) { + INFO("Warm Reset was triggered..\n"); + } else { + INFO("Warm Reset was not triggered..\n"); + } + + return ret; +} + +#endif + +#if defined(IMAGE_BL31) +int prep_n_execute_warm_reset(void) +{ +#ifdef NXP_COINED_BB +#if !TRUSTED_BOARD_BOOT + snvs_disable_zeroize_lp_gpr(); +#endif +#else + int ret; + uint8_t warm_reset = WARM_BOOT_SUCCESS; + + ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR); + + if (ret != 0) { + ERROR("Failed to initialized driver flexspi-nor.\n"); + ERROR("exiting warm-reset request.\n"); + return PSCI_E_INTERN_FAIL; + } + + /* Sector starting from NV_STORAGE_BASE_ADDR is already + * erased for writing. + */ + +#if (ERLY_WRM_RST_FLG_FLSH_UPDT) + ret = xspi_write((uint32_t)NV_STORAGE_BASE_ADDR, + &warm_reset, + sizeof(warm_reset)); +#else + /* Preparation for writing the Warm reset flag. */ + ret = xspi_wren((uint32_t)NV_STORAGE_BASE_ADDR); + + /* IP Control Register0 - SF Address to be read */ + fspi_out32((NXP_FLEXSPI_ADDR + FSPI_IPCR0), + (uint32_t) NV_STORAGE_BASE_ADDR); + + while ((fspi_in32(NXP_FLEXSPI_ADDR + FSPI_INTR) & + FSPI_INTR_IPTXWE_MASK) == 0) { + ; + } + /* Write TX FIFO Data Register */ + fspi_out32(NXP_FLEXSPI_ADDR + FSPI_TFDR, (uint32_t) warm_reset); + + fspi_out32(NXP_FLEXSPI_ADDR + FSPI_INTR, FSPI_INTR_IPTXWE); + + /* IP Control Register1 - SEQID_WRITE operation, Size = 1 Byte */ + fspi_out32(NXP_FLEXSPI_ADDR + FSPI_IPCR1, + (uint32_t)(FSPI_WRITE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | + (uint16_t) sizeof(warm_reset)); + + /* Trigger XSPI-IP-Write cmd only if: + * - Putting DDR in-self refresh mode is successfully. + * to complete the writing of the warm-reset flag + * to flash. + * + * This code is as part of assembly. + */ +#endif +#endif + INFO("Doing DDR Self refresh.\n"); + _soc_sys_warm_reset(); + + /* Expected behaviour is to do the power cycle */ + while (1 != 0) + ; + + return -1; +} +#endif diff --git a/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h b/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h new file mode 100644 index 0000000..e0c39c5 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h @@ -0,0 +1,28 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_WARM_RST_H +#define PLAT_WARM_RST_H + +#ifndef NXP_COINED_BB +#define ERLY_WRM_RST_FLG_FLSH_UPDT 0 +#endif + +#ifndef __ASSEMBLER__ + +#if defined(IMAGE_BL2) +uint32_t is_warm_boot(void); +#endif + +#if defined(IMAGE_BL31) +int prep_n_execute_warm_reset(void); +int _soc_sys_warm_reset(void); +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /* PLAT_WARM_RST_H */ diff --git a/arm-trusted-firmware/plat/nxp/common/warm_reset/warm_reset.mk b/arm-trusted-firmware/plat/nxp/common/warm_reset/warm_reset.mk new file mode 100644 index 0000000..236004f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/warm_reset/warm_reset.mk @@ -0,0 +1,20 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${WARM_RST_ADDED},) + +WARM_RST_ADDED := 1 +NXP_NV_SW_MAINT_LAST_EXEC_DATA := yes + +$(eval $(call add_define,NXP_WARM_BOOT)) + + +WARM_RST_INCLUDES += -I${PLAT_COMMON_PATH}/warm_reset +WARM_RST_BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}_warm_rst.S + +WARM_RST_BL_COMM_SOURCES += ${PLAT_COMMON_PATH}/warm_reset/plat_warm_reset.c + +endif diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S b/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S new file mode 100644 index 0000000..404c39e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S @@ -0,0 +1,1387 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .section .text, "ax" + +#include + +#include +#include +#include +#include + +#include +#include +#include + + .global soc_init_lowlevel + .global soc_init_percpu + .global _set_platform_security + .global _soc_set_start_addr + + .global _soc_core_release + .global _soc_ck_disabled + .global _soc_core_restart + .global _soc_core_prep_off + .global _soc_core_entr_off + .global _soc_core_exit_off + .global _soc_sys_reset + .global _soc_sys_off + .global _soc_core_prep_stdby + .global _soc_core_entr_stdby + .global _soc_core_exit_stdby + .global _soc_core_prep_pwrdn + .global _soc_core_entr_pwrdn + .global _soc_core_exit_pwrdn + .global _soc_clstr_prep_stdby + .global _soc_clstr_exit_stdby + .global _soc_clstr_prep_pwrdn + .global _soc_clstr_exit_pwrdn + .global _soc_sys_prep_stdby + .global _soc_sys_exit_stdby + .global _soc_sys_prep_pwrdn + .global _soc_sys_pwrdn_wfi + .global _soc_sys_exit_pwrdn + + .equ TZPCDECPROT_0_SET_BASE, 0x02200804 + .equ TZPCDECPROT_1_SET_BASE, 0x02200810 + .equ TZPCDECPROT_2_SET_BASE, 0x0220081C + + .equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110 + +/* + * This function initialize the soc. + * in: void + * out: void + * uses x0 - x11 + */ +func soc_init_lowlevel + /* + * Called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + /* + * Make sure the personality has been established by releasing cores + * that are marked "to-be-disabled" from reset + */ + bl release_disabled /* 0-8 */ + + /* Set SCRATCHRW7 to 0x0 */ + ldr x0, =DCFG_SCRATCHRW7_OFFSET + mov x1, xzr + bl _write_reg_dcfg + + /* Restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + ret +endfunc soc_init_lowlevel + +/* + * void soc_init_percpu(void) + * + * This function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0 - x3 + */ +func soc_init_percpu + stp x4, x30, [sp, #-16]! + + bl plat_my_core_mask + mov x2, x0 + + /* x2 = core mask */ + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data /* 0-1 */ + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A72 /* 0 */ +1: + mov x0, #NXP_PMU_ADDR + bl enable_timer_base_to_cluster + + ldp x4, x30, [sp], #16 + ret +endfunc soc_init_percpu + +/* + * This function determines if a core is disabled via COREDISABLEDSR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1 + */ +func _soc_ck_disabled + /* get base addr of dcfg block */ + ldr x1, =NXP_DCFG_ADDR + + /* read COREDISABLEDSR */ + ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET] + + /* test core bit */ + and w0, w1, w0 + + ret +endfunc _soc_ck_disabled + +/* + * This function sets the security mechanisms in the SoC to implement the + * Platform Security Policy + */ +func _set_platform_security + mov x3, x30 + +#if (!SUPPRESS_TZC) + /* initialize the tzpc */ + bl init_tzpc +#endif + +#if (!SUPPRESS_SEC) + /* initialize secmon */ + bl initSecMon +#endif + + mov x30, x3 + ret +endfunc _set_platform_security + +/* + * Part of CPU_ON + * + * This function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0 - x3 + */ +_soc_core_release: + mov x3, x30 + + /* + * Write to CORE_HOLD to tell the bootrom that we want this core + * to run + */ + ldr x1, =NXP_SEC_REGFILE_ADDR + str w0, [x1, #CORE_HOLD_OFFSET] + + /* Read-modify-write BRRL to release core */ + mov x1, #NXP_RESET_ADDR + ldr w2, [x1, #BRR_OFFSET] + orr w2, w2, w0 + str w2, [x1, #BRR_OFFSET] + dsb sy + isb + + /* Send event */ + sev + isb + + mov x30, x3 + ret + +/* + * This function writes a 64-bit address to bootlocptrh/l + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * uses x0, x1, x2 + */ +func _soc_set_start_addr + /* Get the 64-bit base address of the dcfg block */ + ldr x2, =NXP_DCFG_ADDR + + /* Write the 32-bit BOOTLOCPTRL register */ + mov x1, x0 + str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET] + + /* Write the 32-bit BOOTLOCPTRH register */ + lsr x1, x0, #32 + str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET] + ret +endfunc _soc_set_start_addr + +/* + * Part of CPU_ON + * + * This function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0 - x6 + */ +_soc_core_restart: + mov x6, x30 + mov x4, x0 + + /* pgm GICD_CTLR - enable secure grp0 */ + mov x5, #NXP_GICD_ADDR + ldr w2, [x5, #GICD_CTLR_OFFSET] + orr w2, w2, #GICD_CTLR_EN_GRP_0 + str w2, [x5, #GICD_CTLR_OFFSET] + dsb sy + isb + + /* Poll on RWP til write completes */ +4: + ldr w2, [x5, #GICD_CTLR_OFFSET] + tst w2, #GICD_CTLR_RWP + b.ne 4b + + /* + * x4 = core mask lsb + * x5 = gicd base addr + */ + + mov x0, x4 + bl get_mpidr_value + + /* Generate target list bit */ + and x1, x0, #MPIDR_AFFINITY0_MASK + mov x2, #1 + lsl x2, x2, x1 + + /* Get the affinity1 field */ + and x1, x0, #MPIDR_AFFINITY1_MASK + lsl x1, x1, #8 + orr x2, x2, x1 + + /* Insert the INTID for SGI15 */ + orr x2, x2, #ICC_SGI0R_EL1_INTID + + /* Fire the SGI */ + msr ICC_SGI0R_EL1, x2 + dsb sy + isb + + /* Load '0' on success */ + mov x0, xzr + + mov x30, x6 + ret + +/* + * Part of CPU_OFF + * + * This function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0 - x7 + */ +_soc_core_prep_off: + mov x8, x30 + mov x7, x0 + + /* x7 = core mask lsb */ + + mrs x1, CPUECTLR_EL1 + + /* Set smp and disable L2 snoops in cpuectlr */ + orr x1, x1, #CPUECTLR_SMPEN_EN + orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH + bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK + bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK + + /* Set retention control in cpuectlr */ + bic x1, x1, #CPUECTLR_TIMER_MASK + orr x1, x1, #CPUECTLR_TIMER_2TICKS + msr CPUECTLR_EL1, x1 + + /* Get redistributor rd base addr for this core */ + mov x0, x7 + bl get_gic_rd_base + mov x6, x0 + + /* Get redistributor sgi base addr for this core */ + mov x0, x7 + bl get_gic_sgi_base + mov x5, x0 + + /* + * x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* Disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w3, #GICR_ICENABLER0_SGI15 + str w3, [x5, #GICR_ICENABLER0_OFFSET] +2: + /* Poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 2b + + /* Disable GRP1 interrupts at cpu interface */ + msr ICC_IGRPEN1_EL3, xzr + + /* Disable GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* Program the redistributor - poll on GICR_CTLR.RWP as needed */ + + /* Define SGI 15 as Grp0 - GICR_IGROUPR0 */ + ldr w4, [x5, #GICR_IGROUPR0_OFFSET] + bic w4, w4, #GICR_IGROUPR0_SGI15 + str w4, [x5, #GICR_IGROUPR0_OFFSET] + + /* Define SGI 15 as Grp0 - GICR_IGRPMODR0 */ + ldr w3, [x5, #GICR_IGRPMODR0_OFFSET] + bic w3, w3, #GICR_IGRPMODR0_SGI15 + str w3, [x5, #GICR_IGRPMODR0_OFFSET] + + /* Set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */ + ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET] + bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK + str w4, [x5, #GICR_IPRIORITYR3_OFFSET] + + /* Enable SGI 15 at redistributor - GICR_ISENABLER0 */ + mov w3, #GICR_ISENABLER0_SGI15 + str w3, [x5, #GICR_ISENABLER0_OFFSET] + dsb sy + isb +3: + /* Poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 3b + + /* Quiesce the debug interfaces */ + mrs x3, osdlr_el1 + orr x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + /* Enable grp0 ints */ + mov x3, #ICC_IGRPEN0_EL1_EN + msr ICC_IGRPEN0_EL1, x3 + + /* + * x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* Clear any pending interrupts */ + mvn w1, wzr + str w1, [x5, #GICR_ICPENDR0_OFFSET] + + /* Make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 4f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +4: + /* Enable the core timer and mask timer interrupt */ + mov x1, #CNTP_CTL_EL0_EN + orr x1, x1, #CNTP_CTL_EL0_IMASK + msr cntp_ctl_el0, x1 + + isb + mov x30, x8 + ret + +/* + * Part of CPU_OFF + * + * This function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0 - x5 + */ +_soc_core_entr_off: + mov x5, x30 + mov x4, x0 + + /* x4 = core mask */ +1: + /* Enter low-power state by executing wfi */ + wfi + + /* See if SGI15 woke us up */ + mrs x2, ICC_IAR0_EL1 + mov x3, #ICC_IAR0_EL1_SGI15 + cmp x2, x3 + b.ne 1b + + /* Deactivate the int */ + msr ICC_EOIR0_EL1, x2 + + /* x4 = core mask */ +2: + /* Check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + /* x0 = core state */ + + cmp x0, #CORE_WAKEUP + b.ne 1b + + /* If we get here, then we have exited the wfi */ + mov x30, x5 + ret + +/* + * Part of CPU_OFF + * + * This function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6 + */ +_soc_core_exit_off: + mov x6, x30 + mov x5, x0 + + /* Disable forwarding of GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* Get redistributor sgi base addr for this core */ + mov x0, x5 + bl get_gic_sgi_base + mov x4, x0 + + /* x4 = gicr sgi base addr */ + /* x5 = core mask */ + + /* Disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w1, #GICR_ICENABLER0_SGI15 + str w1, [x4, #GICR_ICENABLER0_OFFSET] + + /* Get redistributor rd base addr for this core */ + mov x0, x5 + bl get_gic_rd_base + mov x4, x0 + + /* x4 = gicr rd base addr */ +2: + /* Poll on rwp bit in GICR_CTLR */ + ldr w2, [x4, #GICR_CTLR_OFFSET] + tst w2, #GICR_CTLR_RWP + b.ne 2b + + /* x4 = gicr rd base addr */ + + /* Unlock the debug interfaces */ + mrs x3, osdlr_el1 + bic x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + dsb sy + isb + mov x30, x6 + ret + +/* + * This function requests a reset of the entire SOC + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6 + */ +_soc_sys_reset: + mov x3, x30 + + /* Make sure the mask is cleared in the reset request mask register */ + mov x0, #RST_RSTRQMR1_OFFSET + mov w1, wzr + bl _write_reg_reset + + /* Set the reset request */ + mov x4, #RST_RSTCR_OFFSET + mov x0, x4 + mov w1, #RSTCR_RESET_REQ + bl _write_reg_reset + + /* x4 = RST_RSTCR_OFFSET */ + + /* + * Just in case this address range is mapped as cacheable, + * flush the write out of the dcaches + */ + mov x2, #NXP_RESET_ADDR + add x2, x2, x4 + dc cvac, x2 + dsb st + isb + + /* This function does not return */ +1: + wfi + b 1b + +/* + * Part of SYSTEM_OFF + * + * This function turns off the SoC clocks + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +_soc_sys_off: + /* + * Disable sec, spi and flexspi + * TBD - Check if eNETC needs to be disabled + */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* Set TPMWAKEMR0 */ + ldr x0, =TPMWAKEMR0_ADDR + mov w1, #0x1 + str w1, [x0] + + /* Disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* Disable L2 prefetches */ + mrs x0, CPUECTLR_EL1 + orr x0, x0, #CPUECTLR_SMPEN_EN + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_2TICKS + msr CPUECTLR_EL1, x0 + dsb sy + isb + + /* Disable CCI snoop domain */ + ldr x0, =NXP_CCI_ADDR + mov w1, #0x1 + str w1, [x0] + + bl get_pmu_idle_core_mask + + /* x3 = pmu base addr */ + mov x3, #NXP_PMU_ADDR +4: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, w0 + b.ne 4b + + bl get_pmu_idle_cluster_mask + mov x3, #NXP_PMU_ADDR + str w0, [x3, #PMU_CLAINACTSETR_OFFSET] + + bl get_pmu_idle_core_mask + mov x3, #NXP_PMU_ADDR +1: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, w0 + b.ne 1b + + bl get_pmu_flush_cluster_mask + mov x3, #NXP_PMU_ADDR + str w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET] +2: + ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET] + cmp w1, w0 + b.ne 2b + + str w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET] + + str w0, [x3, #PMU_CLSINACTSETR_OFFSET] + + mov x2, #DAIF_SET_MASK + mrs x1, spsr_el1 + orr x1, x1, x2 + msr spsr_el1, x1 + + mrs x1, spsr_el2 + orr x1, x1, x2 + msr spsr_el2, x1 + + /* Force the debug interface to be quiescent */ + mrs x0, osdlr_el1 + orr x0, x0, #0x1 + msr osdlr_el1, x0 + + /* Invalidate all TLB entries at all 3 exception levels */ + tlbi alle1 + tlbi alle2 + tlbi alle3 + + /* x3 = pmu base addr */ + + /* Request lpm20 */ + ldr x0, =PMU_POWMGTCSR_OFFSET + ldr w1, =PMU_POWMGTCSR_VAL + str w1, [x3, x0] + isb + dsb sy +5: + wfe + b.eq 5b + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_stdby: + /* Clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * Part of CPU_SUSPEND + * + * This function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_stdby: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_stdby: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2 + */ +_soc_core_prep_pwrdn: + /* Make sure system counter is enabled */ + ldr x2, =NXP_TIMER_ADDR + ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] +1: + /* + * Enable dynamic retention control (CPUECTLR[2:0]) + * Set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_2TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * Part of CPU_SUSPEND + * + * This function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_pwrdn: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after power-down state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_pwrdn: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_stdby: + /* Clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_stdby: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2 + */ +_soc_clstr_prep_pwrdn: + /* Make sure system counter is enabled */ + ldr x2, =NXP_TIMER_ADDR + ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] +1: + /* + * Enable dynamic retention control (CPUECTLR[2:0]) + * Set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_2TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after power-down state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_pwrdn: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_prep_stdby: + /* Clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_sys_exit_stdby: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4 + */ +_soc_sys_prep_pwrdn: + /* Set retention control */ + mrs x0, CPUECTLR_EL1 + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_2TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x0 + dsb sy + isb + ret + +/* + * Part of CPU_SUSPEND + * + * This function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x13, x14, x15, + * x16, x17, x18 + */ +_soc_sys_pwrdn_wfi: + mov x18, x30 + + mov x3, #NXP_PMU_ADDR + + /* x3 = pmu base addr */ + + /* Backup epu registers to stack */ + ldr x2, =NXP_EPU_ADDR + ldr w4, [x2, #EPU_EPIMCR10_OFFSET] + ldr w5, [x2, #EPU_EPCCR10_OFFSET] + ldr w6, [x2, #EPU_EPCTR10_OFFSET] + ldr w7, [x2, #EPU_EPGCR_OFFSET] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = epu base addr + * x3 = pmu base addr + */ + + /* Set up EPU event to receive the wake signal from PMU */ + mov w4, #EPU_EPIMCR10_VAL + mov w5, #EPU_EPCCR10_VAL + mov w6, #EPU_EPCTR10_VAL + mov w7, #EPU_EPGCR_VAL + str w4, [x2, #EPU_EPIMCR10_OFFSET] + str w5, [x2, #EPU_EPCCR10_OFFSET] + str w6, [x2, #EPU_EPCTR10_OFFSET] + str w7, [x2, #EPU_EPGCR_OFFSET] + + ldr x2, =NXP_GICD_ADDR + + /* + * x2 = gicd base addr + * x3 = pmu base addr + */ + + /* Backup flextimer/mmc/usb interrupt router */ + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + ldr w4, [x2, x0] + ldr w5, [x2, x1] + ldr x0, =GICD_IROUTER112_OFFSET + ldr x1, =GICD_IROUTER113_OFFSET + ldr w6, [x2, x0] + ldr w7, [x2, x1] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = gicd base addr + * x3 = pmu base addr + * x0 = GICD_IROUTER112_OFFSET + * x1 = GICD_IROUTER113_OFFSET + */ + + /* Re-route interrupt to cluster 1 */ + ldr w4, =GICD_IROUTER_VALUE + str w4, [x2, x0] + str w4, [x2, x1] + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + str w4, [x2, x0] + str w4, [x2, x1] + dsb sy + isb + + /* x3 = pmu base addr */ + + /* Disable sec, Check for eNETC, spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* x3 = pmu base addr */ + + /* Set TPMWAKEMR0 */ + ldr x0, =TPMWAKEMR0_ADDR + mov w1, #0x1 + str w1, [x0] + + /* Disable CCI snoop domain */ + ldr x0, =NXP_CCI_ADDR + mov w1, #0x1 + str w1, [x0] + + /* Setup retention control */ + mrs x0, CPUECTLR_EL1 + orr x0, x0, #CPUECTLR_SMPEN_EN + orr x0, x0, #CPUECTLR_TIMER_2TICKS + msr CPUECTLR_EL1, x0 + dsb sy + isb + + bl get_pmu_idle_core_mask + mov x3, #NXP_PMU_ADDR +8: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, w0 + b.ne 8b + + /* x3 = NXP_PMU_ADDR */ + /* 1 cluster SoC */ + + bl get_pmu_idle_cluster_mask + mov x3, #NXP_PMU_ADDR + + str w0, [x3, #PMU_CLAINACTSETR_OFFSET] + + bl get_pmu_idle_core_mask + /* x3 = NXP_PMU_ADDR */ + mov x3, #NXP_PMU_ADDR +1: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, w0 + b.ne 1b + + /* x3 = NXP_PMU_ADDR */ + bl get_pmu_flush_cluster_mask + mov x3, #NXP_PMU_ADDR + + str w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET] + + /* x3 = NXP_PMU_ADDR */ +2: + ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET] + cmp w1, w0 + b.ne 2b + + /* x3 = NXP_PMU_ADDR */ + + str w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET] + + str w0, [x3, #PMU_CLSINACTSETR_OFFSET] + + /* Force the debug interface to be quiescent */ + mrs x0, osdlr_el1 + orr x0, x0, #0x1 + msr osdlr_el1, x0 + + /* + * Enable the WakeRequest signal + * x3 is cpu mask starting from cpu1 to cpu0 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base // 0-2 + ldr w1, [x0, #GICR_WAKER_OFFSET] + orr w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cmp w1, #GICR_WAKER_ASLEEP + b.ne 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* Invalidate all TLB entries at all 3 exception levels */ + tlbi alle1 + tlbi alle2 + tlbi alle3 + + /* Request lpm20 */ + mov x3, #NXP_PMU_ADDR + ldr x0, =PMU_POWMGTCSR_OFFSET + ldr w1, =PMU_POWMGTCSR_VAL + str w1, [x3, x0] + + ldr x5, =NXP_EPU_ADDR +4: + wfe + ldr w1, [x5, #EPU_EPCTR10_OFFSET] + cmp w1, #0 + b.eq 4b + + /* x3 = NXP_PMU_ADDR */ + + bl get_pmu_idle_cluster_mask + mov x3, NXP_PMU_ADDR + + /* Re-enable the GPP ACP */ + str w0, [x3, #PMU_CLAINACTCLRR_OFFSET] + str w0, [x3, #PMU_CLSINACTCLRR_OFFSET] + + /* x3 = NXP_PMU_ADDR */ +3: + ldr w1, [x3, #PMU_CLAINACTSETR_OFFSET] + cbnz w1, 3b +4: + ldr w1, [x3, #PMU_CLSINACTSETR_OFFSET] + cbnz w1, 4b + + /* + * Enable the WakeRequest signal on cpu 0-1 + * x3 is cpu mask starting from cpu1 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base // 0-2 + ldr w1, [x0, #GICR_WAKER_OFFSET] + bic w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cbnz w1, 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* Enable CCI snoop domain */ + ldr x0, =NXP_CCI_ADDR + str wzr, [x0] + dsb sy + isb + + ldr x3, =NXP_EPU_ADDR + + /* x3 = epu base addr */ + + /* Enable sec, enetc, spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + str wzr, [x2, #DCFG_DEVDISR1_OFFSET] + str wzr, [x2, #DCFG_DEVDISR2_OFFSET] + str wzr, [x2, #DCFG_DEVDISR4_OFFSET] + + /* Restore flextimer/mmc/usb interrupt router */ + ldr x3, =NXP_GICD_ADDR + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER113_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER112_OFFSET + str w0, [x3, x1] + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER76_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER60_OFFSET + str w0, [x3, x1] + + /* Restore EPU registers */ + ldr x3, =NXP_EPU_ADDR + ldp x0, x2, [sp], #16 + str w2, [x3, #EPU_EPGCR_OFFSET] + str w0, [x3, #EPU_EPCTR10_OFFSET] + ldp x2, x1, [sp], #16 + str w1, [x3, #EPU_EPCCR10_OFFSET] + str w2, [x3, #EPU_EPIMCR10_OFFSET] + + dsb sy + isb + mov x30, x18 + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_exit_pwrdn: + /* Enable stack alignment checking */ + mrs x1, SCTLR_EL1 + orr x1, x1, #0x4 + msr SCTLR_EL1, x1 + + /* Enable debug interface */ + mrs x1, osdlr_el1 + bic x1, x1, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x1 + + /* Enable i-cache */ + mrs x1, SCTLR_EL3 + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL3, x1 + + isb + ret + +/* + * This function setc up the TrustZone Address Space Controller (TZASC) + * in: none + * out: none + * uses x0, x1 + */ +init_tzpc: + /* Set Non Secure access for all devices protected via TZPC */ + ldr x1, =TZPCDECPROT_0_SET_BASE /* decode Protection-0 Set Reg */ + mov w0, #0xFF /* set decode region to NS, Bits[7:0] */ + str w0, [x1] + + ldr x1, =TZPCDECPROT_1_SET_BASE /* decode Protection-1 Set Reg */ + mov w0, #0xFF /* set decode region to NS, Bits[7:0] */ + str w0, [x1] + + ldr x1, =TZPCDECPROT_2_SET_BASE /* decode Protection-2 Set Reg */ + mov w0, #0xFF /* set decode region to NS, Bits[7:0] */ + str w0, [x1] + + /* entire SRAM as NS */ + ldr x1, =NXP_OCRAM_TZPC_ADDR /* secure RAM region size Reg */ + mov w0, #0x00000000 /* 0x00000000 = no secure region */ + str w0, [x1] + + ret + +/* + * This function performs any needed initialization on SecMon for + * boot services + */ +initSecMon: + /* Read the register hpcomr */ + ldr x1, =NXP_SNVS_ADDR + ldr w0, [x1, #SECMON_HPCOMR_OFFSET] + /* Turn off secure access for the privileged registers */ + orr w0, w0, #SECMON_HPCOMR_NPSWAEN + /* Write back */ + str w0, [x1, #SECMON_HPCOMR_OFFSET] + + ret + +/* + * This function checks to see if cores which are to be disabled have been + * released from reset - if not, it releases them + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8 + */ +release_disabled: + stp x18, x30, [sp, #-16]! + + /* + * Get the number of cpus on this device + * Calling the below c function. + * No need to Callee saved registers x9-x15, + * as these registers are not used by the callee + * prior to calling the below C-routine. + */ + bl get_tot_num_cores + mov x6, x0 + + /* Read COREDISABLESR */ + mov x0, #NXP_DCFG_ADDR + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + + mov x0, #NXP_RESET_ADDR + ldr w5, [x0, #BRR_OFFSET] + + /* Load the core mask for the first core */ + mov x7, #1 + + /* + * x4 = COREDISABLESR + * x5 = BRR + * x6 = loop count + * x7 = core mask bit + */ +2: + /* Check if the core is to be disabled */ + tst x4, x7 + b.eq 1f + + /* See if disabled cores have already been released from reset */ + tst x5, x7 + b.ne 1f + + /* If core has not been released, then release it (0-3) */ + mov x0, x7 + bl _soc_core_release + + /* Record the core state in the data area (0-3) */ + mov x0, x7 + mov x1, #CORE_DISABLED + bl _setCoreState +1: + /* Decrement the counter */ + subs x6, x6, #1 + b.le 3f + /* Shift the core mask to the next core */ + lsl x7, x7, #1 + /* Continue */ + b 2b +3: + ldp x18, x30, [sp], #16 + ret + +/* + * Write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + str w1, [x2, x0] + ret + +/* + * Read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +_read_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + ldr w1, [x2, x0] + mov w0, w1 + ret + +/* + * This function returns an mpidr value for a core, given a core_mask_lsb + * in: x0 = core mask lsb + * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits + * uses x0, x1 + */ +get_mpidr_value: + /* Convert a core mask to an SoC core number */ + clz w0, w0 + mov w1, #31 + sub w0, w1, w0 + + /* Get the mpidr core number from the SoC core number */ + mov w1, wzr + tst x0, #1 + b.eq 1f + orr w1, w1, #1 +1: + /* Extract the cluster number */ + lsr w0, w0, #1 + orr w0, w1, w0, lsl #8 + + ret + +/* + * This function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor rd base address for specified core + * uses x0, x1, x2 + */ +get_gic_rd_base: + /* Get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + ldr x0, =NXP_GICR_ADDR + mov x1, #GIC_RD_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * This function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor sgi base address for specified core + * uses x0, x1, x2 + */ +get_gic_sgi_base: + /* Get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + ldr x0, =NXP_GICR_SGI_ADDR + mov x1, #GIC_SGI_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * Write a register in the RESET block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_reset: + ldr x2, =NXP_RESET_ADDR + str w1, [x2, x0] + ret + +/* + * Read a register in the RESET block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +_read_reg_reset: + ldr x1, =NXP_RESET_ADDR + ldr w0, [x1, x0] + ret diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S new file mode 100644 index 0000000..ec67529 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S @@ -0,0 +1,70 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +.globl plat_secondary_cold_boot_setup +.globl plat_is_my_cpu_primary +.globl plat_reset_handler +.globl platform_mem_init + +func platform_mem1_init + ret +endfunc platform_mem1_init + +func platform_mem_init + ret +endfunc platform_mem_init + +func apply_platform_errata + ret +endfunc apply_platform_errata + +func plat_reset_handler + mov x29, x30 + bl apply_platform_errata + +#if defined(IMAGE_BL31) + ldr x0, =POLICY_SMMU_PAGESZ_64K + cbz x0, 1f + /* Set the SMMU page size in the sACR register */ + bl _set_smmu_pagesz_64 +#endif +1: + mov x30, x29 + ret +endfunc plat_reset_handler + +/* + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + */ +func plat_secondary_cold_boot_setup + /* ls1028a does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +/* + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, 0x0 + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h new file mode 100644 index 0000000..b1d044a --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h @@ -0,0 +1,149 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include +#include +#include + +/* + * SVR Definition of LS1028A + * (not include major and minor rev) + * These info is listed in Table B-6. DCFG differences + * between LS1028A and LS1027A of LS1028ARM(Reference Manual) + */ +#define SVR_LS1017AN 0x870B25 +#define SVR_LS1017AE 0x870B24 +#define SVR_LS1018AN 0x870B21 +#define SVR_LS1018AE 0x870B20 +#define SVR_LS1027AN 0x870B05 +#define SVR_LS1027AE 0x870B04 +#define SVR_LS1028AN 0x870B01 +#define SVR_LS1028AE 0x870B00 + +/* Number of cores in platform */ +#define PLATFORM_CORE_COUNT 2 +#define NUMBER_OF_CLUSTERS 1 +#define CORES_PER_CLUSTER 2 + +/* Set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 + +#define NUM_DRAM_REGIONS 3 + +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2GB */ + +#define NXP_DRAM1_ADDR 0x2080000000 +#define NXP_DRAM1_MAX_SIZE 0x1F80000000 /* 126G */ + +#define NXP_DRAM2_ADDR 0x6000000000 +#define NXP_DRAM2_MAX_SIZE 0x2000000000 /* 128G */ + +/* DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +/* CCSR space memory Map */ +#undef NXP_UART_ADDR +#define NXP_UART_ADDR 0x021C0500 + +#undef NXP_UART1_ADDR +#define NXP_UART1_ADDR 0x021C0600 + +#undef NXP_WDOG1_TZ_ADDR +#define NXP_WDOG1_TZ_ADDR 0x023C0000 + +#undef NXP_GICR_ADDR +#define NXP_GICR_ADDR 0x06040000 + +#undef NXP_GICR_SGI_ADDR +#define NXP_GICR_SGI_ADDR 0x06050000 + +/* EPU register offsets and values */ +#define EPU_EPGCR_OFFSET 0x0 +#define EPU_EPIMCR10_OFFSET 0x128 +#define EPU_EPCTR10_OFFSET 0xa28 +#define EPU_EPCCR10_OFFSET 0x828 +#define EPU_EPCCR10_VAL 0xb2800000 +#define EPU_EPIMCR10_VAL 0xba000000 +#define EPU_EPCTR10_VAL 0x0 +#define EPU_EPGCR_VAL (1 << 31) + +/* PORSR1 */ +#define PORSR1_RCW_MASK 0x07800000 +#define PORSR1_RCW_SHIFT 23 + +#define SDHC1_VAL 0x8 +#define SDHC2_VAL 0x9 +#define I2C1_VAL 0xa +#define FLEXSPI_NAND2K_VAL 0xc +#define FLEXSPI_NAND4K_VAL 0xd +#define FLEXSPI_NOR 0xf + +/* + * Required LS standard platform porting definitions + * for CCI-400 + */ +#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4 + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40) + +/* Clock Divisors */ +#define NXP_PLATFORM_CLK_DIVIDER 1 +#define NXP_UART_CLK_DIVIDER 2 + +/* dcfg register offsets and values */ +#define DCFG_DEVDISR2_ENETC (1 << 31) + +#define MPIDR_AFFINITY0_MASK 0x00FF +#define MPIDR_AFFINITY1_MASK 0xFF00 +#define CPUECTLR_DISABLE_TWALK_PREFETCH 0x4000000000 +#define CPUECTLR_INS_PREFETCH_MASK 0x1800000000 +#define CPUECTLR_DAT_PREFETCH_MASK 0x0300000000 +#define OSDLR_EL1_DLK_LOCK 0x1 +#define CNTP_CTL_EL0_EN 0x1 +#define CNTP_CTL_EL0_IMASK 0x2 + +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL + +/* Local power state for power domains in Run state */ +#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) +#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE + +/* One cache line needed for bakery locks on ARM platforms */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + NXP_CCI_CLUSTER0_SL_IFACE_IX, +}; +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); +void _set_platform_security(void); +#endif + +#endif /* SOC_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c new file mode 100644 index 0000000..d82be51 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c @@ -0,0 +1,185 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include + +#include + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80040422), + .cs[0].bnds = U(0xFF), + .sdram_cfg[0] = U(0xE50C0004), + .sdram_cfg[1] = U(0x401100), + .timing_cfg[0] = U(0x91550018), + .timing_cfg[1] = U(0xBAB40C42), + .timing_cfg[2] = U(0x48C111), + .timing_cfg[3] = U(0x1111000), + .timing_cfg[4] = U(0x2), + .timing_cfg[5] = U(0x3401400), + .timing_cfg[7] = U(0x23300000), + .timing_cfg[8] = U(0x2114600), + .sdram_mode[0] = U(0x3010210), + .sdram_mode[9] = U(0x4000000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10210), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x4000000), + .sdram_mode[4] = U(0x10210), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x4000000), + .sdram_mode[6] = U(0x10210), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x4000000), + .interval = U(0x18600618), + .data_init = U(0xdeadbeef), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xA181), + .wrlvl_cntl[0] = U(0x8675F605), + .wrlvl_cntl[1] = U(0x6070700), + .wrlvl_cntl[2] = U(0x0000008), + .dq_map[0] = U(0x5b65b658), + .dq_map[1] = U(0xd96d8000), + .dq_map[2] = U(0), + .dq_map[3] = U(0x1600000), + .debug[28] = U(0x00700046), +}; + +unsigned long long board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + return ULL(0x100000000); +} + +#else + +static const struct rc_timing rcz[] = { + {1600, 8, 5}, + {} +}; + +static const struct board_timing ram[] = { + {0x1f, rcz, 0x1020200, 0x00000003}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + ret = cal_board_params(priv, ram, ARRAY_SIZE(ram)); + if (ret != 0) { + return ret; + } + + popts->bstopre = U(0x40); /* precharge value */ + popts->half_strength_drive_en = 1; + popts->cpo_sample = U(0x46); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */ + + popts->addr_hash = 1; /* address hashing */ + return 0; +} + +/* DDR model number: MT40A1G8SA-075:E */ +struct dimm_params ddr_raw_timing = { + .n_ranks = U(1), + .rank_density = ULL(4294967296), + .capacity = ULL(4294967296), + .primary_sdram_width = U(32), + .ec_sdram_width = U(4), + .rdimm = U(0), + .mirrored_dimm = U(0), + .n_row_addr = U(16), + .n_col_addr = U(10), + .bank_group_bits = U(2), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 750, + .tckmax_ps = 1900, + .caslat_x = U(0x0001FFE00), + .taa_ps = 13500, + .trcd_ps = 13500, + .trp_ps = 13500, + .tras_ps = 32000, + .trc_ps = 45500, + .twr_ps = 15000, + .trfc1_ps = 350000, + .trfc2_ps = 260000, + .trfc4_ps = 160000, + .tfaw_ps = 21000, + .trrds_ps = 3000, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = U(7800000), + .dq_mapping[0] = U(0x16), + .dq_mapping[1] = U(0x36), + .dq_mapping[2] = U(0x16), + .dq_mapping[3] = U(0x36), + .dq_mapping[4] = U(0x16), + .dq_mapping[5] = U(0x36), + .dq_mapping[6] = U(0x16), + .dq_mapping[7] = U(0x36), + .dq_mapping[8] = U(0x16), + .dq_mapping[9] = U(0x0), + .dq_mapping[10] = U(0x0), + .dq_mapping[11] = U(0x0), + .dq_mapping[12] = U(0x0), + .dq_mapping[13] = U(0x0), + .dq_mapping[14] = U(0x0), + .dq_mapping[15] = U(0x0), + .dq_mapping[16] = U(0x0), + .dq_mapping[17] = U(0x0), + .dq_mapping_ors = U(0), + .rc = U(0x1f), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, + struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + return 1; +} +#endif + +int64_t init_ddr(void) +{ + struct ddr_info info; + struct sysinfo sys; + int64_t dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h new file mode 100644 index 0000000..63c0219 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h @@ -0,0 +1,76 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +#include +/* + * Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +#define NXP_SPD_EEPROM0 0x51 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0xC000) + +#ifdef SD_BOOT +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) +#else +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#endif +#define BL2_TEXT_LIMIT (BL2_LIMIT) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +#define BL31_WDOG_SEC 89 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) +#endif /* PLAT_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c new file mode 100644 index 0000000..65d508c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk new file mode 100644 index 0000000..c455000 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk @@ -0,0 +1,33 @@ +# +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Board-specific build parameters +BOOT_MODE ?= flexspi_nor +BOARD := ls1028ardb +POVDD_ENABLE := no +WARM_BOOT := no + +# DDR build parameters +NUM_OF_DDRC := 1 +CONFIG_DDR_NODIMM := 1 +DDR_ECC_EN := yes + +# On-board flash +FLASH_TYPE := MT35XU02G +XSPI_FLASH_SZ := 0x10000000 + +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := flexspi_nor \ + sd \ + emmc + +# Add platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Add SoC build info +include plat/nxp/soc-ls1028a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h new file mode 100644 index 0000000..bbad293 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h new file mode 100644 index 0000000..67a8b45 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* + * Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c new file mode 100644 index 0000000..2fb353f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c @@ -0,0 +1,432 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#endif +#include "plat_common.h" +#include "platform_def.h" +#include "soc.h" + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, +}; + +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1017AN, LS1017AN, 1, 1), + SOC_ENTRY(LS1017AE, LS1017AE, 1, 1), + SOC_ENTRY(LS1018AN, LS1018AN, 1, 1), + SOC_ENTRY(LS1018AE, LS1018AE, 1, 1), + SOC_ENTRY(LS1027AN, LS1027AN, 1, 2), + SOC_ENTRY(LS1027AE, LS1027AE, 1, 2), + SOC_ENTRY(LS1028AN, LS1028AN, 1, 2), + SOC_ENTRY(LS1028AE, LS1028AE, 1, 2), +}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1028a_cluster_count); + +/* + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + * + */ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + */ + counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF); + + return counter_base_frequency; +} + +#ifdef IMAGE_BL2 + +#ifdef POLICY_FUSE_PROVISION +static gpio_init_info_t gpio_init_data = { + .gpio1_base_addr = NXP_GPIO1_ADDR, + .gpio2_base_addr = NXP_GPIO2_ADDR, + .gpio3_base_addr = NXP_GPIO3_ADDR, +}; +#endif + +void soc_preload_setup(void) +{ +} + +void soc_early_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); + enable_timer_base_to_cluster(NXP_PMU_ADDR); + enable_core_tb(NXP_PMU_ADDR); + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#ifdef POLICY_FUSE_PROVISION + gpio_init(&gpio_init_data); + sec_init(NXP_CAAM_ADDR); +#endif + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + enum boot_device dev = get_boot_dev(); + /* + * Mark the buffer for SD in OCRAM as non secure. + * The buffer is assumed to be at end of OCRAM for + * the logic below to calculate TZPC programming + */ + if (dev == BOOT_DEVICE_EMMC || dev == BOOT_DEVICE_SDHC2_EMMC) { + /* + * Calculate the region in OCRAM which is secure + * The buffer for SD needs to be marked non-secure + * to allow SD to do DMA operations on it + */ + uint32_t secure_region = (NXP_OCRAM_SIZE - NXP_SD_BLOCK_BUF_SIZE); + uint32_t mask = secure_region/TZPC_BLOCK_SIZE; + + mmio_write_32(NXP_OCRAM_TZPC_ADDR, mask); + + /* Add the entry for buffer in MMU Table */ + mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, MT_DEVICE | MT_RW | MT_NS); + } + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled()) { + sec_init(NXP_CAAM_ADDR); + } else { + INFO("SEC is disabled.\n"); + } +#endif +#endif + + /* Set eDDRTQ for DDR performance */ + scfg_setbits32((void *)(NXP_SCFG_ADDR + 0x210), 0x1f1f1f1f); + + soc_errata(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + + delay_timer_init(NXP_TIMER_ADDR); + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +} + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +/* + * This function returns the boot device based on RCW_SRC + */ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + switch (rcw_src) { + case FLEXSPI_NOR: + src = BOOT_DEVICE_FLEXSPI_NOR; + INFO("RCW BOOT SRC is FLEXSPI NOR\n"); + break; + case FLEXSPI_NAND2K_VAL: + case FLEXSPI_NAND4K_VAL: + INFO("RCW BOOT SRC is FLEXSPI NAND\n"); + src = BOOT_DEVICE_FLEXSPI_NAND; + break; + case SDHC1_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD\n"); + break; + case SDHC2_VAL: + src = BOOT_DEVICE_SDHC2_EMMC; + INFO("RCW BOOT SRC is EMMC\n"); + break; + default: + break; + } + + return src; +} + +/* + * This function sets up access permissions on memory regions + ****************************************************************************/ +void soc_mem_access(void) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx = 0; + /* index 0 is reserved for region-0 */ + int index = 1; + + for (dram_idx = 0; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[dram_idx].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc400_reg_list(tzc400_reg_list, + dram_idx, index, + info_dram_regions->region[dram_idx].addr, + info_dram_regions->region[dram_idx].size, + NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE); + } + + mem_access_setup(NXP_TZC_ADDR, index, tzc400_reg_list); +} + +#else + +static unsigned char _power_domain_tree_desc[NUMBER_OF_CLUSTERS + 2]; +/* + * This function dynamically constructs the topology according to + * SoC Flavor and returns it. + */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + uint8_t num_clusters, cores_per_cluster; + unsigned int i; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + _power_domain_tree_desc[0] = 1; + _power_domain_tree_desc[1] = num_clusters; + + for (i = 0; i < _power_domain_tree_desc[1]; i++) + _power_domain_tree_desc[i + 2] = cores_per_cluster; + + return _power_domain_tree_desc; +} + +/* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + */ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + return num_clusters; +} + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* Initialize system level generic timer for Socs */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uintptr_t target_mask_array[PLATFORM_CORE_COUNT]; + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0) + }; + + plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array, + plat_core_pos); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* This function initializes the soc from the BL31 module */ +void soc_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + /* Low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* Enable Interconnect coherency for the primary CPU's cluster. */ + plat_ls_interconnect_enter_coherency(num_clusters); + + /* Set platform security policies */ + _set_platform_security(); + + /* Init SEC Engine which will be used by SiP */ + if (is_sec_enabled()) { + sec_init(NXP_CAAM_ADDR); + } else { + INFO("SEC is disabled.\n"); + } +} + +#ifdef NXP_WDOG_RESTART +static uint64_t wdog_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint8_t data = WDOG_RESET_FLAG; + + wr_nv_app_data(WDT_RESET_FLAG_OFFSET, + (uint8_t *)&data, sizeof(data)); + + mmio_write_32(NXP_RST_ADDR + RSTCNTL_OFFSET, SW_RST_REQ_INIT); + + return 0; +} +#endif + +void soc_runtime_setup(void) +{ +#ifdef NXP_WDOG_RESTART + request_intr_type_el3(BL31_NS_WDOG_WS1, wdog_interrupt_handler); +#endif +} + +/* This function returns the total number of cores in the SoC. */ +unsigned int get_tot_num_cores(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + return (num_clusters * cores_per_cluster); +} + +/* This function returns the PMU IDLE Cluster mask. */ +unsigned int get_pmu_idle_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + return ((1 << num_clusters) - 2); +} + +/* This function returns the PMU Flush Cluster mask. */ +unsigned int get_pmu_flush_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + return ((1 << num_clusters) - 2); +} + +/* This function returns the PMU idle core mask. */ +unsigned int get_pmu_idle_core_mask(void) +{ + return ((1 << get_tot_num_cores()) - 2); +} + +/* Function to return the SoC SYS CLK */ +unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def new file mode 100644 index 0000000..c23c1bb --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def @@ -0,0 +1,97 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a72 + +CACHE_LINE := 6 + +# Set to GIC400 or GIC500 +GIC := GIC500 + +# Set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# Layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 3_2 + +# TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE is NS16550 or PL011 +CONSOLE := NS16550 + +# DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def +# Input to CST create_hdr_esbc tool +CSF_HDR_SZ := 0x3000 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + +# OCRAM MAP for BL2 +# Before BL2 +# 0x18000000 - 0x18009fff -> Used by ROM code +# 0x1800a000 - 0x1800dfff -> CSF header for BL2 +# For FlexSFlexSPI boot +# 0x1800e000 - 0x18040000 -> Reserved for BL2 binary +# For SD boot +# 0x1800e000 - 0x18030000 -> Reserved for BL2 binary +# 0x18030000 - 0x18040000 -> Reserved for SD buffer +OCRAM_START_ADDR := 0x18000000 +OCRAM_SIZE := 0x40000 + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0xa000 + +# Location of BL2 on OCRAM +BL2_BASE_ADDR := $(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) + $(CSF_HDR_SZ) ))) + +# Covert to HEX to be used by create_pbl.mk +BL2_BASE := $(shell echo "0x"$$(echo "obase=16; ${BL2_BASE_ADDR}" | bc)) + +# BL2_HDR_LOC is at (BL2_BASE + NXP_ROM_RSVD) +# This value BL2_HDR_LOC + CSF_HDR_SZ should not +# overalp with BL2_BASE +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC := 0x1800A000 + +# SoC ERRATAS to be enabled +ERRATA_SOC_A008850 := 1 + +ERRATA_DDR_A009803 := 1 +ERRATA_DDR_A009942 := 1 +ERRATA_DDR_A010165 := 1 + +# Enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# Define Endianness of each module +NXP_GUR_ENDIANNESS := LE +NXP_DDR_ENDIANNESS := LE +NXP_SEC_ENDIANNESS := LE +NXP_SFP_ENDIANNESS := LE +NXP_SNVS_ENDIANNESS := LE +NXP_ESDHC_ENDIANNESS := LE +NXP_QSPI_ENDIANNESS := LE +NXP_FSPI_ENDIANNESS := LE +NXP_SCFG_ENDIANNESS := LE +NXP_GPIO_ENDIANNESS := LE + +NXP_SFP_VER := 3_4 + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.mk new file mode 100644 index 0000000..92d8e98 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.mk @@ -0,0 +1,113 @@ +# +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1028a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH := plat/nxp/common +PLAT_DRIVERS_PATH := drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + +# Get SoC-specific definitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + +ifeq (${TRUSTED_BOARD_BOOT},1) +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + +$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +# Selecting PSCI & SIP_SVC support +$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31)) + +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_SOC_PATH}/include\ + -I${PLAT_COMMON_PATH}/soc_errata + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq ($(WARM_BOOT),yes) +include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk +endif + +ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes) +include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +ifeq (${DDR_FIP_IO_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/fip_handler/ddr_fip/ddr_fip_io.mk +endif + +# For fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + +# Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\ + ${WARM_RST_INCLUDES} + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${WARM_RST_BL31_SOURCES}\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\ + ${NV_STORAGE_SOURCES}\ + ${WARM_RST_BL_COMM_SOURCES}\ + ${PLAT_SOC_PATH}/soc.c + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S \ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + +# Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S b/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S new file mode 100644 index 0000000..a1baf79 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S @@ -0,0 +1,1637 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* the BASE address for these offsets is AUX_01_DATA in the */ +/* bootcore's psci data region */ +#define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */ +#define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */ +#define CPUACTLR_DATA_OFFSET 0x10 /* references AUX_03_DATA */ +/* the BASE address for these offsets is AUX_04_DATA in the */ +/* bootcore's psci data region */ +#define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */ +#define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */ + +#define DAIF_DATA AUX_06_DATA /* references AUX_06_DATA */ + +#define IPSTPACK_RETRY_CNT 0x10000 +#define DDR_SLEEP_RETRY_CNT 0x10000 +#define CPUACTLR_EL1 S3_1_C15_C2_0 +#define DDR_SDRAM_CFG_2_FRCSR 0x80000000 +#define DDR_SDRAM_CFG_2_OFFSET 0x114 +#define DDR_TIMING_CFG_4_OFFSET 0x160 +#define DDR_CNTRL_BASE_ADDR 0x01080000 + +#define DLL_LOCK_MASK 0x3 +#define DLL_LOCK_VALUE 0x2 + +#define ERROR_DDR_SLEEP -1 +#define ERROR_DDR_WAKE -2 +#define ERROR_NO_QUIESCE -3 + +#define CORE_RESTARTABLE 0 +#define CORE_NOT_RESTARTABLE 1 + +#define RESET_RETRY_CNT 800 + +.global soc_init_lowlevel +.global soc_init_percpu +.global _soc_core_release +.global _soc_core_restart +.global _soc_ck_disabled +.global _soc_sys_reset +.global _soc_sys_off +.global _getGICD_BaseAddr +.global _getGICC_BaseAddr +.global _soc_set_start_addr +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off +.global _soc_core_prep_stdby +.global _soc_core_entr_stdby +.global _soc_core_exit_stdby +.global _soc_core_prep_pwrdn +.global _soc_core_entr_pwrdn +.global _soc_core_exit_pwrdn +.global _soc_clstr_prep_stdby +.global _soc_clstr_exit_stdby +.global _soc_clstr_prep_pwrdn +.global _soc_clstr_exit_pwrdn +.global _soc_sys_prep_stdby +.global _soc_sys_exit_stdby +.global _soc_sys_prep_pwrdn +.global _soc_sys_pwrdn_wfi +.global _soc_sys_exit_pwrdn + +/* + * This function initialize the soc. + * in: void + * out: void + */ +func soc_init_lowlevel + ret +endfunc soc_init_lowlevel + +/* + * void soc_init_percpu(void) + * this function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func soc_init_percpu + mov x3, x30 + + bl plat_my_core_mask + mov x2, x0 + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data /* 0-1 */ + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A53 /* 0 */ +1: + mov x30, x3 + ret +endfunc soc_init_percpu + +/* + * part of CPU_ON + * this function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +_soc_core_release: + +#if (TEST_BL31) + mov w2, w0 + CoreMaskMsb w2, w3 + /* x2 = core mask msb */ +#else + mov x2, x0 +#endif + /* write COREBCR */ + ldr x1, =NXP_SCFG_ADDR + rev w3, w2 + str w3, [x1, #SCFG_COREBCR_OFFSET] + isb + + /* read-modify-write BRR */ + mov x1, #NXP_DCFG_ADDR + ldr w2, [x1, #DCFG_BRR_OFFSET] + rev w3, w2 + orr w3, w3, w0 + rev w2, w3 + str w2, [x1, #DCFG_BRR_OFFSET] + isb + + /* send event */ + sev + isb + ret + + +/* + * part of CPU_ON + * this function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0 ~ x5 + */ +_soc_core_restart: + mov x5, x30 + mov x3, x0 + + /* x3 = core mask lsb */ + bl _getGICD_BaseAddr + mov x4, x0 + + /* x4 = GICD_BASE_ADDR */ + /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */ + ldr w1, [x4, #GICD_CTLR_OFFSET] + orr w1, w1, #GICD_CTLR_EN_GRP0 + str w1, [x4, #GICD_CTLR_OFFSET] + dsb sy + isb + + /* + * fire SGI by writing to GICD_SGIR the following values: + * [25:24] = 0x0 (forward interrupt to the CPU interfaces specified in CPUTargetList field) + * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu) + * [15] = 0 (forward SGI only if it is configured as group 0 interrupt) + * [3:0] = 0xF (interrupt ID = 15) + */ + lsl w1, w3, #16 + orr w1, w1, #0xF + str w1, [x4, #GICD_SGIR_OFFSET] + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x5 + ret + +/* + * this function determines if a core is disabled via COREDISR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1, x2 + */ +_soc_ck_disabled: + + /* get base addr of dcfg block */ + ldr x1, =NXP_DCFG_ADDR + + /* read COREDISR */ + ldr w1, [x1, #DCFG_COREDISR_OFFSET] + rev w2, w1 + + /* test core bit */ + and w0, w2, w0 + ret + +/* + * this function resets the system via SoC-specific methods + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +_soc_sys_reset: + + ldr x2, =NXP_DCFG_ADDR + + /* make sure the mask is cleared in the reset request mask register */ + mov w1, wzr + str w1, [x2, #DCFG_RSTRQMR1_OFFSET] + + /* x2 = NXP_DCFG_ADDR */ + + /* set the reset request */ + ldr w1, =RSTCR_RESET_REQ + ldr x3, =DCFG_RSTCR_OFFSET + rev w0, w1 + str w0, [x2, x3] + + /* x2 = NXP_DCFG_ADDR */ + /* x3 = DCFG_RSTCR_OFFSET */ + + /* just in case this address range is mapped as cacheable, + * flush the write out of the dcaches */ + add x3, x2, x3 + dc cvac, x3 + dsb st + isb + + /* Note: this function does not return */ +1: + wfi + b 1b + + +/* + * part of SYSTEM_OFF + * this function turns off the SoC clocks + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0 ~ x8 + */ +_soc_sys_off: + + /* mask interrupts at the core */ + mrs x1, DAIF + mov x0, #DAIF_SET_MASK + orr x0, x1, x0 + msr DAIF, x0 + + /* disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* disable dcache for EL3 */ + mrs x1, SCTLR_EL3 + bic x1, x1, #SCTLR_C_MASK + /* make sure icache is enabled */ + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL3, x1 + isb + + /* set WFIL2_EN in SCFG_COREPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg + + /* set OVRD_EN in RCPM2_POWMGTDCR */ + ldr x0, =RCPM2_POWMGTDCR_OFFSET + ldr x1, =POWMGTDCR_OVRD_EN + bl write_reg_rcpm2 + + /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */ + ldr x0, =RCPM_IPPDEXPCR0_OFFSET + bl read_reg_rcpm + mov x7, x0 + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK2 + and x6, x6, x7 + cbz x6, 1f + + /* x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_I2C_1 + tst x6, #IPPDEXPCR_I2C1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_LPUART1 + tst x6, #IPPDEXPCR_LPUART1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_OCRAM1 + tst x6, #IPPDEXPCR_OCRAM1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_GPIO + tst x6, #IPPDEXPCR_GPIO1 + csel x5, x5, x4, EQ +1: + /* store the DEVDISR5 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR5_MASK_OFFSET] + + /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK1 + and x6, x6, x7 + cbz x6, 2f + + /* x5 = override mask */ + /* x6 = IPPDEXPCR bits for DEVDISR2 */ + + /* get the overrides */ + orr x4, x5, #DEVDISR2_FMAN1_MAC1 + tst x6, #IPPDEXPCR_MAC1_1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC2 + tst x6, #IPPDEXPCR_MAC1_2 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC3 + tst x6, #IPPDEXPCR_MAC1_3 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC4 + tst x6, #IPPDEXPCR_MAC1_4 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC5 + tst x6, #IPPDEXPCR_MAC1_5 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC6 + tst x6, #IPPDEXPCR_MAC1_6 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC9 + tst x6, #IPPDEXPCR_MAC1_9 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1 + tst x6, #IPPDEXPCR_FM1 + csel x5, x5, x4, EQ + +2: + /* store the DEVDISR2 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR2_MASK_OFFSET] + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR0 - no overrides */ + ldr x0, =RCPM2_IPSTPCR0_OFFSET + ldr x1, =IPSTPCR0_VALUE + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR1 - overrides possible */ + ldr x0, =RCPM2_IPSTPCR1_OFFSET + ldr x1, =IPSTPCR1_VALUE + bic x1, x1, x5 + bl write_reg_rcpm2 + + /* write IPSTPCR2 - no overrides */ + ldr x0, =RCPM2_IPSTPCR2_OFFSET + ldr x1, =IPSTPCR2_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR3 - no overrides */ + ldr x0, =RCPM2_IPSTPCR3_OFFSET + ldr x1, =IPSTPCR3_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x0, =RCPM2_IPSTPCR4_OFFSET + ldr x1, =IPSTPCR4_VALUE + bic x1, x1, x6 + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + /* x6 = DEVDISR5 override mask */ + + /* poll on IPSTPACK0 */ + ldr x3, =RCPM2_IPSTPACKR0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x3, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x5 + ldr x3, =RCPM2_IPSTPACKR1_OFFSET +4: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x3, =RCPM2_IPSTPACKR2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x3, =RCPM2_IPSTPACKR3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x3, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x6 + ldr x3, =RCPM2_IPSTPACKR4_OFFSET +7: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + ldr x7, =BC_PSCI_BASE + add x7, x7, #AUX_01_DATA + + /* x5 = DEVDISR2 override mask + * x6 = DEVDISR5 override mask + * x7 = [soc_data_area] */ + + /* DEVDISR1 - load new value */ + mov x0, #DCFG_DEVDISR1_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR1_OFFSET + ldr x1, =DEVDISR1_VALUE + bl write_reg_dcfg + + /* DEVDISR2 - load new value */ + mov x0, #DCFG_DEVDISR2_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR2_OFFSET + ldr x1, =DEVDISR2_VALUE + bic x1, x1, x5 + bl write_reg_dcfg + + /* x6 = DEVDISR5 override mask */ + /* x7 = [soc_data_area] */ + + /* DEVDISR3 - load new value */ + mov x0, #DCFG_DEVDISR3_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR3_OFFSET + ldr x1, =DEVDISR3_VALUE + bl write_reg_dcfg + + /* DEVDISR4 - load new value */ + mov x0, #DCFG_DEVDISR4_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR4_OFFSET + ldr x1, =DEVDISR4_VALUE + bl write_reg_dcfg + + /* DEVDISR5 - load new value */ + mov x0, #DCFG_DEVDISR5_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR5_OFFSET + ldr x1, =DEVDISR5_VALUE + bic x1, x1, x6 + bl write_reg_dcfg + + /* x7 = [soc_data_area] */ + + /* disable data prefetch */ + mrs x0, CPUACTLR_EL1 + bic x0, x0, #CPUACTLR_L1PCTL_MASK + msr CPUACTLR_EL1, x0 + + /* x6 = DEVDISR5 override mask */ + + /* setup registers for cache-only execution */ + ldr x5, =IPSTPCR4_VALUE + bic x5, x5, x6 + mov x6, #DDR_CNTRL_BASE_ADDR + mov x7, #DCSR_RCPM2_BASE + mov x8, #NXP_DCFG_ADDR + dsb sy + isb + + /* set the DLL_LOCK cycle count */ + ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + rev w2, w1 + bic w2, w2, #DLL_LOCK_MASK + orr w2, w2, #DLL_LOCK_VALUE + rev w1, w2 + str w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + + /* x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR */ + + /* enter the cache-only sequence - there is no return */ + b final_shutdown + + +/* + * part of CPU_OFF + * this function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x7 + */ +_soc_core_prep_off: + mov x7, x30 + mov x6, x0 + + /* make sure the smpen bit is set */ + mrs x2, CORTEX_A53_ECTLR_EL1 + orr x2, x2, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x2 + isb + + /* configure the cpu interface */ + + /* disable signaling of ints */ + bl _getGICC_BaseAddr // 0-1 + mov x4, x0 + + ldr w3, [x4, #GICC_CTLR_OFFSET] + bic w3, w3, #GICC_CTLR_EN_GRP0 + bic w3, w3, #GICC_CTLR_EN_GRP1 + str w3, [x4, #GICC_CTLR_OFFSET] + dsb sy + isb + + /* + * x3 = GICC_CTRL + * x4 = GICC_BASE_ADDR + * x6 = core mask + */ + + /* set the priority filter */ + ldr w2, [x4, #GICC_PMR_OFFSET] + orr w2, w2, #GICC_PMR_FILTER + str w2, [x4, #GICC_PMR_OFFSET] + + /* setup GICC_CTLR */ + bic w3, w3, #GICC_CTLR_ACKCTL_MASK + orr w3, w3, #GICC_CTLR_FIQ_EN_MASK + orr w3, w3, #GICC_CTLR_EOImodeS_MASK + orr w3, w3, #GICC_CTLR_CBPR_MASK + str w3, [x4, #GICC_CTLR_OFFSET] + + /* x3 = GICC_CTRL */ + /* x4 = GICC_BASE_ADDR */ + + /* setup the banked-per-core GICD registers */ + bl _getGICD_BaseAddr + + /* + * x0 = GICD_BASE_ADDR + * x3 = GICC_CTRL + * x4 = GICC_BASE_ADDR + * x6 = core mask + */ + + /* define SGI15 as Grp0 */ + ldr w2, [x0, #GICD_IGROUPR0_OFFSET] + bic w2, w2, #GICD_IGROUP0_SGI15 + str w2, [x0, #GICD_IGROUPR0_OFFSET] + + /* set priority of SGI 15 to highest... */ + ldr w2, [x0, #GICD_IPRIORITYR3_OFFSET] + bic w2, w2, #GICD_IPRIORITY_SGI15_MASK + str w2, [x0, #GICD_IPRIORITYR3_OFFSET] + + /* enable SGI 15 */ + ldr w2, [x0, #GICD_ISENABLER0_OFFSET] + orr w2, w2, #GICD_ISENABLE0_SGI15 + str w2, [x0, #GICD_ISENABLER0_OFFSET] + + /* enable the cpu interface */ + orr w3, w3, #GICC_CTLR_EN_GRP0 + str w3, [x4, #GICC_CTLR_OFFSET] + + /* x0 = GICD_BASE_ADDR + * x6 = core mask */ + + /* clear any pending SGIs */ + add x0, x0, #GICD_CPENDSGIR3_OFFSET + ldr x2, =GICD_CPENDSGIR_CLR_MASK + str w2, [x0] + + dsb sy + isb + mov x30, x7 + ret + +/* + * part of CPU_OFF + * this function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x5 + */ +_soc_core_entr_off: + mov x5, x30 + mov x4, x0 + + bl _getGICD_BaseAddr + mov x3, x0 + + /* x3 = GICD_BASE_ADDR */ + /* x4 = core mask (lsb) */ + +3: + /* enter low-power state by executing wfi */ + wfi + + /* x3 = GICD_BASE_ADDR */ + /* x4 = core mask (lsb) */ + + /* see if we got hit by SGI 15 */ + add x0, x3, #GICD_SPENDSGIR3_OFFSET + ldr w2, [x0] + and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK + cbz w2, 4f + + /* clear the pending SGI */ + ldr x2, =GICD_CPENDSGIR_CLR_MASK + add x0, x3, #GICD_CPENDSGIR3_OFFSET + str w2, [x0] +4: + /* check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + /* x0 = core state */ + cmp x0, #CORE_WAKEUP + b.ne 3b + + /* if we get here, then we have exited the wfi */ + dsb sy + isb + mov x30, x5 + ret + +/* + * part of CPU_OFF + * this function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x5 + */ +_soc_core_exit_off: + mov x5, x30 + mov x4, x0 + + /* x4 = core mask */ + + bl _getGICC_BaseAddr + mov x2, x0 + + /* read GICC_IAR */ + ldr w0, [x2, #GICC_IAR_OFFSET] + + /* write GICC_EIOR - signal end-of-interrupt */ + str w0, [x2, #GICC_EOIR_OFFSET] + + /* write GICC_DIR - disable interrupt */ + str w0, [x2, #GICC_DIR_OFFSET] + + /* x2 = GICC_BASE_ADDR */ + + /* disable signaling of grp0 ints */ + ldr w1, [x2, #GICC_CTLR_OFFSET] + bic w1, w1, #GICC_CTLR_EN_GRP0 + str w1, [x2, #GICC_CTLR_OFFSET] + + dsb sy + isb + mov x30, x5 + ret + +/* + * this function loads a 64-bit execution address of the core in the soc registers + * BOOTLOCPTRL/H + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * uses x0, x1, x2, x3 + */ +_soc_set_start_addr: + /* get the 64-bit base address of the scfg block */ + ldr x2, =NXP_SCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register (offset 0x604 in the scfg block) */ + mov x1, x0 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register (offset 0x600 in the scfg block) */ + lsr x1, x0, #32 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET] + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_stdby: + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_pwrdn: + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_pwrdn: + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_pwrdn: + ret + + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_pwrdn: + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_pwrdn: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_sys_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4 + */ +_soc_sys_prep_pwrdn: + mov x4, x30 + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + /* set WFIL2_EN in SCFG_COREPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg // 0-3 + + /* set OVRD_EN in RCPM2_POWMGTDCR */ + ldr x0, =RCPM2_POWMGTDCR_OFFSET + ldr x1, =POWMGTDCR_OVRD_EN + bl write_reg_rcpm2 // 0-3 + + mov x30, x4 + ret +/* + * part of CPU_SUSPEND + * this function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0 ~ x9 + */ +_soc_sys_pwrdn_wfi: + mov x18, x30 + + /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */ + ldr x0, =RCPM_IPPDEXPCR0_OFFSET + bl read_reg_rcpm + mov x7, x0 + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK2 + and x6, x6, x7 + cbz x6, 1f + + /* x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_I2C_1 + tst x6, #IPPDEXPCR_I2C1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_LPUART1 + tst x6, #IPPDEXPCR_LPUART1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_OCRAM1 + tst x6, #IPPDEXPCR_OCRAM1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_GPIO + tst x6, #IPPDEXPCR_GPIO1 + csel x5, x5, x4, EQ +1: + /* store the DEVDISR5 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR5_MASK_OFFSET] + + /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK1 + and x6, x6, x7 + cbz x6, 2f + + /* x5 = override mask */ + /* x6 = IPPDEXPCR bits for DEVDISR2 */ + + /* get the overrides */ + orr x4, x5, #DEVDISR2_FMAN1_MAC1 + tst x6, #IPPDEXPCR_MAC1_1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC2 + tst x6, #IPPDEXPCR_MAC1_2 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC3 + tst x6, #IPPDEXPCR_MAC1_3 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC4 + tst x6, #IPPDEXPCR_MAC1_4 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC5 + tst x6, #IPPDEXPCR_MAC1_5 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC6 + tst x6, #IPPDEXPCR_MAC1_6 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC9 + tst x6, #IPPDEXPCR_MAC1_9 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1 + tst x6, #IPPDEXPCR_FM1 + csel x5, x5, x4, EQ + +2: + /* store the DEVDISR2 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR2_MASK_OFFSET] + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR0 - no overrides */ + ldr x0, =RCPM2_IPSTPCR0_OFFSET + ldr x1, =IPSTPCR0_VALUE + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR1 - overrides possible */ + ldr x0, =RCPM2_IPSTPCR1_OFFSET + ldr x1, =IPSTPCR1_VALUE + bic x1, x1, x5 + bl write_reg_rcpm2 + + /* write IPSTPCR2 - no overrides */ + ldr x0, =RCPM2_IPSTPCR2_OFFSET + ldr x1, =IPSTPCR2_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR3 - no overrides */ + ldr x0, =RCPM2_IPSTPCR3_OFFSET + ldr x1, =IPSTPCR3_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x0, =RCPM2_IPSTPCR4_OFFSET + ldr x1, =IPSTPCR4_VALUE + bic x1, x1, x6 + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + /* x6 = DEVDISR5 override mask */ + + /* poll on IPSTPACK0 */ + ldr x3, =RCPM2_IPSTPACKR0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x3, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x5 + ldr x3, =RCPM2_IPSTPACKR1_OFFSET +4: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x3, =RCPM2_IPSTPACKR2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x3, =RCPM2_IPSTPACKR3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x3, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x6 + ldr x3, =RCPM2_IPSTPACKR4_OFFSET +7: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + ldr x7, =BC_PSCI_BASE + add x7, x7, #AUX_01_DATA + + /* x5 = DEVDISR2 override mask + * x6 = DEVDISR5 override mask + * x7 = [soc_data_area] */ + + /* save DEVDISR1 and load new value */ + mov x0, #DCFG_DEVDISR1_OFFSET + bl read_reg_dcfg + mov w13, w0 + mov x0, #DCFG_DEVDISR1_OFFSET + ldr x1, =DEVDISR1_VALUE + bl write_reg_dcfg + + /* save DEVDISR2 and load new value */ + mov x0, #DCFG_DEVDISR2_OFFSET + bl read_reg_dcfg + mov w14, w0 + mov x0, #DCFG_DEVDISR2_OFFSET + ldr x1, =DEVDISR2_VALUE + bic x1, x1, x5 + bl write_reg_dcfg + + /* x6 = DEVDISR5 override mask */ + /* x7 = [soc_data_area] */ + + /* save DEVDISR3 and load new value */ + mov x0, #DCFG_DEVDISR3_OFFSET + bl read_reg_dcfg + mov w15, w0 + mov x0, #DCFG_DEVDISR3_OFFSET + ldr x1, =DEVDISR3_VALUE + bl write_reg_dcfg + + /* save DEVDISR4 and load new value */ + mov x0, #DCFG_DEVDISR4_OFFSET + bl read_reg_dcfg + mov w16, w0 + mov x0, #DCFG_DEVDISR4_OFFSET + ldr x1, =DEVDISR4_VALUE + bl write_reg_dcfg + + /* save DEVDISR5 and load new value */ + mov x0, #DCFG_DEVDISR5_OFFSET + bl read_reg_dcfg + mov w17, w0 + mov x0, #DCFG_DEVDISR5_OFFSET + ldr x1, =DEVDISR5_VALUE + bic x1, x1, x6 + bl write_reg_dcfg + + /* x7 = [soc_data_area] */ + + /* save cpuactlr and disable data prefetch */ + mrs x0, CPUACTLR_EL1 + str w0, [x7, #CPUACTLR_DATA_OFFSET] + bic x0, x0, #CPUACTLR_L1PCTL_MASK + msr CPUACTLR_EL1, x0 + + /* x6 = DEVDISR5 override mask */ + + /* setup registers for cache-only execution */ + ldr x5, =IPSTPCR4_VALUE + bic x5, x5, x6 + mov x6, #DDR_CNTRL_BASE_ADDR + mov x7, #DCSR_RCPM2_BASE + mov x8, #NXP_DCFG_ADDR + dsb sy + isb + + /* set the DLL_LOCK cycle count */ + ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + rev w2, w1 + bic w2, w2, #DLL_LOCK_MASK + orr w2, w2, #DLL_LOCK_VALUE + rev w1, w2 + str w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + + /* + * x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + */ + + /* enter the cache-only sequence */ + mov x9, #CORE_RESTARTABLE + bl final_pwrdown + + /* when we are here, the core has come out of wfi and the SoC is back up */ + + mov x30, x18 + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_exit_pwrdn: + /* clear POWMGTDCR */ + mov x1, #DCSR_RCPM2_BASE + str wzr, [x1, #RCPM2_POWMGTDCR_OFFSET] + + /* clear WFIL2_EN in SCFG_COREPMCR */ + mov x1, #NXP_SCFG_ADDR + str wzr, [x1, #SCFG_COREPMCR_OFFSET] + + ret + +/* + * write a register in the SCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_scfg: + ldr x2, =NXP_SCFG_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret +/* + * read a register in the SCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_scfg: + ldr x2, =NXP_SCFG_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the RCPM block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_rcpm: + ldr x2, =NXP_RCPM_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the RCPM block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_rcpm: + ldr x2, =NXP_RCPM_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the DCSR-RCPM2 block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_rcpm2: + ldr x2, =DCSR_RCPM2_BASE + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the DCSR-RCPM2 block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_rcpm2: + ldr x2, =DCSR_RCPM2_BASE + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * this function returns the base address of the gic distributor + * in: none + * out: x0 = base address of gic distributor + * uses x0, x1 + */ +_getGICD_BaseAddr: + /* read SVR and get the SoC version */ + mov x0, #NXP_DCFG_ADDR + ldr w1, [x0, #DCFG_SVR_OFFSET] + rev w0, w1 + + /* x0 = svr */ + and w0, w0, #SVR_MIN_VER_MASK + cmp w0, #SVR_MINOR_VER_0 + b.ne 8f + + /* load the gic base addresses for rev 1.0 parts */ + ldr x0, =NXP_GICD_4K_ADDR + b 10f +8: + /* for rev 1.1 and later parts, the GIC base addresses */ + /* can be at 4k or 64k offsets */ + + /* read the scfg reg GIC400_ADDR_ALIGN */ + mov x0, #NXP_SCFG_ADDR + ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET] + rev w0, w1 + + /* x0 = GIC400_ADDR_ALIGN value */ + and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK + mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN + cmp x0, x1 + b.ne 9f + + /* load the base addresses for 4k offsets */ + ldr x0, =NXP_GICD_4K_ADDR + b 10f +9: + /* load the base address for 64k offsets */ + ldr x0, =NXP_GICD_64K_ADDR +10: + ret + +/* + * this function returns the base address of the gic distributor + * in: none + * out: x0 = base address of gic controller + * uses x0, x1 + */ +_getGICC_BaseAddr: + /* read SVR and get the SoC version */ + mov x0, #NXP_DCFG_ADDR + ldr w1, [x0, #DCFG_SVR_OFFSET] + rev w0, w1 + + /* x0 = svr */ + and w0, w0, #SVR_MIN_VER_MASK + cmp w0, #SVR_MINOR_VER_0 + b.ne 8f + + /* load the gic base addresses for rev 1.0 parts */ + ldr x0, =NXP_GICC_4K_ADDR + b 10f +8: + /* for rev 1.1 and later parts, the GIC base addresses */ + /* can be at 4k or 64k offsets */ + + /* read the scfg reg GIC400_ADDR_ALIGN */ + mov x0, #NXP_SCFG_ADDR + ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET] + rev w0, w1 + + /* x0 = GIC400_ADDR_ALIGN value */ + and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK + mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN + cmp x0, x1 + b.ne 9f + + /* load the base addresses for 4k offsets */ + ldr x0, =NXP_GICC_4K_ADDR + b 10f +9: + /* load the base address for 64k offsets */ + ldr x0, =NXP_GICC_64K_ADDR +10: + ret + +/* + * this function will pwrdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * x9 = 0, restartable + * = 1, non-restartable + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * out: none + * uses x0 ~ x9 + */ + +/* 4Kb aligned */ +.align 12 +final_pwrdown: + mov x0, xzr + b touch_line_0 +start_line_0: + mov x0, #1 + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + orr w4, w4, w2 + rev w3, w4 + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */ + orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */ + rev w4, w3 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */ + + mov w3, #DEVDISR5_MEM + rev w3, w3 /* polling mask */ + mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */ +touch_line_0: + cbz x0, touch_line_1 + +start_line_1: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] + tst w1, w3 + b.ne 1f + subs x2, x2, #1 + b.gt start_line_1 /* poll on ipstpack4 - end */ + + /* if we get here, we have a timeout err */ + rev w4, w5 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clks interface */ + mov x0, #ERROR_DDR_SLEEP /* load error code */ + b 2f +1: + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */ +5: + wfi /* stop the final core */ + + cbnz x9, 5b /* if non-restartable, keep in wfi */ + rev w4, w5 + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* re-enable ddr in devdisr5 */ + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clk in ipstpcr4 */ +touch_line_1: + cbz x0, touch_line_2 + +start_line_2: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] /* poll on ipstpack4 - start */ + tst w1, w3 + b.eq 2f + nop + b start_line_2 /* poll on ipstpack4 - end */ +2: + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* take ddr out-of self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + bic w4, w4, w2 + rev w3, w4 + mov x1, #DDR_SLEEP_RETRY_CNT /* wait for ddr cntrlr clock - start */ +3: + subs x1, x1, #1 + b.gt 3b /* wait for ddr cntrlr clock - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* take ddr out-of self refresh - end */ + rev w1, w17 +touch_line_2: + cbz x0, touch_line_3 + +start_line_3: + str w1, [x8, #DCFG_DEVDISR5_OFFSET] /* reset devdisr5 */ + rev w1, w16 + str w1, [x8, #DCFG_DEVDISR4_OFFSET] /* reset devdisr4 */ + rev w1, w15 + str w1, [x8, #DCFG_DEVDISR3_OFFSET] /* reset devdisr3 */ + rev w1, w14 + str w1, [x8, #DCFG_DEVDISR2_OFFSET] /* reset devdisr2 */ + rev w1, w13 + str w1, [x8, #DCFG_DEVDISR1_OFFSET] /* reset devdisr1 */ + str wzr, [x7, #RCPM2_IPSTPCR4_OFFSET] /* reset ipstpcr4 */ + str wzr, [x7, #RCPM2_IPSTPCR3_OFFSET] /* reset ipstpcr3 */ + str wzr, [x7, #RCPM2_IPSTPCR2_OFFSET] /* reset ipstpcr2 */ + str wzr, [x7, #RCPM2_IPSTPCR1_OFFSET] /* reset ipstpcr1 */ + str wzr, [x7, #RCPM2_IPSTPCR0_OFFSET] /* reset ipstpcr0 */ + b continue_restart +touch_line_3: + cbz x0, start_line_0 + +/* execute here after ddr is back up */ +continue_restart: + /* + * if x0 = 1, all is well + * if x0 < 1, we had an error + */ + cmp x0, #1 + b.ne 4f + mov x0, #0 +4: + ret + +/* + * Note: there is no return from this function + * this function will shutdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * out: none + * uses x0 ~ x8 + */ + +/* 4Kb aligned */ +.align 12 +final_shutdown: + + mov x0, xzr + b touch_line0 +start_line0: + mov x0, #1 + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + orr w4, w4, w2 + rev w3, w4 + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */ + orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */ + rev w4, w3 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */ + + mov w3, #DEVDISR5_MEM + rev w3, w3 /* polling mask */ + mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */ +touch_line0: + cbz x0, touch_line1 + +start_line1: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] + tst w1, w3 + b.ne 1f + subs x2, x2, #1 + b.gt start_line1 /* poll on ipstpack4 - end */ + nop + nop + nop + nop +1: + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */ +5: + wfi /* stop the final core */ + b 5b /* stay here until POR */ + nop + nop + nop +touch_line1: + cbz x0, start_line0 diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S new file mode 100644 index 0000000..bc88886 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S @@ -0,0 +1,70 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl plat_reset_handler + .globl platform_mem_init + +func platform_mem1_init + ret +endfunc platform_mem1_init + +func platform_mem_init + ret +endfunc platform_mem_init + +func apply_platform_errata + ret +endfunc apply_platform_errata + +func plat_reset_handler + mov x29, x30 + bl apply_platform_errata + +#if defined(IMAGE_BL31) + ldr x0, =POLICY_SMMU_PAGESZ_64K + cbz x0, 1f + /* Set the SMMU page size in the sACR register */ + bl _set_smmu_pagesz_64 +#endif +1: + mov x30, x29 + ret +endfunc plat_reset_handler + +/* + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + */ +func plat_secondary_cold_boot_setup + /* ls1043a does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +/* + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, 0x0 + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h new file mode 100644 index 0000000..423c454 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015, 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018, 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NS_ACCESS_H +#define NS_ACCESS_H + +#include + +enum csu_cslx_ind { + CSU_CSLX_PCIE2_IO = 0, + CSU_CSLX_PCIE1_IO, + CSU_CSLX_MG2TPR_IP, + CSU_CSLX_IFC_MEM, + CSU_CSLX_OCRAM, + CSU_CSLX_GIC, + CSU_CSLX_PCIE1, + CSU_CSLX_OCRAM2, + CSU_CSLX_QSPI_MEM, + CSU_CSLX_PCIE2, + CSU_CSLX_SATA, + CSU_CSLX_USB1, + CSU_CSLX_QM_BM_SWPORTAL, + CSU_CSLX_PCIE3 = 16, + CSU_CSLX_PCIE3_IO, + CSU_CSLX_USB3 = 20, + CSU_CSLX_USB2, + CSU_CSLX_PFE = 23, + CSU_CSLX_SERDES = 32, + CSU_CSLX_QDMA, + CSU_CSLX_LPUART2, + CSU_CSLX_LPUART1, + CSU_CSLX_LPUART4, + CSU_CSLX_LPUART3, + CSU_CSLX_LPUART6, + CSU_CSLX_LPUART5, + CSU_CSLX_DSPI1 = 41, + CSU_CSLX_QSPI, + CSU_CSLX_ESDHC, + CSU_CSLX_IFC = 45, + CSU_CSLX_I2C1, + CSU_CSLX_USB_2, + CSU_CSLX_I2C3 = 48, + CSU_CSLX_I2C2, + CSU_CSLX_DUART2 = 50, + CSU_CSLX_DUART1, + CSU_CSLX_WDT2, + CSU_CSLX_WDT1, + CSU_CSLX_EDMA, + CSU_CSLX_SYS_CNT, + CSU_CSLX_DMA_MUX2, + CSU_CSLX_DMA_MUX1, + CSU_CSLX_DDR, + CSU_CSLX_QUICC, + CSU_CSLX_DCFG_CCU_RCPM = 60, + CSU_CSLX_SECURE_BOOTROM, + CSU_CSLX_SFP, + CSU_CSLX_TMU, + CSU_CSLX_SECURE_MONITOR, + CSU_CSLX_SCFG, + CSU_CSLX_FM = 66, + CSU_CSLX_SEC5_5, + CSU_CSLX_BM, + CSU_CSLX_QM, + CSU_CSLX_GPIO2 = 70, + CSU_CSLX_GPIO1, + CSU_CSLX_GPIO4, + CSU_CSLX_GPIO3, + CSU_CSLX_PLATFORM_CONT, + CSU_CSLX_CSU, + CSU_CSLX_IIC4 = 77, + CSU_CSLX_WDT4, + CSU_CSLX_WDT3, + CSU_CSLX_ESDHC2 = 80, + CSU_CSLX_WDT5 = 81, + CSU_CSLX_SAI2, + CSU_CSLX_SAI1, + CSU_CSLX_SAI4, + CSU_CSLX_SAI3, + CSU_CSLX_FTM2 = 86, + CSU_CSLX_FTM1, + CSU_CSLX_FTM4, + CSU_CSLX_FTM3, + CSU_CSLX_FTM6 = 90, + CSU_CSLX_FTM5, + CSU_CSLX_FTM8, + CSU_CSLX_FTM7, + CSU_CSLX_DSCR = 121, +}; + +struct csu_ns_dev_st ns_dev[] = { + {CSU_CSLX_PCIE2_IO, CSU_ALL_RW}, + {CSU_CSLX_PCIE1_IO, CSU_ALL_RW}, + {CSU_CSLX_MG2TPR_IP, CSU_ALL_RW}, + {CSU_CSLX_IFC_MEM, CSU_ALL_RW}, + {CSU_CSLX_OCRAM, CSU_S_SUP_RW}, + {CSU_CSLX_GIC, CSU_ALL_RW}, + {CSU_CSLX_PCIE1, CSU_ALL_RW}, + {CSU_CSLX_OCRAM2, CSU_S_SUP_RW}, + {CSU_CSLX_QSPI_MEM, CSU_ALL_RW}, + {CSU_CSLX_PCIE2, CSU_ALL_RW}, + {CSU_CSLX_SATA, CSU_ALL_RW}, + {CSU_CSLX_USB1, CSU_ALL_RW}, + {CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW}, + {CSU_CSLX_PCIE3, CSU_ALL_RW}, + {CSU_CSLX_PCIE3_IO, CSU_ALL_RW}, + {CSU_CSLX_USB3, CSU_ALL_RW}, + {CSU_CSLX_USB2, CSU_ALL_RW}, + {CSU_CSLX_PFE, CSU_ALL_RW}, + {CSU_CSLX_SERDES, CSU_ALL_RW}, + {CSU_CSLX_QDMA, CSU_ALL_RW}, + {CSU_CSLX_LPUART2, CSU_ALL_RW}, + {CSU_CSLX_LPUART1, CSU_ALL_RW}, + {CSU_CSLX_LPUART4, CSU_ALL_RW}, + {CSU_CSLX_LPUART3, CSU_ALL_RW}, + {CSU_CSLX_LPUART6, CSU_ALL_RW}, + {CSU_CSLX_LPUART5, CSU_ALL_RW}, + {CSU_CSLX_DSPI1, CSU_ALL_RW}, + {CSU_CSLX_QSPI, CSU_ALL_RW}, + {CSU_CSLX_ESDHC, CSU_ALL_RW}, + {CSU_CSLX_IFC, CSU_ALL_RW}, + {CSU_CSLX_I2C1, CSU_ALL_RW}, + {CSU_CSLX_USB_2, CSU_ALL_RW}, + {CSU_CSLX_I2C3, CSU_ALL_RW}, + {CSU_CSLX_I2C2, CSU_ALL_RW}, + {CSU_CSLX_DUART2, CSU_ALL_RW}, + {CSU_CSLX_DUART1, CSU_ALL_RW}, + {CSU_CSLX_WDT2, CSU_ALL_RW}, + {CSU_CSLX_WDT1, CSU_ALL_RW}, + {CSU_CSLX_EDMA, CSU_ALL_RW}, + {CSU_CSLX_SYS_CNT, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX2, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX1, CSU_ALL_RW}, + {CSU_CSLX_DDR, CSU_ALL_RW}, + {CSU_CSLX_QUICC, CSU_ALL_RW}, + {CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW}, + {CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW}, + {CSU_CSLX_SFP, CSU_ALL_RW}, + {CSU_CSLX_TMU, CSU_ALL_RW}, + {CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW}, + {CSU_CSLX_SCFG, CSU_ALL_RW}, + {CSU_CSLX_FM, CSU_ALL_RW}, + {CSU_CSLX_SEC5_5, CSU_ALL_RW}, + {CSU_CSLX_BM, CSU_ALL_RW}, + {CSU_CSLX_QM, CSU_ALL_RW}, + {CSU_CSLX_GPIO2, CSU_ALL_RW}, + {CSU_CSLX_GPIO1, CSU_ALL_RW}, + {CSU_CSLX_GPIO4, CSU_ALL_RW}, + {CSU_CSLX_GPIO3, CSU_ALL_RW}, + {CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW}, + {CSU_CSLX_CSU, CSU_ALL_RW}, + {CSU_CSLX_IIC4, CSU_ALL_RW}, + {CSU_CSLX_WDT4, CSU_ALL_RW}, + {CSU_CSLX_WDT3, CSU_ALL_RW}, + {CSU_CSLX_ESDHC2, CSU_ALL_RW}, + {CSU_CSLX_WDT5, CSU_ALL_RW}, + {CSU_CSLX_SAI2, CSU_ALL_RW}, + {CSU_CSLX_SAI1, CSU_ALL_RW}, + {CSU_CSLX_SAI4, CSU_ALL_RW}, + {CSU_CSLX_SAI3, CSU_ALL_RW}, + {CSU_CSLX_FTM2, CSU_ALL_RW}, + {CSU_CSLX_FTM1, CSU_ALL_RW}, + {CSU_CSLX_FTM4, CSU_ALL_RW}, + {CSU_CSLX_FTM3, CSU_ALL_RW}, + {CSU_CSLX_FTM6, CSU_ALL_RW}, + {CSU_CSLX_FTM5, CSU_ALL_RW}, + {CSU_CSLX_FTM8, CSU_ALL_RW}, + {CSU_CSLX_FTM7, CSU_ALL_RW}, + {CSU_CSLX_DSCR, CSU_ALL_RW}, +}; + +#endif /* NS_ACCESS_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h new file mode 100644 index 0000000..e018102 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h @@ -0,0 +1,234 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include "dcfg_lsch2.h" +#include "soc_default_base_addr.h" +#include "soc_default_helper_macros.h" + +/* DDR Regions Info */ +#define NUM_DRAM_REGIONS 3 +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */ + +#define NXP_DRAM1_ADDR 0x880000000 +#define NXP_DRAM1_MAX_SIZE 0x780000000 /* 30 GB */ + +#define NXP_DRAM2_ADDR 0x8800000000 +#define NXP_DRAM2_MAX_SIZE 0x7800000000 /* 480 GB */ +/* DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +/* + * P23: 23 x 23 package + * A: without security + * AE: with security + * SVR Definition (not include major and minor rev) + */ +#define SVR_LS1023A 0x879209 +#define SVR_LS1023AE 0x879208 +#define SVR_LS1023A_P23 0x87920B +#define SVR_LS1023AE_P23 0x87920A +#define SVR_LS1043A 0x879201 +#define SVR_LS1043AE 0x879200 +#define SVR_LS1043A_P23 0x879203 +#define SVR_LS1043AE_P23 0x879202 + +/* Number of cores in platform */ +#define PLATFORM_CORE_COUNT 4 +#define NUMBER_OF_CLUSTERS 1 +#define CORES_PER_CLUSTER 4 + +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 + +/* + * Required LS standard platform porting definitions + * for CCI-400 + */ +#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4 + +/* ls1043 version info for GIC configuration */ +#define REV1_0 0x10 +#define REV1_1 0x11 +#define GIC_ADDR_BIT 31 + +/* Errata */ +#define NXP_ERRATUM_A009663 +#define NXP_ERRATUM_A009942 + +#define NUM_OF_DDRC 1 + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40) + +/* Clock Divisors */ +#define NXP_PLATFORM_CLK_DIVIDER 1 +#define NXP_UART_CLK_DIVIDER 1 + +/* + * Set this switch to 1 if you need to keep the debug block + * clocked during system power-down. + */ +#define DEBUG_ACTIVE 0 + +#define IPPDEXPCR_MAC1_1 0x80000000 // DEVDISR2_FMAN1_MAC1 +#define IPPDEXPCR_MAC1_2 0x40000000 // DEVDISR2_FMAN1_MAC2 +#define IPPDEXPCR_MAC1_3 0x20000000 // DEVDISR2_FMAN1_MAC3 +#define IPPDEXPCR_MAC1_4 0x10000000 // DEVDISR2_FMAN1_MAC4 +#define IPPDEXPCR_MAC1_5 0x08000000 // DEVDISR2_FMAN1_MAC5 +#define IPPDEXPCR_MAC1_6 0x04000000 // DEVDISR2_FMAN1_MAC6 +#define IPPDEXPCR_MAC1_9 0x00800000 // DEVDISR2_FMAN1_MAC9 +#define IPPDEXPCR_I2C1 0x00080000 // DEVDISR5_I2C_1 +#define IPPDEXPCR_LPUART1 0x00040000 // DEVDISR5_LPUART1 +#define IPPDEXPCR_FLX_TMR1 0x00020000 // DEVDISR5_FLX_TMR +#define IPPDEXPCR_OCRAM1 0x00010000 // DEVDISR5_OCRAM1 +#define IPPDEXPCR_GPIO1 0x00000040 // DEVDISR5_GPIO +#define IPPDEXPCR_FM1 0x00000008 // DEVDISR2_FMAN1 + +#define IPPDEXPCR_MASK1 0xFC800008 // overrides for DEVDISR2 +#define IPPDEXPCR_MASK2 0x000F0040 // overriddes for DEVDISR5 + +#define IPSTPCR0_VALUE 0xA000C201 +#define IPSTPCR1_VALUE 0x00000080 +#define IPSTPCR2_VALUE 0x000C0000 +#define IPSTPCR3_VALUE 0x38000000 +#if (DEBUG_ACTIVE) + #define IPSTPCR4_VALUE 0x10833BFC +#else + #define IPSTPCR4_VALUE 0x10A33BFC +#endif + +#define DEVDISR1_QE 0x00000001 +#define DEVDISR1_SEC 0x00000200 +#define DEVDISR1_USB1 0x00004000 +#define DEVDISR1_SATA 0x00008000 +#define DEVDISR1_USB2 0x00010000 +#define DEVDISR1_USB3 0x00020000 +#define DEVDISR1_DMA2 0x00400000 +#define DEVDISR1_DMA1 0x00800000 +#define DEVDISR1_ESDHC 0x20000000 +#define DEVDISR1_PBL 0x80000000 + +#define DEVDISR2_FMAN1 0x00000080 +#define DEVDISR2_FMAN1_MAC9 0x00800000 +#define DEVDISR2_FMAN1_MAC6 0x04000000 +#define DEVDISR2_FMAN1_MAC5 0x08000000 +#define DEVDISR2_FMAN1_MAC4 0x10000000 +#define DEVDISR2_FMAN1_MAC3 0x20000000 +#define DEVDISR2_FMAN1_MAC2 0x40000000 +#define DEVDISR2_FMAN1_MAC1 0x80000000 + +#define DEVDISR3_BMAN 0x00040000 +#define DEVDISR3_QMAN 0x00080000 +#define DEVDISR3_PEX3 0x20000000 +#define DEVDISR3_PEX2 0x40000000 +#define DEVDISR3_PEX1 0x80000000 + +#define DEVDISR4_QSPI 0x08000000 +#define DEVDISR4_DUART2 0x10000000 +#define DEVDISR4_DUART1 0x20000000 + +#define DEVDISR5_ICMMU 0x00000001 +#define DEVDISR5_I2C_1 0x00000002 +#define DEVDISR5_I2C_2 0x00000004 +#define DEVDISR5_I2C_3 0x00000008 +#define DEVDISR5_I2C_4 0x00000010 +#define DEVDISR5_WDG_5 0x00000020 +#define DEVDISR5_WDG_4 0x00000040 +#define DEVDISR5_WDG_3 0x00000080 +#define DEVDISR5_DSPI1 0x00000100 +#define DEVDISR5_WDG_2 0x00000200 +#define DEVDISR5_FLX_TMR 0x00000400 +#define DEVDISR5_WDG_1 0x00000800 +#define DEVDISR5_LPUART6 0x00001000 +#define DEVDISR5_LPUART5 0x00002000 +#define DEVDISR5_LPUART3 0x00008000 +#define DEVDISR5_LPUART2 0x00010000 +#define DEVDISR5_LPUART1 0x00020000 +#define DEVDISR5_DBG 0x00200000 +#define DEVDISR5_GPIO 0x00400000 +#define DEVDISR5_IFC 0x00800000 +#define DEVDISR5_OCRAM2 0x01000000 +#define DEVDISR5_OCRAM1 0x02000000 +#define DEVDISR5_LPUART4 0x10000000 +#define DEVDISR5_DDR 0x80000000 +#define DEVDISR5_MEM 0x80000000 + +#define DEVDISR1_VALUE 0xA0C3C201 +#define DEVDISR2_VALUE 0xCC0C0080 +#define DEVDISR3_VALUE 0xE00C0000 +#define DEVDISR4_VALUE 0x38000000 +#if (DEBUG_ACTIVE) + #define DEVDISR5_VALUE 0x10833BFC +#else + #define DEVDISR5_VALUE 0x10A33BFC +#endif + +/* + * PWR mgmt features supported in the soc-specific code: + * value == 0x0 the soc code does not support this feature + * value != 0x0 the soc code supports this feature + */ +#define SOC_CORE_RELEASE 0x1 +#define SOC_CORE_RESTART 0x1 +#define SOC_CORE_OFF 0x1 +#define SOC_CORE_STANDBY 0x1 +#define SOC_CORE_PWR_DWN 0x1 +#define SOC_CLUSTER_STANDBY 0x1 +#define SOC_CLUSTER_PWR_DWN 0x1 +#define SOC_SYSTEM_STANDBY 0x1 +#define SOC_SYSTEM_PWR_DWN 0x1 +#define SOC_SYSTEM_OFF 0x1 +#define SOC_SYSTEM_RESET 0x1 + +/* PSCI-specific defines */ +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL + +/* Local power state for power domains in Run state */ +#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) +#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE + +/* + * 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. + * CACHE_WRITEBACK_GRANULE is defined in soc.def + */ + +/* One cache line needed for bakery locks on ARM platforms */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + NXP_CCI_CLUSTER0_SL_IFACE_IX, +}; +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); + +#endif + +#endif /* SOC_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c new file mode 100644 index 0000000..2231c18 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c @@ -0,0 +1,159 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x7F), + .sdram_cfg[0] = U(0xC50C0000), + .sdram_cfg[1] = U(0x401100), + .timing_cfg[0] = U(0x91550018), + .timing_cfg[1] = U(0xBBB48C42), + .timing_cfg[2] = U(0x48C111), + .timing_cfg[3] = U(0x10C1000), + .timing_cfg[4] = U(0x2), + .timing_cfg[5] = U(0x3401400), + .timing_cfg[7] = U(0x13300000), + .timing_cfg[8] = U(0x2115600), + .sdram_mode[0] = U(0x3010210), + .sdram_mode[9] = U(0x4000000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10210), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x4000000), + .sdram_mode[4] = U(0x10210), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x4000000), + .sdram_mode[6] = U(0x10210), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x4000000), + .interval = U(0x18600618), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x3000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xA181), + .wrlvl_cntl[0] = U(0x8675F607), + .wrlvl_cntl[1] = U(0x7090807, + .wrlvl_cntl[2] = U(0x7070707), + .debug[28] = U(0x00700046), +}; + +uint64_t board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + + return ULL(0x80000000); +} + +#else +static const struct rc_timing rcz[] = { + {1600, 12, 7}, + {} +}; + +static const struct board_timing ram[] = { + {0x1f, rcz, 0x00020100, 0}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + ret = cal_board_params(priv, ram, ARRAY_SIZE(ram)); + if (ret) + return ret; + + popts->cpo_sample = U(0x46); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */ + + return 0; +} + +/* DDR model number: MT40A512M8HX-093E */ +struct dimm_params ddr_raw_timing = { + .n_ranks = U(1), + .rank_density = ULL(2147483648), + .capacity = ULL(2147483648), + .primary_sdram_width = U(32), + .n_row_addr = U(15), + .n_col_addr = U(10), + .bank_group_bits = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 938, + .tckmax_ps = 1500, + .caslat_x = U(0x000DFA00), + .taa_ps = 13500, + .trcd_ps = 13500, + .trp_ps = 13500, + .tras_ps = 33000, + .trc_ps = 46500, + .twr_ps = 15000, + .trfc1_ps = 260000, + .trfc2_ps = 160000, + .trfc4_ps = 110000, + .tfaw_ps = 21000, + .trrds_ps = 3700, + .trrdl_ps = 5300, + .tccdl_ps = 5355, + .refresh_rate_ps = U(7800000), + .rc = U(0x1f), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, + struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + return 1; +} +#endif + +int64_t init_ddr(void) +{ + struct ddr_info info; + struct sysinfo sys; + int64_t dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h new file mode 100644 index 0000000..249f457 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include + +#include "policy.h" +#include + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x00100000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 3 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif /* PLAT_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c new file mode 100644 index 0000000..65d508c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk new file mode 100644 index 0000000..5d23356 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk @@ -0,0 +1,40 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= nor +BOARD := ls1043ardb +POVDD_ENABLE := no + +# DDR Compilation Configs +CONFIG_DDR_NODIMM := 1 +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 0 +DDRC_NUM_CS := 4 +DDR_ECC_EN := no +CONFIG_STATIC_DDR := 0 + +# On-Board Flash Details +# 128MB IFC NOR Flash +NOR_FLASH_SZ := 0x8000000 + +# Platform specific features. +WARM_BOOT := no + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := nor \ + sd \ + nand + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1043a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h new file mode 100644 index 0000000..4721a32 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h new file mode 100644 index 0000000..843b5e2 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* + * Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c new file mode 100644 index 0000000..7badf8c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c @@ -0,0 +1,435 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#endif +#include +#include +#include + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, + }; + + +/* Function to return the SoC SYS CLK */ +unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} + +/* + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + * + */ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + + counter_base_frequency = get_sys_clk()/4; + + return counter_base_frequency; +} + +#ifdef IMAGE_BL2 + +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1023A, LS1023A, 1, 2), + SOC_ENTRY(LS1023AE, LS1023AE, 1, 2), + SOC_ENTRY(LS1023A_P23, LS1023A_P23, 1, 2), + SOC_ENTRY(LS1023AE_P23, LS1023AE_P23, 1, 2), + SOC_ENTRY(LS1043A, LS1043A, 1, 4), + SOC_ENTRY(LS1043AE, LS1043AE, 1, 4), + SOC_ENTRY(LS1043A_P23, LS1043A_P23, 1, 4), + SOC_ENTRY(LS1043AE_P23, LS1043AE_P23, 1, 4), +}; + +#ifdef POLICY_FUSE_PROVISION +static gpio_init_info_t gpio_init_data = { + .gpio1_base_addr = NXP_GPIO1_ADDR, + .gpio2_base_addr = NXP_GPIO2_ADDR, + .gpio3_base_addr = NXP_GPIO3_ADDR, + .gpio4_base_addr = NXP_GPIO4_ADDR, +}; +#endif + +/* + * Function to set the base counter frequency at + * the first entry of the Frequency Mode Table, + * at CNTFID0 (0x20 offset). + * + * Set the value of the pirmary core register cntfrq_el0. + */ +static void set_base_freq_CNTFID0(void) +{ + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + * + */ + unsigned int counter_base_frequency = get_sys_clk()/4; + + /* + * Setting the frequency in the Frequency modes table. + * + * Note: The value for ls1046ardb board at this offset + * is not RW as stated. This offset have the + * fixed value of 100000400 Hz. + * + * The below code line has no effect. + * Keeping it for other platforms where it has effect. + */ + mmio_write_32(NXP_TIMER_ADDR + CNTFID_OFF, counter_base_frequency); + + write_cntfrq_el0(counter_base_frequency); +} + +void soc_preload_setup(void) +{ + +} + +/******************************************************************************* + * This function implements soc specific erratas + * This is called before DDR is initialized or MMU is enabled + ******************************************************************************/ +void soc_early_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); +#ifdef POLICY_FUSE_PROVISION + gpio_init(&gpio_init_data); + sec_init(NXP_CAAM_ADDR); +#endif +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + set_base_freq_CNTFID0(); + + /* Enable snooping on SEC read and write transactions */ + scfg_setbits32((void *)(NXP_SCFG_ADDR + SCFG_SNPCNFGCR_OFFSET), + SCFG_SNPCNFGCR_SECRDSNP | SCFG_SNPCNFGCR_SECWRSNP); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ + +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +#endif +#elif defined(POLICY_FUSE_PROVISION) + gpio_init(&gpio_init_data); + sfp_init(NXP_SFP_ADDR); + sec_init(NXP_CAAM_ADDR); +#endif + + soc_errata(); + + /* + * Initialize system level generic timer for Layerscape Socs. + */ + delay_timer_init(NXP_TIMER_ADDR); + +#ifdef DDR_INIT + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +#endif +} + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +/***************************************************************************** + * This function returns the boot device based on RCW_SRC + ****************************************************************************/ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src, val; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + val = rcw_src & RCW_SRC_NAND_MASK; + + if (val == RCW_SRC_NAND_VAL) { + val = rcw_src & NAND_RESERVED_MASK; + if ((val != NAND_RESERVED_1) && (val != NAND_RESERVED_2)) { + src = BOOT_DEVICE_IFC_NAND; + INFO("RCW BOOT SRC is IFC NAND\n"); + } + } else { + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_NOR_MASK; + if (val == NOR_8B_VAL || val == NOR_16B_VAL) { + src = BOOT_DEVICE_IFC_NOR; + INFO("RCW BOOT SRC is IFC NOR\n"); + } else { + switch (rcw_src) { + case QSPI_VAL1: + case QSPI_VAL2: + src = BOOT_DEVICE_QSPI; + INFO("RCW BOOT SRC is QSPI\n"); + break; + case SD_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + default: + src = BOOT_DEVICE_NONE; + } + } + } + + return src; +} + +/* This function sets up access permissions on memory regions */ +void soc_mem_access(void) +{ + struct tzc380_reg tzc380_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx, index = 0U; + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + + for (dram_idx = 0U; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[dram_idx].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc380_reg_list(tzc380_reg_list, + dram_idx, index, + info_dram_regions->region[dram_idx].addr, + info_dram_regions->region[dram_idx].size, + NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE); + } + + mem_access_setup(NXP_TZC_ADDR, index, tzc380_reg_list); + + /* Configure CSU secure access register to disable TZASC bypass mux */ + mmio_write_32((uintptr_t)(NXP_CSU_ADDR + + CSU_SEC_ACCESS_REG_OFFSET), + bswap32(TZASC_BYPASS_MUX_DISABLE)); +} + + +#else +const unsigned char _power_domain_tree_desc[] = {1, 1, 4}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1043_cluster_count); + +/* This function returns the SoC topology */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + + return _power_domain_tree_desc; +} + +/* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + */ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + return CORES_PER_CLUSTER; +} + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* Initialize system level generic timer for Socs */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +/* + * For LS1043a rev1.0, GIC base address align with 4k. + * For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT] + * is set, GIC base address align with 4K, or else align + * with 64k. + */ +void get_gic_offset(uint32_t *gicc_base, uint32_t *gicd_base) +{ + uint32_t *ccsr_svr = (uint32_t *)(NXP_DCFG_ADDR + DCFG_SVR_OFFSET); + uint32_t *gic_align = (uint32_t *)(NXP_SCFG_ADDR + + SCFG_GIC400_ADDR_ALIGN_OFFSET); + uint32_t val; + + val = be32toh(mmio_read_32((uintptr_t)ccsr_svr)); + + if ((val & 0xff) == REV1_1) { + val = be32toh(mmio_read_32((uintptr_t)gic_align)); + if (val & (1L << GIC_ADDR_BIT)) { + *gicc_base = NXP_GICC_4K_ADDR; + *gicd_base = NXP_GICD_4K_ADDR; + } else { + *gicc_base = NXP_GICC_64K_ADDR; + *gicd_base = NXP_GICD_64K_ADDR; + } + } else { + *gicc_base = NXP_GICC_4K_ADDR; + *gicd_base = NXP_GICD_4K_ADDR; + } +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uint32_t target_mask_array[PLATFORM_CORE_COUNT]; + /* + * On a GICv2 system, the Group 1 secure interrupts are treated + * as Group 0 interrupts. + */ + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_LS_G0_IRQ_PROPS(GICV2_INTR_GROUP0) + }; + static uint32_t gicc_base, gicd_base; + + get_gic_offset(&gicc_base, &gicd_base); + plat_ls_gic_driver_init(gicd_base, gicc_base, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* This function initializes the soc from the BL31 module */ +void soc_init(void) +{ + /* low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize the interconnect during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this but we can't + * assume so. No harm in executing this code twice. + */ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); + + /* Init CSU to enable non-secure access to peripherals */ + enable_layerscape_ns_access(ns_dev, ARRAY_SIZE(ns_dev), NXP_CSU_ADDR); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +} + +void soc_runtime_setup(void) +{ + +} +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def new file mode 100644 index 0000000..b174bd6 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def @@ -0,0 +1,107 @@ +# +# Copyright 2017-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a53 + +CACHE_LINE := 6 + +# set to GIC400 or GIC500 +GIC := GIC400 + +# set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 2 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC380 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := NS16550 + +# Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# ddr controller - set to MMDC or NXP +DDRCNTLR := NXP + +# ddr phy - set to NXP or SNPS +DDRPHY := NXP + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0x5900 + +# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def +# Input to CST create_hdr_esbc tool +CSF_HDR_SZ := 0x3000 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + +# OCRAM MAP +OCRAM_START_ADDR := 0x10000000 +OCRAM_SIZE := 0x20000 + +# BL2 binary is placed at start of OCRAM. +# Also used by create_pbl.mk. +BL2_BASE := 0x10000000 + +# After BL2 bin, OCRAM is used by ROM Code: +# (OCRAM_START_ADDR + BL2_BIN_SIZE) -> (NXP_ROM_RSVD - 1) + +# After ROM Code, OCRAM is used by CSF header. +# (OCRAM_START_ADDR + BL2_TEXT_LIMIT + NXP_ROM_RSVD) -> (CSF_HDR_SZ - 1) + +# BL2_HDR_LOC has to be (OCRAM_START_ADDR + OCRAM_SIZE - NXP_ROM_RSVD - CSF_HDR_SZ) +# This value should be greater than BL2_TEXT_LIMIT +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(OCRAM_SIZE) - $(NXP_ROM_RSVD) - $(CSF_HDR_SZ)))) +# Covert to HEX to be used by create_pbl.mk +BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc) + +# Core Errata +ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 + +# SoC ERRATAS to be enabled +ERRATA_SOC_A008850 := 1 +ERRATA_SOC_A010539 := 1 +ERRATA_SOC_A009660 := 1 + +# DDR Errata +ERRATA_DDR_A009663 := 1 +ERRATA_DDR_A009942 := 1 + +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# Define Endianness of each module +NXP_GUR_ENDIANNESS := BE +NXP_DDR_ENDIANNESS := BE +NXP_SEC_ENDIANNESS := BE +NXP_SFP_ENDIANNESS := BE +NXP_SNVS_ENDIANNESS := BE +NXP_ESDHC_ENDIANNESS := BE +NXP_QSPI_ENDIANNESS := BE +NXP_FSPI_ENDIANNESS := BE +NXP_SCFG_ENDIANNESS := BE +NXP_GPIO_ENDIANNESS := BE +NXP_IFC_ENDIANNESS := BE + +NXP_SFP_VER := 3_2 + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.mk new file mode 100644 index 0000000..b6ce14e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.mk @@ -0,0 +1,114 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1043a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH := plat/nxp/common +PLAT_DRIVERS_PATH := drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + +# get SoC-specific defnitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + +# For Security Features +DISABLE_FUSE_WRITE := 1 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + +# Selecting Drivers for SoC +$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,CSU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +# Selecting PSCI & SIP_SVC support +$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31)) + +# Source File Addition +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_SOC_PATH}/include\ + -I${PLAT_COMMON_PATH}/soc_errata + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq ($(WARM_BOOT),yes) +include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk +endif + +ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes) +include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +# for fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + +# Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\ + ${WARM_RST_INCLUDES} + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${WARM_RST_BL31_SOURCES}\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\ + ${NV_STORAGE_SOURCES}\ + ${WARM_RST_BL_COMM_SOURCES}\ + ${PLAT_SOC_PATH}/soc.c + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + +# Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S b/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S new file mode 100644 index 0000000..daa0542 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S @@ -0,0 +1,937 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define DAIF_DATA AUX_01_DATA +#define TIMER_CNTRL_DATA AUX_02_DATA + +.global soc_init_lowlevel +.global soc_init_percpu +.global _soc_core_release +.global _soc_core_restart +.global _soc_ck_disabled +.global _soc_sys_reset +.global _soc_sys_off +.global _soc_set_start_addr +.global _getGICC_BaseAddr +.global _getGICD_BaseAddr +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off +.global _soc_core_prep_stdby +.global _soc_core_entr_stdby +.global _soc_core_exit_stdby +.global _soc_core_prep_pwrdn +.global _soc_core_entr_pwrdn +.global _soc_core_exit_pwrdn +.global _soc_clstr_prep_stdby +.global _soc_clstr_exit_stdby +.global _soc_clstr_prep_pwrdn +.global _soc_clstr_exit_pwrdn +.global _soc_sys_prep_stdby +.global _soc_sys_exit_stdby +.global _soc_sys_prep_pwrdn +.global _soc_sys_pwrdn_wfi +.global _soc_sys_exit_pwrdn + + +/* This function initialize the soc + * in: void + * out: void + */ +func soc_init_lowlevel + ret +endfunc soc_init_lowlevel + + +/* void soc_init_percpu(void) + * this function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func soc_init_percpu + mov x3, x30 + + bl plat_my_core_mask + mov x2, x0 + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data /* 0-1 */ + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A72 /* 0 */ +1: + mov x30, x3 + ret +endfunc soc_init_percpu + +/* part of CPU_ON + * this function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +func _soc_core_release + +#if (TEST_BL31) + rbit w2, w0 + /* x2 = core mask msb */ +#else + mov x2, x0 +#endif + /* write COREBCR */ + mov x1, #NXP_SCFG_ADDR + rev w3, w2 + str w3, [x1, #SCFG_COREBCR_OFFSET] + isb + + /* read-modify-write BRR */ + mov x1, #NXP_DCFG_ADDR + ldr w2, [x1, #DCFG_BRR_OFFSET] + rev w3, w2 + orr w3, w3, w0 + rev w2, w3 + str w2, [x1, #DCFG_BRR_OFFSET] + isb + + /* send event */ + sev + isb + ret +endfunc _soc_core_release + + +/* part of CPU_ON + * this function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_restart + mov x5, x30 + mov x3, x0 + + /* + * unset ph20 request in RCPM_PCPH20CLEARR + * this is an lsb-0 register + */ + ldr x1, =NXP_RCPM_ADDR + rev w2, w3 + str w2, [x1, #RCPM_PCPH20CLRR_OFFSET] + dsb sy + isb + + bl _getGICD_BaseAddr + mov x4, x0 + + /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */ + ldr w1, [x4, #GICD_CTLR_OFFSET] + orr w1, w1, #GICD_CTLR_EN_GRP0 + str w1, [x4, #GICD_CTLR_OFFSET] + dsb sy + isb + + + /* + * fire SGI by writing to GICD_SGIR the following values: + * [25:24] = 0x0 (forward interrupt to the CPU interfaces + * specified in CPUTargetList field) + * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu) + * [15] = 0 (forward SGI only if it is configured as group 0 interrupt) + * [3:0] = 0xF (interrupt ID = 15) + */ + lsl w1, w3, #16 + orr w1, w1, #0xF + str w1, [x4, #GICD_SGIR_OFFSET] + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x5 + ret +endfunc _soc_core_restart + +/* + * This function determines if a core is disabled via COREDISR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1, x2 + */ +func _soc_ck_disabled + /* get base addr of dcfg block */ + mov x1, #NXP_DCFG_ADDR + + /* read COREDISR */ + ldr w1, [x1, #DCFG_COREDISR_OFFSET] + rev w2, w1 + + /* test core bit */ + and w0, w2, w0 + ret +endfunc _soc_ck_disabled + +/* + *This function resets the system via SoC-specific methods + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func _soc_sys_reset + ldr x2, =NXP_DCFG_ADDR + + /* make sure the mask is cleared in the reset request mask register */ + mov w1, wzr + str w1, [x2, #DCFG_RSTRQMR1_OFFSET] + + /* set the reset request */ + ldr w1, =RSTCR_RESET_REQ + ldr x3, =DCFG_RSTCR_OFFSET + rev w0, w1 + str w0, [x2, x3] + + /* + * just in case this address range is mapped as cacheable, + * flush the write out of the dcaches + */ + add x3, x2, x3 + dc cvac, x3 + dsb st + isb + + /* Note: this function does not return */ +1: + wfi + b 1b +endfunc _soc_sys_reset + +/* + * Part of SYSTEM_OFF + * this function turns off the SoC clocks + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 + */ +func _soc_sys_off + + /* mask interrupts at the core */ + mrs x1, DAIF + mov x0, #DAIF_SET_MASK + orr x0, x1, x0 + msr DAIF, x0 + + /* disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* disable dcache for EL3 */ + mrs x1, SCTLR_EL3 + bic x1, x1, #SCTLR_C_MASK + /* make sure icache is enabled */ + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL3, x1 + isb + + /* Enable dynamic retention ctrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */ + mrs x0, CORTEX_A72_ECTLR_EL1 + orr x0, x0, #CPUECTLR_TIMER_8TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x0 + + /* set WFIL2EN in SCFG_CLUSTERPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg + + /* request LPM20 */ + mov x0, #RCPM_POWMGTCSR_OFFSET + bl read_reg_rcpm + orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ + mov x0, #RCPM_POWMGTCSR_OFFSET + bl write_reg_rcpm + + dsb sy + isb +1: + wfi + b 1b +endfunc _soc_sys_off + +/* + * Write a register in the RCPM block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +func write_reg_rcpm + ldr x2, =NXP_RCPM_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret +endfunc write_reg_rcpm + +/* + * Read a register in the RCPM block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +func read_reg_rcpm + ldr x2, =NXP_RCPM_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret +endfunc read_reg_rcpm + +/* + * Write a register in the SCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +func write_reg_scfg + mov x2, #NXP_SCFG_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret +endfunc write_reg_scfg + +/* + * Read a register in the SCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +func read_reg_scfg + mov x2, #NXP_SCFG_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret +endfunc read_reg_scfg + +/* + * Part of CPU_OFF + * this function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7 + */ +func _soc_core_prep_off + mov x7, x30 + mov x6, x0 + + /* Set retention control in CPUECTLR make sure smpen bit is set */ + mrs x4, CORTEX_A72_ECTLR_EL1 + bic x4, x4, #CPUECTLR_RET_MASK + orr x4, x4, #CPUECTLR_TIMER_8TICKS + orr x4, x4, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x4 + + /* save timer control current value */ + mov x5, #NXP_TIMER_ADDR + ldr w4, [x5, #SYS_COUNTER_CNTCR_OFFSET] + mov w2, w4 + mov x0, x6 + mov x1, #TIMER_CNTRL_DATA + bl _setCoreData + + /* enable the timer */ + orr w4, w4, #CNTCR_EN_MASK + str w4, [x5, #SYS_COUNTER_CNTCR_OFFSET] + + bl _getGICC_BaseAddr + mov x5, x0 + + /* disable signaling of ints */ + ldr w3, [x5, #GICC_CTLR_OFFSET] + bic w3, w3, #GICC_CTLR_EN_GRP0 + bic w3, w3, #GICC_CTLR_EN_GRP1 + str w3, [x5, #GICC_CTLR_OFFSET] + dsb sy + isb + + + /* + * set retention control in SCFG_RETREQCR + * Note: this register is msb 0 + */ + ldr x4, =SCFG_RETREQCR_OFFSET + mov x0, x4 + bl read_reg_scfg + rbit w1, w6 + orr w1, w0, w1 + mov x0, x4 + bl write_reg_scfg + + /* set the priority filter */ + ldr w2, [x5, #GICC_PMR_OFFSET] + orr w2, w2, #GICC_PMR_FILTER + str w2, [x5, #GICC_PMR_OFFSET] + + /* setup GICC_CTLR */ + bic w3, w3, #GICC_CTLR_ACKCTL_MASK + orr w3, w3, #GICC_CTLR_FIQ_EN_MASK + orr w3, w3, #GICC_CTLR_EOImodeS_MASK + orr w3, w3, #GICC_CTLR_CBPR_MASK + str w3, [x5, #GICC_CTLR_OFFSET] + + /* setup the banked-per-core GICD registers */ + bl _getGICD_BaseAddr + mov x5, x0 + + /* define SGI15 as Grp0 */ + ldr w2, [x5, #GICD_IGROUPR0_OFFSET] + bic w2, w2, #GICD_IGROUP0_SGI15 + str w2, [x5, #GICD_IGROUPR0_OFFSET] + + /* set priority of SGI 15 to highest... */ + ldr w2, [x5, #GICD_IPRIORITYR3_OFFSET] + bic w2, w2, #GICD_IPRIORITY_SGI15_MASK + str w2, [x5, #GICD_IPRIORITYR3_OFFSET] + + /* enable SGI 15 */ + ldr w2, [x5, #GICD_ISENABLER0_OFFSET] + orr w2, w2, #GICD_ISENABLE0_SGI15 + str w2, [x5, #GICD_ISENABLER0_OFFSET] + + /* enable the cpu interface */ + bl _getGICC_BaseAddr + mov x2, x0 + orr w3, w3, #GICC_CTLR_EN_GRP0 + str w3, [x2, #GICC_CTLR_OFFSET] + + + /* clear any pending SGIs */ + ldr x2, =GICD_CPENDSGIR_CLR_MASK + add x0, x5, #GICD_CPENDSGIR3_OFFSET + str w2, [x0] + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR + * this is an lsb-0 register + */ + mov x1, x6 + mov x0, #RCPM_PCPH20SETR_OFFSET + bl write_reg_rcpm + + dsb sy + isb + mov x30, x7 + ret +endfunc _soc_core_prep_off + +/* + * Part of CPU_OFF + * this function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_entr_off + mov x5, x30 + mov x4, x0 + + bl _getGICD_BaseAddr + mov x3, x0 + +3: + /* enter low-power state by executing wfi */ + wfi + + /* see if we got hit by SGI 15 */ + add x0, x3, #GICD_SPENDSGIR3_OFFSET + ldr w2, [x0] + and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK + cbz w2, 4f + + /* clear the pending SGI */ + ldr x2, =GICD_CPENDSGIR_CLR_MASK + add x0, x3, #GICD_CPENDSGIR3_OFFSET + str w2, [x0] +4: + /* check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + cmp x0, #CORE_WAKEUP + b.ne 3b + + /* if we get here, then we have exited the wfi */ + dsb sy + isb + mov x30, x5 + ret +endfunc _soc_core_entr_off + +/* + * Part of CPU_OFF + * this function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6 + */ +func _soc_core_exit_off + mov x6, x30 + mov x5, x0 + + /* + * Clear ph20 request in RCPM_PCPH20CLRR - no need + * to do that here, it has been done in _soc_core_restart + */ + bl _getGICC_BaseAddr + mov x1, x0 + + /* read GICC_IAR */ + ldr w0, [x1, #GICC_IAR_OFFSET] + + /* write GICC_EIOR - signal end-of-interrupt */ + str w0, [x1, #GICC_EOIR_OFFSET] + + /* write GICC_DIR - disable interrupt */ + str w0, [x1, #GICC_DIR_OFFSET] + + /* disable signaling of grp0 ints */ + ldr w3, [x1, #GICC_CTLR_OFFSET] + bic w3, w3, #GICC_CTLR_EN_GRP0 + str w3, [x1, #GICC_CTLR_OFFSET] + + /* + * Unset retention request in SCFG_RETREQCR + * Note: this register is msb-0 + */ + ldr x4, =SCFG_RETREQCR_OFFSET + mov x0, x4 + bl read_reg_scfg + rbit w1, w5 + bic w1, w0, w1 + mov x0, x4 + bl write_reg_scfg + + /* restore timer ctrl */ + mov x0, x5 + mov x1, #TIMER_CNTRL_DATA + bl _getCoreData + /* w0 = timer ctrl saved value */ + mov x2, #NXP_TIMER_ADDR + str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] + + dsb sy + isb + mov x30, x6 + ret +endfunc _soc_core_exit_off + +/* + * Function loads a 64-bit execution address of the core in the soc registers + * BOOTLOCPTRL/H + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * uses x0, x1, x2, x3 + */ +func _soc_set_start_addr + /* get the 64-bit base address of the scfg block */ + ldr x2, =NXP_SCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register */ + mov x1, x0 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register */ + lsr x1, x0, #32 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET] + ret +endfunc _soc_set_start_addr + +/* + * This function returns the base address of the gic distributor + * in: none + * out: x0 = base address of gic distributor + * uses x0 + */ +func _getGICD_BaseAddr +#if (TEST_BL31) + /* defect in simulator - gic base addresses are on 4Kb boundary */ + ldr x0, =NXP_GICD_4K_ADDR +#else + ldr x0, =NXP_GICD_64K_ADDR +#endif + ret +endfunc _getGICD_BaseAddr + +/* + * This function returns the base address of the gic controller + * in: none + * out: x0 = base address of gic controller + * uses x0 + */ +func _getGICC_BaseAddr +#if (TEST_BL31) + /* defect in simulator - gic base addresses are on 4Kb boundary */ + ldr x0, =NXP_GICC_4K_ADDR +#else + ldr x0, =NXP_GICC_64K_ADDR +#endif + ret +endfunc _getGICC_BaseAddr + +/* + * Part of CPU_SUSPEND + * this function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +func _soc_core_entr_stdby + dsb sy + isb + wfi + + ret +endfunc _soc_core_entr_stdby + + +/* + * Part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_core_prep_stdby + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + ret +endfunc _soc_core_prep_stdby + +/* + * Part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_core_exit_stdby + ret +endfunc _soc_core_exit_stdby + +/* + * Part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_prep_pwrdn + mov x5, x30 + mov x4, x0 + + /* enable CPU retention + set smp */ + mrs x1, CORTEX_A72_ECTLR_EL1 + orr x1, x1, #0x1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + /* + * set the retention request in SCFG_RETREQCR + * this is an msb-0 register + */ + ldr x3, =SCFG_RETREQCR_OFFSET + mov x0, x3 + bl read_reg_scfg + rbit w1, w4 + orr w1, w0, w1 + mov x0, x3 + bl write_reg_scfg + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR + * this is an lsb-0 register + */ + mov x1, x4 + mov x0, #RCPM_PCPH20SETR_OFFSET + bl write_reg_rcpm + + mov x30, x5 + ret +endfunc _soc_core_prep_pwrdn + +/* + * Part of CPU_SUSPEND + * this function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +func _soc_core_entr_pwrdn + dsb sy + isb + wfi + + ret +endfunc _soc_core_entr_pwrdn + +/* + * Part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_exit_pwrdn + mov x5, x30 + mov x4, x0 + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR + * this is an lsb-0 register + */ + mov x1, x4 + mov x0, #RCPM_PCPH20CLRR_OFFSET + bl write_reg_rcpm + + /* + * Unset the retention request in SCFG_RETREQCR + * this is an msb-0 register + */ + ldr x3, =SCFG_RETREQCR_OFFSET + mov x0, x3 + bl read_reg_scfg + rbit w1, w4 + bic w1, w0, w1 + mov x0, x3 + bl write_reg_scfg + + mov x30, x5 + ret +endfunc _soc_core_exit_pwrdn + +/* + * Part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_clstr_prep_stdby + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + ret +endfunc _soc_clstr_prep_stdby + +/* + * Part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_clstr_exit_stdby + ret +endfunc _soc_clstr_exit_stdby + +/* + * Part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_clstr_prep_pwrdn + mov x5, x30 + mov x4, x0 + + /* enable CPU retention + set smp */ + mrs x1, CORTEX_A72_ECTLR_EL1 + orr x1, x1, #0x1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + /* + * Set the retention request in SCFG_RETREQCR + * this is an msb-0 register. + */ + ldr x3, =SCFG_RETREQCR_OFFSET + mov x0, x3 + bl read_reg_scfg + rbit w1, w4 + orr w1, w0, w1 + mov x0, x3 + bl write_reg_scfg + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR + * this is an lsb-0 register. + */ + mov x1, x4 + mov x0, #RCPM_PCPH20SETR_OFFSET + bl write_reg_rcpm + + mov x30, x5 + ret +endfunc _soc_clstr_prep_pwrdn + +/* + * Part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_clstr_exit_pwrdn + mov x5, x30 + mov x4, x0 + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR + * this is an lsb-0 register. + */ + mov x1, x4 + mov x0, #RCPM_PCPH20CLRR_OFFSET + bl write_reg_rcpm + + /* + * Unset the retention request in SCFG_RETREQCR + * this is an msb-0 register. + */ + ldr x3, =SCFG_RETREQCR_OFFSET + mov x0, x3 + bl read_reg_scfg + rbit w1, w4 + bic w1, w0, w1 + mov x0, x3 + bl write_reg_scfg + + mov x30, x5 + ret +endfunc _soc_clstr_exit_pwrdn + +/* + * Part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_sys_prep_stdby + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + ret +endfunc _soc_sys_prep_stdby + +/* Part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_sys_exit_stdby + ret +endfunc _soc_sys_exit_stdby + +/* + * Part of CPU_SUSPEND + * this function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4 + */ +func _soc_sys_prep_pwrdn + mov x4, x30 + + /* Enable dynamic retention contrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */ + mrs x0, CORTEX_A72_ECTLR_EL1 + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_8TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x0 + + /* Set WFIL2EN in SCFG_CLUSTERPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg + + isb + mov x30, x4 + ret +endfunc _soc_sys_prep_pwrdn + +/* + * Part of CPU_SUSPEND + * this function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0, x1, x2, x3, x4 + */ +func _soc_sys_pwrdn_wfi + mov x4, x30 + + /* request LPM20 */ + mov x0, #RCPM_POWMGTCSR_OFFSET + bl read_reg_rcpm + orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ + mov x0, #RCPM_POWMGTCSR_OFFSET + bl write_reg_rcpm + + dsb sy + isb + wfi + + mov x30, x4 + ret +endfunc _soc_sys_pwrdn_wfi + +/* + * Part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_sys_exit_pwrdn + /* clear WFIL2_EN in SCFG_COREPMCR */ + mov x1, #NXP_SCFG_ADDR + str wzr, [x1, #SCFG_COREPMCR_OFFSET] + + ret +endfunc _soc_sys_exit_pwrdn diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S new file mode 100644 index 0000000..d2a48ea --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S @@ -0,0 +1,92 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl plat_reset_handler + .globl platform_mem_init + +func platform_mem1_init + ret +endfunc platform_mem1_init + +func platform_mem_init + ret +endfunc platform_mem_init + +func l2_mem_init + /* Initialize the L2 RAM latency */ + mrs x1, S3_1_c11_c0_2 + mov x0, #0x1C7 + /* Clear L2 Tag RAM latency and L2 Data RAM latency */ + bic x1, x1, x0 + /* Set L2 data ram latency bits [2:0] */ + orr x1, x1, #0x2 + /* set L2 tag ram latency bits [8:6] */ + orr x1, x1, #0x80 + msr S3_1_c11_c0_2, x1 + isb + ret +endfunc l2_mem_init + +func apply_platform_errata + ret +endfunc apply_platform_errata + +func plat_reset_handler + mov x29, x30 +#if (defined(IMAGE_BL2) && BL2_AT_EL3) + bl l2_mem_init +#endif + bl apply_platform_errata + +#if defined(IMAGE_BL31) + ldr x0, =POLICY_SMMU_PAGESZ_64K + cbz x0, 1f + /* Set the SMMU page size in the SACR register */ + bl _set_smmu_pagesz_64 +#endif +1: + /* + * May be cntfrq_el0 needs to be assigned + * the value COUNTER_FREQUENCY + */ + mov x30, x29 + ret +endfunc plat_reset_handler + +/* + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + */ +func plat_secondary_cold_boot_setup + /* ls1046a does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +/* + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary cpu. + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, 0x0 + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h new file mode 100644 index 0000000..25c1964 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h @@ -0,0 +1,174 @@ +/* + * Copyright 2017-2018, 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NS_ACCESS_H +#define NS_ACCESS_H + +#include + +enum csu_cslx_ind { + CSU_CSLX_PCIE2_IO = 0, + CSU_CSLX_PCIE1_IO, + CSU_CSLX_MG2TPR_IP, + CSU_CSLX_IFC_MEM, + CSU_CSLX_OCRAM, + CSU_CSLX_GIC, + CSU_CSLX_PCIE1, + CSU_CSLX_OCRAM2, + CSU_CSLX_QSPI_MEM, + CSU_CSLX_PCIE2, + CSU_CSLX_SATA, + CSU_CSLX_USB1, + CSU_CSLX_QM_BM_SWPORTAL, + CSU_CSLX_PCIE3 = 16, + CSU_CSLX_PCIE3_IO, + CSU_CSLX_USB3 = 20, + CSU_CSLX_USB2, + CSU_CSLX_PFE = 23, + CSU_CSLX_SERDES = 32, + CSU_CSLX_QDMA, + CSU_CSLX_LPUART2, + CSU_CSLX_LPUART1, + CSU_CSLX_LPUART4, + CSU_CSLX_LPUART3, + CSU_CSLX_LPUART6, + CSU_CSLX_LPUART5, + CSU_CSLX_DSPI1 = 41, + CSU_CSLX_QSPI, + CSU_CSLX_ESDHC, + CSU_CSLX_IFC = 45, + CSU_CSLX_I2C1, + CSU_CSLX_USB_2, + CSU_CSLX_I2C3 = 48, + CSU_CSLX_I2C2, + CSU_CSLX_DUART2 = 50, + CSU_CSLX_DUART1, + CSU_CSLX_WDT2, + CSU_CSLX_WDT1, + CSU_CSLX_EDMA, + CSU_CSLX_SYS_CNT, + CSU_CSLX_DMA_MUX2, + CSU_CSLX_DMA_MUX1, + CSU_CSLX_DDR, + CSU_CSLX_QUICC, + CSU_CSLX_DCFG_CCU_RCPM = 60, + CSU_CSLX_SECURE_BOOTROM, + CSU_CSLX_SFP, + CSU_CSLX_TMU, + CSU_CSLX_SECURE_MONITOR, + CSU_CSLX_SCFG, + CSU_CSLX_FM = 66, + CSU_CSLX_SEC5_5, + CSU_CSLX_BM, + CSU_CSLX_QM, + CSU_CSLX_GPIO2 = 70, + CSU_CSLX_GPIO1, + CSU_CSLX_GPIO4, + CSU_CSLX_GPIO3, + CSU_CSLX_PLATFORM_CONT, + CSU_CSLX_CSU, + CSU_CSLX_IIC4 = 77, + CSU_CSLX_WDT4, + CSU_CSLX_WDT3, + CSU_CSLX_ESDHC2 = 80, + CSU_CSLX_WDT5 = 81, + CSU_CSLX_SAI2, + CSU_CSLX_SAI1, + CSU_CSLX_SAI4, + CSU_CSLX_SAI3, + CSU_CSLX_FTM2 = 86, + CSU_CSLX_FTM1, + CSU_CSLX_FTM4, + CSU_CSLX_FTM3, + CSU_CSLX_FTM6 = 90, + CSU_CSLX_FTM5, + CSU_CSLX_FTM8, + CSU_CSLX_FTM7, + CSU_CSLX_DSCR = 121, +}; + +struct csu_ns_dev_st ns_dev[] = { + {CSU_CSLX_PCIE2_IO, CSU_ALL_RW}, + {CSU_CSLX_PCIE1_IO, CSU_ALL_RW}, + {CSU_CSLX_MG2TPR_IP, CSU_ALL_RW}, + {CSU_CSLX_IFC_MEM, CSU_ALL_RW}, + {CSU_CSLX_OCRAM, CSU_S_SUP_RW}, + {CSU_CSLX_GIC, CSU_ALL_RW}, + {CSU_CSLX_PCIE1, CSU_ALL_RW}, + {CSU_CSLX_OCRAM2, CSU_S_SUP_RW}, + {CSU_CSLX_QSPI_MEM, CSU_ALL_RW}, + {CSU_CSLX_PCIE2, CSU_ALL_RW}, + {CSU_CSLX_SATA, CSU_ALL_RW}, + {CSU_CSLX_USB1, CSU_ALL_RW}, + {CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW}, + {CSU_CSLX_PCIE3, CSU_ALL_RW}, + {CSU_CSLX_PCIE3_IO, CSU_ALL_RW}, + {CSU_CSLX_USB3, CSU_ALL_RW}, + {CSU_CSLX_USB2, CSU_ALL_RW}, + {CSU_CSLX_PFE, CSU_ALL_RW}, + {CSU_CSLX_SERDES, CSU_ALL_RW}, + {CSU_CSLX_QDMA, CSU_ALL_RW}, + {CSU_CSLX_LPUART2, CSU_ALL_RW}, + {CSU_CSLX_LPUART1, CSU_ALL_RW}, + {CSU_CSLX_LPUART4, CSU_ALL_RW}, + {CSU_CSLX_LPUART3, CSU_ALL_RW}, + {CSU_CSLX_LPUART6, CSU_ALL_RW}, + {CSU_CSLX_LPUART5, CSU_ALL_RW}, + {CSU_CSLX_DSPI1, CSU_ALL_RW}, + {CSU_CSLX_QSPI, CSU_ALL_RW}, + {CSU_CSLX_ESDHC, CSU_ALL_RW}, + {CSU_CSLX_IFC, CSU_ALL_RW}, + {CSU_CSLX_I2C1, CSU_ALL_RW}, + {CSU_CSLX_USB_2, CSU_ALL_RW}, + {CSU_CSLX_I2C3, CSU_ALL_RW}, + {CSU_CSLX_I2C2, CSU_ALL_RW}, + {CSU_CSLX_DUART2, CSU_ALL_RW}, + {CSU_CSLX_DUART1, CSU_ALL_RW}, + {CSU_CSLX_WDT2, CSU_ALL_RW}, + {CSU_CSLX_WDT1, CSU_ALL_RW}, + {CSU_CSLX_EDMA, CSU_ALL_RW}, + {CSU_CSLX_SYS_CNT, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX2, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX1, CSU_ALL_RW}, + {CSU_CSLX_DDR, CSU_ALL_RW}, + {CSU_CSLX_QUICC, CSU_ALL_RW}, + {CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW}, + {CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW}, + {CSU_CSLX_SFP, CSU_ALL_RW}, + {CSU_CSLX_TMU, CSU_ALL_RW}, + {CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW}, + {CSU_CSLX_SCFG, CSU_ALL_RW}, + {CSU_CSLX_FM, CSU_ALL_RW}, + {CSU_CSLX_SEC5_5, CSU_ALL_RW}, + {CSU_CSLX_BM, CSU_ALL_RW}, + {CSU_CSLX_QM, CSU_ALL_RW}, + {CSU_CSLX_GPIO2, CSU_ALL_RW}, + {CSU_CSLX_GPIO1, CSU_ALL_RW}, + {CSU_CSLX_GPIO4, CSU_ALL_RW}, + {CSU_CSLX_GPIO3, CSU_ALL_RW}, + {CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW}, + {CSU_CSLX_CSU, CSU_ALL_RW}, + {CSU_CSLX_IIC4, CSU_ALL_RW}, + {CSU_CSLX_WDT4, CSU_ALL_RW}, + {CSU_CSLX_WDT3, CSU_ALL_RW}, + {CSU_CSLX_ESDHC2, CSU_ALL_RW}, + {CSU_CSLX_WDT5, CSU_ALL_RW}, + {CSU_CSLX_SAI2, CSU_ALL_RW}, + {CSU_CSLX_SAI1, CSU_ALL_RW}, + {CSU_CSLX_SAI4, CSU_ALL_RW}, + {CSU_CSLX_SAI3, CSU_ALL_RW}, + {CSU_CSLX_FTM2, CSU_ALL_RW}, + {CSU_CSLX_FTM1, CSU_ALL_RW}, + {CSU_CSLX_FTM4, CSU_ALL_RW}, + {CSU_CSLX_FTM3, CSU_ALL_RW}, + {CSU_CSLX_FTM6, CSU_ALL_RW}, + {CSU_CSLX_FTM5, CSU_ALL_RW}, + {CSU_CSLX_FTM8, CSU_ALL_RW}, + {CSU_CSLX_FTM7, CSU_ALL_RW}, + {CSU_CSLX_DSCR, CSU_ALL_RW}, +}; + +#endif /* NS_ACCESS_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h new file mode 100644 index 0000000..67810c3 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h @@ -0,0 +1,125 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_H +#define SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include + +#include +#include + +/* DDR Regions Info */ +#define NUM_DRAM_REGIONS U(3) +#define NXP_DRAM0_ADDR ULL(0x80000000) +#define NXP_DRAM0_MAX_SIZE ULL(0x80000000) /* 2 GB */ + +#define NXP_DRAM1_ADDR ULL(0x880000000) +#define NXP_DRAM1_MAX_SIZE ULL(0x780000000) /* 30 GB */ + +#define NXP_DRAM2_ADDR ULL(0x8800000000) +#define NXP_DRAM2_MAX_SIZE ULL(0x7800000000) /* 480 GB */ + +/*DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +/* + * SVR Definition (not include major and minor rev) + * A: without security + * AE: with security + */ +#define SVR_LS1026A 0x870709 +#define SVR_LS1026AE 0x870708 +#define SVR_LS1046A 0x870701 +#define SVR_LS1046AE 0x870700 + +/* Number of cores in platform */ +/* Used by common code for array initialization */ +#define NUMBER_OF_CLUSTERS U(1) +#define CORES_PER_CLUSTER U(4) +#define PLATFORM_CORE_COUNT (NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER) + +/* + * Required LS standard platform porting definitions + * for CCI-400 + */ +#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4 + + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 40) + +/* Clock Divisors */ +#define NXP_PLATFORM_CLK_DIVIDER U(1) +#define NXP_UART_CLK_DIVIDER U(2) + +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS U(1) + + /* + * set this switch to 1 if you need to keep the debug block + * clocked during system power-down + */ +#define DEBUG_ACTIVE 0 + + /* + * pwr mgmt features supported in the soc-specific code: + * value == 0x0 the soc code does not support this feature + * value != 0x0 the soc code supports this feature + */ +#define SOC_CORE_RELEASE 0x1 +#define SOC_CORE_RESTART 0x1 +#define SOC_CORE_OFF 0x1 +#define SOC_CORE_STANDBY 0x1 +#define SOC_CORE_PWR_DWN 0x1 +#define SOC_CLUSTER_STANDBY 0x1 +#define SOC_CLUSTER_PWR_DWN 0x1 +#define SOC_SYSTEM_STANDBY 0x1 +#define SOC_SYSTEM_PWR_DWN 0x1 +#define SOC_SYSTEM_OFF 0x1 +#define SOC_SYSTEM_RESET 0x1 + +/* Start: Macros used by lib/psci files */ +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) + +/* + * 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. + * + * CACHE_WRITEBACK_GRANULE is defined in soc.def + */ + + /* One cache line needed for bakery locks on ARM platforms */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + NXP_CCI_CLUSTER0_SL_IFACE_IX, +}; + +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); +#endif + +#endif /* SOC_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c new file mode 100644 index 0000000..3d561c7 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c @@ -0,0 +1,177 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80010412), + .cs[0].bnds = U(0x7F), + .sdram_cfg[0] = U(0xE50C0008), + .sdram_cfg[1] = U(0x00401010), + .sdram_cfg[2] = U(0x1), + .timing_cfg[0] = U(0xFA550018), + .timing_cfg[1] = U(0xBAB40C52), + .timing_cfg[2] = U(0x0048C11C), + .timing_cfg[3] = U(0x01111000), + .timing_cfg[4] = U(0x00000002), + .timing_cfg[5] = U(0x03401400), + .timing_cfg[6] = U(0x0), + .timing_cfg[7] = U(0x23300000), + .timing_cfg[8] = U(0x02116600), + .timing_cfg[9] = U(0x0), + .dq_map[0] = U(0x0), + .dq_map[1] = U(0x0), + .dq_map[2] = U(0x0), + .dq_map[3] = U(0x0), + .sdram_mode[0] = U(0x01010210), + .sdram_mode[1] = U(0x0), + .sdram_mode[8] = U(0x00000500), + .sdram_mode[9] = U(0x04000000), + .interval = U(0x18600618), + .zq_cntl = U(0x8A090705), + .ddr_sr_cntr = U(0x0), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xC1), + .wrlvl_cntl[0] = U(0x86550607), + .wrlvl_cntl[1] = U(0x07070708), + .wrlvl_cntl[2] = U(0x0808088), +}; + +long long board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + + return 0x80000000ULL; +} +#else /* ifndef CONFIG_STATIC_DDR */ +static const struct rc_timing rcz[] = { + {U(1600), U(8), U(7)}, + {U(2100), U(8), U(7)}, + {} +}; + +static const struct board_timing ram[] = { + {U(0x1f), rcz, U(0x01010101), U(0x01010101)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + ret = cal_board_params(priv, ram, ARRAY_SIZE(ram)); + if (ret != 0) { + return ret; + } + + popts->bstopre = 0; + popts->half_strength_drive_en = 1; + popts->cpo_sample = U(0x46); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_50ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_50ohm) | + DDR_CDR2_VREF_TRAIN_EN; + popts->output_driver_impedance = 1; + + return 0; +} + +/* DDR model number: MT40A512M16JY-083E:B */ +struct dimm_params ddr_raw_timing = { + .n_ranks = U(1), + .rank_density = ULL(4294967296), + .capacity = ULL(4294967296), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .rdimm = U(0), + .mirrored_dimm = U(0), + .n_row_addr = U(16), + .n_col_addr = U(10), + .bank_group_bits = U(1), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 750, + .tckmax_ps = 1900, + .caslat_x = U(0x0001FFE00), + .taa_ps = 13500, + .trcd_ps = 13500, + .trp_ps = 13500, + .tras_ps = 33000, + .trc_ps = 46500, + .twr_ps = 15000, + .trfc1_ps = 350000, + .trfc2_ps = 260000, + .trfc4_ps = 160000, + .tfaw_ps = 30000, + .trrds_ps = 5300, + .trrdl_ps = 6400, + .tccdl_ps = 5355, + .refresh_rate_ps = U(7800000), + .dq_mapping[0] = U(0x0), + .dq_mapping[1] = U(0x0), + .dq_mapping[2] = U(0x0), + .dq_mapping[3] = U(0x0), + .dq_mapping[4] = U(0x0), + .dq_mapping_ors = U(0), + .rc = U(0x1f), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + return 1; +} +#endif /* ifdef CONFIG_STATIC_DDR */ + +long long init_ddr(void) +{ + int spd_addr[] = {NXP_SPD_EEPROM0}; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + assert(0); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h new file mode 100644 index 0000000..5134a00 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include + +#include "policy.h" +#include + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x8000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES U(3) +#define MAX_IO_BLOCK_DEVICES U(1) +#define MAX_IO_HANDLES U(4) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES U(2) +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES U(1) +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif /* PLAT_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk new file mode 100644 index 0000000..1f7fad6 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk @@ -0,0 +1,39 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= qspi +BOARD := ls1046afrwy +POVDD_ENABLE := no + +# DDR Compilation Configs +CONFIG_STATIC_DDR := 0 +CONFIG_DDR_NODIMM := 1 +DDRC_NUM_DIMM := 0 +NUM_OF_DDRC := 1 +DDRC_NUM_CS := 1 +DDR_ECC_EN := yes + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x20000000 +NOR_FLASH_SZ := 0x20000000 + +# Platform specific features. +WARM_BOOT := no + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := qspi \ + sd + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1046a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c new file mode 100644 index 0000000..6d1707c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c @@ -0,0 +1,90 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include + +static const struct rc_timing rce[] = { + {U(1600), U(8), U(7)}, + {U(1867), U(8), U(7)}, + {U(2134), U(8), U(9)}, + {} +}; + +static const struct board_timing udimm[] = { + {U(0x04), rce, U(0x01020304), U(0x06070805)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + if (popts->rdimm) { + debug("RDIMM parameters not set.\n"); + return -EINVAL; + } + + ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); + if (ret != 0) { + return ret; + } + + popts->wrlvl_override = U(1); + popts->wrlvl_sample = U(0x0); /* 32 clocks */ + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_TRAIN_EN | + DDR_CDR2_VREF_RANGE_2; + + /* optimize cpo for erratum A-009942 */ + popts->cpo_sample = U(0x70); + + return 0; +} + +long long init_ddr(void) +{ + int spd_addr[] = { NXP_SPD_EEPROM0 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + assert(0); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h new file mode 100644 index 0000000..aa69a66 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x00100000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES U(3) +#define MAX_IO_BLOCK_DEVICES U(1) +#define MAX_IO_HANDLES U(4) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES U(2) +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES U(1) +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk new file mode 100644 index 0000000..9600b93 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk @@ -0,0 +1,39 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters +BOOT_MODE ?= qspi +BOARD := ls1046aqds +POVDD_ENABLE := no + + # DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDRC_NUM_CS := 4 +DDR_ECC_EN := yes +CONFIG_STATIC_DDR := 0 + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x20000000 +NOR_FLASH_SZ := 0x20000000 + +# Platform specific features. +WARM_BOOT := no + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := qspi \ + sd \ + nor \ + nand + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1046a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c new file mode 100644 index 0000000..b9940cf --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c @@ -0,0 +1,267 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_2100 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x1FF), + .cs[1].config = U(0x80000322), + .cs[1].bnds = U(0x1FF), + .sdram_cfg[0] = U(0xE5004000), + .sdram_cfg[1] = U(0x401151), + .timing_cfg[0] = U(0xD1770018), + .timing_cfg[1] = U(0xF2FC9245), + .timing_cfg[2] = U(0x594197), + .timing_cfg[3] = U(0x2101100), + .timing_cfg[4] = U(0x220002), + .timing_cfg[5] = U(0x5401400), + .timing_cfg[7] = U(0x26600000), + .timing_cfg[8] = U(0x5446A00), + .dq_map[0] = U(0x32C57554), + .dq_map[1] = U(0xD4BB0BD4), + .dq_map[2] = U(0x2EC2F554), + .dq_map[3] = U(0xD95D4001), + .sdram_mode[0] = U(0x3010631), + .sdram_mode[1] = U(0x100200), + .sdram_mode[9] = U(0x8400000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10631), + .sdram_mode[3] = U(0x100200), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x8400000), + .sdram_mode[4] = U(0x10631), + .sdram_mode[5] = U(0x100200), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x8400000), + .sdram_mode[6] = U(0x10631), + .sdram_mode[7] = U(0x100200), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x8400000), + .interval = U(0x1FFE07FF), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xC1), + .wrlvl_cntl[0] = U(0x86750609), + .wrlvl_cntl[1] = U(0xA0B0C0D), + .wrlvl_cntl[2] = U(0xF10110E), +}; + +const struct ddr_cfg_regs static_1800 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x1FF), + .cs[1].config = U(0x80000322), + .cs[1].bnds = U(0x1FF), + .sdram_cfg[0] = U(0xE5004000), + .sdram_cfg[1] = U(0x401151), + .timing_cfg[0] = U(0x91660018), + .timing_cfg[1] = U(0xDDD82045), + .timing_cfg[2] = U(0x512153), + .timing_cfg[3] = U(0x10E1100), + .timing_cfg[4] = U(0x220002), + .timing_cfg[5] = U(0x4401400), + .timing_cfg[7] = U(0x14400000), + .timing_cfg[8] = U(0x3335900), + .dq_map[0] = U(0x32C57554), + .dq_map[1] = U(0xD4BB0BD4), + .dq_map[2] = U(0x2EC2F554), + .dq_map[3] = U(0xD95D4001), + .sdram_mode[0] = U(0x3010421), + .sdram_mode[1] = U(0x80200), + .sdram_mode[9] = U(0x4400000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10421), + .sdram_mode[3] = U(0x80200), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x4400000), + .sdram_mode[4] = U(0x10421), + .sdram_mode[5] = U(0x80200), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x4400000), + .sdram_mode[6] = U(0x10421), + .sdram_mode[7] = U(0x80200), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x4400000), + .interval = U(0x1B6C06DB), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xC1), + .wrlvl_cntl[0] = U(0x86750607), + .wrlvl_cntl[1] = U(0x8090A0B), + .wrlvl_cntl[2] = U(0xD0E0F0C), +}; + +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x1FF), + .cs[1].config = U(0x80000322), + .cs[1].bnds = U(0x1FF), + .sdram_cfg[0] = U(0xE5004000), + .sdram_cfg[1] = U(0x401151), + .sdram_cfg[2] = U(0x0), + .timing_cfg[0] = U(0x91550018), + .timing_cfg[1] = U(0xBAB48E44), + .timing_cfg[2] = U(0x490111), + .timing_cfg[3] = U(0x10C1000), + .timing_cfg[4] = U(0x220002), + .timing_cfg[5] = U(0x3401400), + .timing_cfg[6] = U(0x0), + .timing_cfg[7] = U(0x13300000), + .timing_cfg[8] = U(0x1224800), + .timing_cfg[9] = U(0x0), + .dq_map[0] = U(0x32C57554), + .dq_map[1] = U(0xD4BB0BD4), + .dq_map[2] = U(0x2EC2F554), + .dq_map[3] = U(0xD95D4001), + .sdram_mode[0] = U(0x3010211), + .sdram_mode[1] = U(0x0), + .sdram_mode[9] = U(0x400000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10211), + .sdram_mode[3] = U(0x0), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x400000), + .sdram_mode[4] = U(0x10211), + .sdram_mode[5] = U(0x0), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x400000), + .sdram_mode[6] = U(0x10211), + .sdram_mode[7] = U(0x0), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x400000), + .interval = U(0x18600618), + .zq_cntl = U(0x8A090705), + .ddr_sr_cntr = U(0x0), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xC1), + .wrlvl_cntl[0] = U(0x86750607), + .wrlvl_cntl[1] = U(0x8090A0B), + .wrlvl_cntl[2] = U(0xD0E0F0C), +}; + +struct static_table { + unsigned long rate; + const struct ddr_cfg_regs *regs; +}; + +const struct static_table table[] = { + {1600, &static_1600}, + {1800, &static_1800}, + {2100, &static_2100}, +}; + +long long board_static_ddr(struct ddr_info *priv) +{ + const unsigned long clk = priv->clk / 1000000; + long long size = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(table); i++) { + if (table[i].rate >= clk) { + break; + } + } + if (i < ARRAY_SIZE(table)) { + VERBOSE("Found static setting for rate %ld\n", table[i].rate); + memcpy(&priv->ddr_reg, table[i].regs, + sizeof(struct ddr_cfg_regs)); + size = 0x200000000UL; + } else { + ERROR("Not static settings for rate %ld\n", clk); + } + + return size; +} +#else /* ifndef CONFIG_STATIC_DDR */ +static const struct rc_timing rce[] = { + {U(1600), U(8), U(7)}, + {U(1867), U(8), U(7)}, + {U(2134), U(8), U(9)}, + {} +}; + +static const struct board_timing udimm[] = { + {U(0x04), rce, U(0x01020304), U(0x06070805)}, + {U(0x1f), rce, U(0x01020304), U(0x06070805)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + if (popts->rdimm) { + debug("RDIMM parameters not set.\n"); + return -EINVAL; + } + + ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); + if (ret != 0) { + return ret; + } + + popts->wrlvl_override = U(1); + popts->wrlvl_sample = U(0x0); /* 32 clocks */ + popts->cpo_sample = U(0x61); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_TRAIN_EN | + DDR_CDR2_VREF_RANGE_2; + popts->bstopre = U(0); + + return 0; +} +#endif /* ifdef CONFIG_STATIC_DDR */ + +long long init_ddr(void) +{ + int spd_addr[] = {NXP_SPD_EEPROM0}; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + assert(0); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = U(1); + info.dimm_on_ctlr = U(1); + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h new file mode 100644 index 0000000..b5e66ae --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include + +#include "policy.h" +#include + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x00100000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES U(3) +#define MAX_IO_BLOCK_DEVICES U(1) +#define MAX_IO_HANDLES U(4) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES U(2) +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES U(1) +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif /* PLAT_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk new file mode 100644 index 0000000..32e6db5 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk @@ -0,0 +1,38 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters +BOOT_MODE ?= qspi +BOARD := ls1046ardb +POVDD_ENABLE := no + +# DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDRC_NUM_CS := 4 +DDR_ECC_EN := yes +CONFIG_STATIC_DDR := 0 + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x20000000 +NOR_FLASH_SZ := 0x20000000 + +# Platform specific features. +WARM_BOOT := no + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := qspi \ + sd \ + emmc + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1046a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c new file mode 100644 index 0000000..d17e672 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c @@ -0,0 +1,395 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#endif +#include +#include +#include + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, +}; + +/* Function to return the SoC SYS CLK */ +static unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} + +/* + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + * + */ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + + counter_base_frequency = get_sys_clk() / 4; + + return counter_base_frequency; +} + +#ifdef IMAGE_BL2 +/* Functions for BL2 */ + +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1046A, LS1046A, 1, 4), + SOC_ENTRY(LS1046AE, LS1046AE, 1, 4), + SOC_ENTRY(LS1026A, LS1026A, 1, 2), + SOC_ENTRY(LS1026AE, LS1026AE, 1, 2), +}; + +#ifdef POLICY_FUSE_PROVISION +static gpio_init_info_t gpio_init_data = { + .gpio1_base_addr = NXP_GPIO1_ADDR, + .gpio2_base_addr = NXP_GPIO2_ADDR, + .gpio3_base_addr = NXP_GPIO3_ADDR, + .gpio4_base_addr = NXP_GPIO4_ADDR, +}; +#endif + +/* + * Function to set the base counter frequency at + * the first entry of the Frequency Mode Table, + * at CNTFID0 (0x20 offset). + * + * Set the value of the pirmary core register cntfrq_el0. + */ +static void set_base_freq_CNTFID0(void) +{ + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + */ + unsigned int counter_base_frequency = get_sys_clk() / 4; + + /* Setting the frequency in the Frequency modes table. + * + * Note: The value for ls1046ardb board at this offset + * is not RW as stated. This offset have the + * fixed value of 100000400 Hz. + * + * The below code line has no effect. + * Keeping it for other platforms where it has effect. + */ + mmio_write_32(NXP_TIMER_ADDR + CNTFID_OFF, counter_base_frequency); + + write_cntfrq_el0(counter_base_frequency); +} + +void soc_preload_setup(void) +{ + +} + +/* + * This function implements soc specific erratas + * This is called before DDR is initialized or MMU is enabled + */ +void soc_early_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); +#ifdef POLICY_FUSE_PROVISION + gpio_init(&gpio_init_data); + sec_init(NXP_CAAM_ADDR); +#endif +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + set_base_freq_CNTFID0(); + + /* Enable snooping on SEC read and write transactions */ + scfg_setbits32((void *)(NXP_SCFG_ADDR + SCFG_SNPCNFGCR_OFFSET), + SCFG_SNPCNFGCR_SECRDSNP | SCFG_SNPCNFGCR_SECWRSNP); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +#endif +#elif defined(POLICY_FUSE_PROVISION) + gpio_init(&gpio_init_data); + sfp_init(NXP_SFP_ADDR); + sec_init(NXP_CAAM_ADDR); +#endif + + soc_errata(); + + /* Initialize system level generic timer for Layerscape Socs. */ + delay_timer_init(NXP_TIMER_ADDR); + +#ifdef DDR_INIT + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +#endif +} + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +/* This function returns the boot device based on RCW_SRC */ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src, val; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + val = rcw_src & RCW_SRC_NAND_MASK; + + if (val == RCW_SRC_NAND_VAL) { + val = rcw_src & NAND_RESERVED_MASK; + if ((val != NAND_RESERVED_1) && (val != NAND_RESERVED_2)) { + src = BOOT_DEVICE_IFC_NAND; + INFO("RCW BOOT SRC is IFC NAND\n"); + } + } else { + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_NOR_MASK; + if (val == NOR_8B_VAL || val == NOR_16B_VAL) { + src = BOOT_DEVICE_IFC_NOR; + INFO("RCW BOOT SRC is IFC NOR\n"); + } else { + switch (rcw_src) { + case QSPI_VAL1: + case QSPI_VAL2: + src = BOOT_DEVICE_QSPI; + INFO("RCW BOOT SRC is QSPI\n"); + break; + case SD_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + default: + src = BOOT_DEVICE_NONE; + } + } + } + + return src; +} + +/* This function sets up access permissions on memory regions */ +void soc_mem_access(void) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + unsigned int dram_idx, index = 0U; + + for (dram_idx = 0U; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[dram_idx].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc400_reg_list(tzc400_reg_list, + dram_idx, index, + info_dram_regions->region[dram_idx].addr, + info_dram_regions->region[dram_idx].size, + NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE); + } + + mem_access_setup(NXP_TZC_ADDR, index, tzc400_reg_list); +} + +#else /* IMAGE_BL2 */ +/* Functions for BL31 */ + +const unsigned char _power_domain_tree_desc[] = {1, 1, 4}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1046_cluster_count); + +/* This function returns the SoC topology */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return _power_domain_tree_desc; +} + +/* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + */ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + return CORES_PER_CLUSTER; +} + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* Initialize system level generic timer for SoCs */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +void soc_platform_setup(void) +{ + static uint32_t target_mask_array[PLATFORM_CORE_COUNT]; + /* + * On a GICv2 system, the Group 1 secure interrupts are treated + * as Group 0 interrupts. + */ + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_LS_G0_IRQ_PROPS(GICV2_INTR_GROUP0) + }; + + plat_ls_gic_driver_init( +#if (TEST_BL31) + /* Defect in simulator - GIC base addresses (4Kb aligned) */ + NXP_GICD_4K_ADDR, + NXP_GICC_4K_ADDR, +#else + NXP_GICD_64K_ADDR, + NXP_GICC_64K_ADDR, +#endif + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* This function initializes the soc from the BL31 module */ +void soc_init(void) +{ + /* low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize the interconnect during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this but we can't + * assume so. No harm in executing this code twice. + */ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); + + /* Init CSU to enable non-secure access to peripherals */ + enable_layerscape_ns_access(ns_dev, ARRAY_SIZE(ns_dev), NXP_CSU_ADDR); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +} + +void soc_runtime_setup(void) +{ + +} + +#endif /* IMAGE_BL2 */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def new file mode 100644 index 0000000..e6b37c0 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def @@ -0,0 +1,107 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a72 + +CACHE_LINE := 6 + +# set to GIC400 or GIC500 +GIC := GIC400 + +# set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 2 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := NS16550 + + # Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# ddr controller - set to MMDC or NXP +DDRCNTLR := NXP + +# ddr phy - set to NXP or SNPS +DDRPHY := NXP + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0x5900 + +# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def +# Input to CST create_hdr_esbc tool +CSF_HDR_SZ := 0x3000 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + +# OCRAM MAP +OCRAM_START_ADDR := 0x10000000 +OCRAM_SIZE := 0x20000 + +# BL2 binary is placed at start of OCRAM. +# Also used by create_pbl.mk. +BL2_BASE := 0x10000000 + +# After BL2 bin, OCRAM is used by ROM Code: +# (OCRAM_START_ADDR + BL2_BIN_SIZE) -> (NXP_ROM_RSVD - 1) + +# After ROM Code, OCRAM is used by CSF header. +# (OCRAM_START_ADDR + BL2_TEXT_LIMIT + NXP_ROM_RSVD) -> (CSF_HDR_SZ - 1) + +# BL2_HDR_LOC has to be (OCRAM_START_ADDR + OCRAM_SIZE - NXP_ROM_RSVD - CSF_HDR_SZ) +# This value should be greater than BL2_TEXT_LIMIT +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(OCRAM_SIZE) - $(NXP_ROM_RSVD) - $(CSF_HDR_SZ)))) +# Covert to HEX to be used by create_pbl.mk +BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc) + +# Core Errata +ERRATA_A72_859971 := 1 + +# SoC ERRATAS +ERRATA_SOC_A008850 := 1 +ERRATA_SOC_A010539 := 1 + +# DDR Errata +ERRATA_DDR_A008511 := 1 +ERRATA_DDR_A009803 := 1 +ERRATA_DDR_A009942 := 1 +ERRATA_DDR_A010165 := 1 + +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# Define Endianness of each module +NXP_GUR_ENDIANNESS := BE +NXP_DDR_ENDIANNESS := BE +NXP_SEC_ENDIANNESS := BE +NXP_SFP_ENDIANNESS := BE +NXP_SNVS_ENDIANNESS := BE +NXP_ESDHC_ENDIANNESS := BE +NXP_QSPI_ENDIANNESS := BE +NXP_FSPI_ENDIANNESS := BE +NXP_SCFG_ENDIANNESS := BE +NXP_GPIO_ENDIANNESS := BE +NXP_IFC_ENDIANNESS := BE + +NXP_SFP_VER := 3_2 + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.mk new file mode 100644 index 0000000..8207dcd --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.mk @@ -0,0 +1,114 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1046a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH:= plat/nxp/common +PLAT_DRIVERS_PATH:= drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + +# Get SoC-specific defnitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + +# For Security Features +DISABLE_FUSE_WRITE := 1 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + +# Selecting Drivers for SoC +$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,CSU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +# Selecting PSCI & SIP_SVC support +$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31)) + +# Source File Addition +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_SOC_PATH}/include\ + -I${PLAT_COMMON_PATH}/soc_errata + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq ($(WARM_BOOT),yes) +include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk +endif + +ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes) +include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +# For fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + +# Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\ + ${WARM_RST_INCLUDES} + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${WARM_RST_BL31_SOURCES}\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\ + ${NV_STORAGE_SOURCES}\ + ${WARM_RST_BL_COMM_SOURCES}\ + ${PLAT_SOC_PATH}/soc.c + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + +# Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S b/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S new file mode 100644 index 0000000..0c6b7ea --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S @@ -0,0 +1,1817 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +.section .text, "ax" + +#include +#include +#include +#include + +#include "bl31_data.h" +#include "plat_psci.h" +#include "platform_def.h" + +/* + * the BASE address for these offsets is AUX_01_DATA in the + * bootcore's psci data region + */ +#define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */ +#define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */ + +/* + * the BASE address for these offsets is AUX_04_DATA in the + * bootcore's psci data region + */ +#define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */ +#define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */ + +#define IPSTPACK_RETRY_CNT 0x10000 +#define DDR_SLEEP_RETRY_CNT 0x10000 +#define CPUACTLR_EL1 S3_1_C15_C2_0 +#define DDR_SDRAM_CFG_2_FRCSR 0x80000000 +#define DDR_SDRAM_CFG_2_OFFSET 0x114 +#define DDR_TIMING_CFG_4_OFFSET 0x160 +#define DDR_CNTRL_BASE_ADDR 0x01080000 + +#define DLL_LOCK_MASK 0x3 +#define DLL_LOCK_VALUE 0x2 + +#define ERROR_DDR_SLEEP -1 +#define ERROR_DDR_WAKE -2 +#define ERROR_NO_QUIESCE -3 + +#define CORE_RESTARTABLE 0 +#define CORE_NOT_RESTARTABLE 1 + +.global soc_init_lowlevel +.global soc_init_percpu + +.global _soc_core_release +.global _soc_core_restart +.global _soc_ck_disabled +.global _soc_sys_reset +.global _soc_sys_off + +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off + +.global _soc_core_prep_stdby +.global _soc_core_entr_stdby +.global _soc_core_exit_stdby +.global _soc_core_prep_pwrdn +.global _soc_core_entr_pwrdn +.global _soc_core_exit_pwrdn +.global _soc_clstr_prep_stdby +.global _soc_clstr_exit_stdby +.global _soc_clstr_prep_pwrdn +.global _soc_clstr_exit_pwrdn +.global _soc_sys_prep_stdby +.global _soc_sys_exit_stdby +.global _soc_sys_prep_pwrdn +.global _soc_sys_pwrdn_wfi +.global _soc_sys_exit_pwrdn + +.global _set_platform_security +.global _soc_set_start_addr + +.equ TZPCDECPROT_0_SET_BASE, 0x02200804 +.equ TZPCDECPROT_1_SET_BASE, 0x02200810 +.equ TZPCDECPROT_2_SET_BASE, 0x0220081C + +.equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110 + +.equ MPIDR_AFFINITY0_MASK, 0x00FF +.equ MPIDR_AFFINITY1_MASK, 0xFF00 +.equ CPUECTLR_DISABLE_TWALK_PREFETCH, 0x4000000000 +.equ CPUECTLR_INS_PREFETCH_MASK, 0x1800000000 +.equ CPUECTLR_DAT_PREFETCH_MASK, 0x0300000000 +.equ OSDLR_EL1_DLK_LOCK, 0x1 +.equ CNTP_CTL_EL0_EN, 0x1 +.equ CNTP_CTL_EL0_IMASK, 0x2 +/* shifted value for incrementing cluster count in mpidr */ +.equ MPIDR_CLUSTER, 0x100 + +/* + * This function initialize the soc, + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11 + */ +func soc_init_lowlevel + /* + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + /* + * make sure the personality has been established by releasing cores + * that are marked "to-be-disabled" from reset + */ + bl release_disabled + + /* set SCRATCHRW7 to 0x0 */ + ldr x0, =DCFG_SCRATCHRW7_OFFSET + mov x1, xzr + bl _write_reg_dcfg + + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + ret +endfunc soc_init_lowlevel + +/* + * void soc_init_percpu(void) + * this function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func soc_init_percpu + stp x4, x30, [sp, #-16]! + + bl plat_my_core_mask + mov x2, x0 + + /* x2 = core mask */ + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A53 +1: + mov x0, #NXP_PMU_ADDR + bl enable_timer_base_to_cluster + ldp x4, x30, [sp], #16 + ret +endfunc soc_init_percpu + +/* + * this function sets the security mechanisms in the SoC to implement the + * Platform Security Policy + */ +func _set_platform_security + mov x3, x30 + +#if (!SUPPRESS_TZC) + /* initialize the tzpc */ + bl init_tzpc +#endif + +#if (!SUPPRESS_SEC) + /* initialize secmon */ + bl initSecMon +#endif + mov x30, x3 + ret +endfunc _set_platform_security + +/* + * this function writes a 64-bit address to bootlocptrh/l + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * out: none + * uses x0, x1, x2 + */ +func _soc_set_start_addr + /* get the 64-bit base address of the dcfg block */ + ldr x2, =NXP_DCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register */ + mov x1, x0 + str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register */ + lsr x1, x0, #32 + str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET] + ret +endfunc _soc_set_start_addr + +/* + * part of CPU_ON + * this function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +_soc_core_release: + mov x3, x30 + + /* x0 = core mask */ + + ldr x1, =NXP_SEC_REGFILE_ADDR + /* + * write to CORE_HOLD to tell the bootrom that we want this core + * to run + */ + str w0, [x1, #CORE_HOLD_OFFSET] + + /* x0 = core mask */ + + /* read-modify-write BRRL to release core */ + mov x1, #NXP_RESET_ADDR + ldr w2, [x1, #BRR_OFFSET] + orr w2, w2, w0 + str w2, [x1, #BRR_OFFSET] + dsb sy + isb + + /* send event */ + sev + isb + + mov x30, x3 + ret + +/* + * this function determines if a core is disabled via COREDISABLEDSR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1 + */ +_soc_ck_disabled: + /* get base addr of dcfg block */ + ldr x1, =NXP_DCFG_ADDR + + /* read COREDISABLEDSR */ + ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET] + + /* test core bit */ + and w0, w1, w0 + + ret + +/* + * part of CPU_ON + * this function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0, x1, x2, x3, x4, x5, x6 + */ +_soc_core_restart: + mov x6, x30 + mov x4, x0 + + /* x4 = core mask lsb */ + + /* pgm GICD_CTLR - enable secure grp0 */ + mov x5, #NXP_GICD_ADDR + ldr w2, [x5, #GICD_CTLR_OFFSET] + orr w2, w2, #GICD_CTLR_EN_GRP_0 + str w2, [x5, #GICD_CTLR_OFFSET] + dsb sy + isb + /* poll on RWP til write completes */ +4: + ldr w2, [x5, #GICD_CTLR_OFFSET] + tst w2, #GICD_CTLR_RWP + b.ne 4b + + /* + * x4 = core mask lsb + * x5 = gicd base addr + */ + + mov x0, x4 + bl get_mpidr_value + + /* + * x0 = mpidr of target core + * x4 = core mask lsb of target core + * x5 = gicd base addr + */ + + /* generate target list bit */ + and x1, x0, #MPIDR_AFFINITY0_MASK + mov x2, #1 + lsl x2, x2, x1 + /* get the affinity1 field */ + and x1, x0, #MPIDR_AFFINITY1_MASK + lsl x1, x1, #8 + orr x2, x2, x1 + /* insert the INTID for SGI15 */ + orr x2, x2, #ICC_SGI0R_EL1_INTID + /* fire the SGI */ + msr ICC_SGI0R_EL1, x2 + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x6 + ret + +/* + * part of CPU_OFF + * this function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7 + */ +_soc_core_prep_off: + mov x8, x30 + mov x7, x0 + + /* x7 = core mask lsb */ + + mrs x1, CPUECTLR_EL1 + /* set smp and disable L2 snoops in cpuectlr */ + orr x1, x1, #CPUECTLR_SMPEN_EN + orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH + bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK + bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK + /* set retention control in cpuectlr */ + bic x1, x1, #CPUECTLR_TIMER_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + msr CPUECTLR_EL1, x1 + + /* get redistributor rd base addr for this core */ + mov x0, x7 + bl get_gic_rd_base + mov x6, x0 + + /* get redistributor sgi base addr for this core */ + mov x0, x7 + bl get_gic_sgi_base + mov x5, x0 + + /* x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w3, #GICR_ICENABLER0_SGI15 + str w3, [x5, #GICR_ICENABLER0_OFFSET] +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 2b + + /* disable GRP1 interrupts at cpu interface */ + msr ICC_IGRPEN1_EL3, xzr + + /* disable GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* program the redistributor - poll on GICR_CTLR.RWP as needed */ + + /* define SGI 15 as Grp0 - GICR_IGROUPR0 */ + ldr w4, [x5, #GICR_IGROUPR0_OFFSET] + bic w4, w4, #GICR_IGROUPR0_SGI15 + str w4, [x5, #GICR_IGROUPR0_OFFSET] + + /* define SGI 15 as Grp0 - GICR_IGRPMODR0 */ + ldr w3, [x5, #GICR_IGRPMODR0_OFFSET] + bic w3, w3, #GICR_IGRPMODR0_SGI15 + str w3, [x5, #GICR_IGRPMODR0_OFFSET] + + /* set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */ + ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET] + bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK + str w4, [x5, #GICR_IPRIORITYR3_OFFSET] + + /* enable SGI 15 at redistributor - GICR_ISENABLER0 */ + mov w3, #GICR_ISENABLER0_SGI15 + str w3, [x5, #GICR_ISENABLER0_OFFSET] + dsb sy + isb +3: + /* poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 3b + + /* quiesce the debug interfaces */ + mrs x3, osdlr_el1 + orr x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + /* enable grp0 ints */ + mov x3, #ICC_IGRPEN0_EL1_EN + msr ICC_IGRPEN0_EL1, x3 + + /* + * x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* clear any pending interrupts */ + mvn w1, wzr + str w1, [x5, #GICR_ICPENDR0_OFFSET] + + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 4f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +4: + /* enable the core timer and mask timer interrupt */ + mov x1, #CNTP_CTL_EL0_EN + orr x1, x1, #CNTP_CTL_EL0_IMASK + msr cntp_ctl_el0, x1 + + mov x30, x8 + ret + +/* + * part of CPU_OFF + * this function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +_soc_core_entr_off: + mov x5, x30 + mov x4, x0 + + /* x4 = core mask */ +1: + /* enter low-power state by executing wfi */ + wfi + + /* see if SGI15 woke us up */ + mrs x2, ICC_IAR0_EL1 + mov x3, #ICC_IAR0_EL1_SGI15 + cmp x2, x3 + b.ne 2f + + /* deactivate the int */ + msr ICC_EOIR0_EL1, x2 + + /* x4 = core mask */ +2: + /* check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + /* x0 = core state */ + + cmp x0, #CORE_WAKEUP + b.ne 1b + + /* if we get here, then we have exited the wfi */ + + mov x30, x5 + ret + +/* + * part of CPU_OFF + * this function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6 + */ +_soc_core_exit_off: + mov x6, x30 + mov x5, x0 + + /* disable forwarding of GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* get redistributor sgi base addr for this core */ + mov x0, x5 + bl get_gic_sgi_base + mov x4, x0 + + /* + * x4 = gicr sgi base addr + * x5 = core mask + */ + + /* disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w1, #GICR_ICENABLER0_SGI15 + str w1, [x4, #GICR_ICENABLER0_OFFSET] + + /* get redistributor rd base addr for this core */ + mov x0, x5 + bl get_gic_rd_base + mov x4, x0 + + /* x4 = gicr rd base addr */ +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w2, [x4, #GICR_CTLR_OFFSET] + tst w2, #GICR_CTLR_RWP + b.ne 2b + + /* x4 = gicr rd base addr */ + + /* unlock the debug interfaces */ + mrs x3, osdlr_el1 + bic x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + dsb sy + isb + mov x30, x6 + ret + +/* + * this function requests a reset of the entire SOC + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6 + */ +_soc_sys_reset: + mov x3, x30 + + /* make sure the mask is cleared in the reset request mask register */ + mov x0, #RST_RSTRQMR1_OFFSET + mov w1, wzr + bl _write_reg_reset + + /* set the reset request */ + mov x4, #RST_RSTCR_OFFSET + mov x0, x4 + mov w1, #RSTCR_RESET_REQ + bl _write_reg_reset + + /* x4 = RST_RSTCR_OFFSET */ + + /* + * just in case this address range is mapped as cacheable, + * flush the write out of the dcaches + */ + mov x2, #NXP_RESET_ADDR + add x2, x2, x4 + dc cvac, x2 + dsb st + isb + + /* this function does not return */ + b . + +/* + * this function turns off the SoC + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +_soc_sys_off: + /* + * A-009810: LPM20 entry sequence might cause + * spurious timeout reset request + * workaround: MASK RESET REQ RPTOE + */ + ldr x0, =NXP_RESET_ADDR + ldr w1, [x0, #RST_RSTRQMR1_OFFSET] + orr w1, w1, #RSTRQMR_RPTOE_MASK + str w1, [x0, #RST_RSTRQMR1_OFFSET] + + /* disable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, =DCFG_DEVDISR3_QBMAIN + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* set TPMWAKEMR0 */ + ldr x0, =TPMWAKEMR0_ADDR + mov w1, #0x1 + str w1, [x0] + + /* disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* disable L2 prefetches */ + mrs x0, CPUECTLR_EL1 + orr x0, x0, #CPUECTLR_SMPEN_EN + orr x0, x0, #CPUECTLR_TIMER_8TICKS + msr CPUECTLR_EL1, x0 + dsb sy + isb + + /* disable CCN snoop domain */ + ldr x0, =NXP_CCI_ADDR + mov w1, #0x1 + str w1, [x0] + + mov x2, #DAIF_SET_MASK + + mrs x1, spsr_el1 + orr x1, x1, x2 + msr spsr_el1, x1 + + mrs x1, spsr_el2 + orr x1, x1, x2 + msr spsr_el2, x1 + + bl get_pmu_idle_cluster_mask + mov x3, #NXP_PMU_ADDR + + /* x3 = pmu base addr */ + + /* idle the ACP interfaces */ + str w0, [x3, #PMU_CLAINACTSETR_OFFSET] + + /* force the debug interface to be quiescent */ + mrs x0, osdlr_el1 + orr x0, x0, #0x1 + msr osdlr_el1, x0 + + bl get_pmu_flush_cluster_mask + /* x3 = pmu base addr */ + mov x3, #NXP_PMU_ADDR + + /* clear flush request and status */ + ldr x2, =PMU_CLSL2FLUSHCLRR_OFFSET + str w0, [x3, x2] + + /* close the Skyros master port */ + ldr x2, =PMU_CLSINACTSETR_OFFSET + str w0, [x3, x2] + + /* request lpm20 */ + ldr x0, =PMU_POWMGTCSR_OFFSET + ldr w1, =PMU_POWMGTCSR_VAL + str w1, [x3, x0] + + /* this function does not return */ +1: + wfi + b 1b + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_stdby: + /* clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_stdby: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3 + */ +_soc_core_prep_pwrdn: + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +1: + /* + * enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_pwrdn: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses + */ +_soc_core_exit_pwrdn: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_stdby: + /* clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3 + */ +_soc_clstr_prep_pwrdn: + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +1: + /* + * enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses + */ +_soc_clstr_exit_pwrdn: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_prep_stdby: + /* clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_sys_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_sys_prep_pwrdn: + /* set retention control */ + mrs x0, CPUECTLR_EL1 + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_8TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x0 + dsb sy + isb + + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8 + */ +_soc_sys_pwrdn_wfi: + /* Save LR to stack */ + stp x18, x30, [sp, #-16]! + + /* Poll PCPW20SR for all secondary cores to be placed in PW20 */ + bl get_tot_num_cores + mov x3, #0x1 + lsl x3, x3, x0 + sub x3, x3, #2 +1: + mov x0, #NXP_PMU_ADDR + ldr w1, [x0, #PMU_PCPW20SR_OFFSET] + cmp w1, w3 + b.ne 1b + + /* backup EPU registers to stack */ + mov x3, #NXP_PMU_ADDR + ldr x2, =NXP_EPU_ADDR + ldr w4, [x2, #EPU_EPIMCR10_OFFSET] + ldr w5, [x2, #EPU_EPCCR10_OFFSET] + ldr w6, [x2, #EPU_EPCTR10_OFFSET] + ldr w7, [x2, #EPU_EPGCR_OFFSET] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = epu base addr + * x3 = pmu base addr + */ + + /* set up EPU event to receive the wake signal from PMU */ + mov w4, #EPU_EPIMCR10_VAL + mov w5, #EPU_EPCCR10_VAL + mov w6, #EPU_EPCTR10_VAL + mov w7, #EPU_EPGCR_VAL + str w4, [x2, #EPU_EPIMCR10_OFFSET] + str w5, [x2, #EPU_EPCCR10_OFFSET] + str w6, [x2, #EPU_EPCTR10_OFFSET] + str w7, [x2, #EPU_EPGCR_OFFSET] + + /* + * A-010194: There is logic problem + * in the path of GIC-to-PMU to issue + * wake request to core0 + * Workaround: Re-target the wakeup interrupts + * to a core other than the last active core0 + */ + ldr x2, =NXP_GICD_ADDR + + /* backup flextimer/mmc/usb interrupt router */ + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + ldr w4, [x2, x0] + ldr w5, [x2, x1] + ldr x0, =GICD_IROUTER112_OFFSET + ldr x1, =GICD_IROUTER113_OFFSET + ldr w6, [x2, x0] + ldr w7, [x2, x1] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = gicd base addr + * x0 = GICD_IROUTER112_OFFSET + * x1 = GICD_IROUTER113_OFFSET + */ + + /* re-route interrupt to cluster 1 */ + ldr w4, =GICD_IROUTER_VALUE + str w4, [x2, x0] + str w4, [x2, x1] + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + str w4, [x2, x0] + str w4, [x2, x1] + dsb sy + isb + + /* backup flextimer/mmc/usb interrupt enabler */ + ldr x0, =GICD_ISENABLER_1 + ldr w4, [x2, x0] + ldr x1, =GICD_ISENABLER_2 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + ldr x0, =GICD_ISENABLER_3 + ldr w4, [x2, x0] + ldr x1, =GICD_ICENABLER_1 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + ldr x0, =GICD_ICENABLER_2 + ldr w4, [x2, x0] + ldr x1, =GICD_ICENABLER_3 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + /* enable related interrupt routing */ + ldr w4, =GICD_ISENABLER_1_VALUE + ldr x0, =GICD_ISENABLER_1 + str w4, [x2, x0] + dsb sy + isb + + ldr w4, =GICD_ISENABLER_2_VALUE + ldr x0, =GICD_ISENABLER_2 + str w4, [x2, x0] + dsb sy + isb + + ldr w4, =GICD_ISENABLER_3_VALUE + ldr x0, =GICD_ISENABLER_3 + str w4, [x2, x0] + dsb sy + isb + + /* set POWMGTDCR [STP_PV_EN] = 1 */ + ldr x2, =NXP_POWMGTDCR + ldr w4, =0x01 + str w4, [x2] + + /* program IPSTPCR for override stop request (except DDR) */ + mov x3, #NXP_PMU_ADDR + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + ldr x2, =PMU_IPPDEXPCR4_OFFSET + ldr w7, [x3, x2] + + mov x5, xzr + ldr x6, =IPPDEXPCR4_MASK + and x6, x6, x7 + cbz x6, 1f + + /* + * x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR + */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR + csel x5, x5, x4, EQ +1: + /* store the DEVDISR5 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR5_MASK_OFFSET] + + mov x3, #NXP_PMU_ADDR + + /* write IPSTPCR0 - no overrides */ + ldr x2, =PMU_IPSTPCR0_OFFSET + ldr w5, =IPSTPCR0_VALUE + str w5, [x3, x2] + + /* write IPSTPCR1 - no overrides */ + ldr x2, =PMU_IPSTPCR1_OFFSET + ldr w5, =IPSTPCR1_VALUE + str w5, [x3, x2] + + /* write IPSTPCR2 - no overrides */ + ldr x2, =PMU_IPSTPCR2_OFFSET + ldr w5, =IPSTPCR2_VALUE + str w5, [x3, x2] + + /* write IPSTPCR3 - no overrides */ + ldr x2, =PMU_IPSTPCR3_OFFSET + ldr w5, =IPSTPCR3_VALUE + str w5, [x3, x2] + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x2, =PMU_IPSTPCR4_OFFSET + ldr w5, =IPSTPCR4_VALUE + bic x5, x5, x6 + str w5, [x3, x2] + + /* write IPSTPCR5 - no overrides */ + ldr x2, =PMU_IPSTPCR5_OFFSET + ldr w5, =IPSTPCR5_VALUE + str w5, [x3, x2] + + /* write IPSTPCR6 - no overrides */ + ldr x2, =PMU_IPSTPCR6_OFFSET + ldr w5, =IPSTPCR6_VALUE + str w5, [x3, x2] + + /* poll IPSTPACK for IP stop acknowledgment (except DDR) */ + mov x3, #NXP_PMU_ADDR + + /* poll on IPSTPACK0 */ + ldr x2, =PMU_IPSTPACK0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x2, =PMU_IPSTPACK1_OFFSET + ldr x4, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +4: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x2, =PMU_IPSTPACK2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x2, =PMU_IPSTPACK3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x2, =PMU_IPSTPACK4_OFFSET + ldr x4, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +7: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + /* poll on IPSTPACK5 */ + ldr x2, =PMU_IPSTPACK5_OFFSET + ldr x4, =IPSTPCR5_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +8: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 19f + sub x7, x7, #1 + cbnz x7, 8b + +19: + /* poll on IPSTPACK6 */ + ldr x2, =PMU_IPSTPACK6_OFFSET + ldr x4, =IPSTPCR6_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +9: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 20f + sub x7, x7, #1 + cbnz x7, 9b + +20: + /* save current DEVDISR states to DDR. */ + ldr x2, =NXP_DCFG_ADDR + + /* save DEVDISR1 and load new value */ + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, [x2, x0] + mov w13, w1 + ldr x1, =DEVDISR1_VALUE + str w1, [x2, x0] + /* save DEVDISR2 and load new value */ + ldr x0, =DCFG_DEVDISR2_OFFSET + ldr w1, [x2, x0] + mov w14, w1 + ldr x1, =DEVDISR2_VALUE + str w1, [x2, x0] + + /* x6 = DEVDISR5 override mask */ + + /* save DEVDISR3 and load new value */ + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, [x2, x0] + mov w15, w1 + ldr x1, =DEVDISR3_VALUE + str w1, [x2, x0] + + /* save DEVDISR4 and load new value */ + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, [x2, x0] + mov w16, w1 + /* not stop uart print */ + ldr x1, =0x0000332 + str w1, [x2, x0] + + /* save DEVDISR5 and load new value */ + ldr x0, =DCFG_DEVDISR5_OFFSET + ldr w1, [x2, x0] + mov w17, w1 + /* Enable this wakeup will fail, should enable OCRAM */ + ldr x1, =0x00102300 + str w1, [x2, x0] + + /* save DEVDISR6 and load new value */ + ldr x0, =DCFG_DEVDISR6_OFFSET + ldr w1, [x2, x0] + mov w18, w1 + ldr x1, =DEVDISR6_VALUE + str w1, [x2, x0] + + /* + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * w18 = DEVDISR6 saved value + */ + /* + * A-009810: LPM20 entry sequence might cause + * spurious timeout reset request + * workaround: MASK RESET REQ RPTOE + */ + ldr x0, =NXP_RESET_ADDR + ldr w1, =RSTRQMR_RPTOE_MASK + str w1, [x0, #RST_RSTRQMR1_OFFSET] + + /* disable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, =DCFG_DEVDISR3_QBMAIN + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* + * write the GICR_WAKER.ProcessorSleep bits to 1 + * enable the WakeRequest signal + * x3 is cpu mask starting from cpu7 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base + ldr w1, [x0, #GICR_WAKER_OFFSET] + orr w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cmp w1, #GICR_WAKER_ASLEEP + b.ne 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* x3 = pmu base addr */ + + /* perform Icache Warming Sequence */ + ldr x5, =IPSTPCR4_VALUE + mov x6, DDR_CNTRL_BASE_ADDR + mov x7, #NXP_PMU_ADDR + mov x8, #NXP_DCFG_ADDR + mov x10, #PMU_IPSTPCR4_OFFSET + mov x11, #PMU_IPSTPACK4_OFFSET + mov x12, #PMU_IPSTPCR3_OFFSET + mov x18, #PMU_IPSTPCR2_OFFSET + mov x19, #PMU_IPSTPCR1_OFFSET + mov x21, #PMU_IPSTPCR0_OFFSET + ldr x22, =DCFG_DEVDISR5_OFFSET + ldr x23, =NXP_EPU_ADDR + mov x9, #CORE_RESTARTABLE + bl final_pwrdown + + /* + * disable the WakeRequest signal on cpu 0-7 + * x3 is cpu mask starting from cpu7 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base + ldr w1, [x0, #GICR_WAKER_OFFSET] + bic w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cbnz w1, 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* set SGI for secondary core wakeup */ + ldr x0, =0x1000002 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x2000004 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x3000008 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x4010001 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x5010002 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x6010004 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x7010008 + msr S3_0_C12_C11_7, x0 + + /* enable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + str wzr, [x2, #DCFG_DEVDISR1_OFFSET] + str wzr, [x2, #DCFG_DEVDISR3_OFFSET] + str wzr, [x2, #DCFG_DEVDISR4_OFFSET] + + /* clear POWMGTDCR [STP_PV_EN] */ + ldr x2, =NXP_POWMGTDCR + ldr w4, [x2] + bic w4, w4, #0x01 + str w4, [x2] + + /* restore flextimer/mmc/usb interrupt enabler */ + ldr x3, =NXP_GICD_ADDR + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ICENABLER_2 + mvn w0, w0 + str w0, [x3, x1] + ldr x1, =GICD_ICENABLER_3 + mvn w2, w2 + str w2, [x3, x1] + + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ISENABLER_3 + str w0, [x3, x1] + ldr x1, =GICD_ICENABLER_1 + mvn w2, w2 + str w0, [x3, x1] + + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ISENABLER_1 + str w0, [x3, x1] + ldr x1, =GICD_ISENABLER_2 + str w0, [x3, x1] + + /* restore flextimer/mmc/usb interrupt router */ + ldr x3, =NXP_GICD_ADDR + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER113_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER112_OFFSET + str w0, [x3, x1] + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER76_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER60_OFFSET + str w0, [x3, x1] + + /* restore EPU registers */ + ldr x3, =NXP_EPU_ADDR + ldp x0, x2, [sp], #16 + str w2, [x3, #EPU_EPGCR_OFFSET] + str w0, [x3, #EPU_EPCTR10_OFFSET] + ldp x2, x1, [sp], #16 + str w1, [x3, #EPU_EPCCR10_OFFSET] + str w2, [x3, #EPU_EPIMCR10_OFFSET] + + isb + /* Restor LR */ + ldp x18, x30, [sp], #16 + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_exit_pwrdn: + mrs x1, SCTLR_EL1 + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL1, x1 + isb + ret + +/* + * this function checks to see if cores which are to be disabled have been + * released from reset - if not, it releases them + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8 + */ +release_disabled: + mov x8, x30 + + /* read COREDISABLESR */ + mov x0, #NXP_DCFG_ADDR + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + + /* get the number of cpus on this device */ + mov x6, #PLATFORM_CORE_COUNT + + mov x0, #NXP_RESET_ADDR + ldr w5, [x0, #BRR_OFFSET] + + /* load the core mask for the first core */ + mov x7, #1 + + /* + * x4 = COREDISABLESR + * x5 = BRR + * x6 = loop count + * x7 = core mask bit + */ +2: + /* check if the core is to be disabled */ + tst x4, x7 + b.eq 1f + + /* see if disabled cores have already been released from reset */ + tst x5, x7 + b.ne 1f + + /* if core has not been released, then release it (0-3) */ + mov x0, x7 + bl _soc_core_release + + /* record the core state in the data area (0-3) */ + mov x0, x7 + mov x1, #CORE_DISABLED + bl _setCoreState + +1: + /* decrement the counter */ + subs x6, x6, #1 + b.le 3f + + /* shift the core mask to the next core */ + lsl x7, x7, #1 + /* continue */ + b 2b +3: + mov x30, x8 + ret + +/* + * write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + str w1, [x2, x0] + ret + +/* + * read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +_read_reg_dcfg: + ldr x1, =NXP_DCFG_ADDR + ldr w0, [x1, x0] + ret + +/* + * this function sets up the TrustZone Address Space Controller (TZASC) + * in: none + * out: none + * uses x0, x1 + */ +init_tzpc: + /* + * set Non Secure access for all devices protected via TZPC + * decode Protection-0 Set Reg + */ + ldr x1, =TZPCDECPROT_0_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* decode Protection-1 Set Reg */ + ldr x1, =TZPCDECPROT_1_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* decode Protection-2 Set Reg */ + ldr x1, =TZPCDECPROT_2_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* + * entire SRAM as NS + * secure RAM region size Reg + */ + ldr x1, =NXP_OCRAM_TZPC_ADDR + /* 0x00000000 = no secure region */ + mov w0, #0x00000000 + str w0, [x1] + + ret + +/* this function performs initialization on SecMon for boot services */ +initSecMon: + /* read the register hpcomr */ + ldr x1, =NXP_SNVS_ADDR + ldr w0, [x1, #SECMON_HPCOMR_OFFSET] + /* turn off secure access for the privileged registers */ + orr w0, w0, #SECMON_HPCOMR_NPSWAEN + /* write back */ + str w0, [x1, #SECMON_HPCOMR_OFFSET] + + ret + +/* + * this function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor rd base address for specified core + * uses x0, x1, x2 + */ +get_gic_rd_base: + /* get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + + ldr x0, =NXP_GICR_ADDR + mov x1, #GIC_RD_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * this function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor sgi base address for specified core + * uses x0, x1, x2 + */ +get_gic_sgi_base: + /* get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + + ldr x0, =NXP_GICR_SGI_ADDR + mov x1, #GIC_SGI_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * this function returns an mpidr value for a core, given a core_mask_lsb + * in: x0 = core mask lsb + * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits + * uses x0, x1 + */ +get_mpidr_value: + /* convert a core mask to an SoC core number */ + clz w0, w0 + mov w1, #31 + sub w0, w1, w0 + + /* w0 = SoC core number */ + + mov w1, wzr +2: + cmp w0, #CORES_PER_CLUSTER + b.lt 1f + sub w0, w0, #CORES_PER_CLUSTER + add w1, w1, #MPIDR_CLUSTER + b 2b + + /* insert the mpidr core number */ +1: + orr w0, w1, w0 + ret + +/* + * write a register in the RESET block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_reset: + ldr x2, =NXP_RESET_ADDR + str w1, [x2, x0] + ret + +/* + * read a register in the RESET block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +_read_reg_reset: + ldr x1, =NXP_RESET_ADDR + ldr w0, [x1, x0] + ret + +/* + * this function will pwrdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = NXP_PMU_ADDR + * x8 = NXP_DCFG_ADDR + * x9 = 0, restartable + * = 1, non-restartable + * x10 = PMU_IPSTPCR4_OFFSET + * x11 = PMU_IPSTPACK4_OFFSET + * x12 = PMU_IPSTPCR3_OFFSET + * x18 = PMU_IPSTPCR2_OFFSET + * x19 = PMU_IPSTPCR1_OFFSET + * x21 = PMU_IPSTPCR0_OFFSET + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * x22 = DCFG_DEVDISR5_OFFSET + * x23 = NXP_EPU_ADDR + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16, x17 + * x10, x11, x12, x18, x19, x21, x22, x23 + */ + +final_pwrdown: + /* delay */ + mov w4, #0xffffff +554: + sub w4, w4, #1 + cmp w4, #0 + b.ge 554b + + mov x0, xzr + b touch_line_0 + +/* 4Kb aligned */ +.align 12 +start_line_0: + mov x0, #1 + /* put ddr in self refresh - start */ + mov x2, #DDR_SDRAM_CFG_2_FRCSR + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + orr w3, w3, w2 + /* put ddr in self refresh - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + nop + nop +touch_line_0: + cbz x0, touch_line_1 + +start_line_1: + /* quiesce ddr clocks - start */ + orr w3, w5, #DCFG_DEVDISR5_MEM + mov w4, w3 + /* quiesce ddr clocks - end */ + str w4, [x7, x10] + mov w3, #DCFG_DEVDISR5_MEM + /* poll on ipstpack4 - start */ + mov x2, #DDR_SLEEP_RETRY_CNT + nop + nop +touch_line_1: + cbz x0, touch_line_2 + +start_line_2: + /* x11 = PMU_IPSTPACK4_OFFSET */ + ldr w1, [x7, x11] + tst w1, w3 + b.ne 5f + subs x2, x2, #1 + /* poll on ipstpack4 - end */ + b.gt start_line_2 + + /* if we get here, we have a timeout err */ + mov w4, w5 + /* x10 = PMU_IPSTPCR4_OFFSET re-enable ddr clks interface */ + str w4, [x7, x10] +touch_line_2: + cbz x0, touch_line_3 + +start_line_3: + /* load error code */ + mov x0, #ERROR_DDR_SLEEP + b 2f +5: + wfe + ldr w1, [x23, #EPU_EPCTR10_OFFSET] + cbz w1, 5b + + mov w4, w5 +touch_line_3: + cbz x0, touch_line_4 + +start_line_4: + /* re-enable ddr in devdisr5 */ + str w4, [x8, x22] + /* re-enable ddr clk in ipstpcr4 */ + str w4, [x7, x10] +13: + /* poll on ipstpack4 - start */ + ldr w1, [x7, x11] + tst w1, w3 + b.eq 2f + nop + b 13b + /* poll on ipstpack4 - end */ +2: +touch_line_4: + cbz x0, touch_line_5 + +start_line_5: + /* take ddr out-of self refresh - start */ + mov x2, #DDR_SDRAM_CFG_2_FRCSR + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + mov w4, w3 + bic w4, w4, w2 + mov w3, w4 + /* wait for ddr cntrlr clock- start */ + mov x1, #DDR_SLEEP_RETRY_CNT +3: + subs x1, x1, #1 +touch_line_5: + cbz x0, touch_line_6 + +start_line_6: + /* wait for ddr cntrlr clock - end */ + b.gt 3b + /* take ddr out-of self refresh - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + mov w1, w17 + /* reset devdisr5 */ + str w1, [x8, #DCFG_DEVDISR5_OFFSET] + mov w1, w16 + /* reset devdisr4 */ + str w1, [x8, #DCFG_DEVDISR4_OFFSET] + mov w1, w15 +touch_line_6: + cbz x0, touch_line_7 + +start_line_7: + /* reset devdisr3 */ + str w1, [x8, #DCFG_DEVDISR3_OFFSET] + mov w1, w14 + /* reset devdisr2 */ + str w1, [x8, #DCFG_DEVDISR2_OFFSET] + mov w1, w13 + /* reset devdisr1 */ + str w1, [x8, #DCFG_DEVDISR1_OFFSET] + /* reset ipstpcr4 */ + str wzr, [x7, x10] + /* reset ipstpcr3 */ + str wzr, [x7, x12] +touch_line_7: + cbz x0, touch_line_8 + +start_line_8: + /* reset ipstpcr2 */ + str wzr, [x7, x18] + /* reset ipstpcr1 */ + str wzr, [x7, x19] + /* reset ipstpcr0 */ + str wzr, [x7, x21] + +touch_line_8: + cbz x0, touch_line_9 + +start_line_9: + b continue_restart +touch_line_9: + cbz x0, start_line_0 + +/* execute here after ddr is back up */ +continue_restart: + /* + * if x0 = 1, all is well + * if x0 < 1, we had an error + */ + cmp x0, #1 + b.ne 4f + mov x0, #0 +4: + ret diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S new file mode 100644 index 0000000..890cf81 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S @@ -0,0 +1,69 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl plat_reset_handler + .globl platform_mem_init + +func platform_mem1_init + ret +endfunc platform_mem1_init + +func platform_mem_init + ret +endfunc platform_mem_init + +func apply_platform_errata + ret +endfunc apply_platform_errata + +func plat_reset_handler + mov x29, x30 + bl apply_platform_errata + +#if defined(IMAGE_BL31) + ldr x0, =POLICY_SMMU_PAGESZ_64K + cbz x0, 1f + /* Set the SMMU page size in the sACR register */ + bl _set_smmu_pagesz_64 +#endif +1: + mov x30, x29 + ret +endfunc plat_reset_handler + + /* + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + */ +func plat_secondary_cold_boot_setup + /* ls1088a does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, 0x0 + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h new file mode 100644 index 0000000..eb36c2e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h @@ -0,0 +1,229 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include "dcfg_lsch3.h" +#include "soc_default_base_addr.h" +#include "soc_default_helper_macros.h" + +/* + * SVR Definition of LS1088A + * A: without security + * AE: with security + * (not include major and minor rev) + */ +#define SVR_LS1044A 0x870323 +#define SVR_LS1044AE 0x870322 +#define SVR_LS1048A 0x870321 +#define SVR_LS1048AE 0x870320 +#define SVR_LS1084A 0x870303 +#define SVR_LS1084AE 0x870302 +#define SVR_LS1088A 0x870301 +#define SVR_LS1088AE 0x870300 + +#define SVR_WO_E 0xFFFFFE + +/* Number of cores in platform */ +#define NUMBER_OF_CLUSTERS 2 +#define CORES_PER_CLUSTER 4 +#define PLATFORM_CORE_COUNT (NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER) + +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 + + +#define NUM_DRAM_REGIONS 2 +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */ + +#define NXP_DRAM1_ADDR 0x8080000000 +#define NXP_DRAM1_MAX_SIZE 0x7F80000000 /* 510 G */ + +/* DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +#define NXP_POWMGTDCR 0x700123C20 + +/* epu register offsets and values */ +#define EPU_EPGCR_OFFSET 0x0 +#define EPU_EPIMCR10_OFFSET 0x128 +#define EPU_EPCTR10_OFFSET 0xa28 +#define EPU_EPCCR10_OFFSET 0x828 + +#ifdef EPU_EPCCR10_VAL +#undef EPU_EPCCR10_VAL +#endif +#define EPU_EPCCR10_VAL 0xf2800000 + +#define EPU_EPIMCR10_VAL 0xba000000 +#define EPU_EPCTR10_VAL 0x0 +#define EPU_EPGCR_VAL (1 << 31) + +/* pmu register offsets and values */ +#define PMU_PCPW20SR_OFFSET 0x830 +#define PMU_CLAINACTSETR_OFFSET 0x1100 +#define PMU_CLAINACTCLRR_OFFSET 0x1104 +#define PMU_CLSINACTSETR_OFFSET 0x1108 +#define PMU_CLSINACTCLRR_OFFSET 0x110C +#define PMU_CLL2FLUSHSETR_OFFSET 0x1110 +#define PMU_CLSL2FLUSHCLRR_OFFSET 0x1114 +#define PMU_CLL2FLUSHSR_OFFSET 0x1118 +#define PMU_POWMGTCSR_OFFSET 0x4000 +#define PMU_IPPDEXPCR0_OFFSET 0x4040 +#define PMU_IPPDEXPCR1_OFFSET 0x4044 +#define PMU_IPPDEXPCR2_OFFSET 0x4048 +#define PMU_IPPDEXPCR3_OFFSET 0x404C +#define PMU_IPPDEXPCR4_OFFSET 0x4050 +#define PMU_IPPDEXPCR5_OFFSET 0x4054 +#define PMU_IPSTPCR0_OFFSET 0x4120 +#define PMU_IPSTPCR1_OFFSET 0x4124 +#define PMU_IPSTPCR2_OFFSET 0x4128 +#define PMU_IPSTPCR3_OFFSET 0x412C +#define PMU_IPSTPCR4_OFFSET 0x4130 +#define PMU_IPSTPCR5_OFFSET 0x4134 +#define PMU_IPSTPCR6_OFFSET 0x4138 +#define PMU_IPSTPACK0_OFFSET 0x4140 +#define PMU_IPSTPACK1_OFFSET 0x4144 +#define PMU_IPSTPACK2_OFFSET 0x4148 +#define PMU_IPSTPACK3_OFFSET 0x414C +#define PMU_IPSTPACK4_OFFSET 0x4150 +#define PMU_IPSTPACK5_OFFSET 0x4154 +#define PMU_IPSTPACK6_OFFSET 0x4158 +#define PMU_POWMGTCSR_VAL (1 << 20) + +#define IPPDEXPCR0_MASK 0xFFFFFFFF +#define IPPDEXPCR1_MASK 0xFFFFFFFF +#define IPPDEXPCR2_MASK 0xFFFFFFFF +#define IPPDEXPCR3_MASK 0xFFFFFFFF +#define IPPDEXPCR4_MASK 0xFFFFFFFF +#define IPPDEXPCR5_MASK 0xFFFFFFFF + +/* DEVDISR5_FLX_TMR */ +#define IPPDEXPCR_FLX_TMR 0x00004000 +#define DEVDISR5_FLX_TMR 0x00004000 + +#define IPSTPCR0_VALUE 0x0041310C +#define IPSTPCR1_VALUE 0x000003FF +#define IPSTPCR2_VALUE 0x00013006 + +/* Dont' stop UART */ +#define IPSTPCR3_VALUE 0x0000033A + +#define IPSTPCR4_VALUE 0x00103300 +#define IPSTPCR5_VALUE 0x00000001 +#define IPSTPCR6_VALUE 0x00000000 + + +#define TZPC_BLOCK_SIZE 0x1000 + +/* PORSR1 */ +#define PORSR1_RCW_MASK 0xFF800000 +#define PORSR1_RCW_SHIFT 23 + +/* CFG_RCW_SRC[6:0] */ +#define RCW_SRC_TYPE_MASK 0x70 + +/* RCW SRC NOR */ +#define NOR_16B_VAL 0x20 + +/* + * RCW SRC Serial Flash + * 1. SERAIL NOR (QSPI) + * 2. OTHERS (SD/MMC, SPI, I2C1) + */ +#define RCW_SRC_SERIAL_MASK 0x7F +#define QSPI_VAL 0x62 +#define SDHC_VAL 0x40 +#define EMMC_VAL 0x41 + +/* + * Required LS standard platform porting definitions + * for CCN-504 - Read from RN-F node ID register + */ +#define PLAT_CLUSTER_TO_CCN_ID_MAP 1, 9, 11, 19 + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 40) + +/* + * Clock Divisors + */ +#define NXP_PLATFORM_CLK_DIVIDER 1 +#define NXP_UART_CLK_DIVIDER 2 + +/* dcfg register offsets and values */ +#define DCFG_DEVDISR1_OFFSET 0x70 +#define DCFG_DEVDISR2_OFFSET 0x74 +#define DCFG_DEVDISR3_OFFSET 0x78 +#define DCFG_DEVDISR5_OFFSET 0x80 +#define DCFG_DEVDISR6_OFFSET 0x84 + +#define DCFG_DEVDISR1_SEC (1 << 22) +#define DCFG_DEVDISR3_QBMAIN (1 << 12) +#define DCFG_DEVDISR4_SPI_QSPI (1 << 4 | 1 << 5) +#define DCFG_DEVDISR5_MEM (1 << 0) + +#define DEVDISR1_VALUE 0x0041310c +#define DEVDISR2_VALUE 0x000003ff +#define DEVDISR3_VALUE 0x00013006 +#define DEVDISR4_VALUE 0x0000033e +#define DEVDISR5_VALUE 0x00103300 +#define DEVDISR6_VALUE 0x00000001 + +/* + * pwr mgmt features supported in the soc-specific code: + * value == 0x0, the soc code does not support this feature + * value != 0x0, the soc code supports this feature + */ +#define SOC_CORE_RELEASE 0x1 +#define SOC_CORE_RESTART 0x1 +#define SOC_CORE_OFF 0x1 +#define SOC_CORE_STANDBY 0x1 +#define SOC_CORE_PWR_DWN 0x1 +#define SOC_CLUSTER_STANDBY 0x1 +#define SOC_CLUSTER_PWR_DWN 0x1 +#define SOC_SYSTEM_STANDBY 0x1 +#define SOC_SYSTEM_PWR_DWN 0x1 +#define SOC_SYSTEM_OFF 0x1 +#define SOC_SYSTEM_RESET 0x1 + +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL + +/* Local power state for power domains in Run state */ +#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) +#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + 3, + 4, +}; +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); +void _set_platform_security(void); +#endif + +#endif /* SOC_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c new file mode 100644 index 0000000..b7397ba --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c @@ -0,0 +1,84 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_STATIC_DDR +#error No static value defined +#endif + +static const struct rc_timing rce[] = { + {U(1600), U(8), U(8)}, + {U(1867), U(8), U(8)}, + {U(2134), U(8), U(9)}, + {} +}; + +static const struct board_timing udimm[] = { + {U(0x04), rce, U(0x01020307), U(0x08090b06)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + if (popts->rdimm != 0) { + debug("RDIMM parameters not set.\n"); + return -EINVAL; + } + + ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); + if (ret != 0) { + return ret; + } + + popts->addr_hash = 1; + popts->cpo_sample = U(0x7b); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_60ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) | + DDR_CDR2_VREF_TRAIN_EN | + DDR_CDR2_VREF_RANGE_2; + + return 0; +} + +long long init_ddr(void) +{ + int spd_addr[] = { NXP_SPD_EEPROM0 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL %lu\n", sys.freq_ddr_pll0); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = NUM_OF_DDRC; + info.dimm_on_ctlr = DDRC_NUM_DIMM; + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + erratum_a008850_post(); + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h new file mode 100644 index 0000000..ebd3a26 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h @@ -0,0 +1,81 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +/* + * Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +#define BL2_START NXP_OCRAM_ADDR +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#define BL2_NOLOAD_START NXP_OCRAM_ADDR +#define BL2_NOLOAD_LIMIT BL2_BASE + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +#define BL32_IRQ_SEC_PHY_TIMER 29 +#define BL31_WDOG_SEC 89 + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + + +#endif /* PLAT_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c new file mode 100644 index 0000000..8b3eada --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk new file mode 100644 index 0000000..97ccf26 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk @@ -0,0 +1,31 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters +BOOT_MODE ?= qspi +BOARD := ls1088aqds + +# DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDR_ECC_EN := yes + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x4000000 +NOR_FLASH_SZ := 0x20000000 + +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := qspi \ + sd \ + nor + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1088a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h new file mode 100644 index 0000000..7daf1c0 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h new file mode 100644 index 0000000..0eaafae --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* + * Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c new file mode 100644 index 0000000..c88583f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c @@ -0,0 +1,86 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_STATIC_DDR +#error No static value defined +#endif + +static const struct rc_timing rce[] = { + {U(1600), U(8), U(8)}, + {U(1867), U(8), U(8)}, + {U(2134), U(8), U(9)}, + {} +}; + +static const struct board_timing udimm[] = { + {U(0x04), rce, U(0x01030508), U(0x090b0d06)}, + {U(0x1f), rce, U(0x01030508), U(0x090b0d06)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + if (popts->rdimm != 0) { + debug("RDIMM parameters not set.\n"); + return -EINVAL; + } + + ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); + if (ret != 0) { + return ret; + } + + popts->addr_hash = 1; + popts->cpo_sample = U(0x7b); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_60ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) | + DDR_CDR2_VREF_TRAIN_EN | + DDR_CDR2_VREF_RANGE_2; + + return 0; +} + +long long init_ddr(void) +{ + int spd_addr[] = { NXP_SPD_EEPROM0 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL %lu\n", sys.freq_ddr_pll0); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = NUM_OF_DDRC; + info.dimm_on_ctlr = DDRC_NUM_DIMM; + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + erratum_a008850_post(); + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h new file mode 100644 index 0000000..a6b14fe --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h @@ -0,0 +1,80 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +/* + * Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +#define BL2_START NXP_OCRAM_ADDR +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#define BL2_NOLOAD_START NXP_OCRAM_ADDR +#define BL2_NOLOAD_LIMIT BL2_BASE + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +#define BL32_IRQ_SEC_PHY_TIMER 29 +#define BL31_WDOG_SEC 89 + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#endif /* PLAT_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c new file mode 100644 index 0000000..8b3eada --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk new file mode 100644 index 0000000..6884faf --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk @@ -0,0 +1,30 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters +BOOT_MODE ?= qspi +BOARD := ls1088ardb + +# DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDR_ECC_EN := yes + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x4000000 + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := qspi \ + sd + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1088a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h new file mode 100644 index 0000000..7daf1c0 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h new file mode 100644 index 0000000..af206f9 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h @@ -0,0 +1,15 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c new file mode 100644 index 0000000..5f9f313 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c @@ -0,0 +1,397 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#endif +#include +#include +#include + +static unsigned char _power_domain_tree_desc[NUMBER_OF_CLUSTERS + 2]; +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1044A, LS1044A, 1, 4), + SOC_ENTRY(LS1044AE, LS1044AE, 1, 4), + SOC_ENTRY(LS1048A, LS1048A, 1, 4), + SOC_ENTRY(LS1048AE, LS1048AE, 1, 4), + SOC_ENTRY(LS1084A, LS1084A, 2, 4), + SOC_ENTRY(LS1084AE, LS1084AE, 2, 4), + SOC_ENTRY(LS1088A, LS1088A, 2, 4), + SOC_ENTRY(LS1088AE, LS1088AE, 2, 4), +}; + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, +}; + +/* + * This function dynamically constructs the topology according to + * SoC Flavor and returns it. + */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + _power_domain_tree_desc[0] = 1; + _power_domain_tree_desc[1] = num_clusters; + + for (i = 0; i < _power_domain_tree_desc[1]; i++) { + _power_domain_tree_desc[i + 2] = cores_per_cluster; + } + + + return _power_domain_tree_desc; +} + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1088a_cluster_count); + +/* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + */ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + return CORES_PER_CLUSTER; +} + +/* + * This function returns the total number of cores in the SoC + */ +unsigned int get_tot_num_cores(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return (num_clusters * cores_per_cluster); +} + +/* + * This function returns the PMU IDLE Cluster mask. + */ +unsigned int get_pmu_idle_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return ((1 << num_clusters) - 2); +} + +/* + * This function returns the PMU Flush Cluster mask. + */ +unsigned int get_pmu_flush_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return ((1 << num_clusters) - 2); +} + +/* + * This function returns the PMU IDLE Core mask. + */ +unsigned int get_pmu_idle_core_mask(void) +{ + return ((1 << get_tot_num_cores()) - 2); +} + +#ifdef IMAGE_BL2 + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +void soc_preload_setup(void) +{ + +} + +/* + * This function returns the boot device based on RCW_SRC + */ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src, val; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_TYPE_MASK; + if (val == NOR_16B_VAL) { + src = BOOT_DEVICE_IFC_NOR; + INFO("RCW BOOT SRC is IFC NOR\n"); + } else { + val = rcw_src & RCW_SRC_SERIAL_MASK; + switch (val) { + case QSPI_VAL: + src = BOOT_DEVICE_QSPI; + INFO("RCW BOOT SRC is QSPI\n"); + break; + case SDHC_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + case EMMC_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + default: + src = BOOT_DEVICE_NONE; + } + } + + return src; +} + +/* + * This function sets up access permissions on memory regions + */ +void soc_mem_access(void) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + int i = 0; + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx, index = 1; + + for (dram_idx = 0; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[i].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc400_reg_list(tzc400_reg_list, + dram_idx, index, + info_dram_regions->region[dram_idx].addr, + info_dram_regions->region[dram_idx].size, + NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE); + } + + mem_access_setup(NXP_TZC_ADDR, index, + tzc400_reg_list); +} + +/* + * This function implements soc specific erratum + * This is called before DDR is initialized or MMU is enabled + */ +void soc_early_init(void) +{ + enum boot_device dev; + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + enable_timer_base_to_cluster(NXP_PMU_ADDR); + enable_core_tb(NXP_PMU_ADDR); + + /* + * Use the region(NXP_SD_BLOCK_BUF_ADDR + NXP_SD_BLOCK_BUF_SIZE) + * as dma of sd + */ + dev = get_boot_dev(); + if (dev == BOOT_DEVICE_EMMC) { + mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + MT_DEVICE | MT_RW | MT_NS); + } + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +#endif +#endif + + soc_errata(); + + delay_timer_init(NXP_TIMER_ADDR); + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +} +#else /* !IMAGE_BL2 */ + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* + * Initialize system level generic timer for Socs + */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uintptr_t target_mask_array[PLATFORM_CORE_COUNT]; + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0) + }; + + plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array, + plat_core_pos); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* + * This function initializes the soc from the BL31 module + */ +void soc_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + + /* low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + + /* set platform security policies */ + _set_platform_security(); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +} + +void soc_runtime_setup(void) +{ + +} +#endif /* IMAGE_BL2 */ + +/* + * Function to return the SoC SYS CLK + */ +unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} + +/* + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + */ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + */ + counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF); + + return counter_base_frequency; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def new file mode 100644 index 0000000..25d0847 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def @@ -0,0 +1,87 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a53 + +CACHE_LINE := 6 + +# Set to GIC400 or GIC500 +GIC := GIC500 + +# Set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# Indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 3 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := NS16550 + +NXP_SFP_VER := 3_4 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + + +# OCRAM MAP for BL2 +# Before BL2 +# 0x18000000 - 0x18009fff -> Used by ROM code, (TBD - can it be used for xlat tables) +# 0x1800a000 - 0x1801Cfff -> Reserved for BL2 binary (76 KB) +# 0x1801D000 - 0x1801ffff -> CSF header for BL2 (12 KB) +OCRAM_START_ADDR := 0x18000000 +OCRAM_SIZE := 0x20000 + +CSF_HDR_SZ := 0x3000 + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0xa000 + +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC := 0x1801D000 + +# Location of BL2 on OCRAM +# BL2_BASE=OCRAM_START_ADDR+NXP_ROM_RSVD +BL2_BASE := 0x1800a000 + +# SoC ERRATUM to be enabled +ERRATA_SOC_A008850 := 1 + +# ARM Erratum +ERRATA_A53_855873 := 1 + +# DDR Erratum +ERRATA_DDR_A008511 := 1 +ERRATA_DDR_A009803 := 1 +ERRATA_DDR_A009942 := 1 +ERRATA_DDR_A010165 := 1 + +# Define Endianness of each module +NXP_ESDHC_ENDIANNESS := LE +NXP_SFP_ENDIANNESS := LE +NXP_GPIO_ENDIANNESS := LE +NXP_SNVS_ENDIANNESS := LE +NXP_GUR_ENDIANNESS := LE +NXP_SEC_ENDIANNESS := LE +NXP_DDR_ENDIANNESS := LE +NXP_QSPI_ENDIANNESS := LE + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.mk new file mode 100644 index 0000000..83ac9d0 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.mk @@ -0,0 +1,110 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1088a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH:= plat/nxp/common +PLAT_DRIVERS_PATH:= drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + +# Separate BL2 NOLOAD region (.bss, stack, page tables). need to +# define BL2_NOLOAD_START and BL2_NOLOAD_LIMIT +SEPARATE_BL2_NOLOAD_REGION := 1 + +# get SoC-specific defnitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + +# For Security Features +DISABLE_FUSE_WRITE := 1 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +ifeq (${GENERATE_COT},1) +# Save Keys to be used by DDR FIP image +SAVE_KEYS=1 +endif +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +# Used by create_pbl tool to +# create bl2__sec.pbl image +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + +# Selecting Drivers for SoC +$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +# Selecting PSCI & SIP_SVC support +$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31)) + + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_COMMON_PATH}/soc_errata\ + -I${PLAT_COMMON_PATH}/include\ + -I${PLAT_SOC_PATH}/include + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +# for fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + +# Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/${ARCH}/${SOC}_helpers.S\ + ${PLAT_SOC_PATH}/soc.c + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S \ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + +# Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S new file mode 100644 index 0000000..cc679f2 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S @@ -0,0 +1,1816 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +.section .text, "ax" + +#include + +#include +#include +#include +#include + +#include +#include +#include + +.global soc_init_start +.global soc_init_percpu +.global soc_init_finish +.global _set_platform_security +.global _soc_set_start_addr + +.global _soc_core_release +.global _soc_ck_disabled +.global _soc_core_restart +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off +.global _soc_sys_reset +.global _soc_sys_off +.global _soc_core_prep_stdby +.global _soc_core_entr_stdby +.global _soc_core_exit_stdby +.global _soc_core_prep_pwrdn +.global _soc_core_entr_pwrdn +.global _soc_core_exit_pwrdn +.global _soc_clstr_prep_stdby +.global _soc_clstr_exit_stdby +.global _soc_clstr_prep_pwrdn +.global _soc_clstr_exit_pwrdn +.global _soc_sys_prep_stdby +.global _soc_sys_exit_stdby +.global _soc_sys_prep_pwrdn +.global _soc_sys_pwrdn_wfi +.global _soc_sys_exit_pwrdn + +.equ TZPC_BASE, 0x02200000 +.equ TZPCDECPROT_0_SET_BASE, 0x02200804 +.equ TZPCDECPROT_1_SET_BASE, 0x02200810 +.equ TZPCDECPROT_2_SET_BASE, 0x0220081C + +#define CLUSTER_3_CORES_MASK 0xC0 +#define CLUSTER_3_IN_RESET 1 +#define CLUSTER_3_NORMAL 0 + +/* cluster 3 handling no longer based on frequency, but rather on RCW[850], + * which is bit 18 of RCWSR27 + */ +#define CLUSTER_3_RCW_BIT 0x40000 + +/* retry count for clock-stop acks */ +.equ CLOCK_RETRY_CNT, 800 + +/* disable prefetching in the A72 core */ +#define CPUACTLR_DIS_LS_HW_PRE 0x100000000000000 +#define CPUACTLR_DIS_L2_TLB_PRE 0x200000 + +/* Function starts the initialization tasks of the soc, + * using secondary cores if they are available + * + * Called from C, saving the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + * + * in: + * out: + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11 + */ +func soc_init_start + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + /* make sure the personality has been + * established by releasing cores that + * are marked "to-be-disabled" from reset + */ + bl release_disabled /* 0-9 */ + + /* init the task flags */ + bl _init_task_flags /* 0-1 */ + + /* set SCRATCHRW7 to 0x0 */ + ldr x0, =DCFG_SCRATCHRW7_OFFSET + mov x1, xzr + bl _write_reg_dcfg + +1: + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + ret +endfunc soc_init_start + + +/* Function performs any soc-specific initialization that is needed on + * a per-core basis. + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func soc_init_percpu + stp x4, x30, [sp, #-16]! + + bl plat_my_core_mask + mov x2, x0 /* x2 = core mask */ + + /* Check if this core is marked for prefetch disable + */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data /* 0-1 */ + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A72 /* 0 */ +1: + mov x0, #NXP_PMU_ADDR + bl enable_timer_base_to_cluster + ldp x4, x30, [sp], #16 + ret +endfunc soc_init_percpu + + +/* Function completes the initialization tasks of the soc + * in: + * out: + * uses x0, x1, x2, x3, x4 + */ +func soc_init_finish + stp x4, x30, [sp, #-16]! + + ldp x4, x30, [sp], #16 + ret +endfunc soc_init_finish + + +/* Function sets the security mechanisms in the SoC to implement the + * Platform Security Policy + */ +func _set_platform_security + mov x8, x30 + +#if (!SUPPRESS_TZC) + /* initialize the tzpc */ + bl init_tzpc +#endif + +#if (!SUPPRESS_SEC) + /* initialize secmon */ +#ifdef NXP_SNVS_ENABLED + mov x0, #NXP_SNVS_ADDR + bl init_sec_mon +#endif +#endif + + mov x30, x8 + ret +endfunc _set_platform_security + + +/* Function writes a 64-bit address to bootlocptrh/l + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * uses x0, x1, x2 + */ +func _soc_set_start_addr + /* Get the 64-bit base address of the dcfg block */ + ldr x2, =NXP_DCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register */ + mov x1, x0 + str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register */ + lsr x1, x0, #32 + str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET] + ret +endfunc _soc_set_start_addr + +/* Function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +func _soc_core_release + mov x3, x30 + + ldr x1, =NXP_SEC_REGFILE_ADDR + /* write to CORE_HOLD to tell + * the bootrom that this core is + * expected to run. + */ + str w0, [x1, #CORE_HOLD_OFFSET] + + /* read-modify-write BRRL to release core */ + mov x1, #NXP_RESET_ADDR + ldr w2, [x1, #BRR_OFFSET] + + /* x0 = core mask */ + orr w2, w2, w0 + str w2, [x1, #BRR_OFFSET] + dsb sy + isb + + /* send event */ + sev + isb + + mov x30, x3 + ret +endfunc _soc_core_release + + +/* Function determines if a core is disabled via COREDISABLEDSR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1 + */ +func _soc_ck_disabled + + /* get base addr of dcfg block */ + ldr x1, =NXP_DCFG_ADDR + + /* read COREDISABLEDSR */ + ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET] + + /* test core bit */ + and w0, w1, w0 + + ret +endfunc _soc_ck_disabled + + +/* Part of CPU_ON + * Function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0, x1, x2, x3, x4, x5, x6 + */ +func _soc_core_restart + mov x6, x30 + mov x4, x0 + + /* pgm GICD_CTLR - enable secure grp0 */ + mov x5, #NXP_GICD_ADDR + ldr w2, [x5, #GICD_CTLR_OFFSET] + orr w2, w2, #GICD_CTLR_EN_GRP_0 + str w2, [x5, #GICD_CTLR_OFFSET] + dsb sy + isb + + /* poll on RWP til write completes */ +4: + ldr w2, [x5, #GICD_CTLR_OFFSET] + tst w2, #GICD_CTLR_RWP + b.ne 4b + + /* x4 = core mask lsb + * x5 = gicd base addr + */ + mov x0, x4 + bl get_mpidr_value + + /* x0 = mpidr of target core + * x4 = core mask lsb of target core + * x5 = gicd base addr + */ + + /* generate target list bit */ + and x1, x0, #MPIDR_AFFINITY0_MASK + mov x2, #1 + lsl x2, x2, x1 + + /* get the affinity1 field */ + and x1, x0, #MPIDR_AFFINITY1_MASK + lsl x1, x1, #8 + orr x2, x2, x1 + + /* insert the INTID for SGI15 */ + orr x2, x2, #ICC_SGI0R_EL1_INTID + + /* fire the SGI */ + msr ICC_SGI0R_EL1, x2 + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x6 + ret +endfunc _soc_core_restart + + +/* Part of CPU_OFF + * Function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7 + */ +func _soc_core_prep_off + mov x8, x30 + mov x7, x0 /* x7 = core mask lsb */ + + mrs x1, CORTEX_A72_ECTLR_EL1 + + /* set smp and disable L2 snoops in cpuectlr */ + orr x1, x1, #CPUECTLR_SMPEN_EN + orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH + bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK + bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK + + /* set retention control in cpuectlr */ + bic x1, x1, #CPUECTLR_TIMER_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + msr CORTEX_A72_ECTLR_EL1, x1 + + /* get redistributor rd base addr for this core */ + mov x0, x7 + bl get_gic_rd_base + mov x6, x0 + + /* get redistributor sgi base addr for this core */ + mov x0, x7 + bl get_gic_sgi_base + mov x5, x0 + + /* x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w3, #GICR_ICENABLER0_SGI15 + str w3, [x5, #GICR_ICENABLER0_OFFSET] +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 2b + + /* disable GRP1 interrupts at cpu interface */ + msr ICC_IGRPEN1_EL3, xzr + + /* disable GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* program the redistributor - poll on GICR_CTLR.RWP as needed */ + + /* define SGI 15 as Grp0 - GICR_IGROUPR0 */ + ldr w4, [x5, #GICR_IGROUPR0_OFFSET] + bic w4, w4, #GICR_IGROUPR0_SGI15 + str w4, [x5, #GICR_IGROUPR0_OFFSET] + + /* define SGI 15 as Grp0 - GICR_IGRPMODR0 */ + ldr w3, [x5, #GICR_IGRPMODR0_OFFSET] + bic w3, w3, #GICR_IGRPMODR0_SGI15 + str w3, [x5, #GICR_IGRPMODR0_OFFSET] + + /* set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */ + ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET] + bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK + str w4, [x5, #GICR_IPRIORITYR3_OFFSET] + + /* enable SGI 15 at redistributor - GICR_ISENABLER0 */ + mov w3, #GICR_ISENABLER0_SGI15 + str w3, [x5, #GICR_ISENABLER0_OFFSET] + dsb sy + isb +3: + /* poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 3b + + /* quiesce the debug interfaces */ + mrs x3, osdlr_el1 + orr x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + /* enable grp0 ints */ + mov x3, #ICC_IGRPEN0_EL1_EN + msr ICC_IGRPEN0_EL1, x3 + + /* x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* clear any pending interrupts */ + mvn w1, wzr + str w1, [x5, #GICR_ICPENDR0_OFFSET] + + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 4f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +4: + /* enable the core timer and mask timer interrupt */ + mov x1, #CNTP_CTL_EL0_EN + orr x1, x1, #CNTP_CTL_EL0_IMASK + msr cntp_ctl_el0, x1 + + isb + mov x30, x8 + ret +endfunc _soc_core_prep_off + + +/* Part of CPU_OFF: + * Function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_entr_off + mov x5, x30 + mov x4, x0 + +1: + /* enter low-power state by executing wfi */ + wfi + + /* see if SGI15 woke us up */ + mrs x2, ICC_IAR0_EL1 + mov x3, #ICC_IAR0_EL1_SGI15 + cmp x2, x3 + b.ne 2f + + /* deactivate the intrrupts. */ + msr ICC_EOIR0_EL1, x2 + +2: + /* check if core is turned ON */ + mov x0, x4 + /* Fetched the core state in x0 */ + bl _getCoreState + + cmp x0, #CORE_WAKEUP + b.ne 1b + + /* Reached here, exited the wfi */ + + mov x30, x5 + ret +endfunc _soc_core_entr_off + + +/* Part of CPU_OFF: + * Function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6 + */ +func _soc_core_exit_off + mov x6, x30 + mov x5, x0 + + /* disable forwarding of GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* get redistributor sgi base addr for this core */ + mov x0, x5 + bl get_gic_sgi_base + mov x4, x0 + + /* x4 = gicr sgi base addr + * x5 = core mask + */ + + /* disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w1, #GICR_ICENABLER0_SGI15 + str w1, [x4, #GICR_ICENABLER0_OFFSET] + + /* get redistributor rd base addr for this core */ + mov x0, x5 + bl get_gic_rd_base + mov x4, x0 + +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w2, [x4, #GICR_CTLR_OFFSET] + tst w2, #GICR_CTLR_RWP + b.ne 2b + + /* unlock the debug interfaces */ + mrs x3, osdlr_el1 + bic x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + dsb sy + isb + mov x30, x6 + ret +endfunc _soc_core_exit_off + + +/* Function requests a reset of the entire SOC + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6 + */ +func _soc_sys_reset + mov x6, x30 + + ldr x2, =NXP_RST_ADDR + /* clear the RST_REQ_MSK and SW_RST_REQ */ + + mov w0, #0x00000000 + str w0, [x2, #RSTCNTL_OFFSET] + + /* initiate the sw reset request */ + mov w0, #SW_RST_REQ_INIT + str w0, [x2, #RSTCNTL_OFFSET] + + /* In case this address range is mapped as cacheable, + * flush the write out of the dcaches. + */ + add x2, x2, #RSTCNTL_OFFSET + dc cvac, x2 + dsb st + isb + + /* Function does not return */ + b . +endfunc _soc_sys_reset + + +/* Part of SYSTEM_OFF: + * Function turns off the SoC clocks + * Note: Function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func _soc_sys_off + + /* disable sec, QBman, spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, =DCFG_DEVDISR3_QBMAIN + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* set TPMWAKEMR0 */ + ldr x0, =TPMWAKEMR0_ADDR + mov w1, #0x1 + str w1, [x0] + + /* disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* disable L2 prefetches */ + mrs x0, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_SMPEN_EN + orr x0, x0, #CPUECTLR_TIMER_8TICKS + msr CORTEX_A72_ECTLR_EL1, x0 + isb + + /* disable CCN snoop domain */ + mov x1, #NXP_CCN_HN_F_0_ADDR + ldr x0, =CCN_HN_F_SNP_DMN_CTL_MASK + str x0, [x1, #CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET] +3: + ldr w2, [x1, #CCN_HN_F_SNP_DMN_CTL_OFFSET] + cmp w2, #0x2 + b.ne 3b + + mov x3, #NXP_PMU_ADDR + +4: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, #PMU_IDLE_CORE_MASK + b.ne 4b + + mov w1, #PMU_IDLE_CLUSTER_MASK + str w1, [x3, #PMU_CLAINACTSETR_OFFSET] + +1: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, #PMU_IDLE_CORE_MASK + b.ne 1b + + mov w1, #PMU_FLUSH_CLUSTER_MASK + str w1, [x3, #PMU_CLL2FLUSHSETR_OFFSET] + +2: + ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET] + cmp w1, #PMU_FLUSH_CLUSTER_MASK + b.ne 2b + + mov w1, #PMU_FLUSH_CLUSTER_MASK + str w1, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET] + + mov w1, #PMU_FLUSH_CLUSTER_MASK + str w1, [x3, #PMU_CLSINACTSETR_OFFSET] + + mov x2, #DAIF_SET_MASK + mrs x1, spsr_el1 + orr x1, x1, x2 + msr spsr_el1, x1 + + mrs x1, spsr_el2 + orr x1, x1, x2 + msr spsr_el2, x1 + + /* force the debug interface to be quiescent */ + mrs x0, osdlr_el1 + orr x0, x0, #0x1 + msr osdlr_el1, x0 + + /* invalidate all TLB entries at all 3 exception levels */ + tlbi alle1 + tlbi alle2 + tlbi alle3 + + /* x3 = pmu base addr */ + + /* request lpm20 */ + ldr x0, =PMU_POWMGTCSR_OFFSET + ldr w1, =PMU_POWMGTCSR_VAL + str w1, [x3, x0] + +5: + wfe + b.eq 5b +endfunc _soc_sys_off + + +/* Part of CPU_SUSPEND + * Function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +func _soc_core_entr_stdby + + dsb sy + isb + wfi + + ret +endfunc _soc_core_entr_stdby + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_core_prep_stdby + + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + ret +endfunc _soc_core_prep_stdby + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_core_exit_stdby + + ret +endfunc _soc_core_exit_stdby + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_core_prep_pwrdn + + /* make sure system counter is enabled */ + ldr x2, =NXP_TIMER_ADDR + ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] +1: + + /* enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x1 + + isb + ret +endfunc _soc_core_prep_pwrdn + + +/* Part of CPU_SUSPEND + * Function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +func _soc_core_entr_pwrdn + + /* X0 = core mask lsb */ + + dsb sy + isb + wfi + + ret +endfunc _soc_core_entr_pwrdn + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after power-down state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_core_exit_pwrdn + + ret +endfunc _soc_core_exit_pwrdn + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_clstr_prep_stdby + + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + ret +endfunc _soc_clstr_prep_stdby + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_clstr_exit_stdby + + ret +endfunc _soc_clstr_exit_stdby + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_clstr_prep_pwrdn + + /* make sure system counter is enabled */ + ldr x2, =NXP_TIMER_ADDR + ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] +1: + + /* enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x1 + + isb + ret +endfunc _soc_clstr_prep_pwrdn + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after power-down state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_clstr_exit_pwrdn + + ret +endfunc _soc_clstr_exit_pwrdn + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_sys_prep_stdby + + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + ret +endfunc _soc_sys_prep_stdby + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_sys_exit_stdby + + ret +endfunc _soc_sys_exit_stdby + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_sys_prep_pwrdn + + mrs x1, CORTEX_A72_ECTLR_EL1 + /* make sure the smp bit is set */ + orr x1, x1, #CPUECTLR_SMPEN_MASK + /* set the retention control */ + orr x1, x1, #CPUECTLR_RET_8CLK + /* disable tablewalk prefetch */ + orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH + msr CORTEX_A72_ECTLR_EL1, x1 + isb + + ret +endfunc _soc_sys_prep_pwrdn + + +/* Part of CPU_SUSPEND + * Function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, + * x15, x16, x17, x18, x19, x20, x21, x28 + */ +func _soc_sys_pwrdn_wfi + mov x28, x30 + + /* disable cluster snooping in the CCN-508 */ + ldr x1, =NXP_CCN_HN_F_0_ADDR + ldr x7, [x1, #CCN_HN_F_SNP_DMN_CTL_OFFSET] + mov x6, #CCN_HNF_NODE_COUNT +1: + str x7, [x1, #CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET] + sub x6, x6, #1 + add x1, x1, #CCN_HNF_OFFSET + cbnz x6, 1b + + /* x0 = core mask + * x7 = hnf sdcr + */ + + ldr x1, =NXP_PMU_CCSR_ADDR + ldr x2, =NXP_PMU_DCSR_ADDR + + /* enable the stop-request-override */ + mov x3, #PMU_POWMGTDCR0_OFFSET + mov x4, #POWMGTDCR_STP_OV_EN + str w4, [x2, x3] + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x7 = hnf sdcr + */ + + /* disable prefetching in the A72 core */ + mrs x8, CORTEX_A72_CPUACTLR_EL1 + tst x8, #CPUACTLR_DIS_LS_HW_PRE + b.ne 2f + dsb sy + isb + /* disable data prefetch */ + orr x16, x8, #CPUACTLR_DIS_LS_HW_PRE + /* disable tlb prefetch */ + orr x16, x16, #CPUACTLR_DIS_L2_TLB_PRE + msr CORTEX_A72_CPUACTLR_EL1, x16 + isb + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x7 = hnf sdcr + * x8 = cpuactlr + */ + +2: + /* save hnf-sdcr and cpuactlr to stack */ + stp x7, x8, [sp, #-16]! + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + */ + + /* save the IPSTPCRn registers to stack */ + mov x15, #PMU_IPSTPCR0_OFFSET + ldr w9, [x1, x15] + mov x16, #PMU_IPSTPCR1_OFFSET + ldr w10, [x1, x16] + mov x17, #PMU_IPSTPCR2_OFFSET + ldr w11, [x1, x17] + mov x18, #PMU_IPSTPCR3_OFFSET + ldr w12, [x1, x18] + mov x19, #PMU_IPSTPCR4_OFFSET + ldr w13, [x1, x19] + mov x20, #PMU_IPSTPCR5_OFFSET + ldr w14, [x1, x20] + + stp x9, x10, [sp, #-16]! + stp x11, x12, [sp, #-16]! + stp x13, x14, [sp, #-16]! + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x15 = PMU_IPSTPCR0_OFFSET + * x16 = PMU_IPSTPCR1_OFFSET + * x17 = PMU_IPSTPCR2_OFFSET + * x18 = PMU_IPSTPCR3_OFFSET + * x19 = PMU_IPSTPCR4_OFFSET + * x20 = PMU_IPSTPCR5_OFFSET + */ + + /* load the full clock mask for IPSTPCR0 */ + ldr x3, =DEVDISR1_MASK + /* get the exclusions */ + mov x21, #PMU_IPPDEXPCR0_OFFSET + ldr w4, [x1, x21] + /* apply the exclusions to the mask */ + bic w7, w3, w4 + /* stop the clocks in IPSTPCR0 */ + str w7, [x1, x15] + + /* use same procedure for IPSTPCR1-IPSTPCR5 */ + + /* stop the clocks in IPSTPCR1 */ + ldr x5, =DEVDISR2_MASK + mov x21, #PMU_IPPDEXPCR1_OFFSET + ldr w6, [x1, x21] + bic w8, w5, w6 + str w8, [x1, x16] + + /* stop the clocks in IPSTPCR2 */ + ldr x3, =DEVDISR3_MASK + mov x21, #PMU_IPPDEXPCR2_OFFSET + ldr w4, [x1, x21] + bic w9, w3, w4 + str w9, [x1, x17] + + /* stop the clocks in IPSTPCR3 */ + ldr x5, =DEVDISR4_MASK + mov x21, #PMU_IPPDEXPCR3_OFFSET + ldr w6, [x1, x21] + bic w10, w5, w6 + str w10, [x1, x18] + + /* stop the clocks in IPSTPCR4 + * - exclude the ddr clocks as we are currently executing + * out of *some* memory, might be ddr + * - exclude the OCRAM clk so that we retain any code/data in + * OCRAM + * - may need to exclude the debug clock if we are testing + */ + ldr x3, =DEVDISR5_MASK + mov w6, #DEVDISR5_MASK_ALL_MEM + bic w3, w3, w6 + + mov w5, #POLICY_DEBUG_ENABLE + cbz w5, 3f + mov w6, #DEVDISR5_MASK_DBG + bic w3, w3, w6 +3: + mov x21, #PMU_IPPDEXPCR4_OFFSET + ldr w4, [x1, x21] + bic w11, w3, w4 + str w11, [x1, x19] + + /* stop the clocks in IPSTPCR5 */ + ldr x5, =DEVDISR6_MASK + mov x21, #PMU_IPPDEXPCR5_OFFSET + ldr w6, [x1, x21] + bic w12, w5, w6 + str w12, [x1, x20] + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x7 = IPSTPCR0 + * x8 = IPSTPCR1 + * x9 = IPSTPCR2 + * x10 = IPSTPCR3 + * x11 = IPSTPCR4 + * x12 = IPSTPCR5 + */ + + /* poll until the clocks are stopped in IPSTPACKSR0 */ + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR0_OFFSET +4: + ldr w5, [x1, x21] + cmp w5, w7 + b.eq 5f + sub w4, w4, #1 + cbnz w4, 4b + + /* poll until the clocks are stopped in IPSTPACKSR1 */ +5: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR1_OFFSET +6: + ldr w5, [x1, x21] + cmp w5, w8 + b.eq 7f + sub w4, w4, #1 + cbnz w4, 6b + + /* poll until the clocks are stopped in IPSTPACKSR2 */ +7: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR2_OFFSET +8: + ldr w5, [x1, x21] + cmp w5, w9 + b.eq 9f + sub w4, w4, #1 + cbnz w4, 8b + + /* poll until the clocks are stopped in IPSTPACKSR3 */ +9: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR3_OFFSET +10: + ldr w5, [x1, x21] + cmp w5, w10 + b.eq 11f + sub w4, w4, #1 + cbnz w4, 10b + + /* poll until the clocks are stopped in IPSTPACKSR4 */ +11: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR4_OFFSET +12: + ldr w5, [x1, x21] + cmp w5, w11 + b.eq 13f + sub w4, w4, #1 + cbnz w4, 12b + + /* poll until the clocks are stopped in IPSTPACKSR5 */ +13: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR5_OFFSET +14: + ldr w5, [x1, x21] + cmp w5, w12 + b.eq 15f + sub w4, w4, #1 + cbnz w4, 14b + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x7 = IPSTPCR0 + * x8 = IPSTPCR1 + * x9 = IPSTPCR2 + * x10 = IPSTPCR3 + * x11 = IPSTPCR4 + * x12 = IPSTPCR5 + */ + +15: + mov x3, #NXP_DCFG_ADDR + + /* save the devdisr registers to stack */ + ldr w13, [x3, #DCFG_DEVDISR1_OFFSET] + ldr w14, [x3, #DCFG_DEVDISR2_OFFSET] + ldr w15, [x3, #DCFG_DEVDISR3_OFFSET] + ldr w16, [x3, #DCFG_DEVDISR4_OFFSET] + ldr w17, [x3, #DCFG_DEVDISR5_OFFSET] + ldr w18, [x3, #DCFG_DEVDISR6_OFFSET] + + stp x13, x14, [sp, #-16]! + stp x15, x16, [sp, #-16]! + stp x17, x18, [sp, #-16]! + + /* power down the IP in DEVDISR1 - corresponds to IPSTPCR0 */ + str w7, [x3, #DCFG_DEVDISR1_OFFSET] + + /* power down the IP in DEVDISR2 - corresponds to IPSTPCR1 */ + str w8, [x3, #DCFG_DEVDISR2_OFFSET] + + /* power down the IP in DEVDISR3 - corresponds to IPSTPCR2 */ + str w9, [x3, #DCFG_DEVDISR3_OFFSET] + + /* power down the IP in DEVDISR4 - corresponds to IPSTPCR3 */ + str w10, [x3, #DCFG_DEVDISR4_OFFSET] + + /* power down the IP in DEVDISR5 - corresponds to IPSTPCR4 */ + str w11, [x3, #DCFG_DEVDISR5_OFFSET] + + /* power down the IP in DEVDISR6 - corresponds to IPSTPCR5 */ + str w12, [x3, #DCFG_DEVDISR6_OFFSET] + + /* setup register values for the cache-only sequence */ + mov x4, #NXP_DDR_ADDR + mov x5, #NXP_DDR2_ADDR + mov x6, x11 + mov x7, x17 + ldr x12, =PMU_CLAINACTSETR_OFFSET + ldr x13, =PMU_CLSINACTSETR_OFFSET + ldr x14, =PMU_CLAINACTCLRR_OFFSET + ldr x15, =PMU_CLSINACTCLRR_OFFSET + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x3 = NXP_DCFG_ADDR + * x4 = NXP_DDR_ADDR + * x5 = NXP_DDR2_ADDR + * w6 = IPSTPCR4 + * w7 = DEVDISR5 + * x12 = PMU_CLAINACTSETR_OFFSET + * x13 = PMU_CLSINACTSETR_OFFSET + * x14 = PMU_CLAINACTCLRR_OFFSET + * x15 = PMU_CLSINACTCLRR_OFFSET + */ + + mov x8, #POLICY_DEBUG_ENABLE + cbnz x8, 29f + /* force the debug interface to be quiescent */ + mrs x9, OSDLR_EL1 + orr x9, x9, #0x1 + msr OSDLR_EL1, x9 + + /* enter the cache-only sequence */ +29: + bl final_pwrdown + + /* when we are here, the core has come out of wfi and the + * ddr is back up + */ + + mov x8, #POLICY_DEBUG_ENABLE + cbnz x8, 30f + /* restart the debug interface */ + mrs x9, OSDLR_EL1 + mov x10, #1 + bic x9, x9, x10 + msr OSDLR_EL1, x9 + + /* get saved DEVDISR regs off stack */ +30: + ldp x17, x18, [sp], #16 + ldp x15, x16, [sp], #16 + ldp x13, x14, [sp], #16 + /* restore DEVDISR regs */ + str w18, [x3, #DCFG_DEVDISR6_OFFSET] + str w17, [x3, #DCFG_DEVDISR5_OFFSET] + str w16, [x3, #DCFG_DEVDISR4_OFFSET] + str w15, [x3, #DCFG_DEVDISR3_OFFSET] + str w14, [x3, #DCFG_DEVDISR2_OFFSET] + str w13, [x3, #DCFG_DEVDISR1_OFFSET] + isb + + /* get saved IPSTPCRn regs off stack */ + ldp x13, x14, [sp], #16 + ldp x11, x12, [sp], #16 + ldp x9, x10, [sp], #16 + + /* restore IPSTPCRn regs */ + mov x15, #PMU_IPSTPCR5_OFFSET + str w14, [x1, x15] + mov x16, #PMU_IPSTPCR4_OFFSET + str w13, [x1, x16] + mov x17, #PMU_IPSTPCR3_OFFSET + str w12, [x1, x17] + mov x18, #PMU_IPSTPCR2_OFFSET + str w11, [x1, x18] + mov x19, #PMU_IPSTPCR1_OFFSET + str w10, [x1, x19] + mov x20, #PMU_IPSTPCR0_OFFSET + str w9, [x1, x20] + isb + + /* poll on IPSTPACKCRn regs til IP clocks are restarted */ + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR5_OFFSET +16: + ldr w5, [x1, x15] + and w5, w5, w14 + cbz w5, 17f + sub w4, w4, #1 + cbnz w4, 16b + +17: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR4_OFFSET +18: + ldr w5, [x1, x15] + and w5, w5, w13 + cbz w5, 19f + sub w4, w4, #1 + cbnz w4, 18b + +19: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR3_OFFSET +20: + ldr w5, [x1, x15] + and w5, w5, w12 + cbz w5, 21f + sub w4, w4, #1 + cbnz w4, 20b + +21: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR2_OFFSET +22: + ldr w5, [x1, x15] + and w5, w5, w11 + cbz w5, 23f + sub w4, w4, #1 + cbnz w4, 22b + +23: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR1_OFFSET +24: + ldr w5, [x1, x15] + and w5, w5, w10 + cbz w5, 25f + sub w4, w4, #1 + cbnz w4, 24b + +25: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR0_OFFSET +26: + ldr w5, [x1, x15] + and w5, w5, w9 + cbz w5, 27f + sub w4, w4, #1 + cbnz w4, 26b + +27: + /* disable the stop-request-override */ + mov x8, #PMU_POWMGTDCR0_OFFSET + mov w9, #POWMGTDCR_STP_OV_EN + str w9, [x2, x8] + isb + + /* get hnf-sdcr and cpuactlr off stack */ + ldp x7, x8, [sp], #16 + + /* restore cpuactlr */ + msr CORTEX_A72_CPUACTLR_EL1, x8 + isb + + /* restore snooping in the hnf nodes */ + ldr x9, =NXP_CCN_HN_F_0_ADDR + mov x6, #CCN_HNF_NODE_COUNT +28: + str x7, [x9, #CCN_HN_F_SNP_DMN_CTL_SET_OFFSET] + sub x6, x6, #1 + add x9, x9, #CCN_HNF_OFFSET + cbnz x6, 28b + isb + + mov x30, x28 + ret +endfunc _soc_sys_pwrdn_wfi + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, + */ +func _soc_sys_exit_pwrdn + + mrs x1, CORTEX_A72_ECTLR_EL1 + /* make sure the smp bit is set */ + orr x1, x1, #CPUECTLR_SMPEN_MASK + /* clr the retention control */ + mov x2, #CPUECTLR_RET_8CLK + bic x1, x1, x2 + /* enable tablewalk prefetch */ + mov x2, #CPUECTLR_DISABLE_TWALK_PREFETCH + bic x1, x1, x2 + msr CORTEX_A72_ECTLR_EL1, x1 + isb + + ret +endfunc _soc_sys_exit_pwrdn + + +/* Function will pwrdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: + * x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x3 = NXP_DCFG_ADDR + * x4 = NXP_DDR_ADDR + * x5 = NXP_DDR2_ADDR + * w6 = IPSTPCR4 + * w7 = DEVDISR5 + * x12 = PMU_CLAINACTSETR_OFFSET + * x13 = PMU_CLSINACTSETR_OFFSET + * x14 = PMU_CLAINACTCLRR_OFFSET + * x15 = PMU_CLSINACTCLRR_OFFSET + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16, + * x17, x18 + */ + +/* 4Kb aligned */ +.align 12 +func final_pwrdown + + mov x0, xzr + b touch_line_0 +start_line_0: + mov x0, #1 + /* put ddr controller 1 into self-refresh */ + ldr w8, [x4, #DDR_CFG_2_OFFSET] + orr w8, w8, #CFG_2_FORCE_REFRESH + str w8, [x4, #DDR_CFG_2_OFFSET] + + /* put ddr controller 2 into self-refresh */ + ldr w8, [x5, #DDR_CFG_2_OFFSET] + orr w8, w8, #CFG_2_FORCE_REFRESH + str w8, [x5, #DDR_CFG_2_OFFSET] + + /* stop the clocks in both ddr controllers */ + mov w10, #DEVDISR5_MASK_DDR + mov x16, #PMU_IPSTPCR4_OFFSET + orr w9, w6, w10 + str w9, [x1, x16] + isb + + mov x17, #PMU_IPSTPACKSR4_OFFSET +touch_line_0: + cbz x0, touch_line_1 + +start_line_1: + /* poll IPSTPACKSR4 until + * ddr controller clocks are stopped. + */ +1: + ldr w8, [x1, x17] + and w8, w8, w10 + cmp w8, w10 + b.ne 1b + + /* shut down power to the ddr controllers */ + orr w9, w7, #DEVDISR5_MASK_DDR + str w9, [x3, #DCFG_DEVDISR5_OFFSET] + + /* disable cluster acp ports */ + mov w8, #CLAINACT_DISABLE_ACP + str w8, [x1, x12] + + /* disable skyros ports */ + mov w9, #CLSINACT_DISABLE_SKY + str w9, [x1, x13] + isb + +touch_line_1: + cbz x0, touch_line_2 + +start_line_2: + isb +3: + wfi + + /* if we are here then we are awake + * - bring this device back up + */ + + /* enable skyros ports */ + mov w9, #CLSINACT_DISABLE_SKY + str w9, [x1, x15] + + /* enable acp ports */ + mov w8, #CLAINACT_DISABLE_ACP + str w8, [x1, x14] + isb + + /* bring up the ddr controllers */ + str w7, [x3, #DCFG_DEVDISR5_OFFSET] + isb + str w6, [x1, x16] + isb + + nop +touch_line_2: + cbz x0, touch_line_3 + +start_line_3: + /* poll IPSTPACKSR4 until + * ddr controller clocks are running + */ + mov w10, #DEVDISR5_MASK_DDR +2: + ldr w8, [x1, x17] + and w8, w8, w10 + cbnz w8, 2b + + /* take ddr controller 2 out of self-refresh */ + mov w8, #CFG_2_FORCE_REFRESH + ldr w9, [x5, #DDR_CFG_2_OFFSET] + bic w9, w9, w8 + str w9, [x5, #DDR_CFG_2_OFFSET] + + /* take ddr controller 1 out of self-refresh */ + ldr w9, [x4, #DDR_CFG_2_OFFSET] + bic w9, w9, w8 + str w9, [x4, #DDR_CFG_2_OFFSET] + isb + + nop + nop + nop +touch_line_3: + cbz x0, start_line_0 + + /* execute here after ddr is back up */ + + ret +endfunc final_pwrdown + +/* Function returns CLUSTER_3_NORMAL if the cores of cluster 3 are + * to be handled normally, and it returns CLUSTER_3_IN_RESET if the cores + * are to be held in reset + * in: none + * out: x0 = #CLUSTER_3_NORMAL, cluster 3 treated normal + * x0 = #CLUSTER_3_IN_RESET, cluster 3 cores held in reset + * uses x0, x1, x2 + */ +func cluster3InReset + + /* default return is treat cores normal */ + mov x0, #CLUSTER_3_NORMAL + + /* read RCW_SR27 register */ + mov x1, #NXP_DCFG_ADDR + ldr w2, [x1, #RCW_SR27_OFFSET] + + /* test the cluster 3 bit */ + tst w2, #CLUSTER_3_RCW_BIT + b.eq 1f + + /* if we are here, then the bit was set */ + mov x0, #CLUSTER_3_IN_RESET +1: + ret +endfunc cluster3InReset + + +/* Function checks to see if cores which are to be disabled have been + * released from reset - if not, it releases them + * Note: there may be special handling of cluster 3 cores depending upon the + * sys clk frequency + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 + */ +func release_disabled + mov x9, x30 + + /* check if we need to keep cluster 3 cores in reset */ + bl cluster3InReset /* 0-2 */ + mov x8, x0 + + /* x8 = cluster 3 handling */ + + /* read COREDISABLESR */ + mov x0, #NXP_DCFG_ADDR + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + cmp x8, #CLUSTER_3_IN_RESET + b.ne 4f + + /* the cluster 3 cores are to be held in reset, so remove + * them from the disable mask + */ + bic x4, x4, #CLUSTER_3_CORES_MASK +4: + /* get the number of cpus on this device */ + mov x6, #PLATFORM_CORE_COUNT + + mov x0, #NXP_RESET_ADDR + ldr w5, [x0, #BRR_OFFSET] + + /* load the core mask for the first core */ + mov x7, #1 + + /* x4 = COREDISABLESR + * x5 = BRR + * x6 = loop count + * x7 = core mask bit + */ +2: + /* check if the core is to be disabled */ + tst x4, x7 + b.eq 1f + + /* see if disabled cores have already been released from reset */ + tst x5, x7 + b.ne 5f + + /* if core has not been released, then release it (0-3) */ + mov x0, x7 + bl _soc_core_release + + /* record the core state in the data area (0-3) */ + mov x0, x7 + mov x1, #CORE_STATE_DATA + mov x2, #CORE_DISABLED + bl _setCoreData + +1: + /* see if this is a cluster 3 core */ + mov x3, #CLUSTER_3_CORES_MASK + tst x3, x7 + b.eq 5f + + /* this is a cluster 3 core - see if it needs to be held in reset */ + cmp x8, #CLUSTER_3_IN_RESET + b.ne 5f + + /* record the core state as disabled in the data area (0-3) */ + mov x0, x7 + mov x1, #CORE_STATE_DATA + mov x2, #CORE_DISABLED + bl _setCoreData + +5: + /* decrement the counter */ + subs x6, x6, #1 + b.le 3f + + /* shift the core mask to the next core */ + lsl x7, x7, #1 + /* continue */ + b 2b +3: + cmp x8, #CLUSTER_3_IN_RESET + b.ne 6f + + /* we need to hold the cluster 3 cores in reset, + * so mark them in the COREDISR and COREDISABLEDSR registers as + * "disabled", and the rest of the sw stack will leave them alone + * thinking that they have been disabled + */ + mov x0, #NXP_DCFG_ADDR + ldr w1, [x0, #DCFG_COREDISR_OFFSET] + orr w1, w1, #CLUSTER_3_CORES_MASK + str w1, [x0, #DCFG_COREDISR_OFFSET] + + ldr w2, [x0, #DCFG_COREDISABLEDSR_OFFSET] + orr w2, w2, #CLUSTER_3_CORES_MASK + str w2, [x0, #DCFG_COREDISABLEDSR_OFFSET] + dsb sy + isb + +#if (PSCI_TEST) + /* x0 = NXP_DCFG_ADDR : read COREDISABLESR */ + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + /* read COREDISR */ + ldr w3, [x0, #DCFG_COREDISR_OFFSET] +#endif + +6: + mov x30, x9 + ret + +endfunc release_disabled + + +/* Function setc up the TrustZone Address Space Controller (TZASC) + * in: none + * out: none + * uses x0, x1 + */ +func init_tzpc + + /* set Non Secure access for all devices protected via TZPC */ + + /* decode Protection-0 Set Reg */ + ldr x1, =TZPCDECPROT_0_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* decode Protection-1 Set Reg */ + ldr x1, =TZPCDECPROT_1_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* decode Protection-2 Set Reg */ + ldr x1, =TZPCDECPROT_2_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* entire SRAM as NS */ + /* secure RAM region size Reg */ + ldr x1, =TZPC_BASE + /* 0x00000000 = no secure region */ + mov w0, #0x00000000 + str w0, [x1] + + ret +endfunc init_tzpc + +/* write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +func _write_reg_dcfg + ldr x2, =NXP_DCFG_ADDR + str w1, [x2, x0] + ret +endfunc _write_reg_dcfg + + +/* read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +func _read_reg_dcfg + ldr x2, =NXP_DCFG_ADDR + ldr w1, [x2, x0] + mov w0, w1 + ret +endfunc _read_reg_dcfg + + +/* Function returns an mpidr value for a core, given a core_mask_lsb + * in: x0 = core mask lsb + * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits + * uses x0, x1 + */ +func get_mpidr_value + + /* convert a core mask to an SoC core number */ + clz w0, w0 + mov w1, #31 + sub w0, w1, w0 + + /* get the mpidr core number from the SoC core number */ + mov w1, wzr + tst x0, #1 + b.eq 1f + orr w1, w1, #1 + +1: + /* extract the cluster number */ + lsr w0, w0, #1 + orr w0, w1, w0, lsl #8 + + ret +endfunc get_mpidr_value + + +/* Function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor rd base address for specified core + * uses x0, x1, x2 + */ +func get_gic_rd_base + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + ldr x0, =NXP_GICR_ADDR + mov x1, #GIC_RD_OFFSET + + /* x2 = core number + * loop counter + */ +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret +endfunc get_gic_rd_base + + +/* Function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor sgi base address for specified core + * uses x0, x1, x2 + */ +func get_gic_sgi_base + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + ldr x0, =NXP_GICR_SGI_ADDR + mov x1, #GIC_SGI_OFFSET + + /* loop counter */ +2: + cbz x2, 1f /* x2 = core number */ + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret +endfunc get_gic_sgi_base + +/* Function writes a register in the RESET block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +func _write_reg_reset + ldr x2, =NXP_RESET_ADDR + str w1, [x2, x0] + ret +endfunc _write_reg_reset + + +/* Function reads a register in the RESET block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +func _read_reg_reset + ldr x1, =NXP_RESET_ADDR + ldr w0, [x1, x0] + ret +endfunc _read_reg_reset diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S new file mode 100644 index 0000000..c364dec --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S @@ -0,0 +1,77 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + +.globl plat_secondary_cold_boot_setup +.globl plat_is_my_cpu_primary +.globl plat_reset_handler +.globl platform_mem_init + + +func platform_mem1_init + ret +endfunc platform_mem1_init + + +func platform_mem_init + ret +endfunc platform_mem_init + + +func apply_platform_errata + + ret +endfunc apply_platform_errata + + +func plat_reset_handler + mov x29, x30 + bl apply_platform_errata + +#if defined(IMAGE_BL31) + ldr x0, =POLICY_SMMU_PAGESZ_64K + cbz x0, 1f + /* Set the SMMU page size in the sACR register */ + bl _set_smmu_pagesz_64 +#endif +1: + mov x30, x29 + + ret +endfunc plat_reset_handler + + +/* void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + */ +func plat_secondary_cold_boot_setup + /* lx2160a does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + +/* unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, 0x0 + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S new file mode 100644 index 0000000..9dec3f2 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S @@ -0,0 +1,229 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +.section .text, "ax" + +#include + +#ifndef NXP_COINED_BB +#include +#include +#endif +#include +#ifdef NXP_COINED_BB +#include +#endif + +#include +#include + +#define SDRAM_CFG 0x110 +#define SDRAM_CFG_2 0x114 +#define SDRAM_MD_CNTL 0x120 +#define SDRAM_INTERVAL 0x124 +#define TIMING_CFG_10 0x258 +#define DEBUG_2 0xF04 +#define DEBUG_26 0xF64 +#define DDR_DSR2 0xB24 + +#define DDR_CNTRLR_2 0x2 +#define COUNT_100 1000 + + .globl _soc_sys_warm_reset + .align 12 + +func _soc_sys_warm_reset + mov x3, xzr + b touch_line0 +start_line0: + mov x3, #1 + mov x2, #NUM_OF_DDRC + ldr x1, =NXP_DDR_ADDR +1: + ldr w0, [x1, #SDRAM_CFG] + orr w0, w0, #SDRAM_CFG_MEM_HLT + str w0, [x1, #SDRAM_CFG] +2: + ldr w0, [x1, #DEBUG_2] + and w0, w0, #DDR_DBG_2_MEM_IDLE + cbz w0, 2b + + ldr w0, [x1, #DEBUG_26] + orr w0, w0, #DDR_DEBUG_26_BIT_12 + orr w0, w0, #DDR_DEBUG_26_BIT_13 + orr w0, w0, #DDR_DEBUG_26_BIT_14 +touch_line0: + cbz x3, touch_line1 + + orr w0, w0, #DDR_DEBUG_26_BIT_15 + orr w0, w0, #DDR_DEBUG_26_BIT_16 + str w0, [x1, #DEBUG_26] + + ldr w0, [x1, #SDRAM_CFG_2] + orr w0, w0, #SDRAM_CFG2_FRC_SR + str w0, [x1, #SDRAM_CFG_2] + +3: + ldr w0, [x1, #DDR_DSR2] + orr w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT + str w0, [x1, #DDR_DSR2] + ldr w0, [x1, #DDR_DSR2] + and w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT + cbnz w0, 3b + + ldr w0, [x1, #SDRAM_INTERVAL] + and w0, w0, #SDRAM_INTERVAL_REFINT_CLEAR + str w0, [x1, #SDRAM_INTERVAL] +touch_line1: + cbz x3, touch_line2 + + ldr w0, [x1, #SDRAM_MD_CNTL] + orr w0, w0, #MD_CNTL_CKE(1) + orr w0, w0, #MD_CNTL_MD_EN + str w0, [x1, #SDRAM_MD_CNTL] + + ldr w0, [x1, #TIMING_CFG_10] + orr w0, w0, #DDR_TIMING_CFG_10_T_STAB + str w0, [x1, #TIMING_CFG_10] + + ldr w0, [x1, #SDRAM_CFG_2] + and w0, w0, #SDRAM_CFG2_FRC_SR_CLEAR + str w0, [x1, #SDRAM_CFG_2] + +4: + ldr w0, [x1, #DDR_DSR2] + and w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT + cbz w0, 4b + nop +touch_line2: + cbz x3, touch_line3 + + ldr w0, [x1, #DEBUG_26] + orr w0, w0, #DDR_DEBUG_26_BIT_25 + and w0, w0, #DDR_DEBUG_26_BIT_24_CLEAR + str w0, [x1, #DEBUG_26] + + cmp x2, #DDR_CNTRLR_2 + b.ne 5f + ldr x1, =NXP_DDR2_ADDR + mov x2, xzr + b 1b + +5: + mov x5, xzr +6: + add x5, x5, #1 + cmp x5, #COUNT_100 + b.ne 6b + nop +touch_line3: + cbz x3, touch_line4 +#ifdef NXP_COINED_BB + ldr x1, =NXP_SNVS_ADDR + ldr w0, [x1, #NXP_APP_DATA_LP_GPR_OFFSET] + + /* On Warm Boot is enabled, then zeroth bit + * of SNVS LP GPR register 0 will used + * to save the status of warm-reset as a cause. + */ + orr w0, w0, #(1 << NXP_LPGPR_ZEROTH_BIT) + + /* write back */ + str w0, [x1, #NXP_APP_DATA_LP_GPR_OFFSET] + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +touch_line4: + cbz x3, touch_line6 +#elif !(ERLY_WRM_RST_FLG_FLSH_UPDT) + ldr x1, =NXP_FLEXSPI_ADDR + ldr w0, [x1, #FSPI_IPCMD] + orr w0, w0, #FSPI_IPCMD_TRG_MASK + str w0, [x1, #FSPI_IPCMD] +7: + ldr w0, [x1, #FSPI_INTR] + and w0, w0, #FSPI_INTR_IPCMDDONE_MASK + cmp w0, #0 + b.eq 7b + + ldr w0, [x1, #FSPI_IPTXFCR] + orr w0, w0, #FSPI_IPTXFCR_CLR + str w0, [x1, #FSPI_IPTXFCR] + + ldr w0, [x1, #FSPI_INTR] + orr w0, w0, #FSPI_INTR_IPCMDDONE_MASK + str w0, [x1, #FSPI_INTR] + nop +touch_line4: + cbz x3, touch_line5 + /* flexspi driver has an api + * is_flash_busy(). + * Impelementation of the api will not + * fit-in in 1 cache line. + * instead a nop-cycles are introduced to + * simulate the wait time for flash write + * completion. + * + * Note: This wait time varies from flash to flash. + */ + + mov x0, #FLASH_WR_COMP_WAIT_BY_NOP_COUNT +8: + sub x0, x0, #1 + nop + cmp x0, #0 + b.ne 8b + nop + nop + nop + nop + nop + nop + nop + nop + nop +touch_line5: + cbz x3, touch_line6 +#endif + ldr x2, =NXP_RST_ADDR + /* clear the RST_REQ_MSK and SW_RST_REQ */ + mov w0, #0x00000000 + str w0, [x2, #RSTCNTL_OFFSET] + + /* initiate the sw reset request */ + mov w0, #SW_RST_REQ_INIT + str w0, [x2, #RSTCNTL_OFFSET] + + /* In case this address range is mapped as cacheable, + * flush the write out of the dcaches. + */ + add x2, x2, #RSTCNTL_OFFSET + dc cvac, x2 + dsb st + isb + + /* Function does not return */ + b . + nop + nop + nop + nop + nop + nop + nop +touch_line6: + cbz x3, start_line0 + +endfunc _soc_sys_warm_reset diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_fip.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_fip.mk new file mode 100644 index 0000000..f14a9e8 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_fip.mk @@ -0,0 +1,97 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +DDR_PHY_BIN_PATH ?= ./ddr-phy-binary/lx2160a + +ifeq (${DDR_IMEM_UDIMM_1D},) + DDR_IMEM_UDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_pmu_train_imem.bin +endif + +ifeq (${DDR_IMEM_UDIMM_2D},) + DDR_IMEM_UDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_2d_pmu_train_imem.bin +endif + +ifeq (${DDR_DMEM_UDIMM_1D},) + DDR_DMEM_UDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_pmu_train_dmem.bin +endif + +ifeq (${DDR_DMEM_UDIMM_2D},) + DDR_DMEM_UDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_2d_pmu_train_dmem.bin +endif + +ifeq (${DDR_IMEM_RDIMM_1D},) + DDR_IMEM_RDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm_pmu_train_imem.bin +endif + +ifeq (${DDR_IMEM_RDIMM_2D},) + DDR_IMEM_RDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm2d_pmu_train_imem.bin +endif + +ifeq (${DDR_DMEM_RDIMM_1D},) + DDR_DMEM_RDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm_pmu_train_dmem.bin +endif + +ifeq (${DDR_DMEM_RDIMM_2D},) + DDR_DMEM_RDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm2d_pmu_train_dmem.bin +endif + +$(shell mkdir -p '${BUILD_PLAT}') + +ifeq (${DDR_FIP_NAME},) +ifeq (${TRUSTED_BOARD_BOOT},1) + DDR_FIP_NAME := ddr_fip_sec.bin +else + DDR_FIP_NAME := ddr_fip.bin +endif +endif + +ifneq (${TRUSTED_BOARD_BOOT},1) + +DDR_FIP_ARGS += --ddr-immem-udimm-1d ${DDR_IMEM_UDIMM_1D} \ + --ddr-immem-udimm-2d ${DDR_IMEM_UDIMM_2D} \ + --ddr-dmmem-udimm-1d ${DDR_DMEM_UDIMM_1D} \ + --ddr-dmmem-udimm-2d ${DDR_DMEM_UDIMM_2D} \ + --ddr-immem-rdimm-1d ${DDR_IMEM_RDIMM_1D} \ + --ddr-immem-rdimm-2d ${DDR_IMEM_RDIMM_2D} \ + --ddr-dmmem-rdimm-1d ${DDR_DMEM_RDIMM_1D} \ + --ddr-dmmem-rdimm-2d ${DDR_DMEM_RDIMM_2D} +endif + + +ifeq (${TRUSTED_BOARD_BOOT},1) +ifeq (${MBEDTLS_DIR},) +include plat/nxp/soc-lx2160a/ddr_sb.mk +else +include plat/nxp/soc-lx2160a/ddr_tbbr.mk + +# Variables for use with Certificate Generation Tool +CRTTOOLPATH ?= tools/cert_create +CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT} + +ifneq (${GENERATE_COT},0) +ddr_certificates: ${DDR_CRT_DEPS} ${CRTTOOL} + ${Q}${CRTTOOL} ${DDR_CRT_ARGS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @echo "DDR certificates can be found in ${BUILD_PLAT}" + @${ECHO_BLANK_LINE} +endif +endif +endif + +# Variables for use with Firmware Image Package +FIPTOOLPATH ?= tools/fiptool +FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT} + +${BUILD_PLAT}/${DDR_FIP_NAME}: ${DDR_FIP_DEPS} ${FIPTOOL} + $(eval ${CHECK_DDR_FIP_CMD}) + ${Q}${FIPTOOL} create ${DDR_FIP_ARGS} $@ + ${Q}${FIPTOOL} info $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +fip_ddr: ${BUILD_PLAT}/${DDR_FIP_NAME} diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_sb.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_sb.mk new file mode 100644 index 0000000..c11651e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_sb.mk @@ -0,0 +1,43 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${TRUSTED_BOARD_BOOT},0) + +ifeq (${GENERATE_COT},0) + +DDR_FIP_ARGS += --ddr-immem-udimm-1d ${DDR_IMEM_UDIMM_1D}.sb \ + --ddr-immem-udimm-2d ${DDR_IMEM_UDIMM_2D}.sb \ + --ddr-dmmem-udimm-1d ${DDR_DMEM_UDIMM_1D}.sb \ + --ddr-dmmem-udimm-2d ${DDR_DMEM_UDIMM_2D}.sb \ + --ddr-immem-rdimm-1d ${DDR_IMEM_RDIMM_1D}.sb \ + --ddr-immem-rdimm-2d ${DDR_IMEM_RDIMM_2D}.sb \ + --ddr-dmmem-rdimm-1d ${DDR_DMEM_RDIMM_1D}.sb \ + --ddr-dmmem-rdimm-2d ${DDR_DMEM_RDIMM_2D}.sb +endif + +UDIMM_DEPS = ${DDR_IMEM_UDIMM_1D}.sb ${DDR_IMEM_UDIMM_2D}.sb ${DDR_DMEM_UDIMM_1D}.sb ${DDR_DMEM_UDIMM_2D}.sb +RDIMM_DEPS = ${DDR_IMEM_RDIMM_1D}.sb ${DDR_IMEM_RDIMM_2D}.sb ${DDR_DMEM_RDIMM_1D}.sb ${DDR_DMEM_RDIMM_2D}.sb +DDR_FIP_DEPS += ${UDIMM_DEPS} +DDR_FIP_DEPS += ${RDIMM_DEPS} + +# Max Size of CSF header (CSF_HDR_SZ = 0x3000). +# Image will be appended at this offset of the header. +# Path to CST directory is required to generate the CSF header, +# and prepend it to image before fip image gets generated +ifeq (${CST_DIR},) + $(error Error: CST_DIR not set) +endif + +ifeq (${DDR_INPUT_FILE},) +DDR_INPUT_FILE:= drivers/nxp/auth/csf_hdr_parser/${CSF_FILE} +endif + +%.sb: % + @echo " Generating CSF Header for $@ $<" + $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \ + --app $< ${DDR_INPUT_FILE} + +endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_tbbr.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_tbbr.mk new file mode 100644 index 0000000..deb475b --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_tbbr.mk @@ -0,0 +1,95 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# This file defines the keys and certificates that must be created to establish +# a Chain of Trust for the DDR FW. These definitions include the +# command line options passed to the cert_create and fiptool commands for DDR FW. +# A DDR FW key is used for signing the DDR Firmware. The DDR key is authenticated +# by the Trusted World Key. Two content certificates are created: +# For DDR RDIMM Images [ signed by DDR FW Key] +# For DDR UDIMM Images [ signed by DDR FW Key] +# +# Expected environment: +# +# BUILD_PLAT: output directory +# +# Build options added by this file: +# +# KEY_ALG +# KEY_SIZE +# TRUSTED_WORLD_KEY +# NON_TRUSTED_WORLD_KEY +# + +# Copy the tbbr.mk from PLAT_TOOL_PATH/cert_create_helper +# to the ${PLAT_DIR}. So that cert_create is enabled +# to create certificates for DDR +$(shell cp ${PLAT_TOOL_PATH}/cert_create_helper/cert_create_tbbr.mk ${PLAT_DIR}) + +# Certificate generation tool default parameters +DDR_FW_CERT := ${BUILD_PLAT}/ddr_fw_key_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,DDR_)) + +$(shell mkdir -p '${BUILD_PLAT}') + +ifeq (${DDR_KEY},) +DDR_KEY=${BUILD_PLAT}/ddr.pem +endif + +ifeq (${TRUSTED_KEY_CERT},) +$(info Generating: Trusted key certificate as part of DDR cert creation) +TRUSTED_KEY_CERT := ${BUILD_PLAT}/trusted_key.crt +$(eval $(call TOOL_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert,)) +$(eval $(call TOOL_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert,,DDR_)) +else +$(info Using: Trusted key certificate as part of DDR cert creation) +DDR_FIP_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT} +endif + +# 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,DDR_))) +$(if ${KEY_SIZE},$(eval $(call CERT_ADD_CMD_OPT,${KEY_SIZE},--key-size,DDR_))) +$(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg,DDR_))) +$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,DDR_))) +$(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key,DDR_))) +$(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key, DDR_))) + +# Add the DDR CoT (key cert + img cert) +$(if ${DDR_KEY},$(eval $(call CERT_ADD_CMD_OPT,${DDR_KEY},--ddr-fw-key,DDR_))) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_fw_key.crt,--ddr-fw-key-cert,,DDR_)) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_udimm_fw_content.crt,--ddr-udimm-fw-cert,,DDR_)) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_rdimm_fw_content.crt,--ddr-rdimm-fw-cert,,DDR_)) + +$(eval $(call TOOL_ADD_IMG,DDR_IMEM_UDIMM_1D,--ddr-immem-udimm-1d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_IMEM_UDIMM_2D,--ddr-immem-udimm-2d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_DMEM_UDIMM_1D,--ddr-dmmem-udimm-1d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_DMEM_UDIMM_2D,--ddr-dmmem-udimm-2d,DDR_)) + +$(eval $(call TOOL_ADD_IMG,DDR_IMEM_RDIMM_1D,--ddr-immem-rdimm-1d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_IMEM_RDIMM_2D,--ddr-immem-rdimm-2d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_DMEM_RDIMM_1D,--ddr-dmmem-rdimm-1d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_DMEM_RDIMM_2D,--ddr-dmmem-rdimm-2d,DDR_)) + +DDR_FIP_DEPS += ddr_certificates + +# Process TBB related flags +ifneq (${GENERATE_COT},0) + # Common cert_create options + ifneq (${CREATE_KEYS},0) + $(eval DDR_CRT_ARGS += -n) + ifneq (${SAVE_KEYS},0) + $(eval DDR_CRT_ARGS += -k) + endif + endif +endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h new file mode 100644 index 0000000..7cc4a03 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h @@ -0,0 +1,141 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _SOC_H +#define _SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include +#include +#include + + +#define NUM_DRAM_REGIONS 3 +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */ + +#define NXP_DRAM1_ADDR 0x2080000000 +#define NXP_DRAM1_MAX_SIZE 0x1F80000000 /* 126 G */ + +#define NXP_DRAM2_ADDR 0x6000000000 +#define NXP_DRAM2_MAX_SIZE 0x2000000000 /* 128G */ + +/*DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +#define DDR_PLL_FIX +#define NXP_DDR_PHY1_ADDR 0x01400000 +#define NXP_DDR_PHY2_ADDR 0x01600000 + +#if defined(IMAGE_BL31) +#define LS_SYS_TIMCTL_BASE 0x2890000 + +#ifdef LS_SYS_TIMCTL_BASE +#define PLAT_LS_NSTIMER_FRAME_ID 0 +#define LS_CONFIG_CNTACR 1 +#endif +#endif + +/* Start: Macros used by soc.c: get_boot_dev */ +#define PORSR1_RCW_MASK 0x07800000 +#define PORSR1_RCW_SHIFT 23 + +#define SDHC1_VAL 0x8 +#define SDHC2_VAL 0x9 +#define I2C1_VAL 0xa +#define FLEXSPI_NAND2K_VAL 0xc +#define FLEXSPI_NAND4K_VAL 0xd +#define FLEXSPI_NOR 0xf +/* End: Macros used by soc.c: get_boot_dev */ + +/* SVR Definition (not include major and minor rev) */ +#define SVR_LX2160A 0x873601 +#define SVR_LX2120A 0x873621 +#define SVR_LX2080A 0x873603 + +/* Number of cores in platform */ +/* Used by common code for array initialization */ +#define NUMBER_OF_CLUSTERS 8 +#define CORES_PER_CLUSTER 2 +#define PLATFORM_CORE_COUNT NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER + +/* + * Required LS standard platform porting definitions + * for CCN-508 + */ +#define PLAT_CLUSTER_TO_CCN_ID_MAP 11, 15, 27, 31, 12, 28, 16, 0 +#define PLAT_6CLUSTER_TO_CCN_ID_MAP 11, 15, 27, 31, 12, 28 + + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40) + +/* Clock Divisors */ +#define NXP_PLATFORM_CLK_DIVIDER 2 +#define NXP_UART_CLK_DIVIDER 4 + +/* Start: Macros used by lx2160a.S */ +#define MPIDR_AFFINITY0_MASK 0x00FF +#define MPIDR_AFFINITY1_MASK 0xFF00 +#define CPUECTLR_DISABLE_TWALK_PREFETCH 0x4000000000 +#define CPUECTLR_INS_PREFETCH_MASK 0x1800000000 +#define CPUECTLR_DAT_PREFETCH_MASK 0x0300000000 +#define CPUECTLR_RET_8CLK 0x2 +#define OSDLR_EL1_DLK_LOCK 0x1 +#define CNTP_CTL_EL0_EN 0x1 +#define CNTP_CTL_EL0_IMASK 0x2 +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 +/* End: Macros used by lx2160a.S */ + +/* Start: Macros used by lib/psci files */ +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +/* End: Macros used by lib/psci files */ + +/* 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. + * + * CACHE_WRITEBACK_GRANULE is defined in soc.def + * + * One cache line needed for bakery locks on ARM platforms + */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +#ifndef WDOG_RESET_FLAG +#define WDOG_RESET_FLAG DEFAULT_SET_VALUE +#endif + +#ifndef WARM_BOOT_SUCCESS +#define WARM_BOOT_SUCCESS DEFAULT_SET_VALUE +#endif + +#ifndef __ASSEMBLER__ + +void set_base_freq_CNTFID0(void); +void soc_init_start(void); +void soc_init_finish(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); +void _set_platform_security(void); + +#endif + +#endif /* _SOC_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c new file mode 100644 index 0000000..d44733c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c @@ -0,0 +1,355 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "plat_common.h" +#include + +#ifdef CONFIG_STATIC_DDR + +const struct ddr_cfg_regs static_3200 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFFAA0018), + .timing_cfg[1] = U(0x646A8844), + .timing_cfg[2] = U(0x00058022), + .timing_cfg[3] = U(0x13622100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x07401400), + .timing_cfg[7] = U(0x3BB00000), + .timing_cfg[8] = U(0x0944AC00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010C50), + .sdram_mode[1] = U(0x00280400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x10240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x30C00000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct ddr_cfg_regs static_2900 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFF990018), + .timing_cfg[1] = U(0x4F4A4844), + .timing_cfg[2] = U(0x0005601F), + .timing_cfg[3] = U(0x125F2100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x07401400), + .timing_cfg[7] = U(0x3AA00000), + .timing_cfg[8] = U(0x09449B00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010C50), + .sdram_mode[1] = U(0x00280400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x10240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x2C2E0000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct ddr_cfg_regs static_2600 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFF880018), + .timing_cfg[1] = U(0x2A24F444), + .timing_cfg[2] = U(0x007141DC), + .timing_cfg[3] = U(0x125B2100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x06401400), + .timing_cfg[7] = U(0x28800000), + .timing_cfg[8] = U(0x07338A00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010A70), + .sdram_mode[1] = U(0x00200400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x0C240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x279C0000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct dimm_params static_dimm = { + .rdimm = U(0), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .n_ranks = U(2), + .device_width = U(8), + .mirrored_dimm = U(1), +}; + +/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */ +unsigned long long board_static_ddr(struct ddr_info *priv) +{ + (void)memcpy(&priv->ddr_reg, &static_2900, sizeof(static_2900)); + (void)memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm)); + priv->conf.cs_on_dimm[0] = 0x3; + ddr_board_options(priv); + compute_ddr_phy(priv); + + return ULL(0x400000000); +} + +#elif defined(CONFIG_DDR_NODIMM) +/* + * Sample code to bypass reading SPD. This is a sample, not recommended + * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1. + */ + +const struct dimm_params ddr_raw_timing = { + .n_ranks = U(2), + .rank_density = U(4294967296u), + .capacity = U(8589934592u), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .device_width = U(8), + .die_density = U(0x4), + .rdimm = U(0), + .mirrored_dimm = U(1), + .n_row_addr = U(15), + .n_col_addr = U(10), + .bank_addr_bits = U(0), + .bank_group_bits = U(2), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 750, + .tckmax_ps = 1600, + .caslat_x = U(0x00FFFC00), + .taa_ps = 13750, + .trcd_ps = 13750, + .trp_ps = 13750, + .tras_ps = 32000, + .trc_ps = 457500, + .twr_ps = 15000, + .trfc1_ps = 260000, + .trfc2_ps = 160000, + .trfc4_ps = 110000, + .tfaw_ps = 21000, + .trrds_ps = 3000, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = U(7800000), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, + struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; /* Modify accordingly */ + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */ + return 0x5; +} +#endif /* CONFIG_DDR_NODIMM */ + +int ddr_board_options(struct ddr_info *priv) +{ + struct memctl_opt *popts = &priv->opt; + const struct ddr_conf *conf = &priv->conf; + + popts->vref_dimm = U(0x24); /* range 1, 83.4% */ + popts->rtt_override = 0; + popts->rtt_park = U(240); + popts->otf_burst_chop_en = 0; + popts->burst_length = U(DDR_BL8); + popts->trwt_override = U(1); + popts->bstopre = U(0); /* auto precharge */ + popts->addr_hash = 1; + + /* Set ODT impedance on PHY side */ + switch (conf->cs_on_dimm[1]) { + case 0xc: /* Two slots dual rank */ + case 0x4: /* Two slots single rank, not valid for interleaving */ + popts->trwt = U(0xf); + popts->twrt = U(0x7); + popts->trrt = U(0x7); + popts->twwt = U(0x7); + popts->vref_phy = U(0x6B); /* 83.6% */ + popts->odt = U(60); + popts->phy_tx_impedance = U(28); + break; + case 0: /* One slot used */ + default: + popts->trwt = U(0x3); + popts->twrt = U(0x3); + popts->trrt = U(0x3); + popts->twwt = U(0x3); + popts->vref_phy = U(0x60); /* 75% */ + popts->odt = U(48); + popts->phy_tx_impedance = U(28); + break; + } + + return 0; +} + +#ifdef NXP_WARM_BOOT +long long init_ddr(uint32_t wrm_bt_flg) +#else +long long init_ddr(void) +#endif +{ + int spd_addr[] = {0x51U, 0x52U, 0x53U, 0x54U}; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys) == 1) { + ERROR("System clocks are not set.\n"); + panic(); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(info)); + + /* Set two DDRC. Unused DDRC will be removed automatically. */ + info.num_ctlrs = NUM_OF_DDRC; + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + info.ddr[1] = (void *)NXP_DDR2_ADDR; + info.phy[0] = (void *)NXP_DDR_PHY1_ADDR; + info.phy[1] = (void *)NXP_DDR_PHY2_ADDR; + info.clk = get_ddr_freq(&sys, 0); + info.img_loadr = load_img; + info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER; + if (info.clk == 0) { + info.clk = get_ddr_freq(&sys, 1); + } + info.dimm_on_ctlr = DDRC_NUM_DIMM; + + info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED; +#ifdef NXP_WARM_BOOT + info.warm_boot_flag = DDR_COLD_BOOT; + if (wrm_bt_flg != 0U) { + info.warm_boot_flag = DDR_WARM_BOOT; + } else { + info.warm_boot_flag = DDR_COLD_BOOT; + } +#endif + + dram_size = dram_init(&info +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , NXP_CCN_HN_F_0_ADDR +#endif + ); + + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h new file mode 100644 index 0000000..f480f92 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h @@ -0,0 +1,105 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +#include +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#if defined(IMAGE_BL31) +#define LS_SYS_TIMCTL_BASE 0x2890000 +#define PLAT_LS_NSTIMER_FRAME_ID 0 +#define LS_CONFIG_CNTACR 1 +#endif + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x8000) +#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) + +#ifdef SD_BOOT +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) +#else +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#endif + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 3 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 2 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +#define BL31_WDOG_SEC 89 + +#define BL31_NS_WDOG_WS1 108 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define NXP_IRQ_SEC_SGI_7 15 + +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c new file mode 100644 index 0000000..b00adb5 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk new file mode 100644 index 0000000..226b22b --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk @@ -0,0 +1,51 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= flexspi_nor +BOARD ?= lx2160aqds +POVDD_ENABLE := no +NXP_COINED_BB := no + + # DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDRC_NUM_CS := 2 +DDR_ECC_EN := yes + #enable address decoding feature +DDR_ADDR_DEC := yes +APPLY_MAX_CDD := yes + +# DDR Errata +ERRATA_DDR_A011396 := 1 +ERRATA_DDR_A050450 := 1 + + # On-Board Flash Details +FLASH_TYPE := MT35XU512A +XSPI_FLASH_SZ := 0x10000000 +NXP_XSPI_NOR_UNIT_SIZE := 0x20000 +BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000 +# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This +# config is enabled for future use cases. +FSPI_ERASE_4K := 0 + +# Platform specific features. +WARM_BOOT := yes + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := flexspi_nor \ + sd \ + emmc + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-lx2160a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h new file mode 100644 index 0000000..5fa774e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include "plat_def.h" +#include "plat_default_def.h" + +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h new file mode 100644 index 0000000..05d23e2 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Following defines affect the PLATFORM SECURITY POLICY */ + +/* set this to 0x0 if the platform is not using/responding to ECC errors + * set this to 0x1 if ECC is being used (we have to do some init) + */ +#define POLICY_USING_ECC 0x0 + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +/* + * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I + * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7 + * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23 + */ +#define POLICY_PERF_WRIOP 0 + +/* + * set this to '1' if the debug clocks need to remain enabled during + * system entry to low-power (LPM20) - this should only be necessary + * for testing and NEVER set for normal production + */ +#define POLICY_DEBUG_ENABLE 0 + + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c new file mode 100644 index 0000000..8669b1d --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c @@ -0,0 +1,212 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "plat_common.h" +#include + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0xA8050322), + .cs[1].config = U(0x80000322), + .cs[0].bnds = U(0x3FF), + .cs[1].bnds = U(0x3FF), + .sdram_cfg[0] = U(0xE5044000), + .sdram_cfg[1] = U(0x401011), + .timing_cfg[0] = U(0xFF550018), + .timing_cfg[1] = U(0xBAB48C42), + .timing_cfg[2] = U(0x48C111), + .timing_cfg[3] = U(0x10C1000), + .timing_cfg[4] = U(0x2), + .timing_cfg[5] = U(0x3401400), + .timing_cfg[7] = U(0x13300000), + .timing_cfg[8] = U(0x2114600), + .sdram_mode[0] = U(0x6010210), + .sdram_mode[8] = U(0x500), + .sdram_mode[9] = U(0x4240000), + .interval = U(0x18600000), + .data_init = U(0xDEADBEEF), + .zq_cntl = U(0x8A090705), +}; + +const struct dimm_params static_dimm = { + .rdimm = U(0), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .n_ranks = U(2), + .device_width = U(8), + .mirrored_dimm = U(1), +}; + +/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */ +unsigned long long board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm)); + priv->conf.cs_on_dimm[0] = 0x3; + ddr_board_options(priv); + compute_ddr_phy(priv); + + return ULL(0x400000000); +} + +#elif defined(CONFIG_DDR_NODIMM) +/* + * Sample code to bypass reading SPD. This is a sample, not recommended + * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1. + */ + +const struct dimm_params ddr_raw_timing = { + .n_ranks = U(2), + .rank_density = U(4294967296u), + .capacity = U(8589934592u), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .device_width = U(8), + .die_density = U(0x4), + .rdimm = U(0), + .mirrored_dimm = U(1), + .n_row_addr = U(15), + .n_col_addr = U(10), + .bank_addr_bits = U(0), + .bank_group_bits = U(2), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 750, + .tckmax_ps = 1600, + .caslat_x = U(0x00FFFC00), + .taa_ps = 13750, + .trcd_ps = 13750, + .trp_ps = 13750, + .tras_ps = 32000, + .trc_ps = 457500, + .twr_ps = 15000, + .trfc1_ps = 260000, + .trfc2_ps = 160000, + .trfc4_ps = 110000, + .tfaw_ps = 21000, + .trrds_ps = 3000, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = U(7800000), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, + struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; /* Modify accordingly */ + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */ + return 0x5; +} +#endif /* CONFIG_DDR_NODIMM */ + +int ddr_board_options(struct ddr_info *priv) +{ + struct memctl_opt *popts = &priv->opt; + const struct ddr_conf *conf = &priv->conf; + + popts->vref_dimm = U(0x24); /* range 1, 83.4% */ + popts->rtt_override = 0; + popts->rtt_park = U(240); + popts->otf_burst_chop_en = 0; + popts->burst_length = U(DDR_BL8); + popts->trwt_override = U(1); + popts->bstopre = U(0); /* auto precharge */ + popts->addr_hash = 1; + + /* Set ODT impedance on PHY side */ + switch (conf->cs_on_dimm[1]) { + case 0xc: /* Two slots dual rank */ + case 0x4: /* Two slots single rank, not valid for interleaving */ + popts->trwt = U(0xf); + popts->twrt = U(0x7); + popts->trrt = U(0x7); + popts->twwt = U(0x7); + popts->vref_phy = U(0x6B); /* 83.6% */ + popts->odt = U(60); + popts->phy_tx_impedance = U(28); + break; + case 0: /* One slot used */ + default: + popts->trwt = U(0x3); + popts->twrt = U(0x3); + popts->trrt = U(0x3); + popts->twwt = U(0x3); + popts->vref_phy = U(0x60); /* 75% */ + popts->odt = U(48); + popts->phy_tx_impedance = U(28); + break; + } + + return 0; +} + +long long init_ddr(void) +{ + int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys) != 0) { + ERROR("System clocks are not set\n"); + panic(); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(info)); + + /* Set two DDRC. Unused DDRC will be removed automatically. */ + info.num_ctlrs = NUM_OF_DDRC; + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + info.ddr[1] = (void *)NXP_DDR2_ADDR; + info.phy[0] = (void *)NXP_DDR_PHY1_ADDR; + info.phy[1] = (void *)NXP_DDR_PHY2_ADDR; + info.clk = get_ddr_freq(&sys, 0); + info.img_loadr = load_img; + info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER; + if (info.clk == 0) { + info.clk = get_ddr_freq(&sys, 1); + } + info.dimm_on_ctlr = DDRC_NUM_DIMM; + + info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED; + + dram_size = dram_init(&info +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , NXP_CCN_HN_F_0_ADDR +#endif + ); + + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h new file mode 100644 index 0000000..02f51e7 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h @@ -0,0 +1,105 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +#include +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#if defined(IMAGE_BL31) +#define LS_SYS_TIMCTL_BASE 0x2890000 +#define PLAT_LS_NSTIMER_FRAME_ID 0 +#define LS_CONFIG_CNTACR 1 +#endif + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x8000) +#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) + +#ifdef SD_BOOT +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) +#else +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#endif + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 3 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 2 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +#define BL31_WDOG_SEC 89 + +#define BL31_NS_WDOG_WS1 108 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define NXP_IRQ_SEC_SGI_7 15 + +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c new file mode 100644 index 0000000..b00adb5 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk new file mode 100644 index 0000000..ffb5fad --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk @@ -0,0 +1,51 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= flexspi_nor +BOARD ?= lx2160ardb +POVDD_ENABLE := no +NXP_COINED_BB := no + + # DDR Compilation Configs +NUM_OF_DDRC := 2 +DDRC_NUM_DIMM := 2 +DDRC_NUM_CS := 4 +DDR_ECC_EN := yes + #enable address decoding feature +DDR_ADDR_DEC := yes +APPLY_MAX_CDD := yes + +# DDR Errata +ERRATA_DDR_A011396 := 1 +ERRATA_DDR_A050450 := 1 + + # On-Board Flash Details +FLASH_TYPE := MT35XU512A +XSPI_FLASH_SZ := 0x10000000 +NXP_XSPI_NOR_UNIT_SIZE := 0x20000 +BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000 +# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This +# config is enabled for future use cases. +FSPI_ERASE_4K := 0 + + # Platform specific features. +WARM_BOOT := no + + # Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := flexspi_nor \ + sd \ + emmc + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + + # Adding SoC build info +include plat/nxp/soc-lx2160a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h new file mode 100644 index 0000000..6660998 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h @@ -0,0 +1,14 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include "plat_def.h" +#include "plat_default_def.h" + +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h new file mode 100644 index 0000000..19ad6db --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Following defines affect the PLATFORM SECURITY POLICY */ + +/* set this to 0x0 if the platform is not using/responding to ECC errors + * set this to 0x1 if ECC is being used (we have to do some init) + */ +#define POLICY_USING_ECC 0x0 + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +/* + * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I + * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7 + * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23 + */ +#define POLICY_PERF_WRIOP 0 + +/* + * set this to '1' if the debug clocks need to remain enabled during + * system entry to low-power (LPM20) - this should only be necessary + * for testing and NEVER set for normal production + */ +#define POLICY_DEBUG_ENABLE 0 + + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c new file mode 100644 index 0000000..73bcc93 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c @@ -0,0 +1,354 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "plat_common.h" +#include + +#ifdef CONFIG_STATIC_DDR + +const struct ddr_cfg_regs static_3200 = { + .cs[0].bnds = U(0x03FFU), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFFAA0018), + .timing_cfg[1] = U(0x646A8844), + .timing_cfg[2] = U(0x00058022), + .timing_cfg[3] = U(0x13622100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x07401400), + .timing_cfg[7] = U(0x3BB00000), + .timing_cfg[8] = U(0x0944AC00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010C50), + .sdram_mode[1] = U(0x00280400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x10240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x30C00000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct ddr_cfg_regs static_2900 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFF990018), + .timing_cfg[1] = U(0x4F4A4844), + .timing_cfg[2] = U(0x0005601F), + .timing_cfg[3] = U(0x125F2100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x07401400), + .timing_cfg[7] = U(0x3AA00000), + .timing_cfg[8] = U(0x09449B00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010C50), + .sdram_mode[1] = U(0x00280400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x10240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x2C2E0000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct ddr_cfg_regs static_2600 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFF880018), + .timing_cfg[1] = U(0x2A24F444), + .timing_cfg[2] = U(0x007141DC), + .timing_cfg[3] = U(0x125B2100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x06401400), + .timing_cfg[7] = U(0x28800000), + .timing_cfg[8] = U(0x07338A00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010A70), + .sdram_mode[1] = U(0x00200400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x0C240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x279C0000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct dimm_params static_dimm = { + .rdimm = 0U, + .primary_sdram_width = 64U, + .ec_sdram_width = 8U, + .n_ranks = 2U, + .device_width = 8U, + .mirrored_dimm = 1U, +}; + +/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */ +unsigned long long board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_2900, sizeof(static_2900)); + memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm)); + priv->conf.cs_on_dimm[0] = 0x3; + ddr_board_options(priv); + compute_ddr_phy(priv); + + return ULL(0x400000000); +} + +#elif defined(CONFIG_DDR_NODIMM) +/* + * Sample code to bypass reading SPD. This is a sample, not recommended + * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1. + */ +struct dimm_params ddr_raw_timing = { + .n_ranks = 2U, + .rank_density = U(0x200000000), + .capacity = U(0x400000000), + .primary_sdram_width = 64U, + .ec_sdram_width = 8U, + .device_width = 8U, + .die_density = U(0x5), + .rdimm = 0U, + .mirrored_dimm = 1U, + .n_row_addr = 16U, + .n_col_addr = 10U, + .bank_addr_bits = 0U, + .bank_group_bits = 2U, + .edc_config = 2U, + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 625, + .tckmax_ps = 1600, + .caslat_x = U(0x15FFFC00), + .taa_ps = 13750, + .trcd_ps = 13750, + .trp_ps = 13750, + .tras_ps = 32000, + .trc_ps = 457500, + .twr_ps = 15000, + .trfc1_ps = 350000, + .trfc2_ps = 260000, + .trfc4_ps = 160000, + .tfaw_ps = 21000, + .trrds_ps = 2500, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = 7800000U, +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, + struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; /* Modify accordingly */ + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */ + return 0x5; +} +#endif /* CONFIG_DDR_NODIMM */ + +int ddr_board_options(struct ddr_info *priv) +{ + struct memctl_opt *popts = &priv->opt; + const struct ddr_conf *conf = &priv->conf; + + popts->vref_dimm = U(0x19); /* range 1, 83.4% */ + popts->rtt_override = 1U; + popts->rtt_override_value = 0x5U; /* RTT being used as 60 ohm */ + popts->rtt_park = 120U; + popts->otf_burst_chop_en = 0; + popts->burst_length = DDR_BL8; + popts->trwt_override = 1U; + popts->bstopre = 0U; /* auto precharge */ + popts->addr_hash = 1; + + /* Set ODT impedance on PHY side */ + switch (conf->cs_on_dimm[1]) { + case 0xc: /* Two slots dual rank */ + case 0x4: /* Two slots single rank, not valid for interleaving */ + popts->trwt = U(0xf); + popts->twrt = U(0x7); + popts->trrt = U(0x7); + popts->twwt = U(0x7); + popts->vref_phy = U(0x6B); /* 83.6% */ + popts->odt = 60U; + popts->phy_tx_impedance = 28U; + break; + case 0: /* Ont slot used */ + default: + popts->trwt = U(0x3); + popts->twrt = U(0x3); + popts->trrt = U(0x3); + popts->twwt = U(0x3); + popts->vref_phy = U(0x5D); /* 72% */ + popts->odt = 60U; + popts->phy_tx_impedance = 28U; + break; + } + + return 0; +} + +#ifdef NXP_WARM_BOOT +long long init_ddr(uint32_t wrm_bt_flg) +#else +long long init_ddr(void) +#endif +{ + int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys) != 0) { + ERROR("System clocks are not set\n"); + panic(); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(info)); + + /* Set two DDRC. Unused DDRC will be removed automatically. */ + info.num_ctlrs = NUM_OF_DDRC; + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + info.ddr[1] = (void *)NXP_DDR2_ADDR; + info.phy[0] = (void *)NXP_DDR_PHY1_ADDR; + info.phy[1] = (void *)NXP_DDR_PHY2_ADDR; + info.clk = get_ddr_freq(&sys, 0); + info.img_loadr = load_img; + info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER; + if (info.clk == 0) { + info.clk = get_ddr_freq(&sys, 1); + } + info.dimm_on_ctlr = DDRC_NUM_DIMM; + + info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED; +#ifdef NXP_WARM_BOOT + if (wrm_bt_flg != 0) { + info.warm_boot_flag = DDR_WARM_BOOT; + } else { + info.warm_boot_flag = DDR_COLD_BOOT; + } +#endif + + dram_size = dram_init(&info +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , NXP_CCN_HN_F_0_ADDR +#endif + ); + + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + return dram_size; +} diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h new file mode 100644 index 0000000..de2d244 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h @@ -0,0 +1,105 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include +#include +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#if defined(IMAGE_BL31) +#define LS_SYS_TIMCTL_BASE 0x2890000 +#define PLAT_LS_NSTIMER_FRAME_ID 0 +#define LS_CONFIG_CNTACR 1 +#endif + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x8000) +#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) + +#ifdef SD_BOOT +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) +#else +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#endif + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 3 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 2 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +#define BL31_WDOG_SEC 89 + +#define BL31_NS_WDOG_WS1 108 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define NXP_IRQ_SEC_SGI_7 15 + +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c new file mode 100644 index 0000000..7622cf0 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk new file mode 100644 index 0000000..2b4712c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk @@ -0,0 +1,52 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= flexspi_nor +BOARD ?= lx2162aqds +POVDD_ENABLE := no +NXP_COINED_BB := no + + # DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDRC_NUM_CS := 2 +DDR_ECC_EN := yes + #enable address decoding feature +DDR_ADDR_DEC := yes +APPLY_MAX_CDD := yes + +# DDR Errata +ERRATA_DDR_A011396 := 1 +ERRATA_DDR_A050450 := 1 + + +# On-Board Flash Details +FLASH_TYPE := MT35XU512A +XSPI_FLASH_SZ := 0x10000000 +NXP_XSPI_NOR_UNIT_SIZE := 0x20000 +BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000 +# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This +# config is enabled for future use cases. +FSPI_ERASE_4K := 0 + +# Platform specific features. +WARM_BOOT := yes + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := flexspi_nor \ + sd \ + emmc + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-lx2160a/soc.mk diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h new file mode 100644 index 0000000..5fa774e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include "plat_def.h" +#include "plat_default_def.h" + +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h new file mode 100644 index 0000000..1095f38 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Following defines affect the PLATFORM SECURITY POLICY */ + +/* set this to 0x0 if the platform is not using/responding to ECC errors + * set this to 0x1 if ECC is being used (we have to do some init) + */ +#define POLICY_USING_ECC 0x0 + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +/* + * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I + * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7 + * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23 + */ +#define POLICY_PERF_WRIOP 0 + +/* + * set this to '1' if the debug clocks need to remain enabled during + * system entry to low-power (LPM20) - this should only be necessary + * for testing and NEVER set for normal production + */ +#define POLICY_DEBUG_ENABLE 0 + + +#endif /* POLICY_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c new file mode 100644 index 0000000..2209fda --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c @@ -0,0 +1,509 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#include +#include "plat_common.h" +#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA +#include +#endif +#ifdef NXP_WARM_BOOT +#include +#endif +#include "platform_def.h" +#include "soc.h" + +static struct soc_type soc_list[] = { + SOC_ENTRY(LX2160A, LX2160A, 8, 2), + SOC_ENTRY(LX2080A, LX2080A, 8, 1), + SOC_ENTRY(LX2120A, LX2120A, 6, 2), +}; + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, + }; +static const unsigned char master_to_6rn_id_map[] = { + PLAT_6CLUSTER_TO_CCN_ID_MAP +}; + +static const unsigned char master_to_rn_id_map[] = { + PLAT_CLUSTER_TO_CCN_ID_MAP +}; + +CASSERT(ARRAY_SIZE(master_to_rn_id_map) == NUMBER_OF_CLUSTERS, + assert_invalid_cluster_count_for_ccn_variant); + +static const ccn_desc_t plat_six_cluster_ccn_desc = { + .periphbase = NXP_CCN_ADDR, + .num_masters = ARRAY_SIZE(master_to_6rn_id_map), + .master_to_rn_id_map = master_to_6rn_id_map +}; + +static const ccn_desc_t plat_ccn_desc = { + .periphbase = NXP_CCN_ADDR, + .num_masters = ARRAY_SIZE(master_to_rn_id_map), + .master_to_rn_id_map = master_to_rn_id_map +}; + +/****************************************************************************** + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + * + *****************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + * + * + */ + counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF); + + return counter_base_frequency; +} + +#ifdef IMAGE_BL2 + +#ifdef POLICY_FUSE_PROVISION +static gpio_init_info_t gpio_init_data = { + .gpio1_base_addr = NXP_GPIO1_ADDR, + .gpio2_base_addr = NXP_GPIO2_ADDR, + .gpio3_base_addr = NXP_GPIO3_ADDR, + .gpio4_base_addr = NXP_GPIO4_ADDR, +}; +#endif + +static void soc_interconnect_config(void) +{ + unsigned long long val = 0x0U; + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), + &num_clusters, &cores_per_cluster); + + if (num_clusters == 6U) { + ccn_init(&plat_six_cluster_ccn_desc); + } else { + ccn_init(&plat_ccn_desc); + } + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + plat_ls_interconnect_enter_coherency(num_clusters); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 13, PCIeRC_RN_I_NODE_ID_OFFSET); + val |= (1 << 17); + ccn_write_node_reg(NODE_TYPE_HNI, 13, PCIeRC_RN_I_NODE_ID_OFFSET, val); + + /* PCIe is Connected to RN-I 17 which is connected to HN-I 13. */ + val = ccn_read_node_reg(NODE_TYPE_HNI, 30, PCIeRC_RN_I_NODE_ID_OFFSET); + val |= (1 << 17); + ccn_write_node_reg(NODE_TYPE_HNI, 30, PCIeRC_RN_I_NODE_ID_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET); + val |= SERIALIZE_DEV_nGnRnE_WRITES; + ccn_write_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET); + val &= ~(ENABLE_RESERVE_BIT53); + val |= SERIALIZE_DEV_nGnRnE_WRITES; + ccn_write_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 13, PoS_CONTROL_REG_OFFSET); + val &= ~(HNI_POS_EN); + ccn_write_node_reg(NODE_TYPE_HNI, 13, PoS_CONTROL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 30, PoS_CONTROL_REG_OFFSET); + val &= ~(HNI_POS_EN); + ccn_write_node_reg(NODE_TYPE_HNI, 30, PoS_CONTROL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET); + val &= ~(POS_EARLY_WR_COMP_EN); + ccn_write_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET); + val &= ~(POS_EARLY_WR_COMP_EN); + ccn_write_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET, val); + +#if POLICY_PERF_WRIOP + uint16_t wriop_rni = 0U; + + if (POLICY_PERF_WRIOP == 1) { + wriop_rni = 7U; + } else if (POLICY_PERF_WRIOP == 2) { + wriop_rni = 23U; + } else { + ERROR("Incorrect WRIOP selected.\n"); + panic(); + } + + val = ccn_read_node_reg(NODE_TYPE_RNI, wriop_rni, + SA_AUX_CTRL_REG_OFFSET); + val |= ENABLE_WUO; + ccn_write_node_reg(NODE_TYPE_HNI, wriop_rni, SA_AUX_CTRL_REG_OFFSET, + val); +#else + val = ccn_read_node_reg(NODE_TYPE_RNI, 17, SA_AUX_CTRL_REG_OFFSET); + val |= ENABLE_WUO; + ccn_write_node_reg(NODE_TYPE_RNI, 17, SA_AUX_CTRL_REG_OFFSET, val); +#endif +} + + +void soc_preload_setup(void) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); +#if defined(NXP_WARM_BOOT) + bool warm_reset = is_warm_boot(); +#endif + info_dram_regions->total_dram_size = +#if defined(NXP_WARM_BOOT) + init_ddr(warm_reset); +#else + init_ddr(); +#endif +} + +/******************************************************************************* + * This function implements soc specific erratas + * This is called before DDR is initialized or MMU is enabled + ******************************************************************************/ +void soc_early_init(void) +{ + dcfg_init(&dcfg_init_data); +#ifdef POLICY_FUSE_PROVISION + gpio_init(&gpio_init_data); + sec_init(NXP_CAAM_ADDR); +#endif +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + + enable_timer_base_to_cluster(NXP_PMU_ADDR); + soc_interconnect_config(); + + enum boot_device dev = get_boot_dev(); + /* Mark the buffer for SD in OCRAM as non secure. + * The buffer is assumed to be at end of OCRAM for + * the logic below to calculate TZPC programming + */ + if (dev == BOOT_DEVICE_EMMC || dev == BOOT_DEVICE_SDHC2_EMMC) { + /* Calculate the region in OCRAM which is secure + * The buffer for SD needs to be marked non-secure + * to allow SD to do DMA operations on it + */ + uint32_t secure_region = (NXP_OCRAM_SIZE + - NXP_SD_BLOCK_BUF_SIZE); + uint32_t mask = secure_region/TZPC_BLOCK_SIZE; + + mmio_write_32(NXP_OCRAM_TZPC_ADDR, mask); + + /* Add the entry for buffer in MMU Table */ + mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + MT_DEVICE | MT_RW | MT_NS); + } + + soc_errata(); + +#if (TRUSTED_BOARD_BOOT) || defined(POLICY_FUSE_PROVISION) + sfp_init(NXP_SFP_ADDR); +#endif + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + /* For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ + +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) + INFO("SEC is disabled.\n"); + else + sec_init(NXP_CAAM_ADDR); +#endif +#endif + + /* + * Initialize system level generic timer for Layerscape Socs. + */ + delay_timer_init(NXP_TIMER_ADDR); + i2c_init(NXP_I2C_ADDR); +} + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +/***************************************************************************** + * This function returns the boot device based on RCW_SRC + ****************************************************************************/ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + switch (rcw_src) { + case FLEXSPI_NOR: + src = BOOT_DEVICE_FLEXSPI_NOR; + INFO("RCW BOOT SRC is FLEXSPI NOR\n"); + break; + case FLEXSPI_NAND2K_VAL: + case FLEXSPI_NAND4K_VAL: + INFO("RCW BOOT SRC is FLEXSPI NAND\n"); + src = BOOT_DEVICE_FLEXSPI_NAND; + break; + case SDHC1_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD\n"); + break; + case SDHC2_VAL: + src = BOOT_DEVICE_SDHC2_EMMC; + INFO("RCW BOOT SRC is EMMC\n"); + break; + default: + break; + } + + return src; +} + + +void soc_mem_access(void) +{ + const devdisr5_info_t *devdisr5_info = get_devdisr5_info(); + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx, index = 0U; + + for (dram_idx = 0U; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[dram_idx].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc400_reg_list(tzc400_reg_list, + dram_idx, index, + info_dram_regions->region[dram_idx].addr, + info_dram_regions->region[dram_idx].size, + NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE); + } + + if (devdisr5_info->ddrc1_present != 0) { + INFO("DDR Controller 1.\n"); + mem_access_setup(NXP_TZC_ADDR, index, + tzc400_reg_list); + mem_access_setup(NXP_TZC3_ADDR, index, + tzc400_reg_list); + } + if (devdisr5_info->ddrc2_present != 0) { + INFO("DDR Controller 2.\n"); + mem_access_setup(NXP_TZC2_ADDR, index, + tzc400_reg_list); + mem_access_setup(NXP_TZC4_ADDR, index, + tzc400_reg_list); + } +} + +#else +const unsigned char _power_domain_tree_desc[] = {1, 8, 2, 2, 2, 2, 2, 2, 2, 2}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_lx2160a_cluster_count); + +/****************************************************************************** + * This function returns the SoC topology + ****************************************************************************/ + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + + return _power_domain_tree_desc; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + return CORES_PER_CLUSTER; +} + + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* + * Initialize system level generic timer for Socs + */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uintptr_t target_mask_array[PLATFORM_CORE_COUNT]; + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0) + }; + + plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array, + plat_core_pos); + + plat_ls_gic_init(); + enable_init_timer(); +#ifdef LS_SYS_TIMCTL_BASE + ls_configure_sys_timer(LS_SYS_TIMCTL_BASE, + LS_CONFIG_CNTACR, + PLAT_LS_NSTIMER_FRAME_ID); +#endif +} + +/******************************************************************************* + * This function initializes the soc from the BL31 module + ******************************************************************************/ +void soc_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), + &num_clusters, &cores_per_cluster); + + /* low-level init of the soc */ + soc_init_start(); + soc_init_percpu(); + _init_global_data(); + _initialize_psci(); + + if (ccn_get_part0_id(NXP_CCN_ADDR) != CCN_508_PART0_ID) { + ERROR("Unrecognized CCN variant detected."); + ERROR("Only CCN-508 is supported\n"); + panic(); + } + + if (num_clusters == 6U) { + ccn_init(&plat_six_cluster_ccn_desc); + } else { + ccn_init(&plat_ccn_desc); + } + + plat_ls_interconnect_enter_coherency(num_clusters); + + /* Set platform security policies */ + _set_platform_security(); + + /* make sure any parallel init tasks are finished */ + soc_init_finish(); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } + +} + +#ifdef NXP_WDOG_RESTART +static uint64_t wdog_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint8_t data = WDOG_RESET_FLAG; + + wr_nv_app_data(WDT_RESET_FLAG_OFFSET, + (uint8_t *)&data, sizeof(data)); + + mmio_write_32(NXP_RST_ADDR + RSTCNTL_OFFSET, SW_RST_REQ_INIT); + + return 0; +} +#endif + +void soc_runtime_setup(void) +{ + +#ifdef NXP_WDOG_RESTART + request_intr_type_el3(BL31_NS_WDOG_WS1, wdog_interrupt_handler); +#endif +} +#endif diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def new file mode 100644 index 0000000..81d6744 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def @@ -0,0 +1,116 @@ +# +# Copyright (c) 2015, 2016 Freescale Semiconductor, Inc. +# Copyright 2017-2022 NXP Semiconductors +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a72 + +CACHE_LINE := 6 + +# set to GIC400 or GIC500 +GIC := GIC500 + +# set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCN508 + +# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 3_2 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := PL011 + +# Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN2 + +PHYS_SYS := 64 + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0xa000 + +# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def +# Input to CST create_hdr_esbc tool +CSF_HDR_SZ := 0x3000 + +NXP_SFP_VER := 3_4 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + +# Defining the endianness for NXP ESDHC +NXP_ESDHC_ENDIANNESS := LE + +# Defining the endianness for NXP SFP +NXP_SFP_ENDIANNESS := LE + +# Defining the endianness for NXP GPIO +NXP_GPIO_ENDIANNESS := LE + +# Defining the endianness for NXP SNVS +NXP_SNVS_ENDIANNESS := LE + +# Defining the endianness for NXP CCSR GUR register +NXP_GUR_ENDIANNESS := LE + +# Defining the endianness for NXP FSPI register +NXP_FSPI_ENDIANNESS := LE + +# Defining the endianness for NXP SEC +NXP_SEC_ENDIANNESS := LE + +# Defining the endianness for NXP DDR +NXP_DDR_ENDIANNESS := LE + +NXP_DDR_INTLV_256B := 1 + +# OCRAM MAP for BL2 +# Before BL2 +# 0x18000000 - 0x18009fff -> Used by ROM code +# 0x1800a000 - 0x1800dfff -> CSF header for BL2 +# (The above area i.e 0x18000000 - 0x1800dfff is available +# for DDR PHY images scratch pad region during BL2 run time) +# For FlexSPI boot +# 0x1800e000 - 0x18040000 -> Reserved for BL2 binary +# For SD boot +# 0x1800e000 - 0x18030000 -> Reserved for BL2 binary +# 0x18030000 - 0x18040000 -> Reserved for SD buffer +OCRAM_START_ADDR := 0x18000000 +OCRAM_SIZE := 0x40000 + +# Location of BL2 on OCRAM +BL2_BASE_ADDR := $(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) + $(CSF_HDR_SZ) ))) +# Covert to HEX to be used by create_pbl.mk +BL2_BASE := $(shell echo "0x"$$(echo "obase=16; ${BL2_BASE_ADDR}" | bc)) + +# BL2_HDR_LOC is at (OCRAM_ADDR + NXP_ROM_RSVD) +# This value BL2_HDR_LOC + CSF_HDR_SZ should not overalp with BL2_BASE +BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) ))) +# Covert to HEX to be used by create_pbl.mk +BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc) + +# SoC ERRATAS to be enabled +# +# Core Errata +ERRATA_A72_859971 := 1 + +# SoC Errata +ERRATA_SOC_A050426 := 1 + +# DDR Errata +ERRATA_DDR_A011396 := 1 +ERRATA_DDR_A050450 := 1 +ERRATA_DDR_A050958 := 1 + +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 diff --git a/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.mk new file mode 100644 index 0000000..75a3af2 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.mk @@ -0,0 +1,174 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + + + # SoC-specific build parameters +SOC := lx2160a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH:= plat/nxp/common +PLAT_DRIVERS_PATH:= drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + + # get SoC-specific defnitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + + # SoC-specific +NXP_WDOG_RESTART := yes + + + # Selecting dependent module, + # Selecting dependent drivers, and + # Adding defines. + + # for features enabled above. +ifeq (${NXP_WDOG_RESTART}, yes) +NXP_NV_SW_MAINT_LAST_EXEC_DATA := yes +LS_EL3_INTERRUPT_HANDLER := yes +$(eval $(call add_define, NXP_WDOG_RESTART)) +endif + + + # For Security Features +DISABLE_FUSE_WRITE := 1 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +ifeq (${GENERATE_COT},1) +# Save Keys to be used by DDR FIP image +SAVE_KEYS=1 +endif +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +# Used by create_pbl tool to +# create bl2__sec.pbl image +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + + + # Selecting Drivers for SoC +$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM)) + +$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + + + # Selecting PSCI & SIP_SVC support +$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31)) + + + # Selecting Boot Source for the TFA images. +ifeq (${BOOT_MODE}, flexspi_nor) +$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2)) +$(eval $(call add_define,FLEXSPI_NOR_BOOT)) +else +ifeq (${BOOT_MODE}, sd) +$(eval $(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2)) +$(eval $(call add_define,SD_BOOT)) +else +ifeq (${BOOT_MODE}, emmc) +$(eval $(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2)) +$(eval $(call add_define,EMMC_BOOT)) +else +$(error Un-supported Boot Mode = ${BOOT_MODE}) +endif +endif +endif + + + # Separate DDR-FIP image to be loaded. +$(eval $(call SET_NXP_MAKE_FLAG,DDR_FIP_IO_NEEDED,BL2)) + + +# Source File Addition +# ##################### + +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_SOC_PATH}/include\ + -I${PLAT_COMMON_PATH}/soc_errata + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq ($(WARM_BOOT),yes) +include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk +endif + +ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes) +include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +ifeq (${DDR_FIP_IO_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/fip_handler/ddr_fip/ddr_fip_io.mk +endif + + # for fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + + # Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + + # Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\ + ${WARM_RST_INCLUDES} + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${WARM_RST_BL31_SOURCES}\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\ + ${NV_STORAGE_SOURCES}\ + ${WARM_RST_BL_COMM_SOURCES}\ + ${PLAT_SOC_PATH}/soc.c + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + + + # Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk + + + # Adding source files to generate separate DDR FIP image +include ${PLAT_SOC_PATH}/ddr_fip.mk diff --git a/arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S b/arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S new file mode 100644 index 0000000..5e346d5 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S @@ -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 + + .globl plat_my_core_pos + .globl plat_get_my_entrypoint + .globl platform_mem_init + .globl plat_qemu_calc_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + +func plat_my_core_pos + ldcopr r0, MPIDR + b plat_qemu_calc_core_pos +endfunc plat_my_core_pos + +/* + * unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); + * With this function: CorePos = (ClusterId * 4) + CoreId + */ +func plat_qemu_calc_core_pos + and r1, r0, #MPIDR_CPU_MASK + and r0, r0, #MPIDR_CLUSTER_MASK + add r0, r1, r0, LSR #6 + bx lr +endfunc plat_qemu_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + and r0, r1 + cmp r0, #QEMU_PRIMARY_CPU + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Calculate address of our hold entry */ + bl plat_my_core_pos + lsl r0, r0, #PLAT_QEMU_HOLD_ENTRY_SHIFT + mov_imm r2, PLAT_QEMU_HOLD_BASE + + /* Wait until we have a go */ +poll_mailbox: + ldr r1, [r2, r0] + cmp r1, #PLAT_QEMU_HOLD_STATE_WAIT + beq 1f + + /* Clear the mailbox again ready for next time. */ + mov r1, #PLAT_QEMU_HOLD_STATE_WAIT + str r1, [r2, r0] + + /* Jump to the provided entrypoint. */ + mov_imm r0, PLAT_QEMU_TRUSTED_MAILBOX_BASE + ldr r1, [r0] + bx r1 +1: + wfe + b poll_mailbox +endfunc plat_secondary_cold_boot_setup + +func plat_get_my_entrypoint + /* TODO support warm boot */ + mov r0, #0 + bx lr +endfunc plat_get_my_entrypoint + +func platform_mem_init + bx lr +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm r0, PLAT_QEMU_CRASH_UART_BASE + mov_imm r1, PLAT_QEMU_CRASH_UART_CLK_IN_HZ + mov_imm r2, PLAT_QEMU_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm r1, PLAT_QEMU_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush(int c) + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm r0, PLAT_QEMU_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + diff --git a/arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..08b2817 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_my_core_pos + .globl plat_get_my_entrypoint + .globl platform_mem_init + .globl plat_qemu_calc_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_qemu_calc_core_pos +endfunc plat_my_core_pos + +/* + * unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); + * With this function: CorePos = (ClusterId * 4) + CoreId + */ +func plat_qemu_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #(MPIDR_AFFINITY_BITS -\ + PLATFORM_CPU_PER_CLUSTER_SHIFT) + ret +endfunc plat_qemu_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #QEMU_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Calculate address of our hold entry */ + bl plat_my_core_pos + lsl x0, x0, #PLAT_QEMU_HOLD_ENTRY_SHIFT + mov_imm x2, PLAT_QEMU_HOLD_BASE + + /* Wait until we have a go */ +poll_mailbox: + ldr x1, [x2, x0] + cbz x1, 1f + + /* Clear the mailbox again ready for next time. */ + mov x1, #PLAT_QEMU_HOLD_STATE_WAIT + str x1, [x2, x0] + + /* Jump to the provided entrypoint. */ + mov_imm x0, PLAT_QEMU_TRUSTED_MAILBOX_BASE + ldr x1, [x0] + br x1 +1: + wfe + b poll_mailbox +endfunc plat_secondary_cold_boot_setup + +func plat_get_my_entrypoint + /* TODO support warm boot */ + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, PLAT_QEMU_CRASH_UART_BASE + mov_imm x1, PLAT_QEMU_CRASH_UART_CLK_IN_HZ + mov_imm x2, PLAT_QEMU_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, PLAT_QEMU_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush(int c) + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, PLAT_QEMU_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + diff --git a/arm-trusted-firmware/plat/qemu/common/include/plat_macros.S b/arm-trusted-firmware/plat/qemu/common/include/plat_macros.S new file mode 100644 index 0000000..b6cdb07 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/include/plat_macros.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x17, GICC_BASE + mov_imm x16, GICD_BASE + arm_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c b/arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c new file mode 100644 index 0000000..67f3327 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#include "qemu_private.h" + +/* Data structure which holds the extents of the trusted SRAM for BL1*/ +static meminfo_t bl1_tzram_layout; + + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + qemu_console_init(); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL_RAM_BASE; + bl1_tzram_layout.total_size = BL_RAM_SIZE; +} + +/****************************************************************************** + * Perform the very early platform specific architecture setup. This only + * does basic initialization. Later architectural setup (bl1_arch_setup()) + * does not do anything platform specific. + *****************************************************************************/ +#ifdef __aarch64__ +#define QEMU_CONFIGURE_BL1_MMU(...) qemu_configure_mmu_el3(__VA_ARGS__) +#else +#define QEMU_CONFIGURE_BL1_MMU(...) qemu_configure_mmu_svc_mon(__VA_ARGS__) +#endif + +void bl1_plat_arch_setup(void) +{ + QEMU_CONFIGURE_BL1_MMU(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL_CODE_BASE, BL1_CODE_END, + BL1_RO_DATA_BASE, BL1_RO_DATA_END, + BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); +} + +void bl1_platform_setup(void) +{ + plat_qemu_io_setup(); +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c new file mode 100644 index 0000000..5af3a22 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#ifdef EL3_PAYLOAD_BASE + /* Fill EL3 payload related information (BL31 is EL3 payload) */ + { .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.pc = EL3_PAYLOAD_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + 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 /* EL3_PAYLOAD_BASE */ +#ifdef __aarch64__ + /* Fill BL31 related information */ + { .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +# if DEBUG + .ep_info.args.arg1 = QEMU_BL31_PLAT_PARAM_VAL, +# endif + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef QEMU_LOAD_BL32 + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, +#endif /* __aarch64__ */ +# ifdef QEMU_LOAD_BL32 + +#ifdef __aarch64__ +#define BL32_EP_ATTRIBS (SECURE | EXECUTABLE) +#define BL32_IMG_ATTRIBS 0 +#else +#define BL32_EP_ATTRIBS (SECURE | EXECUTABLE | EP_FIRST_EXE) +#define BL32_IMG_ATTRIBS IMAGE_ATTRIB_PLAT_SETUP +#endif + + /* Fill BL32 related information */ + { .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, BL32_EP_ATTRIBS), + .ep_info.pc = BL32_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, BL32_IMG_ATTRIBS), + + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the + * pager image. + */ + { .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the + * paged image. + */ + { .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE) + .image_info.image_base = QEMU_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = QEMU_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* QEMU_LOAD_BL32 */ + + /* Fill BL33 related information */ + { .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), +# else /* PRELOADED_BL33_BASE */ + .ep_info.pc = NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, + 0), + .image_info.image_base = NS_IMAGE_OFFSET, + .image_info.image_max_size = NS_IMAGE_MAX_SIZE, +# endif /* !PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#endif /* !EL3_PAYLOAD_BASE */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c b/arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c new file mode 100644 index 0000000..2c0da15 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c @@ -0,0 +1,247 @@ +/* + * 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 "qemu_private.h" + + +/* Data structure which holds the extents of the trusted SRAM for BL2 */ +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + meminfo_t *mem_layout = (void *)arg1; + + /* Initialize the console to provide early debug support */ + qemu_console_init(); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; + + plat_qemu_io_setup(); +} + +static void security_setup(void) +{ + /* + * This is where a TrustZone address space controller and other + * security related peripherals, would be configured. + */ +} + +static void update_dt(void) +{ + int ret; + void *fdt = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE; + + ret = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE); + if (ret < 0) { + ERROR("Invalid Device Tree at %p: error %d\n", fdt, ret); + return; + } + + if (dt_add_psci_node(fdt)) { + ERROR("Failed to add PSCI Device Tree node\n"); + return; + } + + if (dt_add_psci_cpu_enable_methods(fdt)) { + ERROR("Failed to add PSCI cpu enable methods in Device Tree\n"); + return; + } + + ret = fdt_pack(fdt); + if (ret < 0) + ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, ret); +} + +void bl2_platform_setup(void) +{ + security_setup(); + update_dt(); + + /* TODO Initialize timer */ +} + +#ifdef __aarch64__ +#define QEMU_CONFIGURE_BL2_MMU(...) qemu_configure_mmu_el1(__VA_ARGS__) +#else +#define QEMU_CONFIGURE_BL2_MMU(...) qemu_configure_mmu_svc_mon(__VA_ARGS__) +#endif + +void bl2_plat_arch_setup(void) +{ + QEMU_CONFIGURE_BL2_MMU(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL_CODE_BASE, BL_CODE_END, + BL_RO_DATA_BASE, BL_RO_DATA_END, + BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +static uint32_t qemu_get_spsr_for_bl32_entry(void) +{ +#ifdef __aarch64__ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL3-2 image. + */ + return 0; +#else + return SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS); +#endif +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +static uint32_t qemu_get_spsr_for_bl33_entry(void) +{ + uint32_t spsr; +#ifdef __aarch64__ + unsigned int mode; + + /* Figure out what mode we enter the non-secure world in */ + mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +#else + spsr = SPSR_MODE32(MODE32_svc, + plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); +#endif + return spsr; +} + +static int qemu_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE) + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif +#if defined(SPD_spmd) + unsigned int mode_rw = MODE_RW_64; + uint64_t pagable_part = 0; +#endif + + assert(bl_mem_params); + + switch (image_id) { + case BL32_IMAGE_ID: +#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE) + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) { + WARN("OPTEE header parse error.\n"); + } +#if defined(SPD_spmd) + mode_rw = bl_mem_params->ep_info.args.arg0; + pagable_part = bl_mem_params->ep_info.args.arg1; +#endif +#endif + +#if defined(SPD_spmd) + bl_mem_params->ep_info.args.arg0 = ARM_PRELOADED_DTB_BASE; + bl_mem_params->ep_info.args.arg1 = pagable_part; + bl_mem_params->ep_info.args.arg2 = mode_rw; + bl_mem_params->ep_info.args.arg3 = 0; +#elif defined(SPD_opteed) + /* + * OP-TEE expect to receive DTB address in x2. + * This will be copied into x2 by dispatcher. + */ + bl_mem_params->ep_info.args.arg3 = ARM_PRELOADED_DTB_BASE; +#elif defined(AARCH32_SP_OPTEE) + bl_mem_params->ep_info.args.arg0 = + bl_mem_params->ep_info.args.arg1; + bl_mem_params->ep_info.args.arg1 = 0; + bl_mem_params->ep_info.args.arg2 = ARM_PRELOADED_DTB_BASE; + bl_mem_params->ep_info.args.arg3 = 0; +#endif + bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl32_entry(); + break; + + case BL33_IMAGE_ID: +#ifdef AARCH32_SP_OPTEE + /* AArch32 only core: OP-TEE expects NSec EP in register LR */ + pager_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID); + assert(pager_mem_params); + pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc; +#endif + +#if ARM_LINUX_KERNEL_AS_BL33 + /* + * According to the file ``Documentation/arm64/booting.txt`` of + * the Linux kernel tree, Linux expects the physical address of + * the device tree blob (DTB) in x0, while x1-x3 are reserved + * for future use and must be 0. + */ + bl_mem_params->ep_info.args.arg0 = + (u_register_t)ARM_PRELOADED_DTB_BASE; + bl_mem_params->ep_info.args.arg1 = 0U; + bl_mem_params->ep_info.args.arg2 = 0U; + bl_mem_params->ep_info.args.arg3 = 0U; +#else + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); +#endif + + bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry(); + break; + default: + /* Do nothing in default case */ + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return qemu_bl2_handle_post_image_load(image_id); +} + +uintptr_t plat_get_ns_image_entrypoint(void) +{ + return NS_IMAGE_OFFSET; +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c b/arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c new file mode 100644 index 0000000..4f60eb1 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "qemu_private.h" + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL3-1 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Perform any BL3-1 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* Initialize the console to provide early debug support */ + qemu_console_init(); + + /* + * Check params passed from BL2 + */ + bl_params_t *params_from_bl2 = (bl_params_t *)arg0; + + assert(params_from_bl2); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_image_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (!bl33_image_ep_info.pc) + panic(); +} + +void bl31_plat_arch_setup(void) +{ + qemu_configure_mmu_el3(BL31_BASE, (BL31_END - BL31_BASE), + BL_CODE_BASE, BL_CODE_END, + BL_RO_DATA_BASE, BL_RO_DATA_END, + BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); +} + +static void qemu_gpio_init(void) +{ +#ifdef SECURE_GPIO_BASE + pl061_gpio_init(); + pl061_gpio_register(SECURE_GPIO_BASE, 0); +#endif +} + +void bl31_platform_setup(void) +{ + plat_qemu_gic_init(); + qemu_gpio_init(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image + * for the security state specified. BL3-3 corresponds to the non-secure + * image type while BL3-2 corresponds to the secure image type. A NULL + * pointer is returned if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_common.c b/arm-trusted-firmware/plat/qemu/common/qemu_common.c new file mode 100644 index 0000000..47ec791 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_common.c @@ -0,0 +1,163 @@ + +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "qemu_private.h" + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef DEVICE1_BASE +#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#ifdef DEVICE2_BASE +#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ + DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \ + SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_FLASH0 MAP_REGION_FLAT(QEMU_FLASH0_BASE, QEMU_FLASH0_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define MAP_FLASH1 MAP_REGION_FLAT(QEMU_FLASH1_BASE, QEMU_FLASH1_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +/* + * Table of regions for various BL stages to map using the MMU. + * This doesn't include TZRAM as the 'mem_layout' argument passed to + * arm_configure_mmu_elx() will give the available subset of that, + */ +#ifdef IMAGE_BL1 +static const mmap_region_t plat_qemu_mmap[] = { + MAP_FLASH0, + MAP_FLASH1, + MAP_SHARED_RAM, + MAP_DEVICE0, +#ifdef MAP_DEVICE1 + MAP_DEVICE1, +#endif +#ifdef MAP_DEVICE2 + MAP_DEVICE2, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL2 +static const mmap_region_t plat_qemu_mmap[] = { + MAP_FLASH0, + MAP_FLASH1, + MAP_SHARED_RAM, + MAP_DEVICE0, +#ifdef MAP_DEVICE1 + MAP_DEVICE1, +#endif +#ifdef MAP_DEVICE2 + MAP_DEVICE2, +#endif + MAP_NS_DRAM0, +#if SPM_MM + QEMU_SP_IMAGE_MMAP, +#else + MAP_BL32_MEM, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL31 +static const mmap_region_t plat_qemu_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, +#ifdef MAP_DEVICE1 + MAP_DEVICE1, +#endif +#ifdef MAP_DEVICE2 + MAP_DEVICE2, +#endif +#if SPM_MM + MAP_NS_DRAM0, + QEMU_SPM_BUF_EL3_MMAP, +#else + MAP_BL32_MEM, +#endif + {0} +}; +#endif +#ifdef IMAGE_BL32 +static const mmap_region_t plat_qemu_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, +#ifdef MAP_DEVICE1 + MAP_DEVICE1, +#endif +#ifdef MAP_DEVICE2 + MAP_DEVICE2, +#endif + {0} +}; +#endif + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ + +#define DEFINE_CONFIGURE_MMU_EL(_el) \ + void qemu_configure_mmu_##_el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long code_start, \ + unsigned long code_limit, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(code_start, code_start, \ + code_limit - code_start, \ + MT_CODE | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_RO_DATA | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(plat_qemu_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_##_el(0); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +#ifdef __aarch64__ +DEFINE_CONFIGURE_MMU_EL(el1) +DEFINE_CONFIGURE_MMU_EL(el3) +#else +DEFINE_CONFIGURE_MMU_EL(svc_mon) +#endif + + diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_console.c b/arm-trusted-firmware/plat/qemu/common/qemu_console.c new file mode 100644 index 0000000..1f00f8a --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_console.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +static console_t console; + +void qemu_console_init(void) +{ + (void)console_pl011_register(PLAT_QEMU_BOOT_UART_BASE, + PLAT_QEMU_BOOT_UART_CLK_IN_HZ, + PLAT_QEMU_CONSOLE_BAUDRATE, &console); + + console_set_scope(&console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME); +} + diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c b/arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c new file mode 100644 index 0000000..2c358ea --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static const interrupt_prop_t qemu_interrupt_props[] = { + PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0), + PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) +}; + +static const struct gicv2_driver_data plat_gicv2_driver_data = { + .gicd_base = GICD_BASE, + .gicc_base = GICC_BASE, + .interrupt_props = qemu_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(qemu_interrupt_props), +}; + +void plat_qemu_gic_init(void) +{ + /* Initialize the gic cpu and distributor interfaces */ + gicv2_driver_init(&plat_gicv2_driver_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +void qemu_pwr_gic_on_finish(void) +{ + /* TODO: This setup is needed only after a cold boot */ + gicv2_pcpu_distif_init(); + + /* Enable the gic cpu interface */ + gicv2_cpuif_enable(); +} + +void qemu_pwr_gic_off(void) +{ + gicv2_cpuif_disable(); +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c b/arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c new file mode 100644 index 0000000..0d35446 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static const interrupt_prop_t qemu_interrupt_props[] = { + PLATFORM_G1S_PROPS(INTR_GROUP1S), + PLATFORM_G0_PROPS(INTR_GROUP0) +}; + +static uintptr_t qemu_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static unsigned int qemu_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +static const gicv3_driver_data_t qemu_gicv3_driver_data = { + .gicd_base = GICD_BASE, + .gicr_base = GICR_BASE, + .interrupt_props = qemu_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(qemu_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = qemu_rdistif_base_addrs, + .mpidr_to_core_pos = qemu_mpidr_to_core_pos +}; + +void plat_qemu_gic_init(void) +{ + gicv3_driver_init(&qemu_gicv3_driver_data); + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void qemu_pwr_gic_on_finish(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void qemu_pwr_gic_off(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); + gicv3_rdistif_off(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_image_load.c b/arm-trusted-firmware/plat/qemu/common/qemu_image_load.c new file mode 100644 index 0000000..9970d1d --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_image_load.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/******************************************************************************* + * This function is a wrapper of a common function which flushes the data + * structures so that they are visible in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function is a wrapper of a common function which returns the list of + * loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function is a wrapper of a common function which returns the data + * structures of the next BL image. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c b/arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c new file mode 100644 index 0000000..1107e44 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2015-2016, 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 + +/* Semihosting filenames */ +#define BL2_IMAGE_NAME "bl2.bin" +#define BL31_IMAGE_NAME "bl31.bin" +#define BL32_IMAGE_NAME "bl32.bin" +#define BL32_EXTRA1_IMAGE_NAME "bl32_extra1.bin" +#define BL32_EXTRA2_IMAGE_NAME "bl32_extra2.bin" +#define BL33_IMAGE_NAME "bl33.bin" + +#if TRUSTED_BOARD_BOOT +#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt" +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt" +#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt" +#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt" +#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt" +#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt" +#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt" +#endif /* TRUSTED_BOARD_BOOT */ + + + +/* IO devices */ +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *memmap_dev_con; +static uintptr_t memmap_dev_handle; +static const io_dev_connector_t *sh_dev_con; +static uintptr_t sh_dev_handle; +#ifndef DECRYPTION_SUPPORT_none +static const io_dev_connector_t *enc_dev_con; +static uintptr_t enc_dev_handle; +#endif + +static const io_block_spec_t fip_block_spec = { + .offset = PLAT_QEMU_FIP_BASE, + .length = PLAT_QEMU_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t tb_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FW_CERT, +}; + +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static const io_file_spec_t sh_file_spec[] = { + [BL2_IMAGE_ID] = { + .path = BL2_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL31_IMAGE_ID] = { + .path = BL31_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL32_IMAGE_ID] = { + .path = BL32_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL32_EXTRA1_IMAGE_ID] = { + .path = BL32_EXTRA1_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL32_EXTRA2_IMAGE_ID] = { + .path = BL32_EXTRA2_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, + [BL33_IMAGE_ID] = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + .path = TRUSTED_BOOT_FW_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_KEY_CERT_ID] = { + .path = TRUSTED_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [SOC_FW_KEY_CERT_ID] = { + .path = SOC_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + .path = TOS_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + .path = NT_FW_KEY_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [SOC_FW_CONTENT_CERT_ID] = { + .path = SOC_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + .path = TOS_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + .path = NT_FW_CONTENT_CERT_NAME, + .mode = FOPEN_MODE_RB + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + +static int open_fip(const uintptr_t spec); +static int open_memmap(const uintptr_t spec); +#ifndef DECRYPTION_SUPPORT_none +static int open_enc_fip(const uintptr_t spec); +#endif + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, ARM platforms load images from the FIP */ +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, + [ENC_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)NULL, + open_fip + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, +#if ENCRYPT_BL31 && !defined(DECRYPTION_SUPPORT_none) + [BL31_IMAGE_ID] = { + &enc_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_enc_fip + }, +#else + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, +#endif +#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none) + [BL32_IMAGE_ID] = { + &enc_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_enc_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &enc_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_enc_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &enc_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_enc_fip + }, +#else + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_fip + }, +#endif + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + open_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + open_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + open_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0 && spec != (uintptr_t)NULL) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +#ifndef DECRYPTION_SUPPORT_none +static int open_enc_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if an encrypted FIP is available */ + result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID); + if (result == 0) { + result = io_open(enc_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using encrypted FIP\n"); + io_close(local_image_handle); + } + } + return result; +} +#endif + +static int open_memmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Memmap\n"); + io_close(local_image_handle); + } + } + return result; +} + +static int open_semihosting(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if the file exists on semi-hosting.*/ + result = io_dev_init(sh_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(sh_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Semi-hosting IO\n"); + io_close(local_image_handle); + } + } + return result; +} + +void plat_qemu_io_setup(void) +{ + int io_result; + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + assert(io_result == 0); + + io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &memmap_dev_handle); + assert(io_result == 0); + +#ifndef DECRYPTION_SUPPORT_none + io_result = register_io_dev_enc(&enc_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL, + &enc_dev_handle); + assert(io_result == 0); +#endif + + /* Register the additional IO devices on this platform */ + io_result = register_io_dev_sh(&sh_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle); + assert(io_result == 0); + + /* Ignore improbable errors in release builds */ + (void)io_result; +} + +static int get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]); + + if (result == 0) { + *dev_handle = sh_dev_handle; + *image_spec = (uintptr_t)&sh_file_spec[image_id]; + } + + return result; +} + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } else { + VERBOSE("Trying alternative IO\n"); + result = get_alt_image_source(image_id, dev_handle, image_spec); + } + + return result; +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_pm.c b/arm-trusted-firmware/plat/qemu/common/qemu_pm.c new file mode 100644 index 0000000..c2b5091 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_pm.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "qemu_private.h" + +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 + +/* + * The secure entry point to be used on warm reset. + */ +static unsigned long secure_entrypoint; + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#else +#define qemu_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 */ + + +#define qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ + qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + + + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +static const unsigned int qemu_pm_idle_states[] = { + /* State-id - 0x01 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, + MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0, +}; + +/******************************************************************************* + * Platform handler called to check the validity of the power state + * parameter. The power state parameter has to be a composite power state. + ******************************************************************************/ +static int qemu_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + assert(req_state); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; !!qemu_pm_idle_states[i]; i++) { + if (power_state == qemu_pm_idle_states[i]) + break; + } + + /* Return error if entry not found in the idle state array */ + if (!qemu_pm_idle_states[i]) + return PSCI_E_INVALID_PARAMS; + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + PLAT_LOCAL_PSTATE_MASK; + state_id >>= PLAT_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called to check the validity of the non secure + * entrypoint. + ******************************************************************************/ +static int qemu_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint >= NS_DRAM0_BASE) && + (entrypoint < (NS_DRAM0_BASE + NS_DRAM0_SIZE))) + return PSCI_E_SUCCESS; + return PSCI_E_INVALID_ADDRESS; +} + +/******************************************************************************* + * Platform handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void qemu_cpu_standby(plat_local_state_t cpu_state) +{ + + assert(cpu_state == PLAT_LOCAL_STATE_RET); + + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int qemu_pwr_domain_on(u_register_t mpidr) +{ + int rc = PSCI_E_SUCCESS; + unsigned pos = plat_core_pos_by_mpidr(mpidr); + uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE; + + hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO; + sev(); + + return rc; +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void qemu_pwr_domain_off(const psci_power_state_t *target_state) +{ + qemu_pwr_gic_off(); +} + +void __dead2 plat_secondary_cold_boot_setup(void); + +static void __dead2 +qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + disable_mmu_el3(); + plat_secondary_cold_boot_setup(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void qemu_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + assert(0); +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void qemu_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + qemu_pwr_gic_on_finish(); +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + ******************************************************************************/ +void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + assert(0); +} + +/******************************************************************************* + * Platform handlers to shutdown/reboot the system + ******************************************************************************/ + +static void __dead2 qemu_system_off(void) +{ +#ifdef SECURE_GPIO_BASE + ERROR("QEMU System Power off: with GPIO.\n"); + gpio_set_direction(SECURE_GPIO_POWEROFF, GPIO_DIR_OUT); + gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_LOW); + gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_HIGH); +#else + semihosting_exit(ADP_STOPPED_APPLICATION_EXIT, 0); + ERROR("QEMU System Off: semihosting call unexpectedly returned.\n"); +#endif + panic(); +} + +static void __dead2 qemu_system_reset(void) +{ + ERROR("QEMU System Reset: with GPIO.\n"); +#ifdef SECURE_GPIO_BASE + gpio_set_direction(SECURE_GPIO_RESET, GPIO_DIR_OUT); + gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_LOW); + gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_HIGH); +#else + ERROR("QEMU System Reset: operation not handled.\n"); +#endif + panic(); +} + +static const plat_psci_ops_t plat_qemu_psci_pm_ops = { + .cpu_standby = qemu_cpu_standby, + .pwr_domain_on = qemu_pwr_domain_on, + .pwr_domain_off = qemu_pwr_domain_off, + .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi, + .pwr_domain_suspend = qemu_pwr_domain_suspend, + .pwr_domain_on_finish = qemu_pwr_domain_on_finish, + .pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish, + .system_off = qemu_system_off, + .system_reset = qemu_system_reset, + .validate_power_state = qemu_validate_power_state, + .validate_ns_entrypoint = qemu_validate_ns_entrypoint +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *mailbox = (void *) PLAT_QEMU_TRUSTED_MAILBOX_BASE; + + *mailbox = sec_entrypoint; + secure_entrypoint = (unsigned long) sec_entrypoint; + *psci_ops = &plat_qemu_psci_pm_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_private.h b/arm-trusted-firmware/plat/qemu/common/qemu_private.h new file mode 100644 index 0000000..4dc62f5 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_private.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QEMU_PRIVATE_H +#define QEMU_PRIVATE_H + +#include + +void qemu_configure_mmu_svc_mon(unsigned long total_base, + unsigned long total_size, + unsigned long code_start, unsigned long code_limit, + unsigned long ro_start, unsigned long ro_limit, + unsigned long coh_start, unsigned long coh_limit); + +void qemu_configure_mmu_el1(unsigned long total_base, unsigned long total_size, + unsigned long code_start, unsigned long code_limit, + unsigned long ro_start, unsigned long ro_limit, + unsigned long coh_start, unsigned long coh_limit); + +void qemu_configure_mmu_el3(unsigned long total_base, unsigned long total_size, + unsigned long code_start, unsigned long code_limit, + unsigned long ro_start, unsigned long ro_limit, + unsigned long coh_start, unsigned long coh_limit); + +void plat_qemu_io_setup(void); +unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); + +void qemu_console_init(void); + +void plat_qemu_gic_init(void); +void qemu_pwr_gic_on_finish(void); +void qemu_pwr_gic_off(void); + +#endif /* QEMU_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S b/arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S new file mode 100644 index 0000000..5d1b83f --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global qemu_rotpk_hash + .global qemu_rotpk_hash_end +qemu_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +qemu_rotpk_hash_end: diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_spm.c b/arm-trusted-firmware/plat/qemu/common/qemu_spm.c new file mode 100644 index 0000000..c66f47e --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_spm.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2020, Linaro Limited and Contributors. All rights reserved. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* Region equivalent to MAP_DEVICE1 suitable for mapping at EL0 */ +#define MAP_DEVICE1_EL0 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE | MT_USER) + +mmap_region_t plat_qemu_secure_partition_mmap[] = { + QEMU_SP_IMAGE_NS_BUF_MMAP, /* must be placed at first entry */ + MAP_DEVICE1_EL0, /* for the UART */ + QEMU_SP_IMAGE_MMAP, + QEMU_SPM_BUF_EL0_MMAP, + QEMU_SP_IMAGE_RW_MMAP, + MAP_SECURE_VARSTORE, + {0} +}; + +/* Boot information passed to a secure partition during initialisation. */ +static spm_mm_mp_info_t sp_mp_info[PLATFORM_CORE_COUNT]; + +spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = PLAT_QEMU_SP_IMAGE_BASE, + .sp_mem_limit = BL32_LIMIT, + .sp_image_base = PLAT_QEMU_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = PLAT_QEMU_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = PLAT_QEMU_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = PLAT_QEMU_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = sp_mp_info +}; + +/* Enumeration of priority levels on QEMU platforms. */ +ehf_pri_desc_t qemu_exceptions[] = { + EHF_PRI_DESC(QEMU_PRI_BITS, PLAT_SP_PRI) +}; + +static void qemu_initialize_mp_info(spm_mm_mp_info_t *mp_info) +{ + unsigned int i, j; + spm_mm_mp_info_t *tmp = mp_info; + + for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { + for (j = 0; j < PLATFORM_MAX_CPUS_PER_CLUSTER; j++) { + tmp->mpidr = (0x80000000 | (i << MPIDR_AFF1_SHIFT)) + j; + /* + * Linear indices and flags will be filled + * in the spm_mm service. + */ + tmp->linear_id = 0; + tmp->flags = 0; + tmp++; + } + } +} + +int dt_add_ns_buf_node(uintptr_t *base) +{ + uintptr_t addr; + size_t size; + uintptr_t ns_buf_addr; + int node; + int err; + void *fdt = (void *)ARM_PRELOADED_DTB_BASE; + + err = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE); + if (err < 0) { + ERROR("Invalid Device Tree at %p: error %d\n", fdt, err); + return err; + } + + /* + * reserved-memory for standaloneMM non-secure buffer + * is allocated at the top of the first system memory region. + */ + node = fdt_path_offset(fdt, "/memory"); + + err = fdt_get_reg_props_by_index(fdt, node, 0, &addr, &size); + if (err < 0) { + ERROR("Failed to get the memory node information\n"); + return err; + } + INFO("System RAM @ 0x%lx - 0x%lx\n", addr, addr + size - 1); + + ns_buf_addr = addr + (size - PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE); + INFO("reserved-memory for spm-mm @ 0x%lx - 0x%llx\n", ns_buf_addr, + ns_buf_addr + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE - 1); + + err = fdt_add_reserved_memory(fdt, "ns-buf-spm-mm", ns_buf_addr, + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE); + if (err < 0) { + ERROR("Failed to add the reserved-memory node\n"); + return err; + } + + *base = ns_buf_addr; + return 0; +} + +/* Plug in QEMU exceptions to Exception Handling Framework. */ +EHF_REGISTER_PRIORITIES(qemu_exceptions, ARRAY_SIZE(qemu_exceptions), + QEMU_PRI_BITS); + +const mmap_region_t *plat_get_secure_partition_mmap(void *cookie) +{ + uintptr_t ns_buf_base; + + dt_add_ns_buf_node(&ns_buf_base); + + plat_qemu_secure_partition_mmap[0].base_pa = ns_buf_base; + plat_qemu_secure_partition_mmap[0].base_va = ns_buf_base; + plat_qemu_secure_partition_boot_info.sp_ns_comm_buf_base = ns_buf_base; + + return plat_qemu_secure_partition_mmap; +} + +const spm_mm_boot_info_t * +plat_get_secure_partition_boot_info(void *cookie) +{ + qemu_initialize_mp_info(sp_mp_info); + + return &plat_qemu_secure_partition_boot_info; +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c b/arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c new file mode 100644 index 0000000..fd46e26 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest, + const void *pm_addr) +{ + entry_point_info_t *ep_info = bl31_plat_get_next_image_ep_info(SECURE); + + assert(ep_info != NULL); + assert(manifest != NULL); + + manifest->major_version = 1; + manifest->minor_version = 0; + manifest->exec_state = ep_info->args.arg2; + manifest->load_address = BL32_BASE; + manifest->entrypoint = BL32_BASE; + manifest->binary_size = BL32_LIMIT - BL32_BASE; + manifest->spmc_id = 0x8000; + + return 0; +} diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c b/arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c new file mode 100644 index 0000000..15ce3d6 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ +#if ENABLE_FEAT_RNG + /* Use the RNDR instruction if the CPU supports it */ + if (is_armv8_5_rng_present()) { + return read_rndr(); + } +#endif + + /* + * Ideally, a random number should be returned above. If a random + * number generator is not supported, return instead a + * combination of a timer's value and a compile-time constant. + * This is better than nothing but not necessarily really secure. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} + diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c b/arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c new file mode 100644 index 0000000..1ef7e43 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +extern char qemu_rotpk_hash[], qemu_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = qemu_rotpk_hash; + *key_len = qemu_rotpk_hash_end - qemu_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min-qemu.mk b/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min-qemu.mk new file mode 100644 index 0000000..e93a0c2 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min-qemu.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += plat/qemu/sp_min/sp_min_setup.c \ + plat/qemu/aarch32/plat_helpers.S \ + plat/qemu/qemu_pm.c \ + plat/qemu/topology.c + +BL32_SOURCES += lib/cpus/aarch32/aem_generic.S \ + lib/cpus/aarch32/cortex_a15.S + +BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \ + plat/common/plat_psci_common.c \ + plat/common/plat_gicv2.c + + +BL32_SOURCES += drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/common/gic_common.c diff --git a/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c b/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c new file mode 100644 index 0000000..7ec657b --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017-2019, 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 "../qemu_private.h" + +#if RESET_TO_SP_MIN +#error qemu does not support RESET_TO_SP_MIN +#endif + +static entry_point_info_t bl33_image_ep_info; + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL) + +#define PLATFORM_G0_PROPS(grp) + +static const interrupt_prop_t stih410_interrupt_props[] = { + PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0), + PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const struct gicv2_driver_data plat_gicv2_driver_data = { + .gicd_base = GICD_BASE, + .gicc_base = GICC_BASE, + .interrupt_props = stih410_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(stih410_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) +{ + entry_point_info_t *next_image_info = &bl33_image_ep_info; + + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + bl_params_t *params_from_bl2 = (bl_params_t *)arg0; + + /* Initialize the console to provide early debug support */ + qemu_console_init(); + + ERROR("qemu sp_min, console init\n"); + /* + * Check params passed from BL2 + */ + assert(params_from_bl2); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 entry point information from BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (!bl33_image_ep_info.pc) + panic(); +} + +void sp_min_plat_arch_setup(void) +{ + qemu_configure_mmu_svc_mon(BL32_RO_BASE, BL32_END - BL32_RO_BASE, + BL_CODE_BASE, BL_CODE_END, + BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); + +} + +void sp_min_platform_setup(void) +{ + /* Initialize the gic cpu and distributor interfaces */ + gicv2_driver_init(&plat_gicv2_driver_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +void sp_min_plat_fiq_handler(uint32_t id) +{ + VERBOSE("[sp_min] interrupt #%d\n", id); +} diff --git a/arm-trusted-firmware/plat/qemu/common/topology.c b/arm-trusted-firmware/plat/qemu/common/topology.c new file mode 100644 index 0000000..6352706 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/topology.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include "qemu_private.h" + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first node */ + PLATFORM_CLUSTER0_CORE_COUNT, + /* Number of children for the second node */ + PLATFORM_CLUSTER1_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the ARM default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) + return -1; + + return plat_qemu_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h b/arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h new file mode 100644 index 0000000..c02eff9 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define QEMU_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define PLATFORM_STACK_SIZE 0x1000 + +#if ARM_ARCH_MAJOR == 7 +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#else +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +/* + * Define the number of cores per cluster used in calculating core position. + * The cluster number is shifted by this value and added to the core ID, + * so its value represents log2(cores/cluster). + * Default is 2**(2) = 4 cores per cluster. + */ +#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(2) + +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#endif +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ + PLATFORM_CLUSTER1_CORE_COUNT) + +#define QEMU_PRIMARY_CPU U(0) + +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF 2 + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH 4 +#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Partition memory into secure ROM, non-secure DRAM, secure "SRAM", + * and secure DRAM. + */ +#define SEC_ROM_BASE 0x00000000 +#define SEC_ROM_SIZE 0x00020000 + +#define NS_DRAM0_BASE ULL(0x40000000) +#define NS_DRAM0_SIZE ULL(0xc0000000) + +#define SEC_SRAM_BASE 0x0e000000 +#define SEC_SRAM_SIZE 0x00060000 + +#define SEC_DRAM_BASE 0x0e100000 +#define SEC_DRAM_SIZE 0x00f00000 + +#define SECURE_GPIO_BASE 0x090b0000 +#define SECURE_GPIO_SIZE 0x00001000 +#define SECURE_GPIO_POWEROFF 0 +#define SECURE_GPIO_RESET 1 + +/* Load pageable part of OP-TEE 2MB above secure DRAM base */ +#define QEMU_OPTEE_PAGEABLE_LOAD_BASE (SEC_DRAM_BASE + 0x00200000) +#define QEMU_OPTEE_PAGEABLE_LOAD_SIZE 0x00400000 + +/* + * ARM-TF lives in SRAM, partition it here + */ + +#define SHARED_RAM_BASE SEC_SRAM_BASE +#define SHARED_RAM_SIZE 0x00001000 + +#define PLAT_QEMU_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE +#define PLAT_QEMU_TRUSTED_MAILBOX_SIZE (8 + PLAT_QEMU_HOLD_SIZE) +#define PLAT_QEMU_HOLD_BASE (PLAT_QEMU_TRUSTED_MAILBOX_BASE + 8) +#define PLAT_QEMU_HOLD_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_QEMU_HOLD_ENTRY_SIZE) +#define PLAT_QEMU_HOLD_ENTRY_SHIFT 3 +#define PLAT_QEMU_HOLD_ENTRY_SIZE (1 << PLAT_QEMU_HOLD_ENTRY_SHIFT) +#define PLAT_QEMU_HOLD_STATE_WAIT 0 +#define PLAT_QEMU_HOLD_STATE_GO 1 + +#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE) +#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE) + +/* + * BL1 specific defines. + * + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using + * the current BL1 RW debug size plus a little space for growth. + */ +#define BL1_RO_BASE SEC_ROM_BASE +#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE) +#define BL1_RW_BASE (BL1_RW_LIMIT - 0x12000) +#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) + +/* + * BL2 specific defines. + * + * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define BL2_BASE (BL31_BASE - 0x25000) +#define BL2_LIMIT BL31_BASE + +/* + * BL3-1 specific defines. + * + * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL3-1 debug size plus a little space for growth. + */ +#define BL31_BASE (BL31_LIMIT - 0x20000) +#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE + + +/* + * BL3-2 specific defines. + * + * BL3-2 can execute from Secure SRAM, or Secure DRAM. + */ +#define BL32_SRAM_BASE BL_RAM_BASE +#define BL32_SRAM_LIMIT BL31_BASE +#define BL32_DRAM_BASE SEC_DRAM_BASE +#define BL32_DRAM_LIMIT (SEC_DRAM_BASE + SEC_DRAM_SIZE) + +#define SEC_SRAM_ID 0 +#define SEC_DRAM_ID 1 + +#if BL32_RAM_LOCATION_ID == SEC_SRAM_ID +# define BL32_MEM_BASE BL_RAM_BASE +# define BL32_MEM_SIZE BL_RAM_SIZE +# define BL32_BASE BL32_SRAM_BASE +# define BL32_LIMIT BL32_SRAM_LIMIT +#elif BL32_RAM_LOCATION_ID == SEC_DRAM_ID +# define BL32_MEM_BASE SEC_DRAM_BASE +# define BL32_MEM_SIZE SEC_DRAM_SIZE +# define BL32_BASE BL32_DRAM_BASE +# define BL32_LIMIT BL32_DRAM_LIMIT +#else +# error "Unsupported BL32_RAM_LOCATION_ID value" +#endif + +#define NS_IMAGE_OFFSET (NS_DRAM0_BASE + 0x20000000) +#define NS_IMAGE_MAX_SIZE (NS_DRAM0_SIZE - 0x20000000) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_MMAP_REGIONS 11 +#define MAX_XLAT_TABLES 6 +#define MAX_IO_DEVICES 4 +#define MAX_IO_HANDLES 4 + +/* + * PL011 related constants + */ +#define UART0_BASE 0x09000000 +#define UART1_BASE 0x09040000 +#define UART0_CLK_IN_HZ 1 +#define UART1_CLK_IN_HZ 1 + +#define PLAT_QEMU_BOOT_UART_BASE UART0_BASE +#define PLAT_QEMU_BOOT_UART_CLK_IN_HZ UART0_CLK_IN_HZ + +#define PLAT_QEMU_CRASH_UART_BASE UART1_BASE +#define PLAT_QEMU_CRASH_UART_CLK_IN_HZ UART1_CLK_IN_HZ + +#define PLAT_QEMU_CONSOLE_BAUDRATE 115200 + +#define QEMU_FLASH0_BASE 0x00000000 +#define QEMU_FLASH0_SIZE 0x04000000 +#define QEMU_FLASH1_BASE 0x04000000 +#define QEMU_FLASH1_SIZE 0x04000000 + +#define PLAT_QEMU_FIP_BASE 0x00040000 +#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000 + +#define DEVICE0_BASE 0x08000000 +#define DEVICE0_SIZE 0x01000000 +#define DEVICE1_BASE 0x09000000 +#define DEVICE1_SIZE 0x00c00000 + +/* + * GIC related constants + */ + +#define GICD_BASE 0x8000000 +#define GICC_BASE 0x8010000 +#define GICR_BASE 0x80A0000 + + +#define QEMU_IRQ_SEC_SGI_0 8 +#define QEMU_IRQ_SEC_SGI_1 9 +#define QEMU_IRQ_SEC_SGI_2 10 +#define QEMU_IRQ_SEC_SGI_3 11 +#define QEMU_IRQ_SEC_SGI_4 12 +#define QEMU_IRQ_SEC_SGI_5 13 +#define QEMU_IRQ_SEC_SGI_6 14 +#define QEMU_IRQ_SEC_SGI_7 15 + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE) + +#define PLATFORM_G0_PROPS(grp) + +/* + * DT related constants + */ +#define PLAT_QEMU_DT_BASE NS_DRAM0_BASE +#define PLAT_QEMU_DT_MAX_SIZE 0x100000 + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/qemu/qemu/platform.mk b/arm-trusted-firmware/plat/qemu/qemu/platform.mk new file mode 100644 index 0000000..a8f978a --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu/platform.mk @@ -0,0 +1,232 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Use the GICv2 driver on QEMU by default +QEMU_USE_GIC_DRIVER := QEMU_GICV2 + +ifeq (${ARM_ARCH_MAJOR},7) +# ARMv7 Qemu support in trusted firmware expects the Cortex-A15 model. +# Qemu Cortex-A15 model does not implement the virtualization extension. +# For this reason, we cannot set ARM_CORTEX_A15=yes and must define all +# the ARMv7 build directives. +MARCH32_DIRECTIVE := -mcpu=cortex-a15 +$(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)) +$(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER)) +$(eval $(call add_define,ARMV7_SUPPORTS_VFP)) +# Qemu expects a BL32 boot stage. +NEED_BL32 := yes +endif # ARMv7 + +ifeq (${SPD},opteed) +add-lib-optee := yes +endif +ifeq ($(AARCH32_SP),optee) +add-lib-optee := yes +endif +ifeq ($(SPMC_OPTEE),1) +$(eval $(call add_define,SPMC_OPTEE)) +add-lib-optee := yes +endif + +include lib/libfdt/libfdt.mk + +ifeq ($(NEED_BL32),yes) +$(eval $(call add_define,QEMU_LOAD_BL32)) +endif + +PLAT_QEMU_PATH := plat/qemu/qemu +PLAT_QEMU_COMMON_PATH := plat/qemu/common +PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ + -I${PLAT_QEMU_COMMON_PATH}/include \ + -I${PLAT_QEMU_PATH}/include \ + -Iinclude/common/tbbr + +ifeq (${ARM_ARCH_MAJOR},8) +PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH} +endif + +PLAT_BL_COMMON_SOURCES := ${PLAT_QEMU_COMMON_PATH}/qemu_common.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_console.c \ + drivers/arm/pl011/${ARCH}/pl011_console.S + +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +ifneq (${TRUSTED_BOARD_BOOT},0) + + include drivers/auth/mbedtls/mbedtls_crypto.mk + include drivers/auth/mbedtls/mbedtls_x509.mk + + AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c + + BL1_SOURCES += ${AUTH_SOURCES} \ + bl1/tbbr/tbbr_img_desc.c \ + plat/common/tbbr/plat_tbbr.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c \ + $(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl1.c + + BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c \ + $(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl2.c + + ROT_KEY = $(BUILD_PLAT)/rot_key.pem + ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + + $(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) + + $(BUILD_PLAT)/bl1/qemu_rotpk.o: $(ROTPK_HASH) + $(BUILD_PLAT)/bl2/qemu_rotpk.o: $(ROTPK_HASH) + + certificates: $(ROT_KEY) + + $(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + $(Q)openssl genrsa 2048 > $@ 2>/dev/null + + $(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +BL1_SOURCES += drivers/io/io_semihosting.c \ + drivers/io/io_storage.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \ + ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_bl1_setup.c + +ifeq (${ARM_ARCH_MAJOR},8) +BL1_SOURCES += lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/qemu_max.S \ + +else +BL1_SOURCES += lib/cpus/${ARCH}/cortex_a15.S +endif + +BL2_SOURCES += drivers/io/io_semihosting.c \ + drivers/io/io_storage.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \ + ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_setup.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_image_load.c \ + common/fdt_fixup.c \ + common/desc_image_load.c + +ifeq ($(add-lib-optee),yes) +BL2_SOURCES += lib/optee/optee_utils.c +endif + +ifneq (${DECRYPTION_SUPPORT},none) +BL1_SOURCES += drivers/io/io_encrypted.c +BL2_SOURCES += drivers/io/io_encrypted.c +endif + +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk +QEMU_GICV2_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_gicv2.c + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +QEMU_GICV3_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c + +ifeq (${QEMU_USE_GIC_DRIVER}, QEMU_GICV2) +QEMU_GIC_SOURCES := ${QEMU_GICV2_SOURCES} +else ifeq (${QEMU_USE_GIC_DRIVER}, QEMU_GICV3) +QEMU_GIC_SOURCES := ${QEMU_GICV3_SOURCES} +else +$(error "Incorrect GIC driver chosen for QEMU platform") +endif + +ifeq (${ARM_ARCH_MAJOR},8) +BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/qemu_max.S \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/common/plat_psci_common.c \ + drivers/arm/pl061/pl061_gpio.c \ + drivers/gpio/gpio.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_pm.c \ + ${PLAT_QEMU_COMMON_PATH}/topology.c \ + ${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c \ + ${QEMU_GIC_SOURCES} + +ifeq (${SPD},spmd) +BL31_SOURCES += plat/qemu/common/qemu_spmd_manifest.c +endif +endif + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +ifneq (${DECRYPTION_SUPPORT},none) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1,,$(ENCRYPT_BL32))) +else +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) +endif +endif +ifneq ($(BL32_EXTRA2),) +ifneq (${DECRYPTION_SUPPORT},none) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2,,$(ENCRYPT_BL32))) +else +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) +endif +endif + +SEPARATE_CODE_AND_RODATA := 1 +ENABLE_STACK_PROTECTOR := 0 +ifneq ($(ENABLE_STACK_PROTECTOR), 0) + PLAT_BL_COMMON_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_stack_protector.c +endif + +BL32_RAM_LOCATION := tdram +ifeq (${BL32_RAM_LOCATION}, tsram) + BL32_RAM_LOCATION_ID = SEC_SRAM_ID +else ifeq (${BL32_RAM_LOCATION}, tdram) + BL32_RAM_LOCATION_ID = SEC_DRAM_ID +else + $(error "Unsupported BL32_RAM_LOCATION value") +endif + +# Process flags +$(eval $(call add_define,BL32_RAM_LOCATION_ID)) + +# Don't have the Linux kernel as a BL33 image by default +ARM_LINUX_KERNEL_AS_BL33 := 0 +$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33)) +$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33)) + +ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE +$(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h b/arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h new file mode 100644 index 0000000..d971ebe --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2019-2020, Linaro Limited and Contributors. + * All rights reserved. + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define QEMU_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define PLATFORM_STACK_SIZE 0x1000 + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8) +/* + * Define the number of cores per cluster used in calculating core position. + * The cluster number is shifted by this value and added to the core ID, + * so its value represents log2(cores/cluster). + * Default is 2**(3) = 8 cores per cluster. + */ +#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(3) +#define PLATFORM_CLUSTER_COUNT U(64) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) +#define QEMU_PRIMARY_CPU U(0) + +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 + +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN 0 +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET 1 +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF 2 + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH 4 +#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Partition memory into secure ROM, non-secure DRAM, secure "SRAM", + * and secure DRAM. + */ +#define SEC_ROM_BASE 0x00000000 +#define SEC_ROM_SIZE 0x00020000 + +#define NS_DRAM0_BASE 0x10000000000ULL +#define NS_DRAM0_SIZE 0x00020000000 + +#define SEC_SRAM_BASE 0x20000000 +#define SEC_SRAM_SIZE 0x20000000 + +/* + * RAD just placeholders, need to be chosen after finalizing mem map + */ +#define SEC_DRAM_BASE 0x1000 +#define SEC_DRAM_SIZE 0x1000 + +/* Load pageable part of OP-TEE 2MB above secure DRAM base */ +#define QEMU_OPTEE_PAGEABLE_LOAD_BASE (SEC_DRAM_BASE + 0x00200000) +#define QEMU_OPTEE_PAGEABLE_LOAD_SIZE 0x00400000 + +/* + * ARM-TF lives in SRAM, partition it here + */ + +#define SHARED_RAM_BASE SEC_SRAM_BASE +#define SHARED_RAM_SIZE 0x00002000 + +#define PLAT_QEMU_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE +#define PLAT_QEMU_TRUSTED_MAILBOX_SIZE (8 + PLAT_QEMU_HOLD_SIZE) +#define PLAT_QEMU_HOLD_BASE (PLAT_QEMU_TRUSTED_MAILBOX_BASE + 8) +#define PLAT_QEMU_HOLD_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_QEMU_HOLD_ENTRY_SIZE) +#define PLAT_QEMU_HOLD_ENTRY_SHIFT 3 +#define PLAT_QEMU_HOLD_ENTRY_SIZE (1 << PLAT_QEMU_HOLD_ENTRY_SHIFT) +#define PLAT_QEMU_HOLD_STATE_WAIT 0 +#define PLAT_QEMU_HOLD_STATE_GO 1 + +#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE) +#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE) + +/* + * BL1 specific defines. + * + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using + * the current BL1 RW debug size plus a little space for growth. + */ +#define BL1_SIZE 0x12000 +#define BL1_RO_BASE SEC_ROM_BASE +#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE) +#define BL1_RW_BASE (BL1_RW_LIMIT - BL1_SIZE) +#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) + +/* + * BL2 specific defines. + * + * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define BL2_SIZE 0x1D000 +#define BL2_BASE (BL31_BASE - BL2_SIZE) +#define BL2_LIMIT BL31_BASE + +/* + * BL3-1 specific defines. + * + * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL3-1 debug size plus a little space for growth. + */ +#define BL31_SIZE 0x300000 +#define BL31_BASE (BL31_LIMIT - BL31_SIZE) +#define BL31_LIMIT (BL1_RW_BASE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE + + +/* + * BL3-2 specific defines. + * + * BL3-2 can execute from Secure SRAM, or Secure DRAM. + */ +#define BL32_SRAM_BASE BL_RAM_BASE +#define BL32_SRAM_LIMIT BL2_BASE + +#define BL32_MEM_BASE BL_RAM_BASE +#define BL32_MEM_SIZE (BL_RAM_SIZE - BL1_SIZE - \ + BL2_SIZE - BL31_SIZE) +#define BL32_BASE BL32_SRAM_BASE +#define BL32_LIMIT BL32_SRAM_LIMIT + +#define NS_IMAGE_OFFSET (NS_DRAM0_BASE + 0x20000000) +#define NS_IMAGE_MAX_SIZE (NS_DRAM0_SIZE - 0x20000000) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 42) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 42) +#if SPM_MM +#define MAX_MMAP_REGIONS 12 +#define MAX_XLAT_TABLES 12 +#else +#define MAX_MMAP_REGIONS 11 +#define MAX_XLAT_TABLES 11 +#endif +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +#if SPM_MM && defined(IMAGE_BL31) +# define PLAT_SP_IMAGE_MMAP_REGIONS 30 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 50 +#endif + +/* + * PL011 related constants + */ +#define UART0_BASE 0x60000000 +#define UART1_BASE 0x60030000 +#define UART0_CLK_IN_HZ 1 +#define UART1_CLK_IN_HZ 1 + +/* Secure UART */ +#define UART2_BASE 0x60040000 +#define UART2_CLK_IN_HZ 1 + +#define PLAT_QEMU_BOOT_UART_BASE UART0_BASE +#define PLAT_QEMU_BOOT_UART_CLK_IN_HZ UART0_CLK_IN_HZ + +#define PLAT_QEMU_CRASH_UART_BASE UART1_BASE +#define PLAT_QEMU_CRASH_UART_CLK_IN_HZ UART1_CLK_IN_HZ + +#define PLAT_QEMU_CONSOLE_BAUDRATE 115200 + +#define QEMU_FLASH0_BASE 0x00000000 +#define QEMU_FLASH0_SIZE 0x10000000 +#define QEMU_FLASH1_BASE 0x10000000 +#define QEMU_FLASH1_SIZE 0x10000000 + +#define PLAT_QEMU_FIP_BASE 0x00008000 +#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000 + +/* This is map from GIC_DIST up to last CPU (255) GIC_REDISTR */ +#define DEVICE0_BASE 0x40000000 +#define DEVICE0_SIZE 0x04080000 +/* This is map from NORMAL_UART up to SECURE_UART_MM */ +#define DEVICE1_BASE 0x60000000 +#define DEVICE1_SIZE 0x10041000 +/* This is a map for SECURE_EC */ +#define DEVICE2_BASE 0x50000000 +#define DEVICE2_SIZE 0x00001000 + +/* + * GIC related constants + * We use GICv3 where CPU Interface registers are not memory mapped + */ +#define GICD_BASE 0x40060000 +#define GICR_BASE 0x40080000 +#define GICC_BASE 0x0 + +#define QEMU_IRQ_SEC_SGI_0 8 +#define QEMU_IRQ_SEC_SGI_1 9 +#define QEMU_IRQ_SEC_SGI_2 10 +#define QEMU_IRQ_SEC_SGI_3 11 +#define QEMU_IRQ_SEC_SGI_4 12 +#define QEMU_IRQ_SEC_SGI_5 13 +#define QEMU_IRQ_SEC_SGI_6 14 +#define QEMU_IRQ_SEC_SGI_7 15 + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE) + +#define PLATFORM_G0_PROPS(grp) + +/* + * DT related constants + */ +#define PLAT_QEMU_DT_BASE NS_DRAM0_BASE +#define PLAT_QEMU_DT_MAX_SIZE 0x100000 + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16) + +#if SPM_MM +#define PLAT_QEMU_SP_IMAGE_BASE BL_RAM_BASE +#define PLAT_QEMU_SP_IMAGE_SIZE ULL(0x300000) + +#ifdef IMAGE_BL2 +/* In BL2 all memory allocated to the SPM Payload image is marked as RW. */ +# define QEMU_SP_IMAGE_MMAP MAP_REGION_FLAT( \ + PLAT_QEMU_SP_IMAGE_BASE, \ + PLAT_QEMU_SP_IMAGE_SIZE, \ + MT_MEMORY | MT_RW | \ + MT_SECURE) +#elif IMAGE_BL31 +/* All SPM Payload memory is marked as code in S-EL0 */ +# define QEMU_SP_IMAGE_MMAP MAP_REGION2(PLAT_QEMU_SP_IMAGE_BASE, \ + PLAT_QEMU_SP_IMAGE_BASE, \ + PLAT_QEMU_SP_IMAGE_SIZE, \ + MT_CODE | MT_SECURE | \ + MT_USER, \ + PAGE_SIZE) +#endif + +/* + * EL3 -> S-EL0 secure shared memory + */ +#define PLAT_SPM_BUF_PCPU_SIZE ULL(0x10000) +#define PLAT_SPM_BUF_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_SPM_BUF_PCPU_SIZE) +#define PLAT_SPM_BUF_BASE (BL32_LIMIT - PLAT_SPM_BUF_SIZE) + +#define QEMU_SPM_BUF_EL3_MMAP MAP_REGION_FLAT(PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_SIZE, \ + MT_RW_DATA | MT_SECURE) + +#define QEMU_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) + +/* + * Shared memory between Normal world and S-EL0 for + * passing data during service requests. It will be marked as RW and NS. + * This buffer is allocated at the top of NS_DRAM, the base address is + * overridden in SPM initialization. + */ +#define PLAT_QEMU_SP_IMAGE_NS_BUF_BASE (PLAT_QEMU_DT_BASE + \ + PLAT_QEMU_DT_MAX_SIZE) +#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE ULL(0x200000) + +#define QEMU_SP_IMAGE_NS_BUF_MMAP MAP_REGION2( \ + PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \ + PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \ + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE, \ + MT_RW_DATA | MT_NS | \ + MT_USER, \ + PAGE_SIZE) + +#define PLAT_SP_IMAGE_NS_BUF_BASE PLAT_QEMU_SP_IMAGE_NS_BUF_BASE +#define PLAT_SP_IMAGE_NS_BUF_SIZE PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE + +#define PLAT_QEMU_SP_IMAGE_HEAP_BASE (PLAT_QEMU_SP_IMAGE_BASE + \ + PLAT_QEMU_SP_IMAGE_SIZE) +#define PLAT_QEMU_SP_IMAGE_HEAP_SIZE ULL(0x800000) + +#define PLAT_SP_IMAGE_STACK_BASE (PLAT_QEMU_SP_IMAGE_HEAP_BASE + \ + PLAT_QEMU_SP_IMAGE_HEAP_SIZE) +#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x10000) +#define QEMU_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_SP_IMAGE_STACK_PCPU_SIZE) + +#define QEMU_SP_IMAGE_RW_MMAP MAP_REGION2( \ + PLAT_QEMU_SP_IMAGE_HEAP_BASE, \ + PLAT_QEMU_SP_IMAGE_HEAP_BASE, \ + (QEMU_SP_IMAGE_STACK_TOTAL_SIZE + \ + PLAT_QEMU_SP_IMAGE_HEAP_SIZE), \ + MT_RW_DATA | MT_SECURE | \ + MT_USER, \ + PAGE_SIZE) + +/* + * Secure variable storage is located at Secure Flash. + */ +#if SPM_MM +#define QEMU_SECURE_VARSTORE_BASE 0x01000000 +#define QEMU_SECURE_VARSTORE_SIZE 0x00100000 +#define MAP_SECURE_VARSTORE MAP_REGION_FLAT( \ + QEMU_SECURE_VARSTORE_BASE, \ + QEMU_SECURE_VARSTORE_SIZE, \ + MT_DEVICE | MT_RW | \ + MT_SECURE | MT_USER) +#endif + +/* Total number of memory regions with distinct properties */ +#define PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS 6 + +/* + * Name of the section to put the translation tables used by the S-EL1/S-EL0 + * context of a Secure Partition. + */ +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "qemu_sp_xlat_table" +#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME "qemu_sp_xlat_table" + +/* Cookies passed to the Secure Partition at boot. Not used by QEMU platforms.*/ +#define PLAT_SPM_COOKIE_0 ULL(0) +#define PLAT_SPM_COOKIE_1 ULL(0) +#endif + +#define QEMU_PRI_BITS 2 +#define PLAT_SP_PRI 0x20 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/qemu/qemu_sbsa/platform.mk b/arm-trusted-firmware/plat/qemu/qemu_sbsa/platform.mk new file mode 100644 index 0000000..5a6b1e1 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu_sbsa/platform.mk @@ -0,0 +1,127 @@ +# +# Copyright (c) 2019-2021, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +CRASH_REPORTING := 1 + +include lib/libfdt/libfdt.mk + +ifeq (${SPM_MM},1) +NEED_BL32 := yes +EL3_EXCEPTION_HANDLING := 1 +GICV2_G0_FOR_EL3 := 1 +endif + +# Enable new version of image loading on QEMU platforms +LOAD_IMAGE_V2 := 1 + +ifeq ($(NEED_BL32),yes) +$(eval $(call add_define,QEMU_LOAD_BL32)) +endif + +PLAT_QEMU_PATH := plat/qemu/qemu_sbsa +PLAT_QEMU_COMMON_PATH := plat/qemu/common +PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ + -I${PLAT_QEMU_COMMON_PATH}/include \ + -I${PLAT_QEMU_PATH}/include \ + -Iinclude/common/tbbr + +PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH} + +PLAT_BL_COMMON_SOURCES := ${PLAT_QEMU_COMMON_PATH}/qemu_common.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_console.c \ + drivers/arm/pl011/${ARCH}/pl011_console.S + +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +BL1_SOURCES += drivers/io/io_semihosting.c \ + drivers/io/io_storage.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \ + ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_bl1_setup.c + +BL1_SOURCES += lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/qemu_max.S \ + +BL2_SOURCES += drivers/io/io_semihosting.c \ + drivers/io/io_storage.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \ + ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_setup.c \ + common/fdt_fixup.c \ + $(LIBFDT_SRCS) +ifeq (${LOAD_IMAGE_V2},1) +BL2_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_image_load.c \ + common/desc_image_load.c +endif + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +QEMU_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + ${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/qemu_max.S \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/common/plat_psci_common.c \ + ${PLAT_QEMU_PATH}/sbsa_pm.c \ + ${PLAT_QEMU_PATH}/sbsa_topology.c \ + ${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S \ + ${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c \ + common/fdt_fixup.c \ + ${QEMU_GIC_SOURCES} + +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +ifeq (${SPM_MM},1) + BL31_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_spm.c +endif + +SEPARATE_CODE_AND_RODATA := 1 +ENABLE_STACK_PROTECTOR := 0 +ifneq ($(ENABLE_STACK_PROTECTOR), 0) + PLAT_BL_COMMON_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_stack_protector.c +endif + +MULTI_CONSOLE_API := 1 + +# Disable the PSCI platform compatibility layer +ENABLE_PLAT_COMPAT := 0 + +# Use known base for UEFI if not given from command line +# By default BL33 is at FLASH1 base +PRELOADED_BL33_BASE ?= 0x10000000 + +# Qemu SBSA plafrom only support SEC_SRAM +BL32_RAM_LOCATION_ID = SEC_SRAM_ID +$(eval $(call add_define,BL32_RAM_LOCATION_ID)) + +# Don't have the Linux kernel as a BL33 image by default +ARM_LINUX_KERNEL_AS_BL33 := 0 +$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33)) +$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33)) + +ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE +$(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c new file mode 100644 index 0000000..8d1e1d4 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include +#include +#include +#include +#include + +#include +#include "sbsa_private.h" + +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 + +/* + * Define offset and commands for the fake EC device + */ +#define SBSA_SECURE_EC_OFFSET 0x50000000 + +#define SBSA_SECURE_EC_CMD_SHUTDOWN 0x01 +#define SBSA_SECURE_EC_CMD_REBOOT 0x02 + +/* + * The secure entry point to be used on warm reset. + */ +static unsigned long secure_entrypoint; + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#else +#define qemu_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 */ + + +#define qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ + qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + + + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +static const unsigned int qemu_pm_idle_states[] = { + /* State-id - 0x01 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, + MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0 +}; + +/******************************************************************************* + * Platform handler called to check the validity of the power state + * parameter. The power state parameter has to be a composite power state. + ******************************************************************************/ +static int qemu_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + unsigned int i; + + assert(req_state != NULL); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justifies the additional complexity. + */ + for (i = 0U; qemu_pm_idle_states[i] != 0U; i++) { + if (power_state == qemu_pm_idle_states[i]) { + break; + } + } + + /* Return error if entry not found in the idle state array */ + if (qemu_pm_idle_states[i] == 0U) { + return PSCI_E_INVALID_PARAMS; + } + + i = 0U; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id != 0U) { + req_state->pwr_domain_state[i++] = state_id & + PLAT_LOCAL_PSTATE_MASK; + state_id >>= PLAT_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void qemu_cpu_standby(plat_local_state_t cpu_state) +{ + + assert(cpu_state == PLAT_LOCAL_STATE_RET); + + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int qemu_pwr_domain_on(u_register_t mpidr) +{ + int pos = plat_core_pos_by_mpidr(mpidr); + uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE; + + if (pos < 0) { + return PSCI_E_INVALID_PARAMS; + } + + hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO; + dsb(); + sev(); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void qemu_pwr_domain_off(const psci_power_state_t *target_state) +{ + qemu_pwr_gic_off(); +} + +void __dead2 plat_secondary_cold_boot_setup(void); + +static void __dead2 +qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + disable_mmu_el3(); + plat_secondary_cold_boot_setup(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void qemu_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + assert(false); +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void qemu_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + qemu_pwr_gic_on_finish(); +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + ******************************************************************************/ +void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + assert(false); +} + +/******************************************************************************* + * Platform handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 qemu_system_off(void) +{ + mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_SHUTDOWN); + panic(); +} + +static void __dead2 qemu_system_reset(void) +{ + mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_REBOOT); + panic(); +} + +static const plat_psci_ops_t plat_qemu_psci_pm_ops = { + .cpu_standby = qemu_cpu_standby, + .pwr_domain_on = qemu_pwr_domain_on, + .pwr_domain_off = qemu_pwr_domain_off, + .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi, + .pwr_domain_suspend = qemu_pwr_domain_suspend, + .pwr_domain_on_finish = qemu_pwr_domain_on_finish, + .pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish, + .system_off = qemu_system_off, + .system_reset = qemu_system_reset, + .validate_power_state = qemu_validate_power_state +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *mailbox = (uintptr_t *)PLAT_QEMU_TRUSTED_MAILBOX_BASE; + + *mailbox = sec_entrypoint; + secure_entrypoint = (unsigned long)sec_entrypoint; + *psci_ops = &plat_qemu_psci_pm_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h new file mode 100644 index 0000000..a9f4601 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SBSA_PRIVATE_H +#define SBSA_PRIVATE_H + +#include + +unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); + +void qemu_pwr_gic_on_finish(void); +void qemu_pwr_gic_off(void); + +#endif /* SBSA_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c new file mode 100644 index 0000000..bd8d16b --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include "sbsa_private.h" + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[PLATFORM_CLUSTER_COUNT + 1]; + +/******************************************************************************* + * This function returns the sbsa-ref default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + + power_domain_tree_desc[0] = PLATFORM_CLUSTER_COUNT; + + for (i = 0U; i < PLATFORM_CLUSTER_COUNT; i++) { + power_domain_tree_desc[i + 1] = PLATFORM_MAX_CPUS_PER_CLUSTER; + } + + return power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) { + ERROR("Invalid MPIDR\n"); + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + ERROR("cluster_id >= PLATFORM_CLUSTER_COUNT define\n"); + return -1; + } + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + ERROR("cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER define\n"); + return -1; + } + + return plat_qemu_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S b/arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S new file mode 100644 index 0000000..2e292fb --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_MACROS_S__ +#define __PLAT_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)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +/** Macro : plat_crash_print_regs + * This macro allows the crash reporting routine to print GIC registers + * in case of an unhandled exception in BL31. This aids in debugging and + * this macro can be defined to be empty in case GIC register reporting is + * not desired. + * The below required platform porting macro + * prints out relevant GIC registers whenever an + * unhandled exception is taken in BL31. + * Clobbers: x0 - x10, x26, x27, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs +print_gic_regs: + ldr x26, =QTI_GICD_BASE + ldr x27, =QTI_GICC_BASE + + /* 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, [x27, #GICC_HPPIR] + ldr w9, [x27, #GICC_AHPPIR] + ldr w10, [x27, #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, x26, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +gicd_ispendr_loop: + sub x4, x7, x26 + cmp x4, #0x280 + b.eq exit_print_gic_regs + bl asm_print_hex + + 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 /* __PLAT_MACROS_S__ */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h b/arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h new file mode 100644 index 0000000..c95e4c0 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef QTI_BOARD_DEF_H +#define QTI_BOARD_DEF_H + +/* + * Required platform porting definitions common to all ARM + * development platforms + */ + +/* + * Defines used to retrieve QTI SOC Version + */ +#define JEDEC_QTI_BKID U(0x0) +#define JEDEC_QTI_MFID U(0x70) +#define QTI_SOC_CONTINUATION_SHIFT U(24) +#define QTI_SOC_IDENTIFICATION_SHIFT U(16) + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x1000 + +/* + * PLAT_QTI_MMAP_ENTRIES depends on the number of entries in the + * plat_qti_mmap array defined for each BL stage. + */ +#define PLAT_QTI_MMAP_ENTRIES 12 + +/* + * Platform specific page table and MMU setup constants + */ +#define MAX_XLAT_TABLES 12 + +#endif /* QTI_BOARD_DEF_H */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h b/arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h new file mode 100644 index 0000000..3316f7b --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTI_CPU_H +#define QTI_CPU_H + +/* KRYO-4xx Gold MIDR */ +#define QTI_KRYO4_GOLD_MIDR 0x517F804D + +/* KRYO-4xx Silver MIDR */ +#define QTI_KRYO4_SILVER_MIDR 0x517F805D + +/* KRYO-6xx Gold MIDR */ +#define QTI_KRYO6_GOLD_MIDR 0x412FD410 + +/* KRYO-6xx Silver MIDR */ +#define QTI_KRYO6_SILVER_MIDR 0x412FD050 + +#endif /* QTI_CPU_H */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h b/arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h new file mode 100644 index 0000000..59bde86 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTI_INTERRUPT_SVC_H +#define QTI_INTERRUPT_SVC_H + +int qti_interrupt_svc_init(void); + +#endif /* QTI_INTERRUPT_SVC_H */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/qti_plat.h b/arm-trusted-firmware/plat/qti/common/inc/qti_plat.h new file mode 100644 index 0000000..4d9d320 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/qti_plat.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTI_PLAT_H +#define QTI_PLAT_H + +#include + +#include +#include +#include +#include + +/* + * Utility functions common to QTI platforms + */ +int qti_mmap_add_dynamic_region(uintptr_t base_pa, size_t size, + unsigned int attr); +int qti_mmap_remove_dynamic_region(uintptr_t base_va, size_t size); + +/* + * Utility functions common to ARM standard platforms + */ +void qti_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit, + uintptr_t coh_start, uintptr_t coh_limit); + +/* + * Mandatory functions required in ARM standard platforms + */ +void plat_qti_gic_driver_init(void); +void plat_qti_gic_init(void); +void plat_qti_gic_cpuif_enable(void); +void plat_qti_gic_cpuif_disable(void); +void plat_qti_gic_pcpu_init(void); + +/* + * Optional functions required in ARM standard platforms + */ +unsigned int plat_qti_core_pos_by_mpidr(u_register_t mpidr); +unsigned int plat_qti_my_cluster_pos(void); + +void gic_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr); + +void qti_pmic_prepare_reset(void); +void qti_pmic_prepare_shutdown(void); + +#endif /* QTI_PLAT_H */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/qti_rng.h b/arm-trusted-firmware/plat/qti/common/inc/qti_rng.h new file mode 100644 index 0000000..62c31f3 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/qti_rng.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTI_RNG_H +#define QTI_RNG_H + +#include + +int qti_rng_get_data(uint8_t *out, uint32_t out_len); + +#endif /* QTI_RNG_H */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h b/arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h new file mode 100644 index 0000000..c5a65d6 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018,2020 The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTI_UART_CONSOLE_H +#define QTI_UART_CONSOLE_H + +#include + +#ifndef __ASSEMBLER__ + +int qti_console_uart_register(console_t *console, uintptr_t uart_base_addr); + +#endif /* __ASSEMBLER__ */ + +#endif /* QTI_UART_CONSOLE_H */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h b/arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h new file mode 100644 index 0000000..362f740 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020, Google LLC. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPMI_ARB_H +#define SPMI_ARB_H + +#include + +/******************************************************************************* + * WARNING: This driver does not arbitrate access with the kernel. These APIs + * must only be called when the kernel is known to be quiesced (such as before + * boot or while the system is shutting down). + ******************************************************************************/ + +/* 32-bit addresses combine (U)SID, PID and register address. */ + +int spmi_arb_read8(uint32_t addr); +int spmi_arb_write8(uint32_t addr, uint8_t data); + +#endif /* SPMI_ARB_H */ diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S new file mode 100644 index 0000000..c1ea7b3 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + + .globl plat_my_core_pos + .globl plat_qti_core_pos_by_mpidr + .globl plat_reset_handler + .globl plat_panic_handler + + /* ----------------------------------------------------- + * unsigned int plat_qti_core_pos_by_mpidr(uint64_t mpidr) + * Helper function to calculate the core position. + * With this function: + * CorePos = (ClusterId * 4) + CoreId + * - In ARM v8 (MPIDR_EL1[24]=0) + * ClusterId = MPIDR_EL1[15:8] + * CoreId = MPIDR_EL1[7:0] + * - In ARM v8.1 (MPIDR_EL1[24]=1) + * ClusterId = MPIDR_EL1[23:15] + * CoreId = MPIDR_EL1[15:8] + * Clobbers: x0 & x1. + * ----------------------------------------------------- + */ +func plat_qti_core_pos_by_mpidr + mrs x1, mpidr_el1 + tst x1, #MPIDR_MT_MASK + beq plat_qti_core_pos_by_mpidr_no_mt + /* Right shift mpidr by one affinity level when MT=1. */ + lsr x0, x0, #MPIDR_AFFINITY_BITS +plat_qti_core_pos_by_mpidr_no_mt: + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_qti_core_pos_by_mpidr + + /* -------------------------------------------------------------------- + * void plat_panic_handler(void) + * calls SDI and reset system + * -------------------------------------------------------------------- + */ +func plat_panic_handler + msr spsel, #0 + bl plat_set_my_stack + b qtiseclib_panic +endfunc plat_panic_handler + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_qti_calc_core_pos() + * definition to get the index of the calling CPU + * Clobbers: x0 & x1. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_qti_core_pos_by_mpidr +endfunc plat_my_core_pos + +func plat_reset_handler + /* save the lr */ + mov x18, x30 + + /* Serialize CPUSS boot setup. Multi core enter simultaneously. */ + ldr x0, =g_qti_cpuss_boot_lock + bl spin_lock + + /* pass cold boot status. */ + ldr w0, g_qti_bl31_cold_booted + /* Execuete CPUSS boot set up on every core. */ + bl qtiseclib_cpuss_reset_asm + + ldr x0, =g_qti_cpuss_boot_lock + bl spin_unlock + + ret x18 +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S new file mode 100644 index 0000000..a1b40c8 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + + .p2align 3 + +/* ------------------------------------------------- + * The CPU Ops reset function for Kryo-3 Gold + * ------------------------------------------------- + */ +func qti_kryo4_gold_reset_func +#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715 + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb +#endif + + mov x19, x30 + + bl qtiseclib_kryo4_gold_reset_asm + + ret x19 + +endfunc qti_kryo4_gold_reset_func + +/* ---------------------------------------------------- + * The CPU Ops core power down function for Kryo-3 Gold + * ---------------------------------------------------- + */ +func qti_kryo4_gold_core_pwr_dwn + ret +endfunc qti_kryo4_gold_core_pwr_dwn + +/* ------------------------------------------------------- + * The CPU Ops cluster power down function for Kryo-3 Gold + * ------------------------------------------------------- + */ +func qti_kryo4_gold_cluster_pwr_dwn + ret +endfunc qti_kryo4_gold_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Kryo4 Gold. Must follow AAPCS. + */ +func qti_kryo4_gold_errata_report + /* TODO : Need to add support. Required only for debug bl31 image.*/ + ret +endfunc qti_kryo4_gold_errata_report +#endif + +/* --------------------------------------------- + * This function provides kryo4_gold 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.qti_kryo4_gold_regs, "aS" +qti_kryo4_gold_regs: /* The ASCII list of register names to be reported */ + .asciz "" + +func qti_kryo4_gold_cpu_reg_dump + adr x6, qti_kryo4_gold_regs + ret +endfunc qti_kryo4_gold_cpu_reg_dump + +declare_cpu_ops qti_kryo4_gold, QTI_KRYO4_GOLD_MIDR, \ + qti_kryo4_gold_reset_func, \ + qti_kryo4_gold_core_pwr_dwn, \ + qti_kryo4_gold_cluster_pwr_dwn diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S new file mode 100644 index 0000000..183eeb0 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + + .p2align 3 + +/* ------------------------------------------------- + * The CPU Ops reset function for Kryo-3 Silver + * ------------------------------------------------- + */ +func qti_kryo4_silver_reset_func + mov x19, x30 + + bl qtiseclib_kryo4_silver_reset_asm + + ret x19 + +endfunc qti_kryo4_silver_reset_func + +/* ------------------------------------------------------ + * The CPU Ops core power down function for Kryo-3 Silver + * ------------------------------------------------------ + */ +func qti_kryo4_silver_core_pwr_dwn + ret +endfunc qti_kryo4_silver_core_pwr_dwn + +/* --------------------------------------------------------- + * The CPU Ops cluster power down function for Kryo-3 Silver + * --------------------------------------------------------- + */ +func qti_kryo4_silver_cluster_pwr_dwn + ret +endfunc qti_kryo4_silver_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Kryo4 Silver. Must follow AAPCS. + */ +func qti_kryo4_silver_errata_report + /* TODO : Need to add support. Required only for debug bl31 image.*/ + ret +endfunc qti_kryo4_silver_errata_report +#endif + + +/* --------------------------------------------- + * This function provides kryo4_silver 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.qti_kryo4_silver_regs, "aS" +qti_kryo4_silver_regs: /* The ASCII list of register names to be reported */ + .asciz "" + +func qti_kryo4_silver_cpu_reg_dump + adr x6, qti_kryo4_silver_regs + ret +endfunc qti_kryo4_silver_cpu_reg_dump + + +declare_cpu_ops qti_kryo4_silver, QTI_KRYO4_SILVER_MIDR, \ + qti_kryo4_silver_reset_func, \ + qti_kryo4_silver_core_pwr_dwn, \ + qti_kryo4_silver_cluster_pwr_dwn diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S new file mode 100644 index 0000000..db1a304 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + + .p2align 3 + +/* ------------------------------------------------- + * The CPU Ops reset function for Kryo-3 Gold + * ------------------------------------------------- + */ +func qti_kryo6_gold_reset_func +#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715 + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb +#endif + + mov x19, x30 + + bl qtiseclib_kryo6_gold_reset_asm + + ret x19 + +endfunc qti_kryo6_gold_reset_func + +/* ---------------------------------------------------- + * The CPU Ops core power down function for Kryo-3 Gold + * ---------------------------------------------------- + */ +func qti_kryo6_gold_core_pwr_dwn + ret +endfunc qti_kryo6_gold_core_pwr_dwn + +/* ------------------------------------------------------- + * The CPU Ops cluster power down function for Kryo-3 Gold + * ------------------------------------------------------- + */ +func qti_kryo6_gold_cluster_pwr_dwn + ret +endfunc qti_kryo6_gold_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Kryo4 Gold. Must follow AAPCS. + */ +func qti_kryo6_gold_errata_report + /* TODO : Need to add support. Required only for debug bl31 image.*/ + ret +endfunc qti_kryo6_gold_errata_report +#endif + +/* --------------------------------------------- + * This function provides kryo4_gold 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.qti_kryo4_gold_regs, "aS" +qti_kryo6_gold_regs: /* The ASCII list of register names to be reported */ + .asciz "" + +func qti_kryo6_gold_cpu_reg_dump + adr x6, qti_kryo6_gold_regs + ret +endfunc qti_kryo6_gold_cpu_reg_dump + +declare_cpu_ops qti_kryo6_gold, QTI_KRYO6_GOLD_MIDR, \ + qti_kryo6_gold_reset_func, \ + qti_kryo6_gold_core_pwr_dwn, \ + qti_kryo6_gold_cluster_pwr_dwn diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S new file mode 100644 index 0000000..2d189f2 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + + .p2align 3 + +/* ------------------------------------------------- + * The CPU Ops reset function for Kryo-3 Silver + * ------------------------------------------------- + */ +func qti_kryo6_silver_reset_func + mov x19, x30 + + bl qtiseclib_kryo6_silver_reset_asm + + ret x19 + +endfunc qti_kryo6_silver_reset_func + +/* ------------------------------------------------------ + * The CPU Ops core power down function for Kryo-3 Silver + * ------------------------------------------------------ + */ +func qti_kryo6_silver_core_pwr_dwn + ret +endfunc qti_kryo6_silver_core_pwr_dwn + +/* --------------------------------------------------------- + * The CPU Ops cluster power down function for Kryo-3 Silver + * --------------------------------------------------------- + */ +func qti_kryo6_silver_cluster_pwr_dwn + ret +endfunc qti_kryo6_silver_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Kryo4 Silver. Must follow AAPCS. + */ +func qti_kryo6_silver_errata_report + /* TODO : Need to add support. Required only for debug bl31 image.*/ + ret +endfunc qti_kryo6_silver_errata_report +#endif + + +/* --------------------------------------------- + * This function provides kryo4_silver 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.qti_kryo4_silver_regs, "aS" +qti_kryo6_silver_regs: /* The ASCII list of register names to be reported */ + .asciz "" + +func qti_kryo6_silver_cpu_reg_dump + adr x6, qti_kryo6_silver_regs + ret +endfunc qti_kryo6_silver_cpu_reg_dump + + +declare_cpu_ops qti_kryo6_silver, QTI_KRYO6_SILVER_MIDR, \ + qti_kryo6_silver_reset_func, \ + qti_kryo6_silver_core_pwr_dwn, \ + qti_kryo6_silver_cluster_pwr_dwn diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S new file mode 100644 index 0000000..2eb33d9 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018,2020 The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +/* + * This driver implements console logging into a ring buffer. + */ + + .globl qti_console_uart_register + + /* ----------------------------------------------- + * int qti_console_uart_register(console_t *console, + * uintptr_t uart_base_addr) + * Registers uart console instance. + * In: x0 - pointer to empty console_t struct + * x1 - start address of uart block. + * Out: x0 - 1 to indicate success + * Clobber list: x0, x1, x14 + * ----------------------------------------------- + */ +func qti_console_uart_register + str x1, [x0, #CONSOLE_T_BASE] /* Save UART base. */ + finish_console_register uart putc=1, flush=1 +endfunc qti_console_uart_register + + /* ----------------------------------------------- + * int qti_console_uart_puts(int c, console_t *console) + * Writes a character to the UART console. + * The character must be preserved in x0. + * In: x0 - character to be stored + * x1 - pointer to console_t struct + * Clobber list: x1, x2 + * ----------------------------------------------- + */ +func console_uart_putc + /* set x1 = UART base. */ + ldr x1, [x1, #CONSOLE_T_BASE] + + /* Loop until M_GENI_CMD_ACTIVE bit not clear. */ +1: ldr w2, [x1, #GENI_STATUS_REG] + and w2, w2, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK + cmp w2, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK + b.eq 1b + + /* Transmit data. */ + cmp w0, #0xA + b.ne 3f + + /* Add '\r' when input char is '\n' */ + mov w2, #0x1 + mov w0, #0xD + str w2, [x1, #UART_TX_TRANS_LEN_REG] + mov w2, #GENI_M_CMD_TX + str w2, [x1, #GENI_M_CMD0_REG] + str w0, [x1, #GENI_TX_FIFOn_REG] + mov w0, #0xA + + /* Loop until M_GENI_CMD_ACTIVE bit not clear. */ +2: ldr w2, [x1, #GENI_STATUS_REG] + and w2, w2, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK + cmp w2, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK + b.eq 2b + + /* Transmit i/p data. */ +3: mov w2, #0x1 + str w2, [x1, #UART_TX_TRANS_LEN_REG] + mov w2, #GENI_M_CMD_TX + str w2, [x1, #GENI_M_CMD0_REG] + str w0, [x1, #GENI_TX_FIFOn_REG] + + ret +endfunc console_uart_putc + + /* ----------------------------------------------- + * int qti_console_uart_flush(console_t *console) + * In: x0 - pointer to console_t struct + * Out: x0 - 0 for success + * Clobber list: x0, x1 + * ----------------------------------------------- + */ +func console_uart_flush + /* set x0 = UART base. */ + ldr x0, [x0, #CONSOLE_T_BASE] + + /* Loop until M_GENI_CMD_ACTIVE bit not clear. */ +1: ldr w1, [x0, #GENI_STATUS_REG] + and w1, w1, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK + cmp w1, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK + b.eq 1b + + mov w0, #0 + ret +endfunc console_uart_flush diff --git a/arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c b/arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c new file mode 100644 index 0000000..208345c --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, Google LLC. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * This driver implements PON support for PM8998-compatible PMICs. This can + * include other part numbers like PM6150. + */ + +#define RESET_TYPE_WARM_RESET 1 +#define RESET_TYPE_SHUTDOWN 4 + +#define S2_RESET_EN BIT(7) + +static void configure_ps_hold(uint32_t reset_type) +{ + /* QTI recommends disabling reset for 10 cycles before reconfiguring. */ + spmi_arb_write8(PON_PS_HOLD_RESET_CTL2, 0); + mdelay(1); + + spmi_arb_write8(PON_PS_HOLD_RESET_CTL, reset_type); + spmi_arb_write8(PON_PS_HOLD_RESET_CTL2, S2_RESET_EN); + mdelay(1); +} + +void qti_pmic_prepare_reset(void) +{ + configure_ps_hold(RESET_TYPE_WARM_RESET); +} + +void qti_pmic_prepare_shutdown(void) +{ + configure_ps_hold(RESET_TYPE_SHUTDOWN); +} diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c b/arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c new file mode 100644 index 0000000..b2bc543 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl33_image_ep_info; + +/* + * Variable to hold counter frequency for the CPU's generic timer. In this + * platform coreboot image configure counter frequency for boot core before + * reaching TF-A. + */ +static uint64_t g_qti_cpu_cntfrq; + +/* + * Lock variable to serialize cpuss reset execution. + */ +spinlock_t g_qti_cpuss_boot_lock __attribute__ ((section("tzfw_coherent_mem"), + aligned(CACHE_WRITEBACK_GRANULE))) = {0x0}; + +/* + * Variable to hold bl31 cold boot status. Default value 0x0 means yet to boot. + * Any other value means cold booted. + */ +uint32_t g_qti_bl31_cold_booted __attribute__ ((section("tzfw_coherent_mem"))) = 0x0; + +/******************************************************************************* + * Perform any BL31 early platform setup common to ARM standard platforms. + * Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & S-EL3 in BL1) before they are lost (potentially). This needs to be + * done before the MMU is initialized so that the memory layout can be used + * while creating page tables. BL2 has flushed this information to memory, so + * we are guaranteed to pick up good data. + ******************************************************************************/ +void bl31_early_platform_setup(u_register_t from_bl2, + u_register_t plat_params_from_bl2) +{ + + g_qti_cpu_cntfrq = read_cntfrq_el0(); + + bl_aux_params_parse(plat_params_from_bl2, NULL); + +#if COREBOOT + if (coreboot_serial.baseaddr != 0) { + static console_t g_qti_console_uart; + + qti_console_uart_register(&g_qti_console_uart, + coreboot_serial.baseaddr); + } +#endif + + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl31_params_parse_helper(from_bl2, NULL, &bl33_image_ep_info); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + bl31_early_platform_setup(arg0, arg1); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + qti_setup_page_tables(BL_CODE_BASE, + BL_COHERENT_RAM_END - BL_CODE_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END, + BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); + enable_mmu_el3(0); +} + +/******************************************************************************* + * Perform any BL31 platform setup common to ARM standard platforms + ******************************************************************************/ +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + /* Initialize the GIC driver, CPU and distributor interfaces */ + plat_qti_gic_driver_init(); + plat_qti_gic_init(); + qti_interrupt_svc_init(); + qtiseclib_bl31_platform_setup(); + + /* set boot state to cold boot complete. */ + g_qti_bl31_cold_booted = 0x1; +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for the + * security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + /* QTI platform don't have BL32 implementation. */ + assert(type == NON_SECURE); + assert(bl33_image_ep_info.h.type == PARAM_EP); + assert(bl33_image_ep_info.h.attr == NON_SECURE); + /* + * None of the images on the platforms can have 0x0 + * as the entrypoint. + */ + if (bl33_image_ep_info.pc) { + return &bl33_image_ep_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * This function is used by the architecture setup code to retrieve the counter + * frequency for the CPU's generic timer. This value will be programmed into the + * CNTFRQ_EL0 register. In Arm standard platforms, it returns the base frequency + * of the system counter, which is retrieved from the first entry in the + * frequency modes table. This will be used later in warm boot (psci_arch_setup) + * of CPUs to set when CPU frequency. + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + assert(g_qti_cpu_cntfrq != 0); + return g_qti_cpu_cntfrq; +} diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_common.c b/arm-trusted-firmware/plat/qti/common/src/qti_common.c new file mode 100644 index 0000000..da0eaec --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_common.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * Table of regions for various BL stages to map using the MMU. + * This doesn't include TZRAM as the 'mem_layout' argument passed to + * qti_configure_mmu_elx() will give the available subset of that, + */ + +const mmap_region_t plat_qti_mmap[] = { + MAP_REGION_FLAT(QTI_DEVICE_BASE, QTI_DEVICE_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(QTI_AOP_CMD_DB_BASE, QTI_AOP_CMD_DB_SIZE, + MT_NS | MT_RO | MT_EXECUTE_NEVER), + {0} +}; + +CASSERT(ARRAY_SIZE(plat_qti_mmap) <= MAX_MMAP_REGIONS, assert_max_mmap_regions); + + +bool qti_is_overlap_atf_rg(unsigned long long addr, size_t size) +{ + if (addr > addr + size + || (BL31_BASE < addr + size && BL31_LIMIT > addr)) { + return true; + } + return false; +} + +/* + * unsigned int plat_qti_my_cluster_pos(void) + * definition to get the cluster index of the calling CPU. + * - In ARM v8 (MPIDR_EL1[24]=0) + * ClusterId = MPIDR_EL1[15:8] + * - In ARM v8.1 & Later version (MPIDR_EL1[24]=1) + * ClusterId = MPIDR_EL1[23:15] + */ +unsigned int plat_qti_my_cluster_pos(void) +{ + unsigned int mpidr, cluster_id; + + mpidr = read_mpidr_el1(); + if ((mpidr & MPIDR_MT_MASK) == 0) { /* MT not supported */ + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + } else { /* MT supported */ + cluster_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK; + } + assert(cluster_id < PLAT_CLUSTER_COUNT); + return cluster_id; +} + +/* + * Set up the page tables for the generic and platform-specific memory regions. + * The extents of the generic memory regions are specified by the function + * arguments and consist of: + * - Trusted SRAM seen by the BL image; + * - Code section; + * - Read-only data section; + * - Coherent memory region, if applicable. + */ +void qti_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit, + uintptr_t coh_start, uintptr_t coh_limit) +{ + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n", + (void *)total_base, (void *)(total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, MT_MEMORY | MT_RW | MT_SECURE); + + /* Re-map the code section */ + VERBOSE("Code region: %p - %p\n", + (void *)code_start, (void *)code_limit); + mmap_add_region(code_start, code_start, + code_limit - code_start, MT_CODE | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *)rodata_start, (void *)rodata_limit); + mmap_add_region(rodata_start, rodata_start, + rodata_limit - rodata_start, MT_RO_DATA | MT_SECURE); + + /* Re-map the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *)coh_start, (void *)coh_limit); + mmap_add_region(coh_start, coh_start, + coh_limit - coh_start, MT_DEVICE | MT_RW | MT_SECURE); + + /* Now (re-)map the platform-specific memory regions */ + mmap_add(plat_qti_mmap); + + /* Create the page tables to reflect the above mappings */ + init_xlat_tables(); +} + +static inline void qti_align_mem_region(uintptr_t addr, size_t size, + uintptr_t *aligned_addr, + size_t *aligned_size) +{ + *aligned_addr = round_down(addr, PAGE_SIZE); + *aligned_size = round_up(addr - *aligned_addr + size, PAGE_SIZE); +} + +int qti_mmap_add_dynamic_region(uintptr_t base_pa, size_t size, + unsigned int attr) +{ + uintptr_t aligned_pa; + size_t aligned_size; + + qti_align_mem_region(base_pa, size, &aligned_pa, &aligned_size); + + if (qti_is_overlap_atf_rg(base_pa, size)) { + /* Memory shouldn't overlap with TF-A range. */ + return -EPERM; + } + + return mmap_add_dynamic_region(aligned_pa, aligned_pa, aligned_size, + attr); +} + +int qti_mmap_remove_dynamic_region(uintptr_t base_va, size_t size) +{ + qti_align_mem_region(base_va, size, &base_va, &size); + return mmap_remove_dynamic_region(base_va, size); +} + +/* + * This function returns soc version which mainly consist of below fields + * + * soc_version[30:24] = JEP-106 continuation code for the SiP + * soc_version[23:16] = JEP-106 identification code with parity bit for the SiP + * soc_version[0:15] = Implementation defined SoC ID + */ +int32_t plat_get_soc_version(void) +{ + uint32_t soc_version = (QTI_SOC_VERSION & QTI_SOC_VERSION_MASK); + uint32_t jep106az_code = (JEDEC_QTI_BKID << QTI_SOC_CONTINUATION_SHIFT) + | (JEDEC_QTI_MFID << QTI_SOC_IDENTIFICATION_SHIFT); + return (int32_t)(jep106az_code | (soc_version)); +} + +/* + * This function returns soc revision in below format + * + * soc_revision[0:30] = SOC revision of specific SOC + */ +int32_t plat_get_soc_revision(void) +{ + return mmio_read_32(QTI_SOC_REVISION_REG) & QTI_SOC_REVISION_MASK; +} + +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC feature + * is availabile for the platform or not. + * @fid: SMCCC function id + * + * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and + * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c b/arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c new file mode 100644 index 0000000..f00267a --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +/* Array of interrupts to be configured by the gic driver */ +static const interrupt_prop_t qti_interrupt_props[] = { + INTR_PROP_DESC(QTISECLIB_INT_ID_CPU_WAKEUP_SGI, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_RESET_SGI, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_SEC_WDOG_BARK, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_NON_SEC_WDOG_BITE, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_XPU_SEC, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_XPU_NON_SEC, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), +#ifdef QTISECLIB_INT_ID_A1_NOC_ERROR + INTR_PROP_DESC(QTISECLIB_INT_ID_A1_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), +#endif + INTR_PROP_DESC(QTISECLIB_INT_ID_A2_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_CONFIG_NOC_ERROR, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_DC_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_MEM_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_SYSTEM_NOC_ERROR, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(QTISECLIB_INT_ID_MMSS_NOC_ERROR, + GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), +#ifdef QTISECLIB_INT_ID_LPASS_AGNOC_ERROR + INTR_PROP_DESC(QTISECLIB_INT_ID_LPASS_AGNOC_ERROR, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), +#endif +#ifdef QTISECLIB_INT_ID_NSP_NOC_ERROR + INTR_PROP_DESC(QTISECLIB_INT_ID_NSP_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY, + INTR_GROUP0, + GIC_INTR_CFG_EDGE), +#endif +}; + +const gicv3_driver_data_t qti_gic_data = { + .gicd_base = QTI_GICD_BASE, + .gicr_base = QTI_GICR_BASE, + .interrupt_props = qti_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(qti_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = plat_qti_core_pos_by_mpidr +}; + +void plat_qti_gic_driver_init(void) +{ + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ + gicv3_driver_init(&qti_gic_data); +} + +/****************************************************************************** + * ARM common helper to initialize the GIC. Only invoked by BL31 + *****************************************************************************/ +void plat_qti_gic_init(void) +{ + unsigned int i; + + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); + + /* Route secure spi interrupt to ANY. */ + for (i = 0; i < ARRAY_SIZE(qti_interrupt_props); i++) { + unsigned int int_id = qti_interrupt_props[i].intr_num; + + if (plat_ic_is_spi(int_id)) { + gicv3_set_spi_routing(int_id, GICV3_IRM_ANY, 0x0); + } + } +} + +void gic_set_spi_routing(unsigned int id, unsigned int irm, u_register_t target) +{ + gicv3_set_spi_routing(id, irm, target); +} + +/****************************************************************************** + * ARM common helper to enable the GIC CPU interface + *****************************************************************************/ +void plat_qti_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * ARM common helper to disable the GIC CPU interface + *****************************************************************************/ +void plat_qti_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/****************************************************************************** + * ARM common helper to initialize the per-CPU redistributor interface in GICv3 + *****************************************************************************/ +void plat_qti_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} + +/****************************************************************************** + * ARM common helpers to power GIC redistributor interface + *****************************************************************************/ +void plat_qti_gic_redistif_on(void) +{ + gicv3_rdistif_on(plat_my_core_pos()); +} + +void plat_qti_gic_redistif_off(void) +{ + gicv3_rdistif_off(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c b/arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c new file mode 100644 index 0000000..89cd7b5 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#define QTI_INTR_INVALID_INT_NUM 0xFFFFFFFFU + +/* + * Top-level EL3 interrupt handler. + */ +static uint64_t qti_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint32_t irq = QTI_INTR_INVALID_INT_NUM; + + /* + * EL3 non-interruptible. Interrupt shouldn't occur when we are at + * EL3 / Secure. + */ + assert(handle != cm_get_context(SECURE)); + + irq = plat_ic_acknowledge_interrupt(); + + qtiseclib_invoke_isr(irq, handle); + + /* End of Interrupt. */ + if (irq < 1022U) { + plat_ic_end_of_interrupt(irq); + } + + return (uint64_t) handle; +} + +int qti_interrupt_svc_init(void) +{ + int ret; + uint64_t flags = 0U; + + /* + * Route EL3 interrupts to EL3 when in Non-secure. + * Note: EL3 won't have interrupt enable + * & we don't have S-EL1 support. + */ + set_interrupt_rm_flag(flags, NON_SECURE); + + /* Register handler for EL3 interrupts */ + ret = register_interrupt_type_handler(INTR_TYPE_EL3, + qti_el3_interrupt_handler, flags); + assert(ret == 0); + + return ret; +} diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_pm.c b/arm-trusted-firmware/plat/qti/common/src/qti_pm.c new file mode 100644 index 0000000..5f1b7aa --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_pm.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define QTI_LOCAL_PSTATE_WIDTH 4 +#define QTI_LOCAL_PSTATE_MASK ((1 << QTI_LOCAL_PSTATE_WIDTH) - 1) + +/* Make composite power state parameter till level 0 */ +#define qti_make_pwrstate_lvl0(lvl0_state, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT)) + +/* Make composite power state parameter till level 1 */ +#define qti_make_pwrstate_lvl1(lvl1_state, lvl0_state, type) \ + (((lvl1_state) << QTI_LOCAL_PSTATE_WIDTH) | \ + qti_make_pwrstate_lvl0(lvl0_state, type)) + +/* Make composite power state parameter till level 2 */ +#define qti_make_pwrstate_lvl2(lvl2_state, lvl1_state, lvl0_state, type) \ + (((lvl2_state) << (QTI_LOCAL_PSTATE_WIDTH * 2)) | \ + qti_make_pwrstate_lvl1(lvl1_state, lvl0_state, type)) + +/* Make composite power state parameter till level 3 */ +#define qti_make_pwrstate_lvl3(lvl3_state, lvl2_state, lvl1_state, lvl0_state, type) \ + (((lvl3_state) << (QTI_LOCAL_PSTATE_WIDTH * 3)) | \ + qti_make_pwrstate_lvl2(lvl2_state, lvl1_state, lvl0_state, type)) + +/* QTI_CORE_PWRDN_EN_MASK happens to be same across all CPUs */ +#define QTI_CORE_PWRDN_EN_MASK 1 + +/* cpu power control happens to be same across all CPUs */ +_DEFINE_SYSREG_WRITE_FUNC(cpu_pwrctrl_val, S3_0_C15_C2_7) +_DEFINE_SYSREG_READ_FUNC(cpu_pwrctrl_val, S3_0_C15_C2_7) + +const unsigned int qti_pm_idle_states[] = { + qti_make_pwrstate_lvl0(QTI_LOCAL_STATE_OFF, + PSTATE_TYPE_POWERDOWN), + qti_make_pwrstate_lvl0(QTI_LOCAL_STATE_DEEPOFF, + PSTATE_TYPE_POWERDOWN), + qti_make_pwrstate_lvl1(QTI_LOCAL_STATE_DEEPOFF, + QTI_LOCAL_STATE_DEEPOFF, + PSTATE_TYPE_POWERDOWN), + qti_make_pwrstate_lvl2(QTI_LOCAL_STATE_OFF, + QTI_LOCAL_STATE_DEEPOFF, + QTI_LOCAL_STATE_DEEPOFF, + PSTATE_TYPE_POWERDOWN), + qti_make_pwrstate_lvl3(QTI_LOCAL_STATE_OFF, + QTI_LOCAL_STATE_DEEPOFF, + QTI_LOCAL_STATE_DEEPOFF, + QTI_LOCAL_STATE_DEEPOFF, + PSTATE_TYPE_POWERDOWN), + 0, +}; + +/******************************************************************************* + * QTI standard platform handler called to check the validity of the power + * state parameter. The power state parameter has to be a composite power + * state. + ******************************************************************************/ +int qti_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + assert(req_state); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; !!qti_pm_idle_states[i]; i++) { + if (power_state == qti_pm_idle_states[i]) + break; + } + + /* Return error if entry not found in the idle state array */ + if (!qti_pm_idle_states[i]) + return PSCI_E_INVALID_PARAMS; + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + QTI_LOCAL_PSTATE_MASK; + state_id >>= QTI_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * PLATFORM FUNCTIONS + ******************************************************************************/ + +static void qti_set_cpupwrctlr_val(void) +{ + unsigned long val; + + val = read_cpu_pwrctrl_val(); + val |= QTI_CORE_PWRDN_EN_MASK; + write_cpu_pwrctrl_val(val); + + isb(); +} + +/** + * CPU power on function - ideally we want a wrapper since this function is + * target specific. But to unblock teams. + */ +static int qti_cpu_power_on(u_register_t mpidr) +{ + int core_pos = plat_core_pos_by_mpidr(mpidr); + + /* If not valid mpidr, return error */ + if (core_pos < 0 || core_pos >= QTISECLIB_PLAT_CORE_COUNT) { + return PSCI_E_INVALID_PARAMS; + } + + return qtiseclib_psci_node_power_on(mpidr); +} + +static bool is_cpu_off(const psci_power_state_t *target_state) +{ + if ((target_state->pwr_domain_state[QTI_PWR_LVL0] == + QTI_LOCAL_STATE_OFF) || + (target_state->pwr_domain_state[QTI_PWR_LVL0] == + QTI_LOCAL_STATE_DEEPOFF)) { + return true; + } else { + return false; + } +} + +static void qti_cpu_power_on_finish(const psci_power_state_t *target_state) +{ + const uint8_t *pwr_states = + (const uint8_t *)target_state->pwr_domain_state; + qtiseclib_psci_node_on_finish(pwr_states); + + if (is_cpu_off(target_state)) { + plat_qti_gic_cpuif_enable(); + } +} + +static void qti_cpu_standby(plat_local_state_t cpu_state) +{ +} + +static void qti_node_power_off(const psci_power_state_t *target_state) +{ + qtiseclib_psci_node_power_off((const uint8_t *) + target_state->pwr_domain_state); + if (is_cpu_off(target_state)) { + plat_qti_gic_cpuif_disable(); + qti_set_cpupwrctlr_val(); + } +} + +static void qti_node_suspend(const psci_power_state_t *target_state) +{ + qtiseclib_psci_node_suspend((const uint8_t *)target_state-> + pwr_domain_state); + if (is_cpu_off(target_state)) { + plat_qti_gic_cpuif_disable(); + qti_set_cpupwrctlr_val(); + } +} + +static void qti_node_suspend_finish(const psci_power_state_t *target_state) +{ + const uint8_t *pwr_states = + (const uint8_t *)target_state->pwr_domain_state; + qtiseclib_psci_node_suspend_finish(pwr_states); + if (is_cpu_off(target_state)) { + plat_qti_gic_cpuif_enable(); + } +} + +__dead2 void qti_domain_power_down_wfi(const psci_power_state_t *target_state) +{ + + /* For now just do WFI - add any target specific handling if needed */ + psci_power_down_wfi(); + /* We should never reach here */ +} + +static __dead2 void assert_ps_hold(void) +{ + mmio_write_32(QTI_PS_HOLD_REG, 0); + mdelay(1000); + + /* Should be dead before reaching this. */ + panic(); +} + +__dead2 void qti_system_off(void) +{ + qti_pmic_prepare_shutdown(); + assert_ps_hold(); +} + +__dead2 void qti_system_reset(void) +{ + qti_pmic_prepare_reset(); + assert_ps_hold(); +} + +void qti_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i = 0; + unsigned int state_id, power_state; + int size = ARRAY_SIZE(qti_pm_idle_states); + + /* + * Find deepest state. + * The arm_pm_idle_states[] array has last element by default 0, + * so the real deepest state is second last element of that array. + */ + power_state = qti_pm_idle_states[size - 2]; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = + state_id & QTI_LOCAL_PSTATE_MASK; + state_id >>= QTI_LOCAL_PSTATE_WIDTH; + } +} + +/* + * Structure containing platform specific PSCI operations. Common + * PSCI layer will use this. + */ +const plat_psci_ops_t plat_qti_psci_pm_ops = { + .pwr_domain_on = qti_cpu_power_on, + .pwr_domain_on_finish = qti_cpu_power_on_finish, + .cpu_standby = qti_cpu_standby, + .pwr_domain_off = qti_node_power_off, + .pwr_domain_suspend = qti_node_suspend, + .pwr_domain_suspend_finish = qti_node_suspend_finish, + .pwr_domain_pwr_down_wfi = qti_domain_power_down_wfi, + .system_off = qti_system_off, + .system_reset = qti_system_reset, + .get_node_hw_state = NULL, + .translate_power_state_by_mpidr = NULL, + .get_sys_suspend_power_state = qti_get_sys_suspend_power_state, + .validate_power_state = qti_validate_power_state, +}; + +/** + * The QTI Standard platform definition of platform porting API + * `plat_setup_psci_ops`. + */ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + int err; + + err = qtiseclib_psci_init((uintptr_t)bl31_warm_entrypoint); + if (err == PSCI_E_SUCCESS) { + *psci_ops = &plat_qti_psci_pm_ops; + } + + return err; +} diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_rng.c b/arm-trusted-firmware/plat/qti/common/src/qti_rng.c new file mode 100644 index 0000000..f63f3b8 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_rng.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include + +#include +#include + +int qti_rng_get_data(uint8_t *out, uint32_t out_len) +{ + uint32_t tmp_rndm = 0; + uint32_t bytes_left = out_len; + int i = 0; + + if (NULL == out || 0 == out_len) { + return -1; + } + + /* + * RNG HW initialized at previous boot image. + * RNG clocks are expected to be ON. + */ + + do { + /* There is no data to read */ + if ((mmio_read_32(SEC_PRNG_STATUS) & + SEC_PRNG_STATUS_DATA_AVAIL_BMSK) == 0) { + continue; + } + + while ((tmp_rndm = mmio_read_32(SEC_PRNG_DATA_OUT)) == 0) { + ; + } + + for (i = 0; i < 4; i++) { + *out = (uint8_t) (tmp_rndm >> (8 * i)); + + out++; + bytes_left--; + + if (bytes_left == 0) { + break; + } + } + + } while (bytes_left != 0); + + return 0; +} diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c b/arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c new file mode 100644 index 0000000..572830f --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +u_register_t plat_get_stack_protector_canary(void) +{ + u_register_t random = 0x0; + + /* + * get random data , the below API doesn't return random = 0 on success + */ + qti_rng_get_data((uint8_t *) &random, sizeof(random)); + assert(random != 0x0); + + return random; +} diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_syscall.c b/arm-trusted-firmware/plat/qti/common/src/qti_syscall.c new file mode 100644 index 0000000..d8e5be9 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_syscall.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * SIP service - SMC function IDs for SiP Service queries + * + */ +#define QTI_SIP_SVC_CALL_COUNT_ID U(0x0200ff00) +#define QTI_SIP_SVC_UID_ID U(0x0200ff01) +/* 0x8200ff02 is reserved*/ +#define QTI_SIP_SVC_VERSION_ID U(0x0200ff03) +#define QTI_SIP_SVC_AVAILABLE_ID U(0x02000601) +/* + * Syscall's to allow Non Secure world accessing peripheral/IO memory + * those are secure/proteced BUT not required to be secure. + */ +#define QTI_SIP_SVC_SECURE_IO_READ_ID U(0x02000501) +#define QTI_SIP_SVC_SECURE_IO_WRITE_ID U(0x02000502) + +/* + * Syscall's to assigns a list of intermediate PAs from a + * source Virtual Machine (VM) to a destination VM. + */ +#define QTI_SIP_SVC_MEM_ASSIGN_ID U(0x02000C16) + +#define QTI_SIP_SVC_SECURE_IO_READ_PARAM_ID U(0x1) +#define QTI_SIP_SVC_SECURE_IO_WRITE_PARAM_ID U(0x2) +#define QTI_SIP_SVC_MEM_ASSIGN_PARAM_ID U(0x1117) + +#define QTI_SIP_SVC_CALL_COUNT U(0x3) +#define QTI_SIP_SVC_VERSION_MAJOR U(0x0) +#define QTI_SIP_SVC_VERSION_MINOR U(0x0) + +#define QTI_VM_LAST U(44) +#define SIZE4K U(0x1000) +#define QTI_VM_MAX_LIST_SIZE U(0x20) + +#define FUNCID_OEN_NUM_MASK ((FUNCID_OEN_MASK << FUNCID_OEN_SHIFT)\ + |(FUNCID_NUM_MASK << FUNCID_NUM_SHIFT)) + +enum { + QTI_SIP_SUCCESS = 0, + QTI_SIP_NOT_SUPPORTED = -1, + QTI_SIP_PREEMPTED = -2, + QTI_SIP_INVALID_PARAM = -3, +}; + +/* QTI SiP Service UUID */ +DEFINE_SVC_UUID2(qti_sip_svc_uid, + 0x43864748, 0x217f, 0x41ad, 0xaa, 0x5a, + 0xba, 0xe7, 0x0f, 0xa5, 0x52, 0xaf); + +static bool qti_is_secure_io_access_allowed(u_register_t addr) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(qti_secure_io_allowed_regs); i++) { + if ((uintptr_t) addr == qti_secure_io_allowed_regs[i]) { + return true; + } + } + + return false; +} + +static bool qti_check_syscall_availability(u_register_t smc_fid) +{ + switch (smc_fid) { + case QTI_SIP_SVC_CALL_COUNT_ID: + case QTI_SIP_SVC_UID_ID: + case QTI_SIP_SVC_VERSION_ID: + case QTI_SIP_SVC_AVAILABLE_ID: + case QTI_SIP_SVC_SECURE_IO_READ_ID: + case QTI_SIP_SVC_SECURE_IO_WRITE_ID: + case QTI_SIP_SVC_MEM_ASSIGN_ID: + return true; + default: + return false; + } +} + +bool qti_mem_assign_validate_param(memprot_info_t *mem_info, + u_register_t u_num_mappings, + uint32_t *source_vm_list, + u_register_t src_vm_list_cnt, + memprot_dst_vm_perm_info_t *dest_vm_list, + u_register_t dst_vm_list_cnt) +{ + int i; + + if (!source_vm_list || !dest_vm_list || !mem_info + || (src_vm_list_cnt == 0) + || (src_vm_list_cnt >= QTI_VM_LAST) || (dst_vm_list_cnt == 0) + || (dst_vm_list_cnt >= QTI_VM_LAST) || (u_num_mappings == 0) + || u_num_mappings > QTI_VM_MAX_LIST_SIZE) { + ERROR("vm count is 0 or more then QTI_VM_LAST or empty list\n"); + ERROR("source_vm_list %p dest_vm_list %p mem_info %p src_vm_list_cnt %u dst_vm_list_cnt %u u_num_mappings %u\n", + source_vm_list, dest_vm_list, mem_info, + (unsigned int)src_vm_list_cnt, + (unsigned int)dst_vm_list_cnt, + (unsigned int)u_num_mappings); + return false; + } + for (i = 0; i < u_num_mappings; i++) { + if ((mem_info[i].mem_addr & (SIZE4K - 1)) + || (mem_info[i].mem_size == 0) + || (mem_info[i].mem_size & (SIZE4K - 1))) { + ERROR("mem_info passed buffer 0x%x or size 0x%x is not 4k aligned\n", + (unsigned int)mem_info[i].mem_addr, + (unsigned int)mem_info[i].mem_size); + return false; + } + + if ((mem_info[i].mem_addr + mem_info[i].mem_size) < + mem_info[i].mem_addr) { + ERROR("overflow in mem_addr 0x%x add mem_size 0x%x\n", + (unsigned int)mem_info[i].mem_addr, + (unsigned int)mem_info[i].mem_size); + return false; + } + coreboot_memory_t mem_type = coreboot_get_memory_type( + mem_info[i].mem_addr, + mem_info[i].mem_size); + if (mem_type != CB_MEM_RAM && mem_type != CB_MEM_RESERVED) { + ERROR("memory region not in CB MEM RAM or RESERVED area: region start 0x%x size 0x%x\n", + (unsigned int)mem_info[i].mem_addr, + (unsigned int)mem_info[i].mem_size); + return false; + } + } + for (i = 0; i < src_vm_list_cnt; i++) { + if (source_vm_list[i] >= QTI_VM_LAST) { + ERROR("source_vm_list[%d] 0x%x is more then QTI_VM_LAST\n", + i, (unsigned int)source_vm_list[i]); + return false; + } + } + for (i = 0; i < dst_vm_list_cnt; i++) { + if (dest_vm_list[i].dst_vm >= QTI_VM_LAST) { + ERROR("dest_vm_list[%d] 0x%x is more then QTI_VM_LAST\n", + i, (unsigned int)dest_vm_list[i].dst_vm); + return false; + } + } + return true; +} + +static uintptr_t qti_sip_mem_assign(void *handle, uint32_t smc_cc, + u_register_t x1, + u_register_t x2, + u_register_t x3, u_register_t x4) +{ + uintptr_t dyn_map_start = 0, dyn_map_end = 0; + size_t dyn_map_size = 0; + u_register_t x6, x7; + int ret = QTI_SIP_NOT_SUPPORTED; + u_register_t x5 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X5); + + if (smc_cc == SMC_32) { + x5 = (uint32_t) x5; + } + /* Validate input arg count & retrieve arg3-6 from NS Buffer. */ + if ((x1 != QTI_SIP_SVC_MEM_ASSIGN_PARAM_ID) || (x5 == 0x0)) { + ERROR("invalid mem_assign param id or no mapping info\n"); + goto unmap_return; + } + + /* Map NS Buffer. */ + dyn_map_start = x5; + dyn_map_size = + (smc_cc == + SMC_32) ? (sizeof(uint32_t) * 4) : (sizeof(uint64_t) * 4); + if (qti_mmap_add_dynamic_region(dyn_map_start, dyn_map_size, + (MT_NS | MT_RO_DATA)) != 0) { + ERROR("map failed for params NS Buffer %x %x\n", + (unsigned int)dyn_map_start, (unsigned int)dyn_map_size); + goto unmap_return; + } + /* Retrieve indirect args. */ + if (smc_cc == SMC_32) { + x6 = *((uint32_t *) x5 + 1); + x7 = *((uint32_t *) x5 + 2); + x5 = *(uint32_t *) x5; + } else { + x6 = *((uint64_t *) x5 + 1); + x7 = *((uint64_t *) x5 + 2); + x5 = *(uint64_t *) x5; + } + /* Un-Map NS Buffer. */ + if (qti_mmap_remove_dynamic_region(dyn_map_start, dyn_map_size) != 0) { + ERROR("unmap failed for params NS Buffer %x %x\n", + (unsigned int)dyn_map_start, (unsigned int)dyn_map_size); + goto unmap_return; + } + + /* + * Map NS Buffers. + * arg0,2,4 points to buffers & arg1,3,5 hold sizes. + * MAP api's fail to map if it's already mapped. Let's + * find lowest start & highest end address, then map once. + */ + dyn_map_start = MIN(x2, x4); + dyn_map_start = MIN(dyn_map_start, x6); + dyn_map_end = MAX((x2 + x3), (x4 + x5)); + dyn_map_end = MAX(dyn_map_end, (x6 + x7)); + dyn_map_size = dyn_map_end - dyn_map_start; + + if (qti_mmap_add_dynamic_region(dyn_map_start, dyn_map_size, + (MT_NS | MT_RO_DATA)) != 0) { + ERROR("map failed for params NS Buffer2 %x %x\n", + (unsigned int)dyn_map_start, (unsigned int)dyn_map_size); + goto unmap_return; + } + memprot_info_t *mem_info_p = (memprot_info_t *) x2; + uint32_t u_num_mappings = x3 / sizeof(memprot_info_t); + uint32_t *source_vm_list_p = (uint32_t *) x4; + uint32_t src_vm_list_cnt = x5 / sizeof(uint32_t); + memprot_dst_vm_perm_info_t *dest_vm_list_p = + (memprot_dst_vm_perm_info_t *) x6; + uint32_t dst_vm_list_cnt = + x7 / sizeof(memprot_dst_vm_perm_info_t); + if (qti_mem_assign_validate_param(mem_info_p, u_num_mappings, + source_vm_list_p, src_vm_list_cnt, + dest_vm_list_p, + dst_vm_list_cnt) != true) { + ERROR("Param validation failed\n"); + goto unmap_return; + } + + memprot_info_t mem_info[QTI_VM_MAX_LIST_SIZE]; + /* Populating the arguments */ + for (int i = 0; i < u_num_mappings; i++) { + mem_info[i].mem_addr = mem_info_p[i].mem_addr; + mem_info[i].mem_size = mem_info_p[i].mem_size; + } + + memprot_dst_vm_perm_info_t dest_vm_list[QTI_VM_LAST]; + + for (int i = 0; i < dst_vm_list_cnt; i++) { + dest_vm_list[i].dst_vm = dest_vm_list_p[i].dst_vm; + dest_vm_list[i].dst_vm_perm = dest_vm_list_p[i].dst_vm_perm; + dest_vm_list[i].ctx = dest_vm_list_p[i].ctx; + dest_vm_list[i].ctx_size = dest_vm_list_p[i].ctx_size; + } + + uint32_t source_vm_list[QTI_VM_LAST]; + + for (int i = 0; i < src_vm_list_cnt; i++) { + source_vm_list[i] = source_vm_list_p[i]; + } + /* Un-Map NS Buffers. */ + if (qti_mmap_remove_dynamic_region(dyn_map_start, + dyn_map_size) != 0) { + ERROR("unmap failed for params NS Buffer %x %x\n", + (unsigned int)dyn_map_start, (unsigned int)dyn_map_size); + goto unmap_return; + } + /* Invoke API lib api. */ + ret = qtiseclib_mem_assign(mem_info, u_num_mappings, + source_vm_list, src_vm_list_cnt, + dest_vm_list, dst_vm_list_cnt); + + if (ret == 0) { + SMC_RET2(handle, QTI_SIP_SUCCESS, ret); + } +unmap_return: + /* Un-Map NS Buffers if mapped */ + if (dyn_map_start && dyn_map_size) { + qti_mmap_remove_dynamic_region(dyn_map_start, dyn_map_size); + } + + SMC_RET2(handle, QTI_SIP_INVALID_PARAM, ret); +} + +/* + * This function handles QTI specific syscalls. Currently only SiP calls are present. + * Both FAST & YIELD type call land here. + */ +static uintptr_t qti_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) +{ + uint32_t l_smc_fid = smc_fid & FUNCID_OEN_NUM_MASK; + + if (GET_SMC_CC(smc_fid) == SMC_32) { + x1 = (uint32_t) x1; + x2 = (uint32_t) x2; + x3 = (uint32_t) x3; + x4 = (uint32_t) x4; + } + + switch (l_smc_fid) { + case QTI_SIP_SVC_CALL_COUNT_ID: + { + SMC_RET1(handle, QTI_SIP_SVC_CALL_COUNT); + break; + } + case QTI_SIP_SVC_UID_ID: + { + /* Return UID to the caller */ + SMC_UUID_RET(handle, qti_sip_svc_uid); + break; + } + case QTI_SIP_SVC_VERSION_ID: + { + /* Return the version of current implementation */ + SMC_RET2(handle, QTI_SIP_SVC_VERSION_MAJOR, + QTI_SIP_SVC_VERSION_MINOR); + break; + } + case QTI_SIP_SVC_AVAILABLE_ID: + { + if (x1 != 1) { + SMC_RET1(handle, QTI_SIP_INVALID_PARAM); + } + if (qti_check_syscall_availability(x2) == true) { + SMC_RET2(handle, QTI_SIP_SUCCESS, 1); + } else { + SMC_RET2(handle, QTI_SIP_SUCCESS, 0); + } + break; + } + case QTI_SIP_SVC_SECURE_IO_READ_ID: + { + if ((x1 == QTI_SIP_SVC_SECURE_IO_READ_PARAM_ID) && + qti_is_secure_io_access_allowed(x2)) { + SMC_RET2(handle, QTI_SIP_SUCCESS, + *((volatile uint32_t *)x2)); + } + SMC_RET1(handle, QTI_SIP_INVALID_PARAM); + break; + } + case QTI_SIP_SVC_SECURE_IO_WRITE_ID: + { + if ((x1 == QTI_SIP_SVC_SECURE_IO_WRITE_PARAM_ID) && + qti_is_secure_io_access_allowed(x2)) { + *((volatile uint32_t *)x2) = x3; + SMC_RET1(handle, QTI_SIP_SUCCESS); + } + SMC_RET1(handle, QTI_SIP_INVALID_PARAM); + break; + } + case QTI_SIP_SVC_MEM_ASSIGN_ID: + { + return qti_sip_mem_assign(handle, GET_SMC_CC(smc_fid), + x1, x2, x3, x4); + break; + } + default: + { + SMC_RET1(handle, QTI_SIP_NOT_SUPPORTED); + } + } + return (uintptr_t) handle; +} + +/* Define a runtime service descriptor for both fast & yield SiP calls */ +DECLARE_RT_SVC(qti_sip_fast_svc, OEN_SIP_START, + OEN_SIP_END, SMC_TYPE_FAST, NULL, qti_sip_handler); + +DECLARE_RT_SVC(qti_sip_yield_svc, OEN_SIP_START, + OEN_SIP_END, SMC_TYPE_YIELD, NULL, qti_sip_handler); diff --git a/arm-trusted-firmware/plat/qti/common/src/qti_topology.c b/arm-trusted-firmware/plat/qti/common/src/qti_topology.c new file mode 100644 index 0000000..bf2e3f3 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_topology.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018,2020 The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* The QTI power domain tree descriptor */ +const unsigned char qti_power_domain_tree_desc[] = { + /* One domain to represent PDC */ + PLAT_PDC_COUNT, + /* One domain to represent RSC */ + PLAT_RSC_COUNT, + /* There is one top-level FCM cluster */ + PLAT_CLUSTER_COUNT, + /* No. of cores in the FCM cluster */ + PLAT_CLUSTER0_CORE_COUNT +}; + +/******************************************************************************* + * This function returns the ARM default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return qti_power_domain_tree_desc; +} + +/** Function: plat_core_pos_by_mpidr + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + */ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + int core_linear_index = plat_qti_core_pos_by_mpidr(mpidr); + + if (core_linear_index < PLATFORM_CORE_COUNT) { + return core_linear_index; + } else { + return -1; + } +} diff --git a/arm-trusted-firmware/plat/qti/common/src/spmi_arb.c b/arm-trusted-firmware/plat/qti/common/src/spmi_arb.c new file mode 100644 index 0000000..4213ed1 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/spmi_arb.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2020, Google LLC. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#define REG_APID_MAP(apid) (0x0C440900U + sizeof(uint32_t) * apid) +#define NUM_APID ((0x1100U - 0x900U) / sizeof(uint32_t)) + +#define PPID_MASK (0xfffU << 8) + +#define REG_ARB_CMD(apid) (0x0C600000U + 0x10000U * apid) +/* These are opcodes specific to this SPMI arbitrator, *not* SPMI commands. */ +#define OPC_EXT_WRITEL 0 +#define OPC_EXT_READL 1 + +#define REG_ARB_STATUS(apid) (0x0C600008U + 0x10000U * apid) +#define ARB_STATUS_DONE BIT(0) +#define ARB_STATUS_FAILURE BIT(1) +#define ARB_STATUS_DENIED BIT(2) +#define ARB_STATUS_DROPPED BIT(3) + +/* Fake status to report driver errors. */ +#define ARB_FAKE_STATUS_TIMEOUT BIT(8) + +#define REG_ARB_RDATA0(apid) (0x0C600018U + 0x10000U * apid) +#define REG_ARB_WDATA0(apid) (0x0C600010U + 0x10000U * apid) + +static int addr_to_apid(uint32_t addr) +{ + unsigned int i; + + for (i = 0U; i < NUM_APID; i++) { + uint32_t reg = mmio_read_32(REG_APID_MAP(i)); + if ((reg != 0U) && ((addr & PPID_MASK) == (reg & PPID_MASK))) { + return i; + } + } + + return -1; +} + +static int wait_for_done(uint16_t apid) +{ + unsigned int timeout = 100; + + while (timeout-- != 0U) { + uint32_t status = mmio_read_32(REG_ARB_STATUS(apid)); + if ((status & ARB_STATUS_DONE) != 0U) { + if ((status & ARB_STATUS_FAILURE) != 0U || + (status & ARB_STATUS_DENIED) != 0U || + (status & ARB_STATUS_DROPPED) != 0U) { + return status & 0xff; + } + return 0; + } + mdelay(1); + } + ERROR("SPMI_ARB timeout!\n"); + return ARB_FAKE_STATUS_TIMEOUT; +} + +static void arb_command(uint16_t apid, uint8_t opcode, uint32_t addr, + uint8_t bytes) +{ + mmio_write_32(REG_ARB_CMD(apid), (uint32_t)opcode << 27 | + (addr & 0xff) << 4 | (bytes - 1)); +} + +int spmi_arb_read8(uint32_t addr) +{ + int apid = addr_to_apid(addr); + + if (apid < 0) { + return apid; + } + + arb_command(apid, OPC_EXT_READL, addr, 1); + + int ret = wait_for_done(apid); + if (ret != 0) { + ERROR("SPMI_ARB read error [0x%x]: 0x%x\n", addr, ret); + return ret; + } + + return mmio_read_32(REG_ARB_RDATA0(apid)) & 0xff; +} + +int spmi_arb_write8(uint32_t addr, uint8_t data) +{ + int apid = addr_to_apid(addr); + + if (apid < 0) { + return apid; + } + + mmio_write_32(REG_ARB_WDATA0(apid), data); + arb_command(apid, OPC_EXT_WRITEL, addr, 1); + + int ret = wait_for_done(apid); + if (ret != 0) { + ERROR("SPMI_ARB write error [0x%x] = 0x%x: 0x%x\n", + addr, data, ret); + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S b/arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S new file mode 100644 index 0000000..dad9968 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#define APCS_TCM_START_ADDR 0x10 +#define APCS_TCM_REDIRECT_EN_0 BIT_32(0) + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_panic_handler + .globl plat_my_core_pos + .globl plat_get_my_entrypoint + .globl plat_reset_handler + .globl platform_mem_init + .globl msm8916_entry_point + + /* ------------------------------------------------- + * int plat_crash_console_init(void) + * Initialize the crash console. + * Out: x0 - 1 on success, 0 on error + * Clobber list : x0 - x4 + * ------------------------------------------------- + */ +func plat_crash_console_init + mov x1, #BLSP_UART2_BASE + + /* + * If the non-secure world has been actively using the UART there might + * be still some characters left to be sent in the FIFO. In that case, + * resetting the transmitter too early might cause all output to become + * corrupted. To avoid that, try to flush (wait until FIFO empty) first. + */ + mov x4, lr + bl console_uartdm_core_flush + mov lr, x4 + + mov x0, #1 + b console_uartdm_core_init +endfunc plat_crash_console_init + + /* ------------------------------------------------- + * int plat_crash_console_putc(int c) + * Print a character on the crash console. + * In : w0 - character to be printed + * Out: w0 - printed character on success + * Clobber list : x1, x2 + * ------------------------------------------------- + */ +func plat_crash_console_putc + mov x1, #BLSP_UART2_BASE + b console_uartdm_core_putc +endfunc plat_crash_console_putc + + /* ------------------------------------------------- + * void plat_crash_console_flush(void) + * Force a write of all buffered data that has not + * been output. + * Clobber list : x1, x2 + * ------------------------------------------------- + */ +func plat_crash_console_flush + mov x1, #BLSP_UART2_BASE + b console_uartdm_core_flush +endfunc plat_crash_console_flush + + /* ------------------------------------------------- + * void plat_panic_handler(void) __dead + * Called when an unrecoverable error occurs. + * ------------------------------------------------- + */ +func plat_panic_handler + /* Try to shutdown/reset */ + mov_imm x0, MPM_PS_HOLD + str wzr, [x0] +1: b 1b +endfunc plat_panic_handler + + /* ------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * Out: x0 - index of the calling CPU + * ------------------------------------------------- + */ +func plat_my_core_pos + /* There is just a single cluster so this is very simple */ + mrs x0, mpidr_el1 + and x0, x0, #MPIDR_CPU_MASK + ret +endfunc plat_my_core_pos + + /* ------------------------------------------------- + * uintptr_t plat_get_my_entrypoint(void) + * Distinguish cold and warm boot and return warm boot + * entry address if available. + * Out: x0 - warm boot entry point or 0 on cold boot + * ------------------------------------------------- + */ +func plat_get_my_entrypoint + ldr x0, msm8916_entry_point + ret +endfunc plat_get_my_entrypoint + + /* ------------------------------------------------- + * void plat_reset_handler(void) + * Perform additional initialization after reset. + * Clobber list : x0 - x18, x30 + * ------------------------------------------------- + */ +func plat_reset_handler + /* + * Check if the CPU is running at the correct address. + * During cold boot the CPU enters here at the wrong address + * using the "boot remapper". (It remaps the BL31_BASE to + * the CPU reset address 0x0). + */ + mov x0, #BL31_BASE + adr x1, bl31_entrypoint + cmp x0, x1 + b.ne _remapped_cold_boot + /* Already running at correct address, just return directly */ + ret + +_remapped_cold_boot: + /* + * The previous boot stage seems to use the L2 cache as TCM. + * Disable the TCM redirect before enabling caches to avoid + * strange crashes. + */ + mov x2, #APCS_CFG + ldr w3, [x2, #APCS_TCM_START_ADDR] + and w3, w3, #~APCS_TCM_REDIRECT_EN_0 + str w3, [x2, #APCS_TCM_START_ADDR] + + /* Enter BL31 again at the real address */ + br x0 +endfunc plat_reset_handler + + /* ------------------------------------------------- + * void platform_mem_init(void) + * Performs additional memory initialization early + * in the boot process. + * ------------------------------------------------- + */ +func platform_mem_init + /* Nothing to do here, all memory is already initialized */ + ret +endfunc platform_mem_init + + .data + .align 3 + + /* ------------------------------------------------- + * Warm boot entry point for CPU. Set by PSCI code. + * ------------------------------------------------- + */ +msm8916_entry_point: + .quad 0 diff --git a/arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S b/arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S new file mode 100644 index 0000000..c69c193 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * Based on aarch64/skeleton_console.S: + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* UART DM registers */ +#define UART_DM_DMEN 0x03c /* DMA / data packing */ +#define UART_DM_SR 0x0a4 /* status register */ +#define UART_DM_CR 0x0a8 /* command register */ +#define UART_DM_TF 0x100 /* transmit FIFO */ + +#define UART_DM_DMEN_TX_SC BIT_32(4) /* TX single character mode */ + +#define UART_DM_SR_TXRDY_BIT 2 /* TX FIFO has space */ +#define UART_DM_SR_TXEMT_BIT 3 /* TX FIFO is empty */ + +#define UART_DM_CR_RESET_RX (U(0x01) << 4) /* reset receiver */ +#define UART_DM_CR_RESET_TX (U(0x02) << 4) /* reset transmitter */ +#define UART_DM_CR_TX_ENABLE BIT_32(2) /* enable transmitter */ + + .globl console_uartdm_register + .globl console_uartdm_core_init + .globl console_uartdm_putc + .globl console_uartdm_core_putc + .globl console_uartdm_flush + .globl console_uartdm_core_flush + + /* ----------------------------------------------------------- + * int console_uartdm_register(console_t *console, + * uintptr_t base_addr) + * Function to initialize and register the console. The caller + * needs to pass an empty console_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 - base address + * Out: x0 - 1 on success, 0 on error + * Clobber list : x0 - x7 + * ----------------------------------------------------------- + */ +func console_uartdm_register + str x1, [x0, #CONSOLE_T_BASE] + mov x7, lr + bl console_uartdm_core_init + mov lr, x7 + + /* Register the new console */ + finish_console_register uartdm putc=1, flush=1 +endfunc console_uartdm_register + + /* ----------------------------------------------------------- + * void console_uartdm_core_init(unused, uintptr_t base_addr) + * Function to initialize the console. + * In : x0 - unused + * x1 - base address + * Out: void + * Clobber list : x1, x2, x3 + * ----------------------------------------------------------- + */ +func console_uartdm_core_init + /* Reset receiver */ + mov w3, #UART_DM_CR_RESET_RX + str w3, [x1, #UART_DM_CR] + + /* Reset transmitter */ + mov w3, #UART_DM_CR_RESET_TX + str w3, [x1, #UART_DM_CR] + + /* + * Disable BAM/DMA modes but enable single-character mode for TX. + * The single character mode allows simplifying the putc implementation + * since characters can be written directly to the FIFO instead of + * having to initiate a new transfer and waiting for its completion. + */ + mov w3, #UART_DM_DMEN_TX_SC + str w3, [x1, #UART_DM_DMEN] + + /* Enable transmitter */ + mov w3, #UART_DM_CR_TX_ENABLE + str w3, [x1, #UART_DM_CR] + + ret +endfunc console_uartdm_core_init + + /* ----------------------------------------------------------- + * int console_uartdm_putc(int c, console_t *console) + * Function to output a character over the console. + * 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_uartdm_putc + ldr x1, [x1, #CONSOLE_T_BASE] + b console_uartdm_core_putc +endfunc console_uartdm_putc + + /* ----------------------------------------------------------- + * int console_uartdm_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. + * In : w0 - character to be printed + * x1 - base address + * Out: w0 - printed character on success, < 0 on error. + * Clobber list : x2 + * ----------------------------------------------------------- + */ +func console_uartdm_core_putc +1: /* Loop until TX FIFO has space */ + ldr w2, [x1, #UART_DM_SR] + tbz w2, #UART_DM_SR_TXRDY_BIT, 1b + + /* Write character to FIFO */ + str w0, [x1, #UART_DM_TF] + ret +endfunc console_uartdm_core_putc + + /* ----------------------------------------------------------- + * void console_uartdm_flush(console_t *console) + * Function to force a write of all buffered data + * that has not been output. + * In : x0 - pointer to console_t struct + * Out: void + * Clobber list : x0, x1, x2, x3, x4, x5 + * ----------------------------------------------------------- + */ +func console_uartdm_flush + ldr x1, [x0, #CONSOLE_T_BASE] + b console_uartdm_core_flush +endfunc console_uartdm_flush + + /* ----------------------------------------------------------- + * void console_uartdm_core_flush(unused, uintptr_t base_addr) + * Function to force a write of all buffered data + * that has not been output. + * In : x0 - unused + * x1 - base address + * Out: void + * Clobber list : x2 + * ----------------------------------------------------------- + */ +func console_uartdm_core_flush +1: /* Loop until TX FIFO is empty */ + ldr w2, [x1, #UART_DM_SR] + tbz w2, #UART_DM_SR_TXEMT_BIT, 1b + ret +endfunc console_uartdm_core_flush diff --git a/arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h b/arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h new file mode 100644 index 0000000..406ae6b --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MSM8916_MMAP_H +#define MSM8916_MMAP_H + +#define PCNOC_BASE 0x00000000 +#define PCNOC_SIZE 0x8000000 /* 128 MiB */ +#define APCS_BASE 0x0b000000 +#define APCS_SIZE 0x800000 /* 8 MiB */ + +#define MPM_BASE (PCNOC_BASE + 0x04a0000) +#define MPM_PS_HOLD (MPM_BASE + 0xb000) + +#define TLMM_BASE (PCNOC_BASE + 0x1000000) +#define TLMM_GPIO_CFG(n) (TLMM_BASE + ((n) * 0x1000)) + +#define GCC_BASE (PCNOC_BASE + 0x1800000) + +#define APPS_SMMU_BASE (PCNOC_BASE + 0x1e00000) +#define APPS_SMMU_QCOM (APPS_SMMU_BASE + 0xf0000) + +#define BLSP_UART1_BASE (PCNOC_BASE + 0x78af000) +#define BLSP_UART2_BASE (PCNOC_BASE + 0x78b0000) + +#define APCS_QGIC2_BASE (APCS_BASE + 0x00000) +#define APCS_QGIC2_GICD (APCS_QGIC2_BASE + 0x0000) +#define APCS_QGIC2_GICC (APCS_QGIC2_BASE + 0x2000) +#define APCS_BANKED_ACS (APCS_BASE + 0x08000) +#define APCS_BANKED_SAW2 (APCS_BASE + 0x09000) +#define APCS_CFG (APCS_BASE + 0x10000) +#define APCS_GLB (APCS_BASE + 0x11000) +#define APCS_L2_SAW2 (APCS_BASE + 0x12000) +#define APCS_QTMR (APCS_BASE + 0x20000) +#define APCS_ALIAS_ACS(cpu) (APCS_BASE + 0x88000 + ((cpu) * 0x10000)) +#define APCS_ALIAS_SAW2(cpu) (APCS_BASE + 0x89000 + ((cpu) * 0x10000)) + +#endif /* MSM8916_MMAP_H */ diff --git a/arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S b/arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S new file mode 100644 index 0000000..552add2 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_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 plat_crash_print_regs + mov_imm x16, APCS_QGIC2_GICD + mov_imm x17, APCS_QGIC2_GICC + arm_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h b/arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h new file mode 100644 index 0000000..bfade70 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +/* + * There is at least 1 MiB available for BL31. However, at the moment the + * "msm8916_entry_point" variable in the data section is read through the + * 64 KiB region of the "boot remapper" after reset. For simplicity, limit + * the end of the data section (BL31_PROGBITS_LIMIT) to 64 KiB for now and + * the overall limit to 128 KiB. This could be increased if needed by placing + * the "msm8916_entry_point" variable explicitly in the first 64 KiB of BL31. + */ +#define BL31_LIMIT (BL31_BASE + 0x20000) /* 128 KiB */ +#define BL31_PROGBITS_LIMIT (BL31_BASE + 0x10000) /* 64 KiB */ + +#define CACHE_WRITEBACK_GRANULE U(64) +#define PLATFORM_STACK_SIZE U(0x1000) + +/* CPU topology: single cluster with 4 cores */ +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) + +/* Power management */ +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_RET_STATE U(2) +#define PLAT_MAX_OFF_STATE U(3) + +/* Translation tables */ +#define MAX_MMAP_REGIONS 8 +#define MAX_XLAT_TABLES 4 + +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +/* Timer frequency */ +#define PLAT_SYSCNT_FREQ 19200000 + +/* + * The Qualcomm QGIC2 implementation seems to have PIDR0-4 and PIDR4-7 + * erroneously swapped for some reason. PIDR2 is actually at 0xFD8. + * Override the address in to avoid a failing assert(). + */ +#define GICD_PIDR2_GICV2 U(0xFD8) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h b/arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h new file mode 100644 index 0000000..0f09ba8 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UARTDM_CONSOLE_H +#define UARTDM_CONSOLE_H + +int console_uartdm_register(console_t *console, uintptr_t base_addr); + +#endif /* UARTDM_CONSOLE_H */ diff --git a/arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c new file mode 100644 index 0000000..638cd09 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "msm8916_gicv2.h" +#include +#include +#include + +static const mmap_region_t msm8916_mmap[] = { + MAP_REGION_FLAT(PCNOC_BASE, PCNOC_SIZE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), + MAP_REGION_FLAT(APCS_BASE, APCS_SIZE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), + {}, +}; + +static struct { + entry_point_info_t bl32; + entry_point_info_t bl33; +} image_ep_info = { + /* BL32 entry point */ + SET_STATIC_PARAM_HEAD(bl32, PARAM_EP, VERSION_1, + entry_point_info_t, SECURE), + .bl32.pc = BL32_BASE, + + /* BL33 entry point */ + SET_STATIC_PARAM_HEAD(bl33, PARAM_EP, VERSION_1, + entry_point_info_t, NON_SECURE), + .bl33.pc = PRELOADED_BL33_BASE, + .bl33.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), +}; + +static console_t console; + +unsigned int plat_get_syscnt_freq2(void) +{ + return PLAT_SYSCNT_FREQ; +} + +#define CLK_ENABLE BIT_32(0) +#define CLK_OFF BIT_32(31) + +#define GPIO_BLSP_UART2_TX 4 +#define GPIO_BLSP_UART2_RX 5 +#define GPIO_CFG_FUNC_BLSP_UART2 (U(0x2) << 2) +#define GPIO_CFG_DRV_STRENGTH_16MA (U(0x7) << 6) + +#define GCC_BLSP1_AHB_CBCR (GCC_BASE + 0x01008) +#define GCC_BLSP1_UART2_APPS_CBCR (GCC_BASE + 0x0302c) +#define GCC_APCS_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x45004) +#define BLSP1_AHB_CLK_ENA BIT_32(10) + +/* + * The previous boot stage seems to disable most of the UART setup before exit + * so it must be enabled here again before the UART console can be used. + */ +static void msm8916_enable_blsp_uart2(void) +{ + /* Route GPIOs to BLSP UART2 */ + mmio_write_32(TLMM_GPIO_CFG(GPIO_BLSP_UART2_TX), + GPIO_CFG_FUNC_BLSP_UART2 | GPIO_CFG_DRV_STRENGTH_16MA); + mmio_write_32(TLMM_GPIO_CFG(GPIO_BLSP_UART2_RX), + GPIO_CFG_FUNC_BLSP_UART2 | GPIO_CFG_DRV_STRENGTH_16MA); + + /* Enable AHB clock */ + mmio_setbits_32(GCC_APCS_CLOCK_BRANCH_ENA_VOTE, BLSP1_AHB_CLK_ENA); + while (mmio_read_32(GCC_BLSP1_AHB_CBCR) & CLK_OFF) + ; + + /* Enable BLSP UART2 clock */ + mmio_setbits_32(GCC_BLSP1_UART2_APPS_CBCR, CLK_ENABLE); + while (mmio_read_32(GCC_BLSP1_UART2_APPS_CBCR) & CLK_OFF) + ; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* Initialize the debug console as early as possible */ + msm8916_enable_blsp_uart2(); + console_uartdm_register(&console, BLSP_UART2_BASE); +} + +void bl31_plat_arch_setup(void) +{ + mmap_add_region(BL31_BASE, BL31_BASE, BL31_END - BL31_BASE, + MT_RW_DATA | MT_SECURE); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, + BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE); + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER); + + mmap_add(msm8916_mmap); + init_xlat_tables(); + enable_mmu_el3(0); +} + +static void msm8916_configure_timer(void) +{ + /* Set timer frequency */ + mmio_write_32(APCS_QTMR + CNTCTLBASE_CNTFRQ, plat_get_syscnt_freq2()); + + /* Make frame 0 available to non-secure world */ + mmio_write_32(APCS_QTMR + CNTNSAR, BIT_32(CNTNSAR_NS_SHIFT(0))); + mmio_write_32(APCS_QTMR + CNTACR_BASE(0), + BIT_32(CNTACR_RPCT_SHIFT) | BIT_32(CNTACR_RVCT_SHIFT) | + BIT_32(CNTACR_RFRQ_SHIFT) | BIT_32(CNTACR_RVOFF_SHIFT) | + BIT_32(CNTACR_RWVT_SHIFT) | BIT_32(CNTACR_RWPT_SHIFT)); +} + +/* + * The APCS register regions always start with a SECURE register that should + * be cleared to 0 to only allow secure access. Since BL31 handles most of + * the CPU power management, most of them can be cleared to secure access only. + */ +#define APCS_GLB_SECURE_STS_NS BIT_32(0) +#define APCS_GLB_SECURE_PWR_NS BIT_32(1) +#define APCS_BOOT_START_ADDR_SEC (APCS_CFG + 0x04) +#define REMAP_EN BIT_32(0) +#define APCS_AA64NAA32_REG (APCS_CFG + 0x0c) + +static void msm8916_configure_cpu_pm(void) +{ + unsigned int cpu; + + /* Disallow non-secure access to boot remapper / TCM registers */ + mmio_write_32(APCS_CFG, 0); + + /* + * Disallow non-secure access to power management registers. + * However, allow STS and PWR since those also seem to control access + * to CPU frequency related registers (e.g. APCS_CMD_RCGR). If these + * bits are not set, CPU frequency control fails in the non-secure world. + */ + mmio_write_32(APCS_GLB, APCS_GLB_SECURE_STS_NS | APCS_GLB_SECURE_PWR_NS); + + /* Disallow non-secure access to L2 SAW2 */ + mmio_write_32(APCS_L2_SAW2, 0); + + /* Disallow non-secure access to CPU ACS and SAW2 */ + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { + mmio_write_32(APCS_ALIAS_ACS(cpu), 0); + mmio_write_32(APCS_ALIAS_SAW2(cpu), 0); + } + + /* Make sure all further warm boots end up in BL31 and aarch64 state */ + CASSERT((BL31_BASE & 0xffff) == 0, assert_bl31_base_64k_aligned); + mmio_write_32(APCS_BOOT_START_ADDR_SEC, BL31_BASE | REMAP_EN); + mmio_write_32(APCS_AA64NAA32_REG, 1); +} + +/* + * MSM8916 has a special "interrupt aggregation logic" in the APPS SMMU, + * which allows routing context bank interrupts to one of 3 interrupt numbers + * ("TZ/HYP/NS"). Route all interrupts to the non-secure interrupt number + * by default to avoid special setup on the non-secure side. + */ +#define GCC_SMMU_CFG_CBCR (GCC_BASE + 0x12038) +#define GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x4500c) +#define SMMU_CFG_CLK_ENA BIT_32(12) +#define APPS_SMMU_INTR_SEL_NS (APPS_SMMU_QCOM + 0x2000) +#define APPS_SMMU_INTR_SEL_NS_EN_ALL U(0xffffffff) + +static void msm8916_configure_smmu(void) +{ + /* Enable SMMU configuration clock to enable register access */ + mmio_setbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA); + while (mmio_read_32(GCC_SMMU_CFG_CBCR) & CLK_OFF) + ; + + /* Route all context bank interrupts to non-secure interrupt */ + mmio_write_32(APPS_SMMU_INTR_SEL_NS, APPS_SMMU_INTR_SEL_NS_EN_ALL); + + /* Disable configuration clock again */ + mmio_clrbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA); +} + +void bl31_platform_setup(void) +{ + INFO("BL31: Platform setup start\n"); + generic_delay_timer_init(); + msm8916_configure_timer(); + msm8916_gicv2_init(); + msm8916_configure_cpu_pm(); + msm8916_configure_smmu(); + INFO("BL31: Platform setup done\n"); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + switch (type) { + case SECURE: + return &image_ep_info.bl32; + case NON_SECURE: + return &image_ep_info.bl33; + default: + assert(sec_state_is_valid(type)); + return NULL; + } +} diff --git a/arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c new file mode 100644 index 0000000..b3f51f6 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include "msm8916_pm.h" + +#define CPU_PWR_CTL 0x4 +#define APC_PWR_GATE_CTL 0x14 + +#define CPU_PWR_CTL_CLAMP BIT_32(0) +#define CPU_PWR_CTL_CORE_MEM_CLAMP BIT_32(1) +#define CPU_PWR_CTL_L1_RST_DIS BIT_32(2) +#define CPU_PWR_CTL_CORE_MEM_HS BIT_32(3) +#define CPU_PWR_CTL_CORE_RST BIT_32(4) +#define CPU_PWR_CTL_COREPOR_RST BIT_32(5) +#define CPU_PWR_CTL_GATE_CLK BIT_32(6) +#define CPU_PWR_CTL_CORE_PWRD_UP BIT_32(7) + +#define APC_PWR_GATE_CTL_GHDS_EN BIT_32(0) +#define APC_PWR_GATE_CTL_GHDS_CNT(cnt) ((cnt) << 24) + +/* Boot a secondary CPU core for the first time. */ +void msm8916_cpu_boot(unsigned int core) +{ + uintptr_t acs = APCS_ALIAS_ACS(core); + uint32_t pwr_ctl; + + pwr_ctl = CPU_PWR_CTL_CLAMP | CPU_PWR_CTL_CORE_MEM_CLAMP | + CPU_PWR_CTL_CORE_RST | CPU_PWR_CTL_COREPOR_RST; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + + mmio_write_32(acs + APC_PWR_GATE_CTL, APC_PWR_GATE_CTL_GHDS_EN | + APC_PWR_GATE_CTL_GHDS_CNT(16)); + dsb(); + udelay(2); + + pwr_ctl &= ~CPU_PWR_CTL_CORE_MEM_CLAMP; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + + pwr_ctl |= CPU_PWR_CTL_CORE_MEM_HS; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + udelay(2); + + pwr_ctl &= ~CPU_PWR_CTL_CLAMP; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + udelay(2); + + pwr_ctl &= ~(CPU_PWR_CTL_CORE_RST | CPU_PWR_CTL_COREPOR_RST); + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + + pwr_ctl |= CPU_PWR_CTL_CORE_PWRD_UP; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); +} diff --git a/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c new file mode 100644 index 0000000..25a6628 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "msm8916_gicv2.h" +#include + +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 + +#define IRQ_SEC_PHY_TIMER (16 + 2) /* PPI #2 */ + +static const interrupt_prop_t msm8916_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +static const gicv2_driver_data_t msm8916_gic_data = { + .gicd_base = APCS_QGIC2_GICD, + .gicc_base = APCS_QGIC2_GICC, + .interrupt_props = msm8916_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(msm8916_interrupt_props), +}; + +void msm8916_gicv2_init(void) +{ + gicv2_driver_init(&msm8916_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} diff --git a/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h b/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h new file mode 100644 index 0000000..99db0d3 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MSM8916_GICV2_H +#define MSM8916_GICV2_H + +void msm8916_gicv2_init(void); + +#endif /* MSM8916_GICV2_H */ diff --git a/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c new file mode 100644 index 0000000..6891e38 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "msm8916_pm.h" + +static int msm8916_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + VERBOSE("PSCI: Booting CPU %d\n", core); + msm8916_cpu_boot(core); + + return PSCI_E_SUCCESS; +} + +static void msm8916_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void __dead2 msm8916_system_reset(void) +{ + mmio_write_32(MPM_PS_HOLD, 0); + mdelay(1000); + + ERROR("PSCI: System reset failed\n"); + panic(); +} + +static const plat_psci_ops_t msm8916_psci_ops = { + .pwr_domain_on = msm8916_pwr_domain_on, + .pwr_domain_on_finish = msm8916_pwr_domain_on_finish, + .system_off = msm8916_system_reset, + .system_reset = msm8916_system_reset, +}; + +/* Defined and used in msm8916_helpers.S */ +extern uintptr_t msm8916_entry_point; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + msm8916_entry_point = sec_entrypoint; + *psci_ops = &msm8916_psci_ops; + return 0; +} diff --git a/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h b/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h new file mode 100644 index 0000000..5473bfa --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MSM8916_PM_H +#define MSM8916_PM_H + +void msm8916_cpu_boot(unsigned int core); + +#endif /* MSM8916_PM_H */ diff --git a/arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c new file mode 100644 index 0000000..4d0ed8f --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +static const unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = { + PLATFORM_SYSTEM_COUNT, + PLATFORM_CLUSTER_COUNT, + PLATFORM_MAX_CPUS_PER_CLUSTER, +}; + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + if (MPIDR_AFFLVL3_VAL(mpidr) > 0 || + MPIDR_AFFLVL2_VAL(mpidr) > 0 || + MPIDR_AFFLVL1_VAL(mpidr) > 0 || + core >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return core; +} + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/arm-trusted-firmware/plat/qti/msm8916/platform.mk b/arm-trusted-firmware/plat/qti/msm8916/platform.mk new file mode 100644 index 0000000..e516cea --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/platform.mk @@ -0,0 +1,62 @@ +# +# Copyright (c) 2021, Stephan Gerhold +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/arm/gic/v2/gicv2.mk +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES := ${XLAT_TABLES_LIB_SRCS} + +PLAT_INCLUDES := -Iinclude/plat/arm/common/${ARCH} \ + -Iplat/qti/msm8916/include + +BL31_SOURCES += ${GICV2_SOURCES} \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/${ARCH}/cortex_a53.S \ + plat/common/plat_gicv2.c \ + plat/common/plat_psci_common.c \ + plat/qti/msm8916/msm8916_bl31_setup.c \ + plat/qti/msm8916/msm8916_cpu_boot.c \ + plat/qti/msm8916/msm8916_gicv2.c \ + plat/qti/msm8916/msm8916_pm.c \ + plat/qti/msm8916/msm8916_topology.c \ + plat/qti/msm8916/${ARCH}/msm8916_helpers.S \ + plat/qti/msm8916/${ARCH}/uartdm_console.S + +# Only BL31 is supported at the moment and is entered on a single CPU +RESET_TO_BL31 := 1 +COLD_BOOT_SINGLE_CPU := 1 + +# Build config flags +# ------------------ +BL31_BASE ?= 0x86500000 +BL32_BASE ?= 0x86000000 +PRELOADED_BL33_BASE ?= 0x8f600000 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Single cluster +WARMBOOT_ENABLE_DCACHE_EARLY := 1 + +# Disable features unsupported in ARMv8.0 +ENABLE_AMU := 0 +ENABLE_SPE_FOR_LOWER_ELS := 0 +ENABLE_SVE_FOR_NS := 0 + +# MSM8916 uses ARM Cortex-A53 r0p0 so likely all the errata apply +ERRATA_A53_819472 := 1 +ERRATA_A53_824069 := 1 +ERRATA_A53_826319 := 1 +ERRATA_A53_827319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 0 # Workaround works only for >= r0p3 +ERRATA_A53_1530924 := 1 + +$(eval $(call add_define,BL31_BASE)) +$(eval $(call add_define,BL32_BASE)) diff --git a/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h new file mode 100644 index 0000000..deef41c --- /dev/null +++ b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTISECLIB_CB_INTERFACE_H +#define QTISECLIB_CB_INTERFACE_H + +#include +#include +#include +#include + +#include + +/* Standard Library API's */ +void *qtiseclib_cb_memcpy(void *dst, const void *src, size_t len); +int qtiseclib_cb_strcmp(const char *s1, const char *s2); +void *qtiseclib_cb_memset(void *s, int c, size_t n); +void *qtiseclib_cb_memmove(void *dest, const void *src, size_t n); + +#define QTISECLIB_CB_ERROR(...) qtiseclib_cb_log(QTISECLIB_LOG_LEVEL_ERROR, __VA_ARGS__) +#define QTISECLIB_CB_NOTICE(...) qtiseclib_cb_log(QTISECLIB_LOG_LEVEL_NOTICE, __VA_ARGS__) +#define QTISECLIB_CB_WARN(...) qtiseclib_cb_log(QTISECLIB_LOG_LEVEL_WARNING, __VA_ARGS__) +#define QTISECLIB_CB_INFO(...) qtiseclib_cb_log(QTISECLIB_LOG_LEVEL_INFO, __VA_ARGS__) + +void qtiseclib_cb_log(unsigned int loglvl, const char *fmt, ...); + +void qtiseclib_cb_spin_lock(qtiseclib_cb_spinlock_t *lock); +void qtiseclib_cb_spin_unlock(qtiseclib_cb_spinlock_t *lock); + +unsigned int qtiseclib_cb_plat_my_core_pos(void); +int qtiseclib_cb_plat_core_pos_by_mpidr(u_register_t mpidr); +unsigned int qtiseclib_cb_plat_my_cluster_pos(void); + +/* GIC platform wrappers */ +void qtiseclib_cb_gic_pcpu_init(void); +void qtiseclib_cb_ic_raise_sgi(int sgi_num, u_register_t target); +void qtiseclib_cb_set_spi_routing(unsigned int id, unsigned int irm, + u_register_t target); +/* Crash reporting api's wrappers */ +void qtiseclib_cb_switch_console_to_crash_state(void); + +void qtiseclib_cb_udelay(uint32_t usec); + +void qtiseclib_cb_console_flush(void); + +#if QTI_SDI_BUILD +int qtiseclib_cb_mmap_remove_dynamic_region(uintptr_t base_va, size_t size); +int qtiseclib_cb_mmap_add_dynamic_region(unsigned long long base_pa, + size_t size, + qtiseclib_mmap_attr_t attr); + +void qtiseclib_cb_flush_dcache_all(void); +void qtiseclib_cb_get_ns_ctx(qtiseclib_dbg_a64_ctxt_regs_type *ns_ctx); +#endif + +#endif /* QTISECLIB_CB_INTERFACE_H */ diff --git a/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h new file mode 100644 index 0000000..2afefe1 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTISECLIB_DEFS_H +#define QTISECLIB_DEFS_H + +#include + +#ifndef u_register_t +typedef uintptr_t u_register_t; +#endif + +/* + * Different Log Level supported in qtiseclib. + * TODO: Currently no filtering done on QTISECLIB logs. + */ +#define QTISECLIB_LOG_LEVEL_NONE 0 +#define QTISECLIB_LOG_LEVEL_ERROR 10 +#define QTISECLIB_LOG_LEVEL_NOTICE 20 +#define QTISECLIB_LOG_LEVEL_WARNING 30 +#define QTISECLIB_LOG_LEVEL_INFO 40 +#define QTISECLIB_LOG_LEVEL_VERBOSE 50 + +#define QTI_GICV3_IRM_PE 0 +#define QTI_GICV3_IRM_ANY 1 + +/* Common interrupt number/ID defs. */ +#define QTISECLIB_INT_ID_RESET_SGI (0xf) +#define QTISECLIB_INT_ID_CPU_WAKEUP_SGI (0x8) + +#define QTISECLIB_INT_INVALID_INT_NUM (0xFFFFFFFFU) + +typedef struct qtiseclib_cb_spinlock { + volatile uint32_t lock; +} qtiseclib_cb_spinlock_t; + +#if QTI_SDI_BUILD +/* External CPU Dump Structure - 64 bit EL */ +typedef struct { + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; + uint64_t x30; + uint64_t pc; + uint64_t currentEL; + uint64_t sp_el3; + uint64_t elr_el3; + uint64_t spsr_el3; + uint64_t sp_el2; + uint64_t elr_el2; + uint64_t spsr_el2; + uint64_t sp_el1; + uint64_t elr_el1; + uint64_t spsr_el1; + uint64_t sp_el0; + uint64_t __reserved1; + uint64_t __reserved2; + uint64_t __reserved3; + uint64_t __reserved4; + uint64_t __reserved5; + uint64_t __reserved6; + uint64_t __reserved7; + uint64_t __reserved8; +} qtiseclib_dbg_a64_ctxt_regs_type; + +typedef enum qtiseclib_mmap_attr_s { + QTISECLIB_MAP_NS_RO_XN_DATA = 1, + QTISECLIB_MAP_RW_XN_NC_DATA = 2, + QTISECLIB_MAP_RW_XN_DATA = 3, +} qtiseclib_mmap_attr_t; + +#endif /* QTI_SDI_BUILD */ + +#endif /* QTISECLIB_DEFS_H */ diff --git a/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h new file mode 100644 index 0000000..babed1b --- /dev/null +++ b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTISECLIB_INTERFACE_H +#define QTISECLIB_INTERFACE_H + +#include +#include + +#include + +typedef struct memprot_ipa_info_s { + uint64_t mem_addr; + uint64_t mem_size; +} memprot_info_t; + +typedef struct memprot_dst_vm_perm_info_s { + uint32_t dst_vm; + uint32_t dst_vm_perm; + uint64_t ctx; + uint32_t ctx_size; +} memprot_dst_vm_perm_info_t; + +/* + * QTISECLIB Published API's. + */ + +/* + * Assembly API's + */ + +/* + * CPUSS common reset handler for all CPU wake up (both cold & warm boot). + * Executes on all core. This API assume serialization across CPU + * already taken care before invoking. + * + * Clobbers: x0 - x17, x30 + */ +void qtiseclib_cpuss_reset_asm(uint32_t bl31_cold_boot_state); + +/* + * Execute CPU (Kryo4 gold) specific reset handler / system initialization. + * This takes care of executing required CPU errata's. + * + * Clobbers: x0 - x16 + */ +void qtiseclib_kryo4_gold_reset_asm(void); + +/* + * Execute CPU (Kryo46 gold) specific reset handler / system initialization. + * This takes care of executing required CPU errata's. + * + * Clobbers: x0 - x16 + */ +void qtiseclib_kryo6_gold_reset_asm(void); + +/* + * Execute CPU (Kryo4 silver) specific reset handler / system initialization. + * This takes care of executing required CPU errata's. + * + * Clobbers: x0 - x16 + */ +void qtiseclib_kryo4_silver_reset_asm(void); + +/* + * Execute CPU (Kryo6 silver) specific reset handler / system initialization. + * This takes care of executing required CPU errata's. + * + * Clobbers: x0 - x16 + */ +void qtiseclib_kryo6_silver_reset_asm(void); + +/* + * C Api's + */ +void qtiseclib_bl31_platform_setup(void); +void qtiseclib_invoke_isr(uint32_t irq, void *handle); +void qtiseclib_panic(void); + +int qtiseclib_mem_assign(const memprot_info_t *mem_info, + uint32_t mem_info_list_cnt, + const uint32_t *source_vm_list, + uint32_t src_vm_list_cnt, + const memprot_dst_vm_perm_info_t *dest_vm_list, + uint32_t dst_vm_list_cnt); + +int qtiseclib_psci_init(uintptr_t warmboot_entry); +int qtiseclib_psci_node_power_on(u_register_t mpidr); +void qtiseclib_psci_node_on_finish(const uint8_t *states); +void qtiseclib_psci_cpu_standby(uint8_t pwr_state); +void qtiseclib_psci_node_power_off(const uint8_t *states); +void qtiseclib_psci_node_suspend(const uint8_t *states); +void qtiseclib_psci_node_suspend_finish(const uint8_t *states); +void qtiseclib_disable_cluster_coherency(uint8_t state); + +#endif /* QTISECLIB_INTERFACE_H */ diff --git a/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h new file mode 100644 index 0000000..3ecee20 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QTISECLIB_DEFS_PLAT_H +#define QTISECLIB_DEFS_PLAT_H + +#define QTISECLIB_PLAT_CLUSTER_COUNT 1 +#define QTISECLIB_PLAT_CORE_COUNT 8 + +#define BL31_BASE 0x80b00000 +#define BL31_SIZE 0x00100000 + +/* Chipset specific secure interrupt number/ID defs. */ +#define QTISECLIB_INT_ID_SEC_WDOG_BARK (0x204) +#define QTISECLIB_INT_ID_NON_SEC_WDOG_BITE (0x21) + +#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC (0xE6) +#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC (0xE7) +#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC (0xE8) +#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC (0xE9) + +#define QTISECLIB_INT_ID_XPU_SEC (0xE3) +#define QTISECLIB_INT_ID_XPU_NON_SEC (0xE4) + +#define QTISECLIB_INT_ID_A2_NOC_ERROR (0x194) +#define QTISECLIB_INT_ID_CONFIG_NOC_ERROR (0xE2) +#define QTISECLIB_INT_ID_DC_NOC_ERROR (0x122) +#define QTISECLIB_INT_ID_MEM_NOC_ERROR (0x6C) +#define QTISECLIB_INT_ID_SYSTEM_NOC_ERROR (0xC6) +#define QTISECLIB_INT_ID_MMSS_NOC_ERROR (0xBA) + +#endif /* QTISECLIB_DEFS_PLAT_H */ diff --git a/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h new file mode 100644 index 0000000..b3d309f --- /dev/null +++ b/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __QTISECLIB_DEFS_PLAT_H__ +#define __QTISECLIB_DEFS_PLAT_H__ + +#define QTISECLIB_PLAT_CLUSTER_COUNT 1 +#define QTISECLIB_PLAT_CORE_COUNT 8 + +#define BL31_BASE 0xC0000000 +#define BL31_SIZE 0x00100000 + +/*----------------------------------------------------------------------------*/ +/* AOP CMD DB address space for mapping */ +/*----------------------------------------------------------------------------*/ +#define QTI_AOP_CMD_DB_BASE 0x80860000 +#define QTI_AOP_CMD_DB_SIZE 0x00020000 + +/* Chipset specific secure interrupt number/ID defs. */ +#define QTISECLIB_INT_ID_SEC_WDOG_BARK (0x204) +#define QTISECLIB_INT_ID_NON_SEC_WDOG_BITE (0x21) + +#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC (0xE6) +#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC (0xE7) +#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC (0xE8) +#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC (0xE9) + +#define QTISECLIB_INT_ID_XPU_SEC (0xE3) +#define QTISECLIB_INT_ID_XPU_NON_SEC (0xE4) + +//NOC INterrupt +#define QTISECLIB_INT_ID_A1_NOC_ERROR (0xC9) +#define QTISECLIB_INT_ID_A2_NOC_ERROR (0xEA) +#define QTISECLIB_INT_ID_CONFIG_NOC_ERROR (0xE2) +#define QTISECLIB_INT_ID_DC_NOC_ERROR (0x122) +#define QTISECLIB_INT_ID_MEM_NOC_ERROR (0x6C) +#define QTISECLIB_INT_ID_SYSTEM_NOC_ERROR (0xC8) +#define QTISECLIB_INT_ID_MMSS_NOC_ERROR (0xBA) +#define QTISECLIB_INT_ID_LPASS_AGNOC_ERROR (0x143) +#define QTISECLIB_INT_ID_NSP_NOC_ERROR (0x1CE) + +#endif /* __QTISECLIB_DEFS_PLAT_H__ */ diff --git a/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c b/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c new file mode 100644 index 0000000..c4cd259 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2018-2020, The Linux Foundation. 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 + +void *qtiseclib_cb_memcpy(void *dst, const void *src, size_t len) +{ + return memcpy(dst, src, len); +} + +int qtiseclib_cb_strcmp(const char *s1, const char *s2) +{ + return strcmp(s1, s2); +} + +void *qtiseclib_cb_memset(void *s, int c, size_t n) +{ + return memset(s, c, n); +} + +void *qtiseclib_cb_memmove(void *dest, const void *src, size_t n) +{ + return memmove(dest, src, n); +} + +/* Printing logs below or equal LOG_LEVEL from QTISECLIB. */ +void qtiseclib_cb_log(unsigned int loglvl, const char *fmt, ...) +{ + if (loglvl <= LOG_LEVEL) { + va_list argp; + static spinlock_t qti_log_lock; + uint64_t uptime = read_cntpct_el0(); + + va_start(argp, fmt); + + spin_lock(&qti_log_lock); + printf("QTISECLIB [%x%08x]", + (uint32_t) ((uptime >> 32) & 0xFFFFFFFF), + (uint32_t) (uptime & 0xFFFFFFFF)); + vprintf(fmt, argp); + putchar('\n'); + spin_unlock(&qti_log_lock); + + va_end(argp); + } +} + +void qtiseclib_cb_spin_lock(qtiseclib_cb_spinlock_t *lock) +{ + spin_lock((spinlock_t *) lock); +} + +void qtiseclib_cb_spin_unlock(qtiseclib_cb_spinlock_t *lock) +{ + spin_unlock((spinlock_t *) lock); +} + +unsigned int qtiseclib_cb_plat_my_core_pos(void) +{ + return plat_my_core_pos(); +} + +int qtiseclib_cb_plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return plat_core_pos_by_mpidr(mpidr); +} + +unsigned int qtiseclib_cb_plat_my_cluster_pos(void) +{ + return plat_qti_my_cluster_pos(); +} + +/* GIC platform functions */ +void qtiseclib_cb_gic_pcpu_init(void) +{ + plat_qti_gic_pcpu_init(); +} + +void qtiseclib_cb_ic_raise_sgi(int sgi_num, u_register_t target) +{ + plat_ic_raise_el3_sgi(sgi_num, target); +} + +void qtiseclib_cb_set_spi_routing(unsigned int id, unsigned int irm, + u_register_t target) +{ + assert(QTI_GICV3_IRM_PE == GICV3_IRM_PE); + assert(QTI_GICV3_IRM_ANY == GICV3_IRM_ANY); + gic_set_spi_routing(id, irm, target); +} + +/* Crash reporting api's wrappers */ +void qtiseclib_cb_switch_console_to_crash_state(void) +{ + console_switch_state(CONSOLE_FLAG_CRASH); +} + +void qtiseclib_cb_udelay(uint32_t usec) +{ + udelay(usec); +} + +void qtiseclib_cb_console_flush(void) +{ + return console_flush(); +} + +#if QTI_SDI_BUILD +void qtiseclib_cb_get_ns_ctx(qtiseclib_dbg_a64_ctxt_regs_type *qti_ns_ctx) +{ + void *ctx; + + ctx = cm_get_context(NON_SECURE); + if (ctx) { + /* nothing to be done w/o ns context */ + return; + } + + qti_ns_ctx->spsr_el3 = + read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3); + qti_ns_ctx->elr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_ELR_EL3); + + qti_ns_ctx->spsr_el1 = + read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SPSR_EL1); + qti_ns_ctx->elr_el1 = + read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_ELR_EL1); + qti_ns_ctx->sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SP_EL1); + + qti_ns_ctx->x0 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0); + qti_ns_ctx->x1 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1); + qti_ns_ctx->x2 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2); + qti_ns_ctx->x3 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3); + qti_ns_ctx->x4 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X4); + qti_ns_ctx->x5 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X5); + qti_ns_ctx->x6 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X6); + qti_ns_ctx->x7 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X7); + qti_ns_ctx->x8 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X8); + qti_ns_ctx->x9 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X9); + qti_ns_ctx->x10 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X10); + qti_ns_ctx->x11 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X11); + qti_ns_ctx->x12 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X12); + qti_ns_ctx->x13 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X13); + qti_ns_ctx->x14 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X14); + qti_ns_ctx->x15 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X15); + qti_ns_ctx->x16 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X16); + qti_ns_ctx->x17 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X17); + qti_ns_ctx->x18 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X18); + qti_ns_ctx->x19 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X19); + qti_ns_ctx->x20 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X20); + qti_ns_ctx->x21 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X21); + qti_ns_ctx->x22 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X22); + qti_ns_ctx->x23 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X23); + qti_ns_ctx->x24 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X24); + qti_ns_ctx->x25 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X25); + qti_ns_ctx->x26 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X26); + qti_ns_ctx->x27 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X27); + qti_ns_ctx->x28 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X28); + qti_ns_ctx->x29 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X29); + qti_ns_ctx->x30 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_LR); + qti_ns_ctx->sp_el0 = + read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_SP_EL0); +} + +void qtiseclib_cb_flush_dcache_all(void) +{ + dcsw_op_all(DCCISW); +} + +int qtiseclib_cb_mmap_add_dynamic_region(unsigned long long base_pa, + size_t size, + qtiseclib_mmap_attr_t attr) +{ + unsigned int l_attr = 0; + + if (attr == QTISECLIB_MAP_NS_RO_XN_DATA) { + l_attr = MT_NS | MT_RO | MT_EXECUTE_NEVER; + } else if (attr == QTISECLIB_MAP_RW_XN_NC_DATA) { + l_attr = MT_RW | MT_NON_CACHEABLE | MT_EXECUTE_NEVER; + } else if (attr == QTISECLIB_MAP_RW_XN_DATA) { + l_attr = MT_RW | MT_EXECUTE_NEVER; + } + return qti_mmap_add_dynamic_region(base_pa, size, l_attr); +} + +int qtiseclib_cb_mmap_remove_dynamic_region(uintptr_t base_va, size_t size) +{ + return qti_mmap_remove_dynamic_region(base_va, size); +} +#endif + diff --git a/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c b/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c new file mode 100644 index 0000000..9c93d51 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +/* + * This file contains dummy implementation of QTISECLIB Published API's. + * which will be used to compile PLATFORM successfully when + * qtiseclib is not available + */ + +/* + * CPUSS common reset handler for all CPU wake up (both cold & warm boot). + * Executes on all core. This API assume serialization across CPU + * already taken care before invoking. + * + * Clobbers: x0 - x17, x30 + */ +void qtiseclib_cpuss_reset_asm(uint32_t bl31_cold_boot_state) +{ +} + +/* + * Execute CPU (Kryo4 gold) specific reset handler / system initialization. + * This takes care of executing required CPU errata's. + * + * Clobbers: x0 - x16 + */ +void qtiseclib_kryo4_gold_reset_asm(void) +{ +} + +/* + * Execute CPU (Kryo4 silver) specific reset handler / system initialization. + * This takes care of executing required CPU errata's. + * + * Clobbers: x0 - x16 + */ +void qtiseclib_kryo4_silver_reset_asm(void) +{ +} + +/* + * C Api's + */ +void qtiseclib_bl31_platform_setup(void) +{ + ERROR("Please use QTISECLIB_PATH while building TF-A\n"); + ERROR("Please refer docs/plat/qti.rst for more details.\n"); + panic(); +} + +void qtiseclib_invoke_isr(uint32_t irq, void *handle) +{ +} + +void qtiseclib_panic(void) +{ +} + +int +qtiseclib_mem_assign(const memprot_info_t *mem_info, + uint32_t mem_info_list_cnt, + const uint32_t *source_vm_list, + uint32_t src_vm_list_cnt, + const memprot_dst_vm_perm_info_t *dest_vm_list, + uint32_t dst_vm_list_cnt) +{ + return 0; +} + +int qtiseclib_psci_init(uintptr_t warmboot_entry) +{ + return 0; +} + +int qtiseclib_psci_node_power_on(u_register_t mpidr) +{ + return 0; +} + +void qtiseclib_psci_node_on_finish(const uint8_t *states) +{ +} + +void qtiseclib_psci_cpu_standby(uint8_t pwr_state) +{ +} + +void qtiseclib_psci_node_power_off(const uint8_t *states) +{ +} + +void qtiseclib_psci_node_suspend(const uint8_t *states) +{ +} + +void qtiseclib_psci_node_suspend_finish(const uint8_t *states) +{ +} + +void qtiseclib_disable_cluster_coherency(uint8_t state) +{ +} + diff --git a/arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h b/arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h new file mode 100644 index 0000000..e3dc811 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +/* Enable the dynamic translation tables library. */ +#define PLAT_XLAT_TABLES_DYNAMIC 1 + +#include + +#include +#include + +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* + * MPIDR_PRIMARY_CPU + * You just need to have the correct core_affinity_val i.e. [7:0] + * and cluster_affinity_val i.e. [15:8] + * the other bits will be ignored + */ +/*----------------------------------------------------------------------------*/ +#define MPIDR_PRIMARY_CPU 0x0000 +/*----------------------------------------------------------------------------*/ + +#define QTI_PWR_LVL0 MPIDR_AFFLVL0 +#define QTI_PWR_LVL1 MPIDR_AFFLVL1 +#define QTI_PWR_LVL2 MPIDR_AFFLVL2 +#define QTI_PWR_LVL3 MPIDR_AFFLVL3 + +/* + * Macros for local power states encoded by State-ID field + * within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define QTI_LOCAL_STATE_RUN 0 +/* + * Local power state for clock-gating. Valid only for CPU and not cluster power + * domains + */ +#define QTI_LOCAL_STATE_STB 1 +/* + * Local power state for retention. Valid for CPU and cluster power + * domains + */ +#define QTI_LOCAL_STATE_RET 2 +/* + * Local power state for OFF/power down. Valid for CPU, cluster, RSC and PDC + * power domains + */ +#define QTI_LOCAL_STATE_OFF 3 +/* + * Local power state for DEEPOFF/power rail down. Valid for CPU, cluster and RSC + * power domains + */ +#define QTI_LOCAL_STATE_DEEPOFF 4 + +/* + * 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 QTI_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 QTI_LOCAL_STATE_DEEPOFF + +/****************************************************************************** + * Required platform porting definitions common to all ARM standard platforms + *****************************************************************************/ + +/* + * Platform specific page table and MMU setup constants. + */ +#define MAX_MMAP_REGIONS (PLAT_QTI_MMAP_ENTRIES) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 36) + +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * 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 (1 << ARM_CACHE_WRITEBACK_SHIFT) + +/* + * One cache line needed for bakery locks on ARM platforms + */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +/*----------------------------------------------------------------------------*/ +/* PSCI power domain topology definitions */ +/*----------------------------------------------------------------------------*/ +/* One domain each to represent RSC and PDC level */ +#define PLAT_PDC_COUNT 1 +#define PLAT_RSC_COUNT 1 + +/* There is one top-level FCM cluster */ +#define PLAT_CLUSTER_COUNT 1 + +/* No. of cores in the FCM cluster */ +#define PLAT_CLUSTER0_CORE_COUNT 8 + +#define PLATFORM_CORE_COUNT (PLAT_CLUSTER0_CORE_COUNT) + +#define PLAT_NUM_PWR_DOMAINS (PLAT_PDC_COUNT +\ + PLAT_RSC_COUNT +\ + PLAT_CLUSTER_COUNT +\ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_PWR_LVL 3 + +/*****************************************************************************/ +/* Memory mapped Generic timer interfaces */ +/*****************************************************************************/ + +/*----------------------------------------------------------------------------*/ +/* GIC-600 constants */ +/*----------------------------------------------------------------------------*/ +#define BASE_GICD_BASE 0x17A00000 +#define BASE_GICR_BASE 0x17A60000 +#define BASE_GICC_BASE 0x0 +#define BASE_GICH_BASE 0x0 +#define BASE_GICV_BASE 0x0 + +#define QTI_GICD_BASE BASE_GICD_BASE +#define QTI_GICR_BASE BASE_GICR_BASE +#define QTI_GICC_BASE BASE_GICC_BASE + +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* UART related constants. */ +/*----------------------------------------------------------------------------*/ +/* BASE ADDRESS OF DIFFERENT REGISTER SPACES IN HW */ +#define GENI4_CFG 0x0 +#define GENI4_IMAGE_REGS 0x100 +#define GENI4_DATA 0x600 + +/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */ +#define GENI_STATUS_REG (GENI4_CFG + 0x00000040) +#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK (0x1) +#define UART_TX_TRANS_LEN_REG (GENI4_IMAGE_REGS + 0x00000170) +/* MASTER/TX ENGINE REGISTERS */ +#define GENI_M_CMD0_REG (GENI4_DATA + 0x00000000) +/* FIFO, STATUS REGISTERS AND MASKS */ +#define GENI_TX_FIFOn_REG (GENI4_DATA + 0x00000100) + +#define GENI_M_CMD_TX (0x08000000) + +/*----------------------------------------------------------------------------*/ +/* Device address space for mapping. Excluding starting 4K */ +/*----------------------------------------------------------------------------*/ +#define QTI_DEVICE_BASE 0x1000 +#define QTI_DEVICE_SIZE (0x80000000 - QTI_DEVICE_BASE) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at DDR as per memory map. BL31_BASE is calculated using the + * current BL31 debug size plus a little space for growth. + */ +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +/*----------------------------------------------------------------------------*/ +/* AOSS registers */ +/*----------------------------------------------------------------------------*/ +#define QTI_PS_HOLD_REG 0x0C264000 +/*----------------------------------------------------------------------------*/ +/* AOP CMD DB address space for mapping */ +/*----------------------------------------------------------------------------*/ +#define QTI_AOP_CMD_DB_BASE 0x80820000 +#define QTI_AOP_CMD_DB_SIZE 0x00020000 +/*----------------------------------------------------------------------------*/ +/* SOC hw version register */ +/*----------------------------------------------------------------------------*/ +#define QTI_SOC_VERSION U(0x7180) +#define QTI_SOC_VERSION_MASK U(0xFFFF) +#define QTI_SOC_REVISION_REG 0x1FC8000 +#define QTI_SOC_REVISION_MASK U(0xFFFF) +/*----------------------------------------------------------------------------*/ +/* LC PON register offsets */ +/*----------------------------------------------------------------------------*/ +#define PON_PS_HOLD_RESET_CTL 0x85a +#define PON_PS_HOLD_RESET_CTL2 0x85b +/*----------------------------------------------------------------------------*/ + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h b/arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h new file mode 100644 index 0000000..f50234f --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef QTI_RNG_IO_H +#define QTI_RNG_IO_H + +#define SEC_PRNG_STATUS 0x00791004 +#define SEC_PRNG_STATUS_DATA_AVAIL_BMSK 0x1 +#define SEC_PRNG_DATA_OUT 0x00791000 + + +#endif /* QTI_RNG_IO_H */ + diff --git a/arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h b/arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h new file mode 100644 index 0000000..3de636d --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef QTI_SECURE_IO_CFG_H +#define QTI_SECURE_IO_CFG_H + +#include + +/* + * List of peripheral/IO memory areas that are protected from + * non-secure world but not required to be secure. + */ + +#define APPS_SMMU_TBU_PWR_STATUS 0x15002204 +#define APPS_SMMU_CUSTOM_CFG 0x15002300 +#define APPS_SMMU_STATS_SYNC_INV_TBU_ACK 0x150025DC +#define APPS_SMMU_SAFE_SEC_CFG 0x15002648 +#define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x15002670 + +static const uintptr_t qti_secure_io_allowed_regs[] = { + APPS_SMMU_TBU_PWR_STATUS, + APPS_SMMU_CUSTOM_CFG, + APPS_SMMU_STATS_SYNC_INV_TBU_ACK, + APPS_SMMU_SAFE_SEC_CFG, + APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR, +}; + +#endif /* QTI_SECURE_IO_CFG_H */ diff --git a/arm-trusted-firmware/plat/qti/sc7180/platform.mk b/arm-trusted-firmware/plat/qti/sc7180/platform.mk new file mode 100644 index 0000000..141e2c3 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7180/platform.mk @@ -0,0 +1,119 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Make for SC7180 QTI platform. + +QTI_PLAT_PATH := plat/qti +CHIPSET := ${PLAT} + +# Turn On Separate code & data. +SEPARATE_CODE_AND_RODATA := 1 +USE_COHERENT_MEM := 1 +WARMBOOT_ENABLE_DCACHE_EARLY := 1 + +# Disable the PSCI platform compatibility layer +ENABLE_PLAT_COMPAT := 0 + +# Enable PSCI v1.0 extended state ID format +PSCI_EXTENDED_STATE_ID := 1 +ARM_RECOM_STATE_ID_ENC := 1 + +COLD_BOOT_SINGLE_CPU := 1 +PROGRAMMABLE_RESET_ADDRESS := 1 + +RESET_TO_BL31 := 0 + +MULTI_CONSOLE_API := 1 + +QTI_SDI_BUILD := 0 +$(eval $(call assert_boolean,QTI_SDI_BUILD)) +$(eval $(call add_define,QTI_SDI_BUILD)) + +#disable CTX_INCLUDE_AARCH32_REGS to support sc7180 gold cores +override CTX_INCLUDE_AARCH32_REGS := 0 +WORKAROUND_CVE_2017_5715 := 0 +DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 +# Enable stack protector. +ENABLE_STACK_PROTECTOR := strong + + +QTI_EXTERNAL_INCLUDES := -I${QTI_PLAT_PATH}/${CHIPSET}/inc \ + -I${QTI_PLAT_PATH}/common/inc \ + -I${QTI_PLAT_PATH}/common/inc/$(ARCH) \ + -I${QTI_PLAT_PATH}/qtiseclib/inc \ + -I${QTI_PLAT_PATH}/qtiseclib/inc/${CHIPSET} \ + +QTI_BL31_SOURCES := $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_helpers.S \ + $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo4_silver.S \ + $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo4_gold.S \ + $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_uart_console.S \ + $(QTI_PLAT_PATH)/common/src/pm_ps_hold.c \ + $(QTI_PLAT_PATH)/common/src/qti_stack_protector.c \ + $(QTI_PLAT_PATH)/common/src/qti_common.c \ + $(QTI_PLAT_PATH)/common/src/qti_bl31_setup.c \ + $(QTI_PLAT_PATH)/common/src/qti_gic_v3.c \ + $(QTI_PLAT_PATH)/common/src/qti_interrupt_svc.c \ + $(QTI_PLAT_PATH)/common/src/qti_syscall.c \ + $(QTI_PLAT_PATH)/common/src/qti_topology.c \ + $(QTI_PLAT_PATH)/common/src/qti_pm.c \ + $(QTI_PLAT_PATH)/common/src/qti_rng.c \ + $(QTI_PLAT_PATH)/common/src/spmi_arb.c \ + $(QTI_PLAT_PATH)/qtiseclib/src/qtiseclib_cb_interface.c \ + + +PLAT_INCLUDES := -Iinclude/plat/common/ \ + +PLAT_INCLUDES += ${QTI_EXTERNAL_INCLUDES} + +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} \ + plat/common/aarch64/crash_console_helpers.S \ + common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + +include lib/coreboot/coreboot.mk + +#PSCI Sources. +PSCI_SOURCES := plat/common/plat_psci_common.c \ + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +#Timer sources +TIMER_SOURCES := drivers/delay_timer/generic_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + +#GIC sources. +GIC_SOURCES := plat/common/plat_gicv3.c \ + ${GICV3_SOURCES} \ + +BL31_SOURCES += ${QTI_BL31_SOURCES} \ + ${PSCI_SOURCES} \ + ${GIC_SOURCES} \ + ${TIMER_SOURCES} \ + +LIB_QTI_PATH := ${QTI_PLAT_PATH}/qtiseclib/lib/${CHIPSET} + + +# Override this on the command line to point to the qtiseclib library which +# will be available in coreboot.org +QTISECLIB_PATH ?= + +ifeq ($(QTISECLIB_PATH),) +# if No lib then use stub implementation for qtiseclib interface +$(warning QTISECLIB_PATH is not provided while building, using stub implementation. \ + Please refer docs/plat/qti.rst for more details \ + THIS FIRMWARE WILL NOT BOOT!) +BL31_SOURCES += plat/qti/qtiseclib/src/qtiseclib_interface_stub.c +else +# use library provided by QTISECLIB_PATH +LDFLAGS += -L $(dir $(QTISECLIB_PATH)) +LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(QTISECLIB_PATH))) +endif + diff --git a/arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h b/arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h new file mode 100644 index 0000000..da7eddc --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +/* Enable the dynamic translation tables library. */ +#define PLAT_XLAT_TABLES_DYNAMIC 1 + +#include + +#include +#include + +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* + * MPIDR_PRIMARY_CPU + * You just need to have the correct core_affinity_val i.e. [7:0] + * and cluster_affinity_val i.e. [15:8] + * the other bits will be ignored + */ +/*----------------------------------------------------------------------------*/ +#define MPIDR_PRIMARY_CPU 0x0000 +/*----------------------------------------------------------------------------*/ + +#define QTI_PWR_LVL0 MPIDR_AFFLVL0 +#define QTI_PWR_LVL1 MPIDR_AFFLVL1 +#define QTI_PWR_LVL2 MPIDR_AFFLVL2 +#define QTI_PWR_LVL3 MPIDR_AFFLVL3 + +/* + * Macros for local power states encoded by State-ID field + * within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define QTI_LOCAL_STATE_RUN 0 +/* + * Local power state for clock-gating. Valid only for CPU and not cluster power + * domains + */ +#define QTI_LOCAL_STATE_STB 1 +/* + * Local power state for retention. Valid for CPU and cluster power + * domains + */ +#define QTI_LOCAL_STATE_RET 2 +/* + * Local power state for OFF/power down. Valid for CPU, cluster, RSC and PDC + * power domains + */ +#define QTI_LOCAL_STATE_OFF 3 +/* + * Local power state for DEEPOFF/power rail down. Valid for CPU, cluster and RSC + * power domains + */ +#define QTI_LOCAL_STATE_DEEPOFF 4 + +/* + * 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 QTI_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 QTI_LOCAL_STATE_DEEPOFF + +/****************************************************************************** + * Required platform porting definitions common to all ARM standard platforms + *****************************************************************************/ + +/* + * Platform specific page table and MMU setup constants. + */ +#define MAX_MMAP_REGIONS (PLAT_QTI_MMAP_ENTRIES) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 36) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 36) + +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * 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 (1 << ARM_CACHE_WRITEBACK_SHIFT) + +/* + * One cache line needed for bakery locks on ARM platforms + */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +/*----------------------------------------------------------------------------*/ +/* PSCI power domain topology definitions */ +/*----------------------------------------------------------------------------*/ +/* One domain each to represent RSC and PDC level */ +#define PLAT_PDC_COUNT 1 +#define PLAT_RSC_COUNT 1 + +/* There is one top-level FCM cluster */ +#define PLAT_CLUSTER_COUNT 1 + +/* No. of cores in the FCM cluster */ +#define PLAT_CLUSTER0_CORE_COUNT 8 + +#define PLATFORM_CORE_COUNT (PLAT_CLUSTER0_CORE_COUNT) + +#define PLAT_NUM_PWR_DOMAINS (PLAT_PDC_COUNT +\ + PLAT_RSC_COUNT +\ + PLAT_CLUSTER_COUNT +\ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_PWR_LVL 3 + +/*****************************************************************************/ +/* Memory mapped Generic timer interfaces */ +/*****************************************************************************/ + +/*----------------------------------------------------------------------------*/ +/* GIC-600 constants */ +/*----------------------------------------------------------------------------*/ +#define BASE_GICD_BASE 0x17A00000 +#define BASE_GICR_BASE 0x17A60000 +#define BASE_GICC_BASE 0x0 +#define BASE_GICH_BASE 0x0 +#define BASE_GICV_BASE 0x0 + +#define QTI_GICD_BASE BASE_GICD_BASE +#define QTI_GICR_BASE BASE_GICR_BASE +#define QTI_GICC_BASE BASE_GICC_BASE + +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* UART related constants. */ +/*----------------------------------------------------------------------------*/ +/* BASE ADDRESS OF DIFFERENT REGISTER SPACES IN HW */ +#define GENI4_CFG 0x0 +#define GENI4_IMAGE_REGS 0x100 +#define GENI4_DATA 0x600 + +/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */ +#define GENI_STATUS_REG (GENI4_CFG + 0x00000040) +#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK (0x1) +#define UART_TX_TRANS_LEN_REG (GENI4_IMAGE_REGS + 0x00000170) +/* MASTER/TX ENGINE REGISTERS */ +#define GENI_M_CMD0_REG (GENI4_DATA + 0x00000000) +/* FIFO, STATUS REGISTERS AND MASKS */ +#define GENI_TX_FIFOn_REG (GENI4_DATA + 0x00000100) + +#define GENI_M_CMD_TX (0x08000000) + +/*----------------------------------------------------------------------------*/ +/* Device address space for mapping. Excluding starting 4K */ +/*----------------------------------------------------------------------------*/ +#define QTI_DEVICE_BASE 0x1000 +#define QTI_DEVICE_SIZE (0x80000000 - QTI_DEVICE_BASE) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at DDR as per memory map. BL31_BASE is calculated using the + * current BL31 debug size plus a little space for growth. + */ +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +/*----------------------------------------------------------------------------*/ +/* AOSS registers */ +/*----------------------------------------------------------------------------*/ +#define QTI_PS_HOLD_REG 0x0C264000 +/*----------------------------------------------------------------------------*/ +/* AOP CMD DB address space for mapping */ +/*----------------------------------------------------------------------------*/ +#define QTI_AOP_CMD_DB_BASE 0x80860000 +#define QTI_AOP_CMD_DB_SIZE 0x00020000 +/*----------------------------------------------------------------------------*/ +/* SOC hw version register */ +/*----------------------------------------------------------------------------*/ +#define QTI_SOC_VERSION U(0x7280) +#define QTI_SOC_VERSION_MASK U(0xFFFF) +#define QTI_SOC_REVISION_REG 0x1FC8000 +#define QTI_SOC_REVISION_MASK U(0xFFFF) +/*----------------------------------------------------------------------------*/ +/* LC PON register offsets */ +/*----------------------------------------------------------------------------*/ +#define PON_PS_HOLD_RESET_CTL 0x852 +#define PON_PS_HOLD_RESET_CTL2 0x853 +/*----------------------------------------------------------------------------*/ + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h b/arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h new file mode 100644 index 0000000..0f41fd6 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef QTI_RNG_IO_H +#define QTI_RNG_IO_H + +#define SEC_PRNG_STATUS 0x10D1004 +#define SEC_PRNG_STATUS_DATA_AVAIL_BMSK 0x1 +#define SEC_PRNG_DATA_OUT 0x10D1000 + + +#endif /* QTI_RNG_IO_H */ + diff --git a/arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h b/arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h new file mode 100644 index 0000000..058c5b5 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef QTI_SECURE_IO_CFG_H +#define QTI_SECURE_IO_CFG_H + +#include + +/* + * List of peripheral/IO memory areas that are protected from + * non-secure world but not required to be secure. + */ + +#define APPS_SMMU_TBU_PWR_STATUS 0x15002204 +#define APPS_SMMU_CUSTOM_CFG 0x15002300 +#define APPS_SMMU_STATS_SYNC_INV_TBU_ACK 0x150025DC +#define APPS_SMMU_SAFE_SEC_CFG 0x15002648 +#define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x15002670 + +static const uintptr_t qti_secure_io_allowed_regs[] = { + APPS_SMMU_TBU_PWR_STATUS, + APPS_SMMU_CUSTOM_CFG, + APPS_SMMU_STATS_SYNC_INV_TBU_ACK, + APPS_SMMU_SAFE_SEC_CFG, + APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR, +}; + +#endif /* QTI_SECURE_IO_CFG_H */ diff --git a/arm-trusted-firmware/plat/qti/sc7280/platform.mk b/arm-trusted-firmware/plat/qti/sc7280/platform.mk new file mode 100644 index 0000000..bc2c221 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7280/platform.mk @@ -0,0 +1,119 @@ +# +# Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Make for SC7280 QTI platform. + +QTI_PLAT_PATH := plat/qti +CHIPSET := ${PLAT} + +# Turn On Separate code & data. +SEPARATE_CODE_AND_RODATA := 1 +USE_COHERENT_MEM := 1 +WARMBOOT_ENABLE_DCACHE_EARLY := 1 + +# Disable the PSCI platform compatibility layer +ENABLE_PLAT_COMPAT := 0 + +# Enable PSCI v1.0 extended state ID format +PSCI_EXTENDED_STATE_ID := 1 +ARM_RECOM_STATE_ID_ENC := 1 + +COLD_BOOT_SINGLE_CPU := 1 +PROGRAMMABLE_RESET_ADDRESS := 1 + +RESET_TO_BL31 := 0 + +MULTI_CONSOLE_API := 1 + +QTI_SDI_BUILD := 0 +$(eval $(call assert_boolean,QTI_SDI_BUILD)) +$(eval $(call add_define,QTI_SDI_BUILD)) + +#disable CTX_INCLUDE_AARCH32_REGS to support sc7280 gold cores +override CTX_INCLUDE_AARCH32_REGS := 0 +WORKAROUND_CVE_2017_5715 := 0 +DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 +# Enable stack protector. +ENABLE_STACK_PROTECTOR := strong + + +QTI_EXTERNAL_INCLUDES := -I${QTI_PLAT_PATH}/${CHIPSET}/inc \ + -I${QTI_PLAT_PATH}/common/inc \ + -I${QTI_PLAT_PATH}/common/inc/$(ARCH) \ + -I${QTI_PLAT_PATH}/qtiseclib/inc \ + -I${QTI_PLAT_PATH}/qtiseclib/inc/${CHIPSET} \ + +QTI_BL31_SOURCES := $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_helpers.S \ + $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo6_silver.S \ + $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo6_gold.S \ + $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_uart_console.S \ + $(QTI_PLAT_PATH)/common/src/pm_ps_hold.c \ + $(QTI_PLAT_PATH)/common/src/qti_stack_protector.c \ + $(QTI_PLAT_PATH)/common/src/qti_common.c \ + $(QTI_PLAT_PATH)/common/src/qti_bl31_setup.c \ + $(QTI_PLAT_PATH)/common/src/qti_gic_v3.c \ + $(QTI_PLAT_PATH)/common/src/qti_interrupt_svc.c \ + $(QTI_PLAT_PATH)/common/src/qti_syscall.c \ + $(QTI_PLAT_PATH)/common/src/qti_topology.c \ + $(QTI_PLAT_PATH)/common/src/qti_pm.c \ + $(QTI_PLAT_PATH)/common/src/qti_rng.c \ + $(QTI_PLAT_PATH)/common/src/spmi_arb.c \ + $(QTI_PLAT_PATH)/qtiseclib/src/qtiseclib_cb_interface.c \ + + +PLAT_INCLUDES := -Iinclude/plat/common/ \ + +PLAT_INCLUDES += ${QTI_EXTERNAL_INCLUDES} + +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} \ + plat/common/aarch64/crash_console_helpers.S \ + common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + +include lib/coreboot/coreboot.mk + +#PSCI Sources. +PSCI_SOURCES := plat/common/plat_psci_common.c \ + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +#Timer sources +TIMER_SOURCES := drivers/delay_timer/generic_delay_timer.c \ + drivers/delay_timer/delay_timer.c \ + +#GIC sources. +GIC_SOURCES := plat/common/plat_gicv3.c \ + ${GICV3_SOURCES} \ + +BL31_SOURCES += ${QTI_BL31_SOURCES} \ + ${PSCI_SOURCES} \ + ${GIC_SOURCES} \ + ${TIMER_SOURCES} \ + +LIB_QTI_PATH := ${QTI_PLAT_PATH}/qtiseclib/lib/${CHIPSET} + + +# Override this on the command line to point to the qtiseclib library which +# will be available in coreboot.org +QTISECLIB_PATH ?= + +ifeq ($(QTISECLIB_PATH),) +# if No lib then use stub implementation for qtiseclib interface +$(warning QTISECLIB_PATH is not provided while building, using stub implementation. \ + Please refer docs/plat/qti.rst for more details \ + THIS FIRMWARE WILL NOT BOOT!) +BL31_SOURCES += plat/qti/qtiseclib/src/qtiseclib_interface_stub.c +else +# use library provided by QTISECLIB_PATH +LDFLAGS += -L $(dir $(QTISECLIB_PATH)) +LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(QTISECLIB_PATH))) +endif + diff --git a/arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..21c3bed --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "rcar_def.h" + + .globl plat_get_my_entrypoint + .extern plat_set_my_stack + .globl platform_mem_init + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_invalidate_icache + .globl plat_report_exception + .globl plat_secondary_reset + .globl plat_reset_handler + .globl plat_my_core_pos + .extern rcar_log_init + + .extern console_rcar_init + .extern console_rcar_putc + .extern console_rcar_flush + +#if IMAGE_BL2 + #define INT_ID_MASK (0x3ff) + .extern bl2_interrupt_error_type + .extern bl2_interrupt_error_id + .globl bl2_enter_bl31 + .extern gicv2_acknowledge_interrupt + .extern rcar_swdt_exec +#endif + + /* ----------------------------------------------------- + * void platform_get_core_pos (mpidr) + * ----------------------------------------------------- + */ +func platform_get_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc platform_get_core_pos + + /* ----------------------------------------------------- + * void platform_my_core_pos + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b platform_get_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * void platform_get_my_entrypoint (unsigned int mpid); + * + * Main job of this routine is to distinguish between + * a cold and warm boot. + * On a cold boot the secondaries first wait for the + * platform to be initialized after which they are + * hotplugged in. The primary proceeds to perform the + * platform initialization. + * On a warm boot, each cpu jumps to the address in its + * mailbox. + * + * TODO: Not a good idea to save lr in a temp reg + * ----------------------------------------------------- + */ +func plat_get_my_entrypoint + mrs x0, mpidr_el1 + mov x9, x30 /* lr */ + +#if defined(IMAGE_BL2) + /* always cold boot on bl2 */ + mov x0, #0 + ret x9 +#else + ldr x1, =BOOT_KIND_BASE + ldr x21, [x1] + + /* Check the reset info */ + and x1, x21, #0x000c + cmp x1, #0x0008 + beq el3_panic + cmp x1, #0x000c + beq el3_panic + + /* Check the boot kind */ + and x1, x21, #0x0003 + cmp x1, #0x0002 + beq el3_panic + cmp x1, #0x0003 + beq el3_panic + + /* warm boot or cold boot */ + and x1, x21, #1 + cmp x1, #0 + bne warm_reset + + /* Cold boot */ + mov x0, #0 + b exit + +warm_reset: + /* -------------------------------------------------------------------- + * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out + * of the caches after every update using normal memory so its safe to + * read it here with SO attributes + * --------------------------------------------------------------------- + */ + ldr x10, =MBOX_BASE + bl platform_get_core_pos + lsl x0, x0, #CACHE_WRITEBACK_SHIFT + ldr x0, [x10, x0] + cbz x0, _panic +exit: + ret x9 +_panic: + b do_panic +#endif + +endfunc plat_get_my_entrypoint + + /* --------------------------------------------- + * plat_secondary_reset + * + * --------------------------------------------- + */ +func plat_secondary_reset + mrs x0, sctlr_el3 + bic x0, x0, #SCTLR_EE_BIT + msr sctlr_el3, x0 + isb + + mrs x0, cptr_el3 + bic w0, w0, #TCPAC_BIT + bic w0, w0, #TTA_BIT + bic w0, w0, #TFP_BIT + msr cptr_el3, x0 + + mov_imm x0, PARAMS_BASE + mov_imm x2, BL31_BASE + ldr x3, =BOOT_KIND_BASE + mov x1, #0x1 + str x1, [x3] + br x2 /* jump to BL31 */ + nop + nop + nop +endfunc plat_secondary_reset + + /* --------------------------------------------- + * plat_enter_bl31 + * + * --------------------------------------------- + */ +func bl2_enter_bl31 + 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. + */ +#if RCAR_BL2_DCACHE == 1 + /* Disable mmu and data cache */ + bl disable_mmu_el3 + /* Data cache clean and invalidate */ + mov x0, #DCCISW + bl dcsw_op_all + /* TLB invalidate all, EL3 */ + tlbi alle3 +#endif /* RCAR_BL2_DCACHE == 1 */ + bl disable_mmu_icache_el3 + /* Invalidate instruction cache */ + ic iallu + dsb sy + isb + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, x1 + exception_return +endfunc bl2_enter_bl31 + + /* ----------------------------------------------------- + * void platform_mem_init (void); + * + * Zero out the mailbox registers in the shared memory + * and set the rcar_boot_kind_flag. + * The mmu is turned off right now and only the primary can + * ever execute this code. Secondaries will read the + * mailboxes using SO accesses. + * ----------------------------------------------------- + */ +func platform_mem_init +#if !IMAGE_BL2 + ldr x0, =MBOX_BASE + mov w1, #PLATFORM_CORE_COUNT +loop: + str xzr, [x0], #CACHE_WRITEBACK_GRANULE + subs w1, w1, #1 + b.gt loop +#endif + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * --------------------------------------------- + */ +func plat_report_exception + /* Switch to SP_EL0 */ + msr spsel, #0 +#if IMAGE_BL2 + mov w1, #FIQ_SP_EL0 + cmp w0, w1 + beq rep_exec_fiq_elx + b rep_exec_panic_type +rep_exec_fiq_elx: + bl gicv2_acknowledge_interrupt + mov x2, #INT_ID_MASK + and x0, x0, x2 + mov x1, #ARM_IRQ_SEC_WDT + cmp x0, x1 + bne rep_exec_panic_id + mrs x0, ELR_EL3 + b rcar_swdt_exec +rep_exec_panic_type: + /* x0 is interrupt TYPE */ + b bl2_interrupt_error_type +rep_exec_panic_id: + /* x0 is interrupt ID */ + b bl2_interrupt_error_id +rep_exec_end: +#endif + ret +endfunc plat_report_exception + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize log area + * --------------------------------------------- + */ +func plat_crash_console_init +#if IMAGE_BL2 + mov x0, #0 +#else + mov x1, sp + mov_imm x2, RCAR_CRASH_STACK + mov sp, x2 + str x1, [sp, #-16]! + str x30, [sp, #-16]! + bl console_rcar_init + ldr x30, [sp], #16 + ldr x1, [sp], #16 + mov sp, x1 +#endif + ret +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to store a character to log area + * --------------------------------------------- + */ +func plat_crash_console_putc + mov x1, sp + mov_imm x2, RCAR_CRASH_STACK + mov sp, x2 + str x1, [sp, #-16]! + str x30, [sp, #-16]! + str x3, [sp, #-16]! + str x4, [sp, #-16]! + str x5, [sp, #-16]! + str x6, [sp, #-16]! + str x7, [sp, #-16]! + bl console_rcar_putc + ldr x7, [sp], #16 + ldr x6, [sp], #16 + ldr x5, [sp], #16 + ldr x4, [sp], #16 + ldr x3, [sp], #16 + ldr x30, [sp], #16 + ldr x1, [sp], #16 + mov sp, x1 + ret +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * --------------------------------------------- + */ +func plat_crash_console_flush + b console_rcar_flush +endfunc plat_crash_console_flush + + /* -------------------------------------------------------------------- + * void plat_reset_handler(void); + * + * Before adding code in this function, refer to the guidelines in + * docs/firmware-design.md to determine whether the code should reside + * within the FIRST_RESET_HANDLER_CALL block or not. + * + * For R-Car H3: + * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57 + * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57 + * For R-Car M3/M3N: + * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 + * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57 + * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57 + * + * -------------------------------------------------------------------- + */ +func plat_reset_handler + /* + * On R-Car H3 : x2 := 0 + * On R-Car M3/M3N: x2 := 1 + */ + /* read PRR */ + ldr x0, =0xFFF00044 + ldr w0, [x0] + ubfx w0, w0, 8, 8 + /* H3? */ + cmp w0, #0x4F + b.eq RCARH3 + /* set R-Car M3/M3N */ + mov x2, #1 + b CHK_A5x +RCARH3: + /* set R-Car H3 */ + mov x2, #0 + /* -------------------------------------------------------------------- + * Determine whether this code is executed on a Cortex-A53 or on a + * Cortex-A57 core. + * -------------------------------------------------------------------- + */ +CHK_A5x: + mrs x0, midr_el1 + ubfx x1, x0, MIDR_PN_SHIFT, #12 + cmp w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + b.eq A57 + ret +A57: + /* Get data from CORTEX_A57_L2CTLR_EL1 */ + mrs x0, CORTEX_A57_L2CTLR_EL1 + /* + * On R-Car H3/M3/M3N + * + * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1 + * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1 + * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1 + */ + /* clear bit of L2 RAM */ + /* ~(0x1e7) -> x1 */ + mov x1, #0x1e7 + neg x1, x1 + /* clear bit of L2 RAM -> x0 */ + and x0, x0, x1 + /* L2 Tag RAM latency (3 cycles) */ + orr x0, x0, #0x2 << 6 + /* If M3/M3N then L2 RAM setup is 0 */ + cbnz x2, M3_L2 + /* L2 Data RAM setup (1 cycle) */ + orr x0, x0, #0x1 << 5 +M3_L2: + /* L2 Data RAM latency (4 cycles) */ + orr x0, x0, #0x3 + /* Store data to L2CTLR_EL1 */ + msr CORTEX_A57_L2CTLR_EL1, x0 +apply_l2_ram_latencies: + ret +endfunc plat_reset_handler + + /* --------------------------------------------- + * void plat_invalidate_icache(void) + * Instruction Cache Invalidate All to PoU + * --------------------------------------------- + */ +func plat_invalidate_icache + ic iallu + + ret +endfunc plat_invalidate_icache diff --git a/arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c b/arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c new file mode 100644 index 0000000..b0a88cb --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_version.h" + +#if (IMAGE_BL2) +extern void rcar_read_certificate(uint64_t cert, uint32_t *len, uintptr_t *p); +extern int32_t rcar_get_certificate(const int32_t name, uint32_t *cert); +#endif + +const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN] + __attribute__ ((__section__("ro"))) = VERSION_OF_RENESAS; + +#define MAP_SHARED_RAM MAP_REGION_FLAT(RCAR_SHARED_MEM_BASE, \ + RCAR_SHARED_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_FLASH0 MAP_REGION_FLAT(FLASH0_BASE, \ + FLASH0_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define MAP_DRAM1_NS MAP_REGION_FLAT(DRAM1_NS_BASE, \ + DRAM1_NS_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_DEVICE_RCAR MAP_REGION_FLAT(DEVICE_RCAR_BASE, \ + DEVICE_RCAR_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DEVICE_RCAR2 MAP_REGION_FLAT(DEVICE_RCAR_BASE2, \ + DEVICE_RCAR_SIZE2, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SRAM MAP_REGION_FLAT(DEVICE_SRAM_BASE, \ + DEVICE_SRAM_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define MAP_SRAM_STACK MAP_REGION_FLAT(DEVICE_SRAM_STACK_BASE, \ + DEVICE_SRAM_STACK_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_ATFW_CRASH MAP_REGION_FLAT(RCAR_BL31_CRASH_BASE, \ + RCAR_BL31_CRASH_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_ATFW_LOG MAP_REGION_FLAT(RCAR_BL31_LOG_BASE, \ + RCAR_BL31_LOG_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#if IMAGE_BL2 +#define MAP_DRAM0 MAP_REGION_FLAT(DRAM1_BASE, \ + DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_REG0 MAP_REGION_FLAT(DEVICE_RCAR_BASE, \ + DEVICE_RCAR_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_RAM0 MAP_REGION_FLAT(RCAR_SYSRAM_BASE, \ + RCAR_SYSRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_REG1 MAP_REGION_FLAT(REG1_BASE, \ + REG1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_ROM MAP_REGION_FLAT(ROM0_BASE, \ + ROM0_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define MAP_REG2 MAP_REGION_FLAT(REG2_BASE, \ + REG2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DRAM1 MAP_REGION_FLAT(DRAM_40BIT_BASE, \ + DRAM_40BIT_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +#ifdef BL32_BASE +#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_BASE, \ + BL32_LIMIT - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +#if IMAGE_BL2 +static const mmap_region_t rcar_mmap[] = { + MAP_FLASH0, /* 0x08000000 - 0x0BFFFFFF RPC area */ + MAP_DRAM0, /* 0x40000000 - 0xBFFFFFFF DRAM area(Legacy) */ + MAP_REG0, /* 0xE6000000 - 0xE62FFFFF SoC register area */ + MAP_RAM0, /* 0xE6300000 - 0xE6303FFF System RAM area */ + MAP_REG1, /* 0xE6400000 - 0xEAFFFFFF SoC register area */ + MAP_ROM, /* 0xEB100000 - 0xEB127FFF boot ROM area */ + MAP_REG2, /* 0xEC000000 - 0xFFFFFFFF SoC register area */ + MAP_DRAM1, /* 0x0400000000 - 0x07FFFFFFFF DRAM area(4GB over) */ + {0} +}; +#endif + +#if IMAGE_BL31 +static const mmap_region_t rcar_mmap[] = { + MAP_SHARED_RAM, + MAP_ATFW_CRASH, + MAP_ATFW_LOG, + MAP_DEVICE_RCAR, + MAP_DEVICE_RCAR2, + MAP_SRAM, + MAP_SRAM_STACK, + {0} +}; +#endif + +#if IMAGE_BL32 +static const mmap_region_t rcar_mmap[] = { + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; +#endif + +CASSERT(ARRAY_SIZE(rcar_mmap) + RCAR_BL_REGIONS + <= MAX_MMAP_REGIONS, assert_max_mmap_regions); + +/* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + */ +#if USE_COHERENT_MEM +void rcar_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit) +{ + mmap_add_region(total_base, total_base, total_size, + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + MT_MEMORY | MT_RO | MT_SECURE); + mmap_add_region(coh_start, coh_start, coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); + mmap_add(rcar_mmap); + + init_xlat_tables(); + enable_mmu_el3(0); +} +#else +void rcar_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit) +{ + mmap_add_region(total_base, total_base, total_size, + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + MT_MEMORY | MT_RO | MT_SECURE); + mmap_add(rcar_mmap); + + init_xlat_tables(); + enable_mmu_el3(0); +} +#endif + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#if (IMAGE_BL2) + uint32_t cert, len; + uintptr_t dst; + int32_t ret; + + ret = rcar_get_certificate(NON_TRUSTED_FW_CONTENT_CERT_ID, &cert); + if (ret) { + ERROR("%s : cert file load error", __func__); + return NS_IMAGE_OFFSET; + } + + rcar_read_certificate((uint64_t) cert, &len, &dst); + + return dst; +#else + return NS_IMAGE_OFFSET; +#endif +} + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int freq; + + freq = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF); + if (freq == 0) + panic(); + + return freq; +} + +void plat_rcar_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static const interrupt_prop_t interrupt_props[] = { +#if IMAGE_BL2 + INTR_PROP_DESC(ARM_IRQ_SEC_WDT, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +#else + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(ARM_IRQ_SEC_RPC, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(ARM_IRQ_SEC_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(ARM_IRQ_SEC_TIMER_UP, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(ARM_IRQ_SEC_WDT, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(ARM_IRQ_SEC_CRYPT, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(ARM_IRQ_SEC_CRYPT_SecPKA, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(ARM_IRQ_SEC_CRYPT_PubPKA, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +#endif +}; + +static const gicv2_driver_data_t plat_gicv2_driver_data = { + .interrupt_props = interrupt_props, + .interrupt_props_num = (uint32_t) ARRAY_SIZE(interrupt_props), + .gicd_base = RCAR_GICD_BASE, + .gicc_base = RCAR_GICC_BASE, +}; + +void plat_rcar_gic_driver_init(void) +{ + gicv2_driver_init(&plat_gicv2_driver_data); +} diff --git a/arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c b/arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c new file mode 100644 index 0000000..a545f71 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" + +static void bl2_secure_cpg_init(void); + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) || \ + (RCAR_LSI == RCAR_H3N) || (RCAR_LSI == RZ_G2H) +static void bl2_realtime_cpg_init_h3(void); +static void bl2_system_cpg_init_h3(void); +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M) +static void bl2_realtime_cpg_init_m3(void); +static void bl2_system_cpg_init_m3(void); +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) || (RCAR_LSI == RZ_G2N) +static void bl2_realtime_cpg_init_m3n(void); +static void bl2_system_cpg_init_m3n(void); +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_V3M) +static void bl2_realtime_cpg_init_v3m(void); +static void bl2_system_cpg_init_v3m(void); +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E) +static void bl2_realtime_cpg_init_e3(void); +static void bl2_system_cpg_init_e3(void); +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_D3) +static void bl2_system_cpg_init_d3(void); +#endif + +typedef struct { + uintptr_t adr; + uint32_t val; +} reg_setting_t; + +static void bl2_secure_cpg_init(void) +{ + uint32_t stop_cr2, reset_cr2; + uint32_t stop_cr4, reset_cr4; + uint32_t stop_cr5, reset_cr5; + +#if (RCAR_LSI == RCAR_D3) + reset_cr2 = 0x00000000U; + stop_cr2 = 0xFFFFFFFFU; +#elif (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E) + reset_cr2 = 0x10000000U; + stop_cr2 = 0xEFFFFFFFU; +#else + reset_cr2 = 0x14000000U; + stop_cr2 = 0xEBFFFFFFU; +#endif + +#if (RCAR_LSI == RCAR_D3) + reset_cr4 = 0x00000000U; + stop_cr4 = 0xFFFFFFFFU; + reset_cr5 = 0x00000000U; + stop_cr5 = 0xFFFFFFFFU; +#else + reset_cr4 = 0x80000003U; + stop_cr4 = 0x7FFFFFFFU; + reset_cr5 = 0x40000000U; + stop_cr5 = 0xBFFFFFFFU; +#endif + + /* Secure Module Stop Control Registers */ + cpg_write(SCMSTPCR0, 0xFFFFFFFFU); + cpg_write(SCMSTPCR1, 0xFFFFFFFFU); + cpg_write(SCMSTPCR2, stop_cr2); + cpg_write(SCMSTPCR3, 0xFFFFFFFFU); + cpg_write(SCMSTPCR4, stop_cr4); + cpg_write(SCMSTPCR5, stop_cr5); + cpg_write(SCMSTPCR6, 0xFFFFFFFFU); + cpg_write(SCMSTPCR7, 0xFFFFFFFFU); + cpg_write(SCMSTPCR8, 0xFFFFFFFFU); + cpg_write(SCMSTPCR9, 0xFFFDFFFFU); + cpg_write(SCMSTPCR10, 0xFFFFFFFFU); + cpg_write(SCMSTPCR11, 0xFFFFFFFFU); + + /* Secure Software Reset Access Enable Control Registers */ + cpg_write(SCSRSTECR0, 0x00000000U); + cpg_write(SCSRSTECR1, 0x00000000U); + cpg_write(SCSRSTECR2, reset_cr2); + cpg_write(SCSRSTECR3, 0x00000000U); + cpg_write(SCSRSTECR4, reset_cr4); + cpg_write(SCSRSTECR5, reset_cr5); + cpg_write(SCSRSTECR6, 0x00000000U); + cpg_write(SCSRSTECR7, 0x00000000U); + cpg_write(SCSRSTECR8, 0x00000000U); + cpg_write(SCSRSTECR9, 0x00020000U); + cpg_write(SCSRSTECR10, 0x00000000U); + cpg_write(SCSRSTECR11, 0x00000000U); +} + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) || \ + (RCAR_LSI == RCAR_H3N) || (RCAR_LSI == RZ_G2H) +static void bl2_realtime_cpg_init_h3(void) +{ + uint32_t cut = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK; + uint32_t cr0, cr8; + + cr0 = (cut == PRR_PRODUCT_10 || cut == PRR_PRODUCT_11) ? + 0x00200000U : 0x00210000U; + cr8 = (cut == PRR_PRODUCT_10 || cut == PRR_PRODUCT_11) ? + 0x01F1FFF4U : 0x01F1FFF7U; + + cpg_write(RMSTPCR0, cr0); + cpg_write(RMSTPCR1, 0xFFFFFFFFU); + cpg_write(RMSTPCR2, 0x040E0FDCU); + cpg_write(RMSTPCR3, 0xFFFFFFDFU); + cpg_write(RMSTPCR4, 0x80000004U); + cpg_write(RMSTPCR5, 0xC3FFFFFFU); + cpg_write(RMSTPCR6, 0xFFFFFFFFU); + cpg_write(RMSTPCR7, 0xFFFFFFFFU); + cpg_write(RMSTPCR8, cr8); + cpg_write(RMSTPCR9, 0xFFFFFFFEU); + cpg_write(RMSTPCR10, 0xFFFEFFE0U); + cpg_write(RMSTPCR11, 0x000000B7U); +} + +static void bl2_system_cpg_init_h3(void) +{ + /** System Module Stop Control Registers */ + cpg_write(SMSTPCR0, 0x00210000U); + cpg_write(SMSTPCR1, 0xFFFFFFFFU); + cpg_write(SMSTPCR2, 0x040E2FDCU); + cpg_write(SMSTPCR3, 0xFFFFFBDFU); + cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4)); + cpg_write(SMSTPCR5, 0xC3FFFFFFU); + cpg_write(SMSTPCR6, 0xFFFFFFFFU); + cpg_write(SMSTPCR7, 0xFFFFFFFFU); + cpg_write(SMSTPCR8, 0x01F1FFF5U); + cpg_write(SMSTPCR9, 0xFFFFFFFFU); + cpg_write(SMSTPCR10, 0xFFFEFFE0U); + cpg_write(SMSTPCR11, 0x000000B7U); +} +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M) +static void bl2_realtime_cpg_init_m3(void) +{ + /* Realtime Module Stop Control Registers */ + cpg_write(RMSTPCR0, 0x00200000U); + cpg_write(RMSTPCR1, 0xFFFFFFFFU); + cpg_write(RMSTPCR2, 0x040E0FDCU); + cpg_write(RMSTPCR3, 0xFFFFFFDFU); + cpg_write(RMSTPCR4, 0x80000004U); + cpg_write(RMSTPCR5, 0xC3FFFFFFU); + cpg_write(RMSTPCR6, 0xFFFFFFFFU); + cpg_write(RMSTPCR7, 0xFFFFFFFFU); + cpg_write(RMSTPCR8, 0x01F1FFF7U); + cpg_write(RMSTPCR9, 0xFFFFFFFEU); + cpg_write(RMSTPCR10, 0xFFFEFFE0U); + cpg_write(RMSTPCR11, 0x000000B7U); +} + +static void bl2_system_cpg_init_m3(void) +{ + /* System Module Stop Control Registers */ + cpg_write(SMSTPCR0, 0x00200000U); + cpg_write(SMSTPCR1, 0xFFFFFFFFU); + cpg_write(SMSTPCR2, 0x040E2FDCU); + cpg_write(SMSTPCR3, 0xFFFFFBDFU); + cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4)); + cpg_write(SMSTPCR5, 0xC3FFFFFFU); + cpg_write(SMSTPCR6, 0xFFFFFFFFU); + cpg_write(SMSTPCR7, 0xFFFFFFFFU); + cpg_write(SMSTPCR8, 0x01F1FFF7U); + cpg_write(SMSTPCR9, 0xFFFFFFFFU); + cpg_write(SMSTPCR10, 0xFFFEFFE0U); + cpg_write(SMSTPCR11, 0x000000B7U); +} +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) || (RCAR_LSI == RZ_G2N) +static void bl2_realtime_cpg_init_m3n(void) +{ + /* Realtime Module Stop Control Registers */ + cpg_write(RMSTPCR0, 0x00210000U); + cpg_write(RMSTPCR1, 0xFFFFFFFFU); + cpg_write(RMSTPCR2, 0x040E0FDCU); + cpg_write(RMSTPCR3, 0xFFFFFFDFU); + cpg_write(RMSTPCR4, 0x80000004U); + cpg_write(RMSTPCR5, 0xC3FFFFFFU); + cpg_write(RMSTPCR6, 0xFFFFFFFFU); + cpg_write(RMSTPCR7, 0xFFFFFFFFU); + cpg_write(RMSTPCR8, 0x00F1FFF7U); + cpg_write(RMSTPCR9, 0xFFFFFFFFU); + cpg_write(RMSTPCR10, 0xFFFFFFE0U); + cpg_write(RMSTPCR11, 0x000000B7U); +} + +static void bl2_system_cpg_init_m3n(void) +{ + /* System Module Stop Control Registers */ + cpg_write(SMSTPCR0, 0x00210000U); + cpg_write(SMSTPCR1, 0xFFFFFFFFU); + cpg_write(SMSTPCR2, 0x040E2FDCU); + cpg_write(SMSTPCR3, 0xFFFFFBDFU); + cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4)); + cpg_write(SMSTPCR5, 0xC3FFFFFFU); + cpg_write(SMSTPCR6, 0xFFFFFFFFU); + cpg_write(SMSTPCR7, 0xFFFFFFFFU); + cpg_write(SMSTPCR8, 0x00F1FFF7U); + cpg_write(SMSTPCR9, 0xFFFFFFFFU); + cpg_write(SMSTPCR10, 0xFFFFFFE0U); + cpg_write(SMSTPCR11, 0x000000B7U); +} +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_V3M) +static void bl2_realtime_cpg_init_v3m(void) +{ + /* Realtime Module Stop Control Registers */ + cpg_write(RMSTPCR0, 0x00230000U); + cpg_write(RMSTPCR1, 0xFFFFFFFFU); + cpg_write(RMSTPCR2, 0x14062FD8U); + cpg_write(RMSTPCR3, 0xFFFFFFDFU); + cpg_write(RMSTPCR4, 0x80000184U); + cpg_write(RMSTPCR5, 0x83FFFFFFU); + cpg_write(RMSTPCR6, 0xFFFFFFFFU); + cpg_write(RMSTPCR7, 0xFFFFFFFFU); + cpg_write(RMSTPCR8, 0x7FF3FFF4U); + cpg_write(RMSTPCR9, 0xFFFFFFFEU); +} + +static void bl2_system_cpg_init_v3m(void) +{ + /* System Module Stop Control Registers */ + cpg_write(SMSTPCR0, 0x00210000U); + cpg_write(SMSTPCR1, 0xFFFFFFFFU); + cpg_write(SMSTPCR2, 0x340E2FDCU); + cpg_write(SMSTPCR3, 0xFFFFFBDFU); + cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4)); + cpg_write(SMSTPCR5, 0xC3FFFFFFU); + cpg_write(SMSTPCR6, 0xFFFFFFFFU); + cpg_write(SMSTPCR7, 0xFFFFFFFFU); + cpg_write(SMSTPCR8, 0x01F1FFF5U); + cpg_write(SMSTPCR9, 0xFFFFFFFEU); +} +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E) +static void bl2_realtime_cpg_init_e3(void) +{ + /* Realtime Module Stop Control Registers */ + cpg_write(RMSTPCR0, 0x00210000U); + cpg_write(RMSTPCR1, 0xFFFFFFFFU); + cpg_write(RMSTPCR2, 0x000E0FDCU); + cpg_write(RMSTPCR3, 0xFFFFFFDFU); + cpg_write(RMSTPCR4, 0x80000004U); + cpg_write(RMSTPCR5, 0xC3FFFFFFU); + cpg_write(RMSTPCR6, 0xFFFFFFFFU); + cpg_write(RMSTPCR7, 0xFFFFFFFFU); + cpg_write(RMSTPCR8, 0x00F1FFF7U); + cpg_write(RMSTPCR9, 0xFFFFFFDFU); + cpg_write(RMSTPCR10, 0xFFFFFFE8U); + cpg_write(RMSTPCR11, 0x000000B7U); +} + +static void bl2_system_cpg_init_e3(void) +{ + /* System Module Stop Control Registers */ + cpg_write(SMSTPCR0, 0x00210000U); + cpg_write(SMSTPCR1, 0xFFFFFFFFU); + cpg_write(SMSTPCR2, 0x000E2FDCU); + cpg_write(SMSTPCR3, 0xFFFFFBDFU); + cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4)); + cpg_write(SMSTPCR5, 0xC3FFFFFFU); + cpg_write(SMSTPCR6, 0xFFFFFFFFU); + cpg_write(SMSTPCR7, 0xFFFFFFFFU); + cpg_write(SMSTPCR8, 0x00F1FFF7U); + cpg_write(SMSTPCR9, 0xFFFFFFDFU); + cpg_write(SMSTPCR10, 0xFFFFFFE8U); + cpg_write(SMSTPCR11, 0x000000B7U); +} +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_D3) +static void bl2_system_cpg_init_d3(void) +{ + /* System Module Stop Control Registers */ + cpg_write(SMSTPCR0, 0x00010000U); + cpg_write(SMSTPCR1, 0xFFFFFFFFU); + cpg_write(SMSTPCR2, 0x00060FDCU); + cpg_write(SMSTPCR3, 0xFFFFFBDFU); + cpg_write(SMSTPCR4, 0x00000080U | (mmio_read_32(SMSTPCR4) & 0x4)); + cpg_write(SMSTPCR5, 0x83FFFFFFU); + cpg_write(SMSTPCR6, 0xFFFFFFFFU); + cpg_write(SMSTPCR7, 0xFFFFFFFFU); + cpg_write(SMSTPCR8, 0x00F1FFF7U); + cpg_write(SMSTPCR9, 0xF3F5E016U); + cpg_write(SMSTPCR10, 0xFFFEFFE0U); + cpg_write(SMSTPCR11, 0x000000B7U); +} +#endif + +void bl2_cpg_init(void) +{ + uint32_t boot_cpu = mmio_read_32(RCAR_MODEMR) & MODEMR_BOOT_CPU_MASK; +#if RCAR_LSI == RCAR_AUTO + uint32_t product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; +#endif + bl2_secure_cpg_init(); + + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { +#if RCAR_LSI == RCAR_AUTO + + switch (product) { + case PRR_PRODUCT_H3: + bl2_realtime_cpg_init_h3(); + break; + case PRR_PRODUCT_M3: + bl2_realtime_cpg_init_m3(); + break; + case PRR_PRODUCT_M3N: + bl2_realtime_cpg_init_m3n(); + break; + case PRR_PRODUCT_V3M: + bl2_realtime_cpg_init_v3m(); + break; + case PRR_PRODUCT_E3: + bl2_realtime_cpg_init_e3(); + break; + case PRR_PRODUCT_D3: + /* no need */ + break; + default: + panic(); + break; + } +#elif (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) || (RCAR_LSI == RZ_G2H) + bl2_realtime_cpg_init_h3(); +#elif (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M) + bl2_realtime_cpg_init_m3(); +#elif RCAR_LSI == RCAR_M3N || (RCAR_LSI == RZ_G2N) + bl2_realtime_cpg_init_m3n(); +#elif RCAR_LSI == RCAR_V3M + bl2_realtime_cpg_init_v3m(); +#elif RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2E + bl2_realtime_cpg_init_e3(); +#elif RCAR_LSI == RCAR_D3 + /* no need */ +#else +#error "Don't have CPG initialize routine(unknown)." +#endif + } +} + +void bl2_system_cpg_init(void) +{ +#if RCAR_LSI == RCAR_AUTO + uint32_t product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + + switch (product) { + case PRR_PRODUCT_H3: + bl2_system_cpg_init_h3(); + break; + case PRR_PRODUCT_M3: + bl2_system_cpg_init_m3(); + break; + case PRR_PRODUCT_M3N: + bl2_system_cpg_init_m3n(); + break; + case PRR_PRODUCT_V3M: + bl2_system_cpg_init_v3m(); + break; + case PRR_PRODUCT_E3: + bl2_system_cpg_init_e3(); + break; + case PRR_PRODUCT_D3: + bl2_system_cpg_init_d3(); + break; + default: + panic(); + break; + } +#elif (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) || (RCAR_LSI == RZ_G2H) + bl2_system_cpg_init_h3(); +#elif (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M) + bl2_system_cpg_init_m3(); +#elif RCAR_LSI == RCAR_M3N || (RCAR_LSI == RZ_G2N) + bl2_system_cpg_init_m3n(); +#elif RCAR_LSI == RCAR_V3M + bl2_system_cpg_init_v3m(); +#elif RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2E + bl2_system_cpg_init_e3(); +#elif RCAR_LSI == RCAR_D3 + bl2_system_cpg_init_d3(); +#else +#error "Don't have CPG initialize routine(unknown)." +#endif +} diff --git a/arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c b/arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c new file mode 100644 index 0000000..d9a4b8e --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "rcar_def.h" + +#define SWDT_ERROR_ID (1024U) +#define SWDT_ERROR_TYPE (16U) +#define SWDT_CHAR_MAX (13U) + +extern void rcar_swdt_release(void); + +void bl2_interrupt_error_id(uint32_t int_id) +{ + ERROR("\n"); + if (int_id >= SWDT_ERROR_ID) { + ERROR("Unhandled exception occurred.\n"); + ERROR(" Exception type = FIQ_SP_EL0\n"); + panic(); + } + + /* Clear the interrupt request */ + gicv2_end_of_interrupt((uint32_t) int_id); + rcar_swdt_release(); + ERROR("Unhandled exception occurred.\n"); + ERROR(" Exception type = FIQ_SP_EL0\n"); + ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3()); + ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3()); + ERROR(" ESR_EL3 = 0x%x\n", (uint32_t) read_esr_el3()); + ERROR(" FAR_EL3 = 0x%x\n", (uint32_t) read_far_el3()); + ERROR("\n"); + panic(); +} + +void bl2_interrupt_error_type(uint32_t ex_type) +{ + const uint8_t interrupt_ex[SWDT_ERROR_TYPE][SWDT_CHAR_MAX] = { + "SYNC SP EL0", + "IRQ SP EL0", + "FIQ SP EL0", + "SERR SP EL0", + "SYNC SP ELx", + "IRQ SP ELx", + "FIQ SP ELx", + "SERR SP ELx", + "SYNC AARCH64", + "IRQ AARCH64", + "FIQ AARCH64", + "SERR AARCH64", + "SYNC AARCH32", + "IRQ AARCH32", + "FIQ AARCH32", + "SERR AARCH32" + }; + char msg[128]; + + /* Clear the interrupt request */ + if (ex_type >= SWDT_ERROR_TYPE) { + ERROR("\n"); + ERROR("Unhandled exception occurred.\n"); + ERROR(" Exception type = Unknown (%d)\n", ex_type); + goto loop; + } + + rcar_swdt_release(); + ERROR("\n"); + ERROR("Unhandled exception occurred.\n"); + snprintf(msg, sizeof(msg), " Exception type = %s\n", + &interrupt_ex[ex_type][0]); + ERROR("%s", msg); + switch (ex_type) { + case SYNC_EXCEPTION_SP_EL0: + ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3()); + ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3()); + ERROR(" ESR_EL3 = 0x%x\n", (uint32_t) read_esr_el3()); + ERROR(" FAR_EL3 = 0x%x\n", (uint32_t) read_far_el3()); + break; + case IRQ_SP_EL0: + ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3()); + ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3()); + ERROR(" IAR_EL3 = 0x%x\n", gicv2_acknowledge_interrupt()); + break; + case FIQ_SP_EL0: + ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3()); + ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3()); + ERROR(" IAR_EL3 = 0x%x\n", gicv2_acknowledge_interrupt()); + break; + case SERROR_SP_EL0: + ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3()); + ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3()); + ERROR(" ESR_EL3 = 0x%x\n", (uint32_t) read_esr_el3()); + ERROR(" FAR_EL3 = 0x%x\n", (uint32_t) read_far_el3()); + break; + default: + break; + } +loop: + ERROR("\n"); + panic(); +} diff --git a/arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c b/arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c new file mode 100644 index 0000000..bf2706d --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#if (RCAR_BL33_EXECUTION_EL != 0) && (RCAR_BL33_EXECUTION_EL != 1) +#error +#endif + +#if (RCAR_BL33_EXECUTION_EL == 0) +#define BL33_MODE MODE_EL1 +#else +#define BL33_MODE MODE_EL2 +#endif + +extern uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)]; + +static bl_mem_params_node_t bl2_mem_params_descs[] = { + { + .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, + + + 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 + }, +# 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, + .ep_info.args.arg3 = (uintptr_t)fdt_blob, + + 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 + { + .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, +#ifdef RCAR_BL33_ARG0 + .ep_info.args.arg0 = RCAR_BL33_ARG0, +#endif + .ep_info.args.arg1 = (uintptr_t)fdt_blob, + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, 0), + .image_info.image_max_size = + (uint32_t) (DRAM_LIMIT - BL33_BASE), + .image_info.image_base = BL33_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c b/arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c new file mode 100644 index 0000000..2f8b001 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "axi_registers.h" +#include "lifec_registers.h" +#include "micro_delay.h" + +static void lifec_security_setting(void); +static void axi_security_setting(void); + +static const struct { + uint32_t reg; + uint32_t val; +} lifec[] = { + /* + * LIFEC0 (SECURITY) settings + * Security attribute setting for master ports + * Bit 0: ARM realtime core (Cortex-R7) master port + * 0: Non-Secure + */ + { SEC_SRC, 0x0000001EU }, + /* + * Security attribute setting for slave ports 0 to 15 + * {SEC_SEL0, 0xFFFFFFFFU}, + * {SEC_SEL1, 0xFFFFFFFFU}, + * {SEC_SEL2, 0xFFFFFFFFU}, + * Bit19: AXI-Bus (Main Memory domain AXI) slave ports + * 0: registers accessed from secure resource only + * Bit 9: DBSC4 register access slave ports. + * 0: registers accessed from secure resource only. + */ +#if (LIFEC_DBSC_PROTECT_ENABLE == 1) + { SEC_SEL3, 0xFFF7FDFFU }, +#else /* LIFEC_DBSC_PROTECT_ENABLE == 1 */ + { SEC_SEL3, 0xFFFFFFFFU }, +#endif /* LIFEC_DBSC_PROTECT_ENABLE == 1 */ + /* + * {SEC_SEL4, 0xFFFFFFFFU}, + * Bit 6: Boot ROM slave ports. + * 0: registers accessed from secure resource only + */ + { SEC_SEL5, 0xFFFFFFBFU }, + /* + * Bit13: SCEG PKA (secure APB) slave ports + * 0: registers accessed from secure resource only + * 1: Reserved[R-Car E3/D3] + * Bit12: SCEG PKA (public APB) slave ports + * 0: registers accessed from secure resource only + * 1: Reserved[R-Car E3/D3] + * Bit10: SCEG Secure Core slave ports + * 0: registers accessed from secure resource only + */ +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) + { SEC_SEL6, 0xFFFFFBFFU }, +#else /* (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) */ + { SEC_SEL6, 0xFFFFCBFFU }, +#endif /* (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) */ + /* + * {SEC_SEL7, 0xFFFFFFFFU}, + * {SEC_SEL8, 0xFFFFFFFFU}, + * {SEC_SEL9, 0xFFFFFFFFU}, + * {SEC_SEL10, 0xFFFFFFFFU}, + * {SEC_SEL11, 0xFFFFFFFFU}, + * {SEC_SEL12, 0xFFFFFFFFU}, + * Bit22: RPC slave ports. + * 0: registers accessed from secure resource only. + */ +#if (RCAR_RPC_HYPERFLASH_LOCKED == 1) + { SEC_SEL13, 0xFFBFFFFFU }, +#endif /* (RCAR_RPC_HYPERFLASH_LOCKED == 1) */ + /* + * Bit27: System Timer (SCMT) slave ports + * 0: registers accessed from secure resource only + * Bit26: System Watchdog Timer (SWDT) slave ports + * 0: registers accessed from secure resource only + */ + { SEC_SEL14, 0xF3FFFFFFU }, + /* + * Bit13: RST slave ports. + * 0: registers accessed from secure resource only + * Bit 7: Life Cycle 0 slave ports + * 0: registers accessed from secure resource only + */ + { SEC_SEL15, 0xFFFFFF3FU }, + /* + * Security group 0 attribute setting for master ports 0 + * Security group 1 attribute setting for master ports 0 + * {SEC_GRP0CR0, 0x00000000U}, + * {SEC_GRP1CR0, 0x00000000U}, + * Security group 0 attribute setting for master ports 1 + * Security group 1 attribute setting for master ports 1 + * {SEC_GRP0CR1, 0x00000000U}, + * {SEC_GRP1CR1, 0x00000000U}, + * Security group 0 attribute setting for master ports 2 + * Security group 1 attribute setting for master ports 2 + * Bit17: SCEG Secure Core master ports. + * SecurityGroup3 + */ + { SEC_GRP0CR2, 0x00020000U }, + { SEC_GRP1CR2, 0x00020000U }, + /* + * Security group 0 attribute setting for master ports 3 + * Security group 1 attribute setting for master ports 3 + * {SEC_GRP0CR3, 0x00000000U}, + * {SEC_GRP1CR3, 0x00000000U}, + * Security group 0 attribute setting for slave ports 0 + * Security group 1 attribute setting for slave ports 0 + * {SEC_GRP0COND0, 0x00000000U}, + * {SEC_GRP1COND0, 0x00000000U}, + * Security group 0 attribute setting for slave ports 1 + * Security group 1 attribute setting for slave ports 1 + * {SEC_GRP0COND1, 0x00000000U}, + * {SEC_GRP1COND1, 0x00000000U}, + * Security group 0 attribute setting for slave ports 2 + * Security group 1 attribute setting for slave ports 2 + * {SEC_GRP0COND2, 0x00000000U}, + * {SEC_GRP1COND2, 0x00000000U}, + * Security group 0 attribute setting for slave ports 3 + * Security group 1 attribute setting for slave ports 3 + * Bit19: AXI-Bus (Main Memory domain AXI) slave ports. + * SecurityGroup3 + * Bit 9: DBSC4 register access slave ports. + * SecurityGroup3 + */ +#if (LIFEC_DBSC_PROTECT_ENABLE == 1) + { SEC_GRP0COND3, 0x00080200U }, + { SEC_GRP1COND3, 0x00080200U }, +#else /* (LIFEC_DBSC_PROTECT_ENABLE == 1) */ + { SEC_GRP0COND3, 0x00000000U }, + { SEC_GRP1COND3, 0x00000000U }, +#endif /* (LIFEC_DBSC_PROTECT_ENABLE == 1) */ + /* + * Security group 0 attribute setting for slave ports 4 + * Security group 1 attribute setting for slave ports 4 + * {SEC_GRP0COND4, 0x00000000U}, + * {SEC_GRP1COND4, 0x00000000U}, + * Security group 0 attribute setting for slave ports 5 + * Security group 1 attribute setting for slave ports 5 + * Bit 6: Boot ROM slave ports + * SecurityGroup3 + */ + { SEC_GRP0COND5, 0x00000040U }, + { SEC_GRP1COND5, 0x00000040U }, + /* + * Security group 0 attribute setting for slave ports 6 + * Security group 1 attribute setting for slave ports 6 + * Bit13: SCEG PKA (secure APB) slave ports + * SecurityGroup3 + * Reserved[R-Car E3/D3] + * Bit12: SCEG PKA (public APB) slave ports + * SecurityGroup3 + * Reserved[R-Car E3/D3] + * Bit10: SCEG Secure Core slave ports + * SecurityGroup3 + */ +#if RCAR_LSI == RCAR_E3 || RCAR_LSI == RCAR_D3 + { SEC_GRP0COND6, 0x00000400U }, + { SEC_GRP1COND6, 0x00000400U }, +#else /* RCAR_LSI == RCAR_E3 */ + { SEC_GRP0COND6, 0x00003400U }, + { SEC_GRP1COND6, 0x00003400U }, +#endif /* RCAR_LSI == RCAR_E3 */ + /* + * Security group 0 attribute setting for slave ports 7 + * Security group 1 attribute setting for slave ports 7 + * {SEC_GRP0COND7, 0x00000000U}, + * {SEC_GRP1COND7, 0x00000000U}, + * Security group 0 attribute setting for slave ports 8 + * Security group 1 attribute setting for slave ports 8 + * {SEC_GRP0COND8, 0x00000000U}, + * {SEC_GRP1COND8, 0x00000000U}, + * Security group 0 attribute setting for slave ports 9 + * Security group 1 attribute setting for slave ports 9 + * {SEC_GRP0COND9, 0x00000000U}, + * {SEC_GRP1COND9, 0x00000000U}, + * Security group 0 attribute setting for slave ports 10 + * Security group 1 attribute setting for slave ports 10 + * {SEC_GRP0COND10, 0x00000000U}, + * {SEC_GRP1COND10, 0x00000000U}, + * Security group 0 attribute setting for slave ports 11 + * Security group 1 attribute setting for slave ports 11 + * {SEC_GRP0COND11, 0x00000000U}, + * {SEC_GRP1COND11, 0x00000000U}, + * Security group 0 attribute setting for slave ports 12 + * Security group 1 attribute setting for slave ports 12 + * {SEC_GRP0COND12, 0x00000000U}, + * {SEC_GRP1COND12, 0x00000000U}, + * Security group 0 attribute setting for slave ports 13 + * Security group 1 attribute setting for slave ports 13 + * Bit22: RPC slave ports. + * SecurityGroup3 + */ +#if (RCAR_RPC_HYPERFLASH_LOCKED == 1) + { SEC_GRP0COND13, 0x00400000U }, + { SEC_GRP1COND13, 0x00400000U }, +#endif /* (RCAR_RPC_HYPERFLASH_LOCKED == 1) */ + /* + * Security group 0 attribute setting for slave ports 14 + * Security group 1 attribute setting for slave ports 14 + * Bit26: System Timer (SCMT) slave ports + * SecurityGroup3 + * Bit27: System Watchdog Timer (SWDT) slave ports + * SecurityGroup3 + */ + { SEC_GRP0COND14, 0x0C000000U }, + { SEC_GRP1COND14, 0x0C000000U }, + /* + * Security group 0 attribute setting for slave ports 15 + * Security group 1 attribute setting for slave ports 15 + * Bit13: RST slave ports + * SecurityGroup3 + * Bit 7: Life Cycle 0 slave ports + * SecurityGroup3 + * Bit 6: TDBG slave ports + * SecurityGroup3 + */ + { SEC_GRP0COND15, 0x000000C0U }, + { SEC_GRP1COND15, 0x000000C0U }, + /* + * Security write protection attribute setting slave ports 0 + * {SEC_READONLY0, 0x00000000U}, + * Security write protection attribute setting slave ports 1 + * {SEC_READONLY1, 0x00000000U}, + * Security write protection attribute setting slave ports 2 + * {SEC_READONLY2, 0x00000000U}, + * Security write protection attribute setting slave ports 3 + * {SEC_READONLY3, 0x00000000U}, + * Security write protection attribute setting slave ports 4 + * {SEC_READONLY4, 0x00000000U}, + * Security write protection attribute setting slave ports 5 + * {SEC_READONLY5, 0x00000000U}, + * Security write protection attribute setting slave ports 6 + * {SEC_READONLY6, 0x00000000U}, + * Security write protection attribute setting slave ports 7 + * {SEC_READONLY7, 0x00000000U}, + * Security write protection attribute setting slave ports 8 + * {SEC_READONLY8, 0x00000000U}, + * Security write protection attribute setting slave ports 9 + * {SEC_READONLY9, 0x00000000U}, + * Security write protection attribute setting slave ports 10 + * {SEC_READONLY10, 0x00000000U}, + * Security write protection attribute setting slave ports 11 + * {SEC_READONLY11, 0x00000000U}, + * Security write protection attribute setting slave ports 12 + * {SEC_READONLY12, 0x00000000U}, + * Security write protection attribute setting slave ports 13 + * {SEC_READONLY13, 0x00000000U}, + * Security write protection attribute setting slave ports 14 + * {SEC_READONLY14, 0x00000000U}, + * Security write protection attribute setting slave ports 15 + * {SEC_READONLY15, 0x00000000U} + */ +}; + +/* AXI settings */ +static const struct { + uint32_t reg; + uint32_t val; +} axi[] = { + /* + * DRAM protection + * AXI dram protected area division + */ + {AXI_DPTDIVCR0, 0x0E0403F0U}, + {AXI_DPTDIVCR1, 0x0E0407E0U}, + {AXI_DPTDIVCR2, 0x0E080000U}, + {AXI_DPTDIVCR3, 0x0E080000U}, + {AXI_DPTDIVCR4, 0x0E080000U}, + {AXI_DPTDIVCR5, 0x0E080000U}, + {AXI_DPTDIVCR6, 0x0E080000U}, + {AXI_DPTDIVCR7, 0x0E080000U}, + {AXI_DPTDIVCR8, 0x0E080000U}, + {AXI_DPTDIVCR9, 0x0E080000U}, + {AXI_DPTDIVCR10, 0x0E080000U}, + {AXI_DPTDIVCR11, 0x0E080000U}, + {AXI_DPTDIVCR12, 0x0E080000U}, + {AXI_DPTDIVCR13, 0x0E080000U}, + {AXI_DPTDIVCR14, 0x0E080000U}, + /* AXI dram protected area setting */ + {AXI_DPTCR0, 0x0E000000U}, + {AXI_DPTCR1, 0x0E000E0EU}, + {AXI_DPTCR2, 0x0E000000U}, + {AXI_DPTCR3, 0x0E000000U}, + {AXI_DPTCR4, 0x0E000000U}, + {AXI_DPTCR5, 0x0E000000U}, + {AXI_DPTCR6, 0x0E000000U}, + {AXI_DPTCR7, 0x0E000000U}, + {AXI_DPTCR8, 0x0E000000U}, + {AXI_DPTCR9, 0x0E000000U}, + {AXI_DPTCR10, 0x0E000000U}, + {AXI_DPTCR11, 0x0E000000U}, + {AXI_DPTCR12, 0x0E000000U}, + {AXI_DPTCR13, 0x0E000000U}, + {AXI_DPTCR14, 0x0E000000U}, + {AXI_DPTCR15, 0x0E000000U}, + /* + * SRAM ptotection + * AXI sram protected area division + */ + {AXI_SPTDIVCR0, 0x0E0E6304U}, + {AXI_SPTDIVCR1, 0x0E0E6360U}, + {AXI_SPTDIVCR2, 0x0E0E6360U}, + {AXI_SPTDIVCR3, 0x0E0E6360U}, + {AXI_SPTDIVCR4, 0x0E0E6360U}, + {AXI_SPTDIVCR5, 0x0E0E6360U}, + {AXI_SPTDIVCR6, 0x0E0E6360U}, + {AXI_SPTDIVCR7, 0x0E0E6360U}, + {AXI_SPTDIVCR8, 0x0E0E6360U}, + {AXI_SPTDIVCR9, 0x0E0E6360U}, + {AXI_SPTDIVCR10, 0x0E0E6360U}, + {AXI_SPTDIVCR11, 0x0E0E6360U}, + {AXI_SPTDIVCR12, 0x0E0E6360U}, + {AXI_SPTDIVCR13, 0x0E0E6360U}, + {AXI_SPTDIVCR14, 0x0E0E6360U}, + /* AXI sram protected area setting */ + {AXI_SPTCR0, 0x0E000E0EU}, + {AXI_SPTCR1, 0x0E000000U}, + {AXI_SPTCR2, 0x0E000000U}, + {AXI_SPTCR3, 0x0E000000U}, + {AXI_SPTCR4, 0x0E000000U}, + {AXI_SPTCR5, 0x0E000000U}, + {AXI_SPTCR6, 0x0E000000U}, + {AXI_SPTCR7, 0x0E000000U}, + {AXI_SPTCR8, 0x0E000000U}, + {AXI_SPTCR9, 0x0E000000U}, + {AXI_SPTCR10, 0x0E000000U}, + {AXI_SPTCR11, 0x0E000000U}, + {AXI_SPTCR12, 0x0E000000U}, + {AXI_SPTCR13, 0x0E000000U}, + {AXI_SPTCR14, 0x0E000000U}, + {AXI_SPTCR15, 0x0E000000U} +}; + +static void lifec_security_setting(void) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(lifec); i++) + mmio_write_32(lifec[i].reg, lifec[i].val); +} + +/* SRAM/DRAM protection setting */ +static void axi_security_setting(void) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(axi); i++) + mmio_write_32(axi[i].reg, axi[i].val); +} + +void bl2_secure_setting(void) +{ + lifec_security_setting(); + axi_security_setting(); + rcar_micro_delay(10U); +} diff --git a/arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c b/arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c new file mode 100644 index 0000000..60960d4 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pwrc.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_version.h" + +static const uint64_t BL31_RO_BASE = BL_CODE_BASE; +static const uint64_t BL31_RO_LIMIT = BL_CODE_END; + +#if USE_COHERENT_MEM +static const uint64_t BL31_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE; +static const uint64_t BL31_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END; +#endif /* USE_COHERENT_MEM */ + +extern void plat_rcar_gic_driver_init(void); +extern void plat_rcar_gic_init(void); + +u_register_t rcar_boot_mpidr; + +static int cci_map[] = { + CCI500_CLUSTER0_SL_IFACE_IX_FOR_M3, + CCI500_CLUSTER1_SL_IFACE_IX_FOR_M3 +}; + +void plat_cci_init(void) +{ + uint32_t prd; + + prd = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + + if (PRR_PRODUCT_H3_CUT10 == prd || PRR_PRODUCT_H3_CUT11 == prd) { + cci_map[0U] = CCI500_CLUSTER0_SL_IFACE_IX; + cci_map[1U] = CCI500_CLUSTER1_SL_IFACE_IX; + } + + cci_init(RCAR_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); +} + +void plat_cci_enable(void) +{ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); +} + +void plat_cci_disable(void) +{ + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); +} + +struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + bl2_to_bl31_params_mem_t *from_bl2 = (bl2_to_bl31_params_mem_t *) + PARAMS_BASE; + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &from_bl2->bl33_ep_info : &from_bl2->bl32_ep_info; + + return next_image_info->pc ? next_image_info : NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + rcar_console_runtime_init(); + + NOTICE("BL3-1 : Rev.%s\n", version_of_renesas); + +#if RCAR_LSI != RCAR_D3 + if (rcar_pwrc_get_cluster() == RCAR_CLUSTER_A53A57) { + plat_cci_init(); + plat_cci_enable(); + } +#endif /* RCAR_LSI != RCAR_D3 */ +} + +void bl31_plat_arch_setup(void) +{ + rcar_configure_mmu_el3(BL31_BASE, + BL31_LIMIT - BL31_BASE, + BL31_RO_BASE, BL31_RO_LIMIT +#if USE_COHERENT_MEM + , BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT +#endif /* USE_COHERENT_MEM */ + ); + rcar_pwrc_code_copy_to_system_ram(); +} + +void bl31_platform_setup(void) +{ + plat_rcar_gic_driver_init(); + plat_rcar_gic_init(); + + /* enable the system level generic timer */ + mmio_write_32(RCAR_CNTC_BASE + CNTCR_OFF, CNTCR_FCREQ(U(0)) | CNTCR_EN); + + rcar_pwrc_setup(); +#if 0 + /* + * TODO: there is a broad number of rcar-gen3 SoC configurations; to + * support all of them, Renesas use the pwrc driver to discover what + * cores are on/off before announcing the topology. + * This code hasnt been ported yet + */ + + rcar_setup_topology(); +#endif + + /* + * mask should match the kernel's MPIDR_HWID_BITMASK so the core can be + * identified during cpuhotplug (check the kernel's psci migrate set of + * functions + */ + rcar_boot_mpidr = read_mpidr_el1() & 0x0000ffffU; + rcar_pwrc_all_disable_interrupt_wakeup(); +} diff --git a/arm-trusted-firmware/plat/renesas/common/common.mk b/arm-trusted-firmware/plat/renesas/common/common.mk new file mode 100644 index 0000000..aef0ad1 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/common.mk @@ -0,0 +1,144 @@ +# +# Copyright (c) 2018-2022, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PROGRAMMABLE_RESET_ADDRESS := 0 +COLD_BOOT_SINGLE_CPU := 1 +ARM_CCI_PRODUCT_ID := 500 +TRUSTED_BOARD_BOOT := 1 +RESET_TO_BL31 := 1 +GENERATE_COT := 1 +BL2_AT_EL3 := 1 +ENABLE_SVE_FOR_NS := 0 +MULTI_CONSOLE_API := 1 + +CRASH_REPORTING := 1 +HANDLE_EA_EL3_FIRST := 1 + +# This option gets enabled automatically if the TRUSTED_BOARD_BOOT +# is set via root Makefile, but Renesas support Trusted-Boot without +# Crypto module. +override CRYPTO_SUPPORT := 0 + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +ifeq (${SPD},none) + SPD_NONE:=1 + $(eval $(call add_define,SPD_NONE)) +endif + +# LSI setting common define +RCAR_H3:=0 +RCAR_M3:=1 +RCAR_M3N:=2 +RCAR_E3:=3 +RCAR_H3N:=4 +RCAR_D3:=5 +RCAR_V3M:=6 +RCAR_AUTO:=99 +RZ_G2M:=100 +RZ_G2H:=101 +RZ_G2N:=102 +RZ_G2E:=103 +$(eval $(call add_define,RCAR_H3)) +$(eval $(call add_define,RCAR_M3)) +$(eval $(call add_define,RCAR_M3N)) +$(eval $(call add_define,RCAR_E3)) +$(eval $(call add_define,RCAR_H3N)) +$(eval $(call add_define,RCAR_D3)) +$(eval $(call add_define,RCAR_V3M)) +$(eval $(call add_define,RCAR_AUTO)) +$(eval $(call add_define,RZ_G2M)) +$(eval $(call add_define,RZ_G2H)) +$(eval $(call add_define,RZ_G2N)) +$(eval $(call add_define,RZ_G2E)) + +RCAR_CUT_10:=0 +RCAR_CUT_11:=1 +RCAR_CUT_13:=3 +RCAR_CUT_20:=10 +RCAR_CUT_30:=20 +$(eval $(call add_define,RCAR_CUT_10)) +$(eval $(call add_define,RCAR_CUT_11)) +$(eval $(call add_define,RCAR_CUT_13)) +$(eval $(call add_define,RCAR_CUT_20)) +$(eval $(call add_define,RCAR_CUT_30)) + +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 + +# Enable workarounds for selected Cortex-A57 erratas. +ERRATA_A57_859972 := 1 +ERRATA_A57_813419 := 1 +ERRATA_A57_1319537 := 1 + +PLAT_INCLUDES := -Iplat/renesas/common/include/registers \ + -Iplat/renesas/common/include \ + -Iplat/renesas/common + +PLAT_BL_COMMON_SOURCES := drivers/renesas/common/iic_dvfs/iic_dvfs.c \ + plat/renesas/common/rcar_common.c + +include drivers/arm/gic/v2/gicv2.mk +RCAR_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c + +BL2_SOURCES += ${RCAR_GIC_SOURCES} \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + ${LIBFDT_SRCS} \ + common/desc_image_load.c \ + plat/renesas/common/aarch64/platform_common.c \ + plat/renesas/common/aarch64/plat_helpers.S \ + plat/renesas/common/bl2_interrupt_error.c \ + plat/renesas/common/bl2_secure_setting.c \ + plat/renesas/common/plat_storage.c \ + plat/renesas/common/bl2_plat_mem_params_desc.c \ + plat/renesas/common/plat_image_load.c \ + plat/renesas/common/bl2_cpg_init.c \ + drivers/renesas/common/console/rcar_printf.c \ + drivers/renesas/common/scif/scif.S \ + drivers/renesas/common/common.c \ + drivers/renesas/common/io/io_emmcdrv.c \ + drivers/renesas/common/io/io_memdrv.c \ + drivers/renesas/common/io/io_rcar.c \ + drivers/renesas/common/auth/auth_mod.c \ + drivers/renesas/common/rpc/rpc_driver.c \ + drivers/renesas/common/dma/dma_driver.c \ + drivers/renesas/common/avs/avs_driver.c \ + drivers/renesas/common/delay/micro_delay.c \ + drivers/renesas/common/emmc/emmc_interrupt.c \ + drivers/renesas/common/emmc/emmc_utility.c \ + drivers/renesas/common/emmc/emmc_mount.c \ + drivers/renesas/common/emmc/emmc_init.c \ + drivers/renesas/common/emmc/emmc_read.c \ + drivers/renesas/common/emmc/emmc_cmd.c \ + drivers/renesas/common/watchdog/swdt.c \ + drivers/renesas/common/rom/rom_api.c \ + drivers/io/io_storage.c + +BL31_SOURCES += ${RCAR_GIC_SOURCES} \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + plat/common/plat_psci_common.c \ + plat/renesas/common/plat_topology.c \ + plat/renesas/common/aarch64/plat_helpers.S \ + plat/renesas/common/aarch64/platform_common.c \ + plat/renesas/common/bl31_plat_setup.c \ + plat/renesas/common/plat_pm.c \ + drivers/renesas/common/console/rcar_console.S \ + drivers/renesas/common/console/rcar_printf.c \ + drivers/renesas/common/delay/micro_delay.c \ + drivers/renesas/common/pwrc/call_sram.S \ + drivers/renesas/common/pwrc/pwrc.c \ + drivers/renesas/common/common.c \ + drivers/arm/cci/cci.c + +include lib/xlat_tables_v2/xlat_tables.mk +include drivers/auth/mbedtls/mbedtls_crypto.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} diff --git a/arm-trusted-firmware/plat/renesas/common/include/plat.ld.S b/arm-trusted-firmware/plat/renesas/common/include/plat.ld.S new file mode 100644 index 0000000..7aef324 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/plat.ld.S @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef RCAR_PLAT_LD_S +#define RCAR_PLAT_LD_S + +#include +#include + +MEMORY { + SRAM (rwx): ORIGIN = BL31_SRAM_BASE, LENGTH = DEVICE_SRAM_SIZE + PRAM (r): ORIGIN = BL31_LIMIT - DEVICE_SRAM_SIZE, LENGTH = DEVICE_SRAM_SIZE +} + +SECTIONS +{ + /* SRAM_COPY is in PRAM */ + . = BL31_LIMIT - DEVICE_SRAM_SIZE; + __SRAM_COPY_START__ = .; + + .system_ram : { + /* system ram start is in SRAM */ + __system_ram_start__ = .; + *(.system_ram*) + *iic_dvfs.o(.rodata) + __system_ram_end__ = .; + } >SRAM AT>PRAM + + ASSERT(__BL31_END__ <= BL31_LIMIT - DEVICE_SRAM_SIZE, + "BL31 image too large - writing on top of SRAM!") + +} + +#endif /* RCAR_PLAT_LD_S */ diff --git a/arm-trusted-firmware/plat/renesas/common/include/plat_macros.S b/arm-trusted-firmware/plat/renesas/common/include/plat_macros.S new file mode 100644 index 0000000..927cd39 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/plat_macros.S @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "rcar_def.h" + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL3-1. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_print_gic_regs + mov_imm x17, RCAR_GICC_BASE + mov_imm x16, RCAR_GICD_BASE +print_gicc_regs: + /* gicc base address is now in x17 */ + adr x6, gicc_regs /* Load the gicc reg list to x6 */ + /* 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 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 + bl asm_print_hex + 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 + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* ------------------------------------------------ + * The below macro prints out relevant interconnect + * registers whenever an unhandled exception is + * taken in BL3-1. + * Clobbers: x0 - x9, sp + * ------------------------------------------------ + */ + .macro plat_print_interconnect_regs + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (CCI500_BASE + SLAVE_IFACE3_OFFSET) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (CCI500_BASE + SLAVE_IFACE4_OFFSET) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + .endm + + .macro plat_crash_print_regs + plat_print_gic_regs + plat_print_interconnect_regs + .endm diff --git a/arm-trusted-firmware/plat/renesas/common/include/platform_def.h b/arm-trusted-firmware/plat/renesas/common/include/platform_def.h new file mode 100644 index 0000000..ab071ec --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/platform_def.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2015-2021, 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 + +#include "rcar_def.h" + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + #define FIRMWARE_WELCOME_STR "Booting Rcar-gen3 Trusted Firmware\n" + +/* Size of cacheable stacks */ +#if IMAGE_BL1 +#if TRUSTED_BOARD_BOOT +#define PLATFORM_STACK_SIZE U(0x1000) +#else +#define PLATFORM_STACK_SIZE U(0x440) +#endif +#elif IMAGE_BL2 +#if TRUSTED_BOARD_BOOT +#define PLATFORM_STACK_SIZE U(0x1000) +#else +#define PLATFORM_STACK_SIZE U(0x400) +#endif +#elif IMAGE_BL31 +#define PLATFORM_STACK_SIZE U(0x800) +#elif IMAGE_BL32 +#define PLATFORM_STACK_SIZE U(0x440) +#endif + +#define BL332_IMAGE_ID (NS_BL2U_IMAGE_ID + 1) +#define BL333_IMAGE_ID (NS_BL2U_IMAGE_ID + 2) +#define BL334_IMAGE_ID (NS_BL2U_IMAGE_ID + 3) +#define BL335_IMAGE_ID (NS_BL2U_IMAGE_ID + 4) +#define BL336_IMAGE_ID (NS_BL2U_IMAGE_ID + 5) +#define BL337_IMAGE_ID (NS_BL2U_IMAGE_ID + 6) +#define BL338_IMAGE_ID (NS_BL2U_IMAGE_ID + 7) + +#define BL332_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 8) +#define BL333_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 9) +#define BL334_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 10) +#define BL335_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 11) +#define BL336_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 12) +#define BL337_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 13) +#define BL338_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 14) + +#define BL332_CERT_ID (NS_BL2U_IMAGE_ID + 15) +#define BL333_CERT_ID (NS_BL2U_IMAGE_ID + 16) +#define BL334_CERT_ID (NS_BL2U_IMAGE_ID + 17) +#define BL335_CERT_ID (NS_BL2U_IMAGE_ID + 18) +#define BL336_CERT_ID (NS_BL2U_IMAGE_ID + 19) +#define BL337_CERT_ID (NS_BL2U_IMAGE_ID + 20) +#define BL338_CERT_ID (NS_BL2U_IMAGE_ID + 21) + +/* io drivers id */ +#define FLASH_DEV_ID U(0) +#define EMMC_DEV_ID U(1) + +/* + * R-Car H3 Cortex-A57 + * L1:I/48KB(16KBx3way) D/32KB(16KBx2way) L2:2MB(128KBx16way) + * Cortex-A53 + * L1:I/32KB(16KBx2way) D/32KB(8KBx4way) L2:512KB(32KBx16way) + */ +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + 1) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +/* + ****************************************************************************** + * BL2 specific defines. + ****************************************************************************** + * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define RCAR_SYSRAM_BASE U(0xE6300000) +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) +#define BL2_LIMIT U(0xE6320000) +#else +#define BL2_LIMIT U(0xE6360000) +#endif + +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) +#define BL2_BASE U(0xE6304000) +#define BL2_IMAGE_LIMIT U(0xE6318000) +#elif (RCAR_LSI == RCAR_V3M) +#define BL2_BASE U(0xE6344000) +#define BL2_IMAGE_LIMIT U(0xE636E800) +#else +#define BL2_BASE U(0xE6304000) +#define BL2_IMAGE_LIMIT U(0xE632E800) +#endif +#define RCAR_SYSRAM_SIZE (BL2_BASE - RCAR_SYSRAM_BASE) + +/* + ****************************************************************************** + * BL31 specific defines. + ****************************************************************************** + * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL3-1 debug size plus a little space for growth. + */ +#define BL31_BASE (RCAR_TRUSTED_SRAM_BASE) +#define BL31_LIMIT (RCAR_TRUSTED_SRAM_BASE + \ + RCAR_TRUSTED_SRAM_SIZE) +#define RCAR_BL31_LOG_BASE (0x44040000) +#define RCAR_BL31_SDRAM_BTM (RCAR_BL31_LOG_BASE + 0x14000) +#define RCAR_BL31_LOG_SIZE (RCAR_BL31_SDRAM_BTM - RCAR_BL31_LOG_BASE) +#define BL31_SRAM_BASE (DEVICE_SRAM_BASE) +#define BL31_SRAM_LIMIT (DEVICE_SRAM_BASE + DEVICE_SRAM_SIZE) + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#ifndef SPD_NONE +#define BL32_BASE U(0x44100000) +#define BL32_LIMIT (BL32_BASE + U(0x200000)) +#endif + +/******************************************************************************* + * BL33 + ******************************************************************************/ +#define BL33_BASE DRAM1_NS_BASE +#define BL33_COMP_SIZE U(0x200000) +#define BL33_COMP_BASE (BL33_BASE - BL33_COMP_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#if IMAGE_BL1 +#define MAX_XLAT_TABLES U(2) +#elif IMAGE_BL2 +#define MAX_XLAT_TABLES U(5) +#elif IMAGE_BL31 +#define MAX_XLAT_TABLES U(4) +#elif IMAGE_BL32 +#define MAX_XLAT_TABLES U(3) +#endif + +#if IMAGE_BL2 +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 40) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) +#endif + +#define MAX_MMAP_REGIONS (RCAR_MMAP_ENTRIES + RCAR_BL_REGIONS) + +/******************************************************************************* + * 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 mailboxes 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 (6) +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/******************************************************************************* + * Size of the per-cpu data in bytes that should be reserved in the generic + * per-cpu data structure for the RCAR port. + ******************************************************************************/ +#if !USE_COHERENT_MEM +#define PLAT_PCPU_DATA_SIZE (2) +#endif + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/renesas/common/include/rcar_def.h b/arm-trusted-firmware/plat/renesas/common/include/rcar_def.h new file mode 100644 index 0000000..2cd26ed --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/rcar_def.h @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_DEF_H +#define RCAR_DEF_H + +#include +#include + +#define RCAR_PRIMARY_CPU 0x0 +#define RCAR_TRUSTED_SRAM_BASE 0x44000000 +#define RCAR_TRUSTED_SRAM_SIZE 0x0003E000 +#define RCAR_SHARED_MEM_BASE (RCAR_TRUSTED_SRAM_BASE + \ + RCAR_TRUSTED_SRAM_SIZE) +#define RCAR_SHARED_MEM_SIZE U(0x00001000) +#define FLASH0_BASE U(0x08000000) +#define FLASH0_SIZE U(0x04000000) +#define FLASH_MEMORY_SIZE U(0x04000000) /* hyper flash */ +#define FLASH_TRANS_SIZE_UNIT U(0x00000100) +#define DEVICE_RCAR_BASE U(0xE6000000) +#define DEVICE_RCAR_SIZE U(0x00300000) +#define DEVICE_RCAR_BASE2 U(0xE6360000) +#define DEVICE_RCAR_SIZE2 U(0x19CA0000) +#define DEVICE_SRAM_BASE U(0xE6300000) +#define DEVICE_SRAM_SIZE U(0x00002000) +#define DEVICE_SRAM_STACK_BASE (DEVICE_SRAM_BASE + DEVICE_SRAM_SIZE) +#define DEVICE_SRAM_STACK_SIZE U(0x00001000) +#define DRAM_LIMIT ULL(0x0000010000000000) +#define DRAM1_BASE U(0x40000000) +#define DRAM1_SIZE U(0x80000000) +#define DRAM1_NS_BASE (DRAM1_BASE + U(0x10000000)) +#define DRAM1_NS_SIZE (DRAM1_SIZE - DRAM1_NS_BASE) +#define DRAM_40BIT_BASE ULL(0x0400000000) +#define DRAM_40BIT_SIZE ULL(0x0400000000) +#define DRAM_PROTECTED_BASE ULL(0x43F00000) +#define DRAM_40BIT_PROTECTED_BASE ULL(0x0403F00000) +#define DRAM_PROTECTED_SIZE ULL(0x03F00000) +#define RCAR_BL31_CRASH_BASE U(0x4403F000) +#define RCAR_BL31_CRASH_SIZE U(0x00001000) +/* Entrypoint mailboxes */ +#define MBOX_BASE RCAR_SHARED_MEM_BASE +#define MBOX_SIZE 0x200 +/* Base address where parameters to BL31 are stored */ +#define PARAMS_BASE (MBOX_BASE + MBOX_SIZE) +#define BOOT_KIND_BASE (RCAR_SHARED_MEM_BASE + \ + RCAR_SHARED_MEM_SIZE - 0x100) +/* + * The number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU + */ +#if USE_COHERENT_MEM +#define RCAR_BL_REGIONS (3) +#else +#define RCAR_BL_REGIONS (2) +#endif +/* + * The RCAR_MAX_MMAP_REGIONS depends on the number of entries in rcar_mmap[] + * defined for each BL stage in rcar_common.c. + */ +#if IMAGE_BL2 +#define RCAR_MMAP_ENTRIES (9) +#endif +#if IMAGE_BL31 +#define RCAR_MMAP_ENTRIES (9) +#endif +#if IMAGE_BL2 +#define REG1_BASE U(0xE6400000) +#define REG1_SIZE U(0x04C00000) +#define ROM0_BASE U(0xEB100000) +#define ROM0_SIZE U(0x00028000) +#define REG2_BASE U(0xEC000000) +#define REG2_SIZE U(0x14000000) +#endif +/* BL33 */ +#define NS_IMAGE_OFFSET (DRAM1_BASE + U(0x09000000)) +/* BL31 */ +#define RCAR_DEVICE_BASE DEVICE_RCAR_BASE +#define RCAR_DEVICE_SIZE (0x1A000000) +#define RCAR_LOG_RES_SIZE (64) +#define RCAR_LOG_HEADER_SIZE (16) +#define RCAR_LOG_OTHER_SIZE (RCAR_LOG_HEADER_SIZE + \ + RCAR_LOG_RES_SIZE) +#define RCAR_BL31_LOG_MAX (RCAR_BL31_LOG_SIZE - \ + RCAR_LOG_OTHER_SIZE) +#define RCAR_CRASH_STACK RCAR_BL31_CRASH_BASE +#define AARCH64_SPACE_BASE ULL(0x00000000000) +#define AARCH64_SPACE_SIZE ULL(0x10000000000) +/* CCI related constants */ +#define CCI500_BASE U(0xF1200000) +#define CCI500_CLUSTER0_SL_IFACE_IX (2) +#define CCI500_CLUSTER1_SL_IFACE_IX (3) +#define CCI500_CLUSTER0_SL_IFACE_IX_FOR_M3 (1) +#define CCI500_CLUSTER1_SL_IFACE_IX_FOR_M3 (2) +#define RCAR_CCI_BASE CCI500_BASE +/* GIC */ +#define RCAR_GICD_BASE U(0xF1010000) +#define RCAR_GICR_BASE U(0xF1010000) +#define RCAR_GICC_BASE U(0xF1020000) +#define RCAR_GICH_BASE U(0xF1040000) +#define RCAR_GICV_BASE U(0xF1060000) +#define ARM_IRQ_SEC_PHY_TIMER U(29) +#define ARM_IRQ_SEC_SGI_0 U(8) +#define ARM_IRQ_SEC_SGI_1 U(9) +#define ARM_IRQ_SEC_SGI_2 U(10) +#define ARM_IRQ_SEC_SGI_3 U(11) +#define ARM_IRQ_SEC_SGI_4 U(12) +#define ARM_IRQ_SEC_SGI_5 U(13) +#define ARM_IRQ_SEC_SGI_6 U(14) +#define ARM_IRQ_SEC_SGI_7 U(15) +#define ARM_IRQ_SEC_RPC U(70) +#define ARM_IRQ_SEC_TIMER U(166) +#define ARM_IRQ_SEC_TIMER_UP U(171) +#define ARM_IRQ_SEC_WDT U(173) +#define ARM_IRQ_SEC_CRYPT U(102) +#define ARM_IRQ_SEC_CRYPT_SecPKA U(97) +#define ARM_IRQ_SEC_CRYPT_PubPKA U(98) +/* Timer control */ +#define RCAR_CNTC_BASE U(0xE6080000) +/* Reset */ +#define RCAR_MODEMR U(0xE6160060) /* Mode pin */ +#define RCAR_CA57RESCNT U(0xE6160040) /* Reset control A57 */ +#define RCAR_CA53RESCNT U(0xE6160044) /* Reset control A53 */ +#define RCAR_SRESCR U(0xE6160110) /* Soft Power On Reset */ +#define RCAR_CA53WUPCR U(0xE6151010) /* Wake-up control A53 */ +#define RCAR_CA57WUPCR U(0xE6152010) /* Wake-up control A57 */ +#define RCAR_CA53PSTR U(0xE6151040) /* Power status A53 */ +#define RCAR_CA57PSTR U(0xE6152040) /* Power status A57 */ +#define RCAR_CA53CPU0CR U(0xE6151100) /* CPU control A53 */ +#define RCAR_CA57CPU0CR U(0xE6152100) /* CPU control A57 */ +#define RCAR_CA53CPUCMCR U(0xE6151184) /* Common power A53 */ +#define RCAR_CA57CPUCMCR U(0xE6152184) /* Common power A57 */ +#define RCAR_WUPMSKCA57 U(0xE6180014) /* Wake-up mask A57 */ +#define RCAR_WUPMSKCA53 U(0xE6180018) /* Wake-up mask A53 */ +/* SYSC */ +#define RCAR_PWRSR3 U(0xE6180140) /* Power stat A53-SCU */ +#define RCAR_PWRSR5 U(0xE61801C0) /* Power stat A57-SCU */ +#define RCAR_SYSCIER U(0xE618000C) /* Interrupt enable */ +#define RCAR_SYSCIMR U(0xE6180010) /* Interrupt mask */ +#define RCAR_SYSCSR U(0xE6180000) /* SYSC status */ +#define RCAR_PWRONCR3 U(0xE618014C) /* Power resume A53-SCU */ +#define RCAR_PWRONCR5 U(0xE61801CC) /* Power resume A57-SCU */ +#define RCAR_PWROFFCR3 U(0xE6180144) /* Power shutoff A53-SCU */ +#define RCAR_PWROFFCR5 U(0xE61801C4) /* Power shutoff A57-SCU */ +#define RCAR_PWRER3 U(0xE6180154) /* shutoff/resume error */ +#define RCAR_PWRER5 U(0xE61801D4) /* shutoff/resume error */ +#define RCAR_SYSCISR U(0xE6180004) /* Interrupt status */ +#define RCAR_SYSCISCR U(0xE6180008) /* Interrupt stat clear */ +#define RCAR_SYSCEXTMASK U(0xE61802F8) /* External Request Mask */ + /* H3/H3-N, M3 v3.0, M3-N, E3 */ +/* Product register */ +#define RCAR_PRR U(0xFFF00044) +#define RCAR_M3_CUT_VER11 U(0x00000010) /* M3 Ver.1.1/Ver.1.2 */ +#define RCAR_D3_CUT_VER10 U(0x00000000) /* D3 Ver.1.0 */ +#define RCAR_D3_CUT_VER11 U(0x00000010) /* D3 Ver.1.1 */ +#define RCAR_MAJOR_MASK U(0x000000F0) +#define RCAR_MINOR_MASK U(0x0000000F) +#define PRR_PRODUCT_SHIFT U(8) +#define RCAR_MAJOR_SHIFT U(4) +#define RCAR_MINOR_SHIFT U(0) +#define RCAR_MAJOR_OFFSET U(1) +#define RCAR_M3_MINOR_OFFSET U(2) +#define PRR_PRODUCT_H3_CUT10 (PRR_PRODUCT_H3 | U(0x00)) /* 1.0 */ +#define PRR_PRODUCT_H3_CUT11 (PRR_PRODUCT_H3 | U(0x01)) /* 1.1 */ +#define PRR_PRODUCT_H3_CUT20 (PRR_PRODUCT_H3 | U(0x10)) /* 2.0 */ +#define PRR_PRODUCT_M3_CUT10 (PRR_PRODUCT_M3 | U(0x00)) /* 1.0 */ +#define PRR_PRODUCT_M3_CUT11 (PRR_PRODUCT_M3 | U(0x10)) +#define PRR 0xFFF00044U +#define PRR_PRODUCT_MASK 0x00007F00U +#define PRR_CUT_MASK 0x000000FFU +#define PRR_PRODUCT_H3 0x00004F00U /* R-Car H3 */ +#define PRR_PRODUCT_M3 0x00005200U /* R-Car M3-W */ +#define PRR_PRODUCT_V3M 0x00005400U /* R-Car V3M */ +#define PRR_PRODUCT_M3N 0x00005500U /* R-Car M3-N */ +#define PRR_PRODUCT_V3H 0x00005600U /* R-Car V3H */ +#define PRR_PRODUCT_E3 0x00005700U /* R-Car E3 */ +#define PRR_PRODUCT_D3 0x00005800U /* R-Car D3 */ +#define PRR_PRODUCT_10 0x00U /* Ver.1.0 */ +#define PRR_PRODUCT_11 0x01U /* Ver.1.1 */ +#define PRR_PRODUCT_20 0x10U /* Ver.2.0 */ +#define PRR_PRODUCT_21 0x11U /* Ver.2.1 */ +#define PRR_PRODUCT_30 0x20U /* Ver.3.0 */ +#define RCAR_CPU_MASK_CA57 U(0x80000000) +#define RCAR_CPU_MASK_CA53 U(0x04000000) +#define RCAR_CPU_HAVE_CA57 U(0x00000000) +#define RCAR_CPU_HAVE_CA53 U(0x00000000) +#define RCAR_SSCG_MASK U(0x1000) /* MD12 */ +#define RCAR_SSCG_ENABLE U(0x1000) +/* MD pin information */ +#define MODEMR_BOOT_CPU_MASK U(0x000000C0) +#define MODEMR_BOOT_CPU_CR7 U(0x000000C0) +#define MODEMR_BOOT_CPU_CA57 U(0x00000000) +#define MODEMR_BOOT_CPU_CA53 U(0x00000040) +#define MODEMR_BOOT_DEV_MASK U(0x0000001E) +#define MODEMR_BOOT_DEV_HYPERFLASH160 U(0x00000004) +#define MODEMR_BOOT_DEV_HYPERFLASH80 U(0x00000006) +#define MODEMR_BOOT_DEV_QSPI_FLASH40 U(0x00000008) +#define MODEMR_BOOT_DEV_QSPI_FLASH80 U(0x0000000C) +#define MODEMR_BOOT_DEV_EMMC_25X1 U(0x0000000A) +#define MODEMR_BOOT_DEV_EMMC_50X8 U(0x0000001A) +#define MODEMR_BOOT_PLL_MASK U(0x00006000) +#define MODEMR_BOOT_PLL_SHIFT U(13) +/* Memory mapped Generic timer interfaces */ +#define ARM_SYS_CNTCTL_BASE RCAR_CNTC_BASE +/* MODEMR PLL masks and bitfield values */ +#define CHECK_MD13_MD14 U(0x6000) +#define MD14_MD13_TYPE_0 U(0x0000) /* MD14=0 MD13=0 */ +#define MD14_MD13_TYPE_1 U(0x2000) /* MD14=0 MD13=1 */ +#define MD14_MD13_TYPE_2 U(0x4000) /* MD14=1 MD13=0 */ +#define MD14_MD13_TYPE_3 U(0x6000) /* MD14=1 MD13=1 */ +/* Frequency of EXTAL(Hz) */ +#define EXTAL_MD14_MD13_TYPE_0 U(8333300) /* MD14=0 MD13=0 */ +#define EXTAL_MD14_MD13_TYPE_1 U(10000000) /* MD14=0 MD13=1 */ +#define EXTAL_MD14_MD13_TYPE_2 U(12500000) /* MD14=1 MD13=0 */ +#define EXTAL_MD14_MD13_TYPE_3 U(16666600) /* MD14=1 MD13=1 */ +#define EXTAL_SALVATOR_XS U(8320000) /* Salvator-XS */ +#define EXTAL_EBISU U(24000000) /* Ebisu */ +#define EXTAL_DRAAK U(24000000) /* Draak */ +/* CPG write protect registers */ +#define CPGWPR_PASSWORD (0x5A5AFFFFU) +#define CPGWPCR_PASSWORD (0xA5A50000U) +/* CA5x Debug Resource control registers */ +#define CPG_CA57DBGRCR (CPG_BASE + 0x2180U) +#define CPG_CA53DBGRCR (CPG_BASE + 0x1180U) +#define DBGCPUPREN ((uint32_t)1U << 19U) +#define CPG_PLL0CR (CPG_BASE + 0x00D8U) +#define CPG_PLL2CR (CPG_BASE + 0x002CU) +#define CPG_PLL4CR (CPG_BASE + 0x01F4U) +#define CPG_CPGWPCR (CPG_BASE + 0x0904U) +/* RST Registers */ +#define RST_BASE (0xE6160000U) +#define RST_WDTRSTCR (RST_BASE + 0x0054U) +#define RST_MODEMR (RST_BASE + 0x0060U) +#define WDTRSTCR_PASSWORD (0xA55A0000U) +#define WDTRSTCR_RWDT_RSTMSK ((uint32_t)1U << 0U) +/* MFIS Registers */ +#define MFISWPCNTR_PASSWORD (0xACCE0000U) +#define MFISWPCNTR (0xE6260900U) +/* IPMMU registers */ +#define IPMMU_MM_BASE (0xE67B0000U) +#define IPMMUMM_IMSCTLR (IPMMU_MM_BASE + 0x0500U) +#define IPMMUMM_IMAUXCTLR (IPMMU_MM_BASE + 0x0504U) +#define IPMMUMM_IMSCTLR_ENABLE (0xC0000000U) +#define IPMMUMM_IMAUXCTLR_NMERGE40_BIT (0x01000000U) +#define IMSCTLR_DISCACHE (0xE0000000U) +#define IPMMU_VP0_BASE (0xFE990000U) +#define IPMMUVP0_IMSCTLR (IPMMU_VP0_BASE + 0x0500U) +#define IPMMU_VI0_BASE (0xFEBD0000U) +#define IPMMUVI0_IMSCTLR (IPMMU_VI0_BASE + 0x0500U) +#define IPMMU_VI1_BASE (0xFEBE0000U) +#define IPMMUVI1_IMSCTLR (IPMMU_VI1_BASE + 0x0500U) +#define IPMMU_PV0_BASE (0xFD800000U) +#define IPMMUPV0_IMSCTLR (IPMMU_PV0_BASE + 0x0500U) +#define IPMMU_PV1_BASE (0xFD950000U) +#define IPMMUPV1_IMSCTLR (IPMMU_PV1_BASE + 0x0500U) +#define IPMMU_PV2_BASE (0xFD960000U) +#define IPMMUPV2_IMSCTLR (IPMMU_PV2_BASE + 0x0500U) +#define IPMMU_PV3_BASE (0xFD970000U) +#define IPMMUPV3_IMSCTLR (IPMMU_PV3_BASE + 0x0500U) +#define IPMMU_HC_BASE (0xE6570000U) +#define IPMMUHC_IMSCTLR (IPMMU_HC_BASE + 0x0500U) +#define IPMMU_RT_BASE (0xFFC80000U) +#define IPMMURT_IMSCTLR (IPMMU_RT_BASE + 0x0500U) +#define IPMMU_MP_BASE (0xEC670000U) +#define IPMMUMP_IMSCTLR (IPMMU_MP_BASE + 0x0500U) +#define IPMMU_DS0_BASE (0xE6740000U) +#define IPMMUDS0_IMSCTLR (IPMMU_DS0_BASE + 0x0500U) +#define IPMMU_DS1_BASE (0xE7740000U) +#define IPMMUDS1_IMSCTLR (IPMMU_DS1_BASE + 0x0500U) +/* ARMREG registers */ +#define P_ARMREG_SEC_CTRL (0xE62711F0U) +#define P_ARMREG_SEC_CTRL_PROT (0x00000001U) +/* MIDR */ +#define MIDR_CA57 (0x0D07U << MIDR_PN_SHIFT) +#define MIDR_CA53 (0x0D03U << MIDR_PN_SHIFT) +/* for SuspendToRAM */ +#define GPIO_BASE (0xE6050000U) +#define GPIO_INDT1 (GPIO_BASE + 0x100CU) +#define GPIO_INDT3 (GPIO_BASE + 0x300CU) +#define GPIO_INDT6 (GPIO_BASE + 0x540CU) +#define GPIO_OUTDT1 (GPIO_BASE + 0x1008U) +#define GPIO_OUTDT3 (GPIO_BASE + 0x3008U) +#define GPIO_OUTDT6 (GPIO_BASE + 0x5408U) +#define RCAR_COLD_BOOT (0x00U) +#define RCAR_WARM_BOOT (0x01U) +#if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR +#define KEEP10_MAGIC (0x55U) +#endif +/* lossy registers */ +#define LOSSY_PARAMS_BASE (0x47FD7000U) +#define AXI_DCMPAREACRA0 (0xE6784100U) +#define AXI_DCMPAREACRB0 (0xE6784104U) +#define LOSSY_ENABLE (0x80000000U) +#define LOSSY_DISABLE (0x00000000U) +#define LOSSY_FMT_YUVPLANAR (0x00000000U) +#define LOSSY_FMT_YUV422INTLV (0x20000000U) +#define LOSSY_FMT_ARGB8888 (0x40000000U) +#define LOSSY_ST_ADDR0 (0x54000000U) +#define LOSSY_END_ADDR0 (0x57000000U) +#define LOSSY_FMT0 LOSSY_FMT_YUVPLANAR +#define LOSSY_ENA_DIS0 LOSSY_ENABLE +#define LOSSY_ST_ADDR1 0x0U +#define LOSSY_END_ADDR1 0x0U +#define LOSSY_FMT1 LOSSY_FMT_ARGB8888 +#define LOSSY_ENA_DIS1 LOSSY_DISABLE +#define LOSSY_ST_ADDR2 0x0U +#define LOSSY_END_ADDR2 0x0U +#define LOSSY_FMT2 LOSSY_FMT_YUV422INTLV +#define LOSSY_ENA_DIS2 LOSSY_DISABLE + +#endif /* RCAR_DEF_H */ diff --git a/arm-trusted-firmware/plat/renesas/common/include/rcar_private.h b/arm-trusted-firmware/plat/renesas/common/include/rcar_private.h new file mode 100644 index 0000000..36f4ca5 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/rcar_private.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_PRIVATE_H +#define RCAR_PRIVATE_H + +#include +#include +#include + +#include + +typedef volatile struct mailbox { + unsigned long value __aligned(CACHE_WRITEBACK_GRANULE); +} mailbox_t; + +/* + * This structure represents the superset of information that is passed to + * BL31 e.g. while passing control to it from BL2 which is bl31_params + * and bl31_plat_params and its elements + */ +typedef struct bl2_to_bl31_params_mem { + image_info_t bl32_image_info; + image_info_t bl33_image_info; + entry_point_info_t bl33_ep_info; + entry_point_info_t bl32_ep_info; +} bl2_to_bl31_params_mem_t; + +#if USE_COHERENT_MEM +#define RCAR_INSTANTIATE_LOCK DEFINE_BAKERY_LOCK(rcar_lock); +#define rcar_lock_init() bakery_lock_init(&rcar_lock) +#define rcar_lock_get() bakery_lock_get(&rcar_lock) +#define rcar_lock_release() bakery_lock_release(&rcar_lock) +#else +/* + * Constants to specify how many bakery locks this platform implements. These + * are used if the platform chooses not to use coherent memory for bakery lock + * data structures. + */ +#define RCAR_MAX_BAKERIES 2 +#define RCAR_PWRC_BAKERY_ID 0 + +/* + * Definition of structure which holds platform specific per-cpu data. Currently + * it holds only the bakery lock information for each cpu. Constants to + * specify how many bakeries this platform implements and bakery ids are + * specified in rcar_def.h + */ +typedef struct rcar_cpu_data { + bakery_info_t pcpu_bakery_info[RCAR_MAX_BAKERIES]; +} rcar_cpu_data_t; + +#define RCAR_CPU_DATA_LOCK_OFFSET \ + __builtin_offsetof(rcar_cpu_data_t, pcpu_bakery_info) +/* + * Helper macros for bakery lock api when using the above rcar_cpu_data_t for + * bakery lock data structures. It assumes that the bakery_info is at the + * beginning of the platform specific per-cpu data. + */ +#define rcar_lock_init(_lock_arg) + +#define rcar_lock_get(_lock_arg) \ + bakery_lock_get(_lock_arg, \ + CPU_DATA_PLAT_PCPU_OFFSET + RCAR_CPU_DATA_LOCK_OFFSET) + +#define rcar_lock_release(_lock_arg) \ + bakery_lock_release(_lock_arg, \ + CPU_DATA_PLAT_PCPU_OFFSET + RCAR_CPU_DATA_LOCK_OFFSET) +/* + * Ensure that the size of the RCAR specific per-cpu data structure and the size + * of the memory allocated in generic per-cpu data for the platform are the same + */ +CASSERT(sizeof(rcar_cpu_data_t) == PLAT_PCPU_DATA_SIZE, + rcar_pcpu_data_size_mismatch); +#endif +/* + * Function and variable prototypes + */ +void rcar_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, unsigned long ro_limit +#if USE_COHERENT_MEM + , unsigned long coh_start, unsigned long coh_limit +#endif + ); + +void rcar_setup_topology(void); +void rcar_cci_disable(void); +void rcar_cci_enable(void); +void rcar_cci_init(void); + +void plat_invalidate_icache(void); +void plat_cci_disable(void); +void plat_cci_enable(void); +void plat_cci_init(void); + +void mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, uint32_t target_bit); +void cpg_write(uintptr_t regadr, uint32_t regval); + +void rcar_console_boot_init(void); +void rcar_console_boot_end(void); +void rcar_console_runtime_init(void); +void rcar_console_runtime_end(void); + +#endif /* RCAR_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/renesas/common/include/rcar_version.h b/arm-trusted-firmware/plat/renesas/common/include/rcar_version.h new file mode 100644 index 0000000..5a0ca31 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/rcar_version.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_VERSION_H +#define RCAR_VERSION_H + +#include + +#define VERSION_OF_RENESAS "3.0.3" +#define VERSION_OF_RENESAS_MAXLEN 128 + +extern const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN]; + +#endif /* RCAR_VERSION_H */ diff --git a/arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h b/arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h new file mode 100644 index 0000000..36cd58b --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AXI_REGISTERS_H +#define AXI_REGISTERS_H + +/* AXI registers */ + +/* AXI base address */ +#define AXI_BASE (0xE6780000U) + +/* address split */ + +/* AXI address split control 0 */ +#define AXI_ADSPLCR0 (AXI_BASE + 0x4008U) +/* AXI address split control 1 */ +#define AXI_ADSPLCR1 (AXI_BASE + 0x400CU) +/* AXI address split control 2 */ +#define AXI_ADSPLCR2 (AXI_BASE + 0x4010U) +/* AXI address split control 3 */ +#define AXI_ADSPLCR3 (AXI_BASE + 0x4014U) + +/* functional safety */ + +/* AXI functional safety control */ +#define AXI_FUSACR (AXI_BASE + 0x4020U) + +/* decompression */ + +/* AXI decompression area configuration A0 */ +#define AXI_DCMPAREACRA0 (AXI_BASE + 0x4100U) +/* AXI decompression area configuration B0 */ +#define AXI_DCMPAREACRB0 (AXI_BASE + 0x4104U) +/* AXI decompression area configuration A1 */ +#define AXI_DCMPAREACRA1 (AXI_BASE + 0x4108U) +/* AXI decompression area configuration B1 */ +#define AXI_DCMPAREACRB1 (AXI_BASE + 0x410CU) +/* AXI decompression area configuration A2 */ +#define AXI_DCMPAREACRA2 (AXI_BASE + 0x4110U) +/* AXI decompression area configuration B2 */ +#define AXI_DCMPAREACRB2 (AXI_BASE + 0x4114U) +/* AXI decompression area configuration A3 */ +#define AXI_DCMPAREACRA3 (AXI_BASE + 0x4118U) +/* AXI decompression area configuration B3 */ +#define AXI_DCMPAREACRB3 (AXI_BASE + 0x411CU) +/* AXI decompression area configuration A4 */ +#define AXI_DCMPAREACRA4 (AXI_BASE + 0x4120U) +/* AXI decompression area configuration B4 */ +#define AXI_DCMPAREACRB4 (AXI_BASE + 0x4124U) +/* AXI decompression area configuration A5 */ +#define AXI_DCMPAREACRA5 (AXI_BASE + 0x4128U) +/* AXI decompression area configuration B5 */ +#define AXI_DCMPAREACRB5 (AXI_BASE + 0x412CU) +/* AXI decompression area configuration A6 */ +#define AXI_DCMPAREACRA6 (AXI_BASE + 0x4130U) +/* AXI decompression area configuration B6 */ +#define AXI_DCMPAREACRB6 (AXI_BASE + 0x4134U) +/* AXI decompression area configuration A7 */ +#define AXI_DCMPAREACRA7 (AXI_BASE + 0x4138U) +/* AXI decompression area configuration B7 */ +#define AXI_DCMPAREACRB7 (AXI_BASE + 0x413CU) +/* AXI decompression area configuration A8 */ +#define AXI_DCMPAREACRA8 (AXI_BASE + 0x4140U) +/* AXI decompression area configuration B8 */ +#define AXI_DCMPAREACRB8 (AXI_BASE + 0x4144U) +/* AXI decompression area configuration A9 */ +#define AXI_DCMPAREACRA9 (AXI_BASE + 0x4148U) +/* AXI decompression area configuration B9 */ +#define AXI_DCMPAREACRB9 (AXI_BASE + 0x414CU) +/* AXI decompression area configuration A10 */ +#define AXI_DCMPAREACRA10 (AXI_BASE + 0x4150U) +/* AXI decompression area configuration B10 */ +#define AXI_DCMPAREACRB10 (AXI_BASE + 0x4154U) +/* AXI decompression area configuration A11 */ +#define AXI_DCMPAREACRA11 (AXI_BASE + 0x4158U) +/* AXI decompression area configuration B11 */ +#define AXI_DCMPAREACRB11 (AXI_BASE + 0x415CU) +/* AXI decompression area configuration A12 */ +#define AXI_DCMPAREACRA12 (AXI_BASE + 0x4160U) +/* AXI decompression area configuration B12 */ +#define AXI_DCMPAREACRB12 (AXI_BASE + 0x4164U) +/* AXI decompression area configuration A13 */ +#define AXI_DCMPAREACRA13 (AXI_BASE + 0x4168U) +/* AXI decompression area configuration B13 */ +#define AXI_DCMPAREACRB13 (AXI_BASE + 0x416CU) +/* AXI decompression area configuration A14 */ +#define AXI_DCMPAREACRA14 (AXI_BASE + 0x4170U) +/* AXI decompression area configuration B14 */ +#define AXI_DCMPAREACRB14 (AXI_BASE + 0x4174U) +/* AXI decompression area configuration A15 */ +#define AXI_DCMPAREACRA15 (AXI_BASE + 0x4178U) +/* AXI decompression area configuration B15 */ +#define AXI_DCMPAREACRB15 (AXI_BASE + 0x417CU) +/* AXI decompression shadow area configuration */ +#define AXI_DCMPSHDWCR (AXI_BASE + 0x4280U) + +/* SDRAM protection */ + +/* AXI dram protected area division 0 */ +#define AXI_DPTDIVCR0 (AXI_BASE + 0x4400U) +/* AXI dram protected area division 1 */ +#define AXI_DPTDIVCR1 (AXI_BASE + 0x4404U) +/* AXI dram protected area division 2 */ +#define AXI_DPTDIVCR2 (AXI_BASE + 0x4408U) +/* AXI dram protected area division 3 */ +#define AXI_DPTDIVCR3 (AXI_BASE + 0x440CU) +/* AXI dram protected area division 4 */ +#define AXI_DPTDIVCR4 (AXI_BASE + 0x4410U) +/* AXI dram protected area division 5 */ +#define AXI_DPTDIVCR5 (AXI_BASE + 0x4414U) +/* AXI dram protected area division 6 */ +#define AXI_DPTDIVCR6 (AXI_BASE + 0x4418U) +/* AXI dram protected area division 7 */ +#define AXI_DPTDIVCR7 (AXI_BASE + 0x441CU) +/* AXI dram protected area division 8 */ +#define AXI_DPTDIVCR8 (AXI_BASE + 0x4420U) +/* AXI dram protected area division 9 */ +#define AXI_DPTDIVCR9 (AXI_BASE + 0x4424U) +/* AXI dram protected area division 10 */ +#define AXI_DPTDIVCR10 (AXI_BASE + 0x4428U) +/* AXI dram protected area division 11 */ +#define AXI_DPTDIVCR11 (AXI_BASE + 0x442CU) +/* AXI dram protected area division 12 */ +#define AXI_DPTDIVCR12 (AXI_BASE + 0x4430U) +/* AXI dram protected area division 13 */ +#define AXI_DPTDIVCR13 (AXI_BASE + 0x4434U) +/* AXI dram protected area division 14 */ +#define AXI_DPTDIVCR14 (AXI_BASE + 0x4438U) + +/* AXI dram protected area setting 0 */ +#define AXI_DPTCR0 (AXI_BASE + 0x4440U) +/* AXI dram protected area setting 1 */ +#define AXI_DPTCR1 (AXI_BASE + 0x4444U) +/* AXI dram protected area setting 2 */ +#define AXI_DPTCR2 (AXI_BASE + 0x4448U) +/* AXI dram protected area setting 3 */ +#define AXI_DPTCR3 (AXI_BASE + 0x444CU) +/* AXI dram protected area setting 4 */ +#define AXI_DPTCR4 (AXI_BASE + 0x4450U) +/* AXI dram protected area setting 5 */ +#define AXI_DPTCR5 (AXI_BASE + 0x4454U) +/* AXI dram protected area setting 6 */ +#define AXI_DPTCR6 (AXI_BASE + 0x4458U) +/* AXI dram protected area setting 7 */ +#define AXI_DPTCR7 (AXI_BASE + 0x445CU) +/* AXI dram protected area setting 8 */ +#define AXI_DPTCR8 (AXI_BASE + 0x4460U) +/* AXI dram protected area setting 9 */ +#define AXI_DPTCR9 (AXI_BASE + 0x4464U) +/* AXI dram protected area setting 10 */ +#define AXI_DPTCR10 (AXI_BASE + 0x4468U) +/* AXI dram protected area setting 11 */ +#define AXI_DPTCR11 (AXI_BASE + 0x446CU) +/* AXI dram protected area setting 12 */ +#define AXI_DPTCR12 (AXI_BASE + 0x4470U) +/* AXI dram protected area setting 13 */ +#define AXI_DPTCR13 (AXI_BASE + 0x4474U) +/* AXI dram protected area setting 14 */ +#define AXI_DPTCR14 (AXI_BASE + 0x4478U) +/* AXI dram protected area setting 15 */ +#define AXI_DPTCR15 (AXI_BASE + 0x447CU) + +/* SRAM protection */ + +/* AXI sram protected area division 0 */ +#define AXI_SPTDIVCR0 (AXI_BASE + 0x4500U) +/* AXI sram protected area division 1 */ +#define AXI_SPTDIVCR1 (AXI_BASE + 0x4504U) +/* AXI sram protected area division 2 */ +#define AXI_SPTDIVCR2 (AXI_BASE + 0x4508U) +/* AXI sram protected area division 3 */ +#define AXI_SPTDIVCR3 (AXI_BASE + 0x450CU) +/* AXI sram protected area division 4 */ +#define AXI_SPTDIVCR4 (AXI_BASE + 0x4510U) +/* AXI sram protected area division 5 */ +#define AXI_SPTDIVCR5 (AXI_BASE + 0x4514U) +/* AXI sram protected area division 6 */ +#define AXI_SPTDIVCR6 (AXI_BASE + 0x4518U) +/* AXI sram protected area division 7 */ +#define AXI_SPTDIVCR7 (AXI_BASE + 0x451CU) +/* AXI sram protected area division 8 */ +#define AXI_SPTDIVCR8 (AXI_BASE + 0x4520U) +/* AXI sram protected area division 9 */ +#define AXI_SPTDIVCR9 (AXI_BASE + 0x4524U) +/* AXI sram protected area division 10 */ +#define AXI_SPTDIVCR10 (AXI_BASE + 0x4528U) +/* AXI sram protected area division 11 */ +#define AXI_SPTDIVCR11 (AXI_BASE + 0x452CU) +/* AXI sram protected area division 12 */ +#define AXI_SPTDIVCR12 (AXI_BASE + 0x4530U) +/* AXI sram protected area division 13 */ +#define AXI_SPTDIVCR13 (AXI_BASE + 0x4534U) +/* AXI sram protected area division 14 */ +#define AXI_SPTDIVCR14 (AXI_BASE + 0x4538U) + +/* AXI sram protected area setting 0 */ +#define AXI_SPTCR0 (AXI_BASE + 0x4540U) +/* AXI sram protected area setting 1 */ +#define AXI_SPTCR1 (AXI_BASE + 0x4544U) +/* AXI sram protected area setting 2 */ +#define AXI_SPTCR2 (AXI_BASE + 0x4548U) +/* AXI sram protected area setting 3 */ +#define AXI_SPTCR3 (AXI_BASE + 0x454CU) +/* AXI sram protected area setting 4 */ +#define AXI_SPTCR4 (AXI_BASE + 0x4550U) +/* AXI sram protected area setting 5 */ +#define AXI_SPTCR5 (AXI_BASE + 0x4554U) +/* AXI sram protected area setting 6 */ +#define AXI_SPTCR6 (AXI_BASE + 0x4558U) +/* AXI sram protected area setting 7 */ +#define AXI_SPTCR7 (AXI_BASE + 0x455CU) +/* AXI sram protected area setting 8 */ +#define AXI_SPTCR8 (AXI_BASE + 0x4560U) +/* AXI sram protected area setting 9 */ +#define AXI_SPTCR9 (AXI_BASE + 0x4564U) +/* AXI sram protected area setting 10 */ +#define AXI_SPTCR10 (AXI_BASE + 0x4568U) +/* AXI sram protected area setting 11 */ +#define AXI_SPTCR11 (AXI_BASE + 0x456CU) +/* AXI sram protected area setting 12 */ +#define AXI_SPTCR12 (AXI_BASE + 0x4570U) +/* AXI sram protected area setting 13 */ +#define AXI_SPTCR13 (AXI_BASE + 0x4574U) +/* AXI sram protected area setting 14 */ +#define AXI_SPTCR14 (AXI_BASE + 0x4578U) +/* AXI sram protected area setting 15 */ +#define AXI_SPTCR15 (AXI_BASE + 0x457CU) + +/* EDC base address */ +#define EDC_BASE (0xFF840000U) + +/* EDC edc enable */ +#define EDC_EDCEN (EDC_BASE + 0x0010U) +/* EDC edc status 0 */ +#define EDC_EDCST0 (EDC_BASE + 0x0020U) +/* EDC edc status 1 */ +#define EDC_EDCST1 (EDC_BASE + 0x0024U) +/* EDC edc interrupt enable 0 */ +#define EDC_EDCINTEN0 (EDC_BASE + 0x0040U) +/* EDC edc interrupt enable 1 */ +#define EDC_EDCINTEN1 (EDC_BASE + 0x0044U) + +#endif /* AXI_REGISTERS_H */ diff --git a/arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h b/arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h new file mode 100644 index 0000000..5d2bb9e --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CPG_REGISTERS_H +#define CPG_REGISTERS_H + +/* CPG base address */ +#define CPG_BASE (0xE6150000U) + +/* CPG system module stop control 2 */ +#define CPG_SMSTPCR2 (CPG_BASE + 0x0138U) +/* CPG software reset 2 */ +#define CPG_SRCR2 (CPG_BASE + 0x00B0U) +/* CPG module stop status 2 */ +#define CPG_MSTPSR2 (CPG_BASE + 0x0040U) +/* CPG module stop status 2 */ +#define CPG_MSTPSR3 (CPG_BASE + 0x0048U) +/* CPG write protect */ +#define CPG_CPGWPR (CPG_BASE + 0x0900U) +/* CPG write protect control */ +#define CPG_CPGWPCR (CPG_BASE + 0x0904U) +/* CPG system module stop control 9 */ +#define CPG_SMSTPCR9 (CPG_BASE + 0x0994U) +/* CPG module stop status 9 */ +#define CPG_MSTPSR9 (CPG_BASE + 0x09A4U) +/* SDHI2 clock frequency control register */ +#define CPG_SD2CKCR (CPG_BASE + 0x0268U) +/* SDHI3 clock frequency control register */ +#define CPG_SD3CKCR (CPG_BASE + 0x026CU) + +/* CPG (SECURITY) registers */ + +/* Secure Module Stop Control Register 0 */ +#define SCMSTPCR0 (CPG_BASE + 0x0B20U) +/* Secure Module Stop Control Register 1 */ +#define SCMSTPCR1 (CPG_BASE + 0x0B24U) +/* Secure Module Stop Control Register 2 */ +#define SCMSTPCR2 (CPG_BASE + 0x0B28U) +/* Secure Module Stop Control Register 3 */ +#define SCMSTPCR3 (CPG_BASE + 0x0B2CU) +/* Secure Module Stop Control Register 4 */ +#define SCMSTPCR4 (CPG_BASE + 0x0B30U) +/* Secure Module Stop Control Register 5 */ +#define SCMSTPCR5 (CPG_BASE + 0x0B34U) +/* Secure Module Stop Control Register 6 */ +#define SCMSTPCR6 (CPG_BASE + 0x0B38U) +/* Secure Module Stop Control Register 7 */ +#define SCMSTPCR7 (CPG_BASE + 0x0B3CU) +/* Secure Module Stop Control Register 8 */ +#define SCMSTPCR8 (CPG_BASE + 0x0B40U) +/* Secure Module Stop Control Register 9 */ +#define SCMSTPCR9 (CPG_BASE + 0x0B44U) +/* Secure Module Stop Control Register 10 */ +#define SCMSTPCR10 (CPG_BASE + 0x0B48U) +/* Secure Module Stop Control Register 11 */ +#define SCMSTPCR11 (CPG_BASE + 0x0B4CU) + +/* CPG (SECURITY) registers */ + +/* Secure Software Reset Access Enable Control Register 0 */ +#define SCSRSTECR0 (CPG_BASE + 0x0B80U) +/* Secure Software Reset Access Enable Control Register 1 */ +#define SCSRSTECR1 (CPG_BASE + 0x0B84U) +/* Secure Software Reset Access Enable Control Register 2 */ +#define SCSRSTECR2 (CPG_BASE + 0x0B88U) +/* Secure Software Reset Access Enable Control Register 3 */ +#define SCSRSTECR3 (CPG_BASE + 0x0B8CU) +/* Secure Software Reset Access Enable Control Register 4 */ +#define SCSRSTECR4 (CPG_BASE + 0x0B90U) +/* Secure Software Reset Access Enable Control Register 5 */ +#define SCSRSTECR5 (CPG_BASE + 0x0B94U) +/* Secure Software Reset Access Enable Control Register 6 */ +#define SCSRSTECR6 (CPG_BASE + 0x0B98U) +/* Secure Software Reset Access Enable Control Register 7 */ +#define SCSRSTECR7 (CPG_BASE + 0x0B9CU) +/* Secure Software Reset Access Enable Control Register 8 */ +#define SCSRSTECR8 (CPG_BASE + 0x0BA0U) +/* Secure Software Reset Access Enable Control Register 9 */ +#define SCSRSTECR9 (CPG_BASE + 0x0BA4U) +/* Secure Software Reset Access Enable Control Register 10 */ +#define SCSRSTECR10 (CPG_BASE + 0x0BA8U) +/* Secure Software Reset Access Enable Control Register 11 */ +#define SCSRSTECR11 (CPG_BASE + 0x0BACU) + +/* CPG (REALTIME) registers */ + +/* Realtime Module Stop Control Register 0 */ +#define RMSTPCR0 (CPG_BASE + 0x0110U) +/* Realtime Module Stop Control Register 1 */ +#define RMSTPCR1 (CPG_BASE + 0x0114U) +/* Realtime Module Stop Control Register 2 */ +#define RMSTPCR2 (CPG_BASE + 0x0118U) +/* Realtime Module Stop Control Register 3 */ +#define RMSTPCR3 (CPG_BASE + 0x011CU) +/* Realtime Module Stop Control Register 4 */ +#define RMSTPCR4 (CPG_BASE + 0x0120U) +/* Realtime Module Stop Control Register 5 */ +#define RMSTPCR5 (CPG_BASE + 0x0124U) +/* Realtime Module Stop Control Register 6 */ +#define RMSTPCR6 (CPG_BASE + 0x0128U) +/* Realtime Module Stop Control Register 7 */ +#define RMSTPCR7 (CPG_BASE + 0x012CU) +/* Realtime Module Stop Control Register 8 */ +#define RMSTPCR8 (CPG_BASE + 0x0980U) +/* Realtime Module Stop Control Register 9 */ +#define RMSTPCR9 (CPG_BASE + 0x0984U) +/* Realtime Module Stop Control Register 10 */ +#define RMSTPCR10 (CPG_BASE + 0x0988U) +/* Realtime Module Stop Control Register 11 */ +#define RMSTPCR11 (CPG_BASE + 0x098CU) + +/* CPG (SYSTEM) registers */ + +/* System Module Stop Control Register 0 */ +#define SMSTPCR0 (CPG_BASE + 0x0130U) +/* System Module Stop Control Register 1 */ +#define SMSTPCR1 (CPG_BASE + 0x0134U) +/* System Module Stop Control Register 2 */ +#define SMSTPCR2 (CPG_BASE + 0x0138U) +/* System Module Stop Control Register 3 */ +#define SMSTPCR3 (CPG_BASE + 0x013CU) +/* System Module Stop Control Register 4 */ +#define SMSTPCR4 (CPG_BASE + 0x0140U) +/* System Module Stop Control Register 5 */ +#define SMSTPCR5 (CPG_BASE + 0x0144U) +/* System Module Stop Control Register 6 */ +#define SMSTPCR6 (CPG_BASE + 0x0148U) +/* System Module Stop Control Register 7 */ +#define SMSTPCR7 (CPG_BASE + 0x014CU) +/* System Module Stop Control Register 8 */ +#define SMSTPCR8 (CPG_BASE + 0x0990U) +/* System Module Stop Control Register 9 */ +#define SMSTPCR9 (CPG_BASE + 0x0994U) +/* System Module Stop Control Register 10 */ +#define SMSTPCR10 (CPG_BASE + 0x0998U) +/* System Module Stop Control Register 11 */ +#define SMSTPCR11 (CPG_BASE + 0x099CU) + +#endif /* CPG_REGISTERS_H */ diff --git a/arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h b/arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h new file mode 100644 index 0000000..5f49e52 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef LIFEC_REGISTERS_H +#define LIFEC_REGISTERS_H + +#define LIFEC_SEC_BASE (0xE6110000U) + +#define SEC_SRC (LIFEC_SEC_BASE + 0x0008U) +#define SEC_SEL0 (LIFEC_SEC_BASE + 0x0030U) +#define SEC_SEL1 (LIFEC_SEC_BASE + 0x0034U) +#define SEC_SEL2 (LIFEC_SEC_BASE + 0x0038U) +#define SEC_SEL3 (LIFEC_SEC_BASE + 0x003CU) +#define SEC_SEL4 (LIFEC_SEC_BASE + 0x0058U) +#define SEC_SEL5 (LIFEC_SEC_BASE + 0x005CU) +#define SEC_SEL6 (LIFEC_SEC_BASE + 0x0060U) +#define SEC_SEL7 (LIFEC_SEC_BASE + 0x0064U) +#define SEC_SEL8 (LIFEC_SEC_BASE + 0x0068U) +#define SEC_SEL9 (LIFEC_SEC_BASE + 0x006CU) +#define SEC_SEL10 (LIFEC_SEC_BASE + 0x0070U) +#define SEC_SEL11 (LIFEC_SEC_BASE + 0x0074U) +#define SEC_SEL12 (LIFEC_SEC_BASE + 0x0078U) +#define SEC_SEL13 (LIFEC_SEC_BASE + 0x007CU) +#define SEC_SEL14 (LIFEC_SEC_BASE + 0x0080U) +#define SEC_SEL15 (LIFEC_SEC_BASE + 0x0084U) +#define SEC_GRP0CR0 (LIFEC_SEC_BASE + 0x0138U) +#define SEC_GRP1CR0 (LIFEC_SEC_BASE + 0x013CU) +#define SEC_GRP0CR1 (LIFEC_SEC_BASE + 0x0140U) +#define SEC_GRP1CR1 (LIFEC_SEC_BASE + 0x0144U) +#define SEC_GRP0CR2 (LIFEC_SEC_BASE + 0x0148U) +#define SEC_GRP1CR2 (LIFEC_SEC_BASE + 0x014CU) +#define SEC_GRP0CR3 (LIFEC_SEC_BASE + 0x0150U) +#define SEC_GRP1CR3 (LIFEC_SEC_BASE + 0x0154U) +#define SEC_GRP0COND0 (LIFEC_SEC_BASE + 0x0158U) +#define SEC_GRP1COND0 (LIFEC_SEC_BASE + 0x015CU) +#define SEC_GRP0COND1 (LIFEC_SEC_BASE + 0x0160U) +#define SEC_GRP1COND1 (LIFEC_SEC_BASE + 0x0164U) +#define SEC_GRP0COND2 (LIFEC_SEC_BASE + 0x0168U) +#define SEC_GRP1COND2 (LIFEC_SEC_BASE + 0x016CU) +#define SEC_GRP0COND3 (LIFEC_SEC_BASE + 0x0170U) +#define SEC_GRP1COND3 (LIFEC_SEC_BASE + 0x0174U) +#define SEC_GRP0COND4 (LIFEC_SEC_BASE + 0x0178U) +#define SEC_GRP1COND4 (LIFEC_SEC_BASE + 0x017CU) +#define SEC_GRP0COND5 (LIFEC_SEC_BASE + 0x0180U) +#define SEC_GRP1COND5 (LIFEC_SEC_BASE + 0x0184U) +#define SEC_GRP0COND6 (LIFEC_SEC_BASE + 0x0188U) +#define SEC_GRP1COND6 (LIFEC_SEC_BASE + 0x018CU) +#define SEC_GRP0COND7 (LIFEC_SEC_BASE + 0x0190U) +#define SEC_GRP1COND7 (LIFEC_SEC_BASE + 0x0194U) +#define SEC_GRP0COND8 (LIFEC_SEC_BASE + 0x0198U) +#define SEC_GRP1COND8 (LIFEC_SEC_BASE + 0x019CU) +#define SEC_GRP0COND9 (LIFEC_SEC_BASE + 0x01A0U) +#define SEC_GRP1COND9 (LIFEC_SEC_BASE + 0x01A4U) +#define SEC_GRP0COND10 (LIFEC_SEC_BASE + 0x01A8U) +#define SEC_GRP1COND10 (LIFEC_SEC_BASE + 0x01ACU) +#define SEC_GRP0COND11 (LIFEC_SEC_BASE + 0x01B0U) +#define SEC_GRP1COND11 (LIFEC_SEC_BASE + 0x01B4U) +#define SEC_GRP0COND12 (LIFEC_SEC_BASE + 0x01B8U) +#define SEC_GRP1COND12 (LIFEC_SEC_BASE + 0x01BCU) +#define SEC_GRP0COND13 (LIFEC_SEC_BASE + 0x01C0U) +#define SEC_GRP1COND13 (LIFEC_SEC_BASE + 0x01C4U) +#define SEC_GRP0COND14 (LIFEC_SEC_BASE + 0x01C8U) +#define SEC_GRP1COND14 (LIFEC_SEC_BASE + 0x01CCU) +#define SEC_GRP0COND15 (LIFEC_SEC_BASE + 0x01D0U) +#define SEC_GRP1COND15 (LIFEC_SEC_BASE + 0x01D4U) +#define SEC_READONLY0 (LIFEC_SEC_BASE + 0x01D8U) +#define SEC_READONLY1 (LIFEC_SEC_BASE + 0x01DCU) +#define SEC_READONLY2 (LIFEC_SEC_BASE + 0x01E0U) +#define SEC_READONLY3 (LIFEC_SEC_BASE + 0x01E4U) +#define SEC_READONLY4 (LIFEC_SEC_BASE + 0x01E8U) +#define SEC_READONLY5 (LIFEC_SEC_BASE + 0x01ECU) +#define SEC_READONLY6 (LIFEC_SEC_BASE + 0x01F0U) +#define SEC_READONLY7 (LIFEC_SEC_BASE + 0x01F4U) +#define SEC_READONLY8 (LIFEC_SEC_BASE + 0x01F8U) +#define SEC_READONLY9 (LIFEC_SEC_BASE + 0x01FCU) +#define SEC_READONLY10 (LIFEC_SEC_BASE + 0x0200U) +#define SEC_READONLY11 (LIFEC_SEC_BASE + 0x0204U) +#define SEC_READONLY12 (LIFEC_SEC_BASE + 0x0208U) +#define SEC_READONLY13 (LIFEC_SEC_BASE + 0x020CU) +#define SEC_READONLY14 (LIFEC_SEC_BASE + 0x0210U) +#define SEC_READONLY15 (LIFEC_SEC_BASE + 0x0214U) + +#define LIFEC_SAFE_BASE (0xE6120000U) +#define SAFE_GRP0CR0 (LIFEC_SAFE_BASE + 0x0138U) +#define SAFE_GRP1CR0 (LIFEC_SAFE_BASE + 0x013CU) +#define SAFE_GRP0CR1 (LIFEC_SAFE_BASE + 0x0140U) +#define SAFE_GRP1CR1 (LIFEC_SAFE_BASE + 0x0144U) +#define SAFE_GRP0CR2 (LIFEC_SAFE_BASE + 0x0148U) +#define SAFE_GRP1CR2 (LIFEC_SAFE_BASE + 0x014CU) +#define SAFE_GRP0CR3 (LIFEC_SAFE_BASE + 0x0150U) +#define SAFE_GRP1CR3 (LIFEC_SAFE_BASE + 0x0154U) +#define SAFE_GRP0COND0 (LIFEC_SAFE_BASE + 0x0158U) +#define SAFE_GRP1COND0 (LIFEC_SAFE_BASE + 0x015CU) +#define SAFE_GRP0COND1 (LIFEC_SAFE_BASE + 0x0160U) +#define SAFE_GRP1COND1 (LIFEC_SAFE_BASE + 0x0164U) +#define SAFE_GRP0COND2 (LIFEC_SAFE_BASE + 0x0168U) +#define SAFE_GRP1COND2 (LIFEC_SAFE_BASE + 0x016CU) +#define SAFE_GRP0COND3 (LIFEC_SAFE_BASE + 0x0170U) +#define SAFE_GRP1COND3 (LIFEC_SAFE_BASE + 0x0174U) +#define SAFE_GRP0COND4 (LIFEC_SAFE_BASE + 0x0178U) +#define SAFE_GRP1COND4 (LIFEC_SAFE_BASE + 0x017CU) +#define SAFE_GRP0COND5 (LIFEC_SAFE_BASE + 0x0180U) +#define SAFE_GRP1COND5 (LIFEC_SAFE_BASE + 0x0184U) +#define SAFE_GRP0COND6 (LIFEC_SAFE_BASE + 0x0188U) +#define SAFE_GRP1COND6 (LIFEC_SAFE_BASE + 0x018CU) +#define SAFE_GRP0COND7 (LIFEC_SAFE_BASE + 0x0190U) +#define SAFE_GRP1COND7 (LIFEC_SAFE_BASE + 0x0194U) +#define SAFE_GRP0COND8 (LIFEC_SAFE_BASE + 0x0198U) +#define SAFE_GRP1COND8 (LIFEC_SAFE_BASE + 0x019CU) +#define SAFE_GRP0COND9 (LIFEC_SAFE_BASE + 0x01A0U) +#define SAFE_GRP1COND9 (LIFEC_SAFE_BASE + 0x01A4U) +#define SAFE_GRP0COND10 (LIFEC_SAFE_BASE + 0x01A8U) +#define SAFE_GRP1COND10 (LIFEC_SAFE_BASE + 0x01ACU) +#define SAFE_GRP0COND11 (LIFEC_SAFE_BASE + 0x01B0U) +#define SAFE_GRP1COND11 (LIFEC_SAFE_BASE + 0x01B4U) +#define SAFE_GRP0COND12 (LIFEC_SAFE_BASE + 0x01B8U) +#define SAFE_GRP1COND12 (LIFEC_SAFE_BASE + 0x01BCU) +#define SAFE_GRP0COND13 (LIFEC_SAFE_BASE + 0x01C0U) +#define SAFE_GRP1COND13 (LIFEC_SAFE_BASE + 0x01C4U) +#define SAFE_GRP0COND14 (LIFEC_SAFE_BASE + 0x01C8U) +#define SAFE_GRP1COND14 (LIFEC_SAFE_BASE + 0x01CCU) +#define SAFE_GRP0COND15 (LIFEC_SAFE_BASE + 0x01D0U) +#define SAFE_GRP1COND15 (LIFEC_SAFE_BASE + 0x01D4U) +#define SAFE_READONLY0 (LIFEC_SAFE_BASE + 0x01D8U) +#define SAFE_READONLY1 (LIFEC_SAFE_BASE + 0x01DCU) +#define SAFE_READONLY2 (LIFEC_SAFE_BASE + 0x01E0U) +#define SAFE_READONLY3 (LIFEC_SAFE_BASE + 0x01E4U) +#define SAFE_READONLY4 (LIFEC_SAFE_BASE + 0x01E8U) +#define SAFE_READONLY5 (LIFEC_SAFE_BASE + 0x01ECU) +#define SAFE_READONLY6 (LIFEC_SAFE_BASE + 0x01F0U) +#define SAFE_READONLY7 (LIFEC_SAFE_BASE + 0x01F4U) +#define SAFE_READONLY8 (LIFEC_SAFE_BASE + 0x01F8U) +#define SAFE_READONLY9 (LIFEC_SAFE_BASE + 0x01FCU) +#define SAFE_READONLY10 (LIFEC_SAFE_BASE + 0x0200U) +#define SAFE_READONLY11 (LIFEC_SAFE_BASE + 0x0204U) +#define SAFE_READONLY12 (LIFEC_SAFE_BASE + 0x0208U) +#define SAFE_READONLY13 (LIFEC_SAFE_BASE + 0x020CU) +#define SAFE_READONLY14 (LIFEC_SAFE_BASE + 0x0210U) +#define SAFE_READONLY15 (LIFEC_SAFE_BASE + 0x0214U) + +#endif /* LIFEC_REGISTERS_H */ diff --git a/arm-trusted-firmware/plat/renesas/common/plat_image_load.c b/arm-trusted-firmware/plat/renesas/common/plat_image_load.c new file mode 100644 index 0000000..9d814a6 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/plat_image_load.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +extern void bl2_plat_flush_bl31_params(void); + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ +#if IMAGE_BL2 + bl2_plat_flush_bl31_params(); +#endif +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/renesas/common/plat_pm.c b/arm-trusted-firmware/plat/renesas/common/plat_pm.c new file mode 100644 index 0000000..9810596 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/plat_pm.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iic_dvfs.h" +#include "platform_def.h" +#include "pwrc.h" +#include "rcar_def.h" +#include "rcar_private.h" +#if RCAR_GEN3_ULCB +#include "ulcb_cpld.h" +#endif /* RCAR_GEN3_ULCB */ + +#define DVFS_SET_VID_0V (0x00) +#define P_ALL_OFF (0x80) +#define KEEPON_DDR1C (0x08) +#define KEEPON_DDR0C (0x04) +#define KEEPON_DDR1 (0x02) +#define KEEPON_DDR0 (0x01) + +#define SYSTEM_PWR_STATE(s) ((s)->pwr_domain_state[PLAT_MAX_PWR_LVL]) +#define CLUSTER_PWR_STATE(s) ((s)->pwr_domain_state[MPIDR_AFFLVL1]) +#define CORE_PWR_STATE(s) ((s)->pwr_domain_state[MPIDR_AFFLVL0]) + +extern void rcar_pwrc_restore_generic_timer(uint64_t *stack); +extern void plat_rcar_gic_driver_init(void); +extern void plat_rcar_gic_init(void); + +static uintptr_t rcar_sec_entrypoint; + +static void rcar_program_mailbox(u_register_t mpidr, uintptr_t address) +{ + mailbox_t *rcar_mboxes = (mailbox_t *) MBOX_BASE; + uint64_t linear_id = plat_core_pos_by_mpidr(mpidr); + unsigned long range; + + rcar_mboxes[linear_id].value = address; + range = (unsigned long)&rcar_mboxes[linear_id]; + + flush_dcache_range(range, sizeof(range)); +} + +static void rcar_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr_el3 = read_scr_el3(); + + write_scr_el3(scr_el3 | SCR_IRQ_BIT); + dsb(); + wfi(); + write_scr_el3(scr_el3); +} + +static int rcar_pwr_domain_on(u_register_t mpidr) +{ + rcar_program_mailbox(mpidr, rcar_sec_entrypoint); + rcar_pwrc_cpuon(mpidr); + + return PSCI_E_SUCCESS; +} + +static void rcar_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + uint32_t cluster_type = rcar_pwrc_get_cluster(); + u_register_t mpidr = read_mpidr_el1(); + + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + if (cluster_type == RCAR_CLUSTER_A53A57) + plat_cci_enable(); + + rcar_program_mailbox(mpidr, 0); + rcar_pwrc_enable_interrupt_wakeup(mpidr); + + gicv2_cpuif_enable(); + gicv2_pcpu_distif_init(); +} + +static void rcar_pwr_domain_off(const psci_power_state_t *target_state) +{ +#if RCAR_LSI != RCAR_D3 + uint32_t cluster_type = rcar_pwrc_get_cluster(); +#endif + u_register_t mpidr = read_mpidr_el1(); + + rcar_pwrc_disable_interrupt_wakeup(mpidr); + gicv2_cpuif_disable(); + rcar_pwrc_cpuoff(mpidr); + +#if RCAR_LSI != RCAR_D3 + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + if (cluster_type == RCAR_CLUSTER_A53A57) + plat_cci_disable(); + + rcar_pwrc_clusteroff(mpidr); + } +#endif +} + +static void rcar_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + uint32_t cluster_type = rcar_pwrc_get_cluster(); + u_register_t mpidr = read_mpidr_el1(); + + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + rcar_program_mailbox(mpidr, rcar_sec_entrypoint); + rcar_pwrc_enable_interrupt_wakeup(mpidr); + gicv2_cpuif_disable(); + rcar_pwrc_cpuoff(mpidr); + + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + if (cluster_type == RCAR_CLUSTER_A53A57) + plat_cci_disable(); + + rcar_pwrc_clusteroff(mpidr); + } +} + +static void rcar_pwr_domain_suspend_finish(const psci_power_state_t + *target_state) +{ + uint32_t cluster_type = rcar_pwrc_get_cluster(); + + if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + goto finish; + + plat_rcar_gic_driver_init(); + plat_rcar_gic_init(); + + if (cluster_type == RCAR_CLUSTER_A53A57) + plat_cci_init(); + + rcar_pwrc_restore_timer_state(); + rcar_pwrc_setup(); + rcar_pwrc_code_copy_to_system_ram(); + +#if RCAR_SYSTEM_SUSPEND + rcar_pwrc_init_suspend_to_ram(); +#endif +finish: + rcar_pwr_domain_on_finish(target_state); +} + +static void __dead2 rcar_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ +#if RCAR_SYSTEM_SUSPEND + if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + rcar_pwrc_suspend_to_ram(); +#endif + wfi(); + + ERROR("RCAR Power Down: operation not handled.\n"); + panic(); +} + +static void __dead2 rcar_system_off(void) +{ +#if PMIC_ROHM_BD9571 +#if PMIC_LEVEL_MODE + if (rcar_iic_dvfs_send(PMIC, DVFS_SET_VID, DVFS_SET_VID_0V)) + ERROR("BL3-1:Failed the SYSTEM-OFF.\n"); +#else + if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF)) + ERROR("BL3-1:Failed the SYSTEM-RESET.\n"); +#endif +#else + u_register_t mpidr = read_mpidr_el1(); + u_register_t cpu = mpidr & 0x0000ffffU; + int32_t rtn_on; + + rtn_on = rcar_pwrc_cpu_on_check(mpidr); + + if (cpu != rcar_boot_mpidr) { + panic(); + } + + if (rtn_on != 0) { + panic(); + } + + rcar_pwrc_cpuoff(mpidr); + rcar_pwrc_clusteroff(mpidr); + +#endif /* PMIC_ROHM_BD9571 */ + wfi(); + ERROR("RCAR System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 rcar_system_reset(void) +{ +#if PMIC_ROHM_BD9571 +#if PMIC_LEVEL_MODE +#if RCAR_SYSTEM_RESET_KEEPON_DDR + uint8_t mode; + int32_t error; + + error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, KEEP10_MAGIC); + if (error) { + ERROR("Failed send KEEP10 magic ret=%d\n", error); + goto done; + } + + error = rcar_iic_dvfs_receive(PMIC, BKUP_MODE_CNT, &mode); + if (error) { + ERROR("Failed receive BKUP_Mode_Cnt ret=%d\n", error); + goto done; + } + + mode |= KEEPON_DDR1C | KEEPON_DDR0C | KEEPON_DDR1 | KEEPON_DDR0; + error = rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, mode); + if (error) { + ERROR("Failed send KEEPON_DDRx ret=%d\n", error); + goto done; + } + + rcar_pwrc_set_suspend_to_ram(); +done: +#else + if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF)) + ERROR("BL3-1:Failed the SYSTEM-RESET.\n"); +#endif +#else +#if (RCAR_GEN3_ULCB == 1) + rcar_cpld_reset_cpu(); +#endif +#endif +#else + rcar_pwrc_system_reset(); +#endif + wfi(); + + ERROR("RCAR System Reset: operation not handled.\n"); + panic(); +} + +static int rcar_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + unsigned int pstate = psci_get_pstate_type(power_state); + uint32_t i; + + if (pstate == PSTATE_TYPE_STANDBY) { + if (pwr_lvl != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + } else { + for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } + + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +#if RCAR_SYSTEM_SUSPEND +static void rcar_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + u_register_t mpidr = read_mpidr_el1() & 0x0000ffffU; + int i; + + if (mpidr != rcar_boot_mpidr) + goto deny; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + + return; +deny: + /* deny system suspend entry */ + req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PSCI_LOCAL_STATE_RUN; + for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; +} +#endif + +static const plat_psci_ops_t rcar_plat_psci_ops = { + .cpu_standby = rcar_cpu_standby, + .pwr_domain_on = rcar_pwr_domain_on, + .pwr_domain_off = rcar_pwr_domain_off, + .pwr_domain_suspend = rcar_pwr_domain_suspend, + .pwr_domain_on_finish = rcar_pwr_domain_on_finish, + .pwr_domain_suspend_finish = rcar_pwr_domain_suspend_finish, + .system_off = rcar_system_off, + .system_reset = rcar_system_reset, + .validate_power_state = rcar_validate_power_state, + .pwr_domain_pwr_down_wfi = rcar_pwr_domain_pwr_down_wfi, +#if RCAR_SYSTEM_SUSPEND + .get_sys_suspend_power_state = rcar_get_sys_suspend_power_state, +#endif +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &rcar_plat_psci_ops; + rcar_sec_entrypoint = sec_entrypoint; + +#if RCAR_SYSTEM_SUSPEND + rcar_pwrc_init_suspend_to_ram(); +#endif + return 0; +} + diff --git a/arm-trusted-firmware/plat/renesas/common/plat_storage.c b/arm-trusted-firmware/plat/renesas/common/plat_storage.c new file mode 100644 index 0000000..6524561 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/plat_storage.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include "io_common.h" +#include "io_memdrv.h" +#include "io_emmcdrv.h" +#include "io_private.h" +#include "io_rcar.h" +#include + +static uintptr_t emmcdrv_dev_handle; +static uintptr_t memdrv_dev_handle; +static uintptr_t rcar_dev_handle; + +static uintptr_t boot_io_drv_id; + +static const io_block_spec_t rcar_block_spec = { + .offset = FLASH0_BASE, + .length = FLASH0_SIZE +}; + +static const io_block_spec_t bl2_file_spec = { + .offset = BL2_IMAGE_ID, +}; + +static const io_block_spec_t bl31_file_spec = { + .offset = BL31_IMAGE_ID, +}; + +static const io_block_spec_t bl32_file_spec = { + .offset = BL32_IMAGE_ID, +}; + +static const io_block_spec_t bl33_file_spec = { + .offset = BL33_IMAGE_ID, +}; + +static const io_block_spec_t bl332_file_spec = { + .offset = BL332_IMAGE_ID, +}; + +static const io_block_spec_t bl333_file_spec = { + .offset = BL333_IMAGE_ID, +}; + +static const io_block_spec_t bl334_file_spec = { + .offset = BL334_IMAGE_ID, +}; + +static const io_block_spec_t bl335_file_spec = { + .offset = BL335_IMAGE_ID, +}; + +static const io_block_spec_t bl336_file_spec = { + .offset = BL336_IMAGE_ID, +}; + +static const io_block_spec_t bl337_file_spec = { + .offset = BL337_IMAGE_ID, +}; + +static const io_block_spec_t bl338_file_spec = { + .offset = BL338_IMAGE_ID, +}; + +#if TRUSTED_BOARD_BOOT +static const io_block_spec_t trusted_key_cert_file_spec = { + .offset = TRUSTED_KEY_CERT_ID, +}; + +static const io_block_spec_t bl31_key_cert_file_spec = { + .offset = SOC_FW_KEY_CERT_ID, +}; + +static const io_block_spec_t bl32_key_cert_file_spec = { + .offset = TRUSTED_OS_FW_KEY_CERT_ID, +}; + +static const io_block_spec_t bl33_key_cert_file_spec = { + .offset = NON_TRUSTED_FW_KEY_CERT_ID, +}; + +static const io_block_spec_t bl332_key_cert_file_spec = { + .offset = BL332_KEY_CERT_ID, +}; + +static const io_block_spec_t bl333_key_cert_file_spec = { + .offset = BL333_KEY_CERT_ID, +}; + +static const io_block_spec_t bl334_key_cert_file_spec = { + .offset = BL334_KEY_CERT_ID, +}; + +static const io_block_spec_t bl335_key_cert_file_spec = { + .offset = BL335_KEY_CERT_ID, +}; + +static const io_block_spec_t bl336_key_cert_file_spec = { + .offset = BL336_KEY_CERT_ID, +}; + +static const io_block_spec_t bl337_key_cert_file_spec = { + .offset = BL337_KEY_CERT_ID, +}; + +static const io_block_spec_t bl338_key_cert_file_spec = { + .offset = BL338_KEY_CERT_ID, +}; + +static const io_block_spec_t bl31_cert_file_spec = { + .offset = SOC_FW_CONTENT_CERT_ID, +}; + +static const io_block_spec_t bl32_cert_file_spec = { + .offset = TRUSTED_OS_FW_CONTENT_CERT_ID, +}; + +static const io_block_spec_t bl33_cert_file_spec = { + .offset = NON_TRUSTED_FW_CONTENT_CERT_ID, +}; + +static const io_block_spec_t bl332_cert_file_spec = { + .offset = BL332_CERT_ID, +}; + +static const io_block_spec_t bl333_cert_file_spec = { + .offset = BL333_CERT_ID, +}; + +static const io_block_spec_t bl334_cert_file_spec = { + .offset = BL334_CERT_ID, +}; + +static const io_block_spec_t bl335_cert_file_spec = { + .offset = BL335_CERT_ID, +}; + +static const io_block_spec_t bl336_cert_file_spec = { + .offset = BL336_CERT_ID, +}; + +static const io_block_spec_t bl337_cert_file_spec = { + .offset = BL337_CERT_ID, +}; + +static const io_block_spec_t bl338_cert_file_spec = { + .offset = BL338_CERT_ID, +}; +#endif + +static int32_t open_emmcdrv(const uintptr_t spec); +static int32_t open_memmap(const uintptr_t spec); +static int32_t open_rcar(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[] = { + [FIP_IMAGE_ID] = { + &memdrv_dev_handle, + (uintptr_t) &rcar_block_spec, + &open_memmap}, + [BL2_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl2_file_spec, + &open_rcar}, + [BL31_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl31_file_spec, + &open_rcar}, + [BL32_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl32_file_spec, + &open_rcar}, + [BL33_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl33_file_spec, + &open_rcar}, + [BL332_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl332_file_spec, + &open_rcar}, + [BL333_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl333_file_spec, + &open_rcar}, + [BL334_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl334_file_spec, + &open_rcar}, + [BL335_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl335_file_spec, + &open_rcar}, + [BL336_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl336_file_spec, + &open_rcar}, + [BL337_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl337_file_spec, + &open_rcar}, + [BL338_IMAGE_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl338_file_spec, + &open_rcar}, +#if TRUSTED_BOARD_BOOT + [TRUSTED_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &trusted_key_cert_file_spec, + &open_rcar}, + [SOC_FW_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl31_key_cert_file_spec, + &open_rcar}, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl32_key_cert_file_spec, + &open_rcar}, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl33_key_cert_file_spec, + &open_rcar}, + [BL332_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl332_key_cert_file_spec, + &open_rcar}, + [BL333_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl333_key_cert_file_spec, + &open_rcar}, + [BL334_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl334_key_cert_file_spec, + &open_rcar}, + [BL335_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl335_key_cert_file_spec, + &open_rcar}, + [BL336_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl336_key_cert_file_spec, + &open_rcar}, + [BL337_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl337_key_cert_file_spec, + &open_rcar}, + [BL338_KEY_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl338_key_cert_file_spec, + &open_rcar}, + [SOC_FW_CONTENT_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl31_cert_file_spec, + &open_rcar}, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl32_cert_file_spec, + &open_rcar}, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl33_cert_file_spec, + &open_rcar}, + [BL332_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl332_cert_file_spec, + &open_rcar}, + [BL333_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl333_cert_file_spec, + &open_rcar}, + [BL334_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl334_cert_file_spec, + &open_rcar}, + [BL335_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl335_cert_file_spec, + &open_rcar}, + [BL336_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl336_cert_file_spec, + &open_rcar}, + [BL337_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl337_cert_file_spec, + &open_rcar}, + [BL338_CERT_ID] = { + &rcar_dev_handle, + (uintptr_t) &bl338_cert_file_spec, + &open_rcar}, { +#else + { +#endif + 0, 0, 0} +}; + +static io_drv_spec_t io_drv_spec_memdrv = { + FLASH0_BASE, + FLASH0_SIZE, + 0, +}; + +static io_drv_spec_t io_drv_spec_emmcdrv = { + 0, + 0, + 0, +}; + +static struct plat_io_policy drv_policies[] __attribute__ ((section(".data"))) = { + /* FLASH_DEV_ID */ + { &memdrv_dev_handle, (uintptr_t) &io_drv_spec_memdrv, &open_memmap, }, + /* EMMC_DEV_ID */ + { &emmcdrv_dev_handle, (uintptr_t) &io_drv_spec_emmcdrv, &open_emmcdrv, } +}; + +static int32_t open_rcar(const uintptr_t spec) +{ + return io_dev_init(rcar_dev_handle, boot_io_drv_id); +} + +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 != IO_SUCCESS) + return result; + + result = io_open(memdrv_dev_handle, spec, &handle); + if (result == IO_SUCCESS) + io_close(handle); + + return result; +} + +static int32_t open_emmcdrv(const uintptr_t spec) +{ + return io_dev_init(emmcdrv_dev_handle, 0); +} + +void rcar_io_setup(void) +{ + const io_dev_connector_t *memmap; + const io_dev_connector_t *rcar; + + boot_io_drv_id = FLASH_DEV_ID; + + rcar_register_io_dev(&rcar); + rcar_register_io_dev_memdrv(&memmap); + io_dev_open(rcar, 0, &rcar_dev_handle); + io_dev_open(memmap, 0, &memdrv_dev_handle); +} + +void rcar_io_emmc_setup(void) +{ + const io_dev_connector_t *rcar; + const io_dev_connector_t *emmc; + + boot_io_drv_id = EMMC_DEV_ID; + + rcar_register_io_dev(&rcar); + rcar_register_io_dev_emmcdrv(&emmc); + io_dev_open(rcar, 0, &rcar_dev_handle); + io_dev_open(emmc, 0, &emmcdrv_dev_handle); +} + +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 != IO_SUCCESS) + return result; + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return IO_SUCCESS; +} + +int32_t plat_get_drv_source(uint32_t io_drv_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + const struct plat_io_policy *policy; + int32_t result; + + policy = &drv_policies[io_drv_id]; + + result = policy->check(policy->image_spec); + if (result != IO_SUCCESS) + return result; + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return IO_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/renesas/common/plat_topology.c b/arm-trusted-firmware/plat/renesas/common/plat_topology.c new file mode 100644 index 0000000..0d5880d --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/plat_topology.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +static const unsigned char rcar_power_domain_tree_desc[] = { + 1, + PLATFORM_CLUSTER_COUNT, + PLATFORM_CLUSTER0_CORE_COUNT, + PLATFORM_CLUSTER1_CORE_COUNT +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rcar_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + if (cluster_id == 0 && cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT) + return -1; + + if (cluster_id == 1 && cpu_id >= PLATFORM_CLUSTER1_CORE_COUNT) + return -1; + + return (cpu_id + cluster_id * PLATFORM_CLUSTER0_CORE_COUNT); +} + diff --git a/arm-trusted-firmware/plat/renesas/common/rcar_common.c b/arm-trusted-firmware/plat/renesas/common/rcar_common.c new file mode 100644 index 0000000..df4c30c --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/rcar_common.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2019-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#define MSTP318 (1 << 18) +#define MSTP319 (1 << 19) +#define PMSR 0x5c +#define PMSR_L1FAEG (1U << 31) +#define PMSR_PMEL1RX (1 << 23) +#define PMCTLR 0x60 +#define PMSR_L1IATN (1U << 31) + +static int rcar_pcie_fixup(unsigned int controller) +{ + uint32_t rcar_pcie_base[] = { 0xfe011000, 0xee811000 }; + uint32_t addr = rcar_pcie_base[controller]; + uint32_t cpg, pmsr; + int ret = 0; + + /* Test if PCIECx is enabled */ + cpg = mmio_read_32(CPG_MSTPSR3); + if (cpg & (MSTP318 << !controller)) + return ret; + + pmsr = mmio_read_32(addr + PMSR); + + if ((pmsr & PMSR_PMEL1RX) && ((pmsr & 0x70000) != 0x30000)) { + /* Fix applicable */ + mmio_write_32(addr + PMCTLR, PMSR_L1IATN); + while (!(mmio_read_32(addr + PMSR) & PMSR_L1FAEG)) + ; + mmio_write_32(addr + PMSR, PMSR_L1FAEG | PMSR_PMEL1RX); + ret = 1; + } + + return ret; +} + +/* 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) +{ + unsigned int fixed = 0; + + fixed |= rcar_pcie_fixup(0); + fixed |= rcar_pcie_fixup(1); + + if (fixed) + return; + + plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags); +} + +#include + +static console_t rcar_boot_console; +static console_t rcar_runtime_console; + +void rcar_console_boot_init(void) +{ + int ret; + + ret = console_rcar_register(0, 0, 0, &rcar_boot_console); + if (!ret) + panic(); + + console_set_scope(&rcar_boot_console, CONSOLE_FLAG_BOOT); +} + +void rcar_console_boot_end(void) +{ +} + +void rcar_console_runtime_init(void) +{ + int ret; + + ret = console_rcar_register(1, 0, 0, &rcar_runtime_console); + if (!ret) + panic(); + + console_set_scope(&rcar_boot_console, CONSOLE_FLAG_RUNTIME); +} + +void rcar_console_runtime_end(void) +{ +} diff --git a/arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c b/arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c new file mode 100644 index 0000000..bbfa169 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c @@ -0,0 +1,1199 @@ +/* + * Copyright (c) 2018-2021, 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 +#if RCAR_GEN3_BL33_GZIP == 1 +#include +#endif + +#include "avs_driver.h" +#include "boot_init_dram.h" +#include "cpg_registers.h" +#include "board.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_std.h" + +#if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR +#include "iic_dvfs.h" +#endif + +#include "io_common.h" +#include "io_rcar.h" +#include "qos_init.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_version.h" +#include "rom_api.h" + +#if RCAR_BL2_DCACHE == 1 +/* + * Following symbols are only used during plat_arch_setup() only + * when RCAR_BL2_DCACHE is enabled. + */ +static const uint64_t BL2_RO_BASE = BL_CODE_BASE; +static const uint64_t BL2_RO_LIMIT = BL_CODE_END; + +#if USE_COHERENT_MEM +static const uint64_t BL2_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE; +static const uint64_t BL2_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END; +#endif + +#endif + +extern void plat_rcar_gic_driver_init(void); +extern void plat_rcar_gic_init(void); +extern void bl2_enter_bl31(const struct entry_point_info *bl_ep_info); +extern void bl2_system_cpg_init(void); +extern void bl2_secure_setting(void); +extern void bl2_cpg_init(void); +extern void rcar_io_emmc_setup(void); +extern void rcar_io_setup(void); +extern void rcar_swdt_release(void); +extern void rcar_swdt_init(void); +extern void rcar_rpc_init(void); +extern void rcar_pfc_init(void); +extern void rcar_dma_init(void); + +static void bl2_init_generic_timer(void); + +/* R-Car Gen3 product check */ +#if (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) +#define TARGET_PRODUCT PRR_PRODUCT_H3 +#define TARGET_NAME "R-Car H3" +#elif RCAR_LSI == RCAR_M3 +#define TARGET_PRODUCT PRR_PRODUCT_M3 +#define TARGET_NAME "R-Car M3" +#elif RCAR_LSI == RCAR_M3N +#define TARGET_PRODUCT PRR_PRODUCT_M3N +#define TARGET_NAME "R-Car M3N" +#elif RCAR_LSI == RCAR_V3M +#define TARGET_PRODUCT PRR_PRODUCT_V3M +#define TARGET_NAME "R-Car V3M" +#elif RCAR_LSI == RCAR_E3 +#define TARGET_PRODUCT PRR_PRODUCT_E3 +#define TARGET_NAME "R-Car E3" +#elif RCAR_LSI == RCAR_D3 +#define TARGET_PRODUCT PRR_PRODUCT_D3 +#define TARGET_NAME "R-Car D3" +#elif RCAR_LSI == RCAR_AUTO +#define TARGET_NAME "R-Car H3/M3/M3N/V3M" +#endif + +#if (RCAR_LSI == RCAR_E3) +#define GPIO_INDT (GPIO_INDT6) +#define GPIO_BKUP_TRG_SHIFT ((uint32_t)1U<<13U) +#else +#define GPIO_INDT (GPIO_INDT1) +#define GPIO_BKUP_TRG_SHIFT ((uint32_t)1U<<8U) +#endif + +CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t) + 0x100) + < (RCAR_SHARED_MEM_BASE + RCAR_SHARED_MEM_SIZE), + assert_bl31_params_do_not_fit_in_shared_memory); + +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/* FDT with DRAM configuration */ +uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)]; +static void *fdt = (void *)fdt_blob; + +static void unsigned_num_print(unsigned long long int unum, unsigned int radix, + char *string) +{ + /* Just need enough space to store 64 bit decimal integer */ + char num_buf[20]; + int i = 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); + + while (--i >= 0) + *string++ = num_buf[i]; + *string = 0; +} + +#if (RCAR_LOSSY_ENABLE == 1) +typedef struct bl2_lossy_info { + uint32_t magic; + uint32_t a0; + uint32_t b0; +} bl2_lossy_info_t; + +static void bl2_lossy_gen_fdt(uint32_t no, uint64_t start_addr, + uint64_t end_addr, uint32_t format, + uint32_t enable, int fcnlnode) +{ + const uint64_t fcnlsize = cpu_to_fdt64(end_addr - start_addr); + char nodename[40] = { 0 }; + int ret, node; + + /* Ignore undefined addresses */ + if (start_addr == 0 && end_addr == 0) + return; + + snprintf(nodename, sizeof(nodename), "lossy-decompression@"); + unsigned_num_print(start_addr, 16, nodename + strlen(nodename)); + + node = ret = fdt_add_subnode(fdt, fcnlnode, nodename); + if (ret < 0) { + NOTICE("BL2: Cannot create FCNL node (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop_string(fdt, node, "compatible", + "renesas,lossy-decompression"); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL compat string (ret=%i)\n", ret); + panic(); + } + + ret = fdt_appendprop_string(fdt, node, "compatible", + "shared-dma-pool"); + if (ret < 0) { + NOTICE("BL2: Cannot append FCNL compat string (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop_u64(fdt, node, "reg", start_addr); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL reg prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_appendprop(fdt, node, "reg", &fcnlsize, sizeof(fcnlsize)); + if (ret < 0) { + NOTICE("BL2: Cannot append FCNL reg size prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop(fdt, node, "no-map", NULL, 0); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL no-map prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop_u32(fdt, node, "renesas,formats", format); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL formats prop (ret=%i)\n", ret); + panic(); + } +} + +static void bl2_lossy_setting(uint32_t no, uint64_t start_addr, + uint64_t end_addr, uint32_t format, + uint32_t enable, int fcnlnode) +{ + bl2_lossy_info_t info; + uint32_t reg; + + bl2_lossy_gen_fdt(no, start_addr, end_addr, format, enable, fcnlnode); + + reg = format | (start_addr >> 20); + mmio_write_32(AXI_DCMPAREACRA0 + 0x8 * no, reg); + mmio_write_32(AXI_DCMPAREACRB0 + 0x8 * no, end_addr >> 20); + mmio_write_32(AXI_DCMPAREACRA0 + 0x8 * no, reg | enable); + + info.magic = 0x12345678U; + info.a0 = mmio_read_32(AXI_DCMPAREACRA0 + 0x8 * no); + info.b0 = mmio_read_32(AXI_DCMPAREACRB0 + 0x8 * no); + + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no, info.magic); + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x4, info.a0); + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x8, info.b0); + + NOTICE(" Entry %d: DCMPAREACRAx:0x%x DCMPAREACRBx:0x%x\n", no, + mmio_read_32(AXI_DCMPAREACRA0 + 0x8 * no), + mmio_read_32(AXI_DCMPAREACRB0 + 0x8 * no)); +} +#endif + +void bl2_plat_flush_bl31_params(void) +{ + uint32_t product_cut, product, cut; + uint32_t boot_dev, boot_cpu; + uint32_t lcs, reg, val; + + reg = mmio_read_32(RCAR_MODEMR); + boot_dev = reg & MODEMR_BOOT_DEV_MASK; + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) + emmc_terminate(); + + if ((reg & MODEMR_BOOT_CPU_MASK) != MODEMR_BOOT_CPU_CR7) + bl2_secure_setting(); + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + if (product == PRR_PRODUCT_M3 && PRR_PRODUCT_30 > cut) + goto tlb; + + if (product == PRR_PRODUCT_H3 && PRR_PRODUCT_20 > cut) + goto tlb; + + /* Disable MFIS write protection */ + mmio_write_32(MFISWPCNTR, MFISWPCNTR_PASSWORD | 1); + +tlb: + reg = mmio_read_32(RCAR_MODEMR); + boot_cpu = reg & MODEMR_BOOT_CPU_MASK; + if (boot_cpu != MODEMR_BOOT_CPU_CA57 && + boot_cpu != MODEMR_BOOT_CPU_CA53) + goto mmu; + + if (product_cut == PRR_PRODUCT_H3_CUT20) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUVI1_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV1_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV2_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV3_IMSCTLR, IMSCTLR_DISCACHE); + } else if (product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11)) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + } else if ((product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) || + (product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_11))) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUVP0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + } + + if (product_cut == (PRR_PRODUCT_H3_CUT20) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11) || + product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) { + mmio_write_32(IPMMUHC_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMURT_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUMP_IMSCTLR, IMSCTLR_DISCACHE); + + mmio_write_32(IPMMUDS0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUDS1_IMSCTLR, IMSCTLR_DISCACHE); + } + +mmu: + mmio_write_32(IPMMUMM_IMSCTLR, IPMMUMM_IMSCTLR_ENABLE); + mmio_write_32(IPMMUMM_IMAUXCTLR, IPMMUMM_IMAUXCTLR_NMERGE40_BIT); + + val = rcar_rom_get_lcs(&lcs); + if (val) { + ERROR("BL2: Failed to get the LCS. (%d)\n", val); + panic(); + } + + if (lcs == LCS_SE) + mmio_clrbits_32(P_ARMREG_SEC_CTRL, P_ARMREG_SEC_CTRL_PROT); + + rcar_swdt_release(); + bl2_system_cpg_init(); + +#if RCAR_BL2_DCACHE == 1 + /* Disable data cache (clean and invalidate) */ + disable_mmu_el3(); +#endif +} + +static uint32_t is_ddr_backup_mode(void) +{ +#if RCAR_SYSTEM_SUSPEND + static uint32_t reason = RCAR_COLD_BOOT; + static uint32_t once; + +#if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR + uint8_t data; +#endif + if (once) + return reason; + + once = 1; + if ((mmio_read_32(GPIO_INDT) & GPIO_BKUP_TRG_SHIFT) == 0) + return reason; + +#if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR + if (rcar_iic_dvfs_receive(PMIC, REG_KEEP10, &data)) { + ERROR("BL2: REG Keep10 READ ERROR.\n"); + panic(); + } + + if (KEEP10_MAGIC != data) + reason = RCAR_WARM_BOOT; +#else + reason = RCAR_WARM_BOOT; +#endif + return reason; +#else + return RCAR_COLD_BOOT; +#endif +} + +#if RCAR_GEN3_BL33_GZIP == 1 +void bl2_plat_preload_setup(void) +{ + image_decompress_init(BL33_COMP_BASE, BL33_COMP_SIZE, gunzip); +} +#endif + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + u_register_t *boot_kind = (void *) BOOT_KIND_BASE; + bl_mem_params_node_t *bl_mem_params; + + bl_mem_params = get_bl_mem_params_node(image_id); + +#if RCAR_GEN3_BL33_GZIP == 1 + if (image_id == BL33_IMAGE_ID) { + image_decompress_prepare(&bl_mem_params->image_info); + } +#endif + + if (image_id != BL31_IMAGE_ID) + return 0; + + if (is_ddr_backup_mode() == RCAR_COLD_BOOT) + goto cold_boot; + + *boot_kind = RCAR_WARM_BOOT; + flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind)); + + console_flush(); + bl2_plat_flush_bl31_params(); + + /* will not return */ + bl2_enter_bl31(&bl_mem_params->ep_info); + +cold_boot: + *boot_kind = RCAR_COLD_BOOT; + flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind)); + + return 0; +} + +static uint64_t rcar_get_dest_addr_from_cert(uint32_t certid, uintptr_t *dest) +{ + uint32_t cert, len; + int ret; + + ret = rcar_get_certificate(certid, &cert); + if (ret) { + ERROR("%s : cert file load error", __func__); + return 1; + } + + rcar_read_certificate((uint64_t) cert, &len, dest); + + 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; + uintptr_t dest; + int ret; + + 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 BL31_IMAGE_ID: + ret = rcar_get_dest_addr_from_cert(SOC_FW_CONTENT_CERT_ID, + &dest); + if (!ret) + bl_mem_params->image_info.image_base = dest; + break; + case BL32_IMAGE_ID: + ret = rcar_get_dest_addr_from_cert(TRUSTED_OS_FW_CONTENT_CERT_ID, + &dest); + if (!ret) + bl_mem_params->image_info.image_base = dest; + + memcpy(¶ms->bl32_ep_info, &bl_mem_params->ep_info, + sizeof(entry_point_info_t)); + break; + case BL33_IMAGE_ID: +#if RCAR_GEN3_BL33_GZIP == 1 + if ((mmio_read_32(BL33_COMP_BASE) & 0xffff) == 0x8b1f) { + /* decompress gzip-compressed image */ + ret = image_decompress(&bl_mem_params->image_info); + if (ret != 0) { + return ret; + } + } else { + /* plain image, copy it in place */ + memcpy((void *)BL33_BASE, (void *)BL33_COMP_BASE, + bl_mem_params->image_info.image_size); + } +#endif + memcpy(¶ms->bl33_ep_info, &bl_mem_params->ep_info, + sizeof(entry_point_info_t)); + break; + } + + return 0; +} + +struct meminfo *bl2_plat_sec_mem_layout(void) +{ + return &bl2_tzram_layout; +} + +static void bl2_populate_compatible_string(void *dt) +{ + uint32_t board_type; + uint32_t board_rev; + uint32_t reg; + int ret; + + fdt_setprop_u32(dt, 0, "#address-cells", 2); + fdt_setprop_u32(dt, 0, "#size-cells", 2); + + /* Populate compatible string */ + rcar_get_board_type(&board_type, &board_rev); + switch (board_type) { + case BOARD_SALVATOR_X: + ret = fdt_setprop_string(dt, 0, "compatible", + "renesas,salvator-x"); + break; + case BOARD_SALVATOR_XS: + ret = fdt_setprop_string(dt, 0, "compatible", + "renesas,salvator-xs"); + break; + case BOARD_STARTER_KIT: + ret = fdt_setprop_string(dt, 0, "compatible", + "renesas,m3ulcb"); + break; + case BOARD_STARTER_KIT_PRE: + ret = fdt_setprop_string(dt, 0, "compatible", + "renesas,h3ulcb"); + break; + case BOARD_EAGLE: + ret = fdt_setprop_string(dt, 0, "compatible", + "renesas,eagle"); + break; + case BOARD_EBISU: + case BOARD_EBISU_4D: + ret = fdt_setprop_string(dt, 0, "compatible", + "renesas,ebisu"); + break; + case BOARD_DRAAK: + ret = fdt_setprop_string(dt, 0, "compatible", + "renesas,draak"); + break; + default: + NOTICE("BL2: Cannot set compatible string, board unsupported\n"); + panic(); + } + + if (ret < 0) { + NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret); + panic(); + } + + reg = mmio_read_32(RCAR_PRR); + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a7795"); + break; + case PRR_PRODUCT_M3: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a7796"); + break; + case PRR_PRODUCT_M3N: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a77965"); + break; + case PRR_PRODUCT_V3M: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a77970"); + break; + case PRR_PRODUCT_E3: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a77990"); + break; + case PRR_PRODUCT_D3: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a77995"); + break; + default: + NOTICE("BL2: Cannot set compatible string, SoC unsupported\n"); + panic(); + } + + if (ret < 0) { + NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret); + panic(); + } +} + +static void bl2_add_rpc_node(void) +{ +#if (RCAR_RPC_HYPERFLASH_LOCKED == 0) + int ret, node; + + node = ret = fdt_add_subnode(fdt, 0, "soc"); + if (ret < 0) { + goto err; + } + + node = ret = fdt_add_subnode(fdt, node, "rpc@ee200000"); + if (ret < 0) { + goto err; + } + + ret = fdt_setprop_string(fdt, node, "status", "okay"); + if (ret < 0) { + goto err; + } + + return; +err: + NOTICE("BL2: Cannot add RPC node to FDT (ret=%i)\n", ret); + panic(); +#endif +} + +static void bl2_add_dram_entry(uint64_t start, uint64_t size) +{ + char nodename[32] = { 0 }; + uint64_t fdtsize; + int ret, node; + + fdtsize = cpu_to_fdt64(size); + + snprintf(nodename, sizeof(nodename), "memory@"); + unsigned_num_print(start, 16, nodename + strlen(nodename)); + node = ret = fdt_add_subnode(fdt, 0, nodename); + if (ret < 0) { + goto err; + } + + ret = fdt_setprop_string(fdt, node, "device_type", "memory"); + if (ret < 0) { + goto err; + } + + ret = fdt_setprop_u64(fdt, node, "reg", start); + if (ret < 0) { + goto err; + } + + ret = fdt_appendprop(fdt, node, "reg", &fdtsize, + sizeof(fdtsize)); + if (ret < 0) { + goto err; + } + + return; +err: + NOTICE("BL2: Cannot add memory node [%" PRIx64 " - %" PRIx64 "] to FDT (ret=%i)\n", + start, start + size - 1, ret); + panic(); +} + +static void bl2_advertise_dram_entries(uint64_t dram_config[8]) +{ + uint64_t start, size, size32; + int chan; + + for (chan = 0; chan < 4; chan++) { + start = dram_config[2 * chan]; + size = dram_config[2 * chan + 1]; + if (!size) + continue; + + NOTICE("BL2: CH%d: %" PRIx64 " - %" PRIx64 ", %" PRId64 " %siB\n", + chan, start, start + size - 1, + (size >> 30) ? : size >> 20, + (size >> 30) ? "G" : "M"); + } + + /* + * We add the DT nodes in reverse order here. The fdt_add_subnode() + * adds the DT node before the first existing DT node, so we have + * to add them in reverse order to get nodes sorted by address in + * the resulting DT. + */ + for (chan = 3; chan >= 0; chan--) { + start = dram_config[2 * chan]; + size = dram_config[2 * chan + 1]; + if (!size) + continue; + + /* + * Channel 0 is mapped in 32bit space and the first + * 128 MiB are reserved and the maximum size is 2GiB. + */ + if (chan == 0) { + /* Limit the 32bit entry to 2 GiB - 128 MiB */ + size32 = size - 0x8000000U; + if (size32 >= 0x78000000U) { + size32 = 0x78000000U; + } + + /* Emit 32bit entry, up to 2 GiB - 128 MiB long. */ + bl2_add_dram_entry(0x48000000, size32); + + /* + * If channel 0 is less than 2 GiB long, the + * entire memory fits into the 32bit space entry, + * so move on to the next channel. + */ + if (size <= 0x80000000U) { + continue; + } + + /* + * If channel 0 is more than 2 GiB long, emit + * another entry which covers the rest of the + * memory in channel 0, in the 64bit space. + * + * Start of this new entry is at 2 GiB offset + * from the beginning of the 64bit channel 0 + * address, size is 2 GiB shorter than total + * size of the channel. + */ + start += 0x80000000U; + size -= 0x80000000U; + } + + bl2_add_dram_entry(start, size); + } +} + +static void bl2_advertise_dram_size(uint32_t product) +{ + uint64_t dram_config[8] = { + [0] = 0x400000000ULL, + [2] = 0x500000000ULL, + [4] = 0x600000000ULL, + [6] = 0x700000000ULL, + }; + uint32_t cut = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK; + + switch (product) { + case PRR_PRODUCT_H3: +#if (RCAR_DRAM_LPDDR4_MEMCONF == 0) + /* 4GB(1GBx4) */ + dram_config[1] = 0x40000000ULL; + dram_config[3] = 0x40000000ULL; + dram_config[5] = 0x40000000ULL; + dram_config[7] = 0x40000000ULL; +#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && \ + (RCAR_DRAM_CHANNEL == 5) && \ + (RCAR_DRAM_SPLIT == 2) + /* 4GB(2GBx2 2ch split) */ + dram_config[1] = 0x80000000ULL; + dram_config[3] = 0x80000000ULL; +#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && (RCAR_DRAM_CHANNEL == 15) + /* 8GB(2GBx4: default) */ + dram_config[1] = 0x80000000ULL; + dram_config[3] = 0x80000000ULL; + dram_config[5] = 0x80000000ULL; + dram_config[7] = 0x80000000ULL; +#endif /* RCAR_DRAM_LPDDR4_MEMCONF == 0 */ + break; + + case PRR_PRODUCT_M3: + if (cut < PRR_PRODUCT_30) { +#if (RCAR_GEN3_ULCB == 1) + /* 2GB(1GBx2 2ch split) */ + dram_config[1] = 0x40000000ULL; + dram_config[5] = 0x40000000ULL; +#else + /* 4GB(2GBx2 2ch split) */ + dram_config[1] = 0x80000000ULL; + dram_config[5] = 0x80000000ULL; +#endif + } else { + /* 8GB(2GBx4 2ch split) */ + dram_config[1] = 0x100000000ULL; + dram_config[5] = 0x100000000ULL; + } + break; + + case PRR_PRODUCT_M3N: +#if (RCAR_DRAM_LPDDR4_MEMCONF == 2) + /* 4GB(4GBx1) */ + dram_config[1] = 0x100000000ULL; +#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) + /* 2GB(1GBx2) */ + dram_config[1] = 0x80000000ULL; +#endif + break; + + case PRR_PRODUCT_V3M: + /* 1GB(512MBx2) */ + dram_config[1] = 0x40000000ULL; + break; + + case PRR_PRODUCT_E3: +#if (RCAR_DRAM_DDR3L_MEMCONF == 0) + /* 1GB(512MBx2) */ + dram_config[1] = 0x40000000ULL; +#elif (RCAR_DRAM_DDR3L_MEMCONF == 1) + /* 2GB(512MBx4) */ + dram_config[1] = 0x80000000ULL; +#elif (RCAR_DRAM_DDR3L_MEMCONF == 2) + /* 4GB(1GBx4) */ + dram_config[1] = 0x100000000ULL; +#endif /* RCAR_DRAM_DDR3L_MEMCONF == 0 */ + break; + + case PRR_PRODUCT_D3: + /* 512MB */ + dram_config[1] = 0x20000000ULL; + break; + } + + bl2_advertise_dram_entries(dram_config); +} + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + uint32_t reg, midr, lcs, boot_dev, boot_cpu, sscg, type, rev; + uint32_t product, product_cut, major, minor; + int32_t ret; + const char *str; + const char *unknown = "unknown"; + const char *cpu_ca57 = "CA57"; + const char *cpu_ca53 = "CA53"; + const char *product_m3n = "M3N"; + const char *product_h3 = "H3"; + const char *product_m3 = "M3"; + const char *product_e3 = "E3"; + const char *product_d3 = "D3"; + const char *product_v3m = "V3M"; + const char *lcs_secure = "SE"; + const char *lcs_cm = "CM"; + const char *lcs_dm = "DM"; + const char *lcs_sd = "SD"; + const char *lcs_fa = "FA"; + const char *sscg_off = "PLL1 nonSSCG Clock select"; + const char *sscg_on = "PLL1 SSCG Clock select"; + const char *boot_hyper80 = "HyperFlash(80MHz)"; + const char *boot_qspi40 = "QSPI Flash(40MHz)"; + const char *boot_qspi80 = "QSPI Flash(80MHz)"; + const char *boot_emmc25x1 = "eMMC(25MHz x1)"; + const char *boot_emmc50x8 = "eMMC(50MHz x8)"; +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) + const char *boot_hyper160 = "HyperFlash(150MHz)"; +#else + const char *boot_hyper160 = "HyperFlash(160MHz)"; +#endif +#if (RCAR_LOSSY_ENABLE == 1) + int fcnlnode; +#endif + + bl2_init_generic_timer(); + + reg = mmio_read_32(RCAR_MODEMR); + boot_dev = reg & MODEMR_BOOT_DEV_MASK; + boot_cpu = reg & MODEMR_BOOT_CPU_MASK; + + bl2_cpg_init(); + + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { + rcar_pfc_init(); + rcar_console_boot_init(); + } + + plat_rcar_gic_driver_init(); + plat_rcar_gic_init(); + rcar_swdt_init(); + + /* FIQ interrupts are taken to EL3 */ + write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); + + write_daifclr(DAIF_FIQ_BIT); + + reg = read_midr(); + midr = reg & (MIDR_PN_MASK << MIDR_PN_SHIFT); + switch (midr) { + case MIDR_CA57: + str = cpu_ca57; + break; + case MIDR_CA53: + str = cpu_ca53; + break; + default: + str = unknown; + break; + } + + NOTICE("BL2: R-Car Gen3 Initial Program Loader(%s) Rev.%s\n", str, + version_of_renesas); + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + product = reg & PRR_PRODUCT_MASK; + + switch (product) { + case PRR_PRODUCT_H3: + str = product_h3; + break; + case PRR_PRODUCT_M3: + str = product_m3; + break; + case PRR_PRODUCT_M3N: + str = product_m3n; + break; + case PRR_PRODUCT_V3M: + str = product_v3m; + break; + case PRR_PRODUCT_E3: + str = product_e3; + break; + case PRR_PRODUCT_D3: + str = product_d3; + break; + default: + str = unknown; + break; + } + + if ((PRR_PRODUCT_M3 == product) && + (PRR_PRODUCT_20 == (reg & RCAR_MAJOR_MASK))) { + if (RCAR_M3_CUT_VER11 == (reg & PRR_CUT_MASK)) { + /* M3 Ver.1.1 or Ver.1.2 */ + NOTICE("BL2: PRR is R-Car %s Ver.1.1 / Ver.1.2\n", + str); + } else { + NOTICE("BL2: PRR is R-Car %s Ver.1.%d\n", + str, + (reg & RCAR_MINOR_MASK) + RCAR_M3_MINOR_OFFSET); + } + } else if (product == PRR_PRODUCT_D3) { + if (RCAR_D3_CUT_VER10 == (reg & PRR_CUT_MASK)) { + NOTICE("BL2: PRR is R-Car %s Ver.1.0\n", str); + } else if (RCAR_D3_CUT_VER11 == (reg & PRR_CUT_MASK)) { + NOTICE("BL2: PRR is R-Car %s Ver.1.1\n", str); + } else { + NOTICE("BL2: PRR is R-Car %s Ver.X.X\n", str); + } + } else { + major = (reg & RCAR_MAJOR_MASK) >> RCAR_MAJOR_SHIFT; + major = major + RCAR_MAJOR_OFFSET; + minor = reg & RCAR_MINOR_MASK; + NOTICE("BL2: PRR is R-Car %s Ver.%d.%d\n", str, major, minor); + } + + if (PRR_PRODUCT_E3 == product || PRR_PRODUCT_D3 == product) { + reg = mmio_read_32(RCAR_MODEMR); + sscg = reg & RCAR_SSCG_MASK; + str = sscg == RCAR_SSCG_ENABLE ? sscg_on : sscg_off; + NOTICE("BL2: %s\n", str); + } + + rcar_get_board_type(&type, &rev); + + switch (type) { + case BOARD_SALVATOR_X: + case BOARD_KRIEK: + case BOARD_STARTER_KIT: + case BOARD_SALVATOR_XS: + case BOARD_EBISU: + case BOARD_STARTER_KIT_PRE: + case BOARD_EBISU_4D: + case BOARD_DRAAK: + case BOARD_EAGLE: + break; + default: + type = BOARD_UNKNOWN; + break; + } + + if (type == BOARD_UNKNOWN || rev == BOARD_REV_UNKNOWN) + NOTICE("BL2: Board is %s Rev.---\n", GET_BOARD_NAME(type)); + else { + NOTICE("BL2: Board is %s Rev.%d.%d\n", + GET_BOARD_NAME(type), + GET_BOARD_MAJOR(rev), GET_BOARD_MINOR(rev)); + } + +#if RCAR_LSI != RCAR_AUTO + if (product != TARGET_PRODUCT) { + ERROR("BL2: IPL was been built for the %s.\n", TARGET_NAME); + ERROR("BL2: Please write the correct IPL to flash memory.\n"); + panic(); + } +#endif + rcar_avs_init(); + rcar_avs_setting(); + + switch (boot_dev) { + case MODEMR_BOOT_DEV_HYPERFLASH160: + str = boot_hyper160; + break; + case MODEMR_BOOT_DEV_HYPERFLASH80: + str = boot_hyper80; + break; + case MODEMR_BOOT_DEV_QSPI_FLASH40: + str = boot_qspi40; + break; + case MODEMR_BOOT_DEV_QSPI_FLASH80: + str = boot_qspi80; + break; + case MODEMR_BOOT_DEV_EMMC_25X1: +#if RCAR_LSI == RCAR_D3 + ERROR("BL2: Failed to Initialize. eMMC is not supported.\n"); + panic(); +#endif + str = boot_emmc25x1; + break; + case MODEMR_BOOT_DEV_EMMC_50X8: + str = boot_emmc50x8; + break; + default: + str = unknown; + break; + } + NOTICE("BL2: Boot device is %s\n", str); + + rcar_avs_setting(); + reg = rcar_rom_get_lcs(&lcs); + if (reg) { + str = unknown; + goto lcm_state; + } + + switch (lcs) { + case LCS_CM: + str = lcs_cm; + break; + case LCS_DM: + str = lcs_dm; + break; + case LCS_SD: + str = lcs_sd; + break; + case LCS_SE: + str = lcs_secure; + break; + case LCS_FA: + str = lcs_fa; + break; + default: + str = unknown; + break; + } + +lcm_state: + NOTICE("BL2: LCM state is %s\n", str); + + rcar_avs_end(); + is_ddr_backup_mode(); + + bl2_tzram_layout.total_base = BL31_BASE; + bl2_tzram_layout.total_size = BL31_LIMIT - BL31_BASE; + + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { + ret = rcar_dram_init(); + if (ret) { + NOTICE("BL2: Failed to DRAM initialize (%d).\n", ret); + panic(); + } + rcar_qos_init(); + } + + /* Set up FDT */ + ret = fdt_create_empty_tree(fdt, sizeof(fdt_blob)); + if (ret) { + NOTICE("BL2: Cannot allocate FDT for U-Boot (ret=%i)\n", ret); + panic(); + } + + /* Add platform compatible string */ + bl2_populate_compatible_string(fdt); + + /* Enable RPC if unlocked */ + bl2_add_rpc_node(); + + /* Print DRAM layout */ + bl2_advertise_dram_size(product); + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) { + if (rcar_emmc_init() != EMMC_SUCCESS) { + NOTICE("BL2: Failed to eMMC driver initialize.\n"); + panic(); + } + rcar_emmc_memcard_power(EMMC_POWER_ON); + if (rcar_emmc_mount() != EMMC_SUCCESS) { + NOTICE("BL2: Failed to eMMC mount operation.\n"); + panic(); + } + } else { + rcar_rpc_init(); + rcar_dma_init(); + } + + reg = mmio_read_32(RST_WDTRSTCR); + reg &= ~WDTRSTCR_RWDT_RSTMSK; + reg |= WDTRSTCR_PASSWORD; + mmio_write_32(RST_WDTRSTCR, reg); + + mmio_write_32(CPG_CPGWPR, CPGWPR_PASSWORD); + mmio_write_32(CPG_CPGWPCR, CPGWPCR_PASSWORD); + + reg = mmio_read_32(RCAR_PRR); + if ((reg & RCAR_CPU_MASK_CA57) == RCAR_CPU_HAVE_CA57) + mmio_write_32(CPG_CA57DBGRCR, + DBGCPUPREN | mmio_read_32(CPG_CA57DBGRCR)); + + if ((reg & RCAR_CPU_MASK_CA53) == RCAR_CPU_HAVE_CA53) + mmio_write_32(CPG_CA53DBGRCR, + DBGCPUPREN | mmio_read_32(CPG_CA53DBGRCR)); + + if (product_cut == PRR_PRODUCT_H3_CUT10) { + reg = mmio_read_32(CPG_PLL2CR); + reg &= ~((uint32_t) 1 << 5); + mmio_write_32(CPG_PLL2CR, reg); + + reg = mmio_read_32(CPG_PLL4CR); + reg &= ~((uint32_t) 1 << 5); + mmio_write_32(CPG_PLL4CR, reg); + + reg = mmio_read_32(CPG_PLL0CR); + reg &= ~((uint32_t) 1 << 12); + mmio_write_32(CPG_PLL0CR, reg); + } +#if (RCAR_LOSSY_ENABLE == 1) + NOTICE("BL2: Lossy Decomp areas\n"); + + fcnlnode = fdt_add_subnode(fdt, 0, "reserved-memory"); + if (fcnlnode < 0) { + NOTICE("BL2: Cannot create reserved mem node (ret=%i)\n", + fcnlnode); + panic(); + } + + bl2_lossy_setting(0, LOSSY_ST_ADDR0, LOSSY_END_ADDR0, + LOSSY_FMT0, LOSSY_ENA_DIS0, fcnlnode); + bl2_lossy_setting(1, LOSSY_ST_ADDR1, LOSSY_END_ADDR1, + LOSSY_FMT1, LOSSY_ENA_DIS1, fcnlnode); + bl2_lossy_setting(2, LOSSY_ST_ADDR2, LOSSY_END_ADDR2, + LOSSY_FMT2, LOSSY_ENA_DIS2, fcnlnode); +#endif + + fdt_pack(fdt); + NOTICE("BL2: FDT at %p\n", fdt); + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) + rcar_io_emmc_setup(); + else + rcar_io_setup(); +} + +void bl2_el3_plat_arch_setup(void) +{ +#if RCAR_BL2_DCACHE == 1 + NOTICE("BL2: D-Cache enable\n"); + rcar_configure_mmu_el3(BL2_BASE, + BL2_END - BL2_BASE, + BL2_RO_BASE, BL2_RO_LIMIT +#if USE_COHERENT_MEM + , BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT +#endif + ); +#endif +} + +void bl2_platform_setup(void) +{ + +} + +static void bl2_init_generic_timer(void) +{ +/* FIXME: V3M 16.666 MHz ? */ +#if RCAR_LSI == RCAR_D3 + uint32_t reg_cntfid = EXTAL_DRAAK; +#elif RCAR_LSI == RCAR_E3 + uint32_t reg_cntfid = EXTAL_EBISU; +#else /* RCAR_LSI == RCAR_E3 */ + uint32_t reg; + uint32_t reg_cntfid; + uint32_t modemr; + uint32_t modemr_pll; + uint32_t board_type; + uint32_t board_rev; + uint32_t pll_table[] = { + EXTAL_MD14_MD13_TYPE_0, /* MD14/MD13 : 0b00 */ + EXTAL_MD14_MD13_TYPE_1, /* MD14/MD13 : 0b01 */ + EXTAL_MD14_MD13_TYPE_2, /* MD14/MD13 : 0b10 */ + EXTAL_MD14_MD13_TYPE_3 /* MD14/MD13 : 0b11 */ + }; + + modemr = mmio_read_32(RCAR_MODEMR); + modemr_pll = (modemr & MODEMR_BOOT_PLL_MASK); + + /* Set frequency data in CNTFID0 */ + reg_cntfid = pll_table[modemr_pll >> MODEMR_BOOT_PLL_SHIFT]; + reg = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + switch (modemr_pll) { + case MD14_MD13_TYPE_0: + rcar_get_board_type(&board_type, &board_rev); + if (BOARD_SALVATOR_XS == board_type) { + reg_cntfid = EXTAL_SALVATOR_XS; + } + break; + case MD14_MD13_TYPE_3: + if (PRR_PRODUCT_H3_CUT10 == reg) { + reg_cntfid = reg_cntfid >> 1U; + } + break; + default: + /* none */ + break; + } +#endif /* RCAR_LSI == RCAR_E3 */ + /* Update memory mapped and register based freqency */ + write_cntfrq_el0((u_register_t )reg_cntfid); + mmio_write_32(ARM_SYS_CNTCTL_BASE + (uintptr_t)CNTFID_OFF, reg_cntfid); + /* Enable counter */ + mmio_setbits_32(RCAR_CNTC_BASE + (uintptr_t)CNTCR_OFF, + (uint32_t)CNTCR_EN); +} diff --git a/arm-trusted-firmware/plat/renesas/rcar/platform.mk b/arm-trusted-firmware/plat/renesas/rcar/platform.mk new file mode 100644 index 0000000..670d499 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/rcar/platform.mk @@ -0,0 +1,371 @@ +# +# Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/renesas/common/common.mk + +ifndef LSI + $(error "Error: Unknown LSI. Please use LSI= to specify the LSI") +else + ifeq (${LSI},AUTO) + RCAR_LSI:=${RCAR_AUTO} + else ifeq (${LSI},H3) + RCAR_LSI:=${RCAR_H3} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else ifeq (${LSI_CUT},11) + RCAR_LSI_CUT:=1 + else ifeq (${LSI_CUT},20) + RCAR_LSI_CUT:=10 + else ifeq (${LSI_CUT},30) + RCAR_LSI_CUT:=20 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},H3N) + RCAR_LSI:=${RCAR_H3N} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},30) + RCAR_LSI_CUT:=20 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},M3) + RCAR_LSI:=${RCAR_M3} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else ifeq (${LSI_CUT},11) + RCAR_LSI_CUT:=1 + else ifeq (${LSI_CUT},13) + RCAR_LSI_CUT:=3 + else ifeq (${LSI_CUT},30) + RCAR_LSI_CUT:=20 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},M3N) + RCAR_LSI:=${RCAR_M3N} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else ifeq (${LSI_CUT},11) + RCAR_LSI_CUT:=1 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},E3) + RCAR_LSI:=${RCAR_E3} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else ifeq (${LSI_CUT},11) + RCAR_LSI_CUT:=1 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},D3) + RCAR_LSI:=${RCAR_D3} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},V3M) + RCAR_LSI:=${RCAR_V3M} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + endif + ifeq (${LSI_CUT},20) + RCAR_LSI_CUT:=10 + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else + $(error "Error: ${LSI} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI)) +endif + +# lock RPC HYPERFLASH access by default +# unlock to repogram the ATF firmware from u-boot +ifndef RCAR_RPC_HYPERFLASH_LOCKED +RCAR_RPC_HYPERFLASH_LOCKED := 1 +endif +$(eval $(call add_define,RCAR_RPC_HYPERFLASH_LOCKED)) + +# Process RCAR_SECURE_BOOT flag +ifndef RCAR_SECURE_BOOT +RCAR_SECURE_BOOT := 1 +endif +$(eval $(call add_define,RCAR_SECURE_BOOT)) + +# Process RCAR_QOS_TYPE flag +ifndef RCAR_QOS_TYPE +RCAR_QOS_TYPE := 0 +endif +$(eval $(call add_define,RCAR_QOS_TYPE)) + +# Process RCAR_DRAM_SPLIT flag +ifndef RCAR_DRAM_SPLIT +RCAR_DRAM_SPLIT := 0 +endif +$(eval $(call add_define,RCAR_DRAM_SPLIT)) + +# Process RCAR_BL33_EXECUTION_EL flag +ifndef RCAR_BL33_EXECUTION_EL +RCAR_BL33_EXECUTION_EL := 0 +endif +$(eval $(call add_define,RCAR_BL33_EXECUTION_EL)) + +# Process RCAR_AVS_SETTING_ENABLE flag +ifeq (${RCAR_AVS_SETTING_ENABLE},0) +AVS_SETTING_ENABLE := 0 +else +AVS_SETTING_ENABLE := 1 +endif +$(eval $(call add_define,AVS_SETTING_ENABLE)) + +# Process RCAR_LOSSY_ENABLE flag +ifndef RCAR_LOSSY_ENABLE +RCAR_LOSSY_ENABLE := 0 +endif +$(eval $(call add_define,RCAR_LOSSY_ENABLE)) + +# Process LIFEC_DBSC_PROTECT_ENABLE flag +ifndef LIFEC_DBSC_PROTECT_ENABLE +LIFEC_DBSC_PROTECT_ENABLE := 1 +endif +$(eval $(call add_define,LIFEC_DBSC_PROTECT_ENABLE)) + +# Process PMIC_ROHM_BD9571 flag +ifndef PMIC_ROHM_BD9571 +PMIC_ROHM_BD9571 := 1 +endif +$(eval $(call add_define,PMIC_ROHM_BD9571)) + +# Process PMIC_LEVEL_MODE flag +ifndef PMIC_LEVEL_MODE +PMIC_LEVEL_MODE := 1 +endif +$(eval $(call add_define,PMIC_LEVEL_MODE)) + +# Process RCAR_GEN3_ULCB flag +ifndef RCAR_GEN3_ULCB +RCAR_GEN3_ULCB := 0 +endif +ifeq (${RCAR_GEN3_ULCB},1) + BOARD_DEFAULT := 0x10 + $(eval $(call add_define,BOARD_DEFAULT)) +endif +$(eval $(call add_define,RCAR_GEN3_ULCB)) + +# Process RCAR_REF_INT flag +ifndef RCAR_REF_INT +RCAR_REF_INT :=0 +endif +$(eval $(call add_define,RCAR_REF_INT)) + +# Process RCAR_REWT_TRAINING flag +ifndef RCAR_REWT_TRAINING +RCAR_REWT_TRAINING := 1 +endif +$(eval $(call add_define,RCAR_REWT_TRAINING)) + +# Process RCAR_SYSTEM_SUSPEND flag +ifndef RCAR_SYSTEM_SUSPEND +RCAR_SYSTEM_SUSPEND := 1 +endif +$(eval $(call add_define,RCAR_SYSTEM_SUSPEND)) + +# SYSTEM_SUSPEND requires power control of PMIC etc. +# When executing SYSTEM_SUSPEND other than Salvator-X, Salvator-XS and Ebisu, +# processing equivalent to that implemented in PMIC_ROHM_BD9571 is necessary. +ifeq (${RCAR_SYSTEM_SUSPEND},1) + ifeq (${PMIC_ROHM_BD9571},0) + $(error "Error: When you want RCAR_SYSTEM_SUSPEND to be enable, please also set PMIC_ROHM_BD9571 to enable.") + endif +endif + +# Process RCAR_DRAM_LPDDR4_MEMCONF flag +ifndef RCAR_DRAM_LPDDR4_MEMCONF +RCAR_DRAM_LPDDR4_MEMCONF :=1 +endif +$(eval $(call add_define,RCAR_DRAM_LPDDR4_MEMCONF)) + +# Process RCAR_DRAM_MEMRANK flag +ifndef RCAR_DRAM_MEMRANK +RCAR_DRAM_MEMRANK :=0 +endif +$(eval $(call add_define,RCAR_DRAM_MEMRANK)) + +# Process RCAR_DRAM_DDR3L_MEMCONF flag +ifndef RCAR_DRAM_DDR3L_MEMCONF +RCAR_DRAM_DDR3L_MEMCONF :=1 +endif +$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMCONF)) + +# Process RCAR_DRAM_DDR3L_MEMDUAL flag +ifndef RCAR_DRAM_DDR3L_MEMDUAL +RCAR_DRAM_DDR3L_MEMDUAL :=1 +endif +$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMDUAL)) + +# Process RCAR_BL33_ARG0 flag +ifdef RCAR_BL33_ARG0 +$(eval $(call add_define,RCAR_BL33_ARG0)) +endif + +#Process RCAR_BL2_DCACHE flag +ifndef RCAR_BL2_DCACHE +RCAR_BL2_DCACHE := 0 +endif +$(eval $(call add_define,RCAR_BL2_DCACHE)) + +# Process RCAR_DRAM_CHANNEL flag +ifndef RCAR_DRAM_CHANNEL +RCAR_DRAM_CHANNEL :=15 +endif +$(eval $(call add_define,RCAR_DRAM_CHANNEL)) + +#Process RCAR_SYSTEM_RESET_KEEPON_DDR flag +ifndef RCAR_SYSTEM_RESET_KEEPON_DDR +RCAR_SYSTEM_RESET_KEEPON_DDR := 0 +endif +$(eval $(call add_define,RCAR_SYSTEM_RESET_KEEPON_DDR)) + +ifndef RCAR_GEN3_BL33_GZIP +RCAR_GEN3_BL33_GZIP := 0 +endif +$(eval $(call add_define,RCAR_GEN3_BL33_GZIP)) + +# RCAR_SYSTEM_RESET_KEEPON_DDR requires power control of PMIC etc. +# When executing SYSTEM_SUSPEND other than Salvator-X, Salvator-XS and Ebisu, +# processing equivalent to that implemented in PMIC_ROHM_BD9571 is necessary. +# Also, it is necessary to enable RCAR_SYSTEM_SUSPEND. +ifeq (${RCAR_SYSTEM_RESET_KEEPON_DDR},1) + ifeq (${PMIC_ROHM_BD9571},0) + $(error "Error: When you want RCAR_SYSTEM_RESET_KEEPON_DDR to be enable, please also set PMIC_ROHM_BD9571 to enable.") + endif + ifeq (${RCAR_SYSTEM_SUSPEND},0) + $(error "Error: When you want RCAR_SYSTEM_RESET_KEEPON_DDR to be enable, please also set RCAR_SYSTEM_SUSPEND to enable.") + endif +endif + +include drivers/renesas/common/ddr/ddr.mk +include drivers/renesas/rcar/qos/qos.mk +include drivers/renesas/rcar/pfc/pfc.mk +include lib/libfdt/libfdt.mk + +PLAT_INCLUDES += -Idrivers/renesas/common/ddr \ + -Idrivers/renesas/rcar/qos \ + -Idrivers/renesas/rcar/board \ + -Idrivers/renesas/rcar/cpld/ \ + -Idrivers/renesas/common \ + -Idrivers/renesas/common/iic_dvfs \ + -Idrivers/renesas/common/avs \ + -Idrivers/renesas/common/delay \ + -Idrivers/renesas/common/rom \ + -Idrivers/renesas/common/scif \ + -Idrivers/renesas/common/emmc \ + -Idrivers/renesas/common/pwrc \ + -Idrivers/renesas/common/io + +BL2_SOURCES += plat/renesas/rcar/bl2_plat_setup.c \ + drivers/renesas/rcar/board/board.c + +ifeq (${RCAR_GEN3_BL33_GZIP},1) +include lib/zlib/zlib.mk + +BL2_SOURCES += common/image_decompress.c \ + $(ZLIB_SOURCES) +endif + +ifeq (${RCAR_GEN3_ULCB},1) +BL31_SOURCES += drivers/renesas/rcar/cpld/ulcb_cpld.c +endif + +# build the layout images for the bootrom and the necessary srecords +rcar: rcar_layout_tool rcar_srecord +distclean realclean clean: clean_layout_tool clean_srecord + +# layout images +LAYOUT_TOOLPATH ?= tools/renesas/rcar_layout_create + +clean_layout_tool: + @echo "clean layout tool" + ${Q}${MAKE} -C ${LAYOUT_TOOLPATH} clean + +.PHONY: rcar_layout_tool +rcar_layout_tool: + @echo "generating layout srecs" + ${Q}${MAKE} CPPFLAGS="-D=AARCH64" --no-print-directory -C ${LAYOUT_TOOLPATH} + +# srecords +SREC_PATH = ${BUILD_PLAT} +BL2_ELF_SRC = ${SREC_PATH}/bl2/bl2.elf +BL31_ELF_SRC = ${SREC_PATH}/bl31/bl31.elf + +clean_srecord: + @echo "clean bl2 and bl31 srecs" + rm -f ${SREC_PATH}/bl2.srec ${SREC_PATH}/bl31.srec + +.PHONY: rcar_srecord +rcar_srecord: $(BL2_ELF_SRC) $(BL31_ELF_SRC) + @echo "generating srec: ${SREC_PATH}/bl2.srec" + $(Q)$(OC) -O srec --srec-forceS3 ${BL2_ELF_SRC} ${SREC_PATH}/bl2.srec + @echo "generating srec: ${SREC_PATH}/bl31.srec" + $(Q)$(OC) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec + diff --git a/arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c b/arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c new file mode 100644 index 0000000..e9dbd20 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c @@ -0,0 +1,1020 @@ +/* + * Copyright (c) 2020-2021, 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 "avs_driver.h" +#include "board.h" +#include "boot_init_dram.h" +#include "cpg_registers.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_std.h" +#include "io_common.h" +#include "io_rcar.h" +#include "qos_init.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_version.h" +#include "rom_api.h" + +#define MAX_DRAM_CHANNELS 4 +/* + * DDR ch0 has a shadow area mapped in 32bit address space. + * Physical address 0x4_0000_0000 - 0x4_7fff_ffff in 64bit space + * is mapped to 0x4000_0000 - 0xbfff_ffff in 32bit space. + */ +#define MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE 0x80000000ULL + +#if RCAR_BL2_DCACHE == 1 +/* + * Following symbols are only used during plat_arch_setup() only + * when RCAR_BL2_DCACHE is enabled. + */ +static const uint64_t BL2_RO_BASE = BL_CODE_BASE; +static const uint64_t BL2_RO_LIMIT = BL_CODE_END; + +#if USE_COHERENT_MEM +static const uint64_t BL2_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE; +static const uint64_t BL2_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END; +#endif /* USE_COHERENT_MEM */ + +#endif /* RCAR_BL2_DCACHE */ + +extern void plat_rcar_gic_driver_init(void); +extern void plat_rcar_gic_init(void); +extern void bl2_enter_bl31(const struct entry_point_info *bl_ep_info); +extern void bl2_system_cpg_init(void); +extern void bl2_secure_setting(void); +extern void bl2_cpg_init(void); +extern void rcar_io_emmc_setup(void); +extern void rcar_io_setup(void); +extern void rcar_swdt_release(void); +extern void rcar_swdt_init(void); +extern void rcar_rpc_init(void); +extern void rcar_dma_init(void); +extern void rzg_pfc_init(void); + +static void bl2_init_generic_timer(void); + +/* RZ/G2 product check */ +#if RCAR_LSI == RZ_G2M +#define TARGET_PRODUCT PRR_PRODUCT_M3 +#define TARGET_NAME "RZ/G2M" +#elif RCAR_LSI == RZ_G2H +#define TARGET_PRODUCT PRR_PRODUCT_H3 +#define TARGET_NAME "RZ/G2H" +#elif RCAR_LSI == RZ_G2N +#define TARGET_PRODUCT PRR_PRODUCT_M3N +#define TARGET_NAME "RZ/G2N" +#elif RCAR_LSI == RZ_G2E +#define TARGET_PRODUCT PRR_PRODUCT_E3 +#define TARGET_NAME "RZ/G2E" +#elif RCAR_LSI == RCAR_AUTO +#define TARGET_NAME "RZ/G2M" +#endif /* RCAR_LSI == RZ_G2M */ + +#if (RCAR_LSI == RZ_G2E) +#define GPIO_INDT (GPIO_INDT6) +#define GPIO_BKUP_TRG_SHIFT ((uint32_t)1U << 13U) +#else +#define GPIO_INDT (GPIO_INDT1) +#define GPIO_BKUP_TRG_SHIFT (1U << 8U) +#endif /* RCAR_LSI == RZ_G2E */ + +CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t) + 0x100) + < (RCAR_SHARED_MEM_BASE + RCAR_SHARED_MEM_SIZE), + assert_bl31_params_do_not_fit_in_shared_memory); + +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/* FDT with DRAM configuration */ +uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)]; +static void *fdt = (void *)fdt_blob; + +static void unsigned_num_print(uint64_t unum, unsigned int radix, char *string) +{ + /* Just need enough space to store 64 bit decimal integer */ + char num_buf[20]; + int i = 0; + unsigned int rem; + + do { + rem = unum % radix; + if (rem < 0xaU) { + num_buf[i] = '0' + rem; + } else { + num_buf[i] = 'a' + (rem - 0xaU); + } + i++; + unum /= radix; + } while (unum > 0U); + + while (--i >= 0) { + *string++ = num_buf[i]; + } + *string = 0; +} + +#if RCAR_LOSSY_ENABLE == 1 +typedef struct bl2_lossy_info { + uint32_t magic; + uint32_t a0; + uint32_t b0; +} bl2_lossy_info_t; + +static void bl2_lossy_gen_fdt(uint32_t no, uint64_t start_addr, + uint64_t end_addr, uint32_t format, + uint32_t enable, int fcnlnode) +{ + const uint64_t fcnlsize = cpu_to_fdt64(end_addr - start_addr); + char nodename[40] = { 0 }; + int ret, node; + + /* Ignore undefined addresses */ + if (start_addr == 0UL && end_addr == 0UL) { + return; + } + + snprintf(nodename, sizeof(nodename), "lossy-decompression@"); + unsigned_num_print(start_addr, 16, nodename + strlen(nodename)); + + node = ret = fdt_add_subnode(fdt, fcnlnode, nodename); + if (ret < 0) { + NOTICE("BL2: Cannot create FCNL node (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop_string(fdt, node, "compatible", + "renesas,lossy-decompression"); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL compat string %s (ret=%i)\n", + "renesas,lossy-decompression", ret); + panic(); + } + + ret = fdt_appendprop_string(fdt, node, "compatible", + "shared-dma-pool"); + if (ret < 0) { + NOTICE("BL2: Cannot append FCNL compat string %s (ret=%i)\n", + "shared-dma-pool", ret); + panic(); + } + + ret = fdt_setprop_u64(fdt, node, "reg", start_addr); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL reg prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_appendprop(fdt, node, "reg", &fcnlsize, sizeof(fcnlsize)); + if (ret < 0) { + NOTICE("BL2: Cannot append FCNL reg size prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop(fdt, node, "no-map", NULL, 0); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL no-map prop (ret=%i)\n", ret); + panic(); + } + + ret = fdt_setprop_u32(fdt, node, "renesas,formats", format); + if (ret < 0) { + NOTICE("BL2: Cannot add FCNL formats prop (ret=%i)\n", ret); + panic(); + } +} + +static void bl2_lossy_setting(uint32_t no, uint64_t start_addr, + uint64_t end_addr, uint32_t format, + uint32_t enable, int fcnlnode) +{ + bl2_lossy_info_t info; + uint32_t reg; + + bl2_lossy_gen_fdt(no, start_addr, end_addr, format, enable, fcnlnode); + + reg = format | (start_addr >> 20); + mmio_write_32(AXI_DCMPAREACRA0 + 0x8U * no, reg); + mmio_write_32(AXI_DCMPAREACRB0 + 0x8U * no, end_addr >> 20); + mmio_write_32(AXI_DCMPAREACRA0 + 0x8U * no, reg | enable); + + info.magic = 0x12345678U; + info.a0 = mmio_read_32(AXI_DCMPAREACRA0 + 0x8U * no); + info.b0 = mmio_read_32(AXI_DCMPAREACRB0 + 0x8U * no); + + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no, info.magic); + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x4U, info.a0); + mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x8U, info.b0); + + NOTICE(" Entry %d: DCMPAREACRAx:0x%x DCMPAREACRBx:0x%x\n", no, + mmio_read_32(AXI_DCMPAREACRA0 + 0x8U * no), + mmio_read_32(AXI_DCMPAREACRB0 + 0x8U * no)); +} +#endif /* RCAR_LOSSY_ENABLE == 1 */ + +void bl2_plat_flush_bl31_params(void) +{ + uint32_t product_cut, product, cut; + uint32_t boot_dev, boot_cpu; + uint32_t reg; + + reg = mmio_read_32(RCAR_MODEMR); + boot_dev = reg & MODEMR_BOOT_DEV_MASK; + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) { + emmc_terminate(); + } + + if ((reg & MODEMR_BOOT_CPU_MASK) != MODEMR_BOOT_CPU_CR7) { + bl2_secure_setting(); + } + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + if (!((product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) || + (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20))) { + /* Disable MFIS write protection */ + mmio_write_32(MFISWPCNTR, MFISWPCNTR_PASSWORD | 1U); + } + + reg = mmio_read_32(RCAR_MODEMR); + boot_cpu = reg & MODEMR_BOOT_CPU_MASK; + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { + if (product_cut == PRR_PRODUCT_H3_CUT20) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUVI1_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV1_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV2_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV3_IMSCTLR, IMSCTLR_DISCACHE); + } else if (product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11)) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + } else if ((product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) || + (product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_11))) { + mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUVP0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE); + } + + if (product_cut == (PRR_PRODUCT_H3_CUT20) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) || + product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11) || + product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) { + mmio_write_32(IPMMUHC_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMURT_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUMP_IMSCTLR, IMSCTLR_DISCACHE); + + mmio_write_32(IPMMUDS0_IMSCTLR, IMSCTLR_DISCACHE); + mmio_write_32(IPMMUDS1_IMSCTLR, IMSCTLR_DISCACHE); + } + } + + mmio_write_32(IPMMUMM_IMSCTLR, IPMMUMM_IMSCTLR_ENABLE); + mmio_write_32(IPMMUMM_IMAUXCTLR, IPMMUMM_IMAUXCTLR_NMERGE40_BIT); + + rcar_swdt_release(); + bl2_system_cpg_init(); + +#if RCAR_BL2_DCACHE == 1 + /* Disable data cache (clean and invalidate) */ + disable_mmu_el3(); +#endif /* RCAR_BL2_DCACHE == 1 */ +} + +static uint32_t is_ddr_backup_mode(void) +{ +#if RCAR_SYSTEM_SUSPEND + static uint32_t reason = RCAR_COLD_BOOT; + static uint32_t once; + + if (once != 0U) { + return reason; + } + + once = 1; + if ((mmio_read_32(GPIO_INDT) & GPIO_BKUP_TRG_SHIFT) == 0U) { + return reason; + } + + reason = RCAR_WARM_BOOT; + return reason; +#else /* RCAR_SYSTEM_SUSPEND */ + return RCAR_COLD_BOOT; +#endif /* RCAR_SYSTEM_SUSPEND */ +} + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + u_register_t *boot_kind = (void *)BOOT_KIND_BASE; + bl_mem_params_node_t *bl_mem_params; + + if (image_id != BL31_IMAGE_ID) { + return 0; + } + + bl_mem_params = get_bl_mem_params_node(image_id); + + if (is_ddr_backup_mode() != RCAR_COLD_BOOT) { + *boot_kind = RCAR_WARM_BOOT; + flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind)); + + console_flush(); + bl2_plat_flush_bl31_params(); + + /* will not return */ + bl2_enter_bl31(&bl_mem_params->ep_info); + } + + *boot_kind = RCAR_COLD_BOOT; + flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind)); + + return 0; +} + +static uint64_t rzg_get_dest_addr_from_cert(uint32_t certid, uintptr_t *dest) +{ + uint32_t cert, len; + int err; + + err = rcar_get_certificate(certid, &cert); + if (err != 0) { + ERROR("%s : cert file load error", __func__); + return 1U; + } + + rcar_read_certificate((uint64_t)cert, &len, dest); + + return 0U; +} + +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; + uintptr_t dest; + uint64_t ret; + + if (params == NULL) { + 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 BL31_IMAGE_ID: + ret = rzg_get_dest_addr_from_cert(SOC_FW_CONTENT_CERT_ID, + &dest); + if (ret == 0U) { + bl_mem_params->image_info.image_base = dest; + } + break; + case BL32_IMAGE_ID: + ret = rzg_get_dest_addr_from_cert(TRUSTED_OS_FW_CONTENT_CERT_ID, + &dest); + if (ret == 0U) { + bl_mem_params->image_info.image_base = dest; + } + + 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: + break; + } + + return 0; +} + +struct meminfo *bl2_plat_sec_mem_layout(void) +{ + return &bl2_tzram_layout; +} + +static void bl2_populate_compatible_string(void *dt) +{ + uint32_t board_type; + uint32_t board_rev; + uint32_t reg; + int ret; + + fdt_setprop_u32(dt, 0, "#address-cells", 2); + fdt_setprop_u32(dt, 0, "#size-cells", 2); + + /* Populate compatible string */ + rzg_get_board_type(&board_type, &board_rev); + switch (board_type) { + case BOARD_HIHOPE_RZ_G2M: + ret = fdt_setprop_string(dt, 0, "compatible", + "hoperun,hihope-rzg2m"); + break; + case BOARD_HIHOPE_RZ_G2H: + ret = fdt_setprop_string(dt, 0, "compatible", + "hoperun,hihope-rzg2h"); + break; + case BOARD_HIHOPE_RZ_G2N: + ret = fdt_setprop_string(dt, 0, "compatible", + "hoperun,hihope-rzg2n"); + break; + case BOARD_EK874_RZ_G2E: + ret = fdt_setprop_string(dt, 0, "compatible", + "si-linux,cat874"); + break; + default: + NOTICE("BL2: Cannot set compatible string, board unsupported\n"); + panic(); + break; + } + + if (ret < 0) { + NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret); + panic(); + } + + reg = mmio_read_32(RCAR_PRR); + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_M3: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a774a1"); + break; + case PRR_PRODUCT_H3: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a774e1"); + break; + case PRR_PRODUCT_M3N: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a774b1"); + break; + case PRR_PRODUCT_E3: + ret = fdt_appendprop_string(dt, 0, "compatible", + "renesas,r8a774c0"); + break; + default: + NOTICE("BL2: Cannot set compatible string, SoC unsupported\n"); + panic(); + break; + } + + if (ret < 0) { + NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret); + panic(); + } +} + +static int bl2_add_memory_node(uint64_t start, uint64_t size) +{ + char nodename[32] = { 0 }; + uint64_t fdtsize; + int ret, node; + + fdtsize = cpu_to_fdt64(size); + + snprintf(nodename, sizeof(nodename), "memory@"); + unsigned_num_print(start, 16, nodename + strlen(nodename)); + node = ret = fdt_add_subnode(fdt, 0, nodename); + if (ret < 0) { + return ret; + } + + ret = fdt_setprop_string(fdt, node, "device_type", "memory"); + if (ret < 0) { + return ret; + } + + ret = fdt_setprop_u64(fdt, node, "reg", start); + if (ret < 0) { + return ret; + } + + return fdt_appendprop(fdt, node, "reg", &fdtsize, sizeof(fdtsize)); +} + +static void bl2_advertise_dram_entries(uint64_t dram_config[8]) +{ + uint64_t start, size; + int ret, chan; + + for (chan = 0; chan < MAX_DRAM_CHANNELS; chan++) { + start = dram_config[2 * chan]; + size = dram_config[2 * chan + 1]; + if (size == 0U) { + continue; + } + + NOTICE("BL2: CH%d: %" PRIx64 " - %" PRIx64 ", %" PRId64 " %siB\n", + chan, start, start + size - 1U, + (size >> 30) ? : size >> 20, + (size >> 30) ? "G" : "M"); + } + + /* + * We add the DT nodes in reverse order here. The fdt_add_subnode() + * adds the DT node before the first existing DT node, so we have + * to add them in reverse order to get nodes sorted by address in + * the resulting DT. + */ + for (chan = MAX_DRAM_CHANNELS - 1; chan >= 0; chan--) { + start = dram_config[2 * chan]; + size = dram_config[2 * chan + 1]; + if (size == 0U) { + continue; + } + + /* + * Channel 0 is mapped in 32bit space and the first + * 128 MiB are reserved + */ + if (chan == 0) { + /* + * Maximum DDR size in Channel 0 for 32 bit space is 2GB, Add DT node + * for remaining region in 64 bit address space + */ + if (size > MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE) { + start = dram_config[chan] + MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE; + size -= MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE; + ret = bl2_add_memory_node(start, size); + if (ret < 0) { + goto err; + } + } + start = 0x48000000U; + size -= 0x8000000U; + } + + ret = bl2_add_memory_node(start, size); + if (ret < 0) { + goto err; + } + } + + return; +err: + NOTICE("BL2: Cannot add memory node to FDT (ret=%i)\n", ret); + panic(); +} + +static void bl2_advertise_dram_size(uint32_t product) +{ + uint64_t dram_config[8] = { + [0] = 0x400000000ULL, + [2] = 0x500000000ULL, + [4] = 0x600000000ULL, + [6] = 0x700000000ULL, + }; + + switch (product) { + case PRR_PRODUCT_M3: + /* 4GB(2GBx2 2ch split) */ + dram_config[1] = 0x80000000ULL; + dram_config[5] = 0x80000000ULL; + break; + case PRR_PRODUCT_H3: +#if (RCAR_DRAM_LPDDR4_MEMCONF == 0) + /* 4GB(1GBx4) */ + dram_config[1] = 0x40000000ULL; + dram_config[3] = 0x40000000ULL; + dram_config[5] = 0x40000000ULL; + dram_config[7] = 0x40000000ULL; +#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && (RCAR_DRAM_CHANNEL == 5) && \ + (RCAR_DRAM_SPLIT == 2) + /* 4GB(2GBx2 2ch split) */ + dram_config[1] = 0x80000000ULL; + dram_config[3] = 0x80000000ULL; +#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && (RCAR_DRAM_CHANNEL == 15) + /* 8GB(2GBx4: default) */ + dram_config[1] = 0x80000000ULL; + dram_config[3] = 0x80000000ULL; + dram_config[5] = 0x80000000ULL; + dram_config[7] = 0x80000000ULL; +#endif /* RCAR_DRAM_LPDDR4_MEMCONF == 0 */ + break; + case PRR_PRODUCT_M3N: + /* 4GB(4GBx1) */ + dram_config[1] = 0x100000000ULL; + break; + case PRR_PRODUCT_E3: +#if (RCAR_DRAM_DDR3L_MEMCONF == 0) + /* 1GB(512MBx2) */ + dram_config[1] = 0x40000000ULL; +#elif (RCAR_DRAM_DDR3L_MEMCONF == 1) + /* 2GB(512MBx4) */ + dram_config[1] = 0x80000000ULL; +#elif (RCAR_DRAM_DDR3L_MEMCONF == 2) + /* 4GB(1GBx4) */ + dram_config[1] = 0x100000000ULL; +#endif /* RCAR_DRAM_DDR3L_MEMCONF == 0 */ + break; + default: + NOTICE("BL2: Detected invalid DRAM entries\n"); + break; + } + + bl2_advertise_dram_entries(dram_config); +} + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + uint32_t reg, midr, boot_dev, boot_cpu, type, rev; + uint32_t product, product_cut, major, minor; + int32_t ret; + const char *str; + const char *unknown = "unknown"; + const char *cpu_ca57 = "CA57"; + const char *cpu_ca53 = "CA53"; + const char *product_g2e = "G2E"; + const char *product_g2h = "G2H"; + const char *product_g2m = "G2M"; + const char *product_g2n = "G2N"; + const char *boot_hyper80 = "HyperFlash(80MHz)"; + const char *boot_qspi40 = "QSPI Flash(40MHz)"; + const char *boot_qspi80 = "QSPI Flash(80MHz)"; + const char *boot_emmc25x1 = "eMMC(25MHz x1)"; + const char *boot_emmc50x8 = "eMMC(50MHz x8)"; +#if (RCAR_LSI == RZ_G2E) + uint32_t sscg; + const char *sscg_on = "PLL1 SSCG Clock select"; + const char *sscg_off = "PLL1 nonSSCG Clock select"; + const char *boot_hyper160 = "HyperFlash(150MHz)"; +#else + const char *boot_hyper160 = "HyperFlash(160MHz)"; +#endif /* RCAR_LSI == RZ_G2E */ +#if RZG_LCS_STATE_DETECTION_ENABLE + uint32_t lcs; + const char *lcs_secure = "SE"; + const char *lcs_cm = "CM"; + const char *lcs_dm = "DM"; + const char *lcs_sd = "SD"; + const char *lcs_fa = "FA"; +#endif /* RZG_LCS_STATE_DETECTION_ENABLE */ + +#if (RCAR_LOSSY_ENABLE == 1) + int fcnlnode; +#endif /* (RCAR_LOSSY_ENABLE == 1) */ + + bl2_init_generic_timer(); + + reg = mmio_read_32(RCAR_MODEMR); + boot_dev = reg & MODEMR_BOOT_DEV_MASK; + boot_cpu = reg & MODEMR_BOOT_CPU_MASK; + + bl2_cpg_init(); + + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { + rzg_pfc_init(); + rcar_console_boot_init(); + } + + plat_rcar_gic_driver_init(); + plat_rcar_gic_init(); + rcar_swdt_init(); + + /* FIQ interrupts are taken to EL3 */ + write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); + + write_daifclr(DAIF_FIQ_BIT); + + reg = read_midr(); + midr = reg & (MIDR_PN_MASK << MIDR_PN_SHIFT); + switch (midr) { + case MIDR_CA57: + str = cpu_ca57; + break; + case MIDR_CA53: + str = cpu_ca53; + break; + default: + str = unknown; + break; + } + + NOTICE("BL2: RZ/G2 Initial Program Loader(%s) Rev.%s\n", str, + version_of_renesas); + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + product = reg & PRR_PRODUCT_MASK; + + switch (product) { + case PRR_PRODUCT_M3: + str = product_g2m; + break; + case PRR_PRODUCT_H3: + str = product_g2h; + break; + case PRR_PRODUCT_M3N: + str = product_g2n; + break; + case PRR_PRODUCT_E3: + str = product_g2e; + break; + default: + str = unknown; + break; + } + + if ((product == PRR_PRODUCT_M3) && + ((reg & RCAR_MAJOR_MASK) == PRR_PRODUCT_20)) { + if ((reg & PRR_CUT_MASK) == RCAR_M3_CUT_VER11) { + /* M3 Ver.1.1 or Ver.1.2 */ + NOTICE("BL2: PRR is RZ/%s Ver.1.1 / Ver.1.2\n", str); + } else { + NOTICE("BL2: PRR is RZ/%s Ver.1.%d\n", str, + (reg & RCAR_MINOR_MASK) + RCAR_M3_MINOR_OFFSET); + } + } else { + major = (reg & RCAR_MAJOR_MASK) >> RCAR_MAJOR_SHIFT; + major = major + RCAR_MAJOR_OFFSET; + minor = reg & RCAR_MINOR_MASK; + NOTICE("BL2: PRR is RZ/%s Ver.%d.%d\n", str, major, minor); + } + +#if (RCAR_LSI == RZ_G2E) + if (product == PRR_PRODUCT_E3) { + reg = mmio_read_32(RCAR_MODEMR); + sscg = reg & RCAR_SSCG_MASK; + str = sscg == RCAR_SSCG_ENABLE ? sscg_on : sscg_off; + NOTICE("BL2: %s\n", str); + } +#endif /* RCAR_LSI == RZ_G2E */ + + rzg_get_board_type(&type, &rev); + + switch (type) { + case BOARD_HIHOPE_RZ_G2M: + case BOARD_HIHOPE_RZ_G2H: + case BOARD_HIHOPE_RZ_G2N: + case BOARD_EK874_RZ_G2E: + break; + default: + type = BOARD_UNKNOWN; + break; + } + + if (type == BOARD_UNKNOWN || rev == BOARD_REV_UNKNOWN) { + NOTICE("BL2: Board is %s Rev.---\n", GET_BOARD_NAME(type)); + } else { + NOTICE("BL2: Board is %s Rev.%d.%d\n", + GET_BOARD_NAME(type), + GET_BOARD_MAJOR(rev), GET_BOARD_MINOR(rev)); + } + +#if RCAR_LSI != RCAR_AUTO + if (product != TARGET_PRODUCT) { + ERROR("BL2: IPL was been built for the %s.\n", TARGET_NAME); + ERROR("BL2: Please write the correct IPL to flash memory.\n"); + panic(); + } +#endif /* RCAR_LSI != RCAR_AUTO */ + rcar_avs_init(); + rcar_avs_setting(); + + switch (boot_dev) { + case MODEMR_BOOT_DEV_HYPERFLASH160: + str = boot_hyper160; + break; + case MODEMR_BOOT_DEV_HYPERFLASH80: + str = boot_hyper80; + break; + case MODEMR_BOOT_DEV_QSPI_FLASH40: + str = boot_qspi40; + break; + case MODEMR_BOOT_DEV_QSPI_FLASH80: + str = boot_qspi80; + break; + case MODEMR_BOOT_DEV_EMMC_25X1: + str = boot_emmc25x1; + break; + case MODEMR_BOOT_DEV_EMMC_50X8: + str = boot_emmc50x8; + break; + default: + str = unknown; + break; + } + NOTICE("BL2: Boot device is %s\n", str); + + rcar_avs_setting(); + +#if RZG_LCS_STATE_DETECTION_ENABLE + reg = rcar_rom_get_lcs(&lcs); + if (reg != 0U) { + str = unknown; + goto lcm_state; + } + + switch (lcs) { + case LCS_CM: + str = lcs_cm; + break; + case LCS_DM: + str = lcs_dm; + break; + case LCS_SD: + str = lcs_sd; + break; + case LCS_SE: + str = lcs_secure; + break; + case LCS_FA: + str = lcs_fa; + break; + default: + str = unknown; + break; + } + +lcm_state: + NOTICE("BL2: LCM state is %s\n", str); +#endif /* RZG_LCS_STATE_DETECTION_ENABLE */ + + rcar_avs_end(); + is_ddr_backup_mode(); + + bl2_tzram_layout.total_base = BL31_BASE; + bl2_tzram_layout.total_size = BL31_LIMIT - BL31_BASE; + + if (boot_cpu == MODEMR_BOOT_CPU_CA57 || + boot_cpu == MODEMR_BOOT_CPU_CA53) { + ret = rcar_dram_init(); + if (ret != 0) { + NOTICE("BL2: Failed to DRAM initialize (%d).\n", ret); + panic(); + } + rzg_qos_init(); + } + + /* Set up FDT */ + ret = fdt_create_empty_tree(fdt, sizeof(fdt_blob)); + if (ret != 0) { + NOTICE("BL2: Cannot allocate FDT for U-Boot (ret=%i)\n", ret); + panic(); + } + + /* Add platform compatible string */ + bl2_populate_compatible_string(fdt); + + /* Print DRAM layout */ + bl2_advertise_dram_size(product); + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) { + if (rcar_emmc_init() != EMMC_SUCCESS) { + NOTICE("BL2: Failed to eMMC driver initialize.\n"); + panic(); + } + rcar_emmc_memcard_power(EMMC_POWER_ON); + if (rcar_emmc_mount() != EMMC_SUCCESS) { + NOTICE("BL2: Failed to eMMC mount operation.\n"); + panic(); + } + } else { + rcar_rpc_init(); + rcar_dma_init(); + } + + reg = mmio_read_32(RST_WDTRSTCR); + reg &= ~WDTRSTCR_RWDT_RSTMSK; + reg |= WDTRSTCR_PASSWORD; + mmio_write_32(RST_WDTRSTCR, reg); + + mmio_write_32(CPG_CPGWPR, CPGWPR_PASSWORD); + mmio_write_32(CPG_CPGWPCR, CPGWPCR_PASSWORD); + + reg = mmio_read_32(RCAR_PRR); + if ((reg & RCAR_CPU_MASK_CA57) == RCAR_CPU_HAVE_CA57) { + mmio_write_32(CPG_CA57DBGRCR, + DBGCPUPREN | mmio_read_32(CPG_CA57DBGRCR)); + } + + if ((reg & RCAR_CPU_MASK_CA53) == RCAR_CPU_HAVE_CA53) { + mmio_write_32(CPG_CA53DBGRCR, + DBGCPUPREN | mmio_read_32(CPG_CA53DBGRCR)); + } + + if (product_cut == PRR_PRODUCT_H3_CUT10) { + reg = mmio_read_32(CPG_PLL2CR); + reg &= ~((uint32_t)1 << 5); + mmio_write_32(CPG_PLL2CR, reg); + + reg = mmio_read_32(CPG_PLL4CR); + reg &= ~((uint32_t)1 << 5); + mmio_write_32(CPG_PLL4CR, reg); + + reg = mmio_read_32(CPG_PLL0CR); + reg &= ~((uint32_t)1 << 12); + mmio_write_32(CPG_PLL0CR, reg); + } +#if (RCAR_LOSSY_ENABLE == 1) + NOTICE("BL2: Lossy Decomp areas\n"); + + fcnlnode = fdt_add_subnode(fdt, 0, "reserved-memory"); + if (fcnlnode < 0) { + NOTICE("BL2: Cannot create reserved mem node (ret=%i)\n", + fcnlnode); + panic(); + } + + bl2_lossy_setting(0, LOSSY_ST_ADDR0, LOSSY_END_ADDR0, + LOSSY_FMT0, LOSSY_ENA_DIS0, fcnlnode); + bl2_lossy_setting(1, LOSSY_ST_ADDR1, LOSSY_END_ADDR1, + LOSSY_FMT1, LOSSY_ENA_DIS1, fcnlnode); + bl2_lossy_setting(2, LOSSY_ST_ADDR2, LOSSY_END_ADDR2, + LOSSY_FMT2, LOSSY_ENA_DIS2, fcnlnode); +#endif /* RCAR_LOSSY_ENABLE */ + + fdt_pack(fdt); + NOTICE("BL2: FDT at %p\n", fdt); + + if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 || + boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) { + rcar_io_emmc_setup(); + } else { + rcar_io_setup(); + } +} + +void bl2_el3_plat_arch_setup(void) +{ +#if RCAR_BL2_DCACHE == 1 + NOTICE("BL2: D-Cache enable\n"); + rcar_configure_mmu_el3(BL2_BASE, + BL2_END - BL2_BASE, + BL2_RO_BASE, BL2_RO_LIMIT +#if USE_COHERENT_MEM + , BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT +#endif /* USE_COHERENT_MEM */ + ); +#endif /* RCAR_BL2_DCACHE == 1 */ +} + +void bl2_platform_setup(void) +{ + /* + * Place holder for performing any platform initialization specific + * to BL2. + */ +} + +static void bl2_init_generic_timer(void) +{ +#if RCAR_LSI == RZ_G2E + uint32_t reg_cntfid = EXTAL_EBISU; +#else + uint32_t reg_cntfid; + uint32_t modemr; + uint32_t modemr_pll; + uint32_t pll_table[] = { + EXTAL_MD14_MD13_TYPE_0, /* MD14/MD13 : 0b00 */ + EXTAL_MD14_MD13_TYPE_1, /* MD14/MD13 : 0b01 */ + EXTAL_MD14_MD13_TYPE_2, /* MD14/MD13 : 0b10 */ + EXTAL_MD14_MD13_TYPE_3 /* MD14/MD13 : 0b11 */ + }; + + modemr = mmio_read_32(RCAR_MODEMR); + modemr_pll = (modemr & MODEMR_BOOT_PLL_MASK); + + /* Set frequency data in CNTFID0 */ + reg_cntfid = pll_table[modemr_pll >> MODEMR_BOOT_PLL_SHIFT]; +#endif /* RCAR_LSI == RZ_G2E */ + + /* Update memory mapped and register based frequency */ + write_cntfrq_el0((u_register_t)reg_cntfid); + mmio_write_32(ARM_SYS_CNTCTL_BASE + (uintptr_t)CNTFID_OFF, reg_cntfid); + /* Enable counter */ + mmio_setbits_32(RCAR_CNTC_BASE + (uintptr_t)CNTCR_OFF, + (uint32_t)CNTCR_EN); +} diff --git a/arm-trusted-firmware/plat/renesas/rzg/platform.mk b/arm-trusted-firmware/plat/renesas/rzg/platform.mk new file mode 100644 index 0000000..f37d7d0 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/rzg/platform.mk @@ -0,0 +1,274 @@ +# +# Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/renesas/common/common.mk + +ifndef LSI + $(error "Error: Unknown LSI. Please use LSI= to specify the LSI") +else + ifeq (${LSI},AUTO) + RCAR_LSI:=${RCAR_AUTO} + else ifeq (${LSI},G2M) + RCAR_LSI:=${RZ_G2M} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else ifeq (${LSI_CUT},11) + RCAR_LSI_CUT:=1 + else ifeq (${LSI_CUT},13) + RCAR_LSI_CUT:=3 + else ifeq (${LSI_CUT},30) + RCAR_LSI_CUT:=20 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},G2H) + RCAR_LSI:=${RZ_G2H} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},30) + RCAR_LSI_CUT:=20 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},G2N) + RCAR_LSI:=${RZ_G2N} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else ifeq (${LSI_CUT},11) + RCAR_LSI_CUT:=1 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else ifeq (${LSI},G2E) + RCAR_LSI:=${RZ_G2E} + ifndef LSI_CUT + # enable compatible function. + RCAR_LSI_CUT_COMPAT := 1 + $(eval $(call add_define,RCAR_LSI_CUT_COMPAT)) + else + # disable compatible function. + ifeq (${LSI_CUT},10) + RCAR_LSI_CUT:=0 + else ifeq (${LSI_CUT},11) + RCAR_LSI_CUT:=1 + else + $(error "Error: ${LSI_CUT} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI_CUT)) + endif + else + $(error "Error: ${LSI} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI)) +endif + +# Process RZG_LCS_STATE_DETECTION_ENABLE flag +# Enable to get LCS state information +ifndef RZG_LCS_STATE_DETECTION_ENABLE +RZG_LCS_STATE_DETECTION_ENABLE := 0 +endif +$(eval $(call add_define,RZG_LCS_STATE_DETECTION_ENABLE)) + +# Process RCAR_SECURE_BOOT flag +ifndef RCAR_SECURE_BOOT +RCAR_SECURE_BOOT := 0 +endif +$(eval $(call add_define,RCAR_SECURE_BOOT)) + +# LCS state of RZ/G2 Chip is all CM. +# However certain chips(RZ/G2M and RZ/G2E) have incorrect factory Fuse settings +# which results in getting incorrect LCS states +# if need to enable RCAR_SECURE_BOOT, make sure the chip has proper factory Fuse settings. +ifeq (${RCAR_SECURE_BOOT},1) + ifeq (${RZG_LCS_STATE_DETECTION_ENABLE},0) + $(error "Error: Please check the chip has proper factory Fuse settings and set RZG_LCS_STATE_DETECTION_ENABLE to enable.") + endif +endif + +# lock RPC HYPERFLASH access by default +# unlock to repogram the ATF firmware from u-boot +ifndef RCAR_RPC_HYPERFLASH_LOCKED +RCAR_RPC_HYPERFLASH_LOCKED := 1 +endif +$(eval $(call add_define,RCAR_RPC_HYPERFLASH_LOCKED)) + +# Process RCAR_QOS_TYPE flag +ifndef RCAR_QOS_TYPE +RCAR_QOS_TYPE := 0 +endif +$(eval $(call add_define,RCAR_QOS_TYPE)) + +# Process RCAR_DRAM_SPLIT flag +ifndef RCAR_DRAM_SPLIT +RCAR_DRAM_SPLIT := 0 +endif +$(eval $(call add_define,RCAR_DRAM_SPLIT)) + +# Process RCAR_BL33_EXECUTION_EL flag +ifndef RCAR_BL33_EXECUTION_EL +RCAR_BL33_EXECUTION_EL := 0 +endif +$(eval $(call add_define,RCAR_BL33_EXECUTION_EL)) + +# Process RCAR_AVS_SETTING_ENABLE flag +ifndef AVS_SETTING_ENABLE +AVS_SETTING_ENABLE := 0 +endif +$(eval $(call add_define,AVS_SETTING_ENABLE)) + +# Process RCAR_LOSSY_ENABLE flag +ifndef RCAR_LOSSY_ENABLE +RCAR_LOSSY_ENABLE := 0 +endif +$(eval $(call add_define,RCAR_LOSSY_ENABLE)) + +# Process LIFEC_DBSC_PROTECT_ENABLE flag +ifndef LIFEC_DBSC_PROTECT_ENABLE +LIFEC_DBSC_PROTECT_ENABLE := 1 +endif +$(eval $(call add_define,LIFEC_DBSC_PROTECT_ENABLE)) + +# Process RCAR_GEN3_ULCB flag +ifndef RCAR_GEN3_ULCB +RCAR_GEN3_ULCB := 0 +endif + +# Process RCAR_REF_INT flag +ifndef RCAR_REF_INT +RCAR_REF_INT :=0 +endif +$(eval $(call add_define,RCAR_REF_INT)) + +# Process RCAR_REWT_TRAINING flag +ifndef RCAR_REWT_TRAINING +RCAR_REWT_TRAINING := 1 +endif +$(eval $(call add_define,RCAR_REWT_TRAINING)) + +# Process RCAR_SYSTEM_SUSPEND flag +ifndef RCAR_SYSTEM_SUSPEND +RCAR_SYSTEM_SUSPEND := 0 +endif +$(eval $(call add_define,RCAR_SYSTEM_SUSPEND)) + +# Process RCAR_DRAM_LPDDR4_MEMCONF flag +ifndef RCAR_DRAM_LPDDR4_MEMCONF +RCAR_DRAM_LPDDR4_MEMCONF :=1 +endif +$(eval $(call add_define,RCAR_DRAM_LPDDR4_MEMCONF)) + +# Process RCAR_DRAM_DDR3L_MEMCONF flag +ifndef RCAR_DRAM_DDR3L_MEMCONF +RCAR_DRAM_DDR3L_MEMCONF :=1 +endif +$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMCONF)) + +# Process RCAR_DRAM_DDR3L_MEMDUAL flag +ifndef RCAR_DRAM_DDR3L_MEMDUAL +RCAR_DRAM_DDR3L_MEMDUAL :=1 +endif +$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMDUAL)) + +# Process RCAR_BL33_ARG0 flag +ifdef RCAR_BL33_ARG0 +$(eval $(call add_define,RCAR_BL33_ARG0)) +endif + +#Process RCAR_BL2_DCACHE flag +ifndef RCAR_BL2_DCACHE +RCAR_BL2_DCACHE := 0 +endif +$(eval $(call add_define,RCAR_BL2_DCACHE)) + +# Process RCAR_DRAM_CHANNEL flag +ifndef RCAR_DRAM_CHANNEL +RCAR_DRAM_CHANNEL :=15 +endif +$(eval $(call add_define,RCAR_DRAM_CHANNEL)) + +#Process RCAR_SYSTEM_RESET_KEEPON_DDR flag +ifndef RCAR_SYSTEM_RESET_KEEPON_DDR +RCAR_SYSTEM_RESET_KEEPON_DDR := 0 +endif +$(eval $(call add_define,RCAR_SYSTEM_RESET_KEEPON_DDR)) + +RZG_SOC :=1 +$(eval $(call add_define,RZG_SOC)) + +include drivers/renesas/common/ddr/ddr.mk +include drivers/renesas/rzg/qos/qos.mk +include drivers/renesas/rzg/pfc/pfc.mk +include lib/libfdt/libfdt.mk + +PLAT_INCLUDES += -Idrivers/renesas/common/ddr \ + -Idrivers/renesas/rzg/qos \ + -Idrivers/renesas/rzg/board \ + -Idrivers/renesas/common \ + -Idrivers/renesas/common/iic_dvfs \ + -Idrivers/renesas/common/avs \ + -Idrivers/renesas/common/delay \ + -Idrivers/renesas/common/rom \ + -Idrivers/renesas/common/scif \ + -Idrivers/renesas/common/emmc \ + -Idrivers/renesas/common/pwrc \ + -Idrivers/renesas/common/io + +BL2_SOURCES += plat/renesas/rzg/bl2_plat_setup.c \ + drivers/renesas/rzg/board/board.c + +# build the layout images for the bootrom and the necessary srecords +rzg: rzg_layout_create rzg_srecord +distclean realclean clean: clean_layout_tool clean_srecord + +# layout images +LAYOUT_TOOLPATH ?= tools/renesas/rzg_layout_create + +clean_layout_tool: + @echo "clean layout tool" + ${Q}${MAKE} -C ${LAYOUT_TOOLPATH} clean + +.PHONY: rzg_layout_create +rzg_layout_create: + @echo "generating layout srecs" + ${Q}${MAKE} CPPFLAGS="-D=AARCH64" --no-print-directory -C ${LAYOUT_TOOLPATH} + +# srecords +SREC_PATH = ${BUILD_PLAT} +BL2_ELF_SRC = ${SREC_PATH}/bl2/bl2.elf +BL31_ELF_SRC = ${SREC_PATH}/bl31/bl31.elf + +clean_srecord: + @echo "clean bl2 and bl31 srecs" + rm -f ${SREC_PATH}/bl2.srec ${SREC_PATH}/bl31.srec + +.PHONY: rzg_srecord +rzg_srecord: $(BL2_ELF_SRC) $(BL31_ELF_SRC) + @echo "generating srec: ${SREC_PATH}/bl2.srec" + $(Q)$(OC) -O srec --srec-forceS3 ${BL2_ELF_SRC} ${SREC_PATH}/bl2.srec + @echo "generating srec: ${SREC_PATH}/bl31.srec" + $(Q)$(OC) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec diff --git a/arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S b/arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S new file mode 100644 index 0000000..475c297 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + + .globl cpuson_entry_point + .globl cpuson_flags + .globl platform_cpu_warmboot + .globl plat_secondary_cold_boot_setup + .globl plat_report_exception + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_reset_handler + .globl plat_panic_handler + + /* + * void plat_reset_handler(void); + * + * Determine the SOC type and call the appropriate reset + * handler. + * + */ +func plat_reset_handler + bx lr +endfunc plat_reset_handler + +func plat_my_core_pos + ldcopr r0, MPIDR + and r1, r0, #MPIDR_CPU_MASK +#ifdef PLAT_RK_MPIDR_CLUSTER_MASK + and r0, r0, #PLAT_RK_MPIDR_CLUSTER_MASK +#else + and r0, r0, #MPIDR_CLUSTER_MASK +#endif + add r0, r1, r0, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT + bx lr +endfunc plat_my_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* rk3288 does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +func plat_is_my_cpu_primary + ldcopr r0, MPIDR +#ifdef PLAT_RK_MPIDR_CLUSTER_MASK + ldr r1, =(PLAT_RK_MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) +#else + ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) +#endif + and r0, r1 + cmp r0, #PLAT_RK_PRIMARY_CPU + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* -------------------------------------------------------------------- + * void plat_panic_handler(void) + * Call system reset function on panic. Set up an emergency stack so we + * can run C functions (it only needs to last for a few calls until we + * reboot anyway). + * -------------------------------------------------------------------- + */ +func plat_panic_handler + bl plat_set_my_stack + b rockchip_soc_soft_reset +endfunc plat_panic_handler + + /* -------------------------------------------------------------------- + * void platform_cpu_warmboot (void); + * cpus online or resume entrypoint + * -------------------------------------------------------------------- + */ +func platform_cpu_warmboot _align=16 + push { r4 - r7, lr } + ldcopr r0, MPIDR + and r5, r0, #MPIDR_CPU_MASK +#ifdef PLAT_RK_MPIDR_CLUSTER_MASK + and r6, r0, #PLAT_RK_MPIDR_CLUSTER_MASK +#else + and r6, r0, #MPIDR_CLUSTER_MASK +#endif + mov r0, r6 + + func_rockchip_clst_warmboot + /* -------------------------------------------------------------------- + * big cluster id is 1 + * big cores id is from 0-3, little cores id 4-7 + * -------------------------------------------------------------------- + */ + add r7, r5, r6, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT + /* -------------------------------------------------------------------- + * get per cpuup flag + * -------------------------------------------------------------------- + */ + ldr r4, =cpuson_flags + add r4, r4, r7, lsl #2 + ldr r1, [r4] + /* -------------------------------------------------------------------- + * check cpuon reason + * -------------------------------------------------------------------- + */ + cmp r1, #PMU_CPU_AUTO_PWRDN + beq boot_entry + cmp r1, #PMU_CPU_HOTPLUG + beq boot_entry + /* -------------------------------------------------------------------- + * If the boot core cpuson_flags or cpuson_entry_point is not + * expection. force the core into wfe. + * -------------------------------------------------------------------- + */ +wfe_loop: + wfe + b wfe_loop +boot_entry: + mov r1, #0 + str r1, [r4] + /* -------------------------------------------------------------------- + * get per cpuup boot addr + * -------------------------------------------------------------------- + */ + ldr r5, =cpuson_entry_point + ldr r2, [r5, r7, lsl #2] /* ehem. #3 */ + pop { r4 - r7, lr } + + bx r2 +endfunc platform_cpu_warmboot + + /* -------------------------------------------------------------------- + * Per-CPU Secure entry point - resume or power up + * -------------------------------------------------------------------- + */ + .section tzfw_coherent_mem, "a" + .align 3 +cpuson_entry_point: + .rept PLATFORM_CORE_COUNT + .quad 0 + .endr +cpuson_flags: + .rept PLATFORM_CORE_COUNT + .word 0 + .endr +rockchip_clst_warmboot_data diff --git a/arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c b/arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c new file mode 100644 index 0000000..9030951 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +void plat_configure_mmu_svc_mon(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit) +{ + mmap_add_region(total_base, total_base, total_size, + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + MT_MEMORY | MT_RO | MT_SECURE); + mmap_add_region(coh_start, coh_start, coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); + mmap_add(plat_rk_mmap); + rockchip_plat_mmu_svc_mon(); + init_xlat_tables(); + enable_mmu_svc_mon(0); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +/* + * generic pm code does cci handling, but rockchip arm32 platforms + * have ever only 1 cluster, so nothing to do. + */ +void plat_cci_init(void) +{ +} + +void plat_cci_enable(void) +{ +} + +void plat_cci_disable(void) +{ +} diff --git a/arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S b/arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S new file mode 100644 index 0000000..a05ae54 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl pmu_cpuson_entrypoint + .macro pmusram_entry_func _name + .section .pmusram.entry, "ax" + .type \_name, %function + .cfi_startproc + \_name: + .endm + +pmusram_entry_func pmu_cpuson_entrypoint + +#if PSRAM_CHECK_WAKEUP_CPU +check_wake_cpus: + ldcopr r0, MPIDR + and r1, r0, #MPIDR_CPU_MASK +#ifdef PLAT_RK_MPIDR_CLUSTER_MASK + and r0, r0, #PLAT_RK_MPIDR_CLUSTER_MASK +#else + and r0, r0, #MPIDR_CLUSTER_MASK +#endif + orr r0, r0, r1 + + /* primary_cpu */ + ldr r1, boot_mpidr + cmp r0, r1 + beq sys_wakeup + + /* + * If the core is not the primary cpu, + * force the core into wfe. + */ +wfe_loop: + wfe + b wfe_loop +sys_wakeup: +#endif + +#if PSRAM_DO_DDR_RESUME +ddr_resume: + ldr r2, =__bl32_sram_stack_end + mov sp, r2 + bl dmc_resume +#endif + bl sram_restore +sys_resume: + bl sp_min_warm_entrypoint +endfunc pmu_cpuson_entrypoint diff --git a/arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..4af052b --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + + .globl cpuson_entry_point + .globl cpuson_flags + .globl platform_cpu_warmboot + .globl plat_secondary_cold_boot_setup + .globl plat_report_exception + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_reset_handler + .globl plat_panic_handler + + /* + * void plat_reset_handler(void); + * + * Determine the SOC type and call the appropriate reset + * handler. + * + */ +func plat_reset_handler + mrs x0, midr_el1 + ubfx x0, x0, MIDR_PN_SHIFT, #12 + cmp w0, #((CORTEX_A72_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + b.eq handler_a72 + b handler_end +handler_a72: + /* + * This handler does the following: + * Set the L2 Data RAM latency for Cortex-A72. + * Set the L2 Tag RAM latency to for Cortex-A72. + */ + mov x0, #((5 << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \ + (0x1 << 5)) + msr CORTEX_A72_L2CTLR_EL1, x0 + isb +handler_end: + ret +endfunc plat_reset_handler + +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT + ret +endfunc plat_my_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* rk3368 does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_RK_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* -------------------------------------------------------------------- + * void plat_panic_handler(void) + * Call system reset function on panic. Set up an emergency stack so we + * can run C functions (it only needs to last for a few calls until we + * reboot anyway). + * -------------------------------------------------------------------- + */ +func plat_panic_handler + msr spsel, #0 + bl plat_set_my_stack + b rockchip_soc_soft_reset +endfunc plat_panic_handler + + /* -------------------------------------------------------------------- + * void platform_cpu_warmboot (void); + * cpus online or resume enterpoint + * -------------------------------------------------------------------- + */ +func platform_cpu_warmboot _align=16 + mrs x0, MPIDR_EL1 + and x19, x0, #MPIDR_CPU_MASK + and x20, x0, #MPIDR_CLUSTER_MASK + mov x0, x20 + func_rockchip_clst_warmboot + /* -------------------------------------------------------------------- + * big cluster id is 1 + * big cores id is from 0-3, little cores id 4-7 + * -------------------------------------------------------------------- + */ + add x21, x19, x20, lsr #PLAT_RK_CLST_TO_CPUID_SHIFT + /* -------------------------------------------------------------------- + * get per cpuup flag + * -------------------------------------------------------------------- + */ + adr x4, cpuson_flags + add x4, x4, x21, lsl #2 + ldr w1, [x4] + /* -------------------------------------------------------------------- + * check cpuon reason + * -------------------------------------------------------------------- + */ + cmp w1, PMU_CPU_AUTO_PWRDN + b.eq boot_entry + cmp w1, PMU_CPU_HOTPLUG + b.eq boot_entry + /* -------------------------------------------------------------------- + * If the boot core cpuson_flags or cpuson_entry_point is not + * expection. force the core into wfe. + * -------------------------------------------------------------------- + */ +wfe_loop: + wfe + b wfe_loop +boot_entry: + str wzr, [x4] + /* -------------------------------------------------------------------- + * get per cpuup boot addr + * -------------------------------------------------------------------- + */ + adr x5, cpuson_entry_point + ldr x2, [x5, x21, lsl #3] + br x2 +endfunc platform_cpu_warmboot + + /* -------------------------------------------------------------------- + * Per-CPU Secure entry point - resume or power up + * -------------------------------------------------------------------- + */ + .section tzfw_coherent_mem, "a" + .align 3 +cpuson_entry_point: + .rept PLATFORM_CORE_COUNT + .quad 0 + .endr +cpuson_flags: + .rept PLATFORM_CORE_COUNT + .word 0 + .endr +rockchip_clst_warmboot_data diff --git a/arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c b/arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c new file mode 100644 index 0000000..81e8520 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef PLAT_RK_CCI_BASE +static const int cci_map[] = { + PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX +}; +#endif + +/****************************************************************************** + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +#define DEFINE_CONFIGURE_MMU_EL(_el) \ + void plat_configure_mmu_el ## _el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(plat_rk_mmap); \ + rockchip_plat_mmu_el##_el(); \ + init_xlat_tables(); \ + \ + enable_mmu_el ## _el(0); \ + } + +/* Define EL3 variants of the function initialising the MMU */ +DEFINE_CONFIGURE_MMU_EL(3) + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +void plat_cci_init(void) +{ +#ifdef PLAT_RK_CCI_BASE + /* Initialize CCI driver */ + cci_init(PLAT_RK_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); +#endif +} + +void plat_cci_enable(void) +{ + /* + * Enable CCI coherency for this cluster. + * No need for locks as no other cpu is active at the moment. + */ +#ifdef PLAT_RK_CCI_BASE + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); +#endif +} + +void plat_cci_disable(void) +{ +#ifdef PLAT_RK_CCI_BASE + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); +#endif +} diff --git a/arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S b/arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S new file mode 100644 index 0000000..d91ee0e --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl pmu_cpuson_entrypoint + .macro pmusram_entry_func _name + .section .pmusram.entry, "ax" + .type \_name, %function + .cfi_startproc + \_name: + .endm + +pmusram_entry_func pmu_cpuson_entrypoint + +#if PSRAM_CHECK_WAKEUP_CPU +check_wake_cpus: + mrs x0, MPIDR_EL1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + orr x0, x0, x1 + + /* primary_cpu */ + ldr w1, boot_mpidr + cmp w0, w1 + b.eq sys_wakeup + + /* + * If the core is not the primary cpu, + * force the core into wfe. + */ +wfe_loop: + wfe + b wfe_loop +sys_wakeup: +#endif + +#if PSRAM_DO_DDR_RESUME +ddr_resume: + ldr x2, =__bl31_sram_stack_end + mov sp, x2 + bl dmc_resume +#endif + bl sram_restore +sys_resume: + bl bl31_warm_entrypoint +endfunc pmu_cpuson_entrypoint diff --git a/arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c b/arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c new file mode 100644 index 0000000..98ef415 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +#pragma weak params_early_setup +void params_early_setup(u_register_t plat_param_from_bl2) +{ +} + +/******************************************************************************* + * Perform any BL3-1 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + * BL2 has flushed this information to memory, so we are guaranteed to pick up + * good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + params_early_setup(arg1); + + if (rockchip_get_uart_base() != 0) + console_16550_register(rockchip_get_uart_base(), + rockchip_get_uart_clock(), + rockchip_get_uart_baudrate(), &console); + + VERBOSE("bl31_setup\n"); + + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); +} + +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + plat_rockchip_soc_init(); + + /* Initialize the gic cpu and distributor interfaces */ + plat_rockchip_gic_driver_init(); + plat_rockchip_gic_init(); + plat_rockchip_pmu_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + plat_cci_init(); + plat_cci_enable(); + plat_configure_mmu_el3(BL_CODE_BASE, + BL_COHERENT_RAM_END - BL_CODE_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} diff --git a/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c b/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c new file mode 100644 index 0000000..e89fe1e --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "ddr_parameter.h" + +/* + * The miniloader delivers the parameters about ddr usage info from address + * 0x02000000 and the data format is defined as below figure. It tells ATF the + * areas of ddr that are used by platform, we treat them as non-secure regions + * by default. Then we should parse the other part regions and configurate them + * as secure regions to avoid illegal access. + * + * [ddr usage info data format] + * 0x02000000 + * ----------------------------------------------------------------------------- + * | | | | + * ----------------------------------------------------------------------------- + * | count | 4byte | the array numbers of the | + * | | | 'addr_array' and 'size_array' | + * ----------------------------------------------------------------------------- + * | reserved | 4byte | just for 'addr_array' 8byte aligned | + * ----------------------------------------------------------------------------- + * | addr_array[count] | per 8byte | memory region base address | + * ----------------------------------------------------------------------------- + * | size_array[count] | per 8byte | memory region size (byte) | + * ----------------------------------------------------------------------------- + */ + +/* + * function: read parameters info(ns-regions) and try to parse s-regions info + * + * @addr: head address to the ddr usage struct from miniloader + * @max_mb: the max ddr capacity(MB) that the platform support + */ +struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb) +{ + uint64_t base, top; + uint32_t i, addr_offset, size_offset; + struct param_ddr_usage p; + + memset(&p, 0, sizeof(p)); + + /* read how many blocks of ns-regions, read from offset: 0x0 */ + p.ns_nr = mmio_read_32(addr + REGION_NR_OFFSET); + if ((p.ns_nr > DDR_REGION_NR_MAX) || (p.ns_nr == 0)) { + ERROR("over or zero region, nr=%d, max=%d\n", + p.ns_nr, DDR_REGION_NR_MAX); + return p; + } + + /* whole ddr regions boundary, it will be used when parse s-regions */ + p.boundary = max_mb; + + /* calculate ns-region base addr and size offset */ + addr_offset = REGION_ADDR_OFFSET; + size_offset = REGION_ADDR_OFFSET + p.ns_nr * REGION_DATA_PER_BYTES; + + /* read all ns-regions base and top address */ + for (i = 0; i < p.ns_nr; i++) { + base = mmio_read_64(addr + addr_offset); + top = base + mmio_read_64(addr + size_offset); + /* + * translate byte to MB and store info, + * Miniloader will promise every ns-region is MB aligned. + */ + p.ns_base[i] = RG_SIZE_MB(base); + p.ns_top[i] = RG_SIZE_MB(top); + + addr_offset += REGION_DATA_PER_BYTES; + size_offset += REGION_DATA_PER_BYTES; + } + + /* + * a s-region's base starts from previous ns-region's top, and a + * s-region's top ends with next ns-region's base. maybe like this: + * + * case1: ns-regison start from 0MB + * ----------------------------------------------- + * | ns0 | S0 | ns1 | S1 | ns2 | + * 0----------------------------------------------- max_mb + * + * + * case2: ns-regison not start from 0MB + * ----------------------------------------------- + * | S0 | ns0 | ns1 | ns2 | S1 | + * 0----------------------------------------------- max_mb + */ + + /* like above case2 figure, ns-region is not start from 0MB */ + if (p.ns_base[0] != 0) { + p.s_base[p.s_nr] = 0; + p.s_top[p.s_nr] = p.ns_base[0]; + p.s_nr++; + } + + /* + * notice: if ns-regions not start from 0MB, p.s_nr = 1 now, otherwise 0 + */ + for (i = 0; i < p.ns_nr; i++) { + /* + * if current ns-regions top covers boundary, + * that means s-regions are all parsed yet, so finsh. + */ + if (p.ns_top[i] == p.boundary) + goto out; + + /* s-region's base starts from previous ns-region's top */ + p.s_base[p.s_nr] = p.ns_top[i]; + + /* s-region's top ends with next ns-region's base */ + if (i + 1 < p.ns_nr) + p.s_top[p.s_nr] = p.ns_base[i + 1]; + else + p.s_top[p.s_nr] = p.boundary; + p.s_nr++; + } +out: + return p; +} diff --git a/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h b/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h new file mode 100644 index 0000000..25c93a1 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DDR_PARAMETER_H +#define DDR_PARAMETER_H + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define DDR_REGION_NR_MAX 10 +#define REGION_NR_OFFSET 0 +#define REGION_ADDR_OFFSET 8 +#define REGION_DATA_PER_BYTES 8 +#define RG_SIZE_MB(byte) ((byte) >> 20) + +/* unit: MB */ +struct param_ddr_usage { + uint64_t boundary; + + uint32_t ns_nr; + uint64_t ns_base[DDR_REGION_NR_MAX]; + uint64_t ns_top[DDR_REGION_NR_MAX]; + + uint32_t s_nr; + uint64_t s_base[DDR_REGION_NR_MAX + 1]; + uint64_t s_top[DDR_REGION_NR_MAX + 1]; +}; + +struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb); + +#endif /* DDR_PARAMETER_H */ diff --git a/arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h b/arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h new file mode 100644 index 0000000..5359f73 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_COM_H +#define PMU_COM_H + +#ifndef CHECK_CPU_WFIE_BASE +#define CHECK_CPU_WFIE_BASE (PMU_BASE + PMU_CORE_PWR_ST) +#endif +/* + * Use this macro to instantiate lock before it is used in below + * rockchip_pd_lock_xxx() macros + */ +DECLARE_BAKERY_LOCK(rockchip_pd_lock); + +/* + * These are wrapper macros to the powe domain Bakery Lock API. + */ +#define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock) +#define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock) +#define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock) + +/***************************************************************************** + * power domain on or off + *****************************************************************************/ +enum pmu_pd_state { + pmu_pd_on = 0, + pmu_pd_off = 1 +}; + +#pragma weak plat_ic_get_pending_interrupt_id +#pragma weak pmu_power_domain_ctr +#pragma weak check_cpu_wfie + +static inline uint32_t pmu_power_domain_st(uint32_t pd) +{ + uint32_t pwrdn_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd); + + if (pwrdn_st) + return pmu_pd_off; + else + return pmu_pd_on; +} + +static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state) +{ + uint32_t val; + uint32_t loop = 0; + int ret = 0; + + rockchip_pd_lock_get(); + + val = mmio_read_32(PMU_BASE + PMU_PWRDN_CON); + if (pd_state == pmu_pd_off) + val |= BIT(pd); + else + val &= ~BIT(pd); + + mmio_write_32(PMU_BASE + PMU_PWRDN_CON, val); + dsb(); + + while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) { + udelay(1); + loop++; + } + + if (pmu_power_domain_st(pd) != pd_state) { + WARN("%s: %d, %d, error!\n", __func__, pd, pd_state); + ret = -EINVAL; + } + + rockchip_pd_lock_rls(); + + return ret; +} + +static int check_cpu_wfie(uint32_t cpu_id, uint32_t wfie_msk) +{ + uint32_t cluster_id, loop = 0; + + if (cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT) { + cluster_id = 1; + cpu_id -= PLATFORM_CLUSTER0_CORE_COUNT; + } else { + cluster_id = 0; + } + + /* + * wfe/wfi tracking not possible, hopefully the host + * was sucessful in enabling wfe/wfi. + * We'll give a bit of additional time, like the kernel does. + */ + if ((cluster_id && clstb_cpu_wfe < 0) || + (!cluster_id && clstl_cpu_wfe < 0)) { + mdelay(1); + return 0; + } + + if (cluster_id) + wfie_msk <<= (clstb_cpu_wfe + cpu_id); + else + wfie_msk <<= (clstl_cpu_wfe + cpu_id); + + while (!(mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) && + (loop < CHK_CPU_LOOP)) { + udelay(1); + loop++; + } + + if ((mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) == 0) { + WARN("%s: %d, %d, %d, error!\n", __func__, + cluster_id, cpu_id, wfie_msk); + return -EINVAL; + } + + return 0; +} + +#endif /* PMU_COM_H */ diff --git a/arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S b/arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S new file mode 100644 index 0000000..691beeb --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ROCKCHIP_PLAT_MACROS_S +#define ROCKCHIP_PLAT_MACROS_S + +#include +#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)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* --------------------------------------------- + * The below utility macro prints out relevant GIC + * and CCI registers whenever an unhandled + * exception is taken in BL31. + * Expects: GICD base in x26, GICC base in x27 + * Clobbers: x0 - x10, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + + mov_imm x26, PLAT_RK_GICD_BASE + mov_imm x27, PLAT_RK_GICC_BASE + + /* 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, [x27, #GICC_HPPIR] + ldr w9, [x27, #GICC_AHPPIR] + ldr w10, [x27, #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, x26, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +gicd_ispendr_loop: + sub x4, x7, x26 + cmp x4, #0x280 + b.eq exit_print_gic_regs + bl asm_print_hex + + 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: + +#if PLATFORM_CLUSTER_COUNT > 1 + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_RK_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_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_RK_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 +#endif + .endm + +#endif /* ROCKCHIP_PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/rockchip/common/include/plat_params.h b/arm-trusted-firmware/plat/rockchip/common/include/plat_params.h new file mode 100644 index 0000000..95b850f --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/include/plat_params.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PARAMS_H +#define PLAT_PARAMS_H + +#include + +#include + +#endif /* PLAT_PARAMS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/common/include/plat_private.h b/arm-trusted-firmware/plat/rockchip/common/include/plat_private.h new file mode 100644 index 0000000..990d106 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/include/plat_private.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#ifndef __ASSEMBLER__ + +#include + +#include +#include +#include +#include + +#define __sramdata __attribute__((section(".sram.data"))) +#define __sramconst __attribute__((section(".sram.rodata"))) +#define __sramfunc __attribute__((section(".sram.text"))) + +#define __pmusramdata __attribute__((section(".pmusram.data"))) +#define __pmusramconst __attribute__((section(".pmusram.rodata"))) +#define __pmusramfunc __attribute__((section(".pmusram.text"))) + +extern uint32_t __bl31_sram_text_start, __bl31_sram_text_end; +extern uint32_t __bl31_sram_data_start, __bl31_sram_data_end; +extern uint32_t __bl31_sram_stack_start, __bl31_sram_stack_end; +extern uint32_t __bl31_sram_text_real_end, __bl31_sram_data_real_end; +extern uint32_t __sram_incbin_start, __sram_incbin_end; +extern uint32_t __sram_incbin_real_end; + +/****************************************************************************** + * The register have write-mask bits, it is mean, if you want to set the bits, + * you needs set the write-mask bits at the same time, + * The write-mask bits is in high 16-bits. + * The fllowing macro definition helps access write-mask bits reg efficient! + ******************************************************************************/ +#define REG_MSK_SHIFT 16 + +#ifndef WMSK_BIT +#define WMSK_BIT(nr) BIT((nr) + REG_MSK_SHIFT) +#endif + +/* set one bit with write mask */ +#ifndef BIT_WITH_WMSK +#define BIT_WITH_WMSK(nr) (BIT(nr) | WMSK_BIT(nr)) +#endif + +#ifndef BITS_SHIFT +#define BITS_SHIFT(bits, shift) (bits << (shift)) +#endif + +#ifndef BITS_WITH_WMASK +#define BITS_WITH_WMASK(bits, msk, shift)\ + (BITS_SHIFT(bits, shift) | BITS_SHIFT(msk, (shift + REG_MSK_SHIFT))) +#endif + +/****************************************************************************** + * Function and variable prototypes + *****************************************************************************/ +#ifdef __aarch64__ +void plat_configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long, + unsigned long, + unsigned long, + unsigned long); + +void rockchip_plat_mmu_el3(void); +#else +void plat_configure_mmu_svc_mon(unsigned long total_base, + unsigned long total_size, + unsigned long, + unsigned long, + unsigned long, + unsigned long); + +void rockchip_plat_mmu_svc_mon(void); +#endif + +void plat_cci_init(void); +void plat_cci_enable(void); +void plat_cci_disable(void); + +void plat_delay_timer_init(void); + +void params_early_setup(u_register_t plat_params_from_bl2); + +void plat_rockchip_gic_driver_init(void); +void plat_rockchip_gic_init(void); +void plat_rockchip_gic_cpuif_enable(void); +void plat_rockchip_gic_cpuif_disable(void); +void plat_rockchip_gic_pcpu_init(void); + +void plat_rockchip_pmu_init(void); +void plat_rockchip_soc_init(void); +uintptr_t plat_get_sec_entrypoint(void); + +void platform_cpu_warmboot(void); + +struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void); +struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void); +struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count); +struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void); +void plat_rockchip_gpio_init(void); +void plat_rockchip_save_gpio(void); +void plat_rockchip_restore_gpio(void); + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint); +int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl, + plat_local_state_t lvl_state); +int rockchip_soc_cores_pwr_dm_off(void); +int rockchip_soc_sys_pwr_dm_suspend(void); +int rockchip_soc_cores_pwr_dm_suspend(void); +int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl, + plat_local_state_t lvl_state); +int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl, + plat_local_state_t lvl_state); +int rockchip_soc_cores_pwr_dm_on_finish(void); +int rockchip_soc_sys_pwr_dm_resume(void); + +int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl, + plat_local_state_t lvl_state); +int rockchip_soc_cores_pwr_dm_resume(void); +void __dead2 rockchip_soc_soft_reset(void); +void __dead2 rockchip_soc_system_off(void); +void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi( + const psci_power_state_t *target_state); +void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void); + +extern const unsigned char rockchip_power_domain_tree_desc[]; + +extern void *pmu_cpuson_entrypoint; +extern u_register_t cpuson_entry_point[PLATFORM_CORE_COUNT]; +extern uint32_t cpuson_flags[PLATFORM_CORE_COUNT]; + +extern const mmap_region_t plat_rk_mmap[]; + +uint32_t rockchip_get_uart_base(void); +uint32_t rockchip_get_uart_baudrate(void); +uint32_t rockchip_get_uart_clock(void); + +#endif /* __ASSEMBLER__ */ + +/****************************************************************************** + * cpu up status + * The bits of macro value is not more than 12 bits for cmp instruction! + ******************************************************************************/ +#define PMU_CPU_HOTPLUG 0xf00 +#define PMU_CPU_AUTO_PWRDN 0xf0 +#define PMU_CLST_RET 0xa5 + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h b/arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h new file mode 100644 index 0000000..340d653 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ROCKCHIP_SIP_SVC_H +#define ROCKCHIP_SIP_SVC_H + +/* SMC function IDs for SiP Service queries */ +#define SIP_SVC_CALL_COUNT 0x8200ff00 +#define SIP_SVC_UID 0x8200ff01 +#define SIP_SVC_VERSION 0x8200ff03 + +/* rockchip SiP Service Calls version numbers */ +#define RK_SIP_SVC_VERSION_MAJOR 0x0 +#define RK_SIP_SVC_VERSION_MINOR 0x1 + +/* Number of ROCKCHIP SiP Calls implemented */ +#define RK_COMMON_SIP_NUM_CALLS 0x3 + +enum { + RK_SIP_E_SUCCESS = 0, + RK_SIP_E_INVALID_PARAM = -1 +}; + +#endif /* ROCKCHIP_SIP_SVC_H */ diff --git a/arm-trusted-firmware/plat/rockchip/common/params_setup.c b/arm-trusted-firmware/plat/rockchip/common/params_setup.c new file mode 100644 index 0000000..aec53ee --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/params_setup.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016-2019, 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 +#include + +static struct bl_aux_gpio_info rst_gpio = { .index = UINT_MAX } ; +static struct bl_aux_gpio_info poweroff_gpio = { .index = UINT_MAX }; +static struct bl_aux_gpio_info suspend_gpio[10]; +uint32_t suspend_gpio_cnt; +static struct bl_aux_rk_apio_info suspend_apio; + +#if COREBOOT +static int dt_process_fdt(u_register_t param_from_bl2) +{ + return -ENODEV; +} +#else +static uint32_t rk_uart_base = PLAT_RK_UART_BASE; +static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE; +static uint32_t rk_uart_clock = PLAT_RK_UART_CLOCK; +#define FDT_BUFFER_SIZE 0x20000 +static uint8_t fdt_buffer[FDT_BUFFER_SIZE]; + +void *plat_get_fdt(void) +{ + return &fdt_buffer[0]; +} + +static void plat_rockchip_dt_process_fdt_uart(void *fdt) +{ + const char *path_name = "/chosen"; + const char *prop_name = "stdout-path"; + int node_offset; + int stdout_path_len; + const char *stdout_path; + const char *separator; + const char *baud_start; + char serial_char; + int serial_no; + uint32_t uart_base; + uint32_t baud; + + node_offset = fdt_path_offset(fdt, path_name); + if (node_offset < 0) + return; + + stdout_path = fdt_getprop(fdt, node_offset, prop_name, + &stdout_path_len); + if (stdout_path == NULL) + return; + + /* + * We expect something like: + * "serial0:baudrate" + */ + if (strncmp("serial", stdout_path, 6) != 0) + return; + + serial_char = stdout_path[6]; + serial_no = serial_char - '0'; + + switch (serial_no) { + case 0: + uart_base = UART0_BASE; + break; + case 1: + uart_base = UART1_BASE; + break; + case 2: + uart_base = UART2_BASE; + break; +#ifdef UART3_BASE + case 3: + uart_base = UART3_BASE; + break; +#endif +#ifdef UART4_BASE + case 4: + uart_base = UART4_BASE; + break; +#endif +#ifdef UART5_BASE + case 5: + uart_base = UART5_BASE; + break; +#endif + default: + return; + } + + rk_uart_base = uart_base; + + separator = strchr(stdout_path, ':'); + if (!separator) + return; + + baud = 0; + baud_start = separator + 1; + while (*baud_start != '\0') { + /* + * uart binding is {{{...}}} + * So the baudrate either is the whole string, or + * we end in the parity characters. + */ + if (*baud_start == 'n' || *baud_start == 'o' || + *baud_start == 'e') + break; + + baud = baud * 10 + (*baud_start - '0'); + baud_start++; + } + + rk_uart_baudrate = baud; +} + +static int dt_process_fdt(u_register_t param_from_bl2) +{ + void *fdt = plat_get_fdt(); + int ret; + + ret = fdt_open_into((void *)param_from_bl2, fdt, FDT_BUFFER_SIZE); + if (ret < 0) + return ret; + + plat_rockchip_dt_process_fdt_uart(fdt); + + return 0; +} +#endif + +uint32_t rockchip_get_uart_base(void) +{ +#if COREBOOT + return coreboot_serial.baseaddr; +#else + return rk_uart_base; +#endif +} + +uint32_t rockchip_get_uart_baudrate(void) +{ +#if COREBOOT + return coreboot_serial.baud; +#else + return rk_uart_baudrate; +#endif +} + +uint32_t rockchip_get_uart_clock(void) +{ +#if COREBOOT + return coreboot_serial.input_hertz; +#else + return rk_uart_clock; +#endif +} + +struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void) +{ + if (rst_gpio.index == UINT_MAX) + return NULL; + + return &rst_gpio; +} + +struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void) +{ + if (poweroff_gpio.index == UINT_MAX) + return NULL; + + return &poweroff_gpio; +} + +struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count) +{ + *count = suspend_gpio_cnt; + + return &suspend_gpio[0]; +} + +struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void) +{ + return &suspend_apio; +} + +static bool rk_aux_param_handler(struct bl_aux_param_header *param) +{ + /* Store platform parameters for later processing if needed. */ + switch (param->type) { + case BL_AUX_PARAM_RK_RESET_GPIO: + rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio; + return true; + case BL_AUX_PARAM_RK_POWEROFF_GPIO: + poweroff_gpio = ((struct bl_aux_param_gpio *)param)->gpio; + return true; + case BL_AUX_PARAM_RK_SUSPEND_GPIO: + if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) { + ERROR("Exceeded the supported suspend GPIO number.\n"); + return true; + } + suspend_gpio[suspend_gpio_cnt++] = + ((struct bl_aux_param_gpio *)param)->gpio; + return true; + case BL_AUX_PARAM_RK_SUSPEND_APIO: + suspend_apio = ((struct bl_aux_param_rk_apio *)param)->apio; + return true; + } + + return false; +} + +void params_early_setup(u_register_t plat_param_from_bl2) +{ + int ret; + + /* + * Test if this is a FDT passed as a platform-specific parameter + * block. + */ + ret = dt_process_fdt(plat_param_from_bl2); + if (!ret) { + return; + } else if (ret != -FDT_ERR_BADMAGIC) { + /* + * If we found an FDT but couldn't parse it (e.g. corrupt, not + * enough space), return and don't attempt to parse the param + * as something else, since we know that will also fail. All + * we're doing is setting up UART, this doesn't need to be + * fatal. + */ + WARN("%s: found FDT but could not parse: error %d\n", + __func__, ret); + return; + } + + bl_aux_params_parse(plat_param_from_bl2, rk_aux_param_handler); +} diff --git a/arm-trusted-firmware/plat/rockchip/common/plat_pm.c b/arm-trusted-firmware/plat/rockchip/common/plat_pm.c new file mode 100644 index 0000000..6926887 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/plat_pm.c @@ -0,0 +1,413 @@ +/* + * 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 + +/* Macros to read the rk power domain state */ +#define RK_CORE_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define RK_CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define RK_SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +static uintptr_t rockchip_sec_entrypoint; + +#pragma weak rockchip_soc_cores_pwr_dm_on +#pragma weak rockchip_soc_hlvl_pwr_dm_off +#pragma weak rockchip_soc_cores_pwr_dm_off +#pragma weak rockchip_soc_sys_pwr_dm_suspend +#pragma weak rockchip_soc_cores_pwr_dm_suspend +#pragma weak rockchip_soc_hlvl_pwr_dm_suspend +#pragma weak rockchip_soc_hlvl_pwr_dm_on_finish +#pragma weak rockchip_soc_cores_pwr_dm_on_finish +#pragma weak rockchip_soc_sys_pwr_dm_resume +#pragma weak rockchip_soc_hlvl_pwr_dm_resume +#pragma weak rockchip_soc_cores_pwr_dm_resume +#pragma weak rockchip_soc_soft_reset +#pragma weak rockchip_soc_system_off +#pragma weak rockchip_soc_sys_pd_pwr_dn_wfi +#pragma weak rockchip_soc_cores_pd_pwr_dn_wfi + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl, + plat_local_state_t lvl_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_cores_pwr_dm_off(void) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_cores_pwr_dm_suspend(void) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl, + plat_local_state_t lvl_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl, + plat_local_state_t lvl_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl, + plat_local_state_t lvl_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int rockchip_soc_cores_pwr_dm_resume(void) +{ + return PSCI_E_NOT_SUPPORTED; +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + while (1) + ; +} + +void __dead2 rockchip_soc_system_off(void) +{ + while (1) + ; +} + +void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi( + const psci_power_state_t *target_state) +{ + psci_power_down_wfi(); +} + +void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void) +{ + psci_power_down_wfi(); +} + +/******************************************************************************* + * Rockchip standard platform handler called to check the validity of the power + * state parameter. + ******************************************************************************/ +int rockchip_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pstate = psci_get_pstate_type(power_state); + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; + + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's probably to enter standby only on power level 0 + * ignore any other power level. + */ + if (pwr_lvl != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[MPIDR_AFFLVL0] = + PLAT_MAX_RET_STATE; + } else { + for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + PLAT_MAX_OFF_STATE; + + for (i = (pwr_lvl + 1); i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = + PLAT_MAX_RET_STATE; + } + + /* We expect the 'state id' to be zero */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +void rockchip_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +/******************************************************************************* + * RockChip handler called when a CPU is about to enter standby. + ******************************************************************************/ +void rockchip_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr; + + assert(cpu_state == PLAT_MAX_RET_STATE); + + scr = read_scr_el3(); + /* Enable PhysicalIRQ bit for NS world to wake the CPU */ + write_scr_el3(scr | SCR_IRQ_BIT); + isb(); + dsb(); + wfi(); + + /* + * Restore SCR to the original value, synchronisation of scr_el3 is + * done by eret while el3_exit to save some execution cycles. + */ + write_scr_el3(scr); +} + +/******************************************************************************* + * RockChip handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +int rockchip_pwr_domain_on(u_register_t mpidr) +{ + return rockchip_soc_cores_pwr_dm_on(mpidr, rockchip_sec_entrypoint); +} + +/******************************************************************************* + * RockChip handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void rockchip_pwr_domain_off(const psci_power_state_t *target_state) +{ + uint32_t lvl; + plat_local_state_t lvl_state; + int ret; + + assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE); + + plat_rockchip_gic_cpuif_disable(); + + if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + plat_cci_disable(); + + rockchip_soc_cores_pwr_dm_off(); + + for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + lvl_state = target_state->pwr_domain_state[lvl]; + ret = rockchip_soc_hlvl_pwr_dm_off(lvl, lvl_state); + if (ret == PSCI_E_NOT_SUPPORTED) + break; + } +} + +/******************************************************************************* + * RockChip handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void rockchip_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + uint32_t lvl; + plat_local_state_t lvl_state; + int ret; + + if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_rockchip_gic_cpuif_disable(); + + if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + rockchip_soc_sys_pwr_dm_suspend(); + else + rockchip_soc_cores_pwr_dm_suspend(); + + /* Perform the common cluster specific operations */ + if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + plat_cci_disable(); + + if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + return; + + for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + lvl_state = target_state->pwr_domain_state[lvl]; + ret = rockchip_soc_hlvl_pwr_dm_suspend(lvl, lvl_state); + if (ret == PSCI_E_NOT_SUPPORTED) + break; + } +} + +/******************************************************************************* + * RockChip handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void rockchip_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + uint32_t lvl; + plat_local_state_t lvl_state; + int ret; + + assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE); + + for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + lvl_state = target_state->pwr_domain_state[lvl]; + ret = rockchip_soc_hlvl_pwr_dm_on_finish(lvl, lvl_state); + if (ret == PSCI_E_NOT_SUPPORTED) + break; + } + + rockchip_soc_cores_pwr_dm_on_finish(); + + /* Perform the common cluster specific operations */ + if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + /* Enable coherency if this cluster was off */ + plat_cci_enable(); + } + + /* Enable the gic cpu interface */ + plat_rockchip_gic_pcpu_init(); + + /* Program the gic per-cpu distributor or re-distributor interface */ + plat_rockchip_gic_cpuif_enable(); +} + +/******************************************************************************* + * RockChip handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ******************************************************************************/ +void rockchip_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + uint32_t lvl; + plat_local_state_t lvl_state; + int ret; + + /* Nothing to be done on waking up from retention from CPU level */ + if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + rockchip_soc_sys_pwr_dm_resume(); + goto comm_finish; + } + + for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + lvl_state = target_state->pwr_domain_state[lvl]; + ret = rockchip_soc_hlvl_pwr_dm_resume(lvl, lvl_state); + if (ret == PSCI_E_NOT_SUPPORTED) + break; + } + + rockchip_soc_cores_pwr_dm_resume(); + + /* + * Program the gic per-cpu distributor or re-distributor interface. + * For sys power domain operation, resuming of the gic needs to operate + * in rockchip_soc_sys_pwr_dm_resume(), according to the sys power mode + * implements. + */ + plat_rockchip_gic_cpuif_enable(); + +comm_finish: + /* Perform the common cluster specific operations */ + if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + /* Enable coherency if this cluster was off */ + plat_cci_enable(); + } +} + +/******************************************************************************* + * RockChip handlers to reboot the system + ******************************************************************************/ +static void __dead2 rockchip_system_reset(void) +{ + rockchip_soc_soft_reset(); +} + +/******************************************************************************* + * RockChip handlers to power off the system + ******************************************************************************/ +static void __dead2 rockchip_system_poweroff(void) +{ + rockchip_soc_system_off(); +} + +static void __dead2 rockchip_pd_pwr_down_wfi( + const psci_power_state_t *target_state) +{ + if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + rockchip_soc_sys_pd_pwr_dn_wfi(); + else + rockchip_soc_cores_pd_pwr_dn_wfi(target_state); +} + +/******************************************************************************* + * Export the platform handlers via plat_rockchip_psci_pm_ops. The rockchip + * standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +const plat_psci_ops_t plat_rockchip_psci_pm_ops = { + .cpu_standby = rockchip_cpu_standby, + .pwr_domain_on = rockchip_pwr_domain_on, + .pwr_domain_off = rockchip_pwr_domain_off, + .pwr_domain_suspend = rockchip_pwr_domain_suspend, + .pwr_domain_on_finish = rockchip_pwr_domain_on_finish, + .pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = rockchip_pd_pwr_down_wfi, + .system_reset = rockchip_system_reset, + .system_off = rockchip_system_poweroff, + .validate_power_state = rockchip_validate_power_state, + .get_sys_suspend_power_state = rockchip_get_sys_suspend_power_state +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &plat_rockchip_psci_pm_ops; + rockchip_sec_entrypoint = sec_entrypoint; + return 0; +} + +uintptr_t plat_get_sec_entrypoint(void) +{ + assert(rockchip_sec_entrypoint); + return rockchip_sec_entrypoint; +} diff --git a/arm-trusted-firmware/plat/rockchip/common/plat_topology.c b/arm-trusted-firmware/plat/rockchip/common/plat_topology.c new file mode 100644 index 0000000..4987eeb --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/plat_topology.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +/******************************************************************************* + * This function returns the RockChip default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rockchip_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + cpu_id = mpidr & MPIDR_AFFLVL_MASK; +#ifdef PLAT_RK_MPIDR_CLUSTER_MASK + cluster_id = mpidr & PLAT_RK_MPIDR_CLUSTER_MASK; +#else + cluster_id = mpidr & MPIDR_CLUSTER_MASK; +#endif + + cpu_id += (cluster_id >> PLAT_RK_CLST_TO_CPUID_SHIFT); + + if (cpu_id >= PLATFORM_CORE_COUNT) + return -1; + + return cpu_id; +} diff --git a/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S b/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S new file mode 100644 index 0000000..6cea2ea --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl sys_sleep_flag_sram + .globl pmu_cpuson_entrypoint + + .macro pmusram_entry_func _name + .section .pmusram.entry, "ax" + .type \_name, %function + .cfi_startproc + \_name: + .endm + +pmusram_entry_func pmu_cpuson_entrypoint + adr x5, sys_sleep_flag_sram + ldr w2, [x5, #PSRAM_DT_PM_FLAG] + + tbz w2, #PM_WARM_BOOT_SHT, sys_resume_sp + ldr x1, =platform_cpu_warmboot + br x1 +sys_resume_sp: + adr x5, sys_sleep_flag_sram + ldr x1, [x5, #PSRAM_DT_SP] + mov sp, x1 +ddr_resume: + ldr x1, [x5, #PSRAM_DT_DDR_FUNC] + cmp x1, #0 + b.eq sys_resume + blr x1 +sys_resume: + ldr x1, =bl31_warm_entrypoint + br x1 +endfunc pmu_cpuson_entrypoint + + .section .pmusram.data, "a" + .align 3 +sys_sleep_flag_sram: + .rept PSRAM_DT_SIZE_WORDS + .word 0 + .endr diff --git a/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h b/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h new file mode 100644 index 0000000..34af29a --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CPU_ON_FIXED_ADDR_H__ +#define __CPU_ON_FIXED_ADDR_H__ + +/***************************************************************************** + * define data offset in struct psram_data + *****************************************************************************/ +#define PSRAM_DT_SP 0x0 +#define PSRAM_DT_DDR_FUNC 0x8 +#define PSRAM_DT_DDR_DATA 0x10 +#define PSRAM_DT_DDRFLAG 0x18 +#define PSRAM_DT_MPIDR 0x1c +#define PSRAM_DT_PM_FLAG 0x20 +#define PSRAM_DT_END 0x24 + +/* reserve 4 byte */ +#define PSRAM_DT_END_RES4 (PSRAM_DT_END + 4) + +#define PSRAM_DT_SIZE_WORDS (PSRAM_DT_END_RES4 / 4) + +#define PM_WARM_BOOT_SHT 0 +#define PM_WARM_BOOT_BIT (1 << PM_WARM_BOOT_SHT) + +#ifndef __ASSEMBLER__ + +struct psram_data_t { + uint64_t sp; + uint64_t ddr_func; + uint64_t ddr_data; + uint32_t ddr_flag; + uint32_t boot_mpidr; + uint32_t pm_flag; +}; + +CASSERT(__builtin_offsetof(struct psram_data_t, sp) == PSRAM_DT_SP, + assert_psram_dt_sp_offset_mistmatch); +CASSERT(__builtin_offsetof(struct psram_data_t, ddr_func) == PSRAM_DT_DDR_FUNC, + assert_psram_dt_ddr_func_offset_mistmatch); +CASSERT(__builtin_offsetof(struct psram_data_t, ddr_data) == PSRAM_DT_DDR_DATA, + assert_psram_dt_ddr_data_offset_mistmatch); +CASSERT(__builtin_offsetof(struct psram_data_t, ddr_flag) == PSRAM_DT_DDRFLAG, + assert_psram_dt_ddr_flag_offset_mistmatch); +CASSERT(__builtin_offsetof(struct psram_data_t, boot_mpidr) == PSRAM_DT_MPIDR, + assert_psram_dt_mpidr_offset_mistmatch); + +extern void *sys_sleep_flag_sram; + +#endif /* __ASSEMBLER__ */ + +#endif diff --git a/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c b/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c new file mode 100644 index 0000000..8db2b30 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way the GICv2 driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_rockchip_gic_driver_init +#pragma weak plat_rockchip_gic_init +#pragma weak plat_rockchip_gic_cpuif_enable +#pragma weak plat_rockchip_gic_cpuif_disable +#pragma weak plat_rockchip_gic_pcpu_init + +/****************************************************************************** + * List of interrupts. + *****************************************************************************/ +static const interrupt_prop_t g0_interrupt_props[] = { + PLAT_RK_GICV2_G0_IRQS +}; + +/* + * Ideally `rockchip_gic_data` structure definition should be a `const` but it + * is kept as modifiable for overwriting with different GICD and GICC base when + * running on FVP with VE memory map. + */ +gicv2_driver_data_t rockchip_gic_data = { + .gicd_base = PLAT_RK_GICD_BASE, + .gicc_base = PLAT_RK_GICC_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +/****************************************************************************** + * RockChip common helper to initialize the GICv2 only driver. + *****************************************************************************/ +void plat_rockchip_gic_driver_init(void) +{ + gicv2_driver_init(&rockchip_gic_data); +} + +void plat_rockchip_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * RockChip common helper to enable the GICv2 CPU interface + *****************************************************************************/ +void plat_rockchip_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * RockChip common helper to disable the GICv2 CPU interface + *****************************************************************************/ +void plat_rockchip_gic_cpuif_disable(void) +{ + gicv2_cpuif_disable(); +} + +/****************************************************************************** + * RockChip common helper to initialize the per cpu distributor interface + * in GICv2 + *****************************************************************************/ +void plat_rockchip_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); +} diff --git a/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c b/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c new file mode 100644 index 0000000..edae2ef --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way the GICv3 driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_rockchip_gic_driver_init +#pragma weak plat_rockchip_gic_init +#pragma weak plat_rockchip_gic_cpuif_enable +#pragma weak plat_rockchip_gic_cpuif_disable +#pragma weak plat_rockchip_gic_pcpu_init + +/* The GICv3 driver only needs to be initialized in EL3 */ +uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t g01s_interrupt_props[] = { + PLAT_RK_GICV3_G0_IRQS, + PLAT_RK_GICV3_G1S_IRQS +}; + +static unsigned int plat_rockchip_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +const gicv3_driver_data_t rockchip_gic_data = { + .gicd_base = PLAT_RK_GICD_BASE, + .gicr_base = PLAT_RK_GICR_BASE, + .interrupt_props = g01s_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g01s_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = plat_rockchip_mpidr_to_core_pos, +}; + +void plat_rockchip_gic_driver_init(void) +{ + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ +#ifdef IMAGE_BL31 + gicv3_driver_init(&rockchip_gic_data); +#endif +} + +/****************************************************************************** + * RockChip common helper to initialize the GIC. Only invoked + * by BL31 + *****************************************************************************/ +void plat_rockchip_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * RockChip common helper to enable the GIC CPU interface + *****************************************************************************/ +void plat_rockchip_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * RockChip common helper to disable the GIC CPU interface + *****************************************************************************/ +void plat_rockchip_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/****************************************************************************** + * RockChip common helper to initialize the per-cpu redistributor interface + * in GICv3 + *****************************************************************************/ +void plat_rockchip_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c b/arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c new file mode 100644 index 0000000..27ef042 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include + +/* Rockchip SiP Service UUID */ +DEFINE_SVC_UUID2(rk_sip_svc_uid, + 0xe2c76fe8, 0x3e31, 0xe611, 0xb7, 0x0d, + 0x8f, 0x88, 0xee, 0x74, 0x7b, 0x72); + +#pragma weak rockchip_plat_sip_handler +uintptr_t rockchip_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) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +/* + * This function is responsible for handling all SiP calls from the NS world + */ +uintptr_t sip_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) +{ + uint32_t ns; + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + if (!ns) + SMC_RET1(handle, SMC_UNK); + + switch (smc_fid) { + case SIP_SVC_CALL_COUNT: + /* Return the number of Rockchip SiP Service Calls. */ + SMC_RET1(handle, + RK_COMMON_SIP_NUM_CALLS + RK_PLAT_SIP_NUM_CALLS); + + case SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, rk_sip_svc_uid); + + case SIP_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, RK_SIP_SVC_VERSION_MAJOR, + RK_SIP_SVC_VERSION_MINOR); + + default: + return rockchip_plat_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + } +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + rockchip_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + sip_smc_handler +); diff --git a/arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c b/arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c new file mode 100644 index 0000000..1898977 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * Ideally, a random number should be returned instead of the + * combination of a timer's value and a compile-time constant. + * As the virt platform does not have any random number generator, + * this is better than nothing but not necessarily really secure. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} + diff --git a/arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c b/arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c new file mode 100644 index 0000000..0237b16 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016-2019, 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 + +static entry_point_info_t bl33_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type. + * A NULL pointer is returned if the image does not exist. + ******************************************************************************/ +entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) +{ + entry_point_info_t *next_image_info; + + next_image_info = &bl33_ep_info; + + if (next_image_info->pc == 0U) { + return NULL; + } + + return next_image_info; +} + +#pragma weak params_early_setup +void params_early_setup(u_register_t plat_param_from_bl2) +{ +} + +unsigned int plat_is_my_cpu_primary(void); + +/******************************************************************************* + * Perform any BL32 specific platform actions. + ******************************************************************************/ +void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + params_early_setup(arg1); + + if (rockchip_get_uart_base() != 0) + console_16550_register(rockchip_get_uart_base(), + rockchip_get_uart_clock(), + rockchip_get_uart_baudrate(), &console); + + VERBOSE("sp_min_setup\n"); + + bl31_params_parse_helper(arg0, NULL, &bl33_ep_info); +} + +/******************************************************************************* + * Perform any sp_min platform setup code + ******************************************************************************/ +void sp_min_platform_setup(void) +{ + generic_delay_timer_init(); + plat_rockchip_soc_init(); + + /* Initialize the gic cpu and distributor interfaces */ + plat_rockchip_gic_driver_init(); + plat_rockchip_gic_init(); + plat_rockchip_pmu_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void sp_min_plat_arch_setup(void) +{ + plat_cci_init(); + plat_cci_enable(); + + plat_configure_mmu_svc_mon(BL_CODE_BASE, + BL_COHERENT_RAM_END - BL_CODE_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); +} + +void sp_min_plat_fiq_handler(uint32_t id) +{ + VERBOSE("[sp_min] interrupt #%d\n", id); +} diff --git a/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..a757621 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +.globl clst_warmboot_data + +.macro func_rockchip_clst_warmboot +.endm + +.macro rockchip_clst_warmboot_data +clst_warmboot_data: + .rept PLATFORM_CLUSTER_COUNT + .word 0 + .endr +.endm diff --git a/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c new file mode 100644 index 0000000..5f4e64f --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c @@ -0,0 +1,1071 @@ +/* + * Copyright (c) 2019, 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 +#include +#include +#include + +DEFINE_BAKERY_LOCK(rockchip_pd_lock); +#define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock) +#define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock) +#define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock) + +static struct psram_data_t *psram_boot_cfg = + (struct psram_data_t *)&sys_sleep_flag_sram; + +/* + * There are two ways to powering on or off on core. + * 1) Control it power domain into on or off in PMU_PWRDN_CON reg, + * it is core_pwr_pd mode + * 2) Enable the core power manage in PMU_CORE_PM_CON reg, + * then, if the core enter into wfi, it power domain will be + * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode + * so we need core_pm_cfg_info to distinguish which method be used now. + */ + +static uint32_t cores_pd_cfg_info[PLATFORM_CORE_COUNT] +#if USE_COHERENT_MEM +__attribute__ ((section("tzfw_coherent_mem"))) +#endif +; + +struct px30_sleep_ddr_data { + uint32_t clk_sel0; + uint32_t cru_mode_save; + uint32_t cru_pmu_mode_save; + uint32_t ddrc_hwlpctl; + uint32_t ddrc_pwrctrl; + uint32_t ddrgrf_con0; + uint32_t ddrgrf_con1; + uint32_t ddrstdby_con0; + uint32_t gpio0b_iomux; + uint32_t gpio0c_iomux; + uint32_t pmu_pwrmd_core_l; + uint32_t pmu_pwrmd_core_h; + uint32_t pmu_pwrmd_cmm_l; + uint32_t pmu_pwrmd_cmm_h; + uint32_t pmu_wkup_cfg2_l; + uint32_t pmu_cru_clksel_con0; + uint32_t pmugrf_soc_con0; + uint32_t pmusgrf_soc_con0; + uint32_t pmic_slp_iomux; + uint32_t pgrf_pvtm_con[2]; + uint32_t cru_clk_gate[CRU_CLKGATES_CON_CNT]; + uint32_t cru_pmu_clk_gate[CRU_PMU_CLKGATE_CON_CNT]; + uint32_t cru_plls_con_save[END_PLL_ID][PLL_CON_CNT]; + uint32_t cpu_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t gpu_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp_128m_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp_rd_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp_wr_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp_m1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vip_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t rga_rd_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t rga_wr_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vop_m0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vop_m1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vpu_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vpu_r128_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t dcf_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t dmac_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t crypto_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t gmac_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t emmc_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t nand_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t sdio_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t sfc_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t sdmmc_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t usb_host_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t usb_otg_qos[CPU_AXI_QOS_NUM_REGS]; +}; + +static struct px30_sleep_ddr_data ddr_data +#if USE_COHERENT_MEM +__attribute__ ((section("tzfw_coherent_mem"))) +#endif +; + +static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) +{ + assert(cpu_id < PLATFORM_CORE_COUNT); + return cores_pd_cfg_info[cpu_id]; +} + +static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value) +{ + assert(cpu_id < PLATFORM_CORE_COUNT); + cores_pd_cfg_info[cpu_id] = value; +#if !USE_COHERENT_MEM + flush_dcache_range((uintptr_t)&cores_pd_cfg_info[cpu_id], + sizeof(uint32_t)); +#endif +} + +static inline uint32_t pmu_power_domain_st(uint32_t pd) +{ + return mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd) ? + pmu_pd_off : + pmu_pd_on; +} + +static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state) +{ + uint32_t loop = 0; + int ret = 0; + + rockchip_pd_lock_get(); + + mmio_write_32(PMU_BASE + PMU_PWRDN_CON, + BITS_WITH_WMASK(pd_state, 0x1, pd)); + dsb(); + + while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) { + udelay(1); + loop++; + } + + if (pmu_power_domain_st(pd) != pd_state) { + WARN("%s: %d, %d, error!\n", __func__, pd, pd_state); + ret = -EINVAL; + } + + rockchip_pd_lock_rls(); + + return ret; +} + +static inline uint32_t pmu_bus_idle_st(uint32_t bus) +{ + return !!((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus)) && + (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus + 16))); +} + +static void pmu_bus_idle_req(uint32_t bus, uint32_t state) +{ + uint32_t wait_cnt = 0; + + mmio_write_32(PMU_BASE + PMU_BUS_IDLE_REQ, + BITS_WITH_WMASK(state, 0x1, bus)); + + while (pmu_bus_idle_st(bus) != state && + wait_cnt < BUS_IDLE_LOOP) { + udelay(1); + wait_cnt++; + } + + if (pmu_bus_idle_st(bus) != state) + WARN("%s:idle_st=0x%x, bus_id=%d\n", + __func__, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST), bus); +} + +static void qos_save(void) +{ + /* scu powerdomain will power off, so cpu qos should be saved */ + SAVE_QOS(ddr_data.cpu_qos, CPU); + + if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) + SAVE_QOS(ddr_data.gpu_qos, GPU); + if (pmu_power_domain_st(PD_VI) == pmu_pd_on) { + SAVE_QOS(ddr_data.isp_128m_qos, ISP_128M); + SAVE_QOS(ddr_data.isp_rd_qos, ISP_RD); + SAVE_QOS(ddr_data.isp_wr_qos, ISP_WR); + SAVE_QOS(ddr_data.isp_m1_qos, ISP_M1); + SAVE_QOS(ddr_data.vip_qos, VIP); + } + if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { + SAVE_QOS(ddr_data.rga_rd_qos, RGA_RD); + SAVE_QOS(ddr_data.rga_wr_qos, RGA_WR); + SAVE_QOS(ddr_data.vop_m0_qos, VOP_M0); + SAVE_QOS(ddr_data.vop_m1_qos, VOP_M1); + } + if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) { + SAVE_QOS(ddr_data.vpu_qos, VPU); + SAVE_QOS(ddr_data.vpu_r128_qos, VPU_R128); + } + if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) { + SAVE_QOS(ddr_data.emmc_qos, EMMC); + SAVE_QOS(ddr_data.nand_qos, NAND); + SAVE_QOS(ddr_data.sdio_qos, SDIO); + SAVE_QOS(ddr_data.sfc_qos, SFC); + } + if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) + SAVE_QOS(ddr_data.gmac_qos, GMAC); + if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on) + SAVE_QOS(ddr_data.crypto_qos, CRYPTO); + if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on) + SAVE_QOS(ddr_data.sdmmc_qos, SDMMC); + if (pmu_power_domain_st(PD_USB) == pmu_pd_on) { + SAVE_QOS(ddr_data.usb_host_qos, USB_HOST); + SAVE_QOS(ddr_data.usb_otg_qos, USB_OTG); + } +} + +static void qos_restore(void) +{ + RESTORE_QOS(ddr_data.cpu_qos, CPU); + + if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) + RESTORE_QOS(ddr_data.gpu_qos, GPU); + if (pmu_power_domain_st(PD_VI) == pmu_pd_on) { + RESTORE_QOS(ddr_data.isp_128m_qos, ISP_128M); + RESTORE_QOS(ddr_data.isp_rd_qos, ISP_RD); + RESTORE_QOS(ddr_data.isp_wr_qos, ISP_WR); + RESTORE_QOS(ddr_data.isp_m1_qos, ISP_M1); + RESTORE_QOS(ddr_data.vip_qos, VIP); + } + if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { + RESTORE_QOS(ddr_data.rga_rd_qos, RGA_RD); + RESTORE_QOS(ddr_data.rga_wr_qos, RGA_WR); + RESTORE_QOS(ddr_data.vop_m0_qos, VOP_M0); + RESTORE_QOS(ddr_data.vop_m1_qos, VOP_M1); + } + if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) { + RESTORE_QOS(ddr_data.vpu_qos, VPU); + RESTORE_QOS(ddr_data.vpu_r128_qos, VPU_R128); + } + if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) { + RESTORE_QOS(ddr_data.emmc_qos, EMMC); + RESTORE_QOS(ddr_data.nand_qos, NAND); + RESTORE_QOS(ddr_data.sdio_qos, SDIO); + RESTORE_QOS(ddr_data.sfc_qos, SFC); + } + if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) + RESTORE_QOS(ddr_data.gmac_qos, GMAC); + if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on) + RESTORE_QOS(ddr_data.crypto_qos, CRYPTO); + if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on) + RESTORE_QOS(ddr_data.sdmmc_qos, SDMMC); + if (pmu_power_domain_st(PD_USB) == pmu_pd_on) { + RESTORE_QOS(ddr_data.usb_host_qos, USB_HOST); + RESTORE_QOS(ddr_data.usb_otg_qos, USB_OTG); + } +} + +static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state) +{ + uint32_t state; + + if (pmu_power_domain_st(pd_id) == pd_state) + goto out; + + if (pd_state == pmu_pd_on) + pmu_power_domain_ctr(pd_id, pd_state); + + state = (pd_state == pmu_pd_off) ? bus_idle : bus_active; + + switch (pd_id) { + case PD_GPU: + pmu_bus_idle_req(BUS_ID_GPU, state); + break; + case PD_VI: + pmu_bus_idle_req(BUS_ID_VI, state); + break; + case PD_VO: + pmu_bus_idle_req(BUS_ID_VO, state); + break; + case PD_VPU: + pmu_bus_idle_req(BUS_ID_VPU, state); + break; + case PD_MMC_NAND: + pmu_bus_idle_req(BUS_ID_MMC, state); + break; + case PD_GMAC: + pmu_bus_idle_req(BUS_ID_GMAC, state); + break; + case PD_CRYPTO: + pmu_bus_idle_req(BUS_ID_CRYPTO, state); + break; + case PD_SDCARD: + pmu_bus_idle_req(BUS_ID_SDCARD, state); + break; + case PD_USB: + pmu_bus_idle_req(BUS_ID_USB, state); + break; + default: + break; + } + + if (pd_state == pmu_pd_off) + pmu_power_domain_ctr(pd_id, pd_state); + +out: + return 0; +} + +static uint32_t pmu_powerdomain_state; + +static void pmu_power_domains_suspend(void) +{ + uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT]; + + clk_gate_con_save(clkgt_save); + clk_gate_con_disable(); + qos_save(); + + pmu_powerdomain_state = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); + pmu_set_power_domain(PD_GPU, pmu_pd_off); + pmu_set_power_domain(PD_VI, pmu_pd_off); + pmu_set_power_domain(PD_VO, pmu_pd_off); + pmu_set_power_domain(PD_VPU, pmu_pd_off); + pmu_set_power_domain(PD_MMC_NAND, pmu_pd_off); + pmu_set_power_domain(PD_GMAC, pmu_pd_off); + pmu_set_power_domain(PD_CRYPTO, pmu_pd_off); + pmu_set_power_domain(PD_SDCARD, pmu_pd_off); + pmu_set_power_domain(PD_USB, pmu_pd_off); + + clk_gate_con_restore(clkgt_save); +} + +static void pmu_power_domains_resume(void) +{ + uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT]; + + clk_gate_con_save(clkgt_save); + clk_gate_con_disable(); + + if (!(pmu_powerdomain_state & BIT(PD_USB))) + pmu_set_power_domain(PD_USB, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_SDCARD))) + pmu_set_power_domain(PD_SDCARD, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_CRYPTO))) + pmu_set_power_domain(PD_CRYPTO, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_GMAC))) + pmu_set_power_domain(PD_GMAC, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_MMC_NAND))) + pmu_set_power_domain(PD_MMC_NAND, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VPU))) + pmu_set_power_domain(PD_VPU, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VO))) + pmu_set_power_domain(PD_VO, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VI))) + pmu_set_power_domain(PD_VI, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_GPU))) + pmu_set_power_domain(PD_GPU, pmu_pd_on); + + qos_restore(); + clk_gate_con_restore(clkgt_save); +} + +static int check_cpu_wfie(uint32_t cpu) +{ + uint32_t loop = 0, wfie_msk = CKECK_WFEI_MSK << cpu; + + while (!(mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) && + (loop < WFEI_CHECK_LOOP)) { + udelay(1); + loop++; + } + + if ((mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) == 0) { + WARN("%s: %d, %d, error!\n", __func__, cpu, wfie_msk); + return -EINVAL; + } + + return 0; +} + +static int cpus_power_domain_on(uint32_t cpu_id) +{ + uint32_t cpu_pd, apm_value, cfg_info, loop = 0; + + cpu_pd = PD_CPU0 + cpu_id; + cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); + + if (cfg_info == core_pwr_pd) { + /* disable apm cfg */ + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } + pmu_power_domain_ctr(cpu_pd, pmu_pd_on); + } else { + /* wait cpu down */ + while (pmu_power_domain_st(cpu_pd) == pmu_pd_on && loop < 100) { + udelay(2); + loop++; + } + + /* return error if can't wait cpu down */ + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + WARN("%s:can't wait cpu down\n", __func__); + return -EINVAL; + } + + /* power up cpu in power down state */ + apm_value = BIT(core_pm_sft_wakeup_en); + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(apm_value)); + } + + return 0; +} + +static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) +{ + uint32_t cpu_pd, apm_value; + + cpu_pd = PD_CPU0 + cpu_id; + if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) + return 0; + + if (pd_cfg == core_pwr_pd) { + if (check_cpu_wfie(cpu_id)) + return -EINVAL; + /* disable apm cfg */ + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } else { + set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); + apm_value = BIT(core_pm_en) | BIT(core_pm_dis_int); + if (pd_cfg == core_pwr_wfi_int) + apm_value |= BIT(core_pm_int_wakeup_en); + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(apm_value)); + } + + return 0; +} + +static void nonboot_cpus_off(void) +{ + uint32_t boot_cpu, cpu; + + boot_cpu = plat_my_core_pos(); + + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { + if (cpu == boot_cpu) + continue; + cpus_power_domain_off(cpu, core_pwr_pd); + } +} + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, + uint64_t entrypoint) +{ + uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpu_id] = entrypoint; + dsb(); + + cpus_power_domain_on(cpu_id); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_off(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + cpus_power_domain_off(cpu_id, core_pwr_wfi); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_suspend(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; + cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint(); + dsb(); + + cpus_power_domain_off(cpu_id, core_pwr_wfi_int); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_resume(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + /* Disable core_pm */ + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + WITH_16BITS_WMSK(CORES_PM_DISABLE)); + + return PSCI_E_SUCCESS; +} + +#define CLK_MSK_GATING(msk, con) \ + mmio_write_32(CRU_BASE + (con), ((msk) << 16) | 0xffff) +#define CLK_MSK_UNGATING(msk, con) \ + mmio_write_32(CRU_BASE + (con), ((~(msk)) << 16) | 0xffff) + +static uint32_t clk_ungt_msk[CRU_CLKGATES_CON_CNT] = { + 0xe0ff, 0xffff, 0x0000, 0x0000, + 0x0000, 0x0380, 0x0000, 0x0000, + 0x07c0, 0x0000, 0x0000, 0x000f, + 0x0061, 0x1f02, 0x0440, 0x1801, + 0x004b, 0x0000 +}; + +static uint32_t clk_pmu_ungt_msk[CRU_PMU_CLKGATE_CON_CNT] = { + 0xf1ff, 0x0310 +}; + +void clk_gate_suspend(void) +{ + int i; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) { + ddr_data.cru_clk_gate[i] = + mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i)); + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + WITH_16BITS_WMSK(~clk_ungt_msk[i])); + } + + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) { + ddr_data.cru_pmu_clk_gate[i] = + mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i)); + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), + WITH_16BITS_WMSK(~clk_pmu_ungt_msk[i])); + } +} + +void clk_gate_resume(void) +{ + int i; + + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), + WITH_16BITS_WMSK(ddr_data.cru_pmu_clk_gate[i])); + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + WITH_16BITS_WMSK(ddr_data.cru_clk_gate[i])); +} + +static void pvtm_32k_config(void) +{ + uint32_t pvtm_freq_khz, pvtm_div; + + ddr_data.pmu_cru_clksel_con0 = + mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0)); + + ddr_data.pgrf_pvtm_con[0] = + mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON0); + ddr_data.pgrf_pvtm_con[1] = + mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON1); + + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + BITS_WITH_WMASK(0, 0x3, pgrf_pvtm_st)); + dsb(); + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_en)); + dsb(); + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1, PVTM_CALC_CNT); + dsb(); + + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_st)); + + /* pmugrf_pvtm_st0 will be clear after PVTM start, + * which will cost about 6 cycles of pvtm at least. + * So we wait 30 cycles of pvtm for security. + */ + while (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) < 30) + ; + + dsb(); + while (!(mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST0) & 0x1)) + ; + + pvtm_freq_khz = + (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) * 24000 + + PVTM_CALC_CNT / 2) / PVTM_CALC_CNT; + pvtm_div = (pvtm_freq_khz + 16) / 32; + + /* pvtm_div = div_factor << 2 + 1, + * so div_factor = (pvtm_div - 1) >> 2. + * But the operation ">> 2" will clear the low bit of pvtm_div, + * so we don't have to do "- 1" for compasation + */ + pvtm_div = pvtm_div >> 2; + if (pvtm_div > 0x3f) + pvtm_div = 0x3f; + + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + BITS_WITH_WMASK(pvtm_div, 0x3f, pgrf_pvtm_div)); + + /* select pvtm as 32k source */ + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0), + BITS_WITH_WMASK(1, 0x3U, 14)); +} + +static void pvtm_32k_config_restore(void) +{ + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0), + ddr_data.pmu_cru_clksel_con0 | BITS_WMSK(0x3U, 14)); + + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, + WITH_16BITS_WMSK(ddr_data.pgrf_pvtm_con[0])); + mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1, + ddr_data.pgrf_pvtm_con[1]); +} + +static void ddr_sleep_config(void) +{ + /* disable ddr pd, sr */ + ddr_data.ddrc_pwrctrl = mmio_read_32(DDR_UPCTL_BASE + 0x30); + mmio_write_32(DDR_UPCTL_BASE + 0x30, BITS_WITH_WMASK(0x0, 0x3, 0)); + + /* disable ddr auto gt */ + ddr_data.ddrgrf_con1 = mmio_read_32(DDRGRF_BASE + 0x4); + mmio_write_32(DDRGRF_BASE + 0x4, BITS_WITH_WMASK(0x0, 0x1f, 0)); + + /* disable ddr standby */ + ddr_data.ddrstdby_con0 = mmio_read_32(DDR_STDBY_BASE + 0x0); + mmio_write_32(DDR_STDBY_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 0)); + while ((mmio_read_32(DDR_UPCTL_BASE + 0x4) & 0x7) != 1) + ; + + /* ddr pmu ctrl */ + ddr_data.ddrgrf_con0 = mmio_read_32(DDRGRF_BASE + 0x0); + mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 5)); + dsb(); + mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x1, 0x1, 4)); + + /* ddr ret sel */ + ddr_data.pmugrf_soc_con0 = + mmio_read_32(PMUGRF_BASE + PMUGRF_SOC_CON(0)); + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0), + BITS_WITH_WMASK(0x0, 0x1, 12)); +} + +static void ddr_sleep_config_restore(void) +{ + /* restore ddr ret sel */ + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0), + ddr_data.pmugrf_soc_con0 | BITS_WMSK(0x1, 12)); + + /* restore ddr pmu ctrl */ + mmio_write_32(DDRGRF_BASE + 0x0, + ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 4)); + dsb(); + mmio_write_32(DDRGRF_BASE + 0x0, + ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 5)); + + /* restore ddr standby */ + mmio_write_32(DDR_STDBY_BASE + 0x0, + ddr_data.ddrstdby_con0 | BITS_WMSK(0x1, 0)); + + /* restore ddr auto gt */ + mmio_write_32(DDRGRF_BASE + 0x4, + ddr_data.ddrgrf_con1 | BITS_WMSK(0x1f, 0)); + + /* restore ddr pd, sr */ + mmio_write_32(DDR_UPCTL_BASE + 0x30, + ddr_data.ddrc_pwrctrl | BITS_WMSK(0x3, 0)); +} + +static void pmu_sleep_config(void) +{ + uint32_t pwrmd_core_lo, pwrmd_core_hi, pwrmd_com_lo, pwrmd_com_hi; + uint32_t pmu_wkup_cfg2_lo; + uint32_t clk_freq_khz; + + /* save pmic_sleep iomux gpio0_a4 */ + ddr_data.pmic_slp_iomux = mmio_read_32(PMUGRF_BASE + GPIO0A_IOMUX); + + ddr_data.pmu_pwrmd_core_l = + mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_LO); + ddr_data.pmu_pwrmd_core_h = + mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_HI); + ddr_data.pmu_pwrmd_cmm_l = + mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO); + ddr_data.pmu_pwrmd_cmm_h = + mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI); + ddr_data.pmu_wkup_cfg2_l = mmio_read_32(PMU_BASE + PMU_WKUP_CFG2_LO); + + pwrmd_core_lo = BIT(pmu_global_int_dis) | + BIT(pmu_core_src_gt) | + BIT(pmu_cpu0_pd) | + BIT(pmu_clr_core) | + BIT(pmu_scu_pd) | + BIT(pmu_l2_idle) | + BIT(pmu_l2_flush) | + BIT(pmu_clr_bus2main) | + BIT(pmu_clr_peri2msch); + + pwrmd_core_hi = BIT(pmu_dpll_pd_en) | + BIT(pmu_apll_pd_en) | + BIT(pmu_cpll_pd_en) | + BIT(pmu_gpll_pd_en) | + BIT(pmu_npll_pd_en); + + pwrmd_com_lo = BIT(pmu_mode_en) | + BIT(pmu_pll_pd) | + BIT(pmu_pmu_use_if) | + BIT(pmu_alive_use_if) | + BIT(pmu_osc_dis) | + BIT(pmu_sref_enter) | + BIT(pmu_ddrc_gt) | + BIT(pmu_clr_pmu) | + BIT(pmu_clr_peri_pmu); + + pwrmd_com_hi = BIT(pmu_clr_bus) | + BIT(pmu_clr_msch) | + BIT(pmu_wakeup_begin_cfg); + + pmu_wkup_cfg2_lo = BIT(pmu_cluster_wkup_en) | + BIT(pmu_gpio_wkup_en) | + BIT(pmu_timer_wkup_en); + + /* set pmic_sleep iomux gpio0_a4 */ + mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, + BITS_WITH_WMASK(1, 0x3, 8)); + + clk_freq_khz = 32; + + mmio_write_32(PMU_BASE + PMU_OSC_CNT_LO, + WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_OSC_CNT_HI, + WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16)); + + mmio_write_32(PMU_BASE + PMU_STABLE_CNT_LO, + WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_STABLE_CNT_HI, + WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16)); + + mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_LO, + WITH_16BITS_WMSK(clk_freq_khz * 2 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_HI, + WITH_16BITS_WMSK(clk_freq_khz * 2 >> 16)); + + /* Pmu's clk has switched to 24M back When pmu FSM counts + * the follow counters, so we should use 24M to calculate + * these counters. + */ + mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_LO, + WITH_16BITS_WMSK(24000 * 2 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_HI, + WITH_16BITS_WMSK(24000 * 2 >> 16)); + + mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_LO, + WITH_16BITS_WMSK(24000 * 2 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_HI, + WITH_16BITS_WMSK(24000 * 2 >> 16)); + + mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_LO, + WITH_16BITS_WMSK(24000 * 5 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_HI, + WITH_16BITS_WMSK(24000 * 5 >> 16)); + + mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_LO, + WITH_16BITS_WMSK(24000 * 2 & 0xffff)); + mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_HI, + WITH_16BITS_WMSK(24000 * 2 >> 16)); + + /* Config pmu power mode and pmu wakeup source */ + mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO, + WITH_16BITS_WMSK(pwrmd_core_lo)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI, + WITH_16BITS_WMSK(pwrmd_core_hi)); + + mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO, + WITH_16BITS_WMSK(pwrmd_com_lo)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI, + WITH_16BITS_WMSK(pwrmd_com_hi)); + + mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO, + WITH_16BITS_WMSK(pmu_wkup_cfg2_lo)); +} + +static void pmu_sleep_restore(void) +{ + mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO, + WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_l)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI, + WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_h)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO, + WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_l)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI, + WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_h)); + mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO, + WITH_16BITS_WMSK(ddr_data.pmu_wkup_cfg2_l)); + + /* restore pmic_sleep iomux */ + mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, + WITH_16BITS_WMSK(ddr_data.pmic_slp_iomux)); +} + +static void soc_sleep_config(void) +{ + ddr_data.gpio0c_iomux = mmio_read_32(PMUGRF_BASE + GPIO0C_IOMUX); + + pmu_sleep_config(); + + ddr_sleep_config(); + + pvtm_32k_config(); +} + +static void soc_sleep_restore(void) +{ + secure_timer_init(); + + pvtm_32k_config_restore(); + + ddr_sleep_config_restore(); + + pmu_sleep_restore(); + + mmio_write_32(PMUGRF_BASE + GPIO0C_IOMUX, + WITH_16BITS_WMSK(ddr_data.gpio0c_iomux)); +} + +static inline void pm_pll_wait_lock(uint32_t pll_base, uint32_t pll_id) +{ + uint32_t delay = PLL_LOCKED_TIMEOUT; + + while (delay > 0) { + if (mmio_read_32(pll_base + PLL_CON(1)) & + PLL_LOCK_MSK) + break; + delay--; + } + + if (delay == 0) + ERROR("Can't wait pll:%d lock\n", pll_id); +} + +static inline void pll_pwr_ctr(uint32_t pll_base, uint32_t pll_id, uint32_t pd) +{ + mmio_write_32(pll_base + PLL_CON(1), + BITS_WITH_WMASK(1, 1U, 15)); + if (pd) + mmio_write_32(pll_base + PLL_CON(1), + BITS_WITH_WMASK(1, 1, 14)); + else + mmio_write_32(pll_base + PLL_CON(1), + BITS_WITH_WMASK(0, 1, 14)); +} + +static inline void pll_set_mode(uint32_t pll_id, uint32_t mode) +{ + uint32_t val = BITS_WITH_WMASK(mode, 0x3, PLL_MODE_SHIFT(pll_id)); + + if (pll_id != GPLL_ID) + mmio_write_32(CRU_BASE + CRU_MODE, val); + else + mmio_write_32(PMUCRU_BASE + CRU_PMU_MODE, + BITS_WITH_WMASK(mode, 0x3, 0)); +} + +static inline void pll_suspend(uint32_t pll_id) +{ + int i; + uint32_t pll_base; + + if (pll_id != GPLL_ID) + pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0); + else + pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0); + + /* save pll con */ + for (i = 0; i < PLL_CON_CNT; i++) + ddr_data.cru_plls_con_save[pll_id][i] = + mmio_read_32(pll_base + PLL_CON(i)); + + /* slow mode */ + pll_set_mode(pll_id, SLOW_MODE); +} + +static inline void pll_resume(uint32_t pll_id) +{ + uint32_t mode, pll_base; + + if (pll_id != GPLL_ID) { + pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0); + mode = (ddr_data.cru_mode_save >> PLL_MODE_SHIFT(pll_id)) & 0x3; + } else { + pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0); + mode = ddr_data.cru_pmu_mode_save & 0x3; + } + + /* if pll locked before suspend, we should wait atfer resume */ + if (ddr_data.cru_plls_con_save[pll_id][1] & PLL_LOCK_MSK) + pm_pll_wait_lock(pll_base, pll_id); + + pll_set_mode(pll_id, mode); +} + +static void pm_plls_suspend(void) +{ + ddr_data.cru_mode_save = mmio_read_32(CRU_BASE + CRU_MODE); + ddr_data.cru_pmu_mode_save = mmio_read_32(PMUCRU_BASE + CRU_PMU_MODE); + ddr_data.clk_sel0 = mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(0)); + + pll_suspend(GPLL_ID); + pll_suspend(NPLL_ID); + pll_suspend(CPLL_ID); + pll_suspend(APLL_ID); + + /* core */ + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), + BITS_WITH_WMASK(0, 0xf, 0)); + + /* pclk_dbg */ + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), + BITS_WITH_WMASK(0, 0xf, 8)); +} + +static void pm_plls_resume(void) +{ + /* pclk_dbg */ + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), + ddr_data.clk_sel0 | BITS_WMSK(0xf, 8)); + + /* core */ + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), + ddr_data.clk_sel0 | BITS_WMSK(0xf, 0)); + + pll_resume(APLL_ID); + pll_resume(CPLL_ID); + pll_resume(NPLL_ID); + pll_resume(GPLL_ID); +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + pmu_power_domains_suspend(); + + clk_gate_suspend(); + + soc_sleep_config(); + + pm_plls_suspend(); + + psram_boot_cfg->pm_flag &= ~PM_WARM_BOOT_BIT; + + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + psram_boot_cfg->pm_flag |= PM_WARM_BOOT_BIT; + + pm_plls_resume(); + + soc_sleep_restore(); + + clk_gate_resume(); + + pmu_power_domains_resume(); + + plat_rockchip_gic_cpuif_enable(); + + return 0; +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + pll_set_mode(GPLL_ID, SLOW_MODE); + pll_set_mode(CPLL_ID, SLOW_MODE); + pll_set_mode(NPLL_ID, SLOW_MODE); + pll_set_mode(APLL_ID, SLOW_MODE); + dsb(); + + mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, CRU_GLB_SRST_FST_VALUE); + dsb(); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to execute valid codes. + */ + psci_power_down_wfi(); +} + +void __dead2 rockchip_soc_system_off(void) +{ + uint32_t val; + + /* set pmic_sleep pin(gpio0_a4) to gpio mode */ + mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, BITS_WITH_WMASK(0, 0x3, 8)); + + /* config output */ + val = mmio_read_32(GPIO0_BASE + SWPORTA_DDR); + val |= BIT(4); + mmio_write_32(GPIO0_BASE + SWPORTA_DDR, val); + + /* config output high level */ + val = mmio_read_32(GPIO0_BASE); + val |= BIT(4); + mmio_write_32(GPIO0_BASE, val); + dsb(); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to execute valid codes. + */ + psci_power_down_wfi(); +} + +void rockchip_plat_mmu_el3(void) +{ + /* TODO: support the el3 for px30 SoCs */ +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + rockchip_pd_lock_init(); + + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = 0; + + psram_boot_cfg->ddr_func = (uint64_t)0; + psram_boot_cfg->ddr_data = (uint64_t)0; + psram_boot_cfg->sp = PSRAM_SP_TOP; + psram_boot_cfg->ddr_flag = 0x0; + psram_boot_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; + psram_boot_cfg->pm_flag = PM_WARM_BOOT_BIT; + + nonboot_cpus_off(); + + /* Remap pmu_sram's base address to boot address */ + mmio_write_32(PMUSGRF_BASE + PMUSGRF_SOC_CON(0), + BITS_WITH_WMASK(1, 0x1, 13)); + + INFO("%s: pd status %x\n", + __func__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); +} diff --git a/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h new file mode 100644 index 0000000..416d1c1 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PMU_H__ +#define __PMU_H__ + +/* Needed aligned 16 bytes for sp stack top */ +#define PSRAM_SP_TOP ((PMUSRAM_BASE + PMUSRAM_RSIZE) & ~0xf) + +/***************************************************************************** + * pmu con,reg + *****************************************************************************/ +#define PMU_WKUP_CFG0_LO 0x00 +#define PMU_WKUP_CFG0_HI 0x04 +#define PMU_WKUP_CFG1_LO 0x08 +#define PMU_WKUP_CFG1_HI 0x0c +#define PMU_WKUP_CFG2_LO 0x10 + +#define PMU_PWRDN_CON 0x18 +#define PMU_PWRDN_ST 0x20 + +#define PMU_PWRMODE_CORE_LO 0x24 +#define PMU_PWRMODE_CORE_HI 0x28 +#define PMU_PWRMODE_COMMON_CON_LO 0x2c +#define PMU_PWRMODE_COMMON_CON_HI 0x30 + +#define PMU_SFT_CON 0x34 +#define PMU_INT_ST 0x44 +#define PMU_BUS_IDLE_REQ 0x64 +#define PMU_BUS_IDLE_ST 0x6c + +#define PMU_OSC_CNT_LO 0x74 +#define PMU_OSC_CNT_HI 0x78 +#define PMU_PLLLOCK_CNT_LO 0x7c +#define PMU_PLLLOCK_CNT_HI 0x80 +#define PMU_PLLRST_CNT_LO 0x84 +#define PMU_PLLRST_CNT_HI 0x88 +#define PMU_STABLE_CNT_LO 0x8c +#define PMU_STABLE_CNT_HI 0x90 +#define PMU_WAKEUP_RST_CLR_LO 0x9c +#define PMU_WAKEUP_RST_CLR_HI 0xa0 + +#define PMU_DDR_SREF_ST 0xa4 + +#define PMU_SYS_REG0_LO 0xa8 +#define PMU_SYS_REG0_HI 0xac +#define PMU_SYS_REG1_LO 0xb0 +#define PMU_SYS_REG1_HI 0xb4 +#define PMU_SYS_REG2_LO 0xb8 +#define PMU_SYS_REG2_HI 0xbc +#define PMU_SYS_REG3_LO 0xc0 +#define PMU_SYS_REG3_HI 0xc4 + +#define PMU_SCU_PWRDN_CNT_LO 0xc8 +#define PMU_SCU_PWRDN_CNT_HI 0xcc +#define PMU_SCU_PWRUP_CNT_LO 0xd0 +#define PMU_SCU_PWRUP_CNT_HI 0xd4 + +#define PMU_TIMEOUT_CNT_LO 0xd8 +#define PMU_TIMEOUT_CNT_HI 0xdc + +#define PMU_CPUAPM_CON(cpu) (0xe0 + (cpu) * 0x4) + +#define CORES_PM_DISABLE 0x0 +#define CLST_CPUS_MSK 0xf + +#define PD_CTR_LOOP 500 +#define PD_CHECK_LOOP 500 +#define WFEI_CHECK_LOOP 500 +#define BUS_IDLE_LOOP 1000 + +enum pmu_wkup_cfg2 { + pmu_cluster_wkup_en = 0, + pmu_gpio_wkup_en = 2, + pmu_sdio_wkup_en = 3, + pmu_sdmmc_wkup_en = 4, + pmu_uart0_wkup_en = 5, + pmu_timer_wkup_en = 6, + pmu_usbdev_wkup_en = 7, + pmu_sft_wkup_en = 8, + pmu_timeout_wkup_en = 10, +}; + +enum pmu_powermode_core_lo { + pmu_global_int_dis = 0, + pmu_core_src_gt = 1, + pmu_cpu0_pd = 3, + pmu_clr_core = 5, + pmu_scu_pd = 6, + pmu_l2_idle = 8, + pmu_l2_flush = 9, + pmu_clr_bus2main = 10, + pmu_clr_peri2msch = 11, +}; + +enum pmu_powermode_core_hi { + pmu_apll_pd_en = 3, + pmu_dpll_pd_en = 4, + pmu_cpll_pd_en = 5, + pmu_gpll_pd_en = 6, + pmu_npll_pd_en = 7, +}; + +enum pmu_powermode_common_lo { + pmu_mode_en = 0, + pmu_ddr_pd_en = 1, + pmu_wkup_rst = 3, + pmu_pll_pd = 4, + pmu_pmu_use_if = 6, + pmu_alive_use_if = 7, + pmu_osc_dis = 8, + pmu_input_clamp = 9, + pmu_sref_enter = 10, + pmu_ddrc_gt = 11, + pmu_ddrio_ret = 12, + pmu_ddrio_ret_deq = 13, + pmu_clr_pmu = 14, + pmu_clr_peri_pmu = 15, +}; + +enum pmu_powermode_common_hi { + pmu_clr_bus = 0, + pmu_clr_mmc = 1, + pmu_clr_msch = 2, + pmu_clr_nandc = 3, + pmu_clr_gmac = 4, + pmu_clr_vo = 5, + pmu_clr_vi = 6, + pmu_clr_gpu = 7, + pmu_clr_usb = 8, + pmu_clr_vpu = 9, + pmu_clr_crypto = 10, + pmu_wakeup_begin_cfg = 11, + pmu_peri_clk_src_gt = 12, + pmu_bus_clk_src_gt = 13, +}; + +enum pmu_pd_id { + PD_CPU0 = 0, + PD_CPU1 = 1, + PD_CPU2 = 2, + PD_CPU3 = 3, + PD_SCU = 4, + PD_USB = 5, + PD_DDR = 6, + PD_SDCARD = 8, + PD_CRYPTO = 9, + PD_GMAC = 10, + PD_MMC_NAND = 11, + PD_VPU = 12, + PD_VO = 13, + PD_VI = 14, + PD_GPU = 15, + PD_END = 16, +}; + +enum pmu_bus_id { + BUS_ID_BUS = 0, + BUS_ID_BUS2MAIN = 1, + BUS_ID_GPU = 2, + BUS_ID_CORE = 3, + BUS_ID_CRYPTO = 4, + BUS_ID_MMC = 5, + BUS_ID_GMAC = 6, + BUS_ID_VO = 7, + BUS_ID_VI = 8, + BUS_ID_SDCARD = 9, + BUS_ID_USB = 10, + BUS_ID_MSCH = 11, + BUS_ID_PERI = 12, + BUS_ID_PMU = 13, + BUS_ID_VPU = 14, + BUS_ID_PERI2MSCH = 15, +}; + +enum pmu_pd_state { + pmu_pd_on = 0, + pmu_pd_off = 1 +}; + +enum pmu_bus_state { + bus_active = 0, + bus_idle = 1, +}; + +enum cores_pm_ctr_mode { + core_pwr_pd = 0, + core_pwr_wfi = 1, + core_pwr_wfi_int = 2 +}; + +enum pmu_cores_pm_by_wfi { + core_pm_en = 0, + core_pm_int_wakeup_en, + core_pm_dis_int, + core_pm_sft_wakeup_en +}; + +/***************************************************************************** + * pmu_sgrf + *****************************************************************************/ +#define PMUSGRF_SOC_CON(i) ((i) * 0x4) + +/***************************************************************************** + * pmu_grf + *****************************************************************************/ +#define GPIO0A_IOMUX 0x0 +#define GPIO0B_IOMUX 0x4 +#define GPIO0C_IOMUX 0x8 +#define GPIO0A_PULL 0x10 + +#define GPIO0L_SMT 0x38 +#define GPIO0H_SMT 0x3c + +#define PMUGRF_SOC_CON(i) (0x100 + (i) * 4) + +#define PMUGRF_PVTM_CON0 0x180 +#define PMUGRF_PVTM_CON1 0x184 +#define PMUGRF_PVTM_ST0 0x190 +#define PMUGRF_PVTM_ST1 0x194 + +#define PVTM_CALC_CNT 0x200 + +#define PMUGRF_OS_REG(n) (0x200 + (n) * 4) + +#define GPIO0A6_IOMUX_MSK (0x3 << 12) +#define GPIO0A6_IOMUX_GPIO (0x0 << 12) +#define GPIO0A6_IOMUX_RSTOUT (0x1 << 12) +#define GPIO0A6_IOMUX_SHTDN (0x2 << 12) + +enum px30_pmugrf_pvtm_con0 { + pgrf_pvtm_st = 0, + pgrf_pvtm_en = 1, + pgrf_pvtm_div = 2, +}; + +/***************************************************************************** + * pmu_cru + *****************************************************************************/ +#define CRU_PMU_MODE 0x20 +#define CRU_PMU_CLKSEL_CON 0x40 +#define CRU_PMU_CLKSELS_CON(i) (CRU_PMU_CLKSEL_CON + (i) * 4) +#define CRU_PMU_CLKSEL_CON_CNT 5 +#define CRU_PMU_CLKGATE_CON 0x80 +#define CRU_PMU_CLKGATES_CON(i) (CRU_PMU_CLKGATE_CON + (i) * 4) +#define CRU_PMU_CLKGATE_CON_CNT 2 +#define CRU_PMU_ATCS_CON 0xc0 +#define CRU_PMU_ATCSS_CON(i) (CRU_PMU_ATCS_CON + (i) * 4) +#define CRU_PMU_ATCS_CON_CNT 2 + +/***************************************************************************** + * pmusgrf + *****************************************************************************/ +#define PMUSGRF_RSTOUT_EN (0x7 << 10) +#define PMUSGRF_RSTOUT_FST 10 +#define PMUSGRF_RSTOUT_TSADC 11 +#define PMUSGRF_RSTOUT_WDT 12 + +#define PMUGRF_SOC_CON2_US_WMSK (0x1fff << 16) +#define PMUGRF_SOC_CON2_MAX_341US 0x1fff +#define PMUGRF_SOC_CON2_200US 0x12c0 + +#define PMUGRF_FAILSAFE_SHTDN_TSADC BIT(0) +#define PMUGRF_FAILSAFE_SHTDN_WDT BIT(1) + +/***************************************************************************** + * QOS + *****************************************************************************/ +#define CPU_AXI_QOS_ID_COREID 0x00 +#define CPU_AXI_QOS_REVISIONID 0x04 +#define CPU_AXI_QOS_PRIORITY 0x08 +#define CPU_AXI_QOS_MODE 0x0c +#define CPU_AXI_QOS_BANDWIDTH 0x10 +#define CPU_AXI_QOS_SATURATION 0x14 +#define CPU_AXI_QOS_EXTCONTROL 0x18 +#define CPU_AXI_QOS_NUM_REGS 0x07 + +#define CPU_AXI_CPU_QOS_BASE 0xff508000 +#define CPU_AXI_GPU_QOS_BASE 0xff520000 +#define CPU_AXI_ISP_128M_QOS_BASE 0xff548000 +#define CPU_AXI_ISP_RD_QOS_BASE 0xff548080 +#define CPU_AXI_ISP_WR_QOS_BASE 0xff548100 +#define CPU_AXI_ISP_M1_QOS_BASE 0xff548180 +#define CPU_AXI_VIP_QOS_BASE 0xff548200 +#define CPU_AXI_RGA_RD_QOS_BASE 0xff550000 +#define CPU_AXI_RGA_WR_QOS_BASE 0xff550080 +#define CPU_AXI_VOP_M0_QOS_BASE 0xff550100 +#define CPU_AXI_VOP_M1_QOS_BASE 0xff550180 +#define CPU_AXI_VPU_QOS_BASE 0xff558000 +#define CPU_AXI_VPU_R128_QOS_BASE 0xff558080 +#define CPU_AXI_DCF_QOS_BASE 0xff500000 +#define CPU_AXI_DMAC_QOS_BASE 0xff500080 +#define CPU_AXI_CRYPTO_QOS_BASE 0xff510000 +#define CPU_AXI_GMAC_QOS_BASE 0xff518000 +#define CPU_AXI_EMMC_QOS_BASE 0xff538000 +#define CPU_AXI_NAND_QOS_BASE 0xff538080 +#define CPU_AXI_SDIO_QOS_BASE 0xff538100 +#define CPU_AXI_SFC_QOS_BASE 0xff538180 +#define CPU_AXI_SDMMC_QOS_BASE 0xff52c000 +#define CPU_AXI_USB_HOST_QOS_BASE 0xff540000 +#define CPU_AXI_USB_OTG_QOS_BASE 0xff540080 + +#define PX30_CPU_AXI_SAVE_QOS(array, base) do { \ + array[0] = mmio_read_32(base + CPU_AXI_QOS_ID_COREID); \ + array[1] = mmio_read_32(base + CPU_AXI_QOS_REVISIONID); \ + array[2] = mmio_read_32(base + CPU_AXI_QOS_PRIORITY); \ + array[3] = mmio_read_32(base + CPU_AXI_QOS_MODE); \ + array[4] = mmio_read_32(base + CPU_AXI_QOS_BANDWIDTH); \ + array[5] = mmio_read_32(base + CPU_AXI_QOS_SATURATION); \ + array[6] = mmio_read_32(base + CPU_AXI_QOS_EXTCONTROL); \ +} while (0) + +#define PX30_CPU_AXI_RESTORE_QOS(array, base) do { \ + mmio_write_32(base + CPU_AXI_QOS_ID_COREID, array[0]); \ + mmio_write_32(base + CPU_AXI_QOS_REVISIONID, array[1]); \ + mmio_write_32(base + CPU_AXI_QOS_PRIORITY, array[2]); \ + mmio_write_32(base + CPU_AXI_QOS_MODE, array[3]); \ + mmio_write_32(base + CPU_AXI_QOS_BANDWIDTH, array[4]); \ + mmio_write_32(base + CPU_AXI_QOS_SATURATION, array[5]); \ + mmio_write_32(base + CPU_AXI_QOS_EXTCONTROL, array[6]); \ +} while (0) + +#define SAVE_QOS(array, NAME) \ + PX30_CPU_AXI_SAVE_QOS(array, CPU_AXI_##NAME##_QOS_BASE) +#define RESTORE_QOS(array, NAME) \ + PX30_CPU_AXI_RESTORE_QOS(array, CPU_AXI_##NAME##_QOS_BASE) + +#endif /* __PMU_H__ */ diff --git a/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c b/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c new file mode 100644 index 0000000..144f945 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/** + * There are 8 regions for DDR security control + * @rgn - the DDR regions 0 ~ 7 which are can be configured. + * @st - start address to set as secure + * @sz - length of area to set as secure + * The internal unit is megabytes, so memory areas need to be aligned + * to megabyte borders. + */ +static void secure_ddr_region(uint32_t rgn, + uintptr_t st, size_t sz) +{ + uintptr_t ed = st + sz; + uintptr_t st_mb, ed_mb; + uint32_t val; + + assert(rgn <= 7); + assert(st < ed); + + /* check aligned 1MB */ + assert(st % SIZE_M(1) == 0); + assert(ed % SIZE_M(1) == 0); + + st_mb = st / SIZE_M(1); + ed_mb = ed / SIZE_M(1); + + /* map top and base */ + mmio_write_32(FIREWALL_DDR_BASE + + FIREWALL_DDR_FW_DDR_RGN(rgn), + RG_MAP_SECURE(ed_mb, st_mb)); + + /* enable secure */ + val = mmio_read_32(FIREWALL_DDR_BASE + FIREWALL_DDR_FW_DDR_CON_REG); + val |= BIT(rgn); + mmio_write_32(FIREWALL_DDR_BASE + + FIREWALL_DDR_FW_DDR_CON_REG, val); +} + +void secure_timer_init(void) +{ + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_CONTROL_REG, + TIMER_DIS); + + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOAD_COUNT0, 0xffffffff); + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOAD_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_CONTROL_REG, + TIMER_EN | TIMER_FMODE); +} + +void sgrf_init(void) +{ +#ifdef PLAT_RK_SECURE_DDR_MINILOADER + uint32_t i; + struct param_ddr_usage usg; + + /* general secure regions */ + usg = ddr_region_usage_parse(DDR_PARAM_BASE, + PLAT_MAX_DDR_CAPACITY_MB); + + /* region-0 for TF-A, region-1 for optional OP-TEE */ + assert(usg.s_nr < 7); + + for (i = 0; i < usg.s_nr; i++) + secure_ddr_region(7 - i, usg.s_top[i], usg.s_base[i]); +#endif + + /* secure the trustzone ram */ + secure_ddr_region(0, TZRAM_BASE, TZRAM_SIZE); + + /* set all slave ip into no-secure, except stimer */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4), SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(8), 0x00030000); + + /* set master crypto to no-secure, dcf to secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), 0x000f0003); + + /* set DMAC into no-secure */ + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(0), DMA_IRQ_BOOT_NS); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(1), DMA_PERI_CH_NS_15_0); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(2), DMA_PERI_CH_NS_19_16); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(3), DMA_MANAGER_BOOT_NS); + + /* soft reset dma before use */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), DMA_SOFTRST_REQ); + udelay(5); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), DMA_SOFTRST_RLS); +} diff --git a/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h b/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h new file mode 100644 index 0000000..498027d --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SECURE_H +#define SECURE_H + +/*************************************************************************** + * SGRF + ***************************************************************************/ +#define SGRF_SOC_CON(i) ((i) * 0x4) +#define SGRF_DMAC_CON(i) (0x30 + (i) * 0x4) + +#define SGRF_MST_S_ALL_NS 0xffffffff +#define SGRF_SLV_S_ALL_NS 0xffff0000 +#define DMA_IRQ_BOOT_NS 0xffffffff +#define DMA_PERI_CH_NS_15_0 0xffffffff +#define DMA_PERI_CH_NS_19_16 0x000f000f +#define DMA_MANAGER_BOOT_NS 0x00010001 +#define DMA_SOFTRST_REQ BITS_WITH_WMASK(1, 0x1, 12) +#define DMA_SOFTRST_RLS BITS_WITH_WMASK(0, 0x1, 12) + +/*************************************************************************** + * DDR FIREWALL + ***************************************************************************/ +#define FIREWALL_DDR_FW_DDR_RGN(i) ((i) * 0x4) +#define FIREWALL_DDR_FW_DDR_MST(i) (0x20 + (i) * 0x4) +#define FIREWALL_DDR_FW_DDR_CON_REG 0x40 +#define FIREWALL_DDR_FW_DDR_RGN_NUM 8 +#define FIREWALL_DDR_FW_DDR_MST_NUM 6 + +#define PLAT_MAX_DDR_CAPACITY_MB 4096 +#define RG_MAP_SECURE(top, base) ((((top) - 1) << 16) | (base)) + +/************************************************** + * secure timer + **************************************************/ + +/* chanal0~5 */ +#define STIMER_CHN_BASE(n) (STIME_BASE + 0x20 * (n)) + +#define TIMER_LOAD_COUNT0 0x0 +#define TIMER_LOAD_COUNT1 0x4 + +#define TIMER_CUR_VALUE0 0x8 +#define TIMER_CUR_VALUE1 0xc + +#define TIMER_CONTROL_REG 0x10 +#define TIMER_INTSTATUS 0x18 + +#define TIMER_DIS 0x0 +#define TIMER_EN 0x1 + +#define TIMER_FMODE (0x0 << 1) +#define TIMER_RMODE (0x1 << 1) + +#define TIMER_LOAD_COUNT0_MSK (0xffffffff) +#define TIMER_LOAD_COUNT1_MSK (0xffffffff00000000) + +void secure_timer_init(void); +void sgrf_init(void); + +#endif /* SECURE_H */ diff --git a/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c new file mode 100644 index 0000000..200563d --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2019, 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 + +/* Aggregate of all devices in the first GB */ +#define PX30_DEV_RNG0_BASE 0xff000000 +#define PX30_DEV_RNG0_SIZE 0x00ff0000 + +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(PX30_DEV_RNG0_BASE, PX30_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SHARE_MEM_BASE, SHARE_MEM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PARAM_BASE, DDR_PARAM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/* The RockChip power domain tree descriptor */ +const unsigned char rockchip_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +void clk_gate_con_save(uint32_t *clkgt_save) +{ + uint32_t i, j; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + clkgt_save[i] = + mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i)); + j = i; + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++, j++) + clkgt_save[j] = + mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i)); +} + +void clk_gate_con_restore(uint32_t *clkgt_save) +{ + uint32_t i, j; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + WITH_16BITS_WMSK(clkgt_save[i])); + + j = i; + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++, j++) + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), + WITH_16BITS_WMSK(clkgt_save[j])); +} + +void clk_gate_con_disable(void) +{ + uint32_t i; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + 0xffff0000); + + for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), + 0xffff0000); +} + +static void soc_reset_config_all(void) +{ + uint32_t tmp; + + /* tsadc and wdt can trigger a first rst */ + tmp = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON); + tmp |= CRU_GLB_RST_TSADC_FST | CRU_GLB_RST_WDT_FST; + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, tmp); + return; + tmp = mmio_read_32(PMUGRF_BASE + PMUGRF_SOC_CON(3)); + tmp &= ~(PMUGRF_FAILSAFE_SHTDN_TSADC | PMUGRF_FAILSAFE_SHTDN_WDT); + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(3), tmp); + + /* wdt pin rst eable */ + mmio_write_32(GRF_BASE + GRF_SOC_CON(2), + BIT_WITH_WMSK(GRF_SOC_CON2_NSWDT_RST_EN)); +} + +void px30_soc_reset_config(void) +{ + uint32_t tmp; + + /* enable soc ip rst hold time cfg */ + tmp = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON); + tmp |= BIT(CRU_GLB_RST_TSADC_EXT) | BIT(CRU_GLB_RST_WDT_EXT); + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, tmp); + /* soc ip rst hold time, 24m */ + tmp = mmio_read_32(CRU_BASE + CRU_GLB_CNT_TH); + tmp &= ~CRU_GLB_CNT_RST_MSK; + tmp |= (CRU_GLB_CNT_RST_1MS / 2); + mmio_write_32(CRU_BASE + CRU_GLB_CNT_TH, tmp); + + mmio_write_32(PMUSGRF_BASE + PMUSGRF_SOC_CON(0), + BIT_WITH_WMSK(PMUSGRF_RSTOUT_FST) | + BIT_WITH_WMSK(PMUSGRF_RSTOUT_TSADC) | + BIT_WITH_WMSK(PMUSGRF_RSTOUT_WDT)); + + /* rst_out pulse time */ + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(2), + PMUGRF_SOC_CON2_MAX_341US | PMUGRF_SOC_CON2_US_WMSK); + + soc_reset_config_all(); +} + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + sgrf_init(); +} diff --git a/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h new file mode 100644 index 0000000..648d18b --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SOC_H__ +#define __SOC_H__ + +#include + +#ifndef BITS_WMSK +#define BITS_WMSK(msk, shift) ((msk) << (shift + REG_MSK_SHIFT)) +#endif + +enum plls_id { + APLL_ID = 0, + DPLL_ID, + CPLL_ID, + NPLL_ID, + GPLL_ID, + END_PLL_ID, +}; + +enum pll_mode { + SLOW_MODE, + NORM_MODE, + DEEP_SLOW_MODE, +}; + +/*************************************************************************** + * GRF + ***************************************************************************/ +#define GRF_SOC_CON(i) (0x0400 + (i) * 4) +#define GRF_PD_VO_CON0 0x0434 +#define GRF_SOC_STATUS0 0x0480 +#define GRF_CPU_STATUS0 0x0520 +#define GRF_CPU_STATUS1 0x0524 +#define GRF_SOC_NOC_CON0 0x0530 +#define GRF_SOC_NOC_CON1 0x0534 + +#define CKECK_WFE_MSK 0x1 +#define CKECK_WFI_MSK 0x10 +#define CKECK_WFEI_MSK 0x11 + +#define GRF_SOC_CON2_NSWDT_RST_EN 12 + +/*************************************************************************** + * cru + ***************************************************************************/ +#define CRU_MODE 0xa0 +#define CRU_MISC 0xa4 +#define CRU_GLB_CNT_TH 0xb0 +#define CRU_GLB_RST_ST 0xb4 +#define CRU_GLB_SRST_FST 0xb8 +#define CRU_GLB_SRST_SND 0xbc +#define CRU_GLB_RST_CON 0xc0 + +#define CRU_CLKSEL_CON 0x100 +#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + (i) * 4) +#define CRU_CLKSEL_CON_CNT 60 + +#define CRU_CLKGATE_CON 0x200 +#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + (i) * 4) +#define CRU_CLKGATES_CON_CNT 18 + +#define CRU_SOFTRST_CON 0x300 +#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4)) +#define CRU_SOFTRSTS_CON_CNT 12 + +#define CRU_AUTOCS_CON0(id) (0x400 + (id) * 8) +#define CRU_AUTOCS_CON1(id) (0x404 + (id) * 8) + +#define CRU_CONS_GATEID(i) (16 * (i)) +#define GATE_ID(reg, bit) ((reg) * 16 + (bit)) + +#define CRU_GLB_SRST_FST_VALUE 0xfdb9 +#define CRU_GLB_SRST_SND_VALUE 0xeca8 + +#define CRU_GLB_RST_TSADC_EXT 6 +#define CRU_GLB_RST_WDT_EXT 7 + +#define CRU_GLB_CNT_RST_MSK 0xffff +#define CRU_GLB_CNT_RST_1MS 0x5DC0 + +#define CRU_GLB_RST_TSADC_FST BIT(0) +#define CRU_GLB_RST_WDT_FST BIT(1) + +/*************************************************************************** + * pll + ***************************************************************************/ +#define CRU_PLL_CONS(id, i) ((id) * 0x20 + (i) * 4) +#define PLL_CON(i) ((i) * 4) +#define PLL_CON_CNT 5 +#define PLL_LOCK_MSK BIT(10) +#define PLL_MODE_SHIFT(id) ((id) == CPLL_ID ? \ + 2 : \ + ((id) == DPLL_ID ? 4 : 2 * (id))) +#define PLL_MODE_MSK(id) (0x3 << PLL_MODE_SHIFT(id)) + +#define PLL_LOCKED_TIMEOUT 600000U + +/*************************************************************************** + * GPIO + ***************************************************************************/ +#define SWPORTA_DR 0x00 +#define SWPORTA_DDR 0x04 +#define GPIO_INTEN 0x30 +#define GPIO_INT_STATUS 0x40 +#define GPIO_NUMS 4 + +void clk_gate_con_save(uint32_t *clkgt_save); +void clk_gate_con_restore(uint32_t *clkgt_save); +void clk_gate_con_disable(void); + +void px30_soc_reset_config(void); + +#endif /* __SOC_H__ */ diff --git a/arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S b/arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S new file mode 100644 index 0000000..44cca0d --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ROCKCHIP_PLAT_LD_S__ +#define __ROCKCHIP_PLAT_LD_S__ + +MEMORY { + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + KEEP(*(.pmusram.entry)) + + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; + } >PMUSRAM +} + +#endif /* __ROCKCHIP_PLAT_LD_S__ */ diff --git a/arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h b/arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h new file mode 100644 index 0000000..7b6a6a8 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_SIP_CALLS_H__ +#define __PLAT_SIP_CALLS_H__ + +#define RK_PLAT_SIP_NUM_CALLS 0 + +#endif /* __PLAT_SIP_CALLS_H__ */ diff --git a/arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h new file mode 100644 index 0000000..a11f84f --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#include +#include +#include + +#define DEBUG_XLAT_TABLE 0 + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if DEBUG_XLAT_TABLE +#define PLATFORM_STACK_SIZE 0x800 +#elif IMAGE_BL1 +#define PLATFORM_STACK_SIZE 0x440 +#elif IMAGE_BL2 +#define PLATFORM_STACK_SIZE 0x400 +#elif IMAGE_BL31 +#define PLATFORM_STACK_SIZE 0x800 +#elif IMAGE_BL32 +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) + +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +#define PLAT_RK_CLST_TO_CPUID_SHIFT 8 + +/* + * 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 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF text, ro, rw, Size: 1MB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x100000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted RAM + */ +#define BL31_BASE (TZRAM_BASE + 0x40000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) +#define ADDR_SPACE_SIZE (1ull << 32) +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 27 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Define GICD and GICC and GICR base + */ +#define PLAT_RK_GICD_BASE PX30_GICD_BASE +#define PLAT_RK_GICC_BASE PX30_GICC_BASE + +#define PLAT_RK_UART_BASE PX30_UART_BASE +#define PLAT_RK_UART_CLOCK PX30_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE PX30_BAUDRATE + +#define PLAT_RK_PRIMARY_CPU 0x0 + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c b/arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c new file mode 100644 index 0000000..a4b8e55 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +uintptr_t rockchip_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) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/plat/rockchip/px30/platform.mk b/arm-trusted-firmware/plat/rockchip/px30/platform.mk new file mode 100644 index 0000000..d14ffc4 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/platform.mk @@ -0,0 +1,73 @@ +# +#Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# +#SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/arm/gic/v2/gicv2.mk + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +DISABLE_BIN_GENERATION := 1 + +PLAT_INCLUDES := -Idrivers/arm/gic/common/ \ + -Idrivers/arm/gic/v2/ \ + -Iinclude/plat/common/ \ + -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/drivers/parameter/ \ + -I${RK_PLAT_COMMON}/pmusram \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/secure/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/include/ + +RK_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/common/aarch64/crash_console_helpers.S \ + ${RK_PLAT}/common/rockchip_gicv2.c + +PLAT_BL_COMMON_SOURCES := lib/bl_aux_params/bl_aux_params.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + plat/common/plat_psci_common.c + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + +BL31_SOURCES += ${RK_GIC_SOURCES} \ + common/desc_image_load.c \ + drivers/arm/cci/cci.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/cpus/aarch64/cortex_a35.S \ + ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ + ${RK_PLAT_COMMON}/aarch64/platform_common.c \ + ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/pmusram/cpus_on_fixed_addr.S \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/drivers/secure/secure.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c + +ifdef PLAT_RK_SECURE_DDR_MINILOADER +BL31_SOURCES += ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c +endif + +ENABLE_PLAT_COMPAT := 0 +MULTI_CONSOLE_API := 1 + +include lib/libfdt/libfdt.mk + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) +$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER)) +$(eval $(call add_define,PLAT_WARMBOOT_ADDR_NOT_ALIGN)) diff --git a/arm-trusted-firmware/plat/rockchip/px30/px30_def.h b/arm-trusted-firmware/plat/rockchip/px30/px30_def.h new file mode 100644 index 0000000..efe789e --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/px30/px30_def.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PX30_DEF_H__ +#define __PX30_DEF_H__ + +#define MAJOR_VERSION (1) +#define MINOR_VERSION (0) + +#define SIZE_K(n) ((n) * 1024) +#define SIZE_M(n) ((n) * 1024 * 1024) + +#define WITH_16BITS_WMSK(bits) (0xffff0000 | (bits)) + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define PMU_BASE 0xff000000 +#define PMU_SIZE SIZE_K(64) + +#define PMUGRF_BASE 0xff010000 +#define PMUGRF_SIZE SIZE_K(64) + +#define PMUSRAM_BASE 0xff020000 +#define PMUSRAM_SIZE SIZE_K(64) +#define PMUSRAM_RSIZE SIZE_K(8) + +#define UART0_BASE 0xff030000 +#define UART0_SIZE SIZE_K(64) + +#define GPIO0_BASE 0xff040000 +#define GPIO0_SIZE SIZE_K(64) + +#define PMUSGRF_BASE 0xff050000 +#define PMUSGRF_SIZE SIZE_K(64) + +#define INTSRAM_BASE 0xff0e0000 +#define INTSRAM_SIZE SIZE_K(64) + +#define SGRF_BASE 0xff11c000 +#define SGRF_SIZE SIZE_K(16) + +#define GIC400_BASE 0xff130000 +#define GIC400_SIZE SIZE_K(64) + +#define GRF_BASE 0xff140000 +#define GRF_SIZE SIZE_K(64) + +#define UART1_BASE 0xff158000 +#define UART1_SIZE SIZE_K(64) + +#define UART2_BASE 0xff160000 +#define UART2_SIZE SIZE_K(64) + +#define UART3_BASE 0xff168000 +#define UART3_SIZE SIZE_K(64) + +#define UART5_BASE 0xff178000 +#define UART5_SIZE SIZE_K(64) + +#define I2C0_BASE 0xff180000 +#define I2C0_SIZE SIZE_K(64) + +#define PWM0_BASE 0xff200000 +#define PWM0_SIZE SIZE_K(32) + +#define PWM1_BASE 0xff208000 +#define PWM1_SIZE SIZE_K(32) + +#define NTIME_BASE 0xff210000 +#define NTIME_SIZE SIZE_K(64) + +#define STIME_BASE 0xff220000 +#define STIME_SIZE SIZE_K(64) + +#define DCF_BASE 0xff230000 +#define DCF_SIZE SIZE_K(64) + +#define GPIO1_BASE 0xff250000 +#define GPIO1_SIZE SIZE_K(64) + +#define GPIO2_BASE 0xff260000 +#define GPIO2_SIZE SIZE_K(64) + +#define GPIO3_BASE 0xff270000 +#define GPIO3_SIZE SIZE_K(64) + +#define DDR_PHY_BASE 0xff2a0000 +#define DDR_PHY_SIZE SIZE_K(64) + +#define CRU_BASE 0xff2b0000 +#define CRU_SIZE SIZE_K(32) + +#define CRU_BOOST_BASE 0xff2b8000 +#define CRU_BOOST_SIZE SIZE_K(16) + +#define PMUCRU_BASE 0xff2bc000 +#define PMUCRU_SIZE SIZE_K(16) + +#define VOP_BASE 0xff460000 +#define VOP_SIZE SIZE_K(16) + +#define SERVER_MSCH_BASE 0xff530000 +#define SERVER_MSCH_SIZE SIZE_K(64) + +#define FIREWALL_DDR_BASE 0xff534000 +#define FIREWALL_DDR_SIZE SIZE_K(16) + +#define DDR_UPCTL_BASE 0xff600000 +#define DDR_UPCTL_SIZE SIZE_K(64) + +#define DDR_MNTR_BASE 0xff610000 +#define DDR_MNTR_SIZE SIZE_K(64) + +#define DDR_STDBY_BASE 0xff620000 +#define DDR_STDBY_SIZE SIZE_K(64) + +#define DDRGRF_BASE 0xff630000 +#define DDRGRF_SIZE SIZE_K(32) + +/************************************************************************** + * UART related constants + **************************************************************************/ +#define PX30_UART_BASE UART2_BASE +#define PX30_BAUDRATE 1500000 +#define PX30_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000 +#define SYS_COUNTER_FREQ_IN_MHZ 24 + +/****************************************************************************** + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base rk_platform compatible GIC memory map */ +#define PX30_GICD_BASE (GIC400_BASE + 0x1000) +#define PX30_GICC_BASE (GIC400_BASE + 0x2000) +#define PX30_GICR_BASE 0 /* no GICR in GIC-400 */ + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#define RK_IRQ_SEC_PHY_TIMER 29 + +#define RK_IRQ_SEC_SGI_0 8 +#define RK_IRQ_SEC_SGI_1 9 +#define RK_IRQ_SEC_SGI_2 10 +#define RK_IRQ_SEC_SGI_3 11 +#define RK_IRQ_SEC_SGI_4 12 +#define RK_IRQ_SEC_SGI_5 13 +#define RK_IRQ_SEC_SGI_6 14 +#define RK_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 0 interrupts. + */ +#define PLAT_RK_GICV2_G0_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K]*/ +#define SHARE_MEM_PAGE_NUM 15 +#define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4) + +#define DDR_PARAM_BASE 0x02000000 +#define DDR_PARAM_SIZE SIZE_K(4) + +#endif /* __PLAT_DEF_H__ */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..2003749 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +.macro func_rockchip_clst_warmboot + /* Nothing to do for rk3288 */ +.endm + +.macro rockchip_clst_warmboot_data + /* Nothing to do for rk3288 */ +.endm diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c new file mode 100644 index 0000000..d6d7098 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2016, 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 + +DEFINE_BAKERY_LOCK(rockchip_pd_lock); + +static uint32_t cpu_warm_boot_addr; + +static uint32_t store_pmu_pwrmode_con; +static uint32_t store_sgrf_soc_con0; +static uint32_t store_sgrf_cpu_con0; + +/* These enum are variants of low power mode */ +enum { + ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0, + ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1, +}; + +static inline int rk3288_pmu_bus_idle(uint32_t req, uint32_t idle) +{ + uint32_t mask = BIT(req); + uint32_t idle_mask = 0; + uint32_t idle_target = 0; + uint32_t val; + uint32_t wait_cnt = 0; + + switch (req) { + case bus_ide_req_gpu: + idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu); + idle_target = (idle << pmu_idle_ack_gpu) | + (idle << pmu_idle_gpu); + break; + case bus_ide_req_core: + idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core); + idle_target = (idle << pmu_idle_ack_core) | + (idle << pmu_idle_core); + break; + case bus_ide_req_cpup: + idle_mask = BIT(pmu_idle_ack_cpup) | BIT(pmu_idle_cpup); + idle_target = (idle << pmu_idle_ack_cpup) | + (idle << pmu_idle_cpup); + break; + case bus_ide_req_bus: + idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus); + idle_target = (idle << pmu_idle_ack_bus) | + (idle << pmu_idle_bus); + break; + case bus_ide_req_dma: + idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma); + idle_target = (idle << pmu_idle_ack_dma) | + (idle << pmu_idle_dma); + break; + case bus_ide_req_peri: + idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri); + idle_target = (idle << pmu_idle_ack_peri) | + (idle << pmu_idle_peri); + break; + case bus_ide_req_video: + idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video); + idle_target = (idle << pmu_idle_ack_video) | + (idle << pmu_idle_video); + break; + case bus_ide_req_hevc: + idle_mask = BIT(pmu_idle_ack_hevc) | BIT(pmu_idle_hevc); + idle_target = (idle << pmu_idle_ack_hevc) | + (idle << pmu_idle_hevc); + break; + case bus_ide_req_vio: + idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio); + idle_target = (pmu_idle_ack_vio) | + (idle << pmu_idle_vio); + break; + case bus_ide_req_alive: + idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive); + idle_target = (idle << pmu_idle_ack_alive) | + (idle << pmu_idle_alive); + break; + default: + ERROR("%s: Unsupported the idle request\n", __func__); + break; + } + + val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ); + if (idle) + val |= mask; + else + val &= ~mask; + + mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val); + + while ((mmio_read_32(PMU_BASE + + PMU_BUS_IDE_ST) & idle_mask) != idle_target) { + wait_cnt++; + if (!(wait_cnt % MAX_WAIT_CONUT)) + WARN("%s:st=%x(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST), + idle_mask); + } + + return 0; +} + +static bool rk3288_sleep_disable_osc(void) +{ + static const uint32_t reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0, + GRF_UOC2_CON0 }; + uint32_t reg, i; + + /* + * if any usb phy is still on(GRF_SIDDQ==0), that means we need the + * function of usb wakeup, so do not switch to 32khz, since the usb phy + * clk does not connect to 32khz osc + */ + for (i = 0; i < ARRAY_SIZE(reg_offset); i++) { + reg = mmio_read_32(GRF_BASE + reg_offset[i]); + if (!(reg & GRF_SIDDQ)) + return false; + } + + return true; +} + +static void pmu_set_sleep_mode(int level) +{ + uint32_t mode_set, mode_set1; + bool osc_disable = rk3288_sleep_disable_osc(); + + mode_set = BIT(pmu_mode_glb_int_dis) | BIT(pmu_mode_l2_flush_en) | + BIT(pmu_mode_sref0_enter) | BIT(pmu_mode_sref1_enter) | + BIT(pmu_mode_ddrc0_gt) | BIT(pmu_mode_ddrc1_gt) | + BIT(pmu_mode_en) | BIT(pmu_mode_chip_pd) | + BIT(pmu_mode_scu_pd); + + mode_set1 = BIT(pmu_mode_clr_core) | BIT(pmu_mode_clr_cpup); + + if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) { + /* arm off, logic deep sleep */ + mode_set |= BIT(pmu_mode_bus_pd) | BIT(pmu_mode_pmu_use_lf) | + BIT(pmu_mode_ddrio1_ret) | + BIT(pmu_mode_ddrio0_ret) | + BIT(pmu_mode_pmu_alive_use_lf) | + BIT(pmu_mode_pll_pd); + + if (osc_disable) + mode_set |= BIT(pmu_mode_osc_dis); + + mode_set1 |= BIT(pmu_mode_clr_alive) | BIT(pmu_mode_clr_bus) | + BIT(pmu_mode_clr_peri) | BIT(pmu_mode_clr_dma); + + mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1, + pmu_armint_wakeup_en); + + /* + * In deep suspend we use PMU_PMU_USE_LF to let the rk3288 + * switch its main clock supply to the alternative 32kHz + * source. Therefore set 30ms on a 32kHz clock for pmic + * stabilization. Similar 30ms on 24MHz for the other + * mode below. + */ + mmio_write_32(PMU_BASE + PMU_STABL_CNT, 32 * 30); + + /* only wait for stabilization, if we turned the osc off */ + mmio_write_32(PMU_BASE + PMU_OSC_CNT, + osc_disable ? 32 * 30 : 0); + } else { + /* + * arm off, logic normal + * if pmu_clk_core_src_gate_en is not set, + * wakeup will be error + */ + mode_set |= BIT(pmu_mode_core_src_gt); + + mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1, + BIT(pmu_armint_wakeup_en) | + BIT(pmu_gpioint_wakeup_en)); + + /* 30ms on a 24MHz clock for pmic stabilization */ + mmio_write_32(PMU_BASE + PMU_STABL_CNT, 24000 * 30); + + /* oscillator is still running, so no need to wait */ + mmio_write_32(PMU_BASE + PMU_OSC_CNT, 0); + } + + mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, mode_set); + mmio_write_32(PMU_BASE + PMU_PWRMODE_CON1, mode_set1); +} + +static int cpus_power_domain_on(uint32_t cpu_id) +{ + uint32_t cpu_pd; + + cpu_pd = PD_CPU0 + cpu_id; + + /* if the core has been on, power it off first */ + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + /* put core in reset - some sort of A12/A17 bug */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), + BIT(cpu_id) | (BIT(cpu_id) << 16)); + + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } + + pmu_power_domain_ctr(cpu_pd, pmu_pd_on); + + /* pull core out of reset */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), BIT(cpu_id) << 16); + + return 0; +} + +static int cpus_power_domain_off(uint32_t cpu_id) +{ + uint32_t cpu_pd = PD_CPU0 + cpu_id; + + if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) + return 0; + + if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) + return -EINVAL; + + /* put core in reset - some sort of A12/A17 bug */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), + BIT(cpu_id) | (BIT(cpu_id) << 16)); + + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + + return 0; +} + +static void nonboot_cpus_off(void) +{ + uint32_t boot_cpu, cpu; + + boot_cpu = plat_my_core_pos(); + boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr()); + + /* turn off noboot cpus */ + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { + if (cpu == boot_cpu) + continue; + + cpus_power_domain_off(cpu); + } +} + +void sram_save(void) +{ + /* TODO: support the sdram save for rk3288 SoCs*/ +} + +void sram_restore(void) +{ + /* TODO: support the sdram restore for rk3288 SoCs */ +} + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) +{ + uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpu_id] = entrypoint; + dsb(); + + cpus_power_domain_on(cpu_id); + + /* + * We communicate with the bootrom to active the cpus other + * than cpu0, after a blob of initialize code, they will + * stay at wfe state, once they are actived, they will check + * the mailbox: + * sram_base_addr + 4: 0xdeadbeaf + * sram_base_addr + 8: start address for pc + * The cpu0 need to wait the other cpus other than cpu0 entering + * the wfe state.The wait time is affected by many aspects. + * (e.g: cpu frequency, bootrom frequency, sram frequency, ...) + */ + mdelay(1); /* ensure the cpus other than cpu0 to startup */ + + /* tell the bootrom mailbox where to start from */ + mmio_write_32(SRAM_BASE + 8, cpu_warm_boot_addr); + mmio_write_32(SRAM_BASE + 4, 0xDEADBEAF); + dsb(); + sev(); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, store_pmu_pwrmode_con); + mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), + store_sgrf_cpu_con0 | SGRF_DAPDEVICE_MSK); + + /* disable fastboot mode */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), + store_sgrf_soc_con0 | SGRF_FAST_BOOT_DIS); + + secure_watchdog_ungate(); + clk_gate_con_restore(); + clk_sel_con_restore(); + clk_plls_resume(); + + secure_gic_init(); + plat_rockchip_gic_init(); + + return 0; +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + nonboot_cpus_off(); + + store_sgrf_cpu_con0 = mmio_read_32(SGRF_BASE + SGRF_CPU_CON(0)); + store_sgrf_soc_con0 = mmio_read_32(SGRF_BASE + SGRF_SOC_CON(0)); + store_pmu_pwrmode_con = mmio_read_32(PMU_BASE + PMU_PWRMODE_CON); + + /* save clk-gates and ungate all for suspend */ + clk_gate_con_save(); + clk_gate_con_disable(); + clk_sel_con_save(); + + pmu_set_sleep_mode(ROCKCHIP_ARM_OFF_LOGIC_NORMAL); + + clk_plls_suspend(); + secure_watchdog_gate(); + + /* + * The dapswjdp can not auto reset before resume, that cause it may + * access some illegal address during resume. Let's disable it before + * suspend, and the MASKROM will enable it back. + */ + mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), SGRF_DAPDEVICE_MSK); + + /* + * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR + */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_FAST_BOOT_ENA); + + /* boot-address of resuming system is from this register value */ + mmio_write_32(SGRF_BASE + SGRF_FAST_BOOT_ADDR, + (uint32_t)&pmu_cpuson_entrypoint); + + /* flush all caches - otherwise we might loose the resume address */ + dcsw_op_all(DC_OP_CISW); + + return 0; +} + +void rockchip_plat_mmu_svc_mon(void) +{ +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + cpu_warm_boot_addr = (uint32_t)platform_cpu_warmboot; + + /* on boot all power-domains are on */ + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = pmu_pd_on; + + nonboot_cpus_off(); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h new file mode 100644 index 0000000..06d5528 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_H +#define PMU_H + +/* Allocate sp reginon in pmusram */ +#define PSRAM_SP_SIZE 0x80 +#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE) + +/***************************************************************************** + * pmu con,reg + *****************************************************************************/ +#define PMU_WAKEUP_CFG0 0x0 +#define PMU_WAKEUP_CFG1 0x4 +#define PMU_PWRDN_CON 0x8 +#define PMU_PWRDN_ST 0xc + +#define PMU_PWRMODE_CON 0x18 +#define PMU_BUS_IDE_REQ 0x10 +#define PMU_BUS_IDE_ST 0x14 + +#define PMU_OSC_CNT 0x20 +#define PMU_PLL_CNT 0x24 +#define PMU_STABL_CNT 0x28 +#define PMU_DDRIO0_PWR_CNT 0x2c +#define PMU_DDRIO1_PWR_CNT 0x30 +#define PMU_WKUPRST_CNT 0x44 +#define PMU_SFT_CON 0x48 +#define PMU_PWRMODE_CON1 0x90 + +enum pmu_pdid { + PD_CPU0 = 0, + PD_CPU1, + PD_CPU2, + PD_CPU3, + PD_BUS = 5, + PD_PERI, + PD_VIO, + PD_VIDEO, + PD_GPU, + PD_SCU = 11, + PD_HEVC = 14, + PD_END +}; + +enum pmu_bus_ide { + bus_ide_req_bus = 0, + bus_ide_req_peri, + bus_ide_req_gpu, + bus_ide_req_video, + bus_ide_req_vio, + bus_ide_req_core, + bus_ide_req_alive, + bus_ide_req_dma, + bus_ide_req_cpup, + bus_ide_req_hevc, + bus_ide_req_end +}; + +enum pmu_pwrmode { + pmu_mode_en = 0, + pmu_mode_core_src_gt, + pmu_mode_glb_int_dis, + pmu_mode_l2_flush_en, + pmu_mode_bus_pd, + pmu_mode_cpu0_pd, + pmu_mode_scu_pd, + pmu_mode_pll_pd = 7, + pmu_mode_chip_pd, + pmu_mode_pwr_off_comb, + pmu_mode_pmu_alive_use_lf, + pmu_mode_pmu_use_lf, + pmu_mode_osc_dis = 12, + pmu_mode_input_clamp, + pmu_mode_wkup_rst, + pmu_mode_sref0_enter, + pmu_mode_sref1_enter, + pmu_mode_ddrio0_ret, + pmu_mode_ddrio1_ret, + pmu_mode_ddrc0_gt, + pmu_mode_ddrc1_gt, + pmu_mode_ddrio0_ret_deq, + pmu_mode_ddrio1_ret_deq, +}; + +enum pmu_pwrmode1 { + pmu_mode_clr_bus = 0, + pmu_mode_clr_core, + pmu_mode_clr_cpup, + pmu_mode_clr_alive, + pmu_mode_clr_dma, + pmu_mode_clr_peri, + pmu_mode_clr_gpu, + pmu_mode_clr_video, + pmu_mode_clr_hevc, + pmu_mode_clr_vio +}; + +enum pmu_sft_con { + pmu_sft_ddrio0_ret_cfg = 6, + pmu_sft_ddrio1_ret_cfg = 9, + pmu_sft_l2flsh = 15, +}; + +enum pmu_wakeup_cfg1 { + pmu_armint_wakeup_en = 0, + pmu_gpio_wakeup_negedge, + pmu_sdmmc0_wakeup_en, + pmu_gpioint_wakeup_en, +}; + +enum pmu_bus_idle_st { + pmu_idle_bus = 0, + pmu_idle_peri, + pmu_idle_gpu, + pmu_idle_video, + pmu_idle_vio, + pmu_idle_core, + pmu_idle_alive, + pmu_idle_dma, + pmu_idle_cpup, + pmu_idle_hevc, + pmu_idle_ack_bus = 16, + pmu_idle_ack_peri, + pmu_idle_ack_gpu, + pmu_idle_ack_video, + pmu_idle_ack_vio, + pmu_idle_ack_core, + pmu_idle_ack_alive, + pmu_idle_ack_dma, + pmu_idle_ack_cpup, + pmu_idle_ack_hevc, +}; + +#define CHECK_CPU_WFIE_BASE (0) + +#define clstl_cpu_wfe -1 +#define clstb_cpu_wfe -1 +#define CKECK_WFEI_MSK 0 + + +#define PD_CTR_LOOP 500 +#define CHK_CPU_LOOP 500 + +#define MAX_WAIT_CONUT 1000 + +#endif /* PMU_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c new file mode 100644 index 0000000..25e1cca --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + +static void sgrf_ddr_rgn_global_bypass(uint32_t bypass) +{ + if (bypass) + /* set bypass (non-secure regions) for whole ddr regions */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(21), + SGRF_DDR_RGN_BYPS); + else + /* cancel bypass for whole ddr regions */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(21), + SGRF_DDR_RGN_NO_BYPS); +} + +/** + * There are 8 + 1 regions for DDR secure control: + * DDR_RGN_0 ~ DDR_RGN_7: Per DDR_RGNs grain size is 1MB + * DDR_RGN_X - the memories of exclude DDR_RGN_0 ~ DDR_RGN_7 + * + * SGRF_SOC_CON6 - start address of RGN_0 + control + * SGRF_SOC_CON7 - end address of RGN_0 + * ... + * SGRF_SOC_CON20 - start address of the RGN_7 + control + * SGRF_SOC_CON21 - end address of the RGN_7 + RGN_X control + * + * @rgn - the DDR regions 0 ~ 7 which are can be configured. + * @st - start address to set as secure + * @sz - length of area to set as secure + * The @st_mb and @ed_mb indicate the start and end addresses for which to set + * the security, and the unit is megabyte. When the st_mb == 0, ed_mb == 0, the + * address range 0x0 ~ 0xfffff is secure. + * + * For example, if we would like to set the range [0, 32MB) is security via + * DDR_RGN0, then rgn == 0, st_mb == 0, ed_mb == 31. + */ +static void sgrf_ddr_rgn_config(uint32_t rgn, uintptr_t st, size_t sz) +{ + uintptr_t ed = st + sz; + uintptr_t st_mb, ed_mb; + + assert(rgn <= 7); + assert(st < ed); + + /* check aligned 1MB */ + assert(st % SIZE_M(1) == 0); + assert(ed % SIZE_M(1) == 0); + + st_mb = st / SIZE_M(1); + ed_mb = ed / SIZE_M(1); + + /* set ddr region addr start */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)), + BITS_WITH_WMASK(st_mb, SGRF_DDR_RGN_ADDR_WMSK, 0)); + + /* set ddr region addr end */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2) + 1), + BITS_WITH_WMASK((ed_mb - 1), SGRF_DDR_RGN_ADDR_WMSK, 0)); + + /* select region security */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)), + SGRF_DDR_RGN_SECURE_SEL); + + /* enable region security */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)), + SGRF_DDR_RGN_SECURE_EN); +} + +void secure_watchdog_gate(void) +{ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_PCLK_WDT_GATE); +} + +void secure_watchdog_ungate(void) +{ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_PCLK_WDT_UNGATE); +} + +__pmusramfunc void sram_secure_timer_init(void) +{ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, 0); + + mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT0, 0xffffffff); + mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN); +} + +void secure_gic_init(void) +{ + /* (re-)enable non-secure access to the gic*/ + mmio_write_32(CORE_AXI_BUS_BASE + CORE_AXI_SECURITY0, + AXI_SECURITY0_GIC); +} + +void secure_timer_init(void) +{ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, 0); + + mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT0, 0xffffffff); + mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN); +} + +void secure_sgrf_init(void) +{ + /* + * We use the first sram part to talk to the bootrom, + * so make it secure. + */ + mmio_write_32(TZPC_BASE + TZPC_R0SIZE, TZPC_SRAM_SECURE_4K(1)); + + secure_gic_init(); + + /* set all master ip to non-secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), SGRF_SOC_CON2_MST_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), SGRF_SOC_CON3_MST_NS); + + /* setting all configurable ip into non-secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4), + SGRF_SOC_CON4_SECURE_WMSK /*TODO:|SGRF_STIMER_SECURE*/); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON5_SECURE_WMSK); + + /* secure dma to non-secure */ + mmio_write_32(TZPC_BASE + TZPC_DECPROT1SET, 0xff); + mmio_write_32(TZPC_BASE + TZPC_DECPROT2SET, 0xff); + mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), 0x3800); + dsb(); + + /* rst dma1 */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), + RST_DMA1_MSK | (RST_DMA1_MSK << 16)); + /* rst dma2 */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), + RST_DMA2_MSK | (RST_DMA2_MSK << 16)); + + dsb(); + + /* release dma1 rst*/ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16)); + /* release dma2 rst*/ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16)); +} + +void secure_sgrf_ddr_rgn_init(void) +{ + sgrf_ddr_rgn_config(0, TZRAM_BASE, TZRAM_SIZE); + sgrf_ddr_rgn_global_bypass(0); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h new file mode 100644 index 0000000..6c0b2b7 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SECURE_H +#define SECURE_H + +/****************************************************************************** + * TZPC TrustZone controller + ******************************************************************************/ + +#define TZPC_R0SIZE 0x0 +#define TZPC_SRAM_SECURE_4K(n) ((n) > 0x200 ? 0x200 : (n)) +#define TZPC_DECPROT1STAT 0x80c +#define TZPC_DECPROT1SET 0x810 +#define TZPC_DECPROT1CLR 0x814 +#define TZPC_DECPROT2STAT 0x818 +#define TZPC_DECPROT2SET 0x818 +#define TZPC_DECPROT2CLR 0x820 + +/************************************************** + * sgrf reg, offset + **************************************************/ +/* + * soc_con0-5 start at 0x0, soc_con6-... start art 0x50 + * adjusted for the 5 lower registers + */ +#define SGRF_SOC_CON(n) ((((n) < 6) ? 0x0 : 0x38) + (n) * 4) +#define SGRF_BUSDMAC_CON(n) (0x20 + (n) * 4) +#define SGRF_CPU_CON(n) (0x40 + (n) * 4) +#define SGRF_SOC_STATUS(n) (0x100 + (n) * 4) +#define SGRF_FAST_BOOT_ADDR 0x120 + +/* SGRF_SOC_CON0 */ +#define SGRF_FAST_BOOT_ENA BIT_WITH_WMSK(8) +#define SGRF_FAST_BOOT_DIS WMSK_BIT(8) +#define SGRF_PCLK_WDT_GATE BIT_WITH_WMSK(6) +#define SGRF_PCLK_WDT_UNGATE WMSK_BIT(6) +#define SGRF_PCLK_STIMER_GATE BIT_WITH_WMSK(4) + +#define SGRF_SOC_CON2_MST_NS 0xffe0ffe0 +#define SGRF_SOC_CON3_MST_NS 0x003f003f + +/* SGRF_SOC_CON4 */ +#define SGRF_SOC_CON4_SECURE_WMSK 0xffff0000 +#define SGRF_DDRC1_SECURE BIT_WITH_WMSK(12) +#define SGRF_DDRC0_SECURE BIT_WITH_WMSK(11) +#define SGRF_PMUSRAM_SECURE BIT_WITH_WMSK(8) +#define SGRF_WDT_SECURE BIT_WITH_WMSK(7) +#define SGRF_STIMER_SECURE BIT_WITH_WMSK(6) + +/* SGRF_SOC_CON5 */ +#define SGRF_SLV_SEC_BYPS BIT_WITH_WMSK(15) +#define SGRF_SLV_SEC_NO_BYPS WMSK_BIT(15) +#define SGRF_SOC_CON5_SECURE_WMSK 0x00ff0000 + +/* ddr regions in SGRF_SOC_CON6 and following */ +#define SGRF_DDR_RGN_SECURE_SEL BIT_WITH_WMSK(15) +#define SGRF_DDR_RGN_SECURE_EN BIT_WITH_WMSK(14) +#define SGRF_DDR_RGN_ADDR_WMSK 0x0fff + +/* SGRF_SOC_CON21 */ +/* All security of the DDR RGNs are bypassed */ +#define SGRF_DDR_RGN_BYPS BIT_WITH_WMSK(15) +#define SGRF_DDR_RGN_NO_BYPS WMSK_BIT(15) + +/* SGRF_CPU_CON0 */ +#define SGRF_DAPDEVICE_ENA BIT_WITH_WMSK(0) +#define SGRF_DAPDEVICE_MSK WMSK_BIT(0) + +/***************************************************************************** + * core-axi + *****************************************************************************/ +#define CORE_AXI_SECURITY0 0x08 +#define AXI_SECURITY0_GIC BIT(0) + +/***************************************************************************** + * secure timer + *****************************************************************************/ +#define TIMER_LOAD_COUNT0 0x00 +#define TIMER_LOAD_COUNT1 0x04 +#define TIMER_CURRENT_VALUE0 0x08 +#define TIMER_CURRENT_VALUE1 0x0C +#define TIMER_CONTROL_REG 0x10 +#define TIMER_INTSTATUS 0x18 + +#define TIMER_EN 0x1 + +#define STIMER1_BASE (STIME_BASE + 0x20) + +/* export secure operating APIs */ +void secure_watchdog_gate(void); +void secure_watchdog_ungate(void); +void secure_gic_init(void); +void secure_timer_init(void); +void secure_sgrf_init(void); +void secure_sgrf_ddr_rgn_init(void); +__pmusramfunc void sram_secure_timer_init(void); + +#endif /* SECURE_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c new file mode 100644 index 0000000..36f410b --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* sleep data for pll suspend */ +static struct deepsleep_data_s slp_data; + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(STIME_BASE, STIME_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TZPC_BASE, TZPC_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SRAM_BASE, SRAM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMU_BASE, PMU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART0_BASE, UART0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART1_BASE, UART1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART2_BASE, UART2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART3_BASE, UART3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART4_BASE, UART4_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CRU_BASE, CRU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GRF_BASE, GRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PCTL0_BASE, DDR_PCTL0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PHY0_BASE, DDR_PHY0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PCTL1_BASE, DDR_PCTL1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PHY1_BASE, DDR_PHY1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CORE_AXI_BUS_BASE, CORE_AXI_BUS_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/* The RockChip power domain tree descriptor */ +const unsigned char rockchip_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + secure_sgrf_init(); + /* + * We cannot enable ddr security at this point, as the kernel + * seems to have an issue with it even living in the same 128MB + * memory block. Only when moving the kernel to the second + * 128MB block does it not conflict, but then we'd loose this + * memory area for use. Late maybe enable + * secure_sgrf_ddr_rgn_init(); + */ +} + +void regs_update_bits(uintptr_t addr, uint32_t val, + uint32_t mask, uint32_t shift) +{ + uint32_t tmp, orig; + + orig = mmio_read_32(addr); + + tmp = orig & ~(mask << shift); + tmp |= (val & mask) << shift; + + if (tmp != orig) + mmio_write_32(addr, tmp); + dsb(); +} + +static void pll_save(uint32_t pll_id) +{ + uint32_t *pll = slp_data.pll_con[pll_id]; + + pll[0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0)); + pll[1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1)); + pll[2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2)); + pll[3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3)); +} + +void clk_plls_suspend(void) +{ + pll_save(NPLL_ID); + pll_save(CPLL_ID); + pll_save(GPLL_ID); + pll_save(APLL_ID); + slp_data.pll_mode = mmio_read_32(CRU_BASE + PLL_MODE_CON); + + /* + * Switch PLLs other than DPLL (for SDRAM) to slow mode to + * avoid crashes on resume. The Mask ROM on the system will + * put APLL, CPLL, and GPLL into slow mode at resume time + * anyway (which is why we restore them), but we might not + * even make it to the Mask ROM if this isn't done at suspend + * time. + * + * NOTE: only APLL truly matters here, but we'll do them all. + */ + mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000); +} + +void clk_plls_resume(void) +{ + /* restore pll-modes */ + mmio_write_32(CRU_BASE + PLL_MODE_CON, + slp_data.pll_mode | REG_SOC_WMSK); +} + +void clk_gate_con_save(void) +{ + uint32_t i = 0; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + slp_data.cru_gate_con[i] = + mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i)); +} + +void clk_gate_con_disable(void) +{ + uint32_t i; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), REG_SOC_WMSK); +} + +void clk_gate_con_restore(void) +{ + uint32_t i; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + REG_SOC_WMSK | slp_data.cru_gate_con[i]); +} + +void clk_sel_con_save(void) +{ + uint32_t i = 0; + + for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) + slp_data.cru_sel_con[i] = + mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(i)); +} + +void clk_sel_con_restore(void) +{ + uint32_t i, val; + + for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) { + /* fractional dividers don't have write-masks */ + if ((i >= 7 && i <= 9) || + (i >= 17 && i <= 20) || + (i == 23) || (i == 41)) + val = slp_data.cru_sel_con[i]; + else + val = slp_data.cru_sel_con[i] | REG_SOC_WMSK; + + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(i), val); + } +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + uint32_t temp_val; + + /* + * Switch PLLs other than DPLL (for SDRAM) to slow mode to + * avoid crashes on resume. The Mask ROM on the system will + * put APLL, CPLL, and GPLL into slow mode at resume time + * anyway (which is why we restore them), but we might not + * even make it to the Mask ROM if this isn't done at suspend + * time. + * + * NOTE: only APLL truly matters here, but we'll do them all. + */ + mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000); + + temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON); + temp_val &= ~PMU_RST_MASK; + temp_val |= PMU_RST_BY_SECOND_SFT; + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val); + mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to excute valid codes. + */ + while (1) + ; +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h new file mode 100644 index 0000000..b96c4dc --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +enum plls_id { + APLL_ID = 0, + DPLL_ID, + CPLL_ID, + GPLL_ID, + NPLL_ID, + END_PLL_ID, +}; + + +#define CYCL_24M_CNT_US(us) (24 * (us)) +#define CYCL_24M_CNT_MS(ms) ((ms) * CYCL_24M_CNT_US(1000)) + +/***************************************************************************** + * grf regs + *****************************************************************************/ +#define GRF_UOC0_CON0 0x320 +#define GRF_UOC1_CON0 0x334 +#define GRF_UOC2_CON0 0x348 +#define GRF_SIDDQ BIT(13) + +/***************************************************************************** + * cru reg, offset + *****************************************************************************/ +#define CRU_SOFTRST_CON 0x1b8 +#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4)) +#define CRU_SOFTRSTS_CON_CNT 11 + +#define RST_DMA1_MSK 0x4 +#define RST_DMA2_MSK 0x1 + +#define CRU_CLKSEL_CON 0x60 +#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4)) +#define CRU_CLKSELS_CON_CNT 42 + +#define CRU_CLKGATE_CON 0x160 +#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4)) +#define CRU_CLKGATES_CON_CNT 18 + +#define CRU_GLB_SRST_FST 0x1b0 +#define CRU_GLB_SRST_SND 0x1b4 +#define CRU_GLB_RST_CON 0x1f0 + +#define CRU_CONS_GATEID(i) (16 * (i)) +#define GATE_ID(reg, bit) (((reg) * 16) + (bit)) + +#define PMU_RST_MASK 0x3 +#define PMU_RST_BY_FIRST_SFT (0 << 2) +#define PMU_RST_BY_SECOND_SFT (1 << 2) +#define PMU_RST_NOT_BY_SFT (2 << 2) + +/*************************************************************************** + * pll + ***************************************************************************/ +#define PLL_CON_COUNT 4 +#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4)) +#define PLL_PWR_DN_MSK BIT(1) +#define PLL_PWR_DN REG_WMSK_BITS(1, 1, 0x1) +#define PLL_PWR_ON REG_WMSK_BITS(0, 1, 0x1) +#define PLL_RESET REG_WMSK_BITS(1, 5, 0x1) +#define PLL_RESET_RESUME REG_WMSK_BITS(0, 5, 0x1) +#define PLL_BYPASS_MSK BIT(0) +#define PLL_BYPASS_W_MSK (PLL_BYPASS_MSK << 16) +#define PLL_BYPASS REG_WMSK_BITS(1, 0, 0x1) +#define PLL_NO_BYPASS REG_WMSK_BITS(0, 0, 0x1) + +#define PLL_MODE_CON 0x50 + +struct deepsleep_data_s { + uint32_t pll_con[END_PLL_ID][PLL_CON_COUNT]; + uint32_t pll_mode; + uint32_t cru_sel_con[CRU_CLKSELS_CON_CNT]; + uint32_t cru_gate_con[CRU_CLKGATES_CON_CNT]; +}; + +#define REG_W_MSK(bits_shift, msk) \ + ((msk) << ((bits_shift) + 16)) +#define REG_VAL_CLRBITS(val, bits_shift, msk) \ + ((val) & (~((msk) << bits_shift))) +#define REG_SET_BITS(bits, bits_shift, msk) \ + (((bits) & (msk)) << (bits_shift)) +#define REG_WMSK_BITS(bits, bits_shift, msk) \ + (REG_W_MSK(bits_shift, msk) | \ + REG_SET_BITS(bits, bits_shift, msk)) +#define REG_SOC_WMSK 0xffff0000 + +#define regs_update_bit_set(addr, shift) \ + regs_update_bits((addr), 0x1, 0x1, (shift)) +#define regs_update_bit_clr(addr, shift) \ + regs_update_bits((addr), 0x0, 0x1, (shift)) + +void regs_update_bits(uintptr_t addr, uint32_t val, + uint32_t mask, uint32_t shift); +void clk_plls_suspend(void); +void clk_plls_resume(void); +void clk_gate_con_save(void); +void clk_gate_con_disable(void); +void clk_gate_con_restore(void); +void clk_sel_con_save(void); +void clk_sel_con_restore(void); +#endif /* SOC_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h b/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h new file mode 100644 index 0000000..66c4868 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +#define RK_PLAT_SIP_NUM_CALLS 0 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S b/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S new file mode 100644 index 0000000..2878437 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ROCKCHIP_PLAT_LD_S +#define ROCKCHIP_PLAT_LD_S + +#include + +MEMORY { + SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = SRAM_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "SRAM_BASE address is not aligned on a page boundary.") + + .text_sram : ALIGN(PAGE_SIZE) { + __bl32_sram_text_start = .; + *(.sram.text) + *(.sram.rodata) + __bl32_sram_text_real_end = .; + . = ALIGN(PAGE_SIZE); + __bl32_sram_text_end = .; + } >SRAM + ASSERT((__bl32_sram_text_real_end - __bl32_sram_text_start) <= + SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit") + + .data_sram : ALIGN(PAGE_SIZE) { + __bl32_sram_data_start = .; + *(.sram.data) + __bl32_sram_data_real_end = .; + . = ALIGN(PAGE_SIZE); + __bl32_sram_data_end = .; + } >SRAM + ASSERT((__bl32_sram_data_real_end - __bl32_sram_data_start) <= + SRAM_DATA_LIMIT, ".data_sram has exceeded its limit") + + .stack_sram : ALIGN(PAGE_SIZE) { + __bl32_sram_stack_start = .; + . += PAGE_SIZE; + __bl32_sram_stack_end = .; + } >SRAM + + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + *(.pmusram.entry) + + __bl32_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl32_pmusram_text_end = .; + + __bl32_pmusram_data_start = .; + *(.pmusram.data) + __bl32_pmusram_data_end = .; + } >PMUSRAM +} + +#endif /* ROCKCHIP_PLAT_LD_S */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h new file mode 100644 index 0000000..85ec3fb --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#include +#include + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf32-littlearm" +#define PLATFORM_LINKER_ARCH arm + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL1) +#define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +#define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x800 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_RK_CLST_TO_CPUID_SHIFT 6 + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* + * 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 U(1) + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 18 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Define GICD and GICC and GICR base + */ +#define PLAT_RK_GICD_BASE RK3288_GICD_BASE +#define PLAT_RK_GICC_BASE RK3288_GICC_BASE + +#define PLAT_RK_UART_BASE UART2_BASE +#define PLAT_RK_UART_CLOCK RK3288_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE RK3288_BAUDRATE + +/* ClusterId is always 0x5 on rk3288, filter it */ +#define PLAT_RK_MPIDR_CLUSTER_MASK 0 +#define PLAT_RK_PRIMARY_CPU 0x0 + +#define PSRAM_DO_DDR_RESUME 0 +#define PSRAM_CHECK_WAKEUP_CPU 0 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h b/arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h new file mode 100644 index 0000000..ffdb2f3 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL32_PARAM_H +#define BL32_PARAM_H + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF text, ro, rw, Size: 1MB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x100000) + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +/* + * Put BL32 at the top of the Trusted RAM + */ +#define BL32_BASE (TZRAM_BASE + 0x40000) +#define BL32_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +#endif /* BL32_PARAM_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c b/arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c new file mode 100644 index 0000000..5918d58 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +uintptr_t rockchip_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) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/platform.mk b/arm-trusted-firmware/plat/rockchip/rk3288/platform.mk new file mode 100644 index 0000000..b8dd195 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/platform.mk @@ -0,0 +1,69 @@ +# +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/arm/gic/v2/gicv2.mk + +ARM_CORTEX_A12 := yes +ARM_ARCH_MAJOR := 7 + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +DISABLE_BIN_GENERATION := 1 + +PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/aarch32/ \ + -I${RK_PLAT_COMMON}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/secure/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/include/ \ + -I${RK_PLAT_SOC}/include/shared/ \ + +RK_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + ${RK_PLAT}/common/rockchip_gicv2.c + +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + plat/common/aarch32/crash_console_helpers.S \ + plat/common/plat_psci_common.c + +PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch32/xlat_tables.c + +BL32_SOURCES += ${RK_GIC_SOURCES} \ + drivers/arm/cci/cci.c \ + drivers/ti/uart/aarch32/16550_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/aarch32/cortex_a12.S \ + ${RK_PLAT_COMMON}/aarch32/plat_helpers.S \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/aarch32/pmu_sram_cpus_on.S \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/aarch32/platform_common.c \ + ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/drivers/secure/secure.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + +MULTI_CONSOLE_API := 1 + +include lib/coreboot/coreboot.mk +include lib/libfdt/libfdt.mk + +$(eval $(call add_define,PLAT_SP_MIN_EXTRA_LD_SCRIPT)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +WORKAROUND_CVE_2017_5715 := 0 diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h b/arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h new file mode 100644 index 0000000..7bff865 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RK3288_DEF_H +#define RK3288_DEF_H + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define SIZE_K(n) ((n) * 1024) +#define SIZE_M(n) ((n) * 1024 * 1024) + +#define SRAM_TEXT_LIMIT (4 * 1024) +#define SRAM_DATA_LIMIT (4 * 1024) + +#define DDR_PCTL0_BASE 0xff610000 +#define DDR_PCTL0_SIZE SIZE_K(64) + +#define DDR_PHY0_BASE 0xff620000 +#define DDR_PHY0_SIZE SIZE_K(64) + +#define DDR_PCTL1_BASE 0xff630000 +#define DDR_PCTL1_SIZE SIZE_K(64) + +#define DDR_PHY1_BASE 0xff640000 +#define DDR_PHY1_SIZE SIZE_K(64) + +#define UART0_BASE 0xff180000 +#define UART0_SIZE SIZE_K(64) + +#define UART1_BASE 0xff190000 +#define UART1_SIZE SIZE_K(64) + +#define UART2_BASE 0xff690000 +#define UART2_SIZE SIZE_K(64) + +#define UART3_BASE 0xff1b0000 +#define UART3_SIZE SIZE_K(64) + +#define UART4_BASE 0xff1c0000 +#define UART4_SIZE SIZE_K(64) + +/* 96k instead of 64k? */ +#define SRAM_BASE 0xff700000 +#define SRAM_SIZE SIZE_K(64) + +#define PMUSRAM_BASE 0xff720000 +#define PMUSRAM_SIZE SIZE_K(4) +#define PMUSRAM_RSIZE SIZE_K(4) + +#define PMU_BASE 0xff730000 +#define PMU_SIZE SIZE_K(64) + +#define SGRF_BASE 0xff740000 +#define SGRF_SIZE SIZE_K(64) + +#define CRU_BASE 0xff760000 +#define CRU_SIZE SIZE_K(64) + +#define GRF_BASE 0xff770000 +#define GRF_SIZE SIZE_K(64) + +/* timer 6+7 can be set as secure in SGRF */ +#define STIME_BASE 0xff810000 +#define STIME_SIZE SIZE_K(64) + +#define SERVICE_BUS_BASE 0xffac0000 +#define SERVICE_BUS_SIZE SIZE_K(64) + +#define TZPC_BASE 0xffb00000 +#define TZPC_SIZE SIZE_K(64) + +#define GIC400_BASE 0xffc00000 +#define GIC400_SIZE SIZE_K(64) + +#define CORE_AXI_BUS_BASE 0xffd00000 +#define CORE_AXI_BUS_SIZE SIZE_M(1) + +#define COLD_BOOT_BASE 0xffff0000 +/************************************************************************** + * UART related constants + **************************************************************************/ +#define RK3288_BAUDRATE 115200 +#define RK3288_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000 + +/****************************************************************************** + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base rk_platform compatible GIC memory map */ +#define RK3288_GICD_BASE (GIC400_BASE + 0x1000) +#define RK3288_GICC_BASE (GIC400_BASE + 0x2000) +#define RK3288_GICR_BASE 0 /* no GICR in GIC-400 */ + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#define RK_IRQ_SEC_PHY_TIMER 29 + +/* what are these, and are they present on rk3288? */ +#define RK_IRQ_SEC_SGI_0 8 +#define RK_IRQ_SEC_SGI_1 9 +#define RK_IRQ_SEC_SGI_2 10 +#define RK_IRQ_SEC_SGI_3 11 +#define RK_IRQ_SEC_SGI_4 12 +#define RK_IRQ_SEC_SGI_5 13 +#define RK_IRQ_SEC_SGI_6 14 +#define RK_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 0 interrupts. + */ +#define PLAT_RK_GICV2_G0_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#endif /* RK3288_DEF_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk b/arm-trusted-firmware/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk new file mode 100644 index 0000000..befdca3 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk @@ -0,0 +1,8 @@ +# +# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \ + plat/rockchip/common/sp_min_plat_setup.c diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..cd604d2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +.globl clst_warmboot_data + +.macro func_rockchip_clst_warmboot +.endm + +.macro rockchip_clst_warmboot_data +clst_warmboot_data: + .rept PLATFORM_CLUSTER_COUNT + .word 0 + .endr +.endm diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c new file mode 100644 index 0000000..a17fef9 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 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 + +#include +#include +#include +#include + +DEFINE_BAKERY_LOCK(rockchip_pd_lock); + +static struct rk3328_sleep_ddr_data ddr_data; +static __sramdata struct rk3328_sleep_sram_data sram_data; + +static uint32_t cpu_warm_boot_addr; + +#pragma weak rk3328_pmic_suspend +#pragma weak rk3328_pmic_resume + +static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) +{ + uint32_t pd_reg, apm_reg; + + pd_reg = mmio_read_32(PMU_BASE + PMU_PWRDN_CON) & BIT(cpu_id); + apm_reg = mmio_read_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id)) & + BIT(core_pm_en); + + if (pd_reg && !apm_reg) + return core_pwr_pd; + else if (!pd_reg && apm_reg) + return core_pwr_wfi; + + ERROR("%s: 0x%x, 0x%x\n", __func__, pd_reg, apm_reg); + while (1) + ; +} + +static int cpus_power_domain_on(uint32_t cpu_id) +{ + uint32_t cpu_pd, cfg_info; + + cpu_pd = PD_CPU0 + cpu_id; + cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); + + if (cfg_info == core_pwr_pd) { + /* disable apm cfg */ + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + CORES_PM_DISABLE); + + /* if the cores have be on, power off it firstly */ + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + CORES_PM_DISABLE); + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } + pmu_power_domain_ctr(cpu_pd, pmu_pd_on); + } else { + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id); + return -EINVAL; + } + + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + BIT(core_pm_sft_wakeup_en)); + } + + return 0; +} + +static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) +{ + uint32_t cpu_pd, core_pm_value; + + cpu_pd = PD_CPU0 + cpu_id; + if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) + return 0; + + if (pd_cfg == core_pwr_pd) { + if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) + return -EINVAL; + /* disable apm cfg */ + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + CORES_PM_DISABLE); + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } else { + core_pm_value = BIT(core_pm_en) | BIT(core_pm_dis_int); + if (pd_cfg == core_pwr_wfi_int) + core_pm_value |= BIT(core_pm_int_wakeup_en); + + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), + core_pm_value); + } + + return 0; +} + +static void nonboot_cpus_off(void) +{ + uint32_t boot_cpu, cpu; + + /* turn off noboot cpus */ + boot_cpu = plat_my_core_pos(); + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { + if (cpu == boot_cpu) + continue; + cpus_power_domain_off(cpu, core_pwr_pd); + } +} + +void sram_save(void) +{ + /* TODO: support the sdram save for rk3328 SoCs*/ +} + +void sram_restore(void) +{ + /* TODO: support the sdram restore for rk3328 SoCs */ +} + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) +{ + uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpu_id] = entrypoint; + dsb(); + + cpus_power_domain_on(cpu_id); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_off(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + cpus_power_domain_off(cpu_id, core_pwr_wfi); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_suspend(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; + cpuson_entry_point[cpu_id] = (uintptr_t)plat_get_sec_entrypoint(); + dsb(); + + cpus_power_domain_off(cpu_id, core_pwr_wfi_int); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), CORES_PM_DISABLE); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_resume(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), CORES_PM_DISABLE); + + return 0; +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(CPLL_ID)); + mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(GPLL_ID)); + mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(NPLL_ID)); + mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(APLL_ID)); + dsb(); + + mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, CRU_GLB_SRST_FST_VALUE); + dsb(); + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to excute valid codes. + */ + while (1) + ; +} + +/* + * For PMIC RK805, its sleep pin is connect with gpio2_d2 from rk3328. + * If the PMIC is configed for responding the sleep pin to power off it, + * once the pin is output high, it will get the pmic power off. + */ +void __dead2 rockchip_soc_system_off(void) +{ + uint32_t val; + + /* gpio config */ + val = mmio_read_32(GRF_BASE + GRF_GPIO2D_IOMUX); + val &= ~GPIO2_D2_GPIO_MODE; + mmio_write_32(GRF_BASE + GRF_GPIO2D_IOMUX, val); + + /* config output */ + val = mmio_read_32(GPIO2_BASE + SWPORTA_DDR); + val |= GPIO2_D2; + mmio_write_32(GPIO2_BASE + SWPORTA_DDR, val); + + /* config output high level */ + val = mmio_read_32(GPIO2_BASE); + val |= GPIO2_D2; + mmio_write_32(GPIO2_BASE, val); + dsb(); + + while (1) + ; +} + +static uint32_t clk_ungt_msk[CRU_CLKGATE_NUMS] = { + 0x187f, 0x0000, 0x010c, 0x0000, 0x0200, + 0x0010, 0x0000, 0x0017, 0x001f, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0003, 0x0000, + 0xf001, 0x27c0, 0x04D9, 0x03ff, 0x0000, + 0x0000, 0x0000, 0x0010, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0x0008 +}; + +static void clks_gating_suspend(uint32_t *ungt_msk) +{ + int i; + + for (i = 0; i < CRU_CLKGATE_NUMS; i++) { + ddr_data.clk_ungt_save[i] = + mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(i)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), + ((~ungt_msk[i]) << 16) | 0xffff); + } +} + +static void clks_gating_resume(void) +{ + int i; + + for (i = 0; i < CRU_CLKGATE_NUMS; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), + ddr_data.clk_ungt_save[i] | 0xffff0000); +} + +static inline void pm_pll_wait_lock(uint32_t pll_id) +{ + uint32_t delay = PLL_LOCKED_TIMEOUT; + + while (delay > 0) { + if (mmio_read_32(CRU_BASE + PLL_CONS(pll_id, 1)) & + PLL_IS_LOCKED) + break; + delay--; + } + if (delay == 0) + ERROR("lock-pll: %d\n", pll_id); +} + +static inline void pll_pwr_dwn(uint32_t pll_id, uint32_t pd) +{ + mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1), + BITS_WITH_WMASK(1U, 1U, 15)); + if (pd) + mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1), + BITS_WITH_WMASK(1, 1, 14)); + else + mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1), + BITS_WITH_WMASK(0, 1, 14)); +} + +static __sramfunc void dpll_suspend(void) +{ + int i; + + /* slow mode */ + mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(DPLL_ID)); + + /* save pll con */ + for (i = 0; i < CRU_PLL_CON_NUMS; i++) + sram_data.dpll_con_save[i] = + mmio_read_32(CRU_BASE + PLL_CONS(DPLL_ID, i)); + mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), + BITS_WITH_WMASK(1U, 1U, 15)); + mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), + BITS_WITH_WMASK(1, 1, 14)); +} + +static __sramfunc void dpll_resume(void) +{ + uint32_t delay = PLL_LOCKED_TIMEOUT; + + mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), + BITS_WITH_WMASK(1U, 1U, 15)); + mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), + BITS_WITH_WMASK(0, 1, 14)); + mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), + sram_data.dpll_con_save[1] | 0xc0000000); + + dsb(); + + while (delay > 0) { + if (mmio_read_32(CRU_BASE + PLL_CONS(DPLL_ID, 1)) & + PLL_IS_LOCKED) + break; + delay--; + } + if (delay == 0) + while (1) + ; + + mmio_write_32(CRU_BASE + CRU_CRU_MODE, + PLL_NORM_MODE(DPLL_ID)); +} + +static inline void pll_suspend(uint32_t pll_id) +{ + int i; + + /* slow mode */ + mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(pll_id)); + + /* save pll con */ + for (i = 0; i < CRU_PLL_CON_NUMS; i++) + ddr_data.cru_plls_con_save[pll_id][i] = + mmio_read_32(CRU_BASE + PLL_CONS(pll_id, i)); + + /* powerdown pll */ + pll_pwr_dwn(pll_id, pmu_pd_off); +} + +static inline void pll_resume(uint32_t pll_id) +{ + mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1), + ddr_data.cru_plls_con_save[pll_id][1] | 0xc0000000); + + pm_pll_wait_lock(pll_id); + + if (PLL_IS_NORM_MODE(ddr_data.cru_mode_save, pll_id)) + mmio_write_32(CRU_BASE + CRU_CRU_MODE, + PLL_NORM_MODE(pll_id)); +} + +static void pm_plls_suspend(void) +{ + ddr_data.cru_mode_save = mmio_read_32(CRU_BASE + CRU_CRU_MODE); + ddr_data.clk_sel0 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(0)); + ddr_data.clk_sel1 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(1)); + ddr_data.clk_sel18 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(18)); + ddr_data.clk_sel20 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(20)); + ddr_data.clk_sel24 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(24)); + ddr_data.clk_sel38 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(38)); + pll_suspend(NPLL_ID); + pll_suspend(CPLL_ID); + pll_suspend(GPLL_ID); + pll_suspend(APLL_ID); + + /* core */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(0), + BITS_WITH_WMASK(0, 0x1f, 0)); + + /* pclk_dbg */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(1), + BITS_WITH_WMASK(0, 0xf, 0)); + + /* crypto */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(20), + BITS_WITH_WMASK(0, 0x1f, 0)); + + /* pwm0 */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(24), + BITS_WITH_WMASK(0, 0x7f, 8)); + + /* uart2 from 24M */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(18), + BITS_WITH_WMASK(2, 0x3, 8)); + + /* clk_rtc32k */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(38), + BITS_WITH_WMASK(767, 0x3fff, 0) | + BITS_WITH_WMASK(2U, 0x3u, 14)); +} + +static void pm_plls_resume(void) +{ + /* clk_rtc32k */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(38), + ddr_data.clk_sel38 | + BITS_WMSK(0x3fff, 0) | + BITS_WMSK(0x3u, 14)); + + /* uart2 */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(18), + ddr_data.clk_sel18 | BITS_WMSK(0x3, 8)); + + /* pwm0 */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(24), + ddr_data.clk_sel24 | BITS_WMSK(0x7f, 8)); + + /* crypto */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(20), + ddr_data.clk_sel20 | BITS_WMSK(0x1f, 0)); + + /* pclk_dbg */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(1), + ddr_data.clk_sel1 | BITS_WMSK(0xf, 0)); + + /* core */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(0), + ddr_data.clk_sel0 | BITS_WMSK(0x1f, 0)); + + pll_pwr_dwn(APLL_ID, pmu_pd_on); + pll_pwr_dwn(GPLL_ID, pmu_pd_on); + pll_pwr_dwn(CPLL_ID, pmu_pd_on); + pll_pwr_dwn(NPLL_ID, pmu_pd_on); + + pll_resume(APLL_ID); + pll_resume(GPLL_ID); + pll_resume(CPLL_ID); + pll_resume(NPLL_ID); +} + +#define ARCH_TIMER_TICKS_PER_US (SYS_COUNTER_FREQ_IN_TICKS / 1000000) + +static __sramfunc void sram_udelay(uint32_t us) +{ + uint64_t pct_orig, pct_now; + uint64_t to_wait = ARCH_TIMER_TICKS_PER_US * us; + + isb(); + pct_orig = read_cntpct_el0(); + + do { + isb(); + pct_now = read_cntpct_el0(); + } while ((pct_now - pct_orig) <= to_wait); +} + +/* + * For PMIC RK805, its sleep pin is connect with gpio2_d2 from rk3328. + * If the PMIC is configed for responding the sleep pin + * to get it into sleep mode, + * once the pin is output high, it will get the pmic into sleep mode. + */ +__sramfunc void rk3328_pmic_suspend(void) +{ + sram_data.pmic_sleep_save = mmio_read_32(GRF_BASE + PMIC_SLEEP_REG); + sram_data.pmic_sleep_gpio_save[1] = mmio_read_32(GPIO2_BASE + 4); + sram_data.pmic_sleep_gpio_save[0] = mmio_read_32(GPIO2_BASE); + mmio_write_32(GRF_BASE + PMIC_SLEEP_REG, BITS_WITH_WMASK(0, 0x3, 4)); + mmio_write_32(GPIO2_BASE + 4, + sram_data.pmic_sleep_gpio_save[1] | BIT(26)); + mmio_write_32(GPIO2_BASE, + sram_data.pmic_sleep_gpio_save[0] | BIT(26)); +} + +__sramfunc void rk3328_pmic_resume(void) +{ + mmio_write_32(GPIO2_BASE, sram_data.pmic_sleep_gpio_save[0]); + mmio_write_32(GPIO2_BASE + 4, sram_data.pmic_sleep_gpio_save[1]); + mmio_write_32(GRF_BASE + PMIC_SLEEP_REG, + sram_data.pmic_sleep_save | BITS_WMSK(0xffffu, 0)); + /* Resuming volt need a lot of time */ + sram_udelay(100); +} + +static __sramfunc void ddr_suspend(void) +{ + sram_data.pd_sr_idle_save = mmio_read_32(DDR_UPCTL_BASE + + DDR_PCTL2_PWRCTL); + sram_data.pd_sr_idle_save &= SELFREF_EN; + + mmio_clrbits_32(DDR_UPCTL_BASE + DDR_PCTL2_PWRCTL, SELFREF_EN); + sram_data.ddr_grf_con0 = mmio_read_32(DDR_GRF_BASE + + DDRGRF_SOC_CON(0)); + mmio_write_32(DDR_GRF_BASE, BIT_WITH_WMSK(14) | WMSK_BIT(15)); + + /* + * Override csysreq from ddrc and + * send valid csysreq signal to PMU, + * csysreq is controlled by ddrc only + */ + + /* in self-refresh */ + mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(0)); + while ((mmio_read_32(DDR_GRF_BASE + DDRGRF_SOC_STATUS(1)) & + (0x03 << 12)) != (0x02 << 12)) + ; + /* ddr retention */ + mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(2)); + + /* ddr gating */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(0), + BITS_WITH_WMASK(0x7, 0x7, 4)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(7), + BITS_WITH_WMASK(1, 1, 4)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18), + BITS_WITH_WMASK(0x1ff, 0x1ff, 1)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(27), + BITS_WITH_WMASK(0x3, 0x3, 0)); + + dpll_suspend(); +} + +__sramfunc void dmc_restore(void) +{ + dpll_resume(); + + /* ddr gating */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(0), + BITS_WITH_WMASK(0, 0x7, 4)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(7), + BITS_WITH_WMASK(0, 1, 4)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18), + BITS_WITH_WMASK(0, 0x1ff, 1)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(27), + BITS_WITH_WMASK(0, 0x3, 0)); + + /* ddr de_retention */ + mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(2)); + /* exit self-refresh */ + mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(0)); + while ((mmio_read_32(DDR_GRF_BASE + DDRGRF_SOC_STATUS(1)) & + (0x03 << 12)) != (0x00 << 12)) + ; + + mmio_write_32(DDR_GRF_BASE, sram_data.ddr_grf_con0 | 0xc0000000); + if (sram_data.pd_sr_idle_save) + mmio_setbits_32(DDR_UPCTL_BASE + DDR_PCTL2_PWRCTL, + SELFREF_EN); +} + +static __sramfunc void sram_dbg_uart_suspend(void) +{ + sram_data.uart2_ier = mmio_read_32(UART2_BASE + UART_IER); + mmio_write_32(UART2_BASE + UART_IER, UART_INT_DISABLE); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(16), 0x20002000); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(2), 0x00040004); +} + +__sramfunc void sram_dbg_uart_resume(void) +{ + /* restore uart clk and reset fifo */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(16), 0x20000000); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(2), 0x00040000); + mmio_write_32(UART2_BASE + UART_FCR, UART_FIFO_RESET); + mmio_write_32(UART2_BASE + UART_IER, sram_data.uart2_ier); +} + +static __sramfunc void sram_soc_enter_lp(void) +{ + uint32_t apm_value; + + apm_value = BIT(core_pm_en) | + BIT(core_pm_dis_int) | + BIT(core_pm_int_wakeup_en); + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(PD_CPU0), apm_value); + + dsb(); + isb(); +err_loop: + wfi(); + /* + *Soc will enter low power mode and + *do not return to here. + */ + goto err_loop; +} + +__sramfunc void sram_suspend(void) +{ + /* disable mmu and icache */ + disable_mmu_icache_el3(); + tlbialle3(); + dsbsy(); + isb(); + + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + ((uintptr_t)&pmu_cpuson_entrypoint >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + + /* ddr self-refresh and gating phy */ + ddr_suspend(); + + rk3328_pmic_suspend(); + + sram_dbg_uart_suspend(); + + sram_soc_enter_lp(); +} + +void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void) +{ + sram_suspend(); + + /* should never reach here */ + psci_power_down_wfi(); +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + clks_gating_suspend(clk_ungt_msk); + + pm_plls_suspend(); + + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + pm_plls_resume(); + + clks_gating_resume(); + + plat_rockchip_gic_cpuif_enable(); + + return 0; +} + +void rockchip_plat_mmu_el3(void) +{ + /* TODO: support the el3 for rk3328 SoCs */ +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = 0; + + cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; + + /* the warm booting address of cpus */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + + nonboot_cpus_off(); + + INFO("%s: pd status 0x%x\n", + __func__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h new file mode 100644 index 0000000..dfb8912 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_H +#define PMU_H + +#include + +struct rk3328_sleep_ddr_data { + uint32_t pmu_debug_enable; + uint32_t debug_iomux_save; + uint32_t pmic_sleep_save; + uint32_t pmu_wakeup_conf0; + uint32_t pmu_pwrmd_com; + uint32_t cru_mode_save; + uint32_t clk_sel0, clk_sel1, clk_sel18, + clk_sel20, clk_sel24, clk_sel38; + uint32_t clk_ungt_save[CRU_CLKGATE_NUMS]; + uint32_t cru_plls_con_save[MAX_PLL][CRU_PLL_CON_NUMS]; +}; + +struct rk3328_sleep_sram_data { + uint32_t pmic_sleep_save; + uint32_t pmic_sleep_gpio_save[2]; + uint32_t ddr_grf_con0; + uint32_t dpll_con_save[CRU_PLL_CON_NUMS]; + uint32_t pd_sr_idle_save; + uint32_t uart2_ier; +}; + +/***************************************************************************** + * The ways of cores power domain contorlling + *****************************************************************************/ +enum cores_pm_ctr_mode { + core_pwr_pd = 0, + core_pwr_wfi = 1, + core_pwr_wfi_int = 2 +}; + +enum pmu_cores_pm_by_wfi { + core_pm_en = 0, + core_pm_int_wakeup_en, + core_pm_dis_int, + core_pm_sft_wakeup_en +}; + +extern void *pmu_cpuson_entrypoint_start; +extern void *pmu_cpuson_entrypoint_end; + +#define CORES_PM_DISABLE 0x0 + +/***************************************************************************** + * pmu con,reg + *****************************************************************************/ +#define PMU_WAKEUP_CFG0 0x00 +#define PMU_PWRDN_CON 0x0c +#define PMU_PWRDN_ST 0x10 +#define PMU_PWRMD_COM 0x18 +#define PMU_SFT_CON 0x1c +#define PMU_INT_CON 0x20 +#define PMU_INT_ST 0x24 +#define PMU_POWER_ST 0x44 +#define PMU_CPUAPM_CON(n) (0x80 + (n) * 4) +#define PMU_SYS_REG(n) (0xa0 + (n) * 4) + +#define CHECK_CPU_WFIE_BASE (GRF_BASE + GRF_CPU_STATUS(1)) + +enum pmu_core_pwrst_shift { + clst_cpu_wfe = 0, + clst_cpu_wfi = 4, +}; + +#define clstl_cpu_wfe (clst_cpu_wfe) +#define clstb_cpu_wfe (clst_cpu_wfe) + +enum pmu_pd_id { + PD_CPU0 = 0, + PD_CPU1, + PD_CPU2, + PD_CPU3, +}; + +enum pmu_power_mode_common { + pmu_mode_en = 0, + sref_enter_en, + global_int_disable_cfg, + cpu0_pd_en, + wait_wakeup_begin_cfg = 4, + l2_flush_en, + l2_idle_en, + ddrio_ret_de_req, + ddrio_ret_en = 8, +}; + +enum pmu_sft_con { + upctl_c_sysreq_cfg = 0, + l2flushreq_req, + ddr_io_ret_cfg, + pmu_sft_ret_cfg, +}; + +#define CKECK_WFE_MSK 0x1 +#define CKECK_WFI_MSK 0x10 +#define CKECK_WFEI_MSK 0x11 + +#define PD_CTR_LOOP 500 +#define CHK_CPU_LOOP 500 +#define MAX_WAIT_CONUT 1000 + +#define WAKEUP_INT_CLUSTER_EN 0x1 +#define PMIC_SLEEP_REG 0x34 + +#define PLL_IS_NORM_MODE(mode, pll_id) \ + ((mode & (PLL_NORM_MODE(pll_id)) & 0xffff) != 0) + +#define CTLR_ENABLE_G1_BIT BIT(1) +#define UART_FIFO_EMPTY BIT(6) + +#define UART_IER 0x04 +#define UART_FCR 0x08 +#define UART_LSR 0x14 + +#define UART_INT_DISABLE 0x00 +#define UART_FIFO_RESET 0x07 + +#endif /* PMU_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c new file mode 100644 index 0000000..306308f --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(UART0_BASE, UART0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART1_BASE, UART1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART2_BASE, UART2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMU_BASE, PMU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GPIO0_BASE, GPIO0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GPIO1_BASE, GPIO1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GPIO2_BASE, GPIO2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GPIO3_BASE, GPIO3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CRU_BASE, CRU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GRF_BASE, GRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(FIREWALL_CFG_BASE, FIREWALL_CFG_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(STIME_BASE, STIME_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SHARE_MEM_BASE, SHARE_MEM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_GRF_BASE, DDR_GRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_UPCTL_BASE, DDR_UPCTL_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PWM_BASE, PWM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PARAM_BASE, DDR_PARAM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(EFUSE8_BASE, EFUSE8_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(EFUSE32_BASE, EFUSE32_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PHY_BASE, DDR_PHY_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SERVER_MSCH_BASE, SERVER_MSCH_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_MONITOR_BASE, DDR_MONITOR_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(VOP_BASE, VOP_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + + { 0 } +}; + +/* The RockChip power domain tree descriptor */ +const unsigned char rockchip_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +void secure_timer_init(void) +{ + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOADE_COUNT0, 0xffffffff); + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOADE_COUNT1, 0xffffffff); + /* auto reload & enable the timer */ + mmio_write_32(STIMER_CHN_BASE(1) + TIMER_CONTROL_REG, TIMER_EN); +} + +void sgrf_init(void) +{ +#ifdef PLAT_RK_SECURE_DDR_MINILOADER + uint32_t i, val; + struct param_ddr_usage usg; + + /* general secure regions */ + usg = ddr_region_usage_parse(DDR_PARAM_BASE, + PLAT_MAX_DDR_CAPACITY_MB); + for (i = 0; i < usg.s_nr; i++) { + /* enable secure */ + val = mmio_read_32(FIREWALL_DDR_BASE + + FIREWALL_DDR_FW_DDR_CON_REG); + val |= BIT(7 - i); + mmio_write_32(FIREWALL_DDR_BASE + + FIREWALL_DDR_FW_DDR_CON_REG, val); + /* map top and base */ + mmio_write_32(FIREWALL_DDR_BASE + + FIREWALL_DDR_FW_DDR_RGN(7 - i), + RG_MAP_SECURE(usg.s_top[i], usg.s_base[i])); + } +#endif + + /* set ddr rgn0_top and rga0_top as 0 */ + mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_FW_DDR_RGN(0), 0x0); + + /* set all slave ip into no-secure, except stimer */ + mmio_write_32(FIREWALL_CFG_BASE + FIREWALL_CFG_FW_SYS_CON(0), + SGRF_SLV_S_ALL_NS); + mmio_write_32(FIREWALL_CFG_BASE + FIREWALL_CFG_FW_SYS_CON(1), + SGRF_SLV_S_ALL_NS); + mmio_write_32(FIREWALL_CFG_BASE + FIREWALL_CFG_FW_SYS_CON(2), + SGRF_SLV_S_ALL_NS | STIMER_S); + mmio_write_32(FIREWALL_CFG_BASE + FIREWALL_CFG_FW_SYS_CON(3), + SGRF_SLV_S_ALL_NS); + + /* set all master ip into no-secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), 0xf0000000); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), SGRF_MST_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4), SGRF_MST_S_ALL_NS); + + /* set DMAC into no-secure */ + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(3), DMA_IRQ_BOOT_NS); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(4), DMA_PERI_CH_NS_15_0); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(5), DMA_PERI_CH_NS_19_16); + mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(5), DMA_MANAGER_BOOT_NS); + + /* soft reset dma before use */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(3), DMA_SOFTRST_REQ); + udelay(5); + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(3), DMA_SOFTRST_RLS); +} + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + sgrf_init(); + + NOTICE("BL31:Rockchip release version: v%d.%d\n", + MAJOR_VERSION, MINOR_VERSION); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h new file mode 100644 index 0000000..e8cbc09 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +/******************************* stimer ***************************************/ +#define TIMER_LOADE_COUNT0 0x00 +#define TIMER_LOADE_COUNT1 0x04 +#define TIMER_CURRENT_VALUE0 0x08 +#define TIMER_CURRENT_VALUE1 0x0C +#define TIMER_CONTROL_REG 0x10 +#define TIMER_INTSTATUS 0x18 +#define TIMER_EN 0x1 + +/**************************** read/write **************************************/ +#ifndef BITS_WMSK +#define BITS_WMSK(msk, shift) ((msk) << (shift + REG_MSK_SHIFT)) +#endif + +/**************************** cru *********************************************/ +enum plls_id { + APLL_ID = 0, + DPLL_ID, + CPLL_ID, + GPLL_ID, + REVERVE, + NPLL_ID, + MAX_PLL, +}; + +#define CRU_CRU_MODE 0x0080 +#define CRU_CRU_MISC 0x0084 +#define CRU_GLB_SRST_FST 0x009c +#define CRU_GLB_SRST_FST_VALUE 0xfdb9 +#define PLL_CONS(id, i) (0x020 * (id) + ((i) * 4)) +#define CRU_CLKSEL_CON(i) (0x100 + ((i) * 4)) +#define CRU_CLKSEL_NUMS 53 +#define CRU_CLKGATE_CON(i) (0x200 + ((i) * 4)) +#define CRU_CLKGATE_NUMS 29 +#define CRU_SOFTRSTS_CON(n) (0x300 + ((n) * 4)) +#define CRU_SOFTRSTS_NUMS 12 +#define CRU_PLL_CON_NUMS 5 + +/* PLLn_CON1 */ +#define PLL_IS_LOCKED BIT(10) +/* PLLn_CON0 */ +#define PLL_BYPASS BITS_WITH_WMASK(1, 0x1, 15) +#define PLL_NO_BYPASS BITS_WITH_WMASK(0, 0x1, 15) +/* CRU_MODE */ +#define PLL_SLOW_MODE(id) ((id) == NPLL_ID) ? \ + BITS_WITH_WMASK(0, 0x1, 1) : \ + BITS_WITH_WMASK(0, 0x1, ((id) * 4)) +#define PLL_NORM_MODE(id) ((id) == NPLL_ID) ? \ + BITS_WITH_WMASK(1, 0x1, 1) : \ + BITS_WITH_WMASK(1, 0x1, ((id) * 4)) + +#define CRU_GATEID_CONS(ID) (0x200 + (ID / 16) * 4) +#define CRU_CONS_GATEID(i) (16 * (i)) +#define GATE_ID(reg, bit) ((reg * 16) + bit) + +#define PLL_LOCKED_TIMEOUT 600000U + +#define STIMER_CHN_BASE(n) (STIME_BASE + 0x20 * (n)) +/************************** config regs ***************************************/ +#define FIREWALL_CFG_FW_SYS_CON(n) (0x000 + (n) * 4) +#define FIREWALL_DDR_FW_DDR_RGN(n) (0x000 + (n) * 4) +#define FIREWALL_DDR_FW_DDR_MST(n) (0x020 + (n) * 4) +#define FIREWALL_DDR_FW_DDR_CON_REG (0x040) +#define GRF_SOC_CON(n) (0x400 + (n) * 4) +#define GRF_SOC_STATUS(n) (0x480 + (n) * 4) +#define GRF_CPU_STATUS(n) (0x520 + (n) * 4) +#define GRF_OS_REG(n) (0x5c8 + (n) * 4) +#define DDRGRF_SOC_CON(n) (0x000 + (n) * 4) +#define DDRGRF_SOC_STATUS(n) (0x100 + (n) * 4) +#define SGRF_SOC_CON(n) (0x000 + (n) * 4) +#define SGRF_DMAC_CON(n) (0x100 + (n) * 4) +#define SGRF_HDCP_KEY_CON(n) (0x280 + (n) * 4) + +#define DDR_PCTL2_PWRCTL 0x30 +/************************** regs func *****************************************/ +#define STIMER_S BIT(23) +#define SGRF_SLV_S_ALL_NS 0x0 +#define SGRF_MST_S_ALL_NS 0xffffffff +#define DMA_IRQ_BOOT_NS 0xffffffff +#define DMA_MANAGER_BOOT_NS 0x80008000 +#define DMA_PERI_CH_NS_15_0 0xffffffff +#define DMA_PERI_CH_NS_19_16 0x000f000f +#define DMA_SOFTRST_REQ 0x01000100 +#define DMA_SOFTRST_RLS 0x01000000 + +#define SELFREF_EN BIT(0) +/************************** cpu ***********************************************/ +#define CPU_BOOT_ADDR_WMASK 0xffff0000 +#define CPU_BOOT_ADDR_ALIGN 16 + +/************************** ddr secure region *********************************/ +#define PLAT_MAX_DDR_CAPACITY_MB 4096 +#define RG_MAP_SECURE(top, base) ((((top) - 1) << 16) | (base)) + +/************************** gpio2_d2 ******************************************/ +#define SWPORTA_DR 0x00 +#define SWPORTA_DDR 0x04 +#define GPIO2_D2 BIT(26) +#define GPIO2_D2_GPIO_MODE 0x30 +#define GRF_GPIO2D_IOMUX 0x34 + +#endif /* SOC_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S b/arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S new file mode 100644 index 0000000..e9bb3a2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ROCKCHIP_PLAT_LD_S +#define ROCKCHIP_PLAT_LD_S + +MEMORY { + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .text_pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + *(.pmusram.entry) + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; + + } >PMUSRAM +} + +#endif /* ROCKCHIP_PLAT_LD_S */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h new file mode 100644 index 0000000..6579756 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL1) +#define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +#define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x800 +#elif defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLATFORM_SYSTEM_COUNT 1 +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) + +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +#define PLAT_RK_CLST_TO_CPUID_SHIFT 6 + +/* + * 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 U(1) + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF text, ro, rw, Size: 1MB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x100000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted RAM + */ +#define BL31_BASE (TZRAM_BASE + 0x40000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 9 +#define MAX_MMAP_REGIONS 33 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Define GICD and GICC and GICR base + */ +#define PLAT_RK_GICD_BASE RK3328_GICD_BASE +#define PLAT_RK_GICC_BASE RK3328_GICC_BASE + +#define PLAT_RK_UART_BASE UART2_BASE +#define PLAT_RK_UART_CLOCK RK3328_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE RK3328_BAUDRATE + +#define PLAT_RK_PRIMARY_CPU 0x0 + +#define PSRAM_DO_DDR_RESUME 0 +#define PSRAM_CHECK_WAKEUP_CPU 0 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/platform.mk b/arm-trusted-firmware/plat/rockchip/rk3328/platform.mk new file mode 100644 index 0000000..5b4766d --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/platform.mk @@ -0,0 +1,75 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/arm/gic/v2/gicv2.mk + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +DISABLE_BIN_GENERATION := 1 + +PLAT_INCLUDES := -Idrivers/arm/gic/common/ \ + -Idrivers/arm/gic/v2/ \ + -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/aarch64/ \ + -I${RK_PLAT_COMMON}/drivers/pmu/ \ + -I${RK_PLAT_COMMON}/drivers/parameter/ \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/include/ + +RK_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + ${RK_PLAT}/common/rockchip_gicv2.c + +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/common/aarch64/crash_console_helpers.S \ + plat/common/plat_psci_common.c + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + +BL31_SOURCES += ${RK_GIC_SOURCES} \ + drivers/arm/cci/cci.c \ + drivers/ti/uart/aarch64/16550_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/aarch64/platform_common.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c + +ifdef PLAT_RK_SECURE_DDR_MINILOADER +BL31_SOURCES += ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c +endif + +include lib/coreboot/coreboot.mk +include lib/libfdt/libfdt.mk + +# Enable workarounds for selected Cortex-A53 errata +ERRATA_A53_855873 := 1 + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) +$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +WORKAROUND_CVE_2017_5715 := 0 diff --git a/arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h b/arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h new file mode 100644 index 0000000..60055e8 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RK3328_DEF_H +#define RK3328_DEF_H + +#define MAJOR_VERSION (1) +#define MINOR_VERSION (2) + +#define SIZE_K(n) ((n) * 1024) + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define UART0_BASE 0xff110000 +#define UART0_SIZE SIZE_K(64) + +#define UART1_BASE 0xff120000 +#define UART1_SIZE SIZE_K(64) + +#define UART2_BASE 0xff130000 +#define UART2_SIZE SIZE_K(64) + +#define PMU_BASE 0xff140000 +#define PMU_SIZE SIZE_K(64) + +#define SGRF_BASE 0xff0d0000 +#define SGRF_SIZE SIZE_K(64) + +#define CRU_BASE 0xff440000 +#define CRU_SIZE SIZE_K(64) + +#define GRF_BASE 0xff100000 +#define GRF_SIZE SIZE_K(64) + +#define GPIO0_BASE 0xff210000 +#define GPIO0_SIZE SIZE_K(32) + +#define GPIO1_BASE 0xff220000 +#define GPIO1_SIZE SIZE_K(32) + +#define GPIO2_BASE 0xff230000 +#define GPIO2_SIZE SIZE_K(64) + +#define GPIO3_BASE 0xff240000 +#define GPIO3_SIZE SIZE_K(64) + +#define STIME_BASE 0xff1d0000 +#define STIME_SIZE SIZE_K(64) + +#define INTMEM_BASE 0xff090000 +#define INTMEM_SIZE SIZE_K(32) + +#define SRAM_LDS_BASE (INTMEM_BASE + SIZE_K(4)) +#define SRAM_LDS_SIZE (INTMEM_SIZE - SIZE_K(4)) + +#define PMUSRAM_BASE INTMEM_BASE +#define PMUSRAM_SIZE SIZE_K(4) +#define PMUSRAM_RSIZE SIZE_K(4) + +#define VOP_BASE 0xff370000 +#define VOP_SIZE SIZE_K(16) + +#define DDR_PHY_BASE 0xff400000 +#define DDR_PHY_SIZE SIZE_K(4) + +#define SERVER_MSCH_BASE 0xff720000 +#define SERVER_MSCH_SIZE SIZE_K(4) + +#define DDR_UPCTL_BASE 0xff780000 +#define DDR_UPCTL_SIZE SIZE_K(12) + +#define DDR_MONITOR_BASE 0xff790000 +#define DDR_MONITOR_SIZE SIZE_K(4) + +#define FIREWALL_DDR_BASE 0xff7c0000 +#define FIREWALL_DDR_SIZE SIZE_K(64) + +#define FIREWALL_CFG_BASE 0xff7d0000 +#define FIREWALL_CFG_SIZE SIZE_K(64) + +#define GIC400_BASE 0xff810000 +#define GIC400_SIZE SIZE_K(64) + +#define DDR_GRF_BASE 0xff798000 +#define DDR_GRF_SIZE SIZE_K(16) + +#define PWM_BASE 0xff1b0000 +#define PWM_SIZE SIZE_K(64) + +#define DDR_PARAM_BASE 0x02000000 +#define DDR_PARAM_SIZE SIZE_K(4) + +#define EFUSE8_BASE 0xff260000 +#define EFUSE8_SIZE SIZE_K(4) + +#define EFUSE32_BASE 0xff0b0000 +#define EFUSE32_SIZE SIZE_K(4) + +/************************************************************************** + * UART related constants + **************************************************************************/ +#define RK3328_BAUDRATE 1500000 +#define RK3328_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000U +#define SYS_COUNTER_FREQ_IN_MHZ 24 + +/****************************************************************************** + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base rk_platform compatible GIC memory map */ +#define RK3328_GICD_BASE (GIC400_BASE + 0x1000) +#define RK3328_GICC_BASE (GIC400_BASE + 0x2000) +#define RK3328_GICR_BASE 0 /* no GICR in GIC-400 */ + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#define RK_IRQ_SEC_PHY_TIMER 29 + +#define RK_IRQ_SEC_SGI_0 8 +#define RK_IRQ_SEC_SGI_1 9 +#define RK_IRQ_SEC_SGI_2 10 +#define RK_IRQ_SEC_SGI_3 11 +#define RK_IRQ_SEC_SGI_4 12 +#define RK_IRQ_SEC_SGI_5 13 +#define RK_IRQ_SEC_SGI_6 14 +#define RK_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 0 interrupts. + */ +#define PLAT_RK_GICV2_G0_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K]*/ +#define SHARE_MEM_PAGE_NUM 15 +#define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4) + +#endif /* RK3328_DEF_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c new file mode 100644 index 0000000..fa98eb3 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +/* GRF_SOC_STATUS0 */ +#define DPLL_LOCK (0x1 << 2) + +/* GRF_DDRC0_CON0 */ +#define GRF_DDR_16BIT_EN (((0x1 << 3) << 16) | (0x1 << 3)) +#define GRF_DDR_32BIT_EN (((0x1 << 3) << 16) | (0x0 << 3)) +#define GRF_MOBILE_DDR_EN (((0x1 << 4) << 16) | (0x1 << 4)) +#define GRF_MOBILE_DDR_DISB (((0x1 << 4) << 16) | (0x0 << 4)) +#define GRF_DDR3_EN (((0x1 << 2) << 16) | (0x1 << 2)) +#define GRF_LPDDR2_3_EN (((0x1 << 2) << 16) | (0x0 << 2)) + +/* PMUGRF_SOC_CON0 */ +#define ddrphy_bufferen_io_en(n) ((0x1 << (9 + 16)) | (n << 9)) +#define ddrphy_bufferen_core_en(n) ((0x1 << (8 + 16)) | (n << 8)) + +struct PCTRL_TIMING_TAG { + uint32_t ddrfreq; + uint32_t TOGCNT1U; + uint32_t TINIT; + uint32_t TRSTH; + uint32_t TOGCNT100N; + uint32_t TREFI; + uint32_t TMRD; + uint32_t TRFC; + uint32_t TRP; + uint32_t TRTW; + uint32_t TAL; + uint32_t TCL; + uint32_t TCWL; + uint32_t TRAS; + uint32_t TRC; + uint32_t TRCD; + uint32_t TRRD; + uint32_t TRTP; + uint32_t TWR; + uint32_t TWTR; + uint32_t TEXSR; + uint32_t TXP; + uint32_t TXPDLL; + uint32_t TZQCS; + uint32_t TZQCSI; + uint32_t TDQS; + uint32_t TCKSRE; + uint32_t TCKSRX; + uint32_t TCKE; + uint32_t TMOD; + uint32_t TRSTL; + uint32_t TZQCL; + uint32_t TMRR; + uint32_t TCKESR; + uint32_t TDPD; + uint32_t TREFI_MEM_DDR3; +}; + +struct MSCH_SAVE_REG_TAG { + uint32_t ddrconf; + uint32_t ddrtiming; + uint32_t ddrmode; + uint32_t readlatency; + uint32_t activate; + uint32_t devtodev; +}; + +/* ddr suspend need save reg */ +struct PCTL_SAVE_REG_TAG { + uint32_t SCFG; + uint32_t CMDTSTATEN; + uint32_t MCFG1; + uint32_t MCFG; + uint32_t PPCFG; + struct PCTRL_TIMING_TAG pctl_timing; + /* DFI Control Registers */ + uint32_t DFITCTRLDELAY; + uint32_t DFIODTCFG; + uint32_t DFIODTCFG1; + uint32_t DFIODTRANKMAP; + /* DFI Write Data Registers */ + uint32_t DFITPHYWRDATA; + uint32_t DFITPHYWRLAT; + uint32_t DFITPHYWRDATALAT; + /* DFI Read Data Registers */ + uint32_t DFITRDDATAEN; + uint32_t DFITPHYRDLAT; + /* DFI Update Registers */ + uint32_t DFITPHYUPDTYPE0; + uint32_t DFITPHYUPDTYPE1; + uint32_t DFITPHYUPDTYPE2; + uint32_t DFITPHYUPDTYPE3; + uint32_t DFITCTRLUPDMIN; + uint32_t DFITCTRLUPDMAX; + uint32_t DFITCTRLUPDDLY; + uint32_t DFIUPDCFG; + uint32_t DFITREFMSKI; + uint32_t DFITCTRLUPDI; + /* DFI Status Registers */ + uint32_t DFISTCFG0; + uint32_t DFISTCFG1; + uint32_t DFITDRAMCLKEN; + uint32_t DFITDRAMCLKDIS; + uint32_t DFISTCFG2; + /* DFI Low Power Register */ + uint32_t DFILPCFG0; +}; + +struct DDRPHY_SAVE_REG_TAG { + uint32_t PHY_REG0; + uint32_t PHY_REG1; + uint32_t PHY_REGB; + uint32_t PHY_REGC; + uint32_t PHY_REG11; + uint32_t PHY_REG13; + uint32_t PHY_REG14; + uint32_t PHY_REG16; + uint32_t PHY_REG20; + uint32_t PHY_REG21; + uint32_t PHY_REG26; + uint32_t PHY_REG27; + uint32_t PHY_REG28; + uint32_t PHY_REG30; + uint32_t PHY_REG31; + uint32_t PHY_REG36; + uint32_t PHY_REG37; + uint32_t PHY_REG38; + uint32_t PHY_REG40; + uint32_t PHY_REG41; + uint32_t PHY_REG46; + uint32_t PHY_REG47; + uint32_t PHY_REG48; + uint32_t PHY_REG50; + uint32_t PHY_REG51; + uint32_t PHY_REG56; + uint32_t PHY_REG57; + uint32_t PHY_REG58; + uint32_t PHY_REGDLL; + uint32_t PHY_REGEC; + uint32_t PHY_REGED; + uint32_t PHY_REGEE; + uint32_t PHY_REGEF; + uint32_t PHY_REGFB; + uint32_t PHY_REGFC; + uint32_t PHY_REGFD; + uint32_t PHY_REGFE; +}; + +struct BACKUP_REG_TAG { + uint32_t tag; + uint32_t pctladdr; + struct PCTL_SAVE_REG_TAG pctl; + uint32_t phyaddr; + struct DDRPHY_SAVE_REG_TAG phy; + uint32_t nocaddr; + struct MSCH_SAVE_REG_TAG noc; + uint32_t pllselect; + uint32_t phypllockaddr; + uint32_t phyplllockmask; + uint32_t phyplllockval; + uint32_t pllpdstat; + uint32_t dpllmodeaddr; + uint32_t dpllslowmode; + uint32_t dpllnormalmode; + uint32_t dpllresetaddr; + uint32_t dpllreset; + uint32_t dplldereset; + uint32_t dpllconaddr; + uint32_t dpllcon[4]; + uint32_t dplllockaddr; + uint32_t dplllockmask; + uint32_t dplllockval; + uint32_t ddrpllsrcdivaddr; + uint32_t ddrpllsrcdiv; + uint32_t retendisaddr; + uint32_t retendisval; + uint32_t grfregaddr; + uint32_t grfddrcreg; + uint32_t crupctlphysoftrstaddr; + uint32_t cruresetpctlphy; + uint32_t cruderesetphy; + uint32_t cruderesetpctlphy; + uint32_t physoftrstaddr; + uint32_t endtag; +}; + +static uint32_t ddr_get_phy_pll_freq(void) +{ + uint32_t ret = 0; + uint32_t fb_div, pre_div; + + fb_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC); + fb_div |= (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED) & 0x1) << 8; + + pre_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) & 0xff; + ret = 2 * 24 * fb_div / (4 * pre_div); + + return ret; +} + +static void ddr_copy(uint32_t *pdest, uint32_t *psrc, uint32_t words) +{ + uint32_t i; + + for (i = 0; i < words; i++) + pdest[i] = psrc[i]; +} + +static void ddr_get_dpll_cfg(uint32_t *p) +{ + uint32_t nmhz, NO, NF, NR; + + nmhz = ddr_get_phy_pll_freq(); + if (nmhz <= 150) + NO = 6; + else if (nmhz <= 250) + NO = 4; + else if (nmhz <= 500) + NO = 2; + else + NO = 1; + + NR = 1; + NF = 2 * nmhz * NR * NO / 24; + + p[0] = SET_NR(NR) | SET_NO(NO); + p[1] = SET_NF(NF); + p[2] = SET_NB(NF / 2); +} + +void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr) +{ + struct BACKUP_REG_TAG *p_ddr_reg = (struct BACKUP_REG_TAG *)base_addr; + struct PCTL_SAVE_REG_TAG *pctl_tim = &p_ddr_reg->pctl; + + p_ddr_reg->tag = 0x56313031; + p_ddr_reg->pctladdr = DDR_PCTL_BASE; + p_ddr_reg->phyaddr = DDR_PHY_BASE; + p_ddr_reg->nocaddr = SERVICE_BUS_BASE; + + /* PCTLR */ + ddr_copy((uint32_t *)&pctl_tim->pctl_timing.TOGCNT1U, + (uint32_t *)(DDR_PCTL_BASE + DDR_PCTL_TOGCNT1U), 35); + pctl_tim->pctl_timing.TREFI |= DDR_UPD_REF_ENABLE; + pctl_tim->SCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_SCFG); + pctl_tim->CMDTSTATEN = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_CMDTSTATEN); + pctl_tim->MCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG1); + pctl_tim->MCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG); + pctl_tim->PPCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_PPCFG); + pctl_tim->pctl_timing.ddrfreq = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_TOGCNT1U * 2); + pctl_tim->DFITCTRLDELAY = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLDELAY); + pctl_tim->DFIODTCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIODTCFG); + pctl_tim->DFIODTCFG1 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFIODTCFG1); + pctl_tim->DFIODTRANKMAP = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFIODTRANKMAP); + pctl_tim->DFITPHYWRDATA = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYWRDATA); + pctl_tim->DFITPHYWRLAT = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYWRLAT); + pctl_tim->DFITPHYWRDATALAT = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYWRDATALAT); + pctl_tim->DFITRDDATAEN = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITRDDATAEN); + pctl_tim->DFITPHYRDLAT = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYRDLAT); + pctl_tim->DFITPHYUPDTYPE0 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYUPDTYPE0); + pctl_tim->DFITPHYUPDTYPE1 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYUPDTYPE1); + pctl_tim->DFITPHYUPDTYPE2 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYUPDTYPE2); + pctl_tim->DFITPHYUPDTYPE3 = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITPHYUPDTYPE3); + pctl_tim->DFITCTRLUPDMIN = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLUPDMIN); + pctl_tim->DFITCTRLUPDMAX = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLUPDMAX); + pctl_tim->DFITCTRLUPDDLY = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLUPDDLY); + + pctl_tim->DFIUPDCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIUPDCFG); + pctl_tim->DFITREFMSKI = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITREFMSKI); + pctl_tim->DFITCTRLUPDI = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITCTRLUPDI); + pctl_tim->DFISTCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG0); + pctl_tim->DFISTCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG1); + pctl_tim->DFITDRAMCLKEN = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITDRAMCLKEN); + pctl_tim->DFITDRAMCLKDIS = mmio_read_32(DDR_PCTL_BASE + + DDR_PCTL_DFITDRAMCLKDIS); + pctl_tim->DFISTCFG2 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG2); + pctl_tim->DFILPCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFILPCFG0); + + /* PHY */ + p_ddr_reg->phy.PHY_REG0 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG0); + p_ddr_reg->phy.PHY_REG1 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG1); + p_ddr_reg->phy.PHY_REGB = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGB); + p_ddr_reg->phy.PHY_REGC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGC); + p_ddr_reg->phy.PHY_REG11 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG11); + p_ddr_reg->phy.PHY_REG13 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG13); + p_ddr_reg->phy.PHY_REG14 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG14); + p_ddr_reg->phy.PHY_REG16 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG16); + p_ddr_reg->phy.PHY_REG20 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG20); + p_ddr_reg->phy.PHY_REG21 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG21); + p_ddr_reg->phy.PHY_REG26 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG26); + p_ddr_reg->phy.PHY_REG27 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG27); + p_ddr_reg->phy.PHY_REG28 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG28); + p_ddr_reg->phy.PHY_REG30 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG30); + p_ddr_reg->phy.PHY_REG31 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG31); + p_ddr_reg->phy.PHY_REG36 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG36); + p_ddr_reg->phy.PHY_REG37 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG37); + p_ddr_reg->phy.PHY_REG38 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG38); + p_ddr_reg->phy.PHY_REG40 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG40); + p_ddr_reg->phy.PHY_REG41 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG41); + p_ddr_reg->phy.PHY_REG46 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG46); + p_ddr_reg->phy.PHY_REG47 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG47); + p_ddr_reg->phy.PHY_REG48 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG48); + p_ddr_reg->phy.PHY_REG50 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG50); + p_ddr_reg->phy.PHY_REG51 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG51); + p_ddr_reg->phy.PHY_REG56 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG56); + p_ddr_reg->phy.PHY_REG57 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG57); + p_ddr_reg->phy.PHY_REG58 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG58); + p_ddr_reg->phy.PHY_REGDLL = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGDLL); + p_ddr_reg->phy.PHY_REGEC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC); + p_ddr_reg->phy.PHY_REGED = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED); + p_ddr_reg->phy.PHY_REGEE = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE); + p_ddr_reg->phy.PHY_REGEF = 0; + + if (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG2) & 0x2) { + p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REG2C); + p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REG3C); + p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REG4C); + p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REG5C); + } else { + p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGFB); + p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGFC); + p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGFD); + p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE + + DDR_PHY_REGFE); + } + + /* NOC */ + p_ddr_reg->noc.ddrconf = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRCONF); + p_ddr_reg->noc.ddrtiming = mmio_read_32(SERVICE_BUS_BASE + + MSCH_DDRTIMING); + p_ddr_reg->noc.ddrmode = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRMODE); + p_ddr_reg->noc.readlatency = mmio_read_32(SERVICE_BUS_BASE + + MSCH_READLATENCY); + p_ddr_reg->noc.activate = mmio_read_32(SERVICE_BUS_BASE + + MSCH_ACTIVATE); + p_ddr_reg->noc.devtodev = mmio_read_32(SERVICE_BUS_BASE + + MSCH_DEVTODEV); + + p_ddr_reg->pllselect = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) * 0x1; + p_ddr_reg->phypllockaddr = GRF_BASE + GRF_SOC_STATUS0; + p_ddr_reg->phyplllockmask = GRF_DDRPHY_LOCK; + p_ddr_reg->phyplllockval = 0; + + /* PLLPD */ + p_ddr_reg->pllpdstat = pllpdstat; + /* DPLL */ + p_ddr_reg->dpllmodeaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3); + /* slow mode and power on */ + p_ddr_reg->dpllslowmode = DPLL_WORK_SLOW_MODE | DPLL_POWER_DOWN; + p_ddr_reg->dpllnormalmode = DPLL_WORK_NORMAL_MODE; + p_ddr_reg->dpllresetaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3); + p_ddr_reg->dpllreset = DPLL_RESET_CONTROL_NORMAL; + p_ddr_reg->dplldereset = DPLL_RESET_CONTROL_RESET; + p_ddr_reg->dpllconaddr = CRU_BASE + PLL_CONS(DPLL_ID, 0); + + if (p_ddr_reg->pllselect == 0) { + p_ddr_reg->dpllcon[0] = (mmio_read_32(CRU_BASE + + PLL_CONS(DPLL_ID, 0)) + & 0xffff) | + (0xFFFFu << 16); + p_ddr_reg->dpllcon[1] = (mmio_read_32(CRU_BASE + + PLL_CONS(DPLL_ID, 1)) + & 0xffff); + p_ddr_reg->dpllcon[2] = (mmio_read_32(CRU_BASE + + PLL_CONS(DPLL_ID, 2)) + & 0xffff); + p_ddr_reg->dpllcon[3] = (mmio_read_32(CRU_BASE + + PLL_CONS(DPLL_ID, 3)) + & 0xffff) | + (0xFFFFu << 16); + } else { + ddr_get_dpll_cfg(&p_ddr_reg->dpllcon[0]); + } + + p_ddr_reg->pllselect = 0; + p_ddr_reg->dplllockaddr = CRU_BASE + PLL_CONS(DPLL_ID, 1); + p_ddr_reg->dplllockmask = DPLL_STATUS_LOCK; + p_ddr_reg->dplllockval = DPLL_STATUS_LOCK; + + /* SET_DDR_PLL_SRC */ + p_ddr_reg->ddrpllsrcdivaddr = CRU_BASE + CRU_CLKSELS_CON(13); + p_ddr_reg->ddrpllsrcdiv = (mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(13)) + & DDR_PLL_SRC_MASK) + | (DDR_PLL_SRC_MASK << 16); + p_ddr_reg->retendisaddr = PMU_BASE + PMU_PWRMD_COM; + p_ddr_reg->retendisval = PD_PERI_PWRDN_ENABLE; + p_ddr_reg->grfregaddr = GRF_BASE + GRF_DDRC0_CON0; + p_ddr_reg->grfddrcreg = (mmio_read_32(GRF_BASE + GRF_DDRC0_CON0) & + DDR_PLL_SRC_MASK) | + (DDR_PLL_SRC_MASK << 16); + + /* pctl phy soft reset */ + p_ddr_reg->crupctlphysoftrstaddr = CRU_BASE + CRU_SOFTRSTS_CON(10); + p_ddr_reg->cruresetpctlphy = DDRCTRL0_PSRSTN_REQ(1) | + DDRCTRL0_SRSTN_REQ(1) | + DDRPHY0_PSRSTN_REQ(1) | + DDRPHY0_SRSTN_REQ(1); + p_ddr_reg->cruderesetphy = DDRCTRL0_PSRSTN_REQ(1) | + DDRCTRL0_SRSTN_REQ(1) | + DDRPHY0_PSRSTN_REQ(0) | + DDRPHY0_SRSTN_REQ(0); + + p_ddr_reg->cruderesetpctlphy = DDRCTRL0_PSRSTN_REQ(0) | + DDRCTRL0_SRSTN_REQ(0) | + DDRPHY0_PSRSTN_REQ(0) | + DDRPHY0_SRSTN_REQ(0); + + p_ddr_reg->physoftrstaddr = DDR_PHY_BASE + DDR_PHY_REG0; + + p_ddr_reg->endtag = 0xFFFFFFFF; +} + +/* + * "rk3368_ddr_reg_resume_V1.05.bin" is an executable bin which is generated + * by ARM DS5 for resuming ddr controller. If the soc wakes up from system + * suspend, ddr needs to be resumed and the resuming code needs to be run in + * sram. But there is not a way to pointing the resuming code to the PMUSRAM + * when linking .o files of bl31, so we use the + * "rk3368_ddr_reg_resume_V1.05.bin" whose code is position-independent and + * it can be loaded anywhere and run. + */ +static __aligned(4) unsigned int ddr_reg_resume[] = { + #include "rk3368_ddr_reg_resume_V1.05.bin" +}; + +uint32_t ddr_get_resume_code_size(void) +{ + return sizeof(ddr_reg_resume); +} + +uint32_t ddr_get_resume_data_size(void) +{ + return sizeof(struct BACKUP_REG_TAG); +} + +uint32_t *ddr_get_resume_code_base(void) +{ + return (unsigned int *)ddr_reg_resume; +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h new file mode 100644 index 0000000..6663bcb --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DDR_RK3368_H +#define DDR_RK3368_H + +#define DDR_PCTL_SCFG 0x0 +#define DDR_PCTL_SCTL 0x4 +#define DDR_PCTL_STAT 0x8 +#define DDR_PCTL_INTRSTAT 0xc + +#define DDR_PCTL_MCMD 0x40 +#define DDR_PCTL_POWCTL 0x44 +#define DDR_PCTL_POWSTAT 0x48 +#define DDR_PCTL_CMDTSTAT 0x4c +#define DDR_PCTL_CMDTSTATEN 0x50 +#define DDR_PCTL_MRRCFG0 0x60 +#define DDR_PCTL_MRRSTAT0 0x64 +#define DDR_PCTL_MRRSTAT1 0x68 +#define DDR_PCTL_MCFG1 0x7c +#define DDR_PCTL_MCFG 0x80 +#define DDR_PCTL_PPCFG 0x84 +#define DDR_PCTL_MSTAT 0x88 +#define DDR_PCTL_LPDDR2ZQCFG 0x8c +#define DDR_PCTL_DTUPDES 0x94 +#define DDR_PCTL_DTUNA 0x98 +#define DDR_PCTL_DTUNE 0x9c +#define DDR_PCTL_DTUPRD0 0xa0 +#define DDR_PCTL_DTUPRD1 0xa4 +#define DDR_PCTL_DTUPRD2 0xa8 +#define DDR_PCTL_DTUPRD3 0xac +#define DDR_PCTL_DTUAWDT 0xb0 +#define DDR_PCTL_TOGCNT1U 0xc0 +#define DDR_PCTL_TINIT 0xc4 +#define DDR_PCTL_TRSTH 0xc8 +#define DDR_PCTL_TOGCNT100N 0xcc +#define DDR_PCTL_TREFI 0xd0 +#define DDR_PCTL_TMRD 0xd4 +#define DDR_PCTL_TRFC 0xd8 +#define DDR_PCTL_TRP 0xdc +#define DDR_PCTL_TRTW 0xe0 +#define DDR_PCTL_TAL 0xe4 +#define DDR_PCTL_TCL 0xe8 +#define DDR_PCTL_TCWL 0xec +#define DDR_PCTL_TRAS 0xf0 +#define DDR_PCTL_TRC 0xf4 +#define DDR_PCTL_TRCD 0xf8 +#define DDR_PCTL_TRRD 0xfc +#define DDR_PCTL_TRTP 0x100 +#define DDR_PCTL_TWR 0x104 +#define DDR_PCTL_TWTR 0x108 +#define DDR_PCTL_TEXSR 0x10c +#define DDR_PCTL_TXP 0x110 +#define DDR_PCTL_TXPDLL 0x114 +#define DDR_PCTL_TZQCS 0x118 +#define DDR_PCTL_TZQCSI 0x11c +#define DDR_PCTL_TDQS 0x120 +#define DDR_PCTL_TCKSRE 0x124 +#define DDR_PCTL_TCKSRX 0x128 +#define DDR_PCTL_TCKE 0x12c +#define DDR_PCTL_TMOD 0x130 +#define DDR_PCTL_TRSTL 0x134 +#define DDR_PCTL_TZQCL 0x138 +#define DDR_PCTL_TMRR 0x13c +#define DDR_PCTL_TCKESR 0x140 +#define DDR_PCTL_TDPD 0x144 +#define DDR_PCTL_TREFI_MEM_DDR3 0x148 +#define DDR_PCTL_ECCCFG 0x180 +#define DDR_PCTL_ECCTST 0x184 +#define DDR_PCTL_ECCCLR 0x188 +#define DDR_PCTL_ECCLOG 0x18c +#define DDR_PCTL_DTUWACTL 0x200 +#define DDR_PCTL_DTURACTL 0x204 +#define DDR_PCTL_DTUCFG 0x208 +#define DDR_PCTL_DTUECTL 0x20c +#define DDR_PCTL_DTUWD0 0x210 +#define DDR_PCTL_DTUWD1 0x214 +#define DDR_PCTL_DTUWD2 0x218 +#define DDR_PCTL_DTUWD3 0x21c +#define DDR_PCTL_DTUWDM 0x220 +#define DDR_PCTL_DTURD0 0x224 +#define DDR_PCTL_DTURD1 0x228 +#define DDR_PCTL_DTURD2 0x22c +#define DDR_PCTL_DTURD3 0x230 +#define DDR_PCTL_DTULFSRWD 0x234 +#define DDR_PCTL_DTULFSRRD 0x238 +#define DDR_PCTL_DTUEAF 0x23c +#define DDR_PCTL_DFITCTRLDELAY 0x240 +#define DDR_PCTL_DFIODTCFG 0x244 +#define DDR_PCTL_DFIODTCFG1 0x248 +#define DDR_PCTL_DFIODTRANKMAP 0x24c +#define DDR_PCTL_DFITPHYWRDATA 0x250 +#define DDR_PCTL_DFITPHYWRLAT 0x254 +#define DDR_PCTL_DFITPHYWRDATALAT 0x258 +#define DDR_PCTL_DFITRDDATAEN 0x260 +#define DDR_PCTL_DFITPHYRDLAT 0x264 +#define DDR_PCTL_DFITPHYUPDTYPE0 0x270 +#define DDR_PCTL_DFITPHYUPDTYPE1 0x274 +#define DDR_PCTL_DFITPHYUPDTYPE2 0x278 +#define DDR_PCTL_DFITPHYUPDTYPE3 0x27c +#define DDR_PCTL_DFITCTRLUPDMIN 0x280 +#define DDR_PCTL_DFITCTRLUPDMAX 0x284 +#define DDR_PCTL_DFITCTRLUPDDLY 0x288 +#define DDR_PCTL_DFIUPDCFG 0x290 +#define DDR_PCTL_DFITREFMSKI 0x294 +#define DDR_PCTL_DFITCTRLUPDI 0x298 +#define DDR_PCTL_DFITRCFG0 0x2ac +#define DDR_PCTL_DFITRSTAT0 0x2b0 +#define DDR_PCTL_DFITRWRLVLEN 0x2b4 +#define DDR_PCTL_DFITRRDLVLEN 0x2b8 +#define DDR_PCTL_DFITRRDLVLGATEEN 0x2bc +#define DDR_PCTL_DFISTSTAT0 0x2c0 +#define DDR_PCTL_DFISTCFG0 0x2c4 +#define DDR_PCTL_DFISTCFG1 0x2c8 +#define DDR_PCTL_DFITDRAMCLKEN 0x2d0 +#define DDR_PCTL_DFITDRAMCLKDIS 0x2d4 +#define DDR_PCTL_DFISTCFG2 0x2d8 +#define DDR_PCTL_DFISTPARCLR 0x2dc +#define DDR_PCTL_DFISTPARLOG 0x2e0 +#define DDR_PCTL_DFILPCFG0 0x2f0 +#define DDR_PCTL_DFITRWRLVLRESP0 0x300 +#define DDR_PCTL_DFITRWRLVLRESP1 0x304 +#define DDR_PCTL_DFITRWRLVLRESP2 0x308 +#define DDR_PCTL_DFITRRDLVLRESP0 0x30c +#define DDR_PCTL_DFITRRDLVLRESP1 0x310 +#define DDR_PCTL_DFITRRDLVLRESP2 0x314 +#define DDR_PCTL_DFITRWRLVLDELAY0 0x318 +#define DDR_PCTL_DFITRWRLVLDELAY1 0x31c +#define DDR_PCTL_DFITRWRLVLDELAY2 0x320 +#define DDR_PCTL_DFITRRDLVLDELAY0 0x324 +#define DDR_PCTL_DFITRRDLVLDELAY1 0x328 +#define DDR_PCTL_DFITRRDLVLDELAY2 0x32c +#define DDR_PCTL_DFITRRDLVLGATEDELAY0 0x330 +#define DDR_PCTL_DFITRRDLVLGATEDELAY1 0x334 +#define DDR_PCTL_DFITRRDLVLGATEDELAY2 0x338 +#define DDR_PCTL_DFITRCMD 0x33c +#define DDR_PCTL_IPVR 0x3f8 +#define DDR_PCTL_IPTR 0x3fc + +/* DDR PHY REG */ +#define DDR_PHY_REG0 0x0 +#define DDR_PHY_REG1 0x4 +#define DDR_PHY_REG2 0x8 +#define DDR_PHY_REG3 0xc +#define DDR_PHY_REG4 0x10 +#define DDR_PHY_REG5 0x14 +#define DDR_PHY_REG6 0x18 +#define DDR_PHY_REGB 0x2c +#define DDR_PHY_REGC 0x30 +#define DDR_PHY_REG11 0x44 +#define DDR_PHY_REG12 0x48 +#define DDR_PHY_REG13 0x4c +#define DDR_PHY_REG14 0x50 +#define DDR_PHY_REG16 0x58 +#define DDR_PHY_REG20 0x80 +#define DDR_PHY_REG21 0x84 +#define DDR_PHY_REG26 0x98 +#define DDR_PHY_REG27 0x9c +#define DDR_PHY_REG28 0xa0 +#define DDR_PHY_REG2C 0xb0 +#define DDR_PHY_REG30 0xc0 +#define DDR_PHY_REG31 0xc4 +#define DDR_PHY_REG36 0xd8 +#define DDR_PHY_REG37 0xdc +#define DDR_PHY_REG38 0xe0 +#define DDR_PHY_REG3C 0xf0 +#define DDR_PHY_REG40 0x100 +#define DDR_PHY_REG41 0x104 +#define DDR_PHY_REG46 0x118 +#define DDR_PHY_REG47 0x11c +#define DDR_PHY_REG48 0x120 +#define DDR_PHY_REG4C 0x130 +#define DDR_PHY_REG50 0x140 +#define DDR_PHY_REG51 0x144 +#define DDR_PHY_REG56 0x158 +#define DDR_PHY_REG57 0x15c +#define DDR_PHY_REG58 0x160 +#define DDR_PHY_REG5C 0x170 +#define DDR_PHY_REGDLL 0x290 +#define DDR_PHY_REGEC 0x3b0 +#define DDR_PHY_REGED 0x3b4 +#define DDR_PHY_REGEE 0x3b8 +#define DDR_PHY_REGEF 0x3bc +#define DDR_PHY_REGF0 0x3c0 +#define DDR_PHY_REGF1 0x3c4 +#define DDR_PHY_REGF2 0x3c8 +#define DDR_PHY_REGFA 0x3e8 +#define DDR_PHY_REGFB 0x3ec +#define DDR_PHY_REGFC 0x3f0 +#define DDR_PHY_REGFD 0x3f4 +#define DDR_PHY_REGFE 0x3f8 +#define DDR_PHY_REGFF 0x3fc + +/* MSCH REG define */ +#define MSCH_COREID 0x0 +#define MSCH_DDRCONF 0x8 +#define MSCH_DDRTIMING 0xc +#define MSCH_DDRMODE 0x10 +#define MSCH_READLATENCY 0x14 +#define MSCH_ACTIVATE 0x38 +#define MSCH_DEVTODEV 0x3c + +#define SET_NR(n) ((0x3f << (8 + 16)) | ((n - 1) << 8)) +#define SET_NO(n) ((0xf << (0 + 16)) | ((n - 1) << 0)) +#define SET_NF(n) ((n - 1) & 0x1fff) +#define SET_NB(n) ((n - 1) & 0xfff) +#define PLLMODE(n) ((0x3 << (8 + 16)) | (n << 8)) + +/* GRF REG define */ +#define GRF_SOC_STATUS0 0x480 +#define GRF_DDRPHY_LOCK (0x1 << 15) +#define GRF_DDRC0_CON0 0x600 + +/* CRU softreset ddr pctl, phy */ +#define DDRMSCH0_SRSTN_REQ(n) (((0x1 << 10) << 16) | (n << 10)) +#define DDRCTRL0_PSRSTN_REQ(n) (((0x1 << 3) << 16) | (n << 3)) +#define DDRCTRL0_SRSTN_REQ(n) (((0x1 << 2) << 16) | (n << 2)) +#define DDRPHY0_PSRSTN_REQ(n) (((0x1 << 1) << 16) | (n << 1)) +#define DDRPHY0_SRSTN_REQ(n) (((0x1 << 0) << 16) | (n << 0)) + +/* CRU_DPLL_CON2 */ +#define DPLL_STATUS_LOCK (1U << 31) + +/* CRU_DPLL_CON3 */ +#define DPLL_POWER_DOWN ((0x1 << (1 + 16)) | (0 << 1)) +#define DPLL_WORK_NORMAL_MODE ((0x3 << (8 + 16)) | (0 << 8)) +#define DPLL_WORK_SLOW_MODE ((0x3 << (8 + 16)) | (1 << 8)) +#define DPLL_RESET_CONTROL_NORMAL ((0x1 << (5 + 16)) | (0x0 << 5)) +#define DPLL_RESET_CONTROL_RESET ((0x1 << (5 + 16)) | (0x1 << 5)) + +/* PMU_PWRDN_CON */ +#define PD_PERI_PWRDN_ENABLE (1 << 13) + +#define DDR_PLL_SRC_MASK 0x13 + +/* DDR_PCTL_TREFI */ +#define DDR_UPD_REF_ENABLE (0X1u << 31) + +uint32_t ddr_get_resume_code_size(void); +uint32_t ddr_get_resume_data_size(void); +uint32_t *ddr_get_resume_code_base(void); +void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr); + +#endif /* DDR_RK3368_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin new file mode 100644 index 0000000..cecd694 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin @@ -0,0 +1,461 @@ + 0x14000088, + 0xd10043ff, + 0x5283ffe1, + 0x52824902, + 0x1b020400, + 0x530d7c00, + 0xb9000fe0, + 0xb9400fe0, + 0x340000a0, + 0xb9400fe0, + 0x51000401, + 0xb9000fe1, + 0x35ffffa0, + 0x910043ff, + 0xd65f03c0, + 0x340000e2, + 0xb9400023, + 0xb9000003, + 0x91001021, + 0x91001000, + 0x51000442, + 0x35ffff62, + 0xd65f03c0, + 0xd10043ff, + 0xb9400801, + 0x12000821, + 0xb9000fe1, + 0xb9400fe1, + 0x7100043f, + 0x54000320, + 0x52800021, + 0x52800082, + 0xb9400fe3, + 0x34000143, + 0x71000c7f, + 0x54000100, + 0x7100147f, + 0x54000161, + 0xb9000402, + 0xb9400803, + 0x12000863, + 0x71000c7f, + 0x54ffffa1, + 0xb9000401, + 0xb9400803, + 0x12000863, + 0x7100047f, + 0x54ffffa1, + 0xb9400803, + 0x12000863, + 0xb9000fe3, + 0xb9400fe3, + 0x7100047f, + 0x54fffd61, + 0x910043ff, + 0xd65f03c0, + 0xd10043ff, + 0xb9400801, + 0x12000821, + 0xb9000fe1, + 0xb9400fe1, + 0x7100143f, + 0x54000400, + 0x52800021, + 0x52800042, + 0x52800063, + 0xb9400fe4, + 0x340000c4, + 0x7100049f, + 0x54000120, + 0x71000c9f, + 0x54000180, + 0x14000010, + 0xb9000401, + 0xb9400804, + 0x12000884, + 0x7100049f, + 0x54ffffa1, + 0xb9000402, + 0xb9400804, + 0x12000884, + 0x71000c9f, + 0x54ffffa1, + 0xb9000403, + 0xb9400804, + 0x12000884, + 0x7100149f, + 0x54ffffa1, + 0xb9400804, + 0x12000884, + 0xb9000fe4, + 0xb9400fe4, + 0x7100149f, + 0x54fffca1, + 0x910043ff, + 0xd65f03c0, + 0xd10043ff, + 0xb9400801, + 0x12000821, + 0xb9000fe1, + 0xb9400fe1, + 0x71000c3f, + 0x54000400, + 0x52800021, + 0x52800042, + 0x52800083, + 0xb9400fe4, + 0x34000164, + 0x7100049f, + 0x540001c0, + 0x7100149f, + 0x54000221, + 0xb9000403, + 0xb9400804, + 0x12000884, + 0x71000c9f, + 0x54ffffa1, + 0x1400000b, + 0xb9000401, + 0xb9400804, + 0x12000884, + 0x7100049f, + 0x54ffffa1, + 0xb9000402, + 0xb9400804, + 0x12000884, + 0x71000c9f, + 0x54ffffa1, + 0xb9400804, + 0x12000884, + 0xb9000fe4, + 0xb9400fe4, + 0x71000c9f, + 0x54fffca1, + 0x910043ff, + 0xd65f03c0, + 0xd10103ff, + 0xa9037bfd, + 0x9100c3fd, + 0xa9025ff6, + 0xa90157f4, + 0xf90007f3, + 0xaa0003f3, + 0xb9400674, + 0xb9411276, + 0xb941c660, + 0xb941aa75, + 0x7100041f, + 0x54000261, + 0xb9418e60, + 0x321f0000, + 0xb903b6c0, + 0xb9418a60, + 0xb903b2c0, + 0xb9419260, + 0xb903bac0, + 0xb9418e60, + 0x121e7800, + 0xb903b6c0, + 0xb941ca60, + 0xb941ce61, + 0xb941d262, + 0xb9400003, + 0xa030023, + 0x6b22407f, + 0x54ffffa0, + 0x1400003b, + 0xb941d660, + 0x7100041f, + 0x54000701, + 0xb941da60, + 0x3100041f, + 0x54000080, + 0xb941de61, + 0x53007c00, + 0xb9000001, + 0xb941e660, + 0x3100041f, + 0x54000080, + 0xb941ea61, + 0x53007c00, + 0xb9000001, + 0xb941f260, + 0x3100041f, + 0x54000120, + 0xaa1f03e1, + 0x53007c00, + 0x9107d262, + 0xb8616843, + 0xb8216803, + 0x91001021, + 0xf100203f, + 0x54ffff81, + 0x52800020, + 0x97ffff3f, + 0xb941e660, + 0x3100041f, + 0x54000080, + 0xb941ee61, + 0x53007c00, + 0xb9000001, + 0x52800020, + 0x97ffff37, + 0xb9420660, + 0x3100041f, + 0x54000100, + 0xb9420a61, + 0xb9420e62, + 0x53007c00, + 0xb9400003, + 0xa030023, + 0x6b22407f, + 0x54ffffa1, + 0xb9421260, + 0x3100041f, + 0x54000080, + 0xb9421661, + 0x53007c00, + 0xb9000001, + 0xb941da60, + 0x3100041f, + 0x54000080, + 0xb941e261, + 0x53007c00, + 0xb9000001, + 0xb9419660, + 0xb903bec0, + 0xb9422a60, + 0x34000400, + 0xb9422e61, + 0x53007c17, + 0xb90002e1, + 0x52800140, + 0x97ffff18, + 0xb9423260, + 0xb90002e0, + 0x52800140, + 0x97ffff14, + 0xb9423660, + 0xb90002e0, + 0x52800140, + 0x97ffff10, + 0xb9423a60, + 0x34000220, + 0x53007c17, + 0xb94002e0, + 0x121c7400, + 0xb90002e0, + 0x52800020, + 0x97ffff08, + 0xb94002e0, + 0x321e0000, + 0xb90002e0, + 0x528000a0, + 0x97ffff03, + 0xb94002e0, + 0x321d0000, + 0xb90002e0, + 0x52800020, + 0x97fffefe, + 0xb9412a60, + 0xb9004ec0, + 0xb9412e60, + 0xb90052c0, + 0xb9413e60, + 0xb9009ac0, + 0xb9414260, + 0xb9009ec0, + 0xb9415260, + 0xb900dac0, + 0xb9415660, + 0xb900dec0, + 0xb9416660, + 0xb9011ac0, + 0xb9416a60, + 0xb9011ec0, + 0xb9417a60, + 0xb9015ac0, + 0xb9417e60, + 0xb9015ec0, + 0xb9418660, + 0xb90292c0, + 0xb9414660, + 0xb900a2c0, + 0xb9415a60, + 0xb900e2c0, + 0xb9416e60, + 0xb90122c0, + 0xb9418260, + 0xb90162c0, + 0xb9411660, + 0xb90002c0, + 0xb9411a60, + 0xb90006c0, + 0xb9411e60, + 0xb9002ec0, + 0xb9412260, + 0xb90032c0, + 0xb9412660, + 0xb90046c0, + 0xb9413260, + 0xb9005ac0, + 0xb9413660, + 0xb90082c0, + 0xb9413a60, + 0xb90086c0, + 0xb9414a60, + 0xb900c2c0, + 0xb9414e60, + 0xb900c6c0, + 0xb9415e60, + 0xb90102c0, + 0xb9416260, + 0xb90106c0, + 0xb9417260, + 0xb90142c0, + 0xb9417660, + 0xb90146c0, + 0x52800040, + 0xb9000ac0, + 0xb9411261, + 0xb9419a60, + 0xb900b020, + 0xb9419a60, + 0xb900b420, + 0xb9419e60, + 0xb900f020, + 0xb9419e60, + 0xb900f420, + 0xb941a260, + 0xb9013020, + 0xb941a260, + 0xb9013420, + 0xb941a660, + 0xb9017020, + 0xb941a662, + 0xaa1f03e0, + 0xb9017422, + 0x91008261, + 0xb8606822, + 0x8b000283, + 0xb900c062, + 0x91001000, + 0xf102301f, + 0x54ffff61, + 0xb9400a60, + 0xb9000280, + 0xb9400e60, + 0xb9005280, + 0xb9401260, + 0xb9007e80, + 0xb9401660, + 0xb9008280, + 0xb9401a60, + 0xb9008680, + 0xb940ae60, + 0xb9024280, + 0xb940b260, + 0xb9024680, + 0xb940b660, + 0xb9024a80, + 0xb940ba60, + 0xb9024e80, + 0xb940be60, + 0xb9025280, + 0xb940c260, + 0xb9025680, + 0xb940c660, + 0xb9025a80, + 0xb940ca60, + 0xb9026280, + 0xb940ce60, + 0xb9026680, + 0xb940d260, + 0xb9027280, + 0xb940d660, + 0xb9027680, + 0xb940da60, + 0xb9027a80, + 0xb940de60, + 0xb9027e80, + 0xb940e260, + 0xb9028280, + 0xb940e660, + 0xb9028680, + 0xb940ea60, + 0xb9028a80, + 0xb940ee60, + 0xb9029280, + 0xb940f260, + 0xb9029680, + 0xb940f660, + 0xb9029a80, + 0xb940fa60, + 0xb902c680, + 0xb940fe60, + 0xb902ca80, + 0xb9410260, + 0xb902d280, + 0xb9410660, + 0xb902d680, + 0xb9410a60, + 0xb902da80, + 0xb9410e60, + 0xb902f280, + 0xb9422260, + 0x3100041f, + 0x540000c0, + 0xb9422661, + 0x53007c00, + 0xb9000001, + 0x52800020, + 0x97fffe65, + 0x52800020, + 0xb9004680, + 0xb9404a80, + 0x3607ffe0, + 0xb941ae60, + 0xb9000aa0, + 0xb941b260, + 0xb9000ea0, + 0xb941b660, + 0xb90012a0, + 0xb941ba60, + 0xb90016a0, + 0xb941be60, + 0xb9003aa0, + 0xb941c260, + 0xb9003ea0, + 0xb9422260, + 0x3100041f, + 0x54000080, + 0x53007c00, + 0x320083e1, + 0xb9000001, + 0xaa1403e0, + 0x97fffe84, + 0xb9421a60, + 0x3100041f, + 0x54000100, + 0x53007c00, + 0xb9421e61, + 0xb9400002, + 0x2a010041, + 0xb9000001, + 0x52800020, + 0x97fffe43, + 0xaa1403e0, + 0x97fffea0, + 0xb9422260, + 0x3100041f, + 0x54000080, + 0x53007c00, + 0x52a00021, + 0xb9000001, + 0xf94007f3, + 0xa94157f4, + 0xa9425ff6, + 0xa9437bfd, + 0x910103ff, + 0xd65f03c0, diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..399f61c --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +.macro func_rockchip_clst_warmboot + /* Nothing to do for rk3368 */ +.endm + +.macro rockchip_clst_warmboot_data + /* Nothing to do for rk3368 */ +.endm diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c new file mode 100644 index 0000000..e277a18 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2016, 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 + +DEFINE_BAKERY_LOCK(rockchip_pd_lock); + +static uint32_t cpu_warm_boot_addr; + +void rk3368_flash_l2_b(void) +{ + uint32_t wait_cnt = 0; + + regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b); + dsb(); + + while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) + & BIT(clst_b_l2_flsh_done))) { + wait_cnt++; + if (!(wait_cnt % MAX_WAIT_CONUT)) + WARN("%s:reg %x,wait\n", __func__, + mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); + } + + regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b); +} + +static inline int rk3368_pmu_bus_idle(uint32_t req, uint32_t idle) +{ + uint32_t mask = BIT(req); + uint32_t idle_mask = 0; + uint32_t idle_target = 0; + uint32_t val; + uint32_t wait_cnt = 0; + + switch (req) { + case bus_ide_req_clst_l: + idle_mask = BIT(pmu_idle_ack_cluster_l); + idle_target = (idle << pmu_idle_ack_cluster_l); + break; + + case bus_ide_req_clst_b: + idle_mask = BIT(pmu_idle_ack_cluster_b); + idle_target = (idle << pmu_idle_ack_cluster_b); + break; + + case bus_ide_req_cxcs: + idle_mask = BIT(pmu_idle_ack_cxcs); + idle_target = ((!idle) << pmu_idle_ack_cxcs); + break; + + case bus_ide_req_cci400: + idle_mask = BIT(pmu_idle_ack_cci400); + idle_target = ((!idle) << pmu_idle_ack_cci400); + break; + + case bus_ide_req_gpu: + idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu); + idle_target = (idle << pmu_idle_ack_gpu) | + (idle << pmu_idle_gpu); + break; + + case bus_ide_req_core: + idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core); + idle_target = (idle << pmu_idle_ack_core) | + (idle << pmu_idle_core); + break; + + case bus_ide_req_bus: + idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus); + idle_target = (idle << pmu_idle_ack_bus) | + (idle << pmu_idle_bus); + break; + case bus_ide_req_dma: + idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma); + idle_target = (idle << pmu_idle_ack_dma) | + (idle << pmu_idle_dma); + break; + + case bus_ide_req_peri: + idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri); + idle_target = (idle << pmu_idle_ack_peri) | + (idle << pmu_idle_peri); + break; + + case bus_ide_req_video: + idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video); + idle_target = (idle << pmu_idle_ack_video) | + (idle << pmu_idle_video); + break; + + case bus_ide_req_vio: + idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio); + idle_target = (pmu_idle_ack_vio) | + (idle << pmu_idle_vio); + break; + + case bus_ide_req_alive: + idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive); + idle_target = (idle << pmu_idle_ack_alive) | + (idle << pmu_idle_alive); + break; + + case bus_ide_req_pmu: + idle_mask = BIT(pmu_idle_ack_pmu) | BIT(pmu_idle_pmu); + idle_target = (idle << pmu_idle_ack_pmu) | + (idle << pmu_idle_pmu); + break; + + case bus_ide_req_msch: + idle_mask = BIT(pmu_idle_ack_msch) | BIT(pmu_idle_msch); + idle_target = (idle << pmu_idle_ack_msch) | + (idle << pmu_idle_msch); + break; + + case bus_ide_req_cci: + idle_mask = BIT(pmu_idle_ack_cci) | BIT(pmu_idle_cci); + idle_target = (idle << pmu_idle_ack_cci) | + (idle << pmu_idle_cci); + break; + + default: + ERROR("%s: Unsupported the idle request\n", __func__); + break; + } + + val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ); + if (idle) + val |= mask; + else + val &= ~mask; + + mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val); + + while ((mmio_read_32(PMU_BASE + + PMU_BUS_IDE_ST) & idle_mask) != idle_target) { + wait_cnt++; + if (!(wait_cnt % MAX_WAIT_CONUT)) + WARN("%s:st=%x(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST), + idle_mask); + } + + return 0; +} + +void pmu_scu_b_pwrup(void) +{ + regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b); + rk3368_pmu_bus_idle(bus_ide_req_clst_b, 0); +} + +static void pmu_scu_b_pwrdn(void) +{ + uint32_t wait_cnt = 0; + + if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & + PM_PWRDM_CPUSB_MSK) != PM_PWRDM_CPUSB_MSK) { + ERROR("%s: not all cpus is off\n", __func__); + return; + } + + rk3368_flash_l2_b(); + + regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b); + + while (!(mmio_read_32(PMU_BASE + + PMU_CORE_PWR_ST) & BIT(clst_b_l2_wfi))) { + wait_cnt++; + if (!(wait_cnt % MAX_WAIT_CONUT)) + ERROR("%s:wait cluster-b l2(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); + } + rk3368_pmu_bus_idle(bus_ide_req_clst_b, 1); +} + +static void pmu_sleep_mode_config(void) +{ + uint32_t pwrmd_core, pwrmd_com; + + pwrmd_core = BIT(pmu_mdcr_cpu0_pd) | + BIT(pmu_mdcr_scu_l_pd) | + BIT(pmu_mdcr_l2_flush) | + BIT(pmu_mdcr_l2_idle) | + BIT(pmu_mdcr_clr_clst_l) | + BIT(pmu_mdcr_clr_core) | + BIT(pmu_mdcr_clr_cci) | + BIT(pmu_mdcr_core_pd); + + pwrmd_com = BIT(pmu_mode_en) | + BIT(pmu_mode_sref_enter) | + BIT(pmu_mode_pwr_off); + + regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_l_wkup_en); + regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_b_wkup_en); + regs_updata_bit_clr(PMU_BASE + PMU_WKUP_CFG2, pmu_gpio_wkup_en); + + mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT, CYCL_24M_CNT_MS(2)); + mmio_write_32(PMU_BASE + PMU_PLLRST_CNT, CYCL_24M_CNT_US(100)); + mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_24M_CNT_MS(2)); + mmio_write_32(PMU_BASE + PMU_PWRMD_CORE, pwrmd_core); + mmio_write_32(PMU_BASE + PMU_PWRMD_COM, pwrmd_com); + dsb(); +} + +static void pmu_set_sleep_mode(void) +{ + pmu_sleep_mode_config(); + soc_sleep_config(); + regs_updata_bit_set(PMU_BASE + PMU_PWRMD_CORE, pmu_mdcr_global_int_dis); + regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_glbl_int_dis_b); + pmu_scu_b_pwrdn(); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + ((uintptr_t)&pmu_cpuson_entrypoint >> + CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), + ((uintptr_t)&pmu_cpuson_entrypoint >> + CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); +} + +static int cpus_id_power_domain(uint32_t cluster, + uint32_t cpu, + uint32_t pd_state, + uint32_t wfie_msk) +{ + uint32_t pd; + uint64_t mpidr; + + if (cluster) + pd = PD_CPUB0 + cpu; + else + pd = PD_CPUL0 + cpu; + + if (pmu_power_domain_st(pd) == pd_state) + return 0; + + if (pd_state == pmu_pd_off) { + mpidr = (cluster << MPIDR_AFF1_SHIFT) | cpu; + if (check_cpu_wfie(mpidr, wfie_msk)) + return -EINVAL; + } + + return pmu_power_domain_ctr(pd, pd_state); +} + +static void nonboot_cpus_off(void) +{ + uint32_t boot_cpu, boot_cluster, cpu; + + boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1()); + boot_cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1()); + + /* turn off noboot cpus */ + for (cpu = 0; cpu < PLATFORM_CLUSTER0_CORE_COUNT; cpu++) { + if (!boot_cluster && (cpu == boot_cpu)) + continue; + cpus_id_power_domain(0, cpu, pmu_pd_off, CKECK_WFEI_MSK); + } + + for (cpu = 0; cpu < PLATFORM_CLUSTER1_CORE_COUNT; cpu++) { + if (boot_cluster && (cpu == boot_cpu)) + continue; + cpus_id_power_domain(1, cpu, pmu_pd_off, CKECK_WFEI_MSK); + } +} + +void sram_save(void) +{ + /* TODO: support the sdram save for rk3368 SoCs*/ +} + +void sram_restore(void) +{ + /* TODO: support the sdram restore for rk3368 SoCs */ +} + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) +{ + uint32_t cpu, cluster; + uint32_t cpuon_id; + + cpu = MPIDR_AFFLVL0_VAL(mpidr); + cluster = MPIDR_AFFLVL1_VAL(mpidr); + + /* Make sure the cpu is off,Before power up the cpu! */ + cpus_id_power_domain(cluster, cpu, pmu_pd_off, CKECK_WFEI_MSK); + + cpuon_id = (cluster * PLATFORM_CLUSTER0_CORE_COUNT) + cpu; + assert(cpuon_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpuon_id] == 0); + cpuson_flags[cpuon_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpuon_id] = entrypoint; + + /* Switch boot addr to pmusram */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster), + (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + dsb(); + + cpus_id_power_domain(cluster, cpu, pmu_pd_on, CKECK_WFEI_MSK); + + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster), + (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), + (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + pm_plls_resume(); + pmu_scu_b_pwrup(); + + return 0; +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + nonboot_cpus_off(); + pmu_set_sleep_mode(); + + return 0; +} + +void rockchip_plat_mmu_el3(void) +{ + /* TODO: support the el3 for rk3368 SoCs */ +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + /* register requires 32bits mode, switch it to 32 bits */ + cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; + + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = 0; + + nonboot_cpus_off(); + INFO("%s(%d): pd status %x\n", __func__, __LINE__, + mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h new file mode 100644 index 0000000..b4d4807 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_H +#define PMU_H + +/* Allocate sp reginon in pmusram */ +#define PSRAM_SP_SIZE 0x80 +#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE) + +/***************************************************************************** + * pmu con,reg + *****************************************************************************/ +#define PMU_WKUP_CFG0 0x0 +#define PMU_WKUP_CFG1 0x4 +#define PMU_WKUP_CFG2 0x8 +#define PMU_TIMEOUT_CNT 0x7c +#define PMU_PWRDN_CON 0xc +#define PMU_PWRDN_ST 0x10 +#define PMU_CORE_PWR_ST 0x38 + +#define PMU_PWRMD_CORE 0x14 +#define PMU_PWRMD_COM 0x18 +#define PMU_SFT_CON 0x1c +#define PMU_BUS_IDE_REQ 0x3c +#define PMU_BUS_IDE_ST 0x40 +#define PMU_OSC_CNT 0x48 +#define PMU_PLLLOCK_CNT 0x4c +#define PMU_PLLRST_CNT 0x50 +#define PMU_STABLE_CNT 0x54 +#define PMU_DDRIO_PWR_CNT 0x58 +#define PMU_WKUPRST_CNT 0x5c + +enum pmu_powermode_core { + pmu_mdcr_global_int_dis = 0, + pmu_mdcr_core_src_gt, + pmu_mdcr_clr_cci, + pmu_mdcr_cpu0_pd, + pmu_mdcr_clr_clst_l = 4, + pmu_mdcr_clr_core, + pmu_mdcr_scu_l_pd, + pmu_mdcr_core_pd, + pmu_mdcr_l2_idle = 8, + pmu_mdcr_l2_flush +}; + +/* + * the shift of bits for cores status + */ +enum pmu_core_pwrst_shift { + clstl_cpu_wfe = 2, + clstl_cpu_wfi = 6, + clstb_cpu_wfe = 12, + clstb_cpu_wfi = 16 +}; + +enum pmu_pdid { + PD_CPUL0 = 0, + PD_CPUL1, + PD_CPUL2, + PD_CPUL3, + PD_SCUL, + PD_CPUB0 = 5, + PD_CPUB1, + PD_CPUB2, + PD_CPUB3, + PD_SCUB = 9, + PD_PERI = 13, + PD_VIDEO, + PD_VIO, + PD_GPU0, + PD_GPU1, + PD_END +}; + +enum pmu_bus_ide { + bus_ide_req_clst_l = 0, + bus_ide_req_clst_b, + bus_ide_req_gpu, + bus_ide_req_core, + bus_ide_req_bus = 4, + bus_ide_req_dma, + bus_ide_req_peri, + bus_ide_req_video, + bus_ide_req_vio = 8, + bus_ide_req_res0, + bus_ide_req_cxcs, + bus_ide_req_alive, + bus_ide_req_pmu = 12, + bus_ide_req_msch, + bus_ide_req_cci, + bus_ide_req_cci400 = 15, + bus_ide_req_end +}; + +enum pmu_powermode_common { + pmu_mode_en = 0, + pmu_mode_res0, + pmu_mode_bus_pd, + pmu_mode_wkup_rst, + pmu_mode_pll_pd = 4, + pmu_mode_pwr_off, + pmu_mode_pmu_use_if, + pmu_mode_pmu_alive_use_if, + pmu_mode_osc_dis = 8, + pmu_mode_input_clamp, + pmu_mode_sref_enter, + pmu_mode_ddrc_gt, + pmu_mode_ddrio_ret = 12, + pmu_mode_ddrio_ret_deq, + pmu_mode_clr_pmu, + pmu_mode_clr_alive, + pmu_mode_clr_bus = 16, + pmu_mode_clr_dma, + pmu_mode_clr_msch, + pmu_mode_clr_peri, + pmu_mode_clr_video = 20, + pmu_mode_clr_vio, + pmu_mode_clr_gpu, + pmu_mode_clr_mcu, + pmu_mode_clr_cxcs = 24, + pmu_mode_clr_cci400, + pmu_mode_res1, + pmu_mode_res2, + pmu_mode_res3 = 28, + pmu_mode_mclst +}; + +enum pmu_core_power_st { + clst_l_cpu_wfe = 2, + clst_l_cpu_wfi = 6, + clst_b_l2_flsh_done = 10, + clst_b_l2_wfi = 11, + clst_b_cpu_wfe = 12, + clst_b_cpu_wfi = 16, + mcu_sleeping = 20, +}; + +enum pmu_sft_con { + pmu_sft_acinactm_clst_b = 5, + pmu_sft_l2flsh_clst_b, + pmu_sft_glbl_int_dis_b = 9, + pmu_sft_ddrio_ret_cfg = 11, +}; + +enum pmu_wkup_cfg2 { + pmu_cluster_l_wkup_en = 0, + pmu_cluster_b_wkup_en, + pmu_gpio_wkup_en, + pmu_sdio_wkup_en, + pmu_sdmmc_wkup_en, + pmu_sim_wkup_en, + pmu_timer_wkup_en, + pmu_usbdev_wkup_en, + pmu_sft_wkup_en, + pmu_wdt_mcu_wkup_en, + pmu_timeout_wkup_en, +}; + +enum pmu_bus_idle_st { + pmu_idle_ack_cluster_l = 0, + pmu_idle_ack_cluster_b, + pmu_idle_ack_gpu, + pmu_idle_ack_core, + pmu_idle_ack_bus, + pmu_idle_ack_dma, + pmu_idle_ack_peri, + pmu_idle_ack_video, + pmu_idle_ack_vio, + pmu_idle_ack_cci = 10, + pmu_idle_ack_msch, + pmu_idle_ack_alive, + pmu_idle_ack_pmu, + pmu_idle_ack_cxcs, + pmu_idle_ack_cci400, + pmu_inactive_cluster_l, + pmu_inactive_cluster_b, + pmu_idle_gpu, + pmu_idle_core, + pmu_idle_bus, + pmu_idle_dma, + pmu_idle_peri, + pmu_idle_video, + pmu_idle_vio, + pmu_idle_cci = 26, + pmu_idle_msch, + pmu_idle_alive, + pmu_idle_pmu, + pmu_active_cxcs, + pmu_active_cci, +}; + +#define PM_PWRDM_CPUSB_MSK (0xf << 5) + +#define CKECK_WFE_MSK 0x1 +#define CKECK_WFI_MSK 0x10 +#define CKECK_WFEI_MSK 0x11 + +#define PD_CTR_LOOP 500 +#define CHK_CPU_LOOP 500 + +#define MAX_WAIT_CONUT 1000 + +#endif /* PMU_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c new file mode 100644 index 0000000..7d51bb8 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + +static uint32_t plls_con[END_PLL_ID][4]; + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(CCI400_BASE, CCI400_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(STIME_BASE, STIME_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMU_BASE, PMU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART0_BASE, UART0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART1_BASE, UART1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART2_BASE, UART2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART3_BASE, UART3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART4_BASE, UART4_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CRU_BASE, CRU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PCTL_BASE, DDR_PCTL_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PHY_BASE, DDR_PHY_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GRF_BASE, GRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SISE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/* The RockChip power domain tree descriptor */ +const unsigned char rockchip_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, + /* No of children for the second cluster node */ + PLATFORM_CLUSTER1_CORE_COUNT +}; + +void secure_timer_init(void) +{ + mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT0, 0xffffffff); + mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN); +} + +void sgrf_init(void) +{ + /* setting all configurable ip into no-secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), SGRF_SOC_CON7_BITS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), SGRF_SOC_CON_NS); + + /* secure dma to no sesure */ + mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(0), SGRF_BUSDMAC_CON0_NS); + mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), SGRF_BUSDMAC_CON1_NS); + dsb(); + + /* rst dma1 */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), + RST_DMA1_MSK | (RST_DMA1_MSK << 16)); + /* rst dma2 */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), + RST_DMA2_MSK | (RST_DMA2_MSK << 16)); + + dsb(); + + /* release dma1 rst*/ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16)); + /* release dma2 rst*/ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16)); +} + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + sgrf_init(); +} + +void regs_updata_bits(uintptr_t addr, uint32_t val, + uint32_t mask, uint32_t shift) +{ + uint32_t tmp, orig; + + orig = mmio_read_32(addr); + + tmp = orig & ~(mask << shift); + tmp |= (val & mask) << shift; + + if (tmp != orig) + mmio_write_32(addr, tmp); + dsb(); +} + +static void plls_suspend(uint32_t pll_id) +{ + plls_con[pll_id][0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0)); + plls_con[pll_id][1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1)); + plls_con[pll_id][2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2)); + plls_con[pll_id][3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3)); + + mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_BYPASS); +} + +static void pm_plls_suspend(void) +{ + plls_suspend(NPLL_ID); + plls_suspend(CPLL_ID); + plls_suspend(GPLL_ID); + plls_suspend(ABPLL_ID); + plls_suspend(ALPLL_ID); +} + +static inline void plls_resume(void) +{ + mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3), + plls_con[ABPLL_ID][3] | PLL_BYPASS_W_MSK); + mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3), + plls_con[ALPLL_ID][3] | PLL_BYPASS_W_MSK); + mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3), + plls_con[GPLL_ID][3] | PLL_BYPASS_W_MSK); + mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3), + plls_con[CPLL_ID][3] | PLL_BYPASS_W_MSK); + mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3), + plls_con[NPLL_ID][3] | PLL_BYPASS_W_MSK); +} + +void soc_sleep_config(void) +{ + int i = 0; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000); + pm_plls_suspend(); + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000); +} + +void pm_plls_resume(void) +{ + plls_resume(); + + mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3), + plls_con[ABPLL_ID][3] | PLLS_MODE_WMASK); + mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3), + plls_con[ALPLL_ID][3] | PLLS_MODE_WMASK); + mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3), + plls_con[GPLL_ID][3] | PLLS_MODE_WMASK); + mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3), + plls_con[CPLL_ID][3] | PLLS_MODE_WMASK); + mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3), + plls_con[NPLL_ID][3] | PLLS_MODE_WMASK); +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + uint32_t temp_val; + + mmio_write_32(CRU_BASE + PLL_CONS((GPLL_ID), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((CPLL_ID), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((NPLL_ID), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((ABPLL_ID), 3), PLL_SLOW_BITS); + mmio_write_32(CRU_BASE + PLL_CONS((ALPLL_ID), 3), PLL_SLOW_BITS); + + temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON) | + PMU_RST_BY_SECOND_SFT; + + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val); + mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to excute valid codes. + */ + while (1) + ; +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h new file mode 100644 index 0000000..6c7a01b --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +enum plls_id { + ABPLL_ID = 0, + ALPLL_ID, + DPLL_ID, + CPLL_ID, + GPLL_ID, + NPLL_ID, + END_PLL_ID, +}; + +/***************************************************************************** + * secure timer + *****************************************************************************/ +#define TIMER_LOADE_COUNT0 0x00 +#define TIMER_LOADE_COUNT1 0x04 +#define TIMER_CURRENT_VALUE0 0x08 +#define TIMER_CURRENT_VALUE1 0x0C +#define TIMER_CONTROL_REG 0x10 +#define TIMER_INTSTATUS 0x18 + +#define TIMER_EN 0x1 + +#define STIMER1_BASE (STIME_BASE + 0x20) + +#define CYCL_24M_CNT_US(us) (24 * us) +#define CYCL_24M_CNT_MS(ms) (ms * CYCL_24M_CNT_US(1000)) + +/***************************************************************************** + * sgrf reg, offset + *****************************************************************************/ +#define SGRF_SOC_CON(n) (0x0 + (n) * 4) +#define SGRF_BUSDMAC_CON(n) (0x100 + (n) * 4) + +#define SGRF_SOC_CON_NS 0xffff0000 + +/***************************************************************************** + * con6[2]pmusram is security. + * con6[6]stimer is security. + *****************************************************************************/ +#define PMUSRAM_S_SHIFT 2 +#define PMUSRAM_S 1 +#define STIMER_S_SHIFT 6 +#define STIMER_S 1 +#define SGRF_SOC_CON7_BITS ((0xffffu << 16) | \ + (PMUSRAM_S << PMUSRAM_S_SHIFT) | \ + (STIMER_S << STIMER_S_SHIFT)) + +#define SGRF_BUSDMAC_CON0_NS 0xfffcfff8 +#define SGRF_BUSDMAC_CON1_NS 0xffff0fff + +/* + * sgrf_soc_con1~2, mask and offset + */ +#define CPU_BOOT_ADDR_WMASK 0xffff0000 +#define CPU_BOOT_ADDR_ALIGN 16 + +/***************************************************************************** + * cru reg, offset + *****************************************************************************/ +#define CRU_SOFTRST_CON 0x300 +#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4)) +#define CRU_SOFTRSTS_CON_CNT 15 + +#define SOFTRST_DMA1 0x40004 +#define SOFTRST_DMA2 0x10001 + +#define RST_DMA1_MSK 0x4 +#define RST_DMA2_MSK 0x0 + +#define CRU_CLKSEL_CON 0x100 +#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4)) +#define CRU_CLKSEL_CON_CNT 56 + +#define CRU_CLKGATE_CON 0x200 +#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4)) +#define CRU_CLKGATES_CON_CNT 25 + +#define CRU_GLB_SRST_FST 0x280 +#define CRU_GLB_SRST_SND 0x284 +#define CRU_GLB_RST_CON 0x388 + +#define CRU_CONS_GATEID(i) (16 * (i)) +#define GATE_ID(reg, bit) ((reg * 16) + bit) + +#define PMU_RST_BY_SECOND_SFT (BIT(1) << 2) +#define PMU_RST_NOT_BY_SFT (BIT(1) << 2) + +/*************************************************************************** + * pll + ***************************************************************************/ +#define PLL_PWR_DN_MSK (0x1 << 1) +#define PLL_PWR_DN REG_WMSK_BITS(1, 1, 0x1) +#define PLL_PWR_ON REG_WMSK_BITS(0, 1, 0x1) +#define PLL_RESET REG_WMSK_BITS(1, 5, 0x1) +#define PLL_RESET_RESUME REG_WMSK_BITS(0, 5, 0x1) +#define PLL_BYPASS_MSK (0x1 << 0) +#define PLL_BYPASS_W_MSK (PLL_BYPASS_MSK << 16) +#define PLL_BYPASS REG_WMSK_BITS(1, 0, 0x1) +#define PLL_NO_BYPASS REG_WMSK_BITS(0, 0, 0x1) +#define PLL_MODE_SHIFT 8 +#define PLL_MODE_MSK 0x3 +#define PLLS_MODE_WMASK (PLL_MODE_MSK << (16 + PLL_MODE_SHIFT)) +#define PLL_SLOW 0x0 +#define PLL_NORM 0x1 +#define PLL_DEEP 0x2 +#define PLL_SLOW_BITS REG_WMSK_BITS(PLL_SLOW, 8, 0x3) +#define PLL_NORM_BITS REG_WMSK_BITS(PLL_NORM, 8, 0x3) +#define PLL_DEEP_BITS REG_WMSK_BITS(PLL_DEEP, 8, 0x3) + +#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4)) + +#define REG_W_MSK(bits_shift, msk) \ + ((msk) << ((bits_shift) + 16)) +#define REG_VAL_CLRBITS(val, bits_shift, msk) \ + (val & (~(msk << bits_shift))) +#define REG_SET_BITS(bits, bits_shift, msk) \ + (((bits) & (msk)) << (bits_shift)) +#define REG_WMSK_BITS(bits, bits_shift, msk) \ + (REG_W_MSK(bits_shift, msk) | \ + REG_SET_BITS(bits, bits_shift, msk)) + +#define regs_updata_bit_set(addr, shift) \ + regs_updata_bits((addr), 0x1, 0x1, (shift)) +#define regs_updata_bit_clr(addr, shift) \ + regs_updata_bits((addr), 0x0, 0x1, (shift)) + +void regs_updata_bits(uintptr_t addr, uint32_t val, + uint32_t mask, uint32_t shift); +void soc_sleep_config(void); +void pm_plls_resume(void); + +#endif /* SOC_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S b/arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S new file mode 100644 index 0000000..e9bb3a2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ROCKCHIP_PLAT_LD_S +#define ROCKCHIP_PLAT_LD_S + +MEMORY { + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .text_pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + *(.pmusram.entry) + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; + + } >PMUSRAM +} + +#endif /* ROCKCHIP_PLAT_LD_S */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h b/arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h new file mode 100644 index 0000000..66c4868 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +#define RK_PLAT_SIP_NUM_CALLS 0 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h new file mode 100644 index 0000000..519a025 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#include + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL1) +#define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +#define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x800 +#elif defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(4) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_RK_CLST_TO_CPUID_SHIFT 6 + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* + * 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 U(1) + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF text, ro, rw, Size: 1MB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x100000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted RAM + */ +#define BL31_BASE (TZRAM_BASE + 0x40000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 20 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Define GICD and GICC and GICR base + */ +#define PLAT_RK_GICD_BASE RK3368_GICD_BASE +#define PLAT_RK_GICC_BASE RK3368_GICC_BASE + +#define PLAT_RK_UART_BASE UART2_BASE +#define PLAT_RK_UART_CLOCK RK3368_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE RK3368_BAUDRATE + +#define PLAT_RK_CCI_BASE CCI400_BASE + +#define PLAT_RK_PRIMARY_CPU 0x0 + +#define PSRAM_DO_DDR_RESUME 0 +#define PSRAM_CHECK_WAKEUP_CPU 0 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c b/arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c new file mode 100644 index 0000000..5918d58 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +uintptr_t rockchip_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) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/platform.mk b/arm-trusted-firmware/plat/rockchip/rk3368/platform.mk new file mode 100644 index 0000000..e6c62de --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/platform.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/arm/gic/v2/gicv2.mk + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +DISABLE_BIN_GENERATION := 1 + +PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/aarch64/ \ + -I${RK_PLAT_COMMON}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/drivers/ddr/ \ + -I${RK_PLAT_SOC}/include/ + +RK_GIC_SOURCES := ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + ${RK_PLAT}/common/rockchip_gicv2.c + +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + plat/common/aarch64/crash_console_helpers.S \ + plat/common/plat_psci_common.c + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + +BL31_SOURCES += ${RK_GIC_SOURCES} \ + drivers/arm/cci/cci.c \ + drivers/ti/uart/aarch64/16550_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/aarch64/cortex_a53.S \ + ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ + ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/aarch64/platform_common.c \ + ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + ${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \ + +include lib/coreboot/coreboot.mk +include lib/libfdt/libfdt.mk + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +WORKAROUND_CVE_2017_5715 := 0 diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h b/arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h new file mode 100644 index 0000000..4b0fbab --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RK3368_DEF_H +#define RK3368_DEF_H + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define CCI400_BASE 0xffb90000 +#define CCI400_SIZE 0x10000 + +#define GIC400_BASE 0xffb70000 +#define GIC400_SIZE 0x10000 + +#define STIME_BASE 0xff830000 +#define STIME_SIZE 0x10000 + +#define CRU_BASE 0xff760000 +#define CRU_SIZE 0x10000 + +#define GRF_BASE 0xff770000 +#define GRF_SIZE 0x10000 + +#define SGRF_BASE 0xff740000 +#define SGRF_SIZE 0x10000 + +#define PMU_BASE 0xff730000 +#define PMU_GRF_BASE 0xff738000 +#define PMU_SIZE 0x10000 + +#define RK_INTMEM_BASE 0xff8c0000 +#define RK_INTMEM_SIZE 0x10000 + +#define UART0_BASE 0xff180000 +#define UART0_SIZE 0x10000 + +#define UART1_BASE 0xff190000 +#define UART1_SIZE 0x10000 + +#define UART2_BASE 0xff690000 +#define UART2_SIZE 0x10000 + +#define UART3_BASE 0xff1b0000 +#define UART3_SIZE 0x10000 + +#define UART4_BASE 0xff1c0000 +#define UART4_SIZE 0x10000 + +#define CRU_BASE 0xff760000 + +#define PMUSRAM_BASE 0xff720000 +#define PMUSRAM_SIZE 0x10000 +#define PMUSRAM_RSIZE 0x1000 + +#define DDR_PCTL_BASE 0xff610000 +#define DDR_PCTL_SIZE 0x10000 + +#define DDR_PHY_BASE 0xff620000 +#define DDR_PHY_SIZE 0x10000 + +#define SERVICE_BUS_BASE 0xffac0000 +#define SERVICE_BUS_SISE 0x50000 + +#define COLD_BOOT_BASE 0xffff0000 +/************************************************************************** + * UART related constants + **************************************************************************/ +#define RK3368_BAUDRATE 115200 +#define RK3368_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000 + +/****************************************************************************** + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base rk_platform compatible GIC memory map */ +#define RK3368_GICD_BASE (GIC400_BASE + 0x1000) +#define RK3368_GICC_BASE (GIC400_BASE + 0x2000) +#define RK3368_GICR_BASE 0 /* no GICR in GIC-400 */ + +/***************************************************************************** + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 3 +#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 4 + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#define RK_IRQ_SEC_PHY_TIMER 29 + +#define RK_IRQ_SEC_SGI_0 8 +#define RK_IRQ_SEC_SGI_1 9 +#define RK_IRQ_SEC_SGI_2 10 +#define RK_IRQ_SEC_SGI_3 11 +#define RK_IRQ_SEC_SGI_4 12 +#define RK_IRQ_SEC_SGI_5 13 +#define RK_IRQ_SEC_SGI_6 14 +#define RK_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 0 interrupts. + */ +#define PLAT_RK_GICV2_G0_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#endif /* RK3368_DEF_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c new file mode 100644 index 0000000..a8773f4 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include + +__asm__( + ".pushsection .text.hdcp_handler, \"ax\", %progbits\n" + ".global hdcp_handler\n" + ".balign 4\n" + "hdcp_handler:\n" + ".incbin \"" HDCPFW "\"\n" + ".type hdcp_handler, %function\n" + ".size hdcp_handler, .- hdcp_handler\n" + ".popsection\n" +); + +static uint64_t *hdcp_key_pdata; +static struct cdn_dp_hdcp_key_1x key; + +int hdcp_handler(struct cdn_dp_hdcp_key_1x *key); + +uint64_t dp_hdcp_ctrl(uint64_t type) +{ + switch (type) { + case HDCP_KEY_DATA_START_TRANSFER: + memset(&key, 0x00, sizeof(key)); + hdcp_key_pdata = (uint64_t *)&key; + return 0; + case HDCP_KEY_DATA_START_DECRYPT: + if (hdcp_key_pdata == (uint64_t *)(&key + 1)) + return hdcp_handler(&key); + else + return PSCI_E_INVALID_PARAMS; + assert(0); /* Unreachable */ + default: + return SMC_UNK; + } +} + +uint64_t dp_hdcp_store_key(uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + uint64_t x5, + uint64_t x6) +{ + if (hdcp_key_pdata < (uint64_t *)&key || + hdcp_key_pdata + 6 > (uint64_t *)(&key + 1)) + return PSCI_E_INVALID_PARAMS; + + hdcp_key_pdata[0] = x1; + hdcp_key_pdata[1] = x2; + hdcp_key_pdata[2] = x3; + hdcp_key_pdata[3] = x4; + hdcp_key_pdata[4] = x5; + hdcp_key_pdata[5] = x6; + hdcp_key_pdata += 6; + + return 0; +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h new file mode 100644 index 0000000..c5cbae2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CDN_DP_H +#define CDN_DP_H + +#include + +enum { + CDN_DP_HDCP_1X_KSV_LEN = 5, + CDN_DP_HDCP_KSV_LEN = 8, + CDN_DP_HDCP_RESERVED_LEN = 10, + CDN_DP_HDCP_UID_LEN = 16, + CDN_DP_HDCP_SHA_LEN = 20, + CDN_DP_HDCP_DPK_LEN = 280, + CDN_DP_HDCP_1X_KEYS_LEN = 285, + CDN_DP_HDCP_KEY_LEN = 326, +}; + +struct cdn_dp_hdcp_key_1x { + uint8_t ksv[CDN_DP_HDCP_KSV_LEN]; + uint8_t device_key[CDN_DP_HDCP_DPK_LEN]; + uint8_t sha1[CDN_DP_HDCP_SHA_LEN]; + uint8_t uid[CDN_DP_HDCP_UID_LEN]; + uint16_t seed; + uint8_t reserved[CDN_DP_HDCP_RESERVED_LEN]; +}; + +#define HDCP_KEY_DATA_START_TRANSFER 0 +#define HDCP_KEY_DATA_START_DECRYPT 1 +#define HDCP_KEY_1X_STORE_DATA_ALIGN_SIZE (6 * 64) / 8 + +/* Checks the cdn_dp_hdcp_key_1x must be aligned on 6 x 64-bit word boundary */ +CASSERT(sizeof(struct cdn_dp_hdcp_key_1x) % HDCP_KEY_1X_STORE_DATA_ALIGN_SIZE, \ + assert_hdcp_key_1x_store_data_align_size_mismatch); + +uint64_t dp_hdcp_ctrl(uint64_t type); + +uint64_t dp_hdcp_store_key(uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + uint64_t x5, + uint64_t x6); + +#endif /* CDN_DP_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin new file mode 100644 index 0000000..28db923 Binary files /dev/null and b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin differ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c new file mode 100644 index 0000000..816372b --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c @@ -0,0 +1,2114 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include "dfs.h" +#include "dram.h" +#include "dram_spec_timing.h" +#include "pmu.h" +#include "soc.h" +#include "string.h" + +#define ENPER_CS_TRAINING_FREQ (666) +#define TDFI_LAT_THRESHOLD_FREQ (928) +#define PHY_DLL_BYPASS_FREQ (260) + +static const struct pll_div dpll_rates_table[] = { + + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2 */ + {.mhz = 928, .refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1}, + {.mhz = 800, .refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1}, + {.mhz = 732, .refdiv = 1, .fbdiv = 61, .postdiv1 = 2, .postdiv2 = 1}, + {.mhz = 666, .refdiv = 1, .fbdiv = 111, .postdiv1 = 4, .postdiv2 = 1}, + {.mhz = 600, .refdiv = 1, .fbdiv = 50, .postdiv1 = 2, .postdiv2 = 1}, + {.mhz = 528, .refdiv = 1, .fbdiv = 66, .postdiv1 = 3, .postdiv2 = 1}, + {.mhz = 400, .refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 1}, + {.mhz = 300, .refdiv = 1, .fbdiv = 50, .postdiv1 = 4, .postdiv2 = 1}, + {.mhz = 200, .refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 2}, +}; + +struct rk3399_dram_status { + uint32_t current_index; + uint32_t index_freq[2]; + uint32_t boot_freq; + uint32_t low_power_stat; + struct timing_related_config timing_config; + struct drv_odt_lp_config drv_odt_lp_cfg; +}; + +struct rk3399_saved_status { + uint32_t freq; + uint32_t low_power_stat; + uint32_t odt; +}; + +static struct rk3399_dram_status rk3399_dram_status; +static struct rk3399_saved_status rk3399_suspend_status; +static uint32_t wrdqs_delay_val[2][2][4]; +static uint32_t rddqs_delay_ps; + +static struct rk3399_sdram_default_config ddr3_default_config = { + .bl = 8, + .ap = 0, + .burst_ref_cnt = 1, + .zqcsi = 0 +}; + +static struct rk3399_sdram_default_config lpddr3_default_config = { + .bl = 8, + .ap = 0, + .burst_ref_cnt = 1, + .zqcsi = 0 +}; + +static struct rk3399_sdram_default_config lpddr4_default_config = { + .bl = 16, + .ap = 0, + .caodt = 240, + .burst_ref_cnt = 1, + .zqcsi = 0 +}; + +static uint32_t get_cs_die_capability(struct rk3399_sdram_params *ram_config, + uint8_t channel, uint8_t cs) +{ + struct rk3399_sdram_channel *ch = &ram_config->ch[channel]; + uint32_t bandwidth; + uint32_t die_bandwidth; + uint32_t die; + uint32_t cs_cap; + uint32_t row; + + row = cs == 0 ? ch->cs0_row : ch->cs1_row; + bandwidth = 8 * (1 << ch->bw); + die_bandwidth = 8 * (1 << ch->dbw); + die = bandwidth / die_bandwidth; + cs_cap = (1 << (row + ((1 << ch->bk) / 4 + 1) + ch->col + + (bandwidth / 16))); + if (ch->row_3_4) + cs_cap = cs_cap * 3 / 4; + + return (cs_cap / die); +} + +static void get_dram_drv_odt_val(uint32_t dram_type, + struct drv_odt_lp_config *drv_config) +{ + uint32_t tmp; + uint32_t mr1_val, mr3_val, mr11_val; + + switch (dram_type) { + case DDR3: + mr1_val = (mmio_read_32(CTL_REG(0, 133)) >> 16) & 0xffff; + tmp = ((mr1_val >> 1) & 1) | ((mr1_val >> 4) & 1); + if (tmp) + drv_config->dram_side_drv = 34; + else + drv_config->dram_side_drv = 40; + tmp = ((mr1_val >> 2) & 1) | ((mr1_val >> 5) & 1) | + ((mr1_val >> 7) & 1); + if (tmp == 0) + drv_config->dram_side_dq_odt = 0; + else if (tmp == 1) + drv_config->dram_side_dq_odt = 60; + else if (tmp == 3) + drv_config->dram_side_dq_odt = 40; + else + drv_config->dram_side_dq_odt = 120; + break; + case LPDDR3: + mr3_val = mmio_read_32(CTL_REG(0, 138)) & 0xf; + mr11_val = (mmio_read_32(CTL_REG(0, 139)) >> 24) & 0x3; + if (mr3_val == 0xb) + drv_config->dram_side_drv = 3448; + else if (mr3_val == 0xa) + drv_config->dram_side_drv = 4048; + else if (mr3_val == 0x9) + drv_config->dram_side_drv = 3440; + else if (mr3_val == 0x4) + drv_config->dram_side_drv = 60; + else if (mr3_val == 0x3) + drv_config->dram_side_drv = 48; + else if (mr3_val == 0x2) + drv_config->dram_side_drv = 40; + else + drv_config->dram_side_drv = 34; + + if (mr11_val == 1) + drv_config->dram_side_dq_odt = 60; + else if (mr11_val == 2) + drv_config->dram_side_dq_odt = 120; + else if (mr11_val == 0) + drv_config->dram_side_dq_odt = 0; + else + drv_config->dram_side_dq_odt = 240; + break; + case LPDDR4: + default: + mr3_val = (mmio_read_32(CTL_REG(0, 138)) >> 3) & 0x7; + mr11_val = (mmio_read_32(CTL_REG(0, 139)) >> 24) & 0xff; + + if ((mr3_val == 0) || (mr3_val == 7)) + drv_config->dram_side_drv = 40; + else + drv_config->dram_side_drv = 240 / mr3_val; + + tmp = mr11_val & 0x7; + if ((tmp == 7) || (tmp == 0)) + drv_config->dram_side_dq_odt = 0; + else + drv_config->dram_side_dq_odt = 240 / tmp; + + tmp = (mr11_val >> 4) & 0x7; + if ((tmp == 7) || (tmp == 0)) + drv_config->dram_side_ca_odt = 0; + else + drv_config->dram_side_ca_odt = 240 / tmp; + break; + } +} + +static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config, + struct rk3399_sdram_params *sdram_params, + struct drv_odt_lp_config *drv_config) +{ + uint32_t i, j; + + for (i = 0; i < sdram_params->num_channels; i++) { + ptiming_config->dram_info[i].speed_rate = DDR3_DEFAULT; + ptiming_config->dram_info[i].cs_cnt = sdram_params->ch[i].rank; + for (j = 0; j < sdram_params->ch[i].rank; j++) { + ptiming_config->dram_info[i].per_die_capability[j] = + get_cs_die_capability(sdram_params, i, j); + } + } + ptiming_config->dram_type = sdram_params->dramtype; + ptiming_config->ch_cnt = sdram_params->num_channels; + switch (sdram_params->dramtype) { + case DDR3: + ptiming_config->bl = ddr3_default_config.bl; + ptiming_config->ap = ddr3_default_config.ap; + break; + case LPDDR3: + ptiming_config->bl = lpddr3_default_config.bl; + ptiming_config->ap = lpddr3_default_config.ap; + break; + case LPDDR4: + ptiming_config->bl = lpddr4_default_config.bl; + ptiming_config->ap = lpddr4_default_config.ap; + ptiming_config->rdbi = 0; + ptiming_config->wdbi = 0; + break; + default: + /* Do nothing in default case */ + break; + } + ptiming_config->dramds = drv_config->dram_side_drv; + ptiming_config->dramodt = drv_config->dram_side_dq_odt; + ptiming_config->caodt = drv_config->dram_side_ca_odt; + ptiming_config->odt = (mmio_read_32(PHY_REG(0, 5)) >> 16) & 0x1; +} + +struct lat_adj_pair { + uint32_t cl; + uint32_t rdlat_adj; + uint32_t cwl; + uint32_t wrlat_adj; +}; + +const struct lat_adj_pair ddr3_lat_adj[] = { + {6, 5, 5, 4}, + {8, 7, 6, 5}, + {10, 9, 7, 6}, + {11, 9, 8, 7}, + {13, 0xb, 9, 8}, + {14, 0xb, 0xa, 9} +}; + +const struct lat_adj_pair lpddr3_lat_adj[] = { + {3, 2, 1, 0}, + {6, 5, 3, 2}, + {8, 7, 4, 3}, + {9, 8, 5, 4}, + {10, 9, 6, 5}, + {11, 9, 6, 5}, + {12, 0xa, 6, 5}, + {14, 0xc, 8, 7}, + {16, 0xd, 8, 7} +}; + +const struct lat_adj_pair lpddr4_lat_adj[] = { + {6, 5, 4, 2}, + {10, 9, 6, 4}, + {14, 0xc, 8, 6}, + {20, 0x11, 0xa, 8}, + {24, 0x15, 0xc, 0xa}, + {28, 0x18, 0xe, 0xc}, + {32, 0x1b, 0x10, 0xe}, + {36, 0x1e, 0x12, 0x10} +}; + +static uint32_t get_rdlat_adj(uint32_t dram_type, uint32_t cl) +{ + const struct lat_adj_pair *p; + uint32_t cnt; + uint32_t i; + + if (dram_type == DDR3) { + p = ddr3_lat_adj; + cnt = ARRAY_SIZE(ddr3_lat_adj); + } else if (dram_type == LPDDR3) { + p = lpddr3_lat_adj; + cnt = ARRAY_SIZE(lpddr3_lat_adj); + } else { + p = lpddr4_lat_adj; + cnt = ARRAY_SIZE(lpddr4_lat_adj); + } + + for (i = 0; i < cnt; i++) { + if (cl == p[i].cl) + return p[i].rdlat_adj; + } + /* fail */ + return 0xff; +} + +static uint32_t get_wrlat_adj(uint32_t dram_type, uint32_t cwl) +{ + const struct lat_adj_pair *p; + uint32_t cnt; + uint32_t i; + + if (dram_type == DDR3) { + p = ddr3_lat_adj; + cnt = ARRAY_SIZE(ddr3_lat_adj); + } else if (dram_type == LPDDR3) { + p = lpddr3_lat_adj; + cnt = ARRAY_SIZE(lpddr3_lat_adj); + } else { + p = lpddr4_lat_adj; + cnt = ARRAY_SIZE(lpddr4_lat_adj); + } + + for (i = 0; i < cnt; i++) { + if (cwl == p[i].cwl) + return p[i].wrlat_adj; + } + /* fail */ + return 0xff; +} + +#define PI_REGS_DIMM_SUPPORT (0) +#define PI_ADD_LATENCY (0) +#define PI_DOUBLEFREEK (1) + +#define PI_PAD_DELAY_PS_VALUE (1000) +#define PI_IE_ENABLE_VALUE (3000) +#define PI_TSEL_ENABLE_VALUE (700) + +static uint32_t get_pi_rdlat_adj(struct dram_timing_t *pdram_timing) +{ + /*[DLLSUBTYPE2] == "STD_DENALI_HS" */ + uint32_t rdlat, delay_adder, ie_enable, hs_offset, tsel_adder, + extra_adder, tsel_enable; + + ie_enable = PI_IE_ENABLE_VALUE; + tsel_enable = PI_TSEL_ENABLE_VALUE; + + rdlat = pdram_timing->cl + PI_ADD_LATENCY; + delay_adder = ie_enable / (1000000 / pdram_timing->mhz); + if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) + delay_adder++; + hs_offset = 0; + tsel_adder = 0; + extra_adder = 0; + /* rdlat = rdlat - (PREAMBLE_SUPPORT & 0x1); */ + tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz); + if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0) + tsel_adder++; + delay_adder = delay_adder - 1; + if (tsel_adder > delay_adder) + extra_adder = tsel_adder - delay_adder; + else + extra_adder = 0; + if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) + hs_offset = 2; + else + hs_offset = 1; + + if (delay_adder > (rdlat - 1 - hs_offset)) { + rdlat = rdlat - tsel_adder; + } else { + if ((rdlat - delay_adder) < 2) + rdlat = 2; + else + rdlat = rdlat - delay_adder - extra_adder; + } + + return rdlat; +} + +static uint32_t get_pi_wrlat(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + uint32_t tmp; + + if (timing_config->dram_type == LPDDR3) { + tmp = pdram_timing->cl; + if (tmp >= 14) + tmp = 8; + else if (tmp >= 10) + tmp = 6; + else if (tmp == 9) + tmp = 5; + else if (tmp == 8) + tmp = 4; + else if (tmp == 6) + tmp = 3; + else + tmp = 1; + } else { + tmp = 1; + } + + return tmp; +} + +static uint32_t get_pi_wrlat_adj(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + return get_pi_wrlat(pdram_timing, timing_config) + PI_ADD_LATENCY - 1; +} + +static uint32_t get_pi_tdfi_phy_rdlat(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + /* [DLLSUBTYPE2] == "STD_DENALI_HS" */ + uint32_t cas_lat, delay_adder, ie_enable, hs_offset, ie_delay_adder; + uint32_t mem_delay_ps, round_trip_ps; + uint32_t phy_internal_delay, lpddr_adder, dfi_adder, rdlat_delay; + + ie_enable = PI_IE_ENABLE_VALUE; + + delay_adder = ie_enable / (1000000 / pdram_timing->mhz); + if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) + delay_adder++; + delay_adder = delay_adder - 1; + if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) + hs_offset = 2; + else + hs_offset = 1; + + cas_lat = pdram_timing->cl + PI_ADD_LATENCY; + + if (delay_adder > (cas_lat - 1 - hs_offset)) { + ie_delay_adder = 0; + } else { + ie_delay_adder = ie_enable / (1000000 / pdram_timing->mhz); + if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) + ie_delay_adder++; + } + + if (timing_config->dram_type == DDR3) { + mem_delay_ps = 0; + } else if (timing_config->dram_type == LPDDR4) { + mem_delay_ps = 3600; + } else if (timing_config->dram_type == LPDDR3) { + mem_delay_ps = 5500; + } else { + NOTICE("get_pi_tdfi_phy_rdlat:dramtype unsupport\n"); + return 0; + } + round_trip_ps = 1100 + 500 + mem_delay_ps + 500 + 600; + delay_adder = round_trip_ps / (1000000 / pdram_timing->mhz); + if ((round_trip_ps % (1000000 / pdram_timing->mhz)) != 0) + delay_adder++; + + phy_internal_delay = 5 + 2 + 4; + lpddr_adder = mem_delay_ps / (1000000 / pdram_timing->mhz); + if ((mem_delay_ps % (1000000 / pdram_timing->mhz)) != 0) + lpddr_adder++; + dfi_adder = 0; + phy_internal_delay = phy_internal_delay + 2; + rdlat_delay = delay_adder + phy_internal_delay + + ie_delay_adder + lpddr_adder + dfi_adder; + + rdlat_delay = rdlat_delay + 2; + return rdlat_delay; +} + +static uint32_t get_pi_todtoff_min(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + uint32_t tmp, todtoff_min_ps; + + if (timing_config->dram_type == LPDDR3) + todtoff_min_ps = 2500; + else if (timing_config->dram_type == LPDDR4) + todtoff_min_ps = 1500; + else + todtoff_min_ps = 0; + /* todtoff_min */ + tmp = todtoff_min_ps / (1000000 / pdram_timing->mhz); + if ((todtoff_min_ps % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + return tmp; +} + +static uint32_t get_pi_todtoff_max(struct dram_timing_t *pdram_timing, + struct timing_related_config *timing_config) +{ + uint32_t tmp, todtoff_max_ps; + + if ((timing_config->dram_type == LPDDR4) + || (timing_config->dram_type == LPDDR3)) + todtoff_max_ps = 3500; + else + todtoff_max_ps = 0; + + /* todtoff_max */ + tmp = todtoff_max_ps / (1000000 / pdram_timing->mhz); + if ((todtoff_max_ps % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + return tmp; +} + +static void gen_rk3399_ctl_params_f0(struct timing_related_config + *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t i; + uint32_t tmp, tmp1; + + for (i = 0; i < timing_config->ch_cnt; i++) { + if (timing_config->dram_type == DDR3) { + tmp = ((700000 + 10) * timing_config->freq + + 999) / 1000; + tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) + + pdram_timing->tmod + pdram_timing->tzqinit; + mmio_write_32(CTL_REG(i, 5), tmp); + + mmio_clrsetbits_32(CTL_REG(i, 22), 0xffff, + pdram_timing->tdllk); + + mmio_write_32(CTL_REG(i, 32), + (pdram_timing->tmod << 8) | + pdram_timing->tmrd); + + mmio_clrsetbits_32(CTL_REG(i, 59), 0xffffu << 16, + (pdram_timing->txsr - + pdram_timing->trcd) << 16); + } else if (timing_config->dram_type == LPDDR4) { + mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1 + + pdram_timing->tinit3); + mmio_write_32(CTL_REG(i, 32), + (pdram_timing->tmrd << 8) | + pdram_timing->tmrd); + mmio_clrsetbits_32(CTL_REG(i, 59), 0xffffu << 16, + pdram_timing->txsr << 16); + } else { + mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1); + mmio_write_32(CTL_REG(i, 7), pdram_timing->tinit4); + mmio_write_32(CTL_REG(i, 32), + (pdram_timing->tmrd << 8) | + pdram_timing->tmrd); + mmio_clrsetbits_32(CTL_REG(i, 59), 0xffffu << 16, + pdram_timing->txsr << 16); + } + mmio_write_32(CTL_REG(i, 6), pdram_timing->tinit3); + mmio_write_32(CTL_REG(i, 8), pdram_timing->tinit5); + mmio_clrsetbits_32(CTL_REG(i, 23), (0x7f << 16), + ((pdram_timing->cl * 2) << 16)); + mmio_clrsetbits_32(CTL_REG(i, 23), (0x1f << 24), + (pdram_timing->cwl << 24)); + mmio_clrsetbits_32(CTL_REG(i, 24), 0x3f, pdram_timing->al); + mmio_clrsetbits_32(CTL_REG(i, 26), 0xffffu << 16, + (pdram_timing->trc << 24) | + (pdram_timing->trrd << 16)); + mmio_write_32(CTL_REG(i, 27), + (pdram_timing->tfaw << 24) | + (pdram_timing->trppb << 16) | + (pdram_timing->twtr << 8) | + pdram_timing->tras_min); + + mmio_clrsetbits_32(CTL_REG(i, 31), 0xffu << 24, + max(4, pdram_timing->trtp) << 24); + mmio_write_32(CTL_REG(i, 33), (pdram_timing->tcke << 24) | + pdram_timing->tras_max); + mmio_clrsetbits_32(CTL_REG(i, 34), 0xff, + max(1, pdram_timing->tckesr)); + mmio_clrsetbits_32(CTL_REG(i, 39), + (0x3f << 16) | (0xff << 8), + (pdram_timing->twr << 16) | + (pdram_timing->trcd << 8)); + mmio_clrsetbits_32(CTL_REG(i, 42), 0x1f << 16, + pdram_timing->tmrz << 16); + tmp = pdram_timing->tdal ? pdram_timing->tdal : + (pdram_timing->twr + pdram_timing->trp); + mmio_clrsetbits_32(CTL_REG(i, 44), 0xff, tmp); + mmio_clrsetbits_32(CTL_REG(i, 45), 0xff, pdram_timing->trp); + mmio_write_32(CTL_REG(i, 48), + ((pdram_timing->trefi - 8) << 16) | + pdram_timing->trfc); + mmio_clrsetbits_32(CTL_REG(i, 52), 0xffff, pdram_timing->txp); + mmio_clrsetbits_32(CTL_REG(i, 53), 0xffffu << 16, + pdram_timing->txpdll << 16); + mmio_clrsetbits_32(CTL_REG(i, 55), 0xf << 24, + pdram_timing->tcscke << 24); + mmio_clrsetbits_32(CTL_REG(i, 55), 0xff, pdram_timing->tmrri); + mmio_write_32(CTL_REG(i, 56), + (pdram_timing->tzqcke << 24) | + (pdram_timing->tmrwckel << 16) | + (pdram_timing->tckehcs << 8) | + pdram_timing->tckelcs); + mmio_clrsetbits_32(CTL_REG(i, 60), 0xffff, pdram_timing->txsnr); + mmio_clrsetbits_32(CTL_REG(i, 62), 0xffffu << 16, + (pdram_timing->tckehcmd << 24) | + (pdram_timing->tckelcmd << 16)); + mmio_write_32(CTL_REG(i, 63), + (pdram_timing->tckelpd << 24) | + (pdram_timing->tescke << 16) | + (pdram_timing->tsr << 8) | + pdram_timing->tckckel); + mmio_clrsetbits_32(CTL_REG(i, 64), 0xfff, + (pdram_timing->tcmdcke << 8) | + pdram_timing->tcsckeh); + mmio_clrsetbits_32(CTL_REG(i, 92), 0xffff << 8, + (pdram_timing->tcksrx << 16) | + (pdram_timing->tcksre << 8)); + mmio_clrsetbits_32(CTL_REG(i, 108), 0x1 << 24, + (timing_config->dllbp << 24)); + mmio_clrsetbits_32(CTL_REG(i, 122), 0x3ff << 16, + (pdram_timing->tvrcg_enable << 16)); + mmio_write_32(CTL_REG(i, 123), (pdram_timing->tfc_long << 16) | + pdram_timing->tvrcg_disable); + mmio_write_32(CTL_REG(i, 124), + (pdram_timing->tvref_long << 16) | + (pdram_timing->tckfspx << 8) | + pdram_timing->tckfspe); + mmio_write_32(CTL_REG(i, 133), (pdram_timing->mr[1] << 16) | + pdram_timing->mr[0]); + mmio_clrsetbits_32(CTL_REG(i, 134), 0xffff, + pdram_timing->mr[2]); + mmio_clrsetbits_32(CTL_REG(i, 138), 0xffff, + pdram_timing->mr[3]); + mmio_clrsetbits_32(CTL_REG(i, 139), 0xffu << 24, + pdram_timing->mr11 << 24); + mmio_write_32(CTL_REG(i, 147), + (pdram_timing->mr[1] << 16) | + pdram_timing->mr[0]); + mmio_clrsetbits_32(CTL_REG(i, 148), 0xffff, + pdram_timing->mr[2]); + mmio_clrsetbits_32(CTL_REG(i, 152), 0xffff, + pdram_timing->mr[3]); + mmio_clrsetbits_32(CTL_REG(i, 153), 0xffu << 24, + pdram_timing->mr11 << 24); + if (timing_config->dram_type == LPDDR4) { + mmio_clrsetbits_32(CTL_REG(i, 140), 0xffffu << 16, + pdram_timing->mr12 << 16); + mmio_clrsetbits_32(CTL_REG(i, 142), 0xffffu << 16, + pdram_timing->mr14 << 16); + mmio_clrsetbits_32(CTL_REG(i, 145), 0xffffu << 16, + pdram_timing->mr22 << 16); + mmio_clrsetbits_32(CTL_REG(i, 154), 0xffffu << 16, + pdram_timing->mr12 << 16); + mmio_clrsetbits_32(CTL_REG(i, 156), 0xffffu << 16, + pdram_timing->mr14 << 16); + mmio_clrsetbits_32(CTL_REG(i, 159), 0xffffu << 16, + pdram_timing->mr22 << 16); + } + mmio_clrsetbits_32(CTL_REG(i, 179), 0xfff << 8, + pdram_timing->tzqinit << 8); + mmio_write_32(CTL_REG(i, 180), (pdram_timing->tzqcs << 16) | + (pdram_timing->tzqinit / 2)); + mmio_write_32(CTL_REG(i, 181), (pdram_timing->tzqlat << 16) | + pdram_timing->tzqcal); + mmio_clrsetbits_32(CTL_REG(i, 212), 0xff << 8, + pdram_timing->todton << 8); + + if (timing_config->odt) { + mmio_setbits_32(CTL_REG(i, 213), 1 << 16); + if (timing_config->freq < 400) + tmp = 4 << 24; + else + tmp = 8 << 24; + } else { + mmio_clrbits_32(CTL_REG(i, 213), 1 << 16); + tmp = 2 << 24; + } + + mmio_clrsetbits_32(CTL_REG(i, 216), 0x1f << 24, tmp); + mmio_clrsetbits_32(CTL_REG(i, 221), (0x3 << 16) | (0xf << 8), + (pdram_timing->tdqsck << 16) | + (pdram_timing->tdqsck_max << 8)); + tmp = + (get_wrlat_adj(timing_config->dram_type, pdram_timing->cwl) + << 8) | get_rdlat_adj(timing_config->dram_type, + pdram_timing->cl); + mmio_clrsetbits_32(CTL_REG(i, 284), 0xffff, tmp); + mmio_clrsetbits_32(CTL_REG(i, 82), 0xffffu << 16, + (4 * pdram_timing->trefi) << 16); + + mmio_clrsetbits_32(CTL_REG(i, 83), 0xffff, + (2 * pdram_timing->trefi) & 0xffff); + + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + tmp = get_pi_wrlat(pdram_timing, timing_config); + tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); + tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; + } else { + tmp = 0; + } + mmio_clrsetbits_32(CTL_REG(i, 214), 0x3f << 16, + (tmp & 0x3f) << 16); + + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + /* min_rl_preamble = cl+TDQSCK_MIN -1 */ + tmp = pdram_timing->cl + + get_pi_todtoff_min(pdram_timing, timing_config) - 1; + /* todtoff_max */ + tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); + tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; + } else { + tmp = pdram_timing->cl - pdram_timing->cwl; + } + mmio_clrsetbits_32(CTL_REG(i, 215), 0x3f << 8, + (tmp & 0x3f) << 8); + + mmio_clrsetbits_32(CTL_REG(i, 275), 0xff << 16, + (get_pi_tdfi_phy_rdlat(pdram_timing, + timing_config) & + 0xff) << 16); + + mmio_clrsetbits_32(CTL_REG(i, 277), 0xffff, + (2 * pdram_timing->trefi) & 0xffff); + + mmio_clrsetbits_32(CTL_REG(i, 282), 0xffff, + (2 * pdram_timing->trefi) & 0xffff); + + mmio_write_32(CTL_REG(i, 283), 20 * pdram_timing->trefi); + + /* CTL_308 TDFI_CALVL_CAPTURE_F0:RW:16:10 */ + tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; + if ((20000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; + mmio_clrsetbits_32(CTL_REG(i, 308), 0x3ff << 16, tmp << 16); + + /* CTL_308 TDFI_CALVL_CC_F0:RW:0:10 */ + tmp = tmp + 18; + mmio_clrsetbits_32(CTL_REG(i, 308), 0x3ff, tmp); + + /* CTL_314 TDFI_WRCSLAT_F0:RW:8:8 */ + tmp1 = get_pi_wrlat_adj(pdram_timing, timing_config); + if (timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) { + if (tmp1 == 0) + tmp = 0; + else if (tmp1 < 5) + tmp = tmp1 - 1; + else + tmp = tmp1 - 5; + } else { + tmp = tmp1 - 2; + } + mmio_clrsetbits_32(CTL_REG(i, 314), 0xff << 8, tmp << 8); + + /* CTL_314 TDFI_RDCSLAT_F0:RW:0:8 */ + if ((timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) && + (pdram_timing->cl >= 5)) + tmp = pdram_timing->cl - 5; + else + tmp = pdram_timing->cl - 2; + mmio_clrsetbits_32(CTL_REG(i, 314), 0xff, tmp); + } +} + +static void gen_rk3399_ctl_params_f1(struct timing_related_config + *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t i; + uint32_t tmp, tmp1; + + for (i = 0; i < timing_config->ch_cnt; i++) { + if (timing_config->dram_type == DDR3) { + tmp = + ((700000 + 10) * timing_config->freq + 999) / 1000; + tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) + + pdram_timing->tmod + pdram_timing->tzqinit; + mmio_write_32(CTL_REG(i, 9), tmp); + mmio_clrsetbits_32(CTL_REG(i, 22), 0xffffu << 16, + pdram_timing->tdllk << 16); + mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00, + (pdram_timing->tmod << 24) | + (pdram_timing->tmrd << 16) | + (pdram_timing->trtp << 8)); + mmio_clrsetbits_32(CTL_REG(i, 60), 0xffffu << 16, + (pdram_timing->txsr - + pdram_timing->trcd) << 16); + } else if (timing_config->dram_type == LPDDR4) { + mmio_write_32(CTL_REG(i, 9), pdram_timing->tinit1 + + pdram_timing->tinit3); + mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00, + (pdram_timing->tmrd << 24) | + (pdram_timing->tmrd << 16) | + (pdram_timing->trtp << 8)); + mmio_clrsetbits_32(CTL_REG(i, 60), 0xffffu << 16, + pdram_timing->txsr << 16); + } else { + mmio_write_32(CTL_REG(i, 9), pdram_timing->tinit1); + mmio_write_32(CTL_REG(i, 11), pdram_timing->tinit4); + mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00, + (pdram_timing->tmrd << 24) | + (pdram_timing->tmrd << 16) | + (pdram_timing->trtp << 8)); + mmio_clrsetbits_32(CTL_REG(i, 60), 0xffffu << 16, + pdram_timing->txsr << 16); + } + mmio_write_32(CTL_REG(i, 10), pdram_timing->tinit3); + mmio_write_32(CTL_REG(i, 12), pdram_timing->tinit5); + mmio_clrsetbits_32(CTL_REG(i, 24), (0x7f << 8), + ((pdram_timing->cl * 2) << 8)); + mmio_clrsetbits_32(CTL_REG(i, 24), (0x1f << 16), + (pdram_timing->cwl << 16)); + mmio_clrsetbits_32(CTL_REG(i, 24), 0x3f << 24, + pdram_timing->al << 24); + mmio_clrsetbits_32(CTL_REG(i, 28), 0xffffff00, + (pdram_timing->tras_min << 24) | + (pdram_timing->trc << 16) | + (pdram_timing->trrd << 8)); + mmio_clrsetbits_32(CTL_REG(i, 29), 0xffffff, + (pdram_timing->tfaw << 16) | + (pdram_timing->trppb << 8) | + pdram_timing->twtr); + mmio_write_32(CTL_REG(i, 35), (pdram_timing->tcke << 24) | + pdram_timing->tras_max); + mmio_clrsetbits_32(CTL_REG(i, 36), 0xff, + max(1, pdram_timing->tckesr)); + mmio_clrsetbits_32(CTL_REG(i, 39), (0xffu << 24), + (pdram_timing->trcd << 24)); + mmio_clrsetbits_32(CTL_REG(i, 40), 0x3f, pdram_timing->twr); + mmio_clrsetbits_32(CTL_REG(i, 42), 0x1f << 24, + pdram_timing->tmrz << 24); + tmp = pdram_timing->tdal ? pdram_timing->tdal : + (pdram_timing->twr + pdram_timing->trp); + mmio_clrsetbits_32(CTL_REG(i, 44), 0xff << 8, tmp << 8); + mmio_clrsetbits_32(CTL_REG(i, 45), 0xff << 8, + pdram_timing->trp << 8); + mmio_write_32(CTL_REG(i, 49), + ((pdram_timing->trefi - 8) << 16) | + pdram_timing->trfc); + mmio_clrsetbits_32(CTL_REG(i, 52), 0xffffu << 16, + pdram_timing->txp << 16); + mmio_clrsetbits_32(CTL_REG(i, 54), 0xffff, + pdram_timing->txpdll); + mmio_clrsetbits_32(CTL_REG(i, 55), 0xff << 8, + pdram_timing->tmrri << 8); + mmio_write_32(CTL_REG(i, 57), (pdram_timing->tmrwckel << 24) | + (pdram_timing->tckehcs << 16) | + (pdram_timing->tckelcs << 8) | + pdram_timing->tcscke); + mmio_clrsetbits_32(CTL_REG(i, 58), 0xf, pdram_timing->tzqcke); + mmio_clrsetbits_32(CTL_REG(i, 61), 0xffff, pdram_timing->txsnr); + mmio_clrsetbits_32(CTL_REG(i, 64), 0xffffu << 16, + (pdram_timing->tckehcmd << 24) | + (pdram_timing->tckelcmd << 16)); + mmio_write_32(CTL_REG(i, 65), (pdram_timing->tckelpd << 24) | + (pdram_timing->tescke << 16) | + (pdram_timing->tsr << 8) | + pdram_timing->tckckel); + mmio_clrsetbits_32(CTL_REG(i, 66), 0xfff, + (pdram_timing->tcmdcke << 8) | + pdram_timing->tcsckeh); + mmio_clrsetbits_32(CTL_REG(i, 92), (0xffu << 24), + (pdram_timing->tcksre << 24)); + mmio_clrsetbits_32(CTL_REG(i, 93), 0xff, + pdram_timing->tcksrx); + mmio_clrsetbits_32(CTL_REG(i, 108), (0x1 << 25), + (timing_config->dllbp << 25)); + mmio_write_32(CTL_REG(i, 125), + (pdram_timing->tvrcg_disable << 16) | + pdram_timing->tvrcg_enable); + mmio_write_32(CTL_REG(i, 126), (pdram_timing->tckfspx << 24) | + (pdram_timing->tckfspe << 16) | + pdram_timing->tfc_long); + mmio_clrsetbits_32(CTL_REG(i, 127), 0xffff, + pdram_timing->tvref_long); + mmio_clrsetbits_32(CTL_REG(i, 134), 0xffffu << 16, + pdram_timing->mr[0] << 16); + mmio_write_32(CTL_REG(i, 135), (pdram_timing->mr[2] << 16) | + pdram_timing->mr[1]); + mmio_clrsetbits_32(CTL_REG(i, 138), 0xffffu << 16, + pdram_timing->mr[3] << 16); + mmio_clrsetbits_32(CTL_REG(i, 140), 0xff, pdram_timing->mr11); + mmio_clrsetbits_32(CTL_REG(i, 148), 0xffffu << 16, + pdram_timing->mr[0] << 16); + mmio_write_32(CTL_REG(i, 149), (pdram_timing->mr[2] << 16) | + pdram_timing->mr[1]); + mmio_clrsetbits_32(CTL_REG(i, 152), 0xffffu << 16, + pdram_timing->mr[3] << 16); + mmio_clrsetbits_32(CTL_REG(i, 154), 0xff, pdram_timing->mr11); + if (timing_config->dram_type == LPDDR4) { + mmio_clrsetbits_32(CTL_REG(i, 141), 0xffff, + pdram_timing->mr12); + mmio_clrsetbits_32(CTL_REG(i, 143), 0xffff, + pdram_timing->mr14); + mmio_clrsetbits_32(CTL_REG(i, 146), 0xffff, + pdram_timing->mr22); + mmio_clrsetbits_32(CTL_REG(i, 155), 0xffff, + pdram_timing->mr12); + mmio_clrsetbits_32(CTL_REG(i, 157), 0xffff, + pdram_timing->mr14); + mmio_clrsetbits_32(CTL_REG(i, 160), 0xffff, + pdram_timing->mr22); + } + mmio_write_32(CTL_REG(i, 182), + ((pdram_timing->tzqinit / 2) << 16) | + pdram_timing->tzqinit); + mmio_write_32(CTL_REG(i, 183), (pdram_timing->tzqcal << 16) | + pdram_timing->tzqcs); + mmio_clrsetbits_32(CTL_REG(i, 184), 0x3f, pdram_timing->tzqlat); + mmio_clrsetbits_32(CTL_REG(i, 188), 0xfff, + pdram_timing->tzqreset); + mmio_clrsetbits_32(CTL_REG(i, 212), 0xff << 16, + pdram_timing->todton << 16); + + if (timing_config->odt) { + mmio_setbits_32(CTL_REG(i, 213), (1 << 24)); + if (timing_config->freq < 400) + tmp = 4 << 24; + else + tmp = 8 << 24; + } else { + mmio_clrbits_32(CTL_REG(i, 213), (1 << 24)); + tmp = 2 << 24; + } + mmio_clrsetbits_32(CTL_REG(i, 217), 0x1f << 24, tmp); + mmio_clrsetbits_32(CTL_REG(i, 221), 0xf << 24, + (pdram_timing->tdqsck_max << 24)); + mmio_clrsetbits_32(CTL_REG(i, 222), 0x3, pdram_timing->tdqsck); + mmio_clrsetbits_32(CTL_REG(i, 291), 0xffff, + (get_wrlat_adj(timing_config->dram_type, + pdram_timing->cwl) << 8) | + get_rdlat_adj(timing_config->dram_type, + pdram_timing->cl)); + + mmio_clrsetbits_32(CTL_REG(i, 84), 0xffff, + (4 * pdram_timing->trefi) & 0xffff); + + mmio_clrsetbits_32(CTL_REG(i, 84), 0xffffu << 16, + ((2 * pdram_timing->trefi) & 0xffff) << 16); + + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + tmp = get_pi_wrlat(pdram_timing, timing_config); + tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); + tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; + } else { + tmp = 0; + } + mmio_clrsetbits_32(CTL_REG(i, 214), 0x3f << 24, + (tmp & 0x3f) << 24); + + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + /* min_rl_preamble = cl + TDQSCK_MIN - 1 */ + tmp = pdram_timing->cl + + get_pi_todtoff_min(pdram_timing, timing_config); + tmp--; + /* todtoff_max */ + tmp1 = get_pi_todtoff_max(pdram_timing, timing_config); + tmp = (tmp > tmp1) ? (tmp - tmp1) : 0; + } else { + tmp = pdram_timing->cl - pdram_timing->cwl; + } + mmio_clrsetbits_32(CTL_REG(i, 215), 0x3f << 16, + (tmp & 0x3f) << 16); + + mmio_clrsetbits_32(CTL_REG(i, 275), 0xffu << 24, + (get_pi_tdfi_phy_rdlat(pdram_timing, + timing_config) & + 0xff) << 24); + + mmio_clrsetbits_32(CTL_REG(i, 284), 0xffffu << 16, + ((2 * pdram_timing->trefi) & 0xffff) << 16); + + mmio_clrsetbits_32(CTL_REG(i, 289), 0xffff, + (2 * pdram_timing->trefi) & 0xffff); + + mmio_write_32(CTL_REG(i, 290), 20 * pdram_timing->trefi); + + /* CTL_309 TDFI_CALVL_CAPTURE_F1:RW:16:10 */ + tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; + if ((20000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; + mmio_clrsetbits_32(CTL_REG(i, 309), 0x3ff << 16, tmp << 16); + + /* CTL_309 TDFI_CALVL_CC_F1:RW:0:10 */ + tmp = tmp + 18; + mmio_clrsetbits_32(CTL_REG(i, 309), 0x3ff, tmp); + + /* CTL_314 TDFI_WRCSLAT_F1:RW:24:8 */ + tmp1 = get_pi_wrlat_adj(pdram_timing, timing_config); + if (timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) { + if (tmp1 == 0) + tmp = 0; + else if (tmp1 < 5) + tmp = tmp1 - 1; + else + tmp = tmp1 - 5; + } else { + tmp = tmp1 - 2; + } + + mmio_clrsetbits_32(CTL_REG(i, 314), 0xffu << 24, tmp << 24); + + /* CTL_314 TDFI_RDCSLAT_F1:RW:16:8 */ + if ((timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) && + (pdram_timing->cl >= 5)) + tmp = pdram_timing->cl - 5; + else + tmp = pdram_timing->cl - 2; + mmio_clrsetbits_32(CTL_REG(i, 314), 0xff << 16, tmp << 16); + } +} + +static void gen_rk3399_enable_training(uint32_t ch_cnt, uint32_t nmhz) +{ + uint32_t i, tmp; + + if (nmhz <= PHY_DLL_BYPASS_FREQ) + tmp = 0; + else + tmp = 1; + + for (i = 0; i < ch_cnt; i++) { + mmio_clrsetbits_32(CTL_REG(i, 305), 1 << 16, tmp << 16); + mmio_clrsetbits_32(CTL_REG(i, 71), 1, tmp); + mmio_clrsetbits_32(CTL_REG(i, 70), 1 << 8, 1 << 8); + } +} + +static void gen_rk3399_disable_training(uint32_t ch_cnt) +{ + uint32_t i; + + for (i = 0; i < ch_cnt; i++) { + mmio_clrbits_32(CTL_REG(i, 305), 1 << 16); + mmio_clrbits_32(CTL_REG(i, 71), 1); + mmio_clrbits_32(CTL_REG(i, 70), 1 << 8); + } +} + +static void gen_rk3399_ctl_params(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing, + uint32_t fn) +{ + if (fn == 0) + gen_rk3399_ctl_params_f0(timing_config, pdram_timing); + else + gen_rk3399_ctl_params_f1(timing_config, pdram_timing); +} + +static void gen_rk3399_pi_params_f0(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t tmp, tmp1, tmp2; + uint32_t i; + + for (i = 0; i < timing_config->ch_cnt; i++) { + /* PI_02 PI_TDFI_PHYMSTR_MAX_F0:RW:0:32 */ + tmp = 4 * pdram_timing->trefi; + mmio_write_32(PI_REG(i, 2), tmp); + /* PI_03 PI_TDFI_PHYMSTR_RESP_F0:RW:0:16 */ + tmp = 2 * pdram_timing->trefi; + mmio_clrsetbits_32(PI_REG(i, 3), 0xffff, tmp); + /* PI_07 PI_TDFI_PHYUPD_RESP_F0:RW:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 7), 0xffffu << 16, tmp << 16); + + /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F0:RW:0:8 */ + if (timing_config->dram_type == LPDDR4) + tmp = 2; + else + tmp = 0; + tmp = (pdram_timing->bl / 2) + 4 + + (get_pi_rdlat_adj(pdram_timing) - 2) + tmp + + get_pi_tdfi_phy_rdlat(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 42), 0xff, tmp); + /* PI_43 PI_WRLAT_F0:RW:0:5 */ + if (timing_config->dram_type == LPDDR3) { + tmp = get_pi_wrlat(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 43), 0x1f, tmp); + } + /* PI_43 PI_ADDITIVE_LAT_F0:RW:8:6 */ + mmio_clrsetbits_32(PI_REG(i, 43), 0x3f << 8, + PI_ADD_LATENCY << 8); + + /* PI_43 PI_CASLAT_LIN_F0:RW:16:7 */ + mmio_clrsetbits_32(PI_REG(i, 43), 0x7f << 16, + (pdram_timing->cl * 2) << 16); + /* PI_46 PI_TREF_F0:RW:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 46), 0xffffu << 16, + pdram_timing->trefi << 16); + /* PI_46 PI_TRFC_F0:RW:0:10 */ + mmio_clrsetbits_32(PI_REG(i, 46), 0x3ff, pdram_timing->trfc); + /* PI_66 PI_TODTL_2CMD_F0:RW:24:8 */ + if (timing_config->dram_type == LPDDR3) { + tmp = get_pi_todtoff_max(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 66), 0xffu << 24, + tmp << 24); + } + /* PI_72 PI_WR_TO_ODTH_F0:RW:16:6 */ + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + tmp1 = get_pi_wrlat(pdram_timing, timing_config); + tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); + if (tmp1 > tmp2) + tmp = tmp1 - tmp2; + else + tmp = 0; + } else if (timing_config->dram_type == DDR3) { + tmp = 0; + } + mmio_clrsetbits_32(PI_REG(i, 72), 0x3f << 16, tmp << 16); + /* PI_73 PI_RD_TO_ODTH_F0:RW:8:6 */ + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + /* min_rl_preamble = cl + TDQSCK_MIN - 1 */ + tmp1 = pdram_timing->cl; + tmp1 += get_pi_todtoff_min(pdram_timing, timing_config); + tmp1--; + /* todtoff_max */ + tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); + if (tmp1 > tmp2) + tmp = tmp1 - tmp2; + else + tmp = 0; + } else if (timing_config->dram_type == DDR3) { + tmp = pdram_timing->cl - pdram_timing->cwl; + } + mmio_clrsetbits_32(PI_REG(i, 73), 0x3f << 8, tmp << 8); + /* PI_89 PI_RDLAT_ADJ_F0:RW:16:8 */ + tmp = get_pi_rdlat_adj(pdram_timing); + mmio_clrsetbits_32(PI_REG(i, 89), 0xff << 16, tmp << 16); + /* PI_90 PI_WRLAT_ADJ_F0:RW:16:8 */ + tmp = get_pi_wrlat_adj(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 90), 0xff << 16, tmp << 16); + /* PI_91 PI_TDFI_WRCSLAT_F0:RW:16:8 */ + tmp1 = tmp; + if (tmp1 == 0) + tmp = 0; + else if (tmp1 < 5) + tmp = tmp1 - 1; + else + tmp = tmp1 - 5; + mmio_clrsetbits_32(PI_REG(i, 91), 0xff << 16, tmp << 16); + /* PI_95 PI_TDFI_CALVL_CAPTURE_F0:RW:16:10 */ + tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; + if ((20000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; + mmio_clrsetbits_32(PI_REG(i, 95), 0x3ff << 16, tmp << 16); + /* PI_95 PI_TDFI_CALVL_CC_F0:RW:0:10 */ + mmio_clrsetbits_32(PI_REG(i, 95), 0x3ff, tmp + 18); + /* PI_102 PI_TMRZ_F0:RW:8:5 */ + mmio_clrsetbits_32(PI_REG(i, 102), 0x1f << 8, + pdram_timing->tmrz << 8); + /* PI_111 PI_TDFI_CALVL_STROBE_F0:RW:8:4 */ + tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz); + if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + /* pi_tdfi_calvl_strobe=tds_train+5 */ + tmp = tmp1 + 5; + mmio_clrsetbits_32(PI_REG(i, 111), 0xf << 8, tmp << 8); + /* PI_116 PI_TCKEHDQS_F0:RW:16:6 */ + tmp = 10000 / (1000000 / pdram_timing->mhz); + if ((10000 % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + if (pdram_timing->mhz <= 100) + tmp = tmp + 1; + else + tmp = tmp + 8; + mmio_clrsetbits_32(PI_REG(i, 116), 0x3f << 16, tmp << 16); + /* PI_125 PI_MR1_DATA_F0_0:RW+:8:16 */ + mmio_clrsetbits_32(PI_REG(i, 125), 0xffff << 8, + pdram_timing->mr[1] << 8); + /* PI_133 PI_MR1_DATA_F0_1:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 133), 0xffff, pdram_timing->mr[1]); + /* PI_140 PI_MR1_DATA_F0_2:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 140), 0xffffu << 16, + pdram_timing->mr[1] << 16); + /* PI_148 PI_MR1_DATA_F0_3:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 148), 0xffff, pdram_timing->mr[1]); + /* PI_126 PI_MR2_DATA_F0_0:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 126), 0xffff, pdram_timing->mr[2]); + /* PI_133 PI_MR2_DATA_F0_1:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 133), 0xffffu << 16, + pdram_timing->mr[2] << 16); + /* PI_141 PI_MR2_DATA_F0_2:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 141), 0xffff, pdram_timing->mr[2]); + /* PI_148 PI_MR2_DATA_F0_3:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 148), 0xffffu << 16, + pdram_timing->mr[2] << 16); + /* PI_156 PI_TFC_F0:RW:0:10 */ + mmio_clrsetbits_32(PI_REG(i, 156), 0x3ff, + pdram_timing->tfc_long); + /* PI_158 PI_TWR_F0:RW:24:6 */ + mmio_clrsetbits_32(PI_REG(i, 158), 0x3f << 24, + pdram_timing->twr << 24); + /* PI_158 PI_TWTR_F0:RW:16:6 */ + mmio_clrsetbits_32(PI_REG(i, 158), 0x3f << 16, + pdram_timing->twtr << 16); + /* PI_158 PI_TRCD_F0:RW:8:8 */ + mmio_clrsetbits_32(PI_REG(i, 158), 0xff << 8, + pdram_timing->trcd << 8); + /* PI_158 PI_TRP_F0:RW:0:8 */ + mmio_clrsetbits_32(PI_REG(i, 158), 0xff, pdram_timing->trp); + /* PI_157 PI_TRTP_F0:RW:24:8 */ + mmio_clrsetbits_32(PI_REG(i, 157), 0xffu << 24, + pdram_timing->trtp << 24); + /* PI_159 PI_TRAS_MIN_F0:RW:24:8 */ + mmio_clrsetbits_32(PI_REG(i, 159), 0xffu << 24, + pdram_timing->tras_min << 24); + /* PI_159 PI_TRAS_MAX_F0:RW:0:17 */ + tmp = pdram_timing->tras_max * 99 / 100; + mmio_clrsetbits_32(PI_REG(i, 159), 0x1ffff, tmp); + /* PI_160 PI_TMRD_F0:RW:16:6 */ + mmio_clrsetbits_32(PI_REG(i, 160), 0x3f << 16, + pdram_timing->tmrd << 16); + /*PI_160 PI_TDQSCK_MAX_F0:RW:0:4 */ + mmio_clrsetbits_32(PI_REG(i, 160), 0xf, + pdram_timing->tdqsck_max); + /* PI_187 PI_TDFI_CTRLUPD_MAX_F0:RW:8:16 */ + mmio_clrsetbits_32(PI_REG(i, 187), 0xffff << 8, + (2 * pdram_timing->trefi) << 8); + /* PI_188 PI_TDFI_CTRLUPD_INTERVAL_F0:RW:0:32 */ + mmio_clrsetbits_32(PI_REG(i, 188), 0xffffffff, + 20 * pdram_timing->trefi); + } +} + +static void gen_rk3399_pi_params_f1(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t tmp, tmp1, tmp2; + uint32_t i; + + for (i = 0; i < timing_config->ch_cnt; i++) { + /* PI_04 PI_TDFI_PHYMSTR_MAX_F1:RW:0:32 */ + tmp = 4 * pdram_timing->trefi; + mmio_write_32(PI_REG(i, 4), tmp); + /* PI_05 PI_TDFI_PHYMSTR_RESP_F1:RW:0:16 */ + tmp = 2 * pdram_timing->trefi; + mmio_clrsetbits_32(PI_REG(i, 5), 0xffff, tmp); + /* PI_12 PI_TDFI_PHYUPD_RESP_F1:RW:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 12), 0xffff, tmp); + + /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F1:RW:8:8 */ + if (timing_config->dram_type == LPDDR4) + tmp = 2; + else + tmp = 0; + tmp = (pdram_timing->bl / 2) + 4 + + (get_pi_rdlat_adj(pdram_timing) - 2) + tmp + + get_pi_tdfi_phy_rdlat(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 42), 0xff << 8, tmp << 8); + /* PI_43 PI_WRLAT_F1:RW:24:5 */ + if (timing_config->dram_type == LPDDR3) { + tmp = get_pi_wrlat(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 43), 0x1f << 24, + tmp << 24); + } + /* PI_44 PI_ADDITIVE_LAT_F1:RW:0:6 */ + mmio_clrsetbits_32(PI_REG(i, 44), 0x3f, PI_ADD_LATENCY); + /* PI_44 PI_CASLAT_LIN_F1:RW:8:7:=0x18 */ + mmio_clrsetbits_32(PI_REG(i, 44), 0x7f << 8, + (pdram_timing->cl * 2) << 8); + /* PI_47 PI_TREF_F1:RW:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 47), 0xffffu << 16, + pdram_timing->trefi << 16); + /* PI_47 PI_TRFC_F1:RW:0:10 */ + mmio_clrsetbits_32(PI_REG(i, 47), 0x3ff, pdram_timing->trfc); + /* PI_67 PI_TODTL_2CMD_F1:RW:8:8 */ + if (timing_config->dram_type == LPDDR3) { + tmp = get_pi_todtoff_max(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 67), 0xff << 8, tmp << 8); + } + /* PI_72 PI_WR_TO_ODTH_F1:RW:24:6 */ + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + tmp1 = get_pi_wrlat(pdram_timing, timing_config); + tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); + if (tmp1 > tmp2) + tmp = tmp1 - tmp2; + else + tmp = 0; + } else if (timing_config->dram_type == DDR3) { + tmp = 0; + } + mmio_clrsetbits_32(PI_REG(i, 72), 0x3f << 24, tmp << 24); + /* PI_73 PI_RD_TO_ODTH_F1:RW:16:6 */ + if ((timing_config->dram_type == LPDDR3) || + (timing_config->dram_type == LPDDR4)) { + /* min_rl_preamble = cl + TDQSCK_MIN - 1 */ + tmp1 = pdram_timing->cl + + get_pi_todtoff_min(pdram_timing, timing_config); + tmp1--; + /* todtoff_max */ + tmp2 = get_pi_todtoff_max(pdram_timing, timing_config); + if (tmp1 > tmp2) + tmp = tmp1 - tmp2; + else + tmp = 0; + } else if (timing_config->dram_type == DDR3) + tmp = pdram_timing->cl - pdram_timing->cwl; + + mmio_clrsetbits_32(PI_REG(i, 73), 0x3f << 16, tmp << 16); + /*P I_89 PI_RDLAT_ADJ_F1:RW:24:8 */ + tmp = get_pi_rdlat_adj(pdram_timing); + mmio_clrsetbits_32(PI_REG(i, 89), 0xffu << 24, tmp << 24); + /* PI_90 PI_WRLAT_ADJ_F1:RW:24:8 */ + tmp = get_pi_wrlat_adj(pdram_timing, timing_config); + mmio_clrsetbits_32(PI_REG(i, 90), 0xffu << 24, tmp << 24); + /* PI_91 PI_TDFI_WRCSLAT_F1:RW:24:8 */ + tmp1 = tmp; + if (tmp1 == 0) + tmp = 0; + else if (tmp1 < 5) + tmp = tmp1 - 1; + else + tmp = tmp1 - 5; + mmio_clrsetbits_32(PI_REG(i, 91), 0xffu << 24, tmp << 24); + /*PI_96 PI_TDFI_CALVL_CAPTURE_F1:RW:16:10 */ + /* tadr=20ns */ + tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1; + if ((20000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + tmp = (tmp1 >> 1) + (tmp1 % 2) + 5; + mmio_clrsetbits_32(PI_REG(i, 96), 0x3ff << 16, tmp << 16); + /* PI_96 PI_TDFI_CALVL_CC_F1:RW:0:10 */ + tmp = tmp + 18; + mmio_clrsetbits_32(PI_REG(i, 96), 0x3ff, tmp); + /*PI_103 PI_TMRZ_F1:RW:0:5 */ + mmio_clrsetbits_32(PI_REG(i, 103), 0x1f, pdram_timing->tmrz); + /*PI_111 PI_TDFI_CALVL_STROBE_F1:RW:16:4 */ + /* tds_train=ceil(2/ns) */ + tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz); + if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0) + tmp1++; + /* pi_tdfi_calvl_strobe=tds_train+5 */ + tmp = tmp1 + 5; + mmio_clrsetbits_32(PI_REG(i, 111), 0xf << 16, + tmp << 16); + /* PI_116 PI_TCKEHDQS_F1:RW:24:6 */ + tmp = 10000 / (1000000 / pdram_timing->mhz); + if ((10000 % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + if (pdram_timing->mhz <= 100) + tmp = tmp + 1; + else + tmp = tmp + 8; + mmio_clrsetbits_32(PI_REG(i, 116), 0x3f << 24, + tmp << 24); + /* PI_128 PI_MR1_DATA_F1_0:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 128), 0xffff, pdram_timing->mr[1]); + /* PI_135 PI_MR1_DATA_F1_1:RW+:8:16 */ + mmio_clrsetbits_32(PI_REG(i, 135), 0xffff << 8, + pdram_timing->mr[1] << 8); + /* PI_143 PI_MR1_DATA_F1_2:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 143), 0xffff, pdram_timing->mr[1]); + /* PI_150 PI_MR1_DATA_F1_3:RW+:8:16 */ + mmio_clrsetbits_32(PI_REG(i, 150), 0xffff << 8, + pdram_timing->mr[1] << 8); + /* PI_128 PI_MR2_DATA_F1_0:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 128), 0xffffu << 16, + pdram_timing->mr[2] << 16); + /* PI_136 PI_MR2_DATA_F1_1:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 136), 0xffff, pdram_timing->mr[2]); + /* PI_143 PI_MR2_DATA_F1_2:RW+:16:16 */ + mmio_clrsetbits_32(PI_REG(i, 143), 0xffffu << 16, + pdram_timing->mr[2] << 16); + /* PI_151 PI_MR2_DATA_F1_3:RW+:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 151), 0xffff, pdram_timing->mr[2]); + /* PI_156 PI_TFC_F1:RW:16:10 */ + mmio_clrsetbits_32(PI_REG(i, 156), 0x3ff << 16, + pdram_timing->tfc_long << 16); + /* PI_162 PI_TWR_F1:RW:8:6 */ + mmio_clrsetbits_32(PI_REG(i, 162), 0x3f << 8, + pdram_timing->twr << 8); + /* PI_162 PI_TWTR_F1:RW:0:6 */ + mmio_clrsetbits_32(PI_REG(i, 162), 0x3f, pdram_timing->twtr); + /* PI_161 PI_TRCD_F1:RW:24:8 */ + mmio_clrsetbits_32(PI_REG(i, 161), 0xffu << 24, + pdram_timing->trcd << 24); + /* PI_161 PI_TRP_F1:RW:16:8 */ + mmio_clrsetbits_32(PI_REG(i, 161), 0xff << 16, + pdram_timing->trp << 16); + /* PI_161 PI_TRTP_F1:RW:8:8 */ + mmio_clrsetbits_32(PI_REG(i, 161), 0xff << 8, + pdram_timing->trtp << 8); + /* PI_163 PI_TRAS_MIN_F1:RW:24:8 */ + mmio_clrsetbits_32(PI_REG(i, 163), 0xffu << 24, + pdram_timing->tras_min << 24); + /* PI_163 PI_TRAS_MAX_F1:RW:0:17 */ + mmio_clrsetbits_32(PI_REG(i, 163), 0x1ffff, + pdram_timing->tras_max * 99 / 100); + /* PI_164 PI_TMRD_F1:RW:16:6 */ + mmio_clrsetbits_32(PI_REG(i, 164), 0x3f << 16, + pdram_timing->tmrd << 16); + /* PI_164 PI_TDQSCK_MAX_F1:RW:0:4 */ + mmio_clrsetbits_32(PI_REG(i, 164), 0xf, + pdram_timing->tdqsck_max); + /* PI_189 PI_TDFI_CTRLUPD_MAX_F1:RW:0:16 */ + mmio_clrsetbits_32(PI_REG(i, 189), 0xffff, + 2 * pdram_timing->trefi); + /* PI_190 PI_TDFI_CTRLUPD_INTERVAL_F1:RW:0:32 */ + mmio_clrsetbits_32(PI_REG(i, 190), 0xffffffff, + 20 * pdram_timing->trefi); + } +} + +static void gen_rk3399_pi_params(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing, + uint32_t fn) +{ + if (fn == 0) + gen_rk3399_pi_params_f0(timing_config, pdram_timing); + else + gen_rk3399_pi_params_f1(timing_config, pdram_timing); +} + +static void gen_rk3399_set_odt(uint32_t odt_en) +{ + uint32_t drv_odt_val; + uint32_t i; + + for (i = 0; i < rk3399_dram_status.timing_config.ch_cnt; i++) { + drv_odt_val = (odt_en | (0 << 1) | (0 << 2)) << 16; + mmio_clrsetbits_32(PHY_REG(i, 5), 0x7 << 16, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 133), 0x7 << 16, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 261), 0x7 << 16, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 389), 0x7 << 16, drv_odt_val); + drv_odt_val = (odt_en | (0 << 1) | (0 << 2)) << 24; + mmio_clrsetbits_32(PHY_REG(i, 6), 0x7 << 24, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 134), 0x7 << 24, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 262), 0x7 << 24, drv_odt_val); + mmio_clrsetbits_32(PHY_REG(i, 390), 0x7 << 24, drv_odt_val); + } +} + +static void gen_rk3399_phy_dll_bypass(uint32_t mhz, uint32_t ch, + uint32_t index, uint32_t dram_type) +{ + uint32_t sw_master_mode = 0; + uint32_t rddqs_gate_delay, rddqs_latency, total_delay; + uint32_t i; + + if (dram_type == DDR3) + total_delay = PI_PAD_DELAY_PS_VALUE; + else if (dram_type == LPDDR3) + total_delay = PI_PAD_DELAY_PS_VALUE + 2500; + else + total_delay = PI_PAD_DELAY_PS_VALUE + 1500; + /* total_delay + 0.55tck */ + total_delay += (55 * 10000)/mhz; + rddqs_latency = total_delay * mhz / 1000000; + total_delay -= rddqs_latency * 1000000 / mhz; + rddqs_gate_delay = total_delay * 0x200 * mhz / 1000000; + if (mhz <= PHY_DLL_BYPASS_FREQ) { + sw_master_mode = 0xc; + mmio_setbits_32(PHY_REG(ch, 514), 1); + mmio_setbits_32(PHY_REG(ch, 642), 1); + mmio_setbits_32(PHY_REG(ch, 770), 1); + + /* setting bypass mode slave delay */ + for (i = 0; i < 4; i++) { + /* wr dq delay = -180deg + (0x60 / 4) * 20ps */ + mmio_clrsetbits_32(PHY_REG(ch, 1 + 128 * i), 0x7ff << 8, + 0x4a0 << 8); + /* rd dqs/dq delay = (0x60 / 4) * 20ps */ + mmio_clrsetbits_32(PHY_REG(ch, 11 + 128 * i), 0x3ff, + 0xa0); + /* rd rddqs_gate delay */ + mmio_clrsetbits_32(PHY_REG(ch, 2 + 128 * i), 0x3ff, + rddqs_gate_delay); + mmio_clrsetbits_32(PHY_REG(ch, 78 + 128 * i), 0xf, + rddqs_latency); + } + for (i = 0; i < 3; i++) + /* adr delay */ + mmio_clrsetbits_32(PHY_REG(ch, 513 + 128 * i), + 0x7ff << 16, 0x80 << 16); + + if ((mmio_read_32(PHY_REG(ch, 86)) & 0xc00) == 0) { + /* + * old status is normal mode, + * and saving the wrdqs slave delay + */ + for (i = 0; i < 4; i++) { + /* save and clear wr dqs slave delay */ + wrdqs_delay_val[ch][index][i] = 0x3ff & + (mmio_read_32(PHY_REG(ch, 63 + i * 128)) + >> 16); + mmio_clrsetbits_32(PHY_REG(ch, 63 + i * 128), + 0x03ff << 16, 0 << 16); + /* + * in normal mode the cmd may delay 1cycle by + * wrlvl and in bypass mode making dqs also + * delay 1cycle. + */ + mmio_clrsetbits_32(PHY_REG(ch, 78 + i * 128), + 0x07 << 8, 0x1 << 8); + } + } + } else if (mmio_read_32(PHY_REG(ch, 86)) & 0xc00) { + /* old status is bypass mode and restore wrlvl resume */ + for (i = 0; i < 4; i++) { + mmio_clrsetbits_32(PHY_REG(ch, 63 + i * 128), + 0x03ff << 16, + (wrdqs_delay_val[ch][index][i] & + 0x3ff) << 16); + /* resume phy_write_path_lat_add */ + mmio_clrbits_32(PHY_REG(ch, 78 + i * 128), 0x07 << 8); + } + } + + /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */ + mmio_clrsetbits_32(PHY_REG(ch, 86), 0xf << 8, sw_master_mode << 8); + mmio_clrsetbits_32(PHY_REG(ch, 214), 0xf << 8, sw_master_mode << 8); + mmio_clrsetbits_32(PHY_REG(ch, 342), 0xf << 8, sw_master_mode << 8); + mmio_clrsetbits_32(PHY_REG(ch, 470), 0xf << 8, sw_master_mode << 8); + + /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */ + mmio_clrsetbits_32(PHY_REG(ch, 547), 0xf << 16, sw_master_mode << 16); + mmio_clrsetbits_32(PHY_REG(ch, 675), 0xf << 16, sw_master_mode << 16); + mmio_clrsetbits_32(PHY_REG(ch, 803), 0xf << 16, sw_master_mode << 16); +} + +static void gen_rk3399_phy_params(struct timing_related_config *timing_config, + struct drv_odt_lp_config *drv_config, + struct dram_timing_t *pdram_timing, + uint32_t fn) +{ + uint32_t tmp, i, div, j; + uint32_t mem_delay_ps, pad_delay_ps, total_delay_ps, delay_frac_ps; + uint32_t trpre_min_ps, gate_delay_ps, gate_delay_frac_ps; + uint32_t ie_enable, tsel_enable, cas_lat, rddata_en_ie_dly, tsel_adder; + uint32_t extra_adder, delta, hs_offset; + + for (i = 0; i < timing_config->ch_cnt; i++) { + + pad_delay_ps = PI_PAD_DELAY_PS_VALUE; + ie_enable = PI_IE_ENABLE_VALUE; + tsel_enable = PI_TSEL_ENABLE_VALUE; + + mmio_clrsetbits_32(PHY_REG(i, 896), (0x3 << 8) | 1, fn << 8); + + /* PHY_LOW_FREQ_SEL */ + /* DENALI_PHY_913 1bit offset_0 */ + if (timing_config->freq > 400) + mmio_clrbits_32(PHY_REG(i, 913), 1); + else + mmio_setbits_32(PHY_REG(i, 913), 1); + + /* PHY_RPTR_UPDATE_x */ + /* DENALI_PHY_87/215/343/471 4bit offset_16 */ + tmp = 2500 / (1000000 / pdram_timing->mhz) + 3; + if ((2500 % (1000000 / pdram_timing->mhz)) != 0) + tmp++; + mmio_clrsetbits_32(PHY_REG(i, 87), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 215), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 343), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 471), 0xf << 16, tmp << 16); + + /* PHY_PLL_CTRL */ + /* DENALI_PHY_911 13bits offset_0 */ + /* PHY_LP4_BOOT_PLL_CTRL */ + /* DENALI_PHY_919 13bits offset_0 */ + tmp = (1 << 12) | (2 << 7) | (1 << 1); + mmio_clrsetbits_32(PHY_REG(i, 911), 0x1fff, tmp); + mmio_clrsetbits_32(PHY_REG(i, 919), 0x1fff, tmp); + + /* PHY_PLL_CTRL_CA */ + /* DENALI_PHY_911 13bits offset_16 */ + /* PHY_LP4_BOOT_PLL_CTRL_CA */ + /* DENALI_PHY_919 13bits offset_16 */ + tmp = (2 << 7) | (1 << 5) | (1 << 1); + mmio_clrsetbits_32(PHY_REG(i, 911), 0x1fff << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 919), 0x1fff << 16, tmp << 16); + + /* PHY_TCKSRE_WAIT */ + /* DENALI_PHY_922 4bits offset_24 */ + if (pdram_timing->mhz <= 400) + tmp = 1; + else if (pdram_timing->mhz <= 800) + tmp = 3; + else if (pdram_timing->mhz <= 1000) + tmp = 4; + else + tmp = 5; + mmio_clrsetbits_32(PHY_REG(i, 922), 0xf << 24, tmp << 24); + /* PHY_CAL_CLK_SELECT_0:RW8:3 */ + div = pdram_timing->mhz / (2 * 20); + for (j = 2, tmp = 1; j <= 128; j <<= 1, tmp++) { + if (div < j) + break; + } + mmio_clrsetbits_32(PHY_REG(i, 947), 0x7 << 8, tmp << 8); + + if (timing_config->dram_type == DDR3) { + mem_delay_ps = 0; + trpre_min_ps = 1000; + } else if (timing_config->dram_type == LPDDR4) { + mem_delay_ps = 1500; + trpre_min_ps = 900; + } else if (timing_config->dram_type == LPDDR3) { + mem_delay_ps = 2500; + trpre_min_ps = 900; + } else { + ERROR("gen_rk3399_phy_params:dramtype unsupport\n"); + return; + } + total_delay_ps = mem_delay_ps + pad_delay_ps; + delay_frac_ps = 1000 * total_delay_ps / + (1000000 / pdram_timing->mhz); + gate_delay_ps = delay_frac_ps + 1000 - (trpre_min_ps / 2); + gate_delay_frac_ps = gate_delay_ps % 1000; + tmp = gate_delay_frac_ps * 0x200 / 1000; + /* PHY_RDDQS_GATE_SLAVE_DELAY */ + /* DENALI_PHY_77/205/333/461 10bits offset_16 */ + mmio_clrsetbits_32(PHY_REG(i, 77), 0x2ff << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 205), 0x2ff << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 333), 0x2ff << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 461), 0x2ff << 16, tmp << 16); + + tmp = gate_delay_ps / 1000; + /* PHY_LP4_BOOT_RDDQS_LATENCY_ADJUST */ + /* DENALI_PHY_10/138/266/394 4bit offset_0 */ + mmio_clrsetbits_32(PHY_REG(i, 10), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 138), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 266), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 394), 0xf, tmp); + /* PHY_GTLVL_LAT_ADJ_START */ + /* DENALI_PHY_80/208/336/464 4bits offset_16 */ + tmp = rddqs_delay_ps / (1000000 / pdram_timing->mhz) + 2; + mmio_clrsetbits_32(PHY_REG(i, 80), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 208), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 336), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 464), 0xf << 16, tmp << 16); + + cas_lat = pdram_timing->cl + PI_ADD_LATENCY; + rddata_en_ie_dly = ie_enable / (1000000 / pdram_timing->mhz); + if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0) + rddata_en_ie_dly++; + rddata_en_ie_dly = rddata_en_ie_dly - 1; + tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz); + if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0) + tsel_adder++; + if (rddata_en_ie_dly > tsel_adder) + extra_adder = rddata_en_ie_dly - tsel_adder; + else + extra_adder = 0; + delta = cas_lat - rddata_en_ie_dly; + if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK) + hs_offset = 2; + else + hs_offset = 1; + if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset)) + tmp = 0; + else if ((delta == 2) || (delta == 1)) + tmp = rddata_en_ie_dly - 0 - extra_adder; + else + tmp = extra_adder; + /* PHY_LP4_BOOT_RDDATA_EN_TSEL_DLY */ + /* DENALI_PHY_9/137/265/393 4bit offset_16 */ + mmio_clrsetbits_32(PHY_REG(i, 9), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 137), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 265), 0xf << 16, tmp << 16); + mmio_clrsetbits_32(PHY_REG(i, 393), 0xf << 16, tmp << 16); + /* PHY_RDDATA_EN_TSEL_DLY */ + /* DENALI_PHY_86/214/342/470 4bit offset_0 */ + mmio_clrsetbits_32(PHY_REG(i, 86), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 214), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 342), 0xf, tmp); + mmio_clrsetbits_32(PHY_REG(i, 470), 0xf, tmp); + + if (tsel_adder > rddata_en_ie_dly) + extra_adder = tsel_adder - rddata_en_ie_dly; + else + extra_adder = 0; + if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset)) + tmp = tsel_adder; + else + tmp = rddata_en_ie_dly - 0 + extra_adder; + /* PHY_LP4_BOOT_RDDATA_EN_DLY */ + /* DENALI_PHY_9/137/265/393 4bit offset_8 */ + mmio_clrsetbits_32(PHY_REG(i, 9), 0xf << 8, tmp << 8); + mmio_clrsetbits_32(PHY_REG(i, 137), 0xf << 8, tmp << 8); + mmio_clrsetbits_32(PHY_REG(i, 265), 0xf << 8, tmp << 8); + mmio_clrsetbits_32(PHY_REG(i, 393), 0xf << 8, tmp << 8); + /* PHY_RDDATA_EN_DLY */ + /* DENALI_PHY_85/213/341/469 4bit offset_24 */ + mmio_clrsetbits_32(PHY_REG(i, 85), 0xf << 24, tmp << 24); + mmio_clrsetbits_32(PHY_REG(i, 213), 0xf << 24, tmp << 24); + mmio_clrsetbits_32(PHY_REG(i, 341), 0xf << 24, tmp << 24); + mmio_clrsetbits_32(PHY_REG(i, 469), 0xf << 24, tmp << 24); + + if (pdram_timing->mhz <= ENPER_CS_TRAINING_FREQ) { + /* + * Note:Per-CS Training is not compatible at speeds + * under 533 MHz. If the PHY is running at a speed + * less than 533MHz, all phy_per_cs_training_en_X + * parameters must be cleared to 0. + */ + + /*DENALI_PHY_84/212/340/468 1bit offset_16 */ + mmio_clrbits_32(PHY_REG(i, 84), 0x1 << 16); + mmio_clrbits_32(PHY_REG(i, 212), 0x1 << 16); + mmio_clrbits_32(PHY_REG(i, 340), 0x1 << 16); + mmio_clrbits_32(PHY_REG(i, 468), 0x1 << 16); + } else { + mmio_setbits_32(PHY_REG(i, 84), 0x1 << 16); + mmio_setbits_32(PHY_REG(i, 212), 0x1 << 16); + mmio_setbits_32(PHY_REG(i, 340), 0x1 << 16); + mmio_setbits_32(PHY_REG(i, 468), 0x1 << 16); + } + gen_rk3399_phy_dll_bypass(pdram_timing->mhz, i, fn, + timing_config->dram_type); + } +} + +static int to_get_clk_index(unsigned int mhz) +{ + int pll_cnt, i; + + pll_cnt = ARRAY_SIZE(dpll_rates_table); + + /* Assumming rate_table is in descending order */ + for (i = 0; i < pll_cnt; i++) { + if (mhz >= dpll_rates_table[i].mhz) + break; + } + + /* if mhz lower than lowest frequency in table, use lowest frequency */ + if (i == pll_cnt) + i = pll_cnt - 1; + + return i; +} + +uint32_t ddr_get_rate(void) +{ + uint32_t refdiv, postdiv1, fbdiv, postdiv2; + + refdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) & 0x3f; + fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff; + postdiv1 = + (mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) >> 8) & 0x7; + postdiv2 = + (mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) >> 12) & 0x7; + + return (24 / refdiv * fbdiv / postdiv1 / postdiv2) * 1000 * 1000; +} + +/* + * return: bit12: channel 1, external self-refresh + * bit11: channel 1, stdby_mode + * bit10: channel 1, self-refresh with controller and memory clock gate + * bit9: channel 1, self-refresh + * bit8: channel 1, power-down + * + * bit4: channel 1, external self-refresh + * bit3: channel 0, stdby_mode + * bit2: channel 0, self-refresh with controller and memory clock gate + * bit1: channel 0, self-refresh + * bit0: channel 0, power-down + */ +uint32_t exit_low_power(void) +{ + uint32_t low_power = 0; + uint32_t channel_mask; + uint32_t tmp, i; + + channel_mask = (mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2)) >> 28) & + 0x3; + for (i = 0; i < 2; i++) { + if (!(channel_mask & (1 << i))) + continue; + + /* exit stdby mode */ + mmio_write_32(CIC_BASE + CIC_CTRL1, + (1 << (i + 16)) | (0 << i)); + /* exit external self-refresh */ + tmp = i ? 12 : 8; + low_power |= ((mmio_read_32(PMU_BASE + PMU_SFT_CON) >> tmp) & + 0x1) << (4 + 8 * i); + mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 1 << tmp); + while (!(mmio_read_32(PMU_BASE + PMU_DDR_SREF_ST) & (1 << i))) + ; + /* exit auto low-power */ + mmio_clrbits_32(CTL_REG(i, 101), 0x7); + /* lp_cmd to exit */ + if (((mmio_read_32(CTL_REG(i, 100)) >> 24) & 0x7f) != + 0x40) { + while (mmio_read_32(CTL_REG(i, 200)) & 0x1) + ; + mmio_clrsetbits_32(CTL_REG(i, 93), 0xffu << 24, + 0x69 << 24); + while (((mmio_read_32(CTL_REG(i, 100)) >> 24) & 0x7f) != + 0x40) + ; + } + } + return low_power; +} + +void resume_low_power(uint32_t low_power) +{ + uint32_t channel_mask; + uint32_t tmp, i, val; + + channel_mask = (mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2)) >> 28) & + 0x3; + for (i = 0; i < 2; i++) { + if (!(channel_mask & (1 << i))) + continue; + + /* resume external self-refresh */ + tmp = i ? 12 : 8; + val = (low_power >> (4 + 8 * i)) & 0x1; + mmio_setbits_32(PMU_BASE + PMU_SFT_CON, val << tmp); + /* resume auto low-power */ + val = (low_power >> (8 * i)) & 0x7; + mmio_setbits_32(CTL_REG(i, 101), val); + /* resume stdby mode */ + val = (low_power >> (3 + 8 * i)) & 0x1; + mmio_write_32(CIC_BASE + CIC_CTRL1, + (1 << (i + 16)) | (val << i)); + } +} + +static void dram_low_power_config(void) +{ + uint32_t tmp, i; + uint32_t ch_cnt = rk3399_dram_status.timing_config.ch_cnt; + uint32_t dram_type = rk3399_dram_status.timing_config.dram_type; + + if (dram_type == DDR3) + tmp = (2 << 16) | (0x7 << 8); + else + tmp = (3 << 16) | (0x7 << 8); + + for (i = 0; i < ch_cnt; i++) + mmio_clrsetbits_32(CTL_REG(i, 101), 0x70f0f, tmp); + + /* standby idle */ + mmio_write_32(CIC_BASE + CIC_CG_WAIT_TH, 0x640008); + + if (ch_cnt == 2) { + mmio_write_32(GRF_BASE + GRF_DDRC1_CON1, + (((0x1<<4) | (0x1<<5) | (0x1<<6) | + (0x1<<7)) << 16) | + ((0x1<<4) | (0x0<<5) | (0x1<<6) | (0x1<<7))); + mmio_write_32(CIC_BASE + CIC_CTRL1, 0x002a0028); + } + + mmio_write_32(GRF_BASE + GRF_DDRC0_CON1, + (((0x1<<4) | (0x1<<5) | (0x1<<6) | (0x1<<7)) << 16) | + ((0x1<<4) | (0x0<<5) | (0x1<<6) | (0x1<<7))); + mmio_write_32(CIC_BASE + CIC_CTRL1, 0x00150014); +} + +void dram_dfs_init(void) +{ + uint32_t trefi0, trefi1, boot_freq; + uint32_t rddqs_adjust, rddqs_slave; + + /* get sdram config for os reg */ + get_dram_drv_odt_val(sdram_config.dramtype, + &rk3399_dram_status.drv_odt_lp_cfg); + sdram_timing_cfg_init(&rk3399_dram_status.timing_config, + &sdram_config, + &rk3399_dram_status.drv_odt_lp_cfg); + + trefi0 = ((mmio_read_32(CTL_REG(0, 48)) >> 16) & 0xffff) + 8; + trefi1 = ((mmio_read_32(CTL_REG(0, 49)) >> 16) & 0xffff) + 8; + + rk3399_dram_status.index_freq[0] = trefi0 * 10 / 39; + rk3399_dram_status.index_freq[1] = trefi1 * 10 / 39; + rk3399_dram_status.current_index = + (mmio_read_32(CTL_REG(0, 111)) >> 16) & 0x3; + if (rk3399_dram_status.timing_config.dram_type == DDR3) { + rk3399_dram_status.index_freq[0] /= 2; + rk3399_dram_status.index_freq[1] /= 2; + } + boot_freq = + rk3399_dram_status.index_freq[rk3399_dram_status.current_index]; + boot_freq = dpll_rates_table[to_get_clk_index(boot_freq)].mhz; + rk3399_dram_status.boot_freq = boot_freq; + rk3399_dram_status.index_freq[rk3399_dram_status.current_index] = + boot_freq; + rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1) & + 0x1] = 0; + rk3399_dram_status.low_power_stat = 0; + /* + * following register decide if NOC stall the access request + * or return error when NOC being idled. when doing ddr frequency + * scaling in M0 or DCF, we need to make sure noc stall the access + * request, if return error cpu may data abort when ddr frequency + * changing. it don't need to set this register every times, + * so we init this register in function dram_dfs_init(). + */ + mmio_write_32(GRF_BASE + GRF_SOC_CON(0), 0xffffffff); + mmio_write_32(GRF_BASE + GRF_SOC_CON(1), 0xffffffff); + mmio_write_32(GRF_BASE + GRF_SOC_CON(2), 0xffffffff); + mmio_write_32(GRF_BASE + GRF_SOC_CON(3), 0xffffffff); + mmio_write_32(GRF_BASE + GRF_SOC_CON(4), 0x70007000); + + /* Disable multicast */ + mmio_clrbits_32(PHY_REG(0, 896), 1); + mmio_clrbits_32(PHY_REG(1, 896), 1); + dram_low_power_config(); + + /* + * If boot_freq isn't in the bypass mode, it can get the + * rddqs_delay_ps from the result of gate training + */ + if (((mmio_read_32(PHY_REG(0, 86)) >> 8) & 0xf) != 0xc) { + + /* + * Select PHY's frequency set to current_index + * index for get the result of gate Training + * from registers + */ + mmio_clrsetbits_32(PHY_REG(0, 896), 0x3 << 8, + rk3399_dram_status.current_index << 8); + rddqs_slave = (mmio_read_32(PHY_REG(0, 77)) >> 16) & 0x3ff; + rddqs_slave = rddqs_slave * 1000000 / boot_freq / 512; + + rddqs_adjust = mmio_read_32(PHY_REG(0, 78)) & 0xf; + rddqs_adjust = rddqs_adjust * 1000000 / boot_freq; + rddqs_delay_ps = rddqs_slave + rddqs_adjust - + (1000000 / boot_freq / 2); + } else { + rddqs_delay_ps = 3500; + } +} + +/* + * arg0: bit0-7: sr_idle; bit8-15:sr_mc_gate_idle; bit16-31: standby idle + * arg1: bit0-11: pd_idle; bit 16-27: srpd_lite_idle + * arg2: bit0: if odt en + */ +uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2) +{ + struct drv_odt_lp_config *lp_cfg = &rk3399_dram_status.drv_odt_lp_cfg; + uint32_t *low_power = &rk3399_dram_status.low_power_stat; + uint32_t dram_type, ch_count, pd_tmp, sr_tmp, i; + + dram_type = rk3399_dram_status.timing_config.dram_type; + ch_count = rk3399_dram_status.timing_config.ch_cnt; + + lp_cfg->sr_idle = arg0 & 0xff; + lp_cfg->sr_mc_gate_idle = (arg0 >> 8) & 0xff; + lp_cfg->standby_idle = (arg0 >> 16) & 0xffff; + lp_cfg->pd_idle = arg1 & 0xfff; + lp_cfg->srpd_lite_idle = (arg1 >> 16) & 0xfff; + + rk3399_dram_status.timing_config.odt = arg2 & 0x1; + + exit_low_power(); + + *low_power = 0; + + /* pd_idle en */ + if (lp_cfg->pd_idle) + *low_power |= ((1 << 0) | (1 << 8)); + /* sr_idle en srpd_lite_idle */ + if (lp_cfg->sr_idle | lp_cfg->srpd_lite_idle) + *low_power |= ((1 << 1) | (1 << 9)); + /* sr_mc_gate_idle */ + if (lp_cfg->sr_mc_gate_idle) + *low_power |= ((1 << 2) | (1 << 10)); + /* standbyidle */ + if (lp_cfg->standby_idle) { + if (rk3399_dram_status.timing_config.ch_cnt == 2) + *low_power |= ((1 << 3) | (1 << 11)); + else + *low_power |= (1 << 3); + } + + pd_tmp = arg1; + if (dram_type != LPDDR4) + pd_tmp = arg1 & 0xfff; + sr_tmp = arg0 & 0xffff; + for (i = 0; i < ch_count; i++) { + mmio_write_32(CTL_REG(i, 102), pd_tmp); + mmio_clrsetbits_32(CTL_REG(i, 103), 0xffff, sr_tmp); + } + mmio_write_32(CIC_BASE + CIC_IDLE_TH, (arg0 >> 16) & 0xffff); + + return 0; +} + +static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index) +{ + mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(pll_div.fbdiv)); + mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON1, + POSTDIV2(pll_div.postdiv2) | POSTDIV1(pll_div.postdiv1) | + REFDIV(pll_div.refdiv)); + + mmio_write_32(M0_PARAM_ADDR + PARAM_DRAM_FREQ, pll_div.mhz); + + mmio_write_32(M0_PARAM_ADDR + PARAM_FREQ_SELECT, ddr_index << 4); + dmbst(); + m0_configure_execute_addr(M0_BINCODE_BASE); +} + +static uint32_t prepare_ddr_timing(uint32_t mhz) +{ + uint32_t index; + struct dram_timing_t dram_timing; + + rk3399_dram_status.timing_config.freq = mhz; + + if (mhz < 300) + rk3399_dram_status.timing_config.dllbp = 1; + else + rk3399_dram_status.timing_config.dllbp = 0; + + if (rk3399_dram_status.timing_config.odt == 1) + gen_rk3399_set_odt(1); + + index = (rk3399_dram_status.current_index + 1) & 0x1; + + /* + * checking if having available gate traiing timing for + * target freq. + */ + dram_get_parameter(&rk3399_dram_status.timing_config, &dram_timing); + gen_rk3399_ctl_params(&rk3399_dram_status.timing_config, + &dram_timing, index); + gen_rk3399_pi_params(&rk3399_dram_status.timing_config, + &dram_timing, index); + gen_rk3399_phy_params(&rk3399_dram_status.timing_config, + &rk3399_dram_status.drv_odt_lp_cfg, + &dram_timing, index); + rk3399_dram_status.index_freq[index] = mhz; + + return index; +} + +uint32_t ddr_set_rate(uint32_t hz) +{ + uint32_t low_power, index, ddr_index; + uint32_t mhz = hz / (1000 * 1000); + + if (mhz == + rk3399_dram_status.index_freq[rk3399_dram_status.current_index]) + return mhz; + + index = to_get_clk_index(mhz); + mhz = dpll_rates_table[index].mhz; + + ddr_index = prepare_ddr_timing(mhz); + gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt, + mhz); + if (ddr_index > 1) + goto out; + + /* + * Make sure the clock is enabled. The M0 clocks should be on all of the + * time during S0. + */ + m0_configure_ddr(dpll_rates_table[index], ddr_index); + m0_start(); + m0_wait_done(); + m0_stop(); + + if (rk3399_dram_status.timing_config.odt == 0) + gen_rk3399_set_odt(0); + + rk3399_dram_status.current_index = ddr_index; + low_power = rk3399_dram_status.low_power_stat; + resume_low_power(low_power); +out: + gen_rk3399_disable_training(rk3399_dram_status.timing_config.ch_cnt); + return mhz; +} + +uint32_t ddr_round_rate(uint32_t hz) +{ + int index; + uint32_t mhz = hz / (1000 * 1000); + + index = to_get_clk_index(mhz); + + return dpll_rates_table[index].mhz * 1000 * 1000; +} + +void ddr_prepare_for_sys_suspend(void) +{ + uint32_t mhz = + rk3399_dram_status.index_freq[rk3399_dram_status.current_index]; + + /* + * If we're not currently at the boot (assumed highest) frequency, we + * need to change frequencies to configure out current index. + */ + rk3399_suspend_status.freq = mhz; + exit_low_power(); + rk3399_suspend_status.low_power_stat = + rk3399_dram_status.low_power_stat; + rk3399_suspend_status.odt = rk3399_dram_status.timing_config.odt; + rk3399_dram_status.low_power_stat = 0; + rk3399_dram_status.timing_config.odt = 1; + if (mhz != rk3399_dram_status.boot_freq) + ddr_set_rate(rk3399_dram_status.boot_freq * 1000 * 1000); + + /* + * This will configure the other index to be the same frequency as the + * current one. We retrain both indices on resume, so both have to be + * setup for the same frequency. + */ + prepare_ddr_timing(rk3399_dram_status.boot_freq); +} + +void ddr_prepare_for_sys_resume(void) +{ + /* Disable multicast */ + mmio_clrbits_32(PHY_REG(0, 896), 1); + mmio_clrbits_32(PHY_REG(1, 896), 1); + + /* The suspend code changes the current index, so reset it now. */ + rk3399_dram_status.current_index = + (mmio_read_32(CTL_REG(0, 111)) >> 16) & 0x3; + rk3399_dram_status.low_power_stat = + rk3399_suspend_status.low_power_stat; + rk3399_dram_status.timing_config.odt = rk3399_suspend_status.odt; + + /* + * Set the saved frequency from suspend if it's different than the + * current frequency. + */ + if (rk3399_suspend_status.freq != + rk3399_dram_status.index_freq[rk3399_dram_status.current_index]) { + ddr_set_rate(rk3399_suspend_status.freq * 1000 * 1000); + return; + } + + gen_rk3399_set_odt(rk3399_dram_status.timing_config.odt); + resume_low_power(rk3399_dram_status.low_power_stat); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h new file mode 100644 index 0000000..172b2a7 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DFS_H +#define DFS_H + +#include + +struct rk3399_sdram_default_config { + unsigned char bl; + /* 1:auto precharge, 0:never auto precharge */ + unsigned char ap; + /* dram driver strength */ + unsigned char dramds; + /* dram ODT, if odt=0, this parameter invalid */ + unsigned char dramodt; + /* ca ODT, if odt=0, this parameter invalid + * only used by LPDDR4 + */ + unsigned char caodt; + unsigned char burst_ref_cnt; + /* zqcs period, unit(s) */ + unsigned char zqcsi; +}; + +struct drv_odt_lp_config { + uint32_t pd_idle; + uint32_t sr_idle; + uint32_t sr_mc_gate_idle; + uint32_t srpd_lite_idle; + uint32_t standby_idle; + uint32_t odt_en; + + uint32_t dram_side_drv; + uint32_t dram_side_dq_odt; + uint32_t dram_side_ca_odt; +}; + +uint32_t ddr_set_rate(uint32_t hz); +uint32_t ddr_round_rate(uint32_t hz); +uint32_t ddr_get_rate(void); +uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2); +void dram_dfs_init(void); +void ddr_prepare_for_sys_suspend(void); +void ddr_prepare_for_sys_resume(void); + +#endif /* DFS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c new file mode 100644 index 0000000..42b6294 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +__pmusramdata struct rk3399_sdram_params sdram_config; + +void dram_init(void) +{ + uint32_t os_reg2_val, i; + + os_reg2_val = mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2)); + sdram_config.dramtype = SYS_REG_DEC_DDRTYPE(os_reg2_val); + sdram_config.num_channels = SYS_REG_DEC_NUM_CH(os_reg2_val); + sdram_config.stride = (mmio_read_32(SGRF_BASE + SGRF_SOC_CON3_7(4)) >> + 10) & 0x1f; + + for (i = 0; i < 2; i++) { + struct rk3399_sdram_channel *ch = &sdram_config.ch[i]; + struct rk3399_msch_timings *noc = &ch->noc_timings; + + if (!(SYS_REG_DEC_CHINFO(os_reg2_val, i))) + continue; + + ch->rank = SYS_REG_DEC_RANK(os_reg2_val, i); + ch->col = SYS_REG_DEC_COL(os_reg2_val, i); + ch->bk = SYS_REG_DEC_BK(os_reg2_val, i); + ch->bw = SYS_REG_DEC_BW(os_reg2_val, i); + ch->dbw = SYS_REG_DEC_DBW(os_reg2_val, i); + ch->row_3_4 = SYS_REG_DEC_ROW_3_4(os_reg2_val, i); + ch->cs0_row = SYS_REG_DEC_CS0_ROW(os_reg2_val, i); + ch->cs1_row = SYS_REG_DEC_CS1_ROW(os_reg2_val, i); + ch->ddrconfig = mmio_read_32(MSCH_BASE(i) + MSCH_DEVICECONF); + + noc->ddrtiminga0.d32 = mmio_read_32(MSCH_BASE(i) + + MSCH_DDRTIMINGA0); + noc->ddrtimingb0.d32 = mmio_read_32(MSCH_BASE(i) + + MSCH_DDRTIMINGB0); + noc->ddrtimingc0.d32 = mmio_read_32(MSCH_BASE(i) + + MSCH_DDRTIMINGC0); + noc->devtodev0.d32 = mmio_read_32(MSCH_BASE(i) + + MSCH_DEVTODEV0); + noc->ddrmode.d32 = mmio_read_32(MSCH_BASE(i) + MSCH_DDRMODE); + noc->agingx0 = mmio_read_32(MSCH_BASE(i) + MSCH_AGINGX0); + } +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h new file mode 100644 index 0000000..5572b16 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRAM_H +#define DRAM_H + +#include + +#include +#include + +enum { + DDR3 = 3, + LPDDR2 = 5, + LPDDR3 = 6, + LPDDR4 = 7, + UNUSED = 0xff +}; + +struct rk3399_ddr_pctl_regs { + uint32_t denali_ctl[CTL_REG_NUM]; +}; + +struct rk3399_ddr_publ_regs { + /* + * PHY registers from 0 to 90 for slice1. + * These are used to restore slice1-4 on resume. + */ + uint32_t phy0[91]; + /* + * PHY registers from 512 to 895. + * Only registers 0-37 of each 128 register range are used. + */ + uint32_t phy512[3][38]; + uint32_t phy896[63]; +}; + +struct rk3399_ddr_pi_regs { + uint32_t denali_pi[PI_REG_NUM]; +}; +union noc_ddrtiminga0 { + uint32_t d32; + struct { + unsigned acttoact : 6; + unsigned reserved0 : 2; + unsigned rdtomiss : 6; + unsigned reserved1 : 2; + unsigned wrtomiss : 6; + unsigned reserved2 : 2; + unsigned readlatency : 8; + } b; +}; + +union noc_ddrtimingb0 { + uint32_t d32; + struct { + unsigned rdtowr : 5; + unsigned reserved0 : 3; + unsigned wrtord : 5; + unsigned reserved1 : 3; + unsigned rrd : 4; + unsigned reserved2 : 4; + unsigned faw : 6; + unsigned reserved3 : 2; + } b; +}; + +union noc_ddrtimingc0 { + uint32_t d32; + struct { + unsigned burstpenalty : 4; + unsigned reserved0 : 4; + unsigned wrtomwr : 6; + unsigned reserved1 : 18; + } b; +}; + +union noc_devtodev0 { + uint32_t d32; + struct { + unsigned busrdtord : 3; + unsigned reserved0 : 1; + unsigned busrdtowr : 3; + unsigned reserved1 : 1; + unsigned buswrtord : 3; + unsigned reserved2 : 1; + unsigned buswrtowr : 3; + unsigned reserved3 : 17; + } b; +}; + +union noc_ddrmode { + uint32_t d32; + struct { + unsigned autoprecharge : 1; + unsigned bypassfiltering : 1; + unsigned fawbank : 1; + unsigned burstsize : 2; + unsigned mwrsize : 2; + unsigned reserved2 : 1; + unsigned forceorder : 8; + unsigned forceorderstate : 8; + unsigned reserved3 : 8; + } b; +}; + +struct rk3399_msch_timings { + union noc_ddrtiminga0 ddrtiminga0; + union noc_ddrtimingb0 ddrtimingb0; + union noc_ddrtimingc0 ddrtimingc0; + union noc_devtodev0 devtodev0; + union noc_ddrmode ddrmode; + uint32_t agingx0; +}; + +struct rk3399_sdram_channel { + unsigned char rank; + /* col = 0, means this channel is invalid */ + unsigned char col; + /* 3:8bank, 2:4bank */ + unsigned char bk; + /* channel buswidth, 2:32bit, 1:16bit, 0:8bit */ + unsigned char bw; + /* die buswidth, 2:32bit, 1:16bit, 0:8bit */ + unsigned char dbw; + /* row_3_4 = 1: 6Gb or 12Gb die + * row_3_4 = 0: normal die, power of 2 + */ + unsigned char row_3_4; + unsigned char cs0_row; + unsigned char cs1_row; + uint32_t ddrconfig; + struct rk3399_msch_timings noc_timings; +}; + +struct rk3399_sdram_params { + struct rk3399_sdram_channel ch[2]; + uint32_t ddr_freq; + unsigned char dramtype; + unsigned char num_channels; + unsigned char stride; + unsigned char odt; + struct rk3399_ddr_pctl_regs pctl_regs; + struct rk3399_ddr_pi_regs pi_regs; + struct rk3399_ddr_publ_regs phy_regs; + uint32_t rx_cal_dqs[2][4]; +}; + +extern struct rk3399_sdram_params sdram_config; + +void dram_init(void); + +#endif /* DRAM_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c new file mode 100644 index 0000000..3cdb7a2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c @@ -0,0 +1,1324 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include + +#include "dram_spec_timing.h" + +static const uint8_t ddr3_cl_cwl[][7] = { + /* + * speed 0~330 331 ~ 400 401 ~ 533 534~666 667~800 801~933 934~1066 + * tCK>3 2.5~3 1.875~2.5 1.5~1.875 1.25~1.5 1.07~1.25 0.938~1.07 + * cl<<4, cwl cl<<4, cwl cl<<4, cwl + */ + /* DDR3_800D (5-5-5) */ + {((5 << 4) | 5), ((5 << 4) | 5), 0, 0, 0, 0, 0}, + /* DDR3_800E (6-6-6) */ + {((5 << 4) | 5), ((6 << 4) | 5), 0, 0, 0, 0, 0}, + /* DDR3_1066E (6-6-6) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), 0, 0, 0, 0}, + /* DDR3_1066F (7-7-7) */ + {((5 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), 0, 0, 0, 0}, + /* DDR3_1066G (8-8-8) */ + {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), 0, 0, 0, 0}, + /* DDR3_1333F (7-7-7) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7), + 0, 0, 0}, + /* DDR3_1333G (8-8-8) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((8 << 4) | 7), + 0, 0, 0}, + /* DDR3_1333H (9-9-9) */ + {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((9 << 4) | 7), + 0, 0, 0}, + /* DDR3_1333J (10-10-10) */ + {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7), + 0, 0, 0}, + /* DDR3_1600G (8-8-8) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7), + ((8 << 4) | 8), 0, 0}, + /* DDR3_1600H (9-9-9) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7), + ((9 << 4) | 8), 0, 0}, + /* DDR3_1600J (10-10-10) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7), + ((10 << 4) | 8), 0, 0}, + /* DDR3_1600K (11-11-11) */ + {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7), + ((11 << 4) | 8), 0, 0}, + /* DDR3_1866J (10-10-10) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7), + ((9 << 4) | 8), ((11 << 4) | 9), 0}, + /* DDR3_1866K (11-11-11) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((8 << 4) | 7), + ((10 << 4) | 8), ((11 << 4) | 9), 0}, + /* DDR3_1866L (12-12-12) */ + {((6 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7), + ((11 << 4) | 8), ((12 << 4) | 9), 0}, + /* DDR3_1866M (13-13-13) */ + {((6 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7), + ((11 << 4) | 8), ((13 << 4) | 9), 0}, + /* DDR3_2133K (11-11-11) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7), + ((9 << 4) | 8), ((10 << 4) | 9), ((11 << 4) | 10)}, + /* DDR3_2133L (12-12-12) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7), + ((9 << 4) | 8), ((11 << 4) | 9), ((12 << 4) | 10)}, + /* DDR3_2133M (13-13-13) */ + {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7), + ((10 << 4) | 8), ((12 << 4) | 9), ((13 << 4) | 10)}, + /* DDR3_2133N (14-14-14) */ + {((6 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7), + ((11 << 4) | 8), ((13 << 4) | 9), ((14 << 4) | 10)}, + /* DDR3_DEFAULT */ + {((6 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7), + ((11 << 4) | 8), ((13 << 4) | 9), ((14 << 4) | 10)} +}; + +static const uint16_t ddr3_trc_tfaw[] = { + /* tRC tFAW */ + ((50 << 8) | 50), /* DDR3_800D (5-5-5) */ + ((53 << 8) | 50), /* DDR3_800E (6-6-6) */ + + ((49 << 8) | 50), /* DDR3_1066E (6-6-6) */ + ((51 << 8) | 50), /* DDR3_1066F (7-7-7) */ + ((53 << 8) | 50), /* DDR3_1066G (8-8-8) */ + + ((47 << 8) | 45), /* DDR3_1333F (7-7-7) */ + ((48 << 8) | 45), /* DDR3_1333G (8-8-8) */ + ((50 << 8) | 45), /* DDR3_1333H (9-9-9) */ + ((51 << 8) | 45), /* DDR3_1333J (10-10-10) */ + + ((45 << 8) | 40), /* DDR3_1600G (8-8-8) */ + ((47 << 8) | 40), /* DDR3_1600H (9-9-9)*/ + ((48 << 8) | 40), /* DDR3_1600J (10-10-10) */ + ((49 << 8) | 40), /* DDR3_1600K (11-11-11) */ + + ((45 << 8) | 35), /* DDR3_1866J (10-10-10) */ + ((46 << 8) | 35), /* DDR3_1866K (11-11-11) */ + ((47 << 8) | 35), /* DDR3_1866L (12-12-12) */ + ((48 << 8) | 35), /* DDR3_1866M (13-13-13) */ + + ((44 << 8) | 35), /* DDR3_2133K (11-11-11) */ + ((45 << 8) | 35), /* DDR3_2133L (12-12-12) */ + ((46 << 8) | 35), /* DDR3_2133M (13-13-13) */ + ((47 << 8) | 35), /* DDR3_2133N (14-14-14) */ + + ((53 << 8) | 50) /* DDR3_DEFAULT */ +}; + +static uint32_t get_max_speed_rate(struct timing_related_config *timing_config) +{ + if (timing_config->ch_cnt > 1) + return max(timing_config->dram_info[0].speed_rate, + timing_config->dram_info[1].speed_rate); + else + return timing_config->dram_info[0].speed_rate; +} + +static uint32_t +get_max_die_capability(struct timing_related_config *timing_config) +{ + uint32_t die_cap = 0; + uint32_t cs, ch; + + for (ch = 0; ch < timing_config->ch_cnt; ch++) { + for (cs = 0; cs < timing_config->dram_info[ch].cs_cnt; cs++) { + die_cap = max(die_cap, + timing_config-> + dram_info[ch].per_die_capability[cs]); + } + } + return die_cap; +} + +/* tRSTL, 100ns */ +#define DDR3_TRSTL (100) +/* trsth, 500us */ +#define DDR3_TRSTH (500000) +/* trefi, 7.8us */ +#define DDR3_TREFI_7_8_US (7800) +/* tWR, 15ns */ +#define DDR3_TWR (15) +/* tRTP, max(4 tCK,7.5ns) */ +#define DDR3_TRTP (7) +/* tRRD = max(4nCK, 10ns) */ +#define DDR3_TRRD (10) +/* tCK */ +#define DDR3_TCCD (4) +/*tWTR, max(4 tCK,7.5ns)*/ +#define DDR3_TWTR (7) +/* tCK */ +#define DDR3_TRTW (0) +/* tRAS, 37.5ns(400MHz) 37.5ns(533MHz) */ +#define DDR3_TRAS (37) +/* ns */ +#define DDR3_TRFC_512MBIT (90) +/* ns */ +#define DDR3_TRFC_1GBIT (110) +/* ns */ +#define DDR3_TRFC_2GBIT (160) +/* ns */ +#define DDR3_TRFC_4GBIT (300) +/* ns */ +#define DDR3_TRFC_8GBIT (350) + +/*pd and sr*/ +#define DDR3_TXP (7) /* tXP, max(3 tCK, 7.5ns)( < 933MHz) */ +#define DDR3_TXPDLL (24) /* tXPDLL, max(10 tCK, 24ns) */ +#define DDR3_TDLLK (512) /* tXSR, tDLLK=512 tCK */ +#define DDR3_TCKE_400MHZ (7) /* tCKE, max(3 tCK,7.5ns)(400MHz) */ +#define DDR3_TCKE_533MHZ (6) /* tCKE, max(3 tCK,5.625ns)(533MHz) */ +#define DDR3_TCKSRE (10) /* tCKSRX, max(5 tCK, 10ns) */ + +/*mode register timing*/ +#define DDR3_TMOD (15) /* tMOD, max(12 tCK,15ns) */ +#define DDR3_TMRD (4) /* tMRD, 4 tCK */ + +/* ZQ */ +#define DDR3_TZQINIT (640) /* tZQinit, max(512 tCK, 640ns) */ +#define DDR3_TZQCS (80) /* tZQCS, max(64 tCK, 80ns) */ +#define DDR3_TZQOPER (320) /* tZQoper, max(256 tCK, 320ns) */ + +/* Write leveling */ +#define DDR3_TWLMRD (40) /* tCK */ +#define DDR3_TWLO (9) /* max 7.5ns */ +#define DDR3_TWLDQSEN (25) /* tCK */ + +/* + * Description: depend on input parameter "timing_config", + * and calculate all ddr3 + * spec timing to "pdram_timing" + * parameters: + * input: timing_config + * output: pdram_timing + */ +static void ddr3_get_parameter(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t nmhz = timing_config->freq; + uint32_t ddr_speed_bin = get_max_speed_rate(timing_config); + uint32_t ddr_capability_per_die = get_max_die_capability(timing_config); + uint32_t tmp; + + zeromem((void *)pdram_timing, sizeof(struct dram_timing_t)); + pdram_timing->mhz = nmhz; + pdram_timing->al = 0; + pdram_timing->bl = timing_config->bl; + if (nmhz <= 330) + tmp = 0; + else if (nmhz <= 400) + tmp = 1; + else if (nmhz <= 533) + tmp = 2; + else if (nmhz <= 666) + tmp = 3; + else if (nmhz <= 800) + tmp = 4; + else if (nmhz <= 933) + tmp = 5; + else + tmp = 6; + + /* when dll bypss cl = cwl = 6 */ + if (nmhz < 300) { + pdram_timing->cl = 6; + pdram_timing->cwl = 6; + } else { + pdram_timing->cl = (ddr3_cl_cwl[ddr_speed_bin][tmp] >> 4) & 0xf; + pdram_timing->cwl = ddr3_cl_cwl[ddr_speed_bin][tmp] & 0xf; + } + + switch (timing_config->dramds) { + case 40: + tmp = DDR3_DS_40; + break; + case 34: + default: + tmp = DDR3_DS_34; + break; + } + + if (timing_config->odt) + switch (timing_config->dramodt) { + case 60: + pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_60; + break; + case 40: + pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_40; + break; + case 120: + pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_120; + break; + case 0: + default: + pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_DIS; + break; + } + else + pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_DIS; + + pdram_timing->mr[2] = DDR3_MR2_CWL(pdram_timing->cwl); + pdram_timing->mr[3] = 0; + + pdram_timing->trstl = ((DDR3_TRSTL * nmhz + 999) / 1000); + pdram_timing->trsth = ((DDR3_TRSTH * nmhz + 999) / 1000); + /* tREFI, average periodic refresh interval, 7.8us */ + pdram_timing->trefi = ((DDR3_TREFI_7_8_US * nmhz + 999) / 1000); + /* base timing */ + pdram_timing->trcd = pdram_timing->cl; + pdram_timing->trp = pdram_timing->cl; + pdram_timing->trppb = pdram_timing->cl; + tmp = ((DDR3_TWR * nmhz + 999) / 1000); + pdram_timing->twr = tmp; + pdram_timing->tdal = tmp + pdram_timing->trp; + if (tmp < 9) { + tmp = tmp - 4; + } else { + tmp += (tmp & 0x1) ? 1 : 0; + tmp = tmp >> 1; + } + if (pdram_timing->bl == 4) + pdram_timing->mr[0] = DDR3_BC4 + | DDR3_CL(pdram_timing->cl) + | DDR3_WR(tmp); + else + pdram_timing->mr[0] = DDR3_BL8 + | DDR3_CL(pdram_timing->cl) + | DDR3_WR(tmp); + tmp = ((DDR3_TRTP * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->trtp = max(4, tmp); + pdram_timing->trc = + (((ddr3_trc_tfaw[ddr_speed_bin] >> 8) * nmhz + 999) / 1000); + tmp = ((DDR3_TRRD * nmhz + 999) / 1000); + pdram_timing->trrd = max(4, tmp); + pdram_timing->tccd = DDR3_TCCD; + tmp = ((DDR3_TWTR * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->twtr = max(4, tmp); + pdram_timing->trtw = DDR3_TRTW; + pdram_timing->tras_max = 9 * pdram_timing->trefi; + pdram_timing->tras_min = ((DDR3_TRAS * nmhz + (nmhz >> 1) + 999) + / 1000); + pdram_timing->tfaw = + (((ddr3_trc_tfaw[ddr_speed_bin] & 0x0ff) * nmhz + 999) + / 1000); + /* tRFC, 90ns(512Mb),110ns(1Gb),160ns(2Gb),300ns(4Gb),350ns(8Gb) */ + if (ddr_capability_per_die <= 0x4000000) + tmp = DDR3_TRFC_512MBIT; + else if (ddr_capability_per_die <= 0x8000000) + tmp = DDR3_TRFC_1GBIT; + else if (ddr_capability_per_die <= 0x10000000) + tmp = DDR3_TRFC_2GBIT; + else if (ddr_capability_per_die <= 0x20000000) + tmp = DDR3_TRFC_4GBIT; + else + tmp = DDR3_TRFC_8GBIT; + pdram_timing->trfc = (tmp * nmhz + 999) / 1000; + pdram_timing->txsnr = max(5, (((tmp + 10) * nmhz + 999) / 1000)); + pdram_timing->tdqsck_max = 0; + /*pd and sr*/ + pdram_timing->txsr = DDR3_TDLLK; + tmp = ((DDR3_TXP * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->txp = max(3, tmp); + tmp = ((DDR3_TXPDLL * nmhz + 999) / 1000); + pdram_timing->txpdll = max(10, tmp); + pdram_timing->tdllk = DDR3_TDLLK; + if (nmhz >= 533) + tmp = ((DDR3_TCKE_533MHZ * nmhz + 999) / 1000); + else + tmp = ((DDR3_TCKE_400MHZ * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->tcke = max(3, tmp); + pdram_timing->tckesr = (pdram_timing->tcke + 1); + tmp = ((DDR3_TCKSRE * nmhz + 999) / 1000); + pdram_timing->tcksre = max(5, tmp); + pdram_timing->tcksrx = max(5, tmp); + /*mode register timing*/ + tmp = ((DDR3_TMOD * nmhz + 999) / 1000); + pdram_timing->tmod = max(12, tmp); + pdram_timing->tmrd = DDR3_TMRD; + pdram_timing->tmrr = 0; + /*ODT*/ + pdram_timing->todton = pdram_timing->cwl - 2; + /*ZQ*/ + tmp = ((DDR3_TZQINIT * nmhz + 999) / 1000); + pdram_timing->tzqinit = max(512, tmp); + tmp = ((DDR3_TZQCS * nmhz + 999) / 1000); + pdram_timing->tzqcs = max(64, tmp); + tmp = ((DDR3_TZQOPER * nmhz + 999) / 1000); + pdram_timing->tzqoper = max(256, tmp); + /* write leveling */ + pdram_timing->twlmrd = DDR3_TWLMRD; + pdram_timing->twldqsen = DDR3_TWLDQSEN; + pdram_timing->twlo = ((DDR3_TWLO * nmhz + (nmhz >> 1) + 999) / 1000); +} + +#define LPDDR2_TINIT1 (100) /* ns */ +#define LPDDR2_TINIT2 (5) /* tCK */ +#define LPDDR2_TINIT3 (200000) /* 200us */ +#define LPDDR2_TINIT4 (1000) /* 1us */ +#define LPDDR2_TINIT5 (10000) /* 10us */ +#define LPDDR2_TRSTL (0) /* tCK */ +#define LPDDR2_TRSTH (500000) /* 500us */ +#define LPDDR2_TREFI_3_9_US (3900) /* 3.9us */ +#define LPDDR2_TREFI_7_8_US (7800) /* 7.8us */ + +/* base timing */ +#define LPDDR2_TRCD (24) /* tRCD,15ns(Fast)18ns(Typ)24ns(Slow) */ +#define LPDDR2_TRP_PB (18) /* tRPpb,15ns(Fast)18ns(Typ)24ns(Slow) */ +#define LPDDR2_TRP_AB_8_BANK (21) /* tRPab,18ns(Fast)21ns(Typ)27ns(Slow) */ +#define LPDDR2_TWR (15) /* tWR, max(3tCK,15ns) */ +#define LPDDR2_TRTP (7) /* tRTP, max(2tCK, 7.5ns) */ +#define LPDDR2_TRRD (10) /* tRRD, max(2tCK,10ns) */ +#define LPDDR2_TCCD (2) /* tCK */ +#define LPDDR2_TWTR_GREAT_200MHZ (7) /* ns */ +#define LPDDR2_TWTR_LITTLE_200MHZ (10) /* ns */ +#define LPDDR2_TRTW (0) /* tCK */ +#define LPDDR2_TRAS_MAX (70000) /* 70us */ +#define LPDDR2_TRAS (42) /* tRAS, max(3tCK,42ns) */ +#define LPDDR2_TFAW_GREAT_200MHZ (50) /* max(8tCK,50ns) */ +#define LPDDR2_TFAW_LITTLE_200MHZ (60) /* max(8tCK,60ns) */ +#define LPDDR2_TRFC_8GBIT (210) /* ns */ +#define LPDDR2_TRFC_4GBIT (130) /* ns */ +#define LPDDR2_TDQSCK_MIN (2) /* tDQSCKmin, 2.5ns */ +#define LPDDR2_TDQSCK_MAX (5) /* tDQSCKmax, 5.5ns */ + +/*pd and sr*/ +#define LPDDR2_TXP (7) /* tXP, max(2tCK,7.5ns) */ +#define LPDDR2_TXPDLL (0) +#define LPDDR2_TDLLK (0) /* tCK */ +#define LPDDR2_TCKE (3) /* tCK */ +#define LPDDR2_TCKESR (15) /* tCKESR, max(3tCK,15ns) */ +#define LPDDR2_TCKSRE (1) /* tCK */ +#define LPDDR2_TCKSRX (2) /* tCK */ + +/*mode register timing*/ +#define LPDDR2_TMOD (0) +#define LPDDR2_TMRD (5) /* tMRD, (=tMRW), 5 tCK */ +#define LPDDR2_TMRR (2) /* tCK */ + +/*ZQ*/ +#define LPDDR2_TZQINIT (1000) /* ns */ +#define LPDDR2_TZQCS (90) /* tZQCS, max(6tCK,90ns) */ +#define LPDDR2_TZQCL (360) /* tZQCL, max(6tCK,360ns) */ +#define LPDDR2_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */ + +/* + * Description: depend on input parameter "timing_config", + * and calculate all lpddr2 + * spec timing to "pdram_timing" + * parameters: + * input: timing_config + * output: pdram_timing + */ +static void lpddr2_get_parameter(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t nmhz = timing_config->freq; + uint32_t ddr_capability_per_die = get_max_die_capability(timing_config); + uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp, twr_tmp, bl_tmp; + + zeromem((void *)pdram_timing, sizeof(struct dram_timing_t)); + pdram_timing->mhz = nmhz; + pdram_timing->al = 0; + pdram_timing->bl = timing_config->bl; + + /* 1066 933 800 667 533 400 333 + * RL, 8 7 6 5 4 3 3 + * WL, 4 4 3 2 2 1 1 + */ + if (nmhz <= 266) { + pdram_timing->cl = 4; + pdram_timing->cwl = 2; + pdram_timing->mr[2] = LPDDR2_RL4_WL2; + } else if (nmhz <= 333) { + pdram_timing->cl = 5; + pdram_timing->cwl = 2; + pdram_timing->mr[2] = LPDDR2_RL5_WL2; + } else if (nmhz <= 400) { + pdram_timing->cl = 6; + pdram_timing->cwl = 3; + pdram_timing->mr[2] = LPDDR2_RL6_WL3; + } else if (nmhz <= 466) { + pdram_timing->cl = 7; + pdram_timing->cwl = 4; + pdram_timing->mr[2] = LPDDR2_RL7_WL4; + } else { + pdram_timing->cl = 8; + pdram_timing->cwl = 4; + pdram_timing->mr[2] = LPDDR2_RL8_WL4; + } + switch (timing_config->dramds) { + case 120: + pdram_timing->mr[3] = LPDDR2_DS_120; + break; + case 80: + pdram_timing->mr[3] = LPDDR2_DS_80; + break; + case 60: + pdram_timing->mr[3] = LPDDR2_DS_60; + break; + case 48: + pdram_timing->mr[3] = LPDDR2_DS_48; + break; + case 40: + pdram_timing->mr[3] = LPDDR2_DS_40; + break; + case 34: + default: + pdram_timing->mr[3] = LPDDR2_DS_34; + break; + } + pdram_timing->mr[0] = 0; + + pdram_timing->tinit1 = (LPDDR2_TINIT1 * nmhz + 999) / 1000; + pdram_timing->tinit2 = LPDDR2_TINIT2; + pdram_timing->tinit3 = (LPDDR2_TINIT3 * nmhz + 999) / 1000; + pdram_timing->tinit4 = (LPDDR2_TINIT4 * nmhz + 999) / 1000; + pdram_timing->tinit5 = (LPDDR2_TINIT5 * nmhz + 999) / 1000; + pdram_timing->trstl = LPDDR2_TRSTL; + pdram_timing->trsth = (LPDDR2_TRSTH * nmhz + 999) / 1000; + /* + * tREFI, average periodic refresh interval, + * 15.6us(<256Mb) 7.8us(256Mb-1Gb) 3.9us(2Gb-8Gb) + */ + if (ddr_capability_per_die >= 0x10000000) + pdram_timing->trefi = (LPDDR2_TREFI_3_9_US * nmhz + 999) + / 1000; + else + pdram_timing->trefi = (LPDDR2_TREFI_7_8_US * nmhz + 999) + / 1000; + /* base timing */ + tmp = ((LPDDR2_TRCD * nmhz + 999) / 1000); + pdram_timing->trcd = max(3, tmp); + /* + * tRPpb, max(3tCK, 15ns(Fast) 18ns(Typ) 24ns(Slow), + */ + trppb_tmp = ((LPDDR2_TRP_PB * nmhz + 999) / 1000); + trppb_tmp = max(3, trppb_tmp); + pdram_timing->trppb = trppb_tmp; + /* + * tRPab, max(3tCK, 4-bank:15ns(Fast) 18ns(Typ) 24ns(Slow), + * 8-bank:18ns(Fast) 21ns(Typ) 27ns(Slow)) + */ + trp_tmp = ((LPDDR2_TRP_AB_8_BANK * nmhz + 999) / 1000); + trp_tmp = max(3, trp_tmp); + pdram_timing->trp = trp_tmp; + twr_tmp = ((LPDDR2_TWR * nmhz + 999) / 1000); + twr_tmp = max(3, twr_tmp); + pdram_timing->twr = twr_tmp; + bl_tmp = (pdram_timing->bl == 16) ? LPDDR2_BL16 : + ((pdram_timing->bl == 8) ? LPDDR2_BL8 : LPDDR2_BL4); + pdram_timing->mr[1] = bl_tmp | LPDDR2_N_WR(twr_tmp); + tmp = ((LPDDR2_TRTP * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->trtp = max(2, tmp); + tras_tmp = ((LPDDR2_TRAS * nmhz + 999) / 1000); + tras_tmp = max(3, tras_tmp); + pdram_timing->tras_min = tras_tmp; + pdram_timing->tras_max = ((LPDDR2_TRAS_MAX * nmhz + 999) / 1000); + pdram_timing->trc = (tras_tmp + trp_tmp); + tmp = ((LPDDR2_TRRD * nmhz + 999) / 1000); + pdram_timing->trrd = max(2, tmp); + pdram_timing->tccd = LPDDR2_TCCD; + /* tWTR, max(2tCK, 7.5ns(533-266MHz) 10ns(200-166MHz)) */ + if (nmhz > 200) + tmp = ((LPDDR2_TWTR_GREAT_200MHZ * nmhz + (nmhz >> 1) + + 999) / 1000); + else + tmp = ((LPDDR2_TWTR_LITTLE_200MHZ * nmhz + 999) / 1000); + pdram_timing->twtr = max(2, tmp); + pdram_timing->trtw = LPDDR2_TRTW; + if (nmhz <= 200) + pdram_timing->tfaw = (LPDDR2_TFAW_LITTLE_200MHZ * nmhz + 999) + / 1000; + else + pdram_timing->tfaw = (LPDDR2_TFAW_GREAT_200MHZ * nmhz + 999) + / 1000; + /* tRFC, 90ns(<=512Mb) 130ns(1Gb-4Gb) 210ns(8Gb) */ + if (ddr_capability_per_die >= 0x40000000) { + pdram_timing->trfc = + (LPDDR2_TRFC_8GBIT * nmhz + 999) / 1000; + tmp = (((LPDDR2_TRFC_8GBIT + 10) * nmhz + 999) / 1000); + } else { + pdram_timing->trfc = + (LPDDR2_TRFC_4GBIT * nmhz + 999) / 1000; + tmp = (((LPDDR2_TRFC_4GBIT + 10) * nmhz + 999) / 1000); + } + if (tmp < 2) + tmp = 2; + pdram_timing->txsr = tmp; + pdram_timing->txsnr = tmp; + /* tdqsck use rounded down */ + pdram_timing->tdqsck = ((LPDDR2_TDQSCK_MIN * nmhz + (nmhz >> 1)) + / 1000); + pdram_timing->tdqsck_max = + ((LPDDR2_TDQSCK_MAX * nmhz + (nmhz >> 1) + 999) + / 1000); + /* pd and sr */ + tmp = ((LPDDR2_TXP * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->txp = max(2, tmp); + pdram_timing->txpdll = LPDDR2_TXPDLL; + pdram_timing->tdllk = LPDDR2_TDLLK; + pdram_timing->tcke = LPDDR2_TCKE; + tmp = ((LPDDR2_TCKESR * nmhz + 999) / 1000); + pdram_timing->tckesr = max(3, tmp); + pdram_timing->tcksre = LPDDR2_TCKSRE; + pdram_timing->tcksrx = LPDDR2_TCKSRX; + /* mode register timing */ + pdram_timing->tmod = LPDDR2_TMOD; + pdram_timing->tmrd = LPDDR2_TMRD; + pdram_timing->tmrr = LPDDR2_TMRR; + /* ZQ */ + pdram_timing->tzqinit = (LPDDR2_TZQINIT * nmhz + 999) / 1000; + tmp = ((LPDDR2_TZQCS * nmhz + 999) / 1000); + pdram_timing->tzqcs = max(6, tmp); + tmp = ((LPDDR2_TZQCL * nmhz + 999) / 1000); + pdram_timing->tzqoper = max(6, tmp); + tmp = ((LPDDR2_TZQRESET * nmhz + 999) / 1000); + pdram_timing->tzqreset = max(3, tmp); +} + +#define LPDDR3_TINIT1 (100) /* ns */ +#define LPDDR3_TINIT2 (5) /* tCK */ +#define LPDDR3_TINIT3 (200000) /* 200us */ +#define LPDDR3_TINIT4 (1000) /* 1us */ +#define LPDDR3_TINIT5 (10000) /* 10us */ +#define LPDDR3_TRSTL (0) +#define LPDDR3_TRSTH (0) /* 500us */ +#define LPDDR3_TREFI_3_9_US (3900) /* 3.9us */ + +/* base timging */ +#define LPDDR3_TRCD (18) /* tRCD,15ns(Fast)18ns(Typ)24ns(Slow) */ +#define LPDDR3_TRP_PB (18) /* tRPpb, 15ns(Fast) 18ns(Typ) 24ns(Slow) */ +#define LPDDR3_TRP_AB (21) /* tRPab, 18ns(Fast) 21ns(Typ) 27ns(Slow) */ +#define LPDDR3_TWR (15) /* tWR, max(4tCK,15ns) */ +#define LPDDR3_TRTP (7) /* tRTP, max(4tCK, 7.5ns) */ +#define LPDDR3_TRRD (10) /* tRRD, max(2tCK,10ns) */ +#define LPDDR3_TCCD (4) /* tCK */ +#define LPDDR3_TWTR (7) /* tWTR, max(4tCK, 7.5ns) */ +#define LPDDR3_TRTW (0) /* tCK register min valid value */ +#define LPDDR3_TRAS_MAX (70000) /* 70us */ +#define LPDDR3_TRAS (42) /* tRAS, max(3tCK,42ns) */ +#define LPDDR3_TFAW (50) /* tFAW,max(8tCK, 50ns) */ +#define LPDDR3_TRFC_8GBIT (210) /* tRFC, 130ns(4Gb) 210ns(>4Gb) */ +#define LPDDR3_TRFC_4GBIT (130) /* ns */ +#define LPDDR3_TDQSCK_MIN (2) /* tDQSCKmin,2.5ns */ +#define LPDDR3_TDQSCK_MAX (5) /* tDQSCKmax,5.5ns */ + +/* pd and sr */ +#define LPDDR3_TXP (7) /* tXP, max(3tCK,7.5ns) */ +#define LPDDR3_TXPDLL (0) +#define LPDDR3_TCKE (7) /* tCKE, (max 7.5ns,3 tCK) */ +#define LPDDR3_TCKESR (15) /* tCKESR, max(3tCK,15ns) */ +#define LPDDR3_TCKSRE (2) /* tCKSRE=tCPDED, 2 tCK */ +#define LPDDR3_TCKSRX (2) /* tCKSRX, 2 tCK */ + +/* mode register timing */ +#define LPDDR3_TMOD (0) +#define LPDDR3_TMRD (14) /* tMRD, (=tMRW), max(14ns, 10 tCK) */ +#define LPDDR3_TMRR (4) /* tMRR, 4 tCK */ +#define LPDDR3_TMRRI LPDDR3_TRCD + +/* ODT */ +#define LPDDR3_TODTON (3) /* 3.5ns */ + +/* ZQ */ +#define LPDDR3_TZQINIT (1000) /* 1us */ +#define LPDDR3_TZQCS (90) /* tZQCS, 90ns */ +#define LPDDR3_TZQCL (360) /* 360ns */ +#define LPDDR3_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */ +/* write leveling */ +#define LPDDR3_TWLMRD (40) /* ns */ +#define LPDDR3_TWLO (20) /* ns */ +#define LPDDR3_TWLDQSEN (25) /* ns */ +/* CA training */ +#define LPDDR3_TCACKEL (10) /* tCK */ +#define LPDDR3_TCAENT (10) /* tCK */ +#define LPDDR3_TCAMRD (20) /* tCK */ +#define LPDDR3_TCACKEH (10) /* tCK */ +#define LPDDR3_TCAEXT (10) /* tCK */ +#define LPDDR3_TADR (20) /* ns */ +#define LPDDR3_TMRZ (3) /* ns */ + +/* FSP */ +#define LPDDR3_TFC_LONG (250) /* ns */ + +/* + * Description: depend on input parameter "timing_config", + * and calculate all lpddr3 + * spec timing to "pdram_timing" + * parameters: + * input: timing_config + * output: pdram_timing + */ +static void lpddr3_get_parameter(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t nmhz = timing_config->freq; + uint32_t ddr_capability_per_die = get_max_die_capability(timing_config); + uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp, twr_tmp, bl_tmp; + + zeromem((void *)pdram_timing, sizeof(struct dram_timing_t)); + pdram_timing->mhz = nmhz; + pdram_timing->al = 0; + pdram_timing->bl = timing_config->bl; + + /* + * Only support Write Latency Set A here + * 1066 933 800 733 667 600 533 400 166 + * RL, 16 14 12 11 10 9 8 6 3 + * WL, 8 8 6 6 6 5 4 3 1 + */ + if (nmhz <= 400) { + pdram_timing->cl = 6; + pdram_timing->cwl = 3; + pdram_timing->mr[2] = LPDDR3_RL6_WL3; + } else if (nmhz <= 533) { + pdram_timing->cl = 8; + pdram_timing->cwl = 4; + pdram_timing->mr[2] = LPDDR3_RL8_WL4; + } else if (nmhz <= 600) { + pdram_timing->cl = 9; + pdram_timing->cwl = 5; + pdram_timing->mr[2] = LPDDR3_RL9_WL5; + } else if (nmhz <= 667) { + pdram_timing->cl = 10; + pdram_timing->cwl = 6; + pdram_timing->mr[2] = LPDDR3_RL10_WL6; + } else if (nmhz <= 733) { + pdram_timing->cl = 11; + pdram_timing->cwl = 6; + pdram_timing->mr[2] = LPDDR3_RL11_WL6; + } else if (nmhz <= 800) { + pdram_timing->cl = 12; + pdram_timing->cwl = 6; + pdram_timing->mr[2] = LPDDR3_RL12_WL6; + } else if (nmhz <= 933) { + pdram_timing->cl = 14; + pdram_timing->cwl = 8; + pdram_timing->mr[2] = LPDDR3_RL14_WL8; + } else { + pdram_timing->cl = 16; + pdram_timing->cwl = 8; + pdram_timing->mr[2] = LPDDR3_RL16_WL8; + } + switch (timing_config->dramds) { + case 80: + pdram_timing->mr[3] = LPDDR3_DS_80; + break; + case 60: + pdram_timing->mr[3] = LPDDR3_DS_60; + break; + case 48: + pdram_timing->mr[3] = LPDDR3_DS_48; + break; + case 40: + pdram_timing->mr[3] = LPDDR3_DS_40; + break; + case 3440: + pdram_timing->mr[3] = LPDDR3_DS_34D_40U; + break; + case 4048: + pdram_timing->mr[3] = LPDDR3_DS_40D_48U; + break; + case 3448: + pdram_timing->mr[3] = LPDDR3_DS_34D_48U; + break; + case 34: + default: + pdram_timing->mr[3] = LPDDR3_DS_34; + break; + } + pdram_timing->mr[0] = 0; + if (timing_config->odt) + switch (timing_config->dramodt) { + case 60: + pdram_timing->mr11 = LPDDR3_ODT_60; + break; + case 120: + pdram_timing->mr11 = LPDDR3_ODT_120; + break; + case 240: + default: + pdram_timing->mr11 = LPDDR3_ODT_240; + break; + } + else + pdram_timing->mr11 = LPDDR3_ODT_DIS; + + pdram_timing->tinit1 = (LPDDR3_TINIT1 * nmhz + 999) / 1000; + pdram_timing->tinit2 = LPDDR3_TINIT2; + pdram_timing->tinit3 = (LPDDR3_TINIT3 * nmhz + 999) / 1000; + pdram_timing->tinit4 = (LPDDR3_TINIT4 * nmhz + 999) / 1000; + pdram_timing->tinit5 = (LPDDR3_TINIT5 * nmhz + 999) / 1000; + pdram_timing->trstl = LPDDR3_TRSTL; + pdram_timing->trsth = (LPDDR3_TRSTH * nmhz + 999) / 1000; + /* tREFI, average periodic refresh interval, 3.9us(4Gb-16Gb) */ + pdram_timing->trefi = (LPDDR3_TREFI_3_9_US * nmhz + 999) / 1000; + /* base timing */ + tmp = ((LPDDR3_TRCD * nmhz + 999) / 1000); + pdram_timing->trcd = max(3, tmp); + trppb_tmp = ((LPDDR3_TRP_PB * nmhz + 999) / 1000); + trppb_tmp = max(3, trppb_tmp); + pdram_timing->trppb = trppb_tmp; + trp_tmp = ((LPDDR3_TRP_AB * nmhz + 999) / 1000); + trp_tmp = max(3, trp_tmp); + pdram_timing->trp = trp_tmp; + twr_tmp = ((LPDDR3_TWR * nmhz + 999) / 1000); + twr_tmp = max(4, twr_tmp); + pdram_timing->twr = twr_tmp; + if (twr_tmp <= 6) + twr_tmp = 6; + else if (twr_tmp <= 8) + twr_tmp = 8; + else if (twr_tmp <= 12) + twr_tmp = twr_tmp; + else if (twr_tmp <= 14) + twr_tmp = 14; + else + twr_tmp = 16; + if (twr_tmp > 9) + pdram_timing->mr[2] |= (1 << 4); /*enable nWR > 9*/ + twr_tmp = (twr_tmp > 9) ? (twr_tmp - 10) : (twr_tmp - 2); + bl_tmp = LPDDR3_BL8; + pdram_timing->mr[1] = bl_tmp | LPDDR3_N_WR(twr_tmp); + tmp = ((LPDDR3_TRTP * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->trtp = max(4, tmp); + tras_tmp = ((LPDDR3_TRAS * nmhz + 999) / 1000); + tras_tmp = max(3, tras_tmp); + pdram_timing->tras_min = tras_tmp; + pdram_timing->trc = (tras_tmp + trp_tmp); + tmp = ((LPDDR3_TRRD * nmhz + 999) / 1000); + pdram_timing->trrd = max(2, tmp); + pdram_timing->tccd = LPDDR3_TCCD; + tmp = ((LPDDR3_TWTR * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->twtr = max(4, tmp); + pdram_timing->trtw = ((LPDDR3_TRTW * nmhz + 999) / 1000); + pdram_timing->tras_max = ((LPDDR3_TRAS_MAX * nmhz + 999) / 1000); + tmp = (LPDDR3_TFAW * nmhz + 999) / 1000; + pdram_timing->tfaw = max(8, tmp); + if (ddr_capability_per_die > 0x20000000) { + pdram_timing->trfc = + (LPDDR3_TRFC_8GBIT * nmhz + 999) / 1000; + tmp = (((LPDDR3_TRFC_8GBIT + 10) * nmhz + 999) / 1000); + } else { + pdram_timing->trfc = + (LPDDR3_TRFC_4GBIT * nmhz + 999) / 1000; + tmp = (((LPDDR3_TRFC_4GBIT + 10) * nmhz + 999) / 1000); + } + pdram_timing->txsr = max(2, tmp); + pdram_timing->txsnr = max(2, tmp); + /* tdqsck use rounded down */ + pdram_timing->tdqsck = + ((LPDDR3_TDQSCK_MIN * nmhz + (nmhz >> 1)) + / 1000); + pdram_timing->tdqsck_max = + ((LPDDR3_TDQSCK_MAX * nmhz + (nmhz >> 1) + 999) + / 1000); + /*pd and sr*/ + tmp = ((LPDDR3_TXP * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->txp = max(3, tmp); + pdram_timing->txpdll = LPDDR3_TXPDLL; + tmp = ((LPDDR3_TCKE * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->tcke = max(3, tmp); + tmp = ((LPDDR3_TCKESR * nmhz + 999) / 1000); + pdram_timing->tckesr = max(3, tmp); + pdram_timing->tcksre = LPDDR3_TCKSRE; + pdram_timing->tcksrx = LPDDR3_TCKSRX; + /*mode register timing*/ + pdram_timing->tmod = LPDDR3_TMOD; + tmp = ((LPDDR3_TMRD * nmhz + 999) / 1000); + pdram_timing->tmrd = max(10, tmp); + pdram_timing->tmrr = LPDDR3_TMRR; + tmp = ((LPDDR3_TRCD * nmhz + 999) / 1000); + pdram_timing->tmrri = max(3, tmp); + /* ODT */ + pdram_timing->todton = (LPDDR3_TODTON * nmhz + (nmhz >> 1) + 999) + / 1000; + /* ZQ */ + pdram_timing->tzqinit = (LPDDR3_TZQINIT * nmhz + 999) / 1000; + pdram_timing->tzqcs = + ((LPDDR3_TZQCS * nmhz + 999) / 1000); + pdram_timing->tzqoper = + ((LPDDR3_TZQCL * nmhz + 999) / 1000); + tmp = ((LPDDR3_TZQRESET * nmhz + 999) / 1000); + pdram_timing->tzqreset = max(3, tmp); + /* write leveling */ + pdram_timing->twlmrd = (LPDDR3_TWLMRD * nmhz + 999) / 1000; + pdram_timing->twlo = (LPDDR3_TWLO * nmhz + 999) / 1000; + pdram_timing->twldqsen = (LPDDR3_TWLDQSEN * nmhz + 999) / 1000; + /* CA training */ + pdram_timing->tcackel = LPDDR3_TCACKEL; + pdram_timing->tcaent = LPDDR3_TCAENT; + pdram_timing->tcamrd = LPDDR3_TCAMRD; + pdram_timing->tcackeh = LPDDR3_TCACKEH; + pdram_timing->tcaext = LPDDR3_TCAEXT; + pdram_timing->tadr = (LPDDR3_TADR * nmhz + 999) / 1000; + pdram_timing->tmrz = (LPDDR3_TMRZ * nmhz + 999) / 1000; + pdram_timing->tcacd = pdram_timing->tadr + 2; + + /* FSP */ + pdram_timing->tfc_long = (LPDDR3_TFC_LONG * nmhz + 999) / 1000; +} + +#define LPDDR4_TINIT1 (200000) /* 200us */ +#define LPDDR4_TINIT2 (10) /* 10ns */ +#define LPDDR4_TINIT3 (2000000) /* 2ms */ +#define LPDDR4_TINIT4 (5) /* tCK */ +#define LPDDR4_TINIT5 (2000) /* 2us */ +#define LPDDR4_TRSTL LPDDR4_TINIT1 +#define LPDDR4_TRSTH LPDDR4_TINIT3 +#define LPDDR4_TREFI_3_9_US (3900) /* 3.9us */ + +/* base timging */ +#define LPDDR4_TRCD (18) /* tRCD, max(18ns,4tCK) */ +#define LPDDR4_TRP_PB (18) /* tRPpb, max(18ns, 4tCK) */ +#define LPDDR4_TRP_AB (21) /* tRPab, max(21ns, 4tCK) */ +#define LPDDR4_TRRD (10) /* tRRD, max(4tCK,10ns) */ +#define LPDDR4_TCCD_BL16 (8) /* tCK */ +#define LPDDR4_TCCD_BL32 (16) /* tCK */ +#define LPDDR4_TWTR (10) /* tWTR, max(8tCK, 10ns) */ +#define LPDDR4_TRTW (0) /* tCK register min valid value */ +#define LPDDR4_TRAS_MAX (70000) /* 70us */ +#define LPDDR4_TRAS (42) /* tRAS, max(3tCK,42ns) */ +#define LPDDR4_TFAW (40) /* tFAW,min 40ns) */ +#define LPDDR4_TRFC_12GBIT (280) /* tRFC, 280ns(>=12Gb) */ +#define LPDDR4_TRFC_6GBIT (180) /* 6Gb/8Gb 180ns */ +#define LPDDR4_TRFC_4GBIT (130) /* 4Gb 130ns */ +#define LPDDR4_TDQSCK_MIN (1) /* tDQSCKmin,1.5ns */ +#define LPDDR4_TDQSCK_MAX (3) /* tDQSCKmax,3.5ns */ +#define LPDDR4_TPPD (4) /* tCK */ + +/* pd and sr */ +#define LPDDR4_TXP (7) /* tXP, max(5tCK,7.5ns) */ +#define LPDDR4_TCKE (7) /* tCKE, max(7.5ns,4 tCK) */ +#define LPDDR4_TESCKE (1) /* tESCKE, max(1.75ns, 3tCK) */ +#define LPDDR4_TSR (15) /* tSR, max(15ns, 3tCK) */ +#define LPDDR4_TCMDCKE (1) /* max(1.75ns, 3tCK) */ +#define LPDDR4_TCSCKE (1) /* 1.75ns */ +#define LPDDR4_TCKELCS (5) /* max(5ns, 5tCK) */ +#define LPDDR4_TCSCKEH (1) /* 1.75ns */ +#define LPDDR4_TCKEHCS (7) /* max(7.5ns, 5tCK) */ +#define LPDDR4_TMRWCKEL (14) /* max(14ns, 10tCK) */ +#define LPDDR4_TCKELCMD (7) /* max(7.5ns, 3tCK) */ +#define LPDDR4_TCKEHCMD (7) /* max(7.5ns, 3tCK) */ +#define LPDDR4_TCKELPD (7) /* max(7.5ns, 3tCK) */ +#define LPDDR4_TCKCKEL (7) /* max(7.5ns, 3tCK) */ + +/* mode register timing */ +#define LPDDR4_TMRD (14) /* tMRD, (=tMRW), max(14ns, 10 tCK) */ +#define LPDDR4_TMRR (8) /* tMRR, 8 tCK */ + +/* ODT */ +#define LPDDR4_TODTON (3) /* 3.5ns */ + +/* ZQ */ +#define LPDDR4_TZQCAL (1000) /* 1us */ +#define LPDDR4_TZQLAT (30) /* tZQLAT, max(30ns,8tCK) */ +#define LPDDR4_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */ +#define LPDDR4_TZQCKE (1) /* tZQCKE, max(1.75ns, 3tCK) */ + +/* write leveling */ +#define LPDDR4_TWLMRD (40) /* tCK */ +#define LPDDR4_TWLO (20) /* ns */ +#define LPDDR4_TWLDQSEN (20) /* tCK */ + +/* CA training */ +#define LPDDR4_TCAENT (250) /* ns */ +#define LPDDR4_TADR (20) /* ns */ +#define LPDDR4_TMRZ (1) /* 1.5ns */ +#define LPDDR4_TVREF_LONG (250) /* ns */ +#define LPDDR4_TVREF_SHORT (100) /* ns */ + +/* VRCG */ +#define LPDDR4_TVRCG_ENABLE (200) /* ns */ +#define LPDDR4_TVRCG_DISABLE (100) /* ns */ + +/* FSP */ +#define LPDDR4_TFC_LONG (250) /* ns */ +#define LPDDR4_TCKFSPE (7) /* max(7.5ns, 4tCK) */ +#define LPDDR4_TCKFSPX (7) /* max(7.5ns, 4tCK) */ + +/* + * Description: depend on input parameter "timing_config", + * and calculate all lpddr4 + * spec timing to "pdram_timing" + * parameters: + * input: timing_config + * output: pdram_timing + */ +static void lpddr4_get_parameter(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing) +{ + uint32_t nmhz = timing_config->freq; + uint32_t ddr_capability_per_die = get_max_die_capability(timing_config); + uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp; + + zeromem((void *)pdram_timing, sizeof(struct dram_timing_t)); + pdram_timing->mhz = nmhz; + pdram_timing->al = 0; + pdram_timing->bl = timing_config->bl; + + /* + * Only support Write Latency Set A here + * 2133 1866 1600 1333 1066 800 533 266 + * RL, 36 32 28 24 20 14 10 6 + * WL, 18 16 14 12 10 8 6 4 + * nWR, 40 34 30 24 20 16 10 6 + * nRTP,16 14 12 10 8 8 8 8 + */ + tmp = (timing_config->bl == 32) ? 1 : 0; + + /* + * we always use WR preamble = 2tCK + * RD preamble = Static + */ + tmp |= (1 << 2); + if (nmhz <= 266) { + pdram_timing->cl = 6; + pdram_timing->cwl = 4; + pdram_timing->twr = 6; + pdram_timing->trtp = 8; + pdram_timing->mr[2] = LPDDR4_RL6_NRTP8 | LPDDR4_A_WL4; + } else if (nmhz <= 533) { + if (timing_config->rdbi) { + pdram_timing->cl = 12; + pdram_timing->mr[2] = LPDDR4_RL12_NRTP8 | LPDDR4_A_WL6; + } else { + pdram_timing->cl = 10; + pdram_timing->mr[2] = LPDDR4_RL10_NRTP8 | LPDDR4_A_WL6; + } + pdram_timing->cwl = 6; + pdram_timing->twr = 10; + pdram_timing->trtp = 8; + tmp |= (1 << 4); + } else if (nmhz <= 800) { + if (timing_config->rdbi) { + pdram_timing->cl = 16; + pdram_timing->mr[2] = LPDDR4_RL16_NRTP8 | LPDDR4_A_WL8; + } else { + pdram_timing->cl = 14; + pdram_timing->mr[2] = LPDDR4_RL14_NRTP8 | LPDDR4_A_WL8; + } + pdram_timing->cwl = 8; + pdram_timing->twr = 16; + pdram_timing->trtp = 8; + tmp |= (2 << 4); + } else if (nmhz <= 1066) { + if (timing_config->rdbi) { + pdram_timing->cl = 22; + pdram_timing->mr[2] = LPDDR4_RL22_NRTP8 | LPDDR4_A_WL10; + } else { + pdram_timing->cl = 20; + pdram_timing->mr[2] = LPDDR4_RL20_NRTP8 | LPDDR4_A_WL10; + } + pdram_timing->cwl = 10; + pdram_timing->twr = 20; + pdram_timing->trtp = 8; + tmp |= (3 << 4); + } else if (nmhz <= 1333) { + if (timing_config->rdbi) { + pdram_timing->cl = 28; + pdram_timing->mr[2] = LPDDR4_RL28_NRTP10 | + LPDDR4_A_WL12; + } else { + pdram_timing->cl = 24; + pdram_timing->mr[2] = LPDDR4_RL24_NRTP10 | + LPDDR4_A_WL12; + } + pdram_timing->cwl = 12; + pdram_timing->twr = 24; + pdram_timing->trtp = 10; + tmp |= (4 << 4); + } else if (nmhz <= 1600) { + if (timing_config->rdbi) { + pdram_timing->cl = 32; + pdram_timing->mr[2] = LPDDR4_RL32_NRTP12 | + LPDDR4_A_WL14; + } else { + pdram_timing->cl = 28; + pdram_timing->mr[2] = LPDDR4_RL28_NRTP12 | + LPDDR4_A_WL14; + } + pdram_timing->cwl = 14; + pdram_timing->twr = 30; + pdram_timing->trtp = 12; + tmp |= (5 << 4); + } else if (nmhz <= 1866) { + if (timing_config->rdbi) { + pdram_timing->cl = 36; + pdram_timing->mr[2] = LPDDR4_RL36_NRTP14 | + LPDDR4_A_WL16; + } else { + pdram_timing->cl = 32; + pdram_timing->mr[2] = LPDDR4_RL32_NRTP14 | + LPDDR4_A_WL16; + } + pdram_timing->cwl = 16; + pdram_timing->twr = 34; + pdram_timing->trtp = 14; + tmp |= (6 << 4); + } else { + if (timing_config->rdbi) { + pdram_timing->cl = 40; + pdram_timing->mr[2] = LPDDR4_RL40_NRTP16 | + LPDDR4_A_WL18; + } else { + pdram_timing->cl = 36; + pdram_timing->mr[2] = LPDDR4_RL36_NRTP16 | + LPDDR4_A_WL18; + } + pdram_timing->cwl = 18; + pdram_timing->twr = 40; + pdram_timing->trtp = 16; + tmp |= (7 << 4); + } + pdram_timing->mr[1] = tmp; + tmp = (timing_config->rdbi ? LPDDR4_DBI_RD_EN : 0) | + (timing_config->wdbi ? LPDDR4_DBI_WR_EN : 0); + switch (timing_config->dramds) { + case 240: + pdram_timing->mr[3] = LPDDR4_PDDS_240 | tmp; + break; + case 120: + pdram_timing->mr[3] = LPDDR4_PDDS_120 | tmp; + break; + case 80: + pdram_timing->mr[3] = LPDDR4_PDDS_80 | tmp; + break; + case 60: + pdram_timing->mr[3] = LPDDR4_PDDS_60 | tmp; + break; + case 48: + pdram_timing->mr[3] = LPDDR4_PDDS_48 | tmp; + break; + case 40: + default: + pdram_timing->mr[3] = LPDDR4_PDDS_40 | tmp; + break; + } + pdram_timing->mr[0] = 0; + if (timing_config->odt) { + switch (timing_config->dramodt) { + case 240: + tmp = LPDDR4_DQODT_240; + break; + case 120: + tmp = LPDDR4_DQODT_120; + break; + case 80: + tmp = LPDDR4_DQODT_80; + break; + case 60: + tmp = LPDDR4_DQODT_60; + break; + case 48: + tmp = LPDDR4_DQODT_48; + break; + case 40: + default: + tmp = LPDDR4_DQODT_40; + break; + } + + switch (timing_config->caodt) { + case 240: + pdram_timing->mr11 = LPDDR4_CAODT_240 | tmp; + break; + case 120: + pdram_timing->mr11 = LPDDR4_CAODT_120 | tmp; + break; + case 80: + pdram_timing->mr11 = LPDDR4_CAODT_80 | tmp; + break; + case 60: + pdram_timing->mr11 = LPDDR4_CAODT_60 | tmp; + break; + case 48: + pdram_timing->mr11 = LPDDR4_CAODT_48 | tmp; + break; + case 40: + default: + pdram_timing->mr11 = LPDDR4_CAODT_40 | tmp; + break; + } + } else { + pdram_timing->mr11 = LPDDR4_CAODT_DIS | tmp; + } + + pdram_timing->tinit1 = (LPDDR4_TINIT1 * nmhz + 999) / 1000; + pdram_timing->tinit2 = (LPDDR4_TINIT2 * nmhz + 999) / 1000; + pdram_timing->tinit3 = (LPDDR4_TINIT3 * nmhz + 999) / 1000; + pdram_timing->tinit4 = (LPDDR4_TINIT4 * nmhz + 999) / 1000; + pdram_timing->tinit5 = (LPDDR4_TINIT5 * nmhz + 999) / 1000; + pdram_timing->trstl = (LPDDR4_TRSTL * nmhz + 999) / 1000; + pdram_timing->trsth = (LPDDR4_TRSTH * nmhz + 999) / 1000; + /* tREFI, average periodic refresh interval, 3.9us(4Gb-16Gb) */ + pdram_timing->trefi = (LPDDR4_TREFI_3_9_US * nmhz + 999) / 1000; + /* base timing */ + tmp = ((LPDDR4_TRCD * nmhz + 999) / 1000); + pdram_timing->trcd = max(4, tmp); + trppb_tmp = ((LPDDR4_TRP_PB * nmhz + 999) / 1000); + trppb_tmp = max(4, trppb_tmp); + pdram_timing->trppb = trppb_tmp; + trp_tmp = ((LPDDR4_TRP_AB * nmhz + 999) / 1000); + trp_tmp = max(4, trp_tmp); + pdram_timing->trp = trp_tmp; + tras_tmp = ((LPDDR4_TRAS * nmhz + 999) / 1000); + tras_tmp = max(3, tras_tmp); + pdram_timing->tras_min = tras_tmp; + pdram_timing->trc = (tras_tmp + trp_tmp); + tmp = ((LPDDR4_TRRD * nmhz + 999) / 1000); + pdram_timing->trrd = max(4, tmp); + if (timing_config->bl == 32) + pdram_timing->tccd = LPDDR4_TCCD_BL16; + else + pdram_timing->tccd = LPDDR4_TCCD_BL32; + pdram_timing->tccdmw = 4 * pdram_timing->tccd; + tmp = ((LPDDR4_TWTR * nmhz + 999) / 1000); + pdram_timing->twtr = max(8, tmp); + pdram_timing->trtw = ((LPDDR4_TRTW * nmhz + 999) / 1000); + pdram_timing->tras_max = ((LPDDR4_TRAS_MAX * nmhz + 999) / 1000); + pdram_timing->tfaw = (LPDDR4_TFAW * nmhz + 999) / 1000; + if (ddr_capability_per_die > 0x60000000) { + /* >= 12Gb */ + pdram_timing->trfc = + (LPDDR4_TRFC_12GBIT * nmhz + 999) / 1000; + tmp = (((LPDDR4_TRFC_12GBIT + 7) * nmhz + (nmhz >> 1) + + 999) / 1000); + } else if (ddr_capability_per_die > 0x30000000) { + pdram_timing->trfc = + (LPDDR4_TRFC_6GBIT * nmhz + 999) / 1000; + tmp = (((LPDDR4_TRFC_6GBIT + 7) * nmhz + (nmhz >> 1) + + 999) / 1000); + } else { + pdram_timing->trfc = + (LPDDR4_TRFC_4GBIT * nmhz + 999) / 1000; + tmp = (((LPDDR4_TRFC_4GBIT + 7) * nmhz + (nmhz >> 1) + + 999) / 1000); + } + pdram_timing->txsr = max(2, tmp); + pdram_timing->txsnr = max(2, tmp); + /* tdqsck use rounded down */ + pdram_timing->tdqsck = ((LPDDR4_TDQSCK_MIN * nmhz + + (nmhz >> 1)) / 1000); + pdram_timing->tdqsck_max = ((LPDDR4_TDQSCK_MAX * nmhz + + (nmhz >> 1) + 999) / 1000); + pdram_timing->tppd = LPDDR4_TPPD; + /* pd and sr */ + tmp = ((LPDDR4_TXP * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->txp = max(5, tmp); + tmp = ((LPDDR4_TCKE * nmhz + (nmhz >> 1) + 999) / 1000); + pdram_timing->tcke = max(4, tmp); + tmp = ((LPDDR4_TESCKE * nmhz + + ((nmhz * 3) / 4) + + 999) / 1000); + pdram_timing->tescke = max(3, tmp); + tmp = ((LPDDR4_TSR * nmhz + 999) / 1000); + pdram_timing->tsr = max(3, tmp); + tmp = ((LPDDR4_TCMDCKE * nmhz + + ((nmhz * 3) / 4) + + 999) / 1000); + pdram_timing->tcmdcke = max(3, tmp); + pdram_timing->tcscke = ((LPDDR4_TCSCKE * nmhz + + ((nmhz * 3) / 4) + + 999) / 1000); + tmp = ((LPDDR4_TCKELCS * nmhz + 999) / 1000); + pdram_timing->tckelcs = max(5, tmp); + pdram_timing->tcsckeh = ((LPDDR4_TCSCKEH * nmhz + + ((nmhz * 3) / 4) + + 999) / 1000); + tmp = ((LPDDR4_TCKEHCS * nmhz + + (nmhz >> 1) + 999) / 1000); + pdram_timing->tckehcs = max(5, tmp); + tmp = ((LPDDR4_TMRWCKEL * nmhz + 999) / 1000); + pdram_timing->tmrwckel = max(10, tmp); + tmp = ((LPDDR4_TCKELCMD * nmhz + (nmhz >> 1) + + 999) / 1000); + pdram_timing->tckelcmd = max(3, tmp); + tmp = ((LPDDR4_TCKEHCMD * nmhz + (nmhz >> 1) + + 999) / 1000); + pdram_timing->tckehcmd = max(3, tmp); + tmp = ((LPDDR4_TCKELPD * nmhz + (nmhz >> 1) + + 999) / 1000); + pdram_timing->tckelpd = max(3, tmp); + tmp = ((LPDDR4_TCKCKEL * nmhz + (nmhz >> 1) + + 999) / 1000); + pdram_timing->tckckel = max(3, tmp); + /* mode register timing */ + tmp = ((LPDDR4_TMRD * nmhz + 999) / 1000); + pdram_timing->tmrd = max(10, tmp); + pdram_timing->tmrr = LPDDR4_TMRR; + pdram_timing->tmrri = pdram_timing->trcd + 3; + /* ODT */ + pdram_timing->todton = (LPDDR4_TODTON * nmhz + (nmhz >> 1) + 999) + / 1000; + /* ZQ */ + pdram_timing->tzqcal = (LPDDR4_TZQCAL * nmhz + 999) / 1000; + tmp = ((LPDDR4_TZQLAT * nmhz + 999) / 1000); + pdram_timing->tzqlat = max(8, tmp); + tmp = ((LPDDR4_TZQRESET * nmhz + 999) / 1000); + pdram_timing->tzqreset = max(3, tmp); + tmp = ((LPDDR4_TZQCKE * nmhz + + ((nmhz * 3) / 4) + + 999) / 1000); + pdram_timing->tzqcke = max(3, tmp); + /* write leveling */ + pdram_timing->twlmrd = LPDDR4_TWLMRD; + pdram_timing->twlo = (LPDDR4_TWLO * nmhz + 999) / 1000; + pdram_timing->twldqsen = LPDDR4_TWLDQSEN; + /* CA training */ + pdram_timing->tcaent = (LPDDR4_TCAENT * nmhz + 999) / 1000; + pdram_timing->tadr = (LPDDR4_TADR * nmhz + 999) / 1000; + pdram_timing->tmrz = (LPDDR4_TMRZ * nmhz + (nmhz >> 1) + 999) / 1000; + pdram_timing->tvref_long = (LPDDR4_TVREF_LONG * nmhz + 999) / 1000; + pdram_timing->tvref_short = (LPDDR4_TVREF_SHORT * nmhz + 999) / 1000; + /* VRCG */ + pdram_timing->tvrcg_enable = (LPDDR4_TVRCG_ENABLE * nmhz + + 999) / 1000; + pdram_timing->tvrcg_disable = (LPDDR4_TVRCG_DISABLE * nmhz + + 999) / 1000; + /* FSP */ + pdram_timing->tfc_long = (LPDDR4_TFC_LONG * nmhz + 999) / 1000; + tmp = (LPDDR4_TCKFSPE * nmhz + (nmhz >> 1) + 999) / 1000; + pdram_timing->tckfspe = max(4, tmp); + tmp = (LPDDR4_TCKFSPX * nmhz + (nmhz >> 1) + 999) / 1000; + pdram_timing->tckfspx = max(4, tmp); +} + +/* + * Description: depend on input parameter "timing_config", + * and calculate correspond "dram_type" + * spec timing to "pdram_timing" + * parameters: + * input: timing_config + * output: pdram_timing + * NOTE: MR ODT is set, need to disable by controller + */ +void dram_get_parameter(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing) +{ + switch (timing_config->dram_type) { + case DDR3: + ddr3_get_parameter(timing_config, pdram_timing); + break; + case LPDDR2: + lpddr2_get_parameter(timing_config, pdram_timing); + break; + case LPDDR3: + lpddr3_get_parameter(timing_config, pdram_timing); + break; + case LPDDR4: + lpddr4_get_parameter(timing_config, pdram_timing); + break; + default: + /* Do nothing in default case */ + break; + } +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h new file mode 100644 index 0000000..9cda22c --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRAM_SPEC_TIMING_H +#define DRAM_SPEC_TIMING_H + +#include + +enum ddr3_speed_rate { + /* 5-5-5 */ + DDR3_800D = 0, + /* 6-6-6 */ + DDR3_800E = 1, + /* 6-6-6 */ + DDR3_1066E = 2, + /* 7-7-7 */ + DDR3_1066F = 3, + /* 8-8-8 */ + DDR3_1066G = 4, + /* 7-7-7 */ + DDR3_1333F = 5, + /* 8-8-8 */ + DDR3_1333G = 6, + /* 9-9-9 */ + DDR3_1333H = 7, + /* 10-10-10 */ + DDR3_1333J = 8, + /* 8-8-8 */ + DDR3_1600G = 9, + /* 9-9-9 */ + DDR3_1600H = 10, + /* 10-10-10 */ + DDR3_1600J = 11, + /* 11-11-11 */ + DDR3_1600K = 12, + /* 10-10-10 */ + DDR3_1866J = 13, + /* 11-11-11 */ + DDR3_1866K = 14, + /* 12-12-12 */ + DDR3_1866L = 15, + /* 13-13-13 */ + DDR3_1866M = 16, + /* 11-11-11 */ + DDR3_2133K = 17, + /* 12-12-12 */ + DDR3_2133L = 18, + /* 13-13-13 */ + DDR3_2133M = 19, + /* 14-14-14 */ + DDR3_2133N = 20, + DDR3_DEFAULT = 21, +}; + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define range(mi, val, ma) (((ma) > (val)) ? (max(mi, val)) : (ma)) + +struct dram_timing_t { + /* unit MHz */ + uint32_t mhz; + /* some timing unit is us */ + uint32_t tinit1; + uint32_t tinit2; + uint32_t tinit3; + uint32_t tinit4; + uint32_t tinit5; + /* reset low, DDR3:200us */ + uint32_t trstl; + /* reset high to CKE high, DDR3:500us */ + uint32_t trsth; + uint32_t trefi; + /* base */ + uint32_t trcd; + /* trp per bank */ + uint32_t trppb; + /* trp all bank */ + uint32_t trp; + uint32_t twr; + uint32_t tdal; + uint32_t trtp; + uint32_t trc; + uint32_t trrd; + uint32_t tccd; + uint32_t twtr; + uint32_t trtw; + uint32_t tras_max; + uint32_t tras_min; + uint32_t tfaw; + uint32_t trfc; + uint32_t tdqsck; + uint32_t tdqsck_max; + /* pd or sr */ + uint32_t txsr; + uint32_t txsnr; + uint32_t txp; + uint32_t txpdll; + uint32_t tdllk; + uint32_t tcke; + uint32_t tckesr; + uint32_t tcksre; + uint32_t tcksrx; + uint32_t tdpd; + /* mode regiter timing */ + uint32_t tmod; + uint32_t tmrd; + uint32_t tmrr; + uint32_t tmrri; + /* ODT */ + uint32_t todton; + /* ZQ */ + uint32_t tzqinit; + uint32_t tzqcs; + uint32_t tzqoper; + uint32_t tzqreset; + /* Write Leveling */ + uint32_t twlmrd; + uint32_t twlo; + uint32_t twldqsen; + /* CA Training */ + uint32_t tcackel; + uint32_t tcaent; + uint32_t tcamrd; + uint32_t tcackeh; + uint32_t tcaext; + uint32_t tadr; + uint32_t tmrz; + uint32_t tcacd; + /* mode register */ + uint32_t mr[4]; + uint32_t mr11; + /* lpddr4 spec */ + uint32_t mr12; + uint32_t mr13; + uint32_t mr14; + uint32_t mr16; + uint32_t mr17; + uint32_t mr20; + uint32_t mr22; + uint32_t tccdmw; + uint32_t tppd; + uint32_t tescke; + uint32_t tsr; + uint32_t tcmdcke; + uint32_t tcscke; + uint32_t tckelcs; + uint32_t tcsckeh; + uint32_t tckehcs; + uint32_t tmrwckel; + uint32_t tzqcal; + uint32_t tzqlat; + uint32_t tzqcke; + uint32_t tvref_long; + uint32_t tvref_short; + uint32_t tvrcg_enable; + uint32_t tvrcg_disable; + uint32_t tfc_long; + uint32_t tckfspe; + uint32_t tckfspx; + uint32_t tckehcmd; + uint32_t tckelcmd; + uint32_t tckelpd; + uint32_t tckckel; + /* other */ + uint32_t al; + uint32_t cl; + uint32_t cwl; + uint32_t bl; +}; + +struct dram_info_t { + /* speed_rate only used when DDR3 */ + enum ddr3_speed_rate speed_rate; + /* 1: use CS0, 2: use CS0 and CS1 */ + uint32_t cs_cnt; + /* give the max per-die capability on each rank/cs */ + uint32_t per_die_capability[2]; +}; + +struct timing_related_config { + struct dram_info_t dram_info[2]; + uint32_t dram_type; + /* MHz */ + uint32_t freq; + uint32_t ch_cnt; + uint32_t bl; + /* 1:auto precharge, 0:never auto precharge */ + uint32_t ap; + /* + * 1:dll bypass, 0:dll normal + * dram and controller dll bypass at the same time + */ + uint32_t dllbp; + /* 1:odt enable, 0:odt disable */ + uint32_t odt; + /* 1:enable, 0:disabe */ + uint32_t rdbi; + uint32_t wdbi; + /* dram driver strength */ + uint32_t dramds; + /* dram ODT, if odt=0, this parameter invalid */ + uint32_t dramodt; + /* + * ca ODT, if odt=0, this parameter invalid + * it only used by LPDDR4 + */ + uint32_t caodt; +}; + +/* mr0 for ddr3 */ +#define DDR3_BL8 (0) +#define DDR3_BC4_8 (1) +#define DDR3_BC4 (2) +#define DDR3_CL(n) (((((n) - 4) & 0x7) << 4)\ + | ((((n) - 4) & 0x8) >> 1)) +#define DDR3_WR(n) (((n) & 0x7) << 9) +#define DDR3_DLL_RESET (1 << 8) +#define DDR3_DLL_DERESET (0 << 8) + +/* mr1 for ddr3 */ +#define DDR3_DLL_ENABLE (0) +#define DDR3_DLL_DISABLE (1) +#define DDR3_MR1_AL(n) (((n) & 0x3) << 3) + +#define DDR3_DS_40 (0) +#define DDR3_DS_34 (1 << 1) +#define DDR3_RTT_NOM_DIS (0) +#define DDR3_RTT_NOM_60 (1 << 2) +#define DDR3_RTT_NOM_120 (1 << 6) +#define DDR3_RTT_NOM_40 ((1 << 2) | (1 << 6)) +#define DDR3_TDQS (1 << 11) + +/* mr2 for ddr3 */ +#define DDR3_MR2_CWL(n) ((((n) - 5) & 0x7) << 3) +#define DDR3_RTT_WR_DIS (0) +#define DDR3_RTT_WR_60 (1 << 9) +#define DDR3_RTT_WR_120 (2 << 9) + +/* + * MR0 (Device Information) + * 0:DAI complete, 1:DAI still in progress + */ +#define LPDDR2_DAI (0x1) +/* 0:S2 or S4 SDRAM, 1:NVM */ +#define LPDDR2_DI (0x1 << 1) +/* 0:DNV not supported, 1:DNV supported */ +#define LPDDR2_DNVI (0x1 << 2) +#define LPDDR2_RZQI (0x3 << 3) + +/* + * 00:RZQ self test not supported, + * 01:ZQ-pin may connect to VDDCA or float + * 10:ZQ-pin may short to GND. + * 11:ZQ-pin self test completed, no error condition detected. + */ + +/* MR1 (Device Feature) */ +#define LPDDR2_BL4 (0x2) +#define LPDDR2_BL8 (0x3) +#define LPDDR2_BL16 (0x4) +#define LPDDR2_N_WR(n) (((n) - 2) << 5) + +/* MR2 (Device Feature 2) */ +#define LPDDR2_RL3_WL1 (0x1) +#define LPDDR2_RL4_WL2 (0x2) +#define LPDDR2_RL5_WL2 (0x3) +#define LPDDR2_RL6_WL3 (0x4) +#define LPDDR2_RL7_WL4 (0x5) +#define LPDDR2_RL8_WL4 (0x6) + +/* MR3 (IO Configuration 1) */ +#define LPDDR2_DS_34 (0x1) +#define LPDDR2_DS_40 (0x2) +#define LPDDR2_DS_48 (0x3) +#define LPDDR2_DS_60 (0x4) +#define LPDDR2_DS_80 (0x6) +/* optional */ +#define LPDDR2_DS_120 (0x7) + +/* MR4 (Device Temperature) */ +#define LPDDR2_TREF_MASK (0x7) +#define LPDDR2_4_TREF (0x1) +#define LPDDR2_2_TREF (0x2) +#define LPDDR2_1_TREF (0x3) +#define LPDDR2_025_TREF (0x5) +#define LPDDR2_025_TREF_DERATE (0x6) + +#define LPDDR2_TUF (0x1 << 7) + +/* MR8 (Basic configuration 4) */ +#define LPDDR2_S4 (0x0) +#define LPDDR2_S2 (0x1) +#define LPDDR2_N (0x2) +/* Unit:MB */ +#define LPDDR2_DENSITY(mr8) (8 << (((mr8) >> 2) & 0xf)) +#define LPDDR2_IO_WIDTH(mr8) (32 >> (((mr8) >> 6) & 0x3)) + +/* MR10 (Calibration) */ +#define LPDDR2_ZQINIT (0xff) +#define LPDDR2_ZQCL (0xab) +#define LPDDR2_ZQCS (0x56) +#define LPDDR2_ZQRESET (0xc3) + +/* MR16 (PASR Bank Mask), S2 SDRAM Only */ +#define LPDDR2_PASR_FULL (0x0) +#define LPDDR2_PASR_1_2 (0x1) +#define LPDDR2_PASR_1_4 (0x2) +#define LPDDR2_PASR_1_8 (0x3) + +/* + * MR0 (Device Information) + * 0:DAI complete, + * 1:DAI still in progress + */ +#define LPDDR3_DAI (0x1) +/* + * 00:RZQ self test not supported, + * 01:ZQ-pin may connect to VDDCA or float + * 10:ZQ-pin may short to GND. + * 11:ZQ-pin self test completed, no error condition detected. + */ +#define LPDDR3_RZQI (0x3 << 3) +/* + * 0:DRAM does not support WL(Set B), + * 1:DRAM support WL(Set B) + */ +#define LPDDR3_WL_SUPOT (1 << 6) +/* + * 0:DRAM does not support RL=3,nWR=3,WL=1; + * 1:DRAM supports RL=3,nWR=3,WL=1 for frequencies <=166 + */ +#define LPDDR3_RL3_SUPOT (1 << 7) + +/* MR1 (Device Feature) */ +#define LPDDR3_BL8 (0x3) +#define LPDDR3_N_WR(n) ((n) << 5) + +/* MR2 (Device Feature 2), WL Set A,default */ +/* <=166MHz,optional*/ +#define LPDDR3_RL3_WL1 (0x1) +/* <=400MHz*/ +#define LPDDR3_RL6_WL3 (0x4) +/* <=533MHz*/ +#define LPDDR3_RL8_WL4 (0x6) +/* <=600MHz*/ +#define LPDDR3_RL9_WL5 (0x7) +/* <=667MHz,default*/ +#define LPDDR3_RL10_WL6 (0x8) +/* <=733MHz*/ +#define LPDDR3_RL11_WL6 (0x9) +/* <=800MHz*/ +#define LPDDR3_RL12_WL6 (0xa) +/* <=933MHz*/ +#define LPDDR3_RL14_WL8 (0xc) +/* <=1066MHz*/ +#define LPDDR3_RL16_WL8 (0xe) + +/* WL Set B, optional */ +/* <=667MHz,default*/ +#define LPDDR3_RL10_WL8 (0x8) +/* <=733MHz*/ +#define LPDDR3_RL11_WL9 (0x9) +/* <=800MHz*/ +#define LPDDR3_RL12_WL9 (0xa) +/* <=933MHz*/ +#define LPDDR3_RL14_WL11 (0xc) +/* <=1066MHz*/ +#define LPDDR3_RL16_WL13 (0xe) + +/* 1:enable nWR programming > 9(default)*/ +#define LPDDR3_N_WRE (1 << 4) +/* 1:Select WL Set B*/ +#define LPDDR3_WL_S (1 << 6) +/* 1:enable*/ +#define LPDDR3_WR_LEVEL (1 << 7) + +/* MR3 (IO Configuration 1) */ +#define LPDDR3_DS_34 (0x1) +#define LPDDR3_DS_40 (0x2) +#define LPDDR3_DS_48 (0x3) +#define LPDDR3_DS_60 (0x4) +#define LPDDR3_DS_80 (0x6) +#define LPDDR3_DS_34D_40U (0x9) +#define LPDDR3_DS_40D_48U (0xa) +#define LPDDR3_DS_34D_48U (0xb) + +/* MR4 (Device Temperature) */ +#define LPDDR3_TREF_MASK (0x7) +/* SDRAM Low temperature operating limit exceeded */ +#define LPDDR3_LT_EXED (0x0) +#define LPDDR3_4_TREF (0x1) +#define LPDDR3_2_TREF (0x2) +#define LPDDR3_1_TREF (0x3) +#define LPDDR3_05_TREF (0x4) +#define LPDDR3_025_TREF (0x5) +#define LPDDR3_025_TREF_DERATE (0x6) +/* SDRAM High temperature operating limit exceeded */ +#define LPDDR3_HT_EXED (0x7) + +/* 1:value has changed since last read of MR4 */ +#define LPDDR3_TUF (0x1 << 7) + +/* MR8 (Basic configuration 4) */ +#define LPDDR3_S8 (0x3) +#define LPDDR3_DENSITY(mr8) (8 << (((mr8) >> 2) & 0xf)) +#define LPDDR3_IO_WIDTH(mr8) (32 >> (((mr8) >> 6) & 0x3)) + +/* MR10 (Calibration) */ +#define LPDDR3_ZQINIT (0xff) +#define LPDDR3_ZQCL (0xab) +#define LPDDR3_ZQCS (0x56) +#define LPDDR3_ZQRESET (0xc3) + +/* MR11 (ODT Control) */ +#define LPDDR3_ODT_60 (1) +#define LPDDR3_ODT_120 (2) +#define LPDDR3_ODT_240 (3) +#define LPDDR3_ODT_DIS (0) + +/* MR2 (Device Feature 2) */ +/* RL & nRTP for DBI-RD Disabled */ +#define LPDDR4_RL6_NRTP8 (0x0) +#define LPDDR4_RL10_NRTP8 (0x1) +#define LPDDR4_RL14_NRTP8 (0x2) +#define LPDDR4_RL20_NRTP8 (0x3) +#define LPDDR4_RL24_NRTP10 (0x4) +#define LPDDR4_RL28_NRTP12 (0x5) +#define LPDDR4_RL32_NRTP14 (0x6) +#define LPDDR4_RL36_NRTP16 (0x7) +/* RL & nRTP for DBI-RD Disabled */ +#define LPDDR4_RL12_NRTP8 (0x1) +#define LPDDR4_RL16_NRTP8 (0x2) +#define LPDDR4_RL22_NRTP8 (0x3) +#define LPDDR4_RL28_NRTP10 (0x4) +#define LPDDR4_RL32_NRTP12 (0x5) +#define LPDDR4_RL36_NRTP14 (0x6) +#define LPDDR4_RL40_NRTP16 (0x7) +/* WL Set A,default */ +#define LPDDR4_A_WL4 (0x0) +#define LPDDR4_A_WL6 (0x1) +#define LPDDR4_A_WL8 (0x2) +#define LPDDR4_A_WL10 (0x3) +#define LPDDR4_A_WL12 (0x4) +#define LPDDR4_A_WL14 (0x5) +#define LPDDR4_A_WL16 (0x6) +#define LPDDR4_A_WL18 (0x7) +/* WL Set B, optional */ +#define LPDDR4_B_WL4 (0x0 << 3) +#define LPDDR4_B_WL8 (0x1 << 3) +#define LPDDR4_B_WL12 (0x2 << 3) +#define LPDDR4_B_WL18 (0x3 << 3) +#define LPDDR4_B_WL22 (0x4 << 3) +#define LPDDR4_B_WL26 (0x5 << 3) +#define LPDDR4_B_WL30 (0x6 << 3) +#define LPDDR4_B_WL34 (0x7 << 3) +/* 1:Select WL Set B*/ +#define LPDDR4_WL_B (1 << 6) +/* 1:enable*/ +#define LPDDR4_WR_LEVEL (1 << 7) + +/* MR3 */ +#define LPDDR4_VDDQ_2_5 (0) +#define LPDDR4_VDDQ_3 (1) +#define LPDDR4_WRPST_0_5_TCK (0 << 1) +#define LPDDR4_WRPST_1_5_TCK (1 << 1) +#define LPDDR4_PPR_EN (1 << 2) +/* PDDS */ +#define LPDDR4_PDDS_240 (0x1 << 3) +#define LPDDR4_PDDS_120 (0x2 << 3) +#define LPDDR4_PDDS_80 (0x3 << 3) +#define LPDDR4_PDDS_60 (0x4 << 3) +#define LPDDR4_PDDS_48 (0x5 << 3) +#define LPDDR4_PDDS_40 (0x6 << 3) +#define LPDDR4_DBI_RD_EN (1 << 6) +#define LPDDR4_DBI_WR_EN (1 << 7) + +/* MR11 (ODT Control) */ +#define LPDDR4_DQODT_240 (1) +#define LPDDR4_DQODT_120 (2) +#define LPDDR4_DQODT_80 (3) +#define LPDDR4_DQODT_60 (4) +#define LPDDR4_DQODT_48 (5) +#define LPDDR4_DQODT_40 (6) +#define LPDDR4_DQODT_DIS (0) +#define LPDDR4_CAODT_240 (1 << 4) +#define LPDDR4_CAODT_120 (2 << 4) +#define LPDDR4_CAODT_80 (3 << 4) +#define LPDDR4_CAODT_60 (4 << 4) +#define LPDDR4_CAODT_48 (5 << 4) +#define LPDDR4_CAODT_40 (6 << 4) +#define LPDDR4_CAODT_DIS (0 << 4) + +/* + * Description: depend on input parameter "timing_config", + * and calculate correspond "dram_type" + * spec timing to "pdram_timing" + * parameters: + * input: timing_config + * output: pdram_timing + * NOTE: MR ODT is set, need to disable by controller + */ +void dram_get_parameter(struct timing_related_config *timing_config, + struct dram_timing_t *pdram_timing); + +#endif /* DRAM_SPEC_TIMING_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c new file mode 100644 index 0000000..a8b1c32 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c @@ -0,0 +1,852 @@ +/* + * Copyright (c) 2016-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 + +#define PMUGRF_OS_REG0 0x300 +#define PMUGRF_OS_REG1 0x304 +#define PMUGRF_OS_REG2 0x308 +#define PMUGRF_OS_REG3 0x30c + +#define CRU_SFTRST_DDR_CTRL(ch, n) ((0x1 << (8 + 16 + (ch) * 4)) | \ + ((n) << (8 + (ch) * 4))) +#define CRU_SFTRST_DDR_PHY(ch, n) ((0x1 << (9 + 16 + (ch) * 4)) | \ + ((n) << (9 + (ch) * 4))) + +#define FBDIV_ENC(n) ((n) << 16) +#define FBDIV_DEC(n) (((n) >> 16) & 0xfff) +#define POSTDIV2_ENC(n) ((n) << 12) +#define POSTDIV2_DEC(n) (((n) >> 12) & 0x7) +#define POSTDIV1_ENC(n) ((n) << 8) +#define POSTDIV1_DEC(n) (((n) >> 8) & 0x7) +#define REFDIV_ENC(n) (n) +#define REFDIV_DEC(n) ((n) & 0x3f) + +/* PMU CRU */ +#define PMUCRU_RSTNHOLD_CON0 0x120 +#define PMUCRU_RSTNHOLD_CON1 0x124 + +#define PRESET_GPIO0_HOLD(n) (((n) << 7) | WMSK_BIT(7)) +#define PRESET_GPIO1_HOLD(n) (((n) << 8) | WMSK_BIT(8)) + +#define SYS_COUNTER_FREQ_IN_MHZ (SYS_COUNTER_FREQ_IN_TICKS / 1000000) + +__pmusramdata uint32_t dpll_data[PLL_CON_COUNT]; +__pmusramdata uint32_t cru_clksel_con6; +__pmusramdata uint8_t pmu_enable_watchdog0; + +/* + * Copy @num registers from @src to @dst + */ +static __pmusramfunc void sram_regcpy(uintptr_t dst, uintptr_t src, + uint32_t num) +{ + while (num--) { + mmio_write_32(dst, mmio_read_32(src)); + dst += sizeof(uint32_t); + src += sizeof(uint32_t); + } +} + +/* + * Copy @num registers from @src to @dst + * This is intentionally a copy of the sram_regcpy function. PMUSRAM functions + * cannot be called from code running in DRAM. + */ +static void dram_regcpy(uintptr_t dst, uintptr_t src, uint32_t num) +{ + while (num--) { + mmio_write_32(dst, mmio_read_32(src)); + dst += sizeof(uint32_t); + src += sizeof(uint32_t); + } +} + +static __pmusramfunc uint32_t sram_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. + */ + return (uint32_t)(~read_cntpct_el0()); +} + +static __pmusramfunc void sram_udelay(uint32_t usec) +{ + uint32_t start, cnt, delta, total_ticks; + + /* counter is decreasing */ + start = sram_get_timer_value(); + total_ticks = usec * SYS_COUNTER_FREQ_IN_MHZ; + do { + cnt = sram_get_timer_value(); + if (cnt > start) { + delta = UINT32_MAX - cnt; + delta += start; + } else + delta = start - cnt; + } while (delta <= total_ticks); +} + +static __pmusramfunc void configure_sgrf(void) +{ + /* + * SGRF_DDR_RGN_DPLL_CLK and SGRF_DDR_RGN_RTC_CLK: + * IC ECO bug, need to set this register. + * + * SGRF_DDR_RGN_BYPS: + * After the PD_CENTER suspend/resume, the DDR region + * related registers in the SGRF will be reset, we + * need to re-initialize them. + */ + mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16), + SGRF_DDR_RGN_DPLL_CLK | + SGRF_DDR_RGN_RTC_CLK | + SGRF_DDR_RGN_BYPS); +} + +static __pmusramfunc void rkclk_ddr_reset(uint32_t channel, uint32_t ctl, + uint32_t phy) +{ + channel &= 0x1; + ctl &= 0x1; + phy &= 0x1; + mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(4), + CRU_SFTRST_DDR_CTRL(channel, ctl) | + CRU_SFTRST_DDR_PHY(channel, phy)); +} + +static __pmusramfunc void phy_pctrl_reset(uint32_t ch) +{ + rkclk_ddr_reset(ch, 1, 1); + sram_udelay(10); + rkclk_ddr_reset(ch, 1, 0); + sram_udelay(10); + rkclk_ddr_reset(ch, 0, 0); + sram_udelay(10); +} + +static __pmusramfunc void set_cs_training_index(uint32_t ch, uint32_t rank) +{ + uint32_t byte; + + /* PHY_8/136/264/392 phy_per_cs_training_index_X 1bit offset_24 */ + for (byte = 0; byte < 4; byte++) + mmio_clrsetbits_32(PHY_REG(ch, 8 + (128 * byte)), 0x1 << 24, + rank << 24); +} + +static __pmusramfunc void select_per_cs_training_index(uint32_t ch, + uint32_t rank) +{ + /* PHY_84 PHY_PER_CS_TRAINING_EN_0 1bit offset_16 */ + if ((mmio_read_32(PHY_REG(ch, 84)) >> 16) & 1) + set_cs_training_index(ch, rank); +} + +static __pmusramfunc void override_write_leveling_value(uint32_t ch) +{ + uint32_t byte; + + for (byte = 0; byte < 4; byte++) { + /* + * PHY_8/136/264/392 + * phy_per_cs_training_multicast_en_X 1bit offset_16 + */ + mmio_clrsetbits_32(PHY_REG(ch, 8 + (128 * byte)), 0x1 << 16, + 1 << 16); + mmio_clrsetbits_32(PHY_REG(ch, 63 + (128 * byte)), + 0xffffu << 16, + 0x200 << 16); + } + + /* CTL_200 ctrlupd_req 1bit offset_8 */ + mmio_clrsetbits_32(CTL_REG(ch, 200), 0x1 << 8, 0x1 << 8); +} + +static __pmusramfunc int data_training(uint32_t ch, + struct rk3399_sdram_params *sdram_params, + uint32_t training_flag) +{ + uint32_t obs_0, obs_1, obs_2, obs_3, obs_err = 0; + uint32_t rank = sdram_params->ch[ch].rank; + uint32_t rank_mask; + uint32_t i, tmp; + + if (sdram_params->dramtype == LPDDR4) + rank_mask = (rank == 1) ? 0x5 : 0xf; + else + rank_mask = (rank == 1) ? 0x1 : 0x3; + + /* PHY_927 PHY_PAD_DQS_DRIVE RPULL offset_22 */ + mmio_setbits_32(PHY_REG(ch, 927), (1 << 22)); + + if (training_flag == PI_FULL_TRAINING) { + if (sdram_params->dramtype == LPDDR4) { + training_flag = PI_WRITE_LEVELING | + PI_READ_GATE_TRAINING | + PI_READ_LEVELING | + PI_WDQ_LEVELING; + } else if (sdram_params->dramtype == LPDDR3) { + training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING | + PI_READ_GATE_TRAINING; + } else if (sdram_params->dramtype == DDR3) { + training_flag = PI_WRITE_LEVELING | + PI_READ_GATE_TRAINING | + PI_READ_LEVELING; + } + } + + /* ca training(LPDDR4,LPDDR3 support) */ + if ((training_flag & PI_CA_TRAINING) == PI_CA_TRAINING) { + for (i = 0; i < 4; i++) { + if (!(rank_mask & (1 << i))) + continue; + + select_per_cs_training_index(ch, i); + /* PI_100 PI_CALVL_EN:RW:8:2 */ + mmio_clrsetbits_32(PI_REG(ch, 100), 0x3 << 8, 0x2 << 8); + + /* PI_92 PI_CALVL_REQ:WR:16:1,PI_CALVL_CS:RW:24:2 */ + mmio_clrsetbits_32(PI_REG(ch, 92), + (0x1 << 16) | (0x3 << 24), + (0x1 << 16) | (i << 24)); + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + + /* + * check status obs + * PHY_532/660/788 phy_adr_calvl_obs1_:0:32 + */ + obs_0 = mmio_read_32(PHY_REG(ch, 532)); + obs_1 = mmio_read_32(PHY_REG(ch, 660)); + obs_2 = mmio_read_32(PHY_REG(ch, 788)); + if (((obs_0 >> 30) & 0x3) || + ((obs_1 >> 30) & 0x3) || + ((obs_2 >> 30) & 0x3)) + obs_err = 1; + if ((((tmp >> 11) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 5) & 0x1) == 0x0) && + (obs_err == 0)) + break; + else if ((((tmp >> 5) & 0x1) == 0x1) || + (obs_err == 1)) + return -1; + } + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + mmio_clrbits_32(PI_REG(ch, 100), 0x3 << 8); + } + + /* write leveling(LPDDR4,LPDDR3,DDR3 support) */ + if ((training_flag & PI_WRITE_LEVELING) == PI_WRITE_LEVELING) { + for (i = 0; i < rank; i++) { + select_per_cs_training_index(ch, i); + /* PI_60 PI_WRLVL_EN:RW:8:2 */ + mmio_clrsetbits_32(PI_REG(ch, 60), 0x3 << 8, 0x2 << 8); + /* PI_59 PI_WRLVL_REQ:WR:8:1,PI_WRLVL_CS:RW:16:2 */ + mmio_clrsetbits_32(PI_REG(ch, 59), + (0x1 << 8) | (0x3 << 16), + (0x1 << 8) | (i << 16)); + + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + + /* + * check status obs, if error maybe can not + * get leveling done PHY_40/168/296/424 + * phy_wrlvl_status_obs_X:0:13 + */ + obs_0 = mmio_read_32(PHY_REG(ch, 40)); + obs_1 = mmio_read_32(PHY_REG(ch, 168)); + obs_2 = mmio_read_32(PHY_REG(ch, 296)); + obs_3 = mmio_read_32(PHY_REG(ch, 424)); + if (((obs_0 >> 12) & 0x1) || + ((obs_1 >> 12) & 0x1) || + ((obs_2 >> 12) & 0x1) || + ((obs_3 >> 12) & 0x1)) + obs_err = 1; + if ((((tmp >> 10) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 4) & 0x1) == 0x0) && + (obs_err == 0)) + break; + else if ((((tmp >> 4) & 0x1) == 0x1) || + (obs_err == 1)) + return -1; + } + + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + override_write_leveling_value(ch); + mmio_clrbits_32(PI_REG(ch, 60), 0x3 << 8); + } + + /* read gate training(LPDDR4,LPDDR3,DDR3 support) */ + if ((training_flag & PI_READ_GATE_TRAINING) == PI_READ_GATE_TRAINING) { + for (i = 0; i < rank; i++) { + select_per_cs_training_index(ch, i); + /* PI_80 PI_RDLVL_GATE_EN:RW:24:2 */ + mmio_clrsetbits_32(PI_REG(ch, 80), 0x3 << 24, + 0x2 << 24); + /* + * PI_74 PI_RDLVL_GATE_REQ:WR:16:1 + * PI_RDLVL_CS:RW:24:2 + */ + mmio_clrsetbits_32(PI_REG(ch, 74), + (0x1 << 16) | (0x3 << 24), + (0x1 << 16) | (i << 24)); + + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + + /* + * check status obs + * PHY_43/171/299/427 + * PHY_GTLVL_STATUS_OBS_x:16:8 + */ + obs_0 = mmio_read_32(PHY_REG(ch, 43)); + obs_1 = mmio_read_32(PHY_REG(ch, 171)); + obs_2 = mmio_read_32(PHY_REG(ch, 299)); + obs_3 = mmio_read_32(PHY_REG(ch, 427)); + if (((obs_0 >> (16 + 6)) & 0x3) || + ((obs_1 >> (16 + 6)) & 0x3) || + ((obs_2 >> (16 + 6)) & 0x3) || + ((obs_3 >> (16 + 6)) & 0x3)) + obs_err = 1; + if ((((tmp >> 9) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 3) & 0x1) == 0x0) && + (obs_err == 0)) + break; + else if ((((tmp >> 3) & 0x1) == 0x1) || + (obs_err == 1)) + return -1; + } + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + mmio_clrbits_32(PI_REG(ch, 80), 0x3 << 24); + } + + /* read leveling(LPDDR4,LPDDR3,DDR3 support) */ + if ((training_flag & PI_READ_LEVELING) == PI_READ_LEVELING) { + for (i = 0; i < rank; i++) { + select_per_cs_training_index(ch, i); + /* PI_80 PI_RDLVL_EN:RW:16:2 */ + mmio_clrsetbits_32(PI_REG(ch, 80), 0x3 << 16, + 0x2 << 16); + /* PI_74 PI_RDLVL_REQ:WR:8:1,PI_RDLVL_CS:RW:24:2 */ + mmio_clrsetbits_32(PI_REG(ch, 74), + (0x1 << 8) | (0x3 << 24), + (0x1 << 8) | (i << 24)); + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + + /* + * make sure status obs not report error bit + * PHY_46/174/302/430 + * phy_rdlvl_status_obs_X:16:8 + */ + if ((((tmp >> 8) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 2) & 0x1) == 0x0)) + break; + else if (((tmp >> 2) & 0x1) == 0x1) + return -1; + } + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + mmio_clrbits_32(PI_REG(ch, 80), 0x3 << 16); + } + + /* wdq leveling(LPDDR4 support) */ + if ((training_flag & PI_WDQ_LEVELING) == PI_WDQ_LEVELING) { + for (i = 0; i < 4; i++) { + if (!(rank_mask & (1 << i))) + continue; + + select_per_cs_training_index(ch, i); + /* + * disable PI_WDQLVL_VREF_EN before wdq leveling? + * PI_181 PI_WDQLVL_VREF_EN:RW:8:1 + */ + mmio_clrbits_32(PI_REG(ch, 181), 0x1 << 8); + /* PI_124 PI_WDQLVL_EN:RW:16:2 */ + mmio_clrsetbits_32(PI_REG(ch, 124), 0x3 << 16, + 0x2 << 16); + /* PI_121 PI_WDQLVL_REQ:WR:8:1,PI_WDQLVL_CS:RW:16:2 */ + mmio_clrsetbits_32(PI_REG(ch, 121), + (0x1 << 8) | (0x3 << 16), + (0x1 << 8) | (i << 16)); + while (1) { + /* PI_174 PI_INT_STATUS:RD:8:18 */ + tmp = mmio_read_32(PI_REG(ch, 174)) >> 8; + if ((((tmp >> 12) & 0x1) == 0x1) && + (((tmp >> 13) & 0x1) == 0x1) && + (((tmp >> 6) & 0x1) == 0x0)) + break; + else if (((tmp >> 6) & 0x1) == 0x1) + return -1; + } + /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */ + mmio_write_32(PI_REG(ch, 175), 0x00003f7c); + } + mmio_clrbits_32(PI_REG(ch, 124), 0x3 << 16); + } + + /* PHY_927 PHY_PAD_DQS_DRIVE RPULL offset_22 */ + mmio_clrbits_32(PHY_REG(ch, 927), (1 << 22)); + + return 0; +} + +static __pmusramfunc void set_ddrconfig( + struct rk3399_sdram_params *sdram_params, + unsigned char channel, uint32_t ddrconfig) +{ + /* only need to set ddrconfig */ + struct rk3399_sdram_channel *ch = &sdram_params->ch[channel]; + unsigned int cs0_cap = 0; + unsigned int cs1_cap = 0; + + cs0_cap = (1 << (ch->cs0_row + ch->col + ch->bk + ch->bw - 20)); + if (ch->rank > 1) + cs1_cap = cs0_cap >> (ch->cs0_row - ch->cs1_row); + if (ch->row_3_4) { + cs0_cap = cs0_cap * 3 / 4; + cs1_cap = cs1_cap * 3 / 4; + } + + mmio_write_32(MSCH_BASE(channel) + MSCH_DEVICECONF, + ddrconfig | (ddrconfig << 6)); + mmio_write_32(MSCH_BASE(channel) + MSCH_DEVICESIZE, + ((cs0_cap / 32) & 0xff) | (((cs1_cap / 32) & 0xff) << 8)); +} + +static __pmusramfunc void dram_all_config( + struct rk3399_sdram_params *sdram_params) +{ + unsigned int i; + + for (i = 0; i < 2; i++) { + struct rk3399_sdram_channel *info = &sdram_params->ch[i]; + struct rk3399_msch_timings *noc = &info->noc_timings; + + if (sdram_params->ch[i].col == 0) + continue; + + mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGA0, + noc->ddrtiminga0.d32); + mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGB0, + noc->ddrtimingb0.d32); + mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGC0, + noc->ddrtimingc0.d32); + mmio_write_32(MSCH_BASE(i) + MSCH_DEVTODEV0, + noc->devtodev0.d32); + mmio_write_32(MSCH_BASE(i) + MSCH_DDRMODE, noc->ddrmode.d32); + + /* rank 1 memory clock disable (dfi_dram_clk_disable = 1) */ + if (sdram_params->ch[i].rank == 1) + mmio_setbits_32(CTL_REG(i, 276), 1 << 17); + } + + DDR_STRIDE(sdram_params->stride); + + /* reboot hold register set */ + mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1), + CRU_PMU_SGRF_RST_RLS | + PRESET_GPIO0_HOLD(1) | + PRESET_GPIO1_HOLD(1)); + mmio_clrsetbits_32(CRU_BASE + CRU_GLB_RST_CON, 0x3, 0x3); +} + +static __pmusramfunc void pctl_cfg(uint32_t ch, + struct rk3399_sdram_params *sdram_params) +{ + const uint32_t *params_ctl = sdram_params->pctl_regs.denali_ctl; + const uint32_t *params_pi = sdram_params->pi_regs.denali_pi; + const struct rk3399_ddr_publ_regs *phy_regs = &sdram_params->phy_regs; + uint32_t tmp, tmp1, tmp2, i; + + /* + * Workaround controller bug: + * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed + */ + sram_regcpy(CTL_REG(ch, 1), (uintptr_t)¶ms_ctl[1], + CTL_REG_NUM - 1); + mmio_write_32(CTL_REG(ch, 0), params_ctl[0]); + sram_regcpy(PI_REG(ch, 0), (uintptr_t)¶ms_pi[0], + PI_REG_NUM); + + sram_regcpy(PHY_REG(ch, 910), (uintptr_t)&phy_regs->phy896[910 - 896], + 3); + + mmio_clrsetbits_32(CTL_REG(ch, 68), PWRUP_SREFRESH_EXIT, + PWRUP_SREFRESH_EXIT); + + /* PHY_DLL_RST_EN */ + mmio_clrsetbits_32(PHY_REG(ch, 957), 0x3 << 24, 1 << 24); + dmbst(); + + mmio_setbits_32(PI_REG(ch, 0), START); + mmio_setbits_32(CTL_REG(ch, 0), START); + + /* wait lock */ + while (1) { + tmp = mmio_read_32(PHY_REG(ch, 920)); + tmp1 = mmio_read_32(PHY_REG(ch, 921)); + tmp2 = mmio_read_32(PHY_REG(ch, 922)); + if ((((tmp >> 16) & 0x1) == 0x1) && + (((tmp1 >> 16) & 0x1) == 0x1) && + (((tmp1 >> 0) & 0x1) == 0x1) && + (((tmp2 >> 0) & 0x1) == 0x1)) + break; + /* if PLL bypass,don't need wait lock */ + if (mmio_read_32(PHY_REG(ch, 911)) & 0x1) + break; + } + + sram_regcpy(PHY_REG(ch, 896), (uintptr_t)&phy_regs->phy896[0], 63); + + for (i = 0; i < 4; i++) + sram_regcpy(PHY_REG(ch, 128 * i), + (uintptr_t)&phy_regs->phy0[0], 91); + + for (i = 0; i < 3; i++) + sram_regcpy(PHY_REG(ch, 512 + 128 * i), + (uintptr_t)&phy_regs->phy512[i][0], 38); +} + +static __pmusramfunc int dram_switch_to_next_index( + struct rk3399_sdram_params *sdram_params) +{ + uint32_t ch, ch_count; + uint32_t fn = ((mmio_read_32(CTL_REG(0, 111)) >> 16) + 1) & 0x1; + + mmio_write_32(CIC_BASE + CIC_CTRL0, + (((0x3 << 4) | (1 << 2) | 1) << 16) | + (fn << 4) | (1 << 2) | 1); + while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2))) + ; + + mmio_write_32(CIC_BASE + CIC_CTRL0, 0x20002); + while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 0))) + ; + + ch_count = sdram_params->num_channels; + + /* LPDDR4 f2 cann't do training, all training will fail */ + for (ch = 0; ch < ch_count; ch++) { + /* + * Without this disabled for LPDDR4 we end up writing 0's + * in place of real data in an interesting pattern. + */ + if (sdram_params->dramtype != LPDDR4) { + mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1, + fn << 8); + } + + /* data_training failed */ + if (data_training(ch, sdram_params, PI_FULL_TRAINING)) + return -1; + } + + return 0; +} + +/* + * Needs to be done for both channels at once in case of a shared reset signal + * between channels. + */ +static __pmusramfunc int pctl_start(uint32_t channel_mask, + struct rk3399_sdram_params *sdram_params) +{ + uint32_t count; + uint32_t byte; + + mmio_setbits_32(CTL_REG(0, 68), PWRUP_SREFRESH_EXIT); + mmio_setbits_32(CTL_REG(1, 68), PWRUP_SREFRESH_EXIT); + + /* need de-access IO retention before controller START */ + if (channel_mask & (1 << 0)) + mmio_setbits_32(PMU_BASE + PMU_PWRMODE_CON, (1 << 19)); + if (channel_mask & (1 << 1)) + mmio_setbits_32(PMU_BASE + PMU_PWRMODE_CON, (1 << 23)); + + /* PHY_DLL_RST_EN */ + if (channel_mask & (1 << 0)) + mmio_clrsetbits_32(PHY_REG(0, 957), 0x3 << 24, + 0x2 << 24); + if (channel_mask & (1 << 1)) + mmio_clrsetbits_32(PHY_REG(1, 957), 0x3 << 24, + 0x2 << 24); + + /* check ERROR bit */ + if (channel_mask & (1 << 0)) { + count = 0; + while (!(mmio_read_32(CTL_REG(0, 203)) & (1 << 3))) { + /* CKE is low, loop 10ms */ + if (count > 100) + return -1; + + sram_udelay(100); + count++; + } + + mmio_clrbits_32(CTL_REG(0, 68), PWRUP_SREFRESH_EXIT); + + /* Restore the PHY_RX_CAL_DQS value */ + for (byte = 0; byte < 4; byte++) + mmio_clrsetbits_32(PHY_REG(0, 57 + 128 * byte), + 0xfff << 16, + sdram_params->rx_cal_dqs[0][byte]); + } + if (channel_mask & (1 << 1)) { + count = 0; + while (!(mmio_read_32(CTL_REG(1, 203)) & (1 << 3))) { + /* CKE is low, loop 10ms */ + if (count > 100) + return -1; + + sram_udelay(100); + count++; + } + + mmio_clrbits_32(CTL_REG(1, 68), PWRUP_SREFRESH_EXIT); + + /* Restore the PHY_RX_CAL_DQS value */ + for (byte = 0; byte < 4; byte++) + mmio_clrsetbits_32(PHY_REG(1, 57 + 128 * byte), + 0xfff << 16, + sdram_params->rx_cal_dqs[1][byte]); + } + + return 0; +} + +__pmusramfunc static void pmusram_restore_pll(int pll_id, uint32_t *src) +{ + mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE); + + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK); + + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK); + + while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) & + (1U << 31)) == 0x0) + ; +} + +__pmusramfunc static void pmusram_enable_watchdog(void) +{ + /* Make the watchdog use the first global reset. */ + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, 1 << 1); + + /* + * This gives the system ~8 seconds before reset. The pclk for the + * watchdog is 4MHz on reset. The value of 0x9 in WDT_TORR means that + * the watchdog will wait for 0x1ffffff cycles before resetting. + */ + mmio_write_32(WDT0_BASE + 4, 0x9); + + /* Enable the watchdog */ + mmio_setbits_32(WDT0_BASE, 0x1); + + /* Magic reset the watchdog timer value for WDT_CRR. */ + mmio_write_32(WDT0_BASE + 0xc, 0x76); + + secure_watchdog_ungate(); + + /* The watchdog is in PD_ALIVE, so deidle it. */ + mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, PMU_CLR_ALIVE); +} + +void dmc_suspend(void) +{ + struct rk3399_sdram_params *sdram_params = &sdram_config; + struct rk3399_ddr_publ_regs *phy_regs; + uint32_t *params_ctl; + uint32_t *params_pi; + uint32_t refdiv, postdiv2, postdiv1, fbdiv; + uint32_t ch, byte, i; + + phy_regs = &sdram_params->phy_regs; + params_ctl = sdram_params->pctl_regs.denali_ctl; + params_pi = sdram_params->pi_regs.denali_pi; + + /* save dpll register and ddr clock register value to pmusram */ + cru_clksel_con6 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON6); + for (i = 0; i < PLL_CON_COUNT; i++) + dpll_data[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, i)); + + fbdiv = dpll_data[0] & 0xfff; + postdiv2 = POSTDIV2_DEC(dpll_data[1]); + postdiv1 = POSTDIV1_DEC(dpll_data[1]); + refdiv = REFDIV_DEC(dpll_data[1]); + + sdram_params->ddr_freq = ((fbdiv * 24) / + (refdiv * postdiv1 * postdiv2)) * MHz; + + INFO("sdram_params->ddr_freq = %d\n", sdram_params->ddr_freq); + sdram_params->odt = (((mmio_read_32(PHY_REG(0, 5)) >> 16) & + 0x7) != 0) ? 1 : 0; + + /* copy the registers CTL PI and PHY */ + dram_regcpy((uintptr_t)¶ms_ctl[0], CTL_REG(0, 0), CTL_REG_NUM); + + /* mask DENALI_CTL_00_DATA.START, only copy here, will trigger later */ + params_ctl[0] &= ~(0x1 << 0); + + dram_regcpy((uintptr_t)¶ms_pi[0], PI_REG(0, 0), + PI_REG_NUM); + + /* mask DENALI_PI_00_DATA.START, only copy here, will trigger later*/ + params_pi[0] &= ~(0x1 << 0); + + dram_regcpy((uintptr_t)&phy_regs->phy0[0], + PHY_REG(0, 0), 91); + + for (i = 0; i < 3; i++) + dram_regcpy((uintptr_t)&phy_regs->phy512[i][0], + PHY_REG(0, 512 + 128 * i), 38); + + dram_regcpy((uintptr_t)&phy_regs->phy896[0], PHY_REG(0, 896), 63); + + for (ch = 0; ch < sdram_params->num_channels; ch++) { + for (byte = 0; byte < 4; byte++) + sdram_params->rx_cal_dqs[ch][byte] = (0xfff << 16) & + mmio_read_32(PHY_REG(ch, 57 + byte * 128)); + } + + /* set DENALI_PHY_957_DATA.PHY_DLL_RST_EN = 0x1 */ + phy_regs->phy896[957 - 896] &= ~(0x3 << 24); + phy_regs->phy896[957 - 896] |= 1 << 24; + phy_regs->phy896[0] |= 1; + phy_regs->phy896[0] &= ~(0x3 << 8); +} + +__pmusramfunc void phy_dll_bypass_set(uint32_t ch, uint32_t freq) +{ + if (freq <= (125 * 1000 * 1000)) { + /* Set master mode to SW for slices*/ + mmio_setbits_32(PHY_REG(ch, 86), 3 << 10); + mmio_setbits_32(PHY_REG(ch, 214), 3 << 10); + mmio_setbits_32(PHY_REG(ch, 342), 3 << 10); + mmio_setbits_32(PHY_REG(ch, 470), 3 << 10); + /* Set master mode to SW for address slices*/ + mmio_setbits_32(PHY_REG(ch, 547), 3 << 18); + mmio_setbits_32(PHY_REG(ch, 675), 3 << 18); + mmio_setbits_32(PHY_REG(ch, 803), 3 << 18); + } else { + /* Clear SW master mode for slices*/ + mmio_clrbits_32(PHY_REG(ch, 86), 3 << 10); + mmio_clrbits_32(PHY_REG(ch, 214), 3 << 10); + mmio_clrbits_32(PHY_REG(ch, 342), 3 << 10); + mmio_clrbits_32(PHY_REG(ch, 470), 3 << 10); + /* Clear SW master mode for address slices*/ + mmio_clrbits_32(PHY_REG(ch, 547), 3 << 18); + mmio_clrbits_32(PHY_REG(ch, 675), 3 << 18); + mmio_clrbits_32(PHY_REG(ch, 803), 3 << 18); + } +} + +__pmusramfunc void dmc_resume(void) +{ + struct rk3399_sdram_params *sdram_params = &sdram_config; + uint32_t channel_mask = 0; + uint32_t channel; + + /* + * We can't turn off the watchdog, so if we have not turned it on before + * we should not turn it on here. + */ + if ((pmu_enable_watchdog0 & 0x1) == 0x1) { + pmusram_enable_watchdog(); + } + pmu_sgrf_rst_hld_release(); + restore_pmu_rsthold(); + sram_secure_timer_init(); + + /* + * we switch ddr clock to abpll when suspend, + * we set back to dpll here + */ + mmio_write_32(CRU_BASE + CRU_CLKSEL_CON6, + cru_clksel_con6 | REG_SOC_WMSK); + pmusram_restore_pll(DPLL_ID, dpll_data); + + configure_sgrf(); + +retry: + for (channel = 0; channel < sdram_params->num_channels; channel++) { + phy_pctrl_reset(channel); + /* + * Without this, LPDDR4 will write 0's in place of real data + * in a strange pattern. + */ + if (sdram_params->dramtype == LPDDR4) { + phy_dll_bypass_set(channel, sdram_params->ddr_freq); + } + pctl_cfg(channel, sdram_params); + } + + for (channel = 0; channel < 2; channel++) { + if (sdram_params->ch[channel].col) + channel_mask |= 1 << channel; + } + + if (pctl_start(channel_mask, sdram_params) < 0) + goto retry; + + for (channel = 0; channel < sdram_params->num_channels; channel++) { + /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */ + if (sdram_params->dramtype == LPDDR3) + sram_udelay(10); + + /* + * Training here will always fail for LPDDR4, so skip it + * If traning fail, retry to do it again. + */ + if (sdram_params->dramtype != LPDDR4 && + data_training(channel, sdram_params, PI_FULL_TRAINING)) + goto retry; + + set_ddrconfig(sdram_params, channel, + sdram_params->ch[channel].ddrconfig); + } + + dram_all_config(sdram_params); + + /* Switch to index 1 and prepare for DDR frequency switch. */ + dram_switch_to_next_index(sdram_params); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h new file mode 100644 index 0000000..1389944 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUSPEND_H +#define SUSPEND_H + +#include +#include + +#define KHz (1000) +#define MHz (1000 * KHz) +#define GHz (1000 * MHz) + +#define PI_CA_TRAINING (1 << 0) +#define PI_WRITE_LEVELING (1 << 1) +#define PI_READ_GATE_TRAINING (1 << 2) +#define PI_READ_LEVELING (1 << 3) +#define PI_WDQ_LEVELING (1 << 4) +#define PI_FULL_TRAINING (0xff) + +void dmc_suspend(void); +__pmusramfunc void dmc_resume(void); +extern __pmusramdata uint8_t pmu_enable_watchdog0; + +#endif /* SUSPEND_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c new file mode 100644 index 0000000..724968f --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +struct gpio_save { + uint32_t swporta_dr; + uint32_t swporta_ddr; + uint32_t inten; + uint32_t intmask; + uint32_t inttype_level; + uint32_t int_polarity; + uint32_t debounce; + uint32_t ls_sync; +} store_gpio[3]; + +static uint32_t store_grf_gpio[(GRF_GPIO2D_HE - GRF_GPIO2A_IOMUX) / 4 + 1]; + +#define SWPORTA_DR 0x00 +#define SWPORTA_DDR 0x04 +#define INTEN 0x30 +#define INTMASK 0x34 +#define INTTYPE_LEVEL 0x38 +#define INT_POLARITY 0x3c +#define DEBOUNCE 0x48 +#define LS_SYNC 0x60 + +#define EXT_PORTA 0x50 +#define PMU_GPIO_PORT0 0 +#define PMU_GPIO_PORT1 1 +#define GPIO_PORT2 2 +#define GPIO_PORT3 3 +#define GPIO_PORT4 4 + +#define PMU_GRF_GPIO0A_P 0x40 +#define GRF_GPIO2A_P 0xe040 +#define GPIO_P_MASK 0x03 + +#define GET_GPIO_PORT(pin) (pin / 32) +#define GET_GPIO_NUM(pin) (pin % 32) +#define GET_GPIO_BANK(pin) ((pin % 32) / 8) +#define GET_GPIO_ID(pin) ((pin % 32) % 8) + +enum { + ENC_ZDZU, + ENC_ZUDR, + ENC_ZUDZ, + NUM_ENC +}; + +static const struct port_info { + uint32_t clkgate_reg; + uint32_t pull_base; + uint32_t port_base; + /* + * Selects the pull mode encoding per bank, + * first index for pull_type_{hw2sw,sw2hw} + */ + uint8_t pull_enc[4]; + uint8_t clkgate_bit; + uint8_t max_bank; +} port_info[] = { + { + .clkgate_reg = PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), + .pull_base = PMUGRF_BASE + PMUGRF_GPIO0A_P, + .port_base = GPIO0_BASE, + .pull_enc = {ENC_ZDZU, ENC_ZDZU}, + .clkgate_bit = PCLK_GPIO0_GATE_SHIFT, + .max_bank = 1, + }, { + .clkgate_reg = PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), + .pull_base = PMUGRF_BASE + PMUGRF_GPIO1A_P, + .port_base = GPIO1_BASE, + .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR}, + .clkgate_bit = PCLK_GPIO1_GATE_SHIFT, + .max_bank = 3, + }, { + .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31), + .pull_base = GRF_BASE + GRF_GPIO2A_P, + .port_base = GPIO2_BASE, + .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZDZU, ENC_ZDZU}, + .clkgate_bit = PCLK_GPIO2_GATE_SHIFT, + .max_bank = 3, + }, { + .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31), + .pull_base = GRF_BASE + GRF_GPIO3A_P, + .port_base = GPIO3_BASE, + .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR}, + .clkgate_bit = PCLK_GPIO3_GATE_SHIFT, + .max_bank = 3, + }, { + .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31), + .pull_base = GRF_BASE + GRF_GPIO4A_P, + .port_base = GPIO4_BASE, + .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR}, + .clkgate_bit = PCLK_GPIO4_GATE_SHIFT, + .max_bank = 3, + } +}; + +/* + * Mappings between TF-A constants and hardware encodings: + * there are 3 different encoding schemes that may differ between + * banks of the same port: the corresponding value of the pull_enc array + * in port_info is used as the first index + */ +static const uint8_t pull_type_hw2sw[NUM_ENC][4] = { + [ENC_ZDZU] = {GPIO_PULL_NONE, GPIO_PULL_DOWN, GPIO_PULL_NONE, GPIO_PULL_UP}, + [ENC_ZUDR] = {GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN, GPIO_PULL_REPEATER}, + [ENC_ZUDZ] = {GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN, GPIO_PULL_NONE} +}; +static const uint8_t pull_type_sw2hw[NUM_ENC][4] = { + [ENC_ZDZU] = { + [GPIO_PULL_NONE] = 0, + [GPIO_PULL_DOWN] = 1, + [GPIO_PULL_UP] = 3, + [GPIO_PULL_REPEATER] = -1 + }, + [ENC_ZUDR] = { + [GPIO_PULL_NONE] = 0, + [GPIO_PULL_DOWN] = 2, + [GPIO_PULL_UP] = 1, + [GPIO_PULL_REPEATER] = 3 + }, + [ENC_ZUDZ] = { + [GPIO_PULL_NONE] = 0, + [GPIO_PULL_DOWN] = 2, + [GPIO_PULL_UP] = 1, + [GPIO_PULL_REPEATER] = -1 + } +}; + +/* Return old clock state, enables clock, in order to do GPIO access */ +static int gpio_get_clock(uint32_t gpio_number) +{ + uint32_t port = GET_GPIO_PORT(gpio_number); + assert(port < 5U); + + const struct port_info *info = &port_info[port]; + + if ((mmio_read_32(info->clkgate_reg) & (1U << info->clkgate_bit)) == 0U) { + return 0; + } + mmio_write_32( + info->clkgate_reg, + BITS_WITH_WMASK(0, 1, info->clkgate_bit) + ); + return 1; +} + +/* Restore old state of gpio clock, assuming it is running now */ +void gpio_put_clock(uint32_t gpio_number, uint32_t clock_state) +{ + if (clock_state == 0) { + return; + } + uint32_t port = GET_GPIO_PORT(gpio_number); + const struct port_info *info = &port_info[port]; + + mmio_write_32(info->clkgate_reg, BITS_WITH_WMASK(1, 1, info->clkgate_bit)); +} + +static int get_pull(int gpio) +{ + uint32_t port = GET_GPIO_PORT(gpio); + uint32_t bank = GET_GPIO_BANK(gpio); + uint32_t id = GET_GPIO_ID(gpio); + uint32_t val, clock_state; + + assert(port < 5U); + const struct port_info *info = &port_info[port]; + + assert(bank <= info->max_bank); + + clock_state = gpio_get_clock(gpio); + val = (mmio_read_32(info->pull_base + 4 * bank) >> (id * 2)) & GPIO_P_MASK; + gpio_put_clock(gpio, clock_state); + + return pull_type_hw2sw[info->pull_enc[bank]][val]; +} + +static void set_pull(int gpio, int pull) +{ + uint32_t port = GET_GPIO_PORT(gpio); + uint32_t bank = GET_GPIO_BANK(gpio); + uint32_t id = GET_GPIO_ID(gpio); + uint32_t clock_state; + + assert(port < 5U); + const struct port_info *info = &port_info[port]; + + assert(bank <= info->max_bank); + + uint8_t val = pull_type_sw2hw[info->pull_enc[bank]][pull]; + + assert(val != (uint8_t)-1); + + clock_state = gpio_get_clock(gpio); + mmio_write_32( + info->pull_base + 4 * bank, + BITS_WITH_WMASK(val, GPIO_P_MASK, id * 2) + ); + gpio_put_clock(gpio, clock_state); +} + +static void set_direction(int gpio, int direction) +{ + uint32_t port = GET_GPIO_PORT(gpio); + uint32_t num = GET_GPIO_NUM(gpio); + uint32_t clock_state; + + assert((port < 5) && (num < 32)); + + clock_state = gpio_get_clock(gpio); + + /* + * in gpio.h + * #define GPIO_DIR_OUT 0 + * #define GPIO_DIR_IN 1 + * but rk3399 gpio direction 1: output, 0: input + * so need to revert direction value + */ + mmio_setbits_32( + port_info[port].port_base + SWPORTA_DDR, + ((direction == 0) ? 1 : 0) << num + ); + gpio_put_clock(gpio, clock_state); +} + +static int get_direction(int gpio) +{ + uint32_t port = GET_GPIO_PORT(gpio); + uint32_t num = GET_GPIO_NUM(gpio); + int direction, clock_state; + + assert((port < 5U) && (num < 32U)); + + clock_state = gpio_get_clock(gpio); + + /* + * in gpio.h + * #define GPIO_DIR_OUT 0 + * #define GPIO_DIR_IN 1 + * but rk3399 gpio direction 1: output, 0: input + * so need to revert direction value + */ + direction = (((mmio_read_32( + port_info[port].port_base + SWPORTA_DDR + ) >> num) & 1U) == 0) ? 1 : 0; + gpio_put_clock(gpio, clock_state); + + return direction; +} + +static int get_value(int gpio) +{ + uint32_t port = GET_GPIO_PORT(gpio); + uint32_t num = GET_GPIO_NUM(gpio); + int value, clock_state; + + assert((port < 5) && (num < 32)); + + clock_state = gpio_get_clock(gpio); + value = (mmio_read_32(port_info[port].port_base + EXT_PORTA) >> num) & + 0x1U; + gpio_put_clock(gpio, clock_state); + + return value; +} + +static void set_value(int gpio, int value) +{ + uint32_t port = GET_GPIO_PORT(gpio); + uint32_t num = GET_GPIO_NUM(gpio); + uint32_t clock_state; + + assert((port < 5U) && (num < 32U)); + + clock_state = gpio_get_clock(gpio); + mmio_clrsetbits_32( + port_info[port].port_base + SWPORTA_DR, + 1 << num, + ((value == 0) ? 0 : 1) << num + ); + gpio_put_clock(gpio, clock_state); +} + +void plat_rockchip_save_gpio(void) +{ + unsigned int i; + uint32_t cru_gate_save; + + cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31)); + + /* + * when shutdown logic, we need to save gpio2 ~ gpio4 register, + * we need to enable gpio2 ~ gpio4 clock here, since it may be gating, + * and we do not care gpio0 and gpio1 clock gate, since we never + * gating them + */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT)); + + /* + * since gpio0, gpio1 are pmugpio, they will keep ther value + * when shutdown logic power rail, so only need to save gpio2 ~ gpio4 + * register value + */ + for (i = 2; i < 5; i++) { + uint32_t base = port_info[i].port_base; + + store_gpio[i - 2] = (struct gpio_save) { + .swporta_dr = mmio_read_32(base + SWPORTA_DR), + .swporta_ddr = mmio_read_32(base + SWPORTA_DDR), + .inten = mmio_read_32(base + INTEN), + .intmask = mmio_read_32(base + INTMASK), + .inttype_level = mmio_read_32(base + INTTYPE_LEVEL), + .int_polarity = mmio_read_32(base + INT_POLARITY), + .debounce = mmio_read_32(base + DEBOUNCE), + .ls_sync = mmio_read_32(base + LS_SYNC), + }; + } + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + cru_gate_save | REG_SOC_WMSK); + + /* + * gpio0, gpio1 in pmuiomux, they will keep ther value + * when shutdown logic power rail, so only need to save gpio2 ~ gpio4 + * iomux register value + */ + for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++) + store_grf_gpio[i] = + mmio_read_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4); +} + +void plat_rockchip_restore_gpio(void) +{ + int i; + uint32_t cru_gate_save; + + for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++) + mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4, + REG_SOC_WMSK | store_grf_gpio[i]); + + cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31)); + + /* + * when shutdown logic, we need to save gpio2 ~ gpio4 register, + * we need to enable gpio2 ~ gpio4 clock here, since it may be gating, + * and we do not care gpio0 and gpio1 clock gate, since we never + * gating them + */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT)); + + for (i = 2; i < 5; i++) { + uint32_t base = port_info[i].port_base; + const struct gpio_save *save = &store_gpio[i - 2]; + + mmio_write_32(base + SWPORTA_DR, save->swporta_dr); + mmio_write_32(base + SWPORTA_DDR, save->swporta_ddr); + mmio_write_32(base + INTEN, save->inten); + mmio_write_32(base + INTMASK, save->intmask); + mmio_write_32(base + INTTYPE_LEVEL, save->inttype_level), + mmio_write_32(base + INT_POLARITY, save->int_polarity); + mmio_write_32(base + DEBOUNCE, save->debounce); + mmio_write_32(base + LS_SYNC, save->ls_sync); + } + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + cru_gate_save | REG_SOC_WMSK); +} + +const gpio_ops_t rk3399_gpio_ops = { + .get_direction = get_direction, + .set_direction = set_direction, + .get_value = get_value, + .set_value = set_value, + .set_pull = set_pull, + .get_pull = get_pull, +}; + +void plat_rockchip_gpio_init(void) +{ + gpio_init(&rk3399_gpio_ops); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile new file mode 100644 index 0000000..79e09f0 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile @@ -0,0 +1,125 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Cross Compile +M0_CROSS_COMPILE ?= arm-none-eabi- + +# Build architecture +ARCH := cortex-m0 + +# Build platform +PLAT_M0 ?= rk3399m0 +PLAT_M0_PMU ?= rk3399m0pmu + +ifeq (${V},0) + Q=@ +else + Q= +endif +export Q + +.SUFFIXES: + +INCLUDES += -Iinclude/ \ + -I../../include/shared/ + +# NOTE: Add C source files here +C_SOURCES_COMMON := src/startup.c +C_SOURCES := src/dram.c \ + src/stopwatch.c +C_SOURCES_PMU := src/suspend.c + +# Flags definition +COMMON_FLAGS := -g -mcpu=$(ARCH) -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft +CFLAGS := -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-common +ASFLAGS := -Wa,--gdwarf-2 +LDFLAGS := -Wl,--gc-sections -Wl,--build-id=none + +# Cross tool +CC := ${M0_CROSS_COMPILE}gcc +CPP := ${M0_CROSS_COMPILE}cpp +AR := ${M0_CROSS_COMPILE}ar +OC := ${M0_CROSS_COMPILE}objcopy +OD := ${M0_CROSS_COMPILE}objdump +NM := ${M0_CROSS_COMPILE}nm + +# 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 bare 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 + +SOURCES_COMMON := $(C_SOURCES_COMMON) +SOURCES := $(C_SOURCES) +SOURCES_PMU := $(C_SOURCES_PMU) +OBJS_COMMON := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_COMMON))) +OBJS := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES))) +OBJS_PMU := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_PMU))) +LINKERFILE := $(BUILD)/$(PLAT_M0).ld +MAPFILE := $(BUILD)/$(PLAT_M0).map +MAPFILE_PMU := $(BUILD)/$(PLAT_M0_PMU).map +ELF := $(BUILD)/$(PLAT_M0).elf +ELF_PMU := $(BUILD)/$(PLAT_M0_PMU).elf +BIN := $(BUILD)/$(PLAT_M0).bin +BIN_PMU := $(BUILD)/$(PLAT_M0_PMU).bin +LINKERFILE_SRC := src/$(PLAT_M0).ld.S + +# Function definition related compilation +define MAKE_C +$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2)))) +-include $(patsubst %.o,%.d,$(OBJ)) + +$(OBJ) : $(2) + @echo " CC $$<" + $$(Q)$$(CC) $$(COMMON_FLAGS) $$(CFLAGS) $$(INCLUDES) -MMD -MT $$@ -c $$< -o $$@ +endef + +define MAKE_S +$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2)))) + +$(OBJ) : $(2) + @echo " AS $$<" + $$(Q)$$(CC) -x assembler-with-cpp $$(COMMON_FLAGS) $$(ASFLAGS) -c $$< -o $$@ +endef + +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 + +.PHONY: all +all: $(BIN) $(BIN_PMU) + +.DEFAULT_GOAL := all + +$(LINKERFILE): $(LINKERFILE_SRC) + $(CC) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $< +-include $(LINKERFILE).d + +$(ELF) : $(OBJS) $(OBJS_COMMON) $(LINKERFILE) + @echo " LD $@" + $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON) + +%.bin : %.elf + @echo " BIN $@" + $(Q)$(OC) -O binary $< $@ + +$(ELF_PMU) : $(OBJS_COMMON) $(OBJS_PMU) $(LINKERFILE) + @echo " LD $@" + $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON) + +$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_COMMON),$(1))) +$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES),$(1))) +$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_PMU),$(1))) diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h new file mode 100644 index 0000000..d431437 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ADDRESSMAP_H +#define ADDRESSMAP_H + +#include + +/* Registers base address for M0 */ +#define MMIO_BASE 0x40000000 + +#endif /* ADDRESSMAP_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h new file mode 100644 index 0000000..2e90694 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RK3399_MCU_H +#define RK3399_MCU_H + +#include + +typedef unsigned int uint32_t; + +#define mmio_read_32(c) ({unsigned int __v = \ + (*(volatile unsigned int *)(c)); __v; }) +#define mmio_write_32(c, v) ((*(volatile unsigned int *)(c)) = (v)) + +#define mmio_clrbits_32(addr, clear) \ + mmio_write_32(addr, (mmio_read_32(addr) & ~(clear))) +#define mmio_setbits_32(addr, set) \ + mmio_write_32(addr, (mmio_read_32(addr)) | (set)) +#define mmio_clrsetbits_32(addr, clear, set) \ + mmio_write_32(addr, (mmio_read_32(addr) & ~(clear)) | (set)) + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +void stopwatch_init_usecs_expire(unsigned int usecs); +int stopwatch_expired(void); +void stopwatch_reset(void); + +#endif /* RK3399_MCU_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c new file mode 100644 index 0000000..84e8884 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "misc_regs.h" +#include "rk3399_mcu.h" + +static uint32_t gatedis_con0; + +static void idle_port(void) +{ + gatedis_con0 = mmio_read_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0); + mmio_write_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0, 0x3fffffff); + + mmio_setbits_32(PMU_BASE + PMU_BUS_IDLE_REQ, + (1 << PMU_IDLE_REQ_MSCH0) | (1 << PMU_IDLE_REQ_MSCH1)); + while ((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & + ((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0))) != + ((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0))) + continue; +} + +static void deidle_port(void) +{ + mmio_clrbits_32(PMU_BASE + PMU_BUS_IDLE_REQ, + (1 << PMU_IDLE_REQ_MSCH0) | (1 << PMU_IDLE_REQ_MSCH1)); + while (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & + ((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0))) + continue; + + /* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */ + mmio_write_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0, gatedis_con0); +} + +static void ddr_set_pll(void) +{ + mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_SLOW_MODE)); + + mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_POWER_DOWN(1)); + mmio_write_32(CRU_BASE + CRU_DPLL_CON0, + mmio_read_32(PARAM_ADDR + PARAM_DPLL_CON0)); + mmio_write_32(CRU_BASE + CRU_DPLL_CON1, + mmio_read_32(PARAM_ADDR + PARAM_DPLL_CON1)); + mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_POWER_DOWN(0)); + + while ((mmio_read_32(CRU_BASE + CRU_DPLL_CON2) & (1u << 31)) == 0) + continue; + + mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE)); +} + +__attribute__((noreturn)) void m0_main(void) +{ + mmio_setbits_32(PHY_REG(0, 927), (1 << 22)); + mmio_setbits_32(PHY_REG(1, 927), (1 << 22)); + idle_port(); + + mmio_write_32(CIC_BASE + CIC_CTRL0, + (((0x3 << 4) | (1 << 2) | 1) << 16) | + (1 << 2) | 1 | + mmio_read_32(PARAM_ADDR + PARAM_FREQ_SELECT)); + while ((mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2)) == 0) + continue; + + ddr_set_pll(); + mmio_write_32(CIC_BASE + CIC_CTRL0, 0x20002); + while ((mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 0)) == 0) + continue; + + deidle_port(); + mmio_clrbits_32(PHY_REG(0, 927), (1 << 22)); + mmio_clrbits_32(PHY_REG(1, 927), (1 << 22)); + + mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG); + + for (;;) + __asm__ volatile ("wfi"); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S new file mode 100644 index 0000000..bfe054e --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +OUTPUT_FORMAT("elf32-littlearm") + +SECTIONS { + .m0_bin 0 : { + KEEP(*(.isr_vector)) + ASSERT(. == 0xc0, "ISR vector has the wrong size."); + ASSERT(. == PARAM_ADDR, "M0 params should go right behind ISR table."); + . += PARAM_M0_SIZE; + *(.text*) + *(.rodata*) + *(.data*) + *(.bss*) + . = ALIGN(8); + *(.co_stack*) + } + + /DISCARD/ : { *(.comment) *(.note*) } +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c new file mode 100644 index 0000000..dfd8af2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "rk3399_mcu.h" + +/* Stack configuration */ +#define STACK_SIZE 0x00000040 +__attribute__ ((section(".co_stack"))) +unsigned long pstack[STACK_SIZE]; + +/* Macro definition */ +#define WEAK __attribute__ ((weak)) + +/* System exception vector handler */ +__attribute__ ((used)) +void WEAK reset_handler(void); +void WEAK nmi_handler(void); +void WEAK hardware_fault_handler(void); +void WEAK svc_handler(void); +void WEAK pend_sv_handler(void); +void WEAK systick_handler(void); + +extern int m0_main(void); + +/* Function prototypes */ +static void default_reset_handler(void); +static void default_handler(void); + +/* + * The minimal vector table for a Cortex M3. Note that the proper constructs + * must be placed on this to ensure that it ends up at physical address + * 0x00000000. + */ +__attribute__ ((used, section(".isr_vector"))) +void (* const g_pfnVectors[])(void) = { + /* core Exceptions */ + (void *)&pstack[STACK_SIZE], /* the initial stack pointer */ + reset_handler, + nmi_handler, + hardware_fault_handler, + 0, 0, 0, 0, 0, 0, 0, + svc_handler, + 0, 0, + pend_sv_handler, + systick_handler, + + /* external exceptions */ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; + +/** + * This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied m0_main() routine is called. + */ +static void default_reset_handler(void) +{ + /* call the application's entry point */ + m0_main(); +} + +/** + * Provide weak aliases for each Exception handler to the Default_Handler. + * As they are weak aliases, any function with the same name will override + * this definition. + */ +#pragma weak reset_handler = default_reset_handler +#pragma weak nmi_handler = default_handler +#pragma weak hardware_fault_handler = default_handler +#pragma weak svc_handler = default_handler +#pragma weak pend_sv_handler = default_handler +#pragma weak systick_handler = default_handler + +/** + * This is the code that gets called when the processor receives + * an unexpected interrupt. This simply enters an infinite loop, + * preserving the system state for examination by a debugger. + */ +static void default_handler(void) +{ + /* go into an infinite loop. */ + while (1) + ; +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c new file mode 100644 index 0000000..5af8caa --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "rk3399_mcu.h" + +/* use 24MHz SysTick */ +#define US_TO_CYCLE(US) (US * 24) + +#define SYST_CST 0xe000e010 +/* enable counter */ +#define ENABLE (1 << 0) +/* count down to 0 does not cause SysTick exception to pend */ +#define TICKINT (1 << 1) +/* core clock used for SysTick */ +#define CLKSOURCE (1 << 2) + +#define COUNTFLAG (1 << 16) +#define SYST_RVR 0xe000e014 +#define MAX_VALUE 0xffffff +#define MAX_USECS (MAX_VALUE / US_TO_CYCLE(1)) +#define SYST_CVR 0xe000e018 +#define SYST_CALIB 0xe000e01c + +unsigned int remaining_usecs; + +static inline void stopwatch_set_usecs(void) +{ + unsigned int cycle; + unsigned int usecs = MIN(MAX_USECS, remaining_usecs); + + remaining_usecs -= usecs; + cycle = US_TO_CYCLE(usecs); + mmio_write_32(SYST_RVR, cycle); + mmio_write_32(SYST_CVR, 0); + + mmio_write_32(SYST_CST, ENABLE | TICKINT | CLKSOURCE); +} + +void stopwatch_init_usecs_expire(unsigned int usecs) +{ + /* + * Enter an inifite loop if the stopwatch is in use. This will allow the + * state to be analyzed with a debugger. + */ + if (mmio_read_32(SYST_CST) & ENABLE) + while (1) + ; + + remaining_usecs = usecs; + stopwatch_set_usecs(); +} + +int stopwatch_expired(void) +{ + int val = mmio_read_32(SYST_CST); + if ((val & COUNTFLAG) || !(val & ENABLE)) { + if (!remaining_usecs) + return 1; + + stopwatch_set_usecs(); + } + + return 0; +} + +void stopwatch_reset(void) +{ + mmio_clrbits_32(SYST_CST, ENABLE); + remaining_usecs = 0; +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c new file mode 100644 index 0000000..9ad2fa2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "rk3399_mcu.h" + +#define M0_SCR 0xe000ed10 /* System Control Register (SCR) */ + +#define SCR_SLEEPDEEP_SHIFT (1 << 2) + +__attribute__((noreturn)) void m0_main(void) +{ + unsigned int status_value; + + /* + * PMU sometimes doesn't clear power mode bit as it's supposed to due + * to a hardware bug. Make the M0 clear it manually to be sure, + * otherwise interrupts some cases with concurrent wake interrupts + * we stay asleep forever. + */ + while (1) { + status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST); + if (status_value) { + mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01); + break; + } + } + + /* + * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. -> + * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP -> + * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> .., + * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by + * power or other single glitch, but WAKEUP_RESET need work with 24MHz, + * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance + * that glitch will affect SOC, and mess up SOC status, so we + * addressmap_shared software clamp between ST_INPUT_CLAMP and + * ST_WAKEUP_RESET_CLR to avoid this happen. + */ + while (1) { + status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST); + if (status_value >= 17) { + mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02); + break; + } + + } + + while (1) { + status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST); + if (status_value >= 26) { + mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02); + break; + } + } + + for (;;) + __asm__ volatile ("wfi"); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c new file mode 100644 index 0000000..cad76ac --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void m0_init(void) +{ + /* secure config for M0 */ + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7)); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), WMSK_BIT(12)); + + /* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */ + mmio_setbits_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, 0x02); + + /* + * To switch the parent to xin24M and div == 1, + * + * We need to close most of the PLLs and clocks except the OSC 24MHz + * durning suspend, and this should be enough to supplies the ddrfreq, + * For the simple handle, we just keep the fixed 24MHz to supply the + * suspend and ddrfreq directly. + */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKSEL_CON0, + BIT_WITH_WMSK(15) | BITS_WITH_WMASK(0x0, 0x1f, 8)); + + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, WMSK_BIT(5)); +} + +void m0_configure_execute_addr(uintptr_t addr) +{ + /* set the execute address for M0 */ + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3), + BITS_WITH_WMASK((addr >> 12) & 0xffff, + 0xffffu, 0)); + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7), + BITS_WITH_WMASK((addr >> 28) & 0xf, + 0xfu, 0)); +} + +void m0_start(void) +{ + /* enable clocks for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, + BITS_WITH_WMASK(0x0, 0xf, 0)); + + /* clean the PARAM_M0_DONE flag, mean that M0 will start working */ + mmio_write_32(M0_PARAM_ADDR + PARAM_M0_DONE, 0); + dmbst(); + + mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, + BITS_WITH_WMASK(0x0, 0x4, 0)); + + udelay(5); + /* start M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, + BITS_WITH_WMASK(0x0, 0x20, 0)); + dmbst(); +} + +void m0_stop(void) +{ + /* stop M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, + BITS_WITH_WMASK(0x24, 0x24, 0)); + + /* disable clocks for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, + BITS_WITH_WMASK(0xf, 0xf, 0)); +} + +void m0_wait_done(void) +{ + do { + /* + * Don't starve the M0 for access to SRAM, so delay before + * reading the PARAM_M0_DONE value again. + */ + udelay(5); + dsb(); + } while (mmio_read_32(M0_PARAM_ADDR + PARAM_M0_DONE) != M0_DONE_FLAG); + + /* + * Let the M0 settle into WFI before we leave. This is so we don't reset + * the M0 in a bad spot which can cause problems with the M0. + */ + udelay(10); + dsb(); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h new file mode 100644 index 0000000..7542e22 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef M0_CTL_H +#define M0_CTL_H + +#include + +#define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin) +#define M0_PARAM_ADDR (M0_BINCODE_BASE + PARAM_ADDR) +#define M0PMU_BINCODE_BASE ((uintptr_t)rk3399m0pmu_bin) + +/* pmu_fw.c */ +extern char rk3399m0_bin[]; +extern char rk3399m0_bin_end[]; + +extern char rk3399m0pmu_bin[]; +extern char rk3399m0pmu_bin_end[]; + +extern void m0_init(void); +extern void m0_start(void); +extern void m0_stop(void); +extern void m0_wait_done(void); +extern void m0_configure_execute_addr(uintptr_t addr); + +#endif /* M0_CTL_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..546c09a --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl clst_warmboot_data + + .macro sram_func _name + .cfi_sections .debug_frame + .section .sram.text, "ax" + .type \_name, %function + .cfi_startproc + \_name: + .endm + +#define CRU_CLKSEL_CON6 0x118 + +#define DDRCTL0_C_SYSREQ_CFG 0x0100 +#define DDRCTL1_C_SYSREQ_CFG 0x1000 + +#define DDRC0_SREF_DONE_EXT 0x01 +#define DDRC1_SREF_DONE_EXT 0x04 + +#define PLL_MODE_SHIFT (0x8) +#define PLL_NORMAL_MODE ((0x3 << (PLL_MODE_SHIFT + 16)) | \ + (0x1 << PLL_MODE_SHIFT)) +#define MPIDR_CLST_L_BITS 0x0 + /* + * For different socs, if we want to speed up warmboot, + * we need to config some regs here. + * If scu was suspend, we must resume related clk + * from slow (24M) mode to normal mode first. + * X0: MPIDR_EL1 & MPIDR_CLUSTER_MASK + */ +.macro func_rockchip_clst_warmboot + adr x4, clst_warmboot_data + lsr x5, x0, #6 + ldr w3, [x4, x5] + str wzr, [x4, x5] + cmp w3, #PMU_CLST_RET + b.ne clst_warmboot_end + ldr w6, =(PLL_NORMAL_MODE) + /* + * core_l offset is CRU_BASE + 0xc, + * core_b offset is CRU_BASE + 0x2c + */ + ldr x7, =(CRU_BASE + 0xc) + lsr x2, x0, #3 + str w6, [x7, x2] +clst_warmboot_end: +.endm + +.macro rockchip_clst_warmboot_data +clst_warmboot_data: + .rept PLATFORM_CLUSTER_COUNT + .word 0 + .endr +.endm + + /* ----------------------------------------------- + * void sram_func_set_ddrctl_pll(uint32_t pll_src) + * Function to switch the PLL source for ddrctrl + * In: x0 - The PLL of the clk_ddrc clock source + * out: None + * Clobber list : x0 - x3, x5, x8 - x10 + * ----------------------------------------------- + */ + + .globl sram_func_set_ddrctl_pll + +sram_func sram_func_set_ddrctl_pll + /* backup parameter */ + mov x8, x0 + + /* disable the MMU at EL3 */ + mrs x9, sctlr_el3 + bic x10, x9, #(SCTLR_M_BIT) + msr sctlr_el3, x10 + isb + dsb sy + + /* enable ddrctl0_1 idle request */ + mov x5, PMU_BASE + ldr w0, [x5, #PMU_SFT_CON] + orr w0, w0, #DDRCTL0_C_SYSREQ_CFG + orr w0, w0, #DDRCTL1_C_SYSREQ_CFG + str w0, [x5, #PMU_SFT_CON] + +check_ddrc0_1_sref_enter: + ldr w1, [x5, #PMU_DDR_SREF_ST] + and w2, w1, #DDRC0_SREF_DONE_EXT + and w3, w1, #DDRC1_SREF_DONE_EXT + orr w2, w2, w3 + cmp w2, #(DDRC0_SREF_DONE_EXT | DDRC1_SREF_DONE_EXT) + b.eq check_ddrc0_1_sref_enter + + /* + * select a PLL for ddrctrl: + * x0 = 0: ALPLL + * x0 = 1: ABPLL + * x0 = 2: DPLL + * x0 = 3: GPLLL + */ + mov x5, CRU_BASE + lsl w0, w8, #4 + orr w0, w0, #0x00300000 + str w0, [x5, #CRU_CLKSEL_CON6] + + /* disable ddrctl0_1 idle request */ + mov x5, PMU_BASE + ldr w0, [x5, #PMU_SFT_CON] + bic w0, w0, #DDRCTL0_C_SYSREQ_CFG + bic w0, w0, #DDRCTL1_C_SYSREQ_CFG + str w0, [x5, #PMU_SFT_CON] + +check_ddrc0_1_sref_exit: + ldr w1, [x5, #PMU_DDR_SREF_ST] + and w2, w1, #DDRC0_SREF_DONE_EXT + and w3, w1, #DDRC1_SREF_DONE_EXT + orr w2, w2, w3 + cmp w2, #0x0 + b.eq check_ddrc0_1_sref_exit + + /* reenable the MMU at EL3 */ + msr sctlr_el3, x9 + isb + dsb sy + + ret +endfunc sram_func_set_ddrctl_pll diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c new file mode 100644 index 0000000..3084c4f --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -0,0 +1,1626 @@ +/* + * Copyright (c) 2016-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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_BAKERY_LOCK(rockchip_pd_lock); + +static uint32_t cpu_warm_boot_addr; +static char store_sram[SRAM_BIN_LIMIT + SRAM_TEXT_LIMIT + SRAM_DATA_LIMIT]; +static uint32_t store_cru[CRU_SDIO0_CON1 / 4 + 1]; +static uint32_t store_usbphy0[7]; +static uint32_t store_usbphy1[7]; +static uint32_t store_grf_io_vsel; +static uint32_t store_grf_soc_con0; +static uint32_t store_grf_soc_con1; +static uint32_t store_grf_soc_con2; +static uint32_t store_grf_soc_con3; +static uint32_t store_grf_soc_con4; +static uint32_t store_grf_soc_con7; +static uint32_t store_grf_ddrc_con[4]; +static uint32_t store_wdt0[2]; +static uint32_t store_wdt1[2]; +static gicv3_dist_ctx_t dist_ctx; +static gicv3_redist_ctx_t rdist_ctx; + +/* + * There are two ways to powering on or off on core. + * 1) Control it power domain into on or off in PMU_PWRDN_CON reg, + * it is core_pwr_pd mode + * 2) Enable the core power manage in PMU_CORE_PM_CON reg, + * then, if the core enter into wfi, it power domain will be + * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode + * so we need core_pm_cfg_info to distinguish which method be used now. + */ + +static uint32_t core_pm_cfg_info[PLATFORM_CORE_COUNT] +#if USE_COHERENT_MEM +__attribute__ ((section("tzfw_coherent_mem"))) +#endif +;/* coheront */ + +static void pmu_bus_idle_req(uint32_t bus, uint32_t state) +{ + uint32_t bus_id = BIT(bus); + uint32_t bus_req; + uint32_t wait_cnt = 0; + uint32_t bus_state, bus_ack; + + if (state) + bus_req = BIT(bus); + else + bus_req = 0; + + mmio_clrsetbits_32(PMU_BASE + PMU_BUS_IDLE_REQ, bus_id, bus_req); + + do { + bus_state = mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & bus_id; + bus_ack = mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK) & bus_id; + if (bus_state == bus_req && bus_ack == bus_req) + break; + + wait_cnt++; + udelay(1); + } while (wait_cnt < MAX_WAIT_COUNT); + + if (bus_state != bus_req || bus_ack != bus_req) { + INFO("%s:st=%x(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST), + bus_state); + INFO("%s:st=%x(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK), + bus_ack); + } +} + +struct pmu_slpdata_s pmu_slpdata; + +static void qos_restore(void) +{ + if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.gpu_qos, GPU); + if (pmu_power_domain_st(PD_ISP0) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.isp0_m0_qos, ISP0_M0); + RESTORE_QOS(pmu_slpdata.isp0_m1_qos, ISP0_M1); + } + if (pmu_power_domain_st(PD_ISP1) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.isp1_m0_qos, ISP1_M0); + RESTORE_QOS(pmu_slpdata.isp1_m1_qos, ISP1_M1); + } + if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.vop_big_r, VOP_BIG_R); + RESTORE_QOS(pmu_slpdata.vop_big_w, VOP_BIG_W); + RESTORE_QOS(pmu_slpdata.vop_little, VOP_LITTLE); + } + if (pmu_power_domain_st(PD_HDCP) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.hdcp_qos, HDCP); + if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.gmac_qos, GMAC); + if (pmu_power_domain_st(PD_CCI) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.cci_m0_qos, CCI_M0); + RESTORE_QOS(pmu_slpdata.cci_m1_qos, CCI_M1); + } + if (pmu_power_domain_st(PD_SD) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.sdmmc_qos, SDMMC); + if (pmu_power_domain_st(PD_EMMC) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.emmc_qos, EMMC); + if (pmu_power_domain_st(PD_SDIOAUDIO) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.sdio_qos, SDIO); + if (pmu_power_domain_st(PD_GIC) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.gic_qos, GIC); + if (pmu_power_domain_st(PD_RGA) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.rga_r_qos, RGA_R); + RESTORE_QOS(pmu_slpdata.rga_w_qos, RGA_W); + } + if (pmu_power_domain_st(PD_IEP) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.iep_qos, IEP); + if (pmu_power_domain_st(PD_USB3) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.usb_otg0_qos, USB_OTG0); + RESTORE_QOS(pmu_slpdata.usb_otg1_qos, USB_OTG1); + } + if (pmu_power_domain_st(PD_PERIHP) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.usb_host0_qos, USB_HOST0); + RESTORE_QOS(pmu_slpdata.usb_host1_qos, USB_HOST1); + RESTORE_QOS(pmu_slpdata.perihp_nsp_qos, PERIHP_NSP); + } + if (pmu_power_domain_st(PD_PERILP) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.dmac0_qos, DMAC0); + RESTORE_QOS(pmu_slpdata.dmac1_qos, DMAC1); + RESTORE_QOS(pmu_slpdata.dcf_qos, DCF); + RESTORE_QOS(pmu_slpdata.crypto0_qos, CRYPTO0); + RESTORE_QOS(pmu_slpdata.crypto1_qos, CRYPTO1); + RESTORE_QOS(pmu_slpdata.perilp_nsp_qos, PERILP_NSP); + RESTORE_QOS(pmu_slpdata.perilpslv_nsp_qos, PERILPSLV_NSP); + RESTORE_QOS(pmu_slpdata.peri_cm1_qos, PERI_CM1); + } + if (pmu_power_domain_st(PD_VDU) == pmu_pd_on) + RESTORE_QOS(pmu_slpdata.video_m0_qos, VIDEO_M0); + if (pmu_power_domain_st(PD_VCODEC) == pmu_pd_on) { + RESTORE_QOS(pmu_slpdata.video_m1_r_qos, VIDEO_M1_R); + RESTORE_QOS(pmu_slpdata.video_m1_w_qos, VIDEO_M1_W); + } +} + +static void qos_save(void) +{ + if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.gpu_qos, GPU); + if (pmu_power_domain_st(PD_ISP0) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.isp0_m0_qos, ISP0_M0); + SAVE_QOS(pmu_slpdata.isp0_m1_qos, ISP0_M1); + } + if (pmu_power_domain_st(PD_ISP1) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.isp1_m0_qos, ISP1_M0); + SAVE_QOS(pmu_slpdata.isp1_m1_qos, ISP1_M1); + } + if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.vop_big_r, VOP_BIG_R); + SAVE_QOS(pmu_slpdata.vop_big_w, VOP_BIG_W); + SAVE_QOS(pmu_slpdata.vop_little, VOP_LITTLE); + } + if (pmu_power_domain_st(PD_HDCP) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.hdcp_qos, HDCP); + if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.gmac_qos, GMAC); + if (pmu_power_domain_st(PD_CCI) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.cci_m0_qos, CCI_M0); + SAVE_QOS(pmu_slpdata.cci_m1_qos, CCI_M1); + } + if (pmu_power_domain_st(PD_SD) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.sdmmc_qos, SDMMC); + if (pmu_power_domain_st(PD_EMMC) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.emmc_qos, EMMC); + if (pmu_power_domain_st(PD_SDIOAUDIO) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.sdio_qos, SDIO); + if (pmu_power_domain_st(PD_GIC) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.gic_qos, GIC); + if (pmu_power_domain_st(PD_RGA) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.rga_r_qos, RGA_R); + SAVE_QOS(pmu_slpdata.rga_w_qos, RGA_W); + } + if (pmu_power_domain_st(PD_IEP) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.iep_qos, IEP); + if (pmu_power_domain_st(PD_USB3) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.usb_otg0_qos, USB_OTG0); + SAVE_QOS(pmu_slpdata.usb_otg1_qos, USB_OTG1); + } + if (pmu_power_domain_st(PD_PERIHP) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.usb_host0_qos, USB_HOST0); + SAVE_QOS(pmu_slpdata.usb_host1_qos, USB_HOST1); + SAVE_QOS(pmu_slpdata.perihp_nsp_qos, PERIHP_NSP); + } + if (pmu_power_domain_st(PD_PERILP) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.dmac0_qos, DMAC0); + SAVE_QOS(pmu_slpdata.dmac1_qos, DMAC1); + SAVE_QOS(pmu_slpdata.dcf_qos, DCF); + SAVE_QOS(pmu_slpdata.crypto0_qos, CRYPTO0); + SAVE_QOS(pmu_slpdata.crypto1_qos, CRYPTO1); + SAVE_QOS(pmu_slpdata.perilp_nsp_qos, PERILP_NSP); + SAVE_QOS(pmu_slpdata.perilpslv_nsp_qos, PERILPSLV_NSP); + SAVE_QOS(pmu_slpdata.peri_cm1_qos, PERI_CM1); + } + if (pmu_power_domain_st(PD_VDU) == pmu_pd_on) + SAVE_QOS(pmu_slpdata.video_m0_qos, VIDEO_M0); + if (pmu_power_domain_st(PD_VCODEC) == pmu_pd_on) { + SAVE_QOS(pmu_slpdata.video_m1_r_qos, VIDEO_M1_R); + SAVE_QOS(pmu_slpdata.video_m1_w_qos, VIDEO_M1_W); + } +} + +static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state) +{ + uint32_t state; + + if (pmu_power_domain_st(pd_id) == pd_state) + goto out; + + if (pd_state == pmu_pd_on) + pmu_power_domain_ctr(pd_id, pd_state); + + state = (pd_state == pmu_pd_off) ? BUS_IDLE : BUS_ACTIVE; + + switch (pd_id) { + case PD_GPU: + pmu_bus_idle_req(BUS_ID_GPU, state); + break; + case PD_VIO: + pmu_bus_idle_req(BUS_ID_VIO, state); + break; + case PD_ISP0: + pmu_bus_idle_req(BUS_ID_ISP0, state); + break; + case PD_ISP1: + pmu_bus_idle_req(BUS_ID_ISP1, state); + break; + case PD_VO: + pmu_bus_idle_req(BUS_ID_VOPB, state); + pmu_bus_idle_req(BUS_ID_VOPL, state); + break; + case PD_HDCP: + pmu_bus_idle_req(BUS_ID_HDCP, state); + break; + case PD_TCPD0: + break; + case PD_TCPD1: + break; + case PD_GMAC: + pmu_bus_idle_req(BUS_ID_GMAC, state); + break; + case PD_CCI: + pmu_bus_idle_req(BUS_ID_CCIM0, state); + pmu_bus_idle_req(BUS_ID_CCIM1, state); + break; + case PD_SD: + pmu_bus_idle_req(BUS_ID_SD, state); + break; + case PD_EMMC: + pmu_bus_idle_req(BUS_ID_EMMC, state); + break; + case PD_EDP: + pmu_bus_idle_req(BUS_ID_EDP, state); + break; + case PD_SDIOAUDIO: + pmu_bus_idle_req(BUS_ID_SDIOAUDIO, state); + break; + case PD_GIC: + pmu_bus_idle_req(BUS_ID_GIC, state); + break; + case PD_RGA: + pmu_bus_idle_req(BUS_ID_RGA, state); + break; + case PD_VCODEC: + pmu_bus_idle_req(BUS_ID_VCODEC, state); + break; + case PD_VDU: + pmu_bus_idle_req(BUS_ID_VDU, state); + break; + case PD_IEP: + pmu_bus_idle_req(BUS_ID_IEP, state); + break; + case PD_USB3: + pmu_bus_idle_req(BUS_ID_USB3, state); + break; + case PD_PERIHP: + pmu_bus_idle_req(BUS_ID_PERIHP, state); + break; + default: + /* Do nothing in default case */ + break; + } + + if (pd_state == pmu_pd_off) + pmu_power_domain_ctr(pd_id, pd_state); + +out: + return 0; +} + +static uint32_t pmu_powerdomain_state; + +static void pmu_power_domains_suspend(void) +{ + clk_gate_con_save(); + clk_gate_con_disable(); + qos_save(); + pmu_powerdomain_state = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); + pmu_set_power_domain(PD_GPU, pmu_pd_off); + pmu_set_power_domain(PD_TCPD0, pmu_pd_off); + pmu_set_power_domain(PD_TCPD1, pmu_pd_off); + pmu_set_power_domain(PD_VO, pmu_pd_off); + pmu_set_power_domain(PD_ISP0, pmu_pd_off); + pmu_set_power_domain(PD_ISP1, pmu_pd_off); + pmu_set_power_domain(PD_HDCP, pmu_pd_off); + pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_off); + pmu_set_power_domain(PD_GMAC, pmu_pd_off); + pmu_set_power_domain(PD_EDP, pmu_pd_off); + pmu_set_power_domain(PD_IEP, pmu_pd_off); + pmu_set_power_domain(PD_RGA, pmu_pd_off); + pmu_set_power_domain(PD_VCODEC, pmu_pd_off); + pmu_set_power_domain(PD_VDU, pmu_pd_off); + pmu_set_power_domain(PD_USB3, pmu_pd_off); + pmu_set_power_domain(PD_EMMC, pmu_pd_off); + pmu_set_power_domain(PD_VIO, pmu_pd_off); + pmu_set_power_domain(PD_SD, pmu_pd_off); + pmu_set_power_domain(PD_PERIHP, pmu_pd_off); + clk_gate_con_restore(); +} + +static void pmu_power_domains_resume(void) +{ + clk_gate_con_save(); + clk_gate_con_disable(); + if (!(pmu_powerdomain_state & BIT(PD_VDU))) + pmu_set_power_domain(PD_VDU, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VCODEC))) + pmu_set_power_domain(PD_VCODEC, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_RGA))) + pmu_set_power_domain(PD_RGA, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_IEP))) + pmu_set_power_domain(PD_IEP, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_EDP))) + pmu_set_power_domain(PD_EDP, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_GMAC))) + pmu_set_power_domain(PD_GMAC, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_SDIOAUDIO))) + pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_HDCP))) + pmu_set_power_domain(PD_HDCP, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_ISP1))) + pmu_set_power_domain(PD_ISP1, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_ISP0))) + pmu_set_power_domain(PD_ISP0, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VO))) + pmu_set_power_domain(PD_VO, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_TCPD1))) + pmu_set_power_domain(PD_TCPD1, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_TCPD0))) + pmu_set_power_domain(PD_TCPD0, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_GPU))) + pmu_set_power_domain(PD_GPU, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_USB3))) + pmu_set_power_domain(PD_USB3, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_EMMC))) + pmu_set_power_domain(PD_EMMC, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_VIO))) + pmu_set_power_domain(PD_VIO, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_SD))) + pmu_set_power_domain(PD_SD, pmu_pd_on); + if (!(pmu_powerdomain_state & BIT(PD_PERIHP))) + pmu_set_power_domain(PD_PERIHP, pmu_pd_on); + qos_restore(); + clk_gate_con_restore(); +} + +void pmu_power_domains_on(void) +{ + clk_gate_con_disable(); + pmu_set_power_domain(PD_VDU, pmu_pd_on); + pmu_set_power_domain(PD_VCODEC, pmu_pd_on); + pmu_set_power_domain(PD_RGA, pmu_pd_on); + pmu_set_power_domain(PD_IEP, pmu_pd_on); + pmu_set_power_domain(PD_EDP, pmu_pd_on); + pmu_set_power_domain(PD_GMAC, pmu_pd_on); + pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_on); + pmu_set_power_domain(PD_HDCP, pmu_pd_on); + pmu_set_power_domain(PD_ISP1, pmu_pd_on); + pmu_set_power_domain(PD_ISP0, pmu_pd_on); + pmu_set_power_domain(PD_VO, pmu_pd_on); + pmu_set_power_domain(PD_TCPD1, pmu_pd_on); + pmu_set_power_domain(PD_TCPD0, pmu_pd_on); + pmu_set_power_domain(PD_GPU, pmu_pd_on); +} + +void rk3399_flush_l2_b(void) +{ + uint32_t wait_cnt = 0; + + mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); + dsb(); + + /* + * The Big cluster flush L2 cache took ~4ms by default, give 10ms for + * the enough margin. + */ + while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & + BIT(L2_FLUSHDONE_CLUSTER_B))) { + wait_cnt++; + udelay(10); + if (wait_cnt == 10000 / 10) + WARN("L2 cache flush on suspend took longer than 10ms\n"); + } + + mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); +} + +static void pmu_scu_b_pwrdn(void) +{ + uint32_t wait_cnt = 0; + + if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & + (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) != + (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) { + ERROR("%s: not all cpus is off\n", __func__); + return; + } + + rk3399_flush_l2_b(); + + mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); + + while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & + BIT(STANDBY_BY_WFIL2_CLUSTER_B))) { + wait_cnt++; + udelay(1); + if (wait_cnt >= MAX_WAIT_COUNT) + ERROR("%s:wait cluster-b l2(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); + } +} + +static void pmu_scu_b_pwrup(void) +{ + mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); +} + +static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) +{ + assert(cpu_id < PLATFORM_CORE_COUNT); + return core_pm_cfg_info[cpu_id]; +} + +static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value) +{ + assert(cpu_id < PLATFORM_CORE_COUNT); + core_pm_cfg_info[cpu_id] = value; +#if !USE_COHERENT_MEM + flush_dcache_range((uintptr_t)&core_pm_cfg_info[cpu_id], + sizeof(uint32_t)); +#endif +} + +static int cpus_power_domain_on(uint32_t cpu_id) +{ + uint32_t cfg_info; + uint32_t cpu_pd = PD_CPUL0 + cpu_id; + /* + * There are two ways to powering on or off on core. + * 1) Control it power domain into on or off in PMU_PWRDN_CON reg + * 2) Enable the core power manage in PMU_CORE_PM_CON reg, + * then, if the core enter into wfi, it power domain will be + * powered off automatically. + */ + + cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); + + if (cfg_info == core_pwr_pd) { + /* disable core_pm cfg */ + mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), + CORES_PM_DISABLE); + /* if the cores have be on, power off it firstly */ + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 0); + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } + + pmu_power_domain_ctr(cpu_pd, pmu_pd_on); + } else { + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id); + return -EINVAL; + } + + mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), + BIT(core_pm_sft_wakeup_en)); + dsb(); + } + + return 0; +} + +static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) +{ + uint32_t cpu_pd; + uint32_t core_pm_value; + + cpu_pd = PD_CPUL0 + cpu_id; + if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) + return 0; + + if (pd_cfg == core_pwr_pd) { + if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) + return -EINVAL; + + /* disable core_pm cfg */ + mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), + CORES_PM_DISABLE); + + set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } else { + set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); + + core_pm_value = BIT(core_pm_en); + if (pd_cfg == core_pwr_wfi_int) + core_pm_value |= BIT(core_pm_int_wakeup_en); + mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), + core_pm_value); + dsb(); + } + + return 0; +} + +static inline void clst_pwr_domain_suspend(plat_local_state_t lvl_state) +{ + uint32_t cpu_id = plat_my_core_pos(); + uint32_t pll_id, clst_st_msk, clst_st_chk_msk, pmu_st; + + assert(cpu_id < PLATFORM_CORE_COUNT); + + if (lvl_state == PLAT_MAX_OFF_STATE) { + if (cpu_id < PLATFORM_CLUSTER0_CORE_COUNT) { + pll_id = ALPLL_ID; + clst_st_msk = CLST_L_CPUS_MSK; + } else { + pll_id = ABPLL_ID; + clst_st_msk = CLST_B_CPUS_MSK << + PLATFORM_CLUSTER0_CORE_COUNT; + } + + clst_st_chk_msk = clst_st_msk & ~(BIT(cpu_id)); + + pmu_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); + + pmu_st &= clst_st_msk; + + if (pmu_st == clst_st_chk_msk) { + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), + PLL_SLOW_MODE); + + clst_warmboot_data[pll_id] = PMU_CLST_RET; + + pmu_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); + pmu_st &= clst_st_msk; + if (pmu_st == clst_st_chk_msk) + return; + /* + * it is mean that others cpu is up again, + * we must resume the cfg at once. + */ + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), + PLL_NOMAL_MODE); + clst_warmboot_data[pll_id] = 0; + } + } +} + +static int clst_pwr_domain_resume(plat_local_state_t lvl_state) +{ + uint32_t cpu_id = plat_my_core_pos(); + uint32_t pll_id, pll_st; + + assert(cpu_id < PLATFORM_CORE_COUNT); + + if (lvl_state == PLAT_MAX_OFF_STATE) { + if (cpu_id < PLATFORM_CLUSTER0_CORE_COUNT) + pll_id = ALPLL_ID; + else + pll_id = ABPLL_ID; + + pll_st = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 3)) >> + PLL_MODE_SHIFT; + + if (pll_st != NORMAL_MODE) { + WARN("%s: clst (%d) is in error mode (%d)\n", + __func__, pll_id, pll_st); + return -1; + } + } + + return 0; +} + +static void nonboot_cpus_off(void) +{ + uint32_t boot_cpu, cpu; + + boot_cpu = plat_my_core_pos(); + + /* turn off noboot cpus */ + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { + if (cpu == boot_cpu) + continue; + cpus_power_domain_off(cpu, core_pwr_pd); + } +} + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) +{ + uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpu_id] = entrypoint; + dsb(); + + cpus_power_domain_on(cpu_id); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_off(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + cpus_power_domain_off(cpu_id, core_pwr_wfi); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl, + plat_local_state_t lvl_state) +{ + if (lvl == MPIDR_AFFLVL1) { + clst_pwr_domain_suspend(lvl_state); + } + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_suspend(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + assert(cpu_id < PLATFORM_CORE_COUNT); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; + cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint(); + dsb(); + + cpus_power_domain_off(cpu_id, core_pwr_wfi_int); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl, plat_local_state_t lvl_state) +{ + if (lvl == MPIDR_AFFLVL1) { + clst_pwr_domain_suspend(lvl_state); + } + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), + CORES_PM_DISABLE); + return PSCI_E_SUCCESS; +} + +int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl, + plat_local_state_t lvl_state) +{ + if (lvl == MPIDR_AFFLVL1) { + clst_pwr_domain_resume(lvl_state); + } + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_cores_pwr_dm_resume(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + /* Disable core_pm */ + mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE); + + return PSCI_E_SUCCESS; +} + +int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl, plat_local_state_t lvl_state) +{ + if (lvl == MPIDR_AFFLVL1) { + clst_pwr_domain_resume(lvl_state); + } + + return PSCI_E_SUCCESS; +} + +/** + * init_pmu_counts - Init timing counts in the PMU register area + * + * At various points when we power up or down parts of the system we need + * a delay to wait for power / clocks to become stable. The PMU has counters + * to help software do the delay properly. Basically, it works like this: + * - Software sets up counter values + * - When software turns on something in the PMU, the counter kicks off + * - The hardware sets a bit automatically when the counter has finished and + * software knows that the initialization is done. + * + * It's software's job to setup these counters. The hardware power on default + * for these settings is conservative, setting everything to 0x5dc0 + * (750 ms in 32 kHz counts or 1 ms in 24 MHz counts). + * + * Note that some of these counters are only really used at suspend/resume + * time (for instance, that's the only time we turn off/on the oscillator) and + * others are used during normal runtime (like turning on/off a CPU or GPU) but + * it doesn't hurt to init everything at boot. + * + * Also note that these counters can run off the 32 kHz clock or the 24 MHz + * clock. While the 24 MHz clock can give us more precision, it's not always + * available (like when we turn the oscillator off at sleep time). The + * pmu_use_lf (lf: low freq) is available in power mode. Current understanding + * is that counts work like this: + * IF (pmu_use_lf == 0) || (power_mode_en == 0) + * use the 24M OSC for counts + * ELSE + * use the 32K OSC for counts + * + * Notes: + * - There is a separate bit for the PMU called PMU_24M_EN_CFG. At the moment + * we always keep that 0. This apparently choose between using the PLL as + * the source for the PMU vs. the 24M clock. If we ever set it to 1 we + * should consider how it affects these counts (if at all). + * - The power_mode_en is documented to auto-clear automatically when we leave + * "power mode". That's why most clocks are on 24M. Only timings used when + * in "power mode" are 32k. + * - In some cases the kernel may override these counts. + * + * The PMU_STABLE_CNT / PMU_OSC_CNT / PMU_PLLLOCK_CNT are important CNTs + * in power mode, we need to ensure that they are available. + */ +static void init_pmu_counts(void) +{ + /* COUNTS FOR INSIDE POWER MODE */ + + /* + * From limited testing, need PMU stable >= 2ms, but go overkill + * and choose 30 ms to match testing on past SoCs. Also let + * OSC have 30 ms for stabilization. + */ + mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_32K_CNT_MS(30)); + mmio_write_32(PMU_BASE + PMU_OSC_CNT, CYCL_32K_CNT_MS(30)); + + /* Unclear what these should be; try 3 ms */ + mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_CNT, CYCL_32K_CNT_MS(3)); + + /* Unclear what this should be, but set the default explicitly */ + mmio_write_32(PMU_BASE + PMU_TIMEOUT_CNT, 0x5dc0); + + /* COUNTS FOR OUTSIDE POWER MODE */ + + /* Put something sorta conservative here until we know better */ + mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT, CYCL_24M_CNT_MS(3)); + mmio_write_32(PMU_BASE + PMU_DDRIO_PWRON_CNT, CYCL_24M_CNT_MS(1)); + mmio_write_32(PMU_BASE + PMU_CENTER_PWRDN_CNT, CYCL_24M_CNT_MS(1)); + mmio_write_32(PMU_BASE + PMU_CENTER_PWRUP_CNT, CYCL_24M_CNT_MS(1)); + + /* + * when we enable PMU_CLR_PERILP, it will shut down the SRAM, but + * M0 code run in SRAM, and we need it to check whether cpu enter + * FSM status, so we must wait M0 finish their code and enter WFI, + * then we can shutdown SRAM, according FSM order: + * ST_NORMAL->..->ST_SCU_L_PWRDN->..->ST_CENTER_PWRDN->ST_PERILP_PWRDN + * we can add delay when shutdown ST_SCU_L_PWRDN to guarantee M0 get + * the FSM status and enter WFI, then enable PMU_CLR_PERILP. + */ + mmio_write_32(PMU_BASE + PMU_SCU_L_PWRDN_CNT, CYCL_24M_CNT_MS(5)); + mmio_write_32(PMU_BASE + PMU_SCU_L_PWRUP_CNT, CYCL_24M_CNT_US(1)); + + /* + * Set CPU/GPU to 1 us. + * + * NOTE: Even though ATF doesn't configure the GPU we'll still setup + * counts here. After all ATF controls all these other bits and also + * chooses which clock these counters use. + */ + mmio_write_32(PMU_BASE + PMU_SCU_B_PWRDN_CNT, CYCL_24M_CNT_US(1)); + mmio_write_32(PMU_BASE + PMU_SCU_B_PWRUP_CNT, CYCL_24M_CNT_US(1)); + mmio_write_32(PMU_BASE + PMU_GPU_PWRDN_CNT, CYCL_24M_CNT_US(1)); + mmio_write_32(PMU_BASE + PMU_GPU_PWRUP_CNT, CYCL_24M_CNT_US(1)); +} + +static uint32_t clk_ddrc_save; + +static void sys_slp_config(void) +{ + uint32_t slp_mode_cfg = 0; + + /* keep enabling clk_ddrc_bpll_src_en gate for DDRC */ + clk_ddrc_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(3)); + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3), WMSK_BIT(1)); + + prepare_abpll_for_ddrctrl(); + sram_func_set_ddrctl_pll(ABPLL_ID); + + mmio_write_32(GRF_BASE + GRF_SOC_CON4, CCI_FORCE_WAKEUP); + mmio_write_32(PMU_BASE + PMU_CCI500_CON, + BIT_WITH_WMSK(PMU_CLR_PREQ_CCI500_HW) | + BIT_WITH_WMSK(PMU_CLR_QREQ_CCI500_HW) | + BIT_WITH_WMSK(PMU_QGATING_CCI500_CFG)); + + mmio_write_32(PMU_BASE + PMU_ADB400_CON, + BIT_WITH_WMSK(PMU_CLR_CORE_L_HW) | + BIT_WITH_WMSK(PMU_CLR_CORE_L_2GIC_HW) | + BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW)); + + slp_mode_cfg = BIT(PMU_PWR_MODE_EN) | + BIT(PMU_WKUP_RST_EN) | + BIT(PMU_INPUT_CLAMP_EN) | + BIT(PMU_POWER_OFF_REQ_CFG) | + BIT(PMU_CPU0_PD_EN) | + BIT(PMU_L2_FLUSH_EN) | + BIT(PMU_L2_IDLE_EN) | + BIT(PMU_SCU_PD_EN) | + BIT(PMU_CCI_PD_EN) | + BIT(PMU_CLK_CORE_SRC_GATE_EN) | + BIT(PMU_ALIVE_USE_LF) | + BIT(PMU_SREF0_ENTER_EN) | + BIT(PMU_SREF1_ENTER_EN) | + BIT(PMU_DDRC0_GATING_EN) | + BIT(PMU_DDRC1_GATING_EN) | + BIT(PMU_DDRIO0_RET_EN) | + BIT(PMU_DDRIO0_RET_DE_REQ) | + BIT(PMU_DDRIO1_RET_EN) | + BIT(PMU_DDRIO1_RET_DE_REQ) | + BIT(PMU_CENTER_PD_EN) | + BIT(PMU_PERILP_PD_EN) | + BIT(PMU_CLK_PERILP_SRC_GATE_EN) | + BIT(PMU_PLL_PD_EN) | + BIT(PMU_CLK_CENTER_SRC_GATE_EN) | + BIT(PMU_OSC_DIS) | + BIT(PMU_PMU_USE_LF); + + mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, BIT(PMU_GPIO_WKUP_EN)); + mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg); + + mmio_write_32(PMU_BASE + PMU_PLL_CON, PLL_PD_HW); + mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON0, EXTERNAL_32K); + mmio_write_32(PMUGRF_BASE, IOMUX_CLK_32K); /* 32k iomux */ +} + +static void set_hw_idle(uint32_t hw_idle) +{ + mmio_setbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle); +} + +static void clr_hw_idle(uint32_t hw_idle) +{ + mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle); +} + +static uint32_t iomux_status[12]; +static uint32_t pull_mode_status[12]; +static uint32_t gpio_direction[3]; +static uint32_t gpio_2_4_clk_gate; + +static void suspend_apio(void) +{ + struct bl_aux_rk_apio_info *suspend_apio; + int i; + + suspend_apio = plat_get_rockchip_suspend_apio(); + + if (!suspend_apio) + return; + + /* save gpio2 ~ gpio4 iomux and pull mode */ + for (i = 0; i < 12; i++) { + iomux_status[i] = mmio_read_32(GRF_BASE + + GRF_GPIO2A_IOMUX + i * 4); + pull_mode_status[i] = mmio_read_32(GRF_BASE + + GRF_GPIO2A_P + i * 4); + } + + /* store gpio2 ~ gpio4 clock gate state */ + gpio_2_4_clk_gate = (mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31)) >> + PCLK_GPIO2_GATE_SHIFT) & 0x07; + + /* enable gpio2 ~ gpio4 clock gate */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT)); + + /* save gpio2 ~ gpio4 direction */ + gpio_direction[0] = mmio_read_32(GPIO2_BASE + 0x04); + gpio_direction[1] = mmio_read_32(GPIO3_BASE + 0x04); + gpio_direction[2] = mmio_read_32(GPIO4_BASE + 0x04); + + /* apio1 charge gpio3a0 ~ gpio3c7 */ + if (suspend_apio->apio1) { + + /* set gpio3a0 ~ gpio3c7 iomux to gpio */ + mmio_write_32(GRF_BASE + GRF_GPIO3A_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + mmio_write_32(GRF_BASE + GRF_GPIO3B_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + mmio_write_32(GRF_BASE + GRF_GPIO3C_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + + /* set gpio3a0 ~ gpio3c7 pull mode to pull none */ + mmio_write_32(GRF_BASE + GRF_GPIO3A_P, REG_SOC_WMSK | 0); + mmio_write_32(GRF_BASE + GRF_GPIO3B_P, REG_SOC_WMSK | 0); + mmio_write_32(GRF_BASE + GRF_GPIO3C_P, REG_SOC_WMSK | 0); + + /* set gpio3a0 ~ gpio3c7 to input */ + mmio_clrbits_32(GPIO3_BASE + 0x04, 0x00ffffff); + } + + /* apio2 charge gpio2a0 ~ gpio2b4 */ + if (suspend_apio->apio2) { + + /* set gpio2a0 ~ gpio2b4 iomux to gpio */ + mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + mmio_write_32(GRF_BASE + GRF_GPIO2B_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + + /* set gpio2a0 ~ gpio2b4 pull mode to pull none */ + mmio_write_32(GRF_BASE + GRF_GPIO2A_P, REG_SOC_WMSK | 0); + mmio_write_32(GRF_BASE + GRF_GPIO2B_P, REG_SOC_WMSK | 0); + + /* set gpio2a0 ~ gpio2b4 to input */ + mmio_clrbits_32(GPIO2_BASE + 0x04, 0x00001fff); + } + + /* apio3 charge gpio2c0 ~ gpio2d4*/ + if (suspend_apio->apio3) { + + /* set gpio2a0 ~ gpio2b4 iomux to gpio */ + mmio_write_32(GRF_BASE + GRF_GPIO2C_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + mmio_write_32(GRF_BASE + GRF_GPIO2D_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + + /* set gpio2c0 ~ gpio2d4 pull mode to pull none */ + mmio_write_32(GRF_BASE + GRF_GPIO2C_P, REG_SOC_WMSK | 0); + mmio_write_32(GRF_BASE + GRF_GPIO2D_P, REG_SOC_WMSK | 0); + + /* set gpio2c0 ~ gpio2d4 to input */ + mmio_clrbits_32(GPIO2_BASE + 0x04, 0x1fff0000); + } + + /* apio4 charge gpio4c0 ~ gpio4c7, gpio4d0 ~ gpio4d6 */ + if (suspend_apio->apio4) { + + /* set gpio4c0 ~ gpio4d6 iomux to gpio */ + mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + mmio_write_32(GRF_BASE + GRF_GPIO4D_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + + /* set gpio4c0 ~ gpio4d6 pull mode to pull none */ + mmio_write_32(GRF_BASE + GRF_GPIO4C_P, REG_SOC_WMSK | 0); + mmio_write_32(GRF_BASE + GRF_GPIO4D_P, REG_SOC_WMSK | 0); + + /* set gpio4c0 ~ gpio4d6 to input */ + mmio_clrbits_32(GPIO4_BASE + 0x04, 0x7fff0000); + } + + /* apio5 charge gpio3d0 ~ gpio3d7, gpio4a0 ~ gpio4a7*/ + if (suspend_apio->apio5) { + /* set gpio3d0 ~ gpio4a7 iomux to gpio */ + mmio_write_32(GRF_BASE + GRF_GPIO3D_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + mmio_write_32(GRF_BASE + GRF_GPIO4A_IOMUX, + REG_SOC_WMSK | GRF_IOMUX_GPIO); + + /* set gpio3d0 ~ gpio4a7 pull mode to pull none */ + mmio_write_32(GRF_BASE + GRF_GPIO3D_P, REG_SOC_WMSK | 0); + mmio_write_32(GRF_BASE + GRF_GPIO4A_P, REG_SOC_WMSK | 0); + + /* set gpio4c0 ~ gpio4d6 to input */ + mmio_clrbits_32(GPIO3_BASE + 0x04, 0xff000000); + mmio_clrbits_32(GPIO4_BASE + 0x04, 0x000000ff); + } +} + +static void resume_apio(void) +{ + struct bl_aux_rk_apio_info *suspend_apio; + int i; + + suspend_apio = plat_get_rockchip_suspend_apio(); + + if (!suspend_apio) + return; + + for (i = 0; i < 12; i++) { + mmio_write_32(GRF_BASE + GRF_GPIO2A_P + i * 4, + REG_SOC_WMSK | pull_mode_status[i]); + mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4, + REG_SOC_WMSK | iomux_status[i]); + } + + /* set gpio2 ~ gpio4 direction back to store value */ + mmio_write_32(GPIO2_BASE + 0x04, gpio_direction[0]); + mmio_write_32(GPIO3_BASE + 0x04, gpio_direction[1]); + mmio_write_32(GPIO4_BASE + 0x04, gpio_direction[2]); + + /* set gpio2 ~ gpio4 clock gate back to store value */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + BITS_WITH_WMASK(gpio_2_4_clk_gate, 0x07, + PCLK_GPIO2_GATE_SHIFT)); +} + +static void suspend_gpio(void) +{ + struct bl_aux_gpio_info *suspend_gpio; + uint32_t count; + int i; + + suspend_gpio = plat_get_rockchip_suspend_gpio(&count); + + for (i = 0; i < count; i++) { + gpio_set_value(suspend_gpio[i].index, suspend_gpio[i].polarity); + gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT); + udelay(1); + } +} + +static void resume_gpio(void) +{ + struct bl_aux_gpio_info *suspend_gpio; + uint32_t count; + int i; + + suspend_gpio = plat_get_rockchip_suspend_gpio(&count); + + for (i = count - 1; i >= 0; i--) { + gpio_set_value(suspend_gpio[i].index, + !suspend_gpio[i].polarity); + gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT); + udelay(1); + } +} + +void sram_save(void) +{ + size_t text_size = (char *)&__bl31_sram_text_real_end - + (char *)&__bl31_sram_text_start; + size_t data_size = (char *)&__bl31_sram_data_real_end - + (char *)&__bl31_sram_data_start; + size_t incbin_size = (char *)&__sram_incbin_real_end - + (char *)&__sram_incbin_start; + + memcpy(&store_sram[0], &__bl31_sram_text_start, text_size); + memcpy(&store_sram[text_size], &__bl31_sram_data_start, data_size); + memcpy(&store_sram[text_size + data_size], &__sram_incbin_start, + incbin_size); +} + +void sram_restore(void) +{ + size_t text_size = (char *)&__bl31_sram_text_real_end - + (char *)&__bl31_sram_text_start; + size_t data_size = (char *)&__bl31_sram_data_real_end - + (char *)&__bl31_sram_data_start; + size_t incbin_size = (char *)&__sram_incbin_real_end - + (char *)&__sram_incbin_start; + + memcpy(&__bl31_sram_text_start, &store_sram[0], text_size); + memcpy(&__bl31_sram_data_start, &store_sram[text_size], data_size); + memcpy(&__sram_incbin_start, &store_sram[text_size + data_size], + incbin_size); +} + +struct uart_debug { + uint32_t uart_dll; + uint32_t uart_dlh; + uint32_t uart_ier; + uint32_t uart_fcr; + uint32_t uart_mcr; + uint32_t uart_lcr; +}; + +#define UART_DLL 0x00 +#define UART_DLH 0x04 +#define UART_IER 0x04 +#define UART_FCR 0x08 +#define UART_LCR 0x0c +#define UART_MCR 0x10 +#define UARTSRR 0x88 + +#define UART_RESET BIT(0) +#define UARTFCR_FIFOEN BIT(0) +#define RCVR_FIFO_RESET BIT(1) +#define XMIT_FIFO_RESET BIT(2) +#define DIAGNOSTIC_MODE BIT(4) +#define UARTLCR_DLAB BIT(7) + +static struct uart_debug uart_save; + +void suspend_uart(void) +{ + uint32_t uart_base = rockchip_get_uart_base(); + + if (uart_base == 0) + return; + + uart_save.uart_lcr = mmio_read_32(uart_base + UART_LCR); + uart_save.uart_ier = mmio_read_32(uart_base + UART_IER); + uart_save.uart_mcr = mmio_read_32(uart_base + UART_MCR); + mmio_write_32(uart_base + UART_LCR, + uart_save.uart_lcr | UARTLCR_DLAB); + uart_save.uart_dll = mmio_read_32(uart_base + UART_DLL); + uart_save.uart_dlh = mmio_read_32(uart_base + UART_DLH); + mmio_write_32(uart_base + UART_LCR, uart_save.uart_lcr); +} + +void resume_uart(void) +{ + uint32_t uart_base = rockchip_get_uart_base(); + uint32_t uart_lcr; + + if (uart_base == 0) + return; + + mmio_write_32(uart_base + UARTSRR, + XMIT_FIFO_RESET | RCVR_FIFO_RESET | UART_RESET); + + uart_lcr = mmio_read_32(uart_base + UART_LCR); + mmio_write_32(uart_base + UART_MCR, DIAGNOSTIC_MODE); + mmio_write_32(uart_base + UART_LCR, uart_lcr | UARTLCR_DLAB); + mmio_write_32(uart_base + UART_DLL, uart_save.uart_dll); + mmio_write_32(uart_base + UART_DLH, uart_save.uart_dlh); + mmio_write_32(uart_base + UART_LCR, uart_save.uart_lcr); + mmio_write_32(uart_base + UART_IER, uart_save.uart_ier); + mmio_write_32(uart_base + UART_FCR, UARTFCR_FIFOEN); + mmio_write_32(uart_base + UART_MCR, uart_save.uart_mcr); +} + +void save_usbphy(void) +{ + store_usbphy0[0] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL0); + store_usbphy0[1] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL2); + store_usbphy0[2] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL3); + store_usbphy0[3] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL12); + store_usbphy0[4] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL13); + store_usbphy0[5] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL15); + store_usbphy0[6] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL16); + + store_usbphy1[0] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL0); + store_usbphy1[1] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL2); + store_usbphy1[2] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL3); + store_usbphy1[3] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL12); + store_usbphy1[4] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL13); + store_usbphy1[5] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL15); + store_usbphy1[6] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL16); +} + +void restore_usbphy(void) +{ + mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL0, + REG_SOC_WMSK | store_usbphy0[0]); + mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL2, + REG_SOC_WMSK | store_usbphy0[1]); + mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL3, + REG_SOC_WMSK | store_usbphy0[2]); + mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL12, + REG_SOC_WMSK | store_usbphy0[3]); + mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL13, + REG_SOC_WMSK | store_usbphy0[4]); + mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL15, + REG_SOC_WMSK | store_usbphy0[5]); + mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL16, + REG_SOC_WMSK | store_usbphy0[6]); + + mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL0, + REG_SOC_WMSK | store_usbphy1[0]); + mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL2, + REG_SOC_WMSK | store_usbphy1[1]); + mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL3, + REG_SOC_WMSK | store_usbphy1[2]); + mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL12, + REG_SOC_WMSK | store_usbphy1[3]); + mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL13, + REG_SOC_WMSK | store_usbphy1[4]); + mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL15, + REG_SOC_WMSK | store_usbphy1[5]); + mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL16, + REG_SOC_WMSK | store_usbphy1[6]); +} + +void grf_register_save(void) +{ + int i; + + store_grf_soc_con0 = mmio_read_32(GRF_BASE + GRF_SOC_CON(0)); + store_grf_soc_con1 = mmio_read_32(GRF_BASE + GRF_SOC_CON(1)); + store_grf_soc_con2 = mmio_read_32(GRF_BASE + GRF_SOC_CON(2)); + store_grf_soc_con3 = mmio_read_32(GRF_BASE + GRF_SOC_CON(3)); + store_grf_soc_con4 = mmio_read_32(GRF_BASE + GRF_SOC_CON(4)); + store_grf_soc_con7 = mmio_read_32(GRF_BASE + GRF_SOC_CON(7)); + + for (i = 0; i < 4; i++) + store_grf_ddrc_con[i] = + mmio_read_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4); + + store_grf_io_vsel = mmio_read_32(GRF_BASE + GRF_IO_VSEL); +} + +void grf_register_restore(void) +{ + int i; + + mmio_write_32(GRF_BASE + GRF_SOC_CON(0), + REG_SOC_WMSK | store_grf_soc_con0); + mmio_write_32(GRF_BASE + GRF_SOC_CON(1), + REG_SOC_WMSK | store_grf_soc_con1); + mmio_write_32(GRF_BASE + GRF_SOC_CON(2), + REG_SOC_WMSK | store_grf_soc_con2); + mmio_write_32(GRF_BASE + GRF_SOC_CON(3), + REG_SOC_WMSK | store_grf_soc_con3); + mmio_write_32(GRF_BASE + GRF_SOC_CON(4), + REG_SOC_WMSK | store_grf_soc_con4); + mmio_write_32(GRF_BASE + GRF_SOC_CON(7), + REG_SOC_WMSK | store_grf_soc_con7); + + for (i = 0; i < 4; i++) + mmio_write_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4, + REG_SOC_WMSK | store_grf_ddrc_con[i]); + + mmio_write_32(GRF_BASE + GRF_IO_VSEL, REG_SOC_WMSK | store_grf_io_vsel); +} + +void cru_register_save(void) +{ + int i; + + for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4) + store_cru[i / 4] = mmio_read_32(CRU_BASE + i); +} + +void cru_register_restore(void) +{ + int i; + + for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4) { + + /* + * since DPLL, CRU_CLKSEL_CON6 have been restore in + * dmc_resume, ABPLL will resote later, so skip them + */ + if ((i == CRU_CLKSEL_CON6) || + (i >= CRU_PLL_CON(ABPLL_ID, 0) && + i <= CRU_PLL_CON(DPLL_ID, 5))) + continue; + + if ((i == CRU_PLL_CON(ALPLL_ID, 2)) || + (i == CRU_PLL_CON(CPLL_ID, 2)) || + (i == CRU_PLL_CON(GPLL_ID, 2)) || + (i == CRU_PLL_CON(NPLL_ID, 2)) || + (i == CRU_PLL_CON(VPLL_ID, 2))) + mmio_write_32(CRU_BASE + i, store_cru[i / 4]); + /* + * CRU_GLB_CNT_TH and CRU_CLKSEL_CON97~CRU_CLKSEL_CON107 + * not need do high 16bit mask + */ + else if ((i > 0x27c && i < 0x2b0) || (i == 0x508)) + mmio_write_32(CRU_BASE + i, store_cru[i / 4]); + else + mmio_write_32(CRU_BASE + i, + REG_SOC_WMSK | store_cru[i / 4]); + } +} + +void wdt_register_save(void) +{ + int i; + + for (i = 0; i < 2; i++) { + store_wdt0[i] = mmio_read_32(WDT0_BASE + i * 4); + store_wdt1[i] = mmio_read_32(WDT1_BASE + i * 4); + } + pmu_enable_watchdog0 = (uint8_t) store_wdt0[0] & 0x1; +} + +void wdt_register_restore(void) +{ + int i; + + for (i = 1; i >= 0; i--) { + mmio_write_32(WDT0_BASE + i * 4, store_wdt0[i]); + mmio_write_32(WDT1_BASE + i * 4, store_wdt1[i]); + } + + /* write 0x76 to cnt_restart to keep watchdog alive */ + mmio_write_32(WDT0_BASE + 0x0c, 0x76); + mmio_write_32(WDT1_BASE + 0x0c, 0x76); +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + uint32_t wait_cnt = 0; + uint32_t status = 0; + + ddr_prepare_for_sys_suspend(); + dmc_suspend(); + pmu_scu_b_pwrdn(); + + gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); + gicv3_distif_save(&dist_ctx); + + /* need to save usbphy before shutdown PERIHP PD */ + save_usbphy(); + + pmu_power_domains_suspend(); + set_hw_idle(BIT(PMU_CLR_CENTER1) | + BIT(PMU_CLR_ALIVE) | + BIT(PMU_CLR_MSCH0) | + BIT(PMU_CLR_MSCH1) | + BIT(PMU_CLR_CCIM0) | + BIT(PMU_CLR_CCIM1) | + BIT(PMU_CLR_CENTER) | + BIT(PMU_CLR_PERILP) | + BIT(PMU_CLR_PERILPM0) | + BIT(PMU_CLR_GIC)); + set_pmu_rsthold(); + sys_slp_config(); + + m0_configure_execute_addr(M0PMU_BINCODE_BASE); + m0_start(); + + pmu_sgrf_rst_hld(); + + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + ((uintptr_t)&pmu_cpuson_entrypoint >> + CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); + + mmio_write_32(PMU_BASE + PMU_ADB400_CON, + BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | + BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_SW) | + BIT_WITH_WMSK(PMU_PWRDWN_REQ_GIC2_CORE_B_SW)); + dsb(); + status = BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW_ST) | + BIT(PMU_PWRDWN_REQ_CORE_B_SW_ST) | + BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW_ST); + while ((mmio_read_32(PMU_BASE + + PMU_ADB400_ST) & status) != status) { + wait_cnt++; + if (wait_cnt >= MAX_WAIT_COUNT) { + ERROR("%s:wait cluster-b l2(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_ADB400_ST)); + panic(); + } + udelay(1); + } + mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN)); + + wdt_register_save(); + secure_watchdog_gate(); + + /* + * Disabling PLLs/PWM/DVFS is approaching WFI which is + * the last steps in suspend. + */ + disable_dvfs_plls(); + disable_pwms(); + disable_nodvfs_plls(); + + suspend_apio(); + suspend_gpio(); + suspend_uart(); + grf_register_save(); + cru_register_save(); + sram_save(); + plat_rockchip_save_gpio(); + + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + uint32_t wait_cnt = 0; + uint32_t status = 0; + + plat_rockchip_restore_gpio(); + cru_register_restore(); + grf_register_restore(); + wdt_register_restore(); + resume_uart(); + resume_apio(); + resume_gpio(); + enable_nodvfs_plls(); + enable_pwms(); + /* PWM regulators take time to come up; give 300us to be safe. */ + udelay(300); + enable_dvfs_plls(); + + secure_sgrf_init(); + secure_sgrf_ddr_rgn_init(); + + /* restore clk_ddrc_bpll_src_en gate */ + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3), + BITS_WITH_WMASK(clk_ddrc_save, 0xff, 0)); + + /* + * The wakeup status is not cleared by itself, we need to clear it + * manually. Otherwise we will alway query some interrupt next time. + * + * NOTE: If the kernel needs to query this, we might want to stash it + * somewhere. + */ + mmio_write_32(PMU_BASE + PMU_WAKEUP_STATUS, 0xffffffff); + mmio_write_32(PMU_BASE + PMU_WKUP_CFG4, 0x00); + + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + + mmio_write_32(PMU_BASE + PMU_CCI500_CON, + WMSK_BIT(PMU_CLR_PREQ_CCI500_HW) | + WMSK_BIT(PMU_CLR_QREQ_CCI500_HW) | + WMSK_BIT(PMU_QGATING_CCI500_CFG)); + dsb(); + mmio_clrbits_32(PMU_BASE + PMU_PWRDN_CON, + BIT(PMU_SCU_B_PWRDWN_EN)); + + mmio_write_32(PMU_BASE + PMU_ADB400_CON, + WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | + WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_SW) | + WMSK_BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW) | + WMSK_BIT(PMU_CLR_CORE_L_HW) | + WMSK_BIT(PMU_CLR_CORE_L_2GIC_HW) | + WMSK_BIT(PMU_CLR_GIC2_CORE_L_HW)); + + status = BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW_ST) | + BIT(PMU_PWRDWN_REQ_CORE_B_SW_ST) | + BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW_ST); + + while ((mmio_read_32(PMU_BASE + + PMU_ADB400_ST) & status)) { + wait_cnt++; + if (wait_cnt >= MAX_WAIT_COUNT) { + ERROR("%s:wait cluster-b l2(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_ADB400_ST)); + panic(); + } + udelay(1); + } + + pmu_scu_b_pwrup(); + pmu_power_domains_resume(); + + restore_abpll(); + clr_hw_idle(BIT(PMU_CLR_CENTER1) | + BIT(PMU_CLR_ALIVE) | + BIT(PMU_CLR_MSCH0) | + BIT(PMU_CLR_MSCH1) | + BIT(PMU_CLR_CCIM0) | + BIT(PMU_CLR_CCIM1) | + BIT(PMU_CLR_CENTER) | + BIT(PMU_CLR_PERILP) | + BIT(PMU_CLR_PERILPM0) | + BIT(PMU_CLR_GIC)); + + gicv3_distif_init_restore(&dist_ctx); + gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); + plat_rockchip_gic_cpuif_enable(); + m0_stop(); + + restore_usbphy(); + + ddr_prepare_for_sys_resume(); + + return 0; +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + struct bl_aux_gpio_info *rst_gpio; + + rst_gpio = plat_get_rockchip_gpio_reset(); + + if (rst_gpio) { + gpio_set_direction(rst_gpio->index, GPIO_DIR_OUT); + gpio_set_value(rst_gpio->index, rst_gpio->polarity); + } else { + soc_global_soft_reset(); + } + + while (1) + ; +} + +void __dead2 rockchip_soc_system_off(void) +{ + struct bl_aux_gpio_info *poweroff_gpio; + + poweroff_gpio = plat_get_rockchip_gpio_poweroff(); + + if (poweroff_gpio) { + /* + * if use tsadc over temp pin(GPIO1A6) as shutdown gpio, + * need to set this pin iomux back to gpio function + */ + if (poweroff_gpio->index == TSADC_INT_PIN) { + mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1A_IOMUX, + GPIO1A6_IOMUX); + } + gpio_set_direction(poweroff_gpio->index, GPIO_DIR_OUT); + gpio_set_value(poweroff_gpio->index, poweroff_gpio->polarity); + } else { + WARN("Do nothing when system off\n"); + } + + while (1) + ; +} + +void rockchip_plat_mmu_el3(void) +{ + size_t sram_size; + + /* sram.text size */ + sram_size = (char *)&__bl31_sram_text_end - + (char *)&__bl31_sram_text_start; + mmap_add_region((unsigned long)&__bl31_sram_text_start, + (unsigned long)&__bl31_sram_text_start, + sram_size, MT_MEMORY | MT_RO | MT_SECURE); + + /* sram.data size */ + sram_size = (char *)&__bl31_sram_data_end - + (char *)&__bl31_sram_data_start; + mmap_add_region((unsigned long)&__bl31_sram_data_start, + (unsigned long)&__bl31_sram_data_start, + sram_size, MT_MEMORY | MT_RW | MT_SECURE); + + sram_size = (char *)&__bl31_sram_stack_end - + (char *)&__bl31_sram_stack_start; + mmap_add_region((unsigned long)&__bl31_sram_stack_start, + (unsigned long)&__bl31_sram_stack_start, + sram_size, MT_MEMORY | MT_RW | MT_SECURE); + + sram_size = (char *)&__sram_incbin_end - (char *)&__sram_incbin_start; + mmap_add_region((unsigned long)&__sram_incbin_start, + (unsigned long)&__sram_incbin_start, + sram_size, MT_NON_CACHEABLE | MT_RW | MT_SECURE); +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + rockchip_pd_lock_init(); + + /* register requires 32bits mode, switch it to 32 bits */ + cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; + + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = 0; + + for (cpu = 0; cpu < PLATFORM_CLUSTER_COUNT; cpu++) + clst_warmboot_data[cpu] = 0; + + /* config cpu's warm boot address */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), + (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | + CPU_BOOT_ADDR_WMASK); + mmio_write_32(PMU_BASE + PMU_NOC_AUTO_ENA, NOC_AUTO_ENABLE); + + /* + * Enable Schmitt trigger for better 32 kHz input signal, which is + * important for suspend/resume reliability among other things. + */ + mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_SMT, GPIO0A0_SMT_ENABLE); + + init_pmu_counts(); + + nonboot_cpus_off(); + + INFO("%s(%d): pd status %x\n", __func__, __LINE__, + mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h new file mode 100644 index 0000000..bb7de50 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_H +#define PMU_H + +#include +#include +#include + +/* Allocate sp reginon in pmusram */ +#define PSRAM_SP_SIZE 0x80 +#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE) + +/***************************************************************************** + * Common define for per soc pmu.h + *****************************************************************************/ +/* The ways of cores power domain contorlling */ +enum cores_pm_ctr_mode { + core_pwr_pd = 0, + core_pwr_wfi = 1, + core_pwr_wfi_int = 2 +}; + +/***************************************************************************** + * pmu con,reg + *****************************************************************************/ +#define PMU_WKUP_CFG(n) ((n) * 4) + +#define PMU_CORE_PM_CON(cpu) (0xc0 + (cpu * 4)) + +/* the shift of bits for cores status */ +enum pmu_core_pwrst_shift { + clstl_cpu_wfe = 2, + clstl_cpu_wfi = 6, + clstb_cpu_wfe = 12, + clstb_cpu_wfi = 16 +}; + +#define CKECK_WFE_MSK 0x1 +#define CKECK_WFI_MSK 0x10 +#define CKECK_WFEI_MSK 0x11 + +/* Specific features required */ +#define AP_PWROFF 0x0a + +#define GPIO0A0_SMT_ENABLE BITS_WITH_WMASK(1, 3, 0) +#define GPIO1A6_IOMUX BITS_WITH_WMASK(0, 3, 12) + +#define TSADC_INT_PIN 38 +#define CORES_PM_DISABLE 0x0 + +#define PD_CTR_LOOP 10000 +#define CHK_CPU_LOOP 500 +#define MAX_WAIT_COUNT 1000 + +#define GRF_SOC_CON4 0x0e210 + +#define PMUGRF_GPIO0A_SMT 0x0120 +#define PMUGRF_SOC_CON0 0x0180 + +#define CCI_FORCE_WAKEUP WMSK_BIT(8) +#define EXTERNAL_32K WMSK_BIT(0) + +#define PLL_PD_HW 0xff +#define IOMUX_CLK_32K 0x00030002 +#define NOC_AUTO_ENABLE 0x3fffffff + +#define SAVE_QOS(array, NAME) \ + RK3399_CPU_AXI_SAVE_QOS(array, CPU_AXI_##NAME##_QOS_BASE) +#define RESTORE_QOS(array, NAME) \ + RK3399_CPU_AXI_RESTORE_QOS(array, CPU_AXI_##NAME##_QOS_BASE) + +#define RK3399_CPU_AXI_SAVE_QOS(array, base) do { \ + array[0] = mmio_read_32(base + CPU_AXI_QOS_ID_COREID); \ + array[1] = mmio_read_32(base + CPU_AXI_QOS_REVISIONID); \ + array[2] = mmio_read_32(base + CPU_AXI_QOS_PRIORITY); \ + array[3] = mmio_read_32(base + CPU_AXI_QOS_MODE); \ + array[4] = mmio_read_32(base + CPU_AXI_QOS_BANDWIDTH); \ + array[5] = mmio_read_32(base + CPU_AXI_QOS_SATURATION); \ + array[6] = mmio_read_32(base + CPU_AXI_QOS_EXTCONTROL); \ +} while (0) + +#define RK3399_CPU_AXI_RESTORE_QOS(array, base) do { \ + mmio_write_32(base + CPU_AXI_QOS_ID_COREID, array[0]); \ + mmio_write_32(base + CPU_AXI_QOS_REVISIONID, array[1]); \ + mmio_write_32(base + CPU_AXI_QOS_PRIORITY, array[2]); \ + mmio_write_32(base + CPU_AXI_QOS_MODE, array[3]); \ + mmio_write_32(base + CPU_AXI_QOS_BANDWIDTH, array[4]); \ + mmio_write_32(base + CPU_AXI_QOS_SATURATION, array[5]); \ + mmio_write_32(base + CPU_AXI_QOS_EXTCONTROL, array[6]); \ +} while (0) + +struct pmu_slpdata_s { + uint32_t cci_m0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t cci_m1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t dmac0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t dmac1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t dcf_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t crypto0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t crypto1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t pmu_cm0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t peri_cm1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t gic_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t sdmmc_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t gmac_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t emmc_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t usb_otg0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t usb_otg1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t usb_host0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t usb_host1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t gpu_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t video_m0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t video_m1_r_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t video_m1_w_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t rga_r_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t rga_w_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t vop_big_r[CPU_AXI_QOS_NUM_REGS]; + uint32_t vop_big_w[CPU_AXI_QOS_NUM_REGS]; + uint32_t vop_little[CPU_AXI_QOS_NUM_REGS]; + uint32_t iep_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp1_m0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp1_m1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp0_m0_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t isp0_m1_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t hdcp_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t perihp_nsp_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t perilp_nsp_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t perilpslv_nsp_qos[CPU_AXI_QOS_NUM_REGS]; + uint32_t sdio_qos[CPU_AXI_QOS_NUM_REGS]; +}; + +extern uint32_t clst_warmboot_data[PLATFORM_CLUSTER_COUNT]; + +extern void sram_func_set_ddrctl_pll(uint32_t pll_src); +void pmu_power_domains_on(void); + +#endif /* PMU_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c new file mode 100644 index 0000000..25596b1 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* convoluted way to make sure that the define is pasted just the right way */ +#define INCBIN(file, sym, sec) \ + __asm__( \ + ".section " sec "\n" \ + ".global " sym "\n" \ + ".type " sym ", %object\n" \ + ".align 4\n" \ + sym ":\n" \ + ".incbin \"" file "\"\n" \ + ".size " sym ", .-" sym "\n" \ + ".global " sym "_end\n" \ + sym "_end:\n" \ + ) + +INCBIN(RK3399M0FW, "rk3399m0_bin", ".sram.incbin"); +INCBIN(RK3399M0PMUFW, "rk3399m0pmu_bin", ".pmusram.incbin"); diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c new file mode 100644 index 0000000..11c1565 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define PWM0_IOMUX_PWM_EN (1 << 0) +#define PWM1_IOMUX_PWM_EN (1 << 1) +#define PWM2_IOMUX_PWM_EN (1 << 2) +#define PWM3_IOMUX_PWM_EN (1 << 3) + +struct pwm_data_s { + uint32_t iomux_bitmask; + uint32_t enable_bitmask; +}; + +static struct pwm_data_s pwm_data; + +/* + * Disable the PWMs. + */ +void disable_pwms(void) +{ + uint32_t i, val; + + pwm_data.iomux_bitmask = 0; + + /* Save PWMs pinmux and change PWMs pinmux to GPIOs */ + val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX); + if (((val >> GRF_GPIO4C2_IOMUX_SHIFT) & + GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C2_IOMUX_PWM) { + pwm_data.iomux_bitmask |= PWM0_IOMUX_PWM_EN; + val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK, + GRF_GPIO4C2_IOMUX_SHIFT); + mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val); + } + + val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX); + if (((val >> GRF_GPIO4C6_IOMUX_SHIFT) & + GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C6_IOMUX_PWM) { + pwm_data.iomux_bitmask |= PWM1_IOMUX_PWM_EN; + val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK, + GRF_GPIO4C6_IOMUX_SHIFT); + mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val); + } + + val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX); + if (((val >> PMUGRF_GPIO1C3_IOMUX_SHIFT) & + GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO1C3_IOMUX_PWM) { + pwm_data.iomux_bitmask |= PWM2_IOMUX_PWM_EN; + val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK, + PMUGRF_GPIO1C3_IOMUX_SHIFT); + mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val); + } + + val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX); + if (((val >> PMUGRF_GPIO0A6_IOMUX_SHIFT) & + GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO0A6_IOMUX_PWM) { + pwm_data.iomux_bitmask |= PWM3_IOMUX_PWM_EN; + val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK, + PMUGRF_GPIO0A6_IOMUX_SHIFT); + mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val); + } + + /* Disable the pwm channel */ + pwm_data.enable_bitmask = 0; + for (i = 0; i < 4; i++) { + val = mmio_read_32(PWM_BASE + PWM_CTRL(i)); + if ((val & PWM_ENABLE) != PWM_ENABLE) + continue; + pwm_data.enable_bitmask |= (1 << i); + mmio_write_32(PWM_BASE + PWM_CTRL(i), val & ~PWM_ENABLE); + } +} + +/* + * Enable the PWMs. + */ +void enable_pwms(void) +{ + uint32_t i, val; + + for (i = 0; i < 4; i++) { + val = mmio_read_32(PWM_BASE + PWM_CTRL(i)); + if (!(pwm_data.enable_bitmask & (1 << i))) + continue; + mmio_write_32(PWM_BASE + PWM_CTRL(i), val | PWM_ENABLE); + } + + /* Restore all IOMUXes */ + if (pwm_data.iomux_bitmask & PWM3_IOMUX_PWM_EN) { + val = BITS_WITH_WMASK(PMUGRF_GPIO0A6_IOMUX_PWM, + GRF_IOMUX_2BIT_MASK, + PMUGRF_GPIO0A6_IOMUX_SHIFT); + mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val); + } + + if (pwm_data.iomux_bitmask & PWM2_IOMUX_PWM_EN) { + val = BITS_WITH_WMASK(PMUGRF_GPIO1C3_IOMUX_PWM, + GRF_IOMUX_2BIT_MASK, + PMUGRF_GPIO1C3_IOMUX_SHIFT); + mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val); + } + + if (pwm_data.iomux_bitmask & PWM1_IOMUX_PWM_EN) { + val = BITS_WITH_WMASK(GRF_GPIO4C6_IOMUX_PWM, + GRF_IOMUX_2BIT_MASK, + GRF_GPIO4C6_IOMUX_SHIFT); + mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val); + } + + if (pwm_data.iomux_bitmask & PWM0_IOMUX_PWM_EN) { + val = BITS_WITH_WMASK(GRF_GPIO4C2_IOMUX_PWM, + GRF_IOMUX_2BIT_MASK, + GRF_GPIO4C2_IOMUX_SHIFT); + mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val); + } +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h new file mode 100644 index 0000000..d665392 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PWM_H +#define PWM_H + +void disable_pwms(void); +void enable_pwms(void); + +#endif /* PWM_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c new file mode 100644 index 0000000..13c83ca --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + +static void sgrf_ddr_rgn_global_bypass(uint32_t bypass) +{ + if (bypass) + /* set bypass (non-secure regions) for whole ddr regions */ + mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16), + SGRF_DDR_RGN_BYPS); + else + /* cancel bypass for whole ddr regions */ + mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16), + SGRF_DDR_RGN_NO_BYPS); +} + +/** + * There are 8 + 1 regions for DDR secure control: + * DDR_RGN_0 ~ DDR_RGN_7: Per DDR_RGNs grain size is 1MB + * DDR_RGN_X - the memories of exclude DDR_RGN_0 ~ DDR_RGN_7 + * + * DDR_RGN_0 - start address of the RGN0 + * DDR_RGN_8 - end address of the RGN0 + * DDR_RGN_1 - start address of the RGN1 + * DDR_RGN_9 - end address of the RGN1 + * ... + * DDR_RGN_7 - start address of the RGN7 + * DDR_RGN_15 - end address of the RGN7 + * DDR_RGN_16 - bit 0 ~ 7 is bitmap for RGN0~7 secure,0: disable, 1: enable + * bit 8 is setting for RGNx, the rest of the memory and region + * which excludes RGN0~7, 0: disable, 1: enable + * bit 9, the global secure configuration via bypass, 0: disable + * bypass, 1: enable bypass + * + * @rgn - the DDR regions 0 ~ 7 which are can be configured. + * @st - start address to set as secure + * @sz - length of area to set as secure + * The @st_mb and @ed_mb indicate the start and end addresses for which to set + * the security, and the unit is megabyte. When the st_mb == 0, ed_mb == 0, the + * address range 0x0 ~ 0xfffff is secure. + * + * For example, if we would like to set the range [0, 32MB) is security via + * DDR_RGN0, then rgn == 0, st_mb == 0, ed_mb == 31. + */ +static void sgrf_ddr_rgn_config(uint32_t rgn, + uintptr_t st, size_t sz) +{ + uintptr_t ed = st + sz; + uintptr_t st_mb, ed_mb; + + assert(rgn <= 7); + assert(st < ed); + + /* check aligned 1MB */ + assert(st % SIZE_M(1) == 0); + assert(ed % SIZE_M(1) == 0); + + st_mb = st / SIZE_M(1); + ed_mb = ed / SIZE_M(1); + + /* set ddr region addr start */ + mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(rgn), + BITS_WITH_WMASK(st_mb, SGRF_DDR_RGN_0_16_WMSK, 0)); + + /* set ddr region addr end */ + mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(rgn + 8), + BITS_WITH_WMASK((ed_mb - 1), SGRF_DDR_RGN_0_16_WMSK, 0)); + + mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16), + BIT_WITH_WMSK(rgn)); +} + +void secure_watchdog_gate(void) +{ + /** + * Disable CA53 and CM0 wdt pclk + * BIT[8]: ca53 wdt pclk, 0: enable 1: disable + * BIT[10]: cm0 wdt pclk, 0: enable 1: disable + */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), + BIT_WITH_WMSK(PCLK_WDT_CA53_GATE_SHIFT) | + BIT_WITH_WMSK(PCLK_WDT_CM0_GATE_SHIFT)); +} + +__pmusramfunc void secure_watchdog_ungate(void) +{ + /** + * Enable CA53 and CM0 wdt pclk + * BIT[8]: ca53 wdt pclk, 0: enable 1: disable + * BIT[10]: cm0 wdt pclk, 0: enable 1: disable + */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), + WMSK_BIT(PCLK_WDT_CA53_GATE_SHIFT) | + WMSK_BIT(PCLK_WDT_CM0_GATE_SHIFT)); +} + +__pmusramfunc void sram_secure_timer_init(void) +{ + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff); + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT1, 0xffffffff); + + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0); + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG, + TIMER_EN | TIMER_FMODE); +} + +void secure_timer_init(void) +{ + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff); + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT1, 0xffffffff); + + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0); + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG, + TIMER_EN | TIMER_FMODE); +} + +void secure_sgrf_init(void) +{ + /* security config for master */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), + REG_SOC_WMSK | SGRF_SOC_ALLMST_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), + REG_SOC_WMSK | SGRF_SOC_ALLMST_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), + REG_SOC_WMSK | SGRF_SOC_ALLMST_NS); + + /* security config for slave */ + mmio_write_32(SGRF_BASE + SGRF_PMU_SLV_CON0_1(0), + SGRF_PMU_SLV_S_CFGED | + SGRF_PMU_SLV_CRYPTO1_NS); + mmio_write_32(SGRF_BASE + SGRF_PMU_SLV_CON0_1(1), + SGRF_SLV_S_WMSK | SGRF_PMUSRAM_S); + mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(0), + SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(1), + SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(2), + SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(3), + SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS); + mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(4), + SGRF_SLV_S_WMSK | SGRF_INTSRAM_S); +} + +void secure_sgrf_ddr_rgn_init(void) +{ + sgrf_ddr_rgn_config(0, TZRAM_BASE, TZRAM_SIZE); + sgrf_ddr_rgn_global_bypass(0); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h new file mode 100644 index 0000000..e31c999 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SECURE_H +#define SECURE_H + +/************************************************** + * sgrf reg, offset + **************************************************/ +#define SGRF_SOC_CON0_1(n) (0xc000 + (n) * 4) +#define SGRF_SOC_CON3_7(n) (0xe00c + ((n) - 3) * 4) +#define SGRF_SOC_CON8_15(n) (0x8020 + ((n) - 8) * 4) +#define SGRF_SOC_CON(n) (n < 3 ? SGRF_SOC_CON0_1(n) :\ + (n < 8 ? SGRF_SOC_CON3_7(n) :\ + SGRF_SOC_CON8_15(n))) + +#define SGRF_PMU_SLV_CON0_1(n) (0xc240 + ((n) - 0) * 4) +#define SGRF_SLV_SECURE_CON0_4(n) (0xe3c0 + ((n) - 0) * 4) +#define SGRF_DDRRGN_CON0_16(n) ((n) * 4) +#define SGRF_DDRRGN_CON20_34(n) (0x50 + ((n) - 20) * 4) + +/* All of master in ns */ +#define SGRF_SOC_ALLMST_NS 0xffff + +/* security config for slave */ +#define SGRF_SLV_S_WMSK 0xffff0000 +#define SGRF_SLV_S_ALL_NS 0x0 + +/* security config pmu slave ip */ +/* All of slaves is ns */ +#define SGRF_PMU_SLV_S_NS BIT_WITH_WMSK(0) +/* slaves secure attr is configed */ +#define SGRF_PMU_SLV_S_CFGED WMSK_BIT(0) +#define SGRF_PMU_SLV_CRYPTO1_NS WMSK_BIT(1) + +#define SGRF_PMUSRAM_S BIT(8) + +#define SGRF_INTSRAM_S BIT(13) + +/* ddr region */ +#define SGRF_DDR_RGN_0_16_WMSK 0x0fff /* DDR RGN 0~16 size mask */ + +#define SGRF_DDR_RGN_DPLL_CLK BIT_WITH_WMSK(15) /* DDR PLL output clock */ +#define SGRF_DDR_RGN_RTC_CLK BIT_WITH_WMSK(14) /* 32K clock for DDR PLL */ + +/* All security of the DDR RGNs are bypass */ +#define SGRF_DDR_RGN_BYPS BIT_WITH_WMSK(9) +/* All security of the DDR RGNs are not bypass */ +#define SGRF_DDR_RGN_NO_BYPS WMSK_BIT(9) + +/* The MST access the ddr rgn n with secure attribution */ +#define SGRF_L_MST_S_DDR_RGN(n) BIT_WITH_WMSK((n)) +/* bits[16:8]*/ +#define SGRF_H_MST_S_DDR_RGN(n) BIT_WITH_WMSK((n) + 8) + +#define SGRF_PMU_CON0 0x0c100 +#define SGRF_PMU_CON(n) (SGRF_PMU_CON0 + (n) * 4) + +/************************************************** + * secure timer + **************************************************/ +/* chanal0~5 */ +#define STIMER0_CHN_BASE(n) (STIME_BASE + 0x20 * (n)) +/* chanal6~11 */ +#define STIMER1_CHN_BASE(n) (STIME_BASE + 0x8000 + 0x20 * (n)) + + /* low 32 bits */ +#define TIMER_END_COUNT0 0x00 + /* high 32 bits */ +#define TIMER_END_COUNT1 0x04 + +#define TIMER_CURRENT_VALUE0 0x08 +#define TIMER_CURRENT_VALUE1 0x0C + + /* low 32 bits */ +#define TIMER_INIT_COUNT0 0x10 + /* high 32 bits */ +#define TIMER_INIT_COUNT1 0x14 + +#define TIMER_INTSTATUS 0x18 +#define TIMER_CONTROL_REG 0x1c + +#define TIMER_EN 0x1 + +#define TIMER_FMODE (0x0 << 1) +#define TIMER_RMODE (0x1 << 1) + +/************************************************** + * secure WDT + **************************************************/ +#define PCLK_WDT_CA53_GATE_SHIFT 8 +#define PCLK_WDT_CM0_GATE_SHIFT 10 + +/* export secure operating APIs */ +void secure_watchdog_gate(void); +__pmusramfunc void secure_watchdog_ungate(void); +void secure_timer_init(void); +void secure_sgrf_init(void); +void secure_sgrf_ddr_rgn_init(void); +__pmusramfunc void sram_secure_timer_init(void); + +#endif /* SECURE_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c new file mode 100644 index 0000000..98b5ad6 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2016, 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 + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(DEV_RNG0_BASE, DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + + { 0 } +}; + +/* The RockChip power domain tree descriptor */ +const unsigned char rockchip_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, + /* No of children for the second cluster node */ + PLATFORM_CLUSTER1_CORE_COUNT +}; + +/* sleep data for pll suspend */ +static struct deepsleep_data_s slp_data; + +/* sleep data that needs to be accessed from pmusram */ +__pmusramdata struct pmu_sleep_data pmu_slp_data; + +static void set_pll_slow_mode(uint32_t pll_id) +{ + if (pll_id == PPLL_ID) + mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_SLOW_MODE); + else + mmio_write_32((CRU_BASE + + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE); +} + +static void set_pll_normal_mode(uint32_t pll_id) +{ + if (pll_id == PPLL_ID) + mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_NOMAL_MODE); + else + mmio_write_32(CRU_BASE + + CRU_PLL_CON(pll_id, 3), PLL_NOMAL_MODE); +} + +static void set_pll_bypass(uint32_t pll_id) +{ + if (pll_id == PPLL_ID) + mmio_write_32(PMUCRU_BASE + + PMUCRU_PPLL_CON(3), PLL_BYPASS_MODE); + else + mmio_write_32(CRU_BASE + + CRU_PLL_CON(pll_id, 3), PLL_BYPASS_MODE); +} + +static void _pll_suspend(uint32_t pll_id) +{ + set_pll_slow_mode(pll_id); + set_pll_bypass(pll_id); +} + +/** + * disable_dvfs_plls - To suspend the specific PLLs + * + * When we close the center logic, the DPLL will be closed, + * so we need to keep the ABPLL and switch to it to supply + * clock for DDR during suspend, then we should not close + * the ABPLL and exclude ABPLL_ID. + */ +void disable_dvfs_plls(void) +{ + _pll_suspend(CPLL_ID); + _pll_suspend(NPLL_ID); + _pll_suspend(VPLL_ID); + _pll_suspend(GPLL_ID); + _pll_suspend(ALPLL_ID); +} + +/** + * disable_nodvfs_plls - To suspend the PPLL + */ +void disable_nodvfs_plls(void) +{ + _pll_suspend(PPLL_ID); +} + +/** + * restore_pll - Copy PLL settings from memory to a PLL. + * + * This will copy PLL settings from an array in memory to the memory mapped + * registers for a PLL. + * + * Note that: above the PLL exclude PPLL. + * + * pll_id: One of the values from enum plls_id + * src: Pointer to the array of values to restore from + */ +static void restore_pll(int pll_id, uint32_t *src) +{ + /* Nice to have PLL off while configuring */ + mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE); + + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK); + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK); + + /* Do PLL_CON3 since that will enable things */ + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK); + + /* Wait for PLL lock done */ + while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) & + 0x80000000) == 0x0) + ; +} + +/** + * save_pll - Copy PLL settings a PLL to memory + * + * This will copy PLL settings from the memory mapped registers for a PLL to + * an array in memory. + * + * Note that: above the PLL exclude PPLL. + * + * pll_id: One of the values from enum plls_id + * src: Pointer to the array of values to save to. + */ +static void save_pll(uint32_t *dst, int pll_id) +{ + int i; + + for (i = 0; i < PLL_CON_COUNT; i++) + dst[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i)); +} + +/** + * prepare_abpll_for_ddrctrl - Copy DPLL settings to ABPLL + * + * This will copy DPLL settings from the memory mapped registers for a PLL to + * an array in memory. + */ +void prepare_abpll_for_ddrctrl(void) +{ + save_pll(slp_data.plls_con[ABPLL_ID], ABPLL_ID); + save_pll(slp_data.plls_con[DPLL_ID], DPLL_ID); + + restore_pll(ABPLL_ID, slp_data.plls_con[DPLL_ID]); +} + +void restore_abpll(void) +{ + restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]); +} + +void clk_gate_con_save(void) +{ + uint32_t i = 0; + + for (i = 0; i < PMUCRU_GATE_COUNT; i++) + slp_data.pmucru_gate_con[i] = + mmio_read_32(PMUCRU_BASE + PMUCRU_GATE_CON(i)); + + for (i = 0; i < CRU_GATE_COUNT; i++) + slp_data.cru_gate_con[i] = + mmio_read_32(CRU_BASE + CRU_GATE_CON(i)); +} + +void clk_gate_con_disable(void) +{ + uint32_t i; + + for (i = 0; i < PMUCRU_GATE_COUNT; i++) + mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i), REG_SOC_WMSK); + + for (i = 0; i < CRU_GATE_COUNT; i++) + mmio_write_32(CRU_BASE + CRU_GATE_CON(i), REG_SOC_WMSK); +} + +void clk_gate_con_restore(void) +{ + uint32_t i; + + for (i = 0; i < PMUCRU_GATE_COUNT; i++) + mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i), + REG_SOC_WMSK | slp_data.pmucru_gate_con[i]); + + for (i = 0; i < CRU_GATE_COUNT; i++) + mmio_write_32(CRU_BASE + CRU_GATE_CON(i), + REG_SOC_WMSK | slp_data.cru_gate_con[i]); +} + +static void set_plls_nobypass(uint32_t pll_id) +{ + if (pll_id == PPLL_ID) + mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), + PLL_NO_BYPASS_MODE); + else + mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), + PLL_NO_BYPASS_MODE); +} + +static void _pll_resume(uint32_t pll_id) +{ + set_plls_nobypass(pll_id); + set_pll_normal_mode(pll_id); +} + +void set_pmu_rsthold(void) +{ + uint32_t rstnhold_cofig0; + uint32_t rstnhold_cofig1; + + pmu_slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE + + PMUCRU_RSTNHOLD_CON0); + pmu_slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE + + PMUCRU_RSTNHOLD_CON1); + rstnhold_cofig0 = BIT_WITH_WMSK(PRESETN_NOC_PMU_HOLD) | + BIT_WITH_WMSK(PRESETN_INTMEM_PMU_HOLD) | + BIT_WITH_WMSK(HRESETN_CM0S_PMU_HOLD) | + BIT_WITH_WMSK(HRESETN_CM0S_NOC_PMU_HOLD) | + BIT_WITH_WMSK(DRESETN_CM0S_PMU_HOLD) | + BIT_WITH_WMSK(POESETN_CM0S_PMU_HOLD) | + BIT_WITH_WMSK(PRESETN_TIMER_PMU_0_1_HOLD) | + BIT_WITH_WMSK(RESETN_TIMER_PMU_0_HOLD) | + BIT_WITH_WMSK(RESETN_TIMER_PMU_1_HOLD) | + BIT_WITH_WMSK(PRESETN_UART_M0_PMU_HOLD) | + BIT_WITH_WMSK(RESETN_UART_M0_PMU_HOLD) | + BIT_WITH_WMSK(PRESETN_WDT_PMU_HOLD); + rstnhold_cofig1 = BIT_WITH_WMSK(PRESETN_RKPWM_PMU_HOLD) | + BIT_WITH_WMSK(PRESETN_PMUGRF_HOLD) | + BIT_WITH_WMSK(PRESETN_SGRF_HOLD) | + BIT_WITH_WMSK(PRESETN_GPIO0_HOLD) | + BIT_WITH_WMSK(PRESETN_GPIO1_HOLD) | + BIT_WITH_WMSK(PRESETN_CRU_PMU_HOLD) | + BIT_WITH_WMSK(PRESETN_PVTM_PMU_HOLD); + + mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0, rstnhold_cofig0); + mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1, rstnhold_cofig1); +} + +void pmu_sgrf_rst_hld(void) +{ + mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1), + CRU_PMU_SGRF_RST_HOLD); +} + +/* + * When system reset in running state, we want the cpus to be reboot + * from maskrom (system reboot), + * the pmusgrf reset-hold bits needs to be released. + * When system wake up from system deep suspend, some soc will be reset + * when waked up, + * we want the bootcpu to be reboot from pmusram, + * the pmusgrf reset-hold bits needs to be held. + */ +__pmusramfunc void pmu_sgrf_rst_hld_release(void) +{ + mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1), + CRU_PMU_SGRF_RST_RLS); +} + +__pmusramfunc void restore_pmu_rsthold(void) +{ + mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0, + pmu_slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK); + mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1, + pmu_slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK); +} + +/** + * enable_dvfs_plls - To resume the specific PLLs + * + * Please see the comment at the disable_dvfs_plls() + * we don't suspend the ABPLL, so don't need resume + * it too. + */ +void enable_dvfs_plls(void) +{ + _pll_resume(ALPLL_ID); + _pll_resume(GPLL_ID); + _pll_resume(VPLL_ID); + _pll_resume(NPLL_ID); + _pll_resume(CPLL_ID); +} + +/** + * enable_nodvfs_plls - To resume the PPLL + */ +void enable_nodvfs_plls(void) +{ + _pll_resume(PPLL_ID); +} + +void soc_global_soft_reset_init(void) +{ + mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1), + CRU_PMU_SGRF_RST_RLS); + + mmio_clrbits_32(CRU_BASE + CRU_GLB_RST_CON, + CRU_PMU_WDTRST_MSK | CRU_PMU_FIRST_SFTRST_MSK); +} + +void __dead2 soc_global_soft_reset(void) +{ + pmu_power_domains_on(); + set_pll_slow_mode(VPLL_ID); + set_pll_slow_mode(NPLL_ID); + set_pll_slow_mode(GPLL_ID); + set_pll_slow_mode(CPLL_ID); + set_pll_slow_mode(PPLL_ID); + set_pll_slow_mode(ABPLL_ID); + set_pll_slow_mode(ALPLL_ID); + + dsb(); + + mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to excute valid codes. + */ + while (1) + ; +} + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + secure_sgrf_init(); + secure_sgrf_ddr_rgn_init(); + soc_global_soft_reset_init(); + plat_rockchip_gpio_init(); + m0_init(); + dram_init(); + dram_dfs_init(); +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h new file mode 100644 index 0000000..8daa5bb --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +#include + +#define GLB_SRST_FST_CFG_VAL 0xfdb9 +#define GLB_SRST_SND_CFG_VAL 0xeca8 + +#define PMUCRU_PPLL_CON(n) ((n) * 4) +#define CRU_PLL_CON(pll_id, n) ((pll_id) * 0x20 + (n) * 4) +#define PLL_MODE_MSK 0x03 +#define PLL_MODE_SHIFT 0x08 +#define PLL_BYPASS_MSK 0x01 +#define PLL_BYPASS_SHIFT 0x01 +#define PLL_PWRDN_MSK 0x01 +#define PLL_PWRDN_SHIFT 0x0 +#define PLL_BYPASS BIT(1) +#define PLL_PWRDN BIT(0) + +#define NO_PLL_BYPASS (0x00) +#define NO_PLL_PWRDN (0x00) + +#define FBDIV(n) ((0xfff << 16) | n) +#define POSTDIV2(n) ((0x7 << (12 + 16)) | (n << 12)) +#define POSTDIV1(n) ((0x7 << (8 + 16)) | (n << 8)) +#define REFDIV(n) ((0x3F << 16) | n) +#define PLL_LOCK(n) ((n >> 31) & 0x1) + +#define PLL_SLOW_MODE BITS_WITH_WMASK(SLOW_MODE,\ + PLL_MODE_MSK, PLL_MODE_SHIFT) + +#define PLL_NOMAL_MODE BITS_WITH_WMASK(NORMAL_MODE,\ + PLL_MODE_MSK, PLL_MODE_SHIFT) + +#define PLL_BYPASS_MODE BIT_WITH_WMSK(PLL_BYPASS_SHIFT) +#define PLL_NO_BYPASS_MODE WMSK_BIT(PLL_BYPASS_SHIFT) + +#define PLL_CON_COUNT 0x06 +#define CRU_CLKSEL_COUNT 108 +#define CRU_CLKSEL_CON(n) (0x100 + (n) * 4) + +#define PMUCRU_CLKSEL_CONUT 0x06 +#define PMUCRU_CLKSEL_OFFSET 0x080 +#define REG_SIZE 0x04 +#define REG_SOC_WMSK 0xffff0000 +#define CLK_GATE_MASK 0x01 + +#define PMUCRU_GATE_COUNT 0x03 +#define CRU_GATE_COUNT 0x23 +#define PMUCRU_GATE_CON(n) (0x100 + (n) * 4) +#define CRU_GATE_CON(n) (0x300 + (n) * 4) + +#define PMUCRU_RSTNHOLD_CON0 0x120 +enum { + PRESETN_NOC_PMU_HOLD = 1, + PRESETN_INTMEM_PMU_HOLD, + HRESETN_CM0S_PMU_HOLD, + HRESETN_CM0S_NOC_PMU_HOLD, + DRESETN_CM0S_PMU_HOLD, + POESETN_CM0S_PMU_HOLD, + PRESETN_SPI3_HOLD, + RESETN_SPI3_HOLD, + PRESETN_TIMER_PMU_0_1_HOLD, + RESETN_TIMER_PMU_0_HOLD, + RESETN_TIMER_PMU_1_HOLD, + PRESETN_UART_M0_PMU_HOLD, + RESETN_UART_M0_PMU_HOLD, + PRESETN_WDT_PMU_HOLD +}; + +#define PMUCRU_RSTNHOLD_CON1 0x124 +enum { + PRESETN_I2C0_HOLD, + PRESETN_I2C4_HOLD, + PRESETN_I2C8_HOLD, + PRESETN_MAILBOX_PMU_HOLD, + PRESETN_RKPWM_PMU_HOLD, + PRESETN_PMUGRF_HOLD, + PRESETN_SGRF_HOLD, + PRESETN_GPIO0_HOLD, + PRESETN_GPIO1_HOLD, + PRESETN_CRU_PMU_HOLD, + PRESETN_INTR_ARB_HOLD, + PRESETN_PVTM_PMU_HOLD, + RESETN_I2C0_HOLD, + RESETN_I2C4_HOLD, + RESETN_I2C8_HOLD +}; + +enum plls_id { + ALPLL_ID = 0, + ABPLL_ID, + DPLL_ID, + CPLL_ID, + GPLL_ID, + NPLL_ID, + VPLL_ID, + PPLL_ID, + END_PLL_ID, +}; + +#define CLST_L_CPUS_MSK (0xf) +#define CLST_B_CPUS_MSK (0x3) + +enum pll_work_mode { + SLOW_MODE = 0x00, + NORMAL_MODE = 0x01, + DEEP_SLOW_MODE = 0x02, +}; + +enum glb_sft_reset { + PMU_RST_BY_FIRST_SFT, + PMU_RST_BY_SECOND_SFT = BIT(2), + PMU_RST_NOT_BY_SFT = BIT(3), +}; + +struct pll_div { + uint32_t mhz; + uint32_t refdiv; + uint32_t fbdiv; + uint32_t postdiv1; + uint32_t postdiv2; + uint32_t frac; + uint32_t freq; +}; + +struct deepsleep_data_s { + uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT]; + uint32_t cru_gate_con[CRU_GATE_COUNT]; + uint32_t pmucru_gate_con[PMUCRU_GATE_COUNT]; +}; + +struct pmu_sleep_data { + uint32_t pmucru_rstnhold_con0; + uint32_t pmucru_rstnhold_con1; +}; + +/************************************************** + * pmugrf reg, offset + **************************************************/ +#define PMUGRF_OSREG(n) (0x300 + (n) * 4) +#define PMUGRF_GPIO0A_P 0x040 +#define PMUGRF_GPIO1A_P 0x050 + +/************************************************** + * DCF reg, offset + **************************************************/ +#define DCF_DCF_CTRL 0x0 +#define DCF_DCF_ADDR 0x8 +#define DCF_DCF_ISR 0xc +#define DCF_DCF_TOSET 0x14 +#define DCF_DCF_TOCMD 0x18 +#define DCF_DCF_CMD_CFG 0x1c + +/* DCF_DCF_ISR */ +#define DCF_TIMEOUT (1 << 2) +#define DCF_ERR (1 << 1) +#define DCF_DONE (1 << 0) + +/* DCF_DCF_CTRL */ +#define DCF_VOP_HW_EN (1 << 2) +#define DCF_STOP (1 << 1) +#define DCF_START (1 << 0) + +#define CYCL_24M_CNT_US(us) (24 * us) +#define CYCL_24M_CNT_MS(ms) (ms * CYCL_24M_CNT_US(1000)) +#define CYCL_32K_CNT_MS(ms) (ms * 32) + +/************************************************** + * cru reg, offset + **************************************************/ +#define CRU_SOFTRST_CON(n) (0x400 + (n) * 4) + +#define CRU_DMAC0_RST BIT_WITH_WMSK(3) + /* reset release*/ +#define CRU_DMAC0_RST_RLS WMSK_BIT(3) + +#define CRU_DMAC1_RST BIT_WITH_WMSK(4) + /* reset release*/ +#define CRU_DMAC1_RST_RLS WMSK_BIT(4) + +#define CRU_GLB_RST_CON 0x0510 +#define CRU_GLB_SRST_FST 0x0500 +#define CRU_GLB_SRST_SND 0x0504 + +#define CRU_CLKGATE_CON(n) (0x300 + n * 4) +#define PCLK_GPIO2_GATE_SHIFT 3 +#define PCLK_GPIO3_GATE_SHIFT 4 +#define PCLK_GPIO4_GATE_SHIFT 5 + +/************************************************** + * pmu cru reg, offset + **************************************************/ +#define CRU_PMU_RSTHOLD_CON(n) (0x120 + n * 4) +/* reset hold*/ +#define CRU_PMU_SGRF_RST_HOLD BIT_WITH_WMSK(6) +/* reset hold release*/ +#define CRU_PMU_SGRF_RST_RLS WMSK_BIT(6) + +#define CRU_PMU_WDTRST_MSK (0x1 << 4) +#define CRU_PMU_WDTRST_EN 0x0 + +#define CRU_PMU_FIRST_SFTRST_MSK (0x3 << 2) +#define CRU_PMU_FIRST_SFTRST_EN 0x0 + +#define CRU_PMU_CLKGATE_CON(n) (0x100 + n * 4) +#define PCLK_GPIO0_GATE_SHIFT 3 +#define PCLK_GPIO1_GATE_SHIFT 4 + +#define CPU_BOOT_ADDR_WMASK 0xffff0000 +#define CPU_BOOT_ADDR_ALIGN 16 + +#define GRF_IOMUX_2BIT_MASK 0x3 +#define GRF_IOMUX_GPIO 0x0 + +#define GRF_GPIO4C2_IOMUX_SHIFT 4 +#define GRF_GPIO4C2_IOMUX_PWM 0x1 +#define GRF_GPIO4C6_IOMUX_SHIFT 12 +#define GRF_GPIO4C6_IOMUX_PWM 0x1 + +#define PWM_CNT(n) (0x0000 + 0x10 * (n)) +#define PWM_PERIOD_HPR(n) (0x0004 + 0x10 * (n)) +#define PWM_DUTY_LPR(n) (0x0008 + 0x10 * (n)) +#define PWM_CTRL(n) (0x000c + 0x10 * (n)) + +#define PWM_DISABLE (0 << 0) +#define PWM_ENABLE (1 << 0) + +/* grf reg offset */ +#define GRF_USBPHY0_CTRL0 0x4480 +#define GRF_USBPHY0_CTRL2 0x4488 +#define GRF_USBPHY0_CTRL3 0x448c +#define GRF_USBPHY0_CTRL12 0x44b0 +#define GRF_USBPHY0_CTRL13 0x44b4 +#define GRF_USBPHY0_CTRL15 0x44bc +#define GRF_USBPHY0_CTRL16 0x44c0 + +#define GRF_USBPHY1_CTRL0 0x4500 +#define GRF_USBPHY1_CTRL2 0x4508 +#define GRF_USBPHY1_CTRL3 0x450c +#define GRF_USBPHY1_CTRL12 0x4530 +#define GRF_USBPHY1_CTRL13 0x4534 +#define GRF_USBPHY1_CTRL15 0x453c +#define GRF_USBPHY1_CTRL16 0x4540 + +#define GRF_GPIO2A_IOMUX 0xe000 +#define GRF_GPIO2A_P 0xe040 +#define GRF_GPIO3A_P 0xe050 +#define GRF_GPIO4A_P 0xe060 +#define GRF_GPIO2D_HE 0xe18c +#define GRF_DDRC0_CON0 0xe380 +#define GRF_DDRC0_CON1 0xe384 +#define GRF_DDRC1_CON0 0xe388 +#define GRF_DDRC1_CON1 0xe38c +#define GRF_SOC_CON_BASE 0xe200 +#define GRF_SOC_CON(n) (GRF_SOC_CON_BASE + (n) * 4) +#define GRF_IO_VSEL 0xe640 + +#define CRU_CLKSEL_CON0 0x0100 +#define CRU_CLKSEL_CON6 0x0118 +#define CRU_SDIO0_CON1 0x058c +#define PMUCRU_CLKSEL_CON0 0x0080 +#define PMUCRU_CLKGATE_CON2 0x0108 +#define PMUCRU_SOFTRST_CON0 0x0110 +#define PMUCRU_GATEDIS_CON0 0x0130 +#define PMUCRU_SOFTRST_CON(n) (PMUCRU_SOFTRST_CON0 + (n) * 4) + +/* export related and operating SoC APIs */ +void __dead2 soc_global_soft_reset(void); +void disable_dvfs_plls(void); +void disable_nodvfs_plls(void); +void enable_dvfs_plls(void); +void enable_nodvfs_plls(void); +void prepare_abpll_for_ddrctrl(void); +void restore_abpll(void); +void clk_gate_con_save(void); +void clk_gate_con_disable(void); +void clk_gate_con_restore(void); +void set_pmu_rsthold(void); +void pmu_sgrf_rst_hld(void); +__pmusramfunc void pmu_sgrf_rst_hld_release(void); +__pmusramfunc void restore_pmu_rsthold(void); +#endif /* SOC_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h new file mode 100644 index 0000000..dc1c703 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ADDRESSMAP_H +#define ADDRESSMAP_H + +#include + +/* Registers base address */ +#define MMIO_BASE 0xF8000000 + +/* Aggregate of all devices in the first GB */ +#define DEV_RNG0_BASE MMIO_BASE +#define DEV_RNG0_SIZE SIZE_M(125) + +#endif /* ADDRESSMAP_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S b/arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S new file mode 100644 index 0000000..cfa912f --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ROCKCHIP_PLAT_LD_S +#define ROCKCHIP_PLAT_LD_S + +#include + +MEMORY { + SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = SRAM_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "SRAM_BASE address is not aligned on a page boundary.") + + /* + * The SRAM space allocation for RK3399 + * ---------------- + * | m0 code bin + * ---------------- + * | sram text + * ---------------- + * | sram data + * ---------------- + */ + .incbin_sram : ALIGN(PAGE_SIZE) { + __sram_incbin_start = .; + *(.sram.incbin) + __sram_incbin_real_end = .; + . = ALIGN(PAGE_SIZE); + __sram_incbin_end = .; + } >SRAM + ASSERT((__sram_incbin_real_end - __sram_incbin_start) <= + SRAM_BIN_LIMIT, ".incbin_sram has exceeded its limit") + + .text_sram : ALIGN(PAGE_SIZE) { + __bl31_sram_text_start = .; + *(.sram.text) + *(.sram.rodata) + __bl31_sram_text_real_end = .; + . = ALIGN(PAGE_SIZE); + __bl31_sram_text_end = .; + } >SRAM + ASSERT((__bl31_sram_text_real_end - __bl31_sram_text_start) <= + SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit") + + .data_sram : ALIGN(PAGE_SIZE) { + __bl31_sram_data_start = .; + *(.sram.data) + __bl31_sram_data_real_end = .; + . = ALIGN(PAGE_SIZE); + __bl31_sram_data_end = .; + } >SRAM + ASSERT((__bl31_sram_data_real_end - __bl31_sram_data_start) <= + SRAM_DATA_LIMIT, ".data_sram has exceeded its limit") + + .stack_sram : ALIGN(PAGE_SIZE) { + __bl31_sram_stack_start = .; + . += PAGE_SIZE; + __bl31_sram_stack_end = .; + } >SRAM + + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + *(.pmusram.entry) + + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + + /* M0 start address request 4K align */ + . = ALIGN(4096); + __pmusram_incbin_start = .; + *(.pmusram.incbin) + __pmusram_incbin_end = .; + + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; + } >PMUSRAM +} + +#endif /* ROCKCHIP_PLAT_LD_S */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h new file mode 100644 index 0000000..66c4868 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +#define RK_PLAT_SIP_NUM_CALLS 0 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h new file mode 100644 index 0000000..78269b6 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#include +#include + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL1) +#define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +#define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x800 +#elif defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(2) +#define PLATFORM_CLUSTER0_CORE_COUNT U(4) +#define PLATFORM_CLUSTER1_CORE_COUNT U(2) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_RK_CLST_TO_CPUID_SHIFT 6 +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* + * 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 U(1) + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 20 +#define MAX_MMAP_REGIONS 25 + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Define GICD and GICC and GICR base + */ +#define PLAT_RK_GICD_BASE BASE_GICD_BASE +#define PLAT_RK_GICR_BASE BASE_GICR_BASE +#define PLAT_RK_GICC_BASE 0 + +#define PLAT_RK_UART_BASE UART2_BASE +#define PLAT_RK_UART_CLOCK RK3399_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE RK3399_BAUDRATE + +#define PLAT_RK_CCI_BASE CCI500_BASE + +#define PLAT_RK_PRIMARY_CPU 0x0 + +#define PSRAM_DO_DDR_RESUME 1 +#define PSRAM_CHECK_WAKEUP_CPU 0 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h new file mode 100644 index 0000000..84a31b2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ADDRESSMAP_SHARED_H +#define ADDRESSMAP_SHARED_H + +#define SIZE_K(n) ((n) * 1024) +#define SIZE_M(n) ((n) * 1024 * 1024) +#define SRAM_TEXT_LIMIT (4 * 1024) +#define SRAM_DATA_LIMIT (4 * 1024) +#define SRAM_BIN_LIMIT (4 * 1024) + +/* + * The parts of the shared defined registers address with AP and M0, + * let's note and mark the previous defines like this: + */ +#define GIC500_BASE (MMIO_BASE + 0x06E00000) +#define UART0_BASE (MMIO_BASE + 0x07180000) +#define UART1_BASE (MMIO_BASE + 0x07190000) +#define UART2_BASE (MMIO_BASE + 0x071A0000) +#define UART3_BASE (MMIO_BASE + 0x071B0000) + +#define PMU_BASE (MMIO_BASE + 0x07310000) +#define PMUGRF_BASE (MMIO_BASE + 0x07320000) +#define SGRF_BASE (MMIO_BASE + 0x07330000) +#define PMUSRAM_BASE (MMIO_BASE + 0x073B0000) +#define PWM_BASE (MMIO_BASE + 0x07420000) + +#define CIC_BASE (MMIO_BASE + 0x07620000) +#define PD_BUS0_BASE (MMIO_BASE + 0x07650000) +#define DCF_BASE (MMIO_BASE + 0x076A0000) +#define GPIO0_BASE (MMIO_BASE + 0x07720000) +#define GPIO1_BASE (MMIO_BASE + 0x07730000) +#define PMUCRU_BASE (MMIO_BASE + 0x07750000) +#define CRU_BASE (MMIO_BASE + 0x07760000) +#define GRF_BASE (MMIO_BASE + 0x07770000) +#define GPIO2_BASE (MMIO_BASE + 0x07780000) +#define GPIO3_BASE (MMIO_BASE + 0x07788000) +#define GPIO4_BASE (MMIO_BASE + 0x07790000) +#define WDT1_BASE (MMIO_BASE + 0x07840000) +#define WDT0_BASE (MMIO_BASE + 0x07848000) +#define TIMER_BASE (MMIO_BASE + 0x07850000) +#define STIME_BASE (MMIO_BASE + 0x07860000) +#define SRAM_BASE (MMIO_BASE + 0x078C0000) +#define SERVICE_NOC_0_BASE (MMIO_BASE + 0x07A50000) +#define DDRC0_BASE (MMIO_BASE + 0x07A80000) +#define SERVICE_NOC_1_BASE (MMIO_BASE + 0x07A84000) +#define DDRC1_BASE (MMIO_BASE + 0x07A88000) +#define SERVICE_NOC_2_BASE (MMIO_BASE + 0x07A8C000) +#define SERVICE_NOC_3_BASE (MMIO_BASE + 0x07A90000) +#define CCI500_BASE (MMIO_BASE + 0x07B00000) +#define COLD_BOOT_BASE (MMIO_BASE + 0x07FF0000) + +/* Registers size */ +#define GIC500_SIZE SIZE_M(2) +#define UART0_SIZE SIZE_K(64) +#define UART1_SIZE SIZE_K(64) +#define UART2_SIZE SIZE_K(64) +#define UART3_SIZE SIZE_K(64) +#define PMU_SIZE SIZE_K(64) +#define PMUGRF_SIZE SIZE_K(64) +#define SGRF_SIZE SIZE_K(64) +#define PMUSRAM_SIZE SIZE_K(64) +#define PMUSRAM_RSIZE SIZE_K(8) +#define PWM_SIZE SIZE_K(64) +#define CIC_SIZE SIZE_K(4) +#define DCF_SIZE SIZE_K(4) +#define GPIO0_SIZE SIZE_K(64) +#define GPIO1_SIZE SIZE_K(64) +#define PMUCRU_SIZE SIZE_K(64) +#define CRU_SIZE SIZE_K(64) +#define GRF_SIZE SIZE_K(64) +#define GPIO2_SIZE SIZE_K(32) +#define GPIO3_SIZE SIZE_K(32) +#define GPIO4_SIZE SIZE_K(32) +#define STIME_SIZE SIZE_K(64) +#define SRAM_SIZE SIZE_K(192) +#define SERVICE_NOC_0_SIZE SIZE_K(192) +#define DDRC0_SIZE SIZE_K(32) +#define SERVICE_NOC_1_SIZE SIZE_K(16) +#define DDRC1_SIZE SIZE_K(32) +#define SERVICE_NOC_2_SIZE SIZE_K(16) +#define SERVICE_NOC_3_SIZE SIZE_K(448) +#define CCI500_SIZE SIZE_M(1) +#define PD_BUS0_SIZE SIZE_K(448) + +/* DDR Registers address */ +#define CTL_BASE(ch) (DDRC0_BASE + (ch) * 0x8000) +#define CTL_REG(ch, n) (CTL_BASE(ch) + (n) * 0x4) + +#define PI_OFFSET 0x800 +#define PI_BASE(ch) (CTL_BASE(ch) + PI_OFFSET) +#define PI_REG(ch, n) (PI_BASE(ch) + (n) * 0x4) + +#define PHY_OFFSET 0x2000 +#define PHY_BASE(ch) (CTL_BASE(ch) + PHY_OFFSET) +#define PHY_REG(ch, n) (PHY_BASE(ch) + (n) * 0x4) + +#define MSCH_BASE(ch) (SERVICE_NOC_1_BASE + (ch) * 0x8000) + +#endif /* ADDRESSMAP_SHARED_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h new file mode 100644 index 0000000..6e7e8ba --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL31_PARAM_H +#define BL31_PARAM_H + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF text, ro, rw, Size: 1MB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x100000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted RAM + */ +#define BL31_BASE (TZRAM_BASE + 0x40000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +#endif /* BL31_PARAM_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h new file mode 100644 index 0000000..4d4ebf6 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRAM_REGS_H +#define DRAM_REGS_H + +#define CTL_REG_NUM 332 +#define PHY_REG_NUM 959 +#define PI_REG_NUM 200 + +#define MSCH_ID_COREID 0x0 +#define MSCH_ID_REVISIONID 0x4 +#define MSCH_DEVICECONF 0x8 +#define MSCH_DEVICESIZE 0xc +#define MSCH_DDRTIMINGA0 0x10 +#define MSCH_DDRTIMINGB0 0x14 +#define MSCH_DDRTIMINGC0 0x18 +#define MSCH_DEVTODEV0 0x1c +#define MSCH_DDRMODE 0x110 +#define MSCH_AGINGX0 0x1000 + +#define CIC_CTRL0 0x0 +#define CIC_CTRL1 0x4 +#define CIC_IDLE_TH 0x8 +#define CIC_CG_WAIT_TH 0xc +#define CIC_STATUS0 0x10 +#define CIC_STATUS1 0x14 +#define CIC_CTRL2 0x18 +#define CIC_CTRL3 0x1c +#define CIC_CTRL4 0x20 + +/* DENALI_CTL_00 */ +#define START 1 + +/* DENALI_CTL_68 */ +#define PWRUP_SREFRESH_EXIT (1 << 16) + +/* DENALI_CTL_274 */ +#define MEM_RST_VALID 1 + +#define PHY_DRV_ODT_Hi_Z 0x0 +#define PHY_DRV_ODT_240 0x1 +#define PHY_DRV_ODT_120 0x8 +#define PHY_DRV_ODT_80 0x9 +#define PHY_DRV_ODT_60 0xc +#define PHY_DRV_ODT_48 0xd +#define PHY_DRV_ODT_40 0xe +#define PHY_DRV_ODT_34_3 0xf + +/* + * sys_reg bitfield struct + * [31] row_3_4_ch1 + * [30] row_3_4_ch0 + * [29:28] chinfo + * [27] rank_ch1 + * [26:25] col_ch1 + * [24] bk_ch1 + * [23:22] cs0_row_ch1 + * [21:20] cs1_row_ch1 + * [19:18] bw_ch1 + * [17:16] dbw_ch1; + * [15:13] ddrtype + * [12] channelnum + * [11] rank_ch0 + * [10:9] col_ch0 + * [8] bk_ch0 + * [7:6] cs0_row_ch0 + * [5:4] cs1_row_ch0 + * [3:2] bw_ch0 + * [1:0] dbw_ch0 + */ +#define SYS_REG_ENC_ROW_3_4(n, ch) ((n) << (30 + (ch))) +#define SYS_REG_DEC_ROW_3_4(n, ch) (((n) >> (30 + (ch))) & 0x1) +#define SYS_REG_ENC_CHINFO(ch) (1 << (28 + (ch))) +#define SYS_REG_DEC_CHINFO(n, ch) (((n) >> (28 + (ch))) & 0x1) +#define SYS_REG_ENC_DDRTYPE(n) ((n) << 13) +#define SYS_REG_DEC_DDRTYPE(n) (((n) >> 13) & 0x7) +#define SYS_REG_ENC_NUM_CH(n) (((n) - 1) << 12) +#define SYS_REG_DEC_NUM_CH(n) (1 + (((n) >> 12) & 0x1)) +#define SYS_REG_ENC_RANK(n, ch) (((n) - 1) << (11 + (ch) * 16)) +#define SYS_REG_DEC_RANK(n, ch) (1 + (((n) >> (11 + (ch) * 16)) & 0x1)) +#define SYS_REG_ENC_COL(n, ch) (((n) - 9) << (9 + (ch) * 16)) +#define SYS_REG_DEC_COL(n, ch) (9 + (((n) >> (9 + (ch) * 16)) & 0x3)) +#define SYS_REG_ENC_BK(n, ch) (((n) == 3 ? 0 : 1) << (8 + (ch) * 16)) +#define SYS_REG_DEC_BK(n, ch) (3 - (((n) >> (8 + (ch) * 16)) & 0x1)) +#define SYS_REG_ENC_CS0_ROW(n, ch) (((n) - 13) << (6 + (ch) * 16)) +#define SYS_REG_DEC_CS0_ROW(n, ch) (13 + (((n) >> (6 + (ch) * 16)) & 0x3)) +#define SYS_REG_ENC_CS1_ROW(n, ch) (((n) - 13) << (4 + (ch) * 16)) +#define SYS_REG_DEC_CS1_ROW(n, ch) (13 + (((n) >> (4 + (ch) * 16)) & 0x3)) +#define SYS_REG_ENC_BW(n, ch) ((2 >> (n)) << (2 + (ch) * 16)) +#define SYS_REG_DEC_BW(n, ch) (2 >> (((n) >> (2 + (ch) * 16)) & 0x3)) +#define SYS_REG_ENC_DBW(n, ch) ((2 >> (n)) << (0 + (ch) * 16)) +#define SYS_REG_DEC_DBW(n, ch) (2 >> (((n) >> (0 + (ch) * 16)) & 0x3)) +#define DDR_STRIDE(n) mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(4), \ + (0x1f<<(10+16))|((n)<<10)) + +#endif /* DRAM_REGS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h new file mode 100644 index 0000000..a5311c9 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef M0_PARAM_H +#define M0_PARAM_H + +#define PARAM_ADDR 0xc0 + +#define PARAM_M0_FUNC 0x00 +#define PARAM_DRAM_FREQ 0x04 +#define PARAM_DPLL_CON0 0x08 +#define PARAM_DPLL_CON1 0x0c +#define PARAM_DPLL_CON2 0x10 +#define PARAM_DPLL_CON3 0x14 +#define PARAM_DPLL_CON4 0x18 +#define PARAM_DPLL_CON5 0x1c +#define PARAM_FREQ_SELECT 0x20 +#define PARAM_M0_DONE 0x24 +#define PARAM_M0_SIZE 0x28 +#define M0_DONE_FLAG 0xf59ec39a + +#endif /* M0_PARAM_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h new file mode 100644 index 0000000..0160453 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MISC_REGS_H +#define MISC_REGS_H + +/* CRU */ +#define CRU_DPLL_CON0 0x40 +#define CRU_DPLL_CON1 0x44 +#define CRU_DPLL_CON2 0x48 +#define CRU_DPLL_CON3 0x4c +#define CRU_DPLL_CON4 0x50 +#define CRU_DPLL_CON5 0x54 + +/* CRU_PLL_CON3 */ +#define PLL_SLOW_MODE 0 +#define PLL_NORMAL_MODE 1 +#define PLL_MODE(n) ((0x3 << (8 + 16)) | ((n) << 8)) +#define PLL_POWER_DOWN(n) ((0x1 << (0 + 16)) | ((n) << 0)) + +/* PMU CRU */ +#define PMU_CRU_GATEDIS_CON0 0x130 + +#endif /* MISC_REGS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h new file mode 100644 index 0000000..2968d5b --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h @@ -0,0 +1,697 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_BITS_H +#define PMU_BITS_H + +enum pmu_powerdomain_id { + PD_CPUL0 = 0, + PD_CPUL1, + PD_CPUL2, + PD_CPUL3, + PD_CPUB0, + PD_CPUB1, + PD_SCUL, + PD_SCUB, + PD_TCPD0, + PD_TCPD1, + PD_CCI, + PD_PERILP, + PD_PERIHP, + PD_CENTER, + PD_VIO, + PD_GPU, + PD_VCODEC, + PD_VDU, + PD_RGA, + PD_IEP, + PD_VO, + PD_ISP0 = 22, + PD_ISP1, + PD_HDCP, + PD_GMAC, + PD_EMMC, + PD_USB3, + PD_EDP, + PD_GIC, + PD_SD, + PD_SDIOAUDIO, + PD_END +}; + +enum powerdomain_state { + PMU_POWER_ON = 0, + PMU_POWER_OFF, +}; + +enum pmu_bus_id { + BUS_ID_GPU = 0, + BUS_ID_PERILP, + BUS_ID_PERIHP, + BUS_ID_VCODEC, + BUS_ID_VDU, + BUS_ID_RGA, + BUS_ID_IEP, + BUS_ID_VOPB, + BUS_ID_VOPL, + BUS_ID_ISP0, + BUS_ID_ISP1, + BUS_ID_HDCP, + BUS_ID_USB3, + BUS_ID_PERILPM0, + BUS_ID_CENTER, + BUS_ID_CCIM0, + BUS_ID_CCIM1, + BUS_ID_VIO, + BUS_ID_MSCH0, + BUS_ID_MSCH1, + BUS_ID_ALIVE, + BUS_ID_PMU, + BUS_ID_EDP, + BUS_ID_GMAC, + BUS_ID_EMMC, + BUS_ID_CENTER1, + BUS_ID_PMUM0, + BUS_ID_GIC, + BUS_ID_SD, + BUS_ID_SDIOAUDIO, +}; + +enum pmu_bus_state { + BUS_ACTIVE, + BUS_IDLE, +}; + +/* pmu_cpuapm bit */ +enum pmu_cores_pm_by_wfi { + core_pm_en = 0, + core_pm_int_wakeup_en, + core_pm_resv, + core_pm_sft_wakeup_en +}; + +enum pmu_wkup_cfg0 { + PMU_GPIO0A_POSE_WKUP_EN = 0, + PMU_GPIO0B_POSE_WKUP_EN = 8, + PMU_GPIO0C_POSE_WKUP_EN = 16, + PMU_GPIO0D_POSE_WKUP_EN = 24, +}; + +enum pmu_wkup_cfg1 { + PMU_GPIO0A_NEGEDGE_WKUP_EN = 0, + PMU_GPIO0B_NEGEDGE_WKUP_EN = 7, + PMU_GPIO0C_NEGEDGE_WKUP_EN = 16, + PMU_GPIO0D_NEGEDGE_WKUP_EN = 24, +}; + +enum pmu_wkup_cfg2 { + PMU_GPIO1A_POSE_WKUP_EN = 0, + PMU_GPIO1B_POSE_WKUP_EN = 7, + PMU_GPIO1C_POSE_WKUP_EN = 16, + PMU_GPIO1D_POSE_WKUP_EN = 24, +}; + +enum pmu_wkup_cfg3 { + PMU_GPIO1A_NEGEDGE_WKUP_EN = 0, + PMU_GPIO1B_NEGEDGE_WKUP_EN = 7, + PMU_GPIO1C_NEGEDGE_WKUP_EN = 16, + PMU_GPIO1D_NEGEDGE_WKUP_EN = 24, +}; + +/* pmu_wkup_cfg4 */ +enum pmu_wkup_cfg4 { + PMU_CLUSTER_L_WKUP_EN = 0, + PMU_CLUSTER_B_WKUP_EN, + PMU_GPIO_WKUP_EN, + PMU_SDIO_WKUP_EN, + + PMU_SDMMC_WKUP_EN, + PMU_TIMER_WKUP_EN = 6, + PMU_USBDEV_WKUP_EN, + + PMU_SFT_WKUP_EN, + PMU_M0_WDT_WKUP_EN, + PMU_TIMEOUT_WKUP_EN, + PMU_PWM_WKUP_EN, + + PMU_PCIE_WKUP_EN = 13, +}; + +enum pmu_pwrdn_con { + PMU_A53_L0_PWRDWN_EN = 0, + PMU_A53_L1_PWRDWN_EN, + PMU_A53_L2_PWRDWN_EN, + PMU_A53_L3_PWRDWN_EN, + + PMU_A72_B0_PWRDWN_EN, + PMU_A72_B1_PWRDWN_EN, + PMU_SCU_L_PWRDWN_EN, + PMU_SCU_B_PWRDWN_EN, + + PMU_TCPD0_PWRDWN_EN, + PMU_TCPD1_PWRDWN_EN, + PMU_CCI_PWRDWN_EN, + PMU_PERILP_PWRDWN_EN, + + PMU_PERIHP_PWRDWN_EN, + PMU_CENTER_PWRDWN_EN, + PMU_VIO_PWRDWN_EN, + PMU_GPU_PWRDWN_EN, + + PMU_VCODEC_PWRDWN_EN, + PMU_VDU_PWRDWN_EN, + PMU_RGA_PWRDWN_EN, + PMU_IEP_PWRDWN_EN, + + PMU_VO_PWRDWN_EN, + PMU_ISP0_PWRDWN_EN = 22, + PMU_ISP1_PWRDWN_EN, + + PMU_HDCP_PWRDWN_EN, + PMU_GMAC_PWRDWN_EN, + PMU_EMMC_PWRDWN_EN, + PMU_USB3_PWRDWN_EN, + + PMU_EDP_PWRDWN_EN, + PMU_GIC_PWRDWN_EN, + PMU_SD_PWRDWN_EN, + PMU_SDIOAUDIO_PWRDWN_EN, +}; + +enum pmu_pwrdn_st { + PMU_A53_L0_PWRDWN_ST = 0, + PMU_A53_L1_PWRDWN_ST, + PMU_A53_L2_PWRDWN_ST, + PMU_A53_L3_PWRDWN_ST, + + PMU_A72_B0_PWRDWN_ST, + PMU_A72_B1_PWRDWN_ST, + PMU_SCU_L_PWRDWN_ST, + PMU_SCU_B_PWRDWN_ST, + + PMU_TCPD0_PWRDWN_ST, + PMU_TCPD1_PWRDWN_ST, + PMU_CCI_PWRDWN_ST, + PMU_PERILP_PWRDWN_ST, + + PMU_PERIHP_PWRDWN_ST, + PMU_CENTER_PWRDWN_ST, + PMU_VIO_PWRDWN_ST, + PMU_GPU_PWRDWN_ST, + + PMU_VCODEC_PWRDWN_ST, + PMU_VDU_PWRDWN_ST, + PMU_RGA_PWRDWN_ST, + PMU_IEP_PWRDWN_ST, + + PMU_VO_PWRDWN_ST, + PMU_ISP0_PWRDWN_ST = 22, + PMU_ISP1_PWRDWN_ST, + + PMU_HDCP_PWRDWN_ST, + PMU_GMAC_PWRDWN_ST, + PMU_EMMC_PWRDWN_ST, + PMU_USB3_PWRDWN_ST, + + PMU_EDP_PWRDWN_ST, + PMU_GIC_PWRDWN_ST, + PMU_SD_PWRDWN_ST, + PMU_SDIOAUDIO_PWRDWN_ST, + +}; + +enum pmu_pll_con { + PMU_PLL_PD_CFG = 0, + PMU_SFT_PLL_PD = 8, +}; + +enum pmu_pwermode_con { + PMU_PWR_MODE_EN = 0, + PMU_WKUP_RST_EN, + PMU_INPUT_CLAMP_EN, + PMU_OSC_DIS, + + PMU_ALIVE_USE_LF, + PMU_PMU_USE_LF, + PMU_POWER_OFF_REQ_CFG, + PMU_CHIP_PD_EN, + + PMU_PLL_PD_EN, + PMU_CPU0_PD_EN, + PMU_L2_FLUSH_EN, + PMU_L2_IDLE_EN, + + PMU_SCU_PD_EN, + PMU_CCI_PD_EN, + PMU_PERILP_PD_EN, + PMU_CENTER_PD_EN, + + PMU_SREF0_ENTER_EN, + PMU_DDRC0_GATING_EN, + PMU_DDRIO0_RET_EN, + PMU_DDRIO0_RET_DE_REQ, + + PMU_SREF1_ENTER_EN, + PMU_DDRC1_GATING_EN, + PMU_DDRIO1_RET_EN, + PMU_DDRIO1_RET_DE_REQ, + + PMU_CLK_CENTER_SRC_GATE_EN = 26, + PMU_CLK_PERILP_SRC_GATE_EN, + + PMU_CLK_CORE_SRC_GATE_EN, + PMU_DDRIO_RET_HW_DE_REQ, + PMU_SLP_OUTPUT_CFG, + PMU_MAIN_CLUSTER, +}; + +enum pmu_sft_con { + PMU_WKUP_SFT = 0, + PMU_INPUT_CLAMP_CFG, + PMU_OSC_DIS_CFG, + PMU_PMU_LF_EN_CFG, + + PMU_ALIVE_LF_EN_CFG, + PMU_24M_EN_CFG, + PMU_DBG_PWRUP_L0_CFG, + PMU_WKUP_SFT_M0, + + PMU_DDRCTL0_C_SYSREQ_CFG, + PMU_DDR0_IO_RET_CFG, + + PMU_DDRCTL1_C_SYSREQ_CFG = 12, + PMU_DDR1_IO_RET_CFG, + DBG_PWRUP_B0_CFG = 15, + + DBG_NOPWERDWN_L0_EN, + DBG_NOPWERDWN_L1_EN, + DBG_NOPWERDWN_L2_EN, + DBG_NOPWERDWN_L3_EN, + + DBG_PWRUP_REQ_L_EN = 20, + CLUSTER_L_CLK_SRC_GATING_CFG, + L2_FLUSH_REQ_CLUSTER_L, + ACINACTM_CLUSTER_L_CFG, + + DBG_NO_PWERDWN_B0_EN, + DBG_NO_PWERDWN_B1_EN, + + DBG_PWRUP_REQ_B_EN = 28, + CLUSTER_B_CLK_SRC_GATING_CFG, + L2_FLUSH_REQ_CLUSTER_B, + ACINACTM_CLUSTER_B_CFG, +}; + +enum pmu_int_con { + PMU_PMU_INT_EN = 0, + PMU_PWRMD_WKUP_INT_EN, + PMU_WKUP_GPIO0_NEG_INT_EN, + PMU_WKUP_GPIO0_POS_INT_EN, + PMU_WKUP_GPIO1_NEG_INT_EN, + PMU_WKUP_GPIO1_POS_INT_EN, +}; + +enum pmu_int_st { + PMU_PWRMD_WKUP_INT_ST = 1, + PMU_WKUP_GPIO0_NEG_INT_ST, + PMU_WKUP_GPIO0_POS_INT_ST, + PMU_WKUP_GPIO1_NEG_INT_ST, + PMU_WKUP_GPIO1_POS_INT_ST, +}; + +enum pmu_gpio0_pos_int_con { + PMU_GPIO0A_POS_INT_EN = 0, + PMU_GPIO0B_POS_INT_EN = 8, + PMU_GPIO0C_POS_INT_EN = 16, + PMU_GPIO0D_POS_INT_EN = 24, +}; + +enum pmu_gpio0_neg_int_con { + PMU_GPIO0A_NEG_INT_EN = 0, + PMU_GPIO0B_NEG_INT_EN = 8, + PMU_GPIO0C_NEG_INT_EN = 16, + PMU_GPIO0D_NEG_INT_EN = 24, +}; + +enum pmu_gpio1_pos_int_con { + PMU_GPIO1A_POS_INT_EN = 0, + PMU_GPIO1B_POS_INT_EN = 8, + PMU_GPIO1C_POS_INT_EN = 16, + PMU_GPIO1D_POS_INT_EN = 24, +}; + +enum pmu_gpio1_neg_int_con { + PMU_GPIO1A_NEG_INT_EN = 0, + PMU_GPIO1B_NEG_INT_EN = 8, + PMU_GPIO1C_NEG_INT_EN = 16, + PMU_GPIO1D_NEG_INT_EN = 24, +}; + +enum pmu_gpio0_pos_int_st { + PMU_GPIO0A_POS_INT_ST = 0, + PMU_GPIO0B_POS_INT_ST = 8, + PMU_GPIO0C_POS_INT_ST = 16, + PMU_GPIO0D_POS_INT_ST = 24, +}; + +enum pmu_gpio0_neg_int_st { + PMU_GPIO0A_NEG_INT_ST = 0, + PMU_GPIO0B_NEG_INT_ST = 8, + PMU_GPIO0C_NEG_INT_ST = 16, + PMU_GPIO0D_NEG_INT_ST = 24, +}; + +enum pmu_gpio1_pos_int_st { + PMU_GPIO1A_POS_INT_ST = 0, + PMU_GPIO1B_POS_INT_ST = 8, + PMU_GPIO1C_POS_INT_ST = 16, + PMU_GPIO1D_POS_INT_ST = 24, +}; + +enum pmu_gpio1_neg_int_st { + PMU_GPIO1A_NEG_INT_ST = 0, + PMU_GPIO1B_NEG_INT_ST = 8, + PMU_GPIO1C_NEG_INT_ST = 16, + PMU_GPIO1D_NEG_INT_ST = 24, +}; + +/* pmu power down configure register 0x0050 */ +enum pmu_pwrdn_inten { + PMU_A53_L0_PWR_SWITCH_INT_EN = 0, + PMU_A53_L1_PWR_SWITCH_INT_EN, + PMU_A53_L2_PWR_SWITCH_INT_EN, + PMU_A53_L3_PWR_SWITCH_INT_EN, + + PMU_A72_B0_PWR_SWITCH_INT_EN, + PMU_A72_B1_PWR_SWITCH_INT_EN, + PMU_SCU_L_PWR_SWITCH_INT_EN, + PMU_SCU_B_PWR_SWITCH_INT_EN, + + PMU_TCPD0_PWR_SWITCH_INT_EN, + PMU_TCPD1_PWR_SWITCH_INT_EN, + PMU_CCI_PWR_SWITCH_INT_EN, + PMU_PERILP_PWR_SWITCH_INT_EN, + + PMU_PERIHP_PWR_SWITCH_INT_EN, + PMU_CENTER_PWR_SWITCH_INT_EN, + PMU_VIO_PWR_SWITCH_INT_EN, + PMU_GPU_PWR_SWITCH_INT_EN, + + PMU_VCODEC_PWR_SWITCH_INT_EN, + PMU_VDU_PWR_SWITCH_INT_EN, + PMU_RGA_PWR_SWITCH_INT_EN, + PMU_IEP_PWR_SWITCH_INT_EN, + + PMU_VO_PWR_SWITCH_INT_EN, + PMU_ISP0_PWR_SWITCH_INT_EN = 22, + PMU_ISP1_PWR_SWITCH_INT_EN, + + PMU_HDCP_PWR_SWITCH_INT_EN, + PMU_GMAC_PWR_SWITCH_INT_EN, + PMU_EMMC_PWR_SWITCH_INT_EN, + PMU_USB3_PWR_SWITCH_INT_EN, + + PMU_EDP_PWR_SWITCH_INT_EN, + PMU_GIC_PWR_SWITCH_INT_EN, + PMU_SD_PWR_SWITCH_INT_EN, + PMU_SDIOAUDIO_PWR_SWITCH_INT_EN, +}; + +enum pmu_wkup_status { + PMU_WKUP_BY_CLSTER_L_INT = 0, + PMU_WKUP_BY_CLSTER_b_INT, + PMU_WKUP_BY_GPIO_INT, + PMU_WKUP_BY_SDIO_DET, + + PMU_WKUP_BY_SDMMC_DET, + PMU_WKUP_BY_TIMER = 6, + PMU_WKUP_BY_USBDEV_DET, + + PMU_WKUP_BY_M0_SFT, + PMU_WKUP_BY_M0_WDT_INT, + PMU_WKUP_BY_TIMEOUT, + PMU_WKUP_BY_PWM, + + PMU_WKUP_BY_PCIE = 13, +}; + +enum pmu_bus_clr { + PMU_CLR_GPU = 0, + PMU_CLR_PERILP, + PMU_CLR_PERIHP, + PMU_CLR_VCODEC, + + PMU_CLR_VDU, + PMU_CLR_RGA, + PMU_CLR_IEP, + PMU_CLR_VOPB, + + PMU_CLR_VOPL, + PMU_CLR_ISP0, + PMU_CLR_ISP1, + PMU_CLR_HDCP, + + PMU_CLR_USB3, + PMU_CLR_PERILPM0, + PMU_CLR_CENTER, + PMU_CLR_CCIM1, + + PMU_CLR_CCIM0, + PMU_CLR_VIO, + PMU_CLR_MSCH0, + PMU_CLR_MSCH1, + + PMU_CLR_ALIVE, + PMU_CLR_PMU, + PMU_CLR_EDP, + PMU_CLR_GMAC, + + PMU_CLR_EMMC, + PMU_CLR_CENTER1, + PMU_CLR_PMUM0, + PMU_CLR_GIC, + + PMU_CLR_SD, + PMU_CLR_SDIOAUDIO, +}; + +/* PMU bus idle request register */ +enum pmu_bus_idle_req { + PMU_IDLE_REQ_GPU = 0, + PMU_IDLE_REQ_PERILP, + PMU_IDLE_REQ_PERIHP, + PMU_IDLE_REQ_VCODEC, + + PMU_IDLE_REQ_VDU, + PMU_IDLE_REQ_RGA, + PMU_IDLE_REQ_IEP, + PMU_IDLE_REQ_VOPB, + + PMU_IDLE_REQ_VOPL, + PMU_IDLE_REQ_ISP0, + PMU_IDLE_REQ_ISP1, + PMU_IDLE_REQ_HDCP, + + PMU_IDLE_REQ_USB3, + PMU_IDLE_REQ_PERILPM0, + PMU_IDLE_REQ_CENTER, + PMU_IDLE_REQ_CCIM0, + + PMU_IDLE_REQ_CCIM1, + PMU_IDLE_REQ_VIO, + PMU_IDLE_REQ_MSCH0, + PMU_IDLE_REQ_MSCH1, + + PMU_IDLE_REQ_ALIVE, + PMU_IDLE_REQ_PMU, + PMU_IDLE_REQ_EDP, + PMU_IDLE_REQ_GMAC, + + PMU_IDLE_REQ_EMMC, + PMU_IDLE_REQ_CENTER1, + PMU_IDLE_REQ_PMUM0, + PMU_IDLE_REQ_GIC, + + PMU_IDLE_REQ_SD, + PMU_IDLE_REQ_SDIOAUDIO, +}; + +/* pmu bus idle status register */ +enum pmu_bus_idle_st { + PMU_IDLE_ST_GPU = 0, + PMU_IDLE_ST_PERILP, + PMU_IDLE_ST_PERIHP, + PMU_IDLE_ST_VCODEC, + + PMU_IDLE_ST_VDU, + PMU_IDLE_ST_RGA, + PMU_IDLE_ST_IEP, + PMU_IDLE_ST_VOPB, + + PMU_IDLE_ST_VOPL, + PMU_IDLE_ST_ISP0, + PMU_IDLE_ST_ISP1, + PMU_IDLE_ST_HDCP, + + PMU_IDLE_ST_USB3, + PMU_IDLE_ST_PERILPM0, + PMU_IDLE_ST_CENTER, + PMU_IDLE_ST_CCIM0, + + PMU_IDLE_ST_CCIM1, + PMU_IDLE_ST_VIO, + PMU_IDLE_ST_MSCH0, + PMU_IDLE_ST_MSCH1, + + PMU_IDLE_ST_ALIVE, + PMU_IDLE_ST_PMU, + PMU_IDLE_ST_EDP, + PMU_IDLE_ST_GMAC, + + PMU_IDLE_ST_EMMC, + PMU_IDLE_ST_CENTER1, + PMU_IDLE_ST_PMUM0, + PMU_IDLE_ST_GIC, + + PMU_IDLE_ST_SD, + PMU_IDLE_ST_SDIOAUDIO, +}; + +enum pmu_bus_idle_ack { + PMU_IDLE_ACK_GPU = 0, + PMU_IDLE_ACK_PERILP, + PMU_IDLE_ACK_PERIHP, + PMU_IDLE_ACK_VCODEC, + + PMU_IDLE_ACK_VDU, + PMU_IDLE_ACK_RGA, + PMU_IDLE_ACK_IEP, + PMU_IDLE_ACK_VOPB, + + PMU_IDLE_ACK_VOPL, + PMU_IDLE_ACK_ISP0, + PMU_IDLE_ACK_ISP1, + PMU_IDLE_ACK_HDCP, + + PMU_IDLE_ACK_USB3, + PMU_IDLE_ACK_PERILPM0, + PMU_IDLE_ACK_CENTER, + PMU_IDLE_ACK_CCIM0, + + PMU_IDLE_ACK_CCIM1, + PMU_IDLE_ACK_VIO, + PMU_IDLE_ACK_MSCH0, + PMU_IDLE_ACK_MSCH1, + + PMU_IDLE_ACK_ALIVE, + PMU_IDLE_ACK_PMU, + PMU_IDLE_ACK_EDP, + PMU_IDLE_ACK_GMAC, + + PMU_IDLE_ACK_EMMC, + PMU_IDLE_ACK_CENTER1, + PMU_IDLE_ACK_PMUM0, + PMU_IDLE_ACK_GIC, + + PMU_IDLE_ACK_SD, + PMU_IDLE_ACK_SDIOAUDIO, +}; + +enum pmu_cci500_con { + PMU_PREQ_CCI500_CFG_SW = 0, + PMU_CLR_PREQ_CCI500_HW, + PMU_PSTATE_CCI500_0, + PMU_PSTATE_CCI500_1, + + PMU_PSTATE_CCI500_2, + PMU_QREQ_CCI500_CFG_SW, + PMU_CLR_QREQ_CCI500_HW, + PMU_QGATING_CCI500_CFG, + + PMU_PREQ_CCI500_CFG_SW_WMSK = 16, + PMU_CLR_PREQ_CCI500_HW_WMSK, + PMU_PSTATE_CCI500_0_WMSK, + PMU_PSTATE_CCI500_1_WMSK, + + PMU_PSTATE_CCI500_2_WMSK, + PMU_QREQ_CCI500_CFG_SW_WMSK, + PMU_CLR_QREQ_CCI500_HW_WMSK, + PMU_QGATING_CCI500_CFG_WMSK, +}; + +enum pmu_adb400_con { + PMU_PWRDWN_REQ_CXCS_SW = 0, + PMU_PWRDWN_REQ_CORE_L_SW, + PMU_PWRDWN_REQ_CORE_L_2GIC_SW, + PMU_PWRDWN_REQ_GIC2_CORE_L_SW, + + PMU_PWRDWN_REQ_CORE_B_SW, + PMU_PWRDWN_REQ_CORE_B_2GIC_SW, + PMU_PWRDWN_REQ_GIC2_CORE_B_SW, + + PMU_CLR_CXCS_HW = 8, + PMU_CLR_CORE_L_HW, + PMU_CLR_CORE_L_2GIC_HW, + PMU_CLR_GIC2_CORE_L_HW, + + PMU_CLR_CORE_B_HW, + PMU_CLR_CORE_B_2GIC_HW, + PMU_CLR_GIC2_CORE_B_HW, + + PMU_PWRDWN_REQ_CXCS_SW_WMSK = 16, + PMU_PWRDWN_REQ_CORE_L_SW_WMSK, + PMU_PWRDWN_REQ_CORE_L_2GIC_SW_WMSK, + PMU_PWRDWN_REQ_GIC2_CORE_L_SW_WMSK, + + PMU_PWRDWN_REQ_CORE_B_SW_WMSK, + PMU_PWRDWN_REQ_CORE_B_2GIC_SW_WMSK, + PMU_PWRDWN_REQ_GIC2_CORE_B_SW_WMSK, + + PMU_CLR_CXCS_HW_WMSK = 24, + PMU_CLR_CORE_L_HW_WMSK, + PMU_CLR_CORE_L_2GIC_HW_WMSK, + PMU_CLR_GIC2_CORE_L_HW_WMSK, + + PMU_CLR_CORE_B_HW_WMSK, + PMU_CLR_CORE_B_2GIC_HW_WMSK, + PMU_CLR_GIC2_CORE_B_HW_WMSK, +}; + +enum pmu_adb400_st { + PMU_PWRDWN_REQ_CXCS_SW_ST = 0, + PMU_PWRDWN_REQ_CORE_L_SW_ST, + PMU_PWRDWN_REQ_CORE_L_2GIC_SW_ST, + PMU_PWRDWN_REQ_GIC2_CORE_L_SW_ST, + + PMU_PWRDWN_REQ_CORE_B_SW_ST, + PMU_PWRDWN_REQ_CORE_B_2GIC_SW_ST, + PMU_PWRDWN_REQ_GIC2_CORE_B_SW_ST, + + PMU_CLR_CXCS_HW_ST = 8, + PMU_CLR_CORE_L_HW_ST, + PMU_CLR_CORE_L_2GIC_HW_ST, + PMU_CLR_GIC2_CORE_L_HW_ST, + + PMU_CLR_CORE_B_HW_ST, + PMU_CLR_CORE_B_2GIC_HW_ST, + PMU_CLR_GIC2_CORE_B_HW_ST, +}; + +enum pmu_pwrdn_con1 { + PMU_VD_SCU_L_PWRDN_EN = 0, + PMU_VD_SCU_B_PWRDN_EN, + PMU_VD_CENTER_PWRDN_EN, +}; + +enum pmu_core_pwr_st { + L2_FLUSHDONE_CLUSTER_L = 0, + STANDBY_BY_WFIL2_CLUSTER_L, + + L2_FLUSHDONE_CLUSTER_B = 10, + STANDBY_BY_WFIL2_CLUSTER_B, +}; + +#endif /* PMU_BITS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h new file mode 100644 index 0000000..43e785e --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_REGS_H +#define PMU_REGS_H + +#define PMU_WKUP_CFG0 0x00 +#define PMU_WKUP_CFG1 0x04 +#define PMU_WKUP_CFG2 0x08 +#define PMU_WKUP_CFG3 0x0c +#define PMU_WKUP_CFG4 0x10 +#define PMU_PWRDN_CON 0x14 +#define PMU_PWRDN_ST 0x18 +#define PMU_PLL_CON 0x1c +#define PMU_PWRMODE_CON 0x20 +#define PMU_SFT_CON 0x24 +#define PMU_INT_CON 0x28 +#define PMU_INT_ST 0x2c +#define PMU_GPIO0_POS_INT_CON 0x30 +#define PMU_GPIO0_NEG_INT_CON 0x34 +#define PMU_GPIO1_POS_INT_CON 0x38 +#define PMU_GPIO1_NEG_INT_CON 0x3c +#define PMU_GPIO0_POS_INT_ST 0x40 +#define PMU_GPIO0_NEG_INT_ST 0x44 +#define PMU_GPIO1_POS_INT_ST 0x48 +#define PMU_GPIO1_NEG_INT_ST 0x4c +#define PMU_PWRDN_INTEN 0x50 +#define PMU_PWRDN_STATUS 0x54 +#define PMU_WAKEUP_STATUS 0x58 +#define PMU_BUS_CLR 0x5c +#define PMU_BUS_IDLE_REQ 0x60 +#define PMU_BUS_IDLE_ST 0x64 +#define PMU_BUS_IDLE_ACK 0x68 +#define PMU_CCI500_CON 0x6c +#define PMU_ADB400_CON 0x70 +#define PMU_ADB400_ST 0x74 +#define PMU_POWER_ST 0x78 +#define PMU_CORE_PWR_ST 0x7c +#define PMU_OSC_CNT 0x80 +#define PMU_PLLLOCK_CNT 0x84 +#define PMU_PLLRST_CNT 0x88 +#define PMU_STABLE_CNT 0x8c +#define PMU_DDRIO_PWRON_CNT 0x90 +#define PMU_WAKEUP_RST_CLR_CNT 0x94 +#define PMU_DDR_SREF_ST 0x98 +#define PMU_SCU_L_PWRDN_CNT 0x9c +#define PMU_SCU_L_PWRUP_CNT 0xa0 +#define PMU_SCU_B_PWRDN_CNT 0xa4 +#define PMU_SCU_B_PWRUP_CNT 0xa8 +#define PMU_GPU_PWRDN_CNT 0xac +#define PMU_GPU_PWRUP_CNT 0xb0 +#define PMU_CENTER_PWRDN_CNT 0xb4 +#define PMU_CENTER_PWRUP_CNT 0xb8 +#define PMU_TIMEOUT_CNT 0xbc +#define PMU_CPU0APM_CON 0xc0 +#define PMU_CPU1APM_CON 0xc4 +#define PMU_CPU2APM_CON 0xc8 +#define PMU_CPU3APM_CON 0xcc +#define PMU_CPU0BPM_CON 0xd0 +#define PMU_CPU1BPM_CON 0xd4 +#define PMU_NOC_AUTO_ENA 0xd8 +#define PMU_PWRDN_CON1 0xdc + +#define PMUGRF_GPIO0A_IOMUX 0x00 +#define PMUGRF_GPIO1A_IOMUX 0x10 +#define PMUGRF_GPIO1C_IOMUX 0x18 + +#define PMUGRF_GPIO0A6_IOMUX_SHIFT 12 +#define PMUGRF_GPIO0A6_IOMUX_PWM 0x1 +#define PMUGRF_GPIO1C3_IOMUX_SHIFT 6 +#define PMUGRF_GPIO1C3_IOMUX_PWM 0x1 + +#define CPU_AXI_QOS_ID_COREID 0x00 +#define CPU_AXI_QOS_REVISIONID 0x04 +#define CPU_AXI_QOS_PRIORITY 0x08 +#define CPU_AXI_QOS_MODE 0x0c +#define CPU_AXI_QOS_BANDWIDTH 0x10 +#define CPU_AXI_QOS_SATURATION 0x14 +#define CPU_AXI_QOS_EXTCONTROL 0x18 +#define CPU_AXI_QOS_NUM_REGS 0x07 + +#define CPU_AXI_CCI_M0_QOS_BASE 0xffa50000 +#define CPU_AXI_CCI_M1_QOS_BASE 0xffad8000 +#define CPU_AXI_DMAC0_QOS_BASE 0xffa64200 +#define CPU_AXI_DMAC1_QOS_BASE 0xffa64280 +#define CPU_AXI_DCF_QOS_BASE 0xffa64180 +#define CPU_AXI_CRYPTO0_QOS_BASE 0xffa64100 +#define CPU_AXI_CRYPTO1_QOS_BASE 0xffa64080 +#define CPU_AXI_PMU_CM0_QOS_BASE 0xffa68000 +#define CPU_AXI_PERI_CM1_QOS_BASE 0xffa64300 +#define CPU_AXI_GIC_QOS_BASE 0xffa78000 +#define CPU_AXI_SDIO_QOS_BASE 0xffa76000 +#define CPU_AXI_SDMMC_QOS_BASE 0xffa74000 +#define CPU_AXI_EMMC_QOS_BASE 0xffa58000 +#define CPU_AXI_GMAC_QOS_BASE 0xffa5c000 +#define CPU_AXI_USB_OTG0_QOS_BASE 0xffa70000 +#define CPU_AXI_USB_OTG1_QOS_BASE 0xffa70080 +#define CPU_AXI_USB_HOST0_QOS_BASE 0xffa60100 +#define CPU_AXI_USB_HOST1_QOS_BASE 0xffa60180 +#define CPU_AXI_GPU_QOS_BASE 0xffae0000 +#define CPU_AXI_VIDEO_M0_QOS_BASE 0xffab8000 +#define CPU_AXI_VIDEO_M1_R_QOS_BASE 0xffac0000 +#define CPU_AXI_VIDEO_M1_W_QOS_BASE 0xffac0080 +#define CPU_AXI_RGA_R_QOS_BASE 0xffab0000 +#define CPU_AXI_RGA_W_QOS_BASE 0xffab0080 +#define CPU_AXI_IEP_QOS_BASE 0xffa98000 +#define CPU_AXI_VOP_BIG_R_QOS_BASE 0xffac8000 +#define CPU_AXI_VOP_BIG_W_QOS_BASE 0xffac8080 +#define CPU_AXI_VOP_LITTLE_QOS_BASE 0xffad0000 +#define CPU_AXI_ISP0_M0_QOS_BASE 0xffaa0000 +#define CPU_AXI_ISP0_M1_QOS_BASE 0xffaa0080 +#define CPU_AXI_ISP1_M0_QOS_BASE 0xffaa8000 +#define CPU_AXI_ISP1_M1_QOS_BASE 0xffaa8080 +#define CPU_AXI_HDCP_QOS_BASE 0xffa90000 +#define CPU_AXI_PERIHP_NSP_QOS_BASE 0xffad8080 +#define CPU_AXI_PERILP_NSP_QOS_BASE 0xffad8180 +#define CPU_AXI_PERILPSLV_NSP_QOS_BASE 0xffad8100 + +#define GRF_GPIO2A_IOMUX 0xe000 +#define GRF_GPIO2B_IOMUX 0xe004 +#define GRF_GPIO2C_IOMUX 0xe008 +#define GRF_GPIO2D_IOMUX 0xe00c +#define GRF_GPIO3A_IOMUX 0xe010 +#define GRF_GPIO3B_IOMUX 0xe014 +#define GRF_GPIO3C_IOMUX 0xe018 +#define GRF_GPIO3D_IOMUX 0xe01c +#define GRF_GPIO4A_IOMUX 0xe020 +#define GRF_GPIO4B_IOMUX 0xe024 +#define GRF_GPIO4C_IOMUX 0xe028 +#define GRF_GPIO4D_IOMUX 0xe02c + +#define GRF_GPIO2A_P 0xe040 +#define GRF_GPIO2B_P 0xe044 +#define GRF_GPIO2C_P 0xe048 +#define GRF_GPIO2D_P 0xe04C +#define GRF_GPIO3A_P 0xe050 +#define GRF_GPIO3B_P 0xe054 +#define GRF_GPIO3C_P 0xe058 +#define GRF_GPIO3D_P 0xe05C +#define GRF_GPIO4A_P 0xe060 +#define GRF_GPIO4B_P 0xe064 +#define GRF_GPIO4C_P 0xe068 +#define GRF_GPIO4D_P 0xe06C + +#endif /* PMU_REGS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c b/arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c new file mode 100644 index 0000000..ce8476c --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#define RK_SIP_DDR_CFG 0x82000008 +#define DRAM_INIT 0x00 +#define DRAM_SET_RATE 0x01 +#define DRAM_ROUND_RATE 0x02 +#define DRAM_SET_AT_SR 0x03 +#define DRAM_GET_BW 0x04 +#define DRAM_GET_RATE 0x05 +#define DRAM_CLR_IRQ 0x06 +#define DRAM_SET_PARAM 0x07 +#define DRAM_SET_ODT_PD 0x08 + +#define RK_SIP_HDCP_CONTROL 0x82000009 +#define RK_SIP_HDCP_KEY_DATA64 0xC200000A + +uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1, + uint64_t id, uint64_t arg2) +{ + switch (id) { + case DRAM_SET_RATE: + return ddr_set_rate((uint32_t)arg0); + case DRAM_ROUND_RATE: + return ddr_round_rate((uint32_t)arg0); + case DRAM_GET_RATE: + return ddr_get_rate(); + case DRAM_SET_ODT_PD: + dram_set_odt_pd(arg0, arg1, arg2); + break; + default: + break; + } + + return 0; +} + +uintptr_t rockchip_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) +{ +#ifdef PLAT_RK_DP_HDCP + uint64_t x5, x6; +#endif + + switch (smc_fid) { + case RK_SIP_DDR_CFG: + SMC_RET1(handle, ddr_smc_handler(x1, x2, x3, x4)); +#ifdef PLAT_RK_DP_HDCP + case RK_SIP_HDCP_CONTROL: + SMC_RET1(handle, dp_hdcp_ctrl(x1)); + case RK_SIP_HDCP_KEY_DATA64: + x5 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X5); + x6 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X6); + SMC_RET1(handle, dp_hdcp_store_key(x1, x2, x3, x4, x5, x6)); +#endif + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/platform.mk b/arm-trusted-firmware/plat/rockchip/rk3399/platform.mk new file mode 100644 index 0000000..aba67c2 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/platform.mk @@ -0,0 +1,113 @@ +# +# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +DISABLE_BIN_GENERATION := 1 + +PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/aarch64/ \ + -I${RK_PLAT_COMMON}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/pwm/ \ + -I${RK_PLAT_SOC}/drivers/secure/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/drivers/dram/ \ + -I${RK_PLAT_SOC}/drivers/dp/ \ + -I${RK_PLAT_SOC}/include/ \ + -I${RK_PLAT_SOC}/include/shared/ \ + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +RK_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + ${RK_PLAT}/common/rockchip_gicv3.c + +PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \ + lib/bl_aux_params/bl_aux_params.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + plat/common/aarch64/crash_console_helpers.S \ + plat/common/plat_psci_common.c + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + +BL31_SOURCES += ${RK_GIC_SOURCES} \ + drivers/arm/cci/cci.c \ + drivers/ti/uart/aarch64/16550_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/gpio/gpio.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ + ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/aarch64/platform_common.c \ + ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c \ + ${RK_PLAT_SOC}/drivers/gpio/rk3399_gpio.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c \ + ${RK_PLAT_SOC}/drivers/pmu/m0_ctl.c \ + ${RK_PLAT_SOC}/drivers/pwm/pwm.c \ + ${RK_PLAT_SOC}/drivers/secure/secure.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + ${RK_PLAT_SOC}/drivers/dram/dfs.c \ + ${RK_PLAT_SOC}/drivers/dram/dram.c \ + ${RK_PLAT_SOC}/drivers/dram/dram_spec_timing.c \ + ${RK_PLAT_SOC}/drivers/dram/suspend.c + +include lib/coreboot/coreboot.mk +include lib/libfdt/libfdt.mk + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_855873 := 1 + +# M0 source build +PLAT_M0 := ${PLAT}m0 +BUILD_M0 := ${BUILD_PLAT}/m0 + +RK3399M0FW=${BUILD_M0}/${PLAT_M0}.bin +$(eval $(call add_define_val,RK3399M0FW,\"$(RK3399M0FW)\")) + +RK3399M0PMUFW=${BUILD_M0}/${PLAT_M0}pmu.bin +$(eval $(call add_define_val,RK3399M0PMUFW,\"$(RK3399M0PMUFW)\")) + +ifdef PLAT_RK_DP_HDCP +BL31_SOURCES += ${RK_PLAT_SOC}/drivers/dp/cdn_dp.c + +HDCPFW=${RK_PLAT_SOC}/drivers/dp/hdcp.bin +$(eval $(call add_define_val,HDCPFW,\"$(HDCPFW)\")) + +${BUILD_PLAT}/bl31/cdn_dp.o: CCACHE_EXTRAFILES=$(HDCPFW) +${RK_PLAT_SOC}/drivers/dp/cdn_dp.c: $(HDCPFW) +endif + +# CCACHE_EXTRAFILES is needed because ccache doesn't handle .incbin +export CCACHE_EXTRAFILES +${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW):$(RK3399M0PMUFW) +${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c: $(RK3399M0FW) + +$(eval $(call MAKE_PREREQ_DIR,${BUILD_M0},${BUILD_PLAT})) +.PHONY: $(RK3399M0FW) +$(RK3399M0FW): | ${BUILD_M0} + $(MAKE) -C ${RK_PLAT_SOC}/drivers/m0 BUILD=$(abspath ${BUILD_PLAT}/m0) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h b/arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h new file mode 100644 index 0000000..ba83242 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RK3399_DEF_H +#define RK3399_DEF_H + +#include + +#define RK3399_PRIMARY_CPU 0x0 + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/************************************************************************** + * UART related constants + **************************************************************************/ +#define RK3399_BAUDRATE 115200 +#define RK3399_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000 + +/* Base rockchip_platform compatible GIC memory map */ +#define BASE_GICD_BASE (GIC500_BASE) +#define BASE_GICR_BASE (GIC500_BASE + SIZE_M(1)) + +/***************************************************************************** + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 0 +#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 1 + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#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 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_RK_GICV3_G1S_IRQS \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + INTR_GROUP1S, GIC_INTR_CFG_LEVEL) + +#define PLAT_RK_GICV3_G0_IRQS \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#endif /* RK3399_DEF_H */ diff --git a/arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..f045e21 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl plat_crash_console_flush + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl platform_mem_init + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_reset_handler + .globl plat_rpi3_calc_core_pos + .globl plat_secondary_cold_boot_setup + .globl plat_rpi_get_model + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * + * This function uses the plat_rpi3_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_rpi3_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); + * + * CorePos = (ClusterId * 4) + CoreId + * ----------------------------------------------------- + */ +func plat_rpi3_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_rpi3_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #RPI_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_wait_for_warm_boot (void); + * + * This function performs any platform specific actions + * needed for a CPU to be put into holding pen to wait + * for a warm boot request. + * The function will never return. + * ----------------------------------------------------- + */ +func plat_wait_for_warm_boot + /* + * Calculate address of our hold entry. + * As the function will never return, there is no need to save LR. + */ + bl plat_my_core_pos + lsl x0, x0, #3 + mov_imm x2, PLAT_RPI3_TM_HOLD_BASE + add x0, x0, x2 + /* + * This code runs way before requesting the warmboot of this core, + * so it is possible to clear the mailbox before getting a request + * to boot. + */ + mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT + str x1,[x0] + + /* Wait until we have a go */ +poll_mailbox: + wfe + ldr x1, [x0] + cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO + bne poll_mailbox + + /* Jump to the provided entrypoint */ + mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT + ldr x1, [x0] + br x1 +endfunc plat_wait_for_warm_boot + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + b plat_wait_for_warm_boot +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. + * + * This functions returns: + * - 0 for a cold boot. + * - Any other value for a warm boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + mov x1, x30 + bl plat_is_my_cpu_primary + /* + * Secondaries always cold boot. + */ + cbz w0, 1f + /* + * Primaries warm boot if they are requested + * to power off. + */ + mov_imm x0, PLAT_RPI3_TM_HOLD_BASE + ldr x0, [x0] + cmp x0, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF + adr x0, plat_wait_for_warm_boot + csel x0, x0, xzr, eq + ret x1 +1: mov x0, #0 + ret x1 +endfunc plat_get_my_entrypoint + + /* --------------------------------------------- + * void platform_mem_init (void); + * + * No need to carry out any memory initialization. + * --------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x3 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, PLAT_RPI_MINI_UART_BASE + mov x1, xzr + mov x2, xzr + b console_16550_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, PLAT_RPI_MINI_UART_BASE + b console_16550_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, PLAT_RPI_MINI_UART_BASE + b console_16550_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * int plat_rpi_get_model() + * Macro to determine whether we are running on + * a Raspberry Pi 3 or 4. Just checks the MIDR for + * being either a Cortex-A72 or a Cortex-A53. + * Out : return 4 if RPi4, 3 otherwise. + * Clobber list : x0 + * --------------------------------------------- + */ + .macro _plat_rpi_get_model + mrs x0, midr_el1 + and x0, x0, #0xf0 /* Isolate low byte of part number */ + cmp w0, #0x80 /* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */ + mov w0, #3 + csinc w0, w0, w0, ne + .endm + + func plat_rpi_get_model + _plat_rpi_get_model + ret + endfunc plat_rpi_get_model + + /* --------------------------------------------- + * void plat_reset_handler(void); + * --------------------------------------------- + */ +func plat_reset_handler + /* L2 cache setup only needed on RPi4 */ + _plat_rpi_get_model + cmp w0, #4 + b.ne 1f + + /* ------------------------------------------------ + * Set L2 read/write cache latency: + * - L2 Data RAM latency: 3 cycles (0b010) + * - L2 Data RAM setup: 1 cycle (bit 5) + * ------------------------------------------------ + */ + mrs x0, CORTEX_A72_L2CTLR_EL1 + mov x1, #0x22 + orr x0, x0, x1 + msr CORTEX_A72_L2CTLR_EL1, x0 + isb + +1: + ret +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h b/arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h new file mode 100644 index 0000000..ddf239e --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI_SHARED_H +#define RPI_SHARED_H + +#include + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +/* Utility functions */ +void rpi3_console_init(void); +void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size, + uintptr_t code_start, uintptr_t code_limit, + uintptr_t rodata_start, uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, uintptr_t coh_limit +#endif + ); + +/* Optional functions required in the Raspberry Pi 3 port */ +unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); + +/* BL2 utility functions */ +uint32_t rpi3_get_spsr_for_bl32_entry(void); +uint32_t rpi3_get_spsr_for_bl33_entry(void); + +/* IO storage utility functions */ +void plat_rpi3_io_setup(void); + +/* VideoCore firmware commands */ +int rpi3_vc_hardware_get_board_revision(uint32_t *revision); + +int plat_rpi_get_model(void); + +#endif /* RPI3_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/rpi/common/rpi3_common.c b/arm-trusted-firmware/plat/rpi/common/rpi3_common.c new file mode 100644 index 0000000..ef88bf1 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_common.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2015-2019, 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 + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef SHARED_RAM_BASE +#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \ + SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#ifdef RPI3_PRELOADED_DTB_BASE +#define MAP_NS_DTB MAP_REGION_FLAT(RPI3_PRELOADED_DTB_BASE, 0x10000, \ + MT_MEMORY | MT_RW | MT_NS) +#endif + +#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_FIP MAP_REGION_FLAT(PLAT_RPI3_FIP_BASE, \ + PLAT_RPI3_FIP_MAX_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + +#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#ifdef SPD_opteed +#define MAP_OPTEE_PAGEABLE MAP_REGION_FLAT( \ + RPI3_OPTEE_PAGEABLE_LOAD_BASE, \ + RPI3_OPTEE_PAGEABLE_LOAD_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +/* + * Table of regions for various BL stages to map using the MMU. + */ +#ifdef IMAGE_BL1 +static const mmap_region_t plat_rpi3_mmap[] = { +#ifdef MAP_SHARED_RAM + MAP_SHARED_RAM, +#endif + MAP_DEVICE0, + MAP_FIP, +#ifdef SPD_opteed + MAP_OPTEE_PAGEABLE, +#endif + {0} +}; +#endif + +#ifdef IMAGE_BL2 +static const mmap_region_t plat_rpi3_mmap[] = { +#ifdef MAP_SHARED_RAM + MAP_SHARED_RAM, +#endif + MAP_DEVICE0, + MAP_FIP, + MAP_NS_DRAM0, +#ifdef BL32_BASE + MAP_BL32_MEM, +#endif + {0} +}; +#endif + +#ifdef IMAGE_BL31 +static const mmap_region_t plat_rpi3_mmap[] = { +#ifdef MAP_SHARED_RAM + MAP_SHARED_RAM, +#endif + MAP_DEVICE0, +#ifdef RPI3_PRELOADED_DTB_BASE + MAP_NS_DTB, +#endif +#ifdef BL32_BASE + MAP_BL32_MEM, +#endif + {0} +}; +#endif + +/******************************************************************************* + * Function that sets up the console + ******************************************************************************/ +static console_t rpi3_console; + + +static bool rpi3_use_mini_uart(void) +{ + return rpi3_gpio_get_select(14) == RPI3_GPIO_FUNC_ALT5; +} + +void rpi3_console_init(void) +{ + int console_scope = CONSOLE_FLAG_BOOT; + int rc; + + if (RPI3_RUNTIME_UART != -1) + console_scope |= CONSOLE_FLAG_RUNTIME; + + rpi3_gpio_init(); + + if (rpi3_use_mini_uart()) + rc = console_16550_register(PLAT_RPI_MINI_UART_BASE, + 0, + PLAT_RPI_UART_BAUDRATE, + &rpi3_console); + else + rc = console_pl011_register(PLAT_RPI_PL011_UART_BASE, + PLAT_RPI_PL011_UART_CLOCK, + PLAT_RPI_UART_BAUDRATE, + &rpi3_console); + + if (rc == 0) { + /* + * The crash console doesn't use the multi console API, it uses + * the core console functions directly. It is safe to call panic + * and let it print debug information. + */ + panic(); + } + + console_set_scope(&rpi3_console, console_scope); +} + +/******************************************************************************* + * Function that sets up the translation tables. + ******************************************************************************/ +void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size, + uintptr_t code_start, uintptr_t code_limit, + uintptr_t rodata_start, uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, uintptr_t coh_limit +#endif + ) +{ + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n", + (void *) total_base, (void *) (total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, + MT_MEMORY | MT_RW | MT_SECURE); + + /* Re-map the code section */ + VERBOSE("Code region: %p - %p\n", + (void *) code_start, (void *) code_limit); + mmap_add_region(code_start, code_start, + code_limit - code_start, + MT_CODE | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *) rodata_start, (void *) rodata_limit); + mmap_add_region(rodata_start, rodata_start, + rodata_limit - rodata_start, + MT_RO_DATA | MT_SECURE); + +#if USE_COHERENT_MEM + /* Re-map the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *) coh_start, (void *) coh_limit); + mmap_add_region(coh_start, coh_start, + coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + mmap_add(plat_rpi3_mmap); + + init_xlat_tables(); +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t rpi3_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +uint32_t rpi3_get_spsr_for_bl33_entry(void) +{ +#if RPI3_BL33_IN_AARCH32 + INFO("BL33 will boot in Non-secure AArch32 Hypervisor mode\n"); + return SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS); +#else + return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +#endif +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +uint32_t plat_ic_get_pending_interrupt_type(void) +{ + ERROR("rpi3: Interrupt routed to EL3.\n"); + return INTR_TYPE_INVAL; +} + +uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state) +{ + assert((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_EL3) || + (type == INTR_TYPE_NS)); + + assert(sec_state_is_valid(security_state)); + + /* Non-secure interrupts are signalled on the IRQ line always. */ + if (type == INTR_TYPE_NS) + return __builtin_ctz(SCR_IRQ_BIT); + + /* Secure interrupts are signalled on the FIQ line always. */ + return __builtin_ctz(SCR_FIQ_BIT); +} diff --git a/arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c b/arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c new file mode 100644 index 0000000..5394c6f --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c b/arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c new file mode 100644 index 0000000..49c6a76 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* Semihosting filenames */ +#define BL2_IMAGE_NAME "bl2.bin" +#define BL31_IMAGE_NAME "bl31.bin" +#define BL32_IMAGE_NAME "bl32.bin" +#define BL33_IMAGE_NAME "bl33.bin" + +#if TRUSTED_BOARD_BOOT +#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt" +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt" +#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt" +#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt" +#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt" +#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt" +#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt" +#endif /* TRUSTED_BOARD_BOOT */ + +/* IO devices */ +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *memmap_dev_con; +static uintptr_t memmap_dev_handle; + +static const io_block_spec_t fip_block_spec = { + .offset = PLAT_RPI3_FIP_BASE, + .length = PLAT_RPI3_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t tb_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FW_CERT, +}; + +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static int open_fip(const uintptr_t spec); +static int open_memmap(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, load images from the FIP */ +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + open_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + open_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + open_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +static int open_memmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Memmap\n"); + io_close(local_image_handle); + } + } + return result; +} + +void plat_rpi3_io_setup(void) +{ + int io_result; + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + assert(io_result == 0); + + io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &memmap_dev_handle); + assert(io_result == 0); + + /* Ignore improbable errors in release builds */ + (void)io_result; +} + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + + return result; +} diff --git a/arm-trusted-firmware/plat/rpi/common/rpi3_pm.c b/arm-trusted-firmware/plat/rpi/common/rpi3_pm.c new file mode 100644 index 0000000..86c61f7 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_pm.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RPI_HAVE_GIC +#include +#endif + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) + +#else + +#define rpi3_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 */ + +#define rpi3_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ + rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +static const unsigned int rpi3_pm_idle_states[] = { + /* State-id - 0x01 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, + MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0, +}; + +/******************************************************************************* + * Platform handler called to check the validity of the power state + * parameter. The power state parameter has to be a composite power state. + ******************************************************************************/ +static int rpi3_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + assert(req_state != 0); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; rpi3_pm_idle_states[i] != 0; i++) { + if (power_state == rpi3_pm_idle_states[i]) { + break; + } + } + + /* Return error if entry not found in the idle state array */ + if (!rpi3_pm_idle_states[i]) { + return PSCI_E_INVALID_PARAMS; + } + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + PLAT_LOCAL_PSTATE_MASK; + state_id >>= PLAT_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void rpi3_cpu_standby(plat_local_state_t cpu_state) +{ + assert(cpu_state == PLAT_LOCAL_STATE_RET); + + /* + * Enter standby state. + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); +} + +static void rpi3_pwr_domain_off(const psci_power_state_t *target_state) +{ +#ifdef RPI_HAVE_GIC + gicv2_cpuif_disable(); +#endif +} + +void __dead2 plat_secondary_cold_boot_setup(void); + +static void __dead2 +rpi3_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + disable_mmu_el3(); + plat_secondary_cold_boot_setup(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int rpi3_pwr_domain_on(u_register_t mpidr) +{ + int rc = PSCI_E_SUCCESS; + unsigned int pos = plat_core_pos_by_mpidr(mpidr); + uintptr_t hold_base = PLAT_RPI3_TM_HOLD_BASE; + + assert(pos < PLATFORM_CORE_COUNT); + + hold_base += pos * PLAT_RPI3_TM_HOLD_ENTRY_SIZE; + + mmio_write_64(hold_base, PLAT_RPI3_TM_HOLD_STATE_GO); + /* No cache maintenance here, hold_base is mapped as device memory. */ + + /* Make sure that the write has completed */ + dsb(); + isb(); + + sev(); + + return rc; +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +static void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + +#ifdef RPI_HAVE_GIC + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +#endif +} + +static void __dead2 rpi3_pwr_down_wfi( + const psci_power_state_t *target_state) +{ + uintptr_t hold_base = PLAT_RPI3_TM_HOLD_BASE; + unsigned int pos = plat_my_core_pos(); + + if (pos == 0) { + /* + * The secondaries will always be in a wait + * for warm boot on reset, but the BSP needs + * to be able to distinguish between waiting + * for warm boot (e.g. after psci_off, waiting + * for psci_on) and a cold boot. + */ + mmio_write_64(hold_base, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF); + /* No cache maintenance here, we run with caches off already. */ + dsb(); + isb(); + } + + write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT); + + while (1) + ; +} + +/******************************************************************************* + * Platform handlers for system reset and system off. + ******************************************************************************/ + +/* 10 ticks (Watchdog timer = Timer clock / 16) */ +#define RESET_TIMEOUT U(10) + +static void __dead2 rpi3_watchdog_reset(void) +{ + uint32_t rstc; + + console_flush(); + + dsbsy(); + isb(); + + mmio_write_32(RPI3_PM_BASE + RPI3_PM_WDOG_OFFSET, + RPI3_PM_PASSWORD | RESET_TIMEOUT); + + rstc = mmio_read_32(RPI3_PM_BASE + RPI3_PM_RSTC_OFFSET); + rstc &= ~RPI3_PM_RSTC_WRCFG_MASK; + rstc |= RPI3_PM_PASSWORD | RPI3_PM_RSTC_WRCFG_FULL_RESET; + mmio_write_32(RPI3_PM_BASE + RPI3_PM_RSTC_OFFSET, rstc); + + for (;;) { + wfi(); + } +} + +static void __dead2 rpi3_system_reset(void) +{ + INFO("rpi3: PSCI_SYSTEM_RESET: Invoking watchdog reset\n"); + + rpi3_watchdog_reset(); +} + +static void __dead2 rpi3_system_off(void) +{ + uint32_t rsts; + + INFO("rpi3: PSCI_SYSTEM_OFF: Invoking watchdog reset\n"); + + /* + * This function doesn't actually make the Raspberry Pi turn itself off, + * the hardware doesn't allow it. It simply reboots it and the RSTS + * value tells the bootcode.bin firmware not to continue the regular + * bootflow and to stay in a low power mode. + */ + + rsts = mmio_read_32(RPI3_PM_BASE + RPI3_PM_RSTS_OFFSET); + rsts |= RPI3_PM_PASSWORD | RPI3_PM_RSTS_WRCFG_HALT; + mmio_write_32(RPI3_PM_BASE + RPI3_PM_RSTS_OFFSET, rsts); + + rpi3_watchdog_reset(); +} + +/******************************************************************************* + * Platform handlers and setup function. + ******************************************************************************/ +static const plat_psci_ops_t plat_rpi3_psci_pm_ops = { + .cpu_standby = rpi3_cpu_standby, + .pwr_domain_off = rpi3_pwr_domain_off, + .pwr_domain_pwr_down_wfi = rpi3_pwr_domain_pwr_down_wfi, + .pwr_domain_on = rpi3_pwr_domain_on, + .pwr_domain_on_finish = rpi3_pwr_domain_on_finish, + .pwr_domain_pwr_down_wfi = rpi3_pwr_down_wfi, + .system_off = rpi3_system_off, + .system_reset = rpi3_system_reset, + .validate_power_state = rpi3_validate_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *entrypoint = (void *) PLAT_RPI3_TM_ENTRYPOINT; + + *entrypoint = sec_entrypoint; + *psci_ops = &plat_rpi3_psci_pm_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S b/arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S new file mode 100644 index 0000000..1c17b21 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global rpi3_rotpk_hash + .global rpi3_rotpk_hash_end +rpi3_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +rpi3_rotpk_hash_end: diff --git a/arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c b/arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c new file mode 100644 index 0000000..aae5fac --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +/* Get 128 bits of entropy and fuse the values together to form the canary. */ +#define TRNG_NBYTES 16U + +u_register_t plat_get_stack_protector_canary(void) +{ + size_t i; + u_register_t buf[TRNG_NBYTES / sizeof(u_register_t)]; + u_register_t ret = 0U; + + rpi3_rng_read(buf, sizeof(buf)); + + for (i = 0U; i < ARRAY_SIZE(buf); i++) + ret ^= buf[i]; + + return ret; +} diff --git a/arm-trusted-firmware/plat/rpi/common/rpi3_topology.c b/arm-trusted-firmware/plat/rpi/common/rpi3_topology.c new file mode 100644 index 0000000..3747287 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_topology.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the ARM default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) { + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return plat_rpi3_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c b/arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c new file mode 100644 index 0000000..f6c669f --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +extern char rpi3_rotpk_hash[], rpi3_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = rpi3_rotpk_hash; + *key_len = rpi3_rotpk_hash_end - rpi3_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 1; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c new file mode 100644 index 0000000..715aec4 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + + /* Fill BL31 related information */ + { + .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.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = RPI3_BL31_PLAT_PARAM_VAL, +#endif + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .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, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager + * image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged + * image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = RPI3_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = RPI3_OPTEE_PAGEABLE_LOAD_SIZE, +#endif + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = PLAT_RPI3_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_RPI3_NS_IMAGE_OFFSET, + .image_info.image_max_size = PLAT_RPI3_NS_IMAGE_MAX_SIZE, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S b/arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S new file mode 100644 index 0000000..c0c3967 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h b/arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h new file mode 100644 index 0000000..f44d1f5 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include + +#include "rpi_hw.h" + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978) + +#define PLATFORM_STACK_SIZE ULL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define RPI_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* + * Partition memory into secure ROM, non-secure DRAM, secure "SRAM", and + * secure DRAM. Note that this is all actually DRAM with different names, + * there is no Secure RAM in the Raspberry Pi 3. + */ +#if RPI3_USE_UEFI_MAP +#define SEC_ROM_BASE ULL(0x00000000) +#define SEC_ROM_SIZE ULL(0x00010000) + +/* FIP placed after ROM to append it to BL1 with very little padding. */ +#define PLAT_RPI3_FIP_BASE ULL(0x00020000) +#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x00010000) + +/* Reserve 2M of secure SRAM and DRAM, starting at 2M */ +#define SEC_SRAM_BASE ULL(0x00200000) +#define SEC_SRAM_SIZE ULL(0x00100000) + +#define SEC_DRAM0_BASE ULL(0x00300000) +#define SEC_DRAM0_SIZE ULL(0x00100000) + +/* Windows on ARM requires some RAM at 4M */ +#define NS_DRAM0_BASE ULL(0x00400000) +#define NS_DRAM0_SIZE ULL(0x00C00000) +#else +#define SEC_ROM_BASE ULL(0x00000000) +#define SEC_ROM_SIZE ULL(0x00020000) + +/* FIP placed after ROM to append it to BL1 with very little padding. */ +#define PLAT_RPI3_FIP_BASE ULL(0x00020000) +#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001E0000) + +/* We have 16M of memory reserved starting at 256M */ +#define SEC_SRAM_BASE ULL(0x10000000) +#define SEC_SRAM_SIZE ULL(0x00100000) + +#define SEC_DRAM0_BASE ULL(0x10100000) +#define SEC_DRAM0_SIZE ULL(0x00F00000) +/* End of reserved memory */ + +#define NS_DRAM0_BASE ULL(0x11000000) +#define NS_DRAM0_SIZE ULL(0x01000000) +#endif /* RPI3_USE_UEFI_MAP */ + +/* + * BL33 entrypoint. + */ +#define PLAT_RPI3_NS_IMAGE_OFFSET NS_DRAM0_BASE +#define PLAT_RPI3_NS_IMAGE_MAX_SIZE NS_DRAM0_SIZE + +/* + * I/O registers. + */ +#define DEVICE0_BASE RPI_IO_BASE +#define DEVICE0_SIZE RPI_IO_SIZE + +/* + * Arm TF lives in SRAM, partition it here + */ +#define SHARED_RAM_BASE SEC_SRAM_BASE +#define SHARED_RAM_SIZE ULL(0x00001000) + +#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE) +#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE) + +/* + * Mailbox to control the secondary cores.All secondary cores are held in a wait + * loop in cold boot. To release them perform the following steps (plus any + * additional barriers that may be needed): + * + * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT; + * *entrypoint = ADDRESS_TO_JUMP_TO; + * + * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE; + * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO; + * + * sev(); + */ +#define PLAT_RPI3_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE + +/* The secure entry point to be used on warm reset by all CPUs. */ +#define PLAT_RPI3_TM_ENTRYPOINT PLAT_RPI3_TRUSTED_MAILBOX_BASE +#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8) + +/* Hold entries for each CPU. */ +#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \ + PLAT_RPI3_TM_ENTRYPOINT_SIZE) +#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8) +#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \ + PLATFORM_CORE_COUNT) + +#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \ + PLAT_RPI3_TM_HOLD_SIZE) + +#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0) +#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1) +#define PLAT_RPI3_TM_HOLD_STATE_BSP_OFF ULL(2) + +/* + * BL1 specific defines. + * + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + * + * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using + * the current BL1 RW debug size plus a little space for growth. + */ +#define PLAT_MAX_BL1_RW_SIZE ULL(0x12000) + +#define BL1_RO_BASE SEC_ROM_BASE +#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE) +#define BL1_RW_BASE (BL1_RW_LIMIT - PLAT_MAX_BL1_RW_SIZE) +#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) + +/* + * BL2 specific defines. + * + * Put BL2 just below BL31. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define PLAT_MAX_BL2_SIZE ULL(0x2C000) + +#define BL2_BASE (BL2_LIMIT - PLAT_MAX_BL2_SIZE) +#define BL2_LIMIT BL31_BASE + +/* + * BL31 specific defines. + * + * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL31 debug size plus a little space for growth. + */ +#define PLAT_MAX_BL31_SIZE ULL(0x20000) + +#define BL31_BASE (BL31_LIMIT - PLAT_MAX_BL31_SIZE) +#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE + +/* + * BL32 specific defines. + * + * BL32 can execute from Secure SRAM or Secure DRAM. + */ +#define BL32_SRAM_BASE BL_RAM_BASE +#define BL32_SRAM_LIMIT BL31_BASE +#define BL32_DRAM_BASE SEC_DRAM0_BASE +#define BL32_DRAM_LIMIT (SEC_DRAM0_BASE + SEC_DRAM0_SIZE) + +#ifdef SPD_opteed +/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */ +#define RPI3_OPTEE_PAGEABLE_LOAD_SIZE 0x080000 /* 512KB */ +#define RPI3_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - \ + RPI3_OPTEE_PAGEABLE_LOAD_SIZE) +#endif + +#define SEC_SRAM_ID 0 +#define SEC_DRAM_ID 1 + +#if RPI3_BL32_RAM_LOCATION_ID == SEC_SRAM_ID +# define BL32_MEM_BASE BL_RAM_BASE +# define BL32_MEM_SIZE BL_RAM_SIZE +# define BL32_BASE BL32_SRAM_BASE +# define BL32_LIMIT BL32_SRAM_LIMIT +#elif RPI3_BL32_RAM_LOCATION_ID == SEC_DRAM_ID +# define BL32_MEM_BASE SEC_DRAM0_BASE +# define BL32_MEM_SIZE SEC_DRAM0_SIZE +# define BL32_BASE BL32_DRAM_BASE +# define BL32_LIMIT BL32_DRAM_LIMIT +#else +# error "Unsupported RPI3_BL32_RAM_LOCATION_ID value" +#endif +#define BL32_SIZE (BL32_LIMIT - BL32_BASE) + +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ + +/* + * Other memory-related defines. + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS 8 +#define MAX_XLAT_TABLES 4 + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +#define MAX_IO_BLOCK_DEVICES U(1) + +/* + * Serial-related constants. + */ +#define PLAT_RPI_MINI_UART_BASE RPI3_MINI_UART_BASE +#define PLAT_RPI_PL011_UART_BASE RPI3_PL011_UART_BASE +#define PLAT_RPI_PL011_UART_CLOCK RPI3_PL011_UART_CLOCK +#define PLAT_RPI_UART_BAUDRATE ULL(115200) + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS ULL(19200000) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h b/arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h new file mode 100644 index 0000000..2aecab3 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI_HW_H +#define RPI_HW_H + +#include + +/* + * Peripherals + */ + +#define RPI_IO_BASE ULL(0x3F000000) +#define RPI_IO_SIZE ULL(0x01000000) + +/* + * ARM <-> VideoCore mailboxes + */ +#define RPI3_MBOX_OFFSET ULL(0x0000B880) +#define RPI3_MBOX_BASE (RPI_IO_BASE + RPI3_MBOX_OFFSET) +/* VideoCore -> ARM */ +#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000) +#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010) +#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014) +#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018) +#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C) +/* ARM -> VideoCore */ +#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020) +#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030) +#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034) +#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038) +#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C) +/* Mailbox status constants */ +#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */ +#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */ + +/* + * Power management, reset controller, watchdog. + */ +#define RPI3_IO_PM_OFFSET ULL(0x00100000) +#define RPI3_PM_BASE (RPI_IO_BASE + RPI3_IO_PM_OFFSET) +/* Registers on top of RPI3_PM_BASE. */ +#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C) +#define RPI3_PM_RSTS_OFFSET ULL(0x00000020) +#define RPI3_PM_WDOG_OFFSET ULL(0x00000024) +/* Watchdog constants */ +#define RPI3_PM_PASSWORD U(0x5A000000) +#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030) +#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020) +/* + * The RSTS register is used by the VideoCore firmware when booting the + * Raspberry Pi to know which partition to boot from. The partition value is + * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware + * to indicate halt. + */ +#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555) + +/* + * Hardware random number generator. + */ +#define RPI3_IO_RNG_OFFSET ULL(0x00104000) +#define RPI3_RNG_BASE (RPI_IO_BASE + RPI3_IO_RNG_OFFSET) +#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000) +#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004) +#define RPI3_RNG_DATA_OFFSET ULL(0x00000008) +#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010) +/* Enable/disable RNG */ +#define RPI3_RNG_CTRL_ENABLE U(0x1) +#define RPI3_RNG_CTRL_DISABLE U(0x0) +/* Number of currently available words */ +#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24) +#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF) +/* Value to mask interrupts caused by the RNG */ +#define RPI3_RNG_INT_MASK_DISABLE U(0x1) + +/* + * Serial ports: + * 'Mini UART' in the BCM docucmentation is the 8250 compatible UART. + * There is also a PL011 UART, multiplexed to the same pins. + */ +#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040) +#define RPI3_MINI_UART_BASE (RPI_IO_BASE + RPI3_IO_MINI_UART_OFFSET) +#define RPI3_IO_PL011_UART_OFFSET ULL(0x00201000) +#define RPI3_PL011_UART_BASE (RPI_IO_BASE + RPI3_IO_PL011_UART_OFFSET) +#define RPI3_PL011_UART_CLOCK ULL(48000000) + +/* + * GPIO controller + */ +#define RPI3_IO_GPIO_OFFSET ULL(0x00200000) +#define RPI3_GPIO_BASE (RPI_IO_BASE + RPI3_IO_GPIO_OFFSET) + +/* + * SDHost controller + */ +#define RPI3_IO_SDHOST_OFFSET ULL(0x00202000) +#define RPI3_SDHOST_BASE (RPI_IO_BASE + RPI3_IO_SDHOST_OFFSET) + +/* + * Local interrupt controller + */ +#define RPI3_INTC_BASE_ADDRESS ULL(0x40000000) +/* Registers on top of RPI3_INTC_BASE_ADDRESS */ +#define RPI3_INTC_CONTROL_OFFSET ULL(0x00000000) +#define RPI3_INTC_PRESCALER_OFFSET ULL(0x00000008) +#define RPI3_INTC_MBOX_CONTROL_OFFSET ULL(0x00000050) +#define RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ ULL(0x00000080) +#define RPI3_INTC_PENDING_FIQ_OFFSET ULL(0x00000070) +#define RPI3_INTC_PENDING_FIQ_MBOX3 ULL(0x00000080) + +#endif /* RPI_HW_H */ diff --git a/arm-trusted-firmware/plat/rpi/rpi3/platform.mk b/arm-trusted-firmware/plat/rpi/rpi3/platform.mk new file mode 100644 index 0000000..6c23923 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/platform.mk @@ -0,0 +1,221 @@ +# +# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/libfdt/libfdt.mk +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_INCLUDES := -Iplat/rpi/common/include \ + -Iplat/rpi/rpi3/include + +PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \ + drivers/arm/pl011/aarch64/pl011_console.S \ + drivers/gpio/gpio.c \ + drivers/delay_timer/delay_timer.c \ + drivers/rpi3/gpio/rpi3_gpio.c \ + plat/rpi/common/aarch64/plat_helpers.S \ + plat/rpi/common/rpi3_common.c \ + ${XLAT_TABLES_LIB_SRCS} + +BL1_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/aarch64/platform_mp_stack.S \ + plat/rpi/rpi3/rpi3_bl1_setup.c \ + plat/rpi/common/rpi3_io_storage.c \ + drivers/rpi3/mailbox/rpi3_mbox.c \ + plat/rpi/rpi3/rpi_mbox_board.c + +BL2_SOURCES += common/desc_image_load.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/io/io_block.c \ + drivers/mmc/mmc.c \ + drivers/rpi3/sdhost/rpi3_sdhost.c \ + plat/common/aarch64/platform_mp_stack.S \ + plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c \ + plat/rpi/rpi3/rpi3_bl2_setup.c \ + plat/rpi/common/rpi3_image_load.c \ + plat/rpi/common/rpi3_io_storage.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/rpi/rpi3/rpi3_bl31_setup.c \ + plat/rpi/common/rpi3_pm.c \ + plat/rpi/common/rpi3_topology.c \ + ${LIBFDT_SRCS} + +# Tune compiler for Cortex-A53 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a53 +endif + +# Platform Makefile target +# ------------------------ + +RPI3_BL1_PAD_BIN := ${BUILD_PLAT}/bl1_pad.bin +RPI3_ARMSTUB8_BIN := ${BUILD_PLAT}/armstub8.bin + +# Add new default target when compiling this platform +all: armstub + +# This target concatenates BL1 and the FIP so that the base addresses match the +# ones defined in the memory map +armstub: bl1 fip + @echo " CAT $@" + ${Q}cp ${BUILD_PLAT}/bl1.bin ${RPI3_BL1_PAD_BIN} + ${Q}truncate --size=131072 ${RPI3_BL1_PAD_BIN} + ${Q}cat ${RPI3_BL1_PAD_BIN} ${BUILD_PLAT}/fip.bin > ${RPI3_ARMSTUB8_BIN} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +# Build config flags +# ------------------ + +# Enable all errata workarounds for Cortex-A53 +ERRATA_A53_826319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +# Disable stack protector by default +ENABLE_STACK_PROTECTOR := 0 + +# Reset to BL31 isn't supported +RESET_TO_BL31 := 0 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Platform build flags +# -------------------- + +# BL33 images are in AArch64 by default +RPI3_BL33_IN_AARCH32 := 0 + +# Assume that BL33 isn't the Linux kernel by default +RPI3_DIRECT_LINUX_BOOT := 0 + +# UART to use at runtime. -1 means the runtime UART is disabled. +# Any other value means the default UART will be used. +RPI3_RUNTIME_UART := -1 + +# Use normal memory mapping for ROM, FIP, SRAM and DRAM +RPI3_USE_UEFI_MAP := 0 + +# BL32 location +RPI3_BL32_RAM_LOCATION := tdram +ifeq (${RPI3_BL32_RAM_LOCATION}, tsram) + RPI3_BL32_RAM_LOCATION_ID = SEC_SRAM_ID +else ifeq (${RPI3_BL32_RAM_LOCATION}, tdram) + RPI3_BL32_RAM_LOCATION_ID = SEC_DRAM_ID +else + $(error "Unsupported RPI3_BL32_RAM_LOCATION value") +endif + +# Process platform flags +# ---------------------- + +$(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID)) +$(eval $(call add_define,RPI3_BL33_IN_AARCH32)) +$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT)) +ifdef RPI3_PRELOADED_DTB_BASE +$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE)) +endif +$(eval $(call add_define,RPI3_RUNTIME_UART)) +$(eval $(call add_define,RPI3_USE_UEFI_MAP)) + +# Verify build config +# ------------------- +# +ifneq (${RPI3_DIRECT_LINUX_BOOT}, 0) + ifndef RPI3_PRELOADED_DTB_BASE + $(error Error: RPI3_PRELOADED_DTB_BASE needed if RPI3_DIRECT_LINUX_BOOT=1) + endif +endif + +ifneq (${RESET_TO_BL31}, 0) + $(error Error: rpi3 needs RESET_TO_BL31=0) +endif + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on rpi3) +endif + +ifneq ($(ENABLE_STACK_PROTECTOR), 0) +PLAT_BL_COMMON_SOURCES += drivers/rpi3/rng/rpi3_rng.c \ + plat/rpi/common/rpi3_stack_protector.c +endif + +ifeq (${SPD},opteed) +BL2_SOURCES += \ + lib/optee/optee_utils.c +endif + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif + +ifneq (${TRUSTED_BOARD_BOOT},0) + + include drivers/auth/mbedtls/mbedtls_crypto.mk + include drivers/auth/mbedtls/mbedtls_x509.mk + + AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c + + BL1_SOURCES += ${AUTH_SOURCES} \ + bl1/tbbr/tbbr_img_desc.c \ + plat/common/tbbr/plat_tbbr.c \ + plat/rpi/common/rpi3_trusted_boot.c \ + plat/rpi/common/rpi3_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl1.c + + BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c \ + plat/rpi/common/rpi3_trusted_boot.c \ + plat/rpi/common/rpi3_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl2.c + + ROT_KEY = $(BUILD_PLAT)/rot_key.pem + ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + + $(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) + + $(BUILD_PLAT)/bl1/rpi3_rotpk.o: $(ROTPK_HASH) + $(BUILD_PLAT)/bl2/rpi3_rotpk.o: $(ROTPK_HASH) + + certificates: $(ROT_KEY) + + $(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + $(Q)openssl genrsa 2048 > $@ 2>/dev/null + + $(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif diff --git a/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c new file mode 100644 index 0000000..3ac30e0 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Data structure which holds the extents of the trusted SRAM for BL1 */ +static meminfo_t bl1_tzram_layout; + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + /* use the 19.2 MHz clock for the architected timer */ + mmio_write_32(RPI3_INTC_BASE_ADDRESS + RPI3_INTC_CONTROL_OFFSET, 0); + mmio_write_32(RPI3_INTC_BASE_ADDRESS + RPI3_INTC_PRESCALER_OFFSET, + 0x80000000); + + /* Initialize the console to provide early debug support */ + rpi3_console_init(); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL_RAM_BASE; + bl1_tzram_layout.total_size = BL_RAM_SIZE; +} + +/****************************************************************************** + * Perform the very early platform specific architecture setup. This only + * does basic initialization. Later architectural setup (bl1_arch_setup()) + * does not do anything platform specific. + *****************************************************************************/ +void bl1_plat_arch_setup(void) +{ + rpi3_setup_page_tables(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL_CODE_BASE, BL1_CODE_END, + BL1_RO_DATA_BASE, BL1_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END +#endif + ); + + enable_mmu_el3(0); +} + +void bl1_platform_setup(void) +{ + uint32_t __unused rev; + int __unused rc; + + rc = rpi3_vc_hardware_get_board_revision(&rev); + + if (rc == 0) { + const char __unused *model, __unused *info; + + switch (rev) { + case 0xA02082: + model = "Raspberry Pi 3 Model B"; + info = "(1GB, Sony, UK)"; + break; + case 0xA22082: + model = "Raspberry Pi 3 Model B"; + info = "(1GB, Embest, China)"; + break; + case 0xA020D3: + model = "Raspberry Pi 3 Model B+"; + info = "(1GB, Sony, UK)"; + break; + default: + model = "Unknown"; + info = "(Unknown)"; + ERROR("rpi3: Unknown board revision 0x%08x\n", rev); + break; + } + + NOTICE("rpi3: Detected: %s %s [0x%08x]\n", model, info, rev); + } else { + ERROR("rpi3: Unable to detect board revision\n"); + } + + /* Initialise the IO layer and register platform IO devices */ + plat_rpi3_io_setup(); +} diff --git a/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c new file mode 100644 index 0000000..db71817 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015-2019, 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 + +/* Data structure which holds the extents of the trusted SRAM for BL2 */ +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/* Data structure which holds the MMC info */ +static struct mmc_device_info mmc_info; + +static void rpi3_sdhost_setup(void) +{ + struct rpi3_sdhost_params params; + + memset(¶ms, 0, sizeof(struct rpi3_sdhost_params)); + params.reg_base = RPI3_SDHOST_BASE; + params.bus_width = MMC_BUS_WIDTH_1; + params.clk_rate = 50000000; + mmc_info.mmc_dev_type = MMC_IS_SD_HC; + rpi3_sdhost_init(¶ms, &mmc_info); +} + +/******************************************************************************* + * BL1 has passed the extents of the trusted SRAM that should be visible to BL2 + * in x0. This memory layout is sitting at the base of the free trusted SRAM. + * Copy it to a safe location before its reclaimed by later BL2 functionality. + ******************************************************************************/ + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + meminfo_t *mem_layout = (meminfo_t *) arg1; + + /* Initialize the console to provide early debug support */ + rpi3_console_init(); + + /* Enable arch timer */ + generic_delay_timer_init(); + + /* Setup GPIO driver */ + rpi3_gpio_init(); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; + + /* Setup SDHost driver */ + rpi3_sdhost_setup(); + + plat_rpi3_io_setup(); +} + +void bl2_platform_setup(void) +{ + /* + * This is where a TrustZone address space controller and other + * security related peripherals would be configured. + */ +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. + ******************************************************************************/ +void bl2_plat_arch_setup(void) +{ + rpi3_setup_page_tables(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL_CODE_BASE, BL_CODE_END, + BL_RO_DATA_BASE, BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END +#endif + ); + + enable_mmu_el1(0); +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif + + assert(bl_mem_params != NULL); + + switch (image_id) { + case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) + WARN("OPTEE header parse error.\n"); +#endif + bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry(); + break; + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl33_entry(); + + /* Shutting down the SDHost driver to let BL33 drives SDHost.*/ + rpi3_sdhost_stop(); + break; + + default: + /* Do nothing in default case */ + break; + } + + return err; +} diff --git a/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c new file mode 100644 index 0000000..5915753 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include +#include +#include +#include + +#include + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type) != 0); + + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Return entrypoint of BL33. + ******************************************************************************/ +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_RPI3_NS_IMAGE_OFFSET; +#endif +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) + +{ + /* Initialize the console to provide early debug support */ + rpi3_console_init(); + + /* + * In debug builds, a special value is passed in 'arg1' to verify + * platform parameters from BL2 to BL31. Not used in release builds. + */ + assert(arg1 == RPI3_BL31_PLAT_PARAM_VAL); + + /* Check that params passed from BL2 are not NULL. */ + bl_params_t *params_from_bl2 = (bl_params_t *) arg0; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) { + bl32_image_ep_info = *bl_params->ep_info; + } + + if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + } + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0) { + panic(); + } + +#if RPI3_DIRECT_LINUX_BOOT +# if RPI3_BL33_IN_AARCH32 + /* + * According to the file ``Documentation/arm/Booting`` of the Linux + * kernel tree, Linux expects: + * r0 = 0 + * r1 = machine type number, optional in DT-only platforms (~0 if so) + * r2 = Physical address of the device tree blob + */ + VERBOSE("rpi3: Preparing to boot 32-bit Linux kernel\n"); + bl33_image_ep_info.args.arg0 = 0U; + bl33_image_ep_info.args.arg1 = ~0U; + bl33_image_ep_info.args.arg2 = (u_register_t) RPI3_PRELOADED_DTB_BASE; +# else + /* + * According to the file ``Documentation/arm64/booting.txt`` of the + * Linux kernel tree, Linux expects the physical address of the device + * tree blob (DTB) in x0, while x1-x3 are reserved for future use and + * must be 0. + */ + VERBOSE("rpi3: Preparing to boot 64-bit Linux kernel\n"); + bl33_image_ep_info.args.arg0 = (u_register_t) RPI3_PRELOADED_DTB_BASE; + bl33_image_ep_info.args.arg1 = 0ULL; + bl33_image_ep_info.args.arg2 = 0ULL; + bl33_image_ep_info.args.arg3 = 0ULL; +# endif /* RPI3_BL33_IN_AARCH32 */ +#endif /* RPI3_DIRECT_LINUX_BOOT */ +} + +void bl31_plat_arch_setup(void) +{ + rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE, + BL_CODE_BASE, BL_CODE_END, + BL_RO_DATA_BASE, BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END +#endif + ); + + enable_mmu_el3(0); +} + +#ifdef RPI3_PRELOADED_DTB_BASE +/* + * Add information to the device tree (if any) about the reserved DRAM used by + * the Trusted Firmware. + */ +static void rpi3_dtb_add_mem_rsv(void) +{ + int i, regions, rc; + uint64_t addr, size; + void *dtb = (void *)RPI3_PRELOADED_DTB_BASE; + + INFO("rpi3: Checking DTB...\n"); + + /* Return if no device tree is detected */ + if (fdt_check_header(dtb) != 0) + return; + + regions = fdt_num_mem_rsv(dtb); + + VERBOSE("rpi3: Found %d mem reserve region(s)\n", regions); + + /* We expect to find one reserved region that we can modify */ + if (regions < 1) + return; + + /* + * Look for the region that corresponds to the default boot firmware. It + * starts at address 0, and it is not needed when the default firmware + * is replaced by this port of the Trusted Firmware. + */ + for (i = 0; i < regions; i++) { + if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) + continue; + + if (addr != 0x0) + continue; + + VERBOSE("rpi3: Firmware mem reserve region found\n"); + + rc = fdt_del_mem_rsv(dtb, i); + if (rc != 0) { + INFO("rpi3: Can't remove mem reserve region (%d)\n", rc); + } + + break; + } + + if (i == regions) { + VERBOSE("rpi3: Firmware mem reserve region not found\n"); + } + + /* + * Reserve all SRAM. As said in the documentation, this isn't actually + * secure memory, so it is needed to tell BL33 that this is a reserved + * memory region. It doesn't guarantee it won't use it, though. + */ + rc = fdt_add_mem_rsv(dtb, SEC_SRAM_BASE, SEC_SRAM_SIZE); + if (rc != 0) { + WARN("rpi3: Can't add mem reserve region (%d)\n", rc); + } + + INFO("rpi3: Reserved 0x%llx - 0x%llx in DTB\n", SEC_SRAM_BASE, + SEC_SRAM_BASE + SEC_SRAM_SIZE); +} +#endif + +void bl31_platform_setup(void) +{ +#ifdef RPI3_PRELOADED_DTB_BASE + /* Only modify a DTB if we know where to look for it */ + rpi3_dtb_add_mem_rsv(); +#endif +} diff --git a/arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c b/arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c new file mode 100644 index 0000000..e7c1e2b --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include + +#define RPI3_MBOX_BUFFER_SIZE U(256) +static uint8_t __aligned(16) rpi3_mbox_buffer[RPI3_MBOX_BUFFER_SIZE]; + +/******************************************************************************* + * Request board revision. Returns the revision and 0 on success, -1 on error. + ******************************************************************************/ +int rpi3_vc_hardware_get_board_revision(uint32_t *revision) +{ + uint32_t tag_request_size = sizeof(uint32_t); + rpi3_mbox_request_t *req = (rpi3_mbox_request_t *) rpi3_mbox_buffer; + + assert(revision != NULL); + + VERBOSE("rpi3: mbox: Sending request at %p\n", (void *)req); + + req->size = sizeof(rpi3_mbox_buffer); + req->code = RPI3_MBOX_PROCESS_REQUEST; + + req->tags[0] = RPI3_TAG_HARDWARE_GET_BOARD_REVISION; + req->tags[1] = tag_request_size; /* Space available for the response */ + req->tags[2] = RPI3_TAG_REQUEST; + req->tags[3] = 0; /* Placeholder for the response */ + + req->tags[4] = RPI3_TAG_END; + + rpi3_vc_mailbox_request_send(req, RPI3_MBOX_BUFFER_SIZE); + + if (req->code != RPI3_MBOX_REQUEST_SUCCESSFUL) { + ERROR("rpi3: mbox: Code = 0x%08x\n", req->code); + return -1; + } + + if (req->tags[2] != (RPI3_TAG_IS_RESPONSE | tag_request_size)) { + ERROR("rpi3: mbox: get board revision failed (0x%08x)\n", + req->tags[2]); + return -1; + } + + *revision = req->tags[3]; + + return 0; +} diff --git a/arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S b/arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S new file mode 100644 index 0000000..246358d --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * armstub8.bin header to let the GPU firmware recognise this code. + * It will then write the load address of the kernel image and the DT + * after the header magic in RAM, so we can read those addresses at runtime. + */ + +.text + b armstub8_end + +.global stub_magic +.global dtb_ptr32 +.global kernel_entry32 + +.org 0xf0 +armstub8: +stub_magic: + .word 0x5afe570b +stub_version: + .word 0 +dtb_ptr32: + .word 0x0 +kernel_entry32: + .word 0x0 + +/* + * Technically an offset of 0x100 would suffice, but the follow-up code + * (bl31_entrypoint.S at BL31_BASE) needs to be page aligned, so pad here + * till the end of the first 4K page. + */ +.org 0x1000 +armstub8_end: diff --git a/arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S b/arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S new file mode 100644 index 0000000..9262fad --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Stub linker script to provide the armstub8.bin header before the actual + * code. If the GPU firmware finds a magic value at offset 240 in + * armstub8.bin, it will put the DTB and kernel load address in subsequent + * words. We can then read those values to find the proper NS entry point + * and find our DTB more flexibly. + */ + +MEMORY { + PRERAM (rwx): ORIGIN = 0, LENGTH = 4096 +} + +SECTIONS +{ + .armstub8 . : { + *armstub8_header.o(.text*) + KEEP(*(.armstub8)) + } >PRERAM +} diff --git a/arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S b/arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S new file mode 100644 index 0000000..6007d03 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h b/arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h new file mode 100644 index 0000000..6787ebf --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include + +#include "rpi_hw.h" + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978) + +#define PLATFORM_STACK_SIZE ULL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define RPI_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* + * I/O registers. + */ +#define DEVICE0_BASE RPI_IO_BASE +#define DEVICE0_SIZE RPI_IO_SIZE + +/* + * Mailbox to control the secondary cores. All secondary cores are held in a + * wait loop in cold boot. To release them perform the following steps (plus + * any additional barriers that may be needed): + * + * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT; + * *entrypoint = ADDRESS_TO_JUMP_TO; + * + * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE; + * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO; + * + * sev(); + */ +/* The secure entry point to be used on warm reset by all CPUs. */ +#define PLAT_RPI3_TM_ENTRYPOINT 0x100 +#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8) + +/* Hold entries for each CPU. */ +#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \ + PLAT_RPI3_TM_ENTRYPOINT_SIZE) +#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8) +#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \ + PLATFORM_CORE_COUNT) + +#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \ + PLAT_RPI3_TM_HOLD_SIZE) + +#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0) +#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1) +#define PLAT_RPI3_TM_HOLD_STATE_BSP_OFF ULL(2) + +/* + * BL31 specific defines. + * + * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL31 debug size plus a little space for growth. + */ +#define PLAT_MAX_BL31_SIZE ULL(0x80000) + +#define BL31_BASE ULL(0x1000) +#define BL31_LIMIT ULL(0x80000) +#define BL31_PROGBITS_LIMIT ULL(0x80000) + +#define SEC_SRAM_ID 0 +#define SEC_DRAM_ID 1 + +/* + * Other memory-related defines. + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS 8 +#define MAX_XLAT_TABLES 4 + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +#define MAX_IO_BLOCK_DEVICES U(1) + +/* + * Serial-related constants. + */ +#define PLAT_RPI_MINI_UART_BASE RPI4_MINI_UART_BASE +#define PLAT_RPI_PL011_UART_BASE RPI4_PL011_UART_BASE +#define PLAT_RPI_PL011_UART_CLOCK RPI4_PL011_UART_CLOCK +#define PLAT_RPI_UART_BAUDRATE ULL(115200) + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS ULL(54000000) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h b/arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h new file mode 100644 index 0000000..0430d46 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI_HW_H +#define RPI_HW_H + +#include + +/* + * Peripherals + */ + +#define RPI_IO_BASE ULL(0xFC000000) +#define RPI_IO_SIZE ULL(0x04000000) + +#define RPI_LEGACY_BASE (ULL(0x02000000) + RPI_IO_BASE) + +/* + * ARM <-> VideoCore mailboxes + */ +#define RPI3_MBOX_OFFSET ULL(0x0000B880) +#define RPI3_MBOX_BASE (RPI_LEGACY_BASE + RPI3_MBOX_OFFSET) +/* VideoCore -> ARM */ +#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000) +#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010) +#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014) +#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018) +#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C) +/* ARM -> VideoCore */ +#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020) +#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030) +#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034) +#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038) +#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C) +/* Mailbox status constants */ +#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */ +#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */ + +/* + * Power management, reset controller, watchdog. + */ +#define RPI3_IO_PM_OFFSET ULL(0x00100000) +#define RPI3_PM_BASE (RPI_LEGACY_BASE + RPI3_IO_PM_OFFSET) +/* Registers on top of RPI3_PM_BASE. */ +#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C) +#define RPI3_PM_RSTS_OFFSET ULL(0x00000020) +#define RPI3_PM_WDOG_OFFSET ULL(0x00000024) +/* Watchdog constants */ +#define RPI3_PM_PASSWORD U(0x5A000000) +#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030) +#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020) +/* + * The RSTS register is used by the VideoCore firmware when booting the + * Raspberry Pi to know which partition to boot from. The partition value is + * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware + * to indicate halt. + */ +#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555) + +/* + * Hardware random number generator. + */ +#define RPI3_IO_RNG_OFFSET ULL(0x00104000) +#define RPI3_RNG_BASE (RPI_LEGACY_BASE + RPI3_IO_RNG_OFFSET) +#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000) +#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004) +#define RPI3_RNG_DATA_OFFSET ULL(0x00000008) +#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010) +/* Enable/disable RNG */ +#define RPI3_RNG_CTRL_ENABLE U(0x1) +#define RPI3_RNG_CTRL_DISABLE U(0x0) +/* Number of currently available words */ +#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24) +#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF) +/* Value to mask interrupts caused by the RNG */ +#define RPI3_RNG_INT_MASK_DISABLE U(0x1) + +/* + * Serial ports: + * 'Mini UART' in the BCM docucmentation is the 8250 compatible UART. + * There is also a PL011 UART, multiplexed to the same pins. + */ +#define RPI4_IO_MINI_UART_OFFSET ULL(0x00215040) +#define RPI4_MINI_UART_BASE (RPI_LEGACY_BASE + RPI4_IO_MINI_UART_OFFSET) +#define RPI4_IO_PL011_UART_OFFSET ULL(0x00201000) +#define RPI4_PL011_UART_BASE (RPI_LEGACY_BASE + RPI4_IO_PL011_UART_OFFSET) +#define RPI4_PL011_UART_CLOCK ULL(48000000) + +/* + * GPIO controller + */ +#define RPI3_IO_GPIO_OFFSET ULL(0x00200000) +#define RPI3_GPIO_BASE (RPI_LEGACY_BASE + RPI3_IO_GPIO_OFFSET) + +/* + * SDHost controller + */ +#define RPI3_IO_SDHOST_OFFSET ULL(0x00202000) +#define RPI3_SDHOST_BASE (RPI_LEGACY_BASE + RPI3_IO_SDHOST_OFFSET) + +/* + * GIC interrupt controller + */ +#define RPI_HAVE_GIC +#define RPI4_GIC_GICD_BASE ULL(0xff841000) +#define RPI4_GIC_GICC_BASE ULL(0xff842000) + +#define RPI4_LOCAL_CONTROL_BASE_ADDRESS ULL(0xff800000) +#define RPI4_LOCAL_CONTROL_PRESCALER ULL(0xff800008) + +#endif /* RPI_HW_H */ diff --git a/arm-trusted-firmware/plat/rpi/rpi4/platform.mk b/arm-trusted-firmware/plat/rpi/rpi4/platform.mk new file mode 100644 index 0000000..528eb1d --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi4/platform.mk @@ -0,0 +1,116 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/libfdt/libfdt.mk +include lib/xlat_tables_v2/xlat_tables.mk + +include drivers/arm/gic/v2/gicv2.mk + +PLAT_INCLUDES := -Iplat/rpi/common/include \ + -Iplat/rpi/rpi4/include + +PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \ + drivers/arm/pl011/aarch64/pl011_console.S \ + plat/rpi/common/rpi3_common.c \ + ${XLAT_TABLES_LIB_SRCS} + +BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \ + plat/rpi/common/aarch64/plat_helpers.S \ + plat/rpi/rpi4/aarch64/armstub8_header.S \ + drivers/delay_timer/delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/rpi3/gpio/rpi3_gpio.c \ + plat/common/plat_gicv2.c \ + plat/rpi/rpi4/rpi4_bl31_setup.c \ + plat/rpi/common/rpi3_pm.c \ + plat/common/plat_psci_common.c \ + plat/rpi/common/rpi3_topology.c \ + common/fdt_fixup.c \ + ${LIBFDT_SRCS} \ + ${GICV2_SOURCES} + +# For now we only support BL31, using the kernel loaded by the GPU firmware. +RESET_TO_BL31 := 1 + +# All CPUs enter armstub8.bin. +COLD_BOOT_SINGLE_CPU := 0 + +# Tune compiler for Cortex-A72 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a72 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a72 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a72 +endif + +# Add support for platform supplied linker script for BL31 build +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +# Enable all errata workarounds for Cortex-A72 +ERRATA_A72_859971 := 1 + +WORKAROUND_CVE_2017_5715 := 1 + +# Add new default target when compiling this platform +all: bl31 + +# Build config flags +# ------------------ + +# Disable stack protector by default +ENABLE_STACK_PROTECTOR := 0 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Platform build flags +# -------------------- + +# There is not much else than a Linux kernel to load at the moment. +RPI3_DIRECT_LINUX_BOOT := 1 + +# BL33 images are in AArch64 by default +RPI3_BL33_IN_AARCH32 := 0 + +# UART to use at runtime. -1 means the runtime UART is disabled. +# Any other value means the default UART will be used. +RPI3_RUNTIME_UART := 0 + +# Use normal memory mapping for ROM, FIP, SRAM and DRAM +RPI3_USE_UEFI_MAP := 0 + +# SMCCC PCI support (should be enabled for ACPI builds) +SMC_PCI_SUPPORT := 0 + +# Process platform flags +# ---------------------- + +$(eval $(call add_define,RPI3_BL33_IN_AARCH32)) +$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT)) +ifdef RPI3_PRELOADED_DTB_BASE +$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE)) +endif +$(eval $(call add_define,RPI3_RUNTIME_UART)) +$(eval $(call add_define,RPI3_USE_UEFI_MAP)) +$(eval $(call add_define,SMC_PCI_SUPPORT)) + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on rpi4) +endif + +ifneq ($(ENABLE_STACK_PROTECTOR), 0) +PLAT_BL_COMMON_SOURCES += drivers/rpi3/rng/rpi3_rng.c \ + plat/rpi/common/rpi3_stack_protector.c +endif + +ifeq ($(SMC_PCI_SUPPORT), 1) +BL31_SOURCES += plat/rpi/rpi4/rpi4_pci_svc.c +endif + diff --git a/arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c b/arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c new file mode 100644 index 0000000..2fb4d3d --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2015-2019, 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 +#include + +#include + +#include + +/* + * Fields at the beginning of armstub8.bin. + * While building the BL31 image, we put the stub magic into the binary. + * The GPU firmware detects this at boot time, clears that field as a + * confirmation and puts the kernel and DT address in the following words. + */ +extern uint32_t stub_magic; +extern uint32_t dtb_ptr32; +extern uint32_t kernel_entry32; + +static const gicv2_driver_data_t rpi4_gic_data = { + .gicd_base = RPI4_GIC_GICD_BASE, + .gicc_base = RPI4_GIC_GICC_BASE, +}; + +/* + * To be filled by the code below. At the moment BL32 is not supported. + * In the future these might be passed down from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type) != 0); + + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + /* Cleared by the GPU if kernel address is valid. */ + if (stub_magic == 0) + return kernel_entry32; + + WARN("Stub magic failure, using default kernel address 0x80000\n"); + return 0x80000; +#endif +} + +static uintptr_t rpi4_get_dtb_address(void) +{ +#ifdef RPI3_PRELOADED_DTB_BASE + return RPI3_PRELOADED_DTB_BASE; +#else + /* Cleared by the GPU if DTB address is valid. */ + if (stub_magic == 0) + return dtb_ptr32; + + WARN("Stub magic failure, DTB address unknown\n"); + return 0; +#endif +} + +static void ldelay(register_t delay) +{ + __asm__ volatile ( + "1:\tcbz %0, 2f\n\t" + "sub %0, %0, #1\n\t" + "b 1b\n" + "2:" + : "=&r" (delay) : "0" (delay) + ); +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) + +{ + /* + * LOCAL_CONTROL: + * Bit 9 clear: Increment by 1 (vs. 2). + * Bit 8 clear: Timer source is 19.2MHz crystal (vs. APB). + */ + mmio_write_32(RPI4_LOCAL_CONTROL_BASE_ADDRESS, 0); + + /* LOCAL_PRESCALER; divide-by (0x80000000 / register_val) == 1 */ + mmio_write_32(RPI4_LOCAL_CONTROL_PRESCALER, 0x80000000); + + /* Early GPU firmware revisions need a little break here. */ + ldelay(100000); + + /* Initialize the console to provide early debug support. */ + rpi3_console_init(); + + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#if RPI3_DIRECT_LINUX_BOOT +# if RPI3_BL33_IN_AARCH32 + /* + * According to the file ``Documentation/arm/Booting`` of the Linux + * kernel tree, Linux expects: + * r0 = 0 + * r1 = machine type number, optional in DT-only platforms (~0 if so) + * r2 = Physical address of the device tree blob + */ + VERBOSE("rpi4: Preparing to boot 32-bit Linux kernel\n"); + bl33_image_ep_info.args.arg0 = 0U; + bl33_image_ep_info.args.arg1 = ~0U; + bl33_image_ep_info.args.arg2 = rpi4_get_dtb_address(); +# else + /* + * According to the file ``Documentation/arm64/booting.txt`` of the + * Linux kernel tree, Linux expects the physical address of the device + * tree blob (DTB) in x0, while x1-x3 are reserved for future use and + * must be 0. + */ + VERBOSE("rpi4: Preparing to boot 64-bit Linux kernel\n"); + bl33_image_ep_info.args.arg0 = rpi4_get_dtb_address(); + bl33_image_ep_info.args.arg1 = 0ULL; + bl33_image_ep_info.args.arg2 = 0ULL; + bl33_image_ep_info.args.arg3 = 0ULL; +# endif /* RPI3_BL33_IN_AARCH32 */ +#endif /* RPI3_DIRECT_LINUX_BOOT */ +} + +void bl31_plat_arch_setup(void) +{ + /* + * Is the dtb_ptr32 pointer valid? If yes, map the DTB region. + * We map the 2MB region the DTB start address lives in, plus + * the next 2MB, to have enough room for expansion. + */ + if (stub_magic == 0) { + unsigned long long dtb_region = dtb_ptr32; + + dtb_region &= ~0x1fffff; /* Align to 2 MB. */ + mmap_add_region(dtb_region, dtb_region, 4U << 20, + MT_MEMORY | MT_RW | MT_NS); + } + /* + * Add the first page of memory, which holds the stub magic, + * the kernel and the DT address. + * This also holds the secondary CPU's entrypoints and mailboxes. + */ + mmap_add_region(0, 0, 4096, MT_NON_CACHEABLE | MT_RW | MT_SECURE); + + rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE, + BL_CODE_BASE, BL_CODE_END, + BL_RO_DATA_BASE, BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END +#endif + ); + + enable_mmu_el3(0); +} + +/* + * Remove the FDT /memreserve/ entry that covers the region at the very + * beginning of memory (if that exists). This is where the secondaries + * originally spin, but we pull them out there. + * Having overlapping /reserved-memory and /memreserve/ regions confuses + * the Linux kernel, so we need to get rid of this one. + */ +static void remove_spintable_memreserve(void *dtb) +{ + uint64_t addr, size; + int regions = fdt_num_mem_rsv(dtb); + int i; + + for (i = 0; i < regions; i++) { + if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) { + return; + } + if (size == 0U) { + return; + } + /* We only look for the region at the beginning of DRAM. */ + if (addr != 0U) { + continue; + } + /* + * Currently the region in the existing DTs is exactly 4K + * in size. Should this value ever change, there is probably + * a reason for that, so inform the user about this. + */ + if (size == 4096U) { + fdt_del_mem_rsv(dtb, i); + return; + } + WARN("Keeping unknown /memreserve/ region at 0, size: %" PRId64 "\n", + size); + } +} + +static void rpi4_prepare_dtb(void) +{ + void *dtb = (void *)rpi4_get_dtb_address(); + uint32_t gic_int_prop[3]; + int ret, offs; + + /* Return if no device tree is detected */ + if (fdt_check_header(dtb) != 0) + return; + + ret = fdt_open_into(dtb, dtb, 0x100000); + if (ret < 0) { + ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret); + return; + } + + if (dt_add_psci_node(dtb)) { + ERROR("Failed to add PSCI Device Tree node\n"); + return; + } + + if (dt_add_psci_cpu_enable_methods(dtb)) { + ERROR("Failed to add PSCI cpu enable methods in Device Tree\n"); + return; + } + + /* + * Remove the original reserved region (used for the spintable), and + * replace it with a region describing the whole of Trusted Firmware. + */ + remove_spintable_memreserve(dtb); + if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000)) + WARN("Failed to add reserved memory nodes to DT.\n"); + + offs = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-400"); + gic_int_prop[0] = cpu_to_fdt32(1); // PPI + gic_int_prop[1] = cpu_to_fdt32(9); // PPI #9 + gic_int_prop[2] = cpu_to_fdt32(0x0f04); // all cores, level high + fdt_setprop(dtb, offs, "interrupts", gic_int_prop, 12); + + offs = fdt_path_offset(dtb, "/chosen"); + fdt_setprop_string(dtb, offs, "stdout-path", "serial0"); + + ret = fdt_pack(dtb); + if (ret < 0) + ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret); + + clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb)); + INFO("Changed device tree to advertise PSCI.\n"); +} + +void bl31_platform_setup(void) +{ + rpi4_prepare_dtb(); + + /* Configure the interrupt controller */ + gicv2_driver_init(&rpi4_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} diff --git a/arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c b/arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c new file mode 100644 index 0000000..7d1ca5c --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * The RPi4 has a single nonstandard PCI config region. It is broken into two + * pieces, the root port config registers and a window to a single device's + * config space which can move between devices. There isn't (yet) an + * authoritative public document on this since the available BCM2711 reference + * notes that there is a PCIe root port in the memory map but doesn't describe + * it. Given that it's not ECAM compliant yet reasonably simple, it makes for + * an excellent example of the PCI SMCCC interface. + * + * The PCI SMCCC interface is described in DEN0115 availabe from: + * https://developer.arm.com/documentation/den0115/latest + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static spinlock_t pci_lock; + +#define PCIE_REG_BASE U(RPI_IO_BASE + 0x01500000) +#define PCIE_MISC_PCIE_STATUS 0x4068 +#define PCIE_EXT_CFG_INDEX 0x9000 +/* A small window pointing at the ECAM of the device selected by CFG_INDEX */ +#define PCIE_EXT_CFG_DATA 0x8000 +#define INVALID_PCI_ADDR 0xFFFFFFFF + +#define PCIE_EXT_BUS_SHIFT 20 +#define PCIE_EXT_DEV_SHIFT 15 +#define PCIE_EXT_FUN_SHIFT 12 + + +static uint64_t pci_segment_lib_get_base(uint32_t address, uint32_t offset) +{ + uint64_t base; + uint32_t bus, dev, fun; + uint32_t status; + + base = PCIE_REG_BASE; + + offset &= PCI_OFFSET_MASK; /* Pick off the 4k register offset */ + + /* The root port is at the base of the PCIe register space */ + if (address != 0U) { + /* + * The current device must be at CFG_DATA, a 4K window mapped, + * via CFG_INDEX, to the device we are accessing. At the same + * time we must avoid accesses to certain areas of the cfg + * space via CFG_DATA. Detect those accesses and report that + * the address is invalid. + */ + base += PCIE_EXT_CFG_DATA; + bus = PCI_ADDR_BUS(address); + dev = PCI_ADDR_DEV(address); + fun = PCI_ADDR_FUN(address); + address = (bus << PCIE_EXT_BUS_SHIFT) | + (dev << PCIE_EXT_DEV_SHIFT) | + (fun << PCIE_EXT_FUN_SHIFT); + + /* Allow only dev = 0 on root port and bus 1 */ + if ((bus < 2U) && (dev > 0U)) { + return INVALID_PCI_ADDR; + } + + /* Assure link up before reading bus 1 */ + status = mmio_read_32(PCIE_REG_BASE + PCIE_MISC_PCIE_STATUS); + if ((status & 0x30) != 0x30) { + return INVALID_PCI_ADDR; + } + + /* Adjust which device the CFG_DATA window is pointing at */ + mmio_write_32(PCIE_REG_BASE + PCIE_EXT_CFG_INDEX, address); + } + return base + offset; +} + +/** + * pci_read_config() - Performs a config space read at addr + * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115 + * @off: register offset of function described by @addr to read + * @sz: size of read (8,16,32) bits. + * @val: returned zero extended value read from config space + * + * sz bits of PCI config space is read at addr:offset, and the value + * is returned in val. Invalid segment/offset values return failure. + * Reads to valid functions that don't exist return INVALID_PCI_ADDR + * as is specified by PCI for requests that aren't completed by EPs. + * The boilerplate in pci_svc.c tends to do basic segment, off + * and sz validation. This routine should avoid duplicating those + * checks. + * + * This function maps directly to the PCI_READ function in DEN0115 + * where detailed requirements may be found. + * + * Return: SMC_PCI_CALL_SUCCESS with val set + * SMC_PCI_CALL_INVAL_PARAM, on parameter error + */ +uint32_t pci_read_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t *val) +{ + uint32_t ret = SMC_PCI_CALL_SUCCESS; + uint64_t base; + + spin_lock(&pci_lock); + base = pci_segment_lib_get_base(addr, off); + + if (base == INVALID_PCI_ADDR) { + *val = base; + } else { + switch (sz) { + case SMC_PCI_SZ_8BIT: + *val = mmio_read_8(base); + break; + case SMC_PCI_SZ_16BIT: + *val = mmio_read_16(base); + break; + case SMC_PCI_SZ_32BIT: + *val = mmio_read_32(base); + break; + default: /* should be unreachable */ + *val = 0; + ret = SMC_PCI_CALL_INVAL_PARAM; + } + } + spin_unlock(&pci_lock); + return ret; +} + +/** + * pci_write_config() - Performs a config space write at addr + * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115 + * @off: register offset of function described by @addr to write + * @sz: size of write (8,16,32) bits. + * @val: value to be written + * + * sz bits of PCI config space is written at addr:offset. Invalid + * segment/BDF values return failure. Writes to valid functions + * without valid EPs are ignored, as is specified by PCI. + * The boilerplate in pci_svc.c tends to do basic segment, off + * and sz validation, so it shouldn't need to be repeated here. + * + * This function maps directly to the PCI_WRITE function in DEN0115 + * where detailed requirements may be found. + * + * Return: SMC_PCI_CALL_SUCCESS + * SMC_PCI_CALL_INVAL_PARAM, on parameter error + */ +uint32_t pci_write_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t val) +{ + uint32_t ret = SMC_PCI_CALL_SUCCESS; + uint64_t base; + + spin_lock(&pci_lock); + base = pci_segment_lib_get_base(addr, off); + + if (base != INVALID_PCI_ADDR) { + switch (sz) { + case SMC_PCI_SZ_8BIT: + mmio_write_8(base, val); + break; + case SMC_PCI_SZ_16BIT: + mmio_write_16(base, val); + break; + case SMC_PCI_SZ_32BIT: + mmio_write_32(base, val); + break; + default: /* should be unreachable */ + ret = SMC_PCI_CALL_INVAL_PARAM; + } + } + spin_unlock(&pci_lock); + return ret; +} + +/** + * pci_get_bus_for_seg() - returns the start->end bus range for a segment + * @seg: segment being queried + * @bus_range: returned bus begin + (end << 8) + * @nseg: returns next segment in this machine or 0 for end + * + * pci_get_bus_for_seg is called to check if a given segment is + * valid on this machine. If it is valid, then its bus ranges are + * returned along with the next valid segment on the machine. If + * this is the last segment, then nseg must be 0. + * + * This function maps directly to the PCI_GET_SEG_INFO function + * in DEN0115 where detailed requirements may be found. + * + * Return: SMC_PCI_CALL_SUCCESS, and appropriate bus_range and nseg + * SMC_PCI_CALL_NOT_IMPL, if the segment is invalid + */ +uint32_t pci_get_bus_for_seg(uint32_t seg, uint32_t *bus_range, uint32_t *nseg) +{ + uint32_t ret = SMC_PCI_CALL_SUCCESS; + *nseg = 0U; /* only a single segment */ + if (seg == 0U) { + *bus_range = 0xFF00; /* start 0, end 255 */ + } else { + *bus_range = 0U; + ret = SMC_PCI_CALL_NOT_IMPL; + } + return ret; +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c b/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c new file mode 100644 index 0000000..925ed97 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#include +#include "sq_mhu.h" + +/* SCP MHU secure channel registers */ +#define SCP_INTR_S_STAT 0x200 +#define SCP_INTR_S_SET 0x208 +#define SCP_INTR_S_CLEAR 0x210 + +/* CPU MHU secure channel registers */ +#define CPU_INTR_S_STAT 0x300 +#define CPU_INTR_S_SET 0x308 +#define CPU_INTR_S_CLEAR 0x310 + +DEFINE_BAKERY_LOCK(sq_lock); + +/* + * Slot 31 is reserved because the MHU hardware uses this register bit to + * indicate a non-secure access attempt. The total number of available slots is + * therefore 31 [30:0]. + */ +#define MHU_MAX_SLOT_ID 30 + +void mhu_secure_message_start(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + + bakery_lock_get(&sq_lock); + + /* Make sure any previous command has finished */ + while (mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id)) + ; +} + +void mhu_secure_message_send(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + assert(!(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id))); + + /* Send command to SCP */ + mmio_write_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id); +} + +uint32_t mhu_secure_message_wait(void) +{ + uint32_t response; + + /* Wait for response from SCP */ + while (!(response = mmio_read_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_STAT))) + ; + + return response; +} + +void mhu_secure_message_end(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + + /* + * Clear any response we got by writing one in the relevant slot bit to + * the CLEAR register + */ + mmio_write_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id); + + bakery_lock_release(&sq_lock); +} + +void mhu_secure_init(void) +{ + bakery_lock_init(&sq_lock); + + /* + * The STAT register resets to zero. Ensure it is in the expected state, + * as a stale or garbage value would make us think it's a message we've + * already sent. + */ + assert(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) == 0); +} + +void plat_sq_pwrc_setup(void) +{ + mhu_secure_init(); +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h b/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h new file mode 100644 index 0000000..f6b5cc3 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SQ_MHU_H +#define SQ_MHU_H + +#include + +void mhu_secure_message_start(unsigned int slot_id); +void mhu_secure_message_send(unsigned int slot_id); +uint32_t mhu_secure_message_wait(void); +void mhu_secure_message_end(unsigned int slot_id); + +void mhu_secure_init(void); + +#endif /* SQ_MHU_H */ diff --git a/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c new file mode 100644 index 0000000..0e99256 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2019, 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 + +/* + * This file implements the SCP helper functions using SCMI protocol. + */ + +DEFINE_BAKERY_LOCK(sq_scmi_lock); +#define SQ_SCMI_LOCK_GET_INSTANCE (&sq_scmi_lock) + +#define SQ_SCMI_PAYLOAD_BASE PLAT_SQ_SCP_COM_SHARED_MEM_BASE +#define MHU_CPU_INTR_S_SET_OFFSET 0x308 + +const uint32_t sq_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 +}; + +static scmi_channel_plat_info_t sq_scmi_plat_info = { + .scmi_mbx_mem = SQ_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_SQ_MHU_BASE + MHU_CPU_INTR_S_SET_OFFSET, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell, +}; + +/* + * SCMI power state parameter bit field encoding for SynQuacer platform. + * + * 31 20 19 16 15 12 11 8 7 4 3 0 + * +-------------------------------------------------------------+ + * | SBZ | Max level | Level 3 | Level 2 | Level 1 | Level 0 | + * | | | state | state | state | state | + * +-------------------------------------------------------------+ + * + * `Max level` encodes the highest level that has a valid power state + * encoded in the power state. + */ +#define SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT 16 +#define SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH 4 +#define SCMI_PWR_STATE_MAX_PWR_LVL_MASK \ + ((1 << SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH) - 1) +#define SCMI_SET_PWR_STATE_MAX_PWR_LVL(_power_state, _max_level) \ + (_power_state) |= ((_max_level) & SCMI_PWR_STATE_MAX_PWR_LVL_MASK)\ + << SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT +#define SCMI_GET_PWR_STATE_MAX_PWR_LVL(_power_state) \ + (((_power_state) >> SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT) \ + & SCMI_PWR_STATE_MAX_PWR_LVL_MASK) + +#define SCMI_PWR_STATE_LVL_WIDTH 4 +#define SCMI_PWR_STATE_LVL_MASK \ + ((1 << SCMI_PWR_STATE_LVL_WIDTH) - 1) +#define SCMI_SET_PWR_STATE_LVL(_power_state, _level, _level_state) \ + (_power_state) |= ((_level_state) & SCMI_PWR_STATE_LVL_MASK) \ + << (SCMI_PWR_STATE_LVL_WIDTH * (_level)) +#define SCMI_GET_PWR_STATE_LVL(_power_state, _level) \ + (((_power_state) >> (SCMI_PWR_STATE_LVL_WIDTH * (_level))) & \ + SCMI_PWR_STATE_LVL_MASK) + +/* + * The SCMI power state enumeration for a power domain level + */ +typedef enum { + scmi_power_state_off = 0, + scmi_power_state_on = 1, + scmi_power_state_sleep = 2, +} scmi_power_state_t; + +/* + * The global handle for invoking the SCMI driver APIs after the driver + * has been initialized. + */ +static void *sq_scmi_handle; + +/* The SCMI channel global object */ +static scmi_channel_t channel; + +/* + * Helper function to turn off a CPU power domain and + * its parent power domains if applicable. + */ +void sq_scmi_off(const struct psci_power_state *target_state) +{ + int lvl = 0, ret; + uint32_t scmi_pwr_state = 0; + + /* At-least the CPU level should be specified to be OFF */ + assert(target_state->pwr_domain_state[SQ_PWR_LVL0] == + SQ_LOCAL_STATE_OFF); + + for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + if (target_state->pwr_domain_state[lvl] == SQ_LOCAL_STATE_RUN) + break; + + assert(target_state->pwr_domain_state[lvl] == + SQ_LOCAL_STATE_OFF); + SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl, + scmi_power_state_off); + } + + SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1); + + ret = scmi_pwr_state_set(sq_scmi_handle, + sq_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()], + scmi_pwr_state); + + if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) { + ERROR("SCMI set power state command return 0x%x unexpected\n", + ret); + panic(); + } +} + +/* + * Helper function to turn ON a CPU power domain and + *its parent power domains if applicable. + */ +void sq_scmi_on(u_register_t mpidr) +{ + int lvl = 0, ret, core_pos; + uint32_t scmi_pwr_state = 0; + + for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) + SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl, + scmi_power_state_on); + + SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1); + + core_pos = plat_core_pos_by_mpidr(mpidr); + assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT); + + ret = scmi_pwr_state_set(sq_scmi_handle, + sq_core_pos_to_scmi_dmn_id_map[core_pos], + scmi_pwr_state); + + if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) { + ERROR("SCMI set power state command return 0x%x unexpected\n", + ret); + panic(); + } +} + +void __dead2 sq_scmi_system_off(int state) +{ + int ret; + + /* + * Disable GIC CPU interface to prevent pending interrupt from waking + * up the AP from WFI. + */ + sq_gic_cpuif_disable(); + + /* + * Issue SCMI command. First issue a graceful + * request and if that fails force the request. + */ + ret = scmi_sys_pwr_state_set(sq_scmi_handle, + SCMI_SYS_PWR_FORCEFUL_REQ, + state); + + if (ret != SCMI_E_SUCCESS) { + ERROR("SCMI system power state set 0x%x returns unexpected 0x%x\n", + state, ret); + panic(); + } + wfi(); + ERROR("SCMI set power state: operation not handled.\n"); + panic(); +} + +/* + * Helper function to reset the system via SCMI. + */ +void __dead2 sq_scmi_sys_shutdown(void) +{ + sq_scmi_system_off(SCMI_SYS_PWR_SHUTDOWN); +} + +void __dead2 sq_scmi_sys_reboot(void) +{ + sq_scmi_system_off(SCMI_SYS_PWR_COLD_RESET); +} + +static int scmi_ap_core_init(scmi_channel_t *ch) +{ +#if PROGRAMMABLE_RESET_ADDRESS + uint32_t version; + int ret; + + ret = scmi_proto_version(ch, SCMI_AP_CORE_PROTO_ID, &version); + if (ret != SCMI_E_SUCCESS) { + WARN("SCMI AP core protocol version message failed\n"); + return -1; + } + + if (!is_scmi_version_compatible(SCMI_AP_CORE_PROTO_VER, version)) { + WARN("SCMI AP core protocol version 0x%x incompatible with driver version 0x%x\n", + version, SCMI_AP_CORE_PROTO_VER); + return -1; + } + INFO("SCMI AP core protocol version 0x%x detected\n", version); +#endif + return 0; +} + +void __init plat_sq_pwrc_setup(void) +{ + channel.info = &sq_scmi_plat_info; + channel.lock = SQ_SCMI_LOCK_GET_INSTANCE; + sq_scmi_handle = scmi_init(&channel); + if (sq_scmi_handle == NULL) { + ERROR("SCMI Initialization failed\n"); + panic(); + } + if (scmi_ap_core_init(&channel) < 0) { + ERROR("SCMI AP core protocol initialization failed\n"); + panic(); + } +} + +uint32_t sq_scmi_get_draminfo(struct draminfo *info) +{ + scmi_get_draminfo(sq_scmi_handle, info); + + return 0; +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c new file mode 100644 index 0000000..e494022 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "sq_scpi.h" + +/* + * Helper function to get dram information from SCP. + */ +uint32_t sq_scp_get_draminfo(struct draminfo *info) +{ +#if SQ_USE_SCMI_DRIVER + sq_scmi_get_draminfo(info); +#else + scpi_get_draminfo(info); +#endif + return 0; +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c new file mode 100644 index 0000000..0cb75a0 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include + +#include "sq_mhu.h" +#include "sq_scpi.h" + +#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_SQ_SCP_COM_SHARED_MEM_BASE +#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_SQ_SCP_COM_SHARED_MEM_BASE \ + + 0x100) + +#define SCPI_CMD_HEADER_AP_TO_SCP \ + ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP) +#define SCPI_CMD_PAYLOAD_AP_TO_SCP \ + ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t))) + +/* ID of the MHU slot used for the SCPI protocol */ +#define SCPI_MHU_SLOT_ID 0 + +static void scpi_secure_message_start(void) +{ + mhu_secure_message_start(SCPI_MHU_SLOT_ID); +} + +static void scpi_secure_message_send(size_t payload_size) +{ + /* + * Ensure that any write to the SCPI payload area is seen by SCP before + * we write to the MHU register. If these 2 writes were reordered by + * the CPU then SCP would read stale payload data + */ + dmbst(); + + mhu_secure_message_send(SCPI_MHU_SLOT_ID); +} + +static void scpi_secure_message_receive(scpi_cmd_t *cmd) +{ + uint32_t mhu_status; + + assert(cmd != NULL); + + mhu_status = mhu_secure_message_wait(); + + /* Expect an SCPI message, reject any other protocol */ + if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) { + ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", + mhu_status); + panic(); + } + + /* + * Ensure that any read to the SCPI payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); + + memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd)); +} + +static void scpi_secure_message_end(void) +{ + mhu_secure_message_end(SCPI_MHU_SLOT_ID); +} + +int scpi_wait_ready(void) +{ + scpi_cmd_t scpi_cmd; + scpi_status_t status = SCP_OK; + + VERBOSE("Waiting for SCP_READY command...\n"); + + /* Get a message from the SCP */ + scpi_secure_message_start(); + scpi_secure_message_receive(&scpi_cmd); + scpi_secure_message_end(); + + /* We are expecting 'SCP Ready', produce correct error if it's not */ + if (scpi_cmd.id != SCPI_CMD_SCP_READY) { + ERROR("Unexpected SCP command: expected command #%u," + "got command #%u\n", SCPI_CMD_SCP_READY, scpi_cmd.id); + status = SCP_E_SUPPORT; + } else if (scpi_cmd.size != 0) { + ERROR("SCP_READY command has incorrect size: expected 0," + "got %u\n", scpi_cmd.size); + status = SCP_E_SIZE; + } + + VERBOSE("Sending response for SCP_READY command\n"); + + /* + * Send our response back to SCP. + * We are using the same SCPI header, just update the status field. + */ + scpi_cmd.status = status; + scpi_secure_message_start(); + memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd)); + scpi_secure_message_send(0); + scpi_secure_message_end(); + + return status == SCP_OK ? 0 : -1; +} + +void scpi_set_sq_power_state(unsigned int mpidr, scpi_power_state_t cpu_state, + scpi_power_state_t cluster_state, scpi_power_state_t sq_state) +{ + scpi_cmd_t *cmd; + uint32_t state = 0; + uint32_t *payload_addr; + + state |= mpidr & 0x0f; /* CPU ID */ + state |= (mpidr & 0xf00) >> 4; /* Cluster ID */ + state |= cpu_state << 8; + state |= cluster_state << 12; + state |= sq_state << 16; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SET_POWER_STATE; + cmd->set = SCPI_SET_NORMAL; + cmd->sender = 0; + cmd->size = sizeof(state); + /* Populate the command payload */ + payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; + *payload_addr = state; + scpi_secure_message_send(sizeof(state)); + + /* + * SCP does not reply to this command in order to avoid MHU interrupts + * from the sender, which could interfere with its power state request. + */ + scpi_secure_message_end(); +} + +uint32_t scpi_sys_power_state(scpi_system_state_t system_state) +{ + scpi_cmd_t *cmd; + uint8_t *payload_addr; + scpi_cmd_t response; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SYS_POWER_STATE; + cmd->set = 0; + cmd->sender = 0; + cmd->size = sizeof(*payload_addr); + /* Populate the command payload */ + payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; + *payload_addr = system_state & 0xff; + scpi_secure_message_send(sizeof(*payload_addr)); + + scpi_secure_message_receive(&response); + + scpi_secure_message_end(); + + return response.status; +} + +uint32_t scpi_get_draminfo(struct draminfo *info) +{ + scpi_cmd_t *cmd; + struct { + scpi_cmd_t cmd; + struct draminfo info; + } response; + uint32_t mhu_status; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_GET_DRAMINFO; + cmd->set = SCPI_SET_EXTENDED; + cmd->sender = 0; + cmd->size = 0; + + scpi_secure_message_send(0); + + mhu_status = mhu_secure_message_wait(); + + /* Expect an SCPI message, reject any other protocol */ + if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) { + ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", + mhu_status); + panic(); + } + + /* + * Ensure that any read to the SCPI payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); + + memcpy(&response, (void *)SCPI_SHARED_MEM_SCP_TO_AP, sizeof(response)); + + scpi_secure_message_end(); + + if (response.cmd.status == SCP_OK) + *info = response.info; + + return response.cmd.status; +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h new file mode 100644 index 0000000..eb6ce5c --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SQ_SCPI_H +#define SQ_SCPI_H + +#include +#include + +/* + * An SCPI command consists of a header and a payload. + * The following structure describes the header. It is 64-bit long. + */ +typedef struct { + /* Command ID */ + uint32_t id : 7; + /* Set ID. Identifies whether this is a standard or extended command. */ + uint32_t set : 1; + /* Sender ID to match a reply. The value is sender specific. */ + uint32_t sender : 8; + /* Size of the payload in bytes (0 - 511) */ + uint32_t size : 9; + uint32_t reserved : 7; + /* + * Status indicating the success of a command. + * See the enum below. + */ + uint32_t status; +} scpi_cmd_t; + +typedef enum { + SCPI_SET_NORMAL = 0, /* Normal SCPI commands */ + SCPI_SET_EXTENDED /* Extended SCPI commands */ +} scpi_set_t; + +enum { + SCP_OK = 0, /* Success */ + SCP_E_PARAM, /* Invalid parameter(s) */ + SCP_E_ALIGN, /* Invalid alignment */ + SCP_E_SIZE, /* Invalid size */ + SCP_E_HANDLER, /* Invalid handler or callback */ + SCP_E_ACCESS, /* Invalid access or permission denied */ + SCP_E_RANGE, /* Value out of range */ + SCP_E_TIMEOUT, /* Time out has ocurred */ + SCP_E_NOMEM, /* Invalid memory area or pointer */ + SCP_E_PWRSTATE, /* Invalid power state */ + SCP_E_SUPPORT, /* Feature not supported or disabled */ + SCPI_E_DEVICE, /* Device error */ + SCPI_E_BUSY, /* Device is busy */ +}; + +typedef uint32_t scpi_status_t; + +typedef enum { + SCPI_CMD_SCP_READY = 0x01, + SCPI_CMD_SET_POWER_STATE = 0x03, + SCPI_CMD_SYS_POWER_STATE = 0x05 +} scpi_command_t; + +typedef enum { + scpi_power_on = 0, + scpi_power_retention = 1, + scpi_power_off = 3, +} scpi_power_state_t; + +typedef enum { + scpi_system_shutdown = 0, + scpi_system_reboot = 1, + scpi_system_reset = 2 +} scpi_system_state_t; + +extern int scpi_wait_ready(void); +extern void scpi_set_sq_power_state(unsigned int mpidr, + scpi_power_state_t cpu_state, + scpi_power_state_t cluster_state, + scpi_power_state_t css_state); +uint32_t scpi_sys_power_state(scpi_system_state_t system_state); +uint32_t scpi_get_draminfo(struct draminfo *info); + +#endif /* SQ_SCPI_H */ diff --git a/arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S b/arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S new file mode 100644 index 0000000..af7a172 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYNQUACER_PLAT_LD_S__ +#define SYNQUACER_PLAT_LD_S__ + +#include + +#define SPM_SHIM_EXCEPTIONS_VMA SP_DRAM + +MEMORY { + SP_DRAM (rw): ORIGIN = PLAT_SQ_SP_PRIV_BASE, LENGTH = PLAT_SQ_SP_PRIV_SIZE +} + +SECTIONS +{ + /* + * Put the page tables in secure DRAM so that the PTW can make cacheable + * accesses, as the core SPM code expects. (The SRAM on SynQuacer does + * not support inner shareable WBWA mappings so it is mapped normal + * non-cacheable) + */ + sp_xlat_table (NOLOAD) : ALIGN(PAGE_SIZE) { + *(sp_xlat_table) + } >SP_DRAM +} + +#endif /* SYNQUACER_PLAT_LD_S__ */ diff --git a/arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S b/arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S new file mode 100644 index 0000000..932b21d --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +/* + * Print CCN registers + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h b/arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h new file mode 100644 index 0000000..49ffbf9 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +/* CPU topology */ +#define PLAT_MAX_CORES_PER_CLUSTER U(2) +#define PLAT_CLUSTER_COUNT U(12) +#define PLATFORM_CORE_COUNT (PLAT_CLUSTER_COUNT * \ + PLAT_MAX_CORES_PER_CLUSTER) + +/* Macros to read the SQ power domain state */ +#define SQ_PWR_LVL0 MPIDR_AFFLVL0 +#define SQ_PWR_LVL1 MPIDR_AFFLVL1 +#define SQ_PWR_LVL2 MPIDR_AFFLVL2 + +#define SQ_CORE_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL0] +#define SQ_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL1] +#define SQ_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\ + (state)->pwr_domain_state[SQ_PWR_LVL2] : 0) + +#define PLAT_MAX_PWR_LVL U(1) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#define SQ_LOCAL_STATE_RUN 0 +#define SQ_LOCAL_STATE_RET 1 +#define SQ_LOCAL_STATE_OFF 2 + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 8 + +#define PLATFORM_STACK_SIZE 0x400 + +#define BL31_BASE 0x04000000 +#define BL31_SIZE 0x00080000 +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +#define BL32_BASE 0xfc000000 +#define BL32_SIZE 0x03c00000 +#define BL32_LIMIT (BL32_BASE + BL32_SIZE) + +#define PLAT_SQ_CCN_BASE 0x32000000 +#define PLAT_SQ_CLUSTER_TO_CCN_ID_MAP \ + 0, /* Cluster 0 */ \ + 18, /* Cluster 1 */ \ + 11, /* Cluster 2 */ \ + 29, /* Cluster 3 */ \ + 35, /* Cluster 4 */ \ + 17, /* Cluster 5 */ \ + 12, /* Cluster 6 */ \ + 30, /* Cluster 7 */ \ + 14, /* Cluster 8 */ \ + 32, /* Cluster 9 */ \ + 15, /* Cluster 10 */ \ + 33 /* Cluster 11 */ + +/* UART related constants */ +#define PLAT_SQ_BOOT_UART_BASE 0x2A400000 +#define PLAT_SQ_BOOT_UART_CLK_IN_HZ 62500000 +#define SQ_CONSOLE_BAUDRATE 115200 + +#define SQ_SYS_CNTCTL_BASE 0x2a430000 + +#define SQ_SYS_TIMCTL_BASE 0x2a810000 +#define PLAT_SQ_NSTIMER_FRAME_ID 0 +#define SQ_SYS_CNT_BASE_NS 0x2a830000 + +#define DRAMINFO_BASE 0x2E00FFC0 + +#define PLAT_SQ_MHU_BASE 0x45000000 + +#define PLAT_SQ_SCP_COM_SHARED_MEM_BASE 0x45400000 +#define SCPI_CMD_GET_DRAMINFO 0x1 + +#define SQ_BOOT_CFG_ADDR 0x45410000 +#define PLAT_SQ_PRIMARY_CPU_SHIFT 8 +#define PLAT_SQ_PRIMARY_CPU_BIT_WIDTH 6 + +#define PLAT_SQ_GICD_BASE 0x30000000 +#define PLAT_SQ_GICR_BASE 0x30400000 + +#define PLAT_SQ_GPIO_BASE 0x51000000 + +#define PLAT_SPM_BUF_BASE (BL32_LIMIT - 32 * PLAT_SPM_BUF_SIZE) +#define PLAT_SPM_BUF_SIZE ULL(0x10000) +#define PLAT_SPM_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) + +#define PLAT_SP_IMAGE_NS_BUF_BASE BL32_LIMIT +#define PLAT_SP_IMAGE_NS_BUF_SIZE ULL(0x200000) +#define PLAT_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) + +#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x10000) +#define PLAT_SP_IMAGE_STACK_SIZE (32 * PLAT_SP_IMAGE_STACK_PCPU_SIZE) +#define PLAT_SP_IMAGE_STACK_BASE (PLAT_SQ_SP_HEAP_BASE + PLAT_SQ_SP_HEAP_SIZE) + +#define PLAT_SQ_SP_IMAGE_SIZE ULL(0x200000) +#define PLAT_SQ_SP_IMAGE_MMAP MAP_REGION2(BL32_BASE, BL32_BASE, \ + PLAT_SQ_SP_IMAGE_SIZE, \ + MT_CODE | MT_SECURE | \ + MT_USER, PAGE_SIZE) + +#define PLAT_SQ_SP_HEAP_BASE (BL32_BASE + PLAT_SQ_SP_IMAGE_SIZE) +#define PLAT_SQ_SP_HEAP_SIZE ULL(0x800000) + +#define PLAT_SQ_SP_IMAGE_RW_MMAP MAP_REGION2(PLAT_SQ_SP_HEAP_BASE, \ + PLAT_SQ_SP_HEAP_BASE, \ + (PLAT_SQ_SP_HEAP_SIZE + \ + PLAT_SP_IMAGE_STACK_SIZE), \ + MT_RW_DATA | MT_SECURE | \ + MT_USER, PAGE_SIZE) + +#define PLAT_SQ_SP_PRIV_BASE (PLAT_SP_IMAGE_STACK_BASE + \ + PLAT_SP_IMAGE_STACK_SIZE) +#define PLAT_SQ_SP_PRIV_SIZE ULL(0x40000) + +#define PLAT_SP_PRI 0x20 +#define PLAT_PRI_BITS 2 +#define PLAT_SPM_COOKIE_0 ULL(0) +#define PLAT_SPM_COOKIE_1 ULL(0) + +/* Total number of memory regions with distinct properties */ +#define PLAT_SP_IMAGE_NUM_MEM_REGIONS 6 + +#define PLAT_SP_IMAGE_MMAP_REGIONS 30 +#define PLAT_SP_IMAGE_MAX_XLAT_TABLES 20 +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "sp_xlat_table" +#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME "sp_xlat_table" + +#define PLAT_SQ_UART1_BASE PLAT_SQ_BOOT_UART_BASE +#define PLAT_SQ_UART1_SIZE ULL(0x1000) +#define PLAT_SQ_UART1_MMAP MAP_REGION_FLAT(PLAT_SQ_UART1_BASE, \ + PLAT_SQ_UART1_SIZE, \ + MT_DEVICE | MT_RW | \ + MT_NS | MT_PRIVILEGED) + +#define PLAT_SQ_PERIPH_BASE 0x50000000 +#define PLAT_SQ_PERIPH_SIZE ULL(0x8000000) +#define PLAT_SQ_PERIPH_MMAP MAP_REGION_FLAT(PLAT_SQ_PERIPH_BASE, \ + PLAT_SQ_PERIPH_SIZE, \ + MT_DEVICE | MT_RW | \ + MT_NS | MT_USER) + +#define PLAT_SQ_FLASH_BASE 0x08000000 +#define PLAT_SQ_FLASH_SIZE ULL(0x8000000) +#define PLAT_SQ_FLASH_MMAP MAP_REGION_FLAT(PLAT_SQ_FLASH_BASE, \ + PLAT_SQ_FLASH_SIZE, \ + MT_DEVICE | MT_RW | \ + MT_NS | MT_USER) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h b/arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h new file mode 100644 index 0000000..b09d22a --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SQ_COMMON_H +#define SQ_COMMON_H + +#include + +#include +#include + +struct draminfo { + uint32_t num_regions; + uint32_t reserved; + uint64_t base1; + uint64_t size1; + uint64_t base2; + uint64_t size2; + uint64_t base3; + uint64_t size3; +}; + +uint32_t sq_scp_get_draminfo(struct draminfo *info); + +void plat_sq_pwrc_setup(void); + +void plat_sq_interconnect_init(void); +void plat_sq_interconnect_enter_coherency(void); +void plat_sq_interconnect_exit_coherency(void); + +unsigned int sq_calc_core_pos(u_register_t mpidr); + +void sq_gic_driver_init(void); +void sq_gic_init(void); +void sq_gic_cpuif_enable(void); +void sq_gic_cpuif_disable(void); +void sq_gic_pcpu_init(void); + +void sq_mmap_setup(uintptr_t total_base, size_t total_size, + const struct mmap_region *mmap); + +/* SCMI API for power management by SCP */ +void sq_scmi_off(const struct psci_power_state *target_state); +void sq_scmi_on(u_register_t mpidr); +void __dead2 sq_scmi_sys_shutdown(void); +void __dead2 sq_scmi_sys_reboot(void); +void __dead2 sq_scmi_system_off(int state); +/* SCMI API for vendor specific protocol */ +uint32_t sq_scmi_get_draminfo(struct draminfo *info); + +#endif /* SQ_COMMON_H */ diff --git a/arm-trusted-firmware/plat/socionext/synquacer/platform.mk b/arm-trusted-firmware/plat/socionext/synquacer/platform.mk new file mode 100644 index 0000000..dcd5d31 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/platform.mk @@ -0,0 +1,69 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +override RESET_TO_BL31 := 1 +override PROGRAMMABLE_RESET_ADDRESS := 1 +override USE_COHERENT_MEM := 1 +override SEPARATE_CODE_AND_RODATA := 1 +override ENABLE_SVE_FOR_NS := 0 +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_855873 := 1 +# Enable SCMI support +SQ_USE_SCMI_DRIVER ?= 0 + +# Libraries +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_PATH := plat/socionext/synquacer +PLAT_INCLUDES := -I$(PLAT_PATH)/include \ + -I$(PLAT_PATH)/drivers/scpi \ + -I$(PLAT_PATH)/drivers/mhu \ + -Idrivers/arm/css/scmi \ + -Idrivers/arm/css/scmi/vendor + +PLAT_BL_COMMON_SOURCES += $(PLAT_PATH)/sq_helpers.S \ + drivers/arm/pl011/aarch64/pl011_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${XLAT_TABLES_LIB_SRCS} + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +BL31_SOURCES += drivers/arm/ccn/ccn.c \ + ${GICV3_SOURCES} \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + $(PLAT_PATH)/sq_bl31_setup.c \ + $(PLAT_PATH)/sq_ccn.c \ + $(PLAT_PATH)/sq_topology.c \ + $(PLAT_PATH)/sq_psci.c \ + $(PLAT_PATH)/sq_gicv3.c \ + $(PLAT_PATH)/sq_xlat_setup.c \ + $(PLAT_PATH)/drivers/scp/sq_scp.c + +ifeq (${SQ_USE_SCMI_DRIVER},0) +BL31_SOURCES += $(PLAT_PATH)/drivers/scpi/sq_scpi.c \ + $(PLAT_PATH)/drivers/mhu/sq_mhu.c +else +BL31_SOURCES += $(PLAT_PATH)/drivers/scp/sq_scmi.c \ + drivers/arm/css/scmi/scmi_common.c \ + drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \ + drivers/arm/css/scmi/scmi_sys_pwr_proto.c \ + drivers/arm/css/scmi/vendor/scmi_sq.c \ + drivers/arm/css/mhu/css_mhu_doorbell.c +endif + +ifeq (${SPM_MM},1) +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +BL31_SOURCES += $(PLAT_PATH)/sq_spm.c +endif + +ifeq (${SQ_USE_SCMI_DRIVER},1) +$(eval $(call add_define,SQ_USE_SCMI_DRIVER)) +endif diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c new file mode 100644 index 0000000..a7a0ce0 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +static console_t console; +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_START__, SPM_SHIM_EXCEPTIONS_START); +IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_END__, SPM_SHIM_EXCEPTIONS_END); +IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_LMA__, SPM_SHIM_EXCEPTIONS_LMA); + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + + /* Read the frequency from Frequency modes table */ + counter_base_frequency = mmio_read_32(SQ_SYS_CNTCTL_BASE + CNTFID_OFF); + + /* The first entry of the frequency modes table must not be 0 */ + if (counter_base_frequency == 0) + panic(); + + return counter_base_frequency; +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + assert(sec_state_is_valid(type)); + return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info; +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t sq_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +uint32_t sq_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* Initialize the console to provide early debug support */ + (void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE, + PLAT_SQ_BOOT_UART_CLK_IN_HZ, + SQ_CONSOLE_BAUDRATE, &console); + + console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME); + + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(arg0 == 0U); + assert(arg1 == 0U); + + /* Initialize power controller before setting up topology */ + plat_sq_pwrc_setup(); + +#ifdef SPD_opteed + struct draminfo di = {0}; + + sq_scp_get_draminfo(&di); + + /* + * Check if OP-TEE has been loaded in Secure RAM allocated + * from DRAM1 region + */ + if ((di.base1 + di.size1) <= BL32_BASE) { + NOTICE("OP-TEE has been loaded by SCP firmware\n"); + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = sq_get_spsr_for_bl32_entry(); + } else { + NOTICE("OP-TEE has not been loaded by SCP firmware\n"); + } +#endif /* SPD_opteed */ + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = PRELOADED_BL33_BASE; + bl33_image_ep_info.spsr = sq_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +static void sq_configure_sys_timer(void) +{ + unsigned int reg_val; + unsigned int freq_val = plat_get_syscnt_freq2(); + + reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); + reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); + reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); + mmio_write_32(SQ_SYS_TIMCTL_BASE + + CNTACR_BASE(PLAT_SQ_NSTIMER_FRAME_ID), reg_val); + + reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_SQ_NSTIMER_FRAME_ID)); + mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTNSAR, reg_val); + + /* Initialize CNTFRQ register in CNTCTLBase frame */ + mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val); + + /* + * Initialize CNTFRQ register in Non-secure CNTBase frame. + * This is required for SynQuacer, because it does not + * follow ARM ARM in that the value updated in CNTFRQ is not + * reflected in CNTBASEN_CNTFRQ. Hence update the value manually. + */ + mmio_write_32(SQ_SYS_CNT_BASE_NS + CNTBASEN_CNTFRQ, freq_val); +} + +void bl31_platform_setup(void) +{ + /* Initialize the CCN interconnect */ + plat_sq_interconnect_init(); + plat_sq_interconnect_enter_coherency(); + + /* Initialize the GIC driver, cpu and distributor interfaces */ + sq_gic_driver_init(); + sq_gic_init(); + + /* Enable and initialize the System level generic timer */ + mmio_write_32(SQ_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0U) | CNTCR_EN); + + /* Allow access to the System counter timer module */ + sq_configure_sys_timer(); +} + +void bl31_plat_runtime_setup(void) +{ + struct draminfo *di = (struct draminfo *)(unsigned long)DRAMINFO_BASE; + + sq_scp_get_draminfo(di); +} + +void bl31_plat_arch_setup(void) +{ + static const mmap_region_t secure_partition_mmap[] = { +#if SPM_MM + MAP_REGION_FLAT(PLAT_SPM_BUF_BASE, + PLAT_SPM_BUF_SIZE, + MT_RW_DATA | MT_SECURE), + MAP_REGION_FLAT(PLAT_SQ_SP_PRIV_BASE, + PLAT_SQ_SP_PRIV_SIZE, + MT_RW_DATA | MT_SECURE), +#endif + {0}, + }; + + sq_mmap_setup(BL31_BASE, BL31_SIZE, secure_partition_mmap); + enable_mmu_el3(XLAT_TABLE_NC); + +#if SPM_MM + memcpy((void *)SPM_SHIM_EXCEPTIONS_START, + (void *)SPM_SHIM_EXCEPTIONS_LMA, + (uintptr_t)SPM_SHIM_EXCEPTIONS_END - + (uintptr_t)SPM_SHIM_EXCEPTIONS_START); +#endif +} + +void bl31_plat_enable_mmu(uint32_t flags) +{ + enable_mmu_el3(flags | XLAT_TABLE_NC); +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c new file mode 100644 index 0000000..fa6ea87 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static const unsigned char master_to_rn_id_map[] = { + PLAT_SQ_CLUSTER_TO_CCN_ID_MAP +}; + +static const ccn_desc_t sq_ccn_desc = { + .periphbase = PLAT_SQ_CCN_BASE, + .num_masters = ARRAY_SIZE(master_to_rn_id_map), + .master_to_rn_id_map = master_to_rn_id_map +}; + +/****************************************************************************** + * Helper function to initialize SQ CCN driver. + *****************************************************************************/ +void plat_sq_interconnect_init(void) +{ + ccn_init(&sq_ccn_desc); +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_sq_interconnect_enter_coherency(void) +{ + ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_sq_interconnect_exit_coherency(void) +{ + ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c new file mode 100644 index 0000000..05318e3 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#include "sq_common.h" + +static uintptr_t sq_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t sq_interrupt_props[] = { + /* G0 interrupts */ + + /* SGI0 */ + INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + /* SGI6 */ + INTR_PROP_DESC(14, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + + /* G1S interrupts */ + + /* Timer */ + INTR_PROP_DESC(29, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_LEVEL), + /* SGI1 */ + INTR_PROP_DESC(9, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI2 */ + INTR_PROP_DESC(10, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI3 */ + INTR_PROP_DESC(11, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI4 */ + INTR_PROP_DESC(12, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI5 */ + INTR_PROP_DESC(13, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI7 */ + INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE) +}; + +static unsigned int sq_mpidr_to_core_pos(u_register_t mpidr) +{ + return plat_core_pos_by_mpidr(mpidr); +} + +static const struct gicv3_driver_data sq_gic_driver_data = { + .gicd_base = PLAT_SQ_GICD_BASE, + .gicr_base = PLAT_SQ_GICR_BASE, + .interrupt_props = sq_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(sq_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = sq_rdistif_base_addrs, + .mpidr_to_core_pos = sq_mpidr_to_core_pos, +}; + +void sq_gic_driver_init(void) +{ + gicv3_driver_init(&sq_gic_driver_data); +} + +void sq_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void sq_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void sq_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void sq_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S b/arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S new file mode 100644 index 0000000..7a2d97b --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .global sq_calc_core_pos + .global plat_my_core_pos + .global platform_mem_init + .global plat_is_my_cpu_primary + .global plat_secondary_cold_boot_setup + .global plat_crash_console_init + .global plat_crash_console_putc + .global plat_crash_console_flush + +/* + * unsigned int sq_calc_core_pos(u_register_t mpidr) + * core_pos = (cluster_id * max_cpus_per_cluster) + core_id + */ +func sq_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, lsr #7 + ret +endfunc sq_calc_core_pos + +func plat_my_core_pos + mrs x0, mpidr_el1 + b sq_calc_core_pos +endfunc plat_my_core_pos + +func platform_mem_init + ret +endfunc platform_mem_init + +/* + * Secondary CPUs are placed in a holding pen, waiting for their mailbox + * to be populated. Note that all CPUs share the same mailbox ; therefore, + * populating it will release all CPUs from their holding pen. If + * finer-grained control is needed then this should be handled in the + * code that secondary CPUs jump to. + */ +func plat_secondary_cold_boot_setup + ldr x0, sq_sec_entrypoint + + /* Wait until the mailbox gets populated */ +poll_mailbox: + cbz x0, 1f + br x0 +1: + wfe + b poll_mailbox +endfunc plat_secondary_cold_boot_setup + +/* + * Find out whether the current cpu is the primary + * cpu (applicable only after a cold boot) + */ +func plat_is_my_cpu_primary + mov x9, x30 + bl plat_my_core_pos + ldr x1, =SQ_BOOT_CFG_ADDR + ldr x1, [x1] + ubfx x1, x1, #PLAT_SQ_PRIMARY_CPU_SHIFT, \ + #PLAT_SQ_PRIMARY_CPU_BIT_WIDTH + cmp x0, x1 + cset w0, eq + ret x9 +endfunc plat_is_my_cpu_primary + +/* + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + */ +func plat_crash_console_init + mov_imm x0, PLAT_SQ_BOOT_UART_BASE + mov_imm x1, PLAT_SQ_BOOT_UART_CLK_IN_HZ + mov_imm x2, SQ_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + +/* + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + */ +func plat_crash_console_putc + mov_imm x1, PLAT_SQ_BOOT_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + +/* + * void plat_crash_console_flush(int c) + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + */ +func plat_crash_console_flush + mov_imm x0, PLAT_SQ_BOOT_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c new file mode 100644 index 0000000..3062f63 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c @@ -0,0 +1,207 @@ +/* + * 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 + +#include +#include "sq_scpi.h" + +uintptr_t sq_sec_entrypoint; + +int sq_pwr_domain_on(u_register_t mpidr) +{ +#if SQ_USE_SCMI_DRIVER + sq_scmi_on(mpidr); +#else + /* + * SCP takes care of powering up parent power domains so we + * only need to care about level 0 + */ + scpi_set_sq_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); +#endif + + return PSCI_E_SUCCESS; +} + +static void sq_pwr_domain_on_finisher_common( + const psci_power_state_t *target_state) +{ + assert(SQ_CORE_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF); + + /* + * Perform the common cluster specific operations i.e enable coherency + * if this cluster was off. + */ + if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) + plat_sq_interconnect_enter_coherency(); +} + +void sq_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* Assert that the system power domain need not be initialized */ + assert(SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_RUN); + + sq_pwr_domain_on_finisher_common(target_state); + + /* Program the gic per-cpu distributor or re-distributor interface */ + sq_gic_pcpu_init(); + + /* Enable the gic cpu interface */ + sq_gic_cpuif_enable(); +} + +#if !SQ_USE_SCMI_DRIVER +static void sq_power_down_common(const psci_power_state_t *target_state) +{ + uint32_t cluster_state = scpi_power_on; + uint32_t system_state = scpi_power_on; + + /* Prevent interrupts from spuriously waking up this cpu */ + sq_gic_cpuif_disable(); + + /* Check if power down at system power domain level is requested */ + if (SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) + system_state = scpi_power_retention; + + /* Cluster is to be turned off, so disable coherency */ + if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) { + plat_sq_interconnect_exit_coherency(); + cluster_state = scpi_power_off; + } + + /* + * Ask the SCP to power down the appropriate components depending upon + * their state. + */ + scpi_set_sq_power_state(read_mpidr_el1(), + scpi_power_off, + cluster_state, + system_state); +} +#endif + +void sq_pwr_domain_off(const psci_power_state_t *target_state) +{ +#if SQ_USE_SCMI_DRIVER + /* Prevent interrupts from spuriously waking up this cpu */ + sq_gic_cpuif_disable(); + + /* Cluster is to be turned off, so disable coherency */ + if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) { + plat_sq_interconnect_exit_coherency(); + } + + sq_scmi_off(target_state); +#else + sq_power_down_common(target_state); +#endif +} + +void __dead2 sq_system_off(void) +{ +#if SQ_USE_SCMI_DRIVER + sq_scmi_sys_shutdown(); +#else + volatile uint32_t *gpio = (uint32_t *)PLAT_SQ_GPIO_BASE; + + /* set PD[9] high to power off the system */ + gpio[5] |= 0x2; /* set output */ + gpio[1] |= 0x2; /* set high */ + dmbst(); + + generic_delay_timer_init(); + + mdelay(1); + + while (1) { + gpio[1] &= ~0x2; /* set low */ + dmbst(); + + mdelay(1); + + gpio[1] |= 0x2; /* set high */ + dmbst(); + + mdelay(100); + } + + wfi(); + ERROR("SQ System Off: operation not handled.\n"); + panic(); +#endif +} + +void __dead2 sq_system_reset(void) +{ +#if SQ_USE_SCMI_DRIVER + sq_scmi_sys_reboot(); +#else + uint32_t response; + + /* Send the system reset request to the SCP */ + response = scpi_sys_power_state(scpi_system_reboot); + + if (response != SCP_OK) { + ERROR("SQ System Reset: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("SQ System Reset: operation not handled.\n"); + panic(); +#endif +} + +void sq_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr; + + assert(cpu_state == SQ_LOCAL_STATE_RET); + + scr = read_scr_el3(); + /* Enable PhysicalIRQ bit for NS world to wake the CPU */ + write_scr_el3(scr | SCR_IRQ_BIT); + isb(); + dsb(); + wfi(); + + /* + * Restore SCR to the original value, synchronisation of scr_el3 is + * done by eret while el3_exit to save some execution cycles. + */ + write_scr_el3(scr); +} + +const plat_psci_ops_t sq_psci_ops = { + .pwr_domain_on = sq_pwr_domain_on, + .pwr_domain_off = sq_pwr_domain_off, + .pwr_domain_on_finish = sq_pwr_domain_on_finish, + .cpu_standby = sq_cpu_standby, + .system_off = sq_system_off, + .system_reset = sq_system_reset, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + sq_sec_entrypoint = sec_entrypoint; + flush_dcache_range((uint64_t)&sq_sec_entrypoint, + sizeof(sq_sec_entrypoint)); + + *psci_ops = &sq_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c new file mode 100644 index 0000000..7bea111 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +static const mmap_region_t plat_arm_secure_partition_mmap[] = { + PLAT_SQ_FLASH_MMAP, + PLAT_SQ_UART1_MMAP, + PLAT_SQ_PERIPH_MMAP, + PLAT_SQ_SP_IMAGE_MMAP, + PLAT_SP_IMAGE_NS_BUF_MMAP, + PLAT_SQ_SP_IMAGE_RW_MMAP, + PLAT_SPM_SPM_BUF_EL0_MMAP, + {0} +}; + +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static spm_mm_mp_info_t sp_mp_info[] = { + {0x80000000, 0}, {0x80000001, 0}, {0x80000100, 0}, {0x80000101, 0}, + {0x80000200, 0}, {0x80000201, 0}, {0x80000300, 0}, {0x80000301, 0}, + {0x80000400, 0}, {0x80000401, 0}, {0x80000500, 0}, {0x80000501, 0}, + {0x80000600, 0}, {0x80000601, 0}, {0x80000700, 0}, {0x80000701, 0}, + {0x80000800, 0}, {0x80000801, 0}, {0x80000900, 0}, {0x80000901, 0}, + {0x80000a00, 0}, {0x80000a01, 0}, {0x80000b00, 0}, {0x80000b01, 0}, +}; + +const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = BL32_BASE, + .sp_mem_limit = BL32_LIMIT, + .sp_image_base = BL32_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = PLAT_SQ_SP_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = PLAT_SQ_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = PLAT_SQ_SP_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = PLAT_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = sp_mp_info, +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} + +static ehf_pri_desc_t sq_exceptions[] = { + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI), +}; +EHF_REGISTER_PRIORITIES(sq_exceptions, ARRAY_SIZE(sq_exceptions), PLAT_PRI_BITS); diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c new file mode 100644 index 0000000..359997a --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +unsigned char sq_pd_tree_desc[PLAT_CLUSTER_COUNT + 1]; + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + if (cluster_id >= PLAT_CLUSTER_COUNT) + return -1; + + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + if (cpu_id >= PLAT_MAX_CORES_PER_CLUSTER) + return -1; + + return sq_calc_core_pos(mpidr); +} + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + sq_pd_tree_desc[0] = PLAT_CLUSTER_COUNT; + + for (i = 0; i < PLAT_CLUSTER_COUNT; i++) + sq_pd_tree_desc[i + 1] = PLAT_MAX_CORES_PER_CLUSTER; + + return sq_pd_tree_desc; +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c new file mode 100644 index 0000000..5d1669d --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#define SQ_REG_REGION_BASE 0x20000000ULL +#define SQ_REG_REGION_SIZE 0x60000000ULL + +void sq_mmap_setup(uintptr_t total_base, size_t total_size, + const struct mmap_region *mmap) +{ + VERBOSE("Trusted RAM seen by this BL image: %p - %p\n", + (void *)total_base, (void *)(total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, + MT_NON_CACHEABLE | MT_RW | MT_SECURE); + + /* remap the code section */ + VERBOSE("Code region: %p - %p\n", + (void *)BL_CODE_BASE, (void *)BL_CODE_END); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + round_up(BL_CODE_END, PAGE_SIZE) - BL_CODE_BASE, + MT_NON_CACHEABLE | MT_RO | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *)BL_RO_DATA_BASE, (void *)BL_RO_DATA_END); + mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, + round_up(BL_RO_DATA_END, PAGE_SIZE) - BL_RO_DATA_BASE, + (MT_NON_CACHEABLE | MT_RO | MT_EXECUTE_NEVER | + MT_SECURE)); + + /* remap the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *)BL_COHERENT_RAM_BASE, (void *)BL_COHERENT_RAM_END); + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE); + + /* register region */ + mmap_add_region(SQ_REG_REGION_BASE, SQ_REG_REGION_BASE, + SQ_REG_REGION_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + + /* additional regions if needed */ + if (mmap) + mmap_add(mmap); + + init_xlat_tables(); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S b/arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S new file mode 100644 index 0000000..d6d2579 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. 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/arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h b/arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h new file mode 100644 index 0000000..b23386d --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#define PLATFORM_STACK_SIZE 0x1000 + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << (CACHE_WRITEBACK_SHIFT)) + +/* topology */ +#define UNIPHIER_MAX_CPUS_PER_CLUSTER U(4) +#define UNIPHIER_CLUSTER_COUNT U(2) + +#define PLATFORM_CORE_COUNT \ + ((UNIPHIER_MAX_CPUS_PER_CLUSTER) * (UNIPHIER_CLUSTER_COUNT)) + +#define PLAT_MAX_PWR_LVL U(1) + +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_RET_STATE U(1) + +#define UNIPHIER_BL2_OFFSET UL(0x00000000) +#define UNIPHIER_BL2_MAX_SIZE UL(0x00080000) + +/* 0x00080000-0x01000000: reserved for DSP */ + +#define UNIPHIER_BL31_OFFSET UL(0x01000000) +#define UNIPHIER_BL31_MAX_SIZE UL(0x00080000) + +#define UNIPHIER_BL32_OFFSET UL(0x01080000) +#define UNIPHIER_BL32_MAX_SIZE UL(0x00100000) + +/* + * The link addresses are determined by UNIPHIER_MEM_BASE + offset. + * When ENABLE_PIE is set, all the TF images can be loaded anywhere, so + * UNIPHIER_MEM_BASE is arbitrary. + * + * When ENABLE_PIE is unset, UNIPHIER_MEM_BASE should be chosen so that + * BL2_BASE matches to the physical address where BL2 is loaded, that is, + * UNIPHIER_MEM_BASE should be the base address of the DRAM region. + */ +#define UNIPHIER_MEM_BASE UL(0x00000000) + +#define BL2_BASE (UNIPHIER_MEM_BASE + UNIPHIER_BL2_OFFSET) +#define BL2_LIMIT (BL2_BASE + UNIPHIER_BL2_MAX_SIZE) + +#define BL31_BASE (UNIPHIER_MEM_BASE + UNIPHIER_BL31_OFFSET) +#define BL31_LIMIT (BL31_BASE + UNIPHIER_BL31_MAX_SIZE) + +#define BL32_BASE (UNIPHIER_MEM_BASE + UNIPHIER_BL32_OFFSET) +#define BL32_LIMIT (BL32_BASE + UNIPHIER_BL32_MAX_SIZE) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +#define MAX_XLAT_TABLES 9 +#define MAX_MMAP_REGIONS 13 + +#define MAX_IO_HANDLES 2 +#define MAX_IO_DEVICES 2 +#define MAX_IO_BLOCK_DEVICES U(1) + +#define TSP_SEC_MEM_BASE (BL32_BASE) +#define TSP_SEC_MEM_SIZE ((BL32_LIMIT) - (BL32_BASE)) +#define TSP_IRQ_SEC_PHY_TIMER 29 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/socionext/uniphier/platform.mk b/arm-trusted-firmware/plat/socionext/uniphier/platform.mk new file mode 100644 index 0000000..6edd181 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/platform.mk @@ -0,0 +1,140 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +override BL2_AT_EL3 := 1 +override COLD_BOOT_SINGLE_CPU := 1 +override PROGRAMMABLE_RESET_ADDRESS := 1 +override USE_COHERENT_MEM := 1 +override ENABLE_SVE_FOR_NS := 0 + +# Disabling ENABLE_PIE saves memory footprint a lot, but you need to adjust +# UNIPHIER_MEM_BASE so that all TF images are loaded at their link addresses. +override ENABLE_PIE := 1 + +ALLOW_RO_XLAT_TABLES := 1 + +ifeq ($(ALLOW_RO_XLAT_TABLES),1) +BL31_CPPFLAGS += -DPLAT_RO_XLAT_TABLES +BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES +endif + +# The dynamic xlat table is only used in BL2 +BL2_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + +# Cortex-A53 revision r0p4-51rel0 +# needed for LD20, unneeded for LD11, PXs3 (no ACE) +ERRATA_A53_855873 := 1 + +FIP_ALIGN := 512 + +ifeq ($(NEED_BL32),yes) +$(eval $(call add_define,UNIPHIER_LOAD_BL32)) +endif + +# Libraries +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_PATH := plat/socionext/uniphier +PLAT_INCLUDES := -I$(PLAT_PATH)/include + +# common sources for BL2, BL31 (and BL32 if SPD=tspd) +PLAT_BL_COMMON_SOURCES += plat/common/aarch64/crash_console_helpers.S \ + $(PLAT_PATH)/uniphier_console.S \ + $(PLAT_PATH)/uniphier_console_setup.c \ + $(PLAT_PATH)/uniphier_helpers.S \ + $(PLAT_PATH)/uniphier_soc_info.c \ + $(PLAT_PATH)/uniphier_xlat_setup.c \ + ${XLAT_TABLES_LIB_SRCS} + +BL2_SOURCES += common/desc_image_load.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + $(PLAT_PATH)/uniphier_bl2_setup.c \ + $(PLAT_PATH)/uniphier_boot_device.c \ + $(PLAT_PATH)/uniphier_emmc.c \ + $(PLAT_PATH)/uniphier_image_desc.c \ + $(PLAT_PATH)/uniphier_io_storage.c \ + $(PLAT_PATH)/uniphier_nand.c \ + $(PLAT_PATH)/uniphier_scp.c \ + $(PLAT_PATH)/uniphier_usb.c + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +BL31_SOURCES += drivers/arm/cci/cci.c \ + ${GICV3_SOURCES} \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + $(PLAT_PATH)/uniphier_bl31_setup.c \ + $(PLAT_PATH)/uniphier_boot_device.c \ + $(PLAT_PATH)/uniphier_cci.c \ + $(PLAT_PATH)/uniphier_gicv3.c \ + $(PLAT_PATH)/uniphier_psci.c \ + $(PLAT_PATH)/uniphier_scp.c \ + $(PLAT_PATH)/uniphier_smp.S \ + $(PLAT_PATH)/uniphier_syscnt.c \ + $(PLAT_PATH)/uniphier_topology.c + +ifeq (${TRUSTED_BOARD_BOOT},1) + +include drivers/auth/mbedtls/mbedtls_crypto.mk +include drivers/auth/mbedtls/mbedtls_x509.mk + +BL2_SOURCES += drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c \ + drivers/auth/tbbr/tbbr_cot_bl2.c \ + plat/common/tbbr/plat_tbbr.c \ + $(PLAT_PATH)/uniphier_rotpk.S \ + $(PLAT_PATH)/uniphier_tbbr.c + +ROT_KEY = $(BUILD_PLAT)/rot_key.pem +ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + +$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) +$(BUILD_PLAT)/bl2/uniphier_rotpk.o: $(ROTPK_HASH) + +certificates: $(ROT_KEY) +$(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + $(Q)openssl genrsa 2048 > $@ 2>/dev/null + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null + +endif + +ifeq (${FIP_GZIP},1) + +include lib/zlib/zlib.mk + +BL2_SOURCES += common/image_decompress.c \ + $(ZLIB_SOURCES) + +$(eval $(call add_define,UNIPHIER_DECOMPRESS_GZIP)) + +# compress all images loaded by BL2 +SCP_BL2_PRE_TOOL_FILTER := GZIP +BL31_PRE_TOOL_FILTER := GZIP +BL32_PRE_TOOL_FILTER := GZIP +BL33_PRE_TOOL_FILTER := GZIP + +endif + +.PHONY: bl2_gzip +bl2_gzip: $(BUILD_PLAT)/bl2.bin.gz +%.gz: % + @echo " GZIP $@" + $(Q)gzip -n -f -9 $< --stdout > $@ diff --git a/arm-trusted-firmware/plat/socionext/uniphier/tsp/tsp-uniphier.mk b/arm-trusted-firmware/plat/socionext/uniphier/tsp/tsp-uniphier.mk new file mode 100644 index 0000000..54d4f51 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/tsp/tsp-uniphier.mk @@ -0,0 +1,9 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += plat/common/plat_gicv3.c \ + plat/common/aarch64/platform_mp_stack.S \ + $(PLAT_PATH)/tsp/uniphier_tsp_setup.c diff --git a/arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c new file mode 100644 index 0000000..4bbb259 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#include "../uniphier.h" + +static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN; + +void tsp_early_platform_setup(void) +{ + uniphier_soc = uniphier_get_soc_id(); + if (uniphier_soc == UNIPHIER_SOC_UNKNOWN) + plat_error_handler(-ENOTSUP); + + uniphier_console_setup(uniphier_soc); +} + +void tsp_platform_setup(void) +{ +} + +void tsp_plat_arch_setup(void) +{ + uniphier_mmap_setup(uniphier_soc); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier.h b/arm-trusted-firmware/plat/socionext/uniphier/uniphier.h new file mode 100644 index 0000000..ee520ad --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UNIPHIER_H +#define UNIPHIER_H + +#include +#include + +unsigned int uniphier_get_soc_type(void); +unsigned int uniphier_get_soc_model(void); +unsigned int uniphier_get_soc_revision(void); +unsigned int uniphier_get_soc_id(void); + +#define UNIPHIER_SOC_LD11 0 +#define UNIPHIER_SOC_LD20 1 +#define UNIPHIER_SOC_PXS3 2 +#define UNIPHIER_SOC_UNKNOWN 0xffffffff + +unsigned int uniphier_get_boot_device(unsigned int soc); + +#define UNIPHIER_BOOT_DEVICE_EMMC 0 +#define UNIPHIER_BOOT_DEVICE_NAND 1 +#define UNIPHIER_BOOT_DEVICE_NOR 2 +#define UNIPHIER_BOOT_DEVICE_SD 3 +#define UNIPHIER_BOOT_DEVICE_USB 4 +#define UNIPHIER_BOOT_DEVICE_RSV 0xffffffff + +unsigned int uniphier_get_boot_master(unsigned int soc); + +#define UNIPHIER_BOOT_MASTER_THIS 0 +#define UNIPHIER_BOOT_MASTER_SCP 1 +#define UNIPHIER_BOOT_MASTER_EXT 2 + +void uniphier_console_setup(unsigned int soc); + +struct io_block_dev_spec; +int uniphier_emmc_init(unsigned int soc, + struct io_block_dev_spec **block_dev_spec); +int uniphier_nand_init(unsigned int soc, + struct io_block_dev_spec **block_dev_spec); +int uniphier_usb_init(unsigned int soc, + struct io_block_dev_spec **block_dev_spec); + +int uniphier_io_setup(unsigned int soc, uintptr_t mem_base); + +void uniphier_init_image_descs(uintptr_t mem_base); +struct image_info; +struct image_info *uniphier_get_image_info(unsigned int image_id); + +int uniphier_scp_is_running(void); +void uniphier_scp_start(uint32_t scp_base); +void uniphier_scp_open_com(void); +void uniphier_scp_system_off(void); +void uniphier_scp_system_reset(void); + +void uniphier_mmap_setup(unsigned int soc); + +void uniphier_cci_init(unsigned int soc); +void uniphier_cci_enable(void); +void uniphier_cci_disable(void); + +void uniphier_gic_driver_init(unsigned int soc); +void uniphier_gic_init(void); +void uniphier_gic_cpuif_enable(void); +void uniphier_gic_cpuif_disable(void); +void uniphier_gic_pcpu_init(void); + +void uniphier_psci_init(unsigned int soc); + +unsigned int uniphier_calc_core_pos(u_register_t mpidr); + +#endif /* UNIPHIER_H */ diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c new file mode 100644 index 0000000..4524610 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c @@ -0,0 +1,166 @@ +/* + * 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 +#ifdef UNIPHIER_DECOMPRESS_GZIP +#include +#endif + +#include "uniphier.h" + +#define UNIPHIER_IMAGE_BUF_OFFSET 0x03800000UL +#define UNIPHIER_IMAGE_BUF_SIZE 0x00800000UL + +static uintptr_t uniphier_mem_base = UNIPHIER_MEM_BASE; +static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN; +static int uniphier_bl2_kick_scp; + +void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1, + u_register_t x2, u_register_t x3) +{ + uniphier_soc = uniphier_get_soc_id(); + if (uniphier_soc == UNIPHIER_SOC_UNKNOWN) + plat_error_handler(-ENOTSUP); + + uniphier_console_setup(uniphier_soc); +} + +void bl2_el3_plat_arch_setup(void) +{ + int skip_scp = 0; + int ret; + + uniphier_mmap_setup(uniphier_soc); + + /* add relocation offset (run-time-address - link-address) */ + uniphier_mem_base += BL_CODE_BASE - BL2_BASE; + + ret = uniphier_io_setup(uniphier_soc, uniphier_mem_base); + if (ret) { + ERROR("failed to setup io devices\n"); + plat_error_handler(ret); + } + + switch (uniphier_get_boot_master(uniphier_soc)) { + case UNIPHIER_BOOT_MASTER_THIS: + INFO("Booting from this SoC\n"); + skip_scp = 1; + break; + case UNIPHIER_BOOT_MASTER_SCP: + INFO("Booting from on-chip SCP\n"); + if (uniphier_scp_is_running()) { + INFO("SCP is already running. SCP_BL2 load will be skipped.\n"); + skip_scp = 1; + } + + /* + * SCP must be kicked every time even if it is already running + * because it polls this event after the reboot of the backend. + */ + uniphier_bl2_kick_scp = 1; + break; + case UNIPHIER_BOOT_MASTER_EXT: + INFO("Booting from external SCP\n"); + skip_scp = 1; + break; + default: + plat_error_handler(-ENOTSUP); + break; + } + + if (skip_scp) { + struct image_info *image_info; + + image_info = uniphier_get_image_info(SCP_BL2_IMAGE_ID); + image_info->h.attr |= IMAGE_ATTRIB_SKIP_LOADING; + } +} + +void bl2_platform_setup(void) +{ +} + +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +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 bl2_plat_preload_setup(void) +{ +#ifdef UNIPHIER_DECOMPRESS_GZIP + uintptr_t buf_base = uniphier_mem_base + UNIPHIER_IMAGE_BUF_OFFSET; + int ret; + + ret = mmap_add_dynamic_region(buf_base, buf_base, + UNIPHIER_IMAGE_BUF_SIZE, + MT_MEMORY | MT_RW | MT_NS); + if (ret) + plat_error_handler(ret); + + image_decompress_init(buf_base, UNIPHIER_IMAGE_BUF_SIZE, gunzip); +#endif + + uniphier_init_image_descs(uniphier_mem_base); +} + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + struct image_info *image_info; + int ret; + + image_info = uniphier_get_image_info(image_id); + + ret = mmap_add_dynamic_region(image_info->image_base, + image_info->image_base, + image_info->image_max_size, + MT_MEMORY | MT_RW | MT_NS); + if (ret) + return ret; + +#ifdef UNIPHIER_DECOMPRESS_GZIP + image_decompress_prepare(image_info); +#endif + return 0; +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + struct image_info *image_info = uniphier_get_image_info(image_id); +#ifdef UNIPHIER_DECOMPRESS_GZIP + int ret; + + if (!(image_info->h.attr & IMAGE_ATTRIB_SKIP_LOADING)) { + ret = image_decompress(uniphier_get_image_info(image_id)); + if (ret) + return ret; + } +#endif + + if (image_id == SCP_BL2_IMAGE_ID && uniphier_bl2_kick_scp) + uniphier_scp_start(image_info->image_base); + + return 0; +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c new file mode 100644 index 0000000..c2baebd --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c @@ -0,0 +1,89 @@ +/* + * 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 "uniphier.h" + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; +static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + assert(sec_state_is_valid(type)); + return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + void *from_bl2; + + from_bl2 = (void *)arg0; + + bl_params_node_t *bl_params = ((bl_params_t *)from_bl2)->head; + + uniphier_soc = uniphier_get_soc_id(); + if (uniphier_soc == UNIPHIER_SOC_UNKNOWN) + plat_error_handler(-ENOTSUP); + + uniphier_console_setup(uniphier_soc); + + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) + bl32_image_ep_info = *bl_params->ep_info; + + if (bl_params->image_id == BL33_IMAGE_ID) + bl33_image_ep_info = *bl_params->ep_info; + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0) + panic(); +} + +static const uintptr_t uniphier_cntctl_base[] = { + [UNIPHIER_SOC_LD11] = 0x60e00000, + [UNIPHIER_SOC_LD20] = 0x60e00000, + [UNIPHIER_SOC_PXS3] = 0x60e00000, +}; + +void bl31_platform_setup(void) +{ + uintptr_t cntctl_base; + + uniphier_cci_init(uniphier_soc); + uniphier_cci_enable(); + + /* Initialize the GIC driver, cpu and distributor interfaces */ + uniphier_gic_driver_init(uniphier_soc); + uniphier_gic_init(); + + assert(uniphier_soc < ARRAY_SIZE(uniphier_cntctl_base)); + cntctl_base = uniphier_cntctl_base[uniphier_soc]; + + /* Enable and initialize the System level generic timer */ + mmio_write_32(cntctl_base + CNTCR_OFF, CNTCR_FCREQ(0U) | CNTCR_EN); + + uniphier_psci_init(uniphier_soc); +} + +void bl31_plat_arch_setup(void) +{ + uniphier_mmap_setup(uniphier_soc); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c new file mode 100644 index 0000000..36a9908 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#include "uniphier.h" + +#define UNIPHIER_PINMON0 0x0 +#define UNIPHIER_PINMON2 0x8 + +static const uintptr_t uniphier_pinmon_base[] = { + [UNIPHIER_SOC_LD11] = 0x5f900100, + [UNIPHIER_SOC_LD20] = 0x5f900100, + [UNIPHIER_SOC_PXS3] = 0x5f900100, +}; + +static bool uniphier_ld11_is_usb_boot(uint32_t pinmon) +{ + return !!(~pinmon & 0x00000080); +} + +static bool uniphier_ld20_is_usb_boot(uint32_t pinmon) +{ + return !!(~pinmon & 0x00000780); +} + +static bool uniphier_pxs3_is_usb_boot(uint32_t pinmon) +{ + uintptr_t pinmon_base = uniphier_pinmon_base[UNIPHIER_SOC_PXS3]; + uint32_t pinmon2 = mmio_read_32(pinmon_base + UNIPHIER_PINMON2); + + return !!(pinmon2 & BIT(31)); +} + +static const unsigned int uniphier_ld11_boot_device_table[] = { + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_NOR, +}; + +static unsigned int uniphier_ld11_get_boot_device(uint32_t pinmon) +{ + unsigned int boot_sel = (pinmon >> 1) & 0x1f; + + assert(boot_sel < ARRAY_SIZE(uniphier_ld11_boot_device_table)); + + return uniphier_ld11_boot_device_table[boot_sel]; +} + +static const unsigned int uniphier_pxs3_boot_device_table[] = { + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_EMMC, + UNIPHIER_BOOT_DEVICE_NAND, + UNIPHIER_BOOT_DEVICE_NAND, +}; + +static unsigned int uniphier_pxs3_get_boot_device(uint32_t pinmon) +{ + unsigned int boot_sel = (pinmon >> 1) & 0xf; + + assert(boot_sel < ARRAY_SIZE(uniphier_pxs3_boot_device_table)); + + return uniphier_pxs3_boot_device_table[boot_sel]; +} + +struct uniphier_boot_device_info { + bool have_boot_swap; + bool (*is_sd_boot)(uint32_t pinmon); + bool (*is_usb_boot)(uint32_t pinmon); + unsigned int (*get_boot_device)(uint32_t pinmon); +}; + +static const struct uniphier_boot_device_info uniphier_boot_device_info[] = { + [UNIPHIER_SOC_LD11] = { + .have_boot_swap = true, + .is_usb_boot = uniphier_ld11_is_usb_boot, + .get_boot_device = uniphier_ld11_get_boot_device, + }, + [UNIPHIER_SOC_LD20] = { + .have_boot_swap = true, + .is_usb_boot = uniphier_ld20_is_usb_boot, + .get_boot_device = uniphier_ld11_get_boot_device, + }, + [UNIPHIER_SOC_PXS3] = { + .have_boot_swap = true, + .is_usb_boot = uniphier_pxs3_is_usb_boot, + .get_boot_device = uniphier_pxs3_get_boot_device, + }, +}; + +unsigned int uniphier_get_boot_device(unsigned int soc) +{ + const struct uniphier_boot_device_info *info; + uintptr_t pinmon_base; + uint32_t pinmon; + + assert(soc < ARRAY_SIZE(uniphier_boot_device_info)); + info = &uniphier_boot_device_info[soc]; + + assert(soc < ARRAY_SIZE(uniphier_boot_device_info)); + pinmon_base = uniphier_pinmon_base[soc]; + + pinmon = mmio_read_32(pinmon_base + UNIPHIER_PINMON0); + + if (info->have_boot_swap && !(pinmon & BIT(29))) + return UNIPHIER_BOOT_DEVICE_NOR; + + if (info->is_sd_boot && info->is_sd_boot(pinmon)) + return UNIPHIER_BOOT_DEVICE_SD; + + if (info->is_usb_boot && info->is_usb_boot(pinmon)) + return UNIPHIER_BOOT_DEVICE_USB; + + return info->get_boot_device(pinmon); +} + +static const bool uniphier_have_onchip_scp[] = { + [UNIPHIER_SOC_LD11] = true, + [UNIPHIER_SOC_LD20] = true, + [UNIPHIER_SOC_PXS3] = false, +}; + +unsigned int uniphier_get_boot_master(unsigned int soc) +{ + assert(soc < ARRAY_SIZE(uniphier_have_onchip_scp)); + + if (uniphier_have_onchip_scp[soc]) { + uintptr_t pinmon_base; + + assert(soc < ARRAY_SIZE(uniphier_boot_device_info)); + pinmon_base = uniphier_pinmon_base[soc]; + + if (mmio_read_32(pinmon_base + UNIPHIER_PINMON0) & BIT(27)) + return UNIPHIER_BOOT_MASTER_THIS; + else + return UNIPHIER_BOOT_MASTER_SCP; + } else { + return UNIPHIER_BOOT_MASTER_EXT; + } +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c new file mode 100644 index 0000000..3ca1768 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "uniphier.h" + +#define UNIPHIER_CCI500_BASE 0x5FD00000 + +static const int uniphier_cci_map[] = {1, 0}; + +static void __uniphier_cci_init(void) +{ + cci_init(UNIPHIER_CCI500_BASE, uniphier_cci_map, + ARRAY_SIZE(uniphier_cci_map)); +} + +static void __uniphier_cci_enable(void) +{ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +static void __uniphier_cci_disable(void) +{ + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +struct uniphier_cci_ops { + void (*init)(void); + void (*enable)(void); + void (*disable)(void); +}; + +static const struct uniphier_cci_ops uniphier_cci_ops_table[] = { + [UNIPHIER_SOC_LD11] = { + .init = NULL, + .enable = NULL, + .disable = NULL, + }, + [UNIPHIER_SOC_LD20] = { + .init = __uniphier_cci_init, + .enable = __uniphier_cci_enable, + .disable = __uniphier_cci_disable, + }, + [UNIPHIER_SOC_PXS3] = { + .init = NULL, + .enable = NULL, + .disable = NULL, + }, +}; + +static struct uniphier_cci_ops uniphier_cci_ops; + +void uniphier_cci_init(unsigned int soc) +{ + uniphier_cci_ops = uniphier_cci_ops_table[soc]; + flush_dcache_range((uint64_t)&uniphier_cci_ops, + sizeof(uniphier_cci_ops)); + + if (uniphier_cci_ops.init) + uniphier_cci_ops.init(); +} + +void uniphier_cci_enable(void) +{ + if (uniphier_cci_ops.enable) + uniphier_cci_ops.enable(); +} + +void uniphier_cci_disable(void) +{ + if (uniphier_cci_ops.disable) + uniphier_cci_ops.disable(); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S new file mode 100644 index 0000000..48927f4 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "uniphier_console.h" + +/* + * In: w0 - character to be printed + * x1 - pointer to console structure + * Out: return the character written (always succeeds) + * Clobber: x2 + */ + .globl uniphier_console_putc +func uniphier_console_putc + ldr x1, [x1, #CONSOLE_T_BASE] + + /* Wait until the transmitter FIFO gets empty */ +0: ldr w2, [x1, #UNIPHIER_UART_LSR] + tbz w2, #UNIPHIER_UART_LSR_THRE_BIT, 0b + + str w0, [x1, #UNIPHIER_UART_TX] + + ret +endfunc uniphier_console_putc + +/* + * In: x0 - pointer to console structure + * Out: return the character read, or ERROR_NO_PENDING_CHAR if no character + is available + * Clobber: x1 + */ + .globl uniphier_console_getc +func uniphier_console_getc + ldr x0, [x0, #CONSOLE_T_BASE] + + ldr w1, [x0, #UNIPHIER_UART_LSR] + tbz w1, #UNIPHIER_UART_LSR_DR_BIT, 0f + + ldr w0, [x0, #UNIPHIER_UART_RX] + ret + +0: mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc uniphier_console_getc + +/* + * In: x0 - pointer to console structure + * Out: return 0 (always succeeds) + * Clobber: x1 + */ + .global uniphier_console_flush +func uniphier_console_flush + ldr x0, [x0, #CONSOLE_T_BASE] + + /* wait until the transmitter gets empty */ +0: ldr w1, [x0, #UNIPHIER_UART_LSR] + tbz w1, #UNIPHIER_UART_LSR_TEMT_BIT, 0b + + ret +endfunc uniphier_console_flush diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h new file mode 100644 index 0000000..e35fc88 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UNIPHIER_CONSOLE_H +#define UNIPHIER_CONSOLE_H + +#define UNIPHIER_UART_RX 0x00 /* In: Receive buffer */ +#define UNIPHIER_UART_TX 0x00 /* Out: Transmit buffer */ + +#define UNIPHIER_UART_FCR 0x0c /* Char/FIFO Control Register */ +#define UNIPHIER_UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ + +#define UNIPHIER_UART_LCR_MCR 0x10 /* Line/Modem Control Register */ +#define UNIPHIER_UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ +#define UNIPHIER_UART_LSR 0x14 /* Line Status Register */ +#define UNIPHIER_UART_LSR_TEMT 0x40 /* Transmitter empty */ +#define UNIPHIER_UART_LSR_TEMT_BIT 6 /* Transmitter empty */ +#define UNIPHIER_UART_LSR_THRE_BIT 5 /* Transmit-hold-register empty */ +#define UNIPHIER_UART_LSR_DR_BIT 0 /* Receiver data ready */ +#define UNIPHIER_UART_DLR 0x24 /* Divisor Latch Register */ + +#endif /* UNIPHIER_CONSOLE_H */ diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c new file mode 100644 index 0000000..9fda26e --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019-2020, Socionext Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include "uniphier.h" +#include "uniphier_console.h" + +#define UNIPHIER_UART_OFFSET 0x100 +#define UNIPHIER_UART_NR_PORTS 4 + +/* These callbacks are implemented in assembly to use crash_console_helpers.S */ +int uniphier_console_putc(int character, struct console *console); +int uniphier_console_getc(struct console *console); +void uniphier_console_flush(struct console *console); + +static console_t uniphier_console = { + .flags = CONSOLE_FLAG_BOOT | +#if DEBUG + CONSOLE_FLAG_RUNTIME | +#endif + CONSOLE_FLAG_CRASH | + CONSOLE_FLAG_TRANSLATE_CRLF, + .putc = uniphier_console_putc, + .getc = uniphier_console_getc, + .flush = uniphier_console_flush, +}; + +static const uintptr_t uniphier_uart_base[] = { + [UNIPHIER_SOC_LD11] = 0x54006800, + [UNIPHIER_SOC_LD20] = 0x54006800, + [UNIPHIER_SOC_PXS3] = 0x54006800, +}; + +/* + * There are 4 UART ports available on this platform. By default, we want to + * use the same one as used in the previous firmware stage. + */ +static uintptr_t uniphier_console_get_base(unsigned int soc) +{ + uintptr_t base, end; + uint32_t div; + + assert(soc < ARRAY_SIZE(uniphier_uart_base)); + base = uniphier_uart_base[soc]; + end = base + UNIPHIER_UART_OFFSET * UNIPHIER_UART_NR_PORTS; + + while (base < end) { + div = mmio_read_32(base + UNIPHIER_UART_DLR); + if (div) + return base; + base += UNIPHIER_UART_OFFSET; + } + + return 0; +} + +static void uniphier_console_init(uintptr_t base) +{ + mmio_write_32(base + UNIPHIER_UART_FCR, UNIPHIER_UART_FCR_ENABLE_FIFO); + mmio_write_32(base + UNIPHIER_UART_LCR_MCR, + UNIPHIER_UART_LCR_WLEN8 << 8); +} + +void uniphier_console_setup(unsigned int soc) +{ + uintptr_t base; + + base = uniphier_console_get_base(soc); + if (!base) + plat_error_handler(-EINVAL); + + uniphier_console.base = base; + console_register(&uniphier_console); + + /* + * The hardware might be still printing characters queued up in the + * previous firmware stage. Make sure the transmitter is empty before + * any initialization. Otherwise, the console might get corrupted. + */ + console_flush(); + + uniphier_console_init(base); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c new file mode 100644 index 0000000..b3d23cb --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c @@ -0,0 +1,308 @@ +/* + * 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 "uniphier.h" + +#define MMC_CMD_SWITCH 6 +#define MMC_CMD_SELECT_CARD 7 +#define MMC_CMD_SEND_CSD 9 +#define MMC_CMD_READ_MULTIPLE_BLOCK 18 + +#define EXT_CSD_PART_CONF 179 /* R/W */ + +#define MMC_RSP_PRESENT BIT(0) +#define MMC_RSP_136 BIT(1) /* 136 bit response */ +#define MMC_RSP_CRC BIT(2) /* expect valid crc */ +#define MMC_RSP_BUSY BIT(3) /* card may send busy */ +#define MMC_RSP_OPCODE BIT(4) /* response contains opcode */ + +#define MMC_RSP_NONE (0) +#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R1b (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | \ + MMC_RSP_BUSY) +#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC) +#define MMC_RSP_R3 (MMC_RSP_PRESENT) +#define MMC_RSP_R4 (MMC_RSP_PRESENT) +#define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) + +#define SDHCI_DMA_ADDRESS 0x00 +#define SDHCI_BLOCK_SIZE 0x04 +#define SDHCI_MAKE_BLKSZ(dma, blksz) ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF)) +#define SDHCI_BLOCK_COUNT 0x06 +#define SDHCI_ARGUMENT 0x08 +#define SDHCI_TRANSFER_MODE 0x0C +#define SDHCI_TRNS_DMA BIT(0) +#define SDHCI_TRNS_BLK_CNT_EN BIT(1) +#define SDHCI_TRNS_ACMD12 BIT(2) +#define SDHCI_TRNS_READ BIT(4) +#define SDHCI_TRNS_MULTI BIT(5) +#define SDHCI_COMMAND 0x0E +#define SDHCI_CMD_RESP_MASK 0x03 +#define SDHCI_CMD_CRC 0x08 +#define SDHCI_CMD_INDEX 0x10 +#define SDHCI_CMD_DATA 0x20 +#define SDHCI_CMD_ABORTCMD 0xC0 +#define SDHCI_CMD_RESP_NONE 0x00 +#define SDHCI_CMD_RESP_LONG 0x01 +#define SDHCI_CMD_RESP_SHORT 0x02 +#define SDHCI_CMD_RESP_SHORT_BUSY 0x03 +#define SDHCI_MAKE_CMD(c, f) ((((c) & 0xff) << 8) | ((f) & 0xff)) +#define SDHCI_RESPONSE 0x10 +#define SDHCI_HOST_CONTROL 0x28 +#define SDHCI_CTRL_DMA_MASK 0x18 +#define SDHCI_CTRL_SDMA 0x00 +#define SDHCI_BLOCK_GAP_CONTROL 0x2A +#define SDHCI_SOFTWARE_RESET 0x2F +#define SDHCI_RESET_CMD 0x02 +#define SDHCI_RESET_DATA 0x04 +#define SDHCI_INT_STATUS 0x30 +#define SDHCI_INT_RESPONSE BIT(0) +#define SDHCI_INT_DATA_END BIT(1) +#define SDHCI_INT_DMA_END BIT(3) +#define SDHCI_INT_ERROR BIT(15) +#define SDHCI_SIGNAL_ENABLE 0x38 + +/* RCA assigned by Boot ROM */ +#define UNIPHIER_EMMC_RCA 0x1000 + +struct uniphier_mmc_cmd { + unsigned int cmdidx; + unsigned int resp_type; + unsigned int cmdarg; + unsigned int is_data; +}; + +struct uniphier_emmc_host { + uintptr_t base; + bool is_block_addressing; +}; + +static struct uniphier_emmc_host uniphier_emmc_host; + +static int uniphier_emmc_send_cmd(uintptr_t host_base, + struct uniphier_mmc_cmd *cmd) +{ + uint32_t mode = 0; + uint32_t end_bit; + uint32_t stat, flags, dma_addr; + + mmio_write_32(host_base + SDHCI_INT_STATUS, -1); + mmio_write_32(host_base + SDHCI_SIGNAL_ENABLE, 0); + mmio_write_32(host_base + SDHCI_ARGUMENT, cmd->cmdarg); + + if (cmd->is_data) + mode = SDHCI_TRNS_DMA | SDHCI_TRNS_BLK_CNT_EN | + SDHCI_TRNS_ACMD12 | SDHCI_TRNS_READ | + SDHCI_TRNS_MULTI; + + mmio_write_16(host_base + SDHCI_TRANSFER_MODE, mode); + + if (!(cmd->resp_type & MMC_RSP_PRESENT)) + flags = SDHCI_CMD_RESP_NONE; + else if (cmd->resp_type & MMC_RSP_136) + flags = SDHCI_CMD_RESP_LONG; + else if (cmd->resp_type & MMC_RSP_BUSY) + flags = SDHCI_CMD_RESP_SHORT_BUSY; + else + flags = SDHCI_CMD_RESP_SHORT; + + if (cmd->resp_type & MMC_RSP_CRC) + flags |= SDHCI_CMD_CRC; + if (cmd->resp_type & MMC_RSP_OPCODE) + flags |= SDHCI_CMD_INDEX; + if (cmd->is_data) + flags |= SDHCI_CMD_DATA; + + if (cmd->resp_type & MMC_RSP_BUSY || cmd->is_data) + end_bit = SDHCI_INT_DATA_END; + else + end_bit = SDHCI_INT_RESPONSE; + + mmio_write_16(host_base + SDHCI_COMMAND, + SDHCI_MAKE_CMD(cmd->cmdidx, flags)); + + do { + stat = mmio_read_32(host_base + SDHCI_INT_STATUS); + if (stat & SDHCI_INT_ERROR) + return -EIO; + + if (stat & SDHCI_INT_DMA_END) { + mmio_write_32(host_base + SDHCI_INT_STATUS, stat); + dma_addr = mmio_read_32(host_base + SDHCI_DMA_ADDRESS); + mmio_write_32(host_base + SDHCI_DMA_ADDRESS, dma_addr); + } + } while (!(stat & end_bit)); + + return 0; +} + +static int uniphier_emmc_switch_part(uintptr_t host_base, int part_num) +{ + struct uniphier_mmc_cmd cmd = {0}; + + cmd.cmdidx = MMC_CMD_SWITCH; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = (EXT_CSD_PART_CONF << 16) | (part_num << 8) | (3 << 24); + + return uniphier_emmc_send_cmd(host_base, &cmd); +} + +static int uniphier_emmc_check_device_size(uintptr_t host_base, + bool *is_block_addressing) +{ + struct uniphier_mmc_cmd cmd = {0}; + uint32_t csd40, csd72; /* CSD[71:40], CSD[103:72] */ + int ret; + + cmd.cmdidx = MMC_CMD_SEND_CSD; + cmd.resp_type = MMC_RSP_R2; + cmd.cmdarg = UNIPHIER_EMMC_RCA << 16; + + ret = uniphier_emmc_send_cmd(host_base, &cmd); + if (ret) + return ret; + + csd40 = mmio_read_32(host_base + SDHCI_RESPONSE + 4); + csd72 = mmio_read_32(host_base + SDHCI_RESPONSE + 8); + + /* C_SIZE == 0xfff && C_SIZE_MULT == 0x7 ? */ + *is_block_addressing = !(~csd40 & 0xffc00380) && !(~csd72 & 0x3); + + return 0; +} + +static int uniphier_emmc_load_image(uintptr_t host_base, + uint32_t dev_addr, + unsigned long load_addr, + uint32_t block_cnt) +{ + struct uniphier_mmc_cmd cmd = {0}; + uint8_t tmp; + + assert((load_addr >> 32) == 0); + + mmio_write_32(host_base + SDHCI_DMA_ADDRESS, load_addr); + mmio_write_16(host_base + SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(7, 512)); + mmio_write_16(host_base + SDHCI_BLOCK_COUNT, block_cnt); + + tmp = mmio_read_8(host_base + SDHCI_HOST_CONTROL); + tmp &= ~SDHCI_CTRL_DMA_MASK; + tmp |= SDHCI_CTRL_SDMA; + mmio_write_8(host_base + SDHCI_HOST_CONTROL, tmp); + + tmp = mmio_read_8(host_base + SDHCI_BLOCK_GAP_CONTROL); + tmp &= ~1; /* clear Stop At Block Gap Request */ + mmio_write_8(host_base + SDHCI_BLOCK_GAP_CONTROL, tmp); + + cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = dev_addr; + cmd.is_data = 1; + + return uniphier_emmc_send_cmd(host_base, &cmd); +} + +static size_t uniphier_emmc_read(int lba, uintptr_t buf, size_t size) +{ + int ret; + + inv_dcache_range(buf, size); + + if (!uniphier_emmc_host.is_block_addressing) + lba *= 512; + + ret = uniphier_emmc_load_image(uniphier_emmc_host.base, + lba, buf, size / 512); + + inv_dcache_range(buf, size); + + return ret ? 0 : size; +} + +static struct io_block_dev_spec uniphier_emmc_dev_spec = { + .ops = { + .read = uniphier_emmc_read, + }, + .block_size = 512, +}; + +static int uniphier_emmc_hw_init(struct uniphier_emmc_host *host) +{ + struct uniphier_mmc_cmd cmd = {0}; + uintptr_t host_base = uniphier_emmc_host.base; + int ret; + + /* + * deselect card before SEND_CSD command. + * Do not check the return code. It fails, but it is OK. + */ + cmd.cmdidx = MMC_CMD_SELECT_CARD; + cmd.resp_type = MMC_RSP_R1; + + uniphier_emmc_send_cmd(host_base, &cmd); /* CMD7 (arg=0) */ + + /* reset CMD Line */ + mmio_write_8(host_base + SDHCI_SOFTWARE_RESET, + SDHCI_RESET_CMD | SDHCI_RESET_DATA); + while (mmio_read_8(host_base + SDHCI_SOFTWARE_RESET)) + ; + + ret = uniphier_emmc_check_device_size(host_base, + &uniphier_emmc_host.is_block_addressing); + if (ret) + return ret; + + cmd.cmdarg = UNIPHIER_EMMC_RCA << 16; + + /* select card again */ + ret = uniphier_emmc_send_cmd(host_base, &cmd); + if (ret) + return ret; + + /* switch to Boot Partition 1 */ + ret = uniphier_emmc_switch_part(host_base, 1); + if (ret) + return ret; + + return 0; +} + +static const uintptr_t uniphier_emmc_base[] = { + [UNIPHIER_SOC_LD11] = 0x5a000200, + [UNIPHIER_SOC_LD20] = 0x5a000200, + [UNIPHIER_SOC_PXS3] = 0x5a000200, +}; + +int uniphier_emmc_init(unsigned int soc, + struct io_block_dev_spec **block_dev_spec) +{ + int ret; + + assert(soc < ARRAY_SIZE(uniphier_emmc_base)); + uniphier_emmc_host.base = uniphier_emmc_base[soc]; + if (uniphier_emmc_host.base == 0UL) + return -ENOTSUP; + + ret = uniphier_emmc_hw_init(&uniphier_emmc_host); + if (ret) + return ret; + + *block_dev_spec = &uniphier_emmc_dev_spec; + + return 0; +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c new file mode 100644 index 0000000..266efe7 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#include "uniphier.h" + +static uintptr_t uniphier_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t uniphier_interrupt_props[] = { + /* G0 interrupts */ + + /* SGI0 */ + INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + /* SGI6 */ + INTR_PROP_DESC(14, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + + /* G1S interrupts */ + + /* Timer */ + INTR_PROP_DESC(29, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_LEVEL), + /* SGI1 */ + INTR_PROP_DESC(9, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI2 */ + INTR_PROP_DESC(10, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI3 */ + INTR_PROP_DESC(11, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI4 */ + INTR_PROP_DESC(12, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI5 */ + INTR_PROP_DESC(13, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI7 */ + INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE) +}; + +static unsigned int uniphier_mpidr_to_core_pos(u_register_t mpidr) +{ + return plat_core_pos_by_mpidr(mpidr); +} + +static const struct gicv3_driver_data uniphier_gic_driver_data[] = { + [UNIPHIER_SOC_LD11] = { + .gicd_base = 0x5fe00000, + .gicr_base = 0x5fe40000, + .interrupt_props = uniphier_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(uniphier_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = uniphier_rdistif_base_addrs, + .mpidr_to_core_pos = uniphier_mpidr_to_core_pos, + }, + [UNIPHIER_SOC_LD20] = { + .gicd_base = 0x5fe00000, + .gicr_base = 0x5fe80000, + .interrupt_props = uniphier_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(uniphier_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = uniphier_rdistif_base_addrs, + .mpidr_to_core_pos = uniphier_mpidr_to_core_pos, + }, + [UNIPHIER_SOC_PXS3] = { + .gicd_base = 0x5fe00000, + .gicr_base = 0x5fe80000, + .interrupt_props = uniphier_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(uniphier_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = uniphier_rdistif_base_addrs, + .mpidr_to_core_pos = uniphier_mpidr_to_core_pos, + }, +}; + +void uniphier_gic_driver_init(unsigned int soc) +{ + assert(soc < ARRAY_SIZE(uniphier_gic_driver_data)); + + gicv3_driver_init(&uniphier_gic_driver_data[soc]); +} + +void uniphier_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void uniphier_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void uniphier_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void uniphier_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S new file mode 100644 index 0000000..105cf9e --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .global uniphier_calc_core_pos + .global plat_my_core_pos + .globl platform_mem_init + +/* + * unsigned int uniphier_calc_core_pos(u_register_t mpidr) + * core_pos = (cluster_id * max_cpus_per_cluster) + core_id + */ +func uniphier_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + lsr x0, x0, #MPIDR_AFFINITY_BITS + mov x2, #UNIPHIER_MAX_CPUS_PER_CLUSTER + madd x0, x0, x2, x1 + ret +endfunc uniphier_calc_core_pos + +func plat_my_core_pos + mrs x0, mpidr_el1 + b uniphier_calc_core_pos +endfunc plat_my_core_pos + +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c new file mode 100644 index 0000000..dd62d1e --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#include "uniphier.h" + +#define UNIPHIER_BL33_OFFSET 0x04000000UL +#define UNIPHIER_BL33_MAX_SIZE 0x00800000UL + +#define UNIPHIER_SCP_OFFSET 0x04800000UL +#define UNIPHIER_SCP_MAX_SIZE 0x00020000UL + +static struct bl_mem_params_node uniphier_image_descs[] = { + { + .image_id = SCP_BL2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = UNIPHIER_SCP_OFFSET, + .image_info.image_max_size = UNIPHIER_SCP_MAX_SIZE, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + NON_SECURE | NON_EXECUTABLE), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = UNIPHIER_BL31_OFFSET, + .image_info.image_max_size = UNIPHIER_BL31_MAX_SIZE, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = UNIPHIER_BL31_OFFSET, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + +#ifdef UNIPHIER_LOAD_BL32 + .next_handoff_image_id = BL32_IMAGE_ID, +#else + .next_handoff_image_id = BL33_IMAGE_ID, +#endif + }, +#ifdef UNIPHIER_LOAD_BL32 + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = UNIPHIER_BL32_OFFSET, + .image_info.image_max_size = UNIPHIER_BL32_MAX_SIZE, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE), + .ep_info.pc = UNIPHIER_BL32_OFFSET, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + .next_handoff_image_id = BL33_IMAGE_ID, + }, +#endif + { + .image_id = BL33_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = UNIPHIER_BL33_OFFSET, + .image_info.image_max_size = UNIPHIER_BL33_MAX_SIZE, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + NON_SECURE | EXECUTABLE), + .ep_info.pc = UNIPHIER_BL33_OFFSET, + .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +}; +REGISTER_BL_IMAGE_DESCS(uniphier_image_descs) + +/* + * image_info.image_base and ep_info.pc are the offset from the memory base. + * When ENABLE_PIE is set, we never know the real memory base at link-time. + * Fix-up the addresses by adding the run-time detected base. + */ +void uniphier_init_image_descs(uintptr_t mem_base) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(uniphier_image_descs); i++) { + uniphier_image_descs[i].image_info.image_base += mem_base; + uniphier_image_descs[i].ep_info.pc += mem_base; + } +} + +struct image_info *uniphier_get_image_info(unsigned int image_id) +{ + struct bl_mem_params_node *desc; + + desc = get_bl_mem_params_node(image_id); + assert(desc); + return &desc->image_info; +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c new file mode 100644 index 0000000..92e15b0 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c @@ -0,0 +1,373 @@ +/* + * 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 "uniphier.h" + +#define UNIPHIER_ROM_REGION_BASE 0x00000000ULL +#define UNIPHIER_ROM_REGION_SIZE 0x04000000ULL + +#define UNIPHIER_OCM_REGION_SIZE 0x00040000ULL + +#define UNIPHIER_BLOCK_BUF_OFFSET 0x03000000UL +#define UNIPHIER_BLOCK_BUF_SIZE 0x00800000UL + +static const io_dev_connector_t *uniphier_fip_dev_con; +static uintptr_t uniphier_fip_dev_handle; + +static const io_dev_connector_t *uniphier_backend_dev_con; +static uintptr_t uniphier_backend_dev_handle; + +static io_block_spec_t uniphier_fip_spec = { + /* .offset will be set by the io_setup func */ + .length = 0x00200000, +}; + +static const io_uuid_spec_t uniphier_bl2_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t uniphier_scp_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +static const io_uuid_spec_t uniphier_bl31_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t uniphier_bl32_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t uniphier_bl33_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t uniphier_tb_fw_cert_spec = { + .uuid = UUID_TRUSTED_BOOT_FW_CERT, +}; + +static const io_uuid_spec_t uniphier_trusted_key_cert_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t uniphier_scp_fw_key_cert_spec = { + .uuid = UUID_SCP_FW_KEY_CERT, +}; + +static const io_uuid_spec_t uniphier_soc_fw_key_cert_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t uniphier_tos_fw_key_cert_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t uniphier_nt_fw_key_cert_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t uniphier_scp_fw_cert_spec = { + .uuid = UUID_SCP_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t uniphier_soc_fw_cert_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t uniphier_tos_fw_cert_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t uniphier_nt_fw_cert_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +struct uniphier_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + uintptr_t init_params; +}; + +static const struct uniphier_io_policy uniphier_io_policies[] = { + [FIP_IMAGE_ID] = { + .dev_handle = &uniphier_backend_dev_handle, + .image_spec = (uintptr_t)&uniphier_fip_spec, + }, + [BL2_IMAGE_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_bl2_spec, + .init_params = FIP_IMAGE_ID, + }, + [SCP_BL2_IMAGE_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_scp_spec, + .init_params = FIP_IMAGE_ID, + }, + [BL31_IMAGE_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_bl31_spec, + .init_params = FIP_IMAGE_ID, + }, + [BL32_IMAGE_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_bl32_spec, + .init_params = FIP_IMAGE_ID, + }, + [BL33_IMAGE_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_bl33_spec, + .init_params = FIP_IMAGE_ID, + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_tb_fw_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [TRUSTED_KEY_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_trusted_key_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [SCP_FW_KEY_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_scp_fw_key_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [SOC_FW_KEY_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_soc_fw_key_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_tos_fw_key_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_nt_fw_key_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [SCP_FW_CONTENT_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_scp_fw_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [SOC_FW_CONTENT_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_soc_fw_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_tos_fw_cert_spec, + .init_params = FIP_IMAGE_ID, + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + .dev_handle = &uniphier_fip_dev_handle, + .image_spec = (uintptr_t)&uniphier_nt_fw_cert_spec, + .init_params = FIP_IMAGE_ID, + }, +#endif +}; + +static int uniphier_io_block_setup(size_t fip_offset, + struct io_block_dev_spec *block_dev_spec, + size_t buffer_offset) +{ + int ret; + + uniphier_fip_spec.offset = fip_offset; + + block_dev_spec->buffer.offset = buffer_offset; + block_dev_spec->buffer.length = UNIPHIER_BLOCK_BUF_SIZE; + + ret = mmap_add_dynamic_region(block_dev_spec->buffer.offset, + block_dev_spec->buffer.offset, + block_dev_spec->buffer.length, + MT_MEMORY | MT_RW | MT_NS); + if (ret) + return ret; + + ret = register_io_dev_block(&uniphier_backend_dev_con); + if (ret) + return ret; + + return io_dev_open(uniphier_backend_dev_con, (uintptr_t)block_dev_spec, + &uniphier_backend_dev_handle); +} + +static int uniphier_io_memmap_setup(size_t fip_offset) +{ + int ret; + + uniphier_fip_spec.offset = fip_offset; + + ret = mmap_add_dynamic_region(fip_offset, fip_offset, + uniphier_fip_spec.length, + MT_RO_DATA | MT_SECURE); + if (ret) + return ret; + + ret = register_io_dev_memmap(&uniphier_backend_dev_con); + if (ret) + return ret; + + return io_dev_open(uniphier_backend_dev_con, 0, + &uniphier_backend_dev_handle); +} + +static int uniphier_io_fip_setup(void) +{ + int ret; + + ret = register_io_dev_fip(&uniphier_fip_dev_con); + if (ret) + return ret; + + return io_dev_open(uniphier_fip_dev_con, 0, &uniphier_fip_dev_handle); +} + +static int uniphier_io_emmc_setup(unsigned int soc, size_t buffer_offset) +{ + struct io_block_dev_spec *block_dev_spec; + int ret; + + ret = uniphier_emmc_init(soc, &block_dev_spec); + if (ret) + return ret; + + return uniphier_io_block_setup(0x20000, block_dev_spec, buffer_offset); +} + +static int uniphier_io_nand_setup(unsigned int soc, size_t buffer_offset) +{ + struct io_block_dev_spec *block_dev_spec; + int ret; + + ret = uniphier_nand_init(soc, &block_dev_spec); + if (ret) + return ret; + + return uniphier_io_block_setup(0x20000, block_dev_spec, buffer_offset); +} + +static int uniphier_io_nor_setup(unsigned int soc_id, size_t buffer_offset) +{ + return uniphier_io_memmap_setup(0x70000); +} + +static const uintptr_t uniphier_ocm_base[] = { + [UNIPHIER_SOC_LD11] = 0x30000000, + [UNIPHIER_SOC_LD20] = 0x30000000, + [UNIPHIER_SOC_PXS3] = 0x30000000, +}; + +static int uniphier_io_rom_api_setup(unsigned int soc) +{ + uintptr_t ocm_base; + int ret; + + assert(soc < ARRAY_SIZE(uniphier_ocm_base)); + ocm_base = uniphier_ocm_base[soc]; + + ret = mmap_add_dynamic_region(UNIPHIER_ROM_REGION_BASE, + UNIPHIER_ROM_REGION_BASE, + UNIPHIER_ROM_REGION_SIZE, + MT_CODE | MT_SECURE); + if (ret) + return ret; + + /* + * on-chip SRAM region: should be DEVICE attribute because the USB + * load functions provided by the ROM use this memory region as a work + * area, but do not cater to cache coherency. + */ + ret = mmap_add_dynamic_region(ocm_base, ocm_base, + UNIPHIER_OCM_REGION_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + if (ret) + return ret; + + return 0; +} + +static int uniphier_io_usb_setup(unsigned int soc, size_t buffer_offset) +{ + struct io_block_dev_spec *block_dev_spec; + int ret; + + /* use ROM API for loading images from USB storage */ + ret = uniphier_io_rom_api_setup(soc); + if (ret) + return ret; + + ret = uniphier_usb_init(soc, &block_dev_spec); + if (ret) + return ret; + + return uniphier_io_block_setup(0x20000, block_dev_spec, buffer_offset); +} + +static int (* const uniphier_io_setup_table[])(unsigned int, size_t) = { + [UNIPHIER_BOOT_DEVICE_EMMC] = uniphier_io_emmc_setup, + [UNIPHIER_BOOT_DEVICE_NAND] = uniphier_io_nand_setup, + [UNIPHIER_BOOT_DEVICE_NOR] = uniphier_io_nor_setup, + [UNIPHIER_BOOT_DEVICE_USB] = uniphier_io_usb_setup, +}; + +int uniphier_io_setup(unsigned int soc_id, uintptr_t mem_base) +{ + int (*io_setup)(unsigned int soc_id, size_t buffer_offset); + unsigned int boot_dev; + int ret; + + boot_dev = uniphier_get_boot_device(soc_id); + if (boot_dev == UNIPHIER_BOOT_DEVICE_RSV) + return -EINVAL; + + io_setup = uniphier_io_setup_table[boot_dev]; + ret = io_setup(soc_id, mem_base + UNIPHIER_BLOCK_BUF_OFFSET); + if (ret) + return ret; + + ret = uniphier_io_fip_setup(); + if (ret) + return ret; + + return 0; +} + +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + uintptr_t init_params; + + assert(image_id < ARRAY_SIZE(uniphier_io_policies)); + + *dev_handle = *uniphier_io_policies[image_id].dev_handle; + *image_spec = uniphier_io_policies[image_id].image_spec; + init_params = uniphier_io_policies[image_id].init_params; + + return io_dev_init(*dev_handle, init_params); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c new file mode 100644 index 0000000..71cb96c --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c @@ -0,0 +1,283 @@ +/* + * 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 "uniphier.h" + +#define NAND_CMD_READ0 0 +#define NAND_CMD_READSTART 0x30 + +#define DENALI_ECC_ENABLE 0x0e0 +#define DENALI_PAGES_PER_BLOCK 0x150 +#define DENALI_DEVICE_MAIN_AREA_SIZE 0x170 +#define DENALI_DEVICE_SPARE_AREA_SIZE 0x180 +#define DENALI_TWO_ROW_ADDR_CYCLES 0x190 +#define DENALI_INTR_STATUS0 0x410 +#define DENALI_INTR_ECC_UNCOR_ERR BIT(1) +#define DENALI_INTR_DMA_CMD_COMP BIT(2) +#define DENALI_INTR_INT_ACT BIT(12) + +#define DENALI_DMA_ENABLE 0x700 + +#define DENALI_HOST_ADDR 0x00 +#define DENALI_HOST_DATA 0x10 + +#define DENALI_MAP01 (1 << 26) +#define DENALI_MAP10 (2 << 26) +#define DENALI_MAP11 (3 << 26) + +#define DENALI_MAP11_CMD ((DENALI_MAP11) | 0) +#define DENALI_MAP11_ADDR ((DENALI_MAP11) | 1) +#define DENALI_MAP11_DATA ((DENALI_MAP11) | 2) + +#define DENALI_ACCESS_DEFAULT_AREA 0x42 + +#define UNIPHIER_NAND_BBT_UNKNOWN 0xff + +struct uniphier_nand { + uintptr_t host_base; + uintptr_t reg_base; + int pages_per_block; + int page_size; + int two_row_addr_cycles; + uint8_t bbt[16]; +}; + +struct uniphier_nand uniphier_nand; + +static void uniphier_nand_host_write(struct uniphier_nand *nand, + uint32_t addr, uint32_t data) +{ + mmio_write_32(nand->host_base + DENALI_HOST_ADDR, addr); + mmio_write_32(nand->host_base + DENALI_HOST_DATA, data); +} + +static uint32_t uniphier_nand_host_read(struct uniphier_nand *nand, + uint32_t addr) +{ + mmio_write_32(nand->host_base + DENALI_HOST_ADDR, addr); + return mmio_read_32(nand->host_base + DENALI_HOST_DATA); +} + +static int uniphier_nand_block_isbad(struct uniphier_nand *nand, int block) +{ + int page = nand->pages_per_block * block; + int column = nand->page_size; + uint8_t bbm; + uint32_t status; + int is_bad; + + /* use cache if available */ + if (block < ARRAY_SIZE(nand->bbt) && + nand->bbt[block] != UNIPHIER_NAND_BBT_UNKNOWN) + return nand->bbt[block]; + + mmio_write_32(nand->reg_base + DENALI_ECC_ENABLE, 0); + + mmio_write_32(nand->reg_base + DENALI_INTR_STATUS0, -1); + + uniphier_nand_host_write(nand, DENALI_MAP11_CMD, NAND_CMD_READ0); + uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, column & 0xff); + uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, (column >> 8) & 0xff); + uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, page & 0xff); + uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, (page >> 8) & 0xff); + if (!nand->two_row_addr_cycles) + uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, + (page >> 16) & 0xff); + uniphier_nand_host_write(nand, DENALI_MAP11_CMD, NAND_CMD_READSTART); + + do { + status = mmio_read_32(nand->reg_base + DENALI_INTR_STATUS0); + } while (!(status & DENALI_INTR_INT_ACT)); + + bbm = uniphier_nand_host_read(nand, DENALI_MAP11_DATA); + + is_bad = bbm != 0xff; + + /* if possible, save the result for future re-use */ + if (block < ARRAY_SIZE(nand->bbt)) + nand->bbt[block] = is_bad; + + if (is_bad) + WARN("found bad block at %d. skip.\n", block); + + return is_bad; +} + +static int uniphier_nand_read_pages(struct uniphier_nand *nand, uintptr_t buf, + int page_start, int page_count) +{ + uint32_t status; + + mmio_write_32(nand->reg_base + DENALI_ECC_ENABLE, 1); + mmio_write_32(nand->reg_base + DENALI_DMA_ENABLE, 1); + + mmio_write_32(nand->reg_base + DENALI_INTR_STATUS0, -1); + + /* use Data DMA (64bit) */ + mmio_write_32(nand->host_base + DENALI_HOST_ADDR, + DENALI_MAP10 | page_start); + + /* + * 1. setup transfer type, interrupt when complete, + * burst len = 64 bytes, the number of pages + */ + mmio_write_32(nand->host_base + DENALI_HOST_DATA, + 0x01002000 | (64 << 16) | page_count); + + /* 2. set memory low address */ + mmio_write_32(nand->host_base + DENALI_HOST_DATA, buf); + + /* 3. set memory high address */ + mmio_write_32(nand->host_base + DENALI_HOST_DATA, buf >> 32); + + do { + status = mmio_read_32(nand->reg_base + DENALI_INTR_STATUS0); + } while (!(status & DENALI_INTR_DMA_CMD_COMP)); + + mmio_write_32(nand->reg_base + DENALI_DMA_ENABLE, 0); + + if (status & DENALI_INTR_ECC_UNCOR_ERR) { + ERROR("uncorrectable error in page range %d-%d", + page_start, page_start + page_count - 1); + return -EBADMSG; + } + + return 0; +} + +static size_t __uniphier_nand_read(struct uniphier_nand *nand, int lba, + uintptr_t buf, size_t size) +{ + int pages_per_block = nand->pages_per_block; + int page_size = nand->page_size; + int blocks_to_skip = lba / pages_per_block; + int pages_to_read = div_round_up(size, page_size); + int page = lba % pages_per_block; + int block = 0; + uintptr_t p = buf; + int page_count, ret; + + while (blocks_to_skip) { + ret = uniphier_nand_block_isbad(nand, block); + if (ret < 0) + goto out; + + if (!ret) + blocks_to_skip--; + + block++; + } + + while (pages_to_read) { + ret = uniphier_nand_block_isbad(nand, block); + if (ret < 0) + goto out; + + if (ret) { + block++; + continue; + } + + page_count = MIN(pages_per_block - page, pages_to_read); + + ret = uniphier_nand_read_pages(nand, p, + block * pages_per_block + page, + page_count); + if (ret) + goto out; + + block++; + page = 0; + p += page_size * page_count; + pages_to_read -= page_count; + } + +out: + /* number of read bytes */ + return MIN(size, p - buf); +} + +static size_t uniphier_nand_read(int lba, uintptr_t buf, size_t size) +{ + size_t count; + + inv_dcache_range(buf, size); + + count = __uniphier_nand_read(&uniphier_nand, lba, buf, size); + + inv_dcache_range(buf, size); + + return count; +} + +static struct io_block_dev_spec uniphier_nand_dev_spec = { + .ops = { + .read = uniphier_nand_read, + }, + /* fill .block_size at run-time */ +}; + +static int uniphier_nand_hw_init(struct uniphier_nand *nand) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(nand->bbt); i++) + nand->bbt[i] = UNIPHIER_NAND_BBT_UNKNOWN; + + nand->reg_base = nand->host_base + 0x100000; + + nand->pages_per_block = + mmio_read_32(nand->reg_base + DENALI_PAGES_PER_BLOCK); + + nand->page_size = + mmio_read_32(nand->reg_base + DENALI_DEVICE_MAIN_AREA_SIZE); + + if (mmio_read_32(nand->reg_base + DENALI_TWO_ROW_ADDR_CYCLES) & BIT(0)) + nand->two_row_addr_cycles = 1; + + uniphier_nand_host_write(nand, DENALI_MAP10, + DENALI_ACCESS_DEFAULT_AREA); + + return 0; +} + +static const uintptr_t uniphier_nand_base[] = { + [UNIPHIER_SOC_LD11] = 0x68000000, + [UNIPHIER_SOC_LD20] = 0x68000000, + [UNIPHIER_SOC_PXS3] = 0x68000000, +}; + +int uniphier_nand_init(unsigned int soc, + struct io_block_dev_spec **block_dev_spec) +{ + int ret; + + assert(soc < ARRAY_SIZE(uniphier_nand_base)); + uniphier_nand.host_base = uniphier_nand_base[soc]; + if (!uniphier_nand.host_base) + return -ENOTSUP; + + ret = uniphier_nand_hw_init(&uniphier_nand); + if (ret) + return ret; + + uniphier_nand_dev_spec.block_size = uniphier_nand.page_size; + + *block_dev_spec = &uniphier_nand_dev_spec; + + return 0; +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c new file mode 100644 index 0000000..a371705 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "uniphier.h" + +#define UNIPHIER_ROM_RSV0 0x0 + +#define UNIPHIER_SLFRSTSEL 0x10 +#define UNIPHIER_SLFRSTSEL_MASK GENMASK(1, 0) +#define UNIPHIER_SLFRSTCTL 0x14 +#define UNIPHIER_SLFRSTCTL_RST BIT(0) + +#define MPIDR_AFFINITY_INVALID ((u_register_t)-1) + +static uintptr_t uniphier_rom_rsv_base; +static uintptr_t uniphier_slfrst_base; + +uintptr_t uniphier_sec_entrypoint; + +void uniphier_warmboot_entrypoint(void); +void __dead2 uniphier_fake_pwr_down(void); +u_register_t uniphier_holding_pen_release; +static int uniphier_psci_scp_mode; + +static int uniphier_psci_pwr_domain_on(u_register_t mpidr) +{ + uniphier_holding_pen_release = mpidr; + flush_dcache_range((uint64_t)&uniphier_holding_pen_release, + sizeof(uniphier_holding_pen_release)); + + mmio_write_64(uniphier_rom_rsv_base + UNIPHIER_ROM_RSV0, + (uint64_t)&uniphier_warmboot_entrypoint); + sev(); + + return PSCI_E_SUCCESS; +} + +static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state) +{ + uniphier_gic_cpuif_disable(); +} + +static void uniphier_psci_pwr_domain_on_finish( + const psci_power_state_t *target_state) +{ + uniphier_gic_pcpu_init(); + uniphier_gic_cpuif_enable(); + + uniphier_cci_enable(); +} + +static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi( + const psci_power_state_t *target_state) +{ + /* + * The Boot ROM cannot distinguish warm and cold resets. + * Instead of the CPU reset, fake it. + */ + uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID; + flush_dcache_range((uint64_t)&uniphier_holding_pen_release, + sizeof(uniphier_holding_pen_release)); + + uniphier_fake_pwr_down(); +} + +static void uniphier_self_system_reset(void) +{ + mmio_clrbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTSEL, + UNIPHIER_SLFRSTSEL_MASK); + mmio_setbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTCTL, + UNIPHIER_SLFRSTCTL_RST); +} + +static void __dead2 uniphier_psci_system_off(void) +{ + if (uniphier_psci_scp_mode) { + uniphier_scp_system_off(); + } else { + NOTICE("SCP is disabled; can't shutdown the system.\n"); + NOTICE("Resetting the system instead.\n"); + uniphier_self_system_reset(); + } + + wfi(); + ERROR("UniPhier System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 uniphier_psci_system_reset(void) +{ + if (uniphier_psci_scp_mode) + uniphier_scp_system_reset(); + else + uniphier_self_system_reset(); + + wfi(); + ERROR("UniPhier System Reset: operation not handled.\n"); + panic(); +} + +static const struct plat_psci_ops uniphier_psci_ops = { + .pwr_domain_on = uniphier_psci_pwr_domain_on, + .pwr_domain_off = uniphier_psci_pwr_domain_off, + .pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish, + .pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi, + .system_off = uniphier_psci_system_off, + .system_reset = uniphier_psci_system_reset, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + uniphier_sec_entrypoint = sec_entrypoint; + flush_dcache_range((uint64_t)&uniphier_sec_entrypoint, + sizeof(uniphier_sec_entrypoint)); + + *psci_ops = &uniphier_psci_ops; + + return 0; +} + +struct uniphier_psci_ctrl_base { + uintptr_t rom_rsv_base; + uintptr_t slfrst_base; +}; + +static const struct uniphier_psci_ctrl_base uniphier_psci_ctrl_base[] = { + [UNIPHIER_SOC_LD11] = { + .rom_rsv_base = 0x59801200, + .slfrst_base = 0x61843000, + }, + [UNIPHIER_SOC_LD20] = { + .rom_rsv_base = 0x59801200, + .slfrst_base = 0x61843000, + }, + [UNIPHIER_SOC_PXS3] = { + .rom_rsv_base = 0x59801200, + .slfrst_base = 0x61843000, + }, +}; + +void uniphier_psci_init(unsigned int soc) +{ + assert(soc < ARRAY_SIZE(uniphier_psci_ctrl_base)); + uniphier_rom_rsv_base = uniphier_psci_ctrl_base[soc].rom_rsv_base; + uniphier_slfrst_base = uniphier_psci_ctrl_base[soc].slfrst_base; + + if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) { + uniphier_psci_scp_mode = uniphier_scp_is_running(); + flush_dcache_range((uint64_t)&uniphier_psci_scp_mode, + sizeof(uniphier_psci_scp_mode)); + + if (uniphier_psci_scp_mode) + uniphier_scp_open_com(); + } +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S new file mode 100644 index 0000000..21c44b6 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .global uniphier_rotpk_hash + .global uniphier_rotpk_hash_end + .section .rodata.uniphier_rotpk_hash, "a" +uniphier_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +uniphier_rotpk_hash_end: diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c new file mode 100644 index 0000000..8a12d5d --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "uniphier.h" + +#define UNIPHIER_ROM_RSV3 0x5980120c + +#define UNIPHIER_STMBE2COM 0x5f800030 +#define UNIPHIER_STMTOBEIRQ 0x5f800060 +#define UNIPHIER_BETOSTMIRQ0PT 0x5f800070 +#define UNIPHIER_BEIRQCLRPT 0x5f800072 + +#define UNIPHIER_SCP_READY_MAGIC 0x0000b6a5 + +#define UNIPHIER_SCP_PACKET_START 0xA0 +#define UNIPHIER_SCP_PACKET_END 0xA5 +#define UNIPHIER_SCP_PACKET_ESC 0xA6 +#define UNIPHIER_SCP_IS_CTRL_CODE(c) (0xA0 <= (c) && (c) <= 0xA6) + +int uniphier_scp_is_running(void) +{ + return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC; +} + +void uniphier_scp_start(uint32_t scp_base) +{ + uint32_t tmp; + + mmio_write_32(UNIPHIER_STMBE2COM + 4, scp_base); + mmio_write_32(UNIPHIER_STMBE2COM, UNIPHIER_SCP_READY_MAGIC); + + do { + tmp = mmio_read_32(UNIPHIER_ROM_RSV3); + } while (!(tmp & BIT(8))); + + mmio_write_32(UNIPHIER_ROM_RSV3, tmp | BIT(9)); +} + +static void uniphier_scp_send_packet(const uint8_t *packet, int packet_len) +{ + uintptr_t reg = UNIPHIER_STMBE2COM; + uint32_t word; + int len, i; + + while (packet_len) { + len = MIN(packet_len, 4); + word = 0; + + for (i = 0; i < len; i++) + word |= *packet++ << (8 * i); + + mmio_write_32(reg, word); + reg += 4; + packet_len -= len; + } + + mmio_write_8(UNIPHIER_BETOSTMIRQ0PT, 0x55); + + while (!(mmio_read_32(UNIPHIER_STMTOBEIRQ) & BIT(1))) + ; + mmio_write_8(UNIPHIER_BEIRQCLRPT, BIT(1) | BIT(0)); +} + +static void uniphier_scp_send_cmd(const uint8_t *cmd, int cmd_len) +{ + uint8_t packet[32]; /* long enough */ + uint8_t *p = packet; + uint8_t c; + int i; + + *p++ = UNIPHIER_SCP_PACKET_START; + *p++ = cmd_len; + + for (i = 0; i < cmd_len; i++) { + c = *cmd++; + if (UNIPHIER_SCP_IS_CTRL_CODE(c)) { + *p++ = UNIPHIER_SCP_PACKET_ESC; + *p++ = c ^ BIT(7); + } else { + *p++ = c; + } + } + + *p++ = UNIPHIER_SCP_PACKET_END; + + uniphier_scp_send_packet(packet, p - packet); +} + +#define UNIPHIER_SCP_CMD(name, ...) \ +static const uint8_t __uniphier_scp_##name##_cmd[] = { \ + __VA_ARGS__ \ +}; \ +void uniphier_scp_##name(void) \ +{ \ + uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd, \ + ARRAY_SIZE(__uniphier_scp_##name##_cmd)); \ +} + +UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05) +UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01) +UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00) diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S new file mode 100644 index 0000000..d6cb9ff --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl uniphier_warmboot_entrypoint + .globl uniphier_fake_pwr_down + +func uniphier_warmboot_entrypoint + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + b 1f +0: wfe +1: ldr x1, uniphier_holding_pen_release + cmp x1, x0 + b.ne 0b + ldr x0, uniphier_sec_entrypoint + br x0 +endfunc uniphier_warmboot_entrypoint + +func uniphier_fake_pwr_down + bl disable_mmu_icache_el3 + b uniphier_warmboot_entrypoint +endfunc uniphier_fake_pwr_down diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c new file mode 100644 index 0000000..0e7a2d1 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "uniphier.h" + +#define UNIPHIER_REVISION 0x5f800000UL +#define UNIPHIER_REVISION_NEW 0x1f800000UL + +static unsigned int uniphier_get_revision_field(unsigned int mask, + unsigned int shift) +{ + uintptr_t reg; + + if (BL_CODE_BASE >= 0x80000000UL) + reg = UNIPHIER_REVISION; + else + reg = UNIPHIER_REVISION_NEW; + + return (mmio_read_32(reg) >> shift) & mask; +} + +unsigned int uniphier_get_soc_type(void) +{ + return uniphier_get_revision_field(0xff, 16); +} + +unsigned int uniphier_get_soc_model(void) +{ + return uniphier_get_revision_field(0x07, 8); +} + +unsigned int uniphier_get_soc_revision(void) +{ + return uniphier_get_revision_field(0x1f, 0); +} + +unsigned int uniphier_get_soc_id(void) +{ + uint32_t type = uniphier_get_soc_type(); + + switch (type) { + case 0x31: + return UNIPHIER_SOC_LD11; + case 0x32: + return UNIPHIER_SOC_LD20; + case 0x35: + return UNIPHIER_SOC_PXS3; + default: + return UNIPHIER_SOC_UNKNOWN; + } +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c new file mode 100644 index 0000000..1937843 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +unsigned int plat_get_syscnt_freq2(void) +{ + return 50000000; +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c new file mode 100644 index 0000000..e31ca03 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +extern char uniphier_rotpk_hash[], uniphier_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = uniphier_rotpk_hash; + *key_len = uniphier_rotpk_hash_end - uniphier_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + /* + * No support for non-volatile counter. Update the ROT key to protect + * the system against rollback. + */ + *nv_ctr = 0; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 0; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c new file mode 100644 index 0000000..c106c98 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "uniphier.h" + +static unsigned char uniphier_power_domain_tree_desc[UNIPHIER_CLUSTER_COUNT + 1]; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + uniphier_power_domain_tree_desc[0] = UNIPHIER_CLUSTER_COUNT; + + for (i = 0; i < UNIPHIER_CLUSTER_COUNT; i++) + uniphier_power_domain_tree_desc[i + 1] = + UNIPHIER_MAX_CPUS_PER_CLUSTER; + + return uniphier_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + if (cluster_id >= UNIPHIER_CLUSTER_COUNT) + return -1; + + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + if (cpu_id >= UNIPHIER_MAX_CPUS_PER_CLUSTER) + return -1; + + return uniphier_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c new file mode 100644 index 0000000..7469ad1 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c @@ -0,0 +1,183 @@ +/* + * 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 "uniphier.h" + +#define UNIPHIER_LD11_USB_DESC_BASE 0x30010000 +#define UNIPHIER_LD20_USB_DESC_BASE 0x30014000 +#define UNIPHIER_PXS3_USB_DESC_BASE 0x30014000 + +#define UNIPHIER_SRB_OCM_CONT 0x61200000 + +struct uniphier_ld11_trans_op { + uint8_t __pad[48]; +}; + +struct uniphier_ld11_op { + uint8_t __pad[56]; + struct uniphier_ld11_trans_op *trans_op; + void *__pad2; + void *dev_desc; +}; + +struct uniphier_ld20_trans_op { + uint8_t __pad[40]; +}; + +struct uniphier_ld20_op { + uint8_t __pad[192]; + struct uniphier_ld20_trans_op *trans_op; + void *__pad2; + void *dev_desc; +}; + +struct uniphier_pxs3_op { + uint8_t __pad[184]; + struct uniphier_ld20_trans_op *trans_op; + void *__pad2; + void *dev_desc; +}; + +static int (*__uniphier_usb_read)(int lba, uintptr_t buf, size_t size); + +static void uniphier_ld11_usb_init(void) +{ + struct uniphier_ld11_op *op = (void *)UNIPHIER_LD11_USB_DESC_BASE; + + op->trans_op = (void *)(op + 1); + + op->dev_desc = op->trans_op + 1; +} + +static int uniphier_ld11_usb_read(int lba, uintptr_t buf, size_t size) +{ + static int (*rom_usb_read)(uintptr_t desc, unsigned int lba, + unsigned int size, uintptr_t buf); + uintptr_t func_addr; + + func_addr = uniphier_get_soc_revision() == 1 ? 0x3880 : 0x3958; + rom_usb_read = (__typeof(rom_usb_read))func_addr; + + return rom_usb_read(UNIPHIER_LD11_USB_DESC_BASE, lba, size, buf); +} + +static void uniphier_ld20_usb_init(void) +{ + struct uniphier_ld20_op *op = (void *)UNIPHIER_LD20_USB_DESC_BASE; + + op->trans_op = (void *)(op + 1); + + op->dev_desc = op->trans_op + 1; +} + +static int uniphier_ld20_usb_read(int lba, uintptr_t buf, size_t size) +{ + static int (*rom_usb_read)(uintptr_t desc, unsigned int lba, + unsigned int size, uintptr_t buf); + int ret; + + rom_usb_read = (__typeof(rom_usb_read))0x37f0; + + mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0x1ff); + + /* ROM-API - return 1 on success, 0 on error */ + ret = rom_usb_read(UNIPHIER_LD20_USB_DESC_BASE, lba, size, buf); + + mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0); + + return ret ? 0 : -1; +} + +static void uniphier_pxs3_usb_init(void) +{ + struct uniphier_pxs3_op *op = (void *)UNIPHIER_PXS3_USB_DESC_BASE; + + op->trans_op = (void *)(op + 1); + + op->dev_desc = op->trans_op + 1; +} + +static int uniphier_pxs3_usb_read(int lba, uintptr_t buf, size_t size) +{ + static int (*rom_usb_read)(uintptr_t desc, unsigned int lba, + unsigned int size, uintptr_t buf); + int ret; + + rom_usb_read = (__typeof(rom_usb_read))0x39e8; + + /* ROM-API - return 1 on success, 0 on error */ + ret = rom_usb_read(UNIPHIER_PXS3_USB_DESC_BASE, lba, size, buf); + + return ret ? 0 : -1; +} + +struct uniphier_usb_rom_param { + void (*init)(void); + int (*read)(int lba, uintptr_t buf, size_t size); +}; + +static const struct uniphier_usb_rom_param uniphier_usb_rom_params[] = { + [UNIPHIER_SOC_LD11] = { + .init = uniphier_ld11_usb_init, + .read = uniphier_ld11_usb_read, + }, + [UNIPHIER_SOC_LD20] = { + .init = uniphier_ld20_usb_init, + .read = uniphier_ld20_usb_read, + }, + [UNIPHIER_SOC_PXS3] = { + .init = uniphier_pxs3_usb_init, + .read = uniphier_pxs3_usb_read, + }, +}; + +static size_t uniphier_usb_read(int lba, uintptr_t buf, size_t size) +{ + int ret; + + inv_dcache_range(buf, size); + + ret = __uniphier_usb_read(lba, buf, size); + + inv_dcache_range(buf, size); + + return ret ? 0 : size; +} + +static struct io_block_dev_spec uniphier_usb_dev_spec = { + .ops = { + .read = uniphier_usb_read, + }, + .block_size = 512, +}; + +int uniphier_usb_init(unsigned int soc, + struct io_block_dev_spec **block_dev_spec) +{ + const struct uniphier_usb_rom_param *param; + + assert(soc < ARRAY_SIZE(uniphier_usb_rom_params)); + param = &uniphier_usb_rom_params[soc]; + + if (param->init) + param->init(); + + __uniphier_usb_read = param->read; + + *block_dev_spec = &uniphier_usb_dev_spec; + + return 0; +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c new file mode 100644 index 0000000..5043f4b --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#include "uniphier.h" + +struct uniphier_reg_region { + uintptr_t base; + size_t size; +}; + +static const struct uniphier_reg_region uniphier_reg_region[] = { + [UNIPHIER_SOC_LD11] = { + .base = 0x50000000UL, + .size = 0x20000000UL, + }, + [UNIPHIER_SOC_LD20] = { + .base = 0x50000000UL, + .size = 0x20000000UL, + }, + [UNIPHIER_SOC_PXS3] = { + .base = 0x50000000UL, + .size = 0x20000000UL, + }, +}; + +void uniphier_mmap_setup(unsigned int soc) +{ + VERBOSE("Trusted RAM seen by this BL image: %p - %p\n", + (void *)BL_CODE_BASE, (void *)BL_END); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + round_up(BL_END, PAGE_SIZE) - BL_CODE_BASE, + MT_MEMORY | MT_RW | MT_SECURE); + + /* remap the code section */ + VERBOSE("Code region: %p - %p\n", + (void *)BL_CODE_BASE, (void *)BL_CODE_END); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + round_up(BL_CODE_END, PAGE_SIZE) - BL_CODE_BASE, + MT_CODE | MT_SECURE); + + /* remap the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *)BL_COHERENT_RAM_BASE, (void *)BL_COHERENT_RAM_END); + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE); + + /* register region */ + assert(soc < ARRAY_SIZE(uniphier_reg_region)); + mmap_add_region(uniphier_reg_region[soc].base, + uniphier_reg_region[soc].base, + uniphier_reg_region[soc].size, + MT_DEVICE | MT_RW | MT_SECURE); + + init_xlat_tables(); + + enable_mmu(0); + +#if PLAT_RO_XLAT_TABLES + { + int ret; + + ret = xlat_make_tables_readonly(); + if (ret) { + ERROR("Failed to make translation tables read-only."); + plat_error_handler(ret); + } + } +#endif +} diff --git a/arm-trusted-firmware/plat/st/common/bl2_io_storage.c b/arm-trusted-firmware/plat/st/common/bl2_io_storage.c new file mode 100644 index 0000000..e129dfd --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/bl2_io_storage.c @@ -0,0 +1,598 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* IO devices */ +uintptr_t fip_dev_handle; +uintptr_t storage_dev_handle; + +static const io_dev_connector_t *fip_dev_con; + +#if STM32MP_SDMMC || STM32MP_EMMC +static struct mmc_device_info mmc_info; + +static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE); + +static io_block_dev_spec_t mmc_block_dev_spec = { + /* It's used as temp buffer in block driver */ + .buffer = { + .offset = (size_t)&block_buffer, + .length = MMC_BLOCK_SIZE, + }, + .ops = { + .read = mmc_read_blocks, + .write = NULL, + }, + .block_size = MMC_BLOCK_SIZE, +}; + +static const io_dev_connector_t *mmc_dev_con; +#endif /* STM32MP_SDMMC || STM32MP_EMMC */ + +#if STM32MP_SPI_NOR +static io_mtd_dev_spec_t spi_nor_dev_spec = { + .ops = { + .init = spi_nor_init, + .read = spi_nor_read, + }, +}; +#endif + +#if STM32MP_RAW_NAND +static io_mtd_dev_spec_t nand_dev_spec = { + .ops = { + .init = nand_raw_init, + .read = nand_read, + .seek = nand_seek_bb + }, +}; + +static const io_dev_connector_t *nand_dev_con; +#endif + +#if STM32MP_SPI_NAND +static io_mtd_dev_spec_t spi_nand_dev_spec = { + .ops = { + .init = spi_nand_init, + .read = nand_read, + .seek = nand_seek_bb + }, +}; +#endif + +#if STM32MP_SPI_NAND || STM32MP_SPI_NOR +static const io_dev_connector_t *spi_dev_con; +#endif + +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER +static const io_dev_connector_t *memmap_dev_con; +#endif + +io_block_spec_t image_block_spec = { + .offset = 0U, + .length = 0U, +}; + +int open_fip(const uintptr_t spec) +{ + return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); +} + +int open_storage(const uintptr_t spec) +{ + return io_dev_init(storage_dev_handle, 0); +} + +static void print_boot_device(boot_api_context_t *boot_context) +{ + switch (boot_context->boot_interface_selected) { + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + INFO("Using SDMMC\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + INFO("Using EMMC\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: + INFO("Using QSPI NOR\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: + INFO("Using FMC NAND\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: + INFO("Using SPI NAND\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: + INFO("Using UART\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: + INFO("Using USB\n"); + break; + default: + ERROR("Boot interface %u not found\n", + boot_context->boot_interface_selected); + panic(); + break; + } + + if (boot_context->boot_interface_instance != 0U) { + INFO(" Instance %d\n", boot_context->boot_interface_instance); + } +} + +#if STM32MP_SDMMC || STM32MP_EMMC +static void boot_mmc(enum mmc_device_type mmc_dev_type, + uint16_t boot_interface_instance) +{ + int io_result __unused; + struct stm32_sdmmc2_params params; + + zeromem(¶ms, sizeof(struct stm32_sdmmc2_params)); + + mmc_info.mmc_dev_type = mmc_dev_type; + + switch (boot_interface_instance) { + case 1: + params.reg_base = STM32MP_SDMMC1_BASE; + break; + case 2: + params.reg_base = STM32MP_SDMMC2_BASE; + break; + case 3: + params.reg_base = STM32MP_SDMMC3_BASE; + break; + default: + WARN("SDMMC instance not found, using default\n"); + if (mmc_dev_type == MMC_IS_SD) { + params.reg_base = STM32MP_SDMMC1_BASE; + } else { + params.reg_base = STM32MP_SDMMC2_BASE; + } + break; + } + + params.device_info = &mmc_info; + if (stm32_sdmmc2_mmc_init(¶ms) != 0) { + ERROR("SDMMC%u init failed\n", boot_interface_instance); + panic(); + } + + /* Open MMC as a block device to read GPT table */ + io_result = register_io_dev_block(&mmc_dev_con); + if (io_result != 0) { + panic(); + } + + io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec, + &storage_dev_handle); + assert(io_result == 0); +} +#endif /* STM32MP_SDMMC || STM32MP_EMMC */ + +#if STM32MP_SPI_NOR +static void boot_spi_nor(boot_api_context_t *boot_context) +{ + int io_result __unused; + + io_result = stm32_qspi_init(); + assert(io_result == 0); + + io_result = register_io_dev_mtd(&spi_dev_con); + assert(io_result == 0); + + /* Open connections to device */ + io_result = io_dev_open(spi_dev_con, + (uintptr_t)&spi_nor_dev_spec, + &storage_dev_handle); + assert(io_result == 0); +} +#endif /* STM32MP_SPI_NOR */ + +#if STM32MP_RAW_NAND +static void boot_fmc2_nand(boot_api_context_t *boot_context) +{ + int io_result __unused; + + io_result = stm32_fmc2_init(); + assert(io_result == 0); + + /* Register the IO device on this platform */ + io_result = register_io_dev_mtd(&nand_dev_con); + assert(io_result == 0); + + /* Open connections to device */ + io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec, + &storage_dev_handle); + assert(io_result == 0); +} +#endif /* STM32MP_RAW_NAND */ + +#if STM32MP_SPI_NAND +static void boot_spi_nand(boot_api_context_t *boot_context) +{ + int io_result __unused; + + io_result = stm32_qspi_init(); + assert(io_result == 0); + + io_result = register_io_dev_mtd(&spi_dev_con); + assert(io_result == 0); + + /* Open connections to device */ + io_result = io_dev_open(spi_dev_con, + (uintptr_t)&spi_nand_dev_spec, + &storage_dev_handle); + assert(io_result == 0); +} +#endif /* STM32MP_SPI_NAND */ + +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER +static void mmap_io_setup(void) +{ + int io_result __unused; + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &storage_dev_handle); + assert(io_result == 0); +} + +#if STM32MP_UART_PROGRAMMER +static void stm32cubeprogrammer_uart(void) +{ + int ret __unused; + boot_api_context_t *boot_context = + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + uintptr_t uart_base; + + uart_base = get_uart_address(boot_context->boot_interface_instance); + ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE); + assert(ret == 0); +} +#endif + +#if STM32MP_USB_PROGRAMMER +static void stm32cubeprogrammer_usb(void) +{ + int ret __unused; + struct usb_handle *pdev; + + /* Init USB on platform */ + pdev = usb_dfu_plat_init(); + + ret = stm32cubeprog_usb_load(pdev, DWL_BUFFER_BASE, DWL_BUFFER_SIZE); + assert(ret == 0); +} +#endif +#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */ + + +void stm32mp_io_setup(void) +{ + int io_result __unused; + boot_api_context_t *boot_context = + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + + print_boot_device(boot_context); + + if ((boot_context->boot_partition_used_toboot == 1U) || + (boot_context->boot_partition_used_toboot == 2U)) { + INFO("Boot used partition fsbl%u\n", + boot_context->boot_partition_used_toboot); + } + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + + switch (boot_context->boot_interface_selected) { +#if STM32MP_SDMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + dmbsy(); + boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance); + break; +#endif +#if STM32MP_EMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + dmbsy(); + boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance); + break; +#endif +#if STM32MP_SPI_NOR + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: + dmbsy(); + boot_spi_nor(boot_context); + break; +#endif +#if STM32MP_RAW_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: + dmbsy(); + boot_fmc2_nand(boot_context); + break; +#endif +#if STM32MP_SPI_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: + dmbsy(); + boot_spi_nand(boot_context); + break; +#endif +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER +#if STM32MP_UART_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: +#endif +#if STM32MP_USB_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: +#endif + dmbsy(); + mmap_io_setup(); + break; +#endif + + default: + ERROR("Boot interface %d not supported\n", + boot_context->boot_interface_selected); + panic(); + break; + } +} + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + static bool gpt_init_done __unused; + uint16_t boot_itf = stm32mp_get_boot_itf_selected(); + + switch (boot_itf) { +#if STM32MP_SDMMC || STM32MP_EMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + if (!gpt_init_done) { +/* + * With FWU Multi Bank feature enabled, the selection of + * the image to boot will be done by fwu_init calling the + * platform hook, plat_fwu_set_images_source. + */ +#if !PSA_FWU_SUPPORT + const partition_entry_t *entry; + + partition_init(GPT_IMAGE_ID); + entry = get_partition_entry(FIP_IMAGE_NAME); + if (entry == NULL) { + ERROR("Could NOT find the %s partition!\n", + FIP_IMAGE_NAME); + return -ENOENT; + } + + image_block_spec.offset = entry->start; + image_block_spec.length = entry->length; +#endif + gpt_init_done = true; + } else { + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base; + mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size; + } + + break; +#endif + +#if STM32MP_RAW_NAND || STM32MP_SPI_NAND +#if STM32MP_RAW_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: +#endif +#if STM32MP_SPI_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: +#endif + image_block_spec.offset = STM32MP_NAND_FIP_OFFSET; + break; +#endif + +#if STM32MP_SPI_NOR + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: + image_block_spec.offset = STM32MP_NOR_FIP_OFFSET; + break; +#endif + +#if STM32MP_UART_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: + if (image_id == FW_CONFIG_ID) { + stm32cubeprogrammer_uart(); + /* FIP loaded at DWL address */ + image_block_spec.offset = DWL_BUFFER_BASE; + image_block_spec.length = DWL_BUFFER_SIZE; + } + break; +#endif +#if STM32MP_USB_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: + if (image_id == FW_CONFIG_ID) { + stm32cubeprogrammer_usb(); + /* FIP loaded at DWL address */ + image_block_spec.offset = DWL_BUFFER_BASE; + image_block_spec.length = DWL_BUFFER_SIZE; + } + break; +#endif + + default: + ERROR("FIP Not found\n"); + panic(); + } + + return 0; +} + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy. + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int rc; + const struct plat_io_policy *policy; + + policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id); + rc = policy->check(policy->image_spec); + if (rc == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + + return rc; +} + +#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT +/* + * Eventually, this function will return the + * boot index to be passed on to the Update + * Agent after performing certain checks like + * a watchdog timeout, or Auth failure while + * trying to load from a certain bank. + * For now, since we do not have that logic + * implemented, just pass the active_index + * read from the metadata. + */ +uint32_t plat_fwu_get_boot_idx(void) +{ + const struct fwu_metadata *metadata; + + metadata = fwu_get_metadata(); + + return metadata->active_index; +} + +static void *stm32_get_image_spec(const uuid_t *img_type_uuid) +{ + unsigned int i; + + for (i = 0U; i < MAX_NUMBER_IDS; i++) { + if ((guidcmp(&policies[i].img_type_guid, img_type_uuid)) == 0) { + return (void *)policies[i].image_spec; + } + } + + return NULL; +} + +void plat_fwu_set_images_source(const struct fwu_metadata *metadata) +{ + unsigned int i; + uint32_t boot_idx; + const partition_entry_t *entry; + const uuid_t *img_type_uuid, *img_uuid; + io_block_spec_t *image_spec; + + boot_idx = plat_fwu_get_boot_idx(); + assert(boot_idx < NR_OF_FW_BANKS); + + for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) { + img_type_uuid = &metadata->img_entry[i].img_type_uuid; + image_spec = stm32_get_image_spec(img_type_uuid); + if (image_spec == NULL) { + ERROR("Unable to get image spec for the image in the metadata\n"); + panic(); + } + + img_uuid = + &metadata->img_entry[i].img_props[boot_idx].img_uuid; + + entry = get_partition_entry_by_uuid(img_uuid); + if (entry == NULL) { + ERROR("Unable to find the partition with the uuid mentioned in metadata\n"); + panic(); + } + + image_spec->offset = entry->start; + image_spec->length = entry->length; + } +} + +static int plat_set_image_source(unsigned int image_id, + uintptr_t *handle, + uintptr_t *image_spec, + const char *part_name) +{ + struct plat_io_policy *policy; + io_block_spec_t *spec; + const partition_entry_t *entry = get_partition_entry(part_name); + + if (entry == NULL) { + ERROR("Unable to find the %s partition\n", part_name); + return -ENOENT; + } + + policy = &policies[image_id]; + + spec = (io_block_spec_t *)policy->image_spec; + spec->offset = entry->start; + spec->length = entry->length; + + *image_spec = policy->image_spec; + *handle = *policy->dev_handle; + + return 0; +} + +int plat_fwu_set_metadata_image_source(unsigned int image_id, + uintptr_t *handle, + uintptr_t *image_spec) +{ + char *part_name; + + assert((image_id == FWU_METADATA_IMAGE_ID) || + (image_id == BKUP_FWU_METADATA_IMAGE_ID)); + + partition_init(GPT_IMAGE_ID); + + if (image_id == FWU_METADATA_IMAGE_ID) { + part_name = METADATA_PART_1; + } else { + part_name = METADATA_PART_2; + } + + return plat_set_image_source(image_id, handle, image_spec, + part_name); +} +#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */ diff --git a/arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c b/arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c new file mode 100644 index 0000000..4391195 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c @@ -0,0 +1,667 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* IO devices */ +#ifndef AARCH32_SP_OPTEE +static const io_dev_connector_t *dummy_dev_con; +static uintptr_t dummy_dev_handle; +static uintptr_t dummy_dev_spec; +#endif + +static uintptr_t image_dev_handle; +static uintptr_t storage_dev_handle; + +#if STM32MP_SDMMC || STM32MP_EMMC +static struct mmc_device_info mmc_info; +static io_block_spec_t gpt_block_spec = { + .offset = 0U, + .length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */ +}; + +static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE); + +static const io_block_dev_spec_t mmc_block_dev_spec = { + /* It's used as temp buffer in block driver */ + .buffer = { + .offset = (size_t)&block_buffer, + .length = MMC_BLOCK_SIZE, + }, + .ops = { + .read = mmc_read_blocks, + .write = NULL, + }, + .block_size = MMC_BLOCK_SIZE, +}; + +#if STM32MP_EMMC_BOOT +static io_block_spec_t emmc_boot_ssbl_block_spec = { + .offset = PLAT_EMMC_BOOT_SSBL_OFFSET, + .length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */ +}; + +static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = { + /* It's used as temp buffer in block driver */ + .buffer = { + .offset = (size_t)&block_buffer, + .length = MMC_BLOCK_SIZE, + }, + .ops = { + .read = mmc_boot_part_read_blocks, + .write = NULL, + }, + .block_size = MMC_BLOCK_SIZE, +}; +#endif + +static struct io_mmc_dev_spec mmc_device_spec = { + .use_boot_part = false, +}; + +static const io_dev_connector_t *mmc_dev_con; +#endif /* STM32MP_SDMMC || STM32MP_EMMC */ + +#if STM32MP_SPI_NOR +static io_mtd_dev_spec_t spi_nor_dev_spec = { + .ops = { + .init = spi_nor_init, + .read = spi_nor_read, + }, +}; +#endif + +#if STM32MP_RAW_NAND +static io_mtd_dev_spec_t nand_dev_spec = { + .ops = { + .init = nand_raw_init, + .read = nand_read, + }, +}; + +static const io_dev_connector_t *nand_dev_con; +#endif + +#if STM32MP_SPI_NAND +static io_mtd_dev_spec_t spi_nand_dev_spec = { + .ops = { + .init = spi_nand_init, + .read = nand_read, + }, +}; +#endif + +#if STM32MP_SPI_NAND || STM32MP_SPI_NOR +static const io_dev_connector_t *spi_dev_con; +#endif + +#ifdef AARCH32_SP_OPTEE +static const struct stm32image_part_info optee_header_partition_spec = { + .name = OPTEE_HEADER_IMAGE_NAME, + .binary_type = OPTEE_HEADER_BINARY_TYPE, +}; + +static const struct stm32image_part_info optee_core_partition_spec = { + .name = OPTEE_CORE_IMAGE_NAME, + .binary_type = OPTEE_CORE_BINARY_TYPE, +}; + +static const struct stm32image_part_info optee_paged_partition_spec = { + .name = OPTEE_PAGED_IMAGE_NAME, + .binary_type = OPTEE_PAGED_BINARY_TYPE, +}; +#else +static const io_block_spec_t bl32_block_spec = { + .offset = BL32_BASE, + .length = STM32MP_BL32_SIZE +}; +#endif + +static const struct stm32image_part_info bl33_partition_spec = { + .name = BL33_IMAGE_NAME, + .binary_type = BL33_BINARY_TYPE, +}; + +enum { + IMG_IDX_BL33, +#ifdef AARCH32_SP_OPTEE + IMG_IDX_OPTEE_HEADER, + IMG_IDX_OPTEE_CORE, + IMG_IDX_OPTEE_PAGED, +#endif + IMG_IDX_NUM +}; + +static struct stm32image_device_info stm32image_dev_info_spec __unused = { + .lba_size = MMC_BLOCK_SIZE, + .part_info[IMG_IDX_BL33] = { + .name = BL33_IMAGE_NAME, + .binary_type = BL33_BINARY_TYPE, + }, +#ifdef AARCH32_SP_OPTEE + .part_info[IMG_IDX_OPTEE_HEADER] = { + .name = OPTEE_HEADER_IMAGE_NAME, + .binary_type = OPTEE_HEADER_BINARY_TYPE, + }, + .part_info[IMG_IDX_OPTEE_CORE] = { + .name = OPTEE_CORE_IMAGE_NAME, + .binary_type = OPTEE_CORE_BINARY_TYPE, + }, + .part_info[IMG_IDX_OPTEE_PAGED] = { + .name = OPTEE_PAGED_IMAGE_NAME, + .binary_type = OPTEE_PAGED_BINARY_TYPE, + }, +#endif +}; + +static io_block_spec_t stm32image_block_spec = { + .offset = 0U, + .length = 0U, +}; + +static const io_dev_connector_t *stm32image_dev_con __unused; + +#ifndef AARCH32_SP_OPTEE +static int open_dummy(const uintptr_t spec); +#endif +static int open_image(const uintptr_t spec); +static int open_storage(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const struct plat_io_policy policies[] = { +#ifdef AARCH32_SP_OPTEE + [BL32_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&optee_header_partition_spec, + .check = open_image + }, + [BL32_EXTRA1_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&optee_core_partition_spec, + .check = open_image + }, + [BL32_EXTRA2_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&optee_paged_partition_spec, + .check = open_image + }, +#else + [BL32_IMAGE_ID] = { + .dev_handle = &dummy_dev_handle, + .image_spec = (uintptr_t)&bl32_block_spec, + .check = open_dummy + }, +#endif + [BL33_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&bl33_partition_spec, + .check = open_image + }, +#if STM32MP_SDMMC || STM32MP_EMMC + [GPT_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&gpt_block_spec, + .check = open_storage + }, +#endif + [STM32_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&stm32image_block_spec, + .check = open_storage + } +}; + +#ifndef AARCH32_SP_OPTEE +static int open_dummy(const uintptr_t spec) +{ + return io_dev_init(dummy_dev_handle, 0); +} +#endif + +static int open_image(const uintptr_t spec) +{ + return io_dev_init(image_dev_handle, 0); +} + +static int open_storage(const uintptr_t spec) +{ + return io_dev_init(storage_dev_handle, 0); +} + +#if STM32MP_EMMC_BOOT +static uint32_t get_boot_part_ssbl_header(void) +{ + uint32_t magic = 0U; + int io_result; + size_t bytes_read; + + io_result = register_io_dev_block(&mmc_dev_con); + if (io_result != 0) { + panic(); + } + + io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec, + &storage_dev_handle); + assert(io_result == 0); + + io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_ssbl_block_spec, + &image_dev_handle); + assert(io_result == 0); + + io_result = io_read(image_dev_handle, (uintptr_t)&magic, sizeof(magic), + &bytes_read); + assert(io_result == 0); + assert(bytes_read == sizeof(magic)); + + io_result = io_dev_close(storage_dev_handle); + assert(io_result == 0); + + return magic; +} +#endif + +static void print_boot_device(boot_api_context_t *boot_context) +{ + switch (boot_context->boot_interface_selected) { + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + INFO("Using SDMMC\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + INFO("Using EMMC\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: + INFO("Using QSPI NOR\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: + INFO("Using FMC NAND\n"); + break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: + INFO("Using SPI NAND\n"); + break; + default: + ERROR("Boot interface not found\n"); + panic(); + break; + } + + if (boot_context->boot_interface_instance != 0U) { + INFO(" Instance %d\n", boot_context->boot_interface_instance); + } +} + +static void stm32image_io_setup(void) +{ + int io_result __unused; + + io_result = register_io_dev_stm32image(&stm32image_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(stm32image_dev_con, + (uintptr_t)&stm32image_dev_info_spec, + &image_dev_handle); + assert(io_result == 0); +} + +#if STM32MP_SDMMC || STM32MP_EMMC +static void boot_mmc(enum mmc_device_type mmc_dev_type, + uint16_t boot_interface_instance) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; + struct stm32_sdmmc2_params params; + const partition_entry_t *entry __unused; + uint32_t magic __unused; + + zeromem(¶ms, sizeof(struct stm32_sdmmc2_params)); + + mmc_info.mmc_dev_type = mmc_dev_type; + + switch (boot_interface_instance) { + case 1: + params.reg_base = STM32MP_SDMMC1_BASE; + break; + case 2: + params.reg_base = STM32MP_SDMMC2_BASE; + break; + case 3: + params.reg_base = STM32MP_SDMMC3_BASE; + break; + default: + WARN("SDMMC instance not found, using default\n"); + if (mmc_dev_type == MMC_IS_SD) { + params.reg_base = STM32MP_SDMMC1_BASE; + } else { + params.reg_base = STM32MP_SDMMC2_BASE; + } + break; + } + + params.device_info = &mmc_info; + if (stm32_sdmmc2_mmc_init(¶ms) != 0) { + ERROR("SDMMC%u init failed\n", boot_interface_instance); + panic(); + } + + stm32image_dev_info_spec.device_size = + stm32_sdmmc2_mmc_get_device_size(); + +#if STM32MP_EMMC_BOOT + if (mmc_dev_type == MMC_IS_EMMC) { + magic = get_boot_part_ssbl_header(); + + if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) { + VERBOSE("%s, header found, jump to emmc load\n", __func__); + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET; + part->bkp_offset = 0U; + mmc_device_spec.use_boot_part = true; + + goto emmc_boot; + } else { + WARN("%s: Can't find STM32 header on a boot partition\n", __func__); + } + } +#endif + + /* Open MMC as a block device to read GPT table */ + io_result = register_io_dev_block(&mmc_dev_con); + if (io_result != 0) { + panic(); + } + + io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec, + &storage_dev_handle); + assert(io_result == 0); + + partition_init(GPT_IMAGE_ID); + + io_result = io_dev_close(storage_dev_handle); + assert(io_result == 0); + + for (idx = 0U; idx < IMG_IDX_NUM; idx++) { + part = &stm32image_dev_info_spec.part_info[idx]; + entry = get_partition_entry(part->name); + if (entry == NULL) { + ERROR("Partition %s not found\n", part->name); + panic(); + } + + part->part_offset = entry->start; + part->bkp_offset = 0U; + } + +#if STM32MP_EMMC_BOOT +emmc_boot: +#endif + /* + * Re-open MMC with io_mmc, for better perfs compared to + * io_block. + */ + io_result = register_io_dev_mmc(&mmc_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec, + &storage_dev_handle); + assert(io_result == 0); +} +#endif /* STM32MP_SDMMC || STM32MP_EMMC */ + +#if STM32MP_SPI_NOR +static void boot_spi_nor(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; + + io_result = stm32_qspi_init(); + assert(io_result == 0); + + io_result = register_io_dev_mtd(&spi_dev_con); + assert(io_result == 0); + + /* Open connections to device */ + io_result = io_dev_open(spi_dev_con, + (uintptr_t)&spi_nor_dev_spec, + &storage_dev_handle); + assert(io_result == 0); + + stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size; + + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_BL33_OFFSET; + part->bkp_offset = 0U; + +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEEH_OFFSET; + part->bkp_offset = 0U; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEED_OFFSET; + part->bkp_offset = 0U; + + idx = IMG_IDX_OPTEE_CORE; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEEX_OFFSET; + part->bkp_offset = 0U; +#endif +} +#endif /* STM32MP_SPI_NOR */ + +#if STM32MP_RAW_NAND +static void boot_fmc2_nand(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; + + io_result = stm32_fmc2_init(); + assert(io_result == 0); + + /* Register the IO device on this platform */ + io_result = register_io_dev_mtd(&nand_dev_con); + assert(io_result == 0); + + /* Open connections to device */ + io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec, + &storage_dev_handle); + assert(io_result == 0); + + stm32image_dev_info_spec.device_size = nand_dev_spec.device_size; + + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_BL33_OFFSET; + part->bkp_offset = nand_dev_spec.erase_size; + +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEH_OFFSET; + part->bkp_offset = nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEED_OFFSET; + part->bkp_offset = nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_CORE; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEX_OFFSET; + part->bkp_offset = nand_dev_spec.erase_size; +#endif +} +#endif /* STM32MP_RAW_NAND */ + +#if STM32MP_SPI_NAND +static void boot_spi_nand(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; + + io_result = stm32_qspi_init(); + assert(io_result == 0); + + io_result = register_io_dev_mtd(&spi_dev_con); + assert(io_result == 0); + + /* Open connections to device */ + io_result = io_dev_open(spi_dev_con, + (uintptr_t)&spi_nand_dev_spec, + &storage_dev_handle); + assert(io_result == 0); + + stm32image_dev_info_spec.device_size = + spi_nand_dev_spec.device_size; + + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_BL33_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEH_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEED_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_CORE; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEX_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; +#endif +} +#endif /* STM32MP_SPI_NAND */ + +void stm32mp_io_setup(void) +{ + int io_result __unused; + boot_api_context_t *boot_context = + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + + print_boot_device(boot_context); + + if ((boot_context->boot_partition_used_toboot == 1U) || + (boot_context->boot_partition_used_toboot == 2U)) { + INFO("Boot used partition fsbl%u\n", + boot_context->boot_partition_used_toboot); + } + +#ifndef AARCH32_SP_OPTEE + io_result = register_io_dev_dummy(&dummy_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, + &dummy_dev_handle); + assert(io_result == 0); +#endif + + switch (boot_context->boot_interface_selected) { +#if STM32MP_SDMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + dmbsy(); + boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance); + stm32image_io_setup(); + break; +#endif +#if STM32MP_EMMC + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + dmbsy(); + boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance); + stm32image_io_setup(); + break; +#endif +#if STM32MP_SPI_NOR + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: + dmbsy(); + boot_spi_nor(boot_context); + stm32image_io_setup(); + break; +#endif +#if STM32MP_RAW_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: + dmbsy(); + boot_fmc2_nand(boot_context); + stm32image_io_setup(); + break; +#endif +#if STM32MP_SPI_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: + dmbsy(); + boot_spi_nand(boot_context); + stm32image_io_setup(); + break; +#endif + + default: + ERROR("Boot interface %d not supported\n", + boot_context->boot_interface_selected); + panic(); + break; + } +} + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy. + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int rc; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + rc = policy->check(policy->image_spec); + if (rc == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + + return rc; +} diff --git a/arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h b/arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h new file mode 100644 index 0000000..0f5a64d --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32CUBEPROGRAMMER_H +#define STM32CUBEPROGRAMMER_H + +#include + +#include + +/* Phase definition */ +#define PHASE_FLASHLAYOUT 0U +#define PHASE_SSBL 3U +#define PHASE_CMD 0xF1U +#define PHASE_RESET 0xFFU + +/* Functions provided by plat */ +uint8_t usb_dfu_get_phase(uint8_t alt); + +int stm32cubeprog_usb_load(struct usb_handle *usb_core_handle, + uintptr_t ssbl_base, + size_t ssbl_len); + +int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len); + +#endif /* STM32CUBEPROGRAMMER_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h new file mode 100644 index 0000000..3075d18 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_AUTH_H +#define STM32MP_AUTH_H + +struct stm32mp_auth_ops { + uint32_t (*check_key)(uint8_t *pubkey_in, uint8_t *pubkey_out); + uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in, + uint8_t *signature, uint32_t ecc_algo); +}; + +void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr); +int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer); + +#endif /* STM32MP_AUTH_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_common.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_common.h new file mode 100644 index 0000000..d8d1c13 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_common.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_COMMON_H +#define STM32MP_COMMON_H + +#include + +#include + +#define JEDEC_ST_BKID U(0x0) +#define JEDEC_ST_MFID U(0x20) + +/* Functions to save and get boot context address given by ROM code */ +void stm32mp_save_boot_ctx_address(uintptr_t address); +uintptr_t stm32mp_get_boot_ctx_address(void); +uint16_t stm32mp_get_boot_itf_selected(void); + +bool stm32mp_is_single_core(void); +bool stm32mp_is_closed_device(void); +bool stm32mp_is_auth_supported(void); + +/* Return the base address of the DDR controller */ +uintptr_t stm32mp_ddrctrl_base(void); + +/* Return the base address of the DDR PHY */ +uintptr_t stm32mp_ddrphyc_base(void); + +/* Return the base address of the PWR peripheral */ +uintptr_t stm32mp_pwr_base(void); + +/* Return the base address of the RCC peripheral */ +uintptr_t stm32mp_rcc_base(void); + +/* Check MMU status to allow spinlock use */ +bool stm32mp_lock_available(void); + +int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx, + uint32_t *otp_len); +int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val); +int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val); + +/* Get IWDG platform instance ID from peripheral IO memory base address */ +uint32_t stm32_iwdg_get_instance(uintptr_t base); + +/* Return bitflag mask for expected IWDG configuration from OTP content */ +uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst); + +#if defined(IMAGE_BL2) +/* Update OTP shadow registers with IWDG configuration from device tree */ +uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags); +#endif + +#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2) +/* Get the UART address from its instance number */ +uintptr_t get_uart_address(uint32_t instance_nb); +#endif + +/* Setup the UART console */ +int stm32mp_uart_console_setup(void); + +#if STM32MP_EARLY_CONSOLE +void stm32mp_setup_early_console(void); +#else +static inline void stm32mp_setup_early_console(void) +{ +} +#endif + +/* + * Platform util functions for the GPIO driver + * @bank: Target GPIO bank ID as per DT bindings + * + * Platform shall implement these functions to provide to stm32_gpio + * driver the resource reference for a target GPIO bank. That are + * memory mapped interface base address, interface offset (see below) + * and clock identifier. + * + * stm32_get_gpio_bank_offset() returns a bank offset that is used to + * check DT configuration matches platform implementation of the banks + * description. + */ +uintptr_t stm32_get_gpio_bank_base(unsigned int bank); +unsigned long stm32_get_gpio_bank_clock(unsigned int bank); +uint32_t stm32_get_gpio_bank_offset(unsigned int bank); +bool stm32_gpio_is_secure_at_reset(unsigned int bank); + +/* Return node offset for target GPIO bank ID @bank or a FDT error code */ +int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank); + +/* Get the chip revision */ +uint32_t stm32mp_get_chip_version(void); +/* Get the chip device ID */ +uint32_t stm32mp_get_chip_dev_id(void); + +/* Get SOC name */ +#define STM32_SOC_NAME_SIZE 20 +void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]); + +/* Print CPU information */ +void stm32mp_print_cpuinfo(void); + +/* Print board information */ +void stm32mp_print_boardinfo(void); + +/* Initialise the IO layer and register platform IO devices */ +void stm32mp_io_setup(void); + +#if STM32MP_USE_STM32IMAGE +/* + * Check that the STM32 header of a .stm32 binary image is valid + * @param header: pointer to the stm32 image header + * @param buffer: address of the binary image (payload) + * @return: 0 on success, negative value in case of error + */ +int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer); +#endif /* STM32MP_USE_STM32IMAGE */ + +/* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */ +int stm32mp_map_ddr_non_cacheable(void); +int stm32mp_unmap_ddr(void); + +/* Functions to save and get boot peripheral info */ +void stm32_save_boot_interface(uint32_t interface, uint32_t instance); +void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance); + +#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT +void stm32mp1_fwu_set_boot_idx(void); +#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */ + +#endif /* STM32MP_COMMON_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h new file mode 100644 index 0000000..b7bf1d0 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2022, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_DT_H +#define STM32MP_DT_H + +#include +#include + +#define DT_DISABLED U(0) +#define DT_NON_SECURE U(1) +#define DT_SECURE U(2) +#define DT_SHARED (DT_NON_SECURE | DT_SECURE) + +struct dt_node_info { + uint32_t base; + int32_t clock; + int32_t reset; + uint32_t status; +}; + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +int dt_open_and_check(uintptr_t dt_addr); +int fdt_get_address(void **fdt_addr); +bool fdt_check_node(int node); +uint8_t fdt_get_status(int node); +int dt_set_stdout_pinctrl(void); +void dt_fill_device_info(struct dt_node_info *info, int node); +int dt_get_node(struct dt_node_info *info, int offset, const char *compat); +int dt_get_stdout_uart_info(struct dt_node_info *info); +int dt_match_instance_by_compatible(const char *compatible, uintptr_t address); +uint32_t dt_get_ddr_size(void); +uint32_t dt_get_pwr_vdd_voltage(void); +struct rdev *dt_get_vdd_regulator(void); +struct rdev *dt_get_cpu_regulator(void); +const char *dt_get_board_model(void); +int dt_find_otp_name(const char *name, uint32_t *otp, uint32_t *otp_len); +int fdt_get_gpio_bank_pin_count(unsigned int bank); + +#endif /* STM32MP_DT_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h new file mode 100644 index 0000000..490560f --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#ifndef STM32MP_EFI_H +#define STM32MP_EFI_H + +#include + +#define STM32MP_FIP_GUID \ + EFI_GUID(0x19d5df83, 0x11b0, 0x457b, \ + 0xbe, 0x2c, 0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5) + +#endif /* STM32MP_EFI_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h new file mode 100644 index 0000000..18884ae --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_FCONF_GETTER +#define STM32MP_FCONF_GETTER + +#include + +#include +#include + +/* IO policies */ +#define stm32mp__io_policies_getter(id) __extension__ ({ \ + assert((id) < MAX_NUMBER_IDS); \ + &policies[id]; \ +}) + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + struct efi_guid img_type_guid; + int (*check)(const uintptr_t spec); +}; + +extern struct plat_io_policy policies[]; +int fconf_populate_stm32mp_io_policies(uintptr_t config); + +#endif /* STM32MP_FCONF_GETTER */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h new file mode 100644 index 0000000..989c890 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef STM32MP_IO_STORAGE_H +#define STM32MP_IO_STORAGE_H + +#include + +#include + +/* IO devices handle */ +extern uintptr_t storage_dev_handle; +extern uintptr_t fip_dev_handle; + +extern io_block_spec_t image_block_spec; + +/* Function declarations */ +int open_fip(const uintptr_t spec); +int open_storage(const uintptr_t spec); + +#endif /* STM32MP_IO_STORAGE_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h new file mode 100644 index 0000000..13f4b13 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_SHARED_RESOURCES_H +#define STM32MP_SHARED_RESOURCES_H + +#include +#include + +#ifdef STM32MP_SHARED_RESOURCES +enum stm32mp_shres; + +/* Return true if @clock_id is shared by secure and non-secure worlds */ +bool stm32mp_nsec_can_access_clock(unsigned long clock_id); + +/* Return true if and only if @reset_id relates to a non-secure peripheral */ +bool stm32mp_nsec_can_access_reset(unsigned int reset_id); + +/* Register a shared resource assigned to the secure world */ +void stm32mp_register_secure_periph(enum stm32mp_shres id); + +/* Register a shared resource assigned to the non-secure world */ +void stm32mp_register_non_secure_periph(enum stm32mp_shres id); + +/* Register a peripheral as secure or non-secure based on IO base address */ +void stm32mp_register_secure_periph_iomem(uintptr_t base); +void stm32mp_register_non_secure_periph_iomem(uintptr_t base); + +/* Register a GPIO as secure or non-secure based on its bank and pin numbers */ +void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin); +void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin); + +/* Consolidate peripheral states and lock against new peripheral registering */ +void stm32mp_lock_periph_registering(void); +#else +static inline void stm32mp_register_secure_periph_iomem(uintptr_t base __unused) +{ +} + +static inline +void stm32mp_register_non_secure_periph_iomem(uintptr_t base __unused) +{ +} + +static inline void stm32mp_register_secure_gpio(unsigned int bank __unused, + unsigned int pin __unused) +{ +} + +static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused, + unsigned int pin __unused) +{ +} +#endif /* STM32MP_SHARED_RESOURCES */ +#endif /* STM32MP_SHARED_RESOURCES_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/usb_dfu.h b/arm-trusted-firmware/plat/st/common/include/usb_dfu.h new file mode 100644 index 0000000..f7d4245 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/usb_dfu.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef USB_DFU_H +#define USB_DFU_H + +#include + +#include + +#define DFU_DESCRIPTOR_TYPE 0x21U + +/* Max DFU Packet Size = 1024 bytes */ +#define USBD_DFU_XFER_SIZE 1024U + +#define TRANSFER_SIZE_BYTES(size) \ + ((uint8_t)((size) & 0xFF)), /* XFERSIZEB0 */\ + ((uint8_t)((size) >> 8)) /* XFERSIZEB1 */ + +/* + * helper for descriptor of DFU interface 0 Alternate setting n + * with iInterface = index of string descriptor, assumed Nth user string + */ +#define USBD_DFU_IF_DESC(n) 0x09U, /* Interface Descriptor size */\ + USB_DESC_TYPE_INTERFACE, /* descriptor type */\ + 0x00U, /* Number of Interface */\ + (n), /* Alternate setting */\ + 0x00U, /* bNumEndpoints*/\ + 0xFEU, /* Application Specific Class Code */\ + 0x01U, /* Device Firmware Upgrade Code */\ + 0x02U, /* DFU mode protocol */ \ + USBD_IDX_USER0_STR + (n) /* iInterface */ + +/* DFU1.1 Standard */ +#define USB_DFU_VERSION 0x0110U +#define USB_DFU_ITF_SIZ 9U +#define USB_DFU_DESC_SIZ(itf) (USB_DFU_ITF_SIZ * ((itf) + 2U)) + +/* + * bmAttribute value for DFU: + * bitCanDnload = 1(bit 0) + * bitCanUpload = 1(bit 1) + * bitManifestationTolerant = 1 (bit 2) + * bitWillDetach = 1(bit 3) + * Reserved (bit4-6) + * bitAcceleratedST = 0(bit 7) + */ +#define DFU_BM_ATTRIBUTE 0x0FU + +#define DFU_STATUS_SIZE 6U + +/* Callback for media access */ +struct usb_dfu_media { + int (*upload)(uint8_t alt, uintptr_t *buffer, uint32_t *len, + void *user_data); + int (*download)(uint8_t alt, uintptr_t *buffer, uint32_t *len, + void *user_data); + int (*manifestation)(uint8_t alt, void *user_data); +}; + +/* Internal DFU handle */ +struct usb_dfu_handle { + uint8_t status[DFU_STATUS_SIZE]; + uint8_t dev_state; + uint8_t dev_status; + uint8_t alt_setting; + const struct usb_dfu_media *callback; +}; + +void usb_dfu_register(struct usb_handle *pdev, struct usb_dfu_handle *phandle); + +int usb_dfu_loop(struct usb_handle *pdev, const struct usb_dfu_media *pmedia); + +/* Function provided by plat */ +struct usb_handle *usb_dfu_plat_init(void); + +#endif /* USB_DFU_H */ diff --git a/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c b/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c new file mode 100644 index 0000000..46ac9cf --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* USART bootloader protocol version V4.0 */ +#define USART_BL_VERSION 0x40U + +/* Command definition */ +#define GET_CMD_COMMAND 0x00U +#define GET_VER_COMMAND 0x01U +#define GET_ID_COMMAND 0x02U +#define PHASE_COMMAND 0x03U +#define READ_PART_COMMAND 0x12U +#define START_COMMAND 0x21U +#define DOWNLOAD_COMMAND 0x31U + +/* Answer defines */ +#define INIT_BYTE 0x7FU +#define ACK_BYTE 0x79U +#define NACK_BYTE 0x1FU +#define ABORT 0x5FU + +#define UNDEFINED_DOWN_ADDR U(0xFFFFFFFF) +#define PROGRAMMER_TIMEOUT_US 20000U + +static const uint8_t command_tab[] = { + GET_CMD_COMMAND, + GET_VER_COMMAND, + GET_ID_COMMAND, + PHASE_COMMAND, + START_COMMAND, + DOWNLOAD_COMMAND +}; + +/* STM32CubeProgrammer over UART handle */ +struct stm32prog_uart_handle_s { + struct stm32_uart_handle_s uart; + uint32_t packet; + uint8_t *addr; + uint32_t len; + uint8_t phase; + /* Error msg buffer: max 255 in UART protocol, reduced in TF-A */ + uint8_t error[64]; +} handle; + +/* Trace and handle unrecoverable UART protocol error */ +#define STM32PROG_ERROR(...) \ + { \ + ERROR(__VA_ARGS__); \ + if (handle.phase != PHASE_RESET) { \ + snprintf((char *)&handle.error, sizeof(handle.error), __VA_ARGS__); \ + handle.phase = PHASE_RESET; \ + handle.addr = (uint8_t *)UNDEFINED_DOWN_ADDR; \ + handle.len = 0U; \ + handle.packet = 0U; \ + } \ + } + +static int uart_write(const uint8_t *addr, uint16_t size) +{ + while (size != 0U) { + if (stm32_uart_putc(&handle.uart, *addr) != 0) { + return -EIO; + } + size--; + addr++; + } + + return 0; +} + +static int uart_write_8(uint8_t byte) +{ + return stm32_uart_putc(&handle.uart, byte); +} + +static int uart_write_32(uint32_t value) +{ + return uart_write((uint8_t *)&value, 4U); +} + +static int uart_read_8(uint8_t *byte) +{ + int ret; + uint64_t timeout_ref = timeout_init_us(PROGRAMMER_TIMEOUT_US); + + do { + ret = stm32_uart_getc(&handle.uart); + if (ret == -EAGAIN) { + if (timeout_elapsed(timeout_ref)) { + return -ETIMEDOUT; + } + } else if (ret < 0) { + return ret; + } + } while (ret == -EAGAIN); + + *byte = (uint8_t)ret; + + return 0; +} + +static int uart_send_result(uint8_t byte) +{ + int ret; + + /* Always flush fifo before to send result = read all pending data */ + do { + ret = stm32_uart_getc(&handle.uart); + } while (ret >= 0); + + return uart_write_8(byte); +} + +static bool is_valid_header(fip_toc_header_t *header) +{ + return (header->name == TOC_HEADER_NAME) && + (header->serial_number != 0U); +} + +static int uart_receive_command(uint8_t *command) +{ + uint8_t byte = 0U; + uint8_t xor = 0U; + unsigned int count; + bool found = false; + int ret; + + /* Repeat read until something is received */ + do { + stm32_iwdg_refresh(); + ret = uart_read_8(&byte); + } while (ret == -ETIMEDOUT); + + if (ret != 0) { + return ret; + } + + /* Handle reconnection request */ + if (byte == INIT_BYTE) { + *command = byte; + return 0; + } + + for (count = 0U; count < ARRAY_SIZE(command_tab); count++) { + if (command_tab[count] == byte) { + found = true; + break; + } + } + if (!found) { + VERBOSE("UART: Command unknown (byte=0x%x)\n", byte); + return -EPROTO; + } + + ret = uart_read_8(&xor); + if (ret != 0) { + return ret; + } + if ((byte ^ xor) != 0xFF) { + VERBOSE("UART: Command XOR check fail (byte=0x%x, xor=0x%x)\n", + byte, xor); + return -EPROTO; + } + + *command = byte; + + return 0; +} + +static int get_cmd_command(void) +{ + const uint8_t msg[2] = { + sizeof(command_tab), /* Length of data - 1 */ + USART_BL_VERSION + }; + int ret; + + ret = uart_write(msg, sizeof(msg)); + if (ret != 0) { + return ret; + } + + return uart_write(command_tab, sizeof(command_tab)); +} + +static int get_version_command(void) +{ + return uart_write_8(STM32_TF_VERSION); +} + +static int get_id_command(void) +{ + uint8_t msg[3] = { + sizeof(msg) - 1 /* Length of data - 1 */ + }; + uint32_t chip_id = stm32mp_get_chip_dev_id(); + + be16enc(&msg[1], chip_id); + + return uart_write(msg, sizeof(msg)); +} + +static int uart_send_phase(uint32_t address) +{ + int ret; + uint8_t msg_size = 5U; /* Length of data - 1 */ + uint8_t error_size = 0U; + + /* Additional information only for RESET phase */ + if (handle.phase == PHASE_RESET) { + error_size = strnlen((char *)&handle.error, sizeof(handle.error)); + } + ret = uart_write_8(msg_size + error_size); + if (ret != 0) { + return ret; + } + + /* Send the ID of next partition */ + ret = uart_write_8(handle.phase); + if (ret != 0) { + return ret; + } + + /* Destination address */ + ret = uart_write_32(address); + if (ret != 0) { + return ret; + } + + ret = uart_write_8(error_size); + if (ret != 0) { + return ret; + } + + /* Additional information: message error */ + if (error_size > 0U) { + ret = uart_write(handle.error, error_size); + } + + return ret; +} + +static int uart_download_part(void) +{ + uint8_t operation = 0U; + uint8_t xor; + uint8_t byte = 0U; + uint32_t packet_number = 0U; + uint32_t packet_size = 0U; + uint32_t i = 0U; + int ret; + + /* Get operation number */ + ret = uart_read_8(&operation); + if (ret != 0) { + return ret; + } + + xor = operation; + + /* Get packet number */ + for (i = 3U; i != 0U; i--) { + ret = uart_read_8(&byte); + if (ret != 0) { + return ret; + } + + xor ^= byte; + packet_number = (packet_number << 8) | byte; + } + + if (packet_number != handle.packet) { + WARN("UART: Bad packet number receive: %u, expected %u\n", + packet_number, handle.packet); + return -EPROTO; + } + + /* Checksum */ + ret = uart_read_8(&byte); + if (ret != 0) { + return ret; + } + if (xor != byte) { + VERBOSE("UART: Download Command checksum xor: %x, received %x\n", + xor, byte); + return -EPROTO; + } + + ret = uart_send_result(ACK_BYTE); + if (ret != 0) { + return ret; + } + + ret = uart_read_8(&byte); + if (ret != 0) { + return ret; + } + xor = byte; + packet_size = byte + 1U; + if (handle.len < packet_size) { + STM32PROG_ERROR("Download overflow at %p\n", handle.addr + packet_size); + return 0; + } + + for (i = 0U; i < packet_size; i++) { + ret = uart_read_8(&byte); + if (ret != 0) { + return ret; + } + + *(handle.addr + i) = byte; + xor ^= byte; + } + + /* Checksum */ + ret = uart_read_8(&byte) != 0; + if (ret != 0) { + return ret; + } + if (xor != byte) { + VERBOSE("UART: Download Data checksum xor: %x, received %x\n", + xor, byte); + return -EPROTO; + } + + /* Packet treated */ + handle.packet++; + handle.addr += packet_size; + handle.len -= packet_size; + + return 0; +} + +static int uart_start_cmd(uintptr_t buffer) +{ + uint8_t byte = 0U; + uint8_t xor = 0U; + uint32_t i; + uint32_t start_address = 0U; + int ret; + + /* Get address */ + for (i = 4U; i != 0U; i--) { + ret = uart_read_8(&byte); + if (ret != 0U) { + return ret; + } + + xor ^= byte; + start_address = (start_address << 8) | byte; + } + + /* Checksum */ + ret = uart_read_8(&byte); + if (ret != 0) { + return ret; + } + + if (xor != byte) { + VERBOSE("UART: Start Command checksum xor: %x, received %x\n", + xor, byte); + return -EPROTO; + } + + if (start_address != UNDEFINED_DOWN_ADDR) { + STM32PROG_ERROR("Invalid start at %x, for phase %u\n", + start_address, handle.phase); + return 0; + } + + if (!is_valid_header((fip_toc_header_t *)buffer)) { + STM32PROG_ERROR("FIP Header check failed %lx, for phase %u\n", + buffer, handle.phase); + return -EIO; + } + VERBOSE("FIP header looks OK.\n"); + + return 0; +} + +static int uart_read(uint8_t id, uintptr_t buffer, size_t length) +{ + bool start_done = false; + int ret; + uint8_t command = 0U; + + handle.phase = id; + handle.packet = 0U; + handle.addr = (uint8_t *)buffer; + handle.len = length; + + INFO("UART: read phase %u at 0x%lx size 0x%x\n", + id, buffer, length); + while (!start_done) { + ret = uart_receive_command(&command); + if (ret != 0) { + /* Delay to wait STM32CubeProgrammer end of transmission */ + mdelay(3); + + ret = uart_send_result(NACK_BYTE); + if (ret != 0U) { + return ret; + } + + continue; + } + + uart_send_result(ACK_BYTE); + + switch (command) { + case INIT_BYTE: + INFO("UART: Connected\n"); + /* Nothing to do */ + continue; + + case GET_CMD_COMMAND: + ret = get_cmd_command(); + break; + + case GET_VER_COMMAND: + ret = get_version_command(); + break; + + case GET_ID_COMMAND: + ret = get_id_command(); + break; + + case PHASE_COMMAND: + ret = uart_send_phase((uint32_t)buffer); + if ((ret == 0) && (handle.phase == PHASE_RESET)) { + start_done = true; + INFO("UART: Reset\n"); + } + break; + + case DOWNLOAD_COMMAND: + ret = uart_download_part(); + break; + + case START_COMMAND: + ret = uart_start_cmd(buffer); + if ((ret == 0) && (handle.phase == id)) { + INFO("UART: Start phase %u\n", handle.phase); + start_done = true; + } + break; + + default: + WARN("UART: Unknown command\n"); + ret = -EINVAL; + break; + } + + if (ret == 0) { + ret = uart_send_result(ACK_BYTE); + } else { + ret = uart_send_result(NACK_BYTE); + } + if (ret != 0) { + return ret; + } + } + + return 0; +} + +/* Init UART: 115200, 8bit 1stop parity even and enable FIFO mode */ +const struct stm32_uart_init_s init = { + .baud_rate = U(115200), + .word_length = STM32_UART_WORDLENGTH_9B, + .stop_bits = STM32_UART_STOPBITS_1, + .parity = STM32_UART_PARITY_EVEN, + .hw_flow_control = STM32_UART_HWCONTROL_NONE, + .mode = STM32_UART_MODE_TX_RX, + .over_sampling = STM32_UART_OVERSAMPLING_16, + .fifo_mode = STM32_UART_FIFOMODE_EN, +}; + +int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len) +{ + int ret; + + if (stm32_uart_init(&handle.uart, instance, &init) != 0) { + return -EIO; + } + + /* + * The following NACK_BYTE is written because STM32CubeProgrammer has + * already sent its command before TF-A has reached this point, and + * because FIFO was not configured by BootROM. + * The byte in the UART_RX register is then the checksum and not the + * command. NACK_BYTE has to be written, so that the programmer will + * re-send the good command. + */ + ret = uart_send_result(NACK_BYTE); + if (ret != 0) { + return ret; + } + + return uart_read(PHASE_SSBL, base, len); +} diff --git a/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c b/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c new file mode 100644 index 0000000..19a6bba --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +/* Undefined download address */ +#define UNDEFINED_DOWN_ADDR 0xFFFFFFFF + +struct dfu_state { + uint8_t phase; + uintptr_t base; + size_t len; + uintptr_t address; + /* working buffer */ + uint8_t buffer[UCHAR_MAX]; +}; + +static struct dfu_state dfu_state; + +/* minimal size of Get Pḧase = offset for additionnl information */ +#define GET_PHASE_LEN 9 + +#define DFU_ERROR(...) \ + { \ + ERROR(__VA_ARGS__); \ + if (dfu->phase != PHASE_RESET) { \ + snprintf((char *)&dfu->buffer[GET_PHASE_LEN], \ + sizeof(dfu->buffer) - GET_PHASE_LEN, \ + __VA_ARGS__); \ + dfu->phase = PHASE_RESET; \ + dfu->address = UNDEFINED_DOWN_ADDR; \ + dfu->len = 0; \ + } \ + } + +static bool is_valid_header(fip_toc_header_t *header) +{ + if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0U)) { + return true; + } + + return false; +} + +static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len, + void *user_data) +{ + int result = 0; + uint32_t length = 0; + struct dfu_state *dfu = (struct dfu_state *)user_data; + + switch (usb_dfu_get_phase(alt)) { + case PHASE_CMD: + /* Get Pḧase */ + dfu->buffer[0] = dfu->phase; + dfu->buffer[1] = (uint8_t)(dfu->address); + dfu->buffer[2] = (uint8_t)(dfu->address >> 8); + dfu->buffer[3] = (uint8_t)(dfu->address >> 16); + dfu->buffer[4] = (uint8_t)(dfu->address >> 24); + dfu->buffer[5] = 0x00; + dfu->buffer[6] = 0x00; + dfu->buffer[7] = 0x00; + dfu->buffer[8] = 0x00; + length = GET_PHASE_LEN; + if (dfu->phase == PHASE_FLASHLAYOUT && + dfu->address == UNDEFINED_DOWN_ADDR) { + INFO("Send detach request\n"); + dfu->buffer[length++] = 0x01; + } + if (dfu->phase == PHASE_RESET) { + /* error information is added by DFU_ERROR macro */ + length += strnlen((char *)&dfu->buffer[GET_PHASE_LEN], + sizeof(dfu->buffer) - GET_PHASE_LEN) + - 1; + } + break; + + default: + DFU_ERROR("phase ID :%i, alternate %i for phase %i\n", + dfu->phase, alt, usb_dfu_get_phase(alt)); + result = -EIO; + break; + } + + if (result == 0) { + *len = length; + *buffer = (uintptr_t)dfu->buffer; + } + + return result; +} + +static int dfu_callback_download(uint8_t alt, uintptr_t *buffer, uint32_t *len, + void *user_data) +{ + struct dfu_state *dfu = (struct dfu_state *)user_data; + + if ((dfu->phase != usb_dfu_get_phase(alt)) || + (dfu->address == UNDEFINED_DOWN_ADDR)) { + DFU_ERROR("phase ID :%i, alternate %i, address %x\n", + dfu->phase, alt, (uint32_t)dfu->address); + return -EIO; + } + + VERBOSE("Download %d %lx %x\n", alt, dfu->address, *len); + *buffer = dfu->address; + dfu->address += *len; + + if (dfu->address - dfu->base > dfu->len) { + return -EIO; + } + + return 0; +} + +static int dfu_callback_manifestation(uint8_t alt, void *user_data) +{ + struct dfu_state *dfu = (struct dfu_state *)user_data; + + if (dfu->phase != usb_dfu_get_phase(alt)) { + ERROR("Manifestation phase ID :%i, alternate %i, address %lx\n", + dfu->phase, alt, dfu->address); + return -EIO; + } + + INFO("phase ID :%i, Manifestation %d at %lx\n", + dfu->phase, alt, dfu->address); + + switch (dfu->phase) { + case PHASE_SSBL: + if (!is_valid_header((fip_toc_header_t *)dfu->base)) { + DFU_ERROR("FIP Header check failed for phase %d\n", alt); + return -EIO; + } + VERBOSE("FIP header looks OK.\n"); + + /* Configure End with request detach */ + dfu->phase = PHASE_FLASHLAYOUT; + dfu->address = UNDEFINED_DOWN_ADDR; + dfu->len = 0; + break; + default: + DFU_ERROR("Unknown phase\n"); + } + + return 0; +} + +/* Open a connection to the USB device */ +static const struct usb_dfu_media usb_dfu_fops = { + .upload = dfu_callback_upload, + .download = dfu_callback_download, + .manifestation = dfu_callback_manifestation, +}; + +int stm32cubeprog_usb_load(struct usb_handle *usb_core_handle, + uintptr_t base, + size_t len) +{ + int ret; + + usb_core_handle->user_data = (void *)&dfu_state; + + INFO("DFU USB START...\n"); + ret = usb_core_start(usb_core_handle); + if (ret != USBD_OK) { + return -EIO; + } + + dfu_state.phase = PHASE_SSBL; + dfu_state.address = base; + dfu_state.base = base; + dfu_state.len = len; + + ret = usb_dfu_loop(usb_core_handle, &usb_dfu_fops); + if (ret != USBD_OK) { + return -EIO; + } + + INFO("DFU USB STOP...\n"); + ret = usb_core_stop(usb_core_handle); + if (ret != USBD_OK) { + return -EIO; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/st/common/stm32mp_auth.c b/arm-trusted-firmware/plat/st/common/stm32mp_auth.c new file mode 100644 index 0000000..97fbffa --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32mp_auth.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +static const struct stm32mp_auth_ops *auth_ops; + +void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr) +{ + if ((init_ptr == NULL) || + (init_ptr->check_key == NULL) || + (init_ptr->verify_signature == NULL) || + (stm32_hash_register() != 0)) { + panic(); + } + + auth_ops = init_ptr; +} + +int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer) +{ + int ret; + uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; + uint32_t header_skip_cksum = sizeof(header->magic) + + sizeof(header->image_signature) + + sizeof(header->payload_checksum); + + /* Check Security Status */ + if (!stm32mp_is_closed_device()) { + if (header->option_flags != 0U) { + WARN("Skip signature check (header option)\n"); + return 0; + } + INFO("Check signature on Open device\n"); + } + + if (auth_ops == NULL) { + ERROR("Device doesn't support image authentication\n"); + return -EOPNOTSUPP; + } + + ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE, + STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE); + if (ret != 0) { + return ret; + } + + /* Check Public Key */ + if (auth_ops->check_key(header->ecc_pubk, NULL) != BOOT_API_RETURN_OK) { + ret = -EINVAL; + goto err; + } + + /* Compute end of header hash and payload hash */ + stm32_hash_init(HASH_SHA256); + + ret = stm32_hash_update((uint8_t *)&header->header_version, + sizeof(boot_api_image_header_t) - + header_skip_cksum); + if (ret != 0) { + ERROR("Hash of header failed, %i\n", ret); + goto err; + } + + ret = stm32_hash_final_update((uint8_t *)buffer, + header->image_length, image_hash); + if (ret != 0) { + ERROR("Hash of payload failed\n"); + goto err; + } + + /* Verify signature */ + if (auth_ops->verify_signature(image_hash, header->ecc_pubk, + header->image_signature, + header->ecc_algo_type) != + BOOT_API_RETURN_OK) { + ret = -EINVAL; + } + +err: + mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED); + return ret; +} diff --git a/arm-trusted-firmware/plat/st/common/stm32mp_common.c b/arm-trusted-firmware/plat/st/common/stm32mp_common.c new file mode 100644 index 0000000..d922d3c --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32mp_common.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2015-2022, 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 + +#define HEADER_VERSION_MAJOR_MASK GENMASK(23, 16) +#define RESET_TIMEOUT_US_1MS 1000U + +static console_t console; + +uintptr_t plat_get_ns_image_entrypoint(void) +{ + return BL33_BASE; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return read_cntfrq_el0(); +} + +static uintptr_t boot_ctx_address; +static uint16_t boot_itf_selected; + +void stm32mp_save_boot_ctx_address(uintptr_t address) +{ + boot_api_context_t *boot_context = (boot_api_context_t *)address; + + boot_ctx_address = address; + boot_itf_selected = boot_context->boot_interface_selected; +} + +uintptr_t stm32mp_get_boot_ctx_address(void) +{ + return boot_ctx_address; +} + +uint16_t stm32mp_get_boot_itf_selected(void) +{ + return boot_itf_selected; +} + +uintptr_t stm32mp_ddrctrl_base(void) +{ + return DDRCTRL_BASE; +} + +uintptr_t stm32mp_ddrphyc_base(void) +{ + return DDRPHYC_BASE; +} + +uintptr_t stm32mp_pwr_base(void) +{ + return PWR_BASE; +} + +uintptr_t stm32mp_rcc_base(void) +{ + return RCC_BASE; +} + +bool stm32mp_lock_available(void) +{ + const uint32_t c_m_bits = SCTLR_M_BIT | SCTLR_C_BIT; + + /* The spinlocks are used only when MMU and data cache are enabled */ + return (read_sctlr() & c_m_bits) == c_m_bits; +} + +#if STM32MP_USE_STM32IMAGE +int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer) +{ + uint32_t i; + uint32_t img_checksum = 0U; + + /* + * Check header/payload validity: + * - Header magic + * - Header version + * - Payload checksum + */ + if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { + ERROR("Header magic\n"); + return -EINVAL; + } + + if ((header->header_version & HEADER_VERSION_MAJOR_MASK) != + (BOOT_API_HEADER_VERSION & HEADER_VERSION_MAJOR_MASK)) { + ERROR("Header version\n"); + return -EINVAL; + } + + for (i = 0U; i < header->image_length; i++) { + img_checksum += *(uint8_t *)(buffer + i); + } + + if (header->payload_checksum != img_checksum) { + ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum, + header->payload_checksum); + return -EINVAL; + } + + return 0; +} +#endif /* STM32MP_USE_STM32IMAGE */ + +int stm32mp_map_ddr_non_cacheable(void) +{ + return mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, + STM32MP_DDR_MAX_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_SECURE); +} + +int stm32mp_unmap_ddr(void) +{ + return mmap_remove_dynamic_region(STM32MP_DDR_BASE, + STM32MP_DDR_MAX_SIZE); +} + +int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx, + uint32_t *otp_len) +{ + assert(otp_name != NULL); + assert(otp_idx != NULL); + + return dt_find_otp_name(otp_name, otp_idx, otp_len); +} + +int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val) +{ + uint32_t otp_idx; + + assert(otp_name != NULL); + assert(otp_val != NULL); + + if (stm32_get_otp_index(otp_name, &otp_idx, NULL) != 0) { + return -1; + } + + if (stm32_get_otp_value_from_idx(otp_idx, otp_val) != 0) { + ERROR("BSEC: %s Read Error\n", otp_name); + return -1; + } + + return 0; +} + +int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val) +{ + uint32_t ret = BSEC_NOT_SUPPORTED; + + assert(otp_val != NULL); + +#if defined(IMAGE_BL2) + ret = bsec_shadow_read_otp(otp_val, otp_idx); +#elif defined(IMAGE_BL32) + ret = bsec_read_otp(otp_val, otp_idx); +#else +#error "Not supported" +#endif + if (ret != BSEC_OK) { + ERROR("BSEC: idx=%u Read Error\n", otp_idx); + return -1; + } + + return 0; +} + +#if defined(IMAGE_BL2) +static void reset_uart(uint32_t reset) +{ + int ret; + + ret = stm32mp_reset_assert(reset, RESET_TIMEOUT_US_1MS); + if (ret != 0) { + panic(); + } + + udelay(2); + + ret = stm32mp_reset_deassert(reset, RESET_TIMEOUT_US_1MS); + if (ret != 0) { + panic(); + } + + mdelay(1); +} +#endif + +static void set_console(uintptr_t base, uint32_t clk_rate) +{ + unsigned int console_flags; + + if (console_stm32_register(base, clk_rate, + (uint32_t)STM32MP_UART_BAUDRATE, &console) == 0) { + panic(); + } + + console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH | + CONSOLE_FLAG_TRANSLATE_CRLF; +#if !defined(IMAGE_BL2) && defined(DEBUG) + console_flags |= CONSOLE_FLAG_RUNTIME; +#endif + + console_set_scope(&console, console_flags); +} + +int stm32mp_uart_console_setup(void) +{ + struct dt_node_info dt_uart_info; + uint32_t clk_rate = 0U; + int result; + uint32_t boot_itf __unused; + uint32_t boot_instance __unused; + + result = dt_get_stdout_uart_info(&dt_uart_info); + + if ((result <= 0) || + (dt_uart_info.status == DT_DISABLED)) { + return -ENODEV; + } + +#if defined(IMAGE_BL2) + if ((dt_uart_info.clock < 0) || + (dt_uart_info.reset < 0)) { + return -ENODEV; + } +#endif + +#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2) + stm32_get_boot_interface(&boot_itf, &boot_instance); + + if ((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) && + (get_uart_address(boot_instance) == dt_uart_info.base)) { + return -EACCES; + } +#endif + +#if defined(IMAGE_BL2) + if (dt_set_stdout_pinctrl() != 0) { + return -ENODEV; + } + + clk_enable((unsigned long)dt_uart_info.clock); + + reset_uart((uint32_t)dt_uart_info.reset); + + clk_rate = clk_get_rate((unsigned long)dt_uart_info.clock); +#endif + + set_console(dt_uart_info.base, clk_rate); + + return 0; +} + +#if STM32MP_EARLY_CONSOLE +void stm32mp_setup_early_console(void) +{ + plat_crash_console_init(); + set_console(STM32MP_DEBUG_USART_BASE, STM32MP_DEBUG_USART_CLK_FRQ); +} +#endif /* STM32MP_EARLY_CONSOLE */ + +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC + * feature is availabile for platform. + * @fid: SMCCC function id + * + * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and + * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} + +/* Get SOC version */ +int32_t plat_get_soc_version(void) +{ + uint32_t chip_id = stm32mp_get_chip_dev_id(); + uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_ST_BKID, JEDEC_ST_MFID); + + return (int32_t)(manfid | (chip_id & SOC_ID_IMPL_DEF_MASK)); +} + +/* Get SOC revision */ +int32_t plat_get_soc_revision(void) +{ + return (int32_t)(stm32mp_get_chip_version() & SOC_ID_REV_MASK); +} diff --git a/arm-trusted-firmware/plat/st/common/stm32mp_dt.c b/arm-trusted-firmware/plat/st/common/stm32mp_dt.c new file mode 100644 index 0000000..ea71571 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32mp_dt.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void *fdt; + +/******************************************************************************* + * This function checks device tree file with its header. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +int dt_open_and_check(uintptr_t dt_addr) +{ + int ret; + + ret = fdt_check_header((void *)dt_addr); + if (ret == 0) { + fdt = (void *)dt_addr; + } + + return ret; +} + +/******************************************************************************* + * This function gets the address of the DT. + * If DT is OK, fdt_addr is filled with DT address. + * Returns 1 if success, 0 otherwise. + ******************************************************************************/ +int fdt_get_address(void **fdt_addr) +{ + if (fdt == NULL) { + return 0; + } + + *fdt_addr = fdt; + + return 1; +} + +/******************************************************************************* + * This function check the presence of a node (generic use of fdt library). + * Returns true if present, else return false. + ******************************************************************************/ +bool fdt_check_node(int node) +{ + int len; + const char *cchar; + + cchar = fdt_get_name(fdt, node, &len); + + return (cchar != NULL) && (len >= 0); +} + +/******************************************************************************* + * This function return global node status (generic use of fdt library). + ******************************************************************************/ +uint8_t fdt_get_status(int node) +{ + uint8_t status = DT_DISABLED; + const char *cchar; + + cchar = fdt_getprop(fdt, node, "status", NULL); + if ((cchar == NULL) || + (strncmp(cchar, "okay", strlen("okay")) == 0)) { + status |= DT_NON_SECURE; + } + + cchar = fdt_getprop(fdt, node, "secure-status", NULL); + if (cchar == NULL) { + if (status == DT_NON_SECURE) { + status |= DT_SECURE; + } + } else if (strncmp(cchar, "okay", strlen("okay")) == 0) { + status |= DT_SECURE; + } + + return status; +} + +#if ENABLE_ASSERTIONS +/******************************************************************************* + * This function returns the address cells from the node parent. + * Returns: + * - #address-cells value if success. + * - invalid value if error. + * - a default value if undefined #address-cells property as per libfdt + * implementation. + ******************************************************************************/ +static int fdt_get_node_parent_address_cells(int node) +{ + int parent; + + parent = fdt_parent_offset(fdt, node); + if (parent < 0) { + return -FDT_ERR_NOTFOUND; + } + + return fdt_address_cells(fdt, parent); +} +#endif + +/******************************************************************************* + * This function gets the stdout pin configuration information from the DT. + * And then calls the sub-function to treat it and set GPIO registers. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +int dt_set_stdout_pinctrl(void) +{ + int node; + + node = fdt_get_stdout_node_offset(fdt); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + return dt_set_pinctrl_config(node); +} + +/******************************************************************************* + * This function fills the generic information from a given node. + ******************************************************************************/ +void dt_fill_device_info(struct dt_node_info *info, int node) +{ + const fdt32_t *cuint; + + assert(fdt_get_node_parent_address_cells(node) == 1); + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint != NULL) { + info->base = fdt32_to_cpu(*cuint); + } else { + info->base = 0; + } + + cuint = fdt_getprop(fdt, node, "clocks", NULL); + if (cuint != NULL) { + cuint++; + info->clock = (int)fdt32_to_cpu(*cuint); + } else { + info->clock = -1; + } + + cuint = fdt_getprop(fdt, node, "resets", NULL); + if (cuint != NULL) { + cuint++; + info->reset = (int)fdt32_to_cpu(*cuint); + } else { + info->reset = -1; + } + + info->status = fdt_get_status(node); +} + +/******************************************************************************* + * This function retrieve the generic information from DT. + * Returns node on success and a negative FDT error code on failure. + ******************************************************************************/ +int dt_get_node(struct dt_node_info *info, int offset, const char *compat) +{ + int node; + + node = fdt_node_offset_by_compatible(fdt, offset, compat); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + dt_fill_device_info(info, node); + + return node; +} + +/******************************************************************************* + * This function gets the UART instance info of stdout from the DT. + * Returns node on success and a negative FDT error code on failure. + ******************************************************************************/ +int dt_get_stdout_uart_info(struct dt_node_info *info) +{ + int node; + + node = fdt_get_stdout_node_offset(fdt); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + dt_fill_device_info(info, node); + + return node; +} + +/******************************************************************************* + * This function returns the node offset matching compatible string in the DT, + * and also matching the reg property with the given address. + * Returns value on success, and error value on failure. + ******************************************************************************/ +int dt_match_instance_by_compatible(const char *compatible, uintptr_t address) +{ + int node; + + fdt_for_each_compatible_node(fdt, node, compatible) { + const fdt32_t *cuint; + + assert(fdt_get_node_parent_address_cells(node) == 1); + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint == NULL) { + continue; + } + + if ((uintptr_t)fdt32_to_cpu(*cuint) == address) { + return node; + } + } + + return -FDT_ERR_NOTFOUND; +} + +/******************************************************************************* + * This function gets DDR size information from the DT. + * Returns value in bytes on success, and 0 on failure. + ******************************************************************************/ +uint32_t dt_get_ddr_size(void) +{ + static uint32_t size; + int node; + + if (size != 0U) { + return size; + } + + node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); + if (node < 0) { + INFO("%s: Cannot read DDR node in DT\n", __func__); + return 0; + } + + size = fdt_read_uint32_default(fdt, node, "st,mem-size", 0U); + + flush_dcache_range((uintptr_t)&size, sizeof(uint32_t)); + + return size; +} + +/******************************************************************************* + * This function gets PWR VDD regulator voltage information from the DT. + * Returns value in microvolts on success, and 0 on failure. + ******************************************************************************/ +uint32_t dt_get_pwr_vdd_voltage(void) +{ + struct rdev *regul = dt_get_vdd_regulator(); + uint16_t min; + + if (regul == NULL) { + return 0; + } + + regulator_get_range(regul, &min, NULL); + + return (uint32_t)min * 1000U; +} + +/******************************************************************************* + * This function retrieves VDD supply regulator from DT. + * Returns an rdev taken from supply node, NULL otherwise. + ******************************************************************************/ +struct rdev *dt_get_vdd_regulator(void) +{ + int node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); + + if (node < 0) { + return NULL; + } + + return regulator_get_by_supply_name(fdt, node, "vdd"); +} + +/******************************************************************************* + * This function retrieves CPU supply regulator from DT. + * Returns an rdev taken from supply node, NULL otherwise. + ******************************************************************************/ +struct rdev *dt_get_cpu_regulator(void) +{ + int node = fdt_path_offset(fdt, "/cpus/cpu@0"); + + if (node < 0) { + return NULL; + } + + return regulator_get_by_supply_name(fdt, node, "cpu"); +} + +/******************************************************************************* + * This function retrieves board model from DT + * Returns string taken from model node, NULL otherwise + ******************************************************************************/ +const char *dt_get_board_model(void) +{ + int node = fdt_path_offset(fdt, "/"); + + if (node < 0) { + return NULL; + } + + return (const char *)fdt_getprop(fdt, node, "model", NULL); +} + +/******************************************************************************* + * dt_find_otp_name: get OTP ID and length in DT. + * name: sub-node name to look up. + * otp: pointer to read OTP number or NULL. + * otp_len: pointer to read OTP length in bits or NULL. + * return value: 0 if no error, an FDT error value otherwise. + ******************************************************************************/ +int dt_find_otp_name(const char *name, uint32_t *otp, uint32_t *otp_len) +{ + int node; + int index, len; + const fdt32_t *cuint; + + if ((name == NULL) || (otp == NULL)) { + return -FDT_ERR_BADVALUE; + } + + node = fdt_node_offset_by_compatible(fdt, -1, DT_NVMEM_LAYOUT_COMPAT); + if (node < 0) { + return node; + } + + index = fdt_stringlist_search(fdt, node, "nvmem-cell-names", name); + if (index < 0) { + return index; + } + + cuint = fdt_getprop(fdt, node, "nvmem-cells", &len); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + if ((index * (int)sizeof(uint32_t)) > len) { + return -FDT_ERR_BADVALUE; + } + + cuint += index; + + node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (node < 0) { + ERROR("Malformed nvmem_layout node: ignored\n"); + return node; + } + + cuint = fdt_getprop(fdt, node, "reg", &len); + if ((cuint == NULL) || (len != (2 * (int)sizeof(uint32_t)))) { + ERROR("Malformed nvmem_layout node: ignored\n"); + return -FDT_ERR_BADVALUE; + } + + if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) { + ERROR("Misaligned nvmem_layout element: ignored\n"); + return -FDT_ERR_BADVALUE; + } + + if (otp != NULL) { + *otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t); + } + + if (otp_len != NULL) { + cuint++; + *otp_len = fdt32_to_cpu(*cuint) * CHAR_BIT; + } + + return 0; +} + +/******************************************************************************* + * This function gets the pin count for a GPIO bank based from the FDT. + * It also checks node consistency. + ******************************************************************************/ +int fdt_get_gpio_bank_pin_count(unsigned int bank) +{ + int pinctrl_node; + int node; + uint32_t bank_offset; + + pinctrl_node = stm32_get_gpio_bank_pinctrl_node(fdt, bank); + if (pinctrl_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + bank_offset = stm32_get_gpio_bank_offset(bank); + + fdt_for_each_subnode(node, fdt, pinctrl_node) { + const fdt32_t *cuint; + int pin_count; + int len; + int i; + + if (fdt_getprop(fdt, node, "gpio-controller", NULL) == NULL) { + continue; + } + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint == NULL) { + continue; + } + + if (fdt32_to_cpu(*cuint) != bank_offset) { + continue; + } + + if (fdt_get_status(node) == DT_DISABLED) { + return 0; + } + + /* Parse gpio-ranges with its 4 parameters */ + cuint = fdt_getprop(fdt, node, "gpio-ranges", &len); + len /= sizeof(*cuint); + if ((len % 4) != 0) { + return -FDT_ERR_BADVALUE; + } + + /* Get the last defined gpio line (offset + nb of pins) */ + pin_count = fdt32_to_cpu(*(cuint + 1)) + fdt32_to_cpu(*(cuint + 3)); + for (i = 0; i < len / 4; i++) { + pin_count = MAX(pin_count, (int)(fdt32_to_cpu(*(cuint + 1)) + + fdt32_to_cpu(*(cuint + 3)))); + cuint += 4; + } + + return pin_count; + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c b/arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c new file mode 100644 index 0000000..ca71958 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if STM32MP_SDMMC || STM32MP_EMMC +static io_block_spec_t gpt_block_spec = { + .offset = 0U, + .length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */ +}; +#endif + +#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT +io_block_spec_t metadata_block_spec = { + .offset = 0, /* To be filled at runtime */ + .length = 0, /* To be filled at runtime */ +}; +#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */ + +/* By default, STM32 platforms load images from the FIP */ +struct plat_io_policy policies[MAX_NUMBER_IDS] = { + [FIP_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&image_block_spec, + .img_type_guid = STM32MP_FIP_GUID, + .check = open_storage + }, +#if STM32MP_SDMMC || STM32MP_EMMC + [GPT_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&gpt_block_spec, + .img_type_guid = NULL_GUID, + .check = open_storage + }, +#endif +#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT + [FWU_METADATA_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&metadata_block_spec, + .img_type_guid = NULL_GUID, + .check = open_storage + }, + [BKUP_FWU_METADATA_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&metadata_block_spec, + .img_type_guid = NULL_GUID, + .check = open_storage + }, +#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */ +}; + +#define FCONF_ST_IO_UUID_NUMBER U(8) + +static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER]; +static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids); + +struct policies_load_info { + unsigned int image_id; + const char *name; +}; + +/* image id to property name table */ +static const struct policies_load_info load_info[FCONF_ST_IO_UUID_NUMBER] = { + {FW_CONFIG_ID, "fw_cfg_uuid"}, + {BL32_IMAGE_ID, "bl32_uuid"}, + {BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"}, + {BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"}, + {BL33_IMAGE_ID, "bl33_uuid"}, + {HW_CONFIG_ID, "hw_cfg_uuid"}, + {TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"}, + {NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"}, +}; + +int fconf_populate_stm32mp_io_policies(uintptr_t config) +{ + int node; + unsigned int i; + + /* As libfdt uses void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* Assert the node offset point to "st,io-fip-handle" compatible property */ + const char *compatible_str = "st,io-fip-handle"; + + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); + return node; + } + + /* Locate the uuid cells and read the value for all the load info uuid */ + for (i = 0U; i < FCONF_ST_IO_UUID_NUMBER; i++) { + union uuid_helper_t uuid_helper; + io_uuid_spec_t *uuid_ptr; + int err; + + uuid_ptr = pool_alloc(&fconf_stm32mp_uuids_pool); + err = fdtw_read_uuid(dtb, node, load_info[i].name, 16, + (uint8_t *)&uuid_helper); + if (err < 0) { + WARN("FCONF: Read cell failed for %s\n", load_info[i].name); + return err; + } + + VERBOSE("FCONF: stm32mp-io_policies.%s cell found with value = " + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + load_info[i].name, + uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1], + uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3], + uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1], + uuid_helper.uuid_struct.time_hi_and_version[0], + uuid_helper.uuid_struct.time_hi_and_version[1], + uuid_helper.uuid_struct.clock_seq_hi_and_reserved, + uuid_helper.uuid_struct.clock_seq_low, + uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1], + uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3], + uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5]); + + uuid_ptr->uuid = uuid_helper.uuid_struct; + policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr; + policies[load_info[i].image_id].dev_handle = &fip_dev_handle; + policies[load_info[i].image_id].check = open_fip; + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(TB_FW, stm32mp_io, fconf_populate_stm32mp_io_policies); diff --git a/arm-trusted-firmware/plat/st/common/usb_dfu.c b/arm-trusted-firmware/plat/st/common/usb_dfu.c new file mode 100644 index 0000000..8bb0994 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/usb_dfu.c @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +/* Device states as defined in DFU spec */ +#define STATE_APP_IDLE 0 +#define STATE_APP_DETACH 1 +#define STATE_DFU_IDLE 2 +#define STATE_DFU_DNLOAD_SYNC 3 +#define STATE_DFU_DNLOAD_BUSY 4 +#define STATE_DFU_DNLOAD_IDLE 5 +#define STATE_DFU_MANIFEST_SYNC 6 +#define STATE_DFU_MANIFEST 7 +#define STATE_DFU_MANIFEST_WAIT_RESET 8 +#define STATE_DFU_UPLOAD_IDLE 9 +#define STATE_DFU_ERROR 10 + +/* DFU errors */ +#define DFU_ERROR_NONE 0x00 +#define DFU_ERROR_TARGET 0x01 +#define DFU_ERROR_FILE 0x02 +#define DFU_ERROR_WRITE 0x03 +#define DFU_ERROR_ERASE 0x04 +#define DFU_ERROR_CHECK_ERASED 0x05 +#define DFU_ERROR_PROG 0x06 +#define DFU_ERROR_VERIFY 0x07 +#define DFU_ERROR_ADDRESS 0x08 +#define DFU_ERROR_NOTDONE 0x09 +#define DFU_ERROR_FIRMWARE 0x0A +#define DFU_ERROR_VENDOR 0x0B +#define DFU_ERROR_USB 0x0C +#define DFU_ERROR_POR 0x0D +#define DFU_ERROR_UNKNOWN 0x0E +#define DFU_ERROR_STALLEDPKT 0x0F + +/* DFU request */ +#define DFU_DETACH 0 +#define DFU_DNLOAD 1 +#define DFU_UPLOAD 2 +#define DFU_GETSTATUS 3 +#define DFU_CLRSTATUS 4 +#define DFU_GETSTATE 5 +#define DFU_ABORT 6 + +static bool usb_dfu_detach_req; + +/* + * usb_dfu_init + * Initialize the DFU interface + * pdev: device instance + * cfgidx: Configuration index + * return: status + */ +static uint8_t usb_dfu_init(struct usb_handle *pdev, uint8_t cfgidx) +{ + (void)pdev; + (void)cfgidx; + + /* Nothing to do in this stage */ + return USBD_OK; +} + +/* + * usb_dfu_de_init + * De-Initialize the DFU layer + * pdev: device instance + * cfgidx: Configuration index + * return: status + */ +static uint8_t usb_dfu_de_init(struct usb_handle *pdev, uint8_t cfgidx) +{ + (void)pdev; + (void)cfgidx; + + /* Nothing to do in this stage */ + return USBD_OK; +} + +/* + * usb_dfu_data_in + * handle data IN Stage + * pdev: device instance + * epnum: endpoint index + * return: status + */ +static uint8_t usb_dfu_data_in(struct usb_handle *pdev, uint8_t epnum) +{ + (void)pdev; + (void)epnum; + + return USBD_OK; +} + +/* + * usb_dfu_ep0_rx_ready + * handle EP0 Rx Ready event + * pdev: device + * return: status + */ +static uint8_t usb_dfu_ep0_rx_ready(struct usb_handle *pdev) +{ + (void)pdev; + + return USBD_OK; +} + +/* + * usb_dfu_ep0_tx_ready + * handle EP0 TRx Ready event + * pdev: device instance + * return: status + */ +static uint8_t usb_dfu_ep0_tx_ready(struct usb_handle *pdev) +{ + (void)pdev; + + return USBD_OK; +} + +/* + * usb_dfu_sof + * handle SOF event + * pdev: device instance + * return: status + */ +static uint8_t usb_dfu_sof(struct usb_handle *pdev) +{ + (void)pdev; + + return USBD_OK; +} + +/* + * usb_dfu_iso_in_incomplete + * handle data ISO IN Incomplete event + * pdev: device instance + * epnum: endpoint index + * return: status + */ +static uint8_t usb_dfu_iso_in_incomplete(struct usb_handle *pdev, uint8_t epnum) +{ + (void)pdev; + (void)epnum; + + return USBD_OK; +} + +/* + * usb_dfu_iso_out_incomplete + * handle data ISO OUT Incomplete event + * pdev: device instance + * epnum: endpoint index + * return: status + */ +static uint8_t usb_dfu_iso_out_incomplete(struct usb_handle *pdev, + uint8_t epnum) +{ + (void)pdev; + (void)epnum; + + return USBD_OK; +} + +/* + * usb_dfu_data_out + * handle data OUT Stage + * pdev: device instance + * epnum: endpoint index + * return: status + */ +static uint8_t usb_dfu_data_out(struct usb_handle *pdev, uint8_t epnum) +{ + (void)pdev; + (void)epnum; + + return USBD_OK; +} + +/* + * usb_dfu_detach + * Handles the DFU DETACH request. + * pdev: device instance + * req: pointer to the request structure. + */ +static void usb_dfu_detach(struct usb_handle *pdev, struct usb_setup_req *req) +{ + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + + INFO("Receive DFU Detach\n"); + + if ((hdfu->dev_state == STATE_DFU_IDLE) || + (hdfu->dev_state == STATE_DFU_DNLOAD_SYNC) || + (hdfu->dev_state == STATE_DFU_DNLOAD_IDLE) || + (hdfu->dev_state == STATE_DFU_MANIFEST_SYNC) || + (hdfu->dev_state == STATE_DFU_UPLOAD_IDLE)) { + /* Update the state machine */ + hdfu->dev_state = STATE_DFU_IDLE; + hdfu->dev_status = DFU_ERROR_NONE; + } + + usb_dfu_detach_req = true; +} + +/* + * usb_dfu_download + * Handles the DFU DNLOAD request. + * pdev: device instance + * req: pointer to the request structure + */ +static void usb_dfu_download(struct usb_handle *pdev, struct usb_setup_req *req) +{ + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + uintptr_t data_ptr; + uint32_t length; + int ret; + + /* Data setup request */ + if (req->length > 0) { + /* Unsupported state */ + if ((hdfu->dev_state != STATE_DFU_IDLE) && + (hdfu->dev_state != STATE_DFU_DNLOAD_IDLE)) { + /* Call the error management function (command will be nacked) */ + usb_core_ctl_error(pdev); + return; + } + + /* Get the data address */ + length = req->length; + ret = hdfu->callback->download(hdfu->alt_setting, &data_ptr, + &length, pdev->user_data); + if (ret == 0U) { + /* Update the state machine */ + hdfu->dev_state = STATE_DFU_DNLOAD_SYNC; + /* Start the transfer */ + usb_core_receive_ep0(pdev, (uint8_t *)data_ptr, length); + } else { + usb_core_ctl_error(pdev); + } + } else { + /* End of DNLOAD operation*/ + if (hdfu->dev_state != STATE_DFU_DNLOAD_IDLE) { + /* Call the error management function (command will be nacked) */ + usb_core_ctl_error(pdev); + return; + } + /* End of DNLOAD operation*/ + hdfu->dev_state = STATE_DFU_MANIFEST_SYNC; + ret = hdfu->callback->manifestation(hdfu->alt_setting, pdev->user_data); + if (ret == 0U) { + hdfu->dev_state = STATE_DFU_MANIFEST_SYNC; + } else { + usb_core_ctl_error(pdev); + } + } +} + +/* + * usb_dfu_upload + * Handles the DFU UPLOAD request. + * pdev: instance + * req: pointer to the request structure + */ +static void usb_dfu_upload(struct usb_handle *pdev, struct usb_setup_req *req) +{ + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + uintptr_t data_ptr; + uint32_t length; + int ret; + + /* Data setup request */ + if (req->length == 0) { + /* No Data setup request */ + hdfu->dev_state = STATE_DFU_IDLE; + return; + } + + /* Unsupported state */ + if ((hdfu->dev_state != STATE_DFU_IDLE) && (hdfu->dev_state != STATE_DFU_UPLOAD_IDLE)) { + ERROR("UPLOAD : Unsupported State\n"); + /* Call the error management function (command will be nacked) */ + usb_core_ctl_error(pdev); + return; + } + + /* Update the data address */ + length = req->length; + ret = hdfu->callback->upload(hdfu->alt_setting, &data_ptr, &length, pdev->user_data); + if (ret == 0U) { + /* Short frame */ + hdfu->dev_state = (req->length > length) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, (uint8_t *)data_ptr, length); + } else { + ERROR("UPLOAD : bad block %i on alt %i\n", req->value, req->index); + hdfu->dev_state = STATE_DFU_ERROR; + hdfu->dev_status = DFU_ERROR_STALLEDPKT; + + /* Call the error management function (command will be nacked) */ + usb_core_ctl_error(pdev); + } +} + +/* + * usb_dfu_get_status + * Handles the DFU GETSTATUS request. + * pdev: instance + */ +static void usb_dfu_get_status(struct usb_handle *pdev) +{ + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + + hdfu->status[0] = hdfu->dev_status; /* bStatus */ + hdfu->status[1] = 0; /* bwPollTimeout[3] */ + hdfu->status[2] = 0; + hdfu->status[3] = 0; + hdfu->status[4] = hdfu->dev_state; /* bState */ + hdfu->status[5] = 0; /* iString */ + + /* next step */ + switch (hdfu->dev_state) { + case STATE_DFU_DNLOAD_SYNC: + hdfu->dev_state = STATE_DFU_DNLOAD_IDLE; + break; + case STATE_DFU_MANIFEST_SYNC: + /* the device is 'ManifestationTolerant' */ + hdfu->status[4] = STATE_DFU_MANIFEST; + hdfu->status[1] = 1U; /* bwPollTimeout = 1ms */ + hdfu->dev_state = STATE_DFU_IDLE; + break; + + default: + break; + } + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->status[0], sizeof(hdfu->status)); +} + +/* + * usb_dfu_clear_status + * Handles the DFU CLRSTATUS request. + * pdev: device instance + */ +static void usb_dfu_clear_status(struct usb_handle *pdev) +{ + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + + if (hdfu->dev_state == STATE_DFU_ERROR) { + hdfu->dev_state = STATE_DFU_IDLE; + hdfu->dev_status = DFU_ERROR_NONE; + } else { + /* State Error */ + hdfu->dev_state = STATE_DFU_ERROR; + hdfu->dev_status = DFU_ERROR_UNKNOWN; + } +} + +/* + * usb_dfu_get_state + * Handles the DFU GETSTATE request. + * pdev: device instance + */ +static void usb_dfu_get_state(struct usb_handle *pdev) +{ + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + + /* Return the current state of the DFU interface */ + usb_core_transmit_ep0(pdev, &hdfu->dev_state, 1); +} + +/* + * usb_dfu_abort + * Handles the DFU ABORT request. + * pdev: device instance + */ +static void usb_dfu_abort(struct usb_handle *pdev) +{ + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + + if ((hdfu->dev_state == STATE_DFU_IDLE) || + (hdfu->dev_state == STATE_DFU_DNLOAD_SYNC) || + (hdfu->dev_state == STATE_DFU_DNLOAD_IDLE) || + (hdfu->dev_state == STATE_DFU_MANIFEST_SYNC) || + (hdfu->dev_state == STATE_DFU_UPLOAD_IDLE)) { + hdfu->dev_state = STATE_DFU_IDLE; + hdfu->dev_status = DFU_ERROR_NONE; + } +} + +/* + * usb_dfu_setup + * Handle the DFU specific requests + * pdev: instance + * req: usb requests + * return: status + */ +static uint8_t usb_dfu_setup(struct usb_handle *pdev, struct usb_setup_req *req) +{ + uint8_t *pbuf = NULL; + uint16_t len = 0U; + uint8_t ret = USBD_OK; + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + + switch (req->bm_request & USB_REQ_TYPE_MASK) { + case USB_REQ_TYPE_CLASS: + switch (req->b_request) { + case DFU_DNLOAD: + usb_dfu_download(pdev, req); + break; + + case DFU_UPLOAD: + usb_dfu_upload(pdev, req); + break; + + case DFU_GETSTATUS: + usb_dfu_get_status(pdev); + break; + + case DFU_CLRSTATUS: + usb_dfu_clear_status(pdev); + break; + + case DFU_GETSTATE: + usb_dfu_get_state(pdev); + break; + + case DFU_ABORT: + usb_dfu_abort(pdev); + break; + + case DFU_DETACH: + usb_dfu_detach(pdev, req); + break; + + default: + ERROR("unknown request %x on alternate %i\n", + req->b_request, hdfu->alt_setting); + usb_core_ctl_error(pdev); + ret = USBD_FAIL; + break; + } + break; + case USB_REQ_TYPE_STANDARD: + switch (req->b_request) { + case USB_REQ_GET_DESCRIPTOR: + if (HIBYTE(req->value) == DFU_DESCRIPTOR_TYPE) { + pbuf = pdev->desc->get_config_desc(&len); + /* DFU descriptor at the end of the USB */ + pbuf += len - 9U; + len = 9U; + len = MIN(len, req->length); + } + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, pbuf, len); + + break; + + case USB_REQ_GET_INTERFACE: + /* Start the transfer */ + usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->alt_setting, 1U); + break; + + case USB_REQ_SET_INTERFACE: + hdfu->alt_setting = LOBYTE(req->value); + break; + + default: + usb_core_ctl_error(pdev); + ret = USBD_FAIL; + break; + } + default: + break; + } + + return ret; +} + +static const struct usb_class usb_dfu = { + .init = usb_dfu_init, + .de_init = usb_dfu_de_init, + .setup = usb_dfu_setup, + .ep0_tx_sent = usb_dfu_ep0_tx_ready, + .ep0_rx_ready = usb_dfu_ep0_rx_ready, + .data_in = usb_dfu_data_in, + .data_out = usb_dfu_data_out, + .sof = usb_dfu_sof, + .iso_in_incomplete = usb_dfu_iso_in_incomplete, + .iso_out_incomplete = usb_dfu_iso_out_incomplete, +}; + +void usb_dfu_register(struct usb_handle *pdev, struct usb_dfu_handle *phandle) +{ + pdev->class = (struct usb_class *)&usb_dfu; + pdev->class_data = phandle; + + phandle->dev_state = STATE_DFU_IDLE; + phandle->dev_status = DFU_ERROR_NONE; +} + +int usb_dfu_loop(struct usb_handle *pdev, const struct usb_dfu_media *pmedia) +{ + uint32_t it_count; + enum usb_status ret; + struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data; + + hdfu->callback = pmedia; + usb_dfu_detach_req = false; + /* Continue to handle USB core IT to assure complete data transmission */ + it_count = 100U; + + /* DFU infinite loop until DETACH_REQ */ + while (it_count != 0U) { + ret = usb_core_handle_it(pdev); + if (ret != USBD_OK) { + return -EIO; + } + + /* Detach request received */ + if (usb_dfu_detach_req) { + it_count--; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c b/arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c new file mode 100644 index 0000000..88d0f8a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2015-2022, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if DEBUG +static const char debug_msg[] = { + "***************************************************\n" + "** DEBUG ACCESS PORT IS OPEN! **\n" + "** This boot image is only for debugging purpose **\n" + "** and is unsafe for production use. **\n" + "** **\n" + "** If you see this message and you are not **\n" + "** debugging report this immediately to your **\n" + "** vendor! **\n" + "***************************************************\n" +}; +#endif + +#if STM32MP15 +static struct stm32mp_auth_ops stm32mp1_auth_ops; +#endif + +static void print_reset_reason(void) +{ + uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR); + + if (rstsr == 0U) { + WARN("Reset reason unknown\n"); + return; + } + + INFO("Reset reason (0x%x):\n", rstsr); + + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) { + if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) { + INFO("System exits from STANDBY\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) { + INFO("MPU exits from CSTANDBY\n"); + return; + } + } + + if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) { + INFO(" Power-on Reset (rst_por)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) { + INFO(" Brownout Reset (rst_bor)\n"); + return; + } + +#if STM32MP15 + if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) { + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { + INFO(" System reset generated by MCU (MCSYSRST)\n"); + } else { + INFO(" Local reset generated by MCU (MCSYSRST)\n"); + } + return; + } +#endif + + if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) { + INFO(" System reset generated by MPU (MPSYSRST)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) { + INFO(" Reset due to a clock failure on HSE\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) { + INFO(" IWDG1 Reset (rst_iwdg1)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) { + INFO(" IWDG2 Reset (rst_iwdg2)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_MPUP0RSTF) != 0U) { + INFO(" MPU Processor 0 Reset\n"); + return; + } + +#if STM32MP15 + if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) { + INFO(" MPU Processor 1 Reset\n"); + return; + } +#endif + + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { + INFO(" Pad Reset from NRST\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) { + INFO(" Reset due to a failure of VDD_CORE\n"); + return; + } + + ERROR(" Unidentified reset reason\n"); +} + +void bl2_el3_early_platform_setup(u_register_t arg0, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) +{ + stm32mp_setup_early_console(); + + stm32mp_save_boot_ctx_address(arg0); +} + +void bl2_platform_setup(void) +{ + int ret; + + ret = stm32mp1_ddr_probe(); + if (ret < 0) { + ERROR("Invalid DDR init: error %d\n", ret); + panic(); + } + + /* Map DDR for binary load, now with cacheable attribute */ + ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, + STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE); + if (ret < 0) { + ERROR("DDR mapping: error %d\n", ret); + panic(); + } + +#if STM32MP_USE_STM32IMAGE +#ifdef AARCH32_SP_OPTEE + INFO("BL2 runs OP-TEE setup\n"); +#else + INFO("BL2 runs SP_MIN setup\n"); +#endif +#endif /* STM32MP_USE_STM32IMAGE */ +} + +#if STM32MP15 +static void update_monotonic_counter(void) +{ + uint32_t version; + uint32_t otp; + + CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE, + assert_stm32mp1_monotonic_counter_reach_max); + + /* Check if monotonic counter needs to be incremented */ + if (stm32_get_otp_index(MONOTONIC_OTP, &otp, NULL) != 0) { + panic(); + } + + if (stm32_get_otp_value_from_idx(otp, &version) != 0) { + panic(); + } + + if ((version + 1U) < BIT(STM32_TF_VERSION)) { + uint32_t result; + + /* Need to increment the monotonic counter. */ + version = BIT(STM32_TF_VERSION) - 1U; + + result = bsec_program_otp(version, otp); + if (result != BSEC_OK) { + ERROR("BSEC: MONOTONIC_OTP program Error %u\n", + result); + panic(); + } + INFO("Monotonic counter has been incremented (value 0x%x)\n", + version); + } +} +#endif + +void bl2_el3_plat_arch_setup(void) +{ + const char *board_model; + boot_api_context_t *boot_context = + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); + uintptr_t pwr_base; + uintptr_t rcc_base; + + if (bsec_probe() != 0U) { + panic(); + } + + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + +#if STM32MP_USE_STM32IMAGE +#ifdef AARCH32_SP_OPTEE + mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE, + STM32MP_OPTEE_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); +#else + /* Prevent corruption of preloaded BL32 */ + mmap_add_region(BL32_BASE, BL32_BASE, + BL32_LIMIT - BL32_BASE, + MT_RO_DATA | MT_SECURE); +#endif +#endif /* STM32MP_USE_STM32IMAGE */ + + /* Prevent corruption of preloaded Device Tree */ + mmap_add_region(DTB_BASE, DTB_BASE, + DTB_LIMIT - DTB_BASE, + MT_RO_DATA | MT_SECURE); + + configure_mmu(); + + if (dt_open_and_check(STM32MP_DTB_BASE) < 0) { + panic(); + } + + pwr_base = stm32mp_pwr_base(); + rcc_base = stm32mp_rcc_base(); + + /* + * Disable the backup domain write protection. + * The protection is enable at each reset by hardware + * and must be disabled by software. + */ + mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP); + + while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) { + ; + } + + /* Reset backup domain on cold boot cases */ + if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) { + mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); + + while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) == + 0U) { + ; + } + + mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); + } + +#if STM32MP15 + /* Disable MCKPROT */ + mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); +#endif + + /* + * Set minimum reset pulse duration to 31ms for discrete power + * supplied boards. + */ + if (dt_pmic_status() <= 0) { + mmio_clrsetbits_32(rcc_base + RCC_RDLSICR, + RCC_RDLSICR_MRD_MASK, + 31U << RCC_RDLSICR_MRD_SHIFT); + } + + generic_delay_timer_init(); + +#if STM32MP_UART_PROGRAMMER + /* Disable programmer UART before changing clock tree */ + if (boot_context->boot_interface_selected == + BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) { + uintptr_t uart_prog_addr = + get_uart_address(boot_context->boot_interface_instance); + + stm32_uart_stop(uart_prog_addr); + } +#endif + if (stm32mp1_clk_probe() < 0) { + panic(); + } + + if (stm32mp1_clk_init() < 0) { + panic(); + } + + stm32_save_boot_interface(boot_context->boot_interface_selected, + boot_context->boot_interface_instance); + +#if STM32MP_USB_PROGRAMMER && STM32MP15 + /* Deconfigure all UART RX pins configured by ROM code */ + stm32mp1_deconfigure_uart_pins(); +#endif + + if (stm32mp_uart_console_setup() != 0) { + goto skip_console_init; + } + + stm32mp_print_cpuinfo(); + + board_model = dt_get_board_model(); + if (board_model != NULL) { + NOTICE("Model: %s\n", board_model); + } + + stm32mp_print_boardinfo(); + + if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) { + NOTICE("Bootrom authentication %s\n", + (boot_context->auth_status == BOOT_API_CTX_AUTH_FAILED) ? + "failed" : "succeeded"); + } + +skip_console_init: + if (fixed_regulator_register() != 0) { + panic(); + } + + if (dt_pmic_status() > 0) { + initialize_pmic(); + if (pmic_voltages_init() != 0) { + ERROR("PMIC voltages init failed\n"); + panic(); + } + print_pmic_info_and_debug(); + } + + stm32mp1_syscfg_init(); + + if (stm32_iwdg_init() < 0) { + panic(); + } + + stm32_iwdg_refresh(); + + if (bsec_read_debug_conf() != 0U) { + if (stm32mp_is_closed_device()) { +#if DEBUG + WARN("\n%s", debug_msg); +#else + ERROR("***Debug opened on closed chip***\n"); +#endif + } + } + +#if STM32MP15 + if (stm32mp_is_auth_supported()) { + stm32mp1_auth_ops.check_key = + boot_context->bootrom_ecdsa_check_key; + stm32mp1_auth_ops.verify_signature = + boot_context->bootrom_ecdsa_verify_signature; + + stm32mp_init_auth(&stm32mp1_auth_ops); + } +#endif + + stm32mp1_arch_security_setup(); + + print_reset_reason(); + +#if STM32MP15 + update_monotonic_counter(); +#endif + + stm32mp1_syscfg_enable_io_compensation_finish(); + +#if !STM32MP_USE_STM32IMAGE + fconf_populate("TB_FW", STM32MP_DTB_BASE); +#endif /* !STM32MP_USE_STM32IMAGE */ + + stm32mp_io_setup(); +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + bl_mem_params_node_t *bl32_mem_params; + bl_mem_params_node_t *pager_mem_params __unused; + bl_mem_params_node_t *paged_mem_params __unused; +#if !STM32MP_USE_STM32IMAGE + const struct dyn_cfg_dtb_info_t *config_info; + bl_mem_params_node_t *tos_fw_mem_params; + unsigned int i; + unsigned int idx; + unsigned long long ddr_top __unused; + const unsigned int image_ids[] = { + BL32_IMAGE_ID, + BL33_IMAGE_ID, + HW_CONFIG_ID, + TOS_FW_CONFIG_ID, + }; +#endif /* !STM32MP_USE_STM32IMAGE */ + + assert(bl_mem_params != NULL); + + switch (image_id) { +#if !STM32MP_USE_STM32IMAGE + case FW_CONFIG_ID: + /* Set global DTB info for fixed fw_config information */ + set_config_info(STM32MP_FW_CONFIG_BASE, STM32MP_FW_CONFIG_MAX_SIZE, FW_CONFIG_ID); + fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE); + + idx = dyn_cfg_dtb_info_get_index(TOS_FW_CONFIG_ID); + + /* Iterate through all the fw config IDs */ + for (i = 0U; i < ARRAY_SIZE(image_ids); i++) { + if ((image_ids[i] == TOS_FW_CONFIG_ID) && (idx == FCONF_INVALID_IDX)) { + continue; + } + + bl_mem_params = get_bl_mem_params_node(image_ids[i]); + assert(bl_mem_params != NULL); + + config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]); + if (config_info == NULL) { + continue; + } + + bl_mem_params->image_info.image_base = config_info->config_addr; + bl_mem_params->image_info.image_max_size = config_info->config_max_size; + + bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; + + switch (image_ids[i]) { + case BL32_IMAGE_ID: + bl_mem_params->ep_info.pc = config_info->config_addr; + + /* In case of OPTEE, initialize address space with tos_fw addr */ + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + pager_mem_params->image_info.image_base = config_info->config_addr; + pager_mem_params->image_info.image_max_size = + config_info->config_max_size; + + /* Init base and size for pager if exist */ + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + paged_mem_params->image_info.image_base = STM32MP_DDR_BASE + + (dt_get_ddr_size() - STM32MP_DDR_S_SIZE - + STM32MP_DDR_SHMEM_SIZE); + paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE; + break; + + case BL33_IMAGE_ID: + bl_mem_params->ep_info.pc = config_info->config_addr; + break; + + case HW_CONFIG_ID: + case TOS_FW_CONFIG_ID: + break; + + default: + return -EINVAL; + } + } + break; +#endif /* !STM32MP_USE_STM32IMAGE */ + + case BL32_IMAGE_ID: + if (optee_header_is_valid(bl_mem_params->image_info.image_base)) { + /* BL32 is OP-TEE header */ + bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base; + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert((pager_mem_params != NULL) && (paged_mem_params != NULL)); + +#if STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) + /* Set OP-TEE extra image load areas at run-time */ + pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE; + pager_mem_params->image_info.image_max_size = STM32MP_OPTEE_SIZE; + + paged_mem_params->image_info.image_base = STM32MP_DDR_BASE + + dt_get_ddr_size() - + STM32MP_DDR_S_SIZE - + STM32MP_DDR_SHMEM_SIZE; + paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE; +#endif /* STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) */ + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err) { + ERROR("OPTEE header parse error.\n"); + panic(); + } + + /* Set optee boot info from parsed header data */ + bl_mem_params->ep_info.args.arg0 = paged_mem_params->image_info.image_base; + bl_mem_params->ep_info.args.arg1 = 0; /* Unused */ + bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */ + } else { +#if !STM32MP_USE_STM32IMAGE + bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base; + tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID); + bl_mem_params->image_info.image_max_size += + tos_fw_mem_params->image_info.image_max_size; +#endif /* !STM32MP_USE_STM32IMAGE */ + bl_mem_params->ep_info.args.arg0 = 0; + } + break; + + case BL33_IMAGE_ID: + bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID); + assert(bl32_mem_params != NULL); + bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc; +#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT + stm32mp1_fwu_set_boot_idx(); +#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */ + break; + + default: + /* Do nothing in default case */ + break; + } + +#if STM32MP_SDMMC || STM32MP_EMMC + /* + * Invalidate remaining data read from MMC but not flushed by load_image_flush(). + * We take the worst case which is 2 MMC blocks. + */ + if ((image_id != FW_CONFIG_ID) && + ((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) { + inv_dcache_range(bl_mem_params->image_info.image_base + + bl_mem_params->image_info.image_size, + 2U * MMC_BLOCK_SIZE); + } +#endif /* STM32MP_SDMMC || STM32MP_EMMC */ + + return err; +} + +void bl2_el3_plat_prepare_exit(void) +{ + uint16_t boot_itf = stm32mp_get_boot_itf_selected(); + + switch (boot_itf) { +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART: + case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB: + /* Invalidate the downloaded buffer used with io_memmap */ + inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE); + break; +#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */ + default: + /* Do nothing in default case */ + break; + } + + stm32mp1_security_setup(); +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h b/arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h new file mode 100644 index 0000000..7638418 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOOT_API_H +#define BOOT_API_H + +#include +#include + +/* + * Possible value of boot context field 'auth_status' + */ +#if STM32MP13 + /* No authentication done */ +#define BOOT_API_CTX_AUTH_NO 0x7CFDD351U + /* Authentication done and failed */ +#define BOOT_API_CTX_AUTH_FAILED 0x51330884U + /* Authentication done and success */ +#define BOOT_API_CTX_AUTH_SUCCESS 0x67E8CAE1U +#endif +#if STM32MP15 +/* No authentication done */ +#define BOOT_API_CTX_AUTH_NO 0x0U +/* Authentication done and failed */ +#define BOOT_API_CTX_AUTH_FAILED 0x1U +/* Authentication done and succeeded */ +#define BOOT_API_CTX_AUTH_SUCCESS 0x2U +#endif + +/* + * Possible value of boot context field 'boot_interface_sel' + */ + +/* Value of field 'boot_interface_sel' when no boot occurred */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_NO 0x0U + +/* Boot occurred on SD */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD 0x1U + +/* Boot occurred on EMMC */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC 0x2U + +/* Boot occurred on FMC */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC 0x3U + +/* Boot occurred on QSPI NOR */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI 0x4U + +/* Boot occurred on UART */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART 0x5U + +/* Boot occurred on USB */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB 0x6U + +/* Boot occurred on QSPI NAND */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI 0x7U + +/** + * @brief Possible value of boot context field 'EmmcXferStatus' + */ +/* + * Possible value of boot context field 'emmc_xfer_status' + */ +#define BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED 0x0U +#define BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED 0x1U +#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED 0x2U +#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT 0x3U + +/* + * Possible value of boot context field 'emmc_error_status' + */ +#define BOOT_API_CTX_EMMC_ERROR_STATUS_NONE 0x0U +#define BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT 0x1U +#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT 0x2U +#define BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL 0x3U +#define BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX 0x4U +#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND 0x5U +#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO 0x6U +#define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE 0x7U +#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_ERROR 0x8U + +/* Image Header related definitions */ + +/* Definition of header version */ +#if STM32MP13 +#define BOOT_API_HEADER_VERSION 0x00020000U +#endif +#if STM32MP15 +#define BOOT_API_HEADER_VERSION 0x00010000U +#endif + +/* + * Magic number used to detect header in memory + * Its value must be 'S' 'T' 'M' 0x32, i.e 0x324D5453 as field + * 'bootapi_image_header_t.magic' + * This identifies the start of a boot image. + */ +#define BOOT_API_IMAGE_HEADER_MAGIC_NB 0x324D5453U + +/* Definitions related to Authentication used in image header structure */ +#define BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES 64 +#define BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES 64 +#define BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES 32 + +/* Possible values of the field 'boot_api_image_header_t.ecc_algo_type' */ +#define BOOT_API_ECDSA_ALGO_TYPE_P256NIST 1 +#define BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256 2 + +/* + * Extension headers related definitions + */ +/* 'bootapi_image_header_t.extension_flag' used for authentication feature */ +#define BOOT_API_AUTHENTICATION_EXTENSION_BIT BIT(0) +/* 'bootapi_image_header_t.extension_flag' used for FSBL decryption feature */ +#define BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT BIT(1) +/* 'bootapi_image_header_t.extension_flag' used for padding header feature */ +#define BOOT_API_PADDING_EXTENSION_BIT BIT(31) +/* + * mask of bits of field 'bootapi_image_header_t.extension_flag' + * used for extension headers + */ +#define BOOT_API_ALL_EXTENSIONS_MASK \ + (BOOT_API_AUTHENTICATION_EXTENSION_BIT | \ + BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT | \ + BOOT_API_PADDING_EXTENSION_BIT) +/* + * Magic number of FSBL decryption extension header + * The value shall gives the four bytes 'S','T',0x00,0x01 in memory + */ +#define BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB 0x01005453U + +/* + * Magic number of PKH revocation extension header + * The value shall gives the four bytes 'S','T',0x00,0x02 in memory + */ +#define BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB 0x02005453U + +/* Max number of ECDSA public key hash in table */ +#define BOOT_API_AUTHENTICATION_NB_PKH_MAX 8U + +/* ECDSA public key hash table size in bytes */ +#define BOOT_API_AUTHENTICATION_TABLE_SIZE_BYTES \ + (BOOT_API_AUTHENTICATION_NB_PKH_MAX * \ + BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) + +/* + * Magic number of padding extension header + * The value shall gives the four bytes 'S','T',0xFF,0xFF in memory + */ +#define BOOT_API_PADDING_HEADER_MAGIC_NB 0xFFFF5453U + +/* + * Cores secure magic numbers + * Constant to be stored in bakcup register + * BOOT_API_MAGIC_NUMBER_TAMP_BCK_REG_IDX + */ +#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0U +#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1U + +/* + * TAMP_BCK4R register index + * This register is used to write a Magic Number in order to restart + * Cortex A7 Core 1 and make it execute @ branch address from TAMP_BCK5R + */ +#define BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX 4U + +/* + * TAMP_BCK5R register index + * This register is used to contain the branch address of + * Cortex A7 Core 1 when restarted by a TAMP_BCK4R magic number writing + */ +#define BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX 5U + +/* + * Possible value of boot context field 'hse_clock_value_in_hz' + */ +#define BOOT_API_CTX_HSE_CLOCK_VALUE_UNDEFINED 0U +#define BOOT_API_CTX_HSE_CLOCK_VALUE_24_MHZ 24000000U +#define BOOT_API_CTX_HSE_CLOCK_VALUE_25_MHZ 25000000U +#define BOOT_API_CTX_HSE_CLOCK_VALUE_26_MHZ 26000000U + +/* + * Possible value of boot context field 'boot_partition_used_toboot' + */ +#define BOOT_API_CTX_BOOT_PARTITION_UNDEFINED 0U + +/* Used FSBL1 to boot */ +#define BOOT_API_CTX_BOOT_PARTITION_FSBL1 1U + +/* Used FSBL2 to boot */ +#define BOOT_API_CTX_BOOT_PARTITION_FSBL2 2U + +/* OTP_CFG0 */ +#define BOOT_API_OTP_MODE_WORD_NB 0 +/* Closed = OTP_CFG0[6] */ +#define BOOT_API_OTP_MODE_CLOSED_BIT_POS 6 + +#define BOOT_API_RETURN_OK 0x77U + +/* + * Boot Context related definitions + */ + +/* + * Boot core boot configuration structure + * Specifies all items of the cold boot configuration + * Memory and peripheral part. + */ +typedef struct { + /* + * Boot interface used to boot : take values from defines + * BOOT_API_CTX_BOOT_INTERFACE_SEL_XXX above + */ + uint16_t boot_interface_selected; + uint16_t boot_interface_instance; +#if STM32MP13 + uint32_t reserved1[12]; +#endif +#if STM32MP15 + uint32_t reserved1[13]; +#endif + uint32_t otp_afmux_values[3]; + uint32_t reserved[3]; +#if STM32MP15 + uint32_t reserved2[2]; +#endif + uint32_t auth_status; + +#if STM32MP15 + /* + * Pointers to bootROM External Secure Services + * - ECDSA check key + * - ECDSA verify signature + * - ECDSA verify signature and go + */ + uint32_t (*bootrom_ecdsa_check_key)(uint8_t *pubkey_in, + uint8_t *pubkey_out); + uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in, + uint8_t *pubkey_in, + uint8_t *signature, + uint32_t ecc_algo); + uint32_t (*bootrom_ecdsa_verify_and_go)(uint8_t *hash_in, + uint8_t *pub_key_in, + uint8_t *signature, + uint32_t ecc_algo, + uint32_t *entry_in); +#endif + /* + * Information specific to an SD boot + * Updated each time an SD boot is at least attempted, + * even if not successful + * Note : This is useful to understand why an SD boot failed + * in particular + */ + uint32_t sd_err_internal_timeout_cnt; + uint32_t sd_err_dcrc_fail_cnt; + uint32_t sd_err_dtimeout_cnt; + uint32_t sd_err_ctimeout_cnt; + uint32_t sd_err_ccrc_fail_cnt; + uint32_t sd_overall_retry_cnt; + /* + * Information specific to an eMMC boot + * Updated each time an eMMC boot is at least attempted, + * even if not successful + * Note : This is useful to understand why an eMMC boot failed + * in particular + */ + uint32_t emmc_xfer_status; + uint32_t emmc_error_status; + uint32_t emmc_nbbytes_rxcopied_tosysram_download_area; + uint32_t hse_clock_value_in_hz; + /* + * Boot partition : + * ie FSBL partition on which the boot was successful + */ + uint32_t boot_partition_used_toboot; + +} __packed boot_api_context_t; + +/* + * Image Header related definitions + */ + +/* + * Structure used to define the common Header format used for FSBL, xloader, + * ... and in particular used by bootROM for FSBL header readout. + * FSBL header size is 256 Bytes = 0x100 + */ +typedef struct { + /* BOOT_API_IMAGE_HEADER_MAGIC_NB */ + uint32_t magic; + uint8_t image_signature[BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES]; + /* + * Checksum of payload + * 32-bit sum all payload bytes considered as 8 bit unsigned + * numbers, discarding any overflow bits. + * Use to check UART/USB downloaded image integrity when signature + * is not used + */ + uint32_t payload_checksum; + /* Image header version : should have value BOOT_API_HEADER_VERSION */ + uint32_t header_version; + /* Image length in bytes */ + uint32_t image_length; + /* + * Image Entry point address : should be in the SYSRAM area + * and at least within the download area range + */ + uint32_t image_entry_point; + /* Reserved */ + uint32_t reserved1; + /* + * Image load address : not used by bootROM but to be consistent + * with header format for other packages (xloader, ...) + */ + uint32_t load_address; + /* Reserved */ + uint32_t reserved2; + /* Image version to be compared by bootROM with monotonic + * counter value in OTP_CFG4 prior executing the downloaded image + */ + uint32_t image_version; + +#if STM32MP13 + /* + * Extension flags : + * + * Bit 0 : Authentication extension header + * value 0 : No signature check request + * Bit 1 : Encryption extension header + * Bit 2 : Padding extension header + */ + uint32_t extension_flags; + /* Length in bytes of all extension headers */ + uint32_t extension_headers_length; + /* Add binary type information */ + uint32_t binary_type; + /* Pad up to 128 byte total size */ + uint8_t pad[16]; +#endif +#if STM32MP15 + /* + * Option flags: + * Bit 0 : No signature check request : 'No_sig_check' + * value 1 : for No signature check request + * value 0 : No request to bypass the signature check + * Note : No signature check is never allowed on a Secured chip + */ + uint32_t option_flags; + /* + * Type of ECC algorithm to use : + * value 1 : for P-256 NIST algorithm + * value 2 : for Brainpool 256 algorithm + * See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above. + */ + uint32_t ecc_algo_type; + /* + * OEM ECC Public Key (aka Root pubk) provided in header on 512 bits. + * The SHA-256 hash of the OEM ECC pubk must match the one stored + * in OTP cells. + */ + uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES]; + /* Pad up to 256 byte total size */ + uint8_t pad[83]; + /* Add binary type information */ + uint8_t binary_type; +#endif +} __packed boot_api_image_header_t; + +#endif /* BOOT_API_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h b/arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h new file mode 100644 index 0000000..8ecb4c3 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include + +#include "../stm32mp1_def.h" + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x600 +#else +#define PLATFORM_STACK_SIZE 0xC00 +#endif + +#if STM32MP_USE_STM32IMAGE +#ifdef AARCH32_SP_OPTEE +#define OPTEE_HEADER_IMAGE_NAME "teeh" +#define OPTEE_CORE_IMAGE_NAME "teex" +#define OPTEE_PAGED_IMAGE_NAME "teed" +#define OPTEE_HEADER_BINARY_TYPE U(0x20) +#define OPTEE_CORE_BINARY_TYPE U(0x21) +#define OPTEE_PAGED_BINARY_TYPE U(0x22) +#endif + +/* SSBL = second stage boot loader */ +#define BL33_IMAGE_NAME "ssbl" +#define BL33_BINARY_TYPE U(0x0) +#else /* STM32MP_USE_STM32IMAGE */ +#define FIP_IMAGE_NAME "fip" +#define METADATA_PART_1 "metadata1" +#define METADATA_PART_2 "metadata2" + +#endif /* STM32MP_USE_STM32IMAGE */ + +#define STM32MP_PRIMARY_CPU U(0x0) +#define STM32MP_SECONDARY_CPU U(0x1) + +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(2) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER 2 + +#define MAX_IO_DEVICES U(4) +#define MAX_IO_HANDLES U(4) +#define MAX_IO_BLOCK_DEVICES U(1) +#define MAX_IO_MTD_DEVICES U(1) + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ +/* + * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define BL2_BASE STM32MP_BL2_BASE +#define BL2_LIMIT (STM32MP_BL2_BASE + \ + STM32MP_BL2_SIZE) + +#define BL2_RO_BASE STM32MP_BL2_RO_BASE +#define BL2_RO_LIMIT (STM32MP_BL2_RO_BASE + \ + STM32MP_BL2_RO_SIZE) + +#define BL2_RW_BASE STM32MP_BL2_RW_BASE +#define BL2_RW_LIMIT (STM32MP_BL2_RW_BASE + \ + STM32MP_BL2_RW_SIZE) +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#if STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32) +#if ENABLE_PIE +#define BL32_BASE 0 +#define BL32_LIMIT STM32MP_BL32_SIZE +#else +#define BL32_BASE STM32MP_BL32_BASE +#define BL32_LIMIT (STM32MP_BL32_BASE + \ + STM32MP_BL32_SIZE) +#endif +#endif /* STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32) */ + +/******************************************************************************* + * BL33 specific defines. + ******************************************************************************/ +#define BL33_BASE STM32MP_BL33_BASE + +/* + * Load address of BL33 for this platform port + */ +#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE + +/* Needed by STM32CubeProgrammer support */ +#define DWL_BUFFER_BASE (STM32MP_DDR_BASE + U(0x08000000)) +#define DWL_BUFFER_SIZE U(0x08000000) + +/* + * SSBL offset in case it's stored in eMMC boot partition. + * We can fix it to 256K because TF-A size can't be bigger than SRAM + */ +#define PLAT_EMMC_BOOT_SSBL_OFFSET U(0x40000) + +/******************************************************************************* + * DTB specific defines. + ******************************************************************************/ +#define DTB_BASE STM32MP_DTB_BASE +#define DTB_LIMIT (STM32MP_DTB_BASE + \ + STM32MP_DTB_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +/******************************************************************************* + * 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 6 +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* + * Secure Interrupt: based on the standard ARM mapping + */ +#define ARM_IRQ_SEC_PHY_TIMER U(29) + +#define ARM_IRQ_SEC_SGI_0 U(8) +#define ARM_IRQ_SEC_SGI_1 U(9) +#define ARM_IRQ_SEC_SGI_2 U(10) +#define ARM_IRQ_SEC_SGI_3 U(11) +#define ARM_IRQ_SEC_SGI_4 U(12) +#define ARM_IRQ_SEC_SGI_5 U(13) +#define ARM_IRQ_SEC_SGI_6 U(14) +#define ARM_IRQ_SEC_SGI_7 U(15) + +#define STM32MP1_IRQ_TZC400 U(36) +#define STM32MP1_IRQ_TAMPSERRS U(229) +#define STM32MP1_IRQ_AXIERRIRQ U(244) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \ + GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(STM32MP1_IRQ_TZC400, \ + 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 PLATFORM_G0_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, \ + GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, \ + GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE) + +/* + * Power + */ +#define PLAT_MAX_PWR_LVL U(1) + +/* 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 power-down. Valid for CPU and cluster power domains */ +#define ARM_LOCAL_STATE_OFF U(2) +/* + * 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 + +/******************************************************************************* + * Size of the per-cpu data in bytes that should be reserved in the generic + * per-cpu data structure for the FVP port. + ******************************************************************************/ +#define PLAT_PCPU_DATA_SIZE 2 + +/******************************************************************************* + * Number of parallel entry slots in SMT SCMI server entry context. For this + * platform, SCMI server is reached through SMC only, hence the number of + * entry slots. + ******************************************************************************/ +#define PLAT_SMT_ENTRY_COUNT PLATFORM_CORE_COUNT + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h new file mode 100644 index 0000000..3663bce --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_DBGMCU_H +#define STM32MP1_DBGMCU_H + +#include + +/* Get chip version and ID from DBGMCU registers */ +int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version); +int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id); + +#endif /* STM32MP1_DBGMCU_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h new file mode 100644 index 0000000..23934e9 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_PRIVATE_H +#define STM32MP1_PRIVATE_H + +#include + +void configure_mmu(void); + +void stm32mp1_arch_security_setup(void); +void stm32mp1_security_setup(void); + +void stm32mp1_gic_pcpu_init(void); +void stm32mp1_gic_init(void); + +void stm32mp1_syscfg_init(void); +void stm32mp1_syscfg_enable_io_compensation_start(void); +void stm32mp1_syscfg_enable_io_compensation_finish(void); +void stm32mp1_syscfg_disable_io_compensation(void); +uint32_t stm32mp1_syscfg_get_chip_version(void); +uint32_t stm32mp1_syscfg_get_chip_dev_id(void); +#if STM32MP13 +void stm32mp1_syscfg_boot_mode_enable(void); +void stm32mp1_syscfg_boot_mode_disable(void); +#endif +#if STM32MP15 +static inline void stm32mp1_syscfg_boot_mode_enable(void){} +static inline void stm32mp1_syscfg_boot_mode_disable(void){} +#endif + +void stm32mp1_deconfigure_uart_pins(void); + +#if STM32MP_USE_STM32IMAGE +uint32_t stm32mp_get_ddr_ns_size(void); +#endif /* STM32MP_USE_STM32IMAGE */ + +void stm32mp1_init_scmi_server(void); +#endif /* STM32MP1_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h new file mode 100644 index 0000000..3f6367e --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_SHARED_RESOURCES_H +#define STM32MP1_SHARED_RESOURCES_H + +#include + +#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + (i)) + +enum stm32mp_shres { + STM32MP1_SHRES_CRYP1, + STM32MP1_SHRES_GPIOZ_0, + STM32MP1_SHRES_GPIOZ_1, + STM32MP1_SHRES_GPIOZ_2, + STM32MP1_SHRES_GPIOZ_3, + STM32MP1_SHRES_GPIOZ_4, + STM32MP1_SHRES_GPIOZ_5, + STM32MP1_SHRES_GPIOZ_6, + STM32MP1_SHRES_GPIOZ_7, + STM32MP1_SHRES_HASH1, + STM32MP1_SHRES_I2C4, + STM32MP1_SHRES_I2C6, + STM32MP1_SHRES_IWDG1, + STM32MP1_SHRES_MCU, + STM32MP1_SHRES_MDMA, + STM32MP1_SHRES_PLL3, + STM32MP1_SHRES_RNG1, + STM32MP1_SHRES_RTC, + STM32MP1_SHRES_SPI6, + STM32MP1_SHRES_USART1, + + STM32MP1_SHRES_COUNT +}; +#endif /* STM32MP1_SHARED_RESOURCES_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h new file mode 100644 index 0000000..52088de --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_SMC_H +#define STM32MP1_SMC_H + +/* + * SMC function IDs for STM32 Service queries + * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF + * like this is defined in SMC calling Convention by ARM + * for SiP (silicon Partner) + * https://developer.arm.com/docs/den0028/latest + */ + +/* Secure Service access from Non-secure */ + +/* + * STM32_SMC_BSEC call API + * + * Argument a0: (input) SMCC ID + * (output) status return code + * Argument a1: (input) Service ID (STM32_SMC_BSEC_xxx) + * Argument a2: (input) OTP index + * (output) OTP read value, if applicable + * Argument a3: (input) OTP value if applicable + */ +#define STM32_SMC_BSEC 0x82001003 + +/* + * STM32_SIP_SMC_SCMI_AGENT0 + * STM32_SIP_SMC_SCMI_AGENT1 + * Process SCMI message pending in SCMI shared memory buffer. + * + * Argument a0: (input) SMCC ID + */ +#define STM32_SIP_SMC_SCMI_AGENT0 0x82002000 +#define STM32_SIP_SMC_SCMI_AGENT1 0x82002001 + +/* SMC function IDs for SiP Service queries */ +#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00 +#define STM32_SIP_SVC_UID 0x8200ff01 +/* 0x8200ff02 is reserved */ +#define STM32_SIP_SVC_VERSION 0x8200ff03 + +/* STM32 SiP Service Calls version numbers */ +#define STM32_SIP_SVC_VERSION_MAJOR 0x0 +#define STM32_SIP_SVC_VERSION_MINOR 0x1 + +/* Number of STM32 SiP Calls implemented */ +#define STM32_COMMON_SIP_NUM_CALLS 3 + +/* Service for BSEC */ +#define STM32_SMC_READ_SHADOW 0x01 +#define STM32_SMC_PROG_OTP 0x02 +#define STM32_SMC_WRITE_SHADOW 0x03 +#define STM32_SMC_READ_OTP 0x04 + +/* SMC error codes */ +#define STM32_SMC_OK 0x00000000U +#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU +#define STM32_SMC_FAILED 0xFFFFFFFEU +#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU + +#endif /* STM32MP1_SMC_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c new file mode 100644 index 0000000..7963c4a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + /* Fill FW_CONFIG related information if it exists */ + { + .image_id = FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP), + + .image_info.image_base = STM32MP_FW_CONFIG_BASE, + .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* Fill BL32 related information */ + { + .image_id = BL32_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_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* Fill BL32 external 1 image related information */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + /* Fill BL32 external 2 image related information */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* Fill HW_CONFIG related information if it exists */ + { + .image_id = HW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, + NON_SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* Fill TOS_FW_CONFIG related information if it exists */ + { + .image_id = TOS_FW_CONFIG_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* Fill BL33 related information */ + { + .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_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c b/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c new file mode 100644 index 0000000..4fce55a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + + /* Updated at runtime if OP-TEE is loaded */ + .ep_info.pc = STM32MP_BL32_BASE, + + .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP), + + /* Updated at runtime if OP-TEE is loaded */ + .image_info.image_base = STM32MP_BL32_BASE, + .image_info.image_max_size = STM32MP_BL32_SIZE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + +#if defined(AARCH32_SP_OPTEE) + /* Fill BL32 external 1 image related information */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + /* Fill BL32 external 2 image related information */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif /* AARCH32_SP_OPTEE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + NON_SECURE | EXECUTABLE), + + .ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET, + .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0U), + + .image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET, + .image_info.image_max_size = STM32MP_DDR_MAX_SIZE - + (PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE), + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c b/arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c new file mode 100644 index 0000000..36a3a1c --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ +#if STM32MP_USE_STM32IMAGE + bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID); + uint32_t ddr_ns_size = stm32mp_get_ddr_ns_size(); + + /* Max size is non-secure DDR end address minus image_base */ + bl33->image_info.image_max_size = STM32MP_DDR_BASE + ddr_ns_size - + bl33->image_info.image_base; +#endif /* STM32MP_USE_STM32IMAGE */ + + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + bl_params_t *bl_params = get_next_bl_params_from_mem_params_desc(); + + populate_next_bl_params_config(bl_params); + + return bl_params; +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/platform.mk b/arm-trusted-firmware/plat/st/stm32mp1/platform.mk new file mode 100644 index 0000000..9e732d6 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/platform.mk @@ -0,0 +1,494 @@ +# +# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ARM_CORTEX_A7 := yes +ARM_WITH_NEON := yes +BL2_AT_EL3 := 1 +USE_COHERENT_MEM := 0 + +STM32MP_EARLY_CONSOLE ?= 0 +STM32MP_UART_BAUDRATE ?= 115200 + +# Allow TF-A to concatenate BL2 & BL32 binaries in a single file, +# share DTB file between BL2 and BL32 +# If it is set to 0, then FIP is used +STM32MP_USE_STM32IMAGE ?= 0 + +# Please don't increment this value without good understanding of +# the monotonic counter +STM32_TF_VERSION ?= 0 + +# Enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# Default Device tree +DTB_FILE_NAME ?= stm32mp157c-ev1.dtb + +STM32MP13 ?= 0 +STM32MP15 ?= 0 + +ifeq ($(STM32MP13),1) +ifeq ($(STM32MP15),1) +$(error Cannot enable both flags STM32MP13 and STM32MP15) +endif +STM32MP13 := 1 +STM32MP15 := 0 +else ifeq ($(STM32MP15),1) +STM32MP13 := 0 +STM32MP15 := 1 +else ifneq ($(findstring stm32mp13,$(DTB_FILE_NAME)),) +STM32MP13 := 1 +STM32MP15 := 0 +else ifneq ($(findstring stm32mp15,$(DTB_FILE_NAME)),) +STM32MP13 := 0 +STM32MP15 := 1 +endif + +ifeq ($(STM32MP13),1) +# DDR controller with single AXI port and 16-bit interface +STM32MP_DDR_DUAL_AXI_PORT:= 0 +STM32MP_DDR_32BIT_INTERFACE:= 0 + +# STM32 image header version v2.0 +STM32_HEADER_VERSION_MAJOR:= 2 +STM32_HEADER_VERSION_MINOR:= 0 +endif + +ifeq ($(STM32MP15),1) +# DDR controller with dual AXI port and 32-bit interface +STM32MP_DDR_DUAL_AXI_PORT:= 1 +STM32MP_DDR_32BIT_INTERFACE:= 1 + +# STM32 image header version v1.0 +STM32_HEADER_VERSION_MAJOR:= 1 +STM32_HEADER_VERSION_MINOR:= 0 +endif + +# STM32 image header binary type for BL2 +STM32_HEADER_BL2_BINARY_TYPE:= 0x10 + +ifeq ($(AARCH32_SP),sp_min) +# Disable Neon support: sp_min runtime may conflict with non-secure world +TF_CFLAGS += -mfloat-abi=soft +endif + +TF_CFLAGS += -Wsign-compare +TF_CFLAGS += -Wformat-signedness + +# Not needed for Cortex-A7 +WORKAROUND_CVE_2017_5715:= 0 +WORKAROUND_CVE_2022_23960:= 0 + +ifeq (${PSA_FWU_SUPPORT},1) +ifneq (${STM32MP_USE_STM32IMAGE},1) +# Number of banks of updatable firmware +NR_OF_FW_BANKS := 2 +NR_OF_IMAGES_IN_FW_BANK := 1 + +# Number of TF-A copies in the device +STM32_TF_A_COPIES := 2 +STM32_BL33_PARTS_NUM := 2 +STM32_RUNTIME_PARTS_NUM := 4 +else +$(error FWU Feature enabled only with FIP images) +endif +else +# Number of TF-A copies in the device +STM32_TF_A_COPIES := 2 +STM32_BL33_PARTS_NUM := 1 +ifeq ($(AARCH32_SP),optee) +STM32_RUNTIME_PARTS_NUM := 3 +else ifeq ($(STM32MP_USE_STM32IMAGE),1) +STM32_RUNTIME_PARTS_NUM := 0 +else +STM32_RUNTIME_PARTS_NUM := 1 +endif +endif +PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + \ + $(STM32_BL33_PARTS_NUM) + \ + $(STM32_RUNTIME_PARTS_NUM)))) + +# Boot devices +STM32MP_EMMC ?= 0 +STM32MP_SDMMC ?= 0 +STM32MP_RAW_NAND ?= 0 +STM32MP_SPI_NAND ?= 0 +STM32MP_SPI_NOR ?= 0 +STM32MP_EMMC_BOOT ?= 0 + +# Serial boot devices +STM32MP_USB_PROGRAMMER ?= 0 +STM32MP_UART_PROGRAMMER ?= 0 + +# Device tree +ifeq ($(STM32MP13),1) +BL2_DTSI := stm32mp13-bl2.dtsi +FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) +else +ifeq ($(STM32MP_USE_STM32IMAGE),1) +ifeq ($(AARCH32_SP),optee) +BL2_DTSI := stm32mp15-bl2.dtsi +FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) +else +FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME))) +endif +else +BL2_DTSI := stm32mp15-bl2.dtsi +FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) +ifeq ($(AARCH32_SP),sp_min) +BL32_DTSI := stm32mp15-bl32.dtsi +FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME))) +endif +endif +endif + +$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}')) +$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g"))) +DTC_CPPFLAGS += ${INCLUDES} +DTC_FLAGS += -Wno-unit_address_vs_reg +ifeq ($(shell test $(DTC_VERSION) -ge 10601; echo $$?),0) +DTC_FLAGS += -Wno-interrupt_provider +endif + +# Macros and rules to build TF binary +STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed +STM32_TF_STM32 := $(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME))) +STM32_TF_LINKERFILE := ${BUILD_PLAT}/stm32mp1.ld + +ASFLAGS += -DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\" +ifeq ($(AARCH32_SP),sp_min) +# BL32 is built only if using SP_MIN +BL32_DEP := bl32 +ASFLAGS += -DBL32_BIN_PATH=\"${BUILD_PLAT}/bl32.bin\" +endif + +# Variables for use with stm32image +STM32IMAGEPATH ?= tools/stm32image +STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT} +STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c + +ifneq (${STM32MP_USE_STM32IMAGE},1) +FIP_DEPS += dtbs +STM32MP_HW_CONFIG := ${BL33_CFG} +STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME)) +STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME) +ifneq (${AARCH32_SP},none) +FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME))) +endif +# Add the FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config)) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config)) +ifeq ($(AARCH32_SP),sp_min) +STM32MP_TOS_FW_CONFIG := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME))) +$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config)) +else +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif +endif +endif + +# Enable flags for C files +$(eval $(call assert_booleans,\ + $(sort \ + PLAT_XLAT_TABLES_DYNAMIC \ + STM32MP_DDR_32BIT_INTERFACE \ + STM32MP_DDR_DUAL_AXI_PORT \ + STM32MP_EARLY_CONSOLE \ + STM32MP_EMMC \ + STM32MP_EMMC_BOOT \ + STM32MP_RAW_NAND \ + STM32MP_SDMMC \ + STM32MP_SPI_NAND \ + STM32MP_SPI_NOR \ + STM32MP_UART_PROGRAMMER \ + STM32MP_USB_PROGRAMMER \ + STM32MP_USE_STM32IMAGE \ + STM32MP13 \ + STM32MP15 \ +))) + +$(eval $(call assert_numerics,\ + $(sort \ + PLAT_PARTITION_MAX_ENTRIES \ + STM32_TF_A_COPIES \ + STM32_TF_VERSION \ + STM32MP_UART_BAUDRATE \ +))) + +$(eval $(call add_defines,\ + $(sort \ + PLAT_PARTITION_MAX_ENTRIES \ + PLAT_XLAT_TABLES_DYNAMIC \ + STM32_TF_A_COPIES \ + STM32_TF_VERSION \ + STM32MP_DDR_32BIT_INTERFACE \ + STM32MP_DDR_DUAL_AXI_PORT \ + STM32MP_EARLY_CONSOLE \ + STM32MP_EMMC \ + STM32MP_EMMC_BOOT \ + STM32MP_RAW_NAND \ + STM32MP_SDMMC \ + STM32MP_SPI_NAND \ + STM32MP_SPI_NOR \ + STM32MP_UART_BAUDRATE \ + STM32MP_UART_PROGRAMMER \ + STM32MP_USB_PROGRAMMER \ + STM32MP_USE_STM32IMAGE \ + STM32MP13 \ + STM32MP15 \ +))) + +# Include paths and source files +PLAT_INCLUDES := -Iplat/st/common/include/ +PLAT_INCLUDES += -Iplat/st/stm32mp1/include/ + +ifeq (${STM32MP_USE_STM32IMAGE},1) +include common/fdt_wrappers.mk +else +include lib/fconf/fconf.mk +endif +include lib/libfdt/libfdt.mk + +PLAT_BL_COMMON_SOURCES := common/uuid.c \ + plat/st/common/stm32mp_common.c \ + plat/st/stm32mp1/stm32mp1_private.c + +PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += plat/st/stm32mp1/stm32mp1_stack_protector.c +endif + +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S + +PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ + drivers/clk/clk.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/st/bsec/bsec2.c \ + drivers/st/clk/stm32mp_clkfunc.c \ + drivers/st/ddr/stm32mp_ddr.c \ + drivers/st/ddr/stm32mp1_ddr_helpers.c \ + drivers/st/gpio/stm32_gpio.c \ + drivers/st/i2c/stm32_i2c.c \ + drivers/st/iwdg/stm32_iwdg.c \ + drivers/st/pmic/stm32mp_pmic.c \ + drivers/st/pmic/stpmic1.c \ + drivers/st/regulator/regulator_core.c \ + drivers/st/regulator/regulator_fixed.c \ + drivers/st/reset/stm32mp1_reset.c \ + plat/st/common/stm32mp_dt.c \ + plat/st/stm32mp1/stm32mp1_dbgmcu.c \ + plat/st/stm32mp1/stm32mp1_helper.S \ + plat/st/stm32mp1/stm32mp1_syscfg.c + +ifeq ($(STM32MP13),1) +PLAT_BL_COMMON_SOURCES += drivers/st/clk/clk-stm32-core.c \ + drivers/st/clk/clk-stm32mp13.c +else +PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c +endif + +ifneq (${STM32MP_USE_STM32IMAGE},1) +BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES} + +BL2_SOURCES += drivers/io/io_fip.c \ + plat/st/common/bl2_io_storage.c \ + plat/st/common/stm32mp_fconf_io.c \ + plat/st/stm32mp1/plat_bl2_mem_params_desc.c \ + plat/st/stm32mp1/stm32mp1_fconf_firewall.c +else +BL2_SOURCES += ${FDT_WRAPPERS_SOURCES} + +BL2_SOURCES += drivers/io/io_dummy.c \ + drivers/st/io/io_stm32image.c \ + plat/st/common/bl2_stm32_io_storage.c \ + plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c \ + plat/st/stm32mp1/stm32mp1_security.c +endif + +ifeq (${PSA_FWU_SUPPORT},1) +include lib/zlib/zlib.mk +include drivers/fwu/fwu.mk + +BL2_SOURCES += $(ZLIB_SOURCES) +endif + +BL2_SOURCES += drivers/io/io_block.c \ + drivers/io/io_mtd.c \ + drivers/io/io_storage.c \ + drivers/st/crypto/stm32_hash.c \ + plat/st/stm32mp1/bl2_plat_setup.c + + +ifeq ($(STM32MP15),1) +BL2_SOURCES += plat/st/common/stm32mp_auth.c +endif + +ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),) +BL2_SOURCES += drivers/mmc/mmc.c \ + drivers/partition/gpt.c \ + drivers/partition/partition.c \ + drivers/st/io/io_mmc.c \ + drivers/st/mmc/stm32_sdmmc2.c +endif + +ifeq (${STM32MP_RAW_NAND},1) +$(eval $(call add_define_val,NAND_ONFI_DETECT,1)) +BL2_SOURCES += drivers/mtd/nand/raw_nand.c \ + drivers/st/fmc/stm32_fmc2_nand.c +endif + +ifeq (${STM32MP_SPI_NAND},1) +BL2_SOURCES += drivers/mtd/nand/spi_nand.c +endif + +ifeq (${STM32MP_SPI_NOR},1) +BL2_SOURCES += drivers/mtd/nor/spi_nor.c +endif + +ifneq ($(filter 1,${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),) +BL2_SOURCES += drivers/mtd/spi-mem/spi_mem.c \ + drivers/st/spi/stm32_qspi.c +endif + +ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND}),) +BL2_SOURCES += drivers/mtd/nand/core.c +endif + +ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),) +BL2_SOURCES += plat/st/stm32mp1/stm32mp1_boot_device.c +endif + +ifneq ($(filter 1,${STM32MP_UART_PROGRAMMER} ${STM32MP_USB_PROGRAMMER}),) +BL2_SOURCES += drivers/io/io_memmap.c +endif + +ifeq (${STM32MP_UART_PROGRAMMER},1) +BL2_SOURCES += drivers/st/uart/stm32_uart.c \ + plat/st/common/stm32cubeprogrammer_uart.c +endif + +ifeq (${STM32MP_USB_PROGRAMMER},1) +#The DFU stack uses only one end point, reduce the USB stack footprint +$(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U)) +BL2_SOURCES += drivers/st/usb/stm32mp1_usb.c \ + drivers/usb/usb_device.c \ + plat/st/common/stm32cubeprogrammer_usb.c \ + plat/st/common/usb_dfu.c \ + plat/st/stm32mp1/stm32mp1_usb_dfu.c +endif + +BL2_SOURCES += drivers/st/ddr/stm32mp_ddr_test.c \ + drivers/st/ddr/stm32mp_ram.c \ + drivers/st/ddr/stm32mp1_ddr.c \ + drivers/st/ddr/stm32mp1_ram.c + +BL2_SOURCES += common/desc_image_load.c \ + plat/st/stm32mp1/plat_image_load.c + +BL2_SOURCES += lib/optee/optee_utils.c + +# Compilation rules +.PHONY: check_dtc_version stm32image clean_stm32image check_boot_device +.SUFFIXES: + +all: check_dtc_version stm32image ${STM32_TF_STM32} + +distclean realclean clean: clean_stm32image + +bl2: check_boot_device + +check_boot_device: + @if [ ${STM32MP_EMMC} != 1 ] && \ + [ ${STM32MP_SDMMC} != 1 ] && \ + [ ${STM32MP_RAW_NAND} != 1 ] && \ + [ ${STM32MP_SPI_NAND} != 1 ] && \ + [ ${STM32MP_SPI_NOR} != 1 ] && \ + [ ${STM32MP_UART_PROGRAMMER} != 1 ] && \ + [ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \ + echo "No boot device driver is enabled"; \ + false; \ + fi + +stm32image: ${STM32IMAGE} + +${STM32IMAGE}: ${STM32IMAGE_SRC} + ${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH} + +clean_stm32image: + ${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean + +check_dtc_version: + @if [ ${DTC_VERSION} -lt 10404 ]; then \ + echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \ + false; \ + fi + +ifeq ($(STM32MP_USE_STM32IMAGE)-$(AARCH32_SP),1-sp_min) +${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%.dtb plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} + @echo " AS stm32mp1.S" + ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ + -DDTB_BIN_PATH=\"$<\" \ + -c $(word 2,$^) -o $@ +else +# Create DTB file for BL2 +${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs + @echo '#include "$(patsubst fdts/%,%,$<)"' > $@ + @echo '#include "${BL2_DTSI}"' >> $@ + +${BUILD_PLAT}/fdts/%-bl2.dtb: ${BUILD_PLAT}/fdts/%-bl2.dts + +ifeq ($(AARCH32_SP),sp_min) +# Create DTB file for BL32 +${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs + @echo '#include "$(patsubst fdts/%,%,$<)"' > $@ + @echo '#include "${BL32_DTSI}"' >> $@ + +${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts +endif + +${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2 + @echo " AS stm32mp1.S" + ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ + -DDTB_BIN_PATH=\"$<\" \ + -c plat/st/stm32mp1/stm32mp1.S -o $@ +endif + +$(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,bl2)) + +tf-a-%.elf: stm32mp1-%.o ${STM32_TF_LINKERFILE} + @echo " LDS $<" + ${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=$(@:.elf=.map) --script ${STM32_TF_LINKERFILE} $< + +tf-a-%.bin: tf-a-%.elf + ${Q}${OC} -O binary $< $@ + @echo + @echo "Built $@ successfully" + @echo + +tf-a-%.stm32: ${STM32IMAGE} tf-a-%.bin + @echo + @echo "Generate $@" + $(eval LOADADDR = $(shell cat $(@:.stm32=.map) | grep RAM | awk '{print $$2}')) + $(eval ENTRY = $(shell cat $(@:.stm32=.map) | grep "__BL2_IMAGE_START" | awk '{print $$1}')) + ${Q}${STM32IMAGE} -s $(word 2,$^) -d $@ \ + -l $(LOADADDR) -e ${ENTRY} \ + -v ${STM32_TF_VERSION} \ + -m ${STM32_HEADER_VERSION_MAJOR} \ + -n ${STM32_HEADER_VERSION_MINOR} \ + -b ${STM32_HEADER_BL2_BINARY_TYPE} + @echo diff --git a/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c b/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c new file mode 100644 index 0000000..1fb44b4 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +#include "bsec_svc.h" + +uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + uint32_t *ret_otp_value) +{ + uint32_t result; + uint32_t tmp_data = 0U; + + switch (x1) { + case STM32_SMC_READ_SHADOW: + result = bsec_read_otp(ret_otp_value, x2); + break; + case STM32_SMC_PROG_OTP: + *ret_otp_value = 0U; + result = bsec_program_otp(x3, x2); + break; + case STM32_SMC_WRITE_SHADOW: + *ret_otp_value = 0U; + result = bsec_write_otp(x3, x2); + break; + case STM32_SMC_READ_OTP: + *ret_otp_value = 0U; + result = bsec_read_otp(&tmp_data, x2); + if (result != BSEC_OK) { + break; + } + + result = bsec_shadow_register(x2); + if (result != BSEC_OK) { + break; + } + + result = bsec_read_otp(ret_otp_value, x2); + if (result != BSEC_OK) { + break; + } + + result = bsec_write_otp(tmp_data, x2); + break; + + default: + return STM32_SMC_INVALID_PARAMS; + } + + return (result == BSEC_OK) ? STM32_SMC_OK : STM32_SMC_FAILED; +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h b/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h new file mode 100644 index 0000000..06752ef --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BSEC_SVC_H +#define BSEC_SVC_H + +#include + +/* version of this service */ +/* must be increase at each structure modification */ +#define BSEC_SERVICE_VERSION 0x01U + +uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + uint32_t *ret_otp_value); + +#endif /* BSEC_SVC_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c new file mode 100644 index 0000000..ed8a448 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "bsec_svc.h" + +/* STM32 SiP Service UUID */ +DEFINE_SVC_UUID2(stm32_sip_svc_uid, + 0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e, + 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14); + +/* Setup STM32MP1 Standard Services */ +static int32_t stm32mp1_svc_setup(void) +{ + /* + * PSCI is the only specification implemented as a Standard Service. + * Invoke PSCI setup from here. + */ + return 0; +} + +/* + * Top-level Standard Service SMC handler. This handler will in turn dispatch + * calls to PSCI SMC handler. + */ +static uintptr_t stm32mp1_svc_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) +{ + uint32_t ret1 = 0U, ret2 = 0U; + bool ret_uid = false, ret2_enabled = false; + + switch (smc_fid) { + case STM32_SIP_SVC_CALL_COUNT: + ret1 = STM32_COMMON_SIP_NUM_CALLS; + break; + + case STM32_SIP_SVC_UID: + /* Return UUID to the caller */ + ret_uid = true; + break; + + case STM32_SIP_SVC_VERSION: + /* Return the version of current implementation */ + ret1 = STM32_SIP_SVC_VERSION_MAJOR; + ret2 = STM32_SIP_SVC_VERSION_MINOR; + ret2_enabled = true; + break; + + case STM32_SMC_BSEC: + ret1 = bsec_main(x1, x2, x3, &ret2); + ret2_enabled = true; + break; + + case STM32_SIP_SMC_SCMI_AGENT0: + scmi_smt_fastcall_smc_entry(0); + break; + case STM32_SIP_SMC_SCMI_AGENT1: + scmi_smt_fastcall_smc_entry(1); + break; + + default: + WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid); + ret1 = STM32_SMC_NOT_SUPPORTED; + break; + } + + if (ret_uid) { + SMC_UUID_RET(handle, stm32_sip_svc_uid); + } + + if (ret2_enabled) { + SMC_RET2(handle, ret1, ret2); + } + + SMC_RET1(handle, ret1); +} + +/* Register Standard Service Calls as runtime service */ +DECLARE_RT_SVC(stm32mp1_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + stm32mp1_svc_setup, + stm32mp1_svc_smc_handler +); diff --git a/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk new file mode 100644 index 0000000..c3fc2cb --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk @@ -0,0 +1,55 @@ +# +# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq ($(STM32MP13),1) +$(error "SP_min is not supported on STM32MP13 platform") +endif + +SP_MIN_WITH_SECURE_FIQ := 1 + +ifneq ($(STM32MP_USE_STM32IMAGE),1) +override ENABLE_PIE := 1 +BL32_CFLAGS += -fpie -DENABLE_PIE +BL32_LDFLAGS += $(PIE_LDFLAGS) +endif + +BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES + +BL32_SOURCES += drivers/st/etzpc/etzpc.c \ + plat/common/aarch32/platform_mp_stack.S \ + plat/st/stm32mp1/sp_min/sp_min_setup.c \ + plat/st/stm32mp1/stm32mp1_pm.c \ + plat/st/stm32mp1/stm32mp1_shared_resources.c \ + plat/st/stm32mp1/stm32mp1_topology.c + +# FDT wrappers +include common/fdt_wrappers.mk +BL32_SOURCES += ${FDT_WRAPPERS_SOURCES} + +# Generic GIC v2 +include drivers/arm/gic/v2/gicv2.mk + +BL32_SOURCES += ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/st/stm32mp1/stm32mp1_gic.c + +# Generic PSCI +BL32_SOURCES += plat/common/plat_psci_common.c + +# SCMI server drivers +BL32_SOURCES += drivers/scmi-msg/base.c \ + drivers/scmi-msg/clock.c \ + drivers/scmi-msg/entry.c \ + drivers/scmi-msg/reset_domain.c \ + drivers/scmi-msg/smt.c + +# stm32mp1 specific services +BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \ + plat/st/stm32mp1/services/stm32mp1_svc_setup.c \ + plat/st/stm32mp1/stm32mp1_scmi.c + +# Arm Archtecture services +BL32_SOURCES += services/arm_arch_svc/arm_arch_svc_setup.c diff --git a/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c b/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c new file mode 100644 index 0000000..8106795 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c @@ -0,0 +1,197 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include + +/****************************************************************************** + * Placeholder variables for copying the arguments that have been passed to + * BL32 from BL2. + ******************************************************************************/ +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Interrupt handler for FIQ (secure IRQ) + ******************************************************************************/ +void sp_min_plat_fiq_handler(uint32_t id) +{ + switch (id & INT_ID_MASK) { + case STM32MP1_IRQ_TZC400: + tzc400_init(STM32MP1_TZC_BASE); + (void)tzc400_it_handler(); + panic(); + break; + case STM32MP1_IRQ_AXIERRIRQ: + ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n"); + panic(); + break; + default: + ERROR("SECURE IT handler not define for it : %u", id); + break; + } +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) +{ + entry_point_info_t *next_image_info; + + next_image_info = &bl33_image_ep_info; + + if (next_image_info->pc == 0U) { + return NULL; + } + + return next_image_info; +} + +CASSERT((STM32MP_SEC_SYSRAM_BASE == STM32MP_SYSRAM_BASE) && + ((STM32MP_SEC_SYSRAM_BASE + STM32MP_SEC_SYSRAM_SIZE) <= + (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)), + assert_secure_sysram_fits_at_begining_of_sysram); + +#ifdef STM32MP_NS_SYSRAM_BASE +CASSERT((STM32MP_NS_SYSRAM_BASE >= STM32MP_SEC_SYSRAM_BASE) && + ((STM32MP_NS_SYSRAM_BASE + STM32MP_NS_SYSRAM_SIZE) == + (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)), + assert_non_secure_sysram_fits_at_end_of_sysram); + +CASSERT((STM32MP_NS_SYSRAM_BASE & (PAGE_SIZE_4KB - U(1))) == 0U, + assert_non_secure_sysram_base_is_4kbyte_aligned); + +#define TZMA1_SECURE_RANGE \ + (((STM32MP_NS_SYSRAM_BASE - STM32MP_SYSRAM_BASE) >> FOUR_KB_SHIFT) - 1U) +#else +#define TZMA1_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE +#endif /* STM32MP_NS_SYSRAM_BASE */ +#define TZMA0_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE + +static void stm32mp1_etzpc_early_setup(void) +{ + if (etzpc_init() != 0) { + panic(); + } + + etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE); + etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE); +} + +/******************************************************************************* + * Perform any BL32 specific platform actions. + ******************************************************************************/ +void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + bl_params_t *params_from_bl2 = (bl_params_t *)arg0; +#if STM32MP_USE_STM32IMAGE + uintptr_t dt_addr = STM32MP_DTB_BASE; +#else + uintptr_t dt_addr = arg1; +#endif + + /* Imprecise aborts can be masked in NonSecure */ + write_scr(read_scr() | SCR_AW_BIT); + + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + + configure_mmu(); + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params != NULL) { + if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + /* + * Check if hw_configuration is given to BL32 and + * share it to BL33. + */ + if (arg2 != 0U) { + bl33_image_ep_info.args.arg0 = 0U; + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = arg2; + } + + break; + } + + bl_params = bl_params->next_params_info; + } + + if (dt_open_and_check(dt_addr) < 0) { + panic(); + } + + if (bsec_probe() != 0) { + panic(); + } + + if (stm32mp1_clk_probe() < 0) { + panic(); + } + + (void)stm32mp_uart_console_setup(); + + stm32mp1_etzpc_early_setup(); +} + +/******************************************************************************* + * Initialize the MMU, security and the GIC. + ******************************************************************************/ +void sp_min_platform_setup(void) +{ + generic_delay_timer_init(); + + stm32mp1_gic_init(); + + if (stm32_iwdg_init() < 0) { + panic(); + } + + stm32mp_lock_periph_registering(); + + stm32mp1_init_scmi_server(); +} + +void sp_min_plat_arch_setup(void) +{ +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S new file mode 100644 index 0000000..85caa0a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if STM32MP_USE_STM32IMAGE +#ifdef BL32_BIN_PATH +.section .bl32_image +.incbin BL32_BIN_PATH +#endif +#endif /* STM32MP_USE_STM32IMAGE */ + +.section .bl2_image +.incbin BL2_BIN_PATH + +.section .dtb_image +.incbin DTB_BIN_PATH diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S new file mode 100644 index 0000000..2254fee --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_LD_S +#define STM32MP1_LD_S + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) + +ENTRY(__BL2_IMAGE_START__) + +MEMORY { + HEADER (rw) : ORIGIN = 0x00000000, LENGTH = STM32MP_HEADER_RESERVED_SIZE + RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE +} + +SECTIONS +{ + /* + * TF mapping must conform to ROM code specification. + */ + .header : { + __HEADER_START__ = .; + KEEP(*(.header)) + . = ALIGN(4); + __HEADER_END__ = .; + } >HEADER + + . = STM32MP_BINARY_BASE; + .data . : { + . = ALIGN(PAGE_SIZE); + __DATA_START__ = .; + *(.data*) + + /* + * dtb. + * The strongest and only alignment contraint is MMU 4K page. + * Indeed as images below will be removed, 4K pages will be re-used. + */ +#if STM32MP_USE_STM32IMAGE + . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE ); +#else + . = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE ); +#endif /* STM32MP_USE_STM32IMAGE */ + __DTB_IMAGE_START__ = .; + *(.dtb_image*) + __DTB_IMAGE_END__ = .; + + /* + * bl2. + * The strongest and only alignment contraint is MMU 4K page. + * Indeed as images below will be removed, 4K pages will be re-used. + */ +#if SEPARATE_CODE_AND_RODATA + . = ( STM32MP_BL2_RO_BASE - STM32MP_BINARY_BASE ); +#else + . = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE ); +#endif + __BL2_IMAGE_START__ = .; + *(.bl2_image*) + __BL2_IMAGE_END__ = .; + +#if STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) + /* + * bl32 will be settled by bl2. + * The strongest and only alignment constraint is 8 words to simplify + * memraise8 assembly code. + */ + . = ( STM32MP_BL32_BASE - STM32MP_BINARY_BASE ); + __BL32_IMAGE_START__ = .; + *(.bl32_image*) + __BL32_IMAGE_END__ = .; +#endif /* STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) */ + + __DATA_END__ = .; + } >RAM + + __TF_END__ = .; + +} +#endif /* STM32MP1_LD_S */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c new file mode 100644 index 0000000..b05de1c --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if STM32MP_RAW_NAND || STM32MP_SPI_NAND +static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc) +{ + uint32_t nand_param; + + /* Check if NAND parameters are stored in OTP */ + if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) { + ERROR("BSEC: NAND_OTP Error\n"); + return -EACCES; + } + + if (nand_param == 0U) { + return 0; + } + + if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) { + goto ecc; + } + + /* NAND parameter shall be read from OTP */ + if ((nand_param & NAND_WIDTH_MASK) != 0U) { + nand_dev->buswidth = NAND_BUS_WIDTH_16; + } else { + nand_dev->buswidth = NAND_BUS_WIDTH_8; + } + + switch ((nand_param & NAND_PAGE_SIZE_MASK) >> NAND_PAGE_SIZE_SHIFT) { + case NAND_PAGE_SIZE_2K: + nand_dev->page_size = 0x800U; + break; + + case NAND_PAGE_SIZE_4K: + nand_dev->page_size = 0x1000U; + break; + + case NAND_PAGE_SIZE_8K: + nand_dev->page_size = 0x2000U; + break; + + default: + ERROR("Cannot read NAND page size\n"); + return -EINVAL; + } + + switch ((nand_param & NAND_BLOCK_SIZE_MASK) >> NAND_BLOCK_SIZE_SHIFT) { + case NAND_BLOCK_SIZE_64_PAGES: + nand_dev->block_size = 64U * nand_dev->page_size; + break; + + case NAND_BLOCK_SIZE_128_PAGES: + nand_dev->block_size = 128U * nand_dev->page_size; + break; + + case NAND_BLOCK_SIZE_256_PAGES: + nand_dev->block_size = 256U * nand_dev->page_size; + break; + + default: + ERROR("Cannot read NAND block size\n"); + return -EINVAL; + } + + nand_dev->size = ((nand_param & NAND_BLOCK_NB_MASK) >> + NAND_BLOCK_NB_SHIFT) * + NAND_BLOCK_NB_UNIT * nand_dev->block_size; + +ecc: + if (is_slc) { + switch ((nand_param & NAND_ECC_BIT_NB_MASK) >> + NAND_ECC_BIT_NB_SHIFT) { + case NAND_ECC_BIT_NB_1_BITS: + nand_dev->ecc.max_bit_corr = 1U; + break; + + case NAND_ECC_BIT_NB_4_BITS: + nand_dev->ecc.max_bit_corr = 4U; + break; + + case NAND_ECC_BIT_NB_8_BITS: + nand_dev->ecc.max_bit_corr = 8U; + break; + + case NAND_ECC_ON_DIE: + nand_dev->ecc.mode = NAND_ECC_ONDIE; + break; + + default: + if (nand_dev->ecc.max_bit_corr == 0U) { + ERROR("No valid eccbit number\n"); + return -EINVAL; + } + } + } else { + /* Selected multiple plane NAND */ + if ((nand_param & NAND_PLANE_BIT_NB_MASK) != 0U) { + nand_dev->nb_planes = 2U; + } else { + nand_dev->nb_planes = 1U; + } + } + + VERBOSE("OTP: Block %u Page %u Size %llu\n", nand_dev->block_size, + nand_dev->page_size, nand_dev->size); + + return 0; +} +#endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */ + +#if STM32MP_RAW_NAND +int plat_get_raw_nand_data(struct rawnand_device *device) +{ + device->nand_dev->ecc.mode = NAND_ECC_HW; + device->nand_dev->ecc.size = SZ_512; + + return get_data_from_otp(device->nand_dev, true); +} +#endif + +#if STM32MP_SPI_NAND +int plat_get_spi_nand_data(struct spinand_device *device) +{ + zeromem(&device->spi_read_cache_op, sizeof(struct spi_mem_op)); + device->spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE_4X; + device->spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->spi_read_cache_op.addr.nbytes = 2U; + device->spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->spi_read_cache_op.dummy.nbytes = 1U; + device->spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE; + device->spi_read_cache_op.data.dir = SPI_MEM_DATA_IN; + + return get_data_from_otp(device->nand_dev, false); +} +#endif + +#if STM32MP_SPI_NOR +int plat_get_nor_data(struct nor_device *device) +{ + device->size = SZ_64M; + + zeromem(&device->read_op, sizeof(struct spi_mem_op)); + device->read_op.cmd.opcode = SPI_NOR_OP_READ_1_1_4; + device->read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->read_op.addr.nbytes = 3U; + device->read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->read_op.dummy.nbytes = 1U; + device->read_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->read_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE; + device->read_op.data.dir = SPI_MEM_DATA_IN; + + return 0; +} +#endif diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c new file mode 100644 index 0000000..08e332a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DBGMCU_IDC U(0x00) + +#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0) +#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16) +#define DBGMCU_IDC_REV_ID_SHIFT 16 + +static int stm32mp1_dbgmcu_init(void) +{ + if ((bsec_read_debug_conf() & BSEC_DBGSWGEN) == 0U) { + INFO("Software access to all debug components is disabled\n"); + return -1; + } + + mmio_setbits_32(RCC_BASE + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); + + return 0; +} + +/* + * @brief Get silicon revision from DBGMCU registers. + * @param chip_version: pointer to the read value. + * @retval 0 on success, negative value on failure. + */ +int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version) +{ + assert(chip_version != NULL); + + if (stm32mp1_dbgmcu_init() != 0) { + return -EPERM; + } + + *chip_version = (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & + DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT; + + return 0; +} + +/* + * @brief Get device ID from DBGMCU registers. + * @param chip_dev_id: pointer to the read value. + * @retval 0 on success, negative value on failure. + */ +int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id) +{ + assert(chip_dev_id != NULL); + + if (stm32mp1_dbgmcu_init() != 0) { + return -EPERM; + } + + *chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) & + DBGMCU_IDC_DEV_ID_MASK; + + return 0; +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h new file mode 100644 index 0000000..d869978 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_DEF_H +#define STM32MP1_DEF_H + +#include +#include +#include +#include +#include +#include + +#ifndef __ASSEMBLER__ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#endif + +#if !STM32MP_USE_STM32IMAGE +#include "stm32mp1_fip_def.h" +#else /* STM32MP_USE_STM32IMAGE */ +#include "stm32mp1_stm32image_def.h" +#endif /* STM32MP_USE_STM32IMAGE */ + +/******************************************************************************* + * CHIP ID + ******************************************************************************/ +#if STM32MP13 +#define STM32MP1_CHIP_ID U(0x501) + +#define STM32MP135C_PART_NB U(0x05010000) +#define STM32MP135A_PART_NB U(0x05010001) +#define STM32MP133C_PART_NB U(0x050100C0) +#define STM32MP133A_PART_NB U(0x050100C1) +#define STM32MP131C_PART_NB U(0x050106C8) +#define STM32MP131A_PART_NB U(0x050106C9) +#define STM32MP135F_PART_NB U(0x05010800) +#define STM32MP135D_PART_NB U(0x05010801) +#define STM32MP133F_PART_NB U(0x050108C0) +#define STM32MP133D_PART_NB U(0x050108C1) +#define STM32MP131F_PART_NB U(0x05010EC8) +#define STM32MP131D_PART_NB U(0x05010EC9) +#endif +#if STM32MP15 +#define STM32MP1_CHIP_ID U(0x500) + +#define STM32MP157C_PART_NB U(0x05000000) +#define STM32MP157A_PART_NB U(0x05000001) +#define STM32MP153C_PART_NB U(0x05000024) +#define STM32MP153A_PART_NB U(0x05000025) +#define STM32MP151C_PART_NB U(0x0500002E) +#define STM32MP151A_PART_NB U(0x0500002F) +#define STM32MP157F_PART_NB U(0x05000080) +#define STM32MP157D_PART_NB U(0x05000081) +#define STM32MP153F_PART_NB U(0x050000A4) +#define STM32MP153D_PART_NB U(0x050000A5) +#define STM32MP151F_PART_NB U(0x050000AE) +#define STM32MP151D_PART_NB U(0x050000AF) +#endif + +#define STM32MP1_REV_B U(0x2000) +#if STM32MP13 +#define STM32MP1_REV_Z U(0x1001) +#endif +#if STM32MP15 +#define STM32MP1_REV_Z U(0x2001) +#endif + +/******************************************************************************* + * PACKAGE ID + ******************************************************************************/ +#if STM32MP15 +#define PKG_AA_LFBGA448 U(4) +#define PKG_AB_LFBGA354 U(3) +#define PKG_AC_TFBGA361 U(2) +#define PKG_AD_TFBGA257 U(1) +#endif + +/******************************************************************************* + * STM32MP1 memory map related constants + ******************************************************************************/ +#define STM32MP_ROM_BASE U(0x00000000) +#define STM32MP_ROM_SIZE U(0x00020000) +#define STM32MP_ROM_SIZE_2MB_ALIGNED U(0x00200000) + +#if STM32MP13 +#define STM32MP_SYSRAM_BASE U(0x2FFE0000) +#define STM32MP_SYSRAM_SIZE U(0x00020000) +#define SRAM1_BASE U(0x30000000) +#define SRAM1_SIZE U(0x00004000) +#define SRAM2_BASE U(0x30004000) +#define SRAM2_SIZE U(0x00002000) +#define SRAM3_BASE U(0x30006000) +#define SRAM3_SIZE U(0x00002000) +#define SRAMS_BASE SRAM1_BASE +#define SRAMS_SIZE_2MB_ALIGNED U(0x00200000) +#endif /* STM32MP13 */ +#if STM32MP15 +#define STM32MP_SYSRAM_BASE U(0x2FFC0000) +#define STM32MP_SYSRAM_SIZE U(0x00040000) +#endif /* STM32MP15 */ + +#define STM32MP_NS_SYSRAM_SIZE PAGE_SIZE +#define STM32MP_NS_SYSRAM_BASE (STM32MP_SYSRAM_BASE + \ + STM32MP_SYSRAM_SIZE - \ + STM32MP_NS_SYSRAM_SIZE) + +#define STM32MP_SCMI_NS_SHM_BASE STM32MP_NS_SYSRAM_BASE +#define STM32MP_SCMI_NS_SHM_SIZE STM32MP_NS_SYSRAM_SIZE + +#define STM32MP_SEC_SYSRAM_BASE STM32MP_SYSRAM_BASE +#define STM32MP_SEC_SYSRAM_SIZE (STM32MP_SYSRAM_SIZE - \ + STM32MP_NS_SYSRAM_SIZE) + +/* DDR configuration */ +#define STM32MP_DDR_BASE U(0xC0000000) +#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */ + +/* DDR power initializations */ +#ifndef __ASSEMBLER__ +enum ddr_type { + STM32MP_DDR3, + STM32MP_LPDDR2, + STM32MP_LPDDR3 +}; +#endif + +/* Section used inside TF binaries */ +#if STM32MP13 +/* 512 Octets reserved for header */ +#define STM32MP_HEADER_RESERVED_SIZE U(0x200) + +#define STM32MP_BINARY_BASE STM32MP_SEC_SYSRAM_BASE + +#define STM32MP_BINARY_SIZE STM32MP_SEC_SYSRAM_SIZE +#endif +#if STM32MP15 +#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 KB for param */ +/* 256 Octets reserved for header */ +#define STM32MP_HEADER_SIZE U(0x00000100) +/* round_up(STM32MP_PARAM_LOAD_SIZE + STM32MP_HEADER_SIZE, PAGE_SIZE) */ +#define STM32MP_HEADER_RESERVED_SIZE U(0x3000) + +#define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_PARAM_LOAD_SIZE + \ + STM32MP_HEADER_SIZE) + +#define STM32MP_BINARY_SIZE (STM32MP_SEC_SYSRAM_SIZE - \ + (STM32MP_PARAM_LOAD_SIZE + \ + STM32MP_HEADER_SIZE)) +#endif + +/* BL2 and BL32/sp_min require finer granularity tables */ +#if defined(IMAGE_BL2) +#define MAX_XLAT_TABLES U(2) /* 8 KB for mapping */ +#endif + +#if defined(IMAGE_BL32) +#define MAX_XLAT_TABLES U(4) /* 16 KB for mapping */ +#endif + +/* + * MAX_MMAP_REGIONS is usually: + * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup + */ +#if defined(IMAGE_BL2) + #if STM32MP_USB_PROGRAMMER + #define MAX_MMAP_REGIONS 8 + #else + #define MAX_MMAP_REGIONS 7 + #endif +#endif + +#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000)) +#define STM32MP_BL33_MAX_SIZE U(0x400000) + +/* Define maximum page size for NAND devices */ +#define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000) + +/******************************************************************************* + * STM32MP1 device/io map related constants (used for MMU) + ******************************************************************************/ +#define STM32MP1_DEVICE1_BASE U(0x40000000) +#define STM32MP1_DEVICE1_SIZE U(0x40000000) + +#define STM32MP1_DEVICE2_BASE U(0x80000000) +#define STM32MP1_DEVICE2_SIZE U(0x40000000) + +/******************************************************************************* + * STM32MP1 RCC + ******************************************************************************/ +#define RCC_BASE U(0x50000000) + +/******************************************************************************* + * STM32MP1 PWR + ******************************************************************************/ +#define PWR_BASE U(0x50001000) + +/******************************************************************************* + * STM32MP1 GPIO + ******************************************************************************/ +#define GPIOA_BASE U(0x50002000) +#define GPIOB_BASE U(0x50003000) +#define GPIOC_BASE U(0x50004000) +#define GPIOD_BASE U(0x50005000) +#define GPIOE_BASE U(0x50006000) +#define GPIOF_BASE U(0x50007000) +#define GPIOG_BASE U(0x50008000) +#define GPIOH_BASE U(0x50009000) +#define GPIOI_BASE U(0x5000A000) +#if STM32MP15 +#define GPIOJ_BASE U(0x5000B000) +#define GPIOK_BASE U(0x5000C000) +#define GPIOZ_BASE U(0x54004000) +#endif +#define GPIO_BANK_OFFSET U(0x1000) + +/* Bank IDs used in GPIO driver API */ +#define GPIO_BANK_A U(0) +#define GPIO_BANK_B U(1) +#define GPIO_BANK_C U(2) +#define GPIO_BANK_D U(3) +#define GPIO_BANK_E U(4) +#define GPIO_BANK_F U(5) +#define GPIO_BANK_G U(6) +#define GPIO_BANK_H U(7) +#define GPIO_BANK_I U(8) +#if STM32MP15 +#define GPIO_BANK_J U(9) +#define GPIO_BANK_K U(10) +#define GPIO_BANK_Z U(25) + +#define STM32MP_GPIOZ_PIN_MAX_COUNT 8 +#endif + +/******************************************************************************* + * STM32MP1 UART + ******************************************************************************/ +#define USART1_BASE U(0x5C000000) +#define USART2_BASE U(0x4000E000) +#define USART3_BASE U(0x4000F000) +#define UART4_BASE U(0x40010000) +#define UART5_BASE U(0x40011000) +#define USART6_BASE U(0x44003000) +#define UART7_BASE U(0x40018000) +#define UART8_BASE U(0x40019000) + +/* For UART crash console */ +#define STM32MP_DEBUG_USART_BASE UART4_BASE +#if STM32MP13 +/* UART4 on HSI@64MHz, TX on GPIOF12 Alternate 8 (Disco board) */ +#define STM32MP_DEBUG_USART_CLK_FRQ 64000000 +#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOD_BASE +#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_S_AHB4ENSETR +#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_S_AHB4ENSETR_GPIODEN +#define DEBUG_UART_TX_GPIO_PORT 6 +#define DEBUG_UART_TX_GPIO_ALTERNATE 8 +#define DEBUG_UART_TX_CLKSRC_REG RCC_UART4CKSELR +#define DEBUG_UART_TX_CLKSRC RCC_UART4CKSELR_HSI +#endif /* STM32MP13 */ +#if STM32MP15 +/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */ +#define STM32MP_DEBUG_USART_CLK_FRQ 64000000 +#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE +#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR +#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN +#define DEBUG_UART_TX_GPIO_PORT 11 +#define DEBUG_UART_TX_GPIO_ALTERNATE 6 +#define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR +#define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI +#endif /* STM32MP15 */ +#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR +#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN +#define DEBUG_UART_RST_REG RCC_APB1RSTSETR +#define DEBUG_UART_RST_BIT RCC_APB1RSTSETR_UART4RST + +/******************************************************************************* + * STM32MP1 ETZPC + ******************************************************************************/ +#define STM32MP1_ETZPC_BASE U(0x5C007000) + +/* ETZPC TZMA IDs */ +#define STM32MP1_ETZPC_TZMA_ROM U(0) +#define STM32MP1_ETZPC_TZMA_SYSRAM U(1) + +#define STM32MP1_ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0) + +/* ETZPC DECPROT IDs */ +#define STM32MP1_ETZPC_STGENC_ID 0 +#define STM32MP1_ETZPC_BKPSRAM_ID 1 +#define STM32MP1_ETZPC_IWDG1_ID 2 +#define STM32MP1_ETZPC_USART1_ID 3 +#define STM32MP1_ETZPC_SPI6_ID 4 +#define STM32MP1_ETZPC_I2C4_ID 5 +#define STM32MP1_ETZPC_RNG1_ID 7 +#define STM32MP1_ETZPC_HASH1_ID 8 +#define STM32MP1_ETZPC_CRYP1_ID 9 +#define STM32MP1_ETZPC_DDRCTRL_ID 10 +#define STM32MP1_ETZPC_DDRPHYC_ID 11 +#define STM32MP1_ETZPC_I2C6_ID 12 +#define STM32MP1_ETZPC_SEC_ID_LIMIT 13 + +#define STM32MP1_ETZPC_TIM2_ID 16 +#define STM32MP1_ETZPC_TIM3_ID 17 +#define STM32MP1_ETZPC_TIM4_ID 18 +#define STM32MP1_ETZPC_TIM5_ID 19 +#define STM32MP1_ETZPC_TIM6_ID 20 +#define STM32MP1_ETZPC_TIM7_ID 21 +#define STM32MP1_ETZPC_TIM12_ID 22 +#define STM32MP1_ETZPC_TIM13_ID 23 +#define STM32MP1_ETZPC_TIM14_ID 24 +#define STM32MP1_ETZPC_LPTIM1_ID 25 +#define STM32MP1_ETZPC_WWDG1_ID 26 +#define STM32MP1_ETZPC_SPI2_ID 27 +#define STM32MP1_ETZPC_SPI3_ID 28 +#define STM32MP1_ETZPC_SPDIFRX_ID 29 +#define STM32MP1_ETZPC_USART2_ID 30 +#define STM32MP1_ETZPC_USART3_ID 31 +#define STM32MP1_ETZPC_UART4_ID 32 +#define STM32MP1_ETZPC_UART5_ID 33 +#define STM32MP1_ETZPC_I2C1_ID 34 +#define STM32MP1_ETZPC_I2C2_ID 35 +#define STM32MP1_ETZPC_I2C3_ID 36 +#define STM32MP1_ETZPC_I2C5_ID 37 +#define STM32MP1_ETZPC_CEC_ID 38 +#define STM32MP1_ETZPC_DAC_ID 39 +#define STM32MP1_ETZPC_UART7_ID 40 +#define STM32MP1_ETZPC_UART8_ID 41 +#define STM32MP1_ETZPC_MDIOS_ID 44 +#define STM32MP1_ETZPC_TIM1_ID 48 +#define STM32MP1_ETZPC_TIM8_ID 49 +#define STM32MP1_ETZPC_USART6_ID 51 +#define STM32MP1_ETZPC_SPI1_ID 52 +#define STM32MP1_ETZPC_SPI4_ID 53 +#define STM32MP1_ETZPC_TIM15_ID 54 +#define STM32MP1_ETZPC_TIM16_ID 55 +#define STM32MP1_ETZPC_TIM17_ID 56 +#define STM32MP1_ETZPC_SPI5_ID 57 +#define STM32MP1_ETZPC_SAI1_ID 58 +#define STM32MP1_ETZPC_SAI2_ID 59 +#define STM32MP1_ETZPC_SAI3_ID 60 +#define STM32MP1_ETZPC_DFSDM_ID 61 +#define STM32MP1_ETZPC_TT_FDCAN_ID 62 +#define STM32MP1_ETZPC_LPTIM2_ID 64 +#define STM32MP1_ETZPC_LPTIM3_ID 65 +#define STM32MP1_ETZPC_LPTIM4_ID 66 +#define STM32MP1_ETZPC_LPTIM5_ID 67 +#define STM32MP1_ETZPC_SAI4_ID 68 +#define STM32MP1_ETZPC_VREFBUF_ID 69 +#define STM32MP1_ETZPC_DCMI_ID 70 +#define STM32MP1_ETZPC_CRC2_ID 71 +#define STM32MP1_ETZPC_ADC_ID 72 +#define STM32MP1_ETZPC_HASH2_ID 73 +#define STM32MP1_ETZPC_RNG2_ID 74 +#define STM32MP1_ETZPC_CRYP2_ID 75 +#define STM32MP1_ETZPC_SRAM1_ID 80 +#define STM32MP1_ETZPC_SRAM2_ID 81 +#define STM32MP1_ETZPC_SRAM3_ID 82 +#define STM32MP1_ETZPC_SRAM4_ID 83 +#define STM32MP1_ETZPC_RETRAM_ID 84 +#define STM32MP1_ETZPC_OTG_ID 85 +#define STM32MP1_ETZPC_SDMMC3_ID 86 +#define STM32MP1_ETZPC_DLYBSD3_ID 87 +#define STM32MP1_ETZPC_DMA1_ID 88 +#define STM32MP1_ETZPC_DMA2_ID 89 +#define STM32MP1_ETZPC_DMAMUX_ID 90 +#define STM32MP1_ETZPC_FMC_ID 91 +#define STM32MP1_ETZPC_QSPI_ID 92 +#define STM32MP1_ETZPC_DLYBQ_ID 93 +#define STM32MP1_ETZPC_ETH_ID 94 +#define STM32MP1_ETZPC_RSV_ID 95 + +#define STM32MP_ETZPC_MAX_ID 96 + +/******************************************************************************* + * STM32MP1 TZC (TZ400) + ******************************************************************************/ +#define STM32MP1_TZC_BASE U(0x5C006000) + +#if STM32MP13 +#define STM32MP1_FILTER_BIT_ALL TZC_400_REGION_ATTR_FILTER_BIT(0) +#endif +#if STM32MP15 +#define STM32MP1_FILTER_BIT_ALL (TZC_400_REGION_ATTR_FILTER_BIT(0) | \ + TZC_400_REGION_ATTR_FILTER_BIT(1)) +#endif + +/******************************************************************************* + * STM32MP1 SDMMC + ******************************************************************************/ +#define STM32MP_SDMMC1_BASE U(0x58005000) +#define STM32MP_SDMMC2_BASE U(0x58007000) +#define STM32MP_SDMMC3_BASE U(0x48004000) + +#define STM32MP_MMC_INIT_FREQ U(400000) /*400 KHz*/ +#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ U(25000000) /*25 MHz*/ +#define STM32MP_SD_HIGH_SPEED_MAX_FREQ U(50000000) /*50 MHz*/ +#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ U(26000000) /*26 MHz*/ +#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ U(52000000) /*52 MHz*/ + +/******************************************************************************* + * STM32MP1 BSEC / OTP + ******************************************************************************/ +#define STM32MP1_OTP_MAX_ID 0x5FU +#define STM32MP1_UPPER_OTP_START 0x20U + +#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) + +/* OTP labels */ +#define CFG0_OTP "cfg0_otp" +#define PART_NUMBER_OTP "part_number_otp" +#if STM32MP15 +#define PACKAGE_OTP "package_otp" +#endif +#define HW2_OTP "hw2_otp" +#define NAND_OTP "nand_otp" +#define MONOTONIC_OTP "monotonic_otp" +#define UID_OTP "uid_otp" +#define BOARD_ID_OTP "board_id" + +/* OTP mask */ +/* CFG0 */ +#if STM32MP13 +#define CFG0_OTP_MODE_MASK GENMASK_32(9, 0) +#define CFG0_OTP_MODE_SHIFT 0 +#define CFG0_OPEN_DEVICE 0x17U +#define CFG0_CLOSED_DEVICE 0x3FU +#define CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN 0x17FU +#define CFG0_CLOSED_DEVICE_NO_JTAG 0x3FFU +#endif +#if STM32MP15 +#define CFG0_CLOSED_DEVICE BIT(6) +#endif + +/* PART NUMBER */ +#if STM32MP13 +#define PART_NUMBER_OTP_PART_MASK GENMASK_32(11, 0) +#endif +#if STM32MP15 +#define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0) +#endif +#define PART_NUMBER_OTP_PART_SHIFT 0 + +/* PACKAGE */ +#if STM32MP15 +#define PACKAGE_OTP_PKG_MASK GENMASK_32(29, 27) +#define PACKAGE_OTP_PKG_SHIFT 27 +#endif + +/* IWDG OTP */ +#define HW2_OTP_IWDG_HW_POS U(3) +#define HW2_OTP_IWDG_FZ_STOP_POS U(5) +#define HW2_OTP_IWDG_FZ_STANDBY_POS U(7) + +/* HW2 OTP */ +#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13) + +/* NAND OTP */ +/* NAND parameter storage flag */ +#define NAND_PARAM_STORED_IN_OTP BIT(31) + +/* NAND page size in bytes */ +#define NAND_PAGE_SIZE_MASK GENMASK_32(30, 29) +#define NAND_PAGE_SIZE_SHIFT 29 +#define NAND_PAGE_SIZE_2K U(0) +#define NAND_PAGE_SIZE_4K U(1) +#define NAND_PAGE_SIZE_8K U(2) + +/* NAND block size in pages */ +#define NAND_BLOCK_SIZE_MASK GENMASK_32(28, 27) +#define NAND_BLOCK_SIZE_SHIFT 27 +#define NAND_BLOCK_SIZE_64_PAGES U(0) +#define NAND_BLOCK_SIZE_128_PAGES U(1) +#define NAND_BLOCK_SIZE_256_PAGES U(2) + +/* NAND number of block (in unit of 256 blocs) */ +#define NAND_BLOCK_NB_MASK GENMASK_32(26, 19) +#define NAND_BLOCK_NB_SHIFT 19 +#define NAND_BLOCK_NB_UNIT U(256) + +/* NAND bus width in bits */ +#define NAND_WIDTH_MASK BIT(18) +#define NAND_WIDTH_SHIFT 18 + +/* NAND number of ECC bits per 512 bytes */ +#define NAND_ECC_BIT_NB_MASK GENMASK_32(17, 15) +#define NAND_ECC_BIT_NB_SHIFT 15 +#define NAND_ECC_BIT_NB_UNSET U(0) +#define NAND_ECC_BIT_NB_1_BITS U(1) +#define NAND_ECC_BIT_NB_4_BITS U(2) +#define NAND_ECC_BIT_NB_8_BITS U(3) +#define NAND_ECC_ON_DIE U(4) + +/* NAND number of planes */ +#define NAND_PLANE_BIT_NB_MASK BIT(14) + +/* MONOTONIC OTP */ +#define MAX_MONOTONIC_VALUE 32 + +/* UID OTP */ +#define UID_WORD_NB U(3) + +/******************************************************************************* + * STM32MP1 TAMP + ******************************************************************************/ +#define TAMP_BASE U(0x5C00A000) +#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100)) + +#if !(defined(__LINKER__) || defined(__ASSEMBLER__)) +static inline uintptr_t tamp_bkpr(uint32_t idx) +{ + return TAMP_BKP_REGISTER_BASE + (idx << 2); +} +#endif + +/******************************************************************************* + * STM32MP1 USB + ******************************************************************************/ +#define USB_OTG_BASE U(0x49000000) + +/******************************************************************************* + * STM32MP1 DDRCTRL + ******************************************************************************/ +#define DDRCTRL_BASE U(0x5A003000) + +/******************************************************************************* + * STM32MP1 DDRPHYC + ******************************************************************************/ +#define DDRPHYC_BASE U(0x5A004000) + +/******************************************************************************* + * STM32MP1 IWDG + ******************************************************************************/ +#define IWDG_MAX_INSTANCE U(2) +#define IWDG1_INST U(0) +#define IWDG2_INST U(1) + +#define IWDG1_BASE U(0x5C003000) +#define IWDG2_BASE U(0x5A002000) + +/******************************************************************************* + * Miscellaneous STM32MP1 peripherals base address + ******************************************************************************/ +#define BSEC_BASE U(0x5C005000) +#if STM32MP13 +#define CRYP_BASE U(0x54002000) +#endif +#if STM32MP15 +#define CRYP1_BASE U(0x54001000) +#endif +#define DBGMCU_BASE U(0x50081000) +#if STM32MP13 +#define HASH_BASE U(0x54003000) +#endif +#if STM32MP15 +#define HASH1_BASE U(0x54002000) +#endif +#if STM32MP13 +#define I2C3_BASE U(0x4C004000) +#define I2C4_BASE U(0x4C005000) +#define I2C5_BASE U(0x4C006000) +#endif +#if STM32MP15 +#define I2C4_BASE U(0x5C002000) +#define I2C6_BASE U(0x5c009000) +#endif +#if STM32MP13 +#define RNG_BASE U(0x54004000) +#endif +#if STM32MP15 +#define RNG1_BASE U(0x54003000) +#endif +#define RTC_BASE U(0x5c004000) +#if STM32MP13 +#define SPI4_BASE U(0x4C002000) +#define SPI5_BASE U(0x4C003000) +#endif +#if STM32MP15 +#define SPI6_BASE U(0x5c001000) +#endif +#define STGEN_BASE U(0x5c008000) +#define SYSCFG_BASE U(0x50020000) + +/******************************************************************************* + * STM32MP13 SAES + ******************************************************************************/ +#define SAES_BASE U(0x54005000) + +/******************************************************************************* + * STM32MP13 PKA + ******************************************************************************/ +#define PKA_BASE U(0x54006000) + +/******************************************************************************* + * REGULATORS + ******************************************************************************/ +/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */ +#define PLAT_NB_RDEVS U(19) +/* 2 FIXED */ +#define PLAT_NB_FIXED_REGS U(2) + +/******************************************************************************* + * Device Tree defines + ******************************************************************************/ +#define DT_BSEC_COMPAT "st,stm32mp15-bsec" +#if STM32MP13 +#define DT_DDR_COMPAT "st,stm32mp13-ddr" +#endif +#if STM32MP15 +#define DT_DDR_COMPAT "st,stm32mp1-ddr" +#endif +#define DT_IWDG_COMPAT "st,stm32mp1-iwdg" +#define DT_NVMEM_LAYOUT_COMPAT "st,stm32-nvmem-layout" +#define DT_PWR_COMPAT "st,stm32mp1,pwr-reg" +#if STM32MP13 +#define DT_RCC_CLK_COMPAT "st,stm32mp13-rcc" +#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp13-rcc-secure" +#endif +#if STM32MP15 +#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" +#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp1-rcc-secure" +#endif +#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" + +#endif /* STM32MP1_DEF_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c new file mode 100644 index 0000000..f2568ab --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define STM32MP_REGION_PARAMS 4 +#define STM32MP_MAX_REGIONS 8 +#define FORCE_SEC_REGION BIT(31) + +static uint32_t nb_regions; + +struct dt_id_attr { + fdt32_t id_attr[STM32MP_MAX_REGIONS]; +}; + +void stm32mp1_arch_security_setup(void) +{ +#if STM32MP13 + clk_enable(TZC); +#endif +#if STM32MP15 + clk_enable(TZC1); + clk_enable(TZC2); +#endif + + tzc400_init(STM32MP1_TZC_BASE); + tzc400_disable_filters(); + + /* + * Region 0 set to cover all DRAM at 0xC000_0000 + * Only secure access is granted in read/write. + */ + tzc400_configure_region0(TZC_REGION_S_RDWR, 0); + + tzc400_set_action(TZC_ACTION_ERR); + tzc400_enable_filters(); +} + +void stm32mp1_security_setup(void) +{ + uint8_t i; + + assert(nb_regions > 0U); + + tzc400_init(STM32MP1_TZC_BASE); + tzc400_disable_filters(); + + /* + * Region 0 set to cover all DRAM at 0xC000_0000 + * No access is allowed. + */ + tzc400_configure_region0(TZC_REGION_S_NONE, 0); + + for (i = 1U; i <= nb_regions; i++) { + tzc400_update_filters(i, STM32MP1_FILTER_BIT_ALL); + } + + tzc400_set_action(TZC_ACTION_INT); + tzc400_enable_filters(); +} + +static int fconf_populate_stm32mp1_firewall(uintptr_t config) +{ + int node, len; + unsigned int i; + const struct dt_id_attr *conf_list; + const void *dtb = (const void *)config; + + /* Assert the node offset point to "st,mem-firewall" compatible property */ + const char *compatible_str = "st,mem-firewall"; + + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); + return node; + } + + conf_list = (const struct dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len); + if (conf_list == NULL) { + WARN("FCONF: Read cell failed for %s\n", "memory-ranges"); + return -1; + } + + /* Locate the memory cells and read all values */ + for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * STM32MP_REGION_PARAMS)); i++) { + uint32_t base; + uint32_t size; + uint32_t sec_attr; + uint32_t nsaid; + + base = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS]); + size = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 1]); + sec_attr = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 2]); + nsaid = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 3]); + + VERBOSE("FCONF: stm32mp1-firewall cell found with value = 0x%x 0x%x 0x%x 0x%x\n", + base, size, sec_attr, nsaid); + + nb_regions++; + + /* Configure region but keep disabled for secure access for BL2 load */ + tzc400_configure_region(0U, nb_regions, (unsigned long long)base, + (unsigned long long)base + size - 1ULL, sec_attr, nsaid); + } + + /* Force flush as the value will be used cache off */ + flush_dcache_range((uintptr_t)&nb_regions, sizeof(uint32_t)); + + return 0; +} + +FCONF_REGISTER_POPULATOR(FW_CONFIG, stm32mp1_firewall, fconf_populate_stm32mp1_firewall); diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h new file mode 100644 index 0000000..7a277fd --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2021-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_FIP_DEF_H +#define STM32MP1_FIP_DEF_H + +#define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */ +#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ + +#if STM32MP13 +#define STM32MP_BL2_RO_SIZE U(0x00015000) /* 84 KB */ +#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */ +#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */ +#endif /* STM32MP13 */ +#if STM32MP15 +#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */ +#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */ +#define STM32MP_BL2_DTB_SIZE U(0x00007000) /* 28 KB for DTB */ +#endif /* STM32MP15 */ +#define STM32MP_BL32_SIZE U(0x0001B000) /* 108 KB for BL32 */ +#define STM32MP_BL32_DTB_SIZE U(0x00005000) /* 20 KB for DTB */ +#define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE /* 4 KB for FCONF DTB */ +#define STM32MP_HW_CONFIG_MAX_SIZE U(0x40000) /* 256 KB for HW config DTB */ + +#if STM32MP13 +#define STM32MP_BL2_BASE (STM32MP_BL2_DTB_BASE + \ + STM32MP_BL2_DTB_SIZE) +#endif /* STM32MP13 */ +#if STM32MP15 +#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL2_SIZE) +#endif /* STM32MP15 */ + +#define STM32MP_BL2_RO_BASE STM32MP_BL2_BASE + +#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \ + STM32MP_BL2_RO_SIZE) + +#if STM32MP13 +#define STM32MP_BL2_RW_SIZE (STM32MP_SYSRAM_BASE + \ + STM32MP_SYSRAM_SIZE - \ + STM32MP_BL2_RW_BASE) + +#define STM32MP_BL2_DTB_BASE STM32MP_SEC_SYSRAM_BASE +#endif /* STM32MP13 */ +#if STM32MP15 +#define STM32MP_BL2_RW_SIZE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL2_RW_BASE) + +#define STM32MP_BL2_DTB_BASE (STM32MP_BL2_BASE - \ + STM32MP_BL2_DTB_SIZE) +#endif /* STM32MP15 */ + +#define STM32MP_BL32_DTB_BASE STM32MP_SYSRAM_BASE + +#define STM32MP_BL32_BASE (STM32MP_BL32_DTB_BASE + \ + STM32MP_BL32_DTB_SIZE) + + +#if defined(IMAGE_BL2) +#define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE +#define STM32MP_DTB_BASE STM32MP_BL2_DTB_BASE +#endif +#if defined(IMAGE_BL32) +#define STM32MP_DTB_SIZE STM32MP_BL32_DTB_SIZE +#define STM32MP_DTB_BASE STM32MP_BL32_DTB_BASE +#endif + +#ifdef AARCH32_SP_OPTEE +#define STM32MP_OPTEE_BASE STM32MP_SEC_SYSRAM_BASE + +#define STM32MP_OPTEE_SIZE (STM32MP_BL2_DTB_BASE - \ + STM32MP_OPTEE_BASE) +#endif + +#if STM32MP13 +#define STM32MP_FW_CONFIG_BASE SRAM3_BASE +#endif /* STM32MP13 */ +#if STM32MP15 +#define STM32MP_FW_CONFIG_BASE (STM32MP_SYSRAM_BASE + \ + STM32MP_SYSRAM_SIZE - \ + PAGE_SIZE) +#endif /* STM32MP15 */ +#define STM32MP_HW_CONFIG_BASE (STM32MP_BL33_BASE + \ + STM32MP_BL33_MAX_SIZE) + +/* + * MAX_MMAP_REGIONS is usually: + * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup + */ +#if defined(IMAGE_BL32) +#define MAX_MMAP_REGIONS 10 +#endif + +/******************************************************************************* + * STM32MP1 RAW partition offset for MTD devices + ******************************************************************************/ +#define STM32MP_NOR_FIP_OFFSET U(0x00080000) +#define STM32MP_NAND_FIP_OFFSET U(0x00200000) + +#endif /* STM32MP1_FIP_DEF_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c new file mode 100644 index 0000000..851a9cf --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +struct stm32_gic_instance { + uint32_t cells; + uint32_t phandle_node; +}; + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t stm32mp1_interrupt_props[] = { + PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0), + PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) +}; + +/* Fix target_mask_array as secondary core is not able to initialize it */ +static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2}; + +static gicv2_driver_data_t platform_gic_data = { + .interrupt_props = stm32mp1_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +static struct stm32_gic_instance stm32_gic; + +void stm32mp1_gic_init(void) +{ + int node; + void *fdt; + const fdt32_t *cuint; + struct dt_node_info dt_gic; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic"); + if (node < 0) { + panic(); + } + + platform_gic_data.gicd_base = dt_gic.base; + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint == NULL) { + panic(); + } + + platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2)); + + cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL); + if (cuint == NULL) { + panic(); + } + + stm32_gic.cells = fdt32_to_cpu(*cuint); + + stm32_gic.phandle_node = fdt_get_phandle(fdt, node); + if (stm32_gic.phandle_node == 0U) { + panic(); + } + + gicv2_driver_init(&platform_gic_data); + gicv2_distif_init(); + + stm32mp1_gic_pcpu_init(); +} + +void stm32mp1_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + gicv2_cpuif_enable(); +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S new file mode 100644 index 0000000..cac9752 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) + + .globl platform_mem_init + .globl plat_report_exception + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .globl plat_reset_handler + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_flush + .globl plat_crash_console_putc + .globl plat_panic_handler + +func platform_mem_init + /* Nothing to do, don't need to init SYSRAM */ + bx lr +endfunc platform_mem_init + +func plat_report_exception +#if DEBUG + mov r8, lr + + /* Test if an abort occurred */ + cmp r0, #MODE32_abt + bne undef_inst_lbl + ldr r4, =abort_str + bl asm_print_str + mrs r4, lr_abt + sub r4, r4, #4 + b print_exception_info + +undef_inst_lbl: + /* Test for an undefined instruction */ + cmp r0, #MODE32_und + bne other_exception_lbl + ldr r4, =undefined_str + bl asm_print_str + mrs r4, lr_und + b print_exception_info + +other_exception_lbl: + /* Other exceptions */ + mov r9, r0 + ldr r4, =exception_start_str + bl asm_print_str + mov r4, r9 + bl asm_print_hex + ldr r4, =exception_end_str + bl asm_print_str + mov r4, r6 + +print_exception_info: + bl asm_print_hex + + ldr r4, =end_error_str + bl asm_print_str + + bx r8 +#else + bx lr +#endif +endfunc plat_report_exception + +func plat_reset_handler + bx lr +endfunc plat_reset_handler + + /* ------------------------------------------------------------------ + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. + * + * Currently supports only cold boot + * ------------------------------------------------------------------ + */ +func plat_get_my_entrypoint + mov r0, #0 + bx lr +endfunc plat_get_my_entrypoint + + /* --------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * Cold-booting secondary CPUs is not supported. + * --------------------------------------------- + */ +func plat_secondary_cold_boot_setup + b . +endfunc plat_secondary_cold_boot_setup + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + and r0, r1 + cmp r0, #STM32MP_PRIMARY_CPU + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* ------------------------------------------- + * int plat_stm32mp1_get_core_pos(int mpidr); + * + * Return CorePos = (ClusterId * 4) + CoreId + * ------------------------------------------- + */ +func plat_stm32mp1_get_core_pos + and r1, r0, #MPIDR_CPU_MASK + and r0, r0, #MPIDR_CLUSTER_MASK + add r0, r1, r0, LSR #6 + bx lr +endfunc plat_stm32mp1_get_core_pos + + /* ------------------------------------ + * unsigned int plat_my_core_pos(void) + * ------------------------------------ + */ +func plat_my_core_pos + ldcopr r0, MPIDR + b plat_stm32mp1_get_core_pos +endfunc plat_my_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * + * Initialize the crash console without a C Runtime stack. + * --------------------------------------------- + */ +func plat_crash_console_init + /* Reset UART peripheral */ + ldr r1, =(RCC_BASE + DEBUG_UART_RST_REG) + ldr r2, =DEBUG_UART_RST_BIT + str r2, [r1] +1: + ldr r0, [r1] + ands r2, r0, r2 + beq 1b + str r2, [r1, #4] /* RSTCLR register */ +2: + ldr r0, [r1] + ands r2, r0, r2 + bne 2b + /* Enable GPIOs for UART TX */ + ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG) + ldr r2, [r1] + /* Configure GPIO */ + orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN + str r2, [r1] + ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS + /* Set GPIO mode alternate */ + ldr r2, [r1, #GPIO_MODE_OFFSET] + bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT) + orr r2, r2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT) + str r2, [r1, #GPIO_MODE_OFFSET] + /* Set GPIO speed low */ + ldr r2, [r1, #GPIO_SPEED_OFFSET] + bic r2, r2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT) + str r2, [r1, #GPIO_SPEED_OFFSET] + /* Set no-pull */ + ldr r2, [r1, #GPIO_PUPD_OFFSET] + bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT) + str r2, [r1, #GPIO_PUPD_OFFSET] + /* Set alternate */ +#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT + ldr r2, [r1, #GPIO_AFRH_OFFSET] + bic r2, r2, #(GPIO_ALTERNATE_MASK << \ + ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)) + orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \ + ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)) + str r2, [r1, #GPIO_AFRH_OFFSET] +#else + ldr r2, [r1, #GPIO_AFRL_OFFSET] + bic r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2)) + orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2)) + str r2, [r1, #GPIO_AFRL_OFFSET] +#endif + /* Enable UART clock, with its source */ + ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG) + mov r2, #DEBUG_UART_TX_CLKSRC + str r2, [r1] + ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG) + ldr r2, [r1] + orr r2, r2, #DEBUG_UART_TX_EN + str r2, [r1] + + ldr r0, =STM32MP_DEBUG_USART_BASE + ldr r1, =STM32MP_DEBUG_USART_CLK_FRQ + ldr r2, =STM32MP_UART_BAUDRATE + b console_stm32_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * void plat_crash_console_flush(void) + * + * Flush the crash console without a C Runtime stack. + * --------------------------------------------- + */ +func plat_crash_console_flush + ldr r0, =STM32MP_DEBUG_USART_BASE + b console_stm32_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * + * Print a character on the crash console without a C Runtime stack. + * Clobber list : r1 - r3 + * + * In case of bootloading through uart, we keep console crash as this. + * Characters could be sent to the programmer, but will be ignored. + * No specific code in that case. + * --------------------------------------------- + */ +func plat_crash_console_putc + ldr r1, =STM32MP_DEBUG_USART_BASE + b console_stm32_core_putc +endfunc plat_crash_console_putc + + /* ---------------------------------------------------------- + * void plat_panic_handler(void) __dead2; + * Report exception + endless loop. + * + * r6 holds the address where the fault occurred. + * Filling lr with this value allows debuggers to reconstruct + * the backtrace. + * ---------------------------------------------------------- + */ +func plat_panic_handler + mrs r0, cpsr + and r0, #MODE32_MASK + bl plat_report_exception + mov lr, r6 + b . +endfunc plat_panic_handler + +#if DEBUG +.section .rodata.rev_err_str, "aS" +abort_str: + .asciz "\nAbort at: 0x" +undefined_str: + .asciz "\nUndefined instruction at: 0x" +exception_start_str: + .asciz "\nException mode=0x" +exception_end_str: + .asciz " at: 0x" +end_error_str: + .asciz "\n\r" +#endif diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c new file mode 100644 index 0000000..3892151 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2015-2022, 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 + +static uintptr_t stm32_sec_entrypoint; +static uint32_t cntfrq_core0; + +/******************************************************************************* + * STM32MP1 handler called when a CPU is about to enter standby. + * call by core 1 to enter in wfi + ******************************************************************************/ +static void stm32_cpu_standby(plat_local_state_t cpu_state) +{ + uint32_t interrupt = GIC_SPURIOUS_INTERRUPT; + + assert(cpu_state == ARM_LOCAL_STATE_RET); + + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + isb(); + dsb(); + while (interrupt == GIC_SPURIOUS_INTERRUPT) { + wfi(); + + /* Acknoledge IT */ + interrupt = gicv2_acknowledge_interrupt(); + /* If Interrupt == 1022 it will be acknowledged by non secure */ + if ((interrupt != PENDING_G1_INTID) && + (interrupt != GIC_SPURIOUS_INTERRUPT)) { + gicv2_end_of_interrupt(interrupt); + } + } +} + +/******************************************************************************* + * STM32MP1 handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + * call by core 0 to activate core 1 + ******************************************************************************/ +static int stm32_pwr_domain_on(u_register_t mpidr) +{ + unsigned long current_cpu_mpidr = read_mpidr_el1(); + uintptr_t bkpr_core1_addr = + tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); + uintptr_t bkpr_core1_magic = + tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); + + if (mpidr == current_cpu_mpidr) { + return PSCI_E_INVALID_PARAMS; + } + + /* Only one valid entry point */ + if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) { + return PSCI_E_INVALID_ADDRESS; + } + + clk_enable(RTCAPB); + + cntfrq_core0 = read_cntfrq_el0(); + + /* Write entrypoint in backup RAM register */ + mmio_write_32(bkpr_core1_addr, stm32_sec_entrypoint); + + /* Write magic number in backup register */ + mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER); + + clk_disable(RTCAPB); + + /* Generate an IT to core 1 */ + gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * STM32MP1 handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void stm32_pwr_domain_off(const psci_power_state_t *target_state) +{ + /* Nothing to do */ +} + +/******************************************************************************* + * STM32MP1 handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + /* Nothing to do, power domain is not disabled */ +} + +/******************************************************************************* + * STM32MP1 handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + * call by core 1 just after wake up + ******************************************************************************/ +static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + stm32mp1_gic_pcpu_init(); + + write_cntfrq_el0(cntfrq_core0); +} + +/******************************************************************************* + * STM32MP1 handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + ******************************************************************************/ +static void stm32_pwr_domain_suspend_finish(const psci_power_state_t + *target_state) +{ + /* Nothing to do, power domain is not disabled */ +} + +static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t + *target_state) +{ + ERROR("stm32mpu1 Power Down WFI: operation not handled.\n"); + panic(); +} + +static void __dead2 stm32_system_off(void) +{ + ERROR("stm32mpu1 System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 stm32_system_reset(void) +{ + mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, + RCC_MP_GRSTCSETR_MPSYSRST); + + /* Loop in case system reset is not immediately caught */ + for ( ; ; ) { + ; + } +} + +static int stm32_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pstate = psci_get_pstate_type(power_state); + + if (pstate != 0) { + return PSCI_E_INVALID_PARAMS; + } + + if (psci_get_pstate_pwrlvl(power_state)) { + return PSCI_E_INVALID_PARAMS; + } + + if (psci_get_pstate_id(power_state)) { + return PSCI_E_INVALID_PARAMS; + } + + req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_RET; + req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_RUN; + + return PSCI_E_SUCCESS; +} + +static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* The non-secure entry point must be in DDR */ + if (entrypoint < STM32MP_DDR_BASE) { + return PSCI_E_INVALID_ADDRESS; + } + + return PSCI_E_SUCCESS; +} + +static int stm32_node_hw_state(u_register_t target_cpu, + unsigned int power_level) +{ + /* + * The format of 'power_level' is implementation-defined, but 0 must + * mean a CPU. Only allow level 0. + */ + if (power_level != MPIDR_AFFLVL0) { + return PSCI_E_INVALID_PARAMS; + } + + /* + * From psci view the CPU 0 is always ON, + * CPU 1 can be SUSPEND or RUNNING. + * Therefore do not manage POWER OFF state and always return HW_ON. + */ + + return (int)HW_ON; +} + +/******************************************************************************* + * Export the platform handlers. The ARM Standard platform layer will take care + * of registering the handlers with PSCI. + ******************************************************************************/ +static const plat_psci_ops_t stm32_psci_ops = { + .cpu_standby = stm32_cpu_standby, + .pwr_domain_on = stm32_pwr_domain_on, + .pwr_domain_off = stm32_pwr_domain_off, + .pwr_domain_suspend = stm32_pwr_domain_suspend, + .pwr_domain_on_finish = stm32_pwr_domain_on_finish, + .pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi, + .system_off = stm32_system_off, + .system_reset = stm32_system_reset, + .validate_power_state = stm32_validate_power_state, + .validate_ns_entrypoint = stm32_validate_ns_entrypoint, + .get_node_hw_state = stm32_node_hw_state +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + stm32_sec_entrypoint = sec_entrypoint; + *psci_ops = &stm32_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c new file mode 100644 index 0000000..a9b9f4c --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c @@ -0,0 +1,740 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Internal layout of the 32bit OTP word board_id */ +#define BOARD_ID_BOARD_NB_MASK GENMASK(31, 16) +#define BOARD_ID_BOARD_NB_SHIFT 16 +#define BOARD_ID_VARCPN_MASK GENMASK(15, 12) +#define BOARD_ID_VARCPN_SHIFT 12 +#define BOARD_ID_REVISION_MASK GENMASK(11, 8) +#define BOARD_ID_REVISION_SHIFT 8 +#define BOARD_ID_VARFG_MASK GENMASK(7, 4) +#define BOARD_ID_VARFG_SHIFT 4 +#define BOARD_ID_BOM_MASK GENMASK(3, 0) + +#define BOARD_ID2NB(_id) (((_id) & BOARD_ID_BOARD_NB_MASK) >> \ + BOARD_ID_BOARD_NB_SHIFT) +#define BOARD_ID2VARCPN(_id) (((_id) & BOARD_ID_VARCPN_MASK) >> \ + BOARD_ID_VARCPN_SHIFT) +#define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \ + BOARD_ID_REVISION_SHIFT) +#define BOARD_ID2VARFG(_id) (((_id) & BOARD_ID_VARFG_MASK) >> \ + BOARD_ID_VARFG_SHIFT) +#define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK) + +#if STM32MP13 +#define TAMP_BOOT_MODE_BACKUP_REG_ID U(30) +#endif +#if STM32MP15 +#define TAMP_BOOT_MODE_BACKUP_REG_ID U(20) +#endif +#define TAMP_BOOT_MODE_ITF_MASK U(0x0000FF00) +#define TAMP_BOOT_MODE_ITF_SHIFT 8 + +#define TAMP_BOOT_COUNTER_REG_ID U(21) + +#if defined(IMAGE_BL2) +#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ + STM32MP_SYSRAM_SIZE, \ + MT_MEMORY | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) +#elif defined(IMAGE_BL32) +#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SEC_SYSRAM_BASE, \ + STM32MP_SEC_SYSRAM_SIZE, \ + MT_MEMORY | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) + +/* Non-secure SYSRAM is used a uncached memory for SCMI message transfer */ +#define MAP_NS_SYSRAM MAP_REGION_FLAT(STM32MP_NS_SYSRAM_BASE, \ + STM32MP_NS_SYSRAM_SIZE, \ + MT_DEVICE | \ + MT_RW | \ + MT_NS | \ + MT_EXECUTE_NEVER) +#endif + +#if STM32MP13 +#define MAP_SRAM_ALL MAP_REGION_FLAT(SRAMS_BASE, \ + SRAMS_SIZE_2MB_ALIGNED, \ + MT_MEMORY | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) +#endif + +#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \ + STM32MP1_DEVICE1_SIZE, \ + MT_DEVICE | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) + +#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \ + STM32MP1_DEVICE2_SIZE, \ + MT_DEVICE | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) + +#if defined(IMAGE_BL2) +static const mmap_region_t stm32mp1_mmap[] = { + MAP_SEC_SYSRAM, +#if STM32MP13 + MAP_SRAM_ALL, +#endif + MAP_DEVICE1, +#if STM32MP_RAW_NAND + MAP_DEVICE2, +#endif + {0} +}; +#endif +#if defined(IMAGE_BL32) +static const mmap_region_t stm32mp1_mmap[] = { + MAP_SEC_SYSRAM, + MAP_NS_SYSRAM, + MAP_DEVICE1, + MAP_DEVICE2, + {0} +}; +#endif + +void configure_mmu(void) +{ + mmap_add(stm32mp1_mmap); + init_xlat_tables(); + + enable_mmu_svc_mon(0); +} + +uintptr_t stm32_get_gpio_bank_base(unsigned int bank) +{ +#if STM32MP13 + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I); +#endif +#if STM32MP15 + if (bank == GPIO_BANK_Z) { + return GPIOZ_BASE; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); +#endif + + return GPIOA_BASE + (bank * GPIO_BANK_OFFSET); +} + +uint32_t stm32_get_gpio_bank_offset(unsigned int bank) +{ +#if STM32MP13 + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I); +#endif +#if STM32MP15 + if (bank == GPIO_BANK_Z) { + return 0; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); +#endif + + return bank * GPIO_BANK_OFFSET; +} + +bool stm32_gpio_is_secure_at_reset(unsigned int bank) +{ +#if STM32MP13 + return true; +#endif +#if STM32MP15 + if (bank == GPIO_BANK_Z) { + return true; + } + + return false; +#endif +} + +unsigned long stm32_get_gpio_bank_clock(unsigned int bank) +{ +#if STM32MP13 + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I); +#endif +#if STM32MP15 + if (bank == GPIO_BANK_Z) { + return GPIOZ; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); +#endif + + return GPIOA + (bank - GPIO_BANK_A); +} + +int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank) +{ + switch (bank) { + case GPIO_BANK_A: + case GPIO_BANK_B: + case GPIO_BANK_C: + case GPIO_BANK_D: + case GPIO_BANK_E: + case GPIO_BANK_F: + case GPIO_BANK_G: + case GPIO_BANK_H: + case GPIO_BANK_I: +#if STM32MP15 + case GPIO_BANK_J: + case GPIO_BANK_K: +#endif + return fdt_path_offset(fdt, "/soc/pin-controller"); +#if STM32MP15 + case GPIO_BANK_Z: + return fdt_path_offset(fdt, "/soc/pin-controller-z"); +#endif + default: + panic(); + } +} + +#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2) +/* + * UART Management + */ +static const uintptr_t stm32mp1_uart_addresses[8] = { + USART1_BASE, + USART2_BASE, + USART3_BASE, + UART4_BASE, + UART5_BASE, + USART6_BASE, + UART7_BASE, + UART8_BASE, +}; + +uintptr_t get_uart_address(uint32_t instance_nb) +{ + if ((instance_nb == 0U) || + (instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))) { + return 0U; + } + + return stm32mp1_uart_addresses[instance_nb - 1U]; +} +#endif + +#if STM32MP_USB_PROGRAMMER +struct gpio_bank_pin_list { + uint32_t bank; + uint32_t pin; +}; + +static const struct gpio_bank_pin_list gpio_list[] = { + { /* USART2_RX: GPIOA3 */ + .bank = 0U, + .pin = 3U, + }, + { /* USART3_RX: GPIOB12 */ + .bank = 1U, + .pin = 12U, + }, + { /* UART4_RX: GPIOB2 */ + .bank = 1U, + .pin = 2U, + }, + { /* UART5_RX: GPIOB4 */ + .bank = 1U, + .pin = 5U, + }, + { /* USART6_RX: GPIOC7 */ + .bank = 2U, + .pin = 7U, + }, + { /* UART7_RX: GPIOF6 */ + .bank = 5U, + .pin = 6U, + }, + { /* UART8_RX: GPIOE0 */ + .bank = 4U, + .pin = 0U, + }, +}; + +void stm32mp1_deconfigure_uart_pins(void) +{ + size_t i; + + for (i = 0U; i < ARRAY_SIZE(gpio_list); i++) { + set_gpio_reset_cfg(gpio_list[i].bank, gpio_list[i].pin); + } +} +#endif + +uint32_t stm32mp_get_chip_version(void) +{ +#if STM32MP13 + return stm32mp1_syscfg_get_chip_version(); +#endif +#if STM32MP15 + uint32_t version = 0U; + + if (stm32mp1_dbgmcu_get_chip_version(&version) < 0) { + INFO("Cannot get CPU version, debug disabled\n"); + return 0U; + } + + return version; +#endif +} + +uint32_t stm32mp_get_chip_dev_id(void) +{ +#if STM32MP13 + return stm32mp1_syscfg_get_chip_dev_id(); +#endif +#if STM32MP15 + uint32_t dev_id; + + if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) { + INFO("Use default chip ID, debug disabled\n"); + dev_id = STM32MP1_CHIP_ID; + } + + return dev_id; +#endif +} + +static uint32_t get_part_number(void) +{ + static uint32_t part_number; + + if (part_number != 0U) { + return part_number; + } + + if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) { + panic(); + } + + part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >> + PART_NUMBER_OTP_PART_SHIFT; + + part_number |= stm32mp_get_chip_dev_id() << 16; + + return part_number; +} + +#if STM32MP15 +static uint32_t get_cpu_package(void) +{ + uint32_t package; + + if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) { + panic(); + } + + package = (package & PACKAGE_OTP_PKG_MASK) >> + PACKAGE_OTP_PKG_SHIFT; + + return package; +} +#endif + +void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]) +{ + char *cpu_s, *cpu_r, *pkg; + + /* MPUs Part Numbers */ + switch (get_part_number()) { +#if STM32MP13 + case STM32MP135F_PART_NB: + cpu_s = "135F"; + break; + case STM32MP135D_PART_NB: + cpu_s = "135D"; + break; + case STM32MP135C_PART_NB: + cpu_s = "135C"; + break; + case STM32MP135A_PART_NB: + cpu_s = "135A"; + break; + case STM32MP133F_PART_NB: + cpu_s = "133F"; + break; + case STM32MP133D_PART_NB: + cpu_s = "133D"; + break; + case STM32MP133C_PART_NB: + cpu_s = "133C"; + break; + case STM32MP133A_PART_NB: + cpu_s = "133A"; + break; + case STM32MP131F_PART_NB: + cpu_s = "131F"; + break; + case STM32MP131D_PART_NB: + cpu_s = "131D"; + break; + case STM32MP131C_PART_NB: + cpu_s = "131C"; + break; + case STM32MP131A_PART_NB: + cpu_s = "131A"; + break; +#endif +#if STM32MP15 + case STM32MP157C_PART_NB: + cpu_s = "157C"; + break; + case STM32MP157A_PART_NB: + cpu_s = "157A"; + break; + case STM32MP153C_PART_NB: + cpu_s = "153C"; + break; + case STM32MP153A_PART_NB: + cpu_s = "153A"; + break; + case STM32MP151C_PART_NB: + cpu_s = "151C"; + break; + case STM32MP151A_PART_NB: + cpu_s = "151A"; + break; + case STM32MP157F_PART_NB: + cpu_s = "157F"; + break; + case STM32MP157D_PART_NB: + cpu_s = "157D"; + break; + case STM32MP153F_PART_NB: + cpu_s = "153F"; + break; + case STM32MP153D_PART_NB: + cpu_s = "153D"; + break; + case STM32MP151F_PART_NB: + cpu_s = "151F"; + break; + case STM32MP151D_PART_NB: + cpu_s = "151D"; + break; +#endif + default: + cpu_s = "????"; + break; + } + + /* Package */ +#if STM32MP13 + /* On STM32MP13, package is not present in OTP */ + pkg = ""; +#endif +#if STM32MP15 + switch (get_cpu_package()) { + case PKG_AA_LFBGA448: + pkg = "AA"; + break; + case PKG_AB_LFBGA354: + pkg = "AB"; + break; + case PKG_AC_TFBGA361: + pkg = "AC"; + break; + case PKG_AD_TFBGA257: + pkg = "AD"; + break; + default: + pkg = "??"; + break; + } +#endif + + /* REVISION */ + switch (stm32mp_get_chip_version()) { + case STM32MP1_REV_B: + cpu_r = "B"; + break; + case STM32MP1_REV_Z: + cpu_r = "Z"; + break; + default: + cpu_r = "?"; + break; + } + + snprintf(name, STM32_SOC_NAME_SIZE, + "STM32MP%s%s Rev.%s", cpu_s, pkg, cpu_r); +} + +void stm32mp_print_cpuinfo(void) +{ + char name[STM32_SOC_NAME_SIZE]; + + stm32mp_get_soc_name(name); + NOTICE("CPU: %s\n", name); +} + +void stm32mp_print_boardinfo(void) +{ + uint32_t board_id = 0; + + if (stm32_get_otp_value(BOARD_ID_OTP, &board_id) != 0) { + return; + } + + if (board_id != 0U) { + char rev[2]; + + rev[0] = BOARD_ID2REV(board_id) - 1 + 'A'; + rev[1] = '\0'; + NOTICE("Board: MB%04x Var%u.%u Rev.%s-%02u\n", + BOARD_ID2NB(board_id), + BOARD_ID2VARCPN(board_id), + BOARD_ID2VARFG(board_id), + rev, + BOARD_ID2BOM(board_id)); + } +} + +/* Return true when SoC provides a single Cortex-A7 core, and false otherwise */ +bool stm32mp_is_single_core(void) +{ +#if STM32MP13 + return true; +#endif +#if STM32MP15 + bool single_core = false; + + switch (get_part_number()) { + case STM32MP151A_PART_NB: + case STM32MP151C_PART_NB: + case STM32MP151D_PART_NB: + case STM32MP151F_PART_NB: + single_core = true; + break; + default: + break; + } + + return single_core; +#endif +} + +/* Return true when device is in closed state */ +bool stm32mp_is_closed_device(void) +{ + uint32_t value; + + if (stm32_get_otp_value(CFG0_OTP, &value) != 0) { + return true; + } + +#if STM32MP13 + value = (value & CFG0_OTP_MODE_MASK) >> CFG0_OTP_MODE_SHIFT; + + switch (value) { + case CFG0_OPEN_DEVICE: + return false; + case CFG0_CLOSED_DEVICE: + case CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN: + case CFG0_CLOSED_DEVICE_NO_JTAG: + return true; + default: + panic(); + } +#endif +#if STM32MP15 + return (value & CFG0_CLOSED_DEVICE) == CFG0_CLOSED_DEVICE; +#endif +} + +/* Return true when device supports secure boot */ +bool stm32mp_is_auth_supported(void) +{ + bool supported = false; + + switch (get_part_number()) { +#if STM32MP13 + case STM32MP131C_PART_NB: + case STM32MP131F_PART_NB: + case STM32MP133C_PART_NB: + case STM32MP133F_PART_NB: + case STM32MP135C_PART_NB: + case STM32MP135F_PART_NB: +#endif +#if STM32MP15 + case STM32MP151C_PART_NB: + case STM32MP151F_PART_NB: + case STM32MP153C_PART_NB: + case STM32MP153F_PART_NB: + case STM32MP157C_PART_NB: + case STM32MP157F_PART_NB: +#endif + supported = true; + break; + default: + break; + } + + return supported; +} + +uint32_t stm32_iwdg_get_instance(uintptr_t base) +{ + switch (base) { + case IWDG1_BASE: + return IWDG1_INST; + case IWDG2_BASE: + return IWDG2_INST; + default: + panic(); + } +} + +uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst) +{ + uint32_t iwdg_cfg = 0U; + uint32_t otp_value; + + if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { + panic(); + } + + if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_HW_POS)) != 0U) { + iwdg_cfg |= IWDG_HW_ENABLED; + } + + if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS)) != 0U) { + iwdg_cfg |= IWDG_DISABLE_ON_STOP; + } + + if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS)) != 0U) { + iwdg_cfg |= IWDG_DISABLE_ON_STANDBY; + } + + return iwdg_cfg; +} + +#if defined(IMAGE_BL2) +uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags) +{ + uint32_t otp_value; + uint32_t otp; + uint32_t result; + + if (stm32_get_otp_index(HW2_OTP, &otp, NULL) != 0) { + panic(); + } + + if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { + panic(); + } + + if ((flags & IWDG_DISABLE_ON_STOP) != 0) { + otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS); + } + + if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) { + otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS); + } + + result = bsec_write_otp(otp_value, otp); + if (result != BSEC_OK) { + return result; + } + + /* Sticky lock OTP_IWDG (read and write) */ + if ((bsec_set_sr_lock(otp) != BSEC_OK) || + (bsec_set_sw_lock(otp) != BSEC_OK)) { + return BSEC_LOCK_FAIL; + } + + return BSEC_OK; +} +#endif + +#if STM32MP_USE_STM32IMAGE +/* Get the non-secure DDR size */ +uint32_t stm32mp_get_ddr_ns_size(void) +{ + static uint32_t ddr_ns_size; + uint32_t ddr_size; + + if (ddr_ns_size != 0U) { + return ddr_ns_size; + } + + ddr_size = dt_get_ddr_size(); + if ((ddr_size <= (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE)) || + (ddr_size > STM32MP_DDR_MAX_SIZE)) { + panic(); + } + + ddr_ns_size = ddr_size - (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE); + + return ddr_ns_size; +} +#endif /* STM32MP_USE_STM32IMAGE */ + +void stm32_save_boot_interface(uint32_t interface, uint32_t instance) +{ + uintptr_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID); + + clk_enable(RTCAPB); + + mmio_clrsetbits_32(bkpr_itf_idx, + TAMP_BOOT_MODE_ITF_MASK, + ((interface << 4) | (instance & 0xFU)) << + TAMP_BOOT_MODE_ITF_SHIFT); + + clk_disable(RTCAPB); +} + +void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance) +{ + static uint32_t itf; + + if (itf == 0U) { + uintptr_t bkpr = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID); + + clk_enable(RTCAPB); + + itf = (mmio_read_32(bkpr) & TAMP_BOOT_MODE_ITF_MASK) >> + TAMP_BOOT_MODE_ITF_SHIFT; + + clk_disable(RTCAPB); + } + + *interface = itf >> 4; + *instance = itf & 0xFU; +} + +#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT +void stm32mp1_fwu_set_boot_idx(void) +{ + clk_enable(RTCAPB); + mmio_write_32(tamp_bkpr(TAMP_BOOT_COUNTER_REG_ID), + plat_fwu_get_boot_idx()); + clk_disable(RTCAPB); +} +#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c new file mode 100644 index 0000000..98585dc --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define TIMEOUT_US_1MS 1000U + +#define SCMI_CLOCK_NAME_SIZE 16U +#define SCMI_RSTD_NAME_SIZE 16U + +/* + * struct stm32_scmi_clk - Data for the exposed clock + * @clock_id: Clock identifier in RCC clock driver + * @name: Clock string ID exposed to agent + * @enabled: State of the SCMI clock + */ +struct stm32_scmi_clk { + unsigned long clock_id; + const char *name; + bool enabled; +}; + +/* + * struct stm32_scmi_rstd - Data for the exposed reset controller + * @reset_id: Reset identifier in RCC reset driver + * @name: Reset string ID exposed to agent + */ +struct stm32_scmi_rstd { + unsigned long reset_id; + const char *name; +}; + +/* Locate all non-secure SMT message buffers in last page of SYSRAM */ +#define SMT_BUFFER_BASE STM32MP_SCMI_NS_SHM_BASE +#define SMT_BUFFER0_BASE SMT_BUFFER_BASE +#define SMT_BUFFER1_BASE (SMT_BUFFER_BASE + 0x200) + +CASSERT((STM32MP_SCMI_NS_SHM_BASE + STM32MP_SCMI_NS_SHM_SIZE) >= + (SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE), + assert_scmi_non_secure_shm_fits_scmi_overall_buffer_size); + +static struct scmi_msg_channel scmi_channel[] = { + [0] = { + .shm_addr = SMT_BUFFER0_BASE, + .shm_size = SMT_BUF_SLOT_SIZE, + }, + [1] = { + .shm_addr = SMT_BUFFER1_BASE, + .shm_size = SMT_BUF_SLOT_SIZE, + }, +}; + +struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id) +{ + assert(agent_id < ARRAY_SIZE(scmi_channel)); + + return &scmi_channel[agent_id]; +} + +#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \ + [_scmi_id] = { \ + .clock_id = _id, \ + .name = _name, \ + .enabled = _init_enabled, \ + } + +static struct stm32_scmi_clk stm32_scmi0_clock[] = { + CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true), + CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true), + CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true), + CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true), + CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true), + CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true), + CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true), + CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true), + CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true), + CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true), + CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false), + CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false), + CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false), + CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false), + CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false), + CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false), + CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true), + CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true), + CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true), + CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false), + CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false), +}; + +static struct stm32_scmi_clk stm32_scmi1_clock[] = { + CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true), + CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true), + CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false), +}; + +#define RESET_CELL(_scmi_id, _id, _name) \ + [_scmi_id] = { \ + .reset_id = _id, \ + .name = _name, \ + } + +static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = { + RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"), + RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"), + RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"), + RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"), + RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"), + RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"), + RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"), + RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"), + RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"), + RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"), + RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"), +}; + +struct scmi_agent_resources { + struct stm32_scmi_clk *clock; + size_t clock_count; + struct stm32_scmi_rstd *rstd; + size_t rstd_count; +}; + +static const struct scmi_agent_resources agent_resources[] = { + [0] = { + .clock = stm32_scmi0_clock, + .clock_count = ARRAY_SIZE(stm32_scmi0_clock), + .rstd = stm32_scmi0_reset_domain, + .rstd_count = ARRAY_SIZE(stm32_scmi0_reset_domain), + }, + [1] = { + .clock = stm32_scmi1_clock, + .clock_count = ARRAY_SIZE(stm32_scmi1_clock), + }, +}; + +static const struct scmi_agent_resources *find_resource(unsigned int agent_id) +{ + assert(agent_id < ARRAY_SIZE(agent_resources)); + + return &agent_resources[agent_id]; +} + +#if ENABLE_ASSERTIONS +static size_t plat_scmi_protocol_count_paranoid(void) +{ + unsigned int n = 0U; + unsigned int count = 0U; + + for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) { + if (agent_resources[n].clock_count) { + count++; + break; + } + } + + for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) { + if (agent_resources[n].rstd_count) { + count++; + break; + } + } + + return count; +} +#endif + +static const char vendor[] = "ST"; +static const char sub_vendor[] = ""; + +const char *plat_scmi_vendor_name(void) +{ + return vendor; +} + +const char *plat_scmi_sub_vendor_name(void) +{ + return sub_vendor; +} + +/* Currently supporting Clocks and Reset Domains */ +static const uint8_t plat_protocol_list[] = { + SCMI_PROTOCOL_ID_CLOCK, + SCMI_PROTOCOL_ID_RESET_DOMAIN, + 0U /* Null termination */ +}; + +size_t plat_scmi_protocol_count(void) +{ + const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U; + + assert(count == plat_scmi_protocol_count_paranoid()); + + return count; +} + +const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused) +{ + assert(plat_scmi_protocol_count_paranoid() == + (ARRAY_SIZE(plat_protocol_list) - 1U)); + + return plat_protocol_list; +} + +/* + * Platform SCMI clocks + */ +static struct stm32_scmi_clk *find_clock(unsigned int agent_id, + unsigned int scmi_id) +{ + const struct scmi_agent_resources *resource = find_resource(agent_id); + size_t n = 0U; + + if (resource != NULL) { + for (n = 0U; n < resource->clock_count; n++) { + if (n == scmi_id) { + return &resource->clock[n]; + } + } + } + + return NULL; +} + +size_t plat_scmi_clock_count(unsigned int agent_id) +{ + const struct scmi_agent_resources *resource = find_resource(agent_id); + + if (resource == NULL) { + return 0U; + } + + return resource->clock_count; +} + +const char *plat_scmi_clock_get_name(unsigned int agent_id, + unsigned int scmi_id) +{ + struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); + + if ((clock == NULL) || + !stm32mp_nsec_can_access_clock(clock->clock_id)) { + return NULL; + } + + return clock->name; +} + +int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, + unsigned long *array, size_t *nb_elts) +{ + struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); + + if (clock == NULL) { + return SCMI_NOT_FOUND; + } + + if (!stm32mp_nsec_can_access_clock(clock->clock_id)) { + return SCMI_DENIED; + } + + if (array == NULL) { + *nb_elts = 1U; + } else if (*nb_elts == 1U) { + *array = clk_get_rate(clock->clock_id); + } else { + return SCMI_GENERIC_ERROR; + } + + return SCMI_SUCCESS; +} + +unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, + unsigned int scmi_id) +{ + struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); + + if ((clock == NULL) || + !stm32mp_nsec_can_access_clock(clock->clock_id)) { + return 0U; + } + + return clk_get_rate(clock->clock_id); +} + +int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id) +{ + struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); + + if ((clock == NULL) || + !stm32mp_nsec_can_access_clock(clock->clock_id)) { + return 0U; + } + + return (int32_t)clock->enabled; +} + +int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id, + bool enable_not_disable) +{ + struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id); + + if (clock == NULL) { + return SCMI_NOT_FOUND; + } + + if (!stm32mp_nsec_can_access_clock(clock->clock_id)) { + return SCMI_DENIED; + } + + if (enable_not_disable) { + if (!clock->enabled) { + VERBOSE("SCMI clock %u enable\n", scmi_id); + clk_enable(clock->clock_id); + clock->enabled = true; + } + } else { + if (clock->enabled) { + VERBOSE("SCMI clock %u disable\n", scmi_id); + clk_disable(clock->clock_id); + clock->enabled = false; + } + } + + return SCMI_SUCCESS; +} + +/* + * Platform SCMI reset domains + */ +static struct stm32_scmi_rstd *find_rstd(unsigned int agent_id, + unsigned int scmi_id) +{ + const struct scmi_agent_resources *resource = find_resource(agent_id); + size_t n; + + if (resource != NULL) { + for (n = 0U; n < resource->rstd_count; n++) { + if (n == scmi_id) { + return &resource->rstd[n]; + } + } + } + + return NULL; +} + +const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id) +{ + const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id); + + if (rstd == NULL) { + return NULL; + } + + return rstd->name; +} + +size_t plat_scmi_rstd_count(unsigned int agent_id) +{ + const struct scmi_agent_resources *resource = find_resource(agent_id); + + if (resource == NULL) { + return 0U; + } + + return resource->rstd_count; +} + +int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id, + uint32_t state) +{ + const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id); + + if (rstd == NULL) { + return SCMI_NOT_FOUND; + } + + if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) { + return SCMI_DENIED; + } + + /* Supports only reset with context loss */ + if (state != 0U) { + return SCMI_NOT_SUPPORTED; + } + + VERBOSE("SCMI reset %lu cycle\n", rstd->reset_id); + + if (stm32mp_reset_assert(rstd->reset_id, TIMEOUT_US_1MS)) { + return SCMI_HARDWARE_ERROR; + } + + if (stm32mp_reset_deassert(rstd->reset_id, TIMEOUT_US_1MS)) { + return SCMI_HARDWARE_ERROR; + } + + return SCMI_SUCCESS; +} + +int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id, + bool assert_not_deassert) +{ + const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id); + + if (rstd == NULL) { + return SCMI_NOT_FOUND; + } + + if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) { + return SCMI_DENIED; + } + + if (assert_not_deassert) { + VERBOSE("SCMI reset %lu set\n", rstd->reset_id); + stm32mp_reset_set(rstd->reset_id); + } else { + VERBOSE("SCMI reset %lu release\n", rstd->reset_id); + stm32mp_reset_release(rstd->reset_id); + } + + return SCMI_SUCCESS; +} + +/* + * Initialize platform SCMI resources + */ +void stm32mp1_init_scmi_server(void) +{ + size_t i; + + for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) { + scmi_smt_init_agent_channel(&scmi_channel[i]); + } + + for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) { + const struct scmi_agent_resources *res = &agent_resources[i]; + size_t j; + + for (j = 0U; j < res->clock_count; j++) { + struct stm32_scmi_clk *clk = &res->clock[j]; + + if ((clk->name == NULL) || + (strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) { + ERROR("Invalid SCMI clock name\n"); + panic(); + } + + /* Sync SCMI clocks with their targeted initial state */ + if (clk->enabled && + stm32mp_nsec_can_access_clock(clk->clock_id)) { + clk_enable(clk->clock_id); + } + } + + for (j = 0U; j < res->rstd_count; j++) { + struct stm32_scmi_rstd *rstd = &res->rstd[j]; + + if ((rstd->name == NULL) || + (strlen(rstd->name) >= SCMI_RSTD_NAME_SIZE)) { + ERROR("Invalid SCMI reset domain name\n"); + panic(); + } + } + } +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c new file mode 100644 index 0000000..c84bffc --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c @@ -0,0 +1,136 @@ +/* + * 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 + +static unsigned int region_nb; + +static void init_tzc400_begin(unsigned int region0_attr) +{ + tzc400_init(STM32MP1_TZC_BASE); + tzc400_disable_filters(); + + /* Region 0 set to cover all DRAM at 0xC000_0000 */ + tzc400_configure_region0(region0_attr, 0); + + region_nb = 1U; +} + +static void init_tzc400_end(unsigned int action) +{ + tzc400_set_action(action); + tzc400_enable_filters(); +} + +static void tzc400_add_region(unsigned long long region_base, + unsigned long long region_top, bool sec) +{ + unsigned int sec_attr; + unsigned int nsaid_permissions; + + if (sec) { + sec_attr = TZC_REGION_S_RDWR; + nsaid_permissions = 0; + } else { + sec_attr = TZC_REGION_S_NONE; + nsaid_permissions = TZC_REGION_NSEC_ALL_ACCESS_RDWR; + } + + tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, region_nb, region_base, + region_top, sec_attr, nsaid_permissions); + + region_nb++; +} + +/******************************************************************************* + * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access + * and allow Non-Secure masters full access. + ******************************************************************************/ +static void init_tzc400(void) +{ + unsigned long long region_base, region_top; + unsigned long long ddr_base = STM32MP_DDR_BASE; + unsigned long long ddr_ns_size = + (unsigned long long)stm32mp_get_ddr_ns_size(); + unsigned long long ddr_ns_top = ddr_base + (ddr_ns_size - 1U); + unsigned long long ddr_top __unused; + + init_tzc400_begin(TZC_REGION_S_NONE); + + /* + * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the + * same configuration to all filters in the TZC. + */ + region_base = ddr_base; + region_top = ddr_ns_top; + tzc400_add_region(region_base, region_top, false); + +#ifdef AARCH32_SP_OPTEE + /* Region 2 set to cover all secure DRAM. */ + region_base = region_top + 1U; + region_top += STM32MP_DDR_S_SIZE; + tzc400_add_region(region_base, region_top, true); + + ddr_top = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U; + if (region_top < ddr_top) { + /* Region 3 set to cover non-secure memory DRAM after BL32. */ + region_base = region_top + 1U; + region_top = ddr_top; + tzc400_add_region(region_base, region_top, false); + } +#endif + + /* + * Raise an interrupt (secure FIQ) if a NS device tries to access + * secure memory + */ + init_tzc400_end(TZC_ACTION_INT); +} + +/******************************************************************************* + * Initialize the TrustZone Controller. + * Early initialization create only one region with full access to secure. + * This setting is used before and during DDR initialization. + ******************************************************************************/ +static void early_init_tzc400(void) +{ + clk_enable(TZC1); + clk_enable(TZC2); + + /* Region 0 set to cover all DRAM secure at 0xC000_0000 */ + init_tzc400_begin(TZC_REGION_S_RDWR); + + /* Raise an exception if a NS device tries to access secure memory */ + init_tzc400_end(TZC_ACTION_ERR); +} + +/******************************************************************************* + * Initialize the secure environment. At this moment only the TrustZone + * Controller is initialized. + ******************************************************************************/ +void stm32mp1_arch_security_setup(void) +{ + early_init_tzc400(); +} + +/******************************************************************************* + * Initialize the secure environment. At this moment only the TrustZone + * Controller is initialized. + ******************************************************************************/ +void stm32mp1_security_setup(void) +{ + init_tzc400(); +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c new file mode 100644 index 0000000..a0ca697 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include + +/* + * Once one starts to get the resource registering state, one cannot register + * new resources. This ensures resource state cannot change. + */ +static bool registering_locked; + +/* + * Shared peripherals and resources registration + * + * Each resource assignation is stored in a table. The state defaults + * to PERIPH_UNREGISTERED if the resource is not explicitly assigned. + * + * Resource driver that as not embedded (a.k.a their related CFG_xxx build + * directive is disabled) are assigned to the non-secure world. + * + * Each pin of the GPIOZ bank can be secure or non-secure. + * + * It is the platform responsibility the ensure resource assignation + * matches the access permission firewalls configuration. + */ +enum shres_state { + SHRES_UNREGISTERED = 0, + SHRES_SECURE, + SHRES_NON_SECURE, +}; + +/* Force uint8_t array for array of enum shres_state for size considerations */ +static uint8_t shres_state[STM32MP1_SHRES_COUNT]; + +static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] __unused = { + [STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0", + [STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1", + [STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2", + [STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3", + [STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4", + [STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5", + [STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6", + [STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7", + [STM32MP1_SHRES_IWDG1] = "IWDG1", + [STM32MP1_SHRES_USART1] = "USART1", + [STM32MP1_SHRES_SPI6] = "SPI6", + [STM32MP1_SHRES_I2C4] = "I2C4", + [STM32MP1_SHRES_RNG1] = "RNG1", + [STM32MP1_SHRES_HASH1] = "HASH1", + [STM32MP1_SHRES_CRYP1] = "CRYP1", + [STM32MP1_SHRES_I2C6] = "I2C6", + [STM32MP1_SHRES_RTC] = "RTC", + [STM32MP1_SHRES_MCU] = "MCU", + [STM32MP1_SHRES_MDMA] = "MDMA", + [STM32MP1_SHRES_PLL3] = "PLL3", +}; + +static const char __unused *shres2str_id(enum stm32mp_shres id) +{ + assert(id < ARRAY_SIZE(shres2str_id_tbl)); + + return shres2str_id_tbl[id]; +} + +static const char __unused *shres2str_state_tbl[] = { + [SHRES_UNREGISTERED] = "unregistered", + [SHRES_NON_SECURE] = "non-secure", + [SHRES_SECURE] = "secure", +}; + +static const char __unused *shres2str_state(unsigned int state) +{ + assert(state < ARRAY_SIZE(shres2str_state_tbl)); + + return shres2str_state_tbl[state]; +} + +/* Get resource state: these accesses lock the registering support */ +static void lock_registering(void) +{ + registering_locked = true; +} + +static bool periph_is_non_secure(enum stm32mp_shres id) +{ + lock_registering(); + + return (shres_state[id] == SHRES_NON_SECURE) || + (shres_state[id] == SHRES_UNREGISTERED); +} + +static bool periph_is_secure(enum stm32mp_shres id) +{ + return !periph_is_non_secure(id); +} + +/* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */ +static int8_t gpioz_nbpin = -1; + +static unsigned int get_gpio_nbpin(unsigned int bank) +{ + if (bank != GPIO_BANK_Z) { + int count = fdt_get_gpio_bank_pin_count(bank); + + assert((count >= 0) && ((unsigned int)count <= (GPIO_PIN_MAX + 1))); + + return (unsigned int)count; + } + + if (gpioz_nbpin < 0) { + int count = fdt_get_gpio_bank_pin_count(GPIO_BANK_Z); + + assert((count == 0) || (count == STM32MP_GPIOZ_PIN_MAX_COUNT)); + + gpioz_nbpin = count; + } + + return (unsigned int)gpioz_nbpin; +} + +static unsigned int get_gpioz_nbpin(void) +{ + return get_gpio_nbpin(GPIO_BANK_Z); +} + +static void register_periph(enum stm32mp_shres id, unsigned int state) +{ + assert((id < STM32MP1_SHRES_COUNT) && + ((state == SHRES_SECURE) || (state == SHRES_NON_SECURE))); + + if (registering_locked) { + if (shres_state[id] == state) { + return; + } + panic(); + } + + if ((shres_state[id] != SHRES_UNREGISTERED) && + (shres_state[id] != state)) { + VERBOSE("Cannot change %s from %s to %s\n", + shres2str_id(id), + shres2str_state(shres_state[id]), + shres2str_state(state)); + panic(); + } + + if (shres_state[id] == SHRES_UNREGISTERED) { + VERBOSE("Register %s as %s\n", + shres2str_id(id), shres2str_state(state)); + } + + if ((id >= STM32MP1_SHRES_GPIOZ(0)) && + (id <= STM32MP1_SHRES_GPIOZ(7)) && + ((unsigned int)(id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) { + ERROR("Invalid GPIO pin %d, %u pin(s) available\n", + (int)(id - STM32MP1_SHRES_GPIOZ(0)), get_gpioz_nbpin()); + panic(); + } + + shres_state[id] = (uint8_t)state; + + /* Explore clock tree to lock dependencies */ + if (state == SHRES_SECURE) { + enum stm32mp_shres clock_res_id; + + switch (id) { + case STM32MP1_SHRES_GPIOZ(0): + case STM32MP1_SHRES_GPIOZ(1): + case STM32MP1_SHRES_GPIOZ(2): + case STM32MP1_SHRES_GPIOZ(3): + case STM32MP1_SHRES_GPIOZ(4): + case STM32MP1_SHRES_GPIOZ(5): + case STM32MP1_SHRES_GPIOZ(6): + case STM32MP1_SHRES_GPIOZ(7): + clock_res_id = GPIOZ; + break; + case STM32MP1_SHRES_IWDG1: + clock_res_id = IWDG1; + break; + case STM32MP1_SHRES_USART1: + clock_res_id = USART1_K; + break; + case STM32MP1_SHRES_SPI6: + clock_res_id = SPI6_K; + break; + case STM32MP1_SHRES_I2C4: + clock_res_id = I2C4_K; + break; + case STM32MP1_SHRES_RNG1: + clock_res_id = RNG1_K; + break; + case STM32MP1_SHRES_HASH1: + clock_res_id = HASH1; + break; + case STM32MP1_SHRES_CRYP1: + clock_res_id = CRYP1; + break; + case STM32MP1_SHRES_I2C6: + clock_res_id = I2C6_K; + break; + case STM32MP1_SHRES_RTC: + clock_res_id = RTC; + break; + default: + /* No clock resource dependency */ + return; + } + + stm32mp1_register_clock_parents_secure(clock_res_id); + } +} + +/* Register resource by ID */ +void stm32mp_register_secure_periph(enum stm32mp_shres id) +{ + register_periph(id, SHRES_SECURE); +} + +void stm32mp_register_non_secure_periph(enum stm32mp_shres id) +{ + register_periph(id, SHRES_NON_SECURE); +} + +static void register_periph_iomem(uintptr_t base, unsigned int state) +{ + enum stm32mp_shres id; + + switch (base) { + case CRYP1_BASE: + id = STM32MP1_SHRES_CRYP1; + break; + case HASH1_BASE: + id = STM32MP1_SHRES_HASH1; + break; + case I2C4_BASE: + id = STM32MP1_SHRES_I2C4; + break; + case I2C6_BASE: + id = STM32MP1_SHRES_I2C6; + break; + case IWDG1_BASE: + id = STM32MP1_SHRES_IWDG1; + break; + case RNG1_BASE: + id = STM32MP1_SHRES_RNG1; + break; + case RTC_BASE: + id = STM32MP1_SHRES_RTC; + break; + case SPI6_BASE: + id = STM32MP1_SHRES_SPI6; + break; + case USART1_BASE: + id = STM32MP1_SHRES_USART1; + break; + + case GPIOA_BASE: + case GPIOB_BASE: + case GPIOC_BASE: + case GPIOD_BASE: + case GPIOE_BASE: + case GPIOF_BASE: + case GPIOG_BASE: + case GPIOH_BASE: + case GPIOI_BASE: + case GPIOJ_BASE: + case GPIOK_BASE: + case USART2_BASE: + case USART3_BASE: + case UART4_BASE: + case UART5_BASE: + case USART6_BASE: + case UART7_BASE: + case UART8_BASE: + case IWDG2_BASE: + /* Allow drivers to register some non-secure resources */ + VERBOSE("IO for non-secure resource 0x%x\n", + (unsigned int)base); + if (state != SHRES_NON_SECURE) { + panic(); + } + + return; + + default: + panic(); + } + + register_periph(id, state); +} + +void stm32mp_register_secure_periph_iomem(uintptr_t base) +{ + register_periph_iomem(base, SHRES_SECURE); +} + +void stm32mp_register_non_secure_periph_iomem(uintptr_t base) +{ + register_periph_iomem(base, SHRES_NON_SECURE); +} + +void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin) +{ + switch (bank) { + case GPIO_BANK_Z: + register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE); + break; + default: + ERROR("GPIO bank %u cannot be secured\n", bank); + panic(); + } +} + +void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin) +{ + switch (bank) { + case GPIO_BANK_Z: + register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE); + break; + default: + break; + } +} + +static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank) +{ + unsigned int non_secure = 0U; + unsigned int i; + + lock_registering(); + + if (bank != GPIO_BANK_Z) { + return true; + } + + for (i = 0U; i < get_gpioz_nbpin(); i++) { + if (periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i))) { + non_secure++; + } + } + + return non_secure == get_gpioz_nbpin(); +} + +static bool stm32mp_gpio_bank_is_secure(unsigned int bank) +{ + unsigned int secure = 0U; + unsigned int i; + + lock_registering(); + + if (bank != GPIO_BANK_Z) { + return false; + } + + for (i = 0U; i < get_gpioz_nbpin(); i++) { + if (periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) { + secure++; + } + } + + return secure == get_gpioz_nbpin(); +} + +bool stm32mp_nsec_can_access_clock(unsigned long clock_id) +{ + enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; + + switch (clock_id) { + case CK_CSI: + case CK_HSE: + case CK_HSE_DIV2: + case CK_HSI: + case CK_LSE: + case CK_LSI: + case PLL1_P: + case PLL1_Q: + case PLL1_R: + case PLL2_P: + case PLL2_Q: + case PLL2_R: + case PLL3_P: + case PLL3_Q: + case PLL3_R: + case RTCAPB: + return true; + case GPIOZ: + /* Allow clock access if at least one pin is non-secure */ + return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z); + case CRYP1: + shres_id = STM32MP1_SHRES_CRYP1; + break; + case HASH1: + shres_id = STM32MP1_SHRES_HASH1; + break; + case I2C4_K: + shres_id = STM32MP1_SHRES_I2C4; + break; + case I2C6_K: + shres_id = STM32MP1_SHRES_I2C6; + break; + case IWDG1: + shres_id = STM32MP1_SHRES_IWDG1; + break; + case RNG1_K: + shres_id = STM32MP1_SHRES_RNG1; + break; + case RTC: + shres_id = STM32MP1_SHRES_RTC; + break; + case SPI6_K: + shres_id = STM32MP1_SHRES_SPI6; + break; + case USART1_K: + shres_id = STM32MP1_SHRES_USART1; + break; + default: + return false; + } + + return periph_is_non_secure(shres_id); +} + +bool stm32mp_nsec_can_access_reset(unsigned int reset_id) +{ + enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; + + switch (reset_id) { + case CRYP1_R: + shres_id = STM32MP1_SHRES_CRYP1; + break; + case GPIOZ_R: + /* GPIOZ reset mandates all pins are non-secure */ + return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z); + case HASH1_R: + shres_id = STM32MP1_SHRES_HASH1; + break; + case I2C4_R: + shres_id = STM32MP1_SHRES_I2C4; + break; + case I2C6_R: + shres_id = STM32MP1_SHRES_I2C6; + break; + case MCU_R: + shres_id = STM32MP1_SHRES_MCU; + break; + case MDMA_R: + shres_id = STM32MP1_SHRES_MDMA; + break; + case RNG1_R: + shres_id = STM32MP1_SHRES_RNG1; + break; + case SPI6_R: + shres_id = STM32MP1_SHRES_SPI6; + break; + case USART1_R: + shres_id = STM32MP1_SHRES_USART1; + break; + default: + return false; + } + + return periph_is_non_secure(shres_id); +} + +static bool mckprot_protects_periph(enum stm32mp_shres id) +{ + switch (id) { + case STM32MP1_SHRES_MCU: + case STM32MP1_SHRES_PLL3: + return true; + default: + return false; + } +} + +/* ETZPC configuration at drivers initialization completion */ +static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id) +{ + assert((id < STM32MP1_SHRES_GPIOZ(0)) || + (id > STM32MP1_SHRES_GPIOZ(7))); + + if (periph_is_non_secure(id)) { + return ETZPC_DECPROT_NS_RW; + } + + return ETZPC_DECPROT_S_RW; +} + +static void set_etzpc_secure_configuration(void) +{ + /* Some system peripherals shall be secure */ + etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); + etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); + etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID, + ETZPC_DECPROT_NS_R_S_W); + etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID, + ETZPC_DECPROT_NS_R_S_W); + + /* Configure ETZPC with peripheral registering */ + etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID, + shres2decprot_attr(STM32MP1_SHRES_CRYP1)); + etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID, + shres2decprot_attr(STM32MP1_SHRES_HASH1)); + etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID, + shres2decprot_attr(STM32MP1_SHRES_I2C4)); + etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID, + shres2decprot_attr(STM32MP1_SHRES_I2C6)); + etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID, + shres2decprot_attr(STM32MP1_SHRES_IWDG1)); + etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID, + shres2decprot_attr(STM32MP1_SHRES_RNG1)); + etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID, + shres2decprot_attr(STM32MP1_SHRES_USART1)); + etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID, + shres2decprot_attr(STM32MP1_SHRES_SPI6)); +} + +static void check_rcc_secure_configuration(void) +{ + uint32_t n; + uint32_t error = 0U; + bool mckprot = stm32mp1_rcc_is_mckprot(); + bool secure = stm32mp1_rcc_is_secure(); + + for (n = 0U; n < ARRAY_SIZE(shres_state); n++) { + if (shres_state[n] != SHRES_SECURE) { + continue; + } + + if (!secure || (mckprot_protects_periph(n) && (!mckprot))) { + ERROR("RCC %s MCKPROT %s and %s secure\n", + secure ? "secure" : "non-secure", + mckprot ? "set" : "not set", + shres2str_id(n)); + error++; + } + } + + if (error != 0U) { + panic(); + } +} + +static void set_gpio_secure_configuration(void) +{ + uint32_t pin; + + for (pin = 0U; pin < get_gpioz_nbpin(); pin++) { + bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin)); + + set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state); + } +} + +static void print_shared_resources_state(void) +{ + unsigned int id; + + for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) { + switch (shres_state[id]) { + case SHRES_SECURE: + INFO("stm32mp1 %s is secure\n", shres2str_id(id)); + break; + case SHRES_NON_SECURE: + case SHRES_UNREGISTERED: + VERBOSE("stm32mp %s is non-secure\n", shres2str_id(id)); + break; + default: + VERBOSE("stm32mp %s is invalid\n", shres2str_id(id)); + panic(); + } + } +} + +void stm32mp_lock_periph_registering(void) +{ + registering_locked = true; + + print_shared_resources_state(); + + check_rcc_secure_configuration(); + set_etzpc_secure_configuration(); + set_gpio_secure_configuration(); +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c new file mode 100644 index 0000000..14e8e16 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#define RANDOM_CANARY_VALUE 2144346116U + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * Ideally, a random number should be returned instead of the + * combination of a timer's value and a compile-time constant. + */ + return RANDOM_CANARY_VALUE ^ (u_register_t)read_cntpct_el0(); +} + diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h new file mode 100644 index 0000000..8efa342 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_STM32IMAGE_DEF_H +#define STM32MP1_STM32IMAGE_DEF_H + +#ifdef AARCH32_SP_OPTEE +#define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */ +#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ +#else +#define STM32MP_DDR_S_SIZE U(0) +#define STM32MP_DDR_SHMEM_SIZE U(0) +#endif + +#define STM32MP_BL2_SIZE U(0x0001C000) /* 112 KB for BL2 */ +#define STM32MP_DTB_SIZE U(0x00006000) /* 24 KB for DTB */ + +#ifdef AARCH32_SP_OPTEE +#define STM32MP_BL32_BASE STM32MP_SEC_SYSRAM_BASE + +#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL2_SIZE) + +/* OP-TEE loads from SYSRAM base to BL2 DTB start address */ +#define STM32MP_OPTEE_BASE STM32MP_BL32_BASE +#define STM32MP_OPTEE_SIZE (STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL2_SIZE - STM32MP_DTB_SIZE) +#define STM32MP_BL32_SIZE STM32MP_OPTEE_SIZE +#else /* AARCH32_SP_OPTEE */ +#define STM32MP_BL32_SIZE U(0x00019000) /* 96 KB for BL32 */ + +#define STM32MP_BL32_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL32_SIZE) + +#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ + STM32MP_BL2_SIZE) +#endif /* AARCH32_SP_OPTEE */ + +/* DTB initialization value */ +#define STM32MP_DTB_BASE (STM32MP_BL2_BASE - \ + STM32MP_DTB_SIZE) + +/* + * MAX_MMAP_REGIONS is usually: + * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup + */ +#if defined(IMAGE_BL32) +#define MAX_MMAP_REGIONS 6 +#endif + +/******************************************************************************* + * STM32MP1 RAW partition offset for MTD devices + ******************************************************************************/ +#define STM32MP_NOR_BL33_OFFSET U(0x00080000) +#ifdef AARCH32_SP_OPTEE +#define STM32MP_NOR_TEEH_OFFSET U(0x00280000) +#define STM32MP_NOR_TEED_OFFSET U(0x002C0000) +#define STM32MP_NOR_TEEX_OFFSET U(0x00300000) +#endif + +#define STM32MP_NAND_BL33_OFFSET U(0x00200000) +#ifdef AARCH32_SP_OPTEE +#define STM32MP_NAND_TEEH_OFFSET U(0x00600000) +#define STM32MP_NAND_TEED_OFFSET U(0x00680000) +#define STM32MP_NAND_TEEX_OFFSET U(0x00700000) +#endif + +#endif /* STM32MP1_STM32IMAGE_DEF_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c new file mode 100644 index 0000000..ff79428 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * SYSCFG REGISTER OFFSET (base relative) + */ +#define SYSCFG_BOOTR 0x00U +#define SYSCFG_BOOTCR 0x0CU +#if STM32MP15 +#define SYSCFG_IOCTRLSETR 0x18U +#define SYSCFG_ICNR 0x1CU +#endif +#define SYSCFG_CMPCR 0x20U +#define SYSCFG_CMPENSETR 0x24U +#define SYSCFG_CMPENCLRR 0x28U +#if STM32MP13 +#define SYSCFG_CMPSD1CR 0x30U +#define SYSCFG_CMPSD1ENSETR 0x34U +#define SYSCFG_CMPSD1ENCLRR 0x38U +#define SYSCFG_CMPSD2CR 0x40U +#define SYSCFG_CMPSD2ENSETR 0x44U +#define SYSCFG_CMPSD2ENCLRR 0x48U +#define SYSCFG_HSLVEN0R 0x50U +#endif +#define SYSCFG_IDC 0x380U + +#define CMPCR_CMPENSETR_OFFSET 0x4U +#define CMPCR_CMPENCLRR_OFFSET 0x8U + +/* + * SYSCFG_BOOTR Register + */ +#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) +#if STM32MP15 +#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4) +#define SYSCFG_BOOTR_BOOTPD_SHIFT 4 +#endif + +/* + * SYSCFG_BOOTCR Register + */ +#define SYSCFG_BOOTCR_BMEN BIT(0) + +/* + * SYSCFG_IOCTRLSETR Register + */ +#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) +#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) +#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) +#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) +#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) + +/* + * SYSCFG_ICNR Register + */ +#define SYSCFG_ICNR_AXI_M9 BIT(9) + +/* + * SYSCFG_CMPCR Register + */ +#define SYSCFG_CMPCR_SW_CTRL BIT(1) +#define SYSCFG_CMPCR_READY BIT(8) +#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16) +#define SYSCFG_CMPCR_RANSRC_SHIFT 16 +#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20) +#define SYSCFG_CMPCR_ANSRC_SHIFT 24 + +#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U + +/* + * SYSCFG_CMPENSETR Register + */ +#define SYSCFG_CMPENSETR_MPU_EN BIT(0) + +/* + * HSLV definitions + */ +#define HSLV_IDX_TPIU 0U +#define HSLV_IDX_QSPI 1U +#define HSLV_IDX_ETH1 2U +#define HSLV_IDX_ETH2 3U +#define HSLV_IDX_SDMMC1 4U +#define HSLV_IDX_SDMMC2 5U +#define HSLV_IDX_SPI1 6U +#define HSLV_IDX_SPI2 7U +#define HSLV_IDX_SPI3 8U +#define HSLV_IDX_SPI4 9U +#define HSLV_IDX_SPI5 10U +#define HSLV_IDX_LTDC 11U +#define HSLV_NB_IDX 12U + +#define HSLV_KEY 0x1018U + +/* + * SYSCFG_IDC Register + */ +#define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0) +#define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16) +#define SYSCFG_IDC_REV_ID_SHIFT 16 + +static void enable_io_comp_cell_finish(uintptr_t cmpcr_off) +{ + uint64_t start; + + start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US); + + while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) { + if (timeout_elapsed(start)) { + /* Failure on IO compensation enable is not a issue: warn only. */ + WARN("IO compensation cell not ready\n"); + break; + } + } + + mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL); +} + +static void disable_io_comp_cell(uintptr_t cmpcr_off) +{ + uint32_t value; + + if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) || + ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) & + SYSCFG_CMPENSETR_MPU_EN) == 0U)) { + return; + } + + value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT; + + mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); + + value <<= SYSCFG_CMPCR_RANSRC_SHIFT; + value |= mmio_read_32(SYSCFG_BASE + cmpcr_off); + + mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL); + + mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); +} + +#if STM32MP13 +static int get_regu_max_voltage(void *fdt, int sdmmc_node, + const char *regu_name, uint32_t *regu_val) +{ + int node; + const fdt32_t *cuint; + + cuint = fdt_getprop(fdt, sdmmc_node, regu_name, NULL); + if (cuint == NULL) { + return -ENODEV; + } + + node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (node < 0) { + return -ENODEV; + } + + cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); + if (cuint == NULL) { + return -ENODEV; + } + + *regu_val = fdt32_to_cpu(*cuint); + + return 0; +} + +static bool sdmmc_is_low_voltage(uintptr_t sdmmc_base) +{ + int ret; + int node; + void *fdt = NULL; + uint32_t regu_max_val; + + if (fdt_get_address(&fdt) == 0) { + return false; + } + + if (fdt == NULL) { + return false; + } + + node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, sdmmc_base); + if (node < 0) { + /* No SD or eMMC device on this instance, enable HSLV */ + return true; + } + + ret = get_regu_max_voltage(fdt, node, "vqmmc-supply", ®u_max_val); + if ((ret < 0) || (regu_max_val > 1800000U)) { + /* + * The vqmmc-supply property should always be present for eMMC. + * For SD-card, if it is not, then the card only supports 3.3V. + */ + return false; + } + + return true; +} + +static void enable_hslv_by_index(uint32_t index) +{ + bool apply_hslv; + + assert(index < HSLV_NB_IDX); + + switch (index) { + case HSLV_IDX_SDMMC1: + apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC1_BASE); + break; + case HSLV_IDX_SDMMC2: + apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC2_BASE); + break; + default: + apply_hslv = true; + break; + } + + if (apply_hslv) { + mmio_write_32(SYSCFG_BASE + SYSCFG_HSLVEN0R + index * sizeof(uint32_t), HSLV_KEY); + } +} +#endif + +static void enable_high_speed_mode_low_voltage(void) +{ +#if STM32MP13 + uint32_t idx; + + for (idx = 0U; idx < HSLV_NB_IDX; idx++) { + enable_hslv_by_index(idx); + } +#endif +#if STM32MP15 + mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR, + SYSCFG_IOCTRLSETR_HSLVEN_TRACE | + SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | + SYSCFG_IOCTRLSETR_HSLVEN_ETH | + SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | + SYSCFG_IOCTRLSETR_HSLVEN_SPI); +#endif +} + +static void stm32mp1_syscfg_set_hslv(void) +{ + uint32_t otp_value; + uint32_t vdd_voltage; + bool product_below_2v5; + + /* + * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI + * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. + * It could be disabled for low frequencies or if AFMUX is selected + * but the function is not used, typically for TRACE. + * If high speed low voltage pad mode is node enable, platform will + * over consume. + * + * WARNING: + * Enabling High Speed mode while VDD > 2.7V + * with the OTP product_below_2v5 (OTP 18, BIT 13) + * erroneously set to 1 can damage the SoC! + * => TF-A enables the low power mode only if VDD < 2.7V (in DT) + * but this value needs to be consistent with board design. + */ + if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) { + panic(); + } + + product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U; + + /* Get VDD supply */ + vdd_voltage = dt_get_pwr_vdd_voltage(); + + /* Check if VDD is Low Voltage */ + if (vdd_voltage == 0U) { + WARN("VDD unknown\n"); + } else if (vdd_voltage < 2700000U) { + enable_high_speed_mode_low_voltage(); + + if (!product_below_2v5) { + INFO("Product_below_2v5=0: HSLVEN protected by HW\n"); + } + } else { + if (product_below_2v5) { + ERROR("Product_below_2v5=1:\n"); + ERROR("\tHSLVEN update is destructive,\n"); + ERROR("\tno update as VDD > 2.7V\n"); + panic(); + } + } +} + +void stm32mp1_syscfg_init(void) +{ +#if STM32MP15 + uint32_t bootr; + + /* + * Interconnect update : select master using the port 1. + * LTDC = AXI_M9. + */ + mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9); + + /* Disable Pull-Down for boot pin connected to VDD */ + bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) & + SYSCFG_BOOTR_BOOT_MASK; + mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, + bootr << SYSCFG_BOOTR_BOOTPD_SHIFT); +#endif + + stm32mp1_syscfg_set_hslv(); + + stm32mp1_syscfg_enable_io_compensation_start(); +} + +void stm32mp1_syscfg_enable_io_compensation_start(void) +{ + /* + * Activate automatic I/O compensation. + * Warning: need to ensure CSI enabled and ready in clock driver. + * Enable non-secure clock, we assume non-secure is suspended. + */ + clk_enable(SYSCFG); + + mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR, + SYSCFG_CMPENSETR_MPU_EN); +#if STM32MP13 + mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD1CR, + SYSCFG_CMPENSETR_MPU_EN); + mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD2CR, + SYSCFG_CMPENSETR_MPU_EN); + +#endif +} + +void stm32mp1_syscfg_enable_io_compensation_finish(void) +{ + enable_io_comp_cell_finish(SYSCFG_CMPCR); +#if STM32MP13 + enable_io_comp_cell_finish(SYSCFG_CMPSD1CR); + enable_io_comp_cell_finish(SYSCFG_CMPSD2CR); +#endif +} + +void stm32mp1_syscfg_disable_io_compensation(void) +{ + clk_enable(SYSCFG); + + /* + * Deactivate automatic I/O compensation. + * Warning: CSI is disabled automatically in STOP if not + * requested for other usages and always OFF in STANDBY. + * Disable non-secure SYSCFG clock, we assume non-secure is suspended. + */ + disable_io_comp_cell(SYSCFG_CMPCR); +#if STM32MP13 + disable_io_comp_cell(SYSCFG_CMPSD1CR); + disable_io_comp_cell(SYSCFG_CMPSD2CR); +#endif + + clk_disable(SYSCFG); +} + +/* + * @brief Get silicon revision from SYSCFG registers. + * @retval chip version (REV_ID). + */ +uint32_t stm32mp1_syscfg_get_chip_version(void) +{ + return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & + SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT; +} + +/* + * @brief Get device ID from SYSCFG registers. + * @retval device ID (DEV_ID). + */ +uint32_t stm32mp1_syscfg_get_chip_dev_id(void) +{ + return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK; +} + +#if STM32MP13 +void stm32mp1_syscfg_boot_mode_enable(void) +{ + mmio_setbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN); +} + +void stm32mp1_syscfg_boot_mode_disable(void) +{ + mmio_clrbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN); +} +#endif diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c new file mode 100644 index 0000000..59a0c17 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* 1 cluster, all cores into */ +static const unsigned char stm32mp1_power_domain_tree_desc[] = { + PLATFORM_CLUSTER_COUNT, + PLATFORM_CORE_COUNT, +}; + +/* This function returns the platform topology */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return stm32mp1_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + u_register_t mpidr_copy = mpidr; + + mpidr_copy &= MPIDR_AFFINITY_MASK; + + if ((mpidr_copy & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) { + return -1; + } + + cluster_id = (mpidr_copy >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr_copy >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + /* + * Validate cpu_id by checking whether it represents a CPU in one + * of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_CORE_COUNT) { + return -1; + } + + return (int)cpu_id; +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c new file mode 100644 index 0000000..0fe2d24 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* String size (1 byte) + type (1 byte) + 24 UTF16 characters: 2 bytes each */ +#define SIZ_STRING_SERIAL U(24) +#define USB_SIZ_STRING_SERIAL (1U + 1U + (SIZ_STRING_SERIAL * 2U)) +#define USBD_MAX_STR_DESC_SIZ 0x100 +#define USBD_VID 0x0483 +#define USBD_PID 0xDF11 +#define USBD_LANGID_STRING 0x409 +#define USBD_MANUFACTURER_STRING "STMicroelectronics" +#define USBD_CONFIGURATION_STRING "DFU Config" +#define USBD_INTERFACE_STRING "DFU Interface" + +#if STM32MP13 +#define USB_DFU_ITF_NUM 2 +#endif +#if STM32MP15 +#define USB_DFU_ITF_NUM 6 +#endif + +#define USB_DFU_CONFIG_DESC_SIZ USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM) + +/* DFU devices */ +static struct usb_dfu_handle usb_dfu_handle; + +/* USB Standard Device Descriptor */ +static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = { + USB_LEN_DEV_DESC, /* bLength */ + USB_DESC_TYPE_DEVICE, /* bDescriptorType */ + 0x00, /* bcdUSB */ + 0x02, /* version */ + 0x00, /* bDeviceClass */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + USB_MAX_EP0_SIZE, /* bMaxPacketSize */ + LOBYTE(USBD_VID), /* idVendor */ + HIBYTE(USBD_VID), /* idVendor */ + LOBYTE(USBD_PID), /* idVendor */ + HIBYTE(USBD_PID), /* idVendor */ + 0x00, /* bcdDevice rel. 2.00 */ + 0x02, + USBD_IDX_MFC_STR, /* Index of manufacturer string */ + USBD_IDX_PRODUCT_STR, /* Index of product string */ + USBD_IDX_SERIAL_STR, /* Index of serial number string */ + USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */ +}; /* USB_DeviceDescriptor */ + +/* USB Standard String Descriptor */ +static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = { + USB_LEN_LANGID_STR_DESC, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING), +}; + +/* USB Standard Device Descriptor */ +static const uint8_t +usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = { + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +}; + +/* USB serial number: build dynamically */ +static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1]; + +/* USB DFU device Configuration Descriptor */ +static const uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x02, /* iConfiguration: Index of string descriptor for configuration */ + 0xC0, /* bmAttributes: bus powered and Supprts Remote Wakeup */ + 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */ + + /* Descriptor of DFU interface 0 Alternate setting 0..N */ + USBD_DFU_IF_DESC(0), + USBD_DFU_IF_DESC(1), +#if USB_DFU_ITF_NUM > 2 + USBD_DFU_IF_DESC(2), +#endif +#if USB_DFU_ITF_NUM > 3 + USBD_DFU_IF_DESC(3), +#endif +#if USB_DFU_ITF_NUM > 4 + USBD_DFU_IF_DESC(4), +#endif +#if USB_DFU_ITF_NUM > 5 + USBD_DFU_IF_DESC(5), +#endif + /* DFU Functional Descriptor */ + 0x09, /* blength = 9 Bytes */ + DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */ + DFU_BM_ATTRIBUTE, /* bmAttribute for DFU */ + 0xFF, /* DetachTimeOut = 255 ms */ + 0x00, + TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */ + ((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion */ + ((USB_DFU_VERSION >> 8) & 0xFF) +}; + +/* The user strings: one by alternate as defined in USBD_DFU_IF_DESC */ +#if STM32MP13 +const char *const if_desc_string[USB_DFU_ITF_NUM] = { + "@SSBL /0x03/1*16Me", + "@virtual /0xF1/1*512Ba" +}; +#endif +#if STM32MP15 +const char *const if_desc_string[USB_DFU_ITF_NUM] = { + "@Partition0 /0x00/1*256Ke", + "@FSBL /0x01/1*1Me", + "@Partition2 /0x02/1*1Me", + "@Partition3 /0x03/1*16Me", + "@Partition4 /0x04/1*16Me", + "@virtual /0xF1/1*512Ba" +}; +#endif + +/* Buffer to build the unicode string provided to USB device stack */ +static uint8_t usb_str_dec[USBD_MAX_STR_DESC_SIZ]; + +/* + * Convert Ascii string into unicode one + * desc : descriptor buffer + * unicode : Formatted string buffer (unicode) + * len : descriptor length + */ +static void stm32mp1_get_string(const char *desc, uint8_t *unicode, uint16_t *len) +{ + uint8_t idx = 0U; + + if (desc == NULL) { + return; + } + + *len = strlen(desc) * 2U + 2U; + unicode[idx++] = *len; + unicode[idx++] = USB_DESC_TYPE_STRING; + + while (*desc != '\0') { + unicode[idx++] = *desc++; + unicode[idx++] = 0x00U; + } +} + +/* + * Create the serial number string descriptor + */ +static void update_serial_num_string(void) +{ + uint8_t i; + char serial_string[SIZ_STRING_SERIAL + 2U]; + /* serial number is set to 0 */ + uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U}; + uint32_t otp; + uint32_t len; + uint16_t length; + + if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) { + ERROR("BSEC: Get UID_OTP number Error\n"); + return; + } + + if ((len / __WORD_BIT) != UID_WORD_NB) { + ERROR("BSEC: Get UID_OTP length Error\n"); + return; + } + + for (i = 0; i < UID_WORD_NB; i++) { + if (bsec_shadow_read_otp(&deviceserial[i], i + otp) != + BSEC_OK) { + ERROR("BSEC: UID%d Error\n", i); + return; + } + } + /* build serial number with OTP value as in ROM code */ + snprintf(serial_string, sizeof(serial_string), "%08X%08X%08X", + deviceserial[0], deviceserial[1], deviceserial[2]); + + length = USB_SIZ_STRING_SERIAL; + stm32mp1_get_string(serial_string, usb_stm32mp1_serial, &length); +} + +/* + * Return Device Qualifier descriptor + * length : pointer data length + * return : pointer to descriptor buffer + */ +static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length) +{ + *length = sizeof(usbd_stm32mp1_qualifier_desc); + + return (uint8_t *)usbd_stm32mp1_qualifier_desc; +} + +/* + * Return configuration descriptor + * length : pointer data length + * return : pointer to descriptor buffer + */ +static uint8_t *stm32mp1_get_config_desc(uint16_t *length) +{ + *length = sizeof(usb_stm32mp1_config_desc); + + return (uint8_t *)usb_stm32mp1_config_desc; +} + +/* + * Returns the device descriptor. + * length: Pointer to data length variable + * return : Pointer to descriptor buffer + */ +static uint8_t *stm32mp1_device_desc(uint16_t *length) +{ + *length = sizeof(usb_stm32mp1_desc); + + return (uint8_t *)usb_stm32mp1_desc; +} + +/* + * Returns the LangID string descriptor. + * length: Pointer to data length variable + * return : Pointer to descriptor buffer + */ +static uint8_t *stm32mp1_lang_id_desc(uint16_t *length) +{ + *length = sizeof(usb_stm32mp1_lang_id_desc); + + return (uint8_t *)usb_stm32mp1_lang_id_desc; +} + +/* + * Returns the product string descriptor. + * length: Pointer to data length variable + * return : Pointer to descriptor buffer + */ +static uint8_t *stm32mp1_product_desc(uint16_t *length) +{ + char name[STM32_SOC_NAME_SIZE]; + char product[128]; + uint32_t chip_id; + uint32_t chip_version; + + stm32mp_get_soc_name(name); + chip_id = stm32mp_get_chip_dev_id(); + chip_version = stm32mp_get_chip_version(); + + snprintf(product, sizeof(product), + "DFU @Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,", + chip_id, chip_version, name); + + stm32mp1_get_string(product, usb_str_dec, length); + + return usb_str_dec; +} + +/* + * Returns the manufacturer string descriptor. + * length: Pointer to data length variable + * return : Pointer to descriptor buffer + */ +static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length) +{ + stm32mp1_get_string(USBD_MANUFACTURER_STRING, usb_str_dec, length); + + return usb_str_dec; +} + +/* + * Returns the serial number string descriptor. + * length: Pointer to data length variable + * return : Pointer to descriptor buffer + */ +static uint8_t *stm32mp1_serial_desc(uint16_t *length) +{ + *length = USB_SIZ_STRING_SERIAL; + + return (uint8_t *)usb_stm32mp1_serial; +} + +/* + * Returns the configuration string descriptor. + * length: Pointer to data length variable + * return : Pointer to descriptor buffer + */ +static uint8_t *stm32mp1_config_desc(uint16_t *length) +{ + stm32mp1_get_string(USBD_CONFIGURATION_STRING, usb_str_dec, length); + + return usb_str_dec; +} + +/* + * Returns the interface string descriptor. + * length : Pointer to data length variable + * return : Pointer to descriptor buffer + */ +static uint8_t *stm32mp1_interface_desc(uint16_t *length) +{ + stm32mp1_get_string(USBD_INTERFACE_STRING, usb_str_dec, length); + + return usb_str_dec; +} + +/* + * Manages the transfer of memory interfaces string descriptors. + * index: descriptor index + * length : pointer data length + * return : pointer to the descriptor table or NULL if the descriptor + * is not supported. + */ +static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length) +{ + if (index >= ARRAY_SIZE(if_desc_string)) { + return NULL; + } + + stm32mp1_get_string(if_desc_string[index], usb_str_dec, length); + + return usb_str_dec; +} + +static const struct usb_desc dfu_desc = { + .get_device_desc = stm32mp1_device_desc, + .get_lang_id_desc = stm32mp1_lang_id_desc, + .get_manufacturer_desc = stm32mp1_manufacturer_desc, + .get_product_desc = stm32mp1_product_desc, + .get_configuration_desc = stm32mp1_config_desc, + .get_serial_desc = stm32mp1_serial_desc, + .get_interface_desc = stm32mp1_interface_desc, + .get_usr_desc = stm32mp1_get_usr_desc, + .get_config_desc = stm32mp1_get_config_desc, + .get_device_qualifier_desc = stm32mp1_get_qualifier_desc, + /* only HS is supported, as ROM code */ + .get_other_speed_config_desc = NULL, +}; + +static struct usb_handle usb_core_handle; +static struct pcd_handle pcd_handle; + +struct usb_handle *usb_dfu_plat_init(void) +{ + /* Prepare USB Driver */ + pcd_handle.in_ep[0].maxpacket = USB_MAX_EP0_SIZE; + pcd_handle.out_ep[0].maxpacket = USB_MAX_EP0_SIZE; + stm32mp1_usb_init_driver(&usb_core_handle, &pcd_handle, + (uint32_t *)USB_OTG_BASE); + +#if STM32MP15 + /* STM32MP15 = keep the configuration from ROM code */ + usb_core_handle.ep0_state = USBD_EP0_DATA_IN; + usb_core_handle.dev_state = USBD_STATE_CONFIGURED; +#endif + + /* Update the serial number string descriptor from the unique ID */ + update_serial_num_string(); + + /* Prepare USB DFU stack */ + usb_dfu_register(&usb_core_handle, &usb_dfu_handle); + + /* Register DFU descriptor in USB stack */ + register_platform(&usb_core_handle, &dfu_desc); + + return &usb_core_handle; +} + +/* Link between USB alternate and STM32CubeProgramer phase */ +uint8_t usb_dfu_get_phase(uint8_t alt) +{ + uint8_t ret; + + switch (alt) { +#if STM32MP13 + case 0: + ret = PHASE_SSBL; + break; + case 1: + ret = PHASE_CMD; + break; +#endif +#if STM32MP15 + case 3: + ret = PHASE_SSBL; + break; + case 5: + ret = PHASE_CMD; + break; +#endif + default: + ret = PHASE_RESET; + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/ti/k3/board/generic/board.mk b/arm-trusted-firmware/plat/ti/k3/board/generic/board.mk new file mode 100644 index 0000000..ef74cd6 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/board/generic/board.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_BASE ?= 0x9e800000 +$(eval $(call add_define,BL32_BASE)) + +PRELOADED_BL33_BASE ?= 0x80080000 +$(eval $(call add_define,PRELOADED_BL33_BASE)) + +K3_HW_CONFIG_BASE ?= 0x82000000 +$(eval $(call add_define,K3_HW_CONFIG_BASE)) + +# Define sec_proxy usage as the full prioritized communication scheme +K3_SEC_PROXY_LITE := 0 +$(eval $(call add_define,K3_SEC_PROXY_LITE)) + +# System coherency is managed in hardware +USE_COHERENT_MEM := 1 + +PLAT_INCLUDES += \ + -Iplat/ti/k3/board/generic/include \ diff --git a/arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h b/arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h new file mode 100644 index 0000000..4ff687c --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_DEF_H +#define BOARD_DEF_H + +#include + +/* The ports must be in order and contiguous */ +#define K3_CLUSTER0_CORE_COUNT U(2) +#define K3_CLUSTER1_CORE_COUNT U(2) +#define K3_CLUSTER2_CORE_COUNT U(2) +#define K3_CLUSTER3_CORE_COUNT U(2) + +/* + * This RAM will be used for the bootloader including code, bss, and stacks. + * It may need to be increased if BL31 grows in size. + * + * The link addresses are determined by SEC_SRAM_BASE + offset. + * When ENABLE_PIE is set, the TF images can be loaded anywhere, so + * SEC_SRAM_BASE is really arbitrary. + * + * When ENABLE_PIE is unset, SEC_SRAM_BASE should be chosen so that + * it matches to the physical address where BL31 is loaded, that is, + * SEC_SRAM_BASE should be the base address of the RAM region. + * + * Lets make things explicit by mapping SRAM_BASE to 0x0 since ENABLE_PIE is + * defined as default for our platform. + */ +#define SEC_SRAM_BASE UL(0x00000000) /* PIE remapped on fly */ +#define SEC_SRAM_SIZE UL(0x00020000) /* 128k */ + +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_RET_STATE U(1) + +#define PLAT_PROC_START_ID U(32) +#define PLAT_PROC_DEVICE_START_ID U(202) +#define PLAT_CLUSTER_DEVICE_START_ID U(198) + +#endif /* BOARD_DEF_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/board/lite/board.mk b/arm-trusted-firmware/plat/ti/k3/board/lite/board.mk new file mode 100644 index 0000000..76246be --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/board/lite/board.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_BASE ?= 0x9e800000 +$(eval $(call add_define,BL32_BASE)) + +PRELOADED_BL33_BASE ?= 0x80080000 +$(eval $(call add_define,PRELOADED_BL33_BASE)) + +K3_HW_CONFIG_BASE ?= 0x82000000 +$(eval $(call add_define,K3_HW_CONFIG_BASE)) + +# Define sec_proxy usage as the lite version +K3_SEC_PROXY_LITE := 1 +$(eval $(call add_define,K3_SEC_PROXY_LITE)) + +# We dont have system level coherency capability +USE_COHERENT_MEM := 0 + +PLAT_INCLUDES += \ + -Iplat/ti/k3/board/lite/include \ diff --git a/arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h b/arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h new file mode 100644 index 0000000..18b7f42 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_DEF_H +#define BOARD_DEF_H + +#include + +/* The ports must be in order and contiguous */ +#define K3_CLUSTER0_CORE_COUNT U(4) +#define K3_CLUSTER1_CORE_COUNT U(0) +#define K3_CLUSTER2_CORE_COUNT U(0) +#define K3_CLUSTER3_CORE_COUNT U(0) + +/* + * This RAM will be used for the bootloader including code, bss, and stacks. + * It may need to be increased if BL31 grows in size. + * Current computation assumes data structures necessary for GIC and ARM for + * a single cluster of 4 processor. + * + * The link addresses are determined by SEC_SRAM_BASE + offset. + * When ENABLE_PIE is set, the TF images can be loaded anywhere, so + * SEC_SRAM_BASE is really arbitrary. + * + * When ENABLE_PIE is unset, SEC_SRAM_BASE should be chosen so that + * it matches to the physical address where BL31 is loaded, that is, + * SEC_SRAM_BASE should be the base address of the RAM region. + * + * Lets make things explicit by mapping SRAM_BASE to 0x0 since ENABLE_PIE is + * defined as default for our platform. + */ +#define SEC_SRAM_BASE UL(0x00000000) /* PIE remapped on fly */ +#define SEC_SRAM_SIZE UL(0x0001c000) /* 112k */ + +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_RET_STATE U(1) + +#define PLAT_PROC_START_ID U(32) +#define PLAT_PROC_DEVICE_START_ID U(135) +#define PLAT_CLUSTER_DEVICE_START_ID U(134) + +#endif /* BOARD_DEF_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c new file mode 100644 index 0000000..a0bfdee --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c @@ -0,0 +1,341 @@ +/* + * Texas Instruments K3 Secure Proxy Driver + * Based on Linux and U-Boot implementation + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "sec_proxy.h" + +/* SEC PROXY RT THREAD STATUS */ +#define RT_THREAD_STATUS (0x0) +#define RT_THREAD_STATUS_ERROR_SHIFT (31) +#define RT_THREAD_STATUS_ERROR_MASK BIT(31) +#define RT_THREAD_STATUS_CUR_CNT_SHIFT (0) +#define RT_THREAD_STATUS_CUR_CNT_MASK GENMASK(7, 0) + +/* SEC PROXY SCFG THREAD CTRL */ +#define SCFG_THREAD_CTRL (0x1000) +#define SCFG_THREAD_CTRL_DIR_SHIFT (31) +#define SCFG_THREAD_CTRL_DIR_MASK BIT(31) + +#define SEC_PROXY_THREAD(base, x) ((base) + (0x1000 * (x))) +#define THREAD_IS_RX (1) +#define THREAD_IS_TX (0) + +/** + * struct k3_sec_proxy_desc - Description of secure proxy integration + * @timeout_us: Timeout for communication (in Microseconds) + * @max_msg_size: Message size in bytes + * @data_start_offset: Offset of the First data register of the thread + * @data_end_offset: Offset of the Last data register of the thread + */ +struct k3_sec_proxy_desc { + uint32_t timeout_us; + uint16_t max_msg_size; + uint16_t data_start_offset; + uint16_t data_end_offset; +}; + +/** + * struct k3_sec_proxy_thread - Description of a Secure Proxy Thread + * @name: Thread Name + * @data: Thread Data path region for target + * @scfg: Secure Config Region for Thread + * @rt: RealTime Region for Thread + */ +struct k3_sec_proxy_thread { + const char *name; + uintptr_t data; + uintptr_t scfg; + uintptr_t rt; +}; + +/** + * struct k3_sec_proxy_mbox - Description of a Secure Proxy Instance + * @desc: Description of the SoC integration + * @chans: Array for valid thread instances + */ +struct k3_sec_proxy_mbox { + const struct k3_sec_proxy_desc desc; + struct k3_sec_proxy_thread threads[]; +}; + +/* + * Thread ID #0: DMSC notify + * Thread ID #1: DMSC request response + * Thread ID #2: DMSC request high priority + * Thread ID #3: DMSC request low priority + * Thread ID #4: DMSC notify response + */ +#define SP_THREAD(_x) \ + [_x] = { \ + .name = #_x, \ + .data = SEC_PROXY_THREAD(SEC_PROXY_DATA_BASE, _x), \ + .scfg = SEC_PROXY_THREAD(SEC_PROXY_SCFG_BASE, _x), \ + .rt = SEC_PROXY_THREAD(SEC_PROXY_RT_BASE, _x), \ + } + +static struct k3_sec_proxy_mbox spm = { + .desc = { + .timeout_us = SEC_PROXY_TIMEOUT_US, + .max_msg_size = SEC_PROXY_MAX_MESSAGE_SIZE, + .data_start_offset = 0x4, + .data_end_offset = 0x3C, + }, + .threads = { +#if !K3_SEC_PROXY_LITE + SP_THREAD(SP_NOTIFY), + SP_THREAD(SP_RESPONSE), + SP_THREAD(SP_HIGH_PRIORITY), + SP_THREAD(SP_LOW_PRIORITY), + SP_THREAD(SP_NOTIFY_RESP), +#else + SP_THREAD(SP_RESPONSE), + SP_THREAD(SP_HIGH_PRIORITY), +#endif /* K3_SEC_PROXY_LITE */ + }, +}; + +/** + * struct sec_msg_hdr - Message header for secure messages and responses + * @checksum: CRC of message for integrity checking + */ +union sec_msg_hdr { + struct { + uint16_t checksum; + uint16_t reserved; + } __packed; + uint32_t data; +}; + +/** + * k3_sec_proxy_verify_thread() - Verify thread status before + * sending/receiving data + * @spt: Pointer to Secure Proxy thread description + * @dir: Direction of the thread + * + * Return: 0 if all goes well, else appropriate error message + */ +static inline int k3_sec_proxy_verify_thread(struct k3_sec_proxy_thread *spt, + uint32_t dir) +{ + /* Check for any errors already available */ + if (mmio_read_32(spt->rt + RT_THREAD_STATUS) & + RT_THREAD_STATUS_ERROR_MASK) { + ERROR("Thread %s is corrupted, cannot send data\n", spt->name); + return -EINVAL; + } + + /* Make sure thread is configured for right direction */ + if ((mmio_read_32(spt->scfg + SCFG_THREAD_CTRL) & SCFG_THREAD_CTRL_DIR_MASK) + != (dir << SCFG_THREAD_CTRL_DIR_SHIFT)) { + if (dir == THREAD_IS_TX) + ERROR("Trying to send data on RX Thread %s\n", + spt->name); + else + ERROR("Trying to receive data on TX Thread %s\n", + spt->name); + return -EINVAL; + } + + /* Check the message queue before sending/receiving data */ + uint32_t tick_start = (uint32_t)read_cntpct_el0(); + uint32_t ticks_per_us = SYS_COUNTER_FREQ_IN_TICKS / 1000000; + while (!(mmio_read_32(spt->rt + RT_THREAD_STATUS) & RT_THREAD_STATUS_CUR_CNT_MASK)) { + VERBOSE("Waiting for thread %s to %s\n", + spt->name, (dir == THREAD_IS_TX) ? "empty" : "fill"); + if (((uint32_t)read_cntpct_el0() - tick_start) > + (spm.desc.timeout_us * ticks_per_us)) { + ERROR("Timeout waiting for thread %s to %s\n", + spt->name, (dir == THREAD_IS_TX) ? "empty" : "fill"); + return -ETIMEDOUT; + } + } + + return 0; +} + +/** + * k3_sec_proxy_clear_rx_thread() - Clear Secure Proxy thread + * + * @id: Channel Identifier + * + * Return: 0 if all goes well, else appropriate error message + */ +int k3_sec_proxy_clear_rx_thread(enum k3_sec_proxy_chan_id id) +{ + struct k3_sec_proxy_thread *spt = &spm.threads[id]; + + /* Check for any errors already available */ + if (mmio_read_32(spt->rt + RT_THREAD_STATUS) & + RT_THREAD_STATUS_ERROR_MASK) { + ERROR("Thread %s is corrupted, cannot send data\n", spt->name); + return -EINVAL; + } + + /* Make sure thread is configured for right direction */ + if (!(mmio_read_32(spt->scfg + SCFG_THREAD_CTRL) & SCFG_THREAD_CTRL_DIR_MASK)) { + ERROR("Cannot clear a transmit thread %s\n", spt->name); + return -EINVAL; + } + + /* Read off messages from thread until empty */ + uint32_t try_count = 10; + while (mmio_read_32(spt->rt + RT_THREAD_STATUS) & RT_THREAD_STATUS_CUR_CNT_MASK) { + if (!(try_count--)) { + ERROR("Could not clear all messages from thread %s\n", spt->name); + return -ETIMEDOUT; + } + WARN("Clearing message from thread %s\n", spt->name); + mmio_read_32(spt->data + spm.desc.data_end_offset); + } + + return 0; +} + +/** + * k3_sec_proxy_send() - Send data over a Secure Proxy thread + * @id: Channel Identifier + * @msg: Pointer to k3_sec_proxy_msg + * + * Return: 0 if all goes well, else appropriate error message + */ +int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_msg *msg) +{ + struct k3_sec_proxy_thread *spt = &spm.threads[id]; + union sec_msg_hdr secure_header; + int num_words, trail_bytes, i, ret; + uintptr_t data_reg; + + ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_TX); + if (ret) { + ERROR("Thread %s verification failed (%d)\n", spt->name, ret); + return ret; + } + + /* Check the message size */ + if (msg->len + sizeof(secure_header) > spm.desc.max_msg_size) { + ERROR("Thread %s message length %lu > max msg size\n", + spt->name, msg->len); + return -EINVAL; + } + + /* TODO: Calculate checksum */ + secure_header.checksum = 0; + + /* Send the secure header */ + data_reg = spm.desc.data_start_offset; + mmio_write_32(spt->data + data_reg, secure_header.data); + data_reg += sizeof(uint32_t); + + /* Send whole words */ + num_words = msg->len / sizeof(uint32_t); + for (i = 0; i < num_words; i++) { + mmio_write_32(spt->data + data_reg, ((uint32_t *)msg->buf)[i]); + data_reg += sizeof(uint32_t); + } + + /* Send remaining bytes */ + trail_bytes = msg->len % sizeof(uint32_t); + if (trail_bytes) { + uint32_t data_trail = 0; + + i = msg->len - trail_bytes; + while (trail_bytes--) { + data_trail <<= 8; + data_trail |= msg->buf[i++]; + } + + mmio_write_32(spt->data + data_reg, data_trail); + data_reg += sizeof(uint32_t); + } + /* + * 'data_reg' indicates next register to write. If we did not already + * write on tx complete reg(last reg), we must do so for transmit + * In addition, we also need to make sure all intermediate data + * registers(if any required), are reset to 0 for TISCI backward + * compatibility to be maintained. + */ + while (data_reg <= spm.desc.data_end_offset) { + mmio_write_32(spt->data + data_reg, 0); + data_reg += sizeof(uint32_t); + } + + VERBOSE("Message successfully sent on thread %s\n", spt->name); + + return 0; +} + +/** + * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread + * @id: Channel Identifier + * @msg: Pointer to k3_sec_proxy_msg + * + * Return: 0 if all goes well, else appropriate error message + */ +int k3_sec_proxy_recv(enum k3_sec_proxy_chan_id id, struct k3_sec_proxy_msg *msg) +{ + struct k3_sec_proxy_thread *spt = &spm.threads[id]; + union sec_msg_hdr secure_header; + uintptr_t data_reg; + int num_words, trail_bytes, i, ret; + + ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_RX); + if (ret) { + ERROR("Thread %s verification failed (%d)\n", spt->name, ret); + return ret; + } + + /* Read secure header */ + data_reg = spm.desc.data_start_offset; + secure_header.data = mmio_read_32(spt->data + data_reg); + data_reg += sizeof(uint32_t); + + /* Read whole words */ + num_words = msg->len / sizeof(uint32_t); + for (i = 0; i < num_words; i++) { + ((uint32_t *)msg->buf)[i] = mmio_read_32(spt->data + data_reg); + data_reg += sizeof(uint32_t); + } + + /* Read remaining bytes */ + trail_bytes = msg->len % sizeof(uint32_t); + if (trail_bytes) { + uint32_t data_trail = mmio_read_32(spt->data + data_reg); + data_reg += sizeof(uint32_t); + + i = msg->len - trail_bytes; + while (trail_bytes--) { + msg->buf[i] = data_trail & 0xff; + data_trail >>= 8; + } + } + + /* + * 'data_reg' indicates next register to read. If we did not already + * read on rx complete reg(last reg), we must do so for receive + */ + if (data_reg <= spm.desc.data_end_offset) + mmio_read_32(spt->data + spm.desc.data_end_offset); + + /* TODO: Verify checksum */ + (void)secure_header.checksum; + + VERBOSE("Message successfully received from thread %s\n", spt->name); + + return 0; +} diff --git a/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h new file mode 100644 index 0000000..f4b0b4b --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h @@ -0,0 +1,82 @@ +/* + * Texas Instruments K3 Secure Proxy Driver + * Based on Linux and U-Boot implementation + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SEC_PROXY_H +#define SEC_PROXY_H + +#include + +/** + * enum k3_sec_proxy_chan_id - Secure Proxy thread IDs + * + * These the available IDs used in k3_sec_proxy_{send,recv}() + * There are two schemes we use: + * * if K3_SEC_PROXY_LITE = 1, we just have two threads to talk + * * if K3_SEC_PROXY_LITE = 0, we have the full fledged + * communication scheme available. + */ +enum k3_sec_proxy_chan_id { +#if !K3_SEC_PROXY_LITE + SP_NOTIFY = 0, + SP_RESPONSE, + SP_HIGH_PRIORITY, + SP_LOW_PRIORITY, + SP_NOTIFY_RESP, +#else + SP_RESPONSE = 8, + /* + * Note: TISCI documentation indicates "low priority", but in reality + * with a single thread, there is no low or high priority.. This usage + * is more appropriate for TF-A since we can reduce the churn as a + * result. + */ + SP_HIGH_PRIORITY, +#endif /* K3_SEC_PROXY_LITE */ +}; + +/** + * struct k3_sec_proxy_msg - Secure proxy message structure + * @len: Length of data in the Buffer + * @buf: Buffer pointer + * + * This is the structure for data used in k3_sec_proxy_{send,recv}() + */ +struct k3_sec_proxy_msg { + size_t len; + uint8_t *buf; +}; + +/** + * k3_sec_proxy_send() - Send data over a Secure Proxy thread + * @id: Channel Identifier + * @msg: Pointer to k3_sec_proxy_msg + * + * Return: 0 if all goes well, else appropriate error message + */ +int k3_sec_proxy_clear_rx_thread(enum k3_sec_proxy_chan_id id); + +/** + * k3_sec_proxy_send() - Send data over a Secure Proxy thread + * @id: Channel Identifier + * @msg: Pointer to k3_sec_proxy_msg + * + * Return: 0 if all goes well, else appropriate error message + */ +int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_msg *msg); + +/** + * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread + * @id: Channel Identifier + * @msg: Pointer to k3_sec_proxy_msg + * + * Return: 0 if all goes well, else appropriate error message + */ +int k3_sec_proxy_recv(enum k3_sec_proxy_chan_id id, struct k3_sec_proxy_msg *msg); + +#endif /* SEC_PROXY_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c new file mode 100644 index 0000000..2c3313c --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c @@ -0,0 +1,1688 @@ +/* + * Texas Instruments System Control Interface Driver + * Based on Linux and U-Boot implementation + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include + +#include "ti_sci_protocol.h" +#include "ti_sci.h" + +#if USE_COHERENT_MEM +__section("tzfw_coherent_mem") +#endif +static uint8_t message_sequence; + +/** + * struct ti_sci_xfer - Structure representing a message flow + * @tx_message: Transmit message + * @rx_message: Receive message + */ +struct ti_sci_xfer { + struct k3_sec_proxy_msg tx_message; + struct k3_sec_proxy_msg rx_message; +}; + +/** + * ti_sci_setup_one_xfer() - Setup one message type + * + * @msg_type: Message type + * @msg_flags: Flag to set for the message + * @tx_buf: Buffer to be sent to mailbox channel + * @tx_message_size: transmit message size + * @rx_buf: Buffer to be received from mailbox channel + * @rx_message_size: receive message size + * + * Helper function which is used by various command functions that are + * exposed to clients of this driver for allocating a message traffic event. + * + * Return: 0 if all goes well, else appropriate error message + */ +static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags, + void *tx_buf, + size_t tx_message_size, + void *rx_buf, + size_t rx_message_size, + struct ti_sci_xfer *xfer) +{ + struct ti_sci_msg_hdr *hdr; + + /* Ensure we have sane transfer sizes */ + if (rx_message_size > TI_SCI_MAX_MESSAGE_SIZE || + tx_message_size > TI_SCI_MAX_MESSAGE_SIZE || + rx_message_size < sizeof(*hdr) || + tx_message_size < sizeof(*hdr)) + return -ERANGE; + + hdr = (struct ti_sci_msg_hdr *)tx_buf; + hdr->seq = ++message_sequence; + hdr->type = msg_type; + hdr->host = TI_SCI_HOST_ID; + hdr->flags = msg_flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED; + + xfer->tx_message.buf = tx_buf; + xfer->tx_message.len = tx_message_size; + + xfer->rx_message.buf = rx_buf; + xfer->rx_message.len = rx_message_size; + + return 0; +} + +/** + * ti_sci_get_response() - Receive response from mailbox channel + * + * @xfer: Transfer to initiate and wait for response + * @chan: Channel to receive the response + * + * Return: 0 if all goes well, else appropriate error message + */ +static inline int ti_sci_get_response(struct ti_sci_xfer *xfer, + enum k3_sec_proxy_chan_id chan) +{ + struct k3_sec_proxy_msg *msg = &xfer->rx_message; + struct ti_sci_msg_hdr *hdr; + unsigned int retry = 5; + int ret; + + for (; retry > 0; retry--) { + /* Receive the response */ + ret = k3_sec_proxy_recv(chan, msg); + if (ret) { + ERROR("Message receive failed (%d)\n", ret); + return ret; + } + + /* msg is updated by Secure Proxy driver */ + hdr = (struct ti_sci_msg_hdr *)msg->buf; + + /* Sanity check for message response */ + if (hdr->seq == message_sequence) + break; + else + WARN("Message with sequence ID %u is not expected\n", hdr->seq); + } + if (!retry) { + ERROR("Timed out waiting for message\n"); + return -EINVAL; + } + + if (msg->len > TI_SCI_MAX_MESSAGE_SIZE) { + ERROR("Unable to handle %lu xfer (max %d)\n", + msg->len, TI_SCI_MAX_MESSAGE_SIZE); + return -EINVAL; + } + + if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK)) + return -ENODEV; + + return 0; +} + +/** + * ti_sci_do_xfer() - Do one transfer + * + * @xfer: Transfer to initiate and wait for response + * + * Return: 0 if all goes well, else appropriate error message + */ +static inline int ti_sci_do_xfer(struct ti_sci_xfer *xfer) +{ + struct k3_sec_proxy_msg *msg = &xfer->tx_message; + int ret; + + /* Clear any spurious messages in receive queue */ + ret = k3_sec_proxy_clear_rx_thread(SP_RESPONSE); + if (ret) { + ERROR("Could not clear response queue (%d)\n", ret); + return ret; + } + + /* Send the message */ + ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, msg); + if (ret) { + ERROR("Message sending failed (%d)\n", ret); + return ret; + } + + /* Get the response */ + ret = ti_sci_get_response(xfer, SP_RESPONSE); + if (ret) { + ERROR("Failed to get response (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_get_revision() - Get the revision of the SCI entity + * + * Updates the SCI information in the internal data structure. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info) +{ + struct ti_sci_msg_hdr hdr; + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0, + &hdr, sizeof(hdr), + rev_info, sizeof(*rev_info), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_device_set_state() - Set device state + * + * @id: Device identifier + * @flags: flags to setup for the device + * @state: State to move the device to + * + * Return: 0 if all goes well, else appropriate error message + */ +static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state) +{ + struct ti_sci_msg_req_set_device_state req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.id = id; + req.state = state; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_device_get_state() - Get device state + * + * @id: Device Identifier + * @clcnt: Pointer to Context Loss Count + * @resets: pointer to resets + * @p_state: pointer to p_state + * @c_state: pointer to c_state + * + * Return: 0 if all goes well, else appropriate error message + */ +static int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt, + uint32_t *resets, uint8_t *p_state, + uint8_t *c_state) +{ + struct ti_sci_msg_req_get_device_state req; + struct ti_sci_msg_resp_get_device_state resp; + + struct ti_sci_xfer xfer; + int ret; + + if (!clcnt && !resets && !p_state && !c_state) + return -EINVAL; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.id = id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (clcnt) + *clcnt = resp.context_loss_count; + if (resets) + *resets = resp.resets; + if (p_state) + *p_state = resp.programmed_state; + if (c_state) + *c_state = resp.current_state; + + return 0; +} + +/** + * ti_sci_device_get() - Request for device managed by TISCI + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_get(uint32_t id) +{ + return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON); +} + +/** + * ti_sci_device_get_exclusive() - Exclusive request for device managed by TISCI + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * NOTE: This _exclusive version of the get API is for exclusive access to the + * device. Any other host in the system will fail to get this device after this + * call until exclusive access is released with device_put or a non-exclusive + * set call. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_get_exclusive(uint32_t id) +{ + return ti_sci_device_set_state(id, + MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_ON); +} + +/** + * ti_sci_device_idle() - Idle a device managed by TISCI + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_idle(uint32_t id) +{ + return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_RETENTION); +} + +/** + * ti_sci_device_idle_exclusive() - Exclusive idle a device managed by TISCI + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * NOTE: This _exclusive version of the idle API is for exclusive access to + * the device. Any other host in the system will fail to get this device after + * this call until exclusive access is released with device_put or a + * non-exclusive set call. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_idle_exclusive(uint32_t id) +{ + return ti_sci_device_set_state(id, + MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_RETENTION); +} + +/** + * ti_sci_device_put() - Release a device managed by TISCI + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_put(uint32_t id) +{ + return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF); +} + +/** + * ti_sci_device_put_no_wait() - Release a device without requesting or waiting + * for a response. + * + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_put_no_wait(uint32_t id) +{ + struct ti_sci_msg_req_set_device_state req; + struct ti_sci_msg_hdr *hdr; + struct k3_sec_proxy_msg tx_message; + int ret; + + /* Ensure we have sane transfer size */ + if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE) + return -ERANGE; + + hdr = (struct ti_sci_msg_hdr *)&req; + hdr->seq = ++message_sequence; + hdr->type = TI_SCI_MSG_SET_DEVICE_STATE; + hdr->host = TI_SCI_HOST_ID; + /* Setup with NORESPONSE flag to keep response queue clean */ + hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE; + + req.id = id; + req.state = MSG_DEVICE_SW_STATE_AUTO_OFF; + + tx_message.buf = (uint8_t *)&req; + tx_message.len = sizeof(req); + + /* Send message */ + ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &tx_message); + if (ret) { + ERROR("Message sending failed (%d)\n", ret); + return ret; + } + + /* Return without waiting for response */ + return 0; +} + +/** + * ti_sci_device_is_valid() - Is the device valid + * + * @id: Device Identifier + * + * Return: 0 if all goes well and the device ID is valid, else return + * appropriate error + */ +int ti_sci_device_is_valid(uint32_t id) +{ + uint8_t unused; + + /* check the device state which will also tell us if the ID is valid */ + return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused); +} + +/** + * ti_sci_device_get_clcnt() - Get context loss counter + * + * @id: Device Identifier + * @count: Pointer to Context Loss counter to populate + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count) +{ + return ti_sci_device_get_state(id, count, NULL, NULL, NULL); +} + +/** + * ti_sci_device_is_idle() - Check if the device is requested to be idle + * + * @id: Device Identifier + * @r_state: true if requested to be idle + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_is_idle(uint32_t id, bool *r_state) +{ + int ret; + uint8_t state; + + if (!r_state) + return -EINVAL; + + ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL); + if (ret) + return ret; + + *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION); + + return 0; +} + +/** + * ti_sci_device_is_stop() - Check if the device is requested to be stopped + * + * @id: Device Identifier + * @r_state: true if requested to be stopped + * @curr_state: true if currently stopped + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state) +{ + int ret; + uint8_t p_state, c_state; + + if (!r_state && !curr_state) + return -EINVAL; + + ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state); + if (ret) + return ret; + + if (r_state) + *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF); + if (curr_state) + *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF); + + return 0; +} + +/** + * ti_sci_device_is_on() - Check if the device is requested to be ON + * + * @id: Device Identifier + * @r_state: true if requested to be ON + * @curr_state: true if currently ON and active + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state) +{ + int ret; + uint8_t p_state, c_state; + + if (!r_state && !curr_state) + return -EINVAL; + + ret = + ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state); + if (ret) + return ret; + + if (r_state) + *r_state = (p_state == MSG_DEVICE_SW_STATE_ON); + if (curr_state) + *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON); + + return 0; +} + +/** + * ti_sci_device_is_trans() - Check if the device is currently transitioning + * + * @id: Device Identifier + * @curr_state: true if currently transitioning + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_is_trans(uint32_t id, bool *curr_state) +{ + int ret; + uint8_t state; + + if (!curr_state) + return -EINVAL; + + ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state); + if (ret) + return ret; + + *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS); + + return 0; +} + +/** + * ti_sci_device_set_resets() - Set resets for device managed by TISCI + * + * @id: Device Identifier + * @reset_state: Device specific reset bit field + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state) +{ + struct ti_sci_msg_req_set_device_resets req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.id = id; + req.resets = reset_state; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_device_get_resets() - Get reset state for device managed by TISCI + * + * @id: Device Identifier + * @reset_state: Pointer to reset state to populate + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state) +{ + return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL); +} + +/** + * ti_sci_clock_set_state() - Set clock state helper + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request, + * Each device has its own set of clock inputs, This indexes + * which clock input to modify + * @flags: Header flags as needed + * @state: State to request for the clock + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id, + uint32_t flags, uint8_t state) +{ + struct ti_sci_msg_req_set_clock_state req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE, flags, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.request_state = state; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_clock_get_state() - Get clock state helper + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @programmed_state: State requested for clock to move to + * @current_state: State that the clock is currently in + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id, + uint8_t *programmed_state, + uint8_t *current_state) +{ + struct ti_sci_msg_req_get_clock_state req; + struct ti_sci_msg_resp_get_clock_state resp; + + struct ti_sci_xfer xfer; + int ret; + + if (!programmed_state && !current_state) + return -EINVAL; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + if (programmed_state) + *programmed_state = resp.programmed_state; + if (current_state) + *current_state = resp.current_state; + + return 0; +} + +/** + * ti_sci_clock_get() - Get control of a clock from TI SCI + + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @needs_ssc: 'true' iff Spread Spectrum clock is desired + * @can_change_freq: 'true' iff frequency change is desired + * @enable_input_term: 'true' iff input termination is desired + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id, + bool needs_ssc, bool can_change_freq, + bool enable_input_term) +{ + uint32_t flags = 0; + + flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0; + flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0; + flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0; + + return ti_sci_clock_set_state(dev_id, clk_id, flags, + MSG_CLOCK_SW_STATE_REQ); +} + +/** + * ti_sci_clock_idle() - Idle a clock which is in our control + + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * + * NOTE: This clock must have been requested by get_clock previously. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id) +{ + return ti_sci_clock_set_state(dev_id, clk_id, 0, + MSG_CLOCK_SW_STATE_UNREQ); +} + +/** + * ti_sci_clock_put() - Release a clock from our control + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * + * NOTE: This clock must have been requested by get_clock previously. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id) +{ + return ti_sci_clock_set_state(dev_id, clk_id, 0, + MSG_CLOCK_SW_STATE_AUTO); +} + +/** + * ti_sci_clock_is_auto() - Is the clock being auto managed + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is auto managed + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state) +{ + uint8_t state = 0; + int ret; + + if (!req_state) + return -EINVAL; + + ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL); + if (ret) + return ret; + + *req_state = (state == MSG_CLOCK_SW_STATE_AUTO); + + return 0; +} + +/** + * ti_sci_clock_is_on() - Is the clock ON + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is managed by us and enabled + * @curr_state: state indicating if the clock is ready for operation + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id, + bool *req_state, bool *curr_state) +{ + uint8_t c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) + return -EINVAL; + + ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state); + if (ret) + return ret; + + if (req_state) + *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ); + if (curr_state) + *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY); + + return 0; +} + +/** + * ti_sci_clock_is_off() - Is the clock OFF + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is managed by us and disabled + * @curr_state: state indicating if the clock is NOT ready for operation + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id, + bool *req_state, bool *curr_state) +{ + uint8_t c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) + return -EINVAL; + + ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state); + if (ret) + return ret; + + if (req_state) + *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ); + if (curr_state) + *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY); + + return 0; +} + +/** + * ti_sci_clock_set_parent() - Set the clock source of a specific device clock + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: Parent clock identifier to set + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id) +{ + struct ti_sci_msg_req_set_clock_parent req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.parent_id = parent_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_clock_get_parent() - Get current parent clock source + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: Current clock parent + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id) +{ + struct ti_sci_msg_req_get_clock_parent req; + struct ti_sci_msg_resp_get_clock_parent resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + *parent_id = resp.parent_id; + + return 0; +} + +/** + * ti_sci_clock_get_num_parents() - Get num parents of the current clk source + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @num_parents: Returns he number of parents to the current clock. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id, + uint8_t *num_parents) +{ + struct ti_sci_msg_req_get_clock_num_parents req; + struct ti_sci_msg_resp_get_clock_num_parents resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + *num_parents = resp.num_parents; + + return 0; +} + +/** + * ti_sci_clock_get_match_freq() - Find a good match for frequency + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @match_freq: Frequency match in Hz response. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, + uint64_t max_freq, uint64_t *match_freq) +{ + struct ti_sci_msg_req_query_clock_freq req; + struct ti_sci_msg_resp_query_clock_freq resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.min_freq_hz = min_freq; + req.target_freq_hz = target_freq; + req.max_freq_hz = max_freq; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + *match_freq = resp.freq_hz; + + return 0; +} + +/** + * ti_sci_clock_set_freq() - Set a frequency for clock + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq, + uint64_t target_freq, uint64_t max_freq) +{ + struct ti_sci_msg_req_set_clock_freq req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + req.min_freq_hz = min_freq; + req.target_freq_hz = target_freq; + req.max_freq_hz = max_freq; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_clock_get_freq() - Get current frequency + * + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @freq: Currently frequency in Hz + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq) +{ + struct ti_sci_msg_req_get_clock_freq req; + struct ti_sci_msg_resp_get_clock_freq resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + *freq = resp.freq_hz; + + return 0; +} + +/** + * ti_sci_core_reboot() - Command to request system reset + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_core_reboot(void) +{ + struct ti_sci_msg_req_reboot req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_proc_request() - Request a physical processor control + * + * @proc_id: Processor ID this request is for + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_request(uint8_t proc_id) +{ + struct ti_sci_msg_req_proc_request req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_proc_release() - Release a physical processor control + * + * @proc_id: Processor ID this request is for + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_release(uint8_t proc_id) +{ + struct ti_sci_msg_req_proc_release req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_proc_handover() - Handover a physical processor control to a host in + * the processor's access control list. + * + * @proc_id: Processor ID this request is for + * @host_id: Host ID to get the control of the processor + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id) +{ + struct ti_sci_msg_req_proc_handover req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.host_id = host_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags + * + * @proc_id: Processor ID this request is for + * @config_flags_set: Configuration flags to be set + * @config_flags_clear: Configuration flags to be cleared + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector, + uint32_t config_flags_set, + uint32_t config_flags_clear) +{ + struct ti_sci_msg_req_set_proc_boot_config req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK; + req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >> + TISCI_ADDR_HIGH_SHIFT; + req.config_flags_set = config_flags_set; + req.config_flags_clear = config_flags_clear; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags + * + * @proc_id: Processor ID this request is for + * @control_flags_set: Control flags to be set + * @control_flags_clear: Control flags to be cleared + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set, + uint32_t control_flags_clear) +{ + struct ti_sci_msg_req_set_proc_boot_ctrl req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.control_flags_set = control_flags_set; + req.control_flags_clear = control_flags_clear; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_proc_set_boot_ctrl_no_wait() - Set the processor boot control flags + * without requesting or waiting for a + * response. + * + * @proc_id: Processor ID this request is for + * @control_flags_set: Control flags to be set + * @control_flags_clear: Control flags to be cleared + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id, + uint32_t control_flags_set, + uint32_t control_flags_clear) +{ + struct ti_sci_msg_req_set_proc_boot_ctrl req; + struct ti_sci_msg_hdr *hdr; + struct k3_sec_proxy_msg tx_message; + int ret; + + /* Ensure we have sane transfer size */ + if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE) + return -ERANGE; + + hdr = (struct ti_sci_msg_hdr *)&req; + hdr->seq = ++message_sequence; + hdr->type = TISCI_MSG_SET_PROC_BOOT_CTRL; + hdr->host = TI_SCI_HOST_ID; + /* Setup with NORESPONSE flag to keep response queue clean */ + hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE; + + req.processor_id = proc_id; + req.control_flags_set = control_flags_set; + req.control_flags_clear = control_flags_clear; + + tx_message.buf = (uint8_t *)&req; + tx_message.len = sizeof(req); + + /* Send message */ + ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &tx_message); + if (ret) { + ERROR("Message sending failed (%d)\n", ret); + return ret; + } + + /* Return without waiting for response */ + return 0; +} + +/** + * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the + * processor configuration flags + * + * @proc_id: Processor ID this request is for + * @cert_addr: Memory address at which payload image certificate is located + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr) +{ + struct ti_sci_msg_req_proc_auth_boot_image req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMIAGE, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK; + req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >> + TISCI_ADDR_HIGH_SHIFT; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_proc_get_boot_status() - Get the processor boot status + * + * @proc_id: Processor ID this request is for + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv, + uint32_t *cfg_flags, + uint32_t *ctrl_flags, + uint32_t *sts_flags) +{ + struct ti_sci_msg_req_get_proc_boot_status req; + struct ti_sci_msg_resp_get_proc_boot_status resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + *bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) | + (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) & + TISCI_ADDR_HIGH_MASK); + *cfg_flags = resp.config_flags; + *ctrl_flags = resp.control_flags; + *sts_flags = resp.status_flags; + + return 0; +} + +/** + * ti_sci_proc_wait_boot_status() - Wait for a processor boot status + * + * @proc_id: Processor ID this request is for + * @num_wait_iterations Total number of iterations we will check before + * we will timeout and give up + * @num_match_iterations How many iterations should we have continued + * status to account for status bits glitching. + * This is to make sure that match occurs for + * consecutive checks. This implies that the + * worst case should consider that the stable + * time should at the worst be num_wait_iterations + * num_match_iterations to prevent timeout. + * @delay_per_iteration_us Specifies how long to wait (in micro seconds) + * between each status checks. This is the minimum + * duration, and overhead of register reads and + * checks are on top of this and can vary based on + * varied conditions. + * @delay_before_iterations_us Specifies how long to wait (in micro seconds) + * before the very first check in the first + * iteration of status check loop. This is the + * minimum duration, and overhead of register + * reads and checks are. + * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 1. + * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 1. + * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 0. + * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 0. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations, + uint8_t num_match_iterations, + uint8_t delay_per_iteration_us, + uint8_t delay_before_iterations_us, + uint32_t status_flags_1_set_all_wait, + uint32_t status_flags_1_set_any_wait, + uint32_t status_flags_1_clr_all_wait, + uint32_t status_flags_1_clr_any_wait) +{ + struct ti_sci_msg_req_wait_proc_boot_status req; + struct ti_sci_msg_hdr resp; + + struct ti_sci_xfer xfer; + int ret; + + ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + req.processor_id = proc_id; + req.num_wait_iterations = num_wait_iterations; + req.num_match_iterations = num_match_iterations; + req.delay_per_iteration_us = delay_per_iteration_us; + req.delay_before_iterations_us = delay_before_iterations_us; + req.status_flags_1_set_all_wait = status_flags_1_set_all_wait; + req.status_flags_1_set_any_wait = status_flags_1_set_any_wait; + req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait; + req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait; + + ret = ti_sci_do_xfer(&xfer); + if (ret) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_proc_wait_boot_status_no_wait() - Wait for a processor boot status + * without requesting or waiting for + * a response. + * + * @proc_id: Processor ID this request is for + * @num_wait_iterations Total number of iterations we will check before + * we will timeout and give up + * @num_match_iterations How many iterations should we have continued + * status to account for status bits glitching. + * This is to make sure that match occurs for + * consecutive checks. This implies that the + * worst case should consider that the stable + * time should at the worst be num_wait_iterations + * num_match_iterations to prevent timeout. + * @delay_per_iteration_us Specifies how long to wait (in micro seconds) + * between each status checks. This is the minimum + * duration, and overhead of register reads and + * checks are on top of this and can vary based on + * varied conditions. + * @delay_before_iterations_us Specifies how long to wait (in micro seconds) + * before the very first check in the first + * iteration of status check loop. This is the + * minimum duration, and overhead of register + * reads and checks are. + * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 1. + * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 1. + * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 0. + * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 0. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id, + uint8_t num_wait_iterations, + uint8_t num_match_iterations, + uint8_t delay_per_iteration_us, + uint8_t delay_before_iterations_us, + uint32_t status_flags_1_set_all_wait, + uint32_t status_flags_1_set_any_wait, + uint32_t status_flags_1_clr_all_wait, + uint32_t status_flags_1_clr_any_wait) +{ + struct ti_sci_msg_req_wait_proc_boot_status req; + struct ti_sci_msg_hdr *hdr; + struct k3_sec_proxy_msg tx_message; + int ret; + + /* Ensure we have sane transfer size */ + if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE) + return -ERANGE; + + hdr = (struct ti_sci_msg_hdr *)&req; + hdr->seq = ++message_sequence; + hdr->type = TISCI_MSG_WAIT_PROC_BOOT_STATUS; + hdr->host = TI_SCI_HOST_ID; + /* Setup with NORESPONSE flag to keep response queue clean */ + hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE; + + req.processor_id = proc_id; + req.num_wait_iterations = num_wait_iterations; + req.num_match_iterations = num_match_iterations; + req.delay_per_iteration_us = delay_per_iteration_us; + req.delay_before_iterations_us = delay_before_iterations_us; + req.status_flags_1_set_all_wait = status_flags_1_set_all_wait; + req.status_flags_1_set_any_wait = status_flags_1_set_any_wait; + req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait; + req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait; + + tx_message.buf = (uint8_t *)&req; + tx_message.len = sizeof(req); + + /* Send message */ + ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &tx_message); + if (ret) { + ERROR("Message sending failed (%d)\n", ret); + return ret; + } + + /* Return without waiting for response */ + return 0; +} + +/** + * ti_sci_init() - Basic initialization + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_init(void) +{ + struct ti_sci_msg_resp_version rev_info; + int ret; + + ret = ti_sci_get_revision(&rev_info); + if (ret) { + ERROR("Unable to communicate with control firmware (%d)\n", ret); + return ret; + } + + INFO("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n", + rev_info.abi_major, rev_info.abi_minor, + rev_info.firmware_revision, + rev_info.firmware_description); + + return 0; +} diff --git a/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h new file mode 100644 index 0000000..c7b09b3 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h @@ -0,0 +1,216 @@ +/* + * Texas Instruments System Control Interface API + * Based on Linux and U-Boot implementation + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TI_SCI_H +#define TI_SCI_H + +#include +#include + +/** + * Device control operations + * + * - ti_sci_device_get - command to request for device managed by TISCI + * - ti_sci_device_get_exclusive - exclusively request a device + * - ti_sci_device_idle - Command to idle a device managed by TISCI + * - ti_sci_device_idle_exclusive - exclusively idle a device + * - ti_sci_device_put - command to release a device managed by TISCI + * - ti_sci_device_put_no_wait - release a device without waiting for response + * - ti_sci_device_is_valid - Is the device valid + * - ti_sci_device_get_clcnt - Get context loss counter + * @count: Pointer to Context Loss counter to populate + * - ti_sci_device_is_idle - Check if the device is requested to be idle + * @r_state: true if requested to be idle + * - ti_sci_device_is_stop - Check if the device is requested to be stopped + * @r_state: true if requested to be stopped + * @curr_state: true if currently stopped. + * - ti_sci_device_is_on - Check if the device is requested to be ON + * @r_state: true if requested to be ON + * @curr_state: true if currently ON and active + * - ti_sci_device_is_trans - Check if the device is currently transitioning + * @curr_state: true if currently transitioning. + * - ti_sci_device_set_resets - Command to set resets for + * device managed by TISCI + * @reset_state: Device specific reset bit field + * - ti_sci_device_get_resets - Get reset state for device managed by TISCI + * @reset_state: Pointer to reset state to populate + * + * NOTE: for all these functions, the following are generic in nature: + * @id: Device Identifier + * Returns 0 for successful request, else returns corresponding error message. + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + */ +int ti_sci_device_get(uint32_t id); +int ti_sci_device_get_exclusive(uint32_t id); +int ti_sci_device_idle(uint32_t id); +int ti_sci_device_idle_exclusive(uint32_t id); +int ti_sci_device_put(uint32_t id); +int ti_sci_device_put_no_wait(uint32_t id); +int ti_sci_device_is_valid(uint32_t id); +int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count); +int ti_sci_device_is_idle(uint32_t id, bool *r_state); +int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state); +int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state); +int ti_sci_device_is_trans(uint32_t id, bool *curr_state); +int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state); +int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state); + +/** + * Clock control operations + * + * - ti_sci_clock_get - Get control of a clock from TI SCI + * @needs_ssc: 'true' iff Spread Spectrum clock is desired + * @can_change_freq: 'true' iff frequency change is desired + * @enable_input_term: 'true' iff input termination is desired + * - ti_sci_clock_idle - Idle a clock which is in our control + * - ti_sci_clock_put - Release a clock from our control + * - ti_sci_clock_is_auto - Is the clock being auto managed + * @req_state: state indicating if the clock is auto managed + * - ti_sci_clock_is_on - Is the clock ON + * @req_state: state indicating if the clock is managed by us and enabled + * @curr_state: state indicating if the clock is ready for operation + * - ti_sci_clock_is_off - Is the clock OFF + * @req_state: state indicating if the clock is managed by us and disabled + * @curr_state: state indicating if the clock is NOT ready for operation + * - ti_sci_clock_set_parent - Set the clock source of a specific device clock + * @parent_id: Parent clock identifier to set + * - ti_sci_clock_get_parent - Get current parent clock source + * @parent_id: Current clock parent + * - ti_sci_clock_get_num_parents - Get num parents of the current clk source + * @num_parents: Returns he number of parents to the current clock. + * - ti_sci_clock_get_match_freq - Find a good match for frequency + * @match_freq: Frequency match in Hz response. + * - ti_sci_clock_set_freq - Set a frequency for clock + * - ti_sci_clock_get_freq - Get current frequency + * @freq: Currently frequency in Hz + * + * NOTE: for all these functions, the following are generic in nature: + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has its own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * Returns 0 for successful request, else returns corresponding error message. + * + * Request for the clock - NOTE: the client MUST maintain integrity of + * usage count by balancing get_clock with put_clock. No refcounting is + * managed by driver for that purpose. + */ +int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id, + bool needs_ssc, bool can_change_freq, + bool enable_input_term); +int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id); +int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id); +int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, + bool *req_state); +int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id, + bool *req_state, bool *curr_state); +int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id, + bool *req_state, bool *curr_state); +int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, + uint8_t parent_id); +int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, + uint8_t *parent_id); +int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id, + uint8_t *num_parents); +int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, + uint64_t max_freq, uint64_t *match_freq); +int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, + uint64_t max_freq); +int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq); + +/** + * Core control operations + * + * - ti_sci_core_reboot() - Command to request system reset + * + * Return: 0 if all went well, else returns appropriate error value. + */ +int ti_sci_core_reboot(void); + +/** + * Processor control operations + * + * - ti_sci_proc_request - Command to request a physical processor control + * - ti_sci_proc_release - Command to release a physical processor control + * - ti_sci_proc_handover - Command to handover a physical processor control to + * a host in the processor's access control list. + * @host_id: Host ID to get the control of the processor + * - ti_sci_proc_set_boot_cfg - Command to set the processor boot configuration flags + * @config_flags_set: Configuration flags to be set + * @config_flags_clear: Configuration flags to be cleared. + * - ti_sci_proc_set_boot_ctrl - Command to set the processor boot control flags + * @control_flags_set: Control flags to be set + * @control_flags_clear: Control flags to be cleared + * - ti_sci_proc_set_boot_ctrl_no_wait - Same as above without waiting for response + * - ti_sci_proc_auth_boot_image - Command to authenticate and load the image + * and then set the processor configuration flags. + * @cert_addr: Memory address at which payload image certificate is located. + * - ti_sci_proc_get_boot_status - Command to get the processor boot status + * - ti_sci_proc_wait_boot_status - Command to wait for a processor boot status + * - ti_sci_proc_wait_boot_status_no_wait - Same as above without waiting for response + * + * NOTE: for all these functions, the following are generic in nature: + * @proc_id: Processor ID + * Returns 0 for successful request, else returns corresponding error message. + */ +int ti_sci_proc_request(uint8_t proc_id); +int ti_sci_proc_release(uint8_t proc_id); +int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id); +int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector, + uint32_t config_flags_set, + uint32_t config_flags_clear); +int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set, + uint32_t control_flags_clear); +int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id, + uint32_t control_flags_set, + uint32_t control_flags_clear); +int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr); +int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv, + uint32_t *cfg_flags, + uint32_t *ctrl_flags, + uint32_t *sts_flags); +int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations, + uint8_t num_match_iterations, + uint8_t delay_per_iteration_us, + uint8_t delay_before_iterations_us, + uint32_t status_flags_1_set_all_wait, + uint32_t status_flags_1_set_any_wait, + uint32_t status_flags_1_clr_all_wait, + uint32_t status_flags_1_clr_any_wait); +int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id, + uint8_t num_wait_iterations, + uint8_t num_match_iterations, + uint8_t delay_per_iteration_us, + uint8_t delay_before_iterations_us, + uint32_t status_flags_1_set_all_wait, + uint32_t status_flags_1_set_any_wait, + uint32_t status_flags_1_clr_all_wait, + uint32_t status_flags_1_clr_any_wait); + +/** + * ti_sci_init() - Basic initialization + * + * Return: 0 if all goes good, else appropriate error message. + */ +int ti_sci_init(void); + +#endif /* TI_SCI_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h new file mode 100644 index 0000000..310bf45 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h @@ -0,0 +1,709 @@ +/* + * Texas Instruments System Control Interface (TISCI) Protocol + * + * Communication protocol with TI SCI hardware + * The system works in a message response protocol + * See: http://processors.wiki.ti.com/index.php/TISCI for details + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TI_SCI_PROTOCOL_H +#define TI_SCI_PROTOCOL_H + +#include + +/* Generic Messages */ +#define TI_SCI_MSG_ENABLE_WDT 0x0000 +#define TI_SCI_MSG_WAKE_RESET 0x0001 +#define TI_SCI_MSG_VERSION 0x0002 +#define TI_SCI_MSG_WAKE_REASON 0x0003 +#define TI_SCI_MSG_GOODBYE 0x0004 +#define TI_SCI_MSG_SYS_RESET 0x0005 + +/* Device requests */ +#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 +#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201 +#define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202 + +/* Clock requests */ +#define TI_SCI_MSG_SET_CLOCK_STATE 0x0100 +#define TI_SCI_MSG_GET_CLOCK_STATE 0x0101 +#define TI_SCI_MSG_SET_CLOCK_PARENT 0x0102 +#define TI_SCI_MSG_GET_CLOCK_PARENT 0x0103 +#define TI_SCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104 +#define TI_SCI_MSG_SET_CLOCK_FREQ 0x010c +#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d +#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e + +/* Processor Control Messages */ +#define TISCI_MSG_PROC_REQUEST 0xc000 +#define TISCI_MSG_PROC_RELEASE 0xc001 +#define TISCI_MSG_PROC_HANDOVER 0xc005 +#define TISCI_MSG_SET_PROC_BOOT_CONFIG 0xc100 +#define TISCI_MSG_SET_PROC_BOOT_CTRL 0xc101 +#define TISCI_MSG_PROC_AUTH_BOOT_IMIAGE 0xc120 +#define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400 +#define TISCI_MSG_WAIT_PROC_BOOT_STATUS 0xc401 + +/** + * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses + * @type: Type of messages: One of TI_SCI_MSG* values + * @host: Host of the message + * @seq: Message identifier indicating a transfer sequence + * @flags: Flag for the message + */ +struct ti_sci_msg_hdr { + uint16_t type; + uint8_t host; + uint8_t seq; +#define TI_SCI_MSG_FLAG(val) (1 << (val)) +#define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0 +#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0) +#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1) +#define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0 +#define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1) + /* Additional Flags */ + uint32_t flags; +} __packed; + +/** + * struct ti_sci_msg_resp_version - Response for a message + * @hdr: Generic header + * @firmware_description: String describing the firmware + * @firmware_revision: Firmware revision + * @abi_major: Major version of the ABI that firmware supports + * @abi_minor: Minor version of the ABI that firmware supports + * + * In general, ABI version changes follow the rule that minor version increments + * are backward compatible. Major revision changes in ABI may not be + * backward compatible. + * + * Response to a generic message with message type TI_SCI_MSG_VERSION + */ +struct ti_sci_msg_resp_version { + struct ti_sci_msg_hdr hdr; +#define FIRMWARE_DESCRIPTION_LENGTH 32 + char firmware_description[FIRMWARE_DESCRIPTION_LENGTH]; + uint16_t firmware_revision; + uint8_t abi_major; + uint8_t abi_minor; +} __packed; + +/** + * struct ti_sci_msg_req_reboot - Reboot the SoC + * @hdr: Generic Header + * @domain: Domain to be reset, 0 for full SoC reboot + * + * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_reboot { + struct ti_sci_msg_hdr hdr; +#define TI_SCI_DOMAIN_FULL_SOC_RESET 0x0 + uint8_t domain; +} __packed; + +/** + * struct ti_sci_msg_req_set_device_state - Set the desired state of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @reserved: Reserved space in message, must be 0 for backward compatibility + * @state: The desired state of the device. + * + * Certain flags can also be set to alter the device state: + * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source. + * The meaning of this flag will vary slightly from device to device and from + * SoC to SoC but it generally allows the device to wake the SoC out of deep + * suspend states. + * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device. + * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed + * with STATE_RETENTION or STATE_ON, it will claim the device exclusively. + * If another host already has this device set to STATE_RETENTION or STATE_ON, + * the message will fail. Once successful, other hosts attempting to set + * STATE_RETENTION or STATE_ON will fail. + * + * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + uint32_t id; + uint32_t reserved; + +#define MSG_DEVICE_SW_STATE_AUTO_OFF 0 +#define MSG_DEVICE_SW_STATE_RETENTION 1 +#define MSG_DEVICE_SW_STATE_ON 2 + uint8_t state; +} __packed; + +/** + * struct ti_sci_msg_req_get_device_state - Request to get device. + * @hdr: Generic header + * @id: Device Identifier + * + * Request type is TI_SCI_MSG_GET_DEVICE_STATE, responded device state + * information + */ +struct ti_sci_msg_req_get_device_state { + struct ti_sci_msg_hdr hdr; + uint32_t id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_device_state - Response to get device request. + * @hdr: Generic header + * @context_loss_count: Indicates how many times the device has lost context. A + * driver can use this monotonic counter to determine if the device has + * lost context since the last time this message was exchanged. + * @resets: Programmed state of the reset lines. + * @programmed_state: The state as programmed by set_device. + * - Uses the MSG_DEVICE_SW_* macros + * @current_state: The actual state of the hardware. + * + * Response to request TI_SCI_MSG_GET_DEVICE_STATE. + */ +struct ti_sci_msg_resp_get_device_state { + struct ti_sci_msg_hdr hdr; + uint32_t context_loss_count; + uint32_t resets; + uint8_t programmed_state; +#define MSG_DEVICE_HW_STATE_OFF 0 +#define MSG_DEVICE_HW_STATE_ON 1 +#define MSG_DEVICE_HW_STATE_TRANS 2 + uint8_t current_state; +} __packed; + +/** + * struct ti_sci_msg_req_set_device_resets - Set the desired resets + * configuration of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @resets: A bit field of resets for the device. The meaning, behavior, + * and usage of the reset flags are device specific. 0 for a bit + * indicates releasing the reset represented by that bit while 1 + * indicates keeping it held. + * + * Request type is TI_SCI_MSG_SET_DEVICE_RESETS, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_resets { + struct ti_sci_msg_hdr hdr; + uint32_t id; + uint32_t resets; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_state - Request to setup a Clock state + * @hdr: Generic Header, Certain flags can be set specific to the clocks: + * MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified + * via spread spectrum clocking. + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's + * frequency to be changed while it is running so long as it + * is within the min/max limits. + * MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this + * is only applicable to clock inputs on the SoC pseudo-device. + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @request_state: Request the state for the clock to be set to. + * MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock, + * it can be disabled, regardless of the state of the device + * MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to + * automatically manage the state of this clock. If the device + * is enabled, then the clock is enabled. If the device is set + * to off or retention, then the clock is internally set as not + * being required by the device.(default) + * MSG_CLOCK_SW_STATE_REQ: Configure the clock to be enabled, + * regardless of the state of the device. + * + * Normally, all required clocks are managed by TISCI entity, this is used + * only for specific control *IF* required. Auto managed state is + * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote + * will explicitly control. + * + * Request type is TI_SCI_MSG_SET_CLOCK_STATE, response is a generic + * ACK or NACK message. + */ +struct ti_sci_msg_req_set_clock_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_CLOCK_ALLOW_SSC TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_CLOCK_INPUT_TERM TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +#define MSG_CLOCK_SW_STATE_UNREQ 0 +#define MSG_CLOCK_SW_STATE_AUTO 1 +#define MSG_CLOCK_SW_STATE_REQ 2 + uint8_t request_state; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_state - Request for clock state + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get state of. + * + * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state + * of the clock + */ +struct ti_sci_msg_req_get_clock_state { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_state - Response to get clock state + * @hdr: Generic Header + * @programmed_state: Any programmed state of the clock. This is one of + * MSG_CLOCK_SW_STATE* values. + * @current_state: Current state of the clock. This is one of: + * MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready + * MSG_CLOCK_HW_STATE_READY: Clock is ready + * + * Response to TI_SCI_MSG_GET_CLOCK_STATE. + */ +struct ti_sci_msg_resp_get_clock_state { + struct ti_sci_msg_hdr hdr; + uint8_t programmed_state; +#define MSG_CLOCK_HW_STATE_NOT_READY 0 +#define MSG_CLOCK_HW_STATE_READY 1 + uint8_t current_state; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_parent - Set the clock parent + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: The new clock parent is selectable by an index via this + * parameter. + * + * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic + * ACK / NACK message. + */ +struct ti_sci_msg_req_set_clock_parent { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; + uint8_t parent_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_parent - Get the clock parent + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get the parent for. + * + * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information + */ +struct ti_sci_msg_req_get_clock_parent { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent + * @hdr: Generic Header + * @parent_id: The current clock parent + * + * Response to TI_SCI_MSG_GET_CLOCK_PARENT. + */ +struct ti_sci_msg_resp_get_clock_parent { + struct ti_sci_msg_hdr hdr; + uint8_t parent_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents + * @hdr: Generic header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * + * This request provides information about how many clock parent options + * are available for a given clock to a device. This is typically used + * for input clocks. + * + * Request type is TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_get_clock_num_parents { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents + * @hdr: Generic header + * @num_parents: Number of clock parents + * + * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS + */ +struct ti_sci_msg_resp_get_clock_num_parents { + struct ti_sci_msg_hdr hdr; + uint8_t num_parents; +} __packed; + +/** + * struct ti_sci_msg_req_query_clock_freq - Request to query a frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq_hz: The target clock frequency. A frequency will be found + * as close to this target frequency as possible. + * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested frequency within provided range and responds with + * result message. + * + * Request type is TI_SCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message, + * or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_query_clock_freq { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint64_t min_freq_hz; + uint64_t target_freq_hz; + uint64_t max_freq_hz; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_query_clock_freq - Response to a clock frequency query + * @hdr: Generic Header + * @freq_hz: Frequency that is the best match in Hz. + * + * Response to request type TI_SCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request + * cannot be satisfied, the message will be of type NACK. + */ +struct ti_sci_msg_resp_query_clock_freq { + struct ti_sci_msg_hdr hdr; + uint64_t freq_hz; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_freq - Request to setup a clock frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq_hz: The target clock frequency. The clock will be programmed + * at a rate as close to this target frequency as possible. + * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested range and responds with success/failure message. + * + * This sets the desired frequency for a clock within an allowable + * range. This message will fail on an enabled clock unless + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally, + * if other clocks have their frequency modified due to this message, + * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled. + * + * Calling set frequency on a clock input to the SoC pseudo-device will + * inform the PMMC of that clock's frequency. Setting a frequency of + * zero will indicate the clock is disabled. + * + * Calling set frequency on clock outputs from the SoC pseudo-device will + * function similarly to setting the clock frequency on a device. + * + * Request type is TI_SCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_clock_freq { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint64_t min_freq_hz; + uint64_t target_freq_hz; + uint64_t max_freq_hz; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In some cases, clock frequencies are configured by host. + * + * Request type is TI_SCI_MSG_GET_CLOCK_FREQ, responded with clock frequency + * that the clock is currently at. + */ +struct ti_sci_msg_req_get_clock_freq { + struct ti_sci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_freq - Response of clock frequency request + * @hdr: Generic Header + * @freq_hz: Frequency that the clock is currently on, in Hz. + * + * Response to request type TI_SCI_MSG_GET_CLOCK_FREQ. + */ +struct ti_sci_msg_resp_get_clock_freq { + struct ti_sci_msg_hdr hdr; + uint64_t freq_hz; +} __packed; + +#define TISCI_ADDR_LOW_MASK 0x00000000ffffffff +#define TISCI_ADDR_HIGH_MASK 0xffffffff00000000 +#define TISCI_ADDR_HIGH_SHIFT 32 + +/** + * struct ti_sci_msg_req_proc_request - Request a processor + * + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_PROC_REQUEST, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_request { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/** + * struct ti_sci_msg_req_proc_release - Release a processor + * + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_PROC_RELEASE, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_release { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/** + * struct ti_sci_msg_req_proc_handover - Handover a processor to a host + * + * @hdr: Generic Header + * @processor_id: ID of processor + * @host_id: New Host we want to give control to + * + * Request type is TISCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_handover { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint8_t host_id; +} __packed; + +/* A53 Config Flags */ +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPIDEN 0x00000004 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPNIDEN 0x00000008 +#define PROC_BOOT_CFG_FLAG_ARMV8_AARCH32 0x00000100 + +/* R5 Config Flags */ +#define PROC_BOOT_CFG_FLAG_R5_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_R5_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_R5_LOCKSTEP 0x00000100 +#define PROC_BOOT_CFG_FLAG_R5_TEINIT 0x00000200 +#define PROC_BOOT_CFG_FLAG_R5_NMFI_EN 0x00000400 +#define PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE 0x00000800 +#define PROC_BOOT_CFG_FLAG_R5_BTCM_EN 0x00001000 +#define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000 + +/** + * struct ti_sci_msg_req_set_proc_boot_config - Set Processor boot configuration + * @hdr: Generic Header + * @processor_id: ID of processor + * @bootvector_low: Lower 32bit (Little Endian) of boot vector + * @bootvector_high: Higher 32bit (Little Endian) of boot vector + * @config_flags_set: Optional Processor specific Config Flags to set. + * Setting a bit here implies required bit sets to 1. + * @config_flags_clear: Optional Processor specific Config Flags to clear. + * Setting a bit here implies required bit gets cleared. + * + * Request type is TISCI_MSG_SET_PROC_BOOT_CONFIG, response is a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_proc_boot_config { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint32_t bootvector_low; + uint32_t bootvector_high; + uint32_t config_flags_set; + uint32_t config_flags_clear; +} __packed; + +/* ARMV8 Control Flags */ +#define PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM 0x00000001 +#define PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS 0x00000002 +#define PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ 0x00000100 + +/* R5 Control Flags */ +#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001 + +/** + * struct ti_sci_msg_req_set_proc_boot_ctrl - Set Processor boot control flags + * @hdr: Generic Header + * @processor_id: ID of processor + * @config_flags_set: Optional Processor specific Config Flags to set. + * Setting a bit here implies required bit sets to 1. + * @config_flags_clear: Optional Processor specific Config Flags to clear. + * Setting a bit here implies required bit gets cleared. + * + * Request type is TISCI_MSG_SET_PROC_BOOT_CTRL, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_proc_boot_ctrl { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint32_t control_flags_set; + uint32_t control_flags_clear; +} __packed; + +/** + * struct ti_sci_msg_req_proc_auth_start_image - Authenticate and start image + * @hdr: Generic Header + * @processor_id: ID of processor + * @cert_addr_low: Lower 32bit (Little Endian) of certificate + * @cert_addr_high: Higher 32bit (Little Endian) of certificate + * + * Request type is TISCI_MSG_PROC_AUTH_BOOT_IMAGE, response is a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_proc_auth_boot_image { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint32_t cert_addr_low; + uint32_t cert_addr_high; +} __packed; + +/** + * struct ti_sci_msg_req_get_proc_boot_status - Get processor boot status + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_GET_PROC_BOOT_STATUS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_get_proc_boot_status { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/* ARMv8 Status Flags */ +#define PROC_BOOT_STATUS_FLAG_ARMV8_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_ARMV8_WFI 0x00000002 +#define PROC_BOOT_STATUS_FLAG_ARMV8_L2F_DONE 0x00000010 +#define PROC_BOOT_STATUS_FLAG_ARMV8_STANDBYWFIL2 0x00000020 + +/* R5 Status Flags */ +#define PROC_BOOT_STATUS_FLAG_R5_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002 +#define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED 0x00000004 +#define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED 0x00000100 + +/** + * \brief Processor Status Response + * struct ti_sci_msg_resp_get_proc_boot_status - Processor boot status response + * @hdr: Generic Header + * @processor_id: ID of processor + * @bootvector_low: Lower 32bit (Little Endian) of boot vector + * @bootvector_high: Higher 32bit (Little Endian) of boot vector + * @config_flags: Optional Processor specific Config Flags set. + * @control_flags: Optional Processor specific Control Flags. + * @status_flags: Optional Processor specific Status Flags set. + * + * Response to TISCI_MSG_GET_PROC_BOOT_STATUS. + */ +struct ti_sci_msg_resp_get_proc_boot_status { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint32_t bootvector_low; + uint32_t bootvector_high; + uint32_t config_flags; + uint32_t control_flags; + uint32_t status_flags; +} __packed; + +/** + * struct ti_sci_msg_req_wait_proc_boot_status - Wait for a processor boot status + * @hdr: Generic Header + * @processor_id: ID of processor + * @num_wait_iterations Total number of iterations we will check before + * we will timeout and give up + * @num_match_iterations How many iterations should we have continued + * status to account for status bits glitching. + * This is to make sure that match occurs for + * consecutive checks. This implies that the + * worst case should consider that the stable + * time should at the worst be num_wait_iterations + * num_match_iterations to prevent timeout. + * @delay_per_iteration_us Specifies how long to wait (in micro seconds) + * between each status checks. This is the minimum + * duration, and overhead of register reads and + * checks are on top of this and can vary based on + * varied conditions. + * @delay_before_iterations_us Specifies how long to wait (in micro seconds) + * before the very first check in the first + * iteration of status check loop. This is the + * minimum duration, and overhead of register + * reads and checks are. + * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 1. + * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 1. + * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 0. + * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 0. + * + * Request type is TISCI_MSG_WAIT_PROC_BOOT_STATUS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_wait_proc_boot_status { + struct ti_sci_msg_hdr hdr; + uint8_t processor_id; + uint8_t num_wait_iterations; + uint8_t num_match_iterations; + uint8_t delay_per_iteration_us; + uint8_t delay_before_iterations_us; + uint32_t status_flags_1_set_all_wait; + uint32_t status_flags_1_set_any_wait; + uint32_t status_flags_1_clr_all_wait; + uint32_t status_flags_1_clr_any_wait; +} __packed; + +#endif /* TI_SCI_PROTOCOL_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c b/arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c new file mode 100644 index 0000000..457c95d --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2017-2018, 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 + +/* Table of regions to map using the MMU */ +const mmap_region_t plat_k3_mmap[] = { + MAP_REGION_FLAT(K3_USART_BASE, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(K3_GIC_BASE, K3_GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(K3_GTC_BASE, K3_GTC_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + { /* sentinel */ } +}; + +/* + * Placeholder variables for maintaining information about the next image(s) + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +static uint32_t k3_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +/******************************************************************************* + * Perform any BL3-1 early platform setup, such as console init and deciding on + * memory layout. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(arg0 == 0U); + assert(arg1 == 0U); + + bl31_console_setup(); + +#ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); +#endif + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); + bl33_image_ep_info.pc = PRELOADED_BL33_BASE; + bl33_image_ep_info.spsr = k3_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#ifdef K3_HW_CONFIG_BASE + /* + * According to the file ``Documentation/arm64/booting.txt`` of the + * Linux kernel tree, Linux expects the physical address of the device + * tree blob (DTB) in x0, while x1-x3 are reserved for future use and + * must be 0. + */ + bl33_image_ep_info.args.arg0 = (u_register_t)K3_HW_CONFIG_BASE; + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = 0U; + bl33_image_ep_info.args.arg3 = 0U; +#endif +} + +void bl31_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL31_START, BL31_SIZE, MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, MT_CODE | MT_RO | MT_SECURE), + MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE, MT_RO_DATA | MT_RO | MT_SECURE), +#if USE_COHERENT_MEM + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, MT_DEVICE | MT_RW | MT_SECURE), +#endif + { /* sentinel */ } + }; + + setup_page_tables(bl_regions, plat_k3_mmap); + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + k3_gic_driver_init(K3_GIC_BASE); + k3_gic_init(); + + ti_sci_init(); +} + +void platform_mem_init(void) +{ + /* Do nothing for now... */ +} + +unsigned int plat_get_syscnt_freq2(void) +{ + uint32_t gtc_freq; + uint32_t gtc_ctrl; + + /* Lets try and provide basic diagnostics - cost is low */ + gtc_ctrl = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTCR_OFFSET); + /* Did the bootloader fail to enable timer and OS guys are confused? */ + if ((gtc_ctrl & K3_GTC_CNTCR_EN_MASK) == 0U) { + ERROR("GTC is disabled! Timekeeping broken. Fix Bootloader\n"); + } + /* + * If debug will not pause time, we will have issues like + * drivers timing out while debugging, in cases of OS like Linux, + * RCU stall errors, which can be hard to differentiate vs real issues. + */ + if ((gtc_ctrl & K3_GTC_CNTCR_HDBG_MASK) == 0U) { + WARN("GTC: Debug access doesn't stop time. Fix Bootloader\n"); + } + + gtc_freq = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTFID0_OFFSET); + /* Many older bootloaders may have missed programming FID0 register */ + if (gtc_freq != 0U) { + return gtc_freq; + } + + /* + * We could have just warned about this, but this can have serious + * hard to debug side effects if we are NOT sure what the actual + * frequency is. Lets make sure people don't miss this. + */ + ERROR("GTC_CNTFID0 is 0! Assuming %d Hz. Fix Bootloader\n", + SYS_COUNTER_FREQ_IN_TICKS); + + return SYS_COUNTER_FREQ_IN_TICKS; +} + +/* + * Empty function to prevent the console from being uninitialized after BL33 is + * started and allow us to see messages from BL31. + */ +void bl31_plat_runtime_setup(void) +{ +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image + * for the security state specified. BL3-3 corresponds to the non-secure + * image type while BL3-2 corresponds to the secure image type. A NULL + * pointer is returned if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) ? &bl33_image_ep_info : + &bl32_image_ep_info; + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + + NOTICE("Requested nonexistent image\n"); + return NULL; +} diff --git a/arm-trusted-firmware/plat/ti/k3/common/k3_console.c b/arm-trusted-firmware/plat/ti/k3/common/k3_console.c new file mode 100644 index 0000000..8c44c17 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/k3_console.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +void bl31_console_setup(void) +{ + static console_t console; + + /* Initialize the console to provide early debug support */ + console_16550_register(K3_USART_BASE, K3_USART_CLK_SPEED, + K3_USART_BAUD, &console); +} diff --git a/arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c b/arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c new file mode 100644 index 0000000..1932eaa --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* The GICv3 driver only needs to be initialized in EL3 */ +uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t k3_interrupt_props[] = { + PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) +}; + +static unsigned int k3_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +gicv3_driver_data_t k3_gic_data = { + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .interrupt_props = k3_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(k3_interrupt_props), + .mpidr_to_core_pos = k3_mpidr_to_core_pos, +}; + +void k3_gic_driver_init(uintptr_t gic_base) +{ + /* GIC Distributor is always at the base of the IP */ + uintptr_t gicd_base = gic_base; + /* GIC Redistributor base is run-time detected */ + uintptr_t gicr_base = 0; + + for (unsigned int gicr_shift = 18; gicr_shift < 21; gicr_shift++) { + uintptr_t gicr_check = gic_base + BIT(gicr_shift); + uint32_t iidr = mmio_read_32(gicr_check + GICR_IIDR); + if (iidr != 0) { + /* Found the GICR base */ + gicr_base = gicr_check; + break; + } + } + /* Assert if we have not found the GICR base */ + assert(gicr_base != 0); + + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ + k3_gic_data.gicd_base = gicd_base; + k3_gic_data.gicr_base = gicr_base; + gicv3_driver_init(&k3_gic_data); +} + +void k3_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void k3_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void k3_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void k3_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S b/arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S new file mode 100644 index 0000000..f4f7d18 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#define K3_BOOT_REASON_COLD_RESET 0x1 + + /* ------------------------------------------------------------------ + * uintptr_t plat_get_my_entrypoint(void) + * ------------------------------------------------------------------ + * + * This function is called with the called with the MMU and caches + * disabled (SCTLR_EL3.M = 0 and SCTLR_EL3.C = 0). The function is + * responsible for distinguishing between a warm and cold reset for the + * current CPU using platform-specific means. If it's a warm reset, + * then it returns the warm reset entrypoint point provided to + * plat_setup_psci_ops() during BL31 initialization. If it's a cold + * reset then this function must return zero. + * + * This function does not follow the Procedure Call Standard used by + * the Application Binary Interface for the ARM 64-bit architecture. + * The caller should not assume that callee saved registers are + * preserved across a call to this function. + */ + .globl plat_get_my_entrypoint +func plat_get_my_entrypoint + ldr x0, k3_boot_reason_data_store + cmp x0, #K3_BOOT_REASON_COLD_RESET + + /* We ONLY support cold boot at this point */ + bne plat_unsupported_boot + mov x0, #0 + ret + + /* + * We self manage our boot reason. + * At load time, we have just a default reason - which is cold reset + */ +k3_boot_reason_data_store: + .word K3_BOOT_REASON_COLD_RESET + +plat_unsupported_boot: + b plat_unsupported_boot + +endfunc plat_get_my_entrypoint + + /* ------------------------------------------------------------------ + * unsigned int plat_my_core_pos(void) + * ------------------------------------------------------------------ + * + * This function returns the index of the calling CPU which is used as a + * CPU-specific linear index into blocks of memory (for example while + * allocating per-CPU stacks). This function will be invoked very early + * in the initialization sequence which mandates that this function + * should be implemented in assembly and should not rely on the + * avalability of a C runtime environment. This function can clobber x0 + * - x8 and must preserve x9 - x29. + * + * This function plays a crucial role in the power domain topology + * framework in PSCI and details of this can be found in Power Domain + * Topology Design. + */ + .globl plat_my_core_pos +func plat_my_core_pos + mrs x0, MPIDR_EL1 + + and x1, x0, #MPIDR_CLUSTER_MASK + lsr x1, x1, #MPIDR_AFF1_SHIFT + and x0, x0, #MPIDR_CPU_MASK + + cmp x1, 0 + b.eq out + add x0, x0, #K3_CLUSTER0_CORE_COUNT + + cmp x1, 1 + b.eq out + add x0, x0, #K3_CLUSTER1_CORE_COUNT + + cmp x1, 2 + b.eq out + add x0, x0, #K3_CLUSTER2_CORE_COUNT + +out: + ret +endfunc plat_my_core_pos + + /* -------------------------------------------------------------------- + * This handler does the following: + * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72 + * -------------------------------------------------------------------- + */ + .globl plat_reset_handler +func plat_reset_handler + /* Only on Cortex-A72 */ + jump_if_cpu_midr CORTEX_A72_MIDR, a72 + ret + + /* Cortex-A72 specific settings */ +a72: + mrs x0, CORTEX_A72_L2CTLR_EL1 + orr x0, x0, #(CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) + msr CORTEX_A72_L2CTLR_EL1, x0 + isb + ret +endfunc plat_reset_handler + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + * --------------------------------------------- + */ + .globl plat_crash_console_init +func plat_crash_console_init + mov_imm x0, CRASH_CONSOLE_BASE + mov_imm x1, CRASH_CONSOLE_CLK + mov_imm x2, CRASH_CONSOLE_BAUD_RATE + mov w3, #0x0 + b console_16550_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(void) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ + .globl plat_crash_console_putc +func plat_crash_console_putc + mov_imm x1, CRASH_CONSOLE_BASE + b console_16550_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ + .globl plat_crash_console_flush +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_16550_core_flush +endfunc plat_crash_console_flush diff --git a/arm-trusted-firmware/plat/ti/k3/common/k3_psci.c b/arm-trusted-firmware/plat/ti/k3/common/k3_psci.c new file mode 100644 index 0000000..0500740 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/k3_psci.c @@ -0,0 +1,256 @@ +/* + * 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 + +#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +uintptr_t k3_sec_entrypoint; + +static void k3_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr; + + scr = read_scr_el3(); + /* Enable the Non secure interrupt to wake the CPU */ + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + isb(); + /* dsb is good practice before using wfi to enter low power states */ + dsb(); + /* Enter standby state */ + wfi(); + /* Restore SCR */ + write_scr_el3(scr); +} + +static int k3_pwr_domain_on(u_register_t mpidr) +{ + int core, proc_id, device_id, ret; + + core = plat_core_pos_by_mpidr(mpidr); + if (core < 0) { + ERROR("Could not get target core id: %d\n", core); + return PSCI_E_INTERN_FAIL; + } + + proc_id = PLAT_PROC_START_ID + core; + device_id = PLAT_PROC_DEVICE_START_ID + core; + + ret = ti_sci_proc_request(proc_id); + if (ret) { + ERROR("Request for processor failed: %d\n", ret); + return PSCI_E_INTERN_FAIL; + } + + ret = ti_sci_proc_set_boot_cfg(proc_id, k3_sec_entrypoint, 0, 0); + if (ret) { + ERROR("Request to set core boot address failed: %d\n", ret); + return PSCI_E_INTERN_FAIL; + } + + /* sanity check these are off before starting a core */ + ret = ti_sci_proc_set_boot_ctrl(proc_id, + 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ | + PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS | + PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM); + if (ret) { + ERROR("Request to clear boot configuration failed: %d\n", ret); + return PSCI_E_INTERN_FAIL; + } + + ret = ti_sci_device_get(device_id); + if (ret) { + ERROR("Request to start core failed: %d\n", ret); + return PSCI_E_INTERN_FAIL; + } + + return PSCI_E_SUCCESS; +} + +void k3_pwr_domain_off(const psci_power_state_t *target_state) +{ + int core, cluster, proc_id, device_id, cluster_id, ret; + + /* At very least the local core should be powering down */ + assert(CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE); + + /* Prevent interrupts from spuriously waking up this cpu */ + k3_gic_cpuif_disable(); + + core = plat_my_core_pos(); + cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1()); + proc_id = PLAT_PROC_START_ID + core; + device_id = PLAT_PROC_DEVICE_START_ID + core; + cluster_id = PLAT_CLUSTER_DEVICE_START_ID + (cluster * 2); + + /* + * If we are the last core in the cluster then we take a reference to + * the cluster device so that it does not get shutdown before we + * execute the entire cluster L2 cleaning sequence below. + */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + ret = ti_sci_device_get(cluster_id); + if (ret) { + ERROR("Request to get cluster failed: %d\n", ret); + return; + } + } + + /* Start by sending wait for WFI command */ + ret = ti_sci_proc_wait_boot_status_no_wait(proc_id, + /* + * Wait maximum time to give us the best chance to get + * to WFI before this command timeouts + */ + UINT8_MAX, 100, UINT8_MAX, UINT8_MAX, + /* Wait for WFI */ + PROC_BOOT_STATUS_FLAG_ARMV8_WFI, 0, 0, 0); + if (ret) { + ERROR("Sending wait for WFI failed (%d)\n", ret); + return; + } + + /* Now queue up the core shutdown request */ + ret = ti_sci_device_put_no_wait(device_id); + if (ret) { + ERROR("Sending core shutdown message failed (%d)\n", ret); + return; + } + + /* If our cluster is not going down we stop here */ + if (CLUSTER_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + /* set AINACTS */ + ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id, + PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS, 0); + if (ret) { + ERROR("Sending set control message failed (%d)\n", ret); + return; + } + + /* set L2FLUSHREQ */ + ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id, + PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ, 0); + if (ret) { + ERROR("Sending set control message failed (%d)\n", ret); + return; + } + + /* wait for L2FLUSHDONE*/ + ret = ti_sci_proc_wait_boot_status_no_wait(proc_id, + UINT8_MAX, 2, UINT8_MAX, UINT8_MAX, + PROC_BOOT_STATUS_FLAG_ARMV8_L2F_DONE, 0, 0, 0); + if (ret) { + ERROR("Sending wait message failed (%d)\n", ret); + return; + } + + /* clear L2FLUSHREQ */ + ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id, + 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ); + if (ret) { + ERROR("Sending set control message failed (%d)\n", ret); + return; + } + + /* set ACINACTM */ + ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id, + PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM, 0); + if (ret) { + ERROR("Sending set control message failed (%d)\n", ret); + return; + } + + /* wait for STANDBYWFIL2 */ + ret = ti_sci_proc_wait_boot_status_no_wait(proc_id, + UINT8_MAX, 2, UINT8_MAX, UINT8_MAX, + PROC_BOOT_STATUS_FLAG_ARMV8_STANDBYWFIL2, 0, 0, 0); + if (ret) { + ERROR("Sending wait message failed (%d)\n", ret); + return; + } + + /* Now queue up the cluster shutdown request */ + ret = ti_sci_device_put_no_wait(cluster_id); + if (ret) { + ERROR("Sending cluster shutdown message failed (%d)\n", ret); + return; + } +} + +void k3_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* TODO: Indicate to System firmware about completion */ + + k3_gic_pcpu_init(); + k3_gic_cpuif_enable(); +} + +static void __dead2 k3_system_off(void) +{ + ERROR("System Off: operation not handled.\n"); + while (true) + wfi(); +} + +static void __dead2 k3_system_reset(void) +{ + /* Send the system reset request to system firmware */ + ti_sci_core_reboot(); + + while (true) + wfi(); +} + +static int k3_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + /* TODO: perform the proper validation */ + + return PSCI_E_SUCCESS; +} + +static int k3_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* TODO: perform the proper validation */ + + return PSCI_E_SUCCESS; +} + +static const plat_psci_ops_t k3_plat_psci_ops = { + .cpu_standby = k3_cpu_standby, + .pwr_domain_on = k3_pwr_domain_on, + .pwr_domain_off = k3_pwr_domain_off, + .pwr_domain_on_finish = k3_pwr_domain_on_finish, + .system_off = k3_system_off, + .system_reset = k3_system_reset, + .validate_power_state = k3_validate_power_state, + .validate_ns_entrypoint = k3_validate_ns_entrypoint +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + k3_sec_entrypoint = sec_entrypoint; + + *psci_ops = &k3_plat_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/ti/k3/common/k3_topology.c b/arm-trusted-firmware/plat/ti/k3/common/k3_topology.c new file mode 100644 index 0000000..139f1fd --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/k3_topology.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[] = { + PLATFORM_SYSTEM_COUNT, + PLATFORM_CLUSTER_COUNT, + K3_CLUSTER0_CORE_COUNT, + K3_CLUSTER1_CORE_COUNT, + K3_CLUSTER2_CORE_COUNT, + K3_CLUSTER3_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + if (MPIDR_AFFLVL3_VAL(mpidr) > 0 || + MPIDR_AFFLVL2_VAL(mpidr) > 0) { + return -1; + } + + if (cluster > 0) + core += K3_CLUSTER0_CORE_COUNT; + if (cluster > 1) + core += K3_CLUSTER1_CORE_COUNT; + if (cluster > 2) + core += K3_CLUSTER2_CORE_COUNT; + if (cluster > 3) + return -1; + + return core; +} diff --git a/arm-trusted-firmware/plat/ti/k3/common/plat_common.mk b/arm-trusted-firmware/plat/ti/k3/common/plat_common.mk new file mode 100644 index 0000000..ab7366b --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/plat_common.mk @@ -0,0 +1,91 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# We don't use BL1 or BL2, so BL31 is the first image to execute +RESET_TO_BL31 := 1 +# Only one core starts up at first +COLD_BOOT_SINGLE_CPU := 1 +# We can choose where a core starts executing +PROGRAMMABLE_RESET_ADDRESS:= 1 + +# ARM coherency is managed in hardware +WARMBOOT_ENABLE_DCACHE_EARLY := 1 + +# A53 erratum for SoC. (enable them all) +ERRATA_A53_826319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 + +# A72 Erratum for SoC +ERRATA_A72_859971 := 1 +ERRATA_A72_1319367 := 1 + +CRASH_REPORTING := 1 +HANDLE_EA_EL3_FIRST := 1 + +# Split out RO data into a non-executable section +SEPARATE_CODE_AND_RODATA := 1 + +# Generate a Position Independent Executable +ENABLE_PIE := 1 + +TI_16550_MDR_QUIRK := 1 +$(eval $(call add_define,TI_16550_MDR_QUIRK)) + +K3_USART := 0 +$(eval $(call add_define,K3_USART)) + +# Allow customizing the UART baud rate +K3_USART_BAUD := 115200 +$(eval $(call add_define,K3_USART_BAUD)) + +# Libraries +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_INCLUDES += \ + -I${PLAT_PATH}/include \ + -I${PLAT_PATH}/common/drivers/sec_proxy \ + -I${PLAT_PATH}/common/drivers/ti_sci \ + +K3_CONSOLE_SOURCES += \ + drivers/ti/uart/aarch64/16550_console.S \ + ${PLAT_PATH}/common/k3_console.c \ + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +K3_GIC_SOURCES += \ + ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + ${PLAT_PATH}/common/k3_gicv3.c \ + +K3_PSCI_SOURCES += \ + plat/common/plat_psci_common.c \ + ${PLAT_PATH}/common/k3_psci.c \ + +K3_SEC_PROXY_SOURCES += \ + ${PLAT_PATH}/common/drivers/sec_proxy/sec_proxy.c \ + +K3_TI_SCI_SOURCES += \ + ${PLAT_PATH}/common/drivers/ti_sci/ti_sci.c \ + +PLAT_BL_COMMON_SOURCES += \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + ${XLAT_TABLES_LIB_SRCS} \ + ${K3_CONSOLE_SOURCES} \ + +BL31_SOURCES += \ + ${PLAT_PATH}/common/k3_bl31_setup.c \ + ${PLAT_PATH}/common/k3_helpers.S \ + ${PLAT_PATH}/common/k3_topology.c \ + ${K3_GIC_SOURCES} \ + ${K3_PSCI_SOURCES} \ + ${K3_SEC_PROXY_SOURCES} \ + ${K3_TI_SCI_SOURCES} \ diff --git a/arm-trusted-firmware/plat/ti/k3/include/k3_console.h b/arm-trusted-firmware/plat/ti/k3/include/k3_console.h new file mode 100644 index 0000000..6376ab3 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/include/k3_console.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef K3_CONSOLE_H +#define K3_CONSOLE_H + +void bl31_console_setup(void); + +#endif /* K3_CONSOLE_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h b/arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h new file mode 100644 index 0000000..2329a16 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef K3_GICV3_H +#define K3_GICV3_H + +#include + +void k3_gic_driver_init(uintptr_t gic_base); +void k3_gic_init(void); +void k3_gic_cpuif_enable(void); +void k3_gic_cpuif_disable(void); +void k3_gic_pcpu_init(void); + +#endif /* K3_GICV3_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/include/plat_macros.S b/arm-trusted-firmware/plat/ti/k3/include/plat_macros.S new file mode 100644 index 0000000..38056b5 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/include/plat_macros.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + /* STUB */ + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/ti/k3/include/platform_def.h b/arm-trusted-firmware/plat/ti/k3/include/platform_def.h new file mode 100644 index 0000000..81a383a --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/include/platform_def.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stack */ +#if IMAGE_BL31 +#define PLATFORM_STACK_SIZE 0x800 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +#define PLATFORM_SYSTEM_COUNT 1 +#define PLATFORM_CORE_COUNT (K3_CLUSTER0_CORE_COUNT + \ + K3_CLUSTER1_CORE_COUNT + \ + K3_CLUSTER2_CORE_COUNT + \ + K3_CLUSTER3_CORE_COUNT) + +#define PLATFORM_CLUSTER_COUNT ((K3_CLUSTER0_CORE_COUNT != 0) + \ + (K3_CLUSTER1_CORE_COUNT != 0) + \ + (K3_CLUSTER2_CORE_COUNT != 0) + \ + (K3_CLUSTER3_CORE_COUNT != 0)) + +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/******************************************************************************* + * Memory layout constants + ******************************************************************************/ + +/* + * ARM-TF lives in SRAM, partition it here + * + * BL3-1 specific defines. + * + * Put BL3-1 at the base of the Trusted SRAM. + */ +#define BL31_BASE SEC_SRAM_BASE +#define BL31_SIZE SEC_SRAM_SIZE +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +/* + * Defines the maximum number of translation tables that are allocated by the + * translation table library code. To minimize the amount of runtime memory + * used, choose the smallest value needed to map the required virtual addresses + * for each BL stage. + */ +#if USE_COHERENT_MEM +#define MAX_XLAT_TABLES 10 +#else +#define MAX_XLAT_TABLES 9 +#endif + +/* + * Defines the maximum number of regions that are allocated by the translation + * table library code. A region consists of physical base address, virtual base + * address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as + * defined in the `mmap_region_t` structure. The platform defines the regions + * that should be mapped. Then, the translation table library will create the + * corresponding tables and descriptors at runtime. To minimize the amount of + * runtime memory used, choose the smallest value needed to register the + * required regions for each BL stage. + */ +#define MAX_MMAP_REGIONS 11 + +/* + * Defines the total size of the address space in bytes. For example, for a 32 + * bit address space, this value should be `(1ull << 32)`. + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) + +/* + * 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_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* Platform default console definitions */ +#ifndef K3_USART_BASE +#define K3_USART_BASE (0x02800000 + 0x10000 * K3_USART) +#endif + +/* USART has a default size for address space */ +#define K3_USART_SIZE 0x1000 + +#ifndef K3_USART_CLK_SPEED +#define K3_USART_CLK_SPEED 48000000 +#endif + +/* Crash console defaults */ +#define CRASH_CONSOLE_BASE K3_USART_BASE +#define CRASH_CONSOLE_CLK K3_USART_CLK_SPEED +#define CRASH_CONSOLE_BAUD_RATE K3_USART_BAUD + +/* Timer frequency */ +#ifndef SYS_COUNTER_FREQ_IN_TICKS +#define SYS_COUNTER_FREQ_IN_TICKS 200000000 +#endif + +/* Interrupt numbers */ +#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 properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_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 PLAT_ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + + +#define K3_GTC_BASE 0x00A90000 +/* We just need 20 byte offset, but simpler to just remap the 64K page in */ +#define K3_GTC_SIZE 0x10000 +#define K3_GTC_CNTCR_OFFSET 0x00 +#define K3_GTC_CNTCR_EN_MASK 0x01 +#define K3_GTC_CNTCR_HDBG_MASK 0x02 +#define K3_GTC_CNTFID0_OFFSET 0x20 + +#define K3_GIC_BASE 0x01800000 +#define K3_GIC_SIZE 0x200000 + +#if !K3_SEC_PROXY_LITE +#define SEC_PROXY_DATA_BASE 0x32C00000 +#define SEC_PROXY_DATA_SIZE 0x80000 +#define SEC_PROXY_SCFG_BASE 0x32800000 +#define SEC_PROXY_SCFG_SIZE 0x80000 +#define SEC_PROXY_RT_BASE 0x32400000 +#define SEC_PROXY_RT_SIZE 0x80000 +#else +#define SEC_PROXY_DATA_BASE 0x4D000000 +#define SEC_PROXY_DATA_SIZE 0x80000 +#define SEC_PROXY_SCFG_BASE 0x4A400000 +#define SEC_PROXY_SCFG_SIZE 0x80000 +#define SEC_PROXY_RT_BASE 0x4A600000 +#define SEC_PROXY_RT_SIZE 0x80000 +#endif /* K3_SEC_PROXY_LITE */ + +#define SEC_PROXY_TIMEOUT_US 1000000 +#define SEC_PROXY_MAX_MESSAGE_SIZE 56 + +#define TI_SCI_HOST_ID 10 +#define TI_SCI_MAX_MESSAGE_SIZE 52 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/platform.mk b/arm-trusted-firmware/plat/ti/k3/platform.mk new file mode 100644 index 0000000..2de21aa --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/platform.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_PATH := plat/ti/k3 +TARGET_BOARD ?= generic + +include ${PLAT_PATH}/common/plat_common.mk +include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk + +# modify BUILD_PLAT to point to board specific build directory +BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE} diff --git a/arm-trusted-firmware/plat/xilinx/common/include/ipi.h b/arm-trusted-firmware/plat/xilinx/common/include/ipi.h new file mode 100644 index 0000000..483902e --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/ipi.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Xilinx IPI management configuration data and macros */ + +#ifndef IPI_H +#define IPI_H + +#include + +/********************************************************************* + * IPI mailbox status macros + ********************************************************************/ +#define IPI_MB_STATUS_IDLE 0 +#define IPI_MB_STATUS_SEND_PENDING 1 +#define IPI_MB_STATUS_RECV_PENDING 2 + +/********************************************************************* + * IPI mailbox call is secure or not macros + ********************************************************************/ +#define IPI_MB_CALL_NOTSECURE 0 +#define IPI_MB_CALL_SECURE 1 + +/********************************************************************* + * IPI secure check + ********************************************************************/ +#define IPI_SECURE_MASK 0x1U +#define IPI_IS_SECURE(I) ((ipi_table[(I)].secure_only & \ + IPI_SECURE_MASK) ? 1 : 0) + +/********************************************************************* + * Struct definitions + ********************************************************************/ + +/* structure to maintain IPI configuration information */ +struct ipi_config { + unsigned int ipi_bit_mask; + unsigned int ipi_reg_base; + unsigned char secure_only; +}; + +/********************************************************************* + * IPI APIs declarations + ********************************************************************/ + +/* Initialize IPI configuration table */ +void ipi_config_table_init(const struct ipi_config *ipi_table, + uint32_t total_ipi); + +/* Validate IPI mailbox access */ +int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure); + +/* Open the IPI mailbox */ +void ipi_mb_open(uint32_t local, uint32_t remote); + +/* Release the IPI mailbox */ +void ipi_mb_release(uint32_t local, uint32_t remote); + +/* Enquire IPI mailbox status */ +int ipi_mb_enquire_status(uint32_t local, uint32_t remote); + +/* Trigger notification on the IPI mailbox */ +void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking); + +/* Ack IPI mailbox notification */ +void ipi_mb_ack(uint32_t local, uint32_t remote); + +/* Disable IPI mailbox notification interrupt */ +void ipi_mb_disable_irq(uint32_t local, uint32_t remote); + +/* Enable IPI mailbox notification interrupt */ +void ipi_mb_enable_irq(uint32_t local, uint32_t remote); + +#endif /* IPI_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h b/arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h new file mode 100644 index 0000000..66e7933 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_STARTUP_H +#define PLAT_STARTUP_H + +/* For FSBL handover */ +enum fsbl_handoff { + FSBL_HANDOFF_SUCCESS = 0, + FSBL_HANDOFF_NO_STRUCT, + FSBL_HANDOFF_INVAL_STRUCT, + FSBL_HANDOFF_TOO_MANY_PARTS +}; + +enum fsbl_handoff fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info, + entry_point_info_t *bl33_image_ep_info, + uint64_t atf_handoff_addr); + +#endif /* PLAT_STARTUP_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/include/pm_client.h b/arm-trusted-firmware/plat/xilinx/common/include/pm_client.h new file mode 100644 index 0000000..e91bb8f --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/pm_client.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Contains APU specific macros and macros to be defined depending on + * the execution environment. + */ + +#ifndef PM_CLIENT_H +#define PM_CLIENT_H + +#include "pm_common.h" +#include "pm_defs.h" + +/* Functions to be implemented by each PU */ +void pm_client_suspend(const struct pm_proc *proc, unsigned int state); +void pm_client_abort_suspend(void); +void pm_client_wakeup(const struct pm_proc *proc); + +/* Global variables to be set in pm_client.c */ +extern const struct pm_proc *primary_proc; + +#ifndef VERSAL_PLATFORM +enum pm_ret_status set_ocm_retention(void); +enum pm_ret_status pm_set_suspend_mode(uint32_t mode); +const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid); +#endif + +#endif /* PM_CLIENT_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/include/pm_common.h b/arm-trusted-firmware/plat/xilinx/common/include/pm_common.h new file mode 100644 index 0000000..0c24a36 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/pm_common.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Contains definitions of commonly used macros and data types needed + * for PU Power Management. This file should be common for all PU's. + */ + +#ifndef PM_COMMON_H +#define PM_COMMON_H + +#include +#include + +#if IPI_CRC_CHECK +#define PAYLOAD_ARG_CNT 8U +#define IPI_W0_TO_W6_SIZE 28U +#define PAYLOAD_CRC_POS 7U +#define CRC_INIT_VALUE 0x4F4EU +#define CRC_ORDER 16U +#define CRC_POLYNOM 0x8005U +#else +#define PAYLOAD_ARG_CNT 6U +#endif +#define PAYLOAD_ARG_SIZE 4U /* size in bytes */ + +/** + * pm_ipi - struct for capturing IPI-channel specific info + * @local_ipi_id Local IPI agent ID + * @remote_ipi_id Remote IPI Agent ID + * @buffer_base base address for payload buffer + */ +struct pm_ipi { + const uint32_t local_ipi_id; + const uint32_t remote_ipi_id; + const uintptr_t buffer_base; +}; + +/** + * pm_proc - struct for capturing processor related info + * @node_id node-ID of the processor + * @pwrdn_mask cpu-specific mask to be used for power control register + * @ipi pointer to IPI channel structure + * (in APU all processors share one IPI channel) + */ +struct pm_proc { + const uint32_t node_id; + const unsigned int pwrdn_mask; + const struct pm_ipi *ipi; +}; + +const struct pm_proc *pm_get_proc(unsigned int cpuid); + +#endif /* PM_COMMON_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h b/arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h new file mode 100644 index 0000000..8c7738d --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_IPI_H +#define PM_IPI_H + +#include +#include "pm_common.h" + +#define IPI_BLOCKING 1 +#define IPI_NON_BLOCKING 0 + +int pm_ipi_init(const struct pm_proc *proc); + +enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, + uint32_t payload[PAYLOAD_ARG_CNT]); +enum pm_ret_status pm_ipi_send_non_blocking(const struct pm_proc *proc, + uint32_t payload[PAYLOAD_ARG_CNT]); +enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, + uint32_t payload[PAYLOAD_ARG_CNT], + unsigned int *value, size_t count); +void pm_ipi_buff_read_callb(unsigned int *value, size_t count); +void pm_ipi_irq_enable(const struct pm_proc *proc); +void pm_ipi_irq_clear(const struct pm_proc *proc); +uint32_t pm_ipi_irq_status(const struct pm_proc *proc); +#if IPI_CRC_CHECK +uint32_t calculate_crc(uint32_t payload[PAYLOAD_ARG_CNT], uint32_t buffersize); +#endif + +#endif /* PM_IPI_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/ipi.c b/arm-trusted-firmware/plat/xilinx/common/ipi.c new file mode 100644 index 0000000..0b8020b --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/ipi.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Xilinx IPI agent registers access management + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +/********************************************************************* + * Macros definitions + ********************************************************************/ + +/* IPI registers offsets macros */ +#define IPI_TRIG_OFFSET 0x00U +#define IPI_OBR_OFFSET 0x04U +#define IPI_ISR_OFFSET 0x10U +#define IPI_IMR_OFFSET 0x14U +#define IPI_IER_OFFSET 0x18U +#define IPI_IDR_OFFSET 0x1CU + +/* IPI register start offset */ +#define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base) + +/* IPI register bit mask */ +#define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask) + +/* IPI configuration table */ +const static struct ipi_config *ipi_table; + +/* Total number of IPI */ +static uint32_t ipi_total; + +/** + * ipi_config_init() - Initialize IPI configuration data + * + * @ipi_config_table - IPI configuration table + * @ipi_total - Total number of IPI available + * + */ +void ipi_config_table_init(const struct ipi_config *ipi_config_table, + uint32_t total_ipi) +{ + ipi_table = ipi_config_table; + ipi_total = total_ipi; +} + +/* is_ipi_mb_within_range() - verify if IPI mailbox is within range + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * return - 1 if within range, 0 if not + */ +static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote) +{ + int ret = 1; + + if (remote >= ipi_total || local >= ipi_total) + ret = 0; + + return ret; +} + +/** + * ipi_mb_validate() - validate IPI mailbox access + * + * @local - local IPI ID + * @remote - remote IPI ID + * @is_secure - indicate if the requester is from secure software + * + * return - 0 success, negative value for errors + */ +int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure) +{ + int ret = 0; + + if (!is_ipi_mb_within_range(local, remote)) + ret = -EINVAL; + else if (IPI_IS_SECURE(local) && !is_secure) + ret = -EPERM; + else if (IPI_IS_SECURE(remote) && !is_secure) + ret = -EPERM; + + return ret; +} + +/** + * ipi_mb_open() - Open IPI mailbox. + * + * @local - local IPI ID + * @remote - remote IPI ID + * + */ +void ipi_mb_open(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, + IPI_BIT_MASK(remote)); + mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, + IPI_BIT_MASK(remote)); +} + +/** + * ipi_mb_release() - Open IPI mailbox. + * + * @local - local IPI ID + * @remote - remote IPI ID + * + */ +void ipi_mb_release(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, + IPI_BIT_MASK(remote)); +} + +/** + * ipi_mb_enquire_status() - Enquire IPI mailbox status + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * return - 0 idle, positive value for pending sending or receiving, + * negative value for errors + */ +int ipi_mb_enquire_status(uint32_t local, uint32_t remote) +{ + int ret = 0; + uint32_t status; + + status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET); + if (status & IPI_BIT_MASK(remote)) + ret |= IPI_MB_STATUS_SEND_PENDING; + status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET); + if (status & IPI_BIT_MASK(remote)) + ret |= IPI_MB_STATUS_RECV_PENDING; + + return ret; +} + +/* ipi_mb_notify() - Trigger IPI mailbox notification + * + * @local - local IPI ID + * @remote - remote IPI ID + * @is_blocking - if to trigger the notification in blocking mode or not. + * + * It sets the remote bit in the IPI agent trigger register. + * + */ +void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) +{ + uint32_t status; + + mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET, + IPI_BIT_MASK(remote)); + if (is_blocking) { + do { + status = mmio_read_32(IPI_REG_BASE(local) + + IPI_OBR_OFFSET); + } while (status & IPI_BIT_MASK(remote)); + } +} + +/* ipi_mb_ack() - Ack IPI mailbox notification from the other end + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * It will clear the remote bit in the isr register. + * + */ +void ipi_mb_ack(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, + IPI_BIT_MASK(remote)); +} + +/* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * It will mask the remote bit in the idr register. + * + */ +void ipi_mb_disable_irq(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, + IPI_BIT_MASK(remote)); +} + +/* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt + * + * @local - local IPI ID + * @remote - remote IPI ID + * + * It will mask the remote bit in the idr register. + * + */ +void ipi_mb_enable_irq(uint32_t local, uint32_t remote) +{ + mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET, + IPI_BIT_MASK(remote)); +} diff --git a/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c b/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c new file mode 100644 index 0000000..f531158 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Top-level SMC handler for ZynqMP IPI Mailbox doorbell functions. + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "ipi_mailbox_svc.h" +#include "../../../services/spd/trusty/smcall.h" + +/********************************************************************* + * Macros definitions + ********************************************************************/ + +/* IPI SMC calls macros: */ +#define IPI_SMC_OPEN_IRQ_MASK 0x00000001U /* IRQ enable bit in IPI + * open SMC call + */ +#define IPI_SMC_NOTIFY_BLOCK_MASK 0x00000001U /* Flag to indicate if + * IPI notification needs + * to be blocking. + */ +#define IPI_SMC_ENQUIRY_DIRQ_MASK 0x00000001U /* Flag to indicate if + * notification interrupt + * to be disabled. + */ +#define IPI_SMC_ACK_EIRQ_MASK 0x00000001U /* Flag to indicate if + * notification interrupt + * to be enable. + */ + +#define UNSIGNED32_MASK 0xFFFFFFFFU /* 32bit mask */ + +/** + * ipi_smc_handler() - SMC handler for IPI SMC calls + * + * @smc_fid - Function identifier + * @x1 - x4 - Arguments + * @cookie - Unused + * @handler - Pointer to caller's context structure + * + * @return - Unused + * + * Determines that smc_fid is valid and supported PM SMC Function ID from the + * list of pm_api_ids, otherwise completes the request with + * the unknown SMC Function ID + * + * The SMC calls for PM service are forwarded from SIP Service SMC handler + * function with rt_svc_handle signature + */ +uint64_t ipi_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) +{ + int ret; + uint32_t ipi_local_id; + uint32_t ipi_remote_id; + unsigned int is_secure; + + ipi_local_id = x1 & UNSIGNED32_MASK; + ipi_remote_id = x2 & UNSIGNED32_MASK; + + if (SMC_ENTITY(smc_fid) >= SMC_ENTITY_TRUSTED_APP) + is_secure = 1; + else + is_secure = 0; + + /* Validate IPI mailbox access */ + ret = ipi_mb_validate(ipi_local_id, ipi_remote_id, is_secure); + if (ret) + SMC_RET1(handle, ret); + + switch (SMC_FUNCTION(smc_fid)) { + case IPI_MAILBOX_OPEN: + ipi_mb_open(ipi_local_id, ipi_remote_id); + SMC_RET1(handle, 0); + case IPI_MAILBOX_RELEASE: + ipi_mb_release(ipi_local_id, ipi_remote_id); + SMC_RET1(handle, 0); + case IPI_MAILBOX_STATUS_ENQUIRY: + { + int disable_irq; + + disable_irq = (x3 & IPI_SMC_ENQUIRY_DIRQ_MASK) ? 1 : 0; + ret = ipi_mb_enquire_status(ipi_local_id, ipi_remote_id); + if ((ret & IPI_MB_STATUS_RECV_PENDING) && disable_irq) + ipi_mb_disable_irq(ipi_local_id, ipi_remote_id); + SMC_RET1(handle, ret); + } + case IPI_MAILBOX_NOTIFY: + { + uint32_t is_blocking; + + is_blocking = (x3 & IPI_SMC_NOTIFY_BLOCK_MASK) ? 1 : 0; + ipi_mb_notify(ipi_local_id, ipi_remote_id, is_blocking); + SMC_RET1(handle, 0); + } + case IPI_MAILBOX_ACK: + { + int enable_irq; + + enable_irq = (x3 & IPI_SMC_ACK_EIRQ_MASK) ? 1 : 0; + ipi_mb_ack(ipi_local_id, ipi_remote_id); + if (enable_irq) + ipi_mb_enable_irq(ipi_local_id, ipi_remote_id); + SMC_RET1(handle, 0); + } + case IPI_MAILBOX_ENABLE_IRQ: + ipi_mb_enable_irq(ipi_local_id, ipi_remote_id); + SMC_RET1(handle, 0); + case IPI_MAILBOX_DISABLE_IRQ: + ipi_mb_disable_irq(ipi_local_id, ipi_remote_id); + SMC_RET1(handle, 0); + default: + WARN("Unimplemented IPI service call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h b/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h new file mode 100644 index 0000000..10682d8 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* ZynqMP IPI mailbox doorbell service enums and defines */ + +#ifndef IPI_MAILBOX_SVC_H +#define IPI_MAILBOX_SVC_H + +#include + +/********************************************************************* + * Enum definitions + ********************************************************************/ + +/* IPI SMC function numbers enum definition */ +enum ipi_api_id { + /* IPI mailbox operations functions: */ + IPI_MAILBOX_OPEN = 0x1000, + IPI_MAILBOX_RELEASE, + IPI_MAILBOX_STATUS_ENQUIRY, + IPI_MAILBOX_NOTIFY, + IPI_MAILBOX_ACK, + IPI_MAILBOX_ENABLE_IRQ, + IPI_MAILBOX_DISABLE_IRQ +}; + +/********************************************************************* + * IPI mailbox service APIs declarations + ********************************************************************/ + +/* IPI SMC handler */ +uint64_t ipi_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 /* IPI_MAILBOX_SVC_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/plat_startup.c b/arm-trusted-firmware/plat/xilinx/common/plat_startup.c new file mode 100644 index 0000000..f02f41e --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/plat_startup.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + + +/* + * ATFHandoffParams + * Parameter bitfield encoding + * ----------------------------------------------------------------------------- + * Exec State 0 0 -> Aarch64, 1-> Aarch32 + * endianness 1 0 -> LE, 1 -> BE + * secure (TZ) 2 0 -> Non secure, 1 -> secure + * EL 3:4 00 -> EL0, 01 -> EL1, 10 -> EL2, 11 -> EL3 + * CPU# 5:6 00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3 + */ + +#define FSBL_FLAGS_ESTATE_SHIFT 0 +#define FSBL_FLAGS_ESTATE_MASK (1 << FSBL_FLAGS_ESTATE_SHIFT) +#define FSBL_FLAGS_ESTATE_A64 0 +#define FSBL_FLAGS_ESTATE_A32 1 + +#define FSBL_FLAGS_ENDIAN_SHIFT 1 +#define FSBL_FLAGS_ENDIAN_MASK (1 << FSBL_FLAGS_ENDIAN_SHIFT) +#define FSBL_FLAGS_ENDIAN_LE 0 +#define FSBL_FLAGS_ENDIAN_BE 1 + +#define FSBL_FLAGS_TZ_SHIFT 2 +#define FSBL_FLAGS_TZ_MASK (1 << FSBL_FLAGS_TZ_SHIFT) +#define FSBL_FLAGS_NON_SECURE 0 +#define FSBL_FLAGS_SECURE 1 + +#define FSBL_FLAGS_EL_SHIFT 3 +#define FSBL_FLAGS_EL_MASK (3 << FSBL_FLAGS_EL_SHIFT) +#define FSBL_FLAGS_EL0 0 +#define FSBL_FLAGS_EL1 1 +#define FSBL_FLAGS_EL2 2 +#define FSBL_FLAGS_EL3 3 + +#define FSBL_FLAGS_CPU_SHIFT 5 +#define FSBL_FLAGS_CPU_MASK (3 << FSBL_FLAGS_CPU_SHIFT) +#define FSBL_FLAGS_A53_0 0 +#define FSBL_FLAGS_A53_1 1 +#define FSBL_FLAGS_A53_2 2 +#define FSBL_FLAGS_A53_3 3 + +#define FSBL_MAX_PARTITIONS 8 + +/* Structure corresponding to each partition entry */ +struct xfsbl_partition { + uint64_t entry_point; + uint64_t flags; +}; + +/* Structure for handoff parameters to ARM Trusted Firmware (ATF) */ +struct xfsbl_atf_handoff_params { + uint8_t magic[4]; + uint32_t num_entries; + struct xfsbl_partition partition[FSBL_MAX_PARTITIONS]; +}; + +/** + * @partition: Pointer to partition struct + * + * Get the target CPU for @partition. + * + * Return: FSBL_FLAGS_A53_0, FSBL_FLAGS_A53_1, FSBL_FLAGS_A53_2 or FSBL_FLAGS_A53_3 + */ +static int get_fsbl_cpu(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_CPU_MASK; + + return flags >> FSBL_FLAGS_CPU_SHIFT; +} + +/** + * @partition: Pointer to partition struct + * + * Get the target exception level for @partition. + * + * Return: FSBL_FLAGS_EL0, FSBL_FLAGS_EL1, FSBL_FLAGS_EL2 or FSBL_FLAGS_EL3 + */ +static int get_fsbl_el(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_EL_MASK; + + return flags >> FSBL_FLAGS_EL_SHIFT; +} + +/** + * @partition: Pointer to partition struct + * + * Get the target security state for @partition. + * + * Return: FSBL_FLAGS_NON_SECURE or FSBL_FLAGS_SECURE + */ +static int get_fsbl_ss(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_TZ_MASK; + + return flags >> FSBL_FLAGS_TZ_SHIFT; +} + +/** + * @partition: Pointer to partition struct + * + * Get the target endianness for @partition. + * + * Return: SPSR_E_LITTLE or SPSR_E_BIG + */ +static int get_fsbl_endian(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_ENDIAN_MASK; + + flags >>= FSBL_FLAGS_ENDIAN_SHIFT; + + if (flags == FSBL_FLAGS_ENDIAN_BE) + return SPSR_E_BIG; + else + return SPSR_E_LITTLE; +} + +/** + * @partition: Pointer to partition struct + * + * Get the target execution state for @partition. + * + * Return: FSBL_FLAGS_ESTATE_A32 or FSBL_FLAGS_ESTATE_A64 + */ +static int get_fsbl_estate(const struct xfsbl_partition *partition) +{ + uint64_t flags = partition->flags & FSBL_FLAGS_ESTATE_MASK; + + return flags >> FSBL_FLAGS_ESTATE_SHIFT; +} + +/** + * Populates the bl32 and bl33 image info structures + * @bl32: BL32 image info structure + * @bl33: BL33 image info structure + * atf_handoff_addr: ATF handoff address + * + * Process the handoff paramters from the FSBL and populate the BL32 and BL33 + * image info structures accordingly. + * + * Return: Return the status of the handoff. The value will be from the + * fsbl_handoff enum. + */ +enum fsbl_handoff fsbl_atf_handover(entry_point_info_t *bl32, + entry_point_info_t *bl33, + uint64_t atf_handoff_addr) +{ + const struct xfsbl_atf_handoff_params *ATFHandoffParams; + assert((atf_handoff_addr < BL31_BASE) || + (atf_handoff_addr > (uint64_t)&__BL31_END__)); + if (!atf_handoff_addr) { + WARN("BL31: No ATF handoff structure passed\n"); + return FSBL_HANDOFF_NO_STRUCT; + } + + ATFHandoffParams = (struct xfsbl_atf_handoff_params *)atf_handoff_addr; + if ((ATFHandoffParams->magic[0] != 'X') || + (ATFHandoffParams->magic[1] != 'L') || + (ATFHandoffParams->magic[2] != 'N') || + (ATFHandoffParams->magic[3] != 'X')) { + ERROR("BL31: invalid ATF handoff structure at %" PRIx64 "\n", + atf_handoff_addr); + return FSBL_HANDOFF_INVAL_STRUCT; + } + + VERBOSE("BL31: ATF handoff params at:0x%" PRIx64 ", entries:%u\n", + atf_handoff_addr, ATFHandoffParams->num_entries); + if (ATFHandoffParams->num_entries > FSBL_MAX_PARTITIONS) { + ERROR("BL31: ATF handoff params: too many partitions (%u/%u)\n", + ATFHandoffParams->num_entries, FSBL_MAX_PARTITIONS); + return FSBL_HANDOFF_TOO_MANY_PARTS; + } + + /* + * we loop over all passed entries but only populate two image structs + * (bl32, bl33). I.e. the last applicable images in the handoff + * structure will be used for the hand off + */ + for (size_t i = 0; i < ATFHandoffParams->num_entries; i++) { + entry_point_info_t *image; + int target_estate, target_secure; + int target_cpu, target_endianness, target_el; + + VERBOSE("BL31: %zd: entry:0x%" PRIx64 ", flags:0x%" PRIx64 "\n", i, + ATFHandoffParams->partition[i].entry_point, + ATFHandoffParams->partition[i].flags); + + target_cpu = get_fsbl_cpu(&ATFHandoffParams->partition[i]); + if (target_cpu != FSBL_FLAGS_A53_0) { + WARN("BL31: invalid target CPU (%i)\n", target_cpu); + continue; + } + + target_el = get_fsbl_el(&ATFHandoffParams->partition[i]); + if ((target_el == FSBL_FLAGS_EL3) || + (target_el == FSBL_FLAGS_EL0)) { + WARN("BL31: invalid exception level (%i)\n", target_el); + continue; + } + + target_secure = get_fsbl_ss(&ATFHandoffParams->partition[i]); + if (target_secure == FSBL_FLAGS_SECURE && + target_el == FSBL_FLAGS_EL2) { + WARN("BL31: invalid security state (%i) for exception level (%i)\n", + target_secure, target_el); + continue; + } + + target_estate = get_fsbl_estate(&ATFHandoffParams->partition[i]); + target_endianness = get_fsbl_endian(&ATFHandoffParams->partition[i]); + + if (target_secure == FSBL_FLAGS_SECURE) { + image = bl32; + + if (target_estate == FSBL_FLAGS_ESTATE_A32) + bl32->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + target_endianness, + DISABLE_ALL_EXCEPTIONS); + else + bl32->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } else { + image = bl33; + + if (target_estate == FSBL_FLAGS_ESTATE_A32) { + if (target_el == FSBL_FLAGS_EL2) + target_el = MODE32_hyp; + else + target_el = MODE32_sys; + + bl33->spsr = SPSR_MODE32(target_el, SPSR_T_ARM, + target_endianness, + DISABLE_ALL_EXCEPTIONS); + } else { + if (target_el == FSBL_FLAGS_EL2) + target_el = MODE_EL2; + else + target_el = MODE_EL1; + + bl33->spsr = SPSR_64(target_el, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } + } + + VERBOSE("Setting up %s entry point to:%" PRIx64 ", el:%x\n", + target_secure == FSBL_FLAGS_SECURE ? "BL32" : "BL33", + ATFHandoffParams->partition[i].entry_point, + target_el); + image->pc = ATFHandoffParams->partition[i].entry_point; + + if (target_endianness == SPSR_E_BIG) + EP_SET_EE(image->h.attr, EP_EE_BIG); + else + EP_SET_EE(image->h.attr, EP_EE_LITTLE); + } + + return FSBL_HANDOFF_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c b/arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c new file mode 100644 index 0000000..03a7278 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c @@ -0,0 +1,291 @@ +/* + * 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 "pm_ipi.h" + +#define ERROR_CODE_MASK 0xFFFFU + +DEFINE_BAKERY_LOCK(pm_secure_lock); + +/** + * pm_ipi_init() - Initialize IPI peripheral for communication with + * remote processor + * + * @proc Pointer to the processor who is initiating request + * @return On success, the initialization function must return 0. + * Any other return value will cause the framework to ignore + * the service + * + * Called from pm_setup initialization function + */ +int pm_ipi_init(const struct pm_proc *proc) +{ + bakery_lock_init(&pm_secure_lock); + ipi_mb_open(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id); + + return 0; +} + +/** + * pm_ipi_send_common() - Sends IPI request to the remote processor + * @proc Pointer to the processor who is initiating request + * @payload API id and call arguments to be written in IPI buffer + * + * Send an IPI request to the power controller. Caller needs to hold + * the 'pm_secure_lock' lock. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc, + uint32_t payload[PAYLOAD_ARG_CNT], + uint32_t is_blocking) +{ + unsigned int offset = 0; + uintptr_t buffer_base = proc->ipi->buffer_base + + IPI_BUFFER_TARGET_REMOTE_OFFSET + + IPI_BUFFER_REQ_OFFSET; +#if IPI_CRC_CHECK + payload[PAYLOAD_CRC_POS] = calculate_crc(payload, IPI_W0_TO_W6_SIZE); +#endif + + /* Write payload into IPI buffer */ + for (size_t i = 0; i < PAYLOAD_ARG_CNT; i++) { + mmio_write_32(buffer_base + offset, payload[i]); + offset += PAYLOAD_ARG_SIZE; + } + + /* Generate IPI to remote processor */ + ipi_mb_notify(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id, + is_blocking); + + return PM_RET_SUCCESS; +} + +/** + * pm_ipi_send_non_blocking() - Sends IPI request to the remote processor + * without blocking notification + * @proc Pointer to the processor who is initiating request + * @payload API id and call arguments to be written in IPI buffer + * + * Send an IPI request to the power controller. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_ipi_send_non_blocking(const struct pm_proc *proc, + uint32_t payload[PAYLOAD_ARG_CNT]) +{ + enum pm_ret_status ret; + + bakery_lock_get(&pm_secure_lock); + + ret = pm_ipi_send_common(proc, payload, IPI_NON_BLOCKING); + + bakery_lock_release(&pm_secure_lock); + + return ret; +} + +/** + * pm_ipi_send() - Sends IPI request to the remote processor + * @proc Pointer to the processor who is initiating request + * @payload API id and call arguments to be written in IPI buffer + * + * Send an IPI request to the power controller. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, + uint32_t payload[PAYLOAD_ARG_CNT]) +{ + enum pm_ret_status ret; + + bakery_lock_get(&pm_secure_lock); + + ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING); + + bakery_lock_release(&pm_secure_lock); + + return ret; +} + + +/** + * pm_ipi_buff_read() - Reads IPI response after remote processor has handled + * interrupt + * @proc Pointer to the processor who is waiting and reading response + * @value Used to return value from IPI buffer element (optional) + * @count Number of values to return in @value + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc, + unsigned int *value, size_t count) +{ + size_t i; +#if IPI_CRC_CHECK + size_t j; + unsigned int response_payload[PAYLOAD_ARG_CNT]; +#endif + uintptr_t buffer_base = proc->ipi->buffer_base + + IPI_BUFFER_TARGET_REMOTE_OFFSET + + IPI_BUFFER_RESP_OFFSET; + + /* + * Read response from IPI buffer + * buf-0: success or error+reason + * buf-1: value + * buf-2: unused + * buf-3: unused + */ + for (i = 1; i <= count; i++) { + *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE)); + value++; + } +#if IPI_CRC_CHECK + for (j = 0; j < PAYLOAD_ARG_CNT; j++) + response_payload[j] = mmio_read_32(buffer_base + + (j * PAYLOAD_ARG_SIZE)); + + if (response_payload[PAYLOAD_CRC_POS] != + calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) + NOTICE("ERROR in CRC response payload value:0x%x\n", + response_payload[PAYLOAD_CRC_POS]); +#endif + + return mmio_read_32(buffer_base); +} + +/** + * pm_ipi_buff_read_callb() - Reads IPI response after remote processor has + * handled interrupt + * @value Used to return value from IPI buffer element (optional) + * @count Number of values to return in @value + * + * @return Returns status, either success or error+reason + */ +void pm_ipi_buff_read_callb(unsigned int *value, size_t count) +{ + size_t i; +#if IPI_CRC_CHECK + size_t j; + unsigned int response_payload[PAYLOAD_ARG_CNT]; +#endif + uintptr_t buffer_base = IPI_BUFFER_REMOTE_BASE + + IPI_BUFFER_TARGET_LOCAL_OFFSET + + IPI_BUFFER_REQ_OFFSET; + + if (count > IPI_BUFFER_MAX_WORDS) + count = IPI_BUFFER_MAX_WORDS; + + for (i = 0; i <= count; i++) { + *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE)); + value++; + } +#if IPI_CRC_CHECK + for (j = 0; j < PAYLOAD_ARG_CNT; j++) + response_payload[j] = mmio_read_32(buffer_base + + (j * PAYLOAD_ARG_SIZE)); + + if (response_payload[PAYLOAD_CRC_POS] != + calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) + NOTICE("ERROR in CRC response payload value:0x%x\n", + response_payload[PAYLOAD_CRC_POS]); +#endif +} + +/** + * pm_ipi_send_sync() - Sends IPI request to the remote processor + * @proc Pointer to the processor who is initiating request + * @payload API id and call arguments to be written in IPI buffer + * @value Used to return value from IPI buffer element (optional) + * @count Number of values to return in @value + * + * Send an IPI request to the power controller and wait for it to be handled. + * + * @return Returns status, either success or error+reason and, optionally, + * @value + */ +enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, + uint32_t payload[PAYLOAD_ARG_CNT], + unsigned int *value, size_t count) +{ + enum pm_ret_status ret; + + bakery_lock_get(&pm_secure_lock); + + ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING); + if (ret != PM_RET_SUCCESS) + goto unlock; + + ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count)); + +unlock: + bakery_lock_release(&pm_secure_lock); + + return ret; +} + +void pm_ipi_irq_enable(const struct pm_proc *proc) +{ + ipi_mb_enable_irq(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id); +} + +void pm_ipi_irq_clear(const struct pm_proc *proc) +{ + ipi_mb_ack(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id); +} + +uint32_t pm_ipi_irq_status(const struct pm_proc *proc) +{ + int ret; + + ret = ipi_mb_enquire_status(proc->ipi->local_ipi_id, + proc->ipi->remote_ipi_id); + if (ret & IPI_MB_STATUS_RECV_PENDING) + return 1; + else + return 0; +} + +#if IPI_CRC_CHECK +uint32_t calculate_crc(uint32_t *payload, uint32_t bufsize) +{ + uint32_t crcinit = CRC_INIT_VALUE; + uint32_t order = CRC_ORDER; + uint32_t polynom = CRC_POLYNOM; + uint32_t i, j, c, bit, datain, crcmask, crchighbit; + uint32_t crc = crcinit; + + crcmask = ((uint32_t)((1U << (order - 1U)) - 1U) << 1U) | 1U; + crchighbit = (uint32_t)(1U << (order - 1U)); + + for (i = 0U; i < bufsize; i++) { + datain = mmio_read_8((unsigned long)payload + i); + c = datain; + j = 0x80U; + while (j != 0U) { + bit = crc & crchighbit; + crc <<= 1U; + if (0U != (c & j)) + bit ^= crchighbit; + if (bit != 0U) + crc ^= polynom; + j >>= 1U; + } + crc &= crcmask; + } + return crc; +} +#endif diff --git a/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c b/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c new file mode 100644 index 0000000..897ed59 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c @@ -0,0 +1,54 @@ +/* + * 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 + +/* + * Table of regions to map using the MMU. + * This doesn't include TZRAM as the 'mem_layout' argument passed to + * configure_mmu_elx() will give the available subset of that, + */ +const mmap_region_t plat_versal_mmap[] = { + MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(FPD_MAINCCI_BASE, FPD_MAINCCI_SIZE, MT_DEVICE | MT_RW | + MT_SECURE), + { 0 } +}; + +const mmap_region_t *plat_versal_get_mmap(void) +{ + return plat_versal_mmap; +} + +static void versal_print_platform_name(void) +{ + NOTICE("ATF running on Xilinx %s\n", PLATFORM_NAME); +} + +void versal_config_setup(void) +{ + /* Configure IPI data for versal */ + versal_ipi_config_table_init(); + + versal_print_platform_name(); + + generic_delay_timer_init(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return VERSAL_CPU_CLOCK; +} + diff --git a/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S b/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S new file mode 100644 index 0000000..26eb052 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl versal_calc_core_pos + .globl platform_mem_init + .globl plat_my_core_pos + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + mrs x0, mpidr_el1 + + /* + * There is no sane reason to come out of this wfi. This + * cpu will be powered on and reset by the cpu_on pm api + */ + dsb sy + bl plat_panic_handler +endfunc plat_secondary_cold_boot_setup + +func plat_is_my_cpu_primary + mov x9, x30 + bl plat_my_core_pos + cmp x0, #VERSAL_PRIMARY_CPU + cset x0, eq + ret x9 +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the versal_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b versal_calc_core_pos +endfunc plat_my_core_pos + +func versal_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc versal_calc_core_pos + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on VERSAL + * platform. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c b/arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c new file mode 100644 index 0000000..78bfc29 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2018-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 +#include +#include + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + */ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + assert(sec_state_is_valid(type)); + + if (type == NON_SECURE) { + return &bl33_image_ep_info; + } + + return &bl32_image_ep_info; +} + +/* + * Set the build time defaults,if we can't find any config data. + */ +static inline void bl31_set_default_config(void) +{ + bl32_image_ep_info.pc = (uintptr_t)BL32_BASE; + bl32_image_ep_info.spsr = (uint32_t)arm_get_spsr_for_bl32_entry(); + bl33_image_ep_info.pc = (uintptr_t)plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = (uint32_t)SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} + +/* + * Perform any BL31 specific platform actions. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + */ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + uint64_t atf_handoff_addr; + + if (VERSAL_CONSOLE_IS(pl011) || (VERSAL_CONSOLE_IS(pl011_1))) { + static console_t versal_runtime_console; + /* Initialize the console to provide early debug support */ + int rc = console_pl011_register((unsigned long)VERSAL_UART_BASE, + (unsigned int)VERSAL_UART_CLOCK, + (unsigned int)VERSAL_UART_BAUDRATE, + &versal_runtime_console); + if (rc == 0) { + panic(); + } + + console_set_scope(&versal_runtime_console, (unsigned int)(CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME)); + } else if (VERSAL_CONSOLE_IS(dcc)) { + /* Initialize the dcc console for debug */ + int rc = console_dcc_register(); + if (rc == 0) { + panic(); + } + } else { + NOTICE("BL31: Did not register for any console.\n"); + } + + /* Initialize the platform config for future decision making */ + versal_config_setup(); + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(arg0 == 0U); + assert(arg1 == 0U); + + /* + * Do initial security configuration to allow DRAM/device access. On + * Base VERSAL only DRAM security is programmable (via TrustZone), but + * other platforms might have more programmable security devices + * present. + */ + + /* Populate common information for BL32 and BL33 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + atf_handoff_addr = mmio_read_32(PMC_GLOBAL_GLOB_GEN_STORAGE4); + enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info, + &bl33_image_ep_info, + atf_handoff_addr); + if (ret == FSBL_HANDOFF_NO_STRUCT || ret == FSBL_HANDOFF_INVAL_STRUCT) { + bl31_set_default_config(); + } else if (ret == FSBL_HANDOFF_TOO_MANY_PARTS) { + ERROR("BL31: Error too many partitions %u\n", ret); + } else if (ret != FSBL_HANDOFF_SUCCESS) { + panic(); + } else { + INFO("BL31: fsbl-atf handover success %u\n", ret); + } + + NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); + NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); +} + +static interrupt_type_handler_t type_el3_interrupt_handler; + +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler) +{ + /* Validate 'handler'*/ + if (handler == NULL) { + return -EINVAL; + } + + type_el3_interrupt_handler = handler; + + return 0; +} + +static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint32_t intr_id; + interrupt_type_handler_t handler; + + intr_id = plat_ic_get_pending_interrupt_id(); + /* Currently we support one interrupt */ + if (intr_id != PLAT_VERSAL_IPI_IRQ) { + WARN("Unexpected interrupt call: 0x%x\n", intr_id); + return 0; + } + + handler = type_el3_interrupt_handler; + if (handler != NULL) { + return handler(intr_id, flags, handle, cookie); + } + + return 0; +} +void bl31_platform_setup(void) +{ + /* Initialize the gic cpu and distributor interfaces */ + plat_versal_gic_driver_init(); + plat_versal_gic_init(); +} + +void bl31_plat_runtime_setup(void) +{ + uint64_t flags = 0; + int32_t rc; + + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_EL3, + rdo_el3_interrupt_handler, flags); + if (rc != 0) { + panic(); + } +} + +/* + * Perform the very early platform specific architectural setup here. + */ +void bl31_plat_arch_setup(void) +{ + plat_arm_interconnect_init(); + plat_arm_interconnect_enter_coherency(); + + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_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), + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), + {0} + }; + + setup_page_tables(bl_regions, plat_versal_get_mmap()); + enable_mmu_el3(0); +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h b/arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h new file mode 100644 index 0000000..36a4380 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Versal IPI management enums and defines */ + +#ifndef PLAT_IPI_H +#define PLAT_IPI_H + +#include +#include + +/********************************************************************* + * IPI agent IDs macros + ********************************************************************/ +#define IPI_ID_PMC 1U +#define IPI_ID_APU 2U +#define IPI_ID_RPU0 3U +#define IPI_ID_RPU1 4U +#define IPI_ID_3 5U +#define IPI_ID_4 6U +#define IPI_ID_5 7U + +/********************************************************************* + * IPI message buffers + ********************************************************************/ +#define IPI_BUFFER_BASEADDR 0xFF3F0000U + +#define IPI_BUFFER_APU_BASE (IPI_BUFFER_BASEADDR + 0x400U) +#define IPI_BUFFER_PMC_BASE (IPI_BUFFER_BASEADDR + 0x200U) + +#define IPI_BUFFER_TARGET_APU_OFFSET 0x80U +#define IPI_BUFFER_TARGET_PMC_OFFSET 0x40U + +#define IPI_BUFFER_LOCAL_BASE IPI_BUFFER_APU_BASE +#define IPI_BUFFER_REMOTE_BASE IPI_BUFFER_PMC_BASE + +#define IPI_BUFFER_TARGET_LOCAL_OFFSET IPI_BUFFER_TARGET_APU_OFFSET +#define IPI_BUFFER_TARGET_REMOTE_OFFSET IPI_BUFFER_TARGET_PMC_OFFSET + +#define IPI_BUFFER_MAX_WORDS 8 + +#define IPI_BUFFER_REQ_OFFSET 0x0U +#define IPI_BUFFER_RESP_OFFSET 0x20U + +/********************************************************************* + * Platform specific IPI API declarations + ********************************************************************/ + +/* Configure IPI table for versal */ +void versal_ipi_config_table_init(void); + +#endif /* PLAT_IPI_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S b/arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S new file mode 100644 index 0000000..3a52212 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include +#include + +#include "../include/platform_def.h" + +.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)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + /* --------------------------------------------- + * The below utility macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31 on Versal platform. + * Expects: GICD base in x16, GICC base in x17 + * Clobbers: x0 - x10, sp + * --------------------------------------------- + */ + .macro versal_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 + bl asm_print_hex + + 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 + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x17, PLAT_VERSAL_GICD_BASE + mov_imm x16, PLAT_VERSAL_GICR_BASE + versal_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h b/arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h new file mode 100644 index 0000000..22c9d11 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Contains platform specific definitions of commonly used macros data types + * for PU Power Management. This file should be common for all PU's. + */ + +#ifndef PLAT_PM_COMMON_H +#define PLAT_PM_COMMON_H + +#include +#include +#include "pm_defs.h" + +#define NON_SECURE_FLAG 1U +#define SECURE_FLAG 0U + +#define VERSAL_TZ_VERSION_MAJOR 1 +#define VERSAL_TZ_VERSION_MINOR 0 +#define VERSAL_TZ_VERSION ((VERSAL_TZ_VERSION_MAJOR << 16) | \ + VERSAL_TZ_VERSION_MINOR) +#endif /* PLAT_PM_COMMON_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h b/arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h new file mode 100644 index 0000000..d12d13a --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#include +#include + +void versal_config_setup(void); + +const mmap_region_t *plat_versal_get_mmap(void); + +void plat_versal_gic_driver_init(void); +void plat_versal_gic_init(void); +void plat_versal_gic_cpuif_enable(void); +void plat_versal_gic_cpuif_disable(void); +void plat_versal_gic_pcpu_init(void); +void plat_versal_gic_save(void); +void plat_versal_gic_resume(void); + +unsigned int versal_calc_core_pos(u_register_t mpidr); +/* + * Register handler to specific GIC entrance + * for INTR_TYPE_EL3 type of interrupt + */ +int request_intr_type_el3(uint32_t irq, interrupt_type_handler_t fiq_handler); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h b/arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h new file mode 100644 index 0000000..83e5083 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include "versal_def.h" + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x440 + +#define PLATFORM_CORE_COUNT U(2) +#define PLAT_MAX_PWR_LVL U(1) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#ifndef VERSAL_ATF_MEM_BASE +# define BL31_BASE U(0xfffe0000) +# define BL31_LIMIT U(0xffffffff) +#else +# define BL31_BASE (VERSAL_ATF_MEM_BASE) +# define BL31_LIMIT (VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_SIZE - 1) +# ifdef VERSAL_ATF_MEM_PROGBITS_SIZE +# define BL31_PROGBITS_LIMIT (VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_PROGBITS_SIZE - 1) +# endif +#endif + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#ifndef VERSAL_BL32_MEM_BASE +# define BL32_BASE U(0x60000000) +# define BL32_LIMIT U(0x7fffffff) +#else +# define BL32_BASE (VERSAL_BL32_MEM_BASE) +# define BL32_LIMIT (VERSAL_BL32_MEM_BASE + VERSAL_BL32_MEM_SIZE - 1) +#endif + +/******************************************************************************* + * BL33 specific defines. + ******************************************************************************/ +#ifndef PRELOADED_BL33_BASE +# define PLAT_ARM_NS_IMAGE_BASE U(0x8000000) +#else +# define PLAT_ARM_NS_IMAGE_BASE PRELOADED_BL33_BASE +#endif + +/******************************************************************************* + * TSP specific defines. + ******************************************************************************/ +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1) + +/* ID of the secure physical generic timer interrupt used by the TSP */ +#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define MAX_MMAP_REGIONS 8 +#define MAX_XLAT_TABLES 5 + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define PLAT_VERSAL_GICD_BASE U(0xF9000000) +#define PLAT_VERSAL_GICR_BASE U(0xF9080000) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_VERSAL_G1S_IRQS VERSAL_IRQ_SEC_PHY_TIMER +#define PLAT_VERSAL_G0_IRQS VERSAL_IRQ_SEC_PHY_TIMER +#define PLAT_VERSAL_IPI_IRQ U(62) + +#define PLAT_VERSAL_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(VERSAL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_VERSAL_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h b/arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h new file mode 100644 index 0000000..9372954 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef VERSAL_DEF_H +#define VERSAL_DEF_H + +#include +#include + +/* List all consoles */ +#define VERSAL_CONSOLE_ID_pl011 1 +#define VERSAL_CONSOLE_ID_pl011_0 1 +#define VERSAL_CONSOLE_ID_pl011_1 2 +#define VERSAL_CONSOLE_ID_dcc 3 + +#define VERSAL_CONSOLE_IS(con) (VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE) + +/* List all supported platforms */ +#define VERSAL_PLATFORM_ID_versal_virt 1 +#define VERSAL_PLATFORM_ID_silicon 4 + +#define VERSAL_PLATFORM_IS(con) (VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM) + +/* Firmware Image Package */ +#define VERSAL_PRIMARY_CPU 0 + +/******************************************************************************* + * memory map related constants + ******************************************************************************/ +#define DEVICE0_BASE 0xFF000000 +#define DEVICE0_SIZE 0x00E00000 +#define DEVICE1_BASE 0xF9000000 +#define DEVICE1_SIZE 0x00800000 + +/* CRL */ +#define VERSAL_CRL 0xFF5E0000 +#define VERSAL_CRL_TIMESTAMP_REF_CTRL (VERSAL_CRL + 0x14C) +#define VERSAL_CRL_RST_TIMESTAMP_OFFSET (VERSAL_CRL + 0x348) + +#define VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT (1 << 25) + +/* IOU SCNTRS */ +#define VERSAL_IOU_SCNTRS 0xFF140000 +#define VERSAL_IOU_SCNTRS_COUNTER_CONTROL_REG (VERSAL_IOU_SCNTRS + 0x0) +#define VERSAL_IOU_SCNTRS_BASE_FREQ (VERSAL_IOU_SCNTRS + 0x20) + +#define VERSAL_IOU_SCNTRS_CONTROL_EN 1 + +/******************************************************************************* + * IRQ constants + ******************************************************************************/ +#define VERSAL_IRQ_SEC_PHY_TIMER U(29) + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_ARM_CCI_BASE 0xFD000000 +#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4 +#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 5 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define VERSAL_UART0_BASE 0xFF000000 +#define VERSAL_UART1_BASE 0xFF010000 + +#if VERSAL_CONSOLE_IS(pl011) || VERSAL_CONSOLE_IS(dcc) +# define VERSAL_UART_BASE VERSAL_UART0_BASE +#elif VERSAL_CONSOLE_IS(pl011_1) +# define VERSAL_UART_BASE VERSAL_UART1_BASE +#else +# error "invalid VERSAL_CONSOLE" +#endif + +#define PLAT_VERSAL_CRASH_UART_BASE VERSAL_UART_BASE +#define PLAT_VERSAL_CRASH_UART_CLK_IN_HZ VERSAL_UART_CLOCK +#define VERSAL_CONSOLE_BAUDRATE VERSAL_UART_BAUDRATE + +/******************************************************************************* + * Platform related constants + ******************************************************************************/ +#if VERSAL_PLATFORM_IS(versal_virt) +# define PLATFORM_NAME "Versal Virt" +# define VERSAL_UART_CLOCK 25000000 +# define VERSAL_UART_BAUDRATE 115200 +# define VERSAL_CPU_CLOCK 2720000 +#elif VERSAL_PLATFORM_IS(silicon) +# define PLATFORM_NAME "Versal Silicon" +# define VERSAL_UART_CLOCK 100000000 +# define VERSAL_UART_BAUDRATE 115200 +# define VERSAL_CPU_CLOCK 100000000 +#endif + +/* Access control register defines */ +#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) + +/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/ +#define CRF_BASE 0xFD1A0000 +#define CRF_SIZE 0x00600000 + +/* CRF registers and bitfields */ +#define CRF_RST_APU (CRF_BASE + 0X00000300) + +#define CRF_RST_APU_ACPU_RESET (1 << 0) +#define CRF_RST_APU_ACPU_PWRON_RESET (1 << 10) + +#define FPD_MAINCCI_BASE 0xFD000000 +#define FPD_MAINCCI_SIZE 0x00100000 + +/* APU registers and bitfields */ +#define FPD_APU_BASE 0xFD5C0000U +#define FPD_APU_CONFIG_0 (FPD_APU_BASE + 0x20U) +#define FPD_APU_RVBAR_L_0 (FPD_APU_BASE + 0x40U) +#define FPD_APU_RVBAR_H_0 (FPD_APU_BASE + 0x44U) +#define FPD_APU_PWRCTL (FPD_APU_BASE + 0x90U) + +#define FPD_APU_CONFIG_0_VINITHI_SHIFT 8U +#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 1U +#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 2U + +/* PMC registers and bitfields */ +#define PMC_GLOBAL_BASE 0xF1110000U +#define PMC_GLOBAL_GLOB_GEN_STORAGE4 (PMC_GLOBAL_BASE + 0x40U) + +/* IPI registers and bitfields */ +#define IPI0_REG_BASE U(0xFF330000) +#define IPI0_TRIG_BIT (1U << 2U) +#define PMC_IPI_TRIG_BIT (1U << 1U) +#define IPI1_REG_BASE U(0xFF340000) +#define IPI1_TRIG_BIT (1U << 3U) +#define IPI2_REG_BASE U(0xFF350000) +#define IPI2_TRIG_BIT (1U << 4U) +#define IPI3_REG_BASE U(0xFF360000) +#define IPI3_TRIG_BIT (1U << 5U) +#define IPI4_REG_BASE U(0xFF370000) +#define IPI4_TRIG_BIT (1U << 5U) +#define IPI5_REG_BASE U(0xFF380000) +#define IPI5_TRIG_BIT (1U << 6U) + +#endif /* VERSAL_DEF_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/plat_psci.c b/arm-trusted-firmware/plat/xilinx/versal/plat_psci.c new file mode 100644 index 0000000..eb05e58 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/plat_psci.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pm_api_sys.h" +#include "pm_client.h" + +static uintptr_t versal_sec_entry; + +static int versal_pwr_domain_on(u_register_t mpidr) +{ + int cpu_id = plat_core_pos_by_mpidr(mpidr); + const struct pm_proc *proc; + + VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); + + if (cpu_id == -1) { + return PSCI_E_INTERN_FAIL; + } + + proc = pm_get_proc((unsigned int)cpu_id); + + /* Send request to PMC to wake up selected ACPU core */ + (void)pm_req_wakeup(proc->node_id, (versal_sec_entry & 0xFFFFFFFFU) | 0x1U, + versal_sec_entry >> 32, 0, SECURE_FLAG); + + /* Clear power down request */ + pm_client_wakeup(proc); + + return PSCI_E_SUCCESS; +} + +/** + * versal_pwr_domain_suspend() - This function sends request to PMC to suspend + * core. + * + * @target_state Targated state + */ +static void versal_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + unsigned int state; + unsigned int cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) { + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + plat_versal_gic_cpuif_disable(); + + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + plat_versal_gic_save(); + } + + state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ? + PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE; + + /* Send request to PMC to suspend this core */ + (void)pm_self_suspend(proc->node_id, MAX_LATENCY, state, versal_sec_entry, + SECURE_FLAG); + + /* APU is to be turned off */ + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + /* disable coherency */ + plat_arm_interconnect_exit_coherency(); + } +} + +/** + * versal_pwr_domain_suspend_finish() - This function performs actions to finish + * suspend procedure. + * + * @target_state Targated state + */ +static void versal_pwr_domain_suspend_finish( + const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) { + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + /* Clear the APU power control register for this cpu */ + pm_client_wakeup(proc); + + /* enable coherency */ + plat_arm_interconnect_enter_coherency(); + + /* APU was turned off, so restore GIC context */ + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + plat_versal_gic_resume(); + } + + plat_versal_gic_cpuif_enable(); +} + +void versal_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* Enable the gic cpu interface */ + plat_versal_gic_pcpu_init(); + + /* Program the gic per-cpu distributor or re-distributor interface */ + plat_versal_gic_cpuif_enable(); +} + +/** + * versal_system_off() - This function sends the system off request + * to firmware. This function does not return. + */ +static void __dead2 versal_system_off(void) +{ + /* Send the power down request to the PMC */ + (void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN, + pm_get_shutdown_scope(), SECURE_FLAG); + + while (1) { + wfi(); + } +} + +/** + * versal_system_reset() - This function sends the reset request + * to firmware for the system to reset. This function does not return. + */ +static void __dead2 versal_system_reset(void) +{ + /* Send the system reset request to the PMC */ + (void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET, + pm_get_shutdown_scope(), SECURE_FLAG); + + while (1) { + wfi(); + } +} + +/** + * versal_pwr_domain_off() - This function performs actions to turn off core + * + * @target_state Targated state + */ +static void versal_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) { + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_versal_gic_cpuif_disable(); + + /* + * Send request to PMC to power down the appropriate APU CPU + * core. + * According to PSCI specification, CPU_off function does not + * have resume address and CPU core can only be woken up + * invoking CPU_on function, during which resume address will + * be set. + */ + (void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0, + SECURE_FLAG); +} + +/** + * versal_validate_power_state() - This function ensures that the power state + * parameter in request is valid. + * + * @power_state Power state of core + * @req_state Requested state + * + * @return Returns status, either success or reason + */ +static int versal_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); + + unsigned int pstate = psci_get_pstate_type(power_state); + + assert(req_state); + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + } else { + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE; + } + + /* We expect the 'state id' to be zero */ + if (psci_get_pstate_id(power_state) != 0U) { + return PSCI_E_INVALID_PARAMS; + } + + return PSCI_E_SUCCESS; +} + +/** + * versal_get_sys_suspend_power_state() - Get power state for system suspend + * + * @req_state Requested state + */ +static void versal_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE; +} + +static const struct plat_psci_ops versal_nopmc_psci_ops = { + .pwr_domain_on = versal_pwr_domain_on, + .pwr_domain_off = versal_pwr_domain_off, + .pwr_domain_on_finish = versal_pwr_domain_on_finish, + .pwr_domain_suspend = versal_pwr_domain_suspend, + .pwr_domain_suspend_finish = versal_pwr_domain_suspend_finish, + .system_off = versal_system_off, + .system_reset = versal_system_reset, + .validate_power_state = versal_validate_power_state, + .get_sys_suspend_power_state = versal_get_sys_suspend_power_state, +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + versal_sec_entry = sec_entrypoint; + + *psci_ops = &versal_nopmc_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/plat_topology.c b/arm-trusted-firmware/plat/xilinx/versal/plat_topology.c new file mode 100644 index 0000000..66d4fae --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/plat_topology.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +static const unsigned char plat_power_domain_tree_desc[] = {1, PLATFORM_CORE_COUNT}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/plat_versal.c b/arm-trusted-firmware/plat/xilinx/versal/plat_versal.c new file mode 100644 index 0000000..54c35b6 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/plat_versal.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + if ((mpidr & MPIDR_CLUSTER_MASK) != 0U) { + return -1; + } + + if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) { + return -1; + } + + return (int)versal_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/platform.mk b/arm-trusted-firmware/plat/xilinx/versal/platform.mk new file mode 100644 index 0000000..a8b2c94 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/platform.mk @@ -0,0 +1,94 @@ +# Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +override PROGRAMMABLE_RESET_ADDRESS := 1 +PSCI_EXTENDED_STATE_ID := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 +SEPARATE_CODE_AND_RODATA := 1 +override RESET_TO_BL31 := 1 +PL011_GENERIC_UART := 1 +IPI_CRC_CHECK := 0 +HARDEN_SLS_ALL := 0 + +ifdef VERSAL_ATF_MEM_BASE + $(eval $(call add_define,VERSAL_ATF_MEM_BASE)) + + ifndef VERSAL_ATF_MEM_SIZE + $(error "VERSAL_ATF_BASE defined without VERSAL_ATF_SIZE") + endif + $(eval $(call add_define,VERSAL_ATF_MEM_SIZE)) + + ifdef VERSAL_ATF_MEM_PROGBITS_SIZE + $(eval $(call add_define,VERSAL_ATF_MEM_PROGBITS_SIZE)) + endif +endif + +ifdef VERSAL_BL32_MEM_BASE + $(eval $(call add_define,VERSAL_BL32_MEM_BASE)) + + ifndef VERSAL_BL32_MEM_SIZE + $(error "VERSAL_BL32_BASE defined without VERSAL_BL32_SIZE") + endif + $(eval $(call add_define,VERSAL_BL32_MEM_SIZE)) +endif + +ifdef IPI_CRC_CHECK + $(eval $(call add_define,IPI_CRC_CHECK)) +endif + +VERSAL_PLATFORM ?= silicon +$(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM})) + +PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ + -Iplat/xilinx/common/include/ \ + -Iplat/xilinx/common/ipi_mailbox_service/ \ + -Iplat/xilinx/versal/include/ \ + -Iplat/xilinx/versal/pm_service/ + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + drivers/arm/dcc/dcc_console.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${GICV3_SOURCES} \ + drivers/arm/pl011/aarch64/pl011_console.S \ + plat/common/aarch64/crash_console_helpers.S \ + plat/arm/common/arm_cci.c \ + plat/arm/common/arm_common.c \ + plat/common/plat_gicv3.c \ + plat/xilinx/versal/aarch64/versal_helpers.S \ + plat/xilinx/versal/aarch64/versal_common.c + +VERSAL_CONSOLE ?= pl011 +ifeq (${VERSAL_CONSOLE}, $(filter ${VERSAL_CONSOLE},pl011 pl011_0 pl011_1 dcc)) +else + $(error "Please define VERSAL_CONSOLE") +endif + +$(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE})) + +BL31_SOURCES += drivers/arm/cci/cci.c \ + lib/cpus/aarch64/cortex_a72.S \ + plat/common/plat_psci_common.c \ + plat/xilinx/common/ipi.c \ + plat/xilinx/common/plat_startup.c \ + plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \ + plat/xilinx/common/pm_service/pm_ipi.c \ + plat/xilinx/versal/bl31_versal_setup.c \ + plat/xilinx/versal/plat_psci.c \ + plat/xilinx/versal/plat_versal.c \ + plat/xilinx/versal/plat_topology.c \ + plat/xilinx/versal/sip_svc_setup.c \ + plat/xilinx/versal/versal_gicv3.c \ + plat/xilinx/versal/versal_ipi.c \ + plat/xilinx/versal/pm_service/pm_svc_main.c \ + plat/xilinx/versal/pm_service/pm_api_sys.c \ + plat/xilinx/versal/pm_service/pm_client.c + +ifeq ($(HARDEN_SLS_ALL), 1) +TF_CFLAGS_aarch64 += -mharden-sls=all +endif diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c new file mode 100644 index 0000000..534d910 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -0,0 +1,1133 @@ +/* + * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Versal system level PM-API functions and communication with PMC via + * IPI interrupts + */ + +#include +#include +#include +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_defs.h" +#include "pm_svc_main.h" +#include "../drivers/arm/gic/v3/gicv3_private.h" + +/********************************************************************* + * Target module IDs macros + ********************************************************************/ +#define LIBPM_MODULE_ID 0x2U +#define LOADER_MODULE_ID 0x7U + +#define MODE 0x80000000U +/* default shutdown/reboot scope is system(2) */ +static unsigned int pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM; + +/** + * pm_get_shutdown_scope() - Get the currently set shutdown scope + * + * @return Shutdown scope value + */ +unsigned int pm_get_shutdown_scope(void) +{ + return pm_shutdown_scope; +} + +/** + * Assigning of argument values into array elements. + */ +#define PM_PACK_PAYLOAD1(pl, mid, flag, arg0) { \ + pl[0] = (uint32_t)(((uint32_t)(arg0) & 0xFFU) | ((mid) << 8U) | ((flag) << 24U)); \ +} + +#define PM_PACK_PAYLOAD2(pl, mid, flag, arg0, arg1) { \ + pl[1] = (uint32_t)(arg1); \ + PM_PACK_PAYLOAD1(pl, (mid), (flag), (arg0)); \ +} + +#define PM_PACK_PAYLOAD3(pl, mid, flag, arg0, arg1, arg2) { \ + pl[2] = (uint32_t)(arg2); \ + PM_PACK_PAYLOAD2(pl, (mid), (flag), (arg0), (arg1)); \ +} + +#define PM_PACK_PAYLOAD4(pl, mid, flag, arg0, arg1, arg2, arg3) { \ + pl[3] = (uint32_t)(arg3); \ + PM_PACK_PAYLOAD3(pl, (mid), (flag), (arg0), (arg1), (arg2)); \ +} + +#define PM_PACK_PAYLOAD5(pl, mid, flag, arg0, arg1, arg2, arg3, arg4) { \ + pl[4] = (uint32_t)(arg4); \ + PM_PACK_PAYLOAD4(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3)); \ +} + +#define PM_PACK_PAYLOAD6(pl, mid, flag, arg0, arg1, arg2, arg3, arg4, arg5) { \ + pl[5] = (uint32_t)(arg5); \ + PM_PACK_PAYLOAD5(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4)); \ +} + +/* PM API functions */ + +/** + * pm_get_api_version() - Get version number of PMC PM firmware + * @version Returns 32-bit version number of PMC Power Management Firmware + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_get_api_version(unsigned int *version, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_GET_API_VERSION); + return pm_ipi_send_sync(primary_proc, payload, version, 1); +} + +/** + * pm_init_finalize() - Call to notify PMC PM firmware that master has power + * management enabled and that it has finished its + * initialization + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Status returned by the PMU firmware + */ +enum pm_ret_status pm_init_finalize(uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_INIT_FINALIZE); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_self_suspend() - PM call for processor to suspend itself + * @nid Node id of the processor or subsystem + * @latency Requested maximum wakeup latency (not supported) + * @state Requested state + * @address Resume address + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * This is a blocking call, it will return only once PMU has responded. + * On a wakeup, resume address will be automatically set by PMU. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_self_suspend(uint32_t nid, + unsigned int latency, + unsigned int state, + uintptr_t address, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + unsigned int cpuid = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpuid); + + if (proc == NULL) { + WARN("Failed to get proc %d\n", cpuid); + return PM_RET_ERROR_INTERNAL; + } + + /* + * Do client specific suspend operations + * (e.g. set powerdown request bit) + */ + pm_client_suspend(proc, state); + + /* Send request to the PLM */ + PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, flag, PM_SELF_SUSPEND, + proc->node_id, latency, state, address, + (address >> 32)); + return pm_ipi_send_sync(proc, payload, NULL, 0); +} + +/** + * pm_abort_suspend() - PM call to announce that a prior suspend request + * is to be aborted. + * @reason Reason for the abort + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * Calling PU expects the PMU to abort the initiated suspend procedure. + * This is a non-blocking call without any acknowledge. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* + * Do client specific abort suspend operations + * (e.g. enable interrupts and clear powerdown request bit) + */ + pm_client_abort_suspend(); + + /* Send request to the PLM */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND, + reason, primary_proc->node_id); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_req_suspend() - PM call to request for another PU or subsystem to + * be suspended gracefully. + * @target Node id of the targeted PU or subsystem + * @ack Flag to specify whether acknowledge is requested + * @latency Requested wakeup latency (not supported) + * @state Requested state (not supported) + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack, + unsigned int latency, unsigned int state, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target, + latency, state); + if (ack == IPI_BLOCKING) { + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + } else { + return pm_ipi_send(primary_proc, payload); + } +} + +/** + * pm_req_wakeup() - PM call for processor to wake up selected processor + * or subsystem + * @target Device ID of the processor or subsystem to wake up + * @set_address Resume address presence indicator + * 1 - resume address specified, 0 - otherwise + * @address Resume address + * @ack Flag to specify whether acknowledge requested + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * This API function is either used to power up another APU core for SMP + * (by PSCI) or to power up an entirely different PU or subsystem, such + * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be + * automatically set by PMC. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, + uintptr_t address, uint8_t ack, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC to perform the wake of the PU */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQ_WAKEUP, target, + set_address, address, ack); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_request_device() - Request a device + * @device_id Device ID + * @capabilities Requested capabilities for the device + * @qos Required Quality of Service + * @ack Flag to specify whether acknowledge requested + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_request_device(uint32_t device_id, uint32_t capabilities, + uint32_t qos, uint32_t ack, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQUEST_DEVICE, + device_id, capabilities, qos, ack); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_release_device() - Release a device + * @device_id Device ID + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_release_device(uint32_t device_id, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_RELEASE_DEVICE, + device_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_set_requirement() - Set requirement for the device + * @device_id Device ID + * @capabilities Requested capabilities for the device + * @latency Requested maximum latency + * @qos Required Quality of Service + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, + uint32_t latency, uint32_t qos, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_SET_REQUIREMENT, + device_id, capabilities, latency, qos); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_get_device_status() - Get device's status + * @device_id Device ID + * @response Buffer to store device status response + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_GET_DEVICE_STATUS, + device_id); + + return pm_ipi_send_sync(primary_proc, payload, response, 3); +} + +/** + * pm_reset_assert() - Assert/De-assert reset + * @reset Reset ID + * @assert Assert (1) or de-assert (0) + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_RESET_ASSERT, reset, + assert); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_reset_get_status() - Get current status of a reset line + * @reset Reset ID + * @status Returns current status of selected reset ID + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_RESET_ASSERT, + reset); + + return pm_ipi_send_sync(primary_proc, payload, status, 1); +} + +/** + * pm_get_callbackdata() - Read from IPI response buffer + * @data - array of PAYLOAD_ARG_CNT elements + * @flag - 0 - Call from secure source + * 1 - Call from non-secure source + * + * Read value from ipi buffer response buffer. + */ +void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag) +{ + /* Return if interrupt is not from PMU */ + if (pm_ipi_irq_status(primary_proc) == 0) { + return; + } + + pm_ipi_buff_read_callb(data, count); + pm_ipi_irq_clear(primary_proc); +} + +/** + * pm_pinctrl_request() - Request a pin + * @pin Pin ID + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_request(uint32_t pin, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PINCTRL_REQUEST, + pin); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_release() - Release a pin + * @pin Pin ID + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_release(uint32_t pin, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PINCTRL_RELEASE, + pin); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_set_function() - Set pin function + * @pin Pin ID + * @function Function ID + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_set_function(uint32_t pin, uint32_t function, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, + PM_PINCTRL_SET_FUNCTION, pin, function) + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_get_function() - Get function set on the pin + * @pin Pin ID + * @function Function set on the pin + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_get_function(uint32_t pin, uint32_t *function, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, + PM_PINCTRL_SET_FUNCTION, pin); + + return pm_ipi_send_sync(primary_proc, payload, function, 1); +} + +/** + * pm_pinctrl_set_pin_param() - Set configuration parameter for the pin + * @pin Pin ID + * @param Parameter ID + * @value Parameter value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_set_pin_param(uint32_t pin, uint32_t param, + uint32_t value, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, + PM_PINCTRL_CONFIG_PARAM_SET, pin, param, value); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_get_pin_param() - Get configuration parameter value for the pin + * @pin Pin ID + * @param Parameter ID + * @value Buffer to store parameter value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param, + uint32_t *value, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, + PM_PINCTRL_CONFIG_PARAM_GET, pin, param); + + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/** + * pm_clock_enable() - Enable the clock + * @clk_id Clock ID + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_enable(uint32_t clk_id, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_ENABLE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_disable() - Disable the clock + * @clk_id Clock ID + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_disable(uint32_t clk_id, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_DISABLE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_state() - Get clock status + * @clk_id Clock ID + * @state: Buffer to store clock status (1: Enabled, 0:Disabled) + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_get_state(uint32_t clk_id, uint32_t *state, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETSTATE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, state, 1); +} + +/** + * pm_clock_set_divider() - Set divider for the clock + * @clk_id Clock ID + * @divider Divider value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_SETDIVIDER, + clk_id, divider); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_divider() - Get divider value for the clock + * @clk_id Clock ID + * @divider: Buffer to store clock divider value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETDIVIDER, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, divider, 1); +} + +/** + * pm_clock_set_parent() - Set parent for the clock + * @clk_id Clock ID + * @parent Parent ID + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_SETPARENT, + clk_id, parent); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_parent() - Get parent value for the clock + * @clk_id Clock ID + * @parent: Buffer to store clock parent value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETPARENT, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, parent, 1); +} +/** + * pm_clock_get_rate() - Get the rate value for the clock + * @clk_id Clock ID + * @rate: Buffer to store clock rate value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETRATE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, clk_rate, 2); +} + +/** + * pm_pll_set_param() - Set PLL parameter + * @clk_id PLL clock ID + * @param PLL parameter ID + * @value Value to set for PLL parameter + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param, + uint32_t value, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_PARAMETER, + clk_id, param, value); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pll_get_param() - Get PLL parameter value + * @clk_id PLL clock ID + * @param PLL parameter ID + * @value: Buffer to store PLL parameter value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, + uint32_t *value, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_PARAMETER, + clk_id, param); + + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/** + * pm_pll_set_mode() - Set PLL mode + * @clk_id PLL clock ID + * @mode PLL mode + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_MODE, + clk_id, mode); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pll_get_mode() - Get PLL mode + * @clk_id PLL clock ID + * @mode: Buffer to store PLL mode + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_MODE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, mode, 1); +} + +/** + * pm_force_powerdown() - PM call to request for another PU or subsystem to + * be powered down forcefully + * @target Device ID of the PU node to be forced powered down. + * @ack Flag to specify whether acknowledge is requested + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN, + target, ack); + + if (ack == IPI_BLOCKING) { + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + } else { + return pm_ipi_send(primary_proc, payload); + } +} + +/** + * pm_system_shutdown() - PM call to request a system shutdown or restart + * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope + * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) { + /* Setting scope for subsequent PSCI reboot or shutdown */ + pm_shutdown_scope = subtype; + return PM_RET_SUCCESS; + } + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN, + type, subtype); + + return pm_ipi_send_non_blocking(primary_proc, payload); +} + +/** +* pm_query_data() - PM API for querying firmware data +* @qid The type of data to query +* @arg1 Argument 1 to requested query data call +* @arg2 Argument 2 to requested query data call +* @arg3 Argument 3 to requested query data call +* @data Returned output data +* @flag 0 - Call from secure source +* 1 - Call from non-secure source +* +* This function returns requested data. +*/ +enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, + uint32_t arg3, uint32_t *data, uint32_t flag) +{ + uint32_t ret; + uint32_t version; + uint32_t payload[PAYLOAD_ARG_CNT]; + uint32_t fw_api_version; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_QUERY_DATA, qid, + arg1, arg2, arg3); + + ret = pm_feature_check(PM_QUERY_DATA, &version, flag); + if (PM_RET_SUCCESS == ret) { + fw_api_version = version & 0xFFFFU; + if ((2U == fw_api_version) && + ((XPM_QID_CLOCK_GET_NAME == qid) || + (XPM_QID_PINCTRL_GET_FUNCTION_NAME == qid))) { + ret = pm_ipi_send_sync(primary_proc, payload, data, 8); + ret = data[0]; + data[0] = data[1]; + data[1] = data[2]; + data[2] = data[3]; + } else { + ret = pm_ipi_send_sync(primary_proc, payload, data, 4); + } + } + return ret; +} +/** + * pm_api_ioctl() - PM IOCTL API for device control and configs + * @device_id Device ID + * @ioctl_id ID of the requested IOCTL + * @arg1 Argument 1 to requested IOCTL call + * @arg2 Argument 2 to requested IOCTL call + * @value Returned output value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * This function calls IOCTL to firmware for device control and configuration. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, + uint32_t arg1, uint32_t arg2, uint32_t *value, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + enum pm_ret_status ret; + + switch (ioctl_id) { + case IOCTL_SET_PLL_FRAC_MODE: + ret = pm_pll_set_mode(arg1, arg2, flag); + break; + case IOCTL_GET_PLL_FRAC_MODE: + ret = pm_pll_get_mode(arg1, value, flag); + break; + case IOCTL_SET_PLL_FRAC_DATA: + ret = pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2, flag); + break; + case IOCTL_GET_PLL_FRAC_DATA: + ret = pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value, flag); + break; + case IOCTL_SET_SGI: + /* Get the sgi number */ + if (pm_register_sgi(arg1) != 0) { + return PM_RET_ERROR_ARGS; + } + gicd_write_irouter(gicv3_driver_data->gicd_base, + (unsigned int)PLAT_VERSAL_IPI_IRQ, MODE); + ret = PM_RET_SUCCESS; + break; + default: + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_IOCTL, + device_id, ioctl_id, arg1, arg2); + ret = pm_ipi_send_sync(primary_proc, payload, value, 1); + break; + } + + return ret; +} + +/** + * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended + * @target Device id of the targeted PU or subsystem + * @wkup_node Device id of the wakeup peripheral + * @enable Enable or disable the specified peripheral as wake source + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device, + uint8_t enable, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE, + target, wkup_device, enable); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_get_chipid() - Read silicon ID registers + * @value Buffer for return values. Must be large enough + * to hold 8 bytes. + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns silicon ID registers + */ +enum pm_ret_status pm_get_chipid(uint32_t *value, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_GET_CHIPID); + + return pm_ipi_send_sync(primary_proc, payload, value, 2); +} + +/** + * pm_feature_check() - Returns the supported API version if supported + * @api_id API ID to check + * @value Returned supported API version + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT], fw_api_version; + enum pm_ret_status status = PM_RET_ERROR_NOFEATURE; + + switch (api_id) { + case PM_GET_CALLBACK_DATA: + case PM_GET_TRUSTZONE_VERSION: + case PM_LOAD_PDI: + *version = (PM_API_BASE_VERSION << 16); + status = PM_RET_SUCCESS; + break; + case PM_GET_API_VERSION: + case PM_GET_DEVICE_STATUS: + case PM_GET_OP_CHARACTERISTIC: + case PM_REQ_SUSPEND: + case PM_SELF_SUSPEND: + case PM_FORCE_POWERDOWN: + case PM_ABORT_SUSPEND: + case PM_REQ_WAKEUP: + case PM_SET_WAKEUP_SOURCE: + case PM_SYSTEM_SHUTDOWN: + case PM_REQUEST_DEVICE: + case PM_RELEASE_DEVICE: + case PM_SET_REQUIREMENT: + case PM_RESET_ASSERT: + case PM_RESET_GET_STATUS: + case PM_GET_CHIPID: + case PM_PINCTRL_REQUEST: + case PM_PINCTRL_RELEASE: + case PM_PINCTRL_GET_FUNCTION: + case PM_PINCTRL_SET_FUNCTION: + case PM_PINCTRL_CONFIG_PARAM_GET: + case PM_PINCTRL_CONFIG_PARAM_SET: + case PM_IOCTL: + case PM_CLOCK_ENABLE: + case PM_CLOCK_DISABLE: + case PM_CLOCK_GETSTATE: + case PM_CLOCK_SETDIVIDER: + case PM_CLOCK_GETDIVIDER: + case PM_CLOCK_SETPARENT: + case PM_CLOCK_GETPARENT: + case PM_CLOCK_GETRATE: + case PM_PLL_SET_PARAMETER: + case PM_PLL_GET_PARAMETER: + case PM_PLL_SET_MODE: + case PM_PLL_GET_MODE: + case PM_FEATURE_CHECK: + case PM_INIT_FINALIZE: + case PM_SET_MAX_LATENCY: + case PM_REGISTER_NOTIFIER: + *version = (PM_API_BASE_VERSION << 16); + status = PM_RET_SUCCESS; + break; + case PM_QUERY_DATA: + *version = (PM_API_QUERY_DATA_VERSION << 16); + status = PM_RET_SUCCESS; + break; + default: + *version = 0U; + status = PM_RET_ERROR_NOFEATURE; + break; + } + + if (status != PM_RET_SUCCESS) { + goto done; + } + + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, + PM_FEATURE_CHECK, api_id); + + status = pm_ipi_send_sync(primary_proc, payload, &fw_api_version, 1); + if (status != PM_RET_SUCCESS) { + goto done; + } + + *version |= fw_api_version; + + status = PM_RET_SUCCESS; + +done: + return status; +} + +/** + * pm_load_pdi() - Load the PDI + * + * This function provides support to load PDI from linux + * + * src: Source device of pdi(DDR, OCM, SD etc) + * address_low: lower 32-bit Linear memory space address + * address_high: higher 32-bit Linear memory space address + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, + uint32_t address_high, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src, + address_high, address_low); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_get_op_characteristic() - PM call to request operating characteristics + * of a device + * @device_id Device id + * @type Type of the operating characteristic + * (power, temperature and latency) + * @result Returns the operating characteristic for the requested device, + * specified by the type + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_get_op_characteristic(uint32_t device_id, + enum pm_opchar_type type, + uint32_t *result, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, + PM_GET_OP_CHARACTERISTIC, device_id, type); + return pm_ipi_send_sync(primary_proc, payload, result, 1); +} + +/** + * pm_set_max_latency() - PM call to change in the maximum wake-up latency + * requirements for a specific device currently + * used by that CPU. + * @device_id Device ID + * @latency Latency value + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SET_MAX_LATENCY, + device_id, latency); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_register_notifier() - PM call to register a subsystem to be notified + * about the device event + * @device_id Device ID for the Node to which the event is related + * @event Event in question + * @wake Wake subsystem upon capturing the event if value 1 + * @enable Enable the registration for value 1, disable for value 0 + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event, + uint32_t wake, uint32_t enable, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER, + device_id, event, wake, enable); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h new file mode 100644 index 0000000..5a92704 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_API_SYS_H +#define PM_API_SYS_H + +#include +#include "pm_defs.h" + +/********************************************************** + * PM API function declarations + **********************************************************/ + +enum pm_ret_status pm_get_api_version(unsigned int *version, uint32_t flag); +enum pm_ret_status pm_init_finalize(uint32_t flag); +enum pm_ret_status pm_self_suspend(uint32_t nid, + unsigned int latency, + unsigned int state, + uintptr_t address, uint32_t flag); +enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag); +enum pm_ret_status pm_req_suspend(uint32_t target, + uint8_t ack, + unsigned int latency, + unsigned int state, uint32_t flag); +enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, + uintptr_t address, uint8_t ack, uint32_t flag); +enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t device_id, + uint8_t enable, uint32_t flag); +enum pm_ret_status pm_request_device(uint32_t device_id, uint32_t capabilities, + uint32_t qos, uint32_t ack, uint32_t flag); +enum pm_ret_status pm_release_device(uint32_t device_id, uint32_t flag); +enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, + uint32_t latency, uint32_t qos, + uint32_t flag); +enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response, + uint32_t flag); +enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert, uint32_t flag); +enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status, + uint32_t flag); +void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag); +enum pm_ret_status pm_pinctrl_request(uint32_t pin, uint32_t flag); +enum pm_ret_status pm_pinctrl_release(uint32_t pin, uint32_t flag); +enum pm_ret_status pm_pinctrl_set_function(uint32_t pin, uint32_t function, + uint32_t flag); +enum pm_ret_status pm_pinctrl_get_function(uint32_t pin, uint32_t *function, + uint32_t flag); +enum pm_ret_status pm_pinctrl_set_pin_param(uint32_t pin, uint32_t param, + uint32_t value, uint32_t flag); +enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param, + uint32_t *value, uint32_t flag); +enum pm_ret_status pm_clock_enable(uint32_t clk_id, uint32_t flag); +enum pm_ret_status pm_clock_disable(uint32_t clk_id, uint32_t flag); +enum pm_ret_status pm_clock_get_state(uint32_t clk_id, uint32_t *state, + uint32_t flag); +enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider, + uint32_t flag); +enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider, + uint32_t flag); +enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent, + uint32_t flag); +enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent, + uint32_t flag); +enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate, + uint32_t flag); +enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param, + uint32_t value, uint32_t flag); +enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, + uint32_t *value, uint32_t flag); +enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode, + uint32_t flag); +enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode, + uint32_t flag); +enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack, + uint32_t flag); +enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype, + uint32_t flag); +enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, + uint32_t arg1, uint32_t arg2, uint32_t *value, + uint32_t flag); +enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, + uint32_t arg3, uint32_t *data, uint32_t flag); +unsigned int pm_get_shutdown_scope(void); +enum pm_ret_status pm_get_chipid(uint32_t *value, uint32_t flag); +enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version, + uint32_t flag); +enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, + uint32_t address_high, uint32_t flag); +enum pm_ret_status pm_get_op_characteristic(uint32_t device_id, + enum pm_opchar_type type, + uint32_t *result, uint32_t flag); +enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency, + uint32_t flag); +enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event, + uint32_t wake, uint32_t enable, + uint32_t flag); +#endif /* PM_API_SYS_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c new file mode 100644 index 0000000..4c1d340 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * APU specific definition of processors in the subsystem as well as functions + * for getting information about and changing state of the APU. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pm_api_sys.h" +#include "pm_client.h" + +#define UNDEFINED_CPUID (~0) +#define IRQ_MAX 142U +#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5U) + 1U) + +DEFINE_BAKERY_LOCK(pm_client_secure_lock); + +static const struct pm_ipi apu_ipi = { + .local_ipi_id = IPI_ID_APU, + .remote_ipi_id = IPI_ID_PMC, + .buffer_base = IPI_BUFFER_APU_BASE, +}; + +/* Order in pm_procs_all array must match cpu ids */ +static const struct pm_proc pm_procs_all[] = { + { + .node_id = XPM_DEVID_ACPU_0, + .ipi = &apu_ipi, + .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK, + }, + { + .node_id = XPM_DEVID_ACPU_1, + .ipi = &apu_ipi, + .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK, + } +}; + +const struct pm_proc *primary_proc = &pm_procs_all[0]; + +/* Interrupt to PM node index map */ +static enum pm_device_node_idx irq_node_map[IRQ_MAX + 1] = { + [13] = XPM_NODEIDX_DEV_GPIO, + [14] = XPM_NODEIDX_DEV_I2C_0, + [15] = XPM_NODEIDX_DEV_I2C_1, + [16] = XPM_NODEIDX_DEV_SPI_0, + [17] = XPM_NODEIDX_DEV_SPI_1, + [18] = XPM_NODEIDX_DEV_UART_0, + [19] = XPM_NODEIDX_DEV_UART_1, + [20] = XPM_NODEIDX_DEV_CAN_FD_0, + [21] = XPM_NODEIDX_DEV_CAN_FD_1, + [22] = XPM_NODEIDX_DEV_USB_0, + [23] = XPM_NODEIDX_DEV_USB_0, + [24] = XPM_NODEIDX_DEV_USB_0, + [25] = XPM_NODEIDX_DEV_USB_0, + [26] = XPM_NODEIDX_DEV_USB_0, + [37] = XPM_NODEIDX_DEV_TTC_0, + [38] = XPM_NODEIDX_DEV_TTC_0, + [39] = XPM_NODEIDX_DEV_TTC_0, + [40] = XPM_NODEIDX_DEV_TTC_1, + [41] = XPM_NODEIDX_DEV_TTC_1, + [42] = XPM_NODEIDX_DEV_TTC_1, + [43] = XPM_NODEIDX_DEV_TTC_2, + [44] = XPM_NODEIDX_DEV_TTC_2, + [45] = XPM_NODEIDX_DEV_TTC_2, + [46] = XPM_NODEIDX_DEV_TTC_3, + [47] = XPM_NODEIDX_DEV_TTC_3, + [48] = XPM_NODEIDX_DEV_TTC_3, + [56] = XPM_NODEIDX_DEV_GEM_0, + [57] = XPM_NODEIDX_DEV_GEM_0, + [58] = XPM_NODEIDX_DEV_GEM_1, + [59] = XPM_NODEIDX_DEV_GEM_1, + [60] = XPM_NODEIDX_DEV_ADMA_0, + [61] = XPM_NODEIDX_DEV_ADMA_1, + [62] = XPM_NODEIDX_DEV_ADMA_2, + [63] = XPM_NODEIDX_DEV_ADMA_3, + [64] = XPM_NODEIDX_DEV_ADMA_4, + [65] = XPM_NODEIDX_DEV_ADMA_5, + [66] = XPM_NODEIDX_DEV_ADMA_6, + [67] = XPM_NODEIDX_DEV_ADMA_7, + [74] = XPM_NODEIDX_DEV_USB_0, + [126] = XPM_NODEIDX_DEV_SDIO_0, + [127] = XPM_NODEIDX_DEV_SDIO_0, + [128] = XPM_NODEIDX_DEV_SDIO_1, + [129] = XPM_NODEIDX_DEV_SDIO_1, + [142] = XPM_NODEIDX_DEV_RTC, +}; + +/** + * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number + * @irq: Interrupt number + * + * Return: PM node index corresponding to the specified interrupt + */ +static enum pm_device_node_idx irq_to_pm_node_idx(unsigned int irq) +{ + assert(irq <= IRQ_MAX); + return irq_node_map[irq]; +} + +/** + * pm_client_set_wakeup_sources - Set all devices with enabled interrupts as + * wake sources in the LibPM. + * @node_id: Node id of processor + */ +static void pm_client_set_wakeup_sources(uint32_t node_id) +{ + uint32_t reg_num; + uint32_t device_id; + uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX]; + uintptr_t isenabler1 = PLAT_VERSAL_GICD_BASE + GICD_ISENABLER + 4; + + zeromem(&pm_wakeup_nodes_set, (u_register_t)sizeof(pm_wakeup_nodes_set)); + + for (reg_num = 0U; reg_num < NUM_GICD_ISENABLER; reg_num++) { + uint32_t base_irq = reg_num << ISENABLER_SHIFT; + uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2)); + + if (reg == 0U) { + continue; + } + + while (reg != 0U) { + enum pm_device_node_idx node_idx; + uint32_t idx, irq, lowest_set = reg & (-reg); + enum pm_ret_status ret; + + idx = __builtin_ctz(lowest_set); + irq = base_irq + idx; + + if (irq > IRQ_MAX) { + break; + } + + node_idx = irq_to_pm_node_idx(irq); + reg &= ~lowest_set; + + if ((node_idx != XPM_NODEIDX_DEV_MIN) && + (pm_wakeup_nodes_set[node_idx] == 0U)) { + /* Get device ID from node index */ + device_id = PERIPH_DEVID(node_idx); + ret = pm_set_wakeup_source(node_id, + device_id, 1, + SECURE_FLAG); + pm_wakeup_nodes_set[node_idx] = (uint8_t)(!ret); + } + } + } +} + +/** + * pm_client_suspend() - Client-specific suspend actions + * + * This function should contain any PU-specific actions + * required prior to sending suspend request to PMU + * Actions taken depend on the state system is suspending to. + */ +void pm_client_suspend(const struct pm_proc *proc, unsigned int state) +{ + bakery_lock_get(&pm_client_secure_lock); + + if (state == PM_STATE_SUSPEND_TO_RAM) { + pm_client_set_wakeup_sources((uint32_t)proc->node_id); + } + + /* Set powerdown request */ + mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | + (uint32_t)proc->pwrdn_mask); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_client_abort_suspend() - Client-specific abort-suspend actions + * + * This function should contain any PU-specific actions + * required for aborting a prior suspend request + */ +void pm_client_abort_suspend(void) +{ + /* Enable interrupts at processor level (for current cpu) */ + gicv3_cpuif_enable(plat_my_core_pos()); + + bakery_lock_get(&pm_client_secure_lock); + + /* Clear powerdown request */ + mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) & + ~((uint32_t)primary_proc->pwrdn_mask)); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_get_cpuid() - get the local cpu ID for a global node ID + * @nid: node id of the processor + * + * Return: the cpu ID (starting from 0) for the subsystem + */ +static unsigned int pm_get_cpuid(uint32_t nid) +{ + for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) { + if (pm_procs_all[i].node_id == nid) { + return i; + } + } + return UNDEFINED_CPUID; +} + +/** + * pm_client_wakeup() - Client-specific wakeup actions + * + * This function should contain any PU-specific actions + * required for waking up another APU core + */ +void pm_client_wakeup(const struct pm_proc *proc) +{ + unsigned int cpuid = pm_get_cpuid(proc->node_id); + + if (cpuid == UNDEFINED_CPUID) { + return; + } + + bakery_lock_get(&pm_client_secure_lock); + + /* clear powerdown bit for affected cpu */ + uint32_t val = mmio_read_32(FPD_APU_PWRCTL); + val &= ~(proc->pwrdn_mask); + mmio_write_32(FPD_APU_PWRCTL, val); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_get_proc() - returns pointer to the proc structure + * @cpuid: id of the cpu whose proc struct pointer should be returned + * + * Return: pointer to a proc structure if proc is found, otherwise NULL + */ +const struct pm_proc *pm_get_proc(unsigned int cpuid) +{ + if (cpuid < ARRAY_SIZE(pm_procs_all)) { + return &pm_procs_all[cpuid]; + } + + return NULL; +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h new file mode 100644 index 0000000..08b46e2 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Versal power management enums and defines */ + +#ifndef PM_DEFS_H +#define PM_DEFS_H + +#include "pm_node.h" + +/********************************************************************* + * Macro definitions + ********************************************************************/ + +/* State arguments of the self suspend */ +#define PM_STATE_CPU_IDLE 0x0U +#define PM_STATE_SUSPEND_TO_RAM 0xFU + +#define MAX_LATENCY (~0U) +#define MAX_QOS 100U + +/* Processor core device IDs */ +#define APU_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, XPM_NODESUBCL_DEV_CORE, \ + XPM_NODETYPE_DEV_CORE_APU, (IDX)) + +#define XPM_DEVID_ACPU_0 APU_DEVID(XPM_NODEIDX_DEV_ACPU_0) +#define XPM_DEVID_ACPU_1 APU_DEVID(XPM_NODEIDX_DEV_ACPU_1) + +#define PERIPH_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, \ + XPM_NODESUBCL_DEV_PERIPH, \ + XPM_NODETYPE_DEV_PERIPH, (IDX)) + +#define PM_GET_CALLBACK_DATA 0xa01U +#define PM_GET_TRUSTZONE_VERSION 0xa03U + +/* PM API Versions */ +#define PM_API_BASE_VERSION 1U + +#define PM_API_QUERY_DATA_VERSION 2U + +/* PM API ids */ +#define PM_GET_API_VERSION 1U +#define PM_GET_DEVICE_STATUS 3U +#define PM_GET_OP_CHARACTERISTIC 4U +#define PM_REGISTER_NOTIFIER 5U +#define PM_REQ_SUSPEND 6U +#define PM_SELF_SUSPEND 7U +#define PM_FORCE_POWERDOWN 8U +#define PM_ABORT_SUSPEND 9U +#define PM_REQ_WAKEUP 10U +#define PM_SET_WAKEUP_SOURCE 11U +#define PM_SYSTEM_SHUTDOWN 12U +#define PM_REQUEST_DEVICE 13U +#define PM_RELEASE_DEVICE 14U +#define PM_SET_REQUIREMENT 15U +#define PM_SET_MAX_LATENCY 16U +#define PM_RESET_ASSERT 17U +#define PM_RESET_GET_STATUS 18U +#define PM_INIT_FINALIZE 21U +#define PM_GET_CHIPID 24U +#define PM_PINCTRL_REQUEST 28U +#define PM_PINCTRL_RELEASE 29U +#define PM_PINCTRL_GET_FUNCTION 30U +#define PM_PINCTRL_SET_FUNCTION 31U +#define PM_PINCTRL_CONFIG_PARAM_GET 32U +#define PM_PINCTRL_CONFIG_PARAM_SET 33U +#define PM_IOCTL 34U +#define PM_QUERY_DATA 35U +#define PM_CLOCK_ENABLE 36U +#define PM_CLOCK_DISABLE 37U +#define PM_CLOCK_GETSTATE 38U +#define PM_CLOCK_SETDIVIDER 39U +#define PM_CLOCK_GETDIVIDER 40U +#define PM_CLOCK_SETRATE 41U +#define PM_CLOCK_GETRATE 42U +#define PM_CLOCK_SETPARENT 43U +#define PM_CLOCK_GETPARENT 44U +#define PM_PLL_SET_PARAMETER 48U +#define PM_PLL_GET_PARAMETER 49U +#define PM_PLL_SET_MODE 50U +#define PM_PLL_GET_MODE 51U +#define PM_FEATURE_CHECK 63U + +/* Loader API ids */ +#define PM_LOAD_PDI 0x701U + +/* IOCTL IDs for clock driver */ +#define IOCTL_SET_PLL_FRAC_MODE 8U +#define IOCTL_GET_PLL_FRAC_MODE 9U +#define IOCTL_SET_PLL_FRAC_DATA 10U +#define IOCTL_GET_PLL_FRAC_DATA 11U +#define IOCTL_SET_SGI 25U + +/* Parameter ID for PLL IOCTLs */ +/* Fractional data portion for PLL */ +#define PM_PLL_PARAM_DATA 2 + +/* System shutdown macros */ +#define XPM_SHUTDOWN_TYPE_SHUTDOWN 0U +#define XPM_SHUTDOWN_TYPE_RESET 1U +#define XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY 2U + +#define XPM_SHUTDOWN_SUBTYPE_RST_SUBSYSTEM 0U +#define XPM_SHUTDOWN_SUBTYPE_RST_PS_ONLY 1U +#define XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM 2U + +/********************************************************************* + * Enum definitions + ********************************************************************/ + +enum pm_abort_reason { + ABORT_REASON_WKUP_EVENT = 100, + ABORT_REASON_PU_BUSY, + ABORT_REASON_NO_PWRDN, + ABORT_REASON_UNKNOWN, +}; + +enum pm_opchar_type { + PM_OPCHAR_TYPE_POWER = 1, + PM_OPCHAR_TYPE_TEMP, + PM_OPCHAR_TYPE_LATENCY, +}; + +/** + * Subsystem IDs + */ +typedef enum { + XPM_SUBSYSID_PMC, + XPM_SUBSYSID_PSM, + XPM_SUBSYSID_APU, + XPM_SUBSYSID_RPU0_LOCK, + XPM_SUBSYSID_RPU0_0, + XPM_SUBSYSID_RPU0_1, + XPM_SUBSYSID_DDR0, + XPM_SUBSYSID_ME, + XPM_SUBSYSID_PL, + XPM_SUBSYSID_MAX, +} XPm_SubsystemId; + +/** + * @PM_RET_SUCCESS: success + * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated) + * @PM_RET_ERROR_NOTSUPPORTED: feature not supported (deprecated) + * @PM_RET_ERROR_NOFEATURE: feature is not available + * @PM_RET_ERROR_INTERNAL: internal error + * @PM_RET_ERROR_CONFLICT: conflict + * @PM_RET_ERROR_ACCESS: access rights violation + * @PM_RET_ERROR_INVALID_NODE: invalid node + * @PM_RET_ERROR_DOUBLE_REQ: duplicate request for same node + * @PM_RET_ERROR_ABORT_SUSPEND: suspend procedure has been aborted + * @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU + * @PM_RET_ERROR_NODE_USED: node is already in use + */ +enum pm_ret_status { + PM_RET_SUCCESS, + PM_RET_ERROR_ARGS = 1, + PM_RET_ERROR_NOTSUPPORTED = 4, + PM_RET_ERROR_NOFEATURE = 19, + PM_RET_ERROR_INTERNAL = 2000, + PM_RET_ERROR_CONFLICT = 2001, + PM_RET_ERROR_ACCESS = 2002, + PM_RET_ERROR_INVALID_NODE = 2003, + PM_RET_ERROR_DOUBLE_REQ = 2004, + PM_RET_ERROR_ABORT_SUSPEND = 2005, + PM_RET_ERROR_TIMEOUT = 2006, + PM_RET_ERROR_NODE_USED = 2007 +}; + +/** + * Qids + */ +enum pm_query_id { + XPM_QID_INVALID, + XPM_QID_CLOCK_GET_NAME, + XPM_QID_CLOCK_GET_TOPOLOGY, + XPM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS, + XPM_QID_CLOCK_GET_MUXSOURCES, + XPM_QID_CLOCK_GET_ATTRIBUTES, + XPM_QID_PINCTRL_GET_NUM_PINS, + XPM_QID_PINCTRL_GET_NUM_FUNCTIONS, + XPM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS, + XPM_QID_PINCTRL_GET_FUNCTION_NAME, + XPM_QID_PINCTRL_GET_FUNCTION_GROUPS, + XPM_QID_PINCTRL_GET_PIN_GROUPS, + XPM_QID_CLOCK_GET_NUM_CLOCKS, + XPM_QID_CLOCK_GET_MAX_DIVISOR, + XPM_QID_PLD_GET_PARENT, +}; +#endif /* PM_DEFS_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h new file mode 100644 index 0000000..1b82ec7 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Versal PM nodes enums and defines */ + +#ifndef PM_NODE_H +#define PM_NODE_H + +/********************************************************************* + * Macro definitions + ********************************************************************/ + +#define NODE_CLASS_SHIFT 26U +#define NODE_SUBCLASS_SHIFT 20U +#define NODE_TYPE_SHIFT 14U +#define NODE_INDEX_SHIFT 0U +#define NODE_CLASS_MASK_BITS 0x3F +#define NODE_SUBCLASS_MASK_BITS 0x3F +#define NODE_TYPE_MASK_BITS 0x3F +#define NODE_INDEX_MASK_BITS 0x3FFF +#define NODE_CLASS_MASK (NODE_CLASS_MASK_BITS << NODE_CLASS_SHIFT) +#define NODE_SUBCLASS_MASK (NODE_SUBCLASS_MASK_BITS << NODE_SUBCLASS_SHIFT) +#define NODE_TYPE_MASK (NODE_TYPE_MASK_BITS << NODE_TYPE_SHIFT) +#define NODE_INDEX_MASK (NODE_INDEX_MASK_BITS << NODE_INDEX_SHIFT) + +#define NODEID(CLASS, SUBCLASS, TYPE, INDEX) \ + ((((CLASS) & NODE_CLASS_MASK_BITS) << NODE_CLASS_SHIFT) | \ + (((SUBCLASS) & NODE_SUBCLASS_MASK_BITS) << NODE_SUBCLASS_SHIFT) | \ + (((TYPE) & NODE_TYPE_MASK_BITS) << NODE_TYPE_SHIFT) | \ + (((INDEX) & NODE_INDEX_MASK_BITS) << NODE_INDEX_SHIFT)) + +#define NODECLASS(ID) (((ID) & NODE_CLASS_MASK) >> NODE_CLASS_SHIFT) +#define NODESUBCLASS(ID) (((ID) & NODE_SUBCLASS_MASK) >> \ + NODE_SUBCLASS_SHIFT) +#define NODETYPE(ID) (((ID) & NODE_TYPE_MASK) >> NODE_TYPE_SHIFT) +#define NODEINDEX(ID) (((ID) & NODE_INDEX_MASK) >> NODE_INDEX_SHIFT) + +/********************************************************************* + * Enum definitions + ********************************************************************/ + +/* Node class types */ +enum pm_node_class { + XPM_NODECLASS_MIN, + + XPM_NODECLASS_POWER, + XPM_NODECLASS_CLOCK, + XPM_NODECLASS_RESET, + XPM_NODECLASS_MEMIC, + XPM_NODECLASS_STMIC, + XPM_NODECLASS_DEVICE, + + XPM_NODECLASS_MAX +}; + +enum pm_device_node_subclass { + /* Device types */ + XPM_NODESUBCL_DEV_CORE = 1, + XPM_NODESUBCL_DEV_PERIPH, + XPM_NODESUBCL_DEV_MEM, + XPM_NODESUBCL_DEV_SOC, + XPM_NODESUBCL_DEV_MEM_CTRLR, + XPM_NODESUBCL_DEV_PHY, +}; + +enum pm_device_node_type { + /* Device types */ + XPM_NODETYPE_DEV_CORE_PMC = 1, + XPM_NODETYPE_DEV_CORE_PSM, + XPM_NODETYPE_DEV_CORE_APU, + XPM_NODETYPE_DEV_CORE_RPU, + XPM_NODETYPE_DEV_OCM, + XPM_NODETYPE_DEV_TCM, + XPM_NODETYPE_DEV_L2CACHE, + XPM_NODETYPE_DEV_DDR, + XPM_NODETYPE_DEV_PERIPH, + XPM_NODETYPE_DEV_SOC, + XPM_NODETYPE_DEV_GT, +}; + +/* Device node Indexes */ +enum pm_device_node_idx { + /* Device nodes */ + XPM_NODEIDX_DEV_MIN, + + /* Processor devices */ + XPM_NODEIDX_DEV_PMC_PROC, + XPM_NODEIDX_DEV_PSM_PROC, + XPM_NODEIDX_DEV_ACPU_0, + XPM_NODEIDX_DEV_ACPU_1, + XPM_NODEIDX_DEV_RPU0_0, + XPM_NODEIDX_DEV_RPU0_1, + + /* Memory devices */ + XPM_NODEIDX_DEV_OCM_0, + XPM_NODEIDX_DEV_OCM_1, + XPM_NODEIDX_DEV_OCM_2, + XPM_NODEIDX_DEV_OCM_3, + XPM_NODEIDX_DEV_TCM_0_A, + XPM_NODEIDX_DEV_TCM_0_B, + XPM_NODEIDX_DEV_TCM_1_A, + XPM_NODEIDX_DEV_TCM_1_B, + XPM_NODEIDX_DEV_L2_BANK_0, + XPM_NODEIDX_DEV_DDR_0, + XPM_NODEIDX_DEV_DDR_1, + XPM_NODEIDX_DEV_DDR_2, + XPM_NODEIDX_DEV_DDR_3, + XPM_NODEIDX_DEV_DDR_4, + XPM_NODEIDX_DEV_DDR_5, + XPM_NODEIDX_DEV_DDR_6, + XPM_NODEIDX_DEV_DDR_7, + + /* LPD Peripheral devices */ + XPM_NODEIDX_DEV_USB_0, + XPM_NODEIDX_DEV_GEM_0, + XPM_NODEIDX_DEV_GEM_1, + XPM_NODEIDX_DEV_SPI_0, + XPM_NODEIDX_DEV_SPI_1, + XPM_NODEIDX_DEV_I2C_0, + XPM_NODEIDX_DEV_I2C_1, + XPM_NODEIDX_DEV_CAN_FD_0, + XPM_NODEIDX_DEV_CAN_FD_1, + XPM_NODEIDX_DEV_UART_0, + XPM_NODEIDX_DEV_UART_1, + XPM_NODEIDX_DEV_GPIO, + XPM_NODEIDX_DEV_TTC_0, + XPM_NODEIDX_DEV_TTC_1, + XPM_NODEIDX_DEV_TTC_2, + XPM_NODEIDX_DEV_TTC_3, + XPM_NODEIDX_DEV_SWDT_LPD, + + /* FPD Peripheral devices */ + XPM_NODEIDX_DEV_SWDT_FPD, + + /* PMC Peripheral devices */ + XPM_NODEIDX_DEV_OSPI, + XPM_NODEIDX_DEV_QSPI, + XPM_NODEIDX_DEV_GPIO_PMC, + XPM_NODEIDX_DEV_I2C_PMC, + XPM_NODEIDX_DEV_SDIO_0, + XPM_NODEIDX_DEV_SDIO_1, + + XPM_NODEIDX_DEV_PL_0, + XPM_NODEIDX_DEV_PL_1, + XPM_NODEIDX_DEV_PL_2, + XPM_NODEIDX_DEV_PL_3, + XPM_NODEIDX_DEV_RTC, + XPM_NODEIDX_DEV_ADMA_0, + XPM_NODEIDX_DEV_ADMA_1, + XPM_NODEIDX_DEV_ADMA_2, + XPM_NODEIDX_DEV_ADMA_3, + XPM_NODEIDX_DEV_ADMA_4, + XPM_NODEIDX_DEV_ADMA_5, + XPM_NODEIDX_DEV_ADMA_6, + XPM_NODEIDX_DEV_ADMA_7, + XPM_NODEIDX_DEV_IPI_0, + XPM_NODEIDX_DEV_IPI_1, + XPM_NODEIDX_DEV_IPI_2, + XPM_NODEIDX_DEV_IPI_3, + XPM_NODEIDX_DEV_IPI_4, + XPM_NODEIDX_DEV_IPI_5, + XPM_NODEIDX_DEV_IPI_6, + + /* Entire SoC */ + XPM_NODEIDX_DEV_SOC, + + /* DDR memory controllers */ + XPM_NODEIDX_DEV_DDRMC_0, + XPM_NODEIDX_DEV_DDRMC_1, + XPM_NODEIDX_DEV_DDRMC_2, + XPM_NODEIDX_DEV_DDRMC_3, + + /* GT devices */ + XPM_NODEIDX_DEV_GT_0, + XPM_NODEIDX_DEV_GT_1, + XPM_NODEIDX_DEV_GT_2, + XPM_NODEIDX_DEV_GT_3, + XPM_NODEIDX_DEV_GT_4, + XPM_NODEIDX_DEV_GT_5, + XPM_NODEIDX_DEV_GT_6, + XPM_NODEIDX_DEV_GT_7, + XPM_NODEIDX_DEV_GT_8, + XPM_NODEIDX_DEV_GT_9, + XPM_NODEIDX_DEV_GT_10, + + XPM_NODEIDX_DEV_MAX +}; + +#endif /* PM_NODE_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c new file mode 100644 index 0000000..b082acb --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Top-level SMC handler for Versal power management calls and + * IPI setup functions for communication with PMC. + */ + +#include +#include +#include +#include +#include +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_ipi.h" +#include + +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U +#define INVALID_SGI 0xFFU +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6) + +/* pm_up = true - UP, pm_up = false - DOWN */ +static bool pm_up; +static unsigned int sgi = (unsigned int)INVALID_SGI; + +static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle, + void *cookie) +{ + unsigned int cpu; + unsigned int reg; + + (void)plat_ic_acknowledge_interrupt(); + cpu = plat_my_core_pos() + 1U; + + if ((unsigned int)sgi != (unsigned int)INVALID_SGI) { + reg = (cpu | ((unsigned int)sgi << (unsigned int)XSCUGIC_SGIR_EL1_INITID_SHIFT)); + write_icc_asgi1r_el1(reg); + } + + /* Clear FIQ */ + plat_ic_end_of_interrupt(id); + + return 0; +} + +/** + * pm_register_sgi() - PM register the IPI interrupt + * + * @sgi - SGI number to be used for communication. + * @return On success, the initialization function must return 0. + * Any other return value will cause the framework to ignore + * the service + * + * Update the SGI number to be used. + * + */ +int pm_register_sgi(unsigned int sgi_num) +{ + if ((unsigned int)sgi != (unsigned int)INVALID_SGI) { + return -EBUSY; + } + + if (sgi_num >= GICV3_MAX_SGI_TARGETS) { + return -EINVAL; + } + + sgi = (unsigned int)sgi_num; + return 0; +} + +/** + * pm_setup() - PM service setup + * + * @return On success, the initialization function must return 0. + * Any other return value will cause the framework to ignore + * the service + * + * Initialization functions for Versal power management for + * communicaton with PMC. + * + * Called from sip_svc_setup initialization function with the + * rt_svc_init signature. + */ +int pm_setup(void) +{ + int status, ret = 0; + + status = pm_ipi_init(primary_proc); + + if (status < 0) { + INFO("BL31: PM Service Init Failed, Error Code %d!\n", status); + ret = status; + } else { + pm_up = true; + } + + /* + * Enable IPI IRQ + * assume the rich OS is OK to handle callback IRQs now. + * Even if we were wrong, it would not enable the IRQ in + * the GIC. + */ + pm_ipi_irq_enable(primary_proc); + + ret = request_intr_type_el3(PLAT_VERSAL_IPI_IRQ, ipi_fiq_handler); + if (ret != 0) { + WARN("BL31: registering IPI interrupt failed\n"); + } + return ret; +} + +/** + * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2. + * @smc_fid - Function Identifier + * @x1 - x4 - Arguments + * @cookie - Unused + * @handler - Pointer to caller's context structure + * + * @return - Unused + * + * Determines that smc_fid is valid and supported PM SMC Function ID from the + * list of pm_api_ids, otherwise completes the request with + * the unknown SMC Function ID + * + * The SMC calls for PM service are forwarded from SIP Service SMC handler + * function with rt_svc_handle signature + */ +uint64_t pm_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) +{ + enum pm_ret_status ret; + + uint32_t pm_arg[4]; + uint32_t security_flag = SECURE_FLAG; + + /* Handle case where PM wasn't initialized properly */ + if (pm_up == false) { + SMC_RET1(handle, SMC_UNK); + } + + pm_arg[0] = (uint32_t)x1; + pm_arg[1] = (uint32_t)(x1 >> 32); + pm_arg[2] = (uint32_t)x2; + pm_arg[3] = (uint32_t)(x2 >> 32); + + /* + * Mark BIT24 payload (i.e 1st bit of pm_arg[3] ) as non-secure (1) + * if smc called is non secure + */ + if (is_caller_non_secure(flags) != 0) { + security_flag = NON_SECURE_FLAG; + } + + switch (smc_fid & FUNCID_NUM_MASK) { + /* PM API Functions */ + case PM_SELF_SUSPEND: + ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_FORCE_POWERDOWN: + ret = pm_force_powerdown(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQ_SUSPEND: + ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_ABORT_SUSPEND: + ret = pm_abort_suspend(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SYSTEM_SHUTDOWN: + ret = pm_system_shutdown(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQ_WAKEUP: + ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SET_WAKEUP_SOURCE: + ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQUEST_DEVICE: + ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_RELEASE_DEVICE: + ret = pm_release_device(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SET_REQUIREMENT: + ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_GET_API_VERSION: + { + uint32_t api_version; + + ret = pm_get_api_version(&api_version, security_flag); + SMC_RET1(handle, (u_register_t)PM_RET_SUCCESS | + ((u_register_t)api_version << 32)); + } + + case PM_GET_DEVICE_STATUS: + { + uint32_t buff[3]; + + ret = pm_get_device_status(pm_arg[0], buff, security_flag); + SMC_RET2(handle, (u_register_t)ret | ((u_register_t)buff[0] << 32), + (u_register_t)buff[1] | ((u_register_t)buff[2] << 32)); + } + + case PM_RESET_ASSERT: + ret = pm_reset_assert(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_RESET_GET_STATUS: + { + uint32_t reset_status; + + ret = pm_reset_get_status(pm_arg[0], &reset_status, + security_flag); + SMC_RET1(handle, (u_register_t)ret | + ((u_register_t)reset_status << 32)); + } + + case PM_INIT_FINALIZE: + ret = pm_init_finalize(security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_GET_CALLBACK_DATA: + { + uint32_t result[4] = {0}; + + pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag); + SMC_RET2(handle, + (u_register_t)result[0] | ((u_register_t)result[1] << 32), + (u_register_t)result[2] | ((u_register_t)result[3] << 32)); + } + + case PM_PINCTRL_REQUEST: + ret = pm_pinctrl_request(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_RELEASE: + ret = pm_pinctrl_release(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_GET_FUNCTION: + { + uint32_t value = 0; + + ret = pm_pinctrl_get_function(pm_arg[0], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_PINCTRL_SET_FUNCTION: + ret = pm_pinctrl_set_function(pm_arg[0], pm_arg[1], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_CONFIG_PARAM_GET: + { + uint32_t value; + + ret = pm_pinctrl_get_pin_param(pm_arg[0], pm_arg[1], &value, + security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_PINCTRL_CONFIG_PARAM_SET: + ret = pm_pinctrl_set_pin_param(pm_arg[0], pm_arg[1], pm_arg[2], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_IOCTL: + { + uint32_t value; + + ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_QUERY_DATA: + { + uint32_t data[8] = { 0 }; + + ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], data, security_flag); + + SMC_RET2(handle, (u_register_t)ret | ((u_register_t)data[0] << 32), + (u_register_t)data[1] | ((u_register_t)data[2] << 32)); + + } + case PM_CLOCK_ENABLE: + ret = pm_clock_enable(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_DISABLE: + ret = pm_clock_disable(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETSTATE: + { + uint32_t value; + + ret = pm_clock_get_state(pm_arg[0], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_CLOCK_SETDIVIDER: + ret = pm_clock_set_divider(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETDIVIDER: + { + uint32_t value; + + ret = pm_clock_get_divider(pm_arg[0], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_CLOCK_SETPARENT: + ret = pm_clock_set_parent(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETPARENT: + { + uint32_t value; + + ret = pm_clock_get_parent(pm_arg[0], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_CLOCK_GETRATE: + { + uint32_t rate[2] = { 0 }; + + ret = pm_clock_get_rate(pm_arg[0], rate, security_flag); + SMC_RET2(handle, (u_register_t)ret | ((u_register_t)rate[0] << 32), + (u_register_t)rate[1] | ((u_register_t)0U << 32)); + } + + case PM_PLL_SET_PARAMETER: + ret = pm_pll_set_param(pm_arg[0], pm_arg[1], pm_arg[2], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PLL_GET_PARAMETER: + { + uint32_t value; + + ret = pm_pll_get_param(pm_arg[0], pm_arg[1], &value, + security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value << 32)); + } + + case PM_PLL_SET_MODE: + ret = pm_pll_set_mode(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PLL_GET_MODE: + { + uint32_t mode; + + ret = pm_pll_get_mode(pm_arg[0], &mode, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)mode << 32)); + } + + case PM_GET_TRUSTZONE_VERSION: + SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | + ((uint64_t)VERSAL_TZ_VERSION << 32)); + + case PM_GET_CHIPID: + { + uint32_t result[2]; + + ret = pm_get_chipid(result, security_flag); + SMC_RET2(handle, (u_register_t)ret | ((u_register_t)result[0] << 32), + (u_register_t)result[1] | ((u_register_t)0U << 32)); + } + + case PM_FEATURE_CHECK: + { + uint32_t version; + + ret = pm_feature_check(pm_arg[0], &version, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)version << 32)); + } + + case PM_LOAD_PDI: + { + ret = pm_load_pdi(pm_arg[0], pm_arg[1], pm_arg[2], + security_flag); + SMC_RET1(handle, (u_register_t)ret); + } + + case PM_GET_OP_CHARACTERISTIC: + { + uint32_t result; + + ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1], &result, + security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)result << 32)); + } + + case PM_SET_MAX_LATENCY: + { + ret = pm_set_max_latency(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (u_register_t)ret); + } + + case PM_REGISTER_NOTIFIER: + { + ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], security_flag); + SMC_RET1(handle, (u_register_t)ret); + } + + default: + WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h new file mode 100644 index 0000000..4f8dc2b --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_SVC_MAIN_H +#define PM_SVC_MAIN_H + +#include + +int pm_setup(void); +uint64_t pm_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); + +int pm_register_sgi(unsigned int sgi_num); +#endif /* PM_SVC_MAIN_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c b/arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c new file mode 100644 index 0000000..6f2ff94 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */ + +#include +#include +#include + +#include "ipi_mailbox_svc.h" +#include "pm_svc_main.h" + +/* SMC function IDs for SiP Service queries */ +#define VERSAL_SIP_SVC_CALL_COUNT U(0x8200ff00) +#define VERSAL_SIP_SVC_UID U(0x8200ff01) +#define VERSAL_SIP_SVC_VERSION U(0x8200ff03) + +/* SiP Service Calls version numbers */ +#define SIP_SVC_VERSION_MAJOR U(0) +#define SIP_SVC_VERSION_MINOR U(1) + +/* These macros are used to identify PM calls from the SMC function ID */ +#define PM_FID_MASK 0xf000u +#define PM_FID_VALUE 0u +#define IPI_FID_VALUE 0x1000u +#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE) +#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE) + +/* SiP Service UUID */ +DEFINE_SVC_UUID2(versal_sip_uuid, + 0x2ab9e4ecU, 0x93b9U, 0x11e7U, 0xa0U, 0x19U, + 0xdfU, 0xe0U, 0xdbU, 0xadU, 0x0aU, 0xe0U); + +/** + * sip_svc_setup() - Setup SiP Service + * + * Invokes PM setup + */ +static int32_t sip_svc_setup(void) +{ + /* PM implementation as SiP Service */ + (void)pm_setup(); + + return 0; +} + +/** + * sip_svc_smc_handler() - Top-level SiP Service SMC handler + * + * Handler for all SiP SMC calls. Handles standard SIP requests + * and calls PM SMC handler if the call is for a PM-API function. + */ +uintptr_t sip_svc_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) +{ + /* Let PM SMC handler deal with PM-related requests */ + if (is_pm_fid(smc_fid)) { + return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } + + /* Let IPI SMC handler deal with IPI-related requests */ + if (is_ipi_fid(smc_fid)) { + return ipi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } + + /* Let PM SMC handler deal with PM-related requests */ + switch (smc_fid) { + case VERSAL_SIP_SVC_CALL_COUNT: + /* PM functions + default functions */ + SMC_RET1(handle, 2); + + case VERSAL_SIP_SVC_UID: + SMC_UUID_RET(handle, versal_sip_uuid); + + case VERSAL_SIP_SVC_VERSION: + SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register PM Service Calls as runtime service */ +DECLARE_RT_SVC( + sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + sip_svc_setup, + sip_svc_smc_handler); diff --git a/arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c b/arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c new file mode 100644 index 0000000..08e7cf9 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way the GICv3 driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_versal_gic_driver_init +#pragma weak plat_versal_gic_init +#pragma weak plat_versal_gic_cpuif_enable +#pragma weak plat_versal_gic_cpuif_disable +#pragma weak plat_versal_gic_pcpu_init +#pragma weak plat_versal_gic_redistif_on +#pragma weak plat_versal_gic_redistif_off + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t versal_interrupt_props[] = { + PLAT_VERSAL_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_VERSAL_G0_IRQ_PROPS(INTR_GROUP0) +}; + +/* + * We save and restore the GICv3 context on system suspend. Allocate the + * data in the designated EL3 Secure carve-out memory. + */ +static gicv3_redist_ctx_t rdist_ctx __section("versal_el3_tzc_dram"); +static gicv3_dist_ctx_t dist_ctx __section("versal_el3_tzc_dram"); + +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static unsigned int versal_gicv3_mpidr_hash(u_register_t mpidr) +{ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return versal_calc_core_pos(mpidr); +} + +static const gicv3_driver_data_t versal_gic_data __unused = { + .gicd_base = PLAT_VERSAL_GICD_BASE, + .gicr_base = PLAT_VERSAL_GICR_BASE, + .interrupt_props = versal_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(versal_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = versal_gicv3_mpidr_hash +}; + +void __init plat_versal_gic_driver_init(void) +{ + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ +#if IMAGE_BL31 + gicv3_driver_init(&versal_gic_data); +#endif +} + +/****************************************************************************** + * Versal common helper to initialize the GIC. Only invoked by BL31 + *****************************************************************************/ +void __init plat_versal_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to enable the GIC CPU interface + *****************************************************************************/ +void plat_versal_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to disable the GIC CPU interface + *****************************************************************************/ +void plat_versal_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to initialize the per-cpu redistributor interface in + * GICv3 + *****************************************************************************/ +void plat_versal_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helpers to power GIC redistributor interface + *****************************************************************************/ +void plat_versal_gic_redistif_on(void) +{ + gicv3_rdistif_on(plat_my_core_pos()); +} + +void plat_versal_gic_redistif_off(void) +{ + gicv3_rdistif_off(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to save & restore the GICv3 on resume from system + * suspend + *****************************************************************************/ +void plat_versal_gic_save(void) +{ + /* + * If an ITS is available, save its context before + * the Redistributor using: + * gicv3_its_save_disable(gits_base, &its_ctx[i]) + * Additionnaly, an implementation-defined sequence may + * be required to save the whole ITS state. + */ + + /* + * Save the GIC Redistributors and ITS contexts before the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to save the context of the CPU that is issuing + * the SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); + + /* Save the GIC Distributor context */ + gicv3_distif_save(&dist_ctx); + + /* + * From here, all the components of the GIC can be safely powered down + * as long as there is an alternate way to handle wakeup interrupt + * sources. + */ +} + +void plat_versal_gic_resume(void) +{ + /* Restore the GIC Distributor context */ + gicv3_distif_init_restore(&dist_ctx); + + /* + * Restore the GIC Redistributor and ITS contexts after the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to restore the context of the CPU that issued + * the SYSTEM SUSPEND call. + */ + gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); + + /* + * If an ITS is available, restore its context after + * the Redistributor using: + * gicv3_its_restore(gits_base, &its_ctx[i]) + * An implementation-defined sequence may be required to + * restore the whole ITS state. The ITS must also be + * re-enabled after this sequence has been executed. + */ +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c b/arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c new file mode 100644 index 0000000..f99af82 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Versal IPI agent registers access management + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* versal ipi configuration table */ +const static struct ipi_config versal_ipi_table[] = { + /* A72 IPI */ + [IPI_ID_APU] = { + .ipi_bit_mask = IPI0_TRIG_BIT, + .ipi_reg_base = IPI0_REG_BASE, + .secure_only = 0U, + }, + + /* PMC IPI */ + [IPI_ID_PMC] = { + .ipi_bit_mask = PMC_IPI_TRIG_BIT, + .ipi_reg_base = IPI0_REG_BASE, + .secure_only = 0U, + }, + + /* RPU0 IPI */ + [IPI_ID_RPU0] = { + .ipi_bit_mask = IPI1_TRIG_BIT, + .ipi_reg_base = IPI1_REG_BASE, + .secure_only = 0U, + }, + + /* RPU1 IPI */ + [IPI_ID_RPU1] = { + .ipi_bit_mask = IPI2_TRIG_BIT, + .ipi_reg_base = IPI2_REG_BASE, + .secure_only = 0U, + }, + + /* IPI3 IPI */ + [IPI_ID_3] = { + .ipi_bit_mask = IPI3_TRIG_BIT, + .ipi_reg_base = IPI3_REG_BASE, + .secure_only = 0U, + }, + + /* IPI4 IPI */ + [IPI_ID_4] = { + .ipi_bit_mask = IPI4_TRIG_BIT, + .ipi_reg_base = IPI4_REG_BASE, + .secure_only = 0U, + }, + + /* IPI5 IPI */ + [IPI_ID_5] = { + .ipi_bit_mask = IPI5_TRIG_BIT, + .ipi_reg_base = IPI5_REG_BASE, + .secure_only = 0U, + }, +}; + +/* versal_ipi_config_table_init() - Initialize versal IPI configuration data + * + * @ipi_config_table - IPI configuration table + * @ipi_total - Total number of IPI available + * + */ +void versal_ipi_config_table_init(void) +{ + ipi_config_table_init(versal_ipi_table, ARRAY_SIZE(versal_ipi_table)); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c new file mode 100644 index 0000000..fae73cf --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pm_api_sys.h" + +/* + * Table of regions to map using the MMU. + * This doesn't include TZRAM as the 'mem_layout' argument passed to + * configure_mmu_elx() will give the available subset of that, + */ +const mmap_region_t plat_arm_mmap[] = { + { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + {0} +}; + +static unsigned int zynqmp_get_silicon_ver(void) +{ + static unsigned int ver; + + if (!ver) { + ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + + ZYNQMP_CSU_VERSION_OFFSET); + ver &= ZYNQMP_SILICON_VER_MASK; + ver >>= ZYNQMP_SILICON_VER_SHIFT; + } + + return ver; +} + +unsigned int zynqmp_get_uart_clk(void) +{ + unsigned int ver = zynqmp_get_silicon_ver(); + + if (ver == ZYNQMP_CSU_VERSION_QEMU) + return 133000000; + else + return 100000000; +} + +#if LOG_LEVEL >= LOG_LEVEL_NOTICE +static const struct { + unsigned int id; + unsigned int ver; + char *name; + bool evexists; +} zynqmp_devices[] = { + { + .id = 0x10, + .name = "XCZU3EG", + }, + { + .id = 0x10, + .ver = 0x2c, + .name = "XCZU3CG", + }, + { + .id = 0x11, + .name = "XCZU2EG", + }, + { + .id = 0x11, + .ver = 0x2c, + .name = "XCZU2CG", + }, + { + .id = 0x20, + .name = "XCZU5EV", + .evexists = true, + }, + { + .id = 0x20, + .ver = 0x100, + .name = "XCZU5EG", + .evexists = true, + }, + { + .id = 0x20, + .ver = 0x12c, + .name = "XCZU5CG", + }, + { + .id = 0x21, + .name = "XCZU4EV", + .evexists = true, + }, + { + .id = 0x21, + .ver = 0x100, + .name = "XCZU4EG", + .evexists = true, + }, + { + .id = 0x21, + .ver = 0x12c, + .name = "XCZU4CG", + }, + { + .id = 0x30, + .name = "XCZU7EV", + .evexists = true, + }, + { + .id = 0x30, + .ver = 0x100, + .name = "XCZU7EG", + .evexists = true, + }, + { + .id = 0x30, + .ver = 0x12c, + .name = "XCZU7CG", + }, + { + .id = 0x38, + .name = "XCZU9EG", + }, + { + .id = 0x38, + .ver = 0x2c, + .name = "XCZU9CG", + }, + { + .id = 0x39, + .name = "XCZU6EG", + }, + { + .id = 0x39, + .ver = 0x2c, + .name = "XCZU6CG", + }, + { + .id = 0x40, + .name = "XCZU11EG", + }, + { + .id = 0x50, + .name = "XCZU15EG", + }, + { + .id = 0x58, + .name = "XCZU19EG", + }, + { + .id = 0x59, + .name = "XCZU17EG", + }, + { + .id = 0x60, + .name = "XCZU28DR", + }, + { + .id = 0x61, + .name = "XCZU21DR", + }, + { + .id = 0x62, + .name = "XCZU29DR", + }, + { + .id = 0x63, + .name = "XCZU23DR", + }, + { + .id = 0x64, + .name = "XCZU27DR", + }, + { + .id = 0x65, + .name = "XCZU25DR", + }, + { + .id = 0x66, + .name = "XCZU39DR", + }, + { + .id = 0x7d, + .name = "XCZU43DR", + }, + { + .id = 0x78, + .name = "XCZU46DR", + }, + { + .id = 0x7f, + .name = "XCZU47DR", + }, + { + .id = 0x7b, + .name = "XCZU48DR", + }, + { + .id = 0x7e, + .name = "XCZU49DR", + }, +}; + +#define ZYNQMP_PL_STATUS_BIT 9 +#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) +#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) + +#define SILICON_ID_XCK26 0x4724093 + +static char *zynqmp_get_silicon_idcode_name(void) +{ + uint32_t id, ver, chipid[2]; + size_t i, j, len; + const char *name = "EG/EV"; + +#ifdef IMAGE_BL32 + /* + * For BL32, get the chip id info directly by reading corresponding + * registers instead of making pm call. This has limitation + * that these registers should be configured to have access + * from APU which is default case. + */ + chipid[0] = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); + chipid[1] = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET); +#else + if (pm_get_chipid(chipid) != PM_RET_SUCCESS) + return "XCZUUNKN"; +#endif + + id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | + ZYNQMP_CSU_IDCODE_SVD_MASK); + id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; + ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT; + + for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { + if (zynqmp_devices[i].id == id && + zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK)) + break; + } + + if (i >= ARRAY_SIZE(zynqmp_devices)) { + if (chipid[0] == SILICON_ID_XCK26) { + return "XCK26"; + } else { + return "XCZUUNKN"; + } + } + + if (!zynqmp_devices[i].evexists) + return zynqmp_devices[i].name; + + if (ver & ZYNQMP_PL_STATUS_MASK) + return zynqmp_devices[i].name; + + len = strlen(zynqmp_devices[i].name) - 2; + for (j = 0; j < strlen(name); j++) { + zynqmp_devices[i].name[len] = name[j]; + len++; + } + zynqmp_devices[i].name[len] = '\0'; + + return zynqmp_devices[i].name; +} + +static unsigned int zynqmp_get_rtl_ver(void) +{ + uint32_t ver; + + ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); + ver &= ZYNQMP_RTL_VER_MASK; + ver >>= ZYNQMP_RTL_VER_SHIFT; + + return ver; +} + +static char *zynqmp_print_silicon_idcode(void) +{ + uint32_t id, maskid, tmp; + + id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); + + tmp = id; + tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK | + ZYNQMP_CSU_IDCODE_FAMILY_MASK; + maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT | + ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT; + if (tmp != maskid) { + ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid); + return "UNKN"; + } + VERBOSE("Xilinx IDCODE 0x%x\n", id); + return zynqmp_get_silicon_idcode_name(); +} + +static unsigned int zynqmp_get_ps_ver(void) +{ + uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); + + ver &= ZYNQMP_PS_VER_MASK; + ver >>= ZYNQMP_PS_VER_SHIFT; + + return ver + 1; +} + +static void zynqmp_print_platform_name(void) +{ + unsigned int ver = zynqmp_get_silicon_ver(); + unsigned int rtl = zynqmp_get_rtl_ver(); + char *label = "Unknown"; + + switch (ver) { + case ZYNQMP_CSU_VERSION_QEMU: + label = "QEMU"; + break; + case ZYNQMP_CSU_VERSION_SILICON: + label = "silicon"; + break; + default: + /* Do nothing in default case */ + break; + } + + NOTICE("TF-A running on %s/%s at 0x%x\n", + zynqmp_print_silicon_idcode(), label, BL31_BASE); + VERBOSE("TF-A running on v%d/RTL%d.%d\n", + zynqmp_get_ps_ver(), (rtl & 0xf0) >> 4, rtl & 0xf); +} +#else +static inline void zynqmp_print_platform_name(void) { } +#endif + +unsigned int zynqmp_get_bootmode(void) +{ + uint32_t r; + unsigned int ret; + + ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r); + + if (ret != PM_RET_SUCCESS) + r = mmio_read_32(CRL_APB_BOOT_MODE_USER); + + return r & CRL_APB_BOOT_MODE_MASK; +} + +void zynqmp_config_setup(void) +{ + uint64_t counter_freq; + + /* Configure IPI data for ZynqMP */ + zynqmp_ipi_config_table_init(); + + zynqmp_print_platform_name(); + + /* Configure counter frequency */ + counter_freq = read_cntfrq_el0(); + if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) { + write_cntfrq_el0(plat_get_syscnt_freq2()); + } + + generic_delay_timer_init(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int ver = zynqmp_get_silicon_ver(); + + if (ver == ZYNQMP_CSU_VERSION_QEMU) + return 65000000; + else + return mmio_read_32(IOU_SCNTRS_BASEFREQ); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S b/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S new file mode 100644 index 0000000..d8439f7 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl zynqmp_calc_core_pos + .globl plat_my_core_pos + .globl platform_mem_init + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + mrs x0, mpidr_el1 + + /* Deactivate the gic cpu interface */ + ldr x1, =BASE_GICC_BASE + mov w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1) + orr w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0) + str w0, [x1, #GICC_CTLR] + + /* + * There is no sane reason to come out of this wfi. This + * cpu will be powered on and reset by the cpu_on pm api + */ + dsb sy +1: + no_ret plat_panic_handler +endfunc plat_secondary_cold_boot_setup + +func plat_is_my_cpu_primary + mov x9, x30 + bl plat_my_core_pos + cmp x0, #ZYNQMP_PRIMARY_CPU + cset x0, eq + ret x9 +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the zynqmp_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b zynqmp_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int zynqmp_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func zynqmp_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc zynqmp_calc_core_pos + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on ARM + * platforms. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c new file mode 100644 index 0000000..58eee3a --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2013-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 +#include +#include + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + */ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + assert(sec_state_is_valid(type)); + + if (type == NON_SECURE) { + return &bl33_image_ep_info; + } + + return &bl32_image_ep_info; +} + +/* + * Set the build time defaults. We want to do this when doing a JTAG boot + * or if we can't find any other config data. + */ +static inline void bl31_set_default_config(void) +{ + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry(); + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} + +/* + * Perform any BL31 specific platform actions. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + */ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + uint64_t atf_handoff_addr; + + if (ZYNQMP_CONSOLE_IS(cadence) || (ZYNQMP_CONSOLE_IS(cadence1))) { + /* Register the console to provide early debug support */ + static console_t bl31_boot_console; + (void)console_cdns_register(ZYNQMP_UART_BASE, + zynqmp_get_uart_clk(), + ZYNQMP_UART_BAUDRATE, + &bl31_boot_console); + console_set_scope(&bl31_boot_console, + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT); + } else if (ZYNQMP_CONSOLE_IS(dcc)) { + /* Initialize the dcc console for debug */ + int rc = console_dcc_register(); + if (rc == 0) { + panic(); + } + } + /* Initialize the platform config for future decision making */ + zynqmp_config_setup(); + + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(arg0 == 0U); + assert(arg1 == 0U); + + /* + * Do initial security configuration to allow DRAM/device access. On + * Base ZYNQMP only DRAM security is programmable (via TrustZone), but + * other platforms might have more programmable security devices + * present. + */ + + /* Populate common information for BL32 and BL33 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + atf_handoff_addr = mmio_read_32(PMU_GLOBAL_GEN_STORAGE6); + + if (zynqmp_get_bootmode() == ZYNQMP_BOOTMODE_JTAG) { + bl31_set_default_config(); + } else { + /* use parameters from FSBL */ + enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info, + &bl33_image_ep_info, + atf_handoff_addr); + if (ret == FSBL_HANDOFF_NO_STRUCT) { + bl31_set_default_config(); + } else if (ret != FSBL_HANDOFF_SUCCESS) { + panic(); + } + } + if (bl32_image_ep_info.pc) { + VERBOSE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); + } + if (bl33_image_ep_info.pc) { + VERBOSE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); + } +} + +#if ZYNQMP_WDT_RESTART +static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3]; + +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler) +{ + /* Validate 'handler' and 'id' parameters */ + if (!handler || id >= MAX_INTR_EL3) { + return -EINVAL; + } + + /* Check if a handler has already been registered */ + if (type_el3_interrupt_table[id]) { + return -EALREADY; + } + + type_el3_interrupt_table[id] = handler; + + return 0; +} + +static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint32_t intr_id; + interrupt_type_handler_t handler; + + intr_id = plat_ic_get_pending_interrupt_id(); + handler = type_el3_interrupt_table[intr_id]; + if (handler != NULL) { + handler(intr_id, flags, handle, cookie); + } + + return 0; +} +#endif + +#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX) +static void prepare_dtb(void) +{ + void *dtb = (void *)XILINX_OF_BOARD_DTB_ADDR; + int ret; + + /* Return if no device tree is detected */ + if (fdt_check_header(dtb) != 0) { + NOTICE("Can't read DT at 0x%p\n", dtb); + return; + } + + ret = fdt_open_into(dtb, dtb, XILINX_OF_BOARD_DTB_MAX_SIZE); + if (ret < 0) { + ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret); + return; + } + + if (dt_add_psci_node(dtb)) { + ERROR("Failed to add PSCI Device Tree node\n"); + return; + } + + if (dt_add_psci_cpu_enable_methods(dtb)) { + ERROR("Failed to add PSCI cpu enable methods in Device Tree\n"); + return; + } + + /* Reserve memory used by Trusted Firmware. */ + if (fdt_add_reserved_memory(dtb, "tf-a", BL31_BASE, BL31_LIMIT - BL31_BASE)) { + WARN("Failed to add reserved memory nodes to DT.\n"); + } + + ret = fdt_pack(dtb); + if (ret < 0) { + ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret); + } + + clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb)); + INFO("Changed device tree to advertise PSCI and reserved memories.\n"); +} +#endif + +void bl31_platform_setup(void) +{ +#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX) + prepare_dtb(); +#endif + + /* Initialize the gic cpu and distributor interfaces */ + plat_arm_gic_driver_init(); + plat_arm_gic_init(); +} + +void bl31_plat_runtime_setup(void) +{ +#if ZYNQMP_WDT_RESTART + uint64_t flags = 0; + uint64_t rc; + + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_EL3, + rdo_el3_interrupt_handler, flags); + if (rc) { + panic(); + } +#endif +} + +/* + * Perform the very early platform specific architectural setup here. + */ +void bl31_plat_arch_setup(void) +{ + plat_arm_interconnect_init(); + plat_arm_interconnect_enter_coherency(); + + + const mmap_region_t bl_regions[] = { +#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX) + MAP_REGION_FLAT(XILINX_OF_BOARD_DTB_ADDR, XILINX_OF_BOARD_DTB_MAX_SIZE, + MT_MEMORY | MT_RW | MT_NS), +#endif + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_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), + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + enable_mmu_el3(0); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h new file mode 100644 index 0000000..bccd2f1 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* ZynqMP IPI management enums and defines */ + +#ifndef PLAT_IPI_H +#define PLAT_IPI_H + +#include +#include + +/********************************************************************* + * IPI agent IDs macros + ********************************************************************/ +#define IPI_ID_APU 0U +#define IPI_ID_RPU0 1U +#define IPI_ID_RPU1 2U +#define IPI_ID_PMU0 3U +#define IPI_ID_PMU1 4U +#define IPI_ID_PMU2 5U +#define IPI_ID_PMU3 6U +#define IPI_ID_PL0 7U +#define IPI_ID_PL1 8U +#define IPI_ID_PL2 9U +#define IPI_ID_PL3 10U + +/********************************************************************* + * IPI message buffers + ********************************************************************/ +#define IPI_BUFFER_BASEADDR 0xFF990000U + +#define IPI_BUFFER_APU_BASE (IPI_BUFFER_BASEADDR + 0x400U) +#define IPI_BUFFER_PMU_BASE (IPI_BUFFER_BASEADDR + 0xE00U) + +#define IPI_BUFFER_LOCAL_BASE IPI_BUFFER_APU_BASE +#define IPI_BUFFER_REMOTE_BASE IPI_BUFFER_PMU_BASE + +#define IPI_BUFFER_TARGET_LOCAL_OFFSET 0x80U +#define IPI_BUFFER_TARGET_REMOTE_OFFSET 0x1C0U + +#define IPI_BUFFER_MAX_WORDS 8 + +#define IPI_BUFFER_REQ_OFFSET 0x0U +#define IPI_BUFFER_RESP_OFFSET 0x20U + +/********************************************************************* + * Platform specific IPI API declarations + ********************************************************************/ + +/* Configure IPI table for zynqmp */ +void zynqmp_ipi_config_table_init(void); + +#endif /* PLAT_IPI_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S new file mode 100644 index 0000000..bf1ff82 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include +#include "zynqmp_def.h" + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x17, BASE_GICC_BASE + mov_imm x16, BASE_GICD_BASE + arm_print_gic_regs + print_cci_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h new file mode 100644 index 0000000..a57aebe --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Contains platform specific definitions of commonly used macros data types + * for PU Power Management. This file should be common for all PU's. + */ + +#ifndef PLAT_PM_COMMON_H +#define PLAT_PM_COMMON_H + +#include +#include +#include "pm_defs.h" + + +#define ZYNQMP_TZ_VERSION_MAJOR 1 +#define ZYNQMP_TZ_VERSION_MINOR 0 +#define ZYNQMP_TZ_VERSION ((ZYNQMP_TZ_VERSION_MAJOR << 16) | \ + ZYNQMP_TZ_VERSION_MINOR) +#endif /* _PLAT_PM_COMMON_H_ */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h new file mode 100644 index 0000000..288cc53 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#include + +#include +#include +#include + +void zynqmp_config_setup(void); + +unsigned int zynqmp_calc_core_pos(u_register_t mpidr); + +/* ZynqMP specific functions */ +unsigned int zynqmp_get_uart_clk(void); +unsigned int zynqmp_get_bootmode(void); + + +#if ZYNQMP_WDT_RESTART +/* + * Register handler to specific GIC entrance + * for INTR_TYPE_EL3 type of interrupt + */ +int request_intr_type_el3(uint32_t, interrupt_type_handler_t); +#endif + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h new file mode 100644 index 0000000..1c4daa1 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include + +#include "zynqmp_def.h" + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x440 + +#define PLATFORM_CORE_COUNT U(4) +#define PLAT_NUM_POWER_DOMAINS U(5) +#define PLAT_MAX_PWR_LVL U(1) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#ifndef ZYNQMP_ATF_MEM_BASE +#if !DEBUG && defined(SPD_none) && !SDEI_SUPPORT +# define BL31_BASE 0xfffea000 +# define BL31_LIMIT 0x100000000 +#else +# define BL31_BASE 0x1000 +# define BL31_LIMIT 0x7ffff +#endif +#else +# define BL31_BASE (ZYNQMP_ATF_MEM_BASE) +# define BL31_LIMIT (ZYNQMP_ATF_MEM_BASE + ZYNQMP_ATF_MEM_SIZE - 1) +# ifdef ZYNQMP_ATF_MEM_PROGBITS_SIZE +# define BL31_PROGBITS_LIMIT (ZYNQMP_ATF_MEM_BASE + ZYNQMP_ATF_MEM_PROGBITS_SIZE - 1) +# endif +#endif + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#ifndef ZYNQMP_BL32_MEM_BASE +# define BL32_BASE 0x60000000 +# define BL32_LIMIT 0x7fffffff +#else +# define BL32_BASE (ZYNQMP_BL32_MEM_BASE) +# define BL32_LIMIT (ZYNQMP_BL32_MEM_BASE + ZYNQMP_BL32_MEM_SIZE - 1) +#endif + +/******************************************************************************* + * BL33 specific defines. + ******************************************************************************/ +#ifndef PRELOADED_BL33_BASE +# define PLAT_ARM_NS_IMAGE_BASE 0x8000000 +#else +# define PLAT_ARM_NS_IMAGE_BASE PRELOADED_BL33_BASE +#endif + +/******************************************************************************* + * TSP specific defines. + ******************************************************************************/ +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1) + +/* ID of the secure physical generic timer interrupt used by the TSP */ +#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define XILINX_OF_BOARD_DTB_ADDR 0x100000 +#define XILINX_OF_BOARD_DTB_MAX_SIZE 0x200000 +#define PLAT_DDR_LOWMEM_MAX 0x80000000 + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX) +#define MAX_MMAP_REGIONS 8 +#define MAX_XLAT_TABLES 6 +#else +#define MAX_MMAP_REGIONS 7 +#define MAX_XLAT_TABLES 5 +#endif + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define ZYNQMP_SDEI_SGI_PRIVATE U(8) + +/* Platform macros to support exception handling framework */ +#define PLAT_PRI_BITS U(3) +#define PLAT_SDEI_CRITICAL_PRI 0x10 +#define PLAT_SDEI_NORMAL_PRI 0x20 + +#define PLAT_ARM_GICD_BASE BASE_GICD_BASE +#define PLAT_ARM_GICC_BASE BASE_GICC_BASE +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#if !ZYNQMP_WDT_RESTART +#define PLAT_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_6, 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) +#else +#define PLAT_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(IRQ_TTC3_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + 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_6, 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) +#endif + +#define PLAT_ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, grp, \ + GIC_INTR_CFG_EDGE) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h new file mode 100644 index 0000000..7e58391 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ZYNQMP_DEF_H +#define ZYNQMP_DEF_H + +#include +#include + +#define ZYNQMP_CONSOLE_ID_cadence 1 +#define ZYNQMP_CONSOLE_ID_cadence0 1 +#define ZYNQMP_CONSOLE_ID_cadence1 2 +#define ZYNQMP_CONSOLE_ID_dcc 3 + +#define ZYNQMP_CONSOLE_IS(con) (ZYNQMP_CONSOLE_ID_ ## con == ZYNQMP_CONSOLE) + +/* Default counter frequency */ +#define ZYNQMP_DEFAULT_COUNTER_FREQ 0U + +/* Firmware Image Package */ +#define ZYNQMP_PRIMARY_CPU 0 + +/* Memory location options for Shared data and TSP in ZYNQMP */ +#define ZYNQMP_IN_TRUSTED_SRAM 0 +#define ZYNQMP_IN_TRUSTED_DRAM 1 + +/******************************************************************************* + * ZYNQMP memory map related constants + ******************************************************************************/ +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE U(0xFF000000) +#define DEVICE0_SIZE U(0x00E00000) +#define DEVICE1_BASE U(0xF9000000) +#define DEVICE1_SIZE U(0x00800000) + +/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/ +#define CRF_APB_BASE U(0xFD1A0000) +#define CRF_APB_SIZE U(0x00600000) +#define CRF_APB_CLK_BASE U(0xFD1A0020) + +/* CRF registers and bitfields */ +#define CRF_APB_RST_FPD_APU (CRF_APB_BASE + 0X00000104) + +#define CRF_APB_RST_FPD_APU_ACPU_RESET (U(1) << 0) +#define CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET (U(1) << 10) + +/* CRL registers and bitfields */ +#define CRL_APB_BASE U(0xFF5E0000) +#define CRL_APB_BOOT_MODE_USER (CRL_APB_BASE + 0x200) +#define CRL_APB_RESET_CTRL (CRL_APB_BASE + 0x218) +#define CRL_APB_RST_LPD_TOP (CRL_APB_BASE + 0x23C) +#define CRL_APB_BOOT_PIN_CTRL (CRL_APB_BASE + U(0x250)) +#define CRL_APB_CLK_BASE U(0xFF5E0020) + +#define CRL_APB_RPU_AMBA_RESET (U(1) << 2) +#define CRL_APB_RPLL_CTRL_BYPASS (U(1) << 3) + +#define CRL_APB_RESET_CTRL_SOFT_RESET (U(1) << 4) + +#define CRL_APB_BOOT_MODE_MASK (U(0xf) << 0) +#define CRL_APB_BOOT_PIN_MASK (U(0xf0f) << 0) +#define CRL_APB_BOOT_DRIVE_PIN_1_SHIFT U(9) +#define CRL_APB_BOOT_ENABLE_PIN_1_SHIFT U(1) +#define CRL_APB_BOOT_ENABLE_PIN_1 (U(0x1) << \ + CRL_APB_BOOT_ENABLE_PIN_1_SHIFT) +#define CRL_APB_BOOT_DRIVE_PIN_1 (U(0x1) << \ + CRL_APB_BOOT_DRIVE_PIN_1_SHIFT) +#define ZYNQMP_BOOTMODE_JTAG U(0) +#define ZYNQMP_ULPI_RESET_VAL_HIGH (CRL_APB_BOOT_ENABLE_PIN_1 | \ + CRL_APB_BOOT_DRIVE_PIN_1) +#define ZYNQMP_ULPI_RESET_VAL_LOW CRL_APB_BOOT_ENABLE_PIN_1 + +/* system counter registers and bitfields */ +#define IOU_SCNTRS_BASE 0xFF260000 +#define IOU_SCNTRS_BASEFREQ (IOU_SCNTRS_BASE + 0x20) + +/* APU registers and bitfields */ +#define APU_BASE 0xFD5C0000 +#define APU_CONFIG_0 (APU_BASE + 0x20) +#define APU_RVBAR_L_0 (APU_BASE + 0x40) +#define APU_RVBAR_H_0 (APU_BASE + 0x44) +#define APU_PWRCTL (APU_BASE + 0x90) + +#define APU_CONFIG_0_VINITHI_SHIFT 8 +#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 1 +#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 2 +#define APU_2_PWRCTL_CPUPWRDWNREQ_MASK 4 +#define APU_3_PWRCTL_CPUPWRDWNREQ_MASK 8 + +/* PMU registers and bitfields */ +#define PMU_GLOBAL_BASE 0xFFD80000 +#define PMU_GLOBAL_CNTRL (PMU_GLOBAL_BASE + 0) +#define PMU_GLOBAL_GEN_STORAGE6 (PMU_GLOBAL_BASE + 0x48) +#define PMU_GLOBAL_REQ_PWRUP_STATUS (PMU_GLOBAL_BASE + 0x110) +#define PMU_GLOBAL_REQ_PWRUP_EN (PMU_GLOBAL_BASE + 0x118) +#define PMU_GLOBAL_REQ_PWRUP_DIS (PMU_GLOBAL_BASE + 0x11c) +#define PMU_GLOBAL_REQ_PWRUP_TRIG (PMU_GLOBAL_BASE + 0x120) + +#define PMU_GLOBAL_CNTRL_FW_IS_PRESENT (1 << 4) + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_ARM_CCI_BASE 0xFD6E0000 +#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 3 +#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 4 + +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ +#define BASE_GICD_BASE 0xF9010000 +#define BASE_GICC_BASE 0xF9020000 +#define BASE_GICH_BASE 0xF9040000 +#define BASE_GICV_BASE 0xF9060000 + +#if ZYNQMP_WDT_RESTART +#define IRQ_SEC_IPI_APU 67 +#define IRQ_TTC3_1 77 +#define TTC3_BASE_ADDR 0xFF140000 +#define TTC3_INTR_REGISTER_1 (TTC3_BASE_ADDR + 0x54) +#define TTC3_INTR_ENABLE_1 (TTC3_BASE_ADDR + 0x60) +#endif + +#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 MAX_INTR_EL3 128 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define ZYNQMP_UART0_BASE 0xFF000000 +#define ZYNQMP_UART1_BASE 0xFF010000 + +#if ZYNQMP_CONSOLE_IS(cadence) || ZYNQMP_CONSOLE_IS(dcc) +# define ZYNQMP_UART_BASE ZYNQMP_UART0_BASE +#elif ZYNQMP_CONSOLE_IS(cadence1) +# define ZYNQMP_UART_BASE ZYNQMP_UART1_BASE +#else +# error "invalid ZYNQMP_CONSOLE" +#endif + +#define ZYNQMP_CRASH_UART_BASE ZYNQMP_UART_BASE +/* impossible to call C routine how it is done now - hardcode any value */ +#define ZYNQMP_CRASH_UART_CLK_IN_HZ 100000000 /* FIXME */ +/* Must be non zero */ +#define ZYNQMP_UART_BAUDRATE 115200 + +/* Silicon version detection */ +#define ZYNQMP_SILICON_VER_MASK 0xF000 +#define ZYNQMP_SILICON_VER_SHIFT 12 +#define ZYNQMP_CSU_VERSION_SILICON 0 +#define ZYNQMP_CSU_VERSION_QEMU 3 + +#define ZYNQMP_RTL_VER_MASK 0xFF0 +#define ZYNQMP_RTL_VER_SHIFT 4 + +#define ZYNQMP_PS_VER_MASK 0xF +#define ZYNQMP_PS_VER_SHIFT 0 + +#define ZYNQMP_CSU_BASEADDR 0xFFCA0000 +#define ZYNQMP_CSU_IDCODE_OFFSET 0x40 + +#define ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT 0 +#define ZYNQMP_CSU_IDCODE_XILINX_ID_MASK (0xFFF << \ + ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT) +#define ZYNQMP_CSU_IDCODE_XILINX_ID 0x093 + +#define ZYNQMP_CSU_IDCODE_SVD_SHIFT 12 +#define ZYNQMP_CSU_IDCODE_SVD_MASK (0x7 << \ + ZYNQMP_CSU_IDCODE_SVD_SHIFT) +#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT 15 +#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK (0xF << \ + ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT) +#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT 19 +#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_MASK (0x3 << \ + ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT) +#define ZYNQMP_CSU_IDCODE_FAMILY_SHIFT 21 +#define ZYNQMP_CSU_IDCODE_FAMILY_MASK (0x7F << \ + ZYNQMP_CSU_IDCODE_FAMILY_SHIFT) +#define ZYNQMP_CSU_IDCODE_FAMILY 0x23 + +#define ZYNQMP_CSU_IDCODE_REVISION_SHIFT 28 +#define ZYNQMP_CSU_IDCODE_REVISION_MASK (0xF << \ + ZYNQMP_CSU_IDCODE_REVISION_SHIFT) +#define ZYNQMP_CSU_IDCODE_REVISION 0 + +#define ZYNQMP_CSU_VERSION_OFFSET 0x44 + +/* Efuse */ +#define EFUSE_BASEADDR 0xFFCC0000 +#define EFUSE_IPDISABLE_OFFSET 0x1018 +#define EFUSE_IPDISABLE_VERSION 0x1FFU +#define ZYNQMP_EFUSE_IPDISABLE_SHIFT 20 + +/* Access control register defines */ +#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) + +#define FPD_SLCR_BASEADDR U(0xFD610000) +#define IOU_SLCR_BASEADDR U(0xFF180000) + +#define ZYNQMP_RPU_GLBL_CNTL U(0xFF9A0000) +#define ZYNQMP_RPU0_CFG U(0xFF9A0100) +#define ZYNQMP_RPU1_CFG U(0xFF9A0200) +#define ZYNQMP_SLSPLIT_MASK U(0x08) +#define ZYNQMP_TCM_COMB_MASK U(0x40) +#define ZYNQMP_SLCLAMP_MASK U(0x10) +#define ZYNQMP_VINITHI_MASK U(0x04) + +/* Tap delay bypass */ +#define IOU_TAPDLY_BYPASS U(0XFF180390) +#define TAP_DELAY_MASK U(0x7) + +/* SGMII mode */ +#define IOU_GEM_CTRL U(0xFF180360) +#define IOU_GEM_CLK_CTRL U(0xFF180308) +#define SGMII_SD_MASK U(0x3) +#define SGMII_SD_OFFSET U(2) +#define SGMII_PCS_SD_0 U(0x0) +#define SGMII_PCS_SD_1 U(0x1) +#define SGMII_PCS_SD_PHY U(0x2) +#define GEM_SGMII_MASK U(0x4) +#define GEM_CLK_CTRL_MASK U(0xF) +#define GEM_CLK_CTRL_OFFSET U(5) +#define GEM_RX_SRC_SEL_GTR U(0x1) +#define GEM_SGMII_MODE U(0x4) + +/* SD DLL reset */ +#define ZYNQMP_SD_DLL_CTRL U(0xFF180358) +#define ZYNQMP_SD0_DLL_RST_MASK U(0x00000004) +#define ZYNQMP_SD0_DLL_RST U(0x00000004) +#define ZYNQMP_SD1_DLL_RST_MASK U(0x00040000) +#define ZYNQMP_SD1_DLL_RST U(0x00040000) + +/* SD tap delay */ +#define ZYNQMP_SD_DLL_CTRL U(0xFF180358) +#define ZYNQMP_SD_ITAP_DLY U(0xFF180314) +#define ZYNQMP_SD_OTAP_DLY U(0xFF180318) +#define ZYNQMP_SD_TAP_OFFSET U(16) +#define ZYNQMP_SD_ITAPCHGWIN_MASK U(0x200) +#define ZYNQMP_SD_ITAPCHGWIN U(0x200) +#define ZYNQMP_SD_ITAPDLYENA_MASK U(0x100) +#define ZYNQMP_SD_ITAPDLYENA U(0x100) +#define ZYNQMP_SD_ITAPDLYSEL_MASK U(0xFF) +#define ZYNQMP_SD_OTAPDLYSEL_MASK U(0x3F) +#define ZYNQMP_SD_OTAPDLYENA_MASK U(0x40) +#define ZYNQMP_SD_OTAPDLYENA U(0x40) + +/* Clock control registers */ +/* Full power domain clocks */ +#define CRF_APB_APLL_CTRL (CRF_APB_CLK_BASE + 0x00) +#define CRF_APB_DPLL_CTRL (CRF_APB_CLK_BASE + 0x0c) +#define CRF_APB_VPLL_CTRL (CRF_APB_CLK_BASE + 0x18) +#define CRF_APB_PLL_STATUS (CRF_APB_CLK_BASE + 0x24) +#define CRF_APB_APLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x28) +#define CRF_APB_DPLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x2c) +#define CRF_APB_VPLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x30) +/* Peripheral clocks */ +#define CRF_APB_ACPU_CTRL (CRF_APB_CLK_BASE + 0x40) +#define CRF_APB_DBG_TRACE_CTRL (CRF_APB_CLK_BASE + 0x44) +#define CRF_APB_DBG_FPD_CTRL (CRF_APB_CLK_BASE + 0x48) +#define CRF_APB_DP_VIDEO_REF_CTRL (CRF_APB_CLK_BASE + 0x50) +#define CRF_APB_DP_AUDIO_REF_CTRL (CRF_APB_CLK_BASE + 0x54) +#define CRF_APB_DP_STC_REF_CTRL (CRF_APB_CLK_BASE + 0x5c) +#define CRF_APB_DDR_CTRL (CRF_APB_CLK_BASE + 0x60) +#define CRF_APB_GPU_REF_CTRL (CRF_APB_CLK_BASE + 0x64) +#define CRF_APB_SATA_REF_CTRL (CRF_APB_CLK_BASE + 0x80) +#define CRF_APB_PCIE_REF_CTRL (CRF_APB_CLK_BASE + 0x94) +#define CRF_APB_GDMA_REF_CTRL (CRF_APB_CLK_BASE + 0x98) +#define CRF_APB_DPDMA_REF_CTRL (CRF_APB_CLK_BASE + 0x9c) +#define CRF_APB_TOPSW_MAIN_CTRL (CRF_APB_CLK_BASE + 0xa0) +#define CRF_APB_TOPSW_LSBUS_CTRL (CRF_APB_CLK_BASE + 0xa4) +#define CRF_APB_GTGREF0_REF_CTRL (CRF_APB_CLK_BASE + 0xa8) +#define CRF_APB_DBG_TSTMP_CTRL (CRF_APB_CLK_BASE + 0xd8) + +/* Low power domain clocks */ +#define CRL_APB_IOPLL_CTRL (CRL_APB_CLK_BASE + 0x00) +#define CRL_APB_RPLL_CTRL (CRL_APB_CLK_BASE + 0x10) +#define CRL_APB_PLL_STATUS (CRL_APB_CLK_BASE + 0x20) +#define CRL_APB_IOPLL_TO_FPD_CTRL (CRL_APB_CLK_BASE + 0x24) +#define CRL_APB_RPLL_TO_FPD_CTRL (CRL_APB_CLK_BASE + 0x28) +/* Peripheral clocks */ +#define CRL_APB_USB3_DUAL_REF_CTRL (CRL_APB_CLK_BASE + 0x2c) +#define CRL_APB_GEM0_REF_CTRL (CRL_APB_CLK_BASE + 0x30) +#define CRL_APB_GEM1_REF_CTRL (CRL_APB_CLK_BASE + 0x34) +#define CRL_APB_GEM2_REF_CTRL (CRL_APB_CLK_BASE + 0x38) +#define CRL_APB_GEM3_REF_CTRL (CRL_APB_CLK_BASE + 0x3c) +#define CRL_APB_USB0_BUS_REF_CTRL (CRL_APB_CLK_BASE + 0x40) +#define CRL_APB_USB1_BUS_REF_CTRL (CRL_APB_CLK_BASE + 0x44) +#define CRL_APB_QSPI_REF_CTRL (CRL_APB_CLK_BASE + 0x48) +#define CRL_APB_SDIO0_REF_CTRL (CRL_APB_CLK_BASE + 0x4c) +#define CRL_APB_SDIO1_REF_CTRL (CRL_APB_CLK_BASE + 0x50) +#define CRL_APB_UART0_REF_CTRL (CRL_APB_CLK_BASE + 0x54) +#define CRL_APB_UART1_REF_CTRL (CRL_APB_CLK_BASE + 0x58) +#define CRL_APB_SPI0_REF_CTRL (CRL_APB_CLK_BASE + 0x5c) +#define CRL_APB_SPI1_REF_CTRL (CRL_APB_CLK_BASE + 0x60) +#define CRL_APB_CAN0_REF_CTRL (CRL_APB_CLK_BASE + 0x64) +#define CRL_APB_CAN1_REF_CTRL (CRL_APB_CLK_BASE + 0x68) +#define CRL_APB_CPU_R5_CTRL (CRL_APB_CLK_BASE + 0x70) +#define CRL_APB_IOU_SWITCH_CTRL (CRL_APB_CLK_BASE + 0x7c) +#define CRL_APB_CSU_PLL_CTRL (CRL_APB_CLK_BASE + 0x80) +#define CRL_APB_PCAP_CTRL (CRL_APB_CLK_BASE + 0x84) +#define CRL_APB_LPD_SWITCH_CTRL (CRL_APB_CLK_BASE + 0x88) +#define CRL_APB_LPD_LSBUS_CTRL (CRL_APB_CLK_BASE + 0x8c) +#define CRL_APB_DBG_LPD_CTRL (CRL_APB_CLK_BASE + 0x90) +#define CRL_APB_NAND_REF_CTRL (CRL_APB_CLK_BASE + 0x94) +#define CRL_APB_ADMA_REF_CTRL (CRL_APB_CLK_BASE + 0x98) +#define CRL_APB_PL0_REF_CTRL (CRL_APB_CLK_BASE + 0xa0) +#define CRL_APB_PL1_REF_CTRL (CRL_APB_CLK_BASE + 0xa4) +#define CRL_APB_PL2_REF_CTRL (CRL_APB_CLK_BASE + 0xa8) +#define CRL_APB_PL3_REF_CTRL (CRL_APB_CLK_BASE + 0xac) +#define CRL_APB_PL0_THR_CNT (CRL_APB_CLK_BASE + 0xb4) +#define CRL_APB_PL1_THR_CNT (CRL_APB_CLK_BASE + 0xbc) +#define CRL_APB_PL2_THR_CNT (CRL_APB_CLK_BASE + 0xc4) +#define CRL_APB_PL3_THR_CNT (CRL_APB_CLK_BASE + 0xdc) +#define CRL_APB_GEM_TSU_REF_CTRL (CRL_APB_CLK_BASE + 0xe0) +#define CRL_APB_DLL_REF_CTRL (CRL_APB_CLK_BASE + 0xe4) +#define CRL_APB_AMS_REF_CTRL (CRL_APB_CLK_BASE + 0xe8) +#define CRL_APB_I2C0_REF_CTRL (CRL_APB_CLK_BASE + 0x100) +#define CRL_APB_I2C1_REF_CTRL (CRL_APB_CLK_BASE + 0x104) +#define CRL_APB_TIMESTAMP_REF_CTRL (CRL_APB_CLK_BASE + 0x108) +#define IOU_SLCR_GEM_CLK_CTRL (IOU_SLCR_BASEADDR + 0x308) +#define IOU_SLCR_CAN_MIO_CTRL (IOU_SLCR_BASEADDR + 0x304) +#define FPD_SLCR_WDT_CLK_SEL (FPD_SLCR_BASEADDR + 0x100) +#define IOU_SLCR_WDT_CLK_SEL (IOU_SLCR_BASEADDR + 0x300) + +/* Global general storage register base address */ +#define GGS_BASEADDR (0xFFD80030U) +#define GGS_NUM_REGS U(4) + +/* Persistent global general storage register base address */ +#define PGGS_BASEADDR (0xFFD80050U) +#define PGGS_NUM_REGS U(4) + +/* PMU GGS4 register 4 is used for warm restart boot health status */ +#define PMU_GLOBAL_GEN_STORAGE4 (GGS_BASEADDR + 0x10) +/* Warm restart boot health status mask */ +#define PM_BOOT_HEALTH_STATUS_MASK U(0x01) +/* WDT restart scope shift and mask */ +#define RESTART_SCOPE_SHIFT (3) +#define RESTART_SCOPE_MASK (0x3U << RESTART_SCOPE_SHIFT) + +/*AFI registers */ +#define AFIFM6_WRCTRL U(13) +#define FABRIC_WIDTH U(3) + +/* CSUDMA Module Base Address*/ +#define CSUDMA_BASE 0xFFC80000 + +/* RSA-CORE Module Base Address*/ +#define RSA_CORE_BASE 0xFFCE0000 + +#endif /* ZYNQMP_DEF_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c new file mode 100644 index 0000000..b2b473a --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "pm_api_sys.h" +#include "pm_client.h" + +uintptr_t zynqmp_sec_entry; + +void zynqmp_cpu_standby(plat_local_state_t cpu_state) +{ + VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state); + + dsb(); + wfi(); +} + +static int zynqmp_pwr_domain_on(u_register_t mpidr) +{ + unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); + const struct pm_proc *proc; + uint32_t buff[3]; + enum pm_ret_status ret; + + VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); + + if (cpu_id == -1) + return PSCI_E_INTERN_FAIL; + + proc = pm_get_proc(cpu_id); + + /* Check the APU proc status before wakeup */ + ret = pm_get_node_status(proc->node_id, buff); + if ((ret != PM_RET_SUCCESS) || (buff[0] == PM_PROC_STATE_SUSPENDING)) { + return PSCI_E_INTERN_FAIL; + } + + /* Clear power down request */ + pm_client_wakeup(proc); + + /* Send request to PMU to wake up selected APU CPU core */ + pm_req_wakeup(proc->node_id, 1, zynqmp_sec_entry, REQ_ACK_BLOCKING); + + return PSCI_E_SUCCESS; +} + +static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* Prevent interrupts from spuriously waking up this cpu */ + gicv2_cpuif_disable(); + + /* + * Send request to PMU to power down the appropriate APU CPU + * core. + * According to PSCI specification, CPU_off function does not + * have resume address and CPU core can only be woken up + * invoking CPU_on function, during which resume address will + * be set. + */ + pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0); +} + +static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + unsigned int state; + unsigned int cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ? + PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE; + + /* Send request to PMU to suspend this core */ + pm_self_suspend(proc->node_id, MAX_LATENCY, state, zynqmp_sec_entry); + + /* APU is to be turned off */ + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + /* disable coherency */ + plat_arm_interconnect_exit_coherency(); + } +} + +static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + plat_arm_gic_pcpu_init(); + gicv2_cpuif_enable(); +} + +static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + unsigned int cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + + /* Clear the APU power control register for this cpu */ + pm_client_wakeup(proc); + + /* enable coherency */ + plat_arm_interconnect_enter_coherency(); + /* APU was turned off */ + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + plat_arm_gic_init(); + } else { + gicv2_cpuif_enable(); + gicv2_pcpu_distif_init(); + } +} + +/******************************************************************************* + * ZynqMP handlers to shutdown/reboot the system + ******************************************************************************/ + +static void __dead2 zynqmp_system_off(void) +{ + /* disable coherency */ + plat_arm_interconnect_exit_coherency(); + + /* Send the power down request to the PMU */ + pm_system_shutdown(PMF_SHUTDOWN_TYPE_SHUTDOWN, + pm_get_shutdown_scope()); + + while (1) + wfi(); +} + +static void __dead2 zynqmp_system_reset(void) +{ + /* disable coherency */ + plat_arm_interconnect_exit_coherency(); + + /* Send the system reset request to the PMU */ + pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET, + pm_get_shutdown_scope()); + + while (1) + wfi(); +} + +int zynqmp_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); + + int pstate = psci_get_pstate_type(power_state); + + assert(req_state); + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + else + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE; + + /* We expect the 'state id' to be zero */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +void zynqmp_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE; +} + +/******************************************************************************* + * Export the platform handlers to enable psci to invoke them + ******************************************************************************/ +static const struct plat_psci_ops zynqmp_psci_ops = { + .cpu_standby = zynqmp_cpu_standby, + .pwr_domain_on = zynqmp_pwr_domain_on, + .pwr_domain_off = zynqmp_pwr_domain_off, + .pwr_domain_suspend = zynqmp_pwr_domain_suspend, + .pwr_domain_on_finish = zynqmp_pwr_domain_on_finish, + .pwr_domain_suspend_finish = zynqmp_pwr_domain_suspend_finish, + .system_off = zynqmp_system_off, + .system_reset = zynqmp_system_reset, + .validate_power_state = zynqmp_validate_power_state, + .get_sys_suspend_power_state = zynqmp_get_sys_suspend_power_state, +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + zynqmp_sec_entry = sec_entrypoint; + + *psci_ops = &zynqmp_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c new file mode 100644 index 0000000..aab24aa --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static const unsigned char plat_power_domain_tree_desc[] = {1, 4}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c new file mode 100644 index 0000000..58a52a3 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) { + return -1; + } + + if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) { + return -1; + } + + return zynqmp_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/platform.mk b/arm-trusted-firmware/plat/xilinx/zynqmp/platform.mk new file mode 100644 index 0000000..620bf6c --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/platform.mk @@ -0,0 +1,125 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +override ERRATA_A53_855873 := 1 +override PROGRAMMABLE_RESET_ADDRESS := 1 +PSCI_EXTENDED_STATE_ID := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 +SEPARATE_CODE_AND_RODATA := 1 +ZYNQMP_WDT_RESTART := 0 +IPI_CRC_CHECK := 0 +override RESET_TO_BL31 := 1 +override GICV2_G0_FOR_EL3 := 1 +override WARMBOOT_ENABLE_DCACHE_EARLY := 1 + +EL3_EXCEPTION_HANDLING := $(SDEI_SUPPORT) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +WORKAROUND_CVE_2017_5715 := 0 + +ifdef ZYNQMP_ATF_MEM_BASE + $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE)) + + ifndef ZYNQMP_ATF_MEM_SIZE + $(error "ZYNQMP_ATF_BASE defined without ZYNQMP_ATF_SIZE") + endif + $(eval $(call add_define,ZYNQMP_ATF_MEM_SIZE)) + + ifdef ZYNQMP_ATF_MEM_PROGBITS_SIZE + $(eval $(call add_define,ZYNQMP_ATF_MEM_PROGBITS_SIZE)) + endif +endif + +ifdef ZYNQMP_BL32_MEM_BASE + $(eval $(call add_define,ZYNQMP_BL32_MEM_BASE)) + + ifndef ZYNQMP_BL32_MEM_SIZE + $(error "ZYNQMP_BL32_BASE defined without ZYNQMP_BL32_SIZE") + endif + $(eval $(call add_define,ZYNQMP_BL32_MEM_SIZE)) +endif + + +ifdef ZYNQMP_WDT_RESTART + $(eval $(call add_define,ZYNQMP_WDT_RESTART)) +endif + +ifdef ZYNQMP_IPI_CRC_CHECK + $(warning "ZYNQMP_IPI_CRC_CHECK macro is deprecated...instead please use IPI_CRC_CHECK.") +endif + +ifdef IPI_CRC_CHECK + $(eval $(call add_define,IPI_CRC_CHECK)) +endif + +PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ + -Iinclude/plat/arm/common/aarch64/ \ + -Iplat/xilinx/common/include/ \ + -Iplat/xilinx/common/ipi_mailbox_service/ \ + -Iplat/xilinx/zynqmp/include/ \ + -Iplat/xilinx/zynqmp/pm_service/ \ + +include lib/libfdt/libfdt.mk +# Include GICv2 driver files +include drivers/arm/gic/v2/gicv2.mk + +PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + drivers/arm/dcc/dcc_console.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${GICV2_SOURCES} \ + drivers/cadence/uart/aarch64/cdns_console.S \ + plat/arm/common/arm_cci.c \ + plat/arm/common/arm_common.c \ + plat/arm/common/arm_gicv2.c \ + plat/common/plat_gicv2.c \ + plat/xilinx/common/ipi.c \ + plat/xilinx/zynqmp/zynqmp_ipi.c \ + plat/common/aarch64/crash_console_helpers.S \ + plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S \ + plat/xilinx/zynqmp/aarch64/zynqmp_common.c + +ZYNQMP_CONSOLE ?= cadence +ifeq (${ZYNQMP_CONSOLE}, $(filter ${ZYNQMP_CONSOLE},cadence cadence0 cadence1 dcc)) +else + $(error "Please define ZYNQMP_CONSOLE") +endif +$(eval $(call add_define_val,ZYNQMP_CONSOLE,ZYNQMP_CONSOLE_ID_${ZYNQMP_CONSOLE})) + +BL31_SOURCES += drivers/arm/cci/cci.c \ + lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + common/fdt_fixup.c \ + ${LIBFDT_SRCS} \ + plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \ + plat/xilinx/common/pm_service/pm_ipi.c \ + plat/xilinx/common/plat_startup.c \ + plat/xilinx/zynqmp/bl31_zynqmp_setup.c \ + plat/xilinx/zynqmp/plat_psci.c \ + plat/xilinx/zynqmp/plat_zynqmp.c \ + plat/xilinx/zynqmp/plat_topology.c \ + plat/xilinx/zynqmp/sip_svc_setup.c \ + plat/xilinx/zynqmp/pm_service/pm_svc_main.c \ + plat/xilinx/zynqmp/pm_service/pm_api_sys.c \ + plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c \ + plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c \ + plat/xilinx/zynqmp/pm_service/pm_api_clock.c \ + plat/xilinx/zynqmp/pm_service/pm_client.c + +ifeq (${SDEI_SUPPORT},1) +BL31_SOURCES += plat/xilinx/zynqmp/zynqmp_ehf.c \ + plat/xilinx/zynqmp/zynqmp_sdei.c +endif + +BL31_CPPFLAGS += -fno-jump-tables +TF_CFLAGS_aarch64 += -mbranch-protection=none + +ifneq (${RESET_TO_BL31},1) + $(error "Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1.") +endif diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c new file mode 100644 index 0000000..4109830 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -0,0 +1,3010 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for clock control. + */ + +#include +#include + +#include +#include +#include + +#include "pm_api_clock.h" +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_common.h" +#include "pm_ipi.h" + +#define CLK_NODE_MAX U(6) + +#define CLK_PARENTS_ID_LEN U(16) +#define CLK_TOPOLOGY_NODE_OFFSET U(16) +#define CLK_TOPOLOGY_PAYLOAD_LEN U(12) +#define CLK_PARENTS_PAYLOAD_LEN U(12) +#define CLK_TYPE_SHIFT U(2) +#define CLK_CLKFLAGS_SHIFT U(8) +#define CLK_TYPEFLAGS_SHIFT U(24) +#define CLK_TYPEFLAGS2_SHIFT U(4) +#define CLK_TYPEFLAGS_BITS_MASK U(0xFF) +#define CLK_TYPEFLAGS2_BITS_MASK U(0x0F00) +#define CLK_TYPEFLAGS_BITS U(8) + +#define CLK_EXTERNAL_PARENT (PARENT_CLK_EXTERNAL << CLK_PARENTS_ID_LEN) + +#define NA_MULT U(0) +#define NA_DIV U(0) +#define NA_SHIFT U(0) +#define NA_WIDTH U(0) +#define NA_CLK_FLAGS U(0) +#define NA_TYPE_FLAGS U(0) + +/* PLL nodes related definitions */ +#define PLL_PRESRC_MUX_SHIFT U(20) +#define PLL_PRESRC_MUX_WIDTH U(3) +#define PLL_POSTSRC_MUX_SHIFT U(24) +#define PLL_POSTSRC_MUX_WIDTH U(3) +#define PLL_DIV2_MUX_SHIFT U(16) +#define PLL_DIV2_MUX_WIDTH U(1) +#define PLL_BYPASS_MUX_SHIFT U(3) +#define PLL_BYPASS_MUX_WIDTH U(1) + +/* Peripheral nodes related definitions */ +/* Peripheral Clocks */ +#define PERIPH_MUX_SHIFT U(0) +#define PERIPH_MUX_WIDTH U(3) +#define PERIPH_DIV1_SHIFT U(8) +#define PERIPH_DIV1_WIDTH U(6) +#define PERIPH_DIV2_SHIFT U(16) +#define PERIPH_DIV2_WIDTH U(6) +#define PERIPH_GATE_SHIFT U(24) +#define PERIPH_GATE_WIDTH U(1) + +#define USB_GATE_SHIFT U(25) + +/* External clock related definitions */ + +#define EXT_CLK_MIO_DATA(mio) \ + [EXT_CLK_INDEX(EXT_CLK_MIO##mio)] = { \ + .name = "mio_clk_"#mio, \ + } + +#define EXT_CLK_INDEX(n) (n - CLK_MAX_OUTPUT_CLK) + +/* Clock control related definitions */ +#define BIT_MASK(x, y) (((1U << (y)) - 1) << (x)) + +#define ISPLL(id) (id == CLK_APLL_INT || \ + id == CLK_DPLL_INT || \ + id == CLK_VPLL_INT || \ + id == CLK_IOPLL_INT || \ + id == CLK_RPLL_INT) + + +#define PLLCTRL_BP_MASK BIT(3) +#define PLLCTRL_RESET_MASK U(1) +#define PLL_FRAC_OFFSET U(8) +#define PLL_FRAC_MODE U(1) +#define PLL_INT_MODE U(0) +#define PLL_FRAC_MODE_MASK U(0x80000000) +#define PLL_FRAC_MODE_SHIFT U(31) +#define PLL_FRAC_DATA_MASK U(0xFFFF) +#define PLL_FRAC_DATA_SHIFT U(0) +#define PLL_FBDIV_MASK U(0x7F00) +#define PLL_FBDIV_WIDTH U(7) +#define PLL_FBDIV_SHIFT U(8) + +#define CLK_PLL_RESET_ASSERT U(1) +#define CLK_PLL_RESET_RELEASE U(2) +#define CLK_PLL_RESET_PULSE (CLK_PLL_RESET_ASSERT | CLK_PLL_RESET_RELEASE) + +/* Common topology definitions */ +#define GENERIC_MUX \ + { \ + .type = TYPE_MUX, \ + .offset = PERIPH_MUX_SHIFT, \ + .width = PERIPH_MUX_WIDTH, \ + .clkflags = CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = NA_TYPE_FLAGS, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define IGNORE_UNUSED_MUX \ + { \ + .type = TYPE_MUX, \ + .offset = PERIPH_MUX_SHIFT, \ + .width = PERIPH_MUX_WIDTH, \ + .clkflags = CLK_IGNORE_UNUSED | \ + CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = NA_TYPE_FLAGS, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define GENERIC_DIV1 \ + { \ + .type = TYPE_DIV1, \ + .offset = PERIPH_DIV1_SHIFT, \ + .width = PERIPH_DIV1_WIDTH, \ + .clkflags = CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = CLK_DIVIDER_ONE_BASED | \ + CLK_DIVIDER_ALLOW_ZERO, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define GENERIC_DIV2 \ + { \ + .type = TYPE_DIV2, \ + .offset = PERIPH_DIV2_SHIFT, \ + .width = PERIPH_DIV2_WIDTH, \ + .clkflags = CLK_SET_RATE_NO_REPARENT | \ + CLK_SET_RATE_PARENT | \ + CLK_IS_BASIC, \ + .typeflags = CLK_DIVIDER_ONE_BASED | \ + CLK_DIVIDER_ALLOW_ZERO, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define IGNORE_UNUSED_DIV(id) \ + { \ + .type = TYPE_DIV##id, \ + .offset = PERIPH_DIV##id##_SHIFT, \ + .width = PERIPH_DIV##id##_WIDTH, \ + .clkflags = CLK_IGNORE_UNUSED | \ + CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = CLK_DIVIDER_ONE_BASED | \ + CLK_DIVIDER_ALLOW_ZERO, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define GENERIC_GATE \ + { \ + .type = TYPE_GATE, \ + .offset = PERIPH_GATE_SHIFT, \ + .width = PERIPH_GATE_WIDTH, \ + .clkflags = CLK_SET_RATE_PARENT | \ + CLK_SET_RATE_GATE | \ + CLK_IS_BASIC, \ + .typeflags = NA_TYPE_FLAGS, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define IGNORE_UNUSED_GATE \ + { \ + .type = TYPE_GATE, \ + .offset = PERIPH_GATE_SHIFT, \ + .width = PERIPH_GATE_WIDTH, \ + .clkflags = CLK_SET_RATE_PARENT | \ + CLK_IGNORE_UNUSED | \ + CLK_IS_BASIC, \ + .typeflags = NA_TYPE_FLAGS, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +/** + * struct pm_clock_node - Clock topology node information + * @type: Topology type (mux/div1/div2/gate/pll/fixed factor) + * @offset: Offset in control register + * @width: Width of the specific type in control register + * @clkflags: Clk specific flags + * @typeflags: Type specific flags + * @mult: Multiplier for fixed factor + * @div: Divisor for fixed factor + */ +struct pm_clock_node { + uint16_t clkflags; + uint16_t typeflags; + uint8_t type; + uint8_t offset; + uint8_t width; + uint8_t mult:4; + uint8_t div:4; +}; + +/** + * struct pm_clock - Clock structure + * @name: Clock name + * @control_reg: Control register address + * @status_reg: Status register address + * @parents: Parents for first clock node. Lower byte indicates parent + * clock id and upper byte indicate flags for that id. + * pm_clock_node: Clock nodes + */ +struct pm_clock { + char name[CLK_NAME_LEN]; + uint8_t num_nodes; + unsigned int control_reg; + unsigned int status_reg; + int32_t (*parents)[]; + struct pm_clock_node(*nodes)[]; +}; + +/** + * struct pm_clock - Clock structure + * @name: Clock name + */ +struct pm_ext_clock { + char name[CLK_NAME_LEN]; +}; + +/* PLL Clocks */ +static struct pm_clock_node generic_pll_nodes[] = { + { + .type = TYPE_PLL, + .offset = NA_SHIFT, + .width = NA_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node ignore_unused_pll_nodes[] = { + { + .type = TYPE_PLL, + .offset = NA_SHIFT, + .width = NA_WIDTH, + .clkflags = CLK_IGNORE_UNUSED | CLK_SET_RATE_NO_REPARENT, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_pll_pre_src_nodes[] = { + { + .type = TYPE_MUX, + .offset = PLL_PRESRC_MUX_SHIFT, + .width = PLL_PRESRC_MUX_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_pll_half_nodes[] = { + { + .type = TYPE_FIXEDFACTOR, + .offset = NA_SHIFT, + .width = NA_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, + .typeflags = NA_TYPE_FLAGS, + .mult = 1, + .div = 2, + }, +}; + +static struct pm_clock_node generic_pll_int_nodes[] = { + { + .type = TYPE_MUX, + .offset = PLL_DIV2_MUX_SHIFT, + .width = PLL_DIV2_MUX_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | + CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_pll_post_src_nodes[] = { + { + .type = TYPE_MUX, + .offset = PLL_POSTSRC_MUX_SHIFT, + .width = PLL_POSTSRC_MUX_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_pll_system_nodes[] = { + { + .type = TYPE_MUX, + .offset = PLL_BYPASS_MUX_SHIFT, + .width = PLL_BYPASS_MUX_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | + CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node acpu_nodes[] = { + { + .type = TYPE_MUX, + .offset = PERIPH_MUX_SHIFT, + .width = PERIPH_MUX_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV1, + .offset = PERIPH_DIV1_SHIFT, + .width = PERIPH_DIV1_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_mux_div_nodes[] = { + GENERIC_MUX, + GENERIC_DIV1, +}; + +static struct pm_clock_node generic_mux_div_gate_nodes[] = { + GENERIC_MUX, + GENERIC_DIV1, + GENERIC_GATE, +}; + +static struct pm_clock_node generic_mux_div_unused_gate_nodes[] = { + GENERIC_MUX, + GENERIC_DIV1, + IGNORE_UNUSED_GATE, +}; + +static struct pm_clock_node generic_mux_div_div_gate_nodes[] = { + GENERIC_MUX, + GENERIC_DIV1, + GENERIC_DIV2, + GENERIC_GATE, +}; + +static struct pm_clock_node dp_audio_video_ref_nodes[] = { + { + .type = TYPE_MUX, + .offset = PERIPH_MUX_SHIFT, + .width = PERIPH_MUX_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | + CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = CLK_FRAC, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV1, + .offset = PERIPH_DIV1_SHIFT, + .width = PERIPH_DIV1_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO | + CLK_FRAC, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV2, + .offset = PERIPH_DIV2_SHIFT, + .width = PERIPH_DIV2_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO | + CLK_FRAC, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = PERIPH_GATE_SHIFT, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_GATE | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node usb_nodes[] = { + GENERIC_MUX, + GENERIC_DIV1, + GENERIC_DIV2, + { + .type = TYPE_GATE, + .offset = USB_GATE_SHIFT, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC | + CLK_SET_RATE_GATE, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_domain_crossing_nodes[] = { + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node rpll_to_fpd_nodes[] = { + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node acpu_half_nodes[] = { + { + .type = TYPE_FIXEDFACTOR, + .offset = 0, + .width = 1, + .clkflags = 0, + .typeflags = 0, + .mult = 1, + .div = 2, + }, + { + .type = TYPE_GATE, + .offset = 25, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node acpu_full_nodes[] = { + { + .type = TYPE_GATE, + .offset = 24, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node wdt_nodes[] = { + { + .type = TYPE_MUX, + .offset = 0, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node ddr_nodes[] = { + GENERIC_MUX, + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_IS_BASIC | CLK_IS_CRITICAL, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node pl_nodes[] = { + GENERIC_MUX, + { + .type = TYPE_DIV1, + .offset = PERIPH_DIV1_SHIFT, + .width = PERIPH_DIV1_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV2, + .offset = PERIPH_DIV2_SHIFT, + .width = PERIPH_DIV2_WIDTH, + .clkflags = CLK_IS_BASIC | CLK_SET_RATE_PARENT, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = PERIPH_GATE_SHIFT, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gpu_pp0_nodes[] = { + { + .type = TYPE_GATE, + .offset = 25, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gpu_pp1_nodes[] = { + { + .type = TYPE_GATE, + .offset = 26, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem_ref_ungated_nodes[] = { + GENERIC_MUX, + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV2, + .offset = 16, + .width = 6, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC | + CLK_SET_RATE_PARENT, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem0_ref_nodes[] = { + { + .type = TYPE_MUX, + .offset = 1, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem1_ref_nodes[] = { + { + .type = TYPE_MUX, + .offset = 6, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem2_ref_nodes[] = { + { + .type = TYPE_MUX, + .offset = 11, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem3_ref_nodes[] = { + { + .type = TYPE_MUX, + .offset = 16, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem_tx_nodes[] = { + { + .type = TYPE_GATE, + .offset = 25, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem_rx_nodes[] = { + { + .type = TYPE_GATE, + .offset = 26, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem_tsu_nodes[] = { + { + .type = TYPE_MUX, + .offset = 20, + .width = 2, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node can0_mio_nodes[] = { + { + .type = TYPE_MUX, + .offset = 0, + .width = 7, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node can1_mio_nodes[] = { + { + .type = TYPE_MUX, + .offset = 15, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node can0_nodes[] = { + { + .type = TYPE_MUX, + .offset = 7, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node can1_nodes[] = { + { + .type = TYPE_MUX, + .offset = 22, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node cpu_r5_core_nodes[] = { + { + .type = TYPE_GATE, + .offset = 25, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_IGNORE_UNUSED | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node dll_ref_nodes[] = { + { + .type = TYPE_MUX, + .offset = 0, + .width = 3, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node timestamp_ref_nodes[] = { + GENERIC_MUX, + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + IGNORE_UNUSED_GATE, +}; + +static int32_t can_mio_parents[] = { + EXT_CLK_MIO0, EXT_CLK_MIO1, EXT_CLK_MIO2, EXT_CLK_MIO3, + EXT_CLK_MIO4, EXT_CLK_MIO5, EXT_CLK_MIO6, EXT_CLK_MIO7, + EXT_CLK_MIO8, EXT_CLK_MIO9, EXT_CLK_MIO10, EXT_CLK_MIO11, + EXT_CLK_MIO12, EXT_CLK_MIO13, EXT_CLK_MIO14, EXT_CLK_MIO15, + EXT_CLK_MIO16, EXT_CLK_MIO17, EXT_CLK_MIO18, EXT_CLK_MIO19, + EXT_CLK_MIO20, EXT_CLK_MIO21, EXT_CLK_MIO22, EXT_CLK_MIO23, + EXT_CLK_MIO24, EXT_CLK_MIO25, EXT_CLK_MIO26, EXT_CLK_MIO27, + EXT_CLK_MIO28, EXT_CLK_MIO29, EXT_CLK_MIO30, EXT_CLK_MIO31, + EXT_CLK_MIO32, EXT_CLK_MIO33, EXT_CLK_MIO34, EXT_CLK_MIO35, + EXT_CLK_MIO36, EXT_CLK_MIO37, EXT_CLK_MIO38, EXT_CLK_MIO39, + EXT_CLK_MIO40, EXT_CLK_MIO41, EXT_CLK_MIO42, EXT_CLK_MIO43, + EXT_CLK_MIO44, EXT_CLK_MIO45, EXT_CLK_MIO46, EXT_CLK_MIO47, + EXT_CLK_MIO48, EXT_CLK_MIO49, EXT_CLK_MIO50, EXT_CLK_MIO51, + EXT_CLK_MIO52, EXT_CLK_MIO53, EXT_CLK_MIO54, EXT_CLK_MIO55, + EXT_CLK_MIO56, EXT_CLK_MIO57, EXT_CLK_MIO58, EXT_CLK_MIO59, + EXT_CLK_MIO60, EXT_CLK_MIO61, EXT_CLK_MIO62, EXT_CLK_MIO63, + EXT_CLK_MIO64, EXT_CLK_MIO65, EXT_CLK_MIO66, EXT_CLK_MIO67, + EXT_CLK_MIO68, EXT_CLK_MIO69, EXT_CLK_MIO70, EXT_CLK_MIO71, + EXT_CLK_MIO72, EXT_CLK_MIO73, EXT_CLK_MIO74, EXT_CLK_MIO75, + EXT_CLK_MIO76, EXT_CLK_MIO77, CLK_NA_PARENT +}; + +/* Clock array containing clock informaton */ +static struct pm_clock clocks[] = { + [CLK_APLL_INT] = { + .name = "apll_int", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_APLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &ignore_unused_pll_nodes, + .num_nodes = ARRAY_SIZE(ignore_unused_pll_nodes), + }, + [CLK_APLL_PRE_SRC] = { + .name = "apll_pre_src", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_APLL_HALF] = { + .name = "apll_half", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_APLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_APLL_INT_MUX] = { + .name = "apll_int_mux", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_APLL_INT, + CLK_APLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_APLL_POST_SRC] = { + .name = "apll_post_src", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_APLL] = { + .name = "apll", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_APLL_INT_MUX, + CLK_APLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + [CLK_DPLL_INT] = { + .name = "dpll_int", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_DPLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &generic_pll_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_nodes), + }, + [CLK_DPLL_PRE_SRC] = { + .name = "dpll_pre_src", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_DPLL_HALF] = { + .name = "dpll_half", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_DPLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_DPLL_INT_MUX] = { + .name = "dpll_int_mux", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_DPLL_INT, + CLK_DPLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_DPLL_POST_SRC] = { + .name = "dpll_post_src", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_DPLL] = { + .name = "dpll", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_DPLL_INT_MUX, + CLK_DPLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + [CLK_VPLL_INT] = { + .name = "vpll_int", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_VPLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &ignore_unused_pll_nodes, + .num_nodes = ARRAY_SIZE(ignore_unused_pll_nodes), + }, + [CLK_VPLL_PRE_SRC] = { + .name = "vpll_pre_src", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_VPLL_HALF] = { + .name = "vpll_half", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_VPLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_VPLL_INT_MUX] = { + .name = "vpll_int_mux", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_VPLL_INT, + CLK_VPLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_VPLL_POST_SRC] = { + .name = "vpll_post_src", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_VPLL] = { + .name = "vpll", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_VPLL_INT_MUX, + CLK_VPLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + [CLK_IOPLL_INT] = { + .name = "iopll_int", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_IOPLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &generic_pll_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_nodes), + }, + [CLK_IOPLL_PRE_SRC] = { + .name = "iopll_pre_src", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_IOPLL_HALF] = { + .name = "iopll_half", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_IOPLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_IOPLL_INT_MUX] = { + .name = "iopll_int_mux", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_IOPLL_INT, + CLK_IOPLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_IOPLL_POST_SRC] = { + .name = "iopll_post_src", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_IOPLL] = { + .name = "iopll", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_IOPLL_INT_MUX, + CLK_IOPLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + [CLK_RPLL_INT] = { + .name = "rpll_int", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_RPLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &generic_pll_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_nodes), + }, + [CLK_RPLL_PRE_SRC] = { + .name = "rpll_pre_src", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_RPLL_HALF] = { + .name = "rpll_half", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_RPLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_RPLL_INT_MUX] = { + .name = "rpll_int_mux", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_RPLL_INT, + CLK_RPLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_RPLL_POST_SRC] = { + .name = "rpll_post_src", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_RPLL] = { + .name = "rpll", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRL_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_RPLL_INT_MUX, + CLK_RPLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + /* Peripheral Clocks */ + [CLK_ACPU] = { + .name = "acpu", + .control_reg = CRF_APB_ACPU_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_VPLL, + CLK_NA_PARENT + }), + .nodes = &acpu_nodes, + .num_nodes = ARRAY_SIZE(acpu_nodes), + }, + [CLK_ACPU_FULL] = { + .name = "acpu_full", + .control_reg = CRF_APB_ACPU_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_ACPU | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_NA_PARENT + }), + .nodes = &acpu_full_nodes, + .num_nodes = ARRAY_SIZE(acpu_full_nodes), + }, + [CLK_DBG_TRACE] = { + .name = "dbg_trace", + .control_reg = CRF_APB_DBG_TRACE_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_APLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_DBG_FPD] = { + .name = "dbg_fpd", + .control_reg = CRF_APB_DBG_FPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_APLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_DBG_TSTMP] = { + .name = "dbg_tstmp", + .control_reg = CRF_APB_DBG_TSTMP_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_APLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_nodes), + }, + [CLK_DP_VIDEO_REF] = { + .name = "dp_video_ref", + .control_reg = CRF_APB_DP_VIDEO_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_VPLL, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_RPLL_TO_FPD, + CLK_NA_PARENT + }), + .nodes = &dp_audio_video_ref_nodes, + .num_nodes = ARRAY_SIZE(dp_audio_video_ref_nodes), + }, + [CLK_DP_AUDIO_REF] = { + .name = "dp_audio_ref", + .control_reg = CRF_APB_DP_AUDIO_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_VPLL, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_RPLL_TO_FPD, + CLK_NA_PARENT + }), + .nodes = &dp_audio_video_ref_nodes, + .num_nodes = ARRAY_SIZE(dp_audio_video_ref_nodes), + }, + [CLK_DP_STC_REF] = { + .name = "dp_stc_ref", + .control_reg = CRF_APB_DP_STC_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_VPLL, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_RPLL_TO_FPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_DPDMA_REF] = { + .name = "dpdma_ref", + .control_reg = CRF_APB_DPDMA_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_VPLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_DDR_REF] = { + .name = "ddr_ref", + .control_reg = CRF_APB_DDR_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_DPLL, + CLK_VPLL, + CLK_NA_PARENT + }), + .nodes = &ddr_nodes, + .num_nodes = ARRAY_SIZE(ddr_nodes), + }, + [CLK_GPU_REF] = { + .name = "gpu_ref", + .control_reg = CRF_APB_GPU_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_VPLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_SATA_REF] = { + .name = "sata_ref", + .control_reg = CRF_APB_SATA_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_APLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_PCIE_REF] = { + .name = "pcie_ref", + .control_reg = CRF_APB_PCIE_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_RPLL_TO_FPD, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_GDMA_REF] = { + .name = "gdma_ref", + .control_reg = CRF_APB_GDMA_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_VPLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_GTGREF0_REF] = { + .name = "gtgref0_ref", + .control_reg = CRF_APB_GTGREF0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_APLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_TOPSW_MAIN] = { + .name = "topsw_main", + .control_reg = CRF_APB_TOPSW_MAIN_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_VPLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_TOPSW_LSBUS] = { + .name = "topsw_lsbus", + .control_reg = CRF_APB_TOPSW_LSBUS_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_IOPLL_TO_FPD, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_IOU_SWITCH] = { + .name = "iou_switch", + .control_reg = CRL_APB_IOU_SWITCH_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_GEM0_REF_UNGATED] = { + .name = "gem0_ref_ung", + .control_reg = CRL_APB_GEM0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &gem_ref_ungated_nodes, + .num_nodes = ARRAY_SIZE(gem_ref_ungated_nodes), + }, + [CLK_GEM1_REF_UNGATED] = { + .name = "gem1_ref_ung", + .control_reg = CRL_APB_GEM1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &gem_ref_ungated_nodes, + .num_nodes = ARRAY_SIZE(gem_ref_ungated_nodes), + }, + [CLK_GEM2_REF_UNGATED] = { + .name = "gem2_ref_ung", + .control_reg = CRL_APB_GEM2_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &gem_ref_ungated_nodes, + .num_nodes = ARRAY_SIZE(gem_ref_ungated_nodes), + }, + [CLK_GEM3_REF_UNGATED] = { + .name = "gem3_ref_ung", + .control_reg = CRL_APB_GEM3_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &gem_ref_ungated_nodes, + .num_nodes = ARRAY_SIZE(gem_ref_ungated_nodes), + }, + [CLK_GEM0_REF] = { + .name = "gem0_ref", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM0_REF_UNGATED | + (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN), + EXT_CLK_GEM0_TX_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem0_ref_nodes, + .num_nodes = ARRAY_SIZE(gem0_ref_nodes), + }, + [CLK_GEM1_REF] = { + .name = "gem1_ref", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM1_REF_UNGATED | + (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN), + EXT_CLK_GEM1_TX_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem1_ref_nodes, + .num_nodes = ARRAY_SIZE(gem1_ref_nodes), + }, + [CLK_GEM2_REF] = { + .name = "gem2_ref", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM2_REF_UNGATED | + (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN), + EXT_CLK_GEM2_TX_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem2_ref_nodes, + .num_nodes = ARRAY_SIZE(gem2_ref_nodes), + }, + [CLK_GEM3_REF] = { + .name = "gem3_ref", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM3_REF_UNGATED | + (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN), + EXT_CLK_GEM3_TX_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem3_ref_nodes, + .num_nodes = ARRAY_SIZE(gem3_ref_nodes), + }, + [CLK_USB0_BUS_REF] = { + .name = "usb0_bus_ref", + .control_reg = CRL_APB_USB0_BUS_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &usb_nodes, + .num_nodes = ARRAY_SIZE(usb_nodes), + }, + [CLK_USB1_BUS_REF] = { + .name = "usb1_bus_ref", + .control_reg = CRL_APB_USB1_BUS_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &usb_nodes, + .num_nodes = ARRAY_SIZE(usb_nodes), + }, + [CLK_USB3_DUAL_REF] = { + .name = "usb3_dual_ref", + .control_reg = CRL_APB_USB3_DUAL_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &usb_nodes, + .num_nodes = ARRAY_SIZE(usb_nodes), + }, + [CLK_QSPI_REF] = { + .name = "qspi_ref", + .control_reg = CRL_APB_QSPI_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_SDIO0_REF] = { + .name = "sdio0_ref", + .control_reg = CRL_APB_SDIO0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_VPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_SDIO1_REF] = { + .name = "sdio1_ref", + .control_reg = CRL_APB_SDIO1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_VPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_UART0_REF] = { + .name = "uart0_ref", + .control_reg = CRL_APB_UART0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_UART1_REF] = { + .name = "uart1_ref", + .control_reg = CRL_APB_UART1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_SPI0_REF] = { + .name = "spi0_ref", + .control_reg = CRL_APB_SPI0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_SPI1_REF] = { + .name = "spi1_ref", + .control_reg = CRL_APB_SPI1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_CAN0_REF] = { + .name = "can0_ref", + .control_reg = CRL_APB_CAN0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_CAN1_REF] = { + .name = "can1_ref", + .control_reg = CRL_APB_CAN1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_NAND_REF] = { + .name = "nand_ref", + .control_reg = CRL_APB_NAND_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_GEM_TSU_REF] = { + .name = "gem_tsu_ref", + .control_reg = CRL_APB_GEM_TSU_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_DLL_REF] = { + .name = "dll_ref", + .control_reg = CRL_APB_DLL_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_RPLL, + CLK_NA_PARENT + }), + .nodes = &dll_ref_nodes, + .num_nodes = ARRAY_SIZE(dll_ref_nodes), + }, + [CLK_ADMA_REF] = { + .name = "adma_ref", + .control_reg = CRL_APB_ADMA_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_DBG_LPD] = { + .name = "dbg_lpd", + .control_reg = CRL_APB_DBG_LPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_CPU_R5] = { + .name = "cpu_r5", + .control_reg = CRL_APB_CPU_R5_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_CSU_PLL] = { + .name = "csu_pll", + .control_reg = CRL_APB_CSU_PLL_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_PCAP] = { + .name = "pcap", + .control_reg = CRL_APB_PCAP_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_LPD_LSBUS] = { + .name = "lpd_lsbus", + .control_reg = CRL_APB_LPD_LSBUS_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_LPD_SWITCH] = { + .name = "lpd_switch", + .control_reg = CRL_APB_LPD_SWITCH_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_I2C0_REF] = { + .name = "i2c0_ref", + .control_reg = CRL_APB_I2C0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_I2C1_REF] = { + .name = "i2c1_ref", + .control_reg = CRL_APB_I2C1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_TIMESTAMP_REF] = { + .name = "timestamp_ref", + .control_reg = CRL_APB_TIMESTAMP_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = ×tamp_ref_nodes, + .num_nodes = ARRAY_SIZE(timestamp_ref_nodes), + }, + [CLK_PL0_REF] = { + .name = "pl0_ref", + .control_reg = CRL_APB_PL0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &pl_nodes, + .num_nodes = ARRAY_SIZE(pl_nodes), + }, + [CLK_PL1_REF] = { + .name = "pl1_ref", + .control_reg = CRL_APB_PL1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &pl_nodes, + .num_nodes = ARRAY_SIZE(pl_nodes), + }, + [CLK_PL2_REF] = { + .name = "pl2_ref", + .control_reg = CRL_APB_PL2_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &pl_nodes, + .num_nodes = ARRAY_SIZE(pl_nodes), + }, + [CLK_PL3_REF] = { + .name = "pl3_ref", + .control_reg = CRL_APB_PL3_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &pl_nodes, + .num_nodes = ARRAY_SIZE(pl_nodes), + }, + [CLK_AMS_REF] = { + .name = "ams_ref", + .control_reg = CRL_APB_AMS_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_IOPLL_TO_FPD] = { + .name = "iopll_to_fpd", + .control_reg = CRL_APB_IOPLL_TO_FPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_IOPLL, CLK_NA_PARENT}), + .nodes = &generic_domain_crossing_nodes, + .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes), + }, + [CLK_RPLL_TO_FPD] = { + .name = "rpll_to_fpd", + .control_reg = CRL_APB_RPLL_TO_FPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_RPLL, CLK_NA_PARENT}), + .nodes = &rpll_to_fpd_nodes, + .num_nodes = ARRAY_SIZE(rpll_to_fpd_nodes), + }, + [CLK_APLL_TO_LPD] = { + .name = "apll_to_lpd", + .control_reg = CRF_APB_APLL_TO_LPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_APLL, CLK_NA_PARENT}), + .nodes = &generic_domain_crossing_nodes, + .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes), + }, + [CLK_DPLL_TO_LPD] = { + .name = "dpll_to_lpd", + .control_reg = CRF_APB_DPLL_TO_LPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_DPLL, CLK_NA_PARENT}), + .nodes = &generic_domain_crossing_nodes, + .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes), + }, + [CLK_VPLL_TO_LPD] = { + .name = "vpll_to_lpd", + .control_reg = CRF_APB_VPLL_TO_LPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_VPLL, CLK_NA_PARENT}), + .nodes = &generic_domain_crossing_nodes, + .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes), + }, + [CLK_GEM0_TX] = { + .name = "gem0_tx", + .control_reg = CRL_APB_GEM0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM0_REF, + CLK_NA_PARENT + }), + .nodes = &gem_tx_nodes, + .num_nodes = ARRAY_SIZE(gem_tx_nodes), + }, + [CLK_GEM1_TX] = { + .name = "gem1_tx", + .control_reg = CRL_APB_GEM1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM1_REF, + CLK_NA_PARENT + }), + .nodes = &gem_tx_nodes, + .num_nodes = ARRAY_SIZE(gem_tx_nodes), + }, + [CLK_GEM2_TX] = { + .name = "gem2_tx", + .control_reg = CRL_APB_GEM2_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM2_REF, + CLK_NA_PARENT + }), + .nodes = &gem_tx_nodes, + .num_nodes = ARRAY_SIZE(gem_tx_nodes), + }, + [CLK_GEM3_TX] = { + .name = "gem3_tx", + .control_reg = CRL_APB_GEM3_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM3_REF, + CLK_NA_PARENT + }), + .nodes = &gem_tx_nodes, + .num_nodes = ARRAY_SIZE(gem_tx_nodes), + }, + [CLK_GEM0_RX] = { + .name = "gem0_rx", + .control_reg = CRL_APB_GEM0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + EXT_CLK_GEM0_RX_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem_rx_nodes, + .num_nodes = ARRAY_SIZE(gem_rx_nodes), + }, + [CLK_GEM1_RX] = { + .name = "gem1_rx", + .control_reg = CRL_APB_GEM1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + EXT_CLK_GEM1_RX_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem_rx_nodes, + .num_nodes = ARRAY_SIZE(gem_rx_nodes), + }, + [CLK_GEM2_RX] = { + .name = "gem2_rx", + .control_reg = CRL_APB_GEM2_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + EXT_CLK_GEM2_RX_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem_rx_nodes, + .num_nodes = ARRAY_SIZE(gem_rx_nodes), + }, + [CLK_GEM3_RX] = { + .name = "gem3_rx", + .control_reg = CRL_APB_GEM3_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + EXT_CLK_GEM3_RX_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem_rx_nodes, + .num_nodes = ARRAY_SIZE(gem_rx_nodes), + }, + [CLK_ACPU_HALF] = { + .name = "acpu_half", + .control_reg = CRF_APB_ACPU_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_ACPU | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_NA_PARENT + }), + .nodes = &acpu_half_nodes, + .num_nodes = ARRAY_SIZE(acpu_half_nodes), + }, + [CLK_FPD_WDT] = { + .name = "fpd_wdt", + .control_reg = FPD_SLCR_WDT_CLK_SEL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_TOPSW_LSBUS, + EXT_CLK_SWDT0 | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &wdt_nodes, + .num_nodes = ARRAY_SIZE(wdt_nodes), + }, + [CLK_GPU_PP0_REF] = { + .name = "gpu_pp0_ref", + .control_reg = CRF_APB_GPU_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GPU_REF | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_NA_PARENT + }), + .nodes = &gpu_pp0_nodes, + .num_nodes = ARRAY_SIZE(gpu_pp0_nodes), + }, + [CLK_GPU_PP1_REF] = { + .name = "gpu_pp1_ref", + .control_reg = CRF_APB_GPU_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GPU_REF | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_NA_PARENT + }), + .nodes = &gpu_pp1_nodes, + .num_nodes = ARRAY_SIZE(gpu_pp1_nodes), + }, + [CLK_GEM_TSU] = { + .name = "gem_tsu", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM_TSU_REF, + CLK_GEM_TSU_REF, + EXT_CLK_MIO26 | CLK_EXTERNAL_PARENT, + EXT_CLK_MIO50_OR_MIO51 | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem_tsu_nodes, + .num_nodes = ARRAY_SIZE(gem_tsu_nodes), + }, + [CLK_CPU_R5_CORE] = { + .name = "cpu_r5_core", + .control_reg = CRL_APB_CPU_R5_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_CPU_R5 | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_DUMMY_PARENT, + CLK_NA_PARENT + }), + .nodes = &cpu_r5_core_nodes, + .num_nodes = ARRAY_SIZE(cpu_r5_core_nodes), + }, + [CLK_CAN0_MIO] = { + .name = "can0_mio", + .control_reg = IOU_SLCR_CAN_MIO_CTRL, + .status_reg = 0, + .parents = &can_mio_parents, + .nodes = &can0_mio_nodes, + .num_nodes = ARRAY_SIZE(can0_mio_nodes), + }, + [CLK_CAN1_MIO] = { + .name = "can1_mio", + .control_reg = IOU_SLCR_CAN_MIO_CTRL, + .status_reg = 0, + .parents = &can_mio_parents, + .nodes = &can1_mio_nodes, + .num_nodes = ARRAY_SIZE(can1_mio_nodes), + }, + [CLK_CAN0] = { + .name = "can0", + .control_reg = IOU_SLCR_CAN_MIO_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_CAN0_REF, + CLK_CAN0_MIO, + CLK_NA_PARENT + }), + .nodes = &can0_nodes, + .num_nodes = ARRAY_SIZE(can0_nodes), + }, + [CLK_CAN1] = { + .name = "can1", + .control_reg = IOU_SLCR_CAN_MIO_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_CAN1_REF, + CLK_CAN1_MIO, + CLK_NA_PARENT + }), + .nodes = &can1_nodes, + .num_nodes = ARRAY_SIZE(can1_nodes), + }, + [CLK_LPD_WDT] = { + .name = "lpd_wdt", + .control_reg = IOU_SLCR_WDT_CLK_SEL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_LPD_LSBUS, + EXT_CLK_SWDT1 | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &wdt_nodes, + .num_nodes = ARRAY_SIZE(wdt_nodes), + }, +}; + +static struct pm_ext_clock ext_clocks[] = { + [EXT_CLK_INDEX(EXT_CLK_PSS_REF)] = { + .name = "pss_ref_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_VIDEO)] = { + .name = "video_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_PSS_ALT_REF)] = { + .name = "pss_alt_ref_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_AUX_REF)] = { + .name = "aux_ref_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_GT_CRX_REF)] = { + .name = "video_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_SWDT0)] = { + .name = "swdt0_ext_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_SWDT1)] = { + .name = "swdt1_ext_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM0_TX_EMIO)] = { + .name = "gem0_tx_ext", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM1_TX_EMIO)] = { + .name = "gem1_tx_ext", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM2_TX_EMIO)] = { + .name = "gem2_tx_ext", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM3_TX_EMIO)] = { + .name = "gem3_tx_ext", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM0_RX_EMIO)] = { + .name = "gem0_rx_ext", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM1_RX_EMIO)] = { + .name = "gem1_rx_ext", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM2_RX_EMIO)] = { + .name = "gem2_rx_ext", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM3_RX_EMIO)] = { + .name = "gem3_rx_ext", + }, + [EXT_CLK_INDEX(EXT_CLK_MIO50_OR_MIO51)] = { + .name = "mio_clk_50_51", + }, + EXT_CLK_MIO_DATA(0), + EXT_CLK_MIO_DATA(1), + EXT_CLK_MIO_DATA(2), + EXT_CLK_MIO_DATA(3), + EXT_CLK_MIO_DATA(4), + EXT_CLK_MIO_DATA(5), + EXT_CLK_MIO_DATA(6), + EXT_CLK_MIO_DATA(7), + EXT_CLK_MIO_DATA(8), + EXT_CLK_MIO_DATA(9), + EXT_CLK_MIO_DATA(10), + EXT_CLK_MIO_DATA(11), + EXT_CLK_MIO_DATA(12), + EXT_CLK_MIO_DATA(13), + EXT_CLK_MIO_DATA(14), + EXT_CLK_MIO_DATA(15), + EXT_CLK_MIO_DATA(16), + EXT_CLK_MIO_DATA(17), + EXT_CLK_MIO_DATA(18), + EXT_CLK_MIO_DATA(19), + EXT_CLK_MIO_DATA(20), + EXT_CLK_MIO_DATA(21), + EXT_CLK_MIO_DATA(22), + EXT_CLK_MIO_DATA(23), + EXT_CLK_MIO_DATA(24), + EXT_CLK_MIO_DATA(25), + EXT_CLK_MIO_DATA(26), + EXT_CLK_MIO_DATA(27), + EXT_CLK_MIO_DATA(28), + EXT_CLK_MIO_DATA(29), + EXT_CLK_MIO_DATA(30), + EXT_CLK_MIO_DATA(31), + EXT_CLK_MIO_DATA(32), + EXT_CLK_MIO_DATA(33), + EXT_CLK_MIO_DATA(34), + EXT_CLK_MIO_DATA(35), + EXT_CLK_MIO_DATA(36), + EXT_CLK_MIO_DATA(37), + EXT_CLK_MIO_DATA(38), + EXT_CLK_MIO_DATA(39), + EXT_CLK_MIO_DATA(40), + EXT_CLK_MIO_DATA(41), + EXT_CLK_MIO_DATA(42), + EXT_CLK_MIO_DATA(43), + EXT_CLK_MIO_DATA(44), + EXT_CLK_MIO_DATA(45), + EXT_CLK_MIO_DATA(46), + EXT_CLK_MIO_DATA(47), + EXT_CLK_MIO_DATA(48), + EXT_CLK_MIO_DATA(49), + EXT_CLK_MIO_DATA(50), + EXT_CLK_MIO_DATA(51), + EXT_CLK_MIO_DATA(52), + EXT_CLK_MIO_DATA(53), + EXT_CLK_MIO_DATA(54), + EXT_CLK_MIO_DATA(55), + EXT_CLK_MIO_DATA(56), + EXT_CLK_MIO_DATA(57), + EXT_CLK_MIO_DATA(58), + EXT_CLK_MIO_DATA(59), + EXT_CLK_MIO_DATA(60), + EXT_CLK_MIO_DATA(61), + EXT_CLK_MIO_DATA(62), + EXT_CLK_MIO_DATA(63), + EXT_CLK_MIO_DATA(64), + EXT_CLK_MIO_DATA(65), + EXT_CLK_MIO_DATA(66), + EXT_CLK_MIO_DATA(67), + EXT_CLK_MIO_DATA(68), + EXT_CLK_MIO_DATA(69), + EXT_CLK_MIO_DATA(70), + EXT_CLK_MIO_DATA(71), + EXT_CLK_MIO_DATA(72), + EXT_CLK_MIO_DATA(73), + EXT_CLK_MIO_DATA(74), + EXT_CLK_MIO_DATA(75), + EXT_CLK_MIO_DATA(76), + EXT_CLK_MIO_DATA(77), +}; + +/* Array of clock which are invalid for this variant */ +static uint32_t pm_clk_invalid_list[] = {CLK_USB0, CLK_USB1, CLK_CSU_SPB, + CLK_ACPU_FULL, + CLK_ACPU_HALF, + CLK_APLL_TO_LPD, + CLK_DBG_FPD, + CLK_DBG_LPD, + CLK_DBG_TRACE, + CLK_DBG_TSTMP, + CLK_DDR_REF, + CLK_TOPSW_MAIN, + CLK_GTGREF0_REF, + CLK_LPD_SWITCH, + CLK_CPU_R5, + CLK_CPU_R5_CORE, + CLK_CSU_SPB, + CLK_CSU_PLL, + CLK_PCAP, + CLK_IOU_SWITCH, + CLK_DLL_REF, + CLK_TIMESTAMP_REF, +}; + +/** + * pm_clock_valid - Check if clock is valid or not + * @clock_id Id of the clock to be queried + * + * This function is used to check if given clock is valid + * or not for the chip variant. + * + * List of invalid clocks are maintained in array list for + * different variants. + * + * Return: Returns 1 if clock is valid else 0. + */ +static bool pm_clock_valid(unsigned int clock_id) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pm_clk_invalid_list); i++) + if (pm_clk_invalid_list[i] == clock_id) + return 0; + + return 1; +} + +/** + * pm_clock_type - Get clock's type + * @clock_id Id of the clock to be queried + * + * This function is used to check type of clock (OUTPUT/EXTERNAL). + * + * Return: Returns type of clock (OUTPUT/EXTERNAL). + */ +static unsigned int pm_clock_type(unsigned int clock_id) +{ + return (clock_id < CLK_MAX_OUTPUT_CLK) ? + CLK_TYPE_OUTPUT : CLK_TYPE_EXTERNAL; +} + +/** + * pm_api_clock_get_num_clocks() - PM call to request number of clocks + * @nclocks Number of clocks + * + * This function is used by master to get number of clocks. + * + * @return Returns success. + */ +enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks) +{ + *nclocks = CLK_MAX; + + return PM_RET_SUCCESS; +} + +/** + * pm_api_clock_get_name() - PM call to request a clock's name + * @clock_id Clock ID + * @name Name of clock (max 16 bytes) + * + * This function is used by master to get nmae of clock specified + * by given clock ID. + */ +void pm_api_clock_get_name(unsigned int clock_id, char *name) +{ + if (clock_id == CLK_MAX) + memcpy(name, END_OF_CLK, sizeof(END_OF_CLK) > CLK_NAME_LEN ? + CLK_NAME_LEN : sizeof(END_OF_CLK)); + else if (!pm_clock_valid(clock_id)) + memset(name, 0, CLK_NAME_LEN); + else if (clock_id < CLK_MAX_OUTPUT_CLK) + memcpy(name, clocks[clock_id].name, CLK_NAME_LEN); + else + memcpy(name, ext_clocks[clock_id - CLK_MAX_OUTPUT_CLK].name, + CLK_NAME_LEN); +} + +/** + * pm_api_clock_get_topology() - PM call to request a clock's topology + * @clock_id Clock ID + * @index Topology index for next toplogy node + * @topology Buffer to store nodes in topology and flags + * + * This function is used by master to get topology information for the + * clock specified by given clock ID. Each response would return 3 + * topology nodes. To get next nodes, caller needs to call this API with + * index of next node. Index starts from 0. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id, + unsigned int index, + uint32_t *topology) +{ + struct pm_clock_node *clock_nodes; + uint8_t num_nodes; + unsigned int i; + uint16_t typeflags; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + + memset(topology, 0, CLK_TOPOLOGY_PAYLOAD_LEN); + clock_nodes = *clocks[clock_id].nodes; + num_nodes = clocks[clock_id].num_nodes; + + /* Skip parent till index */ + if (index >= num_nodes) + return PM_RET_SUCCESS; + + for (i = 0; i < 3U; i++) { + if ((index + i) == num_nodes) + break; + topology[i] = clock_nodes[index + i].type; + topology[i] |= clock_nodes[index + i].clkflags << + CLK_CLKFLAGS_SHIFT; + typeflags = clock_nodes[index + i].typeflags; + topology[i] |= (typeflags & CLK_TYPEFLAGS_BITS_MASK) << + CLK_TYPEFLAGS_SHIFT; + topology[i] |= (typeflags & CLK_TYPEFLAGS2_BITS_MASK) >> + (CLK_TYPEFLAGS_BITS - CLK_TYPEFLAGS2_SHIFT); + } + + return PM_RET_SUCCESS; +} + +/** + * pm_api_clock_get_fixedfactor_params() - PM call to request a clock's fixed + * factor parameters for fixed clock + * @clock_id Clock ID + * @mul Multiplication value + * @div Divisor value + * + * This function is used by master to get fixed factor parameers for the + * fixed clock. This API is application only for the fixed clock. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id, + uint32_t *mul, + uint32_t *div) +{ + struct pm_clock_node *clock_nodes; + uint8_t num_nodes; + unsigned int type, i; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + clock_nodes = *clocks[clock_id].nodes; + num_nodes = clocks[clock_id].num_nodes; + + for (i = 0; i < num_nodes; i++) { + type = clock_nodes[i].type; + if (type == TYPE_FIXEDFACTOR) { + *mul = clock_nodes[i].mult; + *div = clock_nodes[i].div; + break; + } + } + + /* Clock is not fixed clock */ + if (i == num_nodes) + return PM_RET_ERROR_ARGS; + + return PM_RET_SUCCESS; +} + +/** + * pm_api_clock_get_parents() - PM call to request a clock's first 3 parents + * @clock_id Clock ID + * @index Index of next parent + * @parents Parents of the given clock + * + * This function is used by master to get clock's parents information. + * This API will return 3 parents with a single response. To get other + * parents, master should call same API in loop with new parent index + * till error is returned. + * + * E.g First call should have index 0 which will return parents 0, 1 and + * 2. Next call, index should be 3 which will return parent 3,4 and 5 and + * so on. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id, + unsigned int index, + uint32_t *parents) +{ + unsigned int i; + int32_t *clk_parents; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + clk_parents = *clocks[clock_id].parents; + if (clk_parents == NULL) + return PM_RET_ERROR_ARGS; + + memset(parents, 0, CLK_PARENTS_PAYLOAD_LEN); + + /* Skip parent till index */ + for (i = 0; i < index; i++) + if (clk_parents[i] == CLK_NA_PARENT) + return PM_RET_SUCCESS; + + for (i = 0; i < 3; i++) { + parents[i] = clk_parents[index + i]; + if (clk_parents[index + i] == CLK_NA_PARENT) + break; + } + + return PM_RET_SUCCESS; +} + +/** + * pm_api_clock_get_attributes() - PM call to request a clock's attributes + * @clock_id Clock ID + * @attr Clock attributes + * + * This function is used by master to get clock's attributes + * (e.g. valid, clock type, etc). + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id, + uint32_t *attr) +{ + if (clock_id >= CLK_MAX) + return PM_RET_ERROR_ARGS; + + /* Clock valid bit */ + *attr = pm_clock_valid(clock_id); + + /* Clock type (Output/External) */ + *attr |= (pm_clock_type(clock_id) << CLK_TYPE_SHIFT); + + return PM_RET_SUCCESS; +} + +/** + * pm_api_clock_get_max_divisor - PM call to get max divisor + * @clock_id Clock ID + * @div_type Divisor Type (TYPE_DIV1 or TYPE_DIV2) + * @max_div Maximum supported divisor + * + * This function is used by master to get maximum supported value. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_get_max_divisor(enum clock_id clock_id, + uint8_t div_type, + uint32_t *max_div) +{ + uint32_t i; + struct pm_clock_node *nodes; + + if (clock_id >= CLK_MAX_OUTPUT_CLK) + return PM_RET_ERROR_ARGS; + + nodes = *clocks[clock_id].nodes; + for (i = 0; i < clocks[clock_id].num_nodes; i++) { + if (nodes[i].type == div_type) { + if (CLK_DIVIDER_POWER_OF_TWO & + nodes[i].typeflags) { + *max_div = (1 << (BIT(nodes[i].width) - 1)); + } else { + *max_div = BIT(nodes[i].width) - 1; + } + return PM_RET_SUCCESS; + } + } + + return PM_RET_ERROR_ARGS; +} + +/** + * struct pm_pll - PLL related data required to map IOCTL-based PLL control + * implemented by linux to system-level EEMI APIs + * @nid: PLL node ID + * @cid: PLL clock ID + * @pre_src: Pre-source PLL clock ID + * @post_src: Post-source PLL clock ID + * @div2: DIV2 PLL clock ID + * @bypass: PLL output clock ID that maps to bypass select output + * @mode: PLL mode currently set via IOCTL (PLL_FRAC_MODE/PLL_INT_MODE) + */ +struct pm_pll { + const enum pm_node_id nid; + const enum clock_id cid; + const enum clock_id pre_src; + const enum clock_id post_src; + const enum clock_id div2; + const enum clock_id bypass; + uint8_t mode; +}; + +static struct pm_pll pm_plls[] = { + { + .nid = NODE_IOPLL, + .cid = CLK_IOPLL_INT, + .pre_src = CLK_IOPLL_PRE_SRC, + .post_src = CLK_IOPLL_POST_SRC, + .div2 = CLK_IOPLL_INT_MUX, + .bypass = CLK_IOPLL, + }, { + .nid = NODE_RPLL, + .cid = CLK_RPLL_INT, + .pre_src = CLK_RPLL_PRE_SRC, + .post_src = CLK_RPLL_POST_SRC, + .div2 = CLK_RPLL_INT_MUX, + .bypass = CLK_RPLL, + }, { + .nid = NODE_APLL, + .cid = CLK_APLL_INT, + .pre_src = CLK_APLL_PRE_SRC, + .post_src = CLK_APLL_POST_SRC, + .div2 = CLK_APLL_INT_MUX, + .bypass = CLK_APLL, + }, { + .nid = NODE_VPLL, + .cid = CLK_VPLL_INT, + .pre_src = CLK_VPLL_PRE_SRC, + .post_src = CLK_VPLL_POST_SRC, + .div2 = CLK_VPLL_INT_MUX, + .bypass = CLK_VPLL, + }, { + .nid = NODE_DPLL, + .cid = CLK_DPLL_INT, + .pre_src = CLK_DPLL_PRE_SRC, + .post_src = CLK_DPLL_POST_SRC, + .div2 = CLK_DPLL_INT_MUX, + .bypass = CLK_DPLL, + }, +}; + +/** + * pm_clock_get_pll() - Get PLL structure by PLL clock ID + * @clock_id Clock ID of the target PLL + * + * @return Pointer to PLL structure if found, NULL otherwise + */ +struct pm_pll *pm_clock_get_pll(enum clock_id clock_id) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(pm_plls); i++) { + if (pm_plls[i].cid == clock_id) + return &pm_plls[i]; + } + + return NULL; +} + +/** + * pm_clock_get_pll_node_id() - Get PLL node ID by PLL clock ID + * @clock_id Clock ID of the target PLL + * @node_id Location to store node ID of the target PLL + * + * @return PM_RET_SUCCESS if node ID is found, PM_RET_ERROR_ARGS otherwise + */ +enum pm_ret_status pm_clock_get_pll_node_id(enum clock_id clock_id, + enum pm_node_id *node_id) +{ + struct pm_pll *pll = pm_clock_get_pll(clock_id); + + if (pll) { + *node_id = pll->nid; + return PM_RET_SUCCESS; + } + + return PM_RET_ERROR_ARGS; +} + +/** + * pm_clock_get_pll_by_related_clk() - Get PLL structure by PLL-related clock ID + * @clock_id Clock ID + * + * @return Pointer to PLL structure if found, NULL otherwise + */ +struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(pm_plls); i++) { + if (pm_plls[i].pre_src == clock_id || + pm_plls[i].post_src == clock_id || + pm_plls[i].div2 == clock_id || + pm_plls[i].bypass == clock_id) { + return &pm_plls[i]; + } + } + + return NULL; +} + +/** + * pm_clock_pll_enable() - "Enable" the PLL clock (lock the PLL) + * @pll: PLL to be locked + * + * This function is used to map IOCTL/linux-based PLL handling to system-level + * EEMI APIs + * + * Return: Error if the argument is not valid or status as returned by PMU + */ +enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll) +{ + if (!pll) + return PM_RET_ERROR_ARGS; + + /* Set the PLL mode according to the buffered mode value */ + if (pll->mode == PLL_FRAC_MODE) + return pm_pll_set_mode(pll->nid, PM_PLL_MODE_FRACTIONAL); + + return pm_pll_set_mode(pll->nid, PM_PLL_MODE_INTEGER); +} + +/** + * pm_clock_pll_disable - "Disable" the PLL clock (bypass/reset the PLL) + * @pll PLL to be bypassed/reset + * + * This function is used to map IOCTL/linux-based PLL handling to system-level + * EEMI APIs + * + * Return: Error if the argument is not valid or status as returned by PMU + */ +enum pm_ret_status pm_clock_pll_disable(struct pm_pll *pll) +{ + if (!pll) + return PM_RET_ERROR_ARGS; + + return pm_pll_set_mode(pll->nid, PM_PLL_MODE_RESET); +} + +/** + * pm_clock_pll_get_state - Get state of the PLL + * @pll Pointer to the target PLL structure + * @state Location to store the state: 1/0 ("Enabled"/"Disabled") + * + * "Enable" actually means that the PLL is locked and its bypass is deasserted, + * "Disable" means that it is bypassed. + * + * Return: PM_RET_ERROR_ARGS error if the argument is not valid, success if + * returned state value is valid or an error if returned by PMU + */ +enum pm_ret_status pm_clock_pll_get_state(struct pm_pll *pll, + unsigned int *state) +{ + enum pm_ret_status status; + enum pm_pll_mode mode; + + if (!pll || !state) + return PM_RET_ERROR_ARGS; + + status = pm_pll_get_mode(pll->nid, &mode); + if (status != PM_RET_SUCCESS) + return status; + + if (mode == PM_PLL_MODE_RESET) + *state = 0; + else + *state = 1; + + return PM_RET_SUCCESS; +} + +/** + * pm_clock_pll_set_parent - Set the clock parent for PLL-related clock id + * @pll Target PLL structure + * @clock_id Id of the clock + * @parent_index parent index (=mux select value) + * + * The whole clock-tree implementation relies on the fact that parent indexes + * match to the multiplexer select values. This function has to rely on that + * assumption as well => parent_index is actually the mux select value. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_pll_set_parent(struct pm_pll *pll, + enum clock_id clock_id, + unsigned int parent_index) +{ + if (!pll) + return PM_RET_ERROR_ARGS; + if (pll->pre_src == clock_id) + return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_PRE_SRC, + parent_index); + if (pll->post_src == clock_id) + return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_POST_SRC, + parent_index); + if (pll->div2 == clock_id) + return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_DIV2, + parent_index); + + return PM_RET_ERROR_ARGS; +} + +/** + * pm_clock_pll_get_parent - Get mux select value of PLL-related clock parent + * @pll Target PLL structure + * @clock_id Id of the clock + * @parent_index parent index (=mux select value) + * + * This function is used by master to get parent index for PLL-related clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_pll_get_parent(struct pm_pll *pll, + enum clock_id clock_id, + unsigned int *parent_index) +{ + if (!pll) + return PM_RET_ERROR_ARGS; + if (pll->pre_src == clock_id) + return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_PRE_SRC, + parent_index); + if (pll->post_src == clock_id) + return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_POST_SRC, + parent_index); + if (pll->div2 == clock_id) + return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_DIV2, + parent_index); + if (pll->bypass == clock_id) { + *parent_index = 0; + return PM_RET_SUCCESS; + } + + return PM_RET_ERROR_ARGS; +} + +/** + * pm_clock_set_pll_mode() - Set PLL mode + * @clock_id PLL clock id + * @mode Mode fractional/integer + * + * This function buffers/saves the PLL mode that is set. + * + * @return Success if mode is buffered or error if an argument is invalid + */ +enum pm_ret_status pm_clock_set_pll_mode(enum clock_id clock_id, + unsigned int mode) +{ + struct pm_pll *pll = pm_clock_get_pll(clock_id); + + if (!pll || (mode != PLL_FRAC_MODE && mode != PLL_INT_MODE)) + return PM_RET_ERROR_ARGS; + pll->mode = mode; + + return PM_RET_SUCCESS; +} + +/** + * pm_clock_get_pll_mode() - Get PLL mode + * @clock_id PLL clock id + * @mode Location to store the mode (fractional/integer) + * + * This function returns buffered PLL mode. + * + * @return Success if mode is stored or error if an argument is invalid + */ +enum pm_ret_status pm_clock_get_pll_mode(enum clock_id clock_id, + unsigned int *mode) +{ + struct pm_pll *pll = pm_clock_get_pll(clock_id); + + if (!pll || !mode) + return PM_RET_ERROR_ARGS; + *mode = pll->mode; + + return PM_RET_SUCCESS; +} + +/** + * pm_clock_id_is_valid() - Check if given clock ID is valid + * @clock_id ID of the clock to be checked + * + * @return Returns success if clock_id is valid, otherwise an error + */ +enum pm_ret_status pm_clock_id_is_valid(unsigned int clock_id) +{ + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + return PM_RET_SUCCESS; +} + +/** + * pm_clock_has_div() - Check if the clock has divider with given ID + * @clock_id Clock ID + * @div_id Divider ID + * + * @return True(1)=clock has the divider, false(0)=otherwise + */ +uint8_t pm_clock_has_div(unsigned int clock_id, enum pm_clock_div_id div_id) +{ + uint32_t i; + struct pm_clock_node *nodes; + + if (clock_id >= CLK_MAX_OUTPUT_CLK) + return 0; + + nodes = *clocks[clock_id].nodes; + for (i = 0; i < clocks[clock_id].num_nodes; i++) { + if (nodes[i].type == TYPE_DIV1) { + if (div_id == PM_CLOCK_DIV0_ID) + return 1; + } else if (nodes[i].type == TYPE_DIV2) { + if (div_id == PM_CLOCK_DIV1_ID) + return 1; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h new file mode 100644 index 0000000..5efd63f --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for clock control. + */ + +#ifndef PM_API_CLOCK_H +#define PM_API_CLOCK_H + +#include + +#include "pm_common.h" + +#define CLK_NAME_LEN U(15) +#define MAX_PARENTS U(100) +#define CLK_NA_PARENT -1 +#define CLK_DUMMY_PARENT -2 + +/* Flags for parent id */ +#define PARENT_CLK_SELF U(0) +#define PARENT_CLK_NODE1 U(1) +#define PARENT_CLK_NODE2 U(2) +#define PARENT_CLK_NODE3 U(3) +#define PARENT_CLK_NODE4 U(4) +#define PARENT_CLK_EXTERNAL U(5) +#define PARENT_CLK_MIO0_MIO77 U(6) + +#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */ +#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */ +#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */ +#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */ +/* unused */ +#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ +#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ +#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ +#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ +#define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ +#define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */ +#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ +/* parents need enable during gate/ungate, set rate and re-parent */ +#define CLK_OPS_PARENT_ENABLE BIT(12) + +#define CLK_DIVIDER_ONE_BASED BIT(0) +#define CLK_DIVIDER_POWER_OF_TWO BIT(1) +#define CLK_DIVIDER_ALLOW_ZERO BIT(2) +#define CLK_DIVIDER_HIWORD_MASK BIT(3) +#define CLK_DIVIDER_ROUND_CLOSEST BIT(4) +#define CLK_DIVIDER_READ_ONLY BIT(5) +#define CLK_DIVIDER_MAX_AT_ZERO BIT(6) +#define CLK_FRAC BIT(8) + +#define END_OF_CLK "END_OF_CLK" + +//CLock Ids +enum clock_id { + CLK_IOPLL, + CLK_RPLL, + CLK_APLL, + CLK_DPLL, + CLK_VPLL, + CLK_IOPLL_TO_FPD, + CLK_RPLL_TO_FPD, + CLK_APLL_TO_LPD, + CLK_DPLL_TO_LPD, + CLK_VPLL_TO_LPD, + CLK_ACPU, + CLK_ACPU_HALF, + CLK_DBG_FPD, + CLK_DBG_LPD, + CLK_DBG_TRACE, + CLK_DBG_TSTMP, + CLK_DP_VIDEO_REF, + CLK_DP_AUDIO_REF, + CLK_DP_STC_REF, + CLK_GDMA_REF, + CLK_DPDMA_REF, + CLK_DDR_REF, + CLK_SATA_REF, + CLK_PCIE_REF, + CLK_GPU_REF, + CLK_GPU_PP0_REF, + CLK_GPU_PP1_REF, + CLK_TOPSW_MAIN, + CLK_TOPSW_LSBUS, + CLK_GTGREF0_REF, + CLK_LPD_SWITCH, + CLK_LPD_LSBUS, + CLK_USB0_BUS_REF, + CLK_USB1_BUS_REF, + CLK_USB3_DUAL_REF, + CLK_USB0, + CLK_USB1, + CLK_CPU_R5, + CLK_CPU_R5_CORE, + CLK_CSU_SPB, + CLK_CSU_PLL, + CLK_PCAP, + CLK_IOU_SWITCH, + CLK_GEM_TSU_REF, + CLK_GEM_TSU, + CLK_GEM0_TX, + CLK_GEM1_TX, + CLK_GEM2_TX, + CLK_GEM3_TX, + CLK_GEM0_RX, + CLK_GEM1_RX, + CLK_GEM2_RX, + CLK_GEM3_RX, + CLK_QSPI_REF, + CLK_SDIO0_REF, + CLK_SDIO1_REF, + CLK_UART0_REF, + CLK_UART1_REF, + CLK_SPI0_REF, + CLK_SPI1_REF, + CLK_NAND_REF, + CLK_I2C0_REF, + CLK_I2C1_REF, + CLK_CAN0_REF, + CLK_CAN1_REF, + CLK_CAN0, + CLK_CAN1, + CLK_DLL_REF, + CLK_ADMA_REF, + CLK_TIMESTAMP_REF, + CLK_AMS_REF, + CLK_PL0_REF, + CLK_PL1_REF, + CLK_PL2_REF, + CLK_PL3_REF, + CLK_FPD_WDT, + CLK_IOPLL_INT, + CLK_IOPLL_PRE_SRC, + CLK_IOPLL_HALF, + CLK_IOPLL_INT_MUX, + CLK_IOPLL_POST_SRC, + CLK_RPLL_INT, + CLK_RPLL_PRE_SRC, + CLK_RPLL_HALF, + CLK_RPLL_INT_MUX, + CLK_RPLL_POST_SRC, + CLK_APLL_INT, + CLK_APLL_PRE_SRC, + CLK_APLL_HALF, + CLK_APLL_INT_MUX, + CLK_APLL_POST_SRC, + CLK_DPLL_INT, + CLK_DPLL_PRE_SRC, + CLK_DPLL_HALF, + CLK_DPLL_INT_MUX, + CLK_DPLL_POST_SRC, + CLK_VPLL_INT, + CLK_VPLL_PRE_SRC, + CLK_VPLL_HALF, + CLK_VPLL_INT_MUX, + CLK_VPLL_POST_SRC, + CLK_CAN0_MIO, + CLK_CAN1_MIO, + CLK_ACPU_FULL, + CLK_GEM0_REF, + CLK_GEM1_REF, + CLK_GEM2_REF, + CLK_GEM3_REF, + CLK_GEM0_REF_UNGATED, + CLK_GEM1_REF_UNGATED, + CLK_GEM2_REF_UNGATED, + CLK_GEM3_REF_UNGATED, + CLK_LPD_WDT, + END_OF_OUTPUT_CLKS, +}; + +#define CLK_MAX_OUTPUT_CLK (unsigned int)(END_OF_OUTPUT_CLKS) + +//External clock ids +enum { + EXT_CLK_PSS_REF = END_OF_OUTPUT_CLKS, + EXT_CLK_VIDEO, + EXT_CLK_PSS_ALT_REF, + EXT_CLK_AUX_REF, + EXT_CLK_GT_CRX_REF, + EXT_CLK_SWDT0, + EXT_CLK_SWDT1, + EXT_CLK_GEM0_TX_EMIO, + EXT_CLK_GEM1_TX_EMIO, + EXT_CLK_GEM2_TX_EMIO, + EXT_CLK_GEM3_TX_EMIO, + EXT_CLK_GEM0_RX_EMIO, + EXT_CLK_GEM1_RX_EMIO, + EXT_CLK_GEM2_RX_EMIO, + EXT_CLK_GEM3_RX_EMIO, + EXT_CLK_MIO50_OR_MIO51, + EXT_CLK_MIO0, + EXT_CLK_MIO1, + EXT_CLK_MIO2, + EXT_CLK_MIO3, + EXT_CLK_MIO4, + EXT_CLK_MIO5, + EXT_CLK_MIO6, + EXT_CLK_MIO7, + EXT_CLK_MIO8, + EXT_CLK_MIO9, + EXT_CLK_MIO10, + EXT_CLK_MIO11, + EXT_CLK_MIO12, + EXT_CLK_MIO13, + EXT_CLK_MIO14, + EXT_CLK_MIO15, + EXT_CLK_MIO16, + EXT_CLK_MIO17, + EXT_CLK_MIO18, + EXT_CLK_MIO19, + EXT_CLK_MIO20, + EXT_CLK_MIO21, + EXT_CLK_MIO22, + EXT_CLK_MIO23, + EXT_CLK_MIO24, + EXT_CLK_MIO25, + EXT_CLK_MIO26, + EXT_CLK_MIO27, + EXT_CLK_MIO28, + EXT_CLK_MIO29, + EXT_CLK_MIO30, + EXT_CLK_MIO31, + EXT_CLK_MIO32, + EXT_CLK_MIO33, + EXT_CLK_MIO34, + EXT_CLK_MIO35, + EXT_CLK_MIO36, + EXT_CLK_MIO37, + EXT_CLK_MIO38, + EXT_CLK_MIO39, + EXT_CLK_MIO40, + EXT_CLK_MIO41, + EXT_CLK_MIO42, + EXT_CLK_MIO43, + EXT_CLK_MIO44, + EXT_CLK_MIO45, + EXT_CLK_MIO46, + EXT_CLK_MIO47, + EXT_CLK_MIO48, + EXT_CLK_MIO49, + EXT_CLK_MIO50, + EXT_CLK_MIO51, + EXT_CLK_MIO52, + EXT_CLK_MIO53, + EXT_CLK_MIO54, + EXT_CLK_MIO55, + EXT_CLK_MIO56, + EXT_CLK_MIO57, + EXT_CLK_MIO58, + EXT_CLK_MIO59, + EXT_CLK_MIO60, + EXT_CLK_MIO61, + EXT_CLK_MIO62, + EXT_CLK_MIO63, + EXT_CLK_MIO64, + EXT_CLK_MIO65, + EXT_CLK_MIO66, + EXT_CLK_MIO67, + EXT_CLK_MIO68, + EXT_CLK_MIO69, + EXT_CLK_MIO70, + EXT_CLK_MIO71, + EXT_CLK_MIO72, + EXT_CLK_MIO73, + EXT_CLK_MIO74, + EXT_CLK_MIO75, + EXT_CLK_MIO76, + EXT_CLK_MIO77, + END_OF_CLKS, +}; + +#define CLK_MAX (unsigned int)(END_OF_CLKS) + +//CLock types +#define CLK_TYPE_OUTPUT 0U +#define CLK_TYPE_EXTERNAL 1U + +//Topology types +#define TYPE_INVALID 0U +#define TYPE_MUX 1U +#define TYPE_PLL 2U +#define TYPE_FIXEDFACTOR 3U +#define TYPE_DIV1 4U +#define TYPE_DIV2 5U +#define TYPE_GATE 6U + +struct pm_pll; +struct pm_pll *pm_clock_get_pll(enum clock_id clock_id); +struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id); +uint8_t pm_clock_has_div(unsigned int clock_id, enum pm_clock_div_id div_id); + +void pm_api_clock_get_name(unsigned int clock_id, char *name); +enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks); +enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id, + unsigned int index, + uint32_t *topology); +enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id, + uint32_t *mul, + uint32_t *div); +enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id, + unsigned int index, + uint32_t *parents); +enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id, + uint32_t *attr); +enum pm_ret_status pm_api_clock_get_max_divisor(enum clock_id clock_id, + uint8_t div_type, + uint32_t *max_div); + +enum pm_ret_status pm_clock_get_pll_node_id(enum clock_id clock_id, + enum pm_node_id *node_id); +enum pm_ret_status pm_clock_id_is_valid(unsigned int clock_id); + +enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll); +enum pm_ret_status pm_clock_pll_disable(struct pm_pll *pll); +enum pm_ret_status pm_clock_pll_get_state(struct pm_pll *pll, + unsigned int *state); +enum pm_ret_status pm_clock_pll_set_parent(struct pm_pll *pll, + enum clock_id clock_id, + unsigned int parent_index); +enum pm_ret_status pm_clock_pll_get_parent(struct pm_pll *pll, + enum clock_id clock_id, + unsigned int *parent_index); +enum pm_ret_status pm_clock_set_pll_mode(enum clock_id clock_id, + unsigned int mode); +enum pm_ret_status pm_clock_get_pll_mode(enum clock_id clock_id, + unsigned int *mode); + +#endif /* PM_API_CLOCK_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c new file mode 100644 index 0000000..a87681b --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -0,0 +1,734 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for ioctl. + */ + +#include +#include +#include +#include +#include + +#include "pm_api_clock.h" +#include "pm_api_ioctl.h" +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_common.h" +#include "pm_ipi.h" + +/** + * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode + * @mode Buffer to store value of oper mode(Split/Lock-step) + * + * This function provides current configured RPU operational mode. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(unsigned int *mode) +{ + unsigned int val; + + val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); + val &= ZYNQMP_SLSPLIT_MASK; + if (val == 0) + *mode = PM_RPU_MODE_LOCKSTEP; + else + *mode = PM_RPU_MODE_SPLIT; + + return PM_RET_SUCCESS; +} + +/** + * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode + * @mode Value to set for oper mode(Split/Lock-step) + * + * This function configures RPU operational mode(Split/Lock-step). + * It also sets TCM combined mode in RPU lock-step and TCM non-combined + * mode for RPU split mode. In case of Lock step mode, RPU1's output is + * clamped. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(unsigned int mode) +{ + unsigned int val; + + if (mmio_read_32(CRL_APB_RST_LPD_TOP) & CRL_APB_RPU_AMBA_RESET) + return PM_RET_ERROR_ACCESS; + + val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); + + if (mode == PM_RPU_MODE_SPLIT) { + val |= ZYNQMP_SLSPLIT_MASK; + val &= ~ZYNQMP_TCM_COMB_MASK; + val &= ~ZYNQMP_SLCLAMP_MASK; + } else if (mode == PM_RPU_MODE_LOCKSTEP) { + val &= ~ZYNQMP_SLSPLIT_MASK; + val |= ZYNQMP_TCM_COMB_MASK; + val |= ZYNQMP_SLCLAMP_MASK; + } else { + return PM_RET_ERROR_ARGS; + } + + mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val); + + return PM_RET_SUCCESS; +} + +/** + * pm_ioctl_config_boot_addr() - Configure RPU boot address + * @nid Node ID of RPU + * @value Value to set for boot address (TCM/OCM) + * + * This function configures RPU boot address(memory). + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid, + unsigned int value) +{ + unsigned int rpu_cfg_addr, val; + + if (nid == NODE_RPU_0) + rpu_cfg_addr = ZYNQMP_RPU0_CFG; + else if (nid == NODE_RPU_1) + rpu_cfg_addr = ZYNQMP_RPU1_CFG; + else + return PM_RET_ERROR_ARGS; + + val = mmio_read_32(rpu_cfg_addr); + + if (value == PM_RPU_BOOTMEM_LOVEC) + val &= ~ZYNQMP_VINITHI_MASK; + else if (value == PM_RPU_BOOTMEM_HIVEC) + val |= ZYNQMP_VINITHI_MASK; + else + return PM_RET_ERROR_ARGS; + + mmio_write_32(rpu_cfg_addr, val); + + return PM_RET_SUCCESS; +} + +/** + * pm_ioctl_config_tcm_comb() - Configure TCM combined mode + * @value Value to set (Split/Combined) + * + * This function configures TCM to be in split mode or combined + * mode. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_config_tcm_comb(unsigned int value) +{ + unsigned int val; + + val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); + + if (value == PM_RPU_TCM_SPLIT) + val &= ~ZYNQMP_TCM_COMB_MASK; + else if (value == PM_RPU_TCM_COMB) + val |= ZYNQMP_TCM_COMB_MASK; + else + return PM_RET_ERROR_ARGS; + + mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val); + + return PM_RET_SUCCESS; +} + +/** + * pm_ioctl_set_tapdelay_bypass() - Enable/Disable tap delay bypass + * @type Type of tap delay to enable/disable (e.g. QSPI) + * @value Enable/Disable + * + * This function enable/disable tap delay bypass. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_tapdelay_bypass(unsigned int type, + unsigned int value) +{ + if ((value != PM_TAPDELAY_BYPASS_ENABLE && + value != PM_TAPDELAY_BYPASS_DISABLE) || type >= PM_TAPDELAY_MAX) + return PM_RET_ERROR_ARGS; + + return pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK, value << type); +} + +/** + * pm_ioctl_set_sgmii_mode() - Set SGMII mode for the GEM device + * @nid Node ID of the device + * @value Enable/Disable + * + * This function enable/disable SGMII mode for the GEM device. + * While enabling SGMII mode, it also ties the GEM PCS Signal + * Detect to 1 and selects EMIO for RX clock generation. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_sgmii_mode(enum pm_node_id nid, + unsigned int value) +{ + unsigned int val, mask, shift; + enum pm_ret_status ret; + + if (value != PM_SGMII_DISABLE && value != PM_SGMII_ENABLE) + return PM_RET_ERROR_ARGS; + + switch (nid) { + case NODE_ETH_0: + shift = 0; + break; + case NODE_ETH_1: + shift = 1; + break; + case NODE_ETH_2: + shift = 2; + break; + case NODE_ETH_3: + shift = 3; + break; + default: + return PM_RET_ERROR_ARGS; + } + + if (value == PM_SGMII_DISABLE) { + mask = GEM_SGMII_MASK << GEM_CLK_CTRL_OFFSET * shift; + ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, 0U); + } else { + /* Tie the GEM PCS Signal Detect to 1 */ + mask = SGMII_SD_MASK << SGMII_SD_OFFSET * shift; + val = SGMII_PCS_SD_1 << SGMII_SD_OFFSET * shift; + ret = pm_mmio_write(IOU_GEM_CTRL, mask, val); + if (ret != PM_RET_SUCCESS) + return ret; + + /* Set the GEM to SGMII mode */ + mask = GEM_CLK_CTRL_MASK << GEM_CLK_CTRL_OFFSET * shift; + val = GEM_RX_SRC_SEL_GTR | GEM_SGMII_MODE; + val <<= GEM_CLK_CTRL_OFFSET * shift; + ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, val); + } + + return ret; +} + +/** + * pm_ioctl_sd_dll_reset() - Reset DLL logic + * @nid Node ID of the device + * @type Reset type + * + * This function resets DLL logic for the SD device. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_sd_dll_reset(enum pm_node_id nid, + unsigned int type) +{ + unsigned int mask, val; + enum pm_ret_status ret; + + if (nid == NODE_SD_0) { + mask = ZYNQMP_SD0_DLL_RST_MASK; + val = ZYNQMP_SD0_DLL_RST; + } else if (nid == NODE_SD_1) { + mask = ZYNQMP_SD1_DLL_RST_MASK; + val = ZYNQMP_SD1_DLL_RST; + } else { + return PM_RET_ERROR_ARGS; + } + + switch (type) { + case PM_DLL_RESET_ASSERT: + case PM_DLL_RESET_PULSE: + ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, val); + if (ret != PM_RET_SUCCESS) + return ret; + + if (type == PM_DLL_RESET_ASSERT) + break; + mdelay(1); + /* Fallthrough */ + case PM_DLL_RESET_RELEASE: + ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, 0); + break; + default: + ret = PM_RET_ERROR_ARGS; + break; + } + + return ret; +} + +/** + * pm_ioctl_sd_set_tapdelay() - Set tap delay for the SD device + * @nid Node ID of the device + * @type Type of tap delay to set (input/output) + * @value Value to set fot the tap delay + * + * This function sets input/output tap delay for the SD device. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid, + enum tap_delay_type type, + unsigned int value) +{ + unsigned int shift; + enum pm_ret_status ret; + unsigned int val, mask; + + if (nid == NODE_SD_0) { + shift = 0; + mask = ZYNQMP_SD0_DLL_RST_MASK; + } else if (nid == NODE_SD_1) { + shift = ZYNQMP_SD_TAP_OFFSET; + mask = ZYNQMP_SD1_DLL_RST_MASK; + } else { + return PM_RET_ERROR_ARGS; + } + + ret = pm_mmio_read(ZYNQMP_SD_DLL_CTRL, &val); + if (ret != PM_RET_SUCCESS) { + return ret; + } + + if ((val & mask) == 0) { + ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT); + if (ret != PM_RET_SUCCESS) { + return ret; + } + } + + if (type == PM_TAPDELAY_INPUT) { + ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, + (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), + (ZYNQMP_SD_ITAPCHGWIN << shift)); + if (ret != PM_RET_SUCCESS) + goto reset_release; + if (value == 0) + ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, + (ZYNQMP_SD_ITAPDLYENA_MASK << + shift), 0); + else + ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, + (ZYNQMP_SD_ITAPDLYENA_MASK << + shift), (ZYNQMP_SD_ITAPDLYENA << + shift)); + if (ret != PM_RET_SUCCESS) + goto reset_release; + ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, + (ZYNQMP_SD_ITAPDLYSEL_MASK << shift), + (value << shift)); + if (ret != PM_RET_SUCCESS) + goto reset_release; + ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY, + (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0); + } else if (type == PM_TAPDELAY_OUTPUT) { + ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY, + (ZYNQMP_SD_OTAPDLYENA_MASK << shift), 0); + if (ret != PM_RET_SUCCESS) + goto reset_release; + ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY, + (ZYNQMP_SD_OTAPDLYSEL_MASK << shift), + (value << shift)); + } else { + ret = PM_RET_ERROR_ARGS; + } + +reset_release: + if ((val & mask) == 0) { + (void)pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE); + } + + return ret; +} + +/** + * pm_ioctl_set_pll_frac_mode() - Ioctl function for + * setting pll mode + * @pll PLL clock id + * @mode Mode fraction/integar + * + * This function sets PLL mode + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_pll_frac_mode + (unsigned int pll, unsigned int mode) +{ + return pm_clock_set_pll_mode(pll, mode); +} + +/** + * pm_ioctl_get_pll_frac_mode() - Ioctl function for + * getting pll mode + * @pll PLL clock id + * @mode Mode fraction/integar + * + * This function return current PLL mode + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_get_pll_frac_mode + (unsigned int pll, unsigned int *mode) +{ + return pm_clock_get_pll_mode(pll, mode); +} + +/** + * pm_ioctl_set_pll_frac_data() - Ioctl function for + * setting pll fraction data + * @pll PLL clock id + * @data fraction data + * + * This function sets fraction data. + * It is valid for fraction mode only. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_pll_frac_data + (unsigned int pll, unsigned int data) +{ + enum pm_node_id pll_nid; + enum pm_ret_status status; + + /* Get PLL node ID using PLL clock ID */ + status = pm_clock_get_pll_node_id(pll, &pll_nid); + if (status != PM_RET_SUCCESS) + return status; + + return pm_pll_set_parameter(pll_nid, PM_PLL_PARAM_DATA, data); +} + +/** + * pm_ioctl_get_pll_frac_data() - Ioctl function for + * getting pll fraction data + * @pll PLL clock id + * @data fraction data + * + * This function returns fraction data value. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_get_pll_frac_data + (unsigned int pll, unsigned int *data) +{ + enum pm_node_id pll_nid; + enum pm_ret_status status; + + /* Get PLL node ID using PLL clock ID */ + status = pm_clock_get_pll_node_id(pll, &pll_nid); + if (status != PM_RET_SUCCESS) + return status; + + return pm_pll_get_parameter(pll_nid, PM_PLL_PARAM_DATA, data); +} + +/** + * pm_ioctl_write_ggs() - Ioctl function for writing + * global general storage (ggs) + * @index GGS register index + * @value Register value to be written + * + * This function writes value to GGS register. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_write_ggs(unsigned int index, + unsigned int value) +{ + if (index >= GGS_NUM_REGS) + return PM_RET_ERROR_ARGS; + + return pm_mmio_write(GGS_BASEADDR + (index << 2), + 0xFFFFFFFFU, value); +} + +/** + * pm_ioctl_read_ggs() - Ioctl function for reading + * global general storage (ggs) + * @index GGS register index + * @value Register value + * + * This function returns GGS register value. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_read_ggs(unsigned int index, + unsigned int *value) +{ + if (index >= GGS_NUM_REGS) + return PM_RET_ERROR_ARGS; + + return pm_mmio_read(GGS_BASEADDR + (index << 2), value); +} + +/** + * pm_ioctl_write_pggs() - Ioctl function for writing persistent + * global general storage (pggs) + * @index PGGS register index + * @value Register value to be written + * + * This function writes value to PGGS register. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_write_pggs(unsigned int index, + unsigned int value) +{ + if (index >= PGGS_NUM_REGS) + return PM_RET_ERROR_ARGS; + + return pm_mmio_write(PGGS_BASEADDR + (index << 2), + 0xFFFFFFFFU, value); +} + +/** + * pm_ioctl_afi() - Ioctl function for writing afi values + * + * @index AFI register index + * @value Register value to be written + * + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_afi(unsigned int index, + unsigned int value) +{ + unsigned int mask; + unsigned int regarr[] = {0xFD360000, + 0xFD360014, + 0xFD370000, + 0xFD370014, + 0xFD380000, + 0xFD380014, + 0xFD390000, + 0xFD390014, + 0xFD3a0000, + 0xFD3a0014, + 0xFD3b0000, + 0xFD3b0014, + 0xFF9b0000, + 0xFF9b0014, + 0xFD615000, + 0xFF419000, + }; + + if (index >= ARRAY_SIZE(regarr)) + return PM_RET_ERROR_ARGS; + + if (index < AFIFM6_WRCTRL) + mask = FABRIC_WIDTH; + else + mask = 0xf00; + + return pm_mmio_write(regarr[index], mask, value); +} + +/** + * pm_ioctl_read_pggs() - Ioctl function for reading persistent + * global general storage (pggs) + * @index PGGS register index + * @value Register value + * + * This function returns PGGS register value. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_read_pggs(unsigned int index, + unsigned int *value) +{ + if (index >= PGGS_NUM_REGS) + return PM_RET_ERROR_ARGS; + + return pm_mmio_read(PGGS_BASEADDR + (index << 2), value); +} + +/** + * pm_ioctl_ulpi_reset() - Ioctl function for performing ULPI reset + * + * This function peerforms the ULPI reset sequence for resetting + * the ULPI transceiver. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_ulpi_reset(void) +{ + enum pm_ret_status ret; + + ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, + ZYNQMP_ULPI_RESET_VAL_HIGH); + if (ret != PM_RET_SUCCESS) + return ret; + + /* Drive ULPI assert for atleast 1ms */ + mdelay(1); + + ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, + ZYNQMP_ULPI_RESET_VAL_LOW); + if (ret != PM_RET_SUCCESS) + return ret; + + /* Drive ULPI de-assert for atleast 1ms */ + mdelay(1); + + ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK, + ZYNQMP_ULPI_RESET_VAL_HIGH); + + return ret; +} + +/** + * pm_ioctl_set_boot_health_status() - Ioctl for setting healthy boot status + * + * This function sets healthy bit value to indicate boot health status + * to firmware. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_boot_health_status(unsigned int value) +{ + return pm_mmio_write(PMU_GLOBAL_GEN_STORAGE4, + PM_BOOT_HEALTH_STATUS_MASK, value); +} + +/** + * pm_api_ioctl() - PM IOCTL API for device control and configs + * @node_id Node ID of the device + * @ioctl_id ID of the requested IOCTL + * @arg1 Argument 1 to requested IOCTL call + * @arg2 Argument 2 to requested IOCTL call + * @value Returned output value + * + * This function calls IOCTL to firmware for device control and configuration. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value) +{ + enum pm_ret_status ret; + uint32_t payload[PAYLOAD_ARG_CNT]; + + switch (ioctl_id) { + case IOCTL_GET_RPU_OPER_MODE: + ret = pm_ioctl_get_rpu_oper_mode(value); + break; + case IOCTL_SET_RPU_OPER_MODE: + ret = pm_ioctl_set_rpu_oper_mode(arg1); + break; + case IOCTL_RPU_BOOT_ADDR_CONFIG: + ret = pm_ioctl_config_boot_addr(nid, arg1); + break; + case IOCTL_TCM_COMB_CONFIG: + ret = pm_ioctl_config_tcm_comb(arg1); + break; + case IOCTL_SET_TAPDELAY_BYPASS: + ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2); + break; + case IOCTL_SET_SGMII_MODE: + ret = pm_ioctl_set_sgmii_mode(nid, arg1); + break; + case IOCTL_SD_DLL_RESET: + ret = pm_ioctl_sd_dll_reset(nid, arg1); + break; + case IOCTL_SET_SD_TAPDELAY: + ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2); + break; + case IOCTL_SET_PLL_FRAC_MODE: + ret = pm_ioctl_set_pll_frac_mode(arg1, arg2); + break; + case IOCTL_GET_PLL_FRAC_MODE: + ret = pm_ioctl_get_pll_frac_mode(arg1, value); + break; + case IOCTL_SET_PLL_FRAC_DATA: + ret = pm_ioctl_set_pll_frac_data(arg1, arg2); + break; + case IOCTL_GET_PLL_FRAC_DATA: + ret = pm_ioctl_get_pll_frac_data(arg1, value); + break; + case IOCTL_WRITE_GGS: + ret = pm_ioctl_write_ggs(arg1, arg2); + break; + case IOCTL_READ_GGS: + ret = pm_ioctl_read_ggs(arg1, value); + break; + case IOCTL_WRITE_PGGS: + ret = pm_ioctl_write_pggs(arg1, arg2); + break; + case IOCTL_READ_PGGS: + ret = pm_ioctl_read_pggs(arg1, value); + break; + case IOCTL_ULPI_RESET: + ret = pm_ioctl_ulpi_reset(); + break; + case IOCTL_SET_BOOT_HEALTH_STATUS: + ret = pm_ioctl_set_boot_health_status(arg1); + break; + case IOCTL_AFI: + ret = pm_ioctl_afi(arg1, arg2); + break; + default: + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_IOCTL, nid, ioctl_id, arg1, arg2); + + ret = pm_ipi_send_sync(primary_proc, payload, value, 1); + break; + } + + return ret; +} + +/** + * pm_update_ioctl_bitmask() - API to get supported IOCTL ID mask + * @bit_mask Returned bit mask of supported IOCTL IDs + */ +enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask) +{ + uint8_t supported_ids[] = { + IOCTL_GET_RPU_OPER_MODE, + IOCTL_SET_RPU_OPER_MODE, + IOCTL_RPU_BOOT_ADDR_CONFIG, + IOCTL_TCM_COMB_CONFIG, + IOCTL_SET_TAPDELAY_BYPASS, + IOCTL_SET_SGMII_MODE, + IOCTL_SD_DLL_RESET, + IOCTL_SET_SD_TAPDELAY, + IOCTL_SET_PLL_FRAC_MODE, + IOCTL_GET_PLL_FRAC_MODE, + IOCTL_SET_PLL_FRAC_DATA, + IOCTL_GET_PLL_FRAC_DATA, + IOCTL_WRITE_GGS, + IOCTL_READ_GGS, + IOCTL_WRITE_PGGS, + IOCTL_READ_PGGS, + IOCTL_ULPI_RESET, + IOCTL_SET_BOOT_HEALTH_STATUS, + IOCTL_AFI, + }; + uint8_t i, ioctl_id; + int ret; + + for (i = 0U; i < ARRAY_SIZE(supported_ids); i++) { + ioctl_id = supported_ids[i]; + if (ioctl_id >= 64U) { + return PM_RET_ERROR_NOTSUPPORTED; + } + ret = check_api_dependency(ioctl_id); + if (ret == PM_RET_SUCCESS) { + bit_mask[ioctl_id / 32] |= BIT(ioctl_id % 32); + } + } + + return PM_RET_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h new file mode 100644 index 0000000..0c5f33f --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for pin control. + */ + +#ifndef PM_API_IOCTL_H +#define PM_API_IOCTL_H + +#include "pm_common.h" + +//ioctl id +enum { + IOCTL_GET_RPU_OPER_MODE = 0, + IOCTL_SET_RPU_OPER_MODE = 1, + IOCTL_RPU_BOOT_ADDR_CONFIG = 2, + IOCTL_TCM_COMB_CONFIG = 3, + IOCTL_SET_TAPDELAY_BYPASS = 4, + IOCTL_SET_SGMII_MODE = 5, + IOCTL_SD_DLL_RESET = 6, + IOCTL_SET_SD_TAPDELAY = 7, + /* Ioctl for clock driver */ + IOCTL_SET_PLL_FRAC_MODE = 8, + IOCTL_GET_PLL_FRAC_MODE = 9, + IOCTL_SET_PLL_FRAC_DATA = 10, + IOCTL_GET_PLL_FRAC_DATA = 11, + IOCTL_WRITE_GGS = 12, + IOCTL_READ_GGS = 13, + IOCTL_WRITE_PGGS = 14, + IOCTL_READ_PGGS = 15, + /* IOCTL for ULPI reset */ + IOCTL_ULPI_RESET = 16, + /* Set healthy bit value */ + IOCTL_SET_BOOT_HEALTH_STATUS = 17, + IOCTL_AFI = 18, + /* Probe counter read/write */ + IOCTL_PROBE_COUNTER_READ = 19, + IOCTL_PROBE_COUNTER_WRITE = 20, + IOCTL_OSPI_MUX_SELECT = 21, + /* IOCTL for USB power request */ + IOCTL_USB_SET_STATE = 22, + /* IOCTL to get last reset reason */ + IOCTL_GET_LAST_RESET_REASON = 23, + /* AI engine NPI ISR clear */ + IOCTL_AIE_ISR_CLEAR = 24, + /* Register SGI to ATF */ + IOCTL_REGISTER_SGI = 25, +}; + +//RPU operation mode +#define PM_RPU_MODE_LOCKSTEP 0U +#define PM_RPU_MODE_SPLIT 1U + +//RPU boot mem +#define PM_RPU_BOOTMEM_LOVEC 0U +#define PM_RPU_BOOTMEM_HIVEC 1U + +//RPU tcm mpde +#define PM_RPU_TCM_SPLIT 0U +#define PM_RPU_TCM_COMB 1U + +//tap delay signal type +#define PM_TAPDELAY_NAND_DQS_IN 0U +#define PM_TAPDELAY_NAND_DQS_OUT 1U +#define PM_TAPDELAY_QSPI 2U +#define PM_TAPDELAY_MAX 3U + +//tap delay bypass +#define PM_TAPDELAY_BYPASS_DISABLE 0U +#define PM_TAPDELAY_BYPASS_ENABLE 1U + +//sgmii mode +#define PM_SGMII_DISABLE 0U +#define PM_SGMII_ENABLE 1U + +enum tap_delay_type { + PM_TAPDELAY_INPUT, + PM_TAPDELAY_OUTPUT, +}; + +//dll reset type +#define PM_DLL_RESET_ASSERT 0U +#define PM_DLL_RESET_RELEASE 1U +#define PM_DLL_RESET_PULSE 2U + +enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value); +enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask); +#endif /* PM_API_IOCTL_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c new file mode 100644 index 0000000..9a6b497 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c @@ -0,0 +1,2677 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for pin control. + */ + +#include + +#include +#include + +#include "pm_api_pinctrl.h" +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_common.h" +#include "pm_ipi.h" + +struct pinctrl_function { + char name[FUNCTION_NAME_LEN]; + uint16_t (*groups)[]; + uint8_t regval; +}; + +/* Max groups for one pin */ +#define MAX_PIN_GROUPS U(13) + +struct zynqmp_pin_group { + uint16_t (*groups)[]; +}; + +static struct pinctrl_function pinctrl_functions[MAX_FUNCTION] = { + [PINCTRL_FUNC_CAN0] = { + .name = "can0", + .regval = 0x20, + .groups = &((uint16_t []) { + PINCTRL_GRP_CAN0_0, + PINCTRL_GRP_CAN0_1, + PINCTRL_GRP_CAN0_2, + PINCTRL_GRP_CAN0_3, + PINCTRL_GRP_CAN0_4, + PINCTRL_GRP_CAN0_5, + PINCTRL_GRP_CAN0_6, + PINCTRL_GRP_CAN0_7, + PINCTRL_GRP_CAN0_8, + PINCTRL_GRP_CAN0_9, + PINCTRL_GRP_CAN0_10, + PINCTRL_GRP_CAN0_11, + PINCTRL_GRP_CAN0_12, + PINCTRL_GRP_CAN0_13, + PINCTRL_GRP_CAN0_14, + PINCTRL_GRP_CAN0_15, + PINCTRL_GRP_CAN0_16, + PINCTRL_GRP_CAN0_17, + PINCTRL_GRP_CAN0_18, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_CAN1] = { + .name = "can1", + .regval = 0x20, + .groups = &((uint16_t []) { + PINCTRL_GRP_CAN1_0, + PINCTRL_GRP_CAN1_1, + PINCTRL_GRP_CAN1_2, + PINCTRL_GRP_CAN1_3, + PINCTRL_GRP_CAN1_4, + PINCTRL_GRP_CAN1_5, + PINCTRL_GRP_CAN1_6, + PINCTRL_GRP_CAN1_7, + PINCTRL_GRP_CAN1_8, + PINCTRL_GRP_CAN1_9, + PINCTRL_GRP_CAN1_10, + PINCTRL_GRP_CAN1_11, + PINCTRL_GRP_CAN1_12, + PINCTRL_GRP_CAN1_13, + PINCTRL_GRP_CAN1_14, + PINCTRL_GRP_CAN1_15, + PINCTRL_GRP_CAN1_16, + PINCTRL_GRP_CAN1_17, + PINCTRL_GRP_CAN1_18, + PINCTRL_GRP_CAN1_19, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_ETHERNET0] = { + .name = "ethernet0", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_ETHERNET1] = { + .name = "ethernet1", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_ETHERNET2] = { + .name = "ethernet2", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_ETHERNET3] = { + .name = "ethernet3", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_GEMTSU0] = { + .name = "gemtsu0", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_GEMTSU0_0, + PINCTRL_GRP_GEMTSU0_1, + PINCTRL_GRP_GEMTSU0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_GPIO0] = { + .name = "gpio0", + .regval = 0x00, + .groups = &((uint16_t []) { + PINCTRL_GRP_GPIO0_0, + PINCTRL_GRP_GPIO0_1, + PINCTRL_GRP_GPIO0_2, + PINCTRL_GRP_GPIO0_3, + PINCTRL_GRP_GPIO0_4, + PINCTRL_GRP_GPIO0_5, + PINCTRL_GRP_GPIO0_6, + PINCTRL_GRP_GPIO0_7, + PINCTRL_GRP_GPIO0_8, + PINCTRL_GRP_GPIO0_9, + PINCTRL_GRP_GPIO0_10, + PINCTRL_GRP_GPIO0_11, + PINCTRL_GRP_GPIO0_12, + PINCTRL_GRP_GPIO0_13, + PINCTRL_GRP_GPIO0_14, + PINCTRL_GRP_GPIO0_15, + PINCTRL_GRP_GPIO0_16, + PINCTRL_GRP_GPIO0_17, + PINCTRL_GRP_GPIO0_18, + PINCTRL_GRP_GPIO0_19, + PINCTRL_GRP_GPIO0_20, + PINCTRL_GRP_GPIO0_21, + PINCTRL_GRP_GPIO0_22, + PINCTRL_GRP_GPIO0_23, + PINCTRL_GRP_GPIO0_24, + PINCTRL_GRP_GPIO0_25, + PINCTRL_GRP_GPIO0_26, + PINCTRL_GRP_GPIO0_27, + PINCTRL_GRP_GPIO0_28, + PINCTRL_GRP_GPIO0_29, + PINCTRL_GRP_GPIO0_30, + PINCTRL_GRP_GPIO0_31, + PINCTRL_GRP_GPIO0_32, + PINCTRL_GRP_GPIO0_33, + PINCTRL_GRP_GPIO0_34, + PINCTRL_GRP_GPIO0_35, + PINCTRL_GRP_GPIO0_36, + PINCTRL_GRP_GPIO0_37, + PINCTRL_GRP_GPIO0_38, + PINCTRL_GRP_GPIO0_39, + PINCTRL_GRP_GPIO0_40, + PINCTRL_GRP_GPIO0_41, + PINCTRL_GRP_GPIO0_42, + PINCTRL_GRP_GPIO0_43, + PINCTRL_GRP_GPIO0_44, + PINCTRL_GRP_GPIO0_45, + PINCTRL_GRP_GPIO0_46, + PINCTRL_GRP_GPIO0_47, + PINCTRL_GRP_GPIO0_48, + PINCTRL_GRP_GPIO0_49, + PINCTRL_GRP_GPIO0_50, + PINCTRL_GRP_GPIO0_51, + PINCTRL_GRP_GPIO0_52, + PINCTRL_GRP_GPIO0_53, + PINCTRL_GRP_GPIO0_54, + PINCTRL_GRP_GPIO0_55, + PINCTRL_GRP_GPIO0_56, + PINCTRL_GRP_GPIO0_57, + PINCTRL_GRP_GPIO0_58, + PINCTRL_GRP_GPIO0_59, + PINCTRL_GRP_GPIO0_60, + PINCTRL_GRP_GPIO0_61, + PINCTRL_GRP_GPIO0_62, + PINCTRL_GRP_GPIO0_63, + PINCTRL_GRP_GPIO0_64, + PINCTRL_GRP_GPIO0_65, + PINCTRL_GRP_GPIO0_66, + PINCTRL_GRP_GPIO0_67, + PINCTRL_GRP_GPIO0_68, + PINCTRL_GRP_GPIO0_69, + PINCTRL_GRP_GPIO0_70, + PINCTRL_GRP_GPIO0_71, + PINCTRL_GRP_GPIO0_72, + PINCTRL_GRP_GPIO0_73, + PINCTRL_GRP_GPIO0_74, + PINCTRL_GRP_GPIO0_75, + PINCTRL_GRP_GPIO0_76, + PINCTRL_GRP_GPIO0_77, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_I2C0] = { + .name = "i2c0", + .regval = 0x40, + .groups = &((uint16_t []) { + PINCTRL_GRP_I2C0_0, + PINCTRL_GRP_I2C0_1, + PINCTRL_GRP_I2C0_2, + PINCTRL_GRP_I2C0_3, + PINCTRL_GRP_I2C0_4, + PINCTRL_GRP_I2C0_5, + PINCTRL_GRP_I2C0_6, + PINCTRL_GRP_I2C0_7, + PINCTRL_GRP_I2C0_8, + PINCTRL_GRP_I2C0_9, + PINCTRL_GRP_I2C0_10, + PINCTRL_GRP_I2C0_11, + PINCTRL_GRP_I2C0_12, + PINCTRL_GRP_I2C0_13, + PINCTRL_GRP_I2C0_14, + PINCTRL_GRP_I2C0_15, + PINCTRL_GRP_I2C0_16, + PINCTRL_GRP_I2C0_17, + PINCTRL_GRP_I2C0_18, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_I2C1] = { + .name = "i2c1", + .regval = 0x40, + .groups = &((uint16_t []) { + PINCTRL_GRP_I2C1_0, + PINCTRL_GRP_I2C1_1, + PINCTRL_GRP_I2C1_2, + PINCTRL_GRP_I2C1_3, + PINCTRL_GRP_I2C1_4, + PINCTRL_GRP_I2C1_5, + PINCTRL_GRP_I2C1_6, + PINCTRL_GRP_I2C1_7, + PINCTRL_GRP_I2C1_8, + PINCTRL_GRP_I2C1_9, + PINCTRL_GRP_I2C1_10, + PINCTRL_GRP_I2C1_11, + PINCTRL_GRP_I2C1_12, + PINCTRL_GRP_I2C1_13, + PINCTRL_GRP_I2C1_14, + PINCTRL_GRP_I2C1_15, + PINCTRL_GRP_I2C1_16, + PINCTRL_GRP_I2C1_17, + PINCTRL_GRP_I2C1_18, + PINCTRL_GRP_I2C1_19, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_MDIO0] = { + .name = "mdio0", + .regval = 0x60, + .groups = &((uint16_t []) { + PINCTRL_GRP_MDIO0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_MDIO1] = { + .name = "mdio1", + .regval = 0x80, + .groups = &((uint16_t []) { + PINCTRL_GRP_MDIO1_0, + PINCTRL_GRP_MDIO1_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_MDIO2] = { + .name = "mdio2", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_MDIO2_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_MDIO3] = { + .name = "mdio3", + .regval = 0xc0, + .groups = &((uint16_t []) { + PINCTRL_GRP_MDIO3_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_QSPI0] = { + .name = "qspi0", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_QSPI_FBCLK] = { + .name = "qspi_fbclk", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI_FBCLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_QSPI_SS] = { + .name = "qspi_ss", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI_SS, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SPI0] = { + .name = "spi0", + .regval = 0x80, + .groups = &((uint16_t []) { + PINCTRL_GRP_SPI0_0, + PINCTRL_GRP_SPI0_1, + PINCTRL_GRP_SPI0_2, + PINCTRL_GRP_SPI0_3, + PINCTRL_GRP_SPI0_4, + PINCTRL_GRP_SPI0_5, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SPI1] = { + .name = "spi1", + .regval = 0x80, + .groups = &((uint16_t []) { + PINCTRL_GRP_SPI1_0, + PINCTRL_GRP_SPI1_1, + PINCTRL_GRP_SPI1_2, + PINCTRL_GRP_SPI1_3, + PINCTRL_GRP_SPI1_4, + PINCTRL_GRP_SPI1_5, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SPI0_SS] = { + .name = "spi0_ss", + .regval = 0x80, + .groups = &((uint16_t []) { + PINCTRL_GRP_SPI0_0_SS0, + PINCTRL_GRP_SPI0_0_SS1, + PINCTRL_GRP_SPI0_0_SS2, + PINCTRL_GRP_SPI0_1_SS0, + PINCTRL_GRP_SPI0_1_SS1, + PINCTRL_GRP_SPI0_1_SS2, + PINCTRL_GRP_SPI0_2_SS0, + PINCTRL_GRP_SPI0_2_SS1, + PINCTRL_GRP_SPI0_2_SS2, + PINCTRL_GRP_SPI0_3_SS0, + PINCTRL_GRP_SPI0_3_SS1, + PINCTRL_GRP_SPI0_3_SS2, + PINCTRL_GRP_SPI0_4_SS0, + PINCTRL_GRP_SPI0_4_SS1, + PINCTRL_GRP_SPI0_4_SS2, + PINCTRL_GRP_SPI0_5_SS0, + PINCTRL_GRP_SPI0_5_SS1, + PINCTRL_GRP_SPI0_5_SS2, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SPI1_SS] = { + .name = "spi1_ss", + .regval = 0x80, + .groups = &((uint16_t []) { + PINCTRL_GRP_SPI1_0_SS0, + PINCTRL_GRP_SPI1_0_SS1, + PINCTRL_GRP_SPI1_0_SS2, + PINCTRL_GRP_SPI1_1_SS0, + PINCTRL_GRP_SPI1_1_SS1, + PINCTRL_GRP_SPI1_1_SS2, + PINCTRL_GRP_SPI1_2_SS0, + PINCTRL_GRP_SPI1_2_SS1, + PINCTRL_GRP_SPI1_2_SS2, + PINCTRL_GRP_SPI1_3_SS0, + PINCTRL_GRP_SPI1_3_SS1, + PINCTRL_GRP_SPI1_3_SS2, + PINCTRL_GRP_SPI1_4_SS0, + PINCTRL_GRP_SPI1_4_SS1, + PINCTRL_GRP_SPI1_4_SS2, + PINCTRL_GRP_SPI1_5_SS0, + PINCTRL_GRP_SPI1_5_SS1, + PINCTRL_GRP_SPI1_5_SS2, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO0] = { + .name = "sdio0", + .regval = 0x08, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO0_4BIT_0_0, + PINCTRL_GRP_SDIO0_4BIT_0_1, + PINCTRL_GRP_SDIO0_4BIT_1_0, + PINCTRL_GRP_SDIO0_4BIT_1_1, + PINCTRL_GRP_SDIO0_4BIT_2_0, + PINCTRL_GRP_SDIO0_4BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_0_0, + PINCTRL_GRP_SDIO0_1BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_2, + PINCTRL_GRP_SDIO0_1BIT_0_3, + PINCTRL_GRP_SDIO0_1BIT_0_4, + PINCTRL_GRP_SDIO0_1BIT_0_5, + PINCTRL_GRP_SDIO0_1BIT_0_6, + PINCTRL_GRP_SDIO0_1BIT_0_7, + PINCTRL_GRP_SDIO0_1BIT_1_0, + PINCTRL_GRP_SDIO0_1BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_2, + PINCTRL_GRP_SDIO0_1BIT_1_3, + PINCTRL_GRP_SDIO0_1BIT_1_4, + PINCTRL_GRP_SDIO0_1BIT_1_5, + PINCTRL_GRP_SDIO0_1BIT_1_6, + PINCTRL_GRP_SDIO0_1BIT_1_7, + PINCTRL_GRP_SDIO0_1BIT_2_0, + PINCTRL_GRP_SDIO0_1BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_2, + PINCTRL_GRP_SDIO0_1BIT_2_3, + PINCTRL_GRP_SDIO0_1BIT_2_4, + PINCTRL_GRP_SDIO0_1BIT_2_5, + PINCTRL_GRP_SDIO0_1BIT_2_6, + PINCTRL_GRP_SDIO0_1BIT_2_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO0_PC] = { + .name = "sdio0_pc", + .regval = 0x08, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO0_0_PC, + PINCTRL_GRP_SDIO0_1_PC, + PINCTRL_GRP_SDIO0_2_PC, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO0_CD] = { + .name = "sdio0_cd", + .regval = 0x08, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO0_0_CD, + PINCTRL_GRP_SDIO0_1_CD, + PINCTRL_GRP_SDIO0_2_CD, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO0_WP] = { + .name = "sdio0_wp", + .regval = 0x08, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO0_0_WP, + PINCTRL_GRP_SDIO0_1_WP, + PINCTRL_GRP_SDIO0_2_WP, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO1] = { + .name = "sdio1", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_SDIO1_4BIT_0_0, + PINCTRL_GRP_SDIO1_4BIT_0_1, + PINCTRL_GRP_SDIO1_4BIT_1_0, + PINCTRL_GRP_SDIO1_1BIT_0_0, + PINCTRL_GRP_SDIO1_1BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_2, + PINCTRL_GRP_SDIO1_1BIT_0_3, + PINCTRL_GRP_SDIO1_1BIT_0_4, + PINCTRL_GRP_SDIO1_1BIT_0_5, + PINCTRL_GRP_SDIO1_1BIT_0_6, + PINCTRL_GRP_SDIO1_1BIT_0_7, + PINCTRL_GRP_SDIO1_1BIT_1_0, + PINCTRL_GRP_SDIO1_1BIT_1_1, + PINCTRL_GRP_SDIO1_1BIT_1_2, + PINCTRL_GRP_SDIO1_1BIT_1_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO1_PC] = { + .name = "sdio1_pc", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO1_0_PC, + PINCTRL_GRP_SDIO1_1_PC, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO1_CD] = { + .name = "sdio1_cd", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO1_0_CD, + PINCTRL_GRP_SDIO1_1_CD, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO1_WP] = { + .name = "sdio1_wp", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO1_0_WP, + PINCTRL_GRP_SDIO1_1_WP, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_NAND0] = { + .name = "nand0", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_NAND0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_NAND0_CE] = { + .name = "nand0_ce", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_NAND0_0_CE, + PINCTRL_GRP_NAND0_1_CE, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_NAND0_RB] = { + .name = "nand0_rb", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_NAND0_0_RB, + PINCTRL_GRP_NAND0_1_RB, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_NAND0_DQS] = { + .name = "nand0_dqs", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_NAND0_0_DQS, + PINCTRL_GRP_NAND0_1_DQS, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC0_CLK] = { + .name = "ttc0_clk", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TTC0_0_CLK, + PINCTRL_GRP_TTC0_1_CLK, + PINCTRL_GRP_TTC0_2_CLK, + PINCTRL_GRP_TTC0_3_CLK, + PINCTRL_GRP_TTC0_4_CLK, + PINCTRL_GRP_TTC0_5_CLK, + PINCTRL_GRP_TTC0_6_CLK, + PINCTRL_GRP_TTC0_7_CLK, + PINCTRL_GRP_TTC0_8_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC0_WAV] = { + .name = "ttc0_wav", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TTC0_0_WAV, + PINCTRL_GRP_TTC0_1_WAV, + PINCTRL_GRP_TTC0_2_WAV, + PINCTRL_GRP_TTC0_3_WAV, + PINCTRL_GRP_TTC0_4_WAV, + PINCTRL_GRP_TTC0_5_WAV, + PINCTRL_GRP_TTC0_6_WAV, + PINCTRL_GRP_TTC0_7_WAV, + PINCTRL_GRP_TTC0_8_WAV, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC1_CLK] = { + .name = "ttc1_clk", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TTC1_0_CLK, + PINCTRL_GRP_TTC1_1_CLK, + PINCTRL_GRP_TTC1_2_CLK, + PINCTRL_GRP_TTC1_3_CLK, + PINCTRL_GRP_TTC1_4_CLK, + PINCTRL_GRP_TTC1_5_CLK, + PINCTRL_GRP_TTC1_6_CLK, + PINCTRL_GRP_TTC1_7_CLK, + PINCTRL_GRP_TTC1_8_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC1_WAV] = { + .name = "ttc1_wav", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TTC1_0_WAV, + PINCTRL_GRP_TTC1_1_WAV, + PINCTRL_GRP_TTC1_2_WAV, + PINCTRL_GRP_TTC1_3_WAV, + PINCTRL_GRP_TTC1_4_WAV, + PINCTRL_GRP_TTC1_5_WAV, + PINCTRL_GRP_TTC1_6_WAV, + PINCTRL_GRP_TTC1_7_WAV, + PINCTRL_GRP_TTC1_8_WAV, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC2_CLK] = { + .name = "ttc2_clk", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TTC2_0_CLK, + PINCTRL_GRP_TTC2_1_CLK, + PINCTRL_GRP_TTC2_2_CLK, + PINCTRL_GRP_TTC2_3_CLK, + PINCTRL_GRP_TTC2_4_CLK, + PINCTRL_GRP_TTC2_5_CLK, + PINCTRL_GRP_TTC2_6_CLK, + PINCTRL_GRP_TTC2_7_CLK, + PINCTRL_GRP_TTC2_8_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC2_WAV] = { + .name = "ttc2_wav", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TTC2_0_WAV, + PINCTRL_GRP_TTC2_1_WAV, + PINCTRL_GRP_TTC2_2_WAV, + PINCTRL_GRP_TTC2_3_WAV, + PINCTRL_GRP_TTC2_4_WAV, + PINCTRL_GRP_TTC2_5_WAV, + PINCTRL_GRP_TTC2_6_WAV, + PINCTRL_GRP_TTC2_7_WAV, + PINCTRL_GRP_TTC2_8_WAV, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC3_CLK] = { + .name = "ttc3_clk", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TTC3_0_CLK, + PINCTRL_GRP_TTC3_1_CLK, + PINCTRL_GRP_TTC3_2_CLK, + PINCTRL_GRP_TTC3_3_CLK, + PINCTRL_GRP_TTC3_4_CLK, + PINCTRL_GRP_TTC3_5_CLK, + PINCTRL_GRP_TTC3_6_CLK, + PINCTRL_GRP_TTC3_7_CLK, + PINCTRL_GRP_TTC3_8_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC3_WAV] = { + .name = "ttc3_wav", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TTC3_0_WAV, + PINCTRL_GRP_TTC3_1_WAV, + PINCTRL_GRP_TTC3_2_WAV, + PINCTRL_GRP_TTC3_3_WAV, + PINCTRL_GRP_TTC3_4_WAV, + PINCTRL_GRP_TTC3_5_WAV, + PINCTRL_GRP_TTC3_6_WAV, + PINCTRL_GRP_TTC3_7_WAV, + PINCTRL_GRP_TTC3_8_WAV, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_UART0] = { + .name = "uart0", + .regval = 0xc0, + .groups = &((uint16_t []) { + PINCTRL_GRP_UART0_0, + PINCTRL_GRP_UART0_1, + PINCTRL_GRP_UART0_2, + PINCTRL_GRP_UART0_3, + PINCTRL_GRP_UART0_4, + PINCTRL_GRP_UART0_5, + PINCTRL_GRP_UART0_6, + PINCTRL_GRP_UART0_7, + PINCTRL_GRP_UART0_8, + PINCTRL_GRP_UART0_9, + PINCTRL_GRP_UART0_10, + PINCTRL_GRP_UART0_11, + PINCTRL_GRP_UART0_12, + PINCTRL_GRP_UART0_13, + PINCTRL_GRP_UART0_14, + PINCTRL_GRP_UART0_15, + PINCTRL_GRP_UART0_16, + PINCTRL_GRP_UART0_17, + PINCTRL_GRP_UART0_18, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_UART1] = { + .name = "uart1", + .regval = 0xc0, + .groups = &((uint16_t []) { + PINCTRL_GRP_UART1_0, + PINCTRL_GRP_UART1_1, + PINCTRL_GRP_UART1_2, + PINCTRL_GRP_UART1_3, + PINCTRL_GRP_UART1_4, + PINCTRL_GRP_UART1_5, + PINCTRL_GRP_UART1_6, + PINCTRL_GRP_UART1_7, + PINCTRL_GRP_UART1_8, + PINCTRL_GRP_UART1_9, + PINCTRL_GRP_UART1_10, + PINCTRL_GRP_UART1_11, + PINCTRL_GRP_UART1_12, + PINCTRL_GRP_UART1_13, + PINCTRL_GRP_UART1_14, + PINCTRL_GRP_UART1_15, + PINCTRL_GRP_UART1_16, + PINCTRL_GRP_UART1_17, + PINCTRL_GRP_UART1_18, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_USB0] = { + .name = "usb0", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_USB0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_USB1] = { + .name = "usb1", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_USB1_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SWDT0_CLK] = { + .name = "swdt0_clk", + .regval = 0x60, + .groups = &((uint16_t []) { + PINCTRL_GRP_SWDT0_0_CLK, + PINCTRL_GRP_SWDT0_1_CLK, + PINCTRL_GRP_SWDT0_2_CLK, + PINCTRL_GRP_SWDT0_3_CLK, + PINCTRL_GRP_SWDT0_4_CLK, + PINCTRL_GRP_SWDT0_5_CLK, + PINCTRL_GRP_SWDT0_6_CLK, + PINCTRL_GRP_SWDT0_7_CLK, + PINCTRL_GRP_SWDT0_8_CLK, + PINCTRL_GRP_SWDT0_9_CLK, + PINCTRL_GRP_SWDT0_10_CLK, + PINCTRL_GRP_SWDT0_11_CLK, + PINCTRL_GRP_SWDT0_12_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SWDT0_RST] = { + .name = "swdt0_rst", + .regval = 0x60, + .groups = &((uint16_t []) { + PINCTRL_GRP_SWDT0_0_RST, + PINCTRL_GRP_SWDT0_1_RST, + PINCTRL_GRP_SWDT0_2_RST, + PINCTRL_GRP_SWDT0_3_RST, + PINCTRL_GRP_SWDT0_4_RST, + PINCTRL_GRP_SWDT0_5_RST, + PINCTRL_GRP_SWDT0_6_RST, + PINCTRL_GRP_SWDT0_7_RST, + PINCTRL_GRP_SWDT0_8_RST, + PINCTRL_GRP_SWDT0_9_RST, + PINCTRL_GRP_SWDT0_10_RST, + PINCTRL_GRP_SWDT0_11_RST, + PINCTRL_GRP_SWDT0_12_RST, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SWDT1_CLK] = { + .name = "swdt1_clk", + .regval = 0x60, + .groups = &((uint16_t []) { + PINCTRL_GRP_SWDT1_0_CLK, + PINCTRL_GRP_SWDT1_1_CLK, + PINCTRL_GRP_SWDT1_2_CLK, + PINCTRL_GRP_SWDT1_3_CLK, + PINCTRL_GRP_SWDT1_4_CLK, + PINCTRL_GRP_SWDT1_5_CLK, + PINCTRL_GRP_SWDT1_6_CLK, + PINCTRL_GRP_SWDT1_7_CLK, + PINCTRL_GRP_SWDT1_8_CLK, + PINCTRL_GRP_SWDT1_9_CLK, + PINCTRL_GRP_SWDT1_10_CLK, + PINCTRL_GRP_SWDT1_11_CLK, + PINCTRL_GRP_SWDT1_12_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SWDT1_RST] = { + .name = "swdt1_rst", + .regval = 0x60, + .groups = &((uint16_t []) { + PINCTRL_GRP_SWDT1_0_RST, + PINCTRL_GRP_SWDT1_1_RST, + PINCTRL_GRP_SWDT1_2_RST, + PINCTRL_GRP_SWDT1_3_RST, + PINCTRL_GRP_SWDT1_4_RST, + PINCTRL_GRP_SWDT1_5_RST, + PINCTRL_GRP_SWDT1_6_RST, + PINCTRL_GRP_SWDT1_7_RST, + PINCTRL_GRP_SWDT1_8_RST, + PINCTRL_GRP_SWDT1_9_RST, + PINCTRL_GRP_SWDT1_10_RST, + PINCTRL_GRP_SWDT1_11_RST, + PINCTRL_GRP_SWDT1_12_RST, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_PMU0] = { + .name = "pmu0", + .regval = 0x08, + .groups = &((uint16_t []) { + PINCTRL_GRP_PMU0_0, + PINCTRL_GRP_PMU0_1, + PINCTRL_GRP_PMU0_2, + PINCTRL_GRP_PMU0_3, + PINCTRL_GRP_PMU0_4, + PINCTRL_GRP_PMU0_5, + PINCTRL_GRP_PMU0_6, + PINCTRL_GRP_PMU0_7, + PINCTRL_GRP_PMU0_8, + PINCTRL_GRP_PMU0_9, + PINCTRL_GRP_PMU0_10, + PINCTRL_GRP_PMU0_11, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_PCIE0] = { + .name = "pcie0", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_PCIE0_0, + PINCTRL_GRP_PCIE0_1, + PINCTRL_GRP_PCIE0_2, + PINCTRL_GRP_PCIE0_3, + PINCTRL_GRP_PCIE0_4, + PINCTRL_GRP_PCIE0_5, + PINCTRL_GRP_PCIE0_6, + PINCTRL_GRP_PCIE0_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_CSU0] = { + .name = "csu0", + .regval = 0x18, + .groups = &((uint16_t []) { + PINCTRL_GRP_CSU0_0, + PINCTRL_GRP_CSU0_1, + PINCTRL_GRP_CSU0_2, + PINCTRL_GRP_CSU0_3, + PINCTRL_GRP_CSU0_4, + PINCTRL_GRP_CSU0_5, + PINCTRL_GRP_CSU0_6, + PINCTRL_GRP_CSU0_7, + PINCTRL_GRP_CSU0_8, + PINCTRL_GRP_CSU0_9, + PINCTRL_GRP_CSU0_10, + PINCTRL_GRP_CSU0_11, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_DPAUX0] = { + .name = "dpaux0", + .regval = 0x18, + .groups = &((uint16_t []) { + PINCTRL_GRP_DPAUX0_0, + PINCTRL_GRP_DPAUX0_1, + PINCTRL_GRP_DPAUX0_2, + PINCTRL_GRP_DPAUX0_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_PJTAG0] = { + .name = "pjtag0", + .regval = 0x60, + .groups = &((uint16_t []) { + PINCTRL_GRP_PJTAG0_0, + PINCTRL_GRP_PJTAG0_1, + PINCTRL_GRP_PJTAG0_2, + PINCTRL_GRP_PJTAG0_3, + PINCTRL_GRP_PJTAG0_4, + PINCTRL_GRP_PJTAG0_5, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TRACE0] = { + .name = "trace0", + .regval = 0xe0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TRACE0_0, + PINCTRL_GRP_TRACE0_1, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TRACE0_CLK] = { + .name = "trace0_clk", + .regval = 0xe0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TRACE0_0_CLK, + PINCTRL_GRP_TRACE0_1_CLK, + PINCTRL_GRP_TRACE0_2_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TESTSCAN0] = { + .name = "testscan0", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_TESTSCAN0_0, + END_OF_GROUPS, + }), + }, +}; + +static struct zynqmp_pin_group zynqmp_pin_groups[MAX_PIN] = { + [PINCTRL_PIN_0] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_0, + PINCTRL_GRP_CAN1_0, + PINCTRL_GRP_I2C1_0, + PINCTRL_GRP_PJTAG0_0, + PINCTRL_GRP_SPI0_0, + PINCTRL_GRP_TTC3_0_CLK, + PINCTRL_GRP_UART1_0, + PINCTRL_GRP_TRACE0_0_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_1] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_1, + PINCTRL_GRP_CAN1_0, + PINCTRL_GRP_I2C1_0, + PINCTRL_GRP_PJTAG0_0, + PINCTRL_GRP_SPI0_0_SS2, + PINCTRL_GRP_TTC3_0_WAV, + PINCTRL_GRP_UART1_0, + PINCTRL_GRP_TRACE0_0_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_2] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_2, + PINCTRL_GRP_CAN0_0, + PINCTRL_GRP_I2C0_0, + PINCTRL_GRP_PJTAG0_0, + PINCTRL_GRP_SPI0_0_SS1, + PINCTRL_GRP_TTC2_0_CLK, + PINCTRL_GRP_UART0_0, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_3] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_3, + PINCTRL_GRP_CAN0_0, + PINCTRL_GRP_I2C0_0, + PINCTRL_GRP_PJTAG0_0, + PINCTRL_GRP_SPI0_0_SS0, + PINCTRL_GRP_TTC2_0_WAV, + PINCTRL_GRP_UART0_0, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_4] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_4, + PINCTRL_GRP_CAN1_1, + PINCTRL_GRP_I2C1_1, + PINCTRL_GRP_SWDT1_0_CLK, + PINCTRL_GRP_SPI0_0, + PINCTRL_GRP_TTC1_0_CLK, + PINCTRL_GRP_UART1_1, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_5] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI_SS, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_5, + PINCTRL_GRP_CAN1_1, + PINCTRL_GRP_I2C1_1, + PINCTRL_GRP_SWDT1_0_RST, + PINCTRL_GRP_SPI0_0, + PINCTRL_GRP_TTC1_0_WAV, + PINCTRL_GRP_UART1_1, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_6] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI_FBCLK, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_6, + PINCTRL_GRP_CAN0_1, + PINCTRL_GRP_I2C0_1, + PINCTRL_GRP_SWDT0_0_CLK, + PINCTRL_GRP_SPI1_0, + PINCTRL_GRP_TTC0_0_CLK, + PINCTRL_GRP_UART0_1, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_7] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI_SS, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_7, + PINCTRL_GRP_CAN0_1, + PINCTRL_GRP_I2C0_1, + PINCTRL_GRP_SWDT0_0_RST, + PINCTRL_GRP_SPI1_0_SS2, + PINCTRL_GRP_TTC0_0_WAV, + PINCTRL_GRP_UART0_1, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_8] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_8, + PINCTRL_GRP_CAN1_2, + PINCTRL_GRP_I2C1_2, + PINCTRL_GRP_SWDT1_1_CLK, + PINCTRL_GRP_SPI1_0_SS1, + PINCTRL_GRP_TTC3_1_CLK, + PINCTRL_GRP_UART1_2, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_9] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_NAND0_0_CE, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_9, + PINCTRL_GRP_CAN1_2, + PINCTRL_GRP_I2C1_2, + PINCTRL_GRP_SWDT1_1_RST, + PINCTRL_GRP_SPI1_0_SS0, + PINCTRL_GRP_TTC3_1_WAV, + PINCTRL_GRP_UART1_2, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_10] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_NAND0_0_RB, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_10, + PINCTRL_GRP_CAN0_2, + PINCTRL_GRP_I2C0_2, + PINCTRL_GRP_SWDT0_1_CLK, + PINCTRL_GRP_SPI1_0, + PINCTRL_GRP_TTC2_1_CLK, + PINCTRL_GRP_UART0_2, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_11] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_NAND0_0_RB, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_11, + PINCTRL_GRP_CAN0_2, + PINCTRL_GRP_I2C0_2, + PINCTRL_GRP_SWDT0_1_RST, + PINCTRL_GRP_SPI1_0, + PINCTRL_GRP_TTC2_1_WAV, + PINCTRL_GRP_UART0_2, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_12] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_NAND0_0_DQS, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_12, + PINCTRL_GRP_CAN1_3, + PINCTRL_GRP_I2C1_3, + PINCTRL_GRP_PJTAG0_1, + PINCTRL_GRP_SPI0_1, + PINCTRL_GRP_TTC1_1_CLK, + PINCTRL_GRP_UART1_3, + PINCTRL_GRP_TRACE0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_13] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_13, + PINCTRL_GRP_CAN1_3, + PINCTRL_GRP_I2C1_3, + PINCTRL_GRP_PJTAG0_1, + PINCTRL_GRP_SPI0_1_SS2, + PINCTRL_GRP_TTC1_1_WAV, + PINCTRL_GRP_UART1_3, + PINCTRL_GRP_TRACE0_0, + PINCTRL_GRP_SDIO0_4BIT_0_0, + PINCTRL_GRP_SDIO0_1BIT_0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_14] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_14, + PINCTRL_GRP_CAN0_3, + PINCTRL_GRP_I2C0_3, + PINCTRL_GRP_PJTAG0_1, + PINCTRL_GRP_SPI0_1_SS1, + PINCTRL_GRP_TTC0_1_CLK, + PINCTRL_GRP_UART0_3, + PINCTRL_GRP_TRACE0_0, + PINCTRL_GRP_SDIO0_4BIT_0_0, + PINCTRL_GRP_SDIO0_1BIT_0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_15] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_15, + PINCTRL_GRP_CAN0_3, + PINCTRL_GRP_I2C0_3, + PINCTRL_GRP_PJTAG0_1, + PINCTRL_GRP_SPI0_1_SS0, + PINCTRL_GRP_TTC0_1_WAV, + PINCTRL_GRP_UART0_3, + PINCTRL_GRP_TRACE0_0, + PINCTRL_GRP_SDIO0_4BIT_0_0, + PINCTRL_GRP_SDIO0_1BIT_0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_16] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_16, + PINCTRL_GRP_CAN1_4, + PINCTRL_GRP_I2C1_4, + PINCTRL_GRP_SWDT1_2_CLK, + PINCTRL_GRP_SPI0_1, + PINCTRL_GRP_TTC3_2_CLK, + PINCTRL_GRP_UART1_4, + PINCTRL_GRP_TRACE0_0, + PINCTRL_GRP_SDIO0_4BIT_0_0, + PINCTRL_GRP_SDIO0_1BIT_0_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_17] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_17, + PINCTRL_GRP_CAN1_4, + PINCTRL_GRP_I2C1_4, + PINCTRL_GRP_SWDT1_2_RST, + PINCTRL_GRP_SPI0_1, + PINCTRL_GRP_TTC3_2_WAV, + PINCTRL_GRP_UART1_4, + PINCTRL_GRP_TRACE0_0, + PINCTRL_GRP_SDIO0_4BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_4, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_18] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_0, + PINCTRL_GRP_GPIO0_18, + PINCTRL_GRP_CAN0_4, + PINCTRL_GRP_I2C0_4, + PINCTRL_GRP_SWDT0_2_CLK, + PINCTRL_GRP_SPI1_1, + PINCTRL_GRP_TTC2_2_CLK, + PINCTRL_GRP_UART0_4, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_5, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_19] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_1, + PINCTRL_GRP_GPIO0_19, + PINCTRL_GRP_CAN0_4, + PINCTRL_GRP_I2C0_4, + PINCTRL_GRP_SWDT0_2_RST, + PINCTRL_GRP_SPI1_1_SS2, + PINCTRL_GRP_TTC2_2_WAV, + PINCTRL_GRP_UART0_4, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_6, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_20] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_2, + PINCTRL_GRP_GPIO0_20, + PINCTRL_GRP_CAN1_5, + PINCTRL_GRP_I2C1_5, + PINCTRL_GRP_SWDT1_3_CLK, + PINCTRL_GRP_SPI1_1_SS1, + PINCTRL_GRP_TTC1_2_CLK, + PINCTRL_GRP_UART1_5, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_21] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_3, + PINCTRL_GRP_GPIO0_21, + PINCTRL_GRP_CAN1_5, + PINCTRL_GRP_I2C1_5, + PINCTRL_GRP_SWDT1_3_RST, + PINCTRL_GRP_SPI1_1_SS0, + PINCTRL_GRP_TTC1_2_WAV, + PINCTRL_GRP_UART1_5, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_0_0, + PINCTRL_GRP_SDIO0_4BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_0, + PINCTRL_GRP_SDIO0_1BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_2, + PINCTRL_GRP_SDIO0_1BIT_0_3, + PINCTRL_GRP_SDIO0_1BIT_0_4, + PINCTRL_GRP_SDIO0_1BIT_0_5, + PINCTRL_GRP_SDIO0_1BIT_0_6, + PINCTRL_GRP_SDIO0_1BIT_0_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_22] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_4, + PINCTRL_GRP_GPIO0_22, + PINCTRL_GRP_CAN0_5, + PINCTRL_GRP_I2C0_5, + PINCTRL_GRP_SWDT0_3_CLK, + PINCTRL_GRP_SPI1_1, + PINCTRL_GRP_TTC0_2_CLK, + PINCTRL_GRP_UART0_5, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_0_0, + PINCTRL_GRP_SDIO0_4BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_0, + PINCTRL_GRP_SDIO0_1BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_2, + PINCTRL_GRP_SDIO0_1BIT_0_3, + PINCTRL_GRP_SDIO0_1BIT_0_4, + PINCTRL_GRP_SDIO0_1BIT_0_5, + PINCTRL_GRP_SDIO0_1BIT_0_6, + PINCTRL_GRP_SDIO0_1BIT_0_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_23] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0_PC, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_5, + PINCTRL_GRP_GPIO0_23, + PINCTRL_GRP_CAN0_5, + PINCTRL_GRP_I2C0_5, + PINCTRL_GRP_SWDT0_3_RST, + PINCTRL_GRP_SPI1_1, + PINCTRL_GRP_TTC0_2_WAV, + PINCTRL_GRP_UART0_5, + PINCTRL_GRP_RESERVED, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_24] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0_CD, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_6, + PINCTRL_GRP_GPIO0_24, + PINCTRL_GRP_CAN1_6, + PINCTRL_GRP_I2C1_6, + PINCTRL_GRP_SWDT1_4_CLK, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TTC3_3_CLK, + PINCTRL_GRP_UART1_6, + PINCTRL_GRP_RESERVED, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_25] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_SDIO0_0_WP, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_7, + PINCTRL_GRP_GPIO0_25, + PINCTRL_GRP_CAN1_6, + PINCTRL_GRP_I2C1_6, + PINCTRL_GRP_SWDT1_4_RST, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_TTC3_3_WAV, + PINCTRL_GRP_UART1_6, + PINCTRL_GRP_RESERVED, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_26] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_GEMTSU0_0, + PINCTRL_GRP_NAND0_1_CE, + PINCTRL_GRP_PMU0_0, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_8, + PINCTRL_GRP_GPIO0_26, + PINCTRL_GRP_CAN0_6, + PINCTRL_GRP_I2C0_6, + PINCTRL_GRP_PJTAG0_2, + PINCTRL_GRP_SPI0_2, + PINCTRL_GRP_TTC2_3_CLK, + PINCTRL_GRP_UART0_6, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_27] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_NAND0_1_RB, + PINCTRL_GRP_PMU0_1, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_DPAUX0_0, + PINCTRL_GRP_GPIO0_27, + PINCTRL_GRP_CAN0_6, + PINCTRL_GRP_I2C0_6, + PINCTRL_GRP_PJTAG0_2, + PINCTRL_GRP_SPI0_2_SS2, + PINCTRL_GRP_TTC2_3_WAV, + PINCTRL_GRP_UART0_6, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_28] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_NAND0_1_RB, + PINCTRL_GRP_PMU0_2, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_DPAUX0_0, + PINCTRL_GRP_GPIO0_28, + PINCTRL_GRP_CAN1_7, + PINCTRL_GRP_I2C1_7, + PINCTRL_GRP_PJTAG0_2, + PINCTRL_GRP_SPI0_2_SS1, + PINCTRL_GRP_TTC1_3_CLK, + PINCTRL_GRP_UART1_7, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_29] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_PCIE0_0, + PINCTRL_GRP_PMU0_3, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_DPAUX0_1, + PINCTRL_GRP_GPIO0_29, + PINCTRL_GRP_CAN1_7, + PINCTRL_GRP_I2C1_7, + PINCTRL_GRP_PJTAG0_2, + PINCTRL_GRP_SPI0_2_SS0, + PINCTRL_GRP_TTC1_3_WAV, + PINCTRL_GRP_UART1_7, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_30] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_PCIE0_1, + PINCTRL_GRP_PMU0_4, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_DPAUX0_1, + PINCTRL_GRP_GPIO0_30, + PINCTRL_GRP_CAN0_7, + PINCTRL_GRP_I2C0_7, + PINCTRL_GRP_SWDT0_4_CLK, + PINCTRL_GRP_SPI0_2, + PINCTRL_GRP_TTC0_3_CLK, + PINCTRL_GRP_UART0_7, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_31] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_PCIE0_2, + PINCTRL_GRP_PMU0_5, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_9, + PINCTRL_GRP_GPIO0_31, + PINCTRL_GRP_CAN0_7, + PINCTRL_GRP_I2C0_7, + PINCTRL_GRP_SWDT0_4_RST, + PINCTRL_GRP_SPI0_2, + PINCTRL_GRP_TTC0_3_WAV, + PINCTRL_GRP_UART0_7, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_32] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_NAND0_1_DQS, + PINCTRL_GRP_PMU0_6, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_10, + PINCTRL_GRP_GPIO0_32, + PINCTRL_GRP_CAN1_8, + PINCTRL_GRP_I2C1_8, + PINCTRL_GRP_SWDT1_5_CLK, + PINCTRL_GRP_SPI1_2, + PINCTRL_GRP_TTC3_4_CLK, + PINCTRL_GRP_UART1_8, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_33] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_PCIE0_3, + PINCTRL_GRP_PMU0_7, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_CSU0_11, + PINCTRL_GRP_GPIO0_33, + PINCTRL_GRP_CAN1_8, + PINCTRL_GRP_I2C1_8, + PINCTRL_GRP_SWDT1_5_RST, + PINCTRL_GRP_SPI1_2_SS2, + PINCTRL_GRP_TTC3_4_WAV, + PINCTRL_GRP_UART1_8, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_34] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_PCIE0_4, + PINCTRL_GRP_PMU0_8, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_DPAUX0_2, + PINCTRL_GRP_GPIO0_34, + PINCTRL_GRP_CAN0_8, + PINCTRL_GRP_I2C0_8, + PINCTRL_GRP_SWDT0_5_CLK, + PINCTRL_GRP_SPI1_2_SS1, + PINCTRL_GRP_TTC2_4_CLK, + PINCTRL_GRP_UART0_8, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_35] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_PCIE0_5, + PINCTRL_GRP_PMU0_9, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_DPAUX0_2, + PINCTRL_GRP_GPIO0_35, + PINCTRL_GRP_CAN0_8, + PINCTRL_GRP_I2C0_8, + PINCTRL_GRP_SWDT0_5_RST, + PINCTRL_GRP_SPI1_2_SS0, + PINCTRL_GRP_TTC2_4_WAV, + PINCTRL_GRP_UART0_8, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_36] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_PCIE0_6, + PINCTRL_GRP_PMU0_10, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_DPAUX0_3, + PINCTRL_GRP_GPIO0_36, + PINCTRL_GRP_CAN1_9, + PINCTRL_GRP_I2C1_9, + PINCTRL_GRP_SWDT1_6_CLK, + PINCTRL_GRP_SPI1_2, + PINCTRL_GRP_TTC1_4_CLK, + PINCTRL_GRP_UART1_9, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_37] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_PCIE0_7, + PINCTRL_GRP_PMU0_11, + PINCTRL_GRP_TESTSCAN0_0, + PINCTRL_GRP_DPAUX0_3, + PINCTRL_GRP_GPIO0_37, + PINCTRL_GRP_CAN1_9, + PINCTRL_GRP_I2C1_9, + PINCTRL_GRP_SWDT1_6_RST, + PINCTRL_GRP_SPI1_2, + PINCTRL_GRP_TTC1_4_WAV, + PINCTRL_GRP_UART1_9, + PINCTRL_GRP_TRACE0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_38] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_38, + PINCTRL_GRP_CAN0_9, + PINCTRL_GRP_I2C0_9, + PINCTRL_GRP_PJTAG0_3, + PINCTRL_GRP_SPI0_3, + PINCTRL_GRP_TTC0_4_CLK, + PINCTRL_GRP_UART0_9, + PINCTRL_GRP_TRACE0_1_CLK, + PINCTRL_GRP_SDIO0_4BIT_1_0, + PINCTRL_GRP_SDIO0_4BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_0, + PINCTRL_GRP_SDIO0_1BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_2, + PINCTRL_GRP_SDIO0_1BIT_1_3, + PINCTRL_GRP_SDIO0_1BIT_1_4, + PINCTRL_GRP_SDIO0_1BIT_1_5, + PINCTRL_GRP_SDIO0_1BIT_1_6, + PINCTRL_GRP_SDIO0_1BIT_1_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_39] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1_CD, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_39, + PINCTRL_GRP_CAN0_9, + PINCTRL_GRP_I2C0_9, + PINCTRL_GRP_PJTAG0_3, + PINCTRL_GRP_SPI0_3_SS2, + PINCTRL_GRP_TTC0_4_WAV, + PINCTRL_GRP_UART0_9, + PINCTRL_GRP_TRACE0_1_CLK, + PINCTRL_GRP_SDIO1_4BIT_0_0, + PINCTRL_GRP_SDIO1_1BIT_0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_40] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_40, + PINCTRL_GRP_CAN1_10, + PINCTRL_GRP_I2C1_10, + PINCTRL_GRP_PJTAG0_3, + PINCTRL_GRP_SPI0_3_SS1, + PINCTRL_GRP_TTC3_5_CLK, + PINCTRL_GRP_UART1_10, + PINCTRL_GRP_TRACE0_1, + PINCTRL_GRP_SDIO0_4BIT_1_0, + PINCTRL_GRP_SDIO0_4BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_0, + PINCTRL_GRP_SDIO0_1BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_2, + PINCTRL_GRP_SDIO0_1BIT_1_3, + PINCTRL_GRP_SDIO0_1BIT_1_4, + PINCTRL_GRP_SDIO0_1BIT_1_5, + PINCTRL_GRP_SDIO0_1BIT_1_6, + PINCTRL_GRP_SDIO0_1BIT_1_7, + PINCTRL_GRP_SDIO1_4BIT_0_0, + PINCTRL_GRP_SDIO1_1BIT_0_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_41] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_41, + PINCTRL_GRP_CAN1_10, + PINCTRL_GRP_I2C1_10, + PINCTRL_GRP_PJTAG0_3, + PINCTRL_GRP_SPI0_3_SS0, + PINCTRL_GRP_TTC3_5_WAV, + PINCTRL_GRP_UART1_10, + PINCTRL_GRP_TRACE0_1, + PINCTRL_GRP_SDIO0_4BIT_1_0, + PINCTRL_GRP_SDIO0_1BIT_1_0, + PINCTRL_GRP_SDIO1_4BIT_0_0, + PINCTRL_GRP_SDIO1_1BIT_0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_42] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_42, + PINCTRL_GRP_CAN0_10, + PINCTRL_GRP_I2C0_10, + PINCTRL_GRP_SWDT0_6_CLK, + PINCTRL_GRP_SPI0_3, + PINCTRL_GRP_TTC2_5_CLK, + PINCTRL_GRP_UART0_10, + PINCTRL_GRP_TRACE0_1, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO0_4BIT_1_0, + PINCTRL_GRP_SDIO0_1BIT_1_1, + PINCTRL_GRP_SDIO1_4BIT_0_0, + PINCTRL_GRP_SDIO1_1BIT_0_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_43] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0_PC, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_43, + PINCTRL_GRP_CAN0_10, + PINCTRL_GRP_I2C0_10, + PINCTRL_GRP_SWDT0_6_RST, + PINCTRL_GRP_SPI0_3, + PINCTRL_GRP_TTC2_5_WAV, + PINCTRL_GRP_UART0_10, + PINCTRL_GRP_TRACE0_1, + PINCTRL_GRP_SDIO0_4BIT_1_0, + PINCTRL_GRP_SDIO0_1BIT_1_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_44] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0_WP, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_44, + PINCTRL_GRP_CAN1_11, + PINCTRL_GRP_I2C1_11, + PINCTRL_GRP_SWDT1_7_CLK, + PINCTRL_GRP_SPI1_3, + PINCTRL_GRP_TTC1_5_CLK, + PINCTRL_GRP_UART1_11, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_1_0, + PINCTRL_GRP_SDIO0_1BIT_1_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_45] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0_CD, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_45, + PINCTRL_GRP_CAN1_11, + PINCTRL_GRP_I2C1_11, + PINCTRL_GRP_SWDT1_7_RST, + PINCTRL_GRP_SPI1_3_SS2, + PINCTRL_GRP_TTC1_5_WAV, + PINCTRL_GRP_UART1_11, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_4, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_46] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_46, + PINCTRL_GRP_CAN0_11, + PINCTRL_GRP_I2C0_11, + PINCTRL_GRP_SWDT0_7_CLK, + PINCTRL_GRP_SPI1_3_SS1, + PINCTRL_GRP_TTC0_5_CLK, + PINCTRL_GRP_UART0_11, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_5, + PINCTRL_GRP_SDIO1_4BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_4, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_47] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_47, + PINCTRL_GRP_CAN0_11, + PINCTRL_GRP_I2C0_11, + PINCTRL_GRP_SWDT0_7_RST, + PINCTRL_GRP_SPI1_3_SS0, + PINCTRL_GRP_TTC0_5_WAV, + PINCTRL_GRP_UART0_11, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_6, + PINCTRL_GRP_SDIO1_4BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_5, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_48] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_48, + PINCTRL_GRP_CAN1_12, + PINCTRL_GRP_I2C1_12, + PINCTRL_GRP_SWDT1_8_CLK, + PINCTRL_GRP_SPI1_3, + PINCTRL_GRP_TTC3_6_CLK, + PINCTRL_GRP_UART1_12, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_7, + PINCTRL_GRP_SDIO1_4BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_6, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_49] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1_PC, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_49, + PINCTRL_GRP_CAN1_12, + PINCTRL_GRP_I2C1_12, + PINCTRL_GRP_SWDT1_8_RST, + PINCTRL_GRP_SPI1_3, + PINCTRL_GRP_TTC3_6_WAV, + PINCTRL_GRP_UART1_12, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO1_4BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_50] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_GEMTSU0_1, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_1_WP, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_50, + PINCTRL_GRP_CAN0_12, + PINCTRL_GRP_I2C0_12, + PINCTRL_GRP_SWDT0_8_CLK, + PINCTRL_GRP_MDIO1_0, + PINCTRL_GRP_TTC2_6_CLK, + PINCTRL_GRP_UART0_12, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO1_4BIT_0_0, + PINCTRL_GRP_SDIO1_4BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_0, + PINCTRL_GRP_SDIO1_1BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_2, + PINCTRL_GRP_SDIO1_1BIT_0_3, + PINCTRL_GRP_SDIO1_1BIT_0_4, + PINCTRL_GRP_SDIO1_1BIT_0_5, + PINCTRL_GRP_SDIO1_1BIT_0_6, + PINCTRL_GRP_SDIO1_1BIT_0_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_51] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_GEMTSU0_2, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_51, + PINCTRL_GRP_CAN0_12, + PINCTRL_GRP_I2C0_12, + PINCTRL_GRP_SWDT0_8_RST, + PINCTRL_GRP_MDIO1_0, + PINCTRL_GRP_TTC2_6_WAV, + PINCTRL_GRP_UART0_12, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO1_4BIT_0_0, + PINCTRL_GRP_SDIO1_4BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_0, + PINCTRL_GRP_SDIO1_1BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_2, + PINCTRL_GRP_SDIO1_1BIT_0_3, + PINCTRL_GRP_SDIO1_1BIT_0_4, + PINCTRL_GRP_SDIO1_1BIT_0_5, + PINCTRL_GRP_SDIO1_1BIT_0_6, + PINCTRL_GRP_SDIO1_1BIT_0_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_52] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_52, + PINCTRL_GRP_CAN1_13, + PINCTRL_GRP_I2C1_13, + PINCTRL_GRP_PJTAG0_4, + PINCTRL_GRP_SPI0_4, + PINCTRL_GRP_TTC1_6_CLK, + PINCTRL_GRP_UART1_13, + PINCTRL_GRP_TRACE0_2_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_53] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_53, + PINCTRL_GRP_CAN1_13, + PINCTRL_GRP_I2C1_13, + PINCTRL_GRP_PJTAG0_4, + PINCTRL_GRP_SPI0_4_SS2, + PINCTRL_GRP_TTC1_6_WAV, + PINCTRL_GRP_UART1_13, + PINCTRL_GRP_TRACE0_2_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_54] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_54, + PINCTRL_GRP_CAN0_13, + PINCTRL_GRP_I2C0_13, + PINCTRL_GRP_PJTAG0_4, + PINCTRL_GRP_SPI0_4_SS1, + PINCTRL_GRP_TTC0_6_CLK, + PINCTRL_GRP_UART0_13, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_55] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_55, + PINCTRL_GRP_CAN0_13, + PINCTRL_GRP_I2C0_13, + PINCTRL_GRP_PJTAG0_4, + PINCTRL_GRP_SPI0_4_SS0, + PINCTRL_GRP_TTC0_6_WAV, + PINCTRL_GRP_UART0_13, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_56] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_56, + PINCTRL_GRP_CAN1_14, + PINCTRL_GRP_I2C1_14, + PINCTRL_GRP_SWDT1_9_CLK, + PINCTRL_GRP_SPI0_4, + PINCTRL_GRP_TTC3_7_CLK, + PINCTRL_GRP_UART1_14, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_57] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_57, + PINCTRL_GRP_CAN1_14, + PINCTRL_GRP_I2C1_14, + PINCTRL_GRP_SWDT1_9_RST, + PINCTRL_GRP_SPI0_4, + PINCTRL_GRP_TTC3_7_WAV, + PINCTRL_GRP_UART1_14, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_58] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_58, + PINCTRL_GRP_CAN0_14, + PINCTRL_GRP_I2C0_14, + PINCTRL_GRP_PJTAG0_5, + PINCTRL_GRP_SPI1_4, + PINCTRL_GRP_TTC2_7_CLK, + PINCTRL_GRP_UART0_14, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_59] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_59, + PINCTRL_GRP_CAN0_14, + PINCTRL_GRP_I2C0_14, + PINCTRL_GRP_PJTAG0_5, + PINCTRL_GRP_SPI1_4_SS2, + PINCTRL_GRP_TTC2_7_WAV, + PINCTRL_GRP_UART0_14, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_60] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_60, + PINCTRL_GRP_CAN1_15, + PINCTRL_GRP_I2C1_15, + PINCTRL_GRP_PJTAG0_5, + PINCTRL_GRP_SPI1_4_SS1, + PINCTRL_GRP_TTC1_7_CLK, + PINCTRL_GRP_UART1_15, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_61] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_61, + PINCTRL_GRP_CAN1_15, + PINCTRL_GRP_I2C1_15, + PINCTRL_GRP_PJTAG0_5, + PINCTRL_GRP_SPI1_4_SS0, + PINCTRL_GRP_TTC1_7_WAV, + PINCTRL_GRP_UART1_15, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_62] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_62, + PINCTRL_GRP_CAN0_15, + PINCTRL_GRP_I2C0_15, + PINCTRL_GRP_SWDT0_9_CLK, + PINCTRL_GRP_SPI1_4, + PINCTRL_GRP_TTC0_7_CLK, + PINCTRL_GRP_UART0_15, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_63] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_63, + PINCTRL_GRP_CAN0_15, + PINCTRL_GRP_I2C0_15, + PINCTRL_GRP_SWDT0_9_RST, + PINCTRL_GRP_SPI1_4, + PINCTRL_GRP_TTC0_7_WAV, + PINCTRL_GRP_UART0_15, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_64] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_64, + PINCTRL_GRP_CAN1_16, + PINCTRL_GRP_I2C1_16, + PINCTRL_GRP_SWDT1_10_CLK, + PINCTRL_GRP_SPI0_5, + PINCTRL_GRP_TTC3_8_CLK, + PINCTRL_GRP_UART1_16, + PINCTRL_GRP_TRACE0_2, + PINCTRL_GRP_SDIO0_4BIT_2_0, + PINCTRL_GRP_SDIO0_4BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_0, + PINCTRL_GRP_SDIO0_1BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_2, + PINCTRL_GRP_SDIO0_1BIT_2_3, + PINCTRL_GRP_SDIO0_1BIT_2_4, + PINCTRL_GRP_SDIO0_1BIT_2_5, + PINCTRL_GRP_SDIO0_1BIT_2_6, + PINCTRL_GRP_SDIO0_1BIT_2_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_65] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2_CD, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_65, + PINCTRL_GRP_CAN1_16, + PINCTRL_GRP_I2C1_16, + PINCTRL_GRP_SWDT1_10_RST, + PINCTRL_GRP_SPI0_5_SS2, + PINCTRL_GRP_TTC3_8_WAV, + PINCTRL_GRP_UART1_16, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_66] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_66, + PINCTRL_GRP_CAN0_16, + PINCTRL_GRP_I2C0_16, + PINCTRL_GRP_SWDT0_10_CLK, + PINCTRL_GRP_SPI0_5_SS1, + PINCTRL_GRP_TTC2_8_CLK, + PINCTRL_GRP_UART0_16, + PINCTRL_GRP_TRACE0_2, + PINCTRL_GRP_SDIO0_4BIT_2_0, + PINCTRL_GRP_SDIO0_4BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_0, + PINCTRL_GRP_SDIO0_1BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_2, + PINCTRL_GRP_SDIO0_1BIT_2_3, + PINCTRL_GRP_SDIO0_1BIT_2_4, + PINCTRL_GRP_SDIO0_1BIT_2_5, + PINCTRL_GRP_SDIO0_1BIT_2_6, + PINCTRL_GRP_SDIO0_1BIT_2_7, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_67] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_67, + PINCTRL_GRP_CAN0_16, + PINCTRL_GRP_I2C0_16, + PINCTRL_GRP_SWDT0_10_RST, + PINCTRL_GRP_SPI0_5_SS0, + PINCTRL_GRP_TTC2_8_WAV, + PINCTRL_GRP_UART0_16, + PINCTRL_GRP_TRACE0_2, + PINCTRL_GRP_SDIO0_4BIT_2_0, + PINCTRL_GRP_SDIO0_1BIT_2_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_68] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_68, + PINCTRL_GRP_CAN1_17, + PINCTRL_GRP_I2C1_17, + PINCTRL_GRP_SWDT1_11_CLK, + PINCTRL_GRP_SPI0_5, + PINCTRL_GRP_TTC1_8_CLK, + PINCTRL_GRP_UART1_17, + PINCTRL_GRP_TRACE0_2, + PINCTRL_GRP_SDIO0_4BIT_2_0, + PINCTRL_GRP_SDIO0_1BIT_2_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_69] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO1_1_WP, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_69, + PINCTRL_GRP_CAN1_17, + PINCTRL_GRP_I2C1_17, + PINCTRL_GRP_SWDT1_11_RST, + PINCTRL_GRP_SPI0_5, + PINCTRL_GRP_TTC1_8_WAV, + PINCTRL_GRP_UART1_17, + PINCTRL_GRP_TRACE0_2, + PINCTRL_GRP_SDIO0_4BIT_2_0, + PINCTRL_GRP_SDIO0_1BIT_2_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_70] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO1_1_PC, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_70, + PINCTRL_GRP_CAN0_17, + PINCTRL_GRP_I2C0_17, + PINCTRL_GRP_SWDT0_11_CLK, + PINCTRL_GRP_SPI1_5, + PINCTRL_GRP_TTC0_8_CLK, + PINCTRL_GRP_UART0_17, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_2_0, + PINCTRL_GRP_SDIO0_1BIT_2_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_71] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO1_4BIT_1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_71, + PINCTRL_GRP_CAN0_17, + PINCTRL_GRP_I2C0_17, + PINCTRL_GRP_SWDT0_11_RST, + PINCTRL_GRP_SPI1_5_SS2, + PINCTRL_GRP_TTC0_8_WAV, + PINCTRL_GRP_UART0_17, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO0_4BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_4, + PINCTRL_GRP_SDIO1_1BIT_1_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_72] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO1_4BIT_1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_72, + PINCTRL_GRP_CAN1_18, + PINCTRL_GRP_I2C1_18, + PINCTRL_GRP_SWDT1_12_CLK, + PINCTRL_GRP_SPI1_5_SS1, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_UART1_18, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_5, + PINCTRL_GRP_SDIO1_1BIT_1_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_73] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO1_4BIT_1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_73, + PINCTRL_GRP_CAN1_18, + PINCTRL_GRP_I2C1_18, + PINCTRL_GRP_SWDT1_12_RST, + PINCTRL_GRP_SPI1_5_SS0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_UART1_18, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_6, + PINCTRL_GRP_SDIO1_1BIT_1_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_74] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO1_4BIT_1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_74, + PINCTRL_GRP_CAN0_18, + PINCTRL_GRP_I2C0_18, + PINCTRL_GRP_SWDT0_12_CLK, + PINCTRL_GRP_SPI1_5, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_UART0_18, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_4BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_7, + PINCTRL_GRP_SDIO1_1BIT_1_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_75] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_SDIO0_2_PC, + PINCTRL_GRP_SDIO1_4BIT_1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_75, + PINCTRL_GRP_CAN0_18, + PINCTRL_GRP_I2C0_18, + PINCTRL_GRP_SWDT0_12_RST, + PINCTRL_GRP_SPI1_5, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_UART0_18, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO1_1BIT_1_0, + PINCTRL_GRP_SDIO1_1BIT_1_1, + PINCTRL_GRP_SDIO1_1BIT_1_2, + PINCTRL_GRP_SDIO1_1BIT_1_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_76] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO0_2_WP, + PINCTRL_GRP_SDIO1_4BIT_1_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_76, + PINCTRL_GRP_CAN1_19, + PINCTRL_GRP_I2C1_19, + PINCTRL_GRP_MDIO0_0, + PINCTRL_GRP_MDIO1_1, + PINCTRL_GRP_MDIO2_0, + PINCTRL_GRP_MDIO3_0, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO1_1BIT_1_0, + PINCTRL_GRP_SDIO1_1BIT_1_1, + PINCTRL_GRP_SDIO1_1BIT_1_2, + PINCTRL_GRP_SDIO1_1BIT_1_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_PIN_77] = { + .groups = &((uint16_t []) { + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_SDIO1_1_CD, + PINCTRL_GRP_RESERVED, + PINCTRL_GRP_GPIO0_77, + PINCTRL_GRP_CAN1_19, + PINCTRL_GRP_I2C1_19, + PINCTRL_GRP_MDIO0_0, + PINCTRL_GRP_MDIO1_1, + PINCTRL_GRP_MDIO2_0, + PINCTRL_GRP_MDIO3_0, + PINCTRL_GRP_RESERVED, + END_OF_GROUPS, + }), + }, +}; + +/** + * pm_api_pinctrl_get_num_pins() - PM call to request number of pins + * @npins Number of pins + * + * This function is used by master to get number of pins + * + * @return Returns success. + */ +enum pm_ret_status pm_api_pinctrl_get_num_pins(unsigned int *npins) +{ + *npins = MAX_PIN; + + return PM_RET_SUCCESS; +} + +/** + * pm_api_pinctrl_get_num_functions() - PM call to request number of functions + * @nfuncs Number of functions + * + * This function is used by master to get number of functions + * + * @return Returns success. + */ +enum pm_ret_status pm_api_pinctrl_get_num_functions(unsigned int *nfuncs) +{ + *nfuncs = MAX_FUNCTION; + + return PM_RET_SUCCESS; +} + +/** + * pm_api_pinctrl_get_num_func_groups() - PM call to request number of + * function groups + * @fid Function Id + * @ngroups Number of function groups + * + * This function is used by master to get number of function groups + * + * @return Returns success. + */ +enum pm_ret_status pm_api_pinctrl_get_num_func_groups(unsigned int fid, + unsigned int *ngroups) +{ + int i = 0; + uint16_t *grps; + + if (fid >= MAX_FUNCTION) + return PM_RET_ERROR_ARGS; + + *ngroups = 0; + + grps = *pinctrl_functions[fid].groups; + if (grps == NULL) + return PM_RET_SUCCESS; + + while (grps[i++] != (uint16_t)END_OF_GROUPS) + (*ngroups)++; + + return PM_RET_SUCCESS; +} + +/** + * pm_api_pinctrl_get_function_name() - PM call to request a function name + * @fid Function ID + * @name Name of function (max 16 bytes) + * + * This function is used by master to get name of function specified + * by given function ID. + */ +void pm_api_pinctrl_get_function_name(unsigned int fid, char *name) +{ + if (fid >= MAX_FUNCTION) + memcpy(name, END_OF_FUNCTION, FUNCTION_NAME_LEN); + else + memcpy(name, pinctrl_functions[fid].name, FUNCTION_NAME_LEN); +} + +/** + * pm_api_pinctrl_get_function_groups() - PM call to request first 6 function + * groups of function Id + * @fid Function ID + * @index Index of next function groups + * @groups Function groups + * + * This function is used by master to get function groups specified + * by given function Id. This API will return 6 function groups with + * a single response. To get other function groups, master should call + * same API in loop with new function groups index till error is returned. + * + * E.g First call should have index 0 which will return function groups + * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return + * function groups 6, 7, 8, 9, 10 and 11 and so on. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid, + unsigned int index, + uint16_t *groups) +{ + unsigned int i; + uint16_t *grps; + + if (fid >= MAX_FUNCTION) + return PM_RET_ERROR_ARGS; + + memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN); + + grps = *pinctrl_functions[fid].groups; + if (grps == NULL) + return PM_RET_SUCCESS; + + /* Skip groups till index */ + for (i = 0; i < index; i++) + if (grps[i] == (uint16_t)END_OF_GROUPS) + return PM_RET_SUCCESS; + + for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { + groups[i] = grps[index + i]; + if (groups[i] == (uint16_t)END_OF_GROUPS) + break; + } + + return PM_RET_SUCCESS; +} + +/** + * pm_api_pinctrl_get_pin_groups() - PM call to request first 6 pin + * groups of pin + * @pin Pin + * @index Index of next pin groups + * @groups pin groups + * + * This function is used by master to get pin groups specified + * by given pin Id. This API will return 6 pin groups with + * a single response. To get other pin groups, master should call + * same API in loop with new pin groups index till error is returned. + * + * E.g First call should have index 0 which will return pin groups + * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return + * pin groups 6, 7, 8, 9, 10 and 11 and so on. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_pinctrl_get_pin_groups(unsigned int pin, + unsigned int index, + uint16_t *groups) +{ + unsigned int i; + uint16_t *grps; + + if (pin >= MAX_PIN) + return PM_RET_ERROR_ARGS; + + memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN); + + grps = *zynqmp_pin_groups[pin].groups; + if (!grps) + return PM_RET_SUCCESS; + + /* Skip groups till index */ + for (i = 0; i < index; i++) + if (grps[i] == (uint16_t)END_OF_GROUPS) + return PM_RET_SUCCESS; + + for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { + groups[i] = grps[index + i]; + if (groups[i] == (uint16_t)END_OF_GROUPS) + break; + } + + return PM_RET_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h new file mode 100644 index 0000000..2b8fca3 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h @@ -0,0 +1,723 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for pin control. + */ + +#ifndef PM_API_PINCTRL_H +#define PM_API_PINCTRL_H + +#include "pm_common.h" + +#define FUNCTION_NAME_LEN U(16) +#define GROUPS_PAYLOAD_LEN U(12) +#define NUM_GROUPS_PER_RESP U(6) +#define END_OF_FUNCTION "END_OF_FUNCTION" +#define END_OF_GROUPS -1 +#define PINCTRL_GRP_RESERVED -2 + +//pinctrl function ids +enum { + PINCTRL_FUNC_CAN0, + PINCTRL_FUNC_CAN1, + PINCTRL_FUNC_ETHERNET0, + PINCTRL_FUNC_ETHERNET1, + PINCTRL_FUNC_ETHERNET2, + PINCTRL_FUNC_ETHERNET3, + PINCTRL_FUNC_GEMTSU0, + PINCTRL_FUNC_GPIO0, + PINCTRL_FUNC_I2C0, + PINCTRL_FUNC_I2C1, + PINCTRL_FUNC_MDIO0, + PINCTRL_FUNC_MDIO1, + PINCTRL_FUNC_MDIO2, + PINCTRL_FUNC_MDIO3, + PINCTRL_FUNC_QSPI0, + PINCTRL_FUNC_QSPI_FBCLK, + PINCTRL_FUNC_QSPI_SS, + PINCTRL_FUNC_SPI0, + PINCTRL_FUNC_SPI1, + PINCTRL_FUNC_SPI0_SS, + PINCTRL_FUNC_SPI1_SS, + PINCTRL_FUNC_SDIO0, + PINCTRL_FUNC_SDIO0_PC, + PINCTRL_FUNC_SDIO0_CD, + PINCTRL_FUNC_SDIO0_WP, + PINCTRL_FUNC_SDIO1, + PINCTRL_FUNC_SDIO1_PC, + PINCTRL_FUNC_SDIO1_CD, + PINCTRL_FUNC_SDIO1_WP, + PINCTRL_FUNC_NAND0, + PINCTRL_FUNC_NAND0_CE, + PINCTRL_FUNC_NAND0_RB, + PINCTRL_FUNC_NAND0_DQS, + PINCTRL_FUNC_TTC0_CLK, + PINCTRL_FUNC_TTC0_WAV, + PINCTRL_FUNC_TTC1_CLK, + PINCTRL_FUNC_TTC1_WAV, + PINCTRL_FUNC_TTC2_CLK, + PINCTRL_FUNC_TTC2_WAV, + PINCTRL_FUNC_TTC3_CLK, + PINCTRL_FUNC_TTC3_WAV, + PINCTRL_FUNC_UART0, + PINCTRL_FUNC_UART1, + PINCTRL_FUNC_USB0, + PINCTRL_FUNC_USB1, + PINCTRL_FUNC_SWDT0_CLK, + PINCTRL_FUNC_SWDT0_RST, + PINCTRL_FUNC_SWDT1_CLK, + PINCTRL_FUNC_SWDT1_RST, + PINCTRL_FUNC_PMU0, + PINCTRL_FUNC_PCIE0, + PINCTRL_FUNC_CSU0, + PINCTRL_FUNC_DPAUX0, + PINCTRL_FUNC_PJTAG0, + PINCTRL_FUNC_TRACE0, + PINCTRL_FUNC_TRACE0_CLK, + PINCTRL_FUNC_TESTSCAN0, + END_FUNCTION, +}; + +#define MAX_FUNCTION (unsigned int)(END_FUNCTION) + +// pinctrl pin numbers +enum { + PINCTRL_PIN_0, + PINCTRL_PIN_1, + PINCTRL_PIN_2, + PINCTRL_PIN_3, + PINCTRL_PIN_4, + PINCTRL_PIN_5, + PINCTRL_PIN_6, + PINCTRL_PIN_7, + PINCTRL_PIN_8, + PINCTRL_PIN_9, + PINCTRL_PIN_10, + PINCTRL_PIN_11, + PINCTRL_PIN_12, + PINCTRL_PIN_13, + PINCTRL_PIN_14, + PINCTRL_PIN_15, + PINCTRL_PIN_16, + PINCTRL_PIN_17, + PINCTRL_PIN_18, + PINCTRL_PIN_19, + PINCTRL_PIN_20, + PINCTRL_PIN_21, + PINCTRL_PIN_22, + PINCTRL_PIN_23, + PINCTRL_PIN_24, + PINCTRL_PIN_25, + PINCTRL_PIN_26, + PINCTRL_PIN_27, + PINCTRL_PIN_28, + PINCTRL_PIN_29, + PINCTRL_PIN_30, + PINCTRL_PIN_31, + PINCTRL_PIN_32, + PINCTRL_PIN_33, + PINCTRL_PIN_34, + PINCTRL_PIN_35, + PINCTRL_PIN_36, + PINCTRL_PIN_37, + PINCTRL_PIN_38, + PINCTRL_PIN_39, + PINCTRL_PIN_40, + PINCTRL_PIN_41, + PINCTRL_PIN_42, + PINCTRL_PIN_43, + PINCTRL_PIN_44, + PINCTRL_PIN_45, + PINCTRL_PIN_46, + PINCTRL_PIN_47, + PINCTRL_PIN_48, + PINCTRL_PIN_49, + PINCTRL_PIN_50, + PINCTRL_PIN_51, + PINCTRL_PIN_52, + PINCTRL_PIN_53, + PINCTRL_PIN_54, + PINCTRL_PIN_55, + PINCTRL_PIN_56, + PINCTRL_PIN_57, + PINCTRL_PIN_58, + PINCTRL_PIN_59, + PINCTRL_PIN_60, + PINCTRL_PIN_61, + PINCTRL_PIN_62, + PINCTRL_PIN_63, + PINCTRL_PIN_64, + PINCTRL_PIN_65, + PINCTRL_PIN_66, + PINCTRL_PIN_67, + PINCTRL_PIN_68, + PINCTRL_PIN_69, + PINCTRL_PIN_70, + PINCTRL_PIN_71, + PINCTRL_PIN_72, + PINCTRL_PIN_73, + PINCTRL_PIN_74, + PINCTRL_PIN_75, + PINCTRL_PIN_76, + PINCTRL_PIN_77, + END_PINS, +}; + +#define MAX_PIN (unsigned int)(END_PINS) + +// pinctrl group ids +enum { + PINCTRL_GRP_ETHERNET0_0, + PINCTRL_GRP_ETHERNET1_0, + PINCTRL_GRP_ETHERNET2_0, + PINCTRL_GRP_ETHERNET3_0, + PINCTRL_GRP_GEMTSU0_0, + PINCTRL_GRP_GEMTSU0_1, + PINCTRL_GRP_GEMTSU0_2, + PINCTRL_GRP_MDIO0_0, + PINCTRL_GRP_MDIO1_0, + PINCTRL_GRP_MDIO1_1, + PINCTRL_GRP_MDIO2_0, + PINCTRL_GRP_MDIO3_0, + PINCTRL_GRP_QSPI0_0, + PINCTRL_GRP_QSPI_SS, + PINCTRL_GRP_QSPI_FBCLK, + PINCTRL_GRP_SPI0_0, + PINCTRL_GRP_SPI0_0_SS0, + PINCTRL_GRP_SPI0_0_SS1, + PINCTRL_GRP_SPI0_0_SS2, + PINCTRL_GRP_SPI0_1, + PINCTRL_GRP_SPI0_1_SS0, + PINCTRL_GRP_SPI0_1_SS1, + PINCTRL_GRP_SPI0_1_SS2, + PINCTRL_GRP_SPI0_2, + PINCTRL_GRP_SPI0_2_SS0, + PINCTRL_GRP_SPI0_2_SS1, + PINCTRL_GRP_SPI0_2_SS2, + PINCTRL_GRP_SPI0_3, + PINCTRL_GRP_SPI0_3_SS0, + PINCTRL_GRP_SPI0_3_SS1, + PINCTRL_GRP_SPI0_3_SS2, + PINCTRL_GRP_SPI0_4, + PINCTRL_GRP_SPI0_4_SS0, + PINCTRL_GRP_SPI0_4_SS1, + PINCTRL_GRP_SPI0_4_SS2, + PINCTRL_GRP_SPI0_5, + PINCTRL_GRP_SPI0_5_SS0, + PINCTRL_GRP_SPI0_5_SS1, + PINCTRL_GRP_SPI0_5_SS2, + PINCTRL_GRP_SPI1_0, + PINCTRL_GRP_SPI1_0_SS0, + PINCTRL_GRP_SPI1_0_SS1, + PINCTRL_GRP_SPI1_0_SS2, + PINCTRL_GRP_SPI1_1, + PINCTRL_GRP_SPI1_1_SS0, + PINCTRL_GRP_SPI1_1_SS1, + PINCTRL_GRP_SPI1_1_SS2, + PINCTRL_GRP_SPI1_2, + PINCTRL_GRP_SPI1_2_SS0, + PINCTRL_GRP_SPI1_2_SS1, + PINCTRL_GRP_SPI1_2_SS2, + PINCTRL_GRP_SPI1_3, + PINCTRL_GRP_SPI1_3_SS0, + PINCTRL_GRP_SPI1_3_SS1, + PINCTRL_GRP_SPI1_3_SS2, + PINCTRL_GRP_SPI1_4, + PINCTRL_GRP_SPI1_4_SS0, + PINCTRL_GRP_SPI1_4_SS1, + PINCTRL_GRP_SPI1_4_SS2, + PINCTRL_GRP_SPI1_5, + PINCTRL_GRP_SPI1_5_SS0, + PINCTRL_GRP_SPI1_5_SS1, + PINCTRL_GRP_SPI1_5_SS2, + PINCTRL_GRP_SDIO0_0, + PINCTRL_GRP_SDIO0_1, + PINCTRL_GRP_SDIO0_2, + PINCTRL_GRP_SDIO0_4BIT_0_0, + PINCTRL_GRP_SDIO0_4BIT_0_1, + PINCTRL_GRP_SDIO0_4BIT_1_0, + PINCTRL_GRP_SDIO0_4BIT_1_1, + PINCTRL_GRP_SDIO0_4BIT_2_0, + PINCTRL_GRP_SDIO0_4BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_0_0, + PINCTRL_GRP_SDIO0_1BIT_0_1, + PINCTRL_GRP_SDIO0_1BIT_0_2, + PINCTRL_GRP_SDIO0_1BIT_0_3, + PINCTRL_GRP_SDIO0_1BIT_0_4, + PINCTRL_GRP_SDIO0_1BIT_0_5, + PINCTRL_GRP_SDIO0_1BIT_0_6, + PINCTRL_GRP_SDIO0_1BIT_0_7, + PINCTRL_GRP_SDIO0_1BIT_1_0, + PINCTRL_GRP_SDIO0_1BIT_1_1, + PINCTRL_GRP_SDIO0_1BIT_1_2, + PINCTRL_GRP_SDIO0_1BIT_1_3, + PINCTRL_GRP_SDIO0_1BIT_1_4, + PINCTRL_GRP_SDIO0_1BIT_1_5, + PINCTRL_GRP_SDIO0_1BIT_1_6, + PINCTRL_GRP_SDIO0_1BIT_1_7, + PINCTRL_GRP_SDIO0_1BIT_2_0, + PINCTRL_GRP_SDIO0_1BIT_2_1, + PINCTRL_GRP_SDIO0_1BIT_2_2, + PINCTRL_GRP_SDIO0_1BIT_2_3, + PINCTRL_GRP_SDIO0_1BIT_2_4, + PINCTRL_GRP_SDIO0_1BIT_2_5, + PINCTRL_GRP_SDIO0_1BIT_2_6, + PINCTRL_GRP_SDIO0_1BIT_2_7, + PINCTRL_GRP_SDIO0_0_PC, + PINCTRL_GRP_SDIO0_0_CD, + PINCTRL_GRP_SDIO0_0_WP, + PINCTRL_GRP_SDIO0_1_PC, + PINCTRL_GRP_SDIO0_1_CD, + PINCTRL_GRP_SDIO0_1_WP, + PINCTRL_GRP_SDIO0_2_PC, + PINCTRL_GRP_SDIO0_2_CD, + PINCTRL_GRP_SDIO0_2_WP, + PINCTRL_GRP_SDIO1_0, + PINCTRL_GRP_SDIO1_4BIT_0_0, + PINCTRL_GRP_SDIO1_4BIT_0_1, + PINCTRL_GRP_SDIO1_4BIT_1_0, + PINCTRL_GRP_SDIO1_1BIT_0_0, + PINCTRL_GRP_SDIO1_1BIT_0_1, + PINCTRL_GRP_SDIO1_1BIT_0_2, + PINCTRL_GRP_SDIO1_1BIT_0_3, + PINCTRL_GRP_SDIO1_1BIT_0_4, + PINCTRL_GRP_SDIO1_1BIT_0_5, + PINCTRL_GRP_SDIO1_1BIT_0_6, + PINCTRL_GRP_SDIO1_1BIT_0_7, + PINCTRL_GRP_SDIO1_1BIT_1_0, + PINCTRL_GRP_SDIO1_1BIT_1_1, + PINCTRL_GRP_SDIO1_1BIT_1_2, + PINCTRL_GRP_SDIO1_1BIT_1_3, + PINCTRL_GRP_SDIO1_0_PC, + PINCTRL_GRP_SDIO1_0_CD, + PINCTRL_GRP_SDIO1_0_WP, + PINCTRL_GRP_SDIO1_1_PC, + PINCTRL_GRP_SDIO1_1_CD, + PINCTRL_GRP_SDIO1_1_WP, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_NAND0_0_CE, + PINCTRL_GRP_NAND0_0_RB, + PINCTRL_GRP_NAND0_0_DQS, + PINCTRL_GRP_NAND0_1_CE, + PINCTRL_GRP_NAND0_1_RB, + PINCTRL_GRP_NAND0_1_DQS, + PINCTRL_GRP_CAN0_0, + PINCTRL_GRP_CAN0_1, + PINCTRL_GRP_CAN0_2, + PINCTRL_GRP_CAN0_3, + PINCTRL_GRP_CAN0_4, + PINCTRL_GRP_CAN0_5, + PINCTRL_GRP_CAN0_6, + PINCTRL_GRP_CAN0_7, + PINCTRL_GRP_CAN0_8, + PINCTRL_GRP_CAN0_9, + PINCTRL_GRP_CAN0_10, + PINCTRL_GRP_CAN0_11, + PINCTRL_GRP_CAN0_12, + PINCTRL_GRP_CAN0_13, + PINCTRL_GRP_CAN0_14, + PINCTRL_GRP_CAN0_15, + PINCTRL_GRP_CAN0_16, + PINCTRL_GRP_CAN0_17, + PINCTRL_GRP_CAN0_18, + PINCTRL_GRP_CAN1_0, + PINCTRL_GRP_CAN1_1, + PINCTRL_GRP_CAN1_2, + PINCTRL_GRP_CAN1_3, + PINCTRL_GRP_CAN1_4, + PINCTRL_GRP_CAN1_5, + PINCTRL_GRP_CAN1_6, + PINCTRL_GRP_CAN1_7, + PINCTRL_GRP_CAN1_8, + PINCTRL_GRP_CAN1_9, + PINCTRL_GRP_CAN1_10, + PINCTRL_GRP_CAN1_11, + PINCTRL_GRP_CAN1_12, + PINCTRL_GRP_CAN1_13, + PINCTRL_GRP_CAN1_14, + PINCTRL_GRP_CAN1_15, + PINCTRL_GRP_CAN1_16, + PINCTRL_GRP_CAN1_17, + PINCTRL_GRP_CAN1_18, + PINCTRL_GRP_CAN1_19, + PINCTRL_GRP_UART0_0, + PINCTRL_GRP_UART0_1, + PINCTRL_GRP_UART0_2, + PINCTRL_GRP_UART0_3, + PINCTRL_GRP_UART0_4, + PINCTRL_GRP_UART0_5, + PINCTRL_GRP_UART0_6, + PINCTRL_GRP_UART0_7, + PINCTRL_GRP_UART0_8, + PINCTRL_GRP_UART0_9, + PINCTRL_GRP_UART0_10, + PINCTRL_GRP_UART0_11, + PINCTRL_GRP_UART0_12, + PINCTRL_GRP_UART0_13, + PINCTRL_GRP_UART0_14, + PINCTRL_GRP_UART0_15, + PINCTRL_GRP_UART0_16, + PINCTRL_GRP_UART0_17, + PINCTRL_GRP_UART0_18, + PINCTRL_GRP_UART1_0, + PINCTRL_GRP_UART1_1, + PINCTRL_GRP_UART1_2, + PINCTRL_GRP_UART1_3, + PINCTRL_GRP_UART1_4, + PINCTRL_GRP_UART1_5, + PINCTRL_GRP_UART1_6, + PINCTRL_GRP_UART1_7, + PINCTRL_GRP_UART1_8, + PINCTRL_GRP_UART1_9, + PINCTRL_GRP_UART1_10, + PINCTRL_GRP_UART1_11, + PINCTRL_GRP_UART1_12, + PINCTRL_GRP_UART1_13, + PINCTRL_GRP_UART1_14, + PINCTRL_GRP_UART1_15, + PINCTRL_GRP_UART1_16, + PINCTRL_GRP_UART1_17, + PINCTRL_GRP_UART1_18, + PINCTRL_GRP_I2C0_0, + PINCTRL_GRP_I2C0_1, + PINCTRL_GRP_I2C0_2, + PINCTRL_GRP_I2C0_3, + PINCTRL_GRP_I2C0_4, + PINCTRL_GRP_I2C0_5, + PINCTRL_GRP_I2C0_6, + PINCTRL_GRP_I2C0_7, + PINCTRL_GRP_I2C0_8, + PINCTRL_GRP_I2C0_9, + PINCTRL_GRP_I2C0_10, + PINCTRL_GRP_I2C0_11, + PINCTRL_GRP_I2C0_12, + PINCTRL_GRP_I2C0_13, + PINCTRL_GRP_I2C0_14, + PINCTRL_GRP_I2C0_15, + PINCTRL_GRP_I2C0_16, + PINCTRL_GRP_I2C0_17, + PINCTRL_GRP_I2C0_18, + PINCTRL_GRP_I2C1_0, + PINCTRL_GRP_I2C1_1, + PINCTRL_GRP_I2C1_2, + PINCTRL_GRP_I2C1_3, + PINCTRL_GRP_I2C1_4, + PINCTRL_GRP_I2C1_5, + PINCTRL_GRP_I2C1_6, + PINCTRL_GRP_I2C1_7, + PINCTRL_GRP_I2C1_8, + PINCTRL_GRP_I2C1_9, + PINCTRL_GRP_I2C1_10, + PINCTRL_GRP_I2C1_11, + PINCTRL_GRP_I2C1_12, + PINCTRL_GRP_I2C1_13, + PINCTRL_GRP_I2C1_14, + PINCTRL_GRP_I2C1_15, + PINCTRL_GRP_I2C1_16, + PINCTRL_GRP_I2C1_17, + PINCTRL_GRP_I2C1_18, + PINCTRL_GRP_I2C1_19, + PINCTRL_GRP_TTC0_0_CLK, + PINCTRL_GRP_TTC0_0_WAV, + PINCTRL_GRP_TTC0_1_CLK, + PINCTRL_GRP_TTC0_1_WAV, + PINCTRL_GRP_TTC0_2_CLK, + PINCTRL_GRP_TTC0_2_WAV, + PINCTRL_GRP_TTC0_3_CLK, + PINCTRL_GRP_TTC0_3_WAV, + PINCTRL_GRP_TTC0_4_CLK, + PINCTRL_GRP_TTC0_4_WAV, + PINCTRL_GRP_TTC0_5_CLK, + PINCTRL_GRP_TTC0_5_WAV, + PINCTRL_GRP_TTC0_6_CLK, + PINCTRL_GRP_TTC0_6_WAV, + PINCTRL_GRP_TTC0_7_CLK, + PINCTRL_GRP_TTC0_7_WAV, + PINCTRL_GRP_TTC0_8_CLK, + PINCTRL_GRP_TTC0_8_WAV, + PINCTRL_GRP_TTC1_0_CLK, + PINCTRL_GRP_TTC1_0_WAV, + PINCTRL_GRP_TTC1_1_CLK, + PINCTRL_GRP_TTC1_1_WAV, + PINCTRL_GRP_TTC1_2_CLK, + PINCTRL_GRP_TTC1_2_WAV, + PINCTRL_GRP_TTC1_3_CLK, + PINCTRL_GRP_TTC1_3_WAV, + PINCTRL_GRP_TTC1_4_CLK, + PINCTRL_GRP_TTC1_4_WAV, + PINCTRL_GRP_TTC1_5_CLK, + PINCTRL_GRP_TTC1_5_WAV, + PINCTRL_GRP_TTC1_6_CLK, + PINCTRL_GRP_TTC1_6_WAV, + PINCTRL_GRP_TTC1_7_CLK, + PINCTRL_GRP_TTC1_7_WAV, + PINCTRL_GRP_TTC1_8_CLK, + PINCTRL_GRP_TTC1_8_WAV, + PINCTRL_GRP_TTC2_0_CLK, + PINCTRL_GRP_TTC2_0_WAV, + PINCTRL_GRP_TTC2_1_CLK, + PINCTRL_GRP_TTC2_1_WAV, + PINCTRL_GRP_TTC2_2_CLK, + PINCTRL_GRP_TTC2_2_WAV, + PINCTRL_GRP_TTC2_3_CLK, + PINCTRL_GRP_TTC2_3_WAV, + PINCTRL_GRP_TTC2_4_CLK, + PINCTRL_GRP_TTC2_4_WAV, + PINCTRL_GRP_TTC2_5_CLK, + PINCTRL_GRP_TTC2_5_WAV, + PINCTRL_GRP_TTC2_6_CLK, + PINCTRL_GRP_TTC2_6_WAV, + PINCTRL_GRP_TTC2_7_CLK, + PINCTRL_GRP_TTC2_7_WAV, + PINCTRL_GRP_TTC2_8_CLK, + PINCTRL_GRP_TTC2_8_WAV, + PINCTRL_GRP_TTC3_0_CLK, + PINCTRL_GRP_TTC3_0_WAV, + PINCTRL_GRP_TTC3_1_CLK, + PINCTRL_GRP_TTC3_1_WAV, + PINCTRL_GRP_TTC3_2_CLK, + PINCTRL_GRP_TTC3_2_WAV, + PINCTRL_GRP_TTC3_3_CLK, + PINCTRL_GRP_TTC3_3_WAV, + PINCTRL_GRP_TTC3_4_CLK, + PINCTRL_GRP_TTC3_4_WAV, + PINCTRL_GRP_TTC3_5_CLK, + PINCTRL_GRP_TTC3_5_WAV, + PINCTRL_GRP_TTC3_6_CLK, + PINCTRL_GRP_TTC3_6_WAV, + PINCTRL_GRP_TTC3_7_CLK, + PINCTRL_GRP_TTC3_7_WAV, + PINCTRL_GRP_TTC3_8_CLK, + PINCTRL_GRP_TTC3_8_WAV, + PINCTRL_GRP_SWDT0_0_CLK, + PINCTRL_GRP_SWDT0_0_RST, + PINCTRL_GRP_SWDT0_1_CLK, + PINCTRL_GRP_SWDT0_1_RST, + PINCTRL_GRP_SWDT0_2_CLK, + PINCTRL_GRP_SWDT0_2_RST, + PINCTRL_GRP_SWDT0_3_CLK, + PINCTRL_GRP_SWDT0_3_RST, + PINCTRL_GRP_SWDT0_4_CLK, + PINCTRL_GRP_SWDT0_4_RST, + PINCTRL_GRP_SWDT0_5_CLK, + PINCTRL_GRP_SWDT0_5_RST, + PINCTRL_GRP_SWDT0_6_CLK, + PINCTRL_GRP_SWDT0_6_RST, + PINCTRL_GRP_SWDT0_7_CLK, + PINCTRL_GRP_SWDT0_7_RST, + PINCTRL_GRP_SWDT0_8_CLK, + PINCTRL_GRP_SWDT0_8_RST, + PINCTRL_GRP_SWDT0_9_CLK, + PINCTRL_GRP_SWDT0_9_RST, + PINCTRL_GRP_SWDT0_10_CLK, + PINCTRL_GRP_SWDT0_10_RST, + PINCTRL_GRP_SWDT0_11_CLK, + PINCTRL_GRP_SWDT0_11_RST, + PINCTRL_GRP_SWDT0_12_CLK, + PINCTRL_GRP_SWDT0_12_RST, + PINCTRL_GRP_SWDT1_0_CLK, + PINCTRL_GRP_SWDT1_0_RST, + PINCTRL_GRP_SWDT1_1_CLK, + PINCTRL_GRP_SWDT1_1_RST, + PINCTRL_GRP_SWDT1_2_CLK, + PINCTRL_GRP_SWDT1_2_RST, + PINCTRL_GRP_SWDT1_3_CLK, + PINCTRL_GRP_SWDT1_3_RST, + PINCTRL_GRP_SWDT1_4_CLK, + PINCTRL_GRP_SWDT1_4_RST, + PINCTRL_GRP_SWDT1_5_CLK, + PINCTRL_GRP_SWDT1_5_RST, + PINCTRL_GRP_SWDT1_6_CLK, + PINCTRL_GRP_SWDT1_6_RST, + PINCTRL_GRP_SWDT1_7_CLK, + PINCTRL_GRP_SWDT1_7_RST, + PINCTRL_GRP_SWDT1_8_CLK, + PINCTRL_GRP_SWDT1_8_RST, + PINCTRL_GRP_SWDT1_9_CLK, + PINCTRL_GRP_SWDT1_9_RST, + PINCTRL_GRP_SWDT1_10_CLK, + PINCTRL_GRP_SWDT1_10_RST, + PINCTRL_GRP_SWDT1_11_CLK, + PINCTRL_GRP_SWDT1_11_RST, + PINCTRL_GRP_SWDT1_12_CLK, + PINCTRL_GRP_SWDT1_12_RST, + PINCTRL_GRP_GPIO0_0, + PINCTRL_GRP_GPIO0_1, + PINCTRL_GRP_GPIO0_2, + PINCTRL_GRP_GPIO0_3, + PINCTRL_GRP_GPIO0_4, + PINCTRL_GRP_GPIO0_5, + PINCTRL_GRP_GPIO0_6, + PINCTRL_GRP_GPIO0_7, + PINCTRL_GRP_GPIO0_8, + PINCTRL_GRP_GPIO0_9, + PINCTRL_GRP_GPIO0_10, + PINCTRL_GRP_GPIO0_11, + PINCTRL_GRP_GPIO0_12, + PINCTRL_GRP_GPIO0_13, + PINCTRL_GRP_GPIO0_14, + PINCTRL_GRP_GPIO0_15, + PINCTRL_GRP_GPIO0_16, + PINCTRL_GRP_GPIO0_17, + PINCTRL_GRP_GPIO0_18, + PINCTRL_GRP_GPIO0_19, + PINCTRL_GRP_GPIO0_20, + PINCTRL_GRP_GPIO0_21, + PINCTRL_GRP_GPIO0_22, + PINCTRL_GRP_GPIO0_23, + PINCTRL_GRP_GPIO0_24, + PINCTRL_GRP_GPIO0_25, + PINCTRL_GRP_GPIO0_26, + PINCTRL_GRP_GPIO0_27, + PINCTRL_GRP_GPIO0_28, + PINCTRL_GRP_GPIO0_29, + PINCTRL_GRP_GPIO0_30, + PINCTRL_GRP_GPIO0_31, + PINCTRL_GRP_GPIO0_32, + PINCTRL_GRP_GPIO0_33, + PINCTRL_GRP_GPIO0_34, + PINCTRL_GRP_GPIO0_35, + PINCTRL_GRP_GPIO0_36, + PINCTRL_GRP_GPIO0_37, + PINCTRL_GRP_GPIO0_38, + PINCTRL_GRP_GPIO0_39, + PINCTRL_GRP_GPIO0_40, + PINCTRL_GRP_GPIO0_41, + PINCTRL_GRP_GPIO0_42, + PINCTRL_GRP_GPIO0_43, + PINCTRL_GRP_GPIO0_44, + PINCTRL_GRP_GPIO0_45, + PINCTRL_GRP_GPIO0_46, + PINCTRL_GRP_GPIO0_47, + PINCTRL_GRP_GPIO0_48, + PINCTRL_GRP_GPIO0_49, + PINCTRL_GRP_GPIO0_50, + PINCTRL_GRP_GPIO0_51, + PINCTRL_GRP_GPIO0_52, + PINCTRL_GRP_GPIO0_53, + PINCTRL_GRP_GPIO0_54, + PINCTRL_GRP_GPIO0_55, + PINCTRL_GRP_GPIO0_56, + PINCTRL_GRP_GPIO0_57, + PINCTRL_GRP_GPIO0_58, + PINCTRL_GRP_GPIO0_59, + PINCTRL_GRP_GPIO0_60, + PINCTRL_GRP_GPIO0_61, + PINCTRL_GRP_GPIO0_62, + PINCTRL_GRP_GPIO0_63, + PINCTRL_GRP_GPIO0_64, + PINCTRL_GRP_GPIO0_65, + PINCTRL_GRP_GPIO0_66, + PINCTRL_GRP_GPIO0_67, + PINCTRL_GRP_GPIO0_68, + PINCTRL_GRP_GPIO0_69, + PINCTRL_GRP_GPIO0_70, + PINCTRL_GRP_GPIO0_71, + PINCTRL_GRP_GPIO0_72, + PINCTRL_GRP_GPIO0_73, + PINCTRL_GRP_GPIO0_74, + PINCTRL_GRP_GPIO0_75, + PINCTRL_GRP_GPIO0_76, + PINCTRL_GRP_GPIO0_77, + PINCTRL_GRP_USB0_0, + PINCTRL_GRP_USB1_0, + PINCTRL_GRP_PMU0_0, + PINCTRL_GRP_PMU0_1, + PINCTRL_GRP_PMU0_2, + PINCTRL_GRP_PMU0_3, + PINCTRL_GRP_PMU0_4, + PINCTRL_GRP_PMU0_5, + PINCTRL_GRP_PMU0_6, + PINCTRL_GRP_PMU0_7, + PINCTRL_GRP_PMU0_8, + PINCTRL_GRP_PMU0_9, + PINCTRL_GRP_PMU0_10, + PINCTRL_GRP_PMU0_11, + PINCTRL_GRP_PCIE0_0, + PINCTRL_GRP_PCIE0_1, + PINCTRL_GRP_PCIE0_2, + PINCTRL_GRP_PCIE0_3, + PINCTRL_GRP_PCIE0_4, + PINCTRL_GRP_PCIE0_5, + PINCTRL_GRP_PCIE0_6, + PINCTRL_GRP_PCIE0_7, + PINCTRL_GRP_CSU0_0, + PINCTRL_GRP_CSU0_1, + PINCTRL_GRP_CSU0_2, + PINCTRL_GRP_CSU0_3, + PINCTRL_GRP_CSU0_4, + PINCTRL_GRP_CSU0_5, + PINCTRL_GRP_CSU0_6, + PINCTRL_GRP_CSU0_7, + PINCTRL_GRP_CSU0_8, + PINCTRL_GRP_CSU0_9, + PINCTRL_GRP_CSU0_10, + PINCTRL_GRP_CSU0_11, + PINCTRL_GRP_DPAUX0_0, + PINCTRL_GRP_DPAUX0_1, + PINCTRL_GRP_DPAUX0_2, + PINCTRL_GRP_DPAUX0_3, + PINCTRL_GRP_PJTAG0_0, + PINCTRL_GRP_PJTAG0_1, + PINCTRL_GRP_PJTAG0_2, + PINCTRL_GRP_PJTAG0_3, + PINCTRL_GRP_PJTAG0_4, + PINCTRL_GRP_PJTAG0_5, + PINCTRL_GRP_TRACE0_0, + PINCTRL_GRP_TRACE0_0_CLK, + PINCTRL_GRP_TRACE0_1, + PINCTRL_GRP_TRACE0_1_CLK, + PINCTRL_GRP_TRACE0_2, + PINCTRL_GRP_TRACE0_2_CLK, + PINCTRL_GRP_TESTSCAN0_0, +}; + +// pinctrl config parameters +enum { + PINCTRL_CONFIG_SLEW_RATE, + PINCTRL_CONFIG_BIAS_STATUS, + PINCTRL_CONFIG_PULL_CTRL, + PINCTRL_CONFIG_SCHMITT_CMOS, + PINCTRL_CONFIG_DRIVE_STRENGTH, + PINCTRL_CONFIG_VOLTAGE_STATUS, + PINCTRL_CONFIG_MAX, +}; + +// pinctrl slew rate +#define PINCTRL_SLEW_RATE_FAST 0U +#define PINCTRL_SLEW_RATE_SLOW 1U + +// pinctrl bias status +#define PINCTRL_BIAS_DISABLE 0U +#define PINCTRL_BIAS_ENABLE 1U + +// pinctrl pull control +#define PINCTRL_BIAS_PULL_DOWN 0U +#define PINCTRL_BIAS_PULL_UP 1U + +// pinctrl schmitt cmos type +#define PINCTRL_INPUT_TYPE_CMOS 0U +#define PINCTRL_INPUT_TYPE_SCHMITT 1U + +//pinctrl drive strength values +#define PINCTRL_DRIVE_STRENGTH_2MA 0U +#define PINCTRL_DRIVE_STRENGTH_4MA 1U +#define PINCTRL_DRIVE_STRENGTH_8MA 2U +#define PINCTRL_DRIVE_STRENGTH_12MA 3U + +void pm_api_pinctrl_get_function_name(unsigned int fid, char *name); +enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid, + unsigned int index, + uint16_t *groups); +enum pm_ret_status pm_api_pinctrl_get_pin_groups(unsigned int pin, + unsigned int index, + uint16_t *groups); +enum pm_ret_status pm_api_pinctrl_get_num_pins(unsigned int *npins); +enum pm_ret_status pm_api_pinctrl_get_num_functions(unsigned int *nfuncs); +enum pm_ret_status pm_api_pinctrl_get_num_func_groups(unsigned int fid, + unsigned int *ngroups); +#endif /* PM_API_PINCTRL_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c new file mode 100644 index 0000000..f9af451 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -0,0 +1,1804 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions and communication with PMU via + * IPI interrupts + */ + +#include +#include + +#include "pm_api_clock.h" +#include "pm_api_ioctl.h" +#include "pm_api_pinctrl.h" +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_common.h" +#include "pm_ipi.h" + +#define PM_QUERY_FEATURE_BITMASK ( \ + (1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \ + (1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) | \ + (1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \ + (1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \ + (1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \ + (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \ + (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \ + (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \ + (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \ + (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \ + (1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \ + (1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \ + (1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR)) + +/** + * struct eemi_api_dependency - Dependent EEMI APIs which are implemented + * on both the ATF and firmware + * + * @id: EEMI API id or IOCTL id to be checked + * @api_id: Dependent EEMI API + */ +typedef struct __attribute__((packed)) { + uint8_t id; + uint8_t api_id; +} eemi_api_dependency; + +/* Dependent APIs for ATF to check their version from firmware */ +static const eemi_api_dependency api_dep_table[] = { + { + .id = PM_SELF_SUSPEND, + .api_id = PM_SELF_SUSPEND, + }, + { + .id = PM_REQ_WAKEUP, + .api_id = PM_REQ_WAKEUP, + }, + { + .id = PM_ABORT_SUSPEND, + .api_id = PM_ABORT_SUSPEND, + }, + { + .id = PM_SET_WAKEUP_SOURCE, + .api_id = PM_SET_WAKEUP_SOURCE, + }, + { + .id = PM_SYSTEM_SHUTDOWN, + .api_id = PM_SYSTEM_SHUTDOWN, + }, + { + .id = PM_GET_API_VERSION, + .api_id = PM_GET_API_VERSION, + }, + { + .id = PM_CLOCK_ENABLE, + .api_id = PM_PLL_SET_MODE, + }, + { + .id = PM_CLOCK_ENABLE, + .api_id = PM_CLOCK_ENABLE, + }, + { + .id = PM_CLOCK_DISABLE, + .api_id = PM_PLL_SET_MODE, + }, + { + .id = PM_CLOCK_DISABLE, + .api_id = PM_CLOCK_DISABLE, + }, + { + .id = PM_CLOCK_GETSTATE, + .api_id = PM_PLL_GET_MODE, + }, + { + .id = PM_CLOCK_GETSTATE, + .api_id = PM_CLOCK_GETSTATE, + }, + { + .id = PM_CLOCK_SETDIVIDER, + .api_id = PM_PLL_SET_PARAMETER, + }, + { + .id = PM_CLOCK_SETDIVIDER, + .api_id = PM_CLOCK_SETDIVIDER, + }, + { + .id = PM_CLOCK_GETDIVIDER, + .api_id = PM_PLL_GET_PARAMETER, + }, + { + .id = PM_CLOCK_GETDIVIDER, + .api_id = PM_CLOCK_GETDIVIDER, + }, + { + .id = PM_CLOCK_SETPARENT, + .api_id = PM_PLL_SET_PARAMETER, + }, + { + .id = PM_CLOCK_SETPARENT, + .api_id = PM_CLOCK_SETPARENT, + }, + { + .id = PM_CLOCK_GETPARENT, + .api_id = PM_PLL_GET_PARAMETER, + }, + { + .id = PM_CLOCK_GETPARENT, + .api_id = PM_CLOCK_GETPARENT, + }, + { + .id = PM_PLL_SET_PARAMETER, + .api_id = PM_PLL_SET_PARAMETER, + }, + { + .id = PM_PLL_GET_PARAMETER, + .api_id = PM_PLL_GET_PARAMETER, + }, + { + .id = PM_PLL_SET_MODE, + .api_id = PM_PLL_SET_MODE, + }, + { + .id = PM_PLL_GET_MODE, + .api_id = PM_PLL_GET_MODE, + }, + { + .id = PM_REGISTER_ACCESS, + .api_id = PM_MMIO_WRITE, + }, + { + .id = PM_REGISTER_ACCESS, + .api_id = PM_MMIO_READ, + }, + { + .id = PM_FEATURE_CHECK, + .api_id = PM_FEATURE_CHECK, + }, + { + .id = IOCTL_SET_TAPDELAY_BYPASS, + .api_id = PM_MMIO_WRITE, + }, + { + .id = IOCTL_SET_SGMII_MODE, + .api_id = PM_MMIO_WRITE, + }, + { + .id = IOCTL_SD_DLL_RESET, + .api_id = PM_MMIO_WRITE, + }, + { + .id = IOCTL_SET_SD_TAPDELAY, + .api_id = PM_MMIO_WRITE, + }, + { + .id = IOCTL_SET_SD_TAPDELAY, + .api_id = PM_MMIO_READ, + }, + { + .id = IOCTL_SET_PLL_FRAC_DATA, + .api_id = PM_PLL_SET_PARAMETER, + }, + { + .id = IOCTL_GET_PLL_FRAC_DATA, + .api_id = PM_PLL_GET_PARAMETER, + }, + { + .id = IOCTL_WRITE_GGS, + .api_id = PM_MMIO_WRITE, + }, + { + .id = IOCTL_READ_GGS, + .api_id = PM_MMIO_READ, + }, + { + .id = IOCTL_WRITE_PGGS, + .api_id = PM_MMIO_WRITE, + }, + { + .id = IOCTL_READ_PGGS, + .api_id = PM_MMIO_READ, + }, + { + .id = IOCTL_ULPI_RESET, + .api_id = PM_MMIO_WRITE, + }, + { + .id = IOCTL_SET_BOOT_HEALTH_STATUS, + .api_id = PM_MMIO_WRITE, + }, + { + .id = IOCTL_AFI, + .api_id = PM_MMIO_WRITE, + }, +}; + +/* Expected firmware API version to ATF */ +static const uint8_t atf_expected_ver_id[] = { + [PM_SELF_SUSPEND] = FW_API_BASE_VERSION, + [PM_REQ_WAKEUP] = FW_API_BASE_VERSION, + [PM_ABORT_SUSPEND] = FW_API_BASE_VERSION, + [PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION, + [PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION, + [PM_GET_API_VERSION] = FW_API_BASE_VERSION, + [PM_PLL_SET_MODE] = FW_API_BASE_VERSION, + [PM_PLL_GET_MODE] = FW_API_BASE_VERSION, + [PM_CLOCK_ENABLE] = FW_API_BASE_VERSION, + [PM_CLOCK_DISABLE] = FW_API_BASE_VERSION, + [PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION, + [PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION, + [PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION, + [PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION, + [PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION, + [PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION, + [PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION, + [PM_MMIO_WRITE] = FW_API_BASE_VERSION, + [PM_MMIO_READ] = FW_API_BASE_VERSION, + [PM_FEATURE_CHECK] = FW_API_VERSION_2, +}; + +/* default shutdown/reboot scope is system(2) */ +static unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM; + +/** + * pm_get_shutdown_scope() - Get the currently set shutdown scope + * + * @return Shutdown scope value + */ +unsigned int pm_get_shutdown_scope(void) +{ + return pm_shutdown_scope; +} + +#define EM_PACK_PAYLOAD1(pl, arg0) { \ + pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \ +} + +/** + * pm_self_suspend() - PM call for processor to suspend itself + * @nid Node id of the processor or subsystem + * @latency Requested maximum wakeup latency (not supported) + * @state Requested state + * @address Resume address + * + * This is a blocking call, it will return only once PMU has responded. + * On a wakeup, resume address will be automatically set by PMU. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_self_suspend(enum pm_node_id nid, + unsigned int latency, + unsigned int state, + uintptr_t address) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + unsigned int cpuid = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpuid); + + /* + * Do client specific suspend operations + * (e.g. set powerdown request bit) + */ + pm_client_suspend(proc, state); + /* Send request to the PMU */ + PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency, + state, address, (address >> 32)); + return pm_ipi_send_sync(proc, payload, NULL, 0); +} + +/** + * pm_req_suspend() - PM call to request for another PU or subsystem to + * be suspended gracefully. + * @target Node id of the targeted PU or subsystem + * @ack Flag to specify whether acknowledge is requested + * @latency Requested wakeup latency (not supported) + * @state Requested state (not supported) + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_req_suspend(enum pm_node_id target, + enum pm_request_ack ack, + unsigned int latency, unsigned int state) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state); + if (ack == REQ_ACK_BLOCKING) + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + else + return pm_ipi_send(primary_proc, payload); +} + +/** + * pm_req_wakeup() - PM call for processor to wake up selected processor + * or subsystem + * @target Node id of the processor or subsystem to wake up + * @ack Flag to specify whether acknowledge requested + * @set_address Resume address presence indicator + * 1 resume address specified, 0 otherwise + * @address Resume address + * + * This API function is either used to power up another APU core for SMP + * (by PSCI) or to power up an entirely different PU or subsystem, such + * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be + * automatically set by PMU. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_req_wakeup(enum pm_node_id target, + unsigned int set_address, + uintptr_t address, + enum pm_request_ack ack) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + uint64_t encoded_address; + + + /* encode set Address into 1st bit of address */ + encoded_address = address; + encoded_address |= !!set_address; + + /* Send request to the PMU to perform the wake of the PU */ + PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address, + encoded_address >> 32, ack); + + if (ack == REQ_ACK_BLOCKING) + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + else + return pm_ipi_send(primary_proc, payload); +} + +/** + * pm_force_powerdown() - PM call to request for another PU or subsystem to + * be powered down forcefully + * @target Node id of the targeted PU or subsystem + * @ack Flag to specify whether acknowledge is requested + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_force_powerdown(enum pm_node_id target, + enum pm_request_ack ack) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack); + + if (ack == REQ_ACK_BLOCKING) + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + else + return pm_ipi_send(primary_proc, payload); +} + +/** + * pm_abort_suspend() - PM call to announce that a prior suspend request + * is to be aborted. + * @reason Reason for the abort + * + * Calling PU expects the PMU to abort the initiated suspend procedure. + * This is a non-blocking call without any acknowledge. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* + * Do client specific abort suspend operations + * (e.g. enable interrupts and clear powerdown request bit) + */ + pm_client_abort_suspend(); + /* Send request to the PMU */ + /* TODO: allow passing the node ID of the affected CPU */ + PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason, + primary_proc->node_id); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended + * @target Node id of the targeted PU or subsystem + * @wkup_node Node id of the wakeup peripheral + * @enable Enable or disable the specified peripheral as wake source + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target, + enum pm_node_id wkup_node, + unsigned int enable) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node, + enable); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_system_shutdown() - PM call to request a system shutdown or restart + * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope + * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) { + /* Setting scope for subsequent PSCI reboot or shutdown */ + pm_shutdown_scope = subtype; + return PM_RET_SUCCESS; + } + + PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype); + return pm_ipi_send_non_blocking(primary_proc, payload); +} + +/* APIs for managing PM slaves: */ + +/** + * pm_req_node() - PM call to request a node with specific capabilities + * @nid Node id of the slave + * @capabilities Requested capabilities of the slave + * @qos Quality of service (not supported) + * @ack Flag to specify whether acknowledge is requested + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_req_node(enum pm_node_id nid, + unsigned int capabilities, + unsigned int qos, + enum pm_request_ack ack) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack); + + if (ack == REQ_ACK_BLOCKING) + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + else + return pm_ipi_send(primary_proc, payload); +} + +/** + * pm_set_requirement() - PM call to set requirement for PM slaves + * @nid Node id of the slave + * @capabilities Requested capabilities of the slave + * @qos Quality of service (not supported) + * @ack Flag to specify whether acknowledge is requested + * + * This API function is to be used for slaves a PU already has requested + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_set_requirement(enum pm_node_id nid, + unsigned int capabilities, + unsigned int qos, + enum pm_request_ack ack) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos, + ack); + + if (ack == REQ_ACK_BLOCKING) + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + else + return pm_ipi_send(primary_proc, payload); +} + +/* Miscellaneous API functions */ + +/** + * pm_get_api_version() - Get version number of PMU PM firmware + * @version Returns 32-bit version number of PMU Power Management Firmware + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_get_api_version(unsigned int *version) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION); + return pm_ipi_send_sync(primary_proc, payload, version, 1); +} + +/** + * pm_get_node_status() - PM call to request a node's current status + * @nid Node id + * @ret_buff Buffer for the return values: + * [0] - Current power state of the node + * [1] - Current requirements for the node (slave nodes only) + * [2] - Current usage status for the node (slave nodes only) + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_get_node_status(enum pm_node_id nid, + uint32_t *ret_buff) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid); + return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3); +} + +/** + * pm_mmio_write() - Perform write to protected mmio + * @address Address to write to + * @mask Mask to apply + * @value Value to write + * + * This function provides access to PM-related control registers + * that may not be directly accessible by a particular PU. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_mmio_write(uintptr_t address, + unsigned int mask, + unsigned int value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_mmio_read() - Read value from protected mmio + * @address Address to write to + * @value Value to write + * + * This function provides access to PM-related control registers + * that may not be directly accessible by a particular PU. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/** + * pm_fpga_load() - Load the bitstream into the PL. + * + * This function provides access to the xilfpga library to load + * the Bit-stream into PL. + * + * address_low: lower 32-bit Linear memory space address + * + * address_high: higher 32-bit Linear memory space address + * + * size: Number of 32bit words + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_fpga_load(uint32_t address_low, + uint32_t address_high, + uint32_t size, + uint32_t flags) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low, + size, flags); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_fpga_get_status() - Read value from fpga status register + * @value Value to read + * + * This function provides access to the xilfpga library to get + * the fpga status + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_fpga_get_status(unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/** + * pm_get_chipid() - Read silicon ID registers + * @value Buffer for return values. Must be large enough + * to hold 8 bytes. + * + * @return Returns silicon ID registers + */ +enum pm_ret_status pm_get_chipid(uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID); + return pm_ipi_send_sync(primary_proc, payload, value, 2); +} + +/** + * pm_secure_rsaaes() - Load the secure images. + * + * This function provides access to the xilsecure library to load + * the authenticated, encrypted, and authenicated/encrypted images. + * + * address_low: lower 32-bit Linear memory space address + * + * address_high: higher 32-bit Linear memory space address + * + * size: Number of 32bit words + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_secure_rsaaes(uint32_t address_low, + uint32_t address_high, + uint32_t size, + uint32_t flags) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low, + size, flags); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_aes_engine() - Aes data blob encryption/decryption + * This function provides access to the xilsecure library to + * encrypt/decrypt data blobs. + * + * address_low: lower 32-bit address of the AesParams structure + * + * address_high: higher 32-bit address of the AesParams structure + * + * value: Returned output value + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_aes_engine(uint32_t address_high, + uint32_t address_low, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/** + * pm_get_callbackdata() - Read from IPI response buffer + * @data - array of PAYLOAD_ARG_CNT elements + * + * Read value from ipi buffer response buffer. + */ +void pm_get_callbackdata(uint32_t *data, size_t count) +{ + /* Return if interrupt is not from PMU */ + if (!pm_ipi_irq_status(primary_proc)) + return; + + pm_ipi_buff_read_callb(data, count); + pm_ipi_irq_clear(primary_proc); +} + +/** + * pm_ioctl() - PM IOCTL API for device control and configs + * @node_id Node ID of the device + * @ioctl_id ID of the requested IOCTL + * @arg1 Argument 1 to requested IOCTL call + * @arg2 Argument 2 to requested IOCTL call + * @out Returned output value + * + * This function calls IOCTL to firmware for device control and configuration. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_ioctl(enum pm_node_id nid, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value) +{ + return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value); +} + +/** + * fw_api_version() - Returns API version implemented in firmware + * @api_id API ID to check + * @version Returned supported API version + * @len Number of words to be returned + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version, + uint32_t len) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id); + return pm_ipi_send_sync(primary_proc, payload, version, len); +} + +/** + * check_api_dependency() - API to check dependent EEMI API version + * @id EEMI API ID to check + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status check_api_dependency(uint8_t id) +{ + uint8_t i; + uint32_t version; + int ret; + + for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) { + if (api_dep_table[i].id == id) { + if (api_dep_table[i].api_id == 0U) { + break; + } + + ret = fw_api_version(api_dep_table[i].api_id, + &version, 1); + if (ret != PM_RET_SUCCESS) { + return ret; + } + + /* Check if fw version matches ATF expected version */ + if (version != atf_expected_ver_id[api_dep_table[i].api_id]) { + return PM_RET_ERROR_NOTSUPPORTED; + } + } + } + + return PM_RET_SUCCESS; +} + +/** + * feature_check_atf() - These are API's completely implemented in ATF + * @api_id API ID to check + * @version Returned supported API version + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version, + uint32_t *bit_mask) +{ + switch (api_id) { + case PM_QUERY_DATA: + *version = ATF_API_BASE_VERSION; + bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK); + bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32); + return PM_RET_SUCCESS; + case PM_GET_CALLBACK_DATA: + case PM_GET_TRUSTZONE_VERSION: + case PM_SET_SUSPEND_MODE: + *version = ATF_API_BASE_VERSION; + return PM_RET_SUCCESS; + default: + return PM_RET_ERROR_NO_FEATURE; + } +} + +/** + * get_atf_version_for_partial_apis() - Return ATF version for partially + * implemented APIs + * @api_id API ID to check + * @version Returned supported API version + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id, + uint32_t *version) +{ + switch (api_id) { + case PM_SELF_SUSPEND: + case PM_REQ_WAKEUP: + case PM_ABORT_SUSPEND: + case PM_SET_WAKEUP_SOURCE: + case PM_SYSTEM_SHUTDOWN: + case PM_GET_API_VERSION: + case PM_CLOCK_ENABLE: + case PM_CLOCK_DISABLE: + case PM_CLOCK_GETSTATE: + case PM_CLOCK_SETDIVIDER: + case PM_CLOCK_GETDIVIDER: + case PM_CLOCK_SETPARENT: + case PM_CLOCK_GETPARENT: + case PM_PLL_SET_PARAMETER: + case PM_PLL_GET_PARAMETER: + case PM_PLL_SET_MODE: + case PM_PLL_GET_MODE: + case PM_REGISTER_ACCESS: + *version = ATF_API_BASE_VERSION; + return PM_RET_SUCCESS; + case PM_FEATURE_CHECK: + *version = FW_API_VERSION_2; + return PM_RET_SUCCESS; + default: + return PM_RET_ERROR_ARGS; + } +} + +/** + * feature_check_partial() - These are API's partially implemented in + * ATF and firmware both + * @api_id API ID to check + * @version Returned supported API version + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status feature_check_partial(uint32_t api_id, + uint32_t *version) +{ + uint32_t status; + + switch (api_id) { + case PM_SELF_SUSPEND: + case PM_REQ_WAKEUP: + case PM_ABORT_SUSPEND: + case PM_SET_WAKEUP_SOURCE: + case PM_SYSTEM_SHUTDOWN: + case PM_GET_API_VERSION: + case PM_CLOCK_ENABLE: + case PM_CLOCK_DISABLE: + case PM_CLOCK_GETSTATE: + case PM_CLOCK_SETDIVIDER: + case PM_CLOCK_GETDIVIDER: + case PM_CLOCK_SETPARENT: + case PM_CLOCK_GETPARENT: + case PM_PLL_SET_PARAMETER: + case PM_PLL_GET_PARAMETER: + case PM_PLL_SET_MODE: + case PM_PLL_GET_MODE: + case PM_REGISTER_ACCESS: + case PM_FEATURE_CHECK: + status = check_api_dependency(api_id); + if (status != PM_RET_SUCCESS) { + return status; + } + return get_atf_version_for_partial_apis(api_id, version); + default: + return PM_RET_ERROR_NO_FEATURE; + } +} + +/** + * pm_feature_check() - Returns the supported API version if supported + * @api_id API ID to check + * @version Returned supported API version + * @bit_mask Returned supported IOCTL id version + * @len Number of bytes to be returned in bit_mask variable + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version, + uint32_t *bit_mask, uint8_t len) +{ + uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U}; + uint32_t status; + + /* Get API version implemented in ATF */ + status = feature_check_atf(api_id, version, bit_mask); + if (status != PM_RET_ERROR_NO_FEATURE) { + return status; + } + + /* Get API version implemented by firmware and ATF both */ + status = feature_check_partial(api_id, version); + if (status != PM_RET_ERROR_NO_FEATURE) { + return status; + } + + /* Get API version implemented by firmware */ + status = fw_api_version(api_id, ret_payload, 3); + /* IOCTL call may return failure whose ID is not implemented in + * firmware but implemented in ATF + */ + if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) { + return status; + } + + *version = ret_payload[0]; + + /* Update IOCTL bit mask which are implemented in ATF */ + if (api_id == PM_IOCTL) { + if (len < 2) { + return PM_RET_ERROR_ARGS; + } + bit_mask[0] = ret_payload[1]; + bit_mask[1] = ret_payload[2]; + /* Get IOCTL's implemented by ATF */ + status = atf_ioctl_bitmask(bit_mask); + } else { + /* Requires for MISRA */ + } + + return status; +} + +/** + * pm_clock_get_max_divisor - PM call to get max divisor + * @clock_id Clock ID + * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2) + * @max_div Maximum supported divisor + * + * This function is used by master to get maximum supported value. + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_clock_get_max_divisor(unsigned int clock_id, + uint8_t div_type, + uint32_t *max_div) +{ + return pm_api_clock_get_max_divisor(clock_id, div_type, max_div); +} + +/** + * pm_clock_get_num_clocks - PM call to request number of clocks + * @nclockss: Number of clocks + * + * This function is used by master to get number of clocks. + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks) +{ + return pm_api_clock_get_num_clocks(nclocks); +} + +/** + * pm_clock_get_name() - PM call to request a clock's name + * @clock_id Clock ID + * @name Name of clock (max 16 bytes) + * + * This function is used by master to get nmae of clock specified + * by given clock ID. + */ +static void pm_clock_get_name(unsigned int clock_id, char *name) +{ + pm_api_clock_get_name(clock_id, name); +} + +/** + * pm_clock_get_topology() - PM call to request a clock's topology + * @clock_id Clock ID + * @index Topology index for next toplogy node + * @topology Buffer to store nodes in topology and flags + * + * This function is used by master to get topology information for the + * clock specified by given clock ID. Each response would return 3 + * topology nodes. To get next nodes, caller needs to call this API with + * index of next node. Index starts from 0. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id, + unsigned int index, + uint32_t *topology) +{ + return pm_api_clock_get_topology(clock_id, index, topology); +} + +/** + * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor + * parameters for fixed clock + * @clock_id Clock ID + * @mul Multiplication value + * @div Divisor value + * + * This function is used by master to get fixed factor parameers for the + * fixed clock. This API is application only for the fixed clock. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id, + uint32_t *mul, + uint32_t *div) +{ + return pm_api_clock_get_fixedfactor_params(clock_id, mul, div); +} + +/** + * pm_clock_get_parents() - PM call to request a clock's first 3 parents + * @clock_id Clock ID + * @index Index of next parent + * @parents Parents of the given clock + * + * This function is used by master to get clock's parents information. + * This API will return 3 parents with a single response. To get other + * parents, master should call same API in loop with new parent index + * till error is returned. + * + * E.g First call should have index 0 which will return parents 0, 1 and + * 2. Next call, index should be 3 which will return parent 3,4 and 5 and + * so on. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id, + unsigned int index, + uint32_t *parents) +{ + return pm_api_clock_get_parents(clock_id, index, parents); +} + +/** + * pm_clock_get_attributes() - PM call to request a clock's attributes + * @clock_id Clock ID + * @attr Clock attributes + * + * This function is used by master to get clock's attributes + * (e.g. valid, clock type, etc). + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id, + uint32_t *attr) +{ + return pm_api_clock_get_attributes(clock_id, attr); +} + +/** + * pm_clock_gate() - Configure clock gate + * @clock_id Id of the clock to be configured + * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock) + * + * @return Error if an argument is not valid or status as returned by the + * PM controller (PMU) + */ +static enum pm_ret_status pm_clock_gate(unsigned int clock_id, + unsigned char enable) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + enum pm_ret_status status; + enum pm_api_id api_id; + + /* Check if clock ID is valid and return an error if it is not */ + status = pm_clock_id_is_valid(clock_id); + if (status != PM_RET_SUCCESS) + return status; + + if (enable) + api_id = PM_CLOCK_ENABLE; + else + api_id = PM_CLOCK_DISABLE; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD2(payload, api_id, clock_id); + status = pm_ipi_send_sync(primary_proc, payload, NULL, 0); + + /* If action fails due to the lack of permissions filter the error */ + if (status == PM_RET_ERROR_ACCESS) + status = PM_RET_SUCCESS; + + return status; +} + +/** + * pm_clock_enable() - Enable the clock for given id + * @clock_id: Id of the clock to be enabled + * + * This function is used by master to enable the clock + * including peripherals and PLL clocks. + * + * @return: Error if an argument is not valid or status as returned by the + * pm_clock_gate + */ +enum pm_ret_status pm_clock_enable(unsigned int clock_id) +{ + struct pm_pll *pll; + + /* First try to handle it as a PLL */ + pll = pm_clock_get_pll(clock_id); + if (pll) + return pm_clock_pll_enable(pll); + + /* It's an on-chip clock, PMU should configure clock's gate */ + return pm_clock_gate(clock_id, 1); +} + +/** + * pm_clock_disable - Disable the clock for given id + * @clock_id: Id of the clock to be disable + * + * This function is used by master to disable the clock + * including peripherals and PLL clocks. + * + * @return: Error if an argument is not valid or status as returned by the + * pm_clock_gate + */ +enum pm_ret_status pm_clock_disable(unsigned int clock_id) +{ + struct pm_pll *pll; + + /* First try to handle it as a PLL */ + pll = pm_clock_get_pll(clock_id); + if (pll) + return pm_clock_pll_disable(pll); + + /* It's an on-chip clock, PMU should configure clock's gate */ + return pm_clock_gate(clock_id, 0); +} + +/** + * pm_clock_getstate - Get the clock state for given id + * @clock_id: Id of the clock to be queried + * @state: 1/0 (Enabled/Disabled) + * + * This function is used by master to get the state of clock + * including peripherals and PLL clocks. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_getstate(unsigned int clock_id, + unsigned int *state) +{ + struct pm_pll *pll; + uint32_t payload[PAYLOAD_ARG_CNT]; + enum pm_ret_status status; + + /* First try to handle it as a PLL */ + pll = pm_clock_get_pll(clock_id); + if (pll) + return pm_clock_pll_get_state(pll, state); + + /* Check if clock ID is a valid on-chip clock */ + status = pm_clock_id_is_valid(clock_id); + if (status != PM_RET_SUCCESS) + return status; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id); + return pm_ipi_send_sync(primary_proc, payload, state, 1); +} + +/** + * pm_clock_setdivider - Set the clock divider for given id + * @clock_id: Id of the clock + * @divider: divider value + * + * This function is used by master to set divider for any clock + * to achieve desired rate. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_setdivider(unsigned int clock_id, + unsigned int divider) +{ + enum pm_ret_status status; + enum pm_node_id nid; + enum pm_clock_div_id div_id; + uint32_t payload[PAYLOAD_ARG_CNT]; + const uint32_t div0 = 0xFFFF0000; + const uint32_t div1 = 0x0000FFFF; + uint32_t val; + + /* Get PLL node ID using PLL clock ID */ + status = pm_clock_get_pll_node_id(clock_id, &nid); + if (status == PM_RET_SUCCESS) + return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider); + + /* Check if clock ID is a valid on-chip clock */ + status = pm_clock_id_is_valid(clock_id); + if (status != PM_RET_SUCCESS) + return status; + + if (div0 == (divider & div0)) { + div_id = PM_CLOCK_DIV0_ID; + val = divider & ~div0; + } else if (div1 == (divider & div1)) { + div_id = PM_CLOCK_DIV1_ID; + val = (divider & ~div1) >> 16; + } else { + return PM_RET_ERROR_ARGS; + } + + /* Send request to the PMU */ + PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_getdivider - Get the clock divider for given id + * @clock_id: Id of the clock + * @divider: divider value + * + * This function is used by master to get divider values + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_getdivider(unsigned int clock_id, + unsigned int *divider) +{ + enum pm_ret_status status; + enum pm_node_id nid; + uint32_t payload[PAYLOAD_ARG_CNT]; + uint32_t val; + + /* Get PLL node ID using PLL clock ID */ + status = pm_clock_get_pll_node_id(clock_id, &nid); + if (status == PM_RET_SUCCESS) + return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider); + + /* Check if clock ID is a valid on-chip clock */ + status = pm_clock_id_is_valid(clock_id); + if (status != PM_RET_SUCCESS) + return status; + + if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) { + /* Send request to the PMU to get div0 */ + PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id, + PM_CLOCK_DIV0_ID); + status = pm_ipi_send_sync(primary_proc, payload, &val, 1); + if (status != PM_RET_SUCCESS) + return status; + *divider = val; + } + + if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) { + /* Send request to the PMU to get div1 */ + PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id, + PM_CLOCK_DIV1_ID); + status = pm_ipi_send_sync(primary_proc, payload, &val, 1); + if (status != PM_RET_SUCCESS) + return status; + *divider |= val << 16; + } + + return status; +} + +/** + * pm_clock_setrate - Set the clock rate for given id + * @clock_id: Id of the clock + * @rate: rate value in hz + * + * This function is used by master to set rate for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_setrate(unsigned int clock_id, + uint64_t rate) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_clock_getrate - Get the clock rate for given id + * @clock_id: Id of the clock + * @rate: rate value in hz + * + * This function is used by master to get rate + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_getrate(unsigned int clock_id, + uint64_t *rate) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_clock_setparent - Set the clock parent for given id + * @clock_id: Id of the clock + * @parent_index: Index of the parent clock into clock's parents array + * + * This function is used by master to set parent for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_setparent(unsigned int clock_id, + unsigned int parent_index) +{ + struct pm_pll *pll; + uint32_t payload[PAYLOAD_ARG_CNT]; + enum pm_ret_status status; + + /* First try to handle it as a PLL */ + pll = pm_clock_get_pll_by_related_clk(clock_id); + if (pll) + return pm_clock_pll_set_parent(pll, clock_id, parent_index); + + /* Check if clock ID is a valid on-chip clock */ + status = pm_clock_id_is_valid(clock_id); + if (status != PM_RET_SUCCESS) + return status; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_getparent - Get the clock parent for given id + * @clock_id: Id of the clock + * @parent_index: parent index + * + * This function is used by master to get parent index + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_getparent(unsigned int clock_id, + unsigned int *parent_index) +{ + struct pm_pll *pll; + uint32_t payload[PAYLOAD_ARG_CNT]; + enum pm_ret_status status; + + /* First try to handle it as a PLL */ + pll = pm_clock_get_pll_by_related_clk(clock_id); + if (pll) + return pm_clock_pll_get_parent(pll, clock_id, parent_index); + + /* Check if clock ID is a valid on-chip clock */ + status = pm_clock_id_is_valid(clock_id); + if (status != PM_RET_SUCCESS) + return status; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id); + return pm_ipi_send_sync(primary_proc, payload, parent_index, 1); +} + +/** + * pm_pinctrl_get_num_pins - PM call to request number of pins + * @npins: Number of pins + * + * This function is used by master to get number of pins + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins) +{ + return pm_api_pinctrl_get_num_pins(npins); +} + +/** + * pm_pinctrl_get_num_functions - PM call to request number of functions + * @nfuncs: Number of functions + * + * This function is used by master to get number of functions + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs) +{ + return pm_api_pinctrl_get_num_functions(nfuncs); +} + +/** + * pm_pinctrl_get_num_function_groups - PM call to request number of + * function groups + * @fid: Id of function + * @ngroups: Number of function groups + * + * This function is used by master to get number of function groups specified + * by given function Id + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid, + uint32_t *ngroups) +{ + return pm_api_pinctrl_get_num_func_groups(fid, ngroups); +} + +/** + * pm_pinctrl_get_function_name - PM call to request function name + * @fid: Id of function + * @name: Name of function + * + * This function is used by master to get name of function specified + * by given function Id + */ +static void pm_pinctrl_get_function_name(unsigned int fid, char *name) +{ + pm_api_pinctrl_get_function_name(fid, name); +} + +/** + * pm_pinctrl_get_function_groups - PM call to request function groups + * @fid: Id of function + * @index: Index of next function groups + * @groups: Function groups + * + * This function is used by master to get function groups specified + * by given function Id. This API will return 6 function groups with + * a single response. To get other function groups, master should call + * same API in loop with new function groups index till error is returned. + * + * E.g First call should have index 0 which will return function groups + * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return + * function groups 6, 7, 8, 9, 10 and 11 and so on. + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_pinctrl_get_function_groups(unsigned int fid, + unsigned int index, + uint16_t *groups) +{ + return pm_api_pinctrl_get_function_groups(fid, index, groups); +} + +/** + * pm_pinctrl_get_pin_groups - PM call to request pin groups + * @pin_id: Id of pin + * @index: Index of next pin groups + * @groups: pin groups + * + * This function is used by master to get pin groups specified + * by given pin Id. This API will return 6 pin groups with + * a single response. To get other pin groups, master should call + * same API in loop with new pin groups index till error is returned. + * + * E.g First call should have index 0 which will return pin groups + * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return + * pin groups 6, 7, 8, 9, 10 and 11 and so on. + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id, + unsigned int index, + uint16_t *groups) +{ + return pm_api_pinctrl_get_pin_groups(pin_id, index, groups); +} + +/** + * pm_query_data() - PM API for querying firmware data + * @arg1 Argument 1 to requested IOCTL call + * @arg2 Argument 2 to requested IOCTL call + * @arg3 Argument 3 to requested IOCTL call + * @arg4 Argument 4 to requested IOCTL call + * @data Returned output data + * + * This function returns requested data. + */ +void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2, + unsigned int arg3, unsigned int *data) +{ + switch (qid) { + case PM_QID_CLOCK_GET_NAME: + pm_clock_get_name(arg1, (char *)data); + break; + case PM_QID_CLOCK_GET_TOPOLOGY: + data[0] = pm_clock_get_topology(arg1, arg2, &data[1]); + break; + case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS: + data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1], + &data[2]); + break; + case PM_QID_CLOCK_GET_PARENTS: + data[0] = pm_clock_get_parents(arg1, arg2, &data[1]); + break; + case PM_QID_CLOCK_GET_ATTRIBUTES: + data[0] = pm_clock_get_attributes(arg1, &data[1]); + break; + case PM_QID_PINCTRL_GET_NUM_PINS: + data[0] = pm_pinctrl_get_num_pins(&data[1]); + break; + case PM_QID_PINCTRL_GET_NUM_FUNCTIONS: + data[0] = pm_pinctrl_get_num_functions(&data[1]); + break; + case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS: + data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]); + break; + case PM_QID_PINCTRL_GET_FUNCTION_NAME: + pm_pinctrl_get_function_name(arg1, (char *)data); + break; + case PM_QID_PINCTRL_GET_FUNCTION_GROUPS: + data[0] = pm_pinctrl_get_function_groups(arg1, arg2, + (uint16_t *)&data[1]); + break; + case PM_QID_PINCTRL_GET_PIN_GROUPS: + data[0] = pm_pinctrl_get_pin_groups(arg1, arg2, + (uint16_t *)&data[1]); + break; + case PM_QID_CLOCK_GET_NUM_CLOCKS: + data[0] = pm_clock_get_num_clocks(&data[1]); + break; + + case PM_QID_CLOCK_GET_MAX_DIVISOR: + data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]); + break; + default: + data[0] = PM_RET_ERROR_ARGS; + WARN("Unimplemented query service call: 0x%x\n", qid); + } +} + +enum pm_ret_status pm_sha_hash(uint32_t address_high, + uint32_t address_low, + uint32_t size, + uint32_t flags) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low, + size, flags); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +enum pm_ret_status pm_rsa_core(uint32_t address_high, + uint32_t address_low, + uint32_t size, + uint32_t flags) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low, + size, flags); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +enum pm_ret_status pm_secure_image(uint32_t address_low, + uint32_t address_high, + uint32_t key_lo, + uint32_t key_hi, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low, + key_hi, key_lo); + return pm_ipi_send_sync(primary_proc, payload, value, 2); +} + +/** + * pm_fpga_read - Perform the fpga configuration readback + * + * @reg_numframes: Configuration register offset (or) Number of frames to read + * @address_low: lower 32-bit Linear memory space address + * @address_high: higher 32-bit Linear memory space address + * @readback_type: Type of fpga readback operation + * 0 -- Configuration Register readback + * 1 -- Configuration Data readback + * @value: Value to read + * + * This function provides access to the xilfpga library to read + * the PL configuration. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_fpga_read(uint32_t reg_numframes, + uint32_t address_low, + uint32_t address_high, + uint32_t readback_type, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low, + address_high, readback_type); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/* + * pm_pll_set_parameter() - Set the PLL parameter value + * @nid Node id of the target PLL + * @param_id ID of the PLL parameter + * @value Parameter value to be set + * + * Setting the parameter will have physical effect once the PLL mode is set to + * integer or fractional. + * + * @return Error if an argument is not valid or status as returned by the + * PM controller (PMU) + */ +enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid, + enum pm_pll_param param_id, + unsigned int value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Check if given node ID is a PLL node */ + if (nid < NODE_APLL || nid > NODE_IOPLL) + return PM_RET_ERROR_ARGS; + + /* Check if parameter ID is valid and return an error if it's not */ + if (param_id >= PM_PLL_PARAM_MAX) + return PM_RET_ERROR_ARGS; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pll_get_parameter() - Get the PLL parameter value + * @nid Node id of the target PLL + * @param_id ID of the PLL parameter + * @value Location to store the parameter value + * + * @return Error if an argument is not valid or status as returned by the + * PM controller (PMU) + */ +enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid, + enum pm_pll_param param_id, + unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Check if given node ID is a PLL node */ + if (nid < NODE_APLL || nid > NODE_IOPLL) + return PM_RET_ERROR_ARGS; + + /* Check if parameter ID is valid and return an error if it's not */ + if (param_id >= PM_PLL_PARAM_MAX) + return PM_RET_ERROR_ARGS; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/** + * pm_pll_set_mode() - Set the PLL mode + * @nid Node id of the target PLL + * @mode PLL mode to be set + * + * If reset mode is set the PM controller will first bypass the PLL and then + * assert the reset. If integer or fractional mode is set the PM controller will + * ensure that the complete PLL programming sequence is satisfied. After this + * function returns success the PLL is locked and its bypass is deasserted. + * + * @return Error if an argument is not valid or status as returned by the + * PM controller (PMU) + */ +enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Check if given node ID is a PLL node */ + if (nid < NODE_APLL || nid > NODE_IOPLL) + return PM_RET_ERROR_ARGS; + + /* Check if PLL mode is valid */ + if (mode >= PM_PLL_MODE_MAX) + return PM_RET_ERROR_ARGS; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pll_get_mode() - Get the PLL mode + * @nid Node id of the target PLL + * @mode Location to store the mode of the PLL + * + * @return Error if an argument is not valid or status as returned by the + * PM controller (PMU) + */ +enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Check if given node ID is a PLL node */ + if (nid < NODE_APLL || nid > NODE_IOPLL) + return PM_RET_ERROR_ARGS; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid); + return pm_ipi_send_sync(primary_proc, payload, mode, 1); +} + +/** + * pm_register_access() - PM API for register read/write access data + * + * @register_access_id Register_access_id which says register read/write + * + * @address Address of the register to be accessed + * + * @mask Mask value to be used while writing value + * + * @value Value to be written to register + * + * @out Returned output data + * + * This function returns requested data. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_register_access(unsigned int register_access_id, + unsigned int address, + unsigned int mask, + unsigned int value, + unsigned int *out) +{ + enum pm_ret_status ret; + + if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) && + ((CSUDMA_BASE & address) != CSUDMA_BASE) && + ((RSA_CORE_BASE & address) != RSA_CORE_BASE) && + ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) + return PM_RET_ERROR_ACCESS; + + switch (register_access_id) { + case CONFIG_REG_WRITE: + ret = pm_mmio_write(address, mask, value); + break; + case CONFIG_REG_READ: + ret = pm_mmio_read(address, out); + break; + default: + ret = PM_RET_ERROR_ARGS; + WARN("Unimplemented register_access call\n\r"); + } + return ret; +} + +/** + * pm_efuse_access() - To program or read efuse bits. + * + * This function provides access to the xilskey library to program/read + * efuse bits. + * + * address_low: lower 32-bit Linear memory space address + * address_high: higher 32-bit Linear memory space address + * + * value: Returned output value + * + * @return Returns status, either success or error+reason + * + */ +enum pm_ret_status pm_efuse_access(uint32_t address_high, + uint32_t address_low, + uint32_t *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low); + + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +enum pm_ret_status em_set_action(unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + EM_PACK_PAYLOAD1(payload, EM_SET_ACTION); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +enum pm_ret_status em_remove_action(unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +enum pm_ret_status em_send_errors(unsigned int *value) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS); + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h new file mode 100644 index 0000000..48b3877 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_API_SYS_H +#define PM_API_SYS_H + +#include + +#include "pm_defs.h" + +enum pm_query_id { + PM_QID_INVALID, + PM_QID_CLOCK_GET_NAME, + PM_QID_CLOCK_GET_TOPOLOGY, + PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS, + PM_QID_CLOCK_GET_PARENTS, + PM_QID_CLOCK_GET_ATTRIBUTES, + PM_QID_PINCTRL_GET_NUM_PINS, + PM_QID_PINCTRL_GET_NUM_FUNCTIONS, + PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS, + PM_QID_PINCTRL_GET_FUNCTION_NAME, + PM_QID_PINCTRL_GET_FUNCTION_GROUPS, + PM_QID_PINCTRL_GET_PIN_GROUPS, + PM_QID_CLOCK_GET_NUM_CLOCKS, + PM_QID_CLOCK_GET_MAX_DIVISOR, +}; + +enum pm_register_access_id { + CONFIG_REG_WRITE, + CONFIG_REG_READ, +}; + +/** + * Assigning of argument values into array elements. + */ +#define PM_PACK_PAYLOAD1(pl, arg0) { \ + pl[0] = (uint32_t)(arg0); \ +} + +#define PM_PACK_PAYLOAD2(pl, arg0, arg1) { \ + pl[1] = (uint32_t)(arg1); \ + PM_PACK_PAYLOAD1(pl, arg0); \ +} + +#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) { \ + pl[2] = (uint32_t)(arg2); \ + PM_PACK_PAYLOAD2(pl, arg0, arg1); \ +} + +#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) { \ + pl[3] = (uint32_t)(arg3); \ + PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2); \ +} + +#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) { \ + pl[4] = (uint32_t)(arg4); \ + PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3); \ +} + +#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) { \ + pl[5] = (uint32_t)(arg5); \ + PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \ +} + +/********************************************************** + * System-level API function declarations + **********************************************************/ +enum pm_ret_status pm_req_suspend(enum pm_node_id nid, + enum pm_request_ack ack, + unsigned int latency, + unsigned int state); + +enum pm_ret_status pm_self_suspend(enum pm_node_id nid, + unsigned int latency, + unsigned int state, + uintptr_t address); + +enum pm_ret_status pm_force_powerdown(enum pm_node_id nid, + enum pm_request_ack ack); + +enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason); + +enum pm_ret_status pm_req_wakeup(enum pm_node_id nid, + unsigned int set_address, + uintptr_t address, + enum pm_request_ack ack); + +enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target, + enum pm_node_id wkup_node, + unsigned int enable); + +enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype); + +enum pm_ret_status pm_init_suspend_cb(enum pm_suspend_reason reason, + unsigned int latency, + unsigned int state, + unsigned int timeout); + +/* API functions for managing PM Slaves */ +enum pm_ret_status pm_req_node(enum pm_node_id nid, + unsigned int capabilities, + unsigned int qos, + enum pm_request_ack ack); + +enum pm_ret_status pm_set_requirement(enum pm_node_id nid, + unsigned int capabilities, + unsigned int qos, + enum pm_request_ack ack); + +/* Miscellaneous API functions */ +enum pm_ret_status pm_get_api_version(unsigned int *version); +enum pm_ret_status pm_get_node_status(enum pm_node_id node, + uint32_t *ret_buff); +enum pm_ret_status pm_acknowledge_cb(enum pm_node_id nid, + enum pm_ret_status status, + unsigned int oppoint); +enum pm_ret_status pm_notify_cb(enum pm_node_id nid, + unsigned int event, + unsigned int oppoint); + +/* Direct-Control API functions */ +enum pm_ret_status pm_mmio_write(uintptr_t address, + unsigned int mask, + unsigned int value); +enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value); +enum pm_ret_status pm_fpga_load(uint32_t address_low, + uint32_t address_high, + uint32_t size, + uint32_t flags); +enum pm_ret_status pm_fpga_get_status(unsigned int *value); + +enum pm_ret_status pm_get_chipid(uint32_t *value); +enum pm_ret_status pm_secure_rsaaes(uint32_t address_high, + uint32_t address_low, + uint32_t size, + uint32_t flags); +unsigned int pm_get_shutdown_scope(void); +void pm_get_callbackdata(uint32_t *data, size_t count); +enum pm_ret_status pm_ioctl(enum pm_node_id nid, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value); +enum pm_ret_status pm_clock_enable(unsigned int clock_id); +enum pm_ret_status pm_clock_disable(unsigned int clock_id); +enum pm_ret_status pm_clock_getstate(unsigned int clock_id, + unsigned int *state); +enum pm_ret_status pm_clock_setdivider(unsigned int clock_id, + unsigned int divider); +enum pm_ret_status pm_clock_getdivider(unsigned int clock_id, + unsigned int *divider); +enum pm_ret_status pm_clock_setrate(unsigned int clock_id, + uint64_t rate); +enum pm_ret_status pm_clock_getrate(unsigned int clock_id, + uint64_t *rate); +enum pm_ret_status pm_clock_setparent(unsigned int clock_id, + unsigned int parent_id); +enum pm_ret_status pm_clock_getparent(unsigned int clock_id, + unsigned int *parent_id); +void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2, + unsigned int arg3, unsigned int *data); +enum pm_ret_status pm_sha_hash(uint32_t address_high, + uint32_t address_low, + uint32_t size, + uint32_t flags); +enum pm_ret_status pm_rsa_core(uint32_t address_high, + uint32_t address_low, + uint32_t size, + uint32_t flags); +enum pm_ret_status pm_secure_image(uint32_t address_low, + uint32_t address_high, + uint32_t key_lo, + uint32_t key_hi, + uint32_t *value); +enum pm_ret_status pm_fpga_read(uint32_t reg_numframes, + uint32_t address_low, + uint32_t address_high, + uint32_t readback_type, + uint32_t *value); +enum pm_ret_status pm_aes_engine(uint32_t address_high, + uint32_t address_low, + uint32_t *value); +enum pm_ret_status pm_register_access(unsigned int register_access_id, + unsigned int address, + unsigned int mask, + unsigned int value, + unsigned int *out); +enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid, + enum pm_pll_param param_id, + unsigned int value); +enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid, + enum pm_pll_param param_id, + unsigned int *value); +enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode); +enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode); +enum pm_ret_status pm_efuse_access(uint32_t address_high, + uint32_t address_low, uint32_t *value); +enum pm_ret_status em_set_action(unsigned int *value); +enum pm_ret_status em_remove_action(unsigned int *value); +enum pm_ret_status em_send_errors(unsigned int *value); +enum pm_ret_status pm_feature_config(unsigned int ioctl_id, + unsigned int config_id, + unsigned int value, + unsigned int *response); +enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version, + uint32_t *bit_mask, uint8_t len); +enum pm_ret_status check_api_dependency(uint8_t id); + +#endif /* PM_API_SYS_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c new file mode 100644 index 0000000..163e891 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * APU specific definition of processors in the subsystem as well as functions + * for getting information about and changing state of the APU. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_ipi.h" + +#define IRQ_MAX 84 +#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1) +#define UNDEFINED_CPUID (~0) + +#define PM_SUSPEND_MODE_STD 0 +#define PM_SUSPEND_MODE_POWER_OFF 1 + +DEFINE_BAKERY_LOCK(pm_client_secure_lock); + +extern const struct pm_ipi apu_ipi; + +const struct pm_ipi apu_ipi = { + .local_ipi_id = IPI_ID_APU, + .remote_ipi_id = IPI_ID_PMU0, + .buffer_base = IPI_BUFFER_APU_BASE, +}; + +static uint32_t suspend_mode = PM_SUSPEND_MODE_STD; + +/* Order in pm_procs_all array must match cpu ids */ +static const struct pm_proc pm_procs_all[] = { + { + .node_id = NODE_APU_0, + .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK, + .ipi = &apu_ipi, + }, + { + .node_id = NODE_APU_1, + .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK, + .ipi = &apu_ipi, + }, + { + .node_id = NODE_APU_2, + .pwrdn_mask = APU_2_PWRCTL_CPUPWRDWNREQ_MASK, + .ipi = &apu_ipi, + }, + { + .node_id = NODE_APU_3, + .pwrdn_mask = APU_3_PWRCTL_CPUPWRDWNREQ_MASK, + .ipi = &apu_ipi, + }, +}; + +/* Interrupt to PM node ID map */ +static enum pm_node_id irq_node_map[IRQ_MAX + 1] = { + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 3 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 7 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 11 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_NAND, + NODE_QSPI, /* 15 */ + NODE_GPIO, + NODE_I2C_0, + NODE_I2C_1, + NODE_SPI_0, /* 19 */ + NODE_SPI_1, + NODE_UART_0, + NODE_UART_1, + NODE_CAN_0, /* 23 */ + NODE_CAN_1, + NODE_UNKNOWN, + NODE_RTC, + NODE_RTC, /* 27 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 31 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 35, NODE_IPI_APU */ + NODE_TTC_0, + NODE_TTC_0, + NODE_TTC_0, + NODE_TTC_1, /* 39 */ + NODE_TTC_1, + NODE_TTC_1, + NODE_TTC_2, + NODE_TTC_2, /* 43 */ + NODE_TTC_2, + NODE_TTC_3, + NODE_TTC_3, + NODE_TTC_3, /* 47 */ + NODE_SD_0, + NODE_SD_1, + NODE_SD_0, + NODE_SD_1, /* 51 */ + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, + NODE_UNKNOWN, /* 55 */ + NODE_UNKNOWN, + NODE_ETH_0, + NODE_ETH_0, + NODE_ETH_1, /* 59 */ + NODE_ETH_1, + NODE_ETH_2, + NODE_ETH_2, + NODE_ETH_3, /* 63 */ + NODE_ETH_3, + NODE_USB_0, + NODE_USB_0, + NODE_USB_0, /* 67 */ + NODE_USB_0, + NODE_USB_0, + NODE_USB_1, + NODE_USB_1, /* 71 */ + NODE_USB_1, + NODE_USB_1, + NODE_USB_1, + NODE_USB_0, /* 75 */ + NODE_USB_0, + NODE_ADMA, + NODE_ADMA, + NODE_ADMA, /* 79 */ + NODE_ADMA, + NODE_ADMA, + NODE_ADMA, + NODE_ADMA, /* 83 */ + NODE_ADMA, +}; + +/** + * irq_to_pm_node - Get PM node ID corresponding to the interrupt number + * @irq: Interrupt number + * + * Return: PM node ID corresponding to the specified interrupt + */ +static enum pm_node_id irq_to_pm_node(unsigned int irq) +{ + assert(irq <= IRQ_MAX); + return irq_node_map[irq]; +} + +/** + * pm_client_set_wakeup_sources - Set all slaves with enabled interrupts as wake + * sources in the PMU firmware + */ +static void pm_client_set_wakeup_sources(void) +{ + uint32_t reg_num; + uint8_t pm_wakeup_nodes_set[NODE_MAX]; + uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4; + + /* In case of power-off suspend, only NODE_EXTERN must be set */ + if (suspend_mode == PM_SUSPEND_MODE_POWER_OFF) { + enum pm_ret_status ret; + + ret = pm_set_wakeup_source(NODE_APU, NODE_EXTERN, 1); + /** + * If NODE_EXTERN could not be set as wake source, proceed with + * standard suspend (no one will wake the system otherwise) + */ + if (ret == PM_RET_SUCCESS) + return; + } + + zeromem(&pm_wakeup_nodes_set, sizeof(pm_wakeup_nodes_set)); + + for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) { + uint32_t base_irq = reg_num << ISENABLER_SHIFT; + uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2)); + + if (!reg) + continue; + + while (reg) { + enum pm_node_id node; + uint32_t idx, ret, irq, lowest_set = reg & (-reg); + + idx = __builtin_ctz(lowest_set); + irq = base_irq + idx; + + if (irq > IRQ_MAX) + break; + + node = irq_to_pm_node(irq); + reg &= ~lowest_set; + + if ((node != NODE_UNKNOWN) && + (!pm_wakeup_nodes_set[node])) { + ret = pm_set_wakeup_source(NODE_APU, node, 1); + pm_wakeup_nodes_set[node] = !ret; + } + } + } +} + +/** + * pm_get_proc() - returns pointer to the proc structure + * @cpuid: id of the cpu whose proc struct pointer should be returned + * + * Return: pointer to a proc structure if proc is found, otherwise NULL + */ +const struct pm_proc *pm_get_proc(unsigned int cpuid) +{ + if (cpuid < ARRAY_SIZE(pm_procs_all)) + return &pm_procs_all[cpuid]; + + return NULL; +} + +/** + * pm_get_proc_by_node() - returns pointer to the proc structure + * @nid: node id of the processor + * + * Return: pointer to a proc structure if proc is found, otherwise NULL + */ +const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid) +{ + for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) { + if (nid == pm_procs_all[i].node_id) + return &pm_procs_all[i]; + } + return NULL; +} + +/** + * pm_get_cpuid() - get the local cpu ID for a global node ID + * @nid: node id of the processor + * + * Return: the cpu ID (starting from 0) for the subsystem + */ +static unsigned int pm_get_cpuid(enum pm_node_id nid) +{ + for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) { + if (pm_procs_all[i].node_id == nid) + return i; + } + return UNDEFINED_CPUID; +} + +const struct pm_proc *primary_proc = &pm_procs_all[0]; + +/** + * pm_client_suspend() - Client-specific suspend actions + * + * This function should contain any PU-specific actions + * required prior to sending suspend request to PMU + * Actions taken depend on the state system is suspending to. + */ +void pm_client_suspend(const struct pm_proc *proc, unsigned int state) +{ + bakery_lock_get(&pm_client_secure_lock); + + if (state == PM_STATE_SUSPEND_TO_RAM) + pm_client_set_wakeup_sources(); + + /* Set powerdown request */ + mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask); + + bakery_lock_release(&pm_client_secure_lock); +} + + +/** + * pm_client_abort_suspend() - Client-specific abort-suspend actions + * + * This function should contain any PU-specific actions + * required for aborting a prior suspend request + */ +void pm_client_abort_suspend(void) +{ + /* Enable interrupts at processor level (for current cpu) */ + gicv2_cpuif_enable(); + + bakery_lock_get(&pm_client_secure_lock); + + /* Clear powerdown request */ + mmio_write_32(APU_PWRCTL, + mmio_read_32(APU_PWRCTL) & ~primary_proc->pwrdn_mask); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_client_wakeup() - Client-specific wakeup actions + * + * This function should contain any PU-specific actions + * required for waking up another APU core + */ +void pm_client_wakeup(const struct pm_proc *proc) +{ + unsigned int cpuid = pm_get_cpuid(proc->node_id); + + if (cpuid == UNDEFINED_CPUID) + return; + + bakery_lock_get(&pm_client_secure_lock); + + /* clear powerdown bit for affected cpu */ + uint32_t val = mmio_read_32(APU_PWRCTL); + val &= ~(proc->pwrdn_mask); + mmio_write_32(APU_PWRCTL, val); + + bakery_lock_release(&pm_client_secure_lock); +} + +enum pm_ret_status pm_set_suspend_mode(uint32_t mode) +{ + if ((mode != PM_SUSPEND_MODE_STD) && + (mode != PM_SUSPEND_MODE_POWER_OFF)) + return PM_RET_ERROR_ARGS; + + suspend_mode = mode; + return PM_RET_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h new file mode 100644 index 0000000..8eb197a --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* ZynqMP power management enums and defines */ + +#ifndef PM_DEFS_H +#define PM_DEFS_H + +/********************************************************************* + * Macro definitions + ********************************************************************/ + +/* + * Version number is a 32bit value, like: + * (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR + */ +#define PM_VERSION_MAJOR 1 +#define PM_VERSION_MINOR 1 + +#define PM_VERSION ((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR) + +/** + * PM API versions + */ +/* Expected version of firmware APIs */ +#define FW_API_BASE_VERSION (1U) +/* Expected version of firmware API for feature check */ +#define FW_API_VERSION_2 (2U) +/* Version of APIs implemented in ATF */ +#define ATF_API_BASE_VERSION (1U) + +/* Capabilities for RAM */ +#define PM_CAP_ACCESS 0x1U +#define PM_CAP_CONTEXT 0x2U + +#define MAX_LATENCY (~0U) +#define MAX_QOS 100U + +/* State arguments of the self suspend */ +#define PM_STATE_CPU_IDLE 0x0U +#define PM_STATE_SUSPEND_TO_RAM 0xFU + +/* APU processor states */ +#define PM_PROC_STATE_FORCEDOFF 0U +#define PM_PROC_STATE_ACTIVE 1U +#define PM_PROC_STATE_SLEEP 2U +#define PM_PROC_STATE_SUSPENDING 3U + +#define EM_FUNID_NUM_MASK 0xF0000U + +#define PM_GET_CALLBACK_DATA 0xa01 +#define PM_SET_SUSPEND_MODE 0xa02 +#define PM_GET_TRUSTZONE_VERSION 0xa03 + +/********************************************************************* + * Enum definitions + ********************************************************************/ + +enum pm_api_id { + /* Miscellaneous API functions: */ + PM_GET_API_VERSION = 1, /* Do not change or move */ + PM_SET_CONFIGURATION, + PM_GET_NODE_STATUS, + PM_GET_OP_CHARACTERISTIC, + PM_REGISTER_NOTIFIER, + /* API for suspending of PUs: */ + PM_REQ_SUSPEND, + PM_SELF_SUSPEND, + PM_FORCE_POWERDOWN, + PM_ABORT_SUSPEND, + PM_REQ_WAKEUP, + PM_SET_WAKEUP_SOURCE, + PM_SYSTEM_SHUTDOWN, + /* API for managing PM slaves: */ + PM_REQ_NODE, + PM_RELEASE_NODE, + PM_SET_REQUIREMENT, + PM_SET_MAX_LATENCY, + /* Direct control API functions: */ + PM_RESET_ASSERT, + PM_RESET_GET_STATUS, + PM_MMIO_WRITE, + PM_MMIO_READ, + PM_INIT_FINALIZE, + PM_FPGA_LOAD, + PM_FPGA_GET_STATUS, + PM_GET_CHIPID, + PM_SECURE_RSA_AES, + PM_SECURE_SHA, + PM_SECURE_RSA, + PM_PINCTRL_REQUEST, + PM_PINCTRL_RELEASE, + PM_PINCTRL_GET_FUNCTION, + PM_PINCTRL_SET_FUNCTION, + PM_PINCTRL_CONFIG_PARAM_GET, + PM_PINCTRL_CONFIG_PARAM_SET, + PM_IOCTL, + /* API to query information from firmware */ + PM_QUERY_DATA, + /* Clock control API functions */ + PM_CLOCK_ENABLE, + PM_CLOCK_DISABLE, + PM_CLOCK_GETSTATE, + PM_CLOCK_SETDIVIDER, + PM_CLOCK_GETDIVIDER, + PM_CLOCK_SETRATE, + PM_CLOCK_GETRATE, + PM_CLOCK_SETPARENT, + PM_CLOCK_GETPARENT, + PM_SECURE_IMAGE, + /* FPGA PL Readback */ + PM_FPGA_READ, + PM_SECURE_AES, + /* PLL control API functions */ + PM_PLL_SET_PARAMETER, + PM_PLL_GET_PARAMETER, + PM_PLL_SET_MODE, + PM_PLL_GET_MODE, + /* PM Register Access API */ + PM_REGISTER_ACCESS, + PM_EFUSE_ACCESS, + PM_FPGA_GET_VERSION, + PM_FPGA_GET_FEATURE_LIST, + PM_FEATURE_CHECK = 63, + PM_API_MAX +}; + +enum pm_node_id { + NODE_UNKNOWN = 0, + NODE_APU, + NODE_APU_0, + NODE_APU_1, + NODE_APU_2, + NODE_APU_3, + NODE_RPU, + NODE_RPU_0, + NODE_RPU_1, + NODE_PLD, + NODE_FPD, + NODE_OCM_BANK_0, + NODE_OCM_BANK_1, + NODE_OCM_BANK_2, + NODE_OCM_BANK_3, + NODE_TCM_0_A, + NODE_TCM_0_B, + NODE_TCM_1_A, + NODE_TCM_1_B, + NODE_L2, + NODE_GPU_PP_0, + NODE_GPU_PP_1, + NODE_USB_0, + NODE_USB_1, + NODE_TTC_0, + NODE_TTC_1, + NODE_TTC_2, + NODE_TTC_3, + NODE_SATA, + NODE_ETH_0, + NODE_ETH_1, + NODE_ETH_2, + NODE_ETH_3, + NODE_UART_0, + NODE_UART_1, + NODE_SPI_0, + NODE_SPI_1, + NODE_I2C_0, + NODE_I2C_1, + NODE_SD_0, + NODE_SD_1, + NODE_DP, + NODE_GDMA, + NODE_ADMA, + NODE_NAND, + NODE_QSPI, + NODE_GPIO, + NODE_CAN_0, + NODE_CAN_1, + NODE_EXTERN, + NODE_APLL, + NODE_VPLL, + NODE_DPLL, + NODE_RPLL, + NODE_IOPLL, + NODE_DDR, + NODE_IPI_APU, + NODE_IPI_RPU_0, + NODE_GPU, + NODE_PCIE, + NODE_PCAP, + NODE_RTC, + NODE_LPD, + NODE_VCU, + NODE_IPI_RPU_1, + NODE_IPI_PL_0, + NODE_IPI_PL_1, + NODE_IPI_PL_2, + NODE_IPI_PL_3, + NODE_PL, + NODE_GEM_TSU, + NODE_SWDT_0, + NODE_SWDT_1, + NODE_CSU, + NODE_PJTAG, + NODE_TRACE, + NODE_TESTSCAN, + NODE_PMU, + NODE_MAX, +}; + +enum pm_request_ack { + REQ_ACK_NO = 1, + REQ_ACK_BLOCKING, + REQ_ACK_NON_BLOCKING, +}; + +enum pm_abort_reason { + ABORT_REASON_WKUP_EVENT = 100, + ABORT_REASON_PU_BUSY, + ABORT_REASON_NO_PWRDN, + ABORT_REASON_UNKNOWN, +}; + +enum pm_suspend_reason { + SUSPEND_REASON_PU_REQ = 201, + SUSPEND_REASON_ALERT, + SUSPEND_REASON_SYS_SHUTDOWN, +}; + +enum pm_ram_state { + PM_RAM_STATE_OFF = 1, + PM_RAM_STATE_RETENTION, + PM_RAM_STATE_ON, +}; + +enum pm_opchar_type { + PM_OPCHAR_TYPE_POWER = 1, + PM_OPCHAR_TYPE_TEMP, + PM_OPCHAR_TYPE_LATENCY, +}; + +/** + * @PM_RET_SUCCESS: success + * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated) + * @PM_RET_ERROR_NOTSUPPORTED: feature not supported (deprecated) + * @PM_RET_ERROR_INTERNAL: internal error + * @PM_RET_ERROR_CONFLICT: conflict + * @PM_RET_ERROR_ACCESS: access rights violation + * @PM_RET_ERROR_INVALID_NODE: invalid node + * @PM_RET_ERROR_DOUBLE_REQ: duplicate request for same node + * @PM_RET_ERROR_ABORT_SUSPEND: suspend procedure has been aborted + * @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU + * @PM_RET_ERROR_NODE_USED: node is already in use + */ +enum pm_ret_status { + PM_RET_SUCCESS, + PM_RET_ERROR_ARGS = 1, + PM_RET_ERROR_NOTSUPPORTED = 4, + PM_RET_ERROR_INTERNAL = 2000, + PM_RET_ERROR_CONFLICT = 2001, + PM_RET_ERROR_ACCESS = 2002, + PM_RET_ERROR_INVALID_NODE = 2003, + PM_RET_ERROR_DOUBLE_REQ = 2004, + PM_RET_ERROR_ABORT_SUSPEND = 2005, + PM_RET_ERROR_TIMEOUT = 2006, + PM_RET_ERROR_NODE_USED = 2007, + PM_RET_ERROR_NO_FEATURE = 2008 +}; + +/** + * @PM_INITIAL_BOOT: boot is a fresh system startup + * @PM_RESUME: boot is a resume + * @PM_BOOT_ERROR: error, boot cause cannot be identified + */ +enum pm_boot_status { + PM_INITIAL_BOOT, + PM_RESUME, + PM_BOOT_ERROR, +}; + +/** + * @PMF_SHUTDOWN_TYPE_SHUTDOWN: shutdown + * @PMF_SHUTDOWN_TYPE_RESET: reset/reboot + * @PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY: set the shutdown/reboot scope + */ +enum pm_shutdown_type { + PMF_SHUTDOWN_TYPE_SHUTDOWN, + PMF_SHUTDOWN_TYPE_RESET, + PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY, +}; + +/** + * @PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM: shutdown/reboot APU subsystem only + * @PMF_SHUTDOWN_SUBTYPE_PS_ONLY: shutdown/reboot entire PS (but not PL) + * @PMF_SHUTDOWN_SUBTYPE_SYSTEM: shutdown/reboot entire system + */ +enum pm_shutdown_subtype { + PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM, + PMF_SHUTDOWN_SUBTYPE_PS_ONLY, + PMF_SHUTDOWN_SUBTYPE_SYSTEM, +}; + +/** + * @PM_PLL_PARAM_DIV2: Enable for divide by 2 function inside the PLL + * @PM_PLL_PARAM_FBDIV: Feedback divisor integer portion for the PLL + * @PM_PLL_PARAM_DATA: Feedback divisor fractional portion for the PLL + * @PM_PLL_PARAM_PRE_SRC: Clock source for PLL input + * @PM_PLL_PARAM_POST_SRC: Clock source for PLL Bypass mode + * @PM_PLL_PARAM_LOCK_DLY: Lock circuit config settings for lock windowsize + * @PM_PLL_PARAM_LOCK_CNT: Lock circuit counter setting + * @PM_PLL_PARAM_LFHF: PLL loop filter high frequency capacitor control + * @PM_PLL_PARAM_CP: PLL charge pump control + * @PM_PLL_PARAM_RES: PLL loop filter resistor control + */ +enum pm_pll_param { + PM_PLL_PARAM_DIV2, + PM_PLL_PARAM_FBDIV, + PM_PLL_PARAM_DATA, + PM_PLL_PARAM_PRE_SRC, + PM_PLL_PARAM_POST_SRC, + PM_PLL_PARAM_LOCK_DLY, + PM_PLL_PARAM_LOCK_CNT, + PM_PLL_PARAM_LFHF, + PM_PLL_PARAM_CP, + PM_PLL_PARAM_RES, + PM_PLL_PARAM_MAX, +}; + +/** + * @PM_PLL_MODE_RESET: PLL is in reset (not locked) + * @PM_PLL_MODE_INTEGER: PLL is locked in integer mode + * @PM_PLL_MODE_FRACTIONAL: PLL is locked in fractional mode + */ +enum pm_pll_mode { + PM_PLL_MODE_RESET, + PM_PLL_MODE_INTEGER, + PM_PLL_MODE_FRACTIONAL, + PM_PLL_MODE_MAX, +}; + +/** + * @PM_CLOCK_DIV0_ID: Clock divider 0 + * @PM_CLOCK_DIV1_ID: Clock divider 1 + */ +enum pm_clock_div_id { + PM_CLOCK_DIV0_ID, + PM_CLOCK_DIV1_ID, +}; + +/** + * EM API IDs + */ +enum em_api_id { + EM_SET_ACTION = 1, + EM_REMOVE_ACTION, + EM_SEND_ERRORS, +}; + +#endif /* PM_DEFS_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c new file mode 100644 index 0000000..d88e5fa --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Top-level SMC handler for ZynqMP power management calls and + * IPI setup functions for communication with PMU. + */ + +#include + +#include +#if ZYNQMP_WDT_RESTART +#include +#include +#include +#include +#include +#endif + +#include +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_defs.h" +#include "pm_ipi.h" + +/* pm_up = !0 - UP, pm_up = 0 - DOWN */ +static int32_t pm_up, ipi_irq_flag; + +#if ZYNQMP_WDT_RESTART +static spinlock_t inc_lock; +static int active_cores = 0; +#endif + +/** + * pm_context - Structure which contains data for power management + * @api_version version of PM API, must match with one on PMU side + * @payload payload array used to store received + * data from ipi buffer registers + */ +static struct { + uint32_t api_version; + uint32_t payload[PAYLOAD_ARG_CNT]; +} pm_ctx; + +#if ZYNQMP_WDT_RESTART +/** + * trigger_wdt_restart() - Trigger warm restart event to APU cores + * + * This function triggers SGI for all active APU CPUs. SGI handler then + * power down CPU and call system reset. + */ +static void trigger_wdt_restart(void) +{ + uint32_t core_count = 0; + uint32_t core_status[3]; + uint32_t target_cpu_list = 0; + int i; + + for (i = 0; i < 4; i++) { + pm_get_node_status(NODE_APU_0 + i, core_status); + if (core_status[0] == 1) { + core_count++; + target_cpu_list |= (1 << i); + } + } + + spin_lock(&inc_lock); + active_cores = core_count; + spin_unlock(&inc_lock); + + INFO("Active Cores: %d\n", active_cores); + + for (i = PLATFORM_CORE_COUNT - 1; i >= 0; i--) { + if (target_cpu_list & (1 << i)) { + /* trigger SGI to active cores */ + plat_ic_raise_el3_sgi(ARM_IRQ_SEC_SGI_7, i); + } + } +} + +/** + * ttc_fiq_handler() - TTC Handler for timer event + * @id number of the highest priority pending interrupt of the type + * that this handler was registered for + * @flags security state, bit[0] + * @handler pointer to 'cpu_context' structure of the current CPU for the + * security state specified in the 'flags' parameter + * @cookie unused + * + * Function registered as INTR_TYPE_EL3 interrupt handler + * + * When WDT event is received in PMU, PMU needs to notify master to do cleanup + * if required. PMU sets up timer and starts timer to overflow in zero time upon + * WDT event. ATF handles this timer event and takes necessary action required + * for warm restart. + * + * In presence of non-secure software layers (EL1/2) sets the interrupt + * at registered entrance in GIC and informs that PMU responsed or demands + * action. + */ +static uint64_t ttc_fiq_handler(uint32_t id, uint32_t flags, void *handle, + void *cookie) +{ + INFO("BL31: Got TTC FIQ\n"); + + plat_ic_end_of_interrupt(id); + + /* Clear TTC interrupt by reading interrupt register */ + mmio_read_32(TTC3_INTR_REGISTER_1); + + /* Disable the timer interrupts */ + mmio_write_32(TTC3_INTR_ENABLE_1, 0); + + trigger_wdt_restart(); + + return 0; +} + +/** + * zynqmp_sgi7_irq() - Handler for SGI7 IRQ + * @id number of the highest priority pending interrupt of the type + * that this handler was registered for + * @flags security state, bit[0] + * @handler pointer to 'cpu_context' structure of the current CPU for the + * security state specified in the 'flags' parameter + * @cookie unused + * + * Function registered as INTR_TYPE_EL3 interrupt handler + * + * On receiving WDT event from PMU, ATF generates SGI7 to all running CPUs. + * In response to SGI7 interrupt, each CPUs do clean up if required and last + * running CPU calls system restart. + */ +static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + int i; + uint32_t value; + + /* enter wfi and stay there */ + INFO("Entering wfi\n"); + + spin_lock(&inc_lock); + active_cores--; + + for (i = 0; i < 4; i++) { + mmio_write_32(BASE_GICD_BASE + GICD_CPENDSGIR + 4 * i, + 0xffffffff); + } + + spin_unlock(&inc_lock); + + if (active_cores == 0) { + pm_mmio_read(PMU_GLOBAL_GEN_STORAGE4, &value); + value = (value & RESTART_SCOPE_MASK) >> RESTART_SCOPE_SHIFT; + pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET, value); + } + + /* enter wfi and stay there */ + while (1) + wfi(); +} + +/** + * pm_wdt_restart_setup() - Setup warm restart interrupts + * + * This function sets up handler for SGI7 and TTC interrupts + * used for warm restart. + */ +static int pm_wdt_restart_setup(void) +{ + int ret; + + /* register IRQ handler for SGI7 */ + ret = request_intr_type_el3(ARM_IRQ_SEC_SGI_7, zynqmp_sgi7_irq); + if (ret) { + WARN("BL31: registering SGI7 interrupt failed\n"); + goto err; + } + + ret = request_intr_type_el3(IRQ_TTC3_1, ttc_fiq_handler); + if (ret) + WARN("BL31: registering TTC3 interrupt failed\n"); + +err: + return ret; +} +#endif + +/** + * pm_setup() - PM service setup + * + * @return On success, the initialization function must return 0. + * Any other return value will cause the framework to ignore + * the service + * + * Initialization functions for ZynqMP power management for + * communicaton with PMU. + * + * Called from sip_svc_setup initialization function with the + * rt_svc_init signature. + */ +int pm_setup(void) +{ + int status, ret; + + status = pm_ipi_init(primary_proc); + + ret = pm_get_api_version(&pm_ctx.api_version); + if (pm_ctx.api_version < PM_VERSION) { + ERROR("BL31: Platform Management API version error. Expected: " + "v%d.%d - Found: v%d.%d\n", PM_VERSION_MAJOR, + PM_VERSION_MINOR, pm_ctx.api_version >> 16, + pm_ctx.api_version & 0xFFFF); + return -EINVAL; + } + +#if ZYNQMP_WDT_RESTART + status = pm_wdt_restart_setup(); + if (status) + WARN("BL31: warm-restart setup failed\n"); +#endif + + if (status >= 0) { + INFO("BL31: PM Service Init Complete: API v%d.%d\n", + PM_VERSION_MAJOR, PM_VERSION_MINOR); + ret = 0; + } else { + INFO("BL31: PM Service Init Failed, Error Code %d!\n", status); + ret = status; + } + + pm_up = !status; + + return ret; +} + +/** + * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2. + * @smc_fid - Function Identifier + * @x1 - x4 - Arguments + * @cookie - Unused + * @handler - Pointer to caller's context structure + * + * @return - Unused + * + * Determines that smc_fid is valid and supported PM SMC Function ID from the + * list of pm_api_ids, otherwise completes the request with + * the unknown SMC Function ID + * + * The SMC calls for PM service are forwarded from SIP Service SMC handler + * function with rt_svc_handle signature + */ +uint64_t pm_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) +{ + enum pm_ret_status ret; + uint32_t payload[PAYLOAD_ARG_CNT]; + + uint32_t pm_arg[4]; + uint32_t result[PAYLOAD_ARG_CNT]; + uint32_t api_id; + + /* Handle case where PM wasn't initialized properly */ + if (!pm_up) + SMC_RET1(handle, SMC_UNK); + + pm_arg[0] = (uint32_t)x1; + pm_arg[1] = (uint32_t)(x1 >> 32); + pm_arg[2] = (uint32_t)x2; + pm_arg[3] = (uint32_t)(x2 >> 32); + pm_arg[4] = (uint32_t)x3; + + api_id = smc_fid & FUNCID_NUM_MASK; + + switch (api_id) { + /* PM API Functions */ + case PM_SELF_SUSPEND: + ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQ_SUSPEND: + ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQ_WAKEUP: + { + /* Use address flag is encoded in the 1st bit of the low-word */ + unsigned int set_addr = pm_arg[1] & 0x1; + uint64_t address = (uint64_t)pm_arg[2] << 32; + + address |= pm_arg[1] & (~0x1); + ret = pm_req_wakeup(pm_arg[0], set_addr, address, + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + } + + case PM_FORCE_POWERDOWN: + ret = pm_force_powerdown(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_ABORT_SUSPEND: + ret = pm_abort_suspend(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SET_WAKEUP_SOURCE: + ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SYSTEM_SHUTDOWN: + ret = pm_system_shutdown(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQ_NODE: + ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SET_REQUIREMENT: + ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_GET_API_VERSION: + /* Check is PM API version already verified */ + if (pm_ctx.api_version >= PM_VERSION) { + if (!ipi_irq_flag) { + /* + * Enable IPI IRQ + * assume the rich OS is OK to handle callback IRQs now. + * Even if we were wrong, it would not enable the IRQ in + * the GIC. + */ + pm_ipi_irq_enable(primary_proc); + ipi_irq_flag = 1; + } + SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | + ((uint64_t)pm_ctx.api_version << 32)); + } + + case PM_FPGA_LOAD: + ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_FPGA_GET_STATUS: + { + uint32_t value; + + ret = pm_fpga_get_status(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_SECURE_RSA_AES: + ret = pm_secure_rsaaes(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_GET_CALLBACK_DATA: + pm_get_callbackdata(result, ARRAY_SIZE(result)); + SMC_RET2(handle, + (uint64_t)result[0] | ((uint64_t)result[1] << 32), + (uint64_t)result[2] | ((uint64_t)result[3] << 32)); + case PM_IOCTL: + { + uint32_t value; + + ret = pm_ioctl(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_QUERY_DATA: + { + uint32_t data[4] = { 0 }; + + pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], data); + SMC_RET2(handle, (uint64_t)data[0] | ((uint64_t)data[1] << 32), + (uint64_t)data[2] | ((uint64_t)data[3] << 32)); + } + + case PM_CLOCK_ENABLE: + ret = pm_clock_enable(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_DISABLE: + ret = pm_clock_disable(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETSTATE: + { + uint32_t value; + + ret = pm_clock_getstate(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_CLOCK_SETDIVIDER: + ret = pm_clock_setdivider(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETDIVIDER: + { + uint32_t value; + + ret = pm_clock_getdivider(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_CLOCK_SETRATE: + ret = pm_clock_setrate(pm_arg[0], + ((uint64_t)pm_arg[2]) << 32 | pm_arg[1]); + + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETRATE: + { + uint64_t value; + + ret = pm_clock_getrate(pm_arg[0], &value); + SMC_RET2(handle, (uint64_t)ret | + (((uint64_t)value & 0xFFFFFFFFU) << 32U), + (value >> 32U) & 0xFFFFFFFFU); + + } + + case PM_CLOCK_SETPARENT: + ret = pm_clock_setparent(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETPARENT: + { + uint32_t value; + + ret = pm_clock_getparent(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_GET_TRUSTZONE_VERSION: + SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | + ((uint64_t)ZYNQMP_TZ_VERSION << 32)); + + case PM_SET_SUSPEND_MODE: + ret = pm_set_suspend_mode(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SECURE_SHA: + ret = pm_sha_hash(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SECURE_RSA: + ret = pm_rsa_core(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SECURE_IMAGE: + { + ret = pm_secure_image(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &result[0]); + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32), + result[1]); + } + + case PM_FPGA_READ: + { + uint32_t value; + + ret = pm_fpga_read(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3], + &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_SECURE_AES: + { + uint32_t value; + + ret = pm_aes_engine(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_PLL_SET_PARAMETER: + ret = pm_pll_set_parameter(pm_arg[0], pm_arg[1], pm_arg[2]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PLL_GET_PARAMETER: + { + uint32_t value; + + ret = pm_pll_get_parameter(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value << 32)); + } + + case PM_PLL_SET_MODE: + ret = pm_pll_set_mode(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PLL_GET_MODE: + { + uint32_t mode; + + ret = pm_pll_get_mode(pm_arg[0], &mode); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32)); + } + + case PM_REGISTER_ACCESS: + { + uint32_t value; + + ret = pm_register_access(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_EFUSE_ACCESS: + { + uint32_t value; + + ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_FPGA_GET_VERSION: + case PM_FPGA_GET_FEATURE_LIST: + { + uint32_t ret_payload[PAYLOAD_ARG_CNT]; + + PM_PACK_PAYLOAD5(payload, smc_fid & FUNCID_NUM_MASK, + pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); + ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, 3U); + SMC_RET2(handle, (uint64_t)ret | (uint64_t)ret_payload[0] << 32, + (uint64_t)ret_payload[1] | (uint64_t)ret_payload[2] << 32); + } + + case PM_FEATURE_CHECK: + { + uint32_t version; + uint32_t bit_mask[2] = {0}; + + ret = pm_feature_check(pm_arg[0], &version, bit_mask, + ARRAY_SIZE(bit_mask)); + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)version << 32), + (uint64_t)bit_mask[0] | ((uint64_t)bit_mask[1] << 32)); + } + + default: + /* Send request to the PMU */ + PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1], + pm_arg[2], pm_arg[3], pm_arg[4]); + ret = pm_ipi_send_sync(primary_proc, payload, result, + PAYLOAD_ARG_CNT); + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32), + (uint64_t)result[1] | ((uint64_t)result[2] << 32)); + } +} + +/** + * em_smc_handler() - SMC handler for EM-API calls coming from EL1/EL2. + * @smc_fid - Function Identifier + * @x1 - x4 - Arguments + * @cookie - Unused + * @handler - Pointer to caller's context structure + * + * @return - Unused + * + * Determines that smc_fid is valid and supported EM SMC Function ID from the + * list of em_api_ids, otherwise completes the request with + * the unknown SMC Function ID + * + * The SMC calls for EM service are forwarded from SIP Service SMC handler + * function with rt_svc_handle signature + */ +uint64_t em_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) +{ + enum pm_ret_status ret; + + switch (smc_fid & FUNCID_NUM_MASK) { + /* EM API Functions */ + case EM_SET_ACTION: + { + uint32_t value; + + ret = em_set_action(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case EM_REMOVE_ACTION: + { + uint32_t value; + + ret = em_remove_action(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case EM_SEND_ERRORS: + { + uint32_t value; + + ret = em_send_errors(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + default: + WARN("Unimplemented EM Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h new file mode 100644 index 0000000..abadd40 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_SVC_MAIN_H +#define PM_SVC_MAIN_H + +#include "pm_common.h" + +int pm_setup(void); +uint64_t pm_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); + +uint64_t em_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 /* PM_SVC_MAIN_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c b/arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c new file mode 100644 index 0000000..114da33 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */ + +#include +#include + +#include "ipi_mailbox_svc.h" +#include "pm_svc_main.h" + +/* SMC function IDs for SiP Service queries */ +#define ZYNQMP_SIP_SVC_CALL_COUNT 0x8200ff00 +#define ZYNQMP_SIP_SVC_UID 0x8200ff01 +#define ZYNQMP_SIP_SVC_VERSION 0x8200ff03 + +/* SiP Service Calls version numbers */ +#define SIP_SVC_VERSION_MAJOR 0 +#define SIP_SVC_VERSION_MINOR 1 + +/* These macros are used to identify PM, IPI calls from the SMC function ID */ +#define PM_FID_MASK 0xf000u +#define PM_FID_VALUE 0u +#define IPI_FID_VALUE 0x1000u +#define EM_FID_MASK 0xf0000u +#define EM_FID_VALUE 0xE0000u +#define is_em_fid(_fid) (((_fid) & EM_FID_MASK) == EM_FID_VALUE) +#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE) +#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE) + +/* SiP Service UUID */ +DEFINE_SVC_UUID2(zynqmp_sip_uuid, + 0x5c9b1b2a, 0x0586, 0x2340, 0xa6, 0x1b, + 0xb9, 0x25, 0x82, 0x2d, 0xe3, 0xa5); + +/** + * sip_svc_setup() - Setup SiP Service + * + * Invokes PM setup + */ +static int32_t sip_svc_setup(void) +{ + /* PM implementation as SiP Service */ + return pm_setup(); +} + +/** + * sip_svc_smc_handler() - Top-level SiP Service SMC handler + * + * Handler for all SiP SMC calls. Handles standard SIP requests + * and calls PM SMC handler if the call is for a PM-API function. + */ +uintptr_t sip_svc_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) +{ + /* Let EM SMC handler deal with EM-related requests */ + if (is_em_fid(smc_fid)) { + return em_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } else if (is_pm_fid(smc_fid)) { + /* Let PM SMC handler deal with PM-related requests */ + return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } + + /* Let IPI SMC handler deal with IPI-related requests */ + if (is_ipi_fid(smc_fid)) { + return ipi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } + + switch (smc_fid) { + case ZYNQMP_SIP_SVC_CALL_COUNT: + /* PM functions + default functions */ + SMC_RET1(handle, PM_API_MAX + 2); + + case ZYNQMP_SIP_SVC_UID: + SMC_UUID_RET(handle, zynqmp_sip_uuid); + + case ZYNQMP_SIP_SVC_VERSION: + SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register PM Service Calls as runtime service */ +DECLARE_RT_SVC( + sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + sip_svc_setup, + sip_svc_smc_handler); diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk b/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk new file mode 100644 index 0000000..318b01d --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk @@ -0,0 +1,8 @@ +# +# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +# TSP source files specific to ZynqMP platform +BL32_SOURCES += plat/common/aarch64/platform_mp_stack.S \ + plat/xilinx/zynqmp/tsp/tsp_plat_setup.c diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c new file mode 100644 index 0000000..352ba82 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Initialize the UART + ******************************************************************************/ +void tsp_early_platform_setup(void) +{ + /* + * Register a different console than already in use to display + * messages from TSP + */ + static console_t tsp_boot_console; + (void)console_cdns_register(ZYNQMP_UART_BASE, + zynqmp_get_uart_clk(), + ZYNQMP_UART_BAUDRATE, + &tsp_boot_console); + console_set_scope(&tsp_boot_console, + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT); + + /* Initialize the platform config for future decision making */ + zynqmp_config_setup(); +} + +/******************************************************************************* + * Perform platform specific setup placeholder + ******************************************************************************/ +void tsp_platform_setup(void) +{ + plat_arm_gic_driver_init(); + plat_arm_gic_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the MMU + ******************************************************************************/ +void tsp_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL32_BASE, BL32_END - BL32_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), + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), + {0} + }; + + setup_page_tables(bl_regions, plat_arm_get_mmap()); + enable_mmu_el1(0); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c new file mode 100644 index 0000000..fbf1ed0 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) Siemens AG, 2020-2021 + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* + * Enumeration of priority levels on ARM platforms. + */ +ehf_pri_desc_t zynqmp_exceptions[] = { + /* 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), +}; + +/* Plug in ARM exceptions to Exception Handling Framework. */ +EHF_REGISTER_PRIORITIES(zynqmp_exceptions, ARRAY_SIZE(zynqmp_exceptions), PLAT_PRI_BITS); diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c new file mode 100644 index 0000000..f57369f --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Zynq UltraScale+ MPSoC IPI agent registers access management + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +/* Zynqmp ipi configuration table */ +const static struct ipi_config zynqmp_ipi_table[] = { + /* APU IPI */ + { + .ipi_bit_mask = 0x1, + .ipi_reg_base = 0xFF300000, + .secure_only = 0, + }, + /* RPU0 IPI */ + { + .ipi_bit_mask = 0x100, + .ipi_reg_base = 0xFF310000, + .secure_only = 0, + }, + /* RPU1 IPI */ + { + .ipi_bit_mask = 0x200, + .ipi_reg_base = 0xFF320000, + .secure_only = 0, + }, + /* PMU0 IPI */ + { + .ipi_bit_mask = 0x10000, + .ipi_reg_base = 0xFF330000, + .secure_only = IPI_SECURE_MASK, + }, + /* PMU1 IPI */ + { + .ipi_bit_mask = 0x20000, + .ipi_reg_base = 0xFF331000, + .secure_only = 0, + }, + /* PMU2 IPI */ + { + .ipi_bit_mask = 0x40000, + .ipi_reg_base = 0xFF332000, + .secure_only = IPI_SECURE_MASK, + }, + /* PMU3 IPI */ + { + .ipi_bit_mask = 0x80000, + .ipi_reg_base = 0xFF333000, + .secure_only = IPI_SECURE_MASK, + }, + /* PL0 IPI */ + { + .ipi_bit_mask = 0x1000000, + .ipi_reg_base = 0xFF340000, + .secure_only = 0, + }, + /* PL1 IPI */ + { + .ipi_bit_mask = 0x2000000, + .ipi_reg_base = 0xFF350000, + .secure_only = 0, + }, + /* PL2 IPI */ + { + .ipi_bit_mask = 0x4000000, + .ipi_reg_base = 0xFF360000, + .secure_only = 0, + }, + /* PL3 IPI */ + { + .ipi_bit_mask = 0x8000000, + .ipi_reg_base = 0xFF370000, + .secure_only = 0, + }, +}; + +/** + * zynqmp_ipi_config_table_init() - Initialize ZynqMP IPI configuration data + * + */ +void zynqmp_ipi_config_table_init(void) +{ + ipi_config_table_init(zynqmp_ipi_table, ARRAY_SIZE(zynqmp_ipi_table)); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c new file mode 100644 index 0000000..7e92b58 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) Siemens AG, 2020-2021 + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* SDEI configuration for ARM platforms */ + +#include +#include +#include + +#include +#include + +int arm_validate_ns_entrypoint(uintptr_t entrypoint) +{ + return (entrypoint < BL31_BASE || entrypoint > BL31_LIMIT) ? 0 : -1; +} + +/* Private event mappings */ +static sdei_ev_map_t zynqmp_sdei_private[] = { + SDEI_DEFINE_EVENT_0(ZYNQMP_SDEI_SGI_PRIVATE), +}; + +/* Shared event mappings */ +static sdei_ev_map_t zynqmp_sdei_shared[] = { +}; + +void plat_sdei_setup(void) +{ + INFO("SDEI platform setup\n"); +} + +/* Export ARM SDEI events */ +REGISTER_SDEI_MAP(zynqmp_sdei_private, zynqmp_sdei_shared); diff --git a/arm-trusted-firmware/readme.rst b/arm-trusted-firmware/readme.rst new file mode 100644 index 0000000..148d477 --- /dev/null +++ b/arm-trusted-firmware/readme.rst @@ -0,0 +1,51 @@ +Trusted Firmware-A +================== + +Trusted Firmware-A (TF-A) is a reference implementation of secure world software +for `Arm A-Profile architectures`_ (Armv8-A and Armv7-A), including an Exception +Level 3 (EL3) `Secure Monitor`_. It provides a suitable starting point for +productization of secure world boot and runtime firmware, in either the AArch32 +or AArch64 execution states. + +TF-A implements Arm interface standards, including: + +- `Power State Coordination Interface (PSCI)`_ +- `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)`_ +- `SMC Calling Convention`_ +- `System Control and Management Interface (SCMI)`_ +- `Software Delegated Exception Interface (SDEI)`_ + +The code is designed to be portable and reusable across hardware platforms and +software models that are based on the Armv8-A and Armv7-A architectures. + +In collaboration with interested parties, we will continue to enhance TF-A +with reference implementations of Arm standards to benefit developers working +with Armv7-A and Armv8-A TrustZone technology. + +Users are encouraged to do their own security validation, including penetration +testing, on any secure world code derived from TF-A. + +More Info and Documentation +--------------------------- + +To find out more about Trusted Firmware-A, please `view the full documentation`_ +that is available through `trustedfirmware.org`_. + +-------------- + +*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Armv7-A and Armv8-A: https://developer.arm.com/products/architecture/a-profile +.. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php +.. _Power State Coordination Interface (PSCI): PSCI_ +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a +.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _System Control and Management Interface (SCMI): SCMI_ +.. _SCMI: http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/DEN0056A_System_Control_and_Management_Interface.pdf +.. _Software Delegated Exception Interface (SDEI): SDEI_ +.. _SDEI: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _Arm A-Profile architectures: https://developer.arm.com/architectures/cpu-architecture/a-profile +.. _view the full documentation: https://www.trustedfirmware.org/docs/tf-a +.. _trustedfirmware.org: http://www.trustedfirmware.org + diff --git a/arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c b/arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c new file mode 100644 index 0000000..742f6cd --- /dev/null +++ b/arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Arm Arch Service UUID */ +static uuid_t arm_arch_svc_uid = { + {0xb7, 0xe0, 0xe2, 0x4d}, + {0xf0, 0x3d}, + {0x42, 0x8d}, + 0x9c, 0x1d, + {0x87, 0xf6, 0x93, 0x84, 0x76, 0xd9} +}; + +static int32_t smccc_version(void) +{ + return MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION); +} + +static int32_t smccc_arch_features(u_register_t arg1) +{ + switch (arg1) { + case SMCCC_VERSION: + case SMCCC_ARCH_FEATURES: + return SMC_ARCH_CALL_SUCCESS; + case SMCCC_ARCH_SOC_ID: + return plat_is_smccc_feature_available(arg1); +#if WORKAROUND_CVE_2017_5715 + case SMCCC_ARCH_WORKAROUND_1: + if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES) + return 1; + return 0; /* ERRATA_APPLIES || ERRATA_MISSING */ +#endif + +#if WORKAROUND_CVE_2018_3639 + case SMCCC_ARCH_WORKAROUND_2: { +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + unsigned long long ssbs; + + /* + * Firmware doesn't have to carry out dynamic workaround if the + * PE implements architectural Speculation Store Bypass Safe + * (SSBS) feature. + */ + ssbs = (read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_SSBS_SHIFT) & + ID_AA64PFR1_EL1_SSBS_MASK; + + /* + * If architectural SSBS is available on this PE, no firmware + * mitigation via SMCCC_ARCH_WORKAROUND_2 is required. + */ + if (ssbs != SSBS_UNAVAILABLE) + return 1; + + /* + * On a platform where at least one CPU requires + * dynamic mitigation but others are either unaffected + * or permanently mitigated, report the latter as not + * needing dynamic mitigation. + */ + if (wa_cve_2018_3639_get_disable_ptr() == NULL) + return 1; + /* + * If we get here, this CPU requires dynamic mitigation + * so report it as such. + */ + return 0; +#else + /* Either the CPUs are unaffected or permanently mitigated */ + return SMC_ARCH_CALL_NOT_REQUIRED; +#endif + } +#endif + +#if (WORKAROUND_CVE_2022_23960 || WORKAROUND_CVE_2017_5715) + case SMCCC_ARCH_WORKAROUND_3: + /* + * SMCCC_ARCH_WORKAROUND_3 should also take into account + * CVE-2017-5715 since this SMC can be used instead of + * SMCCC_ARCH_WORKAROUND_1. + */ + if ((check_smccc_arch_wa3_applies() == ERRATA_NOT_APPLIES) && + (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)) { + return 1; + } + return 0; /* ERRATA_APPLIES || ERRATA_MISSING */ +#endif + + /* Fallthrough */ + + default: + return SMC_UNK; + } +} + +/* return soc revision or soc version on success otherwise + * return invalid parameter */ +static int32_t smccc_arch_id(u_register_t arg1) +{ + if (arg1 == SMCCC_GET_SOC_REVISION) { + return plat_get_soc_revision(); + } + if (arg1 == SMCCC_GET_SOC_VERSION) { + return plat_get_soc_version(); + } + return SMC_ARCH_CALL_INVAL_PARAM; +} + +/* + * Top-level Arm Architectural Service SMC handler. + */ +static uintptr_t arm_arch_svc_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) +{ + switch (smc_fid) { + case SMCCC_VERSION: + SMC_RET1(handle, smccc_version()); + case SMCCC_ARCH_FEATURES: + SMC_RET1(handle, smccc_arch_features(x1)); + case SMCCC_ARCH_SOC_ID: + SMC_RET1(handle, smccc_arch_id(x1)); + + case ARM_ARCH_SVC_CALL_COUNT: + /* Return the number of Arm Arch Calls. */ + SMC_RET1(handle, ARM_ARCH_SVC_COUNT); + case ARM_ARCH_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, arm_arch_svc_uid); + case ARM_ARCH_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, ARM_ARCH_SVC_VERSION_MAJOR, ARM_ARCH_SVC_VERSION_MINOR); + +#if WORKAROUND_CVE_2017_5715 + case SMCCC_ARCH_WORKAROUND_1: + /* + * The workaround has already been applied on affected PEs + * during entry to EL3. On unaffected PEs, this function + * has no effect. + */ + SMC_RET0(handle); +#endif +#if WORKAROUND_CVE_2018_3639 + case SMCCC_ARCH_WORKAROUND_2: + /* + * The workaround has already been applied on affected PEs + * requiring dynamic mitigation during entry to EL3. + * On unaffected or statically mitigated PEs, this function + * has no effect. + */ + SMC_RET0(handle); +#endif +#if (WORKAROUND_CVE_2022_23960 || WORKAROUND_CVE_2017_5715) + case SMCCC_ARCH_WORKAROUND_3: + /* + * The workaround has already been applied on affected PEs + * during entry to EL3. On unaffected PEs, this function + * has no effect. + */ + SMC_RET0(handle); +#endif + default: + WARN("Unimplemented Arm Architecture Service Call: 0x%x \n", + smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register Standard Service Calls as runtime service */ +DECLARE_RT_SVC( + arm_arch_svc, + OEN_ARM_START, + OEN_ARM_END, + SMC_TYPE_FAST, + NULL, + arm_arch_svc_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/opteed/opteed.mk b/arm-trusted-firmware/services/spd/opteed/opteed.mk new file mode 100644 index 0000000..643b054 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed.mk @@ -0,0 +1,18 @@ +# +# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +OPTEED_DIR := services/spd/opteed +SPD_INCLUDES := + +SPD_SOURCES := services/spd/opteed/opteed_common.c \ + services/spd/opteed/opteed_helpers.S \ + services/spd/opteed/opteed_main.c \ + services/spd/opteed/opteed_pm.c + +NEED_BL32 := yes + +# required so that optee code can control access to the timer registers +NS_TIMER_SWITCH := 1 diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_common.c b/arm-trusted-firmware/services/spd/opteed/opteed_common.c new file mode 100644 index 0000000..f913e11 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_common.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include "opteed_private.h" + +/******************************************************************************* + * Given a OPTEE entrypoint info pointer, entry point PC, register width, + * cpu id & pointer to a context data structure, this function will + * initialize OPTEE context and entry point info for OPTEE. + ******************************************************************************/ +void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point, + uint32_t rw, uint64_t pc, + uint64_t pageable_part, uint64_t mem_limit, + uint64_t dt_addr, optee_context_t *optee_ctx) +{ + uint32_t ep_attr; + + /* Passing a NULL context is a critical programming error */ + assert(optee_ctx); + assert(optee_entry_point); + assert(pc); + + /* Associate this context with the cpu specified */ + optee_ctx->mpidr = read_mpidr_el1(); + optee_ctx->state = 0; + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF); + + cm_set_context(&optee_ctx->cpu_ctx, SECURE); + + /* initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if (read_sctlr_el3() & SCTLR_EE_BIT) + ep_attr |= EP_EE_BIG; + SET_PARAM_HEAD(optee_entry_point, PARAM_EP, VERSION_1, ep_attr); + optee_entry_point->pc = pc; + if (rw == OPTEE_AARCH64) + optee_entry_point->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + else + optee_entry_point->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DAIF_FIQ_BIT | + DAIF_IRQ_BIT | + DAIF_ABT_BIT); + zeromem(&optee_entry_point->args, sizeof(optee_entry_point->args)); + optee_entry_point->args.arg0 = pageable_part; + optee_entry_point->args.arg1 = mem_limit; + optee_entry_point->args.arg2 = dt_addr; +} + +/******************************************************************************* + * This function takes an OPTEE context pointer and: + * 1. Applies the S-EL1 system register context from optee_ctx->cpu_ctx. + * 2. Saves the current C runtime state (callee saved registers) on the stack + * frame and saves a reference to this state. + * 3. Calls el3_exit() so that the EL3 system and general purpose registers + * from the optee_ctx->cpu_ctx are used to enter the OPTEE image. + ******************************************************************************/ +uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx) +{ + uint64_t rc; + + assert(optee_ctx != NULL); + assert(optee_ctx->c_rt_ctx == 0); + + /* Save the Non-Secure EL1 system register context */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* Apply the Secure EL1 system register context and switch to it */ + assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + rc = opteed_enter_sp(&optee_ctx->c_rt_ctx); +#if ENABLE_ASSERTIONS + optee_ctx->c_rt_ctx = 0; +#endif + + return rc; +} + + +/******************************************************************************* + * This function takes an OPTEE context pointer and: + * 1. Saves the S-EL1 system register context tp optee_ctx->cpu_ctx. + * 2. Restores the current C runtime state (callee saved registers) from the + * stack frame using the reference to this state saved in opteed_enter_sp(). + * 3. It does not need to save any general purpose or EL3 system register state + * as the generic smc entry routine should have saved those. + ******************************************************************************/ +void opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret) +{ + assert(optee_ctx != NULL); + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + /* Apply the Non-Secure EL1 system register context and switch to it */ + cm_el1_sysregs_context_restore(NON_SECURE); + + assert(optee_ctx->c_rt_ctx != 0); + opteed_exit_sp(optee_ctx->c_rt_ctx, ret); + + /* Should never reach here */ + assert(0); +} diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_helpers.S b/arm-trusted-firmware/services/spd/opteed/opteed_helpers.S new file mode 100644 index 0000000..075a71b --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_helpers.S @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "opteed_private.h" + + .global opteed_enter_sp + /* --------------------------------------------- + * This function is called with SP_EL0 as stack. + * Here we stash our EL3 callee-saved registers + * on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where + * the address of the C runtime context is to be + * saved. + * --------------------------------------------- + */ +func opteed_enter_sp + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #OPTEED_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #OPTEED_C_RT_CTX_X19] + stp x21, x22, [sp, #OPTEED_C_RT_CTX_X21] + stp x23, x24, [sp, #OPTEED_C_RT_CTX_X23] + stp x25, x26, [sp, #OPTEED_C_RT_CTX_X25] + stp x27, x28, [sp, #OPTEED_C_RT_CTX_X27] + stp x29, x30, [sp, #OPTEED_C_RT_CTX_X29] + + /* --------------------------------------------- + * Everything is setup now. el3_exit() will + * use the secure context to restore to the + * general purpose and EL3 system registers to + * ERET into OPTEE. + * --------------------------------------------- + */ + b el3_exit +endfunc opteed_enter_sp + + /* --------------------------------------------- + * This function is called 'x0' pointing to a C + * runtime context saved in opteed_enter_sp(). It + * restores the saved registers and jumps to + * that runtime with 'x0' as the new sp. This + * destroys the C runtime context that had been + * built on the stack below the saved context by + * the caller. Later the second parameter 'x1' + * is passed as return value to the caller + * --------------------------------------------- + */ + .global opteed_exit_sp +func opteed_exit_sp + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(OPTEED_C_RT_CTX_X19 - OPTEED_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(OPTEED_C_RT_CTX_X21 - OPTEED_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(OPTEED_C_RT_CTX_X23 - OPTEED_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(OPTEED_C_RT_CTX_X25 - OPTEED_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(OPTEED_C_RT_CTX_X27 - OPTEED_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(OPTEED_C_RT_CTX_X29 - OPTEED_C_RT_CTX_SIZE)] + + /* --------------------------------------------- + * This should take us back to the instruction + * after the call to the last opteed_enter_sp(). + * Place the second parameter to x0 so that the + * caller will see it as a return value from the + * original entry call + * --------------------------------------------- + */ + mov x0, x1 + ret +endfunc opteed_exit_sp diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_main.c b/arm-trusted-firmware/services/spd/opteed/opteed_main.c new file mode 100644 index 0000000..160a693 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_main.c @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/******************************************************************************* + * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a + * plug-in component to the Secure Monitor, registered as a runtime service. The + * SPD is expected to be a functional extension of the Secure Payload (SP) that + * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting + * the Trusted OS/Applications range to the dispatcher. The SPD will either + * handle the request locally or delegate it to the Secure Payload. It is also + * responsible for initialising and maintaining communication with the SP. + ******************************************************************************/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "opteed_private.h" +#include "teesmc_opteed.h" +#include "teesmc_opteed_macros.h" + +/******************************************************************************* + * Address of the entrypoint vector table in OPTEE. It is + * initialised once on the primary core after a cold boot. + ******************************************************************************/ +struct optee_vectors *optee_vector_table; + +/******************************************************************************* + * Array to keep track of per-cpu OPTEE state + ******************************************************************************/ +optee_context_t opteed_sp_context[OPTEED_CORE_COUNT]; +uint32_t opteed_rw; + +static int32_t opteed_init(void); + +/******************************************************************************* + * This function is the handler registered for S-EL1 interrupts by the + * OPTEED. It validates the interrupt and upon success arranges entry into + * the OPTEE at 'optee_fiq_entry()' for handling the interrupt. + ******************************************************************************/ +static uint64_t opteed_sel1_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + uint32_t linear_id; + optee_context_t *optee_ctx; + + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering the OPTEE */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* Get a reference to this cpu's OPTEE context */ + linear_id = plat_my_core_pos(); + optee_ctx = &opteed_sp_context[linear_id]; + assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE)); + + cm_set_elr_el3(SECURE, (uint64_t)&optee_vector_table->fiq_entry); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* + * Tell the OPTEE that it has to handle an FIQ (synchronously). + * Also the instruction in normal world where the interrupt was + * generated is passed for debugging purposes. It is safe to + * retrieve this address from ELR_EL3 as the secure context will + * not take effect until el3_exit(). + */ + SMC_RET1(&optee_ctx->cpu_ctx, read_elr_el3()); +} + +/******************************************************************************* + * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type + * (aarch32/aarch64) if not already known and initialises the context for entry + * into OPTEE for its initialization. + ******************************************************************************/ +static int32_t opteed_setup(void) +{ + entry_point_info_t *optee_ep_info; + uint32_t linear_id; + uint64_t opteed_pageable_part; + uint64_t opteed_mem_limit; + uint64_t dt_addr; + + linear_id = plat_my_core_pos(); + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. TODO: Add support to + * conditionally include the SPD service + */ + optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (!optee_ep_info) { + WARN("No OPTEE provided by BL2 boot loader, Booting device" + " without OPTEE initialization. SMC`s destined for OPTEE" + " will return SMC_UNK\n"); + return 1; + } + + /* + * If there's no valid entry point for SP, we return a non-zero value + * signalling failure initializing the service. We bail out without + * registering any handlers + */ + if (!optee_ep_info->pc) + return 1; + + opteed_rw = optee_ep_info->args.arg0; + opteed_pageable_part = optee_ep_info->args.arg1; + opteed_mem_limit = optee_ep_info->args.arg2; + dt_addr = optee_ep_info->args.arg3; + + opteed_init_optee_ep_state(optee_ep_info, + opteed_rw, + optee_ep_info->pc, + opteed_pageable_part, + opteed_mem_limit, + dt_addr, + &opteed_sp_context[linear_id]); + + /* + * All OPTEED initialization done. Now register our init function with + * BL31 for deferred invocation + */ + bl31_register_bl32_init(&opteed_init); + + return 0; +} + +/******************************************************************************* + * This function passes control to the OPTEE image (BL32) for the first time + * on the primary cpu after a cold boot. It assumes that a valid secure + * context has already been created by opteed_setup() which can be directly + * used. It also assumes that a valid non-secure context has been + * initialised by PSCI so it does not need to save and restore any + * non-secure state. This function performs a synchronous entry into + * OPTEE. OPTEE passes control back to this routine through a SMC. + ******************************************************************************/ +static int32_t opteed_init(void) +{ + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + entry_point_info_t *optee_entry_point; + uint64_t rc; + + /* + * Get information about the OPTEE (BL32) image. Its + * absence is a critical failure. + */ + optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE); + assert(optee_entry_point); + + cm_init_my_context(optee_entry_point); + + /* + * Arrange for an entry into OPTEE. It will be returned via + * OPTEE_ENTRY_DONE case + */ + rc = opteed_synchronous_sp_entry(optee_ctx); + assert(rc != 0); + + return rc; +} + + +/******************************************************************************* + * This function is responsible for handling all SMCs in the Trusted OS/App + * range from the non-secure state as defined in the SMC Calling Convention + * Document. It is also responsible for communicating with the Secure + * payload to delegate work and return results back to the non-secure + * state. Lastly it will also return any information that OPTEE needs to do + * the work assigned to it. + ******************************************************************************/ +static uintptr_t opteed_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) +{ + cpu_context_t *ns_cpu_context; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + uint64_t rc; + + /* + * Determine which security state this SMC originated from + */ + + if (is_caller_non_secure(flags)) { + /* + * This is a fresh request from the non-secure client. + * The parameters are in x1 and x2. Figure out which + * registers need to be preserved, save the non-secure + * state and send the request to the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * We are done stashing the non-secure context. Ask the + * OPTEE to do the work now. + */ + + /* + * Verify if there is a valid context to use, copy the + * operation type and parameters to the secure context + * and jump to the fast smc entry point in the secure + * payload. Entry into S-EL1 will take place upon exit + * from this function. + */ + assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE)); + + /* Set appropriate entry for SMC. + * We expect OPTEE to manage the PSTATE.I and PSTATE.F + * flags as appropriate. + */ + if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) { + cm_set_elr_el3(SECURE, (uint64_t) + &optee_vector_table->fast_smc_entry); + } else { + cm_set_elr_el3(SECURE, (uint64_t) + &optee_vector_table->yield_smc_entry); + } + + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X4, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X4)); + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X5, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X5)); + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X6, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X6)); + /* Propagate hypervisor client ID */ + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X7, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X7)); + + SMC_RET4(&optee_ctx->cpu_ctx, smc_fid, x1, x2, x3); + } + + /* + * Returning from OPTEE + */ + + switch (smc_fid) { + /* + * OPTEE has finished initialising itself after a cold boot + */ + case TEESMC_OPTEED_RETURN_ENTRY_DONE: + /* + * Stash the OPTEE entry points information. This is done + * only once on the primary cpu + */ + assert(optee_vector_table == NULL); + optee_vector_table = (optee_vectors_t *) x1; + + if (optee_vector_table) { + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); + + /* + * OPTEE has been successfully initialized. + * Register power management hooks with PSCI + */ + psci_register_spd_pm_hook(&opteed_pm); + + /* + * Register an interrupt handler for S-EL1 interrupts + * when generated during code executing in the + * non-secure state. + */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + opteed_sel1_interrupt_handler, + flags); + if (rc) + panic(); + } + + /* + * OPTEE reports completion. The OPTEED must have initiated + * the original request through a synchronous entry into + * OPTEE. Jump back to the original C runtime context. + */ + opteed_synchronous_sp_exit(optee_ctx, x1); + break; + + + /* + * These function IDs is used only by OP-TEE to indicate it has + * finished: + * 1. turning itself on in response to an earlier psci + * cpu_on request + * 2. resuming itself after an earlier psci cpu_suspend + * request. + */ + case TEESMC_OPTEED_RETURN_ON_DONE: + case TEESMC_OPTEED_RETURN_RESUME_DONE: + + + /* + * These function IDs is used only by the SP to indicate it has + * finished: + * 1. suspending itself after an earlier psci cpu_suspend + * request. + * 2. turning itself off in response to an earlier psci + * cpu_off request. + */ + case TEESMC_OPTEED_RETURN_OFF_DONE: + case TEESMC_OPTEED_RETURN_SUSPEND_DONE: + case TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE: + case TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE: + + /* + * OPTEE reports completion. The OPTEED must have initiated the + * original request through a synchronous entry into OPTEE. + * Jump back to the original C runtime context, and pass x1 as + * return value to the caller + */ + opteed_synchronous_sp_exit(optee_ctx, x1); + break; + + /* + * OPTEE is returning from a call or being preempted from a call, in + * either case execution should resume in the normal world. + */ + case TEESMC_OPTEED_RETURN_CALL_DONE: + /* + * This is the result from the secure client of an + * earlier request. The results are in x0-x3. Copy it + * into the non-secure context, save the secure state + * and return to the non-secure state. + */ + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* Restore non-secure state */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET4(ns_cpu_context, x1, x2, x3, x4); + + /* + * OPTEE has finished handling a S-EL1 FIQ interrupt. Execution + * should resume in the normal world. + */ + case TEESMC_OPTEED_RETURN_FIQ_DONE: + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since OPTEE was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET0((uint64_t) ns_cpu_context); + + default: + panic(); + } +} + +/* Define an OPTEED runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + opteed_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + opteed_setup, + opteed_smc_handler +); + +/* Define an OPTEED runtime service descriptor for yielding SMC calls */ +DECLARE_RT_SVC( + opteed_std, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_YIELD, + NULL, + opteed_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_pm.c b/arm-trusted-firmware/services/spd/opteed/opteed_pm.c new file mode 100644 index 0000000..719eeb7 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_pm.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "opteed_private.h" + +/******************************************************************************* + * The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any + * actions needed. Nothing at the moment. + ******************************************************************************/ +static void opteed_cpu_on_handler(u_register_t target_cpu) +{ +} + +/******************************************************************************* + * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions + * needed + ******************************************************************************/ +static int32_t opteed_cpu_off_handler(u_register_t unused) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point and enter OPTEE */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_off_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* + * Reset OPTEE's context for a fresh start when this cpu is turned on + * subsequently. + */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF); + + return 0; +} + +/******************************************************************************* + * This cpu is being suspended. S-EL1 state must have been saved in the + * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE. + ******************************************************************************/ +static void opteed_cpu_suspend_handler(u_register_t max_off_pwrlvl) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), CTX_GPREG_X0, + max_off_pwrlvl); + + /* Program the entry point and enter OPTEE */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_suspend_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND); +} + +/******************************************************************************* + * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits + * before passing control back to the Secure Monitor. Entry in S-El1 is done + * after initialising minimal architectural state that guarantees safe + * execution. + ******************************************************************************/ +static void opteed_cpu_on_finish_handler(u_register_t unused) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + entry_point_info_t optee_on_entrypoint; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF); + + opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw, + (uint64_t)&optee_vector_table->cpu_on_entry, + 0, 0, 0, optee_ctx); + + /* Initialise this cpu's secure context */ + cm_init_my_context(&optee_on_entrypoint); + + /* Enter OPTEE */ + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); +} + +/******************************************************************************* + * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it + * completed the preceding suspend call. Use that context to program an entry + * into OPTEE to allow it to do any remaining book keeping + ******************************************************************************/ +static void opteed_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND); + + /* Program the entry point, max_off_pwrlvl and enter the SP */ + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X0, + max_off_pwrlvl); + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_resume_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); +} + +/******************************************************************************* + * Return the type of OPTEE the OPTEED is dealing with. Report the current + * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE. + ******************************************************************************/ +static int32_t opteed_cpu_migrate_info(u_register_t *resident_cpu) +{ + return OPTEE_MIGRATE_INFO; +} + +/******************************************************************************* + * System is about to be switched off. Allow the OPTEED/OPTEE to perform + * any actions needed. + ******************************************************************************/ +static void opteed_system_off(void) +{ + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_off_entry); + + /* Enter OPTEE. We do not care about the return value because we + * must continue the shutdown anyway */ + opteed_synchronous_sp_entry(optee_ctx); +} + +/******************************************************************************* + * System is about to be reset. Allow the OPTEED/OPTEE to perform + * any actions needed. + ******************************************************************************/ +static void opteed_system_reset(void) +{ + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_reset_entry); + + /* Enter OPTEE. We do not care about the return value because we + * must continue the reset anyway */ + opteed_synchronous_sp_entry(optee_ctx); +} + + +/******************************************************************************* + * Structure populated by the OPTEE Dispatcher to be given a chance to + * perform any OPTEE bookkeeping before PSCI executes a power mgmt. + * operation. + ******************************************************************************/ +const spd_pm_ops_t opteed_pm = { + .svc_on = opteed_cpu_on_handler, + .svc_off = opteed_cpu_off_handler, + .svc_suspend = opteed_cpu_suspend_handler, + .svc_on_finish = opteed_cpu_on_finish_handler, + .svc_suspend_finish = opteed_cpu_suspend_finish_handler, + .svc_migrate = NULL, + .svc_migrate_info = opteed_cpu_migrate_info, + .svc_system_off = opteed_system_off, + .svc_system_reset = opteed_system_reset, +}; diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_private.h b/arm-trusted-firmware/services/spd/opteed/opteed_private.h new file mode 100644 index 0000000..242154f --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_private.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OPTEED_PRIVATE_H +#define OPTEED_PRIVATE_H + +#include + +#include +#include +#include +#include + +/******************************************************************************* + * OPTEE PM state information e.g. OPTEE is suspended, uninitialised etc + * and macros to access the state information in the per-cpu 'state' flags + ******************************************************************************/ +#define OPTEE_PSTATE_OFF 0 +#define OPTEE_PSTATE_ON 1 +#define OPTEE_PSTATE_SUSPEND 2 +#define OPTEE_PSTATE_SHIFT 0 +#define OPTEE_PSTATE_MASK 0x3 +#define get_optee_pstate(state) ((state >> OPTEE_PSTATE_SHIFT) & \ + OPTEE_PSTATE_MASK) +#define clr_optee_pstate(state) (state &= ~(OPTEE_PSTATE_MASK \ + << OPTEE_PSTATE_SHIFT)) +#define set_optee_pstate(st, pst) do { \ + clr_optee_pstate(st); \ + st |= (pst & OPTEE_PSTATE_MASK) << \ + OPTEE_PSTATE_SHIFT; \ + } while (0) + + +/******************************************************************************* + * OPTEE execution state information i.e. aarch32 or aarch64 + ******************************************************************************/ +#define OPTEE_AARCH32 MODE_RW_32 +#define OPTEE_AARCH64 MODE_RW_64 + +/******************************************************************************* + * The OPTEED should know the type of OPTEE + ******************************************************************************/ +#define OPTEE_TYPE_UP PSCI_TOS_NOT_UP_MIG_CAP +#define OPTEE_TYPE_UPM PSCI_TOS_UP_MIG_CAP +#define OPTEE_TYPE_MP PSCI_TOS_NOT_PRESENT_MP + +/******************************************************************************* + * OPTEE migrate type information as known to the OPTEED. We assume that + * the OPTEED is dealing with an MP Secure Payload. + ******************************************************************************/ +#define OPTEE_MIGRATE_INFO OPTEE_TYPE_MP + +/******************************************************************************* + * Number of cpus that the present on this platform. TODO: Rely on a topology + * tree to determine this in the future to avoid assumptions about mpidr + * allocation + ******************************************************************************/ +#define OPTEED_CORE_COUNT PLATFORM_CORE_COUNT + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define OPTEED_C_RT_CTX_X19 0x0 +#define OPTEED_C_RT_CTX_X20 0x8 +#define OPTEED_C_RT_CTX_X21 0x10 +#define OPTEED_C_RT_CTX_X22 0x18 +#define OPTEED_C_RT_CTX_X23 0x20 +#define OPTEED_C_RT_CTX_X24 0x28 +#define OPTEED_C_RT_CTX_X25 0x30 +#define OPTEED_C_RT_CTX_X26 0x38 +#define OPTEED_C_RT_CTX_X27 0x40 +#define OPTEED_C_RT_CTX_X28 0x48 +#define OPTEED_C_RT_CTX_X29 0x50 +#define OPTEED_C_RT_CTX_X30 0x58 +#define OPTEED_C_RT_CTX_SIZE 0x60 +#define OPTEED_C_RT_CTX_ENTRIES (OPTEED_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +#include + +typedef uint32_t optee_vector_isn_t; + +typedef struct optee_vectors { + optee_vector_isn_t yield_smc_entry; + optee_vector_isn_t fast_smc_entry; + optee_vector_isn_t cpu_on_entry; + optee_vector_isn_t cpu_off_entry; + optee_vector_isn_t cpu_resume_entry; + optee_vector_isn_t cpu_suspend_entry; + optee_vector_isn_t fiq_entry; + optee_vector_isn_t system_off_entry; + optee_vector_isn_t system_reset_entry; +} optee_vectors_t; + +/* + * The number of arguments to save during a SMC call for OPTEE. + * Currently only x1 and x2 are used by OPTEE. + */ +#define OPTEE_NUM_ARGS 0x2 + +/* AArch64 callee saved general purpose register context structure. */ +DEFINE_REG_STRUCT(c_rt_regs, OPTEED_C_RT_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(OPTEED_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \ + assert_spd_c_rt_regs_size_mismatch); + +/******************************************************************************* + * Structure which helps the OPTEED to maintain the per-cpu state of OPTEE. + * 'state' - collection of flags to track OPTEE state e.g. on/off + * 'mpidr' - mpidr to associate a context with a cpu + * 'c_rt_ctx' - stack address to restore C runtime context from after + * returning from a synchronous entry into OPTEE. + * 'cpu_ctx' - space to maintain OPTEE architectural state + ******************************************************************************/ +typedef struct optee_context { + uint32_t state; + uint64_t mpidr; + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; +} optee_context_t; + +/* OPTEED power management handlers */ +extern const spd_pm_ops_t opteed_pm; + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct optee_vectors; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +uint64_t opteed_enter_sp(uint64_t *c_rt_ctx); +void __dead2 opteed_exit_sp(uint64_t c_rt_ctx, uint64_t ret); +uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx); +void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret); +void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point, + uint32_t rw, + uint64_t pc, + uint64_t pageable_part, + uint64_t mem_limit, + uint64_t dt_addr, + optee_context_t *optee_ctx); + +extern optee_context_t opteed_sp_context[OPTEED_CORE_COUNT]; +extern uint32_t opteed_rw; +extern struct optee_vectors *optee_vector_table; +#endif /*__ASSEMBLER__*/ + +#endif /* OPTEED_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h b/arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h new file mode 100644 index 0000000..c82b58a --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Copyright (c) 2014, Linaro Limited. All rights reserved. */ + +#ifndef TEESMC_OPTEED_H +#define TEESMC_OPTEED_H + +/* + * This file specifies SMC function IDs used when returning from TEE to the + * secure monitor. + * + * All SMC Function IDs indicates SMC32 Calling Convention but will carry + * full 64 bit values in the argument registers if invoked from Aarch64 + * mode. This violates the SMC Calling Convention, but since this + * convention only coveres API towards Normal World it's something that + * only concerns the OP-TEE Dispatcher in Trusted Firmware-A and OP-TEE + * OS at Secure EL1. + */ + +/* + * Issued when returning from initial entry. + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ENTRY_DONE + * r1/x1 Pointer to entry vector + */ +#define TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE 0 +#define TEESMC_OPTEED_RETURN_ENTRY_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE) + + + +/* + * Issued when returning from "cpu_on" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ON_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_ON_DONE 1 +#define TEESMC_OPTEED_RETURN_ON_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ON_DONE) + +/* + * Issued when returning from "cpu_off" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_OFF_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE 2 +#define TEESMC_OPTEED_RETURN_OFF_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE) + +/* + * Issued when returning from "cpu_suspend" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SUSPEND_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE 3 +#define TEESMC_OPTEED_RETURN_SUSPEND_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE) + +/* + * Issued when returning from "cpu_resume" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_RESUME_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE 4 +#define TEESMC_OPTEED_RETURN_RESUME_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE) + +/* + * Issued when returning from "std_smc" or "fast_smc" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_CALL_DONE + * r1-4/x1-4 Return value 0-3 which will passed to normal world in + * r0-3/x0-3 + */ +#define TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE 5 +#define TEESMC_OPTEED_RETURN_CALL_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE) + +/* + * Issued when returning from "fiq" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_FIQ_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE 6 +#define TEESMC_OPTEED_RETURN_FIQ_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE) + +/* + * Issued when returning from "system_off" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE 7 +#define TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE) + +/* + * Issued when returning from "system_reset" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE 8 +#define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) + +#endif /*TEESMC_OPTEED_H*/ diff --git a/arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h b/arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h new file mode 100644 index 0000000..9d8a169 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef TEESMC_OPTEED_MACROS_H +#define TEESMC_OPTEED_MACROS_H + +#include + +#define TEESMC_OPTEED_RV(func_num) \ + ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \ + ((SMC_32) << FUNCID_CC_SHIFT) | \ + (62 << FUNCID_OEN_SHIFT) | \ + ((func_num) & FUNCID_NUM_MASK)) + +#endif /* TEESMC_OPTEED_MACROS_H */ diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd.mk b/arm-trusted-firmware/services/spd/tlkd/tlkd.mk new file mode 100644 index 0000000..56de0a6 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ERROR_DEPRECATED},0) +SPD_INCLUDES := -Iinclude/bl32/payloads +endif + +SPD_SOURCES := services/spd/tlkd/tlkd_common.c \ + services/spd/tlkd/tlkd_helpers.S \ + services/spd/tlkd/tlkd_main.c \ + services/spd/tlkd/tlkd_pm.c diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_common.c b/arm-trusted-firmware/services/spd/tlkd/tlkd_common.c new file mode 100644 index 0000000..820bd8a --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_common.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include "tlkd_private.h" + +#define AT_MASK 3 + +/******************************************************************************* + * This function helps the SP to translate NS/S virtual addresses. + ******************************************************************************/ +uint64_t tlkd_va_translate(uintptr_t va, int type) +{ + uint64_t pa; + + if (type & TLK_TRANSLATE_NS_VADDR) { + + /* save secure context */ + cm_el1_sysregs_context_save(SECURE); + + /* restore non-secure context */ + cm_el1_sysregs_context_restore(NON_SECURE); + + /* switch NS bit to start using 64-bit, non-secure mappings */ + write_scr(cm_get_scr_el3(NON_SECURE)); + isb(); + } + + int at = type & AT_MASK; + switch (at) { + case 0: + AT(ats12e1r, va); + break; + case 1: + AT(ats12e1w, va); + break; + case 2: + AT(ats12e0r, va); + break; + case 3: + AT(ats12e0w, va); + break; + default: + assert(0); /* Unreachable */ + break; + } + + /* get the (NS/S) physical address */ + isb(); + pa = read_par_el1(); + + /* Restore secure state */ + if (type & TLK_TRANSLATE_NS_VADDR) { + + /* restore secure context */ + cm_el1_sysregs_context_restore(SECURE); + + /* switch NS bit to start using 32-bit, secure mappings */ + write_scr(cm_get_scr_el3(SECURE)); + isb(); + } + + return pa; +} + +/******************************************************************************* + * Given a secure payload entrypoint, register width, cpu id & pointer to a + * context data structure, this function will create a secure context ready for + * programming an entry into the secure payload. + ******************************************************************************/ +void tlkd_init_tlk_ep_state(struct entry_point_info *tlk_entry_point, + uint32_t rw, + uint64_t pc, + tlk_context_t *tlk_ctx) +{ + uint32_t ep_attr, spsr; + + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + assert(tlk_entry_point); + assert(pc); + + /* Associate this context with the cpu specified */ + tlk_ctx->mpidr = read_mpidr_el1(); + clr_yield_smc_active_flag(tlk_ctx->state); + cm_set_context(&tlk_ctx->cpu_ctx, SECURE); + + if (rw == SP_AARCH64) + spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + else + spsr = SPSR_MODE32(MODE32_svc, + SPSR_T_ARM, + read_sctlr_el3() & SCTLR_EE_BIT, + DISABLE_ALL_EXCEPTIONS); + + /* initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if (read_sctlr_el3() & SCTLR_EE_BIT) + ep_attr |= EP_EE_BIG; + SET_PARAM_HEAD(tlk_entry_point, PARAM_EP, VERSION_1, ep_attr); + + tlk_entry_point->pc = pc; + tlk_entry_point->spsr = spsr; +} + +/******************************************************************************* + * This function takes a TLK context pointer and: + * 1. Applies the S-EL1 system register context from tlk_ctx->cpu_ctx. + * 2. Saves the current C runtime state (callee saved registers) on the stack + * frame and saves a reference to this state. + * 3. Calls el3_exit() so that the EL3 system and general purpose registers + * from the tlk_ctx->cpu_ctx are used to enter the secure payload image. + ******************************************************************************/ +uint64_t tlkd_synchronous_sp_entry(tlk_context_t *tlk_ctx) +{ + uint64_t rc; + + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + + /* Apply the Secure EL1 system register context and switch to it */ + assert(cm_get_context(SECURE) == &tlk_ctx->cpu_ctx); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + rc = tlkd_enter_sp(&tlk_ctx->c_rt_ctx); +#if ENABLE_ASSERTIONS + tlk_ctx->c_rt_ctx = 0; +#endif + + return rc; +} + +/******************************************************************************* + * This function takes a TLK context pointer and: + * 1. Saves the S-EL1 system register context to tlk_ctx->cpu_ctx. + * 2. Restores the current C runtime state (callee saved registers) from the + * stack frame using reference to this state saved in tlkd_enter_sp(). + * 3. It does not need to save any general purpose or EL3 system register state + * as the generic smc entry routine should have saved those. + ******************************************************************************/ +void tlkd_synchronous_sp_exit(tlk_context_t *tlk_ctx, uint64_t ret) +{ + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &tlk_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + assert(tlk_ctx->c_rt_ctx != 0); + tlkd_exit_sp(tlk_ctx->c_rt_ctx, ret); + + /* Should never reach here */ + assert(0); +} diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S b/arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S new file mode 100644 index 0000000..6e616a6 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "tlkd_private.h" + + .global tlkd_enter_sp + .global tlkd_exit_sp + + /* --------------------------------------------- + * This function is called with SP_EL0 as stack. + * Here we stash our EL3 callee-saved registers + * on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where + * the address of the C runtime context is to be + * saved. + * --------------------------------------------- + */ +func tlkd_enter_sp + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #TLKD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #TLKD_C_RT_CTX_X19] + stp x21, x22, [sp, #TLKD_C_RT_CTX_X21] + stp x23, x24, [sp, #TLKD_C_RT_CTX_X23] + stp x25, x26, [sp, #TLKD_C_RT_CTX_X25] + stp x27, x28, [sp, #TLKD_C_RT_CTX_X27] + stp x29, x30, [sp, #TLKD_C_RT_CTX_X29] + + /* ---------------------------------------------- + * Everything is setup now. el3_exit() will + * use the secure context to restore to the + * general purpose and EL3 system registers to + * ERET into the secure payload. + * ---------------------------------------------- + */ + b el3_exit +endfunc tlkd_enter_sp + + /* ---------------------------------------------- + * This function is called with 'x0' pointing to + * a C runtime context saved in tlkd_enter_sp(). + * It restores the saved registers and jumps to + * that runtime with 'x0' as the new sp. This + * destroys the C runtime context that had been + * built on the stack below the saved context by + * the caller. Later the second parameter 'x1' + * is passed as return value to the caller + * ---------------------------------------------- + */ +func tlkd_exit_sp + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(TLKD_C_RT_CTX_X19 - TLKD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(TLKD_C_RT_CTX_X21 - TLKD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(TLKD_C_RT_CTX_X23 - TLKD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(TLKD_C_RT_CTX_X25 - TLKD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(TLKD_C_RT_CTX_X27 - TLKD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(TLKD_C_RT_CTX_X29 - TLKD_C_RT_CTX_SIZE)] + + /* ------------------------------------------------ + * This should take us back to the instruction + * after the call to the last tlkd_enter_sp(). + * Place the second parameter to x0 so that the + * caller will see it as a return value from the + * original entry call + * ------------------------------------------------ + */ + mov x0, x1 + ret +endfunc tlkd_exit_sp diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_main.c b/arm-trusted-firmware/services/spd/tlkd/tlkd_main.c new file mode 100644 index 0000000..e426fac --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_main.c @@ -0,0 +1,558 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/******************************************************************************* + * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a + * plug-in component to the Secure Monitor, registered as a runtime service. The + * SPD is expected to be a functional extension of the Secure Payload (SP) that + * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting + * the Trusted OS/Applications range to the dispatcher. The SPD will either + * handle the request locally or delegate it to the Secure Payload. It is also + * responsible for initialising and maintaining communication with the SP. + ******************************************************************************/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tlkd_private.h" + +extern const spd_pm_ops_t tlkd_pm_ops; + +/******************************************************************************* + * Per-cpu Secure Payload state + ******************************************************************************/ +tlk_context_t tlk_ctx; + +/******************************************************************************* + * CPU number on which TLK booted up + ******************************************************************************/ +static uint32_t boot_cpu; + +/* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */ +DEFINE_SVC_UUID2(tlk_uuid, + 0xc9e911bd, 0xba2b, 0xee52, 0xb1, 0x72, + 0x46, 0x1f, 0xba, 0x97, 0x7f, 0x63); + +static int32_t tlkd_init(void); + +/******************************************************************************* + * Secure Payload Dispatcher's timer interrupt handler + ******************************************************************************/ +static uint64_t tlkd_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + cpu_context_t *s_cpu_context; + int irq = plat_ic_get_pending_interrupt_id(); + + /* acknowledge the interrupt and mark it complete */ + (void)plat_ic_acknowledge_interrupt(); + plat_ic_end_of_interrupt(irq); + + /* + * Disable the routing of NS interrupts from secure world to + * EL3 while interrupted on this core. + */ + disable_intr_rm_local(INTR_TYPE_S_EL1, SECURE); + + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + assert(handle == cm_get_context(NON_SECURE)); + + /* Save non-secure state */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* Get a reference to the secure context */ + s_cpu_context = cm_get_context(SECURE); + assert(s_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the SP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* Provide the IRQ number to the SPD */ + SMC_RET4(s_cpu_context, (uint32_t)TLK_IRQ_FIRED, 0, (uint32_t)irq, 0); +} + +/******************************************************************************* + * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type + * (aarch32/aarch64) if not already known and initialises the context for entry + * into the SP for its initialisation. + ******************************************************************************/ +static int32_t tlkd_setup(void) +{ + entry_point_info_t *tlk_ep_info; + uint32_t flags; + int32_t ret; + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. + */ + tlk_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (!tlk_ep_info) { + WARN("No SP provided. Booting device without SP" + " initialization. SMC`s destined for SP" + " will return SMC_UNK\n"); + return 1; + } + + /* + * If there's no valid entry point for SP, we return a non-zero value + * signalling failure initializing the service. We bail out without + * registering any handlers + */ + if (!tlk_ep_info->pc) + return 1; + + /* + * Inspect the SP image's SPSR and determine it's execution state + * i.e whether AArch32 or AArch64. + */ + tlkd_init_tlk_ep_state(tlk_ep_info, + (tlk_ep_info->spsr >> MODE_RW_SHIFT) & MODE_RW_MASK, + tlk_ep_info->pc, + &tlk_ctx); + + /* get a list of all S-EL1 IRQs from the platform */ + + /* register interrupt handler */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tlkd_interrupt_handler, + flags); + if (ret != 0) { + ERROR("failed to register tlkd interrupt handler (%d)\n", ret); + } + + /* + * All TLK SPD initialization done. Now register our init function + * with BL31 for deferred invocation + */ + bl31_register_bl32_init(&tlkd_init); + + /* get a list of all S-EL1 IRQs from the platform */ + + /* register interrupt handler */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tlkd_interrupt_handler, + flags); + if (ret != 0) { + ERROR("failed to register tlkd interrupt handler (%d)\n", ret); + } + + return 0; +} + +/******************************************************************************* + * This function passes control to the Secure Payload image (BL32) for the first + * time on the primary cpu after a cold boot. It assumes that a valid secure + * context has already been created by tlkd_setup() which can be directly + * used. This function performs a synchronous entry into the Secure payload. + * The SP passes control back to this routine through a SMC. + ******************************************************************************/ +static int32_t tlkd_init(void) +{ + entry_point_info_t *tlk_entry_point; + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. + */ + tlk_entry_point = bl31_plat_get_next_image_ep_info(SECURE); + assert(tlk_entry_point); + + cm_init_my_context(tlk_entry_point); + + /* + * TLK runs only on a single CPU. Store the value of the boot + * CPU for sanity checking later. + */ + boot_cpu = plat_my_core_pos(); + + /* + * Arrange for an entry into the test secure payload. + */ + return tlkd_synchronous_sp_entry(&tlk_ctx); +} + +/******************************************************************************* + * This function is responsible for handling all SMCs in the Trusted OS/App + * range from the non-secure state as defined in the SMC Calling Convention + * Document. It is also responsible for communicating with the Secure payload + * to delegate work and return results back to the non-secure state. Lastly it + * will also return any information that the secure payload needs to do the + * work assigned to it. + ******************************************************************************/ +static uintptr_t tlkd_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) +{ + cpu_context_t *ns_cpu_context; + gp_regs_t *gp_regs; + uint32_t ns; + uint64_t par; + + /* Passing a NULL context is a critical programming error */ + assert(handle); + + /* These SMCs are only supported by a single CPU */ + if (boot_cpu != plat_my_core_pos()) + SMC_RET1(handle, SMC_UNK); + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + + switch (smc_fid) { + + /* + * This function ID is used by SP to indicate that it was + * preempted by a non-secure world IRQ. + */ + case TLK_PREEMPTED: + + if (ns) + SMC_RET1(handle, SMC_UNK); + + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the SP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET1(ns_cpu_context, x1); + + /* + * This is a request from the non-secure context to: + * + * a. register shared memory with the SP for storing it's + * activity logs. + * b. register shared memory with the SP for passing args + * required for maintaining sessions with the Trusted + * Applications. + * c. register shared persistent buffers for secure storage + * d. register NS DRAM ranges passed by Cboot + * e. register Root of Trust parameters from Cboot for Verified Boot + * f. open/close sessions + * g. issue commands to the Trusted Apps + * h. resume the preempted yielding SMC call. + */ + case TLK_REGISTER_LOGBUF: + case TLK_REGISTER_REQBUF: + case TLK_SS_REGISTER_HANDLER: + case TLK_REGISTER_NS_DRAM_RANGES: + case TLK_SET_ROOT_OF_TRUST: + case TLK_OPEN_TA_SESSION: + case TLK_CLOSE_TA_SESSION: + case TLK_TA_LAUNCH_OP: + case TLK_TA_SEND_EVENT: + case TLK_RESUME_FID: + case TLK_SET_BL_VERSION: + case TLK_LOCK_BL_INTERFACE: + case TLK_BL_RPMB_SERVICE: + + if (!ns) + SMC_RET1(handle, SMC_UNK); + + /* + * This is a fresh request from the non-secure client. + * The parameters are in x1 and x2. Figure out which + * registers need to be preserved, save the non-secure + * state and send the request to the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + /* + * Check if we are already processing a yielding SMC + * call. Of all the supported fids, only the "resume" + * fid expects the flag to be set. + */ + if (smc_fid == TLK_RESUME_FID) { + if (!get_yield_smc_active_flag(tlk_ctx.state)) + SMC_RET1(handle, SMC_UNK); + } else { + if (get_yield_smc_active_flag(tlk_ctx.state)) + SMC_RET1(handle, SMC_UNK); + } + + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * Verify if there is a valid context to use. + */ + assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE)); + + /* + * Mark the SP state as active. + */ + set_yield_smc_active_flag(tlk_ctx.state); + + /* + * We are done stashing the non-secure context. Ask the + * secure payload to do the work now. + */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* + * TLK is a 32-bit Trusted OS and so expects the SMC + * arguments via r0-r7. TLK expects the monitor frame + * registers to be 64-bits long. Hence, we pass x0 in + * r0-r1, x1 in r2-r3, x3 in r4-r5 and x4 in r6-r7. + * + * As smc_fid is a uint32 value, r1 contains 0. + */ + gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); + write_ctx_reg(gp_regs, CTX_GPREG_X4, (uint32_t)x2); + write_ctx_reg(gp_regs, CTX_GPREG_X5, (uint32_t)(x2 >> 32)); + write_ctx_reg(gp_regs, CTX_GPREG_X6, (uint32_t)x3); + write_ctx_reg(gp_regs, CTX_GPREG_X7, (uint32_t)(x3 >> 32)); + SMC_RET4(&tlk_ctx.cpu_ctx, smc_fid, 0, (uint32_t)x1, + (uint32_t)(x1 >> 32)); + + /* + * Translate NS/EL1-S virtual addresses. + * + * x1 = virtual address + * x3 = type (NS/S) + * + * Returns PA:lo in r0, PA:hi in r1. + */ + case TLK_VA_TRANSLATE: + + /* Should be invoked only by secure world */ + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* NS virtual addresses are 64-bit long */ + if (x3 & TLK_TRANSLATE_NS_VADDR) + x1 = (uint32_t)x1 | (x2 << 32); + + if (!x1) + SMC_RET1(handle, SMC_UNK); + + /* + * TODO: Sanity check x1. This would require platform + * support. + */ + + /* virtual address and type: ns/s */ + par = tlkd_va_translate(x1, x3); + + /* return physical address in r0-r1 */ + SMC_RET4(handle, (uint32_t)par, (uint32_t)(par >> 32), 0, 0); + + /* + * This is a request from the SP to mark completion of + * a yielding function ID. + */ + case TLK_REQUEST_DONE: + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * Mark the SP state as inactive. + */ + clr_yield_smc_active_flag(tlk_ctx.state); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * This is a request completion SMC and we must switch to + * the non-secure world to pass the result. + */ + cm_el1_sysregs_context_save(SECURE); + + /* + * We are done stashing the secure context. Switch to the + * non-secure context and return the result. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + SMC_RET1(ns_cpu_context, x1); + + /* + * This function ID is used only by the SP to indicate it has + * finished initialising itself after a cold boot + */ + case TLK_ENTRY_DONE: + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * SP has been successfully initialized. Register power + * management hooks with PSCI + */ + psci_register_spd_pm_hook(&tlkd_pm_ops); + + /* + * TLK reports completion. The SPD must have initiated + * the original request through a synchronous entry + * into the SP. Jump back to the original C runtime + * context. + */ + tlkd_synchronous_sp_exit(&tlk_ctx, x1); + break; + + /* + * These function IDs are used only by TLK to indicate it has + * finished: + * 1. suspending itself after an earlier psci cpu_suspend + * request. + * 2. resuming itself after an earlier psci cpu_suspend + * request. + * 3. powering down after an earlier psci system_off/system_reset + * request. + */ + case TLK_SUSPEND_DONE: + case TLK_RESUME_DONE: + + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * TLK reports completion. TLKD must have initiated the + * original request through a synchronous entry into the SP. + * Jump back to the original C runtime context, and pass x1 as + * return value to the caller + */ + tlkd_synchronous_sp_exit(&tlk_ctx, x1); + break; + + /* + * This function ID is used by SP to indicate that it has completed + * handling the secure interrupt. + */ + case TLK_IRQ_DONE: + + if (ns) + SMC_RET1(handle, SMC_UNK); + + assert(handle == cm_get_context(SECURE)); + + /* save secure world context */ + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the SP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET0(ns_cpu_context); + + /* + * Return the number of service function IDs implemented to + * provide service to non-secure + */ + case TOS_CALL_COUNT: + SMC_RET1(handle, TLK_NUM_FID); + + /* + * Return TLK's UID to the caller + */ + case TOS_UID: + SMC_UUID_RET(handle, tlk_uuid); + + /* + * Return the version of current implementation + */ + case TOS_CALL_VERSION: + SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR); + + default: + WARN("%s: Unhandled SMC: 0x%x\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tlkd_tos_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + tlkd_setup, + tlkd_smc_handler +); + +/* Define a SPD runtime service descriptor for yielding SMC calls */ +DECLARE_RT_SVC( + tlkd_tos_std, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_YIELD, + NULL, + tlkd_smc_handler +); + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tlkd_tap_fast, + + OEN_TAP_START, + OEN_TAP_END, + SMC_TYPE_FAST, + NULL, + tlkd_smc_handler +); + +/* Define a SPD runtime service descriptor for yielding SMC calls */ +DECLARE_RT_SVC( + tlkd_tap_std, + + OEN_TAP_START, + OEN_TAP_END, + SMC_TYPE_YIELD, + NULL, + tlkd_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c b/arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c new file mode 100644 index 0000000..ed5bf77 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, 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 "tlkd_private.h" + +extern tlk_context_t tlk_ctx; + +#define MPIDR_CPU0 0x80000000 + +/******************************************************************************* + * Return the type of payload TLKD is dealing with. Report the current + * resident cpu (mpidr format) if it is a UP/UP migratable payload. + ******************************************************************************/ +static int32_t cpu_migrate_info(u_register_t *resident_cpu) +{ + /* the payload runs only on CPU0 */ + *resident_cpu = MPIDR_CPU0; + + /* Uniprocessor, not migrate capable payload */ + return PSCI_TOS_NOT_UP_MIG_CAP; +} + +/******************************************************************************* + * This cpu is being suspended. Inform TLK of the SYSTEM_SUSPEND event, so + * that it can pass this information to its Trusted Apps. + ******************************************************************************/ +static void cpu_suspend_handler(u_register_t suspend_level) +{ + gp_regs_t *gp_regs; + int cpu = read_mpidr() & MPIDR_CPU_MASK; + int32_t rc = 0; + + /* + * TLK runs only on CPU0 and suspends its Trusted Apps during + * SYSTEM_SUSPEND. It has no role to play during CPU_SUSPEND. + */ + if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) + return; + + /* pass system suspend event to TLK */ + gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); + write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_SUSPEND); + + /* Program the entry point and enter TLK */ + rc = tlkd_synchronous_sp_entry(&tlk_ctx); + + /* + * Read the response from TLK. A non-zero return means that + * something went wrong while communicating with it. + */ + if (rc != 0) + panic(); +} + +/******************************************************************************* + * This cpu is being resumed. Inform TLK of the SYSTEM_SUSPEND exit, so + * that it can pass this information to its Trusted Apps. + ******************************************************************************/ +static void cpu_resume_handler(u_register_t suspend_level) +{ + gp_regs_t *gp_regs; + int cpu = read_mpidr() & MPIDR_CPU_MASK; + int32_t rc = 0; + + /* + * TLK runs only on CPU0 and resumes its Trusted Apps during + * SYSTEM_SUSPEND exit. It has no role to play during CPU_SUSPEND + * exit. + */ + if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) + return; + + /* pass system resume event to TLK */ + gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); + write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_RESUME); + + /* Program the entry point and enter TLK */ + rc = tlkd_synchronous_sp_entry(&tlk_ctx); + + /* + * Read the response from TLK. A non-zero return means that + * something went wrong while communicating with it. + */ + if (rc != 0) + panic(); +} + +/******************************************************************************* + * Structure populated by the Dispatcher to be given a chance to perform any + * bookkeeping before PSCI executes a power mgmt. operation. + ******************************************************************************/ +const spd_pm_ops_t tlkd_pm_ops = { + .svc_migrate_info = cpu_migrate_info, + .svc_suspend = cpu_suspend_handler, + .svc_suspend_finish = cpu_resume_handler, +}; diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_private.h b/arm-trusted-firmware/services/spd/tlkd/tlkd_private.h new file mode 100644 index 0000000..5d5d0e8 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_private.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TLKD_PRIVATE_H +#define TLKD_PRIVATE_H + +#include + +#include +#include +#include +#include + +/* + * This flag is used by the TLKD to determine if the SP is servicing a yielding + * SMC request prior to programming the next entry into the SP e.g. if SP + * execution is preempted by a non-secure interrupt and handed control to the + * normal world. If another request which is distinct from what the SP was + * previously doing arrives, then this flag will be help the TLKD to either + * reject the new request or service it while ensuring that the previous context + * is not corrupted. + */ +#define YIELD_SMC_ACTIVE_FLAG_SHIFT 2 +#define YIELD_SMC_ACTIVE_FLAG_MASK 1 +#define get_yield_smc_active_flag(state) \ + (((state) >> YIELD_SMC_ACTIVE_FLAG_SHIFT) \ + & YIELD_SMC_ACTIVE_FLAG_MASK) +#define set_yield_smc_active_flag(state) ((state) |= \ + (1 << YIELD_SMC_ACTIVE_FLAG_SHIFT)) +#define clr_yield_smc_active_flag(state) ((state) &= \ + ~(YIELD_SMC_ACTIVE_FLAG_MASK \ + << YIELD_SMC_ACTIVE_FLAG_SHIFT)) + +/******************************************************************************* + * Translate virtual address received from the NS world + ******************************************************************************/ +#define TLK_TRANSLATE_NS_VADDR 4 + +/******************************************************************************* + * Secure Payload execution state information i.e. aarch32 or aarch64 + ******************************************************************************/ +#define SP_AARCH32 MODE_RW_32 +#define SP_AARCH64 MODE_RW_64 + +/******************************************************************************* + * Number of cpus that the present on this platform. TODO: Rely on a topology + * tree to determine this in the future to avoid assumptions about mpidr + * allocation + ******************************************************************************/ +#define TLKD_CORE_COUNT PLATFORM_CORE_COUNT + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define TLKD_C_RT_CTX_X19 0x0 +#define TLKD_C_RT_CTX_X20 0x8 +#define TLKD_C_RT_CTX_X21 0x10 +#define TLKD_C_RT_CTX_X22 0x18 +#define TLKD_C_RT_CTX_X23 0x20 +#define TLKD_C_RT_CTX_X24 0x28 +#define TLKD_C_RT_CTX_X25 0x30 +#define TLKD_C_RT_CTX_X26 0x38 +#define TLKD_C_RT_CTX_X27 0x40 +#define TLKD_C_RT_CTX_X28 0x48 +#define TLKD_C_RT_CTX_X29 0x50 +#define TLKD_C_RT_CTX_X30 0x58 +#define TLKD_C_RT_CTX_SIZE 0x60 +#define TLKD_C_RT_CTX_ENTRIES (TLKD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* AArch64 callee saved general purpose register context structure. */ +DEFINE_REG_STRUCT(c_rt_regs, TLKD_C_RT_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(TLKD_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \ + assert_tlkd_c_rt_regs_size_mismatch); + +/******************************************************************************* + * Structure which helps the SPD to maintain the per-cpu state of the SP. + * 'state' - collection of flags to track SP state e.g. on/off + * 'mpidr' - mpidr to associate a context with a cpu + * 'c_rt_ctx' - stack address to restore C runtime context from after + * returning from a synchronous entry into the SP. + * 'cpu_ctx' - space to maintain SP architectural state + * 'saved_tsp_args' - space to store arguments for TSP arithmetic operations + * which will queried using the TSP_GET_ARGS SMC by TSP. + ******************************************************************************/ +typedef struct tlk_context { + uint32_t state; + uint64_t mpidr; + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; +} tlk_context_t; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +uint64_t tlkd_va_translate(uintptr_t va, int type); +uint64_t tlkd_enter_sp(uint64_t *c_rt_ctx); +void __dead2 tlkd_exit_sp(uint64_t c_rt_ctx, uint64_t ret); +uint64_t tlkd_synchronous_sp_entry(tlk_context_t *tlk_ctx); +void __dead2 tlkd_synchronous_sp_exit(tlk_context_t *tlk_ctx, + uint64_t ret); +void tlkd_init_tlk_ep_state(struct entry_point_info *tlk_entry_point, + uint32_t rw, + uint64_t pc, + tlk_context_t *tlk_ctx); + +#endif /*__ASSEMBLER__*/ + +#endif /* TLKD_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c b/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c new file mode 100644 index 0000000..5c3a628 --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "generic-arm64-smcall.h" + +#ifndef PLAT_ARM_GICD_BASE +#ifdef GICD_BASE +#define PLAT_ARM_GICD_BASE GICD_BASE +#define PLAT_ARM_GICC_BASE GICC_BASE +#ifdef GICR_BASE +#define PLAT_ARM_GICR_BASE GICR_BASE +#endif +#else +#error PLAT_ARM_GICD_BASE or GICD_BASE must be defined +#endif +#endif + +#ifndef PLAT_ARM_GICR_BASE +#define PLAT_ARM_GICR_BASE SMC_UNK +#endif + +int trusty_disable_serial_debug; + +struct dputc_state { + char linebuf[128]; + unsigned l; +}; + +static struct dputc_state dputc_state[2]; + +static void trusty_dputc(char ch, int secure) +{ + unsigned i; + struct dputc_state *s = &dputc_state[!secure]; + + if (trusty_disable_serial_debug) + return; + + s->linebuf[s->l++] = ch; + if (s->l == sizeof(s->linebuf) || ch == '\n') { + if (secure) + printf("secure os: "); + else + printf("non-secure os: "); + for (i = 0; i < s->l; i++) { + putchar(s->linebuf[i]); + } + if (ch != '\n') { + printf(" <...>\n"); + } + s->l = 0; + } +} + +static uint64_t trusty_get_reg_base(uint32_t reg) +{ + switch (reg) { + case SMC_GET_GIC_BASE_GICD: + return PLAT_ARM_GICD_BASE; + + case SMC_GET_GIC_BASE_GICC: + return PLAT_ARM_GICC_BASE; + + case SMC_GET_GIC_BASE_GICR: + return PLAT_ARM_GICR_BASE; + + default: + NOTICE("%s(0x%x) unknown reg\n", __func__, reg); + return SMC_UNK; + } +} + +static uintptr_t trusty_generic_platform_smc(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 SMC_FC_DEBUG_PUTC: + trusty_dputc(x1, is_caller_secure(flags)); + SMC_RET1(handle, 0); + + case SMC_FC_GET_REG_BASE: + case SMC_FC64_GET_REG_BASE: + SMC_RET1(handle, trusty_get_reg_base(x1)); + + default: + NOTICE("%s(0x%x, 0x%lx) unknown smc\n", __func__, smc_fid, x1); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + trusty_fast, + + SMC_ENTITY_PLATFORM_MONITOR, + SMC_ENTITY_PLATFORM_MONITOR, + SMC_TYPE_FAST, + NULL, + trusty_generic_platform_smc +); + diff --git a/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h b/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h new file mode 100644 index 0000000..ac03469 --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "smcall.h" + +#define SMC_ENTITY_PLATFORM_MONITOR 61 + +/* + * SMC calls implemented by EL3 monitor + */ + +/* + * Write character in r1 to debug console + */ +#define SMC_FC_DEBUG_PUTC SMC_FASTCALL_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x0) + +/* + * Get register base address + * r1: SMC_GET_GIC_BASE_GICD or SMC_GET_GIC_BASE_GICC + */ +#define SMC_GET_GIC_BASE_GICD 0 +#define SMC_GET_GIC_BASE_GICC 1 +#define SMC_GET_GIC_BASE_GICR 2 +#define SMC_FC_GET_REG_BASE SMC_FASTCALL_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1) +#define SMC_FC64_GET_REG_BASE SMC_FASTCALL64_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1) diff --git a/arm-trusted-firmware/services/spd/trusty/sm_err.h b/arm-trusted-firmware/services/spd/trusty/sm_err.h new file mode 100644 index 0000000..80a8748 --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/sm_err.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SM_ERR_H +#define SM_ERR_H + +/* Errors from the secure monitor */ +#define SM_ERR_UNDEFINED_SMC 0xFFFFFFFF /* Unknown SMC (defined by ARM DEN 0028A(0.9.0) */ +#define SM_ERR_INVALID_PARAMETERS -2 +#define SM_ERR_INTERRUPTED -3 /* Got interrupted. Call back with restart SMC */ +#define SM_ERR_UNEXPECTED_RESTART -4 /* Got an restart SMC when we didn't expect it */ +#define SM_ERR_BUSY -5 /* Temporarily busy. Call back with original args */ +#define SM_ERR_INTERLEAVED_SMC -6 /* Got a trusted_service SMC when a restart SMC is required */ +#define SM_ERR_INTERNAL_FAILURE -7 /* Unknown error */ +#define SM_ERR_NOT_SUPPORTED -8 +#define SM_ERR_NOT_ALLOWED -9 /* SMC call not allowed */ +#define SM_ERR_END_OF_INPUT -10 + +#endif /* SM_ERR_H */ diff --git a/arm-trusted-firmware/services/spd/trusty/smcall.h b/arm-trusted-firmware/services/spd/trusty/smcall.h new file mode 100644 index 0000000..c66f7db --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/smcall.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMCALL_H +#define SMCALL_H + +#define SMC_NUM_ENTITIES 64U +#define SMC_NUM_ARGS 4U +#define SMC_NUM_PARAMS (SMC_NUM_ARGS - 1U) + +#define SMC_IS_FASTCALL(smc_nr) ((smc_nr) & 0x80000000U) +#define SMC_IS_SMC64(smc_nr) ((smc_nr) & 0x40000000U) +#define SMC_ENTITY(smc_nr) (((smc_nr) & 0x3F000000U) >> 24U) +#define SMC_FUNCTION(smc_nr) ((smc_nr) & 0x0000FFFFU) + +#define SMC_NR(entity, fn, fastcall, smc64) \ + (((((uint32_t)(fastcall)) & 0x1U) << 31U) | \ + (((smc64) & 0x1U) << 30U) | \ + (((entity) & 0x3FU) << 24U) | \ + ((fn) & 0xFFFFU)) + +#define SMC_FASTCALL_NR(entity, fn) SMC_NR((entity), (fn), 1U, 0U) +#define SMC_FASTCALL64_NR(entity, fn) SMC_NR((entity), (fn), 1U, 1U) +#define SMC_YIELDCALL_NR(entity, fn) SMC_NR((entity), (fn), 0U, 0U) +#define SMC_YIELDCALL64_NR(entity, fn) SMC_NR((entity), (fn), 0U, 1U) + +#define SMC_ENTITY_ARCH 0U /* ARM Architecture calls */ +#define SMC_ENTITY_CPU 1U /* CPU Service calls */ +#define SMC_ENTITY_SIP 2U /* SIP Service calls */ +#define SMC_ENTITY_OEM 3U /* OEM Service calls */ +#define SMC_ENTITY_STD 4U /* Standard Service calls */ +#define SMC_ENTITY_RESERVED 5U /* Reserved for future use */ +#define SMC_ENTITY_TRUSTED_APP 48U /* Trusted Application calls */ +#define SMC_ENTITY_TRUSTED_OS 50U /* Trusted OS calls */ +#define SMC_ENTITY_LOGGING 51U /* Used for secure -> nonsecure logging */ +#define SMC_ENTITY_SECURE_MONITOR 60U /* Trusted OS calls internal to secure monitor */ + +/* FC = Fast call, YC = Yielding call */ +#define SMC_YC_RESTART_LAST SMC_YIELDCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0U) +#define SMC_YC_NOP SMC_YIELDCALL_NR (SMC_ENTITY_SECURE_MONITOR, 1U) + +/* + * Return from secure os to non-secure os with return value in r1 + */ +#define SMC_YC_NS_RETURN SMC_YIELDCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0U) + +#define SMC_FC_RESERVED SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0U) +#define SMC_FC_FIQ_EXIT SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 1U) +#define SMC_FC_REQUEST_FIQ SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 2U) +#define SMC_FC_GET_NEXT_IRQ SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 3U) +#define SMC_FC_FIQ_ENTER SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 4U) + +#define SMC_FC64_SET_FIQ_HANDLER SMC_FASTCALL64_NR(SMC_ENTITY_SECURE_MONITOR, 5U) +#define SMC_FC64_GET_FIQ_REGS SMC_FASTCALL64_NR (SMC_ENTITY_SECURE_MONITOR, 6U) + +#define SMC_FC_CPU_SUSPEND SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 7U) +#define SMC_FC_CPU_RESUME SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 8U) + +#define SMC_FC_AARCH_SWITCH SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 9U) +#define SMC_FC_GET_VERSION_STR SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 10U) + +/* Trusted OS entity calls */ +#define SMC_YC_VIRTIO_GET_DESCR SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 20U) +#define SMC_YC_VIRTIO_START SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 21U) +#define SMC_YC_VIRTIO_STOP SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 22U) + +#define SMC_YC_VDEV_RESET SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 23U) +#define SMC_YC_VDEV_KICK_VQ SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 24U) +#define SMC_YC_SET_ROT_PARAMS SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 65535U) + +/* + * Standard Trusted OS Function IDs that fall under Trusted OS call range + * according to SMC calling convention + */ +#define SMC_FC64_GET_UUID SMC_FASTCALL64_NR(63U, 0xFF01U) /* Implementation UID */ +#define SMC_FC_GET_UUID SMC_FASTCALL_NR(63U, 0xFF01U) /* Implementation.UID */ + +#endif /* SMCALL_H */ diff --git a/arm-trusted-firmware/services/spd/trusty/trusty.c b/arm-trusted-firmware/services/spd/trusty/trusty.c new file mode 100644 index 0000000..7daebcd --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/trusty.c @@ -0,0 +1,541 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "sm_err.h" +#include "smcall.h" + +/* Trusty UID: RFC-4122 compliant UUID version 4 */ +DEFINE_SVC_UUID2(trusty_uuid, + 0x40ee25f0, 0xa2bc, 0x304c, 0x8c, 0x4c, + 0xa1, 0x73, 0xc5, 0x7d, 0x8a, 0xf1); + +/* macro to check if Hypervisor is enabled in the HCR_EL2 register */ +#define HYP_ENABLE_FLAG 0x286001U + +/* length of Trusty's input parameters (in bytes) */ +#define TRUSTY_PARAMS_LEN_BYTES (4096U * 2) + +struct trusty_stack { + uint8_t space[PLATFORM_STACK_SIZE] __aligned(16); + uint32_t end; +}; + +struct trusty_cpu_ctx { + cpu_context_t cpu_ctx; + void *saved_sp; + uint32_t saved_security_state; + int32_t fiq_handler_active; + uint64_t fiq_handler_pc; + uint64_t fiq_handler_cpsr; + uint64_t fiq_handler_sp; + uint64_t fiq_pc; + uint64_t fiq_cpsr; + uint64_t fiq_sp_el1; + gp_regs_t fiq_gpregs; + struct trusty_stack secure_stack; +}; + +struct smc_args { + uint64_t r0; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; +}; + +static struct trusty_cpu_ctx trusty_cpu_ctx[PLATFORM_CORE_COUNT]; + +struct smc_args trusty_init_context_stack(void **sp, void *new_stack); +struct smc_args trusty_context_switch_helper(void **sp, void *smc_params); + +static uint32_t current_vmid; + +static struct trusty_cpu_ctx *get_trusty_ctx(void) +{ + return &trusty_cpu_ctx[plat_my_core_pos()]; +} + +static bool is_hypervisor_mode(void) +{ + uint64_t hcr = read_hcr(); + + return ((hcr & HYP_ENABLE_FLAG) != 0U) ? true : false; +} + +static struct smc_args trusty_context_switch(uint32_t security_state, uint64_t r0, + uint64_t r1, uint64_t r2, uint64_t r3) +{ + struct smc_args args, ret_args; + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + struct trusty_cpu_ctx *ctx_smc; + + assert(ctx->saved_security_state != security_state); + + args.r7 = 0; + if (is_hypervisor_mode()) { + /* According to the ARM DEN0028A spec, VMID is stored in x7 */ + ctx_smc = cm_get_context(NON_SECURE); + assert(ctx_smc != NULL); + args.r7 = SMC_GET_GP(ctx_smc, CTX_GPREG_X7); + } + /* r4, r5, r6 reserved for future use. */ + args.r6 = 0; + args.r5 = 0; + args.r4 = 0; + args.r3 = r3; + args.r2 = r2; + args.r1 = r1; + args.r0 = r0; + + /* + * To avoid the additional overhead in PSCI flow, skip FP context + * saving/restoring in case of CPU suspend and resume, assuming that + * when it's needed the PSCI caller has preserved FP context before + * going here. + */ + if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME) + fpregs_context_save(get_fpregs_ctx(cm_get_context(security_state))); + cm_el1_sysregs_context_save(security_state); + + ctx->saved_security_state = security_state; + ret_args = trusty_context_switch_helper(&ctx->saved_sp, &args); + + assert(ctx->saved_security_state == ((security_state == 0U) ? 1U : 0U)); + + cm_el1_sysregs_context_restore(security_state); + if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME) + fpregs_context_restore(get_fpregs_ctx(cm_get_context(security_state))); + + cm_set_next_eret_context(security_state); + + return ret_args; +} + +static uint64_t trusty_fiq_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + struct smc_args ret; + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + + assert(!is_caller_secure(flags)); + + ret = trusty_context_switch(NON_SECURE, SMC_FC_FIQ_ENTER, 0, 0, 0); + if (ret.r0 != 0U) { + SMC_RET0(handle); + } + + if (ctx->fiq_handler_active != 0) { + INFO("%s: fiq handler already active\n", __func__); + SMC_RET0(handle); + } + + ctx->fiq_handler_active = 1; + (void)memcpy(&ctx->fiq_gpregs, get_gpregs_ctx(handle), sizeof(ctx->fiq_gpregs)); + ctx->fiq_pc = SMC_GET_EL3(handle, CTX_ELR_EL3); + ctx->fiq_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3); + ctx->fiq_sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1); + + write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp); + cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, (uint32_t)ctx->fiq_handler_cpsr); + + SMC_RET0(handle); +} + +static uint64_t trusty_set_fiq_handler(void *handle, uint64_t cpu, + uint64_t handler, uint64_t stack) +{ + struct trusty_cpu_ctx *ctx; + + if (cpu >= (uint64_t)PLATFORM_CORE_COUNT) { + ERROR("%s: cpu %" PRId64 " >= %d\n", __func__, cpu, PLATFORM_CORE_COUNT); + return (uint64_t)SM_ERR_INVALID_PARAMETERS; + } + + ctx = &trusty_cpu_ctx[cpu]; + ctx->fiq_handler_pc = handler; + ctx->fiq_handler_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3); + ctx->fiq_handler_sp = stack; + + SMC_RET1(handle, 0); +} + +static uint64_t trusty_get_fiq_regs(void *handle) +{ + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + uint64_t sp_el0 = read_ctx_reg(&ctx->fiq_gpregs, CTX_GPREG_SP_EL0); + + SMC_RET4(handle, ctx->fiq_pc, ctx->fiq_cpsr, sp_el0, ctx->fiq_sp_el1); +} + +static uint64_t trusty_fiq_exit(void *handle, uint64_t x1, uint64_t x2, uint64_t x3) +{ + struct smc_args ret; + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + + if (ctx->fiq_handler_active == 0) { + NOTICE("%s: fiq handler not active\n", __func__); + SMC_RET1(handle, (uint64_t)SM_ERR_INVALID_PARAMETERS); + } + + ret = trusty_context_switch(NON_SECURE, SMC_FC_FIQ_EXIT, 0, 0, 0); + if (ret.r0 != 1U) { + INFO("%s(%p) SMC_FC_FIQ_EXIT returned unexpected value, %" PRId64 "\n", + __func__, handle, ret.r0); + } + + /* + * Restore register state to state recorded on fiq entry. + * + * x0, sp_el1, pc and cpsr need to be restored because el1 cannot + * restore them. + * + * x1-x4 and x8-x17 need to be restored here because smc_handler64 + * corrupts them (el1 code also restored them). + */ + (void)memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs)); + ctx->fiq_handler_active = 0; + write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1); + cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, (uint32_t)ctx->fiq_cpsr); + + SMC_RET0(handle); +} + +static uintptr_t trusty_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) +{ + struct smc_args ret; + uint32_t vmid = 0U; + entry_point_info_t *ep_info = bl31_plat_get_next_image_ep_info(SECURE); + + /* + * Return success for SET_ROT_PARAMS if Trusty is not present, as + * Verified Boot is not even supported and returning success here + * would not compromise the boot process. + */ + if ((ep_info == NULL) && (smc_fid == SMC_YC_SET_ROT_PARAMS)) { + SMC_RET1(handle, 0); + } else if (ep_info == NULL) { + SMC_RET1(handle, SMC_UNK); + } else { + ; /* do nothing */ + } + + if (is_caller_secure(flags)) { + if (smc_fid == SMC_YC_NS_RETURN) { + ret = trusty_context_switch(SECURE, x1, 0, 0, 0); + SMC_RET8(handle, ret.r0, ret.r1, ret.r2, ret.r3, + ret.r4, ret.r5, ret.r6, ret.r7); + } + INFO("%s (0x%x, 0x%lx, 0x%lx, 0x%lx, 0x%lx, %p, %p, 0x%lx) \ + cpu %d, unknown smc\n", + __func__, smc_fid, x1, x2, x3, x4, cookie, handle, flags, + plat_my_core_pos()); + SMC_RET1(handle, SMC_UNK); + } else { + switch (smc_fid) { + case SMC_FC64_GET_UUID: + case SMC_FC_GET_UUID: + /* provide the UUID for the service to the client */ + SMC_UUID_RET(handle, trusty_uuid); + break; + case SMC_FC64_SET_FIQ_HANDLER: + return trusty_set_fiq_handler(handle, x1, x2, x3); + case SMC_FC64_GET_FIQ_REGS: + return trusty_get_fiq_regs(handle); + case SMC_FC_FIQ_EXIT: + return trusty_fiq_exit(handle, x1, x2, x3); + default: + /* Not all OENs greater than SMC_ENTITY_SECURE_MONITOR are supported */ + if (SMC_ENTITY(smc_fid) > SMC_ENTITY_SECURE_MONITOR) { + VERBOSE("%s: unsupported SMC FID (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); + } + + if (is_hypervisor_mode()) + vmid = SMC_GET_GP(handle, CTX_GPREG_X7); + + if ((current_vmid != 0) && (current_vmid != vmid)) { + /* This message will cause SMC mechanism + * abnormal in multi-guest environment. + * Change it to WARN in case you need it. + */ + VERBOSE("Previous SMC not finished.\n"); + SMC_RET1(handle, SM_ERR_BUSY); + } + current_vmid = vmid; + ret = trusty_context_switch(NON_SECURE, smc_fid, x1, + x2, x3); + current_vmid = 0; + SMC_RET1(handle, ret.r0); + } + } +} + +static int32_t trusty_init(void) +{ + entry_point_info_t *ep_info; + struct smc_args zero_args = {0}; + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + uint32_t cpu = plat_my_core_pos(); + uint64_t reg_width = GET_RW(read_ctx_reg(get_el3state_ctx(&ctx->cpu_ctx), + CTX_SPSR_EL3)); + + /* + * Get information about the Trusty image. Its absence is a critical + * failure. + */ + ep_info = bl31_plat_get_next_image_ep_info(SECURE); + assert(ep_info != NULL); + + fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE))); + cm_el1_sysregs_context_save(NON_SECURE); + + cm_set_context(&ctx->cpu_ctx, SECURE); + cm_init_my_context(ep_info); + + /* + * Adjust secondary cpu entry point for 32 bit images to the + * end of exception vectors + */ + if ((cpu != 0U) && (reg_width == MODE_RW_32)) { + INFO("trusty: cpu %d, adjust entry point to 0x%lx\n", + cpu, ep_info->pc + (1U << 5)); + cm_set_elr_el3(SECURE, ep_info->pc + (1U << 5)); + } + + cm_el1_sysregs_context_restore(SECURE); + fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE))); + cm_set_next_eret_context(SECURE); + + ctx->saved_security_state = ~0U; /* initial saved state is invalid */ + (void)trusty_init_context_stack(&ctx->saved_sp, &ctx->secure_stack.end); + + (void)trusty_context_switch_helper(&ctx->saved_sp, &zero_args); + + cm_el1_sysregs_context_restore(NON_SECURE); + fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE))); + cm_set_next_eret_context(NON_SECURE); + + return 1; +} + +static void trusty_cpu_suspend(uint32_t off) +{ + struct smc_args ret; + + ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_SUSPEND, off, 0, 0); + if (ret.r0 != 0U) { + INFO("%s: cpu %d, SMC_FC_CPU_SUSPEND returned unexpected value, %" PRId64 "\n", + __func__, plat_my_core_pos(), ret.r0); + } +} + +static void trusty_cpu_resume(uint32_t on) +{ + struct smc_args ret; + + ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_RESUME, on, 0, 0); + if (ret.r0 != 0U) { + INFO("%s: cpu %d, SMC_FC_CPU_RESUME returned unexpected value, %" PRId64 "\n", + __func__, plat_my_core_pos(), ret.r0); + } +} + +static int32_t trusty_cpu_off_handler(u_register_t max_off_lvl) +{ + trusty_cpu_suspend(max_off_lvl); + + return 0; +} + +static void trusty_cpu_on_finish_handler(u_register_t max_off_lvl) +{ + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + + if (ctx->saved_sp == NULL) { + (void)trusty_init(); + } else { + trusty_cpu_resume(max_off_lvl); + } +} + +static void trusty_cpu_suspend_handler(u_register_t max_off_lvl) +{ + trusty_cpu_suspend(max_off_lvl); +} + +static void trusty_cpu_suspend_finish_handler(u_register_t max_off_lvl) +{ + trusty_cpu_resume(max_off_lvl); +} + +static const spd_pm_ops_t trusty_pm = { + .svc_off = trusty_cpu_off_handler, + .svc_suspend = trusty_cpu_suspend_handler, + .svc_on_finish = trusty_cpu_on_finish_handler, + .svc_suspend_finish = trusty_cpu_suspend_finish_handler, +}; + +void plat_trusty_set_boot_args(aapcs64_params_t *args); + +#if !defined(TSP_SEC_MEM_SIZE) && defined(BL32_MEM_SIZE) +#define TSP_SEC_MEM_SIZE BL32_MEM_SIZE +#endif + +#ifdef TSP_SEC_MEM_SIZE +#pragma weak plat_trusty_set_boot_args +void plat_trusty_set_boot_args(aapcs64_params_t *args) +{ + args->arg0 = TSP_SEC_MEM_SIZE; +} +#endif + +static int32_t trusty_setup(void) +{ + entry_point_info_t *ep_info; + uint32_t instr; + uint32_t flags; + int32_t ret; + bool aarch32 = false; + + /* Get trusty's entry point info */ + ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (ep_info == NULL) { + VERBOSE("Trusty image missing.\n"); + return -1; + } + + /* memmap first page of trusty's code memory before peeking */ + ret = mmap_add_dynamic_region(ep_info->pc, /* PA */ + ep_info->pc, /* VA */ + PAGE_SIZE, /* size */ + MT_SECURE | MT_RW_DATA); /* attrs */ + assert(ret == 0); + + /* peek into trusty's code to see if we have a 32-bit or 64-bit image */ + instr = *(uint32_t *)ep_info->pc; + + if (instr >> 24 == 0xeaU) { + INFO("trusty: Found 32 bit image\n"); + aarch32 = true; + } else if (instr >> 8 == 0xd53810U || instr >> 16 == 0x9400U) { + INFO("trusty: Found 64 bit image\n"); + } else { + ERROR("trusty: Found unknown image, 0x%x\n", instr); + return -1; + } + + /* unmap trusty's memory page */ + (void)mmap_remove_dynamic_region(ep_info->pc, PAGE_SIZE); + + SET_PARAM_HEAD(ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); + if (!aarch32) + ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + else + ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DAIF_FIQ_BIT | + DAIF_IRQ_BIT | + DAIF_ABT_BIT); + (void)memset(&ep_info->args, 0, sizeof(ep_info->args)); + plat_trusty_set_boot_args(&ep_info->args); + + /* register init handler */ + bl31_register_bl32_init(trusty_init); + + /* register power management hooks */ + psci_register_spd_pm_hook(&trusty_pm); + + /* register interrupt handler */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, + trusty_fiq_handler, + flags); + if (ret != 0) { + VERBOSE("trusty: failed to register fiq handler, ret = %d\n", ret); + } + + if (aarch32) { + entry_point_info_t *ns_ep_info; + uint32_t spsr; + + ns_ep_info = bl31_plat_get_next_image_ep_info(NON_SECURE); + if (ns_ep_info == NULL) { + NOTICE("Trusty: non-secure image missing.\n"); + return -1; + } + spsr = ns_ep_info->spsr; + if (GET_RW(spsr) == MODE_RW_64 && GET_EL(spsr) == MODE_EL2) { + spsr &= ~(MODE_EL_MASK << MODE_EL_SHIFT); + spsr |= MODE_EL1 << MODE_EL_SHIFT; + } + if (GET_RW(spsr) == MODE_RW_32 && GET_M32(spsr) == MODE32_hyp) { + spsr &= ~(MODE32_MASK << MODE32_SHIFT); + spsr |= MODE32_svc << MODE32_SHIFT; + } + if (spsr != ns_ep_info->spsr) { + NOTICE("Trusty: Switch bl33 from EL2 to EL1 (spsr 0x%x -> 0x%x)\n", + ns_ep_info->spsr, spsr); + ns_ep_info->spsr = spsr; + } + } + + return 0; +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + trusty_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + trusty_setup, + trusty_smc_handler +); + +/* Define a SPD runtime service descriptor for yielding SMC calls */ +DECLARE_RT_SVC( + trusty_std, + + OEN_TAP_START, + SMC_ENTITY_SECURE_MONITOR, + SMC_TYPE_YIELD, + NULL, + trusty_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/trusty/trusty.mk b/arm-trusted-firmware/services/spd/trusty/trusty.mk new file mode 100644 index 0000000..43b80bb --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/trusty.mk @@ -0,0 +1,18 @@ +# +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +SPD_INCLUDES := + +SPD_SOURCES := services/spd/trusty/trusty.c \ + services/spd/trusty/trusty_helpers.S + +ifeq (${TRUSTY_SPD_WITH_GENERIC_SERVICES},1) +SPD_SOURCES += services/spd/trusty/generic-arm64-smcall.c +endif + +NEED_BL32 := yes + +CTX_INCLUDE_FPREGS := 1 diff --git a/arm-trusted-firmware/services/spd/trusty/trusty_helpers.S b/arm-trusted-firmware/services/spd/trusty/trusty_helpers.S new file mode 100644 index 0000000..da5cb57 --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/trusty_helpers.S @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +.macro push ra, rb, sp=sp + stp \ra, \rb, [\sp,#-16]! +.endm + +.macro pop ra, rb, sp=sp + ldp \ra, \rb, [\sp], #16 +.endm + + .global trusty_context_switch_helper +func trusty_context_switch_helper + push x8, xzr + push x19, x20 + push x21, x22 + push x23, x24 + push x25, x26 + push x27, x28 + push x29, x30 + + mov x9, sp + ldr x10, [x0] + mov sp, x10 + str x9, [x0] + + pop x29, x30 + pop x27, x28 + pop x25, x26 + pop x23, x24 + pop x21, x22 + pop x19, x20 + pop x8, xzr + + ldr x2, [x1] + ldr x3, [x1, #0x08] + ldr x4, [x1, #0x10] + ldr x5, [x1, #0x18] + ldr x6, [x1, #0x20] + ldr x7, [x1, #0x28] + ldr x10, [x1, #0x30] + ldr x11, [x1, #0x38] + + stp x2, x3, [x8] + stp x4, x5, [x8, #16] + stp x6, x7, [x8, #32] + stp x10, x11, [x8, #48] + + ret +endfunc trusty_context_switch_helper + + .global trusty_init_context_stack +func trusty_init_context_stack + push x8, xzr, x1 + push xzr, xzr, x1 + push xzr, xzr, x1 + push xzr, xzr, x1 + push xzr, xzr, x1 + push xzr, xzr, x1 + adr x9, el3_exit + push xzr, x9, x1 + str x1, [x0] + ret +endfunc trusty_init_context_stack diff --git a/arm-trusted-firmware/services/spd/tspd/tspd.mk b/arm-trusted-firmware/services/spd/tspd/tspd.mk new file mode 100644 index 0000000..bda8338 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd.mk @@ -0,0 +1,46 @@ +# +# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +TSPD_DIR := services/spd/tspd + +ifeq (${ERROR_DEPRECATED},0) +SPD_INCLUDES := -Iinclude/bl32/tsp +endif + +SPD_SOURCES := services/spd/tspd/tspd_common.c \ + services/spd/tspd/tspd_helpers.S \ + services/spd/tspd/tspd_main.c \ + services/spd/tspd/tspd_pm.c + +# This dispatcher is paired with a Test Secure Payload source and we intend to +# build the Test Secure Payload along with this dispatcher. +# +# In cases where an associated Secure Payload lies outside this build +# system/source tree, the the dispatcher Makefile can either invoke an external +# build command or assume it pre-built + +BL32_ROOT := bl32/tsp + +# Include SP's Makefile. The assumption is that the TSP's build system is +# compatible with that of Trusted Firmware, and it'll add and populate necessary +# build targets and variables +include ${BL32_ROOT}/tsp.mk + +# Let the top-level Makefile know that we intend to build the SP from source +NEED_BL32 := yes + +# Flag used to enable routing of non-secure interrupts to EL3 when they are +# generated while the code is executing in S-EL1/0. +TSP_NS_INTR_ASYNC_PREEMPT := 0 + +ifeq ($(EL3_EXCEPTION_HANDLING),1) +ifeq ($(TSP_NS_INTR_ASYNC_PREEMPT),0) +$(error When EL3_EXCEPTION_HANDLING=1, TSP_NS_INTR_ASYNC_PREEMPT must also be 1) +endif +endif + +$(eval $(call assert_boolean,TSP_NS_INTR_ASYNC_PREEMPT)) +$(eval $(call add_define,TSP_NS_INTR_ASYNC_PREEMPT)) diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_common.c b/arm-trusted-firmware/services/spd/tspd/tspd_common.c new file mode 100644 index 0000000..063fd01 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_common.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "tspd_private.h" + +/******************************************************************************* + * Given a secure payload entrypoint info pointer, entry point PC, register + * width, cpu id & pointer to a context data structure, this function will + * initialize tsp context and entry point info for the secure payload + ******************************************************************************/ +void tspd_init_tsp_ep_state(struct entry_point_info *tsp_entry_point, + uint32_t rw, + uint64_t pc, + tsp_context_t *tsp_ctx) +{ + uint32_t ep_attr; + + /* Passing a NULL context is a critical programming error */ + assert(tsp_ctx); + assert(tsp_entry_point); + assert(pc); + + /* + * We support AArch64 TSP for now. + * TODO: Add support for AArch32 TSP + */ + assert(rw == TSP_AARCH64); + + /* Associate this context with the cpu specified */ + tsp_ctx->mpidr = read_mpidr_el1(); + tsp_ctx->state = 0; + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF); + clr_yield_smc_active_flag(tsp_ctx->state); + + cm_set_context(&tsp_ctx->cpu_ctx, SECURE); + + /* initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if (read_sctlr_el3() & SCTLR_EE_BIT) + ep_attr |= EP_EE_BIG; + SET_PARAM_HEAD(tsp_entry_point, PARAM_EP, VERSION_1, ep_attr); + + tsp_entry_point->pc = pc; + tsp_entry_point->spsr = SPSR_64(MODE_EL1, + MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + zeromem(&tsp_entry_point->args, sizeof(tsp_entry_point->args)); +} + +/******************************************************************************* + * This function takes an SP context pointer and: + * 1. Applies the S-EL1 system register context from tsp_ctx->cpu_ctx. + * 2. Saves the current C runtime state (callee saved registers) on the stack + * frame and saves a reference to this state. + * 3. Calls el3_exit() so that the EL3 system and general purpose registers + * from the tsp_ctx->cpu_ctx are used to enter the secure payload image. + ******************************************************************************/ +uint64_t tspd_synchronous_sp_entry(tsp_context_t *tsp_ctx) +{ + uint64_t rc; + + assert(tsp_ctx != NULL); + assert(tsp_ctx->c_rt_ctx == 0); + + /* Apply the Secure EL1 system register context and switch to it */ + assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + rc = tspd_enter_sp(&tsp_ctx->c_rt_ctx); +#if ENABLE_ASSERTIONS + tsp_ctx->c_rt_ctx = 0; +#endif + + return rc; +} + + +/******************************************************************************* + * This function takes an SP context pointer and: + * 1. Saves the S-EL1 system register context tp tsp_ctx->cpu_ctx. + * 2. Restores the current C runtime state (callee saved registers) from the + * stack frame using the reference to this state saved in tspd_enter_sp(). + * 3. It does not need to save any general purpose or EL3 system register state + * as the generic smc entry routine should have saved those. + ******************************************************************************/ +void tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret) +{ + assert(tsp_ctx != NULL); + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + assert(tsp_ctx->c_rt_ctx != 0); + tspd_exit_sp(tsp_ctx->c_rt_ctx, ret); + + /* Should never reach here */ + assert(0); +} + +/******************************************************************************* + * This function takes an SP context pointer and abort any preempted SMC + * request. + * Return 1 if there was a preempted SMC request, 0 otherwise. + ******************************************************************************/ +int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx) +{ + if (!get_yield_smc_active_flag(tsp_ctx->state)) + return 0; + + /* Abort any preempted SMC request */ + clr_yield_smc_active_flag(tsp_ctx->state); + + /* + * Arrange for an entry into the test secure payload. It will + * be returned via TSP_ABORT_DONE case in tspd_smc_handler. + */ + cm_set_elr_el3(SECURE, + (uint64_t) &tsp_vectors->abort_yield_smc_entry); + uint64_t rc = tspd_synchronous_sp_entry(tsp_ctx); + + if (rc != 0) + panic(); + + return 1; +} + diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_helpers.S b/arm-trusted-firmware/services/spd/tspd/tspd_helpers.S new file mode 100644 index 0000000..f15d66b --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_helpers.S @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "tspd_private.h" + + .global tspd_enter_sp + /* --------------------------------------------- + * This function is called with SP_EL0 as stack. + * Here we stash our EL3 callee-saved registers + * on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where + * the address of the C runtime context is to be + * saved. + * --------------------------------------------- + */ +func tspd_enter_sp + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #TSPD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #TSPD_C_RT_CTX_X19] + stp x21, x22, [sp, #TSPD_C_RT_CTX_X21] + stp x23, x24, [sp, #TSPD_C_RT_CTX_X23] + stp x25, x26, [sp, #TSPD_C_RT_CTX_X25] + stp x27, x28, [sp, #TSPD_C_RT_CTX_X27] + stp x29, x30, [sp, #TSPD_C_RT_CTX_X29] + + /* --------------------------------------------- + * Everything is setup now. el3_exit() will + * use the secure context to restore to the + * general purpose and EL3 system registers to + * ERET into the secure payload. + * --------------------------------------------- + */ + b el3_exit +endfunc tspd_enter_sp + + /* --------------------------------------------- + * This function is called 'x0' pointing to a C + * runtime context saved in tspd_enter_sp(). It + * restores the saved registers and jumps to + * that runtime with 'x0' as the new sp. This + * destroys the C runtime context that had been + * built on the stack below the saved context by + * the caller. Later the second parameter 'x1' + * is passed as return value to the caller + * --------------------------------------------- + */ + .global tspd_exit_sp +func tspd_exit_sp + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(TSPD_C_RT_CTX_X19 - TSPD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(TSPD_C_RT_CTX_X21 - TSPD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(TSPD_C_RT_CTX_X23 - TSPD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(TSPD_C_RT_CTX_X25 - TSPD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(TSPD_C_RT_CTX_X27 - TSPD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(TSPD_C_RT_CTX_X29 - TSPD_C_RT_CTX_SIZE)] + + /* --------------------------------------------- + * This should take us back to the instruction + * after the call to the last tspd_enter_sp(). + * Place the second parameter to x0 so that the + * caller will see it as a return value from the + * original entry call + * --------------------------------------------- + */ + mov x0, x1 + ret +endfunc tspd_exit_sp diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_main.c b/arm-trusted-firmware/services/spd/tspd/tspd_main.c new file mode 100644 index 0000000..6cb4992 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_main.c @@ -0,0 +1,819 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/******************************************************************************* + * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a + * plug-in component to the Secure Monitor, registered as a runtime service. The + * SPD is expected to be a functional extension of the Secure Payload (SP) that + * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting + * the Trusted OS/Applications range to the dispatcher. The SPD will either + * handle the request locally or delegate it to the Secure Payload. It is also + * responsible for initialising and maintaining communication with the SP. + ******************************************************************************/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tspd_private.h" + +/******************************************************************************* + * Address of the entrypoint vector table in the Secure Payload. It is + * initialised once on the primary core after a cold boot. + ******************************************************************************/ +tsp_vectors_t *tsp_vectors; + +/******************************************************************************* + * Array to keep track of per-cpu Secure Payload state + ******************************************************************************/ +tsp_context_t tspd_sp_context[TSPD_CORE_COUNT]; + + +/* TSP UID */ +DEFINE_SVC_UUID2(tsp_uuid, + 0xa056305b, 0x9132, 0x7b42, 0x98, 0x11, + 0x71, 0x68, 0xca, 0x50, 0xf3, 0xfa); + +int32_t tspd_init(void); + +/* + * This helper function handles Secure EL1 preemption. The preemption could be + * due Non Secure interrupts or EL3 interrupts. In both the cases we context + * switch to the normal world and in case of EL3 interrupts, it will again be + * routed to EL3 which will get handled at the exception vectors. + */ +uint64_t tspd_handle_sp_preemption(void *handle) +{ + cpu_context_t *ns_cpu_context; + + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * To allow Secure EL1 interrupt handler to re-enter TSP while TSP + * is preempted, the secure system register context which will get + * overwritten must be additionally saved. This is currently done + * by the TSPD S-EL1 interrupt handler. + */ + + /* + * Restore non-secure state. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + /* + * The TSP was preempted during execution of a Yielding SMC Call. + * Return back to the normal world with SMC_PREEMPTED as error + * code in x0. + */ + SMC_RET1(ns_cpu_context, SMC_PREEMPTED); +} + +/******************************************************************************* + * This function is the handler registered for S-EL1 interrupts by the TSPD. It + * validates the interrupt and upon success arranges entry into the TSP at + * 'tsp_sel1_intr_entry()' for handling the interrupt. + * Typically, interrupts for a specific security state get handled in the same + * security execption level if the execution is in the same security state. For + * example, if a non-secure interrupt gets fired when CPU is executing in NS-EL2 + * it gets handled in the non-secure world. + * However, interrupts belonging to the opposite security state typically demand + * a world(context) switch. This is inline with the security principle which + * states a secure interrupt has to be handled in the secure world. + * Hence, the TSPD in EL3 expects the context(handle) for a secure interrupt to + * be non-secure and vice versa. + * However, a race condition between non-secure and secure interrupts can lead to + * a scenario where the above assumptions do not hold true. This is demonstrated + * below through Note 1. + ******************************************************************************/ +static uint64_t tspd_sel1_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + uint32_t linear_id; + tsp_context_t *tsp_ctx; + + /* Get a reference to this cpu's TSP context */ + linear_id = plat_my_core_pos(); + tsp_ctx = &tspd_sp_context[linear_id]; + +#if TSP_NS_INTR_ASYNC_PREEMPT + + /* + * Note 1: + * Under the current interrupt routing model, interrupts from other + * world are routed to EL3 when TSP_NS_INTR_ASYNC_PREEMPT is enabled. + * Consider the following scenario: + * 1/ A non-secure payload(like tftf) requests a secure service from + * TSP by invoking a yielding SMC call. + * 2/ Later, execution jumps to TSP in S-EL1 with the help of TSP + * Dispatcher in Secure Monitor(EL3). + * 3/ While CPU is executing TSP, a Non-secure interrupt gets fired. + * this demands a context switch to the non-secure world through + * secure monitor. + * 4/ Consequently, TSP in S-EL1 get asynchronously pre-empted and + * execution switches to secure monitor(EL3). + * 5/ EL3 tries to triage the (Non-secure) interrupt based on the + * highest pending interrupt. + * 6/ However, while the NS Interrupt was pending, secure timer gets + * fired which makes a S-EL1 interrupt to be pending. + * 7/ Hence, execution jumps to this companion handler of S-EL1 + * interrupt (i.e., tspd_sel1_interrupt_handler) even though the TSP + * was pre-empted due to non-secure interrupt. + * 8/ The above sequence of events explain how TSP was pre-empted by + * S-EL1 interrupt indirectly in an asynchronous way. + * 9/ Hence, we track the TSP pre-emption by S-EL1 interrupt using a + * boolean variable per each core. + * 10/ This helps us to indicate that SMC call for TSP service was + * pre-empted when execution resumes in non-secure world. + */ + + /* Check the security state when the exception was generated */ + if (get_interrupt_src_ss(flags) == NON_SECURE) { + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering the TSP */ + cm_el1_sysregs_context_save(NON_SECURE); + tsp_ctx->preempted_by_sel1_intr = false; + } else { + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(SECURE)); + + /* Save the secure context before entering the TSP for S-EL1 + * interrupt handling + */ + cm_el1_sysregs_context_save(SECURE); + tsp_ctx->preempted_by_sel1_intr = true; + } +#else + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering the TSP */ + cm_el1_sysregs_context_save(NON_SECURE); +#endif + + assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE)); + + /* + * Determine if the TSP was previously preempted. Its last known + * context has to be preserved in this case. + * The TSP should return control to the TSPD after handling this + * S-EL1 interrupt. Preserve essential EL3 context to allow entry into + * the TSP at the S-EL1 interrupt entry point using the 'cpu_context' + * structure. There is no need to save the secure system register + * context since the TSP is supposed to preserve it during S-EL1 + * interrupt handling. + */ + if (get_yield_smc_active_flag(tsp_ctx->state)) { + tsp_ctx->saved_spsr_el3 = (uint32_t)SMC_GET_EL3(&tsp_ctx->cpu_ctx, + CTX_SPSR_EL3); + tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx, + CTX_ELR_EL3); +#if TSP_NS_INTR_ASYNC_PREEMPT + memcpy(&tsp_ctx->sp_ctx, &tsp_ctx->cpu_ctx, TSPD_SP_CTX_SIZE); +#endif + } + + cm_el1_sysregs_context_restore(SECURE); + cm_set_elr_spsr_el3(SECURE, (uint64_t) &tsp_vectors->sel1_intr_entry, + SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)); + + cm_set_next_eret_context(SECURE); + + /* + * Tell the TSP that it has to handle a S-EL1 interrupt synchronously. + * Also the instruction in normal world where the interrupt was + * generated is passed for debugging purposes. It is safe to retrieve + * this address from ELR_EL3 as the secure context will not take effect + * until el3_exit(). + */ + SMC_RET2(&tsp_ctx->cpu_ctx, TSP_HANDLE_SEL1_INTR_AND_RETURN, read_elr_el3()); +} + +#if TSP_NS_INTR_ASYNC_PREEMPT +/******************************************************************************* + * This function is the handler registered for Non secure interrupts by the + * TSPD. It validates the interrupt and upon success arranges entry into the + * normal world for handling the interrupt. + ******************************************************************************/ +static uint64_t tspd_ns_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == SECURE); + + /* + * Disable the routing of NS interrupts from secure world to EL3 while + * interrupted on this core. + */ + disable_intr_rm_local(INTR_TYPE_NS, SECURE); + + return tspd_handle_sp_preemption(handle); +} +#endif + +/******************************************************************************* + * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type + * (aarch32/aarch64) if not already known and initialises the context for entry + * into the SP for its initialisation. + ******************************************************************************/ +static int32_t tspd_setup(void) +{ + entry_point_info_t *tsp_ep_info; + uint32_t linear_id; + + linear_id = plat_my_core_pos(); + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. TODO: Add support to + * conditionally include the SPD service + */ + tsp_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (!tsp_ep_info) { + WARN("No TSP provided by BL2 boot loader, Booting device" + " without TSP initialization. SMC`s destined for TSP" + " will return SMC_UNK\n"); + return 1; + } + + /* + * If there's no valid entry point for SP, we return a non-zero value + * signalling failure initializing the service. We bail out without + * registering any handlers + */ + if (!tsp_ep_info->pc) + return 1; + + /* + * We could inspect the SP image and determine its execution + * state i.e whether AArch32 or AArch64. Assuming it's AArch64 + * for the time being. + */ + tspd_init_tsp_ep_state(tsp_ep_info, + TSP_AARCH64, + tsp_ep_info->pc, + &tspd_sp_context[linear_id]); + +#if TSP_INIT_ASYNC + bl31_set_next_image_type(SECURE); +#else + /* + * All TSPD initialization done. Now register our init function with + * BL31 for deferred invocation + */ + bl31_register_bl32_init(&tspd_init); +#endif + return 0; +} + +/******************************************************************************* + * This function passes control to the Secure Payload image (BL32) for the first + * time on the primary cpu after a cold boot. It assumes that a valid secure + * context has already been created by tspd_setup() which can be directly used. + * It also assumes that a valid non-secure context has been initialised by PSCI + * so it does not need to save and restore any non-secure state. This function + * performs a synchronous entry into the Secure payload. The SP passes control + * back to this routine through a SMC. + ******************************************************************************/ +int32_t tspd_init(void) +{ + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + entry_point_info_t *tsp_entry_point; + uint64_t rc; + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. + */ + tsp_entry_point = bl31_plat_get_next_image_ep_info(SECURE); + assert(tsp_entry_point); + + cm_init_my_context(tsp_entry_point); + + /* + * Arrange for an entry into the test secure payload. It will be + * returned via TSP_ENTRY_DONE case + */ + rc = tspd_synchronous_sp_entry(tsp_ctx); + assert(rc != 0); + + return rc; +} + + +/******************************************************************************* + * This function is responsible for handling all SMCs in the Trusted OS/App + * range from the non-secure state as defined in the SMC Calling Convention + * Document. It is also responsible for communicating with the Secure payload + * to delegate work and return results back to the non-secure state. Lastly it + * will also return any information that the secure payload needs to do the + * work assigned to it. + ******************************************************************************/ +static uintptr_t tspd_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) +{ + cpu_context_t *ns_cpu_context; + uint32_t linear_id = plat_my_core_pos(), ns; + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + uint64_t rc; +#if TSP_INIT_ASYNC + entry_point_info_t *next_image_info; +#endif + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + + switch (smc_fid) { + + /* + * This function ID is used by TSP to indicate that it was + * preempted by a normal world IRQ. + * + */ + case TSP_PREEMPTED: + if (ns) + SMC_RET1(handle, SMC_UNK); + + return tspd_handle_sp_preemption(handle); + + /* + * This function ID is used only by the TSP to indicate that it has + * finished handling a S-EL1 interrupt or was preempted by a higher + * priority pending EL3 interrupt. Execution should resume + * in the normal world. + */ + case TSP_HANDLED_S_EL1_INTR: + if (ns) + SMC_RET1(handle, SMC_UNK); + + assert(handle == cm_get_context(SECURE)); + + /* + * Restore the relevant EL3 state which saved to service + * this SMC. + */ + if (get_yield_smc_active_flag(tsp_ctx->state)) { + SMC_SET_EL3(&tsp_ctx->cpu_ctx, + CTX_SPSR_EL3, + tsp_ctx->saved_spsr_el3); + SMC_SET_EL3(&tsp_ctx->cpu_ctx, + CTX_ELR_EL3, + tsp_ctx->saved_elr_el3); +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Need to restore the previously interrupted + * secure context. + */ + memcpy(&tsp_ctx->cpu_ctx, &tsp_ctx->sp_ctx, + TSPD_SP_CTX_SIZE); +#endif + } + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the TSP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + /* Refer to Note 1 in function tspd_sel1_interrupt_handler()*/ +#if TSP_NS_INTR_ASYNC_PREEMPT + if (tsp_ctx->preempted_by_sel1_intr) { + /* Reset the flag */ + tsp_ctx->preempted_by_sel1_intr = false; + + SMC_RET1(ns_cpu_context, SMC_PREEMPTED); + } else { + SMC_RET0((uint64_t) ns_cpu_context); + } +#else + SMC_RET0((uint64_t) ns_cpu_context); +#endif + + + /* + * This function ID is used only by the SP to indicate it has + * finished initialising itself after a cold boot + */ + case TSP_ENTRY_DONE: + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * Stash the SP entry points information. This is done + * only once on the primary cpu + */ + assert(tsp_vectors == NULL); + tsp_vectors = (tsp_vectors_t *) x1; + + if (tsp_vectors) { + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); + + /* + * TSP has been successfully initialized. Register power + * management hooks with PSCI + */ + psci_register_spd_pm_hook(&tspd_pm); + + /* + * Register an interrupt handler for S-EL1 interrupts + * when generated during code executing in the + * non-secure state. + */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tspd_sel1_interrupt_handler, + flags); + if (rc) + panic(); + +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Register an interrupt handler for NS interrupts when + * generated during code executing in secure state are + * routed to EL3. + */ + flags = 0; + set_interrupt_rm_flag(flags, SECURE); + + rc = register_interrupt_type_handler(INTR_TYPE_NS, + tspd_ns_interrupt_handler, + flags); + if (rc) + panic(); + + /* + * Disable the NS interrupt locally. + */ + disable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + } + + +#if TSP_INIT_ASYNC + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + /* Program EL3 registers to enable entry into the next EL */ + next_image_info = bl31_plat_get_next_image_ep_info(NON_SECURE); + assert(next_image_info); + assert(NON_SECURE == + GET_SECURITY_STATE(next_image_info->h.attr)); + + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(NON_SECURE); + SMC_RET0(cm_get_context(NON_SECURE)); +#else + /* + * SP reports completion. The SPD must have initiated + * the original request through a synchronous entry + * into the SP. Jump back to the original C runtime + * context. + */ + tspd_synchronous_sp_exit(tsp_ctx, x1); + break; +#endif + /* + * This function ID is used only by the SP to indicate it has finished + * aborting a preempted Yielding SMC Call. + */ + case TSP_ABORT_DONE: + + /* + * These function IDs are used only by the SP to indicate it has + * finished: + * 1. turning itself on in response to an earlier psci + * cpu_on request + * 2. resuming itself after an earlier psci cpu_suspend + * request. + */ + case TSP_ON_DONE: + case TSP_RESUME_DONE: + + /* + * These function IDs are used only by the SP to indicate it has + * finished: + * 1. suspending itself after an earlier psci cpu_suspend + * request. + * 2. turning itself off in response to an earlier psci + * cpu_off request. + */ + case TSP_OFF_DONE: + case TSP_SUSPEND_DONE: + case TSP_SYSTEM_OFF_DONE: + case TSP_SYSTEM_RESET_DONE: + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * SP reports completion. The SPD must have initiated the + * original request through a synchronous entry into the SP. + * Jump back to the original C runtime context, and pass x1 as + * return value to the caller + */ + tspd_synchronous_sp_exit(tsp_ctx, x1); + break; + + /* + * Request from non-secure client to perform an + * arithmetic operation or response from secure + * payload to an earlier request. + */ + case TSP_FAST_FID(TSP_ADD): + case TSP_FAST_FID(TSP_SUB): + case TSP_FAST_FID(TSP_MUL): + case TSP_FAST_FID(TSP_DIV): + + case TSP_YIELD_FID(TSP_ADD): + case TSP_YIELD_FID(TSP_SUB): + case TSP_YIELD_FID(TSP_MUL): + case TSP_YIELD_FID(TSP_DIV): + /* + * Request from non-secure client to perform a check + * of the DIT PSTATE bit. + */ + case TSP_YIELD_FID(TSP_CHECK_DIT): + if (ns) { + /* + * This is a fresh request from the non-secure client. + * The parameters are in x1 and x2. Figure out which + * registers need to be preserved, save the non-secure + * state and send the request to the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Check if we are already preempted */ + if (get_yield_smc_active_flag(tsp_ctx->state)) + SMC_RET1(handle, SMC_UNK); + + cm_el1_sysregs_context_save(NON_SECURE); + + /* Save x1 and x2 for use by TSP_GET_ARGS call below */ + store_tsp_args(tsp_ctx, x1, x2); + + /* + * We are done stashing the non-secure context. Ask the + * secure payload to do the work now. + */ + + /* + * Verify if there is a valid context to use, copy the + * operation type and parameters to the secure context + * and jump to the fast smc entry point in the secure + * payload. Entry into S-EL1 will take place upon exit + * from this function. + */ + assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE)); + + /* Set appropriate entry for SMC. + * We expect the TSP to manage the PSTATE.I and PSTATE.F + * flags as appropriate. + */ + if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) { + cm_set_elr_el3(SECURE, (uint64_t) + &tsp_vectors->fast_smc_entry); + } else { + set_yield_smc_active_flag(tsp_ctx->state); + cm_set_elr_el3(SECURE, (uint64_t) + &tsp_vectors->yield_smc_entry); +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Enable the routing of NS interrupts to EL3 + * during processing of a Yielding SMC Call on + * this core. + */ + enable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + +#if EL3_EXCEPTION_HANDLING + /* + * With EL3 exception handling, while an SMC is + * being processed, Non-secure interrupts can't + * preempt Secure execution. However, for + * yielding SMCs, we want preemption to happen; + * so explicitly allow NS preemption in this + * case, and supply the preemption return code + * for TSP. + */ + ehf_allow_ns_preemption(TSP_PREEMPTED); +#endif + } + + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + SMC_RET3(&tsp_ctx->cpu_ctx, smc_fid, x1, x2); + } else { + /* + * This is the result from the secure client of an + * earlier request. The results are in x1-x3. Copy it + * into the non-secure context, save the secure state + * and return to the non-secure state. + */ + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* Restore non-secure state */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_YIELD) { + clr_yield_smc_active_flag(tsp_ctx->state); +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Disable the routing of NS interrupts to EL3 + * after processing of a Yielding SMC Call on + * this core is finished. + */ + disable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + } + + SMC_RET3(ns_cpu_context, x1, x2, x3); + } + assert(0); /* Unreachable */ + + /* + * Request from the non-secure world to abort a preempted Yielding SMC + * Call. + */ + case TSP_FID_ABORT: + /* ABORT should only be invoked by normal world */ + if (!ns) { + assert(0); + break; + } + + assert(handle == cm_get_context(NON_SECURE)); + cm_el1_sysregs_context_save(NON_SECURE); + + /* Abort the preempted SMC request */ + if (!tspd_abort_preempted_smc(tsp_ctx)) { + /* + * If there was no preempted SMC to abort, return + * SMC_UNK. + * + * Restoring the NON_SECURE context is not necessary as + * the synchronous entry did not take place if the + * return code of tspd_abort_preempted_smc is zero. + */ + cm_set_next_eret_context(NON_SECURE); + break; + } + + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + SMC_RET1(handle, SMC_OK); + + /* + * Request from non secure world to resume the preempted + * Yielding SMC Call. + */ + case TSP_FID_RESUME: + /* RESUME should be invoked only by normal world */ + if (!ns) { + assert(0); + break; + } + + /* + * This is a resume request from the non-secure client. + * save the non-secure state and send the request to + * the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Check if we are already preempted before resume */ + if (!get_yield_smc_active_flag(tsp_ctx->state)) + SMC_RET1(handle, SMC_UNK); + + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * We are done stashing the non-secure context. Ask the + * secure payload to do the work now. + */ +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Enable the routing of NS interrupts to EL3 during resumption + * of a Yielding SMC Call on this core. + */ + enable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + +#if EL3_EXCEPTION_HANDLING + /* + * Allow the resumed yielding SMC processing to be preempted by + * Non-secure interrupts. Also, supply the preemption return + * code for TSP. + */ + ehf_allow_ns_preemption(TSP_PREEMPTED); +#endif + + /* We just need to return to the preempted point in + * TSP and the execution will resume as normal. + */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + SMC_RET0(&tsp_ctx->cpu_ctx); + + /* + * This is a request from the secure payload for more arguments + * for an ongoing arithmetic operation requested by the + * non-secure world. Simply return the arguments from the non- + * secure client in the original call. + */ + case TSP_GET_ARGS: + if (ns) + SMC_RET1(handle, SMC_UNK); + + get_tsp_args(tsp_ctx, x1, x2); + SMC_RET2(handle, x1, x2); + + case TOS_CALL_COUNT: + /* + * Return the number of service function IDs implemented to + * provide service to non-secure + */ + SMC_RET1(handle, TSP_NUM_FID); + + case TOS_UID: + /* Return TSP UID to the caller */ + SMC_UUID_RET(handle, tsp_uuid); + + case TOS_CALL_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, TSP_VERSION_MAJOR, TSP_VERSION_MINOR); + + default: + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tspd_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + tspd_setup, + tspd_smc_handler +); + +/* Define a SPD runtime service descriptor for Yielding SMC Calls */ +DECLARE_RT_SVC( + tspd_std, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_YIELD, + NULL, + tspd_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_pm.c b/arm-trusted-firmware/services/spd/tspd/tspd_pm.c new file mode 100644 index 0000000..b95ee8f --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_pm.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "tspd_private.h" + +/******************************************************************************* + * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions + * needed. Nothing at the moment. + ******************************************************************************/ +static void tspd_cpu_on_handler(u_register_t target_cpu) +{ +} + +/******************************************************************************* + * This cpu is being turned off. Allow the TSPD/TSP to perform any actions + * needed + ******************************************************************************/ +static int32_t tspd_cpu_off_handler(u_register_t unused) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); + + /* + * Abort any preempted SMC request before overwriting the SECURE + * context. + */ + tspd_abort_preempted_smc(tsp_ctx); + + /* Program the entry point and enter the TSP */ + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry); + rc = tspd_synchronous_sp_entry(tsp_ctx); + + /* + * Read the response from the TSP. A non-zero return means that + * something went wrong while communicating with the TSP. + */ + if (rc != 0) + panic(); + + /* + * Reset TSP's context for a fresh start when this cpu is turned on + * subsequently. + */ + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF); + + return 0; +} + +/******************************************************************************* + * This cpu is being suspended. S-EL1 state must have been saved in the + * resident cpu (mpidr format) if it is a UP/UP migratable TSP. + ******************************************************************************/ +static void tspd_cpu_suspend_handler(u_register_t max_off_pwrlvl) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); + + /* + * Abort any preempted SMC request before overwriting the SECURE + * context. + */ + tspd_abort_preempted_smc(tsp_ctx); + + /* Program the entry point and enter the TSP */ + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry); + rc = tspd_synchronous_sp_entry(tsp_ctx); + + /* + * Read the response from the TSP. A non-zero return means that + * something went wrong while communicating with the TSP. + */ + if (rc) + panic(); + + /* Update its context to reflect the state the TSP is in */ + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_SUSPEND); +} + +/******************************************************************************* + * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits + * before passing control back to the Secure Monitor. Entry in S-EL1 is done + * after initialising minimal architectural state that guarantees safe + * execution. + ******************************************************************************/ +static void tspd_cpu_on_finish_handler(u_register_t unused) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + entry_point_info_t tsp_on_entrypoint; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF); + + tspd_init_tsp_ep_state(&tsp_on_entrypoint, + TSP_AARCH64, + (uint64_t) &tsp_vectors->cpu_on_entry, + tsp_ctx); + + /* Initialise this cpu's secure context */ + cm_init_my_context(&tsp_on_entrypoint); + +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Disable the NS interrupt locally since it will be enabled globally + * within cm_init_my_context. + */ + disable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + + /* Enter the TSP */ + rc = tspd_synchronous_sp_entry(tsp_ctx); + + /* + * Read the response from the TSP. A non-zero return means that + * something went wrong while communicating with the SP. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state the SP is in */ + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); +} + +/******************************************************************************* + * This cpu has resumed from suspend. The SPD saved the TSP context when it + * completed the preceding suspend call. Use that context to program an entry + * into the TSP to allow it to do any remaining book keeping + ******************************************************************************/ +static void tspd_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_SUSPEND); + + /* Program the entry point, max_off_pwrlvl and enter the SP */ + write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx), + CTX_GPREG_X0, + max_off_pwrlvl); + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_resume_entry); + rc = tspd_synchronous_sp_entry(tsp_ctx); + + /* + * Read the response from the TSP. A non-zero return means that + * something went wrong while communicating with the TSP. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state the SP is in */ + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); +} + +/******************************************************************************* + * Return the type of TSP the TSPD is dealing with. Report the current resident + * cpu (mpidr format) if it is a UP/UP migratable TSP. + ******************************************************************************/ +static int32_t tspd_cpu_migrate_info(u_register_t *resident_cpu) +{ + return TSP_MIGRATE_INFO; +} + +/******************************************************************************* + * System is about to be switched off. Allow the TSPD/TSP to perform + * any actions needed. + ******************************************************************************/ +static void tspd_system_off(void) +{ + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); + + /* + * Abort any preempted SMC request before overwriting the SECURE + * context. + */ + tspd_abort_preempted_smc(tsp_ctx); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry); + + /* Enter the TSP. We do not care about the return value because we + * must continue the shutdown anyway */ + tspd_synchronous_sp_entry(tsp_ctx); +} + +/******************************************************************************* + * System is about to be reset. Allow the TSPD/TSP to perform + * any actions needed. + ******************************************************************************/ +static void tspd_system_reset(void) +{ + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); + + /* + * Abort any preempted SMC request before overwriting the SECURE + * context. + */ + tspd_abort_preempted_smc(tsp_ctx); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry); + + /* + * Enter the TSP. We do not care about the return value because we + * must continue the reset anyway + */ + tspd_synchronous_sp_entry(tsp_ctx); +} + +/******************************************************************************* + * Structure populated by the TSP Dispatcher to be given a chance to perform any + * TSP bookkeeping before PSCI executes a power mgmt. operation. + ******************************************************************************/ +const spd_pm_ops_t tspd_pm = { + .svc_on = tspd_cpu_on_handler, + .svc_off = tspd_cpu_off_handler, + .svc_suspend = tspd_cpu_suspend_handler, + .svc_on_finish = tspd_cpu_on_finish_handler, + .svc_suspend_finish = tspd_cpu_suspend_finish_handler, + .svc_migrate = NULL, + .svc_migrate_info = tspd_cpu_migrate_info, + .svc_system_off = tspd_system_off, + .svc_system_reset = tspd_system_reset +}; diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_private.h b/arm-trusted-firmware/services/spd/tspd/tspd_private.h new file mode 100644 index 0000000..d6c03c9 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_private.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TSPD_PRIVATE_H +#define TSPD_PRIVATE_H + +#include + +#include +#include +#include +#include + +/******************************************************************************* + * Secure Payload PM state information e.g. SP is suspended, uninitialised etc + * and macros to access the state information in the per-cpu 'state' flags + ******************************************************************************/ +#define TSP_PSTATE_OFF 0 +#define TSP_PSTATE_ON 1 +#define TSP_PSTATE_SUSPEND 2 +#define TSP_PSTATE_SHIFT 0 +#define TSP_PSTATE_MASK 0x3 +#define get_tsp_pstate(state) ((state >> TSP_PSTATE_SHIFT) & TSP_PSTATE_MASK) +#define clr_tsp_pstate(state) (state &= ~(TSP_PSTATE_MASK \ + << TSP_PSTATE_SHIFT)) +#define set_tsp_pstate(st, pst) do { \ + clr_tsp_pstate(st); \ + st |= (pst & TSP_PSTATE_MASK) << \ + TSP_PSTATE_SHIFT; \ + } while (0); + + +/* + * This flag is used by the TSPD to determine if the TSP is servicing a yielding + * SMC request prior to programming the next entry into the TSP e.g. if TSP + * execution is preempted by a non-secure interrupt and handed control to the + * normal world. If another request which is distinct from what the TSP was + * previously doing arrives, then this flag will be help the TSPD to either + * reject the new request or service it while ensuring that the previous context + * is not corrupted. + */ +#define YIELD_SMC_ACTIVE_FLAG_SHIFT 2 +#define YIELD_SMC_ACTIVE_FLAG_MASK 1 +#define get_yield_smc_active_flag(state) \ + ((state >> YIELD_SMC_ACTIVE_FLAG_SHIFT) \ + & YIELD_SMC_ACTIVE_FLAG_MASK) +#define set_yield_smc_active_flag(state) (state |= \ + 1 << YIELD_SMC_ACTIVE_FLAG_SHIFT) +#define clr_yield_smc_active_flag(state) (state &= \ + ~(YIELD_SMC_ACTIVE_FLAG_MASK \ + << YIELD_SMC_ACTIVE_FLAG_SHIFT)) + +/******************************************************************************* + * Secure Payload execution state information i.e. aarch32 or aarch64 + ******************************************************************************/ +#define TSP_AARCH32 MODE_RW_32 +#define TSP_AARCH64 MODE_RW_64 + +/******************************************************************************* + * The SPD should know the type of Secure Payload. + ******************************************************************************/ +#define TSP_TYPE_UP PSCI_TOS_NOT_UP_MIG_CAP +#define TSP_TYPE_UPM PSCI_TOS_UP_MIG_CAP +#define TSP_TYPE_MP PSCI_TOS_NOT_PRESENT_MP + +/******************************************************************************* + * Secure Payload migrate type information as known to the SPD. We assume that + * the SPD is dealing with an MP Secure Payload. + ******************************************************************************/ +#define TSP_MIGRATE_INFO TSP_TYPE_MP + +/******************************************************************************* + * Number of cpus that the present on this platform. TODO: Rely on a topology + * tree to determine this in the future to avoid assumptions about mpidr + * allocation + ******************************************************************************/ +#define TSPD_CORE_COUNT PLATFORM_CORE_COUNT + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define TSPD_C_RT_CTX_X19 0x0 +#define TSPD_C_RT_CTX_X20 0x8 +#define TSPD_C_RT_CTX_X21 0x10 +#define TSPD_C_RT_CTX_X22 0x18 +#define TSPD_C_RT_CTX_X23 0x20 +#define TSPD_C_RT_CTX_X24 0x28 +#define TSPD_C_RT_CTX_X25 0x30 +#define TSPD_C_RT_CTX_X26 0x38 +#define TSPD_C_RT_CTX_X27 0x40 +#define TSPD_C_RT_CTX_X28 0x48 +#define TSPD_C_RT_CTX_X29 0x50 +#define TSPD_C_RT_CTX_X30 0x58 +#define TSPD_C_RT_CTX_SIZE 0x60 +#define TSPD_C_RT_CTX_ENTRIES (TSPD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +/******************************************************************************* + * Constants that allow assembler code to preserve caller-saved registers of the + * SP context while performing a TSP preemption. + * Note: These offsets have to match with the offsets for the corresponding + * registers in cpu_context as we are using memcpy to copy the values from + * cpu_context to sp_ctx. + ******************************************************************************/ +#define TSPD_SP_CTX_X0 0x0 +#define TSPD_SP_CTX_X1 0x8 +#define TSPD_SP_CTX_X2 0x10 +#define TSPD_SP_CTX_X3 0x18 +#define TSPD_SP_CTX_X4 0x20 +#define TSPD_SP_CTX_X5 0x28 +#define TSPD_SP_CTX_X6 0x30 +#define TSPD_SP_CTX_X7 0x38 +#define TSPD_SP_CTX_X8 0x40 +#define TSPD_SP_CTX_X9 0x48 +#define TSPD_SP_CTX_X10 0x50 +#define TSPD_SP_CTX_X11 0x58 +#define TSPD_SP_CTX_X12 0x60 +#define TSPD_SP_CTX_X13 0x68 +#define TSPD_SP_CTX_X14 0x70 +#define TSPD_SP_CTX_X15 0x78 +#define TSPD_SP_CTX_X16 0x80 +#define TSPD_SP_CTX_X17 0x88 +#define TSPD_SP_CTX_SIZE 0x90 +#define TSPD_SP_CTX_ENTRIES (TSPD_SP_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* + * The number of arguments to save during a SMC call for TSP. + * Currently only x1 and x2 are used by TSP. + */ +#define TSP_NUM_ARGS 0x2 + +/* AArch64 callee saved general purpose register context structure. */ +DEFINE_REG_STRUCT(c_rt_regs, TSPD_C_RT_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(TSPD_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \ + assert_spd_c_rt_regs_size_mismatch); + +/* SEL1 Secure payload (SP) caller saved register context structure. */ +DEFINE_REG_STRUCT(sp_ctx_regs, TSPD_SP_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(TSPD_SP_CTX_SIZE == sizeof(sp_ctx_regs_t), \ + assert_spd_sp_regs_size_mismatch); + +/******************************************************************************* + * Structure which helps the SPD to maintain the per-cpu state of the SP. + * 'saved_spsr_el3' - temporary copy to allow S-EL1 interrupt handling when + * the TSP has been preempted. + * 'saved_elr_el3' - temporary copy to allow S-EL1 interrupt handling when + * the TSP has been preempted. + * 'state' - collection of flags to track SP state e.g. on/off + * 'mpidr' - mpidr to associate a context with a cpu + * 'c_rt_ctx' - stack address to restore C runtime context from after + * returning from a synchronous entry into the SP. + * 'cpu_ctx' - space to maintain SP architectural state + * 'saved_tsp_args' - space to store arguments for TSP arithmetic operations + * which will queried using the TSP_GET_ARGS SMC by TSP. + * 'sp_ctx' - space to save the SEL1 Secure Payload(SP) caller saved + * register context after it has been preempted by an EL3 + * routed NS interrupt and when a Secure Interrupt is taken + * to SP. + ******************************************************************************/ +typedef struct tsp_context { + uint64_t saved_elr_el3; + uint32_t saved_spsr_el3; + uint32_t state; + uint64_t mpidr; + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; + uint64_t saved_tsp_args[TSP_NUM_ARGS]; +#if TSP_NS_INTR_ASYNC_PREEMPT + sp_ctx_regs_t sp_ctx; + bool preempted_by_sel1_intr; +#endif +} tsp_context_t; + +/* Helper macros to store and retrieve tsp args from tsp_context */ +#define store_tsp_args(_tsp_ctx, _x1, _x2) do {\ + _tsp_ctx->saved_tsp_args[0] = _x1;\ + _tsp_ctx->saved_tsp_args[1] = _x2;\ + } while (0) + +#define get_tsp_args(_tsp_ctx, _x1, _x2) do {\ + _x1 = _tsp_ctx->saved_tsp_args[0];\ + _x2 = _tsp_ctx->saved_tsp_args[1];\ + } while (0) + +/* TSPD power management handlers */ +extern const spd_pm_ops_t tspd_pm; + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +typedef struct tsp_vectors tsp_vectors_t; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +uint64_t tspd_enter_sp(uint64_t *c_rt_ctx); +void __dead2 tspd_exit_sp(uint64_t c_rt_ctx, uint64_t ret); +uint64_t tspd_synchronous_sp_entry(tsp_context_t *tsp_ctx); +void __dead2 tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret); +void tspd_init_tsp_ep_state(struct entry_point_info *tsp_entry_point, + uint32_t rw, + uint64_t pc, + tsp_context_t *tsp_ctx); +int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx); + +uint64_t tspd_handle_sp_preemption(void *handle); + +extern tsp_context_t tspd_sp_context[TSPD_CORE_COUNT]; +extern tsp_vectors_t *tsp_vectors; +#endif /*__ASSEMBLER__*/ + +#endif /* TSPD_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/pci_svc.c b/arm-trusted-firmware/services/std_svc/pci_svc.c new file mode 100644 index 0000000..a02b8a7 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/pci_svc.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +static uint64_t validate_rw_addr_sz(uint32_t addr, uint64_t off, uint64_t sz) +{ + uint32_t nseg; + uint32_t ret; + uint32_t start_end_bus; + + ret = pci_get_bus_for_seg(PCI_ADDR_SEG(addr), &start_end_bus, &nseg); + + if (ret != SMC_PCI_CALL_SUCCESS) { + return SMC_PCI_CALL_INVAL_PARAM; + } + switch (sz) { + case SMC_PCI_SZ_8BIT: + case SMC_PCI_SZ_16BIT: + case SMC_PCI_SZ_32BIT: + break; + default: + return SMC_PCI_CALL_INVAL_PARAM; + } + if ((off + sz) > (PCI_OFFSET_MASK + 1U)) { + return SMC_PCI_CALL_INVAL_PARAM; + } + return SMC_PCI_CALL_SUCCESS; +} + +uint64_t pci_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) +{ + switch (smc_fid) { + case SMC_PCI_VERSION: { + pcie_version ver; + + ver.major = 1U; + ver.minor = 0U; + SMC_RET4(handle, ver.val, 0U, 0U, 0U); + } + case SMC_PCI_FEATURES: + switch (x1) { + case SMC_PCI_VERSION: + case SMC_PCI_FEATURES: + case SMC_PCI_READ: + case SMC_PCI_WRITE: + case SMC_PCI_SEG_INFO: + SMC_RET1(handle, SMC_PCI_CALL_SUCCESS); + default: + SMC_RET1(handle, SMC_PCI_CALL_NOT_SUPPORTED); + } + break; + case SMC_PCI_READ: { + uint32_t ret; + + if (validate_rw_addr_sz(x1, x2, x3) != SMC_PCI_CALL_SUCCESS) { + SMC_RET2(handle, SMC_PCI_CALL_INVAL_PARAM, 0U); + } + if (x4 != 0U) { + SMC_RET2(handle, SMC_PCI_CALL_INVAL_PARAM, 0U); + } + if (pci_read_config(x1, x2, x3, &ret) != 0U) { + SMC_RET2(handle, SMC_PCI_CALL_INVAL_PARAM, 0U); + } else { + SMC_RET2(handle, SMC_PCI_CALL_SUCCESS, ret); + } + break; + } + case SMC_PCI_WRITE: { + uint32_t ret; + + if (validate_rw_addr_sz(x1, x2, x3) != SMC_PCI_CALL_SUCCESS) { + SMC_RET1(handle, SMC_PCI_CALL_INVAL_PARAM); + } + ret = pci_write_config(x1, x2, x3, x4); + SMC_RET1(handle, ret); + break; + } + case SMC_PCI_SEG_INFO: { + uint32_t nseg; + uint32_t ret; + uint32_t start_end_bus; + + if ((x2 != 0U) || (x3 != 0U) || (x4 != 0U)) { + SMC_RET3(handle, SMC_PCI_CALL_INVAL_PARAM, 0U, 0U); + } + ret = pci_get_bus_for_seg(x1, &start_end_bus, &nseg); + SMC_RET3(handle, ret, start_end_bus, nseg); + break; + } + default: + /* should be unreachable */ + WARN("Unimplemented PCI Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_PCI_CALL_NOT_SUPPORTED); + } +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S b/arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S new file mode 100644 index 0000000..6229baf --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../rmmd_private.h" +#include + + .global rmmd_rmm_enter + .global rmmd_rmm_exit + + /* --------------------------------------------------------------------- + * This function is called with SP_EL0 as stack. Here we stash our EL3 + * callee-saved registers on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where the address of the C + * runtime context is to be saved. + * --------------------------------------------------------------------- + */ +func rmmd_rmm_enter + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #RMMD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #RMMD_C_RT_CTX_X19] + stp x21, x22, [sp, #RMMD_C_RT_CTX_X21] + stp x23, x24, [sp, #RMMD_C_RT_CTX_X23] + stp x25, x26, [sp, #RMMD_C_RT_CTX_X25] + stp x27, x28, [sp, #RMMD_C_RT_CTX_X27] + stp x29, x30, [sp, #RMMD_C_RT_CTX_X29] + + /* --------------------------------------------------------------------- + * Everything is setup now. el3_exit() will use the secure context to + * restore to the general purpose and EL3 system registers to ERET + * into the secure payload. + * --------------------------------------------------------------------- + */ + b el3_exit +endfunc rmmd_rmm_enter + + /* --------------------------------------------------------------------- + * This function is called with 'x0' pointing to a C runtime context. + * It restores the saved registers and jumps to that runtime with 'x0' + * as the new SP register. This destroys the C runtime context that had + * been built on the stack below the saved context by the caller. Later + * the second parameter 'x1' is passed as a return value to the caller. + * --------------------------------------------------------------------- + */ +func rmmd_rmm_exit + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(RMMD_C_RT_CTX_X19 - RMMD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(RMMD_C_RT_CTX_X21 - RMMD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(RMMD_C_RT_CTX_X23 - RMMD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(RMMD_C_RT_CTX_X25 - RMMD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(RMMD_C_RT_CTX_X27 - RMMD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(RMMD_C_RT_CTX_X29 - RMMD_C_RT_CTX_SIZE)] + + /* --------------------------------------------------------------------- + * This should take us back to the instruction after the call to the + * last rmmd_rmm_enter().* Place the second parameter to x0 + * so that the caller will see it as a return value from the original + * entry call. + * --------------------------------------------------------------------- + */ + mov x0, x1 + ret +endfunc rmmd_rmm_exit diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd.mk b/arm-trusted-firmware/services/std_svc/rmmd/rmmd.mk new file mode 100644 index 0000000..bcf54e1 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH},aarch64) + $(error "Error: RMMD is only supported on aarch64.") +endif + +include services/std_svc/rmmd/trp/trp.mk + +RMMD_SOURCES += $(addprefix services/std_svc/rmmd/, \ + ${ARCH}/rmmd_helpers.S \ + rmmd_main.c \ + rmmd_attest.c) + +# Let the top-level Makefile know that we intend to include RMM image +NEED_RMM := yes diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c new file mode 100644 index 0000000..0432ec3 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include "rmmd_private.h" +#include + +static spinlock_t lock; + +/* For printing Realm attestation token hash */ +#define DIGITS_PER_BYTE 2UL +#define LENGTH_OF_TERMINATING_ZERO_IN_BYTES 1UL +#define BYTES_PER_LINE_BASE 4UL + +static void print_challenge(uint8_t *hash, size_t hash_size) +{ + size_t leftover; + /* + * bytes_per_line is always a power of two, so it can be used to + * construct mask with it when it is necessary to count remainder. + * + */ + const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE; + char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE + + LENGTH_OF_TERMINATING_ZERO_IN_BYTES]; + const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + unsigned int i; + + for (i = 0U; i < hash_size; ++i) { + hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] = + hex_chars[hash[i] >> 4]; + hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] = + hex_chars[hash[i] & 0x0f]; + if (((i + 1) & (bytes_per_line - 1)) == 0U) { + hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0'; + VERBOSE("hash part %u = %s\n", + (i >> BYTES_PER_LINE_BASE) + 1, hash_text); + } + } + + leftover = (size_t)i & (bytes_per_line - 1); + + if (leftover != 0UL) { + hash_text[leftover * DIGITS_PER_BYTE] = '\0'; + VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1, + hash_text); + } +} + +/* + * TODO: Have different error codes for different errors so that the caller can + * differentiate various error cases. + */ +int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len, uint64_t challenge_hash_len) +{ + int err; + uintptr_t va; + uint8_t temp_buf[SHA512_DIGEST_SIZE]; + + /* + * TODO: Currently we don't validate incoming buf_pa. This is a + * prototype and we will need to allocate static buffer for EL3-RMM + * communication. + */ + + /* We need a page of buffer to pass data */ + if (*buf_len != PAGE_SIZE) { + ERROR("Invalid buffer length\n"); + return RMMD_ERR_INVAL; + } + + if ((challenge_hash_len != SHA256_DIGEST_SIZE) && + (challenge_hash_len != SHA384_DIGEST_SIZE) && + (challenge_hash_len != SHA512_DIGEST_SIZE)) { + ERROR("Invalid hash size: %lu\n", challenge_hash_len); + return RMMD_ERR_INVAL; + } + + spin_lock(&lock); + + /* Map the buffer that was provided by the RMM. */ + err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE, + MT_RW_DATA | MT_REALM); + if (err != 0) { + ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n" + , err, (void *)buf_pa); + spin_unlock(&lock); + return RMMD_ERR_NOMEM; + } + + (void)memcpy(temp_buf, (void *)va, challenge_hash_len); + + print_challenge((uint8_t *)temp_buf, challenge_hash_len); + + /* Get the platform token. */ + err = plat_get_cca_attest_token(va, + buf_len, (uintptr_t)temp_buf, challenge_hash_len); + + if (err != 0) { + ERROR("Failed to get platform token: %d.\n", err); + err = RMMD_ERR_UNK; + } + + /* Unmap RMM memory. */ + (void)mmap_remove_dynamic_region(va, PAGE_SIZE); + spin_unlock(&lock); + + return err; +} + +int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_len, + uint64_t ecc_curve) +{ + int err; + uintptr_t va; + + /* + * TODO: Currently we don't validate incoming buf_pa. This is a + * prototype and we will need to allocate static buffer for EL3-RMM + * communication. + */ + + /* We need a page of buffer to pass data */ + if (*buf_len != PAGE_SIZE) { + ERROR("Invalid buffer length\n"); + return RMMD_ERR_INVAL; + } + + if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) { + ERROR("Invalid ECC curve specified\n"); + return RMMD_ERR_INVAL; + } + + spin_lock(&lock); + + /* Map the buffer that was provided by the RMM. */ + err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE, + MT_RW_DATA | MT_REALM); + if (err != 0) { + ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n" + , err, (void *)buf_pa); + spin_unlock(&lock); + return RMMD_ERR_NOMEM; + } + + /* Get the Realm attestation key. */ + err = plat_get_cca_realm_attest_key(va, buf_len, (unsigned int)ecc_curve); + if (err != 0) { + ERROR("Failed to get attestation key: %d.\n", err); + err = RMMD_ERR_UNK; + } + + /* Unmap RMM memory. */ + (void)mmap_remove_dynamic_region(va, PAGE_SIZE); + spin_unlock(&lock); + + return err; +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h new file mode 100644 index 0000000..d7a743d --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RMMD_INITIAL_CONTEXT_H +#define RMMD_INITIAL_CONTEXT_H + +#include + +/* + * SPSR_EL2 + * M=0x9 (0b1001 EL2h) + * M[4]=0 + * DAIF=0xF Exceptions masked on entry. + * BTYPE=0 BTI not yet supported. + * SSBS=0 Not yet supported. + * IL=0 Not an illegal exception return. + * SS=0 Not single stepping. + * PAN=1 RMM shouldn't access realm memory. + * UAO=0 + * DIT=0 + * TCO=0 + * NZCV=0 + */ +#define REALM_SPSR_EL2 ( \ + SPSR_M_EL2H | \ + (0xF << SPSR_DAIF_SHIFT) | \ + SPSR_PAN_BIT \ + ) + +#endif /* RMMD_INITIAL_CONTEXT_H */ diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c new file mode 100644 index 0000000..cf5ff7b --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2021-2022, 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rmmd_initial_context.h" +#include "rmmd_private.h" + +/******************************************************************************* + * RMM context information. + ******************************************************************************/ +rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * RMM entry point information. Discovered on the primary core and reused + * on secondary cores. + ******************************************************************************/ +static entry_point_info_t *rmm_ep_info; + +/******************************************************************************* + * Static function declaration. + ******************************************************************************/ +static int32_t rmm_init(void); + +/******************************************************************************* + * This function takes an RMM context pointer and performs a synchronous entry + * into it. + ******************************************************************************/ +uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *rmm_ctx) +{ + uint64_t rc; + + assert(rmm_ctx != NULL); + + cm_set_context(&(rmm_ctx->cpu_ctx), REALM); + + /* Save the current el1/el2 context before loading realm context. */ + cm_el1_sysregs_context_save(NON_SECURE); + cm_el2_sysregs_context_save(NON_SECURE); + + /* Restore the realm context assigned above */ + cm_el1_sysregs_context_restore(REALM); + cm_el2_sysregs_context_restore(REALM); + cm_set_next_eret_context(REALM); + + /* Enter RMM */ + rc = rmmd_rmm_enter(&rmm_ctx->c_rt_ctx); + + /* Save realm context */ + cm_el1_sysregs_context_save(REALM); + cm_el2_sysregs_context_save(REALM); + + /* Restore the el1/el2 context again. */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_el2_sysregs_context_restore(NON_SECURE); + + return rc; +} + +/******************************************************************************* + * This function returns to the place where rmmd_rmm_sync_entry() was + * called originally. + ******************************************************************************/ +__dead2 void rmmd_rmm_sync_exit(uint64_t rc) +{ + rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()]; + + /* Get context of the RMM in use by this CPU. */ + assert(cm_get_context(REALM) == &(ctx->cpu_ctx)); + + /* + * The RMMD must have initiated the original request through a + * synchronous entry into RMM. Jump back to the original C runtime + * context with the value of rc in x0; + */ + rmmd_rmm_exit(ctx->c_rt_ctx, rc); + + panic(); +} + +static void rmm_el2_context_init(el2_sysregs_t *regs) +{ + regs->ctx_regs[CTX_SPSR_EL2 >> 3] = REALM_SPSR_EL2; + regs->ctx_regs[CTX_SCTLR_EL2 >> 3] = SCTLR_EL2_RES1; +} + +/******************************************************************************* + * Enable architecture extensions on first entry to Realm world. + ******************************************************************************/ +static void manage_extensions_realm(cpu_context_t *ctx) +{ +#if ENABLE_SVE_FOR_NS + /* + * Enable SVE and FPU in realm context when it is enabled for NS. + * Realm manager must ensure that the SVE and FPU register + * contexts are properly managed. + */ + sve_enable(ctx); +#else + /* + * Disable SVE and FPU in realm context when it is disabled for NS. + */ + sve_disable(ctx); +#endif /* ENABLE_SVE_FOR_NS */ +} + +/******************************************************************************* + * Jump to the RMM for the first time. + ******************************************************************************/ +static int32_t rmm_init(void) +{ + + uint64_t rc; + + rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()]; + + INFO("RMM init start.\n"); + ctx->state = RMM_STATE_RESET; + + /* Enable architecture extensions */ + manage_extensions_realm(&ctx->cpu_ctx); + + /* Initialize RMM EL2 context. */ + rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx); + + rc = rmmd_rmm_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("RMM initialisation failed 0x%" PRIx64 "\n", rc); + panic(); + } + + ctx->state = RMM_STATE_IDLE; + INFO("RMM init end.\n"); + + return 1; +} + +/******************************************************************************* + * Load and read RMM manifest, setup RMM. + ******************************************************************************/ +int rmmd_setup(void) +{ + uint32_t ep_attr; + unsigned int linear_id = plat_my_core_pos(); + rmmd_rmm_context_t *rmm_ctx = &rmm_context[linear_id]; + + /* Make sure RME is supported. */ + assert(get_armv9_2_feat_rme_support() != 0U); + + rmm_ep_info = bl31_plat_get_next_image_ep_info(REALM); + if (rmm_ep_info == NULL) { + WARN("No RMM image provided by BL2 boot loader, Booting " + "device without RMM initialization. SMCs destined for " + "RMM will return SMC_UNK\n"); + return -ENOENT; + } + + /* Under no circumstances will this parameter be 0 */ + assert(rmm_ep_info->pc == RMM_BASE); + + /* Initialise an entrypoint to set up the CPU context */ + ep_attr = EP_REALM; + if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U) { + ep_attr |= EP_EE_BIG; + } + + SET_PARAM_HEAD(rmm_ep_info, PARAM_EP, VERSION_1, ep_attr); + rmm_ep_info->spsr = SPSR_64(MODE_EL2, + MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + + /* Initialise RMM context with this entry point information */ + cm_setup_context(&rmm_ctx->cpu_ctx, rmm_ep_info); + + INFO("RMM setup done.\n"); + + /* Register init function for deferred init. */ + bl31_register_rmm_init(&rmm_init); + + return 0; +} + +/******************************************************************************* + * Forward SMC to the other security state + ******************************************************************************/ +static uint64_t rmmd_smc_forward(uint32_t src_sec_state, + uint32_t dst_sec_state, uint64_t x0, + uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, void *handle) +{ + /* Save incoming security state */ + cm_el1_sysregs_context_save(src_sec_state); + cm_el2_sysregs_context_save(src_sec_state); + + /* Restore outgoing security state */ + cm_el1_sysregs_context_restore(dst_sec_state); + cm_el2_sysregs_context_restore(dst_sec_state); + cm_set_next_eret_context(dst_sec_state); + + /* + * As per SMCCCv1.1, we need to preserve x4 to x7 unless + * being used as return args. Hence we differentiate the + * onward and backward path. Support upto 8 args in the + * onward path and 4 args in return path. + */ + if (src_sec_state == NON_SECURE) { + SMC_RET8(cm_get_context(dst_sec_state), x0, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); + } else { + SMC_RET4(cm_get_context(dst_sec_state), x0, x1, x2, x3); + } +} + +/******************************************************************************* + * This function handles all SMCs in the range reserved for RMI. Each call is + * either forwarded to the other security state or handled by the RMM dispatcher + ******************************************************************************/ +uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, + uint64_t x3, uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()]; + uint32_t src_sec_state; + + /* Determine which security state this SMC originated from */ + src_sec_state = caller_sec_state(flags); + + /* RMI must not be invoked by the Secure world */ + if (src_sec_state == SMC_FROM_SECURE) { + WARN("RMMD: RMI invoked by secure world.\n"); + SMC_RET1(handle, SMC_UNK); + } + + /* + * Forward an RMI call from the Normal world to the Realm world as it + * is. + */ + if (src_sec_state == SMC_FROM_NON_SECURE) { + VERBOSE("RMMD: RMI call from non-secure world.\n"); + return rmmd_smc_forward(NON_SECURE, REALM, smc_fid, + x1, x2, x3, x4, handle); + } + + if (src_sec_state != SMC_FROM_REALM) { + SMC_RET1(handle, SMC_UNK); + } + + switch (smc_fid) { + case RMMD_RMI_REQ_COMPLETE: + if (ctx->state == RMM_STATE_RESET) { + VERBOSE("RMMD: running rmmd_rmm_sync_exit\n"); + rmmd_rmm_sync_exit(x1); + } + + return rmmd_smc_forward(REALM, NON_SECURE, x1, + x2, x3, x4, 0, handle); + + default: + WARN("RMMD: Unsupported RMM call 0x%08x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/******************************************************************************* + * This cpu has been turned on. Enter RMM to initialise R-EL2. Entry into RMM + * is done after initialising minimal architectural state that guarantees safe + * execution. + ******************************************************************************/ +static void *rmmd_cpu_on_finish_handler(const void *arg) +{ + int32_t rc; + uint32_t linear_id = plat_my_core_pos(); + rmmd_rmm_context_t *ctx = &rmm_context[linear_id]; + + ctx->state = RMM_STATE_RESET; + + /* Initialise RMM context with this entry point information */ + cm_setup_context(&ctx->cpu_ctx, rmm_ep_info); + + /* Enable architecture extensions */ + manage_extensions_realm(&ctx->cpu_ctx); + + /* Initialize RMM EL2 context. */ + rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx); + + rc = rmmd_rmm_sync_entry(ctx); + if (rc != 0) { + ERROR("RMM initialisation failed (%d) on CPU%d\n", rc, + linear_id); + panic(); + } + + ctx->state = RMM_STATE_IDLE; + return NULL; +} + +/* Subscribe to PSCI CPU on to initialize RMM on secondary */ +SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, rmmd_cpu_on_finish_handler); + +/* Convert GPT lib error to RMMD GTS error */ +static int gpt_to_gts_error(int error, uint32_t smc_fid, uint64_t address) +{ + int ret; + + if (error == 0) { + return RMMD_OK; + } + + if (error == -EINVAL) { + ret = RMMD_ERR_BAD_ADDR; + } else { + /* This is the only other error code we expect */ + assert(error == -EPERM); + ret = RMMD_ERR_BAD_PAS; + } + + ERROR("RMMD: PAS Transition failed. GPT ret = %d, PA: 0x%"PRIx64 ", FID = 0x%x\n", + error, address, smc_fid); + return ret; +} + +/******************************************************************************* + * This function handles RMM-EL3 interface SMCs + ******************************************************************************/ +uint64_t rmmd_rmm_el3_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, + uint64_t x3, uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + uint32_t src_sec_state; + int ret; + + /* Determine which security state this SMC originated from */ + src_sec_state = caller_sec_state(flags); + + if (src_sec_state != SMC_FROM_REALM) { + WARN("RMMD: RMM-EL3 call originated from secure or normal world\n"); + SMC_RET1(handle, SMC_UNK); + } + + switch (smc_fid) { + case RMMD_GTSI_DELEGATE: + ret = gpt_delegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM); + SMC_RET1(handle, gpt_to_gts_error(ret, smc_fid, x1)); + case RMMD_GTSI_UNDELEGATE: + ret = gpt_undelegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM); + SMC_RET1(handle, gpt_to_gts_error(ret, smc_fid, x1)); + case RMMD_ATTEST_GET_PLAT_TOKEN: + ret = rmmd_attest_get_platform_token(x1, &x2, x3); + SMC_RET2(handle, ret, x2); + case RMMD_ATTEST_GET_REALM_KEY: + ret = rmmd_attest_get_signing_key(x1, &x2, x3); + SMC_RET2(handle, ret, x2); + default: + WARN("RMMD: Unsupported RMM-EL3 call 0x%08x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h new file mode 100644 index 0000000..73df2b8 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RMMD_PRIVATE_H +#define RMMD_PRIVATE_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define RMMD_C_RT_CTX_X19 0x0 +#define RMMD_C_RT_CTX_X20 0x8 +#define RMMD_C_RT_CTX_X21 0x10 +#define RMMD_C_RT_CTX_X22 0x18 +#define RMMD_C_RT_CTX_X23 0x20 +#define RMMD_C_RT_CTX_X24 0x28 +#define RMMD_C_RT_CTX_X25 0x30 +#define RMMD_C_RT_CTX_X26 0x38 +#define RMMD_C_RT_CTX_X27 0x40 +#define RMMD_C_RT_CTX_X28 0x48 +#define RMMD_C_RT_CTX_X29 0x50 +#define RMMD_C_RT_CTX_X30 0x58 + +#define RMMD_C_RT_CTX_SIZE 0x60 +#define RMMD_C_RT_CTX_ENTRIES (RMMD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ +#include + +typedef enum rmm_state { + RMM_STATE_RESET = 0, + RMM_STATE_IDLE +} rmm_state_t; + +/* + * Data structure used by the RMM dispatcher (RMMD) in EL3 to track context of + * the RMM at R-EL2. + */ +typedef struct rmmd_rmm_context { + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; + rmm_state_t state; +} rmmd_rmm_context_t; + +/* Functions used to enter/exit the RMM synchronously */ +uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *ctx); +__dead2 void rmmd_rmm_sync_exit(uint64_t rc); + +/* Functions implementing attestation utilities for RMM */ +int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len, + uint64_t challenge_hash_len); +int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_len, + uint64_t ecc_curve); + +/* Assembly helpers */ +uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx); +void __dead2 rmmd_rmm_exit(uint64_t c_rt_ctx, uint64_t ret); + +/* Reference to PM ops for the RMMD */ +extern const spd_pm_ops_t rmmd_pm; + +#endif /* __ASSEMBLER__ */ + +#endif /* RMMD_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds b/arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds new file mode 100644 index 0000000..2b7f383 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds @@ -0,0 +1,71 @@ +/* + * (C) COPYRIGHT 2021 Arm Limited or its affiliates. + * ALL RIGHTS RESERVED + */ + +#include +#include + +/* Mapped using 4K pages, requires us to align different sections with + * different property at the same granularity. */ +PAGE_SIZE_4K = 4096; + +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(trp_head) + +MEMORY { + RAM (rwx): ORIGIN = RMM_BASE, LENGTH = RMM_LIMIT - RMM_BASE +} + + +SECTIONS +{ + . = RMM_BASE; + + .text : { + *(.head.text) + . = ALIGN(8); + *(.text*) + } >RAM + + . = ALIGN(PAGE_SIZE_4K); + + .rodata : { + *(.rodata*) + } >RAM + + . = ALIGN(PAGE_SIZE_4K); + + __RW_START__ = . ; + + .data : { + *(.data*) + } >RAM + + .bss (NOLOAD) : { + __BSS_START__ = .; + *(.bss*) + __BSS_END__ = .; + } >RAM + __BSS_SIZE__ = SIZEOF(.bss); + + + STACK_SECTION >RAM + + + /* + * Define a linker symbol to mark the end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __RMM_END__ = .; + + + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } + /DISCARD/ : { *(.note*) } +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/trp.mk b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp.mk new file mode 100644 index 0000000..a4f6e03 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp.mk @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RMM_SOURCES += services/std_svc/rmmd/trp/trp_entry.S \ + services/std_svc/rmmd/trp/trp_main.c + +RMM_LINKERFILE := services/std_svc/rmmd/trp/linker.lds + +# Include the platform-specific TRP Makefile +# If no platform-specific TRP Makefile exists, it means TRP is not supported +# on this platform. +TRP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/trp/trp-${PLAT}.mk) +ifeq (,${TRP_PLAT_MAKEFILE}) + $(error TRP is not supported on platform ${PLAT}) +else + include ${TRP_PLAT_MAKEFILE} +endif diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S new file mode 100644 index 0000000..1b03c9f --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "trp_private.h" + +.global trp_head +.global trp_smc + +.section ".head.text", "ax" + + /* --------------------------------------------- + * Populate the params in x0-x7 from the pointer + * to the smc args structure in x0. + * --------------------------------------------- + */ + .macro restore_args_call_smc + ldp x6, x7, [x0, #TRP_ARG6] + ldp x4, x5, [x0, #TRP_ARG4] + ldp x2, x3, [x0, #TRP_ARG2] + ldp x0, x1, [x0, #TRP_ARG0] + smc #0 + .endm + + /* --------------------------------------------- + * Entry point for TRP + * --------------------------------------------- + */ +trp_head: + bl plat_set_my_stack + + /* + * Find out whether this is a cold or warm boot + */ + ldr x1, cold_boot_flag + cbz x1, warm_boot + + /* + * Update cold boot flag to indicate cold boot is done + */ + adr x2, cold_boot_flag + str xzr, [x2] + + + /* --------------------------------------------- + * Zero out BSS section + * --------------------------------------------- + */ + ldr x0, =__BSS_START__ + ldr x1, =__BSS_SIZE__ + bl zeromem + + bl trp_setup + + bl trp_main +warm_boot: + mov_imm x0, RMMD_RMI_REQ_COMPLETE + mov x1, xzr + smc #0 + b trp_handler + + /* + * Flag to mark if it is a cold boot. + * 1: cold boot, 0: warmboot. + */ +.align 3 +cold_boot_flag: + .dword 1 + + /* --------------------------------------------- + * Direct SMC call to BL31 service provided by + * RMM Dispatcher + * --------------------------------------------- + */ +func trp_smc + restore_args_call_smc + ret +endfunc trp_smc + + /* --------------------------------------------- + * RMI call handler + * --------------------------------------------- + */ +func trp_handler + bl trp_rmi_handler + restore_args_call_smc + b trp_handler +endfunc trp_handler diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c new file mode 100644 index 0000000..2e3f076 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include +#include +#include +#include + +#include +#include "trp_private.h" + +/******************************************************************************* + * Per cpu data structure to populate parameters for an SMC in C code and use + * a pointer to this structure in assembler code to populate x0-x7 + ******************************************************************************/ +static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Set the arguments for SMC call + ******************************************************************************/ +static trp_args_t *set_smc_args(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id; + trp_args_t *pcpu_smc_args; + + /* + * Return to Secure Monitor by raising an SMC. The results of the + * service are passed as an arguments to the SMC + */ + linear_id = plat_my_core_pos(); + pcpu_smc_args = &trp_smc_args[linear_id]; + write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0); + write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1); + write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2); + write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3); + write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4); + write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5); + write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6); + write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7); + + return pcpu_smc_args; +} + +/******************************************************************************* + * Setup function for TRP. + ******************************************************************************/ +void trp_setup(void) +{ + /* Perform early platform-specific setup */ + trp_early_platform_setup(); +} + +/* Main function for TRP */ +void trp_main(void) +{ + NOTICE("TRP: %s\n", version_string); + NOTICE("TRP: %s\n", build_message); + INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE); + INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END + - RMM_BASE)); +} + +/******************************************************************************* + * Returning RMI version back to Normal World + ******************************************************************************/ +static trp_args_t *trp_ret_rmi_version(void) +{ + VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, + RMI_ABI_VERSION_MINOR); + return set_smc_args(RMMD_RMI_REQ_COMPLETE, RMI_ABI_VERSION, + 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * Transitioning granule of NON-SECURE type to REALM type + ******************************************************************************/ +static trp_args_t *trp_asc_mark_realm(unsigned long long x1) +{ + unsigned long long ret; + + VERBOSE("Delegating granule 0x%llx\n", x1); + ret = trp_smc(set_smc_args(RMMD_GTSI_DELEGATE, x1, 0, 0, 0, 0, 0, 0)); + + if (ret != 0ULL) { + ERROR("Granule transition from NON-SECURE type to REALM type " + "failed 0x%llx\n", ret); + } + return set_smc_args(RMMD_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * Transitioning granule of REALM type to NON-SECURE type + ******************************************************************************/ +static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1) +{ + unsigned long long ret; + + VERBOSE("Undelegating granule 0x%llx\n", x1); + ret = trp_smc(set_smc_args(RMMD_GTSI_UNDELEGATE, x1, 0, 0, 0, 0, 0, 0)); + + if (ret != 0ULL) { + ERROR("Granule transition from REALM type to NON-SECURE type " + "failed 0x%llx\n", ret); + } + return set_smc_args(RMMD_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * Main RMI SMC handler function + ******************************************************************************/ +trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1) +{ + switch (fid) { + case RMI_RMM_REQ_VERSION: + return trp_ret_rmi_version(); + case RMI_RMM_GRANULE_DELEGATE: + return trp_asc_mark_realm(x1); + case RMI_RMM_GRANULE_UNDELEGATE: + return trp_asc_mark_nonsecure(x1); + default: + ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid); + } + return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0); +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h new file mode 100644 index 0000000..43a4a4b --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRP_PRIVATE_H +#define TRP_PRIVATE_H + +/* Definitions to help the assembler access the SMC/ERET args structure */ +#define TRP_ARGS_SIZE TRP_ARGS_END +#define TRP_ARG0 0x0 +#define TRP_ARG1 0x8 +#define TRP_ARG2 0x10 +#define TRP_ARG3 0x18 +#define TRP_ARG4 0x20 +#define TRP_ARG5 0x28 +#define TRP_ARG6 0x30 +#define TRP_ARG7 0x38 +#define TRP_ARGS_END 0x40 + +#ifndef __ASSEMBLER__ + +#include + +/* Data structure to hold SMC arguments */ +typedef struct trp_args { + uint64_t regs[TRP_ARGS_END >> 3]; +} __aligned(CACHE_WRITEBACK_GRANULE) trp_args_t; + +#define write_trp_arg(args, offset, val) (((args)->regs[offset >> 3]) \ + = val) + +/* RMI handled by TRP */ +#define RMI_FNUM_VERSION_REQ U(0x150) + +#define RMI_FNUM_GRANULE_DELEGATE U(0x151) +#define RMI_FNUM_GRANULE_UNDELEGATE U(0x152) + +#define RMI_RMM_REQ_VERSION RMM_FID(SMC_64, RMI_FNUM_VERSION_REQ) + +#define RMI_RMM_GRANULE_DELEGATE RMM_FID(SMC_64, \ + RMI_FNUM_GRANULE_DELEGATE) +#define RMI_RMM_GRANULE_UNDELEGATE RMM_FID(SMC_64, \ + RMI_FNUM_GRANULE_UNDELEGATE) + +/* Definitions for RMI VERSION */ +#define RMI_ABI_VERSION_MAJOR U(0x0) +#define RMI_ABI_VERSION_MINOR U(0x0) +#define RMI_ABI_VERSION ((RMI_ABI_VERSION_MAJOR << 16) | \ + RMI_ABI_VERSION_MINOR) + +/* Helper to issue SMC calls to BL31 */ +uint64_t trp_smc(trp_args_t *); + +/* The main function to executed only by Primary CPU */ +void trp_main(void); + +/* Setup TRP. Executed only by Primary CPU */ +void trp_setup(void); + +#endif /* __ASSEMBLER__ */ +#endif /* TRP_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S b/arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S new file mode 100644 index 0000000..8449e4b --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl begin_sdei_synchronous_dispatch + +/* + * void begin_sdei_synchronous_dispatch(jmp_buf *buffer); + * + * Begin SDEI dispatch synchronously by setting up a jump point, and exiting + * EL3. This jump point is jumped to by the dispatcher after the event is + * completed by the client. + */ +func begin_sdei_synchronous_dispatch + stp x30, xzr, [sp, #-16]! + bl setjmp + cbz x0, 1f + ldp x30, xzr, [sp], #16 + ret +1: + b el3_exit +endfunc begin_sdei_synchronous_dispatch diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_event.c b/arm-trusted-firmware/services/std_svc/sdei/sdei_event.c new file mode 100644 index 0000000..0b608e1 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_event.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "sdei_private.h" + +#define MAP_OFF(_map, _mapping) ((_map) - (_mapping)->map) + +/* + * Get SDEI entry with the given mapping: on success, returns pointer to SDEI + * entry. On error, returns NULL. + * + * Both shared and private maps are stored in single-dimensional array. Private + * event entries are kept for each PE forming a 2D array. + */ +sdei_entry_t *get_event_entry(sdei_ev_map_t *map) +{ + const sdei_mapping_t *mapping; + sdei_entry_t *cpu_priv_base; + unsigned int base_idx; + long int idx; + + if (is_event_private(map)) { + /* + * For a private map, find the index of the mapping in the + * array. + */ + mapping = SDEI_PRIVATE_MAPPING(); + idx = MAP_OFF(map, mapping); + + /* Base of private mappings for this CPU */ + base_idx = plat_my_core_pos() * ((unsigned int) mapping->num_maps); + cpu_priv_base = &sdei_private_event_table[base_idx]; + + /* + * Return the address of the entry at the same index in the + * per-CPU event entry. + */ + return &cpu_priv_base[idx]; + } else { + mapping = SDEI_SHARED_MAPPING(); + idx = MAP_OFF(map, mapping); + + return &sdei_shared_event_table[idx]; + } +} + +/* + * Find event mapping for a given interrupt number: On success, returns pointer + * to the event mapping. On error, returns NULL. + */ +sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + unsigned int i; + + /* + * Look for a match in private and shared mappings, as requested. This + * is a linear search. However, if the mappings are required to be + * sorted, for large maps, we could consider binary search. + */ + mapping = shared ? SDEI_SHARED_MAPPING() : SDEI_PRIVATE_MAPPING(); + iterate_mapping(mapping, i, map) { + if (map->intr == intr_num) + return map; + } + + return NULL; +} + +/* + * Find event mapping for a given event number: On success returns pointer to + * the event mapping. On error, returns NULL. + */ +sdei_ev_map_t *find_event_map(int ev_num) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + unsigned int i, j; + + /* + * Iterate through mappings to find a match. This is a linear search. + * However, if the mappings are required to be sorted, for large maps, + * we could consider binary search. + */ + for_each_mapping_type(i, mapping) { + iterate_mapping(mapping, j, map) { + if (map->ev_num == ev_num) + return map; + } + } + + return NULL; +} diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c b/arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c new file mode 100644 index 0000000..87a1fb7 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 2017-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 "sdei_private.h" + +/* x0-x17 GPREGS context */ +#define SDEI_SAVED_GPREGS 18U + +/* Maximum preemption nesting levels: Critical priority and Normal priority */ +#define MAX_EVENT_NESTING 2U + +/* Per-CPU SDEI state access macro */ +#define sdei_get_this_pe_state() (&cpu_state[plat_my_core_pos()]) + +/* Structure to store information about an outstanding dispatch */ +typedef struct sdei_dispatch_context { + sdei_ev_map_t *map; + uint64_t x[SDEI_SAVED_GPREGS]; + jmp_buf *dispatch_jmp; + + /* Exception state registers */ + uint64_t elr_el3; + uint64_t spsr_el3; + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + /* CVE-2018-3639 mitigation state */ + uint64_t disable_cve_2018_3639; +#endif +} sdei_dispatch_context_t; + +/* Per-CPU SDEI state data */ +typedef struct sdei_cpu_state { + sdei_dispatch_context_t dispatch_stack[MAX_EVENT_NESTING]; + unsigned short stack_top; /* Empty ascending */ + bool pe_masked; + bool pending_enables; +} sdei_cpu_state_t; + +/* SDEI states for all cores in the system */ +static sdei_cpu_state_t cpu_state[PLATFORM_CORE_COUNT]; + +int64_t sdei_pe_mask(void) +{ + int64_t ret = 0; + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + + /* + * Return value indicates whether this call had any effect in the mask + * status of this PE. + */ + if (!state->pe_masked) { + state->pe_masked = true; + ret = 1; + } + + return ret; +} + +void sdei_pe_unmask(void) +{ + unsigned int i; + sdei_ev_map_t *map; + sdei_entry_t *se; + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + uint64_t my_mpidr = read_mpidr_el1() & MPIDR_AFFINITY_MASK; + + /* + * If there are pending enables, iterate through the private mappings + * and enable those bound maps that are in enabled state. Also, iterate + * through shared mappings and enable interrupts of events that are + * targeted to this PE. + */ + if (state->pending_enables) { + for_each_private_map(i, map) { + se = get_event_entry(map); + if (is_map_bound(map) && GET_EV_STATE(se, ENABLED)) + plat_ic_enable_interrupt(map->intr); + } + + for_each_shared_map(i, map) { + se = get_event_entry(map); + + sdei_map_lock(map); + if (is_map_bound(map) && GET_EV_STATE(se, ENABLED) && + (se->reg_flags == SDEI_REGF_RM_PE) && + (se->affinity == my_mpidr)) { + plat_ic_enable_interrupt(map->intr); + } + sdei_map_unlock(map); + } + } + + state->pending_enables = false; + state->pe_masked = false; +} + +/* Push a dispatch context to the dispatch stack */ +static sdei_dispatch_context_t *push_dispatch(void) +{ + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + sdei_dispatch_context_t *disp_ctx; + + /* Cannot have more than max events */ + assert(state->stack_top < MAX_EVENT_NESTING); + + disp_ctx = &state->dispatch_stack[state->stack_top]; + state->stack_top++; + + return disp_ctx; +} + +/* Pop a dispatch context to the dispatch stack */ +static sdei_dispatch_context_t *pop_dispatch(void) +{ + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + + if (state->stack_top == 0U) + return NULL; + + assert(state->stack_top <= MAX_EVENT_NESTING); + + state->stack_top--; + + return &state->dispatch_stack[state->stack_top]; +} + +/* Retrieve the context at the top of dispatch stack */ +static sdei_dispatch_context_t *get_outstanding_dispatch(void) +{ + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + + if (state->stack_top == 0U) + return NULL; + + assert(state->stack_top <= MAX_EVENT_NESTING); + + return &state->dispatch_stack[state->stack_top - 1U]; +} + +static sdei_dispatch_context_t *save_event_ctx(sdei_ev_map_t *map, + void *tgt_ctx) +{ + sdei_dispatch_context_t *disp_ctx; + const gp_regs_t *tgt_gpregs; + const el3_state_t *tgt_el3; + + assert(tgt_ctx != NULL); + tgt_gpregs = get_gpregs_ctx(tgt_ctx); + tgt_el3 = get_el3state_ctx(tgt_ctx); + + disp_ctx = push_dispatch(); + assert(disp_ctx != NULL); + disp_ctx->map = map; + + /* Save general purpose and exception registers */ + memcpy(disp_ctx->x, tgt_gpregs, sizeof(disp_ctx->x)); + disp_ctx->spsr_el3 = read_ctx_reg(tgt_el3, CTX_SPSR_EL3); + disp_ctx->elr_el3 = read_ctx_reg(tgt_el3, CTX_ELR_EL3); + + return disp_ctx; +} + +static void restore_event_ctx(const sdei_dispatch_context_t *disp_ctx, void *tgt_ctx) +{ + gp_regs_t *tgt_gpregs; + el3_state_t *tgt_el3; + + assert(tgt_ctx != NULL); + tgt_gpregs = get_gpregs_ctx(tgt_ctx); + tgt_el3 = get_el3state_ctx(tgt_ctx); + + CASSERT(sizeof(disp_ctx->x) == (SDEI_SAVED_GPREGS * sizeof(uint64_t)), + foo); + + /* Restore general purpose and exception registers */ + memcpy(tgt_gpregs, disp_ctx->x, sizeof(disp_ctx->x)); + write_ctx_reg(tgt_el3, CTX_SPSR_EL3, disp_ctx->spsr_el3); + write_ctx_reg(tgt_el3, CTX_ELR_EL3, disp_ctx->elr_el3); + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + cve_2018_3639_t *tgt_cve_2018_3639; + tgt_cve_2018_3639 = get_cve_2018_3639_ctx(tgt_ctx); + + /* Restore CVE-2018-3639 mitigation state */ + write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, + disp_ctx->disable_cve_2018_3639); +#endif +} + +static void save_secure_context(void) +{ + cm_el1_sysregs_context_save(SECURE); +} + +/* Restore Secure context and arrange to resume it at the next ERET */ +static void restore_and_resume_secure_context(void) +{ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); +} + +/* + * Restore Non-secure context and arrange to resume it at the next ERET. Return + * pointer to the Non-secure context. + */ +static cpu_context_t *restore_and_resume_ns_context(void) +{ + cpu_context_t *ns_ctx; + + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + ns_ctx = cm_get_context(NON_SECURE); + assert(ns_ctx != NULL); + + return ns_ctx; +} + +/* + * Prepare for ERET: + * - Set the ELR to the registered handler address + * - Set the SPSR register as described in the SDEI documentation and + * the AArch64.TakeException() pseudocode function in + * ARM DDI 0487F.c page J1-7635 + */ + +static void sdei_set_elr_spsr(sdei_entry_t *se, sdei_dispatch_context_t *disp_ctx) +{ + unsigned int client_el = sdei_client_el(); + u_register_t sdei_spsr = SPSR_64(client_el, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + + u_register_t interrupted_pstate = disp_ctx->spsr_el3; + + /* Check the SPAN bit in the client el SCTLR */ + u_register_t client_el_sctlr; + + if (client_el == MODE_EL2) { + client_el_sctlr = read_sctlr_el2(); + } else { + client_el_sctlr = read_sctlr_el1(); + } + + /* + * Check whether to force the PAN bit or use the value in the + * interrupted EL according to the check described in + * TakeException. Since the client can only be Non-Secure + * EL2 or El1 some of the conditions in ElIsInHost() we know + * will always be True. + * When the client_el is EL2 we know that there will be a SPAN + * bit in SCTLR_EL2 as we have already checked for the condition + * HCR_EL2.E2H = 1 and HCR_EL2.TGE = 1 + */ + u_register_t hcr_el2 = read_hcr(); + bool el_is_in_host = is_armv8_1_vhe_present() && + (hcr_el2 & HCR_TGE_BIT) && + (hcr_el2 & HCR_E2H_BIT); + + if (is_armv8_1_pan_present() && + ((client_el == MODE_EL1) || + (client_el == MODE_EL2 && el_is_in_host)) && + ((client_el_sctlr & SCTLR_SPAN_BIT) == 0U)) { + sdei_spsr |= SPSR_PAN_BIT; + } else { + sdei_spsr |= (interrupted_pstate & SPSR_PAN_BIT); + } + + /* If SSBS is implemented, take the value from the client el SCTLR */ + u_register_t ssbs_enabled = (read_id_aa64pfr1_el1() + >> ID_AA64PFR1_EL1_SSBS_SHIFT) + & ID_AA64PFR1_EL1_SSBS_MASK; + if (ssbs_enabled != SSBS_UNAVAILABLE) { + u_register_t ssbs_bit = ((client_el_sctlr & SCTLR_DSSBS_BIT) + >> SCTLR_DSSBS_SHIFT) + << SPSR_SSBS_SHIFT_AARCH64; + sdei_spsr |= ssbs_bit; + } + + /* If MTE is implemented in the client el set the TCO bit */ + if (get_armv8_5_mte_support() >= MTE_IMPLEMENTED_ELX) { + sdei_spsr |= SPSR_TCO_BIT_AARCH64; + } + + /* Take the DIT field from the pstate of the interrupted el */ + sdei_spsr |= (interrupted_pstate & SPSR_DIT_BIT); + + cm_set_elr_spsr_el3(NON_SECURE, (uintptr_t) se->ep, sdei_spsr); +} + +/* + * Populate the Non-secure context so that the next ERET will dispatch to the + * SDEI client. + */ +static void setup_ns_dispatch(sdei_ev_map_t *map, sdei_entry_t *se, + cpu_context_t *ctx, jmp_buf *dispatch_jmp) +{ + sdei_dispatch_context_t *disp_ctx; + + /* Push the event and context */ + disp_ctx = save_event_ctx(map, ctx); + + /* + * Setup handler arguments: + * + * - x0: Event number + * - x1: Handler argument supplied at the time of event registration + * - x2: Interrupted PC + * - x3: Interrupted SPSR + */ + SMC_SET_GP(ctx, CTX_GPREG_X0, (uint64_t) map->ev_num); + SMC_SET_GP(ctx, CTX_GPREG_X1, se->arg); + SMC_SET_GP(ctx, CTX_GPREG_X2, disp_ctx->elr_el3); + SMC_SET_GP(ctx, CTX_GPREG_X3, disp_ctx->spsr_el3); + + /* Setup the elr and spsr register to prepare for ERET */ + sdei_set_elr_spsr(se, disp_ctx); + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + cve_2018_3639_t *tgt_cve_2018_3639; + tgt_cve_2018_3639 = get_cve_2018_3639_ctx(ctx); + + /* Save CVE-2018-3639 mitigation state */ + disp_ctx->disable_cve_2018_3639 = read_ctx_reg(tgt_cve_2018_3639, + CTX_CVE_2018_3639_DISABLE); + + /* Force SDEI handler to execute with mitigation enabled by default */ + write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, 0); +#endif + + disp_ctx->dispatch_jmp = dispatch_jmp; +} + +/* Handle a triggered SDEI interrupt while events were masked on this PE */ +static void handle_masked_trigger(sdei_ev_map_t *map, sdei_entry_t *se, + sdei_cpu_state_t *state, unsigned int intr_raw) +{ + uint64_t my_mpidr __unused = (read_mpidr_el1() & MPIDR_AFFINITY_MASK); + bool disable = false; + + /* Nothing to do for event 0 */ + if (map->ev_num == SDEI_EVENT_0) + return; + + /* + * For a private event, or for a shared event specifically routed to + * this CPU, we disable interrupt, leave the interrupt pending, and do + * EOI. + */ + if (is_event_private(map) || (se->reg_flags == SDEI_REGF_RM_PE)) + disable = true; + + if (se->reg_flags == SDEI_REGF_RM_PE) + assert(se->affinity == my_mpidr); + + if (disable) { + plat_ic_disable_interrupt(map->intr); + plat_ic_set_interrupt_pending(map->intr); + plat_ic_end_of_interrupt(intr_raw); + state->pending_enables = true; + + return; + } + + /* + * We just received a shared event with routing set to ANY PE. The + * interrupt can't be delegated on this PE as SDEI events are masked. + * However, because its routing mode is ANY, it is possible that the + * event can be delegated on any other PE that hasn't masked events. + * Therefore, we set the interrupt back pending so as to give other + * suitable PEs a chance of handling it. + */ + assert(plat_ic_is_spi(map->intr) != 0); + plat_ic_set_interrupt_pending(map->intr); + + /* + * Leaving the same interrupt pending also means that the same interrupt + * can target this PE again as soon as this PE leaves EL3. Whether and + * how often that happens depends on the implementation of GIC. + * + * We therefore call a platform handler to resolve this situation. + */ + plat_sdei_handle_masked_trigger(my_mpidr, map->intr); + + /* This PE is masked. We EOI the interrupt, as it can't be delegated */ + plat_ic_end_of_interrupt(intr_raw); +} + +/* SDEI main interrupt handler */ +int sdei_intr_handler(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie) +{ + sdei_entry_t *se; + cpu_context_t *ctx; + sdei_ev_map_t *map; + const sdei_dispatch_context_t *disp_ctx; + unsigned int sec_state; + sdei_cpu_state_t *state; + uint32_t intr; + jmp_buf dispatch_jmp; + const uint64_t mpidr = read_mpidr_el1(); + + /* + * To handle an event, the following conditions must be true: + * + * 1. Event must be signalled + * 2. Event must be enabled + * 3. This PE must be a target PE for the event + * 4. PE must be unmasked for SDEI + * 5. If this is a normal event, no event must be running + * 6. If this is a critical event, no critical event must be running + * + * (1) and (2) are true when this function is running + * (3) is enforced in GIC by selecting the appropriate routing option + * (4) is satisfied by client calling PE_UNMASK + * (5) and (6) is enforced using interrupt priority, the RPR, in GIC: + * - Normal SDEI events belong to Normal SDE priority class + * - Critical SDEI events belong to Critical CSDE priority class + * + * The interrupt has already been acknowledged, and therefore is active, + * so no other PE can handle this event while we are at it. + * + * Find if this is an SDEI interrupt. There must be an event mapped to + * this interrupt + */ + intr = plat_ic_get_interrupt_id(intr_raw); + map = find_event_map_by_intr(intr, (plat_ic_is_spi(intr) != 0)); + if (map == NULL) { + ERROR("No SDEI map for interrupt %u\n", intr); + panic(); + } + + /* + * Received interrupt number must either correspond to event 0, or must + * be bound interrupt. + */ + assert((map->ev_num == SDEI_EVENT_0) || is_map_bound(map)); + + se = get_event_entry(map); + state = sdei_get_this_pe_state(); + + if (state->pe_masked) { + /* + * Interrupts received while this PE was masked can't be + * dispatched. + */ + SDEI_LOG("interrupt %u on %" PRIx64 " while PE masked\n", + map->intr, mpidr); + if (is_event_shared(map)) + sdei_map_lock(map); + + handle_masked_trigger(map, se, state, intr_raw); + + if (is_event_shared(map)) + sdei_map_unlock(map); + + return 0; + } + + /* Insert load barrier for signalled SDEI event */ + if (map->ev_num == SDEI_EVENT_0) + dmbld(); + + if (is_event_shared(map)) + sdei_map_lock(map); + + /* Assert shared event routed to this PE had been configured so */ + if (is_event_shared(map) && (se->reg_flags == SDEI_REGF_RM_PE)) { + assert(se->affinity == (mpidr & MPIDR_AFFINITY_MASK)); + } + + if (!can_sdei_state_trans(se, DO_DISPATCH)) { + SDEI_LOG("SDEI event 0x%x can't be dispatched; state=0x%x\n", + map->ev_num, se->state); + + /* + * If the event is registered, leave the interrupt pending so + * that it's delivered when the event is enabled. + */ + if (GET_EV_STATE(se, REGISTERED)) + plat_ic_set_interrupt_pending(map->intr); + + /* + * The interrupt was disabled or unregistered after the handler + * started to execute, which means now the interrupt is already + * disabled and we just need to EOI the interrupt. + */ + plat_ic_end_of_interrupt(intr_raw); + + if (is_event_shared(map)) + sdei_map_unlock(map); + + return 0; + } + + disp_ctx = get_outstanding_dispatch(); + if (is_event_critical(map)) { + /* + * If this event is Critical, and if there's an outstanding + * dispatch, assert the latter is a Normal dispatch. Critical + * events can preempt an outstanding Normal event dispatch. + */ + if (disp_ctx != NULL) + assert(is_event_normal(disp_ctx->map)); + } else { + /* + * If this event is Normal, assert that there are no outstanding + * dispatches. Normal events can't preempt any outstanding event + * dispatches. + */ + assert(disp_ctx == NULL); + } + + sec_state = get_interrupt_src_ss(flags); + + if (is_event_shared(map)) + sdei_map_unlock(map); + + SDEI_LOG("ACK %" PRIx64 ", ev:0x%x ss:%d spsr:%lx ELR:%lx\n", + mpidr, map->ev_num, sec_state, read_spsr_el3(), read_elr_el3()); + + ctx = handle; + + /* + * Check if we interrupted secure state. Perform a context switch so + * that we can delegate to NS. + */ + if (sec_state == SECURE) { + save_secure_context(); + ctx = restore_and_resume_ns_context(); + } + + /* Synchronously dispatch event */ + setup_ns_dispatch(map, se, ctx, &dispatch_jmp); + begin_sdei_synchronous_dispatch(&dispatch_jmp); + + /* + * We reach here when client completes the event. + * + * If the cause of dispatch originally interrupted the Secure world, + * resume Secure. + * + * No need to save the Non-secure context ahead of a world switch: the + * Non-secure context was fully saved before dispatch, and has been + * returned to its pre-dispatch state. + */ + if (sec_state == SECURE) + restore_and_resume_secure_context(); + + /* + * The event was dispatched after receiving SDEI interrupt. With + * the event handling completed, EOI the corresponding + * interrupt. + */ + if ((map->ev_num != SDEI_EVENT_0) && !is_map_bound(map)) { + ERROR("Invalid SDEI mapping: ev=0x%x\n", map->ev_num); + panic(); + } + plat_ic_end_of_interrupt(intr_raw); + + return 0; +} + +/* + * Explicitly dispatch the given SDEI event. + * + * When calling this API, the caller must be prepared for the SDEI dispatcher to + * restore and make Non-secure context as active. This call returns only after + * the client has completed the dispatch. Then, the Non-secure context will be + * active, and the following ERET will return to Non-secure. + * + * Should the caller require re-entry to Secure, it must restore the Secure + * context and program registers for ERET. + */ +int sdei_dispatch_event(int ev_num) +{ + sdei_entry_t *se; + sdei_ev_map_t *map; + cpu_context_t *ns_ctx; + sdei_dispatch_context_t *disp_ctx; + sdei_cpu_state_t *state; + jmp_buf dispatch_jmp; + + /* Can't dispatch if events are masked on this PE */ + state = sdei_get_this_pe_state(); + if (state->pe_masked) + return -1; + + /* Event 0 can't be dispatched */ + if (ev_num == SDEI_EVENT_0) + return -1; + + /* Locate mapping corresponding to this event */ + map = find_event_map(ev_num); + if (map == NULL) + return -1; + + /* Only explicit events can be dispatched */ + if (!is_map_explicit(map)) + return -1; + + /* Examine state of dispatch stack */ + disp_ctx = get_outstanding_dispatch(); + if (disp_ctx != NULL) { + /* + * There's an outstanding dispatch. If the outstanding dispatch + * is critical, no more dispatches are possible. + */ + if (is_event_critical(disp_ctx->map)) + return -1; + + /* + * If the outstanding dispatch is Normal, only critical events + * can be dispatched. + */ + if (is_event_normal(map)) + return -1; + } + + se = get_event_entry(map); + if (!can_sdei_state_trans(se, DO_DISPATCH)) + return -1; + + /* + * Prepare for NS dispatch by restoring the Non-secure context and + * marking that as active. + */ + ns_ctx = restore_and_resume_ns_context(); + + /* Activate the priority corresponding to the event being dispatched */ + ehf_activate_priority(sdei_event_priority(map)); + + /* Dispatch event synchronously */ + setup_ns_dispatch(map, se, ns_ctx, &dispatch_jmp); + begin_sdei_synchronous_dispatch(&dispatch_jmp); + + /* + * We reach here when client completes the event. + * + * Deactivate the priority level that was activated at the time of + * explicit dispatch. + */ + ehf_deactivate_priority(sdei_event_priority(map)); + + return 0; +} + +static void end_sdei_synchronous_dispatch(jmp_buf *buffer) +{ + longjmp(*buffer, 1); +} + +int sdei_event_complete(bool resume, uint64_t pc) +{ + sdei_dispatch_context_t *disp_ctx; + sdei_entry_t *se; + sdei_ev_map_t *map; + cpu_context_t *ctx; + sdei_action_t act; + unsigned int client_el = sdei_client_el(); + + /* Return error if called without an active event */ + disp_ctx = get_outstanding_dispatch(); + if (disp_ctx == NULL) + return SDEI_EDENY; + + /* Validate resumption point */ + if (resume && (plat_sdei_validate_entry_point(pc, client_el) != 0)) + return SDEI_EDENY; + + map = disp_ctx->map; + assert(map != NULL); + se = get_event_entry(map); + + if (is_event_shared(map)) + sdei_map_lock(map); + + act = resume ? DO_COMPLETE_RESUME : DO_COMPLETE; + if (!can_sdei_state_trans(se, act)) { + if (is_event_shared(map)) + sdei_map_unlock(map); + return SDEI_EDENY; + } + + if (is_event_shared(map)) + sdei_map_unlock(map); + + /* Having done sanity checks, pop dispatch */ + (void) pop_dispatch(); + + SDEI_LOG("EOI:%lx, %d spsr:%lx elr:%lx\n", read_mpidr_el1(), + map->ev_num, read_spsr_el3(), read_elr_el3()); + + /* + * Restore Non-secure to how it was originally interrupted. Once done, + * it's up-to-date with the saved copy. + */ + ctx = cm_get_context(NON_SECURE); + restore_event_ctx(disp_ctx, ctx); + + if (resume) { + /* + * Complete-and-resume call. Prepare the Non-secure context + * (currently active) for complete and resume. + */ + cm_set_elr_spsr_el3(NON_SECURE, pc, SPSR_64(client_el, + MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)); + + /* + * Make it look as if a synchronous exception were taken at the + * supplied Non-secure resumption point. Populate SPSR and + * ELR_ELx so that an ERET from there works as expected. + * + * The assumption is that the client, if necessary, would have + * saved any live content in these registers before making this + * call. + */ + if (client_el == MODE_EL2) { + write_elr_el2(disp_ctx->elr_el3); + write_spsr_el2(disp_ctx->spsr_el3); + } else { + /* EL1 */ + write_elr_el1(disp_ctx->elr_el3); + write_spsr_el1(disp_ctx->spsr_el3); + } + } + + /* End the outstanding dispatch */ + end_sdei_synchronous_dispatch(disp_ctx->dispatch_jmp); + + return 0; +} + +int64_t sdei_event_context(void *handle, unsigned int param) +{ + sdei_dispatch_context_t *disp_ctx; + + if (param >= SDEI_SAVED_GPREGS) + return SDEI_EINVAL; + + /* Get outstanding dispatch on this CPU */ + disp_ctx = get_outstanding_dispatch(); + if (disp_ctx == NULL) + return SDEI_EDENY; + + assert(disp_ctx->map != NULL); + + if (!can_sdei_state_trans(get_event_entry(disp_ctx->map), DO_CONTEXT)) + return SDEI_EDENY; + + /* + * No locking is required for the Running status as this is the only CPU + * which can complete the event + */ + + return (int64_t) disp_ctx->x[param]; +} diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_main.c b/arm-trusted-firmware/services/std_svc/sdei/sdei_main.c new file mode 100644 index 0000000..44178ed --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_main.c @@ -0,0 +1,1114 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include "sdei_private.h" + +#define MAJOR_VERSION 1ULL +#define MINOR_VERSION 0ULL +#define VENDOR_VERSION 0ULL + +#define MAKE_SDEI_VERSION(_major, _minor, _vendor) \ + ((((_major)) << 48ULL) | (((_minor)) << 32ULL) | (_vendor)) + +#define LOWEST_INTR_PRIORITY 0xff + +#define is_valid_affinity(_mpidr) (plat_core_pos_by_mpidr(_mpidr) >= 0) + +CASSERT(PLAT_SDEI_CRITICAL_PRI < PLAT_SDEI_NORMAL_PRI, + sdei_critical_must_have_higher_priority); + +static unsigned int num_dyn_priv_slots, num_dyn_shrd_slots; + +/* Initialise SDEI map entries */ +static void init_map(sdei_ev_map_t *map) +{ + map->reg_count = 0; +} + +/* Convert mapping to SDEI class */ +static sdei_class_t map_to_class(sdei_ev_map_t *map) +{ + return is_event_critical(map) ? SDEI_CRITICAL : SDEI_NORMAL; +} + +/* Clear SDEI event entries except state */ +static void clear_event_entries(sdei_entry_t *se) +{ + se->ep = 0; + se->arg = 0; + se->affinity = 0; + se->reg_flags = 0; +} + +/* Perform CPU-specific state initialisation */ +static void *sdei_cpu_on_init(const void *arg) +{ + unsigned int i; + sdei_ev_map_t *map; + sdei_entry_t *se; + + /* Initialize private mappings on this CPU */ + for_each_private_map(i, map) { + se = get_event_entry(map); + clear_event_entries(se); + se->state = 0; + } + + SDEI_LOG("Private events initialized on %lx\n", read_mpidr_el1()); + + /* All PEs start with SDEI events masked */ + (void) sdei_pe_mask(); + + return NULL; +} + +/* CPU initialisation after wakeup from suspend */ +static void *sdei_cpu_wakeup_init(const void *arg) +{ + SDEI_LOG("Events masked on %lx\n", read_mpidr_el1()); + + /* All PEs wake up with SDEI events masked */ + sdei_pe_mask(); + + return 0; +} + +/* Initialise an SDEI class */ +static void sdei_class_init(sdei_class_t class) +{ + unsigned int i; + bool zero_found __unused = false; + int ev_num_so_far __unused; + sdei_ev_map_t *map; + + /* Sanity check and configuration of shared events */ + ev_num_so_far = -1; + for_each_shared_map(i, map) { +#if ENABLE_ASSERTIONS + /* Ensure mappings are sorted */ + assert((ev_num_so_far < 0) || (map->ev_num > ev_num_so_far)); + + ev_num_so_far = map->ev_num; + + /* Event 0 must not be shared */ + assert(map->ev_num != SDEI_EVENT_0); + + /* Check for valid event */ + assert(map->ev_num >= 0); + + /* Make sure it's a shared event */ + assert(is_event_shared(map)); + + /* No shared mapping should have signalable property */ + assert(!is_event_signalable(map)); + + /* Shared mappings can't be explicit */ + assert(!is_map_explicit(map)); +#endif + + /* Skip initializing the wrong priority */ + if (map_to_class(map) != class) + continue; + + /* Platform events are always bound, so set the bound flag */ + if (is_map_dynamic(map)) { + assert(map->intr == SDEI_DYN_IRQ); + assert(is_event_normal(map)); + num_dyn_shrd_slots++; + } else { + /* Shared mappings must be bound to shared interrupt */ + assert(plat_ic_is_spi(map->intr) != 0); + set_map_bound(map); + } + + init_map(map); + } + + /* Sanity check and configuration of private events for this CPU */ + ev_num_so_far = -1; + for_each_private_map(i, map) { +#if ENABLE_ASSERTIONS + /* Ensure mappings are sorted */ + assert((ev_num_so_far < 0) || (map->ev_num > ev_num_so_far)); + + ev_num_so_far = map->ev_num; + + if (map->ev_num == SDEI_EVENT_0) { + zero_found = true; + + /* Event 0 must be a Secure SGI */ + assert(is_secure_sgi(map->intr)); + + /* + * Event 0 can have only have signalable flag (apart + * from being private + */ + assert(map->map_flags == (SDEI_MAPF_SIGNALABLE | + SDEI_MAPF_PRIVATE)); + } else { + /* No other mapping should have signalable property */ + assert(!is_event_signalable(map)); + } + + /* Check for valid event */ + assert(map->ev_num >= 0); + + /* Make sure it's a private event */ + assert(is_event_private(map)); + + /* + * Other than priority, explicit events can only have explicit + * and private flags set. + */ + if (is_map_explicit(map)) { + assert((map->map_flags | SDEI_MAPF_CRITICAL) == + (SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE + | SDEI_MAPF_CRITICAL)); + } +#endif + + /* Skip initializing the wrong priority */ + if (map_to_class(map) != class) + continue; + + /* Platform events are always bound, so set the bound flag */ + if (map->ev_num != SDEI_EVENT_0) { + if (is_map_dynamic(map)) { + assert(map->intr == SDEI_DYN_IRQ); + assert(is_event_normal(map)); + num_dyn_priv_slots++; + } else if (is_map_explicit(map)) { + /* + * Explicit mappings don't have a backing + * SDEI interrupt, but verify that anyway. + */ + assert(map->intr == SDEI_DYN_IRQ); + } else { + /* + * Private mappings must be bound to private + * interrupt. + */ + assert(plat_ic_is_ppi((unsigned) map->intr) != 0); + set_map_bound(map); + } + } + + init_map(map); + } + + /* Ensure event 0 is in the mapping */ + assert(zero_found); + + (void) sdei_cpu_on_init(NULL); +} + +/* SDEI dispatcher initialisation */ +void sdei_init(void) +{ + plat_sdei_setup(); + sdei_class_init(SDEI_CRITICAL); + sdei_class_init(SDEI_NORMAL); + + /* Register priority level handlers */ + ehf_register_priority_handler(PLAT_SDEI_CRITICAL_PRI, + sdei_intr_handler); + ehf_register_priority_handler(PLAT_SDEI_NORMAL_PRI, + sdei_intr_handler); +} + +/* Populate SDEI event entry */ +static void set_sdei_entry(sdei_entry_t *se, uint64_t ep, uint64_t arg, + unsigned int flags, uint64_t affinity) +{ + assert(se != NULL); + + se->ep = ep; + se->arg = arg; + se->affinity = (affinity & MPIDR_AFFINITY_MASK); + se->reg_flags = flags; +} + +static uint64_t sdei_version(void) +{ + return MAKE_SDEI_VERSION(MAJOR_VERSION, MINOR_VERSION, VENDOR_VERSION); +} + +/* Validate flags and MPIDR values for REGISTER and ROUTING_SET calls */ +static int validate_flags(uint64_t flags, uint64_t mpidr) +{ + /* Validate flags */ + switch (flags) { + case SDEI_REGF_RM_PE: + if (!is_valid_affinity(mpidr)) + return SDEI_EINVAL; + break; + case SDEI_REGF_RM_ANY: + break; + default: + /* Unknown flags */ + return SDEI_EINVAL; + } + + return 0; +} + +/* Set routing of an SDEI event */ +static int sdei_event_routing_set(int ev_num, uint64_t flags, uint64_t mpidr) +{ + int ret; + unsigned int routing; + sdei_ev_map_t *map; + sdei_entry_t *se; + + ret = validate_flags(flags, mpidr); + if (ret != 0) + return ret; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + /* The event must not be private */ + if (is_event_private(map)) + return SDEI_EINVAL; + + se = get_event_entry(map); + + sdei_map_lock(map); + + if (!is_map_bound(map) || is_event_private(map)) { + ret = SDEI_EINVAL; + goto finish; + } + + if (!can_sdei_state_trans(se, DO_ROUTING)) { + ret = SDEI_EDENY; + goto finish; + } + + /* Choose appropriate routing */ + routing = (unsigned int) ((flags == SDEI_REGF_RM_ANY) ? + INTR_ROUTING_MODE_ANY : INTR_ROUTING_MODE_PE); + + /* Update event registration flag */ + se->reg_flags = (unsigned int) flags; + if (flags == SDEI_REGF_RM_PE) { + se->affinity = (mpidr & MPIDR_AFFINITY_MASK); + } + + /* + * ROUTING_SET is permissible only when event composite state is + * 'registered, disabled, and not running'. This means that the + * interrupt is currently disabled, and not active. + */ + plat_ic_set_spi_routing(map->intr, routing, (u_register_t) mpidr); + +finish: + sdei_map_unlock(map); + + return ret; +} + +/* Register handler and argument for an SDEI event */ +static int64_t sdei_event_register(int ev_num, + uint64_t ep, + uint64_t arg, + uint64_t flags, + uint64_t mpidr) +{ + int ret; + unsigned int routing; + sdei_entry_t *se; + sdei_ev_map_t *map; + sdei_state_t backup_state; + + if ((ep == 0U) || (plat_sdei_validate_entry_point( + ep, sdei_client_el()) != 0)) { + return SDEI_EINVAL; + } + + ret = validate_flags(flags, mpidr); + if (ret != 0) + return ret; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + /* Private events always target the PE */ + if (is_event_private(map)) { + /* + * SDEI internally handles private events in the same manner + * as public events with routing mode=RM_PE, since the routing + * mode flag and affinity fields are not used when registering + * a private event, set them here. + */ + flags = SDEI_REGF_RM_PE; + /* + * Kernel may pass 0 as mpidr, as we set flags to + * SDEI_REGF_RM_PE, so set mpidr also. + */ + mpidr = read_mpidr_el1(); + } + + se = get_event_entry(map); + + /* + * Even though register operation is per-event (additionally for private + * events, registration is required individually), it has to be + * serialised with respect to bind/release, which are global operations. + * So we hold the lock throughout, unconditionally. + */ + sdei_map_lock(map); + + backup_state = se->state; + if (!can_sdei_state_trans(se, DO_REGISTER)) + goto fallback; + + /* + * When registering for dynamic events, make sure it's been bound + * already. This has to be the case as, without binding, the client + * can't know about the event number to register for. + */ + if (is_map_dynamic(map) && !is_map_bound(map)) + goto fallback; + + if (is_event_private(map)) { + /* Multiple calls to register are possible for private events */ + assert(map->reg_count >= 0); + } else { + /* Only single call to register is possible for shared events */ + assert(map->reg_count == 0); + } + + if (is_map_bound(map)) { + /* Meanwhile, did any PE ACK the interrupt? */ + if (plat_ic_get_interrupt_active(map->intr) != 0U) + goto fallback; + + /* The interrupt must currently owned by Non-secure */ + if (plat_ic_get_interrupt_type(map->intr) != INTR_TYPE_NS) + goto fallback; + + /* + * Disable forwarding of new interrupt triggers to CPU + * interface. + */ + plat_ic_disable_interrupt(map->intr); + + /* + * Any events that are triggered after register and before + * enable should remain pending. Clear any previous interrupt + * triggers which are pending (except for SGIs). This has no + * affect on level-triggered interrupts. + */ + if (ev_num != SDEI_EVENT_0) + plat_ic_clear_interrupt_pending(map->intr); + + /* Map interrupt to EL3 and program the correct priority */ + plat_ic_set_interrupt_type(map->intr, INTR_TYPE_EL3); + + /* Program the appropriate interrupt priority */ + plat_ic_set_interrupt_priority(map->intr, sdei_event_priority(map)); + + /* + * Set the routing mode for shared event as requested. We + * already ensure that shared events get bound to SPIs. + */ + if (is_event_shared(map)) { + routing = (unsigned int) ((flags == SDEI_REGF_RM_ANY) ? + INTR_ROUTING_MODE_ANY : INTR_ROUTING_MODE_PE); + plat_ic_set_spi_routing(map->intr, routing, + (u_register_t) mpidr); + } + } + + /* Populate event entries */ + set_sdei_entry(se, ep, arg, (unsigned int) flags, mpidr); + + /* Increment register count */ + map->reg_count++; + + sdei_map_unlock(map); + + return 0; + +fallback: + /* Reinstate previous state */ + se->state = backup_state; + + sdei_map_unlock(map); + + return SDEI_EDENY; +} + +/* Enable SDEI event */ +static int64_t sdei_event_enable(int ev_num) +{ + sdei_ev_map_t *map; + sdei_entry_t *se; + int ret; + bool before, after; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + ret = SDEI_EDENY; + + if (is_event_shared(map)) + sdei_map_lock(map); + + before = GET_EV_STATE(se, ENABLED); + if (!can_sdei_state_trans(se, DO_ENABLE)) + goto finish; + after = GET_EV_STATE(se, ENABLED); + + /* + * Enable interrupt for bound events only if there's a change in enabled + * state. + */ + if (is_map_bound(map) && (!before && after)) + plat_ic_enable_interrupt(map->intr); + + ret = 0; + +finish: + if (is_event_shared(map)) + sdei_map_unlock(map); + + return ret; +} + +/* Disable SDEI event */ +static int sdei_event_disable(int ev_num) +{ + sdei_ev_map_t *map; + sdei_entry_t *se; + int ret; + bool before, after; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + ret = SDEI_EDENY; + + if (is_event_shared(map)) + sdei_map_lock(map); + + before = GET_EV_STATE(se, ENABLED); + if (!can_sdei_state_trans(se, DO_DISABLE)) + goto finish; + after = GET_EV_STATE(se, ENABLED); + + /* + * Disable interrupt for bound events only if there's a change in + * enabled state. + */ + if (is_map_bound(map) && (before && !after)) + plat_ic_disable_interrupt(map->intr); + + ret = 0; + +finish: + if (is_event_shared(map)) + sdei_map_unlock(map); + + return ret; +} + +/* Query SDEI event information */ +static int64_t sdei_event_get_info(int ev_num, int info) +{ + sdei_entry_t *se; + sdei_ev_map_t *map; + + uint64_t flags; + bool registered; + uint64_t affinity; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + + if (is_event_shared(map)) + sdei_map_lock(map); + + /* Sample state under lock */ + registered = GET_EV_STATE(se, REGISTERED); + flags = se->reg_flags; + affinity = se->affinity; + + if (is_event_shared(map)) + sdei_map_unlock(map); + + switch (info) { + case SDEI_INFO_EV_TYPE: + return is_event_shared(map); + + case SDEI_INFO_EV_NOT_SIGNALED: + return !is_event_signalable(map); + + case SDEI_INFO_EV_PRIORITY: + return is_event_critical(map); + + case SDEI_INFO_EV_ROUTING_MODE: + if (!is_event_shared(map)) + return SDEI_EINVAL; + if (!registered) + return SDEI_EDENY; + return (flags == SDEI_REGF_RM_PE); + + case SDEI_INFO_EV_ROUTING_AFF: + if (!is_event_shared(map)) + return SDEI_EINVAL; + if (!registered) + return SDEI_EDENY; + if (flags != SDEI_REGF_RM_PE) + return SDEI_EINVAL; + return affinity; + + default: + return SDEI_EINVAL; + } +} + +/* Unregister an SDEI event */ +static int sdei_event_unregister(int ev_num) +{ + int ret = 0; + sdei_entry_t *se; + sdei_ev_map_t *map; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + + /* + * Even though unregister operation is per-event (additionally for + * private events, unregistration is required individually), it has to + * be serialised with respect to bind/release, which are global + * operations. So we hold the lock throughout, unconditionally. + */ + sdei_map_lock(map); + + if (!can_sdei_state_trans(se, DO_UNREGISTER)) { + /* + * Even if the call is invalid, and the handler is running (for + * example, having unregistered from a running handler earlier), + * return pending error code; otherwise, return deny. + */ + ret = GET_EV_STATE(se, RUNNING) ? SDEI_EPEND : SDEI_EDENY; + + goto finish; + } + + map->reg_count--; + if (is_event_private(map)) { + /* Multiple calls to register are possible for private events */ + assert(map->reg_count >= 0); + } else { + /* Only single call to register is possible for shared events */ + assert(map->reg_count == 0); + } + + if (is_map_bound(map)) { + plat_ic_disable_interrupt(map->intr); + + /* + * Clear pending interrupt. Skip for SGIs as they may not be + * cleared on interrupt controllers. + */ + if (ev_num != SDEI_EVENT_0) + plat_ic_clear_interrupt_pending(map->intr); + + assert(plat_ic_get_interrupt_type(map->intr) == INTR_TYPE_EL3); + plat_ic_set_interrupt_type(map->intr, INTR_TYPE_NS); + plat_ic_set_interrupt_priority(map->intr, LOWEST_INTR_PRIORITY); + } + + clear_event_entries(se); + + /* + * If the handler is running at the time of unregister, return the + * pending error code. + */ + if (GET_EV_STATE(se, RUNNING)) + ret = SDEI_EPEND; + +finish: + sdei_map_unlock(map); + + return ret; +} + +/* Query status of an SDEI event */ +static int sdei_event_status(int ev_num) +{ + sdei_ev_map_t *map; + sdei_entry_t *se; + sdei_state_t state; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + + if (is_event_shared(map)) + sdei_map_lock(map); + + /* State value directly maps to the expected return format */ + state = se->state; + + if (is_event_shared(map)) + sdei_map_unlock(map); + + return (int) state; +} + +/* Bind an SDEI event to an interrupt */ +static int sdei_interrupt_bind(unsigned int intr_num) +{ + sdei_ev_map_t *map; + bool retry = true, shared_mapping; + + /* SGIs are not allowed to be bound */ + if (plat_ic_is_sgi(intr_num) != 0) + return SDEI_EINVAL; + + shared_mapping = (plat_ic_is_spi(intr_num) != 0); + do { + /* + * Bail out if there is already an event for this interrupt, + * either platform-defined or dynamic. + */ + map = find_event_map_by_intr(intr_num, shared_mapping); + if (map != NULL) { + if (is_map_dynamic(map)) { + if (is_map_bound(map)) { + /* + * Dynamic event, already bound. Return + * event number. + */ + return map->ev_num; + } + } else { + /* Binding non-dynamic event */ + return SDEI_EINVAL; + } + } + + /* + * The interrupt is not bound yet. Try to find a free slot to + * bind it. Free dynamic mappings have their interrupt set as + * SDEI_DYN_IRQ. + */ + map = find_event_map_by_intr(SDEI_DYN_IRQ, shared_mapping); + if (map == NULL) + return SDEI_ENOMEM; + + /* The returned mapping must be dynamic */ + assert(is_map_dynamic(map)); + + /* + * We cannot assert for bound maps here, as we might be racing + * with another bind. + */ + + /* The requested interrupt must already belong to NS */ + if (plat_ic_get_interrupt_type(intr_num) != INTR_TYPE_NS) + return SDEI_EDENY; + + /* + * Interrupt programming and ownership transfer are deferred + * until register. + */ + + sdei_map_lock(map); + if (!is_map_bound(map)) { + map->intr = intr_num; + set_map_bound(map); + retry = false; + } + sdei_map_unlock(map); + } while (retry); + + return map->ev_num; +} + +/* Release a bound SDEI event previously to an interrupt */ +static int sdei_interrupt_release(int ev_num) +{ + int ret = 0; + sdei_ev_map_t *map; + sdei_entry_t *se; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + if (!is_map_dynamic(map)) + return SDEI_EINVAL; + + se = get_event_entry(map); + + sdei_map_lock(map); + + /* Event must have been unregistered before release */ + if (map->reg_count != 0) { + ret = SDEI_EDENY; + goto finish; + } + + /* + * Interrupt release never causes the state to change. We only check + * whether it's permissible or not. + */ + if (!can_sdei_state_trans(se, DO_RELEASE)) { + ret = SDEI_EDENY; + goto finish; + } + + if (is_map_bound(map)) { + /* + * Deny release if the interrupt is active, which means it's + * probably being acknowledged and handled elsewhere. + */ + if (plat_ic_get_interrupt_active(map->intr) != 0U) { + ret = SDEI_EDENY; + goto finish; + } + + /* + * Interrupt programming and ownership transfer are already done + * during unregister. + */ + + map->intr = SDEI_DYN_IRQ; + clr_map_bound(map); + } else { + SDEI_LOG("Error release bound:%d cnt:%d\n", is_map_bound(map), + map->reg_count); + ret = SDEI_EINVAL; + } + +finish: + sdei_map_unlock(map); + + return ret; +} + +/* Perform reset of private SDEI events */ +static int sdei_private_reset(void) +{ + sdei_ev_map_t *map; + int ret = 0, final_ret = 0; + unsigned int i; + + /* Unregister all private events */ + for_each_private_map(i, map) { + /* + * The unregister can fail if the event is not registered, which + * is allowed, and a deny will be returned. But if the event is + * running or unregister pending, the call fails. + */ + ret = sdei_event_unregister(map->ev_num); + if ((ret == SDEI_EPEND) && (final_ret == 0)) + final_ret = SDEI_EDENY; + } + + return final_ret; +} + +/* Perform reset of shared SDEI events */ +static int sdei_shared_reset(void) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + int ret = 0, final_ret = 0; + unsigned int i, j; + + /* Unregister all shared events */ + for_each_shared_map(i, map) { + /* + * The unregister can fail if the event is not registered, which + * is allowed, and a deny will be returned. But if the event is + * running or unregister pending, the call fails. + */ + ret = sdei_event_unregister(map->ev_num); + if ((ret == SDEI_EPEND) && (final_ret == 0)) + final_ret = SDEI_EDENY; + } + + if (final_ret != 0) + return final_ret; + + /* + * Loop through both private and shared mappings, and release all + * bindings. + */ + for_each_mapping_type(i, mapping) { + iterate_mapping(mapping, j, map) { + /* + * Release bindings for mappings that are dynamic and + * bound. + */ + if (is_map_dynamic(map) && is_map_bound(map)) { + /* + * Any failure to release would mean there is at + * least a PE registered for the event. + */ + ret = sdei_interrupt_release(map->ev_num); + if ((ret != 0) && (final_ret == 0)) + final_ret = ret; + } + } + } + + return final_ret; +} + +/* Send a signal to another SDEI client PE */ +static int sdei_signal(int ev_num, uint64_t target_pe) +{ + sdei_ev_map_t *map; + + /* Only event 0 can be signalled */ + if (ev_num != SDEI_EVENT_0) + return SDEI_EINVAL; + + /* Find mapping for event 0 */ + map = find_event_map(SDEI_EVENT_0); + if (map == NULL) + return SDEI_EINVAL; + + /* The event must be signalable */ + if (!is_event_signalable(map)) + return SDEI_EINVAL; + + /* Validate target */ + if (plat_core_pos_by_mpidr(target_pe) < 0) + return SDEI_EINVAL; + + /* Raise SGI. Platform will validate target_pe */ + plat_ic_raise_el3_sgi((int) map->intr, (u_register_t) target_pe); + + return 0; +} + +/* Query SDEI dispatcher features */ +static uint64_t sdei_features(unsigned int feature) +{ + if (feature == SDEI_FEATURE_BIND_SLOTS) { + return FEATURE_BIND_SLOTS(num_dyn_priv_slots, + num_dyn_shrd_slots); + } + + return (uint64_t) SDEI_EINVAL; +} + +/* SDEI top level handler for servicing SMCs */ +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) +{ + + uint64_t x5; + unsigned int ss = (unsigned int) get_interrupt_src_ss(flags); + int64_t ret; + bool resume = false; + cpu_context_t *ctx = handle; + int ev_num = (int) x1; + + if (ss != NON_SECURE) + SMC_RET1(ctx, SMC_UNK); + + /* Verify the caller EL */ + if (GET_EL(read_spsr_el3()) != sdei_client_el()) + SMC_RET1(ctx, SMC_UNK); + + switch (smc_fid) { + case SDEI_VERSION: + SDEI_LOG("> VER\n"); + ret = (int64_t) sdei_version(); + SDEI_LOG("< VER:%" PRIx64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_REGISTER: + x5 = SMC_GET_GP(ctx, CTX_GPREG_X5); + SDEI_LOG("> REG(n:%d e:%" PRIx64 " a:%" PRIx64 " f:%x m:%" PRIx64 "\n", ev_num, + x2, x3, (int) x4, x5); + ret = sdei_event_register(ev_num, x2, x3, x4, x5); + SDEI_LOG("< REG:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_ENABLE: + SDEI_LOG("> ENABLE(n:%d)\n", (int) x1); + ret = sdei_event_enable(ev_num); + SDEI_LOG("< ENABLE:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_DISABLE: + SDEI_LOG("> DISABLE(n:0x%x)\n", ev_num); + ret = sdei_event_disable(ev_num); + SDEI_LOG("< DISABLE:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_CONTEXT: + SDEI_LOG("> CTX(p:%d):%lx\n", (int) x1, read_mpidr_el1()); + ret = sdei_event_context(ctx, (unsigned int) x1); + SDEI_LOG("< CTX:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_COMPLETE_AND_RESUME: + resume = true; + /* Fallthrough */ + + case SDEI_EVENT_COMPLETE: + SDEI_LOG("> COMPLETE(r:%u sta/ep:%" PRIx64 "):%lx\n", + (unsigned int) resume, x1, read_mpidr_el1()); + ret = sdei_event_complete(resume, x1); + SDEI_LOG("< COMPLETE:%" PRIx64 "\n", ret); + + /* + * Set error code only if the call failed. If the call + * succeeded, we discard the dispatched context, and restore the + * interrupted context to a pristine condition, and therefore + * shouldn't be modified. We don't return to the caller in this + * case anyway. + */ + if (ret != 0) + SMC_RET1(ctx, ret); + + SMC_RET0(ctx); + + case SDEI_EVENT_STATUS: + SDEI_LOG("> STAT(n:0x%x)\n", ev_num); + ret = sdei_event_status(ev_num); + SDEI_LOG("< STAT:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_GET_INFO: + SDEI_LOG("> INFO(n:0x%x, %d)\n", ev_num, (int) x2); + ret = sdei_event_get_info(ev_num, (int) x2); + SDEI_LOG("< INFO:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_UNREGISTER: + SDEI_LOG("> UNREG(n:0x%x)\n", ev_num); + ret = sdei_event_unregister(ev_num); + SDEI_LOG("< UNREG:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_PE_UNMASK: + SDEI_LOG("> UNMASK:%lx\n", read_mpidr_el1()); + sdei_pe_unmask(); + SDEI_LOG("< UNMASK:%d\n", 0); + SMC_RET1(ctx, 0); + + case SDEI_PE_MASK: + SDEI_LOG("> MASK:%lx\n", read_mpidr_el1()); + ret = sdei_pe_mask(); + SDEI_LOG("< MASK:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_INTERRUPT_BIND: + SDEI_LOG("> BIND(%d)\n", (int) x1); + ret = sdei_interrupt_bind((unsigned int) x1); + SDEI_LOG("< BIND:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_INTERRUPT_RELEASE: + SDEI_LOG("> REL(0x%x)\n", ev_num); + ret = sdei_interrupt_release(ev_num); + SDEI_LOG("< REL:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_SHARED_RESET: + SDEI_LOG("> S_RESET():%lx\n", read_mpidr_el1()); + ret = sdei_shared_reset(); + SDEI_LOG("< S_RESET:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_PRIVATE_RESET: + SDEI_LOG("> P_RESET():%lx\n", read_mpidr_el1()); + ret = sdei_private_reset(); + SDEI_LOG("< P_RESET:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_ROUTING_SET: + SDEI_LOG("> ROUTE_SET(n:%d f:%" PRIx64 " aff:%" PRIx64 ")\n", ev_num, x2, x3); + ret = sdei_event_routing_set(ev_num, x2, x3); + SDEI_LOG("< ROUTE_SET:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_FEATURES: + SDEI_LOG("> FTRS(f:%" PRIx64 ")\n", x1); + ret = (int64_t) sdei_features((unsigned int) x1); + SDEI_LOG("< FTRS:%" PRIx64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_SIGNAL: + SDEI_LOG("> SIGNAL(e:%d t:%" PRIx64 ")\n", ev_num, x2); + ret = sdei_signal(ev_num, x2); + SDEI_LOG("< SIGNAL:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + default: + /* Do nothing in default case */ + break; + } + + WARN("Unimplemented SDEI Call: 0x%x\n", smc_fid); + SMC_RET1(ctx, SMC_UNK); +} + +/* Subscribe to PSCI CPU on to initialize per-CPU SDEI configuration */ +SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, sdei_cpu_on_init); + +/* Subscribe to PSCI CPU suspend finisher for per-CPU configuration */ +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, sdei_cpu_wakeup_init); diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_private.h b/arm-trusted-firmware/services/std_svc/sdei/sdei_private.h new file mode 100644 index 0000000..44a7301 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_private.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDEI_PRIVATE_H +#define SDEI_PRIVATE_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __aarch64__ +# error SDEI is implemented only for AArch64 systems +#endif + +#ifndef PLAT_SDEI_CRITICAL_PRI +# error Platform must define SDEI critical priority value +#endif + +#ifndef PLAT_SDEI_NORMAL_PRI +# error Platform must define SDEI normal priority value +#endif + +/* Output SDEI logs as verbose */ +#define SDEI_LOG(...) VERBOSE("SDEI: " __VA_ARGS__) + +/* SDEI handler unregistered state. This is the default state. */ +#define SDEI_STATE_UNREGISTERED 0U + +/* SDE event status values in bit position */ +#define SDEI_STATF_REGISTERED 0U +#define SDEI_STATF_ENABLED 1U +#define SDEI_STATF_RUNNING 2U + +/* SDEI SMC error codes */ +#define SDEI_EINVAL (-2) +#define SDEI_EDENY (-3) +#define SDEI_EPEND (-5) +#define SDEI_ENOMEM (-10) + +/* + * 'info' parameter to SDEI_EVENT_GET_INFO SMC. + * + * Note that the SDEI v1.0 specification mistakenly enumerates the + * SDEI_INFO_EV_SIGNALED as SDEI_INFO_SIGNALED. This will be corrected in a + * future version. + */ +#define SDEI_INFO_EV_TYPE 0 +#define SDEI_INFO_EV_NOT_SIGNALED 1 +#define SDEI_INFO_EV_PRIORITY 2 +#define SDEI_INFO_EV_ROUTING_MODE 3 +#define SDEI_INFO_EV_ROUTING_AFF 4 + +#define SDEI_PRIVATE_MAPPING() (&sdei_global_mappings[SDEI_MAP_IDX_PRIV_]) +#define SDEI_SHARED_MAPPING() (&sdei_global_mappings[SDEI_MAP_IDX_SHRD_]) + +#define for_each_mapping_type(_i, _mapping) \ + for ((_i) = 0, (_mapping) = &sdei_global_mappings[(_i)]; \ + (_i) < SDEI_MAP_IDX_MAX_; \ + (_i)++, (_mapping) = &sdei_global_mappings[(_i)]) + +#define iterate_mapping(_mapping, _i, _map) \ + for ((_map) = (_mapping)->map, (_i) = 0; \ + (_i) < (_mapping)->num_maps; \ + (_i)++, (_map)++) + +#define for_each_private_map(_i, _map) \ + iterate_mapping(SDEI_PRIVATE_MAPPING(), _i, _map) + +#define for_each_shared_map(_i, _map) \ + iterate_mapping(SDEI_SHARED_MAPPING(), _i, _map) + +/* SDEI_FEATURES */ +#define SDEI_FEATURE_BIND_SLOTS 0U +#define BIND_SLOTS_MASK 0xffffU +#define FEATURES_SHARED_SLOTS_SHIFT 16U +#define FEATURES_PRIVATE_SLOTS_SHIFT 0U +#define FEATURE_BIND_SLOTS(_priv, _shrd) \ + (((((uint64_t) (_priv)) & BIND_SLOTS_MASK) << FEATURES_PRIVATE_SLOTS_SHIFT) | \ + ((((uint64_t) (_shrd)) & BIND_SLOTS_MASK) << FEATURES_SHARED_SLOTS_SHIFT)) + +#define GET_EV_STATE(_e, _s) get_ev_state_bit(_e, SDEI_STATF_##_s) +#define SET_EV_STATE(_e, _s) clr_ev_state_bit(_e->state, SDEI_STATF_##_s) + +static inline bool is_event_private(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_PRIVATE_SHIFT_)) != 0U); +} + +static inline bool is_event_shared(sdei_ev_map_t *map) +{ + return !is_event_private(map); +} + +static inline bool is_event_critical(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_CRITICAL_SHIFT_)) != 0U); +} + +static inline bool is_event_normal(sdei_ev_map_t *map) +{ + return !is_event_critical(map); +} + +static inline bool is_event_signalable(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_SIGNALABLE_SHIFT_)) != 0U); +} + +static inline bool is_map_dynamic(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_DYNAMIC_SHIFT_)) != 0U); +} + +/* + * Checks whether an event is associated with an interrupt. Static events always + * return true, and dynamic events return whether SDEI_INTERRUPT_BIND had been + * called on them. This can be used on both static or dynamic events to check + * for an associated interrupt. + */ +static inline bool is_map_bound(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_BOUND_SHIFT_)) != 0U); +} + +static inline void set_map_bound(sdei_ev_map_t *map) +{ + map->map_flags |= BIT_32(SDEI_MAPF_BOUND_SHIFT_); +} + +static inline bool is_map_explicit(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_EXPLICIT_SHIFT_)) != 0U); +} + +static inline void clr_map_bound(sdei_ev_map_t *map) +{ + map->map_flags &= ~BIT_32(SDEI_MAPF_BOUND_SHIFT_); +} + +static inline bool is_secure_sgi(unsigned int intr) +{ + return ((plat_ic_is_sgi(intr) != 0) && + (plat_ic_get_interrupt_type(intr) == INTR_TYPE_EL3)); +} + +/* + * Determine EL of the client. If EL2 is implemented (hence the enabled HCE + * bit), deem EL2; otherwise, deem EL1. + */ +static inline unsigned int sdei_client_el(void) +{ + cpu_context_t *ns_ctx = cm_get_context(NON_SECURE); + el3_state_t *el3_ctx = get_el3state_ctx(ns_ctx); + + return ((read_ctx_reg(el3_ctx, CTX_SCR_EL3) & SCR_HCE_BIT) != 0U) ? + MODE_EL2 : MODE_EL1; +} + +static inline unsigned int sdei_event_priority(sdei_ev_map_t *map) +{ + return (unsigned int) (is_event_critical(map) ? PLAT_SDEI_CRITICAL_PRI : + PLAT_SDEI_NORMAL_PRI); +} + +static inline bool get_ev_state_bit(sdei_entry_t *se, unsigned int bit_no) +{ + return ((se->state & BIT_32(bit_no)) != 0U); +} + +static inline void clr_ev_state_bit(sdei_entry_t *se, unsigned int bit_no) +{ + se->state &= ~BIT_32(bit_no); +} + +/* SDEI actions for state transition */ +typedef enum { + /* + * Actions resulting from client requests. These directly map to SMC + * calls. Note that the state table columns are listed in this order + * too. + */ + DO_REGISTER = 0, + DO_RELEASE = 1, + DO_ENABLE = 2, + DO_DISABLE = 3, + DO_UNREGISTER = 4, + DO_ROUTING = 5, + DO_CONTEXT = 6, + DO_COMPLETE = 7, + DO_COMPLETE_RESUME = 8, + + /* Action for event dispatch */ + DO_DISPATCH = 9, + + DO_MAX, +} sdei_action_t; + +typedef enum { + SDEI_NORMAL, + SDEI_CRITICAL +} sdei_class_t; + +static inline void sdei_map_lock(sdei_ev_map_t *map) +{ + spin_lock(&map->lock); +} + +static inline void sdei_map_unlock(sdei_ev_map_t *map) +{ + spin_unlock(&map->lock); +} + +extern const sdei_mapping_t sdei_global_mappings[]; +extern sdei_entry_t sdei_private_event_table[]; +extern sdei_entry_t sdei_shared_event_table[]; + +void init_sdei_state(void); + +sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared); +sdei_ev_map_t *find_event_map(int ev_num); +sdei_entry_t *get_event_entry(sdei_ev_map_t *map); + +int64_t sdei_event_context(void *handle, unsigned int param); +int sdei_event_complete(bool resume, uint64_t pc); + +void sdei_pe_unmask(void); +int64_t sdei_pe_mask(void); + +int sdei_intr_handler(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie); +bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act); +void begin_sdei_synchronous_dispatch(jmp_buf *buffer); + +#endif /* SDEI_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_state.c b/arm-trusted-firmware/services/std_svc/sdei/sdei_state.c new file mode 100644 index 0000000..1b448e6 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_state.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include "sdei_private.h" + +/* Aliases for SDEI handler states: 'R'unning, 'E'nabled, and re'G'istered */ +#define r_ 0U +#define R_ (1u << SDEI_STATF_RUNNING) + +#define e_ 0U +#define E_ (1u << SDEI_STATF_ENABLED) + +#define g_ 0U +#define G_ (1u << SDEI_STATF_REGISTERED) + +/* All possible composite handler states */ +#define reg_ (r_ | e_ | g_) +#define reG_ (r_ | e_ | G_) +#define rEg_ (r_ | E_ | g_) +#define rEG_ (r_ | E_ | G_) +#define Reg_ (R_ | e_ | g_) +#define ReG_ (R_ | e_ | G_) +#define REg_ (R_ | E_ | g_) +#define REG_ (R_ | E_ | G_) + +#define MAX_STATES (REG_ + 1u) + +/* Invalid state */ +#define SDEI_STATE_INVALID ((sdei_state_t) (-1)) + +/* No change in state */ +#define SDEI_STATE_NOP ((sdei_state_t) (-2)) + +#define X___ SDEI_STATE_INVALID +#define NOP_ SDEI_STATE_NOP + +/* Ensure special states don't overlap with valid ones */ +CASSERT(X___ > REG_, sdei_state_overlap_invalid); +CASSERT(NOP_ > REG_, sdei_state_overlap_nop); + +/* + * SDEI handler state machine: refer to sections 6.1 and 6.1.2 of the SDEI v1.0 + * specification (ARM DEN0054A). + * + * Not all calls contribute to handler state transition. This table is also used + * to validate whether a call is permissible at a given handler state: + * + * - X___ denotes a forbidden transition; + * - NOP_ denotes a permitted transition, but there's no change in state; + * - Otherwise, XXX_ gives the new state. + * + * DISP[atch] is a transition added for the implementation, but is not mentioned + * in the spec. + * + * Those calls that the spec mentions as can be made any time don't picture in + * this table. + */ + +static const sdei_state_t sdei_state_table[MAX_STATES][DO_MAX] = { +/* + * Action: REG REL ENA DISA UREG ROUT CTX COMP COMPR DISP + * Notes: [3] [1] [3] [3][4] [2] + */ + /* Handler unregistered, disabled, and not running. This is the default state. */ +/* 0 */ [reg_] = { reG_, NOP_, X___, X___, X___, X___, X___, X___, X___, X___, }, + + /* Handler unregistered and running */ +/* 4 */ [Reg_] = { X___, X___, X___, X___, X___, X___, NOP_, reg_, reg_, X___, }, + + /* Handler registered */ +/* 1 */ [reG_] = { X___, X___, rEG_, NOP_, reg_, NOP_, X___, X___, X___, X___, }, + + /* Handler registered and running */ +/* 5 */ [ReG_] = { X___, X___, REG_, NOP_, Reg_, X___, NOP_, reG_, reG_, X___, }, + + /* Handler registered and enabled */ +/* 3 */ [rEG_] = { X___, X___, NOP_, reG_, reg_, X___, X___, X___, X___, REG_, }, + + /* Handler registered, enabled, and running */ +/* 7 */ [REG_] = { X___, X___, NOP_, ReG_, Reg_, X___, NOP_, rEG_, rEG_, X___, }, + + /* + * Invalid states: no valid transition would leave the handler in these + * states; and no transition from these states is possible either. + */ + + /* + * Handler can't be enabled without being registered. I.e., XEg is + * impossible. + */ +/* 2 */ [rEg_] = { X___, X___, X___, X___, X___, X___, X___, X___, X___, X___, }, +/* 6 */ [REg_] = { X___, X___, X___, X___, X___, X___, X___, X___, X___, X___, }, +}; + +/* + * [1] Unregister will always also disable the event, so the new state will have + * Xeg. + * [2] Event is considered for dispatch only when it's both registered and + * enabled. + * [3] Never causes change in state. + * [4] Only allowed when running. + */ + +/* + * Given an action, transition the state of an event by looking up the state + * table above: + * + * - Return false for invalid transition; + * - Return true for valid transition that causes no change in state; + * - Otherwise, update state and return true. + * + * This function assumes that the caller holds necessary locks. If the + * transition has constrains other than the state table describes, the caller is + * expected to restore the previous state. See sdei_event_register() for + * example. + */ +bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act) +{ + sdei_state_t next; + + assert(act < DO_MAX); + if (se->state >= MAX_STATES) { + WARN(" event state invalid: %x\n", se->state); + return false; + } + + next = sdei_state_table[se->state][act]; + switch (next) { + case SDEI_STATE_INVALID: + return false; + + case SDEI_STATE_NOP: + return true; + + default: + /* Valid transition. Update state. */ + SDEI_LOG(" event state 0x%x => 0x%x\n", se->state, next); + se->state = next; + + return true; + } +} diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S b/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S new file mode 100644 index 0000000..2c3aaf7 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "../spm_mm_private.h" + + .global spm_secure_partition_enter + .global spm_secure_partition_exit + + /* --------------------------------------------------------------------- + * This function is called with SP_EL0 as stack. Here we stash our EL3 + * callee-saved registers on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where the address of the C + * runtime context is to be saved. + * --------------------------------------------------------------------- + */ +func spm_secure_partition_enter + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #SP_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #SP_C_RT_CTX_X19] + stp x21, x22, [sp, #SP_C_RT_CTX_X21] + stp x23, x24, [sp, #SP_C_RT_CTX_X23] + stp x25, x26, [sp, #SP_C_RT_CTX_X25] + stp x27, x28, [sp, #SP_C_RT_CTX_X27] + stp x29, x30, [sp, #SP_C_RT_CTX_X29] + + /* --------------------------------------------------------------------- + * Everything is setup now. el3_exit() will use the secure context to + * restore to the general purpose and EL3 system registers to ERET + * into the secure payload. + * --------------------------------------------------------------------- + */ + b el3_exit +endfunc spm_secure_partition_enter + + /* --------------------------------------------------------------------- + * This function is called with 'x0' pointing to a C runtime context + * saved in spm_secure_partition_enter(). + * It restores the saved registers and jumps to that runtime with 'x0' + * as the new SP register. This destroys the C runtime context that had + * been built on the stack below the saved context by the caller. Later + * the second parameter 'x1' is passed as a return value to the caller. + * --------------------------------------------------------------------- + */ +func spm_secure_partition_exit + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(SP_C_RT_CTX_X19 - SP_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(SP_C_RT_CTX_X21 - SP_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(SP_C_RT_CTX_X23 - SP_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(SP_C_RT_CTX_X25 - SP_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(SP_C_RT_CTX_X27 - SP_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(SP_C_RT_CTX_X29 - SP_C_RT_CTX_SIZE)] + + /* --------------------------------------------------------------------- + * This should take us back to the instruction after the call to the + * last spm_secure_partition_enter().* Place the second parameter to x0 + * so that the caller will see it as a return value from the original + * entry call. + * --------------------------------------------------------------------- + */ + mov x0, x1 + ret +endfunc spm_secure_partition_exit diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S b/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S new file mode 100644 index 0000000..be4084c --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by the spm shim layer. + * ----------------------------------------------------------------------------- + */ + .globl spm_shim_exceptions_ptr + +vector_base spm_shim_exceptions_ptr, .spm_shim_exceptions + + /* ----------------------------------------------------- + * Current EL with SP0 : 0x0 - 0x200 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSP0, .spm_shim_exceptions + b . +end_vector_entry SynchronousExceptionSP0 + +vector_entry IrqSP0, .spm_shim_exceptions + b . +end_vector_entry IrqSP0 + +vector_entry FiqSP0, .spm_shim_exceptions + b . +end_vector_entry FiqSP0 + +vector_entry SErrorSP0, .spm_shim_exceptions + b . +end_vector_entry SErrorSP0 + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSPx, .spm_shim_exceptions + b . +end_vector_entry SynchronousExceptionSPx + +vector_entry IrqSPx, .spm_shim_exceptions + b . +end_vector_entry IrqSPx + +vector_entry FiqSPx, .spm_shim_exceptions + b . +end_vector_entry FiqSPx + +vector_entry SErrorSPx, .spm_shim_exceptions + b . +end_vector_entry SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600. No exceptions + * are handled since secure_partition does not implement + * a lower EL + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA64, .spm_shim_exceptions + msr tpidr_el1, x30 + mrs x30, esr_el1 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + + cmp x30, #EC_AARCH64_SVC + b.eq do_smc + + cmp x30, #EC_AARCH32_SVC + b.eq do_smc + + cmp x30, #EC_AARCH64_SYS + b.eq handle_sys_trap + + /* Fail in all the other cases */ + b panic + + /* --------------------------------------------- + * Tell SPM that we are done initialising + * --------------------------------------------- + */ +do_smc: + mrs x30, tpidr_el1 + smc #0 + exception_return + + /* AArch64 system instructions trap are handled as a panic for now */ +handle_sys_trap: +panic: + b panic +end_vector_entry SynchronousExceptionA64 + +vector_entry IrqA64, .spm_shim_exceptions + b . +end_vector_entry IrqA64 + +vector_entry FiqA64, .spm_shim_exceptions + b . +end_vector_entry FiqA64 + +vector_entry SErrorA64, .spm_shim_exceptions + b . +end_vector_entry SErrorA64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32, .spm_shim_exceptions + b . +end_vector_entry SynchronousExceptionA32 + +vector_entry IrqA32, .spm_shim_exceptions + b . +end_vector_entry IrqA32 + +vector_entry FiqA32, .spm_shim_exceptions + b . +end_vector_entry FiqA32 + +vector_entry SErrorA32, .spm_shim_exceptions + b . +end_vector_entry SErrorA32 diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm.mk b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm.mk new file mode 100644 index 0000000..a87bdd8 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm.mk @@ -0,0 +1,32 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${SPD},none) + $(error "Error: SPD and SPM_MM are incompatible build options.") +endif +ifneq (${ARCH},aarch64) + $(error "Error: SPM_MM is only supported on aarch64.") +endif +ifeq (${ENABLE_SVE_FOR_NS},1) + $(error "Error: SPM_MM is not compatible with ENABLE_SVE_FOR_NS") +endif +ifeq (${ENABLE_SME_FOR_NS},1) + $(error "Error: SPM_MM is not compatible with ENABLE_SME_FOR_NS") +endif + +SPM_SOURCES := $(addprefix services/std_svc/spm_mm/, \ + ${ARCH}/spm_mm_helpers.S \ + ${ARCH}/spm_mm_shim_exceptions.S \ + spm_mm_main.c \ + spm_mm_setup.c \ + spm_mm_xlat.c) + + +# Let the top-level Makefile know that we intend to include a BL32 image +NEED_BL32 := yes + +# required so that SPM code executing at S-EL0 can access the timer registers +NS_TIMER_SWITCH := 1 diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c new file mode 100644 index 0000000..14c0038 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2017-2019, 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 +#include +#include + +#include "spm_mm_private.h" + +/******************************************************************************* + * Secure Partition context information. + ******************************************************************************/ +static sp_context_t sp_ctx; + +/******************************************************************************* + * Set state of a Secure Partition context. + ******************************************************************************/ +void sp_state_set(sp_context_t *sp_ptr, sp_state_t state) +{ + spin_lock(&(sp_ptr->state_lock)); + sp_ptr->state = state; + spin_unlock(&(sp_ptr->state_lock)); +} + +/******************************************************************************* + * Wait until the state of a Secure Partition is the specified one and change it + * to the desired state. + ******************************************************************************/ +void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) +{ + int success = 0; + + while (success == 0) { + spin_lock(&(sp_ptr->state_lock)); + + if (sp_ptr->state == from) { + sp_ptr->state = to; + + success = 1; + } + + spin_unlock(&(sp_ptr->state_lock)); + } +} + +/******************************************************************************* + * Check if the state of a Secure Partition is the specified one and, if so, + * change it to the desired state. Returns 0 on success, -1 on error. + ******************************************************************************/ +int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) +{ + int ret = -1; + + spin_lock(&(sp_ptr->state_lock)); + + if (sp_ptr->state == from) { + sp_ptr->state = to; + + ret = 0; + } + + spin_unlock(&(sp_ptr->state_lock)); + + return ret; +} + +/******************************************************************************* + * This function takes an SP context pointer and performs a synchronous entry + * into it. + ******************************************************************************/ +static uint64_t spm_sp_synchronous_entry(sp_context_t *ctx) +{ + uint64_t rc; + + assert(ctx != NULL); + + /* Assign the context of the SP to this CPU */ + cm_set_context(&(ctx->cpu_ctx), SECURE); + + /* Restore the context assigned above */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* Invalidate TLBs at EL1. */ + tlbivmalle1(); + dsbish(); + + /* Enter Secure Partition */ + rc = spm_secure_partition_enter(&ctx->c_rt_ctx); + + /* Save secure state */ + cm_el1_sysregs_context_save(SECURE); + + return rc; +} + +/******************************************************************************* + * This function returns to the place where spm_sp_synchronous_entry() was + * called originally. + ******************************************************************************/ +__dead2 static void spm_sp_synchronous_exit(uint64_t rc) +{ + sp_context_t *ctx = &sp_ctx; + + /* + * The SPM must have initiated the original request through a + * synchronous entry into the secure partition. Jump back to the + * original C runtime context with the value of rc in x0; + */ + spm_secure_partition_exit(ctx->c_rt_ctx, rc); + + panic(); +} + +/******************************************************************************* + * Jump to each Secure Partition for the first time. + ******************************************************************************/ +static int32_t spm_init(void) +{ + uint64_t rc; + sp_context_t *ctx; + + INFO("Secure Partition init...\n"); + + ctx = &sp_ctx; + + ctx->state = SP_STATE_RESET; + + rc = spm_sp_synchronous_entry(ctx); + assert(rc == 0); + + ctx->state = SP_STATE_IDLE; + + INFO("Secure Partition initialized.\n"); + + return !rc; +} + +/******************************************************************************* + * Initialize contexts of all Secure Partitions. + ******************************************************************************/ +int32_t spm_mm_setup(void) +{ + sp_context_t *ctx; + + /* Disable MMU at EL1 (initialized by BL2) */ + disable_mmu_icache_el1(); + + /* Initialize context of the SP */ + INFO("Secure Partition context setup start...\n"); + + ctx = &sp_ctx; + + /* Assign translation tables context. */ + ctx->xlat_ctx_handle = spm_get_sp_xlat_context(); + + spm_sp_setup(ctx); + + /* Register init function for deferred init. */ + bl31_register_bl32_init(&spm_init); + + INFO("Secure Partition setup done.\n"); + + return 0; +} + +/******************************************************************************* + * Function to perform a call to a Secure Partition. + ******************************************************************************/ +uint64_t spm_mm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3) +{ + uint64_t rc; + sp_context_t *sp_ptr = &sp_ctx; + + /* Wait until the Secure Partition is idle and set it to busy. */ + sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY); + + /* Set values for registers on SP entry */ + cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx); + + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3); + + /* Jump to the Secure Partition. */ + rc = spm_sp_synchronous_entry(sp_ptr); + + /* Flag Secure Partition as idle. */ + assert(sp_ptr->state == SP_STATE_BUSY); + sp_state_set(sp_ptr, SP_STATE_IDLE); + + return rc; +} + +/******************************************************************************* + * MM_COMMUNICATE handler + ******************************************************************************/ +static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie, + uint64_t comm_buffer_address, + uint64_t comm_size_address, void *handle) +{ + uint64_t rc; + + /* Cookie. Reserved for future use. It must be zero. */ + if (mm_cookie != 0U) { + ERROR("MM_COMMUNICATE: cookie is not zero\n"); + SMC_RET1(handle, SPM_MM_INVALID_PARAMETER); + } + + if (comm_buffer_address == 0U) { + ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n"); + SMC_RET1(handle, SPM_MM_INVALID_PARAMETER); + } + + if (comm_size_address != 0U) { + VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n"); + } + + /* + * The current secure partition design mandates + * - at any point, only a single core can be + * executing in the secure partiton. + * - a core cannot be preempted by an interrupt + * while executing in secure partition. + * Raise the running priority of the core to the + * interrupt level configured for secure partition + * so as to block any interrupt from preempting this + * core. + */ + ehf_activate_priority(PLAT_SP_PRI); + + /* Save the Normal world context */ + cm_el1_sysregs_context_save(NON_SECURE); + + rc = spm_mm_sp_call(smc_fid, comm_buffer_address, comm_size_address, + plat_my_core_pos()); + + /* Restore non-secure state */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + /* + * Exited from secure partition. This core can take + * interrupts now. + */ + ehf_deactivate_priority(PLAT_SP_PRI); + + SMC_RET1(handle, rc); +} + +/******************************************************************************* + * Secure Partition Manager SMC handler. + ******************************************************************************/ +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) +{ + unsigned int ns; + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + + if (ns == SMC_FROM_SECURE) { + + /* Handle SMCs from Secure world. */ + + assert(handle == cm_get_context(SECURE)); + + /* Make next ERET jump to S-EL0 instead of S-EL1. */ + cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1()); + + switch (smc_fid) { + + case SPM_MM_VERSION_AARCH32: + SMC_RET1(handle, SPM_MM_VERSION_COMPILED); + + case MM_SP_EVENT_COMPLETE_AARCH64: + spm_sp_synchronous_exit(x1); + + case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: + INFO("Received MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); + + if (sp_ctx.state != SP_STATE_RESET) { + WARN("MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); + SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); + } + SMC_RET1(handle, + spm_memory_attributes_get_smc_handler( + &sp_ctx, x1)); + + case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: + INFO("Received MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n"); + + if (sp_ctx.state != SP_STATE_RESET) { + WARN("MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); + SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); + } + SMC_RET1(handle, + spm_memory_attributes_set_smc_handler( + &sp_ctx, x1, x2, x3)); + default: + break; + } + } else { + + /* Handle SMCs from Non-secure world. */ + + assert(handle == cm_get_context(NON_SECURE)); + + switch (smc_fid) { + + case MM_VERSION_AARCH32: + SMC_RET1(handle, MM_VERSION_COMPILED); + + case MM_COMMUNICATE_AARCH32: + case MM_COMMUNICATE_AARCH64: + return mm_communicate(smc_fid, x1, x2, x3, handle); + + case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: + case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: + /* SMC interfaces reserved for secure callers. */ + SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); + + default: + break; + } + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h new file mode 100644 index 0000000..45b4789 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_MM_PRIVATE_H +#define SPM_MM_PRIVATE_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define SP_C_RT_CTX_X19 0x0 +#define SP_C_RT_CTX_X20 0x8 +#define SP_C_RT_CTX_X21 0x10 +#define SP_C_RT_CTX_X22 0x18 +#define SP_C_RT_CTX_X23 0x20 +#define SP_C_RT_CTX_X24 0x28 +#define SP_C_RT_CTX_X25 0x30 +#define SP_C_RT_CTX_X26 0x38 +#define SP_C_RT_CTX_X27 0x40 +#define SP_C_RT_CTX_X28 0x48 +#define SP_C_RT_CTX_X29 0x50 +#define SP_C_RT_CTX_X30 0x58 + +#define SP_C_RT_CTX_SIZE 0x60 +#define SP_C_RT_CTX_ENTRIES (SP_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +#include +#include + +typedef enum sp_state { + SP_STATE_RESET = 0, + SP_STATE_IDLE, + SP_STATE_BUSY +} sp_state_t; + +typedef struct sp_context { + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; + xlat_ctx_t *xlat_ctx_handle; + + sp_state_t state; + spinlock_t state_lock; +} sp_context_t; + +/* Assembly helpers */ +uint64_t spm_secure_partition_enter(uint64_t *c_rt_ctx); +void __dead2 spm_secure_partition_exit(uint64_t c_rt_ctx, uint64_t ret); + +void spm_sp_setup(sp_context_t *sp_ctx); + +xlat_ctx_t *spm_get_sp_xlat_context(void); + +int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx, + uintptr_t base_va); +int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx, + u_register_t page_address, + u_register_t pages_count, + u_register_t smc_attributes); + +#endif /* __ASSEMBLER__ */ + +#endif /* SPM_MM_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c new file mode 100644 index 0000000..9d681c2 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_mm_private.h" +#include "spm_mm_shim_private.h" + +/* Setup context of the Secure Partition */ +void spm_sp_setup(sp_context_t *sp_ctx) +{ + cpu_context_t *ctx = &(sp_ctx->cpu_ctx); + + /* Pointer to the MP information from the platform port. */ + const spm_mm_boot_info_t *sp_boot_info = + plat_get_secure_partition_boot_info(NULL); + + /* + * Initialize CPU context + * ---------------------- + */ + + entry_point_info_t ep_info = {0}; + + SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); + + /* Setup entrypoint and SPSR */ + ep_info.pc = sp_boot_info->sp_image_base; + ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS); + + /* + * X0: Virtual address of a buffer shared between EL3 and Secure EL0. + * The buffer will be mapped in the Secure EL1 translation regime + * with Normal IS WBWA attributes and RO data and Execute Never + * instruction access permissions. + * + * X1: Size of the buffer in bytes + * + * X2: cookie value (Implementation Defined) + * + * X3: cookie value (Implementation Defined) + * + * X4 to X7 = 0 + */ + ep_info.args.arg0 = sp_boot_info->sp_shared_buf_base; + ep_info.args.arg1 = sp_boot_info->sp_shared_buf_size; + ep_info.args.arg2 = PLAT_SPM_COOKIE_0; + ep_info.args.arg3 = PLAT_SPM_COOKIE_1; + + cm_setup_context(ctx, &ep_info); + + /* + * SP_EL0: A non-zero value will indicate to the SP that the SPM has + * initialized the stack pointer for the current CPU through + * implementation defined means. The value will be 0 otherwise. + */ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_SP_EL0, + sp_boot_info->sp_stack_base + sp_boot_info->sp_pcpu_stack_size); + + /* + * Setup translation tables + * ------------------------ + */ + +#if ENABLE_ASSERTIONS + + /* Get max granularity supported by the platform. */ + unsigned int max_granule = xlat_arch_get_max_supported_granule_size(); + + VERBOSE("Max translation granule size supported: %u KiB\n", + max_granule / 1024U); + + unsigned int max_granule_mask = max_granule - 1U; + + /* Base must be aligned to the max granularity */ + assert((sp_boot_info->sp_ns_comm_buf_base & max_granule_mask) == 0); + + /* Size must be a multiple of the max granularity */ + assert((sp_boot_info->sp_ns_comm_buf_size & max_granule_mask) == 0); + +#endif /* ENABLE_ASSERTIONS */ + + /* This region contains the exception vectors used at S-EL1. */ + const mmap_region_t sel1_exception_vectors = + MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START, + SPM_SHIM_EXCEPTIONS_SIZE, + MT_CODE | MT_SECURE | MT_PRIVILEGED); + mmap_add_region_ctx(sp_ctx->xlat_ctx_handle, + &sel1_exception_vectors); + + mmap_add_ctx(sp_ctx->xlat_ctx_handle, + plat_get_secure_partition_mmap(NULL)); + + init_xlat_tables_ctx(sp_ctx->xlat_ctx_handle); + + /* + * MMU-related registers + * --------------------- + */ + xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle; + + uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table, + xlat_ctx->pa_max_address, xlat_ctx->va_max_address, + EL1_EL0_REGIME); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1, + mmu_cfg_params[MMU_CFG_MAIR]); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1, + mmu_cfg_params[MMU_CFG_TCR]); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1, + mmu_cfg_params[MMU_CFG_TTBR0]); + + /* Setup SCTLR_EL1 */ + u_register_t sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1); + + sctlr_el1 |= + /*SCTLR_EL1_RES1 |*/ + /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */ + SCTLR_UCI_BIT | + /* RW regions at xlat regime EL1&0 are forced to be XN. */ + SCTLR_WXN_BIT | + /* Don't trap to EL1 execution of WFI or WFE at EL0. */ + SCTLR_NTWI_BIT | SCTLR_NTWE_BIT | + /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */ + SCTLR_UCT_BIT | + /* Don't trap to EL1 execution of DZ ZVA at EL0. */ + SCTLR_DZE_BIT | + /* Enable SP Alignment check for EL0 */ + SCTLR_SA0_BIT | + /* Don't change PSTATE.PAN on taking an exception to EL1 */ + SCTLR_SPAN_BIT | + /* Allow cacheable data and instr. accesses to normal memory. */ + SCTLR_C_BIT | SCTLR_I_BIT | + /* Enable MMU. */ + SCTLR_M_BIT + ; + + sctlr_el1 &= ~( + /* Explicit data accesses at EL0 are little-endian. */ + SCTLR_E0E_BIT | + /* + * Alignment fault checking disabled when at EL1 and EL0 as + * the UEFI spec permits unaligned accesses. + */ + SCTLR_A_BIT | + /* Accesses to DAIF from EL0 are trapped to EL1. */ + SCTLR_UMA_BIT + ); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1); + + /* + * Setup other system registers + * ---------------------------- + */ + + /* Shim Exception Vector Base Address */ + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1, + SPM_SHIM_EXCEPTIONS_PTR); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1, + EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT); + + /* + * FPEN: Allow the Secure Partition to access FP/SIMD registers. + * Note that SPM will not do any saving/restoring of these registers on + * behalf of the SP. This falls under the SP's responsibility. + * TTA: Enable access to trace registers. + * ZEN (v8.2): Trap SVE instructions and access to SVE registers. + */ + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1, + CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); + + /* + * Prepare information in buffer shared between EL3 and S-EL0 + * ---------------------------------------------------------- + */ + + void *shared_buf_ptr = (void *) sp_boot_info->sp_shared_buf_base; + + /* Copy the boot information into the shared buffer with the SP. */ + assert((uintptr_t)shared_buf_ptr + sizeof(spm_mm_boot_info_t) + <= (sp_boot_info->sp_shared_buf_base + sp_boot_info->sp_shared_buf_size)); + + assert(sp_boot_info->sp_shared_buf_base <= + (UINTPTR_MAX - sp_boot_info->sp_shared_buf_size + 1)); + + assert(sp_boot_info != NULL); + + memcpy((void *) shared_buf_ptr, (const void *) sp_boot_info, + sizeof(spm_mm_boot_info_t)); + + /* Pointer to the MP information from the platform port. */ + spm_mm_mp_info_t *sp_mp_info = + ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info; + + assert(sp_mp_info != NULL); + + /* + * Point the shared buffer MP information pointer to where the info will + * be populated, just after the boot info. + */ + ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info = + (spm_mm_mp_info_t *) ((uintptr_t)shared_buf_ptr + + sizeof(spm_mm_boot_info_t)); + + /* + * Update the shared buffer pointer to where the MP information for the + * payload will be populated + */ + shared_buf_ptr = ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info; + + /* + * Copy the cpu information into the shared buffer area after the boot + * information. + */ + assert(sp_boot_info->num_cpus <= PLATFORM_CORE_COUNT); + + assert((uintptr_t)shared_buf_ptr + <= (sp_boot_info->sp_shared_buf_base + sp_boot_info->sp_shared_buf_size - + (sp_boot_info->num_cpus * sizeof(*sp_mp_info)))); + + memcpy(shared_buf_ptr, (const void *) sp_mp_info, + sp_boot_info->num_cpus * sizeof(*sp_mp_info)); + + /* + * Calculate the linear indices of cores in boot information for the + * secure partition and flag the primary CPU + */ + sp_mp_info = (spm_mm_mp_info_t *) shared_buf_ptr; + + for (unsigned int index = 0; index < sp_boot_info->num_cpus; index++) { + u_register_t mpidr = sp_mp_info[index].mpidr; + + sp_mp_info[index].linear_id = plat_core_pos_by_mpidr(mpidr); + if (plat_my_core_pos() == sp_mp_info[index].linear_id) + sp_mp_info[index].flags |= MP_INFO_FLAG_PRIMARY_CPU; + } +} diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h new file mode 100644 index 0000000..0c8d894 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_MM_SHIM_PRIVATE_H +#define SPM_MM_SHIM_PRIVATE_H + +#include + +#include + +/* Assembly source */ +IMPORT_SYM(uintptr_t, spm_shim_exceptions_ptr, SPM_SHIM_EXCEPTIONS_PTR); + +/* Linker symbols */ +IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_START__, SPM_SHIM_EXCEPTIONS_START); +IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_END__, SPM_SHIM_EXCEPTIONS_END); + +/* Definitions */ + +#define SPM_SHIM_EXCEPTIONS_SIZE \ + (SPM_SHIM_EXCEPTIONS_END - SPM_SHIM_EXCEPTIONS_START) + +#endif /* SPM_MM_SHIM_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c new file mode 100644 index 0000000..eae597c --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_mm_private.h" +#include "spm_mm_shim_private.h" + +/* Place translation tables by default along with the ones used by BL31. */ +#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table" +#endif +#ifndef PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME +#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME ".bss" +#endif + +/* Allocate and initialise the translation context for the secure partitions. */ +REGISTER_XLAT_CONTEXT2(sp, + PLAT_SP_IMAGE_MMAP_REGIONS, + PLAT_SP_IMAGE_MAX_XLAT_TABLES, + PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE, + EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME, + PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME); + +/* Lock used for SP_MEMORY_ATTRIBUTES_GET and SP_MEMORY_ATTRIBUTES_SET */ +static spinlock_t mem_attr_smc_lock; + +/* Get handle of Secure Partition translation context */ +xlat_ctx_t *spm_get_sp_xlat_context(void) +{ + return &sp_xlat_ctx; +}; + +/* + * Attributes are encoded using a different format in the SMC interface than in + * the Trusted Firmware, where the mmap_attr_t enum type is used. This function + * converts an attributes value from the SMC format to the mmap_attr_t format by + * setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and MT_EXECUTE/MT_EXECUTE_NEVER. + * The other fields are left as 0 because they are ignored by the function + * xlat_change_mem_attributes_ctx(). + */ +static unsigned int smc_attr_to_mmap_attr(unsigned int attributes) +{ + unsigned int tf_attr = 0U; + + unsigned int access = (attributes & MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + >> MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; + + if (access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW) { + tf_attr |= MT_RW | MT_USER; + } else if (access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO) { + tf_attr |= MT_RO | MT_USER; + } else { + /* Other values are reserved. */ + assert(access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS); + /* The only requirement is that there's no access from EL0 */ + tf_attr |= MT_RO | MT_PRIVILEGED; + } + + if ((attributes & MM_SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) { + tf_attr |= MT_EXECUTE; + } else { + tf_attr |= MT_EXECUTE_NEVER; + } + + return tf_attr; +} + +/* + * This function converts attributes from the Trusted Firmware format into the + * SMC interface format. + */ +static unsigned int smc_mmap_to_smc_attr(unsigned int attr) +{ + unsigned int smc_attr = 0U; + + unsigned int data_access; + + if ((attr & MT_USER) == 0) { + /* No access from EL0. */ + data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS; + } else { + if ((attr & MT_RW) != 0) { + assert(MT_TYPE(attr) != MT_DEVICE); + data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW; + } else { + data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO; + } + } + + smc_attr |= (data_access & MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + << MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; + + if ((attr & MT_EXECUTE_NEVER) != 0U) { + smc_attr |= MM_SP_MEMORY_ATTRIBUTES_NON_EXEC; + } + + return smc_attr; +} + +int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx, + uintptr_t base_va) +{ + uint32_t attributes; + + spin_lock(&mem_attr_smc_lock); + + int rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, + base_va, &attributes); + + spin_unlock(&mem_attr_smc_lock); + + /* Convert error codes of xlat_get_mem_attributes_ctx() into SPM. */ + assert((rc == 0) || (rc == -EINVAL)); + + if (rc == 0) { + return (int32_t) smc_mmap_to_smc_attr(attributes); + } else { + return SPM_MM_INVALID_PARAMETER; + } +} + +int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx, + u_register_t page_address, + u_register_t pages_count, + u_register_t smc_attributes) +{ + uintptr_t base_va = (uintptr_t) page_address; + size_t size = (size_t) (pages_count * PAGE_SIZE); + uint32_t attributes = (uint32_t) smc_attributes; + + INFO(" Start address : 0x%lx\n", base_va); + INFO(" Number of pages: %i (%zi bytes)\n", (int) pages_count, size); + INFO(" Attributes : 0x%x\n", attributes); + + spin_lock(&mem_attr_smc_lock); + + int ret = xlat_change_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, + base_va, size, + smc_attr_to_mmap_attr(attributes)); + + spin_unlock(&mem_attr_smc_lock); + + /* Convert error codes of xlat_change_mem_attributes_ctx() into SPM. */ + assert((ret == 0) || (ret == -EINVAL)); + + return (ret == 0) ? SPM_MM_SUCCESS : SPM_MM_INVALID_PARAMETER; +} diff --git a/arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S b/arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S new file mode 100644 index 0000000..d7bffca --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "../spmd_private.h" + + .global spmd_spm_core_enter + .global spmd_spm_core_exit + + /* --------------------------------------------------------------------- + * This function is called with SP_EL0 as stack. Here we stash our EL3 + * callee-saved registers on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where the address of the C + * runtime context is to be saved. + * --------------------------------------------------------------------- + */ +func spmd_spm_core_enter + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #SPMD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #SPMD_C_RT_CTX_X19] + stp x21, x22, [sp, #SPMD_C_RT_CTX_X21] + stp x23, x24, [sp, #SPMD_C_RT_CTX_X23] + stp x25, x26, [sp, #SPMD_C_RT_CTX_X25] + stp x27, x28, [sp, #SPMD_C_RT_CTX_X27] + stp x29, x30, [sp, #SPMD_C_RT_CTX_X29] + + /* --------------------------------------------------------------------- + * Everything is setup now. el3_exit() will use the secure context to + * restore to the general purpose and EL3 system registers to ERET + * into the secure payload. + * --------------------------------------------------------------------- + */ + b el3_exit +endfunc spmd_spm_core_enter + + /* --------------------------------------------------------------------- + * This function is called with 'x0' pointing to a C runtime context. + * It restores the saved registers and jumps to that runtime with 'x0' + * as the new SP register. This destroys the C runtime context that had + * been built on the stack below the saved context by the caller. Later + * the second parameter 'x1' is passed as a return value to the caller. + * --------------------------------------------------------------------- + */ +func spmd_spm_core_exit + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(SPMD_C_RT_CTX_X19 - SPMD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(SPMD_C_RT_CTX_X21 - SPMD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(SPMD_C_RT_CTX_X23 - SPMD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(SPMD_C_RT_CTX_X25 - SPMD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(SPMD_C_RT_CTX_X27 - SPMD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(SPMD_C_RT_CTX_X29 - SPMD_C_RT_CTX_SIZE)] + + /* --------------------------------------------------------------------- + * This should take us back to the instruction after the call to the + * last spm_secure_partition_enter().* Place the second parameter to x0 + * so that the caller will see it as a return value from the original + * entry call. + * --------------------------------------------------------------------- + */ + mov x0, x1 + ret +endfunc spmd_spm_core_exit diff --git a/arm-trusted-firmware/services/std_svc/spmd/spmd.mk b/arm-trusted-firmware/services/std_svc/spmd/spmd.mk new file mode 100644 index 0000000..8efbdc8 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/spmd.mk @@ -0,0 +1,26 @@ +# +# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH},aarch64) + $(error "Error: SPMD is only supported on aarch64.") +endif + +ifeq (${ENABLE_SME_FOR_NS},1) + $(error "Error: SPMD is not compatible with ENABLE_SME_FOR_NS") +endif + +SPMD_SOURCES += $(addprefix services/std_svc/spmd/, \ + ${ARCH}/spmd_helpers.S \ + spmd_pm.c \ + spmd_main.c) + +# Let the top-level Makefile know that we intend to include a BL32 image +NEED_BL32 := yes + +# Enable dynamic memory mapping +# The SPMD component maps the SPMC DTB within BL31 virtual space. +PLAT_XLAT_TABLES_DYNAMIC := 1 +$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) diff --git a/arm-trusted-firmware/services/std_svc/spmd/spmd_main.c b/arm-trusted-firmware/services/std_svc/spmd/spmd_main.c new file mode 100644 index 0000000..b767396 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/spmd_main.c @@ -0,0 +1,839 @@ +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2022, NVIDIA 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 "spmd_private.h" + +/******************************************************************************* + * SPM Core context information. + ******************************************************************************/ +static spmd_spm_core_context_t spm_core_context[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * SPM Core attribute information read from its manifest. + ******************************************************************************/ +static spmc_manifest_attribute_t spmc_attrs; + +/******************************************************************************* + * SPM Core entry point information. Discovered on the primary core and reused + * on secondary cores. + ******************************************************************************/ +static entry_point_info_t *spmc_ep_info; + +/******************************************************************************* + * SPM Core context on CPU based on mpidr. + ******************************************************************************/ +spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr) +{ + int core_idx = plat_core_pos_by_mpidr(mpidr); + + if (core_idx < 0) { + ERROR("Invalid mpidr: %" PRIx64 ", returned ID: %d\n", mpidr, core_idx); + panic(); + } + + return &spm_core_context[core_idx]; +} + +/******************************************************************************* + * SPM Core context on current CPU get helper. + ******************************************************************************/ +spmd_spm_core_context_t *spmd_get_context(void) +{ + return spmd_get_context_by_mpidr(read_mpidr()); +} + +/******************************************************************************* + * SPM Core ID getter. + ******************************************************************************/ +uint16_t spmd_spmc_id_get(void) +{ + return spmc_attrs.spmc_id; +} + +/******************************************************************************* + * Static function declaration. + ******************************************************************************/ +static int32_t spmd_init(void); +static int spmd_spmc_init(void *pm_addr); +static uint64_t spmd_ffa_error_return(void *handle, + int error_code); +static uint64_t spmd_smc_forward(uint32_t smc_fid, + bool secure_origin, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *handle); + +/****************************************************************************** + * Builds an SPMD to SPMC direct message request. + *****************************************************************************/ +void spmd_build_spmc_message(gp_regs_t *gpregs, uint8_t target_func, + unsigned long long message) +{ + write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32); + write_ctx_reg(gpregs, CTX_GPREG_X1, + (SPMD_DIRECT_MSG_ENDPOINT_ID << FFA_DIRECT_MSG_SOURCE_SHIFT) | + spmd_spmc_id_get()); + write_ctx_reg(gpregs, CTX_GPREG_X2, BIT(31) | target_func); + write_ctx_reg(gpregs, CTX_GPREG_X3, message); +} + + +/******************************************************************************* + * This function takes an SPMC context pointer and performs a synchronous + * SPMC entry. + ******************************************************************************/ +uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *spmc_ctx) +{ + uint64_t rc; + + assert(spmc_ctx != NULL); + + cm_set_context(&(spmc_ctx->cpu_ctx), SECURE); + + /* Restore the context assigned above */ +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_restore(SECURE); +#else + cm_el1_sysregs_context_restore(SECURE); +#endif + cm_set_next_eret_context(SECURE); + + /* Enter SPMC */ + rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx); + + /* Save secure state */ +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_save(SECURE); +#else + cm_el1_sysregs_context_save(SECURE); +#endif + + return rc; +} + +/******************************************************************************* + * This function returns to the place where spmd_spm_core_sync_entry() was + * called originally. + ******************************************************************************/ +__dead2 void spmd_spm_core_sync_exit(uint64_t rc) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + + /* Get current CPU context from SPMC context */ + assert(cm_get_context(SECURE) == &(ctx->cpu_ctx)); + + /* + * The SPMD must have initiated the original request through a + * synchronous entry into SPMC. Jump back to the original C runtime + * context with the value of rc in x0; + */ + spmd_spm_core_exit(ctx->c_rt_ctx, rc); + + panic(); +} + +/******************************************************************************* + * Jump to the SPM Core for the first time. + ******************************************************************************/ +static int32_t spmd_init(void) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + uint64_t rc; + + VERBOSE("SPM Core init start.\n"); + + /* Primary boot core enters the SPMC for initialization. */ + ctx->state = SPMC_STATE_ON_PENDING; + + rc = spmd_spm_core_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("SPMC initialisation failed 0x%" PRIx64 "\n", rc); + return 0; + } + + ctx->state = SPMC_STATE_ON; + + VERBOSE("SPM Core init end.\n"); + + return 1; +} + +/******************************************************************************* + * spmd_secure_interrupt_handler + * Enter the SPMC for further handling of the secure interrupt by the SPMC + * itself or a Secure Partition. + ******************************************************************************/ +static uint64_t spmd_secure_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); + unsigned int linear_id = plat_my_core_pos(); + int64_t rc; + + /* Sanity check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering SPMC */ + cm_el1_sysregs_context_save(NON_SECURE); +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_save(NON_SECURE); +#endif + + /* Convey the event to the SPMC through the FFA_INTERRUPT interface. */ + write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_INTERRUPT); + write_ctx_reg(gpregs, CTX_GPREG_X1, 0); + write_ctx_reg(gpregs, CTX_GPREG_X2, 0); + write_ctx_reg(gpregs, CTX_GPREG_X3, 0); + write_ctx_reg(gpregs, CTX_GPREG_X4, 0); + write_ctx_reg(gpregs, CTX_GPREG_X5, 0); + write_ctx_reg(gpregs, CTX_GPREG_X6, 0); + write_ctx_reg(gpregs, CTX_GPREG_X7, 0); + + /* Mark current core as handling a secure interrupt. */ + ctx->secure_interrupt_ongoing = true; + + rc = spmd_spm_core_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("%s failed (%" PRId64 ") on CPU%u\n", __func__, rc, linear_id); + } + + ctx->secure_interrupt_ongoing = false; + + cm_el1_sysregs_context_restore(NON_SECURE); +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_restore(NON_SECURE); +#endif + cm_set_next_eret_context(NON_SECURE); + + SMC_RET0(&ctx->cpu_ctx); +} + +/******************************************************************************* + * Loads SPMC manifest and inits SPMC. + ******************************************************************************/ +static int spmd_spmc_init(void *pm_addr) +{ + cpu_context_t *cpu_ctx; + unsigned int core_id; + uint32_t ep_attr, flags; + int rc; + + /* Load the SPM Core manifest */ + rc = plat_spm_core_manifest_load(&spmc_attrs, pm_addr); + if (rc != 0) { + WARN("No or invalid SPM Core manifest image provided by BL2\n"); + return rc; + } + + /* + * Ensure that the SPM Core version is compatible with the SPM + * Dispatcher version. + */ + if ((spmc_attrs.major_version != FFA_VERSION_MAJOR) || + (spmc_attrs.minor_version > FFA_VERSION_MINOR)) { + WARN("Unsupported FFA version (%u.%u)\n", + spmc_attrs.major_version, spmc_attrs.minor_version); + return -EINVAL; + } + + VERBOSE("FFA version (%u.%u)\n", spmc_attrs.major_version, + spmc_attrs.minor_version); + + VERBOSE("SPM Core run time EL%x.\n", + SPMD_SPM_AT_SEL2 ? MODE_EL2 : MODE_EL1); + + /* Validate the SPMC ID, Ensure high bit is set */ + if (((spmc_attrs.spmc_id >> SPMC_SECURE_ID_SHIFT) & + SPMC_SECURE_ID_MASK) == 0U) { + WARN("Invalid ID (0x%x) for SPMC.\n", spmc_attrs.spmc_id); + return -EINVAL; + } + + /* Validate the SPM Core execution state */ + if ((spmc_attrs.exec_state != MODE_RW_64) && + (spmc_attrs.exec_state != MODE_RW_32)) { + WARN("Unsupported %s%x.\n", "SPM Core execution state 0x", + spmc_attrs.exec_state); + return -EINVAL; + } + + VERBOSE("%s%x.\n", "SPM Core execution state 0x", + spmc_attrs.exec_state); + +#if SPMD_SPM_AT_SEL2 + /* Ensure manifest has not requested AArch32 state in S-EL2 */ + if (spmc_attrs.exec_state == MODE_RW_32) { + WARN("AArch32 state at S-EL2 is not supported.\n"); + return -EINVAL; + } + + /* + * Check if S-EL2 is supported on this system if S-EL2 + * is required for SPM + */ + if (!is_armv8_4_sel2_present()) { + WARN("SPM Core run time S-EL2 is not supported.\n"); + return -EINVAL; + } +#endif /* SPMD_SPM_AT_SEL2 */ + + /* Initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0ULL) { + ep_attr |= EP_EE_BIG; + } + + SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr); + + /* + * Populate SPSR for SPM Core based upon validated parameters from the + * manifest. + */ + if (spmc_attrs.exec_state == MODE_RW_32) { + spmc_ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DAIF_FIQ_BIT | + DAIF_IRQ_BIT | + DAIF_ABT_BIT); + } else { + +#if SPMD_SPM_AT_SEL2 + static const uint32_t runtime_el = MODE_EL2; +#else + static const uint32_t runtime_el = MODE_EL1; +#endif + spmc_ep_info->spsr = SPSR_64(runtime_el, + MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } + + /* Set an initial SPMC context state for all cores. */ + for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) { + spm_core_context[core_id].state = SPMC_STATE_OFF; + + /* Setup an initial cpu context for the SPMC. */ + cpu_ctx = &spm_core_context[core_id].cpu_ctx; + cm_setup_context(cpu_ctx, spmc_ep_info); + + /* + * Pass the core linear ID to the SPMC through x4. + * (TF-A implementation defined behavior helping + * a legacy TOS migration to adopt FF-A). + */ + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X4, core_id); + } + + /* Register power management hooks with PSCI */ + psci_register_spd_pm_hook(&spmd_pm); + + /* Register init function for deferred init. */ + bl31_register_bl32_init(&spmd_init); + + INFO("SPM Core setup done.\n"); + + /* + * Register an interrupt handler routing secure interrupts to SPMD + * while the NWd is running. + */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + spmd_secure_interrupt_handler, + flags); + if (rc != 0) { + panic(); + } + + return 0; +} + +/******************************************************************************* + * Initialize context of SPM Core. + ******************************************************************************/ +int spmd_setup(void) +{ + void *spmc_manifest; + int rc; + + spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (spmc_ep_info == NULL) { + WARN("No SPM Core image provided by BL2 boot loader.\n"); + return -EINVAL; + } + + /* Under no circumstances will this parameter be 0 */ + assert(spmc_ep_info->pc != 0ULL); + + /* + * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will + * be used as a manifest for the SPM Core at the next lower EL/mode. + */ + spmc_manifest = (void *)spmc_ep_info->args.arg0; + if (spmc_manifest == NULL) { + ERROR("Invalid or absent SPM Core manifest.\n"); + return -EINVAL; + } + + /* Load manifest, init SPMC */ + rc = spmd_spmc_init(spmc_manifest); + if (rc != 0) { + WARN("Booting device without SPM initialization.\n"); + } + + return rc; +} + +/******************************************************************************* + * Forward SMC to the other security state + ******************************************************************************/ +static uint64_t spmd_smc_forward(uint32_t smc_fid, + bool secure_origin, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *handle) +{ + unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE; + unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE; + + /* Save incoming security state */ +#if SPMD_SPM_AT_SEL2 + if (secure_state_in == NON_SECURE) { + cm_el1_sysregs_context_save(secure_state_in); + } + cm_el2_sysregs_context_save(secure_state_in); +#else + cm_el1_sysregs_context_save(secure_state_in); +#endif + + /* Restore outgoing security state */ +#if SPMD_SPM_AT_SEL2 + if (secure_state_out == NON_SECURE) { + cm_el1_sysregs_context_restore(secure_state_out); + } + cm_el2_sysregs_context_restore(secure_state_out); +#else + cm_el1_sysregs_context_restore(secure_state_out); +#endif + cm_set_next_eret_context(secure_state_out); + + SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); +} + +/******************************************************************************* + * Return FFA_ERROR with specified error code + ******************************************************************************/ +static uint64_t spmd_ffa_error_return(void *handle, int error_code) +{ + SMC_RET8(handle, (uint32_t) FFA_ERROR, + FFA_TARGET_INFO_MBZ, (uint32_t)error_code, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +/******************************************************************************* + * spmd_check_address_in_binary_image + ******************************************************************************/ +bool spmd_check_address_in_binary_image(uint64_t address) +{ + assert(!check_uptr_overflow(spmc_attrs.load_address, spmc_attrs.binary_size)); + + return ((address >= spmc_attrs.load_address) && + (address < (spmc_attrs.load_address + spmc_attrs.binary_size))); +} + +/****************************************************************************** + * spmd_is_spmc_message + *****************************************************************************/ +static bool spmd_is_spmc_message(unsigned int ep) +{ + return ((ffa_endpoint_destination(ep) == SPMD_DIRECT_MSG_ENDPOINT_ID) + && (ffa_endpoint_source(ep) == spmc_attrs.spmc_id)); +} + +/****************************************************************************** + * spmd_handle_spmc_message + *****************************************************************************/ +static int spmd_handle_spmc_message(unsigned long long msg, + unsigned long long parm1, unsigned long long parm2, + unsigned long long parm3, unsigned long long parm4) +{ + VERBOSE("%s %llx %llx %llx %llx %llx\n", __func__, + msg, parm1, parm2, parm3, parm4); + + return -EINVAL; +} + +/******************************************************************************* + * This function handles all SMCs in the range reserved for FFA. Each call is + * either forwarded to the other security state or handled by the SPM dispatcher + ******************************************************************************/ +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) +{ + unsigned int linear_id = plat_my_core_pos(); + spmd_spm_core_context_t *ctx = spmd_get_context(); + bool secure_origin; + int32_t ret; + uint32_t input_version; + + /* Return error if SPMC init failed */ + if ((ctx->state == SPMC_STATE_RESET) || (ctx->state == SPMC_STATE_OFF)) { + WARN("SPM: SPMC not initialized\n"); + return spmd_ffa_error_return(handle, FFA_ERROR_DENIED); + } + + /* Determine which security state this SMC originated from */ + secure_origin = is_caller_secure(flags); + + VERBOSE("SPM(%u): 0x%x 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 + " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 "\n", + linear_id, smc_fid, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); + + switch (smc_fid) { + case FFA_ERROR: + /* + * Check if this is the first invocation of this interface on + * this CPU. If so, then indicate that the SPM Core initialised + * unsuccessfully. + */ + if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) { + spmd_spm_core_sync_exit(x2); + } + + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + break; /* not reached */ + + case FFA_VERSION: + input_version = (uint32_t)(0xFFFFFFFF & x1); + /* + * If caller is secure and SPMC was initialized, + * return FFA_VERSION of SPMD. + * If caller is non secure and SPMC was initialized, + * return SPMC's version. + * Sanity check to "input_version". + */ + if ((input_version & FFA_VERSION_BIT31_MASK) || + (ctx->state == SPMC_STATE_RESET)) { + ret = FFA_ERROR_NOT_SUPPORTED; + } else if (!secure_origin) { + gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); + uint64_t rc; + + if (spmc_attrs.major_version == 1 && + spmc_attrs.minor_version == 0) { + ret = MAKE_FFA_VERSION(spmc_attrs.major_version, + spmc_attrs.minor_version); + SMC_RET8(handle, (uint32_t)ret, + FFA_TARGET_INFO_MBZ, + FFA_TARGET_INFO_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + break; + } + /* Save non-secure system registers context */ + cm_el1_sysregs_context_save(NON_SECURE); +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_save(NON_SECURE); +#endif + + /* + * The incoming request has FFA_VERSION as X0 smc_fid + * and requested version in x1. Prepare a direct request + * from SPMD to SPMC with FFA_VERSION framework function + * identifier in X2 and requested version in X3. + */ + spmd_build_spmc_message(gpregs, + SPMD_FWK_MSG_FFA_VERSION_REQ, + input_version); + + rc = spmd_spm_core_sync_entry(ctx); + + if ((rc != 0ULL) || + (SMC_GET_GP(gpregs, CTX_GPREG_X0) != + FFA_MSG_SEND_DIRECT_RESP_SMC32) || + (SMC_GET_GP(gpregs, CTX_GPREG_X2) != + (SPMD_FWK_MSG_BIT | + SPMD_FWK_MSG_FFA_VERSION_RESP))) { + ERROR("Failed to forward FFA_VERSION\n"); + ret = FFA_ERROR_NOT_SUPPORTED; + } else { + ret = SMC_GET_GP(gpregs, CTX_GPREG_X3); + } + + /* + * Return here after SPMC has handled FFA_VERSION. + * The returned SPMC version is held in X3. + * Forward this version in X0 to the non-secure caller. + */ + return spmd_smc_forward(ret, true, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, gpregs); + } else { + ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, + FFA_VERSION_MINOR); + } + + SMC_RET8(handle, (uint32_t)ret, FFA_TARGET_INFO_MBZ, + FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); + break; /* not reached */ + + case FFA_FEATURES: + /* + * This is an optional interface. Do the minimal checks and + * forward to SPM Core which will handle it if implemented. + */ + + /* Forward SMC from Normal world to the SPM Core */ + if (!secure_origin) { + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + } + + /* + * Return success if call was from secure world i.e. all + * FFA functions are supported. This is essentially a + * nop. + */ + SMC_RET8(handle, FFA_SUCCESS_SMC32, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); + + break; /* not reached */ + + case FFA_ID_GET: + /* + * Returns the ID of the calling FFA component. + */ + if (!secure_origin) { + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, FFA_NS_ENDPOINT_ID, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } + + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + + break; /* not reached */ + + case FFA_SECONDARY_EP_REGISTER_SMC64: + if (secure_origin) { + ret = spmd_pm_secondary_ep_register(x1); + + if (ret < 0) { + SMC_RET8(handle, FFA_ERROR_SMC64, + FFA_TARGET_INFO_MBZ, ret, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } else { + SMC_RET8(handle, FFA_SUCCESS_SMC64, + FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } + } + + return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); + break; /* Not reached */ + + case FFA_SPM_ID_GET: + if (MAKE_FFA_VERSION(1, 1) > FFA_VERSION_COMPILED) { + return spmd_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + /* + * Returns the ID of the SPMC or SPMD depending on the FF-A + * instance where this function is invoked + */ + if (!secure_origin) { + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, SPMD_DIRECT_MSG_ENDPOINT_ID, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + + break; /* not reached */ + + case FFA_MSG_SEND_DIRECT_REQ_SMC32: + if (secure_origin && spmd_is_spmc_message(x1)) { + ret = spmd_handle_spmc_message(x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); + + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, ret, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } else { + /* Forward direct message to the other world */ + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + } + break; /* Not reached */ + + case FFA_MSG_SEND_DIRECT_RESP_SMC32: + if (secure_origin && spmd_is_spmc_message(x1)) { + spmd_spm_core_sync_exit(0ULL); + } else { + /* Forward direct message to the other world */ + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + } + break; /* Not reached */ + + case FFA_RX_RELEASE: + case FFA_RXTX_MAP_SMC32: + case FFA_RXTX_MAP_SMC64: + case FFA_RXTX_UNMAP: + case FFA_PARTITION_INFO_GET: +#if MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED + case FFA_NOTIFICATION_BITMAP_CREATE: + case FFA_NOTIFICATION_BITMAP_DESTROY: + case FFA_NOTIFICATION_BIND: + case FFA_NOTIFICATION_UNBIND: + case FFA_NOTIFICATION_SET: + case FFA_NOTIFICATION_GET: + case FFA_NOTIFICATION_INFO_GET: + case FFA_NOTIFICATION_INFO_GET_SMC64: + case FFA_MSG_SEND2: +#endif + case FFA_MSG_RUN: + /* + * Above calls should be invoked only by the Normal world and + * must not be forwarded from Secure world to Normal world. + */ + if (secure_origin) { + return spmd_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + + /* Fall through to forward the call to the other world */ + case FFA_MSG_SEND: + case FFA_MSG_SEND_DIRECT_REQ_SMC64: + case FFA_MSG_SEND_DIRECT_RESP_SMC64: + case FFA_MEM_DONATE_SMC32: + case FFA_MEM_DONATE_SMC64: + case FFA_MEM_LEND_SMC32: + case FFA_MEM_LEND_SMC64: + case FFA_MEM_SHARE_SMC32: + case FFA_MEM_SHARE_SMC64: + case FFA_MEM_RETRIEVE_REQ_SMC32: + case FFA_MEM_RETRIEVE_REQ_SMC64: + case FFA_MEM_RETRIEVE_RESP: + case FFA_MEM_RELINQUISH: + case FFA_MEM_RECLAIM: + case FFA_SUCCESS_SMC32: + case FFA_SUCCESS_SMC64: + /* + * TODO: Assume that no requests originate from EL3 at the + * moment. This will change if a SP service is required in + * response to secure interrupts targeted to EL3. Until then + * simply forward the call to the Normal world. + */ + + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + break; /* not reached */ + + case FFA_MSG_WAIT: + /* + * Check if this is the first invocation of this interface on + * this CPU from the Secure world. If so, then indicate that the + * SPM Core initialised successfully. + */ + if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) { + spmd_spm_core_sync_exit(0ULL); + } + + /* Fall through to forward the call to the other world */ + case FFA_INTERRUPT: + case FFA_MSG_YIELD: + /* This interface must be invoked only by the Secure world */ + if (!secure_origin) { + return spmd_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + break; /* not reached */ + + case FFA_NORMAL_WORLD_RESUME: + if (secure_origin && ctx->secure_interrupt_ongoing) { + spmd_spm_core_sync_exit(0ULL); + } else { + return spmd_ffa_error_return(handle, FFA_ERROR_DENIED); + } + break; /* Not reached */ + + default: + WARN("SPM: Unsupported call 0x%08x\n", smc_fid); + return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); + } +} diff --git a/arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c b/arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c new file mode 100644 index 0000000..b719161 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include "spmd_private.h" + +static struct { + bool secondary_ep_locked; + uintptr_t secondary_ep; + spinlock_t lock; +} g_spmd_pm; + +/******************************************************************************* + * spmd_pm_secondary_ep_register + ******************************************************************************/ +int spmd_pm_secondary_ep_register(uintptr_t entry_point) +{ + int ret = FFA_ERROR_INVALID_PARAMETER; + + spin_lock(&g_spmd_pm.lock); + + if (g_spmd_pm.secondary_ep_locked == true) { + goto out; + } + + /* + * Check entry_point address is a PA within + * load_address <= entry_point < load_address + binary_size + */ + if (!spmd_check_address_in_binary_image(entry_point)) { + ERROR("%s entry point is not within image boundaries\n", + __func__); + goto out; + } + + g_spmd_pm.secondary_ep = entry_point; + g_spmd_pm.secondary_ep_locked = true; + + VERBOSE("%s %lx\n", __func__, entry_point); + + ret = 0; + +out: + spin_unlock(&g_spmd_pm.lock); + + return ret; +} + +/******************************************************************************* + * This CPU has been turned on. Enter SPMC to initialise S-EL1 or S-EL2. As part + * of the SPMC initialization path, they will initialize any SPs that they + * manage. Entry into SPMC is done after initialising minimal architectural + * state that guarantees safe execution. + ******************************************************************************/ +static void spmd_cpu_on_finish_handler(u_register_t unused) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + unsigned int linear_id = plat_my_core_pos(); + el3_state_t *el3_state; + uintptr_t entry_point; + uint64_t rc; + + assert(ctx != NULL); + assert(ctx->state != SPMC_STATE_ON); + + spin_lock(&g_spmd_pm.lock); + + /* + * Leave the possibility that the SPMC does not call + * FFA_SECONDARY_EP_REGISTER in which case re-use the + * primary core address for booting secondary cores. + */ + if (g_spmd_pm.secondary_ep_locked == true) { + /* + * The CPU context has already been initialized at boot time + * (in spmd_spmc_init by a call to cm_setup_context). Adjust + * below the target core entry point based on the address + * passed to by FFA_SECONDARY_EP_REGISTER. + */ + entry_point = g_spmd_pm.secondary_ep; + el3_state = get_el3state_ctx(&ctx->cpu_ctx); + write_ctx_reg(el3_state, CTX_ELR_EL3, entry_point); + } + + spin_unlock(&g_spmd_pm.lock); + + /* Mark CPU as initiating ON operation. */ + ctx->state = SPMC_STATE_ON_PENDING; + + rc = spmd_spm_core_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("%s failed (%" PRIu64 ") on CPU%u\n", __func__, rc, + linear_id); + ctx->state = SPMC_STATE_OFF; + return; + } + + ctx->state = SPMC_STATE_ON; + + VERBOSE("CPU %u on!\n", linear_id); +} + +/******************************************************************************* + * spmd_cpu_off_handler + ******************************************************************************/ +static int32_t spmd_cpu_off_handler(u_register_t unused) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + unsigned int linear_id = plat_my_core_pos(); + int64_t rc; + + assert(ctx != NULL); + assert(ctx->state != SPMC_STATE_OFF); + + /* Build an SPMD to SPMC direct message request. */ + spmd_build_spmc_message(get_gpregs_ctx(&ctx->cpu_ctx), + SPMD_FWK_MSG_PSCI, PSCI_CPU_OFF); + + rc = spmd_spm_core_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("%s failed (%" PRIu64 ") on CPU%u\n", __func__, rc, linear_id); + } + + /* Expect a direct message response from the SPMC. */ + u_register_t ffa_resp_func = read_ctx_reg(get_gpregs_ctx(&ctx->cpu_ctx), + CTX_GPREG_X0); + if (ffa_resp_func != FFA_MSG_SEND_DIRECT_RESP_SMC32) { + ERROR("%s invalid SPMC response (%lx).\n", + __func__, ffa_resp_func); + return -EINVAL; + } + + ctx->state = SPMC_STATE_OFF; + + VERBOSE("CPU %u off!\n", linear_id); + + return 0; +} + +/******************************************************************************* + * Structure populated by the SPM Dispatcher to perform any bookkeeping before + * PSCI executes a power mgmt. operation. + ******************************************************************************/ +const spd_pm_ops_t spmd_pm = { + .svc_on_finish = spmd_cpu_on_finish_handler, + .svc_off = spmd_cpu_off_handler +}; diff --git a/arm-trusted-firmware/services/std_svc/spmd/spmd_private.h b/arm-trusted-firmware/services/std_svc/spmd/spmd_private.h new file mode 100644 index 0000000..4cd6a74 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/spmd_private.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPMD_PRIVATE_H +#define SPMD_PRIVATE_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define SPMD_C_RT_CTX_X19 0x0 +#define SPMD_C_RT_CTX_X20 0x8 +#define SPMD_C_RT_CTX_X21 0x10 +#define SPMD_C_RT_CTX_X22 0x18 +#define SPMD_C_RT_CTX_X23 0x20 +#define SPMD_C_RT_CTX_X24 0x28 +#define SPMD_C_RT_CTX_X25 0x30 +#define SPMD_C_RT_CTX_X26 0x38 +#define SPMD_C_RT_CTX_X27 0x40 +#define SPMD_C_RT_CTX_X28 0x48 +#define SPMD_C_RT_CTX_X29 0x50 +#define SPMD_C_RT_CTX_X30 0x58 + +#define SPMD_C_RT_CTX_SIZE 0x60 +#define SPMD_C_RT_CTX_ENTRIES (SPMD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ +#include +#include +#include +#include + +typedef enum spmc_state { + SPMC_STATE_RESET = 0, + SPMC_STATE_OFF, + SPMC_STATE_ON_PENDING, + SPMC_STATE_ON +} spmc_state_t; + +/* + * Data structure used by the SPM dispatcher (SPMD) in EL3 to track context of + * the SPM core (SPMC) at the next lower EL. + */ +typedef struct spmd_spm_core_context { + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; + spmc_state_t state; + bool secure_interrupt_ongoing; +} spmd_spm_core_context_t; + +/* + * Reserve ID for NS physical FFA Endpoint. + */ +#define FFA_NS_ENDPOINT_ID U(0) + +/* Mask and shift to check valid secure FF-A Endpoint ID. */ +#define SPMC_SECURE_ID_MASK U(1) +#define SPMC_SECURE_ID_SHIFT U(15) + +#define SPMD_DIRECT_MSG_ENDPOINT_ID U(FFA_ENDPOINT_ID_MAX - 1) + +/* Define SPMD target function IDs for framework messages to the SPMC */ +#define SPMD_FWK_MSG_BIT BIT(31) +#define SPMD_FWK_MSG_PSCI U(0) +#define SPMD_FWK_MSG_FFA_VERSION_REQ U(0x8) +#define SPMD_FWK_MSG_FFA_VERSION_RESP U(0x9) + +/* Function to build SPMD to SPMC message */ +void spmd_build_spmc_message(gp_regs_t *gpregs, uint8_t target, + unsigned long long message); + +/* Functions used to enter/exit SPMC synchronously */ +uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *ctx); +__dead2 void spmd_spm_core_sync_exit(uint64_t rc); + +/* Assembly helpers */ +uint64_t spmd_spm_core_enter(uint64_t *c_rt_ctx); +void __dead2 spmd_spm_core_exit(uint64_t c_rt_ctx, uint64_t ret); + +/* SPMD SPD power management handlers */ +extern const spd_pm_ops_t spmd_pm; + +/* SPMC entry point information helper */ +entry_point_info_t *spmd_spmc_ep_info_get(void); + +/* SPMC ID getter */ +uint16_t spmd_spmc_id_get(void); + +/* SPMC context on CPU based on mpidr */ +spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr); + +/* SPMC context on current CPU get helper */ +spmd_spm_core_context_t *spmd_get_context(void); + +int spmd_pm_secondary_ep_register(uintptr_t entry_point); +bool spmd_check_address_in_binary_image(uint64_t address); + +#endif /* __ASSEMBLER__ */ + +#endif /* SPMD_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/std_svc_setup.c b/arm-trusted-firmware/services/std_svc/std_svc_setup.c new file mode 100644 index 0000000..9452c17 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/std_svc_setup.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2014-2022, 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 +#include +#include +#include + +/* Standard Service UUID */ +static uuid_t arm_svc_uid = { + {0x5b, 0x90, 0x8d, 0x10}, + {0x63, 0xf8}, + {0xe8, 0x47}, + 0xae, 0x2d, + {0xc0, 0xfb, 0x56, 0x41, 0xf6, 0xe2} +}; + +/* Setup Standard Services */ +static int32_t std_svc_setup(void) +{ + uintptr_t svc_arg; + int ret = 0; + + svc_arg = get_arm_std_svc_args(PSCI_FID_MASK); + assert(svc_arg); + + /* + * PSCI is one of the specifications implemented as a Standard Service. + * The `psci_setup()` also does EL3 architectural setup. + */ + if (psci_setup((const psci_lib_args_t *)svc_arg) != PSCI_E_SUCCESS) { + ret = 1; + } + +#if SPM_MM + if (spm_mm_setup() != 0) { + ret = 1; + } +#endif + +#if defined(SPD_spmd) + if (spmd_setup() != 0) { + WARN("SPMD setup failed. Continuing boot.\n"); + } +#endif + +#if ENABLE_RME + if (rmmd_setup() != 0) { + ret = 1; + } +#endif + +#if SDEI_SUPPORT + /* SDEI initialisation */ + sdei_init(); +#endif + + trng_setup(); + + return ret; +} + +/* + * Top-level Standard Service SMC handler. This handler will in turn dispatch + * calls to PSCI SMC handler + */ +static uintptr_t std_svc_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) +{ + if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { + /* 32-bit SMC function, clear top parameter bits */ + + x1 &= UINT32_MAX; + x2 &= UINT32_MAX; + x3 &= UINT32_MAX; + x4 &= UINT32_MAX; + } + + /* + * Dispatch PSCI calls to PSCI SMC handler and return its return + * value + */ + if (is_psci_fid(smc_fid)) { + uint64_t ret; + +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Flush cache line so that even if CPU power down happens + * the timestamp update is reflected in memory. + */ + PMF_WRITE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_PSCI, + PMF_CACHE_MAINT, + get_cpu_data(cpu_data_pmf_ts[CPU_DATA_PMF_TS0_IDX])); +#endif + + ret = psci_smc_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_PSCI, + PMF_NO_CACHE_MAINT); +#endif + + SMC_RET1(handle, ret); + } + +#if SPM_MM + /* + * Dispatch SPM calls to SPM SMC handler and return its return + * value + */ + if (is_spm_mm_fid(smc_fid)) { + return spm_mm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif + +#if defined(SPD_spmd) + /* + * Dispatch FFA calls to the FFA SMC handler implemented by the SPM + * dispatcher and return its return value + */ + if (is_ffa_fid(smc_fid)) { + return spmd_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif + +#if SDEI_SUPPORT + if (is_sdei_fid(smc_fid)) { + return sdei_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } +#endif + +#if TRNG_SUPPORT + if (is_trng_fid(smc_fid)) { + return trng_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } +#endif +#if ENABLE_RME + + if (is_rmmd_el3_fid(smc_fid)) { + return rmmd_rmm_el3_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + + if (is_rmi_fid(smc_fid)) { + return rmmd_rmi_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif + +#if SMC_PCI_SUPPORT + if (is_pci_fid(smc_fid)) { + return pci_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } +#endif + + switch (smc_fid) { + case ARM_STD_SVC_CALL_COUNT: + /* + * Return the number of Standard Service Calls. PSCI is the only + * standard service implemented; so return number of PSCI calls + */ + SMC_RET1(handle, PSCI_NUM_CALLS); + + case ARM_STD_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, arm_svc_uid); + + case ARM_STD_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, STD_SVC_VERSION_MAJOR, STD_SVC_VERSION_MINOR); + + default: + VERBOSE("Unimplemented Standard Service Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register Standard Service Calls as runtime service */ +DECLARE_RT_SVC( + std_svc, + + OEN_STD_START, + OEN_STD_END, + SMC_TYPE_FAST, + std_svc_setup, + std_svc_smc_handler +); diff --git a/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c b/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c new file mode 100644 index 0000000..ac13b1d --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * # Entropy pool + * Note that the TRNG Firmware interface can request up to 192 bits of entropy + * in a single call or three 64bit words per call. We have 4 words in the pool + * so that when we have 1-63 bits in the pool, and we have a request for + * 192 bits of entropy, we don't have to throw out the leftover 1-63 bits of + * entropy. + */ +#define WORDS_IN_POOL (4) +static uint64_t entropy[WORDS_IN_POOL]; +/* index in bits of the first bit of usable entropy */ +static uint32_t entropy_bit_index; +/* then number of valid bits in the entropy pool */ +static uint32_t entropy_bit_size; + +static spinlock_t trng_pool_lock; + +#define BITS_PER_WORD (sizeof(entropy[0]) * 8) +#define BITS_IN_POOL (WORDS_IN_POOL * BITS_PER_WORD) +#define ENTROPY_MIN_WORD (entropy_bit_index / BITS_PER_WORD) +#define ENTROPY_FREE_BIT (entropy_bit_size + entropy_bit_index) +#define _ENTROPY_FREE_WORD (ENTROPY_FREE_BIT / BITS_PER_WORD) +#define ENTROPY_FREE_INDEX (_ENTROPY_FREE_WORD % WORDS_IN_POOL) +/* ENTROPY_WORD_INDEX(0) includes leftover bits in the lower bits */ +#define ENTROPY_WORD_INDEX(i) ((ENTROPY_MIN_WORD + i) % WORDS_IN_POOL) + +/* + * Fill the entropy pool until we have at least as many bits as requested. + * Returns true after filling the pool, and false if the entropy source is out + * of entropy and the pool could not be filled. + * Assumes locks are taken. + */ +static bool trng_fill_entropy(uint32_t nbits) +{ + while (nbits > entropy_bit_size) { + bool valid = plat_get_entropy(&entropy[ENTROPY_FREE_INDEX]); + + if (valid) { + entropy_bit_size += BITS_PER_WORD; + assert(entropy_bit_size <= BITS_IN_POOL); + } else { + return false; + } + } + return true; +} + +/* + * Pack entropy into the out buffer, filling and taking locks as needed. + * Returns true on success, false on failure. + * + * Note: out must have enough space for nbits of entropy + */ +bool trng_pack_entropy(uint32_t nbits, uint64_t *out) +{ + bool success = true; + + spin_lock(&trng_pool_lock); + + if (!trng_fill_entropy(nbits)) { + success = false; + goto out; + } + + const unsigned int rshift = entropy_bit_index % BITS_PER_WORD; + const unsigned int lshift = BITS_PER_WORD - rshift; + const int to_fill = ((nbits + BITS_PER_WORD - 1) / BITS_PER_WORD); + int word_i; + + for (word_i = 0; word_i < to_fill; word_i++) { + /* + * Repack the entropy from the pool into the passed in out + * buffer. This takes the lower bits from the valid upper bits + * of word_i and the upper bits from the lower bits of + * (word_i + 1). + * + * I found the following diagram useful. note: `e` represents + * valid entropy, ` ` represents invalid bits (not entropy) and + * `x` represents valid entropy that must not end up in the + * packed word. + * + * |---------entropy pool----------| + * C var |--(word_i + 1)-|----word_i-----| + * bit idx |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| + * [x,x,e,e,e,e,e,e|e,e, , , , , , ] + * | [e,e,e,e,e,e,e,e] | + * | |--out[word_i]--| | + * lshift|---| |--rshift---| + * + * ==== Which is implemented as ==== + * + * |---------entropy pool----------| + * C var |--(word_i + 1)-|----word_i-----| + * bit idx |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| + * [x,x,e,e,e,e,e,e|e,e, , , , , , ] + * C expr << lshift >> rshift + * bit idx 5 4 3 2 1 0 7 6 + * [e,e,e,e,e,e,0,0|0,0,0,0,0,0,e,e] + * ==== bit-wise or ==== + * 5 4 3 2 1 0 7 6 + * [e,e,e,e,e,e,e,e] + */ + out[word_i] = 0; + out[word_i] |= entropy[ENTROPY_WORD_INDEX(word_i)] >> rshift; + + /* + * Note that a shift of 64 bits is treated as a shift of 0 bits. + * When the shift amount is the same as the BITS_PER_WORD, we + * don't want to include the next word of entropy, so we skip + * the `|=` operation. + */ + if (lshift != BITS_PER_WORD) { + out[word_i] |= entropy[ENTROPY_WORD_INDEX(word_i + 1)] + << lshift; + } + } + const uint64_t mask = ~0ULL >> (BITS_PER_WORD - (nbits % BITS_PER_WORD)); + + out[to_fill - 1] &= mask; + + entropy_bit_index = (entropy_bit_index + nbits) % BITS_IN_POOL; + entropy_bit_size -= nbits; + +out: + spin_unlock(&trng_pool_lock); + + return success; +} + +void trng_entropy_pool_setup(void) +{ + int i; + + for (i = 0; i < WORDS_IN_POOL; i++) { + entropy[i] = 0; + } + entropy_bit_index = 0; + entropy_bit_size = 0; +} diff --git a/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h b/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h new file mode 100644 index 0000000..fab2367 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRNG_ENTROPY_POOL_H +#define TRNG_ENTROPY_POOL_H + +#include +#include + +bool trng_pack_entropy(uint32_t nbits, uint64_t *out); +void trng_entropy_pool_setup(void); + +#endif /* TRNG_ENTROPY_POOL_H */ diff --git a/arm-trusted-firmware/services/std_svc/trng/trng_main.c b/arm-trusted-firmware/services/std_svc/trng/trng_main.c new file mode 100644 index 0000000..38aa649 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/trng/trng_main.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "trng_entropy_pool.h" + +static const uuid_t uuid_null; + +/* handle the RND call in SMC 32 bit mode */ +static uintptr_t trng_rnd32(uint32_t nbits, void *handle) +{ + uint32_t mask = ~0U; + uint64_t ent[2]; + + if (nbits == 0U || nbits > 96U) { + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + } + + if (!trng_pack_entropy(nbits, &ent[0])) { + SMC_RET1(handle, TRNG_E_NO_ENTROPY); + } + + if ((nbits % 32U) != 0U) { + mask >>= 32U - (nbits % 32U); + } + + switch ((nbits - 1U) / 32U) { + case 0: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask); + break; /* unreachable */ + case 1: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, (ent[0] >> 32) & mask, + ent[0] & 0xFFFFFFFF); + break; /* unreachable */ + case 2: + SMC_RET4(handle, TRNG_E_SUCCESS, ent[1] & mask, + (ent[0] >> 32) & 0xFFFFFFFF, ent[0] & 0xFFFFFFFF); + break; /* unreachable */ + default: + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + break; /* unreachable */ + } +} + +/* handle the RND call in SMC 64 bit mode */ +static uintptr_t trng_rnd64(uint32_t nbits, void *handle) +{ + uint64_t mask = ~0ULL; + uint64_t ent[3]; + + if (nbits == 0U || nbits > 192U) { + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + } + + if (!trng_pack_entropy(nbits, &ent[0])) { + SMC_RET1(handle, TRNG_E_NO_ENTROPY); + } + + /* Mask off higher bits if only part of register requested */ + if ((nbits % 64U) != 0U) { + mask >>= 64U - (nbits % 64U); + } + + switch ((nbits - 1U) / 64U) { + case 0: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask); + break; /* unreachable */ + case 1: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, ent[1] & mask, ent[0]); + break; /* unreachable */ + case 2: + SMC_RET4(handle, TRNG_E_SUCCESS, ent[2] & mask, ent[1], ent[0]); + break; /* unreachable */ + default: + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + break; /* unreachable */ + } +} + +void trng_setup(void) +{ + trng_entropy_pool_setup(); + plat_entropy_setup(); +} + +/* Predicate indicating that a function id is part of TRNG */ +bool is_trng_fid(uint32_t smc_fid) +{ + return ((smc_fid == ARM_TRNG_VERSION) || + (smc_fid == ARM_TRNG_FEATURES) || + (smc_fid == ARM_TRNG_GET_UUID) || + (smc_fid == ARM_TRNG_RND32) || + (smc_fid == ARM_TRNG_RND64)); +} + +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) +{ + if (!memcmp(&plat_trng_uuid, &uuid_null, sizeof(uuid_t))) { + SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED); + } + + switch (smc_fid) { + case ARM_TRNG_VERSION: + SMC_RET1(handle, MAKE_SMCCC_VERSION( + TRNG_VERSION_MAJOR, TRNG_VERSION_MINOR + )); + break; /* unreachable */ + case ARM_TRNG_FEATURES: + if (is_trng_fid((uint32_t)x1)) { + SMC_RET1(handle, TRNG_E_SUCCESS); + } else { + SMC_RET1(handle, TRNG_E_NOT_SUPPORTED); + } + break; /* unreachable */ + case ARM_TRNG_GET_UUID: + SMC_UUID_RET(handle, plat_trng_uuid); + break; /* unreachable */ + case ARM_TRNG_RND32: + return trng_rnd32((uint32_t)x1, handle); + case ARM_TRNG_RND64: + return trng_rnd64((uint32_t)x1, handle); + default: + WARN("Unimplemented TRNG Service Call: 0x%x\n", + smc_fid); + SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED); + break; /* unreachable */ + } +} diff --git a/arm-trusted-firmware/tools/amlogic/Makefile b/arm-trusted-firmware/tools/amlogic/Makefile new file mode 100644 index 0000000..1a1d1f8 --- /dev/null +++ b/arm-trusted-firmware/tools/amlogic/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2019 Remi Pommarel +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +PROJECT := doimage${BIN_EXT} +OBJECTS := doimage.o +V := 0 + +HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE + +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif + +ifeq (${V},0) + Q := @ +else + Q := +endif + +HOSTCC := gcc + +.PHONY: all clean distclean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} -o $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) + +distclean: clean diff --git a/arm-trusted-firmware/tools/amlogic/doimage.c b/arm-trusted-firmware/tools/amlogic/doimage.c new file mode 100644 index 0000000..b304038 --- /dev/null +++ b/arm-trusted-firmware/tools/amlogic/doimage.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2019, Remi Pommarel + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + +#define DEFAULT_PROGNAME "doimage" +#define PROGNAME(argc, argv) (((argc) >= 1) ? ((argv)[0]) : DEFAULT_PROGNAME) + +#define BL31_MAGIC 0x12348765 +#define BL31_LOADADDR 0x05100000 +#define BUFLEN 512 + +static inline void usage(char const *prog) +{ + fprintf(stderr, "Usage: %s \n", prog); +} + +static inline int fdwrite(int fd, uint8_t *data, size_t len) +{ + ssize_t nr; + size_t l; + int ret = -1; + + for (l = 0; l < len; l += nr) { + nr = write(fd, data + l, len - l); + if (nr < 0) { + perror("Cannot write to bl31.img"); + goto out; + } + } + + ret = 0; +out: + return ret; +} + +int main(int argc, char **argv) +{ + int fin, fout, ret = -1; + ssize_t len; + uint32_t data; + uint8_t buf[BUFLEN]; + + if (argc != 3) { + usage(PROGNAME(argc, argv)); + goto out; + } + + fin = open(argv[1], O_RDONLY); + if (fin < 0) { + perror("Cannot open bl31.bin"); + goto out; + } + + fout = open(argv[2], O_WRONLY | O_CREAT, 0660); + if (fout < 0) { + perror("Cannot open bl31.img"); + goto closefin; + } + + data = htole32(BL31_MAGIC); + if (fdwrite(fout, (uint8_t *)&data, sizeof(data)) < 0) + goto closefout; + + lseek(fout, 8, SEEK_SET); + data = htole32(BL31_LOADADDR); + if (fdwrite(fout, (uint8_t *)&data, sizeof(data)) < 0) + goto closefout; + + lseek(fout, 0x200, SEEK_SET); + while ((len = read(fin, buf, sizeof(buf))) > 0) + if (fdwrite(fout, buf, len) < 0) + goto closefout; + if (len < 0) { + perror("Cannot read bl31.bin"); + goto closefout; + } + + ret = 0; + +closefout: + close(fout); +closefin: + close(fin); +out: + return ret; +} diff --git a/arm-trusted-firmware/tools/cert_create/Makefile b/arm-trusted-firmware/tools/cert_create/Makefile new file mode 100644 index 0000000..77d2007 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/cert.h b/arm-trusted-firmware/tools/cert_create/include/cert.h new file mode 100644 index 0000000..e63b474 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/cmd_opt.h b/arm-trusted-firmware/tools/cert_create/include/cmd_opt.h new file mode 100644 index 0000000..10df00e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/debug.h b/arm-trusted-firmware/tools/cert_create/include/debug.h new file mode 100644 index 0000000..ee8f1f5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h b/arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h new file mode 100644 index 0000000..3e50c89 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/ext.h b/arm-trusted-firmware/tools/cert_create/include/ext.h new file mode 100644 index 0000000..e900a6d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/key.h b/arm-trusted-firmware/tools/cert_create/include/key.h new file mode 100644 index 0000000..128e7f7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/sha.h b/arm-trusted-firmware/tools/cert_create/include/sha.h new file mode 100644 index 0000000..4c55f37 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h new file mode 100644 index 0000000..e5fa3a2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h new file mode 100644 index 0000000..692b2d4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h new file mode 100644 index 0000000..47ad1de --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/cert.c b/arm-trusted-firmware/tools/cert_create/src/cert.c new file mode 100644 index 0000000..4b35d73 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/cmd_opt.c b/arm-trusted-firmware/tools/cert_create/src/cmd_opt.c new file mode 100644 index 0000000..64180d1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c b/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c new file mode 100644 index 0000000..4dd4cf0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.mk b/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.mk new file mode 100644 index 0000000..a572484 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/ext.c b/arm-trusted-firmware/tools/cert_create/src/ext.c new file mode 100644 index 0000000..2882123 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/key.c b/arm-trusted-firmware/tools/cert_create/src/key.c new file mode 100644 index 0000000..6435975 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/main.c b/arm-trusted-firmware/tools/cert_create/src/main.c new file mode 100644 index 0000000..b39378c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/sha.c b/arm-trusted-firmware/tools/cert_create/src/sha.c new file mode 100644 index 0000000..3d977fb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c new file mode 100644 index 0000000..f4fe63d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c new file mode 100644 index 0000000..60bafb4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c new file mode 100644 index 0000000..a81f0e4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/cert_create/src/tbbr/tbbr.mk b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbbr.mk new file mode 100644 index 0000000..ee82d31 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js b/arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js new file mode 100644 index 0000000..2a9d5b4 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* eslint-env es6 */ + +"use strict"; + +const Handlebars = require("handlebars"); +const Q = require("q"); +const _ = require("lodash"); + +const ccConventionalChangelog = require("conventional-changelog-conventionalcommits/conventional-changelog"); +const ccParserOpts = require("conventional-changelog-conventionalcommits/parser-opts"); +const ccRecommendedBumpOpts = require("conventional-changelog-conventionalcommits/conventional-recommended-bump"); +const ccWriterOpts = require("conventional-changelog-conventionalcommits/writer-opts"); + +const execa = require("execa"); + +const readFileSync = require("fs").readFileSync; +const resolve = require("path").resolve; + +/* + * Register a Handlebars helper that lets us generate Markdown lists that can support multi-line + * strings. This is driven by inconsistent formatting of breaking changes, which may be multiple + * lines long and can terminate the list early unintentionally. + */ +Handlebars.registerHelper("tf-a-mdlist", function (indent, options) { + const spaces = new Array(indent + 1).join(" "); + const first = spaces + "- "; + const nth = spaces + " "; + + return first + options.fn(this).replace(/\n(?!\s*\n)/gm, `\n${nth}`).trim() + "\n"; +}); + +/* + * Register a Handlebars helper that concatenates multiple variables. We use this to generate the + * title for the section partials. + */ +Handlebars.registerHelper("tf-a-concat", function () { + let argv = Array.prototype.slice.call(arguments, 0); + + argv.pop(); + + return argv.join(""); +}); + +function writerOpts(config) { + /* + * Flatten the configuration's sections list. This helps us iterate over all of the sections + * when we don't care about the hierarchy. + */ + + const flattenSections = function (sections) { + return sections.flatMap(section => { + const subsections = flattenSections(section.sections || []); + + return [section].concat(subsections); + }) + }; + + const flattenedSections = flattenSections(config.sections); + + /* + * Register a helper to return a restructured version of the note groups that includes notes + * categorized by their section. + */ + Handlebars.registerHelper("tf-a-notes", function (noteGroups, options) { + const generateTemplateData = function (sections, notes) { + return (sections || []).flatMap(section => { + const templateData = { + title: section.title, + sections: generateTemplateData(section.sections, notes), + notes: notes.filter(note => section.scopes?.includes(note.commit.scope)), + }; + + /* + * Don't return a section if it contains no notes and no sub-sections. + */ + if ((templateData.sections.length == 0) && (templateData.notes.length == 0)) { + return []; + } + + return [templateData]; + }); + }; + + return noteGroups.map(noteGroup => { + return { + title: noteGroup.title, + sections: generateTemplateData(config.sections, noteGroup.notes), + notes: noteGroup.notes.filter(note => + !flattenedSections.some(section => section.scopes?.includes(note.commit.scope))), + }; + }); + }); + + /* + * Register a helper to return a restructured version of the commit groups that includes commits + * categorized by their section. + */ + Handlebars.registerHelper("tf-a-commits", function (commitGroups, options) { + const generateTemplateData = function (sections, commits) { + return (sections || []).flatMap(section => { + const templateData = { + title: section.title, + sections: generateTemplateData(section.sections, commits), + commits: commits.filter(commit => section.scopes?.includes(commit.scope)), + }; + + /* + * Don't return a section if it contains no notes and no sub-sections. + */ + if ((templateData.sections.length == 0) && (templateData.commits.length == 0)) { + return []; + } + + return [templateData]; + }); + }; + + return commitGroups.map(commitGroup => { + return { + title: commitGroup.title, + sections: generateTemplateData(config.sections, commitGroup.commits), + commits: commitGroup.commits.filter(commit => + !flattenedSections.some(section => section.scopes?.includes(commit.scope))), + }; + }); + }); + + const writerOpts = ccWriterOpts(config) + .then(writerOpts => { + const ccWriterOptsTransform = writerOpts.transform; + + /* + * These configuration properties can't be injected directly into the template because + * they themselves are templates. Instead, we register them as partials, which allows + * them to be evaluated as part of the templates they're used in. + */ + Handlebars.registerPartial("commitUrl", config.commitUrlFormat); + Handlebars.registerPartial("compareUrl", config.compareUrlFormat); + Handlebars.registerPartial("issueUrl", config.issueUrlFormat); + + /* + * Register the partials that allow us to recursively create changelog sections. + */ + + const notePartial = readFileSync(resolve(__dirname, "./templates/note.hbs"), "utf-8"); + const noteSectionPartial = readFileSync(resolve(__dirname, "./templates/note-section.hbs"), "utf-8"); + const commitSectionPartial = readFileSync(resolve(__dirname, "./templates/commit-section.hbs"), "utf-8"); + + Handlebars.registerPartial("tf-a-note", notePartial); + Handlebars.registerPartial("tf-a-note-section", noteSectionPartial); + Handlebars.registerPartial("tf-a-commit-section", commitSectionPartial); + + /* + * Override the base templates so that we can generate a changelog that looks at least + * similar to the pre-Conventional Commits TF-A changelog. + */ + writerOpts.mainTemplate = readFileSync(resolve(__dirname, "./templates/template.hbs"), "utf-8"); + writerOpts.headerPartial = readFileSync(resolve(__dirname, "./templates/header.hbs"), "utf-8"); + writerOpts.commitPartial = readFileSync(resolve(__dirname, "./templates/commit.hbs"), "utf-8"); + writerOpts.footerPartial = readFileSync(resolve(__dirname, "./templates/footer.hbs"), "utf-8"); + + writerOpts.transform = function (commit, context) { + /* + * Fix up commit trailers, which for some reason are not correctly recognized and + * end up showing up in the breaking changes. + */ + + commit.notes.forEach(note => { + const trailers = execa.sync("git", ["interpret-trailers", "--parse"], { + input: note.text + }).stdout; + + note.text = note.text.replace(trailers, "").trim(); + }); + + return ccWriterOptsTransform(commit, context); + }; + + return writerOpts; + }); + + return writerOpts; +} + +module.exports = function (parameter) { + const config = parameter || {}; + + return Q.all([ + ccConventionalChangelog(config), + ccParserOpts(config), + ccRecommendedBumpOpts(config), + writerOpts(config) + ]).spread(( + conventionalChangelog, + parserOpts, + recommendedBumpOpts, + writerOpts + ) => { + if (_.isFunction(parameter)) { + return parameter(null, { + gitRawCommitsOpts: { noMerges: null }, + conventionalChangelog, + parserOpts, + recommendedBumpOpts, + writerOpts + }); + } else { + return { + conventionalChangelog, + parserOpts, + recommendedBumpOpts, + writerOpts + }; + } + }); +}; diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json b/arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json new file mode 100644 index 0000000..404ef90 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json @@ -0,0 +1,13 @@ +{ + "name": "conventional-changelog-tf-a", + "version": "2.6.0", + "license": "BSD-3-Clause", + "private": true, + "main": "index.js", + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.6.1", + "execa": "^5.1.1", + "lodash": "^4.17.21", + "q": "^1.5.1" + } +} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs new file mode 100644 index 0000000..86b3335 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs @@ -0,0 +1,17 @@ +{{#if title ~}} +{{ header }} + +{{#if commits.length ~}} + {{#each commits ~}} + {{#tf-a-mdlist 0}}{{> commit root=@root showScope=../topLevel }}{{/tf-a-mdlist ~}} + {{/each}} + +{{/if ~}} + +{{#if sections.length ~}} + {{#each sections ~}} + {{#tf-a-mdlist 0}}{{> tf-a-commit-section root=@root header=(tf-a-concat "**" title "**") }}{{/tf-a-mdlist}} + {{/each}} +{{/if ~}} + +{{/if}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs new file mode 100644 index 0000000..faf264a --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs @@ -0,0 +1,15 @@ +{{#if scope }} + {{~#if showScope }}**{{ scope }}:** {{/if}} +{{~/if}} + +{{~#if subject }} + {{~ subject }} +{{~else}} + {{~ header }} +{{~/if}} + +{{~#if hash }} {{#if @root.linkReferences ~}} + ([{{ shortHash }}]({{> commitUrl root=@root }})) +{{~else}} + {{~ shortHash }} +{{~/if}}{{~/if}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/footer.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/footer.hbs new file mode 100644 index 0000000..e69de29 diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs new file mode 100644 index 0000000..67cb297 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs @@ -0,0 +1,13 @@ +{{#if isPatch~}} + ### +{{~else~}} + ## +{{~/if}} {{#if @root.linkCompare~}} + [{{version}}]({{> compareUrl root=@root}}) +{{~else}} + {{~version}} +{{~/if}} +{{~#if title}} "{{title}}" +{{~/if}} +{{~#if date}} ({{date}}) +{{/if}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs new file mode 100644 index 0000000..f501c96 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs @@ -0,0 +1,13 @@ +{{ header }} + +{{#if notes.length ~}} + {{#each notes ~}} + {{#tf-a-mdlist 0}}{{> tf-a-note root=@root showScope=../topLevel }}{{/tf-a-mdlist}} + {{/each ~}} +{{/if ~}} + +{{#if sections.length ~}} + {{#each sections ~}} + {{#tf-a-mdlist 0}}{{> tf-a-note-section root=@root header=(tf-a-concat "**" title "**") }}{{/tf-a-mdlist}} + {{/each~}} +{{/if}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs new file mode 100644 index 0000000..c780ee8 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs @@ -0,0 +1,3 @@ +{{ text }} + +**See:** {{#with commit }}{{> commit root=@root showScope=../showScope }}{{/with}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs new file mode 100644 index 0000000..95fb68c --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs @@ -0,0 +1,9 @@ +{{> header }} + +{{#each (tf-a-notes noteGroups) ~}} +{{> tf-a-note-section root=@root header=(tf-a-concat "### âš  " title) topLevel=true }} +{{/each ~}} + +{{#each (tf-a-commits commitGroups) ~}} +{{> tf-a-commit-section root=@root header=(tf-a-concat "### " title) topLevel=true }} +{{/each ~}} diff --git a/arm-trusted-firmware/tools/encrypt_fw/Makefile b/arm-trusted-firmware/tools/encrypt_fw/Makefile new file mode 100644 index 0000000..96dff23 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h b/arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h new file mode 100644 index 0000000..bd7d31f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/encrypt_fw/include/debug.h b/arm-trusted-firmware/tools/encrypt_fw/include/debug.h new file mode 100644 index 0000000..ee8f1f5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h b/arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h new file mode 100644 index 0000000..25d3011 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c b/arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c new file mode 100644 index 0000000..64180d1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c b/arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c new file mode 100644 index 0000000..18a514c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/encrypt_fw/src/main.c b/arm-trusted-firmware/tools/encrypt_fw/src/main.c new file mode 100644 index 0000000..39b7af7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/fiptool/Makefile b/arm-trusted-firmware/tools/fiptool/Makefile new file mode 100644 index 0000000..7c2a083 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/Makefile @@ -0,0 +1,63 @@ +# +# 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 +OPENSSL_DIR := /usr + + +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 := -L${OPENSSL_DIR}/lib -lcrypto + +ifeq (${V},0) + Q := @ +else + Q := +endif + +INCLUDE_PATHS := -I../../include/tools_share -I${OPENSSL_DIR}/include + +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/arm-trusted-firmware/tools/fiptool/Makefile.msvc b/arm-trusted-firmware/tools/fiptool/Makefile.msvc new file mode 100644 index 0000000..9081bc6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/fiptool/fiptool b/arm-trusted-firmware/tools/fiptool/fiptool new file mode 100755 index 0000000..bc9aa55 Binary files /dev/null and b/arm-trusted-firmware/tools/fiptool/fiptool differ diff --git a/arm-trusted-firmware/tools/fiptool/fiptool.c b/arm-trusted-firmware/tools/fiptool/fiptool.c new file mode 100644 index 0000000..5c240b5 --- /dev/null +++ b/arm-trusted-firmware/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 || (image->toc_e.size == 0ULL)) + 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/arm-trusted-firmware/tools/fiptool/fiptool.h b/arm-trusted-firmware/tools/fiptool/fiptool.h new file mode 100644 index 0000000..88c4a7e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/fiptool/fiptool_platform.h b/arm-trusted-firmware/tools/fiptool/fiptool_platform.h new file mode 100644 index 0000000..9bfa298 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/fiptool/tbbr_config.c b/arm-trusted-firmware/tools/fiptool/tbbr_config.c new file mode 100644 index 0000000..4998bb2 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/tbbr_config.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016-2021, 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" + }, + { + .name = "Realm Monitor Management Firmware", + .uuid = UUID_REALM_MONITOR_MGMT_FIRMWARE, + .cmdline_name = "rmm-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/arm-trusted-firmware/tools/fiptool/tbbr_config.h b/arm-trusted-firmware/tools/fiptool/tbbr_config.h new file mode 100644 index 0000000..b926ff0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/fiptool/win_posix.c b/arm-trusted-firmware/tools/fiptool/win_posix.c new file mode 100644 index 0000000..33b44d4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/tools/fiptool/win_posix.h b/arm-trusted-firmware/tools/fiptool/win_posix.h new file mode 100644 index 0000000..6f0d8e6 --- /dev/null +++ b/arm-trusted-firmware/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 */ diff --git a/arm-trusted-firmware/tools/marvell/doimage/Makefile b/arm-trusted-firmware/tools/marvell/doimage/Makefile new file mode 100644 index 0000000..9f0d89d --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +PROJECT = doimage +OBJECTS = doimage.o + +HOSTCCFLAGS = -Wall -Werror +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif + +ifeq (${MARVELL_SECURE_BOOT},1) +DOIMAGE_CC_FLAGS := -DCONFIG_MVEBU_SECURE_BOOT +DOIMAGE_LD_FLAGS := -lconfig -lmbedtls -lmbedcrypto -lmbedx509 +endif + +HOSTCCFLAGS += ${DOIMAGE_CC_FLAGS} + +# Make soft links and include from local directory otherwise wrong headers +# could get pulled in from firmware tree. +INCLUDE_PATHS = -I. + +HOSTCC ?= gcc +RM := rm -rf + +.PHONY: all clean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@ + @echo + @echo "Built $@ successfully" + @echo + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@ + +clean: + ${Q}${RM} ${PROJECT} + ${Q}${RM} ${OBJECTS} diff --git a/arm-trusted-firmware/tools/marvell/doimage/doimage.c b/arm-trusted-firmware/tools/marvell/doimage/doimage.c new file mode 100644 index 0000000..e08b820 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/doimage.c @@ -0,0 +1,1764 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MVEBU_SECURE_BOOT +#include /* for parsing config file */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* mbedTLS stuff */ +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \ + defined(MBEDTLS_CTR_DRBG_C) +#include +#include +#include +#include +#include +#include +#include +#else +#error "Bad mbedTLS configuration!" +#endif +#endif /* CONFIG_MVEBU_SECURE_BOOT */ + +#define MAX_FILENAME 256 +#define CSK_ARR_SZ 16 +#define CSK_ARR_EMPTY_FILE "*" +#define AES_KEY_BIT_LEN 256 +#define AES_KEY_BYTE_LEN (AES_KEY_BIT_LEN >> 3) +#define AES_BLOCK_SZ 16 +#define RSA_SIGN_BYTE_LEN 256 +#define MAX_RSA_DER_BYTE_LEN 524 +/* Number of address pairs in control array */ +#define CP_CTRL_EL_ARRAY_SZ 32 + +#define VERSION_STRING "Marvell(C) doimage utility version 3.3" + +/* A8K definitions */ + +/* Extension header types */ +#define EXT_TYPE_SECURITY 0x1 +#define EXT_TYPE_BINARY 0x2 + +#define MAIN_HDR_MAGIC 0xB105B002 + +/* PROLOG alignment considerations: + * 128B: To allow supporting XMODEM protocol. + * 8KB: To align the boot image to the largest NAND page size, and simplify + * the read operations from NAND. + * We choose the largest page size, in order to use a single image for all + * NAND page sizes. + */ +#define PROLOG_ALIGNMENT (8 << 10) + +/* UART argument bitfield */ +#define UART_MODE_UNMODIFIED 0x0 +#define UART_MODE_DISABLE 0x1 +#define UART_MODE_UPDATE 0x2 + +typedef struct _main_header { + uint32_t magic; /* 0-3 */ + uint32_t prolog_size; /* 4-7 */ + uint32_t prolog_checksum; /* 8-11 */ + uint32_t boot_image_size; /* 12-15 */ + uint32_t boot_image_checksum; /* 16-19 */ + uint32_t rsrvd0; /* 20-23 */ + uint32_t load_addr; /* 24-27 */ + uint32_t exec_addr; /* 28-31 */ + uint8_t uart_cfg; /* 32 */ + uint8_t baudrate; /* 33 */ + uint8_t ext_count; /* 34 */ + uint8_t aux_flags; /* 35 */ + uint32_t io_arg_0; /* 36-39 */ + uint32_t io_arg_1; /* 40-43 */ + uint32_t io_arg_2; /* 43-47 */ + uint32_t io_arg_3; /* 48-51 */ + uint32_t rsrvd1; /* 52-55 */ + uint32_t rsrvd2; /* 56-59 */ + uint32_t rsrvd3; /* 60-63 */ +} header_t; + +typedef struct _ext_header { + uint8_t type; + uint8_t offset; + uint16_t reserved; + uint32_t size; +} ext_header_t; + +typedef struct _sec_entry { + uint8_t kak_key[MAX_RSA_DER_BYTE_LEN]; + uint32_t jtag_delay; + uint32_t box_id; + uint32_t flash_id; + uint32_t jtag_en; + uint32_t encrypt_en; + uint32_t efuse_dis; + uint8_t header_sign[RSA_SIGN_BYTE_LEN]; + uint8_t image_sign[RSA_SIGN_BYTE_LEN]; + uint8_t csk_keys[CSK_ARR_SZ][MAX_RSA_DER_BYTE_LEN]; + uint8_t csk_sign[RSA_SIGN_BYTE_LEN]; + uint32_t cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ]; + uint32_t cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ]; +} sec_entry_t; + +/* A8K definitions end */ + +/* UART argument bitfield */ +#define UART_MODE_UNMODIFIED 0x0 +#define UART_MODE_DISABLE 0x1 +#define UART_MODE_UPDATE 0x2 + +#define uart_set_mode(arg, mode) (arg |= (mode & 0x3)) + +typedef struct _sec_options { +#ifdef CONFIG_MVEBU_SECURE_BOOT + char aes_key_file[MAX_FILENAME+1]; + char kak_key_file[MAX_FILENAME+1]; + char csk_key_file[CSK_ARR_SZ][MAX_FILENAME+1]; + uint32_t box_id; + uint32_t flash_id; + uint32_t jtag_delay; + uint8_t csk_index; + uint8_t jtag_enable; + uint8_t efuse_disable; + uint32_t cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ]; + uint32_t cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ]; + mbedtls_pk_context kak_pk; + mbedtls_pk_context csk_pk[CSK_ARR_SZ]; + uint8_t aes_key[AES_KEY_BYTE_LEN]; + uint8_t *encrypted_image; + uint32_t enc_image_sz; +#endif +} sec_options; + +typedef struct _options { + char bin_ext_file[MAX_FILENAME+1]; + char sec_cfg_file[MAX_FILENAME+1]; + sec_options *sec_opts; + uint32_t load_addr; + uint32_t exec_addr; + uint32_t baudrate; + uint8_t disable_print; + int8_t key_index; /* For header signatures verification only */ + uint32_t nfc_io_args; +} options_t; + +void usage_err(char *msg) +{ + fprintf(stderr, "Error: %s\n", msg); + fprintf(stderr, "run 'doimage -h' to get usage information\n"); + exit(-1); +} + +void usage(void) +{ + printf("\n\n%s\n\n", VERSION_STRING); + printf("Usage: doimage [options] [output_file]\n"); + printf("create bootrom image from u-boot and boot extensions\n\n"); + + printf("Arguments\n"); + printf(" input_file name of boot image file.\n"); + printf(" if -p is used, name of the bootrom image file"); + printf(" to parse.\n"); + printf(" output_file name of output bootrom image file\n"); + + printf("\nOptions\n"); + printf(" -s target SOC name. supports a8020,a7020\n"); + printf(" different SOCs may have different boot image\n"); + printf(" format so it's mandatory to know the target SOC\n"); + printf(" -i boot I/F name. supports nand, spi, nor\n"); + printf(" This affects certain parameters coded in the\n"); + printf(" image header\n"); + printf(" -l boot image load address. default is 0x0\n"); + printf(" -e boot image entry address. default is 0x0\n"); + printf(" -b binary extension image file.\n"); + printf(" This image is executed before the boot image.\n"); + printf(" This is typically used to initialize the memory "); + printf(" controller.\n"); + printf(" Currently supports only a single file.\n"); +#ifdef CONFIG_MVEBU_SECURE_BOOT + printf(" -c Make trusted boot image using parameters\n"); + printf(" from the configuration file.\n"); +#endif + printf(" -p Parse and display a pre-built boot image\n"); +#ifdef CONFIG_MVEBU_SECURE_BOOT + printf(" -k Key index for RSA signatures verification\n"); + printf(" when parsing the boot image\n"); +#endif + printf(" -m Disable prints of bootrom and binary extension\n"); + printf(" -u UART baudrate used for bootrom prints.\n"); + printf(" Must be multiple of 1200\n"); + printf(" -h Show this help message\n"); + printf(" IO-ROM NFC-NAND boot parameters:\n"); + printf(" -n NAND device block size in KB [Default is 64KB].\n"); + printf(" -t NAND cell technology (SLC [Default] or MLC)\n"); + + exit(-1); +} + +/* globals */ +static options_t opts = { + .bin_ext_file = "NA", + .sec_cfg_file = "NA", + .sec_opts = 0, + .load_addr = 0x0, + .exec_addr = 0x0, + .disable_print = 0, + .baudrate = 0, + .key_index = -1, +}; + +int get_file_size(char *filename) +{ + struct stat st; + + if (stat(filename, &st) == 0) + return st.st_size; + + return -1; +} + +uint32_t checksum32(uint32_t *start, int len) +{ + uint32_t sum = 0; + uint32_t *startp = start; + + do { + sum += *startp; + startp++; + len -= 4; + } while (len > 0); + + return sum; +} + +/******************************************************************************* + * create_rsa_signature (memory buffer content) + * Create RSASSA-PSS/SHA-256 signature for memory buffer + * using RSA Private Key + * INPUT: + * pk_ctx Private Key context + * input memory buffer + * ilen buffer length + * pers personalization string for seeding the RNG. + * For instance a private key file name. + * OUTPUT: + * signature RSA-2048 signature + * RETURN: + * 0 on success + */ +#ifdef CONFIG_MVEBU_SECURE_BOOT +int create_rsa_signature(mbedtls_pk_context *pk_ctx, + const unsigned char *input, + size_t ilen, + const char *pers, + uint8_t *signature) +{ + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + int rval; + + /* Not sure this is required, + * but it's safer to start with empty buffers + */ + memset(hash, 0, sizeof(hash)); + memset(buf, 0, sizeof(buf)); + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + /* Seed the random number generator */ + rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (rval != 0) { + fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval); + goto sign_exit; + } + + /* The PK context should be already initialized. + * Set the padding type for this PK context + */ + mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk_ctx), + MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); + + /* First compute the SHA256 hash for the input blob */ + mbedtls_sha256_ret(input, ilen, hash, 0); + + /* Then calculate the hash signature */ + rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx), + mbedtls_ctr_drbg_random, + &ctr_drbg, + MBEDTLS_RSA_PRIVATE, + MBEDTLS_MD_SHA256, 0, hash, buf); + if (rval != 0) { + fprintf(stderr, + "Failed to create RSA signature for %s. Error %d\n", + pers, rval); + goto sign_exit; + } + memcpy(signature, buf, 256); + +sign_exit: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + + return rval; +} /* end of create_rsa_signature */ + +/******************************************************************************* + * verify_rsa_signature (memory buffer content) + * Verify RSASSA-PSS/SHA-256 signature for memory buffer + * using RSA Public Key + * INPUT: + * pub_key Public Key buffer + * ilen Public Key buffer length + * input memory buffer + * ilen buffer length + * pers personalization string for seeding the RNG. + * signature RSA-2048 signature + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int verify_rsa_signature(const unsigned char *pub_key, + size_t klen, + const unsigned char *input, + size_t ilen, + const char *pers, + uint8_t *signature) +{ + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_pk_context pk_ctx; + unsigned char hash[32]; + int rval; + unsigned char *pkey = (unsigned char *)pub_key; + + /* Not sure this is required, + * but it's safer to start with empty buffer + */ + memset(hash, 0, sizeof(hash)); + + mbedtls_pk_init(&pk_ctx); + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + /* Seed the random number generator */ + rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (rval != 0) { + fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval); + goto verify_exit; + } + + /* Check ability to read the public key */ + rval = mbedtls_pk_parse_subpubkey(&pkey, pub_key + klen, &pk_ctx); + if (rval != 0) { + fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n", + rval); + goto verify_exit; + } + + /* Set the padding type for the new PK context */ + mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk_ctx), + MBEDTLS_RSA_PKCS_V21, + MBEDTLS_MD_SHA256); + + /* Compute the SHA256 hash for the input buffer */ + mbedtls_sha256_ret(input, ilen, hash, 0); + + rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx), + mbedtls_ctr_drbg_random, + &ctr_drbg, + MBEDTLS_RSA_PUBLIC, + MBEDTLS_MD_SHA256, 0, + hash, signature); + if (rval != 0) + fprintf(stderr, "Failed to verify signature (%d)!\n", rval); + +verify_exit: + + mbedtls_pk_free(&pk_ctx); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return rval; +} /* end of verify_rsa_signature */ + +/******************************************************************************* + * image_encrypt + * Encrypt image buffer using AES-256-CBC scheme. + * The resulting image is saved into opts.sec_opts->encrypted_image + * and the adjusted image size into opts.sec_opts->enc_image_sz + * First AES_BLOCK_SZ bytes of the output image contain IV + * INPUT: + * buf Source buffer to encrypt + * blen Source buffer length + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int image_encrypt(uint8_t *buf, uint32_t blen) +{ + struct timeval tv; + char *ptmp = (char *)&tv; + unsigned char digest[32]; + unsigned char IV[AES_BLOCK_SZ]; + int i, k; + mbedtls_aes_context aes_ctx; + int rval = -1; + uint8_t *test_img = 0; + + if (AES_BLOCK_SZ > 32) { + fprintf(stderr, "Unsupported AES block size %d\n", + AES_BLOCK_SZ); + return rval; + } + + mbedtls_aes_init(&aes_ctx); + memset(IV, 0, AES_BLOCK_SZ); + memset(digest, 0, 32); + + /* Generate initialization vector and init the AES engine + * Use file name XOR current time and finally SHA-256 + * [0...AES_BLOCK_SZ-1] + */ + k = strlen(opts.sec_opts->aes_key_file); + if (k > AES_BLOCK_SZ) + k = AES_BLOCK_SZ; + memcpy(IV, opts.sec_opts->aes_key_file, k); + gettimeofday(&tv, 0); + + for (i = 0, k = 0; i < AES_BLOCK_SZ; i++, + k = (k+1) % sizeof(struct timeval)) + IV[i] ^= ptmp[k]; + + /* compute SHA-256 digest of the results + * and use it as the init vector (IV) + */ + mbedtls_sha256_ret(IV, AES_BLOCK_SZ, digest, 0); + memcpy(IV, digest, AES_BLOCK_SZ); + mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key, + AES_KEY_BIT_LEN); + + /* The output image has to include extra space for IV + * and to be aligned to the AES block size. + * The input image buffer has to be already aligned to AES_BLOCK_SZ + * and padded with zeroes + */ + opts.sec_opts->enc_image_sz = (blen + 2 * AES_BLOCK_SZ - 1) & + ~(AES_BLOCK_SZ - 1); + opts.sec_opts->encrypted_image = calloc(opts.sec_opts->enc_image_sz, 1); + if (opts.sec_opts->encrypted_image == 0) { + fprintf(stderr, "Failed to allocate encrypted image!\n"); + goto encrypt_exit; + } + + /* Put IV into the output buffer next to the encrypted image + * Since the IV is modified by the encryption function, + * this should be done now + */ + memcpy(opts.sec_opts->encrypted_image + + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, AES_BLOCK_SZ); + rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, buf, opts.sec_opts->encrypted_image); + if (rval != 0) { + fprintf(stderr, "Failed to encrypt the image! Error %d\n", + rval); + goto encrypt_exit; + } + + mbedtls_aes_free(&aes_ctx); + + /* Try to decrypt the image and compare it with the original data */ + mbedtls_aes_init(&aes_ctx); + mbedtls_aes_setkey_dec(&aes_ctx, opts.sec_opts->aes_key, + AES_KEY_BIT_LEN); + + test_img = calloc(opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, 1); + if (test_img == 0) { + fprintf(stderr, "Failed to allocate test image!d\n"); + rval = -1; + goto encrypt_exit; + } + + memcpy(IV, opts.sec_opts->encrypted_image + + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + AES_BLOCK_SZ); + rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, opts.sec_opts->encrypted_image, test_img); + if (rval != 0) { + fprintf(stderr, "Failed to decrypt the image! Error %d\n", + rval); + goto encrypt_exit; + } + + for (i = 0; i < blen; i++) { + if (buf[i] != test_img[i]) { + fprintf(stderr, "Failed to compare the image after"); + fprintf(stderr, " decryption! Byte count is %d\n", i); + rval = -1; + goto encrypt_exit; + } + } + +encrypt_exit: + + mbedtls_aes_free(&aes_ctx); + if (test_img) + free(test_img); + + return rval; +} /* end of image_encrypt */ + +/******************************************************************************* + * verify_secure_header_signatures + * Verify CSK array, header and image signatures and print results + * INPUT: + * main_hdr Main header + * sec_ext Secure extension + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int verify_secure_header_signatures(header_t *main_hdr, sec_entry_t *sec_ext) +{ + uint8_t *image = (uint8_t *)main_hdr + main_hdr->prolog_size; + uint8_t signature[RSA_SIGN_BYTE_LEN]; + int rval = -1; + + /* Save headers signature and reset it in the secure header */ + memcpy(signature, sec_ext->header_sign, RSA_SIGN_BYTE_LEN); + memset(sec_ext->header_sign, 0, RSA_SIGN_BYTE_LEN); + + fprintf(stdout, "\nCheck RSA Signatures\n"); + fprintf(stdout, "#########################\n"); + fprintf(stdout, "CSK Block Signature: "); + if (verify_rsa_signature(sec_ext->kak_key, + MAX_RSA_DER_BYTE_LEN, + &sec_ext->csk_keys[0][0], + sizeof(sec_ext->csk_keys), + "CSK Block Signature: ", + sec_ext->csk_sign) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + + if (opts.key_index != -1) { + fprintf(stdout, "Image Signature: "); + if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index], + MAX_RSA_DER_BYTE_LEN, + image, main_hdr->boot_image_size, + "Image Signature: ", + sec_ext->image_sign) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + + fprintf(stdout, "Header Signature: "); + if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index], + MAX_RSA_DER_BYTE_LEN, + (uint8_t *)main_hdr, + main_hdr->prolog_size, + "Header Signature: ", + signature) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + } else { + fprintf(stdout, "SKIP Image and Header Signatures"); + fprintf(stdout, " check (undefined key index)\n"); + } + + rval = 0; + +ver_error: + memcpy(sec_ext->header_sign, signature, RSA_SIGN_BYTE_LEN); + return rval; +} + +/******************************************************************************* + * verify_and_copy_file_name_entry + * INPUT: + * element_name + * element + * OUTPUT: + * copy_to + * RETURN: + * 0 on success + */ +int verify_and_copy_file_name_entry(const char *element_name, + const char *element, char *copy_to) +{ + int element_length = strlen(element); + + if (element_length >= MAX_FILENAME) { + fprintf(stderr, "The file name %s for %s is too long (%d). ", + element, element_name, element_length); + fprintf(stderr, "Maximum allowed %d characters!\n", + MAX_FILENAME); + return -1; + } else if (element_length == 0) { + fprintf(stderr, "The file name for %s is empty!\n", + element_name); + return -1; + } + memcpy(copy_to, element, element_length); + + return 0; +} + +/******************************************************************************* + * parse_sec_config_file + * Read the secure boot configuration from a file + * into internal structures + * INPUT: + * filename File name + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int parse_sec_config_file(char *filename) +{ + config_t sec_cfg; + int array_sz, element, rval = -1; + const char *cfg_string; + int32_t cfg_int32; + const config_setting_t *csk_array, *control_array; + sec_options *sec_opt = 0; + + config_init(&sec_cfg); + + if (config_read_file(&sec_cfg, filename) != CONFIG_TRUE) { + fprintf(stderr, "Failed to read data from config file "); + fprintf(stderr, "%s\n\t%s at line %d\n", + filename, config_error_text(&sec_cfg), + config_error_line(&sec_cfg)); + goto exit_parse; + } + + sec_opt = (sec_options *)calloc(sizeof(sec_options), 1); + if (sec_opt == 0) { + fprintf(stderr, + "Cannot allocate memory for secure boot options!\n"); + goto exit_parse; + } + + /* KAK file name */ + if (config_lookup_string(&sec_cfg, "kak_key_file", + &cfg_string) != CONFIG_TRUE) { + fprintf(stderr, "The \"kak_key_file\" undefined!\n"); + goto exit_parse; + } + if (verify_and_copy_file_name_entry("kak_key_file", + cfg_string, sec_opt->kak_key_file)) + goto exit_parse; + + + /* AES file name - can be empty/undefined */ + if (config_lookup_string(&sec_cfg, "aes_key_file", + &cfg_string) == CONFIG_TRUE) { + if (verify_and_copy_file_name_entry("aes_key_file", + cfg_string, + sec_opt->aes_key_file)) + goto exit_parse; + } + + /* CSK file names array */ + csk_array = config_lookup(&sec_cfg, "csk_key_file"); + if (csk_array == NULL) { + fprintf(stderr, "The \"csk_key_file\" undefined!\n"); + goto exit_parse; + } + array_sz = config_setting_length(csk_array); + if (array_sz > CSK_ARR_SZ) { + fprintf(stderr, "The \"csk_key_file\" array is too big! "); + fprintf(stderr, "Only first %d elements will be used\n", + CSK_ARR_SZ); + array_sz = CSK_ARR_SZ; + } else if (array_sz == 0) { + fprintf(stderr, "The \"csk_key_file\" array is empty!\n"); + goto exit_parse; + } + + for (element = 0; element < array_sz; element++) { + cfg_string = config_setting_get_string_elem(csk_array, element); + if (verify_and_copy_file_name_entry( + "csk_key_file", cfg_string, + sec_opt->csk_key_file[element])) { + fprintf(stderr, "Bad csk_key_file[%d] entry!\n", + element); + goto exit_parse; + } + } + + /* JTAG options */ + if (config_lookup_bool(&sec_cfg, "jtag.enable", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"jtag.enable\" element. "); + fprintf(stderr, "Using default - FALSE\n"); + cfg_int32 = 0; + } + sec_opt->jtag_enable = cfg_int32; + + if (config_lookup_int(&sec_cfg, "jtag.delay", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"jtag.delay\" element. "); + fprintf(stderr, "Using default - 0us\n"); + cfg_int32 = 0; + } + sec_opt->jtag_delay = cfg_int32; + + /* eFUSE option */ + if (config_lookup_bool(&sec_cfg, "efuse_disable", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"efuse_disable\" element. "); + fprintf(stderr, "Using default - TRUE\n"); + cfg_int32 = 1; + } + sec_opt->efuse_disable = cfg_int32; + + /* Box ID option */ + if (config_lookup_int(&sec_cfg, "box_id", &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"box_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->box_id = cfg_int32; + + /* Flash ID option */ + if (config_lookup_int(&sec_cfg, "flash_id", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"flash_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->flash_id = cfg_int32; + + /* CSK index option */ + if (config_lookup_int(&sec_cfg, "csk_key_index", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"flash_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->csk_index = cfg_int32; + + /* Secure boot control array */ + control_array = config_lookup(&sec_cfg, "control"); + if (control_array != NULL) { + array_sz = config_setting_length(control_array); + if (array_sz == 0) + fprintf(stderr, "The \"control\" array is empty!\n"); + } else { + fprintf(stderr, "The \"control\" is undefined!\n"); + array_sz = 0; + } + + for (element = 0; element < CP_CTRL_EL_ARRAY_SZ; element++) { + sec_opt->cp_ctrl_arr[element] = + config_setting_get_int_elem(control_array, element * 2); + sec_opt->cp_efuse_arr[element] = + config_setting_get_int_elem(control_array, + element * 2 + 1); + } + + opts.sec_opts = sec_opt; + rval = 0; + +exit_parse: + config_destroy(&sec_cfg); + if (sec_opt && (rval != 0)) + free(sec_opt); + return rval; +} /* end of parse_sec_config_file */ + +int format_sec_ext(char *filename, FILE *out_fd) +{ + ext_header_t header; + sec_entry_t sec_ext; + int index; + int written; + +#define DER_BUF_SZ 1600 + + /* First, parse the configuration file */ + if (parse_sec_config_file(filename)) { + fprintf(stderr, + "failed parsing configuration file %s\n", filename); + return 1; + } + + /* Everything except signatures can be created at this stage */ + header.type = EXT_TYPE_SECURITY; + header.offset = 0; + header.size = sizeof(sec_entry_t); + header.reserved = 0; + + /* Bring up RSA context and read private keys from their files */ + for (index = 0; index < (CSK_ARR_SZ + 1); index++) { + /* for every private key file */ + mbedtls_pk_context *pk_ctx = (index == CSK_ARR_SZ) ? + &opts.sec_opts->kak_pk : + &opts.sec_opts->csk_pk[index]; + char *fname = (index == CSK_ARR_SZ) ? + opts.sec_opts->kak_key_file : + opts.sec_opts->csk_key_file[index]; + uint8_t *out_der_key = (index == CSK_ARR_SZ) ? + sec_ext.kak_key : + sec_ext.csk_keys[index]; + size_t output_len; + unsigned char output_buf[DER_BUF_SZ]; + unsigned char *der_buf_start; + + /* Handle invalid/reserved file names */ + if (strncmp(CSK_ARR_EMPTY_FILE, fname, + strlen(CSK_ARR_EMPTY_FILE)) == 0) { + if (opts.sec_opts->csk_index == index) { + fprintf(stderr, + "CSK file with index %d cannot be %s\n", + index, CSK_ARR_EMPTY_FILE); + return 1; + } else if (index == CSK_ARR_SZ) { + fprintf(stderr, "KAK file name cannot be %s\n", + CSK_ARR_EMPTY_FILE); + return 1; + } + /* this key will be empty in CSK array */ + continue; + } + + mbedtls_pk_init(pk_ctx); + /* Read the private RSA key into the context + * and verify it (no password) + */ + if (mbedtls_pk_parse_keyfile(pk_ctx, fname, "") != 0) { + fprintf(stderr, + "Cannot read RSA private key file %s\n", fname); + return 1; + } + + /* Create a public key out of private one + * and store it in DER format + */ + output_len = mbedtls_pk_write_pubkey_der(pk_ctx, + output_buf, + DER_BUF_SZ); + if (output_len < 0) { + fprintf(stderr, + "Failed to create DER coded PUB key (%s)\n", + fname); + return 1; + } + + /* Data in the output buffer is aligned to the buffer end */ + der_buf_start = output_buf + sizeof(output_buf) - output_len; + /* In the header DER data is aligned + * to the start of appropriate field + */ + bzero(out_der_key, MAX_RSA_DER_BYTE_LEN); + memcpy(out_der_key, der_buf_start, output_len); + + } /* for every private key file */ + + /* The CSK block signature can be created here */ + if (create_rsa_signature(&opts.sec_opts->kak_pk, + &sec_ext.csk_keys[0][0], + sizeof(sec_ext.csk_keys), + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext.csk_sign) != 0) { + fprintf(stderr, "Failed to sign CSK keys block!\n"); + return 1; + } + + /* Check that everything is correct */ + if (verify_rsa_signature(sec_ext.kak_key, + MAX_RSA_DER_BYTE_LEN, + &sec_ext.csk_keys[0][0], + sizeof(sec_ext.csk_keys), + opts.sec_opts->kak_key_file, + sec_ext.csk_sign) != 0) { + fprintf(stderr, "Failed to verify CSK keys block signature!\n"); + return 1; + } + + /* AES encryption stuff */ + if (strlen(opts.sec_opts->aes_key_file) != 0) { + FILE *in_fd; + + in_fd = fopen(opts.sec_opts->aes_key_file, "rb"); + if (in_fd == NULL) { + fprintf(stderr, "Failed to open AES key file %s\n", + opts.sec_opts->aes_key_file); + return 1; + } + + /* Read the AES key in ASCII format byte by byte */ + for (index = 0; index < AES_KEY_BYTE_LEN; index++) { + if (fscanf(in_fd, "%02hhx", + opts.sec_opts->aes_key + index) != 1) { + fprintf(stderr, + "Failed to read AES key byte %d ", + index); + fprintf(stderr, + "from file %s\n", + opts.sec_opts->aes_key_file); + fclose(in_fd); + return 1; + } + } + fclose(in_fd); + sec_ext.encrypt_en = 1; + } else { + sec_ext.encrypt_en = 0; + } + + /* Fill the rest of the trusted boot extension fields */ + sec_ext.box_id = opts.sec_opts->box_id; + sec_ext.flash_id = opts.sec_opts->flash_id; + sec_ext.efuse_dis = opts.sec_opts->efuse_disable; + sec_ext.jtag_delay = opts.sec_opts->jtag_delay; + sec_ext.jtag_en = opts.sec_opts->jtag_enable; + + memcpy(sec_ext.cp_ctrl_arr, + opts.sec_opts->cp_ctrl_arr, + sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ); + memcpy(sec_ext.cp_efuse_arr, + opts.sec_opts->cp_efuse_arr, + sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ); + + /* Write the resulting extension to file + * (image and header signature fields are still empty) + */ + + /* Write extension header */ + written = fwrite(&header, sizeof(ext_header_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Failed to write SEC extension header to the file\n"); + return 1; + } + /* Write extension body */ + written = fwrite(&sec_ext, sizeof(sec_entry_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Failed to write SEC extension body to the file\n"); + return 1; + } + + return 0; +} + +/******************************************************************************* + * finalize_secure_ext + * Make final changes to secure extension - calculate image and header + * signatures and encrypt the image if needed. + * The main header checksum and image size fields updated accordingly + * INPUT: + * header Main header + * prolog_buf the entire prolog buffer + * prolog_size prolog buffer length + * image_buf buffer containing the input binary image + * image_size image buffer size. + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int finalize_secure_ext(header_t *header, + uint8_t *prolog_buf, uint32_t prolog_size, + uint8_t *image_buf, int image_size) +{ + int cur_ext, offset; + uint8_t *final_image = image_buf; + uint32_t final_image_sz = image_size; + uint8_t hdr_sign[RSA_SIGN_BYTE_LEN]; + sec_entry_t *sec_ext = 0; + + /* Find the Trusted Boot Header between available extensions */ + for (cur_ext = 0, offset = sizeof(header_t); + cur_ext < header->ext_count; cur_ext++) { + ext_header_t *ext_hdr = (ext_header_t *)(prolog_buf + offset); + + if (ext_hdr->type == EXT_TYPE_SECURITY) { + sec_ext = (sec_entry_t *)(prolog_buf + offset + + sizeof(ext_header_t) + ext_hdr->offset); + break; + } + + offset += sizeof(ext_header_t); + /* If offset is Zero, the extension follows its header */ + if (ext_hdr->offset == 0) + offset += ext_hdr->size; + } + + if (sec_ext == 0) { + fprintf(stderr, "Error: No Trusted Boot extension found!\n"); + return -1; + } + + if (sec_ext->encrypt_en) { + /* Encrypt the image if needed */ + fprintf(stdout, "Encrypting the image...\n"); + + if (image_encrypt(image_buf, image_size) != 0) { + fprintf(stderr, "Failed to encrypt the image!\n"); + return -1; + } + + /* Image size and checksum should be updated after encryption. + * This way the image could be verified by the BootROM + * before decryption. + */ + final_image = opts.sec_opts->encrypted_image; + final_image_sz = opts.sec_opts->enc_image_sz; + + header->boot_image_size = final_image_sz; + header->boot_image_checksum = + checksum32((uint32_t *)final_image, final_image_sz); + } /* AES encryption */ + + /* Create the image signature first, since it will be later + * signed along with the header signature + */ + if (create_rsa_signature(&opts.sec_opts->csk_pk[ + opts.sec_opts->csk_index], + final_image, final_image_sz, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext->image_sign) != 0) { + fprintf(stderr, "Failed to sign image!\n"); + return -1; + } + /* Check that the image signature is correct */ + if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index], + MAX_RSA_DER_BYTE_LEN, + final_image, final_image_sz, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext->image_sign) != 0) { + fprintf(stderr, "Failed to verify image signature!\n"); + return -1; + } + + /* Sign the headers and all the extensions block + * when the header signature field is empty + */ + if (create_rsa_signature(&opts.sec_opts->csk_pk[ + opts.sec_opts->csk_index], + prolog_buf, prolog_size, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + hdr_sign) != 0) { + fprintf(stderr, "Failed to sign header!\n"); + return -1; + } + /* Check that the header signature is correct */ + if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index], + MAX_RSA_DER_BYTE_LEN, + prolog_buf, prolog_size, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + hdr_sign) != 0) { + fprintf(stderr, "Failed to verify header signature!\n"); + return -1; + } + + /* Finally, copy the header signature into the trusted boot extension */ + memcpy(sec_ext->header_sign, hdr_sign, RSA_SIGN_BYTE_LEN); + + return 0; +} + +#endif /* CONFIG_MVEBU_SECURE_BOOT */ + + +#define FMT_HEX 0 +#define FMT_DEC 1 +#define FMT_BIN 2 +#define FMT_NONE 3 + +void do_print_field(unsigned int value, char *name, + int start, int size, int format) +{ + fprintf(stdout, "[0x%05x : 0x%05x] %-26s", + start, start + size - 1, name); + + switch (format) { + case FMT_HEX: + printf("0x%x\n", value); + break; + case FMT_DEC: + printf("%d\n", value); + break; + default: + printf("\n"); + break; + } +} + +#define print_field(st, type, field, hex, base) \ + do_print_field((int)st->field, #field, \ + base + offsetof(type, field), sizeof(st->field), hex) + +int print_header(uint8_t *buf, int base) +{ + header_t *main_hdr; + + main_hdr = (header_t *)buf; + + fprintf(stdout, "########### Header ##############\n"); + print_field(main_hdr, header_t, magic, FMT_HEX, base); + print_field(main_hdr, header_t, prolog_size, FMT_DEC, base); + print_field(main_hdr, header_t, prolog_checksum, FMT_HEX, base); + print_field(main_hdr, header_t, boot_image_size, FMT_DEC, base); + print_field(main_hdr, header_t, boot_image_checksum, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd0, FMT_HEX, base); + print_field(main_hdr, header_t, load_addr, FMT_HEX, base); + print_field(main_hdr, header_t, exec_addr, FMT_HEX, base); + print_field(main_hdr, header_t, uart_cfg, FMT_HEX, base); + print_field(main_hdr, header_t, baudrate, FMT_HEX, base); + print_field(main_hdr, header_t, ext_count, FMT_DEC, base); + print_field(main_hdr, header_t, aux_flags, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_0, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_1, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_2, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_3, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd1, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd2, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd3, FMT_HEX, base); + + return sizeof(header_t); +} + +int print_ext_hdr(ext_header_t *ext_hdr, int base) +{ + print_field(ext_hdr, ext_header_t, type, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, offset, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, reserved, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, size, FMT_DEC, base); + + return base + sizeof(ext_header_t); +} + +void print_sec_ext(ext_header_t *ext_hdr, int base) +{ + sec_entry_t *sec_entry; + uint32_t new_base; + + fprintf(stdout, "\n########### Secure extension ###########\n"); + + new_base = print_ext_hdr(ext_hdr, base); + + sec_entry = (sec_entry_t *)(ext_hdr + 1); + + do_print_field(0, "KAK key", new_base, MAX_RSA_DER_BYTE_LEN, FMT_NONE); + new_base += MAX_RSA_DER_BYTE_LEN; + print_field(sec_entry, sec_entry_t, jtag_delay, FMT_DEC, base); + print_field(sec_entry, sec_entry_t, box_id, FMT_HEX, base); + print_field(sec_entry, sec_entry_t, flash_id, FMT_HEX, base); + print_field(sec_entry, sec_entry_t, encrypt_en, FMT_DEC, base); + print_field(sec_entry, sec_entry_t, efuse_dis, FMT_DEC, base); + new_base += 6 * sizeof(uint32_t); + do_print_field(0, "header signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "image signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "CSK keys", new_base, + CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN, FMT_NONE); + new_base += CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN; + do_print_field(0, "CSK block signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "control", new_base, + CP_CTRL_EL_ARRAY_SZ * 2, FMT_NONE); + +} + +void print_bin_ext(ext_header_t *ext_hdr, int base) +{ + fprintf(stdout, "\n########### Binary extension ###########\n"); + base = print_ext_hdr(ext_hdr, base); + do_print_field(0, "binary image", base, ext_hdr->size, FMT_NONE); +} + +int print_extension(void *buf, int base, int count, int ext_size) +{ + ext_header_t *ext_hdr = buf; + int pad = ext_size; + int curr_size; + + while (count--) { + if (ext_hdr->type == EXT_TYPE_BINARY) + print_bin_ext(ext_hdr, base); + else if (ext_hdr->type == EXT_TYPE_SECURITY) + print_sec_ext(ext_hdr, base); + + curr_size = sizeof(ext_header_t) + ext_hdr->size; + base += curr_size; + pad -= curr_size; + ext_hdr = (ext_header_t *)((uintptr_t)ext_hdr + curr_size); + } + + if (pad) + do_print_field(0, "padding", base, pad, FMT_NONE); + + return ext_size; +} + +int parse_image(uint8_t *buf, int size) +{ + int base = 0; + int ret = 1; + header_t *main_hdr; + uint32_t checksum, prolog_checksum; + + + fprintf(stdout, + "################### Prolog Start ######################\n\n"); + main_hdr = (header_t *)buf; + base += print_header(buf, base); + + if (main_hdr->ext_count) + base += print_extension(buf + base, base, + main_hdr->ext_count, + main_hdr->prolog_size - + sizeof(header_t)); + + if (base < main_hdr->prolog_size) { + fprintf(stdout, "\n########### Padding ##############\n"); + do_print_field(0, "prolog padding", + base, main_hdr->prolog_size - base, FMT_HEX); + base = main_hdr->prolog_size; + } + fprintf(stdout, + "\n################### Prolog End ######################\n"); + + fprintf(stdout, + "\n################### Boot image ######################\n"); + + do_print_field(0, "boot image", base, size - base - 4, FMT_NONE); + + fprintf(stdout, + "################### Image end ########################\n"); + + /* Check sanity for certain values */ + printf("\nChecking values:\n"); + + if (main_hdr->magic == MAIN_HDR_MAGIC) { + fprintf(stdout, "Headers magic: OK!\n"); + } else { + fprintf(stderr, + "\n****** ERROR: HEADER MAGIC 0x%08x != 0x%08x\n", + main_hdr->magic, MAIN_HDR_MAGIC); + goto error; + } + + /* headers checksum */ + /* clear the checksum field in header to calculate checksum */ + prolog_checksum = main_hdr->prolog_checksum; + main_hdr->prolog_checksum = 0; + checksum = checksum32((uint32_t *)buf, main_hdr->prolog_size); + + if (checksum == prolog_checksum) { + fprintf(stdout, "Headers checksum: OK!\n"); + } else { + fprintf(stderr, + "\n***** ERROR: BAD HEADER CHECKSUM 0x%08x != 0x%08x\n", + checksum, prolog_checksum); + goto error; + } + + /* boot image checksum */ + checksum = checksum32((uint32_t *)(buf + main_hdr->prolog_size), + main_hdr->boot_image_size); + if (checksum == main_hdr->boot_image_checksum) { + fprintf(stdout, "Image checksum: OK!\n"); + } else { + fprintf(stderr, + "\n****** ERROR: BAD IMAGE CHECKSUM 0x%08x != 0x%08x\n", + checksum, main_hdr->boot_image_checksum); + goto error; + } + +#ifdef CONFIG_MVEBU_SECURE_BOOT + /* RSA signatures */ + if (main_hdr->ext_count) { + uint8_t ext_num = main_hdr->ext_count; + ext_header_t *ext_hdr = (ext_header_t *)(main_hdr + 1); + unsigned char hash[32]; + int i; + + while (ext_num--) { + if (ext_hdr->type == EXT_TYPE_SECURITY) { + sec_entry_t *sec_entry = + (sec_entry_t *)(ext_hdr + 1); + + ret = verify_secure_header_signatures( + main_hdr, sec_entry); + if (ret != 0) { + fprintf(stderr, + "\n****** FAILED TO VERIFY "); + fprintf(stderr, + "RSA SIGNATURES ********\n"); + goto error; + } + + mbedtls_sha256_ret(sec_entry->kak_key, + MAX_RSA_DER_BYTE_LEN, hash, 0); + fprintf(stdout, + ">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n"); + fprintf(stdout, "SHA256: "); + for (i = 0; i < 32; i++) + fprintf(stdout, "%02X", hash[i]); + + fprintf(stdout, + "\n<<<<<<<<< KAK KEY HASH <<<<<<<<<\n"); + + break; + } + ext_hdr = + (ext_header_t *)((uint8_t *)(ext_hdr + 1) + + ext_hdr->size); + } + } +#endif + + ret = 0; +error: + return ret; +} + +int format_bin_ext(char *filename, FILE *out_fd) +{ + ext_header_t header; + FILE *in_fd; + int size, written; + int aligned_size, pad_bytes; + char c; + + in_fd = fopen(filename, "rb"); + if (in_fd == NULL) { + fprintf(stderr, "failed to open bin extension file %s\n", + filename); + return 1; + } + + size = get_file_size(filename); + if (size <= 0) { + fprintf(stderr, "bin extension file size is bad\n"); + return 1; + } + + /* Align extension size to 8 bytes */ + aligned_size = (size + 7) & (~7); + pad_bytes = aligned_size - size; + + header.type = EXT_TYPE_BINARY; + header.offset = 0; + header.size = aligned_size; + header.reserved = 0; + + /* Write header */ + written = fwrite(&header, sizeof(ext_header_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, "failed writing header to extension file\n"); + return 1; + } + + /* Write image */ + while (size--) { + c = getc(in_fd); + fputc(c, out_fd); + } + + while (pad_bytes--) + fputc(0, out_fd); + + fclose(in_fd); + + return 0; +} + +/* **************************************** + * + * Write all extensions (binary, secure + * extensions) to file + * + * ****************************************/ + +int format_extensions(char *ext_filename) +{ + FILE *out_fd; + int ret = 0; + + out_fd = fopen(ext_filename, "wb"); + if (out_fd == NULL) { + fprintf(stderr, "failed to open extension output file %s", + ext_filename); + return 1; + } + + if (strncmp(opts.bin_ext_file, "NA", MAX_FILENAME)) { + if (format_bin_ext(opts.bin_ext_file, out_fd)) { + ret = 1; + goto error; + } + } +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (strncmp(opts.sec_cfg_file, "NA", MAX_FILENAME)) { + if (format_sec_ext(opts.sec_cfg_file, out_fd)) { + ret = 1; + goto error; + } + } +#endif + +error: + fflush(out_fd); + fclose(out_fd); + return ret; +} + +void update_uart(header_t *header) +{ + header->uart_cfg = 0; + header->baudrate = 0; + + if (opts.disable_print) + uart_set_mode(header->uart_cfg, UART_MODE_DISABLE); + + if (opts.baudrate) + header->baudrate = (opts.baudrate / 1200); +} + +/* **************************************** + * + * Write the image prolog, i.e. + * main header and extensions, to file + * + * ****************************************/ + +int write_prolog(int ext_cnt, char *ext_filename, + uint8_t *image_buf, int image_size, FILE *out_fd) +{ + header_t *header; + int main_hdr_size = sizeof(header_t); + int prolog_size = main_hdr_size; + FILE *ext_fd; + char *buf; + int written, read; + int ret = 1; + + + if (ext_cnt) + prolog_size += get_file_size(ext_filename); + + prolog_size = ((prolog_size + PROLOG_ALIGNMENT) & + (~(PROLOG_ALIGNMENT-1))); + + /* Allocate a zeroed buffer to zero the padding bytes */ + buf = calloc(prolog_size, 1); + if (buf == NULL) { + fprintf(stderr, "Error: failed allocating checksum buffer\n"); + return 1; + } + + header = (header_t *)buf; + header->magic = MAIN_HDR_MAGIC; + header->prolog_size = prolog_size; + header->load_addr = opts.load_addr; + header->exec_addr = opts.exec_addr; + header->io_arg_0 = opts.nfc_io_args; + header->ext_count = ext_cnt; + header->aux_flags = 0; + header->boot_image_size = (image_size + 3) & (~0x3); + header->boot_image_checksum = checksum32((uint32_t *)image_buf, + image_size); + + update_uart(header); + + /* Populate buffer with main header and extensions */ + if (ext_cnt) { + ext_fd = fopen(ext_filename, "rb"); + if (ext_fd == NULL) { + fprintf(stderr, + "Error: failed to open extensions file\n"); + goto error; + } + + read = fread(&buf[main_hdr_size], + get_file_size(ext_filename), 1, ext_fd); + if (read != 1) { + fprintf(stderr, + "Error: failed to open extensions file\n"); + goto error; + } + +#ifdef CONFIG_MVEBU_SECURE_BOOT + /* Secure boot mode? */ + if (opts.sec_opts != 0) { + ret = finalize_secure_ext(header, (uint8_t *)buf, + prolog_size, image_buf, + image_size); + if (ret != 0) { + fprintf(stderr, "Error: failed to handle "); + fprintf(stderr, "secure extension!\n"); + goto error; + } + } /* secure boot mode */ +#endif + } + + /* Update the total prolog checksum */ + header->prolog_checksum = checksum32((uint32_t *)buf, prolog_size); + + /* Now spill everything to output file */ + written = fwrite(buf, prolog_size, 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Error: failed to write prolog to output file\n"); + goto error; + } + + ret = 0; + +error: + free(buf); + return ret; +} + +int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd) +{ + int written; + + written = fwrite(buf, image_size, 1, out_fd); + if (written != 1) { + fprintf(stderr, "Error: Failed to write boot image\n"); + goto error; + } + + return 0; +error: + return 1; +} + +int main(int argc, char *argv[]) +{ + char in_file[MAX_FILENAME+1] = { 0 }; + char out_file[MAX_FILENAME+1] = { 0 }; + char ext_file[MAX_FILENAME+1] = { 0 }; + FILE *in_fd = NULL; + FILE *out_fd = NULL; + int parse = 0; + int ext_cnt = 0; + int opt; + int ret = 0; + int image_size, file_size; + uint8_t *image_buf = NULL; + int read; + size_t len; + uint32_t nand_block_size_kb, mlc_nand; + + /* Create temporary file for building extensions + * Use process ID for allowing multiple parallel runs + */ + snprintf(ext_file, MAX_FILENAME, "/tmp/ext_file-%x", getpid()); + + while ((opt = getopt(argc, argv, "hpms:i:l:e:a:b:u:n:t:c:k:")) != -1) { + switch (opt) { + case 'h': + usage(); + break; + case 'l': + opts.load_addr = strtoul(optarg, NULL, 0); + break; + case 'e': + opts.exec_addr = strtoul(optarg, NULL, 0); + break; + case 'm': + opts.disable_print = 1; + break; + case 'u': + opts.baudrate = strtoul(optarg, NULL, 0); + break; + case 'b': + strncpy(opts.bin_ext_file, optarg, MAX_FILENAME); + ext_cnt++; + break; + case 'p': + parse = 1; + break; + case 'n': + nand_block_size_kb = strtoul(optarg, NULL, 0); + opts.nfc_io_args |= (nand_block_size_kb / 64); + break; + case 't': + mlc_nand = 0; + if (!strncmp("MLC", optarg, 3)) + mlc_nand = 1; + opts.nfc_io_args |= (mlc_nand << 8); + break; +#ifdef CONFIG_MVEBU_SECURE_BOOT + case 'c': /* SEC extension */ + strncpy(opts.sec_cfg_file, optarg, MAX_FILENAME); + ext_cnt++; + break; + case 'k': + opts.key_index = strtoul(optarg, NULL, 0); + break; +#endif + default: /* '?' */ + usage_err("Unknown argument"); + exit(EXIT_FAILURE); + } + } + + /* Check validity of inputes */ + if (opts.load_addr % 8) + usage_err("Load address must be 8 bytes aligned"); + + if (opts.baudrate % 1200) + usage_err("Baudrate must be a multiple of 1200"); + + /* The remaining arguments are the input + * and potentially output file + */ + /* Input file must exist so exit if not */ + if (optind >= argc) + usage_err("missing input file name"); + + len = strlen(argv[optind]); + if (len > MAX_FILENAME) + usage_err("file name too long"); + memcpy(in_file, argv[optind], len); + optind++; + + /* Output file must exist in non parse mode */ + if (optind < argc) { + len = strlen(argv[optind]); + if (len > MAX_FILENAME) + usage_err("file name too long"); + memcpy(out_file, argv[optind], len); + } else if (!parse) + usage_err("missing output file name"); + + /* open the input file */ + in_fd = fopen(in_file, "rb"); + if (in_fd == NULL) { + printf("Error: Failed to open input file %s\n", in_file); + goto main_exit; + } + + /* Read the input file to buffer + * Always align the image to 16 byte boundary + */ + file_size = get_file_size(in_file); + image_size = (file_size + AES_BLOCK_SZ - 1) & ~(AES_BLOCK_SZ - 1); + image_buf = calloc(image_size, 1); + if (image_buf == NULL) { + fprintf(stderr, "Error: failed allocating input buffer\n"); + return 1; + } + + read = fread(image_buf, file_size, 1, in_fd); + if (read != 1) { + fprintf(stderr, "Error: failed to read input file\n"); + goto main_exit; + } + + /* Parse the input image and leave */ + if (parse) { + if (opts.key_index >= CSK_ARR_SZ) { + fprintf(stderr, + "Wrong key IDX value. Valid values 0 - %d\n", + CSK_ARR_SZ - 1); + goto main_exit; + } + ret = parse_image(image_buf, image_size); + goto main_exit; + } + + /* Create a blob file from all extensions */ + if (ext_cnt) { + ret = format_extensions(ext_file); + if (ret) + goto main_exit; + } + + out_fd = fopen(out_file, "wb"); + if (out_fd == NULL) { + fprintf(stderr, + "Error: Failed to open output file %s\n", out_file); + goto main_exit; + } + + ret = write_prolog(ext_cnt, ext_file, image_buf, image_size, out_fd); + if (ret) + goto main_exit; + +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (opts.sec_opts && (opts.sec_opts->encrypted_image != 0) && + (opts.sec_opts->enc_image_sz != 0)) { + ret = write_boot_image(opts.sec_opts->encrypted_image, + opts.sec_opts->enc_image_sz, out_fd); + } else +#endif + ret = write_boot_image(image_buf, image_size, out_fd); + if (ret) + goto main_exit; + +main_exit: + if (in_fd) + fclose(in_fd); + + if (out_fd) + fclose(out_fd); + + if (image_buf) + free(image_buf); + + unlink(ext_file); + +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (opts.sec_opts) { + if (opts.sec_opts->encrypted_image) + free(opts.sec_opts->encrypted_image); + free(opts.sec_opts); + } +#endif + exit(ret); +} diff --git a/arm-trusted-firmware/tools/marvell/doimage/doimage.mk b/arm-trusted-firmware/tools/marvell/doimage/doimage.mk new file mode 100644 index 0000000..2b751d4 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/doimage.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +DOIMAGE_FLAGS ?= -l 0x4100000 -e 0x4100000 + + +#NAND params +#Open and update the below when using NAND as a boot device. + +CONFIG_MVEBU_NAND_BLOCK_SIZE := 256 +CONFIG_MVEBU_NAND_CELL_TYPE := SLC +NAND_DOIMAGE_FLAGS := -t $(CONFIG_MVEBU_NAND_CELL_TYPE) -n $(CONFIG_MVEBU_NAND_BLOCK_SIZE) diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/aes_key.txt b/arm-trusted-firmware/tools/marvell/doimage/secure/aes_key.txt new file mode 100644 index 0000000..3e8a888 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/aes_key.txt @@ -0,0 +1 @@ +ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890 diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key new file mode 100644 index 0000000..0840c2a --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAm6jN6o2zQmtyUlvfkfDbSjPJ7Vlpp/KgK/eznoVBBsDIZakX +cIgf8TSLpNVkc+ZE0f/n8X7mEZIyjuSBObLOm9vbkoZcR7DlKUL7RNNOUCv55Ozl +hQwrzpH/uIyIJTvmek29G5wroi0wGbPoxzhelIRTjVCibleBWhYCmZQ6SIRmTY8L +JT8VkX8I/Mhu62DjvxF3BnV6pXuh/FdgDN7MbldzM8Y+GOxVGi5Kcm5WHY7eyMxl +4Y0Yko31Xv7T1PcXahVBIciT+11w+fLc4wQuCJ6GUf9JbzQ0ZllY/FdRG0AhuRMH +zN0jAc/sKrIFoAErED6qlcoQg0vl7gmWN5x+2wIDAQABAoIBACtnPFOkw1FH6I6y +c3qcMGlWW33FKsLb0nGwFfOjsGgTpU1Dgver3UxCnJWPsvzmPlZYBvK9saVAoLxb +VvUhuJ6ZBXar5FtRJfUFak7cpL+SI5IDxFP++tAUwbtR5DyNoUyFFK/4Mep8sybX +lZbHTwgWhb2nuEMQP09BR+RPAplpcitkIoPkhmbGfbt9Hsd25I3bb5Z9R4S/2Rcf +7tmaxndQamij7/pUI7xtd8L6cMESJGIWrgEt/MaT2z8nNPE3EDctDSlH9yKqA2O7 +/LTfrxNDnw5gGRtOgahloThKljVM6pQa4mi91FufD67pHwnKn8urNbt8/3AWg6uU +x4FzZdECgYEA0k2UYzBM+dU6T1bZZ176YI0cZrP1tbf/JwnZGHicQYS7lPLAqgfO +u5oRQzuDimOXaV4xCPBO2nadd6aBxbZTXaglR7GG2uCHX6w2DnOr8/d66YTErTVV +u7/Bf8gMKT9mM4rWPrOEXfXfF0fvcpkBQ+QDynIB37tx/mj2lXRkLx0CgYEAvXuX +Dbe2QgSK0ajrcH7YJyx3RVx9RonOqL4yjCVCELmaDQd307Ef3j+gkd59XIewm+HA +mPyeWEUd8EzH+UvjckfKFuF2I4lEUUWtVZTa7me7mvsFqeEOu5KusD4+Hs+B9Kqd +3Evqcpj2lcMBI519Hvr9BTKfDBcH1EUos6A9rFcCgYAxsyPeTQvj/wBIv72hMFD7 +gF2159GpoFIsZ6dmoRpMYZHzIWtmw3GX5FEwEmCD1AV0YU41TpVUC7QrEq6Yiv4o +pBQrXUkBcQ6NDaW4xJ1eip4Bkd7pEDGyrR6NlDlLhjAg/i6joskla3XNirKL4pzp +7nj23vqSZToLZcLgjyEeAQKBgD5EvDo80j9VwMzvpxecB6qv+S4pG94vcWOQxYm6 +wMBATjjT6HP/9EoUPM9S/32F9er0QFfGRL8bT6Blix4I62Dl6KqmQy2gcXwH2tOS +DHRmUIe40H6oQDAyHwg6HC4B4WInI6N+qzgnvnku0VQD8FdbAgVQQmY1t1PxulN1 +aG8XAoGAPWAr4i8KkVAx4wLlMF8E/ecKcsX1J0+UuKket7Dvk7xJfwtkSLPeV8Bp +HuoHXMM3KYoZ93Hlto5rAT1VQhYuj7heU10v+9UtYTFHgaitptYmxovoCKKiZICl +48aPUI377e5jQ6RhhGYy8ltKsJ80K1T9DIkThJPSS+9NAI+jrmg= +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key new file mode 100644 index 0000000..91d1aeb --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAgwHXB0AaIhT15Z9lHpQ2YT1W8i4oMvvRiLGQCrba5l7BJ03E +ct0x3zagNKZEnpNndT4EAy98ihkhwVlUhxZCparJ2L3JsTs5RgV0wyQkQzwMLM8g +QI5EMmJCgFAVRHmVICOsisGGfNVUHjGdGwPOipyQCsX2MAm3E139VpB7NYj+Q4IR +4kvcb+59LZxKuRJTFKRDIqMGJu98P/ga70+YLXPCBPKSfnZnUppuaI86jF1E6xt8 +o7YtfEPCHDd2LXxKPZ670OapVqwo0t7ZSzEG63NkLp56FXc1OpfC69C8VPiZ8JqW +wxvS/vL8MMCxsBnjSuqnmOAbcNR2GFtUwJOGwwIDAQABAoIBAFcfoiDwQHDp/531 +ownzBzcj0+67Q4Ckd3SwoVp+wJTz7wB0d3DsKX6IlYJuELRk0yjlVUXJDsnIbOpo +vg4Yf7otGo9JqBh1imFGv6AHKRaNmIs0M/66nh/juNYcbAhd0w7MqrKcgRQDyy1J +UXHl1jXYaPLBNDg+PcJjf1dSPp4axzmW2Pk2rXnJCsPcZXL/0YmEvqhfOze0GdjR +hOkbbr6MPPVM66tA00xSwg9XEYJvHtwH6oB0rnANM8ieNK1mtcWkTU5di17CCrjS +ohIhXQrdVpxt549EJoUqEFSgo8OOMm2npDbFrjlukb5euakvMacwoT1te79blSKf +hrTvjgECgYEA0VqoFL0Vqe1qleikYDJ7S5xcv1oruEV31TeuBhDuf0c4PADCnBrV +/RnCEYuXs6wCk60chHg5s0jxg+nGbiY6jRTHkJLRU3ZhDtrtfidEZ78GRzFF3shl +Uzt7dHkKK1ZdiMH4sWzyRLom91TKWMrNKC1AD7v4/zjEXy6phall3ZcCgYEAoDJa +0dIKvVCS6dM2E2kMqi/45mJqsJzFvYL1s4mbma/BAC47bBju/YEse90x+iIi3Gg/ +NoXmNfGPrtgdl+/J/Y6Pohxf/e7gGN71tYVETzgc2Jv09wqmzmTjCmo3wyepyWf+ +pIAE39kdhwnqXVw5xwOG1N3xrQ9TomOO+1QiXbUCgYAF84TJqiJehUA9aLKbhXPZ +z2UXj3GkuFzSs9V/mKWe+qBPnFnr5BtnKX9JzmUOl3ovRoGEBoLlZNJwxIl+ghmx +/wA5TOMkcz4JFRIhPu6D4HtGNNFepuWyewNkaThvyPG5vIHcUVOFvqDy8PcblRBF +7xteFyLZ5nw2lHX/NbSOmwKBgFxLZqPIPcPArkPlGhyow1Ex/lbNkOZcDFkZIHHl +8C3lYm62NCodW2PWjkh2shqInEkcDn9dObsOh1eWz8X/swJQplQhwPROMfJiUnHY +a/iwPX5WrBXAn0X+Pgh8FdBsA5g0QDOKRkSplCd/APX08pzEXWQ60siAMhE3BuOq +H3qZAoGAVnzFidlXuyn+fbNaNVepK9hbuoxHHbzYYWSkpi+73EchN8kXktC+AdEf +owr9TPILbwWWJyisa3wW4xdbMifCgVLTedWZpZ09BENVqC+7g7ksX0pNMGYuFLOh +Td7mFAgmclxG5UiKexajOLjjdnAsJyrDaNKhHn8NQNN6L93N0sE= +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key new file mode 100644 index 0000000..ea47ac5 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAjxTSTh57/5njUpE200+Qb3ySAn8lKeufgaa0K2Xc6Ri7lDZR +ZJ2BPuQZV4lYGqgWUf0IOzNf2WnE2lPfVnLMx08h7NhBqJ83yJVajpr+itnOmW+r +M7h76TFyuna1xz2kw1uhgI5Y4FRnJ4Cg4AexCSyViXSzEN/7LQwxa5z5WGDiNX5N +3/tgjGu+dzSMOiIQhXwIcK/XaiQNm3WHqqnAhPb5Q9IBuuqBfpZoFfH4XmbFWrC8 +neSMMMxX5Ti9pKhLd1EsiaP0aUNQlF8gNWuC/tNaf+OCtwVelVa3sGSRjRFe06VQ +sAE9oyXKri11yD5Dwp1xXivbpOrf7xjUe5gILwIDAQABAoIBABTr94CCxqDucKYP +I9QsSzNyJKuGyfliQdWkea3q3C2ddzhJ5QbwXQjEM8xwAdkMAQ+GD2EQtxBEfgtq +vjqW2MjAEnbefGNavL5w0GgP0+6bwLEA+ii67iuAFoWbfCMhKWmDiY8RwX8z+E13 +ao63sTRlN4x86v4pskG5CbTxpCg+8m7KklLns4SwRGf5gGQcgKRtNSR5nE4g2UNl +dghbDdNlvUncm4zxUcTh0kquhF5Tef5w+6L7W8Hv9Pky3b1c2OK1BMhJlxYrtt69 +/zhIJs89CLx5ACfam+DT/xs0uUiuRQq/e1CCQLCnUO02JqpeN/schtDCd0ZWhbtB +nT7fwTECgYEAx+COhys+7AZI0U+PeuTkI86GUsWHoBislXThxbxyGvMFjgyADZD+ +q/XEGAcxd4eTA1fr0Q9cLuuHZubjGQ7+OIXMZ6arXUsrmMrjRu3kHO+y6K6r4s8j +5bxN/iQ0bymUtJRfJSLI172plszusiPWhCL5+yhYlNoh4mNZJuJnzXkCgYEAt0Gz +07P19YPsxk5ow7ZnSNOMOkkEPP0SuHHWekMIK9KMjiRUSygOAk07zTL7MUoFn9Gy +Prfi0ybFArNhIa4Xio3Fbjfig7rGgaApK4Y3d9A/CGPv/Nj7C2OTepqlEzRLmU9e +Xw5yhbccCydXLyAYFAET2XHsmbewpvHyeYUSoOcCgYBRMJEUrOdhPmhDxZqVo/Zb +6R887gnaaUtpZlHzXUnIUqEWA1PcruIT/b/KttlMIWEBQayDfkbGtFuK3AyxeBqh +4Q+XpucC/W7XIMrTW/yGGIPG6nTdq6B8SFIyAojeArjp5T8Eua11nRAPNm1bJR2V +DRQYBlp9FGIhMJPdLKhXmQKBgGeywSyR0COfBHPu2K+u3uFB/D7bJI/ScS54FHLY +zZ3mpeylOCHTR6IbzDRAng31Ihue0KtW6P6tGJx/nv4tAltAADFvZDlAjqW5WLKt +X2PoLlL0IlBFBEIclc6yBalJVWIqnG9TwJBT3oWdPGOJWLaxKWdJZSZS4J6HmLsV +B0aPAoGAduLsOt8C5z48jPqmJxyPwsmT0Q424FccPMcvGOJ13yxq3xNsfAsbmg9l +L2i/ktE0wCMA+Pm7cuFgxwD7xTr67POZgt9022KsOSonjPsIn24UQeP46vAX/Qtx +Qf3sfvzf57vNy2Hybe38T8RsVOZla+v/QctfSfmb8Y95XL/SZzA= +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key new file mode 100644 index 0000000..e40a864 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAlA/T/5IMTPTu+k5PeesB2oeP80Y6nq0ls8vXLul0TVEJoJ+O +InbPYNqYPu4dbQQg/u8qp8BeXm2ujtJbBTcdn0jKIiDTKYEnlsGfUt9GHnuuzvFh +rORSKuAolUqvo/zcSCo1uykaFvSuyTovSPlwllzSixD9XBbHfn3kXneiIUa45vsJ +AyjTn2qCJt0WgvX42NTxH6Q/OWLeOuKTyRHf25eabucIv77KYy0mlEPq5jjiV5AJ +gl5F1h5G8n07JCIWjkZ2QV4wr+Hv9uGNaSb0WGppBp4CbdQa0eUI75cKzz4WXqds +HZaYiX/a8YC+EUfvqDD02vKREIKFL/1zL53P/wIDAQABAoIBAGzBj5w7oBNrGpr7 +qL9KEyt8xg0Q+gAR+Q6vXRlVXBtquiKk8Jd6I+vlxUz8RNsN3FrGPNPJpse/0yeP +dlJHYNfedLNK3zCucPD4uln6LRw5B3d0sKV5dK2Px9+ZY5iWJQxRDPS0RTi1dCnV +NmRo7P1Vo0WJLkFVbiYIvRVy1MGRfF9ejN41G6U4MoBAQ9WqLp+JasUMTspZI49a +z8tOiJPT94MHBwbKnz8Mcq8sy02LR7U5h82+0T7JoRVix/OXiOoiQExNjZ9yGar0 +wBnl0SL1UW5UUaYzbyNH0mlMXLD+qowbDZM2pBWPfqXK+CMOsL6STIwnns7lY+ZJ +ILbaVmECgYEA2kQXE1PZ25A87a81wCEld402WJ2KegrZC719EWv+xeoS72Ji8uv7 +V0PxVGJQOcG1N+dzJ5tN59SQ/NvVTrjwqNUxQqsygmWq/TcfGb9ONZRmyzcehYLb +m4xTjqJKQ6Kwm5SoaCYmzEb/xaeLwLS9HmR9MdB1dxtDOLpjaK/8qPECgYEArait +QhgaknlxG8pcAimPsEUrLHYWSFRE/MUk4+YvZg/5+YJ8csvY0SO2h0tF/ARwUrdI +DaLEifHm4vqgN03K/0gqj7TKxcNlV16PvVx7Vz97xejdqdHZLDfAo4lcotsgvFQW +zIqoQGGPLf6WhFixZ8mEYj8xnmzLGPvHQmf1h+8CgYEA0LDl917nIN4qw4ARPqDy +t/pXCienrcUNfgIxwSSnNwj2DdjejzI+4VNfPbW6y16BLPCp1CbUOGOwNXTj4R9H +S8Z8ESirZK5c7Tt1CyM1XlmEZ61OC43w+CsWAXz+0OiPQFLFKr+/vPXtvEjUgO7P +HG4sniKZDccNYQIl5oTOaaECgYAPU4u3AZmWw9EPutRT/IcJ75DX47Qjvgw4os2W +r4IPZ+mP88w39XW1P4mkdyg+DcY8BqD9Uxg1dHwEHEp3lw4LabsX48Thn1UaWOYm +uDrKgHfUB7FIg5S/Kkx+ImliliRVerZoZvRiejnAvW9bTtiZaFeetCUU7lUeZ1o2 +qiYpUQKBgHQDfdDhguBGPKpkJ7pVwHkJA/lyRWaN1hwplw4TvX2oH14NsHg5Q5Fd +lHqHFs2Ry/6X3bKgF0E6q4cx0V1Xnnj9sGsemlrHdiSxplDYRQql7X5OeYPGF/Bg +ZTTG8rDwy+ey6EP9BZUb03hISx/LyMynOzjGl6uOcdAcy2d9Vno0 +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key b/arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key new file mode 100644 index 0000000..dfceaba --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAsj2cHcrE2pdyCqNr+oVcQULiRx6RivkrhLl2DTqWXpP33BPm +MP0W0X0z98X7E3kZO+JIGRZ8q+6AWmUpL+53aOGItNeUgT7jQKViPJIo9ZcEnv/n +PJqdgDd4xFhnwYMgq8uVYN9IPfaKDwB3EoOqjNox2JholUVxvLw6W8DAC8La3zwb +0hiqtIlirQOQ/KaTHxC6dPYkrai+jSK5uAX7Vt8RKYg5qfDxSdZckmC2xVKYURhV +bZAlyKki4h6f8CwYCJMQDpHL6mVYCuJ1Ju/OJEXvthDKD0CD2hwILhksdey3qMOC +I5lHSO1b+sTvnVHGs65wI7A+ZYwnadMNvS9e2QIDAQABAoIBAH2uu9q2FEEe8SdX +PNiWGQtbojsL7wzTzj/0lq2VVlqyc+AXmAWLMP/fDTn1vKlqhsSXNseZ96c0sgUL +uBM4T7MA9WivauQH+C6pb6/OUFt8daG4SNGPJOg4NUweGmt1jyAUmeyJBWPL6GXT +qiK//Q78/JECRxyaryyqfWwdak3flzfwONBJ03tQ9EO+L7hf9gAP7OYnAsuNp+Bz +tj1xzNMumYYYiHvsEXx8UTe8HGrmYuO53ZY5fBLGB6Jj7hRlAHNfcdVDvvoBU5cI +Zwi+5YsBuSP2Hr9Gt2Odu+KitH3gFdS0HIiDh44AT+Trj29NMANFDfkDbVHUmE0q +YBL75NECgYEA2E+fJzdaYyyPIcvQgVM8g52hltR5IRgJICND3NOdB/Zb2teBGZh+ +1XJ6ZqQMDcOQZo0CMbX9UNRnf3NU55k48/EEITxCgUJTx/WdfJeTVlWGspt5+U/r +hDnQmkePdU1en63+u9eqsla9+VhLwU3fl/pIOpsBAnoEzs3hMQZ1G0cCgYEA0vHH +ilm3AztIoZlH3wgDAl2Gu5/YopqEofKA8G4Jp89rlkk919P/GNjEc6575wjgztDB +0Xab+H7Nqxjs3HqQX/DTTuAxzAggBg3j/ijpHnmjrCHLeMT5ciyH+EH5Bg///cLq ++Cwn7aOWuSK1hGdDYxUycHylAYZXXFJzmEIEhN8CgYEA1qTrwPZkctTckyS0GiCG +g/P/TLQ6HmTDaWiVBqPVxvjn3RjLuqJf+V5Hp2JRs7bDq39xFfMJExQyP34qWkbp +BOe8uV4agDlY+ar4Q5IFWj40EzfEqWhsxCC6pt0rtbK4mqsFg1BWyfDZQnwjcAXe +QejRk5YMQnDiJHSXaRaHTjECgYAv6ecvD624ODEJM63VhRZZ5TCDUY19caeKuXB8 +LCJZUY3Ydw5rBaY92I7Wz90o3yVhFJ3RnCVVTkgdAu5aLiS5BhSZJ+dntri/Z0xQ +IK7C01JP+OUkq2kVe/Pued28eMnms+13LWBsY+oKZ03foyz1Ro1Ma6N3MzKIr9m9 +zdEE9QKBgECfoh0xE2T/cbJrtH0mwMCUM6eMVGq+yQBKNvuuPg6kaQUsah1n1rp6 +OyvjwRAXdhshszEzNTX1WTT6/i+vZX277Ax50pPo9UhQ9kVteVt1frN6+u5sy07V +fg1f2+m0iFx4BD/irU0fzSyfGE+QkBnmXFBUNSYjp2PSqYIdufmW +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg b/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg new file mode 100644 index 0000000..459f731 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg @@ -0,0 +1,29 @@ +# Trusted boot image extension definitions + +kak_key_file = "tools/doimage/secure/kak_priv_pem.key"; + +# CSK keys array - 16 entries total. +# Only a key with csk_key_index will be used for signing the image +# use "*" string instead of file name for specifying an empty key +csk_key_file = ["tools/doimage/secure/csk_priv_pem0.key", + "tools/doimage/secure/csk_priv_pem1.key", + "tools/doimage/secure/csk_priv_pem2.key", + "tools/doimage/secure/csk_priv_pem3.key", + "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]; + +# index of CSK key in the array. Valid range is 0 to 15 +csk_key_index = 3; + +# AES-256 symmetric key for image encryption +aes_key_file = "tools/doimage/secure/aes_key.txt"; + +efuse_disable = false; +jtag = { enable = true; delay = 20; }; + +box_id = 0xdeadbeef; +flash_id = 0xbaddf00d; + +# SecureBootControl and EfuseBurnControl registers array +# Two register addresses for each connected CP +# A7K - one CP, two register values +control = [0xF2441920, 0xF2441940]; diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg b/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg new file mode 100644 index 0000000..a849dff --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg @@ -0,0 +1,29 @@ +# Trusted boot image extension definitions + +kak_key_file = "tools/doimage/secure/kak_priv_pem.key"; + +# CSK keys array - 16 entries total. +# Only a key with csk_key_index will be used for signing the image +# use "*" string instead of file name for specifying an empty key +csk_key_file = ["tools/doimage/secure/csk_priv_pem0.key", + "tools/doimage/secure/csk_priv_pem1.key", + "tools/doimage/secure/csk_priv_pem2.key", + "tools/doimage/secure/csk_priv_pem3.key", + "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]; + +# index of CSK key in the array. Valid range is 0 to 15 +csk_key_index = 3; + +# AES-256 symmetric key for image encryption +aes_key_file = "tools/doimage/secure/aes_key.txt"; + +efuse_disable = false; +jtag = { enable = true; delay = 20; }; + +box_id = 0xdeadbeef; +flash_id = 0xbaddf00d; + +# SecureBootControl and EfuseBurnControl registers array +# Two register addresses for each connected CP +# A8K - two CP, four register values +control = [0xF2441920, 0xF2441940, 0xF4441920, 0xF4441940]; diff --git a/arm-trusted-firmware/tools/memory/print_memory_map.py b/arm-trusted-firmware/tools/memory/print_memory_map.py new file mode 100755 index 0000000..8a84018 --- /dev/null +++ b/arm-trusted-firmware/tools/memory/print_memory_map.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2019-2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import re +import os +import sys +import operator + +# List of folder/map to parse +bl_images = ['bl1', 'bl2', 'bl31'] + +# List of symbols to search for +blx_symbols = ['__BL1_RAM_START__', '__BL1_RAM_END__', + '__BL2_END__', + '__BL31_END__', + '__TEXT_START__', '__TEXT_END__', + '__RODATA_START__', '__RODATA_END__', + '__DATA_START__', '__DATA_END__', + '__STACKS_START__', '__STACKS_END__', + '__BSS_END', + '__COHERENT_RAM_START__', '__COHERENT_RAM_END__', + ] + +# Regex to extract address from map file +address_pattern = re.compile(r"\b0x\w*") + +# List of found element: [address, symbol, file] +address_list = [] + +# Get the directory from command line or use a default one +inverted_print = True +if len(sys.argv) >= 2: + build_dir = sys.argv[1] + if len(sys.argv) >= 3: + inverted_print = sys.argv[2] == '0' +else: + build_dir = 'build/fvp/debug' + +# Extract all the required symbols from the map files +for image in bl_images: + file_path = os.path.join(build_dir, image, '{}.map'.format(image)) + if os.path.isfile(file_path): + with open (file_path, 'rt') as mapfile: + for line in mapfile: + for symbol in blx_symbols: + # Regex to find symbol definition + line_pattern = re.compile(r"\b0x\w*\s*" + symbol + "\s= .") + match = line_pattern.search(line) + if match: + # Extract address from line + match = address_pattern.search(line) + if match: + address_list.append([match.group(0), symbol, image]) + +# Sort by address +address_list.sort(key=operator.itemgetter(0)) + +# Invert list for lower address at bottom +if inverted_print: + address_list = reversed(address_list) + +# Generate memory view +print('{:-^93}'.format('Memory Map from: ' + build_dir)) +for address in address_list: + if "bl1" in address[2]: + print(address[0], '+{:-^22}+ |{:^22}| |{:^22}|'.format(address[1], '', '')) + elif "bl2" in address[2]: + print(address[0], '|{:^22}| +{:-^22}+ |{:^22}|'.format('', address[1], '')) + elif "bl31" in address[2]: + print(address[0], '|{:^22}| |{:^22}| +{:-^22}+'.format('', '', address[1])) + else: + print(address[0], '|{:^22}| |{:^22}| +{:-^22}+'.format('', '', address[1])) + +print('{:^20}{:_^22} {:_^22} {:_^22}'.format('', '', '', '')) +print('{:^20}{:^22} {:^22} {:^22}'.format('address', 'bl1', 'bl2', 'bl31')) diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/cert_create_tbbr.mk b/arm-trusted-firmware/tools/nxp/cert_create_helper/cert_create_tbbr.mk new file mode 100644 index 0000000..e3b2e91 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/cert_create_tbbr.mk @@ -0,0 +1,31 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Compile time defines used by NXP platforms + +PLAT_DEF_OID := yes + +ifeq (${PLAT_DEF_OID},yes) + +$(eval $(call add_define, PLAT_DEF_OID)) +$(eval $(call add_define, PDEF_KEYS)) +$(eval $(call add_define, PDEF_CERTS)) +$(eval $(call add_define, PDEF_EXTS)) + + +INC_DIR += -I../../plat/nxp/common/fip_handler/common/ + +PDEF_CERT_TOOL_PATH := ../nxp/cert_create_helper +PLAT_INCLUDE += -I${PDEF_CERT_TOOL_PATH}/include + +PLAT_OBJECTS += ${PDEF_CERT_TOOL_PATH}/src/pdef_tbb_cert.o \ + ${PDEF_CERT_TOOL_PATH}/src/pdef_tbb_ext.o \ + ${PDEF_CERT_TOOL_PATH}/src/pdef_tbb_key.o + +$(shell rm ${PLAT_OBJECTS}) + +OBJECTS += ${PLAT_OBJECTS} +endif diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h new file mode 100644 index 0000000..f185619 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h @@ -0,0 +1,21 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PDEF_TBB_CERT_H +#define PDEF_TBB_CERT_H + +#include + +/* + * Enumerate the certificates that are used to establish the chain of trust + */ +enum { + DDR_FW_KEY_CERT = FWU_CERT + 1, + DDR_UDIMM_FW_CONTENT_CERT, + DDR_RDIMM_FW_CONTENT_CERT +}; + +#endif /* PDEF_TBB_CERT_H */ diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h new file mode 100644 index 0000000..5fb349c --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h @@ -0,0 +1,25 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PDEF_TBB_EXT_H +#define PDEF_TBB_EXT_H + +#include + +/* Plat Defined TBBR extensions */ +enum { + DDR_FW_CONTENT_CERT_PK_EXT = FWU_HASH_EXT + 1, + DDR_IMEM_UDIMM_1D_HASH_EXT, + DDR_IMEM_UDIMM_2D_HASH_EXT, + DDR_DMEM_UDIMM_1D_HASH_EXT, + DDR_DMEM_UDIMM_2D_HASH_EXT, + DDR_IMEM_RDIMM_1D_HASH_EXT, + DDR_IMEM_RDIMM_2D_HASH_EXT, + DDR_DMEM_RDIMM_1D_HASH_EXT, + DDR_DMEM_RDIMM_2D_HASH_EXT +}; + +#endif /* PDEF_TBB_EXT_H */ diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h new file mode 100644 index 0000000..b26b651 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h @@ -0,0 +1,18 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PDEF_TBB_KEY_H +#define PDEF_TBB_KEY_H + +#include + +/* + * Enumerate the pltform defined keys that are used to establish the chain of trust + */ +enum { + DDR_FW_CONTENT_KEY = NON_TRUSTED_FW_CONTENT_CERT_KEY + 1, +}; +#endif /* PDEF_TBB_KEY_H */ diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c new file mode 100644 index 0000000..40bd928 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c @@ -0,0 +1,62 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static cert_t pdef_tbb_certs[] = { + [DDR_FW_KEY_CERT - DDR_FW_KEY_CERT] = { + .id = DDR_FW_KEY_CERT, + .opt = "ddr-fw-key-cert", + .help_msg = "DDR Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "DDR Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = DDR_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + DDR_FW_CONTENT_CERT_PK_EXT, + }, + .num_ext = 2 + }, + [DDR_UDIMM_FW_CONTENT_CERT - DDR_FW_KEY_CERT] = { + .id = DDR_UDIMM_FW_CONTENT_CERT, + .opt = "ddr-udimm-fw-cert", + .help_msg = "DDR UDIMM Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "DDR UDIMM Firmware Content Certificate", + .key = DDR_FW_CONTENT_KEY, + .issuer = DDR_UDIMM_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + DDR_IMEM_UDIMM_1D_HASH_EXT, + DDR_IMEM_UDIMM_2D_HASH_EXT, + DDR_DMEM_UDIMM_1D_HASH_EXT, + DDR_DMEM_UDIMM_2D_HASH_EXT, + }, + .num_ext = 5 + }, + [DDR_RDIMM_FW_CONTENT_CERT - DDR_FW_KEY_CERT] = { + .id = DDR_RDIMM_FW_CONTENT_CERT, + .opt = "ddr-rdimm-fw-cert", + .help_msg = "DDR RDIMM Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "DDR RDIMM Firmware Content Certificate", + .key = DDR_FW_CONTENT_KEY, + .issuer = DDR_RDIMM_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + DDR_IMEM_RDIMM_1D_HASH_EXT, + DDR_IMEM_RDIMM_2D_HASH_EXT, + DDR_DMEM_RDIMM_1D_HASH_EXT, + DDR_DMEM_RDIMM_2D_HASH_EXT, + }, + .num_ext = 5 + } +}; + +PLAT_REGISTER_COT(pdef_tbb_certs); diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c new file mode 100644 index 0000000..f6da6dd --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c @@ -0,0 +1,108 @@ +/* + * Copyright 2021 NXP + * + * 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" + +#include +#include + +static ext_t pdef_tbb_ext[] = { + [DDR_FW_CONTENT_CERT_PK_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_FW_CONTENT_CERT_PK_OID, + .sn = "DDR FirmwareContentCertPK", + .ln = "DDR Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = DDR_FW_CONTENT_KEY + }, + [DDR_IMEM_UDIMM_1D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_IMEM_UDIMM_1D_HASH_OID, + .opt = "ddr-immem-udimm-1d", + .help_msg = "DDR Firmware IMEM UDIMM 1D image file", + .sn = "DDR UDIMM IMEM 1D FirmwareHash", + .ln = "DDR UDIMM IMEM 1D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_IMEM_UDIMM_2D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_IMEM_UDIMM_2D_HASH_OID, + .opt = "ddr-immem-udimm-2d", + .help_msg = "DDR Firmware IMEM UDIMM 2D image file", + .sn = "DDR UDIMM IMEM 2D FirmwareHash", + .ln = "DDR UDIMM IMEM 2D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_DMEM_UDIMM_1D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_DMEM_UDIMM_1D_HASH_OID, + .opt = "ddr-dmmem-udimm-1d", + .help_msg = "DDR Firmware DMEM UDIMM 1D image file", + .sn = "DDR UDIMM DMEM 1D FirmwareHash", + .ln = "DDR UDIMM DMEM 1D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_DMEM_UDIMM_2D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_DMEM_UDIMM_2D_HASH_OID, + .opt = "ddr-dmmem-udimm-2d", + .help_msg = "DDR Firmware DMEM UDIMM 2D image file", + .sn = "DDR UDIMM DMEM 2D FirmwareHash", + .ln = "DDR UDIMM DMEM 2D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_IMEM_RDIMM_1D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_IMEM_RDIMM_1D_HASH_OID, + .opt = "ddr-immem-rdimm-1d", + .help_msg = "DDR Firmware IMEM RDIMM 1D image file", + .sn = "DDR RDIMM IMEM 1D FirmwareHash", + .ln = "DDR RDIMM IMEM 1D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_IMEM_RDIMM_2D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_IMEM_RDIMM_2D_HASH_OID, + .opt = "ddr-immem-rdimm-2d", + .help_msg = "DDR Firmware IMEM RDIMM 2D image file", + .sn = "DDR RDIMM IMEM 2D FirmwareHash", + .ln = "DDR RDIMM IMEM 2D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_DMEM_RDIMM_1D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_DMEM_RDIMM_1D_HASH_OID, + .opt = "ddr-dmmem-rdimm-1d", + .help_msg = "DDR Firmware DMEM RDIMM 1D image file", + .sn = "DDR RDIMM DMEM 1D FirmwareHash", + .ln = "DDR RDIMM DMEM 1D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_DMEM_RDIMM_2D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_DMEM_RDIMM_2D_HASH_OID, + .opt = "ddr-dmmem-rdimm-2d", + .help_msg = "DDR Firmware DMEM RDIMM 2D image file", + .sn = "DDR RDIMM DMEM 2D FirmwareHash", + .ln = "DDR RDIMM DMEM 2D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + } +}; + +PLAT_REGISTER_EXTENSIONS(pdef_tbb_ext); diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c new file mode 100644 index 0000000..cf2ebda --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c @@ -0,0 +1,18 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +static key_t pdef_tbb_keys[] = { + [DDR_FW_CONTENT_KEY - DDR_FW_CONTENT_KEY] = { + .id = DDR_FW_CONTENT_KEY, + .opt = "ddr-fw-key", + .help_msg = "DDR Firmware Content Certificate key (input/output file)", + .desc = "DDR Firmware Content Certificate key" + } +}; + +PLAT_REGISTER_KEYS(pdef_tbb_keys); diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/Makefile b/arm-trusted-firmware/tools/nxp/create_pbl/Makefile new file mode 100644 index 0000000..f971a74 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/Makefile @@ -0,0 +1,61 @@ +# +# Copyright 2018-2020 NXP +# +# 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 + +PROJECT_1 := create_pbl${BIN_EXT} +OBJECTS_1 := create_pbl.o +PROJECT_2 := byte_swap${BIN_EXT} +OBJECTS_2 := byte_swap.o +V ?= 0 + +override CPPFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=700 +CFLAGS := -Wall -Werror -pedantic -std=c99 +ifeq (${DEBUG},1) + CFLAGS += -g -O0 -DDEBUG +else + CFLAGS += -O2 +endif +LDLIBS := + +ifeq (${V},0) + Q := @ +else + Q := +endif + +INCLUDE_PATHS := + +HOSTCC ?= gcc +CC = gcc + +.PHONY: all clean distclean + +all: create_pbl byte_swap + +${PROJECT_1}: ${OBJECTS_1} Makefile + @echo " LD $@" + ${Q}${HOSTCC} ${OBJECTS_1} -o $@ ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +${PROJECT_2}: ${OBJECTS_2} Makefile + @echo " LD $@" + ${Q}${HOSTCC} ${OBJECTS_2} -o $@ ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +%.o: %.c %.h Makefile + @echo " CC $<" + ${Q}${HOSTCC} -c ${CPPFLAGS} ${CFLAGS} ${INCLUDE_PATHS} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, ${PROJECT_1} ${OBJECTS_1}) + $(call SHELL_DELETE_ALL, ${PROJECT_2} ${OBJECTS_2}) diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/README b/arm-trusted-firmware/tools/nxp/create_pbl/README new file mode 100644 index 0000000..3b6f854 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/README @@ -0,0 +1,65 @@ +Description: +------------ +Tool 'create_pbl' is a standalone tool to create the PBL images. + where, + On the basis of Chassis, + RCW image is placed first followed by the, + PBI commands to copy the, + Input BL2 image stored on the, + Specified boot source (QSPI or SD or NOR) to the, + Specified destination address. + + +Usage in standalone way: +----------------------- + +./create_pbl [options] (mentioned below): + + -r - name of RCW binary file. + -i - file to be added to rcw file. + -c - SoC numeric identifier, may be one of + 1012,1023,1026.1028, + 1043,1046,1088,2080, + 2088,2160 + -b - Boot source id string, may be one of + "qspi", "nor", "nand", "sd", "emmc" + -d
- Destination address where BL2 + image is to be copied + -o - Name of PBL image generated + as an output of the tool. + -e
- [Optional] Entry Point Address + of the BL2.bin + -f
- BL2 image offset + on Boot Source for block copy. + command for chassis >=3.) + (Must for Ch3, Ignored for Ch2) + -h Help. + -s Secure boot. + + -s secure boot + -c SoC Number (see description above) + -b Boot source. + -r RCW binary file. + -i Input file that is to be added to rcw file. + -o Name of output file + -f Source Offset (Block Copy) + -d Destination address to which file has to be copied + -h Help. + +Example: + ./create_pbl -r -i -c -b -d -o + + + +Usage at compilation time: +-------------------------------- + + make pbl RCW=/ + +Example: QSPI Boot For LS1046ARDB- + + make PLAT=ls1046rdb all fip BOOT_MODE=qspi SPD=opteed BL32=tee.bin BL33=u-boot-ls1046.bin pbl RCW=/home/pankaj/flexbuild/packages/firmware/dash-rcw/ls1046ardb/RR_FFSSPPPN_1133_5506/rcw_1600_qspiboot.bin + +Example: QSPI Boot For LX2160ARDB- + + make PLAT=lx2160ardb all fip BOOT_MODE=flexspi_nor SPD=opteed BL32=tee_lx2.bin BL33=u-boot_lx2160.bin pbl RCW=plat/nxp/soc-lx2160/lx2160ardb/rcw_1900_600_1600_19_5_2.bin diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c b/arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c new file mode 100644 index 0000000..1d0bfce --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c @@ -0,0 +1,113 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include + +#define NUM_MEM_BLOCK 1 +#define FOUR_BYTE_ALIGN 4 +#define EIGHT_BYTE_ALIGN 8 +#define SIZE_TWO_PBL_CMD 24 + +#define SUCCESS 0 +#define FAILURE -1 +#define BYTE_SWAP_32(word) ((((word) & 0xff000000) >> 24)| \ + (((word) & 0x00ff0000) >> 8) | \ + (((word) & 0x0000ff00) << 8) | \ + (((word) & 0x000000ff) << 24)) + + +/* + * Returns: + * SUCCESS, on successful byte swapping. + * FAILURE, on failure. + */ +int do_byteswap(FILE *fp) +{ + int bytes = 0; + uint32_t upper_byte; + uint32_t lower_byte; + uint32_t pad = 0U; + /* Carries number of Padding bytes to be appended to + * make file size 8 byte aligned. + */ + int append_bytes; + int ret = FAILURE; + + fseek(fp, 0L, SEEK_END); + bytes = ftell(fp); + + append_bytes = EIGHT_BYTE_ALIGN - (bytes % EIGHT_BYTE_ALIGN); + if (append_bytes != 0) { + if (fwrite(&pad, append_bytes, NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) { + printf("%s: Error in appending padding bytes.\n", + __func__); + goto byteswap_err; + } + bytes += append_bytes; + } + + rewind(fp); + while (bytes > 0) { + if ((fread(&upper_byte, sizeof(upper_byte), NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) && (feof(fp) == 0)) { + printf("%s: Error reading upper bytes.\n", __func__); + goto byteswap_err; + } + if ((fread(&lower_byte, sizeof(lower_byte), NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) && (feof(fp) == 0)) { + printf("%s: Error reading lower bytes.\n", __func__); + goto byteswap_err; + } + fseek(fp, -8L, SEEK_CUR); + upper_byte = BYTE_SWAP_32(upper_byte); + lower_byte = BYTE_SWAP_32(lower_byte); + if (fwrite(&lower_byte, sizeof(lower_byte), NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) { + printf("%s: Error writing lower bytes.\n", __func__); + goto byteswap_err; + } + if (fwrite(&upper_byte, sizeof(upper_byte), NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) { + printf("%s: Error writing upper bytes.\n", __func__); + goto byteswap_err; + } + bytes -= EIGHT_BYTE_ALIGN; + } + ret = SUCCESS; + +byteswap_err: + return ret; +} + +int main(int argc, char **argv) +{ + FILE *fp = NULL; + int ret = 0; + + if (argc > 2) { + printf("Usage format is byteswap "); + return -1; + } + + fp = fopen(argv[1], "rb+"); + if (fp == NULL) { + printf("%s: Error opening the input file: %s\n", + __func__, argv[1]); + return -1; + } + + ret = do_byteswap(fp); + fclose(fp); + return ret; +} diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c b/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c new file mode 100644 index 0000000..9457a00 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c @@ -0,0 +1,998 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define NUM_MEM_BLOCK 1 +#define FOUR_BYTE_ALIGN 4 +#define EIGHT_BYTE_ALIGN 8 +#define SIZE_TWO_PBL_CMD 24 + +/* Define for add_boot_ptr_cmd() */ +#define BOOTPTR_ADDR 0x09570604 +#define CSF_ADDR_SB 0x09ee0200 +/* CCSR write command to address 0x1e00400 i.e BOOTLOCPTR */ +#define BOOTPTR_ADDR_CH3 0x31e00400 +/* Load CSF header command */ +#define CSF_ADDR_SB_CH3 0x80220000 + +#define MAND_ARG_MASK 0xFFF3 +#define ARG_INIT_MASK 0xFF00 +#define RCW_FILE_NAME_ARG_MASK 0x0080 +#define IN_FILE_NAME_ARG_MASK 0x0040 +#define CHASSIS_ARG_MASK 0x0020 +#define BOOT_SRC_ARG_MASK 0x0010 +#define ENTRY_POINT_ADDR_ARG_MASK 0x0008 +#define BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK 0x0004 +#define BL2_BIN_CPY_DEST_ADDR_ARG_MASK 0x0002 +#define OP_FILE_NAME_ARG_MASK 0x0001 + +/* Define for add_cpy_cmd() */ +#define OFFSET_MASK 0x00ffffff +#define WRITE_CMD_BASE 0x81000000 +#define MAX_PBI_DATA_LEN_BYTE 64 + +/* 140 Bytes = Preamble + LOAD RCW command + RCW (128 bytes) + Checksum */ +#define CHS3_CRC_PAYLOAD_START_OFFSET 140 + +#define PBI_CRC_POLYNOMIAL 0x04c11db7 + +typedef enum { + CHASSIS_UNKNOWN, + CHASSIS_2, + CHASSIS_3, + CHASSIS_3_2, + CHASSIS_MAX /* must be last item in list */ +} chassis_t; + +typedef enum { + UNKNOWN_BOOT = 0, + IFC_NOR_BOOT, + IFC_NAND_BOOT, + QSPI_BOOT, + SD_BOOT, + EMMC_BOOT, + FLXSPI_NOR_BOOT, + FLXSPI_NAND_BOOT, + FLXSPI_NAND4K_BOOT, + MAX_BOOT /* must be last item in list */ +} boot_src_t; + +/* Base Addresses where PBL image is copied depending on the boot source. + * Boot address map varies as per Chassis architecture. + */ +#define BASE_ADDR_UNDEFINED 0xFFFFFFFF +#define BASE_ADDR_QSPI 0x20000000 +#define BASE_ADDR_SD 0x00001000 +#define BASE_ADDR_IFC_NOR 0x30000000 +#define BASE_ADDR_EMMC 0x00001000 +#define BASE_ADDR_FLX_NOR 0x20000000 +#define BASE_ADDR_NAND 0x20000000 + +uint32_t base_addr_ch3[MAX_BOOT] = { + BASE_ADDR_UNDEFINED, + BASE_ADDR_IFC_NOR, + BASE_ADDR_UNDEFINED, /*IFC NAND */ + BASE_ADDR_QSPI, + BASE_ADDR_SD, + BASE_ADDR_EMMC, + BASE_ADDR_UNDEFINED, /*FLXSPI NOR */ + BASE_ADDR_UNDEFINED, /*FLXSPI NAND 2K */ + BASE_ADDR_UNDEFINED /*FLXSPI NAND 4K */ +}; + +uint32_t base_addr_ch32[MAX_BOOT] = { + BASE_ADDR_UNDEFINED, + BASE_ADDR_UNDEFINED, /* IFC NOR */ + BASE_ADDR_UNDEFINED, /* IFC NAND */ + BASE_ADDR_UNDEFINED, /* QSPI */ + BASE_ADDR_SD, + BASE_ADDR_EMMC, + BASE_ADDR_FLX_NOR, + BASE_ADDR_UNDEFINED, /*FLXSPI NAND 2K */ + BASE_ADDR_UNDEFINED /*FLXSPI NAND 4K */ +}; + +/* for Chassis 3 */ +uint32_t blk_cpy_hdr_map_ch3[] = { + + 0, /* Unknown Boot Source */ + 0x80000020, /* NOR_BOOT */ + 0x0, /* NAND_BOOT */ + 0x80000062, /* QSPI_BOOT */ + 0x80000040, /* SD_BOOT */ + 0x80000041, /* EMMC_BOOT */ + 0x0, /* FLEXSPI NOR_BOOT */ + 0x0, /* FLEX SPI NAND2K BOOT */ + 0x0, /* CHASIS3_2_NAND4K_BOOT */ +}; + +uint32_t blk_cpy_hdr_map_ch32[] = { + 0, /* Unknown Boot Source */ + 0x0, /* NOR_BOOT */ + 0x0, /* NAND_BOOT */ + 0x0, /* QSPI_BOOT */ + 0x80000008, /* SD_BOOT */ + 0x80000009, /* EMMC_BOOT */ + 0x8000000F, /* FLEXSPI NOR_BOOT */ + 0x8000000C, /* FLEX SPI NAND2K BOOT */ + 0x8000000D, /* CHASIS3_2_NAND4K_BOOT */ +}; + +char *boot_src_string[] = { + "UNKNOWN_BOOT", + "IFC_NOR_BOOT", + "IFC_NAND_BOOT", + "QSPI_BOOT", + "SD_BOOT", + "EMMC_BOOT", + "FLXSPI_NOR_BOOT", + "FLXSPI_NAND_BOOT", + "FLXSPI_NAND4K_BOOT", +}; + +enum stop_command { + STOP_COMMAND = 0, + CRC_STOP_COMMAND +}; + +/* Structure will get populated in the main function + * as part of parsing the command line arguments. + * All member parameters are mandatory except: + * -ep + * -src_addr + */ +struct pbl_image { + char *rcw_nm; /* Input RCW File */ + char *sec_imgnm; /* Input BL2 binary */ + char *imagefile; /* Generated output file */ + boot_src_t boot_src; /* Boot Source - QSPI, SD, NOR, NAND etc */ + uint32_t src_addr; /* Source Address */ + uint32_t addr; /* Load address */ + uint32_t ep; /* Entry point default is load address */ + chassis_t chassis; /* Chassis type */ +} pblimg; + +#define SUCCESS 0 +#define FAILURE -1 +#define CRC_STOP_CMD_ARM 0x08610040 +#define CRC_STOP_CMD_ARM_CH3 0x808f0000 +#define STOP_CMD_ARM_CH3 0x80ff0000 +#define BYTE_SWAP_32(word) ((((word) & 0xff000000) >> 24)| \ + (((word) & 0x00ff0000) >> 8) | \ + (((word) & 0x0000ff00) << 8) | \ + (((word) & 0x000000ff) << 24)) + +#define PBI_LEN_MASK 0xFFF00000 +#define PBI_LEN_SHIFT 20 +#define NUM_RCW_WORD 35 +#define PBI_LEN_ADD 6 + +#define MAX_CRC_ENTRIES 256 + +/* SoC numeric identifier */ +#define SOC_LS1012 1012 +#define SOC_LS1023 1023 +#define SOC_LS1026 1026 +#define SOC_LS1028 1028 +#define SOC_LS1043 1043 +#define SOC_LS1046 1046 +#define SOC_LS1088 1088 +#define SOC_LS2080 2080 +#define SOC_LS2088 2088 +#define SOC_LX2160 2160 + +static uint32_t pbl_size; +bool sb_flag; + +/*************************************************************************** + * Description : CRC32 Lookup Table + ***************************************************************************/ +static uint32_t crc32_lookup[] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + +static void print_usage(void) +{ + printf("\nCorrect Usage of Tool is:\n"); + printf("\n ./create_pbl [options] (mentioned below):\n\n"); + printf("\t-r - name of RCW binary file.\n"); + printf("\t-i - file to be added to rcw file.\n"); + printf("\t-c - Chassis Architecture (=2 or =3\n"); + printf("\t or =4 for 3.2).\n"); + printf("\t-b - Boot source.\n"); + printf("\t-d
- Destination address where BL2\n"); + printf("\t image is to be copied\n"); + printf("\t-o - Name of PBL image generated\n"); + printf("\t as an output of the tool.\n"); + printf("\t-f
- BL2 image Src Offset\n"); + printf("\t on Boot Source for block copy.\n"); + printf("\t command for chassis >=3.)\n"); + printf("\t-e
- [Optional] Entry Point Address\n"); + printf("\t of the BL2.bin\n"); + printf("\t-s Secure Boot.\n"); + printf("\t-h Help.\n"); + printf("\n\n"); + exit(0); + +} + +/*************************************************************************** + * Function : crypto_calculate_checksum() + * Arguments : data - Pointer to FILE + * num - Number of 32 bit words for checksum + * Return : Checksum Value + * Description : Calculate Checksum over the data + ***************************************************************************/ +uint32_t crypto_calculate_checksum(FILE *fp_rcw_pbi_op, uint32_t num) +{ + uint32_t i; + uint64_t sum = 0; + uint32_t word; + + fseek(fp_rcw_pbi_op, 0L, SEEK_SET); + for (i = 0; i < num ; i++) { + if ((fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_op)) + < NUM_MEM_BLOCK) { + printf("%s: Error reading word.\n", __func__); + return FAILURE; + } + sum = sum + word; + sum = sum & 0xFFFFFFFF; + } + return (uint32_t)sum; +} + +/*************************************************************************** + * Function : add_pbi_stop_cmd + * Arguments : fp_rcw_pbi_op - output rcw_pbi file pointer + * Return : SUCCESS or FAILURE + * Description : This function insert pbi stop command. + ***************************************************************************/ +int add_pbi_stop_cmd(FILE *fp_rcw_pbi_op, enum stop_command flag) +{ + int ret = FAILURE; + int32_t pbi_stop_cmd; + uint32_t pbi_crc = 0xffffffff, i, j, c; + uint32_t crc_table[MAX_CRC_ENTRIES]; + uint8_t data; + + switch (pblimg.chassis) { + case CHASSIS_2: + pbi_stop_cmd = BYTE_SWAP_32(CRC_STOP_CMD_ARM); + break; + case CHASSIS_3: + case CHASSIS_3_2: + /* Based on flag add the corresponsding cmd + * -- stop cmd or stop with CRC cmd + */ + if (flag == CRC_STOP_COMMAND) { + pbi_stop_cmd = CRC_STOP_CMD_ARM_CH3; + } else { + pbi_stop_cmd = STOP_CMD_ARM_CH3; + } + break; + case CHASSIS_UNKNOWN: + case CHASSIS_MAX: + default: + printf("Internal Error: Invalid Chassis val = %d.\n", + pblimg.chassis); + goto pbi_stop_err; + } + + if (fwrite(&pbi_stop_cmd, sizeof(pbi_stop_cmd), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in Writing PBI STOP CMD\n", __func__); + goto pbi_stop_err; + } + + if (flag == CRC_STOP_COMMAND) { + for (i = 0; i < MAX_CRC_ENTRIES; i++) { + c = i << 24; + for (j = 0; j < 8; j++) { + c = (c & 0x80000000) ? + PBI_CRC_POLYNOMIAL ^ (c << 1) : c << 1; + } + + crc_table[i] = c; + } + } + + switch (pblimg.chassis) { + case CHASSIS_2: + /* Chassis 2: CRC is calculated on RCW + PBL cmd.*/ + fseek(fp_rcw_pbi_op, 0L, SEEK_SET); + break; + case CHASSIS_3: + case CHASSIS_3_2: + /* Chassis 3: CRC is calculated on PBL cmd only. */ + fseek(fp_rcw_pbi_op, CHS3_CRC_PAYLOAD_START_OFFSET, SEEK_SET); + break; + case CHASSIS_UNKNOWN: + case CHASSIS_MAX: + printf("%s: Unknown Chassis.\n", __func__); + goto pbi_stop_err; + } + + while ((fread(&data, sizeof(data), NUM_MEM_BLOCK, fp_rcw_pbi_op)) + == NUM_MEM_BLOCK) { + if (flag == CRC_STOP_COMMAND) { + if (pblimg.chassis == CHASSIS_2) { + pbi_crc = crc_table + [((pbi_crc >> 24) ^ (data)) & 0xff] ^ + (pbi_crc << 8); + } else { + pbi_crc = (pbi_crc >> 8) ^ + crc32_lookup[((pbi_crc) ^ + (data)) & 0xff]; + } + } + } + + switch (pblimg.chassis) { + case CHASSIS_2: + pbi_crc = BYTE_SWAP_32(pbi_crc); + break; + case CHASSIS_3: + case CHASSIS_3_2: + if (flag == CRC_STOP_COMMAND) { + pbi_crc = pbi_crc ^ 0xFFFFFFFF; + } else { + pbi_crc = 0x00000000; + } + break; + case CHASSIS_UNKNOWN: + case CHASSIS_MAX: + printf("%s: Unknown Chassis.\n", __func__); + goto pbi_stop_err; + } + + if (fwrite(&pbi_crc, sizeof(pbi_crc), NUM_MEM_BLOCK, fp_rcw_pbi_op) + != NUM_MEM_BLOCK) { + printf("%s: Error in Writing PBI PBI CRC\n", __func__); + goto pbi_stop_err; + } + ret = SUCCESS; + +pbi_stop_err: + return ret; +} + +/* + * Returns: + * File size in bytes, on Success. + * FAILURE, on failure. + */ +int get_filesize(const char *c) +{ + FILE *fp; + int ret = FAILURE; + + fp = fopen(c, "rb"); + if (fp == NULL) { + fprintf(stderr, "%s: Error in opening the file: %s\n", + __func__, c); + goto filesize_err; + } + + fseek(fp, 0L, SEEK_END); + ret = ftell(fp); + fclose(fp); + +filesize_err: + return ret; +} + +/*************************************************************************** + * Function : get_bootptr + * Arguments : fp_rcw_pbi_op - Pointer to output file + * Return : SUCCESS or FAILURE + * Description : Add bootptr pbi command to output file + ***************************************************************************/ +int add_boot_ptr_cmd(FILE *fp_rcw_pbi_op) +{ + uint32_t bootptr_addr; + int ret = FAILURE; + + switch (pblimg.chassis) { + case CHASSIS_2: + if (sb_flag == true) + bootptr_addr = BYTE_SWAP_32(CSF_ADDR_SB); + else + bootptr_addr = BYTE_SWAP_32(BOOTPTR_ADDR); + pblimg.ep = BYTE_SWAP_32(pblimg.ep); + break; + case CHASSIS_3: + case CHASSIS_3_2: + if (sb_flag == true) + bootptr_addr = CSF_ADDR_SB_CH3; + else + bootptr_addr = BOOTPTR_ADDR_CH3; + break; + case CHASSIS_UNKNOWN: + case CHASSIS_MAX: + default: + printf("Internal Error: Invalid Chassis val = %d.\n", + pblimg.chassis); + goto bootptr_err; + } + + if (fwrite(&bootptr_addr, sizeof(bootptr_addr), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in Writing PBI Words:[%d].\n", + __func__, ret); + goto bootptr_err; + } + + if (pblimg.ep != 0) { + if (fwrite(&pblimg.ep, sizeof(pblimg.ep), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in Writing PBI Words\n", __func__); + goto bootptr_err; + } + } + + printf("\nBoot Location Pointer= 0x%x\n", + pblimg.chassis == CHASSIS_2 ? BYTE_SWAP_32(pblimg.ep) : + pblimg.ep); + ret = SUCCESS; + +bootptr_err: + return ret; +} + +/*************************************************************************** + * Function : add_blk_cpy_cmd + * Arguments : pbi_word - pointer to pbi commands + * args - Command line args flag. + * Return : SUCCESS or FAILURE + * Description : Add pbi commands for block copy cmd in pbi_words + ***************************************************************************/ +int add_blk_cpy_cmd(FILE *fp_rcw_pbi_op, uint16_t args) +{ + uint32_t blk_cpy_hdr; + uint32_t file_size, new_file_size; + uint32_t align = 4; + int ret = FAILURE; + int num_pad_bytes = 0; + + if ((args & BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK) == 0) { + printf("ERROR: Offset not specified for Block Copy Cmd.\n"); + printf("\tSee Usage and use -f option\n"); + goto blk_copy_err; + } + + switch (pblimg.chassis) { + case CHASSIS_3: + /* Block copy command */ + blk_cpy_hdr = blk_cpy_hdr_map_ch3[pblimg.boot_src]; + pblimg.src_addr += base_addr_ch3[pblimg.boot_src]; + break; + case CHASSIS_3_2: + /* Block copy command */ + blk_cpy_hdr = blk_cpy_hdr_map_ch32[pblimg.boot_src]; + pblimg.src_addr += base_addr_ch32[pblimg.boot_src]; + break; + default: + printf("%s: Error invalid chassis type for this command.\n", + __func__); + goto blk_copy_err; + } + + file_size = get_filesize(pblimg.sec_imgnm); + if (file_size > 0) { + new_file_size = (file_size + (file_size % align)); + + /* Add Block copy command */ + if (fwrite(&blk_cpy_hdr, sizeof(blk_cpy_hdr), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing blk_cpy_hdr to the file.\n", + __func__); + goto blk_copy_err; + } + + if ((args & BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK) == 0) + num_pad_bytes = pblimg.src_addr % 4; + + /* Add Src address word */ + if (fwrite(&pblimg.src_addr + num_pad_bytes, + sizeof(pblimg.src_addr), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing BLK SRC Addr to the file.\n", + __func__); + goto blk_copy_err; + } + + /* Add Dest address word */ + if (fwrite(&pblimg.addr, sizeof(pblimg.addr), + NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing DST Addr to the file.\n", + __func__); + goto blk_copy_err; + } + + /* Add size */ + if (fwrite(&new_file_size, sizeof(new_file_size), + NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing size to the file.\n", + __func__); + goto blk_copy_err; + } + } + + ret = SUCCESS; + +blk_copy_err: + return ret; +} + +/*************************************************************************** + * Function : add_cpy_cmd + * Arguments : pbi_word - pointer to pbi commands + * Return : SUCCESS or FAILURE + * Description : Append pbi commands for copying BL2 image to the + * load address stored in pbl_image.addr + ***************************************************************************/ +int add_cpy_cmd(FILE *fp_rcw_pbi_op) +{ + uint32_t ALTCBAR_ADDRESS = BYTE_SWAP_32(0x09570158); + uint32_t WAIT_CMD_WRITE_ADDRESS = BYTE_SWAP_32(0x096100c0); + uint32_t WAIT_CMD = BYTE_SWAP_32(0x000FFFFF); + int file_size; + uint32_t pbi_cmd, altcbar; + uint8_t pbi_data[MAX_PBI_DATA_LEN_BYTE]; + uint32_t dst_offset; + FILE *fp_img = NULL; + int ret = FAILURE; + + altcbar = pblimg.addr; + dst_offset = pblimg.addr; + fp_img = fopen(pblimg.sec_imgnm, "rb"); + if (fp_img == NULL) { + printf("%s: Error in opening the file: %s\n", __func__, + pblimg.sec_imgnm); + goto add_cpy_err; + } + file_size = get_filesize(pblimg.sec_imgnm); + altcbar = 0xfff00000 & altcbar; + altcbar = BYTE_SWAP_32(altcbar >> 16); + if (fwrite(&ALTCBAR_ADDRESS, sizeof(ALTCBAR_ADDRESS), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in writing address of ALTCFG CMD.\n", + __func__); + goto add_cpy_err; + } + if (fwrite(&altcbar, sizeof(altcbar), NUM_MEM_BLOCK, fp_rcw_pbi_op) + != NUM_MEM_BLOCK) { + printf("%s: Error in writing ALTCFG CMD.\n", __func__); + goto add_cpy_err; + } + if (fwrite(&WAIT_CMD_WRITE_ADDRESS, sizeof(WAIT_CMD_WRITE_ADDRESS), + NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in writing address of WAIT_CMD.\n", + __func__); + goto add_cpy_err; + } + if (fwrite(&WAIT_CMD, sizeof(WAIT_CMD), NUM_MEM_BLOCK, fp_rcw_pbi_op) + != NUM_MEM_BLOCK) { + printf("%s: Error in writing WAIT_CMD.\n", __func__); + goto add_cpy_err; + } + do { + memset(pbi_data, 0, MAX_PBI_DATA_LEN_BYTE); + + ret = fread(&pbi_data, MAX_PBI_DATA_LEN_BYTE, + NUM_MEM_BLOCK, fp_img); + if ((ret != NUM_MEM_BLOCK) && (!feof(fp_img))) { + printf("%s: Error writing ALTCFG Word: [%d].\n", + __func__, ret); + goto add_cpy_err; + } + + dst_offset &= OFFSET_MASK; + pbi_cmd = WRITE_CMD_BASE | dst_offset; + pbi_cmd = BYTE_SWAP_32(pbi_cmd); + if (fwrite(&pbi_cmd, sizeof(pbi_cmd), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing ALTCFG Word write cmd.\n", + __func__); + goto add_cpy_err; + } + if (fwrite(&pbi_data, MAX_PBI_DATA_LEN_BYTE, NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing ALTCFG_Word.\n", __func__); + goto add_cpy_err; + } + dst_offset += MAX_PBI_DATA_LEN_BYTE; + file_size -= MAX_PBI_DATA_LEN_BYTE; + } while (!feof(fp_img)); + + ret = SUCCESS; + +add_cpy_err: + if (fp_img != NULL) { + fclose(fp_img); + } + return ret; +} + +int main(int argc, char **argv) +{ + FILE *file = NULL; + char *ptr; + int opt; + int tmp; + uint16_t args = ARG_INIT_MASK; + FILE *fp_rcw_pbi_ip = NULL, *fp_rcw_pbi_op = NULL; + uint32_t word, word_1; + int ret = FAILURE; + bool bootptr_flag = false; + enum stop_command flag_stop_cmd = CRC_STOP_COMMAND; + + /* Initializing the global structure to zero. */ + memset(&pblimg, 0x0, sizeof(struct pbl_image)); + + while ((opt = getopt(argc, argv, + ":b:f:r:i:e:d:c:o:h:s")) != -1) { + switch (opt) { + case 'd': + pblimg.addr = strtoull(optarg, &ptr, 16); + if (*ptr != 0) { + fprintf(stderr, "CMD Error: invalid load or destination address %s\n", optarg); + goto exit_main; + } + args |= BL2_BIN_CPY_DEST_ADDR_ARG_MASK; + break; + case 'r': + pblimg.rcw_nm = optarg; + file = fopen(pblimg.rcw_nm, "r"); + if (file == NULL) { + printf("CMD Error: Opening the RCW File.\n"); + goto exit_main; + } else { + args |= RCW_FILE_NAME_ARG_MASK; + fclose(file); + } + break; + case 'e': + bootptr_flag = true; + pblimg.ep = strtoull(optarg, &ptr, 16); + if (*ptr != 0) { + fprintf(stderr, + "CMD Error: Invalid entry point %s\n", optarg); + goto exit_main; + } + break; + case 'h': + print_usage(); + break; + case 'i': + pblimg.sec_imgnm = optarg; + file = fopen(pblimg.sec_imgnm, "r"); + if (file == NULL) { + printf("CMD Error: Opening Input file.\n"); + goto exit_main; + } else { + args |= IN_FILE_NAME_ARG_MASK; + fclose(file); + } + break; + case 'c': + tmp = atoi(optarg); + switch (tmp) { + case SOC_LS1012: + case SOC_LS1023: + case SOC_LS1026: + case SOC_LS1043: + case SOC_LS1046: + pblimg.chassis = CHASSIS_2; + break; + case SOC_LS1088: + case SOC_LS2080: + case SOC_LS2088: + pblimg.chassis = CHASSIS_3; + break; + case SOC_LS1028: + case SOC_LX2160: + pblimg.chassis = CHASSIS_3_2; + break; + default: + printf("CMD Error: Invalid SoC Val = %d.\n", tmp); + goto exit_main; + } + + args |= CHASSIS_ARG_MASK; + break; + case 'o': + pblimg.imagefile = optarg; + args |= OP_FILE_NAME_ARG_MASK; + break; + case 's': + sb_flag = true; + break; + case 'b': + if (strcmp(optarg, "qspi") == 0) { + pblimg.boot_src = QSPI_BOOT; + } else if (strcmp(optarg, "nor") == 0) { + pblimg.boot_src = IFC_NOR_BOOT; + } else if (strcmp(optarg, "nand") == 0) { + pblimg.boot_src = IFC_NAND_BOOT; + } else if (strcmp(optarg, "sd") == 0) { + pblimg.boot_src = SD_BOOT; + } else if (strcmp(optarg, "emmc") == 0) { + pblimg.boot_src = EMMC_BOOT; + } else if (strcmp(optarg, "flexspi_nor") == 0) { + pblimg.boot_src = FLXSPI_NOR_BOOT; + } else if (strcmp(optarg, "flexspi_nand") == 0) { + pblimg.boot_src = FLXSPI_NAND_BOOT; + } else if (strcmp(optarg, "flexspi_nand2k") == 0) { + pblimg.boot_src = FLXSPI_NAND4K_BOOT; + } else { + printf("CMD Error: Invalid boot source.\n"); + goto exit_main; + } + args |= BOOT_SRC_ARG_MASK; + break; + case 'f': + pblimg.src_addr = strtoull(optarg, &ptr, 16); + if (*ptr != 0) { + fprintf(stderr, + "CMD Error: Invalid src offset %s\n", optarg); + goto exit_main; + } + args |= BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK; + break; + default: + /* issue a warning and skip the unknown arg */ + printf("Cmd Warning: Invalid Arg = %c.\n", opt); + } + } + + if ((args & MAND_ARG_MASK) != MAND_ARG_MASK) { + print_usage(); + } + + fp_rcw_pbi_ip = fopen(pblimg.rcw_nm, "rb"); + if (fp_rcw_pbi_ip == NULL) { + printf("%s: Error in opening the rcw file: %s\n", + __func__, pblimg.rcw_nm); + goto exit_main; + } + + fp_rcw_pbi_op = fopen(pblimg.imagefile, "wb+"); + if (fp_rcw_pbi_op == NULL) { + printf("%s: Error opening the input file: %s\n", + __func__, pblimg.imagefile); + goto exit_main; + } + + printf("\nInput Boot Source: %s\n", boot_src_string[pblimg.boot_src]); + printf("Input RCW File: %s\n", pblimg.rcw_nm); + printf("Input BL2 Binary File: %s\n", pblimg.sec_imgnm); + printf("Input load address for BL2 Binary File: 0x%x\n", pblimg.addr); + + printf("Chassis Type: %d\n", pblimg.chassis); + switch (pblimg.chassis) { + case CHASSIS_2: + if (fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_ip) + != NUM_MEM_BLOCK) { + printf("%s: Error in reading word from the rcw file.\n", + __func__); + goto exit_main; + } + while (BYTE_SWAP_32(word) != 0x08610040) { + if (BYTE_SWAP_32(word) == 0x09550000 + || BYTE_SWAP_32(word) == 0x000f400c) { + break; + } + if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: [CH2] Error in Writing PBI Words\n", + __func__); + goto exit_main; + } + if (fread(&word, sizeof(word), NUM_MEM_BLOCK, + fp_rcw_pbi_ip) != NUM_MEM_BLOCK) { + printf("%s: [CH2] Error in Reading PBI Words\n", + __func__); + goto exit_main; + } + } + + if (bootptr_flag == true) { + /* Add command to set boot_loc ptr */ + ret = add_boot_ptr_cmd(fp_rcw_pbi_op); + if (ret != SUCCESS) { + goto exit_main; + } + } + + /* Write acs write commands to output file */ + ret = add_cpy_cmd(fp_rcw_pbi_op); + if (ret != SUCCESS) { + goto exit_main; + } + + /* Add stop command after adding pbi commands + * For Chasis 2.0 platforms it is always CRC & + * Stop command + */ + flag_stop_cmd = CRC_STOP_COMMAND; + ret = add_pbi_stop_cmd(fp_rcw_pbi_op, flag_stop_cmd); + if (ret != SUCCESS) { + goto exit_main; + } + + break; + + case CHASSIS_3: + case CHASSIS_3_2: + if (fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_ip) + != NUM_MEM_BLOCK) { + printf("%s: Error reading PBI Cmd.\n", __func__); + goto exit_main; + } + while (word != 0x808f0000 && word != 0x80ff0000) { + pbl_size++; + /* 11th words in RCW has PBL length. Update it + * with new length. 2 comamnds get added + * Block copy + CCSR Write/CSF header write + */ + if (pbl_size == 11) { + word_1 = (word & PBI_LEN_MASK) + + (PBI_LEN_ADD << 20); + word = word & ~PBI_LEN_MASK; + word = word | word_1; + } + /* Update the CRC command */ + /* Check load command.. + * add a check if command is Stop with CRC + * or stop without checksum + */ + if (pbl_size == 35) { + word = crypto_calculate_checksum(fp_rcw_pbi_op, + NUM_RCW_WORD - 1); + if (word == FAILURE) { + goto exit_main; + } + } + if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: [CH3] Error in Writing PBI Words\n", + __func__); + goto exit_main; + } + if (fread(&word, sizeof(word), NUM_MEM_BLOCK, + fp_rcw_pbi_ip) != NUM_MEM_BLOCK) { + printf("%s: [CH3] Error in Reading PBI Words\n", + __func__); + goto exit_main; + } + + if (word == CRC_STOP_CMD_ARM_CH3) { + flag_stop_cmd = CRC_STOP_COMMAND; + } else if (word == STOP_CMD_ARM_CH3) { + flag_stop_cmd = STOP_COMMAND; + } + } + if (bootptr_flag == true) { + /* Add command to set boot_loc ptr */ + ret = add_boot_ptr_cmd(fp_rcw_pbi_op); + if (ret != SUCCESS) { + printf("%s: add_boot_ptr_cmd return failure.\n", + __func__); + goto exit_main; + } + } + + /* Write acs write commands to output file */ + ret = add_blk_cpy_cmd(fp_rcw_pbi_op, args); + if (ret != SUCCESS) { + printf("%s: Function add_blk_cpy_cmd return failure.\n", + __func__); + goto exit_main; + } + + /* Add stop command after adding pbi commands */ + ret = add_pbi_stop_cmd(fp_rcw_pbi_op, flag_stop_cmd); + if (ret != SUCCESS) { + goto exit_main; + } + + break; + + default: + printf("%s: Unknown chassis type.\n", + __func__); + } + + if (ret == SUCCESS) { + printf("Output file successfully created with name: %s\n\n", + pblimg.imagefile); + } + +exit_main: + if (fp_rcw_pbi_op != NULL) { + fclose(fp_rcw_pbi_op); + } + if (fp_rcw_pbi_ip != NULL) { + fclose(fp_rcw_pbi_ip); + } + + return ret; +} diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.mk b/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.mk new file mode 100644 index 0000000..305c049 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.mk @@ -0,0 +1,52 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT} +BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT} + +HOST_GCC := gcc + +#SWAP is required for Chassis 2 platforms - LS102, ls1043 and ls1046 for QSPI +ifeq (${SOC},ls1046a) +SOC_NUM := 1046a +SWAP = 1 +CH = 2 +else ifeq (${SOC},ls1043a) +SOC_NUM := 1043a +SWAP = 1 +CH = 2 +else ifeq (${SOC},ls1012a) +SOC_NUM := 1012a +SWAP = 1 +CH = 2 +else ifeq (${SOC},ls1088a) +SOC_NUM := 1088a +CH = 3 +else ifeq (${SOC},ls2088a) +SOC_NUM := 2088a +CH = 3 +else ifeq (${SOC},lx2160a) +SOC_NUM := 2160a +CH = 3 +else ifeq (${SOC},ls1028a) +SOC_NUM := 1028a +CH = 3 +else +$(error "Check SOC Not defined in create_pbl.mk.") +endif + +ifeq (${CH},2) + +include ${CREATE_PBL_TOOL_PATH}/pbl_ch2.mk + +endif #CH2 + +ifeq (${CH},3) + +include ${CREATE_PBL_TOOL_PATH}/pbl_ch3.mk + +endif #CH3 diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch2.mk b/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch2.mk new file mode 100644 index 0000000..e6f1d8b --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch2.mk @@ -0,0 +1,60 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT} +BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT} + +HOST_GCC := gcc + +.PHONY: pbl +pbl: ${BUILD_PLAT}/bl2.bin +ifeq ($(SECURE_BOOT),yes) +pbl: ${BUILD_PLAT}/bl2.bin +ifeq ($(RCW),"") + ${Q}echo "Platform ${PLAT} requires rcw file. Please set RCW to point to the right RCW file for boot mode ${BOOT_MODE}" +else + # Generate header for bl2.bin + $(Q)$(CST_DIR)/create_hdr_isbc --in ${BUILD_PLAT}/bl2.bin --out ${BUILD_PLAT}/hdr_bl2 ${BL2_INPUT_FILE} + # Compile create_pbl tool + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${CREATE_PBL_TOOL_PATH};\ + # Add bl2.bin to RCW + ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE}\ + -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl ;\ + # Add header to RCW + ${CREATE_PBL} -r ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -i ${BUILD_PLAT}/hdr_bl2 -b ${BOOT_MODE} -c ${SOC_NUM} \ + -d ${BL2_HDR_LOC} -e ${BL2_HDR_LOC} -o ${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl -s;\ + rm ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl +# Swapping of RCW is required for QSPi Chassis 2 devices +ifeq (${BOOT_MODE}, qspi) +ifeq ($(SWAP),1) + ${Q}echo "Byteswapping RCW for QSPI" + ${BYTE_SWAP} ${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl; +endif # SWAP +endif # BOOT_MODE + cd ${CREATE_PBL_TOOL_PATH}; ${MAKE} clean ; cd -; +endif +else # NON SECURE_BOOT +ifeq ($(RCW),"") + ${Q}echo "Platform ${PLAT} requires rcw file. Please set RCW to point to the right RCW file for boot mode ${BOOT_MODE}" +else + # -a option appends the image for Chassis 3 devices in case of non secure boot + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${CREATE_PBL_TOOL_PATH}; + ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE} \ + -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl ; +# Swapping of RCW is required for QSPi Chassis 2 devices +ifeq (${BOOT_MODE}, qspi) +ifeq ($(SWAP),1) + ${Q}echo "Byteswapping RCW for QSPI" + ${BYTE_SWAP} ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl; +endif # SWAP +endif # BOOT_MODE + cd ${CREATE_PBL_TOOL_PATH}; ${MAKE} clean ; cd -; +endif +endif # SECURE_BOOT + + + diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch3.mk b/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch3.mk new file mode 100644 index 0000000..9283474 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch3.mk @@ -0,0 +1,71 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +SHELL=/bin/bash + +CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT} +BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT} + +HOST_GCC := gcc + +BL2_SRC_OFFSET ?= 0x9000 +BL2_HDR_SRC_OFFSET ?= 0x5000 +bl2_hdr_loc=$(shell echo $$(( $(BL2_HDR_SRC_OFFSET) / 1024 ))) +bl2_loc=$(shell echo $$(( $(BL2_SRC_OFFSET) / 1024 ))) + +.PHONY: pbl +pbl: ${BUILD_PLAT}/bl2.bin +ifeq ($(SECURE_BOOT),yes) +pbl: ${BUILD_PLAT}/bl2.bin +ifeq ($(RCW),"") + ${Q}echo "Platform ${PLAT} requires rcw file. Please set RCW to point to the right RCW file for boot mode ${BOOT_MODE}" +else + # Generate header for bl2.bin + $(Q)$(CST_DIR)/create_hdr_isbc --in ${BUILD_PLAT}/bl2.bin --out ${BUILD_PLAT}/hdr_bl2 ${BL2_INPUT_FILE} + + # Compile create_pbl tool + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${CREATE_PBL_TOOL_PATH};\ + + # Add Block Copy command for bl2.bin to RCW + ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE}\ + -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -f ${BL2_SRC_OFFSET};\ + + # Add Block Copy command and Load CSF header command to RCW + ${CREATE_PBL} -r ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -i ${BUILD_PLAT}/hdr_bl2 -b ${BOOT_MODE} -c ${SOC_NUM} \ + -d ${BL2_HDR_LOC} -e ${BL2_HDR_LOC} -s -f ${BL2_HDR_SRC_OFFSET} \ + -o ${BUILD_PLAT}/rcw_sec.pbl + + # Sign and add "Load Security Header command to PBI commands + $(Q)$(CST_DIR)/create_hdr_pbi --out ${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl --in ${BUILD_PLAT}/rcw_sec.pbl ${PBI_INPUT_FILE} + + # Append the bl2_hdr to the RCW image + @echo "${bl2_hdr_loc}" + dd if=${BUILD_PLAT}/hdr_bl2 of=${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl bs=1K seek=${bl2_hdr_loc} + + # Append the bl2.bin to the RCW image + @echo "${bl2_loc}" + dd if=${BUILD_PLAT}/bl2.bin of=${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl bs=1K seek=${bl2_loc} + + rm ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl + cd ${CREATE_PBL_TOOL_PATH}; ${MAKE} clean ; cd -; +endif +else #SECURE_BOOT +ifeq ($(RCW),"") + ${Q}echo "Platform ${PLAT} requires rcw file. Please set RCW to point to the right RCW file for boot mode ${BOOT_MODE}" +else + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${CREATE_PBL_TOOL_PATH}; + + # Add Block Copy command and populate boot loc ptrfor bl2.bin to RCW + ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE} \ + -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -f ${BL2_SRC_OFFSET}; + + # Append the bl2.bin to the RCW image + @echo "bl2_loc is ${bl2_loc} KB" + dd if=${BUILD_PLAT}/bl2.bin of=${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl bs=1K seek=${bl2_loc} + + cd ${CREATE_PBL_TOOL_PATH}; ${MAKE} clean ; cd -; +endif +endif # SECURE_BOOT diff --git a/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c b/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c new file mode 100644 index 0000000..fdb4b93 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c @@ -0,0 +1,90 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "tbbr_config.h" + +toc_entry_t plat_def_toc_entries[] = { + /* DDR PHY firmwares */ + { + .name = "DDR UDIMM PHY IMEM 1d FW", + .uuid = UUID_DDR_IMEM_UDIMM_1D, + .cmdline_name = "ddr-immem-udimm-1d" + }, + { + .name = "DDR UDIMM PHY IMEM 2d FW", + .uuid = UUID_DDR_IMEM_UDIMM_2D, + .cmdline_name = "ddr-immem-udimm-2d" + }, + { + .name = "DDR UDIMM PHY DMEM 1d FW", + .uuid = UUID_DDR_DMEM_UDIMM_1D, + .cmdline_name = "ddr-dmmem-udimm-1d" + }, + { + .name = "DDR UDIMM PHY DMEM 2d FW", + .uuid = UUID_DDR_DMEM_UDIMM_2D, + .cmdline_name = "ddr-dmmem-udimm-2d" + }, + { + .name = "DDR RDIMM PHY IMEM 1d FW", + .uuid = UUID_DDR_IMEM_RDIMM_1D, + .cmdline_name = "ddr-immem-rdimm-1d" + }, + { + .name = "DDR RDIMM PHY IMEM 2d FW", + .uuid = UUID_DDR_IMEM_RDIMM_2D, + .cmdline_name = "ddr-immem-rdimm-2d" + }, + { + .name = "DDR RDIMM PHY DMEM 1d FW", + .uuid = UUID_DDR_DMEM_RDIMM_1D, + .cmdline_name = "ddr-dmmem-rdimm-1d" + }, + { + .name = "DDR RDIMM PHY DMEM 2d FW", + .uuid = UUID_DDR_DMEM_RDIMM_2D, + .cmdline_name = "ddr-dmmem-rdimm-2d" + }, + { + .name = "FUSE PROV FW", + .uuid = UUID_FUSE_PROV, + .cmdline_name = "fuse-prov" + }, + { + .name = "FUSE UPGRADE FW", + .uuid = UUID_FUSE_UP, + .cmdline_name = "fuse-upgrade" + }, + + /* Key Certificates */ + { + .name = "DDR Firmware key certificate", + .uuid = UUID_DDR_FW_KEY_CERT, + .cmdline_name = "ddr-fw-key-cert" + }, + + /* Content certificates */ + { + .name = "DDR UDIMM Firmware content certificate", + .uuid = UUID_DDR_UDIMM_FW_CONTENT_CERT, + .cmdline_name = "ddr-udimm-fw-cert" + }, + { + .name = "DDR RDIMM Firmware content certificate", + .uuid = UUID_DDR_RDIMM_FW_CONTENT_CERT, + .cmdline_name = "ddr-rdimm-fw-cert" + }, + + { + .name = NULL, + .uuid = { {0} }, + .cmdline_name = NULL, + } +}; diff --git a/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_fiptool.mk b/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_fiptool.mk new file mode 100644 index 0000000..ca2962a --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_fiptool.mk @@ -0,0 +1,33 @@ +# +# Copyright (c) 2021, NXP. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Name of the platform defined source file name, +# which contains platform defined UUID entries populated +# in the plat_def_toc_entries[]. +PLAT_DEF_UUID_CONFIG_FILE_NAME := plat_def_uuid_config + +PLAT_DEF_UUID_CONFIG_FILE_PATH := ../nxp/plat_fiptool + +PLAT_DEF_OID := yes +PLAT_DEF_UUID := yes +PLAT_DEF_UUID_OID_CONFIG_PATH := ../../plat/nxp/common/fip_handler/common + + +INCLUDE_PATHS += -I${PLAT_DEF_UUID_OID_CONFIG_PATH} \ + -I./ +# Clean the stale object file. +$(shell rm ${PLAT_DEF_UUID_CONFIG_FILE_PATH}/${PLAT_DEF_UUID_CONFIG_FILE_NAME}.o) + +ifeq (${PLAT_DEF_OID},yes) +HOSTCCFLAGS += -DPLAT_DEF_OID +endif + +ifeq (${PLAT_DEF_UUID},yes) +HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID +PLAT_OBJECTS += ${PLAT_DEF_UUID_CONFIG_FILE_PATH}/${PLAT_DEF_UUID_CONFIG_FILE_NAME}.o +endif + +OBJECTS += ${PLAT_OBJECTS} diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile b/arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile new file mode 100644 index 0000000..d585754 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile @@ -0,0 +1,121 @@ +# +# Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +################################################### +# makefile +################################################### + +#output file name +FILE_NAME_SA0 = bootparam_sa0 +FILE_NAME_SA6 = cert_header_sa6 + +OUTPUT_FILE_SA0 = $(FILE_NAME_SA0).elf +OUTPUT_FILE_SA6 = $(FILE_NAME_SA6).elf + +#object file name +OBJ_FILE_SA0 = sa0.o +OBJ_FILE_SA6 = sa6.o + +#linker script name +MEMORY_DEF_SA0 = sa0.ld.S +MEMORY_DEF_SA6 = sa6.ld.S + +################################################### +# 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 + +# Process RCAR_SA0_SIZE flag +ifndef RCAR_SA0_SIZE +RCAR_SA0_SIZE := 1 +else +ifeq (${RCAR_SA0_SIZE},0) +RCAR_SA0_SIZE := 0 +else +RCAR_SA0_SIZE := 1 +endif +endif +$(eval $(call add_define,RCAR_SA0_SIZE)) + +# Process RCAR_SA6_TYPE flag +ifndef RCAR_SA6_TYPE +RCAR_SA6_TYPE := 0 +else +ifeq (${RCAR_SA6_TYPE},0) +RCAR_SA6_TYPE := 0 +else +RCAR_SA6_TYPE := 1 +endif +endif +$(eval $(call add_define,RCAR_SA6_TYPE)) + +# Handle different VMA adjustment on D3 +ifeq (${RCAR_LSI},${RCAR_D3}) +RCAR_VMA_ADJUST_ADDR := 0xE6320000 +else +RCAR_VMA_ADJUST_ADDR := 0xE6312000 +endif +$(eval $(call add_define,RCAR_VMA_ADJUST_ADDR)) + + +################################################### + +#c compiler +CC = $(CROSS_COMPILE)gcc +CFLAGS += ${DEFINES} +CFLAGS += -I../../include/lib/stdlib + +#Linker +LD = $(CROSS_COMPILE)ld + +#objcopy +objcopy = $(CROSS_COMPILE)objcopy + +#clean +CL = rm -f + +################################################### +.SUFFIXES : .s .c .o + +################################################### +# command + +.PHONY: all +all: $(OUTPUT_FILE_SA0) $(OUTPUT_FILE_SA6) +################################################### +# Linker +################################################### +$(OUTPUT_FILE_SA0) : $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0) + $(LD) $(OBJ_FILE_SA0) \ + -T $(MEMORY_DEF_SA0) \ + -o $(OUTPUT_FILE_SA0) \ + -Map $(FILE_NAME_SA0).map \ + + $(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec + $(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin + +$(OUTPUT_FILE_SA6) : $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6) + $(LD) $(OBJ_FILE_SA6) \ + -T $(MEMORY_DEF_SA6) \ + -o $(OUTPUT_FILE_SA6) \ + -Map $(FILE_NAME_SA6).map \ + + $(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec + $(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin + +################################################### +# Compile +################################################### + +%.o:../%.c + $(CC) -c -I $< -o $@ + +.PHONY: clean +clean: + $(CL) *.bin *.map *.srec *.elf *.o diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c new file mode 100644 index 0000000..79354ec --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define RCAR_SA0_SIZE_SMALL (0) /* for E3/D3 */ +#define RCAR_SA0_SIZE_NORMAL (1) /* for H3/M3/M3N */ + +#define BL2_ADDRESS (0xE6304000) /* BL2 start address */ + +#if (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) +#define BL2_SIZE (80*1024/4) /* BL2 size is 80KB(0x00005000) */ +#else /* (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) */ +#define BL2_SIZE (170*1024/4) /* BL2 size is 170KB(0x0000AA00) */ +#endif /* (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) */ + +/* SA0 */ +/* 0x00000000 */ +const unsigned int __attribute__ ((section (".sa0_bootrom"))) bootrom_paramA = 0x00000100; +/* 0x00000080 (Map Type 3 for eMMC Boot)*/ +/* 0x000001D4 */ +const unsigned int __attribute__ ((section (".sa0_bl2dst_addr3"))) bl2dst_addr3 = BL2_ADDRESS; +/* 0x000002E4 */ +const unsigned int __attribute__ ((section (".sa0_bl2dst_size3"))) bl2dst_size3 = BL2_SIZE; +/* 0x00000C00 (Map Type 1 for HyperFlash/QSPI Flash Boot)*/ +/* 0x00000D54 */ +const unsigned int __attribute__ ((section (".sa0_bl2dst_addr1"))) bl2dst_addr1 = BL2_ADDRESS; +/* 0x00000E64 */ +const unsigned int __attribute__ ((section (".sa0_bl2dst_size1"))) bl2dst_size1 = BL2_SIZE; diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S new file mode 100644 index 0000000..98fee23 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +SECTIONS +{ + . = 0x00000000; + .rodata : { + KEEP(*(.sa0_bootrom)) + /* Map Type 3 for eMMC Boot */ + /* A-side IPL content cert "Start Address" */ + . = 0x000001D4; /* H'00000080 + H'00000154 */ + KEEP(*(.sa0_bl2dst_addr3)) + /* A-side IPL content cert "Size" */ + . = 0x000002E4; /* H'00000080 + H'00000264 */ + KEEP(*(.sa0_bl2dst_size3)) + /* Map Type 1 for HyperFlash/QSPI Flash Boot */ + /* A-side IPL content cert "Start Address" */ + . = 0x00000D54; /* H'00000C00 + H'00000154 */ + KEEP(*(.sa0_bl2dst_addr1)) + /* A-side IPL content cert "Size" */ + . = 0x00000E64; /* H'00000C00 + H'00000264 */ + KEEP(*(.sa0_bl2dst_size1)) + } + +} diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c new file mode 100644 index 0000000..8fafdad --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#define RCAR_SA6_TYPE_HYPERFLASH (0) +#define RCAR_SA6_TYPE_EMMC (1) + +#if (RCAR_SA6_TYPE == RCAR_SA6_TYPE_HYPERFLASH) + +/* Number of content cert for Non-secure Target Program(BL33x) */ +#define RCAR_IMAGE_NUM (0x00000001U) +/* Source address on flash for BL31 */ +#define RCAR_BL31SRC_ADDRESS (0x001C0000U) +/* Reserved */ +#define RCAR_BL31_PARTITION (0x00000000U) +/* Source address on flash for BL32 */ +#define RCAR_BL32SRC_ADDRESS (0x00200000U) +/* Reserved */ +#define RCAR_BL32_PARTITION (0x00000000U) +/* Source address on flash for BL33 */ +#define RCAR_BL33SRC_ADDRESS (0x00640000U) +/* Reserved */ +#define RCAR_BL33_PARTITION (0x00000000U) +#define RCAR_BL332SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL332_PARTITION (0x00000000U) +#define RCAR_BL333SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL333_PARTITION (0x00000000U) +#define RCAR_BL334SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL334_PARTITION (0x00000000U) +#define RCAR_BL335SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL335_PARTITION (0x00000000U) +#define RCAR_BL336SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL336_PARTITION (0x00000000U) +#define RCAR_BL337SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL337_PARTITION (0x00000000U) +#define RCAR_BL338SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL338_PARTITION (0x00000000U) + +#else /* RCAR_SA6_TYPE == RCAR_SA6_TYPE_HYPERFLASH */ + +/* Number of content cert for Non-secure Target Program(BL33x) */ +#define RCAR_IMAGE_NUM (0x00000001U) +/* Source address on eMMC for BL31 */ +#define RCAR_BL31SRC_ADDRESS (0x00040000U) +/* Source partition on eMMC for BL31 */ +#define RCAR_BL31_PARTITION (0x00000001U) +/* Source address on eMMC for BL32 */ +#define RCAR_BL32SRC_ADDRESS (0x00200000U) +/* Source partition on eMMC for BL32 */ +#define RCAR_BL32_PARTITION (0x00000001U) +/* Source address on eMMC for BL33 */ +#define RCAR_BL33SRC_ADDRESS (0x00000000U) +/* Source partition on eMMC for BL33 */ +#define RCAR_BL33_PARTITION (0x00000002U) +/* Reserved */ +#define RCAR_BL332SRC_ADDRESS (0x00000000U) +#define RCAR_BL332_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL333SRC_ADDRESS (0x00000000U) +#define RCAR_BL333_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL334SRC_ADDRESS (0x00000000U) +#define RCAR_BL334_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL335SRC_ADDRESS (0x00000000U) +#define RCAR_BL335_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL336SRC_ADDRESS (0x00000000U) +#define RCAR_BL336_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL337SRC_ADDRESS (0x00000000U) +#define RCAR_BL337_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL338SRC_ADDRESS (0x00000000U) +#define RCAR_BL338_PARTITION (0x00000000U) + +#endif /* RCAR_SA6_TYPE == RCAR_SA6_TYPE_HYPERFLASH */ + +/* Destination address for BL31 */ +#define RCAR_BL31DST_ADDRESS (0x44000000U) +#define RCAR_BL31DST_ADDRESSH (0x00000000U) +/* Destination size for BL31 */ +#define RCAR_BL31DST_SIZE (0x00004000U) +/* Destination address for BL32 */ +#define RCAR_BL32DST_ADDRESS (0x44100000U) +#define RCAR_BL32DST_ADDRESSH (0x00000000U) +/* Destination size for BL32 */ +#define RCAR_BL32DST_SIZE (0x00080000U) +/* Destination address for BL33 */ +#define RCAR_BL33DST_ADDRESS (0x50000000U) +#define RCAR_BL33DST_ADDRESSH (0x00000000U) +/* Destination size for BL33 */ +#define RCAR_BL33DST_SIZE (0x00040000U) +/* Reserved */ +#define RCAR_BL332DST_ADDRESS (0x00000000U) +#define RCAR_BL332DST_ADDRESSH (0x00000000U) +#define RCAR_BL332DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL333DST_ADDRESS (0x00000000U) +#define RCAR_BL333DST_ADDRESSH (0x00000000U) +#define RCAR_BL333DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL334DST_ADDRESS (0x00000000U) +#define RCAR_BL334DST_ADDRESSH (0x00000000U) +#define RCAR_BL334DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL335DST_ADDRESS (0x00000000U) +#define RCAR_BL335DST_ADDRESSH (0x00000000U) +#define RCAR_BL335DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL336DST_ADDRESS (0x00000000U) +#define RCAR_BL336DST_ADDRESSH (0x00000000U) +#define RCAR_BL336DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL337DST_ADDRESS (0x00000000U) +#define RCAR_BL337DST_ADDRESSH (0x00000000U) +#define RCAR_BL337DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL338DST_ADDRESS (0x00000000U) +#define RCAR_BL338DST_ADDRESSH (0x00000000U) +#define RCAR_BL338DST_SIZE (0x00000000U) + +/* SA6 */ +const uint64_t __attribute__ ((section (".sa6_image_num"))) image_num = RCAR_IMAGE_NUM; +const uint64_t __attribute__ ((section (".sa6_bl31src_addr"))) bl31src_addr = RCAR_BL31SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl31partition"))) bl31partition = RCAR_BL31_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl32src_addr"))) bl32src_addr = RCAR_BL32SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl32partition"))) bl32partition = RCAR_BL32_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl33src_addr"))) bl33src_addr = RCAR_BL33SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl33partition"))) bl33partition = RCAR_BL33_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl332src_addr"))) bl332src_addr = RCAR_BL332SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl332partition")))bl332partition = RCAR_BL332_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl333src_addr"))) bl333src_addr = RCAR_BL333SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl333partition")))bl333partition = RCAR_BL333_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl334src_addr"))) bl334src_addr = RCAR_BL334SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl334partition")))bl334partition = RCAR_BL334_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl335src_addr"))) bl335src_addr = RCAR_BL335SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl335partition")))bl335partition = RCAR_BL335_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl336src_addr"))) bl336src_addr = RCAR_BL336SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl336partition")))bl336partition = RCAR_BL336_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl337src_addr"))) bl337src_addr = RCAR_BL337SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl337partition")))bl337partition = RCAR_BL337_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl338src_addr"))) bl338src_addr = RCAR_BL338SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl338partition")))bl338partition = RCAR_BL338_PARTITION; +const uint32_t __attribute__ ((section (".sa6_bl31dst_addr"))) bl31dst_addr = RCAR_BL31DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl31dst_addrh"))) bl31dst_addrh = RCAR_BL31DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl31dst_size"))) bl31dst_size = RCAR_BL31DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl32dst_addr"))) bl32dst_addr = RCAR_BL32DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl32dst_addrh"))) bl32dst_addrh = RCAR_BL32DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl32dst_size"))) bl32dst_size = RCAR_BL32DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl33dst_addr"))) bl33dst_addr = RCAR_BL33DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl33dst_addrh"))) bl33dst_addrh = RCAR_BL33DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl33dst_size"))) bl33dst_size = RCAR_BL33DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl332dst_addr"))) bl332dst_addr = RCAR_BL332DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl332dst_addrh")))bl332dst_addrh = RCAR_BL332DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl332dst_size"))) bl332dst_size = RCAR_BL332DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl333dst_addr"))) bl333dst_addr = RCAR_BL333DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl333dst_addrh")))bl333dst_addrh = RCAR_BL333DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl333dst_size"))) bl333dst_size = RCAR_BL333DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl334dst_addr"))) bl334dst_addr = RCAR_BL334DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl334dst_addrh")))bl334dst_addrh = RCAR_BL334DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl334dst_size"))) bl334dst_size = RCAR_BL334DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl335dst_addr"))) bl335dst_addr = RCAR_BL335DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl335dst_addrh")))bl335dst_addrh = RCAR_BL335DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl335dst_size"))) bl335dst_size = RCAR_BL335DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl336dst_addr"))) bl336dst_addr = RCAR_BL336DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl336dst_addrh")))bl336dst_addrh = RCAR_BL336DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl336dst_size"))) bl336dst_size = RCAR_BL336DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl337dst_addr"))) bl337dst_addr = RCAR_BL337DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl337dst_addrh")))bl337dst_addrh = RCAR_BL337DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl337dst_size"))) bl337dst_size = RCAR_BL337DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl338dst_addr"))) bl338dst_addr = RCAR_BL338DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl338dst_addrh")))bl338dst_addrh = RCAR_BL338DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl338dst_size"))) bl338dst_size = RCAR_BL338DST_SIZE; diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S new file mode 100644 index 0000000..9ca0c1d --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +SECTIONS +{ + . = 0x00000000; + .rodata : { + KEEP(*(.sa6_image_num)) + . = 0x00000008; + KEEP(*(.sa6_bl31src_addr)) + . = 0x00000010; + KEEP(*(.sa6_bl31partition)) + . = 0x00000018; + KEEP(*(.sa6_bl32src_addr)) + . = 0x00000020; + KEEP(*(.sa6_bl32partition)) + . = 0x00000028; + KEEP(*(.sa6_bl33src_addr)) + . = 0x00000030; + KEEP(*(.sa6_bl33partition)) + . = 0x00000038; + KEEP(*(.sa6_bl332src_addr)) + . = 0x00000040; + KEEP(*(.sa6_bl332partition)) + . = 0x00000048; + KEEP(*(.sa6_bl333src_addr)) + . = 0x00000050; + KEEP(*(.sa6_bl333partition)) + . = 0x00000058; + KEEP(*(.sa6_bl334src_addr)) + . = 0x00000060; + KEEP(*(.sa6_bl334partition)) + . = 0x00000068; + KEEP(*(.sa6_bl335src_addr)) + . = 0x00000070; + KEEP(*(.sa6_bl335partition)) + . = 0x00000078; + KEEP(*(.sa6_bl336src_addr)) + . = 0x00000080; + KEEP(*(.sa6_bl336partition)) + . = 0x00000088; + KEEP(*(.sa6_bl337src_addr)) + . = 0x00000090; + KEEP(*(.sa6_bl337partition)) + . = 0x00000098; + KEEP(*(.sa6_bl338src_addr)) + . = 0x000000A0; + KEEP(*(.sa6_bl338partition)) + . = 0x00000554; + KEEP(*(.sa6_bl31dst_addr)) + . = 0x00000558; + KEEP(*(.sa6_bl31dst_addrh)) + . = 0x00000664; + KEEP(*(.sa6_bl31dst_size)) + . = 0x00000D54; + KEEP(*(.sa6_bl32dst_addr)) + . = 0x00000D58; + KEEP(*(.sa6_bl32dst_addrh)) + . = 0x00000E64; + KEEP(*(.sa6_bl32dst_size)) + . = 0x00001554; + KEEP(*(.sa6_bl33dst_addr)) + . = 0x00001558; + KEEP(*(.sa6_bl33dst_addrh)) + . = 0x00001664; + KEEP(*(.sa6_bl33dst_size)) + . = 0x00001D54; + KEEP(*(.sa6_bl332dst_addr)) + . = 0x00001D58; + KEEP(*(.sa6_bl332dst_addrh)) + . = 0x00001E64; + KEEP(*(.sa6_bl332dst_size)) + . = 0x00002554; + KEEP(*(.sa6_bl333dst_addr)) + . = 0x00002558; + KEEP(*(.sa6_bl333dst_addrh)) + . = 0x00002664; + KEEP(*(.sa6_bl333dst_size)) + . = 0x00002D54; + KEEP(*(.sa6_bl334dst_addr)) + . = 0x00002D58; + KEEP(*(.sa6_bl334dst_addrh)) + . = 0x00002E64; + KEEP(*(.sa6_bl334dst_size)) + . = 0x00003554; + KEEP(*(.sa6_bl335dst_addr)) + . = 0x00003558; + KEEP(*(.sa6_bl335dst_addrh)) + . = 0x00003664; + KEEP(*(.sa6_bl335dst_size)) + . = 0x00003D54; + KEEP(*(.sa6_bl336dst_addr)) + . = 0x00003D58; + KEEP(*(.sa6_bl336dst_addrh)) + . = 0x00003E64; + KEEP(*(.sa6_bl336dst_size)) + . = 0x00004554; + KEEP(*(.sa6_bl337dst_addr)) + . = 0x00004558; + KEEP(*(.sa6_bl337dst_addrh)) + . = 0x00004664; + KEEP(*(.sa6_bl337dst_size)) + . = 0x00004D54; + KEEP(*(.sa6_bl338dst_addr)) + . = 0x00004D58; + KEEP(*(.sa6_bl338dst_addrh)) + . = 0x00004E64; + KEEP(*(.sa6_bl338dst_size)) + } + +} diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile b/arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile new file mode 100644 index 0000000..2d438b9 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile @@ -0,0 +1,118 @@ +# +# Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +################################################### +# makefile +################################################### + +#output file name +FILE_NAME_SA0 = bootparam_sa0 +FILE_NAME_SA6 = cert_header_sa6 + +OUTPUT_FILE_SA0 = $(FILE_NAME_SA0).elf +OUTPUT_FILE_SA6 = $(FILE_NAME_SA6).elf + +#object file name +OBJ_FILE_SA0 = sa0.o +OBJ_FILE_SA6 = sa6.o + +#linker script name +MEMORY_DEF_SA0 = sa0.ld.S +MEMORY_DEF_SA6 = sa6.ld.S + +################################################### +# 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 + +# Process RCAR_SA0_SIZE flag +ifndef RCAR_SA0_SIZE +RCAR_SA0_SIZE := 1 +else +ifeq (${RCAR_SA0_SIZE},0) +RCAR_SA0_SIZE := 0 +else +RCAR_SA0_SIZE := 1 +endif +endif +$(eval $(call add_define,RCAR_SA0_SIZE)) + +# Process RCAR_SA6_TYPE flag +ifndef RCAR_SA6_TYPE +RCAR_SA6_TYPE := 0 +else +ifeq (${RCAR_SA6_TYPE},0) +RCAR_SA6_TYPE := 0 +else +RCAR_SA6_TYPE := 1 +endif +endif +$(eval $(call add_define,RCAR_SA6_TYPE)) + +RCAR_VMA_ADJUST_ADDR := 0xE6320000 +$(eval $(call add_define,RCAR_VMA_ADJUST_ADDR)) + + +################################################### + +#c compiler +CC = $(CROSS_COMPILE)gcc +CFLAGS += ${DEFINES} +CFLAGS += -nostdinc \ + -I../../../include/lib/libc \ + -I../../../include/lib/libc/aarch64 + +#Linker +LD = $(CROSS_COMPILE)ld + +#objcopy +objcopy = $(CROSS_COMPILE)objcopy + +#clean +CL = rm -f + +################################################### +.SUFFIXES : .s .c .o + +################################################### +# command + +.PHONY: all +all: $(OUTPUT_FILE_SA0) $(OUTPUT_FILE_SA6) +################################################### +# Linker +################################################### +$(OUTPUT_FILE_SA0) : $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0) + $(LD) $(OBJ_FILE_SA0) \ + -T $(MEMORY_DEF_SA0) \ + -o $(OUTPUT_FILE_SA0) \ + -Map $(FILE_NAME_SA0).map \ + + $(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec + $(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin + +$(OUTPUT_FILE_SA6) : $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6) + $(LD) $(OBJ_FILE_SA6) \ + -T $(MEMORY_DEF_SA6) \ + -o $(OUTPUT_FILE_SA6) \ + -Map $(FILE_NAME_SA6).map \ + + $(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec + $(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin + +################################################### +# Compile +################################################### + +%.o:../%.c + $(CC) -c -I $< -o $@ + +.PHONY: clean +clean: + $(CL) *.bin *.map *.srec *.elf *.o diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c new file mode 100644 index 0000000..763d3a5 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define RCAR_SA0_SIZE_SMALL (0) /* for RZ/G2E */ +#define RCAR_SA0_SIZE_NORMAL (1) /* for RZ/G2[HMN] */ + +#define BL2_ADDRESS (0xE6304000) /* BL2 start address */ + +#if (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) +#define BL2_SIZE (80*1024/4) /* BL2 size is 80KB(0x00005000) */ +#else /* (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) */ +#define BL2_SIZE (170*1024/4) /* BL2 size is 170KB(0x0000AA00) */ +#endif /* (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) */ + +/* SA0 */ +/* 0x00000000 */ +const unsigned int __attribute__ ((section(".sa0_bootrom"))) bootrom_paramA = 0x00000100; +/* 0x00000080 (Map Type 3 for eMMC Boot)*/ +/* 0x000001D4 */ +const unsigned int __attribute__ ((section(".sa0_bl2dst_addr3"))) bl2dst_addr3 = BL2_ADDRESS; +/* 0x000002E4 */ +const unsigned int __attribute__ ((section(".sa0_bl2dst_size3"))) bl2dst_size3 = BL2_SIZE; +/* 0x00000C00 (Map Type 1 for HyperFlash/QSPI Flash Boot)*/ +/* 0x00000D54 */ +const unsigned int __attribute__ ((section(".sa0_bl2dst_addr1"))) bl2dst_addr1 = BL2_ADDRESS; +/* 0x00000E64 */ +const unsigned int __attribute__ ((section(".sa0_bl2dst_size1"))) bl2dst_size1 = BL2_SIZE; diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S new file mode 100644 index 0000000..23e2b23 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +SECTIONS +{ + . = 0x00000000; + .rodata : { + KEEP(*(.sa0_bootrom)) + /* Map Type 3 for eMMC Boot */ + /* A-side IPL content cert "Start Address" */ + . = 0x000001D4; /* H'00000080 + H'00000154 */ + KEEP(*(.sa0_bl2dst_addr3)) + /* A-side IPL content cert "Size" */ + . = 0x000002E4; /* H'00000080 + H'00000264 */ + KEEP(*(.sa0_bl2dst_size3)) + /* Map Type 1 for HyperFlash/QSPI Flash Boot */ + /* A-side IPL content cert "Start Address" */ + . = 0x00000D54; /* H'00000C00 + H'00000154 */ + KEEP(*(.sa0_bl2dst_addr1)) + /* A-side IPL content cert "Size" */ + . = 0x00000E64; /* H'00000C00 + H'00000264 */ + KEEP(*(.sa0_bl2dst_size1)) + } + +} diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c new file mode 100644 index 0000000..76e3dc5 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#define RCAR_SA6_TYPE_QSPIFLASH (0) +#define RCAR_SA6_TYPE_EMMC (1) + +#if (RCAR_SA6_TYPE == RCAR_SA6_TYPE_QSPIFLASH) + +/* Number of content cert for Non-secure Target Program(BL33x) */ +#define RCAR_IMAGE_NUM (0x00000001U) +/* Source address on flash for BL31 */ +#define RCAR_BL31SRC_ADDRESS (0x001C0000U) +/* Reserved */ +#define RCAR_BL31_PARTITION (0x00000000U) +/* Source address on flash for BL32 */ +#define RCAR_BL32SRC_ADDRESS (0x00200000U) +/* Reserved */ +#define RCAR_BL32_PARTITION (0x00000000U) +/* Source address on flash for BL33 */ +#define RCAR_BL33SRC_ADDRESS (0x00300000U) +/* Reserved */ +#define RCAR_BL33_PARTITION (0x00000000U) +#define RCAR_BL332SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL332_PARTITION (0x00000000U) +#define RCAR_BL333SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL333_PARTITION (0x00000000U) +#define RCAR_BL334SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL334_PARTITION (0x00000000U) +#define RCAR_BL335SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL335_PARTITION (0x00000000U) +#define RCAR_BL336SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL336_PARTITION (0x00000000U) +#define RCAR_BL337SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL337_PARTITION (0x00000000U) +#define RCAR_BL338SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL338_PARTITION (0x00000000U) + +#else /* RCAR_SA6_TYPE == RCAR_SA6_TYPE_EMMC */ + +/* Number of content cert for Non-secure Target Program(BL33x) */ +#define RCAR_IMAGE_NUM (0x00000001U) +/* Source address on eMMC for BL31 */ +#define RCAR_BL31SRC_ADDRESS (0x00040000U) +/* Source partition on eMMC for BL31 */ +#define RCAR_BL31_PARTITION (0x00000001U) +/* Source address on eMMC for BL32 */ +#define RCAR_BL32SRC_ADDRESS (0x00200000U) +/* Source partition on eMMC for BL32 */ +#define RCAR_BL32_PARTITION (0x00000001U) +/* Source address on eMMC for BL33 */ +#define RCAR_BL33SRC_ADDRESS (0x00000000U) +/* Source partition on eMMC for BL33 */ +#define RCAR_BL33_PARTITION (0x00000002U) +/* Reserved */ +#define RCAR_BL332SRC_ADDRESS (0x00000000U) +#define RCAR_BL332_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL333SRC_ADDRESS (0x00000000U) +#define RCAR_BL333_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL334SRC_ADDRESS (0x00000000U) +#define RCAR_BL334_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL335SRC_ADDRESS (0x00000000U) +#define RCAR_BL335_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL336SRC_ADDRESS (0x00000000U) +#define RCAR_BL336_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL337SRC_ADDRESS (0x00000000U) +#define RCAR_BL337_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL338SRC_ADDRESS (0x00000000U) +#define RCAR_BL338_PARTITION (0x00000000U) + +#endif /* RCAR_SA6_TYPE == RCAR_SA6_TYPE_QSPIFLASH */ + +/* Destination address for BL31 */ +#define RCAR_BL31DST_ADDRESS (0x44000000U) +#define RCAR_BL31DST_ADDRESSH (0x00000000U) +/* Destination size for BL31 */ +#define RCAR_BL31DST_SIZE (0x00004000U) +/* Destination address for BL32 */ +#define RCAR_BL32DST_ADDRESS (0x44100000U) +#define RCAR_BL32DST_ADDRESSH (0x00000000U) +/* Destination size for BL32 */ +#define RCAR_BL32DST_SIZE (0x00040000U) +/* Destination address for BL33 */ +#define RCAR_BL33DST_ADDRESS (0x50000000U) +#define RCAR_BL33DST_ADDRESSH (0x00000000U) +/* Destination size for BL33 */ +#define RCAR_BL33DST_SIZE (0x00040000U) +/* Reserved */ +#define RCAR_BL332DST_ADDRESS (0x00000000U) +#define RCAR_BL332DST_ADDRESSH (0x00000000U) +#define RCAR_BL332DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL333DST_ADDRESS (0x00000000U) +#define RCAR_BL333DST_ADDRESSH (0x00000000U) +#define RCAR_BL333DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL334DST_ADDRESS (0x00000000U) +#define RCAR_BL334DST_ADDRESSH (0x00000000U) +#define RCAR_BL334DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL335DST_ADDRESS (0x00000000U) +#define RCAR_BL335DST_ADDRESSH (0x00000000U) +#define RCAR_BL335DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL336DST_ADDRESS (0x00000000U) +#define RCAR_BL336DST_ADDRESSH (0x00000000U) +#define RCAR_BL336DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL337DST_ADDRESS (0x00000000U) +#define RCAR_BL337DST_ADDRESSH (0x00000000U) +#define RCAR_BL337DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL338DST_ADDRESS (0x00000000U) +#define RCAR_BL338DST_ADDRESSH (0x00000000U) +#define RCAR_BL338DST_SIZE (0x00000000U) + +/* SA6 */ +const uint64_t __attribute__ ((section(".sa6_image_num"))) + image_num = RCAR_IMAGE_NUM; +const uint64_t __attribute__ ((section(".sa6_bl31src_addr"))) + bl31src_addr = RCAR_BL31SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl31partition"))) + bl31partition = RCAR_BL31_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl32src_addr"))) + bl32src_addr = RCAR_BL32SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl32partition"))) + bl32partition = RCAR_BL32_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl33src_addr"))) + bl33src_addr = RCAR_BL33SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl33partition"))) + bl33partition = RCAR_BL33_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl332src_addr"))) + bl332src_addr = RCAR_BL332SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl332partition"))) + bl332partition = RCAR_BL332_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl333src_addr"))) + bl333src_addr = RCAR_BL333SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl333partition"))) + bl333partition = RCAR_BL333_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl334src_addr"))) + bl334src_addr = RCAR_BL334SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl334partition"))) + bl334partition = RCAR_BL334_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl335src_addr"))) + bl335src_addr = RCAR_BL335SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl335partition"))) + bl335partition = RCAR_BL335_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl336src_addr"))) + bl336src_addr = RCAR_BL336SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl336partition"))) + bl336partition = RCAR_BL336_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl337src_addr"))) + bl337src_addr = RCAR_BL337SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl337partition"))) + bl337partition = RCAR_BL337_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl338src_addr"))) + bl338src_addr = RCAR_BL338SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl338partition"))) + bl338partition = RCAR_BL338_PARTITION; +const uint32_t __attribute__ ((section(".sa6_bl31dst_addr"))) + bl31dst_addr = RCAR_BL31DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl31dst_addrh"))) + bl31dst_addrh = RCAR_BL31DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl31dst_size"))) + bl31dst_size = RCAR_BL31DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl32dst_addr"))) + bl32dst_addr = RCAR_BL32DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl32dst_addrh"))) + bl32dst_addrh = RCAR_BL32DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl32dst_size"))) + bl32dst_size = RCAR_BL32DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl33dst_addr"))) + bl33dst_addr = RCAR_BL33DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl33dst_addrh"))) + bl33dst_addrh = RCAR_BL33DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl33dst_size"))) + bl33dst_size = RCAR_BL33DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl332dst_addr"))) + bl332dst_addr = RCAR_BL332DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl332dst_addrh"))) + bl332dst_addrh = RCAR_BL332DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl332dst_size"))) + bl332dst_size = RCAR_BL332DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl333dst_addr"))) + bl333dst_addr = RCAR_BL333DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl333dst_addrh"))) + bl333dst_addrh = RCAR_BL333DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl333dst_size"))) + bl333dst_size = RCAR_BL333DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl334dst_addr"))) + bl334dst_addr = RCAR_BL334DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl334dst_addrh"))) + bl334dst_addrh = RCAR_BL334DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl334dst_size"))) + bl334dst_size = RCAR_BL334DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl335dst_addr"))) + bl335dst_addr = RCAR_BL335DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl335dst_addrh"))) + bl335dst_addrh = RCAR_BL335DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl335dst_size"))) + bl335dst_size = RCAR_BL335DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl336dst_addr"))) + bl336dst_addr = RCAR_BL336DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl336dst_addrh"))) + bl336dst_addrh = RCAR_BL336DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl336dst_size"))) + bl336dst_size = RCAR_BL336DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl337dst_addr"))) + bl337dst_addr = RCAR_BL337DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl337dst_addrh"))) + bl337dst_addrh = RCAR_BL337DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl337dst_size"))) + bl337dst_size = RCAR_BL337DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl338dst_addr"))) + bl338dst_addr = RCAR_BL338DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl338dst_addrh"))) + bl338dst_addrh = RCAR_BL338DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl338dst_size"))) + bl338dst_size = RCAR_BL338DST_SIZE; diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S new file mode 100644 index 0000000..efe40b0 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +SECTIONS +{ + . = 0x00000000; + .rodata : { + KEEP(*(.sa6_image_num)) + . = 0x00000008; + KEEP(*(.sa6_bl31src_addr)) + . = 0x00000010; + KEEP(*(.sa6_bl31partition)) + . = 0x00000018; + KEEP(*(.sa6_bl32src_addr)) + . = 0x00000020; + KEEP(*(.sa6_bl32partition)) + . = 0x00000028; + KEEP(*(.sa6_bl33src_addr)) + . = 0x00000030; + KEEP(*(.sa6_bl33partition)) + . = 0x00000038; + KEEP(*(.sa6_bl332src_addr)) + . = 0x00000040; + KEEP(*(.sa6_bl332partition)) + . = 0x00000048; + KEEP(*(.sa6_bl333src_addr)) + . = 0x00000050; + KEEP(*(.sa6_bl333partition)) + . = 0x00000058; + KEEP(*(.sa6_bl334src_addr)) + . = 0x00000060; + KEEP(*(.sa6_bl334partition)) + . = 0x00000068; + KEEP(*(.sa6_bl335src_addr)) + . = 0x00000070; + KEEP(*(.sa6_bl335partition)) + . = 0x00000078; + KEEP(*(.sa6_bl336src_addr)) + . = 0x00000080; + KEEP(*(.sa6_bl336partition)) + . = 0x00000088; + KEEP(*(.sa6_bl337src_addr)) + . = 0x00000090; + KEEP(*(.sa6_bl337partition)) + . = 0x00000098; + KEEP(*(.sa6_bl338src_addr)) + . = 0x000000A0; + KEEP(*(.sa6_bl338partition)) + . = 0x00000554; + KEEP(*(.sa6_bl31dst_addr)) + . = 0x00000558; + KEEP(*(.sa6_bl31dst_addrh)) + . = 0x00000664; + KEEP(*(.sa6_bl31dst_size)) + . = 0x00000D54; + KEEP(*(.sa6_bl32dst_addr)) + . = 0x00000D58; + KEEP(*(.sa6_bl32dst_addrh)) + . = 0x00000E64; + KEEP(*(.sa6_bl32dst_size)) + . = 0x00001554; + KEEP(*(.sa6_bl33dst_addr)) + . = 0x00001558; + KEEP(*(.sa6_bl33dst_addrh)) + . = 0x00001664; + KEEP(*(.sa6_bl33dst_size)) + . = 0x00001D54; + KEEP(*(.sa6_bl332dst_addr)) + . = 0x00001D58; + KEEP(*(.sa6_bl332dst_addrh)) + . = 0x00001E64; + KEEP(*(.sa6_bl332dst_size)) + . = 0x00002554; + KEEP(*(.sa6_bl333dst_addr)) + . = 0x00002558; + KEEP(*(.sa6_bl333dst_addrh)) + . = 0x00002664; + KEEP(*(.sa6_bl333dst_size)) + . = 0x00002D54; + KEEP(*(.sa6_bl334dst_addr)) + . = 0x00002D58; + KEEP(*(.sa6_bl334dst_addrh)) + . = 0x00002E64; + KEEP(*(.sa6_bl334dst_size)) + . = 0x00003554; + KEEP(*(.sa6_bl335dst_addr)) + . = 0x00003558; + KEEP(*(.sa6_bl335dst_addrh)) + . = 0x00003664; + KEEP(*(.sa6_bl335dst_size)) + . = 0x00003D54; + KEEP(*(.sa6_bl336dst_addr)) + . = 0x00003D58; + KEEP(*(.sa6_bl336dst_addrh)) + . = 0x00003E64; + KEEP(*(.sa6_bl336dst_size)) + . = 0x00004554; + KEEP(*(.sa6_bl337dst_addr)) + . = 0x00004558; + KEEP(*(.sa6_bl337dst_addrh)) + . = 0x00004664; + KEEP(*(.sa6_bl337dst_size)) + . = 0x00004D54; + KEEP(*(.sa6_bl338dst_addr)) + . = 0x00004D58; + KEEP(*(.sa6_bl338dst_addrh)) + . = 0x00004E64; + KEEP(*(.sa6_bl338dst_size)) + } + +} diff --git a/arm-trusted-firmware/tools/sptool/Makefile b/arm-trusted-firmware/tools/sptool/Makefile new file mode 100644 index 0000000..ae42f32 --- /dev/null +++ b/arm-trusted-firmware/tools/sptool/Makefile @@ -0,0 +1,60 @@ +# +# Copyright (c) 2018-2020, Arm Limited. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. 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 + +SPTOOL ?= sptool${BIN_EXT} +BUILD_DIR = $(dir $(SPTOOL))/ +SOURCES := $(wildcard *.c) +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 + +ifeq (${V},0) + Q := @ +else + Q := +endif + +INCLUDE_PATHS := -I../../include/tools_share + +HOSTCC ?= gcc + +.PHONY: all clean distclean + +all: ${SPTOOL} + +HOST_OBJS := + +define MAKE_HOST_OBJS +$(eval HOST_OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2)))) + +$(HOST_OBJ): $(2) + @echo " HOSTCC $$<" + $${Q}$${HOSTCC} -c $${CPPFLAGS} ${HOSTCCFLAGS} $${INCLUDE_PATHS} $$< -o $$@ +HOST_OBJS += $(HOST_OBJ) +endef + +$(eval $(call MAKE_HOST_OBJS, $(BUILD_DIR), $(SOURCES))) + +${SPTOOL}: ${HOST_OBJS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${HOST_OBJS} -o $@ ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +clean: + $(call SHELL_DELETE_ALL, ${HOST_OBJS} ${SPTOOL}) diff --git a/arm-trusted-firmware/tools/sptool/Makefile.tmk b/arm-trusted-firmware/tools/sptool/Makefile.tmk new file mode 100644 index 0000000..af164ea --- /dev/null +++ b/arm-trusted-firmware/tools/sptool/Makefile.tmk @@ -0,0 +1,30 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# NVIDIA CORPORATION and its licensors retain all intellectual property +# and proprietary rights in and to this software, related documentation +# and any modifications thereto. Any use, reproduction, disclosure or +# distribution of this software and related documentation without an express +# license agreement from NVIDIA CORPORATION is strictly prohibited. +# +# tmake for component "sptool" +# +############################################################################### + +ifdef NV_COMPONENT_FLAG_STATIC_EXECUTABLE_SECTION +include $(NV_BUILD_START_COMPONENT) + +NV_COMPONENT_NAME := sptool +NV_COMPONENT_SOURCES := sptool.c + +NV_COMPONENT_INCLUDES := ../../include/tools_share + +include $(NV_BUILD_STATIC_EXECUTABLE) +endif + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: diff --git a/arm-trusted-firmware/tools/sptool/sp_mk_generator.py b/arm-trusted-firmware/tools/sptool/sp_mk_generator.py new file mode 100755 index 0000000..82d5c1b --- /dev/null +++ b/arm-trusted-firmware/tools/sptool/sp_mk_generator.py @@ -0,0 +1,157 @@ +#!/usr/bin/python3 +# Copyright (c) 2020-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +""" +This script is invoked by Make system and generates secure partition makefile. +It expects platform provided secure partition layout file which contains list +of Secure Partition Images and Partition manifests(PM). +Layout file can exist outside of TF-A tree and the paths of Image and PM files +must be relative to it. + +This script parses the layout file and generates a make file which updates +FDT_SOURCES, FIP_ARGS, CRT_ARGS and SPTOOL_ARGS which are used in later build +steps. +If the SP entry in the layout file has a "uuid" field the scripts gets the UUID +from there, otherwise it parses the associated partition manifest and extracts +the UUID from there. + +param1: Generated mk file "sp_gen.mk" +param2: "SP_LAYOUT_FILE", json file containing platform provided information +param3: plat out directory +param4: CoT parameter + +Generated "sp_gen.mk" file contains triplet of following information for each +Secure Partition entry + FDT_SOURCES += sp1.dts + SPTOOL_ARGS += -i sp1.bin:sp1.dtb -o sp1.pkg + FIP_ARGS += --blob uuid=XXXXX-XXX...,file=sp1.pkg + CRT_ARGS += --sp-pkg1 sp1.pkg + +A typical SP_LAYOUT_FILE file will look like +{ + "SP1" : { + "image": "sp1.bin", + "pm": "test/sp1.dts" + }, + + "SP2" : { + "image": "sp2.bin", + "pm": "test/sp2.dts", + "uuid": "1b1820fe-48f7-4175-8999-d51da00b7c9f" + } + + ... +} + +""" + +import getopt +import json +import os +import re +import sys +import uuid + +with open(sys.argv[2],'r') as in_file: + data = json.load(in_file) +json_file = os.path.abspath(sys.argv[2]) +json_dir = os.path.dirname(json_file) +gen_file = os.path.abspath(sys.argv[1]) +out_dir = os.path.abspath(sys.argv[3]) +dtb_dir = out_dir + "/fdts/" +MAX_SP = 8 +dualroot = sys.argv[4].lower() == "dualroot" +split = int(MAX_SP / 2) +print(dtb_dir) +platform_count = 1 +sip_count = 1 + +with open(gen_file, 'w') as out_file: + for idx, key in enumerate(data.keys()): + + pkg_num = idx + 1 + + if (pkg_num > MAX_SP): + print("WARNING: Too many secure partitions\n") + exit(-1) + + if dualroot: + owner = data[key].get('owner') + if owner == "Plat": + if (platform_count > split): + print("WARNING: Maximum Secure partitions by Plat " + + "have been exceeded (" + str(split) + ")\n") + exit(-1) + pkg_num = split + platform_count + platform_count += 1 + elif (sip_count > split): + print("WARNING: Maximum Secure partitions by SiP " + + "have been exceeded (" + str(split) + ")\n") + exit(-1) + else: + pkg_num = sip_count + sip_count += 1 + + """ + Append FDT_SOURCES + """ + dts = os.path.join(json_dir, data[key]['pm']) + dtb = dtb_dir + os.path.basename(data[key]['pm'][:-1] + "b") + out_file.write("FDT_SOURCES += " + dts + "\n") + + """ + Update SPTOOL_ARGS + """ + dst = out_dir + "/" + key + ".pkg" + src = [ json_dir + "/" + data[key]['image'] , dtb ] + out_file.write("SPTOOL_ARGS += -i " + ":".join(src) + " -o " + dst + "\n") + + if "uuid" in data[key]: + """ + Extract the UUID from the JSON file if the SP entry has a 'uuid' field + """ + uuid_std = uuid.UUID(data[key]['uuid']) + else: + """ + Extract uuid from partition manifest + """ + pm_file = open(dts) + for line in pm_file: + if "uuid" in line: + # re.findall returns a list of string tuples. + # uuid_hex is the first item in this list representing the four + # uuid hex integers from the manifest uuid field. The heading + # '0x' of the hexadecimal representation is stripped out. + # e.g. uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>; + # uuid_hex = ('1e67b5b4', 'e14f904a', '13fb1fb8', 'cbdae1da') + uuid_hex = re.findall(r'0x([0-9a-f]+) 0x([0-9a-f]+) 0x([0-9a-f]+) 0x([0-9a-f]+)', line)[0]; + + # uuid_hex is a list of four hex string values + if len(uuid_hex) != 4: + print("ERROR: malformed UUID") + exit(-1) + + # The uuid field in SP manifest is the little endian representation + # mapped to arguments as described in SMCCC section 5.3. + # Convert each unsigned integer value to a big endian representation + # required by fiptool. + y=list(map(bytearray.fromhex, uuid_hex)) + z=(int.from_bytes(y[0], byteorder='little', signed=False), + int.from_bytes(y[1], byteorder='little', signed=False), + int.from_bytes(y[2], byteorder='little', signed=False), + int.from_bytes(y[3], byteorder='little', signed=False)) + uuid_std = uuid.UUID(f'{z[0]:08x}{z[1]:08x}{z[2]:08x}{z[3]:08x}') + + """ + Append FIP_ARGS + """ + out_file.write("FIP_ARGS += --blob uuid=" + str(uuid_std) + ",file=" + dst + "\n") + + """ + Append CRT_ARGS + """ + + out_file.write("CRT_ARGS += --sp-pkg" + str(pkg_num) + " " + dst + "\n") + out_file.write("\n") diff --git a/arm-trusted-firmware/tools/sptool/sptool.c b/arm-trusted-firmware/tools/sptool/sptool.c new file mode 100644 index 0000000..38baa2c --- /dev/null +++ b/arm-trusted-firmware/tools/sptool/sptool.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sptool.h" + +#define PAGE_SIZE 4096 + +/* + * Entry describing Secure Partition package. + */ +struct sp_pkg_info { + /* Location of the files in the host's RAM. */ + void *img_data, *pm_data; + + /* Size of the files. */ + uint32_t img_size, pm_size; + + /* Location of the binary files inside the package output file */ + uint32_t img_offset, pm_offset; +}; + +/* + * List of input provided by user + */ +struct arg_list { + char *usr_input; + struct arg_list *next; +}; + +/* Align an address to a power-of-two boundary. */ +static unsigned int align_to(unsigned int address, unsigned int boundary) +{ + unsigned int mask = boundary - 1U; + + if ((address & mask) != 0U) + return (address + boundary) & ~mask; + else + return address; +} + +/* Allocate a memory area of 'size' bytes and zero it. */ +static void *xzalloc(size_t size, const char *msg) +{ + void *d; + + d = malloc(size); + if (d == NULL) { + fprintf(stderr, "error: malloc: %s\n", msg); + exit(1); + } + + memset(d, 0, size); + + return d; +} + +/* + * Write 'size' bytes from 'buf' into the specified file stream. + * Exit the program on error. + */ +static void xfwrite(void *buf, size_t size, FILE *fp) +{ + if (fwrite(buf, 1, size, fp) != size) { + fprintf(stderr, "error: Failed to write to output file.\n"); + exit(1); + } +} + +/* + * Set the file position indicator for the specified file stream. + * Exit the program on error. + */ +static void xfseek(FILE *fp, long offset, int whence) +{ + if (fseek(fp, offset, whence) != 0) { + fprintf(stderr, "error: Failed to set file to offset 0x%lx (%d).\n", + offset, whence); + perror(NULL); + exit(1); + } +} + +/* + * Free SP package structure + */ +static void cleanup(struct sp_pkg_info *sp) +{ + + if (sp != NULL) { + if (sp->img_data != NULL) { + free(sp->img_data); + } + + if (sp->pm_data != NULL) { + free(sp->pm_data); + } + + free(sp); + + } +} + +/* + * Free argument list structure + */ +static void freelist(struct arg_list *head) +{ + struct arg_list *tmp; + + while (head != NULL) { + tmp = head; + head = head->next; + free(tmp); + } +} + +/* + * Append user inputs in argument list structure + */ +static void append_user_input(struct arg_list **head, char *args) +{ + struct arg_list *tmp = *head; + + if (tmp == NULL) { + tmp = xzalloc(sizeof(struct arg_list), + "Failed to allocate arg_list struct"); + tmp->usr_input = args; + *head = tmp; + } else { + while (tmp->next != NULL) { + tmp = tmp->next; + } + tmp->next = xzalloc(sizeof(struct arg_list), + "Failed to allocate arg_list struct"); + tmp = tmp->next; + tmp->usr_input = args; + } +} + +/* + * Allocate a buffer big enough to store the content of the specified file and + * load the file into it. Fill 'size' with the file size. Exit the program on + * error. + */ +static void load_file(const char *path, void **ptr, uint32_t *size) +{ + FILE *f = fopen(path, "rb"); + if (f == NULL) { + fprintf(stderr, "error: %s couldn't be opened.\n", path); + exit(1); + } + + xfseek(f, 0, SEEK_END); + *size = ftell(f); + if (*size == 0) { + fprintf(stderr, "error: Size of %s is 0\n", path); + exit(1); + } + + rewind(f); + + *ptr = malloc(*size); + if (*ptr == NULL) { + fprintf(stderr, "error: Not enough memory to load %s\n", path); + exit(1); + } + + if (fread(*ptr, *size, 1, f) != 1) { + fprintf(stderr, "error: Couldn't read %s\n", path); + exit(1); + } + + fclose(f); +} + +/* + * Parse the string containing input payloads and fill in the + * SP Package data structure. + */ +static void load_sp_pm(char *path, struct sp_pkg_info **sp_out) +{ + struct sp_pkg_info *sp_pkg; + + char *split_mark = strstr(path, ":"); + + *split_mark = '\0'; + + char *sp_path = path; + char *pm_path = split_mark + 1; + + sp_pkg = xzalloc(sizeof(struct sp_pkg_info), + "Failed to allocate sp_pkg_info struct"); + + load_file(pm_path, &sp_pkg->pm_data, &sp_pkg->pm_size); + printf("\nLoaded SP Manifest file %s (%u bytes)\n", pm_path, sp_pkg->pm_size); + + load_file(sp_path, &sp_pkg->img_data, &sp_pkg->img_size); + printf("Loaded SP Image file %s (%u bytes)\n", sp_path, sp_pkg->img_size); + + *sp_out = sp_pkg; +} + +/* + * Write SP package data structure into output file. + */ +static void output_write(const char *path, struct sp_pkg_info *sp, bool header) +{ + struct sp_pkg_header sp_header_info; + unsigned int file_ptr = 0; + + FILE *f = fopen(path, "wb"); + if (f == NULL) { + fprintf(stderr, "error: Failed to open %s\n", path); + exit(1); + } + + /* Reserve Header size */ + if (header) { + file_ptr = sizeof(struct sp_pkg_header); + } + + /* Save partition manifest */ + xfseek(f, file_ptr, SEEK_SET); + printf("Writing SP Manifest at offset 0x%x (%u bytes)\n", + file_ptr, sp->pm_size); + + sp->pm_offset = file_ptr; + xfwrite(sp->pm_data, sp->pm_size, f); + + /* Save partition image aligned to Page size */ + file_ptr = align_to((sp->pm_offset + sp->pm_size), PAGE_SIZE); + xfseek(f, file_ptr, SEEK_SET); + printf("Writing SP Image at offset 0x%x (%u bytes)\n", + file_ptr, sp->img_size); + + sp->img_offset = file_ptr; + xfwrite(sp->img_data, sp->img_size, f); + + /* Finally, write header, if needed */ + if (header) { + sp_header_info.magic = SECURE_PARTITION_MAGIC; + sp_header_info.version = 0x1; + sp_header_info.img_offset = sp->img_offset; + sp_header_info.img_size = sp->img_size; + sp_header_info.pm_offset = sp->pm_offset; + sp_header_info.pm_size = sp->pm_size; + + xfseek(f, 0, SEEK_SET); + + printf("Writing package header\n"); + + xfwrite(&sp_header_info, sizeof(struct sp_pkg_header), f); + } + + /* All information has been written now */ + printf("\nsptool: Built Secure Partition blob %s\n", path); + + fclose(f); +} + +static void usage(void) +{ + printf("usage: sptool "); +#ifdef VERSION + printf(VERSION); +#else + /* If built from sptool directory, VERSION is not set. */ + printf("version unknown"); +#endif + printf(" []\n\n"); + + printf("This tool takes as input set of image binary files and the\n" + "partition manifest blobs as input and generates set of\n" + "output package files\n" + "Usage example: sptool -i sp1.bin:sp1.dtb -o sp1.pkg\n" + " -i sp2.bin:sp2.dtb -o sp2.pkg ...\n\n"); + printf("Commands supported:\n"); + printf(" -o Set output file path.\n"); + printf(" -i Add Secure Partition image and\n" + " Manifest blob (specified in two paths\n" + " separated by a colon).\n"); + printf(" -n Generate package without header\n"); + printf(" -h Show this message.\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct sp_pkg_info *sp_pkg = NULL; + struct arg_list *in_head = NULL; + struct arg_list *out_head = NULL; + struct arg_list *in_list = NULL; + struct arg_list *out_list = NULL; + unsigned int match_counter = 0; + bool need_header = true; + + int ch; + + if (argc <= 1) { + fprintf(stderr, "error: File paths must be provided.\n\n"); + usage(); + return 1; + } + + while ((ch = getopt(argc, argv, "hni:o:")) != -1) { + switch (ch) { + case 'i': + append_user_input(&in_head, optarg); + match_counter++; + break; + case 'o': + append_user_input(&out_head, optarg); + match_counter--; + break; + case 'n': + need_header = false; + break; + case 'h': + default: + usage(); + } + } + + if (match_counter) { + fprintf(stderr, "error: Input/Output count mismatch.\n\n"); + freelist(in_head); + freelist(out_head); + usage(); + return 1; + } + + in_list = in_head; + out_list = out_head; + while (in_list != NULL) { + load_sp_pm(in_list->usr_input, &sp_pkg); + output_write(out_list->usr_input, sp_pkg, need_header); + in_list = in_list->next; + out_list = out_list->next; + } + + argc -= optind; + argv += optind; + + cleanup(sp_pkg); + freelist(in_head); + freelist(out_head); + + return 0; +} diff --git a/arm-trusted-firmware/tools/stm32image/Makefile b/arm-trusted-firmware/tools/stm32image/Makefile new file mode 100644 index 0000000..9c9b7b5 --- /dev/null +++ b/arm-trusted-firmware/tools/stm32image/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (c) 2017-2018, 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 + +PROJECT := stm32image${BIN_EXT} +OBJECTS := stm32image.o +V := 0 + +HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE + +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif + +ifeq (${V},0) + Q := @ +else + Q := +endif + +HOSTCC := gcc + +.PHONY: all clean distclean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} -o $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) + +distclean: clean diff --git a/arm-trusted-firmware/tools/stm32image/stm32image.c b/arm-trusted-firmware/tools/stm32image/stm32image.c new file mode 100644 index 0000000..bd4720c --- /dev/null +++ b/arm-trusted-firmware/tools/stm32image/stm32image.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Magic = 'S' 'T' 'M' 0x32 */ +#define HEADER_MAGIC __be32_to_cpu(0x53544D32) +#define VER_MAJOR 2 +#define VER_MINOR 1 +#define VER_VARIANT 0 +#define HEADER_VERSION_V1 0x1 +#define HEADER_VERSION_V2 0x2 +#define PADDING_HEADER_MAGIC __be32_to_cpu(0x5354FFFF) +#define PADDING_HEADER_FLAG (1 << 31) +#define PADDING_HEADER_LENGTH 0x180 + +struct stm32_header_v1 { + uint32_t magic_number; + uint8_t image_signature[64]; + uint32_t image_checksum; + uint8_t header_version[4]; + uint32_t image_length; + uint32_t image_entry_point; + uint32_t reserved1; + uint32_t load_address; + uint32_t reserved2; + uint32_t version_number; + uint32_t option_flags; + uint32_t ecdsa_algorithm; + uint8_t ecdsa_public_key[64]; + uint8_t padding[83]; + uint8_t binary_type; +}; + +struct stm32_header_v2 { + uint32_t magic_number; + uint8_t image_signature[64]; + uint32_t image_checksum; + uint8_t header_version[4]; + uint32_t image_length; + uint32_t image_entry_point; + uint32_t reserved1; + uint32_t load_address; + uint32_t reserved2; + uint32_t version_number; + uint32_t extension_flags; + uint32_t extension_headers_length; + uint32_t binary_type; + uint8_t padding[16]; + uint32_t extension_header_type; + uint32_t extension_header_length; + uint8_t extension_padding[376]; +}; + +static void stm32image_default_header(void *ptr) +{ + struct stm32_header_v1 *header = (struct stm32_header_v1 *)ptr; + + if (!header) { + return; + } + + header->magic_number = HEADER_MAGIC; + header->version_number = __cpu_to_le32(0); +} + +static uint32_t stm32image_checksum(void *start, uint32_t len, + uint32_t header_size) +{ + uint32_t csum = 0; + uint8_t *p; + + if (len < header_size) { + return 0; + } + + p = (unsigned char *)start + header_size; + len -= header_size; + + while (len > 0) { + csum += *p; + p++; + len--; + } + + return csum; +} + +static void stm32image_print_header(const void *ptr) +{ + struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; + struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; + + printf("Image Type : ST Microelectronics STM32 V%d.%d\n", + stm32hdr->header_version[VER_MAJOR], + stm32hdr->header_version[VER_MINOR]); + printf("Image Size : %lu bytes\n", + (unsigned long)__le32_to_cpu(stm32hdr->image_length)); + printf("Image Load : 0x%08x\n", + __le32_to_cpu(stm32hdr->load_address)); + printf("Entry Point : 0x%08x\n", + __le32_to_cpu(stm32hdr->image_entry_point)); + printf("Checksum : 0x%08x\n", + __le32_to_cpu(stm32hdr->image_checksum)); + + switch (stm32hdr->header_version[VER_MAJOR]) { + case HEADER_VERSION_V1: + printf("Option : 0x%08x\n", + __le32_to_cpu(stm32hdr->option_flags)); + break; + + case HEADER_VERSION_V2: + printf("Extension : 0x%08x\n", + __le32_to_cpu(stm32hdr_v2->extension_flags)); + break; + + default: + printf("Incorrect header version\n"); + } + + printf("Version : 0x%08x\n", + __le32_to_cpu(stm32hdr->version_number)); +} + +static int stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, + uint32_t loadaddr, uint32_t ep, uint32_t ver, + uint32_t major, uint32_t minor, + uint32_t binary_type, uint32_t header_size) +{ + struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; + struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; + uint32_t ext_size = 0U; + uint32_t ext_flags = 0U; + + stm32image_default_header(ptr); + + stm32hdr->header_version[VER_MAJOR] = major; + stm32hdr->header_version[VER_MINOR] = minor; + stm32hdr->load_address = __cpu_to_le32(loadaddr); + stm32hdr->image_entry_point = __cpu_to_le32(ep); + stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size - + header_size); + stm32hdr->image_checksum = + __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size, + header_size)); + + switch (stm32hdr->header_version[VER_MAJOR]) { + case HEADER_VERSION_V1: + /* Default option for header v1 : bit0 => no signature */ + stm32hdr->option_flags = __cpu_to_le32(0x00000001); + stm32hdr->ecdsa_algorithm = __cpu_to_le32(1); + stm32hdr->binary_type = (uint8_t)binary_type; + break; + + case HEADER_VERSION_V2: + stm32hdr_v2->binary_type = binary_type; + ext_size += PADDING_HEADER_LENGTH; + ext_flags |= PADDING_HEADER_FLAG; + stm32hdr_v2->extension_flags = + __cpu_to_le32(ext_flags); + stm32hdr_v2->extension_headers_length = + __cpu_to_le32(ext_size); + stm32hdr_v2->extension_header_type = PADDING_HEADER_MAGIC; + stm32hdr_v2->extension_header_length = + __cpu_to_le32(PADDING_HEADER_LENGTH); + break; + + default: + return -1; + } + + stm32hdr->version_number = __cpu_to_le32(ver); + + return 0; +} + +static int stm32image_create_header_file(char *srcname, char *destname, + uint32_t loadaddr, uint32_t entry, + uint32_t version, uint32_t major, + uint32_t minor, uint32_t binary_type) +{ + int src_fd, dest_fd, header_size; + struct stat sbuf; + unsigned char *ptr; + void *stm32image_header; + + dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); + if (dest_fd == -1) { + fprintf(stderr, "Can't open %s: %s\n", destname, + strerror(errno)); + return -1; + } + + src_fd = open(srcname, O_RDONLY); + if (src_fd == -1) { + fprintf(stderr, "Can't open %s: %s\n", srcname, + strerror(errno)); + return -1; + } + + if (fstat(src_fd, &sbuf) < 0) { + return -1; + } + + ptr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, src_fd, 0); + if (ptr == MAP_FAILED) { + fprintf(stderr, "Can't read %s\n", srcname); + return -1; + } + + switch (major) { + case HEADER_VERSION_V1: + stm32image_header = malloc(sizeof(struct stm32_header_v1)); + header_size = sizeof(struct stm32_header_v1); + break; + + case HEADER_VERSION_V2: + stm32image_header = malloc(sizeof(struct stm32_header_v2)); + header_size = sizeof(struct stm32_header_v2); + break; + + default: + return -1; + } + + memset(stm32image_header, 0, header_size); + if (write(dest_fd, stm32image_header, header_size) != + header_size) { + fprintf(stderr, "Write error %s: %s\n", destname, + strerror(errno)); + free(stm32image_header); + return -1; + } + + free(stm32image_header); + + if (write(dest_fd, ptr, sbuf.st_size) != sbuf.st_size) { + fprintf(stderr, "Write error on %s: %s\n", destname, + strerror(errno)); + return -1; + } + + munmap((void *)ptr, sbuf.st_size); + close(src_fd); + + if (fstat(dest_fd, &sbuf) < 0) { + return -1; + } + + ptr = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, + dest_fd, 0); + + if (ptr == MAP_FAILED) { + fprintf(stderr, "Can't write %s\n", destname); + return -1; + } + + if (stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, + entry, version, major, minor, + binary_type, header_size) != 0) { + return -1; + } + + stm32image_print_header(ptr); + + munmap((void *)ptr, sbuf.st_size); + close(dest_fd); + return 0; +} + +int main(int argc, char *argv[]) +{ + int opt; + int loadaddr = -1; + int entry = -1; + int err = 0; + int version = 0; + int binary_type = -1; + int major = HEADER_VERSION_V2; + int minor = 0; + char *dest = NULL; + char *src = NULL; + + while ((opt = getopt(argc, argv, ":b:s:d:l:e:v:m:n:")) != -1) { + switch (opt) { + case 'b': + binary_type = strtol(optarg, NULL, 0); + break; + case 's': + src = optarg; + break; + case 'd': + dest = optarg; + break; + case 'l': + loadaddr = strtol(optarg, NULL, 0); + break; + case 'e': + entry = strtol(optarg, NULL, 0); + break; + case 'v': + version = strtol(optarg, NULL, 0); + break; + case 'm': + major = strtol(optarg, NULL, 0); + break; + case 'n': + minor = strtol(optarg, NULL, 0); + break; + default: + fprintf(stderr, + "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor] [-b binary_type]\n", + argv[0]); + return -1; + } + } + + if (!src) { + fprintf(stderr, "Missing -s option\n"); + return -1; + } + + if (!dest) { + fprintf(stderr, "Missing -d option\n"); + return -1; + } + + if (loadaddr == -1) { + fprintf(stderr, "Missing -l option\n"); + return -1; + } + + if (entry == -1) { + fprintf(stderr, "Missing -e option\n"); + return -1; + } + + if (binary_type == -1) { + fprintf(stderr, "Missing -b option\n"); + return -1; + } + + err = stm32image_create_header_file(src, dest, loadaddr, + entry, version, major, minor, + binary_type); + + return err; +} diff --git a/atf_and_optee_README.txt b/atf_and_optee_README.txt new file mode 100644 index 0000000..591edda --- /dev/null +++ b/atf_and_optee_README.txt @@ -0,0 +1,127 @@ +********************************************************************** +NVIDIA Jetson Linux (L4T) OP-TEE Package +********************************************************************** + +---------------------------------------------------------------------- +Introduction +---------------------------------------------------------------------- +This package contains the necessary files and instructions to build a +trusted OS image based on ATF and OP-TEE for these Jetson devices: +- Jetson Xavier NX +- Jetson AGX Xavier series +- Jetson AGX Orin series + +---------------------------------------------------------------------- +Prerequisites +---------------------------------------------------------------------- +Please refer to the link below to install build prerequisites, e.g. +python3-pycryptodome and python3-pyelftools, in your build machine. + +https://optee.readthedocs.io/en/latest/building/prerequisites.html + +---------------------------------------------------------------------- +Placeholders used in this document +---------------------------------------------------------------------- +This document uses a placeholder, "", to indicate Jetson platforms. +Its possible values are: +- 194 +- 234 +Choose the platform value according to your Jetson board to build different +trusted OS images and DTBs. + +---------------------------------------------------------------------- +Toolchain +---------------------------------------------------------------------- +Download the toolchain from Jetson release page according to your L4T version: + +https://developer.nvidia.com/embedded/jetson-linux-archive + +Set environment variable CROSS_COMPILE_AARCH64_PATH to point to the aarch64 +toolchain. For example, if the aarch64 toolchain directory is +/toolchain/aarch64--glibc--stable-2022.03-1/, then set +the CROSS_COMPILE_AARCH64_PATH with the command below. + +export CROSS_COMPILE_AARCH64_PATH=/toolchain/aarch64--glibc--stable-2022.03-1 + +Then set environment variable CROSS_COMPILE_AARCH64 with the command +below. + +export CROSS_COMPILE_AARCH64=/toolchain/aarch64--glibc--stable-2022.03-1/bin/aarch64-buildroot-linux-gnu- + +---------------------------------------------------------------------- +UEFI StMM image +---------------------------------------------------------------------- +A UEFI StMM image is required when building OP-TEE. The image is usually at: + +For the Jetson AGX Xavier series and the Jetson Xavier NX: +/bootloader/standalonemm_optee_t194.bin + +For the Jetson AGX Orin series: +/bootloader/standalonemm_optee_t234.bin + +Set the environment variable "UEFI_STMM_PATH" to let the OP-TEE build script +know where the image is: + +export UEFI_STMM_PATH= + +---------------------------------------------------------------------- +Building the OP-TEE source code +---------------------------------------------------------------------- +Execute this command to build the OP-TEE source package: + +./optee_src_build.sh -p t + +---------------------------------------------------------------------- +Building the OP-TEE dtb +---------------------------------------------------------------------- +Execute this command to build OP-TEE dtb: + +dtc -I dts -O dtb -o ./optee/tegra-optee.dtb ./optee/tegra-optee.dts + +---------------------------------------------------------------------- +Building the ATF source code with OP-TEE SPD +---------------------------------------------------------------------- +1. Extract the ATF source package. + mkdir atf_build + tar -I lbzip2 -C atf_build -xpf atf_src.tbz2 + +2. Build the ATF source code: + cd atf_build/arm-trusted-firmware + make BUILD_BASE=./build \ + CROSS_COMPILE="${CROSS_COMPILE_AARCH64}" \ + DEBUG=0 LOG_LEVEL=20 PLAT=tegra SPD=opteed TARGET_SOC=t V=0 + cd ../.. + +---------------------------------------------------------------------- +Generating the tos.img with ATF and OP-TEE images +---------------------------------------------------------------------- +1. Get gen_tos_part_img.py. It's usually in the directory + /nv_tegra/tos-scripts/ of BSP package. + +2. Generate the tos.img with the commands: + ./gen_tos_part_img.py \ + --monitor ./atf_build/arm-trusted-firmware/build/tegra/t/release/bl31.bin \ + --os ./optee/build/t/core/tee-raw.bin \ + --dtb ./optee/tegra-optee.dtb \ + --tostype optee \ + ./tos.img + +---------------------------------------------------------------------- +Verifying the Image +---------------------------------------------------------------------- +To verify the image: +1. Replace the default TOS image file with the newly generated TOS + image. The default TOS image file is located at: + /bootloader/tos-optee_t.img + +2. Perform either of these tasks: + - Flash the system as normal. + This is useful for flashing a new system or replacing the + entire operating system. + - Re-flash the TOS image using these partition flash commands: + sudo ./flash.sh -k mmcblk0p1 + ex: + sudo ./flash.sh -k secure-os jetson-xavier-nx-devkit mmcblk0p1 + sudo ./flash.sh -k A_secure-os jetson-agx-orin-devkit mmcblk0p1 + +3. Copy all the files under ./optee/install/t to the target. diff --git a/commitFile.txt b/commitFile.txt new file mode 100644 index 0000000..97bb8a0 --- /dev/null +++ b/commitFile.txt @@ -0,0 +1,3601 @@ +Updating prebuilts and/or headers + +e8aa3af98539680668d37659b7ba8f7e2becb16b - nvbuild.sh +d15f50688485e11293e0d0bd66d73655e79f7718 - nvcommon_build.sh +55bcfa0a03639a375c3f87b1d3286f526c41b207 - arm-trusted-firmware/.versionrc.js +5f8311228df51d284e4efc6c89e9d193dde99d11 - arm-trusted-firmware/.editorconfig +2b66445d7d00314222c238ee2f233a099ac6d838 - arm-trusted-firmware/.commitlintrc.js +1156a747abe8e5f2a639fe82c7e9b4b8c128428c - arm-trusted-firmware/package-lock.json +d2180c4f81067554a4fa86baaebf7cd7722d0706 - arm-trusted-firmware/Makefile +c10d9e3662b48b6da5c81ce00879a16fd8cf3d60 - arm-trusted-firmware/.cz.json +2d62a7583b85631859c4143f08e0dc332e1cb87e - arm-trusted-firmware/.gitreview +da14c19baefee3959f7c02f68db6cbe8c25d408e - arm-trusted-firmware/readme.rst +7f3fadaf80e3c4745d24cb1a5881c7c5f4d898ba - arm-trusted-firmware/.checkpatch.conf +2da4fc2430e852f43b1ec376e4783a1d4658c039 - arm-trusted-firmware/package.json +1684b8fa062fcf155fb678c6e112cf5436423ba2 - arm-trusted-firmware/changelog.yaml +d8da3627085908a5f974b45528b85dc0a41a8b75 - arm-trusted-firmware/license.rst +5c6a4c08a854ddd3d464e6d96f605ff5e28fcf28 - arm-trusted-firmware/bl31/ehf.c +75c196ade8ef57a9775c286e3c2f88b52c492e67 - arm-trusted-firmware/bl31/bl31_context_mgmt.c +ae44163001e4ade4c2e29f6afb43316e7584ee41 - arm-trusted-firmware/bl31/interrupt_mgmt.c +ccc40b094b337f6e60b8a4f2a7470ab4c1264f4f - arm-trusted-firmware/bl31/bl31_main.c +57600ae63b254bd5341c3728038049d1e9526b9a - arm-trusted-firmware/bl31/bl31.ld.S +64b21af0df86a3f591cbf9889b0990e313980048 - arm-trusted-firmware/bl31/aarch64/ea_delegate.S +7c846b0cc5af2d57b0a9ccac7bb940b95f682bce - arm-trusted-firmware/bl31/aarch64/crash_reporting.S +a6aee212d05e2c649a137adf37160a8d24360040 - arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S +86ee5f1020a1ae3e8788204817e6b6fcb0da5922 - arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S +2c87153926f8a458cffc9a435e15571ba721c2fa - arm-trusted-firmware/licenses/LICENSE.MIT +8887d0d62a1b5248423fbc54ee536be3e5131d91 - arm-trusted-firmware/services/spd/opteed/opteed_private.h +04de846e914d22f5925ba665f709fd3b0793ea5c - arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h +c7af1a7de6cb5d79bf42271e846f04a18df96b63 - arm-trusted-firmware/services/spd/opteed/opteed_pm.c +c8ea87fefa1ecd86c162a85206e9427be8c93afb - arm-trusted-firmware/services/spd/opteed/opteed_helpers.S +b4e16e85997824311dd82861c4c22d6ed046b817 - arm-trusted-firmware/services/spd/opteed/opteed_main.c +e6df3878f8d4759c9f52ea98cbd0d6303bd2983b - arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h +4577f90d8a829f8cb934271e6991bd34844e1854 - arm-trusted-firmware/services/spd/opteed/opteed_common.c +c41250dd18f5502066bab243f1a2f33acf9079f5 - arm-trusted-firmware/services/spd/tspd/tspd_private.h +36db67e2b644b85662e0440abdf6bb464032dfb1 - arm-trusted-firmware/services/spd/tspd/tspd_main.c +d68051c573aae1f65601f9c9307d095259f8de63 - arm-trusted-firmware/services/spd/tspd/tspd_pm.c +45855bd72493c075e03c590cfade6075e5656654 - arm-trusted-firmware/services/spd/tspd/tspd_common.c +f9cf95e919ab4903bc80205e402547ddebe078a8 - arm-trusted-firmware/services/spd/tspd/tspd_helpers.S +61ff410fd8dae3d3ecffc63595125321444d53c7 - arm-trusted-firmware/services/spd/tlkd/tlkd_main.c +176e5bf39535fbb39c81b2deb17ee470cac87159 - arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c +c213fbde43c8075e8fe28297dd6934f2f7c5f6fa - arm-trusted-firmware/services/spd/tlkd/tlkd_common.c +e4543798b8feb237167dc8c495b7aeb079d1b290 - arm-trusted-firmware/services/spd/tlkd/tlkd_private.h +14bc8b1de264fc27498c195073dcf7c1dd736c4d - arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S +cb38cd65497ea7679a3c5ced33d2e833c2f82797 - arm-trusted-firmware/services/spd/trusty/trusty.c +ba437dffc2a576e12cd8b8b5e8331a43244754b0 - arm-trusted-firmware/services/spd/trusty/trusty_helpers.S +405a4e398e27192766391869719c952a77d4e789 - arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c +912f672668f3beed13a6a55a3fab7666e147ea6c - arm-trusted-firmware/services/spd/trusty/sm_err.h +2bbaae4a856f5eba1f98688458729049af38a448 - arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h +55c35f079c4fec17128f7c644425b13fd516f2e8 - arm-trusted-firmware/services/spd/trusty/smcall.h +32f05b17684cd616a34fd51c98e75162d384217a - arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c +250540ab4306221c494658c2239ffed65aa3fbd9 - arm-trusted-firmware/services/std_svc/pci_svc.c +bc64867c51e6a4f26dc11e07d3be01304f8b78e3 - arm-trusted-firmware/services/std_svc/std_svc_setup.c +3e424bb10206165d477d92627a1a6d8955152b74 - arm-trusted-firmware/services/std_svc/spmd/spmd_private.h +6da223d4cbc8ff07b002a40446860274397aa283 - arm-trusted-firmware/services/std_svc/spmd/spmd_main.c +eb2fb622fab718a44678ea1273fb7df9d3dd49be - arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c +eb5c9e4113243964f83a249807ed07711dc6f145 - arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S +45b49532e2610460e0fba1e6cbf18573f216da9e - arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c +26be0a6e880962cffc338be91ad0f344e8aee9ef - arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h +5d93ba8b111b69b7ef12b9a1ce621d9740284e41 - arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c +4268337ed8b89db9b3ad75537a8f1e2a008fc949 - arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h +51c4bc5d5a6c9b18e2f3f2c951d3f8abe0869ba2 - arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S +06bef6d6d25e76eef2278253f480a4afbaebabf3 - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S +6b1ef22efba95bff3270de056f0a4e2484528dee - arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds +83a9c2e476136e139d80cac740c65fee111c0ba6 - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h +ca2e1ed2396b9c004b00095f04cbe848e743043d - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c +2fd31858f771c3fa2d49ac883b8e3bb8486cebae - arm-trusted-firmware/services/std_svc/sdei/sdei_event.c +e020a86b0568edbbb8e8a93f2cee43fc4812d475 - arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c +0a593d9b9aca3739ab4d94c4aa2ecdf7481ad305 - arm-trusted-firmware/services/std_svc/sdei/sdei_main.c +b8207b17922c0b2192565df4c3bc9e1e9e726afa - arm-trusted-firmware/services/std_svc/sdei/sdei_state.c +36f054958b6c01f03eed070113b49903ce936a5d - arm-trusted-firmware/services/std_svc/sdei/sdei_private.h +ed3a4e16186524a88ed19aa95176bc233b0928fe - arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S +0f3a50749094ad519b427c0a9c94db4f8dd32988 - arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c +99c265f55fed0f586d388c5654338897d9e296e6 - arm-trusted-firmware/services/std_svc/trng/trng_main.c +c53e4b9cdb4eaee27196d9759c484c4faeaf7d06 - arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h +e3e6228d6ff51d8d1940c9d13b884a9699bc1a6e - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h +5ddc8c374ed249405453ffb9dd8519ddc8a7a34b - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c +79d13846ac86474d81cf97529b0dcb9876156531 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c +27e07360421aaf616722735cfdc19c90d91af4a0 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c +9f72d160e0732ed98d19b7f82e62c8434b043846 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h +f3b6abb1b262ca29c81fe896193453e05ae2fd50 - arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S +92bbf065b55bbb16728230902e84c1ae124cdd26 - arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S +358ff3e13baa8507b20744e31468185b03077531 - arm-trusted-firmware/common/bl_common.c +91cec99e37b1e7e986e62eb3474f5b0d63516507 - arm-trusted-firmware/common/image_decompress.c +4e8e81d22968abbb440726d3094bc3a5bbab94c6 - arm-trusted-firmware/common/tf_crc32.c +567e84803ece6e7ea1401d347ecba84600dea543 - arm-trusted-firmware/common/uuid.c +bb6318e6a4526a2e75ed8f74f629b22fad67317e - arm-trusted-firmware/common/fdt_wrappers.c +d1831078ebc7756a3c141537c4f33b00ce2ffca0 - arm-trusted-firmware/common/fdt_fixup.c +54620aa80f910434a484672d917861106ecc2df1 - arm-trusted-firmware/common/runtime_svc.c +f4efa0610d34dd7e2935e65e54d8226cf36f94ff - arm-trusted-firmware/common/desc_image_load.c +3ccdb5028aa976066c06527a27303c4a0db57ead - arm-trusted-firmware/common/tf_log.c +b21d0924c4f52357b3815446ebd25cc4f58ad622 - arm-trusted-firmware/common/aarch64/early_exceptions.S +5354886f2c074fe74f50056321be3516724c7536 - arm-trusted-firmware/common/aarch64/debug.S +e1451e78efe19651d81b93634da02b524c4ebcab - arm-trusted-firmware/common/backtrace/backtrace.c +8ce1f388b3852351c1fa8d8001d14910363ee672 - arm-trusted-firmware/common/aarch32/debug.S +d006178768f88929b34ddd8b6f7caf6ffb1577b4 - arm-trusted-firmware/bl1/bl1_main.c +20113f49289a58e42b03525ea9427f94e093f58f - arm-trusted-firmware/bl1/bl1_private.h +653f6de57d95cb1d74a23acc6389ab9292ef0451 - arm-trusted-firmware/bl1/bl1_fwu.c +f34fa7c71b4b146c22d99ea5e88650c232833b2b - arm-trusted-firmware/bl1/bl1.ld.S +587ecb158bf5940ddc7f95250a8802df39806ef0 - arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c +d6181e93a353f492a54a5222fe53d793cc6d46d7 - arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S +5c5e2355ca375fa98ae30f56bcf2f57ea7056c71 - arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S +284a0afe619de982f2bd1d4b1c625831ef7b3b5e - arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c +095ac3b2483b968f263618a4bd6cdd8d6f66d321 - arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c +32bd99d2c29b908009a4aea495162f0bb76949db - arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S +6ef2d19cb4ab43cba39eb87d49604192b1f3b2bd - arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S +8d6e2008e280f848fb14017ba5ba559a10724421 - arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c +85b2afc44851dc57e79c264641730d0e2eca3016 - arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c +3793e73034176c719a8160e57d2216f834867aea - arm-trusted-firmware/drivers/scmi-msg/base.h +d0830b0dd0dcad2627d7e25042e0b04f9172507d - arm-trusted-firmware/drivers/scmi-msg/common.h +9a06fcf18608dead4701ec10a63da3ace748fe3d - arm-trusted-firmware/drivers/scmi-msg/smt.c +6854b6e16a5d00e32471a842ac82a42307f4fd25 - arm-trusted-firmware/drivers/scmi-msg/reset_domain.h +6494de9c4e6d28e03514a090db2224f8b96327ba - arm-trusted-firmware/drivers/scmi-msg/power_domain.h +ed00d8b9bd19e5b6e1f8ecd2721a613d1a9043ef - arm-trusted-firmware/drivers/scmi-msg/power_domain.c +a9219fa6261f43e472c7b1655189ae66022de0e2 - arm-trusted-firmware/drivers/scmi-msg/clock.h +20129a454f6019ae086f0fc760ccbe6441c75105 - arm-trusted-firmware/drivers/scmi-msg/clock.c +51f712caca20f1532dbd7a569fab515695f574f9 - arm-trusted-firmware/drivers/scmi-msg/reset_domain.c +0f8a382f7d1dc362cfb9bf7d2a7189987b1bd9f4 - arm-trusted-firmware/drivers/scmi-msg/entry.c +5d761434daa9ee97981a3e3264d4196b1b9710f7 - arm-trusted-firmware/drivers/scmi-msg/base.c +d53b18f9aba437cc5d23117338ddac6edd9ba447 - arm-trusted-firmware/drivers/clk/clk.c +f1d5a7ca46b231b4291d715aa7312bc93c8c8d3c - arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S +a8b2be0d9781815f941f3b5c54c06d66869ebbb8 - arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c +cbb35d75dea21db6209d5ab41ce216af0acbd5f3 - arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c +7da82df0c542d1d8ae8e69affe9e30ba233590a2 - arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c +d354d19d9f42611b3ad0f293660bac71ee3a801c - arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h +0c3739bdd3d04953083299f803b7c30e40e3fa93 - arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h +af21526870ded933cf4e5455fdd2935a82cea61b - arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c +ce75912d66d9d45c7fb5514c2d883363346b1a48 - arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c +396f26a188a6fb1077b280cdc459ee52ac4dec89 - arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c +a4736e2e943ff2c95ee55ab5550d95dbf4e9fae5 - arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c +fa805a963aca474eb7b99d376fc23bf898fe4457 - arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c +d4cf1b07b3a081078c4e7da1e354adc42f41f7ca - arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c +e4343fd48fd3beed200fd430ec2f84482e7171bf - arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c +bb9ccbfadb1dba83a0035f9bf7b3d22a48fa01ff - arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c +ba408ad853e9ef0e53ce8319419a8b3d8a3da7ed - arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c +32d20982227d5346d95e069f256ec3556d52ecfe - arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c +eeaa299335bd10e0531ff65d6a24c6a4da294057 - arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c +ff23fd02b2c8ce84423f099d2b1bea12faf82aec - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c +eb5515126eb5fa4bef2f7976e79e3f9fd0944afa - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c +02475a8e210c6615aa5138943337551fc8b9087f - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c +f29d54b17cb5dd1f602641d092227c883cb6a57b - arm-trusted-firmware/drivers/nxp/csu/csu.c +bf7712fb75e6373abf6791b46d9a4563fd00feb7 - arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c +1d31a2492e42b2087d68ef756a91274f671987c7 - arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c +5579fdab0db3121aceafcaf39eab316e0253aee3 - arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c +3976af866b0f1353ade3d95b9d4ef92a7a2169ea - arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h +c7adb94bca0f7e2a86394a503007aacd278de299 - arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c +85860d4c7284e5f15ce31d18787f687d6bde61b8 - arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c +9b849f025149e6cf51b2500c8f70b38703ed5078 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 +9489f5c75aa894fc166bb99b848883d0413170cb - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 +753107ce7c270d602a0018c1cabb0ef8e7d3c54a - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 +58bff9b3422ffad20520362a80a6f322da632da3 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 +8b7ec36599206f1c121cf2a9565bc043b6049dba - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c +cb8400c786b03ab4685825c49454f7915622e629 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c +e9bddb61157fc79a6db73771f3abc44b0fa2180e - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 +aaaf596468de0e2b0f1fd9df798408ccae3ec67c - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c +bc6fe6b33a974e9a9e2ae522e3ac00b9f7ff4967 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 +dd7d454c97e1855bb1c228cacfecb6238f4e487d - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 +5a7943b124da3fea7995adb004eff6a0b928e921 - arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c +06049b8071d1258dcc7829e02727d935c561fa1a - arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c +73a87390ee3b46e2b5587087457d8a10a6f4cd35 - arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c +d3e9bd0226d74dffd59af6ef1c8f029ca195db90 - arm-trusted-firmware/drivers/nxp/console/console_16550.c +f15b111b5f8ec4a947c36b642e6c6331bb5331a4 - arm-trusted-firmware/drivers/nxp/console/console_pl011.c +5128d83df7b28a2a4bd817b834e17b74206a84d7 - arm-trusted-firmware/drivers/nxp/console/16550_console.S +fed7a4d64f892002dd30f1e1bf50d5fbf537281d - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c +33929846548a6a6731c652caf6050b64dea2f9d7 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c +59117917987eb057fe4003d4da4c3125ea76dbc9 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c +442cb1d00ad113cbdc5ce076abc56124655dbe2d - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c +eaefee9029f7ccfd854a5813aae54ad816808645 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c +e083ea048179544e9c8e52f7a48d7c315f03a475 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt +7547f7a2396ef42e0140f69a68424c714c210b19 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c +9c36d85b72ea62f1b3e6d8df34efe02d50c468ca - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h +ac55bbcc1387d5092bdce1d236686694d82f2a87 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h +7c05bf68f35c9cbbeb751db67f075cc1bc864b72 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h +8ced20b50814e640a734b45571534428a03235aa - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h +f222d8d69c33519c4908bafaaeb6a2482f35bb20 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h +aac92f8b51eb5a99b8c6c1b861b65d8ed56c92b9 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h +d9b4015568e26bddf900e57b2034588011dc76fe - arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c +6ba34d8cf6a1e66a6b8781b632305c8192f8c47f - arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c +7e7c03a074969dc0547afeb5dbe289ae008dae93 - arm-trusted-firmware/drivers/nxp/qspi/qspi.c +45cce82acdd1f75c2e31f56de0a27738ec712b09 - arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c +1c9fa968ab5e023d06dcdbe0d3d12847d4e13273 - arm-trusted-firmware/drivers/nxp/pmu/pmu.c +e87ea077dcc89cfad504b38c454094873eb4bbae - arm-trusted-firmware/drivers/nxp/sfp/sfp.c +904d53ac1f2e9c98f1e176eae19be267e985db33 - arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c +3a182ddb4f6fa33eaf8b5ae0c60f6bdf113f4fcc - arm-trusted-firmware/drivers/nxp/i2c/i2c.c +b0d5b078d9666eb577b6d96327526056a9c5ff46 - arm-trusted-firmware/drivers/imx/timer/imx_gpt.h +e7fdf9ac8aa8e62e2b82e935887ea9fa71277e50 - arm-trusted-firmware/drivers/imx/timer/imx_gpt.c +d92351086a1b0b0b82cfa7bab9e352d5725339d7 - arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c +11d6bed45c0c1633f53d1a14e935db95a494322d - arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h +30ead9b9f8c8e8a0d0443291726c90dcc10f24ef - arm-trusted-firmware/drivers/imx/uart/imx_uart.c +2b9b4163928ad22b375942df6a419ac25791d15b - arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S +bf6cd6123996ffba448042a934561a9845514132 - arm-trusted-firmware/drivers/imx/uart/imx_uart.h +7ff3e84af33c3fcf6ee55936d6400a52d52203b4 - arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c +c841aaad58e92f728c90bb7cab1771d2578be18a - arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c +5dda361745c9b337192dcd67fc63865e04a3a8a5 - arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c +304398c75526a767b8b3caaeb5722e41955e9803 - arm-trusted-firmware/drivers/allwinner/axp/common.c +f3f36bb92d56df7e9785cc98f6b13594df6404c0 - arm-trusted-firmware/drivers/allwinner/axp/axp803.c +956dadae6d826687fecfa1b522fd8b5c4fdfc764 - arm-trusted-firmware/drivers/allwinner/axp/axp805.c +a5328f6dfd065a9ddc6acad1d5ea28176f33e623 - arm-trusted-firmware/drivers/delay_timer/delay_timer.c +0d32873988a7299902bc11961218f9034c494f5b - arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c +53e86084002c599472f206bebfee855f6de44547 - arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c +4e52ca94a347a31cef85fc1cbbd480490ff065b1 - arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S +340b2a1703f14c42abdade167ac06919ec7deed5 - arm-trusted-firmware/drivers/brcm/chimp.c +99056505e9afb98d0bf6b55cbc9c64814734d610 - arm-trusted-firmware/drivers/brcm/sotp.c +e8c6d05d166788f91925b45e27853f92f98251e5 - arm-trusted-firmware/drivers/brcm/scp.c +490663a4660be758e46f4878a43d7cb947b072e0 - arm-trusted-firmware/drivers/brcm/spi_sf.c +2f55d6018c61491a206aef1e089af2001db52b87 - arm-trusted-firmware/drivers/brcm/rng.c +9b9a1876a8dd35bdd34baeedd3e531617f4b2e03 - arm-trusted-firmware/drivers/brcm/iproc_gpio.c +9156a544c31c11073920be56fe54eb346a8b018b - arm-trusted-firmware/drivers/brcm/ocotp.c +df0910b2680c7694f0b75737fda7682a8712fb64 - arm-trusted-firmware/drivers/brcm/spi_flash.c +de63fe21caac7ce499c3a244965fca77766a1d19 - arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h +653b6a961a19436e1cdba80c2b3b153c1d89a954 - arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c +2dc1c9032a1e64aa390c69bcdf0a42359e402b5a - arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c +c9c8847417d95e3ba03ff5c005edbe8a088cee14 - arm-trusted-firmware/drivers/brcm/mdio/mdio.c +a70c96d7324a040b39217a657625b8b369ed65f9 - arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c +f9de2aeddc61d9a8b63a2bb3d10edd5e5459ac61 - arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c +1e16b849ee30029570c17198cc65dd8c232fbd53 - arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c +d89024f769cfa2a2d90ab6fb83691b494227d848 - arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c +26f0937fbff1f7b2effe7d035d4e6d2c2a9c463f - arm-trusted-firmware/drivers/brcm/i2c/i2c.c +279f67f2161b938ba13883aeab4439e24b76eaf2 - arm-trusted-firmware/drivers/mmc/mmc.c +2e8560e1fee7e0d9ba844f802772a8be3e6be7ad - arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c +150bd08bfbcc1de20e05b6d07950021df0a46322 - arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c +3325b2a520df18fb8bd8859eafba82aa1c89eec1 - arm-trusted-firmware/drivers/rambus/trng_ip_76.c +8e0afaebcd5d1ed41d30457bdb8543f3617640eb - arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c +1d5e94fb3b734e7c9eb7b1628230f3d140a8e958 - arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c +366c422651f720b64f0d606e537b12713c405d8e - arm-trusted-firmware/drivers/fwu/fwu.c +e5c3d888d354f7edd20c09b85d55293a3302d4ad - arm-trusted-firmware/drivers/partition/partition.c +05e51189eff0f94ffa7616efa4a5cd4c11a90a81 - arm-trusted-firmware/drivers/partition/gpt.c +bb264060cf147f5fd4feae216d66ad8c9c66f891 - arm-trusted-firmware/drivers/io/io_fip.c +78ab979470824d9703736ca6da3735d7c11fcba1 - arm-trusted-firmware/drivers/io/io_mtd.c +88a6a7b48a8b3da04a2a2bb9d5bcb70f03c372d3 - arm-trusted-firmware/drivers/io/io_encrypted.c +fe0286bc53aeb4cae686fb9d63d9ffe2283cf119 - arm-trusted-firmware/drivers/io/io_dummy.c +a28c85766eedc583fd38c5f1cb94aa9d5caf8935 - arm-trusted-firmware/drivers/io/io_block.c +858e3130488ef425faa5341098347a0cd446a49d - arm-trusted-firmware/drivers/io/io_memmap.c +2975f82e852f74ac877b00bfa9bcaa8c3baec7e2 - arm-trusted-firmware/drivers/io/io_storage.c +78d0bb21fe92f684f28119691c173b36006dbbb5 - arm-trusted-firmware/drivers/io/io_semihosting.c +5bf3028d91229a2bab7d9be2fbf3db5b63dbdac5 - arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c +46c3bb0a303498f1a79fd2bc48b1becffddbfd71 - arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c +47003ec4d5650ecd811ae9fe4404621c369f61c6 - arm-trusted-firmware/drivers/mtd/nand/raw_nand.c +010e3cc7bf5be7ac20119f77ab261bdf528f2d2d - arm-trusted-firmware/drivers/mtd/nand/core.c +122bf5d15d1cdbcad5bee82566c57049e3fc5bb5 - arm-trusted-firmware/drivers/mtd/nand/spi_nand.c +eefd56420faeb9d836077b23eea175eb7e022871 - arm-trusted-firmware/drivers/mtd/nor/spi_nor.c +b601addd7e20d9e7f019014eac336024a1e57b8f - arm-trusted-firmware/drivers/ufs/ufs.c +1fa3c347f937895d6e5869cff641faf35158d0e0 - arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c +639d42262958e84f1bd83a574ec62649802513a1 - arm-trusted-firmware/drivers/auth/img_parser_mod.c +c16134fe5a7698bda76781fff2f959b23e9effe3 - arm-trusted-firmware/drivers/auth/auth_mod.c +a7feb170a20eb5ee10c9d197dc0097785f67943b - arm-trusted-firmware/drivers/auth/crypto_mod.c +bb94b0069937941cd0d158f609df28bc66e7f7df - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c +aa57938a1ca87b1c2d69b27e2cb210dd52b72f92 - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c +ca516c7a1c11d4ea7d2a36636ad140645e6b3ef0 - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c +ea1ff4dd6466dd5bba2280092f7ad0037f0e3791 - arm-trusted-firmware/drivers/auth/dualroot/cot.c +98690b7915852b4a6a1950623e848b467186a09e - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c +62b38ec608a3b1763bbd31827be93360dc10c4d3 - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c +fbcbbd0aa417147f5e544e91c47edef162f6aa41 - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c +efedb0eaa10e440edf6b73b4b2df6a6d164066da - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c +0931c7209af239bcc95387de431d932bf01175ec - arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c +1527e9ad692eabc3e379a8f7f0a4eecc68b9f9bb - arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c +6e817c6fdbf62d3e636fe69752f1f0bb9281c3a8 - arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c +07632d2568b5990250c7539319c93e9b64c05004 - arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c +2802b6fb340525ddb96baca00341a6a25f703c74 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h +4186c27c3850565f08118234f39f3224a0094fb6 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h +fa11d997720f3e8e38a41e393a485385f56a4981 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c +4fc3b8212dd33e6a33a9bbf4b96d0ffdb7032083 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h +7262dc7de38f8216be32a2cf973c4077da6a5ced - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h +e074216ecbdf97f24cb3e12cc7f5d8e5c99721b5 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h +1ebeec74f28d94d33ad88f9e3cb8abeb2ff4462b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h +49c7e8143b952aa89509efb296f2a3d848f1fcf1 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h +3ebe3831af51ff6dd31f04c19ed726ea47d12ffb - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h +ba3202740e2551524bc86abc295cc82374fea770 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h +17c66fa0e8ef76563d00547c6c281d4fcd025dbf - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h +4120c27434066995e75487d1311e78e2dcf57cb3 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c +5cf260b6fef6d9a6c0ddbe6c45bed9d54daf027e - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c +c9bbbceaf55fd9cdcf0943b427f8b302c902199f - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h +ae6bc783ddb0cb6feec22e234a5383965ad75a8b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h +046e1d3b18c291d99e7f1f95658f5a6bb9f7c207 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h +8146506bb0d47e4499b692d8a0b0d168c697db9a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c +d1c7d38c66ff34e537261485132cb0beb3ab4765 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h +0d2a4685c4bd34d6ec121270bc38ec212c7b1e0a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h +2e4f2532cb1b9aee27f82677a76fc8598ae3e720 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h +05c9d8b400726b0d87a72783f40f17a2a061c31b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h +6a2add07f71f904a80881847adbb4576860c245d - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h +a084e9fcbfdc195d063eee7f1561a5b311238aa2 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c +6bfed6bf0d3eb45780762fbb929d5d57eaeaaedd - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h +d0a732f21ab78828c622303f2eb7f2ab8e85c92a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h +98bd2a7be1d0dcdf1cc534ac4dfa0adf7b3bd752 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c +635fa9d52596ee34cf2cbf85617657684fb653c1 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h +d1016ddc5354d7e63a3ef654ae6899c8c078ce00 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h +33416277d7d82e170d6f1d7ef205870c003c8aff - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h +282efe9d196e496f3be41e3be701e9dc02c1bfc5 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h +330b138c5e24e14484fbdcc38db468c06168918a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h +80605fd39dfaf3536b1da46e80b450127a5ac723 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c +7c37eb45f9f11ee9f370e775f741dd1075944a69 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h +3ca890e94b8943ef7719c09f20c3a71ad9e60295 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h +fe1e1e2a68a2409c85008f78bb7f4048be6dc1c9 - arm-trusted-firmware/drivers/renesas/rzg/board/board.c +8ae500671f7227739bb3b389ee74418bae4974ee - arm-trusted-firmware/drivers/renesas/rzg/board/board.h +45854b76c28a405b83a3ad2f7975038a6a8a34c1 - arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c +fb75fabcb7a5cccd23dafcb83996362d131b28e4 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c +3e16dde8ddd77df4368ed97df8dedfcd363f2195 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h +08bed1ad3f35993a6b63c3a553c0cd1f817cdf72 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h +313d480f7fd9b09de41195d3fe75df7e06b8fad2 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c +fa65175525fa82bac340b43f6d95f68574a6cd59 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h +987d099de106542df3c8adb7613b27edcfd5cb76 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c +42cec83a589b1e8282a06dc496c09fa4d8019bdf - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h +9850cfe7fffb94712b5526ba4dd947a9cec6efbf - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c +96023687d119cdc2a88f0f96847b71070be44d0e - arm-trusted-firmware/drivers/renesas/common/common.c +d4b40e69b2bea69f35d8d12ed25d623c4bafc89e - arm-trusted-firmware/drivers/renesas/common/pfc_regs.h +eb5eaa562bc901bbcea6e5e722e629a4ffe14fa3 - arm-trusted-firmware/drivers/renesas/common/ddr_regs.h +b31c95edffddbecf9d51e7ba6d57f59b07381718 - arm-trusted-firmware/drivers/renesas/common/qos_reg.h +8e9c2ed157c641c0bec372759c5f0d1a29495392 - arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c +f6c548f6ac120c9eae0551d5ca111a654a28e241 - arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c +04d76f4dff98e3290cc3b56689eea7eae6973401 - arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h +197394f4b9c3387bbbe8ade40aed6fd5ba67cd49 - arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c +81389d507ab4f6c15c8302b9d4a550e929350170 - arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h +ba0424f1fb02f541d26148c808ee8576203fae19 - arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c +db6311bc705a8c1d60a616425947adcee84d1063 - arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h +724917ae7e24d07722880d4b74d6a9730336be06 - arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c +648595ebf99d157ff5bec437919b34a18258b411 - arm-trusted-firmware/drivers/renesas/common/scif/scif.S +23d0235cda981605fc638d9031316ff71003ea9f - arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c +5737620466366563b17443ac716f582a4a0e1e8b - arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h +7c0cd66835bf24e2086572d390e9e42847b2cc7c - arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h +7e6776a062962247d7356aa2a4e3db30e8ec9a35 - arm-trusted-firmware/drivers/renesas/common/io/io_common.h +d954a56fdaa915b42433e7f02b933ff5a7f4d553 - arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h +2a9a321a7d2d3f302f63914ea61c0b24ef77ae46 - arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c +94592c6b00d8f46906214144913018912da2cdb1 - arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h +cc69cc1cdbf38f685bfb8c4e843841fc12c17072 - arm-trusted-firmware/drivers/renesas/common/io/io_private.h +ff8a273a7c0157436d3d58824bb0822c1e4c8880 - arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c +4c9c3edfff804648e78fdb6173511fedc8d655c9 - arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c +b95edfb86992c01b146085a6a3a6fa260f62cfb1 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h +1f0175831d01e9a83091abf339b764707fa15732 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c +da6c00a918a45fb21f34a94a1153a619126f856e - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c +53d888462033b6fd9f510352b7ef5a997db98215 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h +1806c4fed1e8009245193be345f42a0bc99a88ff - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c +d18f211fb0f471b7b72797133ccf3a89ff3fe561 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c +e38e56acce60e8f8ba79bf52ebdccbfbb84e60e7 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c +7526f3b1661670d99bae978d76b826697f8eafcc - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h +e3d0fe455add19648ab1dab17abbf8a036851187 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c +9c78d4764ec4942f586af7e70fa2906b79718e72 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h +ae1066faf4581bdf2b74fc79c6880b4541c50262 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h +3a2172abc0cd0c826ca5c1f958e47c616e2d0c2c - arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c +f81a020bdd63ac732719bf014ffb749bc0f35bba - arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h +e285ce8fb65a4579da74f1406d12000d292f45ad - arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c +26bba8a723b7f85d907e8da853e41cb0ec1bc46c - arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S +3567bb0ce5e977a1fe4ee5a8fed4db8dc67ccca3 - arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h +bbe9ec354aa9a66731a4a68b1214e7c88433e78e - arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h +f6092db4bdf15b55332ebf36fb13af42ee1b8f8e - arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c +24c58c71c66617770ef83cfba554a31128de8f35 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c +55a51a3127d0a24e084fc5ad73c0ddc5d5b2fe3b - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h +b5212a79f0a8c1abb0c5088b5730968747253bd9 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c +f5798c0927729a362f779e583438e52a2da51faf - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c +b014a41cf8b77ed434dc0aaeae7efd1a154065c4 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h +94ab11fdbe4c8a942cb23f6604e8a013e0c6c083 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c +178140849c7796c20b8a14ef9af086d4ffb485f1 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h +1f8f7c4a456ce374f80860dcefeb3a1eed7e1b7d - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h +d8448100b460ddc591a2eefae6d2d0abecab166a - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h +e40feff18e0868d48c4bdcc23024fa824eb612ad - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h +56a16c8b12428935f7d194f7bdbda33ebc432e4f - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h +fe75f352b6a7e1643f0857f578e85a4c301d504f - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c +fe518460e8298941fd3ff47df2330afba56085ca - arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c +08b9d46b2389e6316b27218e1e80071e3891915b - arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h +c11df9b69a5d8144823fe6b09c8aee8c6dac3579 - arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S +11290dbdcaf0fc67e9947d59e3177ac503f1276c - arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c +6173062885150750f1c102edb35796e50d6a012a - arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h +ba3873513a76a74ceff9f6818187870191d1faba - arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h +c2b1735bd5896fe759c99cc8b22c392af5bb841b - arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c +50775f0e3315375d2b392a52b57df2e19834d985 - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h +cb0d0e4e929b276e850cc30884ddfd8846a9048f - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h +bab2ef59fc4f4088c90466ebb4823889a1bf3996 - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c +bd60292a364659d7f11eeecac384213969357c04 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h +700940ac5d64f4902064fbf6670e6e59150d9fd0 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h +f5fd4a9a5d50b214bc6ebdebed3c35ae0f1f2be4 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h +8eea8028ec6b2cd4e6e1c5e0a8d8fd9af01ff4fd - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h +f0db0106cc97b359f7a0ab316784658b79e9d544 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h +12e645da3e7fc81893eb36796412a928fc06e57e - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c +7131d3227d06785258892fe7a42df3c91cc8c9f9 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h +824a3717d01b009cea509c61015e64d1722fc212 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h +a6934a3af85414d49cca5e5d99e162bbe9ca133b - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h +f8c08f7eee854de735ce3c60a3e23d3f74fd73f8 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h +23507b41fbfc9c3a39c4c3f5daf7562d67d10b1b - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h +6ea58175e376d869ac3c2a4f103d934df3c2c465 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h +7c805660400d6f609148f8124439843b39232355 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c +59c0f7639b01b8af843d8142eb013348e6a1ba18 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h +7329eefcfc343e2cafffcbc3a208b34789e57968 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h +b7890473a9576eca8081825037d037349512add5 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c +8dbbe234d937dcc1acc85648ecf831824fb5fa48 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c +bc682493eeddc9cec3b24b5dd37418a00e0c064a - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h +dae17d610957cce3799fa9c9946c0196c67d46ac - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h +8623a6e816d06c37ce20ab1b6e410fc23c052d43 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h +504bd76520d259ea03e8b93380c763a3c17ffeb0 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h +630b48fd35a697ed4d1daa03bfc67d0d299a2776 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h +811eb1fecd60de207e7c92a5986acb80e7ecf0f3 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h +8b5287985d180436c31df99d29c586fa8ddf0f26 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c +6dea13df81dd5a2913039ff42dcb9216eb922586 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h +114cb09f888b76f0b1356fb126a483be754d2cd6 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c +81d4efe56b1d9f4c44c942700d01a9ede1677bae - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h +48f7ee0d258f661040d23d898a98d0bc9c066613 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h +d50c2a6a6c4e4910f4fabd7c774ce1986b97ea19 - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c +21ada158d24d4473b1e20f73c499f4d5600e3c8b - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h +70405034a321bd4ced206115508ab438f2f536f6 - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h +f1b2a6505d48a1a6566f88c1e80b4f27cb09896e - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h +8c12bb78bc33032ca8926351b3eedbe5b2b4c81b - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c +8aa68f57355243a72231c3848caec899565cf5da - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h +7e2114420402542982a251fc6b54152f32b0dd88 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c +10f2fc91f336438e4f2073ea1a665d5d67fb79c7 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c +77f8e84524f8a31cd4e5261eca8974eec4bd131a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h +2717b8ac46d4da69ba6b99a7f25097f9e314aad3 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h +2a066b2fcd7583651082fa57bbf12dfe4352326f - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h +a3a502f90241a6c8f8be7ed9af2e0b6cfe9e59e5 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h +7cbcad70fd46dc5761bb14b31f104d6806752af8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h +758dc7396c31d1186836e5ed6c7cafd0a678b4f6 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h +6b699b1443429c5428b8a7056804ed3da10f02f8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h +bf20ed2160ab9535cba30cc680a7bf881b5a442a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h +a6126e66f35f584f38379a6ee5529fed08edf8d8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h +ec016158b5c3b5502240e5835181cf7929e6fb5e - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h +aa7f8d7b49fdee6efbfc48acf8e8bddb01fd52a4 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h +4c577e5e3e00506da4ab89990b8dae561786e20a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h +3d6b988f34914a47bf479526f1f10849a2ae3ae5 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c +96354da81a56cb6373ff756124b8eee42409bfca - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h +60944cd086bb0354e4747ae185b5149ae3f85f72 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h +2bb5c4f7c8795b5aeecf3a8997f515c4890514ae - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h +fb1b1122066b12b184582d53d643246b1a414b3b - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c +b8ba25ef62d360d72dd17d26934062bc0eeea376 - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h +c2f5bcbfd3751341e871e36cd4d2f278b2a4150d - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h +cf8b9626df3b3f81ae4674acc1f379aaf9eea1b5 - arm-trusted-firmware/drivers/renesas/rcar/board/board.c +ef114d85e930b49c92bef6398031e37cb6afcbb3 - arm-trusted-firmware/drivers/renesas/rcar/board/board.h +3ae8c8947fe42e322d70fb7903ada181bfd006ed - arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c +7a112959b420ec60382c2d5688ddced8ca0affd4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c +5eda21c234b108bb6ed5b65d5e58825ec9ac0210 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h +8472797f3f7c7a334dd21719d4dd718c5df01e47 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h +83dad15a244674be1d30dc0200428aa0e82090e6 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c +c7dfaadbc4d96d1fceadc4fae5536b1e1a9cdd59 - arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c +c248864592a61213518c8881be85e4f65fe0a3a2 - arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h +b9d9644305cbbf1e06e176a46903dd18819761a4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h +cc2f31ac87f68592bc44f9d3435c79d99e7dc0e6 - arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c +6fb897befbc4164b71d8975b2d5322b9e77412b4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c +3802b683cd17e49eba932611e33205446291cde4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h +1a2dd6951973faf90ec734331605c3fb336bde9f - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h +ed9b151f951387e31b4a9fc5a26f0d4621beaf13 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c +a7f9c2cb5010e2bfe1f501830a449d314d447ce7 - arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h +6465a6a55c524b8ffb1dca351757b9d96e79d203 - arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c +c83fb1312ae05c6e624572806f085c6919f189af - arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S +1a38fc90bd2ad3b33e7c09de2e338d2f993efe99 - arm-trusted-firmware/drivers/console/multi_console.c +48cb55cb2ee35cd09c7a0759acecc0e5facfe576 - arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S +b837201998c7093cf24c9131e39734b99ab455be - arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S +c8524aa6f76d32913ffaffda10350b753e429b5b - arm-trusted-firmware/drivers/marvell/ddr_phy_access.c +77e98f136f88749eb01cf7092f9d086cae652384 - arm-trusted-firmware/drivers/marvell/thermal.c +f00e9719e8be0259cb5e171298f2ffb0d09c4fef - arm-trusted-firmware/drivers/marvell/gwin.c +e082e89bfcb90fcea87099285d6eb142fff1f589 - arm-trusted-firmware/drivers/marvell/io_win.c +857ba1731ec174905f4cccd68d02bdd3abf08b6e - arm-trusted-firmware/drivers/marvell/amb_adec.c +b724830f0762dc7701cc9fd88c863c7b53f405c5 - arm-trusted-firmware/drivers/marvell/iob.c +e352b30931747ba506a85329d7c6fe69935dd5b0 - arm-trusted-firmware/drivers/marvell/ccu.c +a275b56587e6c0c05df6a7985ad0cf0e2216e4f8 - arm-trusted-firmware/drivers/marvell/comphy.h +6dc9f5af1b3c165888d4faae36b6da72adb6faf0 - arm-trusted-firmware/drivers/marvell/cache_llc.c +c523b2dcff8e39c5cacc416584d42aa530a93315 - arm-trusted-firmware/drivers/marvell/mci.c +6256615787b3a1bb1f9b4fc3d64794006722b859 - arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c +d0ef41df34b7a9ed1d587f10727ba0ee57d04c83 - arm-trusted-firmware/drivers/marvell/ddr_phy_access.h +6426cc04f9e4ae36d19a6624130d17fd035ba491 - arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h +282cbabd8ee584e3d6c2657cd202c11bbbf31685 - arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c +cd9af6970ea49226ec63b2b04d0b06b86d503eae - arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c +bb5f60fb041d3fbc6812ce56b8976c686be8105a - arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c +9a1f55dbc2fc4e8ca97f9af3e7d435f1bddfd83c - arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c +db0bb43d5c002bc3633403571c9e8c06da7c0ead - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h +4fc44238fa459de070b3ffae100986f736c5e3d2 - arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h +041d0631d9cb0fe39ee3d1f8d20629d3d2225f86 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h +1ceb9ca7a78559ee70cb2833d391d99c2ccb3334 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h +52740dfd3574268d954c81e6a708c55188bca7e1 - arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h +6b20ef2ea4fdeded083ed64a100d2e10cc8c4fdb - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c +dc409874b01f2f616b65f4f9e8497ba172fb2535 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c +02f2c79a0efffc643c301848b83a26b232291cec - arm-trusted-firmware/drivers/marvell/uart/a3700_console.S +10ce6fa5d5bbc4205013818f591e235cbcadccd1 - arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h +f89de6e4fae5d6f6d1778f6c5a92d7f25ab403b9 - arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c +e586fb95d55e301bd75a1db9d6ac7b843f45984f - arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c +5a1bf4459a810008901d22e77f2e66c2af4ca7f9 - arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h +12a1ccf32210f9e1106d8d27942f264ab96f58fd - arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c +627856de3e6c6e4ff2ba2bf3dc3803a13f08d1bb - arm-trusted-firmware/drivers/gpio/gpio.c +b98ff0dbd7f6535bc154869089df5f242b23f799 - arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S +cf240f037fbcd65fb3db19fb6994d2f4aaaa52f9 - arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S +0fc051c6d2c2e54cfe39b37cf1a1f85f883f31e3 - arm-trusted-firmware/drivers/usb/usb_device.c +5506b6895fb8d1c468b2bcaeb55a18fba8ecdcff - arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c +ecd654f25b5590f6fd4dfb3c349577da03a78337 - arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c +1529e10e42582df4a41e7632598e85d97dd59ebb - arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c +9383db5e25bb3e3bb240d302eb1e2c81b067f1fd - arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c +c8a2a84e6453323aa9b1b1cd2a29c6ad56036b5e - arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h +abd5092c485b60d2dc6d910618e64227d766ff87 - arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c +09b3e4f32ad36ab93f598fd53971e18cdb4eed9f - arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c +f0d5a528ed1a6d54f39bc84a21586d25029d60b2 - arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c +6bf9357dbb7589b0078e1896de5a58f760761979 - arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c +dc5909c790f8267bcb9bbc047b904810550cb78b - arm-trusted-firmware/drivers/st/pmic/stpmic1.c +31f2612aff5d24d64b3826cbe5c7a9f93ff7eb70 - arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c +a9d894b2465b17dff1217d99ed6752861aadc069 - arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c +2f6084a9d8f84bf599746cd3288b02a0d4755d3c - arm-trusted-firmware/drivers/st/bsec/bsec2.c +943095f905fcfc655c86f6aca5d3287192546feb - arm-trusted-firmware/drivers/st/spi/stm32_qspi.c +f73a865d9abd49d6a37720d4000b86bc1f6b362c - arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c +f71262877fdd2511c5cd086021c2af9d763f9ec1 - arm-trusted-firmware/drivers/st/crypto/stm32_hash.c +1c77b842fc094c883b8e6abc3522e2a5ed4ebb3d - arm-trusted-firmware/drivers/st/regulator/regulator_core.c +f01b87c2b668e9cc15338565f21d115dbeaf62cc - arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c +27adf1000d6bd7ce04979d79256995a5fbb83b5f - arm-trusted-firmware/drivers/st/io/io_stm32image.c +baededfb86b8f337d27173f84b9cc1bac0556f62 - arm-trusted-firmware/drivers/st/io/io_mmc.c +67125c1a18a170ed78552d01772ae577463e506a - arm-trusted-firmware/drivers/st/uart/stm32_uart.c +ab1a40e17764664876964683ffac32bd86def125 - arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S +6b50346722811da8d96bca6f539f0d5e772d467e - arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c +76ef733f3d1d7b8a934c301f2e05724663827f36 - arm-trusted-firmware/drivers/st/etzpc/etzpc.c +d45d152334200ea2acdee930619eff5f1fbbfb5a - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c +9e30ea137b7c1d34dfae32a3c5180396f6fa8bb1 - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c +f5e59973fc84a601316882610f6aa00a70ec8e1f - arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c +88fb79719982f0a2687d7f693109e940e3cdba9f - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c +5ed9e1be8f844737db535ecd2e049e7d820af601 - arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c +4a37a23560ebb26a66cba83a6a77aafee65a783a - arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c +5324162d65037588a526042c0e40fab08cab0e73 - arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c +07bb0b5fe46d4ebca6c6e1feee9d8a9e7d83d6a5 - arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c +def00bc3c52b54611ea6f11a6f5206cf0b3cc08a - arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c +9d7512560e4e1f8767fd18a115db9ee7ff100448 - arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c +1c35b7e5adf1b63d6732729e7c2113d1ea1a74fe - arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c +28b6eb0d5d5856997722ea707dd42c5ad7448dd1 - arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h +47db01b738865c987fa5dbb3656b6b1dab2df5d7 - arm-trusted-firmware/drivers/arm/gic/common/gic_common.c +0325f0421798955c9df7f963bd6f917152f3f9fc - arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c +20000ccb435ae8423c5a2294ecb47fd7961e90f2 - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c +ff4e151fab3e5a027139f8ccb78ada694380998a - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c +8f83171e122be92a8d5e4b0c5ecb35e4918ead83 - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h +0cdfd59744b1db36c123258d6ed80a21b369e0cc - arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c +209b5b0ef79ee3104941281500febec4c3fa7e19 - arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h +51bb1f43fbcc00eb3e6ca46f5ac069a6a4af19db - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h +702d95a03697ab01bc50559d686681042cec6d16 - arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c +457472881d1edadb4da2a64ec3252636e576b054 - arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c +e1cdb7a1b79c3634ed881efd97a423fca6741350 - arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c +1b9888584629f7d2bc9379be5294ff21dd7cf240 - arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c +d424887230b1ad1f25384d0cc4cdf433911a1004 - arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c +ba14a8e6c0af402979f522f4672707b451266d44 - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c +d830753dc30671474545841791bb3ec230bcb2bf - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c +73bb04bd3b4d9fbaec23c129c93b2e89e276c7d5 - arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c +4d212a96f8ab9a54d15002b53f16df7bcd046e6c - arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c +79f4ef16ca7e0a07b86de03a9a04dcb9c6c3673d - arm-trusted-firmware/drivers/arm/ccn/ccn_private.h +9cb6b217ac9499219fd1bb05530709e1ed53c3ff - arm-trusted-firmware/drivers/arm/ccn/ccn.c +960e4d083c1d4f31df54f443dbe23554889af0de - arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c +7aaa9f31ec7c9d36e48fb2d95a6b3895cbef43ae - arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c +cd0ed71ff125804ccf8f2d187005ce075bc2b8e6 - arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c +80686a47331e2b609be783462ef53eb0ad73279e - arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c +4faf8ddbac2e8bfc4ab77ba7365ff0c50187a2d4 - arm-trusted-firmware/drivers/arm/css/scp/css_sds.c +12e2ef4efff1bfd584d3424cee31bbcbaf0f9a1c - arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h +1530ff134d89ce18b2380b7d03828ec84c8eca25 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c +e76c3b0b1252232e7854b8af9db8a9ce94192cd1 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c +50defd7dfa4e38cf230f830fa7e03358ccfcdbb0 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c +b81d931e597cde97768e39fdad4325133c31b76d - arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c +13cf0f0a02adf3ae0f9e2bdbe493ba7c9b58ddf5 - arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c +e4a68362e5109d4e46f1d720d9b02c8fb20a88c1 - arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h +9b45f1ebc9a189e59d1fdade91bde81f2ea110c0 - arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c +595853f3864138408a5e5b51034dd366cc9a3b7a - arm-trusted-firmware/drivers/arm/css/sds/sds.c +9fdd5749ba87bd5ded91306fd6826fa2cf990806 - arm-trusted-firmware/drivers/arm/css/sds/sds_private.h +e609accbdf6501d2f83400b84b7690aaa2bca38a - arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S +f55aeff6049754049ad1b23958094a7dd255200f - arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S +6dfee94cccd0efeaeda770f83e1d10227886d137 - arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c +4f259f1ca4437445346bfd338702c7c257c31470 - arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c +fcdbc7d1ba6dd59840b82ac787ebf67cf36fe4eb - arm-trusted-firmware/drivers/arm/sp805/sp805.c +c0c5af62081f2d6628a6de94cd6a9507723228e3 - arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S +91c557c46edc8be3bd2e4c2efcf9ef8693a9fc0e - arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S +3777989a45b625cf209fc89bcf8a91a468f52a3a - arm-trusted-firmware/drivers/arm/scu/scu.c +1c897f5bd19b9a4c18e905afda282375cbf4f5ba - arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c +64e24a32626429bd2dad6a02c91a123b79fe7528 - arm-trusted-firmware/drivers/arm/dcc/dcc_console.c +9697dd84615aa7c7da7ffe22eb0e3a38c6ace390 - arm-trusted-firmware/drivers/arm/sbsa/sbsa.c +668315548e4d6f930b744983a6542e01f81caae2 - arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c +ed924dc3ed7f91ecff8a2e441fa5152d9fe2b9de - arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h +73c05b4fdb011d3783f2f3f3ed7285ca58a63cc9 - arm-trusted-firmware/drivers/arm/tzc/tzc400.c +b2e58e1a761614ee8bb95e48797500fcd9f66c4c - arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c +0e845129705069d3fce0df742ab8d56a7966edbc - arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c +d0a784c19a578becbc821a36080372d78af9b3b5 - arm-trusted-firmware/drivers/arm/tzc/tzc380.c +57712978c67a02cb381ba1e9203dc26e762d8b43 - arm-trusted-firmware/drivers/arm/dsu/ppu.c +a9cab74a3aa9f59289ec4dac11558cb1e6e3c2a4 - arm-trusted-firmware/drivers/arm/cci/cci.c +bf48b15b9f75300c1f11366746538bd62a99a5ef - arm-trusted-firmware/bl32/tsp/tsp.ld.S +f2cd83bdbfed353fb47e384608fd41f7b78fc98c - arm-trusted-firmware/bl32/tsp/tsp_main.c +227ccd758b1cf98d27e14ac1ebd5e3b21275d6a1 - arm-trusted-firmware/bl32/tsp/tsp_interrupt.c +f9227b30f6aa21bbf4a178697c37fa714ec54eb7 - arm-trusted-firmware/bl32/tsp/tsp_private.h +6727eccb78b649034342ffa087bb189e40734608 - arm-trusted-firmware/bl32/tsp/tsp_timer.c +8d77cc1453037a319f4a5da2e5b77b37bb406277 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S +e94cc0b80bb21c55fc68026d8a981988414ab611 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S +18772624eeb332566bd8dfe2279187bec9b89fe0 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S +68e3f9565c5bf338271a1445ca22507fb2afc5af - arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S +333a280c5264ca6c42b06d977d15e2fd4809f2d9 - arm-trusted-firmware/bl32/sp_min/sp_min_main.c +abbd0cb6ee3ce9ca8584fa872468754316b868ce - arm-trusted-firmware/bl32/sp_min/sp_min_private.h +5ef0dab419f42df9935d7fbc4e30baa8ea83d75e - arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S +b224dca2e5ea95c46e1062767709b1bb1d7d766c - arm-trusted-firmware/bl32/sp_min/sp_min.ld.S +c1854f51280eb002548e763a01a8af613c615ee2 - arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S +0cd1ab24947e0ea5ce307a171756d88683d36cde - arm-trusted-firmware/bl2u/bl2u_main.c +2d32dba27247198d6cd35d150dc8eeba3c8ed8ff - arm-trusted-firmware/bl2u/bl2u.ld.S +1df1aad13ba7e2ed5cb1ae4a6200d169a1715578 - arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S +738660771364acfab975427664536a581abb78df - arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S +4e66ff242f442cdfb5239bef53026c402990b912 - arm-trusted-firmware/docs/change-log.md +d2e89e46ca5ae89064b0a9b0d7983272a60e60a6 - arm-trusted-firmware/docs/conf.py +cdd7c87e02f5cae26200b35f5869f20aa1a526cc - arm-trusted-firmware/docs/Makefile +0b30444600f51212f5be53588f4f68cba0bf92fe - arm-trusted-firmware/docs/glossary.rst +ea9ab85da5d526fc32f3436878dc80c33fbbe334 - arm-trusted-firmware/docs/index.rst +0677c6b28a895fccae194309f759b9f4e0f4c9f5 - arm-trusted-firmware/docs/requirements.in +0b02d28e0d9881fab1b08360d2d9bbef021685c0 - arm-trusted-firmware/docs/license.rst +ff8ad4850057cbaba3caddae15b9429bb9c42b66 - arm-trusted-firmware/docs/perf/tsp.rst +3e1557ac89eff3ea7cb96e090dcc6cd147117008 - arm-trusted-firmware/docs/perf/psci-performance-juno.rst +840dcafe1996d0299a5922474d7980b6d2eb779c - arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst +a19b41fb4dbff6144a8b5f04eb7c296b63c442d6 - arm-trusted-firmware/docs/perf/index.rst +add0156b84b7d9f7760db313170bf81a672a66a6 - arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png +02a0166ec0c907a8725efa2ff467ea4d5984a35c - arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_sp.png +80b81639bb1aa78723d3635f0359764c595e38c8 - arm-trusted-firmware/docs/resources/diagrams/romlib_design.png +66f1f1fd09b5146cb2a5e1c538de29ea7f88ed7e - arm-trusted-firmware/docs/resources/diagrams/fwu_states.png +d9a6dc06e1a28c0235940539e527ac285c179342 - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png +7c4678ac4952c496df4536445b336d96139b0066 - arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png +19e287ff6d7c25917fd56356da40bee3e5ef120e - arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png +04a65e98eceabb17ea534a6dea187021477a1fb2 - arm-trusted-firmware/docs/resources/diagrams/int_handling.dia +d10eb3ff6f8cf071330205ec0d59126d79f939f4 - arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png +4d2668ab5814fb9b799f65b69b427db29952658b - arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png +961fd0fc52b27792b27c6cc8b9f210be8959e285 - arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png +a0ca882a9a47bf5642759780b006f69f3c667fff - arm-trusted-firmware/docs/resources/diagrams/context_management_abs.png +ada526023821d5e57e3e1aa979b38d2c8708227e - arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png +10d343a1dfde1e76a19cfc7a0f8a9ca28710ee17 - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png +4ab0332c836fdf5e5596c2b7ecc6ea4bccb62b8c - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_checks.png +165d02fd6baf4c31ce0c1b034477b6596c724abe - arm-trusted-firmware/docs/resources/diagrams/Makefile +64d840596ae8dbdfb803bfdd471e3d4e7955ca82 - arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png +84f99bb590f5c8748bc6e47f3e7bd4bf5890447d - arm-trusted-firmware/docs/resources/diagrams/xlat_align.png +77da82b847d9c9a0cecaa2e43e40dac166a66399 - arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png +aacd72a3c084647a884d67147510a1b0c26d8359 - arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia +9bd9241452f165fcc7e5018bf8a24204767fa036 - arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png +c279d33545695cac4327bf14a8d84b4237dc8387 - arm-trusted-firmware/docs/resources/diagrams/MMU-600.png +08ebe00cb9823cd55d80c05b4aaaa64c103093ce - arm-trusted-firmware/docs/resources/diagrams/xlat_align.dia +40ffa83fe202970879802b809b75c10ed360c7d4 - arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png +40dca2e6d5cf7cdc88398bf5e2df39f3fce31bab - arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png +2417a250f3f2552f5e881830e947024a92e55adf - arm-trusted-firmware/docs/resources/diagrams/arm-cca-software-arch.png +763017cfa85171acb7422b0f8ef1c40ba69443a3 - arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png +2e886fd02f6b39a545824f0819608260e0671c14 - arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png +d2522911e613a4005eb1e10931779a1bb350a363 - arm-trusted-firmware/docs/resources/diagrams/FIP_in_a_GPT_image.png +17e11d01f23f073cec01fb44acaa3c976495e982 - arm-trusted-firmware/docs/resources/diagrams/cmake_framework_workflow.png +d5775195107610d6a67d5d7f8af6590e4e53e570 - arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png +a68fd21bb442987ce7a67e0eb08d150b81bfe901 - arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png +b42c9e2672802e26c9137df29eff6a1c68652ea6 - arm-trusted-firmware/docs/resources/diagrams/context_mgmt_proposed.png +c05984305daded35b5f3a14ea3c5ac88319f4292 - arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia +1586bdc989b8698512851e436d39fed8ad375030 - arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia +a6a4256584fddbb776f1e274748edeff4289cf4a - arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png +ad73cbcd10b1b5e45ca3a01df6c435b345686322 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg +2c5f1b895b01d75ebe2fd874d61f728fe18fca4a - arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml +4eb0b99548ee5cdbff9d0e01b3455c7c1e1af275 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml +a2eed4587b5987e97e3f8207a2c9783c5e322c90 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg +cde708741ffdd39f92d8670aea4a93ef451cd611 - arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml +0cbedd3989e3d4fc11c3401d7b250d8b14411c50 - arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml +9e7994a98a6d3531ff8f3c7e16b9e27ae0240805 - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml +2c516abafcee77f3889360526590d0764a35d61c - arm-trusted-firmware/docs/resources/diagrams/plantuml/bl2-loading-sp.puml +7ca50157b91a940fdcd61fed7da54e93501b2c3e - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml +89429fb35fc54ad81b4aab0c9d5860b228aab347 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml +0130e90e98cac66f9ac28a56d8fa17af801ead7a - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml +695a4bfc3f0c50586104d10e16a8527c37f3541f - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml +e357fbb8d83445182b61abea380d1885e484c4cb - arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml +732ce8b12943c9ca218e89a1aa3eae1379952d12 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml +853a892ccba3dedfcb4491b7ad449b46d6a4d47c - arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml +7eb6ecf49d5ec8a975cccdc3aeb0d994e07362a0 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml +1441246fa837376cb589e45510656ca210e18bb6 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst +266a8326bc618859a7a18572589b40f197ed1a82 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst +63e67342811855c2803be11bca43aa4c60543575 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst +5a8ee89be8b54261b0e207ca882fab66cb4db5b9 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst +fab06483aeca0f68846039c9146a6d828ab12518 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst +1b8c8e49a1eac7ac65f01b730ef3d22dee6de50f - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst +48c2d42e738237365f9158ca022d56408ef538e9 - arm-trusted-firmware/docs/security_advisories/index.rst +939eb2b8d82c68d6c9a4e8c1271bd83151818553 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-1.rst +b748a01e82c3ad35dacc68ae9295e4553d57beab - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst +e03dee87868096ffa7982026e20837ddfc9a6aa3 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst +96e5d7607dc9d3c5db2cc3e15eb9b771a429b761 - arm-trusted-firmware/docs/getting_started/build-options.rst +da2d29864297e0b06dc8f7ac1d17288a078ae5c6 - arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst +6914f4b323e042c91ae58018d9217b08f655997d - arm-trusted-firmware/docs/getting_started/image-terminology.rst +6cc854b04d58541fc0e9043f88c7ece6a68c925d - arm-trusted-firmware/docs/getting_started/tools-build.rst +34beaf5d32a409eabaabd8b492f4ffb95daf2b70 - arm-trusted-firmware/docs/getting_started/index.rst +32237d53d0db21dee6eedd6143e60e46dec6d79e - arm-trusted-firmware/docs/getting_started/docs-build.rst +6ea980565b00e400d102f63072c110d6471b0818 - arm-trusted-firmware/docs/getting_started/initial-build.rst +97122206fcc716ab5581232da8de4685ba9e7df9 - arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst +9c961219684a654a9367ffdf4856dd21080cfc97 - arm-trusted-firmware/docs/getting_started/porting-guide.rst +e95ba49d1a46a2db605b69f5425a6bc6069d9a41 - arm-trusted-firmware/docs/getting_started/prerequisites.rst +3fe053ce17752ae01f7d815a5df51f4887d2749f - arm-trusted-firmware/docs/_static/css/custom.css +a3f0b5a39e2120fdbcad8de599b7c1a18345cfcc - arm-trusted-firmware/docs/design/alt-boot-flows.rst +f880dd25cbf380065e9d345752376e40bc756664 - arm-trusted-firmware/docs/design/interrupt-framework-design.rst +9ad5964da55f701221ae3b45b710988621fb10c9 - arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst +b5b729e65177f7baad24fd693c9b5a9993c50776 - arm-trusted-firmware/docs/design/firmware-design.rst +ff4749d1e71cf1665bbc340e11787c971b395fbc - arm-trusted-firmware/docs/design/trusted-board-boot-build.rst +af63c8f1c70b2c589dba26872e3ba5244236722f - arm-trusted-firmware/docs/design/reset-design.rst +d789165adbc9c0e0ace7d7326f1cf7512fa63c88 - arm-trusted-firmware/docs/design/index.rst +6e60dedac282498dc34de3ebcecd6f0119e7348d - arm-trusted-firmware/docs/design/trusted-board-boot.rst +ffda28459589a0ec22cacc12c5b92103ed64fbbc - arm-trusted-firmware/docs/design/auth-framework.rst +b15afee5cbc5225a2ef2f709e9761fa2cd73d65e - arm-trusted-firmware/docs/design/psci-pd-tree.rst +11abe92eab64d997319223639ad2693b7f7c8535 - arm-trusted-firmware/docs/components/arm-sip-service.rst +75d075c879040f97f06e2a7b3b6bd34df86b48ac - arm-trusted-firmware/docs/components/activity-monitors.rst +3018701b7ef2e5eca172d3608726f506c4b22909 - arm-trusted-firmware/docs/components/debugfs-design.rst +a4af3a93464aafab3bb5428082fa9dec58ed73b5 - arm-trusted-firmware/docs/components/ras.rst +72ac59432a0693df36a09334d6f57a6f9491189f - arm-trusted-firmware/docs/components/granule-protection-tables-design.rst +ec0ac249385853eeb84cc0e4151f612b9d23cadf - arm-trusted-firmware/docs/components/ffa-manifest-binding.rst +8a1dffa8292f295ef5014ac04a74011b4aeea398 - arm-trusted-firmware/docs/components/exception-handling.rst +d2201aab60e237cccd20ad636c8ad4224d7f0571 - arm-trusted-firmware/docs/components/romlib-design.rst +9db58fa601138b8e16c395f19913a1f106be570c - arm-trusted-firmware/docs/components/realm-management-extension.rst +963a2ee9d3bf60564d3ab545fed12694fec33fff - arm-trusted-firmware/docs/components/cot-binding.rst +193002dc879b3270f34cff05228d20d88d099fce - arm-trusted-firmware/docs/components/index.rst +b8d62ed8d8e52992c481b3f032a11c132ddc32ca - arm-trusted-firmware/docs/components/mpmm.rst +164b5be074959cef709b8de7cd264d2b720e0386 - arm-trusted-firmware/docs/components/secure-partition-manager.rst +5064b1a7d15e72b127c8fbacf8f11b087446958a - arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst +aca3aea7df00338e307623d4735b027b76f48985 - arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst +ca2c86b55376dc70e6bbbb76058286ac38e35ba0 - arm-trusted-firmware/docs/components/sdei.rst +602d20bd46337be44a23550620a7a1f748130fb9 - arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst +e267bb8c86ec7cc1d683daacbb53bd387881178d - arm-trusted-firmware/docs/components/firmware-update.rst +1d91355dae9ce87dd6d332bfe96019333abb6da0 - arm-trusted-firmware/docs/components/fconf/fconf_properties.rst +d795da44f403a2a0bc4010ba95915fcabbef3c31 - arm-trusted-firmware/docs/components/fconf/amu-bindings.rst +10529cbd50c1b2a10d7bf7669a515a30f564db2c - arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst +c3411adb08049c0735f5b9be29bc976bbcde69c8 - arm-trusted-firmware/docs/components/fconf/index.rst +e289a8345f0c801d0e1d079b94c6752a31a28396 - arm-trusted-firmware/docs/components/measured_boot/event_log.rst +f39c4c5b080cb5537f0260d9f3e477e02aa63bfa - arm-trusted-firmware/docs/components/measured_boot/index.rst +68d992f28a446b0ffe6adad209b6189f9f0dd6a9 - arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst +e583074d9e81fffee8804f560b145fa486f1aba8 - arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst +ee5cface9280894c7d9860dccb78eda3849c9cab - arm-trusted-firmware/docs/components/spd/index.rst +5d7421fde74010efb451e6e515079f37ec3227e2 - arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst +53f0692ccc04d5d659e88ac1dc1080af6dcda94d - arm-trusted-firmware/docs/plat/qti.rst +f8d9d0b4336229fecb1a12937b0f1a9b6060aa0b - arm-trusted-firmware/docs/plat/xilinx-versal.rst +2a492964dd82db785e381f828fae2b2a729f6749 - arm-trusted-firmware/docs/plat/meson-gxbb.rst +1fb07134c685f21246757d77653a8c6bb12d949c - arm-trusted-firmware/docs/plat/socionext-uniphier.rst +8b88e9d6cfe72a03efd7e226122d5cd33334fe66 - arm-trusted-firmware/docs/plat/ti-k3.rst +2ed0c805bd3cba59619101f0918aeac59d4e6fd3 - arm-trusted-firmware/docs/plat/rcar-gen3.rst +b54be1ac4f13d0a724629f301e245bbcc4379d44 - arm-trusted-firmware/docs/plat/nvidia-tegra.rst +a970558632482b93ee96aba756982061d20ea4e8 - arm-trusted-firmware/docs/plat/intel-agilex.rst +12b7c2db7722b49705438fabf8b96c0943d163bd - arm-trusted-firmware/docs/plat/meson-g12a.rst +15d03048959cdd154b540a3b91f7aa6b48f7a7ef - arm-trusted-firmware/docs/plat/allwinner.rst +ddffb1cc078fd2d3c58ed8cde2b32388ccd532c9 - arm-trusted-firmware/docs/plat/meson-gxl.rst +a6c4746123e21eba44253912da4e92f0fd31a6cc - arm-trusted-firmware/docs/plat/rz-g2.rst +0db6c8e13659db1d29238baa7d8a870a4e821546 - arm-trusted-firmware/docs/plat/stm32mp1.rst +a928b648d0677930c926401b40e335f052e97be5 - arm-trusted-firmware/docs/plat/mt8195.rst +9085fb1504d30c5d3e75304a86dfa8a1225967b3 - arm-trusted-firmware/docs/plat/qemu.rst +d714f1279de4aa5eb4519255578a2718fc8e3a1e - arm-trusted-firmware/docs/plat/imx8m.rst +4905e051c0a996867dcc2389b8bd5430b0741699 - arm-trusted-firmware/docs/plat/imx8.rst +9e85f6fbc5306c4b0604e98de5fcbddb385c4ce1 - arm-trusted-firmware/docs/plat/mt8192.rst +df909307e45e07ec88f455e8ef27abedd18e3592 - arm-trusted-firmware/docs/plat/rockchip.rst +f2bbe77ac618ba9be663de2bba3cee62eaf17f60 - arm-trusted-firmware/docs/plat/mt8186.rst +a06622efc4dca7ce03e6ea2e305e8a0b8d422bef - arm-trusted-firmware/docs/plat/deprecated.rst +45f03fd73a50f2fe124a2bd1d70fb40243ba0e82 - arm-trusted-firmware/docs/plat/warp7.rst +028d90ceedfb507b0ee1532f28cb8842f1f5b19f - arm-trusted-firmware/docs/plat/index.rst +84cb8ce1de6f042d0693d8a1a4bb2265ef8a7ed0 - arm-trusted-firmware/docs/plat/meson-axg.rst +080191f60f9e441f7527257b977a2c8f6d8c5533 - arm-trusted-firmware/docs/plat/poplar.rst +9bfeb07c04a47aacac6ae649f75799c894e74067 - arm-trusted-firmware/docs/plat/mt8183.rst +05664e895ce6375be6ad98e9576013d1209cb012 - arm-trusted-firmware/docs/plat/hikey.rst +a80443b8a04209092463f6005843be7eb0dc832d - arm-trusted-firmware/docs/plat/rpi3.rst +556090a5f980031e56bccbb5c6d93f41384aad09 - arm-trusted-firmware/docs/plat/intel-stratix10.rst +d0ad3f088b7307bd002023c2fcda2de07a36f40f - arm-trusted-firmware/docs/plat/synquacer.rst +3cefd2238957aeadfec4d578846bb38b56ca5c26 - arm-trusted-firmware/docs/plat/hikey960.rst +ed1a65471d042b402028616f2e38ed56b42dc891 - arm-trusted-firmware/docs/plat/qti-msm8916.rst +25ec8ee5167ea3d60afe26566de20782ee6aa44c - arm-trusted-firmware/docs/plat/qemu-sbsa.rst +4b9ecd5b7418c0a333435d823205f0569bf5e668 - arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst +01b97fb19ab7a8e8baa5a1a96d35f2cb5dc0a05c - arm-trusted-firmware/docs/plat/rpi4.rst +de25efbc7acce27ba0385c2c51a59fbc0f7f7124 - arm-trusted-firmware/docs/plat/brcm-stingray.rst +ed3ec7c6e5baceda79c359ce661ac80dbf660d61 - arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst +231fc05a0b2de9270bfe513d92b37243b1cc9601 - arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst +5d7bd6f5908ace2c36015e0535f2deacac9a2956 - arm-trusted-firmware/docs/plat/nxp/index.rst +7b3072f9759a1fe276a22dcb70d936006608d299 - arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst +e5e2720a56dd4b68568aae99f664a7478121e8cf - arm-trusted-firmware/docs/plat/marvell/index.rst +5315af3195d5a7c46ec750dccbf4f684c0df4e81 - arm-trusted-firmware/docs/plat/marvell/armada/porting.rst +c143e2ca6a4cf9f94d9017f083b9d5dac2a5167d - arm-trusted-firmware/docs/plat/marvell/armada/build.rst +3b71f880342eddec219418df7f6e6034cce505b5 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst +30afe5cabdcd30362317ee05e9fc4203912e1e30 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst +4496a36f12db50b8075c93550ad2b7a23c24e490 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst +0af03a25bc9938840be478afe1f0c3375e852dc7 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst +bcb055e4f5b81eda0adb88f8b79f78b72b1332b9 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst +aa2be0dce19adf3702025c84d42587a8d1febeb0 - arm-trusted-firmware/docs/plat/arm/index.rst +3abb2d351f8ba63685ce15c862339db9da2d3ce2 - arm-trusted-firmware/docs/plat/arm/arm-build-options.rst +839b91011a0ebdde7ac9b056ab0a3b087ef11114 - arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst +09ec3654ccddcc7942d92d28d1cf1ccc973ba893 - arm-trusted-firmware/docs/plat/arm/tc/index.rst +e2a46aa8e82f95847753a68a0be016142edd63d4 - arm-trusted-firmware/docs/plat/arm/juno/index.rst +a845be9736fc1cfcd3cefda5b6a0bde2419f9bc0 - arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst +dc03d6c732257847d92bd05db0e2b93163870fd7 - arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst +b2ee822aa3f35f04c12fdc9ab44cd66e70b96f38 - arm-trusted-firmware/docs/plat/arm/fvp/index.rst +46e0aef67518d4e85f7b3f9dc17b5e3a36fc9640 - arm-trusted-firmware/docs/plat/arm/morello/index.rst +b10bad88c8647f9ecfe8b3bad163830573cfbdc0 - arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst +5d47110e0bea04401c509ac372927b21ea650e12 - arm-trusted-firmware/docs/process/contributing.rst +bfb4f8dc9ec952cc5582f0a704de50db89072cf8 - arm-trusted-firmware/docs/process/code-review-guidelines.rst +3f4a6d7ff70fb05d5b604632a17c4f84f8c5ab3a - arm-trusted-firmware/docs/process/faq.rst +2e72ba549eae51afb536d262d8daa4d81aa9a18a - arm-trusted-firmware/docs/process/coding-guidelines.rst +b69510d5984b9f3bc4ecb789acab9ba5308eb6b6 - arm-trusted-firmware/docs/process/index.rst +9fcde12a65498faac5c43825aec87d7fd0f2ecb2 - arm-trusted-firmware/docs/process/security-hardening.rst +642d7817092741083f4726c2c178f0c3d0e9bba2 - arm-trusted-firmware/docs/process/security.rst +3a4d85651ee64cc9eeb924af2325478bcf1f71e2 - arm-trusted-firmware/docs/process/coding-style.rst +0f5d2a3f45d1b5b5a634ea677c87983ab7a5e769 - arm-trusted-firmware/docs/process/platform-compatibility-policy.rst +947dfc47181528100c27204431008074dead97a4 - arm-trusted-firmware/docs/process/commit-style.rst +6fd5a13007e2c86b56b83ed08af9e4343890c44d - arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst +125013620e921736b4b48b912f62657eb06ae363 - arm-trusted-firmware/docs/threat_model/threat_model_spm.rst +6370cee0ae902a8040401edd8f2ce7aa0d67a170 - arm-trusted-firmware/docs/threat_model/threat_model.rst +c39c2e4ba3f12fbad74aac5304a27e5b3c3fc272 - arm-trusted-firmware/docs/threat_model/index.rst +3c9105f13eb03be1b0c0035eb88daafdd219f4a1 - arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst +b5585102476dfaccde6a472ab5485236468a4d14 - arm-trusted-firmware/docs/design_documents/cmake_framework.rst +1cf19041279928d9215bdd8c91a1559b37e426b4 - arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst +458dad419f00db20225a3987ea193db385391688 - arm-trusted-firmware/docs/design_documents/index.rst +3d4d6eeef77d8e11c9b5da38bf3008531d4cdff8 - arm-trusted-firmware/docs/about/acknowledgements.rst +4717f5ce955ade54d71c40eb4edc26c2ae63540a - arm-trusted-firmware/docs/about/release-information.rst +d0aa75e869685b4dadea831588e9175113411e43 - arm-trusted-firmware/docs/about/features.rst +bd485ae1fd78b7134ac1b633b73d320c4de37262 - arm-trusted-firmware/docs/about/index.rst +b797ee1a8501bb526a8f4e22f7bf644d83ffc96d - arm-trusted-firmware/docs/about/maintainers.rst +15453cf4faa84e1c067c1b9125f90e625547f47d - arm-trusted-firmware/docs/about/contact.rst +d04e79c7e2d1ff0546074efcfda2290f20c1c923 - arm-trusted-firmware/.husky/commit-msg +fd32ceb86780ba4682d238401c5bdc6c51f6652f - arm-trusted-firmware/.husky/prepare-commit-msg.cz +edf09f8f672ed108a22d57c3be9c64c542957347 - arm-trusted-firmware/.husky/commit-msg.commitlint +201f68ff32e77e6400dc5624a726bb46fafe1ac3 - arm-trusted-firmware/.husky/commit-msg.gerrit +11dae66f5031e4fc368d8b20d11916dbcc90b1c0 - arm-trusted-firmware/.husky/prepare-commit-msg +3a094362be710094e9435bc1e4d7eebfa468338d - arm-trusted-firmware/bl2/bl2_el3.ld.S +88bbfcb3f9b827bdab7f16cdfe892b2aa1470576 - arm-trusted-firmware/bl2/bl2_image_load_v2.c +0b07a71ab893d39e7884f11f46b95245ab0cf303 - arm-trusted-firmware/bl2/bl2.ld.S +991c05cee7a30247e2edcade94405aef95480121 - arm-trusted-firmware/bl2/bl2_private.h +d8756b1a7295709e6757c7dbfc53741267823e2a - arm-trusted-firmware/bl2/bl2_main.c +62ef4221f56feaf0907dbe17cad47a9bab86bf03 - arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S +c426fa02b617581d2495667828e9430110cf713a - arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S +247751d71fb2863f439cc217ac18c219dbf15453 - arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S +776c1699268eee43ba9230cb7e785e298e56a233 - arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c +a34048b4cc67bca14b7594e2c1a53b4c0376d779 - arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S +777576955f2ae3959035c33791a33835fe6578f4 - arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S +e514ace46685e16066700af9ec41ffbfa825b369 - arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S +e7ec4f132c5a2ca9bb5f999f47079e4d473e77d9 - arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S +f64693060b1ef904b4abfc04b8480a0f458494c5 - arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S +2534665e628b7612c3896fed4e659f3351601296 - arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c +aac463ba1d35408d94f960ade6d2db95d68455ab - arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S +b296aa0c1c6575bc1a961fcbf21420aa5e6c0d3b - arm-trusted-firmware/include/bl31/bl31.h +89971e627f1aaad3902b29c72eef83520766be40 - arm-trusted-firmware/include/bl31/ea_handle.h +40a0dcdf3add2805bf312c4548d2ee377fc8e4db - arm-trusted-firmware/include/bl31/ehf.h +6d533c4b5b87dfa62fc19f93ea9a2a7d91fa7e0a - arm-trusted-firmware/include/bl31/interrupt_mgmt.h +f237c837e7f3ca6eb78a837961cc378136eb56a4 - arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h +5c7d53dffc9e4dbe1b29a7a3f2c66a36954dd32d - arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h +4b89cad3c01b7767a5a3a13de49705b2cb3e7f9e - arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h +e0d1075d19bd35b9bf189dad00ef6b45991c1bf0 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h +fd1e043f322c708de5aa529250ef0ca7430cc508 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h +bd297c8c069baf4894e271462ecd0387ca142d2b - arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h +f8dfb28848429d1ddd93107a95f47d8c6701e359 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h +080c331a370bfcf9f9ce11ccdc89838ea7fd401c - arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h +f28db646c8bdd11bb9593e0d241d924482a7d3ad - arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h +b7307a0a106f93b2429fa105547d42bc65f8afc2 - arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h +0ca59c4b41f2264bcc0d4b45550b8a587211aece - arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h +c5098c5b107f74cd689ca039a39721bc1ecb7523 - arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h +7efe8c0a3fbb4e9b29850fac16b475c45925c6e3 - arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h +56af3734637f9dcf2f75c88aad9614e515be1570 - arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h +3a4737826d5e90e262be765553886dc9b2cad966 - arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h +eda413e9067c54fd7cb0718642eb3cb770fb5c79 - arm-trusted-firmware/include/services/ffa_svc.h +53e733abf11ec08954e5e64474973896323d428b - arm-trusted-firmware/include/services/arm_arch_svc.h +bd59ae9370224873185cfa4dfc1459db223f86d3 - arm-trusted-firmware/include/services/spm_core_manifest.h +d02d80eef605a92cc293597811496a9801e4761b - arm-trusted-firmware/include/services/rmmd_svc.h +583482e243ae52386041c084650c8579a1f113ab - arm-trusted-firmware/include/services/std_svc.h +3b7a4c6d6c8ce3c42694e589dd7dd5d4ed7a4ced - arm-trusted-firmware/include/services/spm_mm_svc.h +18b02402ab43e28399a4a595544148f960b65c9c - arm-trusted-firmware/include/services/sdei.h +30872b92c4859ac9f8e3a28f996c947b74edbb61 - arm-trusted-firmware/include/services/spmd_svc.h +f9e8e6beb1285dc1b188488dc9a217ba805b04e1 - arm-trusted-firmware/include/services/pci_svc.h +6b3525de0de5c707191677733b6c49dba80eed96 - arm-trusted-firmware/include/services/sdei_flags.h +d3bd4cf8e1c91ab4b8019456b7e19c3fd4675567 - arm-trusted-firmware/include/services/spm_mm_partition.h +5d3f25945b7e037c8732ee7c4702366e6ceef5a0 - arm-trusted-firmware/include/services/trng_svc.h +1f0f251429978e8646a05d91d3f3263364aac596 - arm-trusted-firmware/include/services/trp/platform_trp.h +718add17082d7b0f4631c4aa87879e2dbc634426 - arm-trusted-firmware/include/common/fdt_wrappers.h +b46a10bce55c312c93a16f506296f5642158a823 - arm-trusted-firmware/include/common/asm_macros_common.S +dc31b12d8e0fe348d049aab169721695d6414bc2 - arm-trusted-firmware/include/common/bl_common.h +835fd8c82abcfae1bf3c5dceb1123a8b2bfd587d - arm-trusted-firmware/include/common/ep_info.h +1fb3546ddcbbdb34f1bd8c5532fde531ed03e4fd - arm-trusted-firmware/include/common/runtime_svc.h +1d8edfcfadd6f5b8724ad6ef3530f09bac04d2b9 - arm-trusted-firmware/include/common/fdt_fixup.h +561b168245611d5de641a636b5d632f02dcab868 - arm-trusted-firmware/include/common/debug.h +816190a2de110539cf90ed91f279563c0bca9a18 - arm-trusted-firmware/include/common/uuid.h +9398e9281edb3916d9f8b25e4ac909538f93d5da - arm-trusted-firmware/include/common/interrupt_props.h +b0aadb059bd035c38b54ce8f2f7690b49b417e5a - arm-trusted-firmware/include/common/param_header.h +0adc1932137e9f09ebf8948f60d0bb0258ad0249 - arm-trusted-firmware/include/common/tf_crc32.h +cbf9eec4b4cde89881d2efe44be1dde85d9b6b0d - arm-trusted-firmware/include/common/bl_common.ld.h +9acd7a0a005acdb9eb6ee122677ee9528b36b6e0 - arm-trusted-firmware/include/common/nv_cntr_ids.h +f3ec87cdd303cc80ab1975ee4c970c1d72f2a1d9 - arm-trusted-firmware/include/common/desc_image_load.h +3061ebcc5cc39e9b66461188d5eccd5bef4173d0 - arm-trusted-firmware/include/common/image_decompress.h +5afd89832d7eb27979b6864884c4c5564a60279d - arm-trusted-firmware/include/common/romlib.h +22b063584c188624815fe5a57f199b9bde282c6a - arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h +b1bbf25afc02647d5cf3c2de70985599ed6bf6ea - arm-trusted-firmware/include/common/tbbr/cot_def.h +1d2a96df860280e160ab95e4e51e622a5f546aba - arm-trusted-firmware/include/arch/aarch64/arch_features.h +a014d97e0b18ddd183f03615dfceb42612a05862 - arm-trusted-firmware/include/arch/aarch64/arch.h +40e8dcbc93cae746d0a5db7109f8c2d55204cc36 - arm-trusted-firmware/include/arch/aarch64/asm_macros.S +04b3308044a6768acf0bad187fc2b69cb69a1fe4 - arm-trusted-firmware/include/arch/aarch64/assert_macros.S +ad144423428ec92ff7791f7e65475d8179b74ef7 - arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S +d35ee46e0adae54b398a7fca1dfb048e883b5ad1 - arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S +ed984eb0f0ed8079b711d378fe82a35a98c45803 - arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h +3b667906d524c05d363bb8341f5241bbe7d80fe4 - arm-trusted-firmware/include/arch/aarch64/arch_helpers.h +82b34ecc6637bf3745fec6a4d1cbc29e06e8e19e - arm-trusted-firmware/include/arch/aarch64/console_macros.S +6a8e3ed67bce468bf878dee9e257722a13c705de - arm-trusted-firmware/include/arch/aarch32/arch_features.h +1ac6bbd72fd5efcdea46d665f3b42539e55d19af - arm-trusted-firmware/include/arch/aarch32/smccc_macros.S +e2b5aa5f3ed136a6b09905c047bcd4bba696b753 - arm-trusted-firmware/include/arch/aarch32/arch.h +c2be1c93cd54c4e39aaf2aaa3a0efde1a237ae5d - arm-trusted-firmware/include/arch/aarch32/asm_macros.S +7473145f94c25355b413a071f083825a5bbf2ce8 - arm-trusted-firmware/include/arch/aarch32/assert_macros.S +19edcf9b1fb1a08230c93e3bfa026e7b33cd3ac9 - arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S +0e8c93e8e2069b7b80576b88757ad99a54dabc15 - arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h +68d3700bd1027d9b9ce6280954972329e2653b9e - arm-trusted-firmware/include/arch/aarch32/arch_helpers.h +707cddbbe6226e2efc883af7013f08afced5a708 - arm-trusted-firmware/include/arch/aarch32/console_macros.S +2953c9cd650429f472333ef0f7cb9ab6c69488c0 - arm-trusted-firmware/include/bl1/bl1.h +f3d565fadbf6176b3034b8359d22fa8c03772f95 - arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h +c8f57a02330fc21d063cbfa19b558cbd20de2787 - arm-trusted-firmware/include/drivers/generic_delay_timer.h +c6f581c377a1a1670d1dd54c360deded41593d6f - arm-trusted-firmware/include/drivers/delay_timer.h +3fdd5f2bbd8585722f7176499884e963fcc1806f - arm-trusted-firmware/include/drivers/console.h +3d13f3cbff61918c53bb0a76876155dc82337fe5 - arm-trusted-firmware/include/drivers/console_assertions.h +e52b9017a122dbf25d5764491104335c6a166dd2 - arm-trusted-firmware/include/drivers/usb_device.h +8709de3c5655138d78511772539fb29a8b660364 - arm-trusted-firmware/include/drivers/scmi-msg.h +32b681b12e18f054ea32d70a554e9c07ff59e4f5 - arm-trusted-firmware/include/drivers/spi_nor.h +d73de0ba3c3a5f28ea6d778b2dcb3ccc7d76c74e - arm-trusted-firmware/include/drivers/mmc.h +1e85ce64c0bc0c37f1c87dab8859540aadd4d842 - arm-trusted-firmware/include/drivers/raw_nand.h +061a6a5d58a19fa40602dcb1c9d1042a206ad73e - arm-trusted-firmware/include/drivers/spi_mem.h +58d9040bd23a07f657047c01fbc92a62b9b04d45 - arm-trusted-firmware/include/drivers/clk.h +42c0f53bb57374cb007e6d5c3d4d536db4069f15 - arm-trusted-firmware/include/drivers/nand.h +b11f7ad45072a13e91bd01040adca94742f7cff1 - arm-trusted-firmware/include/drivers/gpio.h +beb3e629b953dd33bc44df27d3f0b251af4a75e5 - arm-trusted-firmware/include/drivers/scmi.h +9148c938d74351967390c1286566f167d1915b59 - arm-trusted-firmware/include/drivers/ufs.h +80ffbe42c480534b02989a02a37fe24a316746dc - arm-trusted-firmware/include/drivers/spi_nand.h +bb163896fcf9655f45d24b8676ea0a79a6c28272 - arm-trusted-firmware/include/drivers/dw_ufs.h +41a9e785cff8ee17c58544900ad2cf351862fb31 - arm-trusted-firmware/include/drivers/cadence/cdns_uart.h +ccb0701fec1000c00375edbf0318bdce6617b109 - arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h +3e33fa498602a762c87ce6d18b27e00fd4d9e153 - arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h +141c6ec9750c86044338eb19ee622331b9a6c0d8 - arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h +aabedc9062342279b677c72861038190cfa65939 - arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h +7989591e2a2162069486ebab7e2728208c51b5c2 - arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h +69289264b7a28a5ce23aa04ce828d8b4af255860 - arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h +ce837ddd809c0d8f381cefc82d212e9a1a20209b - arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h +eb200bcc06472d689f3a7419f0710c4c3d8ce0c5 - arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h +460f93da77ff4c52f61d06eca41dc83c56a92b6d - arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h +66189a3d70ccfb57441e34458abfc9cd72c29d19 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h +fc12ffe1d77603728f2c875a296218ae6cddb095 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h +91adf35b394ad394248624343b9c5b19fa0c2b09 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h +bf836adf23266f3749b5e68af59a31d0ac0ea00a - arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h +57d421cf90453e8aa05285508bc43ed0e325a7a7 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h +2c95c38a7f65a3ef7eb3992c7136879ef75e4c7a - arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h +8308e3c4607508799254cc82d52ec5d4aba905e2 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h +2388bdc4442c2695122e844d49738f95b18a84cf - arm-trusted-firmware/include/drivers/nxp/csu/csu.h +46896393ac73e49d174031ad9db2b897a5a53cd5 - arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h +95b4d87dfcfc29bdf2b6cd0bbb06749112243507 - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h +060901911b3564bae52c8476be0a91ea019b2283 - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h +99694a5f2e9c541d163aa4fc3bae8f07cdd32b4c - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h +e81281948e932f6635309e0cc817672144dd5cc1 - arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h +3d4947f956585eb9cfe3b8245ad4c1749cdc72b1 - arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h +7f0601b767be7522d2b3b053924b860224900737 - arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h +cd9ce08e3ca357e9ac083fd384e2ffd154288032 - arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h +4453a2af06ed170ae6c69f42b415c69314fd3d9b - arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h +225ffbb6a71c970da33f40390a7828768770c824 - arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h +b0e9643a90314ef89452944214806403f53b7b54 - arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h +4229b536f33d8f4775076953d8c91ea47ad378a5 - arm-trusted-firmware/include/drivers/nxp/console/plat_console.h +3b20fa259fde3f160db7996e9571edfc5ab34bc5 - arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h +90e8213c057c2449b5ba645b49e85458c0dc2e43 - arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h +a38ba636dc7402ba5f0f12fac9db9813190a8c39 - arm-trusted-firmware/include/drivers/nxp/ddr/regs.h +2b66abb34254db06ee8c88f5e0596c908b2d2026 - arm-trusted-firmware/include/drivers/nxp/ddr/utility.h +d0fc8c7cc714365c4b36dc3b12083432b0173dd3 - arm-trusted-firmware/include/drivers/nxp/ddr/immap.h +190e1845f17fd2f9c9e7fdcb31f62f22735c2401 - arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h +f76687e9c42877c6684b9f0f42809be11e898f2e - arm-trusted-firmware/include/drivers/nxp/ddr/opts.h +d8d9fce57d178fdfd41f5be63879bfa85d2e2e15 - arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h +07aabe0c38fbe8ae82313542589e8b6013f0a704 - arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h +26748e486ff05a3ed33d842cba65e4fecc362aae - arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h +56618eda200d872addc06447897a8b7ec619ffb8 - arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h +3584254639e10b77ffd6ccf07f7a59923b337ffe - arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h +b6baa4f2facaae8fcb1873db219796f86e62cbbf - arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h +f75c54f08edcc8069804184e40a6d8a74d3d1b42 - arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h +be8a6b00a6db26fef151d90020cd12c856e4cacd - arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h +490bae640af8d15a10cc4a530a23cd51226ca709 - arm-trusted-firmware/include/drivers/mentor/mi2cv.h +1fad8ad24347aab9e6da6d46f5cf581f938d2ab8 - arm-trusted-firmware/include/drivers/allwinner/axp.h +0601d762e1bfda8d93d085ea44202fdbff2d1ad9 - arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h +1c35b8d1dd99e2556585b97e6c5f472b95565fd0 - arm-trusted-firmware/include/drivers/amlogic/meson_console.h +598adf21c9089a664c913fb3faf852fa36dddef8 - arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h +04cc0e519d24a6729fbf6f89e981eaf992fe19d5 - arm-trusted-firmware/include/drivers/brcm/sf.h +2a62cccb75603f1abe573a211d9b149826e87356 - arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h +2dedb1c6a08bb98fab574fbb49becf23a0a40b3d - arm-trusted-firmware/include/drivers/brcm/dmu.h +3b8d411ed511e8d5f5cd285a04229eb0779c2609 - arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h +907603dcc9f90f3393201ab4a2a5c8ce32f61543 - arm-trusted-firmware/include/drivers/brcm/sotp.h +542f2f80df9c9b264f0bfc9387e38e99ad2a9e7b - arm-trusted-firmware/include/drivers/brcm/spi_flash.h +823fbabdd578bbfbf92d8a2d68e8d7d2c3f652cd - arm-trusted-firmware/include/drivers/brcm/spi.h +f1e9babc3d5e854ba472c64f889f2fb01138cff0 - arm-trusted-firmware/include/drivers/brcm/chimp.h +67ec9883d9b0ac3959b68dcf32dbf8d8fbc84bc8 - arm-trusted-firmware/include/drivers/brcm/scp.h +8c4e00a589a41eac59a1e3f7743e362f874b80cd - arm-trusted-firmware/include/drivers/brcm/fru.h +5afc35a13cf962ad7cd0f15b0532bbe11c7ad17a - arm-trusted-firmware/include/drivers/brcm/ocotp.h +5632d0130d0787f77618a2ca64d09d7bc3d2433b - arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h +281ab6dc0343aa92cc689456d9b8b56e7e853961 - arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h +5e1781b653944c224e65bec032fae482c1925591 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h +5657b1337210a575a742026dfa31f3136b5bb625 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h +d6123ce1d15ed92eb457d0e0d13d66841deb34ea - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h +40a4365490452d1db063c69f305c46be1d20e9f5 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h +af14073522c90e3d69b0abc31fd3a2820dc54d47 - arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h +c3be01e418a0c44f650529178aabc99c5fdbef33 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h +eafab2881a9d078ab544df13644c4b47b0670003 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h +869edd881664c3e2332d5b2e6765e7dacbb0afb7 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h +38ad4c8652f178df916a5a1622fad23851187ba2 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h +ba4c82c4f42cf7c6060c7266d23de675e741a191 - arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h +829056e15314b731c22b87d62a2c8606e72e1fb8 - arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h +b5e8788fcbe8f7e5a29ea20b0496f5b331fe6b4b - arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h +bf12d4c88947dab864a8f411bd8b3d752bcece3f - arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h +ddd09be972db2607bb424326a6c8fbb441dbfec2 - arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h +95f57bdb58eaa0c98d1495b69af4481368294101 - arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h +89a898543325d24449f04f9b4f73ab80fe43615a - arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h +bd8eab4d0a2394ab277d17b70d1de2839a83ce04 - arm-trusted-firmware/include/drivers/fwu/fwu.h +53d9f7bd2b149b510835abe889d7520b7f40b916 - arm-trusted-firmware/include/drivers/partition/gpt.h +526e7a59fda5b797d17357c6594325b695dae294 - arm-trusted-firmware/include/drivers/partition/partition.h +bd4bb47e71397b065ce00f2af2e6c24b3a8e1d45 - arm-trusted-firmware/include/drivers/partition/efi.h +1c27aa6ecf64d9c63f2e200bb4b4f34c1493e6b4 - arm-trusted-firmware/include/drivers/partition/mbr.h +e65ada86295c449ba40e5e0d4d1558b8c57e24c5 - arm-trusted-firmware/include/drivers/io/io_mtd.h +53a57c8d46bdf6e3119f7da34bfab0df1ea5be9c - arm-trusted-firmware/include/drivers/io/io_storage.h +fe49b84f7431a3680d29420770e6c5a8e81abd5c - arm-trusted-firmware/include/drivers/io/io_encrypted.h +37187b6d387c4c5065ca5fcf7fb76e54527943c2 - arm-trusted-firmware/include/drivers/io/io_dummy.h +10532a6db736e62308718e7ed4602bcdad21e3e0 - arm-trusted-firmware/include/drivers/io/io_block.h +d44cfbded1853f569ae63d99598504a959d6be61 - arm-trusted-firmware/include/drivers/io/io_fip.h +ea2dcfb76c08ec6fec8d8a369642b152753b0780 - arm-trusted-firmware/include/drivers/io/io_driver.h +65ea10cb954a4eafbc5c1b0e1f4118cece4ff74b - arm-trusted-firmware/include/drivers/io/io_semihosting.h +f255bd6542ce1b5d70e6f1e8d795bf29367099a7 - arm-trusted-firmware/include/drivers/io/io_memmap.h +04830d2bd9eaac4d5ab2cf414e66ae7439c3832d - arm-trusted-firmware/include/drivers/cfi/v2m_flash.h +2a6f91687b0799d7e9d7d79ea9480d7b0f57c185 - arm-trusted-firmware/include/drivers/auth/crypto_mod.h +c7235a5c0dc2db938ba5586b4a94294d0c1cef98 - arm-trusted-firmware/include/drivers/auth/img_parser_mod.h +21f2b4221f273c0afed79420c75126131f6cbd5a - arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h +125b1a75a3651ff04f7dd19ba665ccb6846f3a0b - arm-trusted-firmware/include/drivers/auth/auth_common.h +487e2e7025ad4207cb2dc1e52045c91796c5f00d - arm-trusted-firmware/include/drivers/auth/auth_mod.h +317b0bab814dd8e2cce909a57a2c8be90b0f5273 - arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h +8990234b68caadc3262242514364a5e4326b0c2f - arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h +6092827f0eb5f3c784b6a1da04df8d26918b01c5 - arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h +8d5bb836b8836f486476f20753a83ca09d64567e - arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h +a3de98e4cc085d3cf7d5d52931b5b3623d0a619f - arm-trusted-firmware/include/drivers/marvell/mci.h +2a16f04ed2b2358e61aa3683ec3d1f2b3960dd2b - arm-trusted-firmware/include/drivers/marvell/cache_llc.h +15475b1e40e5c5bddbfabed61f7f24162136b1f7 - arm-trusted-firmware/include/drivers/marvell/amb_adec.h +000c88b50b95ab8b54fed58ab9f840b9bb69e06c - arm-trusted-firmware/include/drivers/marvell/i2c.h +69f49992d9c55ee0e777a11643d0b52001cb7622 - arm-trusted-firmware/include/drivers/marvell/aro.h +9b00b75ebe2ac0600a4eb5f6e9b76c2c77e19a94 - arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h +7f1222ae6a5838bc830b1300ab199a3d42290790 - arm-trusted-firmware/include/drivers/marvell/addr_map.h +6fb4915c93922ffd80c2b7082f5219b13d64a4a9 - arm-trusted-firmware/include/drivers/marvell/iob.h +5c2e0ca868faae2060e6a9f3bf20896783564942 - arm-trusted-firmware/include/drivers/marvell/ccu.h +02710fe143b7937c1b4fad8c1e757146513ac135 - arm-trusted-firmware/include/drivers/marvell/io_win.h +d7bc8fa93e6253a8b9ef6c39613ea88489703b1f - arm-trusted-firmware/include/drivers/marvell/gwin.h +fd4a5e7af241c3b0572f5c9e81decf1868f17fb4 - arm-trusted-firmware/include/drivers/marvell/thermal.h +80057d817a90e75ad1e4eab0e4c81c6a62aa3911 - arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h +9fe146fde5aec71f5cc47d07590e1f76602bc9cc - arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h +1bd923068f35229b4648825afdbe2d5ee74ba4fe - arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h +d9fee9976962b8d9daffbf4d4cb1e7400e14c745 - arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h +898f43097b2545ca29358b143d6e97761f1dbce4 - arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h +d3887ee8e4681e5e21d22c78756f8bb537359ef0 - arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h +8865e3a5b086a9f57937f94373c1488796422a75 - arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h +affa2c8404660a48bcd956f29a50e79120b1cc3b - arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h +a832f792f5fc9564b02d96f85430f190c3f57417 - arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h +431e908bb797e10b7839fe28a0ace7d8a9e7bf99 - arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h +eae4fb4ef015039f57a757e732fbfa815bc9aeb1 - arm-trusted-firmware/include/drivers/st/bsec2_reg.h +16d36c74e72bc40e7ba15ea25ce38621a3dc3a9e - arm-trusted-firmware/include/drivers/st/stm32_console.h +ae8d33f6e04e5baf46e8b00b1613dca79c462e1b - arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h +b0e57331d216261ea6ec7814666ae64bd884dc05 - arm-trusted-firmware/include/drivers/st/io_mmc.h +51b50b86f5dea96ef59764df60f2d64a45d54bf1 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h +eaf998cd31b2112d0a61198a5a7f14d484217251 - arm-trusted-firmware/include/drivers/st/regulator.h +1b6f5d6f48fb0ceab8d15c6308e31e78e85bddba - arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h +173981f3ca549df6d0e56fd0a16e4a055b9151eb - arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h +4cdb146eb6fe5439dec2c5039a903ed5baee6aa6 - arm-trusted-firmware/include/drivers/st/stm32mp_reset.h +b6eb16d19f62ff88852eab346d51d719944f14ed - arm-trusted-firmware/include/drivers/st/stm32_i2c.h +4b9518a5dba55fc1c78dc216a36ce0bb0e045155 - arm-trusted-firmware/include/drivers/st/stm32_uart.h +b6caa41ecb428bd2e6752e1a1f5a0c2ef3fcc953 - arm-trusted-firmware/include/drivers/st/io_stm32image.h +c13f39e45ffdff80cfe87c12423322a15b959794 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h +f2ca7edf66b0d71fec9b893659707c7675f9d0a6 - arm-trusted-firmware/include/drivers/st/regulator_fixed.h +58a87d375953ce331a480d18ecbe92da88b221df - arm-trusted-firmware/include/drivers/st/bsec.h +6c00673ea5fb61808caf3b77e422043972ecafc7 - arm-trusted-firmware/include/drivers/st/stm32_qspi.h +156ba43b85065027d400a1287fa794a828df162b - arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h +7574c3687634e56e414a47e0fb3f5a5d7b1fc708 - arm-trusted-firmware/include/drivers/st/stm32_gpio.h +e02eff807301ff7775369975495cad2a2082972f - arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h +86a1ad6cd3ce837f820ba6c1b9f6ee7182e74956 - arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h +91bfb605e20bff6aead18279afab90eed7856ddd - arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h +e6aa4130f95dc7da0f3a94482c2ee3325afdf0a0 - arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h +967e02371bf07f76cf015635f5a50c0956176296 - arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h +1735a240af4b99862e6cb202fc034231abeb53bd - arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h +ac1cd6d311e2280721ba62f9e82c10322f6dad41 - arm-trusted-firmware/include/drivers/st/stm32mp_ram.h +cfbc99b7bba5966e33409c31f9f47cb7de63f66f - arm-trusted-firmware/include/drivers/st/stm32_hash.h +ff21abb6526ad91314e2f7cc58fa6fd6546c926f - arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h +45a56579470aa4ad7e007373a068f3285f046de0 - arm-trusted-firmware/include/drivers/st/stpmic1.h +bcfc65cd26c42c404b6482da16cdacf6e95c5733 - arm-trusted-firmware/include/drivers/st/stm32_iwdg.h +e86b4fde780cfae34213629b58ff8e1efd1eed73 - arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h +e545051ef77d33ec66036fa94f2d53b51253d436 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h +cacf83dd6e129df0a9ffedbd38bfb757074d1240 - arm-trusted-firmware/include/drivers/st/etzpc.h +ec0355e035856ac49891ebbbfb6b249439fe6bc2 - arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h +f18d30ed876fb854340d329c32144778921ba136 - arm-trusted-firmware/include/drivers/arm/tzc380.h +cd54a5c35b74beeacb16c618204bb31eaa33126b - arm-trusted-firmware/include/drivers/arm/gic_common.h +0f5d3819208e8ad3ef2356f332aceaa4239dd8b3 - arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h +c269f40255323bed655d0c076e5fc771bee91550 - arm-trusted-firmware/include/drivers/arm/cci.h +ea619e78dc1630857e7bca57a8fb64b7d45583ba - arm-trusted-firmware/include/drivers/arm/pl061_gpio.h +3d28678861c6be73909a9fafa1e03dc8bed75dd5 - arm-trusted-firmware/include/drivers/arm/dsu.h +84502e34dabd2a899d93664cb540910ed8183f7a - arm-trusted-firmware/include/drivers/arm/gicv2.h +cad3fc32b992ec321fb47398d69df28d800ddfda - arm-trusted-firmware/include/drivers/arm/gic600_multichip.h +3c63f525fa4ab772695c59df263364d15f606582 - arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h +be5093d8f8d48610060e70ed9a8ee5602ad6739b - arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h +1f2f3ae5b2636732d8a2b76e04392deacdc51203 - arm-trusted-firmware/include/drivers/arm/ccn.h +dcca36bec1c965c6413ab49729c23a771108058e - arm-trusted-firmware/include/drivers/arm/sbsa.h +eb064e58fc5aaf99768b3c9f167e6a369c5d51b2 - arm-trusted-firmware/include/drivers/arm/pl011.h +742d685c4e3046c1a64e99c18d00be7f1f9066fa - arm-trusted-firmware/include/drivers/arm/ethosn.h +2fa5a8cfd7f005b8d48960df0fa9dab5568d8059 - arm-trusted-firmware/include/drivers/arm/dcc.h +abaea50a4f3861dfaa3f55cba235dc00114b68f4 - arm-trusted-firmware/include/drivers/arm/sp805.h +c313d8aea2aa56300528293ebb42d4b35d46b18c - arm-trusted-firmware/include/drivers/arm/nic_400.h +0282c52c2cf6a737b53c9bcebcd089c5bf35ab24 - arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h +8d3c051e8ba42150549dab299eca67bf73caf21d - arm-trusted-firmware/include/drivers/arm/tzc_common.h +8971a6e6b857b7b1e6544d6c3c9a52ca567a9e11 - arm-trusted-firmware/include/drivers/arm/scu.h +e133eeee905e96159734525bddeb5951f44fe0c3 - arm-trusted-firmware/include/drivers/arm/gicv3.h +7ca64097543e0475ded88ff1b0c756ea3e68dce4 - arm-trusted-firmware/include/drivers/arm/tzc400.h +ea5359158383d2c575b976cf638b586aa030cc49 - arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h +93e88fa1b74eaf244a0d0a7346c849ee43adbfee - arm-trusted-firmware/include/drivers/arm/smmu_v3.h +cb3a4608dbc689332bbeee2134f523d78ea6fcb8 - arm-trusted-firmware/include/drivers/arm/css/css_scp.h +c4e97cf187b8de349d494ab89ca4f5c1a83aadc7 - arm-trusted-firmware/include/drivers/arm/css/css_scpi.h +fdc34a2731639423ad5caeb5261f3207a4183cb1 - arm-trusted-firmware/include/drivers/arm/css/css_mhu.h +2199dceebbe76121f35942566cde95a239340491 - arm-trusted-firmware/include/drivers/arm/css/sds.h +faa54f13bf1956078c447ae298b4696adc11ec16 - arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h +644885f6d536f0b9fecf9b19db5324cebdb1cd00 - arm-trusted-firmware/include/drivers/arm/css/scmi.h +749ed7a2a602879315a2a407faa53d9fcc6f4242 - arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h +7d87f35690f4d41b9739eb995465900a8070b7d9 - arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h +3ffecadd4db08d4069780170baac205025ed7194 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h +e14a50e8d5c68b36920485b6db04f106817437e3 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h +d82ceff72eee2f6f805404b84357273d1eb09561 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h +10652996fa07e69877d9fb73449f7ab46d59ffa3 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h +260990d658ffc91bafbece3081bb60c30618fa38 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h +fc07b65f9cc014a0b1524b0068e8beccf88374cc - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h +e610cb68e48f78caf111024d142af863b6398636 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h +5d04efda071e5940b11e2d270b3dae82a55dc93d - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h +6e4f8a88b84a4ce3b762b6c7f14ac5fec8744012 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h +4639b7108f03bef1a92e980f8ee8eff03be1d869 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h +c55427770d64593e3cf15b3ed93e6488363b575d - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h +d73a1ca5bfea93a55e5c13b2b3f2051e3c0d7c12 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h +49417191c51d1d9274572285c8ba5a8c8146e57f - arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h +5ff025817e96abd32dab9c26c2d10d5116b211f8 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h +93088698293330d0f56eaabb73e01615b19fed64 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h +fb12a0265111fe6f1b941f06d20f54b9439c689a - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h +a182cb9bf34d396f46abd93062d06ce6ee8889c1 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h +bf88a456fd40edb9bb68b2450d6251cda06f2465 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h +a8d2ea546937a35c7f822dd9e1a7e8eb3fd4438f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h +f48f4abf712cac68d01844cb146aa3c6e787e97c - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h +a9419e34fbc18ae5da0ef1566f5febc0cf829211 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h +513b5a19f2f0b580cf670eca60e57e793cac539f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h +13f5321936540bd85461ffa7ef611ca5d4082977 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h +b69f3dd73cff9fd442b44ed25f2edbb0bc3baa5f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h +cb4a166015b83acf19a78617be8e774abc6e1798 - arm-trusted-firmware/include/bl32/payloads/tlk.h +61531a0b7ca81943d7aebe7d3183f30c4b6b42b7 - arm-trusted-firmware/include/bl32/tsp/platform_tsp.h +dc1975b639c5dc6b8eee34ada66bffcbd10d3047 - arm-trusted-firmware/include/bl32/tsp/tsp.h +0978d63d1beeeb3f432496ea56acf6f3cf4d2072 - arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h +11335e71ce700055225b4223bb4218122db63853 - arm-trusted-firmware/include/bl2u/bl2u.h +76f24b5df32a33ff953257acc268f140bef007d8 - arm-trusted-firmware/include/bl2/bl2.h +cf5f556d440245d73b0f784be4662e7cd634f39b - arm-trusted-firmware/include/lib/coreboot.h +9637b2573e1df004bff5258027eee07e6d532cf9 - arm-trusted-firmware/include/lib/cassert.h +7ffbca071dbd690b9d0ac30e6b388a848c55cc16 - arm-trusted-firmware/include/lib/semihosting.h +90db5a8e9962b61142ef6eed7165cb5967d686be - arm-trusted-firmware/include/lib/optee_utils.h +f68ef15137b41ae5e5fd646d5b7624ff9843b770 - arm-trusted-firmware/include/lib/smccc.h +1f698e99c775d463461fd358a896217604420ef6 - arm-trusted-firmware/include/lib/runtime_instr.h +0b8f22e03d35106f8213bb63f81feeefe40d0675 - arm-trusted-firmware/include/lib/bakery_lock.h +de7b34ae4f5c2aa97efbb717d681f3f79f6b3a80 - arm-trusted-firmware/include/lib/mmio.h +b1522d52a6103e87ea31e7207f54208dd2c5a6af - arm-trusted-firmware/include/lib/debugfs.h +94cb452f38b47933f36d4af26e71b749a5ce2efc - arm-trusted-firmware/include/lib/utils_def.h +73dc3acb5868e207313dcdae4f6884d5c179faaa - arm-trusted-firmware/include/lib/utils.h +06aee725316857addfb02415a55463647ed20701 - arm-trusted-firmware/include/lib/object_pool.h +ed4976b8261e1ee44f4a2b7952563b6db8e63406 - arm-trusted-firmware/include/lib/spinlock.h +fcc42874d57314ab77ad7f2a2c1b2eb3862a576b - arm-trusted-firmware/include/lib/extensions/amu.h +802b885838cc683c33d5bdf0db010936d1d60c40 - arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h +d9ddc757d1632d6d25a30937684cae6ef3ee6a50 - arm-trusted-firmware/include/lib/extensions/spe.h +cc7362066d33e226e7e9996002c683aeb7291017 - arm-trusted-firmware/include/lib/extensions/trf.h +09511d96743a49bd6a8ce53a10a7a63f66fa69eb - arm-trusted-firmware/include/lib/extensions/ras.h +49864e971e8571d9d0cb63bce06594f6c8b5d684 - arm-trusted-firmware/include/lib/extensions/mpam.h +b60784e6b65f97973b6399350a6bb41d508cb993 - arm-trusted-firmware/include/lib/extensions/ras_arch.h +08342ec02a973e05865c7a200258f0949f7e0948 - arm-trusted-firmware/include/lib/extensions/trbe.h +5e43959b0322424d6c58374b9bf52ca3435e88c1 - arm-trusted-firmware/include/lib/extensions/sme.h +a3c002de51adf7dd52647cf5c6e3f6e119634fc9 - arm-trusted-firmware/include/lib/extensions/pauth.h +84ebabfad9a6aea5b36eca181ecacd9f81feaf8b - arm-trusted-firmware/include/lib/extensions/sve.h +46afc6f495640a910a40703306195c7a6c3a0833 - arm-trusted-firmware/include/lib/extensions/twed.h +1c0e9271a240a44ae26fe23c9d0bf4f2aefdbaa8 - arm-trusted-firmware/include/lib/psci/psci.h +03fe8d1844f9117cf59adf7bb69cbcef990c16c3 - arm-trusted-firmware/include/lib/psci/psci_lib.h +84b28157b2cc81f5a9aa46c6edf2de6083f696bd - arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h +c90d25bb7b217171ad9437ee0bc8d4e0c5c7f4d3 - arm-trusted-firmware/include/lib/libfdt/libfdt_env.h +ec87fea0386b1dcc840a14b66f68bb20746774d2 - arm-trusted-firmware/include/lib/libfdt/libfdt.h +26e37a910f19c0fe0293821c838312e998579df1 - arm-trusted-firmware/include/lib/libfdt/fdt.h +a9be03deeaf86090c4056f6844a1dafec0a14683 - arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h +ff1f378cc136ea5bf58c5fe0df726e1d809c7efb - arm-trusted-firmware/include/lib/zlib/tf_gunzip.h +531877858c00a04ba41ba7d211235fcad2bf2f77 - arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h +1cc2ff30d9d45589c3c7fa34a79ab141314e4974 - arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h +fad98eab51c54e641e9db5451eceb044f426276c - arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h +d152cc84bd5ddb5c62bb91fe605ebd55b28b2585 - arm-trusted-firmware/include/lib/fconf/fconf.h +b61fcbdcf35b00e7cf2a5c7feff04fc5d28e7e6c - arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h +0f9c6bddf555b127d0deea955abd911c85bc89b9 - arm-trusted-firmware/include/lib/mpmm/mpmm.h +58569d6f8289cc5c665cc6dd3455a31057e6209f - arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h +55da8ccc24cdd5cabba3e346f04694958ca9b84a - arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h +d44192225758ac451b1c5bc5111f98c453327523 - arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h +7a7b59a035c26b0ced83b40114b596358f1bd2c4 - arm-trusted-firmware/include/lib/cpus/errata_report.h +3f7b45d32e48e60ee32229b7e8f5860b6e67747e - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h +055e82d4e76261ce1a2108d14cea7176cf18c0a9 - arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h +b58c922be5d4bad0866dbb86570d6f9e94310f89 - arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h +7de432330be3e8f54c1e573f4ab59d51806e7365 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h +ed260f8199efb4c6b1d32218c83039568c4ef425 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h +82d90eaba5c3e4a0d0d67cdc9bb41cf9f9d2aa35 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h +70560b6cca33e37badb4f0e52e2781166227184c - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h +42b29f7ea79198fbf5aa69a3aa080de56572fa3a - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h +32b8e77c476293848bb5884355c7faf95069f8c8 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h +e762cbd4ef8859eb8d8ebd03899ec10c085ce1b5 - arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h +efc8411aa80d03690795c5caab5213f739c3dae2 - arm-trusted-firmware/include/lib/cpus/aarch64/generic.h +b2ba28f5ae615b85d1e4f9417e53743767f749e5 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h +3c127123c7f793221554840dbafc9aecc3acb322 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h +43952567938e0452e6f1cd65b6fab276d3b628e0 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h +b9a6a19c148f0fb9ef9b3e03b113a48c319f50ed - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h +9a1b5aa467e9d2d3b68dbfdc3d96397743562185 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h +4f1b3a7c5699c6ae409698b593edbc6ac8d2a861 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h +309db7cc6a48f2dfc2fc82dad3300ad2825efae6 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h +7c2b1650f6c338afe9ce5b81aaf9c15b6c358c98 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h +fee71b3ac82a2185c4d87e46ee0883cd51017f0f - arm-trusted-firmware/include/lib/cpus/aarch64/denver.h +e7bf4db6f79577db296e4c8444c731b2e3af4822 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h +26f966576d1ba5fe1e871578dea3ea004be5ee67 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h +830034e1c23a2ef04b995935b6aaa835dbe9d5d4 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h +80bf6905c50e6839862d8fc71c9406f081533252 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h +cecb6b77ddae233e9012f44da229b0f25904b481 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h +fe7e88bb537bded4caa68969291e0f7582e7abe1 - arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h +fb525a4bddf12d5307fdd7d77fe2c90783b76d85 - arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h +22958de97bf4027cc040fc0ac360db1706c214e9 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h +316e8929890c4678843eeb9c9f055e3d7b37419b - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h +84e558d38ecba4e5f4d2f894a9291c5037ce66ed - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h +e06ae7d94772d2e7df59aaed91759743f3614979 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h +6f80e2ceb55f9179c0e8b9d91d249e62d6b1face - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h +44559a7bdfb73f25458f7ca2b0e8c8785ef8827f - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h +31b87fd75812c21215587c76fc574207c546b735 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h +b5de08d6bad3b4fa6d103de5fdccbe1dd027b1e2 - arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S +e67d118e55ce590ff3f6428280713a78b8eed58a - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h +03c06290a053bfb539077f235d6cbd00efa9839f - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h +7c549b2ab4e1d1d0e0a845e601e8778c8c5016d1 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h +4f8e78fb1d10bb5da1ae6792f2775a2e3d34e739 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h +b3f572f2b6af62ea012727754cd52c72ab76a8cb - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h +bb26a1dad2c7e0bc860a422313a21fe96c5818e7 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h +b4398b2cbe8c44396c14071dd547d3b4ae231f11 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h +f05e12dd19967571232d263c83c6898dc9f9c9b1 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h +7246c771a29d42ce8df39025143fedec1f1d22ea - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h +964ef94b44f29b27af9693592b55d5e045c68898 - arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h +ab3b500c80e0bf48a6fa1b8aa0cedb3451312f73 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h +4f2016b0ee0a27a62e127a3e9e49889a8cb0d63e - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h +a90685421214c1862d537af563def9b63894e740 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h +b28242a3c70922add954edac6ef6a6cc27eef33f - arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S +cfcb8f035cda18f894c8ee194d3136fc61406fe0 - arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h +db010d01a2298bde5d192dc8ca42d487ad8023ac - arm-trusted-firmware/include/lib/el3_runtime/pubsub.h +df57266f0878fdff7b3180dfc258dae3ca1859cc - arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h +926a8f99c7871413aa6c48ee91bcacf8ea07e438 - arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h +38bab004d095d8c31cc1bb191af9e3c4ee45ca02 - arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h +9c3df6c4d9ecf03368ef7a5cd150157123c12ed1 - arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h +147505a24c5c0680f8c21cd8b77aaa1ed3d9af0f - arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h +748f4763c6956e3a05b07a06f88394f925375806 - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h +a5b742f0a88671c56d4acb2c9f41a2859ccfe63c - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h +0ea4285dd4504af01f2379c11c6b04292b5224d0 - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h +ffd6aa77c205ba28fc3cdedfdf92ad949a1d2c4e - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h +64b082be684d2e9aac73592fc4658c81ded65fcc - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h +d096d2c939939ac7e3ce5358c63127a2e48fc66d - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h +135853a26b41e70bb03df6feaa46157020f24f43 - arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h +ef0a81e88f09c2c6ce252f01c0405fa13cf09822 - arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h +9b838f7bd9f2c4493efedef614f584d30c32546d - arm-trusted-firmware/include/lib/pmf/pmf.h +bf81e2d1db65ed903ef83af8c902a2c570f7d8d7 - arm-trusted-firmware/include/lib/pmf/pmf_helpers.h +2e8bf007844002145509b02185c1cfb380c086c7 - arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S +be45471818b5fb856ed0fc1c303a3439ac749d6c - arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S +72f4645c807c6915c0628b0d200b18fba404f91c - arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h +2f17e8f91531cbdb0dcb5638ffe35b4fc35169f4 - arm-trusted-firmware/include/lib/libc/endian.h +28d598da1ead2bf6ee9fd764635deb7d1a082fc9 - arm-trusted-firmware/include/lib/libc/stdbool.h +05293dcd9dcd66e6fbc14019807633a277c3a53f - arm-trusted-firmware/include/lib/libc/time.h +96064295890c1e484dfcf96039b0cf5c4babd361 - arm-trusted-firmware/include/lib/libc/setjmp.h +5e084e86fa5e4b5fdac774d1aa00b279f68d3c40 - arm-trusted-firmware/include/lib/libc/inttypes.h +b37dff6a9fa0fe100e6e204676f60358dfde29eb - arm-trusted-firmware/include/lib/libc/stdlib.h +81fc18b0518ed12942398f24157b26767f2b5d58 - arm-trusted-firmware/include/lib/libc/stdio.h +83a3b49d103b8453fb98b0625c759bf39c09803e - arm-trusted-firmware/include/lib/libc/assert.h +1f519accd161baa49f478a735728f1b81dd9a443 - arm-trusted-firmware/include/lib/libc/stdarg.h +d0d4318e609c76661d8f0144b559d4c7e5c43cce - arm-trusted-firmware/include/lib/libc/limits.h +0d835510f380ad8267995f98edca212d0c2d8f72 - arm-trusted-firmware/include/lib/libc/errno.h +3ad9051758ee29a3d96abe5881f5a7740eb10550 - arm-trusted-firmware/include/lib/libc/cdefs.h +fec91d22fe696952ba93c2d1ed6cedfa714a5a7e - arm-trusted-firmware/include/lib/libc/stdint.h +167e84c7f69dda6dbee48fff38839436941dfe1c - arm-trusted-firmware/include/lib/libc/stddef.h +de263df3e964aac45b0a9be4096eb2a12c63d72b - arm-trusted-firmware/include/lib/libc/arm_acle.h +38027460aea214583844c4cb07db44077673acc5 - arm-trusted-firmware/include/lib/libc/string.h +8741dd9ddf232520a7e68bd21382fd53539b8c5b - arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h +94f633f89b9ae70068fb70432456057bd04bb750 - arm-trusted-firmware/include/lib/libc/aarch64/endian_.h +dec49d90238a3dc066022d9268b1172c93e6bd29 - arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h +81dc661e625cc7228b67c09aea60df34e729c283 - arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h +a0ec98e34e93c55ac6fc9241cbaed06bc372bb39 - arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h +c881950de56de06d14e10e06d219c0ad40613034 - arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h +e3ba7ed7d41ae3a8c9dd07d94f7bbef48adf165a - arm-trusted-firmware/include/lib/libc/aarch64/limits_.h +8eaba3f90b7b124e01dd67a505f4e8dac6d42826 - arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h +5d60818c76a8f8d0645d40e13fb9c6bba183e2ac - arm-trusted-firmware/include/lib/libc/aarch32/endian_.h +5504c60845bc40c22309d19ad3a370854542606b - arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h +99fb55bd4f7021bebc906bdfbf7f2e0a32e198f9 - arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h +4ffa8f28ee204e4445f86ee9e68903c66fb5487d - arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h +c6119d73104bf3ae1d27bac47db49a0fbbdcd112 - arm-trusted-firmware/include/lib/libc/aarch32/limits_.h +d33d416f27b0a754a92dea111013ae91e9fe09fc - arm-trusted-firmware/include/plat/common/platform.h +ec1ba9f6e5e5199a8174963440c8673120fd65e0 - arm-trusted-firmware/include/plat/common/common_def.h +9cd1950e6a5ff8b2dcd0143c1dfe498c7804a1f0 - arm-trusted-firmware/include/plat/common/plat_trng.h +0ad5bfa2837c10aafe72e696c238db4ebd82794f - arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h +5d91bb2b767050d467d072d4e6d7036d8c71d06a - arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h +e639b2614ce8c77a52995ee2da45fe54fbb8dc2e - arm-trusted-firmware/include/plat/brcm/common/brcm_def.h +d7f8e1c595627094eb1807e5f15cbb7674cb02d5 - arm-trusted-firmware/include/plat/brcm/common/bcm_console.h +dc4318dff472842b4c63c7b87f23c3688def3c5a - arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h +9dd486928223e599a25bc6f13b414fc57c242b36 - arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h +8cdfa6f8ca1d681ba760da2fe49c8f365ef0dcbe - arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h +e2d034b7bbecdf28360fcf107159eae0bf87de48 - arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S +b7faf2c71aa5d9ab793eadfeb28cd9effe284930 - arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S +98c1515593c3e784076edd107c7aa20f26d00900 - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h +618289fd2c98548dbc401a283df9d3c6386ce002 - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h +71dfe89c5f0b7453c5e1af8a81c440aea8ecb34b - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h +e6b0db0b8079bfb25c6c3257a0bc6403591a354f - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h +36e0657b50b40ad54b3ef6b8b6848377fa423ee2 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h +6e72bb219cdd7c32b97b3df3a2fd695dab5d6fc4 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h +8d91b9ddc816f6cc8b89cdde08ef32b86e76f779 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h +79fec062b150f074e53c3a4b1987aea42e5a4eff - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h +5eb5b60a95f1d5821d119a38a870719cd6345ca8 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h +48923d6fcb9d9e02790b158b5eaf6edb34db109d - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h +64f1e7c2408515cbabe2321cf6584901213dcf2b - arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h +a4c302b222e019205abf65fd01745d571d810ce7 - arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h +b6516d7703c189ab60f935aae9db8c643bb2d84b - arm-trusted-firmware/include/plat/arm/common/plat_arm.h +0afd9c0926d88821488dcd5686914fd1ccee3763 - arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h +eb2f94f2fc7e75343b6ebf27607b356ad90cdb7f - arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h +62a021ac07cc197af73c3a77f81b2e3c269b7cb0 - arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h +1fd41daca5740b134bd9df3d981f66ab2fea4f52 - arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S +971368d067997c8cf7b990346646cedab7fb9189 - arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h +88fe915ca8ec7f1f3499a57f534e1396c6b7c98e - arm-trusted-firmware/include/plat/arm/common/smccc_def.h +fdc727288dd453b4dcf18b744fc052a039bed405 - arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h +b9070936733be0fa95be33772381b15e63ef79b2 - arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h +44ce8058a0b197c5c89e419bcebc0ddcd8434c36 - arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h +9437b8c5d8cf84ec02a69c03b1658cfe00ce9a70 - arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S +85db4d68c709e11a4b63da0a434f5aeeef2aadec - arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h +32a205b639eaf056873e852af9f2f925782878ef - arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h +36a2614776249ab76e9c86d1f08fd0057bab8263 - arm-trusted-firmware/include/plat/arm/common/arm_config.h +76e5f8f29adea5aef863105a24eb9d29d8be3952 - arm-trusted-firmware/include/plat/arm/common/arm_def.h +f0fb541bb623a169168129c94b788f2a409ffb5b - arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h +bcb4189176bf949ae7ccbb1fb72c9d29b366f7e4 - arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h +657f1176fd4f82dc1155d86438b6fbf624d2747a - arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S +3bb163e8411b70a5b6f5913631e64392b3154151 - arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S +0081d14a9dd87bdab5919da6391eb2275fa7e94a - arm-trusted-firmware/include/plat/arm/css/common/css_def.h +68405ab09471b8d13fcf6f7e2b8f07a8012d11b8 - arm-trusted-firmware/include/plat/arm/css/common/css_pm.h +406bbb095f6bf7f140e7814e98b0ea99062ad767 - arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S +fe0efb2292b7b971908fcd44d634894276a51f1c - arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h +81ed90e8c99ac6343426728d9299d8ad48305d39 - arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h +40577c7bc2464cf873f1f2708e2db8112b51374f - arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h +e1699b761cd12de148f701d78db5c24eb3aa7251 - arm-trusted-firmware/include/export/README +45ecabce41da084db92b27dd88e6e89f30506036 - arm-trusted-firmware/include/export/common/ep_info_exp.h +91e15bef63bb89bfd921b4d01d17b37dbeff291b - arm-trusted-firmware/include/export/common/bl_common_exp.h +60669a2cabdf40b63773d538d47861c1a584f800 - arm-trusted-firmware/include/export/common/param_header_exp.h +c2a9a69314ba3b3f2369c8c876b39d8acda1b018 - arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h +9367cefce0520648ccdaad1fe3a402422becdf55 - arm-trusted-firmware/include/export/drivers/gpio_exp.h +5091c9e14c49f9799bc9985442295e882a14d3b0 - arm-trusted-firmware/include/export/lib/utils_def_exp.h +72b925e2450734e1991799db8cc30f6a8609462a - arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h +9bb9fdc2ec0963a6cbbd0188ae70e368e67755f2 - arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h +dcd0ca426668c19ab921df2fefbf2d83ca5afdd8 - arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h +a628d4b48c67b17cc32449aacf6052a52eea1705 - arm-trusted-firmware/include/tools_share/uuid.h +1fda7d8e566efd28aaedd2f5d1ae43b5bf4d2705 - arm-trusted-firmware/include/tools_share/tbbr_oid.h +58d6bf8cd75f220139c010d1d5fb6e0a96d4564a - arm-trusted-firmware/include/tools_share/dualroot_oid.h +b279cf845b5ea6ce93f6563029c2dfbe6f85a541 - arm-trusted-firmware/include/tools_share/firmware_encrypted.h +3e0251958205aa29f860e4627e7f29098e266f1d - arm-trusted-firmware/include/tools_share/firmware_image_package.h +5219a8b9ae1ae1722063974c9bedee960cfa351f - arm-trusted-firmware/include/tools_share/sptool.h +7185228489bf2c4e562f37a9f927cbc31c18ced1 - arm-trusted-firmware/lib/aarch64/cache_helpers.S +da63c15641cb6cf532770db54efc30b3f8122a7c - arm-trusted-firmware/lib/aarch64/misc_helpers.S +96718b39d24ee4ca5fd1eb4f87d53c45c9e4f079 - arm-trusted-firmware/lib/aarch64/armclang_printf.S +4ef2e504a667d7529f6e9f0629c04db77435a28a - arm-trusted-firmware/lib/utils/mem_region.c +da13fbd30292be6162a14bb7866fc3da5fce2c10 - arm-trusted-firmware/lib/extensions/sve/sve.c +afd6141e2e07c1fd692c8e845ce6e65899fbbb7d - arm-trusted-firmware/lib/extensions/amu/amu_private.h +7f3f609a1bb0c4b5287f43cd817a535c4e497353 - arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S +896aead96745f721f995de07ec7a83fc77ffc33f - arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c +3dbb067dc92b40dd63f5ee3b50d0e88978e7e528 - arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S +21d2bec3b0a822561dc68c9dab32b97d35ea848a - arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c +1e8ea4b9d81a41c874fd1c0e7b3915a5337cf966 - arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S +aee505d9d1071c6c819d07bc02c1e963cf8c6025 - arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S +4125c51fd3f075d4d291f56b53175ca0683e12eb - arm-trusted-firmware/lib/extensions/spe/spe.c +672dc9ce8ca19e9bad297552bb38f03725d544b2 - arm-trusted-firmware/lib/extensions/mpam/mpam.c +20945ff7a4f02b5797f9043d0dd1dcb655476c0b - arm-trusted-firmware/lib/extensions/sme/sme.c +ba76ca96162e88bc6bc13591b4dbe2d955320a45 - arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c +ecb8e335fe4a2681e714ea9d5c5f2b8f5e1a8e07 - arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c +ebe5066f50de32f019ea11419b6ef11da4604812 - arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S +785751601e97ed8f6b006cbe5a6e26dac81addf3 - arm-trusted-firmware/lib/extensions/ras/ras_common.c +9b56d2cedbd5417e75959a7c83b6361dc3c48f6e - arm-trusted-firmware/lib/extensions/ras/std_err_record.c +1acd16a1b33cf990f1093d8f0ba9c0ebd7a6f719 - arm-trusted-firmware/lib/extensions/trbe/trbe.c +e3dc484cb8d981ceb0cdc03a7bdb8f24e2f9ae85 - arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c +5ccbd178b5c5eb953d97ca519229837a0537e821 - arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c +70011c90369b5b9a9d55faec233e60b90b31801e - arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S +edf2b7a02784eccffa70a8f06817929dd1a8f993 - arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S +b3453819b2250ed7f47a81d57ce565f8d644ddaa - arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c +cf339f00e977a47612e93384a6a0b8e73d731c21 - arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c +ddcc3c9570f910954693aa27a5b355d4a84f2ac5 - arm-trusted-firmware/lib/psci/psci_off.c +dc70197a71b51add43f68a1708e572069b991b10 - arm-trusted-firmware/lib/psci/psci_common.c +96cf95201b14289b9fd8994f635436bd603c2e2c - arm-trusted-firmware/lib/psci/psci_stat.c +70484461d77679b66812b09dd8b56cb0c17acaf9 - arm-trusted-firmware/lib/psci/psci_mem_protect.c +829a7e8232b3efde8c6ad84aff7745c16582da77 - arm-trusted-firmware/lib/psci/psci_system_off.c +bb2c6a22fccb6b37506ba1b0bc6ca6db53f60051 - arm-trusted-firmware/lib/psci/psci_suspend.c +dc79080304d8fd3b4fee3f3ab53559b3a1008d90 - arm-trusted-firmware/lib/psci/psci_private.h +268386d92529e4c7ffed1ece69a88ebc933c34e2 - arm-trusted-firmware/lib/psci/psci_main.c +741cb1ca4722a4062052f5ec8cbb9d6f1d4ee468 - arm-trusted-firmware/lib/psci/psci_setup.c +a45af64e61c40345d7034444490e7fd33b52606e - arm-trusted-firmware/lib/psci/psci_on.c +2c7b752ae78666bc171dbc6858abbe2c9cff4013 - arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S +e3019770bfa11512ec7d2d6785e37d28c72cd2c9 - arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S +ecf8ba50075277e075334d8bf2192d3a03b4d713 - arm-trusted-firmware/lib/gpt_rme/gpt_rme.c +edbe27a26695b90b039ea42ae87e3756c047631a - arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h +7b5870894878b452bb2f89fe98f1e15591a599b9 - arm-trusted-firmware/lib/semihosting/semihosting.c +79d2f0e3c6477c7632a9d7b9d01b42625bf0cbb3 - arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S +bed75bc5da772504027fb7c033a1c918acc82c48 - arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S +3af779f4c2869b4f4f96ca46039bbe9311cfefa4 - arm-trusted-firmware/lib/libfdt/fdt_rw.c +d63d474ccc4d93be45267b9c0a32c3c88c4f42cf - arm-trusted-firmware/lib/libfdt/fdt_overlay.c +c3bed95f695f7f9780ea064580ce245fa8dc6611 - arm-trusted-firmware/lib/libfdt/fdt_ro.c +3aae059b21ecd4f923c8f399d4c2dd101ce03502 - arm-trusted-firmware/lib/libfdt/libfdt_internal.h +c7bf913dd7eabfba85f363d7a05851e84c786828 - arm-trusted-firmware/lib/libfdt/fdt.c +c16e3571ab87b0ea9f8067989a5b0f97251ff8cb - arm-trusted-firmware/lib/libfdt/fdt_wip.c +e01b7a0052b837a4650f2c9ac75ad38c40edc583 - arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c +6db863ac215fcf8880798469701f80b2fc197bcc - arm-trusted-firmware/lib/libfdt/fdt_strerror.c +55fc5d2ffcba07e29948822d0b12e4bf5546b8b8 - arm-trusted-firmware/lib/libfdt/fdt_addresses.c +e6ac4a37689f70dd9fd01a67cabe4439d66dc4ea - arm-trusted-firmware/lib/libfdt/fdt_sw.c +655c16e59bc70c4782c58f76a458853aeb35f2f1 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c +3da3d4c987ce40660bb10580236ee870f603a567 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c +c8e552a0ec8c6fbc0008de98e8cc7e6ac08f1980 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c +6d8e14259a3bddae74927623e68b6e95a578b3a2 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h +97a06786c9d53286c3d0d861d9e6578551650e5e - arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S +250ce42c1d1df6103d9a7eb84f739a52570e85c9 - arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c +c3816ecbb18ec120734f1bea8e79ea2ce6e4f631 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c +eaf23114b5279a2e5177c2d4a103265159f839d9 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h +499b3843cd918ded79d9b4067c70be77235a831e - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c +c56014f913bcddf7eb4618bc48a2d7e188df93e8 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c +48fbcd0295e7c9d2581d235e6c80eced4a10a422 - arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +21604c58893e3fda032bac4d88417fff189d89ca - arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S +990536d736898528cf4565171fb83f57604dd3d8 - arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c +ade75a712dde9020d79686a61994595c14f73163 - arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S +5c1fdfd96d90cc2df42b24e37dc31a193219049b - arm-trusted-firmware/lib/optee/optee_utils.c +f32dab3880d47eca1b71c308cf6542b32941b23c - arm-trusted-firmware/lib/zlib/zutil.h +8770ab43c9050b824c646f6e6cee8b3c0628cbda - arm-trusted-firmware/lib/zlib/inffixed.h +628d8395fc7f67e6d7a9a6cecba64f6594d64eb9 - arm-trusted-firmware/lib/zlib/inflate.h +db9e88b8332953972c9120c73389fa2ce03dd8f8 - arm-trusted-firmware/lib/zlib/crc32.h +a152b76b78f9245ca67db2729de72d51ecc234b0 - arm-trusted-firmware/lib/zlib/inftrees.c +3c63a7707d83991f3e074391c047b3136ff3e558 - arm-trusted-firmware/lib/zlib/inftrees.h +2f1fcc93488ac84acf984415b6ea0bd63c72aa49 - arm-trusted-firmware/lib/zlib/zutil.c +6c1114794db137af50f9b060aaade1a1a35ed784 - arm-trusted-firmware/lib/zlib/adler32.c +d5cfffd5a037697867a78566d583e73f6d0f91b9 - arm-trusted-firmware/lib/zlib/inflate.c +fe2fdfb8f51d9f84881cc453ba64f60e3d7c9cbc - arm-trusted-firmware/lib/zlib/inffast.c +4fc803c43a562b2b92a97e22300754ddfe44c603 - arm-trusted-firmware/lib/zlib/inffast.h +473b29ab06e2be461fe4aa74952fcb9bd08d9fa0 - arm-trusted-firmware/lib/zlib/zlib.h +0ef05b0d12bf2cfbbf1aa84cff0e8dcf4fc5b731 - arm-trusted-firmware/lib/zlib/zconf.h +88ea76a1b42bfc247680dd50b450923858f945fe - arm-trusted-firmware/lib/zlib/crc32.c +8bb206723f10a7635c07f3e77abad21e4e47f520 - arm-trusted-firmware/lib/zlib/tf_gunzip.c +bcf80bf32003cb4ebf4b71fd3b62b2ec5210ba95 - arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c +18fdfde595d6c7a6409f3d91382d81f736bf775d - arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c +1720429b89e9cc8c7b5f6bde6381dcd8f1e4bf0b - arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c +fd4c5030299c6c43d7dcde650254301c4a185c84 - arm-trusted-firmware/lib/fconf/fconf.c +3567bc768ff2f143e4933244eb221b010bd91f80 - arm-trusted-firmware/lib/fconf/fconf_amu_getter.c +06052beb76737879a3430c42f32068e7630ce940 - arm-trusted-firmware/lib/fconf/fconf_cot_getter.c +3c63f678cd78b3c4c10b6d13ffb32f245deb8ef6 - arm-trusted-firmware/lib/stack_protector/stack_protector.c +7c77f07a1d4fda36a4af38ed18da2e22607b53e9 - arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S +c50c9ce39f46bbbfebd47c8645445585727f5b7d - arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S +35242ceafb8e7c1ac58158cde6672b601b1a88f9 - arm-trusted-firmware/lib/mpmm/mpmm.c +3ac2e5a07791e75f8ed81d0c1088a639a14142de - arm-trusted-firmware/lib/cpus/errata_report.c +23b71740924a2f46a4a3766dc7863240494c0c3e - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S +d16bad3d9e6b6ed0a164467a3b25e5174c38de83 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S +67a71ce51804d2c0c43d0c5b928b429383691702 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S +62e253dfa61bf57bc7c8af97146dc643070630b6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c +03c0a2d3e033df508520b527dd03c5487d139556 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S +6c5232d349afaa099b1de4b8274de771a075d0ce - arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S +27cb3501d1a82bf7a2962df5e632ceddc6099479 - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S +f382f5af3fd88a0d159f0fc27bf3ff89e6e6517b - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S +4076b184f1c8b586d8b7e9c16daffa08e81812c6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S +3a0842db6538fada52fd0764e2942e9edcfa61e5 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S +8753b581e7bd70b0612f529761cb2e2f789d26ce - arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S +6256de3b0f8cb82f4629e83dce1ebf3f3d101147 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S +e0dbf2ba5bb288d057c7b39ac8c9217a8e9ef501 - arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S +6c59fcd106e14d7120f6a715ba57542d71f097d9 - arm-trusted-firmware/lib/cpus/aarch64/rainier.S +08801af78758ca580f3619f48f0d2b72b843b8b3 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S +50d6608eb167f02f6eef1948d919c767b8687797 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S +7cd2af73210355f0e23d3b78612b61f25b37cc87 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S +9745ddbfe3bad71ac283cf7afe3f3a58848729fe - arm-trusted-firmware/lib/cpus/aarch64/generic.S +87817fd4d0f4db7bb9527cfe0b1107c39d33bd8b - arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S +2395220984e4ebe2e10ec3658f908b7a208fb99a - arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S +0dc9a7f3f035cf6c322da9c77eacf5cdfd5be43b - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S +bb044127b0f5b6908597c1915659ebabb4b9d8ff - arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S +dd46ea61bba696867fb1ab60d0f54a5955c1f181 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S +4605a62d489dd9762cd96aedcfc0fe6101c14072 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S +c2e3731d8a04eb0fe71b450fe59df2cca99da824 - arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S +f751bc5c9ebc637d2973b137fe4020a9d2b49ef6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S +7ff21ebdc83ea3c05558a7c0798f1424648d5a34 - arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S +e448fa0b2d060a91a00ce5b1747f0bb4963d83e4 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S +e314809e018d3bcc1cb805e4412443d918934828 - arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S +b6f5469c320d8cea71ed93f0779eb1706255e014 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S +5f3bf45f19baa196f8537ea9fa6db1c00692c35f - arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S +366cfe2c271409694f391a9092ce58f0d69d8eec - arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S +0183572f056c98431e9ee40e1ca22f149c8d1995 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S +b3fdd390e1a5194e6396b00ed696c93176174a93 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S +527f0453b6bcc1e3cdbc68d25c5949e9c6d90d21 - arm-trusted-firmware/lib/cpus/aarch64/denver.S +f245d765bc664b16acec02a6040885c8a59f9a54 - arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S +814012a88912a712842aaaf04053a1a8fc46c29c - arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S +006dee1e8ead4bf3e5c48a7374813cd8b78ae362 - arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S +5e64126fe122470b5f906cbd26adc7b19c2b1cbd - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S +516e5e5482ec47fb50a91b19c7c8d86572bd9844 - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S +fd801851b71a05fbc5920f6815d5ab8025a7f156 - arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c +edb24154359f6a874c199325c9d7072c4dedba3b - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c +b6caa69a2838b35a3268cac6784f7f42060028c3 - arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S +4a3f95b9caa66e146e1a7057c238ce166bc17ae0 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S +4bd6136e7c566e86577b42f173af618fff3ec5ce - arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S +dd4d708971e42cb6726bd6bcaeaaeb1ea62cc302 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S +28602f5410ff8b383fbca1c3d420dd85e9e2e12c - arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S +531b8790149c59c6d2a7528e480dc52235a0b5f3 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S +d132a84afe31b0339e4451e7df450856572fd2fa - arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S +dcc4327691c3788d4ca00df40256542be520f4a6 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S +70588b0d27cc22a3c28dcf235cb80cb80658e875 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S +504aecaaa931ada33617064d0c95d4514d583971 - arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S +0011de1efcc751a018cb652d35bf6dfb77ee5da5 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S +33d1e02fb1f40c2b2147fdf1911b9f6d0de2592d - arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S +bbcb12f3afb37a6763f26ed91a5859a16a9185f6 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S +698a71205b1dfcca91b0dc7e75cd8633685859b4 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S +dfe9d1459f2afc808df76389971581e7cd156c05 - arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT +58b4cf2c8174eb2d106886b7cb8a016d40b2d753 - arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c +dd068590d2ed1fd41f248aa09a898df9da988c07 - arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c +eb176115541305cb488d2be70cf8c519c16b494e - arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h +35e2f5c84e2e03c6a63abe1dcf1494fcf8ef9d7d - arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c +32a243925b1b44cce203fbb02b0a15210edf2c34 - arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c +abf726b9d10381fc90d5c11654d391de96b8d950 - arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h +e6b7517bd52e7cd7c50262aa9efbd0f8ae19a1c5 - arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h +f0a970815c4d8d2aac30a5da63d63cc4c5ad824f - arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h +3a299c5cc089640cd5a4723e9f7ef8eb172386e0 - arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c +46a423cd744769dbf4c8a9bace21b176a9e737df - arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c +0740d888a28b420885866b396a4b4c3787fa5d9b - arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h +393af562fe70f1bc9366014f2afdaa0318c8e72a - arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c +fa64ca197ba53f0e818a0f087349634fbd54640f - arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S +534e0612fc60e5acdbd99194724c762a645b1a4c - arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S +14efe65532640ad904e16c0fcfdf2a0aa8ef7892 - arm-trusted-firmware/lib/aarch32/cache_helpers.S +c975d8abfe42e48d68e0e592ba3989ae3f7f0853 - arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S +8a00fe14195497b3dfb4323af7775b79c89a645c - arm-trusted-firmware/lib/aarch32/misc_helpers.S +50b2fea23411834a7cdb5cb61cc8559bcfd872b1 - arm-trusted-firmware/lib/aarch32/armclang_printf.S +00169552baea8da03759257b44162edf097abcd0 - arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c +a9efa4120656b54bbfaf91befd1a82dafb8640a0 - arm-trusted-firmware/lib/romlib/romlib_generator.py +3a7bca01cf9d3b67b9d93fec625c4591ad106379 - arm-trusted-firmware/lib/romlib/Makefile +bc8857833413ad776fefee7b3a4fe3ad74c7cd04 - arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh +0b4fe827956659566fa763cd1b1e15b1cdb505b6 - arm-trusted-firmware/lib/romlib/jmptbl.i +aca0167af243d551e7068e10251ccc62e1b800ea - arm-trusted-firmware/lib/romlib/init.s +1a7d8adbdd571058f2d7cdf2dad5d51e735dfe8d - arm-trusted-firmware/lib/romlib/romlib.ld.S +5c8a013e889e7653f0cbff1346cd13128ff2fd69 - arm-trusted-firmware/lib/romlib/templates/wrapper.S +f9c9050fd5c89b246d718f406a9d9a13f3388a5e - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S +b022feb15f3e84d4eefd318657af38a3a523e363 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S +fa26b89e848f7affd6fd3be71153b55961fbf971 - arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S +e0406a34add19465d2ace2d60bc6c5048bf0a9ff - arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S +8bd9f16af17fc4a81e921654d50217d6ba334d4f - arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S +56fc8c8a2950a0303783ced6bd0e388176043a47 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S +91d0e6f060cd659ba73d0db8886497a823814c65 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S +2e63b0dd99041f913d992fc557f39d47f05937cc - arm-trusted-firmware/lib/coreboot/coreboot_table.c +ccbf0a74a73d6eb9563cb282272e41c9decadde5 - arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c +0407aded26aa40484ccde01e8562c2db1c2ff939 - arm-trusted-firmware/lib/el3_runtime/aarch64/context.S +648e98ef419ac30a1fdfe6e9fdef5a45f6fb8926 - arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c +a748c18c9c1bed5bfa7ad7bc2d42f1241b4eeb59 - arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S +72331f73e0f3f6540837815f472f78059a7fe275 - arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c +c16b6a90e04aa66123dde223fa202f33ab70aa51 - arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S +489fa8c2a31654d4ab05e281acbabb0f8a64608d - arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h +57633f55f011eec32b09f4867a18db8725ad24d4 - arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c +83fd34388e89c93efcad1998551854558c28ad99 - arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c +08dd595ae97e585c165a02faaeecbc5c0615ecca - arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c +bb710f3b156b87d08faaffa4bfdb60074c5bf5b0 - arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c +b3f793c7bec8ccc037a4cb9796f2bcd15f5bf4eb - arm-trusted-firmware/lib/pmf/pmf_main.c +6b60742d3e420cad2de83925c184cc98fd66505b - arm-trusted-firmware/lib/pmf/pmf_smc.c +886c1e8212ddafb0663811837c76ce60a9afb42a - arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c +78982645d4d3008984c9307ee68bfa8eeb1a43a7 - arm-trusted-firmware/lib/debugfs/blobs.h +8102f862edb5ab07783993999c8781385e261628 - arm-trusted-firmware/lib/debugfs/dev.c +5260672b27f35a4368d3be1f6ee66ec91d4beb26 - arm-trusted-firmware/lib/debugfs/dev.h +9802d55cbbaff09010b37afad6d494d8e755eae2 - arm-trusted-firmware/lib/debugfs/devroot.c +758f3be3354709a4f69ee89cacf0db10dd68c75c - arm-trusted-firmware/lib/debugfs/debugfs_smc.c +7c85c537adcb24f5e03d6c71424a2618815086e3 - arm-trusted-firmware/lib/debugfs/devc.c +db9f0e301c7178c315a1c6e72358bae572ce85db - arm-trusted-firmware/lib/debugfs/devfip.c +0e11c2ba3c9318cdcc4c28e3e3663337046128b8 - arm-trusted-firmware/lib/libc/memchr.c +c72f1f1842a78fb427805c7447d370fc148dc89f - arm-trusted-firmware/lib/libc/strtoul.c +76e2ba1d1196be96fef786c3d7c5130fdac79ca7 - arm-trusted-firmware/lib/libc/snprintf.c +06782e2bb8b5e2b70cd089f061be9c1a08621523 - arm-trusted-firmware/lib/libc/memrchr.c +a13fb76d1efd1532d6265ca7e3753be123c5fbef - arm-trusted-firmware/lib/libc/strnlen.c +07dbfb512cae53c03504d60ec4b02bfc74c2af8a - arm-trusted-firmware/lib/libc/strtol.c +f5fe2af7f4f0cad25866aa2422d946f47a11943e - arm-trusted-firmware/lib/libc/abort.c +c64e54b9d37e79c6a5ddf5440518980b4d8023d6 - arm-trusted-firmware/lib/libc/strrchr.c +1a98830ccfe805a879a87ff7eb90306cb197e72d - arm-trusted-firmware/lib/libc/strcmp.c +315e4d792f50e1a2f37ec14616fb2aaeaa866ae8 - arm-trusted-firmware/lib/libc/strncmp.c +8cd93cb80d43bbeeabb3a74bdc1e89d4e0821e6e - arm-trusted-firmware/lib/libc/printf.c +57ac7674f717f57cdd099f4ac2b3be174f71bdda - arm-trusted-firmware/lib/libc/assert.c +82032c79de7b24a84341c8bd5d72baba75337f1e - arm-trusted-firmware/lib/libc/strtoull.c +be9487ae2df331c4b6d1e8eb831fe36f80300829 - arm-trusted-firmware/lib/libc/strlcpy.c +44c32455e06c8ee38e1d4774fa8f70de1d9e3f00 - arm-trusted-firmware/lib/libc/memcmp.c +e99c723c3292973758d597558fd929976df82eff - arm-trusted-firmware/lib/libc/strlen.c +e7eb31dbd9893d98f8ab6cbef6a11143aa052581 - arm-trusted-firmware/lib/libc/strtok.c +0a99e4e59337ea7c2c2fe6dd428552019fc1f053 - arm-trusted-firmware/lib/libc/memset.c +cf851bb6ce469797f295f4789ce50110b175893f - arm-trusted-firmware/lib/libc/memcpy.c +0e2d7fd7063f4e253b3719a95edcfeb99d34044d - arm-trusted-firmware/lib/libc/putchar.c +6d62f8972d334e9b7016abfa5fd60039fd045392 - arm-trusted-firmware/lib/libc/strlcat.c +e68d6a0053ae9810517f220d26386a2ae6290766 - arm-trusted-firmware/lib/libc/exit.c +2e041624618747b95a70ac92007814f04d42907c - arm-trusted-firmware/lib/libc/strchr.c +a1876df5c0fef0a62bc57d6a13bab2234ad7b1ea - arm-trusted-firmware/lib/libc/memmove.c +045917a873ae9e6ad3f96e3d127eb474b0f0baf9 - arm-trusted-firmware/lib/libc/puts.c +8c9668a348c3ffbe4509aa2246941450a7b0de00 - arm-trusted-firmware/lib/libc/strtoll.c +fd7697000146d99611e6aaf57e0f3856602daf6b - arm-trusted-firmware/lib/libc/aarch64/setjmp.S +02977fbcda3d55ed39cafa721d2bd2a901f0c637 - arm-trusted-firmware/lib/libc/aarch64/memset.S +75786d0b78f57474b1c6f960b2c8ecbc07ba830b - arm-trusted-firmware/lib/libc/aarch32/memset.S +d317228143780c8f627a6814a3ca1ab9f1a0d69b - arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi +2a8ccec8476f0d4af01036dc6ecb636d1f2a1387 - arm-trusted-firmware/fdts/stm32mp13xf.dtsi +6b86a9e9c6c06841937a884fcc7b91e67ce3b81c - arm-trusted-firmware/fdts/stm32mp13xd.dtsi +38c31e8b06ea5253a26b8393737ad72d81e1757d - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts +60954c960886d3c55a4f3e819b0ad2411afe194c - arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi +195376b3fa6a4af6db8e90af65ae62d649d506c1 - arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi +abbe0e5a7c63995c207b1995649e3a6ed6b4221a - arm-trusted-firmware/fdts/stm32mp15xc.dtsi +f92cb32ea29e10232721e9d596972e82444c21d2 - arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi +ae59f1caa51f25a19cb7bc925c819f7b663c9ccf - arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi +f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts +f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts +a6ef63af22c25465b4276c77535b30d8baaa1ea4 - arm-trusted-firmware/fdts/arm_fpga.dts +d49435eb3b8dae9e0f687d74ac1343c3f6931d7b - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts +a2179d252faf4859c7a7e68d3ba75a0955f53d37 - arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts +094f752c659ba4c70dae4bfdd3041ffdc45d6451 - arm-trusted-firmware/fdts/corstone700.dtsi +6b86a9e9c6c06841937a884fcc7b91e67ce3b81c - arm-trusted-firmware/fdts/stm32mp13xa.dtsi +4fa3b6d4bddfb09bf8b8ac8f78bc5806a1063cf6 - arm-trusted-firmware/fdts/stm32mp157c-dk2.dts +397204dbf3a8d4f16b213cdf8810bb0c8409a3ea - arm-trusted-firmware/fdts/stm32mp151.dtsi +c028d02d6d68dfd3c16c8ea9c6e247c72a911abc - arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi +e61da20036fff26e3a39b09bcb92733e6c4c3743 - arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts +fb6d607b811f2e027c9859345cf86eb565d31c20 - arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts +f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts +20769b04e4fa588ef10d7460a5b4a9061c70ebfa - arm-trusted-firmware/fdts/corstone700_fvp.dts +ee5b8fc8401ffbd14d01f615b14a1bc2c6bc90ba - arm-trusted-firmware/fdts/stm32mp13xc.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts +9082edd5658eb851151f8944760e3c2741fea749 - arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi +3cafe4429688d04735324b0c1ac24d6fd6df075c - arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts +910ac0ace6638b52d04843f12c3f0f521eb4f4e5 - arm-trusted-firmware/fdts/corstone700_fpga.dts +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts +7b3fc7115bcdc0c82b7a2cf02a4089f67d2402b9 - arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi +841830f5b4fb33dd8e11325e65d3e1ba854144f9 - arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts +4d121467e71a4bd15241201c1c23fbb169901959 - arm-trusted-firmware/fdts/a5ds.dts +09fc90f32545b712b63ea42e925122cabd78c262 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts +fafc1a46bd195774df21a32f1e87a087f14e2c67 - arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +390a6cef77d9095a9c98b9abe19eaaa6eedbdb73 - arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +c551d6d75e35b8e119cd5b31bb7d421eb5007e04 - arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi +3ebcaa602aafc62742776533b737f3eafdbcbeea - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi +b724eb6fc96a68bbfe8f165c465341bbbf27bb27 - arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi +59f777f521b3de55f482d1b9623951a1dc5c0046 - arm-trusted-firmware/fdts/stm32mp157c-ev1.dts +f99071420aca4da5f493b73afa3d3777206e23d7 - arm-trusted-firmware/fdts/n1sdp-single-chip.dts +901a3c633890935dc0ef5dda27689fe471371d5b - arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi +721faf693f101ff246d85ebc2d1772b555d84f20 - arm-trusted-firmware/fdts/stm32mp157c-ed1.dts +7afa8c643fcfe1d0d506c90c0ab7ced868c73040 - arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi +44c1cab21fcc9907b2d084dbac303eff0dfa00b3 - arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts +ddb3d9266ce77ac3e0746820b562a07f35eafb01 - arm-trusted-firmware/fdts/n1sdp.dtsi +122430dfffc3d549a6991bc3154850d76b80c2bb - arm-trusted-firmware/fdts/stm32mp157a-dk1.dts +5061d53c21f2dec61bb9fb74fac882b6142d8931 - arm-trusted-firmware/fdts/juno-ethosn.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts +44c646e57eb44bcfd7927514911f6cefb465cb23 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts +79d8f41f2a5afa474094fe763ef4ee39909d283b - arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts +a61a77e18f14a9ba0916b5d0c1d4c7b0e07d1441 - arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi +0e25cc4f38da64563038297dac19b2cc042284f8 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi +10bae29f18be4785b789ca4c08398643163c76be - arm-trusted-firmware/fdts/cot_descriptors.dtsi +dd88ca9bc617b6bb318f6b74c35655db6ecff39d - arm-trusted-firmware/fdts/stm32mp135f-dk.dts +2d9983ae7b41417977f671f99eec7d6c8f5a99be - arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi +c1a285215a44ab5a76667a51c9a7d2ce06e50659 - arm-trusted-firmware/fdts/morello.dtsi +394dc09a932c8f74fe7aff7d429da06d4bd07878 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts +c1d24ce6492d52d78484c4b3cf9d2466dbf9c0b0 - arm-trusted-firmware/fdts/stm32mp157.dtsi +f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts +c49dfbfab50db6d0014130e8d213b6a8113c9525 - arm-trusted-firmware/fdts/stm32mp153.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts +0fec14d4dc8c75bbdea73be1457f5ed47458cb9a - arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts +ec214ebb9287a791def27fb1b8d74fceb843657f - arm-trusted-firmware/fdts/stm32mp135.dtsi +992348633a6518e2d0464e4afe90c22c87a617a6 - arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi +dc0b8b61bededc06878dfb1e763b36611ea2382a - arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi +3340a6810424caf1eeec960dce9e7f673eca4150 - arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts +fdc05334cd630b63cf2fd11add62d6580489d832 - arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi +d9fadc7223cf3f5db0bfb1f4830e0bf0fbf138ad - arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi +c078bf1220e11a54b0ae9d20bf948f1f4cb30d37 - arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi +fec2d89a3727359109737596ca7c4c1165b7de38 - arm-trusted-firmware/fdts/n1sdp-multi-chip.dts +dc880b2cbd39cde08860e8ebf3cb4b92bbb21748 - arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi +bbe441adbb4706bbc2d792a33b888f441d489177 - arm-trusted-firmware/fdts/juno.dts +c67b47c8582f0a092e22ed701f7ad5d9469dd6b4 - arm-trusted-firmware/fdts/fvp-defs.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts +ee1bb06de6ee0eba0fe695f5c7f9dbc12abb6f3e - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi +9ba3e2b8e2ffe38d252977d731187a52eac72c6b - arm-trusted-firmware/fdts/stm32mp133.dtsi +dbed6c5c0e011af658818b570feee9c093e65a26 - arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts +d72046fed6d7327744da75b395f335791022bfc4 - arm-trusted-firmware/fdts/morello-fvp.dts +708bcdeda398c49482ebc2c3bf4b25f2c71a1e3a - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts +2f05be7afa52d4db4c62e213a91e5efc3908193a - arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts +3b4d8cfb55f06ed3418c0539f4d5d2bc33168635 - arm-trusted-firmware/fdts/stm32mp131.dtsi +d6f0de7f00f3c5d3fc07703cda887ee3d8ea1d2e - arm-trusted-firmware/fdts/tc.dts +6c3fed10148b793fe9f9c4f44b878ccc12d99c3e - arm-trusted-firmware/fdts/morello-soc.dts +79d8f41f2a5afa474094fe763ef4ee39909d283b - arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts +5d5ddb74e5499f300b5d1800520a4651078d347b - arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts +ee87af83d314b14a8d8a41acb7fa47c97f7dda56 - arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c +d66ad3c8e97d38face17234980203ac71836e11f - arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c +6883483605723caec745103ffaafc790ec284c8d - arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c +294a1e169dc8c2e940e56cad57a08e5d4adb3b9f - arm-trusted-firmware/tools/nxp/create_pbl/Makefile +2ec990b299f9fd69d0e0a85e98faba9055f56bab - arm-trusted-firmware/tools/nxp/create_pbl/README +621d8ec57a445f0149ebb8b216ef913ed05f8754 - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h +46fb0f5a24245e631af2a4690c0d7202204c0e54 - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h +3d16696dce452bf99b18bdd1a964fe7ad191477b - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h +f328e450c8ae941e8109578f1721860acbfafbbe - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c +506a53ab2e813a5ce578765b25e1e3fe0f1e643e - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c +4065b3a492865b1f4525586a648df384bf7c961a - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c +12473d63d565d1782e4e3273a27c29c04adaf86f - arm-trusted-firmware/tools/amlogic/doimage.c +58ef2523c26b02365fb70cb1cebc29cba026be23 - arm-trusted-firmware/tools/amlogic/Makefile +495a7786c563fdb9134410b75a95c3e1c3149eb3 - arm-trusted-firmware/tools/memory/print_memory_map.py +30931543e94deea26c28007433bf6d837f1839aa - arm-trusted-firmware/tools/fiptool/tbbr_config.h +6dcc9e2c01e4d8e4c0b531154c0598192ba190c7 - arm-trusted-firmware/tools/fiptool/fiptool_platform.h +12207fca29ab69b8fccc71ef7a95f9d551ec744f - arm-trusted-firmware/tools/fiptool/win_posix.c +02dcc44205d31ccd5e69fd5008848cebfa14b775 - arm-trusted-firmware/tools/fiptool/tbbr_config.c +2b824a81f75e43fe0eb8f52e822974093ad0f246 - arm-trusted-firmware/tools/fiptool/fiptool +d47913d50cdf551a4f0677629c59c1464b96f606 - arm-trusted-firmware/tools/fiptool/Makefile.msvc +022ce17862a03fb1b68881c15cc964cd56706532 - arm-trusted-firmware/tools/fiptool/Makefile +158eb04fba82028aacc8b3cc3884314b37d8a862 - arm-trusted-firmware/tools/fiptool/fiptool.c +ff33081f63178813dd9c9235d17538954c29d7c6 - arm-trusted-firmware/tools/fiptool/fiptool.h +323e507fdf87c7d4a94d0bbbaa72bd905c2d641d - arm-trusted-firmware/tools/fiptool/win_posix.h +638ff14128d59a95756979954071615bb74eb3c4 - arm-trusted-firmware/tools/cert_create/Makefile +491ae06a09039151d3d2fbccaf89bf4de779dd5a - arm-trusted-firmware/tools/cert_create/include/ext.h +843248736f6bce43a9ac3f11f9bfa6a094face5a - arm-trusted-firmware/tools/cert_create/include/debug.h +0a307fbdd842fe9ae8212a2362b356addf0a38df - arm-trusted-firmware/tools/cert_create/include/sha.h +26baf6654b744217670bc74a0372533b7a9347d9 - arm-trusted-firmware/tools/cert_create/include/key.h +f5c9fe91b01c2e36483376d6f0ef0c2794343406 - arm-trusted-firmware/tools/cert_create/include/cert.h +134c6c14b6a384f0e036827b128d4adf08612d9a - arm-trusted-firmware/tools/cert_create/include/cmd_opt.h +596785e69869c848d5fdb306b8084f282876abe7 - arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h +728ba9b1bbfe33e0ca3e33eb166f04922947e3e3 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h +a015fcfd89d3e63781911e5134884343975d6284 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h +0c696ba78f7d568469b58576262a035b3074ae67 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h +1188485867e47cb5d105325c1736aafc8f6b0073 - arm-trusted-firmware/tools/cert_create/src/sha.c +ba404574148313fc2ff134ae8bf798150a5cd0d5 - arm-trusted-firmware/tools/cert_create/src/cert.c +82813403f6e7250a54d55d8c1409be0c9c3538e0 - arm-trusted-firmware/tools/cert_create/src/ext.c +a485a01a7aa89b241a4a2b28b2fbe50c469d51c4 - arm-trusted-firmware/tools/cert_create/src/main.c +29f5f62fba8f9c0fb9e528df8a7c5f9a264d9bad - arm-trusted-firmware/tools/cert_create/src/cmd_opt.c +718afca8b5d04a3f76605646abacc1e597be801b - arm-trusted-firmware/tools/cert_create/src/key.c +87b7868a92308d1b74bbf003f8fb00f89c405d2c - arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c +a71f6edc951824d84282d7f0262e1ebd260a5a38 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c +c5571efb1999abfd481ddccdf9cfa8db65d5e440 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c +11fe1d417bcbf3a47d588f48d738d47a156b9c49 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c +1474476f05acda23a8bb1e859fcc314baf5a4fda - arm-trusted-firmware/tools/stm32image/Makefile +75e7e633ff5fcf6dca970eef0c2acd786d23f188 - arm-trusted-firmware/tools/stm32image/stm32image.c +9bdff25d946a2c61d8312e1f53c49802d66d3577 - arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js +e9b252cbfa9bd844023146ac38470829ac72342a - arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json +5e9ebb4c1ffaf478200ddbd8bd5bbef2b0f2d2f6 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs +da39a3ee5e6b4b0d3255bfef95601890afd80709 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/footer.hbs +99f27ae0dfb07952b2130a819e32599cfc2d78c6 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs +85453d72f48122ba14bd00512fac19ef0fc42d07 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs +bdd671375b10dbdabd4f1f87941d3071e275ff64 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs +1d1032e5160d84f70af7f7ab6dddaf003244f768 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs +65198bc7a494eba7c91745808f3ada1e3034659a - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs +6a4752c84a78127a0b99ece7396ae317661ac61a - arm-trusted-firmware/tools/sptool/sp_mk_generator.py +37ff8b0160a90437e9b84efce7ef73833b96eb39 - arm-trusted-firmware/tools/sptool/Makefile.tmk +4a137ea4eb638729bda39a72491cc6519fc26da5 - arm-trusted-firmware/tools/sptool/Makefile +ee49dbe19d032c60cf3e963764253c2d808b9de5 - arm-trusted-firmware/tools/sptool/sptool.c +ba6ab775fd9474718d717b35f4220e716f7b7ae6 - arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile +c6acebe37afdaba95dbaf9f814eb4bba5dd989a9 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S +a728eb1898ea80778d60fcf57b727f977c29ec98 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S +b4ecd67c81a19d47e59f9a72dd81fc392fff3aea - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c +213e1746ba029a55b6baf19ac0d8863713811b64 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c +3d9335fb1238d08df68e2770f69a0e1bec960069 - arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile +8c2b63db003e2e330f2af95b94c2132bc2fc9725 - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S +01000b7d50599a58601322b9a12174d81bd80571 - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S +4085a8d4104eac744977d5ec6feacf08b8a1283a - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c +f51f929a6294d60d681b03dbf0f3f1fe0835fa3a - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c +0ec11eeb14668d925e198fc42145f8b0fd3d02d8 - arm-trusted-firmware/tools/marvell/doimage/doimage.c +2bbefb66f05e50612c3b0d215f0bd185e076cf20 - arm-trusted-firmware/tools/marvell/doimage/Makefile +f35a6333e76f3fb2bed05bad996a131317f5ac9d - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key +954bc6cdf269e0eaa9581057657a1e2bf9621f38 - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key +c8f9244b21f28bb382b1befed8dce13e4eae06f9 - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key +8fc012a12a4398216ad6fd4b97199ccd159711e5 - arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg +8602871bb27d59d5b5ce180448e1ceb232027bad - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key +f848ecb51058182d4c908f7c9a88561dbdce34bd - arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key +5b6535dd6c94832d3113588ea938b9526b06b0fc - arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg +105f766aba0c8abdca2e88e258a34b28a656edd4 - arm-trusted-firmware/tools/encrypt_fw/Makefile +f37ed62897799b6165569c0842904eb6fe5d21d5 - arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h +843248736f6bce43a9ac3f11f9bfa6a094face5a - arm-trusted-firmware/tools/encrypt_fw/include/debug.h +08dcc81abf0dd5a951f1d7cb36e2d05628055bec - arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h +5093ed93e150e683b735ad26979460536e2419f3 - arm-trusted-firmware/tools/encrypt_fw/src/main.c +93d36734d229d79068472d13bb173cb9b1537d9d - arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c +29f5f62fba8f9c0fb9e528df8a7c5f9a264d9bad - arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c +7c0bab3200267e448b5ee45b83104d2923cc17c8 - arm-trusted-firmware/plat/xilinx/common/ipi.c +05d21184a6dd62749ada768285e6b39b3dc5a1d4 - arm-trusted-firmware/plat/xilinx/common/plat_startup.c +e7cc80e40c4b2aff0799c9db4c351cf1179cf347 - arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c +453e987cd3b0c17b8ae79a6a0794d4fb44adcc3f - arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h +f5cda3dcfb0f4452e442cc526b8178b413b5a17a - arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c +3946a8e5b6578610dbcd1b1c9bb2ac02e357fd1a - arm-trusted-firmware/plat/xilinx/common/include/ipi.h +8ccd5942908d27505a9e0d68679df731210d75ca - arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h +604b0f5de53a36f974ce1926152c895a54796482 - arm-trusted-firmware/plat/xilinx/common/include/pm_client.h +c879e06a73baec6538ce2dece09ae7a976f972df - arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h +3f5242b1d910a45ff664bc128a6e749aa019592c - arm-trusted-firmware/plat/xilinx/common/include/pm_common.h +04dac5fd40da85ec2a19ccf681ff7f4b708b31bc - arm-trusted-firmware/plat/xilinx/versal/plat_versal.c +d25ef41e434700921c3427ff0dac7aba4b81e1ba - arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c +d959b29c70b303c44eca6045c664945b0fe74852 - arm-trusted-firmware/plat/xilinx/versal/plat_topology.c +b01dcfd7b061210199bce3d5632bc39be25a89fb - arm-trusted-firmware/plat/xilinx/versal/plat_psci.c +f241ecfc0ce4c6677cbaca2991578232a4c20ad7 - arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c +415d7b76162c6a447101507b3181aa7434887756 - arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c +0f5013cb9f4dd7864aec9fdc3febb4a88c603b5f - arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c +6b87bc415258116316a3b89d124ff4be9d5fd944 - arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S +14340733608cc8031286a97ddc48222bc0ae7bb5 - arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c +cb6dce6031f613ae2ad69be266bc3eb2a5095a0d - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h +cfb673b998f65ad17832a2c1f376daa4ab836ebd - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c +939082dd0654e1c9d5097e4b088ada2eefc3cc46 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c +67797b5d7b79d4fe75c894faa289f6d4deac5929 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h +6aca4366f91416b1541836b7a999ff0873c61e53 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c +a984b65e29e3ddb17d3c124890861519e0a53788 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h +06ac8403ef4a152a6d5257c08766c878afc2c3e2 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h +3efa1f0d849fb9568699ae3cc5e7cf111f1b8158 - arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h +34e333d135956229875de69051e5d541a789cb2d - arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h +d43cd481e9d0acc960fc0f51fbeb274b0ec28712 - arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S +50268618a09434af24c4a339c20a1b7b4a2e4901 - arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h +f22539e2e0c54efb87ad926699ecb40a60fb024d - arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h +23d939fae06d7a162821162cec379264613379ad - arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h +91da7e2e2aedb93811b290946f5b62a4b99a6e6e - arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c +eed49df98140b8681bbbff7a1c514734c884b8aa - arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c +fc6886e5619aabaff7153e268ba005d385a73e3a - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c +fdef05d43dd39fc9b4d18e7933fadc3d7b388c0b - arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c +e5c72cd4f7db3ba2c52afa5ea2a6f81048fa8876 - arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c +614b7c2d4fab5909e7df0076f873699e84b1737a - arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c +4018dd905c37ab4e205c88450ef0d6b0a1d45041 - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c +9eafad8129f35d9d02d9cc93d60e653c41e3b321 - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c +e9430970a771c9add648211e2c05e63b0b2bf71b - arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +bca57ae928a46e00c62d44205c7238c103d89723 - arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S +cd3edf132c54e7b51bf04235b10d9de35394acda - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +e1e42c17e346cb2bdd9bcedf9491e65dcf5a101f - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h +6a34f58d5ec913711c12c58c945dfa18659b999a - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h +4738dfbb7a3a9789e0e520c2d4c7f83b635e3e9b - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h +7bfba4ae2b47e068f8f5ed8aeed42daad00743c8 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c +4b8489810a7c5bd8524f87d7c37edf02b747ab48 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +620a7d35e7cfe3a416c79ab84094934f41b3821e - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +4cadaaf7eb5f5f047bac44095d19052727b55a02 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c +d55e25c027a7950b3a7d34551ba2af0a05e70ac4 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +63045bc978271095cfdd4cb91e9d2c3d416cdb6b - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h +d6d44bea498c26d61f58d11284635f45c0d747fa - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +4a69759072ab900e304081d6a5542761b628115d - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h +04358429a766678c1ea60bc976430714db3fac40 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h +8ede155c56692751835019579474fd5fbda5ba26 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S +6d98421b38c7e24ec53977e85b4776275af5d9c5 - arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h +719fc3fa9d14be22cfb4a79dd8838b27fef9f247 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h +fcc8c8052c715326e932fd7e210fe0beefa2d175 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h +606bd0aedd3a81bf175ef81f028eae35e7511725 - arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h +f82a0ba91d921f8782dbacd326cf93f93d406ff3 - arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c +2c5220969ad934f5e3904f8b72774332826fb89d - arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S +fdb986fc3069c5b8c185c58c199bc5e56a6d1655 - arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S +cb4accb6830f44fe050021fd6e32cca1a8acf7ee - arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c +d736c2075e7e15a400e61a1db310a4d1b43bffd2 - arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c +475644583f7d46ef814913dcdcfddfa706f9f9bb - arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c +7159132c839b1d3568d7b7b03da30f6d03e5336e - arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c +98e57da5931c557522da93cce9fe3bfb911d2cb0 - arm-trusted-firmware/plat/nxp/common/setup/ls_err.c +6694d9cc9520a800f00a344d9cc1c534b6e88d91 - arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c +e0dfec4c8847e15aeb7a774844188ab382bdd027 - arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c +91c2c52722651995a236e3f10e11504b1d87e098 - arm-trusted-firmware/plat/nxp/common/setup/ls_common.c +8094976b2b7aa5bbc113bbc852215f8e0513c202 - arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c +52c5991d0ead354cd375910f00aefc81953d5681 - arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h +c8d60b0a7cea607dac9dc88673f41a4be9285d2e - arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S +9e4c6090807eed8550b5e6acaf048f870d04011b - arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h +4f9b26944e2ce37da586a62bdec3d03549edca60 - arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h +7deb5f8e4cedbb8f2f2faed66426dac4607d7f04 - arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h +6edca4ab32d5c19db4706b176997f9bc4f085702 - arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h +ac50f0a2929a3c77c87203013245a30bab6a20b2 - arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c +3b5918338beab36f0f06c2b7e82c7f49a7b351bf - arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c +11b25502ea937dd88b3986d358aad3eff9f39c71 - arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S +187a0bff6625818b129b5ab42039158f8126ddb3 - arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h +08360ed6a8b3d051a5cad1cb6e001cf1600b7ac8 - arm-trusted-firmware/plat/nxp/common/ocram/ocram.h +5e45989256d4cb803eb129882666969d3d952ac6 - arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S +f71b1c56189f5904469d9e69c7b5206a4bd12454 - arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c +48b1c6e031a18037fbc338e8d3f6d0efbe6c0eca - arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h +9c72b3ecd5d5982e63db876f7dfefb7cbac10bea - arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c +be62a5510efe4bb10130935015fc6c12d3b02ed4 - arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S +27f86d14fd5ce72d0aaa417b4c893049acc97e1c - arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h +3a09baff31a554c63552bd51f6adea91aa05d3c1 - arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h +193a96b82a70ef052d501107a7358ccca4890c12 - arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c +9670a30b894318a795c85e5ee63edbe979b023b6 - arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h +5898658243b0a5f981f4c051061be8d7f7ff3a7f - arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h +fc286a6d896799156121d56095076ee1765cdd18 - arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h +e41af019a383e1c29f6cfe79b98e6812ee9e71e8 - arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c +0f0ae89b60dfac27f5f00ac6c76a3c1fbbf30e8c - arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h +96bd522ef14fb5ff8a4247a028501ef7c4367f3a - arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h +97667263a954ff77c695a93ec98b767bccf035cd - arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c +dcfd794664af1da07e241e7f44705b02a86955bb - arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h +1c0daba5be7bb7055a56df067ffc86d62af94382 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h +962eb919fbdac8edf23f3cca5303772adc4690b0 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h +3b4e4e380dbab1bf4ad037c20f705b6e42b5d992 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h +9fecb13f267ce5c792719b3969ef19e96064d75a - arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h +2941f6674d8de1d2b22c22b91db3b63996c45d80 - arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h +764ceec06291ed492b81348c85ad37e77f32eb3a - arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h +254c94ec21e9680a13a88c1c24d884bfb8b9479c - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c +c693c689d519e4697e033a4df6e7da75ecaca5b7 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c +5f62419793539e6fbda55df6e2b3fa9e0b21b776 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h +492965693fd60a384d16d12de2ecd89c7f522702 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h +2e0e20e6baddb412ce97b52be66cd32d6f8f367f - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c +f925bc09cf5f24b92110d8e7eb81b6948bc855b7 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c +0b417a1d9881a05757a25db89aa6739867cc6cff - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c +9b61ef7f7b42a7a2448ff56ef3a4dde77d0a3c6a - arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c +99de11a8e1d6aa0d67bff400dc27222a3f67bda3 - arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c +003b4e0c6ab04fb9bd51037a2c976e8e9a1e90dc - arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S +1fc45a1f2166ae38c534bcf389857b89c441c5af - arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c +0f6a22f1e28fcb385608a72a297b0cbd67935113 - arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def +492d3f0900343c093e718ba1816eb94bfc3931e9 - arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S +764c8c04a6189e6992612672f9e41abde5000248 - arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S +a7f75b9047c373fb59a317bd6d2995d70aa0aefa - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h +3328578a5401038f068eded4991d6a403c5276b7 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h +344959df5ba88c1bf9ce847e6735395045c1253c - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c +11e2d32b094714041c63cf972054b12b7c0db04e - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h +e9f8a604d5a2d30bd7a467c0b5624df132c867ee - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c +992637daa6e8a443c6f0a176079ce731d593f699 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h +9c8add03dd402a33b546ebe338030483a6e30892 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h +344959df5ba88c1bf9ce847e6735395045c1253c - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c +11e2d32b094714041c63cf972054b12b7c0db04e - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h +30d19335e7872d98487de84b2cc1cfad32bc26ad - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c +d1bd24409a0956382d617f97af627e582ec04d5c - arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h +b971fa529d2080fd471b3ef7ec4466a972529aee - arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c +189fa51ba04371ccab55ac105b7dfe77c07f3552 - arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def +ed1f52b1a3d4ce48135556f32d8667c7367494d8 - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S +63c93614b627d3a013d8176aa4248010115eecf0 - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S +3e9660b08500144943aee803a37816f45307d66b - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S +e7b379eaa610c82050a0e57c194b10a794f23d91 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h +f53ad9b2677286b07fdbc25c8c257e4891f15607 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h +b52ff38c67c39f3dc4731b38d094152cb31b4ccd - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c +0fe0002fb83ef9fcbbed68caa9cea3b775bfc529 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h +764850c7f4814c83fc8b48d4a353c5ae2836edf6 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c +353f72fa699efe7dc63602a04a220dd43adb85ba - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h +2881529cc073176412af0c380690bab77add20c5 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h +b52ff38c67c39f3dc4731b38d094152cb31b4ccd - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c +c515220a4c8200d4212a8d951e49a9022e7bef2f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h +d07e54f7cdb54922dac5c758dd79b5adb4d9e93f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c +f856b32032e096e20ae0a454ad54d4fd64dfca0c - arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h +ab191a3fce41d791a52ed732c81fa4c127537b13 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h +6701efe4878d9b4a7d1035d7d747426951d04e8b - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h +85eb1ecc310643c5e3edb3761897745f5f4eaa6a - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c +c515220a4c8200d4212a8d951e49a9022e7bef2f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h +e8ecd59dc257f4918515a132b0c4787bc1890021 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c +07fb6c57566e19aa44ef34559874dfd995b582b6 - arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c +059b1c4ea6e6b540b7b01bdeb7153b4dfcacdb1b - arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def +b132e33ac02b41bfdd0b2ba27b1e5432e0f7ef08 - arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S +18db50ef3d11821179318d84b45c532d3b107226 - arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S +2e5c9db35f0a8446aa2a2a08f75f1488255df745 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h +60033abedd63947cfda10bf00d77951046e244c2 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h +859878633110369cd34a10f6683227f6b49d0006 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c +802c1d23237eb5cc83388950a75fa13d076b0dbf - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h +2d532dcfca962bd50e2721dc90a3c5e8f3ef4c00 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c +69427e6f64ce96dfa6842364a758359b8fa821c6 - arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h +9b815992ca7df805a51a7cdece2e7c074a0958fb - arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h +7101b940d392636f546086caa2626d9a940d9eac - arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c +490b7dbb3b819d5251283d9069f177092c665489 - arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def +033fd89d203e44c446aba6134e51e46a7d9cf324 - arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S +e436d0bfcc7b7c83db0242b6ffefad0a2985a81e - arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S +b435bed7113e72930be88bfe8f61e7da61994418 - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h +264c5f8c566b8945850048aceba967dd8fd1e72b - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h +859878633110369cd34a10f6683227f6b49d0006 - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c +daffee032773c1420ec3c8da52a5bc9db4610aaa - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h +3268f346c7eb1578007b13a160c4c3d08efe2c0b - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c +d78024dda44030bb2c60a6c6f0f31b0cdf79c510 - arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h +8539e94b825c242859fa5c4a3c03901703c386f0 - arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c +1e814209bd02d7457755dcf4493b05a3794c811c - arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def +8cc150d9e1c9199572b24d0af559c82e4db71320 - arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S +06d4dda248389e306ea0cf1688bc9944d1511d03 - arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S +0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h +686ad098c68cbf424bb3e89e451ab64b8183a91c - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h +5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c +0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h +2ea7db20f6633e1dbecd9a70ed4cac89d97c2a76 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c +0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h +39ce8f1f0afc76a2d1a98e86df076ef84d185da3 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h +5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c +0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h +60e78557693ed12515227f051b8f55baf47ce8ae - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c +0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h +dc407d2ead98e6d20e59ac0b6c5e75116a82ddd3 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h +5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c +0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h +945ec23ee2ba0c79a5e6140d043290e9afde9b2c - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c +bfdacfdea0aa10e1ece5ae2925625ce34328672a - arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h +9ed3d544ff5ab2cfa0ea13d1fb3b59534eb90e14 - arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h +1e1f92bc6f801c91fde3bbe4ce99b62beb0eb7d2 - arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c +42143dbacac34a118b7b86673774e843e7e84fd8 - arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h +1e876f487cd25f4a6cd08d0a21926f5405676a07 - arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c +1b13f9e313e75353b45d6528629485488b180345 - arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h +8403135be33e11a4b696e90b5b253465b6838682 - arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S +81ea2015e04bbc53b7d42589a21821a183fc1c8a - arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c +3bba3282b340c9896990c2ffcbf10d5bfb0070b2 - arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S +4d406209e8b278e9730968baee57f5106d424aef - arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c +7b5d73ec9d9c7e14fd48653c6e018d432654101d - arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c +bffe5bd7851f8d028c92d9d68dba7806be5bd662 - arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c +10003f2e608d5073c076ab1a446f4ba07c06086d - arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h +d4e968db5e699bc36032dfe35d7fada27142c699 - arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h +1027e5173d316fd6d9dd6588b9666b53ed9d1116 - arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h +9026b30dd1244e0fa2416dac0e9f2b92c11bc83e - arm-trusted-firmware/plat/imx/common/lpuart_console.S +829a4463f8628c61fcb335a0dbd747a6050c8192 - arm-trusted-firmware/plat/imx/common/imx_sip_svc.c +03ff82e03dc9eb60e02c6e23f0c199fdd1753c9c - arm-trusted-firmware/plat/imx/common/imx_aips.c +83187f1c90615deae51e2febc0506394e8d4d444 - arm-trusted-firmware/plat/imx/common/imx_sip_handler.c +c014188b6f4a48f9dc6d6fed678081f02f8d8e86 - arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c +e03b60801f58711597b0bb457ecf6e3e84c9f44e - arm-trusted-firmware/plat/imx/common/imx8_psci.c +5225b741c941cba9f489d347aae2707d99896d7d - arm-trusted-firmware/plat/imx/common/imx_csu.c +1901b0c4a5e19926a9e1b5ae437ebbeb0dc0d181 - arm-trusted-firmware/plat/imx/common/imx7_clock.c +ad339798ed1c81b2dfda72cc1cefaae7acb622d9 - arm-trusted-firmware/plat/imx/common/imx_io_storage.c +e7ef15bdf83a7d4e3ca78dd0d0e9daf56414e55e - arm-trusted-firmware/plat/imx/common/imx_caam.c +f30799014ffd50a32b0d021473b50cf5c4a28634 - arm-trusted-firmware/plat/imx/common/imx_clock.c +da4b81f475ec53f2578ba031cd1f30f759bc5dde - arm-trusted-firmware/plat/imx/common/imx_snvs.c +1b219401b9b5eb5bd8c83fa92fc68c591d48a3da - arm-trusted-firmware/plat/imx/common/imx_io_mux.c +b26cdffd75a0ba04b4a312520443d0c77b388242 - arm-trusted-firmware/plat/imx/common/imx8_topology.c +97029bcef11b7a8598834c9717cec7a5655b895a - arm-trusted-firmware/plat/imx/common/imx8_helpers.S +561b0822ac98206dceac588b536d745fc70829d9 - arm-trusted-firmware/plat/imx/common/imx_ehf.c +6ac985911e7e26d13c75d48a04457fbcb209b62f - arm-trusted-firmware/plat/imx/common/imx_sdei.c +ac923dd7af0d3485eceae86115ea73150575ac4f - arm-trusted-firmware/plat/imx/common/imx_wdog.c +d93d2cf3c9aafc65833374f51376f03bc2387ecd - arm-trusted-firmware/plat/imx/common/imx_uart_console.S +36d5f07566aad340b6ec06b01cfbe631023ca7f5 - arm-trusted-firmware/plat/imx/common/include/imx_wdog.h +a3a14f38cbc846da3bc2498cf8e07b62479aa62a - arm-trusted-firmware/plat/imx/common/include/imx_snvs.h +8830c18819f942388c5badcb2c19eaea2ae058dd - arm-trusted-firmware/plat/imx/common/include/imx_caam.h +0b633d6b19c3fd7cb43c433d74b84ede423bab4f - arm-trusted-firmware/plat/imx/common/include/imx_hab.h +8ae002187ace1e1358c7af1e06ef7957179939f5 - arm-trusted-firmware/plat/imx/common/include/plat_macros.S +bddfe7c6dc079e9f45c4a41601888d27f5d29c48 - arm-trusted-firmware/plat/imx/common/include/imx_csu.h +28b31b74552131c2ba5875fb7db44b22ca16b722 - arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h +2e84528c7d6b12beb2c64505a14d73bcfb03ef87 - arm-trusted-firmware/plat/imx/common/include/imx_aips.h +a5fcaffa0e69f234b0620f32d3556bf79ace50f1 - arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h +816bfc02478ff083b5f3557753a4d0d4f2f32c9e - arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h +b9d688fac07189d434ac636324a632e9bf78825c - arm-trusted-firmware/plat/imx/common/include/imx_clock.h +f5724b26de0d68b4b37e1d580c6e30842eacd6c0 - arm-trusted-firmware/plat/imx/common/include/plat_imx8.h +efda9e3617b99df89057880a566725ab2a7be20d - arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h +24f8d34fd7865c2235d12e87791c7ae77d55d281 - arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h +6f89a14dc12ddacabad367a7e69d8bf469274ec4 - arm-trusted-firmware/plat/imx/common/include/imx_uart.h +1d847530cd83143e4a50b94c5499ee8c11f9d3e1 - arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h +8a65436d5e0b335e9003a30f2da5f7892d23dc05 - arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h +f6e6cd4d5b145f5abd0aa4d840fd7757d4b02c04 - arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h +19674e70669fa3f7fb7e509377e445f7fd4c7be4 - arm-trusted-firmware/plat/imx/common/include/sci/sci.h +cc9366b07e946d7946bdfeae628f8a6c7ac3bed3 - arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h +daeb14deb7c4f498330bb44186346cd1ac4eef92 - arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h +70210ef96ff1f0ccd4e790bb79a148f1bf02efcc - arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h +4be7f4400810802474258ed3e4b8f7a73170db33 - arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h +cf9e73e1a62f99ecb17abeeda5efbdad0f7b1c21 - arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h +d3b138328cc81b7fe0a830b3cec8bd87f7d62835 - arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h +2507eeb7a0cd662322ea96553146f0f0dc8c6e45 - arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h +8169135849017c45a81b2c0447e940e3e5396145 - arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S +985fca791927ad8088399ab8840bcbcfb8277a6e - arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c +f2ab11050d68bdc711e7c18f9437fba728ab77bb - arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h +8c98c79db7801610b0bf01e1ea680ec8347be4f2 - arm-trusted-firmware/plat/imx/common/sci/ipc.c +fdc0fc24ee38df2fd92f2f039664af39724513e7 - arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c +9162637c3ad8ef97f19a264c504c58d5886f9d7c - arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h +a593348ba8dcf5a3577bb48cd9d9ab7fe88c6df7 - arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c +53b961e268ec00956cf3635d8561601e5c5bf70b - arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h +65f1e12aab1c7815ccb98973525d32d30e635a1d - arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c +1dc0e610322825b6f58ac08670b99a4598bc01f1 - arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h +ada89ab08a1bfb90ad5b0e5ffb325268ddbc837e - arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c +99d10095088dddbbe81826dbf7827bdc9c6bffb8 - arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h +3f381087336a847b53323f6828aa61478b46a2cc - arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h +30cf1dfdd48ef57921bbd93789aaedbebd754c55 - arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c +7bd8d4e39f1f3905630b08a16be851097fa5ab67 - arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c +10fb6753c1ece21522f45f372d0cbf3b416b5190 - arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c +51949e20cb7aee1a68f0cc5eaa46f0eb3012c2dc - arm-trusted-firmware/plat/imx/imx8m/gpc_common.c +ceb0518eca09618b3b642b96d4fb43d950bdfabb - arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c +996e00079997c54373e5acb4a6f39bfe8cbe346e - arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c +3065b6071ec153725ca0d9782a393ffd3f24745d - arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c +6253f7542bd4e5a6244779068845d717f8eca3f6 - arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c +ee448951c5f07c67e8c374cb6a4077c505070081 - arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c +a2af87335b959f57d6de74f40740b48de27a802e - arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c +461d439b6ee554e1dce2786de8e131e60083bca6 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c +ff7748fc70a67a41bd452b895f531d103d0b3cfa - arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c +d1fa70b45e2971a3e4103d0b2ff864ec706c5af5 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h +2db42326b731e92225ca5c389557d0b944e8d3a7 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h +3fcc366713e1667476479363fd2d0fb74144e491 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c +f9007785b7de40f327bd11a83c710c297b45e4ab - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c +060756d07ff95fa2e15ef2cab742c6f6fdfdc5e3 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S +5e7971c14f77e2f2450badad4a156ca33a9eb89f - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c +a3afe5951fdd7ba0d6e5b64214a2183800a80132 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c +0e0933de6793e323f4c77e12a89455776a0dfe57 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c +1bb0ea0358213dbd45eb953fdbb45234606078d0 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c +0f9e1a9d6497a3ad4e415d483905f2ef16aaa423 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h +4a704d5f5cc4958ad509fe9771d30d6632cb1a0a - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h +c81f2809571226d121ea1917bdbfe06afcd9b523 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h +e7ded5d1571dcf2246b5480dea7517bbc0e45a87 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c +629b2fa411eef0f016ff98ec22caee2012cdf650 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c +d50646f42ed68bca258b692593812b18c635dbb0 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c +82259d3c2b7d974ad94a42c37f37e0a8f0ce576f - arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h +a6e3b2e69300fabcd3a505525cc5d48d88345f7a - arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h +47de7cdf356158f2b651bafb8659187db3a13e65 - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h +4bc0eb69bf40f2ac07200a788f79ad6e9ec8b3f2 - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h +dbc9dbdd5e6269f4f08553a771a33f13a1fa884a - arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h +3bc736f072705dfa2d00383fe60d8497b3676fcc - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h +a70728dd56a39269eebea0b5d96e9e82765e1e7a - arm-trusted-firmware/plat/imx/imx8m/include/gpc.h +5ec5413514abe79264b0bed81c75f811d2621d46 - arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h +0efee336c964d1973fec201980455aee08396081 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c +be1935709a939c0480bc4cc27058482508f2596b - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c +f822b4b589b5d418d0ea960b764bd311a32466ea - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c +49f3d2caa5e653fc6cdd99c140ff61ad9d83c9c0 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c +3d38c99169530f67aeba8526bd7cd4559981a349 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c +169ab98f3d4cd7620ffef0d78f7c2329be9c1586 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c +97a556f1fc780240a2ad81127c295bd39a0c6512 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S +c65d55a5e1a73f615b9fe213427e4605f4b3806c - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h +df0e3b50430ac47d2263ca8e0a4b83d46c8c0193 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h +f7d6a1f75a510179a6e4a7084b3d70dd9bba5734 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h +399d2117be7573ef7ddc5afb0364b90fc66d9bb6 - arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c +b9316c7a608b29b530aaf325e401e06f62647525 - arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c +06458d5a3b748df586e9ba2064614354842c162f - arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h +5f45eb6e98ea9c90548afd5ee153f8d14c105e48 - arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h +9561f3046a19b5489e0aa9025135c8bb6a7d2582 - arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c +08a0687e7c3b77de90198dc7e5d8ca2ec448ae90 - arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c +6beb54a392291f2d54d207842b2620c7c344af8e - arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h +1fdf9dd0a1e00cee360596ce35842f77598cbf1e - arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h +54eb696ef592336053f52bc556f47122b4e94fdc - arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c +793e163b5e60486c53f3ff36c98ab1c8f144a1bd - arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c +5e76d520f8ea85f6710a605e2c9a4db0d1a66640 - arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S +b1c50f058d68ea165b6dd5f45af97d2b1dd33e64 - arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S +6a73f5496572d65332bbf4a50c3c9d4faa9af438 - arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h +e2412e3cbdcc8daaecfab85f295ee3456cf1f98d - arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h +4d8d91a23a19a15ff7c18f8e6e523c26cd453f2f - arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S +11c87bf8a084123bf9a431cc289a66e23112bade - arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S +e621f46501a2d1856f297145947d1c8d89d5f990 - arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c +d2d1fd0fffc8a200fd42f1b74c8c7d54c483f219 - arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c +41feb9d914df818ac88209ee1569e1701d794248 - arm-trusted-firmware/plat/rpi/common/rpi3_common.c +46c13e3cff3d9c29a733d01629589bd31b37eb5e - arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c +dc79372e77a81c53ff2886832f206db2f63873b7 - arm-trusted-firmware/plat/rpi/common/rpi3_topology.c +854bc00d3c5fce60726920c1e5b1b7cd9352568a - arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c +2880e20e8241800797f95dadcd5a206d82ba45ed - arm-trusted-firmware/plat/rpi/common/rpi3_pm.c +d2456dd752e5376ca6049639fe93ef04bd5aa04f - arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S +c3a79cfd4e400e0a2dfa7ee5e27e50f1bcd8464b - arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h +fd5000ab9d2eac8341e267b879e1ef29eaebf5d7 - arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c +052815ff6a9d47f47e57d320313a74f10c8a34d3 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c +20b2e08539e950f86d86538ed688408f90574454 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c +d9b070fbdda2cab75cc45e6dddd9a31f84baf594 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c +5a79ec05194636d3850044f358b4673a3f0b9fa0 - arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c +64987d2484ce3d48cc4431fee2de9e375235bb5a - arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S +7aeb3415e697151619997c1c184f380eb310be78 - arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h +94001fd4bfa1b8e08f4d51f437c7b006362f24fd - arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h +c2785b4c0937862f1abb7251642a4028a913504d - arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c +2514153e63bbcc5513712db8766fd278fa3b0d44 - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h +3dde76eb498c889851714b3d8e6749211c62bbec - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h +0b8b7ce5f06e24ad7b853125e17507934dfc45e5 - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h +1590f260f1febbedf931a1596cea2d2e437ea92b - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h +704da3ea1b61d5106a6172712ecf6a80b1528bf0 - arm-trusted-firmware/plat/allwinner/common/arisc_off.S +e602a60b0fabfe8e91ecf654c16701712b20c3f1 - arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c +a5e148901e32cb7feaef9ffbd00f43a2a661ea0c - arm-trusted-firmware/plat/allwinner/common/sunxi_common.c +a7dce777afe91e3a8d68aaa84d55530a9b3b66b4 - arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c +385e3bbf7c85ef4e96b553e0f9760bfef1e94a3a - arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c +f2bc1957fa87b9880744d070c964b7803c7bf295 - arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c +b832fd1c1d7bc307d2c3698bf00ee15b93de8cb8 - arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c +a9a0eca6a5cca079ee8007e0afa7f0ffd7a0cf1c - arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c +0ded87657ff47f0fe5896f1ab1d6d2f9b34f0429 - arm-trusted-firmware/plat/allwinner/common/plat_helpers.S +a44feb979fffb71189cf9943a6d99946305122e2 - arm-trusted-firmware/plat/allwinner/common/sunxi_security.c +711ef06aa592d857ab47ecd0a9b7870c6fa1a5da - arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h +7d746a44b6a3bbaa1c3e923de0abdfc40393712e - arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S +77455765d6d80bf4a48d7744bf6f4770b7369215 - arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h +cc00c1c7f46a2a8af976c1c0fb59681803b68d1c - arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h +4333584318d0a967851853f5fcd6c5287277246c - arm-trusted-firmware/plat/allwinner/common/include/platform_def.h +3fa3a563994fcf2710324634950265fc8f9d7850 - arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c +d430caf710295e9e77a240b785740fdde6705e26 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h +1acbdb220cff8edffa7cc7fd4808f71574b90966 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h +f8fae43c9902bbf818480c6633e05fc6b751aabd - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h +2870bd5728ae0e5857fadde22b048a6fcf6ee2d3 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h +a38730b258e2c37f114fdb3c923369bade8e7a1a - arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c +54ee3b911a552e2cd6e3802820f5cf3e09575a01 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h +3f4f908a2f0a6a7660d40d79215077ee248f740e - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h +2c5ad97e48086e62d1d58d1d8289ac4ab3153179 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h +a462f612d127344fc711a68e3751b31b2b7ce938 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h +65eec287284371a887adc4c9aa1952c26be66df7 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h +786942614a650ccd6930f2bd19bb42b2b539e1f9 - arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c +d9eff8a29c53d38215c1d261922df8494c88d5aa - arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c +2b80f35aa1746d608c2eac4eec351c292e0298f0 - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h +3dde76eb498c889851714b3d8e6749211c62bbec - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h +0ba24eb82465b3d3ad4e293692984b972663d57c - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h +1590f260f1febbedf931a1596cea2d2e437ea92b - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h +1c810633809eed169ef7ae47da01b6326b111a64 - arm-trusted-firmware/plat/amlogic/common/aml_console.c +887d16c962bbfdec5ddb366c33ffec0ad5697447 - arm-trusted-firmware/plat/amlogic/common/aml_thermal.c +f1168dcf0c90f4d7a3456d82b909e287a16875ed - arm-trusted-firmware/plat/amlogic/common/aml_topology.c +1b86970e6e211ba1548f3469a4682db7c31577f1 - arm-trusted-firmware/plat/amlogic/common/aml_mhu.c +fa91c2d51bbe34be89ba41e055f4e78eba6ac67e - arm-trusted-firmware/plat/amlogic/common/aml_efuse.c +2321fbf75d8e96d90a1b6f6a14160c91b949cabc - arm-trusted-firmware/plat/amlogic/common/aml_scpi.c +22fc306f5f9b6613312023233481baaf99493614 - arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c +61752908966c74b637938d2fa11e73c5d5373d9d - arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S +74bc476713af13ff5ee94c7bdad6c5763f99e9af - arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S +5240bdc42061a821a089cae1eeca3fb799e6aa1c - arm-trusted-firmware/plat/amlogic/common/include/aml_private.h +5ce07f2865d514a3a8979c638337a338fa110f74 - arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c +68a18488494ea52a108462ec30b6833447e75e62 - arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h +550ec6753c2e8a5f41a920ea9bfffec47ae78dc8 - arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c +8b93edbe34b51b737299797607de4e6ff0003917 - arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c +22603b51918b7c1f721eee33d26629b16cff6683 - arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h +fe8712d8d4a3787c6c2456ffcc2cc468b12bfd7e - arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c +495f096204283e82b03abed56414e3d1a29f9b6f - arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h +03a70925292deabd473bf5ffcd0d0d95dd70456e - arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c +28726387d3750ce4724f9147e5e173131ee7164f - arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c +8e1154709ae343cd8d783739b29005ea2b9a7c7f - arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h +3389361e87f5cd5e4f7e606599032c3aa3a41b72 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h +704885551348b4b44d9b7b092aafc3c54533b7e0 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c +25d4db1b1e385a2e45f4ffea43edbfc8bf4fef89 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c +80fbc4757d8f389dc885b90a5eef8c0c4f6e23c2 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c +d558f98c64955249d21b9227149b68808cb3e358 - arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h +7fdb79ffddbe1ee7f1b2c543a1eaa07f2671a2ca - arm-trusted-firmware/plat/amlogic/axg/axg_pm.c +c60f26b9eb14d703065a758062f9c76e4e70f8ed - arm-trusted-firmware/plat/amlogic/axg/axg_def.h +3667781fa0058dcdd1cff5587b45c798978c7966 - arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c +d3c822e681ab6d5016ae06adb88ca9aeb6073aba - arm-trusted-firmware/plat/amlogic/axg/axg_common.c +faf31bdcea206b83c40fbe2d878c14fa8327a37a - arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h +5e22516412e81af7bbc52e0e460447cf2d1d63f3 - arm-trusted-firmware/plat/common/plat_log_common.c +cd74e2d1ac7f09f4ced54eecf4bed38f973bbdfb - arm-trusted-firmware/plat/common/plat_gicv3.c +c7afb73f40f0759cd775aec59723f92f7dd54435 - arm-trusted-firmware/plat/common/plat_bl1_common.c +ebb8418a3c0ba1d0d9362005c17fc4a3fb03cf1f - arm-trusted-firmware/plat/common/plat_gicv2.c +dd38f3a1079a17328d48c8cb719713d4de7361a6 - arm-trusted-firmware/plat/common/ubsan.c +ca3750949173b2315d20907e7c6da4a66f32a5cf - arm-trusted-firmware/plat/common/plat_bl_common.c +8020a28923a271101b29516f4997bb7a1b8a6708 - arm-trusted-firmware/plat/common/plat_spmd_manifest.c +ec9195d2ba3b66b6f4258c18a36b14a5cf41ac55 - arm-trusted-firmware/plat/common/plat_psci_common.c +6ae1755d17b7040c038dd8b2e6c6880e2bb60394 - arm-trusted-firmware/plat/common/aarch64/plat_common.c +8be9392135f6389b22910a9e22011c2e5abc6708 - arm-trusted-firmware/plat/common/aarch64/crash_console_helpers.S +8bf3a22931bb5a18034f1275429068834943cb9e - arm-trusted-firmware/plat/common/aarch64/plat_ehf.c +53568d8d4a43005d8a1be8a379cf0f4b7ddc5637 - arm-trusted-firmware/plat/common/aarch64/platform_helpers.S +1fe60996e262523b671b678aa41a510a2cfa2ce9 - arm-trusted-firmware/plat/common/aarch64/platform_up_stack.S +785a7be686f124f8b30c5f96bbdc9670988f49c2 - arm-trusted-firmware/plat/common/aarch64/platform_mp_stack.S +05ebeff6ee2416ab2697799fb338367a03b0ba75 - arm-trusted-firmware/plat/common/aarch32/plat_common.c +c8eab49f9d5326ffc974d2ba7c05bd411df90eb1 - arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S +01fc909940aee253c9e140248811b8c4fc5d25b4 - arm-trusted-firmware/plat/common/aarch32/platform_helpers.S +f742befce701fed79ec16b324c92409b36838226 - arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c +79f7a0e7df796600cfad4b11f4bf7dbafb65a4ea - arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S +578b46ce0ccf74ba18ce1747df871537294d4ddf - arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S +36144ebe1637da9185e2256593f8aa7307d0cccb - arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c +43da4a7bd6435c6cc7d733e6363a59cacabb9ef5 - arm-trusted-firmware/plat/brcm/common/brcm_mhu.c +c02bbae941528cbae0665016d62e54bfffb74444 - arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c +389238486613bb86c6032f788a4605c782e7475c - arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c +48faf64df1848d8493a3f273494ea883a4aafb0c - arm-trusted-firmware/plat/brcm/common/brcm_common.c +9b8db7387e47af68fc183fe909d3060d65438cb2 - arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c +d083c67e189d3cd3712a827a23e28d0aaf2964d1 - arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c +02ea7c4006c2910720bf4a85c3766c293d4cb8e5 - arm-trusted-firmware/plat/brcm/common/brcm_mhu.h +2ef6d891873792dd5af17cc1091f369c0865c70d - arm-trusted-firmware/plat/brcm/common/brcm_image_load.c +6d6865834cfc5ce82506bf1ef6df2e3cb196e028 - arm-trusted-firmware/plat/brcm/common/brcm_scpi.c +7c0af43209d486bb7d9b76b244d3fc5ec97b4328 - arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c +303c81103a6ebbdf9e4afc16b17d17195a5b9238 - arm-trusted-firmware/plat/brcm/common/brcm_scpi.h +43088754fcc9a1fcbb6308988d79eca0c2771d5a - arm-trusted-firmware/plat/brcm/common/brcm_ccn.c +a794cd95a890c951acc5192426abc008b4213a8f - arm-trusted-firmware/plat/brcm/board/common/chip_id.h +eeff346a4c2b6893ad0fa417570e747058627c11 - arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h +2d3a08ac4729a455bffd5c4c70365350fec69e23 - arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h +779be799404c9562032c8c586f3a3b23835ad722 - arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c +801bb1cdab4baf3440ac23728e6190881af4264f - arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c +c0ecc823e4de1814edd6bf48321b6317c448b16d - arm-trusted-firmware/plat/brcm/board/common/sbl_util.c +2cf7d5accbb22d89a3c89c768604f667a23bef52 - arm-trusted-firmware/plat/brcm/board/common/sbl_util.h +dfc2e7fae9dd66b664758412e1f4c06762246ed6 - arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c +5f45cc70d813bf16880f4f1f4a246ad6114fbb78 - arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h +aaa8593ded989c77280d5a16f541eefd45c62067 - arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h +eca89f1edcb0c3fc702ac123a55821cde16106bb - arm-trusted-firmware/plat/brcm/board/common/err.c +9eda9f547bdfb6e83ef3c8d82d849e1e4cb68252 - arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c +b2a5352558dc92001c80e614a9b293a1eb19573a - arm-trusted-firmware/plat/brcm/board/common/plat_setup.c +a731b4badf1cf5a90a0ab197b39a2723e4c85dd9 - arm-trusted-firmware/plat/brcm/board/common/platform_common.c +9635661f5e56e9ab172dcec943257465bf36e634 - arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c +500e36754a0240001fe7b400bf8d4806a06de6ee - arm-trusted-firmware/plat/brcm/board/common/timer_sync.c +c124ba5ec6d9fc3e8f1f0b72d3852473ab67e998 - arm-trusted-firmware/plat/brcm/board/common/board_common.c +515e3aecc5237dcc8197e4e8ed7fd7d15765d808 - arm-trusted-firmware/plat/brcm/board/common/bcm_console.c +ac2b64132debec3b54ae614c64dac69067b39291 - arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S +b4637f982a40118b9d83d3908d0b189d3524bce0 - arm-trusted-firmware/plat/brcm/board/stingray/driver/plat_emmc.c +4573848f39ea4bfceb55e0932f0494af8b890d1d - arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h +7cc68c731d1d4e967a6b258c94afef74800e2c27 - arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c +483849480279e54ca28e4177fea05d6bd3cd36d7 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c +1071f5589a11aaf7354868d034e149b27d48adc6 - arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c +13bbb4dc261e840997a59d4e914f071835d33fab - arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c +eed068af90592502021f8e15b556ae302cd8db87 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h +d0dacd8fc79f78cee10bd8513550abf93624afe2 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c +46e832c20411ea4d2bcbcf1cc8968149375047f4 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h +76dbcdb10f12f01d94b3c70d2f8562b0cc8b233a - arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h +a6bea74c09e847241ba6a156aff89b12670cc98b - arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h +2c4acf78dfd7c25c281471b6717273ff7920fea8 - arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h +4bc4735b9e7c2a5eab8ae91a28d110dd24a42d75 - arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h +eeabf0e8e4cda99b503b2ea41298aff2d87e1278 - arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h +cc26d153c04427651e12bf00d19497e5bd8cb7a3 - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h +1dea9a2af71a56fe60929b854a2c73220603d2be - arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h +10104d7d5d9eeeb545dea9ac306deb2c5cf46036 - arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S +b0a1c672d4d7095f6e7ec5305e084cb3a29a790e - arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h +bd25c5d9d7605649bc1d1dee9a734ccb130101c3 - arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h +8c57e437d9f4b2b49f005f899624af9b47121102 - arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h +90c98d478915f89433c419b06613a52965aeeef6 - arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h +2817bede11ad2da4d5612a155f5a76e30b62de62 - arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h +bbaec5f331d8cf8f24898a8d172190c5f7940b6a - arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h +491a5116f054df365b530dc8b09613f1178c2d8a - arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h +e7629876236e444ee69e40c96440f3f24b16fefe - arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h +0ef862af40a95d70feda6b8367e6e7452e90099b - arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h +2ef5c016a1130291e30fb58c1e1b397bb15a531c - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h +d823df9c59408673229302e557a65ad1c404e047 - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h +9765542d155d4fc37ee167eda672c6a33030ca8c - arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h +0228e24fbe8ff775ac7a709f272d375a8e7aa3bf - arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h +1e67ee0873eb29816b418096b514d39c3aeb7d27 - arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h +77916c4c9e55da373b1b66dba19dfed0034cde48 - arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c +52a5e5247c12940390abe486ab490a1d8929feb4 - arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c +863c6f32899af28cd9a60fb273bdc02a29100114 - arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c +0283858faf5651d4db16f0e4b8bcaadd40bcabe1 - arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c +d746f7070f366ac250b3766606d2de76a6192436 - arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c +e9f5650def0bf0c03c50ad69056cf6ff9d71a715 - arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c +d15b82eea2aaa023805036e829ee46cd08ea72ed - arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c +f89deabe82fe9129f1dde3fb24e57c940e008913 - arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c +085cb8e4f6dd01efc01f633680e7db315718c304 - arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c +072e5bc5c72a860c50c3413898b60dd18931b100 - arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c +c01d8b9f9c48a1185129c492ab1f8ce1134ed892 - arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c +1fd2e7122a0c63a14a64215ae5750097f050841b - arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c +062b1d173f23bc015ebb5c790f890e5f2a6934e1 - arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c +78d2915d5c3a6c4b75eb97c897cd4e58b4d5b962 - arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c +9b0afdae90ec3159bd428d4b9f586d84a0cb55b3 - arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c +75de08bf7cc548fc88463a459efa719ce9dae276 - arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c +16002a1a28f7ec581aae95aba10964655f89c5dc - arm-trusted-firmware/plat/qemu/common/qemu_pm.c +c154631e1880ac14882cbb7ec28846bcac331126 - arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c +95a9e39672a85b16243df6db511e352e068b90ee - arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c +00fcc8b29bf97f9ede1c2dfbe40db7ef83c72695 - arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c +2085009221c46e8e62ac297e819084f4b6087615 - arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S +8ebb840a06cb6dddf6c0fd5fe4a612f832842576 - arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c +ec654aff1a7a4e282bbbe2dc13b2042b9534eb61 - arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c +d78bd11a3e46b66140586c01d9f834a788316251 - arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c +2154f29a91decb99dc45f21e790dd6e0d1da88e1 - arm-trusted-firmware/plat/qemu/common/qemu_private.h +ce499ea5552f0a580d2d730cd86b20a544fb4759 - arm-trusted-firmware/plat/qemu/common/qemu_console.c +fcbaa96813c363c3db4933b80039d532e1252dc7 - arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c +51d8305f79f4736a224811e549fd92ffee6e2134 - arm-trusted-firmware/plat/qemu/common/qemu_spm.c +a58c658f18083c55761b946dd01b034df662dada - arm-trusted-firmware/plat/qemu/common/topology.c +854064daf74a72113baf3004985576f30ed85540 - arm-trusted-firmware/plat/qemu/common/qemu_image_load.c +3ca3d10548276087940fd7af8f274b1b68378322 - arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c +3a64a36aaab153d084cd63cb8041cb8e4554c206 - arm-trusted-firmware/plat/qemu/common/qemu_common.c +21efcb8ca3eeadb04af0ad8b5dbff0a548221482 - arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c +b70358ad6ace724f6125a704a64bd882bb7e5e13 - arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c +fe635c884df368ae689c259f9ac0787b17064bb4 - arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S +f58716f140fa8f450f8073fca6f98a8eda79bbc2 - arm-trusted-firmware/plat/qemu/common/include/plat_macros.S +674a4514924db14c06277e39651b46250347d7a4 - arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S +553cd30299445b034280689989176963a39f2b4d - arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c +dc0cb18de3dee5963f78466b58e002bc816d526b - arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h +f2efe87ffe7cd41bf5ac442c75b40fb2593a8fbb - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c +a3366d3ea9b4a5a823b365b0a4fe16dd24af7388 - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h +151cea63605746875bff4fceaa296485033aa280 - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c +46b611bd4d5b4370f104fdcc62cf5da040ec7970 - arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h +e4e4584414cea9a632b613da62b76c3999974c0c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h +006db753e22b1119a67d4f76bd213bf3de08be09 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c +30d16489f342eed522b276128737ad41acb82ba9 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S +69a2371870f65a855d9ff7c728f2e9c32882aa2c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c +21ef9559c64415fef54f3373f28fde4fa86d92d3 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c +2b022afd58ed2221e8abc99099867eab0c42c326 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c +d342acec84b75ea4f64204404f0a54b4158920e1 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c +26621302eaceca62d3b0e8224c6c14d5ea08df38 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c +5fa3e198d6ad7a764cb058e6e88fa12a0d8ffe85 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c +ab09cd5d8d3222857a607791bee8b31359314aa9 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c +91e3ef5fbfd42b725b57f2608d1934a5c717de3b - arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c +516680ab29649a33ea07ffa922f3b18448e61e55 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c +05b8fac4f5d6b8cee9465b541e992f27f071fe8f - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S +7518b6009c736b543504a3f84be4cbd20e8d9f0c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c +eca523ec19dc113ddd19b9427a6651cd6ebe6bb3 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c +ad344a675d5f4bf3287a6e32451b462c3ea7d29c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S +8a0a08bd7b9292bd5b334bc91ad422838eb83118 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c +7cb14fc4ccfe79fe8ffb080b91337e263775111d - arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c +d94b79f813abf374eef409d04968fce943a3ef84 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c +30db57b3d947cfae86d4cb1fbd7d79f7365fe01d - arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S +dd16d7be9af0988718096ec4af552732207ad390 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c +98c1438c270db5db7bd6f971cb928420df53c1b7 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c +456820f5853d3f1676ee19bf63b9c360ed9a80a8 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c +b445ddffd2167b6758d19874673ec99f3f2a1d30 - arm-trusted-firmware/plat/socionext/uniphier/uniphier.h +8bea3f2da202b83b97d9b86e32cb50d5c17cae7e - arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S +e35ee40c042c15de97496be4f1d9c81b960cc3da - arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h +d181839ef722d36e8a51c126deb67a2eae64c527 - arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c +72b5553a5bdc53509ecf17a4d93cbfa1e3d06c8c - arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S +f43a62ef3a99346a097b8813441539c5354436fc - arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c +9b1262ca8c6950227a294b789fb3e53dfa2086b1 - arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c +8286dff95425dddb9a5b25ffda50460831781793 - arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c +a32f17d7db01cfb7a14811a914ba2066581d29a1 - arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c +3db81e971dc630ca534efcd02840b2ee0fc01794 - arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c +f9ac11a5c154783dbbb6fbdf6485867b754f511e - arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c +b60ee8850906f76ada82b2db19c8656ed9c12d9a - arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c +e431465e90b8b68ce2922ff400c2e6953eaeea9d - arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c +f57f50699d6a8f3902d4673f01ec3ff0d6931d29 - arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c +f8fe95fbe1e35e8c328ec5a197b76c329feda4bd - arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h +b6784404cec981a185e6f44ef689f28b7d9513e3 - arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c +ebfc7926ca7e342e5cec3fed564e68be76a80fdd - arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h +961c660b9e7a5641523d5d23b5396c2a2a67746e - arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c +09ba9cfb7c8be52484c3cff427668fc7d2524219 - arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h +9f24e8fcbc08c61f43c8041c0464cae65fe01ce8 - arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S +25666183a169e48e144659003b018f40881b4590 - arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h +ef74e9cda94f07bf3061b037195287d609c0c6b4 - arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S +09dd0d32acc68693a9cc4e6edda975b30b997a7d - arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c +4df6d997a517a03b7120733e3ff6f1a2634caa47 - arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c +077745456537a78c6a462ecaf23835c3ac381a92 - arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c +5366b77beffc310cab412735a4e4f43185e171c6 - arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c +43b6cb88b4528db3610c0591b417afee9f8e086f - arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c +942f440e430db3a0fb9bafcb2877fa0f2b2b2206 - arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c +166469bcfd5bac8ca50e33d23d40607d532f7a9f - arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c +706af98521027fbfb3cb50742e9203904186ccfb - arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c +575e7801ee2435ca3d3bc588117235189cba8fa2 - arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c +5b726e62a784d7660009ac2235ebf2d76dc809ad - arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S +ef034cd3245b78dec24c714d8ffbb7e9b490427c - arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c +54bc2fcf8fb31777a2eee36c5b61246cc0fa0a17 - arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h +2bc481728aac66acbe669f76aa6dd84c3f4e88a7 - arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h +7309b02ef23609fb839b029b295bffaf714cdc1a - arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S +e8d837174e3274ddbcd923af88d3e19e1af8c06a - arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h +5333986fb9d6df5ca3e50aad616e8c1422eafdd2 - arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h +b8ddcea3e66690f3932ae009921566fe249feccd - arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S +1975a45f73616d0ceb03dab4a9397cbabc1e66ce - arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c +0aace28e8f75168d13d7274d81f1f906cc1b2cae - arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S +030496606ff67ba16f47be9282a04338261e38ea - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c +126933334b9ebdde11859016f3bbcc6ac9bbef88 - arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c +3f90b73f27ba47848db784621dd350e6a5ec54d9 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c +e90b7c0a59b785560e233605f2968b642d26fcdb - arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c +bca37120bec0db88310c0e711220bd8301c8b932 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c +1dc25162c504805b378176ceb2a1fac39b8fa3e2 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c +b0603f49d7b1252e6774be83ed95232695f1f263 - arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c +e5479e33302a43e627013dbe10bbcca8ccdbf8b5 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c +33f9c2d61b7aa3242f22100ba2694ba2709f7a1b - arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c +cfc7af573fbb40bb702a616d8f0bf02b017a3e0b - arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c +5366b77beffc310cab412735a4e4f43185e171c6 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c +132b89dc419b19bfabb3eb2450a5e74317faea11 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c +8b11d0569d254ee10c03b8e7dfaebf823b7b1746 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c +1b333e35df79afc9319c45ded87fe22b1e5547fc - arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c +0472150350a0f6a23e8750e0fe14991d176d1a04 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c +a68989337ee4c06cf76f89d69cfc5c3aca210b00 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h +0071214b6af7f5e24aa92d4e7849c79c3818ed05 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c +f3431f5300aefc0065b1e6ad9f3e996878027bff - arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c +f4fe9f99f519b213b8d23015c37b2e4013ebb066 - arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S +fff863e589a15845fe768ee9bd16a482d5946db7 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h +ee2004c34a377b43d61f3fde4201ea86e1834fc7 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h +31f012031e8dec3fe5dab7afc9ab89deffb7fe7c - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h +79f261b3e512eb92ef04e1b172276ba95108b6ac - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h +659dfae8f25d18bef4e2ac3c9b2cc07bbd255dd4 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h +98509207554ab836b38f580d203793668061ce40 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h +5da379773f07f291d897ea36a13ac008c78bbbe4 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h +4619ff482dfa91c976c3d58153ac694dd92a0abf - arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S +e0f40190a4d2a13086e9b7c951d5301f744dd767 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h +42137e1b1e1f31a2b92b351765982cc8bcf28601 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h +b9c87b1b0f989e816c65163d00ead7cd68b4b6bc - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h +e2fd2bbe14a506ac8ab6eb8f4c65dd34827b33a8 - arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h +379cc0fd2c6486a2bfc850d19190835961783f16 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h +eb1ee8f26e0a9e1d174893e2a80e0ea2be070df3 - arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h +c54b714045ab12cfcff4363f00ce94952a40e2d6 - arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h +95b6af34fbda29b2cef5ecaa3ecf9deb1f7a48cb - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h +39568f02d9e541a653aaa3d8503e9976203e27b5 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c +0cd271eb1db1372ebacbc89a1ab7e6b858522177 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c +19471da73d6d6e0316b89091e8034b65252676ea - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c +e7130fd49b764ab203b1f70d8c04929b17c338a1 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c +df960717d8f3e8b3111b85c464d02214767ffe67 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S +9921f6f68c3b333297fb84f0c74626e02e31182e - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c +3b43870e172a97e6682dc9e7adeb7ee54b219ce1 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c +b4ec4794171dff334edac55b287dbba42365301a - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c +6c598ab11230d9af7684a342f64de0ef3aafd2e7 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c +92c35daf2b450ff28a8d64da226b020489472149 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h +e521b7127c97a6dc50d62a6fb23613467dfa5c91 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c +a012da0cb3423fd96bd536ca33852c8fba58ac2d - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h +755c811030252ea484722f83c6773b03bcd1aecf - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c +e5d1ee45233d19ae915b7dcde9d177ac30ff3c59 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c +1178b52937b1f59d49a4b24807fedf6800893f18 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c +33e4f92c8882961c556666d4e463a0cd932589bb - arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S +00786f6204973e7255b3183326d7e2fb8a54f0a2 - arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c +168bc920b2828c8478a977c1e6b9e597791c0e45 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c +4a0475ff7dac46ea547e623a9a83071f69b5a4b7 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h +4abee183dc860ea0fe600bb9b19e3c4a0a3d6773 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c +9b6172a308464c71e87f1f420cb1df10ceb7bfb4 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h +201bc8884be1cfb9b4f87f3fcc6ccf3aeec268d8 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h +390e28e24c8915a9f956b1a1de0cafa7306bf9ed - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h +930c77f84c5ef2c7971e52015e58fd9c314fbba5 - arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S +ce594eaab37f132b152875858c98ea6a8cf2f005 - arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h +d8da79f1ebd9b100b4d3dc915552f3d086d5eda9 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h +b1be891afebf5d255da6f6dcb865725241f566b9 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h +8274c219bcba2090fe7e6e628abe65c7c3780d33 - arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c +3cb5ee19a3d0915879c602a240e4affb4a0d7c94 - arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c +03b9e95dd87fe5cdd436743fb8f5f59d4b2f2de3 - arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c +2f1976dda894f28a35f0cc50623e070a354d044c - arm-trusted-firmware/plat/mediatek/mt8183/scu.c +e9bb8f5dfe42b8cfdd770db2301155ad00d93617 - arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c +7a7fbf6ac91e6e9ff86ac7350e8de64f834b5997 - arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c +9065f62c97422538ddfd15c89806f2869ffb98c5 - arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c +c7ae3ce6e37f4d27b8733d9c3b1bafa8add40a8b - arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c +c5295d987eeadbc7fa82ddedb5266f20e7dd3cec - arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S +214f922545d6899c3e5621df156f1712ebb3c009 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h +ddd6d454dc5e0a1dead801b5cb856c7f27a8065e - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h +1d535ab7f8d2fb5131a0ce0e6a7b11c4a188a009 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c +51b89484342a85c2ee1e944fbbfc08a8bc663f63 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h +4ab8cc9c4d3ff197639f9b78f7b860ebb8879967 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c +edd71b3e0aaea146cfadebca131cd7e6ee13d303 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h +888e5c6480da8cc9f0dd6d5febc12f7d0a8a16fd - arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c +264db153102d726c6a9455244b40d552d0960af2 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h +ed39e8ba2090c26070e12def3287c0ff46721987 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c +316277d91acd7098ec6ac153e95c932aca46d3c5 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h +2e1849b9de23cbd064f9e90e4c83cd761e284e18 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c +96ac9c853839aff7b9c19b8ce2bdd09ffee2c87d - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h +1f21078b5dce77d5939c39ae046fcf15cf1bcc4d - arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h +23040542c3bf819fe42a45ea51427b1a39edfab5 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c +0bae9ef296eeb3bf9ed2342aa58b2d505dc8f04f - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h +7ac4fd4d1072962002d4b4a7439a7fc6fea85b48 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c +b26d910796c32c24b2519666922a9991a16d3562 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c +fe16bd5deb42a8c0e902c3a7547e11d7d5afa0bd - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c +8156e8c4b7f219c9590cfcb2338d845c2b0c71b6 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h +fdbc0bcded1a96ceeb994c74a3a48eec3af06df3 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c +e92a0c648e09b96cd906a5e008c418d7d61fd577 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h +f1a812bc872a1ac1c695c5485fba1a135307986c - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h +645f76b92e2714b452ae24edcd6a40cfa879ea61 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h +fb3c91bb75b7fe6fff5323ead8dc73efc07f1289 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c +346960934a0779649e0412ae87abde963086ff8a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c +3a86fc89605145b3faa5aa385e8f7a11851b424a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h +94b038f0c7b76069f4f85185a375d4d2aa61a74f - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h +62325eff3c956aa9ca90b298e958e8ed5941a8a4 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c +88c148094b3fac4149258b8fe4786fe4ac3f8f3a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h +a52a6337e1e29bc64b0d301f31d88c42981a1105 - arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h +01e8de6953d79923463ea639e7d8e218ecdbc8e6 - arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h +a4d241e1fe6a38acfd38a895dc29d0d3762c185f - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h +f7b9354cce893182c4203079dc774a9b048d05d7 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S +97a99a4b4542d549efbe9122362e0ee8fcac89fa - arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h +16b7a7f8d62f9bc9d06c01d5e72b2ef5653e7455 - arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h +447f690a22efc00539cd931fc1d9aba592997a19 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h +387e06d0f2e4f36818ebd660cd1c4d429222a6fa - arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h +9ff5bdd1f6610dc5e442304399c97ab95361e3a3 - arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h +58b0e33d4a7460c72049a50f5cb8e8af5a5260d9 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h +9d567134def757007ff0196e1a84e96ff6772d7b - arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h +4f1e69980b6fa0691ac24f320f777fa5f690c987 - arm-trusted-firmware/plat/mediatek/common/params_setup.c +4fc10ec9bb95247b13ba3d9b9edeafbb42ba4037 - arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c +ffdbbcc522937a13b7f658754005673d0257f6dc - arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c +311eaf7d7a3b040aee08231328317674a1db9975 - arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h +7858c40d5378047a8869189376fb70d934ed6f9b - arm-trusted-firmware/plat/mediatek/common/plat_params.h +91005aeae3d9de06561b65ab2fcbec18472bcdd3 - arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h +561bde7d3dcce4eb570c0798866c49ac31db4cec - arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c +c272dea0838b85718c51563a46b3274a684e1b83 - arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c +32e5d4c9af02cbaf4603a45ee6ecc742ae4e1a0c - arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h +eca4fbb32aaba0013f15b702c44892eef43998c1 - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c +47b4f5bd98692841b45386f4ac1971904a86e5ef - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h +126307a49e31392042c3224d14fd15ba85a79b43 - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c +a439bfc1e0a18de64b665a1f9f1612c6c723b298 - arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c +a183db6162649664bca3e1e3a7650f0c641ce3d0 - arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c +ea57c5163cb9ad847760738ed46363d3b3e03dd0 - arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c +c78b2291f89f3cb41916e636890a3b8263cb6250 - arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h +7370797acadbb4e47f7b8f407834dbb4c932cc16 - arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h +8cd2ff88ff29bd0f9f3b205a057f4c9bd9601adf - arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c +bcc701f742bbbd6ccfbbc58e60fc17bd7ea2743d - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h +db4a5136746026996b722adcae43bef2530ca8bf - arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S +72586b214f5212b1d0cb120063c07e8eca22b38a - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c +13f55b9e347d50eacc00a183d743c28419be6dea - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h +990b19477486a12883414d383890f2bebcebbd2a - arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c +7203181ede278ce1fd73cf8b9f9204b6cd508282 - arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h +37f3112de6efd829353735288a329458891db6f4 - arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h +dbff628762b596a369e7a96908226677ec6143ce - arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c +cdd4db5d5ea83958ff89700a430e1c54729bbe76 - arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c +2e61bf89860dc6368d6608e4d8447e685d7d88ce - arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c +975fa62263fb56cfc6d4832599aa8a421fbef3ea - arm-trusted-firmware/plat/mediatek/mt6795/scu.c +9a2cc2f4d94dcff8028cd56e4bcd01da0dbd4a6e - arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c +f42fa6a617844b8c56879c8b1f3c34ae4b77aa8d - arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c +e957b0cc082fc56d3b25fafcedf71e23b8fffcdb - arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c +41b33f806ea4e94c4dc6f91cf13b8fe2dd08272b - arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S +c9da62c4ac9c51366c26ca27dccdc85fb8840e6e - arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c +5c5ff1370ff35d42d3c4d77b913247276a4bde02 - arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S +affbb4d9599159566bd93871905eb54cfd7075d7 - arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h +b9ba707119860e36bdab2e1517f34832022480ec - arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c +524f765609b42d6239efa9fbe9d123e031c011b2 - arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h +817e6a410e02d0889f5f69f3da13113cfb9648b7 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h +46009c0467b0d5f5a2b78837653ac6c1d8154100 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S +f2440de976c6c344fcd2cb08353d0bbcf16d8e98 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h +9f36f3e719ea61b6f45d4f3e36e813e42cdac8e6 - arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h +948df1ebf0176a6b28197dd1f5a96ef7b3407200 - arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h +dd9bcb0a34eb0f2806dd3d2764341217a12fca53 - arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h +c585fe19743e984a106c899e16d61ef97416376c - arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h +e90649554240f75d20e82bcaf1d5fc7f72308d84 - arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c +abe0c66165b32a2f3dee830062f153c3c29738ce - arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c +322049a08a3981e4c34fb6991314537e02662946 - arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c +9b148285683f9f62babcdd92b4cbb3edf8d47275 - arm-trusted-firmware/plat/mediatek/mt8173/scu.c +6a2d3a421c077dcc608a94317ecf55a80c640d76 - arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c +b49fda8c23d477e92d842bb950e93962c77a82cd - arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c +5b0d461df0d4936d87d5a3b87846da17b5bffdcd - arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c +314689d0bbe7b2567ccd667c6f70815679729e1f - arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c +fefea9a047dc27fa97fc660c62bc2a4b68539b35 - arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S +27cbf1f064da3e18b5cd7c0e83fb1c9da349e00e - arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h +42adaa32fd22643561c090086db64c635fd6d686 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h +b7e2ebfeb39fa655c846358a6439c708fba4b6d5 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c +0f16bd582feb0391ddd3b4685fab51a7e11667ca - arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c +4535129d635202f3bf1b447e411bd1c7eda5f7db - arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h +bb6c45f6edb308171b205123bd682e3db84ec58f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h +d86950fce5e4e2f48f1efc48472289033367e47e - arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c +9e687cd54be9aa08265355e1079ba5f6cd2a93cc - arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h +4af6a675f41b6d5566fcc13863c1507f5fe28f7f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c +4398c8e27acb0bc2b28771ed5c1a0689971fac4f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c +f6fe2ef42009b0fa69b3957d63488b6192072275 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h +d73f4f2080ec7098103c5209a4c302f80535dc77 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c +b18c4af2e0471a0d5de267ac5c1e4a52b1c94ea6 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c +f3ba2dabf2cabb2644ae09476c62fee2023d6abc - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c +8ffb063b98ca22c66f9f96260216a31b1de20519 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h +0f38df7cc1b225ffb568e7df5c4981b0d29ee7ae - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h +9623b67d4f2dfac8dcc78ed711172fcb5f85511d - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h +3160163c493937b3bb0298d50d918627d0d0e4e4 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h +27287e7e69b6a6be66a87cf9e294f25a682e92fe - arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c +fb0128ee719cdbc40fa546319e2635e3e19f1e11 - arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h +3d43facf8bc958241dcaddfa4cd6f9e61362c87e - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h +95875d234df9d7f7a86bfda389367f298611eb38 - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S +755906af584459bc7964059a3022e624d4743b62 - arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h +12c0bb5878f5671aeb4bc9ea733ddd80cdb960da - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h +7848197b715dc7fd355b6bc2d2232123facb9994 - arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h +2bd6a37616bcda8ee48aa9917c65801ceeea804e - arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h +89bb4015a4309bd60ed5dc2f32033dd0a4f603cc - arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h +6bf419a65264c179e6faecb78b2c7f31faccfa6d - arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c +94708cfb8fd54fdc9e58c01699e1e9e8c26341e5 - arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c +02f0daaeeb8c59d391a631dd2f7624e598748e99 - arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c +f6cbc785839b2fde5bb8c3d87190641b45997d2b - arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c +343bb93fce6c58d4c3497e7f662303320ea1ac83 - arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c +1e5bead24560b23256aa9e306e5a4ece724bd6af - arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S +79002203788efcbfc1db666914278df3cae585a4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h +71ca46ab2b7ecd281fc67a339d97f4e58be53669 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h +b4f867a53f8b97e3d04d472c2edbbcadc2c85240 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c +c925ae2549008a58fda62b34de221dd620c70d96 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c +5785dfb24000631b8d3ec2c8363f0de46908d763 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c +dace58b25824fbc880b58670389d47358981547f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h +e37292ff38e07fc925308e8d725c49e48fa0a085 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h +fb86370251784e4a48a2bfe74baf2d7c56f3701b - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h +98090ad034ce904969ba1583467f8e5ef565d2d8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c +17199f9bb411ca8735cf2bc4b22e8baa7bc2d152 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c +4168e0d14bbe98c0b575d2e572fdb4b73586f8c7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h +d83f926ab5ef0f16323281a34f12b358f3af50be - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h +b6ba63645f7269f8d27b087a36b742340630864b - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c +b1174b8477d0e126d9a35147161079391bf09ab0 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h +79890abe09ae9210d94ce3c0f27c8e1d61ed6fae - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c +e1b4cce4c465228019f6128073e4634dce0d2986 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h +cb6cde28e9dcb269b456216c0e1b8d55c8ea996f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c +f70563982bec81cd15b17e693da41e7d1f469c6d - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h +31705f56afab7b0bfb866eaec7cd621c05f6004e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h +1616d5f796bb92042ec501e01ff39403df39936e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c +f8540b0d0f9d75dd733f6683d68945b2408cb0be - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h +670e89ed3e54a8fcab5f9bdc69b0710229d556a7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h +c4e2a5509c4bbef64807d58ddfea984f66031f26 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c +368d6d264c555843d3708e20700f8851e215df63 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c +73a75da66496e41636460ff121095c03a41ba9a7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h +77b795f3ba595013340ed1473935df13b18992f0 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c +3940dbadf2f6737dbe71207e2be2245fc24a2cf8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c +79676f45e5439628bef50912dcfdb60c2ab34e8a - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c +9aafb1c8544431a32f3d664beca24b47d9489f1f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h +b24e7e4ca2cd9b25fdbad93fed94631f347b78f8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c +1c5969bf63da110696877497bf7bb035238af2c3 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h +33b92edafecacba8aed5f6b12c0b051740d4aa8e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c +445db7752ab6359cd4ddfebded67f1dc59603220 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h +f438fe8befd240fc23c7cc48c7e77e1e1a3cc0c8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c +c5542e49f5d3326418606d161d9490c9dc3c7bcf - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h +6ef0f4493d19b357c77df1b5cd49696a5263d102 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c +28a7ecc5d35653b1b3e42ad19c1d1526f8b4ba13 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c +416b58dbb44fb50ec9cbdda2b4af6cc04bd48d20 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h +a2ab35d6915d2ac73d85c1068d973a0d3514da41 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h +d655b93e0b18efc8d5ac80ceae4a282c70d79c8a - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h +3e3b62df98d3d83eb2016c9d8dd1f67a641e95e4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h +c997c26d9a441b3b550fa191f122a33d669d38b4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c +618680bf1155ee1bdf7f67df15cfeefeded70e66 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h +0a4ed6a9c901c1bc5b75371aa26917fe6d9b243e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h +c13822b4c2268325ef4398fbd0d28eacdfb59602 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c +1e9fb5aa9c1bd6bfedf0be53b9f529290a141a9e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h +709be723f3bb2b8be34dabc19ffec007a928b060 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h +1209a457ffc9d4ceeebf3f3e24300146fecbd276 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h +2516c5016c27a7706bfb86cea698a6741d845eef - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c +d21496a22308580c07df11ebe7adf41f274bfd59 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h +73de5db2e94313670371f83a648fe95de097e7f7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h +85497a05edddd868fbe7322a3621d2b7c88c9814 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c +e3e6596065738a8b19bfde088f92c7a4bf51b851 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h +a3456911635f8af4f989688a8a1ae80de5256fb3 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c +c24f82eb4ee80d7945922eac27dac514db2a49ac - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c +98f55522313c18575ac3b999f71ef98dd128d004 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h +6b5af500b6156d7283e6f315ae2fd1c33e95eeab - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c +872b3910dfca5bff8749f70e72fba760cf6289c7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c +49758ae69918fd8c1b52c54bc298f1f3e80fe1b9 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c +cd5607156fa9256dbf860561db48d3e74c800295 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h +1a8e74d1db7ceb847a8217c94620d6a73c28e8ba - arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c +35dc8ecb34f8b16c7fc40797709568394bfa2700 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h +d923270912bbaad8959a73f39f933db6c98a49ce - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h +1244ea062e485744ad8d59bf66ba3a455bec7f13 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h +4b7558ac17d450a33285d28478f8d8596edbb1b5 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S +97ba7557af145fe931feafea204357431b957299 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h +5fdb5614708d12a66d8b58741f2e38c49b7690aa - arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h +af49cf4a43c7cf77fcfa20fe09d7197390bf3969 - arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h +cfc60d518acd24b2043bf29a48105110ad3068aa - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h +de6346b18cb5bf3c6727a99f6cc0d9a62be9f071 - arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h +9ba9b4651c7e04ead5846597f6564fab10d8de4a - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h +e1863524c093ea2e6d043b9f6c7dc1e219f08467 - arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c +0aaf3b723ed86200d3e2c0e83641074ae213c44c - arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c +653b82370d0b1ad6cebef8b6d7072051e934caa0 - arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c +5d84153e66efa37728948b5b1fe281913f5ea657 - arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c +5c6677206ac7ea4573dbb96868e106a55445d4f9 - arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c +4a2ec93e8013a56c39ca18d0e283fc9cccb43b1c - arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S +9d5ed44c58a8c942270d1e8cd54ff65f463b2336 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h +71ca46ab2b7ecd281fc67a339d97f4e58be53669 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h +b4f867a53f8b97e3d04d472c2edbbcadc2c85240 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c +1b68266c3c155960dc03cba027a4d430c74473bf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c +cb930a7db51e4c8871ab7fcfa242466c2a8b36df - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h +f7c1784f7532b244fe2bbca846d710d03061bed6 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h +45377afc42584fa85f873fca2cd0e157c1a16b37 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h +f5cfe3883759a648f72458b1bd84bf01d3bb1657 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c +9b42c233c5ba1e6b8a384b28424da455c27a53a6 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c +89fce0253e363a84cec3e3957ac8d951a80ebe74 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h +31d2ee83370c6c53704ab1a6ef9b905297491333 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h +f1eb5fa4f4de22b769d0667ea9bea00613216cf9 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c +6710f6e1dfa15b331f9d813a5003b5198af81c04 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h +0652a5c416f4dd969f772d9774e55501993af032 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c +a84fa1ee247e2005166d9018df2bcc75e63deaab - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h +51222b809151abb01db2556abfba262c93f7f0e1 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c +b434a3c4454f2c705b0f3b7c565d85e147e7a7dc - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h +cc63207972ae473d6a68bc41f3aa23093730183f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c +d42c9ba8c699033bed7f64376149e25aaf0ba27b - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h +2dd99ac3ceb6063e89c9c016bf2e965abd2636c0 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h +30341bebf59f92502ed0e0f772ffd6ff3f4691aa - arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c +f8540b0d0f9d75dd733f6683d68945b2408cb0be - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h +6158a4631af76550355215276ddfb61772f11c91 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h +c42e69a4b160aed3d646987f867de63fd6542f09 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c +368d6d264c555843d3708e20700f8851e215df63 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c +73a75da66496e41636460ff121095c03a41ba9a7 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h +965dec0900511bac7618f812c33f95620e3b1068 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c +0d3626281b65260b4b2e49cac33cf6bece32999f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c +9fc0480b22dccdbb2dad940666ba124a785ed285 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c +6c9c6446695fbbb9ef086f4f783aae57f24ff6af - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h +b2f984f7c8707ce9470fc25ae8af0f7a041f1602 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c +26edcaa081665198f705a5d6e4a606c0b4e00689 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h +4b3e251e2f0c0e4796105e6d25927067e14a2a6f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c +aa2819aa55d76d63f05809805f6ebf6f84fb8f71 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h +9858935fcdc71e5145d69b0d6b65410dfc4c6dd0 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c +bb750dd896f8785a87ba62867b0e862dbb4199c2 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c +dd32e9eb6d0e8f5083df2bf5abfe28fcaf6f2c5c - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h +0f8fcf83ec923d192f61376370dd90635259a378 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h +e3a261adfa46ae2657a455b7d25b7af56bb62a37 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h +1f598d0b85f3b211c05adb41726664e4a2bbddc5 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h +1637cf9d86b35aef31283240a30095022c0476cf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c +c7e5e4cde0a05fa756e3fc6cd32654be3343cecb - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h +e5e46ff7c9820b84c61e6bf2afdad854e42c6985 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h +9bd59c04a5dabacf5a9ce010eefebd393e814115 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c +905a72478cd919c732be2d3f3c066d27f34b489e - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h +9479c40f7955d1b8da21fece7877b3f970886a62 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h +a65ccd601ba3861f13ec19d1ec6cc79d4295961d - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h +ab677ba0b11817e784f6008456b3501b7438cfbf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c +ec2b85d104ef0ad52faf88881e864e93c37e0ffa - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h +d2d41012d692a8857c6f842bcf2eb065142a90c2 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h +ca56b6a499c7e44f09c1f020859f9e7d51b014a3 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c +067d8c516f8ce37edb7c8228d9d7fc4ba15ad7ed - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h +1e038ef0b716c1ba013366f2d656026ff4bacd71 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c +345b11fdc0c85e312ed8e6a8643339d691fadf6f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c +b656247e4733dfab4d7db4f7361cd1b15a0c14bf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h +8a1fe395632b1a162c7b9e75d46be042d64f5230 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c +eefb0e4293a309d3eae668a9f4fff6b9d45d3597 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c +fa7a5c1599cac3c19ca4cd64215b1938313806c5 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c +319ec69ebc8189c0b9500805069cb9eab1288242 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h +7494ace1b19166bbf26931bbcce0c574629ee2ab - arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c +a0c85124251b9cdae75734966ce95891397ca477 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h +a6ce0baf4ebd3c81556e0945c2649f2efae6c879 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h +c080e0d9285c2d3fd252d1b5d80f857f7b5f7ca5 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h +166890efce4ba83ab0783f4b56821c8576731a31 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S +5a59b5db38b291cdbebf71aa758859f99c35a751 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h +5fdb5614708d12a66d8b58741f2e38c49b7690aa - arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h +af49cf4a43c7cf77fcfa20fe09d7197390bf3969 - arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h +cfc60d518acd24b2043bf29a48105110ad3068aa - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h +555f92b188335e740adcafa8f411f751f8aa9102 - arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h +d3155938568a3ee3a31e1df08de79e5bf68dc877 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h +98b250fb48fc293e489948124f342093ba6dd423 - arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c +5317d798df3fa15f8fa7b2c33ba670b0a1ecfe42 - arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c +02f0daaeeb8c59d391a631dd2f7624e598748e99 - arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c +e30b233c6a0d10cb0d058f63a7d68bced2033d08 - arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c +e55a87f7c47f362fafe9a61204603c0aacd71ab9 - arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c +2c9ea17eea925548d393c14f7f51d8bc2fbccdcf - arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S +1e1932554b5dee8b5c9f6e42584b440f694fe206 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h +60b16e786121e9076be12c5a78ec91c7e33801be - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h +8fdeee52467e248a082f45d92512e951f2611360 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c +d2b7ae5854f6cb1abfe5c55f52385c86fe6752f0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c +f0e1185e7fac539c5d2edbf5893678d2ca131f70 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h +9114133093483da052525a109b5ca5242a14cdc7 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h +0bf3be2cc82c84d28437a838ec18ee32b52448a2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c +982ba0c3e5b8772dbcb65fe9ec04f07cd66c03e3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h +3880fbedb01ad739666ead858ff32c11692d7ab0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c +8836e6535eaf80d79c28bc7e61f796c61f019c9a - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h +26687de903046dca0b5e9750e8a59b9355a29ec0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c +514a984bcec8f805fbc3fc8b0213b8603009b717 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h +97a67051462aa2dc020abb4c615ec1b8d55798dc - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c +acd408521525ea61a78ab71ab790b33f6c8835a5 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h +68d0d1df925010bde7b53a36dd82ab05a0cc23dc - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h +680305a5142d3cda1b9ccc1bba0d1ca8dbf42b0e - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h +63bd27946e361d2e05b681e47abfc894e0b23e88 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c +3de0a5c82b6c6679381b6c8887a23b11e1ee49e5 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c +391c8bd0413603fab7961273368ae142ef2e605d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h +0950b022f226cf400c633b938956424ef62156a9 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c +b5dccfb4fbab4600a1576c8b74b6e2062cd13c6c - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c +63d1221a97ab18b30010ef6dd666592c84488052 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h +2f14e2189e22b58a7f814523923a82b761565793 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c +a6cfe8969863b9001520ec912315467a2b1213e8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c +c493de6825dedbe205476271578675f186aad0a2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h +5ff4457e67f619c9e7562f12b5fd4772a6d34ada - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c +1b4a0d65fcaaccb28afc897aef9a76972b99b9f2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h +c6cd4eccdc73fc94fe1d36f9c0d24adf82f6b762 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c +85a883d9102bcbda2f8b172b3428fa270a259858 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h +8e4cded7b48b70c4d63171d01619ea77582a15d8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c +6afbc58701e19d1e4b949615eca0a6fee5c0eec7 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c +9842a9ba9c2a948191518a1dcac7efa316141dd3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h +714e06306174609b86f6dfecb362e5d307815984 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h +23822f16c7741b8a82e6c1b2bf37723c9b661d23 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h +ff8ca308a59e802f869d16233f792ae0e6d19a52 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h +be59b0efd4cc9ca4eb6570a3a2fe1d3f0f812fc6 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c +c3913ece4d63b48d8aaa43aaaa4f7c5927073b30 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h +6fad70943b4e7bc9042ec608eca4905531b622d8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h +ed2f1e43ce8ff9065b95a274256a78d34d08b184 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c +2915d56fef4019217f23aeab0ebcf0ff98b2818d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h +302fea6e0fc2351dbc6ccda1ed9190941f2c0250 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h +d252e68c77c34429d934422da1ce46e64553c23d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h +b196a520bf04181913710fa0ad6c7e98df814be6 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c +8d4291524d054f1b355580fb4254843ee94015f3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h +0c0e64bb4e502f8b06cddf4f5701a2004dae88bb - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h +ec1e10ba1585046d426fcca0c8d6a0452015786a - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h +27ef52baeedbc36413879fd421b276824b21ad58 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c +3b25bdf185a1377c793c31e212d50a0027fda91d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h +6dd95a8f29a4eb734a92736d768d92a35ce910f8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c +d7be908565309c39ef0e37d464011c7340c16d6d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c +6dea64a1dcb62407a4021b892e2da1cdc50af221 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h +3035aa1efec0b288548d3a91426946653dc24b80 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c +97b36bd56cf9603b43fd2acace9ae94457d14776 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c +1cd2b844b96d5646b2f021f2b7a50358af7908a1 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c +175403c002e2bae8b4b5f15356300cbbf3a37aac - arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h +a0e2a71a095891a57e56e7e285c8f94dc9d312be - arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c +35dc8ecb34f8b16c7fc40797709568394bfa2700 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h +85515b62d8aa7cf44ac7f0b5a705f9507bc7da21 - arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h +b7a9f887a8578d015d21dcfd1b009adab66f1f2b - arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h +d923270912bbaad8959a73f39f933db6c98a49ce - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h +80a7b771023f421a796b8da96a4d42a7672cb817 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h +4b7558ac17d450a33285d28478f8d8596edbb1b5 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S +567114b72dbc9398566aaf0389041fb7e12ecb12 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h +f3091cf7bfc468b69812a8ad31b9b5d768775e88 - arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h +c02f1fbfaf33a5bbf3351dff53710e6e70a59e74 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h +9d9e1a21208cd3b5491a40bacb421776e8c1b680 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h +e4b12c87945362986c13896e2349ab872d556c61 - arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h +9ba9b4651c7e04ead5846597f6564fab10d8de4a - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h +3b21be43300990b373aae5fc9fe86650293e6465 - arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h +ec2741df6c60880f2d8d7c157dcda59d0c50eacd - arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c +180bf4b2deb975b6753f7b845e0055ea91a2aa13 - arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c +6e7e984a8e5dfab7008759c759d8244470f3dae2 - arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c +e08f230adb59004c64e07444599554c275f1643a - arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h +455f78881f3e452bc906dd8e2dd74d7e668f33dd - arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c +2cfbd336aca6ffd917aac7811b326bc53c734d1c - arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c +91be000247752e30dfd222eef60029b13936f320 - arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S +fd14d1c817b69bd4a42046e3a208b999bffc7e36 - arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S +8150ca146a9314d5192e1e394975bb932029bd0b - arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h +e1247a97415e84032dab91e8daa6df51645413ac - arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S +07c3221b9d62d08349ed7bc9f4f1e779f524ec32 - arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h +d2d25cc01ae69fbf7368f681a6be32083570007e - arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h +8b0399819af138f97f2f4270408c66b5d23b6052 - arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h +d99874d76998c7025371fc6e19def1521bfacc2d - arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h +a0b63dda5b240d0c16799712543a79c70bd462d0 - arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h +e6926afd75dc641585601bff95a258034095c6e1 - arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c +bea1c249fdc7e365ba7e5d773a7e312de9345fb8 - arm-trusted-firmware/plat/qti/common/src/spmi_arb.c +ac89500a8d77a91b9b24a426b3394744bf74efb5 - arm-trusted-firmware/plat/qti/common/src/qti_topology.c +f12c8a79f6141094db1aac3d48ac6ea34800ff6d - arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c +7fc1d5b81ce41fbda7e5fda0ba2e22acdf4d5934 - arm-trusted-firmware/plat/qti/common/src/qti_pm.c +aeecda36338ac151632b50ce13795833a9f6ce3b - arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c +26a9cbddd8b9a236e5d0f3550807554e23563f18 - arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c +a78d1e23bb28b3815e1e4ed90be36d9a18730edc - arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c +825f74a7f38dc32847afc499110e74db3937935f - arm-trusted-firmware/plat/qti/common/src/qti_syscall.c +f3b7fa7c62db7248cf8b50316244b8239596f267 - arm-trusted-firmware/plat/qti/common/src/qti_rng.c +d3fde1360e9da45d7d4f06fa00208544d41ad202 - arm-trusted-firmware/plat/qti/common/src/qti_common.c +7547a5ef92ec4ac40eed5a73041ef25902042bf2 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S +b6ee5b136c1d386d21bdb0c3944363930ea1c5d2 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S +3d127b0f585eb4f2bfaaccd2f04f814fca7770c4 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S +35b43eea9fc4e1679a0349180b49fa1bb96e59b7 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S +b6f69f64118c04b6b54e760cf7005ec1594689fc - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S +a32c3f1d46d7c6cdcb2fa977d2899c8ff2bebb7a - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S +1d172cb4df58b173035b99b5855545b25fd764be - arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h +0b01452153b97f032c89b81698730bd0211ee4cf - arm-trusted-firmware/plat/qti/common/inc/qti_rng.h +2c7d5721030a2353cd649ad2cf4da49242ed3195 - arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h +a492ca7a1a6a0dc9b988c09a6838be72f3a00cc3 - arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h +af87d6c46e8e3304b92c90ed0111bb3066bac8e1 - arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h +f00660ee7d40d5826515fe5266e50d2172c12bc1 - arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h +3030765ef51687943e02ca761d6d518826a6c438 - arm-trusted-firmware/plat/qti/common/inc/qti_plat.h +5901fe33e7d63a4a03e1b95469b48c8299d178f6 - arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S +576c57f662c322a2eac3565e848ea0179d7290a1 - arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h +ce8e6c97e3af86cafccb6b9ffe857b9c1ec62598 - arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h +3591e68af17680a9c8b78bffb866c93838cc5b18 - arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h +0c6b7067545771534db6e2eae7bdf7694a939d12 - arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c +4e66aa575523181fefb5720d798a257e98a26003 - arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c +a28527a439c34c2ff37a3bd1ace46fb9ddb4f357 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h +5db76531814dda261416dc016b511d807c3a4ba5 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h +186065ea9c6a4a2d16c200d4d07466514f5a1c29 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h +3e4d34962a59227a5d8d494f35e80b77fdf8d61e - arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h +885aa0bbda57cb30366ac8f9ea09f3f8e7ad31da - arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h +4bbfc2267980533e77f9d529ab7d174d48d90403 - arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c +f1e4a10f906499fc859ce623d4571dc63e7d5273 - arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c +3c317104013baa1af66596ba8f1eef175f48843d - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c +3a9e2ef84999f167350febae7da7117e414fdaaf - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c +0701baf6d3a2c6d67485a189fa41e9c33fd20ca4 - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c +f28f931b63cba463d5ec189bc42550444729edad - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c +592af310a2153553607e67158a137e3b7d297c79 - arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h +c3fe6580aad543effa72713fb4d54e4fdcd7f76e - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h +2cbef8a830bfec6a533910d7a00ca01de32629c3 - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h +e61cd2fc029895773c3e7781028ff30b7d863cb7 - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h +a86635994a276adad357b7b9a9408af38860c61c - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h +fc798b0a8b41f3e6053be0d0669917e2a704807e - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h +659bce34ee85d1001adb313d9a639d66d3a89deb - arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c +a73994ba0863a0c9119b3e80c2f95fd3a67881de - arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c +98e7e0c1e8b661cfd05aacfbfc969aea710cf145 - arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c +b1605e3612529c3ef25860a30a92276b1762eff8 - arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c +23e53289a40f4fdd5705ffc560d18e9e3086e32e - arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c +0c8169624b733658b1eee7afa553ac38e2f2660d - arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c +cc4b0a911ae0f00cfc94310c6a9d60716e9a1064 - arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c +c93b1e05180647b1752b51838d7b935bf554e073 - arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c +ee464010f7478ad28450e239244175a97360cef4 - arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S +6a4cfd87ff051f635d35973a9d14d941e0dc377e - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c +46033ef6c11ee3af5452b7fdf9b90c20050c0be8 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c +23d9dff6e9c23385b4ccea7791e18d709f29f6d0 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c +30326906ea4956c9a459d8a32363b2ca3de50733 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c +dbb5c27c52afd2347aa5d78b423a051d694a5c1e - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c +41479908d06f853d367898b86dda07763652f4c7 - arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c +c9354b6d74c4a24fae2207b5b999882056d88e91 - arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h +4a2ceded30ce0c9be27082dc3e0a0f646e41c555 - arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c +5e8868245cddc9cd3bff4ded0c90d2f8b356920d - arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h +5c64677609f95ebafb78a49847ca9c07c1a3aa87 - arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h +c72a5bba918c6067f6a77a639c42bc477c71de2c - arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c +c02cf900011574561e4a40f32b4328ee9b4fc2dc - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h +55418579bc9725e40a61a81af232a46218f27291 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h +ffac73fe826ff46223b2ddaebd9e7206528dfe33 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h +3eb20b0d72778ce95cdd02e0732ff2485fdcbe49 - arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S +b117623bbdd5a56a0ff191770082cd80e5b860e4 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h +3886a4a113d64631d91373640cc1e9d6ad0f9de5 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h +987353d4fcf33b0589d816a77ed534bd4b0ee784 - arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h +90cc387dc45aa325c65a5f792054dbf87337d0c0 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h +04e0e1415877c38b1d5b29fd0db73a6ec1bbc63c - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h +f10900dcc55350c0601a0fcddce82a8d8faeb902 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h +def81ce5e821eeb00d79cf3474f11987dd6f1d5a - arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c +8b1c7bd1975b587b7b972a8471ba45698080074c - arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c +2f22a31fb6bf835c01bd19bb362bba1c8a3e4918 - arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c +66cbb2ab82f32d934dc4d303b958c70750303ca6 - arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c +70667783807950b851233233349f9cadef62b70d - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c +4f2d7ac1b88723a36765c17fe3b6b524622ee49d - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c +5a527e1803e29b659091fe8cf586adaf527a55dd - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c +05acb6f9fd3967467369875212f706741e9434c3 - arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h +db28b2738f48c2d2751af6dee5456298ec578706 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h +2a726cacb7d9a01adbb5c593a0bf7a6f0e9d2c18 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h +fbf4ab727479f904a0ae30ca600e339277fc9c11 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h +327e01f2a345b7d3b00f949c0785a60e4c03889f - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h +1e8b5a5e05d44ab9f8f3bcbdc873885fc49c39de - arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c +956551e3f043e449ce36fb1696d99d2ae5b925d3 - arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h +3d01d365783ad5b2ce0f76df72a4a10db3d9a10d - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c +8ba47e3eaf73ff3181e4874c764119b46c88baf2 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c +4597342fc7f0ad8d99af644fbdc636abdee5edd3 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c +e6ee29b4c786d6d279e82a4066d13703168bd28e - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c +b0c855a9e2b50bbe03f42d79ccd6a555853cfefa - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c +c2cd522ab9668274cd7bf26fde63e9dbc9a94f28 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c +7641a42485d020517c692c523a29fe5be4136651 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h +cc8a8d368611f86cdf1901163b06c0975be5ad93 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c +81037a214c1511f91f65b5793f9d5fc3668f3c79 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c +ed3d0d97c20ace9c41ddac5ef51f81f75d2e7d59 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c +78e0e7699170ceb53b16257c0ef0c15fe08ba4ea - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h +46decb1b646ffba87d49eb22447f8e56ed5e0d44 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h +08aec0d0be276f69ddac5a77363f59f1ef42d88b - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h +595bafd552b05d81a25e9916fe91779e18beddda - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c +d893793283c93ce6c488a51940c01574780f7333 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S +c55c5c502ca4117b327d32cc3fef8203d3c64731 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c +d1917ee3fc59b85d699e80636d7ddd7d4c99320d - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c +d5aef4c8d30794a496c1c3bd18d000991bbae988 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c +84d20d5a07d53e649a1b8d130f5d4fdf6ba8f65a - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c +ba0a312824b0782a438e265e86a6e9d7638032db - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c +6d0c46a965f769a08b399225be6c77aa18f3a773 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c +fa7909d4e0ccdeee6f0765cf68a95899ac8aec1f - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h +b3fb31a094585eeb27ecc82ba69416ca4d66b171 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c +0cdfadd153db5ee7d515adb01dd35d62e546226a - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c +ccebfe25a0f4bc54b5d08685ce74082118f713e4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c +99d5d980ae032fa2dfb6e9da5fe48dd600b2a896 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S +8cec2a63b748c24a5fab3c7c47f114b8147894c4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h +ee3f4b7a69c6c3dd475a88c55076077415fc76b7 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h +298abb9097e851023b914f09fe36c8cdaf367e22 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h +89808197706a2d7c9eedc24ca7666ded83f0e84a - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c +ec24a0077b010c615c5e3a083e901d444aae2f20 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c +bee19a74bce67a4d58e2f4deecb801e1a65bf631 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c +1ac68857bdb8a88c7770c006dfd2be48670a7011 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c +17ad1d9d60e3f6debc0329a42e28178fdd497e1f - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h +3b606d0fba33a0ea6729510a467dcb03e9750140 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c +c7611d91a504dd3fe52ee769f9fa2d4f469010a8 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c +0dd6e3b7ed73b5e77f6ebc89320058cde70900c2 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S +1cd4aab41ecfa796a41aecfc70e543cd82e2da72 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +106e68f73e09c8f51c620c0dd840b42ea6dbd67f - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c +d4052416878640cdb19e93edd44e4a7413289b6c - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c +5b9c61a07970be31ce559c1b2c78acc41d5223e3 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c +bf02f90c1795b9e26f314ab310c0ba4e389257e4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c +d96974438f18123824bf23413d2d0d75452fb4da - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h +326d37fa1c2f92a2e56baf3391479c3dd1365396 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c +4588d011d8dbc1073379954dcdfb1c437cf9d4ce - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c +cde1d7e2f8c3e1513d4828b37df69223bfb780be - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c +0a76eef9a0cb2d3c1fffc2a886eab6fdabb34997 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c +015badf34dbdf2955bc1dc9f4b22627bde8f9f9c - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S +34e8d1c4e060805a3f55969aabbd211dc6b08fbd - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h +34309aaec4559a7c2094873802490b96b9cf9dc1 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h +ce1df43aa2a9700b9c00f14be842646284b3ee3d - arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat +348ad39495b7209e9858421f7bd1a02f9712a410 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c +97542646c951833f68e49c013c2d309b885aab65 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c +bbb547cc93729fd63ae5da22480a94dc84ad6fbf - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c +7832f9e627bdeb224b72a22840b7b4cd3354b962 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c +9a23652352c01545d80c980df50b0d1965df8131 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c +c7104ef4a0ccb4a2ceb01951a0c8442349cf4ca7 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c +c97649b9bd33d9e7f4268f6ddc79d603a3a317f2 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c +ab066b0f80239a20f5613a9c2bf4862d9c02e2c2 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c +8617ceef396a9a7f9b5e9e1a4866cede187f6ba6 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c +6356a0b128a435ef5faa1bb6922a5fcc571926ea - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c +0c5a65d7362595eff6d472ba23ccde7af61d9ce8 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c +e531e11712693e6095f810484cb2f8332646c1dc - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c +e73b702494b764ebb0f546aae9de484a69c968f3 - arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S +d25c56f572cf7b3618f7567d502c1ee11dec2bae - arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c +8d9b8ebe2f8407dfc849bee6942b55d0a9c76d41 - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c +58fc3b165ee7a61397eef3e9f2065858876ce9de - arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S +4d04fd613146842b18904061da84f5958c44b16b - arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c +fb218e655fd6a3d77f969fce9cd6cb5dd0a6c5b2 - arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c +2a6016cc527d04ca332373c0d14542d5176aebf8 - arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c +0f53c08fb6e10d933fd28d9f021ccfb0e48212fe - arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c +4dbec584881036aa37e59b66185d958a695a455d - arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c +6f1dca2fba8be7758cfe4395226b2e4be820e3f1 - arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c +bbc86d9dee6c505651fa862133b686ea1e1af43e - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c +ecf2d932f335bc64d226c7d6502806590af552b6 - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c +91900a1e10f18554bc4c6b9f13d0e247da31062d - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h +458bed9c52c48caaa9c30822f0d20359e56e044f - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h +e8e7dbe2842bffabc62ef459d5f4b037b5fc122a - arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h +949736009adf4b730b592ef786e3d66eaf769d8c - arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S +61343b0647173b58eec236e5f6781f95ee64f5d2 - arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h +11b45c0f4e3d96795a403b588930c354305a52d1 - arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h +b76d085fd8bf62b29b2651fb2baafb167bbb3f37 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h +2aec61855e1e16a88683b573ae88e337484a01cb - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h +21b9ecfaf14f5a5aed16e18cf1643f78e890a096 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h +624f3a27eab52b8c97c1d391c9bf0aba2a48ff48 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h +2693485a6a4c24984696bab65e09494c4af953a6 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h +7eee98bf96c4e615e71244fad2270fe3ac7bca96 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h +b01b1d6699848ec430ef6c7ff1fa536c611ac8d8 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h +ecb6bb2512f5f946927baadc3238cacaf9e9c42f - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h +dd094069cb1a5bb53cf55c4e87b2364925c1e25c - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h +eccbd7dbdb2b149abd38a48ddd5f6b0f292373b7 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h +fa073698981deb8685410d390184a2fea2477d8d - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h +0005633528a5228ce544a5fe3fc8b984d26eff95 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h +97366374236e04da0a203c6df1ed7e93325e40f5 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h +d6acbb5f1eb851fbab413c7209bfba21509b4d31 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h +e4e77bfcd8d045ecce243b060298bf229cbf3941 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h +4aa146b81da8a061bda6540907c37d5ec6569962 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h +1ad3acb2c35dab529632e51cfd8a1977d0a3e495 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h +d99d1382679e0a53fedf1afb4781358524154b54 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h +0770b19832587bf494cdf6a16cf0af55ef4e3eba - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h +65dcb16996ba6f5480b25b088c00618a8401e2b0 - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h +249831518e8554837fb8750d200cb4b786c2d683 - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h +412a883e42794de7909b0a3076864c06874a0764 - arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h +68ec103aabc7cf1ba96e9f802589f232bf63e8fb - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h +80ba76cba14e63964ee35830536886c24581020c - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h +00ba4a09814b790749853248a68f57c1bf5d8a77 - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h +fc8ce0bab3e269ab289babbc37c5ffea6c1105c1 - arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h +fbecdf95d5fb90503336b712a6955a36a635aac0 - arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c +d9c373f0351531965e8097178bbc13ede3af7485 - arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c +ffd1e457886f1089d9c344f701ec17dc97f8f074 - arm-trusted-firmware/plat/renesas/common/rcar_common.c +716e1c7c79baa403b9c5d0ef120f23d8cac8e802 - arm-trusted-firmware/plat/renesas/common/plat_pm.c +514484b073de3f03a0c25885d1947529d0863273 - arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c +ea086669ab75f559b2e65b291fea3af158c18bd2 - arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c +ae71ad3a55f0e9c013697f9775e6c12c0ff7bd74 - arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c +d414d4d769295e5a493cf3e77c9c51626ee0e6fb - arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c +12b42e58567a9ecd3d1d63318cb5ec7011a41573 - arm-trusted-firmware/plat/renesas/common/plat_storage.c +a977937122b0a3096d2974c21e1d01713d54ef5b - arm-trusted-firmware/plat/renesas/common/plat_topology.c +5f9406be82d4cf619e442556228de3e2d1283e39 - arm-trusted-firmware/plat/renesas/common/plat_image_load.c +9e2b414041c35052396135ebdc28539af32c2593 - arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c +3c4b66c3e0e2ea740399f2ac87b9c61af5c45031 - arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c +2b4770445484da2ea7c1061c5e772905f5f9eda9 - arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S +f99514b828a7a7fe6f0063a291c023d74a2c9bd2 - arm-trusted-firmware/plat/renesas/common/include/rcar_def.h +72226e12e556432cb547181aa73e0d55c5c8777f - arm-trusted-firmware/plat/renesas/common/include/plat_macros.S +2f021b7dce5115d413267052dd5b471ceff900cf - arm-trusted-firmware/plat/renesas/common/include/rcar_private.h +aa601d2e26e65cab57efac1579ef07d5a4966f23 - arm-trusted-firmware/plat/renesas/common/include/rcar_version.h +939b904cc911a51e5bfd33fc817d5c5b22e55400 - arm-trusted-firmware/plat/renesas/common/include/platform_def.h +f4aa97332efbbc8e20e48e338443fd3b9c208830 - arm-trusted-firmware/plat/renesas/common/include/plat.ld.S +64ef91e2bf3528ac94c8eb79c5c3f80113257721 - arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h +f5943232ea7fe8a4717cdaa5d1f371ec634c8074 - arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h +f773e9cbe28c8c27bd7013b66cd612cd63f790fc - arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h +954d720bbb952517040ea8c1648e94dcd01de552 - arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c +65b77a7dbb8e28f892af2bf3b76eff17c87a9cbd - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h +147f2e7e737cb6a5eb1dd98a0deed8c0462d2041 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c +a1f884a99e9e14ac83551e73429b0cf7a2c5aa0d - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c +2311f962795291fdd649a3acb3d3fcee85e19d11 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h +60baba93a9e38f989d8f3fdfb045849d1edc2d69 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c +79f7407103c1059afb212382689fff9c6a4f4350 - arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c +6ea11f2ef3d7978e714cdf621aeb7c8719c7edf3 - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c +e8797c2639ec349e76fc1946c984275c010e4cc0 - arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c +2c689ed8bfb3abf1dc9ea37ffaa8aa9479649eac - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c +c785e8c07a0fa5d01b9ecf8eee873f7a18697e3a - arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c +5f97ccaef3ab26b2710ad26fb0fdbd9facfd0b7d - arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c +59510c739cc2d9619a9a5c21e1cbf1bb05094867 - arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c +69ee13cde36accbde0f355f89f9cc2b5d1aa2cb9 - arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c +9fa0f4b8209945eb39ccee90bcc305efbe10f211 - arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c +c6e2fab47d050265fe94d5ce57fd1a3a684da2c9 - arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c +db23baf6374a79472a4b930f1fd68144d4f314a1 - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c +0ff28a152c1c0997120e1e3a5fe654f1ae19ac60 - arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c +1a879218f61e83b5068e40a2b093fdb4ab851a4d - arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c +ea896d0f1d011e14c4411020d73d083c22eac783 - arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c +daa5b1a54bfa63c73acf8429940662cd450f1eb9 - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c +a71cc21b90eb5b1d29b125e9c98c3e50f9a145bc - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S +0842c4cae12a7c22367b83357a2c824d060dee67 - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c +872e517062b5b548f6de42424dfb8290309f6773 - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h +5cecfb1042c66b79c4c4c9bc5961fd91b34c880f - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h +44573513efade3da9aa2ca94c3d4069a8af646fd - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h +0bb02e303d4c696fe34379bc2d5dd9f2fe16229d - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c +56e5fda520a793a37c7e8daa1ecfe2354b26e99e - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c +42d2fb2461687118d1f9e79ed2ae2a274cc91c45 - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h +d00c0cf869839d6cd370b5b6c58e8d066705e2e1 - arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c +40c2d9f804ed183a8befa38d61bdd2164d711b34 - arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c +344f94187e37e08b2f532eb66281e7e28e7702c5 - arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c +f1d76afaec515fb65236190a9aced6e0ae2b4d8b - arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c +4e66aa51fabafab21b8e01fa4f3d49fc8fe6a97e - arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c +f0aaac82be8c1b465622b1b82d8514de62c2e937 - arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c +a8ca841fb42e9bb5a9c071732f25138003b82d96 - arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c +1b64a7198143a5ec5cbe075762bfc0f47e7eded0 - arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c +6a97369a4a693cf002e5f5f6ece32516e5978068 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c +80f0ae31f4c2b57b330b01be44b293f6aa2cef72 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S +965bc32da1f0ff9aa830bcede48eaca19cbe3b29 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S +12bd9050e1d74b888a3866cf8ff79d17103fd0f2 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S +6c89be0e3e7e102687ce8d216227785edce4db33 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h +0e8b8f431e24f28a92fcd4fb9d46eb87a1113db4 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h +71cc1316bcad08255d76ad0ad858f47d681be60d - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h +58c7ff47a2230af870313a655dcab4f22dd64957 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h +61ab3a7cf4de99459f74b40ee4aa7c4c063f92ab - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h +6a269296c2d98fb8f6f4c1736696c4e6081cbc88 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h +2cecd73b6df5a49196420939a6810672640ce165 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h +716620282caf3210c15f6795e996035311a8ddd8 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c +8f4af50a0df849dd31970be55e943ee4302b0472 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c +9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h +f1c6500edd19c1540f562c4ea2dba8443a7cd419 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c +4d33d263a3f05c3d8f3400a45afc2dd7f1792669 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c +7bdf0ea1da45eaab8f21dca700b29582ccc57d0a - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c +266ed9c2a714504a190f6bdd10db0d40815a428a - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c +3f6403fd39850e34f4c3bd674ccf8170f74af43d - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c +bc3edb20ef2a7baebacce2c631f800cb6d206bbc - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c +f1e7a83b618d37eb2df8dcc4cff814b934a4ab74 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c +c96d4c2fac061ca1e3be3600ee8748de11d20ed0 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c +4f7afd096359c9aad1f7852029a643db033fe7c7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c +01f390bd22a88039e1fc5f2d062ca126dae34478 - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c +4b2131b48e6b858b49e7e4d819172c5bc729f213 - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c +919f5232edc5f6c3ec1670dedf5bf25fbb59356f - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S +97ae958df0c9d8f54ff36a7803fe0ba27434e45c - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h +9acdf9fa5a506b13c376584f49b42a4f437af6c5 - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c +392f1834ac5b4679e9ae724c7cf1f3a20c0e566a - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c +cc11d9f29f29d9c9366f3e6c66183d38e3031ab7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c +f83bec0cc962f915447a4582455414387713f7ac - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h +86c5d3b710ba9b63aaf82c0f9dc1606c22176f45 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S +9fe71c8db281a9fc253c959e2bf8d7ed5b59f658 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h +0f1625972d53fdedca61514318bdfd1ca806ac51 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h +3145664e80460f27bc2fd8cda127e916e518678f - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h +eb840b0d5bb6e8cbd42b1ab32b72baec165926e7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h +29b7013d6e080d93a60b3780f10310e29aaa6bbb - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c +04e2455b39d088cb56ccb73dac9c842fb6f6b7eb - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S +8d8ccf9d72fb421744052b95f2dc698844542a67 - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S +29e2e91f84a20d0c2f220e0eba6c447909e5aab4 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h +e26cc9cf2cffd853101d24b0e6cade82ff5f5cbe - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c +8211399dfbf7994faafa28d85d5d232265c000fe - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c +99aea1bcabb4f6d0d7452ad42116629d21bb2b61 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h +9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h +027eab15e763f75779fca4721b6612e1cef0f74a - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c +c0c43ed673f4f38bd78a3d145c4ff0f553bf3032 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c +80de920eee6f0214b1cfb2cf104cd6d295bb478b - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h +b79710e67347483f51ba3aa8fcb25a7f7dbb5083 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h +a3184b54f314a3880b11bd80e9ace2a825e4e251 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c +e0382b98cbf2ae3613453ec924646d5af8b1f11e - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c +9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h +586996360a2bcce38bf90fa0b1b7a20a45c6e26b - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c +25524fffee705cfc27dd670e05523c5de9ef0ed6 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c +c7d9738b5d030b72c12bb9649d2dfb58e180b5b8 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h +8eca9aa01df9af91fe07386e941d7557eae7d0ce - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c +eecb4e28621a6ea2bbe58371406ef5f58590424c - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c +0b8ef1037611c38ba89966b1da4ef153e47b4fb4 - arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h +524ab6d6a8a79e76857af71a8c36886929a16243 - arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c +22974ca90d72fb96f260417ace863c692dad5cdc - arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c +cb622b7fdee1e5387ed783d371b6cfdd0400df92 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h +edac1a959247a82db5f820097a9f8ded6c4665b4 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c +7a2d810a3f11780033972a9b1f3f2eb09adddfc5 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin +a4fe0b238351912e5a3b7e1de16ea4b470dbcfe0 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h +985e72c79b58499d32fbf6ef6f46a741c6356e9d - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h +859692a896bf24f76093c6cc1a923f3bd7f06c49 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c +0ea97dd2ed72ec48826e4668463b1067b1e3e91a - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S +0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h +5817c26932930a69f20037fcfd33b6f700e518a0 - arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h +c03dbe37ab69ed71bbbc9100b47ff77d3c1f19e9 - arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S +9213c21ad6f4d071ef85303d7f16f295b02bc212 - arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c +85d08d7cf74717daed56a0770f3c79bca90280dc - arm-trusted-firmware/plat/rockchip/common/plat_pm.c +4761873c26add12f8bff6e22a79c209ce1923023 - arm-trusted-firmware/plat/rockchip/common/params_setup.c +32f9de1c486103a42cf6a9d291f42989b42a98e4 - arm-trusted-firmware/plat/rockchip/common/plat_topology.c +1f63c15382d48351f3d1c1709e7428545ce2cb72 - arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c +3bb10820f3cac4793d72ccd0dbaa9513b9945d80 - arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c +4a1355d1645ef943a89aa54999041bd5a970c764 - arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c +91be87581dcd25681be045b39eb7934ec59a6fa9 - arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c +d30876af46d1b3b1d2c18f43fa7894f8fda3c5f8 - arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c +258f177b9b9412883f714cff3406818288eca04f - arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S +47fca1d947e59a046afce81911f7f552c72c6ab5 - arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c +aceb5792fbe22f18f421f2a754469db4f6f62cac - arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S +e40967392bea64496e752401f887b55eae946bf3 - arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h +5c96dda447934109fef22dbfc20108fea56100fe - arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c +5b690165e56aee2f4e71841059154598362ce876 - arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h +5c6218088ea95aa4cdcffbabdfabcf2054405b9a - arm-trusted-firmware/plat/rockchip/common/include/plat_private.h +2360baef8c09eed0a7d7ca2b2f97f9405c9bfd92 - arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S +c08e0dba86277197d207590daf335b7a863f4f32 - arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h +e0b9109d2e15ba78290c67b35d231cc82990137e - arm-trusted-firmware/plat/rockchip/common/include/plat_params.h +ba0fb41c4b6e827fc3092feb1e41d096daa7e77c - arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S +505eeb07bdc39ad3e19a4f6676774af764d3c300 - arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c +63a3ba51a470fe12e6026880ee67d6de178f8590 - arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S +23b124a5b49de1ae84aecc76669a8e76f9579f93 - arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h +4db0b70aecaf5352c4deda76075a44c7ed772f91 - arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S +ef5a8ce281d95041b91f8f165ef782642d022de2 - arm-trusted-firmware/plat/rockchip/px30/px30_def.h +6fd13eff5a2d17a6f2e651b3eba6211a93d3522f - arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c +288f8f52c9a5423576d1fd403f776da8e5906395 - arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c +dbc0dd67905cb60b55ff82d4f1d8bf96a7ec2514 - arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h +7129bd0759914b2bdbe0af12743e79277b990a3d - arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h +e5df7e7476f59e23d9c3c1097c64bad93fb273ca - arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c +6940e4242af969ec608caab6d93dd03364b78580 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h +338871ee4d601414cf6ab0c718cb19938c37c7b5 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c +4661321c301694bb1cfb029693c60d50387885d6 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S +4abb3f49d90cc7242ff9d366432f9423ed190c44 - arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h +8b1c4b26a5cf109ec97a2bd711e46dc76c20891c - arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h +be822c3b60a3f8f4215925d9c6aa8ff3d90ab56b - arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S +80988c6b4c1d5c128f556b4704d2a13dca1b94ac - arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c +07fcff2e4785739f2818730be2df2798395d6dd0 - arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h +f10fc723b4f781fa92f52d189e12ab2599f2be33 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c +d6f6a92953b02dda92949d05699b4a8c09ec1ab6 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h +81bb90565c30ebb1d2a2074e665099c5df4b3f16 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c +912b3ac53149ee0912cdc571503cbe6f5d9e5e31 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h +1a0ef7b5013eea98c8892cc73f9acf7aadc6542b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c +cc96ce897ce3dfd398d571f73d60df020e312a7f - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h +fde45271c5e9a03975a13a19aa58f7ce1627247b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c +d4edbc276d8a41ceabeabd135ee44750077267fb - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h +91fa17de464bf17060f5d782d3addc2d250f2bcf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h +341cf7780e76c0eed9bb587ced84821148eaeba4 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c +455f3ca45423a7d3a17a25fa9a199ee6f33accdf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c +8bb28c62f323cba1149703071fa6c9cd723e7681 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h +2f72933afb37b859ea9a98d233ab11f81301c9db - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile +98a096aced18ab4c9a4b3ab325773ed273acd4cd - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h +222366fd88fa37c34896b96be4724020febaf122 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h +3832f35bf0192ab6299ed6f72d97ea798c64ec01 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c +c651d2e10f915a285792aa7e66836e66a3fb3b68 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c +249a2bba707f4aae60e76e4d2ca07180426f3657 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c +9cfa6b80558dac90724c830c7c2b792099232962 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S +15ccafa1fb201c2bdc50eb32beb4d9331e95424b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c +34cef331645617d77f27ee050065b2678b021605 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h +12d0e498bcf7645b6d17eda0b6c88f9c68345720 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c +0e0164a1fd25ccd71404f643551fc197b6d3545f - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h +8af098c906ff4222b7fb1b8a8e528a842931e11a - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c +e4ba052fe71c1dbb0fd712a9e23751995fa17236 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin +1761d34cf2fa35e5eaf8e4707cde5f3fec7345ce - arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c +a203f9155033bc4a154799d63ebe669baadb7c82 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c +8080df60a96f3ccb59e64a8c4468c29298a40160 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c +fdf96b7b34ebbd88b6c053c20c493dfcd5d2eec6 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h +26f96f6bfc5d8cd2811341eaa144693019daa5cf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h +21c19d18b927a98e453d2dd32fa075e1556c8d10 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c +4f34aa4fe829a116338b7c8cb363091b98b1df1c - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S +735db5fedc39c83875dd50d345431e840a75ce95 - arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h +0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h +d037385198294976c392eaac15722c2bc43171e6 - arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h +33691c33d59c3cbf5321efb5e9cf1ce6f908b1b3 - arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S +e27f9ab0eb7cc700bac4af81ef063675ddea3d16 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h +f61d8134dfdbc2de01b130177e3623bfc96e582b - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h +514bb50a35bc277734414a501833d9cf9103b613 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h +a3ec096942a7038a658d2de2da28c8d7772e2601 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h +dffb716056a5cfe4289bde5769bacd0a9c517467 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h +37de06dae36b2c9133dfa3db58b9403eca97534e - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h +d3a8c566b07530d947493f642a829c2173e7eb3c - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h +9eb41f0b086d93dd52f10cd88c871e9f872da485 - arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h +aa37703bdb16d2d93c4cb6a1c3f5740f10400717 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c +888b9ca7b2dca798b061df341269bb1bf0cdc6a2 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h +75d3fb351c1418d28d1be951921dde7cac623d53 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h +d6fb6002e2f08bc736d1fbcfef5f7d518331e24a - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c +74e69a5d06c7c10f8fd04052bfd92c89a6b685c2 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S +d0cf327dcd15f8fc85f2c3c93e82fd6199973f0b - arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h +c03dbe37ab69ed71bbbc9100b47ff77d3c1f19e9 - arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S +524ab6d6a8a79e76857af71a8c36886929a16243 - arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c +7d9851bfe1b3a6bff1b3fe3a5a42152bdbbdd641 - arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h +408d92dc22d97bff7148a2338e91746328b4bb4f - arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c +00a800ecdcad577d80ed2968cfee8abc2ff260d0 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h +70ecc34e2c4236edbd52a088d6dc72300d1038e0 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h +90e4b5914845f3238bde4617bcf04acabfc52406 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c +53d9e3936b39e758560745d492d1473ac9c98278 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h +bcf5a24d5d284bc2b87c3b5299a9f548df4bc95f - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c +db1ef060ee221e9b61acbb781c42ed42e926b26e - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S +0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h +58f0ccc10fae70932566781c7c34457a239e027c - arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S +0a2a001f434d83ab306c453b6d60f886a0b59a96 - arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h +1321792bce42c44c3fed91fea86cceca52486ffa - arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h +a5a361643c76bc6ad4e5bf4bef498e6de89c4065 - arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c +4677f1e48833ef10dc9d9ed492dfe849c8466b05 - arm-trusted-firmware/plat/ti/k3/common/k3_console.c +170634ac25c995303394743ee26ab4f2265800ca - arm-trusted-firmware/plat/ti/k3/common/k3_topology.c +96d874b239805cfedc0fadfd9f07eed0e423a919 - arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S +55b3083cc472c5a3e1808d642b6c6516d19c34be - arm-trusted-firmware/plat/ti/k3/common/k3_psci.c +fd1bbe596ff44d2104431c2924e172d0ef4c5b34 - arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c +d3624f3dc097829d1b9f6b277bd1aebe77963d97 - arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c +27b2ba24623a62aa30daea138411571e17aeb579 - arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h +55f8380907084a69006d5211123aef60fc51400d - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h +3ebfed887a97b672cad608bc064e08075f4e2a29 - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h +e81feb55a2328c2ec32fadd561eaf24eb58ae202 - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c +da89ff4506058f3e90a127f4e7d79a7d86057bfd - arm-trusted-firmware/plat/ti/k3/include/plat_macros.S +015fe87701fa82cd48501c2915505c611e20e933 - arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h +33ec06e0674715932071745b37498c738414ee8f - arm-trusted-firmware/plat/ti/k3/include/platform_def.h +f2111ae0b834107dddf37cb4846a7065472db0fe - arm-trusted-firmware/plat/ti/k3/include/k3_console.h +c82ee96d8fb1841fd3068f489a697625a217aebe - arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h +85bfc710f2f6c79b7c0e025f6f6e653d16f39bb7 - arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h +3139c2b0c93ae17696224f59b5486f65e1649dc7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c +6a49ad3765ad1a5c42b66eea4f7aeed6c721fdc2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h +c0910ed9fa547ff95728b0592ee3be13b3615d98 - arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c +10b1e53e6d0c0b259d531d284d6b2f64978ff33d - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c +f171c1cd88d3ea2070a747ca519f7d6b9e8257f5 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c +743906eebddff48371349626564704fa54fcdd27 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S +dacc55b49253b5d86f120fe7e2ed1de0aaadadcc - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c +7b00ed042c247bac94b4766cb42dddc0e21764fc - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c +4ee1c481f43d2f2b9798ffc1f9c6cafa4d1cc371 - arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c +c7727e6a5eb36a39432103f9641b5d1c522fb1a7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h +77c94644e0ef95316e08e0a339fb16a856ae5d97 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c +9ad0a2f43f8a0c69c26073e06425579f59986e7b - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c +e53bc6a3ed66be157fcca494d961241c4a067815 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c +ec9fe0a8eec79fee1d3dd34bf1a969b8f0b93f4a - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c +82d557ad976b6dfd8dcdce69b68986e9be70cd5a - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S +0f0baced38fb65393cd300bdc024b68e707f5f4b - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c +b900c2f6ef836a0f77c00c851815a09220d8c5e3 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c +71c56ab2e235cc9495de74461f1e2035229c09c0 - arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c +d0b4272a97d261d88b6bff05bd2162e0d939ffbb - arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c +43753b990fdb953ffc38ef29474ef4af453444b7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c +3cdcc47dcc28c6e6de2c940df01b5c91d95af92c - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S +edb672bfa3c76059c60544793fb08658398cb3b2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h +58a5d9c283fcb21c6328e65dda44190d07fe6bb2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c +406790007d4d597b108faf9871360acfa7cdcf23 - arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c +89ab811529f632c51fa5e732be395bac1ea89887 - arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c +3b882920ab056c9bbc38be63b2715e1d796109c4 - arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h +34bda94b3b92d9b971e0e52f26c98293f35800df - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h +7eaf59b974175885a0dfccf0b42c774580444f92 - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h +d12872b893bf8db2b51b7243dd638bf34e9d6cfa - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h +6d6391c62306978263be31d559221680ed9b6025 - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h +0cbf680fead56b073a247b36589a06e814bf8995 - arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h +6a9fdf66f28b06f20ed4b08bed769e38d88e5995 - arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h +86477b53739886930268a20a1950ef8cb2a1c279 - arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c +ad3aca5d4f9af9d21c376f972399e2cbbb7102e8 - arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c +46faa99b227394b11051186b86a163d67c081adc - arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c +356f823bccc7081e026233c6fb511c0602208101 - arm-trusted-firmware/plat/st/common/usb_dfu.c +278442fbef0471df0addfc2b3ce1b10552541e65 - arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c +0d0e487dbff201564fae2a5f2e0bc45059a3ad3d - arm-trusted-firmware/plat/st/common/stm32mp_common.c +79d69f4be6d9e1fc494884f41f92bede1b67c8ff - arm-trusted-firmware/plat/st/common/stm32mp_dt.c +a0bc3acc4ac585d95f9023d8859733edb1ff9c9a - arm-trusted-firmware/plat/st/common/stm32mp_auth.c +7a33a3419c93c0bbb21a2c8df792965674477cbf - arm-trusted-firmware/plat/st/common/bl2_io_storage.c +b6a6f8374d7f3eadc9cd9b6ad93f62ed12f6851f - arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c +2a0d6172df32ead3a019d2cbc33e260c3aeba294 - arm-trusted-firmware/plat/st/common/include/stm32mp_common.h +a48402444da4bcb7bce60d2e3f9972f07bebc8a4 - arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h +8c442ea195baf9461f2165bae528286c5a71e7ca - arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h +b270dbb723f5c002dbf393eb752ccb946afc5baf - arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h +4ca9fb0296b649411cecd45263ecadb41540d6e4 - arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h +af93ef4188fb3950141bc4c2a6e971e965e5c071 - arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h +1125720a4a5573b7f8197d2dabdf308f51407896 - arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h +8bb1550cf77c8680e05ba46ad44ab77ff26bb8f3 - arm-trusted-firmware/plat/st/common/include/usb_dfu.h +dd7ae18098736e737a0482a59de65f64d5edd503 - arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h +08fffa1ca580eaca04a26cfc974edd901c2997b1 - arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c +667de698f76e8d0b6d6f1b85f8012f3bed27e925 - arm-trusted-firmware/plat/arm/common/arm_ccn.c +9b812991736d46b06d462799a31eb49ffae96260 - arm-trusted-firmware/plat/arm/common/arm_gicv2.c +c3c969f538ef3f3853d867a2c9c020723e5adc66 - arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c +1f2643d0dcc34c7b46895a5dd300de2674cc1274 - arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c +8d5a41b0cad025e83538d4508b8de54c96dd6be8 - arm-trusted-firmware/plat/arm/common/arm_pm.c +e460d7f371f1102e3c39114a43c606937f3c9f92 - arm-trusted-firmware/plat/arm/common/arm_common.c +9ac215f26148ab94b630463319c086d3e8b88c31 - arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c +e58481ddddf7e4632598a6ca543bfc9fcb6a7c48 - arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c +61b4b6215ec4cf4e050d7a14359bfdc2b64e2d8e - arm-trusted-firmware/plat/arm/common/arm_sip_svc.c +53d385569ada7ff06030853184930078d8a2e4d8 - arm-trusted-firmware/plat/arm/common/arm_cci.c +3b628c17fd98697338a0997a380df8a81c7d2e66 - arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c +bb20b499eb4fed681f076d21eeabaaf686b1c7fe - arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c +abdb20c16e5bae6df0e447b4a356eb5b9ed3eda0 - arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c +d2c7c17798553c8d4e29f9b1bcad9e2754c97e6d - arm-trusted-firmware/plat/arm/common/arm_err.c +5f8fb896e304dbb204531641566de21b2e53a426 - arm-trusted-firmware/plat/arm/common/arm_tzc400.c +842368bd1a44c1ece633a1254dc3cdaa4983c6ae - arm-trusted-firmware/plat/arm/common/arm_topology.c +f2f3b9e0893c37d6ecae1332b3df925e9ab4d30f - arm-trusted-firmware/plat/arm/common/arm_console.c +70afb2dd0a66c2a2b6eb5bfaf16df448d90e029d - arm-trusted-firmware/plat/arm/common/arm_io_storage.c +420e2c07ae07c6152cc914a3b464ec17f2f92843 - arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c +6e9da80beed8b267a6c15c88f8b25e81d8b7bda4 - arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c +845db666afafcf708e365edd5461d9071f72c738 - arm-trusted-firmware/plat/arm/common/arm_gicv3.c +dd2c481628c54d07d905a85f08e527943473d31b - arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c +d663fd87f45498acaee1a4325d0e44e561dd102a - arm-trusted-firmware/plat/arm/common/arm_image_load.c +6ee204b0e2a5012ad4dcef1cfe9fe884590bfb8c - arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c +1177013eddcf476b6a6d1f3367ae319363663450 - arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c +425d4b8c29564ce790babb9ea3fcc7ad80224fc6 - arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c +cc6a2551546758984d250e491c5c077149044f98 - arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S +8543903cea745c6c6709fd524622d3d5d3fd8df2 - arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c +17e3af5dfebbe4a8933589c7b3c67e14faa7dc12 - arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c +361186531a919bdc7825945fec639bf0db44800f - arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c +dce55e77a6a4b9da7a42be37f5bba717d0c353e0 - arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c +ac62b3ab6e132e1747dbd2ffd6f40a72b4270235 - arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c +a666a9d920e0637f17e51eff519cc94c115b1ef7 - arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c +fc971d9e587662fd23f35aa2dfbf0abf23c9da74 - arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c +3ddfbb8ae3448f315371d7a3a814bea1d055cd3a - arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c +cacda44b3716b65a5c30eedd17ed5a1335b8597b - arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c +43a64183c368a80bc24e370c93889989a49bfca3 - arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c +8c6171b381cfc6eca906ce2f7e2e6658895380ca - arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S +3237cf84bb44f0cc5b45b74d69d2934525543135 - arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c +5072fa161b5fff3742a05eb8b9def551087be013 - arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c +bf1abf676327ef4b5c2fbe971bf5c59f9eea2511 - arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c +6986ea7e2525388afa6171359d9f0c71de119e6e - arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c +fc6ffe0f853fbf9871294d23c034cf4eb00a0b99 - arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c +fb1634b97815fe2a2d9fcc807b394bdf1a034423 - arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c +408a01ed446d78cc578fa633ca47d7068ede3735 - arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c +6a32e8055bf1477d80b315a472542bc3c28106d5 - arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c +d55a2717a5f47927531e46527bd40fb912dd16f2 - arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S +883fce52c6e023b9718833ef01eff53d740f4b22 - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h +21772c91952bd2813284b444505fc85183bed867 - arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S +c9020cce76399dabf8d4bf04257761ee38ea4d60 - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h +6c95a3344c3a15036b1db884d62a972e802699ed - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h +00d4810ce12b4356434c80bbf98203811ee07a32 - arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts +5e82b47a941edb5ba37196b7aefe2a54e3bd2f81 - arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c +da446db6b40b974a31d66ba55f23047f28d3f748 - arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c +a12ad9fe2e578f1c9186976a41033a398307aba6 - arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c +5c168081100ace91d38be064d9d21551630d21c0 - arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c +c6341f0f666b8a901520e32310b18a323af9f925 - arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c +31824343e1235090b12b73c827b8cbf02ba4d0e4 - arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c +7a79c4c409726322831974860de49b71547d6feb - arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c +b33a69c22fcc5e0d8abd886b78b557633834d721 - arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c +aeb8a1b51452a7c1b9088cd2cc5f0c6ab2590b45 - arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S +b30c67527c7802085733426c8c113a7ab2492ce8 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h +3bb8192919eea022c0cfa99a7d87f8ecd4588256 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h +468e61508695c6dc9df856865e295b59c32a54e3 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h +b45c063aa1fdf9280c52020500ae6e83d71244c5 - arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S +f340bb1f1f4dcfde1ab65f3d67e26a33025f37a6 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h +5972e7acb9e93b201406ff9cf0cbab522f942eb3 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h +4e4ddcdd110f807b8dcbd6b440a4b4f5c2f9e83b - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h +c388d0822e5ef0bf97db4c66ab46d4088421f0e6 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h +7617a0e9164a7f90465861eedd913dabf15379f8 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h +138c1bc36bb3c91d2b2d9f5ac1702aa0975c850c - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h +f00b456e46701cc6a1e2b31fdd93091805ab0809 - arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c +3bc7caa521ce87bd672c20940f330d81613afdc1 - arm-trusted-firmware/plat/arm/css/common/css_topology.c +75cc05419580aa9e613157ed0cacf5e0447c7d7b - arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c +c788e65cad1a1e84654d127315052a3bcbd35225 - arm-trusted-firmware/plat/arm/css/common/css_pm.c +e35946648a3f4e38af67096b19e7cbe49324a3e2 - arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c +3ddcf64aa2f7a53edf4016ea4d4c636a371f4516 - arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S +29476751ce928c5170b93c840f4fd925619fb9f9 - arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S +795d97596b09631253539c8a66fa49d5d422d01d - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c +3693a7e757b2541552b2c91c91a0dba2d6a0a8de - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c +73d0e620495671f0ffa9cfdd536e8f3c97f6e384 - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c +1cc6a4959dd00202735100b426201a00f18764ec - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c +f8bee970c03b0a4da0d79dcc8895e970ff34ffa1 - arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h +3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts +ed25350e5c803bac231eea3f950d3e7e5aee01d2 - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts +e12be214b71705c426b59f867e2c1e12d74eb660 - arm-trusted-firmware/plat/arm/board/tc/tc_topology.c +ded1714043a17b1985c18754683ddcc8a2954d2a - arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c +4335b9a6f68fb49824b223397621a29f3d1030c9 - arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c +868cf0c3ac2a02db664b5bb1dc788646d79823a0 - arm-trusted-firmware/plat/arm/board/tc/tc_plat.c +ae19b2b5534ecfc11125374e36d9e8f859a89eda - arm-trusted-firmware/plat/arm/board/tc/tc_security.c +1f68f4b41cf660f6aecbd9c91cffd25b5da791a9 - arm-trusted-firmware/plat/arm/board/tc/tc_err.c +e359fea3cdefe52d1384eaf4e3657d1a8639ce5c - arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c +28488a6123a3f6e963e45167297c24b033c4ea20 - arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c +8ad72d03b3ba43d1683a1303fee28ea1c7be281d - arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S +12e15891d91866e073604872dd843da7a55ab1ca - arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S +9660ea0d565256c4b8a124a3b15c393be1d5f9b0 - arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h +fbb9a21e701abf6a427a0a7a4f52bdfac2d65ae5 - arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h +46c4eb5b1105e6fcf9a5ebc8bb219b4f6250ef79 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts +6d8e682b0e92f3c4b0317af9db0cf378942f0637 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts +dd7dfe59caab52d2698deda4e52c6508f481ea7a - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts +b6a0718fcdad5e07263ed41c89641a47d843eb14 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts +ae7769a5c9c26af057b45ea638e7d3e8f7905d63 - arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c +20df07965dd541c0c14b55f71c827c0b992b608c - arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h +673d2aca63b2cddcb1fc087b3849b8459c60178a - arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts +0edacdd0dc4a2af6f50c21ccdf98244fe72c6730 - arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c +885dbc360b97a82697b2978ae8f5665ba4878080 - arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S +f63762c7a16038a4bc3a046a89d815cf9ae9089b - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem +b48500f3591ea941f29e3cb482855cd947d886c3 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin +99b2edcf01ed68e8e25f2687d31ef61f0531f26f - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der +2b0cf90adf32af769b93e85764f195737286be65 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin +c4cd605f9796351468c8e3427ec60a3ab5966a93 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S +b22a3e04b7c492d96f48978250bd02b1de04304b - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der +64194de14ee2424df1ca72d388c407f3d0c16184 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem +aa5febfe9cf8a923785e2509c54c7e03032167e7 - arm-trusted-firmware/plat/arm/board/common/protpk/README +ce90ae54534188e8ed455e84da4ee7656807dc45 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S +a819075a49fd85dede74b56ddededf2f4c046f07 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem +cdb90754cb9118d6571aad9c3846b2c410f708d1 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin +d7941a7e9ec8fa11c4dd7580b57e1543e335d61b - arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S +0b886935846ab1d278829932851b6cc492f106cc - arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c +53c5a79a63bf1f5551016da97e29bf8702e32ad3 - arm-trusted-firmware/plat/arm/board/juno/juno_def.h +ebbb9c3ccbc5ea001a213d0ba5a9b7744bd561dc - arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h +6cea3743018f1d02cac51c8d78a92561ea46ce14 - arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c +49553a7fbab54730a1b3de994aa92810c35025da - arm-trusted-firmware/plat/arm/board/juno/jmptbl.i +d784833f267d4a24f2a529767e8892a4aa11df9d - arm-trusted-firmware/plat/arm/board/juno/juno_common.c +905aac590f6fdf10096fd3e0f4bb661a2953acfb - arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c +8a5716ff7852804effaf5810a335e69d3a788a50 - arm-trusted-firmware/plat/arm/board/juno/juno_trng.c +07f098d234d16533d40b505e91dbb1aae1712650 - arm-trusted-firmware/plat/arm/board/juno/juno_security.c +17d854b860806d6ad8af6ee63952524a3bcbd9e9 - arm-trusted-firmware/plat/arm/board/juno/juno_pm.c +419b6382a2607911be10024a6287e69289234326 - arm-trusted-firmware/plat/arm/board/juno/juno_topology.c +0ff3d7a6c51d9752cc2a86bb19e800a94245eea2 - arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c +bef868e2dcb239da5ba7d1787c2f790e1f31d33a - arm-trusted-firmware/plat/arm/board/juno/juno_err.c +50963e02933b9165b4b2c2a4b8ce7f8cc758df7d - arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c +4780ddabb988fa673f07503011a00242d2ea9faa - arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S +53f8c45c8436fb9bb4378cd8782a0b7d8037e5d2 - arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S +821681f18e15e60a3d540f06924deb6c691c2d7b - arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h +dfc9edcda0daf49b40451e94c30405aa901ef204 - arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts +805360ecd38e071b1f2e9b60704130be813557e2 - arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts +319dfb0515299119770970eb5953825ab7abd95c - arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S +e3d086dd3e36ff5fd58f3282c011f6394739185c - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h +4497a7586471f072a94ff5a066931c86dcb6fd2d - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c +e902fc33536870bb2460962782828919e301f53a - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c +7d80d6700188f44364662e46113af9036afedcbc - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c +7104250da7bca258ddb0bf081570d32f8900092b - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c +5a64604c368489c4585ba4e01e129b3687e5d8ff - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c +4b16feb977654bc82a89a104dc5b31b167bf17d1 - arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S +b45c063aa1fdf9280c52020500ae6e83d71244c5 - arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S +eaeab6f905d711a8fa04d0ce9d2c2ec485934eaf - arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h +af1f8d5af2ee91ba0dd180c42a7b8f73b7543474 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c +6733f3383940d86208b8239c1d08d9221c2c2929 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c +a924444b8053fdd6d907961d26d25ef0d3a207f7 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c +300e69aa5df2f362bc3ddf1c430fe3fab03f11da - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h +4a175994a02eeb79a8ccc76f0b3be5ac2d45771d - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h +b0261bd454617bc33a79aa98dcfa987149992300 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c +87d9fc22d1228a7faf0c17443f9d5afd194e4334 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c +b370460e14d8e464d9f852b0e3f18cf2dca4950b - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c +103c2c1d17da9dfaab63bca2f61e6bd21aa82c19 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c +19f1b6fffc9b7e4d8a55730d5dc6740b06415c71 - arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h +996afef966d673534a7502180616ba362cdb0d9c - arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts +a857b4f74c6a05502271795dcd7a71f24a024b41 - arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts +2ff5ebca71b32318bae21e3dbb7699236b9cbe61 - arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S +d56cac77b62eee0ed50166d2264e0a00c8fe4ffa - arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c +cdf2af8fe7e5ba8b9ff36e04a33ebff2cf20f79b - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c +007839db0f0e5c02b3362ce770b02771a47faa27 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c +f2a71185ac9189cbe4310e27a7ead8d40c23c377 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c +c8bea252a67bd4f3ad0910e3dadd0b76dc62c7f3 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h +7d714f8f2b3f7274c9d2e73eaa5d46215c7d3911 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c +be0cd4f5f48b5eb3a64885536643645036173809 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c +c6fdde231ff1fe0ddb8f585bd3fead2a7f2f0f46 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c +fabc6650d0d7860d4d615e5e997c72bed71aecb3 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c +189ef1e9d436f631711b2a4bd2e75efb635a322a - arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h +996afef966d673534a7502180616ba362cdb0d9c - arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts +adc821bdac8aebcefb26e3f8cd54497b3b8dfab4 - arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts +142d4bce7860550461e2498ba8c9f4ebb17d902d - arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S +a8eb0724c2056ed80453ea31aa3ebc822e93ffa2 - arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c +b20640f66687a9edf5c361b2cf32bf1244777ecd - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c +181e66fa9c41732917a323ee0fe465da3b5ce36d - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c +efd5139ee502cdc5570d9ec338ee84b3410067fd - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S +e985480b9d1aa1426a500f3c4869a1f32bb8b422 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c +860f2b3b1633322a3865add4e226f457c1a7237d - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S +93cd93fd9277603c0a72cf1c730d6486a6247262 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c +b5fe2445bbd4cfd3d360d2d930d9358c4eed5555 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c +5f78d5ae0c4547371279bfc19196f01fb454e3b6 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c +2ce9cd0a5ef399a537316089ff1451da165bdd42 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S +1f85fcf3a3d2c0bd5a8c5e848a4841400b54f9fe - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h +486d3021b7aeeb557efb82cafa7337d3d3041fb7 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c +8e7bab3de835fbccc87f8d20b8acecc011d4fcaa - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S +b1777d180724d85711393cf136ad5b34e80ce86a - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h +deb3a6a31fba479e597c0ae722532692996e2372 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c +db240cab0da9aaf6298ede4c8418abd28744a258 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c +61fa6bbfd2f41f1cc6fe1c4caacb1fa09461692c - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S +e9c7e8c62f6a1ac8f4b8f79ebb080765f9244fbe - arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h +5356ccdf1172f23b213522e8c204e511fd9b8841 - arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h +1c209493074be7ae85b1aafe237784f10e2b7093 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c +daecdf40f28b13596b217b424164a59b35baa192 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c +07a42e98f0211f264decd0d40369a5a22999a7a4 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c +39dd88b06678aa7f03906487a206a758c69bb621 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c +5a4591bc131dd662dddfaa201c233dc2e6f0a9a0 - arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h +3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts +4eee465e298e33cc2776504ed671b987022fb333 - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts +3d1a55d785180dd11beb8473207268d04543695a - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S +ed51f976efc9644368dd64840ed3d158c086650e - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c +90dbd482aecd4e6be49f62fed93a4b38e4d79784 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c +df9742f665da99900fe4a3fdc0b6fbcc02209a0f - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c +8908fa02b1140f0d45e9bdcc3d5552190eb3af41 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c +5f0ac09b373c85fd1d635fb4f06ea45011389b19 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c +688520959b3077ac47e6c17fd87614f5400ec96f - arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c +9f9f59bab890a50e0444edf12481248060aa9c1b - arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h +3c1fd619c9a1da90f7af84b9c6e1b8eceb5e7a20 - arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h +d2cf1d7868d3a048734caa91b018fb43f56c36dd - arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c +bb5bde77d451942a4effe8cd36463c1dfc1df462 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c +4e3d6ef9cbb8925d20f8946cbf6f998ea3c4eb8f - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c +79e40d92dcde7f9d17195a4a63d0608730af9c4b - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c +aa3d4b5a511124fc6ae5cd9244633af5ae0ab4a9 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c +7be90ba89049185165cc3d60d523a66fd7a1a0bf - arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h +e5b638c1ab3d0ee37ca9b8702ee4262358c3559b - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts +0397a242841f6193faacaba41c8326032a1e7729 - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts +1477905828689906107808c1098cccb0a22dc73b - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts +d4a49ec110e03192903aeabeae1df36bca1cae8a - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c +3f70fab8ee8fcd7926df2c977d9380f53cbbb9f6 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c +04538cf26382d09d8e2c07c0b46f13a5b099236a - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c +584cb4b05aeec673c6c04da7c3885037b079afa4 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c +05ecf6ab819a6a6ca826e872d3c1fa6a21c7e7ef - arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h +c139b0b044ff0f3122d7f6e5b65703bc3fbee8d2 - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts +3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c +95aa905a5aa0734b8993eaf65aa91924c6ba1ccd - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c +3aff6d693c63d2b2dc58205e075552c4f14e24c2 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c +e717578fd539b138146efa385134192a8aa4055c - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c +4bcbaa1f0a092433b2d017ed4941be94943fa552 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c +127adaf6d9d5f7353a1893a6f2904417a96def85 - arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts +a19b040188761f8bccb0937f9f397e3b191c143e - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts +9f8fd7d90d63ffe6d71473664ec09b7aa4cdf607 - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts +0e3644e6d15833cfd15ee928af181e156ec27e8a - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c +810d8a4c9a7dff63b504d43fa4691f19cdf86b3b - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c +fbb932100f4228bb8fe153a58d84898837188f8b - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c +b9f80852b169e9c137876fadebe0782792162fe4 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c +dd206cc4d7ea74d0dcace11dc6c64faf0d687b8a - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c +c10b97a1764fe4c02c0a7ae81b0a75313edeed05 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S +5562bd387d6506e0db4a62fe23b24cd1c5046754 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c +7bc7cf637e9751cbed26e48c65722c070a0f9d36 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c +1e7fe4ccc25d366dfe5f6a14851dab68001bdb13 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c +a5086b67555acbdb3f4c3b25f837cbb372b0102a - arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h +16e3686521725b2e8cf355c2d990811fc260a02c - arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts +70913ecf05a6e846d99d63213b643de746a371e8 - arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S +86c2465abfadc0a5dfe9b561b0f5675db8fee013 - arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c +39be04c7a0d7f7559902b8813b1ded035b592985 - arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c +19591a34444effbe25bc3245bb68e6462bda0024 - arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c +1570105ddfc280d36e64641b556bc2da9a0529dc - arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c +10c7154aeb64129154f13657841ad8f9aee6af85 - arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c +a6d08d07ea1ba1184a912ed5ef6a6287291ff743 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c +b4b38f929ba25c093b95fc92938eb9b58213a4b8 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c +a1e4c883f6912bad1724268901a148f96250854a - arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c +fa75b4ccee6e6d8604b819da30a1ed892db70b15 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c +87220bf30d58a155c2f10f38418d094db212e5b6 - arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h +df0b10a5b65cf57a485f5eb846e0cfa7e64c429b - arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c +d25e9c719859733739581faecd38cfa80443aa83 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c +71418933f8bb76fa971723d4cb9bc6748a009f33 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c +d62b302ac0bf1976ed0084160aeba061e325a6c3 - arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c +a3147836e6e11bb9b651753fee98a99b2f81062b - arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c +394a425b1d229fbbad1173c1371edc737857d5f2 - arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i +0c3494f4c7e2590865b69abf91d4b49be1ea469d - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c +20e8179e5c61147fc2d627dbb503babac430603c - arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h +6f76c4d8ae1abb640a62785bfc535bcb485f9511 - arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c +aed35e7aa732be73eef26face244c3acdee67640 - arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c +223e1339e343160feab72cff7621103ada50dbc9 - arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c +1924351967826f1ad9898254b30419ba2e7fb9cc - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c +0a86ad28b6ae96f93bdbcc32be32335d3e8250e9 - arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c +d5a6187ffa8ab68518e9d896c2d50bbf600d68cd - arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S +3f4bcd29ccbf7cd09dfe8275846469b38db62e2f - arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c +83e404fdd5bc4dda0b68b92d365d6e9b047f13d3 - arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c +10fc5531e7b7d5ac9ffba191f525b64179843eae - arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c +84180022623ad574044b9436e62202ee5635c6ae - arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h +aed581dcf8acf86f277ecf028cc1eec4f0c081fc - arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S +12b7439bee5ead5da71eb5a42a9c5cc493f9c7fc - arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h +aaff5cd1241ce58ab9627da89fb4860390a0864b - arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h +c7af81d092cd74c1eba0402a02368b53f801c235 - arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h +1f6772f1b9358e6acc890bc4475a57f68cebc72d - arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S +df9f20c998402fb612824aeec7d618e97e023cb8 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts +7dd67253d1f53292fbdd750b1360cace93220e02 - arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts +aba68daa32f394274fa0c7b3ebb2d77514e105da - arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi +33a1a8c0c5e1f8f806d0dbe69adab509f55301be - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts +5601a00daf6c8ba481f1addc03652d97efe84a3c - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts +b8ba7eb0ce440dedebafa08a9e3ffde066832d0a - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts +b1406e98f75e782442a0fdfe50c8aad26cf5aeb5 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts +26761d08528feec31bb15a854b65dd46629135fe - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts +43a2362473fca426e3a62517552c20c2a629a563 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts +b59b8589b390aaea5c26a9621713fe3d78e47e8b - arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c +2c7ccf1e47b4fdac9dc7745e506f4194cce2e498 - arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S +6adce62f756dc0792fb3a4d6aa6cec60e0b54117 - arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c +561594e99d3e16d7826006d518e141e9a58eadec - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c +ba9b8a6b4b36804eb8c8aee5b17845c85db8a845 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c +851570d1add4283d5a01ff4893f1558decb2d6e9 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c +7d37a6f29bbe666c9db7538d4d7a123d1ab40b17 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c +97f84a745ae8fccb804dc7e0ba50b85d46ed4198 - arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h +5d0744ed59fc75ba7204d9d0083fbc0cd64e74d6 - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts +869fa43b401d5d394651f9d1bd9eb784b7ebb14d - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts +a87583e95c695a2bf6af550cd6fbbffb3eae3961 - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts +d115cd145587e366c9c6d02d47cc7ea610f7791f - arm-trusted-firmware/plat/arm/board/morello/morello_security.c +c855687b5adb537f1a56e37496a708864bd72650 - arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c +275ff8fd1cb66a02cc8ca9b9494035d3aa7f8ebf - arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c +59b5177c9b302f117bea58642d758d747224eaed - arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c +ab6ec67031b519490edd2bdd7efb973f91af2453 - arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c +846d7f92ffe6c368d0d0b85ffa36409b0dd04caf - arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c +021dca0ec2928f72c45e98a602338d8a2bb08cc2 - arm-trusted-firmware/plat/arm/board/morello/morello_err.c +710e4ce5fe08ed123d1977361a4bbf49dff07ba9 - arm-trusted-firmware/plat/arm/board/morello/morello_def.h +eae232f83e8fef4997f24f4cce1d598178a8eab0 - arm-trusted-firmware/plat/arm/board/morello/morello_plat.c +9e616a8e89120ae9b614d9bae16f0de9aa886778 - arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c +0105670429d8a205bc698cf69de09044501a55a1 - arm-trusted-firmware/plat/arm/board/morello/morello_topology.c +1c3ff5d4d35a2aa211380dea2b252236f3dae0b1 - arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S +5361abb465b0253014c38facafec374dd284699a - arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S +e1eb7e2194a62fcfa63e0d92da3567386d98a24d - arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h +a95b1476c52a6213400f2402811d15e5d82d7d83 - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts +bf30791c97940cf78bee90bb458a53b2480a4154 - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts +9c4c899115425303ba08c836c2a6ca740418160b - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts +0ca4a4d2749cd227831e57d361b8c16ee0f3cf03 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c +ef779e5f985f2ebef6d66a83442695603c463465 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h +bdf16498e248d1d87d012aca5001940fb8328395 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h +15269f87cab6dfa65ce9cbaacbb13ee9cf2af583 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c +86553039cac69d2003776608e4a3172af5f6263d - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c +1cfbd3237d5138875eda5a3f57ebd08f452c4992 - arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S +70fd1afdd7b31d55ddd95d7018ba66095315083e - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c +89a8aeb02e2a9467d783383e96d830647443b99d - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c +78391ad4c170cb70d2db6ad5639108f4f6020dc6 - arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S +fe445cbd11196fc3c69cdcbc6be5cdbc4354026b - arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S +205b5febc22c83179a2fc6c9005499ef61e8f347 - arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S +87820ef2083d1576c3d29546b46fb922eafa3737 - arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S +6631f2221faec011381242d2e2011d9eda3e9780 - arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h diff --git a/nvbuild.sh b/nvbuild.sh new file mode 100755 index 0000000..8648626 --- /dev/null +++ b/nvbuild.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * 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 NVIDIA CORPORATION 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 ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This script builds atf sources in this directory. +# Usage: ./${SCRIPT_NAME}.sh [OPTIONS] +set -e + +# shellcheck disable=SC2046 +SCRIPT_DIR="$(dirname $(readlink -f "${0}"))" +SCRIPT_NAME="$(basename "${0}")" + +source "${SCRIPT_DIR}/nvcommon_build.sh" + +function usage { + cat <